[
  {
    "path": ".astylerc",
    "content": "style=allman\nindent=tab\npad-oper\npad-header\nunpad-paren\nalign-pointer=name\nmode=c\n"
  },
  {
    "path": ".clang-format",
    "content": "{\n\tBasedOnStyle: LLVM,\n\tStandard: c++03,\n\tColumnLimit: 0,\n\tUseTab: ForContinuationAndIndentation,\n\tIndentWidth: 4,\t\n\tTabWidth: 4,\n\tBreakBeforeBraces: Allman,\n\tFixNamespaceComments: false,\n\tPointerAlignment: Left,\n#\tEmptyLineAfterAccessModifier: Never,\n}\n"
  },
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\n; Broken in Visual Studio\n;charset = utf-8\ntrim_trailing_whitespace = true\nvc_generate_documentation_comments = doxygen_slash_star\n\n[*.{yml,rul}]\nindent_style = space\nindent_size = 2\n\n[*.{c,cpp,h,hpp}]\nindent_style = tab\nindent_brace_style = Allman\ninsert_final_newline = true\n\n[Makefile]\nindent_style = tab\n\n[CMakeLists.txt]\nindent_style = space\nindent_size = 2\n"
  },
  {
    "path": ".gitattributes",
    "content": "# Set the default behavior, in case people don't have core.autocrlf set.\n* text=auto\n\n# Explicitly declare text files you want to always be normalized and converted\n# to native line endings on checkout.\n*.cpp text\n*.h text\n*.rc text\n\n# Declare files that will always have CRLF line endings on checkout.\n*.sln text eol=crlf\n*.vcxproj* text eol=crlf\n\n# Denote all files that are truly binary and should not be modified.\n*.png binary\n*.gif binary\n"
  },
  {
    "path": ".github/issue_template.md",
    "content": "<!--\n\nBefore reporting a bug, please check what isn't a bug: https://openxcom.org/bug-tracker/\n\nInclude the following information, if applicable:\n\n* IMPORTANT: Step-by-step to reproduce the bug. We need to be able to reproduce the bug to fix it! Savegames are appreciated.\n* Complete description of the bug: what went wrong, when did it happen, what were you doing, what was the game doing, etc.\n* Any relevant error messages, openxcom.log, screenshots, etc.\n* If you were using mods, narrow down the broken mod(s) and report it to the mod author first.\n\nYou can attach files by dragging-and-dropping them here.\n\n-->"
  },
  {
    "path": ".github/pull_request_template.md",
    "content": "<!--\n\nOpenXcom Extended (OXCE) does NOT accept any pull requests without prior discussion!\n\nSuggestion board is here: https://openxcom.org/forum/index.php?board=35.0\nInstructions are here: https://openxcom.org/forum/index.php?topic=11631.0\n\n\nAfter your suggestion has been approved on the forum, follow the below technical guidelines.\n\nGuidelines for pull requests:\n\n* Use a separate branch (instead of \"oxce-plus\"). This will save you a lot of headaches: https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests\n* Only one feature/fix per pull request (unless they're connected).\n* Try to follow our coding conventions: https://www.ufopaedia.org/index.php/Coding_Style_(OpenXcom)\n* Explain in detail what your pull request is changing and why we want it.\n\nWe're very conservative about adding new features to OpenXcom. The bigger the change, the more it's gonna cost us in complexity and maintenance. Gameplay-critical code is very sensitive to changes and prone to bugs. Once it's merged it's our responsibility. So it's not enough that \"it works\", it needs to justify its cost. Is it a highly-demanded must-have feature? Has it been thoroughly tested? Will we regret merging it? Etc.\n\nGitHub isn't a good discussion board, only developers look at this, so it's better to post in the forums first to gauge interest before doing any major changes: https://openxcom.org/forum/\n\n-->"
  },
  {
    "path": ".github/workflows/nightly.test",
    "content": "name: Nightly\non:\n  push:\n    branches:\n      - test\n  workflow_dispatch:\njobs:\n  windows:\n    name: Windows\n    runs-on: windows-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n        with:\n          fetch-depth: 0\n\n      - name: Setup environment\n        shell: bash\n        run: |\n          echo \"DATEFILE=`git log -1 --date=format:\\\"%Y_%m_%d_%H%M\\\" --format=\\\"%ad\\\"`\" >> $GITHUB_ENV\n          echo \"DATEVERSION=`git log -1 --date=format:\\\"%Y-%m-%d %H:%M\\\" --format=\\\"%ad\\\"`\" >> $GITHUB_ENV\n\n      - name: Setup version info\n        shell: bash\n        run: |\n          sed -i \"s/GAME_VERSION_GIT \\\"[^\\\"]*\\\"/GAME_VERSION_GIT \\\" git ${{ env.DATEVERSION }}\\\"/\" install/win/version.nsh\n          sed -i \"s/GAME_DATE_GIT \\\"[^\\\"]*\\\"/GAME_DATE_GIT \\\"${{ env.DATEFILE }}\\\"/\" install/win/version.nsh\n\n          sed -i \"s/OPENXCOM_VERSION_GIT \\\"[^\\\"]*\\\"/OPENXCOM_VERSION_GIT \\\" git ${{ env.DATEVERSION }}\\\"/\" src/version.h\n\n          echo \"FILENAME=oxce_git_${{ env.DATEFILE }}\" >> $GITHUB_ENV\n\n      - name: Install XP Toolset\n        shell: powershell\n        run: |\n          Set-Location \"C:\\Program Files (x86)\\Microsoft Visual Studio\\Installer\\\"\n          $InstallPath = \"C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\"\n          $WorkLoads = '--add Microsoft.VisualStudio.Component.WinXP'\n          $Arguments = ('/c', \"vs_installer.exe\", 'modify', '--installPath', \"`\"$InstallPath`\"\", $WorkLoads, '--quiet', '--norestart', '--nocache')\n          $process = Start-Process -FilePath cmd.exe -ArgumentList $Arguments -Wait -PassThru -WindowStyle Hidden\n          if ($process.ExitCode -eq 0) {\n              Write-Host \"components have been successfully added\"\n          } else {\n              Write-Host \"components were not installed\"\n          }\n\n      - name: Add msbuild to PATH\n        uses: microsoft/setup-msbuild@v2\n\n      - name: Compile source (x86 only)\n        env:\n          VC_FLAGS: /v:minimal /m /p:BuildInParallel=true /p:PreferredToolArchitecture=x64 /p:Configuration=Release_XP\n        run: |\n          cd src\n          msbuild OpenXcom.2010.sln ${{ env.VC_FLAGS }} /p:Platform=Win32\n          cd ..\n          Rename-Item -Path \"bin\\Win32\\Release_XP\" -NewName \"Release\"\n\n      - name: Create nightly ZIP (x86 only)\n        shell: powershell\n        run: |\n          New-Item -ItemType \"directory\" -Path \"artifacts\"\n          Compress-Archive -Path \"bin\\Win32\\Release\\OpenXcom.exe\", \"bin\\Win32\\*.dll\", \"bin\\common\", \"bin\\standard\", \"bin\\TFTD\", \"bin\\UFO\", \"LICENSE.txt\" -DestinationPath \"artifacts\\${{ env.FILENAME }}_win32_xp.zip\"\n\n      - name: Get SHA hashes\n        uses: nrwl/nx-set-shas@v4\n        with:\n          main-branch-name: test\n\n      - name: Generate build log\n        run: |\n          git log --pretty=format:\"<strong>%an, %ad</strong>%n%B\" -n 10 --date=iso-local ${{ env.NX_BASE }}..${{ env.NX_HEAD }} > artifacts\\${{ env.FILENAME }}.log\n\n      - name: Archive artifacts\n        uses: actions/upload-artifact@v4\n        with:\n          name: ${{ env.FILENAME }}_windows\n          path: artifacts/*\n\n  linux:\n    name: Linux\n    runs-on: ubuntu-22.04\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n        with:\n          fetch-depth: 0\n\n      - name: Setup environment\n        run: |\n          echo \"DATEFILE=`git log -1 --date=format:\\\"%Y_%m_%d_%H%M\\\" --format=\\\"%ad\\\"`\" >> $GITHUB_ENV\n          echo \"DATEVERSION=`git log -1 --date=format:\\\"%Y-%m-%d %H:%M\\\" --format=\\\"%ad\\\"`\" >> $GITHUB_ENV\n          echo \"CMAKE_BUILD_PARALLEL_LEVEL=`getconf _NPROCESSORS_ONLN 2>/dev/null || getconf NPROCESSORS_ONLN 2>/dev/null || echo 2`\" >> $GITHUB_ENV\n\n      - name: Setup version info\n        run: |\n          sed -i \"s/OPENXCOM_VERSION_GIT \\\"[^\\\"]*\\\"/OPENXCOM_VERSION_GIT \\\" git ${{ env.DATEVERSION }}\\\"/\" src/version.h\n          echo \"FILENAME=oxce_git_${{ env.DATEFILE }}\" >> $GITHUB_ENV\n\n      - name: Install packages\n        run: |\n          sudo apt-get update\n          sudo apt-get -yq --no-install-suggests --no-install-recommends install appstream libfuse2 libsdl1.2-dev libsdl-mixer1.2-dev libsdl-image1.2-dev libsdl-gfx1.2-dev\n\n      - name: Install LinuxDeploy\n        uses: miurahr/install-linuxdeploy-action@v1\n        with:\n          plugins: appimage\n\n      - name: Compile source code\n        run: |\n          cmake . -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr\n          make -j$(nproc)\n          make install DESTDIR=AppDir\n\n      - name: Generate AppImage\n        run: |\n          rm -rf AppDir/usr/share/openxcom/UFO\n          rm -rf AppDir/usr/share/openxcom/TFTD\n          linuxdeploy-x86_64.AppImage --appdir AppDir --output appimage\n          mkdir artifacts\n          mv OpenXcom-x86_64.AppImage artifacts/${{ env.FILENAME }}-x86_64.AppImage\n\n      - name: Get SHA hashes\n        uses: nrwl/nx-set-shas@v4\n        with:\n          main-branch-name: test\n\n      - name: Generate build log\n        run: |\n          git log --pretty=format:\"<strong>%an, %ad</strong>%n%B\" -n 10 --date=iso-local ${{ env.NX_BASE }}..${{ env.NX_HEAD }} > artifacts/${{ env.FILENAME }}.log\n\n      - name: Create .tar.gz archive\n        run: tar -czvf ${{ env.FILENAME }}_linux.tar.gz -C artifacts .\n\n      - name: Archive artifacts\n        uses: actions/upload-artifact@v4\n        with:\n          name: ${{ env.FILENAME }}_linux.tar.gz\n          path: ${{ env.FILENAME }}_linux.tar.gz\n\n  macos:\n    name: macOS\n    runs-on: macos-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n        with:\n          fetch-depth: 0\n\n      - name: Setup environment\n        run: |\n          echo \"DATEFILE=`git log -1 --date=format:\\\"%Y_%m_%d_%H%M\\\" --format=\\\"%ad\\\"`\" >> $GITHUB_ENV\n          echo \"DATEVERSION=`git log -1 --date=format:\\\"%Y-%m-%d %H:%M\\\" --format=\\\"%ad\\\"`\" >> $GITHUB_ENV\n          echo \"CMAKE_BUILD_PARALLEL_LEVEL=`getconf _NPROCESSORS_ONLN 2>/dev/null || getconf NPROCESSORS_ONLN 2>/dev/null || echo 2`\" >> $GITHUB_ENV\n\n      - name: Setup version info\n        run: |\n          sed -i '' \"s|OPENXCOM_VERSION_GIT \\\"[^\\\"]*\\\"|OPENXCOM_VERSION_GIT \\\" git ${{ env.DATEVERSION }}\\\"|\" src/version.h\n          echo \"FILENAME=oxce_git_${{ env.DATEFILE }}\" >> $GITHUB_ENV\n\n      - name: Install libraries (macOS)\n        uses: melusina-org/setup-macports@v1\n        id: macports\n        with:\n          parameters: scripts/macports-config.yml\n\n      - name: Compile source code\n        run: |\n          CMAKE_EXTRA_ARGS=(-DCMAKE_OSX_ARCHITECTURES=\"arm64;x86_64\")\n          if [ -d /opt/local/share/doc/sdl12-compat ]\n          then\n            echo \"SDL12-compat detected, linking SDL2 as well\"\n            CMAKE_EXTRA_ARGS+=(\"-DEXTRA_XCOM_LIBS=/opt/local/lib/libSDL2.dylib\")\n          fi\n          cmake . -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=/opt/local -G Ninja -B build \"${CMAKE_EXTRA_ARGS[@]}\"\n          cmake --build build\n\n      - name: Create an archive with .app in it\n        run: |\n          mkdir artifacts\n          ditto -c -k --sequesterRsrc --keepParent build/openxcom.app artifacts/${{ env.FILENAME }}_mac.zip\n\n      - name: Get SHA hashes\n        uses: nrwl/nx-set-shas@v4\n        with:\n          main-branch-name: test\n\n      - name: Generate build log\n        run: |\n          git log --pretty=format:\"<strong>%an, %ad</strong>%n%B\" -n 10 --date=iso-local ${{ env.NX_BASE }}..${{ env.NX_HEAD }} > artifacts/${{ env.FILENAME }}.log\n\n      - name: Archive artifacts\n        uses: actions/upload-artifact@v4\n        with:\n          name: ${{ env.FILENAME }}_macos\n          path: artifacts/*\n"
  },
  {
    "path": ".gitignore",
    "content": "# autotools\naclocal.m4\nm4/pkg.m4\nmissing\ninstall-sh\nconfig.status\nconfig.guess\nconfig.sub\nconfigure\nMakefile\nMakefile.in\ndepcomp\ncompile\n.deps/\n*.tar.gz\n*.tar.xz\nopenxcom\n.dirstamp\n# Doxygen autogenerated conf\ndocs/Doxyfile\n# basics\n*.o\n.DS_Store\nThumbs.db\n#Ignore files built by Visual Studio\n*.obj\n*.exe\n*.exp\n*.pdb\n*.dll\n*.*.*.user\n*.aps\n*.pch\n*.vspscc\n*_i.c\n*_p.c\n*.ncb\n*.suo\n*.tlb\n*.tlh\n*.bak\n*.cache\n*.ilk\n*.log\n*.tlog\n*.zip\n[Dd]ebug/\n*.lib\n*.sbr\n[Rr]elease*/\n[Tt]est[Rr]esults/\n_UpgradeReport_Files/\n_ReSharper.*/\n*.ipch\n[Ii]pch*/\n*.aps\n*.svl*\n*.mvf\n*.*sdf\n*.idc\n*.tmp\n*.dgml\n.vs/\n*.VC.*\n#OpenXcom stuff (no ending slashes for dirs so symlinks can be ignored as well as real dirs)\nbin/UFO\nbin/TFTD\ndocs/html/\nbuild/\nDependencies/\ntranslations/\n*.*.user\n!install/win/plugins/**/*.dll\n#Ignore Vim swap files\n*.swp\n#Ignore build config used by Vim plugins for completition\ncompile_commands.json\n#Ignore NetBeans project directory\nnbproject/\n/makefile\nsrc/OpenXcom.2010.VC.opendb\nbin/Win32/user*\nbin/user\n/.kdev4/\n/*.kdev4\n"
  },
  {
    "path": ".tx/config",
    "content": "[main]\nhost         = https://www.transifex.com\nlang_map     = en_US: en-US, en_GB: en-GB, es_419: es-419, fr_CA: fr-CA, zh_CN: zh-CN, ca_ES: ca-ES, es_ES: es-ES, pt_BR: pt-BR, pt_PT: pt-PT, zh_TW: zh-TW\nminimum_perc = 10\n\n[o:openxcom:p:openxcom-extended:r:android]\nfile_filter = translations/openxcom-extended/common/Language/Android/<lang>.yml\nsource_file = bin/common/Language/Android/en_US.yml\nsource_lang = en_US\ntype        = YML\n\n[o:openxcom:p:openxcom-extended:r:common]\nfile_filter = translations/openxcom-extended/common/Language/OXCE/<lang>.yml\nsource_file = bin/common/Language/OXCE/en_US.yml\nsource_lang = en_US\ntype        = YML\n\n[o:openxcom:p:openxcom-extended:r:technical]\nfile_filter = translations/openxcom-extended/common/Language/Technical/<lang>.yml\nsource_file = bin/common/Language/Technical/en_US.yml\nsource_lang = en_US\ntype        = YML\n\n[o:openxcom:p:openxcom-extended:r:x-com-1]\nfile_filter = translations/openxcom-extended/standard/xcom1/Language/OXCE/<lang>.yml\nsource_file = bin/standard/xcom1/Language/OXCE/en_US.yml\nsource_lang = en_US\ntype        = YML\n\n[o:openxcom:p:openxcom-extended:r:x-com-2]\nfile_filter = translations/openxcom-extended/standard/xcom2/Language/OXCE/<lang>.yml\nsource_file = bin/standard/xcom2/Language/OXCE/en_US.yml\nsource_lang = en_US\ntype        = YML\n\n[o:openxcom:p:openxcom:r:installer]\nfile_filter = translations/openxcom/install/win/Language/<lang>.yml\nsource_file = bin/install/win/Language/en_US.yml\nsource_lang = en_US\ntype        = YML\n\n[o:openxcom:p:openxcom:r:openxcom]\nfile_filter = translations/openxcom/common/Language/<lang>.yml\nsource_file = bin/common/Language/en_US.yml\nsource_lang = en_US\ntype        = YML\n\n[o:openxcom:p:openxcom:r:x-com-1]\nfile_filter = translations/openxcom/standard/xcom1/Language/<lang>.yml\nsource_file = bin/standard/xcom1/Language/en_US.yml\nsource_lang = en_US\ntype        = YML\n\n[o:openxcom:p:openxcom:r:x-com-2]\nfile_filter = translations/openxcom/standard/xcom2/Language/<lang>.yml\nsource_file = bin/standard/xcom2/Language/en_US.yml\nsource_lang = en_US\ntype        = YML\n\n"
  },
  {
    "path": "CHANGELOG.txt",
    "content": "Version 1.0 (13-06-2014)\n-------------------------\nNew features:\n  General:\n- Rudimentary mod support has been added to the ruleset loading, including:\n  -- Modular ruleset support.\n  -- The ability to define extra strings, sounds and sprites.\n  -- The starting date can now be set in the ruleset.\n  -- Soldier stat caps are now acquired from the ruleset.\n  -- Added support for custom images in the UFO craft preview window.\n  -- Implemented a list weight value for items, which determines where they appear in ingame lists.\n  -- Allow for resizing of UI surfaces through rulesets.\n  -- Allow for weapons to change max range, autoshots, blast radius, strength modifier, melee attack, dropoff, LOS, bullet speed, etc.\n  -- Allow for armors to change unit stats.\n  -- Allow for setting producedItems for manufacture.\n  -- Allow for negative costs.\n  -- Rulesets will now internally number themselves and offset IDs by 1000 to avoid conflicts intelligently.\n- Begun development on loading TFTD content, specifically .BDY files.\n- Various translation updates, including new languages: Dutch, Finnish, Greek, Norweigan, Portuguese (BR), Slovak, Swedish, Turkish.\n- Localized installer in multiple languages.\n- Updated soldier names: Italian, Belgian, Congolese, Dutch, Greek, French, Kenyan, Korean, Indian, Polynesian, Slovakian.\n- New Battle will now load available terrains from the ruleset instead of having them hardcoded.\n- New Battle now allows unlimited items to be assigned to the craft.\n- Implemented weighting for which soldier look is chosen by which origin. This should decrease the likelihood of races not matching names to realistic levels.\n- Screen is now centered on higher base resolutions.\n- Mouse capture option added, as well as key shortcut.\n- New language format, system language auto-detected on first start.\n- Complete overhaul of pause menu, now totally consistent between geoscape/battlescape.\n- Options can be changed mid-game.\n- Saved Games will now indicate the system save time, in-game date and time, and if appropriate, turn number.\n- Saved Games can now be sorted by creation date or name.\n- Combo Box and Slider functionality added.\n- Scroll bars added to text lists.\n- Options menu completely overhauled.\n  -- Most hidden options now available on the menu.\n  -- All options have in-game descriptions.\n  -- UI volume now adjustable.\n  -- Audio format adjustable.\n  -- New display options: Borderless, Resizable, Letterboxing.\n  -- Internal game resolution may be adjusted for battlescape and geoscape separately.\n  -- All kinds of in-game timings are now adjustable, so you can make it run like your old 286, or pentium.\n  -- Mods can now be activated from in-game, and don't require a restart.\n  -- Many more advanced options added, most of which were previously omitted for requiring a restart.\n  -- Many UFOextender and XComUtil options added (either as advanced options or individual mods).\n  -- Mousewheel scroll speed is now configurable.\n  -- FPS limiter added.\n- New Battle menu completely overhauled.\n- Support for old or modded savedgames improved, including warnings about potential incompatibilities.\n- Multiline support added for textlists.\n- Improved text input.\n- Support added for multiple data folders.\n- Dedicated auto-save and quick-save slots added.\n- Added ironman mode.\n- New loading screen with better error handling.\n- Adlib music emulation added, MIDI playback is no longer required.\n\n  Geoscape:\n- Automatically end dogfights if the UFO outpaces the fighter and the window is minimised.\n- When areas don't have mission data set, they will now fall back to data for an area that does.\n- Psionic training at any time option added: allows adding/removing soldiers from psionic training at your discretion rather than on a monthly basis, and updates their progress daily.*\n- Fields added to craft rulesets for further moddability.\n- Added \"Sack\" button to soldier info screen.\n- Added inventory screen to craft equip screen.\n- Added estimates for craft repair/refuel/rearm times.\n- Alien Containment management screen added.\n- Soldier Memorial screen added to keep track of Xcom casualties.\n- Hotkeys for base selection added.\n- Last selected base now preserved on closing base window.\n- Fixed craft renaming not working.\n- Fixed HWPs not reloading when new ammo arrived.\n- Added Prev/Next key shortcuts to Basescape soldier info.\n- Aircraft flight path line indicators added.\n- Storage limit enforcement option added, complete with \"overflowed item\" management screen.*\n- Drag scroll added.\n- Melee accuracy now shown on soldier stat screens.\n- Manufacture auto sale button added to manufacture screen.\n- Infinite quantity added to manufacture screen.\n- Background now filled out in higher base resolutions.\n- Added various Go To Base shortcuts in Geoscape popups.\n- Added right-click on craft in Intercept screen to center on it.\n- Added right-click on soldier in Craft screen to show their stats.\n- Ufopaedia now shows armor damage and stat modifiers.\n- New Advanced-Option: View soldier's Psi-Strength after the appropriate research has been completed.*\n\n  Battlescape:\n- Inventory: Ctrl-click an item to attempt to swap it between the ground and your soldier's inventory.\n- Inventory: Added ability to define paper dolls for non-player units.\n- Alt-click can now be used as an alternative to right-clicking.\n- Various soldier weapon display changes:\n -- When using two two-handed weapons, display the one currently in use.\n -- Display soldier hands in front of rifles.\n -- If holding a pistol and a two-handed weapon, display both while firing.\n- Factored height into the throwing calculation.\n- Plasma tanks and sectopods now play the correct firing sounds.\n- Item stacking implemented: Functionally identical items will appear in the same place on the ground with a number displayed over them, if there are a large stack of similar items.\n- 2012 item recovery option added: only captured aliens drop intact weapons.*\n- Path preview option updated: displays yellow when you can move to a spot but are unable to perform auto shot (or the type of shot you have on reserve) with your remaining TUs.\n- Path preview option updated: can now be set to show arrows, remaining TUs, or both.*\n- Units will no longer poke their heads through floors above them when standing on tall objects.\n- AI almost completely re-written from scratch, should more closely resemble vanilla.\n- Painkillers from the medikit now work.\n- Tooltips added for all buttons.\n- Number of Auto-shots is now a definable attribute of a weapon.\n- Warning messages added when handling live grenades.\n- Weapons can be defined to charge a \"flat rate\" rather than a percentage of TUs.\n- Reaction fire mechanics completely re-written to replicate vanilla.\n- Stats added to Armor, allowing it to enhance (or hinder) a soldier's abilities.\n- Map draw functions hugely optimized, game is now playable on Android.\n- Buttons for Reserve for Kneel and Zero Time Units added.\n- Debug feature to kill all aliens added. (Ctrl+K)\n- Auto-Equipment function rewritten to mimic vanilla, and an option added to completely disable auto-assignment.\n- Accuracy model completely rewritten to replicate vanilla as closely as possible.\n- Range based accuracy removed - UFO Extender accuracy added.\n- Throw formula modified to mimic vanilla behaviour, with arc angle being a factor of weight, strength and distance.\n- Items in Base storage are now randomly distributed on the floors of storage facility maps.\n- Explosives will deal directional damage to units outside the \"ground zero\" radius.\n- Aliens will now target and destroy \"essential\" objects in base modules, possibly leading to their destruction.\n- When using a medi-kit, any injured body part will be selected by default.\n- Sprites added for mind controlled terror unit weapons.\n- Shotgun behaviour added for modded weapons.\n- Deployment data for crafts added, allows for fine-tuned placement of units.\n- New sprites added for alien weapons, courtesy of Arne.\n- TFTD damage formula added.*\n- Melee Aliens will now hit you with their strength rather than a static value.\n- Notification added for disarming grenades pre-battle.\n- Smooth bullet camera mode, follows the bullet as it moves rather than jumping the camera around.*\n- Confirm fire mode, requires a second click to confirm a fire order.*\n- Melee skill now included in hit calculations.\n- More meaningful errors added to inventory screen.\n\n* These features are disabled by default but can be enabled in the advanced options menu or by editing your configuration file.\n\nBugfixes:\n\n  General:\n- Fixed \"classic mouse behaviour\" and made it the default. (You should now be able to hold down the left mouse button and drag it down a list, incrementing several items)\n- Various Linux and OSX-related fixes.\n- Renamable fields no longer accept blank strings. (ie. no more bases, interceptors, or soldiers named \"\")\n- Can now set the config folder via command line switch (-user)\n- Fixed loading data from multiple folders.\n- Extra sprites fixed for OSX.\n- Game icon now correctly displayed in game window on all operating systems.\n- Palette system overhauled to prevent windows changing colours incorrectly.\n- Fixed various bugs with Unicode handling in paths and strings.\n- Fixed various UI bugs on tablets.\n\n  Geoscape:\n- X-Com now correctly pays their first month's rent and maintenance in advance.\n- To avoid lawsuits, sacked soldiers no longer take their armour with them.\n- Crashed and landed UFOs no longer display a heading, even if that information is available.\n- If a base is lost and a craft from that base is following a UFO but running low on fuel, do not prompt the player to return the craft to the lost base.\n- Fighters no longer get quicker shots due to a bug that made them move in and out of their maximum weapon range when changing behaviours rapidly.\n- UFOs should no longer escape dogfights too quickly.\n- When the game starts, play the \"GMGEO1\" music track, instead of choosing randomly.\n- When only one item remains to research and is added to the active projects, properly clear it from the \"new projects\" menu.\n- Research now consumes items only as appropriate.\n- Landed/Crashed UFOs will no longer try to detect X-Com bases.\n- Graphs screen scale corrected.\n- UFO flight-paths fixed to use correct areas for waypoint selection. Flight paths should now mimic vanilla (as much as something that's random can)\n- Crafts teleporting when over poles corrected.\n- Rare music bug in base defences fixed.\n- Fix for soldiers in transfer not being counted when handing out promotions.\n- Fix the council congratulating XCom on a job well done as they cancel the project.\n- Downed UFOs will use appropriate behaviour after XCom dusts off.\n- Alien mission timers fixed.\n\n  Battlescape:\n- Fixes to various UFOpaedia articles.\n- Loading saved games now correctly preserves the difficulty adjustments to alien stats.\n- Prime grenade buttons over 10 now work.\n- Alien soldiers now reserve less TUs for reaction fire, and commanders reserve more.\n- Stop turning when a new enemy is spotted, but ensure units will always face their targets when shooting.\n- Re-wrote the reaction fire code to implement fixes and changes, including:\n -- Better handling of reaction fire against the last alien in the battle.\n -- Reaction shots should only be snap shots, not auto.\n -- Firing will trigger a reaction check.\n -- Hitting an alien with a non-melee weapon will cause it to face you.\n -- When two units spot each other at the same time, no reaction fire will occur.\n- Adjusted various distance thresholds to compensate for the original game's attempt to approximate bresenham algorithms.\n- Explosions now correctly cause fire.\n- Fixed strafing through doors.\n- Fixed the order of events in the battlescape loop.\n- Fixed a bug causing some tiles to inappropriately act transparent.\n- Aliens have night vision again, as per the original game, spotting soldiers within 20 tiles regardless of light.\n- XCOM soldiers should now always spot aliens within 18 tiles, regardless of light, and 20 tiles in good light.\n- Inventory: Allow scrolling of items on the ground when only two tiles of empty space remain, instead of just one.\n- When ending a turn, the game will now close doors before setting off explosions.\n- When returning a mind controlled alien to alien control, return their lighting to normal.\n- Corrected how gravity applies to Reapers.\n- Check tiles above explosions for whether items or units need to fall.\n- Fixed silacoid attack ability, and made them immune to fire, so that they don't roast themselves.\n- Fixed some celatid sprites.\n- Stop displaying the PSI button after a psi-capable unit dies.\n- Clear waypoints and top displaying the LAUNCH button if the turn is ended while setting waypoints for the blaster launcher.\n- Fixed a crash on loading the battlescape.\n- Fixed line of sight errors for certain walls.\n- Fixed a crash bug relating to automatically ending battles.\n- Tank inventories will no longer open during the Cydonia phase two transition.\n- Properly reset the turn counter for phase two of Cydonia.\n- Improved attribution of grenade kills.\n- Fixed issues with shooting blaster bombs directly into walls not damaging nearby units.\n- Fixed a bug that caused run mode to \"stick\" after pressing Control while the Strafe setting option was enabled.\n- Fixed a bug that caused grenades primed above \"0\" to still instantly explode when Instant Grenades option was enabled.\n- Weapons that aren't armour piercing now also cause minor stun damage.\n- When aborting a mission, mind controlled aliens no longer count as friendly units for scoring purposes.\n- Soldiers now panic in a way that's more consistent with the original game.\n- All buttons disabled while projectiles are in-flight to disable cheating.\n- Fixed TU costs for some alien weapons. (Some alien melee attacks should have flat costs instead of a percentage of TUs)\n- Instant grenade behaviour fixed.\n- Clip recovery fixed.\n- Grenades no longer cause crashes when used to kill the final enemy.\n- Visibility in smoke corrected.\n- Turning to walk and being interrupted (by spotting a unit) now properly costs TUs.\n- Melee and Medikits now use the same algorithm, and obey stairs properly.\n- Units with built-in weapons no longer drop them when falling unconscious.\n- Fixed various issues regarding \"tanks only\" deployment to mission sites.\n- Revived units will no longer have their full TUs.\n- Units can no longer be saved from zombification by reloading.\n- Chryssalid screaming behaviour fixed.\n- Broken alien base map modules removed from ruleset.\n- Alien equipment random distribution re-aligned with vanilla.\n- Aliens will no longer prime grenades unless they have already thrown it.\n- Explosions now play the full animation instead of starting half way through.\n- Lots of bugs regarding flying in power armor and kneeling fixed.\n- Unconscious units being carried into the exit zone will now be properly accounted for.\n- Accuracy formula corrected.\n- Camera movements now follow vanilla formula.\n- Pathfinding preview altered and fixed in many ways.\n  -- Now updates appropriately according to reserve setting.\n  -- No longer thinks that paths moving vertically wipe out all remaining TUs.\n- Energy recovery now in-line with vanilla formula.\n- Mouse Position (relative to screen) now preserved while drag-scrolling.\n- Z-axis scrolling corrected.\n- Large unit rendering fixed to no longer be drawn through walls.\n- Sprite drawing routines revised.\n\nVersion 0.9 (07-05-2013)\n-------------------------\nNew features:\n  General:\n- Intro cinematic.\n- Game can now be completed, game over screens for winning and losing.\n- Randomizer for \"New Battle\" mode.\n- Your settings in \"New Battle\" mode will be saved for next time you play.\n- New translations: Ukrainian, Bulgarian, Portuguese (Portugal), Spanish (Latin American), Danish.\n- New soldier names: Italian, Hungarian.\n- Aliens progress their equipment levels, races and aggression over time.\n- Added \"Alien Weapon Level\" button in New Battle menu.\n- Added \"Right Click to Delete\" function in save/load menus.\n- Added various display filters to the game, including HQX and various OpenGL shaders.*\n- The game can be dynamically resized to a new display resolution when in windowed mode.*\n- The default windowed mode position can now be edited in the configuration file.*\n- Modular Ruleset support.\n- Added \"Controls\" menu.\n- Added \"Advanced Options\" menu.\n- Added button to Restore Defaults to options.\n- Pause Game on Loss of Focus.**\n\n  Geoscape:\n- Live alien capture and interrogation.\n- Psionic training.\n- Hyper-wave decoding.\n- Alien base handling.\n- Scoring for both aliens and Xcom.\n- Funding nation decision making.\n- Multiple dogfight handling.\n- Graphs screen.\n- Base Defense screens.\n- Full research tree.\n- Alien UFO Mission Generation.\n- Alien retaliatory attacks on Xcom bases.\n- Show radar-range lines on the globe after pressing R key.\n- Show funds above the time.*\n- Added the number of soldiers allocated on craft equipment-screen.\n- Custom initial base layout.* (requires a new game to take effect)\n- Building-Queue: Can place buildings next to uncompleted-buildings.*\n- AutoSell Production state for a manufacturing project by a right click on the increase button.*\n- Allowed multiple items to be produced per hour when very large numbers of engineers are assigned to a project.*\n- Upper limit for alien captures per containment facility.* (visible on Base Info screen)\n- Captive aliens can now be sold in the same manner as dead aliens.*\n- Can transfer crafts while airborne.*\n- Increase/decrease buttons now respond to mouse wheel scrolling when the cursor is above them.*\n- Allocate Scientists and Allocate Engineers screens now respond to mouse wheel scrolling.+\n- Debug mode now enables drawing of country and region borders.\n\n  Battlescape:\n- Battlescape melee unit AI.\n- Unit conversion for chryssalids and zombies.\n- All missing units implemented, both alien units and xcom tanks.\n- All missing items implemented.\n- Psionic attacks implemented.\n- Units dual wielding single handed weapons is now represented on the battlescape.\n- The game now dynamically replaces sprite colours in order to represent soldier ethnicity and hair colour.\n- Equipment loadout saving.\n- Show more stats in inventory view.*\n- Proper A* pathfinding.\n- Battlescape RMB scrolling changed to MMB, renamed to Drag-Scroll, improved.\n- Landing Ufos/Ground Assault missions.\n- Ruleset support for multiple-stage missions.\n- Certain units now \"Yell\" when engaging another unit.\n- Enemy unit stats and armour are now affected by difficulty.\n- Grenade explosions now properly credit the previous owner of the grenade with the kill when a unit dies.\n- Units can now \"fall\" off edges by walking off the side of a roof or platform, and other gravity-related features are implemented.\n- The game now centres on the active soldier when the player closes the inventory screen.\n- Reapers can now reaction-attack soldiers that move into a tile adjacent to them.\n- Aliens will attempt to avoid areas where other aliens have died, except in base defense missions.\n- Various AI improvements.\n- Debug mode now has tile colourisation to represent AI evaluations.\n- Debug mode now has a time-slowing feature, which can be used for graphical or voxel debugging.\n- Alien Bases can now be neutralized by destroying the control room.\n- Mission can be won by mind-controlling all remaining units.*\n\n* These features are disabled by default but can be enabled in the advanced options menu or by editing your configuration file.\n+ These features are enabled by default but can be disabled in the advanced options menu or by editing your configuration file.\n** These features can be altered by editing your configuration file.\n\nBugfixes:\n  General:\n- Updated translations.\n- Added support for more Unicode letters.\n- Fix for extra mouse buttons.\n- Various cursor-related bugfixes/improvements.\n- Support for Haiku folder paths.\n- Fix for 8 KHz WAV-file (in SAMPLEx.CAT) playing.\n- Fixed various memory leaks.\n\n  Geoscape:\n- Fix for a crash bug involving an edge case where several craft were sent to intercept a single UFO.\n- Adjusted the length of the date column on the saved game screen to allow room for translated text.\n- Research consumes items properly.\n- If necessary, craft will now always rearm after refuelling.\n- Fixed error in great circle calculation.\n- It is no longer possible to assign armour to a soldier while they're away from the base.\n- Up/down buttons now need to be held for a quarter-second before they increment by more than one.\n(This should fix single-clicks incrementing totals by more than one, making it hard to hit exact values)\n- Items are no longer removed from stores when they are researched.\n- Cut off input to dogfight screens when your craft is destroyed or the UFO decides to disengage.\n- \"New research available\" popups should now only display the first time you research a technology that will unlock a new branch of research.\n- Fixed: Can't dismantle ANY facility if some of the attributes is overflowed!\n- Fixed: Busy people weren't getting paychecks\n- Fixed radar detection calculation.\n\nBattlescape:\n- Battlescape buttons are now unavailable during alien turn.\n- Fixed bug in map generator regarding nodes outside the map.\n- Improved map generation of alien base assault missions.\n- The player no longer reveals the tile an alien is standing on when they detect an alien on an unrevealed tile.\n- The camera resets after non-reaction shots.\n- Camera now correctly centers on explosions, and properly detects explosion visibility.\n- Projectiles are now visible when they fly above an unrevealed tile.\n- Fixed various display bugs with projectiles.\n- UFO walls can no longer be seen through from certain angles.\n- Reaper Corpse tiles now arranged correctly.\n- Doors should no longer close on top of large units.\n- Players can now recover large unit corpses if the northwest piece is intact, as per the original game.\n- Units on stairs will now correctly reveal tiles on the level above.\n- Opening doors now uses time units correctly.\n- Fixed strange spawn behaviour.\n- Undiscovered aliens are no longer factored into pathfinding.\n- Applying stun damage to unconscious units increasing the time they will remain unconscious.\n- Stun damage should no longer damage items.\n- When units are auto-equipped for battle they will now assign as many items to their belt slots as will fit instead of stopping after 1.\n(This should fix alien grenades being recovered less often than in the original)\n- Motion scanners now detect motion on all different levels in addition to the level of the scanning soldier.\n- Various bugfixes for large units.\n- Various psi-related bugfixes.\n- Various clipping issues fixed.\n- Various pathfinding bugfixes/improvements.\n- Various sound-related fixes.\n- Ethereals can now fly as intended. You have been warned.\n- Added some more robust behaviour around what happens when a unit is forced into an occupied tile.\n(ie. for the floor collapsing beneath a soldier standing above another soldier, and for when an unconscious soldier revives when another soldier is standing in their tile)\n- Fixed a bug where items with unlimited ammo would weigh twice as much as they should.\n(removed the step to add clip weight to a weapon if the weapon is its own ammunition)\n\nVersion 0.4.5 (04-11-2012)\n---------------------------\nNew features:\n- Ufopaedia.\n- Hungarian translation.\n- Rightclick mouse scrolling.\n- Rightclick arrow buttons to min/max values.\n- Can prime a grenade on mission pre-equip (Inventory view) with a right-click.\n- Weapons can be toggled on/off during dogfights.\n- Modular rulesets (specified in options.cfg).\n- Soldier reordering.\n- New options.\n- Man page / command-line help.\n- Logging.\n\nBugfixes:\n- Updated translations.\n- Updated soldier names.\n- Various string clipping issues.\n- Various UI issues.\n- Infinite error message when tanks didn't have ammo.\n- Tanks getting it on in the storage room (recovered when mission ended).\n- Multiple \"Tracking Lost\" windows per UFO.\n- Improved auto-equipping to ignore empty weapons and load weapons on the ground.\n- Brought alien weapons counted towards score.\n- Civilians didn't count towards score.\n- Crash when completing a research.\n- Crash during dogfights.\n- Wrong mouse input in minimap.\n- Starting inventory didn't work correctly in mission simulator.\n- HWP ammo popped up in soldier inventory.\n- Incorrect armor damage modifiers.\n- Workaround for big corpse pieces being recovered.\n- Missing rules for Reaper (crashed terror missions).\n- Ammo being reused after loaded.\n- Civilians counting as saved when mission failed.\n- Projectiles went through UFO if missed.\n- Weird avenger spawn point.\n- Item in elevator crash.\n- Diagonally walking through trees.\n- Items flying in the air when flying unit drops items.\n- Fixed proximity grenade.\n- Wrong craft speed when patrolling.\n- Crash when patrolling after UFO lost.\n- \"Go to last known UFO position\" button not working.\n- Incorrect UFO recovery items.\n- Ammo in weapons wasn't recovered after missions.\n- Crafts were fully unloaded after missions.\n- New crafts don't start in base position.\n- Ammo graphics weren't cleared after unloading weapon.\n- Minimap doesn't update level when using scroll wheel.\n- Missing \"Not enough equipment to fully re-equip squad\" screen.\n- Incorrect title in Promotions screen.\n- Various changes to item creation/recovery in Battlescape.\n- Wrong UFO graphics in interception window.\n- Wrong craft/UFO altitudes.\n- \"UFO tracking lost\" window missing sometimes.\n- Crash when targeted terror site disappears.\n- Reapers having incorrect behavior.\n- Soldiers can turn without TUs.\n- Walking through knocked down walls takes 4 TUs.\n- Primed state of a grenade is not saved in the savegame.\n- Firing and throwing accuracy does not decrease on injury.\n- Diagonal line of sight through windows.\n- Minimap not showing visible aliens on invisible tiles.\n- Visible units not stored in save.\n- Beam weapons not dealing any damage to UFOs.\n- Rewritten dogfight radar animation.\n- Dogfight UFO hit animation.\n- Dogfight UFO crash animation.\n- Dogfight projectiles animation.\n- Projectiles could hit UFO even if it was out of their range.\n- Added craft damage indication.\n- Added translated terrain names to New Battle.\n- Sound and graphics of flying suit.\n- Small pathfinding issue.\n- Segfault when mindprobing empty space.\n- Untranslated Geoscape sidebar.\n- Implemented faster unit walk speed off screen.\n- Items visible on minimap on undiscovered tiles.\n- Units walking on top of each other.\n- Incorrect behavior with ground items in inventory.\n- Options screen and resolution selection.\n- Craft has wrong position when transferred.\n- Craft doesn't reequip when transferred.\n- Game returns to the actual game after saving (instead of previous menu).\n- Drawing issue in medikit and scanner view.\n- Improved explosion animation scaling with power.\n- Explosion sound.\n- Added Elerium-115 to battlescape.\n- Vertical pathfinding.\n- Cancel firing mode when pressing move up/down.\n- Flying up/down graphics.\n- Show damage percent of craft on its state-panel.\n- Buttons not pressing with right-clicks.\n- Bugs in soldier name generation.\n- Added geoscape position to saves.\n- Added \"We can now produce\" Geoscape window.\n- Walk/move sounds.\n- Proper ammo accounting after battles.\n- Added \"loading/saving...\" messages to savegame screens.\n- Being able to input text in resolution.\n- Non-ASCII character input.\n- Non-ASCII savegame names.\n- Crash when trying to rearm crafts with empty weapon slots.\n- Weapons glitching when dropped by panicked soldiers.\n- UFO trying to escape after being destroyed.\n- Freeze in wordwrapping.\n- Big text automatically switches to small if string doesn't fit.\n- Battlescape crash when items were dropped.\n- Unlimited ammo weapons being incorrectly recovered.\n- Mouse being restricted to 320x200 area in some systems.\n- Not being able to overwrite saves with non-ASCII names.\n- Save list not synchronizing with text input.\n- Weapon unload not clearing text.\n- Basescape not resetting time to 5 Secs.\n- Random seed missing in saves.\n- Crash when large units tried to move outside the map.\n- Wrong reaper sound.\n\nVersion 0.4 (13-08-2012)\n-------------------------\nNew features:\n- Basescape:\n-- Research screens.\n-- Manufacture screens.\n-- Soldier improved stats.\n-- Tank equipping.\n-- Armor equipping.\n-- Wound recovery.\n- Geoscape:\n-- New globe shading.\n-- Craft pathfinding now uses great circles (more accurate).\n-- New radar detection formula (more accurate).\n-- Terror sites.\n-- UFOs of all sizes.\n-- Tied research requirements to everything.\n-- UFOs in dogfights fight back.\n- Battlescape:\n-- Abort screen.\n-- Debriefing screen.\n-- Battlescape save game.\n-- Panicking units.\n-- Skill increase and promotions.\n-- Ranged based accuracy is now optional (see UFO Extender for details on Ranged Based Accuracy).\n-- Minimap.\n-- Flying units.\n-- Grav lifts.\n-- Optional pathfinding preview.\n-- Medikits.\n-- Laser weapons.\n-- Large units.\n-- Motion scanner.\n-- Alien deployment rules.\n-- AI taking cover & throwing grenades.\n-- Damage to items.\n-- Mind probe.\n-- Stun rod.\n-- Show/hide battlescape layers button.\n-- Rough battlescape artefacts salvaging functionality.\n-- Added civilians.\n-- Added support for skyranger landing on non 0-level.\n-- Added support for multiple craft/ufo maps.\n-- Psi Amp.\n-- Added support for more alien races.\n-- Load Game button.\n- External rulesets.\n- Added entries for most entities in the game.\n- New Battle screen.\n- Options screen.\n- Startup logging.\n- 64-bit version.\n- Game icon and logo.\n- Support for multiple data folders.\n- Support for XDG specification.\n- Support for user soldier name pools.\n- Various new options (see docs).\n- Debug mode.\n\nBugfixes:\n- Two duplicating ammo bugs.\n- Wrong rocket launcher hand sprite.\n- \"Not enough time units\" during alien turn.\n- Bug where alien weapons are given to the soldiers.\n- Target mode is canceled when switching unit.\n- Reserve time unit button is reset when starting new turn.\n- Minor drawing glitch visible when walking down the skyranger ramp.\n- Geoscape sidebar didn't show up on first start on some languages.\n- Bug with line of sight inside UFOs along diagonal walls.\n- Bug with pathfinding inside UFOs along diagonal walls.\n- Aliens not black when in undiscovered terrain.\n- Issue with turn and shoot.\n- Too many reaction fires from autoshot (each shot had a chance of a reaction shot which is wrong).\n- Unit selection arrow showed up during alien turn.\n- Double sliding door didn't open when walking diagonally.\n- Energy usage not calculated correctly.\n- Missing text in Monthly Report.\n- Ground items showing up in soldier's hands.\n- Improved interface performance.\n- Bug with seeing through undiscovered floors.\n- Updated the Rank Bonus values used to calculate soldier \"value\".\n- Apply changes to the base / soldier name when user presses OK.\n- Incorrect globe zoom levels.\n- Incorrect UI strings.\n- Incorrect colors in Battlescape UI.\n- Crash when starting mission on back side of globe.\n- Endless number of soldiers in Skyranger.\n- Clicking visible enemy units clicks other stuff too.\n- Fixed lazy ground inventory arrangement.\n- Aliens do not suffer from fatal wounds anymore.\n- Improved straight line pathfinding in battlescape.\n- Fixed unable to hit unit on stairs.\n- Fixed drawing hidden object's outlines.\n- Fixed pistol aiming position.\n- Fixed HWP rank image.\n- Fixed no LOF error issues.\n- Fixed issue where unit stopped walking when not seeing new alien units.\n- Fixed alien reaction shots costing no TUs.\n- Camera centers on selected unit on battlescape start.\n- Fixed battlescape kill counter not working.\n- Fix cursor hiding and scrolling during AI turn\n- Fix camera scrolling into dark infinite and beyond\n- Fix unit FOV calculated before AI reaction shot.\n- Fixed \"alien floating error\".\n- Fixed walking under skyranger.\n- Fixed firing XP from explosive ammo.\n- Fixed active weapon display.\n- Fixed issue with dead alien count.\n- Fixed autoshot of HE ammo issue.\n- Save turn number in savegame.\n- Fixed free autoshot ammo.\n- Fixed wrong UI colors.\n- Updated translations.\n- Fixed craft loading bug.\n- Fixed crash with invalid savegames.\n- Fixed savegame list not being sorted.\n- Game no longer crashes if no sound device is available.\n- Crafts that are outside of base no longer show in base view.\n- Fixed globe not redrawing properly sometimes.\n- Fixed various data loading bugs.\n- Sell screen now decreases item quantity.\n- Fixed craft pathing bugs.\n- Fixed bug in command-line parameters.\n- Various performance improvements.\n- Added fallback if no soldier name pools are available.\n- Fixed radar detection.\n- Fixed some bugs in globe.\n- Fixed inventory crash with certain armor types.\n- Fixed crash with loading DOS sounds.\n- Fixed battlescape buttons responding to wrong mouse button.\n- Improved mouse click handling.\n- Fixed Language dialog having wrong height.\n- Game no longer crashes if language isn't found.\n- Game no longer crashes if User directory is unavailable.\n- Game now shows an error if no languages are available.\n- Fixed various bugs with text strings not fitting.\n- Fixed text caret not always aligning properly.\n- Fixed crash with UI buttons.\n- Fixed Intercept string not always showing correct stats.\n- Fixed colors in Target Info and Items Arriving windows.\n- Fixed various savegame bugs.\n\nVersion 0.3 (01-09-2011)\n-------------------------\nNew features:\n- Basescape:\n-- Craft rearming.\n-- Craft equipping.\n-- Purchase/Recruit.\n-- Sell/Sack.\n-- Base transfers.\n- Battlescape:\n-- Battle turns.\n-- Item equipping, firing, throwing.\n-- Environment: fire, smoke, explosions, damage, kills.\n-- Unit stats.\n-- Inventory.\n-- AI Phase 1 (patrol, aggro).\n- New languages: Czech, English (UK), Polish, Romanian, Russian.\n- Support for custom font characters and full Unicode.\n- Options.\n- Platform-specific folders.\n- Partial Ufopaedia.\n- Externalized soldier names.\n- Nag screen only shows once.\n- Swapped F5 and F12 keys.\n- Movable caret in text input.\n- Stores column in Purchase screen.\n\nBugfixes:\n- Bug in Geoscape pathfinding.\n- Incorrect language names.\n- Cross-platform bug when loading PCK files.\n- Invisible loading errors.\n- Incorrect mouse events.\n- Missing strings.\n- Various UI issues.\n- Various translation issues.\n- Bug in craft rearming.\n- FPS Counter didn't always show up properly.\n- Crash sites didn't vanish properly.\n- Failing to load a game could crash the Geoscape.\n- Games weren't always saved properly.\n- Monthly report didn't show correct date.\n- Crafts in base view weren't positioned correctly.\n- Music loading issues.\n- Various battlescape fixes.\n- Various performance improvements.\n\nVersion 0.2 (28-01-2011)\n-------------------------\nNew features:\n- Battlescape!\n-- Crash site missions.\n-- Map generation.\n-- Pathfinding.\n-- Alien placement.\n-- Basic lighting.\n-- Basic fog of war.\n- New language format (with Spanish and Italian languages).\n- Crude Unicode support.\n- Windows installer for all your lazy needs!\n- Load/save infinite games.\n- Screenshot, FPS Counter and Fullscreen keys.\n- Any-resolution scaling.\n- Support for DOS music.\n- Being able to remove bases (Access Lift).\n- Friendly start reminder.\n\nBugfixes:\n- Bug in cursor rendering.\n- Removed unused strings and trademarked game names.\n- Craft maintenance bugs.\n- Bug in text list alignment.\n- Bug in bar rendering.\n- Crash when a UFO intercepted by multiple craft was destroyed.\n- Incorrect text in some screens.\n- Some localized strings didn't fit on screen.\n- Palette bugs.\n- Various memory leaks.\n- Being able to click on globe through windows.\n- Bugs with multiple-target display.\n- Various fixes to globe rendering.\n- Big in text word-wrapping.\n- Reorganized country/region data.\n- Added OK button to Base Name window for people having trouble with Enter key.\n- Removed preloading of every language (only one language is used at once, what was I thinking!).\n- Bug in pixel blitting.\n- Improved error handling.\n- Probably many other minor fixes.\n\nVersion 0.1 (17-11-2010)\n-------------------------\nFirst release!\n- Geoscape:\n-- Fully-controllable globe.\n-- Globe details like country borders and names.\n-- Day/night effect.\n-- Initial base placement.\n-- Basic UFO spawning and detection.\n-- Craft interception with fuel consumption and basic dogfights.\n-- Craft repairing/refuelling/rearming.\n-- Funding overview.\n-- Monthly funding.\n-- Scroll-wheel support.\n- Basescape:\n-- Full base view with facilities.\n-- Building new bases with access lift placement.\n-- Base information.\n-- Base stores.\n-- Soldier stats (with randomly generated soldiers).\n-- Craft info and equipping.\n-- Facility building/removal.\n-- Scroll-wheel support.\n"
  },
  {
    "path": "CMakeLists.txt",
    "content": "cmake_minimum_required ( VERSION 3.5 )\n\nproject ( OpenXcom )\n\nset ( CMAKE_MODULE_PATH \"${CMAKE_SOURCE_DIR}/cmake/modules\" )\ninclude(BuildType)\ninclude(GNUInstallDirs)\n\n\nset (CMAKE_CXX_STANDARD 17)\n# use std=c++11 rather than std=gnu++11\n#set (CMAKE_CXX_EXTENSIONS OFF)\n\noption ( DEV_BUILD \"Development Build. Disable this for release builds\" ON )\noption ( DUMP_CORE \"Disables exception and segfault handling.\" OFF )\noption ( BUILD_PACKAGE \"Prepares build for creation of a package with CPack\" ON )\nset ( TARGET_PLATFORM CACHE STRING \"Target platform to include in the package name (win32, etc)\" )\noption ( EMBED_ASSETS \"Embed common and standard into the executable\" OFF )\noption ( FATAL_WARNING \"Treat warnings as errors\" OFF )\noption ( ENABLE_CLANG_ANALYSIS \"When building with clang, enable the static analyzer\" OFF )\noption ( CHECK_CCACHE \"Check if ccache is installed and use it\" OFF )\nset ( MSVC_WARNING_LEVEL 3 CACHE STRING \"Visual Studio warning levels\" )\noption ( FORCE_INSTALL_DATA_TO_BIN \"Force installation of data to binary directory\" OFF )\nset ( DATADIR \"\" CACHE STRING \"Where to search for datafiles\" )\n\nif ( CHECK_CCACHE )\n  find_program( CCACHE_PROGRAM ccache )\n  if( NOT CCACHE_PROGRAM )\n    message ( FATAL_ERROR \"CCACHE requested but not found on the system.\" )\n  else ()\n    set_property( GLOBAL PROPERTY RULE_LAUNCH_COMPILE \"${CCACHE_PROGRAM}\" )\n    set_property( GLOBAL PROPERTY RULE_LAUNCH_LINK \"${CCACHE_PROGRAM}\" )\n    message ( STATUS \"found CCACHE (${CCACHE_PROGRAM})\" )\n  endif()\nendif ()\n\nif ( WIN32 )\n  set ( default_deps_dir \"${CMAKE_SOURCE_DIR}/deps\" )\nendif ()\n\nif ( APPLE )\n  set ( MACOS_SDLMAIN_M_PATH \"${CMAKE_SOURCE_DIR}/src/apple/SDLMain.m\" CACHE STRING \"Path to SDLMain.m file\" )\n  option ( CREATE_BUNDLE \"Create a Mac OS application bundle\" ON )\n  if ( NOT EXISTS \"${MACOS_SDLMAIN_M_PATH}\" )\n    message ( FATAL_ERROR \"On Mac OS, SDLMain.m is required. Please set the MACOS_SDLMAIN_M_PATH variable\" )\n  endif ()\nendif ()\n\n# C++ version check\nif ( CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES \"Clang\" )\n  include(CheckCXXCompilerFlag)\n  CHECK_CXX_COMPILER_FLAG(\"-std=c++17\" COMPILER_SUPPORTS_CXX17)\n  CHECK_CXX_COMPILER_FLAG(\"-std=c++1z\" COMPILER_SUPPORTS_CXX1Z)\n  if(COMPILER_SUPPORTS_CXX17)\n    set(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -std=c++17\")\n  elseif(COMPILER_SUPPORTS_CXX1Z)\n    set(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -std=c++1z\")\n  else()\n    message( FATAL_ERROR \"The compiler ${CMAKE_CXX_COMPILER} has no C++17 support. Please use a different C++ compiler.\")\n  endif()\nelseif(CMAKE_CXX_COMPILER_ID MATCHES \"MSVC\")\n  include(CheckCXXCompilerFlag)\n  CHECK_CXX_COMPILER_FLAG(\"/std:c++17\" COMPILER_SUPPORTS_CXX17)\n  if(COMPILER_SUPPORTS_CXX17)\n    set(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} /std:c++17\")\n  else()\n    message( FATAL_ERROR \"The compiler ${CMAKE_CXX_COMPILER} has no C++17 support. Please use new VS C++ compiler.\")\n  endif()\nendif()\n\nset ( DEPS_DIR \"${default_deps_dir}\" CACHE STRING \"Dependencies directory\" )\n\n# Find OpenGL\nset (OpenGL_GL_PREFERENCE LEGACY)\nfind_package ( OpenGL )\nif ( NOT OPENGL_FOUND )\n  message ( WARNING \"Can't find OpenGL - continuing building without OpenGL support.\" )\n  add_definitions(-D__NO_OPENGL)\nelse ()\n  include_directories ( ${OPENGL_INCLUDE_DIR} )\n  message ( STATUS \"OpenGL libraries: ${OPENGL_LIBRARIES}\" )\nendif ()\n\n# Include rapidyaml lib\ninclude_directories(${CMAKE_SOURCE_DIR}/libs/rapidyaml)\n\nif(NOT UNIX AND IS_DIRECTORY ${DEPS_DIR})\n   include_directories ( ${DEPS_DIR}/include/SDL ${DEPS_DIR}/include )\n   if ( CMAKE_CL_64 )\n     link_directories ( ${DEPS_DIR}/lib/x64 )\n   else ( )\n     link_directories ( ${DEPS_DIR}/lib/Win32 )\n   endif()\n   set( SDL_LIBRARY SDL )\n   set ( SDLGFX_LIBRARY SDL_gfx )\n   set ( SDLMIXER_LIBRARY SDL_mixer )\n   set ( SDLIMAGE_LIBRARY SDL_image )\n   set ( PKG_DEPS_LDFLAGS ${SDLIMAGE_LIBRARY} ${SDLMIXER_LIBRARY} ${SDLGFX_LIBRARY} ${SDL_LIBRARY} ${OPENGL_LIBRARIES} )\nelseif(UNIX OR MINGW OR CYGWIN)\n  if(IS_DIRECTORY ${DEPS_DIR})\n     set(ENV{PKG_CONFIG_PATH} \"${DEPS_DIR}/lib/pkgconfig/\")\n  endif()\n\n  include(FindPkgConfig)\n  pkg_check_modules(PKG_SDL REQUIRED sdl)\n  pkg_check_modules(PKG_ZLIB REQUIRED zlib)\n  pkg_check_modules(PKG_SDLIMAGE REQUIRED SDL_image)\n  pkg_check_modules(PKG_SDLGFX REQUIRED SDL_gfx)\n  pkg_check_modules(PKG_SDLMIXER REQUIRED SDL_mixer)\n\n  include_directories(${PKG_SDL_INCLUDE_DIRS} ${PKG_ZLIB_INCLUDE_DIRS} ${PKG_SDLIMAGE_INCLUDE_DIRS})\n  include_directories(${PKG_SDLGFX_INCLUDE_DIRS} ${PKG_SDLMIXER_INCLUDE_DIRS})\n  set(PKG_DEPS_LDFLAGS ${PKG_SDL_LDFLAGS} ${PKG_ZLIB_LDFLAGS} ${PKG_SDLIMAGE_LDFLAGS} ${PKG_SDLGFX_LDFLAGS} ${PKG_SDLMIXER_LDFLAGS} ${OPENGL_LIBRARIES})\n\n  if (UNIX)\n    set(PKG_DEPS_LDFLAGS \"${PKG_DEPS_LDFLAGS};dl\")\n  endif()\n  message ( STATUS \"PKG_DEPS_LDFLAGS: ${PKG_DEPS_LDFLAGS} \")\nelse()\n  message ( FATAL_ERROR \"pkg-config is not supported on your platform. Use DEPS_DIR\" )\nendif()\n\n# Read version number\nset ( file \"${CMAKE_SOURCE_DIR}/src/version.h\" )\nfile ( READ ${file} lines )\nstring ( REGEX MATCH \".*OPENXCOM_VERSION_LONG \\\"([0-9]+)\\\\.([0-9]+)\\\\.([0-9]+)\" version_line \"${lines}\" )\nset ( CPACK_PACKAGE_VERSION_MAJOR ${CMAKE_MATCH_1} )\nset ( CPACK_PACKAGE_VERSION_MINOR ${CMAKE_MATCH_2} )\nset ( CPACK_PACKAGE_VERSION_PATCH \"${CMAKE_MATCH_3}\" )\n\nfind_package ( Git )\nif ( GIT_FOUND )\n  execute_process ( COMMAND ${GIT_EXECUTABLE} describe --dirty\n    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}\n    OUTPUT_VARIABLE git_describe_out\n    ERROR_VARIABLE git_describe_error\n    RESULT_VARIABLE git_describe_result\n    )\n  string ( REGEX MATCH \"([a-z|0-9|.]*)-([0-9]*)-g([a-z|0-9]*)([-|a-z]*)\" git_commit \"${git_describe_out}\" )\n  set ( git_tag ${CMAKE_MATCH_1} )\n  set ( git_nb_commit ${CMAKE_MATCH_2} )\n  set ( git_commit ${CMAKE_MATCH_3} )\n  set ( git_dirty ${CMAKE_MATCH_4} )\n  execute_process ( COMMAND ${GIT_EXECUTABLE} show -s --format=%ci\n    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}\n    OUTPUT_VARIABLE git_show_out\n    ERROR_VARIABLE git_show_error\n    RESULT_VARIABLE git_show_result\n  )\n  string ( REGEX MATCH \"[0-9-]+\" git_date \"${git_show_out}\" )\n  set ( GIT_STATE \"${git_commit}-${git_date}${git_dirty}\" )\nelse ()\n  message( WARNING \"Git not found.\")\nendif()\n\nset ( OPENXCOM_VERSION_GIT \"${GIT_STATE}\" CACHE STRING \"Git version string (after x.x.x)\" )\n\nconfigure_file(\"${CMAKE_SOURCE_DIR}/src/git_version.h.in\" \"${CMAKE_CURRENT_BINARY_DIR}/git_version.h\" )\ninclude_directories ( \"${CMAKE_CURRENT_BINARY_DIR}\" )\n\nif ( BUILD_PACKAGE )\n  set ( CPACK_PACKAGE_VERSION \"${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}-${GIT_STATE}\" )\n  set ( CPACK_SOURCE_PACKAGE_FILE_NAME \"Extended-${CPACK_PACKAGE_VERSION}-src\" )\n  set ( CPACK_PACKAGE_FILE_NAME \"Extended-${CPACK_PACKAGE_VERSION}-unknown\" ) # TODO: determine package suffix (osrelease+arch)\n\n  if ( NOT CPACK_GENERATOR )\n    set ( CPACK_GENERATOR \"TXZ\" )\n  endif ()\n  if ( NOT CPACK_SOURCE_GENERATOR )\n    set ( CPACK_SOURCE_GENERATOR \"TXZ\" )\n  endif ()\n\n  set ( CPACK_PACKAGE_VENDOR \"The OpenXcom project\" )\n  set ( CPACK_PACKAGE_DESCRIPTION_SUMMARY \"Open-source clone of UFO: Enemy Unknown\" )\n  set ( CPACK_PACKAGE_DESCRIPTION_FILE \"${CMAKE_SOURCE_DIR}/cmake/modules/Description.txt\" )\n  set ( CPACK_RESOURCE_FILE_README \"${CMAKE_SOURCE_DIR}/README.md\" )\n  set ( CPACK_PACKAGE_CONTACT \"The OpenXcom project (http://www.openxcom.org)\" )\n  # DMG-specific -- sets CPACK_GENERATOR to DragNDrop itself\n  if (APPLE)\n    set ( TARGET_PLATFORM \"macos\" )\n    set ( CPACK_BUNDLE_NAME \"OpenXcom Extended\" )\n    set ( CPACK_BUNDLE_ICON \"${CMAKE_SOURCE_DIR}/res/mac/AppIcon.icns\" )\n    set ( CPACK_BUNDLE_PLIST \"${CMAKE_BINARY_DIR}/openxcom.app/Contents/Info.plist\" )\n    set ( CPACK_DMG_VOLUME_NAME \"OpenXcom Extended\" )\n    set ( CPACK_DMG_BACKGROUND_IMAGE \"${CMAKE_SOURCE_DIR}/res/openxcom_block.png\" )\n    set ( CPACK_GENERATOR \"DragNDrop\")\n  else()\n    set ( CPACK_RESOURCE_FILE_LICENSE \"${CMAKE_SOURCE_DIR}/LICENSE.txt\" )\n  endif()\n\n  string ( LENGTH \"${TARGET_PLATFORM}\" has_target )\n  if ( ${has_target} GREATER 0 )\n    set ( CPACK_PACKAGE_FILE_NAME \"Extended-${CPACK_PACKAGE_VERSION}-${TARGET_PLATFORM}\" )\n  else ()\n    set ( CPACK_PACKAGE_FILE_NAME \"Extended-${CPACK_PACKAGE_VERSION}-unknown\" )\n    message ( WARNING \"Missing OPENXCOM_TARGET for package naming. Please set it.\" )\n  endif()\n\n  # DEB-specific -- set -DCPACK_GENERATOR=DEB\n  if ( \"${CPACK_GENERATOR}\" MATCHES \"^(.*;)?DEB(;.*)?$\" )\n    set ( CPACK_DEBIAN_PACKAGE_MAINTAINER \"The OpenXcom project\" )\n    set ( CPACK_DEBIAN_PACKAGE_HOMEPAGE \"https://openxcom.org/\" )\n    set ( CPACK_DEBIAN_PACKAGE_SECTION \"games\" )\n    set ( CPACK_DEBIAN_PACKAGE_PRIORITY \"optional\" )\n    set ( CPACK_DEBIAN_COMPRESSION_TYPE \"xz\" )\n    if ( \"${CMAKE_SYSTEM_PROCESSOR}\" STREQUAL \"x86_64\" )\n      set ( CPACK_DEBIAN_PACKAGE_ARCHITECTURE \"amd64\" )\n    elseif ( \"${CMAKE_SYSTEM_PROCESSOR}\" STREQUAL \"i686\" )\n      set ( CPACK_DEBIAN_PACKAGE_ARCHITECTURE \"i386\" )\n    endif ()\n    if ( NOT CPACK_DEBIAN_PACKAGE_DEPENDS )\n      message ( STATUS \"CPACK_DEBIAN_PACKAGE_DEPENDS not set - DEB package will have no dependencies\" )\n    endif ()\n  endif ()\n  # RPM-specific -- set -DCPACK_GENERATOR=RPM\n  if ( \"${CPACK_GENERATOR}\" MATCHES \"^(.*;)?RPM(;.*)?$\" )\n    set ( CPACK_RPM_PACKAGE_LICENSE \"GPLv3\" )\n    set ( CPACK_RPM_PACKAGE_GROUP \"Amusements/Games\" )\n    set ( CPACK_RPM_PACKAGE_URL \"https://openxcom.org/\" )\n    set ( CPACK_RPM_COMPRESSION_TYPE \"xz\" )\n    if ( NOT CPACK_RPM_PACKAGE_REQUIRES )\n      message ( STATUS \"CPACK_RPM_PACKAGE_REQUIRES not set - RPM package will have no dependencies\" )\n    endif ()\n  endif ()\n  # NSIS-specific -- set -DCPACK_GENERATOR=NSIS\n  set ( CPACK_NSIS_MODIFY_PATH OFF )\n  set ( CPACK_NSIS_DISPLAY_NAME \"OpenXcom Extended\" )\n  include ( CPack )\n  message ( STATUS \"OpenXcom version: ${CPACK_PACKAGE_VERSION}\")\nendif()\n\nif ( NOT WIN32 OR NOT CPACK_GENERATOR STREQUAL \"7Z\" ) # FIXME: that's to exclude DEB and RPM, but hacky.\n  install(FILES \"${CMAKE_SOURCE_DIR}/res/linux/openxcom.desktop\"\n    DESTINATION \"${CMAKE_INSTALL_FULL_DATAROOTDIR}/applications\")\n  install(FILES \"${CMAKE_SOURCE_DIR}/res/linux/icons/openxcom_48x48.png\"\n    DESTINATION \"${CMAKE_INSTALL_FULL_DATAROOTDIR}/icons/hicolor/48x48/apps\" RENAME openxcom.png)\n  install(FILES \"${CMAKE_SOURCE_DIR}/res/linux/icons/openxcom_128x128.png\"\n    DESTINATION \"${CMAKE_INSTALL_FULL_DATAROOTDIR}/icons/hicolor/128x128/apps\" RENAME openxcom.png)\n  install(FILES \"${CMAKE_SOURCE_DIR}/res/linux/icons/openxcom.svg\"\n    DESTINATION \"${CMAKE_INSTALL_FULL_DATAROOTDIR}/icons/hicolor/scalable/apps\")\nendif ()\n\nadd_subdirectory ( docs )\nadd_subdirectory ( src )\n"
  },
  {
    "path": "Extended.txt",
    "content": "[b]Extended version of OpenXcom[/b]\n[b]Mod version 5.0[/b]\nOpenXcom date:   Nightly [dateOrigin/][br/]\nOpenXcom commit: [commitOrigin/][br/]\nExtended date:   [date/][br/]\nExtended commit: [commit/][br/]\n\n[br/][br/]\n[i]Ubuntu required libs[/i]\nsudo apt-get install libsdl1.2debian libsdl-mixer1.2 libsdl-gfx1.2-4 libsdl-image1.2 libyaml-cpp0.5[br/]\n\n[br/][br/]\n[i]Behavior change[/i]\n\nHyper-Wave Decoder can have less than 100% chance to detect aliens.[br/]\nExplosions don't remove unconscious unit if they can't kill them first.[br/]\nCraft weapon equip screen is a bit rearranged.[br/]\nFixed \"weapons\" like the Medikit are now equipped by unit.[br/]\nPsi-Amp use 3d range, not 2d.[br/]\nPsi-Amp can use weapon power.[br/]\nFixed ammo are added after weapons in armor and unit (armor items are before unit items).[br/]\nCorpses, items and Chryssalids are not spawned when unit is killed by weapons with overkill.[br/]\nStunned units can be hited by bullets and fire.[br/]\nBig groups of aliens (20+) get less morale losses from casualties.[br/]\nTerror units can now spawn with any built-in weapon, not only one defined by name.[br/]\nWhile loading and unloading weapons you must pay the cost of moving the item to hand.[br/]\nYou can unprime granade for half of prime TUs cost.[br/]\nSupport for Ufo2000 armor damage type.[br/]\nPsi-Amp can now obey maximum weapon range.[br/]\nPsi-Amp can now deal direct damage using special attack type in popup menu.[br/]\nThrowing now requires a healthy arm to do it (if the item is two-handed, then it requires both).[br/]\nYou can hit aliens in the head using any item you like, not only firearms stock.[br/]\nItems can now be non-throwable.[br/]\nRewriten handling of alien psi attacks to handle new features of Psi-Amp.[br/]\nBuilding, manufactures and research can now have special requirements for buildings available in base.[br/]\nThrowing and hitting using two-handed weapons have the same penalty as with shooting.[br/]\n[br/]\n1.6:[br/]\nYou can train your solders basic skills.[br/]\nAliens weapon types/weapons can have different turn restriction.[br/]\nYou can rename weapon slot names in geoscape craft info.[br/]\n[br/]\n1.7:[br/]\nRewritten item use cost. Now is possible to spend HP, Morale or grain stun damage from using items.[br/]\nYou can't use old `energy*` properties in item, they are removed and replaced by new one in `cost*`.[br/]\nItem have now range threshold unit they start calculating range power reduction.[br/]\nDamage type can now change default power change per tile in explosion.[br/]\n[br/]\n1.8:[br/]\nOption for custom weapon deploy for alien missions and ufos.[br/]\n[br/]\n1.9:[br/]\nOptions for customizing retaliation mission after shooting dow ufo.[br/]\nOptions for adding custom dodge chance or unit psi defence.[br/]\n[br/]\n2.0:[br/]\nBreaking change: Psi-Amp use now weapon dropoff and aimRange for attack chance.[br/]\nBreaking change: Drop support for Regeneration stat in armor. Use new regen stats now.[br/]\nInventory screens can now have up to 128 backgrounds.[br/]\nUnit sprites recolors can now support up to 128 values.[br/]\nOption for custom change of TU, HP, Energy, Morale or Stun after next turn based on unit stats.[br/]\nNew stat bonus based on stun level of unit.[br/]\nOption for changing fuse type in granades and flare.[br/]\nOption for pre-priming granades on map spawn.[br/]\nOption for dodge chance based on direction of attack.[br/]\nOprion for bonus morale recovery when using medkit.[br/]\nOption for self heal using medikit.[br/]\n[br/]\n2.1:[br/]\nCraft can now have up to 4 different wepon type per slot.[br/]\nOprion for overriding shape of alien base.[br/]\nOption for setting chance of special effect of item.[br/]\nMoving can trigger all close proxy not only one.[br/]\nCorpse explosion now can have bonus based on unit stats.[br/]\nGrenades now can explode at once without destroying each others.[br/]\n[br/]\n2.2:[br/]\nOption for custom sound and animation for miss attack and psi weapons.[br/]\n[br/]\n2.3:[br/]\nOption for defining percent of all action cost stats. Old use of `flatPrime` and `flatThrow` is deprecated.[br/]\nFacilities can now require items to build.[br/]\nMedikit can now be used without UI and can use `hitSound`.[br/]\n[br/]\n2.4:[br/]\nOption for defining bonus and damage type for melee in range weapons.[br/]\nOption for big explosion sound for each items.[br/]\nOption for showing fixed weapons on unit.[br/]\n[br/]\n2.5:[br/]\nUpdate to nightly and bug fix.[br/]\n[br/]\n2.9:[br/]\nScripting support in unit graphic (more info in game log with debug on).[br/]\n`bigSpriteAlt` and `floorSpriteAlt` is now obsolete, will be replaced by scripts in next version.[br/]\nNew property `refNode` used to shared values between items/solders/armors etc.[br/]\nOption for setting numbers of melee hits done by AI.[br/]\nControl space usage of soldiers with 2x2 armors in crafts.[br/]\n[br/]\n3.0:[br/]\nBackported game machanic changes from Meridian OXCE+.[br/]\nFix stun damage calculation and add random for random option for final stats change by damage.[br/]\nRefactored script handling.[br/]\nScript support in reaction atack chance calculations.[br/]\nSome light handling improvments.[br/]\nNew recolr and replace script graphic option for items.[br/]\nOption for global events shared by scripts.[br/]\nCustom tags that have user defined values.[br/]\n[br/]\n3.1:[br/]\nBase building can now prevent building other buildings.[br/]\nNew tag type that store other mod id.[br/]\nOption for changing defualt unit light radius.[br/]\nNew functions exposed to script.[br/]\nReaction scripts have now information about runing or strafing of target.[br/]\n[br/]\n3.2:[br/]\nNew functions exposed to script.[br/]\n[br/]\n3.3:[br/]\nNew light system.[br/]\nOption for reserving more space for mod in common surface/sound sets.[br/]\nVisibility scripts that determine visibility of targets.[br/]\n[br/]\n3.5:[br/]\nUpdate to buildin script functions.[br/]\nUpdate to recent nightly OpenXcom.[br/]\n[br/]\n3.6:[br/]\nConfig for new lighting system.[br/]\nNew map script options made by ohartenstein23.[br/]\nNew scripts for items and units.[br/]\nAdd option for grenades to explode in hand.[br/]\nChanges in handlig items with prime.[br/]\nPrimed granades are not recoverable if consumable property is set.[br/]\n[br/]\n3.6a:[br/]\nFix couple of bugs.[br/]\nAdd some missed scripts.[br/]\nAdd damage type param to unit damage script.[br/]\n[br/]\n3.6b:[br/]\nFix critical bug in unit damage function.[br/]\n[br/]\n3.7:[br/]\nNew params with shooting weapon and shooter to damage and hit script.[br/]\nMerge chagnes from master.[br/]\nRandom functions in script.[br/]\nVertical map generation support.[br/]\n[br/]\n3.8:[br/]\nAdd multi ammo weapons.[br/]\nNew param with battle action for unit hit and damage script.[br/]\n[br/]\n3.8a:[br/]\nBug fix.[br/]\n[br/]\n3.9:[br/]\nBug fix.[br/]\nImprovments in displaying multiple ammo items in inventory.[br/]\nScript altering experience grain.[br/]\n[br/]\n3.9a:[br/]\nBug fix.[br/]\n[br/]\n3.9b:[br/]\nBug fix.[br/]\n[br/]\n3.9c:[br/]\nBug fix.[br/]\n[br/]\n3.10:[br/]\nBug fix.[br/]\nUpdate nightly.[br/]\nNew grenade fuse config.[br/]\n[br/]\n3.10a:[br/]\nBug fix.[br/]\nUpdate nightly.[br/]\n[br/]\n3.10b:[br/]\n[br/]\n4.0:[br/]\nDamage script can now alter zombie transformation chance.[br/]\nAdd access to current difficulty level in scripts.[br/]\nAdd base function requirmets to buy items, crafts and solders.[br/]\nAdd access to geoscape soldier in scripts.[br/]\nAdd script that is run at end of mission.[br/]\nAdd arcing shoots per attack type (by ohartenstein23).[br/]\nBreaking change: Renamed `action` to `battle_action` in reaction scripts.[br/]\nAdd battle action to `awardExperience` script.[br/]\nBreaking change: Renamed access function to statis in armor (added prefix `Stats.`).[br/]\n[br/]\n4.0a:[br/]\nBug fix.[br/]\n[br/]\n5.0:[br/]\nMerge both OXCE and OXCE+ into one.[br/]\n[br/]\n\n[examples]\n[br/][br/]\n[i]New ruleset[/i]\n\nExample of usage:\n\nIn `metadata.yml`:\n[code]\nreservedSpace: 4 #how many BIGOBS.PCK/FLOOROB.PCK/BATTLE.CAT etc. reserve for that mod, this is multiply of default reserved size.\n[/code]\n\nIn `*.rul`:\n[code]\nitemCategories:             #from OXCE+\nstartingConditions:         #from OXCE+\ntooMuchSmokeThreshold:      #from OXCE+\ncustomTrainingFactor: 100   #change whow fast solders train.\nchanceToStopRetaliation: 0  #chance to stop retaliation.\nkneelBonusGlobal: 120       #default kneel weapon accuracy bonus in prercent.\noneHandedPenaltyGlobal: 80  #default two hand weapon accuracy penalty in percent.\nmissionRatings:             #from OXCE+\nmonthlyRatings:             #from OXCE+\ndifficultyBasedRetaliationDelay: #from OXCE+\n[/code]\n\n[code]\nitems:\n  - type: STR_ITEM_TYPE #default config ...\n    nameAsInem: ~           #string id used for displaying postfix ammo text in loaded weapon.\n    categories: ~           #from OXCE+\n    kneelBonus: -1          #kneel weapon accuracy bonus in prercent.\n    oneHandedPenalty: -1    #two hand weapon accuracy penalty in percent.\n    dropoff: 1     #used by Psi-Amp too. Default for Psi-Amp is 1.\n    aimRange: 0    #used by Pis-Amp too. Default for Psi-Amp is 0.\n    tuLoad: 15     #cost of loading weapon.\n    tuUnload: 8    #cost of unloading weapon.\n    specialChance: 90       #chance in % of triggering effect like zombify or corpse, granade and proxy explosion.\n    fuseType: -2            #set how prime granade works.\n    # -3 -> no priming, flare always work.\n    # -2 -> can prime, unlimited time. Granade explode instantly after throw. Flare work only after prime.\n    # -1 -> can prime, can set time. Granade explode after set time. Flare and Proxy disappere after set time.\n    #  0 -> can prime, set fixed time of 0 turns.\n    #  1 -> can prime, set fixed time of 1 turns.\n    #  2 -> can prime, set fixed time of 2 turns.\n    # ...\n    # 22 -> can prime, set fixed time of 22 turns.\n    # 23 -> can prime, set fixed time of 23 turns.\n    fuseTriggerEvents:\n      defaultBehavior: true   #used to enable default fuse behavior. Defualt `true`.\n      throwTrigger: false     #timer start on throw.\n      throwExplode: false     #item explode (grenade) or is removed on thorw. Defualt `false`. `specialChance` affect this.\n      proximityTrigger: false #timer start when unit move in it proximity. Defulat `false`.\n      proximityExplode: false #item explode (grenade, proxi) or is removed when unit move in it porximity. Default `false`. `specialChance` affect this.\n    accuracyUse: 0          #bonus to accuracy of Psi-Amp special attack.\n    accuracyMindControl: 0  #bonus to accuracy of Psi-Amp Mind Control attack.\n    accuracyPanic: 0        #bonus to accuracy of Psi-Amp Panic attack.\n    accuracyThrow: 0        #accuracy of throw.\n    costAimed:\n      #cost of Aimed attack.\n      time: 2         #time units cost, can be in %. Alias of `tuAimed`.\n      energy: 0       #energy unit cost.\n      morale: 10      #morale points cost.\n      health: 1       #health points cost.\n      stun: 2         #stun damage applied by atack use.\n    costAuto:\n      #cost of Auto attack, if -1 it use `costAimed` value.\n      #same propertes like `costAimed`.\n    costSnap:\n      #cost of Snap attack, if -1 it use `costAimed` value.\n      #same propertes like `costAimed`.\n    costMelee:\n      #cost of Melee attack.\n      #same propertes like `costAimed`.\n    costUse:\n      #cost of item Use and Psi-Amp special attack.\n      #same propertes like `costAimed`.\n    costMindControl:\n      #cost of Psi-Amp Mind Control attack, if -1 it use `costUse` value.\n      #same propertes like `costAimed`.\n    costPanic:\n      #cost of Psi-Amp Panic attack, if -1 it use `costUse` value.\n      #same propertes like `costAimed`.\n    costThrow:\n      #cost of Throw.\n      #same propertes like `costAimed`.\n    costPrime:\n      #cost of Prime granade.\n      #same propertes like `costAimed`.\n    costUnprime:\n      #cost of Unprime granade.\n      #same propertes like `costAimed`.\n    flatUse:\n      #change how cost of all attacks and use work (flat or percent values).\n      time: true      #time units cost is flat or %. Alias of `flatRate`.\n      energy: true    #energy unit cost is flat or %. Default `true`.\n      morale: true    #morale cost is flat or reduced by bravery. Default `true`.\n      health: true    #health points cost is flat or %. Default `true`.\n      stun: false     #stun damage applied by atack is flat or % of max health. Default `true`.\n    flatAimed:\n      #changes how `costAimed` behaves (flat or percent values), if -1 it use `flatUse` value.\n      #same propertes like `flatUse`.\n    flatAuto:\n      #changes how `costAuto` behaves (flat or percent values), if -1 it use `flatAimed` value.\n      #same propertes like `flatUse`.\n    flatSnap:\n      #changes how `costSnap` behaves (flat or percent values), if -1 it use `flatAimed` value.\n      #same propertes like `flatUse`.\n    flatMelee:\n      #optional for `costMelee` in range weapons.\n      #same propertes like `flatUse`.\n      #use of null (aka `~`) or -1 in property will cause fall back to `flatUse` values.\n    flatThrow:\n      #changes how `costThrow` behaves (flat or percent values).\n      #same propertes like `flatUse`.\n    flatPrime:\n      #changes how `costPrime` behaves (flat or percent values).\n      #same propertes like `flatUse`.\n    flatUnprime:\n      #changes how `costUnprime` behaves (flat or percent values).\n      #same propertes like `flatUse`.\n    confAimed:\n      shots: 1              #number of shots. Defulat `1`.\n      name: STR_AIMED_SHOT  #name of attack in action menu.\n      ammoSlot: 0           #with ammo slot is used by this attack. Defulat `0`.\n      arcing: false         #if `true` it will change attack to arcing shoot.\n    confAuto:\n      shots: 3              #number of shots, its alias with `autoShots`.\n      #...\n      #same properties as `confAimed`\n      #...\n    confSnap:\n      #...\n      #same properties as `confAimed`\n      #...\n    confMelee:\n      name: ~               #if no name is set name then it will be set based on damage type (stun or normal melee).\n      ammoSlot: -1          #override when `battleType` is change, `0` for melee weapons, `-1` for rest.\n      #...\n      #same properties as `confAimed`\n      #...\n    ammo:   #list of avaiable ammo slots in weapon.\n      0:\n        tuLoad: 10                          #alias to `tuLoad` in parent node.\n        toUnload: 20                        #alias to `tuUnload` in parent node.\n        compatibleAmmo: [ AMMO_A, AMMO_B ]  #alias to `compatibleAmmo` in parent node.\n      1:\n        #...\n        #analoge properties as `0` but without aliasing to parent.\n        #...\n      2:\n        #...\n        #analoge properties as `0` but without aliasing to parent.\n        #...\n      3:\n        #...\n        #analoge properties as `0` but without aliasing to parent.\n        #...\n    damageBonus: #used by ammo.\n      #each bonus can be writen as: `s: x`, `s: [x]`, `s: [x, y]` or `s: [x, y, z]`.\n      #where each value represents coefficient of polynomial `x * s + y * s^2 + z * s^3`.\n      #\n      #set `strength` to 1.0 if `strengthApplied: true`.\n      flatHundred: 0.0 #const bonus equal 100.\n      flatOne: 0.0 #const bonus equal 1.\n      strength: 0.1\n      psi: 0.0 #bonus equal `psiSkill*psiStrength`.\n      psiSkill: 0.5\n      psiStrength: 0.0\n      throwing: 0.0\n      bravery: 0.0\n      firing: [0.0, 0.0, 0.0]\n      health: [0.3]\n      tu: 0.0\n      reactions: [1, -0.002]\n      stamina: 0.0\n      melee: 0.0\n      strengthMelee: 0.0      #bonus equal `strength*melee`.\n      strengthThrowing: 0.0   #bonus equal `strength*throwing`.\n      firingReactions: 0.0    #bonus equal `firing*reaction`.\n      healthCurrent: 0.0      #curret value of hp.\n      tuCurrent: 0.0          #curret value of tu.\n      energyCurrent: 0.0      #curret value of energy.\n      moraleCurrent: 0.0      #curret value of morale.\n      stunCurrent: 0.0        #curret value of stun level.\n      healthNormalized: 0.0   #curret hp normalized to 1 (max hp give 1.0).\n      tuNormalized: 0.0       #curret tu normalized to 1 (max tu give 1.0).\n      energyNormalized: 0.0   #curret energy normalized to 1 (max energy give 1.0).\n      moraleNormalized: 0.0   #curret morale normalized to 1 (max morale give 1.0).\n      stunNormalized: 0.0     #curret stun level normalized to 1 (max stun compared to current health give 1.0).\n    meleeBonus: #used by range weapons melee hit.\n      #...\n      #same stats like `damageBonus`.\n      #...\n    accuracyMultiplier: #used by wapons and psi-amp.\n      #set `psi` to 0.02 if weapon is psi-amp\n      #...\n      #same stats like `damageBonus`.\n      #...\n    meleeMultiplier: #used by melee wapons.\n      #set `melee` to 1.00 if `skillApplied: true`\n      #...\n      #same stats like `damageBonus`.\n      #...\n    throwMultiplier: #used by throw.\n      #set `throwing` to 1.00 for default\n      #...\n      #same stats like `damageBonus`.\n      #...\n    powerRangeReduction: 0.0 #how much power a bullet loses per tile, used by Psi-Amp damage too.\n    powerRangeThreshold: 0.0 #how far in tiles bullet need fly to start appling `powerRangeReduction`.\n    damageAlter: #all values have default values based on `damageType`, used by ammo and corpses.\n      FixRadius: 60 #aka `BlastRadius`.\n      RandomType: 1 #how roll damage range.\n      # 0-> default behavior based on damage type\n      # 1-> UFO [0% - 200%]\n      # 2-> TFTD [50% - 150%]\n      # 3-> Flat  [100% - 100%]\n      # 4-> Rng(5,10)\n      # 5-> 0\n      # 6-> Two dices [0% - 100%] + [0% - 100%]\n      ResistType: 1             #what resistance is used by an affected unit, same values like `damageType`.\n      FireBlastCalc: false      #fire had special way of calculating blast.\n      IgnoreDirection: true     #damage ignores direction of hit, used by smoke and fire.\n      IgnoreSelfDestruct: true  #killing using this damage prevents self-destruct by this unit. Used by stun and explosive damage type.\n      IgnorePainImmunity: true  #some units don't get stun level from damage.\n      IgnoreNormalMoraleLose: false #some units ignore normal morale loss from damage.\n      IgnoreOverKill: false     #disables overkill damage. Defualt `true`.\n      ArmorEffectiveness: 0.5   #how effective armor is against this damage. Default `0.0` for smoke and stun, `1.0` rest.\n      RadiusEffectiveness: 0.3  #how power translates to splash radius. Defualt `0.05` for smoke, stun, explosive, `0.03` for fire, `0.0` rest.\n      RadiusReduction: 10.0     #how much explosion power is reduce per tile. Default `10.0`.\n      FireThreshold: 0          #how much damage is required to spawn fire on unit (after armor and ToHealth) or tile. Default `0` for fire, `1000.0` for rest.\n      SmokeThreshold: 100       #how much damage is required to spawn smoke on tile. Default `0.0` for smoke, `1000.0` for rest.\n      ToHealth: 1.0     #how much damage is done to health, can be negative. Default `0.0` for stun, smoke, none, `1.0` for rest.\n      ToArmor: 0.25     #how much damage is done to armor. Default `0.0` for stun, smoke, fire, none, `0.25` for rest.\n      ToArmorPre: 0.0   #how much damage is done to armor before applying armor protection. Default `0.0`.\n      ToWound: 0.1      #determine probability of wounds. Defualt `0.0` for stun, smoke, fire, none, `1.0` for rest (`RandomWound` by defulat change it io 1-3 points by defualt!).\n      ToItem: 0.0       #how much power is applied to items. Default `1.0` for explosive, `0.0` for rest.\n      ToTile: 0.0       #how much power is applied to the ground. Default `0.0` for stun, smoke, fire, none, `0.5` for rest.\n      ToStun: 0.25      #how much damage increases stun level. Default `1.0` for stun, smoke, `0.0` for fire, none, `2.5` for rest.\n      ToEnergy: 0.0     #how much power is applied to energy loss. Default `0.0`.\n      ToTime: 0.0       #how much power is applied to time units loss. Default `0.0`.\n      ToMorale: 0.0     #how much power is applied to morale loss. Affeced by target bravery. Default `0.0` (`IgnoreNormalMoraleLose` control normal morale change).\n      RandomHealth: false     #do calucaltion of final health change use random value.\n      RandomArmor: false      #do calculation of final armor change use random value.\n      RandomArmorPre: false   #do calculation of final armor change use random value.\n      RandomWound: false      #for `true` use original radom system giving `1` to `3` wounds, `false` will give linear value based on `ToWound`.\n      RandomItem: false       #do calculation of value that compare with item armor use random value.\n      RandomTile: false       #do calculation of value that compare with tile armor use random value.\n      RandomStun: false       #do calculation of final stun level change use random value.\n      RandomEnergy: false     #do calculation of final energy change use random value.\n      RandomTime: false       #do calculation of final time units change use random value.\n      RandomMorale: false     #do calculation of final moral change use random value.\n    meleeType: 2        #work like `damageType` but for range weapon melee hit.\n    meleeAlter:         #work like `damageAlter` but for range weapon melee hit.\n      #set defaut values based on `meleeType`.\n      #...\n      #same stats like `damageAlter`.\n      #...\n    requiresBuy: #what tech is required for the item to be visible in the Hire/Purchase screen.\n      - SOME_TECH\n      - SOME_TECH_MK2\n    requiresBuyBaseFunc:  #list of required base functions needed to buy this.\n      - SOME_BASE_FUNC_A\n    psiAttackName: STR_HIT_MELEE                      #string id of psi-amp attack name in the pop-up menu. Required to enable special attack.\n    primeActionName: STR_PRIME_GRENADE                #string id of grenade prime action name in the pop-up menu. Required to enable prime action. Defulat value `STR_PRIME_GRENADE`;\n    primeActionMessage: STR_GRENADE_IS_ACTIVATED      #string id of grenade prime action message.\n    unprimeActionName: ~                              #string id of grenade unprime action name in the pop-up menu. Required to enable unprime action.\n    unprimeActionMessage: STR_GRENADE_IS_DEACTIVATED  #string id of grenade unprime action message.\n    psiRequired: false    #default based on weapon type, if `true` you need Psi Skill to use the weapon.\n    moraleRecovery: 10    #amount of recovered morale by medkit. Defailt `0`.\n    painKillerRecovery: 0 #how much missing health convert to morale. Default `1.0`.\n    allowSelfHeal: true   #can medikit target user.\n    medikitType: 0        #change how medikit wroks, `0` default with UI, `1` fast heal, `2` fast stimulant, `3` fast pain killer.\n    isConsumable: false   #check if medikit is consumable or primed granade not recoverable.\n    isExplodingInHands: false #item if primed will explode in hand, default is `fase`.\n    defaultInventorySlot: ~   #where place fixed weapon.\n    blockBothHands: false #do item require both hands to use?\n    fixedWeaponShow: true #if it's true then it will show fixed weapon on unit.\n    hitMissSound: 0       #override `hitSound` when any psi attack was unsuccessful.\n    meleeMissSound: 12    #override `meleeSound` when melee attack was unsuccessful.\n    psiSound: 0           #override `hitSound` when used for MC or Panic attack.\n    psiMissSound: 0       #override `hitMissSound` when used for MC or Panic attack.\n    hitMissAnimation: 0   #override `hitAnimation` when special psi attack was unsuccessful. Use `SMOKE.PCK`.\n    meleeMissAnimation: 0 #override `meleeMissAnimation` when melee, MC or Panic attack was unsuccessful. Use `HIT.PCK`.\n    psiAnimation: 0       #override `meleeAnimation` when used for MC or Panic attack. Use `HIT.PCK`.\n    psiMissAnimation: 0   #override `meleeMissAnimation` when MC or Panic attack was unsuccessful. Use `HIT.PCK`.\n    explosionHitSound: 2  #override default big explosion sound.\n    tags:\n      SOME_CUSTOM_TAG: 4  #user defined values used by script.\n    scripts:\n      recolorItemSprite: ~      #script that handle recoloring of each pixel in item sprite.\n      selectItemSprite: ~       #script that handle selecting graphic for item.\n      reactionWeaponAction: ~   #script that handle reacion to shoot, throw or melee from that weapon.\n      createItem: ~             #script call on creation of new item in battlespace.\n      newTurnItem: ~            #script call on each turn for all items in battlescape.\n      awardExperience: ~        #script that handle experiance grain from hiting unit.\n    ai:\n      useDelay: 3       #determine on what turn item can be used by aliens.\n      meleeHitCount: 25 #number of hits that AI try to do.\n[/code]\n\n[code]\narmors:\n  - type: STR_ARMOR_TYPE #default config ...\n    fearImmune: false    #default true for big units.\n    bleedImmune: false   #default true for big units.\n    painImmune: false    #default true for big units.\n    zombiImmune: false   #ignored by big units.\n    overKill: 0.8        #when damage drops HPs to negative value greater than `overKill * maxHP` then the corpse is destroyed, default value is 0.50.\n    visibilityAtDay: 20  #default 20 for all.\n    visibilityAtDark: 9  #default 20 for aliens, 9 for humans.\n    personalLight: 15    #solder light radius.\n    specialWeapon: ALIEN_PSI_WEAPON #alien psi or melee attack.\n    builtInWeapons: #same as for units.\n      - STR_SOME_WEAPON\n    psiDefence: #used when attacked by psi-amp.\n      #default is `psiStrength` set to `1.0` and `psiSkill` set to `0.2`.\n      #...\n      #same stats like `damageBonus` in `items`.\n      #...\n    meleeDodge: #used when attacked by melee hit.\n      #default is `0.0`.\n      #...\n      #same stats like `damageBonus` in `items`.\n      #...\n    meleeDodgeBackPenalty: 0.2 #how much dodge unit lost when hit from behind. Default `0.0`.\n    recovery:\n      time: #amount of TU recovered each turn.\n        #default is `tu` set to `1.0`\n        #...\n        #same stats like `damageBonus` in `items`.\n        #...\n      energy: #amount of Energy recovered each turn.\n        #default is `energyRegen` set to `1.0`\n        #...\n        #same stats like `damageBonus` in `items`.\n        #...\n        energyRegen: 1.0 #special stat returning vanilia energy regen.\n      morale: #amount of Morale recovered each turn.\n        #default is `0.0`.\n        #...\n        #same stats like `damageBonus` in `items`.\n        #...\n      health: #amount of Health recovered each turn.\n        #default is `0.0`.\n        #...\n        #same stats like `damageBonus` in `items`.\n        #...\n      stun: #amount of Stun recovered each turn.\n        #default is `flatOne` set to `1.0`.\n        #...\n        #same stats like `damageBonus` in `items`.\n        #...\n    tags:\n      IS_THIS_NINJA: 1        #user defined values used by script.\n    scripts:\n      recolorUnitSprite: ~    #recolor script call for each pixel in unit sprite, used for corpse sprite too.\n      selectUnitSprite: ~     #sprite select script call for each body part.\n      reactionUnitAction: ~   #script used for handling reaction for unit performing action.\n      reactionUnitReaction: ~ #script used for handling reaction for unit reacting.\n      visibilityUnit: ~       #script that handle visibility test of other units, return value need be greater than zero to test be succesful. Second return value is used for distinguish between custom visibility modes, `null` is normal visibility.\n      hitUnit: ~              #script call when unit get hit by something, called before armor handling.\n      damageUnit: ~           #script call after armor handling, it handle damage to unit.\n      createUnit: ~           #script call on creation of new unit in battlescape.\n      newTurnUnit: ~          #script call on every turn for every unit in battlescape.\n[/code]\n\n[code]\nsoldiers:\n  - type: STR_SOLDIER_A\n    requiresBuyBaseFunc:  #list of required base functions needed to buy this.\n      - SOME_BASE_FUNC_A\n[/code]\n\n[code]\ncrafts:\n  - type: STR_CRAFT_TYPE  #default config ...\n    requiresBuyBaseFunc:  #list of required base functions needed to buy this.\n      - SOME_BASE_FUNC_A\n    radarRange: 672     #craft radar range. Default `672`.\n    radarChance: 100    #craft radar dedection chance. Default `100`.\n    sightRange: 1696    #alien base dedection range. Default `1696`.\n    weapons: 4          #weapon number increased to 4.\n    weaponTypes:        #definition of allowed weapon types in craft. Max 4 different types per slot.\n      - 0               #slot 1 accepts weapons with type 0. This is default.\n      - 0               #slot 2 accepts weapons with type 0.\n      - [0, 4, 13]      #slot 3 accepts weapons with type 0, 4 and 13.\n      - 1               #slot 4 accepts weapons with type 1.\n    weaponStrings:      #string ID used by geoscape craft status.\n      - STR_WEAPON_ONE\n      - STR_WEAPON_TWO\n      - STR_WEAPON_THREE\n      - STR_WEAPON_FOURTH\n    hitBonus: 0         #bonus percentage to all weapons hit chance. Range [0, 100].\n    avoidBonus: 0       #bonus percentage to craft dodge chance. Range [0, 100].\n    powerBonus: 0       #bonus percentage to all weapons damage. Range [0, 100].\n    armor: 0            #amount of blocked damage per hit.\n[/code]\n\n[code]\ncraftWeapons:\n  - type: STR_CRAFTWEAPON_TYPE #default config ...\n    weaponType: 1 #default value 0.\n    stats: #added to craft's stats.\n      fuelMax: 0     #additive bonus to craft stats.\n      damageMax: 0   #additive bonus to craft stats.\n      speedMax: 0    #additive bonus to craft stats.\n      accel: 0       #additive bonus to craft stats.\n      radarRange: 0  #additive bonus to craft stats.\n      radarChance: 0 #additive bonus to craft stats.\n      sightRange: 0  #additive bonus to craft stats.\n      hitBonus: 0    #bonus percentage to all weapons hit chance. Range [0, 100].\n      avoidBonus: 0  #bonus percentage to craft dodge chance. Range [0, 100].\n      powerBonus: 0  #bonus percentage to all weapons damage. Range [0, 100].\n      armor: 0       #amount of blocked damage per hit.\n[/code]\n\n[code]\nufos:\n  - type: STR_UFO_TYPE #default config ...\n    sightRange: 268 #xcom base dedection range. Default `268`.\n    hitBonus: 0     #bonus percentage to all weapons hit chance. Range [0, 100].\n    avoidBonus: 0   #bonus percentage to UFO dodge chance. Range [0, 100].\n    powerBonus: 0   #bonus percentage to all weapons damage. Range [0, 100].\n    armor: 0        #amount of blocked damage per hit.\n    craftCustomDeploy: STR_BATTLESHIP_1 #override craft default weapon deploy.\n    missionCustomDeploy: STR_TERROR_MISSION_2 #override mission defulat weapon deploy.\n    raceBonus: #bonus stats per race.\n      STR_SECTOID: #name of race that bonus apply.\n        damageMax: 0  #additive bonus to craft stats.\n        speedMax: 0   #additive bonus to craft stats.\n        accel: 0      #additive bonus to craft stats.\n        sightRange: 0 #additive bonus to craft stats.\n        hitBonus: 0   #bonus percentage to all weapon hit chance. Range [0, 100].\n        avoidBonus: 0 #bonus percentage to craft avoid chance. Range [0, 100].\n        powerBonus: 0 #bonus percentage to all weapon damage. Range [0, 100].\n        armor: 0      #amount of blocked damage per hit.\n        craftCustomDeploy: STR_BATTLESHIP_3 #override craft default weapon deploy.\n        missionCustomDeploy: STR_TERROR_MISSION_2 #override mission defulat weapon deploy.\n[/code]\n\n[code]\nalienRaces:\n  - id: STR_SECTOID\n    retaliationMission: STR_ALIEN_RETALIATION   #default mission spawn after destroing ufo.\n    retaliationAggression: 0                    #chance modiffer to spawn retaliation mission.\n    baseCustomDeploy: STR_ALIEN_BASE_ASSAULT_2  #override alien base default weapon depoly.\n    baseCustomMission: STR_MIB_BASE             #override alien base construction.\n[/code]\n\n[code]\nalienDeployments:\n  - id: STR_SOMETHING\n    startingCondition:      #from OXCE+\n[/code]\n\n[code]\nitemCategories:             #from OXCE+\n  - type:\n    replaceBy:\n    hidden:\n    listOrder:\n[/code]\n\n[code]\nstartingConditions:         #from OXCE+\n  - type:\n    armorTransformations:\n    defaultArmor:\n    defaultItems:\n    allowedArmors:\n    allowedVehicles:\n    allowedItems:\n    allowedItemCategories:\n    allowedCraft:\n[/code]\n\n[code]\nfacilities:\n  - type: STR_SOME_FACILITY\n    buildCostItems:\n      STR_ITEM:\n        build: 10           #how many items of type `STR_ITEM` are require to build.\n        refund: 6           #how many items are returned when facility is dismantled.\n    provideBaseFunc: [ A ]  #List of custom IDs that this bulding provide for base.\n    requiresBaseFunc: [ ]   #List of custom IDs that are require to build this building in base.\n    forbidenBaseFunc: [ B ] #List of custom IDs that are forbiden by this building.\n    trainingRooms: 0        #Number of solder that can be train in that building, require langue strings.\n    refundValue: 0          #how much mony is returned when facility is dismantled.\n[/code]\n\n[code]\nmanufacture:\n  - type: STR_SOME_MANUFACTURE\n    requiresBaseFunc: [ A, C ] #List of custom IDs that are require to start production in base.\n[/code]\n\n[code]\nresearch:\n  - type: STR_SOME_RESEARCH\n    requiresBaseFunc: [ W, K ] #List of custom IDs that are required to start this research in the base.\n[/code]\n\n[code]\nterrains:\n  - name: CULTA\n    mapBlocks:\n      - name: SOMETHING\n        fuseTimers:\n          STR_GRANADE: [6, 16]  #all items of that type will have set fuseTimer to random value in range [6, 16].\n[/code]\n\n[code]\nlighting:\n  enhanced: 7     #flags for lighting system, final value = (`1` if enabled for tiles and fire) + (`2` if enabled for items) + (`4` if enabled for units). Default value `7`.\n  maxStatic: 20   #max range of fire and tile light radius. Affect overall game performace! Default `16`.\n  maxDynamic: 30  #max range of unit and item light radius. Affect overall game performace! Defulat `24`.\n[/code]\n\n[code]\nmapScripts:\n  - type: CULTA\n    commands:\n    - type: addBlock\n      blocks: [1, 2, 3] \n      terrain: FOREST #Add map 1, 2, or 3 from terrain FOREST\n    - type: addLine\n      direction: vertical\n      rects:\n        - [1, 1, 4, 1]\n      terrain: URBAN #Add a road from terrain URBAN\n    - type: addUFO\n      terrain: MOUNT #UFO's LZ block will be from terrain MOUNT\n    - type: addCraft\n      terrain: JUNGLE #Player craft's LZ block will be from terrain JUNGLE\n    - type: fillArea\n      terrain: DESERT #Fill the rest of the map with map blocks from terrain DESERT\n  - type: URBAN\n    commands:\n    - type: addBlock\n      size: [2, 2, 4] # When using verticalLevels, definition of height is necessary\n      verticalLevels: # This block will be a series of maps stacked on top of each other, chosen randomly as with normal addBlock command\n      - type: ground # \"ground\" type maps are always placed first\n        groups: 6 # Pick the first block from group 6\n        size: [2, 2, 1] # Size in x and y must match the size of the block, vertical size definition is necessary for command to run properly\n      - type: middle # \"middle\" types are filler between \"ground\" and \"ceiling,\" a list of all middle types is created to loop over to fill the vertical distance\n        groups: 7 # Pick a middle floor for this block from group 7\n        terrain: SOME_ALTERNATE_URBAN # It's possible to make each section a different terrain\n        size: [2, 2, 1]\n      - type: middle # This one is placed after the previous one, the command alternates back and forth between this and the previous to fill the size in z\n        blocks: [13, 14, 15]\n        size: [2, 2, 1]\n      - type: ceiling # Placed on top of all the other blocks\n        groups: 9\n        size: [2, 2, 1]\n[/code]\n\n[code]\nglobe:\n  textures:\n    - id: 0\n      baseTerrain: CULTA #If baseDefenseMapFromLocation is equal to one, this terrain can be used in conjunction with addBlockFromTerrain and fillAreaFrom terrain to populate empty squares on base defense maps\n[/code]\n\n[code]\nbaseDefenseMapFromLocation: 1 #If equal to one, the RNG will be seeded by the base's location when generating the map and returned to it's original value after\n[/code]\n\n[code]\nai:\n  useDelayBlaster: 3\n  useDelayFirearm: 0\n  useDelayGrenade: 3\n  useDelayMelee: 0\n  useDelayPsionic: 0\n[/code]\n\n[code]\nextended:\n  tags:                     #definitions of user defined values used by script.\n    RuleItem:               #used by `items` nodes.\n      SOME_CUSTOM_TAG: int\n      #avaiable types:\n      #`int` - natural number\n      #`RuleList` - name of other mod that is loaded. Accessed as id number in script. Have value -1 if mod with that name do not exists.\n    RuleArmor:              #used by `armors` nodes.\n      IS_THIS_NINJA: int\n  scripts:\n    reactionUnitAction:     #name of script that have enabled global events.\n      - offset: 1.2         #order in witch each global event is run.\n        code: |             #script that will be called by event.\n          #some code\n          return 100;\n[/code]\n\n[code]\nextraStrings:\n  - type: en-US\n    strings:\n      STR_NOT_ENOUGH_ITEMS: \"Lack of {0} {1} items\"   #required when using `buildCostItems` in `facilities`. `{0}` is name of item, `{1}` is number of item we don't have.\n      STR_PHYSICAL_TRAINING: \"Physical Training\"      #required when using `trainingRooms` in `facilities`.\n      STR_TRAINING: \"Training\"                        #required when using `trainingRooms` in `facilities`.\n      STR_REMAINING_TRAINING_FACILITY_CAPACITY: \"REMAINING TRAINING CAPACITY> {ALT}{0}\" #required when using `trainingRooms` in `facilities`.\n      STR_NOT_ENOUGH_MORALE: \"You lack discipline!\"   #required when using item morale use cost.\n      STR_NOT_ENOUGH_HEALTH: \"Not enough blood!\"      #required when using item health use cost.\n      STR_NOT_ENOUGH_STUN: \"Too much pain!\"           #required when using item stun use cost.\n      STR_NO_USES_LEFT: \"You can't use medi-kit\"      #required when using `medikitType`.\n      STR_NOT_ENOUGH_CRAFT_SPACE: \"You can't fit it!\" #required when you try change armor with 2x2 size and craft don't have space.\n[/code]\n\nExamples of script usage:\n\n\n[code]\n#special statements\nsomeScriptCode: |\n  var int temp;     #define variable of type `int` with name `temp`.\n  var int zero 42;  #new variable with begining value of 42.\n\n  if OPERATION A B; #`OPERATION` can be: `lt` - less, `le` - less equal, `gt` - greater, `ge` - greater equal, `eq` - equal, `neq` - not equal\n    #some code 1\n  else OPERATION A B; #`else` can have same condition as first `if`.\n    #some code 2\n  else OPERATION A B; #you can repeat `else` with test multiple times.\n    #some code 3\n  else;\n    #final case, can be skipped.\n  end;\n\n  if or lt A B eq C D;\n    #you can write multiple operation with `or`.\n    #result will be true if any of this operation would return true.\n  end;\n  if and gt A B neq C D le E F;\n    #same for `and` but in this case all operation need be true.\n  end;\n\n  return B; #exit script with value of `B`.\n[/code]\n\n[code]\nextended:\n  tags:\n    RuleArmor:\n      CORPSE_SWITCH_ENABLED: int\n      CORPSE_SWITCH_RESOURCES_MOD: RuleList\n      CORPSE_SWITCH_SPRITE_FLOOR_STUN: int\n      CORPSE_SWITCH_SPRITE_FLOOR_WOUND: int\n      CORPSE_SWITCH_SPRITE_FLOOR_DEAD: int\n      CORPSE_SWITCH_SPRITE_BIG_STUN: int\n      CORPSE_SWITCH_SPRITE_BIG_WOUND: int\n      CORPSE_SWITCH_SPRITE_BIG_DEAD: int\n  scripts:\n    selectItemSprite:\n      - offset: 1\n        code: |\n          #custom corpse graphic based on state of unit.\n          var int curr_hp;\n          var int curr_wounds;\n          var int temp;\n          var ptr BattleUnit unit;\n          var ptr RuleArmor armor;\n          \n          item.getBattleUnit unit;\n          unit.getRuleArmor armor;\n          if neq armor null;\n            unit.getHealth curr_hp;\n            unit.getFatalwoundsTotal curr_wounds;\n            armor.getTag temp Tag.CORPSE_SWITCH_ENABLED;\n            if eq temp 1;\n              armor.getTag temp Tag.CORPSE_SWITCH_RESOURCES_MOD;\n              if eq blit_part blit_item_floor;\n                if le curr_hp 0;\n                  armor.getTag sprite_index Tag.CORPSE_SWITCH_SPRITE_FLOOR_DEAD;\n                else gt curr_wounds 0;\n                  armor.getTag sprite_index Tag.CORPSE_SWITCH_SPRITE_FLOOR_WOUND;\n                else;\n                  armor.getTag sprite_index Tag.CORPSE_SWITCH_SPRITE_FLOOR_STUN;\n                end;\n                rules.getSpriteOffsetFloorob sprite_index temp;\n                return sprite_index;\n              else eq blit_part blit_item_big;\n                if le curr_hp 0;\n                  armor.getTag sprite_index Tag.CORPSE_SWITCH_SPRITE_BIG_DEAD;\n                else gt curr_wounds 0;\n                  armor.getTag sprite_index Tag.CORPSE_SWITCH_SPRITE_BIG_WOUND;\n                else;\n                  armor.getTag sprite_index Tag.CORPSE_SWITCH_SPRITE_BIG_STUN;\n                end;\n                rules.getSpriteOffsetBigobs sprite_index temp;\n                return sprite_index;\n              end;\n            end;\n          end;\n          return sprite_index;\n#enabling this functionality for unit\narmors:\n  - type: STR_NONE_UC\n    tags:\n      CORPSE_SWITCH_ENABLED: 1 #1 enable this functionality for this unit, 0 disable\n      CORPSE_SWITCH_RESOURCES_MOD: current #to what mod sprites belongs to, `current` mean this mod.\n      CORPSE_SWITCH_SPRITE_FLOOR_STUN: 32\n      CORPSE_SWITCH_SPRITE_FLOOR_WOUND: 33\n      CORPSE_SWITCH_SPRITE_FLOOR_DEAD: 34\n      CORPSE_SWITCH_SPRITE_BIG_STUN: 42\n      CORPSE_SWITCH_SPRITE_BIG_WOUND: 43\n      CORPSE_SWITCH_SPRITE_BIG_DEAD: 44\n[/code]\n\n[code]\narmors:\n  - type: PARROT_ARMOR\n    drawingRoutine: 4\n    scripts:\n      selectUnitSprite: |\n        #this script will always run move animation of unit.\n        var int temp;\n        var int walking;\n        unit.isWalking walking;\n        if eq walking 0;\n          unit.getId temp;\n          offsetmod temp 11 0 8; #desync animation of different units\n          add temp anim_frame;\n          wavegen_saw temp 8 8 7;\n          mul sprite_offset 8;\n          add sprite_offset 8;\n          add sprite_offset temp;\n          set sprite_index sprite_offset;\n        else;\n          add sprite_index sprite_offset;\n        end;\n        return sprite_index;\n[/code]\n\n[/examples]\n\n[br/][br/]\n[i]Links[/i]\n\nCurrent working branch:[br/]\nhttps://github.com/Yankes/OpenXcom/tree/OpenXcomExtended[br/]\n[br/]\nDownload available on mod site (require latest nightly):[br/]\nhttp://www.openxcom.com/mod/openxcom-extended[br/]\n[br/]\nBackup:[br/]\nhttps://www.mediafire.com/folder/w07p0ibc985kd/OXCE[br/]\n[br/]\nForum thread:[br/]\nhttp://openxcom.org/forum/index.php?topic=2915.msg31641#msg31641[br/]\n\n[br/]\n[br/]\n[i]Credits[/i]\n\nMeridian for OXCE+ :)[br/]\nstiansel for FOV speedup.[br/]\nredv & WarBoy1982 for a couple of commits.[br/]\nSolarusScorch for fixing language in readme.[br/]\nSupSuper & WarBoy1982 & Daiky for OpenXcom :)[br/]\n"
  },
  {
    "path": "LICENSE.txt",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<http://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<http://www.gnu.org/philosophy/why-not-lgpl.html>."
  },
  {
    "path": "README-macOS.md",
    "content": "# Building for MacOS\n\n## Dependencies\n\nTo successfully build an OpenXcom macOS bundle you will need relevant dependencies installed:\n\nThe dependencies you require are following:\n- cmake, version 3.12.0 or later\n- SDL (libsdl1.2)\n- SDL_mixer (libsdl-mixer1.2)\n- SDL_gfx (libsdl-gfx1.2), version 2.0.22 or later\n- SDL_image (libsdl-image1.2)\n\nCMake is used to configure the project. Download it [manually](https://cmake.org/download/) or install it with [Homebrew](https://brew.sh) (`brew install cmake`).\n\nThe easiest way of getting library dependencies is [MacPorts](https://www.macports.org/):\n```sh\nport -N install libsdl -compat +legacy libsdl_gfx libsdl_image libsdl_mixer\n```\n\nFollowing instructions assume MacPorts is installed in default prefix `/opt/local`. If you installed ports into different location, replace it.\n\n## Building\nThis project has two ways to build: one with make and the other with Xcode.  The make way is typically used for CI builds and produces a similar artifact as the Linux build.  If you're just looking to get a quick build, this is a good way to do so.  The Xcode way is useful if you're developing features (or bug fixes) and require the need for a debugger or an IDE experience.\n\n### Make\n1. In the root of the repository, generate the Makefile with cmake (Release is also a valid build type):\n    ```\n    cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_PREFIX_PATH=/opt/local -B build .\n    ```\n1. Copy the vanilla game assets (UFO/TFTD) into the build's `bin/` directory. If the game is next to the repo, cd into game and run:\n    ```sh\n    cp  -r GEODATA GEOGRAPH MAPS ROUTES SOUND TERRAIN UFOGRAPH UFOINTRO* UNITS ../OpenXcom/bin/UFO/\n    ```\n1. Build the project (2 being the number of threads to run):\n    ```sh\n    cmake --build build -j2\n    ```\n1. Make sure that you set up your [Data directory](https://github.com/OpenXcom/OpenXcom#directory-locations) properly.\n1. Your artifact will be named `openxcom.app` in the build target directory.\n\n\n### Xcode\n1. In the root of the repository, generate the XCode project file with cmake (Release is also a valid build type):\n    ```sh\n    cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_PREFIX_PATH=/opt/local -G Xcode -B build .\n    ```\n1. Open the `OpenXcom.xcodeproj` in Xcode.\n1. Copy the vanilla game assets (UFO/TFTD) into the build's `bin/` directory.\n1. Build with cmd-B\n1. Your artifact will be named `openxcom.app` in the build target directory (Debug or Release).\n\n## Additional Help\nShould you require any further assistance regarding the macOS build - feel free to ask around on the official forums - https://openxcom.org/forum/ or contact us directly on GitHub - [@rcreasey](http://github.com/rcreasey)\n"
  },
  {
    "path": "README.md",
    "content": "# OpenXcom [![Workflow Status][workflow-badge]][actions-url]\n\n[workflow-badge]: https://github.com/OpenXcom/OpenXcom/workflows/ci/badge.svg\n[actions-url]: https://github.com/OpenXcom/OpenXcom/actions\n\nOpenXcom is an open-source clone of the popular \"UFO: Enemy Unknown\" (\"X-COM:\nUFO Defense\" in the USA release) and \"X-COM: Terror From the Deep\" videogames\nby Microprose, licensed under the GPL and written in C++ / SDL.\n\nSee more info at the [website](https://openxcom.org)\nand the [wiki](https://www.ufopaedia.org/index.php/OpenXcom).\n\nUses modified code from SDL\\_gfx (LGPL) with permission from author.\n\n## Installation\n\nOpenXcom requires a vanilla copy of the X-COM resources -- from either or both\nof the original games.  If you own the games on Steam, the Windows installer\nwill automatically detect it and copy the resources over for you.\n\nIf you want to copy things over manually, you can find the Steam game folders\nat:\n\n    UFO: \"Steam\\SteamApps\\common\\XCom UFO Defense\\XCOM\"\n    TFTD: \"Steam\\SteamApps\\common\\X-COM Terror from the Deep\\TFD\"\n\nDo not use modded versions (e.g. with XcomUtil) as they may cause bugs and\ncrashes.  Copy the UFO subfolders to the UFO subdirectory in OpenXcom's data\nor user folder and/or the TFTD subfolders to the TFTD subdirectory in OpenXcom's\ndata or user folder (see below for folder locations).\n\n## Mods\n\nMods are an important and exciting part of the game.  OpenXcom comes with a set\nof standard mods based on traditional XcomUtil and UFOExtender functionality.\nThere is also a [mod portal website](https://openxcom.mod.io/) with a thriving\nmod community with hundreds of innovative mods to choose from.\n\nTo install a mod, go to the mods subdirectory in your user directory (see below\nfor folder locations).  Extract the mod into a new subdirectory.  WinZip has an\n\"Extract to\" option that creates a directory whose name is based on the archive\nname.  It doesn't really matter what the directory name is as long as it is\nunique.  Some mods are packed with extra directories at the top, so you may\nneed to move files around inside the new mod directory to get things straighted\nout.  For example, if you extract a mod to mods/LulzMod and you see something\nlike:\n\n    mods/LulzMod/data/TERRAIN/\n    mods/LulzMod/data/Rulesets/\n\nand so on, just move everything up a level so it looks like:\n\n    mods/LulzMod/TERRAIN/\n    mods/LulzMod/Rulesets/\n\nand you're good to go!  Enable your new mod on the Options -> Mods page in-game.\n\n## Directory Locations\n\nOpenXcom has three directory locations that it searches for user and game files:\n\n<table>\n  <tr>\n    <th>Folder Type</th>\n    <th>Folder Contents</th>\n  </tr>\n  <tr>\n    <td>user</td>\n    <td>mods, savegames, screenshots</td>\n  </tr>\n  <tr>\n    <td>config</td>\n    <td>game configuration</td>\n  </tr>\n  <tr>\n    <td>data</td>\n    <td>UFO and TFTD data files, standard mods, common resources</td>\n  </tr>\n</table>\n\nEach of these default to different paths on different operating systems (shown\nbelow).  For the user and config directories, OpenXcom will search a list of\ndirectories and use the first one that already exists.  If none exist, it will\ncreate a directory and use that.  When searching for files in the data\ndirectory, OpenXcom will search through all of the named directories, so some\nfiles can be installed in one directory and others in another.  This gives\nyou some flexibility in case you can't copy UFO or TFTD resource files to some\nsystem locations.  You can also specify your own path for each of these by\npassing a commandline argument when running OpenXcom.  For example:\n\n    openxcom -data \"$HOME/bin/OpenXcom/usr/share/openxcom\"\n\nor, if you have a fully self-contained installation:\n\n    openxcom -data \"$HOME/games/openxcom/data\" -user \"$HOME/games/openxcom/user\" -config \"$HOME/games/openxcom/config\"\n\n### Windows\n\nUser and Config folder:\n- C:\\Documents and Settings\\\\\\<user\\>\\My Documents\\OpenXcom (Windows 2000/XP)\n- C:\\Users\\\\\\<user\\>\\Documents\\OpenXcom (Windows Vista/7)\n- \\<game directory\\>\\user\n- .\\user\n\nData folders:\n- C:\\Documents and Settings\\\\\\<user\\>\\My Documents\\OpenXcom\\data (Windows 2000/XP)\n- DATADIR build flag\n- C:\\Users\\\\\\<user\\>\\Documents\\OpenXcom\\data (Windows Vista/7/8)\n- \\<game directory\\>\n- . (the current directory)\n\n### Mac OS X\n\nUser and Config folder:\n- $XDG\\_DATA\\_HOME/openxcom (if $XDG\\_DATA\\_HOME is defined)\n- $HOME/Library/Application Support/OpenXcom\n- $HOME/.openxcom\n- ./user\n\nData folders:\n- $XDG\\_DATA\\_HOME/openxcom (if $XDG\\_DATA\\_HOME is defined)\n- $HOME/Library/Application Support/OpenXcom (if $XDG\\_DATA\\_HOME is not defined)\n- DATADIR build flag\n- $XDG\\_DATA\\_DIRS/openxcom (for each directory in $XDG\\_DATA\\_DIRS if $XDG\\_DATA\\_DIRS is defined)\n- /Users/Shared/OpenXcom (if $XDG\\_DATA\\_DIRS is not defined or is empty)\n- . (the current directory)\n\n### Linux\n\nUser folder:\n- $XDG\\_DATA\\_HOME/openxcom (if $XDG\\_DATA\\_HOME is defined)\n- $HOME/.local/share/openxcom (if $XDG\\_DATA\\_HOME is not defined)\n- $HOME/.openxcom\n- ./user\n\nConfig folder:\n- $XDG\\_CONFIG\\_HOME/openxcom (if $XDG\\_CONFIG\\_HOME is defined)\n- $HOME/.config/openxcom (if $XDG\\_CONFIG\\_HOME is not defined)\n\nData folders:\n- $XDG\\_DATA\\_HOME/openxcom (if $XDG\\_DATA\\_HOME is defined)\n- $HOME/.local/share/openxcom (if $XDG\\_DATA\\_HOME is not defined)\n- DATADIR build flag\n- $XDG\\_DATA\\_DIRS/openxcom (for each directory in $XDG\\_DATA\\_DIRS if $XDG\\_DATA\\_DIRS is defined)\n- /usr/local/share/openxcom (if $XDG\\_DATA\\_DIRS is not defined or is empty)\n- /usr/share/openxcom (if $XDG\\_DATA\\_DIRS is not defined or is empty)\n- the directory data files were installed to\n- . (the current directory)\n\n## Configuration\n\nOpenXcom has a variety of game settings and extras that can be customized, both\nin-game and out-game. These options are global and affect any old or new\nsavegame.\n\nFor more details please check the [wiki](https://ufopaedia.org/index.php/Options_(OpenXcom)).\n\n## Development\n\nOpenXcom requires the following developer libraries:\n\n- [SDL](https://www.libsdl.org) (libsdl1.2)\n- [SDL\\_mixer](https://www.libsdl.org/projects/SDL_mixer/) (libsdl-mixer1.2)\n- [SDL\\_gfx](https://www.ferzkopp.net/wordpress/2016/01/02/sdl_gfx-sdl2_gfx/) (libsdl-gfx1.2), version 2.0.22 or later\n- [SDL\\_image](https://www.libsdl.org/projects/SDL_image/) (libsdl-image1.2)\n\nThe source code includes files for the following build tools:\n\n- Microsoft Visual C++ 2010 or newer\n- Xcode\n- Make (see Makefile.simple)\n- CMake\n\nIt's also been tested on a variety of other tools on Windows/Mac/Linux. More\ndetailed compiling instructions are available at the\n[wiki](https://ufopaedia.org/index.php/Compiling_(OpenXcom)), along with\npre-compiled dependency packages.\n"
  },
  {
    "path": "bin/common/Language/Android/cs.yml",
    "content": "cs:\n  STR_SYSTEM: \"SYSTÉM\"\n  STR_CONTROLS_LABEL: \"Upravit ovládání\"\n  STR_RECONFIGURE_DIRS: \"Nastavit složky hry\"\n  STR_RECONFIGURE_DIRS_BTN: \"Nastavit složky\"\n  STR_LOG_FILE: \"Soubor\"\n  STR_LOG_TOUCH_EVENTS: \"Loguj dotyky\"\n  STR_FAKE_EVENTS: \"Falešné události\"\n  STR_FORCE_GL_MODE: \"Vynuť GL mod\"\n  STR_FORCE_GL_MODE_DESC: \"Vynutí formát textur RGB565. Použij, pokud máš obrazovku načervenalou. Projeví se po restartu.\"\n  STR_MOUSE_MODE: \"Mód myši\"\n  STR_MOUSE_BASIC: \"Základní\"\n  STR_MOUSE_EXTENDED: \"Rozšířený\"\n  STR_LISTDRAGSCROLL: \"Listování přetáhnutím\"\n  STR_DRAGREORDER: \"Tahem přeřadíte vojáky\"\n  STR_DRAGREORDER_DESC: \"Přetáhnutím vojáky seřazujete na obrazovce vybavení letadla\"\n  STR_SHOW_CURSOR: \"Zobraz kurzor\"\n"
  },
  {
    "path": "bin/common/Language/Android/de.yml",
    "content": "de:\n  STR_SYSTEM: \"SYSTEM\"\n  STR_SWIPE: \"Wischen zum Drehen\"\n  STR_HOLD: \"Halten zum Drehen\"\n  STR_SWIPE_DESC: \"Wische in die Richtung, in die der Soldat gehen soll.\"\n  STR_HOLD_DESC: \"Tippen und halten Sie in die Richtung, in die Ihr Soldat zeigen soll.\"\n  STR_SYSTEM_UI: \"Android Nutzeroberfläche Anzeigemodus\"\n  STR_SYSTEM_UI_DESC: \"Ändert den Anzeigemodus der Android-Navigationsleiste\"\n  STR_ALWAYS_SHOWN: \"Immer anzeigen\"\n  STR_LOW_PROFILE: \"Geringes Profil\"\n  STR_IMMERSIVE: \"Immersiver Modus\"\n  STR_CONTROLS_LABEL: \"Bearbeite Steuerung\"\n  STR_RECONFIGURE_DIRS: \"Bestimme Spiel-Ordner\"\n  STR_RECONFIGURE_DIRS_BTN: \"Bestimme Ordner\"\n  STR_LOG_DESTINATION: \"Protokollieren nach\"\n  STR_LOG_FILE: \"Datei\"\n  STR_LOG_FILE_DESC: \"Schicke dein Log zu openxcom.log Kann zu starken Performanceproblemen führen!\"\n  STR_LOG_SYSTEM: \"Logcat\"\n  STR_LOG_SYSTEM_DESC: \"Protokoll in das Android-Systemprotokoll schreiben. Die Deaktivierung dieser Option kann die Leistung ein wenig erhöhen, verhindert aber, dass nützliche Meldungen im Protokoll erscheinen.\"\n  STR_DEBUG_OPTIONS: \"Debug Optionen\"\n  STR_LOG_TOUCH_EVENTS: \"Berührungsereignisse\"\n  STR_LOG_TOUCH_EVENTS_DESC: \"Protokolliert alle Berührungsereignisse. Dies wird die Leistung erheblich verringern, sollte aber für die Fehlersuche nützlich sein.\"\n  STR_FAKE_EVENTS: \"Falsche Events\"\n  STR_FAKE_EVENTS_DESC: \"Sendet vorgetäuschte Finger-Up-Touch-Ereignisse. Benutzen Sie diese Funktion, wenn Tasten eingefroren sind.\"\n  STR_FORCE_GL_MODE: \"Erzwungener GL Modus\"\n  STR_FORCE_GL_MODE_DESC: \"Zwings die Texturen in ein RGB565 Format. Nutze diese Einstellung wenn du rote Flecken auf dem Bildschirm hast. Wird erst nach einem Neustart angewendet.\"\n  STR_MOUSE_MODE: \"Mausmodus\"\n  STR_MOUSE_BASIC: \"Standard\"\n  STR_MOUSE_EXTENDED: \"Erweitert\"\n  STR_MOUSE_MODE_DESC: \"Der erweiterte Modus ermöglicht native Mausereignisse und bietet ein desktopähnliches Erlebnis.\"\n  STR_LISTDRAGSCROLL: \"Ziehen und Scrollen der Liste\"\n  STR_LISTDRAGSCROLL_DESC: \"Aktiviere Drag-Scrolling für scrollbare Listen. Nützlich für Touchscreen basierende Geräte\"\n  STR_DRAGREORDER: \"Ziehen um Soldaten neu zu Ordnen\"\n  STR_DRAGREORDER_DESC: \"Ziehen um Soldaten im Ausrüstungsbildschirm neu zu Ordnen\"\n  STR_SHOW_CURSOR: \"Zeige Cursor\"\n  STR_SHOW_CURSOR_DESC: \"Ziehe den gelben Cursor Pfeil. Nützlich mit einer Maus\"\n  STR_FRAMESKIP: \"Maximal übersprungene Frames\"\n  STR_FRAMESKIP_DESC: \"Dies ist die maximale Zahl an Frames, die übersprungen werden können. Bedingt durch den Codes während des Spiels.\"\n"
  },
  {
    "path": "bin/common/Language/Android/el.yml",
    "content": "el:\n  STR_SYSTEM: \"ΣΥΣΤΗΜΑ\"\n  STR_SWIPE: \"Σύρετε για στροφή\"\n  STR_HOLD: \"Κρατήστε για στροφή\"\n  STR_SWIPE_DESC: \"Σύρε από έναν στρατιώτη προς την κατεύθυνση που θέλεις να κοιτάει.\"\n  STR_HOLD_DESC: \"Πατήστε παρατεταμένα προς την κατεύθυνση που θέλετε να κοιτάει ο στρατιώτης σας\"\n  STR_SYSTEM_UI: \"Λειτουργία προβολής διεπαφής χρήστη Android\"\n  STR_SYSTEM_UI_DESC: \"Αλλαγή λειτουργίας εμφάνισης μπάρας πλοήγησης στο Android\"\n  STR_ALWAYS_SHOWN: \"Πάντα εμφανίζεται\"\n  STR_LOW_PROFILE: \"Χαμηλό προφίλ\"\n  STR_IMMERSIVE: \"Λειτουργία εμβύθισης\"\n  STR_CONTROLS_LABEL: \"Προσαρμογή ελέγχου\"\n  STR_RECONFIGURE_DIRS: \"Ρύθμιση φακέλων παιχνιδιών\"\n  STR_RECONFIGURE_DIRS_BTN: \"Ορισμός φακέλων\"\n  STR_LOG_DESTINATION: \"Σύνδεση στο\"\n  STR_LOG_FILE: \"Αρχείο\"\n  STR_LOG_FILE_DESC: \"Γράψτε το αρχείο καταγραφής στο openxcom.log. Μπορεί να προκαλέσει ΣΗΜΑΝΤΙΚΕΣ πτώσεις απόδοσης!\"\n  STR_LOG_SYSTEM: \"Καταγραφή\"\n  STR_LOG_SYSTEM_DESC: \"Write log to Android system log. Disabling this option might increase performance a bit, but will prevent useful messages from appearing in log. Η απενεργοποίηση αυτής της επιλογής μπορεί να αυξήσει λίγο την απόδοση, αλλά θα αποτρέψει την εμφάνιση χρήσιμων μηνυμάτων στο καταγραφικό.\"\n  STR_DEBUG_OPTIONS: \"Επιλογές εντοπισμού σφαλμάτων\"\n  STR_LOG_TOUCH_EVENTS: \"Καταγραφή αφήσεων\"\n  STR_LOG_TOUCH_EVENTS_DESC: \"Καταγράψτε όλα τα γεγονότα αφής στο αρχείο καταγραφής.Θα μειώσει σημαντικά την απόδοση, αλλά θα πρέπει να είναι χρήσιμο για τον εντοπισμό σφαλμάτων.\"\n  STR_FAKE_EVENTS: \"Ψεύτικες εκδηλώσεις\"\n  STR_FAKE_EVENTS_DESC: \"Στέλνει ψεύτικα συμβάντα αφής δάκτυλου προς τα επάνω. Χρησιμοποιήστε αυτό εάν συνεχίζετε να αντιμετωπίζετε κολλημένα κουμπιά\"\n  STR_FORCE_GL_MODE: \"Εξαναγκασμός λειτουργίας GL\"\n  STR_FORCE_GL_MODE_DESC: \"Επιβάλλει τη μορφή υφής σε RGB565. Χρησιμοποιήστε αυτήν τη ρύθμιση, εάν η οθόνη σας έχει κόκκινο χρώμα. Εφαρμόζεται μετά από επανεκκίνηση.\"\n  STR_MOUSE_MODE: \"Λειτουργία με ποντίκι\"\n  STR_MOUSE_BASIC: \"Βασικά\"\n  STR_MOUSE_EXTENDED: \"Εκτεταμένη\"\n  STR_MOUSE_MODE_DESC: \"Η επεκταμένη λειτουργία ενεργοποιεί τα φυσικά γεγονότα του ποντικιού, παρέχοντας μια εμπειρία που πλησιάζει στον υπολογιστή.\"\n  STR_LISTDRAGSCROLL: \"σύρσιμο λίστας με το δάκτυλο\"\n  STR_LISTDRAGSCROLL_DESC: \"Ενεργοποιήστε την κύλιση με σύρσιμο για λίστες με δυνατότητα κύλισης. Χρήσιμο για συσκευές με οθόνη αφής.\"\n  STR_DRAGREORDER: \"Σύρετε για αναδιάταξη στρατιωτών\"\n  STR_DRAGREORDER_DESC: \"Σύρε στρατιώτες για να τους αναδιατάξεις στην οθόνη εξοπλισμού του σκάφους.\"\n  STR_SHOW_CURSOR: \"Εμφάνιση κέρσορα\"\n  STR_SHOW_CURSOR_DESC: \"Σχεδιάστε το κίτρινο βέλος του κέρσορα. Χρήσιμο με το ποντίκι.\"\n  STR_FRAMESKIP: \"Παράβλεψη μέγιστων καρέ\"\n  STR_FRAMESKIP_DESC: \"Αυτός είναι ο μέγιστος αριθμός καρέ που μπορεί να παραλείψει ο κώδικας σχεδίασης κατά τη διάρκεια του παιχνιδιού.\"\n"
  },
  {
    "path": "bin/common/Language/Android/en-GB.yml",
    "content": "en-GB:\n  STR_SYSTEM: \"SYSTEM\"\n  STR_SWIPE: \"Swipe to turn\"\n  STR_HOLD: \"Hold to turn\"\n  STR_SWIPE_DESC: \"Swipe from a soldier in the direction you want him to face\"\n  STR_HOLD_DESC: \"Tap and hold in the direction you want your soldier to face\"\n  STR_SYSTEM_UI: \"Android UI display mode\"\n  STR_SYSTEM_UI_DESC: \"Changes Android navigation bar display mode\"\n  STR_ALWAYS_SHOWN: \"Always shown\"\n  STR_LOW_PROFILE: \"Low profile\"\n  STR_IMMERSIVE: \"Immersive mode\"\n  STR_CONTROLS_LABEL: \"Customise controls\"\n  STR_RECONFIGURE_DIRS: \"Set game folders\"\n  STR_RECONFIGURE_DIRS_BTN: \"Set folders\"\n  STR_LOG_DESTINATION: \"Log to\"\n  STR_LOG_FILE: \"File\"\n  STR_LOG_FILE_DESC: \"Write log to openxcom.log. May cause SEVERE performance drops!\"\n  STR_LOG_SYSTEM: \"Logcat\"\n  STR_LOG_SYSTEM_DESC: \"Write log to Android system log. Disabling this option might increase performance a bit, but will prevent useful messages from appearing in log.\"\n  STR_DEBUG_OPTIONS: \"Debug options\"\n  STR_LOG_TOUCH_EVENTS: \"Log touches\"\n  STR_LOG_TOUCH_EVENTS_DESC: \"Write all touch events to log. Will decrease performance significantly, but should be useful for debugging.\"\n  STR_FAKE_EVENTS: \"Fake events\"\n  STR_FAKE_EVENTS_DESC: \"Sends fake fingerUp touch events. Use this if you keep getting stuck buttons.\"\n  STR_FORCE_GL_MODE: \"Force GL mode\"\n  STR_FORCE_GL_MODE_DESC: \"Forces texture format to RGB565. Use this setting if you're getting red-tinted screen. Applies after restart.\"\n  STR_MOUSE_MODE: \"Mouse mode\"\n  STR_MOUSE_BASIC: \"Basic\"\n  STR_MOUSE_EXTENDED: \"Extended\"\n  STR_MOUSE_MODE_DESC: \"Extended mode enables native mouse events, providing near-desktop experience.\"\n  STR_LISTDRAGSCROLL: \"List drag-scrolling\"\n  STR_LISTDRAGSCROLL_DESC: \"Enable drag-scrolling for scrollable lists. Useful for touchscreen-based devices.\"\n  STR_DRAGREORDER: \"Drag to reorder soldiers\"\n  STR_DRAGREORDER_DESC: \"Drag soldiers to reorder them in the craft equipment screen.\"\n  STR_SHOW_CURSOR: \"Show cursor\"\n  STR_SHOW_CURSOR_DESC: \"Draw the yellow cursor arrow. Useful with a mouse.\"\n  STR_FRAMESKIP: \"Maximum frames skipped\"\n  STR_FRAMESKIP_DESC: \"This is the maximum number of frames that may be skipped by the draw code during gameplay\"\n"
  },
  {
    "path": "bin/common/Language/Android/en-US.yml",
    "content": "en-US:\n  STR_SYSTEM: \"SYSTEM\"\n  STR_SWIPE: \"Swipe to turn\"\n  STR_HOLD: \"Hold to turn\"\n  STR_SWIPE_DESC: \"Swipe from a soldier in the direction you want him to face\"\n  STR_HOLD_DESC: \"Tap and hold in the direction you want your soldier to face\"\n  STR_SYSTEM_UI: \"Android UI display mode\"\n  STR_SYSTEM_UI_DESC: \"Changes Android navigation bar display mode\"\n  STR_ALWAYS_SHOWN: \"Always shown\"\n  STR_LOW_PROFILE: \"Low profile\"\n  STR_IMMERSIVE: \"Immersive mode\"\n  STR_CONTROLS_LABEL: \"Customize controls\"\n  STR_RECONFIGURE_DIRS: \"Set game folders\"\n  STR_RECONFIGURE_DIRS_BTN: \"Set folders\"\n  STR_LOG_DESTINATION: \"Log to\"\n  STR_LOG_FILE: \"File\"\n  STR_LOG_FILE_DESC: \"Write log to openxcom.log. May cause SEVERE performance drops!\"\n  STR_LOG_SYSTEM: \"Logcat\"\n  STR_LOG_SYSTEM_DESC: \"Write log to Android system log. Disabling this option might increase performance a bit, but will prevent useful messages from appearing in log.\"\n  STR_DEBUG_OPTIONS: \"Debug options\"\n  STR_LOG_TOUCH_EVENTS: \"Log touches\"\n  STR_LOG_TOUCH_EVENTS_DESC: \"Write all touch events to log. Will decrease performance significantly, but should be useful for debugging.\"\n  STR_FAKE_EVENTS: \"Fake events\"\n  STR_FAKE_EVENTS_DESC: \"Sends fake fingerUp touch events. Use this if you keep getting stuck buttons.\"\n  STR_FORCE_GL_MODE: \"Force GL mode\"\n  STR_FORCE_GL_MODE_DESC: \"Forces texture format to RGB565. Use this setting if you're getting red-tinted screen. Applies after restart.\"\n  STR_MOUSE_MODE: \"Mouse mode\"\n  STR_MOUSE_BASIC: \"Basic\"\n  STR_MOUSE_EXTENDED: \"Extended\"\n  STR_MOUSE_MODE_DESC: \"Extended mode enables native mouse events, providing near-desktop experience.\"\n  STR_LISTDRAGSCROLL: \"List drag-scrolling\"\n  STR_LISTDRAGSCROLL_DESC: \"Enable drag-scrolling for scrollable lists. Useful for touchscreen-based devices.\"\n  STR_DRAGREORDER: \"Drag to reorder soldiers\"\n  STR_DRAGREORDER_DESC: \"Drag soldiers to reorder them in the craft equipment screen.\"\n  STR_SHOW_CURSOR: \"Show cursor\"\n  STR_SHOW_CURSOR_DESC: \"Draw the yellow cursor arrow. Useful with a mouse.\"\n  STR_FRAMESKIP: \"Maximum frames skipped\"\n  STR_FRAMESKIP_DESC: \"This is the maximum number of frames that may be skipped by the draw code during gameplay\"\n"
  },
  {
    "path": "bin/common/Language/Android/es-419.yml",
    "content": "es-419:\n  STR_SYSTEM: \"SISTEMA\"\n  STR_SWIPE: \"Deslizar para girar\"\n  STR_HOLD: \"Mantener para girar\"\n  STR_SWIPE_DESC: \"Deslizar desde un soldado hacía la dirección que quieres que apunte\"\n  STR_HOLD_DESC: \"Toca y manten en la dirección que quieres que el soldado apunte\"\n  STR_SYSTEM_UI: \"Modo de mostrar interfaz Android\"\n  STR_SYSTEM_UI_DESC: \"Cambia el modo de mostrar la barra de navegación Android\"\n  STR_ALWAYS_SHOWN: \"Siempre mostrar\"\n  STR_LOW_PROFILE: \"Bajo perfil\"\n  STR_IMMERSIVE: \"Modo inmersivo\"\n  STR_CONTROLS_LABEL: \"Personalizar controles\"\n  STR_RECONFIGURE_DIRS: \"Establecer folders de juego\"\n  STR_RECONFIGURE_DIRS_BTN: \"Establecer folders\"\n  STR_LOG_DESTINATION: \"Iniciar en\"\n  STR_LOG_FILE: \"Archivo\"\n  STR_LOG_FILE_DESC: \"Escribir el registro en openxcom.log. Puede afectar severamente  el desempeño del juego\"\n  STR_LOG_SYSTEM: \"Logcat\"\n  STR_LOG_SYSTEM_DESC: \"Escribir el registro en el registro del sistema Android. Deshabilitar esta opción podría incrementar el rendimiento un poco, pero la aparición de mensajes utiles en el registro.\"\n  STR_DEBUG_OPTIONS: \"Opciones de depurado\"\n  STR_LOG_TOUCH_EVENTS: \"Toques en registro\"\n  STR_LOG_TOUCH_EVENTS_DESC: \"Escribir todos los toques en el registro. Disminuira el rendimiento significablemente, pero podría resultar util durante depuración.\"\n  STR_FAKE_EVENTS: \"Falsos eventos\"\n  STR_FAKE_EVENTS_DESC: \"Envías falsos eventos de soltar toque. Utiliza esto si ves que tus botones atascados.\"\n  STR_FORCE_GL_MODE: \"Forzar modo GL\"\n  STR_FORCE_GL_MODE_DESC: \"Fuerza las texturas al formato de color RGB565. Utiliza esta configuración si ves que tu pantalla tiene tintes rojos. Se aplica despues del reinicio.\"\n  STR_MOUSE_MODE: \"Modo de mouse\"\n  STR_MOUSE_BASIC: \"Basico\"\n  STR_MOUSE_EXTENDED: \"Extendido\"\n  STR_MOUSE_MODE_DESC: \"El modo extendido permite eventos nativos de mouse, proveyendo una experiencia parecida a la de escritorio\"\n  STR_LISTDRAGSCROLL: \"Arrastrar lista para desplazar\"\n  STR_LISTDRAGSCROLL_DESC: \"Habilita el modo de arrastre para listas. Útil para dispositivos basados en pantalla tactil.\"\n  STR_DRAGREORDER: \"Arrastra para reodenar soldados\"\n  STR_DRAGREORDER_DESC: \"Arrastra los soldados para reordenarlos in la pantalla de equipar navio.\"\n  STR_SHOW_CURSOR: \"Mostrar cursor\"\n  STR_SHOW_CURSOR_DESC: \"Dibuja la flecha de cursor amarilla. Util junto a un mouse.\"\n  STR_FRAMESKIP: \"Numero maximo de cuadros omitidos\"\n  STR_FRAMESKIP_DESC: \"Este es el numero máximo de cuadros que pueden ser omitidos por el codigo de dibujado durante el juego\"\n"
  },
  {
    "path": "bin/common/Language/Android/fi.yml",
    "content": "fi:\n  STR_SYSTEM: \"JÄRJESTELMÄ\"\n  STR_SWIPE: \"Käännä pyyhkäisemällä\"\n  STR_HOLD: \"Käännä pitämällä\"\n  STR_SWIPE_DESC: \"Pyyhkäise sotilaasta suuntaan, johon haluat hänen katsovan\"\n  STR_HOLD_DESC: \"Kosketa ja pidä suunnassa, johon haluat sotilaan katsovan\"\n  STR_SYSTEM_UI: \"Android-käyttöliittymän näytön tila\"\n  STR_SYSTEM_UI_DESC: \"Muuttaa Android-navigointipalkin näytön tilaa\"\n  STR_ALWAYS_SHOWN: \"Näytetään aina\"\n  STR_LOW_PROFILE: \"Vähän huomiota herättävä\"\n  STR_IMMERSIVE: \"Syventävä tila\"\n  STR_CONTROLS_LABEL: \"Säädä ohjaimia\"\n  STR_RECONFIGURE_DIRS: \"Määritä pelikansiot\"\n  STR_RECONFIGURE_DIRS_BTN: \"Määritä kansiot\"\n  STR_LOG_DESTINATION: \"Lokisijainti\"\n  STR_LOG_FILE: \"Tiedosto\"\n  STR_LOG_FILE_DESC: \"Kirjoita loki tiedostoon openxcom.log. Saattaa vaikuttaa VAKAVASTI suorituskykyyn!\"\n  STR_LOG_SYSTEM: \"Logcat\"\n  STR_LOG_SYSTEM_DESC: \"Kirjoita loki Android-järjestelmän lokiin. Valinnan käytöstä poistaminen saattaa parantaa suorituskykyä hieman, mutta estää hyödyllisiä viestejä näkymästä lokissa.\"\n  STR_DEBUG_OPTIONS: \"Viankorjausasetukset\"\n  STR_LOG_TOUCH_EVENTS: \"Kirjaa kosketukset lokiin\"\n  STR_LOG_TOUCH_EVENTS_DESC: \"Kaikki kosketustapahtumat kirjataan lokiin, mikä heikentää suorituskykyä huomattavasti mutta auttaa vikojen korjaamisessa.\"\n  STR_FAKE_EVENTS: \"Valetapahtumat\"\n  STR_FAKE_EVENTS_DESC: \"Lähettää tekaistuja \\\"sormen irrotus\\\"-kosketustapahtumia. Käytä, jos näppäimet jäävät jatkuvasti jumiin.\"\n  STR_FORCE_GL_MODE: \"Pakota GL-tila\"\n  STR_FORCE_GL_MODE_DESC: \"Pakottaa tekstuurit RGB565-muotoon. Käytä, jos ruutusi on punasävytteinen. Muutos astuu voimaan uudelleenkäynnistyksen jälkeen.\"\n  STR_MOUSE_MODE: \"Hiiritila\"\n  STR_MOUSE_BASIC: \"Perus\"\n  STR_MOUSE_EXTENDED: \"Laajennettu\"\n  STR_MOUSE_MODE_DESC: \"Laajennetussa tilassa alkuperäiset hiiritapahtumat otetaan käyttöön, mikä tarjoaa lähes pöytäkonemaisen kokemuksen.\"\n  STR_LISTDRAGSCROLL: \"Listojen vieritys vetämällä\"\n  STR_LISTDRAGSCROLL_DESC: \"Ottaa käyttöön vetovierityksen vieritettävillä listoilla. Hyödyllinen kosketusnäytöllisillä laitteilla.\"\n  STR_DRAGREORDER: \"Sotilaiden järjestely vetämällä\"\n  STR_DRAGREORDER_DESC: \"Järjestele sotilaita vetämällä niitä alusvarusteruudulla.\"\n  STR_SHOW_CURSOR: \"Näytä osoitin\"\n  STR_SHOW_CURSOR_DESC: \"Piirtää keltaisen osoitinnuolen. Hyödyllinen hiiren kanssa.\"\n  STR_FRAMESKIP: \"Kuvia ohitettu enintään\"\n  STR_FRAMESKIP_DESC: \"Suurin sallittu kuvamäärä, jonka piirtokoodin annetaan ohittaa pelin ollessa käynnissä.\"\n"
  },
  {
    "path": "bin/common/Language/Android/fr.yml",
    "content": "fr:\n  STR_SYSTEM: \"SYSTÈME\"\n  STR_SWIPE: \"Glisser pour pivoter\"\n  STR_HOLD: \"Maintenir pour pivoter\"\n  STR_SWIPE_DESC: \"Faites glisser à partir d’un soldat dans la direction souhaitée pour qu’il se tourne.\"\n  STR_HOLD_DESC: \"Touchez et maintenez dans la direction souhaitée pour orienter votre soldat\"\n  STR_SYSTEM_UI: \"Mode d’affichage de l’interface Android\"\n  STR_SYSTEM_UI_DESC: \"Modifie le mode d’affichage de la barre de navigation Android\"\n  STR_ALWAYS_SHOWN: \"Toujours affiché\"\n  STR_LOW_PROFILE: \"Profil discret\"\n  STR_IMMERSIVE: \"Mode immersif\"\n  STR_CONTROLS_LABEL: \"Contrôles customisés\"\n  STR_RECONFIGURE_DIRS: \"Spécifier le répertoire du jeu\"\n  STR_RECONFIGURE_DIRS_BTN: \"Spécifier les répertoires\"\n  STR_LOG_DESTINATION: \"Se connecter\"\n  STR_LOG_FILE: \"Fichier\"\n  STR_LOG_FILE_DESC: \"Générer un fichier log openxcom.log. Peut causer de SÉRIEUX problèmes de performance.\"\n  STR_LOG_SYSTEM: \"Journal système\"\n  STR_LOG_SYSTEM_DESC: \"Écrire les journaux dans le journal système d'Android. Désactiver cette option peut légèrement améliorer les performances, mais empêchera l’affichage de messages utiles dans le journal.\"\n  STR_DEBUG_OPTIONS: \"Options de débogage\"\n  STR_LOG_TOUCH_EVENTS: \"Enregistrer les touches\"\n  STR_LOG_TOUCH_EVENTS_DESC: \"Écrit tous les événements tactiles dans le journal. Réduira significativement les performances, mais peut être utile pour le débogage.\"\n  STR_FAKE_EVENTS: \"Événements simulés\"\n  STR_FAKE_EVENTS_DESC: \"Envoie de faux événements tactiles de relâchement du doigt. À utiliser si des boutons restent bloqués.\"\n  STR_FORCE_GL_MODE: \"Forcer le mode GL\"\n  STR_FORCE_GL_MODE_DESC: \"Force le format de texture en RGB565. À utiliser si l’écran a une teinte rouge. S’applique après redémarrage.\"\n  STR_MOUSE_MODE: \"Mode souris\"\n  STR_MOUSE_BASIC: \"Basique\"\n  STR_MOUSE_EXTENDED: \"Étendu\"\n  STR_MOUSE_MODE_DESC: \"Le mode étendu active les événements souris natifs, offrant une expérience proche de celle d’un PC fixe.\"\n  STR_LISTDRAGSCROLL: \"Défilement par glissement dans les listes\"\n  STR_LISTDRAGSCROLL_DESC: \"Active le défilement par glissement pour les listes. Utile pour les appareils à écran tactile.\"\n  STR_DRAGREORDER: \"Glisser pour réorganiser les soldats\"\n  STR_DRAGREORDER_DESC: \"Faites glisser les soldats pour les réorganiser dans l’écran d’équipement du vaisseau.\"\n  STR_SHOW_CURSOR: \"Afficher le curseur\"\n  STR_SHOW_CURSOR_DESC: \"Affiche la flèche de curseur jaune. Utile avec une souris.\"\n  STR_FRAMESKIP: \"Nombre maximal d’images ignorées\"\n  STR_FRAMESKIP_DESC: \"Nombre maximal d’images que le moteur d’affichage peut ignorer pendant le jeu.\"\n"
  },
  {
    "path": "bin/common/Language/Android/hu.yml",
    "content": "hu:\n  STR_SYSTEM: \"RENDSZER\"\n  STR_SWIPE: \"Forduláshoz Húzz\"\n  STR_HOLD: \"Forduláshoz Nyomj\"\n  STR_SWIPE_DESC: \"Húzd az ujjad a katonádtól az irányba ahova fordítanád\"\n  STR_HOLD_DESC: \"Tartsd lenyomva az ujjad az irányba ahova a katonád fordítanád\"\n  STR_SYSTEM_UI: \"Android kijelző mód\"\n  STR_SYSTEM_UI_DESC: \"Változtatja a navigációs sáv kijelzésének módját\"\n  STR_ALWAYS_SHOWN: \"Mindig kijelzi\"\n  STR_LOW_PROFILE: \"Alacsony profil\"\n  STR_IMMERSIVE: \"Immerzív mód\"\n  STR_CONTROLS_LABEL: \"Irányítás beállításai\"\n  STR_RECONFIGURE_DIRS: \"Válaszd ki a játék mappáit\"\n  STR_RECONFIGURE_DIRS_BTN: \"Válaszd ki a mappákat\"\n  STR_LOG_DESTINATION: \"Napló helye\"\n  STR_LOG_FILE: \"Fájl\"\n  STR_LOG_FILE_DESC: \"A napló openxcom.log-ba történő írása. SÚLYOS teljesítmény csökkenéshez vezethet!\"\n  STR_LOG_SYSTEM: \"Logcat\"\n  STR_LOG_SYSTEM_DESC: \"A napló Android rendszerbeli naplóba írása. A beállítás kikapcsolása növelheti a teljesítményt, de a hasznos üzenetek nem jellennek majd meg a naplóban.\"\n  STR_DEBUG_OPTIONS: \"Debug opciók\"\n  STR_LOG_TOUCH_EVENTS: \"Érintések naplózása\"\n  STR_LOG_TOUCH_EVENTS_DESC: \"Minden  érintést naplóz. Drasztikusan csökkenti a teljesítményt, de hasznos lehet debug-oláshoz.\"\n  STR_FAKE_EVENTS: \"Hamis események\"\n  STR_FAKE_EVENTS_DESC: \"Hamis ujjfelengedéseket generál. Használd ha folyton leragadnak a gombok.\"\n  STR_FORCE_GL_MODE: \"GL mód kényszerítése\"\n  STR_FORCE_GL_MODE_DESC: \"A textúrák formátumát RGB565-re állítja. Akkor használd ha vörös árnyalatú a kijelző. Újraindítás szükséges.\"\n  STR_MOUSE_MODE: \"Egér mód\"\n  STR_MOUSE_BASIC: \"Alap\"\n  STR_MOUSE_EXTENDED: \"Kiterjesztett\"\n  STR_MOUSE_MODE_DESC: \"A kiterjesztett mód engedélyezi az egér funkciókat, közel PC élményt nyújtva.\"\n  STR_LISTDRAGSCROLL: \"Listák görgetése húzással\"\n  STR_LISTDRAGSCROLL_DESC: \"Engedélyezi a görgetését a görgethető listáknak húzással. Hasznos érintőképernyős készülékeknél.\"\n  STR_DRAGREORDER: \"Katonák rendezése húzással\"\n  STR_DRAGREORDER_DESC: \"Húzd a katonákat hogy átrendezd a sorrendjüket a gépfelszerelésnél.\"\n  STR_SHOW_CURSOR: \"Kurzor mutatása\"\n  STR_SHOW_CURSOR_DESC: \"Megjeleníti a sárga kurzort. Hasznos ha egeret használsz.\"\n  STR_FRAMESKIP: \"Maximum képkockák átugrása\"\n  STR_FRAMESKIP_DESC: \"Ez a maximum átugorható képkockák száma amiket a megjelenítő kód átugorhat miközben játszol.\"\n"
  },
  {
    "path": "bin/common/Language/Android/it.yml",
    "content": "it:\n  STR_SYSTEM: \"SISTEMA\"\n  STR_SWIPE: \"Swipe per girare\"\n  STR_HOLD: \"Tieni per girare\"\n  STR_SWIPE_DESC: \"Swipe da un soldato nella direzione verso la quale vuoi che si giri\"\n  STR_HOLD_DESC: \"Premi e tieni premuto nella direzione verso la quale vuoi che si giri il soldato\"\n  STR_SYSTEM_UI: \"Modalità Display UI Android\"\n  STR_SYSTEM_UI_DESC: \"Cambia modalità display barra navigazione Android\"\n  STR_ALWAYS_SHOWN: \"Mostra sempre\"\n  STR_LOW_PROFILE: \"Basso profilo\"\n  STR_IMMERSIVE: \"Modalità immersiva\"\n  STR_CONTROLS_LABEL: \"Personalizza controlli\"\n  STR_RECONFIGURE_DIRS: \"Setta le cartelle di gioco\"\n  STR_RECONFIGURE_DIRS_BTN: \"Sette le cartelle\"\n  STR_LOG_DESTINATION: \"Connetti a\"\n  STR_LOG_FILE: \"File\"\n  STR_LOG_FILE_DESC: \"Scrive il log su openxcom.log. Può causare cali di performance GRAVI!\"\n  STR_LOG_SYSTEM: \"Logcat\"\n  STR_LOG_SYSTEM_DESC: \"Scrive un log sul log di sistema Android. Disabilitare questa opzione può migliorare un po' le prestazioni, ma previene alcuni messaggi utili.\"\n  STR_DEBUG_OPTIONS: \"Opzioni debug\"\n  STR_LOG_TOUCH_EVENTS: \"Log tocchi\"\n  STR_LOG_TOUCH_EVENTS_DESC: \"Scrive un log di tutti gli eventi tocco. Decrementa le prestazioni di molto, ma può essere utile per il debugging.\"\n  STR_FAKE_EVENTS: \"Eventi fasulli\"\n  STR_FAKE_EVENTS_DESC: \"Manda eventi falsi di tocco. Usato per disincastrare i bottoni.\"\n  STR_FORCE_GL_MODE: \"Forza Modalità GL\"\n  STR_FORCE_GL_MODE_DESC: \"Forza il formato texture a RGB565. Usala se hai uno schermo a tinta rossa. Serve un riavvio.\"\n  STR_MOUSE_MODE: \"Modalità Mouse\"\n  STR_MOUSE_BASIC: \"Base\"\n  STR_MOUSE_EXTENDED: \"Estesa\"\n  STR_MOUSE_MODE_DESC: \"La modalità estesa permette eventi nativi del mouse, fornendo un'esperienza simile al desktop.\"\n  STR_LISTDRAGSCROLL: \"Trascinamento lista\"\n  STR_LISTDRAGSCROLL_DESC: \"Permette di trascinare le liste. Utile per un device con touchscreen.\"\n  STR_DRAGREORDER: \"Trascina per ordinare i soldati\"\n  STR_DRAGREORDER_DESC: \"Trascina i soldati per riordinarli nella schermata di equipaggiamento veicolo.\"\n  STR_SHOW_CURSOR: \"Mostra cursore\"\n  STR_SHOW_CURSOR_DESC: \"Disegna il cursore giallo. Utile con mouse.\"\n  STR_FRAMESKIP: \"Massimo di frame saltati\"\n  STR_FRAMESKIP_DESC: \"Questo è il numero massimo di frame che possono essere saltati durante il gioco.\"\n"
  },
  {
    "path": "bin/common/Language/Android/ja.yml",
    "content": "ja:\n  STR_SYSTEM: \"システム\"\n  STR_SWIPE: \"スワイプで向き変更\"\n  STR_HOLD: \"タップ保持で向き変更\"\n  STR_SWIPE_DESC: \"対象の兵の上でスワイプをして向きを変える\"\n  STR_HOLD_DESC: \"対象の兵をタップしたままで動かして向きを変える\"\n  STR_SYSTEM_UI: \"Android用UIモード\"\n  STR_SYSTEM_UI_DESC: \"ナビゲーションバーをAndroid向け表示に切り替える\"\n  STR_ALWAYS_SHOWN: \"常時表示\"\n  STR_LOW_PROFILE: \"最低限\"\n  STR_IMMERSIVE: \"特化モード\"\n  STR_CONTROLS_LABEL: \"入力のカスタマイズ\"\n  STR_RECONFIGURE_DIRS: \"ゲームフォルダの指定\"\n  STR_RECONFIGURE_DIRS_BTN: \"フォルダの設定\"\n  STR_LOG_DESTINATION: \"ログの記録先\"\n  STR_LOG_FILE: \"ファイル\"\n  STR_LOG_FILE_DESC: \"openxcom.logの名でログを記録保存しますが、ゲームの動作が非常に重くなる場合が有ります。\"\n  STR_LOG_SYSTEM: \"Logcat\"\n  STR_LOG_SYSTEM_DESC: \"ログをAndroidのシステムログに書き込みます。このオプションをオフにすると多少動作が軽くなる場合がありますが、有用なメッセージが記録されなくなります。\"\n  STR_DEBUG_OPTIONS: \"デバッグオプション\"\n  STR_LOG_TOUCH_EVENTS: \"タッチイベントのログ\"\n  STR_LOG_TOUCH_EVENTS_DESC: \"タッチイベントを全てログに残します。動作が非常に重くなる場合が有りますが、デバッグ目的の為には有用です。\"\n  STR_FAKE_EVENTS: \"疑似イベント\"\n  STR_FAKE_EVENTS_DESC: \"タッチオフの疑似情報を内部的に使用します。ボタンが押されっぱなしになる状態の解消に有効です。\"\n  STR_FORCE_GL_MODE: \"強制GLモード\"\n  STR_FORCE_GL_MODE_DESC: \"テクスチャのフォーマットを強制的にRGB565にします。画面が赤色っぽくなる場合にオンにして下さい。ゲームの再起動後に適用されます。\"\n  STR_MOUSE_MODE: \"マウスモード\"\n  STR_MOUSE_BASIC: \"基本\"\n  STR_MOUSE_EXTENDED: \"拡張\"\n  STR_MOUSE_MODE_DESC: \"拡張モードはネイティブでマウスをサポートし、デスクトップ環境に近い物にします。\"\n  STR_LISTDRAGSCROLL: \"ドラッグスクロールによるリスト\"\n  STR_LISTDRAGSCROLL_DESC: \"スクロール可能なリストでドラッグスクロールを使用可能にします。タッチ入力系でプレイする場合に便利です。\"\n  STR_DRAGREORDER: \"ドラッグで兵の並び替え\"\n  STR_DRAGREORDER_DESC: \"機体の装備画面で表示される兵の並び順をドラッグで変更可能にします。\"\n  STR_SHOW_CURSOR: \"カーソルの表示\"\n  STR_SHOW_CURSOR_DESC: \"黄色いマウスカーソルを表示します。マウス入力向けの機能です。\"\n  STR_FRAMESKIP: \"フレームスキップの最大数\"\n  STR_FRAMESKIP_DESC: \"ゲーム中の描画中に行われるフレームスキップの最大数を指定します。\"\n"
  },
  {
    "path": "bin/common/Language/Android/ko.yml",
    "content": "ko:\n  STR_SYSTEM: \"시스템\"\n  STR_SWIPE: \"밀어서 회전\"\n  STR_HOLD: \"눌러서 회전\"\n  STR_SWIPE_DESC: \"당신이 병사가 바라보기를 원하는 방향으로 민다.\"\n  STR_HOLD_DESC: \"당신이 병사가 바라보기를 원하는 방향으로 누른다.\"\n  STR_SYSTEM_UI: \"안드로이드 UI 표시 모드\"\n  STR_SYSTEM_UI_DESC: \"안드로이드 내비게이션 바 표시 모드를 변경한다.\"\n  STR_ALWAYS_SHOWN: \"항상 보인다\"\n  STR_LOW_PROFILE: \"저시인성\"\n  STR_IMMERSIVE: \"몰입 모드\"\n  STR_CONTROLS_LABEL: \"조작 변경\"\n  STR_RECONFIGURE_DIRS: \"게임 폴더 설정\"\n  STR_RECONFIGURE_DIRS_BTN: \"폴더 설정\"\n  STR_LOG_DESTINATION: \"로그를 저장할 곳\"\n  STR_LOG_FILE: \"파일\"\n  STR_LOG_FILE_DESC: \"openxcom.log에 기록을 저장한다. 심각한 성능 저하가 일어날 수도 있다!\"\n  STR_LOG_SYSTEM: \"로그캣\"\n  STR_LOG_SYSTEM_DESC: \"안드로이드 시스템 로그에 기록을 저장한다. 이 옵션을 비활성화하면 약간의 성능 향상이 있을 수 있지만, 로그에 나타나는 유용한 메세지를 볼 수 없게 된다.\"\n  STR_DEBUG_OPTIONS: \"디버그 옵션\"\n  STR_LOG_TOUCH_EVENTS: \"터치 기록\"\n  STR_LOG_TOUCH_EVENTS_DESC: \"로그에 모든 터치 기록을 남긴다. 심각하게 성능이 떨어질 것이나, 디버그에 유용하다.\"\n  STR_FAKE_EVENTS: \"가짜 이벤트\"\n  STR_FAKE_EVENTS_DESC: \"가짜 fingerUp 터치 이벤트를 전송한다. 버튼이 계속 눌려있는 것 같으면 사용하라.\"\n  STR_FORCE_GL_MODE: \"GL 모드 강제\"\n  STR_FORCE_GL_MODE_DESC: \"텍스처 포맷을 RGB656으로 강제한다. 붉어 보이는 화면이 되면 이 설정을 이용하라. 재시작 후 적용된다.\"\n  STR_MOUSE_MODE: \"마우스 모드\"\n  STR_MOUSE_BASIC: \"기본\"\n  STR_MOUSE_EXTENDED: \"확장\"\n  STR_MOUSE_MODE_DESC: \"데스크탑 비슷한 경험을 제공하도록, 확장 모드는 실제 마우스 이벤트를 활성화한다.\"\n  STR_LISTDRAGSCROLL: \"목록의 드래그-스크롤\"\n  STR_LISTDRAGSCROLL_DESC: \"스크롤 가능한 목록 중 드래그로 스크롤할 항목을 설정한다. 터치스크린 기반 장비에 유용하다.\"\n  STR_DRAGREORDER: \"병사 재정렬하기 위해 드래그\"\n  STR_DRAGREORDER_DESC: \"기체 장비 화면에서 병사를 재정렬하기 위해 드래그한다\"\n  STR_SHOW_CURSOR: \"커서 표시\"\n  STR_SHOW_CURSOR_DESC: \"노란 커서 화살표를 그린다. 마우스와 사용하면 유용하다.\"\n  STR_FRAMESKIP: \"표시하지 않을 최대 프레임\"\n  STR_FRAMESKIP_DESC: \"이건 게임 플레이 중 화면 그리는 코드에 의해 넘어갈 지 모르는 프레임의 최대 숫자다.\"\n"
  },
  {
    "path": "bin/common/Language/Android/no.yml",
    "content": "\"no\":\n  STR_SYSTEM: \"SYSTEM\"\n  STR_RECONFIGURE_DIRS: \"Velg spillmapper\"\n  STR_RECONFIGURE_DIRS_BTN: \"Velg mapper\"\n  STR_LOG_DESTINATION: \"Logg til\"\n  STR_LOG_FILE: \"Fil\"\n  STR_LOG_FILE_DESC: \"Logg til openxcom.log. Kan føre til VELDIG nedsatt system ytelse!\"\n  STR_FORCE_GL_MODE: \"Tving GL modus\"\n  STR_FORCE_GL_MODE_DESC: \"Tving tekstur-formatet til RGB565. Benyttes ved forekomst av rødlig skjerm. Behøver omstart av spillet.\"\n  STR_MOUSE_MODE: \"Mus modus\"\n  STR_MOUSE_BASIC: \"Enkel\"\n  STR_MOUSE_EXTENDED: \"Utvidet\"\n  STR_SHOW_CURSOR: \"Vis peker\"\n  STR_SHOW_CURSOR_DESC: \"Vis den gule peker pilen. Nyttig ved bruk av mus.\"\n"
  },
  {
    "path": "bin/common/Language/Android/pl.yml",
    "content": "pl:\n  STR_SYSTEM: \"SYSTEM\"\n  STR_SWIPE: \"Przesuń by obrócić\"\n  STR_HOLD: \"Przytrzymaj by obrócić\"\n  STR_SWIPE_DESC: \"Przesuń od żołnierza w stronę, w którą ma spojrzeć\"\n  STR_HOLD_DESC: \"Kliknij i przytrzymaj od żołnierza w stronę, w którą ma spojrzeć\"\n  STR_SYSTEM_UI: \"Tryb wyświetlania interfejsu Androida\"\n  STR_SYSTEM_UI_DESC: \"Zmienia tryb wyświetlania paska nawigacji Androida\"\n  STR_ALWAYS_SHOWN: \"Zawsze widoczny\"\n  STR_LOW_PROFILE: \"Niski profil\"\n  STR_IMMERSIVE: \"Tryb immersji\"\n  STR_CONTROLS_LABEL: \"Przedefiniuj klawisze\"\n  STR_RECONFIGURE_DIRS: \"Ustaw foldery gry\"\n  STR_RECONFIGURE_DIRS_BTN: \"Ustaw foldery\"\n  STR_LOG_DESTINATION: \"Zaloguj do\"\n  STR_LOG_FILE: \"Plik\"\n  STR_LOG_FILE_DESC: \"Zapisuj w openxcom.log. Może spowodować POWAŻNY spadek szybkości!\"\n  STR_LOG_SYSTEM: \"Logcat\"\n  STR_LOG_SYSTEM_DESC: \"Zapisuje log systemu Android. Wyłączenie tej opcji może nieco zwiększyć wydajność, ale użyteczne informacje nie będą pojawiały się w logu.\"\n  STR_DEBUG_OPTIONS: \"Opcje debugu\"\n  STR_LOG_TOUCH_EVENTS: \"Loguj dotyk\"\n  STR_LOG_TOUCH_EVENTS_DESC: \"Zapisuje wszystkie zdarzenia dotykowe w logu. Znacznie obniży wydajność, ale może się przydać przy debugowaniu.\"\n  STR_FAKE_EVENTS: \"Fałszywe zdarzenia\"\n  STR_FAKE_EVENTS_DESC: \"Wysyła fałszywe zdarzenia dotykowe fingerUp. Użyj, jeśli przyciski ci się zacinają.\"\n  STR_FORCE_GL_MODE: \"Wymuś tryb GL\"\n  STR_FORCE_GL_MODE_DESC: \"Wymusza format tekstur RGB565. Użyj tej opcji, jeśli twój ekran jest zabarwiony czerwonawo. Działa po restarcie.\"\n  STR_MOUSE_MODE: \"Tryb myszy\"\n  STR_MOUSE_BASIC: \"Podstawowy\"\n  STR_MOUSE_EXTENDED: \"Extended\"\n  STR_MOUSE_MODE_DESC: \"Tryb rozszerzony pozwala na natywne zdarzenia myszy, dając wrażenie grania na komputerze.\"\n  STR_LISTDRAGSCROLL: \"Przewijanie list trzymaniem\"\n  STR_LISTDRAGSCROLL_DESC: \"Włącza skrolowanie list poprzez ciągnięcie. Przydatne dla urządzeń dotykowych.\"\n  STR_DRAGREORDER: \"Przeciągaj żołnierzy, by zmienić kolejność\"\n  STR_DRAGREORDER_DESC: \"Przeciągaj żołnierzy, by zmienić ich kolejność w ekranie pojazdu.\"\n  STR_SHOW_CURSOR: \"Pokaż kursor\"\n  STR_SHOW_CURSOR_DESC: \"Rysuje żółtą strzałkę kursora. Przydatne wraz z myszą.\"\n  STR_FRAMESKIP: \"Maksymalna liczba pominiętych klatek\"\n  STR_FRAMESKIP_DESC: \"Maksymalna liczba klatek, które podczas gry mogą zostać pominięte przez kod wyświetlający\"\n"
  },
  {
    "path": "bin/common/Language/Android/pt-BR.yml",
    "content": "pt-BR:\n  STR_SYSTEM: \"SISTEMA\"\n  STR_SWIPE: \"Deslize para Virar\"\n  STR_HOLD: \"Segure para Virar\"\n  STR_SWIPE_DESC: \"Deslize de um soldado na direção que você quer que ele olhe\"\n  STR_HOLD_DESC: \"Toque e segure na direção que você deseja que seu soldado olhe\"\n  STR_SYSTEM_UI: \"Modo de exibição da IU do Android\"\n  STR_SYSTEM_UI_DESC: \"Altera o modo de exibição da barra de navegação do Android\"\n  STR_ALWAYS_SHOWN: \"Sempre Mostrar\"\n  STR_LOW_PROFILE: \"Discreto\"\n  STR_IMMERSIVE: \"Modo Imersivo\"\n  STR_CONTROLS_LABEL: \"Personalizar Controles\"\n  STR_RECONFIGURE_DIRS: \"Definir pastas do jogo\"\n  STR_RECONFIGURE_DIRS_BTN: \"Definir pastas\"\n  STR_LOG_DESTINATION: \"Entrar em\"\n  STR_LOG_FILE: \"Arquivo\"\n  STR_LOG_FILE_DESC: \"Gravar o log em openxcom.log. Pode causar GRAVES quedas de desempenho!\"\n  STR_LOG_SYSTEM: \"Logcat\"\n  STR_LOG_SYSTEM_DESC: \"Grave o log no log do sistema Android. Desativar esta opção pode aumentar um pouco o desempenho, mas impedirá que mensagens úteis apareçam no log.\"\n  STR_DEBUG_OPTIONS: \"Opções de Depuração\"\n  STR_LOG_TOUCH_EVENTS: \"Log Toques\"\n  STR_LOG_TOUCH_EVENTS_DESC: \"Grave todos os eventos de toque para registrar. Diminuirá o desempenho significativamente, mas deve ser útil para depuração.\"\n  STR_FAKE_EVENTS: \"Eventos falsos\"\n  STR_FAKE_EVENTS_DESC: \"Envia eventos de toque fingerUp falsos. Use-o se os botões ficarem presos.\"\n  STR_FORCE_GL_MODE: \"Forçar modo GL\"\n  STR_FORCE_GL_MODE_DESC: \"Força o formato da textura para RGB565. Use esta configuração se você estiver obtendo uma tela tingida de vermelho. Aplica-se após o reinício.\"\n  STR_MOUSE_MODE: \"Modo mouse\"\n  STR_MOUSE_BASIC: \"Básico\"\n  STR_MOUSE_EXTENDED: \"Estendido\"\n  STR_MOUSE_MODE_DESC: \"O modo estendido permite eventos de mouse nativos, proporcionando uma experiência próxima ao desktop.\"\n  STR_LISTDRAGSCROLL: \"Lista de rolagem arrastada\"\n  STR_LISTDRAGSCROLL_DESC: \"Habilite a rolagem de arrastar para listas roláveis Útil para dispositivos baseados em touchscreen.\"\n  STR_DRAGREORDER: \"Arraste para reordenar os soldados\"\n  STR_DRAGREORDER_DESC: \"Arraste os soldados para reordená-los na tela de equipamentos da aeronave.\"\n  STR_SHOW_CURSOR: \"Mostrar cursor\"\n  STR_SHOW_CURSOR_DESC: \"Desenhe a seta amarela do cursor. Útil com o mouse.\"\n  STR_FRAMESKIP: \"Máximo de quadros pulados\"\n  STR_FRAMESKIP_DESC: \"Este é o número máximo de frames que podem ser ignorados pelo código de desenho durante o jogo\"\n"
  },
  {
    "path": "bin/common/Language/Android/pt-PT.yml",
    "content": "pt-PT:\n  STR_SYSTEM: \"SISTEMA\"\n  STR_SWIPE: \"Deslizar para virar\"\n  STR_HOLD: \"Manter premido para virar\"\n  STR_SWIPE_DESC: \"Deslizar de um soldado para a direção que quer que ele se vire\"\n  STR_HOLD_DESC: \"Tocar e manter na direção que quer que o soldado se vire\"\n  STR_SYSTEM_UI: \"Modo de visualização da interface Android\"\n  STR_SYSTEM_UI_DESC: \"Altera o modo de visualização da barra de navegação do Android\"\n  STR_ALWAYS_SHOWN: \"Sempre mostrado\"\n  STR_LOW_PROFILE: \"Baixo perfil\"\n  STR_IMMERSIVE: \"Modo imersivo\"\n  STR_CONTROLS_LABEL: \"Personalizar controlos\"\n  STR_RECONFIGURE_DIRS: \"Definir pastas do jogo\"\n  STR_RECONFIGURE_DIRS_BTN: \"Definir pastas\"\n  STR_LOG_DESTINATION: \"Registar em\"\n  STR_LOG_FILE: \"Ficheiro\"\n  STR_LOG_FILE_DESC: \"Gravar registo em openxcom.log. Pode causar EXTREMA lentidão!\"\n  STR_LOG_SYSTEM: \"Registo Android\"\n  STR_LOG_SYSTEM_DESC: \"Gravar o registo no registo do sistema do Android. Desativar esta opção pode aumentar um pouco o desempenho, mas irá impedir que apareçam mensagens úteis no registo.\"\n  STR_DEBUG_OPTIONS: \"Opções de depuração\"\n  STR_LOG_TOUCH_EVENTS: \"Registar toques\"\n  STR_LOG_TOUCH_EVENTS_DESC: \"Gravar todos os eventos de toque no registo. Irá aumentar o desempenho consideravelmente, mas deve ser utilizado para depuração de erros.\"\n  STR_FAKE_EVENTS: \"Eventos falsos\"\n  STR_FAKE_EVENTS_DESC: \"Enviar eventos de toque fingerUp. Use isto que os botões encravarem muitas vezes.\"\n  STR_FORCE_GL_MODE: \"Forçar modo GL\"\n  STR_FORCE_GL_MODE_DESC: \"Força o formato de textura RGB565. Use esta configuração se estiver e ver o ecrã avermelhado. Surte efeito após reiniciar.\"\n  STR_MOUSE_MODE: \"Modo rato\"\n  STR_MOUSE_BASIC: \"Básico\"\n  STR_MOUSE_EXTENDED: \"Estendido\"\n  STR_MOUSE_MODE_DESC: \"O modo estendido ativa os eventos de rato nativo, fornecendo uma experiência semelhante a um computador de mesa.\"\n  STR_LISTDRAGSCROLL_DESC: \"Activar a deslocação por arrastamento para listas deslocáveis. Útil para dispositivos com ecrã táctil.\"\n  STR_DRAGREORDER: \"Arrastar para reordenar soldados\"\n  STR_DRAGREORDER_DESC: \"Arraste soldados para reordená-los no ecrã de equipamentos da aeronave.\"\n  STR_SHOW_CURSOR: \"Mostrar cursor\"\n  STR_SHOW_CURSOR_DESC: \"Desenhar a seta do cursor amarelo. Útil com um rato.\"\n  STR_FRAMESKIP: \"Máximo de fotogramas ignorado\"\n  STR_FRAMESKIP_DESC: \"Isto é o número máximo de fotogramas que podem ser ignorados pelo código de desenhar durante o jogo.\"\n"
  },
  {
    "path": "bin/common/Language/Android/ro.yml",
    "content": "ro:\n  STR_SYSTEM: \"SISTEM\"\n  STR_SWIPE: \"Glisați pentru a întoarce\"\n  STR_HOLD: \"Țineți pentru a întoarce\"\n  STR_SWIPE_DESC: \"Glisați de la un soldat în direcția în care îl vreți să fie poziționat\"\n  STR_HOLD_DESC: \"Loviți si țineți apăsat în direcția în care vreți să fie poziționați soldatul vostru\"\n  STR_SYSTEM_UI: \"Mod de afișare Android UI \"\n  STR_SYSTEM_UI_DESC: \"Schimbă modul de afișare al barei de navigare Android\"\n  STR_ALWAYS_SHOWN: \"Întotdeauna arătat\"\n  STR_LOW_PROFILE: \"Profil scăzut\"\n  STR_IMMERSIVE: \"Modul imersiv\"\n  STR_CONTROLS_LABEL: \"Customizează controale\"\n  STR_RECONFIGURE_DIRS: \"Setează dosare de joc\"\n  STR_RECONFIGURE_DIRS_BTN: \"Seteaza dosare\"\n  STR_LOG_DESTINATION: \"Scrie log la\"\n  STR_LOG_FILE: \"Fisier\"\n  STR_LOG_FILE_DESC: \"Scrie log la openxcom.log. Poate cauza cădere de performanţă SEVERĂ!\"\n  STR_LOG_SYSTEM: \"Logcat\"\n  STR_LOG_SYSTEM_DESC: \"Scrie log la log-ul de system Android. Dezactivarea acestei opțiuni poate crește performanța un pic, dar va preveni mesaje utile să apareă în log.\"\n  STR_DEBUG_OPTIONS: \"Opțiuni de depanare\"\n  STR_LOG_TOUCH_EVENTS: \"Scrie atingeri in log\"\n  STR_LOG_TOUCH_EVENTS_DESC: \"Scrie orice eveniment tactil la log. Va scade performanța semnificativ, dar poate fii folositor pentru depanare.\"\n  STR_FAKE_EVENTS: \"Evenimente false\"\n  STR_FAKE_EVENTS_DESC: \"Trimite evenimente tactile false fingerUp. Folosește această opțiune dacă aveți butoanele care rămân blocate. \"\n  STR_FORCE_GL_MODE: \"Forțează modul GL\"\n  STR_FORCE_GL_MODE_DESC: \"Forțeaza formatul de textura la RGB565. Folosește aceasta opțiune dacă vedeți ecran cu tentă roșie. Este aplicat după restartare. \"\n  STR_MOUSE_MODE: \"Modul mouse\"\n  STR_MOUSE_BASIC: \"Bază\"\n  STR_MOUSE_EXTENDED: \"Extins\"\n  STR_MOUSE_MODE_DESC: \"Modul extins permite evenimente native de mouse, furnizând o experiență aproape-desktop.\"\n  STR_LISTDRAGSCROLL: \"Liste cu defilare prin glisare\"\n  STR_LISTDRAGSCROLL_DESC: \"Permite defilare prin glisare a listelor de parurgere. Folositor pentru dispositive cu touchscreen.\"\n  STR_DRAGREORDER: \"Trage să reorganizezi soldații\"\n  STR_DRAGREORDER_DESC: \"Trage soldații să îi reorganizezi in meniul de echipament al navei\"\n  STR_SHOW_CURSOR: \"Afișează cursorul\"\n  STR_SHOW_CURSOR_DESC: \"Desenează cursorul sageată galbenă. Folositor cu mouse.\"\n  STR_FRAMESKIP: \"Maximum frame-uri sărite.\"\n  STR_FRAMESKIP_DESC: \"Acesta este numărul maxim de frame-uri care pot fi sărite de codul de desenare in timpul jocului.\"\n"
  },
  {
    "path": "bin/common/Language/Android/ru.yml",
    "content": "ru:\n  STR_SYSTEM: \"СИСТЕМА\"\n  STR_SWIPE: \"Поворот свайпом\"\n  STR_HOLD: \"Поворот удержанием\"\n  STR_SWIPE_DESC: \"Проведите пальцем от бойца в ту сторону, в которую хотите его развернуть\"\n  STR_HOLD_DESC: \"Удерживайте палец в точке, в направлении которой хотите развернуть бойца\"\n  STR_SYSTEM_UI: \"Интерфейс системы\"\n  STR_SYSTEM_UI_DESC: \"Позволяет изменить режим отображения системной навигационной панели\"\n  STR_ALWAYS_SHOWN: \"Отображается\"\n  STR_LOW_PROFILE: \"Затемнена\"\n  STR_IMMERSIVE: \"Скрыта\"\n  STR_CONTROLS_LABEL: \"Настройки управления\"\n  STR_RECONFIGURE_DIRS: \"Папки игры\"\n  STR_RECONFIGURE_DIRS_BTN: \"Изменить\"\n  STR_LOG_DESTINATION: \"Журналирование\"\n  STR_LOG_FILE: \"Файл\"\n  STR_LOG_FILE_DESC: \"Запись событий в openxcom.log. Может серьезно влиять на производительность.\"\n  STR_LOG_SYSTEM: \"Logcat\"\n  STR_LOG_SYSTEM_DESC: \"Запись событий в системный журнал. Отключение может немного повысить производительность, но полезная информация не будет сохраняться в логе.\"\n  STR_DEBUG_OPTIONS: \"Отладка\"\n  STR_LOG_TOUCH_EVENTS: \"Нажатия\"\n  STR_LOG_TOUCH_EVENTS_DESC: \"Запись всех касаний экрана в журнал. Значительно снижает производительность. Только для отладки.\"\n  STR_FAKE_EVENTS: \"События\"\n  STR_FAKE_EVENTS_DESC: \"При активации игра посылает фиктивные события fingerUp, чтобы предотвратить залипание кнопок.\"\n  STR_FORCE_GL_MODE: \"Режим GL\"\n  STR_FORCE_GL_MODE_DESC: \"Принуд. выбор текстур формата RGB565. Может предотвратить появление «красного экрана». Требует перезапуска игры.\"\n  STR_MOUSE_MODE: \"Режим мыши\"\n  STR_MOUSE_BASIC: \"Обычный\"\n  STR_MOUSE_EXTENDED: \"Расширенный\"\n  STR_MOUSE_MODE_DESC: \"Расширенный режим включает полноценную поддержку событий мыши и обеспечивает поведение, схожее с десктопным.\"\n  STR_LISTDRAGSCROLL: \"Прокрутка списков удержанием\"\n  STR_LISTDRAGSCROLL_DESC: \"Позволяет прокручивать списки удержанием. Особенно эффективно на сенсорных экранах.\"\n  STR_DRAGREORDER: \"Сортировка бойцов перетаскиванием\"\n  STR_DRAGREORDER_DESC: \"Позволяет изменять расположение бойцов в транспорте перетаскиванием на экране грузового отсека.\"\n  STR_SHOW_CURSOR: \"Отображать курсор\"\n  STR_SHOW_CURSOR_DESC: \"Отображать желтый курсор мыши. Особенно удобно при использовании мыши.\"\n  STR_FRAMESKIP: \"Макс. количество пропущенных кадров\"\n  STR_FRAMESKIP_DESC: \"Максимальное количество кадров, которое может быть пропущено при отрисовке во время игры\"\n"
  },
  {
    "path": "bin/common/Language/Android/sv.yml",
    "content": "sv:\n  STR_SYSTEM: \"SYSTEM\"\n  STR_SWIPE: \"Svep för att vända\"\n  STR_HOLD: \"Håll ner för att vända\"\n  STR_ALWAYS_SHOWN: \"Visas alltid\"\n  STR_LOW_PROFILE: \"Låg profil\"\n  STR_CONTROLS_LABEL: \"Anpassa kontroller\"\n  STR_RECONFIGURE_DIRS: \"Ställ in spelmappar\"\n  STR_RECONFIGURE_DIRS_BTN: \"Ställ in mappar\"\n  STR_DEBUG_OPTIONS: \"Felsökningsalternativ\"\n  STR_MOUSE_MODE: \"Musläge\"\n  STR_MOUSE_BASIC: \"Grundläggande\"\n  STR_MOUSE_EXTENDED: \"Utökat\"\n  STR_SHOW_CURSOR: \"Visa muspekare\"\n"
  },
  {
    "path": "bin/common/Language/Android/uk.yml",
    "content": "uk:\n  STR_SYSTEM: \"СИСТЕМА\"\n  STR_SWIPE: \"Проведіть пальцем, щоб повернути\"\n  STR_HOLD: \"Утримуйте, щоб повернути\"\n  STR_SWIPE_DESC: \"Проведіть пальцем від солдата у тому напрямку, в якому ви хочете, щоб він був обличчям\"\n  STR_HOLD_DESC: \"Торкніться та утримуйте у тому напрямку, в якому ви хочете, щоб солдат був оберненим обличчям\"\n  STR_SYSTEM_UI: \"Режим інтерфейсу Android\"\n  STR_SYSTEM_UI_DESC: \"Змінити режим навігаційної панелі Android\"\n  STR_ALWAYS_SHOWN: \"Завжди відображати\"\n  STR_LOW_PROFILE: \"Легкий профіль\"\n  STR_IMMERSIVE: \"Режим занурення\"\n  STR_CONTROLS_LABEL: \"Налаштувати управління\"\n  STR_RECONFIGURE_DIRS: \"Встановити ігрову директорію\"\n  STR_RECONFIGURE_DIRS_BTN: \"Встановити директорії\"\n  STR_LOG_DESTINATION: \"Логувати до\"\n  STR_LOG_FILE: \"Файл\"\n  STR_LOG_FILE_DESC: \"Записати журнал у openxcom.log. Може спричинити серйозне падіння продуктивності!\"\n  STR_LOG_SYSTEM: \"Logcat\"\n  STR_LOG_SYSTEM_DESC: \"Запис журналу до системного журналу Android. Вимкнення цієї опції може дещо збільшити продуктивність, але унеможливить появу корисних повідомлень у журналі.\"\n  STR_DEBUG_OPTIONS: \"Debug-параметри\"\n  STR_LOG_TOUCH_EVENTS: \"Логувати дотики\"\n  STR_LOG_TOUCH_EVENTS_DESC: \"Записувати усі події дотику до журналу. Значно знижує продуктивність, але має бути корисним для налагодження.\"\n  STR_FAKE_EVENTS: \"Фейкові події\"\n  STR_FAKE_EVENTS_DESC: \"Надсилає підроблені події дотику пальцями. Використовуйте це, якщо кнопки постійно застрягають.\"\n  STR_FORCE_GL_MODE: \"Примусовий GL-режим\"\n  STR_FORCE_GL_MODE_DESC: \"Примусовий формат текстур RGB565. Використовуйте це налаштування, якщо екран стає червоним. Застосовується після перезапуску.\"\n  STR_MOUSE_MODE: \"Режим миші\"\n  STR_MOUSE_BASIC: \"Базовий\"\n  STR_MOUSE_EXTENDED: \"Розширений\"\n  STR_MOUSE_MODE_DESC: \"Розширений режим включає системні події миші, забезпечуючи роботу майже на робочому столі.\"\n  STR_LISTDRAGSCROLL: \"Прокручування списку перетягуванням\"\n  STR_LISTDRAGSCROLL_DESC: \"Увімкнути прокрутку перетягуванням для прокручуваних списків. Корисно для пристроїв із сенсорним екраном.\"\n  STR_DRAGREORDER: \"Перетягування для зміни порядку солдат\"\n  STR_DRAGREORDER_DESC: \"Перетягніть солдатів, щоб змінити їх порядок на екрані вибору спорядження.\"\n  STR_SHOW_CURSOR: \"Відображати курсор\"\n  STR_SHOW_CURSOR_DESC: \"Малювати жовту стрілку курсору. Корисно при використанні миші.\"\n  STR_FRAMESKIP: \"Максимальна кількість пропущених кадрів\"\n  STR_FRAMESKIP_DESC: \"Це максимальна кількість кадрів, які можуть бути пропущені при оновленні зображення під час гри\"\n"
  },
  {
    "path": "bin/common/Language/OXCE/cs.yml",
    "content": "cs:\n  STR_CANNOT_DISMANTLE_FACILITY_UPGRADING: \"ZAŘÍZENÍ NELZE ODSTRANIT!{SMALLLINE}Zařízení nelze odstranit během vylepšování.\"\n  STR_CANNOT_UPGRADE_FACILITY_ALREADY_UPGRADING: \"TADY NELZE STAVĚT!{SMALLLINE}Na tomto místě je zařízení již vylepšováno.\"\n  STR_CANNOT_UPGRADE_FACILITY_WRONG_SIZE: \"TADY NELZE STAVĚT!{SMALLLINE}Vybrané zařízení musí plně překrývat již postavené.\"\n  STR_CANNOT_UPGRADE_FACILITY_WRONG_TYPE: \"TADY NELZE STAVĚT!{SMALLLINE}Toto stávající zařízení nelze vybraným vylepšit.\"\n  STR_CANNOT_UPGRADE_FACILITY_DISALLOWED: \"TADY NELZE STAVĚT!{SMALLLINE}Toto stávající zařízení nelze přestavět.\"\n  STR_CANNOT_BUILD_QUEUE_OFF: \"TADY NELZE STAVĚT!{SMALLLINE}Propojovaná zařízení musí být nejprve dostavěna.\"\n  STR_FACILITY_FORBIDDEN_BY_OTHER: \"ZDE NELZE STAVĚT!{SMALLLINE}Nějaké jiné zařízení znemožňuje stavbu.\"\n  STR_FACILITY_OTHER_FORBIDDEN_BY_THIS: \"ZDE NELZE STAVĚT!{SMALLLINE}Některé postavené zařízení by bylo s touto stavbou v rozporu.\"\n  STR_NOT_ENOUGH_ITEMS: \"NEDOSTATEK MATERIÁLU!{SMALLLINE}Je potřeba více materiálu pro stavbu tohoto zařízení:{NEWLINE}Chybí> {0}: {1}\"\n  STR_ID: \"ID\"\n  STR_FIRST_LETTER: \"PRVNÍ PÍSMENO\"\n  STR_SOLDIER_TYPE: \"TYP JEDNOTKY\"\n  STR_IDLE_DAYS: \"NEAKTIVNÍ DNY\"\n  STR_MANA: \"MANA\"\n  STR_MANA_POOL: \"ZÁSOBA MANY\"\n  STR_MANA_MISSING: \"CHYBĚJÍCÍ MANA\"\n  STR_LOAD_CRAFT_LOADOUT_TEMPLATE: \"Načíst náklad pro stroj\"\n  STR_EMPTY_SLOT_N: \"Volná pozice {0}\"\n  STR_UNNAMED_SLOT_N: \"Nepojmenovaná pozice {0}\"\n  STR_ADD_ON_TOP: \"Přidat navíc\"\n  STR_SAVE_CRAFT_LOADOUT_TEMPLATE: \"Uložit náklad pro stroj\"\n  STR_SAVE_UC: \"ULOŽIT\"\n  STR_ALL: \"Vše\"\n  STR_EQUIPPED: \"Vybaveno\"\n  STR_NOT_EQUIPPED: \"Nepoužito\"\n  STR_UNASSIGNED: \"Ostatní\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED_BY_SIZE: \"VÍCE VYBAVENÍ NA PALUBĚ NENÍ DOVOLENO!{SMALLLINE}Maximální skladovací prostor: {0}\"\n  STR_PILOTS: \"PILOTI\"\n  STR_SHIELD: \"ŠTÍT>{ALT}{0}\"\n  STR_CRAFT_SKIN_ID: \"[{0}]\"\n  STR_SELECT_PILOT: \"Vybrat pilota\"\n  STR_PILOTS_FOR_CRAFT: \"Pilot(i) pro {0}\"\n  STR_PILOTS_REQUIRED: \"Pilot(i) potřeba:  {ALT}{0}\"\n  STR_ADD_PILOT: \"Přidat pilota\"\n  STR_REMOVE_ALL_PILOTS: \"Odebrat všechny piloty\"\n  STR_ACCURACY_BONUS: \"Bonus pro přesnost\"\n  STR_DODGE_BONUS: \"Bonus pro uhýbání\"\n  STR_APPROACH_SPEED: \"Rychlost přiblížení\"\n  STR_COWARDLY: \"Zbaběle (-50%)\"\n  STR_NORMAL: \"Normálně\"\n  STR_BOLD: \"Směle (+50%)\"\n  STR_VERY_BOLD: \"Statečně (+100%)\"\n  STR_ARMOR_GROUP_NOT_ALLOWED: \"Zbroj tohoto typu nesmí na palubu.\"\n  STR_SOLDIER_GROUP_NOT_ALLOWED: \"Jednotka tohoto typu nesmí na palubu.\"\n  STR_SOLDIER_GROUP_NOT_SAME: \"Jednotka tohoto typu nemůže na palubu s jednotkami co tam už jsou.\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW: \"Náhled\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_SAVED: \"Náhled *\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_BRIEFING: \"Tato možnost nabízí náhled a úpravu rozestavení vašich jednotek na začátku mise. Pohyb není omezen. Stiskněte a podržte 'Alt' pro zvýraznění platných pozic jednotek. Klikněte na ikonu 'Přerušit misi' pro uložení upravené rozmístění. Klikněte na ikonu 'Ukončit kolo' pro opuštění náhledu.{NEWLINE}Mějte na paměti, že přidáním nových vojáků nebo vozidel do stroje se automaticky zneplatní uložené vlastní rozmístění. Je li nějaké vlastní rozmístění nastaveno, u tlačítka 'Náhled' je zobrazena hvězdička.\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_BRIEFING_DUMMY: \"Tato možnost nabízí náhled a úpravu rozestavovací tabulky pro tento typ stroje. Veškeré změny budou aplikovány na všechny vaše současné stroje a i na nakoupené, či vyrobené v budoucnu. Začínáte s maximálním počtem vojáků. Každý voják představuje jeden řádek v rozmísťovací tabulce. Vojákovo jméno odpovídá číslu řádku. Pro vytvoření místa pro jednotku 2x2, umístěte 4 vojáky do čtverce 2x2. Pokud nebude místo přiděleno, v bitvě bude 2x2 jednotka chybět.\"\n  STR_BASE_DEFENSE_BRIEFING_PREVIEW: \"Tato možnost nabízí náhled na vaši základnu.{NEWLINE}Hodně zábavy!{NEWLINE}{NEWLINE}Klikněte na ikonu 'Konec kola' pro ukončení náhledu.\"\n  STR_REFUND_VALUE: \"Prodejní hodnota> {ALT}{0}\"\n  STR_REFUND_VALUE_NEGATIVE: \"Výdaje> {ALT}{0}\"\n  STR_PRODUCTION_OVERVIEW: \"PŘEHLED PRODUKCE\"\n  STR_RESEARCH_DIARY: \"DENÍK VÝZKUMU\"\n  STR_RESEARCH_OVERVIEW: \"PŘEHLED VÝZKUMU\"\n  STR_PRISONER_OVERVIEW: \"PŘEHLED VĚZŇŮ\"\n  STR_PRISONER: \"VĚZEŇ\"\n  STR_PRISONER_AMOUNT: \"MNOŽSTVÍ\"\n  STR_PRISONER_INTERROGATED: \"VYSLÝCHÁN\"\n  STR_TOTAL_IN_PRISON: \"Využito prostoru>{ALT}{0}\"\n  STR_TOTAL_INTERROGATED: \"Vyslýchán>{ALT}{0}\"\n  STR_PRISON_TYPE: \"Cizácká cela\"\n  STR_KILL_SELECTED: \"Zabij\"\n  STR_SELL_SELECTED: \"Prodej\"\n  STR_GO_TO_TRANSFERS: \"Přesun...\"\n  STR_PRISON_CLEANUP: \"Čistka věznice\"\n  STR_TOPIC: \"Téma>{ALT} {0}\"\n  STR_SHOW_ALL: \"Ukázat vše\"\n  STR_NO_DEPENDENCIES: \"Bez závislostí.\"\n  STR_DIRECT_DEPENDENCIES: \"Přímé závislosti\"\n  STR_LEVEL_2_DEPENDENCIES: \"Závislosti na 2. úrovni\"\n  STR_LEVEL_3_DEPENDENCIES: \"Závislosti na 3. úrovni\"\n  STR_LEVEL_4_DEPENDENCIES: \"Závislosti na 4. úrovni\"\n  STR_MORE_DEPENDENCIES: \"Existují ještě hlubší závislosti...\"\n  STR_END_OF_SEARCH: \"Konec prohledávání.\"\n  STR_REFUND_PRODUCTION: \"VRATKA!\"\n  STR_HOURS_PER_UNIT: \"HODIN NA JEDNOTKU>{ALT}{0}\"\n  STR_PERSON_JOINING: \"Nastupující osoba\"\n  STR_RANDOM_PRODUCTION_DISCLAIMER: \"Náhodná produkce!\"\n  STR_OTHER_EMPLOYEES: \"Ostatní personál a vybavení\"\n  STR_SHOW_ONLY_NEW: \"Ukázat jen nové\"\n  STR_FILTER_DEFAULT: \"Výchozí\"\n  STR_FILTER_DEFAULT_SUPPLIES_OK: \"Výchozí (zásoby OK)\"\n  STR_FILTER_DEFAULT_NO_SUPPLIES: \"Výchozí (bez zásob)\"\n  STR_FILTER_FACILITY_REQUIRED: \"Zařízení chybí\"\n  STR_FILTER_HIDDEN: \"Zkryté\"\n  STR_FILTER_EQUIPPED: \"Vybaveno\"\n  STR_FILTER_MISSING: \"Chybí\"\n  STR_SORT_DEFAULT: \"Výchozí\"\n  STR_SORT_BY_COST: \"Dle ceny\"\n  STR_SORT_BY_NAME: \"Dle jména\"\n  STR_RANDOM_PRODUCTION_SUMMARY: \"Výsledek\"\n  STR_NOT_ENOUGH_PRISON_SPACE: \"NEDOSTATEK CIZÁCKÝCH CEL!{SMALLLINE}Postav nové cizácké cely, nebo přesuň cizáky na jiné základny.\"\n  STR_MONTHLY_ITEM_PURCHASE_LIMIT_EXCEEDED: \"MĚSÍČNÍ NÁKUPNÍ LIMIT BYL PŘEKROČEN!{SMALLLINE}Více zboží bude k dispozici příští měsíc.\"\n  STR_MONTHLY_CRAFT_PURCHASE_LIMIT_EXCEEDED: \"MĚSÍČNÍ NÁKUPNÍ LIMIT BYL PŘEKROČEN!{SMALLLINE}Více strojů bude k dispozici příští měsíc.\"\n  STR_MONTHLY_SOLDIER_HIRING_LIMIT_EXCEEDED: \"MĚSÍČNÍ NÁKUPNÍ LIMIT BYL PŘEKROČEN!{SMALLLINE}Více rekrutů bude k dispozici příští měsíc.\"\n  STR_NOT_ENOUGH_CRAFT_SPACE: \"Na palubě již není místo!\"\n  STR_SELECT_AVATAR_FOR: \"ZVOLIT AVATAR PRO{NEWLINE}{0}\"\n  STR_SOLDIER_BONUSES_FOR: \"BONUSY JEDNOTKY{NEWLINE}{0}\"\n  STR_SUMMARY: \"Výsledek\"\n  STR_MANA_RECOVERY: \"OBNOVA MANY> {ALT}{0}\"\n  STR_HEALTH_RECOVERY: \"UZDRAVENÍ> {ALT}{0}\"\n  STR_BONUSES_BUTTON: \"+\"\n  STR_PROMOTE_SOLDIER: \"POVÝŠIT/DEGRADOVAT{NEWLINE}{0} {1}\"\n  STR_RANK_HEADER: \"HODNOST\"\n  STR_OPENINGS_HEADER: \"OTEVŘENÍ\"\n  STR_KILLER_AND_WEAPON: \"{0}, {1}\"\n  STR_TRAINING: \"Tréning\"\n  STR_SOLDIER_INFO: \"Informace o jednotce\"\n  STR_TRANSFORMATIONS_BUTTON: \"^\"\n  STR_TRANSFER_TIME: \"Čas přesunu>{ALT}{0}\"\n  STR_RECOVERY_TIME: \"Čas zotavení>{ALT}{0}\"\n  STR_CURRENT_STATS: \"Aktuální statistiky\"\n  STR_CHANGES: \"Změny\"\n  STR_CHANGES_MIN: \"Změny (min)\"\n  STR_CHANGES_MAX: \"Změny (max)\"\n  STR_BONUS_STATS: \"Bonusové stat.\"\n  STR_TRANSFORMATIONS_OVERVIEW: \"Přehled transformací\"\n  STR_PROJECT_NAME: \"JMÉNO PROJEKTU\"\n  STR_AVAILABLE_MATERIALS: \"DOSTUPNÉ MATERIÁLY\"\n  STR_ELIGIBLE_SOLDIERS: \"ZPŮSOBILÍ VOJÁCI\"\n  STR_SHOW_ONLY_ELIGIBLE: \"Zobrazit pouze způsobilé\"\n  STR_ALL_SOLDIER_TYPES: \"Všechny typy vojáků\"\n  STR_ALL_SOLDIERS: \"Všichni vojáci\"\n  STR_HEALTHY_SOLDIERS: \"Zdraví vojáci\"\n  STR_WOUNDED_SOLDIERS: \"Zranění vojáci\"\n  STR_DEAD_SOLDIERS: \"Mrtví vojáci\"\n  STR_GRAND_TOTAL: \"Celkový součet\"\n  STR_AVAILABLE_TOPICS: \"DOSTUPNÁ TÉMATA\"\n  STR_QS_THREE_LETTERS_A: \"Zadejte alespoň 3 znaky\"\n  STR_QS_THREE_LETTERS_B: \"Do rychlého hledání...\"\n  STR_M_FLAG: \" [m]\"\n  STR_F_FLAG: \" [f]\"\n  STR_I_FLAG: \" [i]\"\n  STR_C_FLAG: \" [c]\"\n  STR_THIS_FEATURE_IS_DISABLED_1: \"Tuto možnost nelze použít.\"\n  STR_THIS_FEATURE_IS_DISABLED_2: \"Tuto možnost nelze použít.\"\n  STR_THIS_FEATURE_IS_DISABLED_3: \"Tuto možnost nelze použít.\"\n  STR_THIS_FEATURE_IS_DISABLED_4: \"Tuto možnost nelze použít.\"\n  STR_THIS_FEATURE_IS_DISABLED_5: \"Tuto možnost nelze použít.\"\n  STR_TECH_TREE_VIEWER: \"Prohlížeč technologického stromu\"\n  STR_SELECT_TOPIC: \"Vybrat téma\"\n  STR_RESEARCH_PROGRESS: \"Pokrok>{ALT} {0}%\"\n  STR_ITEM_DESTROYED: \"Předmět zničen:\"\n  STR_ITEM_REQUIRED: \"Vyžadován předmět:\"\n  STR_SERVICES_REQUIRED: \"Vyžadovaná zařízení:\"\n  STR_SERVICES_PROVIDED: \"Poskytnutých služeb:\"\n  STR_SERVICES_FORBIDDEN: \"Zakázaná zařízení:\"\n  STR_REQUIRES: \"Vyžaduje:\"\n  STR_DEPENDS_ON: \"Závisí na:\"\n  STR_UNLOCKED_BY: \"Čím odemknuto:\"\n  STR_DISABLED_BY: \"Čím znepřístupněn:\"\n  STR_REENABLED_BY: \"reaktivováno:\"\n  STR_GET_FOR_FREE_FROM: \"Obdrž zdarma za:\"\n  STR_IS_LOOKUP_OF: \"Je hledáno:\"\n  STR_LOOKUP: \"Hledání:\"\n  STR_SPAWNED_ITEMS: \"Stvořené věci:\"\n  STR_SPAWNED_EVENT: \"Vytvoří událost:\"\n  STR_REQUIRED_BY: \"Čím vyžadován:\"\n  STR_REQUIRED_BY_TRANSFORMATIONS: \"Vyžadováno pro transformace:\"\n  STR_LEADS_TO: \"Vede k:\"\n  STR_UNLOCKS: \"Odemyká:\"\n  STR_DISABLES: \"Znepřístupňuje:\"\n  STR_REENABLES: \"Znovu umožňuje:\"\n  STR_GIVES_ONE_FOR_FREE_SEQ: \"Dává zdarma jeden z (postupně):\"\n  STR_GIVES_ONE_FOR_FREE: \"Dává zdarma jeden z:\"\n  STR_RESEARCH_REQUIRED: \"Vyžadován výzkum:\"\n  STR_RESEARCH_REQUIRED_USE: \"Požadovaný výzkum (použít):\"\n  STR_RESEARCH_REQUIRED_BUY: \" Požadovaný výzkum (koupit):\"\n  STR_SERVICES_REQUIRED_BUY: \" Požadované služby (koupit):\"\n  STR_PRODUCED_BY: \"Kde se vyrábí:\"\n  STR_SPAWNED_BY: \"Vytvořeno kým/čím:\"\n  STR_MATERIALS_REQUIRED: \"Vyžaduje materiál:\"\n  STR_TTV_COST_PER_UNIT: \"Cena jednotky:\"\n  STR_TTV_ENGINEER_HOURS: \"Hodiny inženýrů:\"\n  STR_TTV_WORK_SPACE_REQUIRED: \"Potřebný pracovní prostor\"\n  STR_ITEMS_PRODUCED: \"Vyrobené předměty:\"\n  STR_PERSON_RECRUITED: \"Najmuty jednotky:\"\n  STR_UNLOCKS_ARCS: \"Odemknout oblouky:\"\n  STR_DISABLES_ARCS: \"Vypnout oblouky:\"\n  STR_UNLOCKS_MISSIONS: \"Odemyká mise:\"\n  STR_DISABLES_MISSIONS: \"Znepřístupňuje mise:\"\n  STR_UNLOCKS_EVENTS: \"Odemyká události:\"\n  STR_DISABLES_EVENTS: \"Znemožní události:\"\n  STR_AFFECTS_GAME_PROGRESSION: \"Ovlivňuje postup hrou!\"\n  STR_ITEMS_AT_DESTINATION: \"Předměty v cíli\"\n  STR_PRISONERS: \"Vězni\"\n  STR_ARMORS: \"Zbroje\"\n  STR_CRAFT_DEPLOYMENT_QUESTION: \"Uložit umístění stroje?\"\n  STR_MUST_USE_BOTH_HANDS: \"Na tohle potřebuješ obě ruce!\"\n  STR_NOT_ENOUGH_MORALE: \"Nedostatek morálky!\"\n  STR_NOT_ENOUGH_HEALTH: \"Nedostatek zdraví!\"\n  STR_NOT_ENOUGH_MANA: \"Nedostatek many!\"\n  STR_NOT_ENOUGH_STUN: \"Příliš velká úroveň omráčení!\"\n  STR_MIND_CONTROL_SUCCESSFUL_ALT: \"Akce úspěšná\"\n  STR_LINE_OF_SIGHT_REQUIRED: \"Musí být na dohled (LoS).\"\n  STR_CENTER_ON_WOUNDED_FRIEND: \"Vycentruj na raněnou přátelskou jednotku.\"\n  STR_CENTER_ON_DIZZY_FRIEND: \"Vycentruj na zmateného kamaráda\"\n  STR_BUG_HUNT_ACTIVATED: \"Lov škodné aktivován: nepřátelé jsou vidět na minimapě!\"\n  STR_QUICK_MODE_ACTIVATED: \"Aktivován mód Usain Bolt.{NEWLINE}Opětovným stiskem Ctrl+S ho deaktivuješ.\"\n  STR_QUICK_MODE_DEACTIVATED: \"Mód Usain Bolt deaktivován.\"\n  STR_TARGET_ENEMY: \"; Cíl = NEPŘÍTEL\"\n  STR_TARGET_NEUTRAL: \"; Cíl = NEUTRÁL\"\n  STR_TARGET_FRIEND: \"; Cíl = PŘÍTEL\"\n  STR_TARGET_YOURSELF: \"; Cíl = TY\"\n  STR_TARGET_ON_THE_GROUND: \"(na zemi)\"\n  STR_USE_SPECIAL_ITEM: \"Použij zvláštní předmět\"\n  STR_NO_EXPERIENCE_YET: \"Zatím bez zkušeností:\"\n  STR_OPERATION_UC: \"PROVOZ> {0}\"\n  STR_WHAT_CAN_I_WEAR: \"Co na sebe?\"\n  STR_STARTING_CONDITION_ARMORS_FORBIDDEN: \"Tato mise vyžaduje specifické vybavení.{NEWLINE}{NEWLINE}Zakázané typy zbroje: {0}\"\n  STR_STARTING_CONDITION_ARMORS_ALLOWED: \"Tato mise vyžaduje specifické vybavení.{NEWLINE}{NEWLINE}Povolené typy zbroje: {0}\"\n  STR_MISSION_OVER: \"Mise dokončena.\"\n  STR_UNITS_WITH_FATAL_WOUNDS:\n    one: \"Jedna těžce zraněná jednotka.\"\n    few: \"{N} zraněné jednotky.\"\n    many: \"{N} zraněných jednotek.\"\n    other: \"{N} zraněných jednotek.\"\n  STR_END_MISSION_QUESTION: \"Ukončit misi?\"\n  STR_LOOT: \"KOŘIST\"\n  STR_SELL: \"PRODAT\"\n  STR_LIVE_ALIENS_SURRENDERED: \"NEPŘÁTELÉ SE VZDALI\"\n  STR_MISSION_ABORTED: \"MISE ZRUŠENA\"\n  STR_VIPS_SAVED: \"ZACHRÁNĚNO VIP\"\n  STR_VIPS_LOST: \"ZTRACENO VIP\"\n  STR_BOUNTY: \"ODMĚNA\"\n  STR_MANA_ABBREVIATION: \"MAN\"\n  STR_EXPERIENCE_OVERVIEW: \"Přehled zkušeností\"\n  STR_CANNOT_PLACE_ITEM_INTO_THIS_SECTION: \"Sem to umístit nejde.{NEWLINE}Neptej se proč!\"\n  STR_ONE_HAND_MUST_BE_EMPTY: \"Alespoň jedna ruka musí být prázdná!\"\n  STR_LOAD_EQUIPMENT_TEMPLATE: \"Načti šablonu vybavení.\"\n  STR_SAVE_EQUIPMENT_TEMPLATE: \"Ulož šablonu vybavení.\"\n  STR_FIRING_SHORT: \"Střelba>{ALT}{0}\"\n  STR_THROWING_SHORT: \"Vrh>{ALT}{0}\"\n  STR_MELEE_SHORT: \"Zblízka>{ALT}{0}\"\n  STR_PERSONAL_EQUIPMENT: \"OSOBNÍ VYBAVENÍ\"\n  STR_SAVE_PERSONAL_EQUIPMENT: \"Uložit osobní vybavení\"\n  STR_LOAD_PERSONAL_EQUIPMENT: \"Načíst osobní vybavení\"\n  STR_PERSONAL_EQUIPMENT_SAVED: \"Osobní vybavení uloženo.\"\n  STR_SLOT: \"Slot>{ALT}{0}\"\n  STR_THINKING: \"Promýšlení...\"\n  STR_TELL_ME_MORE: \"Pověz mi víc...\"\n  STR_REINFORCEMENTS_ALERT: \"Varování - Posily!\"\n  STR_HIT_LOG_NEW_TURN: \"Nový tah\"\n  STR_FAILED_CQB_CHECK: \"Nepřítel přerušil tvůj útok!\"\n  STR_NO_TRAJECTORY: \"Žádná rozumná trajektorie!\"\n  STR_HIT_LOG_NEW_BULLET: \"=>\"\n  STR_MANA_SHORT: \"MA>{ALT}{0}\"\n  STR_SKILL_NEEDS_ITEM: \"Tato schopnost vyžaduje věc!\"\n  STR_HIT_LOG_NO_DAMAGE: \"0\"\n  STR_HIT_LOG_SMALL_DAMAGE: \"zásah\"\n  STR_HIT_LOG_BIG_DAMAGE: \"ZÁSAH\"\n  STR_HIT_LOG_REACTION_FIRE: \"Reakční střelba...\"\n  STR_HIT_LOG: \"Záznam zásahů\"\n  STR_BUTTON_TOUCH: \"Dotyk\"\n  STR_BUTTON_1: \"1\"\n  STR_BUTTON_10: \"10\"\n  STR_BUTTON_100: \"100\"\n  STR_BUTTON_CTRL: \"Ctrl\"\n  STR_BUTTON_ALT: \"Alt\"\n  STR_BUTTON_SHIFT: \"Shift\"\n  STR_LAZY_LOADING: \"Líné nahrávání\"\n  STR_LAZY_LOADING_DESC: \"Zdroje grafiky hry jsou nahrávány až tehdy, když jsou potřeba. Při vypnutí se vše nahraje při spuštění.\"\n  STR_VSYNC_FOR_OPENGL: \"VSync pro OpenGL\"\n  STR_VSYNC_FOR_OPENGL_DESC: \"Vypněte pro maximální rychlost skrytého pohybu nepřítele a (případně) rychlost pohybu vojáka. NESNIŽUJTE FPS na 0. Platí pouze pro OpenGL vykreslování.\"\n  STR_UPDATE_CHECK: \"Automaticky kontroluj aktualizace\"\n  STR_UPDATE_CHECK_DESC: \"OpenXcom bude automaticky kontrolovat dostupné aktualizace a případně nabídne aktualizaci na jedno kliknutí.\"\n  STR_AUTOSAVE_SLOTS: \"Pozice automatického ukládání\"\n  STR_AUTOSAVE_SLOTS_DESC: \"Počet pozic pro automatické ukládání bitvy.\"\n  STR_AUTO_SAVE_BATTLESCAPE_SLOT_WITH_NUMBER: \"<AUTO BATTLESCAPE> {0}\"\n  STR_GEO_AUTOSAVE_FREQUENCY: \"Frekvence automatického ukládaní (Geoscape)\"\n  STR_GEO_AUTOSAVE_FREQUENCY_DESC: \"Počet dnů po které se hra sama uloží.\"\n  STR_OXCE_LINKS: \"Rozšířené odkazy\"\n  STR_OXCE_LINKS_DESC: \"Aktivuje dodatečná menu/tlačítka/odkazy pro funkce OXCE.\"\n  STR_PEDIA_SHOW_CLIP_SIZE: \"Zobraz kapacitu zásobníku v Ufopedii\"\n  STR_PEDIA_SHOW_CLIP_SIZE_DESC: \"V Ufopedii zobrazí kapacitu zásobníku vedle ikony munice.\"\n  STR_SHOW_SLACKING_INDICATOR: \"Zobraz indikátor flákačů\"\n  STR_SHOW_SLACKING_INDICATOR_DESC: \"Zobrazí počet vědců a inženýrů, kteří aktuálně na ničem nepracují.\"\n  STR_SHOW_MAINTENANCE_TIME: \"Zobraz dobu údržby\"\n  STR_SHOW_ETA: \"Zobraz přibližnou dobu letu\"\n  STR_UFO_LANDING_ALERT: \"Upozornění na přistání UFA.\"\n  STR_UFO_LANDING_ALERT_DESC: \"Pokud je aktivováno, pokaždé, když UFO přistane, zobrazí se ti upozornění.\"\n  STR_REMEMBER_DISABLED_CRAFT_WEAPONS: \"Pamatuj si vypnuté zbraně plavidel\"\n  STR_REMEMBER_DISABLED_CRAFT_WEAPONS_DESC: \"Zbraně vypnuté při vzdušném souboji zůstanou vypnuté. Také nebudou dobíjeny v základně.\"\n  STR_ALTERNATE_CRAFT_EQUIPMENT_MANAGEMENT: \"Alternativní správa vybavení stroje\"\n  STR_ALTERNATE_CRAFT_EQUIPMENT_MANAGEMENT_DESC: \"Je li aktivní, bude se s přesouvaným vojákem stěhovat i jeho vybavení (pokud možno).\"\n  STR_HIGHLIGHT_NEW: \"Zvýrazni nová témata\"\n  STR_PERSONAL_LAYOUT_INCLUDING_ARMOR: \"Zbroj započítávej do osobní výbavy\"\n  STR_PERSONAL_LAYOUT_INCLUDING_ARMOR_DESC: \"Oblečená zbroj je součástí uložené výbavy jednotky.\"\n  STR_MANUALPROMOTIONS: \"Ruční povýšení\"\n  STR_MANUALPROMOTIONS_DESC: \"Je li aktivní, vojáci mohou být manuálně povýšení (nebo degradováni) kliknutím na ikonu hodnosti.\"\n  STR_WOUNDED_DEFEND_BASE_IF: \"Ranění brání základnu (pokud mají život nad x%)\"\n  STR_WOUNDED_DEFEND_BASE_IF_DESC: \"Obrany základny se účastní i raněné jednotky, pokud je jejich zdraví nad udanou procentní částí.\"\n  STR_PLAY_BRIEFING_MUSIC_DURING_EQUIPMENT: \"Hraj hudbu v briefingu déle\"\n  STR_PLAY_BRIEFING_MUSIC_DURING_EQUIPMENT_DESC: \"Hudba z briefingu bude hrát i během vyzbrojování, dokud se neobjeví bojiště.\"\n  STR_NIGHT_VISION_COLOR: \"Vyber barvu nočního vidění\"\n  STR_NIGHT_VISION_COLOR_DESC: \"Hodnoty od 1 do 15 reprezentují různé odstíny barvy.\"\n  STR_AUTO_NIGHT_VISION_THRESHOLD: \"Autom. hranice pro noční vidění\"\n  STR_AUTO_NIGHT_VISION_THRESHOLD_DESC: \"Je li temněji než tato hranice, zapne automaticky noční vidění\"\n  STR_SHOW_ACCURACY_ON_CROSSHAIR: \"Zobraz přesnost na zaměřovači\"\n  STR_AUTO_SELL: \"Automatizovaný prodej kořisti\"\n  STR_AUTO_SELL_DESC: \"Na prodejní obrazovce po boji budou předměty, které byly prodány po předchozích bitvách, automaticky označeny k prodeji.\"\n  STR_AUTOMATICPROMOTIONS: \"Automatická povýšení\"\n  STR_AUTOMATICPROMOTIONS_DESC: \"Je li aktivní, vojácí jsou po misi automaticky povýšeni.\"\n  STR_OFF_CENTRE_SHOOTING: \"Adaptabilní střelba\"\n  STR_OFF_CENTRE_SHOOTING_DESC: \"Pokud voják při střelbě nevidí přímo na cíl, zkusí se automaticky naklonit, aby viděl.\"\n  STR_GRAPHS_ZOOM_IN: \"Přiblížit (graf)\"\n  STR_GRAPHS_ZOOM_OUT: \"Oddálit (graf)\"\n  STR_MARK_ALL_AS_SEEN: \"Označ vše jako přečtené\"\n  STR_SELL_ALL: \"Nastav vše\"\n  STR_SELL_ALL_BUT_ONE: \"Nastav vše až na jednu\"\n  STR_TRANSFER_ALL: \"Přesunout vše\"\n  STR_REMOVE_SOLDIERS_FROM_ALL_CRAFTS: \"Odstranit vojáky ze všech strojů\"\n  STR_REMOVE_SOLDIERS_FROM_CRAFT: \"Odstranit vojáky ze stroje\"\n  STR_REMOVE_EQUIPMENT_FROM_CRAFT: \"Odstranit vybavení ze stroje\"\n  STR_REMOVE_ARMOR_FROM_ALL_CRAFTS: \"Demontovat pancéřování ze všech strojů\"\n  STR_REMOVE_ARMOR_FROM_CRAFT: \"Demontovat pancéřování stroje\"\n  STR_REMOVE_SOLDIERS_FROM_TRAINING: \"Vyřadit vojáka z tréningu\"\n  STR_ADD_SOLDIERS_TO_TRAINING: \"Přiřadit vojáka k tréningu\"\n  STR_INVENTORY_ARMOR: \"Změň zbroj\"\n  STR_INVENTORY_AVATAR: \"Změn avatara\"\n  STR_ACTION_ITEM_1: \"Akce předmětu 1 (Miř/Použij)\"\n  STR_ACTION_ITEM_2: \"Akce předmětu 2 (od boku)\"\n  STR_ACTION_ITEM_3: \"Akce předmětu 3 (dávka)\"\n  STR_ACTION_ITEM_4: \"Akce předmětu 4 (Zblízka)\"\n  STR_ACTION_ITEM_5: \"Akce předmětu 5 (Vrh)\"\n  STR_TOGGLE_QUICK_SEARCH: \"Přepnout na pole rychlého hledání\"\n  STR_TOGGLE_NIGHT_VISION: \"Přepni noční vidění\"\n  STR_HOLD_NIGHT_VISION: \"Krátké noční vidění\"\n  STR_SELECT_MUSIC_TRACK: \"Vyber si skladbu\"\n  STR_TOGGLE_TOUCH_BUTTONS: \"Zapnout dotyková tlačítka\"\n  STR_TOGGLE_BRIGHTNESS: \"Nastavit jas (jen obraz)\"\n  STR_BRIEFING: \"Brífing\"\n  STR_TOGGLE_DEBUG_MODE: \"Vypni/zapni debugování\"\n  STR_DEBUG_KILL_ALL_ALIENS: \"DEBUG: Zabij všechny nepřátele\"\n  STR_PHYSICAL_TRAINING: \"Bojový trénink\"\n  STR_REMAINING_TRAINING_FACILITY_CAPACITY: \"ZBÝVAJÍCÍ TRÉNINKOVÁ KAPACITA> {ALT}{0}\"\n  STR_NO_WOUNDED: \"-\"\n  STR_NO_QUEUED: \"+\"\n  STR_NO_DONE: \"HOTOVO\"\n  STR_NO_AMMO: \"BEZ MUNICE!\"\n  STR_START_FIRING: \"Pal!\"\n  STR_SKIP_FIRING: \"Pusť je dovnitř...\"\n  STR_ALIEN_MISSILES_HAVE_DAMAGED_OUR_BASE: \"Základna {0} byla poškozena nepřátelskými raketami\"\n  STR_ALIEN_MISSILES_HAVE_DESTROYED_OUR_BASE: \"Základna {0} byla zničena nepřátelskými raketami\"\n  STR_STARTING_CONDITION_COMMANDER: \"Na této misi musí být přítomen velitel.\"\n  STR_STARTING_CONDITION_CRAFT: \"Tato loď není pro tuto misi vhodná.\"\n  STR_STARTING_CONDITION_CRAFT_ALLOWED: \"Tato loď není pro tuto misi vhodná.{NEWLINE}{NEWLINE}Použitelné stroje: {0}\"\n  STR_STARTING_CONDITION_CRAFT_FORBIDDEN: \"Tato loď není pro tuto misi vhodná.{NEWLINE}{NEWLINE}Zakázané stroje: {0}\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE: \"Některé jednotky se nemohou mise zúčastnit.\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE_ALLOWED: \"Některé jednotky se nemohou mise zúčastnit.{NEWLINE}{NEWLINE}Povolené typy jednotek: {0}\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE_FORBIDDEN: \"Některé jednotky se nemohou mise zúčastnit.{NEWLINE}{NEWLINE}Zakázané typy jednotek: {0}\"\n  STR_STARTING_CONDITION_ITEM: \"Tato mise vyžaduje specifické vybavení.{NEWLINE}{NEWLINE}{0}\"\n  STR_NOT_ENOUGH_FUEL_TO_REACH_TARGET: \"NEDOSTATEK PALIVA!{SMALLLINE}Cíl je mimo letový dosah plavidla.\"\n  STR_ASSIGN_PILOTS: \"Přiřaď piloty...\"\n  STR_NOT_ENOUGH_PILOTS: \"Nedostatek pilotů!{NEWLINE}Minimum: {0}\"\n  STR_DAILY_PILOT_EXPERIENCE: \"Denní zkušenost pilota\"\n  STR_UFO_SHIELD_HIT: \"ZÁSAH ŠTÍTŮ!\"\n  STR_UFO_HIT_NO_DAMAGE: \"ODRAZ OD TRUPU!\"\n  STR_UFO_SHIELD_DOWN: \"NEPŘÁTELSKÉ ŠTÍTY VYPNUTY!\"\n  STR_UFO_HIT_GLANCING: \"BLESKOVÝ ZÁSAH!\"\n  STR_INTERCEPTOR_SHIELD_HIT: \"NAŠE ŠTÍTY DRŽÍ!\"\n  STR_TRACTOR_BEAM_ENGAGED: \"ZÁCHYTNÝ PAPRSEK AKTIVOVÁN!\"\n  STR_TRACTOR_BEAM_DISENGAGED: \"ODPOJENÍ ZÁCHYTNÉHO PAPRSKU\"\n  STR_SELF_DESTRUCT_ACTIVATED: \"SEBEZNIČENÍ AKTIVOVÁNO!\"\n  STR_SELF_DESTRUCT_CANCELLED: \"SEBEZNIČENÍ ZRUŠENO\"\n  STR_MISSILE_DAMAGED: \">>> RAKETA POŠKOZENA <<<\"\n  STR_MISSILE_DESTROYED: \">>> RAKETA ZNIČENA <<<\"\n  STR_EXTENDED_LINKS: \"Odkazy\"\n  STR_AUTO_PATROL: \"AUTOMATICKÁ HLÍDKA\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_FACILITY_AT_BASE: \"{2} hlásí nedostatek {0} k nabíjení {1}\"\n  STR_UFO_STARTED_HUNTING: \"{0} pronásleduje {1}\"\n  STR_CRAFT_IS_READY: \"{0} na {1} je připravena.\"\n  STR_ECONOMY_WARNING: \"Finance {0} a a příjem {1} jsou nízké, a údržba {2} příliš nákladná! Raději něco prodej, aby nebyla nutná půjčka... Chybějící finance: {3}\"\n  STR_SLACKING_INDICATOR: \"{0}:{1}\"\n  STR_TRAINING_INDICATOR: \"{0}:{1}\"\n  STR_EXTENDED_UC: \"ROZŠÍŘENÍ\"\n  STR_RETURNING: \"VRACÍ SE\"\n  STR_INTERCEPTING: \"STÍHÁ\"\n  STR_ESCORTING: \"ESKORTUJE\"\n  STR_EN_ROUTE: \"NA CESTĚ\"\n  STR_PILOT_MISSING: \"CHYBĚJÍCÍ PILOT\"\n  STR_DAY_SHORT: \"{0} d\"\n  STR_HOUR_SHORT: \"{0} h\"\n  STR_PERFORMANCE_BONUS: \"Prémie za výkon\"\n  STR_COUNTRY_HAS_CANCELLED_A_SECRET_PACT: \"{0} ohlašuje vypovězení smlouvy s cizáky a opět se stává součástí projektu.\"\n  STR_COUNTRIES_HAVE_CANCELLED_A_SECRET_PACT: \"{0} ohlašují vypovězení smlouvy s cizáky a opět se stávají součástí projektu.\"\n  STR_WE_CAN_NOW_RENT: \"Nyní si můžeme pronajmout\"\n  STR_REQUIRED_BASE_SERVICES: \"Vyžaduje v základně zařízení: {0}\"\n  STR_WE_CAN_NOW_BUILD: \"Nyní můžeme stavět\"\n  STR_WE_CAN_NOW_PURCHASE: \"Nyní můžeme koupit\"\n  STR_NOT_ENOUGH_LIVING_SPACE_AT_BASE: \"Nedostatek ubytovacího místa pro ubytování{NEWLINE}{0}{NEWLINE}na{NEWLINE}{1}\"\n  STR_INFO: \"INFO\"\n  STR_DESPAWN_PENALTY: \"Postih za odstranění> {0}\"\n  STR_TRAINING_FINISHED: \"{0} hlásí{NEWLINE}dokončený výcvik.\"\n  STR_PSI_TRAINING_FINISHED: \"Psi tréning dokončen{NEWLINE}v {0}\"\n  STR_IGNORE_UC: \"IGNORUJ\"\n  STR_UFO_TRACKER: \"Stopař UFO\"\n  STR_UPDATE: \"Aktualizace\"\n  STR_LATEST_VERSION_INFO: \"Používáte aktuální verzi OpenXcom.\"\n  STR_MASTER_MOD_VERSION_REQUIRED_QUESTION: \"Tento mód pro správný běh vyžaduje základní hru ve verzi v{0}. Povolit mód? \"\n  STR_VERSION_REQUIRED_QUESTION: \"Tento mod pro svůj běh vyžaduje OXCE v{0}. Aktivovat ho?\"\n  STR_OPEN_MODS_FOLDER: \"Otevřít\"\n  STR_NOTES: \"Poznámky\"\n  STR_NEW_NOTE: \"<NEW NOTE>\"\n  STR_PATH_ENERGY_COST: \"Výdrž\"\n  STR_PATH_ENERGY_COST_DESC: \"Kliknutím se zobrazí zbývající energie vaší jednotky po přesunutí do cíle.\"\n  STR_TEST_SCREEN: \"TESTOVACÍ OBRAZOVKA\"\n  STR_PALETTE: \"Paleta\"\n  STR_PREVIEW: \"Náhled\"\n  STR_TINY_BORDERLESS: \"Drobné, bez okrajů\"\n  STR_TINY_BORDER: \"Drobné\"\n  STR_SMALL_LOW_CONTRAST: \"Malé\"\n  STR_SMALL_HIGH_CONTRAST: \"Malé s vysokým kontrastem\"\n  STR_BIG_LOW_CONTRAST: \"Velké\"\n  STR_BIG_HIGH_CONTRAST: \"Velké s vysokým kontrastem\"\n  STR_TEST_CASE: \"Pokusný případ:\"\n  STR_RUN: \"Spusť vybrané testy!\"\n  STR_TESTS_STARTING: \"Startuji...\"\n  STR_TESTS_ERRORS_FOUND: \"Celkem nalezeno chyb (mohou zde být duplikace): {0}\"\n  STR_TESTS_NO_ERRORS_FOUND: \"Žádné chyby nenalezeny.\"\n  STR_TESTS_FINISHED: \"Konec.\"\n  STR_DETAILED_INFO_IN_LOG_FILE: \"Detailní informace byly uloženy do souboru openxcom.log\"\n  STR_RANK_NONE: \"-\"\n  STR_DAMAGE_NONE: \"ŽÁDNÉ\"\n  STR_INFO_UFOPEDIA: \"INFO\"\n  STR_COCKPIT_CAPACITY: \"PILOTŮ>{ALT}{0}{ALT}\"\n  STR_MAXIMUM_RANGE: \"MAX DOSAH>{ALT}{0}{ALT}\"\n  STR_MINIMUM_RANGE: \"MIN DOSAH>{ALT}{0}{ALT}\"\n  STR_INFINITE_RANGE: \"N/A\"\n  STR_TRACTOR_BEAM_POWER: \"Účinek\"\n  STR_WEIGHT_PEDIA1: \"Hm.: {0}\"\n  STR_WEIGHT_PEDIA2: \"Hm.: {0}/{1}\"\n  STR_SHOT_TYPE_MELEE: \"Zblízka\"\n  STR_ACCURACY_MODIFIER: \"Modifikátor přesnosti>{ALT} {0}\"\n  STR_POWER_BONUS: \"Bonus k účinku>{ALT} {0}\"\n  STR_MULTIPLE_DIFFERENT_BONUSES: \"různé bonusy v závislosti na munici\"\n  STR_STATS_FOR_NERDS: \"Čísla pro šprty\"\n  STR_ARTICLE: \"Článek>{ALT} {0}\"\n  STR_COMPATIBLE_AMMO: \"Kompatibilní munice:\"\n  STR_BUILT_IN_ITEMS: \"Vestavěno:\"\n  STR_CLIP_SIZE_UNLIMITED: \"neomezený\"\n  STR_SHOTGUN_BEHAVIOR_OXCE: \"rozšířená\"\n  STR_INCLUDE_DEBUG: \"DEBUG\"\n  STR_INCLUDE_IDS: \"ID\"\n  STR_INCLUDE_DEFAULTS: \"VÝCHOZÍ HODNOTY\"\n  STR_TRUE: \"ano\"\n  STR_FALSE: \"ne\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH: \"PSI DOVEDNOST * PSI SÍLA\"\n  STR_STRENGTH_AND_MELEE_ACCURACY: \"SÍLA * PŘESNOST ZBLÍZKA\"\n  STR_STRENGTH_AND_THROWING_ACCURACY: \"SÍLA * PŘESNOST VRHU\"\n  STR_FIRING_ACCURACY_AND_REACTIONS: \"PŘESNOST STŘELBY * REAKCE\"\n  STR_HEALTH_CURRENT: \"AKTUÁLNÍ ZDRAVÍ\"\n  STR_MANA_CURRENT: \"DOSTUPNÁ MANA\"\n  STR_TIME_UNITS_CURRENT: \"AKTUÁLNÍ ČASOVÉ JEDNOTKY\"\n  STR_STUN_LEVEL_CURRENT: \"AKTUÁLNÍ ÚROVEŇ OMRÁČENÍ\"\n  STR_HEALTH_NORMALIZED: \"NORMALIZOVANÉ ZDRAVÍ\"\n  STR_MANA_NORMALIZED: \"NORMALIZOVANÁ MANA\"\n  STR_TIME_UNITS_NORMALIZED: \"NORMALIZOVANÉ ČASOVÉ JEDNOTKY\"\n  STR_ENERGY_NORMALIZED: \"NORMALIZOVANÁ VÝDRŽ\"\n  STR_MORALE_NORMALIZED: \"NORMALIZOVANÁ MORÁLKA\"\n  STR_STUN_LEVEL_NORMALIZED: \"NORMALIZOVANÁ ÚROVEŇ OMRÁČENÍ\"\n  STR_ENERGY_REGENERATION: \"OBNOVA VÝDRŽE\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH_ABBREVIATION: \"PSD*PSL\"\n  STR_STRENGTH_AND_MELEE_ACCURACY_ABBREVIATION: \"SIL*BOJ\"\n  STR_STRENGTH_AND_THROWING_ACCURACY_ABBREVIATION: \"SIL*HOD\"\n  STR_FIRING_ACCURACY_AND_REACTIONS_ABBREVIATION: \"PŘE*REA\"\n  STR_HEALTH_CURRENT_ABBREVIATION: \"AKTUÁLNÍ ZDRAVÍ\"\n  STR_MANA_CURRENT_ABBREVIATION: \"DOSTUPNÁ MANA\"\n  STR_TIME_UNITS_CURRENT_ABBREVIATION: \"AKTUÁLNÍ ČASOVÉ JEDNOTKY\"\n  STR_STUN_LEVEL_CURRENT_ABBREVIATION: \"AKTUÁLNÍ ÚROVEŇ OMRÁČENÍ\"\n  STR_HEALTH_NORMALIZED_ABBREVIATION: \"NORMALIZOVANÉ ZDRAVÍ\"\n  STR_MANA_NORMALIZED_ABBREVIATION: \"NORMALIZOVANÁ MANA\"\n  STR_TIME_UNITS_NORMALIZED_ABBREVIATION: \"NORMALIZOVANÉ ČASOVÉ JEDNOTKY\"\n  STR_ENERGY_NORMALIZED_ABBREVIATION: \"NORMALIZOVANÁ VÝDRŽ\"\n  STR_MORALE_NORMALIZED_ABBREVIATION: \"NORMALIZOVANÁ MORÁLKA\"\n  STR_STUN_LEVEL_NORMALIZED_ABBREVIATION: \"NORMALIZOVANÁ ÚROVEŇ OMRÁČENÍ\"\n  STR_ENERGY_REGENERATION_ABBREVIATION: \"OBNOVA VÝDRŽE\"\n  STR_COST_TIME: \"čas\"\n  STR_COST_ENERGY: \"výdrž\"\n  STR_COST_MORALE: \"morálka\"\n  STR_COST_HEALTH: \"zdraví\"\n  STR_COST_STUN: \"omráčení\"\n  STR_COST_MANA: \"mana\"\n  STR_COST_BUILD: \"postav\"\n  STR_COST_REFUND: \"vrácení peněz\"\n  STR_DAMAGE_10: \"10\"\n  STR_DAMAGE_11: \"11\"\n  STR_DAMAGE_12: \"12\"\n  STR_DAMAGE_13: \"13\"\n  STR_DAMAGE_14: \"14\"\n  STR_DAMAGE_15: \"15\"\n  STR_DAMAGE_16: \"16\"\n  STR_DAMAGE_17: \"17\"\n  STR_DAMAGE_18: \"18\"\n  STR_DAMAGE_19: \"19\"\n  STR_NAUTICAL_MILES: \"{0} námořních mil\"\n  STR_KILOMETERS_PER_HOUR: \"{0} km/h\"\n  STR_SECONDS_LONG: \"{0} sekund\"\n  STR_RACE_BONUS: \"Bonus za rasu\"\n  STR_FOR_DIFFICULTY: \"za obtížnost: {0}\"\n  STR_NOT_AWARDED_YET: \"Zatím bez vyznamenání\"\n"
  },
  {
    "path": "bin/common/Language/OXCE/de.yml",
    "content": "de:\n  STR_CANNOT_DISMANTLE_FACILITY_UPGRADING: \"DEMONTAGE NICHT MÖGLICH!{SMALLLINE}Einrichtung kann nicht während eines Umbaus demontiert werden.\"\n  STR_CANNOT_UPGRADE_FACILITY_ALREADY_UPGRADING: \"BAU HIER NICHT MÖGLICH!{SMALLLINE}Vorhandene Einrichtung wird bereits umgebaut.\"\n  STR_CANNOT_UPGRADE_FACILITY_WRONG_SIZE: \"BAU HIER NICHT MÖGLICH!{SMALLLINE}Ausgewählte Einrichtung muss die vorhandene Einrichtung komplett bedecken.\"\n  STR_CANNOT_UPGRADE_FACILITY_WRONG_TYPE: \"BAU HIER NICHT MÖGLICH!{SMALLLINE}Vorhandene Einrichtung kann nicht durch gewählte Einrichtung ersetzt werden.\"\n  STR_CANNOT_UPGRADE_FACILITY_DISALLOWED: \"BAU HIER NICHT MÖGLICH!{SMALLLINE}Vorhandene Einrichtung kann nicht ersetzt werden.\"\n  STR_CANNOT_BUILD_QUEUE_OFF: \"BAU HIER NICHT MÖGLICH!{SMALLLINE}Bau verbundener Einrichtung muss erst abgeschlossen werden.\"\n  STR_FACILITY_FORBIDDEN_BY_OTHER: \"BAU HIER NICHT MÖGLICH!{SMALLLINE}Eine bestehende Einrichtung verhindert den Bau dieser Einrichtung.\"\n  STR_FACILITY_OTHER_FORBIDDEN_BY_THIS: \"BAU HIER NICHT MÖGLICH!{SMALLLINE}Eine bestehende Einrichtung würde durch diese Einrichtung verhindert werden.\"\n  STR_NOT_ENOUGH_ITEMS: \"NICHT GENUG MATERIALIEN!{SMALLLINE}Wir brauchen mehr Materialien, um diese Einrichtung zu bauen.{NEWLINE}Fehlend> {0}: {1}\"\n  STR_ID: \"ID\"\n  STR_FIRST_LETTER: \"ANFANGSBUCHSTABE\"\n  STR_SOLDIER_TYPE: \"SOLDATEN-TYP\"\n  STR_IDLE_DAYS: \"UNTÄTIGE TAGE\"\n  STR_MANA: \"MANA\"\n  STR_MANA_POOL: \"MANAVORRAT\"\n  STR_MANA_MISSING: \"KEIN MANA\"\n  STR_LOAD_CRAFT_LOADOUT_TEMPLATE: \"Fahrzeugausrüstung laden\"\n  STR_EMPTY_SLOT_N: \"Leerer Platz {0}\"\n  STR_UNNAMED_SLOT_N: \"Unbenannter Platz {0}\"\n  STR_ADD_ON_TOP: \"Hinzufügen\"\n  STR_SAVE_CRAFT_LOADOUT_TEMPLATE: \"Fahrzeugausrüstung speichern\"\n  STR_SAVE_UC: \"SPEICHERN\"\n  STR_ALL: \"Alles\"\n  STR_EQUIPPED: \"Ausgerüstet\"\n  STR_NOT_EQUIPPED: \"Nicht ausgerüstet\"\n  STR_UNASSIGNED: \"Sonstige\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED_BY_SIZE: \"KEINE WEITERE AUSRÜSTUNG MEHR AN BORD ERLAUBT!{SMALLLINE}Maximaler Stauraum: {0}\"\n  STR_PILOTS: \"PILOTEN\"\n  STR_SHIELD: \"SCHILD>{ALT}{0}\"\n  STR_CRAFT_SKIN_ID: \"[{0}]\"\n  STR_SELECT_PILOT: \"Piloten auswählen\"\n  STR_PILOTS_FOR_CRAFT: \"Pilot(en) für {0}\"\n  STR_PILOTS_REQUIRED: \"Pilot(en) benötigt: {ALT}{0}\"\n  STR_ADD_PILOT: \"Pilot hinzufügen\"\n  STR_REMOVE_ALL_PILOTS: \"Alle Piloten entfernen\"\n  STR_ACCURACY_BONUS: \"Trefferbonus:\"\n  STR_DODGE_BONUS: \"Ausweichbonus:\"\n  STR_APPROACH_SPEED: \"Annäherungsgeschwindigkeit:\"\n  STR_COWARDLY: \"Feige (-50%)\"\n  STR_NORMAL: \"Normal\"\n  STR_BOLD: \"Mutig (+50%)\"\n  STR_VERY_BOLD: \"Sehr mutig (+100%)\"\n  STR_SOLDIER_GROUP_NOT_ALLOWED: \"Dieser Soldatentyp ist an Bord nicht erlaubt.\"\n  STR_SOLDIER_GROUP_NOT_SAME: \"Dieser Soldatentyp ist nicht mit anderen Soldaten an Bord kombinierbar.\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW: \"Vorschau\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_SAVED: \"Vorschau *\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_BRIEFING: \"Hier können Sie die Aufstellung Ihrer Einheiten zu Beginn einer Schlacht in der Vorschau anzeigen und anpassen. Sie haben unbegrenzte Bewegungsfreiheit. Halten Sie die 'Alt'-Taste gedrückt, um gültige Einheitenpositionen anzuzeigen. Klicken Sie auf das Symbol 'Mission abbrechen', um die aktuelle Aufstellung zu speichern. Klicken Sie auf das Symbol 'Runde beenden', um die Vorschau zu beenden. {NEWLINE}Beachten Sie, dass das Hinzufügen neuer Einheiten zum Fahrzeug die gespeicherte Aufstellung ungültig macht. Das Vorhandensein einer benutzerdefinierten Aufstellung wird durch ein '*' auf der Schaltfläche 'Vorschau' angezeigt.\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_BRIEFING_DUMMY: \"Mit dieser Funktion können Sie die Einsatztabelle dieses Fahrzeugtyps in der Vorschau anzeigen und ändern. Alle Änderungen gelten für alle Ihre aktuellen Schiffe und auch für alle Schiffe, die Sie später in der Kampagne kaufen oder herstellen. Sie beginnen mit der maximalen Anzahl von Soldaten. Jeder Soldat steht für eine Zeile in der Einsatztabelle. Die Soldatennamen entsprechen den Zeilennummern. Um Platz für eine 2x2-Einheit zu schaffen, stellt man 4 Soldaten in ein 2x2-Quadrat. Wenn kein Platz vorhanden ist, wird die 2x2-Einheit in einer echten Schlacht fehlen.\"\n  STR_BASE_DEFENSE_BRIEFING_PREVIEW: \"Mit dieser Funktion können Sie eine Vorschau Ihrer Basis erstellen.{NEWLINE}\\nViel Spaß!{NEWLINE}{NEWLINE}\\nKlicken Sie auf das Symbol „Runde beenden“, um die Vorschau zu beenden.\"\n  STR_NOT_ENOUGH_CARGO_SPACE: \"NICHT GENÜGEND LADERAUM VORHANDEN!{SMALLLINE}Verwenden Sie ein anderes Transportfahrzeug oder reduzieren Sie die zugewiesene Besatzung.\"\n  STR_NOT_ENOUGH_STORAGE_SPACE_1: \"NICHT GENÜGEND LAGERRAUM VORHANDEN!{SMALLLINE}Zu viele Gegenstände! Verwenden Sie ein anderes Transportfahrzeug oder reduzieren Sie die zugewiesene Ausrüstung.\"\n  STR_NOT_ENOUGH_STORAGE_SPACE_2: \"NICHT GENÜGEND LAGERRAUM VORHANDEN!{SMALLLINE}Die Gegenstände nehmen zu viel Platz ein! Verwenden Sie ein anderes Fahrzeug oder verringern Sie die Größe der zugewiesenen Ausrüstung.\"\n  STR_REFUND_VALUE: \"Verkaufswert> {ALT}{0}\"\n  STR_PRODUCTION_OVERVIEW: \"Produktionsübersicht\"\n  STR_RESEARCH_OVERVIEW: \"FORSCHUNGSÜBERSICHT\"\n  STR_PRISONER_OVERVIEW: \"HÄFTLINGSÜBERSICHT\"\n  STR_PRISONER: \"HÄFTLING\"\n  STR_PRISONER_AMOUNT: \"MENGE\"\n  STR_PRISONER_INTERROGATED: \"VERHÖRT\"\n  STR_TOTAL_IN_PRISON: \"Platz genutzt>{ALT}{0}\"\n  STR_TOTAL_INTERROGATED: \"Verhört>{ALT}{0}\"\n  STR_PRISON_TYPE: \"Außerirdischen-Klimazelle\"\n  STR_KILL_SELECTED: \"Töten\"\n  STR_SELL_SELECTED: \"Verkaufen\"\n  STR_GO_TO_TRANSFERS: \"Transfer...\"\n  STR_PRISON_CLEANUP: \"Gefängnisbereinigung\"\n  STR_TOPIC: \"Objekt>{ALT} {0}\"\n  STR_SHOW_ALL: \"Alle anzeigen\"\n  STR_NO_DEPENDENCIES: \"Keine Abhängigkeiten.\"\n  STR_DIRECT_DEPENDENCIES: \"Direkte Abhängigkeiten\"\n  STR_LEVEL_2_DEPENDENCIES: \"Level 2 Abhängigkeiten\"\n  STR_LEVEL_3_DEPENDENCIES: \"Level 3 Abhängigkeiten\"\n  STR_LEVEL_4_DEPENDENCIES: \"Level 4 Abhängigkeiten\"\n  STR_MORE_DEPENDENCIES: \"Es gibt noch entferntere Abhängigkeiten...\"\n  STR_END_OF_SEARCH: \"Ende der Suche.\"\n  STR_REFUND_PRODUCTION: \"ERSTATTEN!\"\n  STR_HOURS_PER_UNIT: \"STUNDEN PRO EINHEIT>{ALT}{0}\"\n  STR_PERSON_JOINING: \"Person rekrutiert\"\n  STR_RANDOM_PRODUCTION_DISCLAIMER: \"Zufällige Produktion!\"\n  STR_OTHER_EMPLOYEES: \"Sonst. Personal/Inventar\"\n  STR_SHOW_ONLY_NEW: \"Nur Neues anzeigen\"\n  STR_FILTER_DEFAULT: \"Standard\"\n  STR_FILTER_DEFAULT_SUPPLIES_OK: \"Standard (Material vorh.)\"\n  STR_FILTER_DEFAULT_NO_SUPPLIES: \"Standard (Kein Material)\"\n  STR_FILTER_FACILITY_REQUIRED: \"Fehlende Einrichtung\"\n  STR_FILTER_HIDDEN: \"Versteckt\"\n  STR_FILTER_EQUIPPED: \"Ausgerüstet\"\n  STR_FILTER_MISSING: \"Vermisst\"\n  STR_SORT_DEFAULT: \"Standard\"\n  STR_SORT_BY_COST: \"Nach Kosten\"\n  STR_SORT_BY_NAME: \"Nach Name\"\n  STR_RANDOM_PRODUCTION_SUMMARY: \"Gesamt\"\n  STR_NOT_ENOUGH_PRISON_SPACE: \"NICHT GENUG KLIMAZELLEN!{SMALLLINE}Baue weitere Außerirdischen-Klimazellen oder transferiere Außerirdische zu einem anderen Stützpunkt.\"\n  STR_MONTHLY_ITEM_PURCHASE_LIMIT_EXCEEDED: \"MONATLICHES KAUFLIMIT ÜBERSTIEGEN {SMALLLINE}Weitere Artikel werden nächsten Monat verfügbar sein.\"\n  STR_MONTHLY_CRAFT_PURCHASE_LIMIT_EXCEEDED: \"MONATLICHES KAUFLIMIT ÜBERSTIEGEN {SMALLLINE}Weitere Fahrzeuge werden nächsten Monat verfügbar sein.\"\n  STR_MONTHLY_SOLDIER_HIRING_LIMIT_EXCEEDED: \"MONATLICHES EINSTELLUNGSLIMIT ÜBERSCHRITTEN!{SMALLLINE}Nächsten Monat werden weitere Bewerber zur Verfügung stehen.\"\n  STR_NOT_ENOUGH_CRAFT_SPACE: \"Nicht genug Platz!\"\n  STR_SELECT_AVATAR_FOR: \"WÄHLE AVATAR FÜR{NEWLINE}{0}\"\n  STR_SOLDIER_BONUSES_FOR: \"Soldatenbonus für {NEWLINE}{0}\"\n  STR_SUMMARY: \"Gesamt\"\n  STR_MANA_RECOVERY: \"MANA-WIEDERHERSTELLUNG> {ALT}{0}\"\n  STR_HEALTH_RECOVERY: \"Gesundheitswiederherstellung> {ALT}{0}\"\n  STR_BONUSES_BUTTON: \"+\"\n  STR_PROMOTE_SOLDIER: \"BEFÖRDERN/DEGRADIEREN{NEWLINE}{0} {1}\"\n  STR_RANK_HEADER: \"RANG\"\n  STR_OPENINGS_HEADER: \"ERÖFFNUNGEN\"\n  STR_KILLER_AND_WEAPON: \"{0}, {1}\"\n  STR_TRAINING: \"Training\"\n  STR_SOLDIER_INFO: \"Soldateninfo\"\n  STR_SELECT_TRANSFORMATION_FOR: \"WÄHLEN SIE EINE UMWANDLUNG FÜR{NEWLINE}{0}\"\n  STR_TRANSFORMATIONS_BUTTON: \"^\"\n  STR_TRANSFER_TIME: \"Transferzeit>{ALT}{0}\"\n  STR_RECOVERY_TIME: \"Erholungszeit>{ALT}{0}\"\n  STR_CURRENT_STATS: \"Aktuelle Werte\"\n  STR_CHANGES: \"Änderungen\"\n  STR_CHANGES_MIN: \"Änderungen (Min)\"\n  STR_CHANGES_MAX: \"Änderungen (Max)\"\n  STR_BONUS_STATS: \"Bonus Statistik\"\n  STR_TRANSFORMATIONS_OVERVIEW: \"Übersicht Umwandlungen\"\n  STR_PROJECT_NAME: \"PROJEKTNAME\"\n  STR_AVAILABLE_MATERIALS: \"VERFÜGBARE MATERIALIEN\"\n  STR_ELIGIBLE_SOLDIERS: \"TAUGLICHE SOLDATEN\"\n  STR_SHOW_ONLY_ELIGIBLE: \"Zeige nur taugliche\"\n  STR_ALL_SOLDIER_TYPES: \"Alle Soldatentypen\"\n  STR_ALL_SOLDIERS: \"Alle Soldaten\"\n  STR_HEALTHY_SOLDIERS: \"Gesunde Soldaten\"\n  STR_WOUNDED_SOLDIERS: \"Verletze Soldaten\"\n  STR_DEAD_SOLDIERS: \"Tote Soldaten\"\n  STR_GRAND_TOTAL: \"Gesamtsumme\"\n  STR_AVAILABLE_TOPICS: \"VERFÜGBARE THEMEN\"\n  STR_QS_THREE_LETTERS_A: \"Bitte mindestens 3 Buchstaben\"\n  STR_QS_THREE_LETTERS_B: \"in die Schnellsuche eingeben...\"\n  STR_M_FLAG: \" [m]\"\n  STR_F_FLAG: \" [f]\"\n  STR_I_FLAG: \" [i]\"\n  STR_C_FLAG: \" [c]\"\n  STR_THIS_FEATURE_IS_DISABLED_1: \"Diese Funktion ist deaktiviert.\"\n  STR_THIS_FEATURE_IS_DISABLED_2: \"Diese Funktion ist deaktiviert.\"\n  STR_THIS_FEATURE_IS_DISABLED_3: \"Diese Funktion ist deaktiviert.\"\n  STR_THIS_FEATURE_IS_DISABLED_4: \"Diese Funktion ist deaktiviert.\"\n  STR_THIS_FEATURE_IS_DISABLED_5: \"Diese Funktion ist deaktiviert.\"\n  STR_TECH_TREE_VIEWER: \"Forschungsbaum Ansicht\"\n  STR_SELECT_TOPIC: \"Wähle Thema\"\n  STR_RESEARCH_PROGRESS: \"Fortschritt>{ALT} {0}%\"\n  STR_ITEM_DESTROYED: \"Gegenstand zerstört:\"\n  STR_ITEM_REQUIRED: \"Gegenstand benötigt:\"\n  STR_SERVICES_REQUIRED: \"Dienstleistungen benötigt:\"\n  STR_SERVICES_PROVIDED: \"Dienstleistungen angeboten:\"\n  STR_SERVICES_FORBIDDEN: \"Dienstleistungen verboten:\"\n  STR_REQUIRES: \"Benötigt:\"\n  STR_DEPENDS_ON: \"Abhängig von:\"\n  STR_UNLOCKED_BY: \"Freigeschaltet durch:\"\n  STR_DISABLED_BY: \"Deaktiviert durch:\"\n  STR_REENABLED_BY: \"Wiederfreigabe durch:\"\n  STR_GET_FOR_FREE_FROM: \"Frei erhältlich von:\"\n  STR_IS_LOOKUP_OF: \"Im Visier von:\"\n  STR_LOOKUP: \"Visier:\"\n  STR_SPAWNED_ITEMS: \"Hergestellte Gegenstände:\"\n  STR_SPAWNED_EVENT: \"Ausgelöstes Ereignis:\"\n  STR_REQUIRED_BY: \"Benötigt von:\"\n  STR_REQUIRED_BY_TRANSFORMATIONS: \"Erforderlich für Umwandlungen:\"\n  STR_LEADS_TO: \"Führt zu:\"\n  STR_UNLOCKS: \"Schaltet frei:\"\n  STR_DISABLES: \"Deaktiviert:\"\n  STR_REENABLES: \"Wieder aktivieren:\"\n  STR_GIVES_ONE_FOR_FREE_SEQ: \"Erhalte eine umsonst (der Reihe nach):\"\n  STR_GIVES_ONE_FOR_FREE: \"Erhalte eine umsonst:\"\n  STR_RESEARCH_REQUIRED: \"Forschung benötigt:\"\n  STR_RESEARCH_REQUIRED_USE: \"Forschung benötigt (benutzen):\"\n  STR_RESEARCH_REQUIRED_BUY: \"Forschung benötigt (kaufen):\"\n  STR_SERVICES_REQUIRED_BUY: \"Dienstleistungen benötigt (kaufen):\"\n  STR_PRODUCED_BY: \"Hergestellt von:\"\n  STR_SPAWNED_BY: \"Ausgelöst durch:\"\n  STR_MATERIALS_REQUIRED: \"Material benötigt:\"\n  STR_TTV_COST_PER_UNIT: \"Kosten pro Einheit:\"\n  STR_TTV_ENGINEER_HOURS: \"Ingenieur Stunden:\"\n  STR_TTV_WORK_SPACE_REQUIRED: \"Benötigter Werkstattraum:\"\n  STR_ITEMS_PRODUCED: \"Gegenstand hergestellt:\"\n  STR_PERSON_RECRUITED: \"Person rekrutiert:\"\n  STR_UNLOCKS_ARCS: \"Schaltet Bögen frei:\"\n  STR_DISABLES_ARCS: \"Deaktiviert Bögen:\"\n  STR_UNLOCKS_MISSIONS: \"Schalte Missionen frei\"\n  STR_DISABLES_MISSIONS: \"Deaktiviere Missionen:\"\n  STR_UNLOCKS_EVENTS: \"Schalte Events frei\"\n  STR_DISABLES_EVENTS: \"Deaktiviere Events\"\n  STR_AFFECTS_GAME_PROGRESSION: \"Betrifft Spielfortschritt\"\n  STR_ITEMS_AT_DESTINATION: \"Gegenstände am Ziel\"\n  STR_PRISONERS: \"Häftlinge\"\n  STR_ARMORS: \"Rüstungen\"\n  STR_CRAFT_DEPLOYMENT_QUESTION: \"Aufstellung speichern?\"\n  STR_MUST_USE_BOTH_HANDS: \"Es werden beide Hände benötigt!\"\n  STR_NOT_ENOUGH_MORALE: \"Nicht genug Moral!\"\n  STR_NOT_ENOUGH_HEALTH: \"Nicht genug Gesundheit!\"\n  STR_NOT_ENOUGH_MANA: \"Nicht genug Mana!\"\n  STR_NOT_ENOUGH_STUN: \"Betäubung zu hoch!\"\n  STR_MIND_CONTROL_SUCCESSFUL_ALT: \"Aktion erfolgreich\"\n  STR_LINE_OF_SIGHT_REQUIRED: \"Sichtlinie (LoS) benötigt.\"\n  STR_CENTER_ON_WOUNDED_FRIEND: \"Auf verwundeten Freund zentrieren\"\n  STR_CENTER_ON_DIZZY_FRIEND: \"Zentriere auf verwirrten Freund\"\n  STR_BUG_HUNT_ACTIVATED: \"Bug Hunt Modus aktiviert: Gegner sind auf der Minikarte sichtbar!\"\n  STR_TARGET_ENEMY: \"; Ziel = GEGNER\"\n  STR_TARGET_NEUTRAL: \"; Ziel = NEUTRAL\"\n  STR_TARGET_FRIEND: \"; Ziel = FREUND\"\n  STR_TARGET_YOURSELF: \"; Ziel = SELBST\"\n  STR_TARGET_ON_THE_GROUND: \" (Auf dem Boden)\"\n  STR_USE_SPECIAL_ITEM: \"Spezialgegenstand benutzen\"\n  STR_NO_EXPERIENCE_YET: \"Bisher keine Erfahrung erhalten:\"\n  STR_OPERATION_UC: \"OPERATION> {0}\"\n  STR_WHAT_CAN_I_WEAR: \"Was kann ich tragen?\"\n  STR_STARTING_CONDITION_ARMORS_FORBIDDEN: \"Diese Mission benötigt besondere Ausrüstung. {NEWLINE}{NEWLINE}Verbotene Rüstungstypen sind: {0}\"\n  STR_STARTING_CONDITION_ARMORS_ALLOWED: \"Diese Mission erfordert eine bestimmte Ausrüstung.{NEWLINE}{NEWLINE}Erlaubte Rüstungsarten sind: {0}\"\n  STR_MISSION_OVER: \"Mission beendet.\"\n  STR_UNITS_WITH_FATAL_WOUNDS:\n    one: \"{N} von uns ist noch schwer verwundet\"\n    other: \"{N} von uns sind noch schwer verwundet\"\n  STR_END_MISSION_QUESTION: \"Mission beenden?\"\n  STR_LOOT: \"BEUTE\"\n  STR_SELL: \"VERKAUFEN\"\n  STR_LIVE_ALIENS_SURRENDERED: \"KAPITULIERENDE GEGNER\"\n  STR_MISSION_ABORTED: \"Mission abgebrochen\"\n  STR_VIPS_SAVED: \"VIPS gerettet\"\n  STR_VIPS_LOST: \"VIPS verloren\"\n  STR_BOUNTY: \"KOPFGELD\"\n  STR_MANA_ABBREVIATION: \"MANN\"\n  STR_CANNOT_PLACE_ITEM_INTO_THIS_SECTION: \"Es ist nicht erlaubt den Gegenstand hier abzulegen.{NEWLINE}Frag nicht warum!\"\n  STR_ONE_HAND_MUST_BE_EMPTY: \"Mindestens eine Hand muss frei sein!\"\n  STR_LOAD_EQUIPMENT_TEMPLATE: \"Ausrüstungsvorlage laden\"\n  STR_SAVE_EQUIPMENT_TEMPLATE: \"Ausrüstungsvorlage speichern\"\n  STR_FIRING_SHORT: \"Schu.>{ALT}{0}\"\n  STR_THROWING_SHORT: \"Wurf.>{ALT}{0}\"\n  STR_MELEE_SHORT: \"Nahk.>{ALT}{0}\"\n  STR_PERSONAL_EQUIPMENT: \"Persönliche Ausrüstung\"\n  STR_SAVE_PERSONAL_EQUIPMENT: \"Speichere persönliche Ausrüstung\"\n  STR_LOAD_PERSONAL_EQUIPMENT: \"Lade persönliche Ausrüstung\"\n  STR_PERSONAL_EQUIPMENT_SAVED: \"Persönliche Ausrüstung gespeichert\"\n  STR_SLOT: \"Platz>{ALT}{0}\"\n  STR_THINKING: \"Nachdenken...\"\n  STR_TELL_ME_MORE: \"Erzähl mir mehr...\"\n  STR_REINFORCEMENTS_ALERT: \"Achtung, Verstärkung!\"\n  STR_HIT_LOG_NEW_TURN: \"Neue Runde\"\n  STR_FAILED_CQB_CHECK: \"Gegner hat deinen Angriff unterbrochen!\"\n  STR_NO_TRAJECTORY: \"Keine mögliche Flugbahn!\"\n  STR_HIT_LOG_NEW_BULLET: \"=> \"\n  STR_MANA_SHORT: \"MA>{ALT}{0}\"\n  STR_SKILL_NEEDS_ITEM: \"Diese Fertigkeit benötigt einen Gegenstand\"\n  STR_HIT_LOG_NO_DAMAGE: \"0 \"\n  STR_HIT_LOG_SMALL_DAMAGE: \"Treffer\"\n  STR_HIT_LOG_BIG_DAMAGE: \"TREFFER\"\n  STR_HIT_LOG_REACTION_FIRE: \"Reaktionsfeuer...\"\n  STR_HIT_LOG: \"Treffer-Log\"\n  STR_BUTTON_10: \"10\"\n  STR_LAZY_LOADING: \"Träges Laden\"\n  STR_LAZY_LOADING_DESC: \"Wenn aktiviert, werden Grafikressourcen bei Bedarf geladen. Ansonsten werden sie beim Starten geladen.\"\n  STR_VSYNC_FOR_OPENGL: \"VSync for OpenGL\"\n  STR_VSYNC_FOR_OPENGL_DESC: \"Ausschalten für maximale feindliche verborgene Bewegungsgeschwindigkeit und (optional) Soldaten Bewegungsgeschwindigkeit. Setze nicht das FPS Limit auf 0. Betriff nur OpenGL rendering\"\n  STR_UPDATE_CHECK: \"Automatische Update-Überprüfung\"\n  STR_UPDATE_CHECK_DESC: \"Wenn aktiviert, überprüft OpenXcom automatisch nach neuen Updates und gewährt die Option ein Update durchzuführen mit einem Mausklick.\"\n  STR_AUTOSAVE_SLOTS: \"Automatische Speicherplätze\"\n  STR_AUTOSAVE_SLOTS_DESC: \"Anzahl der Slots für Battlescape-Autosaves.\"\n  STR_AUTO_SAVE_BATTLESCAPE_SLOT_WITH_NUMBER: \" {0}\"\n  STR_GEO_AUTOSAVE_FREQUENCY: \"Auto-Speichern Häufigkeit (Weltkarte)\"\n  STR_GEO_AUTOSAVE_FREQUENCY_DESC: \"Anzahl der Tage, nach denen das Spiel automatisch gespeichert wird.\"\n  STR_GEO_AUTOSAVE_SLOTS: \"Auto-Speicherplätze (Weltkarte)\"\n  STR_GEO_AUTOSAVE_SLOTS_DESC: \"Anzahl der Auto-Speicherplätze in der Weltkartenansicht.\"\n  STR_AUTO_SAVE_GEOSCAPE_SLOT_WITH_NUMBER: \"<AUTO GEOSCAPE> {0}\"\n  STR_OXCE_LINKS: \"Weiterführende Verknüpfungen\"\n  STR_OXCE_LINKS_DESC: \"Ermöglicht zusätzliche Menüs/Schaltflächen/Verknüpfungen für OXCE-Funktionen.\"\n  STR_PEDIA_SHOW_CLIP_SIZE: \"Magazingröße in Ufopedia anzeigen\"\n  STR_PEDIA_SHOW_CLIP_SIZE_DESC: \"Wenn diese Option aktiviert ist, wird die Kapazität der Munitionsmagazine neben den Munitionssymbolen in der Ufopedia angezeigt.\"\n  STR_INTERCEPT_TABLE_SIZE: \"Größe der Abfangtabelle\"\n  STR_INTERCEPT_TABLE_SIZE_DESC: \"Größe der Tabellen in den folgenden Dialogfenstern: Abfangen, UFO- Verfolgung.\"\n  STR_SHOW_SLACKING_INDICATOR: \"Untätigkeitsindikator anzeigen\"\n  STR_SHOW_SLACKING_INDICATOR_DESC: \"Falls aktiviert, wird die Anzahl der nicht zugewiesenen Wissenschaftler und Ingenieure angezeigt.\"\n  STR_SHOW_MAINTENANCE_TIME: \"Fahrzeugwartungszeit anzeigen\"\n  STR_SHOW_MAINTENANCE_TIME_DESC: \"{ALT}0>{ALT} Nicht anzeigen {ALT}1>{ALT} Nur aktuelle Aktivitätsdauer anzeigen {ALT}2>{ALT} Alles zusammen anzeigen (Reparieren + Aufrüsten + Tanken).\"\n  STR_SHOW_ETA: \"Voraussichtliche Flugdauer anzeigen\"\n  STR_SHOW_ETA_DESC: \"{ALT}0>{ALT} Nicht anzeigen {ALT}1>{ALT} ETA nur für statische Ziele anzeigen {ALT}2>{ALT} ETA auch für bewegliche Ziele anzeigen.\"\n  STR_UFO_LANDING_ALERT: \"UFO gelandet Alarm\"\n  STR_UFO_LANDING_ALERT_DESC: \"Wenn aktiviert wird eine Nachricht angezeigt wenn ein erfasstes UFO landet.\"\n  STR_REMEMBER_DISABLED_CRAFT_WEAPONS: \"Speicher deaktivierte Schiffs-Waffen\"\n  STR_REMEMBER_DISABLED_CRAFT_WEAPONS_DESC: \"Fahrzeugwaffen, die während eines Nahkampfes deaktiviert werden, bleiben deaktiviert. Sie können auch nicht in der Basis wieder bewaffnet werden.\"\n  STR_GEO_EVENT_INSTANT_DELIVERY: \"Sofortige Zustellung von Gegenständen bei Veranstaltungen\"\n  STR_GEO_EVENT_INSTANT_DELIVERY_DESC: \"Wenn diese Option aktiviert ist, werden Gegenstände aus Weltkarten-Ereignissen sofort geliefert. Andernfalls kommen sie 1 Stunde später an.\"\n  STR_SHOW_BASE_NAME_IN_POPUPS: \"Basisnamen in PopUp-Fenstern anzeigen\"\n  STR_SHOW_BASE_NAME_IN_POPUPS_DESC: \"Wenn diese Option aktiviert ist, wird der entsprechende Basisname in PopUp-Fenstern angezeigt (z. B. „Forschung abgeschlossen“).\"\n  STR_ALTERNATE_CRAFT_EQUIPMENT_MANAGEMENT: \"Alternative Verwaltung der Fahrzeugausrüstung\"\n  STR_ALTERNATE_CRAFT_EQUIPMENT_MANAGEMENT_DESC: \"Wenn diese Funktion aktiviert ist, wird bei der Verlegung von Soldaten zwischen einem Stützpunkt und einem Raumschiff auch deren Ausrüstung verschoben (sofern möglich).\"\n  STR_BASE_INFO_SCALE: \"Große Balken in der Basisinfo skalieren\"\n  STR_BASE_INFO_SCALE_DESC: \"Wenn diese Option aktiviert ist, werden Balken, die größer als 140 sind, verkleinert, damit sie in der Benutzeroberfläche dargestellt werden können.\"\n  STR_HIGHLIGHT_NEW: \"Neue Inhalte hervorheben\"\n  STR_HIGHLIGHT_NEW_DESC: \"Wenn diese Option aktiviert ist, werden neue Forschungs/- Herstellungprojekte sowie neue Ufopedia-Artikel in verschiedenen Farben angezeigt.\"\n  STR_RESEARCH_SCROLL_SPEED: \"Scrolltaste bei Forschungsprojekten\"\n  STR_RESEARCH_SCROLL_SPEED_DESC: \"Wissenschaftler können direkt in der Benutzeroberfläche „Aktuelle Forschung“ mit der Scrolltaste der Maus ab- und zugewiesen werden.\"\n  STR_RESEARCH_SCROLL_SPEED_CTRL: \"Scrolltaste bei Forschungsprojekten (mit Ctrl)\"\n  STR_RESEARCH_SCROLL_SPEED_CTRL_DESC: \"Wissenschaftler können direkt in der Benutzeroberfläche „Aktuelle Forschung“ mit der Scrolltaste der Maus ab- und zugewiesen werden.\"\n  STR_MANUFACTURE_FILTER_SUPPLIES_OK: \"Alternativer Filter in der Produktion\"\n  STR_MANUFACTURE_FILTER_SUPPLIES_OK_DESC: \"Wenn diese Option aktiviert ist, zeigt die Benutzeroberfläche nur Produktionsartikel an, für die genügend Materialien vorhanden sind.\"\n  STR_MANUFACTURE_SCROLL_SPEED: \"Scrolltaste bei der Herstellung\"\n  STR_MANUFACTURE_SCROLL_SPEED_DESC: \"Ingenieure können direkt in der Benutzeroberfläche „Aktuelle Herstellung“ mit der Scrolltaste der Maus ab- und zugewiesen werden.\"\n  STR_MANUFACTURE_SCROLL_SPEED_CTRL: \"Scrolltaste bei Forschungsprojekten (mit Ctrl)\"\n  STR_MANUFACTURE_SCROLL_SPEED_CTRL_DESC: \"Ingenieure können direkt in der Benutzeroberfläche „Aktuelle Herstellung“ mit der Scrolltaste der Maus ab- und zugewiesen werden.\"\n  STR_PERSONAL_LAYOUT_INCLUDING_ARMOR: \"Rüstungen in die persönliche Ausrüstung einbeziehen\"\n  STR_PERSONAL_LAYOUT_INCLUDING_ARMOR_DESC: \"Wenn aktiviert, wird das Layout der persönlichen Ausrüstung des Soldaten einschließlich der getragenen Rüstung gespeichert.\"\n  STR_MANUALPROMOTIONS: \"Manuelle Beförderungen\"\n  STR_MANUALPROMOTIONS_DESC: \"Wenn aktiviert, können Soldaten manuell befördert (oder degradiert) werden, indem Sie auf das Rangsymbol klicken.\"\n  STR_WOUNDED_DEFEND_BASE_IF: \"Verwundete verteidigen (TP über x%)\"\n  STR_WOUNDED_DEFEND_BASE_IF_DESC: \"Verwundete Soldaten verteidigen die Basis wenn ihre Gesundheit über dem angegebenen Wert liegt.\"\n  STR_PLAY_BRIEFING_MUSIC_DURING_EQUIPMENT: \"Einsatzbesprechungsmusik spielt länger\"\n  STR_PLAY_BRIEFING_MUSIC_DURING_EQUIPMENT_DESC: \"Einsatzbesprechungsmusik spielt in der Ausrüstungsphase weiter bis der Kampf beginnt.\"\n  STR_NIGHT_VISION_COLOR: \"Nachtsichtfarbe\"\n  STR_NIGHT_VISION_COLOR_DESC: \"Die Werte von 1 bis 15 ergeben unterschiedliche Farbschattierungen.\"\n  STR_AUTO_NIGHT_VISION_THRESHOLD: \"Automatische Nachtsichtschwelle\"\n  STR_AUTO_NIGHT_VISION_THRESHOLD_DESC: \"Wenn es dunkler als dieser Schwellenwert ist, wird die Nachtsicht automatisch eingeschaltet.\"\n  STR_SHOW_ACCURACY_ON_CROSSHAIR: \"Genauigkeit im Fadenkreuz anzeigen\"\n  STR_SHOW_ACCURACY_ON_CROSSHAIR_DESC: \"{ALT}0>{ALT}Nie {ALT}1>{ALT}Nur wenn UFO Extender-Genauigkeit aktiviert ist {ALT}2>{ALT}Immer\"\n  STR_AUTO_SELL: \"Auto-Verkauf Manager\"\n  STR_AUTO_SELL_DESC: \"Im Verkaufsbildschirm der Nachbesprechung werden verkaufte Gegenstände der vorherigen Missionen automatisch zum Verkauf markiert.\"\n  STR_AUTOMATICPROMOTIONS: \"Automatische Beförderungen\"\n  STR_AUTOMATICPROMOTIONS_DESC: \"Wenn diese Funktion aktiviert ist, werden Soldaten nach einem Einsatz automatisch befördert.\"\n  STR_OFF_CENTRE_SHOOTING: \"Außermittiges Schießen\"\n  STR_OFF_CENTRE_SHOOTING_DESC: \"Die Soldaten werden automatisch versuchen, den Schusswinkel geringfügig zu verändern, wenn keine Schusslinie vorhanden ist.\"\n  STR_GRAPHS_ZOOM_IN: \"Reinzoomen (Diagramme)\"\n  STR_GRAPHS_ZOOM_OUT: \"Rauszoomen (Diagramme)\"\n  STR_MARK_ALL_AS_SEEN: \"Alles als gelesen markieren\"\n  STR_SELL_ALL: \"Verkaufe alles\"\n  STR_SELL_ALL_BUT_ONE: \"Verkaufe alles bis auf ein Stück\"\n  STR_TRANSFER_ALL: \"Alles transferieren\"\n  STR_REMOVE_SOLDIERS_FROM_ALL_CRAFTS: \"Entferne Soldaten von allen Fahrzeugen\"\n  STR_REMOVE_SOLDIERS_FROM_CRAFT: \"Entferne Soldaten vom Fahrzeug\"\n  STR_REMOVE_EQUIPMENT_FROM_CRAFT: \"Entferne Ausrüstung vom Fahrzeug\"\n  STR_REMOVE_ARMOR_FROM_ALL_CRAFTS: \"Entferne Rüstung von allen Fahrzeugen\"\n  STR_REMOVE_ARMOR_FROM_CRAFT: \"Entferne Rüstung vom Fahrzeug\"\n  STR_REMOVE_SOLDIERS_FROM_TRAINING: \"Entferne Soldaten vom Training\"\n  STR_ADD_SOLDIERS_TO_TRAINING: \"Soldaten zur Ausbildung hinzufügen\"\n  STR_INVENTORY_ARMOR: \"Rüstung wechseln\"\n  STR_INVENTORY_AVATAR: \"Avatar ändern\"\n  STR_ACTION_ITEM_1: \"Gegenstandsaktion 1 (Zielschuss/Benutzen)\"\n  STR_ACTION_ITEM_2: \"Gegenstandsaktion 2 (Schnellschuss)\"\n  STR_ACTION_ITEM_3: \"Gegenstandsaktion 3 (Autoschuss)\"\n  STR_ACTION_ITEM_4: \"Gegenstandsaktion 4 (Nahkampf)\"\n  STR_ACTION_ITEM_5: \"Gegenstandsaktion 5 (Werfen)\"\n  STR_TOGGLE_QUICK_SEARCH: \"Schnellsuche Feld aktivieren\"\n  STR_TOGGLE_NIGHT_VISION: \"Nachtsicht umschalten\"\n  STR_HOLD_NIGHT_VISION: \"Nachtsicht prüfen\"\n  STR_SELECT_MUSIC_TRACK: \"Musikstück wählen\"\n  STR_TOGGLE_TOUCH_BUTTONS: \"Touch-Tasten umschalten\"\n  STR_TOGGLE_BRIGHTNESS: \"Helligkeit einstellen (nur visuell)\"\n  STR_BRIEFING: \"Einweisung\"\n  STR_TOGGLE_DEBUG_MODE: \"Debug-Modus umschalten\"\n  STR_DEBUG_KILL_ALL_ALIENS: \"DEBUG: Alle Außerirdischen Einheiten töten\"\n  STR_PHYSICAL_TRAINING: \"Kampfausbildung\"\n  STR_REMAINING_TRAINING_FACILITY_CAPACITY: \"VERFÜGBARER TRAININGSRAUM> {ALT}{0}\"\n  STR_NO_WOUNDED: \"-\"\n  STR_NO_QUEUED: \"+\"\n  STR_NO_DONE: \"Abgeschlossen\"\n  STR_NO_AMMO: \"KEINE MUNITION!\"\n  STR_START_FIRING: \"Feuer!\"\n  STR_SKIP_FIRING: \"Lasst sie rein...\"\n  STR_ALIEN_MISSILES_HAVE_DAMAGED_OUR_BASE: \"Feidlicher Angriff hat unseren Stützpunkt beschädigt {0}\"\n  STR_ALIEN_MISSILES_HAVE_DESTROYED_OUR_BASE: \"Feidlicher Angriff hat unseren Stützpunkt zerstört {0}\"\n  STR_STARTING_CONDITION_COMMANDER: \"Diese Mission erfordert die Anwesenheit des Kommandanten.\"\n  STR_STARTING_CONDITION_CRAFT: \"Dieses Raumschiff ist für die Mission ungeeignet.\"\n  STR_STARTING_CONDITION_CRAFT_ALLOWED: \"Dieses Fahrzeug kann in dieser Mission nicht genutzt werden. {NEWLINE}{NEWLINE}Erlaubte Fahrzeuge: {0}\"\n  STR_STARTING_CONDITION_CRAFT_FORBIDDEN: \"Dieses Fahrzeug kann in dieser Mission nicht genutzt werden. {NEWLINE}{NEWLINE}Verbotene Fahrzeuge: {0}\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE: \"Einige Soldaten können an dieser Mission nicht teilnehmen\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE_ALLOWED: \"Einige Soldaten können an dieser Mission nicht teilnehmen. {NEWLINE}{NEWLINE}Erlaubte Soldatentypen: {0}\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE_FORBIDDEN: \"Einige Soldaten können an dieser Mission nicht teilnehmen. {NEWLINE}{NEWLINE}Verbotene Soldatentypen: {0}\"\n  STR_STARTING_CONDITION_ITEM: \"Diese Mission erfordert bestimmte Gegenstände:{NEWLINE}{NEWLINE}{0}\"\n  STR_NOT_ENOUGH_FUEL_TO_REACH_TARGET: \"NICHT GENUG TREIBSTOFF!{SMALLLINE}Das Ziel ist außerhalb der Reichweite des Fahrzeugs.\"\n  STR_FOLLOW_WING_LEADER_QUESTION: \"Dem Anführer folgen?\"\n  STR_ASSIGN_PILOTS: \"Piloten zuweisen...\"\n  STR_NOT_ENOUGH_PILOTS: \"Nicht genug Piloten!{NEWLINE}Minimum: {0}\"\n  STR_DAILY_PILOT_EXPERIENCE: \"Tägliche Pilotenerfahrung\"\n  STR_UFO_SHIELD_HIT: \"SCHILDE GETROFFEN!\"\n  STR_UFO_HIT_NO_DAMAGE: \"VON HÜLLE ABGEPRALLT!\"\n  STR_UFO_SHIELD_DOWN: \"FEINDLICHE SCHILDE UNTEN!\"\n  STR_UFO_HIT_GLANCING: \"STREIFSCHUSS!\"\n  STR_INTERCEPTOR_SHIELD_HIT: \"UNSERE SCHILDE HALTEN!\"\n  STR_TRACTOR_BEAM_ENGAGED: \"TRAKTORSTRAHL AKTIVIERT!\"\n  STR_TRACTOR_BEAM_DISENGAGED: \"DEAKTIVIERE TRAKTORSTRAHL\"\n  STR_SELF_DESTRUCT_ACTIVATED: \"SELBSTZERSTÖRUNG AKTIVIERT!\"\n  STR_SELF_DESTRUCT_CANCELLED: \"SELBSTZERSTÖRUNG ABGEBROCHEN\"\n  STR_EXTENDED_LINKS: \"Veknüpfungen\"\n  STR_AUTO_PATROL: \"AUTO-PATROUILLE\"\n  STR_ETA: \"ETA>{ALT}{0}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_FACILITY_AT_BASE: \"Nicht genug {0} zum Wiederbewaffnen {1} in {2}\"\n  STR_UFO_STARTED_HUNTING: \"{0} ist auf einem Abfangkurs mit {1}\"\n  STR_CRAFT_IS_READY: \"{0} in {1} ist bereit.\"\n  STR_ECONOMY_WARNING: \"Die Gelder {0} und das Einkommen {1} sind zu niedrig und der Unterhalt {2} zu hoch! Verkaufe etwas um Schulden zu vermeiden... fehlende Gelder: {3}\"\n  STR_SLACKING_INDICATOR: \"{0}:{1}\"\n  STR_TRAINING_INDICATOR: \"{0}:{1}\"\n  STR_EXTENDED_UC: \"ERWEITERT\"\n  STR_RETURNING: \"RÜCKKEHR\"\n  STR_INTERCEPTING: \"ABFANGKURS\"\n  STR_ESCORTING: \"ESKORTIEREN\"\n  STR_EN_ROUTE: \"UNTERWEGS\"\n  STR_PILOT_MISSING: \"KEIN PILOT\"\n  STR_DAY_SHORT: \"{0}d\"\n  STR_HOUR_SHORT: \"{0}h\"\n  STR_PERFORMANCE_BONUS: \"Leistungsbonus\"\n  STR_COUNTRY_HAS_CANCELLED_A_SECRET_PACT: \"{0} hat seinen Pakt mit den Außerirdischen aufgegeben und ist zum Projekt zurückgekehrt.\"\n  STR_COUNTRIES_HAVE_CANCELLED_A_SECRET_PACT: \"{0} haben ihren Pakt mit den Außerirdischen aufgegeben und sind zum Projekt zurückgekehrt.\"\n  STR_WE_CAN_NOW_RENT: \"Zur Miete verfügbar\"\n  STR_REQUIRED_BASE_SERVICES: \"Benötigt Basisdienstleistung: {0}\"\n  STR_WE_CAN_NOW_BUILD: \"Zum Bau verfügbar\"\n  STR_WE_CAN_NOW_PURCHASE: \"Zum Kauf verfügbar\"\n  STR_NOT_ENOUGH_LIVING_SPACE_AT_BASE: \"Nicht genug freie Quartiere zum unterbringen von{NEWLINE}{0}{NEWLINE}in{NEWLINE}{1}\"\n  STR_INFO: \"INFO\"\n  STR_DESPAWN_PENALTY: \"Strafe für Entkommen> {0}\"\n  STR_TRAINING_FINISHED: \"Training abgeschlossen {NEWLINE}am {0}\"\n  STR_PSI_TRAINING_FINISHED: \"Psi-Training beendet{NEWLINE}bei {0}\"\n  STR_IGNORE_UC: \"IGNORIEREN\"\n  STR_UFO_TRACKER: \"UFO Tracker\"\n  STR_UPDATE: \"Update\"\n  STR_LATEST_VERSION_INFO: \"Du nutzt die aktuellste OpenXcom Version\"\n  STR_MASTER_MOD_VERSION_REQUIRED_QUESTION: \"Dieser Mod benötigt das Basisspiel v{0}, um korrekt zu funktionieren. Diesen Mod aktivieren?\"\n  STR_VERSION_REQUIRED_QUESTION: \"Diese Mod benötigt OXCE v{0} um richtig zu funktionieren. Mod trotzdem aktivieren?\"\n  STR_GLOBE_TEXTURE: \"Textur der Weltkarte\"\n  STR_NOTES: \"Anmerkungen\"\n  STR_NEW_NOTE: \"<NEW NOTE>\"\n  STR_ENGINE_OXC: \"OXC\"\n  STR_ENGINE_OXCE: \"OXCE\"\n  STR_ENGINE_OTHER: \"ANDERE\"\n  STR_BASESCAPE: \"Grundriss\"\n  STR_AI: \"KI\"\n  STR_PATH_ENERGY_COST: \"Energie\"\n  STR_PATH_ENERGY_COST_DESC: \"Durch Anklicken wird die Energie angezeigt, die Ihrer Einheit nach der Ankunft am Zielort noch zur Verfügung steht.\"\n  STR_TEST_SCREEN: \"TESTBILDSCHIRM\"\n  STR_PALETTE: \"Palette:\"\n  STR_PREVIEW: \"Vorschau\"\n  STR_TINY_BORDERLESS: \"Winzig, randlos\"\n  STR_TINY_BORDER: \"Winzig\"\n  STR_SMALL_LOW_CONTRAST: \"Small\"\n  STR_SMALL_HIGH_CONTRAST: \"Klein, hoher Kontrast\"\n  STR_BIG_LOW_CONTRAST: \"Groß\"\n  STR_BIG_HIGH_CONTRAST: \"Groß, hoher Kontrast\"\n  STR_TEST_CASE: \"Test:\"\n  STR_RUN: \"Ausgewählten Test durchführen!\"\n  STR_TESTS_STARTING: \"Starting...\"\n  STR_TESTS_ERRORS_FOUND: \"Insgesamt gefundene Fehler (es können Duplikate vorhanden sein): {0}\"\n  STR_TESTS_NO_ERRORS_FOUND: \"Keine Fehler gefunden.\"\n  STR_TESTS_FINISHED: \"Fertig.\"\n  STR_DETAILED_INFO_IN_LOG_FILE: \"Detaillierte Informationen wurden in openxcom.log gespeichert.\"\n  STR_RANK_NONE: \"-\"\n  STR_DAMAGE_NONE: \"KEINE\"\n  STR_INFO_UFOPEDIA: \"INFO\"\n  STR_COCKPIT_CAPACITY: \"PILOTEN>{ALT}{0}{ALT}\"\n  STR_MAXIMUM_RANGE: \"MAX REICHWEITE>{ALT}{0}{ALT}\"\n  STR_MINIMUM_RANGE: \"MIN REICHWEITE>{ALT}{0}{ALT}\"\n  STR_INFINITE_RANGE: \"K/A\"\n  STR_TRACTOR_BEAM_POWER: \"Energie\"\n  STR_WEIGHT_PEDIA1: \"Gewicht: {0}\"\n  STR_WEIGHT_PEDIA2: \"Gewicht: {0}/{1}\"\n  STR_SHOT_TYPE_MELEE: \"Nahkampf\"\n  STR_ACCURACY_MODIFIER: \"Genauigkeitsmodifikator>{ALT} {0}\"\n  STR_POWER_BONUS: \"Stärkemodifikator>{ALT} {0}\"\n  STR_MULTIPLE_DIFFERENT_BONUSES: \"Verschiedene Boni je nach Munitionsart\"\n  STR_STATS_FOR_NERDS: \"Stats für Nerds\"\n  STR_ARTICLE: \"Artikel>{ALT} {0}\"\n  STR_COMPATIBLE_AMMO: \"Kompatible Munition:\"\n  STR_BUILT_IN_ITEMS: \"Eingebaute Gegenstände:\"\n  STR_CLIP_SIZE_UNLIMITED: \"Unbegrenzt\"\n  STR_SHOTGUN_BEHAVIOR_OXCE: \"erweitert\"\n  STR_INCLUDE_DEBUG: \"DEBUG\"\n  STR_INCLUDE_IDS: \"IDs\"\n  STR_INCLUDE_DEFAULTS: \"STANDARD\"\n  STR_TRUE: \"ja\"\n  STR_FALSE: \"nein\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH: \"PSI FÄHIGKEIT*PSI STÄRKE\"\n  STR_STRENGTH_AND_MELEE_ACCURACY: \"STÄRKE*NAHKAMPFGENAUIGKEIT\"\n  STR_STRENGTH_AND_THROWING_ACCURACY: \"STÄRKE*WURFGENAUIGKEIT\"\n  STR_FIRING_ACCURACY_AND_REACTIONS: \"SCHUSSGENAUIGKEIT*REAKTION\"\n  STR_HEALTH_CURRENT: \"AKTUELLE GESUNDHEIT\"\n  STR_MANA_CURRENT: \"AKTUELLES MANA\"\n  STR_TIME_UNITS_CURRENT: \"AKTUELLE ZEITEINHEITEN\"\n  STR_STUN_LEVEL_CURRENT: \"AKTUELLE BETÄUBUNG\"\n  STR_HEALTH_NORMALIZED: \"NORMALE GESUNDHEIT\"\n  STR_MANA_NORMALIZED: \"STANDARDMANA\"\n  STR_TIME_UNITS_NORMALIZED: \"NORMALE ZEITEINHEITEN\"\n  STR_ENERGY_NORMALIZED: \"NORMALE ENERGIE\"\n  STR_MORALE_NORMALIZED: \"NORMALE MORAL\"\n  STR_STUN_LEVEL_NORMALIZED: \"NORMALE BETÄUBUNG\"\n  STR_ENERGY_REGENERATION: \"ENERGIEREGENERATION\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH_ABBREVIATION: \"P.FÄH*P.STÄ\"\n  STR_STRENGTH_AND_MELEE_ACCURACY_ABBREVIATION: \"STÄ*NK\"\n  STR_STRENGTH_AND_THROWING_ACCURACY_ABBREVIATION: \"STÄ*WG\"\n  STR_FIRING_ACCURACY_AND_REACTIONS_ABBREVIATION: \"SG*RE\"\n  STR_HEALTH_CURRENT_ABBREVIATION: \"AKTUELLE GESUNDHEIT\"\n  STR_MANA_CURRENT_ABBREVIATION: \"AKTUELLES MANA\"\n  STR_TIME_UNITS_CURRENT_ABBREVIATION: \"AKTUELLE ZEITEINHEITEN\"\n  STR_STUN_LEVEL_CURRENT_ABBREVIATION: \"AKTUELLE BETÄUBUNG\"\n  STR_HEALTH_NORMALIZED_ABBREVIATION: \"NORMALE GESUNDHEIT\"\n  STR_MANA_NORMALIZED_ABBREVIATION: \"STANDARDMANA\"\n  STR_TIME_UNITS_NORMALIZED_ABBREVIATION: \"NORMALE ZEITEINHEITEN\"\n  STR_ENERGY_NORMALIZED_ABBREVIATION: \"NORMALE ENERGIE\"\n  STR_MORALE_NORMALIZED_ABBREVIATION: \"NORMALE MORAL\"\n  STR_STUN_LEVEL_NORMALIZED_ABBREVIATION: \"NORMALE BETÄUBUNG\"\n  STR_ENERGY_REGENERATION_ABBREVIATION: \"ENERGIEREGENERATION\"\n  STR_COST_TIME: \"Zeit\"\n  STR_COST_ENERGY: \"Energie\"\n  STR_COST_MORALE: \"Moral\"\n  STR_COST_HEALTH: \"Gesundheit\"\n  STR_COST_STUN: \"Betäubung\"\n  STR_COST_MANA: \"Mana\"\n  STR_COST_BUILD: \"Bau\"\n  STR_COST_REFUND: \"Erstattung\"\n  STR_DAMAGE_10: \"10\"\n  STR_DAMAGE_11: \"11\"\n  STR_DAMAGE_12: \"12\"\n  STR_DAMAGE_13: \"13\"\n  STR_DAMAGE_14: \"14\"\n  STR_DAMAGE_15: \"15\"\n  STR_DAMAGE_16: \"16\"\n  STR_DAMAGE_17: \"17\"\n  STR_DAMAGE_18: \"18\"\n  STR_DAMAGE_19: \"19\"\n  STR_NAUTICAL_MILES: \"{0} Nautische Meilen\"\n  STR_KILOMETERS_PER_HOUR: \"{0} km/h\"\n  STR_SECONDS_LONG: \"{0} Sekunden\"\n  STR_RACE_BONUS: \"Rassenbonus\"\n  STR_FOR_DIFFICULTY: \"Für Schwierigkeit: {0}\"\n  STR_NOT_AWARDED_YET: \"Noch nicht erhalten\"\n"
  },
  {
    "path": "bin/common/Language/OXCE/el.yml",
    "content": "el:\n  STR_CANNOT_DISMANTLE_FACILITY_UPGRADING: \"ΑΔΥΝΑΜΙΑ ΑΠΟΣΥΝΑΡΜΟΛΟΓΗΣΕΙΣ ΕΓΚΑΤΑΣΤΑΣΗΣ!{SMALLLINE}Η εγκατάσταση δεν μπορεί να μετακινηθεί την ώρα της αναβάθμισης.\"\n  STR_CANNOT_UPGRADE_FACILITY_ALREADY_UPGRADING: \"ΑΔΥΝΑΜΙΑ ΑΝΕΓΕΡΣΗΣ ΕΔΩ!{SMALLLINE}Η υπάρχων εγκατάσταση ήδη κατασκευάζετε.\"\n  STR_CANNOT_UPGRADE_FACILITY_WRONG_SIZE: \"ΑΔΥΝΑΜΙΑ ΑΝΕΓΕΡΣΗΣ ΕΔΩ!{SMALLLINE}Η επιλεγμένη εγκατάσταση πρέπει να καλύπτει πλήρως την υπάρχουσα εγκατάσταση.\"\n  STR_CANNOT_UPGRADE_FACILITY_WRONG_TYPE: \"ΑΔΥΝΑΜΙΑ ΑΝΕΓΕΡΣΗΣ ΕΔΩ!{SMALLLINE}Δεν είναι δυνατή η αναβάθμιση της υπάρχουσας εγκατάστασης από επιλεγμένη εγκατάσταση.\"\n  STR_CANNOT_UPGRADE_FACILITY_DISALLOWED: \"ΑΔΥΝΑΜΙΑ ΑΝΕΓΕΡΣΗΣ ΕΔΩ!{SMALLLINE}Η υπάρχουσα εγκατάσταση δεν μπορεί να κατασκευαστεί ξανά.\"\n  STR_CANNOT_BUILD_QUEUE_OFF: \"ΑΔΥΝΑΜΙΑ ΑΝΕΓΕΡΣΗΣ ΕΔΩ!{SMALLLINE}Πρώτα πρέπει να κατασκευαστούν οι εγκαταστάσεις σύνδεσης.\"\n  STR_CANNOT_BUILD_UPGRADE_ONLY: \"ΑΔΥΝΑΜΙΑ ΑΝΕΓΕΡΣΗΣ ΕΔΩ!{SMALLLINE}Αυτή η εγκατάσταση μπορεί να κατασκευαστεί μόνο ως αναβάθμιση άλλης εγκατάστασης.\"\n  STR_FACILITY_FORBIDDEN_BY_OTHER: \"ΑΔΥΝΑΜΙΑ ΑΝΕΓΕΡΣΗΣ ΕΔΩ!{SMALLLINE}Κάποιες υπάρχουσες εγκαταστάσεις απαγορεύουν την κατασκευή αυτής της εγκατάστασης.\"\n  STR_FACILITY_OTHER_FORBIDDEN_BY_THIS: \"ΑΔΥΝΑΜΙΑ ΑΝΕΓΕΡΣΗΣ ΕΔΩ!{SMALLLINE}Κάποιες υπάρχουσες εγκαταστάσεις θα απαγορευθούν από αυτήν την εγκατάσταση.\"\n  STR_NOT_ENOUGH_ITEMS: \"ΑΝΕΠΑΡΚΕΙΑ ΠΟΡΩΝ{SMALLLINE}Χρειαζόμαστε περισσότερους πόρους για την κατασκευή αυτής της εγκατάστασης.{NEWLINE}Missing> {0}: {1}\"\n  STR_ID: \"Ταυτότητα\"\n  STR_FIRST_LETTER: \"ΠΡΩΤΟ ΓΡΑΜΜΑ\"\n  STR_SOLDIER_TYPE: \"ΤΥΠΟΣ ΣΤΡΑΤΙΩΤΗ\"\n  STR_IDLE_DAYS: \"ΜΕΡΕΣ ΑΔΡΑΝΙΑΣ\"\n  STR_MANA: \"ΜΑΝΑ\"\n  STR_MANA_POOL: \"ΥΠΑΡΧΩΝ ΜΑΝΑ\"\n  STR_MANA_MISSING: \"ΕΛΛΕΙΨΗ ΜΑΝΑ\"\n  STR_LOAD_CRAFT_LOADOUT_TEMPLATE: \"Φόρτωση Φορτίου Σκάφους\"\n  STR_EMPTY_SLOT_N: \"Κενή υποδοχή {0}\"\n  STR_UNNAMED_SLOT_N: \"Ανώνυμη υποδοχή {0}\"\n  STR_ADD_ON_TOP: \"Προσθέστε στην κορυφή\"\n  STR_SAVE_CRAFT_LOADOUT_TEMPLATE: \"Αποθήκευση Φορτίου Σκάφους\"\n  STR_SAVE_UC: \"ΑΠΟΘΗΚΕΥΣΗ\"\n  STR_ALL: \"Τα πάντα\"\n  STR_EQUIPPED: \"Εξοπλισμένα\"\n  STR_NOT_EQUIPPED: \"Μη εξοπλισμένα\"\n  STR_UNASSIGNED: \"Άλλα\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED_BY_SIZE: \"ΔΕΝ ΕΠΙΤΡΕΠΕΤΑΙ ΠΕΡΙΣΣΟΤΕΡΟΣ ΕΞΟΠΛΙΣΜΟΣ ΣΤΟ ΣΚΑΦΟΣ!{SMALLLINE}Μέγιστος χώρος αποθήκευσης: {0}\"\n  STR_PILOTS: \"ΠΙΛΟΤΟΙ\"\n  STR_SHIELD: \"ΑΣΠΙΔΑ>{ALT}{0}\"\n  STR_CRAFT_SKIN_ID: \"[{0}]\"\n  STR_SELECT_PILOT: \"Επιλέξτε Πιλότο\"\n  STR_PILOTS_FOR_CRAFT: \"Πιλότος(οι) για {0}\"\n  STR_PILOTS_REQUIRED: \"Πιλότος(οι) απετούνται: {ALT}{0}\"\n  STR_ADD_PILOT: \"Προσθήκη πιλότου\"\n  STR_REMOVE_ALL_PILOTS: \"Κατάργηση Όλων των Πιλότων\"\n  STR_ACCURACY_BONUS: \"Μπόνους ακρίβειας:\"\n  STR_DODGE_BONUS: \"Μπόνους ελιγμού:\"\n  STR_APPROACH_SPEED: \"Ταχύτητα προσέγγησεις\"\n  STR_COWARDLY: \"Δειλά (-50%)\"\n  STR_NORMAL: \"Ομαλά\"\n  STR_BOLD: \"Τολμηρά (+50%)\"\n  STR_VERY_BOLD: \"Πολύ τολμηρά (+100%)\"\n  STR_ARMOR_GROUP_NOT_ALLOWED: \"Αυτός ο τύπος πανοπλίας δεν επιτρέπεται στο σκάφος.\"\n  STR_SOLDIER_GROUP_NOT_ALLOWED: \"Αυτός ο τύπος στρατιώτη δεν επιτρέπεται στο σκάφος.\"\n  STR_SOLDIER_GROUP_NOT_SAME: \"Αυτός ο τύπος στρατιώτη δεν είναι συμβατός με άλλους στρατιώτες που βρίσκονται στο σκάφος.\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW: \"Προεπισκόπηση\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_SAVED: \"Προεπισκόπηση *\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_BRIEFING: \"Αυτή η λειτουργία σάς επιτρέπει να κάνετε προεπισκόπηση και να προσαρμόσετε την ανάπτυξη των μονάδων σας στην αρχή μιας μάχης. Έχεις απεριόριστες κινήσεις. Πιέστε παρατεταμένα το 'Alt' για να επισημάνετε τις έγκυρες θέσεις της μονάδας. Κάντε κλικ στο εικονίδιο «Ακύρωση αποστολής» για να αποθηκεύσετε μια προσαρμοσμένη ανάπτυξη. Κάντε κλικ στο εικονίδιο \\\"Τερματισμός Σειράς\\\" για να βγείτε από την προεπισκόπηση.{NEWLINE}Λάβετε υπόψη ότι η προσθήκη νέων στρατιωτών ή οχημάτων στο σκάφος ακυρώνει αυτόματα την αποθηκευμένη προσαρμοσμένη ανάπτυξη. Η παρουσία προσαρμοσμένης ανάπτυξης υποδεικνύεται με έναν αστερίσκο στο κουμπί \\\"Προεπισκόπηση\\\".\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_BRIEFING_DUMMY: \"Αυτή η λειτουργία σάς επιτρέπει να κάνετε προεπισκόπηση και να τροποποιήσετε τον πίνακα ανάπτυξης αυτού του τύπου σκάφους. Οποιεσδήποτε αλλαγές θα ισχύουν για όλες τις τρέχουσες δημιουργίες σας, καθώς και για όλες τις δημιουργίες που αγοράζετε ή κατασκευάζετε αργότερα στην καμπάνια. Ξεκινάτε με το μέγιστο αριθμό στρατιωτών. Κάθε στρατιώτης αντιπροσωπεύει μία γραμμή στον πίνακα ανάπτυξης. Τα ονόματα των στρατιωτών αντιστοιχούν στους αριθμούς σειρών. Για να εξασφαλίσετε χώρο για μια μονάδα 2x2, τοποθετήστε 4 στρατιώτες σε ένα τετράγωνο 2x2. Εάν δεν παρέχεται χώρος, η μονάδα 2x2 θα λείπει σε μια πραγματική μάχη.\"\n  STR_BASE_DEFENSE_BRIEFING_PREVIEW: \"Αυτή η λειτουργία σας επιτρέπει να κάνετε προεπισκόπηση της βάσης σας.{NEWLINE}Καλή διασκέδαση!{NEWLINE}{NEWLINE}Κάντε κλικ στο εικονίδιο «Τέλος Σειράς» για έξοδο από την προεπισκόπηση.\"\n  STR_NOT_ENOUGH_CARGO_SPACE: \"ΔΕΝ ΔΙΑΤΙΘΕΤΑΙ ΑΡΚΕΤΟΣ ΧΩΡΟΣ ΦΟΡΤΙΟΥ!!{SMALLLINE}Χρησιμοποιήστε μια διαφορετική μονάδα ή μειώστε το πλήρωμα που σας έχει ανατεθεί.\"\n  STR_NOT_ENOUGH_STORAGE_SPACE_1: \"ΔΕΝ ΔΙΑΤΙΘΕΤΑΙ ΑΡΚΕΤΟΣ ΧΩΡΟΣ ΦΟΡΤΙΟΥ!!{SMALLLINE}Πάρα πολλά αντικείμενα! Χρησιμοποιήστε διαφορετική μονάδα ή μειώστε τον εκχωρημένο εξοπλισμό.\"\n  STR_NOT_ENOUGH_STORAGE_SPACE_2: \"ΔΕΝ ΔΙΑΤΙΘΕΤΑΙ ΑΡΚΕΤΟΣ ΧΩΡΟΣ ΦΟΡΤΙΟΥ!!{SMALLLINE}Τα αντικείμενα πιάνουν πολύ χώρο! Χρησιμοποιήστε διαφορετική μονάδα ή μειώστε το μέγεθος του εκχωρημένου εξοπλισμού.\"\n  STR_REFUND_VALUE: \"Εμπορική αξία> {ALT}{0}\"\n  STR_REFUND_VALUE_NEGATIVE: \"Έξοδα> {ALT}{0}\"\n  STR_PRODUCTION_OVERVIEW: \"ΕΠΙΣΚΟΠΗΣΗ ΠΑΡΑΓΩΓΗΣ\"\n  STR_RESEARCH_DIARY: \"ΕΡΕΥΝΗΤΙΚΟ ΗΜΕΡΟΛΟΓΙΟ\"\n  STR_DISCOVERY_SOURCE_BASE: \"Αυτό το αντικείμενο ανακαλύφθηκε μέσω ερευνητικού έργου.{NEWLINE}Βάση έρευνας> {ALT}{1}{ALT}{NEWLINE}Κωδικός αντικειμένου> {ALT}{0}{ALT}\"\n  STR_DISCOVERY_SOURCE_FREE_FROM: \"Αυτό το αντικείμενο δόθηκε δωρεάν από άλλο ερευνητικό έργο.{NEWLINE}Από ερευνητικό έργο> {ALT}{2}{ALT}{NEWLINE}{ALT}{1}{ALT} -> {ALT}{0}{ALT}\"\n  STR_DISCOVERY_SOURCE_FREE_AFTER: \"Αυτό το τεχνικό αντικείμενο ανακαλύφθηκε αυτόματα.{NEWLINE}Μετά από ερευνητικό έργο> {ALT}{2}{ALT}{NEWLINE}{ALT}{1}{ALT} -> {ALT}{0}{ALT}\"\n  STR_DISCOVERY_SOURCE_MISSION: \"Αυτό το αντικείμενο δόθηκε δωρεάν ως ανταμοιβή αποστολής.{NEWLINE}Τύπος αποστολής> {ALT}{2}{ALT}{NEWLINE}{ALT}{1}{ALT} -> {ALT}{0}{ALT}\"\n  STR_DISCOVERY_SOURCE_EVENT: \"Αυτό το αντικείμενο δόθηκε δωρεάν ως ανταμοιβή εκδήλωσης.{NEWLINE}Τύπος εκδήλωσης> {ALT}{2}{ALT}{NEWLINE}{ALT}{1}{ALT} -> {ALT}{0}{ALT}\"\n  STR_RESEARCH_OVERVIEW: \"ΕΠΙΣΚΟΠΗΣΗ ΕΡΕΥΝΑΣ\"\n  STR_PRISONER_OVERVIEW: \"ΕΠΙΣΚΟΠΗΣΗ ΦΥΛΑΚΙΣΜΕΝΟΥ\"\n  STR_PRISONER: \"ΦΥΛΑΚΙΣΜΕΝΟΣ\"\n  STR_PRISONER_AMOUNT: \"ΠΟΣΟ\"\n  STR_PRISONER_INTERROGATED: \"ΑΝΑΚΡΙΝΟΜΕΝΟΙ\"\n  STR_TOTAL_IN_PRISON: \"Χρησιμοποιημένος Χώρος>{ALT}{0}\"\n  STR_TOTAL_INTERROGATED: \"Ανακρινόμενοι>{ALT}{0}\"\n  STR_PRISON_TYPE: \"Περιορισμένοι Εξωγήινοι\"\n  STR_KILL_SELECTED: \"Εξουδετέρωσε\"\n  STR_SELL_SELECTED: \"Πούλησε\"\n  STR_GO_TO_TRANSFERS: \"Μετέφερε...\"\n  STR_PRISON_CLEANUP: \"Εκκαθάριση Φυλακών\"\n  STR_TOPIC: \"Θέμα>{ALT} {0}\"\n  STR_SHOW_ALL: \"Εμφάνιση όλων\"\n  STR_NO_DEPENDENCIES: \"Χωρίς εξαρτήσεις.\"\n  STR_DIRECT_DEPENDENCIES: \"Άμεσες εξαρτήσεις\"\n  STR_LEVEL_2_DEPENDENCIES: \"Εξαρτήσεις επιπέδου 2\"\n  STR_LEVEL_3_DEPENDENCIES: \"Εξαρτήσεις επιπέδου 3\"\n  STR_LEVEL_4_DEPENDENCIES: \"Εξαρτήσεις επιπέδου 4\"\n  STR_MORE_DEPENDENCIES: \"Υπάρχουν ακόμη βαθύτερες εξαρτήσεις...\"\n  STR_END_OF_SEARCH: \"Τέλος αναζήτησης.\"\n  STR_FALLBACK_PRODUCTION: \"ΥΠΟΧΩΡΗΣΗ\"\n  STR_REFUND_PRODUCTION: \"ΕΠΙΣΤΡΟΦΗ ΧΡΗΜΑΤΩΝ!\"\n  STR_HOURS_PER_UNIT: \"ΩΡΕΣ ΑΝΑ ΜΟΝΑΔΑ>{ALT}{0}\"\n  STR_PERSON_JOINING: \"Άτομο Συνδέεται\"\n  STR_RANDOM_PRODUCTION_DISCLAIMER: \"Τυχαία παραγωγή!\"\n  STR_OTHER_EMPLOYEES: \"Άλλο Προσωπικό και Υπάρχοντα\"\n  STR_SHOW_ONLY_NEW: \"Εμφάνιση μόνο νέων\"\n  STR_FILTER_DEFAULT: \"Προεπιλογή\"\n  STR_FILTER_DEFAULT_SUPPLIES_OK: \"Προεπιλογή (προμήθειες ΟΚ)\"\n  STR_FILTER_DEFAULT_NO_SUPPLIES: \"Προεπιλογή (χωρίς προμήθειες)\"\n  STR_FILTER_FACILITY_REQUIRED: \"Η Εγκατάσταση Λείπει\"\n  STR_FILTER_HIDDEN: \"Κρυμμένο\"\n  STR_FILTER_EQUIPPED: \"Εξοπλισμένα\"\n  STR_FILTER_MISSING: \"Λείπουν\"\n  STR_SORT_DEFAULT: \"Προεπιλεγμένα\"\n  STR_SORT_BY_COST: \"Ανά κόστος\"\n  STR_SORT_BY_NAME: \"Ανά όνομα\"\n  STR_RANDOM_PRODUCTION_SUMMARY: \"Σύνοψη\"\n  STR_NOT_ENOUGH_PRISON_SPACE: \"ΑΝΕΠΑΡΚΕΙΣ ΧΩΡΟΣ ΠΕΡΙΟΡΙΣΜΟΥ ΕΞΩΓΗΙΝΩΝ!{SMALLLINE}Φτιάξτε νέα μονάδα περιορισμού εξωγήινων ή μεταφέρετε εξωγήινους σε άλλες βάσεις.\"\n  STR_MONTHLY_ITEM_PURCHASE_LIMIT_EXCEEDED: \"ΥΠΕΡΒΑΣΗ ΜΗΝΙΑΙΟΥ ΟΡΙΟΥ ΑΓΟΡΩΝ!!{SMALLLINE}Περισσότερα αντικείμενα θα είναι διαθέσιμα τον επόμενο μήνα.\"\n  STR_MONTHLY_CRAFT_PURCHASE_LIMIT_EXCEEDED: \"ΥΠΕΡΒΑΣΗ ΜΗΝΙΑΙΟΥ ΟΡΙΟΥ ΑΓΟΡΩΝ!!{SMALLLINE}Περισσότερα σκάφη θα είναι διαθέσιμα τον επόμενο μήνα.\"\n  STR_MONTHLY_SOLDIER_HIRING_LIMIT_EXCEEDED: \"ΥΠΕΡΒΑΣΗ ΜΗΝΙΑΙΟΥ ΟΡΙΟΥ ΠΡΟΣΛΗΨΕΩΝ!!{SMALLLINE}Περισσότεροι νεοσύλλεκτοι θα είναι διαθέσιμοι τον επόμενο μήνα.\"\n  STR_NOT_ENOUGH_CRAFT_SPACE: \"Δεν υπάρχει αρκετός χώρος στο σκάφος!\"\n  STR_SELECT_AVATAR_FOR: \"ΕΠΙΛΟΓΗ ΑΒΑΤΑΡ ΓΙΑ{NEWLINE}{0}\"\n  STR_SOLDIER_BONUSES_FOR: \"ΜΠΟΝΟΥΣ ΣΤΡΑΤΙΩΤΩΝ ΓΙΑ{NEWLINE}{0}\"\n  STR_SUMMARY: \"Περίληψη\"\n  STR_MANA_RECOVERY: \"ΑΠΟΚΑΤΑΣΤΑΣΗ ΜΑΝΑ> {ALT}{0}\"\n  STR_HEALTH_RECOVERY: \"ΑΠΟΚΑΤΑΣΤΑΣΗ ΥΓΕΙΑΣ> {ALT}{0}\"\n  STR_BONUSES_BUTTON: \"+\"\n  STR_PROMOTE_SOLDIER: \"ΠΡΟΩΘΗΣΗ/ΥΠΟΒΙΒΑΣΗ{NEWLINE}{0} {1}\"\n  STR_RANK_HEADER: \"ΒΑΘΜΟΣ\"\n  STR_OPENINGS_HEADER: \"ΑΝΟΙΧΤΕΣ ΘΕΣΕΙΣ\"\n  STR_KILLER_AND_WEAPON: \"{0}, {1}\"\n  STR_TRAINING: \"Προπόνηση\"\n  STR_SOLDIER_INFO: \"Πληροφορίες Στρατιώτη\"\n  STR_SELECT_TRANSFORMATION_FOR: \"ΕΠΙΛΕΞΤΕ ΜΕΤΑΤΡΟΠΗ ΓΙΑ{NEWLINE}{0}\"\n  STR_TRANSFORMATIONS_BUTTON: \"^\"\n  STR_TRANSFER_TIME: \"Χρόνος Μεταβίβασης>{ALT}{0}\"\n  STR_RECOVERY_TIME: \"Χρόνος Ανάρρωσης>{ALT}{0}\"\n  STR_CURRENT_STATS: \"Τρέχουσα στατιστική\"\n  STR_CHANGES: \"Αλαγές\"\n  STR_CHANGES_MIN: \"Μεταβολές (min)\"\n  STR_CHANGES_MAX: \"Μεταβολές (max)\"\n  STR_BONUS_STATS: \"Στατιστικά μπόνους\"\n  STR_TRANSFORMATIONS_OVERVIEW: \"Επισκόπηση Μετασχηματισμών\"\n  STR_PROJECT_NAME: \"ΟΝΟΜΑ ΣΧΕΔΙΟΥ\"\n  STR_AVAILABLE_MATERIALS: \"ΔΙΑΘΕΣΙΜΑ ΥΛΙΚΑ\"\n  STR_ELIGIBLE_SOLDIERS: \"ΔΙΚΑΙΟΥΧΟΙ ΣΤΡΑΤΙΩΤΕΣ\"\n  STR_SHOW_ONLY_ELIGIBLE: \"Εμφάνιση Μόνο Επιλέξιμων\"\n  STR_ALL_SOLDIER_TYPES: \"Όλοι οι Τύποι Στρατιωτών\"\n  STR_ALL_SOLDIERS: \"Όλοι οι Στρατιώτες\"\n  STR_HEALTHY_SOLDIERS: \"Υγιείς Στρατιώτες\"\n  STR_WOUNDED_SOLDIERS: \"Τραυματίες Στρατιώτες\"\n  STR_DEAD_SOLDIERS: \"Νεκροί Στρατιώτες\"\n  STR_GRAND_TOTAL: \"Μεγάλο Σύνολο\"\n  STR_AVAILABLE_TOPICS: \"ΔΙΑΘΕΣΙΜΑ ΘΕΜΑΤΑ\"\n  STR_QS_THREE_LETTERS_A: \"Παρακαλώ εισάγετε τουλάχιστον 3 γράμματα\"\n  STR_QS_THREE_LETTERS_B: \"στο πλαίσιο Γρήγορης Αναζήτησης...\"\n  STR_M_FLAG: \" [m]\"\n  STR_F_FLAG: \" [f]\"\n  STR_I_FLAG: \" [i]\"\n  STR_C_FLAG: \" [c]\"\n  STR_THIS_FEATURE_IS_DISABLED_1: \"Αυτή η λειτουργία είναι απενεργοποιημένη.\"\n  STR_THIS_FEATURE_IS_DISABLED_2: \"Αυτή η λειτουργία είναι απενεργοποιημένη.\"\n  STR_THIS_FEATURE_IS_DISABLED_3: \"Αυτή η λειτουργία είναι απενεργοποιημένη.\"\n  STR_THIS_FEATURE_IS_DISABLED_4: \"Αυτή η λειτουργία είναι απενεργοποιημένη.\"\n  STR_THIS_FEATURE_IS_DISABLED_5: \"Αυτή η λειτουργία είναι απενεργοποιημένη.\"\n  STR_TECH_TREE_VIEWER: \"Προβολή Τεχνικού Δέντρου\"\n  STR_SELECT_TOPIC: \"Επιλέξτε Θέμα\"\n  STR_RESEARCH_PROGRESS: \"Πρόοδος>{ALT} {0}%\"\n  STR_ITEM_DESTROYED: \"Το αντικείμενο καταστράφηκε:\"\n  STR_ITEM_REQUIRED: \"Απαιτούμενο αντικείμενο:\"\n  STR_SERVICES_REQUIRED: \"Απαιτούμενες υπηρεσίες:\"\n  STR_SERVICES_PROVIDED: \"Παρεχόμενες υπηρεσίες:\"\n  STR_SERVICES_FORBIDDEN: \"Απαγορευμένες υπηρεσίες:\"\n  STR_REQUIRES: \"Απαιτούνται:\"\n  STR_DEPENDS_ON: \"Εξαρτάται από:\"\n  STR_UNLOCKED_BY: \"Ξεκλειδώθηκε από:\"\n  STR_DISABLED_BY: \"Απενεργοποιημένο από:\"\n  STR_REENABLED_BY: \"Ενεργοποιήθηκε εκ νέου από:\"\n  STR_GET_FOR_FREE_FROM: \"Αποκτήστε το δωρεάν από:\"\n  STR_IS_LOOKUP_OF: \"Είναι αναζήτηση της:\"\n  STR_LOOKUP: \"Αναζήτηση:\"\n  STR_SPAWNED_ITEMS: \"Αντικείμενα που Αναπαράγονται:\"\n  STR_SPAWNED_EVENT: \"Γεννημένο γεγονός:\"\n  STR_REQUIRED_BY: \"Απαιτείται από:\"\n  STR_REQUIRED_BY_TRANSFORMATIONS: \"Απαιτείται από μετασχηματισμούς:\"\n  STR_LEADS_TO: \"Οδηγεί προς:\"\n  STR_UNLOCKS: \"Ξεκλειδώνει:\"\n  STR_DISABLES: \"Απενεργοποιεί:\"\n  STR_REENABLES: \"Ενεργοποιεί εκ νέου:\"\n  STR_GIVES_ONE_FOR_FREE_SEQ: \"Δίνει ένα δωρεάν (διαδοχικά):\"\n  STR_GIVES_ONE_FOR_FREE: \"Δίνει ένα δωρεάν:\"\n  STR_RESEARCH_REQUIRED: \"Απαιτείται έρευνα:\"\n  STR_RESEARCH_REQUIRED_USE: \"Απαιτούμενη έρευνα (χρήση):\"\n  STR_RESEARCH_REQUIRED_BUY: \"Απαιτείται έρευνα (αγορά):\"\n  STR_SERVICES_REQUIRED_BUY: \"Απαιτούμενες υπηρεσίες (αγορά):\"\n  STR_PRODUCED_BY: \"Παραγωγή από:\"\n  STR_SPAWNED_BY: \"Δημιουργήθηκε από:\"\n  STR_MATERIALS_REQUIRED: \"Απαραίτητα υλικά:\"\n  STR_TTV_COST_PER_UNIT: \"Κόστος ανά μονάδα:\"\n  STR_TTV_ENGINEER_HOURS: \"Ώρες μηχανικού:\"\n  STR_TTV_WORK_SPACE_REQUIRED: \"Απαιτείται χώρος εργασίας:\"\n  STR_ITEMS_PRODUCED: \"Παραγόμενα αντικείμενα:\"\n  STR_PERSON_RECRUITED: \"Προσληφθέν πρόσωπο:\"\n  STR_UNLOCKS_ARCS: \"Ξεκλειδώνει αψίδες:\"\n  STR_DISABLES_ARCS: \"Απενεργοποιεί αψίδες:\"\n  STR_UNLOCKS_MISSIONS: \"Ξεκλειδώνει αποστολές:\"\n  STR_DISABLES_MISSIONS: \"Απενεργοποιεί αποστολές:\"\n  STR_UNLOCKS_EVENTS: \"Ξεκλειδώνει συμβάντα:\"\n  STR_DISABLES_EVENTS: \"Απενεργοποιεί συμβάντα:\"\n  STR_AFFECTS_GAME_PROGRESSION: \"Επηρεάζει την πρόοδο του παιχνιδιού!\"\n  STR_ITEMS_AT_DESTINATION: \"Αντικείμενα στον τόπο προορισμού\"\n  STR_PRISONERS: \"Αιχμάλωτοι\"\n  STR_ARMORS: \"Θωρακίσεις\"\n  STR_FILTER_RESEARCHED: \"Πλήρως ερευνημένο\"\n  STR_FILTER_RESEARCHABLE: \"Ερευνήσιμο\"\n  STR_CRAFT_DEPLOYMENT_QUESTION: \"Αποθήκευση Ανάπτυξης Σκάφους;\"\n  STR_MUST_USE_BOTH_HANDS: \"Απαιτούνται και τα δύο χέρια γι' αυτό!\"\n  STR_NOT_ENOUGH_MORALE: \"Δεν υπάρχει αρκετό ηθικό!\"\n  STR_NOT_ENOUGH_HEALTH: \"Δεν είναι αρκετή η υγεία!\"\n  STR_NOT_ENOUGH_MANA: \"Δεν υπάρχει αρκετή Μάνα!\"\n  STR_NOT_ENOUGH_STUN: \"Το επίπεδο ακινητοποίησης είναι πολύ υψηλό!\"\n  STR_MIND_CONTROL_SUCCESSFUL_ALT: \"Δράση Επιτυχής\"\n  STR_LINE_OF_SIGHT_REQUIRED: \"Γραμμή οπτικής επαφής (ΓΟΕ) απαιτείται.\"\n  STR_CENTER_ON_WOUNDED_FRIEND: \"Εστίασε σε Τραυματισμένο Φίλο\"\n  STR_CENTER_ON_DIZZY_FRIEND: \"Εστίασε σε Ζαλιζμένο Φίλο\"\n  STR_BUG_HUNT_ACTIVATED: \"Ενεργοποιημένη λειτουργία κυνηγιού εντόμων: οι εχθροί είναι ορατοί στον μίνι χάρτη!\"\n  STR_QUICK_MODE_ACTIVATED: \"Ενεργοποιήθηκε η λειτουργία Usain Bolt.{NEWLINE}Πιέστε ξανά Ctrl+S για να την απενεργοποιήσετε.\"\n  STR_QUICK_MODE_DEACTIVATED: \"Η λειτουργία Usain Bolt απενεργοποιήθηκε.\"\n  STR_TARGET_ENEMY: \"; Target = ΕΧΘΡΟΣ\"\n  STR_TARGET_NEUTRAL: \"; Target = ΟΥΔΕΤΕΡΟΣ\"\n  STR_TARGET_FRIEND: \"; Target = ΦΙΛΟΣ\"\n  STR_TARGET_YOURSELF: \"; Target = ΕΣΥ\"\n  STR_TARGET_ON_THE_GROUND: \"(επί του εδάφους)\"\n  STR_USE_SPECIAL_ITEM: \"Χρήση ειδικού αντικειμένου\"\n  STR_NO_EXPERIENCE_YET: \"Καμία εμπειρία ακόμη:\"\n  STR_OPERATION_UC: \"ΛΕΙΤΟΥΡΓΙΑ> {0}\"\n  STR_WHAT_CAN_I_WEAR: \"Τι μπορώ να φορέσω;\"\n  STR_STARTING_CONDITION_ARMORS_FORBIDDEN: \"Αυτή η αποστολή απαιτεί συγκεκριμένο εξοπλισμό.{NEWLINE}{NEWLINE}Απαγορευμένοι τύποι πανοπλίας είναι: {0}\"\n  STR_STARTING_CONDITION_ARMORS_ALLOWED: \"Αυτή η αποστολή απαιτεί συγκεκριμένο εξοπλισμό.{NEWLINE}{NEWLINE}Επιτρεπόμενοι τύποι πανοπλίας είναι: {0}\"\n  STR_MISSION_OVER: \"Αποστολή εξετελέσθη.\"\n  STR_UNITS_WITH_FATAL_WOUNDS:\n    one: \"{Ν} από εμάς είμαστε ακόμα θανάσιμα τραυματισμένοι\"\n    other: \"{Ν} από εμάς είμαστε ακόμα θανάσιμα τραυματισμένοι\"\n  STR_END_MISSION_QUESTION: \"Τέλος αποστολής;\"\n  STR_LOOT: \"ΛΑΦΥΡΑ\"\n  STR_SELL: \"ΠΩΛΗΣΗ\"\n  STR_LIVE_ALIENS_SURRENDERED: \"ΟΙ ΕΧΘΡΟΙ ΠΑΡΑΔΟΘΗΚΑΝ\"\n  STR_MISSION_ABORTED: \"ΑΠΟΣΤΟΛΗ ΜΑΤΑΙΩΘΗΚΕ\"\n  STR_VIPS_SAVED: \"ΕΠΙΣΗΜΟΙ ΣΩΘΗΚΑΝ\"\n  STR_VIPS_LOST: \"ΕΠΙΣΗΜΟΙ ΧΑΘΗΚΑΝ\"\n  STR_BOUNTY: \"ΕΠΙΔΟΤΗΣΗ\"\n  STR_MANA_ABBREVIATION: \"ΑΝΤΡΑΣ\"\n  STR_EXPERIENCE_OVERVIEW: \"Επισκόπηση Εμπειριών\"\n  STR_CANNOT_PLACE_ITEM_INTO_THIS_SECTION: \"Δεν επιτρέπεται να τοποθετήσετε αυτό το αντικείμενο εκεί.{NEWLINE}Μην ρωτάτε γιατί!\"\n  STR_ONE_HAND_MUST_BE_EMPTY: \"Τουλάχιστον ένα χέρι πρέπει να είναι άδειο!\"\n  STR_LOAD_EQUIPMENT_TEMPLATE: \"Φόρτωση Πρότυπου Εξοπλισμού\"\n  STR_SAVE_EQUIPMENT_TEMPLATE: \"Αποθήκευση Προτύπου Εξοπλισμού\"\n  STR_FIRING_SHORT: \"Πυροδότηση>{ALT}{0}\"\n  STR_THROWING_SHORT: \"Ρίψη>{ALT}{0}\"\n  STR_MELEE_SHORT: \"Μάχη σώμα με σώμα>{ALT}{0}\"\n  STR_PERSONAL_EQUIPMENT: \"ΠΡΟΣΩΠΙΚΟΣ ΕΞΟΠΛΙΣΜΟΣ\"\n  STR_SAVE_PERSONAL_EQUIPMENT: \"Αποθήκευση Προσωπικού Εξοπλισμού\"\n  STR_LOAD_PERSONAL_EQUIPMENT: \"Φόρτωση Προσωπικού Εξοπλισμού\"\n  STR_PERSONAL_EQUIPMENT_SAVED: \"Προσωπικός εξοπλισμός αποθηκεύτηκε.\"\n  STR_PERSONAL_EQUIPMENT_NOT_DEFINED: \"Ο προσωπικός εξοπλισμός δεν έχει οριστεί ακόμη.\"\n  STR_SLOT: \"Θέση>{ALT}{0}\"\n  STR_THINKING: \"Σκέφτομαι...\"\n  STR_TELL_ME_MORE: \"Πες μου περισσότερα...\"\n  STR_REINFORCEMENTS_ALERT: \"Ειδοποίηση για ενίσχυση!\"\n  STR_HIT_LOG_NEW_TURN: \"Νέα Στροφή\"\n  STR_FAILED_CQB_CHECK: \"Ο εχθρός κατάφερε να διακόψει την επίθεσή σας!\"\n  STR_NO_TRAJECTORY: \"Καμία εφικτή τροχιά!\"\n  STR_HIT_LOG_NEW_BULLET: \"=> \"\n  STR_MANA_SHORT: \"MA>{ALT}{0}\"\n  STR_SKILL_NEEDS_ITEM: \"Η δεξιότητα αυτή χρειάζεται ένα αντικείμενο!\"\n  STR_HIT_LOG_NO_DAMAGE: \"0 \"\n  STR_HIT_LOG_SMALL_DAMAGE: \"πλήγμα\"\n  STR_HIT_LOG_BIG_DAMAGE: \"ΠΛΗΓΜΑ\"\n  STR_HIT_LOG_REACTION_FIRE: \"Βολή αντίδρασης...\"\n  STR_HIT_LOG: \"Ιστορικό Πληγμάτων\"\n  STR_BUTTON_TOUCH: \"Επαφή\"\n  STR_BUTTON_1: \"1\"\n  STR_BUTTON_10: \"10\"\n  STR_BUTTON_100: \"100\"\n  STR_BUTTON_LMB: \"ΑΚΠ\"\n  STR_BUTTON_RMB: \"ΔΚΠ\"\n  STR_BUTTON_MMB: \"ΜΚΠ\"\n  STR_BUTTON_CTRL: \"Ctrl\"\n  STR_BUTTON_ALT: \"Alt\"\n  STR_BUTTON_SHIFT: \"Shift\"\n  STR_LAZY_LOADING: \"Αργή φόρτωση\"\n  STR_LAZY_LOADING_DESC: \"Εάν είναι ενεργοποιημένο, οι πόροι γραφικών φορτώνονται κατ' απαίτηση. Διαφορετικά, όλα φορτώνονται κατά την εκκίνηση.\"\n  STR_VSYNC_FOR_OPENGL: \"VSync for OpenGL\"\n  STR_VSYNC_FOR_OPENGL_DESC: \"Απενεργοποιήστε τη για μέγιστη κρυφή ταχύτητα κίνησης του εχθρού και (προαιρετικά) ταχύτητα κίνησης στρατιώτη. ΜΗΝ ορίσετε το όριο FPS στο 0. Ισχύει μόνο για απόδοση OpenGL.\"\n  STR_UPDATE_CHECK: \"Αυτόματος έλεγχος ενημερώσεων\"\n  STR_UPDATE_CHECK_DESC: \"Εάν είναι ενεργοποιημένο, το OpenXcom θα ελέγξει αυτόματα για ενημερώσεις και θα σας δώσει την επιλογή να ενημερωθεί με ένα μόνο κλικ.\"\n  STR_AUTOSAVE_SLOTS: \"Αυτόματες θέσεις αποθήκευσης\"\n  STR_AUTOSAVE_SLOTS_DESC: \"Αριθμός θέσεων για αυτόματη αποθήκευση Battlescape.\"\n  STR_AUTO_SAVE_BATTLESCAPE_SLOT_WITH_NUMBER: \"<AUTO BATTLESCAPE> {0}\"\n  STR_GEO_AUTOSAVE_FREQUENCY: \"Συχνότητα Αυτόματης αποθήκευσης (Geoscape)\"\n  STR_GEO_AUTOSAVE_FREQUENCY_DESC: \"Ο αριθμός των ημερών μετά τις οποίες το παιχνίδι θα αποθηκευτεί αυτόματα.\"\n  STR_GEO_AUTOSAVE_SLOTS: \"Θέσεις αυτόματης αποθήκευσης (Geoscape)\"\n  STR_GEO_AUTOSAVE_SLOTS_DESC: \"Αριθμός θέσεων για αυτόματη αποθήκευση Geoscape.\"\n  STR_AUTO_SAVE_GEOSCAPE_SLOT_WITH_NUMBER: \"<AUTO GEOSCAPE> {0}\"\n  STR_OXCE_LINKS: \"Εκτεταμένοι σύνδεσμοι\"\n  STR_OXCE_LINKS_DESC: \"Ενεργοποιεί πρόσθετα μενού/κουμπιά/ συνδέσμους για τις λειτουργίες OXCE.\"\n  STR_PEDIA_SHOW_CLIP_SIZE: \"Εμφάνιση του μεγέθους γεμηστήρα στην Ufopedia\"\n  STR_PEDIA_SHOW_CLIP_SIZE_DESC: \"Εάν είναι ενεργοποιημένο, τα μεγέθη των γεμηστήρων πυρομαχικών θα εμφανίζονται δίπλα στα εικονίδια πυρομαχικών στην Ufopedia.\"\n  STR_INTERCEPT_TABLE_SIZE: \"Μέγεθος πίνακα τομής\"\n  STR_INTERCEPT_TABLE_SIZE_DESC: \"Μέγεθος των πινάκων στα ακόλουθα παράθυρα διαλόγου: Αναχαίτιση, Παρακολούθηση UFO.\"\n  STR_SHOW_SLACKING_INDICATOR: \"Εμφάνιση ένδειξης περιορισμού\"\n  STR_SHOW_SLACKING_INDICATOR_DESC: \"Εάν ενεργοποιηθεί, θα εμφανιστεί ο αριθμός των επιστημόνων και μηχανικών που δεν έχουν ανατεθεί.\"\n  STR_SHOW_MAINTENANCE_TIME: \"Εμφάνιση χρόνου συντήρησης σκάφους\"\n  STR_SHOW_MAINTENANCE_TIME_DESC: \"{ALT}0>{ALT} Να μην εμφανίζεται {ALT}1>{ALT} Εμφάνιση μόνο της τρέχουσας διάρκειας δραστηριότητας {ALT}2>{ALT} Εμφάνιση όλων μαζί (επισκευή + επανεξοπλισμός + ανεφοδιασμός).\"\n  STR_SHOW_ETA: \"Προβολή εκτιμώμενης διάρκειας πτήσης\"\n  STR_SHOW_ETA_DESC: \"{ALT}0>{ALT} Να μην εμφανίζεται {ALT}1>{ALT} Εμφάνιση ΕΤΑ μόνο για στατικούς στόχους {ALT}2>{ALT} Εμφάνιση ΕΤΑ και για κινούμενους στόχους.\"\n  STR_UFO_LANDING_ALERT: \"Συναγερμός προσγείωσης ΑΤΙΑ\"\n  STR_UFO_LANDING_ALERT_DESC: \"Εάν είναι ενεργοποιημένο, ένα μήνυμα θα εμφανίζεται κάθε φορά που προσγειώνεται ένα ΑΤΙΑ που έχει εντοπιστεί.\"\n  STR_REMEMBER_DISABLED_CRAFT_WEAPONS: \"Να θυμάστε τα ακινητοποιημένα όπλα του σκάφους\"\n  STR_REMEMBER_DISABLED_CRAFT_WEAPONS_DESC: \"Τα όπλα του σκάφους που απενεργοποιούνται κατά τη διάρκεια μιας αερομαχίας θα παραμείνουν απενεργοποιημένα. Επίσης δεν θα επανοπλιστούν στη βάση.\"\n  STR_GEO_EVENT_INSTANT_DELIVERY: \"Άμεση παράδοση αντικειμένων σε συμβάντα\"\n  STR_GEO_EVENT_INSTANT_DELIVERY_DESC: \"Εάν είναι ενεργοποιημένο, τα στοιχεία από συμβάντα geoscape φτάνουν αμέσως. Διαφορετικά, φτάνουν 1 ώρα αργότερα.\"\n  STR_SHOW_BASE_NAME_IN_POPUPS: \"Εμφάνιση ονόματος βάσης σε αναδυόμενα παράθυρα\"\n  STR_SHOW_BASE_NAME_IN_POPUPS_DESC: \"Εάν είναι ενεργοποιημένη, το αντίστοιχο όνομα βάσης εμφανίζεται σε αναδυόμενα παράθυρα (π.χ. Έρευνα Ολοκληρώθηκε).\"\n  STR_ALTERNATE_CRAFT_EQUIPMENT_MANAGEMENT: \"Εναλλακτική διαχείριση εξοπλισμού σκάφους\"\n  STR_ALTERNATE_CRAFT_EQUIPMENT_MANAGEMENT_DESC: \"Εάν ενεργοποιηθεί, η μετακίνηση στρατιωτών μεταξύ βάσης και σκάφους θα μετακινήσει και τον εξοπλισμό τους (αν είναι δυνατόν).\"\n  STR_BASE_INFO_SCALE: \"Κλίμακα μεγάλων ράβδων στις πληροφορίες βάσης\"\n  STR_BASE_INFO_SCALE_DESC: \"Εάν είναι ενεργοποιημένο, οι ράβδοι μεγαλύτερες από 140 μειώνονται για να ταιριάζουν στο περιβάλλον εργασίας χρήστη.\"\n  STR_HIGHLIGHT_NEW: \"Επισήμανση νέων θεμάτων\"\n  STR_HIGHLIGHT_NEW_DESC: \"Εάν είναι ενεργοποιημένο, τα νέα ερευνητικά θέματα, τα νέα θέματα παραγωγής και τα νέα άρθρα της ουφοπαίδειας εμφανίζονται με διαφορετικό χρώμα.\"\n  STR_RESEARCH_SCROLL_SPEED: \"Ταχύτητα κύλισης έρευνας\"\n  STR_RESEARCH_SCROLL_SPEED_DESC: \"Οι επιστήμονες μπορούν να (μη) εκχωρηθούν απευθείας στη διεπαφή χρήστη της τρέχουσας έρευνας χρησιμοποιώντας το κουμπί κύλισης του ποντικιού.\"\n  STR_RESEARCH_SCROLL_SPEED_CTRL: \"Ταχύτητα κύλισης έρευνας (με Ctrl)\"\n  STR_RESEARCH_SCROLL_SPEED_CTRL_DESC: \"Οι επιστήμονες μπορούν να (μη) εκχωρηθούν απευθείας στο περιβάλον χρήστη της τρέχουσας έρευνας χρησιμοποιώντας το κουμπί κύλισης του ποντικιού.\"\n  STR_MANUFACTURE_FILTER_SUPPLIES_OK: \"Εναλλακτικό φίλτρο στην Κατασκευή\"\n  STR_MANUFACTURE_FILTER_SUPPLIES_OK_DESC: \"Εάν είναι ενεργοποιημένο, το περιβάλον χρήστη εμφανίζει μόνο στοιχεία παραγωγής για τα οποία υπάρχουν αρκετά αναλώσιμα.\"\n  STR_MANUFACTURE_SCROLL_SPEED: \"Ταχύτητα κύλισης κατασκευής\"\n  STR_MANUFACTURE_SCROLL_SPEED_DESC: \"Οι μηχανικοί μπορούν να (μη) εκχωρηθούν απευθείας στο περιβάλον χρήστη τρέχουσας παραγωγής χρησιμοποιώντας το κουμπί κύλισης του ποντικιού.\"\n  STR_MANUFACTURE_SCROLL_SPEED_CTRL: \"Ταχύτητα κύλισης κατασκευής (με Ctrl)\"\n  STR_MANUFACTURE_SCROLL_SPEED_CTRL_DESC: \"Οι μηχανικοί μπορούν να (μη) εκχωρηθούν απευθείας στο περιβάλον χρήστη τρέχουσας παραγωγής χρησιμοποιώντας το κουμπί κύλισης του ποντικιού.\"\n  STR_PERSONAL_LAYOUT_INCLUDING_ARMOR: \"Συμπεριλάβετε την πανοπλία στον προσωπικό εξοπλισμό\"\n  STR_PERSONAL_LAYOUT_INCLUDING_ARMOR_DESC: \"Εάν είναι ενεργοποιημένη, αποθηκεύεται η διάταξη προσωπικού εξοπλισμού στρατιώτη συμπεριλαμβανομένης της φθαρμένης πανοπλίας.\"\n  STR_MANUALPROMOTIONS: \"Χειροκίνητες προωθητικές ενέργειες\"\n  STR_MANUALPROMOTIONS_DESC: \"Εάν είναι ενεργοποιημένο, οι στρατιώτες μπορούν να προαχθούν (ή να υποβιβαστούν) με μη αυτόματο τρόπο κάνοντας κλικ στο εικονίδιο κατάταξης.\"\n  STR_WOUNDED_DEFEND_BASE_IF: \"Αμυνόμενος τραυματίας (αν η Υγεία είναι πάνω από x%)\"\n  STR_WOUNDED_DEFEND_BASE_IF_DESC: \"Οι τραυματισμένοι στρατιώτες υπερασπίζονται επίσης τη βάση, εάν η υγεία τους είναι πάνω από το δεδομένο όριο.\"\n  STR_PLAY_BRIEFING_MUSIC_DURING_EQUIPMENT: \"Αναπαραγωγή μουσικής Ενημέρωσης για μεγαλύτερο χρονικό διάστημα\"\n  STR_PLAY_BRIEFING_MUSIC_DURING_EQUIPMENT_DESC: \"Η μουσική ενημέρωσης θα συνεχίσει να παίζει κατά τη φάση εξοπλισμού μέχρι να εμφανιστεί το Πεδίο Μάχης.\"\n  STR_NIGHT_VISION_COLOR: \"Επιλέξτε το χρώμα Νυχτερινής όρασης\"\n  STR_NIGHT_VISION_COLOR_DESC: \"Τιμές από 1 έως 15, καθεμία από τις οποίες αντιπροσωπεύει διαφορετικό χρώμα απόχρωσης.\"\n  STR_AUTO_NIGHT_VISION_THRESHOLD: \"Αυτόματο όριο νυχτερινής όρασης\"\n  STR_AUTO_NIGHT_VISION_THRESHOLD_DESC: \"Αν είναι πιο σκοτεινό από αυτό το όριο, ενεργοποιήστε αυτόματα τη Νυχτερινή όραση.\"\n  STR_SHOW_ACCURACY_ON_CROSSHAIR: \"Εμφάνιση ακρίβειας στο στόχαστρο\"\n  STR_SHOW_ACCURACY_ON_CROSSHAIR_DESC: \"{ALT}0>{ALT}Ποτέ {ALT}1>{ALT}Μόνο εάν είναι ενεργοποιημένη η ακρίβεια του UFO Extender {ALT}2>{ALT}Πάντα\"\n  STR_REACTION_FIRE_THRESHOLD: \"Όριο αντίδρασης πυρός\"\n  STR_REACTION_FIRE_THRESHOLD_DESC: \"Οι μονάδες που ελέγχονται από το Xcom δεν θα αντιδράσουν σε πυρ, εάν η ακρίβειά τους (για έναν δεδομένο στόχο) είναι κάτω από αυτό το όριο.\"\n  STR_AUTO_SELL: \"Διαχειριστής αυτόματης πώλησης\"\n  STR_AUTO_SELL_DESC: \"Στην οθόνη πώλησης ενημερωτικού δελτίου μάχης, τυχόν τύποι αντικειμένων που πουλήσατε σε προηγούμενες μάχες θα επισημαίνονται αυτόματα για πώληση.\"\n  STR_AUTOMATICPROMOTIONS: \"Αυτόματες προωθήσεις\"\n  STR_AUTOMATICPROMOTIONS_DESC: \"Εάν ενεργοποιηθεί, οι στρατιώτες προάγονται αυτόματα μετά από μια αποστολή.\"\n  STR_OFF_CENTRE_SHOOTING: \"Πυροβολισμοί εκτός κέντρου\"\n  STR_OFF_CENTRE_SHOOTING_DESC: \"Οι στρατιώτες θα προσπαθήσουν αυτόματα να ρυθμίσουν ελαφρώς τη γωνία βολής σε περίπτωση που δεν υπάρχει γραμμή πυρός.\"\n  STR_UNIFORM_SHOOTING_SPREAD: \"Ομοιόμορφη εξάπλωση βολής\"\n  STR_UNIFORM_SHOOTING_SPREAD_DESC: \"Η κατά ριπάς βολές είναι ομοιόμορφη προς όλες τις κατευθύνσεις και πιο μαζεμένη.\"\n  STR_CRASHED_OR_LANDED: \"Κουμπί Συνετρίβη/Προσγειώθηκε\"\n  STR_CRASHED_OR_LANDED_DESC: \"Εάν είναι ενεργοποιημένο, εμφανίζεται ένα επιπλέον κουμπί στην οθόνη Νέας Μάχης. Εναλλακτικά, πατήστε το πλήκτρο F11 για να εμφανίσετε/κρύψετε το κουμπί. {ALT}0>{ALT}Απενεργοποιημένο, {ALT}1>{ALT}Συνετρίβη, {ALT}2>{ALT}Προσγειώθηκε.\"\n  STR_GRAPHS_ZOOM_IN: \"Μεγέθυνση (Γραφήματα)\"\n  STR_GRAPHS_ZOOM_OUT: \"Σμίκρυνση (Γραφήματα)\"\n  STR_MARK_ALL_AS_SEEN: \"Σήμανση Όλων Ως Ορατών\"\n  STR_SELL_ALL: \"Πούλησε Όλα\"\n  STR_SELL_ALL_BUT_ONE: \"Πούλησε Όλα Εκτός Από Ένα\"\n  STR_TRANSFER_ALL: \"Μεταφορά Όλων\"\n  STR_REMOVE_SOLDIERS_FROM_ALL_CRAFTS: \"Αφαίρεση Στρατιωτών από Όλα Τα Σκάφοι\"\n  STR_REMOVE_SOLDIERS_FROM_CRAFT: \"Αφαίρεση Στρατιωτών Από Ένα Σκάφος\"\n  STR_REMOVE_EQUIPMENT_FROM_CRAFT: \"Αφαίρεση Εξοπλισμού Από Το Σκάφος\"\n  STR_REMOVE_ARMOR_FROM_ALL_CRAFTS: \"Αφαίρεση Πανοπλίας Από Όλα Τα Σκάφη\"\n  STR_REMOVE_ARMOR_FROM_CRAFT: \"Αφαίρεση Πανοπλιών Από Το Σκάφος\"\n  STR_REMOVE_SOLDIERS_FROM_TRAINING: \"Αφαιρέστε Τους Στρατιώτες Από Την Εκπαίδευση\"\n  STR_ADD_SOLDIERS_TO_TRAINING: \"Προσθέστε Στρατιώτες Στην Εκπαίδευση\"\n  STR_INVENTORY_ARMOR: \"Αλλάξτε την πανοπλία\"\n  STR_INVENTORY_AVATAR: \"Αλλάξτε το Avatar\"\n  STR_INVENTORY_DIARY_LIGHT: \"Προβολή Σύντομου Ημερολογίου\"\n  STR_ACTION_ITEM_1: \"Αντικείμενο Δράση 1 (Στόχος/Χρήση)\"\n  STR_ACTION_ITEM_2: \"Αντικείμενο Ενέργεια 2 (Σύντομο)\"\n  STR_ACTION_ITEM_3: \"Αντικείμενο Ενέργεια 3 (Αυτόματη)\"\n  STR_ACTION_ITEM_4: \"Αντικείμενο Δράση 4 (Σώμα με Σώμα).\"\n  STR_ACTION_ITEM_5: \"Αντικείμενο Ενέργεια 5 (Πέταγμα)\"\n  STR_INSTA_SAVE: \"Στιγμιαία αποθήκευση\"\n  STR_TOGGLE_QUICK_SEARCH: \"Ενεργοποίηση Πεδίου Γρήγορης Αναζήτησης\"\n  STR_TOGGLE_NIGHT_VISION: \"Ενεργοποίηση Νυχτερινής Όρασης\"\n  STR_HOLD_NIGHT_VISION: \"Σύντομη Νυχτερινή Όραση\"\n  STR_SELECT_MUSIC_TRACK: \"Επιλέξτε Μουσικό Κομμάτι\"\n  STR_TOGGLE_TOUCH_BUTTONS: \"Εναλλαγή Πλήκτρων Αφής\"\n  STR_TOGGLE_BRIGHTNESS: \"Εναλλαγή Φωτεινότητας (μόνο οπτικά)\"\n  STR_BRIEFING: \"Σύνοψη\"\n  STR_TOGGLE_DEBUG_MODE: \"Ενεργοποίηση Λειτουργίας Εντοπισμού Σφαλμάτων\"\n  STR_DEBUG_KILL_ALL_ALIENS: \"DEBUG: Σκοτώστε Όλους Τους Εξωγήινους\"\n  STR_PHYSICAL_TRAINING: \"Εκπαίδευση Σε Πολεμικές Τέχνες\"\n  STR_REMAINING_TRAINING_FACILITY_CAPACITY: \"ΥΠΟΜΕΝΟΥΣΑ ΕΚΠΑΙΔΕΥΤΙΚΗ ΙΚΑΝΟΤΗΤΑ> {ALT}{0}\"\n  STR_NO_WOUNDED: \"-\"\n  STR_NO_QUEUED: \"+\"\n  STR_NO_DONE: \"ΕΓΕΙΝΕ\"\n  STR_NO_AMMO: \"ΧΩΡΙΣ ΠΥΡΟΜΑΧΙΚΑ!\"\n  STR_START_FIRING: \"Πυρ!\"\n  STR_SKIP_FIRING: \"Αφήστε τους να μπουν…\"\n  STR_ALIEN_MISSILES_HAVE_DAMAGED_OUR_BASE: \"Εξωγήινοι πύραυλοι προκάλεσαν ζημιά στη βάση μας {0}\"\n  STR_ALIEN_MISSILES_HAVE_DESTROYED_OUR_BASE: \"Εξωγήινοι πύραυλοι κατέστρεψαν τη βάση μας {0}\"\n  STR_STARTING_CONDITION_COMMANDER: \"Αυτή η αποστολή απαιτεί την παρουσία του διοικητή.\"\n  STR_STARTING_CONDITION_CRAFT: \"Αυτό το σκάφος είναι ακατάλληλο για αυτήν την αποστολή.\"\n  STR_STARTING_CONDITION_CRAFT_ALLOWED: \"Αυτό το σκάφος είναι ακατάλληλο για αυτήν την αποστολή.{NEWLINE}{NEWLINE}Επιτρεπόμενο σκάφος: {0}\"\n  STR_STARTING_CONDITION_CRAFT_FORBIDDEN: \"Αυτό το σκάφος είναι ακατάλληλο για αυτήν την αποστολή.{NEWLINE}{NEWLINE}Απαγορευμένο σκάφος: {0}\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE: \"Ορισμένοι στρατιώτες δεν μπορούν να συμμετάσχουν σε αυτήν την αποστολή.\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE_ALLOWED: \"Ορισμένοι στρατιώτες δεν μπορούν να συμμετάσχουν σε αυτήν την αποστολή.{NEWLINE}{NEWLINE}Επιτρεπόμενοι τύποι στρατιωτών: {0}\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE_FORBIDDEN: \"Ορισμένοι στρατιώτες δεν μπορούν να συμμετάσχουν σε αυτήν την αποστολή.{NEWLINE}{NEWLINE}Απαγορευμένοι τύποι στρατιωτών: {0}\"\n  STR_STARTING_CONDITION_ITEM: \"Αυτή η αποστολή απαιτεί συγκεκριμένο(α) αντικείμενο(α):{NEWLINE}{NEWLINE}{0}\"\n  STR_NOT_ENOUGH_FUEL_TO_REACH_TARGET: \"ΑΝΕΠΑΡΚΗ ΚΑΥΣΙΜΑ!{SMALLLINE}Ο προορισμός είναι εκτός εμβέλειας του σκάφους.\"\n  STR_TOO_MANY_ITEMS_ONBOARD: \"ΠΑΡΑ ΠΟΛΛΑ ΑΝΤΙΚΕΙΜΕΝΑ!{SMALLLINE}Αυτό το σκάφος δεν μπορεί να μεταφέρει τόσα πολλά αντικείμενα.\"\n  STR_ARMOR_NOT_ALLOWED_ONBOARD: \"Η ΘΩΡΑΚΙΣΗ ΔΕΝ ΕΠΙΤΡΕΠΕΤΑΙ!{SMALLLINE}Μερικοί στρατιώτες φορούν απαγορευμένη πανοπλία.\"\n  STR_FOLLOW_WING_LEADER_QUESTION: \"Ακολουθήστε τον αρχηγό της πτέρυγας;\"\n  STR_ASSIGN_PILOTS: \"Αναθέστε πιλότους...\"\n  STR_NOT_ENOUGH_PILOTS: \"Δεν υπάρχουν αρκετοί πιλότοι!{NEWLINE}Ελάχιστο: {0}\"\n  STR_DAILY_PILOT_EXPERIENCE: \"Καθημερινή Εμπειρία Πιλότου\"\n  STR_UFO_SHIELD_HIT: \"ΧΤΥΠΗΣΑΤΕ ΤΙΣ ΑΣΠΙΔΕΣ!\"\n  STR_UFO_HIT_NO_DAMAGE: \"ΑΝΑΠΗΔΗΣΕ ΑΠΟ ΤΟ ΣΚΑΦΟΣ!\"\n  STR_UFO_SHIELD_DOWN: \"ΤΕΛΟΣ ΟΙ ΑΣΠΙΔΕΣ ΤΟΥ ΕΧΘΡΟΥ!\"\n  STR_UFO_HIT_GLANCING: \"ΑΣΤΡΑΠΙΑΙΟ ΧΤΥΠΗΜΑ!\"\n  STR_INTERCEPTOR_SHIELD_HIT: \"ΟΙ ΑΣΠΙΔΕΣ ΜΑΣ ΚΡΑΤΟΥΝ!\"\n  STR_TRACTOR_BEAM_ENGAGED: \"Η ΔΕΣΜΗ ΕΛΞΗΣ ΕΙΝΑΙ ΕΝΕΡΓΟΠΟΙΗΜΕΝΗ!\"\n  STR_TRACTOR_BEAM_DISENGAGED: \"ΑΠΕΝΕΡΓΟΠΟΙΗΣΗ ΔΕΣΜΗΣ ΕΛΞΗΣ\"\n  STR_SELF_DESTRUCT_ACTIVATED: \"Η ΑΥΤΟΚΑΤΑΣΤΡΟΦΗ ΕΝΕΡΓΟΠΟΙΗΘΗΚΕ!\"\n  STR_SELF_DESTRUCT_CANCELLED: \"Η ΑΥΤΟΚΑΤΑΣΤΡΟΦΗ ΑΠΕΝΕΡΓΟΠΟΙΗΘΗΚΕ!\"\n  STR_MISSILE_DAMAGED: \">>> Ο ΠΥΡΑΥΛΟΣ ΕΧΕΙ ΖΗΜΙΑ <<<\"\n  STR_MISSILE_DESTROYED: \">>> Ο ΠΥΡΑΥΛΟΣ  ΚΑΤΑΣΤΡΑΦΗΚΕ <<<\"\n  STR_EXTENDED_LINKS: \"Σύνδεσμοι\"\n  STR_AUTO_PATROL: \"ΑΥΤΟΠΕΡΙΠΟΛΙΑ\"\n  STR_ETA: \"ETA>{ALT}{0}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_FACILITY_AT_BASE: \"Δεν υπάρχουν αρκετά {0} για να επανοπλιστεί το {1} στο {2}\"\n  STR_UFO_STARTED_HUNTING: \"Ο χρήστης {0} βρίσκεται σε μια πορεία αναχαίτισης με τον {1}\"\n  STR_CRAFT_IS_READY: \"Το {0} στο {1} είναι έτοιμο.\"\n  STR_ECONOMY_WARNING: \"Τα κεφάλαια {0} και το εισόδημα {1} είναι χαμηλά και η συντήρηση {2} πολύ υψηλή! Πουλήστε κάτι για να αποφύγετε την πίστωση... λείπουν κεφάλαια: {3}\"\n  STR_SLACKING_INDICATOR: \"{0}:{1}\"\n  STR_TRAINING_INDICATOR: \"{0}:{1}\"\n  STR_EXTENDED_UC: \"ΕΠΕΚΤΕΙΝΟΜΕΝΟ\"\n  STR_RETURNING: \"ΕΠΙΣΤΡΕΦΟΝΤΑΣ\"\n  STR_INTERCEPTING: \"ΑΝΑΧΑΙΤΊΖΟΝΤΑΣ\"\n  STR_ESCORTING: \"ΣΥΝΟΔΕΙΑ\"\n  STR_EN_ROUTE: \"ΣΤΗ ΔΙΑΔΡΟΜΗ\"\n  STR_PILOT_MISSING: \"Ο ΠΙΛΟΤΟΣ ΑΓΝΟΕΙΤΑΙ\"\n  STR_DAY_SHORT: \"{0}d\"\n  STR_HOUR_SHORT: \"{0}h\"\n  STR_PERFORMANCE_BONUS: \"Μπόνους Απόδοσης\"\n  STR_COUNTRY_HAS_CANCELLED_A_SECRET_PACT: \"Ο {0} αποκήρυξε το σύμφωνο με εξωγήινες δυνάμεις και του επετράπη να επιστρέψει στο έργο.\"\n  STR_COUNTRIES_HAVE_CANCELLED_A_SECRET_PACT: \"Οι {0} έχουν αποκηρύξει το σύμφωνο με εξωγήινες δυνάμεις και τους επετράπη να επιστρέψουν στο έργο.\"\n  STR_WE_CAN_NOW_RENT: \"Τώρα μπορούμε να νοικιάσουμε\"\n  STR_REQUIRED_BASE_SERVICES: \"Απαιτούμενες υπηρεσίες βάσης: {0}\"\n  STR_WE_CAN_NOW_BUILD: \"Τώρα μπορούμε να χτίσουμε\"\n  STR_WE_CAN_NOW_PURCHASE: \"Τώρα μπορούμε να αγοράσουμε\"\n  STR_NOT_ENOUGH_LIVING_SPACE_AT_BASE: \"Δεν υπάρχει αρκετός χώρος διαβίωσης{NEWLINE}{0}{NEWLINE}στο{NEWLINE}{1}\"\n  STR_INFO: \"ΠΛΗΡΟΦΟΡΙΕΣ\"\n  STR_DESPAWN_PENALTY: \"Despawn ποινή> {0}\"\n  STR_TRAINING_FINISHED: \"Η εκπαίδευση ολοκληρώθηκε{NEWLINE}στις {0}\"\n  STR_PSI_TRAINING_FINISHED: \"Η εκπαίδευση Ψ ολοκληρώθηκε{NEWLINE}στις {0}\"\n  STR_IGNORE_UC: \"ΑΓΝΟΗΣΕ\"\n  STR_UFO_TRACKER: \"Ανιχνευτής ΑΤΙΑ\"\n  STR_UPDATE: \"Αναβάθμηση\"\n  STR_LATEST_VERSION_INFO: \"Χρησιμοποιείτε την πιο πρόσφατη έκδοση του OpenXcom.\"\n  STR_MASTER_MOD_VERSION_REQUIRED_QUESTION: \"Αυτή η τροποποίηση απαιτεί την έκδοση {0} του βασικού παιχνιδιού για να εκτελεστεί σωστά. Ενεργοποίηση αυτής της τροποποίησης;\"\n  STR_VERSION_REQUIRED_QUESTION: \"Αυτή η τροποποίηση απαιτεί OXCE v{0} για να εκτελεστεί σωστά. Ενεργοποίηση αυτής της τροποποίησης;\"\n  STR_OPEN_MODS_FOLDER: \"Άνοιξε\"\n  STR_GLOBE_TEXTURE: \"Υφή Υδρόγειου\"\n  STR_NOTES: \"Σημειώσεις\"\n  STR_NEW_NOTE: \"<NEW NOTE>\"\n  STR_ENGINE_OXC: \"OXC\"\n  STR_ENGINE_OXCE: \"OXCE\"\n  STR_ENGINE_OTHER: \"ΆΛΛΟ\"\n  STR_BASESCAPE: \"Βασικό τοπίο\"\n  STR_AI: \"AI\"\n  STR_PATH_ENERGY_COST: \"Ενέργεια\"\n  STR_PATH_ENERGY_COST_DESC: \"Κάνοντας κλικ εμφανίζεται η ενέργεια που θα απομένει στη μονάδα σας μετά τη μετακίνηση στον προορισμό.\"\n  STR_VEHICLES_LOST: \"Τα οχήματα χάθηκαν\"\n  STR_CRAFT_LOST_DOGFIGHT: \"Αναχαιτιστικά χάθηκαν\"\n  STR_CRAFT_LOST_MISSION: \"Μεταγωγικά χάθηκαν\"\n  STR_ALIEN_BASES_DESTROYED: \"Βάση εξωγήινων καταστράφηκε\"\n  STR_XCOM_BASES_LOST: \"Βάσεις χάθηκαν\"\n  STR_TEST_SCREEN: \"ΟΘΟΝΗ ΔΟΚΙΜΗΣ\"\n  STR_PALETTE: \"Παλέτα:\"\n  STR_PREVIEW: \"Προεπισκόπηση\"\n  STR_TINY_BORDERLESS: \"Μικροσκοπικό, χωρίς περιθώρια\"\n  STR_TINY_BORDER: \"Μικροσκοπικό\"\n  STR_SMALL_LOW_CONTRAST: \"Μικρό\"\n  STR_SMALL_HIGH_CONTRAST: \"Μικρή, υψηλή αντίθεση\"\n  STR_BIG_LOW_CONTRAST: \"Μεγάλη\"\n  STR_BIG_HIGH_CONTRAST: \"Μεγάλη, υψηλή αντίθεση\"\n  STR_TEST_CASE: \"Περίπτωση δοκιμής:\"\n  STR_RUN: \"Εκτελέστε την επιλεγμένη δοκιμή!\"\n  STR_TESTS_STARTING: \"Έναρξη...\"\n  STR_TESTS_ERRORS_FOUND: \"Συνολικά σφάλματα που βρέθηκαν (μπορεί να υπάρχουν διπλότυπα): {0}\"\n  STR_TESTS_NO_ERRORS_FOUND: \"Δεν βρέθηκαν σφάλματα.\"\n  STR_TESTS_FINISHED: \"Ολοκληρωμένος.\"\n  STR_DETAILED_INFO_IN_LOG_FILE: \"Οι αναλυτικές πληροφορίες έχουν αποθηκευτεί στο openxcom.log\"\n  STR_RANK_NONE: \"-\"\n  STR_DAMAGE_NONE: \"ΚΑΝΕΝΑ\"\n  STR_INFO_UFOPEDIA: \"ΠΛΗΡΟΦΟΡΙΕΣ\"\n  STR_COCKPIT_CAPACITY: \"ΠΙΛΟΤΟΙ>{ALT}{0}{ALT}\"\n  STR_MAXIMUM_RANGE: \"ΜΑΞΙΜΟΥΜ ΑΠΟΣΤΑΣΗ>{ALT}{0}{ALT}\"\n  STR_MINIMUM_RANGE: \"ΜΙΝΙΜΟΥΝ ΑΠΟΣΤΑΣΗ>{ALT}{0}{ALT}\"\n  STR_INFINITE_RANGE: \"N/A\"\n  STR_TRACTOR_BEAM_POWER: \"Δύναμη\"\n  STR_WEIGHT_PEDIA1: \"Wt: {0}\"\n  STR_WEIGHT_PEDIA2: \"Wt: {0}/{1}\"\n  STR_SHOT_TYPE_MELEE: \"Σώμα με σώμα\"\n  STR_ACCURACY_MODIFIER: \"Τροποποιητής Ευστοχίας>{ALT} {0}\"\n  STR_POWER_BONUS: \"Μπόνους ισχύος>{ALT} {0}\"\n  STR_MULTIPLE_DIFFERENT_BONUSES: \"πολλαπλά μπόνους σε διάφορα συμβατά πυρομαχικά\"\n  STR_STATS_FOR_NERDS: \"Στατιστικά για Σπασίκλες\"\n  STR_ARTICLE: \"Άρθρο>{ALT} {0}\"\n  STR_COMPATIBLE_AMMO: \"Συμβατά πυρομαχικά:\"\n  STR_BUILT_IN_ITEMS: \"Ενσωματωμένα είδη:\"\n  STR_CLIP_SIZE_UNLIMITED: \"απεριόριστα\"\n  STR_SHOTGUN_BEHAVIOR_OXCE: \"εκτεταμένο\"\n  STR_INCLUDE_DEBUG: \"ΕΝΤΟΠΙΣΜΟΣ ΣΦΑΛΜΑΤΩΝ\"\n  STR_INCLUDE_IDS: \"Ταυτότητες\"\n  STR_INCLUDE_DEFAULTS: \"ΠΡΟΕΠΙΛΟΓΕΣ\"\n  STR_TRUE: \"αλήθες\"\n  STR_FALSE: \"ψευδής\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH: \"ΔΕΞΙΟΤΗΤΑ Ψ*ΔΥΝΑΜΗ Ψ\"\n  STR_STRENGTH_AND_MELEE_ACCURACY: \"ΔΥΝΑΜΗ* ΑΚΡΙΒΕΙΑ ΣΥΜΠΛΟΚΗΣ\"\n  STR_STRENGTH_AND_THROWING_ACCURACY: \"ΔΥΝΑΜΗ*ΑΚΡΙΒΕΙΑ ΡΙΨΗΣ\"\n  STR_FIRING_ACCURACY_AND_REACTIONS: \"ΑΚΡΙΒΕΙΑ ΒΟΛΗΣ*ΑΝΤΙΔΡΑΣΕΙΣ\"\n  STR_HEALTH_CURRENT: \"ΤΡΕΧΟΥΣΑ ΥΓΕΙΑ\"\n  STR_MANA_CURRENT: \"ΤΡΕΧΟΥΣΑ ΜΑΓΕΙΑ\"\n  STR_TIME_UNITS_CURRENT: \"ΤΡΕΧΟΥΣΕΣ ΜΟΝΑΔΕΣ ΧΡΟΝΟΥ\"\n  STR_STUN_LEVEL_CURRENT: \"ΤΡΕΧΟΝ ΕΠΙΠΕΔΟ ΑΝΑΙΣΘΗΣΙΑΣ\"\n  STR_HEALTH_NORMALIZED: \"ΟΜΑΛΟΠΟΙΗΜΕΝΗ ΥΓΕΙΑ\"\n  STR_MANA_NORMALIZED: \"ΟΜΑΛΟΠΟΙΗΜΕΝΗ ΜΑΓΕΙΑ\"\n  STR_TIME_UNITS_NORMALIZED: \"ΟΜΑΛΟΠΟΙΗΜΕΝΕΣ ΜΟΝΑΔΕΣ ΧΡΟΝΟΥ\"\n  STR_ENERGY_NORMALIZED: \"ΟΜΑΛΟΠΟΙΗΜΕΝΗ ΕΝΕΡΓΕΙΑ\"\n  STR_MORALE_NORMALIZED: \"ΟΜΑΛΟΠΟΙΗΜΕΝΟ ΗΘΙΚΟ\"\n  STR_STUN_LEVEL_NORMALIZED: \"ΟΜΑΛΟΠΟΙΗΜΕΝΟ ΕΠΙΠΕΔΟ ΑΝΑΙΣΘΗΣΙΑΣ\"\n  STR_ENERGY_REGENERATION: \"ΑΝΑΠΛΗΡΩΣΗ ΕΝΕΡΓΕΙΑΣ\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH_ABBREVIATION: \"PSK*PST\"\n  STR_STRENGTH_AND_MELEE_ACCURACY_ABBREVIATION: \"STR*MEL\"\n  STR_STRENGTH_AND_THROWING_ACCURACY_ABBREVIATION: \"STR*THR\"\n  STR_FIRING_ACCURACY_AND_REACTIONS_ABBREVIATION: \"ACC*REA\"\n  STR_HEALTH_CURRENT_ABBREVIATION: \"ΤΡΕΧΟΥΣΑ ΥΓΕΙΑ\"\n  STR_MANA_CURRENT_ABBREVIATION: \"ΤΡΕΧΟΥΣΑ ΜΑΓΕΙΑ\"\n  STR_TIME_UNITS_CURRENT_ABBREVIATION: \"ΤΡΕΧΟΥΣΕΣ ΜΟΝΑΔΕΣ ΧΡΟΝΟΥ\"\n  STR_STUN_LEVEL_CURRENT_ABBREVIATION: \"ΤΡΕΧΟΝ ΕΠΙΠΕΔΟ ΑΝΑΙΣΘΗΣΙΑΣ\"\n  STR_HEALTH_NORMALIZED_ABBREVIATION: \"ΟΜΑΛΟΠΟΙΗΜΕΝΗ ΥΓΕΙΑ\"\n  STR_MANA_NORMALIZED_ABBREVIATION: \"ΟΜΑΛΟΠΟΙΗΜΕΝΗ ΜΑΓΕΙΑ\"\n  STR_TIME_UNITS_NORMALIZED_ABBREVIATION: \"ΟΜΑΛΟΠΟΙΗΜΕΝΕΣ ΜΟΝΑΔΕΣ ΧΡΟΝΟΥ\"\n  STR_ENERGY_NORMALIZED_ABBREVIATION: \"ΟΜΑΛΟΠΟΙΗΜΕΝΗ ΕΝΕΡΓΕΙΑ\"\n  STR_MORALE_NORMALIZED_ABBREVIATION: \"ΟΜΑΛΟΠΟΙΗΜΕΝΟ ΗΘΙΚΟ\"\n  STR_STUN_LEVEL_NORMALIZED_ABBREVIATION: \"ΟΜΑΛΟΠΟΙΗΜΕΝΟ ΕΠΙΠΕΔΟ ΑΝΑΙΣΘΗΣΙΑΣ\"\n  STR_ENERGY_REGENERATION_ABBREVIATION: \"ΑΝΑΠΛΗΡΩΣΗ ΕΝΕΡΓΕΙΑΣ\"\n  STR_TIME_UNITS_SCALED: \"ΚΛΙΜΑΚΩΜΕΝΕΣ ΜΟΝΑΔΕΣ ΧΡΟΝΟΥ\"\n  STR_STAMINA_SCALED: \"ΚΛΙΜΑΚΕΥΜΕΝΗ ΑΝΤΟΧΗ\"\n  STR_HEALTH_SCALED: \"ΚΛΙΜΑΚΩΜΕΝΗ ΥΓΕΙΑ\"\n  STR_BRAVERY_SCALED: \"ΚΛΙΜΑΚΩΜΕΝΗΓΕΝΝΑΙΟΤΗΤΑ\"\n  STR_REACTIONS_SCALED: \"ΚΛΙΜΑΚΩΜΕΝΕΣ ΑΝΤΙΔΡΑΣΕΙΣ\"\n  STR_FIRING_ACCURACY_SCALED: \"ΚΛΙΜΑΚΩΜΕΝΗ ΑΚΡΙΒΕΙΑ ΒΟΛΗΣ\"\n  STR_THROWING_ACCURACY_SCALED: \"ΚΛΙΜΑΚΩΜΕΝΗ ΑΚΡΙΒΕΙΑ ΡΙΨΗΣ\"\n  STR_STRENGTH_SCALED: \"ΚΛΙΜΑΚΩΜΕΝΗ ΔΥΝΑΜΗ\"\n  STR_PSIONIC_STRENGTH_SCALED: \"ΚΛΙΜΑΚΩΜΕΝΗ ΨΙΟΝΙΚΗ ΔΥΝΑΜΗ\"\n  STR_PSIONIC_SKILL_SCALED: \"ΚΛΙΜΑΚΩΜΕΝΗ ΨΙΟΝΙΚΗ ΔΕΞΙΟΤΗΤΑ\"\n  STR_MELEE_ACCURACY_SCALED: \"ΚΛΙΜΑΚΩΜΕΝΗ ΑΚΡΙΒΕΙΑ ΣΥΓΚΡΟΥΣΗΣ\"\n  STR_MANA_POOL_SCALED: \"ΚΛΙΜΑΚΩΜΕΝΟ ΤΑΜΕΊΟ ΜΑΓΕΙΑΣ\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH_SCALED: \"ΚΛΙΜΑΚΩΜΕΝΗ ΔΕΞΙΟΤΗΤΑ Ψ*ΔΥΝΑΜΗ Ψ\"\n  STR_STRENGTH_AND_MELEE_ACCURACY_SCALED: \"ΚΛΙΜΑΚΩΜΕΝΗ ΔΥΝΑΜΗ*ΑΚΡΙΒΕΙΑ ΣΥΓΚΡΟΥΣΗΣ\"\n  STR_STRENGTH_AND_THROWING_ACCURACY_SCALED: \"ΚΛΙΜΑΚΩΜΕΝΗ ΔΥΝΑΜΗ*ΑΚΡΙΒΕΙΑ ΡΙΨΗΣ\"\n  STR_FIRING_ACCURACY_AND_REACTIONS_SCALED: \"ΚΛΙΜΑΚΩΜΕΝΗ ΑΚΡΙΒΕΙΑ ΒΟΛΗΣ*ΑΝΤΙΔΡΑΣΕΙΣ\"\n  STR_TIME_UNITS_SCALED_ABBREVIATION: \"ΚΛΙΜΑΚΩΜΕΝΕΣ TU\"\n  STR_STAMINA_SCALED_ABBREVIATION: \"ΚΛΙΜΑΚΩΜΕΝΕΣ STA\"\n  STR_HEALTH_SCALED_ABBREVIATION: \"ΚΛΙΜΑΚΩΜΕΝΕΣ HP\"\n  STR_BRAVERY_SCALED_ABBREVIATION: \"ΚΛΙΜΑΚΩΜΕΝΕΣ BRV\"\n  STR_REACTIONS_SCALED_ABBREVIATION: \"ΚΛΙΜΑΚΩΜΕΝΕΣ REA\"\n  STR_FIRING_ACCURACY_SCALED_ABBREVIATION: \"ΚΛΙΜΑΚΩΜΕΝΕΣ ACC\"\n  STR_THROWING_ACCURACY_SCALED_ABBREVIATION: \"ΚΛΙΜΑΚΩΜΕΝΕΣ THR\"\n  STR_STRENGTH_SCALED_ABBREVIATION: \"ΚΛΙΜΑΚΩΜΕΝΕΣ STR\"\n  STR_PSIONIC_STRENGTH_SCALED_ABBREVIATION: \"ΚΛΙΜΑΚΩΜΕΝΕΣ PST\"\n  STR_PSIONIC_SKILL_SCALED_ABBREVIATION: \"ΚΛΙΜΑΚΩΜΕΝΕΣ PSK\"\n  STR_MELEE_ACCURACY_SCALED_ABBREVIATION: \"ΚΛΙΜΑΚΩΜΕΝΕΣ MEL\"\n  STR_MANA_POOL_SCALED_ABBREVIATION: \"ΚΛΙΜΑΚΩΜΕΝΕΣ MAN\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH_SCALED_ABBREVIATION: \"ΚΛΙΜΑΚΩΜΕΝΕΣ  PSK*PST\"\n  STR_STRENGTH_AND_MELEE_ACCURACY_SCALED_ABBREVIATION: \"ΚΛΙΜΑΚΩΜΕΝΕΣ  STR*MEL\"\n  STR_STRENGTH_AND_THROWING_ACCURACY_SCALED_ABBREVIATION: \"ΚΛΙΜΑΚΩΜΕΝΕΣ  STR*THR\"\n  STR_FIRING_ACCURACY_AND_REACTIONS_SCALED_ABBREVIATION: \"ΚΛΙΜΑΚΩΜΕΝΕΣ  ACC*REA\"\n  STR_COST_TIME: \"χρόνος\"\n  STR_COST_ENERGY: \"ενέργεια\"\n  STR_COST_MORALE: \"ηθικό\"\n  STR_COST_HEALTH: \"υγεία\"\n  STR_COST_STUN: \"ζάλη\"\n  STR_COST_MANA: \"μαγεία\"\n  STR_COST_BUILD: \"χτίσε\"\n  STR_COST_REFUND: \"επιστροφή\"\n  STR_DAMAGE_10: \"10\"\n  STR_DAMAGE_11: \"11\"\n  STR_DAMAGE_12: \"12\"\n  STR_DAMAGE_13: \"13\"\n  STR_DAMAGE_14: \"14\"\n  STR_DAMAGE_15: \"15\"\n  STR_DAMAGE_16: \"16\"\n  STR_DAMAGE_17: \"17\"\n  STR_DAMAGE_18: \"18\"\n  STR_DAMAGE_19: \"19\"\n  STR_NAUTICAL_MILES: \"{0} ναυτικά μίλια\"\n  STR_KILOMETERS_PER_HOUR: \"{0} χμ/ω\"\n  STR_SECONDS_LONG: \"{0} δευτερόλεπτα\"\n  STR_RACE_BONUS: \"Μπόνους αγώνα\"\n  STR_FOR_DIFFICULTY: \"για δυσκολία: {0}\"\n  STR_NOT_AWARDED_YET: \"Δεν έχει βραβευτεί ακόμη\"\n"
  },
  {
    "path": "bin/common/Language/OXCE/en-GB.yml",
    "content": "en-GB:\n#=================== Basescape ===================\n#BasescapeState.cpp\n  STR_CANNOT_DISMANTLE_FACILITY_UPGRADING: \"CANNOT DISMANTLE FACILITY!{SMALLLINE}Facility cannot be removed during upgrading.\"\n#BaseView.cpp\n  STR_CANNOT_UPGRADE_FACILITY_ALREADY_UPGRADING: \"CANNOT BUILD HERE!{SMALLLINE}Existing facility is already being built over.\"\n  STR_CANNOT_UPGRADE_FACILITY_WRONG_SIZE: \"CANNOT BUILD HERE!{SMALLLINE}Selected facility must completely cover existing facility.\"\n  STR_CANNOT_UPGRADE_FACILITY_WRONG_TYPE: \"CANNOT BUILD HERE!{SMALLLINE}Existing facility cannot be upgraded over by selected facility.\"\n  STR_CANNOT_UPGRADE_FACILITY_DISALLOWED: \"CANNOT BUILD HERE!{SMALLLINE}Existing facility cannot be built over.\"\n  STR_CANNOT_BUILD_QUEUE_OFF: \"CANNOT BUILD HERE!{SMALLLINE}Connecting facilities must finish construction first.\"\n  STR_CANNOT_BUILD_UPGRADE_ONLY: \"CANNOT BUILD HERE!{SMALLLINE}This facility can be built only as an upgrade of another facility.\"\n  STR_FACILITY_FORBIDDEN_BY_OTHER: \"CANNOT BUILD HERE!{SMALLLINE}Some existing facility forbids building this facility.\"\n  STR_FACILITY_OTHER_FORBIDDEN_BY_THIS: \"CANNOT BUILD HERE!{SMALLLINE}Some existing facility would be forbidden by this facility.\"\n  STR_NOT_ENOUGH_ITEMS: \"NOT ENOUGH MATERIALS!{SMALLLINE}We need more resources to build this facility.{NEWLINE}Missing> {0}: {1}\"\n#CraftArmorState.cpp\n  STR_ID: \"ID\"\n  STR_FIRST_LETTER: \"FIRST LETTER\"\n  STR_SOLDIER_TYPE: \"SOLDIER TYPE\"\n  STR_IDLE_DAYS: \"IDLE DAYS\"\n  STR_MANA: \"MANA\"\n  STR_MANA_POOL: \"MANA POOL\"\n  STR_MANA_MISSING: \"MANA MISSING\"\n#CraftEquipmentLoadState.cpp\n  STR_LOAD_CRAFT_LOADOUT_TEMPLATE: \"Load Craft Loadout\"\n  STR_EMPTY_SLOT_N: \"Empty slot {0}\"\n  STR_UNNAMED_SLOT_N: \"Unnamed slot {0}\"\n  STR_ADD_ON_TOP: \"Add on top\"\n#CraftEquipmentSaveState.cpp\n  STR_SAVE_CRAFT_LOADOUT_TEMPLATE: \"Save Craft Loadout\"\n  STR_SAVE_UC: \"SAVE\"\n#CraftEquipmentState.cpp\n  STR_ALL: \"Everything\"\n  STR_EQUIPPED: \"Equipped\"\n  STR_NOT_EQUIPPED: \"Not equipped\"\n  STR_UNASSIGNED: \"Other\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED_BY_SIZE: \"NO MORE EQUIPMENT ALLOWED ON BOARD!{SMALLLINE}Maximum storage space: {0}\"\n#CraftInfoState.cpp\n  STR_PILOTS: \"PILOTS\"\n  STR_SHIELD: \"SHIELD>{ALT}{0}\"\n  STR_CRAFT_SKIN_ID: \"[{0}]\"\n#CraftPilotSelectState.cpp\n  STR_SELECT_PILOT: \"Select Pilot\"\n#CraftPilotsState.cpp\n  STR_PILOTS_FOR_CRAFT: \"Pilot(s) for {0}\"\n  STR_PILOTS_REQUIRED: \"Pilot(s) required: {ALT}{0}\"\n  STR_ADD_PILOT: \"Add Pilot\"\n  STR_REMOVE_ALL_PILOTS: \"Remove All Pilots\"\n  STR_ACCURACY_BONUS: \"Accuracy bonus:\"\n  STR_DODGE_BONUS: \"Dodge bonus:\"\n  STR_APPROACH_SPEED: \"Approach speed:\"\n  STR_COWARDLY: \"Cowardly (-50%)\"\n  STR_NORMAL: \"Normal\"\n  STR_BOLD: \"Bold (+50%)\"\n  STR_VERY_BOLD: \"Very bold (+100%)\"\n#CraftSoldiersState.cpp\n  STR_ARMOR_GROUP_NOT_ALLOWED: \"This armor type is not allowed onboard.\"\n  STR_SOLDIER_GROUP_NOT_ALLOWED: \"This soldier type is not allowed onboard.\"\n  STR_SOLDIER_GROUP_NOT_SAME: \"This soldier type is not compatible with other soldiers onboard.\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW: \"Preview\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_SAVED: \"Preview *\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_BRIEFING: \"This feature allows you to preview and customise the deployment of your units at the beginning of a battle. You have unlimited movement. Press and hold 'Alt' to highlight valid unit positions. Click on the 'Abort Mission' icon to save a custom deployment. Click on the 'End Turn' icon to exit the preview.{NEWLINE}Note that adding any new soldiers or vehicles to the craft automatically invalidates the saved custom deployment. Presence of a custom deployment is indicated by an asterisk on the 'Preview' button.\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_BRIEFING_DUMMY: \"This feature allows you to preview and modify the deployment table of this craft type. Any changes will apply to all your current craft and also to any craft you buy or manufacture later in the campaign. You start with the maximum number of soldiers. Each soldier represents one row in the deployment table. Soldier names correspond to row numbers. To provide space for a 2x2 unit, place 4 soldiers in a 2x2 square. If space is not provided, the 2x2 unit will be missing in a real battle.\"\n  STR_BASE_DEFENSE_BRIEFING_PREVIEW: \"This feature allows you to preview your base.{NEWLINE}Have fun!{NEWLINE}{NEWLINE}Click on the 'End Turn' icon to exit the preview.\"\n#CraftWeaponsState.cpp\n  STR_NOT_ENOUGH_CARGO_SPACE: \"NOT ENOUGH CARGO SPACE AVAILABLE!{SMALLLINE}Use a different module or reduce the assigned crew.\"\n  STR_NOT_ENOUGH_STORAGE_SPACE_1: \"NOT ENOUGH STORAGE SPACE AVAILABLE!{SMALLLINE}Too many items! Use a different module or reduce the assigned equipment.\"\n  STR_NOT_ENOUGH_STORAGE_SPACE_2: \"NOT ENOUGH STORAGE SPACE AVAILABLE!{SMALLLINE}The items take up too much space! Use a different module or reduce the size of assigned equipment.\"\n#DismantleFacilityState.cpp\n  STR_REFUND_VALUE: \"Sales value> {ALT}{0}\"\n  STR_REFUND_VALUE_NEGATIVE: \"Expenses> {ALT}{0}\"\n#GlobalManufactureState.cpp\n  STR_PRODUCTION_OVERVIEW: \"PRODUCTION OVERVIEW\"\n#GlobalResearchDiaryState.cpp\n  STR_RESEARCH_DIARY: \"RESEARCH DIARY\"\n  STR_DISCOVERY_SOURCE_BASE: \"This item was discovered via a research project.{NEWLINE}Research base> {ALT}{1}{ALT}{NEWLINE}Item code> {ALT}{0}{ALT}\"\n  STR_DISCOVERY_SOURCE_FREE_FROM: \"This item was given for free from another research project.{NEWLINE}From research project> {ALT}{2}{ALT}{NEWLINE}{ALT}{1}{ALT} -> {ALT}{0}{ALT}\"\n  STR_DISCOVERY_SOURCE_FREE_AFTER: \"This technical item was discovered automatically.{NEWLINE}After research project> {ALT}{2}{ALT}{NEWLINE}{ALT}{1}{ALT} -> {ALT}{0}{ALT}\"\n  STR_DISCOVERY_SOURCE_MISSION: \"This item was given for free as a mission reward.{NEWLINE}Mission type> {ALT}{2}{ALT}{NEWLINE}{ALT}{1}{ALT} -> {ALT}{0}{ALT}\"\n  STR_DISCOVERY_SOURCE_EVENT: \"This item was given for free as an event reward.{NEWLINE}Event type> {ALT}{2}{ALT}{NEWLINE}{ALT}{1}{ALT} -> {ALT}{0}{ALT}\"\n#GlobalResearchState.cpp\n  STR_RESEARCH_OVERVIEW: \"RESEARCH OVERVIEW\"\n#GlobalAlienContainmentState.cpp\n  STR_PRISONER_OVERVIEW: \"PRISONER OVERVIEW\"\n  STR_PRISONER: \"PRISONER\"\n  STR_PRISONER_AMOUNT: \"AMOUNT\"\n  STR_PRISONER_INTERROGATED: \"INTERROGATED\"\n  STR_TOTAL_IN_PRISON: \"Space Used>{ALT}{0}\"\n  STR_TOTAL_INTERROGATED: \"Interrogated>{ALT}{0}\"\n  STR_PRISON_TYPE: \"Alien Containment\"\n#ManageAlienContainmentState.cpp\n  STR_KILL_SELECTED: \"Kill\"\n  STR_SELL_SELECTED: \"Sell\"\n  STR_GO_TO_TRANSFERS: \"Transfer...\"\n  STR_PRISON_CLEANUP: \"Prison Cleanup\"\n#ManufactureDependenciesTreeState.cpp\n  STR_TOPIC: \"Topic>{ALT} {0}\"\n  STR_SHOW_ALL: \"Show all\"\n  STR_NO_DEPENDENCIES: \"No dependencies.\"\n  STR_DIRECT_DEPENDENCIES: \"Direct dependencies\"\n  STR_LEVEL_2_DEPENDENCIES: \"Level 2 dependencies\"\n  STR_LEVEL_3_DEPENDENCIES: \"Level 3 dependencies\"\n  STR_LEVEL_4_DEPENDENCIES: \"Level 4 dependencies\"\n  STR_MORE_DEPENDENCIES: \"There are even deeper dependencies...\"\n  STR_END_OF_SEARCH: \"End of search.\"\n#ManufactureInfoState.cpp\n  STR_FALLBACK_PRODUCTION: \"FALLBACK\"\n  STR_REFUND_PRODUCTION: \"REFUND!\"\n  STR_HOURS_PER_UNIT: \"HOURS PER UNIT>{ALT}{0}\"\n#ManufactureStartState.cpp\n  STR_PERSON_JOINING: \"Person Joining\"\n  STR_RANDOM_PRODUCTION_DISCLAIMER: \"Random production!\"\n#MonthlyCostsState.cpp\n  STR_OTHER_EMPLOYEES: \"Other Staff & Inventory\"\n#NewManufactureListState.cpp\n  STR_SHOW_ONLY_NEW: \"Show only new\"\n  STR_FILTER_DEFAULT: \"Default\"\n  STR_FILTER_DEFAULT_SUPPLIES_OK: \"Default (supplies OK)\"\n  STR_FILTER_DEFAULT_NO_SUPPLIES: \"Default (no supplies)\"\n  STR_FILTER_FACILITY_REQUIRED: \"Facility Missing\"\n  STR_FILTER_HIDDEN: \"Hidden\"\n  STR_FILTER_EQUIPPED: \"Equipped\"\n  STR_FILTER_MISSING: \"Missing\"\n#NewResearchListState.cpp\n  STR_SORT_DEFAULT: \"Default\"\n  STR_SORT_BY_COST: \"By cost\"\n  STR_SORT_BY_NAME: \"By name\"\n#ProductionCompleteState.cpp\n  STR_RANDOM_PRODUCTION_SUMMARY: \"Summary\"\n#PurchaseState.cpp\n  STR_NOT_ENOUGH_PRISON_SPACE: \"NOT ENOUGH ALIEN CONTAINMENT!{SMALLLINE}Build new alien containment or transfer aliens to other bases.\"\n  STR_MONTHLY_ITEM_PURCHASE_LIMIT_EXCEEDED: \"MONTHLY PURCHASE LIMIT EXCEEDED!{SMALLLINE}More items will be available next month.\"\n  STR_MONTHLY_CRAFT_PURCHASE_LIMIT_EXCEEDED: \"MONTHLY PURCHASE LIMIT EXCEEDED!{SMALLLINE}More craft will be available next month.\"\n  STR_MONTHLY_SOLDIER_HIRING_LIMIT_EXCEEDED: \"MONTHLY HIRING LIMIT EXCEEDED!{SMALLLINE}More recruits will be available next month.\"\n#SoldierArmorState.cpp\n  STR_NOT_ENOUGH_CRAFT_SPACE: \"Not enough space onboard!\"\n#SoldierAvatarState.cpp\n  STR_SELECT_AVATAR_FOR: \"SELECT AVATAR FOR{NEWLINE}{0}\"\n#SoldierBonusState.cpp\n  STR_SOLDIER_BONUSES_FOR: \"SOLDIER BONUSES FOR{NEWLINE}{0}\"\n  STR_SUMMARY: \"Summary\"\n#SoldierInfoState.cpp\n  STR_MANA_RECOVERY: \"MANA RECOVERY> {ALT}{0}\"\n  STR_HEALTH_RECOVERY: \"HEALTH RECOVERY> {ALT}{0}\"\n  STR_BONUSES_BUTTON: \"+\"\n#SoldierRankState.cpp\n  STR_PROMOTE_SOLDIER: \"PROMOTE/DEMOTE{NEWLINE}{0} {1}\"\n  STR_RANK_HEADER: \"RANK\"\n  STR_OPENINGS_HEADER: \"OPENINGS\"\n#SoldierDiaryOverviewState.cpp\n  STR_KILLER_AND_WEAPON: \"{0}, {1}\"\n#SoldiersState.h\n  STR_TRAINING: \"Training\"\n  STR_SOLDIER_INFO: \"Soldier Info\"\n#SoldierTransformState.cpp\n  STR_SELECT_TRANSFORMATION_FOR: \"SELECT TRANSFORMATION FOR{NEWLINE}{0}\"\n  STR_TRANSFORMATIONS_BUTTON: \"^\"\n#SoldierTransformationAssignState.cpp\n  STR_TRANSFER_TIME: \"Transfer Time>{ALT}{0}\"\n  STR_RECOVERY_TIME: \"Recovery Time>{ALT}{0}\"\n  STR_CURRENT_STATS: \"Current stats\"\n  STR_CHANGES: \"Changes\"\n  STR_CHANGES_MIN: \"Changes (min)\"\n  STR_CHANGES_MAX: \"Changes (max)\"\n  STR_BONUS_STATS: \"Bonus stats\"\n#SoldierTransformationListState.cpp\n  STR_TRANSFORMATIONS_OVERVIEW: \"Transformations Overview\"\n  STR_PROJECT_NAME: \"PROJECT NAME\"\n  STR_AVAILABLE_MATERIALS: \"AVAILABLE MATERIALS\"\n  STR_ELIGIBLE_SOLDIERS: \"ELIGIBLE SOLDIERS\"\n  STR_SHOW_ONLY_ELIGIBLE: \"Show Only Eligible\"\n  STR_ALL_SOLDIER_TYPES: \"All Soldier Types\"\n  STR_ALL_SOLDIERS: \"All Soldiers\"\n  STR_HEALTHY_SOLDIERS: \"Healthy Soldiers\"\n  STR_WOUNDED_SOLDIERS: \"Wounded Soldiers\"\n  STR_DEAD_SOLDIERS: \"Dead Soldiers\"\n#StoresState.cpp\n  STR_GRAND_TOTAL: \"Grand Total\"\n#TechTreeSelectState.cpp\n  STR_AVAILABLE_TOPICS: \"AVAILABLE TOPICS\"\n  STR_QS_THREE_LETTERS_A: \"Please enter at least 3 letters\"\n  STR_QS_THREE_LETTERS_B: \"into the Quick Search box...\"\n  STR_M_FLAG: \" [m]\"\n  STR_F_FLAG: \" [f]\"\n  STR_I_FLAG: \" [i]\"\n  STR_C_FLAG: \" [c]\"\n#TechTreeViewerState.cpp\n  STR_THIS_FEATURE_IS_DISABLED_1: \"This feature is disabled.\"\n  STR_THIS_FEATURE_IS_DISABLED_2: \"This feature is disabled.\"\n  STR_THIS_FEATURE_IS_DISABLED_3: \"This feature is disabled.\"\n  STR_THIS_FEATURE_IS_DISABLED_4: \"This feature is disabled.\"\n  STR_THIS_FEATURE_IS_DISABLED_5: \"This feature is disabled.\"\n  STR_TECH_TREE_VIEWER: \"Tech Tree Viewer\"\n  STR_SELECT_TOPIC: \"Select Topic\"\n  STR_RESEARCH_PROGRESS: \"Progress>{ALT} {0}%\"\n  STR_ITEM_DESTROYED: \"Item destroyed:\"\n  STR_ITEM_REQUIRED: \"Item required:\"\n  STR_SERVICES_REQUIRED: \"Services required:\"\n  STR_SERVICES_PROVIDED: \"Services provided:\"\n  STR_SERVICES_FORBIDDEN: \"Services forbidden:\"\n  STR_REQUIRES: \"Requires:\"\n  STR_DEPENDS_ON: \"Depends on:\"\n  STR_UNLOCKED_BY: \"Unlocked by:\"\n  STR_DISABLED_BY: \"Disabled by:\"\n  STR_REENABLED_BY: \"Re-enabled by:\"\n  STR_GET_FOR_FREE_FROM: \"Get for free from:\"\n  STR_IS_LOOKUP_OF: \"Is lookup of:\"\n  STR_LOOKUP: \"Lookup:\"\n  STR_SPAWNED_ITEMS: \"Spawned items:\"\n  STR_SPAWNED_EVENT: \"Spawned event:\"\n  STR_RANDOM_EVENTS: \"Events:\"\n  STR_REQUIRED_BY: \"Required by:\"\n  STR_REQUIRED_BY_TRANSFORMATIONS: \"Required by transformations:\"\n  STR_LEADS_TO: \"Leads to:\"\n  STR_UNLOCKS: \"Unlocks:\"\n  STR_DISABLES: \"Disables:\"\n  STR_REENABLES: \"Re-enables:\"\n  STR_GIVES_ONE_FOR_FREE_SEQ: \"Gives one for free (sequential):\"\n  STR_GIVES_ONE_FOR_FREE: \"Gives one for free:\"\n  STR_RESEARCH_REQUIRED: \"Research required:\"\n  STR_RESEARCH_REQUIRED_USE: \"Research required (use):\"\n  STR_RESEARCH_REQUIRED_BUY: \"Research required (buy):\"\n  STR_SERVICES_REQUIRED_BUY: \"Services required (buy):\"\n  STR_PRODUCED_BY: \"Produced by:\"\n  STR_SPAWNED_BY: \"Spawned by:\"\n  STR_MATERIALS_REQUIRED: \"Materials required:\"\n  STR_TTV_COST_PER_UNIT: \"Cost per unit:\"\n  STR_TTV_ENGINEER_HOURS: \"Engineer hours:\"\n  STR_TTV_WORK_SPACE_REQUIRED: \"Work space required:\"\n  STR_ITEMS_PRODUCED: \"Items produced:\"\n  STR_PERSON_RECRUITED: \"Person recruited:\"\n  STR_UNLOCKS_ARCS: \"Unlocks arcs:\"\n  STR_DISABLES_ARCS: \"Disables arcs:\"\n  STR_UNLOCKS_MISSIONS: \"Unlocks missions:\"\n  STR_DISABLES_MISSIONS: \"Disables missions:\"\n  STR_UNLOCKS_EVENTS: \"Unlocks events:\"\n  STR_DISABLES_EVENTS: \"Disables events:\"\n  STR_AFFECTS_GAME_PROGRESSION: \"Affects game progression!\"\n#TransferItemsState.cpp\n  STR_ITEMS_AT_DESTINATION: \"Items at destination\"\n  STR_PRISONERS: \"Prisoners\"\n  STR_ARMORS: \"Armors\"\n  STR_FILTER_RESEARCHED: \"Fully researched\"\n  STR_FILTER_RESEARCHABLE: \"Researchable\"\n#=================== Battlescape ===================\n#AbortMissionState.cpp\n  STR_CRAFT_DEPLOYMENT_QUESTION: \"Save Craft Deployment?\"\n#ActionMenuState.cpp\n  STR_MUST_USE_BOTH_HANDS: \"Both hands are required for this!\"\n#BattlescapeGame.cpp\n  STR_NOT_ENOUGH_MORALE: \"Not Enough Morale!\"\n  STR_NOT_ENOUGH_HEALTH: \"Not Enough Health!\"\n  STR_NOT_ENOUGH_MANA: \"Not Enough Mana!\"\n  STR_NOT_ENOUGH_STUN: \"Stun level is too high!\"\n  STR_MIND_CONTROL_SUCCESSFUL_ALT: \"Action Successful\"\n  STR_LINE_OF_SIGHT_REQUIRED: \"Line of sight (LoS) required.\"\n#BattlescapeState.cpp\n  STR_CENTER_ON_WOUNDED_FRIEND: \"Centre on Wounded Friend\"\n  STR_CENTER_ON_DIZZY_FRIEND: \"Centre on Dizzy Friend\"\n  STR_BUG_HUNT_ACTIVATED: \"Bug Hunt mode activated: enemies are visible on the minimap!\"\n  STR_QUICK_MODE_ACTIVATED: \"Usain Bolt mode activated.{NEWLINE}Press Ctrl+S again to deactivate.\"\n  STR_QUICK_MODE_DEACTIVATED: \"Usain Bolt mode deactivated.\"\n  STR_SINGLE_MAP_LAYER_ACTIVATED: \"Single map layer mode activated.{NEWLINE}Press Ctrl+C again to deactivate.\"\n  STR_SINGLE_MAP_LAYER_DEACTIVATED: \"Single map layer mode deactivated.\"\n  STR_TARGET_ENEMY: \"; Target = ENEMY\"\n  STR_TARGET_NEUTRAL: \"; Target = NEUTRAL\"\n  STR_TARGET_FRIEND: \"; Target = FRIEND\"\n  STR_TARGET_YOURSELF: \"; Target = YOURSELF\"\n  STR_TARGET_ON_THE_GROUND: \" (on the ground)\"\n  STR_USE_SPECIAL_ITEM: \"Use Special Item\"\n  STR_NO_EXPERIENCE_YET: \"No experience yet:\"\n#BriefingState.cpp\n  STR_OPERATION_UC: \"OPERATION> {0}\"\n#BriefingLightState.cpp\n  STR_WHAT_CAN_I_WEAR: \"What can I wear?\"\n  STR_STARTING_CONDITION_ARMORS_FORBIDDEN: \"This mission requires specific gear.{NEWLINE}{NEWLINE}Forbidden armour types are: {0}\"\n  STR_STARTING_CONDITION_ARMORS_ALLOWED: \"This mission requires specific gear.{NEWLINE}{NEWLINE}Allowed armour types are: {0}\"\n#ConfirmEndMissionState.cpp\n  STR_MISSION_OVER: \"Mission complete.\"\n  STR_UNITS_WITH_FATAL_WOUNDS:\n    one: \"{N} of us is still fatally wounded\"\n    other: \"{N} of us are still fatally wounded\"\n  STR_END_MISSION_QUESTION: \"End Mission?\"\n#DebriefingState.cpp\n  STR_LOOT: \"LOOT\"\n  STR_SELL: \"SELL\"\n  STR_LIVE_ALIENS_SURRENDERED: \"ENEMIES SURRENDERED\"\n  STR_MISSION_ABORTED: \"MISSION ABORTED\"\n  STR_VIPS_SAVED: \"VIPS SAVED\"\n  STR_VIPS_LOST: \"VIPS LOST\"\n  STR_BOUNTY: \"BOUNTY\"\n  STR_MANA_ABBREVIATION: \"MAN\"\n#ExperienceOverviewState.cpp\n  STR_EXPERIENCE_OVERVIEW: \"Experience Overview\"\n#Inventory.cpp\n  STR_CANNOT_PLACE_ITEM_INTO_THIS_SECTION: \"It's not allowed to place that item there.{NEWLINE}Don't ask why!\"\n  STR_ONE_HAND_MUST_BE_EMPTY: \"At least one hand must be empty!\"\n#InventoryLoadState.cpp\n  STR_LOAD_EQUIPMENT_TEMPLATE: \"Load Equipment Template\"\n#InventorySaveState.cpp\n  STR_SAVE_EQUIPMENT_TEMPLATE: \"Save Equipment Template\"\n#InventoryState.cpp\n  STR_FIRING_SHORT: \"Firing>{ALT}{0}\"\n  STR_THROWING_SHORT: \"Throw>{ALT}{0}\"\n  STR_MELEE_SHORT: \"Melee>{ALT}{0}\"\n  STR_PERSONAL_EQUIPMENT: \"PERSONAL EQUIPMENT\"\n  STR_SAVE_PERSONAL_EQUIPMENT: \"Save Personal Equipment\"\n  STR_LOAD_PERSONAL_EQUIPMENT: \"Load Personal Equipment\"\n  STR_PERSONAL_EQUIPMENT_SAVED: \"Personal equipment saved.\"\n  STR_PERSONAL_EQUIPMENT_NOT_DEFINED: \"Personal equipment is not defined yet.\"\n  STR_SLOT: \"Slot>{ALT}{0}\"\n#Map.cpp\n  STR_THINKING: \"Thinking...\"\n#NextTurnState.cpp\n  STR_TELL_ME_MORE: \"Tell me more...\"\n  STR_REINFORCEMENTS_ALERT: \"Reinforcements alert!\"\n  STR_HIT_LOG_NEW_TURN: \"New Turn\"\n#ProjectileFlyBState.cpp\n  STR_FAILED_CQB_CHECK: \"Enemy managed to interrupt your attack!\"\n  STR_NO_TRAJECTORY: \"No viable trajectory!\"\n  STR_HIT_LOG_NEW_BULLET: \"=> \"\n#SkillMenuState.cpp\n  STR_MANA_SHORT: \"MA>{ALT}{0}\"\n  STR_SKILL_NEEDS_ITEM: \"This skill needs an item!\"\n#TileEngine.cpp\n  STR_HIT_LOG_NO_DAMAGE: \"0 \"\n  STR_HIT_LOG_SMALL_DAMAGE: \"hit \"\n  STR_HIT_LOG_BIG_DAMAGE: \"HIT \"\n  STR_HIT_LOG_REACTION_FIRE: \"Reaction fire...\"\n#TurnDiaryState.cpp\n  STR_HIT_LOG: \"Hit Log\"\n#=================== Engine ===================\n#TouchState.cpp\n  STR_BUTTON_TOUCH: \"Touch\"\n  STR_BUTTON_1: \"1\"\n  STR_BUTTON_10: \"10\"\n  STR_BUTTON_100: \"100\"\n  STR_BUTTON_LMB: \"LMB\"\n  STR_BUTTON_RMB: \"RMB\"\n  STR_BUTTON_MMB: \"MMB\"\n  STR_BUTTON_CTRL: \"Ctrl\"\n  STR_BUTTON_ALT: \"Alt\"\n  STR_BUTTON_SHIFT: \"Shift\"\n#Options.cpp\n  STR_LAZY_LOADING: \"Lazy loading\"\n  STR_LAZY_LOADING_DESC: \"If enabled, graphic resources are loaded on-demand. Otherwise everything is loaded at start-up.\"\n  STR_VSYNC_FOR_OPENGL: \"VSync for OpenGL\"\n  STR_VSYNC_FOR_OPENGL_DESC: \"Turn off for maximum enemy hidden movement speed and (optionally) soldier movement speed. DO NOT set FPS limit to 0. Only applies to OpenGL rendering.\"\n#==== General ===============\n  STR_UPDATE_CHECK: \"Automatic update check\"\n  STR_UPDATE_CHECK_DESC: \"If enabled, OpenXcom will automatically check for updates and give you an option to update itself by a single button click.\"\n  STR_AUTOSAVE_SLOTS: \"Autosave slots\"\n  STR_AUTOSAVE_SLOTS_DESC: \"Number of slots for Battlescape autosaves.\"\n  STR_AUTO_SAVE_BATTLESCAPE_SLOT_WITH_NUMBER: \"<AUTO BATTLESCAPE> {0}\"\n  STR_GEO_AUTOSAVE_FREQUENCY: \"Autosave Frequency (Geoscape)\"\n  STR_GEO_AUTOSAVE_FREQUENCY_DESC: \"Amount of days after which the game will be automatically saved.\"\n  STR_GEO_AUTOSAVE_SLOTS: \"Autosave slots (Geoscape)\"\n  STR_GEO_AUTOSAVE_SLOTS_DESC: \"Number of slots for Geoscape autosaves.\"\n  STR_AUTO_SAVE_GEOSCAPE_SLOT_WITH_NUMBER: \"<AUTO GEOSCAPE> {0}\"\n  STR_OXCE_LINKS: \"Extended links\"\n  STR_OXCE_LINKS_DESC: \"Enables additional menus/buttons/links for OXCE features.\"\n  STR_PEDIA_SHOW_CLIP_SIZE: \"Show clip size in Ufopedia\"\n  STR_PEDIA_SHOW_CLIP_SIZE_DESC: \"If enabled, ammo clip sizes will be displayed next to ammo icons in the Ufopedia.\"\n#==== Geoscape ===============\n  STR_INTERCEPT_TABLE_SIZE: \"Intercept table size\"\n  STR_INTERCEPT_TABLE_SIZE_DESC: \"Size of the tables in the following dialog windows: Intercept, UFO Tracker.\"\n  STR_SHOW_SLACKING_INDICATOR: \"Show slacking indicator\"\n  STR_SHOW_SLACKING_INDICATOR_DESC: \"If enabled, number of unassigned scientists and engineers will be displayed.\"\n  STR_SHOW_MAINTENANCE_TIME: \"Show craft maintenance time\"\n  STR_SHOW_MAINTENANCE_TIME_DESC: \"{ALT}0>{ALT} Don't show {ALT}1>{ALT} Show only current activity duration {ALT}2>{ALT} Show all together (repair + rearm + refuel).\"\n  STR_SHOW_ETA: \"Show estimated flight duration\"\n  STR_SHOW_ETA_DESC: \"{ALT}0>{ALT} Don't show {ALT}1>{ALT} Show ETA for static targets only {ALT}2>{ALT} Show ETA also for moving targets.\"\n  STR_UFO_LANDING_ALERT: \"UFO landing alert\"\n  STR_UFO_LANDING_ALERT_DESC: \"If enabled, a message will pop up each time a detected UFO lands.\"\n  STR_REMEMBER_DISABLED_CRAFT_WEAPONS: \"Remember disabled craft weapons\"\n  STR_REMEMBER_DISABLED_CRAFT_WEAPONS_DESC: \"Craft weapons disabled during a dogfight will stay disabled. They will also not be rearmed at the base.\"\n  STR_GEO_EVENT_INSTANT_DELIVERY: \"Instant item delivery in events\"\n  STR_GEO_EVENT_INSTANT_DELIVERY_DESC: \"If enabled, items from geoscape events arrive instantly. Otherwise, they arrive 1 hour later.\"\n  STR_SHOW_BASE_NAME_IN_POPUPS: \"Show base name in pop-ups\"\n  STR_SHOW_BASE_NAME_IN_POPUPS_DESC: \"If enabled, corresponding base name is displayed in pop-up windows (e.g. Research Completed).\"\n#==== Basescape ===============\n  STR_ALTERNATE_CRAFT_EQUIPMENT_MANAGEMENT: \"Alternate craft equipment management\"\n  STR_ALTERNATE_CRAFT_EQUIPMENT_MANAGEMENT_DESC: \"If enabled, moving soldiers between a base and a craft will move their equipment too (if possible).\"\n  STR_BASE_INFO_SCALE: \"Scale large bars in base info\"\n  STR_BASE_INFO_SCALE_DESC: \"If enabled, bars larger than 140 are scaled down to fit the UI.\"\n  STR_HIGHLIGHT_NEW: \"Highlight new topics\"\n  STR_HIGHLIGHT_NEW_DESC: \"If enabled, new research topics, new manufacturing topics and new ufopedia articles are shown in different colour.\"\n  STR_RESEARCH_SCROLL_SPEED: \"Research scroll speed\"\n  STR_RESEARCH_SCROLL_SPEED_DESC: \"Scientists can be (un)assigned directly in the Current Research UI using the mouse scroll button.\"\n  STR_RESEARCH_SCROLL_SPEED_CTRL: \"Research scroll speed (with Ctrl)\"\n  STR_RESEARCH_SCROLL_SPEED_CTRL_DESC: \"Scientists can be (un)assigned directly in the Current Research UI using the mouse scroll button.\"\n  STR_MANUFACTURE_FILTER_SUPPLIES_OK: \"Alternate filter in Manufacturing\"\n  STR_MANUFACTURE_FILTER_SUPPLIES_OK_DESC: \"If enabled, the UI shows only production items for which there are enough supplies.\"\n  STR_MANUFACTURE_SCROLL_SPEED: \"Manufacture scroll speed\"\n  STR_MANUFACTURE_SCROLL_SPEED_DESC: \"Engineers can be (un)assigned directly in the Current Production UI using the mouse scroll button.\"\n  STR_MANUFACTURE_SCROLL_SPEED_CTRL: \"Manufacture scroll speed (with Ctrl)\"\n  STR_MANUFACTURE_SCROLL_SPEED_CTRL_DESC: \"Engineers can be (un)assigned directly in the Current Production UI using the mouse scroll button.\"\n  STR_PERSONAL_LAYOUT_INCLUDING_ARMOR: \"Include armor in personal equipment\"\n  STR_PERSONAL_LAYOUT_INCLUDING_ARMOR_DESC: \"If enabled, soldier personal equipment layout is saved including the worn armor.\"\n  STR_MANUALPROMOTIONS: \"Manual promotions\"\n  STR_MANUALPROMOTIONS_DESC: \"If enabled, soldiers can be manually promoted (or demoted) by clicking on the rank icon.\"\n#==== Battlescape ===============\n  STR_WOUNDED_DEFEND_BASE_IF: \"Wounded defend (if HP above x%)\"\n  STR_WOUNDED_DEFEND_BASE_IF_DESC: \"Wounded soldiers defend the base too, if their health is above the given percentage threshold.\"\n  STR_PLAY_BRIEFING_MUSIC_DURING_EQUIPMENT: \"Play Briefing music longer\"\n  STR_PLAY_BRIEFING_MUSIC_DURING_EQUIPMENT_DESC: \"Briefing music will continue playing during equipment phase until the Battlescape is displayed.\"\n  STR_NIGHT_VISION_COLOR: \"Select Night Vision colour\"\n  STR_NIGHT_VISION_COLOR_DESC: \"Values from 1 to 15, each representing a different shade colour.\"\n  STR_AUTO_NIGHT_VISION_THRESHOLD: \"Auto Night Vision threshold\"\n  STR_AUTO_NIGHT_VISION_THRESHOLD_DESC: \"If darker than this threshold, toggle Night Vision on automatically.\"\n  STR_SHOW_ACCURACY_ON_CROSSHAIR: \"Show accuracy on crosshair\"\n  STR_SHOW_ACCURACY_ON_CROSSHAIR_DESC: \"{ALT}0>{ALT}Never {ALT}1>{ALT}Only if UFO Extender accuracy is enabled {ALT}2>{ALT}Always\"\n  STR_REACTION_FIRE_THRESHOLD: \"Reaction fire threshold\"\n  STR_REACTION_FIRE_THRESHOLD_DESC: \"Xcom-controlled units will not reaction fire, if their accuracy (for a given target) is below this threshold.\"\n  STR_AUTO_SELL: \"Auto-Sell Manager\"\n  STR_AUTO_SELL_DESC: \"In the battle debriefing sell screen, any item types you sold in previous battles will be automatically marked for selling.\"\n  STR_AUTOMATICPROMOTIONS: \"Automatic promotions\"\n  STR_AUTOMATICPROMOTIONS_DESC: \"If enabled, soldiers are automatically promoted after a mission.\"\n  STR_OFF_CENTRE_SHOOTING: \"Off-centre shooting\"\n  STR_OFF_CENTRE_SHOOTING_DESC: \"Soldiers will automatically try to adjust the firing angle slightly in case there is no line of fire.\"\n  STR_UNIFORM_SHOOTING_SPREAD: \"Uniform shooting spread\"\n  STR_UNIFORM_SHOOTING_SPREAD_DESC: \"Spread is uniform in all directions and more tight.\"\n  STR_CRASHED_OR_LANDED: \"Crashed/Landed button\"\n  STR_CRASHED_OR_LANDED_DESC: \"If enabled, an extra button is displayed on the New Battle screen. Alternatively, press F11 to show/hide the button. {ALT}0>{ALT}Disabled, {ALT}1>{ALT}Crashed, {ALT}2>{ALT}Landed.\"\n#===================\n  STR_GRAPHS_ZOOM_IN: \"Zoom In (Graphs)\"\n  STR_GRAPHS_ZOOM_OUT: \"Zoom Out (Graphs)\"\n  STR_MARK_ALL_AS_SEEN: \"Mark All As Seen\"\n  STR_SELL_ALL: \"Sell All\"\n  STR_SELL_ALL_BUT_ONE: \"Sell All But One\"\n  STR_TRANSFER_ALL: \"Transfer All\"\n  STR_REMOVE_SOLDIERS_FROM_ALL_CRAFTS: \"Remove Soldiers From All Crafts\"\n  STR_REMOVE_SOLDIERS_FROM_CRAFT: \"Remove Soldiers From Craft\"\n  STR_REMOVE_EQUIPMENT_FROM_CRAFT: \"Remove Equipment From Craft\"\n  STR_REMOVE_ARMOR_FROM_ALL_CRAFTS: \"Remove Armor From All Crafts\"\n  STR_REMOVE_ARMOR_FROM_CRAFT: \"Remove Armor From Craft\"\n  STR_REMOVE_SOLDIERS_FROM_TRAINING: \"Remove Soldiers From Training\"\n  STR_ADD_SOLDIERS_TO_TRAINING: \"Add Soldiers To Training\"\n  STR_INVENTORY_ARMOR: \"Change Armor\"\n  STR_INVENTORY_AVATAR: \"Change Avatar\"\n  STR_INVENTORY_DIARY_LIGHT: \"View Diary Light\"\n  STR_ACTION_ITEM_1: \"Item Action 1 (Aim/Use)\"\n  STR_ACTION_ITEM_2: \"Item Action 2 (Snap)\"\n  STR_ACTION_ITEM_3: \"Item Action 3 (Auto)\"\n  STR_ACTION_ITEM_4: \"Item Action 4 (Melee)\"\n  STR_ACTION_ITEM_5: \"Item Action 5 (Throw)\"\n  STR_INSTA_SAVE: \"Insta-save\"\n  STR_TOGGLE_QUICK_SEARCH: \"Toggle Quick Search Field\"\n  STR_TOGGLE_NIGHT_VISION: \"Toggle Night Vision\"\n  STR_HOLD_NIGHT_VISION: \"Short Night Vision\"\n  STR_SELECT_MUSIC_TRACK: \"Select Music Track\"\n#===================\n  STR_TOGGLE_TOUCH_BUTTONS: \"Toggle Touch Buttons\"\n  STR_TOGGLE_BRIGHTNESS: \"Toggle Brightness (visual only)\"\n  STR_BRIEFING: \"Briefing\"\n  STR_TOGGLE_DEBUG_MODE: \"Toggle Debug Mode\"\n  STR_DEBUG_KILL_ALL_ALIENS: \"DEBUG: Kill All Aliens\"\n#=================== Geoscape ===================\n#AllocateTrainingState.cpp\n  STR_PHYSICAL_TRAINING: \"Martial Training\"\n  STR_REMAINING_TRAINING_FACILITY_CAPACITY: \"REMAINING TRAINING CAPACITY> {ALT}{0}\"\n  STR_NO_WOUNDED: \"-\"\n  STR_NO_QUEUED: \"+\"\n  STR_NO_DONE: \"DONE\"\n#BaseDefenseState.cpp\n  STR_NO_AMMO: \"NO AMMO!\"\n  STR_START_FIRING: \"Fire!\"\n  STR_SKIP_FIRING: \"Let them in...\"\n#BaseDestroyedState.cpp\n  STR_ALIEN_MISSILES_HAVE_DAMAGED_OUR_BASE: \"Alien missiles have damaged our base {0}\"\n  STR_ALIEN_MISSILES_HAVE_DESTROYED_OUR_BASE: \"Alien missiles have destroyed our base {0}\"\n#ConfirmDestinationState.cpp\n  STR_STARTING_CONDITION_COMMANDER: \"This mission requires the presence of the commander.\"\n  STR_STARTING_CONDITION_CRAFT: \"This craft is unsuitable for this mission.\"\n  STR_STARTING_CONDITION_CRAFT_ALLOWED: \"This craft is unsuitable for this mission.{NEWLINE}{NEWLINE}Allowed craft: {0}\"\n  STR_STARTING_CONDITION_CRAFT_FORBIDDEN: \"This craft is unsuitable for this mission.{NEWLINE}{NEWLINE}Forbidden craft: {0}\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE: \"Some soldiers cannot participate in this mission.\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE_ALLOWED: \"Some soldiers cannot participate in this mission.{NEWLINE}{NEWLINE}Allowed soldier types: {0}\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE_FORBIDDEN: \"Some soldiers cannot participate in this mission.{NEWLINE}{NEWLINE}Forbidden soldier types: {0}\"\n  STR_STARTING_CONDITION_ITEM: \"This mission requires specific item(s):{NEWLINE}{NEWLINE}{0}\"\n  STR_NOT_ENOUGH_FUEL_TO_REACH_TARGET: \"NOT ENOUGH FUEL!{SMALLLINE}The destination is too far for the range of the craft.\"\n  STR_TOO_MANY_ITEMS_ONBOARD: \"TOO MANY ITEMS!{SMALLLINE}This craft cannot carry so many items.\"\n  STR_ARMOR_NOT_ALLOWED_ONBOARD: \"ARMOR NOT ALLOWED!{SMALLLINE}Some soldiers are wearing forbidden armor.\"\n  STR_FOLLOW_WING_LEADER_QUESTION: \"Follow wing leader?\"\n#CraftNotEnoughPilotsState.cpp\n  STR_ASSIGN_PILOTS: \"Assign pilots...\"\n  STR_NOT_ENOUGH_PILOTS: \"Not enough pilots!{NEWLINE}Minimum: {0}\"\n#DogfightExperienceState.cpp\n  STR_DAILY_PILOT_EXPERIENCE: \"Daily Pilot Experience\"\n#DogfightState.cpp\n  STR_UFO_SHIELD_HIT: \"HIT THE SHIELDS!\"\n  STR_UFO_HIT_NO_DAMAGE: \"BOUNCED OFF THE HULL!\"\n  STR_UFO_SHIELD_DOWN: \"ENEMY SHIELDS DOWN!\"\n  STR_UFO_HIT_GLANCING: \"GLANCING HIT!\"\n  STR_INTERCEPTOR_SHIELD_HIT: \"OUR SHIELDS ARE HOLDING!\"\n  STR_TRACTOR_BEAM_ENGAGED: \"TRACTOR BEAM IS ENGAGED!\"\n  STR_TRACTOR_BEAM_DISENGAGED: \"DISENGAGING TRACTOR BEAM\"\n  STR_SELF_DESTRUCT_ACTIVATED: \"SELF-DESTRUCT ACTIVATED!\"\n  STR_SELF_DESTRUCT_CANCELLED: \"SELF-DESTRUCT CANCELLED\"\n  STR_MISSILE_DAMAGED: \">>> MISSILE DAMAGED <<<\"\n  STR_MISSILE_DESTROYED: \">>> MISSILE DESTROYED <<<\"\n  STR_OCEAN_INDICATOR: \"\"\n  STR_OCEAN_INDICATOR_RNG: \"\"\n#ExtendedGeoscapeLinksState.cpp\n  STR_EXTENDED_LINKS: \"Links\"\n#GeoscapeCraftState.cpp\n  STR_AUTO_PATROL: \"AUTO-PATROL\"\n  STR_ETA: \"ETA>{ALT}{0}\"\n#GeoscapeState.cpp\n  STR_NOT_ENOUGH_ITEM_TO_REARM_FACILITY_AT_BASE: \"Not enough {0} to rearm {1} at {2}\"\n  STR_UFO_STARTED_HUNTING: \"{0} is on an intercept course with {1}\"\n  STR_CRAFT_IS_READY: \"{0} at {1} is ready.\"\n  STR_ECONOMY_WARNING: \"The funds {0} and income {1} are low and the maintenance {2} too high! Sell something to avoid taking a credit... funds missing: {3}\"\n  STR_SLACKING_INDICATOR: \"{0}:{1}\"\n  STR_TRAINING_INDICATOR: \"{0}:{1}\"\n  STR_EXTENDED_UC: \"EXTENDED\"\n#InterceptState.cpp\n  STR_RETURNING: \"RETURNING\"\n  STR_INTERCEPTING: \"INTERCEPTING\"\n  STR_ESCORTING: \"ESCORTING\"\n  STR_EN_ROUTE: \"EN ROUTE\"\n  STR_PILOT_MISSING: \"PILOT MISSING\"\n  STR_DAY_SHORT: \"{0}d\"\n  STR_HOUR_SHORT: \"{0}h\"\n#MonthlyReportState.cpp\n  STR_PERFORMANCE_BONUS: \"Performance Bonus\"\n  STR_COUNTRY_HAS_CANCELLED_A_SECRET_PACT: \"{0} has renounced the pact with alien forces and was allowed to return to the project.\"\n  STR_COUNTRIES_HAVE_CANCELLED_A_SECRET_PACT: \"{0} have renounced the pact with alien forces and were allowed to return to the project.\"\n#NewPossibleCraftState.cpp\n  STR_WE_CAN_NOW_RENT: \"We can now rent\"\n#NewPossibleFacilityState.cpp\n  STR_REQUIRED_BASE_SERVICES: \"Required base services: {0}\"\n  STR_WE_CAN_NOW_BUILD: \"We can now build\"\n#NewPossiblePurchaseState.cpp\n  STR_WE_CAN_NOW_PURCHASE: \"We can now purchase\"\n#ProductionCompleteState.cpp\n  STR_NOT_ENOUGH_LIVING_SPACE_AT_BASE: \"Not enough living space to accomodate{NEWLINE}{0}{NEWLINE}at{NEWLINE}{1}\"\n#TargetInfoState.cpp\n  STR_INFO: \"INFO\"\n  STR_DESPAWN_PENALTY: \"Despawn penalty> {0}\"\n#TrainingFinishedState.cpp\n  STR_TRAINING_FINISHED: \"Training Finished{NEWLINE}at {0}\"\n  STR_PSI_TRAINING_FINISHED: \"Psi Training Finished{NEWLINE}at {0}\"\n#UfoDetectedState.cpp\n  STR_IGNORE_UC: \"IGNORE\"\n#UfoTrackerState.cpp\n  STR_UFO_TRACKER: \"UFO Tracker\"\n#=================== Menu ===================\n#MainMenuState.cpp\n  STR_UPDATE: \"Update\"\n  STR_LATEST_VERSION_INFO: \"You are using the latest OpenXcom version.\"\n#ModConfirmExtendedState.cpp\n  STR_MASTER_MOD_VERSION_REQUIRED_QUESTION: \"This mod requires base game v{0} to run correctly. Enable this mod?\"\n  STR_VERSION_REQUIRED_QUESTION: \"This mod requires OXCE v{0} to run correctly. Enable this mod?\"\n#ModListState.cpp\n  STR_OPEN_MODS_FOLDER: \"Open\"\n#NewBattleState.cpp\n  STR_GLOBE_TEXTURE: \"Globe Texture\"\n#NotesState.cpp\n  STR_NOTES: \"Notes\"\n  STR_NEW_NOTE: \"<NEW NOTE>\"\n#OptionsAdvancedState.cpp\n  STR_ENGINE_OXC: \"OXC\"\n  STR_ENGINE_OXCE: \"OXCE\"\n  STR_ENGINE_OTHER: \"OTHER\"\n  STR_BASESCAPE: \"Basescape\"\n  STR_AI: \"AI\"\n#OptionsBattlescapeState.cpp\n  STR_PATH_ENERGY_COST: \"Energy\"\n  STR_PATH_ENERGY_COST_DESC: \"Clicking shows the energy your unit will have remaining after moving to the destination.\"\n#StatisticsState.cpp\n  STR_VEHICLES_LOST: \"Vehicles lost\"\n  STR_CRAFT_LOST_DOGFIGHT: \"Interceptors lost\"\n  STR_CRAFT_LOST_MISSION: \"Transports lost\"\n  STR_ALIEN_BASES_DESTROYED: \"Alien bases destroyed\"\n  STR_XCOM_BASES_LOST: \"Bases lost\"\n#TestState.cpp\n  STR_TEST_SCREEN: \"TEST SCREEN\"\n  STR_PALETTE: \"Palette:\"\n  STR_PREVIEW: \"Preview\"\n  STR_TINY_BORDERLESS: \"Tiny, borderless\"\n  STR_TINY_BORDER: \"Tiny\"\n  STR_SMALL_LOW_CONTRAST: \"Small\"\n  STR_SMALL_HIGH_CONTRAST: \"Small, high contrast\"\n  STR_BIG_LOW_CONTRAST: \"Big\"\n  STR_BIG_HIGH_CONTRAST: \"Big, high contrast\"\n  STR_TEST_CASE: \"Test case:\"\n  STR_RUN: \"Run selected test!\"\n  STR_TESTS_STARTING: \"Starting...\"\n  STR_TESTS_ERRORS_FOUND: \"Total errors found (there may be duplicates): {0}\"\n  STR_TESTS_NO_ERRORS_FOUND: \"No errors found.\"\n  STR_TESTS_FINISHED: \"Finished.\"\n  STR_DETAILED_INFO_IN_LOG_FILE: \"Detailed info has been saved into openxcom.log\"\n#=================== Savegame ===================\n#Soldier.cpp\n  STR_RANK_NONE: \"-\"\n#=================== Ufopaedia ===================\n#ArticleState.cpp\n  STR_DAMAGE_NONE: \"NONE\"\n  STR_INFO_UFOPEDIA: \"INFO\"\n#ArticleStateCraft.cpp\n  STR_COCKPIT_CAPACITY: \"PILOTS>{ALT}{0}{ALT}\"\n  STR_MAXIMUM_RANGE: \"MAX RANGE>{ALT}{0}{ALT}\"\n  STR_MINIMUM_RANGE: \"MIN RANGE>{ALT}{0}{ALT}\"\n  STR_INFINITE_RANGE: \"N/A\"\n#ArticleStateCraftWeapon.cpp\n  STR_TRACTOR_BEAM_POWER: \"Power\"\n#ArticleStateItem.cpp\n  STR_WEIGHT_PEDIA1: \"Wt: {0}\"\n  STR_WEIGHT_PEDIA2: \"Wt: {0}/{1}\"\n  STR_SHOT_TYPE_MELEE: \"Melee\"\n  STR_ACCURACY_MODIFIER: \"Accuracy modifier>{ALT} {0}\"\n  STR_POWER_BONUS: \"Power bonus>{ALT} {0}\"\n  STR_MULTIPLE_DIFFERENT_BONUSES: \"multiple bonuses on various compatible ammo\"\n#StatsForNerdsState.cpp\n  STR_STATS_FOR_NERDS: \"Stats for Nerds\"\n  STR_ARTICLE: \"Article>{ALT} {0}\"\n  STR_COMPATIBLE_AMMO: \"Compatible ammo:\"\n  STR_BUILT_IN_ITEMS: \"Built-in items:\"\n  STR_CLIP_SIZE_UNLIMITED: \"unlimited\"\n  STR_SHOTGUN_BEHAVIOR_OXCE: \"extended\"\n  STR_INCLUDE_DEBUG: \"DEBUG\"\n  STR_INCLUDE_IDS: \"IDs\"\n  STR_INCLUDE_DEFAULTS: \"DEFAULTS\"\n  STR_TRUE: \"true\"\n  STR_FALSE: \"false\"\n#\n  STR_PSI_SKILL_AND_PSI_STRENGTH: \"PSI SKILL*PSI STRENGTH\"\n  STR_STRENGTH_AND_MELEE_ACCURACY: \"STRENGTH*MELEE ACCURACY\"\n  STR_STRENGTH_AND_THROWING_ACCURACY: \"STRENGTH*THROWING ACCURACY\"\n  STR_FIRING_ACCURACY_AND_REACTIONS: \"FIRING ACCURACY*REACTIONS\"\n  STR_HEALTH_CURRENT: \"CURRENT HEALTH\"\n  STR_MANA_CURRENT: \"CURRENT MANA\"\n  STR_TIME_UNITS_CURRENT: \"CURRENT TIME UNITS\"\n  STR_STUN_LEVEL_CURRENT: \"CURRENT STUN LEVEL\"\n  STR_HEALTH_NORMALIZED: \"NORMALISED HEALTH\"\n  STR_MANA_NORMALIZED: \"NORMALISED MANA\"\n  STR_TIME_UNITS_NORMALIZED: \"NORMALISED TIME UNITS\"\n  STR_ENERGY_NORMALIZED: \"NORMALISED ENERGY\"\n  STR_MORALE_NORMALIZED: \"NORMALISED MORALE\"\n  STR_STUN_LEVEL_NORMALIZED: \"NORMALISED STUN LEVEL\"\n  STR_ENERGY_REGENERATION: \"ENERGY REGENERATION\"\n#\n  STR_PSI_SKILL_AND_PSI_STRENGTH_ABBREVIATION: \"PSK*PST\"\n  STR_STRENGTH_AND_MELEE_ACCURACY_ABBREVIATION: \"STR*MEL\"\n  STR_STRENGTH_AND_THROWING_ACCURACY_ABBREVIATION: \"STR*THR\"\n  STR_FIRING_ACCURACY_AND_REACTIONS_ABBREVIATION: \"ACC*REA\"\n  STR_HEALTH_CURRENT_ABBREVIATION: \"CURRENT HEALTH\"\n  STR_MANA_CURRENT_ABBREVIATION: \"CURRENT MANA\"\n  STR_TIME_UNITS_CURRENT_ABBREVIATION: \"CURRENT TIME UNITS\"\n  STR_STUN_LEVEL_CURRENT_ABBREVIATION: \"CURRENT STUN LEVEL\"\n  STR_HEALTH_NORMALIZED_ABBREVIATION: \"NORMALISED HEALTH\"\n  STR_MANA_NORMALIZED_ABBREVIATION: \"NORMALISED MANA\"\n  STR_TIME_UNITS_NORMALIZED_ABBREVIATION: \"NORMALISED TIME UNITS\"\n  STR_ENERGY_NORMALIZED_ABBREVIATION: \"NORMALISED ENERGY\"\n  STR_MORALE_NORMALIZED_ABBREVIATION: \"NORMALISED MORALE\"\n  STR_STUN_LEVEL_NORMALIZED_ABBREVIATION: \"NORMALISED STUN LEVEL\"\n  STR_ENERGY_REGENERATION_ABBREVIATION: \"ENERGY REGENERATION\"\n#\n  STR_TIME_UNITS_SCALED: \"SCALED TIME UNITS\"\n  STR_STAMINA_SCALED: \"SCALED STAMINA\"\n  STR_HEALTH_SCALED: \"SCALED HEALTH\"\n  STR_BRAVERY_SCALED: \"SCALED BRAVERY\"\n  STR_REACTIONS_SCALED: \"SCALED REACTIONS\"\n  STR_FIRING_ACCURACY_SCALED: \"SCALED FIRING ACCURACY\"\n  STR_THROWING_ACCURACY_SCALED: \"SCALED THROWING ACCURACY\"\n  STR_STRENGTH_SCALED: \"SCALED STRENGTH\"\n  STR_PSIONIC_STRENGTH_SCALED: \"SCALED PSIONIC STRENGTH\"\n  STR_PSIONIC_SKILL_SCALED: \"SCALED PSIONIC SKILL\"\n  STR_MELEE_ACCURACY_SCALED: \"SCALED MELEE ACCURACY\"\n  STR_MANA_POOL_SCALED: \"SCALED MANA POOL\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH_SCALED: \"SCALED PSI SKILL*PSI STRENGTH\"\n  STR_STRENGTH_AND_MELEE_ACCURACY_SCALED: \"SCALED STRENGTH*MELEE ACCURACY\"\n  STR_STRENGTH_AND_THROWING_ACCURACY_SCALED: \"SCALED STRENGTH*THROWING ACCURACY\"\n  STR_FIRING_ACCURACY_AND_REACTIONS_SCALED: \"SCALED FIRING ACCURACY*REACTIONS\"\n#\n  STR_TIME_UNITS_SCALED_ABBREVIATION: \"SCALED TU\"\n  STR_STAMINA_SCALED_ABBREVIATION: \"SCALED STA\"\n  STR_HEALTH_SCALED_ABBREVIATION: \"SCALED HP\"\n  STR_BRAVERY_SCALED_ABBREVIATION: \"SCALED BRV\"\n  STR_REACTIONS_SCALED_ABBREVIATION: \"SCALED REA\"\n  STR_FIRING_ACCURACY_SCALED_ABBREVIATION: \"SCALED ACC\"\n  STR_THROWING_ACCURACY_SCALED_ABBREVIATION: \"SCALED THR\"\n  STR_STRENGTH_SCALED_ABBREVIATION: \"SCALED STR\"\n  STR_PSIONIC_STRENGTH_SCALED_ABBREVIATION: \"SCALED PST\"\n  STR_PSIONIC_SKILL_SCALED_ABBREVIATION: \"SCALED PSK\"\n  STR_MELEE_ACCURACY_SCALED_ABBREVIATION: \"SCALED MEL\"\n  STR_MANA_POOL_SCALED_ABBREVIATION: \"SCALED MAN\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH_SCALED_ABBREVIATION: \"SCALED PSK*PST\"\n  STR_STRENGTH_AND_MELEE_ACCURACY_SCALED_ABBREVIATION: \"SCALED STR*MEL\"\n  STR_STRENGTH_AND_THROWING_ACCURACY_SCALED_ABBREVIATION: \"SCALED STR*THR\"\n  STR_FIRING_ACCURACY_AND_REACTIONS_SCALED_ABBREVIATION: \"SCALED ACC*REA\"\n#\n  STR_COST_TIME: \"time\"\n  STR_COST_ENERGY: \"energy\"\n  STR_COST_MORALE: \"morale\"\n  STR_COST_HEALTH: \"health\"\n  STR_COST_STUN: \"stun\"\n  STR_COST_MANA: \"mana\"\n  STR_COST_BUILD: \"build\"\n  STR_COST_REFUND: \"refund\"\n#\n  STR_DAMAGE_10: \"10\"\n  STR_DAMAGE_11: \"11\"\n  STR_DAMAGE_12: \"12\"\n  STR_DAMAGE_13: \"13\"\n  STR_DAMAGE_14: \"14\"\n  STR_DAMAGE_15: \"15\"\n  STR_DAMAGE_16: \"16\"\n  STR_DAMAGE_17: \"17\"\n  STR_DAMAGE_18: \"18\"\n  STR_DAMAGE_19: \"19\"\n#\n  STR_NAUTICAL_MILES: \"{0} nautical miles\"\n  STR_KILOMETERS_PER_HOUR: \"{0} km/h\"\n  STR_SECONDS_LONG: \"{0} seconds\"\n  STR_RACE_BONUS: \"Race bonus\"\n  STR_FOR_DIFFICULTY: \"for difficulty: {0}\"\n#UfopaediaSelectState.cpp\n  STR_NOT_AWARDED_YET: \"Not awarded yet\"\n"
  },
  {
    "path": "bin/common/Language/OXCE/en-US.yml",
    "content": "en-US:\n#=================== Basescape ===================\n#BasescapeState.cpp\n  STR_CANNOT_DISMANTLE_FACILITY_UPGRADING: \"CANNOT DISMANTLE FACILITY!{SMALLLINE}Facility cannot be removed during upgrading.\"\n#BaseView.cpp\n  STR_CANNOT_UPGRADE_FACILITY_ALREADY_UPGRADING: \"CANNOT BUILD HERE!{SMALLLINE}Existing facility is already being built over.\"\n  STR_CANNOT_UPGRADE_FACILITY_WRONG_SIZE: \"CANNOT BUILD HERE!{SMALLLINE}Selected facility must completely cover existing facility.\"\n  STR_CANNOT_UPGRADE_FACILITY_WRONG_TYPE: \"CANNOT BUILD HERE!{SMALLLINE}Existing facility cannot be upgraded over by selected facility.\"\n  STR_CANNOT_UPGRADE_FACILITY_DISALLOWED: \"CANNOT BUILD HERE!{SMALLLINE}Existing facility cannot be built over.\"\n  STR_CANNOT_BUILD_QUEUE_OFF: \"CANNOT BUILD HERE!{SMALLLINE}Connecting facilities must finish construction first.\"\n  STR_CANNOT_BUILD_UPGRADE_ONLY: \"CANNOT BUILD HERE!{SMALLLINE}This facility can be built only as an upgrade of another facility.\"\n  STR_FACILITY_FORBIDDEN_BY_OTHER: \"CANNOT BUILD HERE!{SMALLLINE}Some existing facility forbids building this facility.\"\n  STR_FACILITY_OTHER_FORBIDDEN_BY_THIS: \"CANNOT BUILD HERE!{SMALLLINE}Some existing facility would be forbidden by this facility.\"\n  STR_NOT_ENOUGH_ITEMS: \"NOT ENOUGH MATERIALS!{SMALLLINE}We need more resources to build this facility.{NEWLINE}Missing> {0}: {1}\"\n#CraftArmorState.cpp\n  STR_ID: \"ID\"\n  STR_FIRST_LETTER: \"FIRST LETTER\"\n  STR_SOLDIER_TYPE: \"SOLDIER TYPE\"\n  STR_IDLE_DAYS: \"IDLE DAYS\"\n  STR_MANA: \"MANA\"\n  STR_MANA_POOL: \"MANA POOL\"\n  STR_MANA_MISSING: \"MANA MISSING\"\n#CraftEquipmentLoadState.cpp\n  STR_LOAD_CRAFT_LOADOUT_TEMPLATE: \"Load Craft Loadout\"\n  STR_EMPTY_SLOT_N: \"Empty slot {0}\"\n  STR_UNNAMED_SLOT_N: \"Unnamed slot {0}\"\n  STR_ADD_ON_TOP: \"Add on top\"\n#CraftEquipmentSaveState.cpp\n  STR_SAVE_CRAFT_LOADOUT_TEMPLATE: \"Save Craft Loadout\"\n  STR_SAVE_UC: \"SAVE\"\n#CraftEquipmentState.cpp\n  STR_ALL: \"Everything\"\n  STR_EQUIPPED: \"Equipped\"\n  STR_NOT_EQUIPPED: \"Not equipped\"\n  STR_UNASSIGNED: \"Other\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED_BY_SIZE: \"NO MORE EQUIPMENT ALLOWED ON BOARD!{SMALLLINE}Maximum storage space: {0}\"\n#CraftInfoState.cpp\n  STR_PILOTS: \"PILOTS\"\n  STR_SHIELD: \"SHIELD>{ALT}{0}\"\n  STR_CRAFT_SKIN_ID: \"[{0}]\"\n#CraftPilotSelectState.cpp\n  STR_SELECT_PILOT: \"Select Pilot\"\n#CraftPilotsState.cpp\n  STR_PILOTS_FOR_CRAFT: \"Pilot(s) for {0}\"\n  STR_PILOTS_REQUIRED: \"Pilot(s) required: {ALT}{0}\"\n  STR_ADD_PILOT: \"Add Pilot\"\n  STR_REMOVE_ALL_PILOTS: \"Remove All Pilots\"\n  STR_ACCURACY_BONUS: \"Accuracy bonus:\"\n  STR_DODGE_BONUS: \"Dodge bonus:\"\n  STR_APPROACH_SPEED: \"Approach speed:\"\n  STR_COWARDLY: \"Cowardly (-50%)\"\n  STR_NORMAL: \"Normal\"\n  STR_BOLD: \"Bold (+50%)\"\n  STR_VERY_BOLD: \"Very bold (+100%)\"\n#CraftSoldiersState.cpp\n  STR_ARMOR_GROUP_NOT_ALLOWED: \"This armor type is not allowed onboard.\"\n  STR_SOLDIER_GROUP_NOT_ALLOWED: \"This soldier type is not allowed onboard.\"\n  STR_SOLDIER_GROUP_NOT_SAME: \"This soldier type is not compatible with other soldiers onboard.\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW: \"Preview\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_SAVED: \"Preview *\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_BRIEFING: \"This feature allows you to preview and customize the deployment of your units at the beginning of a battle. You have unlimited movement. Press and hold 'Alt' to highlight valid unit positions. Click on the 'Abort Mission' icon to save a custom deployment. Click on the 'End Turn' icon to exit the preview.{NEWLINE}Note that adding any new soldiers or vehicles to the craft automatically invalidates the saved custom deployment. Presence of a custom deployment is indicated by an asterisk on the 'Preview' button.\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_BRIEFING_DUMMY: \"This feature allows you to preview and modify the deployment table of this craft type. Any changes will apply to all your current craft and also to any craft you buy or manufacture later in the campaign. You start with the maximum number of soldiers. Each soldier represents one row in the deployment table. Soldier names correspond to row numbers. To provide space for a 2x2 unit, place 4 soldiers in a 2x2 square. If space is not provided, the 2x2 unit will be missing in a real battle.\"\n  STR_BASE_DEFENSE_BRIEFING_PREVIEW: \"This feature allows you to preview your base.{NEWLINE}Have fun!{NEWLINE}{NEWLINE}Click on the 'End Turn' icon to exit the preview.\"\n#CraftWeaponsState.cpp\n  STR_NOT_ENOUGH_CARGO_SPACE: \"NOT ENOUGH CARGO SPACE AVAILABLE!{SMALLLINE}Use a different module or reduce the assigned crew.\"\n  STR_NOT_ENOUGH_STORAGE_SPACE_1: \"NOT ENOUGH STORAGE SPACE AVAILABLE!{SMALLLINE}Too many items! Use a different module or reduce the assigned equipment.\"\n  STR_NOT_ENOUGH_STORAGE_SPACE_2: \"NOT ENOUGH STORAGE SPACE AVAILABLE!{SMALLLINE}The items take up too much space! Use a different module or reduce the size of assigned equipment.\"\n#DismantleFacilityState.cpp\n  STR_REFUND_VALUE: \"Sales value> {ALT}{0}\"\n  STR_REFUND_VALUE_NEGATIVE: \"Expenses> {ALT}{0}\"\n#GlobalManufactureState.cpp\n  STR_PRODUCTION_OVERVIEW: \"PRODUCTION OVERVIEW\"\n#GlobalResearchDiaryState.cpp\n  STR_RESEARCH_DIARY: \"RESEARCH DIARY\"\n  STR_DISCOVERY_SOURCE_BASE: \"This item was discovered via a research project.{NEWLINE}Research base> {ALT}{1}{ALT}{NEWLINE}Item code> {ALT}{0}{ALT}\"\n  STR_DISCOVERY_SOURCE_FREE_FROM: \"This item was given for free from another research project.{NEWLINE}From research project> {ALT}{2}{ALT}{NEWLINE}{ALT}{1}{ALT} -> {ALT}{0}{ALT}\"\n  STR_DISCOVERY_SOURCE_FREE_AFTER: \"This technical item was discovered automatically.{NEWLINE}After research project> {ALT}{2}{ALT}{NEWLINE}{ALT}{1}{ALT} -> {ALT}{0}{ALT}\"\n  STR_DISCOVERY_SOURCE_MISSION: \"This item was given for free as a mission reward.{NEWLINE}Mission type> {ALT}{2}{ALT}{NEWLINE}{ALT}{1}{ALT} -> {ALT}{0}{ALT}\"\n  STR_DISCOVERY_SOURCE_EVENT: \"This item was given for free as an event reward.{NEWLINE}Event type> {ALT}{2}{ALT}{NEWLINE}{ALT}{1}{ALT} -> {ALT}{0}{ALT}\"\n#GlobalResearchState.cpp\n  STR_RESEARCH_OVERVIEW: \"RESEARCH OVERVIEW\"\n#GlobalAlienContainmentState.cpp\n  STR_PRISONER_OVERVIEW: \"PRISONER OVERVIEW\"\n  STR_PRISONER: \"PRISONER\"\n  STR_PRISONER_AMOUNT: \"AMOUNT\"\n  STR_PRISONER_INTERROGATED: \"INTERROGATED\"\n  STR_TOTAL_IN_PRISON: \"Space Used>{ALT}{0}\"\n  STR_TOTAL_INTERROGATED: \"Interrogated>{ALT}{0}\"\n  STR_PRISON_TYPE: \"Alien Containment\"\n#ManageAlienContainmentState.cpp\n  STR_KILL_SELECTED: \"Kill\"\n  STR_SELL_SELECTED: \"Sell\"\n  STR_GO_TO_TRANSFERS: \"Transfer...\"\n  STR_PRISON_CLEANUP: \"Prison Cleanup\"\n#ManufactureDependenciesTreeState.cpp\n  STR_TOPIC: \"Topic>{ALT} {0}\"\n  STR_SHOW_ALL: \"Show all\"\n  STR_NO_DEPENDENCIES: \"No dependencies.\"\n  STR_DIRECT_DEPENDENCIES: \"Direct dependencies\"\n  STR_LEVEL_2_DEPENDENCIES: \"Level 2 dependencies\"\n  STR_LEVEL_3_DEPENDENCIES: \"Level 3 dependencies\"\n  STR_LEVEL_4_DEPENDENCIES: \"Level 4 dependencies\"\n  STR_MORE_DEPENDENCIES: \"There are even deeper dependencies...\"\n  STR_END_OF_SEARCH: \"End of search.\"\n#ManufactureInfoState.cpp\n  STR_FALLBACK_PRODUCTION: \"FALLBACK\"\n  STR_REFUND_PRODUCTION: \"REFUND!\"\n  STR_HOURS_PER_UNIT: \"HOURS PER UNIT>{ALT}{0}\"\n#ManufactureStartState.cpp\n  STR_PERSON_JOINING: \"Person Joining\"\n  STR_RANDOM_PRODUCTION_DISCLAIMER: \"Random production!\"\n#MonthlyCostsState.cpp\n  STR_OTHER_EMPLOYEES: \"Other Staff & Inventory\"\n#NewManufactureListState.cpp\n  STR_SHOW_ONLY_NEW: \"Show only new\"\n  STR_FILTER_DEFAULT: \"Default\"\n  STR_FILTER_DEFAULT_SUPPLIES_OK: \"Default (supplies OK)\"\n  STR_FILTER_DEFAULT_NO_SUPPLIES: \"Default (no supplies)\"\n  STR_FILTER_FACILITY_REQUIRED: \"Facility Missing\"\n  STR_FILTER_HIDDEN: \"Hidden\"\n  STR_FILTER_EQUIPPED: \"Equipped\"\n  STR_FILTER_MISSING: \"Missing\"\n#NewResearchListState.cpp\n  STR_SORT_DEFAULT: \"Default\"\n  STR_SORT_BY_COST: \"By cost\"\n  STR_SORT_BY_NAME: \"By name\"\n#ProductionCompleteState.cpp\n  STR_RANDOM_PRODUCTION_SUMMARY: \"Summary\"\n#PurchaseState.cpp\n  STR_NOT_ENOUGH_PRISON_SPACE: \"NOT ENOUGH ALIEN CONTAINMENT!{SMALLLINE}Build new alien containment or transfer aliens to other bases.\"\n  STR_MONTHLY_ITEM_PURCHASE_LIMIT_EXCEEDED: \"MONTHLY PURCHASE LIMIT EXCEEDED!{SMALLLINE}More items will be available next month.\"\n  STR_MONTHLY_CRAFT_PURCHASE_LIMIT_EXCEEDED: \"MONTHLY PURCHASE LIMIT EXCEEDED!{SMALLLINE}More craft will be available next month.\"\n  STR_MONTHLY_SOLDIER_HIRING_LIMIT_EXCEEDED: \"MONTHLY HIRING LIMIT EXCEEDED!{SMALLLINE}More recruits will be available next month.\"\n#SoldierArmorState.cpp\n  STR_NOT_ENOUGH_CRAFT_SPACE: \"Not enough space onboard!\"\n#SoldierAvatarState.cpp\n  STR_SELECT_AVATAR_FOR: \"SELECT AVATAR FOR{NEWLINE}{0}\"\n#SoldierBonusState.cpp\n  STR_SOLDIER_BONUSES_FOR: \"SOLDIER BONUSES FOR{NEWLINE}{0}\"\n  STR_SUMMARY: \"Summary\"\n#SoldierInfoState.cpp\n  STR_MANA_RECOVERY: \"MANA RECOVERY> {ALT}{0}\"\n  STR_HEALTH_RECOVERY: \"HEALTH RECOVERY> {ALT}{0}\"\n  STR_BONUSES_BUTTON: \"+\"\n#SoldierRankState.cpp\n  STR_PROMOTE_SOLDIER: \"PROMOTE/DEMOTE{NEWLINE}{0} {1}\"\n  STR_RANK_HEADER: \"RANK\"\n  STR_OPENINGS_HEADER: \"OPENINGS\"\n#SoldierDiaryOverviewState.cpp\n  STR_KILLER_AND_WEAPON: \"{0}, {1}\"\n#SoldiersState.h\n  STR_TRAINING: \"Training\"\n  STR_SOLDIER_INFO: \"Soldier Info\"\n#SoldierTransformState.cpp\n  STR_SELECT_TRANSFORMATION_FOR: \"SELECT TRANSFORMATION FOR{NEWLINE}{0}\"\n  STR_TRANSFORMATIONS_BUTTON: \"^\"\n#SoldierTransformationAssignState.cpp\n  STR_TRANSFER_TIME: \"Transfer Time>{ALT}{0}\"\n  STR_RECOVERY_TIME: \"Recovery Time>{ALT}{0}\"\n  STR_CURRENT_STATS: \"Current stats\"\n  STR_CHANGES: \"Changes\"\n  STR_CHANGES_MIN: \"Changes (min)\"\n  STR_CHANGES_MAX: \"Changes (max)\"\n  STR_BONUS_STATS: \"Bonus stats\"\n#SoldierTransformationListState.cpp\n  STR_TRANSFORMATIONS_OVERVIEW: \"Transformations Overview\"\n  STR_PROJECT_NAME: \"PROJECT NAME\"\n  STR_AVAILABLE_MATERIALS: \"AVAILABLE MATERIALS\"\n  STR_ELIGIBLE_SOLDIERS: \"ELIGIBLE SOLDIERS\"\n  STR_SHOW_ONLY_ELIGIBLE: \"Show Only Eligible\"\n  STR_ALL_SOLDIER_TYPES: \"All Soldier Types\"\n  STR_ALL_SOLDIERS: \"All Soldiers\"\n  STR_HEALTHY_SOLDIERS: \"Healthy Soldiers\"\n  STR_WOUNDED_SOLDIERS: \"Wounded Soldiers\"\n  STR_DEAD_SOLDIERS: \"Dead Soldiers\"\n#StoresState.cpp\n  STR_GRAND_TOTAL: \"Grand Total\"\n#TechTreeSelectState.cpp\n  STR_AVAILABLE_TOPICS: \"AVAILABLE TOPICS\"\n  STR_QS_THREE_LETTERS_A: \"Please enter at least 3 letters\"\n  STR_QS_THREE_LETTERS_B: \"into the Quick Search box...\"\n  STR_M_FLAG: \" [m]\"\n  STR_F_FLAG: \" [f]\"\n  STR_I_FLAG: \" [i]\"\n  STR_C_FLAG: \" [c]\"\n#TechTreeViewerState.cpp\n  STR_THIS_FEATURE_IS_DISABLED_1: \"This feature is disabled.\"\n  STR_THIS_FEATURE_IS_DISABLED_2: \"This feature is disabled.\"\n  STR_THIS_FEATURE_IS_DISABLED_3: \"This feature is disabled.\"\n  STR_THIS_FEATURE_IS_DISABLED_4: \"This feature is disabled.\"\n  STR_THIS_FEATURE_IS_DISABLED_5: \"This feature is disabled.\"\n  STR_TECH_TREE_VIEWER: \"Tech Tree Viewer\"\n  STR_SELECT_TOPIC: \"Select Topic\"\n  STR_RESEARCH_PROGRESS: \"Progress>{ALT} {0}%\"\n  STR_ITEM_DESTROYED: \"Item destroyed:\"\n  STR_ITEM_REQUIRED: \"Item required:\"\n  STR_SERVICES_REQUIRED: \"Services required:\"\n  STR_SERVICES_PROVIDED: \"Services provided:\"\n  STR_SERVICES_FORBIDDEN: \"Services forbidden:\"\n  STR_REQUIRES: \"Requires:\"\n  STR_DEPENDS_ON: \"Depends on:\"\n  STR_UNLOCKED_BY: \"Unlocked by:\"\n  STR_DISABLED_BY: \"Disabled by:\"\n  STR_REENABLED_BY: \"Re-enabled by:\"\n  STR_GET_FOR_FREE_FROM: \"Get for free from:\"\n  STR_IS_LOOKUP_OF: \"Is lookup of:\"\n  STR_LOOKUP: \"Lookup:\"\n  STR_SPAWNED_ITEMS: \"Spawned items:\"\n  STR_SPAWNED_EVENT: \"Spawned event:\"\n  STR_RANDOM_EVENTS: \"Events:\"\n  STR_REQUIRED_BY: \"Required by:\"\n  STR_REQUIRED_BY_TRANSFORMATIONS: \"Required by transformations:\"\n  STR_LEADS_TO: \"Leads to:\"\n  STR_UNLOCKS: \"Unlocks:\"\n  STR_DISABLES: \"Disables:\"\n  STR_REENABLES: \"Re-enables:\"\n  STR_GIVES_ONE_FOR_FREE_SEQ: \"Gives one for free (sequential):\"\n  STR_GIVES_ONE_FOR_FREE: \"Gives one for free:\"\n  STR_RESEARCH_REQUIRED: \"Research required:\"\n  STR_RESEARCH_REQUIRED_USE: \"Research required (use):\"\n  STR_RESEARCH_REQUIRED_BUY: \"Research required (buy):\"\n  STR_SERVICES_REQUIRED_BUY: \"Services required (buy):\"\n  STR_PRODUCED_BY: \"Produced by:\"\n  STR_SPAWNED_BY: \"Spawned by:\"\n  STR_MATERIALS_REQUIRED: \"Materials required:\"\n  STR_TTV_COST_PER_UNIT: \"Cost per unit:\"\n  STR_TTV_ENGINEER_HOURS: \"Engineer hours:\"\n  STR_TTV_WORK_SPACE_REQUIRED: \"Work space required:\"\n  STR_ITEMS_PRODUCED: \"Items produced:\"\n  STR_PERSON_RECRUITED: \"Person recruited:\"\n  STR_UNLOCKS_ARCS: \"Unlocks arcs:\"\n  STR_DISABLES_ARCS: \"Disables arcs:\"\n  STR_UNLOCKS_MISSIONS: \"Unlocks missions:\"\n  STR_DISABLES_MISSIONS: \"Disables missions:\"\n  STR_UNLOCKS_EVENTS: \"Unlocks events:\"\n  STR_DISABLES_EVENTS: \"Disables events:\"\n  STR_AFFECTS_GAME_PROGRESSION: \"Affects game progression!\"\n#TransferItemsState.cpp\n  STR_ITEMS_AT_DESTINATION: \"Items at destination\"\n  STR_PRISONERS: \"Prisoners\"\n  STR_ARMORS: \"Armors\"\n  STR_FILTER_RESEARCHED: \"Fully researched\"\n  STR_FILTER_RESEARCHABLE: \"Researchable\"\n#=================== Battlescape ===================\n#AbortMissionState.cpp\n  STR_CRAFT_DEPLOYMENT_QUESTION: \"Save Craft Deployment?\"\n#ActionMenuState.cpp\n  STR_MUST_USE_BOTH_HANDS: \"Both hands are required for this!\"\n#BattlescapeGame.cpp\n  STR_NOT_ENOUGH_MORALE: \"Not Enough Morale!\"\n  STR_NOT_ENOUGH_HEALTH: \"Not Enough Health!\"\n  STR_NOT_ENOUGH_MANA: \"Not Enough Mana!\"\n  STR_NOT_ENOUGH_STUN: \"Stun level is too high!\"\n  STR_MIND_CONTROL_SUCCESSFUL_ALT: \"Action Successful\"\n  STR_LINE_OF_SIGHT_REQUIRED: \"Line of sight (LoS) required.\"\n#BattlescapeState.cpp\n  STR_CENTER_ON_WOUNDED_FRIEND: \"Center on Wounded Friend\"\n  STR_CENTER_ON_DIZZY_FRIEND: \"Center on Dizzy Friend\"\n  STR_BUG_HUNT_ACTIVATED: \"Bug Hunt mode activated: enemies are visible on the minimap!\"\n  STR_QUICK_MODE_ACTIVATED: \"Usain Bolt mode activated.{NEWLINE}Press Ctrl+S again to deactivate.\"\n  STR_QUICK_MODE_DEACTIVATED: \"Usain Bolt mode deactivated.\"\n  STR_SINGLE_MAP_LAYER_ACTIVATED: \"Single map layer mode activated.{NEWLINE}Press Ctrl+C again to deactivate.\"\n  STR_SINGLE_MAP_LAYER_DEACTIVATED: \"Single map layer mode deactivated.\"\n  STR_TARGET_ENEMY: \"; Target = ENEMY\"\n  STR_TARGET_NEUTRAL: \"; Target = NEUTRAL\"\n  STR_TARGET_FRIEND: \"; Target = FRIEND\"\n  STR_TARGET_YOURSELF: \"; Target = YOURSELF\"\n  STR_TARGET_ON_THE_GROUND: \" (on the ground)\"\n  STR_USE_SPECIAL_ITEM: \"Use Special Item\"\n  STR_NO_EXPERIENCE_YET: \"No experience yet:\"\n#BriefingState.cpp\n  STR_OPERATION_UC: \"OPERATION> {0}\"\n#BriefingLightState.cpp\n  STR_WHAT_CAN_I_WEAR: \"What can I wear?\"\n  STR_STARTING_CONDITION_ARMORS_FORBIDDEN: \"This mission requires specific gear.{NEWLINE}{NEWLINE}Forbidden armor types are: {0}\"\n  STR_STARTING_CONDITION_ARMORS_ALLOWED: \"This mission requires specific gear.{NEWLINE}{NEWLINE}Allowed armor types are: {0}\"\n#ConfirmEndMissionState.cpp\n  STR_MISSION_OVER: \"Mission complete.\"\n  STR_UNITS_WITH_FATAL_WOUNDS:\n    one: \"{N} of us is still fatally wounded\"\n    other: \"{N} of us are still fatally wounded\"\n  STR_END_MISSION_QUESTION: \"End Mission?\"\n#DebriefingState.cpp\n  STR_LOOT: \"LOOT\"\n  STR_SELL: \"SELL\"\n  STR_LIVE_ALIENS_SURRENDERED: \"ENEMIES SURRENDERED\"\n  STR_MISSION_ABORTED: \"MISSION ABORTED\"\n  STR_VIPS_SAVED: \"VIPS SAVED\"\n  STR_VIPS_LOST: \"VIPS LOST\"\n  STR_BOUNTY: \"BOUNTY\"\n  STR_MANA_ABBREVIATION: \"MAN\"\n#ExperienceOverviewState.cpp\n  STR_EXPERIENCE_OVERVIEW: \"Experience Overview\"\n#Inventory.cpp\n  STR_CANNOT_PLACE_ITEM_INTO_THIS_SECTION: \"It's not allowed to place that item there.{NEWLINE}Don't ask why!\"\n  STR_ONE_HAND_MUST_BE_EMPTY: \"At least one hand must be empty!\"\n#InventoryLoadState.cpp\n  STR_LOAD_EQUIPMENT_TEMPLATE: \"Load Equipment Template\"\n#InventorySaveState.cpp\n  STR_SAVE_EQUIPMENT_TEMPLATE: \"Save Equipment Template\"\n#InventoryState.cpp\n  STR_FIRING_SHORT: \"Firing>{ALT}{0}\"\n  STR_THROWING_SHORT: \"Throw>{ALT}{0}\"\n  STR_MELEE_SHORT: \"Melee>{ALT}{0}\"\n  STR_PERSONAL_EQUIPMENT: \"PERSONAL EQUIPMENT\"\n  STR_SAVE_PERSONAL_EQUIPMENT: \"Save Personal Equipment\"\n  STR_LOAD_PERSONAL_EQUIPMENT: \"Load Personal Equipment\"\n  STR_PERSONAL_EQUIPMENT_SAVED: \"Personal equipment saved.\"\n  STR_PERSONAL_EQUIPMENT_NOT_DEFINED: \"Personal equipment is not defined yet.\"\n  STR_SLOT: \"Slot>{ALT}{0}\"\n#Map.cpp\n  STR_THINKING: \"Thinking...\"\n#NextTurnState.cpp\n  STR_TELL_ME_MORE: \"Tell me more...\"\n  STR_REINFORCEMENTS_ALERT: \"Reinforcements alert!\"\n  STR_HIT_LOG_NEW_TURN: \"New Turn\"\n#ProjectileFlyBState.cpp\n  STR_FAILED_CQB_CHECK: \"Enemy managed to interrupt your attack!\"\n  STR_NO_TRAJECTORY: \"No viable trajectory!\"\n  STR_HIT_LOG_NEW_BULLET: \"=> \"\n#SkillMenuState.cpp\n  STR_MANA_SHORT: \"MA>{ALT}{0}\"\n  STR_SKILL_NEEDS_ITEM: \"This skill needs an item!\"\n#TileEngine.cpp\n  STR_HIT_LOG_NO_DAMAGE: \"0 \"\n  STR_HIT_LOG_SMALL_DAMAGE: \"hit \"\n  STR_HIT_LOG_BIG_DAMAGE: \"HIT \"\n  STR_HIT_LOG_REACTION_FIRE: \"Reaction fire...\"\n#TurnDiaryState.cpp\n  STR_HIT_LOG: \"Hit Log\"\n#=================== Engine ===================\n#TouchState.cpp\n  STR_BUTTON_TOUCH: \"Touch\"\n  STR_BUTTON_1: \"1\"\n  STR_BUTTON_10: \"10\"\n  STR_BUTTON_100: \"100\"\n  STR_BUTTON_LMB: \"LMB\"\n  STR_BUTTON_RMB: \"RMB\"\n  STR_BUTTON_MMB: \"MMB\"\n  STR_BUTTON_CTRL: \"Ctrl\"\n  STR_BUTTON_ALT: \"Alt\"\n  STR_BUTTON_SHIFT: \"Shift\"\n#Options.cpp\n  STR_LAZY_LOADING: \"Lazy loading\"\n  STR_LAZY_LOADING_DESC: \"If enabled, graphic resources are loaded on-demand. Otherwise everything is loaded at start-up.\"\n  STR_VSYNC_FOR_OPENGL: \"VSync for OpenGL\"\n  STR_VSYNC_FOR_OPENGL_DESC: \"Turn off for maximum enemy hidden movement speed and (optionally) soldier movement speed. DO NOT set FPS limit to 0. Only applies to OpenGL rendering.\"\n#==== General ===============\n  STR_UPDATE_CHECK: \"Automatic update check\"\n  STR_UPDATE_CHECK_DESC: \"If enabled, OpenXcom will automatically check for updates and give you an option to update itself by a single button click.\"\n  STR_AUTOSAVE_SLOTS: \"Autosave slots\"\n  STR_AUTOSAVE_SLOTS_DESC: \"Number of slots for Battlescape autosaves.\"\n  STR_AUTO_SAVE_BATTLESCAPE_SLOT_WITH_NUMBER: \"<AUTO BATTLESCAPE> {0}\"\n  STR_GEO_AUTOSAVE_FREQUENCY: \"Autosave Frequency (Geoscape)\"\n  STR_GEO_AUTOSAVE_FREQUENCY_DESC: \"Amount of days after which the game will be automatically saved.\"\n  STR_GEO_AUTOSAVE_SLOTS: \"Autosave slots (Geoscape)\"\n  STR_GEO_AUTOSAVE_SLOTS_DESC: \"Number of slots for Geoscape autosaves.\"\n  STR_AUTO_SAVE_GEOSCAPE_SLOT_WITH_NUMBER: \"<AUTO GEOSCAPE> {0}\"\n  STR_OXCE_LINKS: \"Extended links\"\n  STR_OXCE_LINKS_DESC: \"Enables additional menus/buttons/links for OXCE features.\"\n  STR_PEDIA_SHOW_CLIP_SIZE: \"Show clip size in Ufopedia\"\n  STR_PEDIA_SHOW_CLIP_SIZE_DESC: \"If enabled, ammo clip sizes will be displayed next to ammo icons in the Ufopedia.\"\n#==== Geoscape ===============\n  STR_INTERCEPT_TABLE_SIZE: \"Intercept table size\"\n  STR_INTERCEPT_TABLE_SIZE_DESC: \"Size of the tables in the following dialog windows: Intercept, UFO Tracker.\"\n  STR_SHOW_SLACKING_INDICATOR: \"Show slacking indicator\"\n  STR_SHOW_SLACKING_INDICATOR_DESC: \"If enabled, number of unassigned scientists and engineers will be displayed.\"\n  STR_SHOW_MAINTENANCE_TIME: \"Show craft maintenance time\"\n  STR_SHOW_MAINTENANCE_TIME_DESC: \"{ALT}0>{ALT} Don't show {ALT}1>{ALT} Show only current activity duration {ALT}2>{ALT} Show all together (repair + rearm + refuel).\"\n  STR_SHOW_ETA: \"Show estimated flight duration\"\n  STR_SHOW_ETA_DESC: \"{ALT}0>{ALT} Don't show {ALT}1>{ALT} Show ETA for static targets only {ALT}2>{ALT} Show ETA also for moving targets.\"\n  STR_UFO_LANDING_ALERT: \"UFO landing alert\"\n  STR_UFO_LANDING_ALERT_DESC: \"If enabled, a message will pop up each time a detected UFO lands.\"\n  STR_REMEMBER_DISABLED_CRAFT_WEAPONS: \"Remember disabled craft weapons\"\n  STR_REMEMBER_DISABLED_CRAFT_WEAPONS_DESC: \"Craft weapons disabled during a dogfight will stay disabled. They will also not be rearmed at the base.\"\n  STR_GEO_EVENT_INSTANT_DELIVERY: \"Instant item delivery in events\"\n  STR_GEO_EVENT_INSTANT_DELIVERY_DESC: \"If enabled, items from geoscape events arrive instantly. Otherwise, they arrive 1 hour later.\"\n  STR_SHOW_BASE_NAME_IN_POPUPS: \"Show base name in pop-ups\"\n  STR_SHOW_BASE_NAME_IN_POPUPS_DESC: \"If enabled, corresponding base name is displayed in pop-up windows (e.g. Research Completed).\"\n#==== Basescape ===============\n  STR_ALTERNATE_CRAFT_EQUIPMENT_MANAGEMENT: \"Alternate craft equipment management\"\n  STR_ALTERNATE_CRAFT_EQUIPMENT_MANAGEMENT_DESC: \"If enabled, moving soldiers between a base and a craft will move their equipment too (if possible).\"\n  STR_BASE_INFO_SCALE: \"Scale large bars in base info\"\n  STR_BASE_INFO_SCALE_DESC: \"If enabled, bars larger than 140 are scaled down to fit the UI.\"\n  STR_HIGHLIGHT_NEW: \"Highlight new topics\"\n  STR_HIGHLIGHT_NEW_DESC: \"If enabled, new research topics, new manufacturing topics and new ufopedia articles are shown in different color.\"\n  STR_RESEARCH_SCROLL_SPEED: \"Research scroll speed\"\n  STR_RESEARCH_SCROLL_SPEED_DESC: \"Scientists can be (un)assigned directly in the Current Research UI using the mouse scroll button.\"\n  STR_RESEARCH_SCROLL_SPEED_CTRL: \"Research scroll speed (with Ctrl)\"\n  STR_RESEARCH_SCROLL_SPEED_CTRL_DESC: \"Scientists can be (un)assigned directly in the Current Research UI using the mouse scroll button.\"\n  STR_MANUFACTURE_FILTER_SUPPLIES_OK: \"Alternate filter in Manufacturing\"\n  STR_MANUFACTURE_FILTER_SUPPLIES_OK_DESC: \"If enabled, the UI shows only production items for which there are enough supplies.\"\n  STR_MANUFACTURE_SCROLL_SPEED: \"Manufacture scroll speed\"\n  STR_MANUFACTURE_SCROLL_SPEED_DESC: \"Engineers can be (un)assigned directly in the Current Production UI using the mouse scroll button.\"\n  STR_MANUFACTURE_SCROLL_SPEED_CTRL: \"Manufacture scroll speed (with Ctrl)\"\n  STR_MANUFACTURE_SCROLL_SPEED_CTRL_DESC: \"Engineers can be (un)assigned directly in the Current Production UI using the mouse scroll button.\"\n  STR_PERSONAL_LAYOUT_INCLUDING_ARMOR: \"Include armor in personal equipment\"\n  STR_PERSONAL_LAYOUT_INCLUDING_ARMOR_DESC: \"If enabled, soldier personal equipment layout is saved including the worn armor.\"\n  STR_MANUALPROMOTIONS: \"Manual promotions\"\n  STR_MANUALPROMOTIONS_DESC: \"If enabled, soldiers can be manually promoted (or demoted) by clicking on the rank icon.\"\n#==== Battlescape ===============\n  STR_WOUNDED_DEFEND_BASE_IF: \"Wounded defend (if HP above x%)\"\n  STR_WOUNDED_DEFEND_BASE_IF_DESC: \"Wounded soldiers defend the base too, if their health is above the given percentage threshold.\"\n  STR_PLAY_BRIEFING_MUSIC_DURING_EQUIPMENT: \"Play Briefing music longer\"\n  STR_PLAY_BRIEFING_MUSIC_DURING_EQUIPMENT_DESC: \"Briefing music will continue playing during equipment phase until the Battlescape is displayed.\"\n  STR_NIGHT_VISION_COLOR: \"Select Night Vision color\"\n  STR_NIGHT_VISION_COLOR_DESC: \"Values from 1 to 15, each representing a different shade color.\"\n  STR_AUTO_NIGHT_VISION_THRESHOLD: \"Auto Night Vision threshold\"\n  STR_AUTO_NIGHT_VISION_THRESHOLD_DESC: \"If darker than this threshold, toggle Night Vision on automatically.\"\n  STR_SHOW_ACCURACY_ON_CROSSHAIR: \"Show accuracy on crosshair\"\n  STR_SHOW_ACCURACY_ON_CROSSHAIR_DESC: \"{ALT}0>{ALT}Never {ALT}1>{ALT}Only if UFO Extender accuracy is enabled {ALT}2>{ALT}Always\"\n  STR_REACTION_FIRE_THRESHOLD: \"Reaction fire threshold\"\n  STR_REACTION_FIRE_THRESHOLD_DESC: \"Xcom-controlled units will not reaction fire, if their accuracy (for a given target) is below this threshold.\"\n  STR_AUTO_SELL: \"Auto-Sell Manager\"\n  STR_AUTO_SELL_DESC: \"In the battle debriefing sell screen, any item types you sold in previous battles will be automatically marked for selling.\"\n  STR_AUTOMATICPROMOTIONS: \"Automatic promotions\"\n  STR_AUTOMATICPROMOTIONS_DESC: \"If enabled, soldiers are automatically promoted after a mission.\"\n  STR_OFF_CENTRE_SHOOTING: \"Off-center shooting\"\n  STR_OFF_CENTRE_SHOOTING_DESC: \"Soldiers will automatically try to adjust the firing angle slightly in case there is no line of fire.\"\n  STR_UNIFORM_SHOOTING_SPREAD: \"Uniform shooting spread\"\n  STR_UNIFORM_SHOOTING_SPREAD_DESC: \"Spread is uniform in all directions and more tight.\"\n  STR_CRASHED_OR_LANDED: \"Crashed/Landed button\"\n  STR_CRASHED_OR_LANDED_DESC: \"If enabled, an extra button is displayed on the New Battle screen. Alternatively, press F11 to show/hide the button. {ALT}0>{ALT}Disabled, {ALT}1>{ALT}Crashed, {ALT}2>{ALT}Landed.\"\n#===================\n  STR_GRAPHS_ZOOM_IN: \"Zoom In (Graphs)\"\n  STR_GRAPHS_ZOOM_OUT: \"Zoom Out (Graphs)\"\n  STR_MARK_ALL_AS_SEEN: \"Mark All As Seen\"\n  STR_SELL_ALL: \"Sell All\"\n  STR_SELL_ALL_BUT_ONE: \"Sell All But One\"\n  STR_TRANSFER_ALL: \"Transfer All\"\n  STR_REMOVE_SOLDIERS_FROM_ALL_CRAFTS: \"Remove Soldiers From All Crafts\"\n  STR_REMOVE_SOLDIERS_FROM_CRAFT: \"Remove Soldiers From Craft\"\n  STR_REMOVE_EQUIPMENT_FROM_CRAFT: \"Remove Equipment From Craft\"\n  STR_REMOVE_ARMOR_FROM_ALL_CRAFTS: \"Remove Armor From All Crafts\"\n  STR_REMOVE_ARMOR_FROM_CRAFT: \"Remove Armor From Craft\"\n  STR_REMOVE_SOLDIERS_FROM_TRAINING: \"Remove Soldiers From Training\"\n  STR_ADD_SOLDIERS_TO_TRAINING: \"Add Soldiers To Training\"\n  STR_INVENTORY_ARMOR: \"Change Armor\"\n  STR_INVENTORY_AVATAR: \"Change Avatar\"\n  STR_INVENTORY_DIARY_LIGHT: \"View Diary Light\"\n  STR_ACTION_ITEM_1: \"Item Action 1 (Aim/Use)\"\n  STR_ACTION_ITEM_2: \"Item Action 2 (Snap)\"\n  STR_ACTION_ITEM_3: \"Item Action 3 (Auto)\"\n  STR_ACTION_ITEM_4: \"Item Action 4 (Melee)\"\n  STR_ACTION_ITEM_5: \"Item Action 5 (Throw)\"\n  STR_INSTA_SAVE: \"Insta-save\"\n  STR_TOGGLE_QUICK_SEARCH: \"Toggle Quick Search Field\"\n  STR_TOGGLE_NIGHT_VISION: \"Toggle Night Vision\"\n  STR_HOLD_NIGHT_VISION: \"Short Night Vision\"\n  STR_SELECT_MUSIC_TRACK: \"Select Music Track\"\n#===================\n  STR_TOGGLE_TOUCH_BUTTONS: \"Toggle Touch Buttons\"\n  STR_TOGGLE_BRIGHTNESS: \"Toggle Brightness (visual only)\"\n  STR_BRIEFING: \"Briefing\"\n  STR_TOGGLE_DEBUG_MODE: \"Toggle Debug Mode\"\n  STR_DEBUG_KILL_ALL_ALIENS: \"DEBUG: Kill All Aliens\"\n#=================== Geoscape ===================\n#AllocateTrainingState.cpp\n  STR_PHYSICAL_TRAINING: \"Martial Training\"\n  STR_REMAINING_TRAINING_FACILITY_CAPACITY: \"REMAINING TRAINING CAPACITY> {ALT}{0}\"\n  STR_NO_WOUNDED: \"-\"\n  STR_NO_QUEUED: \"+\"\n  STR_NO_DONE: \"DONE\"\n#BaseDefenseState.cpp\n  STR_NO_AMMO: \"NO AMMO!\"\n  STR_START_FIRING: \"Fire!\"\n  STR_SKIP_FIRING: \"Let them in...\"\n#BaseDestroyedState.cpp\n  STR_ALIEN_MISSILES_HAVE_DAMAGED_OUR_BASE: \"Alien missiles have damaged our base {0}\"\n  STR_ALIEN_MISSILES_HAVE_DESTROYED_OUR_BASE: \"Alien missiles have destroyed our base {0}\"\n#ConfirmDestinationState.cpp\n  STR_STARTING_CONDITION_COMMANDER: \"This mission requires the presence of the commander.\"\n  STR_STARTING_CONDITION_CRAFT: \"This craft is unsuitable for this mission.\"\n  STR_STARTING_CONDITION_CRAFT_ALLOWED: \"This craft is unsuitable for this mission.{NEWLINE}{NEWLINE}Allowed craft: {0}\"\n  STR_STARTING_CONDITION_CRAFT_FORBIDDEN: \"This craft is unsuitable for this mission.{NEWLINE}{NEWLINE}Forbidden craft: {0}\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE: \"Some soldiers cannot participate in this mission.\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE_ALLOWED: \"Some soldiers cannot participate in this mission.{NEWLINE}{NEWLINE}Allowed soldier types: {0}\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE_FORBIDDEN: \"Some soldiers cannot participate in this mission.{NEWLINE}{NEWLINE}Forbidden soldier types: {0}\"\n  STR_STARTING_CONDITION_ITEM: \"This mission requires specific item(s):{NEWLINE}{NEWLINE}{0}\"\n  STR_NOT_ENOUGH_FUEL_TO_REACH_TARGET: \"NOT ENOUGH FUEL!{SMALLLINE}The destination is too far for the range of the craft.\"\n  STR_TOO_MANY_ITEMS_ONBOARD: \"TOO MANY ITEMS!{SMALLLINE}This craft cannot carry so many items.\"\n  STR_ARMOR_NOT_ALLOWED_ONBOARD: \"ARMOR NOT ALLOWED!{SMALLLINE}Some soldiers are wearing forbidden armor.\"\n  STR_FOLLOW_WING_LEADER_QUESTION: \"Follow wing leader?\"\n#CraftNotEnoughPilotsState.cpp\n  STR_ASSIGN_PILOTS: \"Assign pilots...\"\n  STR_NOT_ENOUGH_PILOTS: \"Not enough pilots!{NEWLINE}Minimum: {0}\"\n#DogfightExperienceState.cpp\n  STR_DAILY_PILOT_EXPERIENCE: \"Daily Pilot Experience\"\n#DogfightState.cpp\n  STR_UFO_SHIELD_HIT: \"HIT THE SHIELDS!\"\n  STR_UFO_HIT_NO_DAMAGE: \"BOUNCED OFF THE HULL!\"\n  STR_UFO_SHIELD_DOWN: \"ENEMY SHIELDS DOWN!\"\n  STR_UFO_HIT_GLANCING: \"GLANCING HIT!\"\n  STR_INTERCEPTOR_SHIELD_HIT: \"OUR SHIELDS ARE HOLDING!\"\n  STR_TRACTOR_BEAM_ENGAGED: \"TRACTOR BEAM IS ENGAGED!\"\n  STR_TRACTOR_BEAM_DISENGAGED: \"DISENGAGING TRACTOR BEAM\"\n  STR_SELF_DESTRUCT_ACTIVATED: \"SELF-DESTRUCT ACTIVATED!\"\n  STR_SELF_DESTRUCT_CANCELLED: \"SELF-DESTRUCT CANCELLED\"\n  STR_MISSILE_DAMAGED: \">>> MISSILE DAMAGED <<<\"\n  STR_MISSILE_DESTROYED: \">>> MISSILE DESTROYED <<<\"\n  STR_OCEAN_INDICATOR: \"\"\n  STR_OCEAN_INDICATOR_RNG: \"\"\n#ExtendedGeoscapeLinksState.cpp\n  STR_EXTENDED_LINKS: \"Links\"\n#GeoscapeCraftState.cpp\n  STR_AUTO_PATROL: \"AUTO-PATROL\"\n  STR_ETA: \"ETA>{ALT}{0}\"\n#GeoscapeState.cpp\n  STR_NOT_ENOUGH_ITEM_TO_REARM_FACILITY_AT_BASE: \"Not enough {0} to rearm {1} at {2}\"\n  STR_UFO_STARTED_HUNTING: \"{0} is on an intercept course with {1}\"\n  STR_CRAFT_IS_READY: \"{0} at {1} is ready.\"\n  STR_ECONOMY_WARNING: \"The funds {0} and income {1} are low and the maintenance {2} too high! Sell something to avoid taking a credit... funds missing: {3}\"\n  STR_SLACKING_INDICATOR: \"{0}:{1}\"\n  STR_TRAINING_INDICATOR: \"{0}:{1}\"\n  STR_EXTENDED_UC: \"EXTENDED\"\n#InterceptState.cpp\n  STR_RETURNING: \"RETURNING\"\n  STR_INTERCEPTING: \"INTERCEPTING\"\n  STR_ESCORTING: \"ESCORTING\"\n  STR_EN_ROUTE: \"EN ROUTE\"\n  STR_PILOT_MISSING: \"PILOT MISSING\"\n  STR_DAY_SHORT: \"{0}d\"\n  STR_HOUR_SHORT: \"{0}h\"\n#MonthlyReportState.cpp\n  STR_PERFORMANCE_BONUS: \"Performance Bonus\"\n  STR_COUNTRY_HAS_CANCELLED_A_SECRET_PACT: \"{0} has renounced the pact with alien forces and was allowed to return to the project.\"\n  STR_COUNTRIES_HAVE_CANCELLED_A_SECRET_PACT: \"{0} have renounced the pact with alien forces and were allowed to return to the project.\"\n#NewPossibleCraftState.cpp\n  STR_WE_CAN_NOW_RENT: \"We can now rent\"\n#NewPossibleFacilityState.cpp\n  STR_REQUIRED_BASE_SERVICES: \"Required base services: {0}\"\n  STR_WE_CAN_NOW_BUILD: \"We can now build\"\n#NewPossiblePurchaseState.cpp\n  STR_WE_CAN_NOW_PURCHASE: \"We can now purchase\"\n#ProductionCompleteState.cpp\n  STR_NOT_ENOUGH_LIVING_SPACE_AT_BASE: \"Not enough living space to accomodate{NEWLINE}{0}{NEWLINE}at{NEWLINE}{1}\"\n#TargetInfoState.cpp\n  STR_INFO: \"INFO\"\n  STR_DESPAWN_PENALTY: \"Despawn penalty> {0}\"\n#TrainingFinishedState.cpp\n  STR_TRAINING_FINISHED: \"Training Finished{NEWLINE}at {0}\"\n  STR_PSI_TRAINING_FINISHED: \"Psi Training Finished{NEWLINE}at {0}\"\n#UfoDetectedState.cpp\n  STR_IGNORE_UC: \"IGNORE\"\n#UfoTrackerState.cpp\n  STR_UFO_TRACKER: \"UFO Tracker\"\n#=================== Menu ===================\n#MainMenuState.cpp\n  STR_UPDATE: \"Update\"\n  STR_LATEST_VERSION_INFO: \"You are using the latest OpenXcom version.\"\n#ModConfirmExtendedState.cpp\n  STR_MASTER_MOD_VERSION_REQUIRED_QUESTION: \"This mod requires base game v{0} to run correctly. Enable this mod?\"\n  STR_VERSION_REQUIRED_QUESTION: \"This mod requires OXCE v{0} to run correctly. Enable this mod?\"\n#ModListState.cpp\n  STR_OPEN_MODS_FOLDER: \"Open\"\n#NewBattleState.cpp\n  STR_GLOBE_TEXTURE: \"Globe Texture\"\n#NotesState.cpp\n  STR_NOTES: \"Notes\"\n  STR_NEW_NOTE: \"<NEW NOTE>\"\n#OptionsAdvancedState.cpp\n  STR_ENGINE_OXC: \"OXC\"\n  STR_ENGINE_OXCE: \"OXCE\"\n  STR_ENGINE_OTHER: \"OTHER\"\n  STR_BASESCAPE: \"Basescape\"\n  STR_AI: \"AI\"\n#OptionsBattlescapeState.cpp\n  STR_PATH_ENERGY_COST: \"Energy\"\n  STR_PATH_ENERGY_COST_DESC: \"Clicking shows the energy your unit will have remaining after moving to the destination.\"\n#StatisticsState.cpp\n  STR_VEHICLES_LOST: \"Vehicles lost\"\n  STR_CRAFT_LOST_DOGFIGHT: \"Interceptors lost\"\n  STR_CRAFT_LOST_MISSION: \"Transports lost\"\n  STR_ALIEN_BASES_DESTROYED: \"Alien bases destroyed\"\n  STR_XCOM_BASES_LOST: \"Bases lost\"\n#TestState.cpp\n  STR_TEST_SCREEN: \"TEST SCREEN\"\n  STR_PALETTE: \"Palette:\"\n  STR_PREVIEW: \"Preview\"\n  STR_TINY_BORDERLESS: \"Tiny, borderless\"\n  STR_TINY_BORDER: \"Tiny\"\n  STR_SMALL_LOW_CONTRAST: \"Small\"\n  STR_SMALL_HIGH_CONTRAST: \"Small, high contrast\"\n  STR_BIG_LOW_CONTRAST: \"Big\"\n  STR_BIG_HIGH_CONTRAST: \"Big, high contrast\"\n  STR_TEST_CASE: \"Test case:\"\n  STR_RUN: \"Run selected test!\"\n  STR_TESTS_STARTING: \"Starting...\"\n  STR_TESTS_ERRORS_FOUND: \"Total errors found (there may be duplicates): {0}\"\n  STR_TESTS_NO_ERRORS_FOUND: \"No errors found.\"\n  STR_TESTS_FINISHED: \"Finished.\"\n  STR_DETAILED_INFO_IN_LOG_FILE: \"Detailed info has been saved into openxcom.log\"\n#=================== Savegame ===================\n#Soldier.cpp\n  STR_RANK_NONE: \"-\"\n#=================== Ufopaedia ===================\n#ArticleState.cpp\n  STR_DAMAGE_NONE: \"NONE\"\n  STR_INFO_UFOPEDIA: \"INFO\"\n#ArticleStateCraft.cpp\n  STR_COCKPIT_CAPACITY: \"PILOTS>{ALT}{0}{ALT}\"\n  STR_MAXIMUM_RANGE: \"MAX RANGE>{ALT}{0}{ALT}\"\n  STR_MINIMUM_RANGE: \"MIN RANGE>{ALT}{0}{ALT}\"\n  STR_INFINITE_RANGE: \"N/A\"\n#ArticleStateCraftWeapon.cpp\n  STR_TRACTOR_BEAM_POWER: \"Power\"\n#ArticleStateItem.cpp\n  STR_WEIGHT_PEDIA1: \"Wt: {0}\"\n  STR_WEIGHT_PEDIA2: \"Wt: {0}/{1}\"\n  STR_SHOT_TYPE_MELEE: \"Melee\"\n  STR_ACCURACY_MODIFIER: \"Accuracy modifier>{ALT} {0}\"\n  STR_POWER_BONUS: \"Power bonus>{ALT} {0}\"\n  STR_MULTIPLE_DIFFERENT_BONUSES: \"multiple bonuses on various compatible ammo\"\n#StatsForNerdsState.cpp\n  STR_STATS_FOR_NERDS: \"Stats for Nerds\"\n  STR_ARTICLE: \"Article>{ALT} {0}\"\n  STR_COMPATIBLE_AMMO: \"Compatible ammo:\"\n  STR_BUILT_IN_ITEMS: \"Built-in items:\"\n  STR_CLIP_SIZE_UNLIMITED: \"unlimited\"\n  STR_SHOTGUN_BEHAVIOR_OXCE: \"extended\"\n  STR_INCLUDE_DEBUG: \"DEBUG\"\n  STR_INCLUDE_IDS: \"IDs\"\n  STR_INCLUDE_DEFAULTS: \"DEFAULTS\"\n  STR_TRUE: \"true\"\n  STR_FALSE: \"false\"\n#\n  STR_PSI_SKILL_AND_PSI_STRENGTH: \"PSI SKILL*PSI STRENGTH\"\n  STR_STRENGTH_AND_MELEE_ACCURACY: \"STRENGTH*MELEE ACCURACY\"\n  STR_STRENGTH_AND_THROWING_ACCURACY: \"STRENGTH*THROWING ACCURACY\"\n  STR_FIRING_ACCURACY_AND_REACTIONS: \"FIRING ACCURACY*REACTIONS\"\n  STR_HEALTH_CURRENT: \"CURRENT HEALTH\"\n  STR_MANA_CURRENT: \"CURRENT MANA\"\n  STR_TIME_UNITS_CURRENT: \"CURRENT TIME UNITS\"\n  STR_STUN_LEVEL_CURRENT: \"CURRENT STUN LEVEL\"\n  STR_HEALTH_NORMALIZED: \"NORMALIZED HEALTH\"\n  STR_MANA_NORMALIZED: \"NORMALIZED MANA\"\n  STR_TIME_UNITS_NORMALIZED: \"NORMALIZED TIME UNITS\"\n  STR_ENERGY_NORMALIZED: \"NORMALIZED ENERGY\"\n  STR_MORALE_NORMALIZED: \"NORMALIZED MORALE\"\n  STR_STUN_LEVEL_NORMALIZED: \"NORMALIZED STUN LEVEL\"\n  STR_ENERGY_REGENERATION: \"ENERGY REGENERATION\"\n#\n  STR_PSI_SKILL_AND_PSI_STRENGTH_ABBREVIATION: \"PSK*PST\"\n  STR_STRENGTH_AND_MELEE_ACCURACY_ABBREVIATION: \"STR*MEL\"\n  STR_STRENGTH_AND_THROWING_ACCURACY_ABBREVIATION: \"STR*THR\"\n  STR_FIRING_ACCURACY_AND_REACTIONS_ABBREVIATION: \"ACC*REA\"\n  STR_HEALTH_CURRENT_ABBREVIATION: \"CURRENT HEALTH\"\n  STR_MANA_CURRENT_ABBREVIATION: \"CURRENT MANA\"\n  STR_TIME_UNITS_CURRENT_ABBREVIATION: \"CURRENT TIME UNITS\"\n  STR_STUN_LEVEL_CURRENT_ABBREVIATION: \"CURRENT STUN LEVEL\"\n  STR_HEALTH_NORMALIZED_ABBREVIATION: \"NORMALIZED HEALTH\"\n  STR_MANA_NORMALIZED_ABBREVIATION: \"NORMALIZED MANA\"\n  STR_TIME_UNITS_NORMALIZED_ABBREVIATION: \"NORMALIZED TIME UNITS\"\n  STR_ENERGY_NORMALIZED_ABBREVIATION: \"NORMALIZED ENERGY\"\n  STR_MORALE_NORMALIZED_ABBREVIATION: \"NORMALIZED MORALE\"\n  STR_STUN_LEVEL_NORMALIZED_ABBREVIATION: \"NORMALIZED STUN LEVEL\"\n  STR_ENERGY_REGENERATION_ABBREVIATION: \"ENERGY REGENERATION\"\n#\n  STR_TIME_UNITS_SCALED: \"SCALED TIME UNITS\"\n  STR_STAMINA_SCALED: \"SCALED STAMINA\"\n  STR_HEALTH_SCALED: \"SCALED HEALTH\"\n  STR_BRAVERY_SCALED: \"SCALED BRAVERY\"\n  STR_REACTIONS_SCALED: \"SCALED REACTIONS\"\n  STR_FIRING_ACCURACY_SCALED: \"SCALED FIRING ACCURACY\"\n  STR_THROWING_ACCURACY_SCALED: \"SCALED THROWING ACCURACY\"\n  STR_STRENGTH_SCALED: \"SCALED STRENGTH\"\n  STR_PSIONIC_STRENGTH_SCALED: \"SCALED PSIONIC STRENGTH\"\n  STR_PSIONIC_SKILL_SCALED: \"SCALED PSIONIC SKILL\"\n  STR_MELEE_ACCURACY_SCALED: \"SCALED MELEE ACCURACY\"\n  STR_MANA_POOL_SCALED: \"SCALED MANA POOL\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH_SCALED: \"SCALED PSI SKILL*PSI STRENGTH\"\n  STR_STRENGTH_AND_MELEE_ACCURACY_SCALED: \"SCALED STRENGTH*MELEE ACCURACY\"\n  STR_STRENGTH_AND_THROWING_ACCURACY_SCALED: \"SCALED STRENGTH*THROWING ACCURACY\"\n  STR_FIRING_ACCURACY_AND_REACTIONS_SCALED: \"SCALED FIRING ACCURACY*REACTIONS\"\n#\n  STR_TIME_UNITS_SCALED_ABBREVIATION: \"SCALED TU\"\n  STR_STAMINA_SCALED_ABBREVIATION: \"SCALED STA\"\n  STR_HEALTH_SCALED_ABBREVIATION: \"SCALED HP\"\n  STR_BRAVERY_SCALED_ABBREVIATION: \"SCALED BRV\"\n  STR_REACTIONS_SCALED_ABBREVIATION: \"SCALED REA\"\n  STR_FIRING_ACCURACY_SCALED_ABBREVIATION: \"SCALED ACC\"\n  STR_THROWING_ACCURACY_SCALED_ABBREVIATION: \"SCALED THR\"\n  STR_STRENGTH_SCALED_ABBREVIATION: \"SCALED STR\"\n  STR_PSIONIC_STRENGTH_SCALED_ABBREVIATION: \"SCALED PST\"\n  STR_PSIONIC_SKILL_SCALED_ABBREVIATION: \"SCALED PSK\"\n  STR_MELEE_ACCURACY_SCALED_ABBREVIATION: \"SCALED MEL\"\n  STR_MANA_POOL_SCALED_ABBREVIATION: \"SCALED MAN\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH_SCALED_ABBREVIATION: \"SCALED PSK*PST\"\n  STR_STRENGTH_AND_MELEE_ACCURACY_SCALED_ABBREVIATION: \"SCALED STR*MEL\"\n  STR_STRENGTH_AND_THROWING_ACCURACY_SCALED_ABBREVIATION: \"SCALED STR*THR\"\n  STR_FIRING_ACCURACY_AND_REACTIONS_SCALED_ABBREVIATION: \"SCALED ACC*REA\"\n#\n  STR_COST_TIME: \"time\"\n  STR_COST_ENERGY: \"energy\"\n  STR_COST_MORALE: \"morale\"\n  STR_COST_HEALTH: \"health\"\n  STR_COST_STUN: \"stun\"\n  STR_COST_MANA: \"mana\"\n  STR_COST_BUILD: \"build\"\n  STR_COST_REFUND: \"refund\"\n#\n  STR_DAMAGE_10: \"10\"\n  STR_DAMAGE_11: \"11\"\n  STR_DAMAGE_12: \"12\"\n  STR_DAMAGE_13: \"13\"\n  STR_DAMAGE_14: \"14\"\n  STR_DAMAGE_15: \"15\"\n  STR_DAMAGE_16: \"16\"\n  STR_DAMAGE_17: \"17\"\n  STR_DAMAGE_18: \"18\"\n  STR_DAMAGE_19: \"19\"\n#\n  STR_NAUTICAL_MILES: \"{0} nautical miles\"\n  STR_KILOMETERS_PER_HOUR: \"{0} km/h\"\n  STR_SECONDS_LONG: \"{0} seconds\"\n  STR_RACE_BONUS: \"Race bonus\"\n  STR_FOR_DIFFICULTY: \"for difficulty: {0}\"\n#UfopaediaSelectState.cpp\n  STR_NOT_AWARDED_YET: \"Not awarded yet\"\n"
  },
  {
    "path": "bin/common/Language/OXCE/es-419.yml",
    "content": "es-419:\n  STR_CANNOT_DISMANTLE_FACILITY_UPGRADING: \"NO SE PUEDEN DESMANTELAR LAS INSTALACIONES!{SMALLLINE}La instalación no puede ser removida durante su mejora.\"\n  STR_CANNOT_UPGRADE_FACILITY_ALREADY_UPGRADING: \"NO SE PUEDE CONSTRUIR AQUI!{SMALLLINE}Una instalación ya ha sido construida aquí.\"\n  STR_CANNOT_UPGRADE_FACILITY_WRONG_SIZE: \"NO SE PUEDE CONSTRUIR AQUI!{SMALLLINE}La instalación seleccionada debe cubrir completamente  la ya existente.\"\n  STR_CANNOT_UPGRADE_FACILITY_WRONG_TYPE: \"NO SE PUEDE CONSTRUIR AQUI!{SMALLLINE}Instalacción existente no puede ser mejorada subro la instalación seleccionada.\"\n  STR_CANNOT_UPGRADE_FACILITY_DISALLOWED: \"NO SE PUEDE CONSTRUIR AQUI!{SMALLLINE}Instalación existente no puede ser reconstruida.\"\n  STR_CANNOT_BUILD_QUEUE_OFF: \"NO SE PUEDE CONSTRUIR AQUI!{SMALLLINE}Instalaciones conectadas deben terminar su construcción primero.\"\n  STR_ID: \"ID\"\n  STR_FIRST_LETTER: \"Primera letra\"\n  STR_SOLDIER_TYPE: \"Tipo de soldado\"\n  STR_LOAD_CRAFT_LOADOUT_TEMPLATE: \"Cargar equipamento de navio\"\n  STR_EMPTY_SLOT_N: \"Espacio vacio{0}\"\n  STR_UNNAMED_SLOT_N: \"Espacio sin nombre{0}\"\n  STR_SAVE_CRAFT_LOADOUT_TEMPLATE: \"Guardar equipamento de navio\"\n  STR_SAVE_UC: \"GUARDAR\"\n  STR_ALL: \"Todo\"\n  STR_EQUIPPED: \"Equipado\"\n  STR_UNASSIGNED: \"Otro\"\n  STR_PILOTS: \"PILOTOS\"\n  STR_SHIELD: \"ESCUDO>{ALT}{0}\"\n  STR_SELECT_PILOT: \"Seleccionar piloto\"\n  STR_PILOTS_FOR_CRAFT: \"Piloto(s) para {0}\"\n  STR_PILOTS_REQUIRED: \"Piloto(s) requeridos: {ALT}{0}\"\n  STR_ADD_PILOT: \"Añadir piloto\"\n  STR_REMOVE_ALL_PILOTS: \"Remover todos los pilotos\"\n  STR_ACCURACY_BONUS: \"Bonus de puntería\"\n  STR_DODGE_BONUS: \"Bonus de evasión\"\n  STR_APPROACH_SPEED: \"Velocidad de aproximación\"\n  STR_COWARDLY: \"Cobardemente (-50%)\"\n  STR_NORMAL: \"Normal\"\n  STR_BOLD: \"Valiente(+50%)\"\n  STR_VERY_BOLD: \"Temerario(+100%)\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW: \"Muestra\"\n  STR_REFUND_VALUE: \"Valor de ventas>{ALT}{0}\"\n  STR_PRODUCTION_OVERVIEW: \"INFORME DE PRODUCCION\"\n  STR_RESEARCH_OVERVIEW: \"Resumén de investigación\"\n  STR_SELL_SELECTED: \"Vender\"\n  STR_GO_TO_TRANSFERS: \"Transferir...\"\n  STR_TOPIC: \"Tema>{ALT} {0}\"\n  STR_SHOW_ALL: \"Mostrar todo\"\n  STR_NO_DEPENDENCIES: \"Sin dependencias\"\n  STR_DIRECT_DEPENDENCIES: \"Dependencias directas\"\n  STR_LEVEL_2_DEPENDENCIES: \"Dependencias de nivel 2\"\n  STR_LEVEL_3_DEPENDENCIES: \"Dependencias de nivel 3\"\n  STR_LEVEL_4_DEPENDENCIES: \"Dependencias de nivel 4\"\n  STR_MORE_DEPENDENCIES: \"Hay dependencías incluso más profundas...\"\n  STR_END_OF_SEARCH: \"Fin de investigación.\"\n  STR_REFUND_PRODUCTION: \"REEMBOLSO!\"\n  STR_PERSON_JOINING: \"Ingreso de personal\"\n  STR_RANDOM_PRODUCTION_DISCLAIMER: \"Producción al azar!\"\n  STR_OTHER_EMPLOYEES: \"Otro personal e inventario\"\n  STR_SHOW_ONLY_NEW: \"Mostrar solo nuevo\"\n  STR_FILTER_DEFAULT: \"Por defecto\"\n  STR_FILTER_DEFAULT_SUPPLIES_OK: \"Por defecto (suministros OK)\"\n  STR_FILTER_DEFAULT_NO_SUPPLIES: \"Por defecto (sin suministros)\"\n  STR_FILTER_FACILITY_REQUIRED: \"Instalación faltante\"\n  STR_FILTER_HIDDEN: \"Oculto\"\n  STR_FILTER_EQUIPPED: \"Equipado\"\n  STR_SORT_DEFAULT: \"Por defecto\"\n  STR_RANDOM_PRODUCTION_SUMMARY: \"Resumen\"\n  STR_NOT_ENOUGH_PRISON_SPACE: \"NO HAY SUFICIENTE ALMACENAMIENTO PARA EXTRATERRESTRES!{SMALLLINE}Construye mas almacenamiento o transfiere extraterrestres a otras bases. \"\n  STR_NOT_ENOUGH_CRAFT_SPACE: \"No hay suficiente espacio  a bordo!\"\n  STR_SELECT_AVATAR_FOR: \"SELECIONAR AVATAR PARA{NEWLINE]{0}}\"\n  STR_SUMMARY: \"Resumen\"\n  STR_TRAINING: \"Entrenamiento\"\n  STR_SOLDIER_INFO: \"Información de soldado\"\n  STR_TRANSFER_TIME: \"Tiempo de transferencia>{ALT}{0}\"\n  STR_RECOVERY_TIME: \"Tiempo de recuperación>{ALT}{0}\"\n  STR_CURRENT_STATS: \"Estados actuales\"\n  STR_CHANGES: \"Cambios\"\n  STR_GRAND_TOTAL: \"Gran total\"\n  STR_AVAILABLE_TOPICS: \"TEMAS DISPONIBLES\"\n  STR_QS_THREE_LETTERS_A: \"Por favor ingresar al menos 3 letras\"\n  STR_QS_THREE_LETTERS_B: \"Hacía la caja de busqueda rápida\"\n  STR_M_FLAG: \"[m]\"\n  STR_F_FLAG: \"[f]\"\n  STR_I_FLAG: \"[i]\"\n  STR_TECH_TREE_VIEWER: \"Visor de arbol de tecnologías\"\n  STR_SELECT_TOPIC: \"Seleccionar tema\"\n  STR_RESEARCH_PROGRESS: \"Progreso>{ALT} {0}%\"\n  STR_ITEM_DESTROYED: \"Objeto destruido:\"\n  STR_ITEM_REQUIRED: \"Objeto requerido:\"\n  STR_SERVICES_REQUIRED: \"Servicios requeridos:\"\n  STR_SERVICES_PROVIDED: \"Servicios entregados:\"\n  STR_SERVICES_FORBIDDEN: \"Servicios prohibidos:\"\n  STR_REQUIRES: \"Requiere:\"\n  STR_DEPENDS_ON: \"Depende de:\"\n  STR_UNLOCKED_BY: \"Desbloqueado por:\"\n  STR_DISABLED_BY: \"Deshabilitado por:\"\n  STR_GET_FOR_FREE_FROM: \"Se consigue gratis de:\"\n  STR_REQUIRED_BY: \"Requerido por:\"\n  STR_LEADS_TO: \"Lleva a:\"\n  STR_UNLOCKS: \"Desbloquea:\"\n  STR_DISABLES: \"Deshabilita:\"\n  STR_GIVES_ONE_FOR_FREE_SEQ: \"Da uno gratis (sequencial):\"\n  STR_GIVES_ONE_FOR_FREE: \"Da uno gratis:\"\n  STR_RESEARCH_REQUIRED: \"Investigación requerida:\"\n  STR_RESEARCH_REQUIRED_USE: \"Investigación requerida (uso):\"\n  STR_RESEARCH_REQUIRED_BUY: \"Investigación requerida (comprar)\"\n  STR_SERVICES_REQUIRED_BUY: \"Servicios requeridos (comprar)\"\n  STR_MATERIALS_REQUIRED: \"Materiales requeridos:\"\n  STR_ITEMS_PRODUCED: \"Objetos producidos:\"\n  STR_PERSON_RECRUITED: \"Persona reclutada:\"\n  STR_UNLOCKS_MISSIONS: \"Desbloquea misiones:\"\n  STR_DISABLES_MISSIONS: \"Desactiva misiones:\"\n  STR_AFFECTS_GAME_PROGRESSION: \"¡Afecta la progresion del juego!\"\n  STR_MUST_USE_BOTH_HANDS: \"Amas manos son requeridas para esto!\"\n  STR_NOT_ENOUGH_MORALE: \"No hay suficiente moral!\"\n  STR_NOT_ENOUGH_HEALTH: \"No hay suficiente salud!\"\n  STR_NOT_ENOUGH_STUN: \"Nivel de aturdimiento es demasiado alto!\"\n  STR_LINE_OF_SIGHT_REQUIRED: \"Linea de vista (LdV) requerida.\"\n  STR_CENTER_ON_WOUNDED_FRIEND: \"Centrar en amigo herido\"\n  STR_BUG_HUNT_ACTIVATED: \"Modo de caza de errores activado: los enemigos son visibles en el minimapa!\"\n  STR_TARGET_ENEMY: \"; Objetivo = ENEMIGO\"\n  STR_TARGET_NEUTRAL: \"; Objetivo = NEUTRAL\"\n  STR_TARGET_FRIEND: \"; OBJETIVO = Amigo\"\n  STR_TARGET_YOURSELF: \"; Objetivo = TU\"\n  STR_TARGET_ON_THE_GROUND: \"(Sobre el suelo)\"\n  STR_USE_SPECIAL_ITEM: \"Usar objeto especial\"\n  STR_NO_EXPERIENCE_YET: \"Sin experiencia todavía\"\n  STR_WHAT_CAN_I_WEAR: \"Que puedo vestir?\"\n  STR_STARTING_CONDITION_ARMORS_ALLOWED: \"Esta misión requiere equipo especifico.{NEWLINE}{NEWLINE}Los tipos de armadura permitida son: {0}\"\n  STR_MISSION_OVER: \"Misión completada.\"\n  STR_UNITS_WITH_FATAL_WOUNDS:\n    one: \"{N} de nosotros seguimos fatalmente lastimados\"\n    many: \"{N} de nosotros siguen fatalmente lastimados.\"\n    other: \"{N} de nosotros siguen fatalmente lastimados.\"\n  STR_END_MISSION_QUESTION: \"Terminar misión?\"\n  STR_LOOT: \"BOTÍN\"\n  STR_SELL: \"VENDER\"\n  STR_LIVE_ALIENS_SURRENDERED: \"ENEMIGOS RENDIDOS\"\n  STR_MISSION_ABORTED: \"MISION ABORTADA\"\n  STR_BOUNTY: \"RECOMPENSA\"\n  STR_CANNOT_PLACE_ITEM_INTO_THIS_SECTION: \"No esta permitido el poner este objeto aquí.{NEWLINE}No preguntes por que!\"\n  STR_ONE_HAND_MUST_BE_EMPTY: \"Al menos una mano debe estar vacía!\"\n  STR_LOAD_EQUIPMENT_TEMPLATE: \"Cargar plantilla de equipamento\"\n  STR_SAVE_EQUIPMENT_TEMPLATE: \"Guardar plantilla de equipamento\"\n  STR_FIRING_SHORT: \"Disparando>{ALT}{0}\"\n  STR_THROWING_SHORT: \"Arrojar>{ALT}{0}\"\n  STR_MELEE_SHORT: \"Cuerpo a cuerpo>{ALT}{0}\"\n  STR_HIT_LOG_NEW_TURN: \"Nuevo turno\"\n  STR_FAILED_CQB_CHECK: \"El enemigo logro interrumpir tu ataque!\"\n  STR_NO_TRAJECTORY: \"No hay una trajectoría viable!\"\n  STR_HIT_LOG_NEW_BULLET: \"=>\"\n  STR_HIT_LOG_NO_DAMAGE: \"0\"\n  STR_HIT_LOG_SMALL_DAMAGE: \"impacto\"\n  STR_HIT_LOG_BIG_DAMAGE: \"IMPACTO\"\n  STR_HIT_LOG_REACTION_FIRE: \"Fuego de reacción...\"\n  STR_BUTTON_10: \"10\"\n  STR_UFO_LANDING_ALERT: \"Alerta de aterrizaje OVNI\"\n  STR_UFO_LANDING_ALERT_DESC: \"Al estar activado, un mensaje se mostrara cada vez que un OVNI detectado aterrize.\"\n  STR_WOUNDED_DEFEND_BASE_IF: \"Los heridos se defienden (si los HP son más de x%)\"\n  STR_WOUNDED_DEFEND_BASE_IF_DESC: \"Los soldados heridos también defienden la base, si su salud está sobre el porcentaje indicado.\"\n  STR_PLAY_BRIEFING_MUSIC_DURING_EQUIPMENT: \"Reproducir la música de resumen por más tiempo\"\n  STR_PLAY_BRIEFING_MUSIC_DURING_EQUIPMENT_DESC: \"La música continuara reproduciendose durante la fase de equipamiento hasta que el mapa de batalla sea mostrado.\"\n  STR_NIGHT_VISION_COLOR: \"Seleccionar el color de visión nopturna\"\n  STR_AUTO_SELL: \"Administrador de Auto-venta\"\n  STR_AUTO_SELL_DESC: \"En la pantalla de resumen de batalla, cualquier objeto vendido en batallas prevías será seleccionado automaticamente para vender.\"\n  STR_GRAPHS_ZOOM_IN: \"Acercar (Graphs)\"\n  STR_GRAPHS_ZOOM_OUT: \"Alejar (Graphs)\"\n  STR_MARK_ALL_AS_SEEN: \"Marcar todo como visto\"\n  STR_ACTION_ITEM_1: \"Acción de objeto 1(Apuntar/usar)\"\n  STR_ACTION_ITEM_2: \"Acción de objeto 2 (Rápido)\"\n  STR_ACTION_ITEM_3: \"Acción de objeto 3 (Auto)\"\n  STR_ACTION_ITEM_4: \"Acción de objeto 4(Cuerpo a cuerpo)\"\n  STR_ACTION_ITEM_5: \"Acción de objeto 5 (Arrojar)\"\n  STR_TOGGLE_QUICK_SEARCH: \"Cambiar campo de busqueda rápido\"\n  STR_TOGGLE_NIGHT_VISION: \"Cambiar visión nopturna\"\n  STR_HOLD_NIGHT_VISION: \"Visión nopturna corta\"\n  STR_SELECT_MUSIC_TRACK: \"Seleccionar pista de música\"\n  STR_PHYSICAL_TRAINING: \"Entrenamiento marcial\"\n  STR_REMAINING_TRAINING_FACILITY_CAPACITY: \"Capacida de entrenamiento restante> {ALT}{0}\"\n  STR_NO_WOUNDED: \"-\"\n  STR_NO_DONE: \"HECHO\"\n  STR_START_FIRING: \"FUEGO!\"\n  STR_SKIP_FIRING: \"Dejenlos pasar...\"\n  STR_ALIEN_MISSILES_HAVE_DAMAGED_OUR_BASE: \"Misiles alienígenas han dañado nuestra base [0]\"\n  STR_ALIEN_MISSILES_HAVE_DESTROYED_OUR_BASE: \"Misiles alienígenas han destruido nuestra base [0]\"\n  STR_STARTING_CONDITION_ITEM: \"Esta misión requiere un(os) ítem(s) específico(s):[NEWLINE][NEWLINE][0]\"\n  STR_ASSIGN_PILOTS: \"Asignar pilotos...\"\n  STR_NOT_ENOUGH_PILOTS: \"No hay pilotos suficientes!{NEWLINE}Minimo: {0}\"\n  STR_UFO_SHIELD_HIT: \"GOLPEAR LOS ESCUDOS!\"\n  STR_UFO_HIT_NO_DAMAGE: \"REBOTO DEL CASCO!\"\n  STR_UFO_SHIELD_DOWN: \"ESCUDOS ENEMIGOS ABATIDOS!\"\n  STR_UFO_HIT_GLANCING: \"AVISTANDO GOLPE!\"\n  STR_INTERCEPTOR_SHIELD_HIT: \"NUESTROS ESCUDOS SE MANTIENEN!\"\n  STR_TRACTOR_BEAM_ENGAGED: \"EL RAYO TRACTOR HA SIDO ALCANZADO!\"\n  STR_TRACTOR_BEAM_DISENGAGED: \"ALEJANDOSE DE RAYO TRACTOR\"\n  STR_SELF_DESTRUCT_ACTIVATED: \"AUTO-DESTRUCCIÓN ACTIVADA!\"\n  STR_SELF_DESTRUCT_CANCELLED: \"AUTO-DESTRUCCIÓN CANCELADA!\"\n  STR_AUTO_PATROL: \"AUTO-PATRULLA\"\n  STR_UFO_STARTED_HUNTING: \"{0} esta en curso de interceptar con {1}\"\n  STR_CRAFT_IS_READY: \"{0} en {1} esta listo.\"\n  STR_ECONOMY_WARNING: \"Los fondos{0} e ingresos {1} son bajos y el mantenimiento {2} demasiado alto! Vende algo para evitar tomar un prestamo...Fondos faltantes: {3}\"\n  STR_RETURNING: \"REGRESANDO\"\n  STR_INTERCEPTING: \"INTERCEPTANDO\"\n  STR_ESCORTING: \"ESCOLTANDO\"\n  STR_EN_ROUTE: \"EN RUTA\"\n  STR_PILOT_MISSING: \"PILOTO FALTANTE\"\n  STR_DAY_SHORT: \"{0}d\"\n  STR_HOUR_SHORT: \"{0}h\"\n  STR_PERFORMANCE_BONUS: \"Bonus de rendimiento\"\n  STR_COUNTRY_HAS_CANCELLED_A_SECRET_PACT: \"{0} ha renunciado al pacto con las fuerzas alienigenas y se le ha permitido regresar al projecto.\"\n  STR_COUNTRIES_HAVE_CANCELLED_A_SECRET_PACT: \"{0} ha renunciado al pacto con fuerzas alienigenas y se les permitio regresar al projecto.\"\n  STR_WE_CAN_NOW_RENT: \"Ahora podemos rentar\"\n  STR_WE_CAN_NOW_BUILD: \"Ahora podemos construir\"\n  STR_WE_CAN_NOW_PURCHASE: \"Ahora podemos comprar\"\n  STR_NOT_ENOUGH_LIVING_SPACE_AT_BASE: \"No hay suficiente espacio de vivienda para acomodar{NEWLINE}{0}{NEWLINE}en{NEWLINE}{1}\"\n  STR_INFO: \"INFO\"\n  STR_UFO_TRACKER: \"Rastreador OVNi\"\n  STR_TEST_SCREEN: \"PANTALLA DE PRUEBA\"\n  STR_PALETTE: \"Paleta;\"\n  STR_PREVIEW: \"Muestra\"\n  STR_TINY_BORDERLESS: \"Diminuta, sin bordes\"\n  STR_TINY_BORDER: \"Diminuta\"\n  STR_SMALL_LOW_CONTRAST: \"Pequeña\"\n  STR_SMALL_HIGH_CONTRAST: \"Pequeña, alto contraste\"\n  STR_BIG_LOW_CONTRAST: \"Grande\"\n  STR_BIG_HIGH_CONTRAST: \"Grande, alto contraste\"\n  STR_TEST_CASE: \"Caja de prueba:\"\n  STR_RUN: \"Empezar prueba seleccionada!\"\n  STR_TESTS_STARTING: \"Empezando...\"\n  STR_TESTS_ERRORS_FOUND: \"Total de errores encontrados (podía haber duplicados): {0}\"\n  STR_TESTS_NO_ERRORS_FOUND: \"Sin errores encontrados.\"\n  STR_TESTS_FINISHED: \"Terminada\"\n  STR_DETAILED_INFO_IN_LOG_FILE: \"Información detalla ha sido guardada en openxcom.log\"\n  STR_RANK_NONE: \"-\"\n  STR_DAMAGE_NONE: \"NADA\"\n  STR_INFO_UFOPEDIA: \"INFO\"\n  STR_COCKPIT_CAPACITY: \"PILOTOS>{ALT}{0}{ALT}\"\n  STR_MAXIMUM_RANGE: \"RANGO MAXIMO>{ALT}{0}{ALT}\"\n  STR_MINIMUM_RANGE: \"RANGO MINIMO>{ALT}{0}{ALT}\"\n  STR_INFINITE_RANGE: \"N/A\"\n  STR_WEIGHT_PEDIA1: \"Peso: {0}\"\n  STR_WEIGHT_PEDIA2: \"Peso: {0}/{1}\"\n  STR_SHOT_TYPE_MELEE: \"Cuerpo a cuerpo\"\n  STR_ACCURACY_MODIFIER: \"Modificador de puntería>{ALT} {0}\"\n  STR_POWER_BONUS: \"Bonus de poder>{ALT} {0}\"\n  STR_MULTIPLE_DIFFERENT_BONUSES: \"multiples bonus en varios tipos de munición compatible\"\n  STR_STATS_FOR_NERDS: \"Estadísticas para nerds\"\n  STR_ARTICLE: \"Articulo>{ALT} {0}\"\n  STR_COMPATIBLE_AMMO: \"Munición compatible:\"\n  STR_BUILT_IN_ITEMS: \"Objetos incluidos:\"\n  STR_CLIP_SIZE_UNLIMITED: \"ilimitado\"\n  STR_SHOTGUN_BEHAVIOR_OXCE: \"extendido\"\n  STR_INCLUDE_DEBUG: \"DEPURAR\"\n  STR_INCLUDE_IDS: \"IDs\"\n  STR_INCLUDE_DEFAULTS: \"POR DEFECTO\"\n  STR_TRUE: \"verdadero\"\n  STR_FALSE: \"falso\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH: \"PSI habilidad*PSI FUERZA\"\n  STR_STRENGTH_AND_MELEE_ACCURACY: \"FUERZA*PUNTERIA CUERPO A CUERPO\"\n  STR_STRENGTH_AND_THROWING_ACCURACY: \"FUERZA*PUNTERÍA ARROJADIZA\"\n  STR_FIRING_ACCURACY_AND_REACTIONS: \"PUNTERÍA DE DISPARO*REACCIONES\"\n  STR_HEALTH_CURRENT: \"VIDA ACTUAL\"\n  STR_TIME_UNITS_CURRENT: \"UNIDADES DE TIEMPO ACTUALES\"\n  STR_STUN_LEVEL_CURRENT: \"NIVEL DE ATURDIMIENTO ACTUAL\"\n  STR_HEALTH_NORMALIZED: \"SALUD NORMALIZADA\"\n  STR_TIME_UNITS_NORMALIZED: \"UNIDADES DE TIEMPO NORMALIZADAS\"\n  STR_ENERGY_NORMALIZED: \"ENERGIA NORMALIZADA\"\n  STR_MORALE_NORMALIZED: \"MORAL NORMALIZADA\"\n  STR_STUN_LEVEL_NORMALIZED: \"NIVEL DE ATURDIMIENTO NORMALIZADO\"\n  STR_ENERGY_REGENERATION: \"REGENERACIÓN DE ENERGÍA\"\n  STR_HEALTH_CURRENT_ABBREVIATION: \"VIDA ACTUAL\"\n  STR_TIME_UNITS_CURRENT_ABBREVIATION: \"UNIDADES DE TIEMPO ACTUALES\"\n  STR_STUN_LEVEL_CURRENT_ABBREVIATION: \"NIVEL DE ATURDIMIENTO ACTUAL\"\n  STR_HEALTH_NORMALIZED_ABBREVIATION: \"SALUD NORMALIZADA\"\n  STR_TIME_UNITS_NORMALIZED_ABBREVIATION: \"UNIDADES DE TIEMPO NORMALIZADAS\"\n  STR_ENERGY_NORMALIZED_ABBREVIATION: \"ENERGIA NORMALIZADA\"\n  STR_MORALE_NORMALIZED_ABBREVIATION: \"MORAL NORMALIZADA\"\n  STR_STUN_LEVEL_NORMALIZED_ABBREVIATION: \"NIVEL DE ATURDIMIENTO NORMALIZADO\"\n  STR_ENERGY_REGENERATION_ABBREVIATION: \"REGENERACIÓN DE ENERGÍA\"\n  STR_COST_TIME: \"tiempo\"\n  STR_COST_ENERGY: \"energía\"\n  STR_COST_MORALE: \"moral\"\n  STR_COST_HEALTH: \"salud\"\n  STR_COST_STUN: \"aturdimiento\"\n  STR_COST_BUILD: \"construir\"\n  STR_COST_REFUND: \"reembolsar\"\n  STR_DAMAGE_10: \"10\"\n  STR_DAMAGE_11: \"11\"\n  STR_DAMAGE_12: \"12\"\n  STR_DAMAGE_13: \"13\"\n  STR_DAMAGE_14: \"14\"\n  STR_DAMAGE_15: \"15\"\n  STR_DAMAGE_16: \"16\"\n  STR_DAMAGE_17: \"17\"\n  STR_DAMAGE_18: \"18\"\n  STR_DAMAGE_19: \"19\"\n  STR_NAUTICAL_MILES: \"{0} millas nauticas\"\n  STR_KILOMETERS_PER_HOUR: \"{0} km/h\"\n  STR_SECONDS_LONG: \"{0} segundos\"\n  STR_RACE_BONUS: \"Bonus de raza\"\n  STR_FOR_DIFFICULTY: \"por dificultar: {0}\"\n  STR_NOT_AWARDED_YET: \"No recompensado todavía\"\n"
  },
  {
    "path": "bin/common/Language/OXCE/es-ES.yml",
    "content": "es-ES:\n  STR_CANNOT_DISMANTLE_FACILITY_UPGRADING: \"¡NO SE PUEDE DESMANTAR LA INSTALACIÓN!{SMALLLINE}La instalación no se puede eliminar durante la actualización.\"\n  STR_CANNOT_UPGRADE_FACILITY_ALREADY_UPGRADING: \"¡NO SE PUEDE CONSTRUIR AQUI!{SMALLLINE}Una instalación ya ha sido construida aquí.\"\n  STR_CANNOT_UPGRADE_FACILITY_WRONG_SIZE: \"¡NO SE PUEDE CONSTRUIR AQUI!{SMALLLINE}La instalación seleccionada debe cubrir completamente  la ya existente.\"\n  STR_CANNOT_UPGRADE_FACILITY_WRONG_TYPE: \"¡NO SE PUEDE CONSTRUIR AQUI!{SMALLLINE}La Instalación existente no puede ser mejorada por la instalación seleccionada.\"\n  STR_CANNOT_UPGRADE_FACILITY_DISALLOWED: \"¡NO SE PUEDE CONSTRUIR AQUÍ!{SMALLLINE}No se puede reconstruir la instalación existente.\"\n  STR_CANNOT_BUILD_QUEUE_OFF: \"¡NO SE PUEDE CONSTRUIR AQUÍ!{SMALLLINE}Las instalaciones adyacentes han de finalizarse previamente.\"\n  STR_FACILITY_FORBIDDEN_BY_OTHER: \"¡NO SE PUEDE CONSTRUIR AQUÍ!{SMALLLINE}Algunas instalaciones existentes impiden construir esta instalación.\"\n  STR_FACILITY_OTHER_FORBIDDEN_BY_THIS: \"¡NO SE PUEDE CONSTRUIR AQUÍ!{SMALLLINE}Esta instalación es incompatible con alguna de las instalaciones ya existentes.\"\n  STR_NOT_ENOUGH_ITEMS: \"¡NO HAY SUFICIENTES MATERIALES!{SMALLLINE}Necesitamos más recursos para construir esta instalación.{NEWLINE}Falta> {0}: {1}\"\n  STR_LOAD_CRAFT_LOADOUT_TEMPLATE: \"Cargar equipamiento de naves\"\n  STR_EMPTY_SLOT_N: \"Ranura vacía {0}\"\n  STR_UNNAMED_SLOT_N: \"Ranura sin nombre {0}\"\n  STR_ADD_ON_TOP: \"Añadir encima\"\n  STR_SAVE_CRAFT_LOADOUT_TEMPLATE: \"Guardar equipamiento de naves\"\n  STR_SAVE_UC: \"GUARDAR\"\n  STR_ALL: \"Todo\"\n  STR_EQUIPPED: \"Equipado\"\n  STR_NOT_EQUIPPED: \"No equipado\"\n  STR_UNASSIGNED: \"Otro\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED_BY_SIZE: \"¡NO SE PERMITE MÁS EQUIPO A BORDO!{SMALLLINE}Espacio de almacenamiento máximo: {0}\"\n  STR_PILOTS: \"PILOTOS\"\n  STR_SHIELD: \"ESCUDO>{ALT}{0}\"\n  STR_SELECT_PILOT: \"Seleccionar piloto\"\n  STR_PILOTS_FOR_CRAFT: \"Piloto(s) para {0}\"\n  STR_PILOTS_REQUIRED: \"Piloto(s) requeridos: {ALT}{0}\"\n  STR_ADD_PILOT: \"Añadir piloto\"\n  STR_REMOVE_ALL_PILOTS: \"Quitar todos los pilotos\"\n  STR_ACCURACY_BONUS: \"Bonus de puntería:\"\n  STR_DODGE_BONUS: \"Bonus de evasión:\"\n  STR_APPROACH_SPEED: \"Velocidad de aproximación:\"\n  STR_COWARDLY: \"Cobardemente (-50%)\"\n  STR_BOLD: \"Valiente (+50%)\"\n  STR_VERY_BOLD: \"Temerario (+100%)\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW: \"Muestra\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_SAVED: \"Muestra *\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_BRIEFING: \"Esta función te permite obtener una vista previa y personalizar el despliegue de tus unidades al comienzo de una batalla. Tienes movimiento ilimitado. Mantenga presionado 'Alt' para resaltar las posiciones válidas de las unidades. Haga clic en el icono 'Abortar misión' para guardar una implementación personalizada. Haz clic en el icono \\\"Finalizar turno\\\" para salir de la vista previa.{NEWLINE}Ten en cuenta que agregar nuevos soldados o vehículos a la nave invalida automáticamente el despliegue personalizado guardado. La presencia de una implementación personalizada se indica con un asterisco en el botón \\\"Vista previa\\\".\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_BRIEFING_DUMMY: \"Esta característica le permite obtener una vista previa y modificar la tabla de despliegue de este tipo de nave. Cualquier cambio se aplicará a todas tus naves actuales y también a cualquier nave que compres o fabriques más adelante en la campaña. Comienzas con el número máximo de soldados. Cada soldado representa una fila en la tabla de despliegue. Los nombres de los soldados corresponden a los números de fila. Para proporcionar espacio para una unidad de 2x2, coloca 4 soldados en un cuadrado de 2x2. Si no se proporciona espacio, la unidad 2x2 faltará en una batalla real.\"\n  STR_BASE_DEFENSE_BRIEFING_PREVIEW: \"Esta función te permite obtener una vista previa de tu base.{NEWLINE}¡Diviértete!{NEWLINE}{NEWLINE}Haz clic en el icono \\\"Finalizar turno\\\" para salir de la vista previa.\"\n  STR_NOT_ENOUGH_CARGO_SPACE: \"¡NO HAY SUFICIENTE ESPACIO DE CARGA DISPONIBLE!{SMALLLINE}Utilice un módulo diferente o reduzca la tripulación asignada.\"\n  STR_REFUND_VALUE: \"Valor de ventas> {ALT}{0}\"\n  STR_PRODUCTION_OVERVIEW: \"INFORME DE PRODUCCIÓN\"\n  STR_RESEARCH_OVERVIEW: \"INFORME DE LA INVESTIGACIÓN\"\n  STR_PRISONER_OVERVIEW: \"INFORME DEL PRISIONERO\"\n  STR_PRISONER: \"PRISIONERO\"\n  STR_PRISONER_AMOUNT: \"CANTIDAD\"\n  STR_PRISONER_INTERROGATED: \"INTERROGADO\"\n  STR_TOTAL_IN_PRISON: \"Espacio utilizado>{ALT}{0}\"\n  STR_TOTAL_INTERROGATED: \"Interrogado>{ALT}{0}\"\n  STR_PRISON_TYPE: \"Contención alienígena\"\n  STR_KILL_SELECTED: \"Matar\"\n  STR_SELL_SELECTED: \"Vender\"\n  STR_GO_TO_TRANSFERS: \"Tranferir...\"\n  STR_PRISON_CLEANUP: \"Vaciar prisión\"\n  STR_TOPIC: \"Tema>{ALT} {0}\"\n  STR_SHOW_ALL: \"Mostrar todo\"\n  STR_NO_DEPENDENCIES: \"Sin dependencias\"\n  STR_DIRECT_DEPENDENCIES: \"Dependencias directas\"\n  STR_LEVEL_2_DEPENDENCIES: \"Dependencias de nivel 2\"\n  STR_LEVEL_3_DEPENDENCIES: \"Dependencias de nivel 3\"\n  STR_LEVEL_4_DEPENDENCIES: \"Dependencias de nivel 4\"\n  STR_MORE_DEPENDENCIES: \"Hay dependencías incluso más profundas...\"\n  STR_END_OF_SEARCH: \"Fin de búsqueda.\"\n  STR_REFUND_PRODUCTION: \"¡REEMBOLSO!\"\n  STR_HOURS_PER_UNIT: \"HORAS POR UNIDAD>{ALT}{0}\"\n  STR_PERSON_JOINING: \"Persona uniéndose\"\n  STR_RANDOM_PRODUCTION_DISCLAIMER: \"¡Producción al azar!\"\n  STR_OTHER_EMPLOYEES: \"Otro personal e inventario\"\n  STR_SHOW_ONLY_NEW: \"Mostrar solo nuevo\"\n  STR_FILTER_DEFAULT: \"Por defecto\"\n  STR_FILTER_DEFAULT_SUPPLIES_OK: \"Por defecto (suministros OK)\"\n  STR_FILTER_DEFAULT_NO_SUPPLIES: \"Por defecto (sin suministros)\"\n  STR_FILTER_FACILITY_REQUIRED: \"Instalación faltante\"\n  STR_FILTER_HIDDEN: \"Oculto\"\n  STR_FILTER_EQUIPPED: \"Equipado\"\n  STR_FILTER_MISSING: \"Perdido\"\n  STR_SORT_DEFAULT: \"Por defecto\"\n  STR_SORT_BY_COST: \"Por coste\"\n  STR_SORT_BY_NAME: \"Por nombre\"\n  STR_RANDOM_PRODUCTION_SUMMARY: \"Resumen\"\n  STR_NOT_ENOUGH_PRISON_SPACE: \"¡NO HAY SUFICIENTE CONTENCIÓN ALIENÍGENA!{SMALLLINE}Construye más contenciones alienígenas o transfiérelos a otras bases.\"\n  STR_MONTHLY_ITEM_PURCHASE_LIMIT_EXCEEDED: \"¡SE SUPERÓ EL LÍMITE DE COMPRAS MENSUALES!{SMALLLINE}Habrá más artículos disponibles el próximo mes.\"\n  STR_MONTHLY_CRAFT_PURCHASE_LIMIT_EXCEEDED: \"¡SE SUPERÓ EL LÍMITE DE COMPRAS MENSUALES!{SMALLLINE}Habrá más naves disponibles el próximo mes.\"\n  STR_MONTHLY_SOLDIER_HIRING_LIMIT_EXCEEDED: \"¡SE SUPERÓ EL LÍMITE DE CONTRATACIÓN MENSUAL!{SMALLLINE}Habrá más reclutas disponibles el próximo mes.\"\n  STR_NOT_ENOUGH_CRAFT_SPACE: \"¡No hay suficiente espacio  a bordo!\"\n  STR_SELECT_AVATAR_FOR: \"SELECIONAR AVATAR PARA{NEWLINE}{0}\"\n  STR_SOLDIER_BONUSES_FOR: \"BONIFICACIONES DE SOLDADO PARA{NEWLINE}{0}\"\n  STR_SUMMARY: \"Resumen\"\n  STR_MANA_RECOVERY: \"RECUPERACIÓN DE MANÁ> {ALT}{0}\"\n  STR_HEALTH_RECOVERY: \"RECUPERACIÓN DE SALUD> {ALT}{0}\"\n  STR_PROMOTE_SOLDIER: \"PROMOVER/DEGRADAR{NEWLINE}{0} {1}\"\n  STR_RANK_HEADER: \"RANGO\"\n  STR_OPENINGS_HEADER: \"APERTURAS\"\n  STR_TRAINING: \"Entrenamiento\"\n  STR_SOLDIER_INFO: \"Información de soldado\"\n  STR_TRANSFER_TIME: \"Tiempo de transferencia>{ALT}{0}\"\n  STR_RECOVERY_TIME: \"Tiempo de recuperación>{ALT}{0}\"\n  STR_CURRENT_STATS: \"Estadísticas actuales\"\n  STR_CHANGES: \"Cambios\"\n  STR_CHANGES_MIN: \"Cambios (mín)\"\n  STR_CHANGES_MAX: \"Cambios (máx)\"\n  STR_BONUS_STATS: \"Estadísticas bonus\"\n  STR_TRANSFORMATIONS_OVERVIEW: \"Resumen de transformaciones\"\n  STR_PROJECT_NAME: \"NOMBRE DEL PROYECTO\"\n  STR_AVAILABLE_MATERIALS: \"MATERIALES DISPONIBLES\"\n  STR_ELIGIBLE_SOLDIERS: \"SOLDADOS ELEGIBLES\"\n  STR_SHOW_ONLY_ELIGIBLE: \"Mostrar solo elegibles\"\n  STR_ALL_SOLDIER_TYPES: \"Todos los tipos de soldados\"\n  STR_ALL_SOLDIERS: \"Todos los soldados\"\n  STR_HEALTHY_SOLDIERS: \"Soldados sanos\"\n  STR_WOUNDED_SOLDIERS: \"Soldados heridos\"\n  STR_DEAD_SOLDIERS: \"Soldados muertos\"\n  STR_GRAND_TOTAL: \"Gran total\"\n  STR_AVAILABLE_TOPICS: \"TEMAS DISPONIBLES\"\n  STR_QS_THREE_LETTERS_A: \"Por favor ingrese al menos 3 letras\"\n  STR_QS_THREE_LETTERS_B: \"en el cuadro de Búsqueda Rápida...\"\n  STR_THIS_FEATURE_IS_DISABLED_1: \"Esta característica está deshabilitada.\"\n  STR_THIS_FEATURE_IS_DISABLED_2: \"Esta característica está deshabilitada.\"\n  STR_THIS_FEATURE_IS_DISABLED_3: \"Esta característica está deshabilitada.\"\n  STR_THIS_FEATURE_IS_DISABLED_4: \"Esta característica está deshabilitada.\"\n  STR_THIS_FEATURE_IS_DISABLED_5: \"Esta característica está deshabilitada.\"\n  STR_TECH_TREE_VIEWER: \"Visor de árbol tecnológico\"\n  STR_SELECT_TOPIC: \"Seleccionar tema\"\n  STR_RESEARCH_PROGRESS: \"Progreso>{ALT} {0}%\"\n  STR_ITEM_DESTROYED: \"Objeto destruido:\"\n  STR_ITEM_REQUIRED: \"Objeto requerido:\"\n  STR_SERVICES_REQUIRED: \"Servicios requeridos:\"\n  STR_SERVICES_PROVIDED: \"Servicios prestados:\"\n  STR_SERVICES_FORBIDDEN: \"Servicios prohibidos:\"\n  STR_REQUIRES: \"Requiere:\"\n  STR_DEPENDS_ON: \"Depende de:\"\n  STR_UNLOCKED_BY: \"Desbloqueado por:\"\n  STR_DISABLED_BY: \"Deshabilitado por:\"\n  STR_REENABLED_BY: \"Reactivado por:\"\n  STR_GET_FOR_FREE_FROM: \"Se consigue gratis de:\"\n  STR_IS_LOOKUP_OF: \"Es la búsqueda de:\"\n  STR_LOOKUP: \"Búsqueda:\"\n  STR_SPAWNED_ITEMS: \"Artículos generados:\"\n  STR_SPAWNED_EVENT: \"Eventos generados:\"\n  STR_REQUIRED_BY: \"Requerido por:\"\n  STR_REQUIRED_BY_TRANSFORMATIONS: \"Requerido por transformaciones:\"\n  STR_LEADS_TO: \"Lleva a:\"\n  STR_UNLOCKS: \"Desbloquea:\"\n  STR_DISABLES: \"Deshabilita:\"\n  STR_REENABLES: \"Reactiva:\"\n  STR_GIVES_ONE_FOR_FREE_SEQ: \"Da uno gratis (sequencial):\"\n  STR_GIVES_ONE_FOR_FREE: \"Da uno gratis:\"\n  STR_RESEARCH_REQUIRED: \"Investigación requerida:\"\n  STR_RESEARCH_REQUIRED_USE: \"Investigación requerida (uso):\"\n  STR_RESEARCH_REQUIRED_BUY: \"Investigación requerida (comprar):\"\n  STR_SERVICES_REQUIRED_BUY: \"Servicios requeridos (comprar):\"\n  STR_PRODUCED_BY: \"Producido por:\"\n  STR_SPAWNED_BY: \"Generado por:\"\n  STR_MATERIALS_REQUIRED: \"Materiales requeridos:\"\n  STR_TTV_COST_PER_UNIT: \"Coste por unidad:\"\n  STR_TTV_ENGINEER_HOURS: \"Horas de ingeniero:\"\n  STR_TTV_WORK_SPACE_REQUIRED: \"Espacio de trabajo requerido:\"\n  STR_ITEMS_PRODUCED: \"Objetos producidos:\"\n  STR_PERSON_RECRUITED: \"Persona reclutada:\"\n  STR_UNLOCKS_ARCS: \"Desbloquea arcos:\"\n  STR_DISABLES_ARCS: \"Deshabilita arcos:\"\n  STR_UNLOCKS_MISSIONS: \"Desbloquea misiones:\"\n  STR_DISABLES_MISSIONS: \"Desactiva misiones:\"\n  STR_UNLOCKS_EVENTS: \"Desbloquea eventos:\"\n  STR_DISABLES_EVENTS: \"Desactiva eventos:\"\n  STR_AFFECTS_GAME_PROGRESSION: \"¡Afecta la progresión del juego!\"\n  STR_ITEMS_AT_DESTINATION: \"Artículos en destino\"\n  STR_PRISONERS: \"Prisioneros\"\n  STR_ARMORS: \"Armaduras\"\n  STR_CRAFT_DEPLOYMENT_QUESTION: \"¿Guardar el despliegue de la nave?\"\n  STR_MUST_USE_BOTH_HANDS: \"¡Para esto se necesitan ambas manos!\"\n  STR_NOT_ENOUGH_MORALE: \"¡No hay suficiente moral!\"\n  STR_NOT_ENOUGH_HEALTH: \"¡No hay suficiente salud!\"\n  STR_NOT_ENOUGH_MANA: \"¡No hay suficiente maná!\"\n  STR_NOT_ENOUGH_STUN: \"¡El nivel de aturdimiento es demasiado alto!\"\n  STR_LINE_OF_SIGHT_REQUIRED: \"Se requiere línea de visión (LdV).\"\n  STR_CENTER_ON_WOUNDED_FRIEND: \"Centrar en amigo herido\"\n  STR_CENTER_ON_DIZZY_FRIEND: \"Centrar en amigo mareado\"\n  STR_BUG_HUNT_ACTIVATED: \"Modo Bug Hunt activado: ¡los enemigos son visibles en el minimapa!\"\n  STR_TARGET_ENEMY: \"; Objetivo = ENEMIGO\"\n  STR_TARGET_NEUTRAL: \"; Objetivo = NEUTRAL\"\n  STR_TARGET_FRIEND: \"; Objetivo = AMIGO\"\n  STR_TARGET_YOURSELF: \"; Objetivo = TU\"\n  STR_TARGET_ON_THE_GROUND: \"(en el suelo)\"\n  STR_USE_SPECIAL_ITEM: \"Usar objeto especial\"\n  STR_NO_EXPERIENCE_YET: \"Aún no hay experiencia:\"\n  STR_OPERATION_UC: \"OPERACIÓN> {0}\"\n  STR_WHAT_CAN_I_WEAR: \"¿Qué puedo ponerme?\"\n  STR_STARTING_CONDITION_ARMORS_FORBIDDEN: \"Esta misión requiere equipo específico.{NEWLINE}{NEWLINE}Los tipos de armadura prohibidos son: {0}\"\n  STR_STARTING_CONDITION_ARMORS_ALLOWED: \"Esta misión requiere equipo específico.{NEWLINE}{NEWLINE}Los tipos de armadura permitidos son: {0}\"\n  STR_MISSION_OVER: \"Misión completada.\"\n  STR_UNITS_WITH_FATAL_WOUNDS:\n    one: \"{N} de los nuestros todavía está fatalmente herido\"\n    many: \"{N} de los nuestros todavía están fatalmente heridos\"\n    other: \"{N} de los nuestros todavía están fatalmente heridos\"\n  STR_END_MISSION_QUESTION: \"¿Finalizar misión?\"\n  STR_LOOT: \"BOTÍN\"\n  STR_SELL: \"VENDER\"\n  STR_LIVE_ALIENS_SURRENDERED: \"ENEMIGOS RENDIDOS\"\n  STR_MISSION_ABORTED: \"MISIÓN ABORTADA\"\n  STR_VIPS_SAVED: \"VIPS SALVADOS\"\n  STR_VIPS_LOST: \"VIPS PERDIDOS\"\n  STR_BOUNTY: \"RECOMPENSA\"\n  STR_CANNOT_PLACE_ITEM_INTO_THIS_SECTION: \"No está permitido colocar ese objeto aquí.{NEWLINE}¡No preguntes por qué!\"\n  STR_ONE_HAND_MUST_BE_EMPTY: \"¡Al menos una mano debe estar vacía!\"\n  STR_LOAD_EQUIPMENT_TEMPLATE: \"Cargar plantilla de equipamento\"\n  STR_SAVE_EQUIPMENT_TEMPLATE: \"Guardar plantilla de equipamento\"\n  STR_FIRING_SHORT: \"Disp.>{ALT}{0}\"\n  STR_THROWING_SHORT: \"Lanz.>{ALT}{0}\"\n  STR_MELEE_SHORT: \"C.aC.>{ALT}{0}\"\n  STR_PERSONAL_EQUIPMENT: \"EQUIPO PERSONAL\"\n  STR_SAVE_PERSONAL_EQUIPMENT: \"Guardar equipo personal\"\n  STR_LOAD_PERSONAL_EQUIPMENT: \"Cargar equipo personal\"\n  STR_PERSONAL_EQUIPMENT_SAVED: \"Equipo personal guardado.\"\n  STR_TELL_ME_MORE: \"Dime más...\"\n  STR_REINFORCEMENTS_ALERT: \"¡Alerta de refuerzos!\"\n  STR_HIT_LOG_NEW_TURN: \"Nuevo turno\"\n  STR_FAILED_CQB_CHECK: \"¡El enemigo logró interrumpir tu ataque!\"\n  STR_NO_TRAJECTORY: \"¡Sin trayectoria viable!\"\n  STR_SKILL_NEEDS_ITEM: \"¡Esta habilidad necesita un objeto!\"\n  STR_HIT_LOG_SMALL_DAMAGE: \"impacto\"\n  STR_HIT_LOG_BIG_DAMAGE: \"IMPACTO\"\n  STR_HIT_LOG_REACTION_FIRE: \"Fuego de reacción...\"\n  STR_HIT_LOG: \"Registro de impactos\"\n  STR_LAZY_LOADING: \"Carga ligera\"\n  STR_LAZY_LOADING_DESC: \"Si está habilitado, los recursos gráficos se cargan bajo demanda. De lo contrario, todo se carga al inicio.\"\n  STR_VSYNC_FOR_OPENGL: \"VSync para OpenGL\"\n  STR_VSYNC_FOR_OPENGL_DESC: \"Desactívelo para obtener la máxima velocidad de movimiento oculto del enemigo y (opcionalmente) velocidad de movimiento del soldado. NO establezca el límite de FPS en 0. Solo se aplica al renderizado OpenGL.\"\n  STR_UPDATE_CHECK: \"Comprobación de actualización automática\"\n  STR_UPDATE_CHECK_DESC: \"Si está habilitado, OpenXcom buscará automáticamente actualizaciones y le dará la opción de actualizarse con un solo clic.\"\n  STR_AUTOSAVE_SLOTS: \"Ranuras de guardado automático\"\n  STR_AUTOSAVE_SLOTS_DESC: \"Número de espacios para guardado automático de Battlescape.\"\n  STR_OXCE_LINKS: \"Enlaces a 'Extended'\"\n  STR_OXCE_LINKS_DESC: \"Habilita menús/botones/enlaces adicionales para funciones de OXCE.\"\n  STR_UFO_LANDING_ALERT: \"Alerta de aterrizaje OVNI\"\n  STR_UFO_LANDING_ALERT_DESC: \"Si está habilitado, aparecerá un mensaje cada vez que aterrice un OVNI detectado.\"\n  STR_REMEMBER_DISABLED_CRAFT_WEAPONS: \"Recuerda las armas de nave deshabilitadas.\"\n  STR_REMEMBER_DISABLED_CRAFT_WEAPONS_DESC: \"Las armas de nave desactivadas durante un combate aéreo permanecerán desactivadas. Tampoco serán rearmados en la base.\"\n  STR_ALTERNATE_CRAFT_EQUIPMENT_MANAGEMENT: \"Gestión de equipo de naves alternativo\"\n  STR_ALTERNATE_CRAFT_EQUIPMENT_MANAGEMENT_DESC: \"Si está habilitado, mover soldados entre la base y la nave también moverá su equipo (si es posible).\"\n  STR_MANUALPROMOTIONS: \"Promociones manuales\"\n  STR_MANUALPROMOTIONS_DESC: \"Si está habilitado, los soldados pueden ser promovidos (o degradados) manualmente haciendo clic en el ícono de rango.\"\n  STR_WOUNDED_DEFEND_BASE_IF: \"Heridos defienden (si PS es superior al x%)\"\n  STR_WOUNDED_DEFEND_BASE_IF_DESC: \"Los soldados heridos también defienden la base, si su salud supera el umbral porcentual determinado.\"\n  STR_PLAY_BRIEFING_MUSIC_DURING_EQUIPMENT: \"Reproducir música de preparación por más tiempo\"\n  STR_PLAY_BRIEFING_MUSIC_DURING_EQUIPMENT_DESC: \"La música informativa seguirá sonando durante la fase de equipamiento hasta que se muestre Battlescape.\"\n  STR_NIGHT_VISION_COLOR: \"Seleccione el color de visión nocturna\"\n  STR_NIGHT_VISION_COLOR_DESC: \"Valores del 1 al 15, cada uno representa un color de tono diferente.\"\n  STR_AUTO_NIGHT_VISION_THRESHOLD: \"Umbral de visión nocturna automática\"\n  STR_AUTO_NIGHT_VISION_THRESHOLD_DESC: \"Si es más oscuro que este umbral, activa la visión nocturna automáticamente.\"\n  STR_AUTO_SELL: \"Gestor de venta automática\"\n  STR_AUTO_SELL_DESC: \"En la pantalla de venta del informe de batalla, cualquier tipo de artículo que hayas vendido en batallas anteriores se marcará automáticamente para su venta.\"\n  STR_AUTOMATICPROMOTIONS: \"Promociones automáticas\"\n  STR_AUTOMATICPROMOTIONS_DESC: \"Si está habilitado, los soldados son promovidos automáticamente después de una misión.\"\n  STR_OFF_CENTRE_SHOOTING: \"Tiro descentrado\"\n  STR_OFF_CENTRE_SHOOTING_DESC: \"Los soldados intentarán automáticamente ajustar ligeramente el ángulo de disparo en caso de que no haya una línea de fuego.\"\n  STR_GRAPHS_ZOOM_IN: \"Acercar (Gráficos)\"\n  STR_GRAPHS_ZOOM_OUT: \"Alejar (Gráficos)\"\n  STR_MARK_ALL_AS_SEEN: \"Marcar todo como visto\"\n  STR_SELL_ALL: \"Vender todo\"\n  STR_SELL_ALL_BUT_ONE: \"Vender todos menos uno\"\n  STR_TRANSFER_ALL: \"Transferir todo\"\n  STR_REMOVE_SOLDIERS_FROM_ALL_CRAFTS: \"Quitar soldados de todas las naves\"\n  STR_REMOVE_SOLDIERS_FROM_CRAFT: \"Quitar soldados de la nave\"\n  STR_REMOVE_EQUIPMENT_FROM_CRAFT: \"Quitar equipo de la nave\"\n  STR_REMOVE_ARMOR_FROM_ALL_CRAFTS: \"Quitar armaduras de todas las naves\"\n  STR_REMOVE_ARMOR_FROM_CRAFT: \"Quitar armaduras de la nave\"\n  STR_REMOVE_SOLDIERS_FROM_TRAINING: \"Quitar soldados del entrenamiento\"\n  STR_ADD_SOLDIERS_TO_TRAINING: \"Añadir soldados al entrenamiento\"\n  STR_INVENTORY_ARMOR: \"Cambiar armadura\"\n  STR_INVENTORY_AVATAR: \"Cambiar avatar\"\n  STR_DEBUG_KILL_ALL_ALIENS: \"DEBUG: Mata a todos los alienígenas\"\n  STR_PHYSICAL_TRAINING: \"Entrenamiento marcial\"\n  STR_REMAINING_TRAINING_FACILITY_CAPACITY: \"CAPACIDAD DE ENTRENAMIENTO RESTANTE> {ALT}{0}\"\n  STR_NO_DONE: \"HECHO\"\n  STR_NO_AMMO: \"¡SIN MUNICIÓN!\"\n  STR_START_FIRING: \"¡Fuego!\"\n  STR_SKIP_FIRING: \"Déjales entrar...\"\n  STR_ALIEN_MISSILES_HAVE_DAMAGED_OUR_BASE: \"Misiles alienígenas han dañado nuestra base {0}\"\n  STR_ALIEN_MISSILES_HAVE_DESTROYED_OUR_BASE: \"Misiles alienígenas han destruido nuestra base {0}\"\n  STR_STARTING_CONDITION_COMMANDER: \"Esta misión requiere la presencia del comandante.\"\n  STR_STARTING_CONDITION_CRAFT: \"Esta nave no es adecuada para esta misión.\"\n  STR_STARTING_CONDITION_CRAFT_ALLOWED: \"Esta nave no es adecuada para esta misión.{NEWLINE}{NEWLINE}Naves permitidas: {0}\"\n  STR_STARTING_CONDITION_CRAFT_FORBIDDEN: \"Esta nave no es adecuada para esta misión.{NEWLINE}{NEWLINE}Naves prohibidas: {0}\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE: \"Algunos soldados no pueden participar en esta misión.\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE_ALLOWED: \"Algunos soldados no pueden participar en esta misión.{NEWLINE}{NEWLINE}Tipos de soldados permitidos: {0}\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE_FORBIDDEN: \"Algunos soldados no pueden participar en esta misión.{NEWLINE}{NEWLINE}Tipos de soldados prohibidos: {0}\"\n  STR_STARTING_CONDITION_ITEM: \"Esta misión requiere de objetos específicos:{NEWLINE}{NEWLINE}{0}\"\n  STR_NOT_ENOUGH_FUEL_TO_REACH_TARGET: \"¡NO HAY SUFICIENTE COMBUSTIBLE!{SMALLLINE}El destino está demasiado lejos para el alcance de la nave.\"\n  STR_ASSIGN_PILOTS: \"Asignar pilotos...\"\n  STR_NOT_ENOUGH_PILOTS: \"¡No hay suficientes pilotos!{NEWLINE}Mínimo: {0}\"\n  STR_DAILY_PILOT_EXPERIENCE: \"Experiencia de piloto diaria\"\n  STR_UFO_SHIELD_HIT: \"¡IMPACTO EN LOS ESCUDOS!\"\n  STR_UFO_HIT_NO_DAMAGE: \"¡REBOTÓ EN EL CASCO!\"\n  STR_UFO_SHIELD_DOWN: \"¡ESCUDOS ENEMIGOS CAÍDOS!\"\n  STR_UFO_HIT_GLANCING: \"¡LE HA ROZADO!\"\n  STR_INTERCEPTOR_SHIELD_HIT: \"¡NUESTROS ESCUDOS ESTÁN AGUANTANDO!\"\n  STR_TRACTOR_BEAM_ENGAGED: \"¡EL RAYO TRACTOR ESTÁ ACTIVADO!\"\n  STR_TRACTOR_BEAM_DISENGAGED: \"DESACTIVANDO DEL RAYO TRACTOR\"\n  STR_SELF_DESTRUCT_ACTIVATED: \"¡AUTODESTRUCCIÓN ACTIVADA!\"\n  STR_SELF_DESTRUCT_CANCELLED: \"AUTODESTRUCCIÓN CANCELADA\"\n  STR_EXTENDED_LINKS: \"Enlaces\"\n  STR_AUTO_PATROL: \"AUTO PATRULLAR\"\n  STR_UFO_STARTED_HUNTING: \"{0} está de camino a interceptar a {1}\"\n  STR_CRAFT_IS_READY: \"{0} en {1} está listo.\"\n  STR_ECONOMY_WARNING: \"¡Los fondos {0} y los ingresos {1} son bajos y el mantenimiento {2} demasiado alto! Vende algo para evitar tener que pedir un crédito... faltan fondos: {3}\"\n  STR_RETURNING: \"REGRESANDO\"\n  STR_INTERCEPTING: \"INTERCEPTANDO\"\n  STR_ESCORTING: \"ACOMPAÑANDO\"\n  STR_EN_ROUTE: \"EN CAMINO\"\n  STR_PILOT_MISSING: \"PILOTO DESAPARECIDO\"\n  STR_PERFORMANCE_BONUS: \"Bonus de desempeño\"\n  STR_COUNTRY_HAS_CANCELLED_A_SECRET_PACT: \"{0} renunció al pacto con fuerzas alienígenas y se le ha permitido regresar al proyecto.\"\n  STR_COUNTRIES_HAVE_CANCELLED_A_SECRET_PACT: \"{0} han renunciado al pacto con fuerzas alienígenas y se les ha permitido regresar al proyecto.\"\n  STR_WE_CAN_NOW_RENT: \"Ya podemos alquilar\"\n  STR_REQUIRED_BASE_SERVICES: \"Servicios básicos requeridos: {0}\"\n  STR_WE_CAN_NOW_BUILD: \"Ya podemos construir\"\n  STR_WE_CAN_NOW_PURCHASE: \"Ya podemos comprar\"\n  STR_NOT_ENOUGH_LIVING_SPACE_AT_BASE: \"No hay suficiente espacio habitable para acomodar{NEWLINE}{0}{NEWLINE}en{NEWLINE}{1}\"\n  STR_DESPAWN_PENALTY: \"Penalización por desaparición> {0}\"\n  STR_TRAINING_FINISHED: \"Entrenamiento finalizado{NEWLINE}en {0}\"\n  STR_PSI_TRAINING_FINISHED: \"Entrenamiento Psiónico finalizado{NEWLINE}en {0}\"\n  STR_IGNORE_UC: \"IGNORAR\"\n  STR_UFO_TRACKER: \"Rastreador OVNI\"\n  STR_UPDATE: \"Actualizar\"\n  STR_LATEST_VERSION_INFO: \"Está utilizando la última versión de OpenXcom.\"\n  STR_MASTER_MOD_VERSION_REQUIRED_QUESTION: \"Este mod requiere el juego base v{0} para ejecutarse correctamente. ¿Habilitar este mod?\"\n  STR_VERSION_REQUIRED_QUESTION: \"Este mod requiere OXCE v{0} para ejecutarse correctamente. ¿Habilitar este mod?\"\n  STR_NOTES: \"Notas\"\n  STR_PATH_ENERGY_COST: \"Energia\"\n  STR_PATH_ENERGY_COST_DESC: \"Al hacer clic se muestra la energía que le quedará a su unidad después de moverse al destino.\"\n  STR_TEST_SCREEN: \"PROBAR PANTALLA\"\n  STR_PALETTE: \"Paleta:\"\n  STR_PREVIEW: \"Muestra\"\n  STR_TINY_BORDERLESS: \"Diminuto, sin bordes\"\n  STR_TINY_BORDER: \"Diminuto\"\n  STR_SMALL_LOW_CONTRAST: \"Pequeño\"\n  STR_SMALL_HIGH_CONTRAST: \"Pequeño, alto contraste\"\n  STR_BIG_LOW_CONTRAST: \"Grande\"\n  STR_BIG_HIGH_CONTRAST: \"Grande, alto contraste\"\n  STR_TEST_CASE: \"Caso de prueba:\"\n  STR_RUN: \"¡Ejecutar prueba seleccionada!\"\n  STR_TESTS_STARTING: \"Iniciando...\"\n  STR_TESTS_ERRORS_FOUND: \"Total de errores encontrados (puede haber duplicados): {0}\"\n  STR_TESTS_NO_ERRORS_FOUND: \"No se encontraron errores.\"\n  STR_TESTS_FINISHED: \"Finalizado.\"\n  STR_DETAILED_INFO_IN_LOG_FILE: \"La información detallada se ha guardado en openxcom.log\"\n  STR_DAMAGE_NONE: \"NINGUNO\"\n  STR_COCKPIT_CAPACITY: \"PILOTOS>{ALT}{0}{ALT}\"\n  STR_MAXIMUM_RANGE: \"RANGO MÁX>{ALT}{0}{ALT}\"\n  STR_MINIMUM_RANGE: \"RANGO MÍN>{ALT}{0}{ALT}\"\n  STR_MULTIPLE_DIFFERENT_BONUSES: \"múltiples bonificaciones en varias municiones compatibles\"\n  STR_ARTICLE: \"Artículo>{ALT} {0}\"\n  STR_COMPATIBLE_AMMO: \"Munición compatible:\"\n  STR_BUILT_IN_ITEMS: \"Objetos incorporados:\"\n  STR_CLIP_SIZE_UNLIMITED: \"ilimitado\"\n  STR_NAUTICAL_MILES: \"{0} millas náuticas\"\n  STR_SECONDS_LONG: \"{0} segundos\"\n  STR_RACE_BONUS: \"Bonificación de carrera\"\n  STR_FOR_DIFFICULTY: \"por dificultad: {0}\"\n  STR_NOT_AWARDED_YET: \"Aún no premiado\"\n"
  },
  {
    "path": "bin/common/Language/OXCE/et.yml",
    "content": "et:\n  STR_CANNOT_DISMANTLE_FACILITY_UPGRADING: \"EHITIST EI SAA LAMMUTADA!{SMALLLINE}Uuenduste ajal ei saa ehitist eemaldada.\"\n  STR_CANNOT_UPGRADE_FACILITY_WRONG_SIZE: \"SIIA EI SAA EHITADA!{SMALLLINE}Valitud rajatis peab täielikult katma olemasolevat ehitist.\"\n  STR_CANNOT_UPGRADE_FACILITY_WRONG_TYPE: \"SIIA EI SAA EHITADA!{SMALLLINE}Olemasolevat rajatist ei saa uuendada.\"\n  STR_ID: \"ID\"\n  STR_FIRST_LETTER: \"ESIMENE TÄHT\"\n  STR_SOLDIER_TYPE: \"SÕDURI TÜÜP\"\n  STR_MANA: \"MANA\"\n  STR_SAVE_UC: \"SALVESTA\"\n  STR_ALL: \"Kõik\"\n  STR_UNASSIGNED: \"Muu\"\n  STR_PILOTS: \"PILOODID\"\n  STR_SELECT_PILOT: \"Vali piloot\"\n  STR_PILOTS_FOR_CRAFT: \"Piloot(id) {0} jaoks\"\n  STR_PILOTS_REQUIRED: \"Piloote() vaja: {ALT}{0}\"\n  STR_ADD_PILOT: \"Lisa piloot\"\n  STR_COWARDLY: \"Ettevaatlik (-50%)\"\n  STR_NORMAL: \"Tavaline\"\n  STR_BOLD: \"Julge (+50%)\"\n  STR_VERY_BOLD: \"Väga julge (+100%)\"\n  STR_REFUND_VALUE: \"Müügisumma>{ALT}{0}\"\n  STR_PRODUCTION_OVERVIEW: \"TOOTMISE ÜLEVAADE\"\n  STR_KILL_SELECTED: \"Tapa\"\n  STR_SELL_SELECTED: \"Müü\"\n  STR_GO_TO_TRANSFERS: \"Vii üle...\"\n  STR_SHOW_ALL: \"Näita kõike\"\n  STR_SHOW_ONLY_NEW: \"Näita ainult uued\"\n  STR_FILTER_DEFAULT: \"Vaikimisi\"\n  STR_FILTER_DEFAULT_SUPPLIES_OK: \"Vaikimisi (laos olemas)\"\n  STR_FILTER_DEFAULT_NO_SUPPLIES: \"Vaikimisi (puudub laost)\"\n  STR_FILTER_FACILITY_REQUIRED: \"Rajatis puudub\"\n  STR_FILTER_HIDDEN: \"Peidus\"\n  STR_SORT_DEFAULT: \"Vaikimisi\"\n  STR_RANDOM_PRODUCTION_SUMMARY: \"Kokkuvõte\"\n  STR_SUMMARY: \"Kokkuvõte\"\n  STR_BONUSES_BUTTON: \"+\"\n  STR_KILLER_AND_WEAPON: \"{0}, {1}\"\n  STR_QS_THREE_LETTERS_A: \"Kirjuta vähemalt kolm tähte\"\n  STR_QS_THREE_LETTERS_B: \"kiirotsingu lahtrisse..\"\n  STR_M_FLAG: \" [m]\"\n  STR_F_FLAG: \" [f]\"\n  STR_I_FLAG: \" [i]\"\n  STR_TECH_TREE_VIEWER: \"Tehnopuu vaatleja\"\n  STR_SELECT_TOPIC: \"Vali teema\"\n  STR_NOT_ENOUGH_MORALE: \"Liiga väike moraal!\"\n  STR_NOT_ENOUGH_HEALTH: \"Liiga vähe elusid!\"\n  STR_NOT_ENOUGH_MANA: \"Liiga vähe mana!\"\n  STR_TARGET_ENEMY: \"; Sihtmärk = VAENLANE\"\n  STR_TARGET_NEUTRAL: \"; Sihtmärk = NEUTRAALNE\"\n  STR_TARGET_FRIEND: \"; Sihtmärk = OMA\"\n  STR_TARGET_YOURSELF: \"; SIHTMÄRK = ISE\"\n  STR_TARGET_ON_THE_GROUND: \"(maas)\"\n  STR_STARTING_CONDITION_ARMORS_FORBIDDEN: \"Selle missiooni jaoks on vaja erivarustust.{NEWLINE}{NEWLINE}Keelatud turvised: {0}\"\n  STR_STARTING_CONDITION_ARMORS_ALLOWED: \"Selle missiooni jaoks on vaja erivarustust.{NEWLINE}{NEWLINE}Lubatud turvised: {0}\"\n  STR_MISSION_OVER: \"Missioon õnnestus\"\n  STR_UNITS_WITH_FATAL_WOUNDS:\n    one: \"{N} meist on ikka veel surmavalt haavatud\"\n    other: \"{N} meist on ikka veel surmavalt haavatud\"\n  STR_END_MISSION_QUESTION: \"Lõpeta missioon?\"\n  STR_LOOT: \"SAAK\"\n  STR_SELL: \"MÜÜ\"\n  STR_LIVE_ALIENS_SURRENDERED: \"ALISTUNUD VAENLASED\"\n  STR_MISSION_ABORTED: \"MISSIOON KATKESTATUD\"\n  STR_BOUNTY: \"PEARAHA\"\n  STR_MANA_ABBREVIATION: \"MAN\"\n  STR_CANNOT_PLACE_ITEM_INTO_THIS_SECTION: \"Antud asja ei ole lubatud siia panna.{NEWLINE}. Ära küsi miks!\"\n  STR_ONE_HAND_MUST_BE_EMPTY: \"Vähemalt üks käsi peab tühi olema!\"\n  STR_LOAD_EQUIPMENT_TEMPLATE: \"Loadi varustuse mall.\"\n  STR_SAVE_EQUIPMENT_TEMPLATE: \"Salvesta varustuse mall.\"\n  STR_MELEE_SHORT: \"Lähivõitlus>{ALT}{0}\"\n  STR_HIT_LOG_NEW_BULLET: \"=> \"\n  STR_HIT_LOG_NO_DAMAGE: \"0\"\n  STR_BUTTON_10: \"10\"\n  STR_UFO_LANDING_ALERT: \"UFO maandumise hoiatus\"\n  STR_UFO_LANDING_ALERT_DESC: \"Kui aktiveeritud siis iga kord kui avastatud UFO maandub ilmub ekraanile kiri.\"\n  STR_NO_WOUNDED: \"-\"\n  STR_NO_QUEUED: \"+\"\n  STR_NO_DONE: \"TEHTUD\"\n  STR_START_FIRING: \"Tuld!\"\n  STR_SKIP_FIRING: \"Lase nad sisse...\"\n  STR_ALIEN_MISSILES_HAVE_DAMAGED_OUR_BASE: \"Tulnukate raketid on meie baasi {0} kahjustanud\"\n  STR_ALIEN_MISSILES_HAVE_DESTROYED_OUR_BASE: \"Tulnukate raketid on meie baasi {0} hävitanud\"\n  STR_STARTING_CONDITION_CRAFT: \"See sõiduk on antud missiooniks sobimatu\"\n  STR_STARTING_CONDITION_CRAFT_ALLOWED: \"See sõiduk on antud missiooniks sobimatu.{NEWLINE}{NEWLINE}Lubatud sõidukid: {0}\"\n  STR_STARTING_CONDITION_CRAFT_FORBIDDEN: \"See sõiduk on antud missiooniks sobimatu.{NEWLINE}{NEWLINE}Keelatud sõidukid: {0}\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE: \"Osad sõdurid ei saa sellel missioonil osaleda.\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE_ALLOWED: \"Mõned sõdurid ei saa antud missioonil osaleda.{NEWLINE}{NEWLINE}Lubatud sõdurite tüübid:{0}\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE_FORBIDDEN: \"Mõned sõdurid ei saa antud missioonil osaleda.{NEWLINE}{NEWLINE}keelatud sõdurite tüübid:{0}\"\n  STR_STARTING_CONDITION_ITEM: \"See missioon vajab kindlat varustust:{NEWLINE}{NEWLINE}{0}\"\n  STR_ASSIGN_PILOTS: \"Lisa piloodid...\"\n  STR_NOT_ENOUGH_PILOTS: \"Pole piisavalt piloote!{NEWLINE}Miinimum: {0}\"\n  STR_DAILY_PILOT_EXPERIENCE: \"Päevane pilootide kulu.\"\n  STR_UFO_SHIELD_HIT: \"TABAMUS KILPI!\"\n  STR_SLACKING_INDICATOR: \"{0}:{1}\"\n  STR_TRAINING_INDICATOR: \"{0}:{1}\"\n  STR_RETURNING: \"NAASEN\"\n  STR_INTERCEPTING: \"LÄHENEN\"\n  STR_ESCORTING: \"ESKORDIN\"\n  STR_EN_ROUTE: \"TEEL\"\n  STR_PILOT_MISSING: \"PILOOT KADUNUD\"\n  STR_DAY_SHORT: \"{0}d\"\n  STR_HOUR_SHORT: \"{0}t\"\n  STR_WE_CAN_NOW_RENT: \"Saame nüüd rentida\"\n  STR_REQUIRED_BASE_SERVICES: \"Vajalikud baasi teenused: {0}\"\n  STR_WE_CAN_NOW_BUILD: \"Saame nüüd ehitada\"\n  STR_WE_CAN_NOW_PURCHASE: \"Saame nüüd osta\"\n  STR_NOT_ENOUGH_LIVING_SPACE_AT_BASE: \"Pole piisavalt eluruume, et majutada {NEWLINE}{0}{NEWLINE} baasis nimega{NEWLINE}{1}\"\n  STR_INFO: \"INFO\"\n  STR_UFO_TRACKER: \"UFO jälitaja\"\n  STR_UPDATE: \"Uuenda\"\n  STR_LATEST_VERSION_INFO: \"Kasutad uusimat OpenXcomi versiooni.\"\n  STR_RANK_NONE: \"-\"\n  STR_INFO_UFOPEDIA: \"INFO\"\n  STR_DAMAGE_10: \"10\"\n  STR_DAMAGE_11: \"11\"\n  STR_DAMAGE_12: \"12\"\n  STR_DAMAGE_13: \"13\"\n  STR_DAMAGE_14: \"14\"\n  STR_DAMAGE_15: \"15\"\n  STR_DAMAGE_16: \"16\"\n  STR_DAMAGE_17: \"17\"\n  STR_DAMAGE_18: \"18\"\n  STR_DAMAGE_19: \"19\"\n  STR_NAUTICAL_MILES: \"{0} meremiili\"\n  STR_KILOMETERS_PER_HOUR: \"{0} km/h\"\n  STR_SECONDS_LONG: \"{0} sekundit\"\n  STR_RACE_BONUS: \"Võidusõidu boonus\"\n"
  },
  {
    "path": "bin/common/Language/OXCE/fi.yml",
    "content": "fi:\n  STR_CANNOT_DISMANTLE_FACILITY_UPGRADING: \"LAITOSTA EI VOI PURKAA!{SMALLLINE}Laitosta ei voi poistaa päivitystyön aikana.\"\n  STR_CANNOT_UPGRADE_FACILITY_ALREADY_UPGRADING: \"TÄHÄN EI VOI RAKENTAA!{SMALLLINE}Nykyisen laitoksen päälle ollaan jo rakentamassa.\"\n  STR_CANNOT_UPGRADE_FACILITY_WRONG_SIZE: \"TÄHÄN EI VOI RAKENTAA!{SMALLLINE}Valitun laitoksen tulee kattaa nykyinen laitos kokonaan.\"\n  STR_CANNOT_UPGRADE_FACILITY_WRONG_TYPE: \"TÄHÄN EI VOI RAKENTAA!{SMALLLINE}Nykyistä laitosta ei voi päivittää valitulla laitoksella.\"\n  STR_CANNOT_UPGRADE_FACILITY_DISALLOWED: \"TÄHÄN EI VOI RAKENTAA!{SMALLLINE}Nykyisen laitoksen päälle ei voi rakentaa.\"\n  STR_CANNOT_BUILD_QUEUE_OFF: \"TÄHÄN EI VOI RAKENTAA!{SMALLLINE}Viereisten laitosten rakennustöiden on ensin valmistuttava.\"\n  STR_FACILITY_FORBIDDEN_BY_OTHER: \"TÄHÄN EI VOI RAKENTAA!{SMALLLINE}Jokin olemassa oleva laitos estää rakentamasta tätä laitosta.\"\n  STR_FACILITY_OTHER_FORBIDDEN_BY_THIS: \"TÄHÄN EI VOI RAKENTAA!{SMALLLINE}Laitos kieltäisi jonkin olemassa olevan laitoksen toiminnan.\"\n  STR_NOT_ENOUGH_ITEMS: \"EI RIITTÄVÄSTI RAAKA-AINEITA!{SMALLLINE}Tarvitsemme lisää raaka-aineita tämän laitoksen rakentamiseksi.{NEWLINE}Puutteet> {0}: {1}\"\n  STR_ID: \"TUNNISTE\"\n  STR_FIRST_LETTER: \"ENSIMMÄINEN KIRJAIN\"\n  STR_SOLDIER_TYPE: \"SOTILASTYYPPI\"\n  STR_IDLE_DAYS: \"HUKKAPÄIVÄT\"\n  STR_MANA: \"MANA\"\n  STR_MANA_POOL: \"MANAVARANTO\"\n  STR_MANA_MISSING: \"MANAA PUUTTUU\"\n  STR_LOAD_CRAFT_LOADOUT_TEMPLATE: \"Lastaa alus mallivarustuksella\"\n  STR_EMPTY_SLOT_N: \"Tyhjä paikka {0}\"\n  STR_UNNAMED_SLOT_N: \"Nimeämätön paikka {0}\"\n  STR_ADD_ON_TOP: \"Lisää ylimmäiseksi\"\n  STR_SAVE_CRAFT_LOADOUT_TEMPLATE: \"Määritä mallivarustukseksi\"\n  STR_SAVE_UC: \"TALLENNA\"\n  STR_ALL: \"Kaikki\"\n  STR_EQUIPPED: \"Varustettu\"\n  STR_NOT_EQUIPPED: \"Varustamaton\"\n  STR_UNASSIGNED: \"Muu\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED_BY_SIZE: \"EI ENEMPÄÄ VARUSTEITA SALLITTU RUUMAAN!{SMALLLINE}Enimmäisvarastotila: {0}\"\n  STR_PILOTS: \"LENTÄJÄT\"\n  STR_SHIELD: \"SUOJA>{ALT}{0}\"\n  STR_CRAFT_SKIN_ID: \"[{0}]\"\n  STR_SELECT_PILOT: \"Valitse lentäjä\"\n  STR_PILOTS_FOR_CRAFT: \"Lentäjä(t) alukselle {0}\"\n  STR_PILOTS_REQUIRED: \"Tarvittava määrä lentäjiä: {ALT}{0}\"\n  STR_ADD_PILOT: \"Lisää lentäjä\"\n  STR_REMOVE_ALL_PILOTS: \"Poista kaikki lentäjät\"\n  STR_ACCURACY_BONUS: \"Tarkkuusvaikutus:\"\n  STR_DODGE_BONUS: \"Väistökykyvaikutus:\"\n  STR_APPROACH_SPEED: \"Lähestymisnopeus:\"\n  STR_COWARDLY: \"Pelokas (-50%)\"\n  STR_NORMAL: \"Tavallinen\"\n  STR_BOLD: \"Rohkea (+50%)\"\n  STR_VERY_BOLD: \"Erittäin rohkea (+100%)\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW: \"Esikatselu\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_SAVED: \"Esikatselu *\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_BRIEFING: \"Tällä toiminnolla voit esikatsella ja muokata yksiköittesi sijoittumista taistelun alussa. Liikkumista ei ole rajoitettu. Pidä pohjassa Alt-näppäintä korostaaksesi kelvolliset yksiköiden sijoituspaikat. Napsauttamalla \\\"Keskeytä tehtävä\\\"-kuvaketta tallennat räätälöidyn sijoittelun. Napsauta \\\"Lopeta vuoro\\\"-kuvaketta poistuaksesi esikatselusta.{NEWLINE}Huomaa, että uusien sotilaiden tai kulkuneuvojen lisääminen alukselle automaattisesti poistaa tallennetun räätälöidyn sijoittelun. Räätälöidyn sijoittelun olemassaolon huomaa \\\"Esikatselu\\\"-painikkeen tähtimerkistä.\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_BRIEFING_DUMMY: \"Tällä toiminnolla voit esikatsella ja muokata tämän alustyypin sijoittelutaulua. Kaikki muutokset otetaan käyttöön sekä kaikilla nykyisillä aluksillasi että millä tahansa aluksella, jonka ostat tai valmistat myöhemmin kampanjan aikana. Aloitat suurimmalla määrällä sotilaita. Kukin sotilas edustaa yhtä riviä sijoittelutaululla. Sotilaiden nimiä vastaa omat rivinumeronsa. Tehdäksesi tilaa 2x2-yksikölle aseta neljä sotilasta 2x2-neliöön. Jos tilaa ei ole tehty, 2x2-yksikkö puuttuu oikeasta taistelusta.\"\n  STR_BASE_DEFENSE_BRIEFING_PREVIEW: \"Voit esikatsella tukikohtaasi tällä toiminnolla.{NEWLINE}Pidä hauskaa!{NEWLINE}{NEWLINE}Napsauta \\\"Lopeta vuoro\\\"-kuvaketta poistuaksesi esikatselusta.\"\n  STR_REFUND_VALUE: \"Myyntiarvo> {ALT}{0}\"\n  STR_PRODUCTION_OVERVIEW: \"TUOTANTOYHTEENVETO\"\n  STR_RESEARCH_OVERVIEW: \"TUTKIMUSYHTEENVETO\"\n  STR_PRISONER_OVERVIEW: \"VANKIYHTEENVETO\"\n  STR_PRISONER: \"VANKI\"\n  STR_PRISONER_AMOUNT: \"MÄÄRÄ\"\n  STR_PRISONER_INTERROGATED: \"KUULUSTELTU\"\n  STR_TOTAL_IN_PRISON: \"Tilankäyttö>{ALT}{0}\"\n  STR_TOTAL_INTERROGATED: \"Kuulusteltu>{ALT}{0}\"\n  STR_PRISON_TYPE: \"Muukalaisten vankilaitos\"\n  STR_KILL_SELECTED: \"Tapa\"\n  STR_SELL_SELECTED: \"Myy\"\n  STR_GO_TO_TRANSFERS: \"Siirrä...\"\n  STR_PRISON_CLEANUP: \"Vankilaitoksen tyhjennys\"\n  STR_TOPIC: \"Aihe>{ALT} {0}\"\n  STR_SHOW_ALL: \"Näytä kaikki\"\n  STR_NO_DEPENDENCIES: \"Ei riippuvuussuhteita.\"\n  STR_DIRECT_DEPENDENCIES: \"Suoria riippuvuussuhteita\"\n  STR_LEVEL_2_DEPENDENCIES: \"2. asteen riippuvuussuhteita\"\n  STR_LEVEL_3_DEPENDENCIES: \"3. asteen riippuvuussuhteita\"\n  STR_LEVEL_4_DEPENDENCIES: \"4. asteen riippuvuussuhteita\"\n  STR_MORE_DEPENDENCIES: \"Vielä syvempiä riippuvuussuhteita...\"\n  STR_END_OF_SEARCH: \"Haun loppu.\"\n  STR_REFUND_PRODUCTION: \"PALAUTUS!\"\n  STR_HOURS_PER_UNIT: \"TUNTIA / YKS.>{ALT}{0}\"\n  STR_PERSON_JOINING: \"Henkilö liittymässä\"\n  STR_RANDOM_PRODUCTION_DISCLAIMER: \"Sattumanvarainen tuotanto!\"\n  STR_OTHER_EMPLOYEES: \"Muu henkilöstö & varasto\"\n  STR_SHOW_ONLY_NEW: \"Näytä vain uudet\"\n  STR_FILTER_DEFAULT: \"Oletus\"\n  STR_FILTER_DEFAULT_SUPPLIES_OK: \"Oletus (tarvikkeet OK)\"\n  STR_FILTER_DEFAULT_NO_SUPPLIES: \"Oletus (ei tarvikkeita)\"\n  STR_FILTER_FACILITY_REQUIRED: \"Laitos puuttuu\"\n  STR_FILTER_HIDDEN: \"Piilotettu\"\n  STR_FILTER_EQUIPPED: \"Varustettu\"\n  STR_FILTER_MISSING: \"Puuttuu\"\n  STR_SORT_DEFAULT: \"Oletus\"\n  STR_SORT_BY_COST: \"Hinnan mukaan\"\n  STR_SORT_BY_NAME: \"Nimen mukaan\"\n  STR_RANDOM_PRODUCTION_SUMMARY: \"Yhteenveto\"\n  STR_NOT_ENOUGH_PRISON_SPACE: \"EI RIITTÄVÄSTI VANKITILAA!{SMALLLINE}Rakenna uusia muukalaisten vankilaitoksia tai siirrä muukalaisia toisiin tukikohtiin.\"\n  STR_MONTHLY_ITEM_PURCHASE_LIMIT_EXCEEDED: \"KUUKAUSIKIINTIÖ YLITETTY!{SMALLLINE}Tavaraa on saatavilla lisää ensi kuussa.\"\n  STR_MONTHLY_CRAFT_PURCHASE_LIMIT_EXCEEDED: \"KUUKAUSIKIINTIÖ YLITETTY!{SMALLLINE}Aluksia on saatavilla lisää ensi kuussa.\"\n  STR_MONTHLY_SOLDIER_HIRING_LIMIT_EXCEEDED: \"KUUKAUSIKIINTIÖ YLITETTY!{SMALLLINE}Värvättäviä on saatavilla lisää ensi kuussa.\"\n  STR_NOT_ENOUGH_CRAFT_SPACE: \"Aluksessa ei ole riittävästi tilaa!\"\n  STR_SELECT_AVATAR_FOR: \"VALITSE ULKONÄKÖ HENKILÖLLE{NEWLINE}{0}\"\n  STR_SOLDIER_BONUSES_FOR: \"KEHITYSPISTEITÄ SOTILAALLE{NEWLINE}{0}\"\n  STR_SUMMARY: \"Yhteenveto\"\n  STR_MANA_RECOVERY: \"MANAN PALAUTUMINEN> {ALT}{0}\"\n  STR_HEALTH_RECOVERY: \"TERVEYDEN PALAUTUMINEN> {ALT}{0}\"\n  STR_BONUSES_BUTTON: \"+\"\n  STR_PROMOTE_SOLDIER: \"YLENNÄ/ALENNA{NEWLINE}{0} {1}\"\n  STR_RANK_HEADER: \"SOTILASARVO\"\n  STR_OPENINGS_HEADER: \"AVOIMET PAIKAT\"\n  STR_KILLER_AND_WEAPON: \"{0}, {1}\"\n  STR_TRAINING: \"Koulutus\"\n  STR_SOLDIER_INFO: \"Sotilastiedot\"\n  STR_TRANSFER_TIME: \"Siirtoaika>{ALT}{0}\"\n  STR_RECOVERY_TIME: \"Toipilasaika>{ALT}{0}\"\n  STR_CURRENT_STATS: \"Ominaisuudet\"\n  STR_CHANGES: \"Muutokset\"\n  STR_CHANGES_MIN: \"Muutokset (min)\"\n  STR_CHANGES_MAX: \"Muutokset (max)\"\n  STR_BONUS_STATS: \"Kehityspisteet\"\n  STR_TRANSFORMATIONS_OVERVIEW: \"Muunnosten yleiskatsaus\"\n  STR_PROJECT_NAME: \"PROJEKTIN NIMI\"\n  STR_AVAILABLE_MATERIALS: \"KÄYTETTÄVÄT RAAKA-AINEET\"\n  STR_ELIGIBLE_SOLDIERS: \"SOVELIAAT SOTILAAT\"\n  STR_SHOW_ONLY_ELIGIBLE: \"Näytä vain soveliaat\"\n  STR_ALL_SOLDIER_TYPES: \"Kaikenlaiset sotilaat\"\n  STR_ALL_SOLDIERS: \"Kaikki sotilaat\"\n  STR_HEALTHY_SOLDIERS: \"Terveet sotilaat\"\n  STR_WOUNDED_SOLDIERS: \"Haavoittuneet sotilaat\"\n  STR_DEAD_SOLDIERS: \"Kuolleet sotilaat\"\n  STR_GRAND_TOTAL: \"Kokonaismäärä\"\n  STR_AVAILABLE_TOPICS: \"VALITTAVAT AIHEET\"\n  STR_QS_THREE_LETTERS_A: \"Syötä vähintään kolme kirjainta\"\n  STR_QS_THREE_LETTERS_B: \"pikahakuruutuun...\"\n  STR_M_FLAG: \" [tuotanto]\"\n  STR_F_FLAG: \" [laitos]\"\n  STR_I_FLAG: \" [esine]\"\n  STR_C_FLAG: \" [c]\"\n  STR_THIS_FEATURE_IS_DISABLED_1: \"Tämä ominaisuus on pois käytöstä.\"\n  STR_THIS_FEATURE_IS_DISABLED_2: \"Tämä ominaisuus on pois käytöstä.\"\n  STR_THIS_FEATURE_IS_DISABLED_3: \"Tämä ominaisuus on pois käytöstä.\"\n  STR_THIS_FEATURE_IS_DISABLED_4: \"Tämä ominaisuus on pois käytöstä.\"\n  STR_THIS_FEATURE_IS_DISABLED_5: \"Tämä ominaisuus on pois käytöstä.\"\n  STR_TECH_TREE_VIEWER: \"Tutkimuspuu\"\n  STR_SELECT_TOPIC: \"Valitse aihe\"\n  STR_RESEARCH_PROGRESS: \"Edistyminen>{ALT} {0}%\"\n  STR_ITEM_DESTROYED: \"Tuhoutuva tavara:\"\n  STR_ITEM_REQUIRED: \"Tarvittava tavara:\"\n  STR_SERVICES_REQUIRED: \"Tarvittavat palvelut:\"\n  STR_SERVICES_PROVIDED: \"Annettavat palvelut:\"\n  STR_SERVICES_FORBIDDEN: \"Kiellettävät palvelut:\"\n  STR_REQUIRES: \"Vaadittavat:\"\n  STR_DEPENDS_ON: \"Riippuvuudet:\"\n  STR_UNLOCKED_BY: \"Lukituksen avaavat:\"\n  STR_DISABLED_BY: \"Käytöstä poistavat:\"\n  STR_REENABLED_BY: \"Käyttöön palauttavat:\"\n  STR_GET_FOR_FREE_FROM: \"Ilmaiseksi antavat:\"\n  STR_IS_LOOKUP_OF: \"Haun kohteena seuraaville:\"\n  STR_LOOKUP: \"Hakee seuraavia:\"\n  STR_SPAWNED_ITEMS: \"Synnytetyt esineet:\"\n  STR_SPAWNED_EVENT: \"Syntynyt tapahtuma:\"\n  STR_REQUIRED_BY: \"Vaatijat:\"\n  STR_REQUIRED_BY_TRANSFORMATIONS: \"Seuraavien muunnosten edellyttämä:\"\n  STR_LEADS_TO: \"Johdokset:\"\n  STR_UNLOCKS: \"Avaukset:\"\n  STR_DISABLES: \"Käytöstä poistettavat:\"\n  STR_REENABLES: \"Palauttaa käyttöön:\"\n  STR_GIVES_ONE_FOR_FREE_SEQ: \"Ilmaiseksi annettavat asiat (peräkkäiset):\"\n  STR_GIVES_ONE_FOR_FREE: \"Ilmaiseksi annettavat asiat:\"\n  STR_RESEARCH_REQUIRED: \"Tarvittava tutkimus:\"\n  STR_RESEARCH_REQUIRED_USE: \"Tarvittava tutkimus (käyttö):\"\n  STR_RESEARCH_REQUIRED_BUY: \"Tarvittava tutkimus (osto):\"\n  STR_SERVICES_REQUIRED_BUY: \"Tarvittavat palvelut (osto):\"\n  STR_PRODUCED_BY: \"Tuottavat:\"\n  STR_SPAWNED_BY: \"Synnyttävät:\"\n  STR_MATERIALS_REQUIRED: \"Tarvittavat raaka-aineet:\"\n  STR_TTV_COST_PER_UNIT: \"Yksikköhinta:\"\n  STR_TTV_ENGINEER_HOURS: \"Teknikkotyötunteja:\"\n  STR_TTV_WORK_SPACE_REQUIRED: \"Tarvittava työpajatila:\"\n  STR_ITEMS_PRODUCED: \"Tuotettavat tavarat:\"\n  STR_PERSON_RECRUITED: \"Värvättävä henkilö:\"\n  STR_UNLOCKS_ARCS: \"Avautuvat juonihaarat:\"\n  STR_DISABLES_ARCS: \"Sulkeutuvat juonihaarat:\"\n  STR_UNLOCKS_MISSIONS: \"Avautuvat tehtävät:\"\n  STR_DISABLES_MISSIONS: \"Poistuvat tehtävät:\"\n  STR_UNLOCKS_EVENTS: \"Avautuvat tapahtumat:\"\n  STR_DISABLES_EVENTS: \"Sulkeutuvat tapahtumat:\"\n  STR_AFFECTS_GAME_PROGRESSION: \"Vaikuttaa pelin etenemiseen!\"\n  STR_ITEMS_AT_DESTINATION: \"Tavaraa määränpäässä\"\n  STR_PRISONERS: \"Vangit\"\n  STR_ARMORS: \"Panssarit\"\n  STR_CRAFT_DEPLOYMENT_QUESTION: \"Tallenna aluksen sijoittelu?\"\n  STR_MUST_USE_BOTH_HANDS: \"Molempia käsiä tarvitaan tätä varten!\"\n  STR_NOT_ENOUGH_MORALE: \"Ei riittävästi taistelutahtoa!\"\n  STR_NOT_ENOUGH_HEALTH: \"Ei riittävästi terveyttä!\"\n  STR_NOT_ENOUGH_MANA: \"Ei riittävästi manaa!\"\n  STR_NOT_ENOUGH_STUN: \"Taintumusaste liian korkea!\"\n  STR_LINE_OF_SIGHT_REQUIRED: \"Näköyhteys vaaditaan.\"\n  STR_CENTER_ON_WOUNDED_FRIEND: \"Keskitä haavoittuneeseen toveriin\"\n  STR_CENTER_ON_DIZZY_FRIEND: \"Keskitä pyörryksissä olevaan toveriin\"\n  STR_BUG_HUNT_ACTIVATED: \"Tuholaistorjuntatila aktivoitu: Viholliset näkyvät minikartalla!\"\n  STR_TARGET_ENEMY: \"; kohde = VIHOLLINEN\"\n  STR_TARGET_NEUTRAL: \"; kohde = PUOLUEETON\"\n  STR_TARGET_FRIEND: \"; kohde = TOVERI\"\n  STR_TARGET_YOURSELF: \"; kohde = SINÄ\"\n  STR_TARGET_ON_THE_GROUND: \"(maassa)\"\n  STR_USE_SPECIAL_ITEM: \"Käytä erityisesinettä\"\n  STR_NO_EXPERIENCE_YET: \"Ei vielä kokemusta:\"\n  STR_OPERATION_UC: \"TEHTÄVÄ> {0}\"\n  STR_WHAT_CAN_I_WEAR: \"Mitä voin pukea?\"\n  STR_STARTING_CONDITION_ARMORS_FORBIDDEN: \"Tehtävä vaatii erityisvarustusta.{NEWLINE}{NEWLINE}Kielletyt panssarityypit: {0}\"\n  STR_STARTING_CONDITION_ARMORS_ALLOWED: \"Tehtävä vaatii erityisvarustusta.{NEWLINE}{NEWLINE}Sallitut panssarityypit: {0}\"\n  STR_MISSION_OVER: \"Tehtävä suoritettu.\"\n  STR_UNITS_WITH_FATAL_WOUNDS:\n    one: \"{N} meistä on vielä vakavasti haavoittunut\"\n    other: \"{N} meistä on vielä vakavasti haavoittunut\"\n  STR_END_MISSION_QUESTION: \"Lopetetaanko tehtävä?\"\n  STR_LOOT: \"SAALIS\"\n  STR_SELL: \"MYY\"\n  STR_LIVE_ALIENS_SURRENDERED: \"ANTAUTUNEET VIHOLLISET\"\n  STR_MISSION_ABORTED: \"TEHTÄVÄ KESKEYTETTY\"\n  STR_VIPS_SAVED: \"PELASTETUT ARVOHENKILÖT\"\n  STR_VIPS_LOST: \"MENETETYT ARVOHENKILÖT\"\n  STR_BOUNTY: \"PALKKIO\"\n  STR_MANA_ABBREVIATION: \"MAN\"\n  STR_CANNOT_PLACE_ITEM_INTO_THIS_SECTION: \"Esinettä ei saa laittaa siihen!{NEWLINE}Älä kysy syytä!\"\n  STR_ONE_HAND_MUST_BE_EMPTY: \"Vähintään yhden käden on oltava tyhjä!\"\n  STR_LOAD_EQUIPMENT_TEMPLATE: \"Lataa varustusmalli\"\n  STR_SAVE_EQUIPMENT_TEMPLATE: \"Tallenna varustusmalli\"\n  STR_FIRING_SHORT: \"Tuli>{ALT}{0}\"\n  STR_THROWING_SHORT: \"Heitto>{ALT}{0}\"\n  STR_MELEE_SHORT: \"Lähi>{ALT}{0}\"\n  STR_PERSONAL_EQUIPMENT: \"HENKILÖKOHTAINEN VARUSTUS\"\n  STR_SAVE_PERSONAL_EQUIPMENT: \"Tallenna henkilökohtainen varustus\"\n  STR_LOAD_PERSONAL_EQUIPMENT: \"Lataa henkilökohtainen varustus\"\n  STR_PERSONAL_EQUIPMENT_SAVED: \"Henkilökohtainen varustus tallennettu.\"\n  STR_TELL_ME_MORE: \"Kerro lisää...\"\n  STR_REINFORCEMENTS_ALERT: \"Vahvistushälytys!\"\n  STR_HIT_LOG_NEW_TURN: \"Uusi vuoro\"\n  STR_FAILED_CQB_CHECK: \"Vihollinen onnistui keskeyttämään hyökkäyksesi!\"\n  STR_NO_TRAJECTORY: \"Ei mahdollinen lentorata!\"\n  STR_HIT_LOG_NEW_BULLET: \"=> \"\n  STR_MANA_SHORT: \"MA>{ALT}{0}\"\n  STR_SKILL_NEEDS_ITEM: \"Tämä kyky tarvitsee esineen!\"\n  STR_HIT_LOG_NO_DAMAGE: \"0 \"\n  STR_HIT_LOG_SMALL_DAMAGE: \"osuma\"\n  STR_HIT_LOG_BIG_DAMAGE: \"OSUMA\"\n  STR_HIT_LOG_REACTION_FIRE: \"Reaktiotuli...\"\n  STR_HIT_LOG: \"Osumaloki\"\n  STR_BUTTON_10: \"10\"\n  STR_LAZY_LOADING: \"Laiska lataaminen\"\n  STR_LAZY_LOADING_DESC: \"Päälle kytkettynä grafiikkaresurssit ladataan tarvittaessa. Muutoin kaikki ladataan käynnistyksen yhteydessä.\"\n  STR_VSYNC_FOR_OPENGL: \"OpenGL-pystytahdistus (VSync)\"\n  STR_VSYNC_FOR_OPENGL_DESC: \"Kytke pois päältä saavuttaaksesi nopeimman vihollisen ja (vaihtoehtoisesti) sotilaiden liikkeen. ÄLÄ rajoita kuvataajuutta nollaan. Koskee ainoastaan OpenGL-hahmonnusta.\"\n  STR_UPDATE_CHECK: \"Automaattiset päivitystarkistukset\"\n  STR_UPDATE_CHECK_DESC: \"Päälle kytkettynä OpenXcom tarkistaa automaattisesti päivitykset ja antaa sinulle vaihtoehdon päivittää ohjelman yhdellä napin painalluksella.\"\n  STR_AUTOSAVE_SLOTS: \"Automaattitallennuspaikat\"\n  STR_AUTOSAVE_SLOTS_DESC: \"Taistelukentän automaattitallennuspaikkojen määrä\"\n  STR_AUTO_SAVE_BATTLESCAPE_SLOT_WITH_NUMBER: \"<TAISTELUKENTÄN AUTOMAATTITALLENNUS> {0}\"\n  STR_OXCE_LINKS: \"Laajennetut linkit\"\n  STR_OXCE_LINKS_DESC: \"Ottaa käyttöön lisävalikoita/-painikkeita/-linkkejä OXCEn toiminnallisuuksia varten.\"\n  STR_UFO_LANDING_ALERT: \"Ufon laskeutumisvaroitus\"\n  STR_UFO_LANDING_ALERT_DESC: \"Päälle kytkettynä ponnahdusviesti ilmestyy aina, kun havaittu ufo laskeutuu.\"\n  STR_REMEMBER_DISABLED_CRAFT_WEAPONS: \"Muista pois päältä kytketyt alusten aseet\"\n  STR_REMEMBER_DISABLED_CRAFT_WEAPONS_DESC: \"Ilmataistelun aikana pois päältä kytketyt aseet pysyvät pois päältä. Niitä ei myöskään aseisteta tukikohdassa.\"\n  STR_ALTERNATE_CRAFT_EQUIPMENT_MANAGEMENT: \"Vaihtoehtoinen alusten varustelun hallinta\"\n  STR_ALTERNATE_CRAFT_EQUIPMENT_MANAGEMENT_DESC: \"Päälle kytkettynä sotilaiden siirtäminen tukikohdan ja aluksen välillä siirtää myös heidän varusteensa (jos mahdollista).\"\n  STR_HIGHLIGHT_NEW: \"Korosta uudet aiheet\"\n  STR_MANUALPROMOTIONS: \"Käsin tehtävät ylennykset\"\n  STR_MANUALPROMOTIONS_DESC: \"Päälle kytkettynä sotilaat on mahdollista ylentää (tai alentaa) käsin napsauttamalla sotilasarvokuvaketta.\"\n  STR_WOUNDED_DEFEND_BASE_IF: \"Haavoittuneet puolustavat (jos terveys yli x %)\"\n  STR_WOUNDED_DEFEND_BASE_IF_DESC: \"Myös haavoittuneet sotilaat puolustavat tukikohtaa, jos heidän terveytensä ylittää annetun prosenttikynnyksen.\"\n  STR_PLAY_BRIEFING_MUSIC_DURING_EQUIPMENT: \"Soita tehtävänantomusiikkia pidempään\"\n  STR_PLAY_BRIEFING_MUSIC_DURING_EQUIPMENT_DESC: \"Tehtävänantomusiikki jatkaa soimistaan varustusvaiheessa ja taistelukentän näkymiseen asti.\"\n  STR_NIGHT_VISION_COLOR: \"Valitse pimeänäköväri\"\n  STR_NIGHT_VISION_COLOR_DESC: \"Arvoväli 1-15, joista kukin esittää erisävyistä väriä.\"\n  STR_AUTO_NIGHT_VISION_THRESHOLD: \"Automaattisen pimeänäön kynnys\"\n  STR_AUTO_NIGHT_VISION_THRESHOLD_DESC: \"Jos on tätä kynnysarvoa pimeämpää, kytke pimeänäkö päälle automaattisesti.\"\n  STR_AUTO_SELL: \"Automaattisen myynnin hallinta\"\n  STR_AUTO_SELL_DESC: \"Taisteluraportin myyntiruudulla esinetyypit, jotka myit edellisissä taisteluissa, automaattisesti merkitään myytäviksi.\"\n  STR_AUTOMATICPROMOTIONS: \"Automaattiset ylennykset\"\n  STR_AUTOMATICPROMOTIONS_DESC: \"Päälle kytkettynä sotilaat ylennetään automaattisesti tehtävän jälkeen.\"\n  STR_OFF_CENTRE_SHOOTING: \"Epäkeskeisammunta\"\n  STR_OFF_CENTRE_SHOOTING_DESC: \"Sotilaat yrittävät automaattisesti hieman korjata ampumakulmaansa, jos tulilinja puuttuu.\"\n  STR_GRAPHS_ZOOM_IN: \"Lähennä (kuvaajat)\"\n  STR_GRAPHS_ZOOM_OUT: \"Loitonna (kuvaajat)\"\n  STR_MARK_ALL_AS_SEEN: \"Merkitse kaikki nähdyiksi\"\n  STR_SELL_ALL: \"Myy kaikki\"\n  STR_SELL_ALL_BUT_ONE: \"Myy kaikki paitsi yksi\"\n  STR_TRANSFER_ALL: \"Siirrä kaikki\"\n  STR_REMOVE_SOLDIERS_FROM_ALL_CRAFTS: \"Poista sotilaat kaikista aluksista\"\n  STR_REMOVE_SOLDIERS_FROM_CRAFT: \"Poista sotilaat aluksesta\"\n  STR_REMOVE_EQUIPMENT_FROM_CRAFT: \"Poista varusteet aluksesta\"\n  STR_REMOVE_ARMOR_FROM_ALL_CRAFTS: \"Poista panssarit kaikista aluksista\"\n  STR_REMOVE_ARMOR_FROM_CRAFT: \"Poista panssarit aluksesta\"\n  STR_REMOVE_SOLDIERS_FROM_TRAINING: \"Poista sotilaat koulutuksesta\"\n  STR_ADD_SOLDIERS_TO_TRAINING: \"Lisää sotilaita koulutukseen\"\n  STR_INVENTORY_ARMOR: \"Vaihda panssaria\"\n  STR_INVENTORY_AVATAR: \"Vaihda ulkonäköä\"\n  STR_ACTION_ITEM_1: \"Esineen toiminta 1 (tähtäys/käyttö)\"\n  STR_ACTION_ITEM_2: \"Esineen toiminta 2 (kertatuli)\"\n  STR_ACTION_ITEM_3: \"Esineen toiminta 3 (sarjatuli)\"\n  STR_ACTION_ITEM_4: \"Esineen toiminta 4 (lähitaistelu)\"\n  STR_ACTION_ITEM_5: \"Esineen toiminta 5 (heitto)\"\n  STR_TOGGLE_QUICK_SEARCH: \"Kytke pikahakukenttä\"\n  STR_TOGGLE_NIGHT_VISION: \"Kytke pimeänäkö\"\n  STR_HOLD_NIGHT_VISION: \"Lyhyt pimeänäkö\"\n  STR_SELECT_MUSIC_TRACK: \"Valitse musiikkikappale\"\n  STR_TOGGLE_TOUCH_BUTTONS: \"Kytke kosketusnäppäimet\"\n  STR_TOGGLE_BRIGHTNESS: \"Kytke kirkkaus (vain havainnollinen)\"\n  STR_BRIEFING: \"Tehtävänanto\"\n  STR_TOGGLE_DEBUG_MODE: \"Kytke vianmääritystila\"\n  STR_DEBUG_KILL_ALL_ALIENS: \"VIANMÄÄRITYS: Tapa kaikki muukalaiset\"\n  STR_PHYSICAL_TRAINING: \"Taistelukoulutus\"\n  STR_REMAINING_TRAINING_FACILITY_CAPACITY: \"VAPAA KOULUTUSTILA> {ALT}{0}\"\n  STR_NO_WOUNDED: \"-\"\n  STR_NO_QUEUED: \"+\"\n  STR_NO_DONE: \"VALMIS\"\n  STR_NO_AMMO: \"EI AMMUKSIA!\"\n  STR_START_FIRING: \"Laukaus!\"\n  STR_SKIP_FIRING: \"Päästä ne sisään...\"\n  STR_ALIEN_MISSILES_HAVE_DAMAGED_OUR_BASE: \"Muukalaisohjukset ovat vaurioittaneet tukikohtaa {0}\"\n  STR_ALIEN_MISSILES_HAVE_DESTROYED_OUR_BASE: \"Muukalaisohjukset ovat tuhonneet tukikohdan {0}\"\n  STR_STARTING_CONDITION_COMMANDER: \"Tämä tehtävä edellyttää komentajan läsnäoloa.\"\n  STR_STARTING_CONDITION_CRAFT: \"Tämä alus ei sovellu tähän tehtävään.\"\n  STR_STARTING_CONDITION_CRAFT_ALLOWED: \"Alus ei sovellu tähän tehtävään.{NEWLINE}{NEWLINE}Sallitut alukset: {0}\"\n  STR_STARTING_CONDITION_CRAFT_FORBIDDEN: \"Alus ei sovellu tähän tehtävään.{NEWLINE}{NEWLINE}Kielletyt alukset: {0}\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE: \"Osa sotilaista ei voi osallistua tähän tehtävään.\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE_ALLOWED: \"Osa sotilaista ei voi osallistua tähän tehtävään. {NEWLINE}{NEWLINE}Sallitut sotilastyypit: {0}\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE_FORBIDDEN: \"Osa sotilaista ei voi osallistua tähän tehtävään. {NEWLINE}{NEWLINE}Kielletyt sotilastyypit: {0}\"\n  STR_STARTING_CONDITION_ITEM: \"Tehtävä vaatii erityisvarustusta:{NEWLINE}{NEWLINE}{0}\"\n  STR_NOT_ENOUGH_FUEL_TO_REACH_TARGET: \"EI RIITTÄVÄSTI POLTTOAINETTA!{SMALLLINE}Määränpää on aluksen kantaman ulkopuolella.\"\n  STR_ASSIGN_PILOTS: \"Määrää lentäjät...\"\n  STR_NOT_ENOUGH_PILOTS: \"Ei riittävästi lentäjiä!{NEWLINE}Vähimmäismäärä: {0}\"\n  STR_DAILY_PILOT_EXPERIENCE: \"Päivittäinen lentäjäkokemus\"\n  STR_UFO_SHIELD_HIT: \"OSUI SUOJIIN!\"\n  STR_UFO_HIT_NO_DAMAGE: \"KIMPOSI RUNGOSTA!\"\n  STR_UFO_SHIELD_DOWN: \"VIHOLLISSUOJAT ALHAALLA!\"\n  STR_UFO_HIT_GLANCING: \"PINTAOSUMA!\"\n  STR_INTERCEPTOR_SHIELD_HIT: \"SUOJAMME PITELEVÄT!\"\n  STR_TRACTOR_BEAM_ENGAGED: \"VETOSÄDE PÄÄLLÄ!\"\n  STR_TRACTOR_BEAM_DISENGAGED: \"SAMMUTETAAN VETOSÄDETTÄ\"\n  STR_SELF_DESTRUCT_ACTIVATED: \"ITSETUHO AKTIVOITU!\"\n  STR_SELF_DESTRUCT_CANCELLED: \"ITSETUHO PERUUTETTU\"\n  STR_EXTENDED_LINKS: \"Linkit\"\n  STR_AUTO_PATROL: \"AUTOMAATTINEN PARTIOINTI\"\n  STR_UFO_STARTED_HUNTING: \"{0} on torjuntakurssilla kohteeseen {1}\"\n  STR_CRAFT_IS_READY: \"{0} kohteessa {1} on valmis.\"\n  STR_ECONOMY_WARNING: \"Varat {0} ja tulot {1} ovat alhaiset ja ylläpitokustannukset {2} liian korkeat! Myy jotain välttääksesi luoton ottamisen... Varoja puuttuu {3}.\"\n  STR_SLACKING_INDICATOR: \"{0}:{1}\"\n  STR_TRAINING_INDICATOR: \"{0}:{1}\"\n  STR_EXTENDED_UC: \"LAAJENNETTU\"\n  STR_RETURNING: \"PALAAMASSA\"\n  STR_INTERCEPTING: \"TORJUNNASSA\"\n  STR_ESCORTING: \"SAATTAMASSA\"\n  STR_EN_ROUTE: \"MATKALLA\"\n  STR_PILOT_MISSING: \"LENTÄJÄ PUUTTUU\"\n  STR_DAY_SHORT: \"{0}d\"\n  STR_HOUR_SHORT: \"{0}h\"\n  STR_PERFORMANCE_BONUS: \"Suorituspalkkio\"\n  STR_COUNTRY_HAS_CANCELLED_A_SECRET_PACT: \"{0} on luopunut sopimuksesta muukalaisvoimien kanssa ja on saanut luvan palata projektiin.\"\n  STR_COUNTRIES_HAVE_CANCELLED_A_SECRET_PACT: \"{0} ovat luopuneet sopimuksesta muukalaisvoimien kanssa ja ovat saaneet luvan palata projektiin.\"\n  STR_WE_CAN_NOW_RENT: \"Uudet vuokratuotteet:\"\n  STR_REQUIRED_BASE_SERVICES: \"Vaaditut tukikohtapalvelut: {0}\"\n  STR_WE_CAN_NOW_BUILD: \"Uudet rakennusprojektit:\"\n  STR_WE_CAN_NOW_PURCHASE: \"Uudet ostotuotteet:\"\n  STR_NOT_ENOUGH_LIVING_SPACE_AT_BASE: \"Ei riittävästi asuintilaa majoittaa{NEWLINE}{0}{NEWLINE}kohteessa{NEWLINE}{1}\"\n  STR_INFO: \"TIEDOT\"\n  STR_DESPAWN_PENALTY: \"Poistosakko> {0}\"\n  STR_TRAINING_FINISHED: \"Koulutus suoritettu{NEWLINE}tukikohdassa {0}\"\n  STR_PSI_TRAINING_FINISHED: \"Psi-koulutus valmis{NEWLINE}kohteessa {0}\"\n  STR_IGNORE_UC: \"HYLKÄÄ\"\n  STR_UFO_TRACKER: \"Ufoseuranta\"\n  STR_UPDATE: \"Päivitys\"\n  STR_LATEST_VERSION_INFO: \"Käytät OpenXcomin uusinta versiota.\"\n  STR_MASTER_MOD_VERSION_REQUIRED_QUESTION: \"Toimiakseen oikein tämä modi edellyttää peruspelin versiota {0}. Otetaanko modi käyttöön?\"\n  STR_VERSION_REQUIRED_QUESTION: \"OXCE v{0} vaaditaan, jotta modi toimisi kunnolla. Kytketäänkö modi päälle?\"\n  STR_NOTES: \"Merkinnät\"\n  STR_NEW_NOTE: \"<NEW NOTE>\"\n  STR_PATH_ENERGY_COST: \"Energia\"\n  STR_PATH_ENERGY_COST_DESC: \"Napsauttaminen näyttää yksikkösi jäljelle jäävän energian saavutettuaan määränpäänsä.\"\n  STR_TEST_SCREEN: \"KOERUUTU\"\n  STR_PALETTE: \"Paletti:\"\n  STR_PREVIEW: \"Esikatselu\"\n  STR_TINY_BORDERLESS: \"Hyvin pieni, reunaton\"\n  STR_TINY_BORDER: \"Hyvin pieni\"\n  STR_SMALL_LOW_CONTRAST: \"Pieni\"\n  STR_SMALL_HIGH_CONTRAST: \"Pieni, korkea sävykkyys\"\n  STR_BIG_LOW_CONTRAST: \"Suuri\"\n  STR_BIG_HIGH_CONTRAST: \"Suuri, korkea sävykkyys\"\n  STR_TEST_CASE: \"Koetapaus:\"\n  STR_RUN: \"Aja valittu koe!\"\n  STR_TESTS_STARTING: \"Aloitetaan...\"\n  STR_TESTS_ERRORS_FOUND: \"Havaitut virheet (joukossa saattaa olla kaksoiskappaleita): {0}\"\n  STR_TESTS_NO_ERRORS_FOUND: \"Ei havaittuja virheitä.\"\n  STR_TESTS_FINISHED: \"Suoritettu.\"\n  STR_DETAILED_INFO_IN_LOG_FILE: \"Yksityiskohtaiset tiedot on tallennettu tiedostoon openxcom.log\"\n  STR_RANK_NONE: \"-\"\n  STR_DAMAGE_NONE: \"EI MITÄÄN\"\n  STR_INFO_UFOPEDIA: \"TIEDOT\"\n  STR_COCKPIT_CAPACITY: \"LENTÄJÄT>{ALT}{0}{ALT}\"\n  STR_MAXIMUM_RANGE: \"KANTAMA (MAX)>{ALT}{0}{ALT}\"\n  STR_MINIMUM_RANGE: \"KANTAMA (MIN)>{ALT}{0}{ALT}\"\n  STR_INFINITE_RANGE: \"EI SAATAVILLA\"\n  STR_TRACTOR_BEAM_POWER: \"Tehokkuus\"\n  STR_WEIGHT_PEDIA1: \"m: {0}\"\n  STR_WEIGHT_PEDIA2: \"m: {0}/{1}\"\n  STR_SHOT_TYPE_MELEE: \"Lähitaistelu\"\n  STR_ACCURACY_MODIFIER: \"Tarkkuuskerroin>{ALT} {0}\"\n  STR_POWER_BONUS: \"Voimalisä>{ALT} {0}\"\n  STR_MULTIPLE_DIFFERENT_BONUSES: \"useita hyötykertoimia erilaisilla yhteensopivilla ammuksilla\"\n  STR_STATS_FOR_NERDS: \"Tilastoja nörteille\"\n  STR_ARTICLE: \"Asia>{ALT} {0}\"\n  STR_COMPATIBLE_AMMO: \"Yhteensopivat ammukset:\"\n  STR_BUILT_IN_ITEMS: \"Sisäänrakennetut esineet:\"\n  STR_CLIP_SIZE_UNLIMITED: \"loppumaton\"\n  STR_SHOTGUN_BEHAVIOR_OXCE: \"pidennetty\"\n  STR_INCLUDE_DEBUG: \"VIANKORJAUS\"\n  STR_INCLUDE_IDS: \"TUNNISTEET\"\n  STR_INCLUDE_DEFAULTS: \"OLETUKSET\"\n  STR_TRUE: \"tosi\"\n  STR_FALSE: \"epätosi\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH: \"PSI-TAITO*PSI-VOIMA\"\n  STR_STRENGTH_AND_MELEE_ACCURACY: \"VOIMA*LÄHITAISTELUTARKKUUS\"\n  STR_STRENGTH_AND_THROWING_ACCURACY: \"VOIMA*HEITTOTARKKUUS\"\n  STR_FIRING_ACCURACY_AND_REACTIONS: \"AMPUMATARKKUUS*REAKTIOKYKY\"\n  STR_HEALTH_CURRENT: \"NYKYINEN TERVEYS\"\n  STR_MANA_CURRENT: \"NYKYINEN MANA\"\n  STR_TIME_UNITS_CURRENT: \"NYKYISET AIKAYKSIKÖT\"\n  STR_STUN_LEVEL_CURRENT: \"NYKYINEN TAINTUMUSASTE\"\n  STR_HEALTH_NORMALIZED: \"NORMALISOITU TERVEYS\"\n  STR_MANA_NORMALIZED: \"NORMALISOITU MANA\"\n  STR_TIME_UNITS_NORMALIZED: \"NORMALISOIDUT AIKAYKSIKÖT\"\n  STR_ENERGY_NORMALIZED: \"NORMALISOITU ENERGIA\"\n  STR_MORALE_NORMALIZED: \"NORMALISOITU TAISTELUTAHTO\"\n  STR_STUN_LEVEL_NORMALIZED: \"NORMALISOITU TAINTUMUSASTE\"\n  STR_ENERGY_REGENERATION: \"ENERGIAN UUSIUTUMISNOPEUS\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH_ABBREVIATION: \"PST*PSV\"\n  STR_STRENGTH_AND_MELEE_ACCURACY_ABBREVIATION: \"VOI*LÄH\"\n  STR_STRENGTH_AND_THROWING_ACCURACY_ABBREVIATION: \"VOI*HEI\"\n  STR_FIRING_ACCURACY_AND_REACTIONS_ABBREVIATION: \"TAR*REA\"\n  STR_HEALTH_CURRENT_ABBREVIATION: \"NYKYINEN TERVEYS\"\n  STR_MANA_CURRENT_ABBREVIATION: \"NYKYINEN MANA\"\n  STR_TIME_UNITS_CURRENT_ABBREVIATION: \"NYKYISET AIKAYKSIKÖT\"\n  STR_STUN_LEVEL_CURRENT_ABBREVIATION: \"NYKYINEN TAINTUMUSASTE\"\n  STR_HEALTH_NORMALIZED_ABBREVIATION: \"NORMALISOITU TERVEYS\"\n  STR_MANA_NORMALIZED_ABBREVIATION: \"NORMALISOITU MANA\"\n  STR_TIME_UNITS_NORMALIZED_ABBREVIATION: \"NORMALISOIDUT AIKAYKSIKÖT\"\n  STR_ENERGY_NORMALIZED_ABBREVIATION: \"NORMALISOITU ENERGIA\"\n  STR_MORALE_NORMALIZED_ABBREVIATION: \"NORMALISOITU TAISTELUTAHTO\"\n  STR_STUN_LEVEL_NORMALIZED_ABBREVIATION: \"NORMALISOITU TAINTUMUSASTE\"\n  STR_ENERGY_REGENERATION_ABBREVIATION: \"ENERGIAN UUSIUTUMISNOPEUS\"\n  STR_COST_TIME: \"aika\"\n  STR_COST_ENERGY: \"energia\"\n  STR_COST_MORALE: \"taistelutahto\"\n  STR_COST_HEALTH: \"terveys\"\n  STR_COST_STUN: \"tainnutus\"\n  STR_COST_MANA: \"mana\"\n  STR_COST_BUILD: \"rakennus\"\n  STR_COST_REFUND: \"palautus\"\n  STR_DAMAGE_10: \"10\"\n  STR_DAMAGE_11: \"11\"\n  STR_DAMAGE_12: \"12\"\n  STR_DAMAGE_13: \"13\"\n  STR_DAMAGE_14: \"14\"\n  STR_DAMAGE_15: \"15\"\n  STR_DAMAGE_16: \"16\"\n  STR_DAMAGE_17: \"17\"\n  STR_DAMAGE_18: \"18\"\n  STR_DAMAGE_19: \"19\"\n  STR_NAUTICAL_MILES: \"{0} merimailia\"\n  STR_KILOMETERS_PER_HOUR: \"{0} km/h\"\n  STR_SECONDS_LONG: \"{0} sekuntia\"\n  STR_RACE_BONUS: \"Lajivaikutus\"\n  STR_FOR_DIFFICULTY: \"vaikeustasolle: {0}\"\n  STR_NOT_AWARDED_YET: \"Ei myönnetty vielä\"\n"
  },
  {
    "path": "bin/common/Language/OXCE/fr.yml",
    "content": "fr:\n  STR_CANNOT_DISMANTLE_FACILITY_UPGRADING: \"L'INSTALLATION NE PEUT ÊTRE DÉMANTELÉE{SMALLLINE}L'installation ne peut être retirée durant sa mise à jour.\"\n  STR_CANNOT_UPGRADE_FACILITY_ALREADY_UPGRADING: \"CONSTRUCTION IMPOSSIBLE ICI !{SMALLLINE}Une construction par-dessus cette installation est déjà en cours.\"\n  STR_CANNOT_UPGRADE_FACILITY_WRONG_SIZE: \"CONSTRUCTION IMPOSSIBLE ICI !{SMALLLINE}L'installation choisie doit complètement recouvrir l'installation existante.\"\n  STR_CANNOT_UPGRADE_FACILITY_WRONG_TYPE: \"CONSTRUCTION IMPOSSIBLE ICI !{SMALLLINE}L'installation existante ne peut être mise à jour par l'installation sélectionnée.\"\n  STR_CANNOT_UPGRADE_FACILITY_DISALLOWED: \"CONSTRUCTION IMPOSSIBLE ICI !{SMALLLINE}L'installation existante ne peut être remplacée.\"\n  STR_CANNOT_BUILD_QUEUE_OFF: \"CONSTRUCTION IMPOSSIBLE ICI !{SMALLLINE}Les installations adjacentes doivent être finie au préalable.\"\n  STR_CANNOT_BUILD_UPGRADE_ONLY: \"IMPOSSIBLE DE CONSTRUIRE ICI !{SMALLLINE}Cette installation ne peut être construite qu’en tant qu’amélioration d’une autre installation.\"\n  STR_FACILITY_FORBIDDEN_BY_OTHER: \"CONSTRUCTION IMPOSSIBLE ICI !{SMALLLINE}Une installation existante empêche la construction de cette installation.\"\n  STR_FACILITY_OTHER_FORBIDDEN_BY_THIS: \"CONSTRUCTION IMPOSSIBLE ICI !{SMALLLINE}Une installation existante serait prohibée par l'installation sélectionnée.\"\n  STR_NOT_ENOUGH_ITEMS: \"PAS ASSEZ DE MATÉRIAUX{SMALLLINE}Nous avons besoin de plus de ressources pour construire cette installation.{SMALLLINE}Manquant> {0}: {1}\"\n  STR_ID: \"ID\"\n  STR_FIRST_LETTER: \"PREMIÉRE LETTRE\"\n  STR_SOLDIER_TYPE: \"TYPE DE SOLDAT\"\n  STR_IDLE_DAYS: \"JOURS D'INACTIVITÉ\"\n  STR_MANA: \"MANA\"\n  STR_MANA_POOL: \"RÉSERVE DE MANA\"\n  STR_MANA_MISSING: \"MANA MANQUANTE\"\n  STR_LOAD_CRAFT_LOADOUT_TEMPLATE: \"Charger un modèle de véhicule\"\n  STR_EMPTY_SLOT_N: \"Emplacement libre {0}\"\n  STR_UNNAMED_SLOT_N: \"Emplacement sans nom {0}\"\n  STR_ADD_ON_TOP: \"Ajouter au dessus\"\n  STR_SAVE_CRAFT_LOADOUT_TEMPLATE: \"Sauvegarder un modèle de véhicule\"\n  STR_SAVE_UC: \"SAUVEGARDER\"\n  STR_ALL: \"Tout\"\n  STR_EQUIPPED: \"Équipé\"\n  STR_NOT_EQUIPPED: \"Non-équipé\"\n  STR_UNASSIGNED: \"Autres\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED_BY_SIZE: \"PLUS D'ÉQUIPEMENTS AUTORISÉS À BORD !{SMALLLINE}Espace de stockage maximum : {0}\"\n  STR_PILOTS: \"PILOTES\"\n  STR_SHIELD: \"BOUCLIER> {ALT}{0}\"\n  STR_CRAFT_SKIN_ID: \"[{0}]\"\n  STR_SELECT_PILOT: \"Sélectionner un pilote\"\n  STR_PILOTS_FOR_CRAFT: \"Pilote(s) pour {0}\"\n  STR_PILOTS_REQUIRED: \"Pilote(s) requis : {ALT}{0}\"\n  STR_ADD_PILOT: \"Ajouter un pilote\"\n  STR_REMOVE_ALL_PILOTS: \"Retirer tous les pilotes\"\n  STR_ACCURACY_BONUS: \"Bonus de Précision :\"\n  STR_DODGE_BONUS: \"Bonus d'Esquive :\"\n  STR_APPROACH_SPEED: \"Vitesse d'approche :\"\n  STR_COWARDLY: \"Lâcheté (-50%)\"\n  STR_NORMAL: \"Normal\"\n  STR_BOLD: \"Audacieux (+50%)\"\n  STR_VERY_BOLD: \"Très audacieux (+100%)\"\n  STR_SOLDIER_GROUP_NOT_ALLOWED: \"Ce type de combattant n'est pas autorisé à bord.\"\n  STR_SOLDIER_GROUP_NOT_SAME: \"Ce type de combattant n'est pas compatible avec les autres combattant à bord.\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW: \"Aperçu\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_SAVED: \"Aperçu *\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_BRIEFING: \"Cette fonctionnalité vous permet de prévisualiser et de personnaliser le déploiement de vos unités au début d'une bataille. Vous avez un mouvement illimité. Appuyez et maintenez la touche « Alt » pour afficher les positions valides des unités. Cliquez sur l'icône « Abandonner la mission » pour enregistrer un déploiement personnalisé. Cliquez sur l'icône « Fin de tour » pour quitter la prévisualisation.{NEWLINE}Notez que l'ajout de nouveaux soldats ou véhicules à l'aéronef invalide automatiquement le déploiement personnalisé enregistré. La présence d'un déploiement personnalisé est indiquée par un astérisque sur le bouton « Prévisualisation ». \"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_BRIEFING_DUMMY: \"Cette fonctionnalité vous permet de prévisualiser et de modifier la table de déploiement pour ce type de véhicules. Tous les changements s'appliqueront à vos véhicules actuels ainsi qu'à ceux que vous achèterez ou fabriquerez plus tard dans la campagne. Vous commencez avec le nombre maximum de soldats. Chaque soldat correspond à une ligne dans la table de déploiement. Les noms des soldats correspondent aux numéros de ligne. Pour fournir de l'espace à une unité 2x2, placez 4 soldats dans un carré 2x2. Si l'espace fournis, l'unité 2x2 sera absente lors de la bataille réelle.\"\n  STR_BASE_DEFENSE_BRIEFING_PREVIEW: \"Cette fonctionnalité vous permet d'avoir un aperçu de votre base.{NEWLINE}Amusez-vous !{NEWLINE}{NEWLINE}Cliquez sur l'icône \\\"Fin du tour\\\" pour quitter l'aperçu.\"\n  STR_NOT_ENOUGH_CARGO_SPACE: \"PAS ASSEZ D'ESPACE SOUTE DISPONIBLE !{SMALLLINE}Utilisez un module différent ou réduisez l'équipage assigné.\"\n  STR_NOT_ENOUGH_STORAGE_SPACE_1: \"PAS ASSEZ D'ESPACE SOUTE DISPONIBLE !{SMALLLINE}Trop d'objet différents ! Utilisez un module différent ou réduisez l'équipement assigné.\"\n  STR_NOT_ENOUGH_STORAGE_SPACE_2: \"PAS ASSEZ D'ESPACE SOUTE DISPONIBLE !{SMALLLINE}Les objets prennent trop de place ! Utilisez un module différent ou réduisez la taille l'équipement assigné.\"\n  STR_REFUND_VALUE: \"Valeur de vente> {ALT}{0}\"\n  STR_REFUND_VALUE_NEGATIVE: \"Dépenses> {ALT}{0}\"\n  STR_PRODUCTION_OVERVIEW: \"APERÇU DE LA PRODUCTION\"\n  STR_RESEARCH_DIARY: \"JOURNAL DE RECHERCHE\"\n  STR_DISCOVERY_SOURCE_BASE: \"Cet objet a été découvert lors d’un projet de recherche.{NEWLINE}Base de recherche> {ALT}{1}{ALT}{NEWLINE}Code de l’objet> {ALT}{0}{ALT}\"\n  STR_DISCOVERY_SOURCE_FREE_FROM: \"Cet objet a été obtenu gratuitement grâce à un autre projet de recherche.{NEWLINE}Depuis le projet de recherche > {ALT}{2}{ALT}{NEWLINE}{ALT}{1}{ALT} -> {ALT}{0}{ALT}\"\n  STR_DISCOVERY_SOURCE_FREE_AFTER: \"Cet objet a été découvert automatiquement.{NEWLINE}Après le projet de recherche > {ALT}{2}{ALT}{NEWLINE}{ALT}{1}{ALT} -> {ALT}{0}{ALT}\"\n  STR_DISCOVERY_SOURCE_MISSION: \"Cet objet a été obtenu gratuitement comme récompense de mission.{NEWLINE}Type de mission > {ALT}{2}{ALT}{NEWLINE}{ALT}{1}{ALT} -> {ALT}{0}{ALT}\"\n  STR_DISCOVERY_SOURCE_EVENT: \"Cet objet a été obtenu gratuitement comme récompense d’événement.{NEWLINE}Type d’événement > {ALT}{2}{ALT}{NEWLINE}{ALT}{1}{ALT} -> {ALT}{0}{ALT}\"\n  STR_RESEARCH_OVERVIEW: \"APERÇU DE LA RECHERCHE\"\n  STR_PRISONER_OVERVIEW: \"APERÇU DES PRISONNIERS\"\n  STR_PRISONER: \"PRISONNIER\"\n  STR_PRISONER_AMOUNT: \"QUANTITÉ\"\n  STR_PRISONER_INTERROGATED: \"INTERROGÉ\"\n  STR_TOTAL_IN_PRISON: \"Espace utilisé> {ALT}{0}\"\n  STR_TOTAL_INTERROGATED: \"Interrogés> {ALT}{0}\"\n  STR_PRISON_TYPE: \"Confinement alien\"\n  STR_KILL_SELECTED: \"Tuer\"\n  STR_SELL_SELECTED: \"Vendre\"\n  STR_GO_TO_TRANSFERS: \"Transférer…\"\n  STR_PRISON_CLEANUP: \"Nettoyage de la prison\"\n  STR_TOPIC: \"Sujet> {ALT} {0}\"\n  STR_SHOW_ALL: \"Tout montrer\"\n  STR_NO_DEPENDENCIES: \"Aucune dépendance.\"\n  STR_DIRECT_DEPENDENCIES: \"Dépendances directes\"\n  STR_LEVEL_2_DEPENDENCIES: \"Dépendances de niveau 2\"\n  STR_LEVEL_3_DEPENDENCIES: \"Dépendances de niveau 3\"\n  STR_LEVEL_4_DEPENDENCIES: \"Dépendances de niveau 4\"\n  STR_MORE_DEPENDENCIES: \"Il y a des dépendances encore plus profondes...\"\n  STR_END_OF_SEARCH: \"Fin de recherche.\"\n  STR_REFUND_PRODUCTION: \"REMBOURSÉ !\"\n  STR_HOURS_PER_UNIT: \"HEURES PAR UNITÉ> {ALT}{0}\"\n  STR_PERSON_JOINING: \"Individu qui rejoindra\"\n  STR_RANDOM_PRODUCTION_DISCLAIMER: \"Production aléatoire !\"\n  STR_OTHER_EMPLOYEES: \"Autre Personnel & Inventaire\"\n  STR_SHOW_ONLY_NEW: \"Montrer seulement les nouveaux\"\n  STR_FILTER_DEFAULT: \"Par défaut\"\n  STR_FILTER_DEFAULT_SUPPLIES_OK: \"Par défaut (Fournitures OK)\"\n  STR_FILTER_DEFAULT_NO_SUPPLIES: \"Par défaut (pas de fournitures)\"\n  STR_FILTER_FACILITY_REQUIRED: \"Installation manquante\"\n  STR_FILTER_HIDDEN: \"Masqué\"\n  STR_FILTER_EQUIPPED: \"Équipé\"\n  STR_FILTER_MISSING: \"Manquant\"\n  STR_SORT_DEFAULT: \"Par défaut\"\n  STR_SORT_BY_COST: \"Par prix\"\n  STR_SORT_BY_NAME: \"Par nom\"\n  STR_RANDOM_PRODUCTION_SUMMARY: \"Récapitulatif\"\n  STR_NOT_ENOUGH_PRISON_SPACE: \"PAS ASSEZ DE CONFINEMENTS E.T. !{SMALLLINE}Construisez un nouveau confinement E.T. ou transférez les dans une base.\"\n  STR_MONTHLY_ITEM_PURCHASE_LIMIT_EXCEEDED: \"LIMITE D'ACHAT MENSUELLE DÉPASSÉE !{SMALLLINE}Davantage d'articles seront disponibles le mois prochain.\"\n  STR_MONTHLY_CRAFT_PURCHASE_LIMIT_EXCEEDED: \"LIMITE D'ACHAT MENSUELLE DÉPASSÉE !{SMALLLINE}Davantage de véhicules seront disponibles le mois prochain.\"\n  STR_MONTHLY_SOLDIER_HIRING_LIMIT_EXCEEDED: \"LIMITE D'ENGAGEMENT MENSUEL DÉPASSÉ !{SMALLLINE}Davantage de recrues seront disponible le mois prochain.\"\n  STR_NOT_ENOUGH_CRAFT_SPACE: \"Plus assez de place à bord !\"\n  STR_SELECT_AVATAR_FOR: \"SÉLECTIONNEZ UN AVATAR POUR{NEWLINE}{0}\"\n  STR_SOLDIER_BONUSES_FOR: \"BONUS DE SOLDAT POUR{NEWLINE}{0}\"\n  STR_SUMMARY: \"Récapitulatif\"\n  STR_MANA_RECOVERY: \"RÉCUPÉRATION DE MANA> {ALT}{0}\"\n  STR_HEALTH_RECOVERY: \"RÉCUPÉRATION DE SANTÉ> {ALT}{0}\"\n  STR_BONUSES_BUTTON: \"+\"\n  STR_PROMOTE_SOLDIER: \"PROMOUVOIR/DÉMOUVOIR{NEWLINE}{0} {1}\"\n  STR_RANK_HEADER: \"RANG\"\n  STR_OPENINGS_HEADER: \"OUVERTURES\"\n  STR_KILLER_AND_WEAPON: \"{0}, {1}\"\n  STR_TRAINING: \"Entraînement\"\n  STR_SOLDIER_INFO: \"Info soldat\"\n  STR_SELECT_TRANSFORMATION_FOR: \"SÉLECTIONNEZ LA CIBLE DE LA TRANSFORMATION{0}\"\n  STR_TRANSFORMATIONS_BUTTON: \"^\"\n  STR_TRANSFER_TIME: \"Temps de transfert> {ALT}{0}\"\n  STR_RECOVERY_TIME: \"Temps de récupération> {ALT}{0}\"\n  STR_CURRENT_STATS: \"Stats actuelles\"\n  STR_CHANGES: \"Changements\"\n  STR_CHANGES_MIN: \"Changements (min)\"\n  STR_CHANGES_MAX: \"Changement (max)\"\n  STR_BONUS_STATS: \"Bonus de stats\"\n  STR_TRANSFORMATIONS_OVERVIEW: \"Aperçu de transformation\"\n  STR_PROJECT_NAME: \"NOM DU PROJET\"\n  STR_AVAILABLE_MATERIALS: \"MATÉRIAUX DISPONIBLES\"\n  STR_ELIGIBLE_SOLDIERS: \"SOLDATS ÉLIGIBLES\"\n  STR_SHOW_ONLY_ELIGIBLE: \"Seulement les éligibles\"\n  STR_ALL_SOLDIER_TYPES: \"Tout type de soldat\"\n  STR_ALL_SOLDIERS: \"Tous les soldats\"\n  STR_HEALTHY_SOLDIERS: \"Soldats en bonne santé\"\n  STR_WOUNDED_SOLDIERS: \"Soldats blessés\"\n  STR_DEAD_SOLDIERS: \"Soldats morts\"\n  STR_GRAND_TOTAL: \"Grand Total\"\n  STR_AVAILABLE_TOPICS: \"SUJETS DISPONIBLES\"\n  STR_QS_THREE_LETTERS_A: \"Veuillez entrer au moins 3 lettres\"\n  STR_QS_THREE_LETTERS_B: \"dans la boîte de recherche rapide...\"\n  STR_M_FLAG: \" [m]\"\n  STR_F_FLAG: \" [f]\"\n  STR_I_FLAG: \" [i]\"\n  STR_C_FLAG: \" [c]\"\n  STR_THIS_FEATURE_IS_DISABLED_1: \"Cette fonctionnalité est désactivée.\"\n  STR_THIS_FEATURE_IS_DISABLED_2: \"Cette fonctionnalité est désactivée.\"\n  STR_THIS_FEATURE_IS_DISABLED_3: \"Cette fonctionnalité est désactivée.\"\n  STR_THIS_FEATURE_IS_DISABLED_4: \"Cette fonctionnalité est désactivée.\"\n  STR_THIS_FEATURE_IS_DISABLED_5: \"Cette fonctionnalité est désactivée.\"\n  STR_TECH_TREE_VIEWER: \"Aperçu de l'arbre technologique\"\n  STR_SELECT_TOPIC: \"Choisir un sujet\"\n  STR_RESEARCH_PROGRESS: \"Progrès> {ALT} {0}%\"\n  STR_ITEM_DESTROYED: \"Objet détruit :\"\n  STR_ITEM_REQUIRED: \"Objet requis :\"\n  STR_SERVICES_REQUIRED: \"Services requis :\"\n  STR_SERVICES_PROVIDED: \"Services fournis :\"\n  STR_SERVICES_FORBIDDEN: \"Services prohibés :\"\n  STR_REQUIRES: \"Requiert :\"\n  STR_DEPENDS_ON: \"Dépendences :\"\n  STR_UNLOCKED_BY: \"Déverrouillé par :\"\n  STR_DISABLED_BY: \"Désactivé par :\"\n  STR_REENABLED_BY: \"Réactivé par :\"\n  STR_GET_FOR_FREE_FROM: \"Reçu en bonus de :\"\n  STR_IS_LOOKUP_OF: \"Est la recherche de :\"\n  STR_LOOKUP: \"Recherche :\"\n  STR_SPAWNED_ITEMS: \"Apparition d'objets :\"\n  STR_SPAWNED_EVENT: \"Apparition de l'événement :\"\n  STR_REQUIRED_BY: \"Requis par :\"\n  STR_REQUIRED_BY_TRANSFORMATIONS: \"Requis pour les transformations :\"\n  STR_LEADS_TO: \"Mène à :\"\n  STR_UNLOCKS: \"Déverrouille :\"\n  STR_DISABLES: \"Désactive :\"\n  STR_REENABLES: \"Réactive :\"\n  STR_GIVES_ONE_FOR_FREE_SEQ: \"Donne l'un gratuitement (séquence) :\"\n  STR_GIVES_ONE_FOR_FREE: \"Donne l'un gratuitement :\"\n  STR_RESEARCH_REQUIRED: \"Recherches requises :\"\n  STR_RESEARCH_REQUIRED_USE: \"Rechercher requise (utiliser) :\"\n  STR_RESEARCH_REQUIRED_BUY: \"Recherche requise (acheter) :\"\n  STR_SERVICES_REQUIRED_BUY: \"Services requis (achat) :\"\n  STR_PRODUCED_BY: \"Produit par :\"\n  STR_SPAWNED_BY: \"Engendré par :\"\n  STR_MATERIALS_REQUIRED: \"Matériaux requis :\"\n  STR_TTV_COST_PER_UNIT: \"Coût par unité :\"\n  STR_TTV_ENGINEER_HOURS: \"Heures de travail :\"\n  STR_TTV_WORK_SPACE_REQUIRED: \"Espace de travail requi :\"\n  STR_ITEMS_PRODUCED: \"Objets produits :\"\n  STR_PERSON_RECRUITED: \"Personnel recruté :\"\n  STR_UNLOCKS_ARCS: \"Active les arcs :\"\n  STR_DISABLES_ARCS: \"Désactive les arcs :\"\n  STR_UNLOCKS_MISSIONS: \"Déverrouille les missions :\"\n  STR_DISABLES_MISSIONS: \"Désactive les missions :\"\n  STR_UNLOCKS_EVENTS: \"Active les événements :\"\n  STR_DISABLES_EVENTS: \"désactive les événements :\"\n  STR_AFFECTS_GAME_PROGRESSION: \"Affecte la progression !\"\n  STR_ITEMS_AT_DESTINATION: \"Objets à destination\"\n  STR_PRISONERS: \"Prisonniers\"\n  STR_ARMORS: \"Armures\"\n  STR_FILTER_RESEARCHED: \"Complètement recherché\"\n  STR_FILTER_RESEARCHABLE: \"Recherchable\"\n  STR_CRAFT_DEPLOYMENT_QUESTION: \"Sauvegarder le déploiement du véhicule\"\n  STR_MUST_USE_BOTH_HANDS: \"Les deux mains sont requises !\"\n  STR_NOT_ENOUGH_MORALE: \"Moral insuffisant !\"\n  STR_NOT_ENOUGH_HEALTH: \"Santé insuffisante !\"\n  STR_NOT_ENOUGH_MANA: \"Mana insuffisante !\"\n  STR_NOT_ENOUGH_STUN: \"État d'étourdissement trop élevé !\"\n  STR_MIND_CONTROL_SUCCESSFUL_ALT: \"Action réussie\"\n  STR_LINE_OF_SIGHT_REQUIRED: \"Ligne de vue (LoS) requise.\"\n  STR_CENTER_ON_WOUNDED_FRIEND: \"Centrer sur un blessé amical\"\n  STR_CENTER_ON_DIZZY_FRIEND: \"Centrer sur un étourdi amical\"\n  STR_BUG_HUNT_ACTIVATED: \"Chasse au cafards activé : les ennemis sont visible sur la minicarte !\"\n  STR_QUICK_MODE_ACTIVATED: \"Mode Usain Bolt activé.{NEWLINE}Appuyez de nouveau sur Ctrl+S pour le désactiver.\"\n  STR_QUICK_MODE_DEACTIVATED: \"Mode Usain Bolt désactivé.\"\n  STR_TARGET_ENEMY: \"; Cible = ENNEMI\"\n  STR_TARGET_NEUTRAL: \"; Cible = NEUTRE\"\n  STR_TARGET_FRIEND: \"; Cible = AMICALE\"\n  STR_TARGET_YOURSELF: \"; Cible = VOUS-MÊME\"\n  STR_TARGET_ON_THE_GROUND: \"(au sol)\"\n  STR_USE_SPECIAL_ITEM: \"Utiliser un objet spécial\"\n  STR_NO_EXPERIENCE_YET: \"Aucune expérience pour le moment :\"\n  STR_OPERATION_UC: \"OPÉRATION> {0}\"\n  STR_WHAT_CAN_I_WEAR: \"Que puis-je porter ?\"\n  STR_STARTING_CONDITION_ARMORS_FORBIDDEN: \"Cette mission requiert un équipement spécifique.{NEWLINE}{NEWLINE}Type d'armures interdites : {0}\"\n  STR_STARTING_CONDITION_ARMORS_ALLOWED: \"Cette mission requiert un équipement spécifique.{NEWLINE}{NEWLINE}Type d'armures autorisée : {0}\"\n  STR_MISSION_OVER: \"Mission accomplie.\"\n  STR_UNITS_WITH_FATAL_WOUNDS:\n    one: \"L'un d'entre nous est encore mortellement blessé\"\n    many: \"{N} d'entre nous sont encore mortellement blessés\"\n    other: \"{N} d'entre nous sont encore mortellement blessés\"\n  STR_END_MISSION_QUESTION: \"Finir la mission ?\"\n  STR_LOOT: \"BUTIN\"\n  STR_SELL: \"VENDRE\"\n  STR_LIVE_ALIENS_SURRENDERED: \"ENNEMIS QUI SE SONT RENDUS\"\n  STR_MISSION_ABORTED: \"MISSION ANNULÉE\"\n  STR_VIPS_SAVED: \"VIPS SAUVÉS\"\n  STR_VIPS_LOST: \"VIPS PERDUS\"\n  STR_BOUNTY: \"PRIME\"\n  STR_MANA_ABBREVIATION: \"HOMME\"\n  STR_EXPERIENCE_OVERVIEW: \"Aperçu de l’expérience\"\n  STR_CANNOT_PLACE_ITEM_INTO_THIS_SECTION: \"Cette objet ne peut être placé ici.{NEWLINE}Ne demandez pas pourquoi!\"\n  STR_ONE_HAND_MUST_BE_EMPTY: \"Au moins une main doit être libre !\"\n  STR_LOAD_EQUIPMENT_TEMPLATE: \"Charger le modèle d'équipement\"\n  STR_SAVE_EQUIPMENT_TEMPLATE: \"Sauvegarder le modèle d'équipement\"\n  STR_FIRING_SHORT: \"Tirer>{ALT}{0}\"\n  STR_THROWING_SHORT: \"Lancer>{ALT}{0}\"\n  STR_MELEE_SHORT: \"Mêlée>{ALT}{0}\"\n  STR_PERSONAL_EQUIPMENT: \"ÉQUIPEMENT  PERSONNEL\"\n  STR_SAVE_PERSONAL_EQUIPMENT: \"Sauvegarder l'équipement personnel\"\n  STR_LOAD_PERSONAL_EQUIPMENT: \"Charger l'équipement personnel\"\n  STR_PERSONAL_EQUIPMENT_SAVED: \"Équipement personnel sauvegardé.\"\n  STR_PERSONAL_EQUIPMENT_NOT_DEFINED: \"L’équipement personnel n’est pas encore défini.\"\n  STR_SLOT: \"EMPL>{ALT}{0}\"\n  STR_THINKING: \"Réflexion...\"\n  STR_TELL_ME_MORE: \"Dites m'en plus...\"\n  STR_REINFORCEMENTS_ALERT: \"Alerte de renforts !\"\n  STR_HIT_LOG_NEW_TURN: \"Nouveau tour\"\n  STR_FAILED_CQB_CHECK: \"L'ennemi a réussi à interrompre votre attaque !\"\n  STR_NO_TRAJECTORY: \"Pas de trajectoire valide !\"\n  STR_HIT_LOG_NEW_BULLET: \"=> \"\n  STR_MANA_SHORT: \"MA>{ALT}{0}\"\n  STR_SKILL_NEEDS_ITEM: \"Cette compétence nécessite un objet !\"\n  STR_HIT_LOG_NO_DAMAGE: \"0 \"\n  STR_HIT_LOG_SMALL_DAMAGE: \"touché\"\n  STR_HIT_LOG_BIG_DAMAGE: \"TOUCHÉ\"\n  STR_HIT_LOG_REACTION_FIRE: \"Tir de réaction...\"\n  STR_HIT_LOG: \"Journal des touches\"\n  STR_BUTTON_TOUCH: \"Tactile\"\n  STR_BUTTON_1: \"1\"\n  STR_BUTTON_10: \"10\"\n  STR_BUTTON_100: \"100\"\n  STR_BUTTON_LMB: \"LMB\"\n  STR_BUTTON_RMB: \"RMB\"\n  STR_BUTTON_MMB: \"MMB\"\n  STR_BUTTON_CTRL: \"Ctrl\"\n  STR_BUTTON_ALT: \"Alt\"\n  STR_BUTTON_SHIFT: \"Shift\"\n  STR_LAZY_LOADING: \"Chargement différé\"\n  STR_LAZY_LOADING_DESC: \"Si activé, les ressources graphiques sont chargées à la demande. Auquel cas, tout est chargé au lancement.\"\n  STR_VSYNC_FOR_OPENGL: \"VSync pour OpenGL\"\n  STR_VSYNC_FOR_OPENGL_DESC: \"Désactivez pour accélérer le déplacement caché des ennemis et (optionnellement) la vitesse des soldats. NE METTEZ PAS la limite de FPS à 0. S'applique seulement au rendu OpenGL.\"\n  STR_UPDATE_CHECK: \"Vérification de version automatique\"\n  STR_UPDATE_CHECK_DESC: \"Si activé, OpenXcom vérifiera automatiquement s'il y a des mises-à-jours et vous proposera un bouton afin de faire la mise-à-jour par un simple clic.\"\n  STR_AUTOSAVE_SLOTS: \"Nombre de sauvegardes\"\n  STR_AUTOSAVE_SLOTS_DESC: \"Nombre d'emplacements de sauvegardes automatiques en bataille.\"\n  STR_GEO_AUTOSAVE_FREQUENCY: \"Fréquence de sauvegarde (Géoscape)\"\n  STR_GEO_AUTOSAVE_FREQUENCY_DESC: \"Nombre de jours entre chaque sauvegardes automatiques.\"\n  STR_GEO_AUTOSAVE_SLOTS: \"Nombre de sauvegarde (Géoscape)\"\n  STR_GEO_AUTOSAVE_SLOTS_DESC: \"Nombre d'emplacements de sauvegardes automatiques sur le Géoscape\"\n  STR_AUTO_SAVE_GEOSCAPE_SLOT_WITH_NUMBER: \"<GÉOSCAPE AUTO>\"\n  STR_OXCE_LINKS: \"Liens étendus\"\n  STR_OXCE_LINKS_DESC: \"Active des menus/boutons/liens supplémentaires pour les fonctionnalités de OXCE.\"\n  STR_PEDIA_SHOW_CLIP_SIZE: \"Taille du chargeur dans l'OVNIpédie\"\n  STR_PEDIA_SHOW_CLIP_SIZE_DESC: \"Si activé, la taille du chargeur sera affichée à côté de l'icône de celui-ci dans l'OVNIpédie.\"\n  STR_INTERCEPT_TABLE_SIZE: \"Taille du tableau d'interception\"\n  STR_INTERCEPT_TABLE_SIZE_DESC: \"Taille des tableaux dans les fenêtres suivantes : Interception, Suivi des OVNIs.\"\n  STR_SHOW_SLACKING_INDICATOR: \"Montrer l'indicateur d'inactivité\"\n  STR_SHOW_SLACKING_INDICATOR_DESC: \"Si activé, le nombre de scientifiques et d'ingénieurs inactifs sera affiché.\"\n  STR_SHOW_MAINTENANCE_TIME: \"Afficher le temps de maintenance\"\n  STR_SHOW_MAINTENANCE_TIME_DESC: \"{ALT}0>{ALT} Masquer {ALT}1>{ALT} Montrer seulement la durée de la tâche en cours{ALT}2>{ALT} Montrer tout ensemble (réparation + réarmement + ravitaillement).\"\n  STR_SHOW_ETA: \"Montrer le temps de vol estimé\"\n  STR_SHOW_ETA_DESC: \"{ALT}0>{ALT} Masquer {ALT}1>{ALT} Montrer l'ETA pour les cibles immobiles seulement {ALT}2>{ALT} Montrer l'ETA aussi pour les cibles mobiles.\"\n  STR_UFO_LANDING_ALERT: \"Alerte d'atterrissage d'OVNI\"\n  STR_UFO_LANDING_ALERT_DESC: \"Si activé, un message s'affichera à chaque fois qu'un OVNI détecté atterrira. \"\n  STR_REMEMBER_DISABLED_CRAFT_WEAPONS: \"Conserver les armes désactivées \"\n  STR_REMEMBER_DISABLED_CRAFT_WEAPONS_DESC: \"Les armes d'un véhicule désactivées durant un engagement resteront désactivées. Elles ne seront également pas réarmées à la base\"\n  STR_GEO_EVENT_INSTANT_DELIVERY: \"Livraison instant. lors des événements\"\n  STR_GEO_EVENT_INSTANT_DELIVERY_DESC: \"Si activée, les objets obtenus lors d'événements sur le géoscape arriveront instantanément. Autrement, ils arriveront une heure plus tard.\"\n  STR_SHOW_BASE_NAME_IN_POPUPS: \"Montrer le nom de la base dans les popups\"\n  STR_SHOW_BASE_NAME_IN_POPUPS_DESC: \"Si activé, le nom de la base correspondante est affiché dans les fenêtres pop-ups (par exemple, Recherche terminée).\"\n  STR_ALTERNATE_CRAFT_EQUIPMENT_MANAGEMENT: \"Gestion alternative de l'équipement\"\n  STR_ALTERNATE_CRAFT_EQUIPMENT_MANAGEMENT_DESC: \"Si activé, déplacer des soldats entre une base et un véhicule déplacera également son équipement (si possible).\"\n  STR_BASE_INFO_SCALE: \"Mise à l'échelle dans les infos sur la base\"\n  STR_BASE_INFO_SCALE_DESC: \"Si activé, les barres supérieures à 140 seront mise à l'échelle pour correspondre à l'UI.\"\n  STR_HIGHLIGHT_NEW: \"Mise en évidence des nouveaux sujets\"\n  STR_HIGHLIGHT_NEW_DESC: \"Si activé, les nouveaux sujets de recherche, les nouveaux sujets de fabrication et les nouveaux articles dans l'OVNIpédie seront d'une couleur différente.\"\n  STR_RESEARCH_SCROLL_SPEED: \"Défilement sur les recherches\"\n  STR_RESEARCH_SCROLL_SPEED_DESC: \"Les scientifiques peuvent être (dé)assignés directement en utilisant le défilement de la molette de la souris dans l'interface de recherche.\"\n  STR_RESEARCH_SCROLL_SPEED_CTRL: \"Défilement sur les recherches (Ctrl)\"\n  STR_RESEARCH_SCROLL_SPEED_CTRL_DESC: \"Les scientifiques peuvent être (dé)assignés directement en utilisant le défilement de la molette de la souris dans l'interface de recherche.\"\n  STR_MANUFACTURE_FILTER_SUPPLIES_OK: \"Filtre alternatif dans la fabrication\"\n  STR_MANUFACTURE_FILTER_SUPPLIES_OK_DESC: \"Si activé, l'interface montrera seulement les articles pour lesquels il y a assez de matériaux.\"\n  STR_MANUFACTURE_SCROLL_SPEED: \"Défilement sur les fabrications\"\n  STR_MANUFACTURE_SCROLL_SPEED_DESC: \"Les ingénieurs peuvent être (dé)assignés directement en utilisant le défilement de la molette de la souris.\"\n  STR_MANUFACTURE_SCROLL_SPEED_CTRL: \"Défilement sur les fabrications  (Ctrl)\"\n  STR_MANUFACTURE_SCROLL_SPEED_CTRL_DESC: \"Les ingénieurs peuvent être (dé)assignés directement en utilisant le défilement de la molette de la souris.\"\n  STR_PERSONAL_LAYOUT_INCLUDING_ARMOR: \"Inclure l'armure dans l'équipement perso\"\n  STR_PERSONAL_LAYOUT_INCLUDING_ARMOR_DESC: \"Si activé, l'armure portée est sauvegardée dans l'équipement personnel des soldats\"\n  STR_MANUALPROMOTIONS: \"Promotion manuelle\"\n  STR_MANUALPROMOTIONS_DESC: \"Si activé, les soldats peuvent être promus manuellement (ou rétrogradé) en cliquant sur l'icône de grade.\"\n  STR_WOUNDED_DEFEND_BASE_IF: \"Les blessés défendent (si la santé > x%)\"\n  STR_WOUNDED_DEFEND_BASE_IF_DESC: \"Les soldats blessés défendront également la base, si leur santé est au-dessus du seuil de santé donné.\"\n  STR_PLAY_BRIEFING_MUSIC_DURING_EQUIPMENT: \"Musique de briefing plus longtemps\"\n  STR_PLAY_BRIEFING_MUSIC_DURING_EQUIPMENT_DESC: \"La musique de briefing continuera durant la phase d'équipement jusqu'à ce que le Battlescape soit affiché.\"\n  STR_NIGHT_VISION_COLOR: \"Couleur de la vision nocturne\"\n  STR_NIGHT_VISION_COLOR_DESC: \"Valeur entre 1 et 15, chaque valeur représentant une teinte de couleur différente.\"\n  STR_AUTO_NIGHT_VISION_THRESHOLD: \"Seuil de vision nocturne automatique\"\n  STR_AUTO_NIGHT_VISION_THRESHOLD_DESC: \"S'il fait plus sombre que ce seuil, la vision nocturne sera activée automatiquement.\"\n  STR_SHOW_ACCURACY_ON_CROSSHAIR: \"Montrer la précision sur le réticule\"\n  STR_SHOW_ACCURACY_ON_CROSSHAIR_DESC: \"{ALT}0>{ALT}Jamais {ALT}1>{ALT}Seulement si l'extension du mode de précision X-COM est activé {ALT}2>{ALT}Toujours\"\n  STR_REACTION_FIRE_THRESHOLD: \"Seuil de tir de réaction\"\n  STR_AUTO_SELL: \"Gestionnaire de vente-auto\"\n  STR_AUTO_SELL_DESC: \"Sur l'écran de débriefing de bataille, tous les types d'articles vendus lors des batailles précédentes seront automatiquement marqués pour la vente.\"\n  STR_AUTOMATICPROMOTIONS: \"Promotions automatiques\"\n  STR_AUTOMATICPROMOTIONS_DESC: \"Si activé, les soldats seront automatiquement promus après une mission.\"\n  STR_OFF_CENTRE_SHOOTING: \"Tir excentré\"\n  STR_OFF_CENTRE_SHOOTING_DESC: \"Les soldats tenteront automatiquement d'ajuster légèrement leur angle de tir  dans le cas où il n'y a pas de ligne de tir.\"\n  STR_UNIFORM_SHOOTING_SPREAD: \"Dispersion des tirs uniforme\"\n  STR_CRASHED_OR_LANDED: \"Bouton Écrasé/Atterri\"\n  STR_CRASHED_OR_LANDED_DESC: \"Si activé, un bouton supplémentaire est affiché sur l'écran de Nouvelle bataille. Sinon, appuyez sur F11 pour afficher/masquer le bouton. {ALT}0>{ALT}Désactivé, {ALT}1>{ALT}Écrasé, {ALT}2>{ALT}Atterri.\"\n  STR_GRAPHS_ZOOM_IN: \"Zoomer (Graphs)\"\n  STR_GRAPHS_ZOOM_OUT: \"Dézoomer (Graphs)\"\n  STR_MARK_ALL_AS_SEEN: \"Marquer tout comme vu\"\n  STR_SELL_ALL: \"Ventre tout\"\n  STR_SELL_ALL_BUT_ONE: \"Vendre tout sauf un\"\n  STR_TRANSFER_ALL: \"Tout transférer\"\n  STR_REMOVE_SOLDIERS_FROM_ALL_CRAFTS: \"Retirer tous les soldats de tous les véhicules\"\n  STR_REMOVE_SOLDIERS_FROM_CRAFT: \"Retirer les soldats d'un véhicule\"\n  STR_REMOVE_EQUIPMENT_FROM_CRAFT: \"Retirer l'équipement d'un véhicule\"\n  STR_REMOVE_ARMOR_FROM_ALL_CRAFTS: \"Retirer toutes les armures de tous les véhicules\"\n  STR_REMOVE_ARMOR_FROM_CRAFT: \"Retirer toutes les armures du véhicule\"\n  STR_REMOVE_SOLDIERS_FROM_TRAINING: \"Retirer des soldats de l'entraînement\"\n  STR_ADD_SOLDIERS_TO_TRAINING: \"Ajouter des soldats à l'entraînement\"\n  STR_INVENTORY_ARMOR: \"Changer l'armure\"\n  STR_INVENTORY_AVATAR: \"Changer l'avatar\"\n  STR_ACTION_ITEM_1: \"Action d'objet 1 (Viser/Utiliser)\"\n  STR_ACTION_ITEM_2: \"Action d'objet 2 (Instantané)\"\n  STR_ACTION_ITEM_3: \"Action d'objet 1 (Auto)\"\n  STR_ACTION_ITEM_4: \"Action d'objet 4 (Mêlée)\"\n  STR_ACTION_ITEM_5: \"Action d'objet 5 (Lancer)\"\n  STR_INSTA_SAVE: \"Sauvegarde instantanée\"\n  STR_TOGGLE_QUICK_SEARCH: \"Champ de recherche rapide\"\n  STR_TOGGLE_NIGHT_VISION: \"Activer/Désactiver la vision nocturne\"\n  STR_HOLD_NIGHT_VISION: \"Brève vision nocturne\"\n  STR_SELECT_MUSIC_TRACK: \"Choisir la musique\"\n  STR_TOGGLE_TOUCH_BUTTONS: \"Activer/Désactiver les contrôles tactiles\"\n  STR_TOGGLE_BRIGHTNESS: \"Changer la luminosité (visuel seulement)\"\n  STR_BRIEFING: \"Briefing\"\n  STR_TOGGLE_DEBUG_MODE: \"Activer/Désactiver le mode débogage\"\n  STR_DEBUG_KILL_ALL_ALIENS: \"DEBUG: Tuer tous les aliens\"\n  STR_PHYSICAL_TRAINING: \"Entraînement martial\"\n  STR_REMAINING_TRAINING_FACILITY_CAPACITY: \"CAPACITÉ D'ENTRAÎNEMENT RESTANTE> {ALT}{0}\"\n  STR_NO_WOUNDED: \"-\"\n  STR_NO_QUEUED: \"+\"\n  STR_NO_DONE: \"FINI\"\n  STR_NO_AMMO: \"PAS DE MUNITIONS !\"\n  STR_START_FIRING: \"Feu !\"\n  STR_SKIP_FIRING: \"Laissez les entrer...\"\n  STR_ALIEN_MISSILES_HAVE_DAMAGED_OUR_BASE: \"Les extraterrestres ont endommagé notre base {0}\"\n  STR_ALIEN_MISSILES_HAVE_DESTROYED_OUR_BASE: \"Les extraterrestres ont détruit notre base {0}\"\n  STR_STARTING_CONDITION_COMMANDER: \"Cette mission requiert la présence du commandant.\"\n  STR_STARTING_CONDITION_CRAFT: \"Ce véhicule est inadapté à cette mission.\"\n  STR_STARTING_CONDITION_CRAFT_ALLOWED: \"Ce véhicule est inadapté à cette mission.{NEWLINE}{NEWLINE}Véhicules autorisés : {0}\"\n  STR_STARTING_CONDITION_CRAFT_FORBIDDEN: \"Ce véhicule est inadapté à cette mission.{NEWLINE}{NEWLINE}Véhicules interdits : {0}\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE: \"Certains soldats ne peuvent participer à cette mission.\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE_ALLOWED: \"Certains soldats ne peuvent participer à cette mission.{NEWLINE}{NEWLINE}Types de soldats autorisés : {0}\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE_FORBIDDEN: \"Certains soldats ne peuvent participer à cette mission.{NEWLINE}{NEWLINE}Types de soldats interdits : {0}\"\n  STR_STARTING_CONDITION_ITEM: \"Cette mission requiert certain(s) objet(s) spécifiques :{NEWLINE}{NEWLINE}{0}\"\n  STR_NOT_ENOUGH_FUEL_TO_REACH_TARGET: \"PLUS ASSEZ DE CARBURANT !{SMALLLINE}La destination est plus éloignée que la portée de ce véhicule.\"\n  STR_TOO_MANY_ITEMS_ONBOARD: \"TROP D'OBJETS !{SMALLLINE}Ce vaisseau ne peut pas transporter autant d'objets.\"\n  STR_ARMOR_NOT_ALLOWED_ONBOARD: \"ARMURE NON-AUTORISÉE !{SMALLLINE}Certains soldats portent des armures interdites.\"\n  STR_FOLLOW_WING_LEADER_QUESTION: \"Suivre le chef d'escadre ?\"\n  STR_ASSIGN_PILOTS: \"Assigner des pilotes...\"\n  STR_NOT_ENOUGH_PILOTS: \"Pas assez de pilotes !{NEWLINE}Minimum: {0}\"\n  STR_DAILY_PILOT_EXPERIENCE: \"Expérience de pilotage journalière\"\n  STR_UFO_SHIELD_HIT: \"BOUCLIERS TOUCHÉS !\"\n  STR_UFO_HIT_NO_DAMAGE: \"REBOND SUR LA COQUE !\"\n  STR_UFO_SHIELD_DOWN: \"BOUCLIERS ENNEMIS DÉSACTIVÉS !\"\n  STR_UFO_HIT_GLANCING: \"EFFLEUREMENT !\"\n  STR_INTERCEPTOR_SHIELD_HIT: \"NOS BLOUCLIERS TIENNENT !\"\n  STR_TRACTOR_BEAM_ENGAGED: \"FAISCEAU TRACTEUR ENGAGÉ !\"\n  STR_TRACTOR_BEAM_DISENGAGED: \"DÉSENGAGEMENT DU FAISCEAU TRACTEUR !\"\n  STR_SELF_DESTRUCT_ACTIVATED: \"AUTO-DESTRUCTION ACTIVÉE !\"\n  STR_SELF_DESTRUCT_CANCELLED: \"AUTO-DESTRUCTION DÉSACTIVÉE !\"\n  STR_MISSILE_DAMAGED: \">>> MISSILE ENDOMMAGÉ <<<\"\n  STR_MISSILE_DESTROYED: \">>> MISSILE DÉTRUIT <<<\"\n  STR_EXTENDED_LINKS: \"Liens\"\n  STR_AUTO_PATROL: \"PATROUILLE-AUTO\"\n  STR_ETA: \"ETA>{ALT}{0}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_FACILITY_AT_BASE: \"Pas assez de {0} pour réarmer {1} à {2}\"\n  STR_UFO_STARTED_HUNTING: \"{0} est sur une trajectoire d'interception avec {1}\"\n  STR_CRAFT_IS_READY: \"{0} à {1} est prêt.\"\n  STR_ECONOMY_WARNING: \"Les fonds {0} et les revenus {1} sont bas et la maintenance {2} est trop élevée ! Vendez quelque-chose pour éviter à devoir prendre un crédit... fonds manquants : {3}\"\n  STR_SLACKING_INDICATOR: \"{0}:{1}\"\n  STR_TRAINING_INDICATOR: \"{0}:{1}\"\n  STR_EXTENDED_UC: \"ÉTENDU\"\n  STR_RETURNING: \"RETOUR\"\n  STR_INTERCEPTING: \"INTERCEPTE\"\n  STR_ESCORTING: \"ESCORTE\"\n  STR_EN_ROUTE: \"EN ROUTE\"\n  STR_PILOT_MISSING: \"PILOTE MANQUANT\"\n  STR_DAY_SHORT: \"{0}j\"\n  STR_HOUR_SHORT: \"{0}h\"\n  STR_PERFORMANCE_BONUS: \"Bonus de performance\"\n  STR_COUNTRY_HAS_CANCELLED_A_SECRET_PACT: \"{0} a renoncé à son pacte avec les forces extraterrestres et a été autorisé à rejoindre le projet.\"\n  STR_COUNTRIES_HAVE_CANCELLED_A_SECRET_PACT: \"{0} ont renoncé à leur pacte avec les forces extraterrestres et ont été autorisé à rejoindre le projet.\"\n  STR_WE_CAN_NOW_RENT: \"Nous pouvons désormais louer\"\n  STR_REQUIRED_BASE_SERVICES: \"Requère les services de base: {0}\"\n  STR_WE_CAN_NOW_BUILD: \"Nous pouvons désormais construire\"\n  STR_WE_CAN_NOW_PURCHASE: \"Nous pouvons désormais acheter :\"\n  STR_NOT_ENOUGH_LIVING_SPACE_AT_BASE: \"Pas assez d'espace de vie pour accueillir{NEWLINE}{0}{NEWLINE}à{NEWLINE}{1}\"\n  STR_INFO: \"INFO\"\n  STR_DESPAWN_PENALTY: \"Pénalité de disparition> {0}\"\n  STR_TRAINING_FINISHED: \"Entrainement terminé{NEWLINE}à {0}\"\n  STR_PSI_TRAINING_FINISHED: \"Entrainement PSI terminée{NEWLINE}à {0}\"\n  STR_IGNORE_UC: \"IGNORER\"\n  STR_UFO_TRACKER: \"Suivi des OVNIs\"\n  STR_UPDATE: \"Mise à jour\"\n  STR_LATEST_VERSION_INFO: \"Vous utilisez la dernière version de OpenXcom.\"\n  STR_MASTER_MOD_VERSION_REQUIRED_QUESTION: \"Ce mod nécessite le jeu de base v{0} pour s'exécuter correctement. Activer ce mod ?\"\n  STR_VERSION_REQUIRED_QUESTION: \"Ce mod nécessite OXCE v{0} pour s'exécuter correctement. Activer ce mod ?\"\n  STR_OPEN_MODS_FOLDER: \"Ouvrir\"\n  STR_GLOBE_TEXTURE: \"Texture du globe\"\n  STR_NOTES: \"Notes\"\n  STR_NEW_NOTE: \"<NOUVELLE NOTE>\"\n  STR_ENGINE_OXC: \"OXC\"\n  STR_ENGINE_OXCE: \"OXCE\"\n  STR_ENGINE_OTHER: \"AUTRE\"\n  STR_BASESCAPE: \"Plan de la base\"\n  STR_AI: \"IA\"\n  STR_PATH_ENERGY_COST: \"Énergie\"\n  STR_PATH_ENERGY_COST_DESC: \"Un clique montre l'énergie restante de votre unité après avoir bougé à cette destination.\"\n  STR_VEHICLES_LOST: \"Véhicules perdus\"\n  STR_CRAFT_LOST_DOGFIGHT: \"Intercepteurs perdus\"\n  STR_CRAFT_LOST_MISSION: \"Transports perdus\"\n  STR_ALIEN_BASES_DESTROYED: \"Bases alien détruites\"\n  STR_XCOM_BASES_LOST: \"Bases perdues\"\n  STR_TEST_SCREEN: \"ÉCRAN DE TEST\"\n  STR_PALETTE: \"Palette :\"\n  STR_PREVIEW: \"Aperçu\"\n  STR_TINY_BORDERLESS: \"Minuscule, sans bordure\"\n  STR_TINY_BORDER: \"Minuscule\"\n  STR_SMALL_LOW_CONTRAST: \"Petit\"\n  STR_SMALL_HIGH_CONTRAST: \"Petit, fort contraste\"\n  STR_BIG_LOW_CONTRAST: \"Grand\"\n  STR_BIG_HIGH_CONTRAST: \"Grand, fort contraste\"\n  STR_TEST_CASE: \"Cas de test :\"\n  STR_RUN: \"Lancer le test sélectionné !\"\n  STR_TESTS_STARTING: \"Démarrage...\"\n  STR_TESTS_ERRORS_FOUND: \"Nombre total d'erreurs trouvées (il peut y avoir des doublons) : {0}\"\n  STR_TESTS_NO_ERRORS_FOUND: \"Aucune erreur trouvée.\"\n  STR_TESTS_FINISHED: \"Terminé.\"\n  STR_DETAILED_INFO_IN_LOG_FILE: \"Les informations détaillées ont été sauvegardées dans openxcom.log\"\n  STR_RANK_NONE: \"-\"\n  STR_DAMAGE_NONE: \"AUCUN\"\n  STR_INFO_UFOPEDIA: \"INFO\"\n  STR_COCKPIT_CAPACITY: \"PILOTES> {ALT}{0}{ALT}\"\n  STR_MAXIMUM_RANGE: \"PORTÉE MAXIMALE> {ALT}{0}{ALT}\"\n  STR_MINIMUM_RANGE: \"PORTÉE MIN> {ALT}{0}{ALT}\"\n  STR_INFINITE_RANGE: \"N/A\"\n  STR_TRACTOR_BEAM_POWER: \"Puissance\"\n  STR_WEIGHT_PEDIA1: \"Pds: {0}\"\n  STR_WEIGHT_PEDIA2: \"Pds: {0}/{1}\"\n  STR_SHOT_TYPE_MELEE: \"Mêlée\"\n  STR_ACCURACY_MODIFIER: \"Modificateur de Précision> {ALT} {0}\"\n  STR_POWER_BONUS: \"Bonus de Puissance> {ALT} {0}\"\n  STR_MULTIPLE_DIFFERENT_BONUSES: \"bonus multiples dépendants des munitions\"\n  STR_STATS_FOR_NERDS: \"Nerds pour les Nerds\"\n  STR_ARTICLE: \"Article> {ALT} {0}\"\n  STR_COMPATIBLE_AMMO: \"Munitions compatibles:\"\n  STR_BUILT_IN_ITEMS: \"Objets intégrés :\"\n  STR_CLIP_SIZE_UNLIMITED: \"illimité\"\n  STR_SHOTGUN_BEHAVIOR_OXCE: \"étendu\"\n  STR_INCLUDE_DEBUG: \"DEBUG\"\n  STR_INCLUDE_IDS: \"IDs\"\n  STR_INCLUDE_DEFAULTS: \"PARAMÈTRES PAR DÉFAUT\"\n  STR_TRUE: \"vrai\"\n  STR_FALSE: \"faux\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH: \"TALENT PSI*FORCE PSI\"\n  STR_STRENGTH_AND_MELEE_ACCURACY: \"FORCE*PRÉCISION EN MÊLÉE\"\n  STR_STRENGTH_AND_THROWING_ACCURACY: \"FORCE*THROWING ACCURACY\"\n  STR_FIRING_ACCURACY_AND_REACTIONS: \"PRÉCISION AU TIR*RÉACTIONS\"\n  STR_HEALTH_CURRENT: \"SANTÉ ACTUELLE\"\n  STR_MANA_CURRENT: \"MANA ACTUEL\"\n  STR_TIME_UNITS_CURRENT: \"UNITÉS DE TEMPS ACTUELLES\"\n  STR_STUN_LEVEL_CURRENT: \"NIVEAU ACTUEL D'ÉTOURDISSEMENT\"\n  STR_HEALTH_NORMALIZED: \"SANTÉ NORMALISÉE\"\n  STR_MANA_NORMALIZED: \"MANA NORMALISÉ\"\n  STR_TIME_UNITS_NORMALIZED: \"UNITÉS DE TEMPS NORMALISÉES\"\n  STR_ENERGY_NORMALIZED: \"ÉNERGIE NORMALISÉE\"\n  STR_MORALE_NORMALIZED: \"MORAL NORMALISÉ\"\n  STR_STUN_LEVEL_NORMALIZED: \"NIVEAU D'ÉTOURDISSEMENT NORMALISÉ \"\n  STR_ENERGY_REGENERATION: \"RÉCUPÉRATION D'ÉNERGIE\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH_ABBREVIATION: \"PCO*PFO\"\n  STR_STRENGTH_AND_MELEE_ACCURACY_ABBREVIATION: \"FOR*MÊL\"\n  STR_STRENGTH_AND_THROWING_ACCURACY_ABBREVIATION: \"FOR*LAN\"\n  STR_FIRING_ACCURACY_AND_REACTIONS_ABBREVIATION: \"PRÉ*RÉA\"\n  STR_HEALTH_CURRENT_ABBREVIATION: \"SANTÉ ACTUELLE\"\n  STR_MANA_CURRENT_ABBREVIATION: \"MANA ACTUEL\"\n  STR_TIME_UNITS_CURRENT_ABBREVIATION: \"UNITÉS DE TEMPS ACTUELLES\"\n  STR_STUN_LEVEL_CURRENT_ABBREVIATION: \"NIVEAU ACTUEL D'ÉTOURDISSEMENT\"\n  STR_HEALTH_NORMALIZED_ABBREVIATION: \"SANTÉ NORMALISÉE\"\n  STR_MANA_NORMALIZED_ABBREVIATION: \"MANA NORMALISÉ\"\n  STR_TIME_UNITS_NORMALIZED_ABBREVIATION: \"UNITÉS DE TEMPS NORMALISÉES\"\n  STR_ENERGY_NORMALIZED_ABBREVIATION: \"ÉNERGIE NORMALISÉE\"\n  STR_MORALE_NORMALIZED_ABBREVIATION: \"MORAL NORMALISÉ\"\n  STR_STUN_LEVEL_NORMALIZED_ABBREVIATION: \"NIVEAU D'ÉTOURDISSEMENT NORMALISÉ \"\n  STR_ENERGY_REGENERATION_ABBREVIATION: \"RÉCUPÉRATION D'ÉNERGIE\"\n  STR_TIME_UNITS_SCALED: \"UNITÉS DE TEMPS ÉCHELONNÉES\"\n  STR_STAMINA_SCALED: \"ENDURANCE ÉCHELONNÉE\"\n  STR_HEALTH_SCALED: \"SANTÉ ÉCHELONNÉE\"\n  STR_BRAVERY_SCALED: \"COURAGE ÉCHELONNÉ\"\n  STR_REACTIONS_SCALED: \"RÉACTIONS ÉCHELONNÉES\"\n  STR_FIRING_ACCURACY_SCALED: \"PRÉCISION DE TIR ÉCHELONNÉE\"\n  STR_THROWING_ACCURACY_SCALED: \"PRÉCISION DE LANCER ÉCHELONNÉE\"\n  STR_STRENGTH_SCALED: \"FORCE ÉCHELONNÉE\"\n  STR_PSIONIC_STRENGTH_SCALED: \"FORCE PSIONIQUE ÉCHELONNÉE\"\n  STR_PSIONIC_SKILL_SCALED: \"COMPÉTENCE PSIONIQUE ÉCHELONNÉE\"\n  STR_MELEE_ACCURACY_SCALED: \"PRÉCISION DE MÊLÉE ÉCHELONNÉE\"\n  STR_MANA_POOL_SCALED: \"RÉSERVOIR DE MANA ÉCHELONNÉ\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH_SCALED: \"COMPÉTENCE PSIONIQUE * FORCE PSIONIQUE ÉCHELONNÉ\"\n  STR_STRENGTH_AND_MELEE_ACCURACY_SCALED: \"FORCE * PRÉCISION EN MÊLÉE ÉCHELONNÉ\"\n  STR_STRENGTH_AND_THROWING_ACCURACY_SCALED: \"FORCE * PRÉCISION DE LANCER ÉCHELONNÉ\"\n  STR_FIRING_ACCURACY_AND_REACTIONS_SCALED: \"PRÉCISION DE TIR * RÉACTIONS ÉCHELONNÉ\"\n  STR_TIME_UNITS_SCALED_ABBREVIATION: \"UT ÉCHELONNÉ\"\n  STR_STAMINA_SCALED_ABBREVIATION: \"END ÉCHELONNÉ\"\n  STR_HEALTH_SCALED_ABBREVIATION: \"PV ÉCHELONNÉ\"\n  STR_BRAVERY_SCALED_ABBREVIATION: \"COU ÉCHELONNÉ\"\n  STR_REACTIONS_SCALED_ABBREVIATION: \"RÉA ÉCHELONNÉ\"\n  STR_FIRING_ACCURACY_SCALED_ABBREVIATION: \"TIR ÉCHELONNÉ\"\n  STR_THROWING_ACCURACY_SCALED_ABBREVIATION: \"LAN ÉCHELONNÉ\"\n  STR_STRENGTH_SCALED_ABBREVIATION: \"FOR ÉCHELONNÉ\"\n  STR_PSIONIC_STRENGTH_SCALED_ABBREVIATION: \"PFO ÉCHELONNÉ\"\n  STR_PSIONIC_SKILL_SCALED_ABBREVIATION: \"PCO ÉCHELONNÉ\"\n  STR_MELEE_ACCURACY_SCALED_ABBREVIATION: \"MÊL ÉCHELONNÉ\"\n  STR_MANA_POOL_SCALED_ABBREVIATION: \"MAN ÉCHELONNÉ\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH_SCALED_ABBREVIATION: \"PCO*PFO ÉCHELONNÉ\"\n  STR_STRENGTH_AND_MELEE_ACCURACY_SCALED_ABBREVIATION: \"FOR*MÊL ÉCHELONNÉ\"\n  STR_STRENGTH_AND_THROWING_ACCURACY_SCALED_ABBREVIATION: \"FOR*LAN ÉCHELONNÉ\"\n  STR_FIRING_ACCURACY_AND_REACTIONS_SCALED_ABBREVIATION: \"TIR*RÉA ÉCHELONNÉ\"\n  STR_COST_TIME: \"temps\"\n  STR_COST_ENERGY: \"énergie\"\n  STR_COST_MORALE: \"moral\"\n  STR_COST_HEALTH: \"santé\"\n  STR_COST_STUN: \"étourdissement\"\n  STR_COST_MANA: \"mana\"\n  STR_COST_BUILD: \"construire\"\n  STR_COST_REFUND: \"remboursé\"\n  STR_DAMAGE_10: \"10\"\n  STR_DAMAGE_11: \"11\"\n  STR_DAMAGE_12: \"12\"\n  STR_DAMAGE_13: \"13\"\n  STR_DAMAGE_14: \"14\"\n  STR_DAMAGE_15: \"15\"\n  STR_DAMAGE_16: \"16\"\n  STR_DAMAGE_17: \"17\"\n  STR_DAMAGE_18: \"18\"\n  STR_DAMAGE_19: \"19\"\n  STR_NAUTICAL_MILES: \"{0} milles nautiques\"\n  STR_KILOMETERS_PER_HOUR: \"{0} km/h\"\n  STR_SECONDS_LONG: \"{0} secondes\"\n  STR_RACE_BONUS: \"Bonus racial\"\n  STR_FOR_DIFFICULTY: \"pour la difficulté : {0}\"\n  STR_NOT_AWARDED_YET: \"Pas encore attribué\"\n"
  },
  {
    "path": "bin/common/Language/OXCE/hu.yml",
    "content": "hu:\n  STR_CANNOT_DISMANTLE_FACILITY_UPGRADING: \"A LÉTESÍTMÉNY NEM LEBONTHATÓ!{SMALLLINE}A létesítményt fejlesztés alatt nem tudjuk eltávolítani. \"\n  STR_CANNOT_UPGRADE_FACILITY_ALREADY_UPGRADING: \"NEM ÉPÍTHETSZ IDE!{SMALLLINE}Az itt lévő létesítményre már építenek.\"\n  STR_CANNOT_UPGRADE_FACILITY_WRONG_SIZE: \"NEM ÉPÍTHETSZ IDE!{SMALLLINE}A kiválasztott létesítménynek teljesen fednie kell a meglévőt.\"\n  STR_CANNOT_UPGRADE_FACILITY_WRONG_TYPE: \"NEM ÉPÍTHETSZ IDE!{SMALLLINE}Az itt lévő létesítmény nem fejleszthető a kiválasztottal.\"\n  STR_CANNOT_UPGRADE_FACILITY_DISALLOWED: \"NEM ÉPÍTHETSZ IDE!{SMALLLINE}Az itt lévő létesítményre nem lehet építeni.\"\n  STR_CANNOT_BUILD_QUEUE_OFF: \"NEM ÉPÍTHETSZ IDE!{SMALLLINE}A környező létesítmények építését előbb be kell fejezni.\"\n  STR_FACILITY_FORBIDDEN_BY_OTHER: \"NEM ÉPÍTHETSZ IDE!{SMALLLINE}Már létező létesítmények kizárják e létesítmény építését.\"\n  STR_FACILITY_OTHER_FORBIDDEN_BY_THIS: \"NEM ÉPÍTHETSZ IDE!{SMALLLINE}E létesítmény megléte kizárna más, már meglévő létesítményeket.\"\n  STR_ID: \"ID\"\n  STR_FIRST_LETTER: \"ELSŐ BETŰ\"\n  STR_SOLDIER_TYPE: \"KATONA TÍPUSA\"\n  STR_MANA: \"MANA\"\n  STR_MANA_POOL: \"MANA POOL\"\n  STR_MANA_MISSING: \"MANA HIÁNYZIK\"\n  STR_LOAD_CRAFT_LOADOUT_TEMPLATE: \"Jármű felszerelésének betöltése\"\n  STR_EMPTY_SLOT_N: \"Üres hely {0}\"\n  STR_UNNAMED_SLOT_N: \"Névtelen hely {0}\"\n  STR_SAVE_CRAFT_LOADOUT_TEMPLATE: \"Jármű felszerelésének mentése\"\n  STR_SAVE_UC: \"MENTÉS\"\n  STR_ALL: \"Minden\"\n  STR_EQUIPPED: \"Felszerelt\"\n  STR_UNASSIGNED: \"Egyéb\"\n  STR_PILOTS: \"PILÓTÁK\"\n  STR_SHIELD: \"PAJZS>{ALT}{0}\"\n  STR_SELECT_PILOT: \"Pilóta választása\"\n  STR_PILOTS_FOR_CRAFT: \"{0} Pilótája (Pilótái)\"\n  STR_PILOTS_REQUIRED: \"Szükséges pilóta (pilóták): {ALT}{0}\"\n  STR_ADD_PILOT: \"Pilóta hozzárendelése\"\n  STR_REMOVE_ALL_PILOTS: \"Összes pilóta eltávolítása\"\n  STR_ACCURACY_BONUS: \"Pontossági bónusz:\"\n  STR_DODGE_BONUS: \"Kitérési bónusz:\"\n  STR_APPROACH_SPEED: \"Elfogási sebesség:\"\n  STR_COWARDLY: \"Gyáva (-50%)\"\n  STR_NORMAL: \"Normál\"\n  STR_BOLD: \"Bátor (+50%)\"\n  STR_VERY_BOLD: \"Vakmerő (+100%)\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW: \"Előnézet\"\n  STR_REFUND_VALUE: \"Eladási érték>{ALT}{0}\"\n  STR_PRODUCTION_OVERVIEW: \"TERMELÉS ÁTTEKINTÉSE\"\n  STR_RESEARCH_OVERVIEW: \"KUTATÁS ÁTTEKINTÉSE\"\n  STR_KILL_SELECTED: \"Megöl\"\n  STR_SELL_SELECTED: \"Elad\"\n  STR_GO_TO_TRANSFERS: \"Transzfer...\"\n  STR_TOPIC: \"Téma>{ALT}{0}\"\n  STR_SHOW_ALL: \"Összes mutatása\"\n  STR_NO_DEPENDENCIES: \"Nincs követelmény.\"\n  STR_DIRECT_DEPENDENCIES: \"Direkt követelmények\"\n  STR_LEVEL_2_DEPENDENCIES: \"2-es szintű követelmények\"\n  STR_LEVEL_3_DEPENDENCIES: \"3-as szintű követelmények\"\n  STR_LEVEL_4_DEPENDENCIES: \"4-es szintű követelmények\"\n  STR_MORE_DEPENDENCIES: \"Vannak még mélyebb követelmények...\"\n  STR_END_OF_SEARCH: \"Keresés vége.\"\n  STR_REFUND_PRODUCTION: \"VISSZATÉRÍTÉS!\"\n  STR_PERSON_JOINING: \"Csatlakozó Személy\"\n  STR_RANDOM_PRODUCTION_DISCLAIMER: \"Véletlenszerű termelés\"\n  STR_OTHER_EMPLOYEES: \"Egyéb Személyzet és Felszerelés\"\n  STR_SHOW_ONLY_NEW: \"Csak az újat mutasd\"\n  STR_FILTER_DEFAULT: \"Alapvető\"\n  STR_FILTER_DEFAULT_SUPPLIES_OK: \"Alapvető (ellátmány OK)\"\n  STR_FILTER_DEFAULT_NO_SUPPLIES: \"Alapvető (nincs ellátmány)\"\n  STR_FILTER_FACILITY_REQUIRED: \"Hiányzó Létesítmény\"\n  STR_FILTER_HIDDEN: \"Rejtett\"\n  STR_FILTER_EQUIPPED: \"Felszerelt\"\n  STR_SORT_DEFAULT: \"Alapvető\"\n  STR_RANDOM_PRODUCTION_SUMMARY: \"Összegzés\"\n  STR_NOT_ENOUGH_PRISON_SPACE: \"NINCS ELÉG IDEGEN TÁROLÓ!{SMALLLINE}Építs új idegen tárolót vagy csoportosíts át idegeneket a többi bázisodra.\"\n  STR_NOT_ENOUGH_CRAFT_SPACE: \"Nincs elég hely a fedélzeten!\"\n  STR_SELECT_AVATAR_FOR: \"VÁLASSZ KINÉZETET:{NEWLINE}{0}\"\n  STR_SOLDIER_BONUSES_FOR: \"KATONAI BÓNUSZOK:{NEWLINE}{0}\"\n  STR_SUMMARY: \"Összegzés\"\n  STR_MANA_RECOVERY: \"MANA VISSZANYERÉS> {ALT}{0}\"\n  STR_BONUSES_BUTTON: \"+\"\n  STR_KILLER_AND_WEAPON: \"{0}, {1}\"\n  STR_TRAINING: \"Kiképzés\"\n  STR_SOLDIER_INFO: \"Katona Infója\"\n  STR_TRANSFER_TIME: \"Transzferidő>{ALT}{0}\"\n  STR_RECOVERY_TIME: \"Felépülés ideje>{ALT}{0}\"\n  STR_CURRENT_STATS: \"Jelenlegi Statok\"\n  STR_CHANGES: \"Változások\"\n  STR_CHANGES_MIN: \"Változás (min)\"\n  STR_CHANGES_MAX: \"Változás (max)\"\n  STR_BONUS_STATS: \"Bónusz adatok\"\n  STR_GRAND_TOTAL: \"Totál\"\n  STR_AVAILABLE_TOPICS: \"RENDELKEZÉSRE ÁLLÓ TÉMÁK\"\n  STR_QS_THREE_LETTERS_A: \"Kérlek írj be legalább 3 betűt\"\n  STR_QS_THREE_LETTERS_B: \"a Gyorskeresőbe...\"\n  STR_M_FLAG: \"[m]\"\n  STR_F_FLAG: \"[f]\"\n  STR_I_FLAG: \"[i]\"\n  STR_TECH_TREE_VIEWER: \"Tech Fa Áttekintés\"\n  STR_SELECT_TOPIC: \"Válassz Témát\"\n  STR_RESEARCH_PROGRESS: \"Státusz>{ALT}{0}%\"\n  STR_ITEM_DESTROYED: \"Elpusztított tárgy:\"\n  STR_ITEM_REQUIRED: \"Szükséges tárgy:\"\n  STR_SERVICES_REQUIRED: \"Szükséges szolgáltatások:\"\n  STR_SERVICES_PROVIDED: \"Nyújtott szolgáltatások:\"\n  STR_SERVICES_FORBIDDEN: \"Tiltott szolgáltatások:\"\n  STR_REQUIRES: \"Szükséges:\"\n  STR_DEPENDS_ON: \"Függ ettől:\"\n  STR_UNLOCKED_BY: \"Elérhetővé válik ettől:\"\n  STR_DISABLED_BY: \"Elérhetetlenné válik ettől:\"\n  STR_GET_FOR_FREE_FROM: \"Ingyen megkapod ettől:\"\n  STR_REQUIRED_BY: \"Szükséges ehhez:\"\n  STR_LEADS_TO: \"Vezet ehhez:\"\n  STR_UNLOCKS: \"Elérhetővé teszi ezt:\"\n  STR_DISABLES: \"Elérhetetlenné teszi ezt:\"\n  STR_GIVES_ONE_FOR_FREE_SEQ: \"Egyet ad ingyen (sorban):\"\n  STR_GIVES_ONE_FOR_FREE: \"Egyet ad ingyen:\"\n  STR_RESEARCH_REQUIRED: \"Szükséges kutatás:\"\n  STR_RESEARCH_REQUIRED_USE: \"Szükséges kutatás (használathoz):\"\n  STR_RESEARCH_REQUIRED_BUY: \"Szükséges kutatás (vételhez):\"\n  STR_SERVICES_REQUIRED_BUY: \"Szükséges szolgáltatások (vételhez):\"\n  STR_MATERIALS_REQUIRED: \"Szükséges alapanyagok:\"\n  STR_ITEMS_PRODUCED: \"Legyártott tárgyak:\"\n  STR_PERSON_RECRUITED: \"Toborzott személy:\"\n  STR_UNLOCKS_MISSIONS: \"Megnyitja a küldetéseket:\"\n  STR_DISABLES_MISSIONS: \"Elérhetetlenné teszi a küldetéseket:\"\n  STR_AFFECTS_GAME_PROGRESSION: \"Hatással van a játékmenetre!\"\n  STR_ITEMS_AT_DESTINATION: \"Tárgyak a célállomáson\"\n  STR_MUST_USE_BOTH_HANDS: \"Mindkét kéz szükséges ehhez!\"\n  STR_NOT_ENOUGH_MORALE: \"Nincs elég Morál!\"\n  STR_NOT_ENOUGH_HEALTH: \"Nincs elég Életerő!\"\n  STR_NOT_ENOUGH_MANA: \"Nincs elég Mana!\"\n  STR_NOT_ENOUGH_STUN: \"Túl magas a kábítás mértéke!\"\n  STR_LINE_OF_SIGHT_REQUIRED: \"Tűzvonal (LoS) szükséges.\"\n  STR_CENTER_ON_WOUNDED_FRIEND: \"Sérült Barát Középre\"\n  STR_CENTER_ON_DIZZY_FRIEND: \"Kábult Barát Középre\"\n  STR_BUG_HUNT_ACTIVATED: \"Csótányirtás mód aktiválva: az ellenfelek láthatók a minitérképen!\"\n  STR_TARGET_ENEMY: \"; Célpont = ELLENSÉG\"\n  STR_TARGET_NEUTRAL: \"; Célpont = SEMLEGES\"\n  STR_TARGET_FRIEND: \"; Célpont = BARÁT\"\n  STR_TARGET_YOURSELF: \"; Célpont = ÖNMAGAD\"\n  STR_TARGET_ON_THE_GROUND: \"(a padlón)\"\n  STR_USE_SPECIAL_ITEM: \"Spec. Tárgy Használata\"\n  STR_NO_EXPERIENCE_YET: \"Nincs tapasztalat még:\"\n  STR_OPERATION_UC: \"MŰVELET> {0}\"\n  STR_WHAT_CAN_I_WEAR: \"Mit viselhetek?\"\n  STR_STARTING_CONDITION_ARMORS_FORBIDDEN: \"Spec. felszerelés szükséges ehhez a küldetéshez.{NEWLINE}{NEWLINE}A tiltott páncél típusok: {0}\"\n  STR_STARTING_CONDITION_ARMORS_ALLOWED: \"Spec. felszerelés szükséges ehhez a küldetéshez.{NEWLINE}{NEWLINE}A megengedett páncél típusok: {0}\"\n  STR_MISSION_OVER: \"Küldetés végrehajtva.\"\n  STR_UNITS_WITH_FATAL_WOUNDS:\n    one: \"{N} emberünk még súlyosan sérült\"\n    other: \"{N} emberünk még súlyosan sérült\"\n  STR_END_MISSION_QUESTION: \"Befejezed a küldetést?\"\n  STR_LOOT: \"ZSÁKMÁNY\"\n  STR_SELL: \"ELADÁS\"\n  STR_LIVE_ALIENS_SURRENDERED: \"ELLENFELEK AKIK MEGADTÁK MAGUKAT\"\n  STR_MISSION_ABORTED: \"KÜLDETÉS MEGSZAKÍTVA\"\n  STR_BOUNTY: \"JUTALOM\"\n  STR_MANA_ABBREVIATION: \"MAN\"\n  STR_CANNOT_PLACE_ITEM_INTO_THIS_SECTION: \"Azt a tárgyat nem rakhatod oda.{NEWLINE}Ne kérdezd miért!\"\n  STR_ONE_HAND_MUST_BE_EMPTY: \"Legalább egy kéz szabad kell legyen!\"\n  STR_LOAD_EQUIPMENT_TEMPLATE: \"Felszerelési Sablon Betöltése\"\n  STR_SAVE_EQUIPMENT_TEMPLATE: \"Felszerelési Sablon Mentése\"\n  STR_FIRING_SHORT: \"Tüzelés>{ALT}{0}\"\n  STR_THROWING_SHORT: \"Dobás>{ALT}{0}\"\n  STR_MELEE_SHORT: \"Közelharc>{ALT}{0}\"\n  STR_HIT_LOG_NEW_TURN: \"Új Kör\"\n  STR_FAILED_CQB_CHECK: \"Az ellenfél megszakította a támadásod!\"\n  STR_NO_TRAJECTORY: \"Nincs lehetséges röppálya!\"\n  STR_HIT_LOG_NEW_BULLET: \"=>\"\n  STR_HIT_LOG_NO_DAMAGE: \"0\"\n  STR_HIT_LOG_SMALL_DAMAGE: \"találat\"\n  STR_HIT_LOG_BIG_DAMAGE: \"TALÁLAT\"\n  STR_HIT_LOG_REACTION_FIRE: \"Reakció lövés...\"\n  STR_HIT_LOG: \"Találati Napló\"\n  STR_BUTTON_10: \"10\"\n  STR_LAZY_LOADING: \"Lusta betöltés\"\n  STR_LAZY_LOADING_DESC: \"Ha engedélyezve van, a grafikus erőforrásokat csak szükség esetén töltjük be. Máskülönben minden betölt induláskor.\"\n  STR_UPDATE_CHECK: \"Frissitések automatikus ellenőrzése\"\n  STR_UPDATE_CHECK_DESC: \"Ha engedélyezve van, az OpenXcom automatikusan ellenőrzi az elérhető frissítéseket és felkínálja azok gyors telepítését.\"\n  STR_UFO_LANDING_ALERT: \"UFO leszállási értesítés\"\n  STR_UFO_LANDING_ALERT_DESC: \"Ha engedélyezed, egy üzenet ugrik fel mindig, mikor egy észlelt UFO leszáll.\"\n  STR_REMEMBER_DISABLED_CRAFT_WEAPONS: \"Kikapcsolt jármű fegyverzet megjegyzése\"\n  STR_REMEMBER_DISABLED_CRAFT_WEAPONS_DESC: \"A harc során kikapcsolt fegyverek kikapcsolva maradnak és a bázison sem kerülnek újratöltésre.\"\n  STR_HIGHLIGHT_NEW: \"Új témák kiemelése\"\n  STR_WOUNDED_DEFEND_BASE_IF: \"Védekező sebesültek (x% ÉP felett)\"\n  STR_WOUNDED_DEFEND_BASE_IF_DESC: \"Sebesült katonák is védik a bázist, ha az egészségük a megadott százalékpont felett van.\"\n  STR_PLAY_BRIEFING_MUSIC_DURING_EQUIPMENT: \"Értesítési zene hosszabban\"\n  STR_PLAY_BRIEFING_MUSIC_DURING_EQUIPMENT_DESC: \"Az Értesítési zene addig játszódik a háttérben a felszerelési fázis alatt míg el nem kezded a csatát.\"\n  STR_NIGHT_VISION_COLOR: \"Válassz Éjjellátó színt\"\n  STR_NIGHT_VISION_COLOR_DESC: \"1-15-ig tartó skála, minden érték más színárnyalatot jelöl.\"\n  STR_AUTO_NIGHT_VISION_THRESHOLD: \"Automata éjjellátó küszöbérték\"\n  STR_AUTO_NIGHT_VISION_THRESHOLD_DESC: \"Ha sötétebb, mint a küszöbérték, automatikusan bekapcsolja az éjjellátást.\"\n  STR_AUTO_SELL: \"Auto-Eladás Menedzser\"\n  STR_AUTO_SELL_DESC: \"A csataértékelés eladás részén minden olyan tárgyat eladásra jelöl, melyet előző csaták után eladtál.\"\n  STR_GRAPHS_ZOOM_IN: \"Közelítés (Gráfok)\"\n  STR_GRAPHS_ZOOM_OUT: \"Távolítás (Gráfok)\"\n  STR_MARK_ALL_AS_SEEN: \"Összeset Láttam\"\n  STR_SELL_ALL: \"Mindent elad\"\n  STR_SELL_ALL_BUT_ONE: \"Egyet megtart, többit elad\"\n  STR_REMOVE_SOLDIERS_FROM_ALL_CRAFTS: \"Katonák eltávolítása az összes gépről\"\n  STR_REMOVE_SOLDIERS_FROM_CRAFT: \"Katonák eltávolítása a gépről\"\n  STR_REMOVE_EQUIPMENT_FROM_CRAFT: \"Felszerelés eltávolítása a gépről\"\n  STR_REMOVE_ARMOR_FROM_ALL_CRAFTS: \"Páncél eltávolítása az összes gépről\"\n  STR_REMOVE_ARMOR_FROM_CRAFT: \"Páncél eltávolítása a gépről\"\n  STR_REMOVE_SOLDIERS_FROM_TRAINING: \"Katonák képzésének megszakítása\"\n  STR_INVENTORY_ARMOR: \"Páncélcsere\"\n  STR_INVENTORY_AVATAR: \"Kinézetváltás\"\n  STR_ACTION_ITEM_1: \"Tárgy Akció 1 (Célzott L./Használat)\"\n  STR_ACTION_ITEM_2: \"Tárgy Akció 2 (Kapás L.)\"\n  STR_ACTION_ITEM_3: \"Tárgy Akció 3 (Auto)\"\n  STR_ACTION_ITEM_4: \"Tárgy Akció 4 (Közelharc)\"\n  STR_ACTION_ITEM_5: \"Tárgy Akció 5 (Dobás)\"\n  STR_TOGGLE_QUICK_SEARCH: \"Gyorskeresés Kapcsoló\"\n  STR_TOGGLE_NIGHT_VISION: \"Éjjellátó Kapcsoló\"\n  STR_HOLD_NIGHT_VISION: \"Rövid Éjjellátó\"\n  STR_SELECT_MUSIC_TRACK: \"Zene Kiválasztása\"\n  STR_PHYSICAL_TRAINING: \"Harcművészeti Kiképzés\"\n  STR_REMAINING_TRAINING_FACILITY_CAPACITY: \"FENNMARADÓ KIKÉPZŐ KAPACITÁS>{ALT}{0}\"\n  STR_NO_WOUNDED: \"-\"\n  STR_NO_QUEUED: \"+\"\n  STR_NO_DONE: \"KÉSZ\"\n  STR_START_FIRING: \"Tűz!\"\n  STR_SKIP_FIRING: \"Hadd jöjjenek...\"\n  STR_ALIEN_MISSILES_HAVE_DAMAGED_OUR_BASE: \"Idegen torpedók megrongálták a bázist: {0}\"\n  STR_ALIEN_MISSILES_HAVE_DESTROYED_OUR_BASE: \"Idegen torpedók megsemmisítették a bázist: {0}\"\n  STR_STARTING_CONDITION_CRAFT: \"Ez a gép alkalmatlan erre a küldetésre.\"\n  STR_STARTING_CONDITION_CRAFT_ALLOWED: \"Ez a gép alkalmatlan erre a küldetésre.{NEWLINE}{NEWLINE}Alkalmas gépek: {0}\"\n  STR_STARTING_CONDITION_CRAFT_FORBIDDEN: \"Ez a gép alkalmatlan erre a küldetésre.{NEWLINE}{NEWLINE}Tiltott gépek: {0}\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE: \"Nem minden katona tud részt venni a küldetésen.\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE_ALLOWED: \"Nem minden katona tud részt venni a küldetésen.{NEWLINE}{NEWLINE}Engedélyezett katonatípusok: {0}\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE_FORBIDDEN: \"Nem minden katona tud részt venni a küldetésen.{NEWLINE}{NEWLINE}Tiltott katonatípusok: {0}\"\n  STR_STARTING_CONDITION_ITEM: \"A küldetéshez az alábbi spec. eszköz(ök)re van szükség:{NEWLINE}{NEWLINE}{0}\"\n  STR_ASSIGN_PILOTS: \"Pilóták kinevezése...\"\n  STR_NOT_ENOUGH_PILOTS: \"Nincs elég pilóta!{NEWLINE}Minimum:{0}\"\n  STR_UFO_SHIELD_HIT: \"PAJZSOT TALÁLT!\"\n  STR_UFO_HIT_NO_DAMAGE: \"LEPATTANT A HAJÓTESTRŐL!\"\n  STR_UFO_SHIELD_DOWN: \"ÁTTÖRTÜNK A PAJZSUKON!\"\n  STR_UFO_HIT_GLANCING: \"LEPATTANÓ TALÁLAT!\"\n  STR_INTERCEPTOR_SHIELD_HIT: \"A PAJZSAINK MÉG TARTANAK!\"\n  STR_TRACTOR_BEAM_ENGAGED: \"VONÓSUGÁR AKTÍV!\"\n  STR_TRACTOR_BEAM_DISENGAGED: \"A VONÓSUGÁR MEGSZŰNT\"\n  STR_SELF_DESTRUCT_ACTIVATED: \"ÖNMEGSEMMISíTÉS AKTIVÁLVA!\"\n  STR_SELF_DESTRUCT_CANCELLED: \"ÖNMEGSEMMISíTÉS LEÁLLÍTVA\"\n  STR_AUTO_PATROL: \"AUTO-ŐRJÁRAT\"\n  STR_UFO_STARTED_HUNTING: \"{0} elfogó pályára állt. A célpont {1}\"\n  STR_CRAFT_IS_READY: \"{0} készen áll itt: {1}.\"\n  STR_ECONOMY_WARNING: \"A tőke {0} és a bevétel {1} alacsony, a karbantartás {2} viszont nem! Adj el valamit hogy ne kelljen hitelt felvenned... a hiányzó összeg: {3}\"\n  STR_RETURNING: \"VISSZATÉR\"\n  STR_INTERCEPTING: \"ELFOGÓ PÁLYÁN\"\n  STR_ESCORTING: \"KÍSÉR\"\n  STR_EN_ROUTE: \"CÉLRA TART\"\n  STR_PILOT_MISSING: \"PILÓTA HIÁNYZIK\"\n  STR_DAY_SHORT: \"{0}d\"\n  STR_HOUR_SHORT: \"{0}h\"\n  STR_PERFORMANCE_BONUS: \"Teljesítmény Bónusz\"\n  STR_COUNTRY_HAS_CANCELLED_A_SECRET_PACT: \"{0} megtagadta az idegenekkel kötött paktumát és visszatért a projektbe.\"\n  STR_COUNTRIES_HAVE_CANCELLED_A_SECRET_PACT: \"{0} mind megtagadták az idegenekkel kötött paktumukat és visszatértek a projektbe.\"\n  STR_WE_CAN_NOW_RENT: \"Mostantól bérelhetünk\"\n  STR_REQUIRED_BASE_SERVICES: \"Szükséges bázis funkciók: {0}\"\n  STR_WE_CAN_NOW_BUILD: \"Mostantól építhetünk\"\n  STR_WE_CAN_NOW_PURCHASE: \"Mostantól vásárolhatunk\"\n  STR_NOT_ENOUGH_LIVING_SPACE_AT_BASE: \"Nincs elég személyzeti hely hogy elférjen{NEWLINE}{0}{NEWLINE}itt:{NEWLINE}{1}\"\n  STR_INFO: \"INFÓ\"\n  STR_TRAINING_FINISHED: \"A vépzés befejeződött:{NEWLINE}{0}\"\n  STR_UFO_TRACKER: \"UFO Követő\"\n  STR_UPDATE: \"Frissítés\"\n  STR_LATEST_VERSION_INFO: \"A legfrissebb OpenXcom verziót használod.\"\n  STR_VERSION_REQUIRED_QUESTION: \"Az OXCE v{0} szükséges ahhoz, hogy ez a mod megfelelően fusson. Engedélyezed ezt a modot?\"\n  STR_PATH_ENERGY_COST: \"Energia\"\n  STR_TEST_SCREEN: \"TESZT KÉPERNYŐ\"\n  STR_PALETTE: \"Paletta:\"\n  STR_PREVIEW: \"Előnézet\"\n  STR_TINY_BORDERLESS: \"Mini, keret nélkül\"\n  STR_TINY_BORDER: \"Mini\"\n  STR_SMALL_LOW_CONTRAST: \"Kicsi\"\n  STR_SMALL_HIGH_CONTRAST: \"Kicsi, magas kontraszt\"\n  STR_BIG_LOW_CONTRAST: \"Nagy\"\n  STR_BIG_HIGH_CONTRAST: \"Nagy, magas kontraszt\"\n  STR_TEST_CASE: \"Teszt eset:\"\n  STR_RUN: \"Kiválasztott teszt futtatása\"\n  STR_TESTS_STARTING: \"Indítás...\"\n  STR_TESTS_ERRORS_FOUND: \"Összes talált hiba (lehet közte egyforma): {0}\"\n  STR_TESTS_NO_ERRORS_FOUND: \"Nem találtunk hibát.\"\n  STR_TESTS_FINISHED: \"Befejezve.\"\n  STR_DETAILED_INFO_IN_LOG_FILE: \"Részletes info le lett mentve az openxcom.log-ba.\"\n  STR_RANK_NONE: \"-\"\n  STR_DAMAGE_NONE: \"NINCS\"\n  STR_INFO_UFOPEDIA: \"INFÓ\"\n  STR_COCKPIT_CAPACITY: \"PILÓTÁK>{ALT}{0}{ALT}\"\n  STR_MAXIMUM_RANGE: \"MAX HATÓTÁV>{ALT}{0}{ALT}\"\n  STR_MINIMUM_RANGE: \"MIN HATÓTÁV>{ALT}{0}{ALT}\"\n  STR_INFINITE_RANGE: \"N/A\"\n  STR_TRACTOR_BEAM_POWER: \"Erő\"\n  STR_WEIGHT_PEDIA1: \"Súly: {0}\"\n  STR_WEIGHT_PEDIA2: \"Súly: {0}/{1}\"\n  STR_SHOT_TYPE_MELEE: \"Közelharc\"\n  STR_ACCURACY_MODIFIER: \"Pontosság módosító>{ALT} {0}\"\n  STR_POWER_BONUS: \"Erő Bónusz>{ALT} {0}\"\n  STR_MULTIPLE_DIFFERENT_BONUSES: \"többféle bónusz különböző lőszereken\"\n  STR_STATS_FOR_NERDS: \"Statok kockáknak\"\n  STR_ARTICLE: \"Cikkszám>{ALT} {0}\"\n  STR_COMPATIBLE_AMMO: \"Használható lőszer:\"\n  STR_BUILT_IN_ITEMS: \"Beépített tárgyak:\"\n  STR_CLIP_SIZE_UNLIMITED: \"korlátlan\"\n  STR_SHOTGUN_BEHAVIOR_OXCE: \"bővített\"\n  STR_INCLUDE_DEBUG: \"DEBUG\"\n  STR_INCLUDE_IDS: \"IDk\"\n  STR_INCLUDE_DEFAULTS: \"ALAPÉRTÉKEK\"\n  STR_TRUE: \"igaz\"\n  STR_FALSE: \"hamis\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH: \"PSI ÜGYESSÉG*PSI ERŐ\"\n  STR_STRENGTH_AND_MELEE_ACCURACY: \"ERŐ*KÖZELHARCI PONTOSSÁG\"\n  STR_STRENGTH_AND_THROWING_ACCURACY: \"ERŐ*DOBÁSI PONTOSSÁG\"\n  STR_FIRING_ACCURACY_AND_REACTIONS: \"TÜZELÉSI PONTOSSÁG*REAKCIÓK\"\n  STR_HEALTH_CURRENT: \"JELENLEGI EGÉSZSÉG\"\n  STR_MANA_CURRENT: \"JELENLEGI MANA\"\n  STR_TIME_UNITS_CURRENT: \"JELENLEGI IDŐEGYSÉG\"\n  STR_STUN_LEVEL_CURRENT: \"JELENLEGI KÁBULTSÁGI SZINT\"\n  STR_HEALTH_NORMALIZED: \"NORMALIZÁLT EGÉSZSÉG\"\n  STR_MANA_NORMALIZED: \"NORMALIZÁLT MANA\"\n  STR_TIME_UNITS_NORMALIZED: \"NORMALIZÁLT IDŐEGYSÉG\"\n  STR_ENERGY_NORMALIZED: \"NORMALIZÁLT ENERGIA\"\n  STR_MORALE_NORMALIZED: \"NORMALIZÁLT MORÁL\"\n  STR_STUN_LEVEL_NORMALIZED: \"NORMALIZÁLT KÁBULTSÁGI SZINT\"\n  STR_ENERGY_REGENERATION: \"ENERGIATÖLTŐDÉS\"\n  STR_HEALTH_CURRENT_ABBREVIATION: \"JELENLEGI EGÉSZSÉG\"\n  STR_MANA_CURRENT_ABBREVIATION: \"JELENLEGI MANA\"\n  STR_TIME_UNITS_CURRENT_ABBREVIATION: \"JELENLEGI IDŐEGYSÉG\"\n  STR_STUN_LEVEL_CURRENT_ABBREVIATION: \"JELENLEGI KÁBULTSÁGI SZINT\"\n  STR_HEALTH_NORMALIZED_ABBREVIATION: \"NORMALIZÁLT EGÉSZSÉG\"\n  STR_MANA_NORMALIZED_ABBREVIATION: \"NORMALIZÁLT MANA\"\n  STR_TIME_UNITS_NORMALIZED_ABBREVIATION: \"NORMALIZÁLT IDŐEGYSÉG\"\n  STR_ENERGY_NORMALIZED_ABBREVIATION: \"NORMALIZÁLT ENERGIA\"\n  STR_MORALE_NORMALIZED_ABBREVIATION: \"NORMALIZÁLT MORÁL\"\n  STR_STUN_LEVEL_NORMALIZED_ABBREVIATION: \"NORMALIZÁLT KÁBULTSÁGI SZINT\"\n  STR_ENERGY_REGENERATION_ABBREVIATION: \"ENERGIATÖLTŐDÉS\"\n  STR_COST_TIME: \"idő\"\n  STR_COST_ENERGY: \"energia\"\n  STR_COST_MORALE: \"morál\"\n  STR_COST_HEALTH: \"egészség\"\n  STR_COST_STUN: \"kábultság\"\n  STR_COST_MANA: \"mana\"\n  STR_COST_BUILD: \"építés\"\n  STR_COST_REFUND: \"visszatérítés\"\n  STR_DAMAGE_10: \"10\"\n  STR_DAMAGE_11: \"11\"\n  STR_DAMAGE_12: \"12\"\n  STR_DAMAGE_13: \"13\"\n  STR_DAMAGE_14: \"14\"\n  STR_DAMAGE_15: \"15\"\n  STR_DAMAGE_16: \"16\"\n  STR_DAMAGE_17: \"17\"\n  STR_DAMAGE_18: \"18\"\n  STR_DAMAGE_19: \"19\"\n  STR_NAUTICAL_MILES: \"{0} tengeri mérföld\"\n  STR_KILOMETERS_PER_HOUR: \"{0} km/h\"\n  STR_SECONDS_LONG: \"{0} másodperc\"\n  STR_RACE_BONUS: \"Faji bónusz\"\n  STR_FOR_DIFFICULTY: \"nehézségért: {0}\"\n  STR_NOT_AWARDED_YET: \"Még nem érdemelted ki\"\n"
  },
  {
    "path": "bin/common/Language/OXCE/it.yml",
    "content": "it:\n  STR_CANNOT_DISMANTLE_FACILITY_UPGRADING: \"EDIFICIO NON SMANTELLABILE!{SMALLLINE}Gli edifici non possono essere rimossi durante il miglioramento.\"\n  STR_CANNOT_UPGRADE_FACILITY_ALREADY_UPGRADING: \"NON EDIFICABILE!{SMALLLINE}Un edificio è già stato costruito qui.\"\n  STR_CANNOT_UPGRADE_FACILITY_WRONG_SIZE: \"NON EDIFICABILE!{SMALLLINE}L'edificio selezionato deve coprire completamente un edificio esistente.\"\n  STR_CANNOT_UPGRADE_FACILITY_WRONG_TYPE: \"NON EDIFICABILE!{SMALLLINE}L'edificio esistente non può essere migliorato da un edificio selezionato.\"\n  STR_CANNOT_UPGRADE_FACILITY_DISALLOWED: \"NON EDIFICABILE!{SMALLLINE}Non è possibile costruire sopra l'edificio esistente.\"\n  STR_CANNOT_BUILD_QUEUE_OFF: \"NON EDIFICABILE!{SMALLLINE}Edifici connessi devono essere costruti.\"\n  STR_CANNOT_BUILD_UPGRADE_ONLY: \"NON EDIFICABILE!{SMALLLINE}Questa struttura può essere costruita solo come miglioramento ad un'altra struttura.\"\n  STR_FACILITY_FORBIDDEN_BY_OTHER: \"NON EDIFICABILE!{SMALLLINE}C'è un edificio pregresso che non permette di costruire.\"\n  STR_FACILITY_OTHER_FORBIDDEN_BY_THIS: \"NON EDIFICABILE!{SMALLLINE}C'è un edificio pregresso che non permetterà di costruire.\"\n  STR_NOT_ENOUGH_ITEMS: \"NON HAI ABBASTANZA MATERIALI!{SMALLLINE}Servono più risorse per costruire questa struttura.{NEWLINE}Mancante> {0}: {1}\"\n  STR_ID: \"ID\"\n  STR_FIRST_LETTER: \"PRIMA LETTERA\"\n  STR_SOLDIER_TYPE: \"TIPO SOLDATO\"\n  STR_IDLE_DAYS: \"GIORNI FERMO\"\n  STR_MANA: \"MANA\"\n  STR_MANA_POOL: \"MANA POOL\"\n  STR_MANA_MISSING: \"MANA MANCANTE\"\n  STR_LOAD_CRAFT_LOADOUT_TEMPLATE: \"Carica Stiva Salvata\"\n  STR_EMPTY_SLOT_N: \"Slot vuoto {0}\"\n  STR_UNNAMED_SLOT_N: \"Slot senza nome {0}\"\n  STR_ADD_ON_TOP: \"Aggiungi in cima\"\n  STR_SAVE_CRAFT_LOADOUT_TEMPLATE: \"Salva Stiva Salvata\"\n  STR_SAVE_UC: \"SALVA\"\n  STR_ALL: \"Tutto\"\n  STR_EQUIPPED: \"Equipaggiato\"\n  STR_NOT_EQUIPPED: \"Non equipaggiato\"\n  STR_UNASSIGNED: \"Altro\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED_BY_SIZE: \"NON PUOI AGGIUNGERE ALTRO EQUIPAGGIAMENTO!{SMALLLINE}Capacità di spazio massima: {0}\"\n  STR_PILOTS: \"PILOTI\"\n  STR_SHIELD: \"SCUDO>{ALT}{0}\"\n  STR_CRAFT_SKIN_ID: \"[{0}]\"\n  STR_SELECT_PILOT: \"Seleziona Pilota\"\n  STR_PILOTS_FOR_CRAFT: \"Pilota(i) per {0}\"\n  STR_PILOTS_REQUIRED: \"Pilota(i) necessari: {ALT}{0}\"\n  STR_ADD_PILOT: \"Aggiungi Pilota\"\n  STR_REMOVE_ALL_PILOTS: \"Rimuovi Piloti\"\n  STR_ACCURACY_BONUS: \"Bonus Precisione:\"\n  STR_DODGE_BONUS: \"Bonus Schivata:\"\n  STR_APPROACH_SPEED: \"Velocità avvicinamento:\"\n  STR_COWARDLY: \"Codardo (-50%)\"\n  STR_NORMAL: \"Normale\"\n  STR_BOLD: \"Audace (+50%)\"\n  STR_VERY_BOLD: \"Coraggioso (+100%)\"\n  STR_ARMOR_GROUP_NOT_ALLOWED: \"Questa tipologia di armatura non è consentita a bordo.\"\n  STR_SOLDIER_GROUP_NOT_ALLOWED: \"Questa tipologia di soldato non è consentita a bordo.\"\n  STR_SOLDIER_GROUP_NOT_SAME: \"Questa tipologia di soldato non è compatibile con altri soldati a bordo.\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW: \"Anteprima\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_SAVED: \"Anteprima *\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_BRIEFING: \"Questa funzione ti consente di vedere e customizzare lo shcieramento delle tue unità all'inizio di una battaglia. Hai punti movimento illimitati. Tieni premuto 'Alt' per evidenziare posizioni valide per le unità. Clicka sull'icona 'Interrompi Missione' per salvare uno schieramento personalizzato. Clicka sull'icona 'Fine Turno' per uscire dall'anteprima.{NEWLINE}Nota bene: aggiungere altri soldati o veicoli alla nave invalida automaticamente lo schieramento personalizzato salvato. Un asterisco sul pulsante 'Anteprima' indica la presenza di uno schieramento personalizzato.\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_BRIEFING_DUMMY: \"Questa funzione permette di visualizzare e modificare l'attuale schieramento per questo tipo di nave. Qualsiasi cambiamento sarà applicato ad ogni tipo di questa comprata o prodotta durante la campagna. Cominci con il massimo numero di soldati. Ogni soldato rappresenta una riga nella tabella di schieramento. I nomi dei soldati corrispondono ai numero di riga. Per fornire lo spazio per una unità 2x2, piazza 4 soldati in un area 2x2. Se lo spazio non viene settato, non saranno disponibili unità 2x2 durante le ver battaglie.\"\n  STR_BASE_DEFENSE_BRIEFING_PREVIEW: \"Questa funzione ti permette di vedere una anteprima della tua base.{NEWLINE}Divertiti!{NEWLINE}{NEWLINE}Clicka sull'icona 'Fine Turno' per uscire dall'anteprima\"\n  STR_NOT_ENOUGH_CARGO_SPACE: \"SPAZIO DI CARICO INSUFFICIENTE!{SMALLLINE}Usa un modulo diverso o riduci il numero di membri dell'equipaggio assegnati.\"\n  STR_NOT_ENOUGH_STORAGE_SPACE_1: \"SPAZIO DI MAGAZZINO INSUFFICIENTE!{SMALLLINE}Troppi oggetti! Usa un modulo diverso o riduci l'equipaggiamento assegnato.\"\n  STR_NOT_ENOUGH_STORAGE_SPACE_2: \"SPAZIO DI MAGAZZINO INSUFFICIENTE!{SMALLLINE}Gli oggetti occupano troppo spazio! Usa un modulo diverso o riduci le dimensioni dell'equipaggiamento assegnato.\"\n  STR_REFUND_VALUE: \"Valore vendite> {ALT}{0}\"\n  STR_REFUND_VALUE_NEGATIVE: \"Spese> {ALT}{0}\"\n  STR_PRODUCTION_OVERVIEW: \"PANORAMICA PRODUZIONE\"\n  STR_RESEARCH_DIARY: \"DIARIO RICERCA\"\n  STR_DISCOVERY_SOURCE_BASE: \"Questo oggetto è stato scoperto tramite un progetto di ricerca.{NEWLINE}Ricerca base> {ALT}{1}{ALT}{NEWLINE}Codice soggetto> {ALT}{0}{ALT}\"\n  STR_DISCOVERY_SOURCE_FREE_FROM: \"Questo oggetto è stato ottenuto gratuitamente da un altro progetto di ricerca.{NEWLINE}Da progetto ricerca> {ALT}{2}{ALT}{NEWLINE}{ALT}{1}{ALT} -> {ALT}{0}{ALT}\"\n  STR_DISCOVERY_SOURCE_FREE_AFTER: \"Questo oggetto tecnico è stato scoperto automaticamente.{NEWLINE}Dopo progetto ricerca> {ALT}{2}{ALT}{NEWLINE}{ALT}{1}{ALT} -> {ALT}{0}{ALT}\"\n  STR_DISCOVERY_SOURCE_MISSION: \"Questo oggetto è stato ottenuto gratuitamente come ricompensa per una missione.{NEWLINE}Tipo missione> {ALT}{2}{ALT}{NEWLINE}{ALT}{1}{ALT} -> {ALT}{0}{ALT}\"\n  STR_DISCOVERY_SOURCE_EVENT: \"Questo oggetto è stato ottenuto gratuitamente come ricompensa per un evento.{NEWLINE}Tipo evento> {ALT}{2}{ALT}{NEWLINE}{ALT}{1}{ALT} -> {ALT}{0}{ALT}\"\n  STR_RESEARCH_OVERVIEW: \"PANORAMICA RICERCA\"\n  STR_PRISONER_OVERVIEW: \"PANORAMICA PRIGIONIERI\"\n  STR_PRISONER: \"PRIGIONIERI\"\n  STR_PRISONER_AMOUNT: \"QUANTITÀ\"\n  STR_PRISONER_INTERROGATED: \"INTERROGATI\"\n  STR_TOTAL_IN_PRISON: \"Spazio Usato>{ALT}{0}\"\n  STR_TOTAL_INTERROGATED: \"Interrogati>{ALT}{0}\"\n  STR_PRISON_TYPE: \"Contenimento Alieni\"\n  STR_KILL_SELECTED: \"Uccidi\"\n  STR_SELL_SELECTED: \"Vendi\"\n  STR_GO_TO_TRANSFERS: \"Trasferimento...\"\n  STR_PRISON_CLEANUP: \"Pulizia prigione\"\n  STR_TOPIC: \"Argomento>{ALT} {0}\"\n  STR_SHOW_ALL: \"Mostra tutto\"\n  STR_NO_DEPENDENCIES: \"Nessuna dipendenza\"\n  STR_DIRECT_DEPENDENCIES: \"Dipendenza diretta\"\n  STR_LEVEL_2_DEPENDENCIES: \"Dipendenza Livello 2\"\n  STR_LEVEL_3_DEPENDENCIES: \"Dipendenza Livello 3\"\n  STR_LEVEL_4_DEPENDENCIES: \"Dipendenza Livello 4\"\n  STR_MORE_DEPENDENCIES: \"Ci sono dipendenze più profonde...\"\n  STR_END_OF_SEARCH: \"Fine ricerca.\"\n  STR_FALLBACK_PRODUCTION: \"RIPIEGO\"\n  STR_REFUND_PRODUCTION: \"RIMBORSO!\"\n  STR_HOURS_PER_UNIT: \"ORE PER UNITÀ>{ALT}{0}\"\n  STR_PERSON_JOINING: \"Aggiunta Persona\"\n  STR_RANDOM_PRODUCTION_DISCLAIMER: \"Produzione casuale!\"\n  STR_OTHER_EMPLOYEES: \"Altro Staff & Inventario\"\n  STR_SHOW_ONLY_NEW: \"Mostra solo nuovo\"\n  STR_FILTER_DEFAULT: \"Predefinito\"\n  STR_FILTER_DEFAULT_SUPPLIES_OK: \"Predefinito (forniture OK)\"\n  STR_FILTER_DEFAULT_NO_SUPPLIES: \"Predefinito (forniture NO)\"\n  STR_FILTER_FACILITY_REQUIRED: \"Edificio Mancante\"\n  STR_FILTER_HIDDEN: \"Nascosto\"\n  STR_FILTER_EQUIPPED: \"Equipaggiato\"\n  STR_FILTER_MISSING: \"Mancante\"\n  STR_SORT_DEFAULT: \"Predefinito\"\n  STR_SORT_BY_COST: \"Per costo\"\n  STR_SORT_BY_NAME: \"Per nome\"\n  STR_RANDOM_PRODUCTION_SUMMARY: \"Sommario\"\n  STR_NOT_ENOUGH_PRISON_SPACE: \"NON CI SONO ABBASTANZA CONTENIMENTO ALIENO!{SMALLLINE}Costruisci nuovi contenimenti alieni o trasferiscili alle altre basi.\"\n  STR_MONTHLY_ITEM_PURCHASE_LIMIT_EXCEEDED: \"LIMITE DI ACQUISTO MENSILE SUPERATO!{SMALLLINE}Altri articoli saranno disponibili il mese prossimo.\"\n  STR_MONTHLY_CRAFT_PURCHASE_LIMIT_EXCEEDED: \"LIMITE DI ACQUISTO MENSILE SUPERATO!{SMALLLINE}Altri veicoli saranno disponibili il mese prossimo.\"\n  STR_MONTHLY_SOLDIER_HIRING_LIMIT_EXCEEDED: \"LIMITE DI ASSUNZIONI MENSILI SUPERATO!{SMALLLINE}Altre reclute saranno disponibili il mese prossimo.\"\n  STR_NOT_ENOUGH_CRAFT_SPACE: \"Spazio a bordo esaurito!\"\n  STR_SELECT_AVATAR_FOR: \"SELEZIONA AVATAR PER{NEWLINE}{0}\"\n  STR_SOLDIER_BONUSES_FOR: \"Bonus al soldato per{NEWLINE}{0} \"\n  STR_SUMMARY: \"Sommario\"\n  STR_MANA_RECOVERY: \"RECUPERO MANA> {ALT}{0}\"\n  STR_HEALTH_RECOVERY: \"RECUPERO SALUTE> {ALT}{0}\"\n  STR_BONUSES_BUTTON: \"+\"\n  STR_PROMOTE_SOLDIER: \"PROMUOVI/DECLASSA{NEWLINE}{0} {1}\"\n  STR_RANK_HEADER: \"RANGO\"\n  STR_OPENINGS_HEADER: \"POSIZIONI DISPONIBILI\"\n  STR_KILLER_AND_WEAPON: \"{0}, {1}\"\n  STR_TRAINING: \"Addestramento\"\n  STR_SOLDIER_INFO: \"Info Soldato\"\n  STR_SELECT_TRANSFORMATION_FOR: \"SELEZIONA TRASFOMAZIONE PER{NEWLINE}{0}\"\n  STR_TRANSFORMATIONS_BUTTON: \"^\"\n  STR_TRANSFER_TIME: \"Tempo Trasferimento>{ALT}{0}\"\n  STR_RECOVERY_TIME: \"Tempo Recupero>{ALT}{0}\"\n  STR_CURRENT_STATS: \"Statistiche correnti\"\n  STR_CHANGES: \"Cambiamenti\"\n  STR_CHANGES_MIN: \"Cambiamenti (min)\"\n  STR_CHANGES_MAX: \"Cambiamenti (max)\"\n  STR_BONUS_STATS: \"Bonus di Statistica\"\n  STR_TRANSFORMATIONS_OVERVIEW: \"Panoramica Trasformazioni\"\n  STR_PROJECT_NAME: \"NOME PROGETTO\"\n  STR_AVAILABLE_MATERIALS: \"MATERIALI DISPONIBILI\"\n  STR_ELIGIBLE_SOLDIERS: \"SOLDATI IDONEI\"\n  STR_SHOW_ONLY_ELIGIBLE: \"Mostra solo idonei\"\n  STR_ALL_SOLDIER_TYPES: \"Tutti i tipi di soldato\"\n  STR_ALL_SOLDIERS: \"Tutti i soldati\"\n  STR_HEALTHY_SOLDIERS: \"Soldati in salute\"\n  STR_WOUNDED_SOLDIERS: \"Soldati feriti\"\n  STR_DEAD_SOLDIERS: \"Soldati morti\"\n  STR_GRAND_TOTAL: \"Totale\"\n  STR_AVAILABLE_TOPICS: \"ARGOMENTI DISPONIBILI\"\n  STR_QS_THREE_LETTERS_A: \"Inserire almeno 3 lettere\"\n  STR_QS_THREE_LETTERS_B: \"nel box di Ricerca Veloce...\"\n  STR_M_FLAG: \" [m]\"\n  STR_F_FLAG: \" [f]\"\n  STR_I_FLAG: \" [i]\"\n  STR_C_FLAG: \" [c]\"\n  STR_THIS_FEATURE_IS_DISABLED_1: \"Questa funzione è disabilitata.\"\n  STR_THIS_FEATURE_IS_DISABLED_2: \"Questa funzione è disabilitata.\"\n  STR_THIS_FEATURE_IS_DISABLED_3: \"Questa funzione è disabilitata.\"\n  STR_THIS_FEATURE_IS_DISABLED_4: \"Questa funzione è disabilitata.\"\n  STR_THIS_FEATURE_IS_DISABLED_5: \"Questa funzione è disabilitata.\"\n  STR_TECH_TREE_VIEWER: \"Visione Tech Tree\"\n  STR_SELECT_TOPIC: \"Seleziona Argomento\"\n  STR_RESEARCH_PROGRESS: \"Progresso>{ALT} {0}%\"\n  STR_ITEM_DESTROYED: \"Oggetto distrutto:\"\n  STR_ITEM_REQUIRED: \"Oggetto necessario:\"\n  STR_SERVICES_REQUIRED: \"Servizio necessario:\"\n  STR_SERVICES_PROVIDED: \"Servizio fornito:\"\n  STR_SERVICES_FORBIDDEN: \"Servizio proibito:\"\n  STR_REQUIRES: \"Richiede:\"\n  STR_DEPENDS_ON: \"Dipende da:\"\n  STR_UNLOCKED_BY: \"Sbloccato da:\"\n  STR_DISABLED_BY: \"Disabilitato da:\"\n  STR_REENABLED_BY: \"Riattivata da:\"\n  STR_GET_FOR_FREE_FROM: \"Gratis da:\"\n  STR_IS_LOOKUP_OF: \"Porta a:\"\n  STR_LOOKUP: \"Guarda:\"\n  STR_SPAWNED_ITEMS: \"Oggetti generati:\"\n  STR_SPAWNED_EVENT: \"Evento generato:\"\n  STR_REQUIRED_BY: \"Richiesto da:\"\n  STR_REQUIRED_BY_TRANSFORMATIONS: \"Richiesto per trasformazione:\"\n  STR_LEADS_TO: \"Porta a:\"\n  STR_UNLOCKS: \"Sblocca:\"\n  STR_DISABLES: \"Disabilita:\"\n  STR_REENABLES: \"Riattiva:\"\n  STR_GIVES_ONE_FOR_FREE_SEQ: \"Regala una (sequenziale):\"\n  STR_GIVES_ONE_FOR_FREE: \"Regala una:\"\n  STR_RESEARCH_REQUIRED: \"Ricerca richiesta:\"\n  STR_RESEARCH_REQUIRED_USE: \"Ricerca richiesta (uso):\"\n  STR_RESEARCH_REQUIRED_BUY: \"Ricerca richiesta (comprare):\"\n  STR_SERVICES_REQUIRED_BUY: \"Servizio richiesto (comprare):\"\n  STR_PRODUCED_BY: \"Prodotto da:\"\n  STR_SPAWNED_BY: \"Generato da:\"\n  STR_MATERIALS_REQUIRED: \"Materiali richiesti:\"\n  STR_TTV_COST_PER_UNIT: \"Costo per unità\"\n  STR_TTV_ENGINEER_HOURS: \"Ore per ingegnere:\"\n  STR_TTV_WORK_SPACE_REQUIRED: \"Spazio di lavoro richiesto:\"\n  STR_ITEMS_PRODUCED: \"Oggetti prodotti:\"\n  STR_PERSON_RECRUITED: \"Persona reclutate:\"\n  STR_UNLOCKS_ARCS: \"Sblocca archi:\"\n  STR_DISABLES_ARCS: \"Disabilità archi:\"\n  STR_UNLOCKS_MISSIONS: \"Sblocca missioni:\"\n  STR_DISABLES_MISSIONS: \"Disabilita missioni:\"\n  STR_UNLOCKS_EVENTS: \"Sblocca eventi:\"\n  STR_DISABLES_EVENTS: \"Disabilita eventi:\"\n  STR_AFFECTS_GAME_PROGRESSION: \"Cambia la progressione di gioco!\"\n  STR_ITEMS_AT_DESTINATION: \"Oggetti a destinazione\"\n  STR_PRISONERS: \"Prigionieri\"\n  STR_ARMORS: \"Armature\"\n  STR_FILTER_RESEARCHED: \"Studiato completamente\"\n  STR_FILTER_RESEARCHABLE: \"Studiabile\"\n  STR_CRAFT_DEPLOYMENT_QUESTION: \"Salva schieramento nave?\"\n  STR_MUST_USE_BOTH_HANDS: \"Sono necessarie entrambe le mani!\"\n  STR_NOT_ENOUGH_MORALE: \"Non Abbastanza Morale!\"\n  STR_NOT_ENOUGH_HEALTH: \"Non Abbastanza Salute!\"\n  STR_NOT_ENOUGH_MANA: \"Non Abbastanza Mana!\"\n  STR_NOT_ENOUGH_STUN: \"Il livello di Stordimento è troppo alto!\"\n  STR_MIND_CONTROL_SUCCESSFUL_ALT: \"Azione Riuscita\"\n  STR_LINE_OF_SIGHT_REQUIRED: \"Richiesta Linea Visiva (LV).\"\n  STR_CENTER_ON_WOUNDED_FRIEND: \"Centra su Alleato Ferito\"\n  STR_CENTER_ON_DIZZY_FRIEND: \"Centra sulla persona stordita\"\n  STR_BUG_HUNT_ACTIVATED: \"Modalità Bug Hunt attiva: i nemici sono visibili sulla minimappa!\"\n  STR_QUICK_MODE_ACTIVATED: \"Modalità Usain Bolt attivata.{NEWLINE}Premi Ctrl+S di nuovo per disattivarla.\"\n  STR_QUICK_MODE_DEACTIVATED: \"Modalità Usain Bolt disattivata.\"\n  STR_SINGLE_MAP_LAYER_ACTIVATED: \"Modalità mappa a singolo layer attivata.{NEWLINE}Premi Ctrl+C di nuovo per disattivarla.\"\n  STR_SINGLE_MAP_LAYER_DEACTIVATED: \"Modalità mappa a singolo layer disattivata.\"\n  STR_TARGET_ENEMY: \"; Bersaglio = NEMICO\"\n  STR_TARGET_NEUTRAL: \"; Bersaglio = NEUTRALE\"\n  STR_TARGET_FRIEND: \"; Bersaglio = ALLEATO\"\n  STR_TARGET_YOURSELF: \"; Bersaglio = TE STESSO\"\n  STR_TARGET_ON_THE_GROUND: \"(sul terreno)\"\n  STR_USE_SPECIAL_ITEM: \"Usa Oggetto Speciale\"\n  STR_NO_EXPERIENCE_YET: \"Nessuna esperienza:\"\n  STR_OPERATION_UC: \"OPERAZIONE> {0}\"\n  STR_WHAT_CAN_I_WEAR: \"Cosa posso indossare?\"\n  STR_STARTING_CONDITION_ARMORS_FORBIDDEN: \"Questa missione richiede un equipaggiamento specifico.{NEWLINE}{NEWLINE}Tipologie di armatura vietata sono: {0}\"\n  STR_STARTING_CONDITION_ARMORS_ALLOWED: \"Questa missione richiede un equipaggiamento specifico.{NEWLINE}{NEWLINE}Tipologie di armatura permessa sono: {0}\"\n  STR_MISSION_OVER: \"Missione completata.\"\n  STR_UNITS_WITH_FATAL_WOUNDS:\n    one: \"{N} di noi è ferito mortalmente\"\n    many: \"{N} di noi sono feriti mortalmente\"\n    other: \"{N} di noi sono feriti mortalmente\"\n  STR_END_MISSION_QUESTION: \"Fine Missione?\"\n  STR_LOOT: \"BOTTINO\"\n  STR_SELL: \"VENDI\"\n  STR_LIVE_ALIENS_SURRENDERED: \"NEMICI ARRESI\"\n  STR_MISSION_ABORTED: \"MISSIONE INTERROTTA\"\n  STR_VIPS_SAVED: \"VIP SALVATI\"\n  STR_VIPS_LOST: \"VIP PERSI\"\n  STR_BOUNTY: \"TAGLIA\"\n  STR_MANA_ABBREVIATION: \"MAN\"\n  STR_EXPERIENCE_OVERVIEW: \"Panoramica Esperienza\"\n  STR_CANNOT_PLACE_ITEM_INTO_THIS_SECTION: \"Non è permesso mettere un oggetto li.{NEWLINE}Non chiedere perché!\"\n  STR_ONE_HAND_MUST_BE_EMPTY: \"Almeno una mano dev'essere libera!\"\n  STR_LOAD_EQUIPMENT_TEMPLATE: \"Carica Equipaggiamento Salvato\"\n  STR_SAVE_EQUIPMENT_TEMPLATE: \"Salva Equipaggiamento Salvato\"\n  STR_FIRING_SHORT: \"Mira>{ALT}{0}\"\n  STR_THROWING_SHORT: \"Tiro>{ALT}{0}\"\n  STR_MELEE_SHORT: \"Mischia>{ALT}{0}\"\n  STR_PERSONAL_EQUIPMENT: \"EQUIP. PERSONALE\"\n  STR_SAVE_PERSONAL_EQUIPMENT: \"Salva Equip. Personale\"\n  STR_LOAD_PERSONAL_EQUIPMENT: \"Carica Equip. Personale\"\n  STR_PERSONAL_EQUIPMENT_SAVED: \"Equip. personale salvato.\"\n  STR_PERSONAL_EQUIPMENT_NOT_DEFINED: \"Equipaggiamento personale non definito.\"\n  STR_SLOT: \"Slot>{ALT}{0}\"\n  STR_THINKING: \"Pensando...\"\n  STR_TELL_ME_MORE: \"Dimmi di più...\"\n  STR_REINFORCEMENTS_ALERT: \"Allarme rinforzi!\"\n  STR_HIT_LOG_NEW_TURN: \"Nuovo Turno\"\n  STR_FAILED_CQB_CHECK: \"Il nemico è riuscito ad interrompere il tuo attacco!\"\n  STR_NO_TRAJECTORY: \"Nessuna traiettoria possibile!\"\n  STR_HIT_LOG_NEW_BULLET: \"=> \"\n  STR_MANA_SHORT: \"MA>{ALT}{0}\"\n  STR_SKILL_NEEDS_ITEM: \"Questa abilità ha bisogno di un oggetto!\"\n  STR_HIT_LOG_NO_DAMAGE: \"0 \"\n  STR_HIT_LOG_SMALL_DAMAGE: \"hit \"\n  STR_HIT_LOG_BIG_DAMAGE: \"HIT \"\n  STR_HIT_LOG_REACTION_FIRE: \"Fuoco di reazione...\"\n  STR_HIT_LOG: \"Registro Colpi\"\n  STR_BUTTON_TOUCH: \"Tocco\"\n  STR_BUTTON_1: \"1\"\n  STR_BUTTON_10: \"10\"\n  STR_BUTTON_100: \"100\"\n  STR_BUTTON_LMB: \"MouseSX\"\n  STR_BUTTON_RMB: \"MouseDX\"\n  STR_BUTTON_MMB: \"MouseCN\"\n  STR_BUTTON_CTRL: \"Ctrl\"\n  STR_BUTTON_ALT: \"Alt\"\n  STR_BUTTON_SHIFT: \"Shift\"\n  STR_LAZY_LOADING: \"Lazy loading\"\n  STR_LAZY_LOADING_DESC: \"Se attiva, le risorse grafiche saranno caricate su richiesta. Altrimenti viene caricato tutto all'inizio.\"\n  STR_VSYNC_FOR_OPENGL: \"VSync per OpenGL\"\n  STR_VSYNC_FOR_OPENGL_DESC: \"Disattiva per la massima velocità di movimento nascosta del nemico e (facoltativamente) la velocità di movimento del soldato. NON impostare il limite FPS su 0. Si applica solo al rendering OpenGL.\"\n  STR_UPDATE_CHECK: \"Controllo Aggiornamenti Automatici\"\n  STR_UPDATE_CHECK_DESC: \"Se attivato, OpenXcom controllerà automaticamente gli aggiornamenti e darà la possibilità di aggiornarsi automaticamente premendo un bottone\"\n  STR_AUTOSAVE_SLOTS: \"Slot salvataggi automatici\"\n  STR_AUTOSAVE_SLOTS_DESC: \"Numero di slot per salvataggi automatici nel Battlescape\"\n  STR_AUTO_SAVE_BATTLESCAPE_SLOT_WITH_NUMBER: \"<AUTO BATTLESCAPE> {0}\"\n  STR_GEO_AUTOSAVE_FREQUENCY: \"Frequenza Salvataggi Automatici (Geoscape)\"\n  STR_GEO_AUTOSAVE_FREQUENCY_DESC: \"Numero di giorni dopo i quali il gioco verrà salvato automaticamente.\"\n  STR_GEO_AUTOSAVE_SLOTS: \"Slot Salvataggi Automatici (Geoscape)\"\n  STR_GEO_AUTOSAVE_SLOTS_DESC: \"Numero di slot per i salvataggi automatici nel Geoscape.\"\n  STR_AUTO_SAVE_GEOSCAPE_SLOT_WITH_NUMBER: \"<AUTO GEOSCAPE> {0}\"\n  STR_OXCE_LINKS: \"Collegamenti Extended\"\n  STR_OXCE_LINKS_DESC: \"Aggiunge ulteriori menù/pulsanti/collegamenti per funzioni OXCE.\"\n  STR_PEDIA_SHOW_CLIP_SIZE: \"Mostra dim. caricatore nella Ufopedia\"\n  STR_PEDIA_SHOW_CLIP_SIZE_DESC: \"Se attivata le dimensioni dei caricatori saranno mostrate di fianco alle icone delle munizioni nella Ufopedia\"\n  STR_INTERCEPT_TABLE_SIZE: \"Dimensione tabella intercettazioni\"\n  STR_INTERCEPT_TABLE_SIZE_DESC: \"Dimensione della tabelle delle seguenti finestre di dialogo: Intercettazione, Tracciamento UFO.\"\n  STR_SHOW_SLACKING_INDICATOR: \"Mostra indicatore pigrizia\"\n  STR_SHOW_SLACKING_INDICATOR_DESC: \"Se attivato verrà mostrato il numero di scienziati ed ingegneri inattivi.\"\n  STR_SHOW_MAINTENANCE_TIME: \"Mostra tempo per manutenzione veicolo\"\n  STR_SHOW_MAINTENANCE_TIME_DESC: \"{ALT}0>{ALT} Non mostrare {ALT}1>{ALT} Mostra solo la durata dell'attività in corso {ALT}2>{ALT} Mostrale tutte (riparazione + riarmo + rifornimento).\"\n  STR_SHOW_ETA: \"Mostra stima della durata del volo\"\n  STR_SHOW_ETA_DESC: \"{ALT}0>{ALT} Non mostrare {ALT}1>{ALT} Mostra il tempo stimato solo per bersagli statici {ALT}2>{ALT} Mostra il tempo stimato anche per bersagli mobili.\"\n  STR_UFO_LANDING_ALERT: \"Allerta atterraggio UFO\"\n  STR_UFO_LANDING_ALERT_DESC: \"Se abilitato, apparirà un messaggio ogni volta che un UFO rilevato atterra.\"\n  STR_REMEMBER_DISABLED_CRAFT_WEAPONS: \"Ricorda armi del veicolo disattivate\"\n  STR_REMEMBER_DISABLED_CRAFT_WEAPONS_DESC: \"Le armi del veicolo rese inoperanti durante un combattimento rimarranno disabilitate. Esse non verranno neanche ricaricate alla base\"\n  STR_GEO_EVENT_INSTANT_DELIVERY: \"Consegna immediata oggetti negli eventi\"\n  STR_GEO_EVENT_INSTANT_DELIVERY_DESC: \"Se attivata gli oggetti ottenuti da eventi del geoscape arriveranno immediatamente. Altrimenti arriveranno dopo un'ora.\"\n  STR_SHOW_BASE_NAME_IN_POPUPS: \"Mostra nome base nei pop-up\"\n  STR_SHOW_BASE_NAME_IN_POPUPS_DESC: \"Se attivata sarà visualizzato il nome della base in questione nelle finestra di pop-up (es. Ricerca Completata).\"\n  STR_ALTERNATE_CRAFT_EQUIPMENT_MANAGEMENT: \"Gestione equipaggiamento velivolo alternativa\"\n  STR_ALTERNATE_CRAFT_EQUIPMENT_MANAGEMENT_DESC: \"Se abilitata, spostare i soldati tra una base ed un velivolo trasferirà anche il loro equipaggiamento (se possibile).\"\n  STR_BASE_INFO_SCALE: \"Ridimensiona barre grandi nelle info della base\"\n  STR_BASE_INFO_SCALE_DESC: \"Se attivata le barre più grandi di 140 saranno ridimensionate per adattarsi all'interfaccia.\"\n  STR_HIGHLIGHT_NEW: \"Evidenzia nuovi argomenti\"\n  STR_HIGHLIGHT_NEW_DESC: \"Se attivata i nuovi argomenti di ricerca, le nuove produzioni e i nuovi articoli della ufopedia avranno un colore diverso.\"\n  STR_RESEARCH_SCROLL_SPEED: \"Rotella di ricerca\"\n  STR_RESEARCH_SCROLL_SPEED_DESC: \"Usando la rotellina del mouse gli scienziati potreanno essere direttamente assegnati (o rimossi) dall'interfaccia Ricerca Attuale.\"\n  STR_RESEARCH_SCROLL_SPEED_CTRL: \"Research scroll speed (con Ctrl)\"\n  STR_RESEARCH_SCROLL_SPEED_CTRL_DESC: \"Usando la rotellina del mouse gli scienziati potreanno essere direttamente assegnati (o rimossi) dall'interfaccia Ricerca Attuale.\"\n  STR_MANUFACTURE_FILTER_SUPPLIES_OK: \"Filtro alternativo per la Produzione\"\n  STR_MANUFACTURE_FILTER_SUPPLIES_OK_DESC: \"Se attivato l'interfaccia mostrerà solo oggetti producibili per i quali ci sono scorte sufficienti.\"\n  STR_MANUFACTURE_SCROLL_SPEED: \"Rotella per produzione\"\n  STR_MANUFACTURE_SCROLL_SPEED_DESC: \"Usando la rotellina del mouse gli ingegneri potreanno essere direttamente assegnati (o rimossi) dall'interfaccia Produzione Attuale.\"\n  STR_MANUFACTURE_SCROLL_SPEED_CTRL: \"Rotella per produzione (con Ctrl)\"\n  STR_MANUFACTURE_SCROLL_SPEED_CTRL_DESC: \"Usando la rotellina del mouse gli ingegneri potreanno essere direttamente assegnati (o rimossi) dall'interfaccia Produzione Attuale.\"\n  STR_PERSONAL_LAYOUT_INCLUDING_ARMOR: \"Includi armatura nell'equip. personale\"\n  STR_PERSONAL_LAYOUT_INCLUDING_ARMOR_DESC: \"Se attivata il layout dell'equipaggiamento personale di un soldato salvato includerà anche l'armatura.\"\n  STR_MANUALPROMOTIONS: \"Promozioni manuali\"\n  STR_MANUALPROMOTIONS_DESC: \"Se attivata, sarà possibile promuovere (o declassare) manualmente i soldati cliccando sull'icona del rango.\"\n  STR_WOUNDED_DEFEND_BASE_IF: \"I feriti difendono (se PV sopra x%)\"\n  STR_WOUNDED_DEFEND_BASE_IF_DESC: \"Anche i soldati feriti difendono la base, se la loro salute è superiore alla soglia percentuale data.\"\n  STR_PLAY_BRIEFING_MUSIC_DURING_EQUIPMENT: \"Riproduci la musica di Briefing più a lungo\"\n  STR_PLAY_BRIEFING_MUSIC_DURING_EQUIPMENT_DESC: \"La musica di briefing continuerà a suonare durante la fase di equipaggiamento fino a quando non viene visualizzato il Battlescape.\"\n  STR_NIGHT_VISION_COLOR: \"Seleziona il colore della Visione Notturna\"\n  STR_NIGHT_VISION_COLOR_DESC: \"Valori da 1 a 15, ognuno rappresenta un colore differente.\"\n  STR_AUTO_NIGHT_VISION_THRESHOLD: \"Soglia per Visione Notturna Automatica\"\n  STR_AUTO_NIGHT_VISION_THRESHOLD_DESC: \"Se più buio di questa soglia, attiva automaticamente Visione Notturna.\"\n  STR_SHOW_ACCURACY_ON_CROSSHAIR: \"Mostra precisione sul mirino\"\n  STR_SHOW_ACCURACY_ON_CROSSHAIR_DESC: \"{ALT}0>{ALT}Mai {ALT}1>{ALT}Solo se è abilitata la precisione UFO Extender {ALT}2>{ALT}Sempre\"\n  STR_REACTION_FIRE_THRESHOLD: \"Limite fuoco di reazione\"\n  STR_REACTION_FIRE_THRESHOLD_DESC: \"Le unità Xcom non risponderanno al fuoco se la loro precisione (per un dato bersaglio) è al di sotto di questo valore.\"\n  STR_AUTO_SELL: \"Gestione Auto-Vendita\"\n  STR_AUTO_SELL_DESC: \"Nella schermata di vendità debriefing, ogni oggetti che hai venduto precedentemente sarà evidenziato per la vendita.\"\n  STR_AUTOMATICPROMOTIONS: \"Promozioni automatiche\"\n  STR_AUTOMATICPROMOTIONS_DESC: \"Se attivata, i soldati verranno automaticamente promossi dopo una missione.\"\n  STR_OFF_CENTRE_SHOOTING: \"Mira fuori centro\"\n  STR_OFF_CENTRE_SHOOTING_DESC: \"I soldati proveranno a mirare meglio automaticamente se non vedono bene.\"\n  STR_UNIFORM_SHOOTING_SPREAD: \"Propagazione uniforme dei colpi\"\n  STR_UNIFORM_SHOOTING_SPREAD_DESC: \"La propagazione è uniforme in tutte le direzioni ed è più compatta\"\n  STR_CRASHED_OR_LANDED: \"Pulsante Schianto/Atterraggio\"\n  STR_CRASHED_OR_LANDED_DESC: \"Se attivato, nella schermata Nuova battaglia viene visualizzato un pulsante aggiuntivo. In alternativa, premere F11 per mostrare/nascondere il pulsante. {ALT}0>{ALT}Disattivato, {ALT}1>{ALT}Schiantato, {ALT}2>{ALT}Atterrato.\"\n  STR_GRAPHS_ZOOM_IN: \"Zoom In (Grafici)\"\n  STR_GRAPHS_ZOOM_OUT: \"Zoom Out (Grafici)\"\n  STR_MARK_ALL_AS_SEEN: \"Segna Come Già Letti\"\n  STR_SELL_ALL: \"Vendi Tutto\"\n  STR_SELL_ALL_BUT_ONE: \"Vendi Tutto Tranne Uno\"\n  STR_TRANSFER_ALL: \"Trasferisci tutto\"\n  STR_REMOVE_SOLDIERS_FROM_ALL_CRAFTS: \"Rimuovi Soldati Da Veicoli\"\n  STR_REMOVE_SOLDIERS_FROM_CRAFT: \"Rimuovi Soldati Da Veicolo\"\n  STR_REMOVE_EQUIPMENT_FROM_CRAFT: \"Rimuovi Equipaggiamento Da Veicolo\"\n  STR_REMOVE_ARMOR_FROM_ALL_CRAFTS: \"Rimuovi Armatura Da Veicoli\"\n  STR_REMOVE_ARMOR_FROM_CRAFT: \"Rimuovi Armatura Da Veicolo\"\n  STR_REMOVE_SOLDIERS_FROM_TRAINING: \"Rimuovi Soldati Da Allenamento\"\n  STR_ADD_SOLDIERS_TO_TRAINING: \"Aggiungi soldati all'addestramento\"\n  STR_INVENTORY_ARMOR: \"Cambia Armatura\"\n  STR_INVENTORY_AVATAR: \"Cambia Avatar\"\n  STR_INVENTORY_DIARY_LIGHT: \"Visualizza Diario\"\n  STR_ACTION_ITEM_1: \"Azione Oggetti 1 (Mira/Usa)\"\n  STR_ACTION_ITEM_2: \"Azione Oggetti 2 (Snap)\"\n  STR_ACTION_ITEM_3: \"Azione Oggetti 3 (Auto)\"\n  STR_ACTION_ITEM_4: \"Azione Oggetti 4 (Mischia)\"\n  STR_ACTION_ITEM_5: \"Azione Oggetti 5 (Lancia)\"\n  STR_INSTA_SAVE: \"Insta-save\"\n  STR_TOGGLE_QUICK_SEARCH: \"Attiva Campo Ricerca Veloce\"\n  STR_TOGGLE_NIGHT_VISION: \"Attiva Visione Notturna\"\n  STR_HOLD_NIGHT_VISION: \"Visione Notturna Breve\"\n  STR_SELECT_MUSIC_TRACK: \"Selezione Traccia Musicale\"\n  STR_TOGGLE_TOUCH_BUTTONS: \"Attiva pulsanti Touch\"\n  STR_TOGGLE_BRIGHTNESS: \"Attiva/disattiva luminosità (solo visiva)\"\n  STR_BRIEFING: \"Briefing\"\n  STR_TOGGLE_DEBUG_MODE: \"Attiva modalità Debug\"\n  STR_DEBUG_KILL_ALL_ALIENS: \"DEBUG: Uccidi tutti gli alieni\"\n  STR_PHYSICAL_TRAINING: \"Addestramento Marziale\"\n  STR_REMAINING_TRAINING_FACILITY_CAPACITY: \"CAPACITÀ ADDESTRAMENTO RIMANENTE> {ALT}{0}\"\n  STR_NO_WOUNDED: \"-\"\n  STR_NO_QUEUED: \"+\"\n  STR_NO_DONE: \"FATTO\"\n  STR_NO_AMMO: \"NIENTE MUNIZIONI!\"\n  STR_START_FIRING: \"Fuoco!\"\n  STR_SKIP_FIRING: \"Falli entrare...\"\n  STR_ALIEN_MISSILES_HAVE_DAMAGED_OUR_BASE: \"I missili alieni hanno danneggiato la nostra base {0}\"\n  STR_ALIEN_MISSILES_HAVE_DESTROYED_OUR_BASE: \"I missili alieni hanno distrutto la nostra base {0}\"\n  STR_STARTING_CONDITION_COMMANDER: \"Questa missione richiede la presenza del comandante.\"\n  STR_STARTING_CONDITION_CRAFT: \"Questo veicolo non è adatto per questa missione.\"\n  STR_STARTING_CONDITION_CRAFT_ALLOWED: \"Questo veicolo non è adatto per questa missione.{NEWLINE}{NEWLINE}Veicolo permesso {0}\"\n  STR_STARTING_CONDITION_CRAFT_FORBIDDEN: \"Questo veicolo non è adatto per questa missione.{NEWLINE}{NEWLINE}Veicolo proibito {0}\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE: \"Alcuni soldati non possono partecipare a questa missione\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE_ALLOWED: \"Alcuni soldati non possono partecipare a questa missione.{NEWLINE}{NEWLINE}Tipi di soldati permessi: {0}\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE_FORBIDDEN: \"Alcuni soldati non possono partecipare a questa missione.{NEWLINE}{NEWLINE}Tipi di soldati vietati: {0}\"\n  STR_STARTING_CONDITION_ITEM: \"Questa missione richiede oggetti specifici:{NEWLINE}{NEWLINE}{0}\"\n  STR_NOT_ENOUGH_FUEL_TO_REACH_TARGET: \"NON C'È ABBASTANZA CARBURANTE!{SMALLLINE}La destinazione è troppo lontana per il raggio d'azione della nave.\"\n  STR_TOO_MANY_ITEMS_ONBOARD: \"TROPPI OGGETTI!{SMALLLINE}Questo veicolo non può portare così tanti oggetti.\"\n  STR_ARMOR_NOT_ALLOWED_ONBOARD: \"ARMATURA NON CONSENTITA!{SMALLLINE}Alcuni soldati indossano un'armatura proibita.\"\n  STR_FOLLOW_WING_LEADER_QUESTION: \"Seguire il pilota principale?\"\n  STR_ASSIGN_PILOTS: \"Assegna piloti...\"\n  STR_NOT_ENOUGH_PILOTS: \"Non abbastanza piloti!{NEWLINE}Minimo: {0}\"\n  STR_DAILY_PILOT_EXPERIENCE: \"Esperienza Giornaliera Pilota\"\n  STR_UFO_SHIELD_HIT: \"COLPITO GLI SCUDI!\"\n  STR_UFO_HIT_NO_DAMAGE: \"RIMBALZA SULLO SCAFO!\"\n  STR_UFO_SHIELD_DOWN: \"SCUDI NEMICI DISATTIVATI!\"\n  STR_UFO_HIT_GLANCING: \"COLPO DI STRISCIO!\"\n  STR_INTERCEPTOR_SHIELD_HIT: \"I NOSTRI SCUDI STANNO RESISTENDO!\"\n  STR_TRACTOR_BEAM_ENGAGED: \"RAGGIO TRAENTE ATTIVATO!\"\n  STR_TRACTOR_BEAM_DISENGAGED: \"DISATTIVAZIONE RAGGIO TRAENTE\"\n  STR_SELF_DESTRUCT_ACTIVATED: \"AUTO-DISTRUZIONE ATTIVATA!\"\n  STR_SELF_DESTRUCT_CANCELLED: \"AUTO-DISTRUZIONE CANCELLATA\"\n  STR_MISSILE_DAMAGED: \">>> MISSILE DANNEGGIATO <<<\"\n  STR_MISSILE_DESTROYED: \">>> MISSILE DISTRUTTO <<<\"\n  STR_EXTENDED_LINKS: \"Collegamenti\"\n  STR_AUTO_PATROL: \"AUTO-RICOGNIZIONE\"\n  STR_ETA: \"ARRIVO>{ALT}{0}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_FACILITY_AT_BASE: \"Non ci sono abbastanza {0} per riarmare {1} a {2}\"\n  STR_UFO_STARTED_HUNTING: \"{0} è su una rotta d'intercettazione verso {1}\"\n  STR_CRAFT_IS_READY: \"{0} a {1} è pronto.\"\n  STR_ECONOMY_WARNING: \"I fondi {0} ed il reddito {1} sono bassi e la manutenzione {2} troppo alta! Vendi qualcosa per evitare di prendere un prestito... fondi mancanti: {3}\"\n  STR_SLACKING_INDICATOR: \"{0}:{1}\"\n  STR_TRAINING_INDICATOR: \"{0}:{1}\"\n  STR_EXTENDED_UC: \"EXTENDED\"\n  STR_RETURNING: \"DI RITORNO\"\n  STR_INTERCEPTING: \"INTERCETTANDO\"\n  STR_ESCORTING: \"SCORTANDO\"\n  STR_EN_ROUTE: \"IN ROTTA\"\n  STR_PILOT_MISSING: \"PILOTA MANCANTE\"\n  STR_DAY_SHORT: \"{0}g\"\n  STR_HOUR_SHORT: \"{0}h\"\n  STR_PERFORMANCE_BONUS: \"Bonus Prestazione\"\n  STR_COUNTRY_HAS_CANCELLED_A_SECRET_PACT: \"{0} ha rinunciato al patto con le forze aliene e gli è stato permesso di tornare al progetto.\"\n  STR_COUNTRIES_HAVE_CANCELLED_A_SECRET_PACT: \"{0} hanno rinunciato al patto con le forze aliene e sono stati autorizzati a ritornare al progetto.\"\n  STR_WE_CAN_NOW_RENT: \"Ora possiamo affittare\"\n  STR_REQUIRED_BASE_SERVICES: \"Servizi necessari: {0}\"\n  STR_WE_CAN_NOW_BUILD: \"Ora possiamo costruire\"\n  STR_WE_CAN_NOW_PURCHASE: \"Ora possiamo comprare\"\n  STR_NOT_ENOUGH_LIVING_SPACE_AT_BASE: \"Spazio abitativo insufficiente per ospitare{NEWLINE}{0}{NEWLINE}a{NEWLINE}{1}\"\n  STR_INFO: \"INFO\"\n  STR_DESPAWN_PENALTY: \"Penalità despawn> {0}\"\n  STR_TRAINING_FINISHED: \"Allenamento Completato{NEWLINE}a {0}\"\n  STR_PSI_TRAINING_FINISHED: \"Addestramento Psi finito{NEWLINE}a {0}\"\n  STR_IGNORE_UC: \"IGNORA\"\n  STR_UFO_TRACKER: \"Tracker UFO\"\n  STR_UPDATE: \"Aggiornamento\"\n  STR_LATEST_VERSION_INFO: \"Stai usando l'ultima versione di OpenXcom\"\n  STR_MASTER_MOD_VERSION_REQUIRED_QUESTION: \"Questa mod richiede il gioco base v{0} per funzionare correttamente. Abilito la mod?\"\n  STR_VERSION_REQUIRED_QUESTION: \"Questa mod richiede OXCE v{0} per funzionare correttamente. Abilito la mod?\"\n  STR_OPEN_MODS_FOLDER: \"Apri\"\n  STR_GLOBE_TEXTURE: \"Texture del Globo\"\n  STR_NOTES: \"Note\"\n  STR_NEW_NOTE: \"<NEW NOTE>\"\n  STR_ENGINE_OXC: \"OXC\"\n  STR_ENGINE_OXCE: \"OXCE\"\n  STR_ENGINE_OTHER: \"Altro\"\n  STR_BASESCAPE: \"Basescape\"\n  STR_AI: \"IA\"\n  STR_PATH_ENERGY_COST: \"Energia\"\n  STR_PATH_ENERGY_COST_DESC: \"Clickando visualizzarai l'energia che resterà alla tua unità dopo aver raggiunto la destinazione\"\n  STR_VEHICLES_LOST: \"Veicoli persi\"\n  STR_CRAFT_LOST_DOGFIGHT: \"Intercettori persi\"\n  STR_CRAFT_LOST_MISSION: \"Trasporti persi\"\n  STR_ALIEN_BASES_DESTROYED: \"Basi aliene distrutte\"\n  STR_XCOM_BASES_LOST: \"Basi perse\"\n  STR_TEST_SCREEN: \"TEST SCREEN\"\n  STR_PALETTE: \"Palette:\"\n  STR_PREVIEW: \"Anteprima\"\n  STR_TINY_BORDERLESS: \"Micro, senza bordi\"\n  STR_TINY_BORDER: \"Micro\"\n  STR_SMALL_LOW_CONTRAST: \"Piccolo\"\n  STR_SMALL_HIGH_CONTRAST: \"Piccolo, alto contrasto\"\n  STR_BIG_LOW_CONTRAST: \"Grande\"\n  STR_BIG_HIGH_CONTRAST: \"Grande, alto contrasto\"\n  STR_TEST_CASE: \"Test case:\"\n  STR_RUN: \"Avvia test!\"\n  STR_TESTS_STARTING: \"Inizio...\"\n  STR_TESTS_ERRORS_FOUND: \"Totale errori trovati (potrebbero esserci duplicati): {0}\"\n  STR_TESTS_NO_ERRORS_FOUND: \"Nessun errore rilevato.\"\n  STR_TESTS_FINISHED: \"Finito.\"\n  STR_DETAILED_INFO_IN_LOG_FILE: \"I dettagli sono stati salvati in openxcom.log\"\n  STR_RANK_NONE: \"-\"\n  STR_DAMAGE_NONE: \"NESSUNO\"\n  STR_INFO_UFOPEDIA: \"INFO\"\n  STR_COCKPIT_CAPACITY: \"PILOTI>{ALT}{0}{ALT}\"\n  STR_MAXIMUM_RANGE: \"MAX RANGE>{ALT}{0}{ALT}\"\n  STR_MINIMUM_RANGE: \"MIN RANGE>{ALT}{0}{ALT}\"\n  STR_INFINITE_RANGE: \"N/D\"\n  STR_TRACTOR_BEAM_POWER: \"Energia\"\n  STR_WEIGHT_PEDIA1: \"P: {0}\"\n  STR_WEIGHT_PEDIA2: \"P: {0}/{1}\"\n  STR_SHOT_TYPE_MELEE: \"Mischia\"\n  STR_ACCURACY_MODIFIER: \"Modificatore precisione>{ALT} {0}\"\n  STR_POWER_BONUS: \"Bonus potenza>{ALT} {0}\"\n  STR_MULTIPLE_DIFFERENT_BONUSES: \"bonus multipli su varie munizioni compatibili\"\n  STR_STATS_FOR_NERDS: \"Statistiche per Nerd\"\n  STR_ARTICLE: \"Articolo>{ALT} {0}\"\n  STR_COMPATIBLE_AMMO: \"Munizioni compatibili:\"\n  STR_BUILT_IN_ITEMS: \"Oggetti Built-in:\"\n  STR_CLIP_SIZE_UNLIMITED: \"illimitato\"\n  STR_SHOTGUN_BEHAVIOR_OXCE: \"extended\"\n  STR_INCLUDE_DEBUG: \"DEBUG\"\n  STR_INCLUDE_IDS: \"ID\"\n  STR_INCLUDE_DEFAULTS: \"DEFAULT\"\n  STR_TRUE: \"vero\"\n  STR_FALSE: \"falso\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH: \"ABILITÀ PSI*FORZA PSI\"\n  STR_STRENGTH_AND_MELEE_ACCURACY: \"FORZA*MISCHIA\"\n  STR_STRENGTH_AND_THROWING_ACCURACY: \"FORZA*TIRO\"\n  STR_FIRING_ACCURACY_AND_REACTIONS: \"MIRA*REAZIONI\"\n  STR_HEALTH_CURRENT: \"SALUTE CORRENTE\"\n  STR_MANA_CURRENT: \"MANA CORRENTE\"\n  STR_TIME_UNITS_CURRENT: \"UT CORRENTI\"\n  STR_STUN_LEVEL_CURRENT: \"LIV. STORDIMENTO CORRENTE\"\n  STR_HEALTH_NORMALIZED: \"SALUTE NORMALIZZATA\"\n  STR_MANA_NORMALIZED: \"MANA NORMALIZZATO\"\n  STR_TIME_UNITS_NORMALIZED: \"TU NORMALIZZATE\"\n  STR_ENERGY_NORMALIZED: \"ENERGIA NORMALIZZATA\"\n  STR_MORALE_NORMALIZED: \"MORALE NORMALIZZATO\"\n  STR_STUN_LEVEL_NORMALIZED: \"LIV. STORDIMENTO NORMALIZZATO\"\n  STR_ENERGY_REGENERATION: \"RIGENERAZIONE ENERGIA\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH_ABBREVIATION: \"APS*FPS\"\n  STR_STRENGTH_AND_MELEE_ACCURACY_ABBREVIATION: \"FOR*MIS\"\n  STR_STRENGTH_AND_THROWING_ACCURACY_ABBREVIATION: \"FOR*TIR\"\n  STR_FIRING_ACCURACY_AND_REACTIONS_ABBREVIATION: \"MIR*REA\"\n  STR_HEALTH_CURRENT_ABBREVIATION: \"SALUTE CORRENTE\"\n  STR_MANA_CURRENT_ABBREVIATION: \"MANA CORRENTE\"\n  STR_TIME_UNITS_CURRENT_ABBREVIATION: \"UT CORRENTI\"\n  STR_STUN_LEVEL_CURRENT_ABBREVIATION: \"LIV. STORDIMENTO CORRENTE\"\n  STR_HEALTH_NORMALIZED_ABBREVIATION: \"SALUTE NORMALIZZATA\"\n  STR_MANA_NORMALIZED_ABBREVIATION: \"MANA NORMALIZZATO\"\n  STR_TIME_UNITS_NORMALIZED_ABBREVIATION: \"TU NORMALIZZATE\"\n  STR_ENERGY_NORMALIZED_ABBREVIATION: \"ENERGIA NORMALIZZATA\"\n  STR_MORALE_NORMALIZED_ABBREVIATION: \"MORALE NORMALIZZATO\"\n  STR_STUN_LEVEL_NORMALIZED_ABBREVIATION: \"LIV. STORDIMENTO NORMALIZZATO\"\n  STR_ENERGY_REGENERATION_ABBREVIATION: \"RIGENERAZIONE ENERGIA\"\n  STR_TIME_UNITS_SCALED: \"UNITÀ DI TEMPO SCALATE\"\n  STR_STAMINA_SCALED: \"STAMINA SCALATA\"\n  STR_HEALTH_SCALED: \"SALUTE SCALATA\"\n  STR_BRAVERY_SCALED: \"CORAGGIO SCALATO\"\n  STR_REACTIONS_SCALED: \"REAZIONI SCALATE\"\n  STR_FIRING_ACCURACY_SCALED: \"MIRA SCALATA\"\n  STR_THROWING_ACCURACY_SCALED: \"TIRO SCALATO\"\n  STR_STRENGTH_SCALED: \"FORZA SCALATA\"\n  STR_PSIONIC_STRENGTH_SCALED: \"FORZA PSIONICA SCALATA\"\n  STR_PSIONIC_SKILL_SCALED: \"ABILITÀ PSIONICA SCALATA\"\n  STR_MELEE_ACCURACY_SCALED: \"MISCHIA SCALATA\"\n  STR_MANA_POOL_SCALED: \"MANA SCALATO\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH_SCALED: \"ABILITÀ PSI*FORZA PSI SCALATA\"\n  STR_STRENGTH_AND_MELEE_ACCURACY_SCALED: \"FORZA*MISCHIA SCALATA\"\n  STR_STRENGTH_AND_THROWING_ACCURACY_SCALED: \"FORZA*TIRO SCALATA\"\n  STR_FIRING_ACCURACY_AND_REACTIONS_SCALED: \"MIRA*REAZIONI SCALATA\"\n  STR_TIME_UNITS_SCALED_ABBREVIATION: \"UdT SCALATE\"\n  STR_STAMINA_SCALED_ABBREVIATION: \"VIG SCALATO\"\n  STR_HEALTH_SCALED_ABBREVIATION: \"SAL SCALATA\"\n  STR_BRAVERY_SCALED_ABBREVIATION: \"COR SCALATO\"\n  STR_REACTIONS_SCALED_ABBREVIATION: \"REA SCALATE\"\n  STR_FIRING_ACCURACY_SCALED_ABBREVIATION: \"MIR SCALATA\"\n  STR_THROWING_ACCURACY_SCALED_ABBREVIATION: \"TIR SCALATO\"\n  STR_STRENGTH_SCALED_ABBREVIATION: \"FRZ SCALATA\"\n  STR_PSIONIC_STRENGTH_SCALED_ABBREVIATION: \"FPS SCALATA\"\n  STR_PSIONIC_SKILL_SCALED_ABBREVIATION: \"APS SCALATA\"\n  STR_MELEE_ACCURACY_SCALED_ABBREVIATION: \"MIS SCALATA\"\n  STR_MANA_POOL_SCALED_ABBREVIATION: \"MAN SCALATO\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH_SCALED_ABBREVIATION: \"APS*FPS SCALATA\"\n  STR_STRENGTH_AND_MELEE_ACCURACY_SCALED_ABBREVIATION: \"FRZ*MIS SCALATA\"\n  STR_STRENGTH_AND_THROWING_ACCURACY_SCALED_ABBREVIATION: \"FRZ*TIR SCALATA\"\n  STR_FIRING_ACCURACY_AND_REACTIONS_SCALED_ABBREVIATION: \"PRE*REA SCALATA\"\n  STR_COST_TIME: \"tempo\"\n  STR_COST_ENERGY: \"energia\"\n  STR_COST_MORALE: \"morale\"\n  STR_COST_HEALTH: \"salute\"\n  STR_COST_STUN: \"stordimento\"\n  STR_COST_MANA: \"mana\"\n  STR_COST_BUILD: \"costruzione\"\n  STR_COST_REFUND: \"rimborso\"\n  STR_DAMAGE_10: \"10\"\n  STR_DAMAGE_11: \"11\"\n  STR_DAMAGE_12: \"12\"\n  STR_DAMAGE_13: \"13\"\n  STR_DAMAGE_14: \"14\"\n  STR_DAMAGE_15: \"15\"\n  STR_DAMAGE_16: \"16\"\n  STR_DAMAGE_17: \"17\"\n  STR_DAMAGE_18: \"18\"\n  STR_DAMAGE_19: \"19\"\n  STR_NAUTICAL_MILES: \"{0} miglia nautiche\"\n  STR_KILOMETERS_PER_HOUR: \"{0} km/h\"\n  STR_SECONDS_LONG: \"{0} secondi\"\n  STR_RACE_BONUS: \"Race bonus\"\n  STR_FOR_DIFFICULTY: \"per difficoltà: {0}\"\n  STR_NOT_AWARDED_YET: \"Non ancora assegnato\"\n"
  },
  {
    "path": "bin/common/Language/OXCE/ja.yml",
    "content": "ja:\n  STR_CANNOT_DISMANTLE_FACILITY_UPGRADING: \"施設の撤去は不可能{SMALLLINE}アップグレード中の撤去は不可能です\"\n  STR_CANNOT_UPGRADE_FACILITY_ALREADY_UPGRADING: \"ここには建設できません{SMALLLINE}既に施設が存在します\"\n  STR_CANNOT_UPGRADE_FACILITY_WRONG_SIZE: \"ここには建設できません{SMALLLINE}条件に合いません\"\n  STR_CANNOT_UPGRADE_FACILITY_WRONG_TYPE: \"ここには建設できません{SMALLLINE}改良条件に合いません\"\n  STR_CANNOT_UPGRADE_FACILITY_DISALLOWED: \"ここには建設できません{SMALLLINE}既に施設が存在します\"\n  STR_CANNOT_BUILD_QUEUE_OFF: \"ここには建設できません{SMALLLINE}隣接施設の建造を完了させてください\"\n  STR_CANNOT_BUILD_UPGRADE_ONLY: \"ここには建設できません{SMALLLINE}アップグレード専用\"\n  STR_FACILITY_FORBIDDEN_BY_OTHER: \"ここには建設できません！{SMALLLINE}既存施設と排他関係\"\n  STR_FACILITY_OTHER_FORBIDDEN_BY_THIS: \"ここには建設できません！{SMALLLINE}既存施設と排他関係\"\n  STR_NOT_ENOUGH_ITEMS: \"資材が足りません！{SMALLLINE}この施設の建造には特定の資材が必要です。{NEWLINE}不足資材> {0}: {1}\"\n  STR_ID: \"ID\"\n  STR_FIRST_LETTER: \"頭文字\"\n  STR_SOLDIER_TYPE: \"兵種\"\n  STR_IDLE_DAYS: \"待機日数\"\n  STR_MANA: \"MP\"\n  STR_MANA_POOL: \"マナプール\"\n  STR_MANA_MISSING: \"MP不足分\"\n  STR_LOAD_CRAFT_LOADOUT_TEMPLATE: \"機体装備セットのロード\"\n  STR_EMPTY_SLOT_N: \"空のスロット {0}\"\n  STR_UNNAMED_SLOT_N: \"名称未定のスロット {0}\"\n  STR_ADD_ON_TOP: \"トップに追加\"\n  STR_SAVE_CRAFT_LOADOUT_TEMPLATE: \"機体装備セットのセーブ\"\n  STR_SAVE_UC: \"セーブ\"\n  STR_ALL: \"全て\"\n  STR_EQUIPPED: \"装着済み\"\n  STR_NOT_EQUIPPED: \"未装備\"\n  STR_UNASSIGNED: \"その他\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED_BY_SIZE: \"装備品の搭載量超過！{SMALLLINE}最大容量: {0}\"\n  STR_PILOTS: \"パイロット\"\n  STR_SHIELD: \"シールド>{ALT}{0}\"\n  STR_CRAFT_SKIN_ID: \"[{0}]\"\n  STR_SELECT_PILOT: \"パイロットを選択\"\n  STR_PILOTS_FOR_CRAFT: \"{0} のパイロット\"\n  STR_PILOTS_REQUIRED: \"パイロット未配属: {ALT}{0}\"\n  STR_ADD_PILOT: \"パイロットを追加\"\n  STR_REMOVE_ALL_PILOTS: \"全パイロットを解任\"\n  STR_ACCURACY_BONUS: \"命中ボーナス：\"\n  STR_DODGE_BONUS: \"回避ボーナス：\"\n  STR_APPROACH_SPEED: \"接近速度：\"\n  STR_COWARDLY: \"慎重 (-50%)\"\n  STR_NORMAL: \"通常\"\n  STR_BOLD: \"大胆 (+50%)\"\n  STR_VERY_BOLD: \"勇猛 (+100%)\"\n  STR_ARMOR_GROUP_NOT_ALLOWED: \"このアーマーは搭載不可です\"\n  STR_SOLDIER_GROUP_NOT_ALLOWED: \"この兵種は搭乗できません\"\n  STR_SOLDIER_GROUP_NOT_SAME: \"この兵種は他の兵種と同乗できません\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW: \"プレビュー\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_SAVED: \"プレビュー *\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_BRIEFING: \"戦闘開始時にユニット配備のプレビューと変更を行う機能です。回数制限はなく、'Alt'キーを押している間対象ユニットの配備可能な位置をハイライトします。'任務中断'をクリックする事でカスタム配備を保存し、'ターン終了'をクリックしてプレビューモードから抜けます。{NEWLINE}※注意：新たな兵士や乗り物を輸送機に乗せるとそれまでのカスタム配備は取り消されます。また、カスタム配備中は'プレビュー'ボタンにアスタリスク '*' が付きます。\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_BRIEFING_DUMMY: \"この機能は輸送機に乗り込んだユニットのプレビューと配備テーブルを設定する為のものです。現在の輸送機に適用された変化はそれ以降に購入または製造された機体全てに自動適用されます。デフォルト設定では兵士を最大数搭載しますが、配備テーブルの一列を埋める形となり、各兵士の名にそのテーブル列のナンバーが付きます。2x2サイズのユニットの搭載スペースを確保するには4名の兵士を2x2マスに置いてください。そうしないと戦闘開始時に2x2のユニットが存在しない結果となります。\"\n  STR_BASE_DEFENSE_BRIEFING_PREVIEW: \"基地のプレビュー機能です。{NEWLINE}よく検討してより良い造営計画を！{NEWLINE}{NEWLINE}'ターン終了'をクリックして抜けます。\"\n  STR_NOT_ENOUGH_CARGO_SPACE: \"搭乗スペースに空きがありません！{SMALLLINE}他のモジュールを選択あるいは人員を減らしてください\"\n  STR_NOT_ENOUGH_STORAGE_SPACE_1: \"貨物スペースが不足しています！{SMALLLINE}アイテムが多すぎです。他のモジュールを選択あるいは装備品を減らしてください\"\n  STR_NOT_ENOUGH_STORAGE_SPACE_2: \"貨物スペースが不足しています！{SMALLLINE}アイテムが大きすぎです。他のモジュールを選択あるいは装備品のサイズを減らしてください\"\n  STR_REFUND_VALUE: \"売却価格> {ALT}{0}\"\n  STR_REFUND_VALUE_NEGATIVE: \"支出> {ALT}{0}\"\n  STR_PRODUCTION_OVERVIEW: \"製造一覧\"\n  STR_RESEARCH_DIARY: \"研究日誌\"\n  STR_DISCOVERY_SOURCE_BASE: \"このアイテムは研究プロジェクトを通じて発見された{NEWLINE}基地> {ALT}{1}{ALT}{NEWLINE}アイテムコード> {ALT}{1}{ALT}\"\n  STR_DISCOVERY_SOURCE_FREE_FROM: \"このアイテムは他の研究プロジェクトを通じて発見された{NEWLINE}該当プロジェクト> {ALT}{2}{ALT}{NEWLINE}{ALT}{1}{ALT} -> {ALT}{0}{ALT}\"\n  STR_DISCOVERY_SOURCE_FREE_AFTER: \"このテクノロジーは付随的に発見された。{NEWLINE}以下のプロジェクトを研究後> {ALT}{2}{ALT}{NEWLINE}{ALT}{1}{ALT} -> {ALT}{0}{ALT}\"\n  STR_DISCOVERY_SOURCE_MISSION: \"このアイテムはミッション報酬として与えられた{NEWLINE}該当ミッション> {ALT}{2}{ALT}{NEWLINE}{ALT}{1}{ALT} -> {ALT}{0}{ALT}\"\n  STR_DISCOVERY_SOURCE_EVENT: \"このアイテムはイベント報酬として与えられた{NEWLINE}該当イベント> {ALT}{2}{ALT}{NEWLINE}{ALT}{1}{ALT} -> {ALT}{0}{ALT}\"\n  STR_RESEARCH_OVERVIEW: \"研究状態\"\n  STR_PRISONER_OVERVIEW: \"囚人情報\"\n  STR_PRISONER: \"囚人\"\n  STR_PRISONER_AMOUNT: \"数量\"\n  STR_PRISONER_INTERROGATED: \"尋問済み\"\n  STR_TOTAL_IN_PRISON: \"空きなし>{ALT}{0}\"\n  STR_TOTAL_INTERROGATED: \"尋問済み>{ALT}{0}\"\n  STR_PRISON_TYPE: \"エイリアン隔離室\"\n  STR_KILL_SELECTED: \"殺処分\"\n  STR_SELL_SELECTED: \"売る\"\n  STR_GO_TO_TRANSFERS: \"移送...\"\n  STR_PRISON_CLEANUP: \"牢を空にする\"\n  STR_TOPIC: \"課題>{ALT} {0}\"\n  STR_SHOW_ALL: \"全て表示\"\n  STR_NO_DEPENDENCIES: \"依存関係なし\"\n  STR_DIRECT_DEPENDENCIES: \"直接依存\"\n  STR_LEVEL_2_DEPENDENCIES: \"二次依存\"\n  STR_LEVEL_3_DEPENDENCIES: \"三次依存\"\n  STR_LEVEL_4_DEPENDENCIES: \"四次依存\"\n  STR_MORE_DEPENDENCIES: \"五次以上の依存\"\n  STR_END_OF_SEARCH: \"探索完了\"\n  STR_FALLBACK_PRODUCTION: \"撤退\"\n  STR_REFUND_PRODUCTION: \"払い戻し\"\n  STR_HOURS_PER_UNIT: \"時間/ユニット>{ALT}{0}\"\n  STR_PERSON_JOINING: \"雇用数\"\n  STR_RANDOM_PRODUCTION_DISCLAIMER: \"ランダムで製造\"\n  STR_OTHER_EMPLOYEES: \"その他人員及び品\"\n  STR_SHOW_ONLY_NEW: \"新規のみ表示\"\n  STR_FILTER_DEFAULT: \"デフォルト\"\n  STR_FILTER_DEFAULT_SUPPLIES_OK: \"デフォルト (必要品あり)\"\n  STR_FILTER_DEFAULT_NO_SUPPLIES: \"デフォルト (必要品なし)\"\n  STR_FILTER_FACILITY_REQUIRED: \"特定施設の不足\"\n  STR_FILTER_HIDDEN: \"非表示\"\n  STR_FILTER_EQUIPPED: \"装着済み\"\n  STR_FILTER_MISSING: \"消失\"\n  STR_SORT_DEFAULT: \"デフォルト\"\n  STR_SORT_BY_COST: \"コスト\"\n  STR_SORT_BY_NAME: \"名前\"\n  STR_RANDOM_PRODUCTION_SUMMARY: \"状態\"\n  STR_NOT_ENOUGH_PRISON_SPACE: \"隔離室が一杯です！{SMALLLINE}新規の隔離室を建造するか、エイリアンを他の基地へ移送してください\"\n  STR_MONTHLY_ITEM_PURCHASE_LIMIT_EXCEEDED: \"月間購入上限超過！{SMALLLINE}来月になれば購入可能品目が増加します\"\n  STR_MONTHLY_CRAFT_PURCHASE_LIMIT_EXCEEDED: \"月間購入上限超過！{SMALLLINE}来月になれば購入可能な機体が増加します\"\n  STR_MONTHLY_SOLDIER_HIRING_LIMIT_EXCEEDED: \"月間雇用上限超過！{SMALLLINE}来月になれば雇用可能人員が増加します\"\n  STR_NOT_ENOUGH_CRAFT_SPACE: \"搭載スペース不足\"\n  STR_SELECT_AVATAR_FOR: \"兵を選択{NEWLINE}{0}\"\n  STR_SOLDIER_BONUSES_FOR: \"兵へのボーナス{NEWLINE}{0}\"\n  STR_SUMMARY: \"状態\"\n  STR_MANA_RECOVERY: \"MP回復量> {ALT}{0}\"\n  STR_HEALTH_RECOVERY: \"HP回復量> {ALT}{0}\"\n  STR_BONUSES_BUTTON: \"+\"\n  STR_PROMOTE_SOLDIER: \"昇進/降格{NEWLINE}{0} {1}\"\n  STR_RANK_HEADER: \"ランク\"\n  STR_OPENINGS_HEADER: \"オープニング\"\n  STR_KILLER_AND_WEAPON: \"{0}、{1}\"\n  STR_TRAINING: \"訓練\"\n  STR_SOLDIER_INFO: \"兵の情報\"\n  STR_SELECT_TRANSFORMATION_FOR: \"改造を選択{NEWLINE}{0}\"\n  STR_TRANSFORMATIONS_BUTTON: \"^\"\n  STR_TRANSFER_TIME: \"輸送時間>{ALT}{0}\"\n  STR_RECOVERY_TIME: \"治療期間>{ALT}{0}\"\n  STR_CURRENT_STATS: \"現在の状況\"\n  STR_CHANGES: \"変動\"\n  STR_CHANGES_MIN: \"変動(最少)\"\n  STR_CHANGES_MAX: \"変動(最大)\"\n  STR_BONUS_STATS: \"ステータスボーナス\"\n  STR_TRANSFORMATIONS_OVERVIEW: \"兵の改造/変容歴\"\n  STR_PROJECT_NAME: \"プロジェクト名\"\n  STR_AVAILABLE_MATERIALS: \"使用可能資材\"\n  STR_ELIGIBLE_SOLDIERS: \"適性兵\"\n  STR_SHOW_ONLY_ELIGIBLE: \"適性者のみ表示\"\n  STR_ALL_SOLDIER_TYPES: \"全兵種\"\n  STR_ALL_SOLDIERS: \"全ての兵士\"\n  STR_HEALTHY_SOLDIERS: \"健康体の兵士\"\n  STR_WOUNDED_SOLDIERS: \"負傷中の兵士\"\n  STR_DEAD_SOLDIERS: \"殉職者\"\n  STR_GRAND_TOTAL: \"総計\"\n  STR_AVAILABLE_TOPICS: \"選択可能な課題\"\n  STR_QS_THREE_LETTERS_A: \"最低でも3文字を\"\n  STR_QS_THREE_LETTERS_B: \"クイックサーチ欄に入力してください\"\n  STR_M_FLAG: \" [m]\"\n  STR_F_FLAG: \" [f]\"\n  STR_I_FLAG: \" [i]\"\n  STR_C_FLAG: \" [c]\"\n  STR_THIS_FEATURE_IS_DISABLED_1: \"この機能は無効\"\n  STR_THIS_FEATURE_IS_DISABLED_2: \"この機能は無効\"\n  STR_THIS_FEATURE_IS_DISABLED_3: \"この機能は無効\"\n  STR_THIS_FEATURE_IS_DISABLED_4: \"この機能は無効\"\n  STR_THIS_FEATURE_IS_DISABLED_5: \"この機能は無効\"\n  STR_TECH_TREE_VIEWER: \"テクツリー表示\"\n  STR_SELECT_TOPIC: \"課題を選択\"\n  STR_RESEARCH_PROGRESS: \"進行度>{ALT} {0}%\"\n  STR_ITEM_DESTROYED: \"アイテムを破壊：\"\n  STR_ITEM_REQUIRED: \"必要なアイテム：\"\n  STR_SERVICES_REQUIRED: \"必要な業務：\"\n  STR_SERVICES_PROVIDED: \"取得する業務：\"\n  STR_SERVICES_FORBIDDEN: \"未許可の業務：\"\n  STR_REQUIRES: \"必要：\"\n  STR_DEPENDS_ON: \"依存：\"\n  STR_UNLOCKED_BY: \"アンロック条件：\"\n  STR_DISABLED_BY: \"以下の為に無効化：\"\n  STR_REENABLED_BY: \"再有効化された：\"\n  STR_GET_FOR_FREE_FROM: \"以下から無料入手：\"\n  STR_IS_LOOKUP_OF: \"現在調査中：\"\n  STR_LOOKUP: \"調査：\"\n  STR_SPAWNED_ITEMS: \"生成アイテム：\"\n  STR_SPAWNED_EVENT: \"発生イベント：\"\n  STR_REQUIRED_BY: \"以下の必要条件：\"\n  STR_REQUIRED_BY_TRANSFORMATIONS: \"変化に必要なもの：\"\n  STR_LEADS_TO: \"関連先：\"\n  STR_UNLOCKS: \"アンロック：\"\n  STR_DISABLES: \"無効化：\"\n  STR_REENABLES: \"再有効化：\"\n  STR_GIVES_ONE_FOR_FREE_SEQ: \"無料入手(順番)：\"\n  STR_GIVES_ONE_FOR_FREE: \"無料入手：\"\n  STR_RESEARCH_REQUIRED: \"研究の必要条件：\"\n  STR_RESEARCH_REQUIRED_USE: \"研究の必要条件(購入)：\"\n  STR_RESEARCH_REQUIRED_BUY: \"研究の必要条件(使用)：\"\n  STR_SERVICES_REQUIRED_BUY: \"必要な業務(購入)：\"\n  STR_PRODUCED_BY: \"製造元：\"\n  STR_SPAWNED_BY: \"発生源：\"\n  STR_MATERIALS_REQUIRED: \"必要素材：\"\n  STR_TTV_COST_PER_UNIT: \"１ユニットのコスト：\"\n  STR_TTV_ENGINEER_HOURS: \"開発期間：\"\n  STR_TTV_WORK_SPACE_REQUIRED: \"必要ワークスペース：\"\n  STR_ITEMS_PRODUCED: \"生産アイテム：\"\n  STR_PERSON_RECRUITED: \"雇用した人員：\"\n  STR_UNLOCKS_ARCS: \"アンロック：\"\n  STR_DISABLES_ARCS: \"無効化：\"\n  STR_UNLOCKS_MISSIONS: \"アンロックされたミッション：\"\n  STR_DISABLES_MISSIONS: \"無効化されたミッション：\"\n  STR_UNLOCKS_EVENTS: \"解禁イベント：\"\n  STR_DISABLES_EVENTS: \"無効化されたイベント：\"\n  STR_AFFECTS_GAME_PROGRESSION: \"ゲームの進展に影響します！\"\n  STR_ITEMS_AT_DESTINATION: \"輸送完了\"\n  STR_PRISONERS: \"捕虜\"\n  STR_ARMORS: \"アーマー\"\n  STR_FILTER_RESEARCHED: \"研究完了\"\n  STR_FILTER_RESEARCHABLE: \"研究可能\"\n  STR_CRAFT_DEPLOYMENT_QUESTION: \"輸送機の配備内容を保存しますか？\"\n  STR_MUST_USE_BOTH_HANDS: \"使用には両手が必要！\"\n  STR_NOT_ENOUGH_MORALE: \"士気不足！\"\n  STR_NOT_ENOUGH_HEALTH: \"HP不足！\"\n  STR_NOT_ENOUGH_MANA: \"MPが不足！\"\n  STR_NOT_ENOUGH_STUN: \"スタン耐性が高すぎる！\"\n  STR_MIND_CONTROL_SUCCESSFUL_ALT: \"アクション成功\"\n  STR_LINE_OF_SIGHT_REQUIRED: \"LOS(射線)が通りません\"\n  STR_CENTER_ON_WOUNDED_FRIEND: \"負傷者をセンターに表示\"\n  STR_CENTER_ON_DIZZY_FRIEND: \"目眩中の友軍ユニットを中心に\"\n  STR_BUG_HUNT_ACTIVATED: \"害虫駆除モード発動：ミニマップ上に敵が表示されます！\"\n  STR_QUICK_MODE_ACTIVATED: \"ウサイン・ボルトモード発動{NEWLINE}Ctrl+S を再び押すことで解除\"\n  STR_QUICK_MODE_DEACTIVATED: \"ウサイン・ボルトモード解除\"\n  STR_SINGLE_MAP_LAYER_ACTIVATED: \"単一マップレイヤーを有効化{NEWLINE}再度 Ctrl+C を押すと無効化\"\n  STR_SINGLE_MAP_LAYER_DEACTIVATED: \"単一マップレイヤを解除\"\n  STR_TARGET_ENEMY: \"; 標的 = 敵\"\n  STR_TARGET_NEUTRAL: \"; 標的 = 中立\"\n  STR_TARGET_FRIEND: \"; 標的 = 味方\"\n  STR_TARGET_YOURSELF: \"; 標的 = 自分\"\n  STR_TARGET_ON_THE_GROUND: \" (地表)\"\n  STR_USE_SPECIAL_ITEM: \"特殊アイテムを使用\"\n  STR_NO_EXPERIENCE_YET: \"未経験：\"\n  STR_OPERATION_UC: \"進行中の作戦> {0}\"\n  STR_WHAT_CAN_I_WEAR: \"装備可能\"\n  STR_STARTING_CONDITION_ARMORS_FORBIDDEN: \"このミッションには装備制限あり{NEWLINE}{NEWLINE}使用不可能なアーマー: {0}\"\n  STR_STARTING_CONDITION_ARMORS_ALLOWED: \"この任務には装備制限あり：{NEWLINE}{NEWLINE}使用できるアーマー：{0}\"\n  STR_MISSION_OVER: \"ミッション完了\"\n  STR_UNITS_WITH_FATAL_WOUNDS:\n    other: \"{N} 名が致命傷を負った\"\n  STR_END_MISSION_QUESTION: \"ミッションを終了しますか？\"\n  STR_LOOT: \"戦利品\"\n  STR_SELL: \"売却\"\n  STR_LIVE_ALIENS_SURRENDERED: \"敵が降伏した\"\n  STR_MISSION_ABORTED: \"ミッションを中断した\"\n  STR_VIPS_SAVED: \"救助されたVIP\"\n  STR_VIPS_LOST: \"行方不明のVIP\"\n  STR_BOUNTY: \"戦利品\"\n  STR_MANA_ABBREVIATION: \"人員\"\n  STR_EXPERIENCE_OVERVIEW: \"経験値一覧\"\n  STR_CANNOT_PLACE_ITEM_INTO_THIS_SECTION: \"そこにそのアイテムは置けません{NEWLINE}質疑は却下する！\"\n  STR_ONE_HAND_MUST_BE_EMPTY: \"最低でも片手の空きが必要！\"\n  STR_LOAD_EQUIPMENT_TEMPLATE: \"装備テンプレートのロード\"\n  STR_SAVE_EQUIPMENT_TEMPLATE: \"装備テンプレートのセーブ\"\n  STR_FIRING_SHORT: \"射撃>{ALT}{0}\"\n  STR_THROWING_SHORT: \"投擲>{ALT}{0}\"\n  STR_MELEE_SHORT: \"近接>{ALT}{0}\"\n  STR_PERSONAL_EQUIPMENT: \"個人用兵装\"\n  STR_SAVE_PERSONAL_EQUIPMENT: \"個人兵装のセーブ\"\n  STR_LOAD_PERSONAL_EQUIPMENT: \"個人兵装のロード\"\n  STR_PERSONAL_EQUIPMENT_SAVED: \"個人兵装のセーブ完了\"\n  STR_PERSONAL_EQUIPMENT_NOT_DEFINED: \"個人兵装が指定されていません\"\n  STR_SLOT: \"スロット>{ALT}{0}\"\n  STR_THINKING: \"思考中・・・\"\n  STR_TELL_ME_MORE: \"続き･･･\"\n  STR_REINFORCEMENTS_ALERT: \"警告！：増援\"\n  STR_HIT_LOG_NEW_TURN: \"ターン開始\"\n  STR_FAILED_CQB_CHECK: \"敵の割り込み！\"\n  STR_NO_TRAJECTORY: \"有効な軌道がない！\"\n  STR_HIT_LOG_NEW_BULLET: \"=> \"\n  STR_MANA_SHORT: \"MA>{ALT}{0}\"\n  STR_SKILL_NEEDS_ITEM: \"スキル使用にはアイテムが必要！\"\n  STR_HIT_LOG_NO_DAMAGE: \"０\"\n  STR_HIT_LOG_SMALL_DAMAGE: \"命中\"\n  STR_HIT_LOG_BIG_DAMAGE: \"命中\"\n  STR_HIT_LOG_REACTION_FIRE: \"反応射撃・・\"\n  STR_HIT_LOG: \"命中率の記録\"\n  STR_BUTTON_TOUCH: \"接触\"\n  STR_BUTTON_1: \"1\"\n  STR_BUTTON_10: \"10\"\n  STR_BUTTON_100: \"100\"\n  STR_BUTTON_LMB: \"左ボタン\"\n  STR_BUTTON_RMB: \"右ボタン\"\n  STR_BUTTON_MMB: \"中ボタン\"\n  STR_BUTTON_CTRL: \"Ctrl\"\n  STR_BUTTON_ALT: \"Alt\"\n  STR_BUTTON_SHIFT: \"Shift\"\n  STR_LAZY_LOADING: \"非一括ロード\"\n  STR_LAZY_LOADING_DESC: \"オンにするとグラフィック関連のデータを必要な時に、オフの時は起動時に全てをロードします。\"\n  STR_VSYNC_FOR_OPENGL: \"OpenGLでVSync\"\n  STR_VSYNC_FOR_OPENGL_DESC: \"敵（オプションで味方側も）のターン中の移動速度制限を無視。決してFPSを0にしないように。OpenGLレンダのみ適用可\"\n  STR_UPDATE_CHECK: \"アップデートの自動チェック\"\n  STR_UPDATE_CHECK_DESC: \"オンにすればOpenXcomの更新チェックを自動化し、ボタン一発で適用可能に！\"\n  STR_AUTOSAVE_SLOTS: \"自動セーブスロット\"\n  STR_AUTOSAVE_SLOTS_DESC: \"バトルスケープの自動保存の数\"\n  STR_AUTO_SAVE_BATTLESCAPE_SLOT_WITH_NUMBER: \"<AUTO BATTLESCAPE> {0}\"\n  STR_GEO_AUTOSAVE_FREQUENCY: \"オートセーブの頻度 (ジオスケープ)\"\n  STR_GEO_AUTOSAVE_FREQUENCY_DESC: \"自動保存を何日ごとに行うか\"\n  STR_GEO_AUTOSAVE_SLOTS: \"オートセーブの数 (ジオスケープ)\"\n  STR_GEO_AUTOSAVE_SLOTS_DESC: \"ジオスケープの自動保存の数\"\n  STR_AUTO_SAVE_GEOSCAPE_SLOT_WITH_NUMBER: \"<AUTO GEOSCAPE> {0}\"\n  STR_OXCE_LINKS: \"Extended Mod化\"\n  STR_OXCE_LINKS_DESC: \"メニュー/ボタン/各リンクなど、OXCEの追加機能を有効化\"\n  STR_PEDIA_SHOW_CLIP_SIZE: \"弾倉の装填数をUfoペディアで表示\"\n  STR_PEDIA_SHOW_CLIP_SIZE_DESC: \"ONにするとUfoペディア内で弾倉アイコンの隣に装弾数が表示される様になります\"\n  STR_INTERCEPT_TABLE_SIZE: \"インターセプト情報のサイズ\"\n  STR_INTERCEPT_TABLE_SIZE_DESC: \"以下の情報ウインドウのサイズ：追跡、UFOの軌跡\"\n  STR_SHOW_SLACKING_INDICATOR: \"有閑メーター\"\n  STR_SHOW_SLACKING_INDICATOR_DESC: \"ONにすると仕事をしていない科学者とエンジニアの数が表示されます\"\n  STR_SHOW_MAINTENANCE_TIME: \"機体整備時間の表示\"\n  STR_SHOW_MAINTENANCE_TIME_DESC: \"{ALT}0>{ALT} 非表示 {ALT}1>{ALT} 進行中の整備期間のみ表示 {ALT}2>{ALT} 全てを一括表示 (修理 + 装弾 + 燃料)\"\n  STR_SHOW_ETA: \"推定戦闘時間を表示\"\n  STR_SHOW_ETA_DESC: \"{ALT}0>{ALT} 非表示 {ALT}1>{ALT} 停止中の標的のみ表示 {ALT}2>{ALT} 移動中の標的に対する戦闘の推定時間を表示\"\n  STR_UFO_LANDING_ALERT: \"UFO着陸警報\"\n  STR_UFO_LANDING_ALERT_DESC: \"オンにすると探知済みのUFOが着陸した際に警告が表示されます。\"\n  STR_REMEMBER_DISABLED_CRAFT_WEAPONS: \"使用オフにした機体用兵器を記憶\"\n  STR_REMEMBER_DISABLED_CRAFT_WEAPONS_DESC: \"空中戦の時に使用オフにした兵器を次回まで記憶し、基地に帰還後もその武器の弾薬は補充されなくなります\"\n  STR_GEO_EVENT_INSTANT_DELIVERY: \"イベントアイテムの即時入手\"\n  STR_GEO_EVENT_INSTANT_DELIVERY_DESC: \"ONにするとジオスケープ上のイベントで入手したアイテムが即納入されます。オフの場合は1時間後に到着\"\n  STR_SHOW_BASE_NAME_IN_POPUPS: \"基地名もポップアップに表示\"\n  STR_SHOW_BASE_NAME_IN_POPUPS_DESC: \"オンにするとポップアップウインドウ内に対象基地の名が表示されます。(研究などの完了通知時）\"\n  STR_ALTERNATE_CRAFT_EQUIPMENT_MANAGEMENT: \"機体用の代替装備\"\n  STR_ALTERNATE_CRAFT_EQUIPMENT_MANAGEMENT_DESC: \"オンにすると基地間の兵士や機体の際に装備品込みで移動させます (可能な場合)\"\n  STR_BASE_INFO_SCALE: \"基地情報の大きなバーを自動スケール\"\n  STR_BASE_INFO_SCALE_DESC: \"ONにするとサイズ140超えのバーはUIに収まる様に自動でサイズ調整\"\n  STR_HIGHLIGHT_NEW: \"新しい出来事をハイライト\"\n  STR_HIGHLIGHT_NEW_DESC: \"ONにすると新しい製造やUfoペディアの新記事の追加時に異なる文字色で告知されます\"\n  STR_RESEARCH_SCROLL_SPEED: \"マウスホイールで研究速度調整\"\n  STR_RESEARCH_SCROLL_SPEED_DESC: \"科学者のプロジェクトへの参加と除名を'現在進行中の研究'のUI上でマウスのホイールボタンで直接操作可能にする\"\n  STR_RESEARCH_SCROLL_SPEED_CTRL: \"マウスホイールで研究速度調整 (+ Ctrlキー)\"\n  STR_RESEARCH_SCROLL_SPEED_CTRL_DESC: \"科学者のプロジェクトへの参加と除名を'現在進行中の研究'のUI上でマウスのホイールボタンで直接操作可能にする\"\n  STR_MANUFACTURE_FILTER_SUPPLIES_OK: \"製造可能フィルタ\"\n  STR_MANUFACTURE_FILTER_SUPPLIES_OK_DESC: \"ONにすると材料が足りている製造のみ表示\"\n  STR_MANUFACTURE_SCROLL_SPEED: \"マウスホイールで製造速度調整\"\n  STR_MANUFACTURE_SCROLL_SPEED_DESC: \"技術者の製造の参加と除名を'現在進行中の研究'のUI上でマウスのホイールボタンで直接操作可能にする\"\n  STR_MANUFACTURE_SCROLL_SPEED_CTRL: \"マウスホイールで製造速度調整 (+ Ctrlキー)\"\n  STR_MANUFACTURE_SCROLL_SPEED_CTRL_DESC: \"技術者の製造への参加と除名を'現在進行中の研究'のUI上でマウスのホイールボタンで直接操作可能にする\"\n  STR_PERSONAL_LAYOUT_INCLUDING_ARMOR: \"個人兵装にアーマー追加\"\n  STR_PERSONAL_LAYOUT_INCLUDING_ARMOR_DESC: \"ONにすると個々の兵装のレイアウトセーブ時にアーマーも追加する\"\n  STR_MANUALPROMOTIONS: \"手動で昇進\"\n  STR_MANUALPROMOTIONS_DESC: \"有効にするとランクのアイコンをクリックして兵士の昇進と降格を手動で行えます\"\n  STR_WOUNDED_DEFEND_BASE_IF: \"負傷兵も基地防衛 (HPがx%以上の者)\"\n  STR_WOUNDED_DEFEND_BASE_IF_DESC: \"負傷兵も設定%以上のHPがあれば基地防衛ミッションに参加します\"\n  STR_PLAY_BRIEFING_MUSIC_DURING_EQUIPMENT: \"ブリーフィング画面BGMの延長\"\n  STR_PLAY_BRIEFING_MUSIC_DURING_EQUIPMENT_DESC: \"装備画面＞バトルスケープに切り替わるまでブリーフィング画面のBGMを再生します。\"\n  STR_NIGHT_VISION_COLOR: \"ナイトビジョンの色変更\"\n  STR_NIGHT_VISION_COLOR_DESC: \"1から15の数値を入力し、陰影色を変えます\"\n  STR_AUTO_NIGHT_VISION_THRESHOLD: \"自動ナイトビジョン適用のしきい値\"\n  STR_AUTO_NIGHT_VISION_THRESHOLD_DESC: \"暗さがここで設定された値以上の時にナイトビジョンが自動適用されます\"\n  STR_SHOW_ACCURACY_ON_CROSSHAIR: \"クロスヘアに命中率\"\n  STR_SHOW_ACCURACY_ON_CROSSHAIR_DESC: \"{ALT}0>{ALT}非表示 {ALT}1>{ALT}UFO Extender accuracy がON時のみ表示 {ALT}2>{ALT}常時表示\"\n  STR_REACTION_FIRE_THRESHOLD: \"反応射撃のしきい値\"\n  STR_REACTION_FIRE_THRESHOLD_DESC: \"X-Comのユニットは（標的に対する）命中精度がしきい値より低い場合は反応射撃をしない\"\n  STR_AUTO_SELL: \"自動売却マネージャー\"\n  STR_AUTO_SELL_DESC: \"戦闘終了後の画面で報告されるアイテムの中で、以前売却したものを自動的に売却候補にします。\"\n  STR_AUTOMATICPROMOTIONS: \"自動昇進\"\n  STR_AUTOMATICPROMOTIONS_DESC: \"有効にするとミッション完了後に自動的に兵士の昇進が行われます\"\n  STR_OFF_CENTRE_SHOOTING: \"射線外への非軸射撃\"\n  STR_OFF_CENTRE_SHOOTING_DESC: \"射線が通らない時に射軸を僅かにずらし、自動調整して発砲する\"\n  STR_UNIFORM_SHOOTING_SPREAD: \"射撃の拡散率の統一\"\n  STR_UNIFORM_SHOOTING_SPREAD_DESC: \"射撃の拡散率を全方位的に統一化し、より集弾させる\"\n  STR_CRASHED_OR_LANDED: \"墜落/着陸ボタン\"\n  STR_CRASHED_OR_LANDED_DESC: \"ONにすると新規の戦闘画面で追加のボタンが表示される。F11キーを押すことでも表示を切り替えられる。{ALT}0>{ALT}非表示 {ALT}1>{ALT}墜落 {ALT}2>{ALT}着陸\"\n  STR_GRAPHS_ZOOM_IN: \"拡大 (グラフ)\"\n  STR_GRAPHS_ZOOM_OUT: \"縮小 (グラフ)\"\n  STR_MARK_ALL_AS_SEEN: \"全てを既知としてマーク\"\n  STR_SELL_ALL: \"全て売却\"\n  STR_SELL_ALL_BUT_ONE: \"一つ残して売却\"\n  STR_TRANSFER_ALL: \"全て移動\"\n  STR_REMOVE_SOLDIERS_FROM_ALL_CRAFTS: \"全ての乗り物から隊員を降ろす\"\n  STR_REMOVE_SOLDIERS_FROM_CRAFT: \"乗り物から隊員を降ろす\"\n  STR_REMOVE_EQUIPMENT_FROM_CRAFT: \"乗り物から装備品を降ろす\"\n  STR_REMOVE_ARMOR_FROM_ALL_CRAFTS: \"全ての乗り物から装備品を降ろす\"\n  STR_REMOVE_ARMOR_FROM_CRAFT: \"乗り物からアーマーを降ろす\"\n  STR_REMOVE_SOLDIERS_FROM_TRAINING: \"訓練中の隊員を復帰させる\"\n  STR_ADD_SOLDIERS_TO_TRAINING: \"訓練させる兵を指定\"\n  STR_INVENTORY_ARMOR: \"アーマー変更\"\n  STR_INVENTORY_AVATAR: \"外見変更\"\n  STR_INVENTORY_DIARY_LIGHT: \"デイライト点灯\"\n  STR_ACTION_ITEM_1: \"アクション１(精密射/使用)\"\n  STR_ACTION_ITEM_2: \"アクション２(急速射)\"\n  STR_ACTION_ITEM_3: \"アクション３(オート射)\"\n  STR_ACTION_ITEM_4: \"アクション４(近接)\"\n  STR_ACTION_ITEM_5: \"アクション５(投擲)\"\n  STR_INSTA_SAVE: \"瞬間セーブ\"\n  STR_TOGGLE_QUICK_SEARCH: \"戦場クイック視認のトグル\"\n  STR_TOGGLE_NIGHT_VISION: \"ナイトビジョンのトグル\"\n  STR_HOLD_NIGHT_VISION: \"短期ナイトビジョン\"\n  STR_SELECT_MUSIC_TRACK: \"BGMの選択\"\n  STR_TOGGLE_TOUCH_BUTTONS: \"タッチボタンのトグル\"\n  STR_TOGGLE_BRIGHTNESS: \"明暗トグル(見た目のみ)\"\n  STR_BRIEFING: \"作戦\"\n  STR_TOGGLE_DEBUG_MODE: \"デバッグモードのトグル\"\n  STR_DEBUG_KILL_ALL_ALIENS: \"デバッグ: エイリアンを全滅\"\n  STR_PHYSICAL_TRAINING: \"武術訓練\"\n  STR_REMAINING_TRAINING_FACILITY_CAPACITY: \"訓練可能人数> {ALT}{0}\"\n  STR_NO_WOUNDED: \"ー\"\n  STR_NO_QUEUED: \"+\"\n  STR_NO_DONE: \"完了\"\n  STR_NO_AMMO: \"弾切れ！\"\n  STR_START_FIRING: \"射撃！\"\n  STR_SKIP_FIRING: \"搭乗させる・・\"\n  STR_ALIEN_MISSILES_HAVE_DAMAGED_OUR_BASE: \"敵ミサイルにより基地にダメージ {0}\"\n  STR_ALIEN_MISSILES_HAVE_DESTROYED_OUR_BASE: \"敵ミサイルにより基地が潰滅 {0}\"\n  STR_STARTING_CONDITION_COMMANDER: \"本作戦には司令官の存在が不可欠\"\n  STR_STARTING_CONDITION_CRAFT: \"この乗り物は本ミッションでは不可\"\n  STR_STARTING_CONDITION_CRAFT_ALLOWED: \"この乗り物は本ミッションでは使用不可{NEWLINE}{NEWLINE}使用可: {0}\"\n  STR_STARTING_CONDITION_CRAFT_FORBIDDEN: \"この乗り物は本ミッションでは使用不可{NEWLINE}{NEWLINE}使用不可: {0}\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE: \"何名かの兵が参加不可\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE_ALLOWED: \"このミッションに参加できない兵が居ます{NEWLINE}{NEWLINE}許可された兵種: {0}\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE_FORBIDDEN: \"このミッションに参加できない兵が居ます{NEWLINE}{NEWLINE}禁止された兵種: {0}\"\n  STR_STARTING_CONDITION_ITEM: \"特殊アイテムが必要なミッション:{NEWLINE}{NEWLINE}{0}\"\n  STR_NOT_ENOUGH_FUEL_TO_REACH_TARGET: \"燃料不足！{SMALLLINE}目的地が航続距離を越えています\"\n  STR_TOO_MANY_ITEMS_ONBOARD: \"アイテムが多すぎます！{SMALLLINE}この機体にはそんなに搭載できません\"\n  STR_ARMOR_NOT_ALLOWED_ONBOARD: \"アーマーが搭載不可！{SMALLLINE}搭載禁止のアーマーを着た兵がいます\"\n  STR_FOLLOW_WING_LEADER_QUESTION: \"ウイングリーダーに追従しますか？\"\n  STR_ASSIGN_PILOTS: \"パイロットを任命・・\"\n  STR_NOT_ENOUGH_PILOTS: \"パイロットが足りません！{NEWLINE}最低人数: {0}\"\n  STR_DAILY_PILOT_EXPERIENCE: \"パイロットの日間経験値\"\n  STR_UFO_SHIELD_HIT: \"シールドに着弾！\"\n  STR_UFO_HIT_NO_DAMAGE: \"機体が弾いた！\"\n  STR_UFO_SHIELD_DOWN: \"敵シールド消滅！\"\n  STR_UFO_HIT_GLANCING: \"外した！\"\n  STR_INTERCEPTOR_SHIELD_HIT: \"シールドが耐えた！\"\n  STR_TRACTOR_BEAM_ENGAGED: \"牽引ビーム発射！\"\n  STR_TRACTOR_BEAM_DISENGAGED: \"牽引ビーム停止\"\n  STR_SELF_DESTRUCT_ACTIVATED: \"自爆装置起動！\"\n  STR_SELF_DESTRUCT_CANCELLED: \"自爆装置解除\"\n  STR_MISSILE_DAMAGED: \">>> ミサイル破損 <<<\"\n  STR_MISSILE_DESTROYED: \">>> ミサイルが破壊された <<<\"\n  STR_EXTENDED_LINKS: \"リンク\"\n  STR_AUTO_PATROL: \"自動パトロール\"\n  STR_ETA: \"ETA>{ALT}{0}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_FACILITY_AT_BASE: \" {0} が {1} の補給に不足： {2}\"\n  STR_UFO_STARTED_HUNTING: \"{0} が {1} を追撃\"\n  STR_CRAFT_IS_READY: \"{0} は {1} で準備完了\"\n  STR_ECONOMY_WARNING: \"{0} の資金と {1} の収入は低く、 {2} の維持費が足りません！何かを売ってこれ以上の借金は避けて下さい。資金減少: {3}\"\n  STR_SLACKING_INDICATOR: \"{0}:{1}\"\n  STR_TRAINING_INDICATOR: \"{0}:{1}\"\n  STR_EXTENDED_UC: \"EXTENDED\"\n  STR_RETURNING: \"帰還中\"\n  STR_INTERCEPTING: \"追跡中\"\n  STR_ESCORTING: \"護衛中\"\n  STR_EN_ROUTE: \"航行中\"\n  STR_PILOT_MISSING: \"搭乗者不在\"\n  STR_DAY_SHORT: \"{0}日\"\n  STR_HOUR_SHORT: \"{0}時\"\n  STR_PERFORMANCE_BONUS: \"成績ボーナス\"\n  STR_COUNTRY_HAS_CANCELLED_A_SECRET_PACT: \"{0} はエイリアンとの協定を破棄した為、プロジェクトへの復帰が認められました\"\n  STR_COUNTRIES_HAVE_CANCELLED_A_SECRET_PACT: \"{0} はエイリアンとの協定を破棄した為、プロジェクトへの復帰が認められました\"\n  STR_WE_CAN_NOW_RENT: \"雇用/購入可能になりました\"\n  STR_REQUIRED_BASE_SERVICES: \"必要な施設: {0}\"\n  STR_WE_CAN_NOW_BUILD: \"建築可能になりました\"\n  STR_WE_CAN_NOW_PURCHASE: \"購入可能になりました\"\n  STR_NOT_ENOUGH_LIVING_SPACE_AT_BASE: \"居住スペース不足{NEWLINE}{1}名{NEWLINE}基地：{NEWLINE}{0}\"\n  STR_INFO: \"報告\"\n  STR_DESPAWN_PENALTY: \"生成中止ペナルティ> {0}\"\n  STR_TRAINING_FINISHED: \"{0}で{NEWLINE}訓練が完了\"\n  STR_PSI_TRAINING_FINISHED: \"Psi 強化訓練完了{NEWLINE}{0}\"\n  STR_IGNORE_UC: \"無視\"\n  STR_UFO_TRACKER: \"UFOトラッカー\"\n  STR_UPDATE: \"更新\"\n  STR_LATEST_VERSION_INFO: \"あなたのOpenXcomは最新バージョンです\"\n  STR_MASTER_MOD_VERSION_REQUIRED_QUESTION: \"このModはベースゲームが v{0} でないと正常に動作しません。適用しますか？\"\n  STR_VERSION_REQUIRED_QUESTION: \"このModは予めOXCE v{0} が適用されていないと正常に動作しません。適用しますか？\"\n  STR_OPEN_MODS_FOLDER: \"開ける\"\n  STR_GLOBE_TEXTURE: \"地球のテクスチャ\"\n  STR_NOTES: \"備考\"\n  STR_NEW_NOTE: \"<NEW NOTE>\"\n  STR_ENGINE_OXC: \"OXC\"\n  STR_ENGINE_OXCE: \"OXCE\"\n  STR_ENGINE_OTHER: \"その他\"\n  STR_BASESCAPE: \"基地スケープ\"\n  STR_AI: \"AI\"\n  STR_PATH_ENERGY_COST: \"スタミナ\"\n  STR_PATH_ENERGY_COST_DESC: \"目的地に到達後の残りスタミナをクリックで表示\"\n  STR_VEHICLES_LOST: \"車両消失\"\n  STR_TEST_SCREEN: \"テスト画面\"\n  STR_PALETTE: \"色パレット:\"\n  STR_PREVIEW: \"プレビュー\"\n  STR_TINY_BORDERLESS: \"極小、境界なし\"\n  STR_TINY_BORDER: \"極小\"\n  STR_SMALL_LOW_CONTRAST: \"小\"\n  STR_SMALL_HIGH_CONTRAST: \"小、高コントラスト\"\n  STR_BIG_LOW_CONTRAST: \"大\"\n  STR_BIG_HIGH_CONTRAST: \"大、高コントラスト\"\n  STR_TEST_CASE: \"テストケース：\"\n  STR_RUN: \"選択したテストを行う！\"\n  STR_TESTS_STARTING: \"テスト開始・・・\"\n  STR_TESTS_ERRORS_FOUND: \"発見したエラーの数(重複の可能性あり)：{0}\"\n  STR_TESTS_NO_ERRORS_FOUND: \"エラーなし\"\n  STR_TESTS_FINISHED: \"テスト完了\"\n  STR_DETAILED_INFO_IN_LOG_FILE: \"詳細はopenxcom.logに記録されました\"\n  STR_RANK_NONE: \"ー\"\n  STR_DAMAGE_NONE: \"なし\"\n  STR_INFO_UFOPEDIA: \"情報\"\n  STR_COCKPIT_CAPACITY: \"パイロット>{ALT}{0}{ALT}\"\n  STR_MAXIMUM_RANGE: \"最大航続距離>{ALT}{0}{ALT}\"\n  STR_MINIMUM_RANGE: \"最短航続距離>{ALT}{0}{ALT}\"\n  STR_INFINITE_RANGE: \"N/A\"\n  STR_TRACTOR_BEAM_POWER: \"威力\"\n  STR_WEIGHT_PEDIA1: \"重量: {0}\"\n  STR_WEIGHT_PEDIA2: \"重量: {0}/{1}\"\n  STR_SHOT_TYPE_MELEE: \"近接攻撃\"\n  STR_ACCURACY_MODIFIER: \"命中率補正>{ALT} {0}\"\n  STR_POWER_BONUS: \"威力ボーナス>{ALT} {0}\"\n  STR_MULTIPLE_DIFFERENT_BONUSES: \"互換弾倉には重複ボーナスあり\"\n  STR_STATS_FOR_NERDS: \"ステータス一覧\"\n  STR_ARTICLE: \"記事>{ALT} {0}\"\n  STR_COMPATIBLE_AMMO: \"互換弾倉：\"\n  STR_BUILT_IN_ITEMS: \"内蔵アイテム：\"\n  STR_CLIP_SIZE_UNLIMITED: \"無限\"\n  STR_SHOTGUN_BEHAVIOR_OXCE: \"拡張\"\n  STR_INCLUDE_DEBUG: \"デバッグ\"\n  STR_INCLUDE_IDS: \"ID\"\n  STR_INCLUDE_DEFAULTS: \"デフォルト\"\n  STR_TRUE: \"はい\"\n  STR_FALSE: \"いいえ\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH: \"Psiスキル* Psi強度\"\n  STR_STRENGTH_AND_MELEE_ACCURACY: \"筋力*近接命中率\"\n  STR_STRENGTH_AND_THROWING_ACCURACY: \"筋力*投擲成功率\"\n  STR_FIRING_ACCURACY_AND_REACTIONS: \"射撃命中率*反応\"\n  STR_HEALTH_CURRENT: \"現在のHP\"\n  STR_MANA_CURRENT: \"現在のMP\"\n  STR_TIME_UNITS_CURRENT: \"TU残量\"\n  STR_STUN_LEVEL_CURRENT: \"現在のスタンレベル\"\n  STR_HEALTH_NORMALIZED: \"HPが通常化\"\n  STR_MANA_NORMALIZED: \"MPが通常化\"\n  STR_TIME_UNITS_NORMALIZED: \"TUが通常化\"\n  STR_ENERGY_NORMALIZED: \"スタミナが通常化\"\n  STR_MORALE_NORMALIZED: \"士気が通常化\"\n  STR_STUN_LEVEL_NORMALIZED: \"スタンレベルが通常化\"\n  STR_ENERGY_REGENERATION: \"スタミナの自然回復\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH_ABBREVIATION: \"Psi技xPsi強\"\n  STR_STRENGTH_AND_MELEE_ACCURACY_ABBREVIATION: \"筋力x近接\"\n  STR_STRENGTH_AND_THROWING_ACCURACY_ABBREVIATION: \"筋力x投擲\"\n  STR_FIRING_ACCURACY_AND_REACTIONS_ABBREVIATION: \"精度x反応\"\n  STR_HEALTH_CURRENT_ABBREVIATION: \"現在のHP\"\n  STR_MANA_CURRENT_ABBREVIATION: \"現在のMP\"\n  STR_TIME_UNITS_CURRENT_ABBREVIATION: \"TU残量\"\n  STR_STUN_LEVEL_CURRENT_ABBREVIATION: \"現在のスタンレベル\"\n  STR_HEALTH_NORMALIZED_ABBREVIATION: \"HPが通常化\"\n  STR_MANA_NORMALIZED_ABBREVIATION: \"MPが通常化\"\n  STR_TIME_UNITS_NORMALIZED_ABBREVIATION: \"TUが通常化\"\n  STR_ENERGY_NORMALIZED_ABBREVIATION: \"スタミナが通常化\"\n  STR_MORALE_NORMALIZED_ABBREVIATION: \"士気が通常化\"\n  STR_STUN_LEVEL_NORMALIZED_ABBREVIATION: \"スタンレベルが通常化\"\n  STR_ENERGY_REGENERATION_ABBREVIATION: \"スタミナの自然回復\"\n  STR_TIME_UNITS_SCALED: \"TU制限\"\n  STR_STAMINA_SCALED: \"スタミナ制限\"\n  STR_HEALTH_SCALED: \"HP制限\"\n  STR_BRAVERY_SCALED: \"勇敢さ制限\"\n  STR_REACTIONS_SCALED: \"反応制限\"\n  STR_FIRING_ACCURACY_SCALED: \"命中率制限\"\n  STR_THROWING_ACCURACY_SCALED: \"投てき成功率制限\"\n  STR_STRENGTH_SCALED: \"筋力制限\"\n  STR_PSIONIC_STRENGTH_SCALED: \"Psi強度制限\"\n  STR_PSIONIC_SKILL_SCALED: \"Psiスキル制限\"\n  STR_MELEE_ACCURACY_SCALED: \"近接命中率制限\"\n  STR_MANA_POOL_SCALED: \"MP制限\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH_SCALED: \"Psiスキル*Psi強度の制限\"\n  STR_STRENGTH_AND_MELEE_ACCURACY_SCALED: \"筋力*近接命中率の制限\"\n  STR_STRENGTH_AND_THROWING_ACCURACY_SCALED: \"筋力*投てき成功率の制限\"\n  STR_FIRING_ACCURACY_AND_REACTIONS_SCALED: \"命中率*反応の制限\"\n  STR_TIME_UNITS_SCALED_ABBREVIATION: \"制限されたTU\"\n  STR_STAMINA_SCALED_ABBREVIATION: \"制限されたSTA\"\n  STR_HEALTH_SCALED_ABBREVIATION: \"制限されたHP\"\n  STR_BRAVERY_SCALED_ABBREVIATION: \"制限されたBRV\"\n  STR_REACTIONS_SCALED_ABBREVIATION: \"制限されたREA\"\n  STR_FIRING_ACCURACY_SCALED_ABBREVIATION: \"制限されたACC\"\n  STR_THROWING_ACCURACY_SCALED_ABBREVIATION: \"制限されたTHR\"\n  STR_STRENGTH_SCALED_ABBREVIATION: \"制限されたSTR\"\n  STR_PSIONIC_STRENGTH_SCALED_ABBREVIATION: \"制限されたPST\"\n  STR_PSIONIC_SKILL_SCALED_ABBREVIATION: \"制限されたPSK\"\n  STR_MELEE_ACCURACY_SCALED_ABBREVIATION: \"制限されたMEL\"\n  STR_MANA_POOL_SCALED_ABBREVIATION: \"制限されたMAN\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH_SCALED_ABBREVIATION: \"制限されたPSK*PST\"\n  STR_STRENGTH_AND_MELEE_ACCURACY_SCALED_ABBREVIATION: \"制限されたSTR*MEL\"\n  STR_STRENGTH_AND_THROWING_ACCURACY_SCALED_ABBREVIATION: \"制限されたSTR*THR\"\n  STR_FIRING_ACCURACY_AND_REACTIONS_SCALED_ABBREVIATION: \"制限されたACC*REA\"\n  STR_COST_TIME: \"時間\"\n  STR_COST_ENERGY: \"スタミナ\"\n  STR_COST_MORALE: \"士気\"\n  STR_COST_HEALTH: \"HP\"\n  STR_COST_STUN: \"気絶\"\n  STR_COST_MANA: \"MP\"\n  STR_COST_BUILD: \"建造済み\"\n  STR_COST_REFUND: \"環金\"\n  STR_DAMAGE_10: \"10\"\n  STR_DAMAGE_11: \"11\"\n  STR_DAMAGE_12: \"12\"\n  STR_DAMAGE_13: \"13\"\n  STR_DAMAGE_14: \"14\"\n  STR_DAMAGE_15: \"15\"\n  STR_DAMAGE_16: \"16\"\n  STR_DAMAGE_17: \"17\"\n  STR_DAMAGE_18: \"18\"\n  STR_DAMAGE_19: \"19\"\n  STR_NAUTICAL_MILES: \"{0} 海里\"\n  STR_KILOMETERS_PER_HOUR: \"{0} km/h\"\n  STR_SECONDS_LONG: \"{0} 秒\"\n  STR_RACE_BONUS: \"種族ボーナス\"\n  STR_FOR_DIFFICULTY: \"難易度より: {0}\"\n  STR_NOT_AWARDED_YET: \"叙勲なし\"\n"
  },
  {
    "path": "bin/common/Language/OXCE/ko.yml",
    "content": "ko:\n  STR_CANNOT_DISMANTLE_FACILITY_UPGRADING: \"시설을 철거할 수 없다!{SMALLLINE}시설은 개수 중에는 제거될 수 없다.\"\n  STR_CANNOT_UPGRADE_FACILITY_ALREADY_UPGRADING: \"여기 지을 수 없다!{SMALLLINE}기존 시설은 이미 개수 중이다.\"\n  STR_CANNOT_UPGRADE_FACILITY_WRONG_SIZE: \"여기 지을 수 없다!{SMALLLINE}선택된 시설은 반드시 기존 시설을 완전히 덮어야 한다.\"\n  STR_CANNOT_UPGRADE_FACILITY_WRONG_TYPE: \"여기 지을 수 없다!{SMALLLINE}기존 시설은 선택된 시설로 개수가 될 수 없다.\"\n  STR_CANNOT_UPGRADE_FACILITY_DISALLOWED: \"여기 지을 수 없다!{SMALLLINE}기존 시설은 개수가 될 수 없다.\"\n  STR_CANNOT_BUILD_QUEUE_OFF: \"여기 지을 수 없다!{SMALLLINE}연결하는 시설은 반드시 건설이 먼저 끝나야 한다.\"\n  STR_CANNOT_BUILD_UPGRADE_ONLY: \"여기 지을 수 없다!{SMALLLINE}이 시설은 또 다른 시설의 개수로만 지어질 수 있다.\"\n  STR_FACILITY_FORBIDDEN_BY_OTHER: \"여기 지을 수 없다!{SMALLLINE}어떤 기존 시설이 이 시설의 건설을 금지한다.\"\n  STR_FACILITY_OTHER_FORBIDDEN_BY_THIS: \"여기 지을 수 없다!{SMALLLINE}어떤 기존 시설은 이 시설에 의해 건설 금지될 것이다.\"\n  STR_NOT_ENOUGH_ITEMS: \"재료가 충분하지 않다!{SMALLLINE}우리는 이 시설을 짓기 위해 더 많은 자원이 필요하다.{NEWLINE}부족분> {0}: {1}개\"\n  STR_ID: \"ID\"\n  STR_FIRST_LETTER: \"두문자\"\n  STR_SOLDIER_TYPE: \"병사 유형\"\n  STR_IDLE_DAYS: \"대기 기간\"\n  STR_MANA: \"마나\"\n  STR_MANA_POOL: \"최대 마나\"\n  STR_MANA_MISSING: \"잃은 마나\"\n  STR_LOAD_CRAFT_LOADOUT_TEMPLATE: \"기체 화물 적재\"\n  STR_EMPTY_SLOT_N: \"빈칸 {0}\"\n  STR_UNNAMED_SLOT_N: \"이름없는 칸 {0}\"\n  STR_ADD_ON_TOP: \"위에 더함\"\n  STR_SAVE_CRAFT_LOADOUT_TEMPLATE: \"기체 화물 저장\"\n  STR_SAVE_UC: \"저장\"\n  STR_ALL: \"전부\"\n  STR_EQUIPPED: \"적재된 것\"\n  STR_NOT_EQUIPPED: \"적재되지 않은 것\"\n  STR_UNASSIGNED: \"다른 것\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED_BY_SIZE: \"더 이상 장비를 적재할 수 없다!{SMALLLINE}최대 저장 공간: {0}\"\n  STR_PILOTS: \"조종사\"\n  STR_SHIELD: \"방어막>{ALT}{0}\"\n  STR_CRAFT_SKIN_ID: \"[{0}]\"\n  STR_SELECT_PILOT: \"조종사 선택\"\n  STR_PILOTS_FOR_CRAFT: \"{0}에 탑승할 조종사\"\n  STR_PILOTS_REQUIRED: \"요구되는 조종사: {ALT}{0}\"\n  STR_ADD_PILOT: \"조종사 추가\"\n  STR_REMOVE_ALL_PILOTS: \"모든 조종사 제거\"\n  STR_ACCURACY_BONUS: \"명중 보너스:\"\n  STR_DODGE_BONUS: \"회피 보너스:\"\n  STR_APPROACH_SPEED: \"접근 속도:\"\n  STR_COWARDLY: \"겁내며(-50%)\"\n  STR_NORMAL: \"평범하게\"\n  STR_BOLD: \"대담하게(+50%)\"\n  STR_VERY_BOLD: \"무모하게(+100%)\"\n  STR_ARMOR_GROUP_NOT_ALLOWED: \"이 유형의 갑옷은 탑승이 허용되지 않는다.\"\n  STR_SOLDIER_GROUP_NOT_ALLOWED: \"이 유형의 병사는 탑승이 허용되지 않는다.\"\n  STR_SOLDIER_GROUP_NOT_SAME: \"이 유형의 병사는 탑승한 다른 병사와 같이 타지 못한다.\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW: \"미리보기\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_SAVED: \"미리보기 *\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_BRIEFING: \"이 특징은 당신에게 전투 시작 시 당신의 유닛 배치를 미리 보고 조정하게 해 준다. 당신은 무제한의 이동력을 지닌다. 유효한 유닛 위치를 강조하기 위해 'ALT'키를 누르고 있어라. 맞춤 배치를 저장하려면 '임무 중단' 아이콘을 눌러라. 미리보기를 끝내려면 '턴 종료'를 눌러라.{NEWLINE}기체에 어떠한 병사 또는 차량을 추가하는 것이 저장된 맞춤 배치를 자동으로 무효화한다는 걸 주목하라. 맞춤 배치의 존재는 '미리보기' 버튼에 있는 * 표로 알려 준다.\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_BRIEFING_DUMMY: \"이 특징은 이러한 유형의 기체에 대한 배치표를 미리 보고 수정하도록 한다. 어떠한 변경도 당신의 모든 현재 기체와 또한 이 캠페인에서 이후에 사거나 제조한 어떠한 기체에도 적용될 것이다. 당신은 최대 숫자의 병사로 시작한다. 각각의 병사는 배치표의 한 열을 나타낸다. 병사 이름은 열 번호에 대응된다. 2x2 유닛의 공간을 제공하려면, 4명의 병사를 2x2 사각형 안에 놓아라. 만약 공간이 제공되지 않는다면, 2x2유닛은 실제 전투에서 잃어버릴 것이다.\"\n  STR_BASE_DEFENSE_BRIEFING_PREVIEW: \"이 특징은 당신의 기지를 미리 보게 해 준다.{NEWLINE}보고 즐기시오!{NEWLINE}{NEWLINE}미리보기를 끝내려면 '턴 종료' 아이콘을 눌러라.\"\n  STR_NOT_ENOUGH_CARGO_SPACE: \"쓸 수 있는 화물 공간이 충분하지 않다!{SMALLLINE}다른 모듈을 이용하거나 할당된 승무원을 줄여라.\"\n  STR_NOT_ENOUGH_STORAGE_SPACE_1: \"쓸 수 있는 저장 공간이 충분하지 않다!{SMALLLINE}물품이 너무 많다! 다른 모듈을 이용하거나 할당된 장비를 줄여라.\"\n  STR_NOT_ENOUGH_STORAGE_SPACE_2: \"쓸 수 있는 저장 공간이 충분하지 않다!{SMALLLINE}이 물품은 너무 많은 공간을 차지한다! 다른 모듈을 이용하거나 할당된 장비의 규모를 줄여라.\"\n  STR_REFUND_VALUE: \"판매가>{ALT}{0}\"\n  STR_REFUND_VALUE_NEGATIVE: \"지출> {ALT}{0}\"\n  STR_PRODUCTION_OVERVIEW: \"생산 개요\"\n  STR_RESEARCH_DIARY: \"연구 일지\"\n  STR_DISCOVERY_SOURCE_BASE: \"이 물품은 연구 과제 중 발견되었다.{NEWLINE}연구 기지> {ALT}{1}{ALT}{NEWLINE}물품 코드> {ALT}{0}{ALT}\"\n  STR_DISCOVERY_SOURCE_FREE_FROM: \"이 물품은 또 다른 연구 과제에서 공짜로 주어졌다.{NEWLINE}다음 연구 과제에서> {ALT}{2}{ALT}{NEWLINE}{ALT}{1}{ALT} -> {ALT}{0}{ALT}\"\n  STR_DISCOVERY_SOURCE_FREE_AFTER: \"이 기술 물품은 자동으로 발견되었다.{NEWLINE}다음 연구 과제 후> {ALT}{2}{ALT}{NEWLINE}{ALT}{1}{ALT} -> {ALT}{0}{ALT}\"\n  STR_DISCOVERY_SOURCE_MISSION: \"이 물품은 임무 보상으로 공짜로 주어졌다.{NEWLINE}임무 유형> {ALT}{2}{ALT}{NEWLINE}{ALT}{1}{ALT} -> {ALT}{0}{ALT}\"\n  STR_DISCOVERY_SOURCE_EVENT: \"이 물품은 이벤트 보상으로 공짜로 주어졌다.{NEWLINE}이벤트 유형> {ALT}{2}{ALT}{NEWLINE}{ALT}{1}{ALT} -> {ALT}{0}{ALT}\"\n  STR_RESEARCH_OVERVIEW: \"연구 개요\"\n  STR_PRISONER_OVERVIEW: \"수용자 개요\"\n  STR_PRISONER: \"수용자\"\n  STR_PRISONER_AMOUNT: \"숫자\"\n  STR_PRISONER_INTERROGATED: \"심문중\"\n  STR_TOTAL_IN_PRISON: \"이용되는 공간>{ALT}{0}\"\n  STR_TOTAL_INTERROGATED: \"심문중>{ALT}{0}\"\n  STR_PRISON_TYPE: \"외계인 격리실\"\n  STR_KILL_SELECTED: \"사살\"\n  STR_SELL_SELECTED: \"판매\"\n  STR_GO_TO_TRANSFERS: \"이송...\"\n  STR_PRISON_CLEANUP: \"감옥 비우기\"\n  STR_TOPIC: \"주제>{ALT}{0}\"\n  STR_SHOW_ALL: \"전부 표시\"\n  STR_NO_DEPENDENCIES: \"관련 없음\"\n  STR_DIRECT_DEPENDENCIES: \"직접 연관\"\n  STR_LEVEL_2_DEPENDENCIES: \"한 다리 건너 연관\"\n  STR_LEVEL_3_DEPENDENCIES: \"두 다리 건너 연관\"\n  STR_LEVEL_4_DEPENDENCIES: \"세 다리 건너 연관\"\n  STR_MORE_DEPENDENCIES: \"네 다리 이상 건너 연관...\"\n  STR_END_OF_SEARCH: \"검색 종료.\"\n  STR_FALLBACK_PRODUCTION: \"대체\"\n  STR_REFUND_PRODUCTION: \"환불!\"\n  STR_HOURS_PER_UNIT: \"유닛 당 시간>{ALT}{0}\"\n  STR_PERSON_JOINING: \"합류한 사람\"\n  STR_RANDOM_PRODUCTION_DISCLAIMER: \"무작위 생산!\"\n  STR_OTHER_EMPLOYEES: \"기타 직원 & 물품\"\n  STR_SHOW_ONLY_NEW: \"새로운 것만 표시\"\n  STR_FILTER_DEFAULT: \"기본\"\n  STR_FILTER_DEFAULT_SUPPLIES_OK: \"기본(재료 있음)\"\n  STR_FILTER_DEFAULT_NO_SUPPLIES: \"기본(재료 없음)\"\n  STR_FILTER_FACILITY_REQUIRED: \"생산 시설 부재\"\n  STR_FILTER_HIDDEN: \"숨겨짐\"\n  STR_FILTER_EQUIPPED: \"적재된 것\"\n  STR_FILTER_MISSING: \"재료 부재\"\n  STR_SORT_DEFAULT: \"기본\"\n  STR_SORT_BY_COST: \"가격순\"\n  STR_SORT_BY_NAME: \"이름순\"\n  STR_RANDOM_PRODUCTION_SUMMARY: \"요약\"\n  STR_NOT_ENOUGH_PRISON_SPACE: \"외계인 격리실이 충분하지 않다!{SMALLLINE}새 외계인 격리실을 짓거나 다른 기지로 외계인을 이송하라.\"\n  STR_MONTHLY_ITEM_PURCHASE_LIMIT_EXCEEDED: \"월 구매 한도를 초과했다!{SMALLLINE}더 많은 물품은 다음 달에 살 수 있을 것이다.\"\n  STR_MONTHLY_CRAFT_PURCHASE_LIMIT_EXCEEDED: \"월 구매 한도를 초과했다!{SMALLLINE}더 많은 기체는 다음 달에 살 수 있을 것이다.\"\n  STR_MONTHLY_SOLDIER_HIRING_LIMIT_EXCEEDED: \"월 고용 한도를 초과했다!{SMALLLINE}더 많은 인력은 다음 달에 고용할 수 있을 것이다.\"\n  STR_NOT_ENOUGH_CRAFT_SPACE: \"적재 공간이 충분하지 않다!\"\n  STR_SELECT_AVATAR_FOR: \"{0}{NEWLINE}의 외형 선택\"\n  STR_SOLDIER_BONUSES_FOR: \"{0}{NEWLINE}의 병사 보너스\"\n  STR_SUMMARY: \"요약\"\n  STR_MANA_RECOVERY: \"마나 회복량> {ALT}{0}\"\n  STR_HEALTH_RECOVERY: \"체력 회복량> {ALT}{0}\"\n  STR_BONUSES_BUTTON: \"+\"\n  STR_PROMOTE_SOLDIER: \"진급/강등{NEWLINE}{0} {1}\"\n  STR_RANK_HEADER: \"계급\"\n  STR_OPENINGS_HEADER: \"오프닝\"\n  STR_KILLER_AND_WEAPON: \"{0}, {1}\"\n  STR_TRAINING: \"훈련중\"\n  STR_SOLDIER_INFO: \"병사 정보\"\n  STR_SELECT_TRANSFORMATION_FOR: \"{0}{NEWLINE}의 변신을 선택\"\n  STR_TRANSFORMATIONS_BUTTON: \"^\"\n  STR_TRANSFER_TIME: \"이송 시간>{ALT}{0}\"\n  STR_RECOVERY_TIME: \"회복 시간>{ALT}{0}\"\n  STR_CURRENT_STATS: \"현재 능력치\"\n  STR_CHANGES: \"변동\"\n  STR_CHANGES_MIN: \"변동 (최소)\"\n  STR_CHANGES_MAX: \"변동 (최대)\"\n  STR_BONUS_STATS: \"보너스 능력치\"\n  STR_TRANSFORMATIONS_OVERVIEW: \"변신 개요\"\n  STR_PROJECT_NAME: \"과제 이름\"\n  STR_AVAILABLE_MATERIALS: \"쓸 수 있는 재료\"\n  STR_ELIGIBLE_SOLDIERS: \"자격을 갖춘 병사\"\n  STR_SHOW_ONLY_ELIGIBLE: \"자격을 갖춘 병사만 보기\"\n  STR_ALL_SOLDIER_TYPES: \"모든 병사 유형\"\n  STR_ALL_SOLDIERS: \"모든 병사\"\n  STR_HEALTHY_SOLDIERS: \"건강한 병사\"\n  STR_WOUNDED_SOLDIERS: \"다친 병사\"\n  STR_DEAD_SOLDIERS: \"죽은 병사\"\n  STR_GRAND_TOTAL: \"총계\"\n  STR_AVAILABLE_TOPICS: \"쓸 수 있는 주제\"\n  STR_QS_THREE_LETTERS_A: \"빠른 검색창에\"\n  STR_QS_THREE_LETTERS_B: \"3글자 이상 입력하세요-미작동\"\n  STR_M_FLAG: \"[m]\"\n  STR_F_FLAG: \"[f]\"\n  STR_I_FLAG: \"[i]\"\n  STR_C_FLAG: \"[c]\"\n  STR_THIS_FEATURE_IS_DISABLED_1: \"이 특징은 비활성화되었다.\"\n  STR_THIS_FEATURE_IS_DISABLED_2: \"이 특징은 비활성화되었다.\"\n  STR_THIS_FEATURE_IS_DISABLED_3: \"이 특징은 비활성화되었다.\"\n  STR_THIS_FEATURE_IS_DISABLED_4: \"이 특징은 비활성화되었다.\"\n  STR_THIS_FEATURE_IS_DISABLED_5: \"이 특징은 비활성화되었다.\"\n  STR_TECH_TREE_VIEWER: \"기술개발도 열람기\"\n  STR_SELECT_TOPIC: \"주제 선택\"\n  STR_RESEARCH_PROGRESS: \"진도>{ALT} {0}%\"\n  STR_ITEM_DESTROYED: \"부서지는 물품:\"\n  STR_ITEM_REQUIRED: \"요구되는 물품:\"\n  STR_SERVICES_REQUIRED: \"요구되는 기능:\"\n  STR_SERVICES_PROVIDED: \"제공되는 기능:\"\n  STR_SERVICES_FORBIDDEN: \"금지되는 기능:\"\n  STR_REQUIRES: \"요구사항:\"\n  STR_DEPENDS_ON: \"아래에 연관:\"\n  STR_UNLOCKED_BY: \"아래에 의해 해금:\"\n  STR_DISABLED_BY: \"아래에 의해 비활성화:\"\n  STR_REENABLED_BY: \"아래에 의해 재활성화:\"\n  STR_GET_FOR_FREE_FROM: \"아래에 의해 공짜 획득:\"\n  STR_IS_LOOKUP_OF: \"아래의 색인:\"\n  STR_LOOKUP: \"색인:\"\n  STR_SPAWNED_ITEMS: \"생성되는 물품:\"\n  STR_SPAWNED_EVENT: \"생성되는 이벤트:\"\n  STR_REQUIRED_BY: \"아래의 요구사항:\"\n  STR_REQUIRED_BY_TRANSFORMATIONS: \"아래 변신의 요구사항:\"\n  STR_LEADS_TO: \"아래의 단서:\"\n  STR_UNLOCKS: \"아래를 해금:\"\n  STR_DISABLES: \"아래를 비활성화:\"\n  STR_REENABLES: \"아래를 재활성화:\"\n  STR_GIVES_ONE_FOR_FREE_SEQ: \"아래 중 하나를 공짜로 제공(순차적):\"\n  STR_GIVES_ONE_FOR_FREE: \"아래 중 하나를 공짜로 제공:\"\n  STR_RESEARCH_REQUIRED: \"요구되는 연구:\"\n  STR_RESEARCH_REQUIRED_USE: \"요구되는 연구(사용 시):\"\n  STR_RESEARCH_REQUIRED_BUY: \"요구되는 연구(구매 시):\"\n  STR_SERVICES_REQUIRED_BUY: \"요구되는 기능(구매 시):\"\n  STR_PRODUCED_BY: \"아래에 의해 생산:\"\n  STR_SPAWNED_BY: \"아래에 의해 생성:\"\n  STR_MATERIALS_REQUIRED: \"요구되는 재료:\"\n  STR_TTV_COST_PER_UNIT: \"유닛 당 비용:\"\n  STR_TTV_ENGINEER_HOURS: \"작업 인시:\"\n  STR_TTV_WORK_SPACE_REQUIRED: \"요구되는 작업 공간:\"\n  STR_ITEMS_PRODUCED: \"생산되는 물품:\"\n  STR_PERSON_RECRUITED: \"고용되는 인력:\"\n  STR_UNLOCKS_ARCS: \"아래 분기 해금:\"\n  STR_DISABLES_ARCS: \"아래 분기 비활성화:\"\n  STR_UNLOCKS_MISSIONS: \"아래 임무 해금:\"\n  STR_DISABLES_MISSIONS: \"아래 임무 비활성화:\"\n  STR_UNLOCKS_EVENTS: \"아래 이벤트 해금:\"\n  STR_DISABLES_EVENTS: \"아래 이벤트 비활성화:\"\n  STR_AFFECTS_GAME_PROGRESSION: \"게임 진행에 영향을 줌!\"\n  STR_ITEMS_AT_DESTINATION: \"행선지에 있는 물품\"\n  STR_PRISONERS: \"수용자\"\n  STR_ARMORS: \"갑옷\"\n  STR_FILTER_RESEARCHED: \"전부 연구되었음\"\n  STR_FILTER_RESEARCHABLE: \"연구 가능\"\n  STR_CRAFT_DEPLOYMENT_QUESTION: \"기체의 배치를 저장하는가?\"\n  STR_MUST_USE_BOTH_HANDS: \"이걸 사용하는 데 양손 모두가 요구된다!\"\n  STR_NOT_ENOUGH_MORALE: \"사기가 충분하지 않다!\"\n  STR_NOT_ENOUGH_HEALTH: \"체력이 충분하지 않다!\"\n  STR_NOT_ENOUGH_MANA: \"마나가 충분하지 않다!\"\n  STR_NOT_ENOUGH_STUN: \"기절 수준이 너무 높다!\"\n  STR_MIND_CONTROL_SUCCESSFUL_ALT: \"행동 성공\"\n  STR_LINE_OF_SIGHT_REQUIRED: \"시선(LoS)을 요구한다.\"\n  STR_CENTER_ON_WOUNDED_FRIEND: \"다친 동료를 화면 가운데로\"\n  STR_CENTER_ON_DIZZY_FRIEND: \"어지러운 동료를 화면 가운데로\"\n  STR_BUG_HUNT_ACTIVATED: \"소탕 모드 활성화: 적이 미니맵에 보인다!\"\n  STR_QUICK_MODE_ACTIVATED: \"우사인 볼트 모드가 활성화되었다.{NEWLINE}끄려면 컨트롤+S를 눌러라.\"\n  STR_QUICK_MODE_DEACTIVATED: \"우사인 볼트 모드가 꺼졌다.\"\n  STR_SINGLE_MAP_LAYER_ACTIVATED: \"단일 층 맵 모드가 활성화되었다.{NEWLINE}끄려면 컨트롤+C를 눌러라.\"\n  STR_SINGLE_MAP_LAYER_DEACTIVATED: \"단일 층 맵 모드가 꺼졌다.\"\n  STR_TARGET_ENEMY: \"; 표적 = 적\"\n  STR_TARGET_NEUTRAL: \"; 표적 = 중립\"\n  STR_TARGET_FRIEND: \"; 표적 = 아군\"\n  STR_TARGET_YOURSELF: \"; 표적 = 자신\"\n  STR_TARGET_ON_THE_GROUND: \"(지면에)\"\n  STR_USE_SPECIAL_ITEM: \"특별 물품 이용\"\n  STR_NO_EXPERIENCE_YET: \"아직 경험을 얻지 못한 이:\"\n  STR_OPERATION_UC: \"작전> {0}\"\n  STR_WHAT_CAN_I_WEAR: \"내가 입을 수 있는 것은?\"\n  STR_STARTING_CONDITION_ARMORS_FORBIDDEN: \"이 임무는 특정 복장을 요구한다.{NEWLINE}{NEWLINE}금지되는 갑옷 유형: {0}\"\n  STR_STARTING_CONDITION_ARMORS_ALLOWED: \"이 임무는 특정 복장을 요구한다.{NEWLINE}{NEWLINE}허용되는 갑옷 유형: {0}\"\n  STR_MISSION_OVER: \"임무 완료.\"\n  STR_UNITS_WITH_FATAL_WOUNDS:\n    other: \"우리 중 {N} 명은 아직 치명상을 입은 상태다.\"\n  STR_END_MISSION_QUESTION: \"임무 종료?\"\n  STR_LOOT: \"전리품\"\n  STR_SELL: \"매각\"\n  STR_LIVE_ALIENS_SURRENDERED: \"항복한 적\"\n  STR_MISSION_ABORTED: \"중단한 임무\"\n  STR_VIPS_SAVED: \"구조된 VIP\"\n  STR_VIPS_LOST: \"잃은 VIP\"\n  STR_BOUNTY: \"현상금\"\n  STR_MANA_ABBREVIATION: \"MAN\"\n  STR_EXPERIENCE_OVERVIEW: \"경험치 개요\"\n  STR_CANNOT_PLACE_ITEM_INTO_THIS_SECTION: \"저 물품을 거기에 놓는 건 허용되지 않는다.{NEWLINE}이유를 묻지 마라!\"\n  STR_ONE_HAND_MUST_BE_EMPTY: \"적어도 한 손은 반드시 비어야 한다!\"\n  STR_LOAD_EQUIPMENT_TEMPLATE: \"장비 템플릿 불러오기\"\n  STR_SAVE_EQUIPMENT_TEMPLATE: \"장비 템플릿 저장하기\"\n  STR_FIRING_SHORT: \"사격>{ALT}{0}\"\n  STR_THROWING_SHORT: \"투척>{ALT}{0}\"\n  STR_MELEE_SHORT: \"근접>{ALT}{0}\"\n  STR_PERSONAL_EQUIPMENT: \"개인 장비\"\n  STR_SAVE_PERSONAL_EQUIPMENT: \"개인 장비 저장하기\"\n  STR_LOAD_PERSONAL_EQUIPMENT: \"개인 장비 불러오기\"\n  STR_PERSONAL_EQUIPMENT_SAVED: \"개인 장비 저장됨.\"\n  STR_PERSONAL_EQUIPMENT_NOT_DEFINED: \"개인 장비가 아직 정의되지 않음.\"\n  STR_SLOT: \"칸>{ALT}{0}\"\n  STR_THINKING: \"생각하는 중...\"\n  STR_TELL_ME_MORE: \"조금만 더...\"\n  STR_REINFORCEMENTS_ALERT: \"증원 경고!\"\n  STR_HIT_LOG_NEW_TURN: \"새로운 턴\"\n  STR_FAILED_CQB_CHECK: \"적이 당신의 공격에 훼방을 놓았다!\"\n  STR_NO_TRAJECTORY: \"실현 가능한 궤적이 없다!\"\n  STR_HIT_LOG_NEW_BULLET: \"=>\"\n  STR_MANA_SHORT: \"마나>{ALT}{0}\"\n  STR_SKILL_NEEDS_ITEM: \"이 기술은 물픔이 필요하다!\"\n  STR_HIT_LOG_NO_DAMAGE: \"0\"\n  STR_HIT_LOG_SMALL_DAMAGE: \"경상\"\n  STR_HIT_LOG_BIG_DAMAGE: \"중상\"\n  STR_HIT_LOG_REACTION_FIRE: \"반응사격...\"\n  STR_HIT_LOG: \"타격 기록\"\n  STR_BUTTON_TOUCH: \"터치\"\n  STR_BUTTON_1: \"1\"\n  STR_BUTTON_10: \"10\"\n  STR_BUTTON_100: \"100\"\n  STR_BUTTON_LMB: \"마우스 좌버튼\"\n  STR_BUTTON_RMB: \"마우스 우버튼\"\n  STR_BUTTON_MMB: \"마우스 중버튼\"\n  STR_BUTTON_CTRL: \"CTRL\"\n  STR_BUTTON_ALT: \"ALT\"\n  STR_BUTTON_SHIFT: \"SHIFT\"\n  STR_LAZY_LOADING: \"게으른 로딩\"\n  STR_LAZY_LOADING_DESC: \"만약 켜지면, 그래픽 자원은 필요 시 불러옵니다. 아니면 모든 것은 시작할 때 불러옵니다.\"\n  STR_VSYNC_FOR_OPENGL: \"OpenGL용 VSync\"\n  STR_VSYNC_FOR_OPENGL_DESC: \"적의 숨겨진 이동 속도 및 (부가적으로) 병사의 이동 속도를 극대화하려면 켜세요. FPS 제한을 0으로 설정하지 마세요. 오직 OpenGL 렌더링에만 적용됩니다.\"\n  STR_UPDATE_CHECK: \"자동 업데이트 확인\"\n  STR_UPDATE_CHECK_DESC: \"만약 켜지면, OpenXcom은 업데이트를 자동으로 확인하고 마우스 버튼 딸깍 한 번으로 자체 업데이트를 할 선택지를 줄 것입니다.\"\n  STR_AUTOSAVE_SLOTS: \"자동 세이브 칸\"\n  STR_AUTOSAVE_SLOTS_DESC: \"전투 화면에서 자동 세이브를 할 칸의 숫자를 정합니다.\"\n  STR_AUTO_SAVE_BATTLESCAPE_SLOT_WITH_NUMBER: \"<AUTO BATTLESCAPE> {0}\"\n  STR_GEO_AUTOSAVE_FREQUENCY: \"자동 저장 빈도(지구 화면)\"\n  STR_GEO_AUTOSAVE_FREQUENCY_DESC: \"게임이 자동으로 저장될 날짜 간격을 정합니다.\"\n  STR_GEO_AUTOSAVE_SLOTS: \"자동 저장 칸(지구 화면)\"\n  STR_GEO_AUTOSAVE_SLOTS_DESC: \"지구 화면에서 자동 세이브를 할 칸의 숫자를 정합니다.\"\n  STR_AUTO_SAVE_GEOSCAPE_SLOT_WITH_NUMBER: \"<AUTO GEOSCAPE> {0}\"\n  STR_OXCE_LINKS: \"확장된 링크\"\n  STR_OXCE_LINKS_DESC: \"OXCE 특징을 위한 추가 메뉴/버튼/링크를 켭니다.\"\n  STR_PEDIA_SHOW_CLIP_SIZE: \"UFO사전에 탄창 크기를 표시\"\n  STR_PEDIA_SHOW_CLIP_SIZE_DESC: \"만약 켜지면, 탄창의 크기가 UFO사전 안의 탄약 아이콘 옆에 표시될 것입니다.\"\n  STR_INTERCEPT_TABLE_SIZE: \"요격 테이블 칸\"\n  STR_INTERCEPT_TABLE_SIZE_DESC: \"다음의 대화 창에 있는 테이블의 크기입니다: 요격, UFO 추적기.\"\n  STR_SHOW_SLACKING_INDICATOR: \"땡땡이 지시기 표시\"\n  STR_SHOW_SLACKING_INDICATOR_DESC: \"만약 켜지면, 업무가 할당되지 않은 과학자 및 공학자의 수가 표시될 것입니다.\"\n  STR_SHOW_MAINTENANCE_TIME: \"기체 유지 보수 시간 표시\"\n  STR_SHOW_MAINTENANCE_TIME_DESC: \"{ALT}0>{ALT} 표시하지 않음 {ALT}1>{ALT} 현재 진행 중인 행동의 기간만 표시{ALT}2>{ALT} 전부 표시(수리 + 재무장 + 급유).\"\n  STR_SHOW_ETA: \"예상 비행 기간 표시\"\n  STR_SHOW_ETA_DESC: \"{ALT}0>{ALT} 표시하지 않음 {ALT}1>{ALT} 고정 표적의 예상도착시간만 표시{ALT}2>{ALT} 이동하는 표적도 예상도착시간 표시\"\n  STR_UFO_LANDING_ALERT: \"UFO 착륙 경보\"\n  STR_UFO_LANDING_ALERT_DESC: \"만약 켜지면, 탐지된 UFO가 착륙하는 때마다 메시지가 뜰 것입니다.\"\n  STR_REMEMBER_DISABLED_CRAFT_WEAPONS: \"기체의 꺼진 무장 기억\"\n  STR_REMEMBER_DISABLED_CRAFT_WEAPONS_DESC: \"공중전 동안 기체의 꺼진 무장은 꺼진 채로 있을 것입니다. 그들은 또한 기지에서 재무장되지 않을 것입니다.\"\n  STR_GEO_EVENT_INSTANT_DELIVERY: \"이벤트 물품의 즉시 배송\"\n  STR_GEO_EVENT_INSTANT_DELIVERY_DESC: \"만약 켜지면, 지구 화면의 이벤트로부터 온 물품은 즉시 도착합니다. 아니면, 그것들은 1시간 후에 도착합니다.\"\n  STR_SHOW_BASE_NAME_IN_POPUPS: \"팝업 창에 기지 이름 표시\"\n  STR_SHOW_BASE_NAME_IN_POPUPS_DESC: \"만약 켜지면, 관련된 기지 이름이 팝업 창에(예를 들면, 연구 완료) 표시됩니다.\"\n  STR_ALTERNATE_CRAFT_EQUIPMENT_MANAGEMENT: \"대체 기체 장비 관리\"\n  STR_ALTERNATE_CRAFT_EQUIPMENT_MANAGEMENT_DESC: \"만약 켜지면, 기지와 기체 사이를 이동하는 병사는 자기 장비 또한 가져갈 것입니다(가능하다면).\"\n  STR_BASE_INFO_SCALE: \"기지 정보에서 막대그래프 크기 조절\"\n  STR_BASE_INFO_SCALE_DESC: \"만약 켜지면, 140보다 커다란 막대는 UI에 맞게 축소됩니다.\"\n  STR_HIGHLIGHT_NEW: \"새로운 주제 강조\"\n  STR_HIGHLIGHT_NEW_DESC: \"만약 켜지면, 새로운 연구 주제, 새로운 제작 주제 및 새로운 UFO사전 항목이 서로 다른 색상으로 보여집니다.\"\n  STR_RESEARCH_SCROLL_SPEED: \"연구 스크롤 속도\"\n  STR_RESEARCH_SCROLL_SPEED_DESC: \"과학자를 마우스 스크롤 버튼을 이용해 현재 연구 UI에서 직접 할당(해제)할 수 있습니다.\"\n  STR_RESEARCH_SCROLL_SPEED_CTRL: \"연구 스크롤 속도(CTRL키)\"\n  STR_RESEARCH_SCROLL_SPEED_CTRL_DESC: \"과학자를 마우스 스크롤 버튼을 이용해 현재 연구 UI에서 직접 할당(해제)할 수 있습니다.\"\n  STR_MANUFACTURE_FILTER_SUPPLIES_OK: \"제조 시 대체 필터\"\n  STR_MANUFACTURE_FILTER_SUPPLIES_OK_DESC: \"만약 켜지면, UI는 오직 충분한 재료가 있는 생산 물품만 표시합니다.\"\n  STR_MANUFACTURE_SCROLL_SPEED: \"제조 스크롤 속도\"\n  STR_MANUFACTURE_SCROLL_SPEED_DESC: \"마우스 스크롤 버튼을 이용해 공학자는 현재 연구 UI 화면에서 직접 할당(해제)될 수 있습니다.\"\n  STR_MANUFACTURE_SCROLL_SPEED_CTRL: \"제조 스크롤 속도(CTRL키)\"\n  STR_MANUFACTURE_SCROLL_SPEED_CTRL_DESC: \"마우스 스크롤 버튼을 이용해 공학자는 현재 연구 UI 화면에서 직접 할당(해제)될 수 있습니다.\"\n  STR_PERSONAL_LAYOUT_INCLUDING_ARMOR: \"개인 장비에 갑옷을 포함\"\n  STR_PERSONAL_LAYOUT_INCLUDING_ARMOR_DESC: \"만약 켜지면, 병사의 개인 장비 배치는 입혀진 갑옷을 포함해 저장됩니다.\"\n  STR_MANUALPROMOTIONS: \"수동 진급\"\n  STR_MANUALPROMOTIONS_DESC: \"만약 켜지면, 병사는 계급 아이콘을 눌러 수동으로 진급(또는 강등)시킬 수 있습니다.\"\n  STR_WOUNDED_DEFEND_BASE_IF: \"부상병 방어(체력 x% 이상 시)\"\n  STR_WOUNDED_DEFEND_BASE_IF_DESC: \"만약 병사의 체력이 주어진 퍼센트 기준 이상이면, 다친 병사 또한 기지를 방어합니다.\"\n  STR_PLAY_BRIEFING_MUSIC_DURING_EQUIPMENT: \"브리핑 음악 계속 재생\"\n  STR_PLAY_BRIEFING_MUSIC_DURING_EQUIPMENT_DESC: \"브리핑 음악은 전투 화면이 표시될 때까지 장비 단계 중 계속 연주될 것입니다.\"\n  STR_NIGHT_VISION_COLOR: \"야간시야 색상 선택\"\n  STR_NIGHT_VISION_COLOR_DESC: \"1부터 15까지의 숫자로, 각각은 서로 다른 음영 색상을 나타냅니다.\"\n  STR_AUTO_NIGHT_VISION_THRESHOLD: \"자동 야간시야 기준\"\n  STR_AUTO_NIGHT_VISION_THRESHOLD_DESC: \"만약 이 기준보다 더 어두우면, 야간시야가 자동으로 켜집니다.\"\n  STR_SHOW_ACCURACY_ON_CROSSHAIR: \"조준선에 정확도 표시\"\n  STR_SHOW_ACCURACY_ON_CROSSHAIR_DESC: \"{ALT}0>{ALT}미표시{ALT}1>{ALT}UFO 익스텐더 정확도가 활성화되었을 때만 {ALT}2>{ALT}항상\"\n  STR_REACTION_FIRE_THRESHOLD: \"반응 사격 기준점\"\n  STR_REACTION_FIRE_THRESHOLD_DESC: \"만약 (주어진 표적에 대한) 명중률이 기준 이하라면, X-Com이 조종하는 유닛은 반응 사격하지 않을 것입니다.\"\n  STR_AUTO_SELL: \"자동 판매 관리자\"\n  STR_AUTO_SELL_DESC: \"전투 디브리핑의 매각 화면에서, 이전 전투에서 당신이 팔았던 어떠한 유형의 물품도 자동으로 매각에 표기될 것입니다.\"\n  STR_AUTOMATICPROMOTIONS: \"자동 진급\"\n  STR_AUTOMATICPROMOTIONS_DESC: \"만약 켜지면, 병사는 임무 후 자동으로 진급합니다.\"\n  STR_OFF_CENTRE_SHOOTING: \"중심축에서 벗어난 사격\"\n  STR_OFF_CENTRE_SHOOTING_DESC: \"사선이 없는 경우에 병사는 발사 각도를 자동으로 살짝 조정하려 시도할 것입니다.\"\n  STR_UNIFORM_SHOOTING_SPREAD: \"균일한 사격 퍼짐\"\n  STR_UNIFORM_SHOOTING_SPREAD_DESC: \"총알의 퍼짐이 모든 방향에서 균일해지고 더 좁아집니다.\"\n  STR_CRASHED_OR_LANDED: \"추락/착륙 버튼\"\n  STR_CRASHED_OR_LANDED_DESC: \"만약 켜지면, 새로운 전투 화면에서 추가 버튼이 표시됩니다. 그밖에는, 버튼을 표시/숨기려면 F11을 누르세요. {ALT}0>{ALT}비활성화, {ALT}1>{ALT}추락, {ALT}2>{ALT}착륙.\"\n  STR_GRAPHS_ZOOM_IN: \"확대(그래프)\"\n  STR_GRAPHS_ZOOM_OUT: \"축소(그래프)\"\n  STR_MARK_ALL_AS_SEEN: \"보이는 모든 것을 마킹\"\n  STR_SELL_ALL: \"전부 판매\"\n  STR_SELL_ALL_BUT_ONE: \"하나 빼고 전부 판매\"\n  STR_TRANSFER_ALL: \"전부 이송\"\n  STR_REMOVE_SOLDIERS_FROM_ALL_CRAFTS: \"모든 기체에서 병사 제거\"\n  STR_REMOVE_SOLDIERS_FROM_CRAFT: \"기체에서 병사 제거\"\n  STR_REMOVE_EQUIPMENT_FROM_CRAFT: \"기체에서 장비 제거\"\n  STR_REMOVE_ARMOR_FROM_ALL_CRAFTS: \"모든 기체에서 갑옷 제거\"\n  STR_REMOVE_ARMOR_FROM_CRAFT: \"기체에서 갑옷 제거\"\n  STR_REMOVE_SOLDIERS_FROM_TRAINING: \"훈련에서 병사 제거\"\n  STR_ADD_SOLDIERS_TO_TRAINING: \"훈련할 병사 추가\"\n  STR_INVENTORY_ARMOR: \"갑옷 변경\"\n  STR_INVENTORY_AVATAR: \"외형 변경\"\n  STR_INVENTORY_DIARY_LIGHT: \"작은 메모장 보여주기\"\n  STR_ACTION_ITEM_1: \"물품 행동 1 (조준사격/이용)\"\n  STR_ACTION_ITEM_2: \"물품 행동 2 (지향사격)\"\n  STR_ACTION_ITEM_3: \"물품 행동 3 (자동사격)\"\n  STR_ACTION_ITEM_4: \"물품 행동 4 (격투)\"\n  STR_ACTION_ITEM_5: \"물품 작동 5 (투척)\"\n  STR_INSTA_SAVE: \"즉석 세이브\"\n  STR_TOGGLE_QUICK_SEARCH: \"빠른 검색기 표시 - 검색불가\"\n  STR_TOGGLE_NIGHT_VISION: \"야간시야 켜고 끄기\"\n  STR_HOLD_NIGHT_VISION: \"야간시야 일시 적용\"\n  STR_SELECT_MUSIC_TRACK: \"음악 트랙 선택\"\n  STR_TOGGLE_TOUCH_BUTTONS: \"터치 버튼 켜고 끄기\"\n  STR_TOGGLE_BRIGHTNESS: \"밝기 켜고 끄기(보이는 것만)\"\n  STR_BRIEFING: \"브리핑\"\n  STR_TOGGLE_DEBUG_MODE: \"디버그 모드 켜고 끄기\"\n  STR_DEBUG_KILL_ALL_ALIENS: \"디버그: 모든 외계인 사살\"\n  STR_PHYSICAL_TRAINING: \"군사 훈련\"\n  STR_REMAINING_TRAINING_FACILITY_CAPACITY: \"남아 있는 훈련 수용량> {ALT}{0}\"\n  STR_NO_WOUNDED: \"-\"\n  STR_NO_QUEUED: \"+\"\n  STR_NO_DONE: \"종료\"\n  STR_NO_AMMO: \"탄약 없음!\"\n  STR_START_FIRING: \"발사!\"\n  STR_SKIP_FIRING: \"안으로 들여보내...\"\n  STR_ALIEN_MISSILES_HAVE_DAMAGED_OUR_BASE: \"외계인의 미사일이 우리 {0} 기지를 손상시켰다\"\n  STR_ALIEN_MISSILES_HAVE_DESTROYED_OUR_BASE: \"외계인 미사일이 우리 {0} 기지를 부수었다\"\n  STR_STARTING_CONDITION_COMMANDER: \"이 임무는 준장이 있을 것을 요구한다.\"\n  STR_STARTING_CONDITION_CRAFT: \"이 기체는 이 임무에 적합하지 않다.\"\n  STR_STARTING_CONDITION_CRAFT_ALLOWED: \"이 기체는 이 임무에 적합하지 않다.{NEWLINE}{NEWLINE}허용되는 기체: {0}\"\n  STR_STARTING_CONDITION_CRAFT_FORBIDDEN: \"이 기체는 이 임무에 적합하지 않다.{NEWLINE}{NEWLINE}금지되는 기체: {0}\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE: \"일부 병사는 이 임무에 참여할 수 없다.\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE_ALLOWED: \"일부 병사는 이 임무에 참여할 수 없다.{NEWLINE}{NEWLINE}허용되는 병사 유형: {0}\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE_FORBIDDEN: \"일부 병사는 이 임무에 참여할 수 없다.{NEWLINE}{NEWLINE}금지되는 병사 유형: {0}\"\n  STR_STARTING_CONDITION_ITEM: \"이 임무는 특정 물품(들)을 요구한다:{NEWLINE}{NEWLINE}{0}\"\n  STR_NOT_ENOUGH_FUEL_TO_REACH_TARGET: \"연료가 충분하지 않다!{SMALLLINE}이 행선지는 이 기체의 전투행동반경에 비해 너무 멀다.\"\n  STR_TOO_MANY_ITEMS_ONBOARD: \"물품이 너무 많다!{SMALLINE}이 기체는 이렇게 많은 물품을 나를 수 없다.\"\n  STR_ARMOR_NOT_ALLOWED_ONBOARD: \"갑옷이 허용되지 않는다!{SMALLLINE}일부 병사는 금지된 갑옷을 입고 있다.\"\n  STR_FOLLOW_WING_LEADER_QUESTION: \"편대장을 따르는가?\"\n  STR_ASSIGN_PILOTS: \"조종사 할당...\"\n  STR_NOT_ENOUGH_PILOTS: \"조종사가 충분하지 않다!{NEWLINE}최소: {0}명\"\n  STR_DAILY_PILOT_EXPERIENCE: \"일일 조종사 경험치\"\n  STR_UFO_SHIELD_HIT: \"방어막에 맞음!\"\n  STR_UFO_HIT_NO_DAMAGE: \"선체에서 튕겨나감!\"\n  STR_UFO_SHIELD_DOWN: \"적 방어막 해제!\"\n  STR_UFO_HIT_GLANCING: \"빗겨 맞음!\"\n  STR_INTERCEPTOR_SHIELD_HIT: \"우리 방어막 유지 중!\"\n  STR_TRACTOR_BEAM_ENGAGED: \"트랙터 빔이 접근함!\"\n  STR_TRACTOR_BEAM_DISENGAGED: \"트랙터 빔이 멀어짐\"\n  STR_SELF_DESTRUCT_ACTIVATED: \"자폭장치 활성화!\"\n  STR_SELF_DESTRUCT_CANCELLED: \"자폭 취소\"\n  STR_MISSILE_DAMAGED: \">>> 미사일이 손상됨 <<<\"\n  STR_MISSILE_DESTROYED: \">>> 미사일이 파괴됨 <<<\"\n  STR_EXTENDED_LINKS: \"링크\"\n  STR_AUTO_PATROL: \"자동 순찰\"\n  STR_ETA: \"예상도착시간:>{ALT}{0}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_FACILITY_AT_BASE: \"{2}에서 {1}을 재무장하기 위한 {0}이 충분하지 않다\"\n  STR_UFO_STARTED_HUNTING: \"{0}은 {1}을 요격 경로 상에 두고 있다\"\n  STR_CRAFT_IS_READY: \"{1}에 있는 {0} 기체가 준비되었다.\"\n  STR_ECONOMY_WARNING: \"자금 {0} 및 수입 {1}이 낮고 유지비 {2}는 너무 높다! 신용을 잃는 걸 피하기 위해 무언가 팔아라... 부족한 자금: {3}\"\n  STR_SLACKING_INDICATOR: \"과{0}/공{1}\"\n  STR_TRAINING_INDICATOR: \"{0}:{1}\"\n  STR_EXTENDED_UC: \"확장\"\n  STR_RETURNING: \"복귀함\"\n  STR_INTERCEPTING: \"요격함\"\n  STR_ESCORTING: \"호위함\"\n  STR_EN_ROUTE: \"이동함\"\n  STR_PILOT_MISSING: \"조종사 없음\"\n  STR_DAY_SHORT: \"{0}일\"\n  STR_HOUR_SHORT: \"{0}시간\"\n  STR_PERFORMANCE_BONUS: \"성과 보너스\"\n  STR_COUNTRY_HAS_CANCELLED_A_SECRET_PACT: \"{0} 당국은 외계인 세력과의 조약을 파기했고 프로젝트에 복귀하기로 했다.\"\n  STR_COUNTRIES_HAVE_CANCELLED_A_SECRET_PACT: \"{0} 당국은 외계인 세력과의 조약을 파기했고 프로젝트에 복귀하기로 했다.\"\n  STR_WE_CAN_NOW_RENT: \"이제 아래를 빌릴 수 있다\"\n  STR_REQUIRED_BASE_SERVICES: \"요구되는 기지 기능: {0}\"\n  STR_WE_CAN_NOW_BUILD: \"이제 아래를 지을 수 있다\"\n  STR_WE_CAN_NOW_PURCHASE: \"이제 아래를 구매할 수 있다\"\n  STR_NOT_ENOUGH_LIVING_SPACE_AT_BASE: \"{1}{NEWLINE}에{NEWLINE}{0}{NEWLINE}병사가 거주하기 위한 생활 공간이 충분하지 않다\"\n  STR_INFO: \"정보\"\n  STR_DESPAWN_PENALTY: \"임무 소멸 페널티> {0}\"\n  STR_TRAINING_FINISHED: \"{0}에서{NEWLINE}훈련 완료\"\n  STR_PSI_TRAINING_FINISHED: \"{0}에서{NEWLINE}사이오닉 훈련 완료\"\n  STR_IGNORE_UC: \"무시\"\n  STR_UFO_TRACKER: \"UFO 추적창\"\n  STR_UPDATE: \"업데이트\"\n  STR_LATEST_VERSION_INFO: \"최신 OpenXcom 버전을 사용하고 있습니다.\"\n  STR_MASTER_MOD_VERSION_REQUIRED_QUESTION: \"이 모드는 올바로 실행되기 위해 기본 게임 v{0}을 요구합니다. 이 모드를 켭니까?\"\n  STR_VERSION_REQUIRED_QUESTION: \"이 모드는 올바로 실행되기 위해 OXCE v{0}를 요구합니다. 이 모드를 켭니까?\"\n  STR_OPEN_MODS_FOLDER: \"열기\"\n  STR_GLOBE_TEXTURE: \"지구 화면 텍스처\"\n  STR_NOTES: \"노트\"\n  STR_NEW_NOTE: \"<NEW NOTE>\"\n  STR_ENGINE_OXC: \"오픈엑스컴\"\n  STR_ENGINE_OXCE: \"익스텐디드\"\n  STR_ENGINE_OTHER: \"기타\"\n  STR_BASESCAPE: \"기지 화면\"\n  STR_AI: \"AI\"\n  STR_PATH_ENERGY_COST: \"기력\"\n  STR_PATH_ENERGY_COST_DESC: \"누르면 당신의 유닛이 행선지로 이동한 후 남아 있을 기력을 보여줍니다.\"\n  STR_VEHICLES_LOST: \"손실된 차량\"\n  STR_CRAFT_LOST_DOGFIGHT: \"손실된 요격기\"\n  STR_CRAFT_LOST_MISSION: \"손실된 수송기\"\n  STR_ALIEN_BASES_DESTROYED: \"부순 외계인 기지\"\n  STR_XCOM_BASES_LOST: \"잃은 기지\"\n  STR_TEST_SCREEN: \"시험 화면\"\n  STR_PALETTE: \"팔레트:\"\n  STR_PREVIEW: \"미리보기\"\n  STR_TINY_BORDERLESS: \"자그마함, 경계선 없음\"\n  STR_TINY_BORDER: \"자그마함\"\n  STR_SMALL_LOW_CONTRAST: \"작음\"\n  STR_SMALL_HIGH_CONTRAST: \"작고, 선명도 높음\"\n  STR_BIG_LOW_CONTRAST: \"큼\"\n  STR_BIG_HIGH_CONTRAST: \"크고, 선명도 높음\"\n  STR_TEST_CASE: \"시험 케이스:\"\n  STR_RUN: \"선택된 시험 실행!\"\n  STR_TESTS_STARTING: \"시작 중...\"\n  STR_TESTS_ERRORS_FOUND: \"발견된 총 에러(중복이 있을 수 있음): {0}\"\n  STR_TESTS_NO_ERRORS_FOUND: \"에러가 발견되지 않음.\"\n  STR_TESTS_FINISHED: \"완료.\"\n  STR_DETAILED_INFO_IN_LOG_FILE: \"구체적인 정보는 openxcom.log.에 저장되었다\"\n  STR_RANK_NONE: \"-\"\n  STR_DAMAGE_NONE: \"없음\"\n  STR_INFO_UFOPEDIA: \"정보\"\n  STR_COCKPIT_CAPACITY: \"조종사>{ALT}{0}{ALT}\"\n  STR_MAXIMUM_RANGE: \"최대 행동반경>{ALT}{0}{ALT}\"\n  STR_MINIMUM_RANGE: \"최소 행동반경>{ALT}{0}{ALT}\"\n  STR_INFINITE_RANGE: \"무한\"\n  STR_TRACTOR_BEAM_POWER: \"위력\"\n  STR_WEIGHT_PEDIA1: \"무게: {0}\"\n  STR_WEIGHT_PEDIA2: \"무게: {0}/{1}\"\n  STR_SHOT_TYPE_MELEE: \"격투\"\n  STR_ACCURACY_MODIFIER: \"정확도 보정>{ALT} {0}\"\n  STR_POWER_BONUS: \"위력 보너스>{ALT} {0}\"\n  STR_MULTIPLE_DIFFERENT_BONUSES: \"다양한 호환 탄종에 대해 복수의 보너스 제공\"\n  STR_STATS_FOR_NERDS: \"덕후를 위한 설명\"\n  STR_ARTICLE: \"주제>{ALT} {0}\"\n  STR_COMPATIBLE_AMMO: \"호환 탄종:\"\n  STR_BUILT_IN_ITEMS: \"내장된 물품:\"\n  STR_CLIP_SIZE_UNLIMITED: \"무한대\"\n  STR_SHOTGUN_BEHAVIOR_OXCE: \"익스텐디드\"\n  STR_INCLUDE_DEBUG: \"디버그\"\n  STR_INCLUDE_IDS: \"ID\"\n  STR_INCLUDE_DEFAULTS: \"기본\"\n  STR_TRUE: \"참\"\n  STR_FALSE: \"거짓\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH: \"사이오닉 기술*사이오닉 강도\"\n  STR_STRENGTH_AND_MELEE_ACCURACY: \"근력*격투술\"\n  STR_STRENGTH_AND_THROWING_ACCURACY: \"근력*투척술\"\n  STR_FIRING_ACCURACY_AND_REACTIONS: \"사격술*반응\"\n  STR_HEALTH_CURRENT: \"현재 체력\"\n  STR_MANA_CURRENT: \"현재 마나\"\n  STR_TIME_UNITS_CURRENT: \"현재 행동력\"\n  STR_STUN_LEVEL_CURRENT: \"현재 기절 수준\"\n  STR_HEALTH_NORMALIZED: \"체력 백분율\"\n  STR_MANA_NORMALIZED: \"마나 백분율\"\n  STR_TIME_UNITS_NORMALIZED: \"행동력 백분율\"\n  STR_ENERGY_NORMALIZED: \"기력 백분율\"\n  STR_MORALE_NORMALIZED: \"사기 백분율\"\n  STR_STUN_LEVEL_NORMALIZED: \"기절 수준 백분율\"\n  STR_ENERGY_REGENERATION: \"기력 재생\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH_ABBREVIATION: \"PSK*PST\"\n  STR_STRENGTH_AND_MELEE_ACCURACY_ABBREVIATION: \"STR*MEL\"\n  STR_STRENGTH_AND_THROWING_ACCURACY_ABBREVIATION: \"STR*THR\"\n  STR_FIRING_ACCURACY_AND_REACTIONS_ABBREVIATION: \"ACC*REA\"\n  STR_HEALTH_CURRENT_ABBREVIATION: \"현재 체력\"\n  STR_MANA_CURRENT_ABBREVIATION: \"현재 마나\"\n  STR_TIME_UNITS_CURRENT_ABBREVIATION: \"현재 행동력\"\n  STR_STUN_LEVEL_CURRENT_ABBREVIATION: \"현재 기절 수준\"\n  STR_HEALTH_NORMALIZED_ABBREVIATION: \"체력 백분율\"\n  STR_MANA_NORMALIZED_ABBREVIATION: \"마나 백분율\"\n  STR_TIME_UNITS_NORMALIZED_ABBREVIATION: \"행동력 백분율\"\n  STR_ENERGY_NORMALIZED_ABBREVIATION: \"기력 백분율\"\n  STR_MORALE_NORMALIZED_ABBREVIATION: \"사기 백분율\"\n  STR_STUN_LEVEL_NORMALIZED_ABBREVIATION: \"기절 수준 백분율\"\n  STR_ENERGY_REGENERATION_ABBREVIATION: \"기력 재생\"\n  STR_TIME_UNITS_SCALED: \"축척 적용된 행동력\"\n  STR_STAMINA_SCALED: \"축척 적용된 기력\"\n  STR_HEALTH_SCALED: \"축척 적용된 체력\"\n  STR_BRAVERY_SCALED: \"축척 적용된 용기\"\n  STR_REACTIONS_SCALED: \"축척 적용된 반응\"\n  STR_FIRING_ACCURACY_SCALED: \"축척 적용된 사격술\"\n  STR_THROWING_ACCURACY_SCALED: \"축척 적용된 투척술\"\n  STR_STRENGTH_SCALED: \"축척 적용된 근력\"\n  STR_PSIONIC_STRENGTH_SCALED: \"축척 적용된 사이오닉 강도\"\n  STR_PSIONIC_SKILL_SCALED: \"축척 적용된 사이오닉 기술\"\n  STR_MELEE_ACCURACY_SCALED: \"축척 적용된 격투술\"\n  STR_MANA_POOL_SCALED: \"축척 적용된 최대 마나\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH_SCALED: \"축척 적용된 사이오닉 기술*사이오닉 강도\"\n  STR_STRENGTH_AND_MELEE_ACCURACY_SCALED: \"축척 적용된 근력*격투술\"\n  STR_STRENGTH_AND_THROWING_ACCURACY_SCALED: \"축척 적용된 근력*투척술\"\n  STR_FIRING_ACCURACY_AND_REACTIONS_SCALED: \"축척 적용된 사격술*반응\"\n  STR_TIME_UNITS_SCALED_ABBREVIATION: \"축척 TU\"\n  STR_STAMINA_SCALED_ABBREVIATION: \"축척 STA\"\n  STR_HEALTH_SCALED_ABBREVIATION: \"축척 HP\"\n  STR_BRAVERY_SCALED_ABBREVIATION: \"축척 BRV\"\n  STR_REACTIONS_SCALED_ABBREVIATION: \"축척 REA\"\n  STR_FIRING_ACCURACY_SCALED_ABBREVIATION: \"축척 ACC\"\n  STR_THROWING_ACCURACY_SCALED_ABBREVIATION: \"축척 THR\"\n  STR_STRENGTH_SCALED_ABBREVIATION: \"축척 STR\"\n  STR_PSIONIC_STRENGTH_SCALED_ABBREVIATION: \"축척 PST\"\n  STR_PSIONIC_SKILL_SCALED_ABBREVIATION: \"축척 PSK\"\n  STR_MELEE_ACCURACY_SCALED_ABBREVIATION: \"축척 MEL\"\n  STR_MANA_POOL_SCALED_ABBREVIATION: \"축척 MAN\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH_SCALED_ABBREVIATION: \"축척 PSK*PST\"\n  STR_STRENGTH_AND_MELEE_ACCURACY_SCALED_ABBREVIATION: \"축척 STR*MEL\"\n  STR_STRENGTH_AND_THROWING_ACCURACY_SCALED_ABBREVIATION: \"축척 STR*THR\"\n  STR_FIRING_ACCURACY_AND_REACTIONS_SCALED_ABBREVIATION: \"축척 ACC*REA\"\n  STR_COST_TIME: \"행동력\"\n  STR_COST_ENERGY: \"기력\"\n  STR_COST_MORALE: \"사기\"\n  STR_COST_HEALTH: \"체력\"\n  STR_COST_STUN: \"기절\"\n  STR_COST_MANA: \"마나\"\n  STR_COST_BUILD: \"짓기\"\n  STR_COST_REFUND: \"환불\"\n  STR_DAMAGE_10: \"10\"\n  STR_DAMAGE_11: \"11\"\n  STR_DAMAGE_12: \"12\"\n  STR_DAMAGE_13: \"13\"\n  STR_DAMAGE_14: \"14\"\n  STR_DAMAGE_15: \"15\"\n  STR_DAMAGE_16: \"16\"\n  STR_DAMAGE_17: \"17\"\n  STR_DAMAGE_18: \"18\"\n  STR_DAMAGE_19: \"19\"\n  STR_NAUTICAL_MILES: \"{0} 해리\"\n  STR_KILOMETERS_PER_HOUR: \"{0} km/h\"\n  STR_SECONDS_LONG: \"{0} 초\"\n  STR_RACE_BONUS: \"종족 보너스\"\n  STR_FOR_DIFFICULTY: \"다음 난이도에서: {0}\"\n  STR_NOT_AWARDED_YET: \"아직 포상을 받지 못함\"\n"
  },
  {
    "path": "bin/common/Language/OXCE/no.yml",
    "content": "\"no\":\n  STR_ID: \"ID\"\n  STR_FIRST_LETTER: \"FØRSTE BOKSTAV\"\n  STR_SAVE_UC: \"LAGRE\"\n  STR_ALL: \"Alt\"\n  STR_PILOTS: \"PILOTER\"\n  STR_SHIELD: \"SKJOLD>{ALT}{0}\"\n  STR_SELECT_PILOT: \"Velg Pilot\"\n  STR_PILOTS_FOR_CRAFT: \"Pilot(er) til  {0}\"\n  STR_PILOTS_REQUIRED: \"Pilot(er) påkrevd: {ALT}{0}\"\n  STR_ADD_PILOT: \"Legg til Pilot\"\n  STR_REMOVE_ALL_PILOTS: \"Fjern Alle Piloter\"\n  STR_NORMAL: \"Normal\"\n  STR_SHOW_ALL: \"Vis alle\"\n  STR_NO_DEPENDENCIES: \"Ingen avhengigheter.\"\n  STR_DIRECT_DEPENDENCIES: \"Direkte avhengigheter\"\n  STR_REFUND_PRODUCTION: \"REFUNDER!\"\n  STR_SHOW_ONLY_NEW: \"Vis kun nye\"\n  STR_NOT_ENOUGH_CRAFT_SPACE: \"Ikke nok plass ombord!\"\n  STR_TRAINING: \"Trening\"\n  STR_TECH_TREE_VIEWER: \"Teknologi-tre Visning\"\n  STR_OXCE: \"Utvidet\"\n"
  },
  {
    "path": "bin/common/Language/OXCE/pl.yml",
    "content": "pl:\n  STR_CANNOT_DISMANTLE_FACILITY_UPGRADING: \"NIE MOŻNA ZLIKWIDOWAĆ BUDYNKU!{SMALLLINE}Budynku nie można usunąć w trakcie przebudowy.\"\n  STR_CANNOT_UPGRADE_FACILITY_ALREADY_UPGRADING: \"NIE MOŻNA TU BUDOWAĆ!{SMALLLINE}Istniejący budynek jest już zastępowany innym.\"\n  STR_CANNOT_UPGRADE_FACILITY_WRONG_SIZE: \"NIE MOŻNA TU BUDOWAĆ!{SMALLLINE}Wybrany budynek musi całkowicie pokryć istniejący budynek.\"\n  STR_CANNOT_UPGRADE_FACILITY_WRONG_TYPE: \"NIE MOŻNA TU BUDOWAĆ!{SMALLLINE}Istniejący budynek nie może być zastąpiony wybranym budynkiem.\"\n  STR_CANNOT_UPGRADE_FACILITY_DISALLOWED: \"NIE MOŻNA TU BUDOWAĆ!{SMALLLINE}Istniejący budynek nie może być zastąpiony.\"\n  STR_CANNOT_BUILD_QUEUE_OFF: \"NIE MOŻNA TU BUDOWAĆ!{SMALLLINE}Najpierw trzeba ukończyć budowę dojścia do budynku.\"\n  STR_FACILITY_FORBIDDEN_BY_OTHER: \"NIE MOŻNA TU BUDOWAĆ!{SMALLLINE}Któryś z istniejących budynków zabrania budowy tego budynku.\"\n  STR_FACILITY_OTHER_FORBIDDEN_BY_THIS: \"NIE MOŻNA TU BUDOWAĆ!{SMALLLINE}Któryś z istniejących budynków zostałby zabroniony przez ten budynek.\"\n  STR_NOT_ENOUGH_ITEMS: \"ZA MAŁO MATERIAŁÓW!{SMALLLINE}Potrzebujemy więcej surowców, by zbudować tę instalację.{NEWLINE}Brakuje> {0}: {1}\"\n  STR_ID: \"Identyfikator\"\n  STR_FIRST_LETTER: \"PIERWSZA LITERA\"\n  STR_SOLDIER_TYPE: \"TYP ŻOŁNIERZA\"\n  STR_IDLE_DAYS: \"DNI BEZ AKCJI\"\n  STR_MANA: \"MANA\"\n  STR_MANA_POOL: \"PULA MANY\"\n  STR_MANA_MISSING: \"BRAKUJĄCA MANA\"\n  STR_LOAD_CRAFT_LOADOUT_TEMPLATE: \"Załaduj wyposażenie statku\"\n  STR_EMPTY_SLOT_N: \"Niezapisane {0}\"\n  STR_UNNAMED_SLOT_N: \"Bez nazwy {0}\"\n  STR_ADD_ON_TOP: \"Dodaj na górze\"\n  STR_SAVE_CRAFT_LOADOUT_TEMPLATE: \"Zapisz wyposażenie statku\"\n  STR_SAVE_UC: \"ZAPISZ\"\n  STR_ALL: \"Wszystko\"\n  STR_EQUIPPED: \"Zaekwipowane\"\n  STR_NOT_EQUIPPED: \"Nie zaekwipowane\"\n  STR_UNASSIGNED: \"Inne\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED_BY_SIZE: \"NIE MOŻNA ZAŁADOWAĆ WIĘCEJ SPRZĘTU NA POKŁAD!{SMALLLINE}Maksymalna przestrzeń magazynowa: {0}\"\n  STR_PILOTS: \"PILOCI\"\n  STR_SHIELD: \"TARCZA>{ALT}{0}\"\n  STR_CRAFT_SKIN_ID: \"[{0}]\"\n  STR_SELECT_PILOT: \"Wybierz pilota\"\n  STR_PILOTS_FOR_CRAFT: \"Pilot(ci) dla {0}\"\n  STR_PILOTS_REQUIRED: \"Pilot(ci) potrzebni: {ALT}{0}\"\n  STR_ADD_PILOT: \"Dodaj pilota\"\n  STR_REMOVE_ALL_PILOTS: \"Zdejmij wszystkich pilotów\"\n  STR_ACCURACY_BONUS: \"Premia do celności:\"\n  STR_DODGE_BONUS: \"Premia do uników:\"\n  STR_APPROACH_SPEED: \"Szybkość podejścia:\"\n  STR_COWARDLY: \"Nieśmiała (-50%)\"\n  STR_NORMAL: \"Normalna\"\n  STR_BOLD: \"Śmiała (+50%)\"\n  STR_VERY_BOLD: \"Bardzo śmiała (+100%)\"\n  STR_ARMOR_GROUP_NOT_ALLOWED: \"Ten typ pancerza nie może wejść na pokład.\"\n  STR_SOLDIER_GROUP_NOT_ALLOWED: \"Ten typ żołnierza nie może wejść na pokład.\"\n  STR_SOLDIER_GROUP_NOT_SAME: \"Ten typ żołnierza nie jest kompatybilny z innymi żołnierzami na pokładzie.\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW: \"Podgląd\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_SAVED: \"Podgląd *\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_BRIEFING: \"Ta funkcja pozwala sprawdzić i zmodyfikować rozmieszczenie twoich jednostek na początku bitwy. Masz nieograniczony ruch. Naciśnij i przytrzymaj 'Alt', by podświetlić miejsca dostępne dla jednostek. Naciśnij przycisk 'Przerwij misję', aby zapisać swoje rozmieszczenie. Naciśnij przycisk 'Zakończ turę', by wyjść z podglądu.{NEWLINE}Zauważ, że dodanie nowych żołnierzy lub pojazdów do statku automatycznie skasuje zapisane wcześniej rozmieszczenie. Obecność specjalnego rozmieszczenia jest oznaczona gwiazdką na przycisku 'Podgląd'.\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_BRIEFING_DUMMY: \"Ta funkcja pozwala na podgląd i zmianę tabeli rozmieszczenia tego typu transportowca. Wszelkie zmiany będą zastosowane dla obecnego transportowca, a także każdego, jako kupisz lub wyprodukujesz później w tej kampanii. Zaczynasz z maksymalną liczbą żołnierzy. Każdy żołnierz reprezentuje jeden rząd w tabeli rozmieszczenia. Imiona żołnierzy odpowiadają numerom rzędów. Aby zrobić miejsce na jednostkę 2x2, postaw 4 żołnierzy w kwadracie 2x2. Jeśli nie zapewnisz jej miejsca, duża jednostka nie pojawi się w bitwie.\"\n  STR_BASE_DEFENSE_BRIEFING_PREVIEW: \"Ta funkcja pozwala na podgląd twojej bazy.{NEWLINE}Baw się dobrze!{NEWLINE}{NEWLINE}Naciśnij przycisk 'Koniec tury', aby zamknąć podgląd.\"\n  STR_NOT_ENOUGH_CARGO_SPACE: \"ZA MAŁO MIEJSCA W ŁADOWNI!{SMALLLINE}Użyj innego modułu lub zmniejsz przydzieloną załogę.\"\n  STR_NOT_ENOUGH_STORAGE_SPACE_1: \"ZA MAŁO MIEJSCA W MAGAZYNACH!{SMALLLINE}Za dużo przedmiotów! Użyj innego modułu lub zmniejsz przydzielony sprzęt.\"\n  STR_NOT_ENOUGH_STORAGE_SPACE_2: \"ZA MAŁO MIEJSCA W MAGAZYNACH!{SMALLLINE}Przedmiotów zajmują zbyt wiele miejsca! Użyj innego modułu lub zmniejsz rozmiar przydzielonego sprzętu.\"\n  STR_REFUND_VALUE: \"Wartość sprzedaży> {ALT}{0}\"\n  STR_REFUND_VALUE_NEGATIVE: \"Wydatki> {ALT}{0}\"\n  STR_PRODUCTION_OVERVIEW: \"PRZEGLĄD PRODUKCJI\"\n  STR_RESEARCH_DIARY: \"DZIENNIK BADAŃ\"\n  STR_DISCOVERY_SOURCE_BASE: \"Ten przedmiot odkryto poprzez projekt badawczy.{NEWLINE}Baza badawcza> {ALT}{1}{ALT}{NEWLINE}Kod przedmiotu> {ALT}{0}{ALT}\"\n  STR_DISCOVERY_SOURCE_FREE_FROM: \"Ten przedmiot otrzymano za darmo z innego projektu badawczego.{NEWLINE}Z projektu badawczego> {ALT}{2}{ALT}{NEWLINE}{ALT}{1}{ALT} -> {ALT}{0}{ALT}\"\n  STR_DISCOVERY_SOURCE_FREE_AFTER: \"Ten przedmiot odkryto automatycznie.{NEWLINE}Po projekcie badawczym> {ALT}{2}{ALT}{NEWLINE}{ALT}{1}{ALT} -> {ALT}{0}{ALT}\"\n  STR_DISCOVERY_SOURCE_MISSION: \"Ten przedmiot otrzymano jako nagrodę za misję.{NEWLINE}Typ misji> {ALT}{2}{ALT}{NEWLINE}{ALT}{1}{ALT} -> {ALT}{0}{ALT}\"\n  STR_DISCOVERY_SOURCE_EVENT: \"Ten przedmiot otrzymano jako nagrodę za wydarzenie.{NEWLINE}Typ wydarzenia> {ALT}{2}{ALT}{NEWLINE}{ALT}{1}{ALT} -> {ALT}{0}{ALT}\"\n  STR_RESEARCH_OVERVIEW: \"PRZEGLĄD BADAŃ\"\n  STR_PRISONER_OVERVIEW: \"PRZEGLĄD WIĘŹNIÓW\"\n  STR_PRISONER: \"WIĘZIEŃ\"\n  STR_PRISONER_AMOUNT: \"LICZBA\"\n  STR_PRISONER_INTERROGATED: \"PRZESŁUCHANO\"\n  STR_TOTAL_IN_PRISON: \"Zajęte miejsce>{ALT}{0}\"\n  STR_TOTAL_INTERROGATED: \"Przesłuchano>{ALT}{0}\"\n  STR_PRISON_TYPE: \"Przechowalnia obcych\"\n  STR_KILL_SELECTED: \"Zlikwiduj\"\n  STR_SELL_SELECTED: \"Sprzedaj\"\n  STR_GO_TO_TRANSFERS: \"Prześlij...\"\n  STR_PRISON_CLEANUP: \"Porządki w więzieniu\"\n  STR_TOPIC: \"Temat>{ALT} {0}\"\n  STR_SHOW_ALL: \"Pokaż wszystkie\"\n  STR_NO_DEPENDENCIES: \"Brak wymagań.\"\n  STR_DIRECT_DEPENDENCIES: \"Wymagania bezpośrednie\"\n  STR_LEVEL_2_DEPENDENCIES: \"Wymagania poziomu 2\"\n  STR_LEVEL_3_DEPENDENCIES: \"Wymagania poziomu 3\"\n  STR_LEVEL_4_DEPENDENCIES: \"Wymagania poziomu 4\"\n  STR_MORE_DEPENDENCIES: \"Istnieją jeszcze dalsze wymagania...\"\n  STR_END_OF_SEARCH: \"Koniec szukania.\"\n  STR_REFUND_PRODUCTION: \"ZWROT!\"\n  STR_HOURS_PER_UNIT: \"GODZIN NA JEDNOSTKĘ>{ALT}{0}\"\n  STR_PERSON_JOINING: \"Osoba dołączająca\"\n  STR_RANDOM_PRODUCTION_DISCLAIMER: \"Produkcja losowa!\"\n  STR_OTHER_EMPLOYEES: \"Inny personel i inwentarz\"\n  STR_SHOW_ONLY_NEW: \"Pokaż tylko nowe\"\n  STR_FILTER_DEFAULT: \"Domyślnie\"\n  STR_FILTER_DEFAULT_SUPPLIES_OK: \"Domyślnie (są zasoby)\"\n  STR_FILTER_DEFAULT_NO_SUPPLIES: \"Domyślnie (brak zasobów)\"\n  STR_FILTER_FACILITY_REQUIRED: \"Brakujący budynek\"\n  STR_FILTER_HIDDEN: \"Ukryte\"\n  STR_FILTER_EQUIPPED: \"Zaekwipowane\"\n  STR_FILTER_MISSING: \"Brakujące\"\n  STR_SORT_DEFAULT: \"Domyślnie\"\n  STR_SORT_BY_COST: \"Po koszcie\"\n  STR_SORT_BY_NAME: \"Po nazwie\"\n  STR_RANDOM_PRODUCTION_SUMMARY: \"Podsumowanie\"\n  STR_NOT_ENOUGH_PRISON_SPACE: \"ZA MAŁO POMIESZCZEŃ DLA OBCYCH!{SMALLLINE}Zbuduj nowe pomieszczenia lub prześlij obcych do innych baz.\"\n  STR_MONTHLY_ITEM_PURCHASE_LIMIT_EXCEEDED: \"MIESIĘCZNY LIMIT ZAKUPÓW PRZEKROCZONY!{SMALLLINE}Więcej sztuk będzie dostępnych w przyszłym miesiącu.\"\n  STR_MONTHLY_CRAFT_PURCHASE_LIMIT_EXCEEDED: \"MIESIĘCZNY LIMIT ZAKUPÓW PRZEKROCZONY!{SMALLLINE}Więcej statków będzie dostępnych w przyszłym miesiącu.\"\n  STR_MONTHLY_SOLDIER_HIRING_LIMIT_EXCEEDED: \"MIESIĘCZNY LIMIT REKRUTACJI PRZEKROCZONY!{SMALLLINE}Więcej kandydatów będzie dostępnych w przyszłym miesiącu.\"\n  STR_NOT_ENOUGH_CRAFT_SPACE: \"Za mało miejsca na pokładzie!\"\n  STR_SELECT_AVATAR_FOR: \"WYBIERZ AWATAR DLA{NEWLINE}{0}\"\n  STR_SOLDIER_BONUSES_FOR: \"PREMIE ŻOŁNIERSKIE DLA{NEWLINE}{0}\"\n  STR_SUMMARY: \"Podsumowanie\"\n  STR_MANA_RECOVERY: \"ODZYSKIWANIE MANY> {ALT}{0}\"\n  STR_HEALTH_RECOVERY: \"ODZYSKIWANIE ZDROWIA> {ALT}{0}\"\n  STR_BONUSES_BUTTON: \"+\"\n  STR_PROMOTE_SOLDIER: \"AWANS/DEGRADACJA{NEWLINE}{0} {1}\"\n  STR_RANK_HEADER: \"RANGA\"\n  STR_OPENINGS_HEADER: \"WAKATY\"\n  STR_KILLER_AND_WEAPON: \"{0}, {1}\"\n  STR_TRAINING: \"Trening\"\n  STR_SOLDIER_INFO: \"Dane żołnierza\"\n  STR_SELECT_TRANSFORMATION_FOR: \"WYBIERZ TRANSFORMACJĘ DLA{NEWLINE}{0}\"\n  STR_TRANSFORMATIONS_BUTTON: \"^\"\n  STR_TRANSFER_TIME: \"Czas transferu>{ALT}{0}\"\n  STR_RECOVERY_TIME: \"Czas leczenia>{ALT}{0}\"\n  STR_CURRENT_STATS: \"Obecne\"\n  STR_CHANGES: \"Zmiany\"\n  STR_CHANGES_MIN: \"Zmiany (min.)\"\n  STR_CHANGES_MAX: \"Zmiany (maks.)\"\n  STR_BONUS_STATS: \"Premia\"\n  STR_TRANSFORMATIONS_OVERVIEW: \"Przegląd transformacji\"\n  STR_PROJECT_NAME: \"NAZWA PROJEKTU\"\n  STR_AVAILABLE_MATERIALS: \"DOSTĘPNE MATERIAŁY\"\n  STR_ELIGIBLE_SOLDIERS: \"DOZWOLENI ŻOŁNIERZE\"\n  STR_SHOW_ONLY_ELIGIBLE: \"Pokaż tylko dozwolone\"\n  STR_ALL_SOLDIER_TYPES: \"Wszystkie typy żołnierzy\"\n  STR_ALL_SOLDIERS: \"Wszyscy żołnierze\"\n  STR_HEALTHY_SOLDIERS: \"Zdrowi żołnierze\"\n  STR_WOUNDED_SOLDIERS: \"Ranni żołnierze\"\n  STR_DEAD_SOLDIERS: \"Martwi żołnierze\"\n  STR_GRAND_TOTAL: \"Łączna suma\"\n  STR_AVAILABLE_TOPICS: \"DOSTĘPNE TEMATY\"\n  STR_QS_THREE_LETTERS_A: \"Wpisz przynajmniej 3 znaki\"\n  STR_QS_THREE_LETTERS_B: \"w polu szybkiego szukania...\"\n  STR_M_FLAG: \"[prod.]\"\n  STR_F_FLAG: \"[bud.]\"\n  STR_I_FLAG: \" [przdm.]\"\n  STR_C_FLAG: \"[p]\"\n  STR_THIS_FEATURE_IS_DISABLED_1: \"Ta funkcja jest wyłączona.\"\n  STR_THIS_FEATURE_IS_DISABLED_2: \"Ta funkcja jest wyłączona.\"\n  STR_THIS_FEATURE_IS_DISABLED_3: \"Ta funkcja jest wyłączona.\"\n  STR_THIS_FEATURE_IS_DISABLED_4: \"Ta funkcja jest wyłączona.\"\n  STR_THIS_FEATURE_IS_DISABLED_5: \"Ta funkcja jest wyłączona.\"\n  STR_TECH_TREE_VIEWER: \"Przeglądarka drzewa technologii\"\n  STR_SELECT_TOPIC: \"Wybierz temat:\"\n  STR_RESEARCH_PROGRESS: \"Postęp>{ALT} {0}%\"\n  STR_ITEM_DESTROYED: \"Przedmioty zniszczone:\"\n  STR_ITEM_REQUIRED: \"Przedmioty wymagane:\"\n  STR_SERVICES_REQUIRED: \"Wymagane funkcje:\"\n  STR_SERVICES_PROVIDED: \"Zapewnia funkcje:\"\n  STR_SERVICES_FORBIDDEN: \"Zabrania funkcji:\"\n  STR_REQUIRES: \"Wymaga:\"\n  STR_DEPENDS_ON: \"Wymaga:\"\n  STR_UNLOCKED_BY: \"Odblokowywane przez:\"\n  STR_DISABLED_BY: \"Wyłączane przez:\"\n  STR_REENABLED_BY: \"Włączane ponownie przez:\"\n  STR_GET_FOR_FREE_FROM: \"Za darmo od:\"\n  STR_IS_LOOKUP_OF: \"Wywołane przez:\"\n  STR_LOOKUP: \"Wywołuje:\"\n  STR_SPAWNED_ITEMS: \"Tworzone obiekty:\"\n  STR_SPAWNED_EVENT: \"Uruchamia zdarzenie:\"\n  STR_REQUIRED_BY: \"Wymagane przez:\"\n  STR_REQUIRED_BY_TRANSFORMATIONS: \"Wymagane do transformacji:\"\n  STR_LEADS_TO: \"Prowadzi do:\"\n  STR_UNLOCKS: \"Odblokowuje:\"\n  STR_DISABLES: \"Wyłącza:\"\n  STR_REENABLES: \"Włącza ponownie:\"\n  STR_GIVES_ONE_FOR_FREE_SEQ: \"Daje za darmo (sekwencyjnie):\"\n  STR_GIVES_ONE_FOR_FREE: \"Daje za darmo:\"\n  STR_RESEARCH_REQUIRED: \"Wymagane badania:\"\n  STR_RESEARCH_REQUIRED_USE: \"Wymagane badania (użycie):\"\n  STR_RESEARCH_REQUIRED_BUY: \"Wymagane badania (zakup):\"\n  STR_SERVICES_REQUIRED_BUY: \"Wymagane funkcje (zakup):\"\n  STR_PRODUCED_BY: \"Produkowane przez:\"\n  STR_SPAWNED_BY: \"Tworzone przez:\"\n  STR_MATERIALS_REQUIRED: \"Wymagane materiały:\"\n  STR_TTV_COST_PER_UNIT: \"Koszt na jednostkę:\"\n  STR_TTV_ENGINEER_HOURS: \"Roboczogodzin:\"\n  STR_TTV_WORK_SPACE_REQUIRED: \"Wymagana przestrzeń w warsztacie:\"\n  STR_ITEMS_PRODUCED: \"Wyprodukowane przedmioty:\"\n  STR_PERSON_RECRUITED: \"Zrekrutowane osoby:\"\n  STR_UNLOCKS_ARCS: \"Odblokowuje wątki:\"\n  STR_DISABLES_ARCS: \"Wyłącza wątki:\"\n  STR_UNLOCKS_MISSIONS: \"Odblokowuje misje:\"\n  STR_DISABLES_MISSIONS: \"Wyłącza misje:\"\n  STR_UNLOCKS_EVENTS: \"Odblokowuje zdarzenia:\"\n  STR_DISABLES_EVENTS: \"Wyłącza zdarzenia:\"\n  STR_AFFECTS_GAME_PROGRESSION: \"Wpływa na postęp w grze!\"\n  STR_ITEMS_AT_DESTINATION: \"Sztuk na miejscu\"\n  STR_PRISONERS: \"Więźniowie\"\n  STR_ARMORS: \"Pancerze\"\n  STR_CRAFT_DEPLOYMENT_QUESTION: \"Zapisać rozstawienie w pojeździe?\"\n  STR_MUST_USE_BOTH_HANDS: \"Do tego potrzebne są obie ręce!\"\n  STR_NOT_ENOUGH_MORALE: \"Za niskie morale!\"\n  STR_NOT_ENOUGH_HEALTH: \"Za mało zdrowia!\"\n  STR_NOT_ENOUGH_MANA: \"Za mało many!\"\n  STR_NOT_ENOUGH_STUN: \"Za wysoki poziom oszołomienia!\"\n  STR_MIND_CONTROL_SUCCESSFUL_ALT: \"Akcja udana\"\n  STR_LINE_OF_SIGHT_REQUIRED: \"Wymagana linia wzroku.\"\n  STR_CENTER_ON_WOUNDED_FRIEND: \"Wycentruj na rannym sojuszniku\"\n  STR_CENTER_ON_DIZZY_FRIEND: \"Wycentruj na oszołomionym sojuszniku\"\n  STR_BUG_HUNT_ACTIVATED: \"Tryb obławy włączony: wrogowie są widoczni na minimapie!\"\n  STR_QUICK_MODE_ACTIVATED: \"Tryb Usaina Bolta włączony.{NEWLINE}Naciśnij znów Ctrl+S , by wyłączyć.\"\n  STR_QUICK_MODE_DEACTIVATED: \"Tryb Usaina Bolta wyłączony.\"\n  STR_TARGET_ENEMY: \"; Cel = WRÓG\"\n  STR_TARGET_NEUTRAL: \"; Cel = NEUTRALNY\"\n  STR_TARGET_FRIEND: \"; Cel = SOJUSZNIK\"\n  STR_TARGET_YOURSELF: \"; Cel = NA SOBIE\"\n  STR_TARGET_ON_THE_GROUND: \"(na ziemi)\"\n  STR_USE_SPECIAL_ITEM: \"Użyj przedmiotu specjalnego\"\n  STR_NO_EXPERIENCE_YET: \"Na razie brak doświadczenia:\"\n  STR_OPERATION_UC: \"OPERACJA> {0}\"\n  STR_WHAT_CAN_I_WEAR: \"Co mogę założyć?\"\n  STR_STARTING_CONDITION_ARMORS_FORBIDDEN: \"Ta misja wymaga określonego stroju.{NEWLINE}{NEWLINE}Zakazane typy pancerzy: {0}\"\n  STR_STARTING_CONDITION_ARMORS_ALLOWED: \"Ta misja wymaga określonego stroju.{NEWLINE}{NEWLINE}Dostępne typy pancerzy: {0}\"\n  STR_MISSION_OVER: \"Misja ukończona.\"\n  STR_UNITS_WITH_FATAL_WOUNDS:\n    one: \"{N} z nas wciąż ma nieopatrzone rany\"\n    few: \"{N} z nas wciąż ma nieopatrzone rany\"\n    many: \"{N} z nas wciąż ma nieopatrzone rany\"\n    other: \"{N} z nas wciąż ma nieopatrzone rany\"\n  STR_END_MISSION_QUESTION: \"Zakończyć misję?\"\n  STR_LOOT: \"ŁUP\"\n  STR_SELL: \"SPRZEDAŻ\"\n  STR_LIVE_ALIENS_SURRENDERED: \"WROGOWIE SKAPITULOWALI\"\n  STR_MISSION_ABORTED: \"MISJA PORZUCONA\"\n  STR_VIPS_SAVED: \"OCALENI VIP-OWIE\"\n  STR_VIPS_LOST: \"UTRACENI VIP-OWIE\"\n  STR_BOUNTY: \"OKUP\"\n  STR_MANA_ABBREVIATION: \"MAN\"\n  STR_EXPERIENCE_OVERVIEW: \"Przegląd doświadczenia\"\n  STR_CANNOT_PLACE_ITEM_INTO_THIS_SECTION: \"Nie wolno tutaj umieścić tego przedmiotu.{NEWLINE}Nie pytaj, dlaczego!\"\n  STR_ONE_HAND_MUST_BE_EMPTY: \"Choć jedna ręka musi być wolna!\"\n  STR_LOAD_EQUIPMENT_TEMPLATE: \"Załaduj schemat wyposażenia\"\n  STR_SAVE_EQUIPMENT_TEMPLATE: \"Zapisz schemat wyposażenia\"\n  STR_FIRING_SHORT: \"Strz.>{ALT}{0}\"\n  STR_THROWING_SHORT: \"Rzut>{ALT}{0}\"\n  STR_MELEE_SHORT: \"Wręcz>{ALT}{0}\"\n  STR_PERSONAL_EQUIPMENT: \"EKWIPUNEK OSOBISTY\"\n  STR_SAVE_PERSONAL_EQUIPMENT: \"Zapisz ekwipunek osobisty\"\n  STR_LOAD_PERSONAL_EQUIPMENT: \"Załaduj ekwipunek osobisty\"\n  STR_PERSONAL_EQUIPMENT_SAVED: \"Zapisano ekwipunek osobisty.\"\n  STR_PERSONAL_EQUIPMENT_NOT_DEFINED: \"Ekwipunek osobisty jeszcze niezdefiniowany.\"\n  STR_SLOT: \"Mocowanie>{ALT}{0}\"\n  STR_THINKING: \"Myślę...\"\n  STR_TELL_ME_MORE: \"Więcej informacji...\"\n  STR_REINFORCEMENTS_ALERT: \"Uwaga, posiłki!\"\n  STR_HIT_LOG_NEW_TURN: \"Nowa tura\"\n  STR_FAILED_CQB_CHECK: \"Wróg odbija twój atak!\"\n  STR_NO_TRAJECTORY: \"Brak odpowiedniej trajektorii!\"\n  STR_HIT_LOG_NEW_BULLET: \"=> \"\n  STR_MANA_SHORT: \"MA>{ALT}{0}\"\n  STR_SKILL_NEEDS_ITEM: \"Ta umiejętność wymaga przedmiotu!\"\n  STR_HIT_LOG_NO_DAMAGE: \"0 \"\n  STR_HIT_LOG_SMALL_DAMAGE: \"uraz\"\n  STR_HIT_LOG_BIG_DAMAGE: \"URAZ\"\n  STR_HIT_LOG_REACTION_FIRE: \"Strzał z reakcji...\"\n  STR_HIT_LOG: \"Rejestr trafień\"\n  STR_BUTTON_TOUCH: \"Dotyk\"\n  STR_BUTTON_1: \"1\"\n  STR_BUTTON_10: \"10\"\n  STR_BUTTON_100: \"100\"\n  STR_BUTTON_LMB: \"LPM\"\n  STR_BUTTON_RMB: \"PPM\"\n  STR_BUTTON_MMB: \"ŚPM\"\n  STR_BUTTON_CTRL: \"Ctrl\"\n  STR_BUTTON_ALT: \"Alt\"\n  STR_BUTTON_SHIFT: \"Shift\"\n  STR_LAZY_LOADING: \"Szybkie ładowanie\"\n  STR_LAZY_LOADING_DESC: \"Gdy włączone, zasoby graficzne ładują się w miarę potrzeby. Gdy wyłączone, wszystkie zasoby są ładowane przy starcie gry.\"\n  STR_VSYNC_FOR_OPENGL: \"VSync dla OpenGL\"\n  STR_VSYNC_FOR_OPENGL_DESC: \"Wyłącz by maksymalnie przyspieszyć ukryte ruchy przeciwników i (opcjonalnie) twoich żołnierzy. NIE USTAWIAJ limitu FPS na 0. Działa tylko dla wyświetlania w trybie OpenGL.\"\n  STR_UPDATE_CHECK: \"Automatycznie sprawdź aktualizację\"\n  STR_UPDATE_CHECK_DESC: \"Gdy włączone, gra OpenXcom będzie automatycznie sprawdzała, czy są aktualizacje, oraz da ci opcję pobrania ich jednym przyciskiem.\"\n  STR_AUTOSAVE_SLOTS: \"Miejsca na zapis gry\"\n  STR_AUTOSAVE_SLOTS_DESC: \"Liczba miejsc na samozapis podczas bitwy.\"\n  STR_AUTO_SAVE_BATTLESCAPE_SLOT_WITH_NUMBER: \"<SAMOZAPIS BITWY> {0}\"\n  STR_GEO_AUTOSAVE_FREQUENCY: \"Częstośćsamozapisu (widok globu)\"\n  STR_GEO_AUTOSAVE_FREQUENCY_DESC: \"Liczba dni, po upływie których gra będzie automatycznie zapisywana.\"\n  STR_GEO_AUTOSAVE_SLOTS: \"Miejsc na samozapis (widok globu)\"\n  STR_GEO_AUTOSAVE_SLOTS_DESC: \"Liczba miejsc na samozapis w widoku globu.\"\n  STR_AUTO_SAVE_GEOSCAPE_SLOT_WITH_NUMBER: \"<SAMOZAPIS GLOBU> {0}\"\n  STR_OXCE_LINKS: \"Panel\"\n  STR_OXCE_LINKS_DESC: \"Włącza dodatkowe menu, przyciski i linki dla funkcji OXCE.\"\n  STR_PEDIA_SHOW_CLIP_SIZE: \"Pokaż wielkość magazynka w Ufopedii\"\n  STR_PEDIA_SHOW_CLIP_SIZE_DESC: \"Gdy włączone, liczba naboi w magazynku będzie widoczna przy ikonach amunicji w Ufopedii.\"\n  STR_INTERCEPT_TABLE_SIZE: \"Rozmiar pulpitu przechwycenia\"\n  STR_INTERCEPT_TABLE_SIZE_DESC: \"Rozmiar tabel w oknach dialogowych: przechwycenia i listy celów.\"\n  STR_SHOW_SLACKING_INDICATOR: \"Pokaż wskaźnik próżniactwa\"\n  STR_SHOW_SLACKING_INDICATOR_DESC: \"Gdy włączone, gra będzie wyświetlała, ilu naukowców i inżynierów nie pracuje.\"\n  STR_SHOW_MAINTENANCE_TIME: \"Pokaż czas przygotowania pojazdu\"\n  STR_SHOW_MAINTENANCE_TIME_DESC: \"{ALT}0>{ALT} Nie pokazuj {ALT}1>{ALT} Pokaż tylko dla bieżącej czynności {ALT}2>{ALT} Pokaż wszystko (naprawa + uzbrajanie + tankowanie).\"\n  STR_SHOW_ETA: \"Pokaż szacowany czas lotu\"\n  STR_SHOW_ETA_DESC: \"{ALT}0>{ALT} Nie pokazuj {ALT}1>{ALT} Pokaż czas tylko do celów stacjonarnych {ALT}2>{ALT} Pokaż czas też do celów ruchomych.\"\n  STR_UFO_LANDING_ALERT: \"Ostrzeżenie o lądowaniu UFO\"\n  STR_UFO_LANDING_ALERT_DESC: \"Gdy włączone, otrzymasz powiadomienie za każdym razem, gdy odkryte UFO wyląduje.\"\n  STR_REMEMBER_DISABLED_CRAFT_WEAPONS: \"Zapamiętuj wyłączone systemy broni myśliwców\"\n  STR_REMEMBER_DISABLED_CRAFT_WEAPONS_DESC: \"Broń wyłączona podczas walki powietrznej pozostanie wyłączona. Nie będzie też uzbrajana w bazie.\"\n  STR_GEO_EVENT_INSTANT_DELIVERY: \"Natychmiastowa dostawa z wydarzeń\"\n  STR_GEO_EVENT_INSTANT_DELIVERY_DESC: \"Gdy włączone, przedmioty przyznawane z wydarzeń przychodzą natychmiast. W innym wypadku, po 1 godzinie.\"\n  STR_SHOW_BASE_NAME_IN_POPUPS: \"Pokaż nazwę bazy w powiadomieniach\"\n  STR_SHOW_BASE_NAME_IN_POPUPS_DESC: \"Gdy włączone, w oknach powiadomień (np. o ukończonych badaniach) wyświetli się odpowiednia nazwa bazy.\"\n  STR_ALTERNATE_CRAFT_EQUIPMENT_MANAGEMENT: \"Alternatywne zarządzanie wyposażeniem\"\n  STR_ALTERNATE_CRAFT_EQUIPMENT_MANAGEMENT_DESC: \"Gdy włączone, przenoszenie żołnierzy między bazą a pojazdem przeniesie też ich ekwipunek (jeśli to możliwe).\"\n  STR_BASE_INFO_SCALE: \"Skaluj długie paski w ekranie bazy\"\n  STR_BASE_INFO_SCALE_DESC: \"Gdy włączone, paski dłuższe niż 140 pikseli są skalowane, żeby się zmieściły w interfejsie.\"\n  STR_HIGHLIGHT_NEW: \"Zaznacz nowe tematy\"\n  STR_HIGHLIGHT_NEW_DESC: \"Gdy włączone, nowe tematy badań, nowe projekty inżynieryjne i nowe artykuły w Ufopedii zaznaczone będą innym kolorem.\"\n  STR_RESEARCH_SCROLL_SPEED: \"Szybkość rolki w badaniach\"\n  STR_RESEARCH_SCROLL_SPEED_DESC: \"Naukowców można przydzielać/zdejmować bezpośrednio w interfejsie aktywnych projektów badawczych za pomocą rolki myszy.\"\n  STR_RESEARCH_SCROLL_SPEED_CTRL: \"Szybkość rolki w badaniach (z Ctrl)\"\n  STR_RESEARCH_SCROLL_SPEED_CTRL_DESC: \"Naukowców można przydzielać/zdejmować bezpośrednio w interfejsie aktywnych projektów badawczych za pomocą rolki myszy.\"\n  STR_MANUFACTURE_FILTER_SUPPLIES_OK: \"Alternatywny filtr produkcyjny\"\n  STR_MANUFACTURE_FILTER_SUPPLIES_OK_DESC: \"Gdy włączone, interfejs pokazuje tylko przedmioty, które można produkować z dostępnych materiałów.\"\n  STR_MANUFACTURE_SCROLL_SPEED: \"Szybkość rolki w produkcji\"\n  STR_MANUFACTURE_SCROLL_SPEED_DESC: \"Inżynierów można przydzielać/zdejmować bezpośrednio w interfejsie aktywnych projektów produkcyjnych za pomocą rolki myszy.\"\n  STR_MANUFACTURE_SCROLL_SPEED_CTRL: \"Szybkość rolki w produkcji (z Ctrl)\"\n  STR_MANUFACTURE_SCROLL_SPEED_CTRL_DESC: \"Inżynierów można przydzielać/zdejmować bezpośrednio w interfejsie aktywnych projektów produkcyjnych za pomocą rolki myszy.\"\n  STR_PERSONAL_LAYOUT_INCLUDING_ARMOR: \"Zawrzyj pancerz w ekwipunku osobistym\"\n  STR_PERSONAL_LAYOUT_INCLUDING_ARMOR_DESC: \"Gdy włączone, ekwipunek osobisty żołnierza będzie zapisywany łącznie z noszonym pancerzem.\"\n  STR_MANUALPROMOTIONS: \"Awanse ręczne\"\n  STR_MANUALPROMOTIONS_DESC: \"Gdy włączone, żołnierzy można osobiście awansować (lub degradować), klikając ikonę rangi.\"\n  STR_WOUNDED_DEFEND_BASE_IF: \"Ranni bronią (gdy PŻ powyżej X%)\"\n  STR_WOUNDED_DEFEND_BASE_IF_DESC: \"Ranni żołnierze również bronią bazy, o ile ich zdrowie przekracza zadany próg procentowy.\"\n  STR_PLAY_BRIEFING_MUSIC_DURING_EQUIPMENT: \"Przedłużaj muzykę odprawy\"\n  STR_PLAY_BRIEFING_MUSIC_DURING_EQUIPMENT_DESC: \"Muzyka z odprawy będzie grała podczas wyposażania żołnierzy, do początku bitwy.\"\n  STR_NIGHT_VISION_COLOR: \"Wybierz kolor nocnego wyświetlania\"\n  STR_NIGHT_VISION_COLOR_DESC: \"Wartości od 1 do 15 reprezentują różne kolory wyświetlania.\"\n  STR_AUTO_NIGHT_VISION_THRESHOLD: \"Automatyczny próg dodatkowego widzenia w ciemności\"\n  STR_AUTO_NIGHT_VISION_THRESHOLD_DESC: \"Jeśli jasność mapy jest poniżej tego progu, tryb nocnego widzenia włącza się automatycznie.\"\n  STR_SHOW_ACCURACY_ON_CROSSHAIR: \"Pokazuj szanse trafienia na celowniku\"\n  STR_SHOW_ACCURACY_ON_CROSSHAIR_DESC: \"{ALT}0>{ALT}Never {ALT}1>{ALT}tylko, gdy włączona jest celność z UFO Extendera {ALT}2>{ALT}Zawsze\"\n  STR_REACTION_FIRE_THRESHOLD: \"Próg strzału z reakcji\"\n  STR_REACTION_FIRE_THRESHOLD_DESC: \"Jednostki kontrolowane przez X-Com nie będą strzelać z reakcji, jeśli ich celność (dla danego celu) będzie niższa od tego progu.\"\n  STR_AUTO_SELL: \"Menedżer automatycznej sprzedaży\"\n  STR_AUTO_SELL_DESC: \"W ekranie sprzedaży ekwipunku po bitwie wszelkie typy przedmiotów sprzedane wcześniej zostaną automatycznie oznaczone do sprzedaży.\"\n  STR_AUTOMATICPROMOTIONS: \"Awanse automatyczne\"\n  STR_AUTOMATICPROMOTIONS_DESC: \"Gdy włączone, żołnierze są awansowani automatycznie po misji.\"\n  STR_OFF_CENTRE_SHOOTING: \"Strzelanie zdecentrowane\"\n  STR_OFF_CENTRE_SHOOTING_DESC: \"Żołnierze będą próbowali nieco korygować kąt strzału przy braku linii ognia.\"\n  STR_UNIFORM_SHOOTING_SPREAD: \"Ujednolicony rozrzut\"\n  STR_UNIFORM_SHOOTING_SPREAD_DESC: \"Rozrzut jest ujednolicony we wszystkich kierunkach i ciaśniejszy.\"\n  STR_CRASHED_OR_LANDED: \"Przycisk kraksa/lądowanie\"\n  STR_CRASHED_OR_LANDED_DESC: \"Gdy włączone, na ekranie nowej bitwy pojawia się jeszcze jeden przycisk. Możesz też wcisnąć F11, by go wyświetlić/ukryć. {ALT}0>{ALT}wyłączone, {ALT}1>{ALT}kraksa, {ALT}2>{ALT}lądowanie.\"\n  STR_GRAPHS_ZOOM_IN: \"Przybliż (wykresy)\"\n  STR_GRAPHS_ZOOM_OUT: \"Oddal (wykresy)\"\n  STR_MARK_ALL_AS_SEEN: \"Oznacz wszystkie jako przeczytane\"\n  STR_SELL_ALL: \"Sprzedaj wszystko\"\n  STR_SELL_ALL_BUT_ONE: \"Sprzedaj wszystko oprócz jednego\"\n  STR_TRANSFER_ALL: \"Prześlij wszystko\"\n  STR_REMOVE_SOLDIERS_FROM_ALL_CRAFTS: \"Usuń żołnierzy ze wszystkich pojazdów\"\n  STR_REMOVE_SOLDIERS_FROM_CRAFT: \"Usuń żołnierzy z pojazdu\"\n  STR_REMOVE_EQUIPMENT_FROM_CRAFT: \"Usuń wyposażenie z pojazdu\"\n  STR_REMOVE_ARMOR_FROM_ALL_CRAFTS: \"Usuń pancerze ze wszystkich pojazdów\"\n  STR_REMOVE_ARMOR_FROM_CRAFT: \"Usuń pancerze z pojazdu\"\n  STR_REMOVE_SOLDIERS_FROM_TRAINING: \"Odwołaj żołnierzy z treningu\"\n  STR_ADD_SOLDIERS_TO_TRAINING: \"Dodaj żołnierzy do treningu\"\n  STR_INVENTORY_ARMOR: \"Zmień pancerz\"\n  STR_INVENTORY_AVATAR: \"Zmień awatar\"\n  STR_INVENTORY_DIARY_LIGHT: \"Zobacz okrojony dziennik\"\n  STR_ACTION_ITEM_1: \"Przedmiot: akcja 1 (celowany/użyj)\"\n  STR_ACTION_ITEM_2: \"Przedmiot: akcja 2 (szybki)\"\n  STR_ACTION_ITEM_3: \"Przedmiot: akcja 3 (seria)\"\n  STR_ACTION_ITEM_4: \"Przedmiot: akcja 4 (walka wręcz)\"\n  STR_ACTION_ITEM_5: \"Przedmiot: akcja 5 (rzut)\"\n  STR_INSTA_SAVE: \"Hiperzapis\"\n  STR_TOGGLE_QUICK_SEARCH: \"Włącz pasek szybkiego szukania\"\n  STR_TOGGLE_NIGHT_VISION: \"Przełącz wyświetlanie nocne\"\n  STR_HOLD_NIGHT_VISION: \"Zerknij wyświetlaniem nocnym\"\n  STR_SELECT_MUSIC_TRACK: \"Wybierz ścieżkę dźwiękową\"\n  STR_TOGGLE_TOUCH_BUTTONS: \"Przełącz przyciski dotykowe\"\n  STR_TOGGLE_BRIGHTNESS: \"Przełącz jasność (efekt tylko wizualny)\"\n  STR_BRIEFING: \"Odprawa\"\n  STR_TOGGLE_DEBUG_MODE: \"Przełącz tryb debugowania\"\n  STR_DEBUG_KILL_ALL_ALIENS: \"DEBUG: Zabij wszystkich obcych\"\n  STR_PHYSICAL_TRAINING: \"Trening bojowy\"\n  STR_REMAINING_TRAINING_FACILITY_CAPACITY: \"POZOSTAŁO MIEJSC W TRENINGU> {ALT}{0}\"\n  STR_NO_WOUNDED: \"-\"\n  STR_NO_QUEUED: \"+\"\n  STR_NO_DONE: \"GOTOWE\"\n  STR_NO_AMMO: \"BRAK AMUNICJI!\"\n  STR_START_FIRING: \"Ognia!\"\n  STR_SKIP_FIRING: \"Wpuśćmy ich...\"\n  STR_ALIEN_MISSILES_HAVE_DAMAGED_OUR_BASE: \"Ostrzał obcych uszkodził naszą bazę {0}\"\n  STR_ALIEN_MISSILES_HAVE_DESTROYED_OUR_BASE: \"Ostrzał obcych zniszczył naszą bazę {0}\"\n  STR_STARTING_CONDITION_COMMANDER: \"Ta misja wymaga obecności komendanta.\"\n  STR_STARTING_CONDITION_CRAFT: \"Nie można użyć tego pojazdu w tej misji.\"\n  STR_STARTING_CONDITION_CRAFT_ALLOWED: \"Nie można użyć tego pojazdu w tej misji.{NEWLINE}{NEWLINE}Dozwolone pojazdy: {0}\"\n  STR_STARTING_CONDITION_CRAFT_FORBIDDEN: \"Nie można użyć tego pojazdu w tej misji.{NEWLINE}{NEWLINE}Zakazane pojazdy: {0}\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE: \"Niektórzy żołnierze nie mogą wziąć udziału w tej misji.\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE_ALLOWED: \"Niektórzy nie mogą wziąć udziału w tej misji.{NEWLINE}{NEWLINE}Dozwolone typy żołnierzy: {0}\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE_FORBIDDEN: \"Niektórzy nie mogą wziąć udziału w tej misji.{NEWLINE}{NEWLINE}Zakazane typy żołnierzy: {0}\"\n  STR_STARTING_CONDITION_ITEM: \"Ta misja wymaga określonych przedmiotów:{NEWLINE}{NEWLINE}{0}\"\n  STR_NOT_ENOUGH_FUEL_TO_REACH_TARGET: \"ZA MAŁO PALIWA!{SMALLLINE}Punkt docelowy leży poza zasięgiem pojazdu.\"\n  STR_TOO_MANY_ITEMS_ONBOARD: \"ZA DUŻO PRZEDMIOTÓW!{SMALLLINE}Ten pojazd nie pomieści tylu przedmiotów.\"\n  STR_ARMOR_NOT_ALLOWED_ONBOARD: \"PANCERZ NIEDOZWOLONY!{SMALLLINE}Niektórzy żołnierze noszą nieodpowiednie pancerze.\"\n  STR_FOLLOW_WING_LEADER_QUESTION: \"Leć za dowódcą eskadry?\"\n  STR_ASSIGN_PILOTS: \"Przydziel pilotów...\"\n  STR_NOT_ENOUGH_PILOTS: \"Za mało pilotów!{NEWLINE}Minimum: {0}\"\n  STR_DAILY_PILOT_EXPERIENCE: \"Dzienne doświadczenie pilotów\"\n  STR_UFO_SHIELD_HIT: \"TRAFIENIE W TARCZE!\"\n  STR_UFO_HIT_NO_DAMAGE: \"KADŁUB NIENARUSZONY!\"\n  STR_UFO_SHIELD_DOWN: \"TARCZE WROGA PADŁY!\"\n  STR_UFO_HIT_GLANCING: \"SŁABE TRAFIENIE!\"\n  STR_INTERCEPTOR_SHIELD_HIT: \"NASZE TARCZE TRZYMAJĄ!\"\n  STR_TRACTOR_BEAM_ENGAGED: \"PROMIEŃ ŚCIĄGAJĄCY WŁĄCZONY!\"\n  STR_TRACTOR_BEAM_DISENGAGED: \"PROMIEŃ ŚCIĄGAJĄCY WYŁĄCZONY\"\n  STR_SELF_DESTRUCT_ACTIVATED: \"SAMOZNISZCZENIE URUCHOMIONE!\"\n  STR_SELF_DESTRUCT_CANCELLED: \"SAMOZNISZCZENIE ODWOŁANE\"\n  STR_MISSILE_DAMAGED: \">>> POCISK USZKODZONY <<<\"\n  STR_MISSILE_DESTROYED: \">>> POCISK ZNISZCZONY <<<\"\n  STR_EXTENDED_LINKS: \"Linki\"\n  STR_AUTO_PATROL: \"AUTOMATYCZNY PATROL\"\n  STR_ETA: \"CZAS>{ALT}{0}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_FACILITY_AT_BASE: \"Za mało: {0} by uzbroić: {1} w bazie {2}\"\n  STR_UFO_STARTED_HUNTING: \"{0} jest na kursie przechwytującym {1}\"\n  STR_CRAFT_IS_READY: \"{0} w {1} jest w gotowości.\"\n  STR_ECONOMY_WARNING: \"Fundusze {0} i przychód {1} są za niskie a koszty utrzymania {2} za wysokie! Sprzedaj coś, by uniknąć zadłużenia... Brakujące fundusze: {3}\"\n  STR_SLACKING_INDICATOR: \"{0}:{1}\"\n  STR_TRAINING_INDICATOR: \"{0}:{1}\"\n  STR_EXTENDED_UC: \"PANEL\"\n  STR_RETURNING: \"WRACA\"\n  STR_INTERCEPTING: \"PRZECHWYTUJE\"\n  STR_ESCORTING: \"ESKORTA\"\n  STR_EN_ROUTE: \"W DRODZE\"\n  STR_PILOT_MISSING: \"BRAK PILOTA\"\n  STR_DAY_SHORT: \"{0}d\"\n  STR_HOUR_SHORT: \"{0}h\"\n  STR_PERFORMANCE_BONUS: \"Premia za wyniki\"\n  STR_COUNTRY_HAS_CANCELLED_A_SECRET_PACT: \"{0} zrywa pakt z siłami obcych i uzyskuje zezwolenie na powrót do projektu.\"\n  STR_COUNTRIES_HAVE_CANCELLED_A_SECRET_PACT: \"{0} zrywają pakt z siłami obcych i uzyskują zezwolenie na powrót do projektu.\"\n  STR_WE_CAN_NOW_RENT: \"Możemy teraz wynająć\"\n  STR_REQUIRED_BASE_SERVICES: \"Wymaga funkcji bazy: {0}\"\n  STR_WE_CAN_NOW_BUILD: \"Możemy teraz budować\"\n  STR_WE_CAN_NOW_PURCHASE: \"Możemy teraz kupować\"\n  STR_NOT_ENOUGH_LIVING_SPACE_AT_BASE: \"Za mało pomieszczeń mieszkalnych, by przyjąć{NEWLINE}{0}{NEWLINE}w{NEWLINE}{1}\"\n  STR_INFO: \"DANE\"\n  STR_DESPAWN_PENALTY: \"Kara za pominięcie> {0}\"\n  STR_TRAINING_FINISHED: \"Trening ukończony{NEWLINE}w bazie {0}\"\n  STR_PSI_TRAINING_FINISHED: \"Trening psi ukończony{NEWLINE}w bazie {0}\"\n  STR_IGNORE_UC: \"IGNORUJ\"\n  STR_UFO_TRACKER: \"Lista celów\"\n  STR_UPDATE: \"Aktualizacja\"\n  STR_LATEST_VERSION_INFO: \"Używasz najnowszej wersji OpenXcom.\"\n  STR_MASTER_MOD_VERSION_REQUIRED_QUESTION: \"Ten mod wymaga podstawowej gry w wersji {0} do poprawnego działania. Włączyć moda?\"\n  STR_VERSION_REQUIRED_QUESTION: \"Ten mod wymaga OXCE w wersji {0} do poprawnego działania. Włączyć moda?\"\n  STR_OPEN_MODS_FOLDER: \"Otwórz\"\n  STR_GLOBE_TEXTURE: \"Tekstura globu\"\n  STR_NOTES: \"Notatki\"\n  STR_NEW_NOTE: \"<NOWA NOTATKA>\"\n  STR_ENGINE_OXC: \"OXC\"\n  STR_ENGINE_OXCE: \"OXCE\"\n  STR_ENGINE_OTHER: \"INNE\"\n  STR_BASESCAPE: \"Widok bazy\"\n  STR_AI: \"SI\"\n  STR_PATH_ENERGY_COST: \"Energia\"\n  STR_PATH_ENERGY_COST_DESC: \"Kliknięcie pokazuje energię, jaką twoja jednostka będzie miała po ruchu do tego celu.\"\n  STR_VEHICLES_LOST: \"Utraconych pojazdów\"\n  STR_TEST_SCREEN: \"EKRAN TESTOWY\"\n  STR_PALETTE: \"Paleta:\"\n  STR_PREVIEW: \"Podgląd\"\n  STR_TINY_BORDERLESS: \"Malutkie, bez ramek\"\n  STR_TINY_BORDER: \"Malutkie\"\n  STR_SMALL_LOW_CONTRAST: \"Małe\"\n  STR_SMALL_HIGH_CONTRAST: \"Małe, wysoki kontrast\"\n  STR_BIG_LOW_CONTRAST: \"Duże\"\n  STR_BIG_HIGH_CONTRAST: \"Duże, wysoki kontrast\"\n  STR_TEST_CASE: \"Obiekt testu:\"\n  STR_RUN: \"Przeprowadź wybrany test!\"\n  STR_TESTS_STARTING: \"Start...\"\n  STR_TESTS_ERRORS_FOUND: \"Znaleziono błędów (mogą wystąpić duplikaty): {0}\"\n  STR_TESTS_NO_ERRORS_FOUND: \"Nie znaleziono błędów.\"\n  STR_TESTS_FINISHED: \"Koniec.\"\n  STR_DETAILED_INFO_IN_LOG_FILE: \"Szczegóły zostały zapisane w openxcom.log\"\n  STR_RANK_NONE: \"-\"\n  STR_DAMAGE_NONE: \"BRAK\"\n  STR_INFO_UFOPEDIA: \"INFO\"\n  STR_COCKPIT_CAPACITY: \"PILOCI>{ALT}{0}{ALT}\"\n  STR_MAXIMUM_RANGE: \"MAKS. ZAS.>{ALT}{0}{ALT}\"\n  STR_MINIMUM_RANGE: \"MIN. ZAS.>{ALT}{0}{ALT}\"\n  STR_INFINITE_RANGE: \"N/D\"\n  STR_TRACTOR_BEAM_POWER: \"Moc\"\n  STR_WEIGHT_PEDIA1: \"Waga: {0}\"\n  STR_WEIGHT_PEDIA2: \"Waga: {0}/{1}\"\n  STR_SHOT_TYPE_MELEE: \"Atak wręcz\"\n  STR_ACCURACY_MODIFIER: \"Modyfikator celności>{ALT} {0}\"\n  STR_POWER_BONUS: \"Premia do obrażeń>{ALT} {0}\"\n  STR_MULTIPLE_DIFFERENT_BONUSES: \"różne premie, zależnie od amunicji\"\n  STR_STATS_FOR_NERDS: \"Statystyki dla dociekliwych\"\n  STR_ARTICLE: \"Artykuł>{ALT} {0}\"\n  STR_COMPATIBLE_AMMO: \"Kompatybilna amunicja:\"\n  STR_BUILT_IN_ITEMS: \"Przedmioty wbudowane:\"\n  STR_CLIP_SIZE_UNLIMITED: \"nieograniczone\"\n  STR_SHOTGUN_BEHAVIOR_OXCE: \"rozszerzone\"\n  STR_INCLUDE_DEBUG: \"DEBUG\"\n  STR_INCLUDE_IDS: \"ID\"\n  STR_INCLUDE_DEFAULTS: \"DOMYŚLNE\"\n  STR_TRUE: \"prawda\"\n  STR_FALSE: \"fałsz\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH: \"ZDOLNOŚCI PSI*SIŁA PSI\"\n  STR_STRENGTH_AND_MELEE_ACCURACY: \"SIŁA*WALKA WRĘCZ\"\n  STR_STRENGTH_AND_THROWING_ACCURACY: \"SIŁA*RZUCANIE\"\n  STR_FIRING_ACCURACY_AND_REACTIONS: \"STRZELANIE*REFLEKS\"\n  STR_HEALTH_CURRENT: \"OBECNE ZDROWIE\"\n  STR_MANA_CURRENT: \"OBECNA MANA\"\n  STR_TIME_UNITS_CURRENT: \"OBECNE JEDNOSTKI CZASU\"\n  STR_STUN_LEVEL_CURRENT: \"OBECNY POZIOM OSZOŁOMIENIA\"\n  STR_HEALTH_NORMALIZED: \"ZNORMALIZOWANE ZDROWIE\"\n  STR_MANA_NORMALIZED: \"ZNORMALIZOWANA MANA\"\n  STR_TIME_UNITS_NORMALIZED: \"ZNORMALIZOWANE JEDNOSTKI CZASU \"\n  STR_ENERGY_NORMALIZED: \"ZNORMALIZOWANA ENERGIA\"\n  STR_MORALE_NORMALIZED: \"ZNORMALIZOWANE MORALE\"\n  STR_STUN_LEVEL_NORMALIZED: \"ZNORMALIZOWANY POZIOM OSZOŁOMIENIA\"\n  STR_ENERGY_REGENERATION: \"REGENERACJA ENERGII\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH_ABBREVIATION: \"UPS*SPS\"\n  STR_STRENGTH_AND_MELEE_ACCURACY_ABBREVIATION: \"SIŁ*WW\"\n  STR_STRENGTH_AND_THROWING_ACCURACY_ABBREVIATION: \"SIŁ*RZC\"\n  STR_FIRING_ACCURACY_AND_REACTIONS_ABBREVIATION: \"STR*REF\"\n  STR_HEALTH_CURRENT_ABBREVIATION: \"OBECNE ZDROWIE\"\n  STR_MANA_CURRENT_ABBREVIATION: \"OBECNA MANA\"\n  STR_TIME_UNITS_CURRENT_ABBREVIATION: \"OBECNE JEDNOSTKI CZASU\"\n  STR_STUN_LEVEL_CURRENT_ABBREVIATION: \"OBECNY POZIOM OSZOŁOMIENIA\"\n  STR_HEALTH_NORMALIZED_ABBREVIATION: \"ZNORMALIZOWANE ZDROWIE\"\n  STR_MANA_NORMALIZED_ABBREVIATION: \"ZNORMALIZOWANA MANA\"\n  STR_TIME_UNITS_NORMALIZED_ABBREVIATION: \"ZNORMALIZOWANE JEDNOSTKI CZASU \"\n  STR_ENERGY_NORMALIZED_ABBREVIATION: \"ZNORMALIZOWANA ENERGIA\"\n  STR_MORALE_NORMALIZED_ABBREVIATION: \"ZNORMALIZOWANE MORALE\"\n  STR_STUN_LEVEL_NORMALIZED_ABBREVIATION: \"ZNORMALIZOWANY POZIOM OSZOŁOMIENIA\"\n  STR_ENERGY_REGENERATION_ABBREVIATION: \"REGENERACJA ENERGII\"\n  STR_TIME_UNITS_SCALED: \"SKALOWANE JEDNOSTKI CZASU \"\n  STR_STAMINA_SCALED: \"SKALOWANA KONDYCJA\"\n  STR_HEALTH_SCALED: \"SKALOWANE ZDROWIE\"\n  STR_BRAVERY_SCALED: \"SKALOWANA ODWAGA\"\n  STR_REACTIONS_SCALED: \"SKALOWANY REFLEKS\"\n  STR_FIRING_ACCURACY_SCALED: \"SKALOWANE STRZELANIE\"\n  STR_THROWING_ACCURACY_SCALED: \"SKALOWANE RZUCANIE\"\n  STR_STRENGTH_SCALED: \"SKALOWANA SIŁA\"\n  STR_PSIONIC_STRENGTH_SCALED: \"SKALOWANA SIŁA PSI\"\n  STR_PSIONIC_SKILL_SCALED: \"SKALOWANE ZDOLNOŚCI PSI\"\n  STR_MELEE_ACCURACY_SCALED: \"SKALOWANA WALKA WRĘCZ\"\n  STR_MANA_POOL_SCALED: \"SKALOWANA PULA MANY\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH_SCALED: \"SKALOWANE ZDOLNOŚCI PSI*SIŁA PSI\"\n  STR_STRENGTH_AND_MELEE_ACCURACY_SCALED: \"SKALOWANA SIŁA*WALKA WRĘCZ\"\n  STR_STRENGTH_AND_THROWING_ACCURACY_SCALED: \"SKALOWANA SIŁA*RZUCANIE\"\n  STR_FIRING_ACCURACY_AND_REACTIONS_SCALED: \"SKALOWANE STRZELANIE*REFLEKS\"\n  STR_TIME_UNITS_SCALED_ABBREVIATION: \"SKALOWANE JC\"\n  STR_STAMINA_SCALED_ABBREVIATION: \"SKALOWANA KON\"\n  STR_HEALTH_SCALED_ABBREVIATION: \"SKALOWANE PŻ\"\n  STR_BRAVERY_SCALED_ABBREVIATION: \"SKALOWANA ODW\"\n  STR_REACTIONS_SCALED_ABBREVIATION: \"SKALOWANY REF\"\n  STR_FIRING_ACCURACY_SCALED_ABBREVIATION: \"SKALOWANE STR\"\n  STR_THROWING_ACCURACY_SCALED_ABBREVIATION: \"SKALOWANE RZC\"\n  STR_STRENGTH_SCALED_ABBREVIATION: \"SKALOWANA SIŁ\"\n  STR_PSIONIC_STRENGTH_SCALED_ABBREVIATION: \"SKALOWANA SPS\"\n  STR_PSIONIC_SKILL_SCALED_ABBREVIATION: \"SKALOWANE UPS\"\n  STR_MELEE_ACCURACY_SCALED_ABBREVIATION: \"SKALOWANA WW\"\n  STR_MANA_POOL_SCALED_ABBREVIATION: \"SKALOWANA MAN\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH_SCALED_ABBREVIATION: \"SKALOWANE UPS*SPS\"\n  STR_STRENGTH_AND_MELEE_ACCURACY_SCALED_ABBREVIATION: \"SKALOWANA SIŁ*WW\"\n  STR_STRENGTH_AND_THROWING_ACCURACY_SCALED_ABBREVIATION: \"SKALOWANA SIŁ*RZC\"\n  STR_FIRING_ACCURACY_AND_REACTIONS_SCALED_ABBREVIATION: \"SKALOWANE STR*REF\"\n  STR_COST_TIME: \"czas\"\n  STR_COST_ENERGY: \"energia\"\n  STR_COST_MORALE: \"morale\"\n  STR_COST_HEALTH: \"zdrowie\"\n  STR_COST_STUN: \"oszołomienie\"\n  STR_COST_MANA: \"mana\"\n  STR_COST_BUILD: \"budowa\"\n  STR_COST_REFUND: \"zwrot\"\n  STR_DAMAGE_10: \"10\"\n  STR_DAMAGE_11: \"11\"\n  STR_DAMAGE_12: \"12\"\n  STR_DAMAGE_13: \"13\"\n  STR_DAMAGE_14: \"14\"\n  STR_DAMAGE_15: \"15\"\n  STR_DAMAGE_16: \"16\"\n  STR_DAMAGE_17: \"17\"\n  STR_DAMAGE_18: \"18\"\n  STR_DAMAGE_19: \"19\"\n  STR_NAUTICAL_MILES: \"{0} mil morskich\"\n  STR_KILOMETERS_PER_HOUR: \"{0} km/h\"\n  STR_SECONDS_LONG: \"{0} sekund\"\n  STR_RACE_BONUS: \"Premia rasowa\"\n  STR_FOR_DIFFICULTY: \"dla trudności: {0}\"\n  STR_NOT_AWARDED_YET: \"Jeszcze nieprzyznane\"\n"
  },
  {
    "path": "bin/common/Language/OXCE/pt-BR.yml",
    "content": "pt-BR:\n  STR_CANNOT_DISMANTLE_FACILITY_UPGRADING: \"NÃO PODE DEMOLIR A INSTALAÇÃO!{SMALLLINE}A instalação não pode ser removida durante a atualização.\"\n  STR_CANNOT_UPGRADE_FACILITY_ALREADY_UPGRADING: \"NÃO PODE CONSTRUIR AQUI!{SMALLLINE}A instalação existente já está sendo construída.\"\n  STR_CANNOT_UPGRADE_FACILITY_WRONG_SIZE: \"NÃO PODE CONSTRUIR AQUI!{SMALLLINE}A instalação selecionada deve cobrir completamente as instalações existentes.\"\n  STR_CANNOT_UPGRADE_FACILITY_WRONG_TYPE: \"NÃO PODE CONSTRUIR AQUI!{SMALLLINE}A instalação existente não pode ser atualizada por instalações selecionadas.\"\n  STR_CANNOT_UPGRADE_FACILITY_DISALLOWED: \"NÃO PODE CONSTRUIR AQUI!{SMALLLINE}A instalação existente não pode ser construída.\"\n  STR_CANNOT_BUILD_QUEUE_OFF: \"NÃO PODE CONSTRUIR AQUI!{SMALLLINE}As instalações de conexão devem terminar a construção primeiro.\"\n  STR_FACILITY_FORBIDDEN_BY_OTHER: \"NÃO PODE CONSTRUIR AQUI!{SMALLLINE}Algumas instalações existentes proíbem a construção desta instalação.\"\n  STR_FACILITY_OTHER_FORBIDDEN_BY_THIS: \"NÃO PODE CONSTRUIR AQUI! {SMALLLINE} Algumas instalações existentes seriam bloqueadas por esta instalação.\"\n  STR_NOT_ENOUGH_ITEMS: \"NÃO HÁ MATERIAIS SUFICIENTES!{SMALLLINE}Precisamos de mais recursos para construir esta instalação.{NEWLINE}Faltando> {0}: {1}\"\n  STR_ID: \"ORDEM DE CONTRATADO\"\n  STR_FIRST_LETTER: \"PRIMEIRA LETRA\"\n  STR_SOLDIER_TYPE: \"TIPO DE SOLDADO\"\n  STR_IDLE_DAYS: \"DIAS OCIOSOS\"\n  STR_MANA: \"MANA\"\n  STR_MANA_POOL: \"RESERVA DE MANA\"\n  STR_MANA_MISSING: \"MANA FALTANDO\"\n  STR_LOAD_CRAFT_LOADOUT_TEMPLATE: \"Carregar Equipamento de Nave\"\n  STR_EMPTY_SLOT_N: \"Compartimento vazio {0}\"\n  STR_UNNAMED_SLOT_N: \"Compartimento sem nome {0}\"\n  STR_ADD_ON_TOP: \"Adicionar no topo\"\n  STR_SAVE_CRAFT_LOADOUT_TEMPLATE: \"Salvar Equipamento de Nave\"\n  STR_SAVE_UC: \"SALVAR\"\n  STR_ALL: \"Tudo\"\n  STR_EQUIPPED: \"Equipado\"\n  STR_NOT_EQUIPPED: \"Não equipado\"\n  STR_UNASSIGNED: \"Outros\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED_BY_SIZE: \"NÃO É PERMITIDO MAIS EQUIPAMENTO A BORDO!{SMALLLINE}Espaço máximo de armazenamento: {0}\"\n  STR_PILOTS: \"PILOTOS\"\n  STR_SHIELD: \"ESCUDO>{ALT}{0}\"\n  STR_CRAFT_SKIN_ID: \"[{0}]\"\n  STR_SELECT_PILOT: \"Selecionar Piloto\"\n  STR_PILOTS_FOR_CRAFT: \"Piloto(s) para {0}\"\n  STR_PILOTS_REQUIRED: \"Piloto(s) necessários: {ALT}{0}\"\n  STR_ADD_PILOT: \"Adicionar Piloto\"\n  STR_REMOVE_ALL_PILOTS: \"Remover Todos os Pilotos\"\n  STR_ACCURACY_BONUS: \"Bônus de precisão:\"\n  STR_DODGE_BONUS: \"Bônus de esquiva:\"\n  STR_APPROACH_SPEED: \"Velocidade de aproximação:\"\n  STR_COWARDLY: \"Covarde (-50%)\"\n  STR_NORMAL: \"Normal\"\n  STR_BOLD: \"Corajoso (+50%)\"\n  STR_VERY_BOLD: \"Muito corajoso (+100%)\"\n  STR_SOLDIER_GROUP_NOT_ALLOWED: \"Este tipo de soldado não é permitido a bordo.\"\n  STR_SOLDIER_GROUP_NOT_SAME: \"Este tipo de soldado não é compatível com outros soldados a bordo.\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW: \"Prévia\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_SAVED: \"Prévia *\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_BRIEFING: \"Este recurso permite pré-visualizar e personalizar a implantação das suas unidades no início de uma batalha. Você tem movimento ilimitado. Pressione e segure 'Alt' para destacar posições válidas de unidades. Clique no ícone 'Abortar Missão' para salvar uma implantação personalizada. Clique no ícone 'Terminar Turno' para sair da pré-visualização.{NEWLINE}Observe que adicionar novos soldados ou veículos à aeronave invalida automaticamente a implantação personalizada salva. A presença de uma implantação personalizada é indicada por um asterisco no botão 'Prévia'.\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_BRIEFING_DUMMY: \"Este recurso permite visualizar e modificar a tabela de implantação deste tipo de aeronave. Quaisquer alterações serão aplicadas a todas as suas aeronaves atuais e também a quaisquer aeronaves que você comprar ou fabricar mais tarde na campanha. Você começa com o número máximo de soldados. Cada soldado representa uma linha na tabela de implantação. Os nomes dos soldados correspondem aos números das linhas. Para fornecer espaço para uma unidade 2x2, coloque 4 soldados em um quadrado 2x2. Se o espaço não for fornecido, a unidade 2x2 estará ausente em uma batalha real.\"\n  STR_BASE_DEFENSE_BRIEFING_PREVIEW: \"Este recurso permite visualizar sua base.{NEWLINE}Divirta-se!{NEWLINE}{NEWLINE}Clique no ícone 'Terminar Turno' para sair da prévia.\"\n  STR_NOT_ENOUGH_CARGO_SPACE: \"NÃO HÁ ESPAÇO DE CARGA SUFICIENTE!{SMALLLINE}Use um módulo diferente ou reduza a tripulação atribuída.\"\n  STR_NOT_ENOUGH_STORAGE_SPACE_1: \"NÃO HÁ ESPAÇO SUFICIENTE DE ARMAZENAMENTO!{SMALLLINE}Itens demais! Use um módulo diferente ou reduza o equipamento atribuído.\"\n  STR_NOT_ENOUGH_STORAGE_SPACE_2: \"NÃO HÁ ESPAÇO SUFICIENTE DE ARMAZENAMENTO!{SMALLLINE}Os itens ocupam muito espaço! Use um módulo diferente ou reduza o tamanho do equipamento atribuído.\"\n  STR_REFUND_VALUE: \"Valor de venda> {ALT}{0}\"\n  STR_REFUND_VALUE_NEGATIVE: \"Despesas> {ALT}{0}\"\n  STR_PRODUCTION_OVERVIEW: \"VISÃO GERAL DA PRODUÇÃO\"\n  STR_RESEARCH_DIARY: \"DIÁRIO DE PESQUISA\"\n  STR_RESEARCH_OVERVIEW: \"VISÃO GERAL DA PESQUISA\"\n  STR_PRISONER_OVERVIEW: \"VISÃO GERAL DOS PRISIONEIROS\"\n  STR_PRISONER: \"PRISIONEIRO\"\n  STR_PRISONER_AMOUNT: \"QUANTIDADE\"\n  STR_PRISONER_INTERROGATED: \"INTERROGADO\"\n  STR_TOTAL_IN_PRISON: \"Espaço Usado>{ALT}{0}\"\n  STR_TOTAL_INTERROGATED: \"Interrogado>{ALT}{0}\"\n  STR_PRISON_TYPE: \"Contenção Alienígena\"\n  STR_KILL_SELECTED: \"Matar\"\n  STR_SELL_SELECTED: \"Vender\"\n  STR_GO_TO_TRANSFERS: \"Transferir...\"\n  STR_PRISON_CLEANUP: \"Limpeza da Prisão\"\n  STR_TOPIC: \"Tópico>{ALT} {0}\"\n  STR_SHOW_ALL: \"Mostrar tudo\"\n  STR_NO_DEPENDENCIES: \"Sem dependências.\"\n  STR_DIRECT_DEPENDENCIES: \"Dependências diretas\"\n  STR_LEVEL_2_DEPENDENCIES: \"Dependências de nível 2\"\n  STR_LEVEL_3_DEPENDENCIES: \"Dependências de nível 3\"\n  STR_LEVEL_4_DEPENDENCIES: \"Dependências de nível 4\"\n  STR_MORE_DEPENDENCIES: \"Existem dependências ainda mais profundas...\"\n  STR_END_OF_SEARCH: \"Fim da pesquisa.\"\n  STR_REFUND_PRODUCTION: \"REEMBOLSO!\"\n  STR_HOURS_PER_UNIT: \"HORAS POR UNIDADE>{ALT}{0}\"\n  STR_PERSON_JOINING: \"Pessoa Entrando\"\n  STR_RANDOM_PRODUCTION_DISCLAIMER: \"Produção aleatória!\"\n  STR_OTHER_EMPLOYEES: \"Outros Funcionários & Inventário\"\n  STR_SHOW_ONLY_NEW: \"Mostrar apenas novos\"\n  STR_FILTER_DEFAULT: \"Padrão\"\n  STR_FILTER_DEFAULT_SUPPLIES_OK: \"Padrão (suprimentos OK)\"\n  STR_FILTER_DEFAULT_NO_SUPPLIES: \"Padrão (sem suprimentos)\"\n  STR_FILTER_FACILITY_REQUIRED: \"Instalação Faltando\"\n  STR_FILTER_HIDDEN: \"Oculto\"\n  STR_FILTER_EQUIPPED: \"Equipado\"\n  STR_FILTER_MISSING: \"Faltando\"\n  STR_SORT_DEFAULT: \"Padrão\"\n  STR_SORT_BY_COST: \"Por custo\"\n  STR_SORT_BY_NAME: \"Por nome\"\n  STR_RANDOM_PRODUCTION_SUMMARY: \"Resumo\"\n  STR_NOT_ENOUGH_PRISON_SPACE: \"NÃO HÁ ESPAÇO SUFICIENTE NA CONTENÇÃO DE ALIENÍGENAS!{SMALLLINE}Construa uma nova contenção de alienígenas ou transfira alienígenas para outras bases.\"\n  STR_MONTHLY_ITEM_PURCHASE_LIMIT_EXCEEDED: \"LIMITE MENSAL DE COMPRA DE ITENS EXCEDIDO!{SMALLLINE}Mais itens estarão disponíveis no próximo mês.\"\n  STR_MONTHLY_CRAFT_PURCHASE_LIMIT_EXCEEDED: \"LIMITE MENSAL DE COMPRA DE NAVES EXCEDIDO!{SMALLLINE}Mais naves estarão disponíveis no próximo mês.\"\n  STR_MONTHLY_SOLDIER_HIRING_LIMIT_EXCEEDED: \"LIMITE MENSAL DE CONTRATAÇÃO DE SOLDADOS EXCEDIDO!{SMALLLINE}Mais recrutas estarão disponíveis no próximo mês.\"\n  STR_NOT_ENOUGH_CRAFT_SPACE: \"Não há espaço suficiente a bordo!\"\n  STR_SELECT_AVATAR_FOR: \"SELECIONAR AVATAR PARA{NEWLINE}{0}\"\n  STR_SOLDIER_BONUSES_FOR: \"BÔNUS PARA O SOLDADO{NEWLINE}{0}\"\n  STR_SUMMARY: \"Resumo\"\n  STR_MANA_RECOVERY: \"RECUPERAÇÃO DE MANA> {ALT}{0}\"\n  STR_HEALTH_RECOVERY: \"RECUPERAÇÃO DE SAÚDE> {ALT}{0}\"\n  STR_BONUSES_BUTTON: \"+\"\n  STR_PROMOTE_SOLDIER: \"PROMOVER/REBAIXAR{NEWLINE}{0} {1}\"\n  STR_RANK_HEADER: \"PATENTE\"\n  STR_OPENINGS_HEADER: \"ABERTURAS\"\n  STR_KILLER_AND_WEAPON: \"{0}, {1}\"\n  STR_TRAINING: \"Treinamento\"\n  STR_SOLDIER_INFO: \"Informações do Soldado\"\n  STR_SELECT_TRANSFORMATION_FOR: \"SELECIONAR TRANSFORMAÇÃO PARA{NEWLINE}{0}\"\n  STR_TRANSFORMATIONS_BUTTON: \"^\"\n  STR_TRANSFER_TIME: \"Tempo de Transferência>{ALT}{0}\"\n  STR_RECOVERY_TIME: \"Tempo de Recuperação>{ALT}{0}\"\n  STR_CURRENT_STATS: \"Estatísticas atuais\"\n  STR_CHANGES: \"Mudanças\"\n  STR_CHANGES_MIN: \"Mudanças (mín)\"\n  STR_CHANGES_MAX: \"Mudanças (máx)\"\n  STR_BONUS_STATS: \"Estatísticas de bônus\"\n  STR_TRANSFORMATIONS_OVERVIEW: \"Visão Geral das Transformações\"\n  STR_PROJECT_NAME: \"NOME DO PROJETO\"\n  STR_AVAILABLE_MATERIALS: \"MATERIAIS DISPONÍVEIS\"\n  STR_ELIGIBLE_SOLDIERS: \"SOLDADOS ELEGÍVEIS\"\n  STR_SHOW_ONLY_ELIGIBLE: \"Mostrar Apenas Elegíveis\"\n  STR_ALL_SOLDIER_TYPES: \"Todos os Tipos de Soldados\"\n  STR_ALL_SOLDIERS: \"Todos os Soldados\"\n  STR_HEALTHY_SOLDIERS: \"Soldados Saudáveis\"\n  STR_WOUNDED_SOLDIERS: \"Soldados Feridos\"\n  STR_DEAD_SOLDIERS: \"Soldados Mortos\"\n  STR_GRAND_TOTAL: \"Total Geral\"\n  STR_AVAILABLE_TOPICS: \"TÓPICOS DISPONÍVEIS\"\n  STR_QS_THREE_LETTERS_A: \"Por favor, insira pelo menos 3 letras\"\n  STR_QS_THREE_LETTERS_B: \"na caixa de Pesquisa Rápida...\"\n  STR_M_FLAG: \" [m]\"\n  STR_F_FLAG: \" [f]\"\n  STR_I_FLAG: \" [i]\"\n  STR_C_FLAG: \" [c]\"\n  STR_THIS_FEATURE_IS_DISABLED_1: \"Este recurso está desativado\"\n  STR_THIS_FEATURE_IS_DISABLED_2: \"Este recurso está desativado\"\n  STR_THIS_FEATURE_IS_DISABLED_3: \"Este recurso está desativado\"\n  STR_THIS_FEATURE_IS_DISABLED_4: \"Este recurso está desativado\"\n  STR_THIS_FEATURE_IS_DISABLED_5: \"Este recurso está desativado\"\n  STR_TECH_TREE_VIEWER: \"Visualizador da Árvore Tecnológica\"\n  STR_SELECT_TOPIC: \"Selecionar Tópico\"\n  STR_RESEARCH_PROGRESS: \"Progresso>{ALT} {0}%\"\n  STR_ITEM_DESTROYED: \"Item destruído:\"\n  STR_ITEM_REQUIRED: \"Item requerido:\"\n  STR_SERVICES_REQUIRED: \"Serviços requeridos:\"\n  STR_SERVICES_PROVIDED: \"Serviços prestados:\"\n  STR_SERVICES_FORBIDDEN: \"Serviços proibidos:\"\n  STR_REQUIRES: \"Requer:\"\n  STR_DEPENDS_ON: \"Depende de:\"\n  STR_UNLOCKED_BY: \"Desbloqueado por:\"\n  STR_DISABLED_BY: \"Desativado por:\"\n  STR_REENABLED_BY: \"Reativado por:\"\n  STR_GET_FOR_FREE_FROM: \"Obtenha gratuitamente a partir de:\"\n  STR_IS_LOOKUP_OF: \"É a busca por:\"\n  STR_LOOKUP: \"Busca:\"\n  STR_SPAWNED_ITEMS: \"Itens gerados:\"\n  STR_SPAWNED_EVENT: \"Evento gerado:\"\n  STR_REQUIRED_BY: \"Necessário por:\"\n  STR_REQUIRED_BY_TRANSFORMATIONS: \"Necessário por transformações:\"\n  STR_LEADS_TO: \"Leva a:\"\n  STR_UNLOCKS: \"Desbloqueia:\"\n  STR_DISABLES: \"Desativa:\"\n  STR_REENABLES: \"Reativa:\"\n  STR_GIVES_ONE_FOR_FREE_SEQ: \"Fornece um de graça (sequencial):\"\n  STR_GIVES_ONE_FOR_FREE: \"Fornece um de graça:\"\n  STR_RESEARCH_REQUIRED: \"Pesquisa necessária:\"\n  STR_RESEARCH_REQUIRED_USE: \"Pesquisa necessária (usar):\"\n  STR_RESEARCH_REQUIRED_BUY: \"Pesquisa necessária (comprar):\"\n  STR_SERVICES_REQUIRED_BUY: \"Serviços necessários (comprar):\"\n  STR_PRODUCED_BY: \"Produzido por:\"\n  STR_SPAWNED_BY: \"Gerado por:\"\n  STR_MATERIALS_REQUIRED: \"Materiais requisitados:\"\n  STR_TTV_COST_PER_UNIT: \"Custo por unidade:\"\n  STR_TTV_ENGINEER_HOURS: \"Horas do engenheiro:\"\n  STR_TTV_WORK_SPACE_REQUIRED: \"Espaço de trabalho necessário:\"\n  STR_ITEMS_PRODUCED: \"Itens produzidos:\"\n  STR_PERSON_RECRUITED: \"Pessoa recrutada:\"\n  STR_UNLOCKS_ARCS: \"Desbloqueia arcos:\"\n  STR_DISABLES_ARCS: \"Desativa arcos:\"\n  STR_UNLOCKS_MISSIONS: \"Desbloqueia missões:\"\n  STR_DISABLES_MISSIONS: \"Desabilita missões:\"\n  STR_UNLOCKS_EVENTS: \"Desbloqueia eventos:\"\n  STR_DISABLES_EVENTS: \"Desabilita eventos:\"\n  STR_AFFECTS_GAME_PROGRESSION: \"Afeta a progressão do jogo!\"\n  STR_ITEMS_AT_DESTINATION: \"Itens em destino\"\n  STR_PRISONERS: \"Prisioneiros\"\n  STR_ARMORS: \"Armaduras\"\n  STR_CRAFT_DEPLOYMENT_QUESTION: \"Salvar Implantação da Nave?\"\n  STR_MUST_USE_BOTH_HANDS: \"Ambas as mãos são necessárias para isso!\"\n  STR_NOT_ENOUGH_MORALE: \"Moral Insuficiente!\"\n  STR_NOT_ENOUGH_HEALTH: \"Saúde Insuficiente!\"\n  STR_NOT_ENOUGH_MANA: \"Mana Insuficiente!\"\n  STR_NOT_ENOUGH_STUN: \"Nível de atordoamento é muito alto!\"\n  STR_MIND_CONTROL_SUCCESSFUL_ALT: \"Ação Bem Sucedida\"\n  STR_LINE_OF_SIGHT_REQUIRED: \"Linha de visão (LoS) necessária.\"\n  STR_CENTER_ON_WOUNDED_FRIEND: \"Centralizar no Amigo Ferido\"\n  STR_CENTER_ON_DIZZY_FRIEND: \"Centralizar no Amigo Tonto\"\n  STR_BUG_HUNT_ACTIVATED: \"Modo Caça ao Inseto ativado: inimigos são visíveis no minimapa!\"\n  STR_TARGET_ENEMY: \"; Alvo = INIMIGO\"\n  STR_TARGET_NEUTRAL: \"; Alvo = NEUTRO\"\n  STR_TARGET_FRIEND: \"; Alvo = AMIGO\"\n  STR_TARGET_YOURSELF: \"; Alvo = VOCÊ MESMO\"\n  STR_TARGET_ON_THE_GROUND: \" (no chão)\"\n  STR_USE_SPECIAL_ITEM: \"Usar Item Especial\"\n  STR_NO_EXPERIENCE_YET: \"Ainda sem experiência:\"\n  STR_OPERATION_UC: \"OPERAÇÃO> {0}\"\n  STR_WHAT_CAN_I_WEAR: \"O que eu posso vestir?\"\n  STR_STARTING_CONDITION_ARMORS_FORBIDDEN: \"Esta missão requer equipamento específico.{NEWLINE}{NEWLINE}Tipos de armaduras proibidos são: {0}\"\n  STR_STARTING_CONDITION_ARMORS_ALLOWED: \"Esta missão requer equipamento específico.{NEWLINE}{NEWLINE}Tipos de armadura permitidos são: {0}\"\n  STR_MISSION_OVER: \"Missão completa.\"\n  STR_UNITS_WITH_FATAL_WOUNDS:\n    one: \"{N} de nós ainda está fatalmente ferido\"\n    many: \"{N} de nós ainda estão fatalmente feridos\"\n    other: \"{N} de nós ainda estão fatalmente feridos\"\n  STR_END_MISSION_QUESTION: \"Terminar Missão?\"\n  STR_LOOT: \"SAQUE\"\n  STR_SELL: \"VENDER\"\n  STR_LIVE_ALIENS_SURRENDERED: \"INIMIGOS RENDERAM-SE\"\n  STR_MISSION_ABORTED: \"MISSÃO ABORTADA\"\n  STR_VIPS_SAVED: \"VIPs SALVOS\"\n  STR_VIPS_LOST: \"VIPs PERDIDOS\"\n  STR_BOUNTY: \"RECOMPENSA\"\n  STR_MANA_ABBREVIATION: \"MAN\"\n  STR_CANNOT_PLACE_ITEM_INTO_THIS_SECTION: \"Não é permitido colocar esse item lá.{NEWLINE}Não pergunte por quê!\"\n  STR_ONE_HAND_MUST_BE_EMPTY: \"Pelo menos uma das mãos deve estar vazia!\"\n  STR_LOAD_EQUIPMENT_TEMPLATE: \"Carregar Modelo de Equipamento\"\n  STR_SAVE_EQUIPMENT_TEMPLATE: \"Salvar Modelo de Equipamento\"\n  STR_FIRING_SHORT: \"Disp.>{ALT}{0}\"\n  STR_THROWING_SHORT: \"Lançar>{ALT}{0}\"\n  STR_MELEE_SHORT: \"Corp.>{ALT}{0}\"\n  STR_PERSONAL_EQUIPMENT: \"EQUIPAMENTO PESSOAL\"\n  STR_SAVE_PERSONAL_EQUIPMENT: \"Salvar Equipamento Pessoal\"\n  STR_LOAD_PERSONAL_EQUIPMENT: \"Carregar Equipamento Pessoal\"\n  STR_PERSONAL_EQUIPMENT_SAVED: \"Equipamento pessoal salvo.\"\n  STR_SLOT: \"Slot>{ALT}{0}\"\n  STR_THINKING: \"Pensando...\"\n  STR_TELL_ME_MORE: \"Conte-me mais...\"\n  STR_REINFORCEMENTS_ALERT: \"Alerta de Reforços!\"\n  STR_HIT_LOG_NEW_TURN: \"Novo Turno\"\n  STR_FAILED_CQB_CHECK: \"O inimigo conseguiu interromper seu ataque!\"\n  STR_NO_TRAJECTORY: \"Nenhuma trajetória viável!\"\n  STR_HIT_LOG_NEW_BULLET: \"=>\"\n  STR_MANA_SHORT: \"MA>{ALT}{0}\"\n  STR_SKILL_NEEDS_ITEM: \"Esta habilidade precisa de um item!\"\n  STR_HIT_LOG_NO_DAMAGE: \"0\"\n  STR_HIT_LOG_SMALL_DAMAGE: \"dano\"\n  STR_HIT_LOG_BIG_DAMAGE: \"DANO\"\n  STR_HIT_LOG_REACTION_FIRE: \"Fogo de reação...\"\n  STR_HIT_LOG: \"Registro de Atingidos\"\n  STR_BUTTON_10: \"10\"\n  STR_LAZY_LOADING: \"Carregamento Preguiçoso\"\n  STR_LAZY_LOADING_DESC: \"Se habilitado, os recursos gráficos são carregados sob demanda. Caso contrário, tudo é carregado na inicialização.\"\n  STR_VSYNC_FOR_OPENGL: \"VSync para OpenGL\"\n  STR_VSYNC_FOR_OPENGL_DESC: \"Desative para máxima velocidade de movimento oculto do inimigo e (opcionalmente) de movimento do soldado. NÃO ajuste o limite de FPS para 0. Aplica-se apenas à renderização OpenGL.\"\n  STR_UPDATE_CHECK: \"Verificação automática de atualização\"\n  STR_UPDATE_CHECK_DESC: \"Se ativado, OpenXcom irá automaticamente checar por atualizações e dar a você a opção de atualizar com um único clique.\"\n  STR_AUTOSAVE_SLOTS: \"Compartimentos de salvamento automático\"\n  STR_AUTOSAVE_SLOTS_DESC: \"Número de compartimentos para salvamentos automáticos na Tela de Combate.\"\n  STR_AUTO_SAVE_BATTLESCAPE_SLOT_WITH_NUMBER: \"<AUTO BATTLESCAPE> {0}\"\n  STR_GEO_AUTOSAVE_FREQUENCY: \"Frequência de Salvamento Automático (Geoscape)\"\n  STR_GEO_AUTOSAVE_FREQUENCY_DESC: \"Quantidade de dias após os quais o jogo será salvo automaticamente.\"\n  STR_GEO_AUTOSAVE_SLOTS: \"Slot de Salvamento Automático (Geoscape)\"\n  STR_GEO_AUTOSAVE_SLOTS_DESC: \"Número de slots para salvamentos automáticos do Geoscape.\"\n  STR_AUTO_SAVE_GEOSCAPE_SLOT_WITH_NUMBER: \"<AUTO GEOSCAPE> {0}\"\n  STR_OXCE_LINKS: \"Links estendidos\"\n  STR_OXCE_LINKS_DESC: \"Habilita menus/botões/links adicionais para recursos OXCE.\"\n  STR_PEDIA_SHOW_CLIP_SIZE: \"Mostrar tamanho do clipe na Ufopédia\"\n  STR_PEDIA_SHOW_CLIP_SIZE_DESC: \"Se habilitado, os tamanhos dos clipes de munição serão exibidos ao lado dos ícones de munição na Ufopédia.\"\n  STR_INTERCEPT_TABLE_SIZE: \"Tamanho da tabela de interceptação\"\n  STR_INTERCEPT_TABLE_SIZE_DESC: \"Tamanho das tabelas nas seguintes janelas de diálogo: Interceptar, Rastreador de OVNIs.\"\n  STR_SHOW_SLACKING_INDICATOR: \"Mostrar indicador de ociosidade\"\n  STR_SHOW_SLACKING_INDICATOR_DESC: \"Se habilitado, o número de cientistas e engenheiros não atribuídos será exibido.\"\n  STR_SHOW_MAINTENANCE_TIME: \"Mostrar tempo de manutenção da nave\"\n  STR_SHOW_MAINTENANCE_TIME_DESC: \"{ALT}0>{ALT} Não mostrar {ALT}1>{ALT} Mostrar apenas a duração da atividade atual {ALT}2>{ALT} Mostrar tudo junto (reparo + rearmar + reabastecer).\"\n  STR_SHOW_ETA: \"Mostrar duração de Tempo Estimado de Voo\"\n  STR_SHOW_ETA_DESC: \"{ALT}0>{ALT} Não mostrar {ALT}1>{ALT} Mostrar TEV apenas para alvos estáticos {ALT}2>{ALT} Mostrar TEV também para alvos em movimento.\"\n  STR_UFO_LANDING_ALERT: \"Alerta de pouso de OVNI\"\n  STR_UFO_LANDING_ALERT_DESC: \"Se habilitado, uma mensagem aparecerá cada vez que um OVNI detectado pousar.\"\n  STR_REMEMBER_DISABLED_CRAFT_WEAPONS: \"Lembrar armas de nave desativadas\"\n  STR_REMEMBER_DISABLED_CRAFT_WEAPONS_DESC: \"Armas da nave desativadas durante um combate aéreo permanecerão desativadas. Elas também não serão rearmadas na base.\"\n  STR_GEO_EVENT_INSTANT_DELIVERY: \"Entrega instantânea de itens em eventos\"\n  STR_GEO_EVENT_INSTANT_DELIVERY_DESC: \"Se habilitado, os itens dos eventos da tela global chegam instantaneamente. Caso contrário, chegam 1 hora depois.\"\n  STR_SHOW_BASE_NAME_IN_POPUPS: \"Mostrar nome da base em janelas emergentes\"\n  STR_SHOW_BASE_NAME_IN_POPUPS_DESC: \"Se habilitado, o nome da base correspondente será exibido em janelas emergentes (por exemplo, Pesquisa Concluída).\"\n  STR_ALTERNATE_CRAFT_EQUIPMENT_MANAGEMENT: \"Gestão alternativa de equipamento de nave\"\n  STR_ALTERNATE_CRAFT_EQUIPMENT_MANAGEMENT_DESC: \"Se habilitado, mover soldados entre uma base e uma nave também moverá seu equipamento (se possível).\"\n  STR_BASE_INFO_SCALE: \"Dimensionar barras grandes nas informações da base\"\n  STR_BASE_INFO_SCALE_DESC: \"Se habilitado, barras maiores que 140 são reduzidas para caber na interface.\"\n  STR_HIGHLIGHT_NEW: \"Destacar novos tópicos\"\n  STR_HIGHLIGHT_NEW_DESC: \"Se habilitado, novos tópicos de pesquisa, novos tópicos de manufatura e novos artigos da Ufopédia são mostrados em cores diferentes.\"\n  STR_RESEARCH_SCROLL_SPEED: \"Velocidade de rolagem da pesquisa\"\n  STR_RESEARCH_SCROLL_SPEED_DESC: \"Cientistas podem ser (des)atribuídos diretamente na interface de Pesquisa Atual usando o botão de rolagem do mouse.\"\n  STR_RESEARCH_SCROLL_SPEED_CTRL: \"Velocidade de rolagem da pesquisa (com Ctrl)\"\n  STR_RESEARCH_SCROLL_SPEED_CTRL_DESC: \"Cientistas podem ser (des)atribuídos diretamente na interface de Pesquisa Atual usando o botão de rolagem do mouse.\"\n  STR_MANUFACTURE_FILTER_SUPPLIES_OK: \"Filtro alternativo na Manufatura\"\n  STR_MANUFACTURE_FILTER_SUPPLIES_OK_DESC: \"Se habilitado, a interface mostra apenas itens de produção para os quais há suprimentos suficientes.\"\n  STR_MANUFACTURE_SCROLL_SPEED: \"Velocidade de rolagem da manufatura\"\n  STR_MANUFACTURE_SCROLL_SPEED_DESC: \"Engenheiros podem ser (des)atribuídos diretamente na interface de Produção Atual usando o botão de rolagem do mouse.\"\n  STR_MANUFACTURE_SCROLL_SPEED_CTRL: \"Velocidade de rolagem da manufatura (com Ctrl)\"\n  STR_MANUFACTURE_SCROLL_SPEED_CTRL_DESC: \"Engenheiros podem ser (des)atribuídos diretamente na interface de Produção Atual usando o botão de rolagem do mouse.\"\n  STR_PERSONAL_LAYOUT_INCLUDING_ARMOR: \"Incluir armadura no equipamento pessoal\"\n  STR_PERSONAL_LAYOUT_INCLUDING_ARMOR_DESC: \"Se habilitado, a disposição do equipamento pessoal do soldado é salva incluindo a armadura usada.\"\n  STR_MANUALPROMOTIONS: \"Promoções manuais\"\n  STR_MANUALPROMOTIONS_DESC: \"Se habilitado, os soldados podem ser promovidos (ou rebaixados) manualmente clicando no ícone de patente.\"\n  STR_WOUNDED_DEFEND_BASE_IF: \"Feridos defendem (se PV acima de x%)\"\n  STR_WOUNDED_DEFEND_BASE_IF_DESC: \"Os soldados feridos defendem a base também, se seus pontos de vida exceder o limite percentual determinado.\"\n  STR_PLAY_BRIEFING_MUSIC_DURING_EQUIPMENT: \"Tocar música do menu de Instruções por mais tempo\"\n  STR_PLAY_BRIEFING_MUSIC_DURING_EQUIPMENT_DESC: \"A música do menu de Instruções continuará tocando durante a fase de equipamento até o Tela de Combate ser exibida.\"\n  STR_NIGHT_VISION_COLOR: \"Selecionar cor da Visão Noturna\"\n  STR_NIGHT_VISION_COLOR_DESC: \"Valores de 1 a 15, cada um representando uma cor diferente.\"\n  STR_AUTO_NIGHT_VISION_THRESHOLD: \"Limite automático de Visão Noturna\"\n  STR_AUTO_NIGHT_VISION_THRESHOLD_DESC: \"Se mais escuro que este limite, a Visão Noturna será ativada automaticamente.\"\n  STR_SHOW_ACCURACY_ON_CROSSHAIR: \"Mostrar precisão na mira\"\n  STR_SHOW_ACCURACY_ON_CROSSHAIR_DESC: \"{ALT}0>{ALT}Nunca {ALT}1>{ALT}Somente se a precisão do Extensor de OVNI estiver habilitada {ALT}2>{ALT}Sempre\"\n  STR_AUTO_SELL: \"Gerenciador de Venda Automática\"\n  STR_AUTO_SELL_DESC: \"Na tela de venda de itens pós-batalha, qualquer tipo de item que você vendeu em batalhas anteriores será automaticamente marcado para venda.\"\n  STR_AUTOMATICPROMOTIONS: \"Promoções automáticas\"\n  STR_AUTOMATICPROMOTIONS_DESC: \"Se habilitado, os soldados são promovidos automaticamente após uma missão.\"\n  STR_OFF_CENTRE_SHOOTING: \"Tiro fora do centro\"\n  STR_OFF_CENTRE_SHOOTING_DESC: \"Os soldados tentarão ajustar automaticamente o ângulo de tiro ligeiramente caso não haja linha de fogo.\"\n  STR_GRAPHS_ZOOM_IN: \"Aproximar (Gráficos)\"\n  STR_GRAPHS_ZOOM_OUT: \"Afastar (Gráficos)\"\n  STR_MARK_ALL_AS_SEEN: \"Marcar Tudo Como Visto\"\n  STR_SELL_ALL: \"Vender Tudo\"\n  STR_SELL_ALL_BUT_ONE: \"Vender Tudo Menos Um\"\n  STR_TRANSFER_ALL: \"Transferir Tudo\"\n  STR_REMOVE_SOLDIERS_FROM_ALL_CRAFTS: \"Remover Soldados De Todas As Aeronaves\"\n  STR_REMOVE_SOLDIERS_FROM_CRAFT: \"Remover Soldados Da Aeronave\"\n  STR_REMOVE_EQUIPMENT_FROM_CRAFT: \"Remover Equipamentos Da Aeronave\"\n  STR_REMOVE_ARMOR_FROM_ALL_CRAFTS: \"Remover Armaduras De Todas As Aeronaves\"\n  STR_REMOVE_ARMOR_FROM_CRAFT: \"Remover Armadura Da Aeronave\"\n  STR_REMOVE_SOLDIERS_FROM_TRAINING: \"Remover Soldados Do Treinamento\"\n  STR_ADD_SOLDIERS_TO_TRAINING: \"Adicionar Soldados ao Treinamento\"\n  STR_INVENTORY_ARMOR: \"Mudar Armadura\"\n  STR_INVENTORY_AVATAR: \"Mudar Avatar\"\n  STR_ACTION_ITEM_1: \"Ação do Item 1 (Preciso/Usar)\"\n  STR_ACTION_ITEM_2: \"Ação do Item 2 (Simples)\"\n  STR_ACTION_ITEM_3: \"Ação do Item 3 (Rajada)\"\n  STR_ACTION_ITEM_4: \"Ação do Item 4 (Corpo a Corpo)\"\n  STR_ACTION_ITEM_5: \"Ação do Item 5 (Arremessar)\"\n  STR_TOGGLE_QUICK_SEARCH: \"Alternar Entre o Campo de Pesquisa Rápida\"\n  STR_TOGGLE_NIGHT_VISION: \"Alternar Visão Noturna\"\n  STR_HOLD_NIGHT_VISION: \"Visão Noturna Curta\"\n  STR_SELECT_MUSIC_TRACK: \"Selecionar Faixa de Música\"\n  STR_TOGGLE_TOUCH_BUTTONS: \"Alternar Botões de Toque\"\n  STR_TOGGLE_BRIGHTNESS: \"Alternar Brilho (visual apenas)\"\n  STR_BRIEFING: \"Instruções\"\n  STR_TOGGLE_DEBUG_MODE: \"Alternar Modo de Depuração\"\n  STR_DEBUG_KILL_ALL_ALIENS: \"DEPURAÇÃO: Matar Todos os Alienígenas\"\n  STR_PHYSICAL_TRAINING: \"Treinamento Marcial\"\n  STR_REMAINING_TRAINING_FACILITY_CAPACITY: \"CAPACIDADE DE TREINAMENTO RESTANTE> {ALT}{0}\"\n  STR_NO_WOUNDED: \"-\"\n  STR_NO_QUEUED: \"+\"\n  STR_NO_DONE: \"FEITO\"\n  STR_NO_AMMO: \"SEM MUNIÇÃO\"\n  STR_START_FIRING: \"Atirar!\"\n  STR_SKIP_FIRING: \"Deixe-os entrar...\"\n  STR_ALIEN_MISSILES_HAVE_DAMAGED_OUR_BASE: \"Mísseis alienígenas danificaram nossa base {0}\"\n  STR_ALIEN_MISSILES_HAVE_DESTROYED_OUR_BASE: \"Mísseis alienígenas destruíram nossa base {0}\"\n  STR_STARTING_CONDITION_COMMANDER: \"Esta missão requer a presença do comandante.\"\n  STR_STARTING_CONDITION_CRAFT: \"Esta aeronave é inapropriada para esta missão.\"\n  STR_STARTING_CONDITION_CRAFT_ALLOWED: \"Esta aeronave é inapropriada para esta missão.\\n{NEWLINE}{NEWLINE}Aeronaves permitidas: {0}\"\n  STR_STARTING_CONDITION_CRAFT_FORBIDDEN: \"Esta aeronave é inapropriada para esta missão.\\n{NEWLINE}{NEWLINE}Aeronaves proibidas: {0}\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE: \"Alguns soldados não podem participar desta missão.\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE_ALLOWED: \"Alguns soldados não podem participar desta missão.{NEWLINE}{NEWLINE}Tipos permitidos de soldados: {0}\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE_FORBIDDEN: \"Alguns soldados não podem participar desta missão.{NEWLINE}{NEWLINE}Tipos proibidos de soldados: {0}\"\n  STR_STARTING_CONDITION_ITEM: \"Esta missão requer item(s) específico:{NEWLINE}{NEWLINE}{0}\"\n  STR_NOT_ENOUGH_FUEL_TO_REACH_TARGET: \"COMBUSTÍVEL INSUFICIENTE!{SMALLLINE}O destino está muito distante para o alcance da nave.\"\n  STR_FOLLOW_WING_LEADER_QUESTION: \"Seguir líder de ala?\"\n  STR_ASSIGN_PILOTS: \"Atribuir pilotos...\"\n  STR_NOT_ENOUGH_PILOTS: \"Pilotos insuficientes!{NEWLINE}Mínimo: {0}\"\n  STR_DAILY_PILOT_EXPERIENCE: \"Experiência Diária do Piloto\"\n  STR_UFO_SHIELD_HIT: \"ACERTE OS ESCUDOS!\"\n  STR_UFO_HIT_NO_DAMAGE: \"SALTOU DO CASCO!\"\n  STR_UFO_SHIELD_DOWN: \"ESCUDOS INIMIGO CAEM!\"\n  STR_UFO_HIT_GLANCING: \"ATINGIDO DE RASPÃO!\"\n  STR_INTERCEPTOR_SHIELD_HIT: \"NOSSOS ESCUDOS ESTÃO AGUENTANDO!\"\n  STR_TRACTOR_BEAM_ENGAGED: \"RAIO TRATOR ATIVADO!\"\n  STR_TRACTOR_BEAM_DISENGAGED: \"DESATIVANDO RAIO TRATOR\"\n  STR_SELF_DESTRUCT_ACTIVATED: \"AUTO-DESTRUIÇÃO ATIVADA!\"\n  STR_SELF_DESTRUCT_CANCELLED: \"AUTO-DESTRUIÇÃO CANCELADA\"\n  STR_EXTENDED_LINKS: \"Links\"\n  STR_AUTO_PATROL: \"AUTO-PATRULHA\"\n  STR_ETA: \"TEV>{ALT}{0}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_FACILITY_AT_BASE: \"Não há {0} suficiente para rearmar {1} em {2}\"\n  STR_UFO_STARTED_HUNTING: \"{0} está em um curso de interceptação com {1}\"\n  STR_CRAFT_IS_READY: \"{0} em {1} está pronto.\"\n  STR_ECONOMY_WARNING: \"Os fundos {0} e renda {1} são baixos e a manutenção {2} muito alta! Venda algo para evitar receber um crédito... fundos que faltam: {3}\"\n  STR_SLACKING_INDICATOR: \"{0}:{1}\"\n  STR_TRAINING_INDICATOR: \"{0}:{1}\"\n  STR_EXTENDED_UC: \"ESTENDIDO\"\n  STR_RETURNING: \"RETORNANDO\"\n  STR_INTERCEPTING: \"INTERCEPTANDO\"\n  STR_ESCORTING: \"ESCOLTANDO\"\n  STR_EN_ROUTE: \"A CAMINHO\"\n  STR_PILOT_MISSING: \"PILOTO DESAPARECIDO\"\n  STR_DAY_SHORT: \"{0}d\"\n  STR_HOUR_SHORT: \"{0}h\"\n  STR_PERFORMANCE_BONUS: \"Bônus de Desempenho\"\n  STR_COUNTRY_HAS_CANCELLED_A_SECRET_PACT: \"{0} renunciou ao pacto com forças alienígenas e foi autorizado a retornar ao projeto.\"\n  STR_COUNTRIES_HAVE_CANCELLED_A_SECRET_PACT: \"{0} renunciaram ao pacto com forças alienígenas e foram autorizados a retornar ao projeto.\"\n  STR_WE_CAN_NOW_RENT: \"Agora podemos alugar\"\n  STR_REQUIRED_BASE_SERVICES: \"Serviços requiridos na base: {0}\"\n  STR_WE_CAN_NOW_BUILD: \"Agora podemos construir\"\n  STR_WE_CAN_NOW_PURCHASE: \"Agora podemos comprar\"\n  STR_NOT_ENOUGH_LIVING_SPACE_AT_BASE: \"Espaço insuficiente para acomodar{NEWLINE}{0}{NEWLINE}em{NEWLINE}{1}\"\n  STR_INFO: \"INFORMAÇÃO\"\n  STR_DESPAWN_PENALTY: \"Penalidade por desaparecer> {0}\"\n  STR_TRAINING_FINISHED: \"Treinamento Concluído{NEWLINE}em {0}\"\n  STR_PSI_TRAINING_FINISHED: \"Treinamento Psiônico Concluído{NEWLINE}em {0}\"\n  STR_IGNORE_UC: \"IGNORAR\"\n  STR_UFO_TRACKER: \"Rastreador OVNI\"\n  STR_UPDATE: \"Atualizar\"\n  STR_LATEST_VERSION_INFO: \"Você está usando a última versão de OpenXcom.\"\n  STR_MASTER_MOD_VERSION_REQUIRED_QUESTION: \"Este mod requer o jogo base v{0} para funcionar corretamente. Ativar este mod?\"\n  STR_VERSION_REQUIRED_QUESTION: \"Este mod requer OXCE v{0} para ser executado corretamente. Ativar este mod?\"\n  STR_GLOBE_TEXTURE: \"Textura do Globo\"\n  STR_NOTES: \"Notas\"\n  STR_NEW_NOTE: \"<NEW NOTE>\"\n  STR_ENGINE_OXC: \"OXC\"\n  STR_ENGINE_OXCE: \"OXCE\"\n  STR_ENGINE_OTHER: \"OUTRO\"\n  STR_BASESCAPE: \"Tela da Base\"\n  STR_AI: \"IA\"\n  STR_PATH_ENERGY_COST: \"Energia\"\n  STR_PATH_ENERGY_COST_DESC: \"Clicar mostra a energia que sua unidade terá restante após se mover para o destino.\"\n  STR_TEST_SCREEN: \"TELA DE TESTE\"\n  STR_PALETTE: \"Paleta:\"\n  STR_PREVIEW: \"Prévia\"\n  STR_TINY_BORDERLESS: \"Minúsculo, sem bordas\"\n  STR_TINY_BORDER: \"Minúsculo\"\n  STR_SMALL_LOW_CONTRAST: \"Pequeno\"\n  STR_SMALL_HIGH_CONTRAST: \"Pequeno, alto contraste\"\n  STR_BIG_LOW_CONTRAST: \"Grande\"\n  STR_BIG_HIGH_CONTRAST: \"Grande, alto contraste\"\n  STR_TEST_CASE: \"Caso de teste:\"\n  STR_RUN: \"Executar teste selecionado!\"\n  STR_TESTS_STARTING: \"Iniciando...\"\n  STR_TESTS_ERRORS_FOUND: \"Total de erros encontrados (pode haver duplicatas): {0}\"\n  STR_TESTS_NO_ERRORS_FOUND: \"Nenhum erro encontrado.\"\n  STR_TESTS_FINISHED: \"Finalizado.\"\n  STR_DETAILED_INFO_IN_LOG_FILE: \"Informações detalhadas foram salvas em openxcom.log\"\n  STR_RANK_NONE: \"-\"\n  STR_DAMAGE_NONE: \"NENHUM\"\n  STR_INFO_UFOPEDIA: \"INFORMAÇÃO\"\n  STR_COCKPIT_CAPACITY: \"PILOTOS>{ALT}{0}{ALT}\"\n  STR_MAXIMUM_RANGE: \"ALCANCE MÁX>{ALT}{0}{ALT}\"\n  STR_MINIMUM_RANGE: \"ALCANCE MÍN>{ALT}{0}{ALT}\"\n  STR_INFINITE_RANGE: \"N/D\"\n  STR_TRACTOR_BEAM_POWER: \"Potência\"\n  STR_WEIGHT_PEDIA1: \"Peso: {0}\"\n  STR_WEIGHT_PEDIA2: \"Peso: {0}/{1}\"\n  STR_SHOT_TYPE_MELEE: \"Corpo a Corpo\"\n  STR_ACCURACY_MODIFIER: \"Modificador de precisão>{ALT} {0}\"\n  STR_POWER_BONUS: \"Bônus de potência>{ALT} {0}\"\n  STR_MULTIPLE_DIFFERENT_BONUSES: \"múltiplos bônus em várias munições compatíveis\"\n  STR_STATS_FOR_NERDS: \"Estatísticas para Nerds\"\n  STR_ARTICLE: \"Artigo>{ALT} {0}\"\n  STR_COMPATIBLE_AMMO: \"Munição compatível:\"\n  STR_BUILT_IN_ITEMS: \"Itens embutidos:\"\n  STR_CLIP_SIZE_UNLIMITED: \"ilimitado\"\n  STR_SHOTGUN_BEHAVIOR_OXCE: \"estendido\"\n  STR_INCLUDE_DEBUG: \"DEPURAÇÃO\"\n  STR_INCLUDE_IDS: \"IDs\"\n  STR_INCLUDE_DEFAULTS: \"PADRÕES\"\n  STR_TRUE: \"verdadeiro\"\n  STR_FALSE: \"falso\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH: \"HABILIDADE PSI*FORÇA PSI\"\n  STR_STRENGTH_AND_MELEE_ACCURACY: \"FORÇA*PRECISÃO CORPO A CORPO\"\n  STR_STRENGTH_AND_THROWING_ACCURACY: \"FORÇA*PRECISÃO DE ARREMESSO\"\n  STR_FIRING_ACCURACY_AND_REACTIONS: \"PRECISÃO DE TIRO*REAÇÕES\"\n  STR_HEALTH_CURRENT: \"SAÚDE ATUAL\"\n  STR_MANA_CURRENT: \"MANA ATUAL\"\n  STR_TIME_UNITS_CURRENT: \"UNIDADES DE TEMPO ATUAIS\"\n  STR_STUN_LEVEL_CURRENT: \"NÍVEL DE ATORDOAMENTO ATUAL\"\n  STR_HEALTH_NORMALIZED: \"SAÚDE NORMALIZADA\"\n  STR_MANA_NORMALIZED: \"MANA NORMALIZADA\"\n  STR_TIME_UNITS_NORMALIZED: \"UNIDADES DE TEMPO NORMALIZADAS\"\n  STR_ENERGY_NORMALIZED: \"ENERGIA NORMALIZADA\"\n  STR_MORALE_NORMALIZED: \"MORAL NORMALIZADA\"\n  STR_STUN_LEVEL_NORMALIZED: \"NÍVEL DE ATORDOAMENTO NORMALIZADO\"\n  STR_ENERGY_REGENERATION: \"REGENERAÇÃO DE ENERGIA\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH_ABBREVIATION: \"PSI*FPSI\"\n  STR_STRENGTH_AND_MELEE_ACCURACY_ABBREVIATION: \"FOR*CPC\"\n  STR_STRENGTH_AND_THROWING_ACCURACY_ABBREVIATION: \"FOR*ARR\"\n  STR_FIRING_ACCURACY_AND_REACTIONS_ABBREVIATION: \"PRE*REA\"\n  STR_HEALTH_CURRENT_ABBREVIATION: \"SAÚDE ATUAL\"\n  STR_MANA_CURRENT_ABBREVIATION: \"MANA ATUAL\"\n  STR_TIME_UNITS_CURRENT_ABBREVIATION: \"UNIDADES DE TEMPO ATUAIS\"\n  STR_STUN_LEVEL_CURRENT_ABBREVIATION: \"NÍVEL DE ATORDOAMENTO ATUAL\"\n  STR_HEALTH_NORMALIZED_ABBREVIATION: \"SAÚDE NORMALIZADA\"\n  STR_MANA_NORMALIZED_ABBREVIATION: \"MANA NORMALIZADA\"\n  STR_TIME_UNITS_NORMALIZED_ABBREVIATION: \"UNIDADES DE TEMPO NORMALIZADAS\"\n  STR_ENERGY_NORMALIZED_ABBREVIATION: \"ENERGIA NORMALIZADA\"\n  STR_MORALE_NORMALIZED_ABBREVIATION: \"MORAL NORMALIZADA\"\n  STR_STUN_LEVEL_NORMALIZED_ABBREVIATION: \"NÍVEL DE ATORDOAMENTO NORMALIZADO\"\n  STR_ENERGY_REGENERATION_ABBREVIATION: \"REGENERAÇÃO DE ENERGIA\"\n  STR_COST_TIME: \"tempo\"\n  STR_COST_ENERGY: \"energia\"\n  STR_COST_MORALE: \"moral\"\n  STR_COST_HEALTH: \"saúde\"\n  STR_COST_STUN: \"atordoamento\"\n  STR_COST_MANA: \"mana\"\n  STR_COST_BUILD: \"construir\"\n  STR_COST_REFUND: \"reembolso\"\n  STR_DAMAGE_10: \"10\"\n  STR_DAMAGE_11: \"11\"\n  STR_DAMAGE_12: \"12\"\n  STR_DAMAGE_13: \"13\"\n  STR_DAMAGE_14: \"14\"\n  STR_DAMAGE_15: \"15\"\n  STR_DAMAGE_16: \"16\"\n  STR_DAMAGE_17: \"17\"\n  STR_DAMAGE_18: \"18\"\n  STR_DAMAGE_19: \"19\"\n  STR_NAUTICAL_MILES: \"{0} milhas náuticas\"\n  STR_KILOMETERS_PER_HOUR: \"{0} km/h\"\n  STR_SECONDS_LONG: \"{0} segundos\"\n  STR_RACE_BONUS: \"Bônus de raça\"\n  STR_FOR_DIFFICULTY: \"para dificuldade: {0}\"\n  STR_NOT_AWARDED_YET: \"Ainda não concedido\"\n"
  },
  {
    "path": "bin/common/Language/OXCE/ro.yml",
    "content": "ro:\n  STR_CANNOT_DISMANTLE_FACILITY_UPGRADING: \"NU SE POATE DEMONTA FACILITATEA!{SMALLLINE}Facilitatea nu poate fi eliminată in timpul upgrade-ului.\"\n  STR_CANNOT_UPGRADE_FACILITY_ALREADY_UPGRADING: \"NU SE POATE CONSTRUI AICI!{SMALLLINE}Deja se construeste peste facilitea existentă.\"\n  STR_CANNOT_UPGRADE_FACILITY_WRONG_SIZE: \"NU SE POATE CONSTRUI AICI{SMALLLINE}Facilitatea selectată trebuie sa acopere facilitatea existentă.\"\n  STR_CANNOT_UPGRADE_FACILITY_WRONG_TYPE: \"NU SE POATE CONSTRUI AICI!{SMALLLINE}Facilitățile existente nu pot fi upgradate de facilitatea selectată.\"\n  STR_CANNOT_UPGRADE_FACILITY_DISALLOWED: \"NU SE POATE CONSTRUI AICI!{SMALLLINE}Nu se poate construi peste facilitățile existente. \"\n  STR_CANNOT_BUILD_QUEUE_OFF: \"NU SE POATE CONSTRUI AICI!{SMALLLINE}Facilitățile conectate trebuie să fie mai întâi construite. \"\n  STR_ID: \"ID\"\n  STR_FIRST_LETTER: \"PRIMA LITERA\"\n  STR_LOAD_CRAFT_LOADOUT_TEMPLATE: \"Încarca înarmarea navei\"\n  STR_EMPTY_SLOT_N: \"Slot {0} Gol\"\n  STR_UNNAMED_SLOT_N: \"Slot {0} Anonim\"\n  STR_SAVE_CRAFT_LOADOUT_TEMPLATE: \"Salvează înarmarea navei\"\n  STR_SAVE_UC: \"SALVEAZĂ\"\n  STR_ALL: \"Tot\"\n  STR_EQUIPPED: \"Echipat\"\n  STR_UNASSIGNED: \"Alt\"\n  STR_PILOTS: \"PILOȚI\"\n  STR_SHIELD: \"SCUT>{ALT}{0}\"\n  STR_SELECT_PILOT: \"Selectează Pilot\"\n  STR_PILOTS_FOR_CRAFT: \"Pilot(ți) pentru {0}\"\n  STR_PILOTS_REQUIRED: \"Pilot(ți) necesari: {ALT}{0}\"\n  STR_ADD_PILOT: \"Adauga Pilot\"\n  STR_REMOVE_ALL_PILOTS: \"Elimina toți pilotii\"\n  STR_ACCURACY_BONUS: \"Bonus de precizie:\"\n  STR_DODGE_BONUS: \"Bonus se evitare:\"\n  STR_APPROACH_SPEED: \"Viteza de apropiere:\"\n  STR_COWARDLY: \"Frică (-50%)\"\n  STR_NORMAL: \"Normal\"\n  STR_BOLD: \"Îndrăzneală (+50%)\"\n  STR_VERY_BOLD: \"Curaj (+100%)\"\n  STR_REFUND_VALUE: \"Valoarea vânzarilor> {ALT}{0}\"\n  STR_GO_TO_TRANSFERS: \"Transfer...\"\n  STR_TOPIC: \"Subiect>{ALT} {0}\"\n  STR_SHOW_ALL: \"Arată tot\"\n  STR_NO_DEPENDENCIES: \"Fără dependențe\"\n  STR_DIRECT_DEPENDENCIES: \"Dependențe directe\"\n  STR_LEVEL_2_DEPENDENCIES: \"Dependență nivelul 2\"\n  STR_LEVEL_3_DEPENDENCIES: \"Dependență nivelul 3\"\n  STR_LEVEL_4_DEPENDENCIES: \"Dependență nivelul 4\"\n  STR_MORE_DEPENDENCIES: \"Exista dependențe si mai adânci...\"\n  STR_END_OF_SEARCH: \"Sfârșit de cautare.\"\n  STR_REFUND_PRODUCTION: \"RESTITUIE!\"\n  STR_PERSON_JOINING: \"Persoană se altătură\"\n  STR_OTHER_EMPLOYEES: \"Alt Personal și Inventar\"\n  STR_SHOW_ONLY_NEW: \"Arata numai nou\"\n  STR_FILTER_DEFAULT: \"Mod implicit\"\n  STR_FILTER_DEFAULT_SUPPLIES_OK: \"Mod implicit (consumabile OK)\"\n  STR_FILTER_DEFAULT_NO_SUPPLIES: \"Mod implicit (fără consumabile)\"\n  STR_FILTER_FACILITY_REQUIRED: \"Facilitatea lipsește\"\n  STR_FILTER_HIDDEN: \"Ascuns\"\n  STR_FILTER_EQUIPPED: \"Echipat\"\n  STR_SORT_DEFAULT: \"Mod implicit\"\n  STR_NOT_ENOUGH_CRAFT_SPACE: \"Nu este destul spațiu la bord!\"\n  STR_SELECT_AVATAR_FOR: \"ALEGE AVATAR PENTRU{NEWLINE}{0}\"\n  STR_TRAINING: \"Antrenament\"\n  STR_GRAND_TOTAL: \"Marele Total\"\n  STR_AVAILABLE_TOPICS: \"SUBIECTE DISPONIBILE\"\n  STR_QS_THREE_LETTERS_A: \"Va rugăm să intrați cel putin 3 litere\"\n  STR_QS_THREE_LETTERS_B: \"în caseta de Căutare Rapidă\"\n  STR_M_FLAG: \"[m]\"\n  STR_TECH_TREE_VIEWER: \"Inspector pentru Arborele Technologiilor\"\n  STR_SELECT_TOPIC: \"Alege Subiect\"\n  STR_RESEARCH_PROGRESS: \"Progres>{ALT} {0}%\"\n  STR_ITEM_DESTROYED: \"Obiect distrus:\"\n  STR_ITEM_REQUIRED: \"Obiect necesar:\"\n  STR_REQUIRES: \"Necesitează:\"\n  STR_DEPENDS_ON: \"Depinde de:\"\n  STR_UNLOCKED_BY: \"Deschis de:\"\n  STR_DISABLED_BY: \"Încapacitat de:\"\n  STR_GET_FOR_FREE_FROM: \"Ia gratis de la:\"\n  STR_REQUIRED_BY: \"Necesar prin:\"\n  STR_LEADS_TO: \"Aduce la:\"\n  STR_UNLOCKS: \"Deschide:\"\n  STR_DISABLES: \"Încapacitează:\"\n  STR_GIVES_ONE_FOR_FREE_SEQ: \"Dă unul pe gratis (secvețial):\"\n  STR_GIVES_ONE_FOR_FREE: \"Dă unul pe gratis:\"\n  STR_RESEARCH_REQUIRED: \"Cercetare necesară:\"\n  STR_MATERIALS_REQUIRED: \"Materiale necesare:\"\n  STR_ITEMS_PRODUCED: \"Obiecte produse:\"\n  STR_PERSON_RECRUITED: \"Persoană recrutată:\"\n  STR_MUST_USE_BOTH_HANDS: \"Ambele mâini sunt necesare pentru asta!\"\n  STR_NOT_ENOUGH_MORALE: \"Nu Este Destulă Morală!\"\n  STR_NOT_ENOUGH_HEALTH: \"Nu Este Destulă Sănătate!\"\n  STR_NOT_ENOUGH_STUN: \"Nivelul de Paralizare e prea ridicat!\"\n  STR_LINE_OF_SIGHT_REQUIRED: \"Linie de Vedere (LoS) necesară.\"\n  STR_CENTER_ON_WOUNDED_FRIEND: \"Centrează pe Prieten Rănit\"\n  STR_BUG_HUNT_ACTIVATED: \"Modul de vânatoare de bug-uri activat: inamicii sunt vizibili pe minimap!\"\n  STR_TARGET_ENEMY: \"; Țintă = INAMIC\"\n  STR_TARGET_NEUTRAL: \"; Țintă = NEUTRĂ\"\n  STR_TARGET_FRIEND: \"; Țintă = PRIETEN\"\n  STR_TARGET_YOURSELF: \"; Țintă = TU\"\n  STR_TARGET_ON_THE_GROUND: \"(la pământ)\"\n  STR_WHAT_CAN_I_WEAR: \"Ce pot purta?\"\n  STR_STARTING_CONDITION_ARMORS_ALLOWED: \"Aceasta misiune necesită echipament specific.{NEWLINE}{NEWLINE}Tipuri de armură permise sunt: {0}\"\n  STR_MISSION_OVER: \"Misiune completă.\"\n  STR_UNITS_WITH_FATAL_WOUNDS:\n    one: \"{N} din noi încă sunt rănit fatal\"\n    few: \"{N} din noi încă sunt rănit fatal\"\n    other: \"{N} din noi încă sunt răniți fatal\"\n  STR_END_MISSION_QUESTION: \"Termină misiunea?\"\n  STR_LOOT: \"FURĂ\"\n  STR_SELL: \"VINDE\"\n  STR_LIVE_ALIENS_SURRENDERED: \"INAMICII S-AU PREDAT\"\n  STR_BOUNTY: \"RECOMPENSĂ\"\n  STR_CANNOT_PLACE_ITEM_INTO_THIS_SECTION: \"Nu este permis să plazați obiectul aici.{NEWLINE}Nu întrebați de ce!\"\n  STR_LOAD_EQUIPMENT_TEMPLATE: \"Încarca Șablonul de Echipament\"\n  STR_SAVE_EQUIPMENT_TEMPLATE: \"Salvează Șablonul de Echipament\"\n  STR_FIRING_SHORT: \"Tragând>{ALT}{0}\"\n  STR_THROWING_SHORT: \"Aruncă>{ALT}{0}\"\n  STR_MELEE_SHORT: \"Corp La Corp>{ALT}{0}\"\n  STR_HIT_LOG_NEW_TURN: \"Rând Nou\"\n  STR_FAILED_CQB_CHECK: \"Inamicul a reușit să va intrerupă atacul!\"\n  STR_NO_TRAJECTORY: \"Nici o traiectorie viabilă!\"\n  STR_HIT_LOG_NEW_BULLET: \"=>\"\n  STR_HIT_LOG_NO_DAMAGE: \"0\"\n  STR_HIT_LOG_SMALL_DAMAGE: \"lovitură\"\n  STR_HIT_LOG_REACTION_FIRE: \"Tragere de reacție...\"\n  STR_UFO_LANDING_ALERT: \"Alterta aterizare OZN\"\n  STR_UFO_LANDING_ALERT_DESC: \"Dacă este activat, un mesaj va apare fiecare dată când un OZN aterizează.\"\n  STR_PLAY_BRIEFING_MUSIC_DURING_EQUIPMENT: \"Rulează muzica din meniul de informare înainte de misiune\"\n  STR_PLAY_BRIEFING_MUSIC_DURING_EQUIPMENT_DESC: \"Muzica din meniul informativ înainte de misiune va continua să ruleze  până când campul de lupta este afișat.\"\n  STR_NIGHT_VISION_COLOR: \"Selectează vedere nocturnă\"\n  STR_AUTO_SELL: \"Administrator automat de vânzare\"\n  STR_AUTO_SELL_DESC: \"În meniul de vânzare de după luptă, orice tip de echipament care l-ai vânzat in trecut va fi automatic marcat pentru vânzare.\"\n  STR_GRAPHS_ZOOM_IN: \"Zoomează În (Grafice)\"\n  STR_GRAPHS_ZOOM_OUT: \"Zoomează Out (Gragice)\"\n  STR_MARK_ALL_AS_SEEN: \"Marchează Totul ca Văzut\"\n  STR_ACTION_ITEM_1: \"Object Actiunea 1 (Țintește/Folosește)\"\n  STR_ACTION_ITEM_2: \"Obiect Acțiunea 2 (Pleznește)\"\n  STR_ACTION_ITEM_3: \"Obiect Actiunea 3 (Auto)\"\n  STR_ACTION_ITEM_4: \"Obiect Acțiunea 4 (Corp la Corp)\"\n  STR_ACTION_ITEM_5: \"Obiect Acțiunea 5 (Aruncă)\"\n  STR_TOGGLE_QUICK_SEARCH: \"Activează sau deactivează Cautare Rapidă\"\n  STR_TOGGLE_NIGHT_VISION: \"Activează sau Deactivează Viziune Nocturnă\"\n  STR_HOLD_NIGHT_VISION: \"Viziune Nocturna Scurtă\"\n  STR_SELECT_MUSIC_TRACK: \"Alege Melodia\"\n  STR_PHYSICAL_TRAINING: \"Antrenament Marțial\"\n  STR_REMAINING_TRAINING_FACILITY_CAPACITY: \"CAPCITATE DE ANTRENAMENT RĂMAS> {ALT}{0}\"\n  STR_NO_WOUNDED: \"-\"\n  STR_NO_DONE: \"TERMINAT\"\n  STR_START_FIRING: \"Trage!\"\n  STR_SKIP_FIRING: \"Lasă-i inăuntru...\"\n  STR_ASSIGN_PILOTS: \"Atribuie piloți...\"\n  STR_NOT_ENOUGH_PILOTS: \"Nu sunt destui piloți!{NEWLINE}Minimum: {0}\"\n  STR_UFO_SHIELD_HIT: \"ATACĂ SCUTURILE!\"\n  STR_UFO_HIT_NO_DAMAGE: \"RICOȘAT DIN FUSELAJ\"\n  STR_UFO_SHIELD_DOWN: \"SCUTURILE INAMICE SUNT JOS\"\n  STR_UFO_HIT_GLANCING: \"LOVIRE DEVIATĂ!\"\n  STR_INTERCEPTOR_SHIELD_HIT: \"SCUTURILE NOASTRE ȚIN!\"\n  STR_TRACTOR_BEAM_ENGAGED: \"RAZA TRACTOARE A FOST ACTIVATĂ!\"\n  STR_TRACTOR_BEAM_DISENGAGED: \"RAZA TRACTOARE A FOST DEACTIVATĂ!\"\n  STR_AUTO_PATROL: \"PATRULARE AUTOMATĂ\"\n  STR_UFO_STARTED_HUNTING: \"{0} este in curs de incerceptare cu  {1}\"\n  STR_CRAFT_IS_READY: \"{0} la {1} este gata.\"\n  STR_ECONOMY_WARNING: \"Fondurile {0} și venitul {1} sunt scăzute iar întreținrea  {2} prea ridicată! Vinde ceva să eviți luare de credit... fonduri lipsă: {3}\"\n  STR_RETURNING: \"INTORCÂND\"\n  STR_INTERCEPTING: \"INTERCEPTÂND\"\n  STR_ESCORTING: \"ESCORTÂND\"\n  STR_EN_ROUTE: \"PE DRUM\"\n  STR_PILOT_MISSING: \"PILOT LIPSEȘTE\"\n  STR_DAY_SHORT: \"{0}d\"\n  STR_HOUR_SHORT: \"{0}d\"\n  STR_PERFORMANCE_BONUS: \"Performanță Bonus\"\n  STR_WE_CAN_NOW_RENT: \"Acum putem sa închiriem\"\n  STR_WE_CAN_NOW_BUILD: \"Acum putem să construim\"\n  STR_WE_CAN_NOW_PURCHASE: \"Acum putem sa cumpărăm\"\n  STR_NOT_ENOUGH_LIVING_SPACE_AT_BASE: \"Nu este destul spațiu de trai să acomodeze {NEWLINE}{0}{NEWLINE}la{NEWLINE}{1}\"\n  STR_INFO: \"INFORMAȚIE\"\n  STR_UFO_TRACKER: \"Urmăritor de OZN-uri\"\n  STR_TEST_SCREEN: \"ECRAN TEST\"\n  STR_PALETTE: \"Paletă:\"\n  STR_TEST_CASE: \"Caz TestȘ\"\n  STR_RUN: \"Rulează testul selectat!\"\n  STR_TESTS_STARTING: \"Începere...\"\n  STR_TESTS_ERRORS_FOUND: \"Toate erorile găsite (pot exista duplicate): {0}\"\n  STR_TESTS_NO_ERRORS_FOUND: \"Nici o eroare găsită.\"\n  STR_TESTS_FINISHED: \"Terminat.\"\n  STR_RANK_NONE: \"-\"\n  STR_DAMAGE_NONE: \"NIMIC\"\n  STR_INFO_UFOPEDIA: \"INFORMAȚIE\"\n  STR_COCKPIT_CAPACITY: \"PILOȚI>{ALT}{0}{ALT}\"\n  STR_WEIGHT_PEDIA1: \"Gt: {0}\"\n  STR_WEIGHT_PEDIA2: \"Gt: {0}/{1}\"\n  STR_SHOT_TYPE_MELEE: \"Corp la Corp\"\n"
  },
  {
    "path": "bin/common/Language/OXCE/ru.yml",
    "content": "ru:\n  STR_CANNOT_DISMANTLE_FACILITY_UPGRADING: \"СНОС НЕВОЗМОЖЕН!{SMALLLINE}Строение невозможно снести в ходе модернизации.\"\n  STR_CANNOT_UPGRADE_FACILITY_ALREADY_UPGRADING: \"СТРОИТЕЛЬСТВО НЕВОЗМОЖНО!{SMALLLINE}Существующее сооружение уже надстроено.\"\n  STR_CANNOT_UPGRADE_FACILITY_WRONG_SIZE: \"СТРОИТЕЛЬСТВО НЕВОЗМОЖНО!{SMALLLINE}Выбранная постройка должна совпадать по размерам с существующим сооружением.\"\n  STR_CANNOT_UPGRADE_FACILITY_WRONG_TYPE: \"СТРОИТЕЛЬСТВО НЕВОЗМОЖНО!{SMALLLINE}Выбранная постройка не является улучшением существующей.\"\n  STR_CANNOT_UPGRADE_FACILITY_DISALLOWED: \"СТРОИТЕЛЬСТВО НЕВОЗМОЖНО!{SMALLLINE}Существующее сооружение не может быть надстроено.\"\n  STR_CANNOT_BUILD_QUEUE_OFF: \"СТРОИТЕЛЬСТВО НЕВОЗМОЖНО!{SMALLLINE}Сначала необходимо завершить строительство связующих сооружений.\"\n  STR_CANNOT_BUILD_UPGRADE_ONLY: \"СТРОИТЕЛЬСТВО НЕВОЗМОЖНО!{SMALLLINE}Это сооружение может быть построено только поверх существующего.\"\n  STR_FACILITY_FORBIDDEN_BY_OTHER: \"СТРОИТЕЛЬСТВО НЕВОЗМОЖНО!{SMALLLINE}Существующие сооружения запрещают постройку.\"\n  STR_FACILITY_OTHER_FORBIDDEN_BY_THIS: \"СТРОИТЕЛЬСТВО НЕВОЗМОЖНО!{SMALLLINE}Выбранная постройка заблокирует существующее сооружение.\"\n  STR_NOT_ENOUGH_ITEMS: \"НЕДОСТАТОЧНО РЕСУРСОВ!{SMALLLINE}Нам нужно больше материалов для строительства сооружения{NEWLINE}Отсутствуют> {0}: {1}\"\n  STR_ID: \"ИДЕНТИФИКАТОР\"\n  STR_FIRST_LETTER: \"ПЕРВАЯ БУКВА\"\n  STR_SOLDIER_TYPE: \"ТИП БОЙЦА\"\n  STR_IDLE_DAYS: \"ДНЕЙ НЕАКТ.\"\n  STR_MANA: \"МАНА\"\n  STR_MANA_POOL: \"ВСЕГО МАНЫ\"\n  STR_MANA_MISSING: \"ОТСУТСТВУЕТ МАНА\"\n  STR_LOAD_CRAFT_LOADOUT_TEMPLATE: \"Загрузить компоновку ТС\"\n  STR_EMPTY_SLOT_N: \"Пустая ячейка {0}\"\n  STR_UNNAMED_SLOT_N: \"Ячейка без названия {0}\"\n  STR_ADD_ON_TOP: \"Добавить к существующей\"\n  STR_SAVE_CRAFT_LOADOUT_TEMPLATE: \"Сохранить компоновку ТС\"\n  STR_SAVE_UC: \"СОХРАНИТЬ\"\n  STR_ALL: \"Все\"\n  STR_EQUIPPED: \"Снаряженное\"\n  STR_NOT_EQUIPPED: \"Не снаряженное\"\n  STR_UNASSIGNED: \"Прочее\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED_BY_SIZE: \"ГРУЗОВОЙ ОТСЕК ЗАПОЛНЕН!{SMALLLINE}Объем отсека: {0}\"\n  STR_PILOTS: \"ПИЛОТЫ\"\n  STR_SHIELD: \"ЩИТ>{ALT}{0}\"\n  STR_CRAFT_SKIN_ID: \"[{0}]\"\n  STR_SELECT_PILOT: \"Выберите пилота\"\n  STR_PILOTS_FOR_CRAFT: \"Пилот(ы) на {0}\"\n  STR_PILOTS_REQUIRED: \"Пилот(ов) необходим(о): {ALT}{0}\"\n  STR_ADD_PILOT: \"Добавить пилота\"\n  STR_REMOVE_ALL_PILOTS: \"Снять всех пилотов\"\n  STR_ACCURACY_BONUS: \"Бонус к точности:\"\n  STR_DODGE_BONUS: \"Бонус к уклонению:\"\n  STR_APPROACH_SPEED: \"Скорость сближения:\"\n  STR_COWARDLY: \"Осторожно (-50 %)\"\n  STR_NORMAL: \"Нормально\"\n  STR_BOLD: \"Храбро (+50 %)\"\n  STR_VERY_BOLD: \"Очень храбро (+100 %)\"\n  STR_ARMOR_GROUP_NOT_ALLOWED: \"Бронезащиту этого типа запрещено брать на борт.\"\n  STR_SOLDIER_GROUP_NOT_ALLOWED: \"Нельзя погрузить бойца такого типа на борт.\"\n  STR_SOLDIER_GROUP_NOT_SAME: \"Боец этого типа несовместим с имеющимися на борту пассажирами.\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW: \"Предпросмотр\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_SAVED: \"Предпросмотр *\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_BRIEFING: \"Позволяет просматривать и изменять схему высадки боевых единиц игрока перед началом операции. Количество ОД не ограничено. Чтобы отобразить доступные точки высадки, нажмите Alt. Чтобы сохранить схему, нажмите кнопку «Покинуть поле боя». Чтобы выйти из режима просмотра схемы, нажмите кнопку «Закончить ход».{NEWLINE}Назначение новых бойцов или техники в ТС автоматически аннулирует сохраненную схему высадки. Наличие индивидуальной схемы высадки отображается знаком '*' на кнопке «Предпросмотр».\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_BRIEFING_DUMMY: \"Эта функция позволяет просматривать и изменять схему размещения бойцов на ТС выбранного типа. Изменения применяются ко всем ТС, имеющимся в наличии, а также купленным или произведенным в дальнейшем. Для размещения выдается максимально возможное для выбранного ТС число бойцов. Один боец соответствует одному ряду в схеме размещения. Имена бойцов совпадают с номером ряда. Чтобы разместить боевую единицу, занимающую 2х2 клетки, расставьте 4 бойцов в квадрате 2х2. Если этого не сделать, боевая единица размером 2х2 не появится на поле боя в тактической фазе игры.\"\n  STR_BASE_DEFENSE_BRIEFING_PREVIEW: \"Эта опция позволяет просматривать базу в тактическом режиме.{NEWLINE}{NEWLINE}Для выхода из режима просмотра нажмите кнопку «Покинуть поле боя».\"\n  STR_NOT_ENOUGH_CARGO_SPACE: \"НЕДОСТАТОЧНАЯ ВМЕСТИМОСТЬ!{SMALLLINE}Установите другой пассажирский отсек или сократите число пассажиров.\"\n  STR_NOT_ENOUGH_STORAGE_SPACE_1: \"НЕДОСТАТОЧНО МЕСТА В ГРУЗОВОМ ОТСЕКЕ!{SMALLLINE}Слишком много грузов! Установите другой грузовой отсек или уберите часть груза.\"\n  STR_NOT_ENOUGH_STORAGE_SPACE_2: \"НЕДОСТАТОЧНО МЕСТА В ГРУЗОВОМ ОТСЕКЕ!{SMALLLINE}Груз занимает слишком большой объем! Установите другой грузовой отсек или измените габариты груза.\"\n  STR_REFUND_VALUE: \"Цена продажи> {ALT}{0}\"\n  STR_REFUND_VALUE_NEGATIVE: \"Затраты> {ALT}{0}\"\n  STR_PRODUCTION_OVERVIEW: \"ОБЗОР ПРОИЗВОДСТВА\"\n  STR_RESEARCH_DIARY: \"ЖУРНАЛ ИССЛЕДОВАНИЙ\"\n  STR_DISCOVERY_SOURCE_BASE: \"Получено в ходе исследований.{NEWLINE}База> {ALT}{1}{ALT}{NEWLINE}Код> {ALT}{0}{ALT}\"\n  STR_DISCOVERY_SOURCE_FREE_FROM: \"Получено исследованием другого проекта.{NEWLINE}Исследованный проект> {ALT}{2}{ALT}{NEWLINE}{ALT}{1}{ALT} -> {ALT}{0}{ALT}\"\n  STR_DISCOVERY_SOURCE_FREE_AFTER: \"Получено автоматически.{NEWLINE}Завершенный проект> {ALT}{2}{ALT}{NEWLINE}{ALT}{1}{ALT} -> {ALT}{0}{ALT}\"\n  STR_DISCOVERY_SOURCE_MISSION: \"Получено наградой за выполнение задания.{NEWLINE}Тип задания> {ALT}{2}{ALT}{NEWLINE}{ALT}{1}{ALT} -> {ALT}{0}{ALT}\"\n  STR_DISCOVERY_SOURCE_EVENT: \"Получено в результате события.{NEWLINE}Тип события> {ALT}{2}{ALT}{NEWLINE}{ALT}{1}{ALT} -> {ALT}{0}{ALT}\"\n  STR_RESEARCH_OVERVIEW: \"ОБЗОР ИССЛЕДОВАНИЙ\"\n  STR_PRISONER_OVERVIEW: \"ОБЗОР ПЛЕННЫХ\"\n  STR_PRISONER: \"ПЛЕННЫЙ\"\n  STR_PRISONER_AMOUNT: \"КОЛ-ВО\"\n  STR_PRISONER_INTERROGATED: \"ДОПРОШЕН\"\n  STR_TOTAL_IN_PRISON: \"Камер занято>{ALT}{0}\"\n  STR_TOTAL_INTERROGATED: \"Допрошено>{ALT}{0}\"\n  STR_PRISON_TYPE: \"Изолятор пришельцев\"\n  STR_KILL_SELECTED: \"Ликвид.\"\n  STR_SELL_SELECTED: \"Продать\"\n  STR_GO_TO_TRANSFERS: \"К транспортировке...\"\n  STR_PRISON_CLEANUP: \"Освободить камеры\"\n  STR_TOPIC: \"Топик>{ALT} {0}\"\n  STR_SHOW_ALL: \"Показать все\"\n  STR_NO_DEPENDENCIES: \"Зависимостей нет.\"\n  STR_DIRECT_DEPENDENCIES: \"Прямые зависимости\"\n  STR_LEVEL_2_DEPENDENCIES: \"Зависимости 2-го уровня\"\n  STR_LEVEL_3_DEPENDENCIES: \"Зависимости 3-го уровня\"\n  STR_LEVEL_4_DEPENDENCIES: \"Зависимости 4-го уровня\"\n  STR_MORE_DEPENDENCIES: \"Более далекие зависимости...\"\n  STR_END_OF_SEARCH: \"Поиск окончен.\"\n  STR_FALLBACK_PRODUCTION: \"РЕЗЕРВ\"\n  STR_REFUND_PRODUCTION: \"ВОЗВРАТ!\"\n  STR_HOURS_PER_UNIT: \"ЧАСОВ НА ЕД.>{ALT}{0}\"\n  STR_PERSON_JOINING: \"Присоединяется персонаж\"\n  STR_RANDOM_PRODUCTION_DISCLAIMER: \"Случайный результат!\"\n  STR_OTHER_EMPLOYEES: \"Прочий персонал и техника\"\n  STR_SHOW_ONLY_NEW: \"Только новые\"\n  STR_FILTER_DEFAULT: \"По умолчанию\"\n  STR_FILTER_DEFAULT_SUPPLIES_OK: \"По умолч. (ресурсы есть)\"\n  STR_FILTER_DEFAULT_NO_SUPPLIES: \"По умолч. (ресурсов нет)\"\n  STR_FILTER_FACILITY_REQUIRED: \"Необходимо сооружение\"\n  STR_FILTER_HIDDEN: \"Скрытые\"\n  STR_FILTER_EQUIPPED: \"Снаряженные\"\n  STR_FILTER_MISSING: \"Недостача\"\n  STR_SORT_DEFAULT: \"По умолчанию\"\n  STR_SORT_BY_COST: \"По стоимости\"\n  STR_SORT_BY_NAME: \"По названию\"\n  STR_RANDOM_PRODUCTION_SUMMARY: \"Отчет\"\n  STR_NOT_ENOUGH_PRISON_SPACE: \"НЕ ХВАТАЕТ МЕСТА В ИЗОЛЯТОРЕ ПРИШЕЛЬЦЕВ!{SMALLLINE}Постройте другой изолятор или отправьте пришельцев на другие базы.\"\n  STR_MONTHLY_ITEM_PURCHASE_LIMIT_EXCEEDED: \"МЕСЯЧНЫЙ ЛИМИТ НА ЗАКУПКИ ИСЧЕРПАН!{SMALLLINE}Возможность покупки выбранных товаров появится в следующем месяце.\"\n  STR_MONTHLY_CRAFT_PURCHASE_LIMIT_EXCEEDED: \"МЕСЯЧНЫЙ ЛИМИТ НА ЗАКУПКИ ИСЧЕРПАН!{SMALLLINE}Возможность покупки выбранных ТС появится в следующем месяце.\"\n  STR_MONTHLY_SOLDIER_HIRING_LIMIT_EXCEEDED: \"МЕСЯЧНЫЙ ЛИМИТ НА НАЕМ ИСЧЕРПАН!{SMALLLINE}Возможность найма новобранцев появится в следующем месяце.\"\n  STR_NOT_ENOUGH_CRAFT_SPACE: \"Недостаточно места на борту!\"\n  STR_SELECT_AVATAR_FOR: \"ВЫБЕРИТЕ АВАТАР ДЛЯ{NEWLINE}{0}\"\n  STR_SOLDIER_BONUSES_FOR: \"ЛИЧНЫЕ БОНУСЫ БОЙЦА{NEWLINE}{0}\"\n  STR_SUMMARY: \"Отчет\"\n  STR_MANA_RECOVERY: \"ВОССТ. МАНЫ> {ALT}{0}\"\n  STR_HEALTH_RECOVERY: \"ВОССТ. ОЗ> {ALT}{0}\"\n  STR_BONUSES_BUTTON: \"+\"\n  STR_PROMOTE_SOLDIER: \"ПОВЫСИТЬ/ПОНИЗИТЬ{NEWLINE}{0} {1}\"\n  STR_RANK_HEADER: \"ЗВАНИЕ\"\n  STR_OPENINGS_HEADER: \"ВАКАНСИИ\"\n  STR_KILLER_AND_WEAPON: \"{0}, {1}\"\n  STR_TRAINING: \"Тренировка\"\n  STR_SOLDIER_INFO: \"Инф. о бойце\"\n  STR_SELECT_TRANSFORMATION_FOR: \"{0}{NEWLINE}КАКУЮ ТРАНСФОРМАЦИЮ ОСУЩЕСТВИТЬ?\"\n  STR_TRANSFORMATIONS_BUTTON: \"^\"\n  STR_TRANSFER_TIME: \"Время трансп.>{ALT}{0}\"\n  STR_RECOVERY_TIME: \"Время лечения>{ALT}{0}\"\n  STR_CURRENT_STATS: \"Тек. показатели\"\n  STR_CHANGES: \"Изменения\"\n  STR_CHANGES_MIN: \"Изменения (мин.)\"\n  STR_CHANGES_MAX: \"Изменения (макс.)\"\n  STR_BONUS_STATS: \"Бонус к хар-кам\"\n  STR_TRANSFORMATIONS_OVERVIEW: \"Обзор трансформаций\"\n  STR_PROJECT_NAME: \"НАЗВАНИЕ ПРОЕКТА\"\n  STR_AVAILABLE_MATERIALS: \"РЕСУРСЫ В НАЛИЧИИ\"\n  STR_ELIGIBLE_SOLDIERS: \"ГОДНЫЕ БОЙЦЫ\"\n  STR_SHOW_ONLY_ELIGIBLE: \"Показать только годных\"\n  STR_ALL_SOLDIER_TYPES: \"Все типы бойцов\"\n  STR_ALL_SOLDIERS: \"Все бойцы\"\n  STR_HEALTHY_SOLDIERS: \"Здоровые бойцы\"\n  STR_WOUNDED_SOLDIERS: \"Раненые бойцы\"\n  STR_DEAD_SOLDIERS: \"Мертвые бойцы\"\n  STR_GRAND_TOTAL: \"Итого\"\n  STR_AVAILABLE_TOPICS: \"ДОСТУПНЫЕ ТОПИКИ\"\n  STR_QS_THREE_LETTERS_A: \"Введите не менее 3 букв\"\n  STR_QS_THREE_LETTERS_B: \"в поле быстрого поиска...\"\n  STR_M_FLAG: \" [пр.]\"\n  STR_F_FLAG: \"[соор.]\"\n  STR_I_FLAG: \"[ед.]\"\n  STR_C_FLAG: \" [ТС]\"\n  STR_THIS_FEATURE_IS_DISABLED_1: \"Эта функция отключена.\"\n  STR_THIS_FEATURE_IS_DISABLED_2: \"Эта функция отключена.\"\n  STR_THIS_FEATURE_IS_DISABLED_3: \"Эта функция отключена.\"\n  STR_THIS_FEATURE_IS_DISABLED_4: \"Эта функция отключена.\"\n  STR_THIS_FEATURE_IS_DISABLED_5: \"Эта функция отключена.\"\n  STR_TECH_TREE_VIEWER: \"Экран технологического древа\"\n  STR_SELECT_TOPIC: \"Выберите топик\"\n  STR_RESEARCH_PROGRESS: \"Прогресс>{ALT} {0}%\"\n  STR_ITEM_DESTROYED: \"Уничтожается предмет:\"\n  STR_ITEM_REQUIRED: \"Необходимые предметы:\"\n  STR_SERVICES_REQUIRED: \"Необходимые функции:\"\n  STR_SERVICES_PROVIDED: \"Обеспечиваемые функции:\"\n  STR_SERVICES_FORBIDDEN: \"Запрещаемые функции:\"\n  STR_REQUIRES: \"Требует:\"\n  STR_DEPENDS_ON: \"Зависит от:\"\n  STR_UNLOCKED_BY: \"Разблокируется:\"\n  STR_DISABLED_BY: \"Блокируется:\"\n  STR_REENABLED_BY: \"Деблокируется:\"\n  STR_GET_FOR_FREE_FROM: \"Дается:\"\n  STR_IS_LOOKUP_OF: \"Предмет статьи:\"\n  STR_LOOKUP: \"Статья:\"\n  STR_SPAWNED_ITEMS: \"Порожденные предметы:\"\n  STR_SPAWNED_EVENT: \"Вызывает событие:\"\n  STR_REQUIRED_BY: \"Требуется для:\"\n  STR_REQUIRED_BY_TRANSFORMATIONS: \"Требуется трансформациям:\"\n  STR_LEADS_TO: \"Ведет к:\"\n  STR_UNLOCKS: \"Разблокирует:\"\n  STR_DISABLES: \"Блокирует:\"\n  STR_REENABLES: \"Деблокирует:\"\n  STR_GIVES_ONE_FOR_FREE_SEQ: \"Дает (последовательно):\"\n  STR_GIVES_ONE_FOR_FREE: \"Дает:\"\n  STR_RESEARCH_REQUIRED: \"Необходимые исследования:\"\n  STR_RESEARCH_REQUIRED_USE: \"Необх. исследования (для исп-я):\"\n  STR_RESEARCH_REQUIRED_BUY: \"Необх. исследования (для покупки):\"\n  STR_SERVICES_REQUIRED_BUY: \"Необх. функции (для покупки):\"\n  STR_PRODUCED_BY: \"Производится:\"\n  STR_SPAWNED_BY: \"Порождается:\"\n  STR_MATERIALS_REQUIRED: \"Необходимые ресурсы:\"\n  STR_TTV_COST_PER_UNIT: \"Стоимость ед.:\"\n  STR_TTV_ENGINEER_HOURS: \"Человеко-часов:\"\n  STR_TTV_WORK_SPACE_REQUIRED: \"Наличие места в мастерских:\"\n  STR_ITEMS_PRODUCED: \"Производится:\"\n  STR_PERSON_RECRUITED: \"Присоединяется персонаж:\"\n  STR_UNLOCKS_ARCS: \"Разблокирует арки:\"\n  STR_DISABLES_ARCS: \"Блокирует арки:\"\n  STR_UNLOCKS_MISSIONS: \"Разблокирует задания:\"\n  STR_DISABLES_MISSIONS: \"Блокирует задания:\"\n  STR_UNLOCKS_EVENTS: \"Разблокирует события:\"\n  STR_DISABLES_EVENTS: \"Блокирует события:\"\n  STR_AFFECTS_GAME_PROGRESSION: \"Влияет на дальнейшее прохождение!\"\n  STR_ITEMS_AT_DESTINATION: \"В пункте назначения\"\n  STR_PRISONERS: \"Пленные\"\n  STR_ARMORS: \"Броня\"\n  STR_FILTER_RESEARCHED: \"Исследовано\"\n  STR_FILTER_RESEARCHABLE: \"Исследуемо\"\n  STR_CRAFT_DEPLOYMENT_QUESTION: \"Сохранить схему высадки?\"\n  STR_MUST_USE_BOTH_HANDS: \"Для этого нужны обе руки!\"\n  STR_NOT_ENOUGH_MORALE: \"Недостаточно морали!\"\n  STR_NOT_ENOUGH_HEALTH: \"Недостаточно ОЗ!\"\n  STR_NOT_ENOUGH_MANA: \"Недостаточно маны!\"\n  STR_NOT_ENOUGH_STUN: \"Слишком сильно оглушен(а)!\"\n  STR_MIND_CONTROL_SUCCESSFUL_ALT: \"Действие успешно\"\n  STR_LINE_OF_SIGHT_REQUIRED: \"Нет прямой видимости.\"\n  STR_CENTER_ON_WOUNDED_FRIEND: \"Показать раненого бойца\"\n  STR_CENTER_ON_DIZZY_FRIEND: \"Показать оглушенного бойца\"\n  STR_BUG_HUNT_ACTIVATED: \"Активирован режим поиска посл. противника: их видно на карте!\"\n  STR_QUICK_MODE_ACTIVATED: \"Режим непрерывного спринта.{NEWLINE}Для отключения нажмите Ctrl-S.\"\n  STR_QUICK_MODE_DEACTIVATED: \"Режим непрерывного спринта отключен.\"\n  STR_SINGLE_MAP_LAYER_ACTIVATED: \"Включен однослойный режим карты.{NEWLINE}Для отключения нажмите Ctrl-C.\"\n  STR_SINGLE_MAP_LAYER_DEACTIVATED: \"Однослойный режим карты выключен.\"\n  STR_TARGET_ENEMY: \"; Цель = ПРОТИВНИК\"\n  STR_TARGET_NEUTRAL: \"; Цель = НЕЙТРАЛ\"\n  STR_TARGET_FRIEND: \"; Цель = СОЮЗНИК\"\n  STR_TARGET_YOURSELF: \"; Цель = САМ БОЕЦ\"\n  STR_TARGET_ON_THE_GROUND: \"(на земле)\"\n  STR_USE_SPECIAL_ITEM: \"Использовать специальный блок\"\n  STR_NO_EXPERIENCE_YET: \"Не получившие опыта:\"\n  STR_OPERATION_UC: \"ОПЕРАЦИЯ> {0}\"\n  STR_WHAT_CAN_I_WEAR: \"Что я могу надеть?\"\n  STR_STARTING_CONDITION_ARMORS_FORBIDDEN: \"Это задание требует спец. снаряжения.{NEWLINE}{NEWLINE}Запрещено: {0}\"\n  STR_STARTING_CONDITION_ARMORS_ALLOWED: \"Это задание требует спец. снаряжения.{NEWLINE}{NEWLINE}Разрешено: {0}\"\n  STR_MISSION_OVER: \"Задание выполнено.\"\n  STR_UNITS_WITH_FATAL_WOUNDS:\n    one: \"{N} из нас все еще критически ранен\"\n    few: \"{N} из нас все еще критически ранены\"\n    many: \"{N} из нас все еще критически ранены\"\n    other: \"{N} из нас все еще критически ранен(ы)\"\n  STR_END_MISSION_QUESTION: \"Завершить задание?\"\n  STR_LOOT: \"ТРОФЕИ\"\n  STR_SELL: \"ПРОДАТЬ\"\n  STR_LIVE_ALIENS_SURRENDERED: \"СДАЛОСЬ ПРОТИВНИКОВ\"\n  STR_MISSION_ABORTED: \"ВЫПОЛНЕНИЕ ЗАДАНИЯ ПРЕКРАЩЕНО\"\n  STR_VIPS_SAVED: \"ВИПОВ СПАСЕНО\"\n  STR_VIPS_LOST: \"ВИПОВ ПОТЕРЯНО\"\n  STR_BOUNTY: \"НАГРАДА\"\n  STR_MANA_ABBREVIATION: \"МАН\"\n  STR_EXPERIENCE_OVERVIEW: \"Распределение опыта\"\n  STR_CANNOT_PLACE_ITEM_INTO_THIS_SECTION: \"Этот предмет нельзя поместить сюда.{NEWLINE}Не спрашивайте, почему!\"\n  STR_ONE_HAND_MUST_BE_EMPTY: \"Нужна свободная рука!\"\n  STR_LOAD_EQUIPMENT_TEMPLATE: \"Загрузить шаблон экипировки\"\n  STR_SAVE_EQUIPMENT_TEMPLATE: \"Сохранить шаблон экипировки\"\n  STR_FIRING_SHORT: \"Точн.>{ALT}{0}\"\n  STR_THROWING_SHORT: \"Мет.>{ALT}{0}\"\n  STR_MELEE_SHORT: \"Ближ.>{ALT}{0}\"\n  STR_PERSONAL_EQUIPMENT: \"БОЕВАЯ ЭКИПИРОВКА\"\n  STR_SAVE_PERSONAL_EQUIPMENT: \"Сохранить боевую экипировку\"\n  STR_LOAD_PERSONAL_EQUIPMENT: \"Загрузить боевую экипировку\"\n  STR_PERSONAL_EQUIPMENT_SAVED: \"Боевая экипировка сохранена.\"\n  STR_PERSONAL_EQUIPMENT_NOT_DEFINED: \"Сохраненная боевая экипировка отсутствует.\"\n  STR_SLOT: \"Место>{ALT}{0}\"\n  STR_THINKING: \"Идет анализ...\"\n  STR_TELL_ME_MORE: \"Разведданные\"\n  STR_REINFORCEMENTS_ALERT: \"Прибыло подкрепление!\"\n  STR_HIT_LOG_NEW_TURN: \"След. ход\"\n  STR_FAILED_CQB_CHECK: \"Противник смог прервать вашу атаку!\"\n  STR_NO_TRAJECTORY: \"Траектория отсутствует!\"\n  STR_HIT_LOG_NEW_BULLET: \"=> \"\n  STR_MANA_SHORT: \"МА>{ALT}{0}\"\n  STR_SKILL_NEEDS_ITEM: \"Навык требует наличия предмета!\"\n  STR_HIT_LOG_NO_DAMAGE: \"0 \"\n  STR_HIT_LOG_SMALL_DAMAGE: \"Попал\"\n  STR_HIT_LOG_BIG_DAMAGE: \"ПОПАЛ\"\n  STR_HIT_LOG_REACTION_FIRE: \"Ответный выстрел...\"\n  STR_HIT_LOG: \"Журнал попаданий\"\n  STR_BUTTON_TOUCH: \"Сенсор\"\n  STR_BUTTON_1: \"1\"\n  STR_BUTTON_10: \"10\"\n  STR_BUTTON_100: \"100\"\n  STR_BUTTON_LMB: \"ЛКМ\"\n  STR_BUTTON_RMB: \"ПКМ\"\n  STR_BUTTON_MMB: \"СКМ\"\n  STR_BUTTON_CTRL: \"Ctrl\"\n  STR_BUTTON_ALT: \"Alt\"\n  STR_BUTTON_SHIFT: \"Shift\"\n  STR_LAZY_LOADING: \"Ленивая загрузка\"\n  STR_LAZY_LOADING_DESC: \"При включении графические ресурсы подгружаются по мере необходимости. В противном случае они загружаются при запуске приложения.\"\n  STR_VSYNC_FOR_OPENGL: \"Верт. синхронизация в OpenGL\"\n  STR_VSYNC_FOR_OPENGL_DESC: \"При выключении ускоряет скрытые перемещения противника, а также (в зав. от настроек) перемещение бойцов. НЕ РЕКОМЕНДУЕТСЯ ограничение к/с, равное 0. Только для OpenGL-рендера.\"\n  STR_UPDATE_CHECK: \"Автопроверка обновлений\"\n  STR_UPDATE_CHECK_DESC: \"При включении опции OpenXcom автоматически проверяет наличие обновлений и позволяет обновить игру автоматически одним нажатием на кнопку.\"\n  STR_AUTOSAVE_SLOTS: \"Слоты автосохранения\"\n  STR_AUTOSAVE_SLOTS_DESC: \"Количество слотов автосохранения в тактическом режиме.\"\n  STR_AUTO_SAVE_BATTLESCAPE_SLOT_WITH_NUMBER: \"{0}\"\n  STR_GEO_AUTOSAVE_FREQUENCY: \"Частота автосохранения (в страт. режиме)\"\n  STR_GEO_AUTOSAVE_FREQUENCY_DESC: \"Количество игровых дней, по истечении которых игра будет автоматически сохранена.\"\n  STR_GEO_AUTOSAVE_SLOTS: \"Число автосохранений (в страт. режиме)\"\n  STR_GEO_AUTOSAVE_SLOTS_DESC: \"Количество доступных слотов под циклические автосохранения в стратегическом режиме.\"\n  STR_AUTO_SAVE_GEOSCAPE_SLOT_WITH_NUMBER: \"<AUTO GEOSCAPE> {0}\"\n  STR_OXCE_LINKS: \"Дополнительные кнопки\"\n  STR_OXCE_LINKS_DESC: \"Дополнительные меню / кнопки / элементы навигации, упрощающие доступ к новым возможностям, внедренным в OXCE.\"\n  STR_PEDIA_SHOW_CLIP_SIZE: \"Отображать количество боеприпасов в магазине в Уфопедии\"\n  STR_PEDIA_SHOW_CLIP_SIZE_DESC: \"При включении на страницах Уфопедии будет отображаться количество боеприпасов, содержащихся в выстреле / обойме / магазине / ленте / коробке / батарее.\"\n  STR_INTERCEPT_TABLE_SIZE: \"Размер окна перехвата\"\n  STR_INTERCEPT_TABLE_SIZE_DESC: \"Количество строк в следующих диалоговых окнах: «Перехват», «Наблюдение за НЛО».\"\n  STR_SHOW_SLACKING_INDICATOR: \"Показывать бездействующих работников\"\n  STR_SHOW_SLACKING_INDICATOR_DESC: \"При включении в интерфейсе отображается количество незадействованных ученых и инженеров.\"\n  STR_SHOW_MAINTENANCE_TIME: \"Отображать время обслуживания ТС\"\n  STR_SHOW_MAINTENANCE_TIME_DESC: \"{ALT}0>{ALT} Не отображать {ALT}1>{ALT} Отображать только текущую операцию {ALT}{NEWLINE}2>{ALT} Отображать всё (ремонт + пополнение БК + заправка).\"\n  STR_SHOW_ETA: \"Отобр. расчетное время прибытия (РВП)\"\n  STR_SHOW_ETA_DESC: \"{ALT}0>{ALT} Не отображать {ALT}1>{ALT} Отображать только для статичных целей {ALT}{NEWLINE}2>{ALT} Отображать также для движущихся целей.\"\n  STR_UFO_LANDING_ALERT: \"Предупреждение о приземлении НЛО\"\n  STR_UFO_LANDING_ALERT_DESC: \"При включении отображается сообщение о приземлении замеченного НЛО.\"\n  STR_REMEMBER_DISABLED_CRAFT_WEAPONS: \"Запоминать отключенные вооружения ТС\"\n  STR_REMEMBER_DISABLED_CRAFT_WEAPONS_DESC: \"Отключенные во время боя вооружения ТС будут оставаться отключенными. Их боекомплект также не будет пополняться на базе.\"\n  STR_GEO_EVENT_INSTANT_DELIVERY: \"Мгновенная доставка после событий\"\n  STR_GEO_EVENT_INSTANT_DELIVERY_DESC: \"При включении любые предметы, сгенерировавшиеся в результате событий на стратегической карте, мгновенно оказываются на складе. При отключении они приходят на склад через 1 час.\"\n  STR_SHOW_BASE_NAME_IN_POPUPS: \"Название базы во всплывающих окнах\"\n  STR_SHOW_BASE_NAME_IN_POPUPS_DESC: \"При включении название базы отображается в соответствующих всплывающих окнах (например, в окне «Исследование завершено»).\"\n  STR_ALTERNATE_CRAFT_EQUIPMENT_MANAGEMENT: \"Изменение менеджмента груз. отсека ТС\"\n  STR_ALTERNATE_CRAFT_EQUIPMENT_MANAGEMENT_DESC: \"При включении опции перемещение бойцов с базы на корабль и наоборот переносит их снаряжение вместе с ними (если это возможно).\"\n  STR_BASE_INFO_SCALE: \"Масшт. полосы прокрутки на экране базы\"\n  STR_BASE_INFO_SCALE_DESC: \"При включении полосы прокрутки шириной более 140 пикселей масштабируются под размеры элементов интерфейса.\"\n  STR_HIGHLIGHT_NEW: \"Подсвечивать новые топики\"\n  STR_HIGHLIGHT_NEW_DESC: \"При включении новые исследования, позиции в каталоге производства и статьи Уфопедии подсвечиваются другим цветом.\"\n  STR_RESEARCH_SCROLL_SPEED: \"Скорость прокрутки исследований\"\n  STR_RESEARCH_SCROLL_SPEED_DESC: \"Позволяет назначать/снимать ученых на экране текущих исследований средней кнопкой мыши.\"\n  STR_RESEARCH_SCROLL_SPEED_CTRL: \"Скорость прокрутки исследований (с Ctrl)\"\n  STR_RESEARCH_SCROLL_SPEED_CTRL_DESC: \"Позволяет назначать/снимать ученых на экране текущих исследований средней кнопкой мыши.\"\n  STR_MANUFACTURE_FILTER_SUPPLIES_OK: \"Фильтр каталога производства\"\n  STR_MANUFACTURE_FILTER_SUPPLIES_OK_DESC: \"При включении в списке производства отображаются только те позиции, для которых есть сырье.\"\n  STR_MANUFACTURE_SCROLL_SPEED: \"Скорость прокрутки каталога производства\"\n  STR_MANUFACTURE_SCROLL_SPEED_DESC: \"Позволяет назначать/снимать инженеров на экране производства с помощью средней кнопки мыши.\"\n  STR_MANUFACTURE_SCROLL_SPEED_CTRL: \"Скорость прокрутки каталога производства (с Ctrl)\"\n  STR_MANUFACTURE_SCROLL_SPEED_CTRL_DESC: \"Позволяет назначать/снимать инженеров на экране производства с помощью средней кнопки мыши.\"\n  STR_PERSONAL_LAYOUT_INCLUDING_ARMOR: \"Бронезащита в личном снаряжении\"\n  STR_PERSONAL_LAYOUT_INCLUDING_ARMOR_DESC: \"При включении личное снаряжение бойцов сохраняется вместе с надетой бронезащитой.\"\n  STR_MANUALPROMOTIONS: \"Повышение игроком\"\n  STR_MANUALPROMOTIONS_DESC: \"При включении опции повышение (или понижение) бойцов осуществляется вручную при нажатии на иконку звания.\"\n  STR_WOUNDED_DEFEND_BASE_IF: \"Раненые в обороне (если ОЗ больше %)\"\n  STR_WOUNDED_DEFEND_BASE_IF_DESC: \"Раненые бойцы принимают участие в обороне базы, если их ОЗ выше указанного процента.\"\n  STR_PLAY_BRIEFING_MUSIC_DURING_EQUIPMENT: \"Продлевать воспроизв. трека брифинга\"\n  STR_PLAY_BRIEFING_MUSIC_DURING_EQUIPMENT_DESC: \"Музыка из брифинга будет воспроизводиться во время снаряжения бойцов, пока не отобразится поле боя.\"\n  STR_NIGHT_VISION_COLOR: \"Цвет ночного видения\"\n  STR_NIGHT_VISION_COLOR_DESC: \"Диапазон значений от 1 до 15, каждое из которых соответствует определенному оттенку.\"\n  STR_AUTO_NIGHT_VISION_THRESHOLD: \"Порог активации ночного видения\"\n  STR_AUTO_NIGHT_VISION_THRESHOLD_DESC: \"Если уровень освещенности ниже указанного порога, автоматически включать ночное видение.\"\n  STR_SHOW_ACCURACY_ON_CROSSHAIR: \"Отображать точность возле прицела\"\n  STR_SHOW_ACCURACY_ON_CROSSHAIR_DESC: \"{ALT}0>{ALT}Никогда {ALT}1>{ALT}Только с формулой точности UFO Extender {ALT}{NEWLINE}2>{ALT}Всегда\"\n  STR_REACTION_FIRE_THRESHOLD: \"Порог ответного выстрела\"\n  STR_REACTION_FIRE_THRESHOLD_DESC: \"Боевые единицы под управлением игрока не будут открывать ответный огонь, если точность их выстрела по конкретной цели ниже указанного порога.\"\n  STR_AUTO_SELL: \"Менеджер автоматической продажи\"\n  STR_AUTO_SELL_DESC: \"На экране продажи трофеев после боя любой предмет, который продавался после предыдущих боев, будет отмечен как продаваемый.\"\n  STR_AUTOMATICPROMOTIONS: \"Автоматическое повышение\"\n  STR_AUTOMATICPROMOTIONS_DESC: \"При включении повышение бойцов происходит автоматически по завершении задания.\"\n  STR_OFF_CENTRE_SHOOTING: \"Стрельба со смещением\"\n  STR_OFF_CENTRE_SHOOTING_DESC: \"Бойцы будут вести огонь, немного сдвигая угол стрельбы при отсутствии линии огня.\"\n  STR_UNIFORM_SHOOTING_SPREAD: \"Равномерный разброс выстрелов\"\n  STR_UNIFORM_SHOOTING_SPREAD_DESC: \"Разброс выстрелов / бросков уменьшен и не зависит от направления.\"\n  STR_CRASHED_OR_LANDED: \"Кнопка посадки/катастрофы\"\n  STR_CRASHED_OR_LANDED_DESC: \"При активации на экране генератора миссий отображается дополнительная кнопка. Ее также можно отобразить/скрыть нажатием на F11. {ALT}0>{ALT}Отключена, {ALT}1>{ALT}Катастрофа, {ALT}2>{ALT}Посадка.\"\n  STR_GRAPHS_ZOOM_IN: \"Увеличение (графиков)\"\n  STR_GRAPHS_ZOOM_OUT: \"Уменьшение (графиков)\"\n  STR_MARK_ALL_AS_SEEN: \"Отметить все как просмотренное\"\n  STR_SELL_ALL: \"Продать все\"\n  STR_SELL_ALL_BUT_ONE: \"Продать все, кроме одного\"\n  STR_TRANSFER_ALL: \"Транспортировать все\"\n  STR_REMOVE_SOLDIERS_FROM_ALL_CRAFTS: \"Высадить бойцов со всех кораблей\"\n  STR_REMOVE_SOLDIERS_FROM_CRAFT: \"Высадить бойцов с корабля\"\n  STR_REMOVE_EQUIPMENT_FROM_CRAFT: \"Выгрузить снаряжение с транспорта\"\n  STR_REMOVE_ARMOR_FROM_ALL_CRAFTS: \"Выгрузить броню со всех кораблей\"\n  STR_REMOVE_ARMOR_FROM_CRAFT: \"Выгрузить броню с корабля\"\n  STR_REMOVE_SOLDIERS_FROM_TRAINING: \"Снять бойцов с тренировок\"\n  STR_ADD_SOLDIERS_TO_TRAINING: \"Направить бойцов на тренировку\"\n  STR_INVENTORY_ARMOR: \"Сменить бронекостюм\"\n  STR_INVENTORY_AVATAR: \"Сменить аватар\"\n  STR_INVENTORY_DIARY_LIGHT: \"Краткий дневник\"\n  STR_ACTION_ITEM_1: \"Действие 1 с объектом (Прицельный/Использовать)\"\n  STR_ACTION_ITEM_2: \"Действие 2 с объектом (Навскидку)\"\n  STR_ACTION_ITEM_3: \"Действие 3 с объектом (Очередь)\"\n  STR_ACTION_ITEM_4: \"Действие 4 с объектом (Удар в бл. бою)\"\n  STR_ACTION_ITEM_5: \"Действие 5 с объектом (Бросок)\"\n  STR_INSTA_SAVE: \"Быстрое сохранение\"\n  STR_TOGGLE_QUICK_SEARCH: \"Быстрый поиск Вкл./Выкл.\"\n  STR_TOGGLE_NIGHT_VISION: \"Ночное видение Вкл./Выкл.\"\n  STR_HOLD_NIGHT_VISION: \"Ночное видение при удержании\"\n  STR_SELECT_MUSIC_TRACK: \"Выбор музыкального трека\"\n  STR_TOGGLE_TOUCH_BUTTONS: \"Включить сенс. интерфейс\"\n  STR_TOGGLE_BRIGHTNESS: \"Повысить яркость (виз. эффект)\"\n  STR_BRIEFING: \"Инструктаж\"\n  STR_TOGGLE_DEBUG_MODE: \"ВКЛ./ВЫКЛ. РЕЖИМА РАЗРАБОТЧИКА\"\n  STR_DEBUG_KILL_ALL_ALIENS: \"РАЗР.: Убить всех противников\"\n  STR_PHYSICAL_TRAINING: \"Боевая подготовка\"\n  STR_REMAINING_TRAINING_FACILITY_CAPACITY: \"СВОБОДНЫХ ТРЕНИРОВОЧНЫХ МЕСТ> {ALT}{0}\"\n  STR_NO_WOUNDED: \"-\"\n  STR_NO_QUEUED: \"+\"\n  STR_NO_DONE: \"НАТРЕНИР.\"\n  STR_NO_AMMO: \"КОНЧИЛИСЬ БОЕПРИПАСЫ!\"\n  STR_START_FIRING: \"Огонь!\"\n  STR_SKIP_FIRING: \"Пропустить их...\"\n  STR_ALIEN_MISSILES_HAVE_DAMAGED_OUR_BASE: \"Ракеты пришельцев повредили нашу базу {0}\"\n  STR_ALIEN_MISSILES_HAVE_DESTROYED_OUR_BASE: \"Ракеты пришельцев уничтожили нашу базу {0}\"\n  STR_STARTING_CONDITION_COMMANDER: \"Для выполнения этого задания в подразделении необходимо присутствие командующего.\"\n  STR_STARTING_CONDITION_CRAFT: \"Этот транспорт не подходит для выполнения задания.\"\n  STR_STARTING_CONDITION_CRAFT_ALLOWED: \"Этот транспорт не подходит для выполнения задания.{NEWLINE}{NEWLINE}Допустимый транспорт: {0}\"\n  STR_STARTING_CONDITION_CRAFT_FORBIDDEN: \"Этот транспорт не подходит для выполнения задания.{NEWLINE}{NEWLINE}Запрещенный транспорт: {0}\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE: \"Не все бойцы могут выполнять это задание.\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE_ALLOWED: \"Не все бойцы могут выполнять это задание.{NEWLINE}{NEWLINE}Разрешены следующие типы бойцов: {0}\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE_FORBIDDEN: \"Не все бойцы могут выполнять это задание.{NEWLINE}{NEWLINE}Запрещены следующие типы бойцов: {0}\"\n  STR_STARTING_CONDITION_ITEM: \"Для этого задания необходимы следующие предметы:{NEWLINE}{NEWLINE}{0}\"\n  STR_NOT_ENOUGH_FUEL_TO_REACH_TARGET: \"НЕДОСТАТОЧНО ТОПЛИВА!{SMALLLINE}Расстояние до места назначения превышает радиус действия ТС.\"\n  STR_TOO_MANY_ITEMS_ONBOARD: \"ПЕРЕГРУЗКА!{SMALLLINE}ТС не может нести столько грузов.\"\n  STR_ARMOR_NOT_ALLOWED_ONBOARD: \"БРОНЕКОСТЮМ ЗАПРЕЩЕН!{SMALLLINE}На некоторых бойцах надета недопустимая бронезащита.\"\n  STR_FOLLOW_WING_LEADER_QUESTION: \"Следовать за ведущим?\"\n  STR_ASSIGN_PILOTS: \"Назначить пилотов\"\n  STR_NOT_ENOUGH_PILOTS: \"Не хватает пилотов!{NEWLINE}Минимум: {0}\"\n  STR_DAILY_PILOT_EXPERIENCE: \"Опыт пилотов за день\"\n  STR_UFO_SHIELD_HIT: \"ПОПАДАНИЕ В ЩИТ!\"\n  STR_UFO_HIT_NO_DAMAGE: \"РИКОШЕТ ОТ ОБШИВКИ!\"\n  STR_UFO_SHIELD_DOWN: \"ЩИТЫ ПРОТИВНИКА ОТКЛЮЧИЛИСЬ!\"\n  STR_UFO_HIT_GLANCING: \"ПОПАДАНИЕ ПО КАСАТЕЛЬНОЙ!\"\n  STR_INTERCEPTOR_SHIELD_HIT: \"НАШИ ЩИТЫ ДЕРЖАТСЯ!\"\n  STR_TRACTOR_BEAM_ENGAGED: \"ПРИТЯГИВАЮЩИЙ ЛУЧ АКТИВИРОВАН!\"\n  STR_TRACTOR_BEAM_DISENGAGED: \"ПРИТЯГИВАЮЩИЙ ЛУЧ ДЕАКТИВИРОВАН\"\n  STR_SELF_DESTRUCT_ACTIVATED: \"САМОУНИЧТОЖЕНИЕ АКТИВИРОВАНО!\"\n  STR_SELF_DESTRUCT_CANCELLED: \"САМОУНИЧТОЖЕНИЕ ОТМЕНЕНО\"\n  STR_MISSILE_DAMAGED: \">>> РАКЕТА ПОВРЕЖДЕНА <<<\"\n  STR_MISSILE_DESTROYED: \">>> РАКЕТА УНИЧТОЖЕНА <<<\"\n  STR_EXTENDED_LINKS: \"Навигация\"\n  STR_AUTO_PATROL: \"АВТОН. ПАТРУЛИР.\"\n  STR_ETA: \"РВП>{ALT}{0}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_FACILITY_AT_BASE: \"{0} отсутствует для модуля {1} на базе {2}\"\n  STR_UFO_STARTED_HUNTING: \"{0} пытается перехватить {1}\"\n  STR_CRAFT_IS_READY: \"{0} в {1} готов.\"\n  STR_ECONOMY_WARNING: \"Текущих средств на счете ({0}) и доходов ({1}) недостаточно, а эксплуатационные расходы ({2}) слишком высоки! Продайте что-нибудь, чтобы не влезть в долги. Необходимая сумма: {3}\"\n  STR_SLACKING_INDICATOR: \"{0}:{1}\"\n  STR_TRAINING_INDICATOR: \"{0}:{1}\"\n  STR_EXTENDED_UC: \"БЫСТРЫЙ ДОСТУП\"\n  STR_RETURNING: \"ВОЗВРАЩАЕТСЯ\"\n  STR_INTERCEPTING: \"НА ПЕРЕХВАТЕ\"\n  STR_ESCORTING: \"В ЭСКОРТЕ\"\n  STR_EN_ROUTE: \"В ПУТИ\"\n  STR_PILOT_MISSING: \"НЕ ХВАТАЕТ ПИЛОТОВ\"\n  STR_DAY_SHORT: \"{0} д\"\n  STR_HOUR_SHORT: \"{0} ч\"\n  STR_PERFORMANCE_BONUS: \"Бонус за результативность\"\n  STR_COUNTRY_HAS_CANCELLED_A_SECRET_PACT: \"Страна {0} расторгла пакт с пришельцами и теперь может возобновить участие в проекте.\"\n  STR_COUNTRIES_HAVE_CANCELLED_A_SECRET_PACT: \"{0} расторгли пакт с пришельцами и теперь могут возобновить участие в проекте.\"\n  STR_WE_CAN_NOW_RENT: \"Мы теперь можем арендовать\"\n  STR_REQUIRED_BASE_SERVICES: \"Требуемые функции базы: {0}\"\n  STR_WE_CAN_NOW_BUILD: \"Мы теперь можем построить\"\n  STR_WE_CAN_NOW_PURCHASE: \"Мы теперь можем купить\"\n  STR_NOT_ENOUGH_LIVING_SPACE_AT_BASE: \"Недостаточно мест для размещения{NEWLINE}{0}{NEWLINE}в{NEWLINE}{1}\"\n  STR_INFO: \"ИНФОРМАЦИЯ\"\n  STR_DESPAWN_PENALTY: \"Штраф за игнорир.> {0}\"\n  STR_TRAINING_FINISHED: \"Тренировка окончена.{NEWLINE}Место - {0}\"\n  STR_PSI_TRAINING_FINISHED: \"Пси-тренировка окончена.{NEWLINE}Место - {0}\"\n  STR_IGNORE_UC: \"ИГНОРИРОВАТЬ\"\n  STR_UFO_TRACKER: \"Наблюдение за НЛО\"\n  STR_UPDATE: \"Обновить\"\n  STR_LATEST_VERSION_INFO: \"У вас уже установлена последняя версия OpenXcom.\"\n  STR_MASTER_MOD_VERSION_REQUIRED_QUESTION: \"Мод требует установки OpenXcom версии v{0} для корректной работы. Активировать мод?\"\n  STR_VERSION_REQUIRED_QUESTION: \"Этот мод требует OXCE вер. {0}. Активировать его?\"\n  STR_OPEN_MODS_FOLDER: \"Папка\"\n  STR_GLOBE_TEXTURE: \"Текстура поверхности\"\n  STR_NOTES: \"Заметки\"\n  STR_NEW_NOTE: \"<НОВАЯ ЗАМЕТКА>\"\n  STR_ENGINE_OXC: \"OXC\"\n  STR_ENGINE_OXCE: \"OXCE\"\n  STR_ENGINE_OTHER: \"ПРОЧИЕ\"\n  STR_BASESCAPE: \"Управление базой\"\n  STR_AI: \"ИИ\"\n  STR_PATH_ENERGY_COST: \"Выносл.\"\n  STR_PATH_ENERGY_COST_DESC: \"По клику мышью отображается, сколько ОВ останется по достижении указанной точки.\"\n  STR_VEHICLES_LOST: \"Техники потеряно\"\n  STR_CRAFT_LOST_DOGFIGHT: \"Перехватчиков потеряно\"\n  STR_CRAFT_LOST_MISSION: \"Транспортов потеряно\"\n  STR_ALIEN_BASES_DESTROYED: \"Баз пришельцев уничтожено\"\n  STR_XCOM_BASES_LOST: \"Баз потеряно\"\n  STR_TEST_SCREEN: \"ТЕСТОВЫЙ РЕЖИМ\"\n  STR_PALETTE: \"Палитра:\"\n  STR_PREVIEW: \"Предпросмотр\"\n  STR_TINY_BORDERLESS: \"Мелкий, без контура\"\n  STR_TINY_BORDER: \"Мелкий\"\n  STR_SMALL_LOW_CONTRAST: \"Средний\"\n  STR_SMALL_HIGH_CONTRAST: \"Средний, высококонтр.\"\n  STR_BIG_LOW_CONTRAST: \"Крупный\"\n  STR_BIG_HIGH_CONTRAST: \"Крупный, высококонтр.\"\n  STR_TEST_CASE: \"Тест. сценарий:\"\n  STR_RUN: \"Запустить выбранный тест!\"\n  STR_TESTS_STARTING: \"Запуск...\"\n  STR_TESTS_ERRORS_FOUND: \"Всего ошибок найдено (возможны повторы): {0}\"\n  STR_TESTS_NO_ERRORS_FOUND: \"Ошибок не найдено.\"\n  STR_TESTS_FINISHED: \"Закончен.\"\n  STR_DETAILED_INFO_IN_LOG_FILE: \"Подробная нформация сохранена в файле openxcom.log.\"\n  STR_RANK_NONE: \"-\"\n  STR_DAMAGE_NONE: \"ОТСУТСТВ.\"\n  STR_INFO_UFOPEDIA: \"ИНФО\"\n  STR_COCKPIT_CAPACITY: \"ПИЛОТОВ>{ALT}{0}{ALT}\"\n  STR_MAXIMUM_RANGE: \"МАКС. ДАЛЬНОСТЬ>{ALT}{0}{ALT}\"\n  STR_MINIMUM_RANGE: \"МИН. ДАЛЬНОСТЬ>{ALT}{0}{ALT}\"\n  STR_INFINITE_RANGE: \"Отс.\"\n  STR_TRACTOR_BEAM_POWER: \"Мощность\"\n  STR_WEIGHT_PEDIA1: \"Вес: {0}\"\n  STR_WEIGHT_PEDIA2: \"Вес: {0}/{1}\"\n  STR_SHOT_TYPE_MELEE: \"Ближний бой\"\n  STR_ACCURACY_MODIFIER: \"Мод. точн.>{ALT} {0}\"\n  STR_POWER_BONUS: \"Бонус к урону>{ALT} {0}\"\n  STR_MULTIPLE_DIFFERENT_BONUSES: \"различные бонусы от используемых боеприпасов\"\n  STR_STATS_FOR_NERDS: \"Инф-я для зануд\"\n  STR_ARTICLE: \"Топик>{ALT} {0}\"\n  STR_COMPATIBLE_AMMO: \"Использ. боеприпасы:\"\n  STR_BUILT_IN_ITEMS: \"Встроенные блоки:\"\n  STR_CLIP_SIZE_UNLIMITED: \"не ограничено\"\n  STR_SHOTGUN_BEHAVIOR_OXCE: \"расш. версия\"\n  STR_INCLUDE_DEBUG: \"ОТЛАДКА\"\n  STR_INCLUDE_IDS: \"ЗНАЧ.\"\n  STR_INCLUDE_DEFAULTS: \"ПО УМОЛЧ.\"\n  STR_TRUE: \"да\"\n  STR_FALSE: \"нет\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH: \"ПСИ-НАВЫК*ПСИ-СИЛА\"\n  STR_STRENGTH_AND_MELEE_ACCURACY: \"СИЛА*БЛИЖНИЙ БОЙ\"\n  STR_STRENGTH_AND_THROWING_ACCURACY: \"СИЛА*ТОЧНОСТЬ БРОСКА\"\n  STR_FIRING_ACCURACY_AND_REACTIONS: \"ТОЧНОСТЬ ВЫСТРЕЛА*РЕАКЦИЯ\"\n  STR_HEALTH_CURRENT: \"ТЕКУЩИЕ ОЗ\"\n  STR_MANA_CURRENT: \"ТЕКУЩАЯ МАНА\"\n  STR_TIME_UNITS_CURRENT: \"ТЕКУЩИЕ ОД\"\n  STR_STUN_LEVEL_CURRENT: \"ТЕКУЩЕЕ ОГЛУШЕНИЕ\"\n  STR_HEALTH_NORMALIZED: \"НОРМАЛИЗОВАННЫЕ ОЗ\"\n  STR_MANA_NORMALIZED: \"НОРМАЛИЗОВАННАЯ МАНА\"\n  STR_TIME_UNITS_NORMALIZED: \"НОРМАЛИЗОВАННЫЕ ОД\"\n  STR_ENERGY_NORMALIZED: \"НОРМАЛИЗОВАННЫЕ ОВ\"\n  STR_MORALE_NORMALIZED: \"НОРМАЛИЗОВАННАЯ МОРАЛЬ\"\n  STR_STUN_LEVEL_NORMALIZED: \"НОРМАЛИЗОВАННОЕ ОГЛУШЕНИЕ\"\n  STR_ENERGY_REGENERATION: \"ВОССТАНОВЛЕНИЕ ОВ\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH_ABBREVIATION: \"ПСН*ПСС\"\n  STR_STRENGTH_AND_MELEE_ACCURACY_ABBREVIATION: \"СИЛ*ББ\"\n  STR_STRENGTH_AND_THROWING_ACCURACY_ABBREVIATION: \"СИЛ*БРС\"\n  STR_FIRING_ACCURACY_AND_REACTIONS_ABBREVIATION: \"ТЧН*РЕА\"\n  STR_HEALTH_CURRENT_ABBREVIATION: \"ТЕКУЩИЕ ОЗ\"\n  STR_MANA_CURRENT_ABBREVIATION: \"ТЕКУЩАЯ МАНА\"\n  STR_TIME_UNITS_CURRENT_ABBREVIATION: \"ТЕКУЩИЕ ОД\"\n  STR_STUN_LEVEL_CURRENT_ABBREVIATION: \"ТЕКУЩЕЕ ОГЛУШЕНИЕ\"\n  STR_HEALTH_NORMALIZED_ABBREVIATION: \"НОРМАЛИЗОВАННЫЕ ОЗ\"\n  STR_MANA_NORMALIZED_ABBREVIATION: \"НОРМАЛИЗОВАННАЯ МАНА\"\n  STR_TIME_UNITS_NORMALIZED_ABBREVIATION: \"НОРМАЛИЗОВАННЫЕ ОД\"\n  STR_ENERGY_NORMALIZED_ABBREVIATION: \"НОРМАЛИЗОВАННЫЕ ОВ\"\n  STR_MORALE_NORMALIZED_ABBREVIATION: \"НОРМАЛИЗОВАННАЯ МОРАЛЬ\"\n  STR_STUN_LEVEL_NORMALIZED_ABBREVIATION: \"НОРМАЛИЗОВАННОЕ ОГЛУШЕНИЕ\"\n  STR_ENERGY_REGENERATION_ABBREVIATION: \"ВОССТАНОВЛЕНИЕ ОВ\"\n  STR_TIME_UNITS_SCALED: \"ОТНОСИТЕЛЬНЫЕ ОД\"\n  STR_STAMINA_SCALED: \"ОТНОСИТЕЛЬНЫЕ ОВ\"\n  STR_HEALTH_SCALED: \"ОТНОСИТЕЛЬНЫЕ ОЗ\"\n  STR_BRAVERY_SCALED: \"ОТНОСИТЕЛЬНАЯ ХРАБРОСТЬ\"\n  STR_REACTIONS_SCALED: \"ОТНОСИТЕЛЬНАЯ РЕАКЦИЯ\"\n  STR_FIRING_ACCURACY_SCALED: \"ОТНОСИТЕЛЬНАЯ ТОЧНОСТЬ ВЫСТРЕЛА\"\n  STR_THROWING_ACCURACY_SCALED: \"ОТНОСИТЕЛЬНАЯ ТОЧНОСТЬ БРОСКА\"\n  STR_STRENGTH_SCALED: \"ОТНОСИТЕЛЬНАЯ СИЛА\"\n  STR_PSIONIC_STRENGTH_SCALED: \"ОТНОСИТЕЛЬНАЯ ПСИ-СИЛА\"\n  STR_PSIONIC_SKILL_SCALED: \"ОТНОСИТЕЛЬНЫЙ ПСИ-НАВЫК\"\n  STR_MELEE_ACCURACY_SCALED: \"ОТНОСИТЕЛЬНЫЙ БЛИЖНИЙ БОЙ\"\n  STR_MANA_POOL_SCALED: \"ОТНОСИТЕЛЬНЫЙ ПУЛ МАНЫ\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH_SCALED: \"ОТНОСИТЕЛЬНЫЙ ПСИ-НАВЫК*ПСИ-СИЛА\"\n  STR_STRENGTH_AND_MELEE_ACCURACY_SCALED: \"ОТНОСИТЕЛЬНАЯ СИЛА*БЛИЖНИЙ БОЙ\"\n  STR_STRENGTH_AND_THROWING_ACCURACY_SCALED: \"ОТНОСИТЕЛЬНАЯ СИЛА*ТОЧНОСТЬ БРОСКА\"\n  STR_FIRING_ACCURACY_AND_REACTIONS_SCALED: \"ОТНОСИТЕЛЬНАЯ ТОЧНОСТЬ ВЫСТРЕЛА*РЕАКЦИЯ\"\n  STR_TIME_UNITS_SCALED_ABBREVIATION: \"ОТН. ОД\"\n  STR_STAMINA_SCALED_ABBREVIATION: \"ОТН. ОВ\"\n  STR_HEALTH_SCALED_ABBREVIATION: \"ОТН. ОЗ\"\n  STR_BRAVERY_SCALED_ABBREVIATION: \"ОТН. ХРА\"\n  STR_REACTIONS_SCALED_ABBREVIATION: \"ОТН. РЕА\"\n  STR_FIRING_ACCURACY_SCALED_ABBREVIATION: \"ОТН. ТЧН\"\n  STR_THROWING_ACCURACY_SCALED_ABBREVIATION: \"ОТН. БРС\"\n  STR_STRENGTH_SCALED_ABBREVIATION: \"ОТН. СИЛ\"\n  STR_PSIONIC_STRENGTH_SCALED_ABBREVIATION: \"ОТН. ПСС\"\n  STR_PSIONIC_SKILL_SCALED_ABBREVIATION: \"ОТН. ПСН\"\n  STR_MELEE_ACCURACY_SCALED_ABBREVIATION: \"ОТН. ББ\"\n  STR_MANA_POOL_SCALED_ABBREVIATION: \"ОТН. МАН\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH_SCALED_ABBREVIATION: \"ОТН. ПСН*ПСС\"\n  STR_STRENGTH_AND_MELEE_ACCURACY_SCALED_ABBREVIATION: \"ОТН. СИЛ*ББ\"\n  STR_STRENGTH_AND_THROWING_ACCURACY_SCALED_ABBREVIATION: \"ОТН. СИЛ*БРС\"\n  STR_FIRING_ACCURACY_AND_REACTIONS_SCALED_ABBREVIATION: \"ОТН. ТЧН*РЕА\"\n  STR_COST_TIME: \"ОД\"\n  STR_COST_ENERGY: \"выносливость\"\n  STR_COST_MORALE: \"мораль\"\n  STR_COST_HEALTH: \"ОЗ\"\n  STR_COST_STUN: \"оглушение\"\n  STR_COST_MANA: \"мана\"\n  STR_COST_BUILD: \"постройка\"\n  STR_COST_REFUND: \"возмещение\"\n  STR_DAMAGE_10: \"10\"\n  STR_DAMAGE_11: \"11\"\n  STR_DAMAGE_12: \"12\"\n  STR_DAMAGE_13: \"13\"\n  STR_DAMAGE_14: \"14\"\n  STR_DAMAGE_15: \"15\"\n  STR_DAMAGE_16: \"16\"\n  STR_DAMAGE_17: \"17\"\n  STR_DAMAGE_18: \"18\"\n  STR_DAMAGE_19: \"19\"\n  STR_NAUTICAL_MILES: \"{0} мор. миль\"\n  STR_KILOMETERS_PER_HOUR: \"{0} км/ч\"\n  STR_SECONDS_LONG: \"{0} секунд\"\n  STR_RACE_BONUS: \"Бонус при преслед.\"\n  STR_FOR_DIFFICULTY: \"для ур-ня сложности: {0}\"\n  STR_NOT_AWARDED_YET: \"Еще не вручались\"\n"
  },
  {
    "path": "bin/common/Language/OXCE/sv.yml",
    "content": "sv:\n  STR_ID: \"ID\"\n  STR_SOLDIER_TYPE: \"SOLDATTYP\"\n  STR_SAVE_UC: \"SPARA\"\n  STR_ALL: \"Allting\"\n  STR_PILOTS: \"PILOTER\"\n  STR_SHIELD: \"SKÖLD>{ALT}{0}\"\n  STR_CRAFT_SKIN_ID: \"[{0}]\"\n  STR_SELECT_PILOT: \"Välj pilot\"\n  STR_PILOTS_FOR_CRAFT: \"Pilot(er) för {0}\"\n  STR_ADD_PILOT: \"Lägg till pilot\"\n  STR_REMOVE_ALL_PILOTS: \"Ta bort alla piloter\"\n  STR_NORMAL: \"Normal\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW: \"Förhandsvisa\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_SAVED: \"Förhandsvisa *\"\n  STR_REFUND_VALUE: \"Försäljningsvärde> {ALT}{0}\"\n  STR_REFUND_VALUE_NEGATIVE: \"Utgifter> {ALT}{0}\"\n  STR_RESEARCH_OVERVIEW: \"FORSKNINGSÖVERSIKT\"\n  STR_PRISONER: \"FÅNGE\"\n  STR_PRISONER_AMOUNT: \"MÄNGD\"\n  STR_PRISONER_INTERROGATED: \"FÖRHÖRD\"\n  STR_KILL_SELECTED: \"Döda\"\n  STR_SELL_SELECTED: \"Sälj\"\n  STR_GO_TO_TRANSFERS: \"Överför...\"\n  STR_SHOW_ALL: \"Visa alla\"\n  STR_END_OF_SEARCH: \"Slut på sökningen.\"\n  STR_FILTER_DEFAULT: \"Standard\"\n  STR_FILTER_FACILITY_REQUIRED: \"Anläggning saknas\"\n  STR_FILTER_HIDDEN: \"Dold\"\n  STR_SORT_DEFAULT: \"Standard\"\n  STR_SORT_BY_COST: \"Efter kostnad\"\n  STR_SORT_BY_NAME: \"Efter namn\"\n  STR_RANDOM_PRODUCTION_SUMMARY: \"Sammandrag\"\n  STR_NOT_ENOUGH_CRAFT_SPACE: \"Inte tillräckligt med plats ombord!\"\n  STR_SUMMARY: \"Sammandrag\"\n  STR_BONUSES_BUTTON: \"+\"\n  STR_RANK_HEADER: \"RANK\"\n  STR_KILLER_AND_WEAPON: \"{0}, {1}\"\n  STR_TRAINING: \"Träning\"\n  STR_SOLDIER_INFO: \"Soldatinfo\"\n  STR_PROJECT_NAME: \"PROJEKTNAMN\"\n  STR_AVAILABLE_MATERIALS: \"TILLGÄNGLIGA MATERIAL\"\n  STR_ELIGIBLE_SOLDIERS: \"KVALIFICERADE SOLDATER\"\n  STR_SHOW_ONLY_ELIGIBLE: \"Visa endast kvalificerade\"\n  STR_ALL_SOLDIER_TYPES: \"Alla soldattyper\"\n  STR_ALL_SOLDIERS: \"Alla soldater\"\n  STR_WOUNDED_SOLDIERS: \"Skadade soldater\"\n  STR_DEAD_SOLDIERS: \"Döda soldater\"\n  STR_THIS_FEATURE_IS_DISABLED_1: \"Denna funktion är inaktiverad.\"\n  STR_THIS_FEATURE_IS_DISABLED_2: \"Denna funktion är inaktiverad.\"\n  STR_THIS_FEATURE_IS_DISABLED_3: \"Denna funktion är inaktiverad.\"\n  STR_THIS_FEATURE_IS_DISABLED_4: \"Denna funktion är inaktiverad.\"\n  STR_THIS_FEATURE_IS_DISABLED_5: \"Denna funktion är inaktiverad.\"\n  STR_RESEARCH_PROGRESS: \"Förlopp>{ALT} {0}%\"\n  STR_REQUIRES: \"Kräver:\"\n  STR_DEPENDS_ON: \"Beroende av:\"\n  STR_UNLOCKED_BY: \"Låses upp av:\"\n  STR_DISABLED_BY: \"Inaktiveras av:\"\n  STR_REENABLED_BY: \"Återaktiveras av:\"\n  STR_REQUIRED_BY: \"Krävs av:\"\n  STR_LEADS_TO: \"Leder till:\"\n  STR_UNLOCKS: \"Låser upp:\"\n  STR_DISABLES: \"Inaktiverar:\"\n  STR_REENABLES: \"Återaktiverar:\"\n  STR_TTV_COST_PER_UNIT: \"Kostnad per enhet:\"\n  STR_TTV_ENGINEER_HOURS: \"Ingenjörstimmar:\"\n  STR_PRISONERS: \"Fångar\"\n  STR_FILTER_RESEARCHED: \"Fullt forskad\"\n  STR_FILTER_RESEARCHABLE: \"Forskningsbar\"\n  STR_TARGET_ENEMY: \"; Mål = FIENDE\"\n  STR_TARGET_NEUTRAL: \"; Mål = NEUTRAL\"\n  STR_TARGET_FRIEND: \"; Mål = VÄN\"\n  STR_TARGET_YOURSELF: \"; Mål = DIG SJÄLV\"\n  STR_TARGET_ON_THE_GROUND: \" (på marken)\"\n  STR_NO_EXPERIENCE_YET: \"Ingen erfarenhet ännu:\"\n  STR_WHAT_CAN_I_WEAR: \"Vad kan jag bära?\"\n  STR_END_MISSION_QUESTION: \"Avsluta uppdrag?\"\n  STR_SELL: \"SÄLJ\"\n  STR_LOAD_EQUIPMENT_TEMPLATE: \"Läs in utrustningsmall\"\n  STR_SAVE_EQUIPMENT_TEMPLATE: \"Spara utrustningsmall\"\n  STR_PERSONAL_EQUIPMENT: \"PERSONLIG UTRUSTNING\"\n  STR_SAVE_PERSONAL_EQUIPMENT: \"Spara personlig utrustning\"\n  STR_LOAD_PERSONAL_EQUIPMENT: \"Läs in personlig utrustning\"\n  STR_THINKING: \"Tänker...\"\n  STR_HIT_LOG_NO_DAMAGE: \"0 \"\n  STR_HIT_LOG_SMALL_DAMAGE: \"träff\"\n  STR_HIT_LOG_BIG_DAMAGE: \"TRÄFF\"\n  STR_BUTTON_1: \"1\"\n  STR_BUTTON_10: \"10\"\n  STR_BUTTON_100: \"100\"\n  STR_BUTTON_CTRL: \"Ctrl\"\n  STR_BUTTON_ALT: \"Alt\"\n  STR_VSYNC_FOR_OPENGL: \"VSync för OpenGL\"\n  STR_AUTO_SAVE_BATTLESCAPE_SLOT_WITH_NUMBER: \"<AUTO BATTLESCAPE> {0}\"\n  STR_AUTO_SAVE_GEOSCAPE_SLOT_WITH_NUMBER: \"<AUTO GEOSCAPE> {0}\"\n  STR_SELL_ALL: \"Sälj alla\"\n  STR_SELL_ALL_BUT_ONE: \"Sälj alla förutom en\"\n  STR_TRANSFER_ALL: \"Överför alla\"\n  STR_SELECT_MUSIC_TRACK: \"Välj musikspår\"\n  STR_TOGGLE_DEBUG_MODE: \"Växla felsökningsläge\"\n  STR_NO_WOUNDED: \"-\"\n  STR_NO_QUEUED: \"+\"\n  STR_START_FIRING: \"Eld!\"\n  STR_ASSIGN_PILOTS: \"Tilldela piloter...\"\n  STR_MISSILE_DAMAGED: \">>> MISSIL SKADAD <<<\"\n  STR_MISSILE_DESTROYED: \">>> MISSIL FÖRSTÖRD <<<\"\n  STR_EXTENDED_LINKS: \"Länkar\"\n  STR_SLACKING_INDICATOR: \"{0}:{1}\"\n  STR_TRAINING_INDICATOR: \"{0}:{1}\"\n  STR_EXTENDED_UC: \"UTÖKAT\"\n  STR_ESCORTING: \"ESKORTERAR\"\n  STR_PILOT_MISSING: \"PILOT SAKNAS\"\n  STR_DAY_SHORT: \"{0}d\"\n  STR_HOUR_SHORT: \"{0}h\"\n  STR_WE_CAN_NOW_RENT: \"Vi kan nu hyra\"\n  STR_WE_CAN_NOW_BUILD: \"Vi kan nu bygga\"\n  STR_WE_CAN_NOW_PURCHASE: \"Vi kan nu köpa\"\n  STR_INFO: \"INFO\"\n  STR_IGNORE_UC: \"IGNORERA\"\n  STR_UPDATE: \"Uppdatera\"\n  STR_OPEN_MODS_FOLDER: \"Öppna\"\n  STR_PATH_ENERGY_COST: \"Energi\"\n  STR_TEST_SCREEN: \"TESTSKÄRM\"\n  STR_PALETTE: \"Palett:\"\n  STR_PREVIEW: \"Förhandsvisa\"\n  STR_SMALL_LOW_CONTRAST: \"Liten\"\n  STR_BIG_LOW_CONTRAST: \"Stor\"\n  STR_TESTS_STARTING: \"Startar...\"\n  STR_TESTS_NO_ERRORS_FOUND: \"Inga fel hittades.\"\n  STR_RANK_NONE: \"-\"\n  STR_DAMAGE_NONE: \"INGEN\"\n  STR_INFO_UFOPEDIA: \"INFO\"\n  STR_CLIP_SIZE_UNLIMITED: \"obegränsat\"\n  STR_SHOTGUN_BEHAVIOR_OXCE: \"utökat\"\n  STR_INCLUDE_DEBUG: \"FELSÖK\"\n  STR_TRUE: \"sant\"\n  STR_FALSE: \"falskt\"\n  STR_COST_TIME: \"tid\"\n  STR_COST_ENERGY: \"energi\"\n  STR_COST_MORALE: \"moral\"\n  STR_COST_HEALTH: \"hälsa\"\n  STR_DAMAGE_10: \"10\"\n  STR_DAMAGE_11: \"11\"\n  STR_DAMAGE_12: \"12\"\n  STR_DAMAGE_13: \"13\"\n  STR_DAMAGE_14: \"14\"\n  STR_DAMAGE_15: \"15\"\n  STR_DAMAGE_16: \"16\"\n  STR_DAMAGE_17: \"17\"\n  STR_DAMAGE_18: \"18\"\n  STR_DAMAGE_19: \"19\"\n  STR_NAUTICAL_MILES: \"{0} sjömil\"\n  STR_KILOMETERS_PER_HOUR: \"{0} km/h\"\n  STR_SECONDS_LONG: \"{0} sekunder\"\n  STR_FOR_DIFFICULTY: \"för svårighetsgrad: {0}\"\n"
  },
  {
    "path": "bin/common/Language/OXCE/uk.yml",
    "content": "uk:\n  STR_CANNOT_DISMANTLE_FACILITY_UPGRADING: \"НЕ МОЖНА РОЗБИРАТИ ОБ'ЄКТ!{SMALLLINE}Об’єкт не можна видалити під час оновлення.\"\n  STR_CANNOT_UPGRADE_FACILITY_ALREADY_UPGRADING: \"НЕ МОЖНА БУДУВАТИ ТУТ!{SMALLLINE}Існуючий об’єкт уже тут будується.\"\n  STR_CANNOT_UPGRADE_FACILITY_WRONG_SIZE: \"НЕ МОЖНА БУДУВАТИ ТУТ!{SMALLLINE}Вибраний об’єкт повинен повністю покривати існуючий об’єкт.\"\n  STR_CANNOT_UPGRADE_FACILITY_WRONG_TYPE: \"НЕ МОЖНА БУДУВАТИ ТУТ!{SMALLLINE}Існуючий об’єкт не може бути оновлений вибраним об’єктом.\"\n  STR_CANNOT_UPGRADE_FACILITY_DISALLOWED: \"НЕ МОЖНА БУДУВАТИ ТУТ!{SMALLLINE}Існуючий об’єкт неможливо покращити.\"\n  STR_CANNOT_BUILD_QUEUE_OFF: \"НЕ МОЖНА БУДУВАТИ ТУТ!{SMALLLINE}Спочатку необхідно завершити будівництво сполучних об'єктів.\"\n  STR_FACILITY_FORBIDDEN_BY_OTHER: \"НЕ МОЖНА БУДУВАТИ ТУТ!{SMALLLINE}Деякі існуючі об’єкти забороняють будівництво цього об’єкта.\"\n  STR_FACILITY_OTHER_FORBIDDEN_BY_THIS: \"НЕ МОЖНА БУДУВАТИ ТУТ!{SMALLLINE}Деякі існуючі об’єкти конфліктують із цим об'єктом.\"\n  STR_NOT_ENOUGH_ITEMS: \"НЕДОСТАТНЬО МАТЕРІАЛІВ!{SMALLLINE}Нам необхідно більше ресурсів для будівництва цього об’єкта.{NEWLINE}Відсутні> {0}: {1}\"\n  STR_ID: \"ID\"\n  STR_FIRST_LETTER: \"ПЕРША ЛІТЕРА\"\n  STR_SOLDIER_TYPE: \"ТИП БІЙЦЯ\"\n  STR_IDLE_DAYS: \"ДНІ БЕЗДІЯЛЬНОСТІ\"\n  STR_MANA: \"МАНА\"\n  STR_MANA_POOL: \"ЗАПАС МАНИ\"\n  STR_MANA_MISSING: \"МАНА ВІДСУТНЯ\"\n  STR_LOAD_CRAFT_LOADOUT_TEMPLATE: \"Завантажити корабельне спорядження\"\n  STR_EMPTY_SLOT_N: \"Пустий слот {0}\"\n  STR_UNNAMED_SLOT_N: \"Безіменний слот {0}\"\n  STR_ADD_ON_TOP: \"Додати до існуючої\"\n  STR_SAVE_CRAFT_LOADOUT_TEMPLATE: \"Зберегти корабельне спорядження\"\n  STR_SAVE_UC: \"ЗБЕРЕГТИ\"\n  STR_ALL: \"Усе\"\n  STR_EQUIPPED: \"Оснащений\"\n  STR_NOT_EQUIPPED: \"Не оснащений\"\n  STR_UNASSIGNED: \"Інше\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED_BY_SIZE: \"ПЕРЕВИЩЕНО МАКСИМАЛЬНИЙ РІВЕНЬ ОСНАЩЕННЯ НА КОРАБЛІ!{SMALLLINE}Максимальне місце для зберігання: {0}\"\n  STR_PILOTS: \"ПІЛОТИ\"\n  STR_SHIELD: \"ЩИТ>{ALT}{0}\"\n  STR_CRAFT_SKIN_ID: \"[{0}]\"\n  STR_SELECT_PILOT: \"Виберіть пілота\"\n  STR_PILOTS_FOR_CRAFT: \"Пілот(и) для {0}\"\n  STR_PILOTS_REQUIRED: \"Пілотів необхідно: {ALT}{0}\"\n  STR_ADD_PILOT: \"Додати Пілота\"\n  STR_REMOVE_ALL_PILOTS: \"Видалити Всіх Пілотів\"\n  STR_ACCURACY_BONUS: \"Бонус точності:\"\n  STR_DODGE_BONUS: \"Бонус ухилення:\"\n  STR_APPROACH_SPEED: \"Швидкість наближення:\"\n  STR_COWARDLY: \"Боягузливий (-50%)\"\n  STR_NORMAL: \"Нормальний\"\n  STR_BOLD: \"Відважний (+50%)\"\n  STR_VERY_BOLD: \"Дуже відважний (+100%)\"\n  STR_SOLDIER_GROUP_NOT_ALLOWED: \"Цей тип солдатів не допускається на борт.\"\n  STR_SOLDIER_GROUP_NOT_SAME: \"Цей тип солдата не сумісний з іншими солдатами на борту.\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW: \"Попередній перегляд\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_SAVED: \"Передперегляд *\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_BRIEFING: \"Дозволяє переглядати і змінювати схему висадки бойових одиниць гравця перед початком операції. Кількість ОД не обмежена. Щоб відобразити доступні точки висадки, натисніть Alt. Щоб зберегти схему, натисніть кнопку «Покинути поле бою». Щоб вийти з режиму перегляду схеми, натисніть кнопку \\\"Закінчити хід\\\".{NEWLINE}Призначення нових бійців або техніки в ТЗ автоматично анулює збережену схему висадки. Наявність індивідуальної схеми висадки відображається знаком '*' на кнопці «Передперегляд».\"\n  STR_CRAFT_DEPLOYMENT_PREVIEW_BRIEFING_DUMMY: \"Ця функція дає змогу переглядати і змінювати схему розміщення бійців на ТЗ конкретного типу. Зміни застосовуються до всіх наявних ТЗ, а також до куплених або вироблених надалі. Для розміщення видається максимально можливе число бійців для обраного ТЗ. Один боєць відповідає одному ряду в схемі розміщення. Імена бійців збігаються з номером ряду. Щоб розмістити бойову одиницю, що займає 2х2 тайла, розставте 4 бійців у квадраті 2х2. Якщо цього не зробити, бойова одиниця розміром 2х2 не з'явиться на полі бою в тактичній фазі гри.\"\n  STR_BASE_DEFENSE_BRIEFING_PREVIEW: \"Ця опція дає змогу переглядати базу в тактичному режимі. {NEWLINE}{NEWLINE}Для виходу з режиму перегляду натисніть кнопку «Покинути поле бою».\"\n  STR_NOT_ENOUGH_CARGO_SPACE: \"НЕМАЄ ДОСТАТНЬО МІСЦЯ ДЛЯ ВАНТАЖУ! {SMALLLINE}Використайте інший модуль або зменшіть кількість членів екіпажу.\"\n  STR_NOT_ENOUGH_STORAGE_SPACE_1: \"НЕ ДОСТАТНЬО МІСЦЯ ДЛЯ ЗБЕРІГАННЯ! {SMALLLINE}Занадто багато елементів! Використовуйте інший модуль або зменшіть кількість призначеного обладнання.\"\n  STR_NOT_ENOUGH_STORAGE_SPACE_2: \"НЕ ДОСТАТНЬО МІСЦЯ ДЛЯ ЗБЕРІГАННЯ! {SMALLLINE}Елементи займають забагато місця! Використовуйте інший модуль або зменшіть розмір призначеного обладнання.\"\n  STR_REFUND_VALUE: \"Вартість продажу> {ALT}{0}\"\n  STR_PRODUCTION_OVERVIEW: \"ОГЛЯД ВИРОБНИЦТВА\"\n  STR_RESEARCH_OVERVIEW: \"ОГЛЯД ДОСЛІДЖЕНЬ\"\n  STR_PRISONER_OVERVIEW: \"ОГЛЯД В'ЯЗНІВ\"\n  STR_PRISONER: \"УВ'ЯЗНЕНИЙ\"\n  STR_PRISONER_AMOUNT: \"СУМА\"\n  STR_PRISONER_INTERROGATED: \"ДОПИТАНО\"\n  STR_TOTAL_IN_PRISON: \"Використаний простір>{ALT}{0}\"\n  STR_TOTAL_INTERROGATED: \"Допитаний>{ALT}{0}\"\n  STR_PRISON_TYPE: \"Утримання чужорідних істот\"\n  STR_KILL_SELECTED: \"Вбити\"\n  STR_SELL_SELECTED: \"Продати\"\n  STR_GO_TO_TRANSFERS: \"Транспортування...\"\n  STR_PRISON_CLEANUP: \"Звільнити камери\"\n  STR_TOPIC: \"Предмет>{ALT} {0}\"\n  STR_SHOW_ALL: \"Показати все\"\n  STR_NO_DEPENDENCIES: \"Немає залежностей.\"\n  STR_DIRECT_DEPENDENCIES: \"Прямі залежності\"\n  STR_LEVEL_2_DEPENDENCIES: \"Залежності 2-го рівня\"\n  STR_LEVEL_3_DEPENDENCIES: \"Залежності 3-го рівня\"\n  STR_LEVEL_4_DEPENDENCIES: \"Залежності 4-го рівня\"\n  STR_MORE_DEPENDENCIES: \"Існують ще більш глибокі залежності...\"\n  STR_END_OF_SEARCH: \"Кінець пошуку.\"\n  STR_REFUND_PRODUCTION: \"ПОВЕРНЕННЯ!\"\n  STR_HOURS_PER_UNIT: \"ГОДИН НА ОДИНИЦЮ>{ALT}{0}\"\n  STR_PERSON_JOINING: \"Приєднання особи\"\n  STR_RANDOM_PRODUCTION_DISCLAIMER: \"Випадкове виробництво!\"\n  STR_OTHER_EMPLOYEES: \"Інший персонал та інвентар\"\n  STR_SHOW_ONLY_NEW: \"Показати лише нове\"\n  STR_FILTER_DEFAULT: \"За замовчуванням\"\n  STR_FILTER_DEFAULT_SUPPLIES_OK: \"За замовчуванням (витратні матеріали в порядку)\"\n  STR_FILTER_DEFAULT_NO_SUPPLIES: \"За замовчуванням (немає витратних матеріалів)\"\n  STR_FILTER_FACILITY_REQUIRED: \"Об’єкт відсутній\"\n  STR_FILTER_HIDDEN: \"Приховано\"\n  STR_FILTER_EQUIPPED: \"Оснащений\"\n  STR_FILTER_MISSING: \"Недостача\"\n  STR_SORT_DEFAULT: \"За замовчуванням\"\n  STR_SORT_BY_COST: \"За вартістю\"\n  STR_SORT_BY_NAME: \"За назвою\"\n  STR_RANDOM_PRODUCTION_SUMMARY: \"Резюме\"\n  STR_NOT_ENOUGH_PRISON_SPACE: \"НЕДОСТАТНЬО ТЮРЕМ ДЛЯ УТРИМАННЯ ПРИБУЛЬЦІВ{SMALLLINE}Побудуйте нові тюрми для прибульців або перенаправте прибульців на інші бази.\"\n  STR_MONTHLY_ITEM_PURCHASE_LIMIT_EXCEEDED: \"ЛІМІТ НА ЩОМЕСЯЧНИЙ ОБСЯГ ЗАКУПІВЛЕЙ ВИЧЕРПАНО!{SMALLLINE}Можливість купівлі обраних товарів з'явиться в наступному місяці.\"\n  STR_MONTHLY_CRAFT_PURCHASE_LIMIT_EXCEEDED: \"ЛІМІТ НА ЩОМЕСЯЧНИЙ ОБСЯГ ЗАКУПІВЛЕЙ ВИЧЕРПАНО!{SMALLLINE}Можливість купівлі обраних ТЗ з'явиться в наступному місяці.\"\n  STR_MONTHLY_SOLDIER_HIRING_LIMIT_EXCEEDED: \"ЛІМІТ НА ЩОМЕСЯЧНИЙ НАЙМ ВИЧЕРПАНО!{SMALLLINE}Можливість найму новобранців з'явиться в наступному місяці.\"\n  STR_NOT_ENOUGH_CRAFT_SPACE: \"Не вистачає місця на борту!\"\n  STR_SELECT_AVATAR_FOR: \"ВИБЕРІТЬ АВАТАР ДЛЯ{NEWLINE}{0}\"\n  STR_SOLDIER_BONUSES_FOR: \"БІЙЦІВСЬКІ БОНУСИ ДЛЯ{NEWLINE}{0}\"\n  STR_SUMMARY: \"Резюме\"\n  STR_MANA_RECOVERY: \"ВІДНОВЛЕННЯ МАНИ> {ALT}{0}\"\n  STR_HEALTH_RECOVERY: \"ВІДНОВЛЕННЯ ЗДОРОВ'Я> {ALT}{0}\"\n  STR_BONUSES_BUTTON: \"+\"\n  STR_PROMOTE_SOLDIER: \"ПІДВИЩИТИ/ЗНИЗИТИ{NEWLINE}{0} {1}\"\n  STR_RANK_HEADER: \"ЗВАННЯ\"\n  STR_OPENINGS_HEADER: \"ВІДКРИТТЯ\"\n  STR_KILLER_AND_WEAPON: \"{0}, {1}\"\n  STR_TRAINING: \"Тренування\"\n  STR_SOLDIER_INFO: \"Інформація про бійця\"\n  STR_SELECT_TRANSFORMATION_FOR: \"ВИБРАТИ ПЕРЕТВОРЕННЯ ДЛЯ{NEWLINE}{0}\"\n  STR_TRANSFORMATIONS_BUTTON: \"^\"\n  STR_TRANSFER_TIME: \"Час доставки>{ALT}{0}\"\n  STR_RECOVERY_TIME: \"Час відновлення>{ALT}{0}\"\n  STR_CURRENT_STATS: \"Поточна статистика\"\n  STR_CHANGES: \"Зміни\"\n  STR_CHANGES_MIN: \"Зміни (мін)\"\n  STR_CHANGES_MAX: \"Зміни (макс)\"\n  STR_BONUS_STATS: \"Бонусна статистика\"\n  STR_TRANSFORMATIONS_OVERVIEW: \"Огляд Трансформацій\"\n  STR_PROJECT_NAME: \"НАЗВА ПРОЕКТУ\"\n  STR_AVAILABLE_MATERIALS: \"ДОСТУПНІ МАТЕРІАЛИ\"\n  STR_ELIGIBLE_SOLDIERS: \"ПІДХОДЯЩІ СОЛДАТИ\"\n  STR_SHOW_ONLY_ELIGIBLE: \"Показати лише підходящих\"\n  STR_ALL_SOLDIER_TYPES: \"Усі типи бійців\"\n  STR_ALL_SOLDIERS: \"Усі бійці\"\n  STR_HEALTHY_SOLDIERS: \"Здорові бійці\"\n  STR_WOUNDED_SOLDIERS: \"Поранені бійці\"\n  STR_DEAD_SOLDIERS: \"Мертві бійці\"\n  STR_GRAND_TOTAL: \"Загальна сума\"\n  STR_AVAILABLE_TOPICS: \"ДОСТУПНІ ТЕМИ\"\n  STR_QS_THREE_LETTERS_A: \"Будь ласка, введіть принаймні 3 літери\"\n  STR_QS_THREE_LETTERS_B: \"у вікні швидкого пошуку...\"\n  STR_M_FLAG: \" [м]\"\n  STR_F_FLAG: \" [фут]\"\n  STR_I_FLAG: \" [дюйм]\"\n  STR_C_FLAG: \"[ТЗ]\"\n  STR_THIS_FEATURE_IS_DISABLED_1: \"Ця функція відключена.\"\n  STR_THIS_FEATURE_IS_DISABLED_2: \"Ця функція відключена.\"\n  STR_THIS_FEATURE_IS_DISABLED_3: \"Ця функція відключена.\"\n  STR_THIS_FEATURE_IS_DISABLED_4: \"Ця функція відключена.\"\n  STR_THIS_FEATURE_IS_DISABLED_5: \"Ця функція відключена.\"\n  STR_TECH_TREE_VIEWER: \"Перегляд технологічного дерева\"\n  STR_SELECT_TOPIC: \"Виберіть тему\"\n  STR_RESEARCH_PROGRESS: \"Прогрес>{ALT} {0}%\"\n  STR_ITEM_DESTROYED: \"Предметів знищено:\"\n  STR_ITEM_REQUIRED: \"Предметів необхідно:\"\n  STR_SERVICES_REQUIRED: \"Необхідні послуги:\"\n  STR_SERVICES_PROVIDED: \"Послуги, що надаються:\"\n  STR_SERVICES_FORBIDDEN: \"Заборонені послуги:\"\n  STR_REQUIRES: \"Вимагає:\"\n  STR_DEPENDS_ON: \"Залежить від:\"\n  STR_UNLOCKED_BY: \"Розблоковано:\"\n  STR_DISABLED_BY: \"Вимкнено:\"\n  STR_REENABLED_BY: \"Повторно ввімкнено:\"\n  STR_GET_FOR_FREE_FROM: \"Отримати безкоштовно від:\"\n  STR_IS_LOOKUP_OF: \"Чи шукати за:\"\n  STR_LOOKUP: \"Пошук:\"\n  STR_SPAWNED_ITEMS: \"Породжені предмети:\"\n  STR_SPAWNED_EVENT: \"Породжена подія:\"\n  STR_REQUIRED_BY: \"Потрібно для:\"\n  STR_REQUIRED_BY_TRANSFORMATIONS: \"Вимагається трансформаціями:\"\n  STR_LEADS_TO: \"Призводить до:\"\n  STR_UNLOCKS: \"Розблоковує:\"\n  STR_DISABLES: \"Вимикає:\"\n  STR_REENABLES: \"Повторно вмикає:\"\n  STR_GIVES_ONE_FOR_FREE_SEQ: \"Надає один безкоштовно (послідовно):\"\n  STR_GIVES_ONE_FOR_FREE: \"Надає один безкоштовно:\"\n  STR_RESEARCH_REQUIRED: \"Необхідні дослідження:\"\n  STR_RESEARCH_REQUIRED_USE: \"Необхідні дослідження (використати):\"\n  STR_RESEARCH_REQUIRED_BUY: \"Необхідні дослідження (купити):\"\n  STR_SERVICES_REQUIRED_BUY: \"Необхідні послуги (купити):\"\n  STR_PRODUCED_BY: \"Вироблено:\"\n  STR_SPAWNED_BY: \"Породжено:\"\n  STR_MATERIALS_REQUIRED: \"Необхідні матеріали:\"\n  STR_TTV_COST_PER_UNIT: \"Вартість за од.:\"\n  STR_TTV_ENGINEER_HOURS: \"Людино-годин:\"\n  STR_TTV_WORK_SPACE_REQUIRED: \"Наявність місця у майстернях:\"\n  STR_ITEMS_PRODUCED: \"Виготовлені предмети:\"\n  STR_PERSON_RECRUITED: \"Найнята особа:\"\n  STR_UNLOCKS_ARCS: \"Розблоковані дуги:\"\n  STR_DISABLES_ARCS: \"Вимкнені дуги:\"\n  STR_UNLOCKS_MISSIONS: \"Відкриває місії:\"\n  STR_DISABLES_MISSIONS: \"Блокує місії:\"\n  STR_UNLOCKS_EVENTS: \"Розблоковує події:\"\n  STR_DISABLES_EVENTS: \"Блокує події:\"\n  STR_AFFECTS_GAME_PROGRESSION: \"Впливає на прогрес гри!\"\n  STR_ITEMS_AT_DESTINATION: \"Предмети за призначенням\"\n  STR_PRISONERS: \"В'язні\"\n  STR_ARMORS: \"Броня\"\n  STR_CRAFT_DEPLOYMENT_QUESTION: \"Зберігти схему висадки?\"\n  STR_MUST_USE_BOTH_HANDS: \"Для цього потрібні обидві руки!\"\n  STR_NOT_ENOUGH_MORALE: \"Не вистачає моралі!\"\n  STR_NOT_ENOUGH_HEALTH: \"Недостатньо здоров'я!\"\n  STR_NOT_ENOUGH_MANA: \"Не вистачає мани!\"\n  STR_NOT_ENOUGH_STUN: \"Рівень оглушення надто високий!\"\n  STR_MIND_CONTROL_SUCCESSFUL_ALT: \"Дію виконано успішно\"\n  STR_LINE_OF_SIGHT_REQUIRED: \"Необхідна лінія видимості (ЛВ).\"\n  STR_CENTER_ON_WOUNDED_FRIEND: \"Центр Пораненого Союзника\"\n  STR_CENTER_ON_DIZZY_FRIEND: \"Центр Приголомшеного Союзника\"\n  STR_BUG_HUNT_ACTIVATED: \"Активовано режим полювання: на міні-карті видно ворогів!\"\n  STR_QUICK_MODE_ACTIVATED: \"Режим Усейна Болта активовано.{NEWLINE}Для деактивації натисніть Ctrl+S ще раз.\"\n  STR_QUICK_MODE_DEACTIVATED: \"Режим Усейна Болта деактивовано.\"\n  STR_TARGET_ENEMY: \"; Ціль = ВОРОГ\"\n  STR_TARGET_NEUTRAL: \"; Ціль = НЕЙТРАЛ\"\n  STR_TARGET_FRIEND: \"; Ціль = ДРУГ\"\n  STR_TARGET_YOURSELF: \"; Ціль = Я\"\n  STR_TARGET_ON_THE_GROUND: \" (на землі)\"\n  STR_USE_SPECIAL_ITEM: \"Використовуйте спеціальний предмет\"\n  STR_NO_EXPERIENCE_YET: \"Недостатньо досвіду:\"\n  STR_OPERATION_UC: \"БИТВА> {0}\"\n  STR_WHAT_CAN_I_WEAR: \"Що я можу носити?\"\n  STR_STARTING_CONDITION_ARMORS_FORBIDDEN: \"Для цієї місії неохбідне спеціальне спорядження.{NEWLINE}{NEWLINE}Заборонені типи броні: {0}\"\n  STR_STARTING_CONDITION_ARMORS_ALLOWED: \"Для цієї місії неохбідне спеціальне спорядження.{NEWLINE}{NEWLINE}Дозволені типи броні: {0}\"\n  STR_MISSION_OVER: \"Завдання виконано.\"\n  STR_UNITS_WITH_FATAL_WOUNDS:\n    one: \"{N} з нас досі смертельно поранений\"\n    few: \"{N} з нас досі смертельно поранені\"\n    many: \"{N} з нас досі смертельно поранені\"\n    other: \"{N} з нас досі смертельно поранені\"\n  STR_END_MISSION_QUESTION: \"Завершити місію?\"\n  STR_LOOT: \"ЗДОБИЧ\"\n  STR_SELL: \"ПРОДАЖ\"\n  STR_LIVE_ALIENS_SURRENDERED: \"ВОРОГИ ЗДАЛИСЯ\"\n  STR_MISSION_ABORTED: \"МІСІЮ ПЕРЕРВАНО\"\n  STR_VIPS_SAVED: \"VIP-ів ВРЯТОВАНО\"\n  STR_VIPS_LOST: \"VIP-ів ВТРАЧЕНО\"\n  STR_BOUNTY: \"НАГОРОДА\"\n  STR_MANA_ABBREVIATION: \"ЛЮДИНА\"\n  STR_EXPERIENCE_OVERVIEW: \"Огляд досвіду\"\n  STR_CANNOT_PLACE_ITEM_INTO_THIS_SECTION: \"Не дозволяється розміщувати цей елемент там.{NEWLINE}Не питайте чому!\"\n  STR_ONE_HAND_MUST_BE_EMPTY: \"Принаймні одна рука повинна бути порожньою!\"\n  STR_LOAD_EQUIPMENT_TEMPLATE: \"Завантажити шаблон оснащення\"\n  STR_SAVE_EQUIPMENT_TEMPLATE: \"Зберегти шаблон оснащення\"\n  STR_FIRING_SHORT: \"Стрільба>{ALT}{0}\"\n  STR_THROWING_SHORT: \"Метання>{ALT}{0}\"\n  STR_MELEE_SHORT: \"Рукопашний бій>{ALT}{0}\"\n  STR_PERSONAL_EQUIPMENT: \"ОСОБИСТЕ ОБМУНДИРУВАННЯ\"\n  STR_SAVE_PERSONAL_EQUIPMENT: \"Зберегти особисте обмундирування\"\n  STR_LOAD_PERSONAL_EQUIPMENT: \"Завантажити особисте обмундирування\"\n  STR_PERSONAL_EQUIPMENT_SAVED: \"Особисте обмундирування збережено.\"\n  STR_PERSONAL_EQUIPMENT_NOT_DEFINED: \"Особисте спорядження ще не визначено.\"\n  STR_SLOT: \"Слот>{ALT}{0}\"\n  STR_THINKING: \"Обмірковування...\"\n  STR_TELL_ME_MORE: \"Розкажи мені більше...\"\n  STR_REINFORCEMENTS_ALERT: \"Попередження про підкріплення!\"\n  STR_HIT_LOG_NEW_TURN: \"Новий хід\"\n  STR_FAILED_CQB_CHECK: \"Ворогам вдалося перервати вашу атаку!\"\n  STR_NO_TRAJECTORY: \"Немає допустимої траєкторії!\"\n  STR_HIT_LOG_NEW_BULLET: \"=> \"\n  STR_MANA_SHORT: \"НМ>{ALT}{0}\"\n  STR_SKILL_NEEDS_ITEM: \"Для цього вміння потрібен предмет!\"\n  STR_HIT_LOG_NO_DAMAGE: \"0 \"\n  STR_HIT_LOG_SMALL_DAMAGE: \"удар\"\n  STR_HIT_LOG_BIG_DAMAGE: \"УДАР\"\n  STR_HIT_LOG_REACTION_FIRE: \"Реакційний вогонь...\"\n  STR_HIT_LOG: \"Журнал влучань\"\n  STR_BUTTON_10: \"10\"\n  STR_LAZY_LOADING: \"Ліниве завантаження\"\n  STR_LAZY_LOADING_DESC: \"Якщо цей параметр увімкнено, графічні ресурси завантажуються по мірі необхідності. В іншому випадку все завантажується при запуску.\"\n  STR_VSYNC_FOR_OPENGL: \"VSync для OpenGL\"\n  STR_VSYNC_FOR_OPENGL_DESC: \"Вимкніть для максимальної прихованої швидкості руху противника та (необов’язково) швидкості руху солдата. НЕ встановлюйте обмеження FPS на 0. Це стосується лише рендеринга OpenGL.\"\n  STR_UPDATE_CHECK: \"Автоматична перевірка оновлення\"\n  STR_UPDATE_CHECK_DESC: \"Якщо цей параметр увімкнено, OpenXcom автоматично перевірить наявність оновлень і надасть вам можливість оновити себе одним натисканням кнопки.\"\n  STR_AUTOSAVE_SLOTS: \"Слоти автозбереження\"\n  STR_AUTOSAVE_SLOTS_DESC: \"Кількість слотів для автозбережень поля бою.\"\n  STR_AUTO_SAVE_BATTLESCAPE_SLOT_WITH_NUMBER: \"<AUTO BATTLESCAPE> {0}\"\n  STR_GEO_AUTOSAVE_FREQUENCY: \"Частота Автозбереження (Глобус)\"\n  STR_GEO_AUTOSAVE_FREQUENCY_DESC: \"Кількість днів, через яку гра буде автоматично збережена.\"\n  STR_GEO_AUTOSAVE_SLOTS: \"Автозбереження слотів (Глобус)\"\n  STR_GEO_AUTOSAVE_SLOTS_DESC: \"Кількість слотів для автозбережень на Глобусі.\"\n  STR_AUTO_SAVE_GEOSCAPE_SLOT_WITH_NUMBER: \"<AUTO GEOSCAPE> {0}\"\n  STR_OXCE_LINKS: \"Розширені посилання\"\n  STR_OXCE_LINKS_DESC: \"Вмикає додаткові меню/кнопки/посилання для функцій OXCE.\"\n  STR_PEDIA_SHOW_CLIP_SIZE: \"Показати розмір магазину в Уфопедії\"\n  STR_PEDIA_SHOW_CLIP_SIZE_DESC: \"Якщо увімкнено, розміри боєприпасів відображатимуться поруч зі значками боєприпасів в Уфопедії.\"\n  STR_INTERCEPT_TABLE_SIZE: \"Розмір таблиці перехоплення\"\n  STR_INTERCEPT_TABLE_SIZE_DESC: \"Розміри таблиць у наступних діалогових вікнах: Перехоплення, Трекер НЛО.\"\n  STR_SHOW_SLACKING_INDICATOR: \"Показати індикатор простоювання\"\n  STR_SHOW_SLACKING_INDICATOR_DESC: \"Якщо увімкнено, буде показано кількість непризначених науковців та інженерів.\"\n  STR_SHOW_MAINTENANCE_TIME: \"Показати час обслуговування судна\"\n  STR_SHOW_MAINTENANCE_TIME_DESC: \"{ALT}0>{ALT} Не показувати {ALT}1>{ALT} Показувати лише тривалість поточної активності {ALT}2>{ALT} Показувати все разом (ремонт + переозброєння + заправка).\"\n  STR_SHOW_ETA: \"Показати приблизну тривалість польоту\"\n  STR_SHOW_ETA_DESC: \"{ALT}0>{ALT} Не показувати {ALT}1>{ALT} Показувати ПТП тільки для статичних цілей {ALT}2>{ALT} Показувати ПТП також для рухомих цілей.\"\n  STR_UFO_LANDING_ALERT: \"Сповіщення про посадку НЛО\"\n  STR_UFO_LANDING_ALERT_DESC: \"Якщо цей параметр увімкнено, повідомлення з'являтиметься щоразу, коли виявиться НЛО.\"\n  STR_REMEMBER_DISABLED_CRAFT_WEAPONS: \"Запам'ятовувати вимкнену корабельну зброю\"\n  STR_REMEMBER_DISABLED_CRAFT_WEAPONS_DESC: \"Корабельна зброя, вимкнена під час повітряного бою, залишиться вимкненою. Вона також не буде перезаряджена на базі.\"\n  STR_GEO_EVENT_INSTANT_DELIVERY: \"Миттєва доставка товарів на події\"\n  STR_GEO_EVENT_INSTANT_DELIVERY_DESC: \"Якщо увімкнено, елементи з подій геоландшафту надходять миттєво. В іншому випадку вони з'являються на 1 годину пізніше.\"\n  STR_SHOW_BASE_NAME_IN_POPUPS: \"Показувати назву бази у спливаючих вікнах\"\n  STR_SHOW_BASE_NAME_IN_POPUPS_DESC: \"Якщо увімкнено, відповідна назва бази відображається у спливаючих вікнах (наприклад, «Дослідження завершено»).\"\n  STR_ALTERNATE_CRAFT_EQUIPMENT_MANAGEMENT: \"Альтернативне управління вантажним відсіком ТЗ\"\n  STR_ALTERNATE_CRAFT_EQUIPMENT_MANAGEMENT_DESC: \"Якщо увімкнено, переміщення солдатів між базою та ТЗ також переміщує їхнє спорядження (якщо це можливо).\"\n  STR_BASE_INFO_SCALE: \"Масштабування великих відрізків у полі інформації\"\n  STR_BASE_INFO_SCALE_DESC: \"Якщо увімкнено, відрізки, більші за 140, зменшуються, щоб відповідати інтерфейсу.\"\n  STR_HIGHLIGHT_NEW: \"Виділяти нові теми\"\n  STR_HIGHLIGHT_NEW_DESC: \"Якщо увімкнено, нові дослідницькі теми, нові виробничі теми та нові статті уфопедії відображаються іншим кольором.\"\n  STR_RESEARCH_SCROLL_SPEED: \"Швидкість прокручування досліджень\"\n  STR_RESEARCH_SCROLL_SPEED_DESC: \"Вчених можна призначати/звільняти безпосередньо в інтерфейсі поточних досліджень за допомогою кнопки прокрутки миші.\"\n  STR_RESEARCH_SCROLL_SPEED_CTRL: \"Швидкість прокрутки досліджень (з клавішею Ctrl)\"\n  STR_RESEARCH_SCROLL_SPEED_CTRL_DESC: \"Вчених можна призначати/звільняти безпосередньо в інтерфейсі поточних досліджень за допомогою кнопки прокрутки миші.\"\n  STR_MANUFACTURE_FILTER_SUPPLIES_OK: \"Альтернативний фільтр для виробництва\"\n  STR_MANUFACTURE_FILTER_SUPPLIES_OK_DESC: \"Якщо увімкнено, користувацький інтерфейс показує лише ті виробничі позиції, для яких є достатньо запасів.\"\n  STR_MANUFACTURE_SCROLL_SPEED: \"Швидкість прокрутки виробництва\"\n  STR_MANUFACTURE_SCROLL_SPEED_DESC: \"Інженерів можна призначати/звільняти безпосередньо в інтерфейсі поточного виробництва за допомогою кнопки прокрутки миші.\"\n  STR_MANUFACTURE_SCROLL_SPEED_CTRL: \"Швидкість прокрутки виробництва (з клавішею Ctrl)\"\n  STR_MANUFACTURE_SCROLL_SPEED_CTRL_DESC: \"Інженерів можна призначати/звільняти безпосередньо в інтерфейсі поточного виробництва за допомогою кнопки прокрутки миші.\"\n  STR_PERSONAL_LAYOUT_INCLUDING_ARMOR: \"Включити бронежилет до особистого спорядження\"\n  STR_PERSONAL_LAYOUT_INCLUDING_ARMOR_DESC: \"Якщо увімкнено, зберігається макет особистого спорядження солдата, включно із ношеною бронею.\"\n  STR_MANUALPROMOTIONS: \"Ручне підвищування\"\n  STR_MANUALPROMOTIONS_DESC: \"Якщо увімкнено, солдатів можна вручну підвищувати (або понижувати) у званні, натиснувши на іконку звання.\"\n  STR_WOUNDED_DEFEND_BASE_IF: \"Захист бази пораненими бійцями (якщо здоров'я вище x%)\"\n  STR_WOUNDED_DEFEND_BASE_IF_DESC: \"Поранені солдати також захищають базу, якщо їхнє здоров'я вище заданого відсотка.\"\n  STR_PLAY_BRIEFING_MUSIC_DURING_EQUIPMENT: \"Відтворювати музику брифінгу довше\"\n  STR_PLAY_BRIEFING_MUSIC_DURING_EQUIPMENT_DESC: \"Брифінг-музика продовжуватиме грати під час фази спорядження, поки не відобразиться поле бою.\"\n  STR_NIGHT_VISION_COLOR: \"Вибір кольору нічного бачення\"\n  STR_NIGHT_VISION_COLOR_DESC: \"Значення від 1 до 15, кожен з яких представляє інший відтінок кольору.\"\n  STR_AUTO_NIGHT_VISION_THRESHOLD: \"Поріг автоматичного нічного бачення\"\n  STR_AUTO_NIGHT_VISION_THRESHOLD_DESC: \"Якщо темніше за цей поріг, нічне бачення увімкнеться автоматично.\"\n  STR_SHOW_ACCURACY_ON_CROSSHAIR: \"Показати точність на перехресті прицілу\"\n  STR_SHOW_ACCURACY_ON_CROSSHAIR_DESC: \"{ALT}0>{ALT}Ніколи {ALT}1>{ALT}Тільки якщо увімкнено точність UFO Extender {ALT}2>{ALT}Завжди\"\n  STR_AUTO_SELL: \"Менеджер автоматичних продажів\"\n  STR_AUTO_SELL_DESC: \"На екрані продажу після завершення бою будь-які типи предметів, продані вами в попередніх боях, будуть автоматично позначені для продажу.\"\n  STR_AUTOMATICPROMOTIONS: \"Автоматичне підвищування\"\n  STR_AUTOMATICPROMOTIONS_DESC: \"Якщо увімкнено, солдати автоматично отримують підвищення після виконання місії.\"\n  STR_OFF_CENTRE_SHOOTING: \"Стрільба поза центром\"\n  STR_OFF_CENTRE_SHOOTING_DESC: \"Солдати автоматично намагатимуться трохи відрегулювати кут стрільби, якщо немає лінії вогню.\"\n  STR_CRASHED_OR_LANDED: \"Кнопка Розбився/Приземлився\"\n  STR_CRASHED_OR_LANDED_DESC: \"Якщо увімкнено, додаткова кнопка відображається на екрані «Нова битва». Також, щоб показати/приховати кнопку, натисніть F11. {ALT}0>{ALT}Відключено, {ALT}1>{ALT}Збито, {ALT}2>{ALT}Приземлено.\"\n  STR_GRAPHS_ZOOM_IN: \"Збільшення (графіки)\"\n  STR_GRAPHS_ZOOM_OUT: \"Зменшити (графіки)\"\n  STR_MARK_ALL_AS_SEEN: \"Позначити все як побачене\"\n  STR_SELL_ALL: \"Продати все\"\n  STR_SELL_ALL_BUT_ONE: \"Продати все, крім одного\"\n  STR_TRANSFER_ALL: \"Транспортувати все\"\n  STR_REMOVE_SOLDIERS_FROM_ALL_CRAFTS: \"Прибрати бійців з усіх кораблів\"\n  STR_REMOVE_SOLDIERS_FROM_CRAFT: \"Прибрати бійців з корабля\"\n  STR_REMOVE_EQUIPMENT_FROM_CRAFT: \"Прибрати обладнання з корабля\"\n  STR_REMOVE_ARMOR_FROM_ALL_CRAFTS: \"Прибрати броню з усіх кораблів\"\n  STR_REMOVE_ARMOR_FROM_CRAFT: \"Прибрати броню з корабля\"\n  STR_REMOVE_SOLDIERS_FROM_TRAINING: \"Прибрати солдатів з навчання\"\n  STR_ADD_SOLDIERS_TO_TRAINING: \"Направити бійців на тренування\"\n  STR_INVENTORY_ARMOR: \"Змінити броню\"\n  STR_INVENTORY_AVATAR: \"Змінити аватар\"\n  STR_INVENTORY_DIARY_LIGHT: \"Переглянути Щоденник Світла\"\n  STR_ACTION_ITEM_1: \"Активація предмета 1 (Мета/Використання)\"\n  STR_ACTION_ITEM_2: \"Активація предмета 2 (Знімок)\"\n  STR_ACTION_ITEM_3: \"Активація предмета 3 (Авто)\"\n  STR_ACTION_ITEM_4: \"Активація предмета 4 (Ближній бій)\"\n  STR_ACTION_ITEM_5: \"Активація предмета 5 (Кидок)\"\n  STR_INSTA_SAVE: \"Інста-збереження\"\n  STR_TOGGLE_QUICK_SEARCH: \"Переключити поле швидкого пошуку\"\n  STR_TOGGLE_NIGHT_VISION: \"Переключити режим нічного бачення\"\n  STR_HOLD_NIGHT_VISION: \"Короткочасний режим нічного бачення\"\n  STR_SELECT_MUSIC_TRACK: \"Вибрати музичний трек\"\n  STR_TOGGLE_TOUCH_BUTTONS: \"Перемикання сенсорних кнопок\"\n  STR_TOGGLE_BRIGHTNESS: \"Перемкнути яскравість (лише візуально)\"\n  STR_BRIEFING: \"Брифінг\"\n  STR_TOGGLE_DEBUG_MODE: \"Перемкнути режим налагодження\"\n  STR_DEBUG_KILL_ALL_ALIENS: \"НАЛАГОДЖЕННЯ: Вбити всіх прибульців\"\n  STR_PHYSICAL_TRAINING: \"Бойові тренування\"\n  STR_REMAINING_TRAINING_FACILITY_CAPACITY: \"З МОЖЛИВІСТЮ НАВЧАННЯ> {ALT}{0}\"\n  STR_NO_WOUNDED: \"-\"\n  STR_NO_QUEUED: \"+\"\n  STR_NO_DONE: \"ЗРОБЛЕНО\"\n  STR_NO_AMMO: \"НЕМАЄ БОЄПРИПАСІВ!\"\n  STR_START_FIRING: \"Вогонь!\"\n  STR_SKIP_FIRING: \"Впустити їх...\"\n  STR_ALIEN_MISSILES_HAVE_DAMAGED_OUR_BASE: \"Ракети інопланетян пошкодили нашу базу {0}\"\n  STR_ALIEN_MISSILES_HAVE_DESTROYED_OUR_BASE: \"Ракети інопланетян знищили нашу базу {0}\"\n  STR_STARTING_CONDITION_COMMANDER: \"Це завдання вимагає присутності командира.\"\n  STR_STARTING_CONDITION_CRAFT: \"Цей корабель не підходить для даної місії.\"\n  STR_STARTING_CONDITION_CRAFT_ALLOWED: \"Цей корабель непридатний для цієї місії.{NEWLINE}{NEWLINE}Дозволені кораблі: {0}\"\n  STR_STARTING_CONDITION_CRAFT_FORBIDDEN: \"Цей корабель непридатний для цієї місії.{NEWLINE}{NEWLINE}Заборонені кораблі: {0}\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE: \"Деякі солдати не можуть брати участь у цій місії.\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE_ALLOWED: \"Деякі солдати не можуть брати участь у цій місії.{NEWLINE}{NEWLINE}Дозволені типи солдатів: {0}\"\n  STR_STARTING_CONDITION_SOLDIER_TYPE_FORBIDDEN: \"Деякі солдати не можуть брати участь у цій місії.{NEWLINE}{NEWLINE}Заборонені типи солдатів: {0}\"\n  STR_STARTING_CONDITION_ITEM: \"Для цієї місії потрібен специфічний предмет(и):{NEWLINE}{NEWLINE}{0}\"\n  STR_NOT_ENOUGH_FUEL_TO_REACH_TARGET: \"НЕДОСТАТНЬО ПАЛЬНОГО!{SMALLLINE}Місце призначення занадто далеко для дальності польоту судна.\"\n  STR_TOO_MANY_ITEMS_ONBOARD: \"Занадто багато речей!{SMALLLINE}Цей корабель не може везти стільки речей.\"\n  STR_FOLLOW_WING_LEADER_QUESTION: \"Слідувати за лідером?\"\n  STR_ASSIGN_PILOTS: \"Призначити пілотів...\"\n  STR_NOT_ENOUGH_PILOTS: \"Недостатньо пілотів!{NEWLINE}Мінімум: {0}\"\n  STR_DAILY_PILOT_EXPERIENCE: \"Щоденний досвід пілотування\"\n  STR_UFO_SHIELD_HIT: \"ВЛУЧАННЯ У ЩИТИ!\"\n  STR_UFO_HIT_NO_DAMAGE: \"ВІДБИТТЯ ВІД КОРПУСА!\"\n  STR_UFO_SHIELD_DOWN: \"ВОРОЖІ ЩИТИ ЗНИЩЕНО!\"\n  STR_UFO_HIT_GLANCING: \"ТОЧНЕ ВЛУЧАННЯ!\"\n  STR_INTERCEPTOR_SHIELD_HIT: \"НАШІ ЩИТИ ТРИМАЮТЬСЯ!\"\n  STR_TRACTOR_BEAM_ENGAGED: \"ПРИТЯГУВАЛЬНИЙ ПРОМІНЬ УВІМКНЕНИЙ!\"\n  STR_TRACTOR_BEAM_DISENGAGED: \"ВИМКНЕННЯ ПРИТЯГУВАЛЬНОГО ПРОМЕНЮ\"\n  STR_SELF_DESTRUCT_ACTIVATED: \"САМОЗНИЩЕННЯ АКТИВОВАНО!\"\n  STR_SELF_DESTRUCT_CANCELLED: \"САМОЗНИЩЕННЯ ВІДМІНЕНО\"\n  STR_MISSILE_DAMAGED: \">>> РАКЕТУ ПОШКОДЖЕНО <<<\"\n  STR_MISSILE_DESTROYED: \">>> РАКЕТУ ЗНИЩЕНО <<<\"\n  STR_EXTENDED_LINKS: \"Посилання\"\n  STR_AUTO_PATROL: \"АВТОМАТИЧНЕ ПАТРУЛЮВАННЯ\"\n  STR_ETA: \"ETA>{ALT}{0}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_FACILITY_AT_BASE: \"Не вистачає {0}, щоб переозброїти {1} на {2}.\"\n  STR_UFO_STARTED_HUNTING: \"{0} перебуває на курсі перехоплення разом із {1}\"\n  STR_CRAFT_IS_READY: \"{0} на {1} готовий.\"\n  STR_ECONOMY_WARNING: \"Кошти {0} та дохід {1} низькі, а утримання {2} занадто велике! Продайте щось, щоб не брати кредит ... коштів не вистачає: {3}\"\n  STR_SLACKING_INDICATOR: \"{0}:{1}\"\n  STR_TRAINING_INDICATOR: \"{0}:{1}\"\n  STR_EXTENDED_UC: \"РОЗШИРЕНО\"\n  STR_RETURNING: \"ПОВЕРНЕННЯ\"\n  STR_INTERCEPTING: \"ПЕРЕХОПЛЕННЯ\"\n  STR_ESCORTING: \"СУПРОВІД\"\n  STR_EN_ROUTE: \"В ДОРОЗІ\"\n  STR_PILOT_MISSING: \"ПІЛОТ ВІДСУТНІЙ\"\n  STR_DAY_SHORT: \"{0}дн.\"\n  STR_HOUR_SHORT: \"{0}год.\"\n  STR_PERFORMANCE_BONUS: \"Бонус продуктивності\"\n  STR_COUNTRY_HAS_CANCELLED_A_SECRET_PACT: \"{0} відмовилася від договору з інопланетними силами і їй було дозволено повернутися до проекту.\"\n  STR_COUNTRIES_HAVE_CANCELLED_A_SECRET_PACT: \"{0} відмовилися від договору з інопланетними силами і їм було дозволено повернутися до проекту.\"\n  STR_WE_CAN_NOW_RENT: \"Тепер ми можемо орендувати\"\n  STR_REQUIRED_BASE_SERVICES: \"Необхідні базові послуги: {0}\"\n  STR_WE_CAN_NOW_BUILD: \"Тепер ми можемо будувати\"\n  STR_WE_CAN_NOW_PURCHASE: \"Тепер ми можемо придбати\"\n  STR_NOT_ENOUGH_LIVING_SPACE_AT_BASE: \"Недостатньо житлової площі для розміщення{NEWLINE}{0}{NEWLINE}у{NEWLINE}{1}\"\n  STR_INFO: \"ІНФОРМАЦІЯ\"\n  STR_DESPAWN_PENALTY: \"Штраф за зникнення> {0}\"\n  STR_TRAINING_FINISHED: \"Навчання завершено{NEWLINE}в {0}\"\n  STR_PSI_TRAINING_FINISHED: \"PSI-навчання завершено {NEWLINE}в {0}\"\n  STR_IGNORE_UC: \"ІГНОРУВАТИ\"\n  STR_UFO_TRACKER: \"НЛО шукач\"\n  STR_UPDATE: \"Оновлення\"\n  STR_LATEST_VERSION_INFO: \"Ви використовуєте останню версію OpenXcom.\"\n  STR_MASTER_MOD_VERSION_REQUIRED_QUESTION: \"Для коректної роботи цього моду потрібна базова гра v{0}. Увімкнути цей мод?\"\n  STR_VERSION_REQUIRED_QUESTION: \"Дана модифікація вимагає OXCE v{0} для правильного запуску. Увімкнути цю модифікацію?\"\n  STR_OPEN_MODS_FOLDER: \"Відкрити\"\n  STR_GLOBE_TEXTURE: \"Текстура глобуса\"\n  STR_NOTES: \"Примітки\"\n  STR_NEW_NOTE: \"<NEW NOTE>\"\n  STR_ENGINE_OXC: \"OXC\"\n  STR_ENGINE_OXCE: \"OXCE\"\n  STR_ENGINE_OTHER: \"ІНШЕ\"\n  STR_BASESCAPE: \"Базовий ландшафт\"\n  STR_AI: \"ШІ\"\n  STR_PATH_ENERGY_COST: \"Енергія\"\n  STR_PATH_ENERGY_COST_DESC: \"Натиснувши, ви побачите, скільки енергії залишиться у вашої бойової одиниці після переміщення до місця призначення.\"\n  STR_VEHICLES_LOST: \"Втрачені транспортні засоби\"\n  STR_TEST_SCREEN: \"ТЕСТОВИЙ ЕКРАН\"\n  STR_PALETTE: \"Палітра:\"\n  STR_PREVIEW: \"Попередній перегляд\"\n  STR_TINY_BORDERLESS: \"Крихітний, без меж\"\n  STR_TINY_BORDER: \"Крихітний\"\n  STR_SMALL_LOW_CONTRAST: \"Малий\"\n  STR_SMALL_HIGH_CONTRAST: \"Малий, високий контраст\"\n  STR_BIG_LOW_CONTRAST: \"Великий\"\n  STR_BIG_HIGH_CONTRAST: \"Великий, високий контраст\"\n  STR_TEST_CASE: \"Тестовий випадок:\"\n  STR_RUN: \"Запустити вибрані тести!\"\n  STR_TESTS_STARTING: \"Запуск...\"\n  STR_TESTS_ERRORS_FOUND: \"Загальна кількість знайдених помилок (можуть бути повторювані): {0}\"\n  STR_TESTS_NO_ERRORS_FOUND: \"Помилок не знайдено.\"\n  STR_TESTS_FINISHED: \"Завершено.\"\n  STR_DETAILED_INFO_IN_LOG_FILE: \"Детальна інформація збережена у openxcom.log\"\n  STR_RANK_NONE: \"-\"\n  STR_DAMAGE_NONE: \"ЖОДЕН\"\n  STR_INFO_UFOPEDIA: \"ІНФОРМАЦІЯ\"\n  STR_COCKPIT_CAPACITY: \"ПІЛОТИ>{ALT}{0}{ALT}\"\n  STR_MAXIMUM_RANGE: \"МАКСИМАЛЬНИЙ ДІАПАЗОН>{ALT}{0}{ALT}\"\n  STR_MINIMUM_RANGE: \"МІНІМАЛЬНИЙ ДІАПАЗОН>{ALT}{0}{ALT}\"\n  STR_INFINITE_RANGE: \"Н/Д\"\n  STR_TRACTOR_BEAM_POWER: \"Потужність\"\n  STR_WEIGHT_PEDIA1: \"Вага: {0}\"\n  STR_WEIGHT_PEDIA2: \"Вага: {0}/{1}\"\n  STR_SHOT_TYPE_MELEE: \"Рукопашний бій\"\n  STR_ACCURACY_MODIFIER: \"Модифікатор точності>{ALT} {0}\"\n  STR_POWER_BONUS: \"Бонус потужності>{ALT} {0}\"\n  STR_MULTIPLE_DIFFERENT_BONUSES: \"множинні бонуси на різні сумісні боєприпаси\"\n  STR_STATS_FOR_NERDS: \"Статистика для Ботанів\"\n  STR_ARTICLE: \"Стаття>{ALT} {0}\"\n  STR_COMPATIBLE_AMMO: \"Сумісні боєприпаси:\"\n  STR_BUILT_IN_ITEMS: \"Вбудовані предмети:\"\n  STR_CLIP_SIZE_UNLIMITED: \"необмежений\"\n  STR_SHOTGUN_BEHAVIOR_OXCE: \"розширений\"\n  STR_INCLUDE_DEBUG: \"НАЛАГОДЖУВАННЯ\"\n  STR_INCLUDE_IDS: \"Ідентифікатори\"\n  STR_INCLUDE_DEFAULTS: \"ЗА ЗАМОВЧУВАННЯМ\"\n  STR_TRUE: \"правда\"\n  STR_FALSE: \"брехня\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH: \"PSI-НАВИК * PSI-СИЛА\"\n  STR_STRENGTH_AND_MELEE_ACCURACY: \"СИЛА * ТОЧНІСТЬ РУКОПАШНОГО БОЮ\"\n  STR_STRENGTH_AND_THROWING_ACCURACY: \"СИЛА * ТОЧНІСТЬ КИДАННЯ\"\n  STR_FIRING_ACCURACY_AND_REACTIONS: \"ТОЧНІСТЬ СТРІЛЬБИ * РЕАКЦІЯ\"\n  STR_HEALTH_CURRENT: \"ПОТОЧНЕ ЗДОРОВ'Я\"\n  STR_MANA_CURRENT: \"ПОТОЧНА МАНА\"\n  STR_TIME_UNITS_CURRENT: \"ПОТОЧНІ ОДИНИЦІ ЧАСУ\"\n  STR_STUN_LEVEL_CURRENT: \"ПОТОЧНИЙ РІВЕНЬ ОГЛУШЕННЯ\"\n  STR_HEALTH_NORMALIZED: \"НОРМАЛІЗОВАНЕ ЗДОРОВ'Я\"\n  STR_MANA_NORMALIZED: \"НОРМАЛІЗОВАНА МАНА\"\n  STR_TIME_UNITS_NORMALIZED: \"НОРМАЛІЗОВАНІ ОДИНИЦІ ЧАСУ\"\n  STR_ENERGY_NORMALIZED: \"НОРМАЛІЗОВАНА ЕНЕРГІЯ\"\n  STR_MORALE_NORMALIZED: \"НОРМАЛІЗОВАНА МОРАЛЬ\"\n  STR_STUN_LEVEL_NORMALIZED: \"НОРМАЛІЗОВАНИЙ РІВЕНЬ ОГЛУШЕННЯ\"\n  STR_ENERGY_REGENERATION: \"РЕГЕНЕРАЦІЯ ЕНЕРГІЇ\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH_ABBREVIATION: \"ПСН*ПСС\"\n  STR_STRENGTH_AND_MELEE_ACCURACY_ABBREVIATION: \"СИЛ*ББ\"\n  STR_STRENGTH_AND_THROWING_ACCURACY_ABBREVIATION: \"СИЛ*БРС\"\n  STR_FIRING_ACCURACY_AND_REACTIONS_ABBREVIATION: \"ТЧН*РЕА\"\n  STR_HEALTH_CURRENT_ABBREVIATION: \"ПОТОЧНЕ ЗДОРОВ'Я\"\n  STR_MANA_CURRENT_ABBREVIATION: \"ПОТОЧНА МАНА\"\n  STR_TIME_UNITS_CURRENT_ABBREVIATION: \"ПОТОЧНІ ОДИНИЦІ ЧАСУ\"\n  STR_STUN_LEVEL_CURRENT_ABBREVIATION: \"ПОТОЧНИЙ РІВЕНЬ ОГЛУШЕННЯ\"\n  STR_HEALTH_NORMALIZED_ABBREVIATION: \"НОРМАЛІЗОВАНЕ ЗДОРОВ'Я\"\n  STR_MANA_NORMALIZED_ABBREVIATION: \"НОРМАЛІЗОВАНА МАНА\"\n  STR_TIME_UNITS_NORMALIZED_ABBREVIATION: \"НОРМАЛІЗОВАНІ ОДИНИЦІ ЧАСУ\"\n  STR_ENERGY_NORMALIZED_ABBREVIATION: \"НОРМАЛІЗОВАНА ЕНЕРГІЯ\"\n  STR_MORALE_NORMALIZED_ABBREVIATION: \"НОРМАЛІЗОВАНА МОРАЛЬ\"\n  STR_STUN_LEVEL_NORMALIZED_ABBREVIATION: \"НОРМАЛІЗОВАНИЙ РІВЕНЬ ОГЛУШЕННЯ\"\n  STR_ENERGY_REGENERATION_ABBREVIATION: \"РЕГЕНЕРАЦІЯ ЕНЕРГІЇ\"\n  STR_TIME_UNITS_SCALED: \"ЗБІЛЬШЕНО ОДИНИЦІ ЧАСУ\"\n  STR_STAMINA_SCALED: \"ЗБІЛЬШЕНО ВИТРИВАЛІСТЬ\"\n  STR_HEALTH_SCALED: \"ЗБІЛЬШЕНО ЗДОРОВ'Я\"\n  STR_BRAVERY_SCALED: \"ЗБІЛЬШЕНО ВІДВАГУ\"\n  STR_REACTIONS_SCALED: \"ЗБІЛЬШЕНО РЕАКЦІЮ\"\n  STR_FIRING_ACCURACY_SCALED: \"ЗБІЛЬШЕНО ТОЧНІСТЬ СТРІЛЬБИ\"\n  STR_THROWING_ACCURACY_SCALED: \"БІЛЬШЕНО ТОЧНІСТЬ МЕТАННЯ\"\n  STR_STRENGTH_SCALED: \"ЗБІЛЬШЕНО СИЛУ\"\n  STR_PSIONIC_STRENGTH_SCALED: \"ЗБІЛЬШЕНО ПСІОНІЧНУ СИЛУ\"\n  STR_PSIONIC_SKILL_SCALED: \"ЗБІЛЬШЕНО ПСІОНІЧНЕ ВМІННЯ\"\n  STR_MELEE_ACCURACY_SCALED: \"ЗБІЛЬШЕНО ТОЧНІСТЬ БЛИЖНЬОГО БОЮ\"\n  STR_MANA_POOL_SCALED: \"ЗБІЛЬШЕНО РІВЕНЬ МАНИ\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH_SCALED: \"ЗБІЛЬШЕНО ПСІ СИЛУ*ПСІ ВМІННЯ\"\n  STR_STRENGTH_AND_MELEE_ACCURACY_SCALED: \"ЗБІЛЬШЕНО СИЛУ*ТОЧНІСТЬ БЛИЖНЬОГО БОЮ\"\n  STR_STRENGTH_AND_THROWING_ACCURACY_SCALED: \"ЗБІЛЬШЕНО СИЛУ*ТОЧНІСТЬ МЕТАННЯ\"\n  STR_FIRING_ACCURACY_AND_REACTIONS_SCALED: \"ЗБІЛЬШЕНО ТОЧНІСТЬ СТРІЛЬБИ*РЕАКЦІЮ\"\n  STR_TIME_UNITS_SCALED_ABBREVIATION: \"Збільшено ОЧ\"\n  STR_STAMINA_SCALED_ABBREVIATION: \"Збільшено ВТ\"\n  STR_HEALTH_SCALED_ABBREVIATION: \"Збільшено ЗД\"\n  STR_BRAVERY_SCALED_ABBREVIATION: \"Збільшено ХР\"\n  STR_REACTIONS_SCALED_ABBREVIATION: \"Збільшено РЕ\"\n  STR_FIRING_ACCURACY_SCALED_ABBREVIATION: \"Збільшено ТС\"\n  STR_THROWING_ACCURACY_SCALED_ABBREVIATION: \"Збільшено ТМ\"\n  STR_STRENGTH_SCALED_ABBREVIATION: \"Збільшено СЛ\"\n  STR_PSIONIC_STRENGTH_SCALED_ABBREVIATION: \"Збільшено ПС\"\n  STR_PSIONIC_SKILL_SCALED_ABBREVIATION: \"Збільшено ПВ\"\n  STR_MELEE_ACCURACY_SCALED_ABBREVIATION: \"Збільшено ББ\"\n  STR_MANA_POOL_SCALED_ABBREVIATION: \"Збільшено МН\"\n  STR_PSI_SKILL_AND_PSI_STRENGTH_SCALED_ABBREVIATION: \"Збільшено ПВ*ПС\"\n  STR_STRENGTH_AND_MELEE_ACCURACY_SCALED_ABBREVIATION: \"Збільшено СЛ*ББ\"\n  STR_STRENGTH_AND_THROWING_ACCURACY_SCALED_ABBREVIATION: \"Збільшено СЛ*ТМ\"\n  STR_FIRING_ACCURACY_AND_REACTIONS_SCALED_ABBREVIATION: \"Збільшено ТС*РЕ\"\n  STR_COST_TIME: \"час\"\n  STR_COST_ENERGY: \"енергія\"\n  STR_COST_MORALE: \"мораль\"\n  STR_COST_HEALTH: \"здоров'я\"\n  STR_COST_STUN: \"оглушення\"\n  STR_COST_MANA: \"мана\"\n  STR_COST_BUILD: \"будувати\"\n  STR_COST_REFUND: \"повернення коштів\"\n  STR_DAMAGE_10: \"10\"\n  STR_DAMAGE_11: \"11\"\n  STR_DAMAGE_12: \"12\"\n  STR_DAMAGE_13: \"13\"\n  STR_DAMAGE_14: \"14\"\n  STR_DAMAGE_15: \"15\"\n  STR_DAMAGE_16: \"16\"\n  STR_DAMAGE_17: \"17\"\n  STR_DAMAGE_18: \"18\"\n  STR_DAMAGE_19: \"19\"\n  STR_NAUTICAL_MILES: \"{0} морських миль\"\n  STR_KILOMETERS_PER_HOUR: \"{0} км/год\"\n  STR_SECONDS_LONG: \"{0} секунд\"\n  STR_RACE_BONUS: \"Бонус раси\"\n  STR_FOR_DIFFICULTY: \"за складність: {0}\"\n  STR_NOT_AWARDED_YET: \"Поки що не нагороджено\"\n"
  },
  {
    "path": "bin/common/Language/Technical/cs.yml",
    "content": "cs:\n#=================== Menu ===================\n#TestState.cpp\n  STR_BAD_NODES: \"Chybné uzly v RPM souborech\"\n  STR_BAD_NODES_DESC: \"Prověří RPM soubory pro uzly mimo hranice mapy.{NEWLINE}Sice NEzpůsobují crashe, ale budou hrou ignorovány, a tedy nefunkční.\"\n#\n  STR_MCD_CHECK: \"Prověření MCD\"\n  STR_MCD_CHECK_DESC: \"\"\n#\n  STR_PALETTE_CHECK: \"Srovnání palety\"\n  STR_PALETTE_CHECK_DESC: \"Pokusí se porovnat palety modifikovaných obrázků s originální paletou a nahlásí obrázky s odchylkami.\"\n#\n  STR_SCRIPT_TAGS: \"Export značek skriptu\"\n  STR_SCRIPT_TAGS_DESC: \"Exportuje značky skriptu v CSV formátu.\"\n#\n  STR_MAP_RESOURCES: \"Prověření zdrojů mapy\"\n  STR_MAP_RESOURCES_DESC: \"Prověří chybějící a nepoužité soubory a sady pravidel související s mapou.\"\n#\n  STR_CHECKING_TERRAIN: \"Kontroluji terén...\"\n  STR_CHECKING_UFOS: \"Kontroluji UFA...\"\n  STR_CHECKING_CRAFT: \"Kontroluji plavidlo...\"\n#\n  BACKPALS.DAT: \"BACKPALS.DAT\"\n  PAL_GEOSCAPE: \"PAL_GEOSCAPE\"\n  PAL_BASESCAPE: \"PAL_BASESCAPE\"\n  PAL_GRAPHS: \"PAL_GRAPHS\"\n  PAL_UFOPAEDIA: \"PAL_UFOPAEDIA\"\n  PAL_BATTLEPEDIA: \"PAL_BATTLEPEDIA\"\n  PAL_BATTLESCAPE: \"PAL_BATTLESCAPE\"\n  PAL_BATTLESCAPE_1: \"PAL_BATTLESCAPE_1\"\n  PAL_BATTLESCAPE_2: \"PAL_BATTLESCAPE_2\"\n  PAL_BATTLESCAPE_3: \"PAL_BATTLESCAPE_3\"\n#=================== Ufopaedia ===================\n#StatsForNerdsState.cpp\n  BT_NONE: \"Žádný\"\n  BT_FIREARM: \"Střelná zbraň\"\n  BT_AMMO: \"Munice\"\n  BT_MELEE: \"Zbraň na blízko\"\n  BT_GRENADE: \"Granát\"\n  BT_PROXIMITYGRENADE: \"Pohybem aktivovaná výbušnina\"\n  BT_MEDIKIT: \"Lékárnička\"\n  BT_SCANNER: \"Detektor pohybu\"\n  BT_MINDPROBE: \"Čtečka mysli\"\n  BT_PSIAMP: \"Čtečka mysli\"\n  BT_FLARE: \"Světlice\"\n  BT_CORPSE: \"Mrtvola/tělo\"\n#\n  DRT_DEFAULT: \"výchozí vanilla\"\n  DRT_UFO: \"rozptyl 0-200 %\"\n  DRT_TFTD: \"rozptyl 50-150 %\"\n  DRT_FLAT: \"plošné poškození\"\n  DRT_FIRE: \"zvláštní ohnivé poškození\"\n  DRT_NONE: \"žádné poškození\"\n  DRT_UFO_WITH_TWO_DICE: \"rozptyl 0-200 % (2 hody kostkou)\"\n  DRT_EASY: \"rozptyl 50-200 %\"\n  DRT_STANDARD: \"standardní rozsah poškození\"\n  DRT_EXPLOSION: \"rozsah poškození explozí\"\n#\n  BFT_NONE: \"žádné\"\n  BFT_INSTANT: \"instantní\"\n  BFT_SET: \"manuálně nastavené\"\n  BFT_FIXED: \"pevně dané\"\n#\n  BMT_NORMAL: \"standard (víceúčelové)\"\n  BMT_HEAL: \"léčivo\"\n  BMT_STIMULANT: \"Stimulant\"\n  BMT_PAINKILLER: \"utišovač bolesti\"\n#\n  ETM_DEFAULT: \"výchozí\"\n  ETM_MELEE_100: \"ZBLÍZKA\"\n  ETM_MELEE_50: \"ZBLÍZKA (50% šance)\"\n  ETM_MELEE_33: \"ZBLÍZKA (33% šance)\"\n  ETM_FIRING_100: \"STŘELBA\"\n  ETM_FIRING_50: \"STŘELBA (50% šance)\"\n  ETM_FIRING_33: \"STŘELBA (33% šance)\"\n  ETM_THROWING_100: \"VRH\"\n  ETM_THROWING_50: \"VRH (50% šance)\"\n  ETM_THROWING_33: \"VRH (33% šance)\"\n  ETM_FIRING_AND_THROWING: \"STŘELBA a VRH\"\n  ETM_FIRING_OR_THROWING: \"STŘELBA nebo VRH\"\n  ETM_REACTIONS: \"REAKCE\"\n  ETM_REACTIONS_AND_MELEE: \"REAKCE a ZBLÍZKA\"\n  ETM_REACTIONS_AND_FIRING: \"REAKCE a STŘELBA\"\n  ETM_REACTIONS_AND_THROWING: \"REAKCE a VRH\"\n  ETM_REACTIONS_OR_MELEE: \"REAKCE nebo ZBLÍZKA\"\n  ETM_REACTIONS_OR_FIRING: \"REAKCE nebo STŘELBA\"\n  ETM_REACTIONS_OR_THROWING: \"REAKCE nebo VRH\"\n  ETM_BRAVERY: \"ODVAHA\"\n  ETM_BRAVERY_2X: \"ODVAHA (x2)\"\n  ETM_BRAVERY_AND_REACTIONS: \"ODVAHA a REAKCE\"\n  ETM_BRAVERY_OR_REACTIONS: \"ODVAHA nebo REAKCE\"\n  ETM_BRAVERY_OR_REACTIONS_2X: \"ODVAHA nebo REAKCE (x2)\"\n  ETM_PSI_STRENGTH: \"PSI SÍLA\"\n  ETM_PSI_STRENGTH_2X: \"PSI SÍLA (x2)\"\n  ETM_PSI_SKILL: \"PSI DOVEDNOST\"\n  ETM_PSI_SKILL_2X: \"PSI DOVEDNOST (x2)\"\n  ETM_PSI_STRENGTH_AND_SKILL: \"PSI SÍLA a PSI DOVEDNOST\"\n  ETM_PSI_STRENGTH_AND_SKILL_2X: \"PSI SÍLA a PSI DOVEDNOST (x2)\"\n  ETM_PSI_STRENGTH_OR_SKILL: \"PSI SÍLA nebo PSI DOVEDNOST\"\n  ETM_PSI_STRENGTH_OR_SKILL_2X: \"PSI SÍLA nebo PSI DOVEDNOST (x2)\"\n  ETM_NOTHING: \"žádný trénink\"\n#\n  battleType: \"Typ předmětu\"\n  experienceTrainingMode: \"Mód zkušeností\"\n  manaExperience: \"Zkušenost s manou\"\n  arcingShot: \"Oblouková?\"\n  isFireExtinguisher: \"Hasí oheň?\"\n  explodeInventory: \"Bouchne v inventáři?\"\n  waypoints: \"Max záchytných bodů\"\n  sprayWaypoints: \"Pokrop záchytné body\"\n#\n  shotgunPellets: \"Počet broků\"\n  shotgunBehavior: \"Chování brokovnice\"\n  shotgunSpread: \"Rozptyl brokovnice\"\n  shotgunChoke: \"Ucpání brokovnice\"\n#\n  underwaterOnly: \"Jen podvodní?\"\n  landOnly: \"Jen pozemské?\"\n  psiRequired: \"Vyžaduje psi dovednost?\"\n  targetMatrix: \"Terče věcí\"\n  convertToCivilian: \"Konvertovat na civilistu?\"\n  manaRequired: \"Vyžaduje manu?\"\n  LOSRequired: \"Musí vidět cíl?\"\n#\n  noLOSAccuracyPenalty: \"Postih bez vidění cíle\"\n  kneelBonus: \"Bonus při zakleknutí\"\n  twoHanded: \"Obouruční?\"\n  blockBothHands: \"Blokuje obě ruce?\"\n  oneHandedPenalty: \"Postih za jednoruční použití\"\n#\n  minRange: \"Minimální dosah\"\n  maxRange: \"Maximální dosah\"\n  aimRange: \"Dostřel mířeně\"\n  autoRange: \"Dostřel dávkou\"\n  snapRange: \"Dostřel od boku\"\n  dropoff: \"Pokles přesnosti za pole\"\n#\n  accuracyMultiplier: \"Výpočet přes. střelby\"\n  accuracyAimed: \"Přesnost mířeně\"\n  accuracyAuto: \"Přesnost dávkou\"\n  accuracySnap: \"Přesnost od boku\"\n  costAimed: \"Cena mířeného výstřelu\"\n  costAuto: \"Cena střelby dávkou\"\n  costSnap: \"Cena střelby od boku\"\n#\n  meleeMultiplier: \"Výpočet přes. zblízka\"\n  accuracyMelee: \"Přesnost zblízka\"\n  costMelee: \"Cena zblízka\"\n#\n  psiAttackName: \"Název psi útoku\"\n  accuracyUse: \"Přesnost akce\"\n  accuracyMindControl: \"Přesnost ovládnutí mysli\"\n  accuracyPanic: \"Přesnost zpanikaření\"\n  costUse: \"Cena akce\"\n  costMindcontrol: \"Cena ovládnutí mysli\"\n  costPanic: \"Cena zpanikaření\"\n#\n  weight: \"Váha\"\n  throwRange: \"\"\n  underwaterThrowRange: \"\"\n  throwDropoffRange: \"\"\n  underwaterThrowDropoffRange: \"\"\n  throwDropoff: \"\"\n  throwMultiplier: \"Výpočet přes. vrhu\"\n  accuracyThrow: \"Přesnost vrhu\"\n  costThrow: \"Cena vrhnutí\"\n  costPrime: \"Cena načasování\"\n  costUnprime: \"Cena zrušení načasování\"\n#\n  closeQuartersMultiplier: \"Výpočet přes. BBV\"\n  accuracyCloseQuarters: \"BBV přesnost\"\n#\n  damageType: \"Typ poškození\"\n  power: \"Účinek\"\n  powerRangeReduction: \"Pokles účinku za pole\"\n  powerRangeThreshold: \"Hranice poklesu účinku\"\n  damageBonus: \"Bonus k poškození\"\n  blastRadius: \"Velikost výbuchu\"\n  damageAlter: \"Info o dalším poškození:\"\n  meleeType: \"Typ poškození zblízka\"\n  meleePower: \"Účinek zblízka\"\n  meleeBonus: \"Bonus k účinku zblízka\"\n  meleeAlter: \"Extra info z boje tváří v tvář\"\n  FixRadius: \"Velikost výbuchu\"\n  RandomType: \"Typ výpočtu\"\n  FireBlastCalc: \"Vanilla účinek ohně?\"\n  IgnoreDirection: \"Ignorovat směr\"\n  IgnoreSelfDestruct: \"Ignoruj sebedestrukci\"\n  IgnorePainImmunity: \"Ignoruj imunitu k omráčení\"\n  IgnoreNormalMoraleLose: \"Ignorovat vanilla ztrátu morálky\"\n  IgnoreOverKill: \"Ignoruj overkill\"\n  ArmorEffectiveness: \"Účinnost zbroje\"\n  RadiusEffectiveness: \"Poloměrová účinnost\"\n  RadiusReduction: \"Poloměrový pokles poškození\"\n  FireThreshold: \"Hranice vzplanutí\"\n  SmokeThreshold: \"Hranice pro vytvoření kouře\"\n#\n  ToArmorPre: \"Násobek zbroje před poškozením\"\n  RandomArmorPre: \"Rozsah zbroje před poškozením\"\n  ToArmor: \"Násobek poškození zbroje\"\n  RandomArmor: \"Rozsah násobku poškození zbroje\"\n  ToHealth: \"Násobek poškození ŽVT\"\n  RandomHealth: \"Rozsah poškození ŽVT\"\n  ToStun: \"Násobek omračovacího poškození\"\n  RandomStun: \"Rozsah omračovacího poškození\"\n  ToWound: \"Násobek počtu zranění\"\n  RandomWound: \"Vanilla rozsah zranění\"\n  ToTime: \"Násobek poškození ČJ\"\n  RandomTime: \"Rozsah poškození ČJ\"\n  ToEnergy: \"Násobek poškození Energie\"\n  RandomEnergy: \"Rozsah poškození Energie\"\n  ToMorale: \"\"\n  RandomMorale: \"\"\n  ToItem: \"\"\n  RandomItem: \"\"\n  ToMana: \"\"\n  RandomMana: \"\"\n  ToTile: \"\"\n  RandomTile: \"\"\n  TileDamageMethod: \"\"\n  TileDamageLimit: \"\"\n#\n  confAimed: \"Akce mířená:\"\n  confAuto: \"Akce dávkou:\"\n  confSnap: \"Akce od boku:\"\n  confMelee: \"Akce zblízka:\"\n  shots: \"Výstřelů za akci\"\n  spendPerShot: \"\"\n  followProjectiles: \"\"\n  name: \"Název\"\n  shortName: \"\"\n  ammoSlot: \"\"\n  ammoZombieUnitChanceOverride: \"Šance na zombifikaci\"\n  ammoSpawnUnitChanceOverride: \"\"\n  ammoSpawnItemChanceOverride: \"\"\n  arcing: \"Oblouková?\"\n#\n  clipSize: \"Velikost zásobníku\"\n  isAmmoRechargeable: \"\"\n#\n  primaryAmmo: \"\"\n  compatibleAmmo: \"Kompatibilní munice\"\n  tuLoad: \"Cena nabití\"\n  tuUnload: \"Cena vybití\"\n  ammo[1]: \"\"\n  ammo[2]: \"\"\n  ammo[3]: \"\"\n#\n  armor: \"Zbroj\"\n#\n  medikitType: \"Typ lékárničky\"\n  painKillerActionName: \"\"\n  stimulantActionName: \"\"\n  healActionName: \"\"\n  medikitActionName: \"Jméno akce léčení\"\n  medikitTargetSelf: \"Léčení sebe?\"\n  medikitTargetImmune: \"\"\n  medikitTargetMatrix: \"\"\n  isConsumable: \"Konzumuje se?\"\n  painKiller: \"Dávek utišovače bolesti\"\n  heal: \"Dávek léčení\"\n  stimulant: \"Dávek stimulantů\"\n  woundRecovery: \"Léčení zranění\"\n  healthRecovery: \"Obnova zdraví\"\n  stunRecovery: \"Obnova omráčení\"\n  energyRecovery: \"Obnova výdrže\"\n  manaRecovery: \"Obnova many\"\n  moraleRecovery: \"Obnova morálky\"\n  painKillerRecovery: \"Síla utišení bolesti\"\n#\n  requires: \"Vyžadována technologie\"\n  requiresBuy: \"Technologie pro nákup\"\n  requiresBuyBaseFunc: \"Vyžaduje pořídit služby\"\n  requiresBuyCountry: \"Vyžaduje spojenectví se státem\"\n  requiresAward: \"\"\n  requiresBonus: \"\"\n  categories: \"Kategorie\"\n  supportedInventorySections: \"Sloty inventáře\"\n#\n  size: \"Velikost\"\n  costBuy: \"Nákupní cena\"\n  monthlyBuyLimit: \"Měsíční limit nákupů\"\n  costSell: \"Prodejní cena\"\n  transferTime: \"Hodin na přesun\"\n  monthlySalary: \"Měsíční mzda\"\n  monthlyMaintenance: \"Měsíční údržba\"\n#\n  SPECAB_NONE: \"Žádný\"\n  SPECAB_EXPLODEONDEATH: \"Explodovat při smrti\"\n  SPECAB_BURNFLOOR: \"Spalovat zemi\"\n  SPECAB_BURN_AND_EXPLODE: \"Spalovat zemi a explodovat při smrti\"\n#\n  MT_WALK: \"Chodí\"\n  MT_FLY: \"Létá\"\n  MT_SLIDE: \"Klouže\"\n  MT_FLOAT: \"Vznáší se\"\n  MT_SINK: \"Potápí se\"\n#\n  TORSO_USE_GENDER: \"Použij gender\"\n  TORSO_ALWAYS_MALE: \"Vždy muž\"\n  TORSO_ALWAYS_FEMALE: \"Vždy žena\"\n#\n  DRAWING_ROUTINE_SOLDIER_SECTOID: \"Voják, sektan\"\n  DRAWING_ROUTINE_FLOATER: \"Levit\"\n  DRAWING_ROUTINE_HWP: \"Těžké zbraňové platformy\"\n  DRAWING_ROUTINE_CYBERDISC: \"Kyberdisk\"\n  DRAWING_ROUTINE_CIVILIAN_ETHEREAL: \"Civilista, Etheral\"\n  DRAWING_ROUTINE_SECTOPOD_REAPER: \"Sektonoh, Párák\"\n  DRAWING_ROUTINE_SNAKEMAN: \"Hadom\"\n  DRAWING_ROUTINE_CHRYSSALID: \"Krysklad\"\n  DRAWING_ROUTINE_SILACOID: \"Silacoid\"\n  DRAWING_ROUTINE_CELATID: \"Celatid\"\n  DRAWING_ROUTINE_MUTON: \"Muton\"\n  DRAWING_ROUTINE_SWS: \"Ponorné Zbraňové Systémy\"\n  DRAWING_ROUTINE_HALLUCINOID: \"Halucinoid\"\n  DRAWING_ROUTINE_AQUANAUTS: \"Akvanauti\"\n  DRAWING_ROUTINE_CALCINITE_AND_MORE: \"Kalcinit, Hlubiňák, Žábroun, Kraboun, Tasot\"\n  DRAWING_ROUTINE_AQUATOID: \"Akvatoid\"\n  DRAWING_ROUTINE_BIO_DRONE: \"Biodron\"\n  DRAWING_ROUTINE_TFTD_CIVILIAN_A: \"TFTD Civilista typ A a TFTD Zombie\"\n  DRAWING_ROUTINE_TFTD_CIVILIAN_B: \"TFTD Civilista typ B\"\n  DRAWING_ROUTINE_TENTACULAT: \"Tentakulát\"\n  DRAWING_ROUTINE_TRISCENE: \"Triscen\"\n  DRAWING_ROUTINE_XARQUID: \"\"\n  DRAWING_ROUTINE_INVERTED_CYBERDISC: \"\"\n#\n  stats: \"Modifikátory statistik\"\n  specab: \"\"\n  movementType: \"Typ pohybu\"\n  allowsRunning: \"Umožňuje běh?\"\n  allowsStrafing: \"Umožňuje úkrok?\"\n  allowsSneaking: \"\"\n  allowsKneeling: \"Umožňuje zakleknutí?\"\n  allowsMoving: \"\"\n  fearImmune: \"Imunní ke ztrátě morálky?\"\n  bleedImmune: \"Imunní ke krvácení?\"\n  painImmune: \"Imunní k omráčení?\"\n  zombiImmune: \"Imunní k zombifikaci?\"\n  ignoresMeleeThreat: \"Ignoruje BBV?\"\n  createsMeleeThreat: \"Vyvolává BBV?\"\n  builtInWeapons: \"\"\n  specialWeapon: \"Zvláštní zbraň\"\n  heatVision: \"\"\n  visibilityThroughFire: \"\"\n  psiVision: \"Psi smysl\"\n  psiCamouflage: \"\"\n  visibilityAtDay: \"Viditelnost za dne\"\n  visibilityAtDark: \"Viditelnost v noci\"\n  camouflageAtDay: \"Kamufláž za dne\"\n  camouflageAtDark: \"Kamufláž v noci\"\n  antiCamouflageAtDay: \"Protikamufláž ve dne\"\n  antiCamouflageAtDark: \"Protikamufláž v noci\"\n  psiDefence: \"Psi obrana\"\n  meleeDodge: \"Úhyb zblízka\"\n  meleeDodgeBackPenalty: \"Postih k úhybu zblízka\"\n  recovery: \"Obnovuje každý tah:\"\n  time: \"Čas\"\n  energy: \"Výdrž\"\n  morale: \"Morálku\"\n  health: \"Zdraví\"\n  stun: \"Omráčení\"\n  mana: \"Mana\"\n  units: \"Kompatibilní jednotky\"\n  ranks: \"\"\n  frontArmor: \"Čelní zbroj\"\n  sideArmor: \"Boční zbroj\"\n  leftArmorDiff: \"\"\n  rearArmor: \"Zadní zbroj\"\n  underArmor: \"Spodní zbroj\"\n#\n  sizeX: \"\"\n  sizeY: \"\"\n  buildCost: \"Cena postavení\"\n  buildCostItems: \"Materiály k výrobě:\"\n  buildTime: \"Čas postavení\"\n  monthlyCost: \"Měsíční cena\"\n  refundValue: \"Hodnota při vrácení peněz\"\n  requiresBaseFunc: \"\"\n  provideBaseFunc: \"\"\n  forbiddenBaseFunc: \"\"\n  lift: \"Přístupový výtah?\"\n  hyper: \"\"\n  mind: \"\"\n  mindPower: \"\"\n  grav: \"\"\n  storage: \"Úložného místa\"\n  personnel: \"Ubikací\"\n  aliens: \"Vězeňských cel\"\n  crafts: \"Hangárových stání\"\n  labs: \"Místo v laboratořích\"\n  workshops: \"Místo v dílnách\"\n  psiLabs: \"\"\n  trainingRooms: \"\"\n  sightRange: \"Dohled\"\n  sightChance: \"\"\n  radarRange: \"Dosah radaru\"\n  radarChance: \"Šance radarové detekce\"\n  defense: \"Obranná hodnota\"\n  hitRatio: \"Šance na zásah\"\n  ammoNeeded: \"\"\n  unifiedDamageFormula: \"\"\n  ammoItem: \"\"\n  maxAllowedPerBase: \"Maximum na základnu\"\n  manaRecoveryPerDay: \"Many za den\"\n  healthRecoveryPerDay: \"\"\n  sickBayAbsoluteBonus: \"\"\n  sickBayRelativeBonus: \"\"\n  prisonType: \"Druh vězení\"\n  rightClickActionType: \"Akce pravé myši\"\n  leavesBehindOnSell: \"Po prodej po sobě nechá\"\n  removalTime: \"Čas odstranění\"\n  canBeBuiltOver: \"Může být přestavěno?\"\n  upgradeOnly: \"\"\n  buildOverFacilities: \"\"\n#\n  BFRCT_DEFAULT: \"Výchozí vanilla\"\n  BFRCT_PRISON: \"přejdi do cel\"\n  BFRCT_ENGINEERING: \"přejdi k výrobě\"\n  BFRCT_RESEARCH: \"přejdi k výzkumu\"\n  BFRCT_GYM: \"přejdi k výcviku\"\n  BFRCT_PSI_LABS: \"přejdi k psilaboratoři\"\n  BFRCT_BARRACKS: \"přejdi do kasáren\"\n  BFRCT_GREY_MARKET: \"přejdi k šedému trhu\"\n  BFRCT_GEOSCAPE: \"přejdi na glóbus\"\n#\n  costRent: \"Cena pronájmu\"\n  soldiers: \"Nákladový prostor\"\n  maxUnitsLimit: \"\"\n  pilots: \"Kapacita kokpitu\"\n  pilotMinStatsRequired: \"\"\n  pilotSoldierBonusesRequired: \"\"\n  vehicles: \"Kapacita platformy\"\n  onlyOneSoldierGroupAllowed: \"\"\n  allowedSoldierGroups: \"\"\n  allowedArmorGroups: \"\"\n  limitArmorGroups: \"\"\n  maxHWPUnitsLimit: \"\"\n  maxSmallSoldiers: \"\"\n  maxLargeSoldiers: \"\"\n  maxSmallVehicles: \"\"\n  maxLargeVehicles: \"\"\n  maxSmallUnits: \"\"\n  maxLargeUnits: \"\"\n  maxSoldiers: \"\"\n  maxVehicles: \"\"\n  maxItems: \"Limit vybavení\"\n  maxStorageSpace: \"Úložného místa\"\n  maxAltitude: \"Limit výšky souboje\"\n  weapons: \"\"\n  weaponStrings: \"Názvy zbraní\"\n  fixedWeapons: \"\"\n  weaponTypes: \"Přípustné typy zbraní\"\n  damageMax: \"\"\n  avoidBonus: \"\"\n  avoidBonus2: \"\"\n  powerBonus: \"\"\n  hitBonus: \"\"\n  fuelMax: \"Kapacita nádrže\"\n  speedMax: \"Maximální rychlost\"\n  accel: \"Zrychlení\"\n  shieldCapacity: \"Kapacita štítu\"\n  shieldRecharge: \"Obnova štítu (za letu)\"\n  shieldRechargeInGeoscape: \"Obnova štítu (na glóbu)\"\n  shieldBleedThrough: \"\"\n  shieldRechargedAtBase: \"\"\n  refuelItem: \"\"\n  refuelRate: \"\"\n  repairRate: \"\"\n  spacecraft: \"\"\n  allowLanding: \"Může přistávat?\"\n  notifyWhenRefueled: \"Upozornit na natankování?\"\n  autoPatrol: \"Automaticky hlídkovat?\"\n  undetectable: \"\"\n  patrolWithoutFuel: \"\"\n  keepCraftAfterFailedMission: \"Parašutisté?\"\n  _calculatedValues: \"Vypočítané hodnoty\"\n  _maxRange: \"Maximální dosah\"\n  _minRange: \"Minimální dosah\"\n  _avgRange: \"\"\n#\n  hunterKillerPercentage: \"\"\n  huntMode: \"Mód lovu\"\n  huntSpeed: \"Rychlost lovu\"\n  huntBehavior: \"Chování při lovu\"\n  range: \"Dosah\"\n  reload: \"Čas nabití\"\n  breakOffTime: \"\"\n  score: \"Body\"\n  missionScore: \"Body za misi\"\n  craftCustomDeploy: \"\"\n  missionCustomDeploy: \"\"\n  _escapeCountdown: \"\"\n  _fireRate: \"Kadence střelby\"\n  _averageDPM: \"\"\n#\n  HM_INTERCEPTORS: \"\"\n  HM_TRANSPORTS: \"\"\n  HM_RANDOM: \"\"\n#\n  HB_FLEE: \"prchej když prohráváš\"\n  HB_KAMIKAZE: \"bujuj do roztrhání\"\n  HB_RANDOM: \"\"\n#\n  tractorBeamPower: \"\"\n  damage: \"\"\n  shieldDamageModifier: \"\"\n  accuracy: \"\"\n  reloadCautious: \"\"\n  reloadStandard: \"\"\n  reloadAggressive: \"\"\n  launcher: \"\"\n  weaponType: \"\"\n  clip: \"\"\n  ammoMax: \"\"\n  rearmRate: \"\"\n  bulletSaving: \"\"\n  _damageRange: \"\"\n  _damageRangeBasic: \"\"\n  _averageTotalDamage: \"\"\n#\n  allowPiloting: \"\"\n  costSalary: \"\"\n  costSalarySquaddie: \"\"\n  costSalarySergeant: \"\"\n  costSalaryCaptain: \"\"\n  costSalaryColonel: \"\"\n  costSalaryCommander: \"\"\n#\n  race: \"\"\n  rank: \"\"\n  livingWeapon: \"\"\n  meleeWeapon: \"Zbraň na blízko\"\n  psiWeapon: \"\"\n  _builtInWeaponSets: \"\"\n  _weightedBuiltInWeaponSets: \"\"\n  spawnUnit: \"\"\n  _capturable: \"\"\n  capturable: \"\"\n  canSurrender: \"\"\n  autoSurrender: \"\"\n  spotter: \"\"\n  sniper: \"\"\n"
  },
  {
    "path": "bin/common/Language/Technical/de.yml",
    "content": "de:\n#=================== Menu ===================\n#TestState.cpp\n  STR_BAD_NODES: \"Schlechte Notizen in RMP Dateien\"\n  STR_BAD_NODES_DESC: \"Prüft die RMP-Dateien auf Knoten außerhalb der Kartengrenzen.{NEWLINE}Diese verursachen zwar KEINE Abstürze, werden aber vom Spiel ignoriert und funktionieren daher nicht wie vorgesehen.\"\n#\n  STR_MCD_CHECK: \"MCD Überprüfung\"\n  STR_MCD_CHECK_DESC: \"\"\n#\n  STR_PALETTE_CHECK: \"Farbabgleich\"\n  STR_PALETTE_CHECK_DESC: \"Versucht, die Paletten der modifizierten Bilder mit den offiziellen Paletten abzugleichen und meldet alle Bilder, die nicht zu 100% übereinstimmen.\"\n#\n  STR_SCRIPT_TAGS: \"Script tag export\"\n  STR_SCRIPT_TAGS_DESC: \"Exportiere Script Tags in ein CSV Format\"\n#\n  STR_MAP_RESOURCES: \"Kartenressourcenüberprüfung\"\n  STR_MAP_RESOURCES_DESC: \"Prüfe nach fehlenden oder ungenutztn Kartenbasierten Dateien und Regelwerken\"\n#\n  STR_CHECKING_TERRAIN: \"Überprüfe Terrain...\"\n  STR_CHECKING_UFOS: \"Suche nach UFOs...\"\n  STR_CHECKING_CRAFT: \"Überprüfe Fahrzeug...\"\n#\n  BACKPALS.DAT: \"BACKPALS.DAT\"\n  PAL_GEOSCAPE: \"PAL_GEOSCAPE\"\n  PAL_BASESCAPE: \"PAL_BASESCAPE\"\n  PAL_GRAPHS: \"PAL_GRAPHS\"\n  PAL_UFOPAEDIA: \"PAL_UFOPAEDIA\"\n  PAL_BATTLEPEDIA: \"PAL_BATTLEPEDIA\"\n  PAL_BATTLESCAPE: \"PAL_BATTLESCAPE\"\n  PAL_BATTLESCAPE_1: \"PAL_BATTLESCAPE_1\"\n  PAL_BATTLESCAPE_2: \"PAL_BATTLESCAPE_2\"\n  PAL_BATTLESCAPE_3: \"PAL_BATTLESCAPE_3\"\n#=================== Ufopaedia ===================\n#StatsForNerdsState.cpp\n  BT_NONE: \"Keine\"\n  BT_FIREARM: \"Schusswaffe\"\n  BT_AMMO: \"Munition\"\n  BT_MELEE: \"Nahkampfwaffe\"\n  BT_GRENADE: \"Granate\"\n  BT_PROXIMITYGRENADE: \"Annäherungsgranate\"\n  BT_MEDIKIT: \"Medikit\"\n  BT_SCANNER: \"Bewegungsscanner\"\n  BT_MINDPROBE: \"Gedankensonde\"\n  BT_PSIAMP: \"Psi Verstärker\"\n  BT_FLARE: \"Leuchtfackel\"\n  BT_CORPSE: \"Leiche\"\n#\n  DRT_DEFAULT: \"Vanilla Voreinstellung\"\n  DRT_UFO: \"0-200% Streuung\"\n  DRT_TFTD: \"50-150% Streuung\"\n  DRT_FLAT: \"Pauschalschaden\"\n  DRT_FIRE: \"Spezieller Feuerschaden\"\n  DRT_NONE: \"Kein Schaden\"\n  DRT_UFO_WITH_TWO_DICE: \"0-200% Streuung (2 Würfel)\"\n  DRT_EASY: \"50-200% Streuung\"\n  DRT_STANDARD: \"Standard-Schadensspanne\"\n  DRT_EXPLOSION: \"Schadensbereich der Explosion\"\n#\n  BFT_NONE: \"keine\"\n  BFT_INSTANT: \"Sofort\"\n  BFT_SET: \"manuell eingestellt\"\n  BFT_FIXED: \"fixiert\"\n#\n  BMT_NORMAL: \"Standard (vielseitig)\"\n  BMT_HEAL: \"Heilung\"\n  BMT_STIMULANT: \"Stimulanz\"\n  BMT_PAINKILLER: \"Schmerzmittel\"\n#\n  ETM_DEFAULT: \"Voreinstellung\"\n  ETM_MELEE_100: \"Nahkampf\"\n  ETM_MELEE_50: \"Nahkampf (50% Chance)\"\n  ETM_MELEE_33: \"Nahkampf (33% Chance)\"\n  ETM_FIRING_100: \"FEUER\"\n  ETM_FIRING_50: \"Feuern (50% Chance)\"\n  ETM_FIRING_33: \"Feuern (33% Chance)\"\n  ETM_THROWING_100: \"Werfen\"\n  ETM_THROWING_50: \"Werfen (50% Chance)\"\n  ETM_THROWING_33: \"Werfen (33% Chance)\"\n  ETM_FIRING_AND_THROWING: \"Feuern und Werfen\"\n  ETM_FIRING_OR_THROWING: \"Feuern oder Werfen\"\n  ETM_REACTIONS: \"Reaktionen\"\n  ETM_REACTIONS_AND_MELEE: \"Reaktionen und Nahkampf\"\n  ETM_REACTIONS_AND_FIRING: \"Reaktionen und Feuern\"\n  ETM_REACTIONS_AND_THROWING: \"Reaktionen und Werfen\"\n  ETM_REACTIONS_OR_MELEE: \"Reaktionen oder Nahkampf\"\n  ETM_REACTIONS_OR_FIRING: \"Reaktionen oder Feuern\"\n  ETM_REACTIONS_OR_THROWING: \"Reaktionen oder Werfen\"\n  ETM_BRAVERY: \"Mut\"\n  ETM_BRAVERY_2X: \"Mut (x2)\"\n  ETM_BRAVERY_AND_REACTIONS: \"Mut und Reaktionen\"\n  ETM_BRAVERY_OR_REACTIONS: \"Mut oder Reaktionen\"\n  ETM_BRAVERY_OR_REACTIONS_2X: \"Mut oder Reaktionen (x2)\"\n  ETM_PSI_STRENGTH: \"Psi Stärke\"\n  ETM_PSI_STRENGTH_2X: \"Psi-Stärke (x2)\"\n  ETM_PSI_SKILL: \"Psi Fertigkeit\"\n  ETM_PSI_SKILL_2X: \"Psi Fertigkeit (x2)\"\n  ETM_PSI_STRENGTH_AND_SKILL: \"Psi Stärke und Psi Fähigkeit\"\n  ETM_PSI_STRENGTH_AND_SKILL_2X: \"PSI-Stärke und PSI-Fähigkeit (x2)\"\n  ETM_PSI_STRENGTH_OR_SKILL: \"Psi Stärke oder Psi Fähigkeit\"\n  ETM_PSI_STRENGTH_OR_SKILL_2X: \"Psi Stärke oder Psi Fähigkeit (x2)\"\n  ETM_NOTHING: \"Kein Training\"\n#\n  battleType: \"Gegenstandstyp\"\n  experienceTrainingMode: \"Erfahrungsmodus\"\n  manaExperience: \"Mana-Erfahrung\"\n  arcingShot: \"Lichtbogenbildung?\"\n  isFireExtinguisher: \"Feuerlöscher?\"\n  explodeInventory: \"Explodiert im Inventar?\"\n  waypoints: \"Maximale Wegpunkte\"\n  sprayWaypoints: \"Wegpunkte für Streuschüsse\"\n#\n  shotgunPellets: \"Zahl der Projektile\"\n  shotgunBehavior: \"Schrotflintenverhalten\"\n  shotgunSpread: \"Schrotflintenstreuung\"\n  shotgunChoke: \"Schrotflintendrossel\"\n#\n  underwaterOnly: \"Ausschließlich Unterwasser\"\n  landOnly: \"Ausschließlich Land\"\n  psiRequired: \"Psi-Fertigkeit benötigt\"\n  targetMatrix: \"Zielobjekte\"\n  convertToCivilian: \"Zu einem Zivilisten mutieren?\"\n  manaRequired: \"Mana benötigt?\"\n  LOSRequired: \"Sicht benötigt\"\n#\n  noLOSAccuracyPenalty: \"Keine Sicht-Abzug Multiplikator\"\n  kneelBonus: \"Kniend Bonus Multiplikator\"\n  twoHanded: \"Zweihändig?\"\n  blockBothHands: \"Blockiert beide Hände\"\n  oneHandedPenalty: \"Einhandnutzungsnachteil\"\n#\n  minRange: \"Minimale Reichweite\"\n  maxRange: \"Maximale Reichweite\"\n  aimRange: \"Reichweite gezielter Schuss\"\n  autoRange: \"Reichweite automatischer Schuss\"\n  snapRange: \"Reichweite Schnellschuss\"\n  dropoff: \"Genauigkeitsverlust\"\n#\n  accuracyMultiplier: \"Feuergenauigkeit Multiplikator\"\n  accuracyAimed: \"Gezielter Schuss Genauigkeit\"\n  accuracyAuto: \"Auto-Schuss Genauigkeit\"\n  accuracySnap: \"Schnellschussgenauigkeit\"\n  costAimed: \"Gezielter Schuss Kosten\"\n  costAuto: \"Automatischer Schuss Kosten\"\n  costSnap: \"Kosten für Schnellschuss\"\n#\n  meleeMultiplier: \"Nahkampfgenauigkeit Multiplikator\"\n  accuracyMelee: \"Nahkampfgenauigkeit\"\n  costMelee: \"Nahkampfkosten\"\n#\n  psiAttackName: \"Psi-Angriff Name\"\n  accuracyUse: \"Aktionsgenauigkeit\"\n  accuracyMindControl: \"Gedankenkontrollgenauigkeit\"\n  accuracyPanic: \"Panikgenauigkeit\"\n  costUse: \"Aktionskosten\"\n  costMindcontrol: \"Gedankenkontrolle Kosten\"\n  costPanic: \"Panik Kosten\"\n#\n  weight: \"Gewicht\"\n  throwRange: \"\"\n  underwaterThrowRange: \"\"\n  throwDropoffRange: \"\"\n  underwaterThrowDropoffRange: \"\"\n  throwDropoff: \"\"\n  throwMultiplier: \"Multiplikator der Wurfgenauigkeit\"\n  accuracyThrow: \"Wurfgenauigkeit\"\n  costThrow: \"Wurfkosten\"\n  costPrime: \"Ladekosten\"\n  costUnprime: \"Entladekosten\"\n#\n  closeQuartersMultiplier: \"Multiplikator der Nahkampfgenauigkeit\"\n  accuracyCloseQuarters: \"Nahkampfgenauigkeit\"\n#\n  damageType: \"Schadenstyp\"\n  power: \"Energie\"\n  powerRangeReduction: \"Energiereduktion je Feld\"\n  powerRangeThreshold: \"Schwellenwert für die Energiereduzierung\"\n  damageBonus: \"Schadensbonus\"\n  blastRadius: \"Sprengradius\"\n  damageAlter: \"Extra Schadensinformation\"\n  meleeType: \"Nahkampf Schadenstyp\"\n  meleePower: \"Nahkampfkraft\"\n  meleeBonus: \"Nahkampfkraft Bonus\"\n  meleeAlter: \"Extra Nahkampf Information:\"\n  FixRadius: \"Sprengradius\"\n  RandomType: \"Berechnungstyp\"\n  FireBlastCalc: \"Vanille Schusseffekte\"\n  IgnoreDirection: \"Ignoriere Richtung\"\n  IgnoreSelfDestruct: \"Ignoriere Selbstzerstörung\"\n  IgnorePainImmunity: \"Ignoriere Betäubungsimmunität\"\n  IgnoreNormalMoraleLose: \"Ignoriere Vanilla Moralverlust\"\n  IgnoreOverKill: \"Ignoriere Overkill\"\n  ArmorEffectiveness: \"Rüstungseffektivität\"\n  RadiusEffectiveness: \"Radius Effektivität\"\n  RadiusReduction: \"Radius Schadensverringerung\"\n  FireThreshold: \"Schwellenwert für das In-Brand-Setzen\"\n  SmokeThreshold: \"Schwellenwert für Rauch\"\n#\n  ToArmorPre: \"Vorschau Rüstungsschaden Multiplikator\"\n  RandomArmorPre: \"Vorschau zufälliger Rüstungsschaden\"\n  ToArmor: \"Rüstungsschaden Multiplikator\"\n  RandomArmor: \"Zufälliger Rüstungsschaden? \"\n  ToHealth: \"HP Schadensmultiplikator\"\n  RandomHealth: \"Zufälliger Verlust von Trefferpunkten?\"\n  ToStun: \"Betäubungsschaden Multiplikator\"\n  RandomStun: \"Zufälliger Betäubungsschaden?\"\n  ToWound: \"Wunden Multiplikator\"\n  RandomWound: \"Zufällige (originale) Verwundung\"\n  ToTime: \"Zeiteinheiten Schaden Multiplikator\"\n  RandomTime: \"Zufälliger Verlust von Zeiteinheiten?\"\n  ToEnergy: \"Energieschaden Multiplikator\"\n  RandomEnergy: \"Zufälliger Energieverlust?\"\n  ToMorale: \"Moralschaden Multiplikator\"\n  RandomMorale: \"Zufälliger Moralverlust?\"\n  ToItem: \"Gegenstandsschaden Multiplikator\"\n  RandomItem: \"Zufälliger Schaden an Gegenständen?\"\n  ToMana: \"Mana Schadensmultiplikator\"\n  RandomMana: \"Zufälliger Manaverlust?\"\n  ToTile: \"Terrain Schadensmultiplikator\"\n  RandomTile: \"Zufälliger Umgebungsschaden\"\n  TileDamageMethod: \"Fliesen-Schaden-Methode\"\n  TileDamageLimit: \"\"\n#\n  confAimed: \"Gezielte Aktion:\"\n  confAuto: \"Automatische Aktion\"\n  confSnap: \"Schnellaktion:\"\n  confMelee: \"Nahkampfaktion:\"\n  shots: \"Schüsse pro Aktion\"\n  spendPerShot: \"Kosten pro Schuss:\"\n  followProjectiles: \"Folge Projektilen?\"\n  name: \"Name\"\n  shortName: \"Kurzbezeichnung\"\n  ammoSlot: \"genutzte Munitionsplätze\"\n  ammoZombieUnitChanceOverride: \"\"\n  ammoSpawnUnitChanceOverride: \"\"\n  ammoSpawnItemChanceOverride: \"\"\n  arcing: \"Lichtbogenbildung?\"\n#\n  clipSize: \"Magazingröße\"\n  isAmmoRechargeable: \"\"\n#\n  primaryAmmo: \"Primärer Munitionsplatz\"\n  compatibleAmmo: \"Kompatible Munition\"\n  tuLoad: \"Kosten für Laden\"\n  tuUnload: \"Entladungskosten\"\n  ammo[1]: \"Extra Munitionsplatz #1\"\n  ammo[2]: \"Extra Munitionsplatz #2\"\n  ammo[3]: \"Extra Munitionsplatz #3\"\n#\n  armor: \"Rüstung\"\n#\n  medikitType: \"Medikit-Typ\"\n  painKillerActionName: \"\"\n  stimulantActionName: \"\"\n  healActionName: \"\"\n  medikitActionName: \"Bezeichnung der Medikit-Aktion\"\n  medikitTargetSelf: \"Medikit selbst benutzen?\"\n  medikitTargetImmune: \"Medikit bei Blutungsimmunen?\"\n  medikitTargetMatrix: \"Medikit Ziele\"\n  isConsumable: \"Verbrauchsgut\"\n  painKiller: \"Schmerzmittel nutzen\"\n  heal: \"Heilungen genutzt\"\n  stimulant: \"Stimulanzien genutzt\"\n  woundRecovery: \"Wundheilung\"\n  healthRecovery: \"Gesundheitsregeneration\"\n  stunRecovery: \"Betäubungswiederherstellung\"\n  energyRecovery: \"Energiewiederherstellung\"\n  manaRecovery: \"Mana-Wiederherstellung\"\n  moraleRecovery: \"Moralregeneration\"\n  painKillerRecovery: \"Schmerzmittel Stärke\"\n#\n  requires: \"Technologie benötigt\"\n  requiresBuy: \"Forschung benötigt zum Kaufen:\"\n  requiresBuyBaseFunc: \"Dienstleistungen benötigt um zu kaufen\"\n  requiresBuyCountry: \"Verbündetes Land erforderlich\"\n  requiresAward: \"\"\n  requiresBonus: \"\"\n  categories: \"Kategorien\"\n  supportedInventorySections: \"Inventarplätze\"\n#\n  size: \"Größe\"\n  costBuy: \"Kaufkosten\"\n  monthlyBuyLimit: \"Monatliches Kauflimit\"\n  costSell: \"Verkaufskosten\"\n  transferTime: \"Stunden zum Transfer\"\n  monthlySalary: \"Bezahlung/Monat\"\n  monthlyMaintenance: \"Wartungskosten/Monat\"\n#\n  SPECAB_NONE: \"Keine\"\n  SPECAB_EXPLODEONDEATH: \"Bei Tod explodieren\"\n  SPECAB_BURNFLOOR: \"Brennbarer Boden\"\n  SPECAB_BURN_AND_EXPLODE: \"Brennbarer Boden und bei Tod explodieren\"\n#\n  MT_WALK: \"Gehen\"\n  MT_FLY: \"Fliegen\"\n  MT_SLIDE: \"Rutschen\"\n  MT_FLOAT: \"Schweben\"\n  MT_SINK: \"Abtauchen\"\n#\n  TORSO_USE_GENDER: \"Nutze Geschlecht\"\n  TORSO_ALWAYS_MALE: \"Immer männlich\"\n  TORSO_ALWAYS_FEMALE: \"Immer weiblich\"\n#\n  DRAWING_ROUTINE_SOLDIER_SECTOID: \"Sektoidensoldat\"\n  DRAWING_ROUTINE_FLOATER: \"Schweber\"\n  DRAWING_ROUTINE_HWP: \"Schwere Waffen Plattform\"\n  DRAWING_ROUTINE_CYBERDISC: \"Cyberdisc\"\n  DRAWING_ROUTINE_CIVILIAN_ETHEREAL: \"Zivilist, Ätherer\"\n  DRAWING_ROUTINE_SECTOPOD_REAPER: \"Sektopode, Schnitter\"\n  DRAWING_ROUTINE_SNAKEMAN: \"Schlangenmensch\"\n  DRAWING_ROUTINE_CHRYSSALID: \"Chryssalid\"\n  DRAWING_ROUTINE_SILACOID: \"Silakoid\"\n  DRAWING_ROUTINE_CELATID: \"Celatid\"\n  DRAWING_ROUTINE_MUTON: \"Mutone\"\n  DRAWING_ROUTINE_SWS: \"Unterwasserwaffensysteme\"\n  DRAWING_ROUTINE_HALLUCINOID: \"Halluzinoide\"\n  DRAWING_ROUTINE_AQUANAUTS: \"Aquanauten\"\n  DRAWING_ROUTINE_CALCINITE_AND_MORE: \"Calcinite, Ungetüm, Kiemenmensch, Hummermensch, Tasoth\"\n  DRAWING_ROUTINE_AQUATOID: \"Aquatoide\"\n  DRAWING_ROUTINE_BIO_DRONE: \"Bio-Drone\"\n  DRAWING_ROUTINE_TFTD_CIVILIAN_A: \"TFTD Zivilist Typ A und TFTD Zombie\"\n  DRAWING_ROUTINE_TFTD_CIVILIAN_B: \"TFTD Zivilist Typ B\"\n  DRAWING_ROUTINE_TENTACULAT: \"Tentakulat\"\n  DRAWING_ROUTINE_TRISCENE: \"Triszene\"\n  DRAWING_ROUTINE_XARQUID: \"Xintfisch\"\n  DRAWING_ROUTINE_INVERTED_CYBERDISC: \"Umgekehrte Cyberdisc (Antriebsanimation oben)\"\n#\n  stats: \"Statistikmodifikatoren\"\n  specab: \"Spezielle Fähigkeit\"\n  movementType: \"Bewegungstyp\"\n  allowsRunning: \"Rennen erlauben?\"\n  allowsStrafing: \"Beschuss erlauben?\"\n  allowsSneaking: \"Schleichen erlauben?\"\n  allowsKneeling: \"Hinknien erlauben?\"\n  allowsMoving: \"Bewegung erlauben?\"\n  fearImmune: \"Immun gegen Moralverlust?\"\n  bleedImmune: \"Immun gegen blutende Wunden?\"\n  painImmune: \"Immun gegen Betäubung?\"\n  zombiImmune: \"Immun gegen Zombifizierung?\"\n  ignoresMeleeThreat: \"Ignoriert Nahkampfangriff?\"\n  createsMeleeThreat: \"Produziert Nahkampfangriff?\"\n  builtInWeapons: \"Eingebaute Gegenstände\"\n  specialWeapon: \"Spezialwaffe\"\n  heatVision: \"\"\n  visibilityThroughFire: \"\"\n  psiVision: \"Psi-Sinn\"\n  psiCamouflage: \"Psi Tarnung\"\n  visibilityAtDay: \"Sichtbarkeit bei Tag\"\n  visibilityAtDark: \"Sichtbarkeit bei Nacht\"\n  camouflageAtDay: \"Tarnung am Tag\"\n  camouflageAtDark: \"Tarnung bei Nacht\"\n  antiCamouflageAtDay: \"Enttarnung am Tag\"\n  antiCamouflageAtDark: \"Enttarnung bei Nacht\"\n  psiDefence: \"Psi-Verteidigung\"\n  meleeDodge: \"Nahkampfvermeidung\"\n  meleeDodgeBackPenalty: \"Nahkampfvermeidungsstrafe\"\n  recovery: \"Wiederherstellung pro Zug:\"\n  time: \"Zeit\"\n  energy: \"Energie\"\n  morale: \"Moral\"\n  health: \"Gesundheit\"\n  stun: \"Betäubung\"\n  mana: \"Mana\"\n  units: \"Kompatible Einheiten\"\n  ranks: \"\"\n  frontArmor: \"Rüstung vorn\"\n  sideArmor: \"Rüstung seitlich\"\n  leftArmorDiff: \"Differenz Rüstung links\"\n  rearArmor: \"Rüstung hinten\"\n  underArmor: \"Rüstung unten\"\n#\n  sizeX: \"Größe X\"\n  sizeY: \"Größe Y\"\n  buildCost: \"Baukosten\"\n  buildCostItems: \"Baumaterialien:\"\n  buildTime: \"Bauzeit\"\n  monthlyCost: \"monatliche Kosten\"\n  refundValue: \"Erstattungswert\"\n  requiresBaseFunc: \"Benötigt Basisfunktion\"\n  provideBaseFunc: \"Angebotene Dienste\"\n  forbiddenBaseFunc: \"Verbotene Dienste\"\n  lift: \"Hauptaufzug?\"\n  hyper: \"Hyperwellen-Decoder?\"\n  mind: \"Gedankenschild\"\n  mindPower: \"Gedankenschild Kraft\"\n  grav: \"Gravitationsschild\"\n  storage: \"Lagerplatz\"\n  personnel: \"Unterkünfte\"\n  aliens: \"Gefängnis Platz\"\n  crafts: \"Hangarplatz\"\n  labs: \"Laborplatz\"\n  workshops: \"Werkstattplatz\"\n  psiLabs: \"Psi-Labor Platz\"\n  trainingRooms: \"Trainingshalle Platz\"\n  sightRange: \"Sichtweite\"\n  sightChance: \"Sichtchance\"\n  radarRange: \"Radarreichweite\"\n  radarChance: \"Radar Chance\"\n  defense: \"Defensivwert\"\n  hitRatio: \"Trefferchance\"\n  ammoNeeded: \"Benötigte Munition\"\n  unifiedDamageFormula: \"\"\n  ammoItem: \"Munitionsartikel\"\n  maxAllowedPerBase: \"Maximal erlaubte pro Basis\"\n  manaRecoveryPerDay: \"Mana pro Tag\"\n  healthRecoveryPerDay: \"Gesundheit pro Tag\"\n  sickBayAbsoluteBonus: \"Gesamter Bonus der Krankenstation\"\n  sickBayRelativeBonus: \"Relativer Bonus der Krankenstation\"\n  prisonType: \"Gefängnistyp\"\n  rightClickActionType: \"Rechtsklick Aktion\"\n  leavesBehindOnSell: \"Hinterlassenschaften beim Verkauf\"\n  removalTime: \"Zeit für die Beseitigung\"\n  canBeBuiltOver: \"Kann überbaut werden?\"\n  upgradeOnly: \"\"\n  buildOverFacilities: \"Überbaubare Einrichtungen\"\n#\n  BFRCT_DEFAULT: \"Originale Voreinstellung\"\n  BFRCT_PRISON: \"Gehe zu Außerirdischen-Klimazelle\"\n  BFRCT_ENGINEERING: \"Gehe zur Herstellung\"\n  BFRCT_RESEARCH: \"Gehe zur Forschung\"\n  BFRCT_GYM: \"Gehe zur Kampfausbildung\"\n  BFRCT_PSI_LABS: \"Gehe zum Psionik Labor\"\n  BFRCT_BARRACKS: \"Gehe zur Kaserne\"\n  BFRCT_GREY_MARKET: \"Gehe zum Grauen Markt\"\n  BFRCT_GEOSCAPE: \"Gehe zu Geoscape\"\n#\n  costRent: \"Mietkosten\"\n  soldiers: \"Lagerraum\"\n  maxUnitsLimit: \"Maximaler Lagerraum\"\n  pilots: \"Cockpit Größe\"\n  pilotMinStatsRequired: \"\"\n  pilotSoldierBonusesRequired: \"\"\n  vehicles: \"SWT Kapazität\"\n  onlyOneSoldierGroupAllowed: \"Nur eine Soldatengruppe erlaubt?\"\n  allowedSoldierGroups: \"Erlaubte Soldatengruppen\"\n  allowedArmorGroups: \"\"\n  limitArmorGroups: \"\"\n  maxHWPUnitsLimit: \"Maximale SWT Kapazität\"\n  maxSmallSoldiers: \"Maximale Anzahl kleiner Soldaten\"\n  maxLargeSoldiers: \"Maximale Anzahl großer Soldaten\"\n  maxSmallVehicles: \"Maximale Anzahl kleiner Fahrzeuge\"\n  maxLargeVehicles: \"Maximale Anzahl großer Fahrzeuge\"\n  maxSmallUnits: \"Maximale Anzahl kleiner Einheiten\"\n  maxLargeUnits: \"Maximale Anzahl großer Einheiten\"\n  maxSoldiers: \"Maximale Soldatenanzahl\"\n  maxVehicles: \"Maximale Anzahl von Fahrzeugen\"\n  maxItems: \"Ausrüstungslimit\"\n  maxStorageSpace: \"Lagerplatz\"\n  maxAltitude: \"Höhenlimit für Luftkämpfe\"\n  weapons: \"Waffensysteme\"\n  weaponStrings: \"Waffennamen\"\n  fixedWeapons: \"Befestigte Waffen\"\n  weaponTypes: \"Erlaubte Waffentypen\"\n  damageMax: \"Schadenskapazität\"\n  avoidBonus: \"Ausweichbonus (pauschal)\"\n  avoidBonus2: \"\"\n  powerBonus: \"Stärkebonus (pauschal)\"\n  hitBonus: \"Trefferbonus (pauschal)\"\n  fuelMax: \"Treibstoffkapazität\"\n  speedMax: \"Maximale Geschwindigkeit\"\n  accel: \"Beschleunigung\"\n  shieldCapacity: \"Schildkapazität\"\n  shieldRecharge: \"Schildwiederherstellung (Kampf)\"\n  shieldRechargeInGeoscape: \"Schildwiederherstellung (Globus)\"\n  shieldBleedThrough: \"Schutzschilddurchdringung\"\n  shieldRechargedAtBase: \"Schildwiederherstellung  (Basis)\"\n  refuelItem: \"Gegenstand wiederauffüllen\"\n  refuelRate: \"Betankungsrate\"\n  repairRate: \"Reperaturrate\"\n  spacecraft: \"Finales Schiff`?\"\n  allowLanding: \"Erlaube Landungen?\"\n  notifyWhenRefueled: \"Benachrichtigung wenn vollständig betankt?\"\n  autoPatrol: \"Automatische Patrouille?\"\n  undetectable: \"Unentdeckbar?\"\n  patrolWithoutFuel: \"\"\n  keepCraftAfterFailedMission: \"Fallschirmjäger?\"\n  _calculatedValues: \"Kalkulierte Werte\"\n  _maxRange: \"Reichweite maximal\"\n  _minRange: \"Reichweite minimal\"\n  _avgRange: \"Reichweite durchschnitt\"\n#\n  hunterKillerPercentage: \"Jäger-killer Chance\"\n  huntMode: \"Jagdmodus\"\n  huntSpeed: \"Jagdgeschwindigkeit\"\n  huntBehavior: \"Jagdverhalten\"\n  range: \"Reichweite\"\n  reload: \"Nachladezeit\"\n  breakOffTime: \"Abbruchzeit\"\n  score: \"Punktzahl\"\n  missionScore: \"Missionsbewertung\"\n  craftCustomDeploy: \"Benutzerdefinierte UFO Aufstellung\"\n  missionCustomDeploy: \"Benutzerdefinierte Missions-Aufstellung\"\n  _escapeCountdown: \"Rückzugs-Countdown\"\n  _fireRate: \"Feuerrate\"\n  _averageDPM: \"Durchschnittlicher Schaden pro Minute\"\n#\n  HM_INTERCEPTORS: \"Abfangjäger bevorzugen\"\n  HM_TRANSPORTS: \"Jagdtransporter bevorzugen\"\n  HM_RANDOM: \"zufällig\"\n#\n  HB_FLEE: \"Flüchte, bei Gefahr zu verlieren\"\n  HB_KAMIKAZE: \"Kampf bis zur Zerstörung\"\n  HB_RANDOM: \"zufällig\"\n#\n  tractorBeamPower: \"Traktorstrahlkraft\"\n  damage: \"Schaden\"\n  shieldDamageModifier: \"Schutzschild Schadensmodifikator\"\n  accuracy: \"Genauigkeit\"\n  reloadCautious: \"Nachladen (Vorsichtig)\"\n  reloadStandard: \"Nachladen (Standard)\"\n  reloadAggressive: \"Nachladen (Aggressiv)\"\n  launcher: \"Werfer Gegenstand\"\n  weaponType: \"Waffentyp\"\n  clip: \"Magazin Gegenstand\"\n  ammoMax: \"Kugeln/Patronen\"\n  rearmRate: \"Wiederbewaffnungsrate\"\n  bulletSaving: \"Munition sparen?\"\n  _damageRange: \"\"\n  _damageRangeBasic: \"\"\n  _averageTotalDamage: \"Durchschnittlicher Gesamtschaden\"\n#\n  allowPiloting: \"\"\n  costSalary: \"\"\n  costSalarySquaddie: \"\"\n  costSalarySergeant: \"\"\n  costSalaryCaptain: \"\"\n  costSalaryColonel: \"\"\n  costSalaryCommander: \"\"\n#\n  race: \"\"\n  rank: \"\"\n  livingWeapon: \"\"\n  meleeWeapon: \"Nahkampfwaffe\"\n  psiWeapon: \"\"\n  _builtInWeaponSets: \"\"\n  _weightedBuiltInWeaponSets: \"\"\n  spawnUnit: \"\"\n  _capturable: \"\"\n  capturable: \"\"\n  canSurrender: \"\"\n  autoSurrender: \"\"\n  spotter: \"\"\n  sniper: \"\"\n"
  },
  {
    "path": "bin/common/Language/Technical/el.yml",
    "content": "el:\n#=================== Menu ===================\n#TestState.cpp\n  STR_BAD_NODES: \"Κακοί κόμβοι σε αρχεία RMP\"\n  STR_BAD_NODES_DESC: \"Ελέγχει τα αρχεία RMP για κόμβους εκτός των ορίων του χάρτη.{NEWLINE}Αυτά ΔΕΝ θα προκαλέσουν σφάλματα, αλλά θα αγνοηθούν από το παιχνίδι, επομένως δεν λειτουργούν όπως προβλέπεται.\"\n#\n  STR_MCD_CHECK: \"MCD έλεγχοι\"\n  STR_MCD_CHECK_DESC: \"Ελέγχει αρχεία MCD για αντικείμενα δαπέδου με μηδενικό κόστος κίνησης. Επίσης ελέγχει για μη έγκυρες αναφορές DieMCD/AltMCD. επίσης ελέγχει μη έγκυρα LOFTemps.\"\n#\n  STR_PALETTE_CHECK: \"Ταίριασμα παλέτας\"\n  STR_PALETTE_CHECK_DESC: \"Προσπαθεί να αντιστοιχίσει παλέτες τροποποιημένων εικόνων με επίσημες παλέτες και αναφέρει οποιεσδήποτε εικόνες δεν έχουν 100% αντιστοιχία.\"\n#\n  STR_SCRIPT_TAGS: \"Εξαγωγή ετικέτας σεναρίου\"\n  STR_SCRIPT_TAGS_DESC: \"Εξαγωγή ετικέτας σεναρίου σε CSV τύπο.\"\n#\n  STR_MAP_RESOURCES: \"Έλεγχος πόρων χάρτη\"\n  STR_MAP_RESOURCES_DESC: \"Ελέγχει για αρχεία και σύνολο κανόνων που λείπουν και δεν χρησιμοποιούνται.\"\n#\n  STR_CHECKING_TERRAIN: \"Έλεγχος εδάφους...\"\n  STR_CHECKING_UFOS: \"Έλεγχος ΑΤΙΑ...\"\n  STR_CHECKING_CRAFT: \"Έλεγχος σκάφους...\"\n#\n  BACKPALS.DAT: \"BACKPALS.DAT\"\n  PAL_GEOSCAPE: \"PAL_GEOSCAPE\"\n  PAL_BASESCAPE: \"PAL_BASESCAPE\"\n  PAL_GRAPHS: \"PAL_GRAPHS\"\n  PAL_UFOPAEDIA: \"PAL_UFOPAEDIA\"\n  PAL_BATTLEPEDIA: \"PAL_BATTLEPEDIA\"\n  PAL_BATTLESCAPE: \"PAL_BATTLESCAPE\"\n  PAL_BATTLESCAPE_1: \"PAL_BATTLESCAPE_1\"\n  PAL_BATTLESCAPE_2: \"PAL_BATTLESCAPE_2\"\n  PAL_BATTLESCAPE_3: \"PAL_BATTLESCAPE_3\"\n#=================== Ufopaedia ===================\n#StatsForNerdsState.cpp\n  BT_NONE: \"Κανένα\"\n  BT_FIREARM: \"Όπλο\"\n  BT_AMMO: \"Σφαίρα\"\n  BT_MELEE: \"Όπλο χειρός\"\n  BT_GRENADE: \"Χειροβομβίδα\"\n  BT_PROXIMITYGRENADE: \"Χειροβομβίδα ανίχνευσης\"\n  BT_MEDIKIT: \"Κιτ πρώτων βοηθειών\"\n  BT_SCANNER: \"Σαρωτής κίνησης\"\n  BT_MINDPROBE: \"Έρευνα νου\"\n  BT_PSIAMP: \"Psi Amp\"\n  BT_FLARE: \"Φωτοβολίδα\"\n  BT_CORPSE: \"Πτώμα/Σώμα\"\n#\n  DRT_DEFAULT: \"απλή προεπιλογή\"\n  DRT_UFO: \"0-200% εξάπλωση\"\n  DRT_TFTD: \"50-150% εξάπλωση\"\n  DRT_FLAT: \"επίπεδη βλάβη\"\n  DRT_FIRE: \"ειδική ζημιά από πυρά\"\n  DRT_NONE: \"καμία ζημιά\"\n  DRT_UFO_WITH_TWO_DICE: \"0-200% διασπορά (2 ζαριές)\"\n  DRT_EASY: \"50-200% διασπορά\"\n  DRT_STANDARD: \"τυπικό εύρος βλάβης\"\n  DRT_EXPLOSION: \"εύρος ζημιάς έκρηξης\"\n#\n  BFT_NONE: \"ουδείς\"\n  BFT_INSTANT: \"άμεσο\"\n  BFT_SET: \"ρυθμίζεται χειροκίνητα\"\n  BFT_FIXED: \"επισκευασμένο\"\n#\n  BMT_NORMAL: \"τυπικό (πολλαπλών χρήσεων)\"\n  BMT_HEAL: \"θεραπεία\"\n  BMT_STIMULANT: \"τονωτικό\"\n  BMT_PAINKILLER: \"παυσίπονο\"\n#\n  ETM_DEFAULT: \"προεπιλογή\"\n  ETM_MELEE_100: \"ΣΩΜΑ ΜΕ ΣΩΜΑ\"\n  ETM_MELEE_50: \"ΣΩΜΑ ΜΕ ΣΩΜΑ (50% chance)\"\n  ETM_MELEE_33: \"ΣΩΜΑ ΜΕ ΣΩΜΑ (33% chance)\"\n  ETM_FIRING_100: \"ΒΟΛΗ\"\n  ETM_FIRING_50: \"ΒΟΛΗ (50% chance)\"\n  ETM_FIRING_33: \"ΒΟΛΗ (33% chance)\"\n  ETM_THROWING_100: \"ΡΙΨΗ\"\n  ETM_THROWING_50: \"ΡΙΨΗ (50% chance)\"\n  ETM_THROWING_33: \"ΡΙΨΗ (33% chance)\"\n  ETM_FIRING_AND_THROWING: \"ΒΟΛΗ και ΡΙΨΗ\"\n  ETM_FIRING_OR_THROWING: \"ΒΟΛΗ ή ΡΙΨΗ\"\n  ETM_REACTIONS: \"ΑΝΤΙΔΡΑΣΕΙΣ\"\n  ETM_REACTIONS_AND_MELEE: \"ΑΝΤΙΔΡΑΣΕΙΣ και ΣΩΜΑ ΜΕ ΣΩΜΑ\"\n  ETM_REACTIONS_AND_FIRING: \"ΑΝΤΙΔΡΑΣΕΙΣ και ΒΟΛΗ\"\n  ETM_REACTIONS_AND_THROWING: \"ΑΝΤΙΔΡΑΣΕΙΣ και ΡΙΨΗ\"\n  ETM_REACTIONS_OR_MELEE: \"ΑΝΤΙΔΡΑΣΕΙΣ ή ΣΩΜΑ ΜΕ ΣΩΜΑ\"\n  ETM_REACTIONS_OR_FIRING: \"ΑΝΤΙΔΡΑΣΕΙΣ ή ΒΟΛΗ\"\n  ETM_REACTIONS_OR_THROWING: \"ΑΝΤΙΔΡΑΣΕΙΣ ή ΡΙΨΗ\"\n  ETM_BRAVERY: \"ΑΝΔΡΕΙΑ\"\n  ETM_BRAVERY_2X: \"ΑΝΔΡΕΙΑ (x2)\"\n  ETM_BRAVERY_AND_REACTIONS: \"ΑΝΔΡΕΙΑ και ΑΝΤΙΔΡΑΣΕΙΣ\"\n  ETM_BRAVERY_OR_REACTIONS: \"ΑΝΔΡΕΙΑ ή ΑΝΤΙΔΡΑΣΕΙΣ\"\n  ETM_BRAVERY_OR_REACTIONS_2X: \"ΑΝΔΡΕΙΑ και ΑΝΤΙΔΡΑΣΕΙΣ (x2)\"\n  ETM_PSI_STRENGTH: \"Ψ ΔΥΝΑΜΗ\"\n  ETM_PSI_STRENGTH_2X: \"Ψ ΔΥΝΑΜΗ (x2)\"\n  ETM_PSI_SKILL: \"Ψ ΔΕΞΙΟΤΕΧΝΙΑ\"\n  ETM_PSI_SKILL_2X: \"Ψ ΔΕΞΙΟΤΕΧΝΙΑ (x2)\"\n  ETM_PSI_STRENGTH_AND_SKILL: \"Ψ ΔΥΝΑΜΗ και Ψ ΔΕΞΙΟΤΕΧΝΙΑ\"\n  ETM_PSI_STRENGTH_AND_SKILL_2X: \"Ψ ΔΥΝΑΜΗ και Ψ ΔΕΞΙΟΤΕΧΝΙΑ (x2)\"\n  ETM_PSI_STRENGTH_OR_SKILL: \"Ψ ΔΥΝΑΜΗ ή Ψ ΔΕΞΙΟΤΕΧΝΙΑ\"\n  ETM_PSI_STRENGTH_OR_SKILL_2X: \"Ψ ΔΥΝΑΜΗ ή Ψ ΔΕΞΙΟΤΕΧΝΙΑ (x2)\"\n  ETM_NOTHING: \"καμία εκπαίδευση\"\n#\n  battleType: \"Τύπος αντικειμένου\"\n  experienceTrainingMode: \"Λειτουργία εμπειρίας\"\n  manaExperience: \"Εμπειρία μαγείας\"\n  arcingShot: \"Τόξο;\"\n  isFireExtinguisher: \"Πυροσβεστήρας;\"\n  explodeInventory: \"Εκρήγνυται στις αποσκευές;\"\n  waypoints: \"Μέγιστα σημεία\"\n  sprayWaypoints: \"Σημεία βολής με διασπορά\"\n#\n  shotgunPellets: \"Αριθμός πέλλετ\"\n  shotgunBehavior: \"Συμπεριφορά καραμπίνας\"\n  shotgunSpread: \"Διασπορά καραμπίνας\"\n  shotgunChoke: \"Τσοκ καραμπίνας\"\n#\n  underwaterOnly: \"Μόνο υποβρύχιο;\"\n  landOnly: \"Μόνο επίγειο;\"\n  psiRequired: \"Απαιτείται δεξιότητα Ψ;\"\n  targetMatrix: \"Στόχοι αντικειμένων\"\n  convertToCivilian: \"Μετατροπή σε πολίτη;\"\n  manaRequired: \"Απαιτείται μαγεία;\"\n  LOSRequired: \"Απαιτείται όραση;\"\n#\n  noLOSAccuracyPenalty: \"Πολλαπλασιαστής πέναλτι χωρίς όραση.\"\n  kneelBonus: \"Πολλαπλαστιαστής μπόνους γονυπετής\"\n  twoHanded: \"Δίχειρα;\"\n  blockBothHands: \"Μπλοκάρει και τα δύο χέρια;\"\n  oneHandedPenalty: \"Ποινή χρήσης με το ένα χέρι\"\n#\n  minRange: \"Ελάχιστη εμβέλεια\"\n  maxRange: \"Μέγιστη εμβέλεια\"\n  aimRange: \"Στοχευμένη εμβέλεια βολής\"\n  autoRange: \"Αυτόματη εμβέλεια βολής\"\n  snapRange: \"Βιαστική εμβέλεια βολής\"\n  dropoff: \"Πτώση ευστοχίας/πλακίδιο\"\n#\n  accuracyMultiplier: \"Πολλαπλασιαστής ευστοχίας βολής\"\n  accuracyAimed: \"Ακρίβεια στοχευμένης βολής\"\n  accuracyAuto: \"Ακρίβεια αυτόματης βολής\"\n  accuracySnap: \"Ακρίβεια βιαστικής βολής\"\n  costAimed: \"Κόστος στοχευμένης βολής\"\n  costAuto: \"Κόστος αυτόματης βολής\"\n  costSnap: \"Κόστος βιαστικής βολής\"\n#\n  meleeMultiplier: \"Πολλαπλασιαστής ευστοχίας σώμα με σώμα\"\n  accuracyMelee: \"Ευστοχία σώμα με σώμα\"\n  costMelee: \"Κόστος σώμα με σώμα\"\n#\n  psiAttackName: \"Ψ επίθεση ονομασία\"\n  accuracyUse: \"Ακρίβεια δράσης\"\n  accuracyMindControl: \"Ακρίβεια ελέγχου μυαλού\"\n  accuracyPanic: \"Ακρίβεια πανικού\"\n  costUse: \"Κόστος δράσης\"\n  costMindcontrol: \"Κόστος ελέγχου μυαλού\"\n  costPanic: \"Πανικός κόστος\"\n#\n  weight: \"Βάρος\"\n  throwRange: \"Ρίψη μαξ (αέρας)\"\n  underwaterThrowRange: \"Ρίψη μαξ (νερό)\"\n  throwDropoffRange: \"Ρίψη απόσταση (αέρας)\"\n  underwaterThrowDropoffRange: \"Ρίψη απόσταση (νερό)\"\n  throwDropoff: \"Ρίψη ευστοχίας/πλακίδιο\"\n  throwMultiplier: \"Πολλαπλασιαστής ακρίβειας ρίψης\"\n  accuracyThrow: \"Ακρίβεια ρίψης\"\n  costThrow: \"Κόστος ρίψης\"\n  costPrime: \"Κόστος εκκίνησης\"\n  costUnprime: \"Κόστος χωρίς εκκίνηση\"\n#\n  closeQuartersMultiplier: \"Πολλαπλασιαστής ακρίβειας MET\"\n  accuracyCloseQuarters: \"Ακρίβεια MET\"\n#\n  damageType: \"Τύπος ζημιάς\"\n  power: \"Δύναμη\"\n  powerRangeReduction: \"Δύναμη μείωση/πλακίδιο\"\n  powerRangeThreshold: \"Δύναμη μείωση κατώτατου ορίου\"\n  damageBonus: \"Μπόνους ζημιάς\"\n  blastRadius: \"Ακτίνα έκρηξης\"\n  damageAlter: \"Πρόσθετες πληροφορίες ζημιάς:\"\n  meleeType: \"Τύπος σημιάς σώμα με σώμα\"\n  meleePower: \"Δύναμη σώμα με σώμα\"\n  meleeBonus: \"Μπόνους δύναμης σώμα με σώμα\"\n  meleeAlter: \"Έξτρα πληροφορίες σώμα με σώμα\"\n  FixRadius: \"Ακτίνα έκρηξης\"\n  RandomType: \"Τύπος υπολογισμού\"\n  FireBlastCalc: \"Εφέ φωτιάς πρώτης έκδοσης;\"\n  IgnoreDirection: \"Αγνόηση κατεύθυνσης\"\n  IgnoreSelfDestruct: \"Αγνοήστε την αυτοκαταστροφή\"\n  IgnorePainImmunity: \"Αγνοήστε την ανοσία αναισθητοποίησης\"\n  IgnoreNormalMoraleLose: \"Αγνοήστε απλή απώλεια ηθικού\"\n  IgnoreOverKill: \"Αγνόηση υπερβολής\"\n  ArmorEffectiveness: \"Αποτελεσματικότητα θωράκισης\"\n  RadiusEffectiveness: \"Ακτίνα αποτελεσματικότητας\"\n  RadiusReduction: \"Μείωση ζημιάς ακτίνας\"\n  FireThreshold: \"\"\n  SmokeThreshold: \"\"\n#\n  ToArmorPre: \"\"\n  RandomArmorPre: \"\"\n  ToArmor: \"\"\n  RandomArmor: \"\"\n  ToHealth: \"\"\n  RandomHealth: \"\"\n  ToStun: \"\"\n  RandomStun: \"\"\n  ToWound: \"\"\n  RandomWound: \"\"\n  ToTime: \"\"\n  RandomTime: \"\"\n  ToEnergy: \"\"\n  RandomEnergy: \"\"\n  ToMorale: \"\"\n  RandomMorale: \"\"\n  ToItem: \"\"\n  RandomItem: \"\"\n  ToMana: \"\"\n  RandomMana: \"\"\n  ToTile: \"\"\n  RandomTile: \"\"\n  TileDamageMethod: \"\"\n  TileDamageLimit: \"\"\n#\n  confAimed: \"\"\n  confAuto: \"\"\n  confSnap: \"\"\n  confMelee: \"\"\n  shots: \"\"\n  spendPerShot: \"\"\n  followProjectiles: \"\"\n  name: \"\"\n  shortName: \"\"\n  ammoSlot: \"\"\n  ammoZombieUnitChanceOverride: \"\"\n  ammoSpawnUnitChanceOverride: \"\"\n  ammoSpawnItemChanceOverride: \"\"\n  arcing: \"Τόξο;\"\n#\n  clipSize: \"\"\n  isAmmoRechargeable: \"\"\n#\n  primaryAmmo: \"\"\n  compatibleAmmo: \"\"\n  tuLoad: \"\"\n  tuUnload: \"\"\n  ammo[1]: \"\"\n  ammo[2]: \"\"\n  ammo[3]: \"\"\n#\n  armor: \"\"\n#\n  medikitType: \"\"\n  painKillerActionName: \"\"\n  stimulantActionName: \"\"\n  healActionName: \"\"\n  medikitActionName: \"\"\n  medikitTargetSelf: \"\"\n  medikitTargetImmune: \"\"\n  medikitTargetMatrix: \"\"\n  isConsumable: \"\"\n  painKiller: \"\"\n  heal: \"\"\n  stimulant: \"\"\n  woundRecovery: \"\"\n  healthRecovery: \"\"\n  stunRecovery: \"\"\n  energyRecovery: \"\"\n  manaRecovery: \"\"\n  moraleRecovery: \"\"\n  painKillerRecovery: \"\"\n#\n  requires: \"\"\n  requiresBuy: \"\"\n  requiresBuyBaseFunc: \"\"\n  requiresBuyCountry: \"\"\n  requiresAward: \"\"\n  requiresBonus: \"\"\n  categories: \"\"\n  supportedInventorySections: \"\"\n#\n  size: \"\"\n  costBuy: \"\"\n  monthlyBuyLimit: \"\"\n  costSell: \"\"\n  transferTime: \"\"\n  monthlySalary: \"\"\n  monthlyMaintenance: \"\"\n#\n  SPECAB_NONE: \"Κανένα\"\n  SPECAB_EXPLODEONDEATH: \"\"\n  SPECAB_BURNFLOOR: \"\"\n  SPECAB_BURN_AND_EXPLODE: \"\"\n#\n  MT_WALK: \"\"\n  MT_FLY: \"\"\n  MT_SLIDE: \"\"\n  MT_FLOAT: \"\"\n  MT_SINK: \"\"\n#\n  TORSO_USE_GENDER: \"\"\n  TORSO_ALWAYS_MALE: \"\"\n  TORSO_ALWAYS_FEMALE: \"\"\n#\n  DRAWING_ROUTINE_SOLDIER_SECTOID: \"\"\n  DRAWING_ROUTINE_FLOATER: \"\"\n  DRAWING_ROUTINE_HWP: \"\"\n  DRAWING_ROUTINE_CYBERDISC: \"\"\n  DRAWING_ROUTINE_CIVILIAN_ETHEREAL: \"\"\n  DRAWING_ROUTINE_SECTOPOD_REAPER: \"\"\n  DRAWING_ROUTINE_SNAKEMAN: \"\"\n  DRAWING_ROUTINE_CHRYSSALID: \"\"\n  DRAWING_ROUTINE_SILACOID: \"\"\n  DRAWING_ROUTINE_CELATID: \"\"\n  DRAWING_ROUTINE_MUTON: \"\"\n  DRAWING_ROUTINE_SWS: \"\"\n  DRAWING_ROUTINE_HALLUCINOID: \"\"\n  DRAWING_ROUTINE_AQUANAUTS: \"\"\n  DRAWING_ROUTINE_CALCINITE_AND_MORE: \"\"\n  DRAWING_ROUTINE_AQUATOID: \"\"\n  DRAWING_ROUTINE_BIO_DRONE: \"\"\n  DRAWING_ROUTINE_TFTD_CIVILIAN_A: \"\"\n  DRAWING_ROUTINE_TFTD_CIVILIAN_B: \"\"\n  DRAWING_ROUTINE_TENTACULAT: \"\"\n  DRAWING_ROUTINE_TRISCENE: \"\"\n  DRAWING_ROUTINE_XARQUID: \"\"\n  DRAWING_ROUTINE_INVERTED_CYBERDISC: \"\"\n#\n  stats: \"\"\n  specab: \"\"\n  movementType: \"\"\n  allowsRunning: \"\"\n  allowsStrafing: \"\"\n  allowsSneaking: \"\"\n  allowsKneeling: \"\"\n  allowsMoving: \"\"\n  fearImmune: \"\"\n  bleedImmune: \"\"\n  painImmune: \"\"\n  zombiImmune: \"\"\n  ignoresMeleeThreat: \"\"\n  createsMeleeThreat: \"\"\n  builtInWeapons: \"\"\n  specialWeapon: \"\"\n  heatVision: \"\"\n  visibilityThroughFire: \"\"\n  psiVision: \"\"\n  psiCamouflage: \"\"\n  visibilityAtDay: \"\"\n  visibilityAtDark: \"\"\n  camouflageAtDay: \"\"\n  camouflageAtDark: \"\"\n  antiCamouflageAtDay: \"\"\n  antiCamouflageAtDark: \"\"\n  psiDefence: \"\"\n  meleeDodge: \"\"\n  meleeDodgeBackPenalty: \"\"\n  recovery: \"\"\n  time: \"\"\n  energy: \"Ενέργεια\"\n  morale: \"\"\n  health: \"\"\n  stun: \"\"\n  mana: \"\"\n  units: \"\"\n  ranks: \"\"\n  frontArmor: \"\"\n  sideArmor: \"\"\n  leftArmorDiff: \"\"\n  rearArmor: \"\"\n  underArmor: \"\"\n#\n  sizeX: \"\"\n  sizeY: \"\"\n  buildCost: \"\"\n  buildCostItems: \"\"\n  buildTime: \"\"\n  monthlyCost: \"\"\n  refundValue: \"\"\n  requiresBaseFunc: \"\"\n  provideBaseFunc: \"\"\n  forbiddenBaseFunc: \"\"\n  lift: \"\"\n  hyper: \"\"\n  mind: \"\"\n  mindPower: \"\"\n  grav: \"\"\n  storage: \"\"\n  personnel: \"\"\n  aliens: \"\"\n  crafts: \"\"\n  labs: \"\"\n  workshops: \"\"\n  psiLabs: \"\"\n  trainingRooms: \"\"\n  sightRange: \"\"\n  sightChance: \"\"\n  radarRange: \"\"\n  radarChance: \"\"\n  defense: \"\"\n  hitRatio: \"\"\n  ammoNeeded: \"\"\n  unifiedDamageFormula: \"\"\n  ammoItem: \"\"\n  maxAllowedPerBase: \"\"\n  manaRecoveryPerDay: \"\"\n  healthRecoveryPerDay: \"\"\n  sickBayAbsoluteBonus: \"\"\n  sickBayRelativeBonus: \"\"\n  prisonType: \"\"\n  rightClickActionType: \"\"\n  leavesBehindOnSell: \"\"\n  removalTime: \"\"\n  canBeBuiltOver: \"\"\n  upgradeOnly: \"\"\n  buildOverFacilities: \"\"\n#\n  BFRCT_DEFAULT: \"απλή προεπιλογή\"\n  BFRCT_PRISON: \"\"\n  BFRCT_ENGINEERING: \"\"\n  BFRCT_RESEARCH: \"\"\n  BFRCT_GYM: \"\"\n  BFRCT_PSI_LABS: \"\"\n  BFRCT_BARRACKS: \"\"\n  BFRCT_GREY_MARKET: \"\"\n  BFRCT_GEOSCAPE: \"\"\n#\n  costRent: \"\"\n  soldiers: \"\"\n  maxUnitsLimit: \"\"\n  pilots: \"\"\n  pilotMinStatsRequired: \"\"\n  pilotSoldierBonusesRequired: \"\"\n  vehicles: \"\"\n  onlyOneSoldierGroupAllowed: \"\"\n  allowedSoldierGroups: \"\"\n  allowedArmorGroups: \"\"\n  limitArmorGroups: \"\"\n  maxHWPUnitsLimit: \"\"\n  maxSmallSoldiers: \"\"\n  maxLargeSoldiers: \"\"\n  maxSmallVehicles: \"\"\n  maxLargeVehicles: \"\"\n  maxSmallUnits: \"\"\n  maxLargeUnits: \"\"\n  maxSoldiers: \"\"\n  maxVehicles: \"\"\n  maxItems: \"\"\n  maxStorageSpace: \"\"\n  maxAltitude: \"\"\n  weapons: \"\"\n  weaponStrings: \"\"\n  fixedWeapons: \"\"\n  weaponTypes: \"\"\n  damageMax: \"\"\n  avoidBonus: \"\"\n  avoidBonus2: \"\"\n  powerBonus: \"\"\n  hitBonus: \"\"\n  fuelMax: \"\"\n  speedMax: \"\"\n  accel: \"\"\n  shieldCapacity: \"\"\n  shieldRecharge: \"\"\n  shieldRechargeInGeoscape: \"\"\n  shieldBleedThrough: \"\"\n  shieldRechargedAtBase: \"\"\n  refuelItem: \"\"\n  refuelRate: \"\"\n  repairRate: \"\"\n  spacecraft: \"\"\n  allowLanding: \"\"\n  notifyWhenRefueled: \"\"\n  autoPatrol: \"\"\n  undetectable: \"\"\n  patrolWithoutFuel: \"\"\n  keepCraftAfterFailedMission: \"\"\n  _calculatedValues: \"\"\n  _maxRange: \"Μέγιστη εμβέλεια\"\n  _minRange: \"Ελάχιστη εμβέλεια\"\n  _avgRange: \"\"\n#\n  hunterKillerPercentage: \"\"\n  huntMode: \"\"\n  huntSpeed: \"\"\n  huntBehavior: \"\"\n  range: \"\"\n  reload: \"\"\n  breakOffTime: \"\"\n  score: \"\"\n  missionScore: \"\"\n  craftCustomDeploy: \"\"\n  missionCustomDeploy: \"\"\n  _escapeCountdown: \"\"\n  _fireRate: \"\"\n  _averageDPM: \"\"\n#\n  HM_INTERCEPTORS: \"\"\n  HM_TRANSPORTS: \"\"\n  HM_RANDOM: \"\"\n#\n  HB_FLEE: \"\"\n  HB_KAMIKAZE: \"\"\n  HB_RANDOM: \"\"\n#\n  tractorBeamPower: \"\"\n  damage: \"\"\n  shieldDamageModifier: \"\"\n  accuracy: \"\"\n  reloadCautious: \"\"\n  reloadStandard: \"\"\n  reloadAggressive: \"\"\n  launcher: \"\"\n  weaponType: \"\"\n  clip: \"\"\n  ammoMax: \"\"\n  rearmRate: \"\"\n  bulletSaving: \"\"\n  _damageRange: \"\"\n  _damageRangeBasic: \"\"\n  _averageTotalDamage: \"\"\n#\n  allowPiloting: \"\"\n  costSalary: \"\"\n  costSalarySquaddie: \"\"\n  costSalarySergeant: \"\"\n  costSalaryCaptain: \"\"\n  costSalaryColonel: \"\"\n  costSalaryCommander: \"\"\n#\n  race: \"\"\n  rank: \"\"\n  livingWeapon: \"\"\n  meleeWeapon: \"Όπλο χειρός\"\n  psiWeapon: \"\"\n  _builtInWeaponSets: \"\"\n  _weightedBuiltInWeaponSets: \"\"\n  spawnUnit: \"\"\n  _capturable: \"\"\n  capturable: \"\"\n  canSurrender: \"\"\n  autoSurrender: \"\"\n  spotter: \"\"\n  sniper: \"\"\n"
  },
  {
    "path": "bin/common/Language/Technical/en-GB.yml",
    "content": "en-GB:\n#=================== Menu ===================\n#TestState.cpp\n  STR_BAD_NODES: \"Bad nodes in RMP files\"\n  STR_BAD_NODES_DESC: \"Checks RMP files for nodes outside of map boundaries.{NEWLINE}These will NOT cause any crashes, but they will be ignored by the game, thus not work as intended.\"\n#\n  STR_MCD_CHECK: \"MCD checks\"\n  STR_MCD_CHECK_DESC: \"Checks MCD files for floor objects with zero movement cost; also checks for invalid DieMCD/AltMCD references; also checks invalid LOFTemps.\"\n#\n  STR_PALETTE_CHECK: \"Palette matching\"\n  STR_PALETTE_CHECK_DESC: \"Tries to match palettes of modded images to official palettes and reports any images that don't have a 100% match.\"\n#\n  STR_SCRIPT_TAGS: \"Script tag export\"\n  STR_SCRIPT_TAGS_DESC: \"Exports script tags in CSV format.\"\n#\n  STR_MAP_RESOURCES: \"Map resources check\"\n  STR_MAP_RESOURCES_DESC: \"Checks for missing and unused map-related files and ruleset.\"\n#\n  STR_CHECKING_TERRAIN: \"Checking terrain...\"\n  STR_CHECKING_UFOS: \"Checking UFOs...\"\n  STR_CHECKING_CRAFT: \"Checking craft...\"\n#\n  BACKPALS.DAT: \"BACKPALS.DAT\"\n  PAL_GEOSCAPE: \"PAL_GEOSCAPE\"\n  PAL_BASESCAPE: \"PAL_BASESCAPE\"\n  PAL_GRAPHS: \"PAL_GRAPHS\"\n  PAL_UFOPAEDIA: \"PAL_UFOPAEDIA\"\n  PAL_BATTLEPEDIA: \"PAL_BATTLEPEDIA\"\n  PAL_BATTLESCAPE: \"PAL_BATTLESCAPE\"\n  PAL_BATTLESCAPE_1: \"PAL_BATTLESCAPE_1\"\n  PAL_BATTLESCAPE_2: \"PAL_BATTLESCAPE_2\"\n  PAL_BATTLESCAPE_3: \"PAL_BATTLESCAPE_3\"\n#=================== Ufopaedia ===================\n#StatsForNerdsState.cpp\n  BT_NONE: \"None\"\n  BT_FIREARM: \"Firearm\"\n  BT_AMMO: \"Ammo\"\n  BT_MELEE: \"Melee weapon\"\n  BT_GRENADE: \"Grenade\"\n  BT_PROXIMITYGRENADE: \"Proximity grenade\"\n  BT_MEDIKIT: \"Medikit\"\n  BT_SCANNER: \"Motion scanner\"\n  BT_MINDPROBE: \"Mind probe\"\n  BT_PSIAMP: \"Psi Amp\"\n  BT_FLARE: \"Flare\"\n  BT_CORPSE: \"Corpse/Body\"\n#\n  DRT_DEFAULT: \"vanilla default\"\n  DRT_UFO: \"0-200% spread\"\n  DRT_TFTD: \"50-150% spread\"\n  DRT_FLAT: \"flat damage\"\n  DRT_FIRE: \"special fire damage\"\n  DRT_NONE: \"no damage\"\n  DRT_UFO_WITH_TWO_DICE: \"0-200% spread (2 dice roll)\"\n  DRT_EASY: \"50-200% spread\"\n  DRT_STANDARD: \"standard damage range\"\n  DRT_EXPLOSION: \"explosion damage range\"\n#\n  BFT_NONE: \"none\"\n  BFT_INSTANT: \"instant\"\n  BFT_SET: \"manually set\"\n  BFT_FIXED: \"fixed\"\n#\n  BMT_NORMAL: \"standard (multi-purpose)\"\n  BMT_HEAL: \"heal\"\n  BMT_STIMULANT: \"stimulant\"\n  BMT_PAINKILLER: \"painkiller\"\n#\n  ETM_DEFAULT: \"default\"\n  ETM_MELEE_100: \"MELEE\"\n  ETM_MELEE_50: \"MELEE (50% chance)\"\n  ETM_MELEE_33: \"MELEE (33% chance)\"\n  ETM_FIRING_100: \"FIRING\"\n  ETM_FIRING_50: \"FIRING (50% chance)\"\n  ETM_FIRING_33: \"FIRING (33% chance)\"\n  ETM_THROWING_100: \"THROWING\"\n  ETM_THROWING_50: \"THROWING (50% chance)\"\n  ETM_THROWING_33: \"THROWING (33% chance)\"\n  ETM_FIRING_AND_THROWING: \"FIRING and THROWING\"\n  ETM_FIRING_OR_THROWING: \"FIRING or THROWING\"\n  ETM_REACTIONS: \"REACTIONS\"\n  ETM_REACTIONS_AND_MELEE: \"REACTIONS and MELEE\"\n  ETM_REACTIONS_AND_FIRING: \"REACTIONS and FIRING\"\n  ETM_REACTIONS_AND_THROWING: \"REACTIONS and THROWING\"\n  ETM_REACTIONS_OR_MELEE: \"REACTIONS or MELEE\"\n  ETM_REACTIONS_OR_FIRING: \"REACTIONS or FIRING\"\n  ETM_REACTIONS_OR_THROWING: \"REACTIONS or THROWING\"\n  ETM_BRAVERY: \"BRAVERY\"\n  ETM_BRAVERY_2X: \"BRAVERY (x2)\"\n  ETM_BRAVERY_AND_REACTIONS: \"BRAVERY and REACTIONS\"\n  ETM_BRAVERY_OR_REACTIONS: \"BRAVERY or REACTIONS\"\n  ETM_BRAVERY_OR_REACTIONS_2X: \"BRAVERY or REACTIONS (x2)\"\n  ETM_PSI_STRENGTH: \"PSI STRENGTH\"\n  ETM_PSI_STRENGTH_2X: \"PSI  STRENGTH (x2)\"\n  ETM_PSI_SKILL: \"PSI SKILL\"\n  ETM_PSI_SKILL_2X: \"PSI SKILL (x2)\"\n  ETM_PSI_STRENGTH_AND_SKILL: \"PSI STRENGTH and PSI SKILL\"\n  ETM_PSI_STRENGTH_AND_SKILL_2X: \"PSI STRENGTH and PSI SKILL (x2)\"\n  ETM_PSI_STRENGTH_OR_SKILL: \"PSI STRENGTH or PSI SKILL\"\n  ETM_PSI_STRENGTH_OR_SKILL_2X: \"PSI STRENGTH or PSI SKILL (x2)\"\n  ETM_NOTHING: \"no training\"\n#\n  battleType: \"Item type\"\n  experienceTrainingMode: \"Experience mode\"\n  manaExperience: \"Mana experience\"\n  arcingShot: \"Arcing?\"\n  isFireExtinguisher: \"Fire exinguisher?\"\n  explodeInventory: \"Explodes in inventory?\"\n  waypoints: \"Max waypoints\"\n  sprayWaypoints: \"Spray shot waypoints\"\n#\n  shotgunPellets: \"Number of pellets\"\n  shotgunBehavior: \"Shotgun behavior\"\n  shotgunSpread: \"Shotgun spread\"\n  shotgunChoke: \"Shotgun choke\"\n#\n  underwaterOnly: \"Underwater only?\"\n  landOnly: \"Land only?\"\n  psiRequired: \"Psi skill required?\"\n  targetMatrix: \"Item targets\"\n  convertToCivilian: \"Convert to civilian?\"\n  manaRequired: \"Mana required?\"\n  LOSRequired: \"Sight required?\"\n#\n  noLOSAccuracyPenalty: \"No-sight penalty mult.\"\n  kneelBonus: \"Kneel bonus multiplier\"\n  twoHanded: \"Two-handed?\"\n  blockBothHands: \"Blocks both hands?\"\n  oneHandedPenalty: \"One-hand use penalty\"\n#\n  minRange: \"Minimum range\"\n  maxRange: \"Maximum range\"\n  aimRange: \"Aimed shot range\"\n  autoRange: \"Auto shot range\"\n  snapRange: \"Snap shot range\"\n  dropoff: \"Accuracy dropoff/tile\"\n#\n  accuracyMultiplier: \"Firing acc. multiplier\"\n  accuracyAimed: \"Aimed shot accuracy\"\n  accuracyAuto: \"Auto shot accuracy\"\n  accuracySnap: \"Snap shot accuracy\"\n  costAimed: \"Aimed shot cost\"\n  costAuto: \"Auto shot cost\"\n  costSnap: \"Snap shot cost\"\n#\n  meleeMultiplier: \"Melee acc. multiplier\"\n  accuracyMelee: \"Melee accuracy\"\n  costMelee: \"Melee cost\"\n#\n  psiAttackName: \"Psi attack name\"\n  accuracyUse: \"Action accuracy\"\n  accuracyMindControl: \"Mind control accuracy\"\n  accuracyPanic: \"Panic accuracy\"\n  costUse: \"Action cost\"\n  costMindcontrol: \"Mind control cost\"\n  costPanic: \"Panic cost\"\n#\n  weight: \"Weight\"\n  throwRange: \"Throw max (air)\"\n  underwaterThrowRange: \"Throw max (water)\"\n  throwDropoffRange: \"Throw range (air)\"\n  underwaterThrowDropoffRange: \"Throw range (water)\"\n  throwDropoff: \"Throw dropoff/tile\"\n  throwMultiplier: \"Throwing acc. multiplier\"\n  accuracyThrow: \"Throwing accuracy\"\n  costThrow: \"Throwing cost\"\n  costPrime: \"Priming cost\"\n  costUnprime: \"Unpriming cost\"\n#\n  closeQuartersMultiplier: \"CQC acc. multiplier\"\n  accuracyCloseQuarters: \"CQC accuracy\"\n#\n  damageType: \"Damage type\"\n  power: \"Power\"\n  powerRangeReduction: \"Power reduction/tile\"\n  powerRangeThreshold: \"Power red. threshold\"\n  damageBonus: \"Damage bonus\"\n  blastRadius: \"Blast radius\"\n  damageAlter: \"Extra damage info:\"\n  meleeType: \"Melee damage type\"\n  meleePower: \"Melee power\"\n  meleeBonus: \"Melee power bonus\"\n  meleeAlter: \"Extra melee info:\"\n  FixRadius: \"Blast radius\"\n  RandomType: \"Calculation type\"\n  FireBlastCalc: \"Vanilla fire effects?\"\n  IgnoreDirection: \"Ignore direction\"\n  IgnoreSelfDestruct: \"Ignore self-destruct\"\n  IgnorePainImmunity: \"Ignore stun immunity\"\n  IgnoreNormalMoraleLose: \"Ign. vanilla morale loss\"\n  IgnoreOverKill: \"Ignore overkill\"\n  ArmorEffectiveness: \"Armor effectiveness\"\n  RadiusEffectiveness: \"Radius effectiveness\"\n  RadiusReduction: \"Radius dmg reduction\"\n  FireThreshold: \"Set-on-fire threshold\"\n  SmokeThreshold: \"Make smoke threshold\"\n#\n  ToArmorPre: \"Armor pre-dmg mult.\"\n  RandomArmorPre: \"Armor pre-dmg RNG?\"\n  ToArmor: \"Armor damage multiplier\"\n  RandomArmor: \"Armor damage RNG?\"\n  ToHealth: \"HP damage multiplier\"\n  RandomHealth: \"HP damage RNG?\"\n  ToStun: \"Stun damage multiplier\"\n  RandomStun: \"Stun damage RNG?\"\n  ToWound: \"Wound count multiplier\"\n  RandomWound: \"Vanilla wound RNG?\"\n  ToTime: \"TU damage multiplier\"\n  RandomTime: \"TU damage RNG?\"\n  ToEnergy: \"Energy dmg multiplier\"\n  RandomEnergy: \"Energy dmg RNG?\"\n  ToMorale: \"Morale dmg multiplier\"\n  RandomMorale: \"Morale dmg RNG?\"\n  ToItem: \"Item damage multiplier\"\n  RandomItem: \"Item damage RNG?\"\n  ToMana: \"Mana dmg multiplier\"\n  RandomMana: \"Mana dmg RNG?\"\n  ToTile: \"Terrain dmg multiplier\"\n  RandomTile: \"Terrain dmg RNG?\"\n  TileDamageMethod: \"Tile Damage Method\"\n  TileDamageLimit: \"Tile Damage Limit\"\n#\n  confAimed: \"Aimed action:\"\n  confAuto: \"Auto action:\"\n  confSnap: \"Snap action:\"\n  confMelee: \"Melee action:\"\n  shots: \"Shots per action\"\n  spendPerShot: \"Spend per shot:\"\n  followProjectiles: \"Follow projectiles?\"\n  name: \"Name\"\n  shortName: \"Short name\"\n  ammoSlot: \"Ammo slot used\"\n  ammoZombieUnitChanceOverride: \"Zombification chance\"\n  ammoSpawnUnitChanceOverride: \"Unit spawn chance\"\n  ammoSpawnItemChanceOverride: \"Item spawn chance\"\n  arcing: \"Arcing?\"\n#\n  clipSize: \"Clip size\"\n  isAmmoRechargeable: \"Ammo rechargeable?\"\n#\n  primaryAmmo: \"Primary ammo slot:\"\n  compatibleAmmo: \"Compatible ammo\"\n  tuLoad: \"Load cost\"\n  tuUnload: \"Unload cost\"\n  ammo[1]: \"Extra ammo slot #1:\"\n  ammo[2]: \"Extra ammo slot #2:\"\n  ammo[3]: \"Extra ammo slot #3:\"\n#\n  armor: \"Armor\"\n#\n  medikitType: \"Medikit type\"\n  painKillerActionName: \"Painkiller action name\"\n  stimulantActionName: \"Stimulant action name\"\n  healActionName: \"Heal action name\"\n  medikitActionName: \"Medikit action name\"\n  medikitTargetSelf: \"Medikit on self?\"\n  medikitTargetImmune: \"Medikit on bleed immune?\"\n  medikitTargetMatrix: \"Medikit targets\"\n  isConsumable: \"Consumable?\"\n  painKiller: \"Painkiller uses\"\n  heal: \"Heal uses\"\n  stimulant: \"Stim uses\"\n  woundRecovery: \"Wound healing\"\n  healthRecovery: \"Health recovery\"\n  stunRecovery: \"Stun recovery\"\n  energyRecovery: \"Energy recovery\"\n  manaRecovery: \"Mana recovery\"\n  moraleRecovery: \"Morale recovery\"\n  painKillerRecovery: \"Painkiller strength\"\n#\n  requires: \"Tech required\"\n  requiresBuy: \"Tech required to buy\"\n  requiresBuyBaseFunc: \"Services needed to buy\"\n  requiresBuyCountry: \"Allied country required\"\n  requiresAward: \"Award required\"\n  requiresBonus: \"Bonus required\"\n  categories: \"Categories\"\n  supportedInventorySections: \"Inventory slots\"\n#\n  size: \"Size\"\n  costBuy: \"Buy cost\"\n  monthlyBuyLimit: \"Monthly buy limit\"\n  costSell: \"Sell cost\"\n  transferTime: \"Hours to transfer\"\n  monthlySalary: \"Salary/month\"\n  monthlyMaintenance: \"Maintenance/month\"\n#\n  SPECAB_NONE: \"None\"\n  SPECAB_EXPLODEONDEATH: \"Explode on death\"\n  SPECAB_BURNFLOOR: \"Burn floor\"\n  SPECAB_BURN_AND_EXPLODE: \"Burn floor and explode on death\"\n#\n  MT_WALK: \"Walk\"\n  MT_FLY: \"Fly\"\n  MT_SLIDE: \"Slide\"\n  MT_FLOAT: \"Float\"\n  MT_SINK: \"Sink\"\n#\n  TORSO_USE_GENDER: \"Use gender\"\n  TORSO_ALWAYS_MALE: \"Always male\"\n  TORSO_ALWAYS_FEMALE: \"Always female\"\n#\n  DRAWING_ROUTINE_SOLDIER_SECTOID: \"Soldier, Sectoid\"\n  DRAWING_ROUTINE_FLOATER: \"Floater\"\n  DRAWING_ROUTINE_HWP: \"Heavy Weapons Platforms\"\n  DRAWING_ROUTINE_CYBERDISC: \"Cyberdisc\"\n  DRAWING_ROUTINE_CIVILIAN_ETHEREAL: \"Civilian, Ethereal\"\n  DRAWING_ROUTINE_SECTOPOD_REAPER: \"Sectopod, Reaper\"\n  DRAWING_ROUTINE_SNAKEMAN: \"Snakeman\"\n  DRAWING_ROUTINE_CHRYSSALID: \"Chryssalid\"\n  DRAWING_ROUTINE_SILACOID: \"Silacoid\"\n  DRAWING_ROUTINE_CELATID: \"Celatid\"\n  DRAWING_ROUTINE_MUTON: \"Muton\"\n  DRAWING_ROUTINE_SWS: \"Submersible Weapons Systems\"\n  DRAWING_ROUTINE_HALLUCINOID: \"Hallucinoid\"\n  DRAWING_ROUTINE_AQUANAUTS: \"Aquanauts\"\n  DRAWING_ROUTINE_CALCINITE_AND_MORE: \"Calcinite, Deep One, Gillman, Lobster Man, Tasoth\"\n  DRAWING_ROUTINE_AQUATOID: \"Aquatoid\"\n  DRAWING_ROUTINE_BIO_DRONE: \"Bio-Drone\"\n  DRAWING_ROUTINE_TFTD_CIVILIAN_A: \"TFTD Civilians type A and TFTD Zombie\"\n  DRAWING_ROUTINE_TFTD_CIVILIAN_B: \"TFTD Civilians type B\"\n  DRAWING_ROUTINE_TENTACULAT: \"Tentaculat\"\n  DRAWING_ROUTINE_TRISCENE: \"Triscene\"\n  DRAWING_ROUTINE_XARQUID: \"Xarquid\"\n  DRAWING_ROUTINE_INVERTED_CYBERDISC: \"Inverted Cyberdisc (propulsion animation on top)\"\n#\n  stats: \"Stat modifiers\"\n  specab: \"Special ability\"\n  movementType: \"Movement type\"\n  allowsRunning: \"Allow running?\"\n  allowsStrafing: \"Allow strafing?\"\n  allowsSneaking: \"Allow sneaking?\"\n  allowsKneeling: \"Allow kneeling?\"\n  allowsMoving: \"Allow moving?\"\n  fearImmune: \"Immune to morale loss?\"\n  bleedImmune: \"Immune to bleeding?\"\n  painImmune: \"Immune to stun?\"\n  zombiImmune: \"Immune to zombifying?\"\n  ignoresMeleeThreat: \"Ignores CQC?\"\n  createsMeleeThreat: \"Produces CQC?\"\n  builtInWeapons: \"Built-in items\"\n  specialWeapon: \"Special weapon\"\n  heatVision: \"Visibility through smoke\"\n  visibilityThroughFire: \"Visibility through fire\"\n  psiVision: \"Psi sense\"\n  psiCamouflage: \"Psi camouflage\"\n  visibilityAtDay: \"Visibility at day\"\n  visibilityAtDark: \"Visibility at night\"\n  camouflageAtDay: \"Camouflage at day\"\n  camouflageAtDark: \"Camouflage at night\"\n  antiCamouflageAtDay: \"Anticamo at day\"\n  antiCamouflageAtDark: \"Anticamo at night\"\n  psiDefence: \"Psi defense\"\n  meleeDodge: \"Melee dodge\"\n  meleeDodgeBackPenalty: \"Melee dodge penalty\"\n  recovery: \"Recovery each turn:\"\n  time: \"Time\"\n  energy: \"Energy\"\n  morale: \"Morale\"\n  health: \"Health\"\n  stun: \"Stun\"\n  mana: \"Mana\"\n  units: \"Compatible units\"\n  ranks: \"Compatible ranks\"\n  frontArmor: \"Front Armor\"\n  sideArmor: \"Side Armor\"\n  leftArmorDiff: \"Left Armor Diff\"\n  rearArmor: \"Rear Armor\"\n  underArmor: \"Under Armor\"\n#\n  sizeX: \"Size X\"\n  sizeY: \"Size Y\"\n  buildCost: \"Build cost\"\n  buildCostItems: \"Build materials:\"\n  buildTime: \"Build time\"\n  monthlyCost: \"Monthly cost\"\n  refundValue: \"Refund value\"\n  requiresBaseFunc: \"Requires services\"\n  provideBaseFunc: \"Provides services\"\n  forbiddenBaseFunc: \"Forbids services\"\n  lift: \"Access lift?\"\n  hyper: \"Hyper-wave decoder?\"\n  mind: \"Mind shield?\"\n  mindPower: \"Mind shield power\"\n  grav: \"Grav shield?\"\n  storage: \"Storage space\"\n  personnel: \"Living space\"\n  aliens: \"Prison space\"\n  crafts: \"Hangar space\"\n  labs: \"Laboratory space\"\n  workshops: \"Workshop space\"\n  psiLabs: \"Psi-lab space\"\n  trainingRooms: \"Gym space\"\n  sightRange: \"Sight range\"\n  sightChance: \"Sight chance\"\n  radarRange: \"Radar range\"\n  radarChance: \"Radar chance\"\n  defense: \"Defense value\"\n  hitRatio: \"Hit chance\"\n  ammoNeeded: \"Ammo needed\"\n  unifiedDamageFormula: \"New damage formula?\"\n  ammoItem: \"Ammo item\"\n  maxAllowedPerBase: \"Max allowed per base\"\n  manaRecoveryPerDay: \"Mana per day\"\n  healthRecoveryPerDay: \"Health per day\"\n  sickBayAbsoluteBonus: \"Sickbay abs. bonus\"\n  sickBayRelativeBonus: \"Sickbay rel. bonus\"\n  prisonType: \"Prison type\"\n  rightClickActionType: \"Right-click action\"\n  leavesBehindOnSell: \"Leaves behind on sell\"\n  removalTime: \"Removal time\"\n  canBeBuiltOver: \"Can be built-over?\"\n  upgradeOnly: \"Upgrade only?\"\n  buildOverFacilities: \"Build-over facilities\"\n#\n  BFRCT_DEFAULT: \"vanilla default\"\n  BFRCT_PRISON: \"go to Alien Containment\"\n  BFRCT_ENGINEERING: \"go to Manufacturing\"\n  BFRCT_RESEARCH: \"go to Research\"\n  BFRCT_GYM: \"go to Martial Training\"\n  BFRCT_PSI_LABS: \"go to Psionic Labs\"\n  BFRCT_BARRACKS: \"go to Barracks\"\n  BFRCT_GREY_MARKET: \"go to Grey Market\"\n  BFRCT_GEOSCAPE: \"go to Geoscape\"\n#\n  costRent: \"Rent cost\"\n  soldiers: \"Cargo space\"\n  maxUnitsLimit: \"Max cargo space\"\n  pilots: \"Cockpit size\"\n  pilotMinStatsRequired: \"Pilot min stats\"\n  pilotSoldierBonusesRequired: \"Pilot requirements\"\n  vehicles: \"HWP capacity\"\n  onlyOneSoldierGroupAllowed: \"Only one soldier group allowed?\"\n  allowedSoldierGroups: \"Allowed soldier groups\"\n  allowedArmorGroups: \"Allowed armor groups\"\n  limitArmorGroups: \"Limit armor groups\"\n  maxHWPUnitsLimit: \"Max HWP capacity\"\n  maxSmallSoldiers: \"Max small soldiers\"\n  maxLargeSoldiers: \"Max large soldiers\"\n  maxSmallVehicles: \"Max small vehicles\"\n  maxLargeVehicles: \"Max large vehicles\"\n  maxSmallUnits: \"Max small units\"\n  maxLargeUnits: \"Max large units\"\n  maxSoldiers: \"Max soldiers\"\n  maxVehicles: \"Max vehicles\"\n  maxItems: \"Equipment limit\"\n  maxStorageSpace: \"Storage space\"\n  maxAltitude: \"Dogfight altitude limit\"\n  weapons: \"Weapon pods\"\n  weaponStrings: \"Weapon names\"\n  fixedWeapons: \"Fixed weapons\"\n  weaponTypes: \"Allowed weapon types\"\n  damageMax: \"Damage capacity\"\n  avoidBonus: \"Dodge bonus (flat)\"\n  avoidBonus2: \"Dodge bonus 2 (flat)\"\n  powerBonus: \"Power bonus (flat)\"\n  hitBonus: \"Hit bonus (flat)\"\n  fuelMax: \"Fuel capacity\"\n  speedMax: \"Maximum speed\"\n  accel: \"Acceleration\"\n  shieldCapacity: \"Shield capacity\"\n  shieldRecharge: \"Shield recharge (Fight)\"\n  shieldRechargeInGeoscape: \"Shield recharge (Globe)\"\n  shieldBleedThrough: \"Shield bleed-through\"\n  shieldRechargedAtBase: \"Shield recharge (Base)\"\n  refuelItem: \"Refuel item\"\n  refuelRate: \"Refuel rate\"\n  repairRate: \"Repair rate\"\n  spacecraft: \"Final craft?\"\n  allowLanding: \"Allow landing?\"\n  notifyWhenRefueled: \"Notify when refueled?\"\n  autoPatrol: \"Auto-patrol?\"\n  undetectable: \"Undetectable?\"\n  patrolWithoutFuel: \"Patrol for free?\"\n  keepCraftAfterFailedMission: \"Paratroopers?\"\n  _calculatedValues: \"Calculated values\"\n  _maxRange: \"Maximum range\"\n  _minRange: \"Minimum range\"\n  _avgRange: \"Average range\"\n#\n  hunterKillerPercentage: \"Hunter-killer chance\"\n  huntMode: \"Hunt mode\"\n  huntSpeed: \"Hunt speed\"\n  huntBehavior: \"Hunt behavior\"\n  range: \"Range\"\n  reload: \"Reload time\"\n  breakOffTime: \"Break-off time\"\n  score: \"Score\"\n  missionScore: \"Mission score\"\n  craftCustomDeploy: \"UFO site deployment\"\n  missionCustomDeploy: \"Mission site deployment\"\n  _escapeCountdown: \"Escape countdown\"\n  _fireRate: \"Fire rate\"\n  _averageDPM: \"Average DPM\"\n#\n  HM_INTERCEPTORS: \"prefer hunting interceptors\"\n  HM_TRANSPORTS: \"prefer hunting transports\"\n  HM_RANDOM: \"random\"\n#\n  HB_FLEE: \"flee when losing\"\n  HB_KAMIKAZE: \"fight until destroyed\"\n  HB_RANDOM: \"random\"\n#\n  tractorBeamPower: \"Tractor beam power\"\n  damage: \"Damage\"\n  shieldDamageModifier: \"Shield damage modifier\"\n  accuracy: \"Accuracy\"\n  reloadCautious: \"Reload (Cautious)\"\n  reloadStandard: \"Reload (Standard)\"\n  reloadAggressive: \"Reload (Aggressive)\"\n  launcher: \"Launcher item\"\n  weaponType: \"Weapon type\"\n  clip: \"Clip item\"\n  ammoMax: \"Rounds\"\n  rearmRate: \"Rearm rate\"\n  bulletSaving: \"Bullet saving?\"\n  _damageRange: \"Damage range\"\n  _damageRangeBasic: \"Damage range (basic)\"\n  _averageTotalDamage: \"Average total damage\"\n#\n  allowPiloting: \"Allow piloting?\"\n  costSalary: \"Salary\"\n  costSalarySquaddie: \"Bonus (squaddie)\"\n  costSalarySergeant: \"Bonus (sergeant)\"\n  costSalaryCaptain: \"Bonus (captain)\"\n  costSalaryColonel: \"Bonus (colonel)\"\n  costSalaryCommander: \"Bonus (commander)\"\n#\n  race: \"Race\"\n  rank: \"Rank\"\n  livingWeapon: \"Is living weapon?\"\n  meleeWeapon: \"Melee weapon\"\n  psiWeapon: \"Psi weapon\"\n  _builtInWeaponSets: \"Weapon sets?\"\n  _weightedBuiltInWeaponSets: \"Other weapon sets?\"\n  spawnUnit: \"Spawn on death\"\n  _capturable: \"Is capturable?\"\n  capturable: \"Capturable (flag)\"\n  canSurrender: \"Can surrender?\"\n  autoSurrender: \"Auto surrender?\"\n  spotter: \"Spotter duration\"\n  sniper: \"Sniper odds\"\n"
  },
  {
    "path": "bin/common/Language/Technical/en-US.yml",
    "content": "en-US:\n#=================== Menu ===================\n#TestState.cpp\n  STR_BAD_NODES: \"Bad nodes in RMP files\"\n  STR_BAD_NODES_DESC: \"Checks RMP files for nodes outside of map boundaries.{NEWLINE}These will NOT cause any crashes, but they will be ignored by the game, thus not work as intended.\"\n#\n  STR_MCD_CHECK: \"MCD checks\"\n  STR_MCD_CHECK_DESC: \"Checks MCD files for floor objects with zero movement cost; also checks for invalid DieMCD/AltMCD references; also checks invalid LOFTemps.\"\n#\n  STR_PALETTE_CHECK: \"Palette matching\"\n  STR_PALETTE_CHECK_DESC: \"Tries to match palettes of modded images to official palettes and reports any images that don't have a 100% match.\"\n#\n  STR_SCRIPT_TAGS: \"Script tag export\"\n  STR_SCRIPT_TAGS_DESC: \"Exports script tags in CSV format.\"\n#\n  STR_MAP_RESOURCES: \"Map resources check\"\n  STR_MAP_RESOURCES_DESC: \"Checks for missing and unused map-related files and ruleset.\"\n#\n  STR_CHECKING_TERRAIN: \"Checking terrain...\"\n  STR_CHECKING_UFOS: \"Checking UFOs...\"\n  STR_CHECKING_CRAFT: \"Checking craft...\"\n#\n  BACKPALS.DAT: \"BACKPALS.DAT\"\n  PAL_GEOSCAPE: \"PAL_GEOSCAPE\"\n  PAL_BASESCAPE: \"PAL_BASESCAPE\"\n  PAL_GRAPHS: \"PAL_GRAPHS\"\n  PAL_UFOPAEDIA: \"PAL_UFOPAEDIA\"\n  PAL_BATTLEPEDIA: \"PAL_BATTLEPEDIA\"\n  PAL_BATTLESCAPE: \"PAL_BATTLESCAPE\"\n  PAL_BATTLESCAPE_1: \"PAL_BATTLESCAPE_1\"\n  PAL_BATTLESCAPE_2: \"PAL_BATTLESCAPE_2\"\n  PAL_BATTLESCAPE_3: \"PAL_BATTLESCAPE_3\"\n#=================== Ufopaedia ===================\n#StatsForNerdsState.cpp\n  BT_NONE: \"None\"\n  BT_FIREARM: \"Firearm\"\n  BT_AMMO: \"Ammo\"\n  BT_MELEE: \"Melee weapon\"\n  BT_GRENADE: \"Grenade\"\n  BT_PROXIMITYGRENADE: \"Proximity grenade\"\n  BT_MEDIKIT: \"Medikit\"\n  BT_SCANNER: \"Motion scanner\"\n  BT_MINDPROBE: \"Mind probe\"\n  BT_PSIAMP: \"Psi Amp\"\n  BT_FLARE: \"Flare\"\n  BT_CORPSE: \"Corpse/Body\"\n#\n  DRT_DEFAULT: \"vanilla default\"\n  DRT_UFO: \"0-200% spread\"\n  DRT_TFTD: \"50-150% spread\"\n  DRT_FLAT: \"flat damage\"\n  DRT_FIRE: \"special fire damage\"\n  DRT_NONE: \"no damage\"\n  DRT_UFO_WITH_TWO_DICE: \"0-200% spread (2 dice roll)\"\n  DRT_EASY: \"50-200% spread\"\n  DRT_STANDARD: \"standard damage range\"\n  DRT_EXPLOSION: \"explosion damage range\"\n#\n  BFT_NONE: \"none\"\n  BFT_INSTANT: \"instant\"\n  BFT_SET: \"manually set\"\n  BFT_FIXED: \"fixed\"\n#\n  BMT_NORMAL: \"standard (multi-purpose)\"\n  BMT_HEAL: \"heal\"\n  BMT_STIMULANT: \"stimulant\"\n  BMT_PAINKILLER: \"painkiller\"\n#\n  ETM_DEFAULT: \"default\"\n  ETM_MELEE_100: \"MELEE\"\n  ETM_MELEE_50: \"MELEE (50% chance)\"\n  ETM_MELEE_33: \"MELEE (33% chance)\"\n  ETM_FIRING_100: \"FIRING\"\n  ETM_FIRING_50: \"FIRING (50% chance)\"\n  ETM_FIRING_33: \"FIRING (33% chance)\"\n  ETM_THROWING_100: \"THROWING\"\n  ETM_THROWING_50: \"THROWING (50% chance)\"\n  ETM_THROWING_33: \"THROWING (33% chance)\"\n  ETM_FIRING_AND_THROWING: \"FIRING and THROWING\"\n  ETM_FIRING_OR_THROWING: \"FIRING or THROWING\"\n  ETM_REACTIONS: \"REACTIONS\"\n  ETM_REACTIONS_AND_MELEE: \"REACTIONS and MELEE\"\n  ETM_REACTIONS_AND_FIRING: \"REACTIONS and FIRING\"\n  ETM_REACTIONS_AND_THROWING: \"REACTIONS and THROWING\"\n  ETM_REACTIONS_OR_MELEE: \"REACTIONS or MELEE\"\n  ETM_REACTIONS_OR_FIRING: \"REACTIONS or FIRING\"\n  ETM_REACTIONS_OR_THROWING: \"REACTIONS or THROWING\"\n  ETM_BRAVERY: \"BRAVERY\"\n  ETM_BRAVERY_2X: \"BRAVERY (x2)\"\n  ETM_BRAVERY_AND_REACTIONS: \"BRAVERY and REACTIONS\"\n  ETM_BRAVERY_OR_REACTIONS: \"BRAVERY or REACTIONS\"\n  ETM_BRAVERY_OR_REACTIONS_2X: \"BRAVERY or REACTIONS (x2)\"\n  ETM_PSI_STRENGTH: \"PSI STRENGTH\"\n  ETM_PSI_STRENGTH_2X: \"PSI  STRENGTH (x2)\"\n  ETM_PSI_SKILL: \"PSI SKILL\"\n  ETM_PSI_SKILL_2X: \"PSI SKILL (x2)\"\n  ETM_PSI_STRENGTH_AND_SKILL: \"PSI STRENGTH and PSI SKILL\"\n  ETM_PSI_STRENGTH_AND_SKILL_2X: \"PSI STRENGTH and PSI SKILL (x2)\"\n  ETM_PSI_STRENGTH_OR_SKILL: \"PSI STRENGTH or PSI SKILL\"\n  ETM_PSI_STRENGTH_OR_SKILL_2X: \"PSI STRENGTH or PSI SKILL (x2)\"\n  ETM_NOTHING: \"no training\"\n#\n  battleType: \"Item type\"\n  experienceTrainingMode: \"Experience mode\"\n  manaExperience: \"Mana experience\"\n  arcingShot: \"Arcing?\"\n  isFireExtinguisher: \"Fire exinguisher?\"\n  explodeInventory: \"Explodes in inventory?\"\n  waypoints: \"Max waypoints\"\n  sprayWaypoints: \"Spray shot waypoints\"\n#\n  shotgunPellets: \"Number of pellets\"\n  shotgunBehavior: \"Shotgun behavior\"\n  shotgunSpread: \"Shotgun spread\"\n  shotgunChoke: \"Shotgun choke\"\n#\n  underwaterOnly: \"Underwater only?\"\n  landOnly: \"Land only?\"\n  psiRequired: \"Psi skill required?\"\n  targetMatrix: \"Item targets\"\n  convertToCivilian: \"Convert to civilian?\"\n  manaRequired: \"Mana required?\"\n  LOSRequired: \"Sight required?\"\n#\n  noLOSAccuracyPenalty: \"No-sight penalty mult.\"\n  kneelBonus: \"Kneel bonus multiplier\"\n  twoHanded: \"Two-handed?\"\n  blockBothHands: \"Blocks both hands?\"\n  oneHandedPenalty: \"One-hand use penalty\"\n#\n  minRange: \"Minimum range\"\n  maxRange: \"Maximum range\"\n  aimRange: \"Aimed shot range\"\n  autoRange: \"Auto shot range\"\n  snapRange: \"Snap shot range\"\n  dropoff: \"Accuracy dropoff/tile\"\n#\n  accuracyMultiplier: \"Firing acc. multiplier\"\n  accuracyAimed: \"Aimed shot accuracy\"\n  accuracyAuto: \"Auto shot accuracy\"\n  accuracySnap: \"Snap shot accuracy\"\n  costAimed: \"Aimed shot cost\"\n  costAuto: \"Auto shot cost\"\n  costSnap: \"Snap shot cost\"\n#\n  meleeMultiplier: \"Melee acc. multiplier\"\n  accuracyMelee: \"Melee accuracy\"\n  costMelee: \"Melee cost\"\n#\n  psiAttackName: \"Psi attack name\"\n  accuracyUse: \"Action accuracy\"\n  accuracyMindControl: \"Mind control accuracy\"\n  accuracyPanic: \"Panic accuracy\"\n  costUse: \"Action cost\"\n  costMindcontrol: \"Mind control cost\"\n  costPanic: \"Panic cost\"\n#\n  weight: \"Weight\"\n  throwRange: \"Throw max (air)\"\n  underwaterThrowRange: \"Throw max (water)\"\n  throwDropoffRange: \"Throw range (air)\"\n  underwaterThrowDropoffRange: \"Throw range (water)\"\n  throwDropoff: \"Throw dropoff/tile\"\n  throwMultiplier: \"Throwing acc. multiplier\"\n  accuracyThrow: \"Throwing accuracy\"\n  costThrow: \"Throwing cost\"\n  costPrime: \"Priming cost\"\n  costUnprime: \"Unpriming cost\"\n#\n  closeQuartersMultiplier: \"CQC acc. multiplier\"\n  accuracyCloseQuarters: \"CQC accuracy\"\n#\n  damageType: \"Damage type\"\n  power: \"Power\"\n  powerRangeReduction: \"Power reduction/tile\"\n  powerRangeThreshold: \"Power red. threshold\"\n  damageBonus: \"Damage bonus\"\n  blastRadius: \"Blast radius\"\n  damageAlter: \"Extra damage info:\"\n  meleeType: \"Melee damage type\"\n  meleePower: \"Melee power\"\n  meleeBonus: \"Melee power bonus\"\n  meleeAlter: \"Extra melee info:\"\n  FixRadius: \"Blast radius\"\n  RandomType: \"Calculation type\"\n  FireBlastCalc: \"Vanilla fire effects?\"\n  IgnoreDirection: \"Ignore direction\"\n  IgnoreSelfDestruct: \"Ignore self-destruct\"\n  IgnorePainImmunity: \"Ignore stun immunity\"\n  IgnoreNormalMoraleLose: \"Ign. vanilla morale loss\"\n  IgnoreOverKill: \"Ignore overkill\"\n  ArmorEffectiveness: \"Armor effectiveness\"\n  RadiusEffectiveness: \"Radius effectiveness\"\n  RadiusReduction: \"Radius dmg reduction\"\n  FireThreshold: \"Set-on-fire threshold\"\n  SmokeThreshold: \"Make smoke threshold\"\n#\n  ToArmorPre: \"Armor pre-dmg mult.\"\n  RandomArmorPre: \"Armor pre-dmg RNG?\"\n  ToArmor: \"Armor damage multiplier\"\n  RandomArmor: \"Armor damage RNG?\"\n  ToHealth: \"HP damage multiplier\"\n  RandomHealth: \"HP damage RNG?\"\n  ToStun: \"Stun damage multiplier\"\n  RandomStun: \"Stun damage RNG?\"\n  ToWound: \"Wound count multiplier\"\n  RandomWound: \"Vanilla wound RNG?\"\n  ToTime: \"TU damage multiplier\"\n  RandomTime: \"TU damage RNG?\"\n  ToEnergy: \"Energy dmg multiplier\"\n  RandomEnergy: \"Energy dmg RNG?\"\n  ToMorale: \"Morale dmg multiplier\"\n  RandomMorale: \"Morale dmg RNG?\"\n  ToItem: \"Item damage multiplier\"\n  RandomItem: \"Item damage RNG?\"\n  ToMana: \"Mana dmg multiplier\"\n  RandomMana: \"Mana dmg RNG?\"\n  ToTile: \"Terrain dmg multiplier\"\n  RandomTile: \"Terrain dmg RNG?\"\n  TileDamageMethod: \"Tile Damage Method\"\n  TileDamageLimit: \"Tile Damage Limit\"\n#\n  confAimed: \"Aimed action:\"\n  confAuto: \"Auto action:\"\n  confSnap: \"Snap action:\"\n  confMelee: \"Melee action:\"\n  shots: \"Shots per action\"\n  spendPerShot: \"Spend per shot:\"\n  followProjectiles: \"Follow projectiles?\"\n  name: \"Name\"\n  shortName: \"Short name\"\n  ammoSlot: \"Ammo slot used\"\n  ammoZombieUnitChanceOverride: \"Zombification chance\"\n  ammoSpawnUnitChanceOverride: \"Unit spawn chance\"\n  ammoSpawnItemChanceOverride: \"Item spawn chance\"\n  arcing: \"Arcing?\"\n#\n  clipSize: \"Clip size\"\n  isAmmoRechargeable: \"Ammo rechargeable?\"\n#\n  primaryAmmo: \"Primary ammo slot:\"\n  compatibleAmmo: \"Compatible ammo\"\n  tuLoad: \"Load cost\"\n  tuUnload: \"Unload cost\"\n  ammo[1]: \"Extra ammo slot #1:\"\n  ammo[2]: \"Extra ammo slot #2:\"\n  ammo[3]: \"Extra ammo slot #3:\"\n#\n  armor: \"Armor\"\n#\n  medikitType: \"Medikit type\"\n  painKillerActionName: \"Painkiller action name\"\n  stimulantActionName: \"Stimulant action name\"\n  healActionName: \"Heal action name\"\n  medikitActionName: \"Medikit action name\"\n  medikitTargetSelf: \"Medikit on self?\"\n  medikitTargetImmune: \"Medikit on bleed immune?\"\n  medikitTargetMatrix: \"Medikit targets\"\n  isConsumable: \"Consumable?\"\n  painKiller: \"Painkiller uses\"\n  heal: \"Heal uses\"\n  stimulant: \"Stim uses\"\n  woundRecovery: \"Wound healing\"\n  healthRecovery: \"Health recovery\"\n  stunRecovery: \"Stun recovery\"\n  energyRecovery: \"Energy recovery\"\n  manaRecovery: \"Mana recovery\"\n  moraleRecovery: \"Morale recovery\"\n  painKillerRecovery: \"Painkiller strength\"\n#\n  requires: \"Tech required\"\n  requiresBuy: \"Tech required to buy\"\n  requiresBuyBaseFunc: \"Services needed to buy\"\n  requiresBuyCountry: \"Allied country required\"\n  requiresAward: \"Award required\"\n  requiresBonus: \"Bonus required\"\n  categories: \"Categories\"\n  supportedInventorySections: \"Inventory slots\"\n#\n  size: \"Size\"\n  costBuy: \"Buy cost\"\n  monthlyBuyLimit: \"Monthly buy limit\"\n  costSell: \"Sell cost\"\n  transferTime: \"Hours to transfer\"\n  monthlySalary: \"Salary/month\"\n  monthlyMaintenance: \"Maintenance/month\"\n#\n  SPECAB_NONE: \"None\"\n  SPECAB_EXPLODEONDEATH: \"Explode on death\"\n  SPECAB_BURNFLOOR: \"Burn floor\"\n  SPECAB_BURN_AND_EXPLODE: \"Burn floor and explode on death\"\n#\n  MT_WALK: \"Walk\"\n  MT_FLY: \"Fly\"\n  MT_SLIDE: \"Slide\"\n  MT_FLOAT: \"Float\"\n  MT_SINK: \"Sink\"\n#\n  TORSO_USE_GENDER: \"Use gender\"\n  TORSO_ALWAYS_MALE: \"Always male\"\n  TORSO_ALWAYS_FEMALE: \"Always female\"\n#\n  DRAWING_ROUTINE_SOLDIER_SECTOID: \"Soldier, Sectoid\"\n  DRAWING_ROUTINE_FLOATER: \"Floater\"\n  DRAWING_ROUTINE_HWP: \"Heavy Weapons Platforms\"\n  DRAWING_ROUTINE_CYBERDISC: \"Cyberdisc\"\n  DRAWING_ROUTINE_CIVILIAN_ETHEREAL: \"Civilian, Ethereal\"\n  DRAWING_ROUTINE_SECTOPOD_REAPER: \"Sectopod, Reaper\"\n  DRAWING_ROUTINE_SNAKEMAN: \"Snakeman\"\n  DRAWING_ROUTINE_CHRYSSALID: \"Chryssalid\"\n  DRAWING_ROUTINE_SILACOID: \"Silacoid\"\n  DRAWING_ROUTINE_CELATID: \"Celatid\"\n  DRAWING_ROUTINE_MUTON: \"Muton\"\n  DRAWING_ROUTINE_SWS: \"Submersible Weapons Systems\"\n  DRAWING_ROUTINE_HALLUCINOID: \"Hallucinoid\"\n  DRAWING_ROUTINE_AQUANAUTS: \"Aquanauts\"\n  DRAWING_ROUTINE_CALCINITE_AND_MORE: \"Calcinite, Deep One, Gillman, Lobster Man, Tasoth\"\n  DRAWING_ROUTINE_AQUATOID: \"Aquatoid\"\n  DRAWING_ROUTINE_BIO_DRONE: \"Bio-Drone\"\n  DRAWING_ROUTINE_TFTD_CIVILIAN_A: \"TFTD Civilians type A and TFTD Zombie\"\n  DRAWING_ROUTINE_TFTD_CIVILIAN_B: \"TFTD Civilians type B\"\n  DRAWING_ROUTINE_TENTACULAT: \"Tentaculat\"\n  DRAWING_ROUTINE_TRISCENE: \"Triscene\"\n  DRAWING_ROUTINE_XARQUID: \"Xarquid\"\n  DRAWING_ROUTINE_INVERTED_CYBERDISC: \"Inverted Cyberdisc (propulsion animation on top)\"\n#\n  stats: \"Stat modifiers\"\n  specab: \"Special ability\"\n  movementType: \"Movement type\"\n  allowsRunning: \"Allow running?\"\n  allowsStrafing: \"Allow strafing?\"\n  allowsSneaking: \"Allow sneaking?\"\n  allowsKneeling: \"Allow kneeling?\"\n  allowsMoving: \"Allow moving?\"\n  fearImmune: \"Immune to morale loss?\"\n  bleedImmune: \"Immune to bleeding?\"\n  painImmune: \"Immune to stun?\"\n  zombiImmune: \"Immune to zombifying?\"\n  ignoresMeleeThreat: \"Ignores CQC?\"\n  createsMeleeThreat: \"Produces CQC?\"\n  builtInWeapons: \"Built-in items\"\n  specialWeapon: \"Special weapon\"\n  heatVision: \"Visibility through smoke\"\n  visibilityThroughFire: \"Visibility through fire\"\n  psiVision: \"Psi sense\"\n  psiCamouflage: \"Psi camouflage\"\n  visibilityAtDay: \"Visibility at day\"\n  visibilityAtDark: \"Visibility at night\"\n  camouflageAtDay: \"Camouflage at day\"\n  camouflageAtDark: \"Camouflage at night\"\n  antiCamouflageAtDay: \"Anticamo at day\"\n  antiCamouflageAtDark: \"Anticamo at night\"\n  psiDefence: \"Psi defense\"\n  meleeDodge: \"Melee dodge\"\n  meleeDodgeBackPenalty: \"Melee dodge penalty\"\n  recovery: \"Recovery each turn:\"\n  time: \"Time\"\n  energy: \"Energy\"\n  morale: \"Morale\"\n  health: \"Health\"\n  stun: \"Stun\"\n  mana: \"Mana\"\n  units: \"Compatible units\"\n  ranks: \"Compatible ranks\"\n  frontArmor: \"Front Armor\"\n  sideArmor: \"Side Armor\"\n  leftArmorDiff: \"Left Armor Diff\"\n  rearArmor: \"Rear Armor\"\n  underArmor: \"Under Armor\"\n#\n  sizeX: \"Size X\"\n  sizeY: \"Size Y\"\n  buildCost: \"Build cost\"\n  buildCostItems: \"Build materials:\"\n  buildTime: \"Build time\"\n  monthlyCost: \"Monthly cost\"\n  refundValue: \"Refund value\"\n  requiresBaseFunc: \"Requires services\"\n  provideBaseFunc: \"Provides services\"\n  forbiddenBaseFunc: \"Forbids services\"\n  lift: \"Access lift?\"\n  hyper: \"Hyper-wave decoder?\"\n  mind: \"Mind shield?\"\n  mindPower: \"Mind shield power\"\n  grav: \"Grav shield?\"\n  storage: \"Storage space\"\n  personnel: \"Living space\"\n  aliens: \"Prison space\"\n  crafts: \"Hangar space\"\n  labs: \"Laboratory space\"\n  workshops: \"Workshop space\"\n  psiLabs: \"Psi-lab space\"\n  trainingRooms: \"Gym space\"\n  sightRange: \"Sight range\"\n  sightChance: \"Sight chance\"\n  radarRange: \"Radar range\"\n  radarChance: \"Radar chance\"\n  defense: \"Defense value\"\n  hitRatio: \"Hit chance\"\n  ammoNeeded: \"Ammo needed\"\n  unifiedDamageFormula: \"New damage formula?\"\n  ammoItem: \"Ammo item\"\n  maxAllowedPerBase: \"Max allowed per base\"\n  manaRecoveryPerDay: \"Mana per day\"\n  healthRecoveryPerDay: \"Health per day\"\n  sickBayAbsoluteBonus: \"Sickbay abs. bonus\"\n  sickBayRelativeBonus: \"Sickbay rel. bonus\"\n  prisonType: \"Prison type\"\n  rightClickActionType: \"Right-click action\"\n  leavesBehindOnSell: \"Leaves behind on sell\"\n  removalTime: \"Removal time\"\n  canBeBuiltOver: \"Can be built-over?\"\n  upgradeOnly: \"Upgrade only?\"\n  buildOverFacilities: \"Build-over facilities\"\n#\n  BFRCT_DEFAULT: \"vanilla default\"\n  BFRCT_PRISON: \"go to Alien Containment\"\n  BFRCT_ENGINEERING: \"go to Manufacturing\"\n  BFRCT_RESEARCH: \"go to Research\"\n  BFRCT_GYM: \"go to Martial Training\"\n  BFRCT_PSI_LABS: \"go to Psionic Labs\"\n  BFRCT_BARRACKS: \"go to Barracks\"\n  BFRCT_GREY_MARKET: \"go to Grey Market\"\n  BFRCT_GEOSCAPE: \"go to Geoscape\"\n#\n  costRent: \"Rent cost\"\n  soldiers: \"Cargo space\"\n  maxUnitsLimit: \"Max cargo space\"\n  pilots: \"Cockpit size\"\n  pilotMinStatsRequired: \"Pilot min stats\"\n  pilotSoldierBonusesRequired: \"Pilot requirements\"\n  vehicles: \"HWP capacity\"\n  onlyOneSoldierGroupAllowed: \"Only one soldier group allowed?\"\n  allowedSoldierGroups: \"Allowed soldier groups\"\n  allowedArmorGroups: \"Allowed armor groups\"\n  limitArmorGroups: \"Limit armor groups\"\n  maxHWPUnitsLimit: \"Max HWP capacity\"\n  maxSmallSoldiers: \"Max small soldiers\"\n  maxLargeSoldiers: \"Max large soldiers\"\n  maxSmallVehicles: \"Max small vehicles\"\n  maxLargeVehicles: \"Max large vehicles\"\n  maxSmallUnits: \"Max small units\"\n  maxLargeUnits: \"Max large units\"\n  maxSoldiers: \"Max soldiers\"\n  maxVehicles: \"Max vehicles\"\n  maxItems: \"Equipment limit\"\n  maxStorageSpace: \"Storage space\"\n  maxAltitude: \"Dogfight altitude limit\"\n  weapons: \"Weapon pods\"\n  weaponStrings: \"Weapon names\"\n  fixedWeapons: \"Fixed weapons\"\n  weaponTypes: \"Allowed weapon types\"\n  damageMax: \"Damage capacity\"\n  avoidBonus: \"Dodge bonus (flat)\"\n  avoidBonus2: \"Dodge bonus 2 (flat)\"\n  powerBonus: \"Power bonus (flat)\"\n  hitBonus: \"Hit bonus (flat)\"\n  fuelMax: \"Fuel capacity\"\n  speedMax: \"Maximum speed\"\n  accel: \"Acceleration\"\n  shieldCapacity: \"Shield capacity\"\n  shieldRecharge: \"Shield recharge (Fight)\"\n  shieldRechargeInGeoscape: \"Shield recharge (Globe)\"\n  shieldBleedThrough: \"Shield bleed-through\"\n  shieldRechargedAtBase: \"Shield recharge (Base)\"\n  refuelItem: \"Refuel item\"\n  refuelRate: \"Refuel rate\"\n  repairRate: \"Repair rate\"\n  spacecraft: \"Final craft?\"\n  allowLanding: \"Allow landing?\"\n  notifyWhenRefueled: \"Notify when refueled?\"\n  autoPatrol: \"Auto-patrol?\"\n  undetectable: \"Undetectable?\"\n  patrolWithoutFuel: \"Patrol for free?\"\n  keepCraftAfterFailedMission: \"Paratroopers?\"\n  _calculatedValues: \"Calculated values\"\n  _maxRange: \"Maximum range\"\n  _minRange: \"Minimum range\"\n  _avgRange: \"Average range\"\n#\n  hunterKillerPercentage: \"Hunter-killer chance\"\n  huntMode: \"Hunt mode\"\n  huntSpeed: \"Hunt speed\"\n  huntBehavior: \"Hunt behavior\"\n  range: \"Range\"\n  reload: \"Reload time\"\n  breakOffTime: \"Break-off time\"\n  score: \"Score\"\n  missionScore: \"Mission score\"\n  craftCustomDeploy: \"UFO site deployment\"\n  missionCustomDeploy: \"Mission site deployment\"\n  _escapeCountdown: \"Escape countdown\"\n  _fireRate: \"Fire rate\"\n  _averageDPM: \"Average DPM\"\n#\n  HM_INTERCEPTORS: \"prefer hunting interceptors\"\n  HM_TRANSPORTS: \"prefer hunting transports\"\n  HM_RANDOM: \"random\"\n#\n  HB_FLEE: \"flee when losing\"\n  HB_KAMIKAZE: \"fight until destroyed\"\n  HB_RANDOM: \"random\"\n#\n  tractorBeamPower: \"Tractor beam power\"\n  damage: \"Damage\"\n  shieldDamageModifier: \"Shield damage modifier\"\n  accuracy: \"Accuracy\"\n  reloadCautious: \"Reload (Cautious)\"\n  reloadStandard: \"Reload (Standard)\"\n  reloadAggressive: \"Reload (Aggressive)\"\n  launcher: \"Launcher item\"\n  weaponType: \"Weapon type\"\n  clip: \"Clip item\"\n  ammoMax: \"Rounds\"\n  rearmRate: \"Rearm rate\"\n  bulletSaving: \"Bullet saving?\"\n  _damageRange: \"Damage range\"\n  _damageRangeBasic: \"Damage range (basic)\"\n  _averageTotalDamage: \"Average total damage\"\n#\n  allowPiloting: \"Allow piloting?\"\n  costSalary: \"Salary\"\n  costSalarySquaddie: \"Bonus (squaddie)\"\n  costSalarySergeant: \"Bonus (sergeant)\"\n  costSalaryCaptain: \"Bonus (captain)\"\n  costSalaryColonel: \"Bonus (colonel)\"\n  costSalaryCommander: \"Bonus (commander)\"\n#\n  race: \"Race\"\n  rank: \"Rank\"\n  livingWeapon: \"Is living weapon?\"\n  meleeWeapon: \"Melee weapon\"\n  psiWeapon: \"Psi weapon\"\n  _builtInWeaponSets: \"Weapon sets?\"\n  _weightedBuiltInWeaponSets: \"Other weapon sets?\"\n  spawnUnit: \"Spawn on death\"\n  _capturable: \"Is capturable?\"\n  capturable: \"Capturable (flag)\"\n  canSurrender: \"Can surrender?\"\n  autoSurrender: \"Auto surrender?\"\n  spotter: \"Spotter duration\"\n  sniper: \"Sniper odds\"\n"
  },
  {
    "path": "bin/common/Language/Technical/es-419.yml",
    "content": "es-419:\n#=================== Menu ===================\n#TestState.cpp\n  STR_BAD_NODES: \"Nodos erroneos en archivos RMP\"\n  STR_BAD_NODES_DESC: \"Revisa los archivos RMP for nodos fuera de los limites del mapa.{NEWLINE}Estos no causaran ningun crasheo, en su lugar serán ignorados por el juego, por lo tanto no funcionado como se debe.\"\n#\n  STR_MCD_CHECK: \"\"\n  STR_MCD_CHECK_DESC: \"\"\n#\n  STR_PALETTE_CHECK: \"Coincidir paleta\"\n  STR_PALETTE_CHECK_DESC: \"Intenta coincidir las paletas de imagenes modificadas con las oficiales y reportara aquellas que no hayan podido ser emparejadas en un 100%.\"\n#\n  STR_SCRIPT_TAGS: \"\"\n  STR_SCRIPT_TAGS_DESC: \"\"\n#\n  STR_MAP_RESOURCES: \"\"\n  STR_MAP_RESOURCES_DESC: \"\"\n#\n  STR_CHECKING_TERRAIN: \"Revisando terreno...\"\n  STR_CHECKING_UFOS: \"Revisando OVNIs...\"\n  STR_CHECKING_CRAFT: \"Revisando navió...\"\n#\n  BACKPALS.DAT: \"\"\n  PAL_GEOSCAPE: \"\"\n  PAL_BASESCAPE: \"\"\n  PAL_GRAPHS: \"\"\n  PAL_UFOPAEDIA: \"\"\n  PAL_BATTLEPEDIA: \"\"\n  PAL_BATTLESCAPE: \"\"\n  PAL_BATTLESCAPE_1: \"\"\n  PAL_BATTLESCAPE_2: \"\"\n  PAL_BATTLESCAPE_3: \"\"\n#=================== Ufopaedia ===================\n#StatsForNerdsState.cpp\n  BT_NONE: \"Nada\"\n  BT_FIREARM: \"Arma de fuego\"\n  BT_AMMO: \"Munición\"\n  BT_MELEE: \"Arma blanca\"\n  BT_GRENADE: \"Granada\"\n  BT_PROXIMITYGRENADE: \"Granada de proximidad\"\n  BT_MEDIKIT: \"Kit médico\"\n  BT_SCANNER: \"Scaner de movimiento\"\n  BT_MINDPROBE: \"Sonda mental\"\n  BT_PSIAMP: \"Amplificador psiquico\"\n  BT_FLARE: \"Bengala\"\n  BT_CORPSE: \"Cadaver/Cuerpo\"\n#\n  DRT_DEFAULT: \"Normal por defecto\"\n  DRT_UFO: \"0-200% dispersión\"\n  DRT_TFTD: \"50-150% dispersión\"\n  DRT_FLAT: \"daño plano\"\n  DRT_FIRE: \"daño de fuego especial\"\n  DRT_NONE: \"sin daño\"\n  DRT_UFO_WITH_TWO_DICE: \"0-200% dispersión(2 tiradas de dados)\"\n  DRT_EASY: \"50-200% dispersión\"\n  DRT_STANDARD: \"\"\n  DRT_EXPLOSION: \"\"\n#\n  BFT_NONE: \"ningún\"\n  BFT_INSTANT: \"instante\"\n  BFT_SET: \"establecer manualmente\"\n  BFT_FIXED: \"arreglado\"\n#\n  BMT_NORMAL: \"estandar (multi proposito)\"\n  BMT_HEAL: \"curar\"\n  BMT_STIMULANT: \"estimulante\"\n  BMT_PAINKILLER: \"calmante\"\n#\n  ETM_DEFAULT: \"por defecto\"\n  ETM_MELEE_100: \"CUERPO A CUERPO\"\n  ETM_MELEE_50: \"CUERPO A CUERPO(50% probabilidad)\"\n  ETM_MELEE_33: \"CUERPO A CUERPO(33% probabilidad)\"\n  ETM_FIRING_100: \"DISPARO\"\n  ETM_FIRING_50: \"DISPARO (50% probabilidad)\"\n  ETM_FIRING_33: \"DISPARO (33% probabilidad)\"\n  ETM_THROWING_100: \"ARROJANDO\"\n  ETM_THROWING_50: \"ARROJAMIENTO(50% probabilidad)\"\n  ETM_THROWING_33: \"ARROJAMIENTO (33% probabilidad)\"\n  ETM_FIRING_AND_THROWING: \"DISPARO y ARROJAMIENTO\"\n  ETM_FIRING_OR_THROWING: \"DISPARO o ARROJAMIENTO\"\n  ETM_REACTIONS: \"REACCIONES\"\n  ETM_REACTIONS_AND_MELEE: \"REACCIONES Y CUERPO A CUERPO\"\n  ETM_REACTIONS_AND_FIRING: \"REACCIONES y DISPARO\"\n  ETM_REACTIONS_AND_THROWING: \"REACCIONES y ARROJAMIENTO\"\n  ETM_REACTIONS_OR_MELEE: \"REACCIONES o CUERPO A CUERPO\"\n  ETM_REACTIONS_OR_FIRING: \"REACCIONES o DISPARO\"\n  ETM_REACTIONS_OR_THROWING: \"REACCIONES o ARROJAMIENTO\"\n  ETM_BRAVERY: \"VALENTÍA\"\n  ETM_BRAVERY_2X: \"VALENTÍA (x2)\"\n  ETM_BRAVERY_AND_REACTIONS: \"\"\n  ETM_BRAVERY_OR_REACTIONS: \"\"\n  ETM_BRAVERY_OR_REACTIONS_2X: \"\"\n  ETM_PSI_STRENGTH: \"\"\n  ETM_PSI_STRENGTH_2X: \"\"\n  ETM_PSI_SKILL: \"\"\n  ETM_PSI_SKILL_2X: \"\"\n  ETM_PSI_STRENGTH_AND_SKILL: \"\"\n  ETM_PSI_STRENGTH_AND_SKILL_2X: \"\"\n  ETM_PSI_STRENGTH_OR_SKILL: \"\"\n  ETM_PSI_STRENGTH_OR_SKILL_2X: \"\"\n  ETM_NOTHING: \"\"\n#\n  battleType: \"\"\n  experienceTrainingMode: \"\"\n  manaExperience: \"\"\n  arcingShot: \"\"\n  isFireExtinguisher: \"\"\n  explodeInventory: \"\"\n  waypoints: \"\"\n  sprayWaypoints: \"\"\n#\n  shotgunPellets: \"\"\n  shotgunBehavior: \"\"\n  shotgunSpread: \"\"\n  shotgunChoke: \"\"\n#\n  underwaterOnly: \"\"\n  landOnly: \"\"\n  psiRequired: \"\"\n  targetMatrix: \"\"\n  convertToCivilian: \"\"\n  manaRequired: \"\"\n  LOSRequired: \"\"\n#\n  noLOSAccuracyPenalty: \"\"\n  kneelBonus: \"\"\n  twoHanded: \"\"\n  blockBothHands: \"\"\n  oneHandedPenalty: \"\"\n#\n  minRange: \"\"\n  maxRange: \"\"\n  aimRange: \"\"\n  autoRange: \"\"\n  snapRange: \"\"\n  dropoff: \"\"\n#\n  accuracyMultiplier: \"\"\n  accuracyAimed: \"\"\n  accuracyAuto: \"\"\n  accuracySnap: \"\"\n  costAimed: \"\"\n  costAuto: \"\"\n  costSnap: \"\"\n#\n  meleeMultiplier: \"\"\n  accuracyMelee: \"\"\n  costMelee: \"\"\n#\n  psiAttackName: \"\"\n  accuracyUse: \"\"\n  accuracyMindControl: \"\"\n  accuracyPanic: \"\"\n  costUse: \"\"\n  costMindcontrol: \"\"\n  costPanic: \"\"\n#\n  weight: \"\"\n  throwRange: \"\"\n  underwaterThrowRange: \"\"\n  throwDropoffRange: \"\"\n  underwaterThrowDropoffRange: \"\"\n  throwDropoff: \"\"\n  throwMultiplier: \"\"\n  accuracyThrow: \"\"\n  costThrow: \"\"\n  costPrime: \"\"\n  costUnprime: \"\"\n#\n  closeQuartersMultiplier: \"\"\n  accuracyCloseQuarters: \"\"\n#\n  damageType: \"\"\n  power: \"\"\n  powerRangeReduction: \"\"\n  powerRangeThreshold: \"\"\n  damageBonus: \"\"\n  blastRadius: \"\"\n  damageAlter: \"\"\n  meleeType: \"\"\n  meleePower: \"\"\n  meleeBonus: \"\"\n  meleeAlter: \"\"\n  FixRadius: \"\"\n  RandomType: \"\"\n  FireBlastCalc: \"\"\n  IgnoreDirection: \"\"\n  IgnoreSelfDestruct: \"\"\n  IgnorePainImmunity: \"\"\n  IgnoreNormalMoraleLose: \"\"\n  IgnoreOverKill: \"\"\n  ArmorEffectiveness: \"\"\n  RadiusEffectiveness: \"\"\n  RadiusReduction: \"\"\n  FireThreshold: \"\"\n  SmokeThreshold: \"\"\n#\n  ToArmorPre: \"\"\n  RandomArmorPre: \"\"\n  ToArmor: \"\"\n  RandomArmor: \"\"\n  ToHealth: \"\"\n  RandomHealth: \"\"\n  ToStun: \"\"\n  RandomStun: \"\"\n  ToWound: \"\"\n  RandomWound: \"\"\n  ToTime: \"\"\n  RandomTime: \"\"\n  ToEnergy: \"\"\n  RandomEnergy: \"\"\n  ToMorale: \"\"\n  RandomMorale: \"\"\n  ToItem: \"\"\n  RandomItem: \"\"\n  ToMana: \"\"\n  RandomMana: \"\"\n  ToTile: \"\"\n  RandomTile: \"\"\n  TileDamageMethod: \"\"\n  TileDamageLimit: \"\"\n#\n  confAimed: \"\"\n  confAuto: \"\"\n  confSnap: \"\"\n  confMelee: \"\"\n  shots: \"\"\n  spendPerShot: \"\"\n  followProjectiles: \"\"\n  name: \"\"\n  shortName: \"\"\n  ammoSlot: \"\"\n  ammoZombieUnitChanceOverride: \"\"\n  ammoSpawnUnitChanceOverride: \"\"\n  ammoSpawnItemChanceOverride: \"\"\n  arcing: \"\"\n#\n  clipSize: \"\"\n  isAmmoRechargeable: \"\"\n#\n  primaryAmmo: \"\"\n  compatibleAmmo: \"\"\n  tuLoad: \"\"\n  tuUnload: \"\"\n  ammo[1]: \"\"\n  ammo[2]: \"\"\n  ammo[3]: \"\"\n#\n  armor: \"\"\n#\n  medikitType: \"\"\n  painKillerActionName: \"\"\n  stimulantActionName: \"\"\n  healActionName: \"\"\n  medikitActionName: \"\"\n  medikitTargetSelf: \"\"\n  medikitTargetImmune: \"\"\n  medikitTargetMatrix: \"\"\n  isConsumable: \"\"\n  painKiller: \"\"\n  heal: \"\"\n  stimulant: \"\"\n  woundRecovery: \"\"\n  healthRecovery: \"\"\n  stunRecovery: \"\"\n  energyRecovery: \"\"\n  manaRecovery: \"\"\n  moraleRecovery: \"\"\n  painKillerRecovery: \"\"\n#\n  requires: \"\"\n  requiresBuy: \"\"\n  requiresBuyBaseFunc: \"\"\n  requiresBuyCountry: \"\"\n  requiresAward: \"\"\n  requiresBonus: \"\"\n  categories: \"\"\n  supportedInventorySections: \"\"\n#\n  size: \"\"\n  costBuy: \"\"\n  monthlyBuyLimit: \"\"\n  costSell: \"\"\n  transferTime: \"\"\n  monthlySalary: \"\"\n  monthlyMaintenance: \"\"\n#\n  SPECAB_NONE: \"Nada\"\n  SPECAB_EXPLODEONDEATH: \"\"\n  SPECAB_BURNFLOOR: \"\"\n  SPECAB_BURN_AND_EXPLODE: \"\"\n#\n  MT_WALK: \"\"\n  MT_FLY: \"\"\n  MT_SLIDE: \"\"\n  MT_FLOAT: \"\"\n  MT_SINK: \"\"\n#\n  TORSO_USE_GENDER: \"\"\n  TORSO_ALWAYS_MALE: \"\"\n  TORSO_ALWAYS_FEMALE: \"\"\n#\n  DRAWING_ROUTINE_SOLDIER_SECTOID: \"\"\n  DRAWING_ROUTINE_FLOATER: \"\"\n  DRAWING_ROUTINE_HWP: \"\"\n  DRAWING_ROUTINE_CYBERDISC: \"\"\n  DRAWING_ROUTINE_CIVILIAN_ETHEREAL: \"\"\n  DRAWING_ROUTINE_SECTOPOD_REAPER: \"\"\n  DRAWING_ROUTINE_SNAKEMAN: \"\"\n  DRAWING_ROUTINE_CHRYSSALID: \"\"\n  DRAWING_ROUTINE_SILACOID: \"\"\n  DRAWING_ROUTINE_CELATID: \"\"\n  DRAWING_ROUTINE_MUTON: \"\"\n  DRAWING_ROUTINE_SWS: \"\"\n  DRAWING_ROUTINE_HALLUCINOID: \"\"\n  DRAWING_ROUTINE_AQUANAUTS: \"\"\n  DRAWING_ROUTINE_CALCINITE_AND_MORE: \"\"\n  DRAWING_ROUTINE_AQUATOID: \"\"\n  DRAWING_ROUTINE_BIO_DRONE: \"\"\n  DRAWING_ROUTINE_TFTD_CIVILIAN_A: \"\"\n  DRAWING_ROUTINE_TFTD_CIVILIAN_B: \"\"\n  DRAWING_ROUTINE_TENTACULAT: \"\"\n  DRAWING_ROUTINE_TRISCENE: \"\"\n  DRAWING_ROUTINE_XARQUID: \"\"\n  DRAWING_ROUTINE_INVERTED_CYBERDISC: \"\"\n#\n  stats: \"\"\n  specab: \"\"\n  movementType: \"\"\n  allowsRunning: \"\"\n  allowsStrafing: \"\"\n  allowsSneaking: \"\"\n  allowsKneeling: \"\"\n  allowsMoving: \"\"\n  fearImmune: \"\"\n  bleedImmune: \"\"\n  painImmune: \"\"\n  zombiImmune: \"\"\n  ignoresMeleeThreat: \"\"\n  createsMeleeThreat: \"\"\n  builtInWeapons: \"\"\n  specialWeapon: \"\"\n  heatVision: \"\"\n  visibilityThroughFire: \"\"\n  psiVision: \"\"\n  psiCamouflage: \"\"\n  visibilityAtDay: \"\"\n  visibilityAtDark: \"\"\n  camouflageAtDay: \"\"\n  camouflageAtDark: \"\"\n  antiCamouflageAtDay: \"\"\n  antiCamouflageAtDark: \"\"\n  psiDefence: \"\"\n  meleeDodge: \"\"\n  meleeDodgeBackPenalty: \"\"\n  recovery: \"\"\n  time: \"\"\n  energy: \"\"\n  morale: \"\"\n  health: \"\"\n  stun: \"\"\n  mana: \"\"\n  units: \"\"\n  ranks: \"\"\n  frontArmor: \"\"\n  sideArmor: \"\"\n  leftArmorDiff: \"\"\n  rearArmor: \"\"\n  underArmor: \"\"\n#\n  sizeX: \"\"\n  sizeY: \"\"\n  buildCost: \"\"\n  buildCostItems: \"\"\n  buildTime: \"\"\n  monthlyCost: \"\"\n  refundValue: \"\"\n  requiresBaseFunc: \"\"\n  provideBaseFunc: \"\"\n  forbiddenBaseFunc: \"\"\n  lift: \"\"\n  hyper: \"\"\n  mind: \"\"\n  mindPower: \"\"\n  grav: \"\"\n  storage: \"\"\n  personnel: \"\"\n  aliens: \"\"\n  crafts: \"\"\n  labs: \"\"\n  workshops: \"\"\n  psiLabs: \"\"\n  trainingRooms: \"\"\n  sightRange: \"\"\n  sightChance: \"\"\n  radarRange: \"\"\n  radarChance: \"\"\n  defense: \"\"\n  hitRatio: \"\"\n  ammoNeeded: \"\"\n  unifiedDamageFormula: \"\"\n  ammoItem: \"\"\n  maxAllowedPerBase: \"\"\n  manaRecoveryPerDay: \"\"\n  healthRecoveryPerDay: \"\"\n  sickBayAbsoluteBonus: \"\"\n  sickBayRelativeBonus: \"\"\n  prisonType: \"\"\n  rightClickActionType: \"\"\n  leavesBehindOnSell: \"\"\n  removalTime: \"\"\n  canBeBuiltOver: \"\"\n  upgradeOnly: \"\"\n  buildOverFacilities: \"\"\n#\n  BFRCT_DEFAULT: \"Normal por defecto\"\n  BFRCT_PRISON: \"\"\n  BFRCT_ENGINEERING: \"\"\n  BFRCT_RESEARCH: \"\"\n  BFRCT_GYM: \"\"\n  BFRCT_PSI_LABS: \"\"\n  BFRCT_BARRACKS: \"\"\n  BFRCT_GREY_MARKET: \"\"\n  BFRCT_GEOSCAPE: \"\"\n#\n  costRent: \"\"\n  soldiers: \"\"\n  maxUnitsLimit: \"\"\n  pilots: \"\"\n  pilotMinStatsRequired: \"\"\n  pilotSoldierBonusesRequired: \"\"\n  vehicles: \"\"\n  onlyOneSoldierGroupAllowed: \"\"\n  allowedSoldierGroups: \"\"\n  allowedArmorGroups: \"\"\n  limitArmorGroups: \"\"\n  maxHWPUnitsLimit: \"\"\n  maxSmallSoldiers: \"\"\n  maxLargeSoldiers: \"\"\n  maxSmallVehicles: \"\"\n  maxLargeVehicles: \"\"\n  maxSmallUnits: \"\"\n  maxLargeUnits: \"\"\n  maxSoldiers: \"\"\n  maxVehicles: \"\"\n  maxItems: \"\"\n  maxStorageSpace: \"\"\n  maxAltitude: \"\"\n  weapons: \"\"\n  weaponStrings: \"\"\n  fixedWeapons: \"\"\n  weaponTypes: \"\"\n  damageMax: \"\"\n  avoidBonus: \"\"\n  avoidBonus2: \"\"\n  powerBonus: \"\"\n  hitBonus: \"\"\n  fuelMax: \"\"\n  speedMax: \"\"\n  accel: \"\"\n  shieldCapacity: \"\"\n  shieldRecharge: \"\"\n  shieldRechargeInGeoscape: \"\"\n  shieldBleedThrough: \"\"\n  shieldRechargedAtBase: \"\"\n  refuelItem: \"\"\n  refuelRate: \"\"\n  repairRate: \"\"\n  spacecraft: \"\"\n  allowLanding: \"\"\n  notifyWhenRefueled: \"\"\n  autoPatrol: \"\"\n  undetectable: \"\"\n  patrolWithoutFuel: \"\"\n  keepCraftAfterFailedMission: \"\"\n  _calculatedValues: \"\"\n  _maxRange: \"\"\n  _minRange: \"\"\n  _avgRange: \"\"\n#\n  hunterKillerPercentage: \"\"\n  huntMode: \"\"\n  huntSpeed: \"\"\n  huntBehavior: \"\"\n  range: \"\"\n  reload: \"\"\n  breakOffTime: \"\"\n  score: \"\"\n  missionScore: \"\"\n  craftCustomDeploy: \"\"\n  missionCustomDeploy: \"\"\n  _escapeCountdown: \"\"\n  _fireRate: \"\"\n  _averageDPM: \"\"\n#\n  HM_INTERCEPTORS: \"\"\n  HM_TRANSPORTS: \"\"\n  HM_RANDOM: \"\"\n#\n  HB_FLEE: \"\"\n  HB_KAMIKAZE: \"\"\n  HB_RANDOM: \"\"\n#\n  tractorBeamPower: \"\"\n  damage: \"\"\n  shieldDamageModifier: \"\"\n  accuracy: \"\"\n  reloadCautious: \"\"\n  reloadStandard: \"\"\n  reloadAggressive: \"\"\n  launcher: \"\"\n  weaponType: \"\"\n  clip: \"\"\n  ammoMax: \"\"\n  rearmRate: \"\"\n  bulletSaving: \"\"\n  _damageRange: \"\"\n  _damageRangeBasic: \"\"\n  _averageTotalDamage: \"\"\n#\n  allowPiloting: \"\"\n  costSalary: \"\"\n  costSalarySquaddie: \"\"\n  costSalarySergeant: \"\"\n  costSalaryCaptain: \"\"\n  costSalaryColonel: \"\"\n  costSalaryCommander: \"\"\n#\n  race: \"\"\n  rank: \"\"\n  livingWeapon: \"\"\n  meleeWeapon: \"Arma blanca\"\n  psiWeapon: \"\"\n  _builtInWeaponSets: \"\"\n  _weightedBuiltInWeaponSets: \"\"\n  spawnUnit: \"\"\n  _capturable: \"\"\n  capturable: \"\"\n  canSurrender: \"\"\n  autoSurrender: \"\"\n  spotter: \"\"\n  sniper: \"\"\n"
  },
  {
    "path": "bin/common/Language/Technical/fi.yml",
    "content": "fi:\n#=================== Menu ===================\n#TestState.cpp\n  STR_BAD_NODES: \"Huonot solmut (noodit) RMP-tiedostoissa\"\n  STR_BAD_NODES_DESC: \"Tarkistaa RMP-tiedostoista kentän rajojen ulkopuoliset solmut.{NEWLINE}Nämä EIVÄT aiheuta kaatumisia, mutta peli jättää ne huomiotta eivätkä siis toimi tarkoitetulla tavalla.\"\n#\n  STR_MCD_CHECK: \"MCD-tarkistus\"\n  STR_MCD_CHECK_DESC: \"\"\n#\n  STR_PALETTE_CHECK: \"Palettisovitus\"\n  STR_PALETTE_CHECK_DESC: \"Pyrkii sovittamaan muunneltujen kuvien paletit virallisiin paletteihin ja antaa selon kaikista kuvista, joilla ei ole 100 % vastaavuutta.\"\n#\n  STR_SCRIPT_TAGS: \"Komentosarjojen tunnisteiden vienti\"\n  STR_SCRIPT_TAGS_DESC: \"Vie komentosarjojen tunnisteet CSV-muodossa.\"\n#\n  STR_MAP_RESOURCES: \"Etsi kentän tiedostoja\"\n  STR_MAP_RESOURCES_DESC: \"Etsii puuttuvia ja käyttämättömiä kenttään liittyviä tiedostoja ja sääntöjoukkoja.\"\n#\n  STR_CHECKING_TERRAIN: \"Tarkistetaan maastoa...\"\n  STR_CHECKING_UFOS: \"Tarkistetaan ufoja...\"\n  STR_CHECKING_CRAFT: \"Tarkistetaan alusta...\"\n#\n  BACKPALS.DAT: \"BACKPALS.DAT\"\n  PAL_GEOSCAPE: \"PAL_GEOSCAPE\"\n  PAL_BASESCAPE: \"PAL_BASESCAPE\"\n  PAL_GRAPHS: \"PAL_GRAPHS\"\n  PAL_UFOPAEDIA: \"PAL_UFOPAEDIA\"\n  PAL_BATTLEPEDIA: \"PAL_BATTLEPEDIA\"\n  PAL_BATTLESCAPE: \"PAL_BATTLESCAPE\"\n  PAL_BATTLESCAPE_1: \"PAL_BATTLESCAPE_1\"\n  PAL_BATTLESCAPE_2: \"PAL_BATTLESCAPE_2\"\n  PAL_BATTLESCAPE_3: \"PAL_BATTLESCAPE_3\"\n#=================== Ufopaedia ===================\n#StatsForNerdsState.cpp\n  BT_NONE: \"Ei mitään\"\n  BT_FIREARM: \"Tuliase\"\n  BT_AMMO: \"Ammukset\"\n  BT_MELEE: \"Lähitaisteluase\"\n  BT_GRENADE: \"Kranaatti\"\n  BT_PROXIMITYGRENADE: \"Sensorikranaatti\"\n  BT_MEDIKIT: \"Ensiapulaite\"\n  BT_SCANNER: \"Liiketunnistin\"\n  BT_MINDPROBE: \"Mielenluotain\"\n  BT_PSIAMP: \"Psi-vahvistin\"\n  BT_FLARE: \"Valonlähde\"\n  BT_CORPSE: \"Ruumis\"\n#\n  DRT_DEFAULT: \"alkuperäispelin (vanilla) oletus\"\n  DRT_UFO: \"0-200% väli\"\n  DRT_TFTD: \"50-150% väli\"\n  DRT_FLAT: \"tasainen vahinko\"\n  DRT_FIRE: \"erityinen tulivahinko\"\n  DRT_NONE: \"ei vahinkoa\"\n  DRT_UFO_WITH_TWO_DICE: \"0-200% väli (2 nopan heitto)\"\n  DRT_EASY: \"50-200% väli\"\n  DRT_STANDARD: \"tavallisen vahingon kantama\"\n  DRT_EXPLOSION: \"räjähdysvahingon kantama\"\n#\n  BFT_NONE: \"ei mitään\"\n  BFT_INSTANT: \"välitön\"\n  BFT_SET: \"käsin asetettu\"\n  BFT_FIXED: \"kiinteä\"\n#\n  BMT_NORMAL: \"perus (monikäyttöinen)\"\n  BMT_HEAL: \"parannus\"\n  BMT_STIMULANT: \"piriste\"\n  BMT_PAINKILLER: \"kipulääke\"\n#\n  ETM_DEFAULT: \"oletus\"\n  ETM_MELEE_100: \"LÄHITAISTELU\"\n  ETM_MELEE_50: \"LÄHITAISTELU (50% todennäköisyys)\"\n  ETM_MELEE_33: \"LÄHITAISTELU (33% todennäköisyys)\"\n  ETM_FIRING_100: \"TULITUS\"\n  ETM_FIRING_50: \"TULITUS (50% todennäköisyys)\"\n  ETM_FIRING_33: \"TULITUS (33% todennäköisyys)\"\n  ETM_THROWING_100: \"HEITTO\"\n  ETM_THROWING_50: \"HEITTO (50% todennäköisyys)\"\n  ETM_THROWING_33: \"HEITTO (33% todennäköisyys)\"\n  ETM_FIRING_AND_THROWING: \"TULITUS ja HEITTO\"\n  ETM_FIRING_OR_THROWING: \"TULITUS tai HEITTO\"\n  ETM_REACTIONS: \"REAKTIOKYKY\"\n  ETM_REACTIONS_AND_MELEE: \"REAKTIOKYKY ja LÄHITAISTELU\"\n  ETM_REACTIONS_AND_FIRING: \"REAKTIOKYKY ja TULITUS\"\n  ETM_REACTIONS_AND_THROWING: \"REAKTIOKYKY ja HEITTO\"\n  ETM_REACTIONS_OR_MELEE: \"REAKTIOKYKY tai LÄHITAISTELU\"\n  ETM_REACTIONS_OR_FIRING: \"REAKTIOKYKY tai TULITUS\"\n  ETM_REACTIONS_OR_THROWING: \"REAKTIOKYKY tai HEITTO\"\n  ETM_BRAVERY: \"ROHKEUS\"\n  ETM_BRAVERY_2X: \"ROHKEUS (x2)\"\n  ETM_BRAVERY_AND_REACTIONS: \"ROHKEUS ja REAKTIOKYKY\"\n  ETM_BRAVERY_OR_REACTIONS: \"ROHKEUS tai REAKTIOKYKY\"\n  ETM_BRAVERY_OR_REACTIONS_2X: \"ROHKEUS tai REAKTIOKYKY (x2)\"\n  ETM_PSI_STRENGTH: \"PSI-VOIMA\"\n  ETM_PSI_STRENGTH_2X: \"PSI-VOIMA (x2)\"\n  ETM_PSI_SKILL: \"PSI-TAITO\"\n  ETM_PSI_SKILL_2X: \"PSI-TAITO (x2)\"\n  ETM_PSI_STRENGTH_AND_SKILL: \"PSI-VOIMA ja PSI-TAITO\"\n  ETM_PSI_STRENGTH_AND_SKILL_2X: \"PSI-VOIMA ja PSI-TAITO (x2)\"\n  ETM_PSI_STRENGTH_OR_SKILL: \"PSI-VOIMA tai PSI-TAITO\"\n  ETM_PSI_STRENGTH_OR_SKILL_2X: \"PSI-VOIMA tai PSI-TAITO (x2)\"\n  ETM_NOTHING: \"ei koulutusta\"\n#\n  battleType: \"Esinetyyppi\"\n  experienceTrainingMode: \"Koulutustapa\"\n  manaExperience: \"Manakokemus\"\n  arcingShot: \"Kaareva?\"\n  isFireExtinguisher: \"Sammuttaa tulta?\"\n  explodeInventory: \"Räjähtää repussa?\"\n  waypoints: \"Enimmäisvälietapit\"\n  sprayWaypoints: \"Epätarkan tulen välietapit\"\n#\n  shotgunPellets: \"Haulien määrä\"\n  shotgunBehavior: \"Haulikon käyttäytyminen\"\n  shotgunSpread: \"Haulien hajonta\"\n  shotgunChoke: \"Haulikon supistus\"\n#\n  underwaterOnly: \"Vain vedessä?\"\n  landOnly: \"Vain maalla?\"\n  psiRequired: \"Vaatiiko psi-taitoa?\"\n  targetMatrix: \"Esineen kohteet\"\n  convertToCivilian: \"\"\n  manaRequired: \"Vaatiiko manaa?\"\n  LOSRequired: \"Vaatiiko näköyhteyttä?\"\n#\n  noLOSAccuracyPenalty: \"Puuttuvan näköyhteyden sakkokerroin\"\n  kneelBonus: \"Polvistumishyötykerroin\"\n  twoHanded: \"Kaksikätinen?\"\n  blockBothHands: \"Tukkii molemmat kädet?\"\n  oneHandedPenalty: \"Yksikätisen käytön sakko\"\n#\n  minRange: \"Vähimmäisetäisyys\"\n  maxRange: \"Huippuetäisyys\"\n  aimRange: \"Tähdätyn laukauksen etäisyys\"\n  autoRange: \"Sarjatulen etäisyys\"\n  snapRange: \"Kertatulen etäisyys\"\n  dropoff: \"Tarkkuuden lasku/ruutu\"\n#\n  accuracyMultiplier: \"Tulituksen tarkkuuskerroin\"\n  accuracyAimed: \"Tähdätyn laukauksen tarkkuus\"\n  accuracyAuto: \"Sarjatulen tarkkuus\"\n  accuracySnap: \"Kertatulen tarkkuus\"\n  costAimed: \"Tähdätyn laukauksen hinta\"\n  costAuto: \"Sarjatulen hinta\"\n  costSnap: \"Kertatulen hinta\"\n#\n  meleeMultiplier: \"Lähitaistelun tarkkuuskerroin\"\n  accuracyMelee: \"Lähitaistelutarkkuus\"\n  costMelee: \"Lähitaistelun hinta\"\n#\n  psiAttackName: \"Psi-hyökkäyksen nimi\"\n  accuracyUse: \"Toiminnan tarkkuus\"\n  accuracyMindControl: \"Mielenhallinnan tarkkuus\"\n  accuracyPanic: \"Paniikkihyökkäyksen tarkkuus\"\n  costUse: \"Toiminnan hinta\"\n  costMindcontrol: \"Mielenhallinnan hinta\"\n  costPanic: \"Paniikkihyökkäyksen hinta\"\n#\n  weight: \"Paino\"\n  throwRange: \"\"\n  underwaterThrowRange: \"\"\n  throwDropoffRange: \"\"\n  underwaterThrowDropoffRange: \"\"\n  throwDropoff: \"\"\n  throwMultiplier: \"Heiton tarkkuuskerroin\"\n  accuracyThrow: \"Heittotarkkuus\"\n  costThrow: \"Heiton hinta\"\n  costPrime: \"Virittämishinta\"\n  costUnprime: \"Virityksenpoiston hinta\"\n#\n  closeQuartersMultiplier: \"Lähietäisyyden (CQC) tarkkuuskerroin\"\n  accuracyCloseQuarters: \"Lähietäisyyden (CQC) tarkkuus\"\n#\n  damageType: \"Vahinkotyyppi\"\n  power: \"Tuhovoima\"\n  powerRangeReduction: \"Tuhovoiman lasku/ruutu\"\n  powerRangeThreshold: \"Tuhovoiman laskun kynnys\"\n  damageBonus: \"Lisävahinko\"\n  blastRadius: \"Räjähdyssäde\"\n  damageAlter: \"Lisätietoa vahingosta:\"\n  meleeType: \"Lähitaistelun vahinkotyyppi\"\n  meleePower: \"Lähitaistelun tuhovoima\"\n  meleeBonus: \"Lähitaisteluvoiman lisä\"\n  meleeAlter: \"Lisätietoa lähitaistelusta:\"\n  FixRadius: \"Räjähdyssäde\"\n  RandomType: \"Laskutapa\"\n  FireBlastCalc: \"Alkuperäinen (vanilla) tulen käyttäytyminen?\"\n  IgnoreDirection: \"Älä huomioi suuntaa\"\n  IgnoreSelfDestruct: \"Älä huomioi itsetuhoa\"\n  IgnorePainImmunity: \"Älä huomioi tainnutusimmuniteettia\"\n  IgnoreNormalMoraleLose: \"Älä huomioi alkuperäistä (vanilla) taistelutahdon menetystä\"\n  IgnoreOverKill: \"Älä huomioi ylilyöntejä\"\n  ArmorEffectiveness: \"Panssarin tehokkuus\"\n  RadiusEffectiveness: \"Säteen tehokkuus\"\n  RadiusReduction: \"Vahingon säteittäinen lasku\"\n  FireThreshold: \"Syttymiskynnys\"\n  SmokeThreshold: \"Savunmuodostuskynnys\"\n#\n  ToArmorPre: \"Panssarin vahinkoa edeltävä kerroin\"\n  RandomArmorPre: \"Panssarin vahinkoa edeltävä SLG (RNG)?\"\n  ToArmor: \"Panssarivahingon kerroin\"\n  RandomArmor: \"Panssarivahingon SLG (RNG)?\"\n  ToHealth: \"Terveysvahinkokerroin\"\n  RandomHealth: \"Terveysvahingon SLG (RNG)?\"\n  ToStun: \"Tainnutusvahingon kerroin\"\n  RandomStun: \"Tainnutusvahingon SLG (RNG)?\"\n  ToWound: \"Haavalukukerroin\"\n  RandomWound: \"Alkuperäinen (vanilla) haavoittumisen SLG (RNG)?\"\n  ToTime: \"AY-vahinkokerroin\"\n  RandomTime: \"AY-vahingon SLG (RNG)?\"\n  ToEnergy: \"Energiavahinkokerroin\"\n  RandomEnergy: \"Energiavahingon SLG (RNG)?\"\n  ToMorale: \"Taistelutahtovahingon kerroin\"\n  RandomMorale: \"Taistelutahtovahingon SLG (RNG)?\"\n  ToItem: \"Esinevahinkokerroin\"\n  RandomItem: \"Esinevahingon SLG (RNG)?\"\n  ToMana: \"Manavahingon kerroin\"\n  RandomMana: \"Manavahingon SLG (RNG)?\"\n  ToTile: \"Maastovahinkokerroin\"\n  RandomTile: \"Maastovahingon SLG (RNG)?\"\n  TileDamageMethod: \"Ruudun vahingoitustapa\"\n  TileDamageLimit: \"\"\n#\n  confAimed: \"Tähdätyn toiminta:\"\n  confAuto: \"Sarjatulen toiminta:\"\n  confSnap: \"Kertatulen toiminta:\"\n  confMelee: \"Lähitaistelun toiminta:\"\n  shots: \"Laukauksia toimintaa kohden:\"\n  spendPerShot: \"Kulutus ammusta kohti:\"\n  followProjectiles: \"Seuraa ammuksia?\"\n  name: \"Nimi\"\n  shortName: \"Lyhyt nimi\"\n  ammoSlot: \"Käytetty ammuspaikka\"\n  ammoZombieUnitChanceOverride: \"\"\n  ammoSpawnUnitChanceOverride: \"\"\n  ammoSpawnItemChanceOverride: \"\"\n  arcing: \"Kaareva?\"\n#\n  clipSize: \"Lipaskoko\"\n  isAmmoRechargeable: \"\"\n#\n  primaryAmmo: \"Ensisijainen ammuspaikka\"\n  compatibleAmmo: \"Yhteensopivat ammukset\"\n  tuLoad: \"Lataushinta\"\n  tuUnload: \"Tyhjennyshinta\"\n  ammo[1]: \"Lisäammuspaikka 1:\"\n  ammo[2]: \"Lisäammuspaikka 2:\"\n  ammo[3]: \"Lisäammuspaikka 3:\"\n#\n  armor: \"Panssari\"\n#\n  medikitType: \"Ensiapulaitetyyppi\"\n  painKillerActionName: \"\"\n  stimulantActionName: \"\"\n  healActionName: \"\"\n  medikitActionName: \"Ensiapulaitteen toiminnon nimi\"\n  medikitTargetSelf: \"Ensiapulaitteen käyttö itseen?\"\n  medikitTargetImmune: \"Ensiapulaitteen käyttö verenvuodolle immuuneihin?\"\n  medikitTargetMatrix: \"Ensiapulaitteen kohteet\"\n  isConsumable: \"Kulutettavissa?\"\n  painKiller: \"Kipulääkkeiden käyttöjä\"\n  heal: \"Parannusten käyttöjä\"\n  stimulant: \"Piristeiden käyttöjä\"\n  woundRecovery: \"Haavojen parantuminen\"\n  healthRecovery: \"Terveyden palautuminen\"\n  stunRecovery: \"Tainnutusvahingon vähentyminen\"\n  energyRecovery: \"Energian palautuminen\"\n  manaRecovery: \"Manan palautuminen\"\n  moraleRecovery: \"Taistelutahdon palautuminen\"\n  painKillerRecovery: \"Kipulääkkeen voimakkuus\"\n#\n  requires: \"Vaatii tutkimusta\"\n  requiresBuy: \"Vaatii tutkimusta ostoon\"\n  requiresBuyBaseFunc: \"Tarvitaan palveluja ostoon\"\n  requiresBuyCountry: \"Valtion oltava liitossa\"\n  requiresAward: \"\"\n  requiresBonus: \"\"\n  categories: \"Luokat\"\n  supportedInventorySections: \"Varustepaikat\"\n#\n  size: \"Koko\"\n  costBuy: \"Ostohinta\"\n  monthlyBuyLimit: \"Ostosten kuukausikiintiö\"\n  costSell: \"Myyntihinta\"\n  transferTime: \"Siirtoaika tunteina\"\n  monthlySalary: \"Kuukausipalkka\"\n  monthlyMaintenance: \"Ylläpitokustannukset / kuukausi\"\n#\n  SPECAB_NONE: \"Ei mitään\"\n  SPECAB_EXPLODEONDEATH: \"Räjähtää kuollessaan\"\n  SPECAB_BURNFLOOR: \"Polttaa lattiaa\"\n  SPECAB_BURN_AND_EXPLODE: \"Polttaa lattiaa ja räjähtää kuollessaan\"\n#\n  MT_WALK: \"Kävely\"\n  MT_FLY: \"Lento\"\n  MT_SLIDE: \"Liukuminen\"\n  MT_FLOAT: \"Leijuminen\"\n  MT_SINK: \"Uppoaminen\"\n#\n  TORSO_USE_GENDER: \"Käytä sukupuolta\"\n  TORSO_ALWAYS_MALE: \"Aina miespuolinen\"\n  TORSO_ALWAYS_FEMALE: \"Aina naispuolinen\"\n#\n  DRAWING_ROUTINE_SOLDIER_SECTOID: \"Sotilas, harmaa\"\n  DRAWING_ROUTINE_FLOATER: \"Leijuja\"\n  DRAWING_ROUTINE_HWP: \"Miehittämättömät taistelukoneet\"\n  DRAWING_ROUTINE_CYBERDISC: \"Kybelautanen\"\n  DRAWING_ROUTINE_CIVILIAN_ETHEREAL: \"Siviili, eteeri\"\n  DRAWING_ROUTINE_SECTOPOD_REAPER: \"Sektopodi, raatelija\"\n  DRAWING_ROUTINE_SNAKEMAN: \"Käärmemies\"\n  DRAWING_ROUTINE_CHRYSSALID: \"Munamies\"\n  DRAWING_ROUTINE_SILACOID: \"Silikoidi\"\n  DRAWING_ROUTINE_CELATID: \"Kelatoidi\"\n  DRAWING_ROUTINE_MUTON: \"Mutoni\"\n  DRAWING_ROUTINE_SWS: \"Miehittämättömät taistelukoneet\"\n  DRAWING_ROUTINE_HALLUCINOID: \"Hallusinoidi\"\n  DRAWING_ROUTINE_AQUANAUTS: \"Akvanautit\"\n  DRAWING_ROUTINE_CALCINITE_AND_MORE: \"Kalsiniitti, syväläinen, kidusihminen, hummerimies, tasootti\"\n  DRAWING_ROUTINE_AQUATOID: \"Akvatoidi\"\n  DRAWING_ROUTINE_BIO_DRONE: \"Biodroidi\"\n  DRAWING_ROUTINE_TFTD_CIVILIAN_A: \"TFTD:n A-tyypin siviilit ja TFTD:n zombi\"\n  DRAWING_ROUTINE_TFTD_CIVILIAN_B: \"TFTD:n B-tyypin siviilit\"\n  DRAWING_ROUTINE_TENTACULAT: \"Lonkeromanaaja\"\n  DRAWING_ROUTINE_TRISCENE: \"Triaslisko\"\n  DRAWING_ROUTINE_XARQUID: \"Kalmanhelmi\"\n  DRAWING_ROUTINE_INVERTED_CYBERDISC: \"Käänteinen kyberlautanen (työntöanimaatio ylhäällä)\"\n#\n  stats: \"Ominaisuuskertoimet\"\n  specab: \"Erikoistaito\"\n  movementType: \"Liikkumistapa\"\n  allowsRunning: \"Salli juoksu?\"\n  allowsStrafing: \"Salli sivuttaisastunta?\"\n  allowsSneaking: \"Salli hiipiminen?\"\n  allowsKneeling: \"Salli polvistuminen?\"\n  allowsMoving: \"Salli liikkuminen?\"\n  fearImmune: \"Immuuni taistelutahdon laskulle?\"\n  bleedImmune: \"Immuuni verenvuodolle?\"\n  painImmune: \"Immuuni tainnutukselle?\"\n  zombiImmune: \"Immuuni zombifikaatiolle?\"\n  ignoresMeleeThreat: \"Ei huomioi lähietäisyystaistelua? (CQC)\"\n  createsMeleeThreat: \"Tuottaa lähietäisyystaistelun? (CQC)\"\n  builtInWeapons: \"Sisäänrakennetut esineet\"\n  specialWeapon: \"Erikoisase\"\n  heatVision: \"\"\n  visibilityThroughFire: \"\"\n  psiVision: \"Psi-aisti\"\n  psiCamouflage: \"Psi-naamioituminen\"\n  visibilityAtDay: \"Näkyvyys päivällä\"\n  visibilityAtDark: \"Näkyvyys yöllä\"\n  camouflageAtDay: \"Piiloutuvuus päivällä\"\n  camouflageAtDark: \"Piiloutuvuus yöllä\"\n  antiCamouflageAtDay: \"Paljastavuus päivällä\"\n  antiCamouflageAtDark: \"Paljastavuus yöllä\"\n  psiDefence: \"Psi-puolustus\"\n  meleeDodge: \"Väistäminen lähitaistelussa\"\n  meleeDodgeBackPenalty: \"Väistörangaistus lähitaistelussa\"\n  recovery: \"Palautuminen joka vuoro:\"\n  time: \"Aika\"\n  energy: \"Energia\"\n  morale: \"Taistelutahto\"\n  health: \"Terveys\"\n  stun: \"Tainnutus\"\n  mana: \"Mana\"\n  units: \"Yhteensopivat yksiköt\"\n  ranks: \"\"\n  frontArmor: \"Etupanssari\"\n  sideArmor: \"Sivupanssari\"\n  leftArmorDiff: \"Vasemman panssarin ero\"\n  rearArmor: \"Takapanssari\"\n  underArmor: \"Alapanssari\"\n#\n  sizeX: \"\"\n  sizeY: \"\"\n  buildCost: \"Rakennushinta\"\n  buildCostItems: \"Rakennusaineet:\"\n  buildTime: \"Rakennusaika\"\n  monthlyCost: \"Kuukausihinta\"\n  refundValue: \"Palautusarvo\"\n  requiresBaseFunc: \"Tarvitsee palveluja\"\n  provideBaseFunc: \"Antaa palveluja\"\n  forbiddenBaseFunc: \"Estää palveluja\"\n  lift: \"Laitoshissi?\"\n  hyper: \"Hyperaaltotulkitsin?\"\n  mind: \"EEG-suoja?\"\n  mindPower: \"EEG-suojan tehokkuus\"\n  grav: \"Painovoimasuoja?\"\n  storage: \"Varastotila\"\n  personnel: \"Asuintila\"\n  aliens: \"Vankitila\"\n  crafts: \"Hallitila\"\n  labs: \"Laboratoriotila\"\n  workshops: \"Työpajatila\"\n  psiLabs: \"Psi-laboratoriotila\"\n  trainingRooms: \"Kuntosalitila\"\n  sightRange: \"Näköetäisyys\"\n  sightChance: \"Näkötodennäköisyys\"\n  radarRange: \"Tutkan kantama\"\n  radarChance: \"Tutkan havaintotodennäköisyys\"\n  defense: \"Puolustusarvo\"\n  hitRatio: \"Osumatarkkuus\"\n  ammoNeeded: \"Tarvittavat ammukset\"\n  unifiedDamageFormula: \"\"\n  ammoItem: \"Ammustyyppi\"\n  maxAllowedPerBase: \"Suurin sallittu määrä tukikohdassa\"\n  manaRecoveryPerDay: \"Päivittäinen mana\"\n  healthRecoveryPerDay: \"Päivittäinen terveys\"\n  sickBayAbsoluteBonus: \"Sairasosaston absoluuttinen vaikutus\"\n  sickBayRelativeBonus: \"Sairasosaston suhteellinen vaikutus\"\n  prisonType: \"Vankilatyyppi\"\n  rightClickActionType: \"Oikean hiirennäppäimen toiminta\"\n  leavesBehindOnSell: \"Jättää jälkeen myynnissä\"\n  removalTime: \"Poistoaika\"\n  canBeBuiltOver: \"Päälle voi rakentaa?\"\n  upgradeOnly: \"\"\n  buildOverFacilities: \"Päällerakennuslaitokset\"\n#\n  BFRCT_DEFAULT: \"alkuperäispelin (vanilla) oletus\"\n  BFRCT_PRISON: \"Mene muukalaisten vankilaitokseen\"\n  BFRCT_ENGINEERING: \"Mene tuotantoon\"\n  BFRCT_RESEARCH: \"Mene tutkimukseen\"\n  BFRCT_GYM: \"Mene taistelukoulutukseen\"\n  BFRCT_PSI_LABS: \"Mene psi-laboratorioon\"\n  BFRCT_BARRACKS: \"Mene parakkeihin\"\n  BFRCT_GREY_MARKET: \"Mene harmaille markkinoille\"\n  BFRCT_GEOSCAPE: \"Mene geomaisemaan\"\n#\n  costRent: \"Vuokrahinta\"\n  soldiers: \"Rahtitila\"\n  maxUnitsLimit: \"\"\n  pilots: \"Ohjaamotila\"\n  pilotMinStatsRequired: \"\"\n  pilotSoldierBonusesRequired: \"\"\n  vehicles: \"MTK-tila\"\n  onlyOneSoldierGroupAllowed: \"\"\n  allowedSoldierGroups: \"\"\n  allowedArmorGroups: \"\"\n  limitArmorGroups: \"\"\n  maxHWPUnitsLimit: \"\"\n  maxSmallSoldiers: \"Max pienet sotilaat\"\n  maxLargeSoldiers: \"Max isot sotilaat\"\n  maxSmallVehicles: \"Max pienet kulkuneuvot\"\n  maxLargeVehicles: \"Max isot kulkuneuvot\"\n  maxSmallUnits: \"Max pienet yksiköt\"\n  maxLargeUnits: \"Max isot yksiköt\"\n  maxSoldiers: \"Max sotilaat\"\n  maxVehicles: \"Max kulkuneuvot\"\n  maxItems: \"Varustemäärärajoitus\"\n  maxStorageSpace: \"Varastotila\"\n  maxAltitude: \"Ilmataistelun korkeusraja\"\n  weapons: \"Asepaikat\"\n  weaponStrings: \"Asenimet\"\n  fixedWeapons: \"Ennalta määrätyt aseet\"\n  weaponTypes: \"Sallitut asetyypit\"\n  damageMax: \"Kestävyys\"\n  avoidBonus: \"Väistöetu (kiinteä)\"\n  avoidBonus2: \"\"\n  powerBonus: \"Tuhovoimalisä (kiinteä)\"\n  hitBonus: \"Osumalisä (kiinteä)\"\n  fuelMax: \"Polttoainetankki\"\n  speedMax: \"Huippunopeus\"\n  accel: \"Kiihtyvyys\"\n  shieldCapacity: \"Suojat\"\n  shieldRecharge: \"Suojien latautuminen (taistelu)\"\n  shieldRechargeInGeoscape: \"Suojien latautuminen (kartta)\"\n  shieldBleedThrough: \"Suojien vuotaminen\"\n  shieldRechargedAtBase: \"Suojien latautuminen (tukikohta)\"\n  refuelItem: \"Tankkausaine\"\n  refuelRate: \"Tankkausnopeus\"\n  repairRate: \"Korjausnopeus\"\n  spacecraft: \"Lopullinen alus?\"\n  allowLanding: \"Salli laskeutuminen?\"\n  notifyWhenRefueled: \"Ilmoita, kun tankattu?\"\n  autoPatrol: \"Automaattinen partiointi?\"\n  undetectable: \"Ei havaittavissa?\"\n  patrolWithoutFuel: \"\"\n  keepCraftAfterFailedMission: \"Laskuvarjojoukkoja?\"\n  _calculatedValues: \"Lasketut arvot\"\n  _maxRange: \"Huippuetäisyys\"\n  _minRange: \"Vähimmäisetäisyys\"\n  _avgRange: \"Keskimääräinen etäisyys\"\n#\n  hunterKillerPercentage: \"Vastatorjunnan (HK) todennäköisyys\"\n  huntMode: \"Vastatorjuntatila\"\n  huntSpeed: \"Vastatorjuntanopeus\"\n  huntBehavior: \"Vastatorjuntakäyttäytyminen\"\n  range: \"Kantama\"\n  reload: \"Latausaika\"\n  breakOffTime: \"Irrottautumisaika\"\n  score: \"Pisteet\"\n  missionScore: \"Tehtävän pisteet\"\n  craftCustomDeploy: \"Sijoitus ufon ympäristöön\"\n  missionCustomDeploy: \"Sijoitus tehtäväalueelle\"\n  _escapeCountdown: \"Paon lähtölaskenta\"\n  _fireRate: \"Tulinopeus\"\n  _averageDPM: \"Keskimääräinen DPM\"\n#\n  HM_INTERCEPTORS: \"suosi torjuntahävittäjiä\"\n  HM_TRANSPORTS: \"suosi torjuntakuljetusaluksia\"\n  HM_RANDOM: \"satunnainen\"\n#\n  HB_FLEE: \"pakene alakynnessä\"\n  HB_KAMIKAZE: \"taistele tuhoutumiseen asti\"\n  HB_RANDOM: \"satunnainen\"\n#\n  tractorBeamPower: \"Vetosäteen teho\"\n  damage: \"Vahinko\"\n  shieldDamageModifier: \"Kilven vahinkokerroin\"\n  accuracy: \"Tarkkuus\"\n  reloadCautious: \"Lataa (varovainen)\"\n  reloadStandard: \"Lataa (tavallinen)\"\n  reloadAggressive: \"Lataa (aggressiivinen)\"\n  launcher: \"Laukaisuesine\"\n  weaponType: \"Asetyyppi\"\n  clip: \"Lipasesine\"\n  ammoMax: \"Ammukset\"\n  rearmRate: \"Aseistusnopeus\"\n  bulletSaving: \"Ammusten säästö?\"\n  _damageRange: \"\"\n  _damageRangeBasic: \"\"\n  _averageTotalDamage: \"Keskimääräinen kokonaisvahinko\"\n#\n  allowPiloting: \"\"\n  costSalary: \"\"\n  costSalarySquaddie: \"\"\n  costSalarySergeant: \"\"\n  costSalaryCaptain: \"\"\n  costSalaryColonel: \"\"\n  costSalaryCommander: \"\"\n#\n  race: \"\"\n  rank: \"\"\n  livingWeapon: \"\"\n  meleeWeapon: \"Lähitaisteluase\"\n  psiWeapon: \"\"\n  _builtInWeaponSets: \"\"\n  _weightedBuiltInWeaponSets: \"\"\n  spawnUnit: \"\"\n  _capturable: \"\"\n  capturable: \"\"\n  canSurrender: \"\"\n  autoSurrender: \"\"\n  spotter: \"\"\n  sniper: \"\"\n"
  },
  {
    "path": "bin/common/Language/Technical/fr.yml",
    "content": "fr:\n#=================== Menu ===================\n#TestState.cpp\n  STR_BAD_NODES: \"Mauvais nœuds dans les fichiers RMP\"\n  STR_BAD_NODES_DESC: \"Vérifie les fichiers RMP pour détecter des nœuds en dehors des limites de la carte.{NEWLINE}Cela ne provoquera PAS de plantages, mais ces nœuds seront ignorés par le jeu et ne fonctionneront donc pas comme prévu.\"\n#\n  STR_MCD_CHECK: \"Vérifications MCD\"\n  STR_MCD_CHECK_DESC: \"Vérifie les fichiers MCD pour les objets de sol avec un coût de mouvement nul ; vérifie également les références invalides DieMCD/AltMCD ; vérifie les LOFTemps invalides.\"\n#\n  STR_PALETTE_CHECK: \"Correspondance de palette\"\n  STR_PALETTE_CHECK_DESC: \"Tente de faire correspondre les palettes des images modifiées aux palettes officielles et signale toutes les images qui n'ont pas une correspondance parfaite.\"\n#\n  STR_SCRIPT_TAGS: \"Export des balises de script\"\n  STR_SCRIPT_TAGS_DESC: \"Exporte les balises de script au format CSV.\"\n#\n  STR_MAP_RESOURCES: \"Vérification des ressources de la carte\"\n  STR_MAP_RESOURCES_DESC: \"Vérifie les fichiers et règles manquants relatifs aux cartes.\"\n#\n  STR_CHECKING_TERRAIN: \"Vérification du terrain...\"\n  STR_CHECKING_UFOS: \"Vérification des OVNIs...\"\n  STR_CHECKING_CRAFT: \"Vérification des vaisseaux...\"\n#\n  BACKPALS.DAT: \"BACKPALS.DAT\"\n  PAL_GEOSCAPE: \"PAL_GEOSCAPE\"\n  PAL_BASESCAPE: \"PAL_BASESCAPE\"\n  PAL_GRAPHS: \"PAL_GRAPHS\"\n  PAL_UFOPAEDIA: \"PAL_UFOPAEDIA\"\n  PAL_BATTLEPEDIA: \"PAL_BATTLEPEDIA\"\n  PAL_BATTLESCAPE: \"PAL_BATTLESCAPE\"\n  PAL_BATTLESCAPE_1: \"PAL_BATTLESCAPE_1\"\n  PAL_BATTLESCAPE_2: \"PAL_BATTLESCAPE_2\"\n  PAL_BATTLESCAPE_3: \"PAL_BATTLESCAPE_3\"\n#=================== Ufopaedia ===================\n#StatsForNerdsState.cpp\n  BT_NONE: \"Aucun\"\n  BT_FIREARM: \"Arme à feu\"\n  BT_AMMO: \"Munition\"\n  BT_MELEE: \"Arme de mêlée\"\n  BT_GRENADE: \"Grenade\"\n  BT_PROXIMITYGRENADE: \"Grenade de proximité\"\n  BT_MEDIKIT: \"Médikit\"\n  BT_SCANNER: \"Détecteur de mouvement\"\n  BT_MINDPROBE: \"Sonde d'esprit\"\n  BT_PSIAMP: \"Psi Amp\"\n  BT_FLARE: \"Flare\"\n  BT_CORPSE: \"Cadavre/Corps\"\n#\n  DRT_DEFAULT: \"Paramètres par défaut de la version d'origine\"\n  DRT_UFO: \"Écart de 0% à 200%\"\n  DRT_TFTD: \"Écart de 50% à 150%\"\n  DRT_FLAT: \"dégâts fixes\"\n  DRT_FIRE: \"Dégâts de feu spéciaux\"\n  DRT_NONE: \"pas de dégâts\"\n  DRT_UFO_WITH_TWO_DICE: \"Écart de 0% à 200% (2 jets)\"\n  DRT_EASY: \"Écart de 50% à 200%\"\n  DRT_STANDARD: \"Plage de dégâts standard\"\n  DRT_EXPLOSION: \"Plage de dégâts d'explosion\"\n#\n  BFT_NONE: \"aucun\"\n  BFT_INSTANT: \"instantané\"\n  BFT_SET: \"Réglé manuellement\"\n  BFT_FIXED: \"fixé\"\n#\n  BMT_NORMAL: \"standard (multi-usage)\"\n  BMT_HEAL: \"soin\"\n  BMT_STIMULANT: \"stimulant\"\n  BMT_PAINKILLER: \"analgésique\"\n#\n  ETM_DEFAULT: \"par défaut\"\n  ETM_MELEE_100: \"MÊLÉE\"\n  ETM_MELEE_50: \"MÊLÉE (50% de chance)\"\n  ETM_MELEE_33: \"MÊLÉE (33% de chance)\"\n  ETM_FIRING_100: \"TIR\"\n  ETM_FIRING_50: \"TIR (50% de chance)\"\n  ETM_FIRING_33: \"LANCER (33% de chance)\"\n  ETM_THROWING_100: \"LANCER\"\n  ETM_THROWING_50: \"LANCER (50% de chance)\"\n  ETM_THROWING_33: \"LANCER (33% de chance)\"\n  ETM_FIRING_AND_THROWING: \"TIR et LANCER\"\n  ETM_FIRING_OR_THROWING: \"TIR ou LANCER\"\n  ETM_REACTIONS: \"RÉACTIONS\"\n  ETM_REACTIONS_AND_MELEE: \"RÉACTIONS et MÊLÉE\"\n  ETM_REACTIONS_AND_FIRING: \"RÉACTIONS et TIR\"\n  ETM_REACTIONS_AND_THROWING: \"RÉACTIONS et LANCER\"\n  ETM_REACTIONS_OR_MELEE: \"RÉACTIONS ou MÊLÉE\"\n  ETM_REACTIONS_OR_FIRING: \"RÉACTIONS ou TIR\"\n  ETM_REACTIONS_OR_THROWING: \"RÉACTIONS ou LANCER\"\n  ETM_BRAVERY: \"COURAGE\"\n  ETM_BRAVERY_2X: \"COURAGE (x2)\"\n  ETM_BRAVERY_AND_REACTIONS: \"COURAGE et RÉACTIONS\"\n  ETM_BRAVERY_OR_REACTIONS: \"COURAGE ou RÉACTIONS\"\n  ETM_BRAVERY_OR_REACTIONS_2X: \"COURAGE ou RÉACTIONS (x2)\"\n  ETM_PSI_STRENGTH: \"FORCE PSI\"\n  ETM_PSI_STRENGTH_2X: \"FORCE PSI (x2)\"\n  ETM_PSI_SKILL: \"TALENT PSI\"\n  ETM_PSI_SKILL_2X: \"TALENT PSI (x2)\"\n  ETM_PSI_STRENGTH_AND_SKILL: \"FORCE PSI et TALENT PSI\"\n  ETM_PSI_STRENGTH_AND_SKILL_2X: \"FORCE PSI et TALENT PSI (x2)\"\n  ETM_PSI_STRENGTH_OR_SKILL: \"FORCE PSI ou TALENT PSI\"\n  ETM_PSI_STRENGTH_OR_SKILL_2X: \"FORCE PSI ou TALENT PSI (x2)\"\n  ETM_NOTHING: \"pas d'entraînement\"\n#\n  battleType: \"Type d'objet\"\n  experienceTrainingMode: \"Mode d'expérience\"\n  manaExperience: \"Expérience de mana\"\n  arcingShot: \"Arc ?\"\n  isFireExtinguisher: \"Extincteur d'incendie ?\"\n  explodeInventory: \"Explose dans l'inventaire ?\"\n  waypoints: \"Points de passage max\"\n  sprayWaypoints: \"Point de passage d'aspertion\"\n#\n  shotgunPellets: \"Nombre de balles\"\n  shotgunBehavior: \"Comportement du fusil à pompe\"\n  shotgunSpread: \"Dispersion du fusil à pompe\"\n  shotgunChoke: \"Étranglement du shotgun\"\n#\n  underwaterOnly: \"Uniquement sous l'eau ?\"\n  landOnly: \"Uniquement sur terre ?\"\n  psiRequired: \"Compétence psionique nécessaire ?\"\n  targetMatrix: \"Cibles\"\n  convertToCivilian: \"Convertir en civil ?\"\n  manaRequired: \"Mana nécessaire ?\"\n  LOSRequired: \"Visibilité nécessaire ?\"\n#\n  noLOSAccuracyPenalty: \"Multiplicateur de pénalité sans visibilité\"\n  kneelBonus: \"Bonus multiplicateur en position accroupie\"\n  twoHanded: \"À deux mains ?\"\n  blockBothHands: \"Occupe les deux mains ?\"\n  oneHandedPenalty: \"Pénalité d'utilisation à une main\"\n#\n  minRange: \"Portée minimale\"\n  maxRange: \"Portée maximale\"\n  aimRange: \"Portée de tir précis\"\n  autoRange: \"Portée de tir automatique\"\n  snapRange: \"Portée de tir rapide\"\n  dropoff: \"Perte de précision par case\"\n#\n  accuracyMultiplier: \"Multiplicateur de précision de tir\"\n  accuracyAimed: \"Précision de tir précis\"\n  accuracyAuto: \"Précision de tir automatique\"\n  accuracySnap: \"Précision de tir rapide\"\n  costAimed: \"Coût du tir précis\"\n  costAuto: \"Coût du tir automatique\"\n  costSnap: \"Coût du tir rapide\"\n#\n  meleeMultiplier: \"Multiplicateur de précision en mêlée\"\n  accuracyMelee: \"Précision en mêlée\"\n  costMelee: \"Coût d'une action de mêlée\"\n#\n  psiAttackName: \"Nom de l'attaque psionique\"\n  accuracyUse: \"Précision de l'action\"\n  accuracyMindControl: \"Précision du contrôle mental\"\n  accuracyPanic: \"Précision de la panique\"\n  costUse: \"Coût de l'action\"\n  costMindcontrol: \"Coût du contrôle mental\"\n  costPanic: \"Coût de la panique\"\n#\n  weight: \"Poids\"\n  throwRange: \"\"\n  underwaterThrowRange: \"\"\n  throwDropoffRange: \"\"\n  underwaterThrowDropoffRange: \"\"\n  throwDropoff: \"\"\n  throwMultiplier: \"Multiplicateur de précision au lancer\"\n  accuracyThrow: \"Précision au lancer\"\n  costThrow: \"Coût du lancer\"\n  costPrime: \"Coût d'amorçage\"\n  costUnprime: \"Coût de désamorçage\"\n#\n  closeQuartersMultiplier: \"Multiplicateur de précision CQC\"\n  accuracyCloseQuarters: \"Précision CQC\"\n#\n  damageType: \"Type de dégâts\"\n  power: \"Puissance\"\n  powerRangeReduction: \"Réduction de puissance par case\"\n  powerRangeThreshold: \"Seuil de réd. de puissance\"\n  damageBonus: \"Bonus de dégâts\"\n  blastRadius: \"Rayon de l'explosion\"\n  damageAlter: \"Informations supplémentaires sur les dégâts :\"\n  meleeType: \"Type de dégâts en mêlée\"\n  meleePower: \"Puissance en mêlée\"\n  meleeBonus: \"Bonus de puissance en mêlée\"\n  meleeAlter: \"Informations supplémentaires en mêlée :\"\n  FixRadius: \"Rayon de l'explosion\"\n  RandomType: \"Type de calcul\"\n  FireBlastCalc: \"Effets de feu de la version d'origine ?\"\n  IgnoreDirection: \"Ignorer la direction\"\n  IgnoreSelfDestruct: \"Ignorer l'auto-destruction\"\n  IgnorePainImmunity: \"Ignorer l'immunité à l'étourdissement\"\n  IgnoreNormalMoraleLose: \"Ign. la perte de moral de la version d'origine\"\n  IgnoreOverKill: \"Ignorer l'excès de dégâts\"\n  ArmorEffectiveness: \"Efficacité de l'armure\"\n  RadiusEffectiveness: \"Efficacité du rayon\"\n  RadiusReduction: \"Réduction des dégâts en fonction du rayon\"\n  FireThreshold: \"Seuil de mise à feu\"\n  SmokeThreshold: \"Seuil de création de fumée\"\n#\n  ToArmorPre: \"Multiplicateur de pré-dégâts de l'armure\"\n  RandomArmorPre: \"Pré-dégâts à l'armure aléatoires ?\"\n  ToArmor: \"Multiplicateur de dégâts d'armure\"\n  RandomArmor: \"Dégâts à l'armure aléatoires ?\"\n  ToHealth: \"Multiplicateur de dégâts aux PV\"\n  RandomHealth: \"Dégâts aux PV aléatoires ?\"\n  ToStun: \"Multiplicateur de dégâts d'étourdissement\"\n  RandomStun: \"Dégâts d'étourdissement aléatoires ?\"\n  ToWound: \"Multiplicateur du nombre de blessures\"\n  RandomWound: \"Blessures de la version d'origine aléatoires ?\"\n  ToTime: \"Multiplicateur de dégâts aux UT\"\n  RandomTime: \"Dégâts aux UT aléatoires ?\"\n  ToEnergy: \"Multiplicateur de dégâts à l'endurance\"\n  RandomEnergy: \"Dégâts à l'Énergie aléatoires ?\"\n  ToMorale: \"Multiplicateur de dégâts au moral\"\n  RandomMorale: \"Dégâts au moral aléatoires ?\"\n  ToItem: \"Multiplicateur de dégâts aux objets\"\n  RandomItem: \"Dégâts aux objets aléatoires ?\"\n  ToMana: \"Multiplicateur de dégâts à la mana\"\n  RandomMana: \"Dégâts à la mana aléatoires ?\"\n  ToTile: \"Multiplicateur de dégâts au terrain\"\n  RandomTile: \"Dégâts au terrain aléatoires ?\"\n  TileDamageMethod: \"Méthode de dégâts par case\"\n  TileDamageLimit: \"\"\n#\n  confAimed: \"Action Précis :\"\n  confAuto: \"Action Auto :\"\n  confSnap: \"Action Rapide :\"\n  confMelee: \"Action Mêlée :\"\n  shots: \"Tirs par action\"\n  spendPerShot: \"Dépensé par tir :\"\n  followProjectiles: \"Suivre les projectiles ?\"\n  name: \"Nom\"\n  shortName: \"Nom court\"\n  ammoSlot: \"Emplacement de munitions utilisé\"\n  ammoZombieUnitChanceOverride: \"Chance de zombification\"\n  ammoSpawnUnitChanceOverride: \"Chance d'apparition de l'unité\"\n  ammoSpawnItemChanceOverride: \"Chance d'apparition de l'objet\"\n  arcing: \"Courbe?\"\n#\n  clipSize: \"Taille du chargeur\"\n  isAmmoRechargeable: \"\"\n#\n  primaryAmmo: \"Emplacement principal de munitions :\"\n  compatibleAmmo: \"Munitions compatibles\"\n  tuLoad: \"Coût de chargement\"\n  tuUnload: \"Coût de déchargement\"\n  ammo[1]: \"Emplacement supplémentaire de munitions #1 :\"\n  ammo[2]: \"Emplacement supplémentaire de munitions #2 :\"\n  ammo[3]: \"Emplacement supplémentaire de munitions #3 :\"\n#\n  armor: \"Armure\"\n#\n  medikitType: \"Type de medikit\"\n  painKillerActionName: \"\"\n  stimulantActionName: \"\"\n  healActionName: \"\"\n  medikitActionName: \"Nom de l'action du medikit\"\n  medikitTargetSelf: \"Medikit sur soi ?\"\n  medikitTargetImmune: \"Medikit sur une cible immunisée contre les saignements ?\"\n  medikitTargetMatrix: \"Cibles du medikit\"\n  isConsumable: \"Consommable ?\"\n  painKiller: \"Utilisations des analgésiques\"\n  heal: \"Utilisation des soins\"\n  stimulant: \"Utilisations des stimulants\"\n  woundRecovery: \"Soin de blessure\"\n  healthRecovery: \"Récupération de santé\"\n  stunRecovery: \"Récupération d'étourdissement\"\n  energyRecovery: \"Récupération d'énergie\"\n  manaRecovery: \"Récupération de mana\"\n  moraleRecovery: \"Récupération de moral\"\n  painKillerRecovery: \"Force des analgésiques\"\n#\n  requires: \"Technologie requise\"\n  requiresBuy: \"Technologie requise pour acheter\"\n  requiresBuyBaseFunc: \"Services requis pour acheter\"\n  requiresBuyCountry: \"Pays allié requis\"\n  requiresAward: \"\"\n  requiresBonus: \"Bonus requis\"\n  categories: \"Catégories\"\n  supportedInventorySections: \"Emplacements d'inventaire\"\n#\n  size: \"Taille\"\n  costBuy: \"Coût d'achat\"\n  monthlyBuyLimit: \"Limite d'achat mensuel\"\n  costSell: \"Valeur de vente\"\n  transferTime: \"Heures de transfert\"\n  monthlySalary: \"Salaire/mois\"\n  monthlyMaintenance: \"Maintenance/mois\"\n#\n  SPECAB_NONE: \"Aucun\"\n  SPECAB_EXPLODEONDEATH: \"Exploser en mourant\"\n  SPECAB_BURNFLOOR: \"Brûler le sol\"\n  SPECAB_BURN_AND_EXPLODE: \"Brûler le sol et exploser en mourant\"\n#\n  MT_WALK: \"Marcher\"\n  MT_FLY: \"Voler\"\n  MT_SLIDE: \"Glisser\"\n  MT_FLOAT: \"Flotter\"\n  MT_SINK: \"Couler\"\n#\n  TORSO_USE_GENDER: \"Utiliser le genre\"\n  TORSO_ALWAYS_MALE: \"Toujours masculin\"\n  TORSO_ALWAYS_FEMALE: \"Toujours féminin\"\n#\n  DRAWING_ROUTINE_SOLDIER_SECTOID: \"Soldat, Sectoïde\"\n  DRAWING_ROUTINE_FLOATER: \"Planeur\"\n  DRAWING_ROUTINE_HWP: \"Plate-forme d'Armement Lourd\"\n  DRAWING_ROUTINE_CYBERDISC: \"Cyberdisque\"\n  DRAWING_ROUTINE_CIVILIAN_ETHEREAL: \"Civil, Éthéré\"\n  DRAWING_ROUTINE_SECTOPOD_REAPER: \"Sectopode, Faucheur\"\n  DRAWING_ROUTINE_SNAKEMAN: \"Homme-Serpent\"\n  DRAWING_ROUTINE_CHRYSSALID: \"Chryssalide\"\n  DRAWING_ROUTINE_SILACOID: \"Silacoîde\"\n  DRAWING_ROUTINE_CELATID: \"Célatide\"\n  DRAWING_ROUTINE_MUTON: \"Muton\"\n  DRAWING_ROUTINE_SWS: \"Systèmes d'Armement Submersibles\"\n  DRAWING_ROUTINE_HALLUCINOID: \"Hallucinoïde\"\n  DRAWING_ROUTINE_AQUANAUTS: \"Aquanautes\"\n  DRAWING_ROUTINE_CALCINITE_AND_MORE: \"Calcinite, Profond, Homme-Poisson, Homme-Homard, Tasoth\"\n  DRAWING_ROUTINE_AQUATOID: \"Aquatoïde\"\n  DRAWING_ROUTINE_BIO_DRONE: \"Bio-Drone\"\n  DRAWING_ROUTINE_TFTD_CIVILIAN_A: \"Civils TFTD type A et Zombie TFTD\"\n  DRAWING_ROUTINE_TFTD_CIVILIAN_B: \"Civils TFTD type B\"\n  DRAWING_ROUTINE_TENTACULAT: \"Tentaculaire\"\n  DRAWING_ROUTINE_TRISCENE: \"Triscène\"\n  DRAWING_ROUTINE_XARQUID: \"Xarquide\"\n  DRAWING_ROUTINE_INVERTED_CYBERDISC: \"Cyberdisc inversé (animation de propulsion en haut)\"\n#\n  stats: \"Modificateurs de statistiques\"\n  specab: \"Habilité spéciale\"\n  movementType: \"Type de mouvement\"\n  allowsRunning: \"Autoriser la course ?\"\n  allowsStrafing: \"Autoriser le déplacement latéral ?\"\n  allowsSneaking: \"Autoriser la furtivité ?\"\n  allowsKneeling: \"Autoriser l'accroupissement ?\"\n  allowsMoving: \"Autoriser le déplacement ?\"\n  fearImmune: \"Immunisé à la perte de moral ?\"\n  bleedImmune: \"Immunisé au saignement ?\"\n  painImmune: \"Immunisé à l'étourdissement ?\"\n  zombiImmune: \"Immunisé à la zombification ?\"\n  ignoresMeleeThreat: \"Ignore le combat rapproché ?\"\n  createsMeleeThreat: \"Génère du combat rapproché ?\"\n  builtInWeapons: \"Objets intégrés\"\n  specialWeapon: \"Arme spéciale\"\n  heatVision: \"Visibilité à travers la fumée\"\n  visibilityThroughFire: \"Visibilité à travers le feu\"\n  psiVision: \"Sens psionique\"\n  psiCamouflage: \"Camouflage psionique\"\n  visibilityAtDay: \"Visibilité diurne\"\n  visibilityAtDark: \"Visibilité nocturne\"\n  camouflageAtDay: \"Camouflage de jour\"\n  camouflageAtDark: \"Camouflage de nuit\"\n  antiCamouflageAtDay: \"Anticamouflage de jour\"\n  antiCamouflageAtDark: \"Anticamouflage de nuit\"\n  psiDefence: \"Défense psionique\"\n  meleeDodge: \"Esquive en mêlée\"\n  meleeDodgeBackPenalty: \"Pénalité d'esquive en mêlée\"\n  recovery: \"Régénération par tour :\"\n  time: \"Temps\"\n  energy: \"Énergie\"\n  morale: \"Moral\"\n  health: \"Santé\"\n  stun: \"Étourdissement\"\n  mana: \"Mana\"\n  units: \"Unités compatibles\"\n  ranks: \"\"\n  frontArmor: \"Armure avant\"\n  sideArmor: \"Armure de côté\"\n  leftArmorDiff: \"Diff armure gauche\"\n  rearArmor: \"Armure arrière\"\n  underArmor: \"Armure de dessous\"\n#\n  sizeX: \"Taille X\"\n  sizeY: \"Taille Y\"\n  buildCost: \"Coût de construction\"\n  buildCostItems: \"Matériaux de construction :\"\n  buildTime: \"Durée de construction\"\n  monthlyCost: \"Coût mensuel\"\n  refundValue: \"Valeur de vente\"\n  requiresBaseFunc: \"Nécessite des services\"\n  provideBaseFunc: \"Procure des services\"\n  forbiddenBaseFunc: \"Interdit des services\"\n  lift: \"Ascenseur d'accès ?\"\n  hyper: \"Décodeur d'hyper-ondes ?\"\n  mind: \"Bouclier psychique ?\"\n  mindPower: \"Puissance du bouclier psychique\"\n  grav: \"Bouclier gravitationnel ?\"\n  storage: \"Espace de stockage\"\n  personnel: \"Espace de vie\"\n  aliens: \"Espace de confinement\"\n  crafts: \"Espace de hangar\"\n  labs: \"Espace de laboratoire\"\n  workshops: \"Espace d'atelier\"\n  psiLabs: \"Espace de laboratoire psionique\"\n  trainingRooms: \"Espace de salle de sport\"\n  sightRange: \"Portée de visibilité\"\n  sightChance: \"Chance de visibilité\"\n  radarRange: \"Portée de radar\"\n  radarChance: \"Chance de détection radar\"\n  defense: \"Valeur de défense\"\n  hitRatio: \"Chance de toucher\"\n  ammoNeeded: \"Munitions requises\"\n  unifiedDamageFormula: \"\"\n  ammoItem: \"Munitions\"\n  maxAllowedPerBase: \"Maximum autorisé par base\"\n  manaRecoveryPerDay: \"Mana par jour\"\n  healthRecoveryPerDay: \"Santé par jour\"\n  sickBayAbsoluteBonus: \"Bonus abs. de l'infirmerie\"\n  sickBayRelativeBonus: \"Bonus rel. de l'infirmerie\"\n  prisonType: \"Type de confinement\"\n  rightClickActionType: \"Action clic-droit\"\n  leavesBehindOnSell: \"Laisse derrière soi lors de la vente\"\n  removalTime: \"Temps de retrait\"\n  canBeBuiltOver: \"Peut être construit par-dessus ?\"\n  upgradeOnly: \"\"\n  buildOverFacilities: \"Installations constructibles par-dessus\"\n#\n  BFRCT_DEFAULT: \"Paramètres par défaut de la version d'origine\"\n  BFRCT_PRISON: \"Aller à la Confinement Extraterrestre\"\n  BFRCT_ENGINEERING: \"Aller à Production\"\n  BFRCT_RESEARCH: \"Aller à Recherche\"\n  BFRCT_GYM: \"Aller à Entraînement Martial\"\n  BFRCT_PSI_LABS: \"Aller à Laboratoire Psionique\"\n  BFRCT_BARRACKS: \"Aller à Baraquements\"\n  BFRCT_GREY_MARKET: \"Aller à Marché Noir\"\n  BFRCT_GEOSCAPE: \"Aller à Géoscape\"\n#\n  costRent: \"Coût de location\"\n  soldiers: \"Espace soute\"\n  maxUnitsLimit: \"Expace soute maximal\"\n  pilots: \"Taille du cockpit\"\n  pilotMinStatsRequired: \"\"\n  pilotSoldierBonusesRequired: \"\"\n  vehicles: \"Capacité PAL\"\n  onlyOneSoldierGroupAllowed: \"Un seul groupe de soldats autorisé ?\"\n  allowedSoldierGroups: \"Groupes de soldats autorisés\"\n  allowedArmorGroups: \"\"\n  limitArmorGroups: \"\"\n  maxHWPUnitsLimit: \"Capacité PAL Max\"\n  maxSmallSoldiers: \"Nombre max de petits soldats\"\n  maxLargeSoldiers: \"Nombre max de grands soldats\"\n  maxSmallVehicles: \"Nombre max de petits véhicules\"\n  maxLargeVehicles: \"Nombre max de grands véhicules\"\n  maxSmallUnits: \"Nombre max de petites unités\"\n  maxLargeUnits: \"Nombre max de grandes unités\"\n  maxSoldiers: \"Nombre max de soldats\"\n  maxVehicles: \"Nombre max de véhicules\"\n  maxItems: \"Limite d'équipement\"\n  maxStorageSpace: \"Espace de stockage\"\n  maxAltitude: \"Limite d'altitude des combats aériens\"\n  weapons: \"Nacelles d'armes\"\n  weaponStrings: \"Noms des armes\"\n  fixedWeapons: \"Armes fixes\"\n  weaponTypes: \"Types d'armes autorisés\"\n  damageMax: \"Capacité de dégâts\"\n  avoidBonus: \"Bonus d'esquive (flat)\"\n  avoidBonus2: \"\"\n  powerBonus: \"Bonus de puissance (flat)\"\n  hitBonus: \"Bonus de toucher (flat)\"\n  fuelMax: \"Capacité de carburant\"\n  speedMax: \"Vitesse maxi\"\n  accel: \"Accélération\"\n  shieldCapacity: \"Capacité du bouclier\"\n  shieldRecharge: \"Recharge du bouclier (Combat)\"\n  shieldRechargeInGeoscape: \"Recharge du bouclier (Globe)\"\n  shieldBleedThrough: \"Pénétration du bouclier\"\n  shieldRechargedAtBase: \"Recharge du bouclier (Base)\"\n  refuelItem: \"Carburant de ravitaillement\"\n  refuelRate: \"Taux de ravitaillement\"\n  repairRate: \"Taux de réparation\"\n  spacecraft: \"Vaisseau final ?\"\n  allowLanding: \"Autoriser l'atterrissage ?\"\n  notifyWhenRefueled: \"Signaler la fin du ravitaillement ?\"\n  autoPatrol: \"Patrouille auto ?\"\n  undetectable: \"Furtif ?\"\n  patrolWithoutFuel: \"\"\n  keepCraftAfterFailedMission: \"Troupes aéroportées ?\"\n  _calculatedValues: \"Valeurs calculées\"\n  _maxRange: \"Portée maximale\"\n  _minRange: \"Portée minimale\"\n  _avgRange: \"Portée moyenne\"\n#\n  hunterKillerPercentage: \"Chance de chasseur-tueur\"\n  huntMode: \"Mode chasseur\"\n  huntSpeed: \"Vitesse de chasse\"\n  huntBehavior: \"Comportement de chasse\"\n  range: \"Portée\"\n  reload: \"Temps de rechargement\"\n  breakOffTime: \"Temps de séparation\"\n  score: \"Score\"\n  missionScore: \"Score de mission\"\n  craftCustomDeploy: \"Déploiement du site OVNI\"\n  missionCustomDeploy: \"Déploiement du site de mission\"\n  _escapeCountdown: \"Compte à rebours pour l'évasion\"\n  _fireRate: \"Cadence de tir\"\n  _averageDPM: \"DPM moyen\"\n#\n  HM_INTERCEPTORS: \"préférer chasser les intercepteurs\"\n  HM_TRANSPORTS: \"préférer chasser les transports\"\n  HM_RANDOM: \"aléatoire\"\n#\n  HB_FLEE: \"fuir si en train de perdre\"\n  HB_KAMIKAZE: \"combattre jusqu'à la destruction\"\n  HB_RANDOM: \"aléatoire\"\n#\n  tractorBeamPower: \"Puissance du rayon tracteur\"\n  damage: \"Dégâts\"\n  shieldDamageModifier: \"Modificateur de dégâts au bouclier\"\n  accuracy: \"Précision\"\n  reloadCautious: \"Rechargement (Prudent)\"\n  reloadStandard: \"Rechargement (Standard)\"\n  reloadAggressive: \"Rechargement (Agressif)\"\n  launcher: \"Lanceur\"\n  weaponType: \"Type d'arme\"\n  clip: \"Chargeur\"\n  ammoMax: \"Munitions\"\n  rearmRate: \"Taux de réarmement\"\n  bulletSaving: \"Économie de balles ?\"\n  _damageRange: \"\"\n  _damageRangeBasic: \"\"\n  _averageTotalDamage: \"Dégâts totaux moyens\"\n#\n  allowPiloting: \"\"\n  costSalary: \"\"\n  costSalarySquaddie: \"\"\n  costSalarySergeant: \"\"\n  costSalaryCaptain: \"\"\n  costSalaryColonel: \"\"\n  costSalaryCommander: \"\"\n#\n  race: \"\"\n  rank: \"\"\n  livingWeapon: \"\"\n  meleeWeapon: \"Arme de mêlée\"\n  psiWeapon: \"\"\n  _builtInWeaponSets: \"\"\n  _weightedBuiltInWeaponSets: \"\"\n  spawnUnit: \"\"\n  _capturable: \"\"\n  capturable: \"\"\n  canSurrender: \"\"\n  autoSurrender: \"\"\n  spotter: \"\"\n  sniper: \"\"\n"
  },
  {
    "path": "bin/common/Language/Technical/hu.yml",
    "content": "hu:\n#=================== Menu ===================\n#TestState.cpp\n  STR_BAD_NODES: \"Rossz pontok az RMP fájlokban\"\n  STR_BAD_NODES_DESC: \"Ellenőrzi az RMP fájlokat pályahatáron kívüli pontokért.{NEWLINE}Ezek NEM okoznak összeomlást, de a játék nem fogja érzékelni őket.\"\n#\n  STR_MCD_CHECK: \"MCD ellenőrzés\"\n  STR_MCD_CHECK_DESC: \"\"\n#\n  STR_PALETTE_CHECK: \"Színpaletta egyezés\"\n  STR_PALETTE_CHECK_DESC: \"Megpróbálja egyeztetni a modolt és az eredeti színpalettát és jelent minden képet ami nem egyezik 100% -osan.\"\n#\n  STR_SCRIPT_TAGS: \"Script tag exportálása\"\n  STR_SCRIPT_TAGS_DESC: \"Script tagek exportálása CSV formátumban.\"\n#\n  STR_MAP_RESOURCES: \"Térképerőforrások ellenőrzése\"\n  STR_MAP_RESOURCES_DESC: \"Hiányzó és használaton kívüli térképpel kapcsolatos fájlokat és szabálygyűjteményeket keres.\"\n#\n  STR_CHECKING_TERRAIN: \"Terep ellenőrzése...\"\n  STR_CHECKING_UFOS: \"UFO-k ellenőrzése...\"\n  STR_CHECKING_CRAFT: \"Gépek ellenőrzése...\"\n#\n  BACKPALS.DAT: \"BACKPALS.DAT\"\n  PAL_GEOSCAPE: \"PAL_GEOSCAPE\"\n  PAL_BASESCAPE: \"PAL_BASESCAPE\"\n  PAL_GRAPHS: \"PAL_GRAPHS\"\n  PAL_UFOPAEDIA: \"PAL_UFOPAEDIA\"\n  PAL_BATTLEPEDIA: \"PAL_BATTLEPEDIA\"\n  PAL_BATTLESCAPE: \"PAL_BATTLESCAPE\"\n  PAL_BATTLESCAPE_1: \"PAL_BATTLESCAPE_1\"\n  PAL_BATTLESCAPE_2: \"PAL_BATTLESCAPE_2\"\n  PAL_BATTLESCAPE_3: \"PAL_BATTLESCAPE_3\"\n#=================== Ufopaedia ===================\n#StatsForNerdsState.cpp\n  BT_NONE: \"Semmi\"\n  BT_FIREARM: \"Lőfegyver\"\n  BT_AMMO: \"Lőszer\"\n  BT_MELEE: \"Közelfegyver\"\n  BT_GRENADE: \"Gránát\"\n  BT_PROXIMITYGRENADE: \"Mozgásérzékelő Gránát\"\n  BT_MEDIKIT: \"Elsősegélycsomag\"\n  BT_SCANNER: \"Mozgásérzékelő\"\n  BT_MINDPROBE: \"Elmeszonda\"\n  BT_PSIAMP: \"Pszi Erősítő\"\n  BT_FLARE: \"Fényforrás\"\n  BT_CORPSE: \"Tetem/Test\"\n#\n  DRT_DEFAULT: \"vanilla alapérték\"\n  DRT_UFO: \"0-200% -os szórás\"\n  DRT_TFTD: \"50-150% -os szórás\"\n  DRT_FLAT: \"sima sebzés\"\n  DRT_FIRE: \"spec. lősebzés\"\n  DRT_NONE: \"nincs sebzés\"\n  DRT_UFO_WITH_TWO_DICE: \"0-200% -os szórás (2-kockával)\"\n  DRT_EASY: \"50-200% -os szórás\"\n  DRT_STANDARD: \"normál sebzési tartomány\"\n  DRT_EXPLOSION: \"robbanás sebzési tartomány\"\n#\n  BFT_NONE: \"semmi\"\n  BFT_INSTANT: \"instant\"\n  BFT_SET: \"manuállisan beállított\"\n  BFT_FIXED: \"fixált\"\n#\n  BMT_NORMAL: \"alapvető (többcélú)\"\n  BMT_HEAL: \"gyógyítás\"\n  BMT_STIMULANT: \"stimulálás\"\n  BMT_PAINKILLER: \"fájdalomcsillapító\"\n#\n  ETM_DEFAULT: \"alapérték\"\n  ETM_MELEE_100: \"KÖZELHARC\"\n  ETM_MELEE_50: \"KÖZELHARC (50% esély)\"\n  ETM_MELEE_33: \"KÖZELHARC (33% esély)\"\n  ETM_FIRING_100: \"LÖVÉS\"\n  ETM_FIRING_50: \"LÖVÉS (50% esély)\"\n  ETM_FIRING_33: \"LÖVÉS (33% esély)\"\n  ETM_THROWING_100: \"DOBÁS\"\n  ETM_THROWING_50: \"DOBÁS (50% esély)\"\n  ETM_THROWING_33: \"DOBÁS (33% esély)\"\n  ETM_FIRING_AND_THROWING: \"LÖVÉS és DOBÁS\"\n  ETM_FIRING_OR_THROWING: \"LÖVÉS vagy DOBÁS\"\n  ETM_REACTIONS: \"REAKCIÓK\"\n  ETM_REACTIONS_AND_MELEE: \"REAKCIÓK és KÖZELHARC\"\n  ETM_REACTIONS_AND_FIRING: \"REAKCIÓK és LÖVÉS\"\n  ETM_REACTIONS_AND_THROWING: \"REAKCIÓK és DOBÁS\"\n  ETM_REACTIONS_OR_MELEE: \"REAKCIÓK vagy KÖZELHARC\"\n  ETM_REACTIONS_OR_FIRING: \"REAKCIÓK vagy LÖVÉS\"\n  ETM_REACTIONS_OR_THROWING: \"REAKCIÓK vagy DOBÁS\"\n  ETM_BRAVERY: \"BÁTORSÁG\"\n  ETM_BRAVERY_2X: \"BÁTORSÁG (x2)\"\n  ETM_BRAVERY_AND_REACTIONS: \"BÁTORSÁG és REAKCIÓK\"\n  ETM_BRAVERY_OR_REACTIONS: \"BÁTORSÁG vagy REAKCIÓK\"\n  ETM_BRAVERY_OR_REACTIONS_2X: \"BÁTORSÁG vagy REAKCIÓK (x2)\"\n  ETM_PSI_STRENGTH: \"PSZI ERŐ\"\n  ETM_PSI_STRENGTH_2X: \"PSZI ERŐ (x2)\"\n  ETM_PSI_SKILL: \"PSZI ÜGYESSÉG\"\n  ETM_PSI_SKILL_2X: \"PSZI ÜGYESSÉG (X2)\"\n  ETM_PSI_STRENGTH_AND_SKILL: \"PSZI ERŐ és PSZI ÜGYESSÉG\"\n  ETM_PSI_STRENGTH_AND_SKILL_2X: \"PSZI ERŐ és PSZI ÜGYESSÉG (x2)\"\n  ETM_PSI_STRENGTH_OR_SKILL: \"PSZI ERŐ vagy PSZI ÜGYESSÉG\"\n  ETM_PSI_STRENGTH_OR_SKILL_2X: \"PSZI ERŐ vagy PSZI ÜGYESSÉG (x2)\"\n  ETM_NOTHING: \"semmi\"\n#\n  battleType: \"Tárgy típusa\"\n  experienceTrainingMode: \"Tapasztalatszerzés\"\n  manaExperience: \"Mana tapasztalat\"\n  arcingShot: \"Ívelt?\"\n  isFireExtinguisher: \"Tüzet olt?\"\n  explodeInventory: \"Felszerelések között felrobban?\"\n  waypoints: \"Max útpontok\"\n  sprayWaypoints: \"Max célpontok\"\n#\n  shotgunPellets: \"Lövedékek száma\"\n  shotgunBehavior: \"Shotgunszerű viselkedés\"\n  shotgunSpread: \"Shotgun szórás\"\n  shotgunChoke: \"Shotgun folytás\"\n#\n  underwaterOnly: \"Csak víz alatti?\"\n  landOnly: \"Csak szárazföldi?\"\n  psiRequired: \"Pszi ügyesség szükséges?\"\n  targetMatrix: \"\"\n  convertToCivilian: \"\"\n  manaRequired: \"Mana szükséges?\"\n  LOSRequired: \"Tűzvonal szükséges?\"\n#\n  noLOSAccuracyPenalty: \"Nincs LoS célzásromlás\"\n  kneelBonus: \"Térdelési célzásszorzó\"\n  twoHanded: \"Két kezes?\"\n  blockBothHands: \"Mindkét kezet foglalja?\"\n  oneHandedPenalty: \"Egykezes célzásromlás\"\n#\n  minRange: \"Min. hatótáv\"\n  maxRange: \"Max. hatótáv\"\n  aimRange: \"Célzott lövés hatótáv\"\n  autoRange: \"Auto hatótáv\"\n  snapRange: \"Kapás lövés hatótáv\"\n  dropoff: \"Célzásromlás/Mező\"\n#\n  accuracyMultiplier: \"Célzási szorzó\"\n  accuracyAimed: \"Célzott lövés pontosság\"\n  accuracyAuto: \"Auto pontosság\"\n  accuracySnap: \"Kapás lövés pontosság\"\n  costAimed: \"Célzott lövés költsége\"\n  costAuto: \"Auto költsége\"\n  costSnap: \"Kapás lövés költsége\"\n#\n  meleeMultiplier: \"Közelharci pts. szorzó\"\n  accuracyMelee: \"Közelharci pontosság\"\n  costMelee: \"Közelharc költsége\"\n#\n  psiAttackName: \"Pszi támadás neve\"\n  accuracyUse: \"Akció pontossága\"\n  accuracyMindControl: \"Elmeirányítás pontosság\"\n  accuracyPanic: \"Pánik pontosság\"\n  costUse: \"Akció költsége\"\n  costMindcontrol: \"Elmeirányítás költsége\"\n  costPanic: \"Pánik költsége\"\n#\n  weight: \"Súly\"\n  throwRange: \"\"\n  underwaterThrowRange: \"\"\n  throwDropoffRange: \"\"\n  underwaterThrowDropoffRange: \"\"\n  throwDropoff: \"\"\n  throwMultiplier: \"Dobási pts. szorzó\"\n  accuracyThrow: \"Dobási pontosság\"\n  costThrow: \"Dobás költsége\"\n  costPrime: \"Időzítés költsége\"\n  costUnprime: \"Hatástalanítás költsége\"\n#\n  closeQuartersMultiplier: \"Közvetlen lövéspts. szorzó\"\n  accuracyCloseQuarters: \"Közvetlen lövéspontosság\"\n#\n  damageType: \"Sebzés fajtája\"\n  power: \"Erő\"\n  powerRangeReduction: \"Erőcsökkenés/mező\"\n  powerRangeThreshold: \"Max. erőcsökkenés\"\n  damageBonus: \"Sebzési bónusz\"\n  blastRadius: \"Robbanás hatóköre\"\n  damageAlter: \"Extra sebzés infó:\"\n  meleeType: \"Közelharci sebzés fajtája\"\n  meleePower: \"Közelharc ereje\"\n  meleeBonus: \"Közelharci erőbónusz\"\n  meleeAlter: \"Extra közelharc infó:\"\n  FixRadius: \"Robbanás hatóköre\"\n  RandomType: \"Számítás fajtája\"\n  FireBlastCalc: \"Vanilla lövési effektek?\"\n  IgnoreDirection: \"Irány nem számít\"\n  IgnoreSelfDestruct: \"Önmegsemmisítés nem számít\"\n  IgnorePainImmunity: \"Kábításimmúnitás nem számít\"\n  IgnoreNormalMoraleLose: \"Vanilla morálvesztés nem számít\"\n  IgnoreOverKill: \"Overkill nem számít\"\n  ArmorEffectiveness: \"Páncél hatásfoka\"\n  RadiusEffectiveness: \"Hatókör hatásfoka\"\n  RadiusReduction: \"Hatókör sebzéscsökkenés\"\n  FireThreshold: \"Felgyújtási határ\"\n  SmokeThreshold: \"Füstképzési határ\"\n#\n  ToArmorPre: \"Páncél elősebz. szorzó\"\n  RandomArmorPre: \"Páncél elősebz. RNG?\"\n  ToArmor: \"Páncélsebzés szorzó\"\n  RandomArmor: \"Páncélsebzés RNG?\"\n  ToHealth: \"EP sebzés szorzó\"\n  RandomHealth: \"EP sebzés RNG?\"\n  ToStun: \"Kábító sebz. szorzó\"\n  RandomStun: \"Kábító sebzés RNG?\"\n  ToWound: \"Sérülés szorzó\"\n  RandomWound: \"Vanilla sérülés RNG?\"\n  ToTime: \"IE sebzés szorzó\"\n  RandomTime: \"IE sebzés RNG?\"\n  ToEnergy: \"Energiasebz. szorzó\"\n  RandomEnergy: \"Energiasebz. RNG?\"\n  ToMorale: \"Morálsebz. szorzó\"\n  RandomMorale: \"Morálsebz. RNG?\"\n  ToItem: \"Tárgysebzés szorzó\"\n  RandomItem: \"Tárgysebzés RNG?\"\n  ToMana: \"Mana sebzés sokszorozó\"\n  RandomMana: \"Mana sebzés terjedelme?\"\n  ToTile: \"Terepsebzés szorzó\"\n  RandomTile: \"Terepsebzés RNG?\"\n  TileDamageMethod: \"Mezősebzés módja\"\n  TileDamageLimit: \"\"\n#\n  confAimed: \"Célzott akció:\"\n  confAuto: \"Auto akció:\"\n  confSnap: \"Kapás akció:\"\n  confMelee: \"Közelh. akció:\"\n  shots: \"Akciónkénti lövések\"\n  spendPerShot: \"\"\n  followProjectiles: \"\"\n  name: \"Név\"\n  shortName: \"\"\n  ammoSlot: \"Lőszertárhely\"\n  ammoZombieUnitChanceOverride: \"\"\n  ammoSpawnUnitChanceOverride: \"\"\n  ammoSpawnItemChanceOverride: \"\"\n  arcing: \"Ívelt?\"\n#\n  clipSize: \"Tár mérete\"\n  isAmmoRechargeable: \"\"\n#\n  primaryAmmo: \"Elsődleges lőszertárhely\"\n  compatibleAmmo: \"Használható lőszer\"\n  tuLoad: \"Betárazás költsége\"\n  tuUnload: \"Kitárazás költsége\"\n  ammo[1]: \"Extra lőszertárhely #1:\"\n  ammo[2]: \"Extra lőszertárhely #2:\"\n  ammo[3]: \"Extra lőszertárhely #3:\"\n#\n  armor: \"Páncél\"\n#\n  medikitType: \"Elsősegélycsomag fajtája\"\n  painKillerActionName: \"\"\n  stimulantActionName: \"\"\n  healActionName: \"\"\n  medikitActionName: \"\"\n  medikitTargetSelf: \"Medikit önmagán?\"\n  medikitTargetImmune: \"Medikit immunison?\"\n  medikitTargetMatrix: \"Medikit célpontok\"\n  isConsumable: \"Elfogyhat?\"\n  painKiller: \"Fájdalomcsillapító száma\"\n  heal: \"Gyógyítás száma\"\n  stimulant: \"Stimuláns száma\"\n  woundRecovery: \"Sérülésgyógyítás\"\n  healthRecovery: \"Egészség visszatöltés\"\n  stunRecovery: \"Kábuláscsökkentés\"\n  energyRecovery: \"Energiavisszatöltés\"\n  manaRecovery: \"Mana visszanyerés\"\n  moraleRecovery: \"Morálvisszatöltés\"\n  painKillerRecovery: \"Fájdalomcsillapító ereje\"\n#\n  requires: \"Szükséges tech\"\n  requiresBuy: \"Vételhez szükséges tech\"\n  requiresBuyBaseFunc: \"Vételhez szükséges szolgáltatások\"\n  requiresBuyCountry: \"\"\n  requiresAward: \"\"\n  requiresBonus: \"\"\n  categories: \"Kategóriák\"\n  supportedInventorySections: \"Felszerelés tárhelyek\"\n#\n  size: \"Méret\"\n  costBuy: \"Vételár\"\n  monthlyBuyLimit: \"\"\n  costSell: \"Eladási ár\"\n  transferTime: \"Órák megérkezésig\"\n  monthlySalary: \"Fizetés/hónap\"\n  monthlyMaintenance: \"Karbantartás/hónap\"\n#\n  SPECAB_NONE: \"Semmi\"\n  SPECAB_EXPLODEONDEATH: \"\"\n  SPECAB_BURNFLOOR: \"\"\n  SPECAB_BURN_AND_EXPLODE: \"\"\n#\n  MT_WALK: \"Séta\"\n  MT_FLY: \"Repülés\"\n  MT_SLIDE: \"Csúszás\"\n  MT_FLOAT: \"Lebegés -víz-\"\n  MT_SINK: \"Süllyedés\"\n#\n  TORSO_USE_GENDER: \"Nemek használata\"\n  TORSO_ALWAYS_MALE: \"Mindig férfi\"\n  TORSO_ALWAYS_FEMALE: \"Mindig nő\"\n#\n  DRAWING_ROUTINE_SOLDIER_SECTOID: \"Katona, Szektoid\"\n  DRAWING_ROUTINE_FLOATER: \"Lebegő\"\n  DRAWING_ROUTINE_HWP: \"Nehézfegyverzet Platform\"\n  DRAWING_ROUTINE_CYBERDISC: \"Kiberkorong\"\n  DRAWING_ROUTINE_CIVILIAN_ETHEREAL: \"Civil, Éteri\"\n  DRAWING_ROUTINE_SECTOPOD_REAPER: \"Szektopod, Arató\"\n  DRAWING_ROUTINE_SNAKEMAN: \"Kígyóember\"\n  DRAWING_ROUTINE_CHRYSSALID: \"Krisszalid\"\n  DRAWING_ROUTINE_SILACOID: \"Szilakoid\"\n  DRAWING_ROUTINE_CELATID: \"Kelatid\"\n  DRAWING_ROUTINE_MUTON: \"Muton\"\n  DRAWING_ROUTINE_SWS: \"Merülő Fegyverrendszer\"\n  DRAWING_ROUTINE_HALLUCINOID: \"Hallucinoid\"\n  DRAWING_ROUTINE_AQUANAUTS: \"Akvanauták\"\n  DRAWING_ROUTINE_CALCINITE_AND_MORE: \"Kalcinit, Mélységi, Kopoltyús, Rákember, Tasoth\"\n  DRAWING_ROUTINE_AQUATOID: \"Akvatoid\"\n  DRAWING_ROUTINE_BIO_DRONE: \"Biorobot\"\n  DRAWING_ROUTINE_TFTD_CIVILIAN_A: \"TFTD A-típusú civilek és TFTD zombi\"\n  DRAWING_ROUTINE_TFTD_CIVILIAN_B: \"TFTD B-típusú civilek\"\n  DRAWING_ROUTINE_TENTACULAT: \"Csápolat\"\n  DRAWING_ROUTINE_TRISCENE: \"Triscene\"\n  DRAWING_ROUTINE_XARQUID: \"Xarquid\"\n  DRAWING_ROUTINE_INVERTED_CYBERDISC: \"Fordított Kiberkorong (hajtásanimáció a tetején)\"\n#\n  stats: \"Értékmódosítók\"\n  specab: \"\"\n  movementType: \"Mozgástípus\"\n  allowsRunning: \"Futás engedélyezve?\"\n  allowsStrafing: \"Oldalazás engedélyezve?\"\n  allowsSneaking: \"\"\n  allowsKneeling: \"Térdelés engedélyezve?\"\n  allowsMoving: \"Mozgás engedélyezve?\"\n  fearImmune: \"Immunis a morálcsökkenésre?\"\n  bleedImmune: \"Immunis a vérzésre?\"\n  painImmune: \"Immunis a kábításra?\"\n  zombiImmune: \"Immunis a zombi állapotra?\"\n  ignoresMeleeThreat: \"Közelharcot ignorál?\"\n  createsMeleeThreat: \"Közelharcot okoz?\"\n  builtInWeapons: \"Beépített tárgyak\"\n  specialWeapon: \"Speciális fegyver\"\n  heatVision: \"\"\n  visibilityThroughFire: \"\"\n  psiVision: \"Pszi érzék\"\n  psiCamouflage: \"\"\n  visibilityAtDay: \"Láthatóság nappal\"\n  visibilityAtDark: \"Láthatóság éjjel\"\n  camouflageAtDay: \"Álca nappal\"\n  camouflageAtDark: \"Álca éjjel\"\n  antiCamouflageAtDay: \"Anti-álca nappal\"\n  antiCamouflageAtDark: \"Anti-álca éjjel\"\n  psiDefence: \"Pszi védelem\"\n  meleeDodge: \"Félreugrás közelharcban\"\n  meleeDodgeBackPenalty: \"Félreugrás büntetés\"\n  recovery: \"Visszanyerés körönként:\"\n  time: \"Idő\"\n  energy: \"Energia\"\n  morale: \"Morál\"\n  health: \"Egészség\"\n  stun: \"Kábultság\"\n  mana: \"Mana\"\n  units: \"Kompatibilis egységek\"\n  ranks: \"\"\n  frontArmor: \"\"\n  sideArmor: \"\"\n  leftArmorDiff: \"\"\n  rearArmor: \"\"\n  underArmor: \"\"\n#\n  sizeX: \"\"\n  sizeY: \"\"\n  buildCost: \"Építési költség\"\n  buildCostItems: \"Építőanyagok:\"\n  buildTime: \"Építési idő\"\n  monthlyCost: \"Havi költség\"\n  refundValue: \"Visszatérítés értéke\"\n  requiresBaseFunc: \"Szükséges fukciók\"\n  provideBaseFunc: \"Nyújtott fukciók\"\n  forbiddenBaseFunc: \"Tiltott fukciók\"\n  lift: \"Központi lift?\"\n  hyper: \"Hiperhullám-dekóder?\"\n  mind: \"Elmepajzs?\"\n  mindPower: \"Elmepajzs ereje\"\n  grav: \"Gravipajzs?\"\n  storage: \"Raktárméret\"\n  personnel: \"Lakótérméret\"\n  aliens: \"Börtönméret\"\n  crafts: \"Hangárméret\"\n  labs: \"Laborméret\"\n  workshops: \"Műhelyméret\"\n  psiLabs: \"Pszi-laborméret\"\n  trainingRooms: \"Kiképzőközpont mérete\"\n  sightRange: \"Látómező\"\n  sightChance: \"\"\n  radarRange: \"Radar hatótáv\"\n  radarChance: \"Radar esély\"\n  defense: \"Védelmi érték\"\n  hitRatio: \"Találati esély\"\n  ammoNeeded: \"\"\n  unifiedDamageFormula: \"\"\n  ammoItem: \"\"\n  maxAllowedPerBase: \"Bázisonkénti megengedett maximum\"\n  manaRecoveryPerDay: \"Mana naponta\"\n  healthRecoveryPerDay: \"Egészség naponta\"\n  sickBayAbsoluteBonus: \"Gyengélkedő absz. bónusz\"\n  sickBayRelativeBonus: \"Gyengélkedő rel. bónusz\"\n  prisonType: \"Böntöntípus\"\n  rightClickActionType: \"Jobbkattintás akció\"\n  leavesBehindOnSell: \"Eladáskor marad utána\"\n  removalTime: \"Eltávolítás ideje\"\n  canBeBuiltOver: \"Lehet ráépíteni?\"\n  upgradeOnly: \"\"\n  buildOverFacilities: \"Ráépülő funkciók\"\n#\n  BFRCT_DEFAULT: \"vanilla alapérték\"\n  BFRCT_PRISON: \"ide: Idegen tároló\"\n  BFRCT_ENGINEERING: \"ide: Termelés\"\n  BFRCT_RESEARCH: \"ide: Kutatás\"\n  BFRCT_GYM: \"ide: Marsi kiképzés\"\n  BFRCT_PSI_LABS: \"ide: Pszionikus Labor\"\n  BFRCT_BARRACKS: \"ide: Barakk\"\n  BFRCT_GREY_MARKET: \"ide: Szürkepiac\"\n  BFRCT_GEOSCAPE: \"ide: Földgömb\"\n#\n  costRent: \"Bérleti költség\"\n  soldiers: \"Raktér\"\n  maxUnitsLimit: \"\"\n  pilots: \"Pilótafülke mérete\"\n  pilotMinStatsRequired: \"\"\n  pilotSoldierBonusesRequired: \"\"\n  vehicles: \"NFP kapacitás\"\n  onlyOneSoldierGroupAllowed: \"\"\n  allowedSoldierGroups: \"\"\n  allowedArmorGroups: \"\"\n  limitArmorGroups: \"\"\n  maxHWPUnitsLimit: \"\"\n  maxSmallSoldiers: \"\"\n  maxLargeSoldiers: \"\"\n  maxSmallVehicles: \"\"\n  maxLargeVehicles: \"\"\n  maxSmallUnits: \"\"\n  maxLargeUnits: \"\"\n  maxSoldiers: \"\"\n  maxVehicles: \"\"\n  maxItems: \"Max felszerelés\"\n  maxStorageSpace: \"Raktárméret\"\n  maxAltitude: \"Max támadási magasság\"\n  weapons: \"Fegyverállványok\"\n  weaponStrings: \"Fegyvernevek\"\n  fixedWeapons: \"\"\n  weaponTypes: \"Megengedett fegyvertípusok\"\n  damageMax: \"Sérüléstűrés\"\n  avoidBonus: \"Kitérési bónusz (átalány)\"\n  avoidBonus2: \"\"\n  powerBonus: \"Erő bónusz (átalány)\"\n  hitBonus: \"Találati bónusz (átalány)\"\n  fuelMax: \"Üzemanyag-kapacitás\"\n  speedMax: \"Maximális sebesség\"\n  accel: \"Gyorsulás\"\n  shieldCapacity: \"Pajzs kapacitás\"\n  shieldRecharge: \"Pajzs újratöltés (Harc)\"\n  shieldRechargeInGeoscape: \"Pajzs újratöltés (Földgömb)\"\n  shieldBleedThrough: \"Pajzs átvérzés\"\n  shieldRechargedAtBase: \"Pajzs újratöltés (Bázis)\"\n  refuelItem: \"Üzemanyag újratöltése\"\n  refuelRate: \"Tankolási költség\"\n  repairRate: \"Javítási költség\"\n  spacecraft: \"Végső gép?\"\n  allowLanding: \"Landolás engedélyezve?\"\n  notifyWhenRefueled: \"Értesítsen, ha megtankolt?\"\n  autoPatrol: \"Automata őrjárat?\"\n  undetectable: \"Észlelhetetlen?\"\n  patrolWithoutFuel: \"\"\n  keepCraftAfterFailedMission: \"Ejtőernyősök?\"\n  _calculatedValues: \"Kalkulált értékek\"\n  _maxRange: \"Max. hatótáv\"\n  _minRange: \"Min. hatótáv\"\n  _avgRange: \"Átlagos hatótáv\"\n#\n  hunterKillerPercentage: \"Hunter-killer esély\"\n  huntMode: \"Vadász mód\"\n  huntSpeed: \"Vadászati sebesség\"\n  huntBehavior: \"Viselkedés vadászatkor\"\n  range: \"Hatótáv\"\n  reload: \"Újratöltési idő\"\n  breakOffTime: \"Elszakadási idő\"\n  score: \"Pontszám\"\n  missionScore: \"Küldetés pontszáma\"\n  craftCustomDeploy: \"Bevetés UFO-hoz\"\n  missionCustomDeploy: \"Bevetés küldetésre\"\n  _escapeCountdown: \"Menkülés visszaszámlálás\"\n  _fireRate: \"Tűzgyorsaság\"\n  _averageDPM: \"Átlag DPM\"\n#\n  HM_INTERCEPTORS: \"vadászó elfogók előnyben\"\n  HM_TRANSPORTS: \"vadászó transzportok előnyben\"\n  HM_RANDOM: \"véletlen\"\n#\n  HB_FLEE: \"vesztéskor menekül\"\n  HB_KAMIKAZE: \"harcol megsemmisülésig\"\n  HB_RANDOM: \"véletlen\"\n#\n  tractorBeamPower: \"Vonósugár ereje\"\n  damage: \"Sebzés\"\n  shieldDamageModifier: \"Pajzs sebzésmódosító\"\n  accuracy: \"Pontosság\"\n  reloadCautious: \"Újratöltés (Óvatos)\"\n  reloadStandard: \"Újratöltés (Normál)\"\n  reloadAggressive: \"Újratöltés (Agresszív)\"\n  launcher: \"Indító elem\"\n  weaponType: \"Fegyvertípus\"\n  clip: \"Tár\"\n  ammoMax: \"Töltények\"\n  rearmRate: \"Fegyverzési sebesség\"\n  bulletSaving: \"\"\n  _damageRange: \"\"\n  _damageRangeBasic: \"\"\n  _averageTotalDamage: \"Átlag teljes sebzés\"\n#\n  allowPiloting: \"\"\n  costSalary: \"\"\n  costSalarySquaddie: \"\"\n  costSalarySergeant: \"\"\n  costSalaryCaptain: \"\"\n  costSalaryColonel: \"\"\n  costSalaryCommander: \"\"\n#\n  race: \"\"\n  rank: \"\"\n  livingWeapon: \"\"\n  meleeWeapon: \"Közelfegyver\"\n  psiWeapon: \"\"\n  _builtInWeaponSets: \"\"\n  _weightedBuiltInWeaponSets: \"\"\n  spawnUnit: \"\"\n  _capturable: \"\"\n  capturable: \"\"\n  canSurrender: \"\"\n  autoSurrender: \"\"\n  spotter: \"\"\n  sniper: \"\"\n"
  },
  {
    "path": "bin/common/Language/Technical/it.yml",
    "content": "it:\n#=================== Menu ===================\n#TestState.cpp\n  STR_BAD_NODES: \"Nodi errati nei file RMP\"\n  STR_BAD_NODES_DESC: \"Controlla i file RMP per i nodi al di fuori dei limiti della mappa.{NEWLINE}Questi NON causeranno arresti anomali, ma saranno ignorati dal gioco, quindi non funzioneranno come previsto.\"\n#\n  STR_MCD_CHECK: \"Controllo MCD\"\n  STR_MCD_CHECK_DESC: \"Controlla file MCD per oggetti a terra senza costo di movimento; controlla anche riferimenti invalidi DieMCD/AltMCD; controlla anche LOFTemps invalidi.\"\n#\n  STR_PALETTE_CHECK: \"Concordanza Palette\"\n  STR_PALETTE_CHECK_DESC: \"Cerca di abbinare palette di immagini modificate alle tavolozze ufficiali e riporta le immagini che non hanno una corrispondenza del 100%.\"\n#\n  STR_SCRIPT_TAGS: \"Esporta Script tag\"\n  STR_SCRIPT_TAGS_DESC: \"Esporta script in formato CSV.\"\n#\n  STR_MAP_RESOURCES: \"Controllo risorse mappa\"\n  STR_MAP_RESOURCES_DESC: \"Controlla file e regole mancanti o non usate di mappa.\"\n#\n  STR_CHECKING_TERRAIN: \"Verifica terreno...\"\n  STR_CHECKING_UFOS: \"Verifica UFO...\"\n  STR_CHECKING_CRAFT: \"Verifica veicoli...\"\n#\n  BACKPALS.DAT: \"BACKPALS.DAT\"\n  PAL_GEOSCAPE: \"PAL_GEOSCAPE\"\n  PAL_BASESCAPE: \"PAL_BASESCAPE\"\n  PAL_GRAPHS: \"PAL_GRAPHS\"\n  PAL_UFOPAEDIA: \"PAL_UFOPAEDIA\"\n  PAL_BATTLEPEDIA: \"PAL_BATTLEPEDIA\"\n  PAL_BATTLESCAPE: \"PAL_BATTLESCAPE\"\n  PAL_BATTLESCAPE_1: \"PAL_BATTLESCAPE_1\"\n  PAL_BATTLESCAPE_2: \"PAL_BATTLESCAPE_2\"\n  PAL_BATTLESCAPE_3: \"PAL_BATTLESCAPE_3\"\n#=================== Ufopaedia ===================\n#StatsForNerdsState.cpp\n  BT_NONE: \"Nessuno\"\n  BT_FIREARM: \"Armi\"\n  BT_AMMO: \"Munizioni\"\n  BT_MELEE: \"Armi mischia\"\n  BT_GRENADE: \"Granate\"\n  BT_PROXIMITYGRENADE: \"Granate di prossimità\"\n  BT_MEDIKIT: \"Kit Medici\"\n  BT_SCANNER: \"Scanner di movimento\"\n  BT_MINDPROBE: \"Sonde mentali\"\n  BT_PSIAMP: \"Psi Amp\"\n  BT_FLARE: \"Flare\"\n  BT_CORPSE: \"Cadaveri/Corpi\"\n#\n  DRT_DEFAULT: \"vanilla default\"\n  DRT_UFO: \"0-200% spread\"\n  DRT_TFTD: \"50-150% spread\"\n  DRT_FLAT: \"danno base\"\n  DRT_FIRE: \"danno fuoco speciale\"\n  DRT_NONE: \"no danno\"\n  DRT_UFO_WITH_TWO_DICE: \"0-200% spread (2 lanci dado)\"\n  DRT_EASY: \"50-200% spread\"\n  DRT_STANDARD: \"Raggio danno standard\"\n  DRT_EXPLOSION: \"Raggio danno esplosione\"\n#\n  BFT_NONE: \"nessuno\"\n  BFT_INSTANT: \"istantaneo\"\n  BFT_SET: \"manuale\"\n  BFT_FIXED: \"fisso\"\n#\n  BMT_NORMAL: \"standard (multi-scopo)\"\n  BMT_HEAL: \"cura\"\n  BMT_STIMULANT: \"stimolante\"\n  BMT_PAINKILLER: \"antidolorifici\"\n#\n  ETM_DEFAULT: \"predefinito\"\n  ETM_MELEE_100: \"MISCHIA\"\n  ETM_MELEE_50: \"MISCHIA (50% chance)\"\n  ETM_MELEE_33: \"MISCHIA (33% chance)\"\n  ETM_FIRING_100: \"MIRA\"\n  ETM_FIRING_50: \"MIRA (50% chance)\"\n  ETM_FIRING_33: \"MIRA (33% chance)\"\n  ETM_THROWING_100: \"TIRO\"\n  ETM_THROWING_50: \"TIRO (50% chance)\"\n  ETM_THROWING_33: \"TIRO (33% chance)\"\n  ETM_FIRING_AND_THROWING: \"MIRA e TIRO\"\n  ETM_FIRING_OR_THROWING: \"MIRA o TIRO\"\n  ETM_REACTIONS: \"REAZIONI\"\n  ETM_REACTIONS_AND_MELEE: \"REAZIONI e MISCHIA\"\n  ETM_REACTIONS_AND_FIRING: \"REAZIONI e MIRA\"\n  ETM_REACTIONS_AND_THROWING: \"REAZIONI e TIRO\"\n  ETM_REACTIONS_OR_MELEE: \"REAZIONI o MISCHIA\"\n  ETM_REACTIONS_OR_FIRING: \"REAZIONI o MIRA\"\n  ETM_REACTIONS_OR_THROWING: \"REAZIONI o TIRO\"\n  ETM_BRAVERY: \"CORAGGIO\"\n  ETM_BRAVERY_2X: \"CORAGGIO (x2)\"\n  ETM_BRAVERY_AND_REACTIONS: \"CORAGGIO e REAZIONI\"\n  ETM_BRAVERY_OR_REACTIONS: \"CORAGGIO e REAZIONI\"\n  ETM_BRAVERY_OR_REACTIONS_2X: \"CORAGGIO o REAZIONI (x2)\"\n  ETM_PSI_STRENGTH: \"FORZA PSI\"\n  ETM_PSI_STRENGTH_2X: \"FORZA PSI (x2)\"\n  ETM_PSI_SKILL: \"ABILITÀ PSI\"\n  ETM_PSI_SKILL_2X: \"ABILITÀ PSI (x2)\"\n  ETM_PSI_STRENGTH_AND_SKILL: \"FORZA PSI e ABILITÀ PSI\"\n  ETM_PSI_STRENGTH_AND_SKILL_2X: \"FORZA PSI e ABILITÀ PSI (x2)\"\n  ETM_PSI_STRENGTH_OR_SKILL: \"FORZA PSI o ABILITÀ PSI\"\n  ETM_PSI_STRENGTH_OR_SKILL_2X: \"FORZA PSI o ABILITÀ PSI (x2)\"\n  ETM_NOTHING: \"no addestramento\"\n#\n  battleType: \"Tipo oggetto\"\n  experienceTrainingMode: \"Modalità Esperienza\"\n  manaExperience: \"Esperienza mana\"\n  arcingShot: \"Archi?\"\n  isFireExtinguisher: \"Estintore?\"\n  explodeInventory: \"Esplode in inventario?\"\n  waypoints: \"Waypoint massimi\"\n  sprayWaypoints: \"Waypoint sventagliata\"\n#\n  shotgunPellets: \"Numero di pallettoni\"\n  shotgunBehavior: \"Comportamento fucile\"\n  shotgunSpread: \"Spread fucile\"\n  shotgunChoke: \"Chiusura fucile\"\n#\n  underwaterOnly: \"Solo subacqueo?\"\n  landOnly: \"Solo terreno?\"\n  psiRequired: \"Richiesta abilità Psi?\"\n  targetMatrix: \"Bersaglio oggetto\"\n  convertToCivilian: \"Converti in Civile?\"\n  manaRequired: \"Mana richiesto?\"\n  LOSRequired: \"Vista richiesta?\"\n#\n  noLOSAccuracyPenalty: \"mult. penalità non visiva\"\n  kneelBonus: \"molt. bonus inginocchiato\"\n  twoHanded: \"A due mani?\"\n  blockBothHands: \"Blocca entrambe le ani?\"\n  oneHandedPenalty: \"Penalità uso una mano\"\n#\n  minRange: \"Gittata minima\"\n  maxRange: \"Gittata massima\"\n  aimRange: \"Gittata tiro mirato\"\n  autoRange: \"Gittata tiro auto\"\n  snapRange: \"Gittata tiro non mirato\"\n  dropoff: \"Precisione dropoff/tile\"\n#\n  accuracyMultiplier: \"Molt. precisione tiro\"\n  accuracyAimed: \"Precisione tiro mirato\"\n  accuracyAuto: \"Precisione tiro auto\"\n  accuracySnap: \"Precisione tiro snap\"\n  costAimed: \"Costo tiro mirato\"\n  costAuto: \"Costo tiro auto\"\n  costSnap: \"Costo tiro snap\"\n#\n  meleeMultiplier: \"Moltiplicatore mischia\"\n  accuracyMelee: \"Mischia\"\n  costMelee: \"Costo mischia\"\n#\n  psiAttackName: \"Nome attacco psi\"\n  accuracyUse: \"Precisione azione\"\n  accuracyMindControl: \"Precisione controllo mentale\"\n  accuracyPanic: \"Precisione panico\"\n  costUse: \"Costo azione\"\n  costMindcontrol: \"Costo controllo mentale\"\n  costPanic: \"Costo panico\"\n#\n  weight: \"Peso\"\n  throwRange: \"Tiro massimo (aria)\"\n  underwaterThrowRange: \"Tiro massimo (acqua)\"\n  throwDropoffRange: \"Distanza tiro (aria)\"\n  underwaterThrowDropoffRange: \"Distanza tiro (acqua)\"\n  throwDropoff: \"Decremento tiro/distanza\"\n  throwMultiplier: \"Molt. precisione tiro\"\n  accuracyThrow: \"Precisione tiro\"\n  costThrow: \"Costo tiro\"\n  costPrime: \"Costo innesco\"\n  costUnprime: \"Costo disinnesco\"\n#\n  closeQuartersMultiplier: \"Molt. precisione CQC\"\n  accuracyCloseQuarters: \"Precisione CQC\"\n#\n  damageType: \"Tipo danno\"\n  power: \"Potenza\"\n  powerRangeReduction: \"Riduzione Potenza\"\n  powerRangeThreshold: \"Limite rid. potenza\"\n  damageBonus: \"Bonus danno\"\n  blastRadius: \"Raggio esplosione\"\n  damageAlter: \"Info danno extra:\"\n  meleeType: \"Tipo danno mischia\"\n  meleePower: \"Potenza mischia\"\n  meleeBonus: \"Bonus potenza mischia\"\n  meleeAlter: \"Info extra mischia:\"\n  FixRadius: \"Raggio esplosione\"\n  RandomType: \"Tipo calcolo\"\n  FireBlastCalc: \"Effetti fuoco vanilla?\"\n  IgnoreDirection: \"Ignora direzione\"\n  IgnoreSelfDestruct: \"Ignora autodistruzione\"\n  IgnorePainImmunity: \"Ignora immunità stordimento\"\n  IgnoreNormalMoraleLose: \"Ign. calo morale vanilla\"\n  IgnoreOverKill: \"Ignora overkill\"\n  ArmorEffectiveness: \"Effetto armatura\"\n  RadiusEffectiveness: \"Effetto raggio\"\n  RadiusReduction: \"Riduzione danno raggio\"\n  FireThreshold: \"Limite incendio\"\n  SmokeThreshold: \"Limite fumo\"\n#\n  ToArmorPre: \"Molt. pre-danno armatura\"\n  RandomArmorPre: \"RNG pre-danno armatura\"\n  ToArmor: \"Molt. danno armatura\"\n  RandomArmor: \"RNG danno armatura\"\n  ToHealth: \"Molt. danno PV\"\n  RandomHealth: \"RNG danno PV\"\n  ToStun: \"Molt. danno stordimento\"\n  RandomStun: \"RNG danno stordimento\"\n  ToWound: \"Molt. conteggio ferite\"\n  RandomWound: \"RNG ferite vanilla\"\n  ToTime: \"Molt. danno UT\"\n  RandomTime: \"RNG danno UT\"\n  ToEnergy: \"Molt. danno energia\"\n  RandomEnergy: \"RNG danno energia\"\n  ToMorale: \"Molt. danno morale\"\n  RandomMorale: \"RNG danno morale\"\n  ToItem: \"Molt. danno oggetto\"\n  RandomItem: \"RNG danno oggetto?\"\n  ToMana: \"Moltiplicatore danno mana\"\n  RandomMana: \"RNG danno mana?\"\n  ToTile: \"Molt. danno terreno\"\n  RandomTile: \"RNG danno terreno?\"\n  TileDamageMethod: \"Metodo Danno Tile\"\n  TileDamageLimit: \"Limite Danno Tile\"\n#\n  confAimed: \"Azione mirata:\"\n  confAuto: \"Azione auto:\"\n  confSnap: \"Azione snap:\"\n  confMelee: \"Azione mischia:\"\n  shots: \"Colpi per azione\"\n  spendPerShot: \"Speso per sparo:\"\n  followProjectiles: \"Segui i proiettili?\"\n  name: \"Nome\"\n  shortName: \"Nome breve\"\n  ammoSlot: \"Slot munizione usato\"\n  ammoZombieUnitChanceOverride: \"Probabilità zombificazione\"\n  ammoSpawnUnitChanceOverride: \"Probabilità generazione unità\"\n  ammoSpawnItemChanceOverride: \"Probabilità generazione oggetto\"\n  arcing: \"Archi?\"\n#\n  clipSize: \"Dim. caricatore\"\n  isAmmoRechargeable: \"Munizione ricaricabile?\"\n#\n  primaryAmmo: \"Slot munizione primario:\"\n  compatibleAmmo: \"Munizione compatibile\"\n  tuLoad: \"Costo carico\"\n  tuUnload: \"Costo scarico\"\n  ammo[1]: \"Slot extra munizioni #1\"\n  ammo[2]: \"Slot extra munizioni #2\"\n  ammo[3]: \"Slot extra munizioni #3\"\n#\n  armor: \"Armatura\"\n#\n  medikitType: \"Tipo medikit\"\n  painKillerActionName: \"Nome azione antidolorifico\"\n  stimulantActionName: \"Nome azione stimolante\"\n  healActionName: \"Nome azione cura\"\n  medikitActionName: \"Nome azione Medikit\"\n  medikitTargetSelf: \"Medikit su se stessi?\"\n  medikitTargetImmune: \"Immunità a medikit per sanguinamento?\"\n  medikitTargetMatrix: \"Bersagli Medikit\"\n  isConsumable: \"Consumabile?\"\n  painKiller: \"Usi antidolorifici\"\n  heal: \"Usi cura\"\n  stimulant: \"Usi stimolanti\"\n  woundRecovery: \"Cura ferita\"\n  healthRecovery: \"Recupero salute\"\n  stunRecovery: \"Recupero stordimento\"\n  energyRecovery: \"Recupero energia\"\n  manaRecovery: \"Recupero mana\"\n  moraleRecovery: \"Recupero morale\"\n  painKillerRecovery: \"Forza antidolorifico\"\n#\n  requires: \"Tech richiesta\"\n  requiresBuy: \"Tech richiesta per comprare\"\n  requiresBuyBaseFunc: \"Servizio richiesto per comprare\"\n  requiresBuyCountry: \"Richiede un paese alleato\"\n  requiresAward: \"Medaglia richiesta\"\n  requiresBonus: \"Bonus richiesto\"\n  categories: \"Categorie\"\n  supportedInventorySections: \"Slot inventario\"\n#\n  size: \"Dim.\"\n  costBuy: \"Prezzo\"\n  monthlyBuyLimit: \"Limite d'acquisto mensile\"\n  costSell: \"Costo\"\n  transferTime: \"Ore per trasferire\"\n  monthlySalary: \"Salario/mese\"\n  monthlyMaintenance: \"Mantenimento/mese\"\n#\n  SPECAB_NONE: \"Nessuno\"\n  SPECAB_EXPLODEONDEATH: \"Esplode se muore\"\n  SPECAB_BURNFLOOR: \"Brucia il pavimento\"\n  SPECAB_BURN_AND_EXPLODE: \"Brucia il pavimento ed esplode se muore\"\n#\n  MT_WALK: \"Camminare\"\n  MT_FLY: \"Volare\"\n  MT_SLIDE: \"Scivolare\"\n  MT_FLOAT: \"Fluttuare\"\n  MT_SINK: \"Affondare\"\n#\n  TORSO_USE_GENDER: \"Usa genere\"\n  TORSO_ALWAYS_MALE: \"Sempre maschio\"\n  TORSO_ALWAYS_FEMALE: \"Sempre femmina\"\n#\n  DRAWING_ROUTINE_SOLDIER_SECTOID: \"Soldato, Sectoide\"\n  DRAWING_ROUTINE_FLOATER: \"Fluttuante\"\n  DRAWING_ROUTINE_HWP: \"Piattaforme Armi Pesanti\"\n  DRAWING_ROUTINE_CYBERDISC: \"Cyberdisco\"\n  DRAWING_ROUTINE_CIVILIAN_ETHEREAL: \"Civile, Etereo\"\n  DRAWING_ROUTINE_SECTOPOD_REAPER: \"Sectopode, Mietitore\"\n  DRAWING_ROUTINE_SNAKEMAN: \"Uomo-Serpente\"\n  DRAWING_ROUTINE_CHRYSSALID: \"Crisalide\"\n  DRAWING_ROUTINE_SILACOID: \"Silacoide\"\n  DRAWING_ROUTINE_CELATID: \"Celatide\"\n  DRAWING_ROUTINE_MUTON: \"Muton\"\n  DRAWING_ROUTINE_SWS: \"Sistemi d'Armi Sommergibili\"\n  DRAWING_ROUTINE_HALLUCINOID: \"Allucinoide\"\n  DRAWING_ROUTINE_AQUANAUTS: \"Acquanauti\"\n  DRAWING_ROUTINE_CALCINITE_AND_MORE: \"Calcinite, Essere Abissale, Gillman, Aragosta Umana, Tasoth\"\n  DRAWING_ROUTINE_AQUATOID: \"Acquatoide\"\n  DRAWING_ROUTINE_BIO_DRONE: \"Bio-Drone\"\n  DRAWING_ROUTINE_TFTD_CIVILIAN_A: \"Civili tipo A di TFTD e Zombi TFTD\"\n  DRAWING_ROUTINE_TFTD_CIVILIAN_B: \"Civili tipo B di TFTD\"\n  DRAWING_ROUTINE_TENTACULAT: \"Tentacolato\"\n  DRAWING_ROUTINE_TRISCENE: \"Triscene\"\n  DRAWING_ROUTINE_XARQUID: \"Xarquid\"\n  DRAWING_ROUTINE_INVERTED_CYBERDISC: \"Cyberdisco Inverso (animazione propulsione sopra)\"\n#\n  stats: \"Modificatori stat\"\n  specab: \"Abilità speciale\"\n  movementType: \"Tipo movimento\"\n  allowsRunning: \"Permetti corsa?\"\n  allowsStrafing: \"Permetti strafe?\"\n  allowsSneaking: \"Permette l'infiltrazione?\"\n  allowsKneeling: \"Permetti inginocchio?\"\n  allowsMoving: \"Permetti movimento?\"\n  fearImmune: \"Immune al calo morale?\"\n  bleedImmune: \"Immune al sanguinamento?\"\n  painImmune: \"Immune allo stordimento?\"\n  zombiImmune: \"Immune alla zombificazione?\"\n  ignoresMeleeThreat: \"Ignora CQC?\"\n  createsMeleeThreat: \"Produci CQC?\"\n  builtInWeapons: \"Oggetti built-in\"\n  specialWeapon: \"Arma speciale\"\n  heatVision: \"Visibilità attraverso fumo\"\n  visibilityThroughFire: \"Visibilità attraverso fuoco\"\n  psiVision: \"Senso Psi\"\n  psiCamouflage: \"Camuffamento Psi\"\n  visibilityAtDay: \"Visibilità diurna\"\n  visibilityAtDark: \"Visibilità notturna\"\n  camouflageAtDay: \"Camo diurno\"\n  camouflageAtDark: \"Camo notturno\"\n  antiCamouflageAtDay: \"Anticamo diurno\"\n  antiCamouflageAtDark: \"Anticamo notturno\"\n  psiDefence: \"Difesa Psi\"\n  meleeDodge: \"Schivata mischia\"\n  meleeDodgeBackPenalty: \"Penalità schivata mischia\"\n  recovery: \"Recupero ogni turno:\"\n  time: \"Tempo\"\n  energy: \"Energia\"\n  morale: \"Morale\"\n  health: \"Salute\"\n  stun: \"Stordimento\"\n  mana: \"Mana\"\n  units: \"Unità compatibili\"\n  ranks: \"Ranghi compatibili\"\n  frontArmor: \"Armatura frontale\"\n  sideArmor: \"Armatura laterale\"\n  leftArmorDiff: \"Diff Armatura sinistra\"\n  rearArmor: \"Armatura posteriore\"\n  underArmor: \"Armatura inferiore\"\n#\n  sizeX: \"Dim. X\"\n  sizeY: \"Dim. Y\"\n  buildCost: \"Costo costruzione\"\n  buildCostItems: \"Materiale costruzione:\"\n  buildTime: \"Tempo costruzione\"\n  monthlyCost: \"Costo mensile\"\n  refundValue: \"Valore rimborso\"\n  requiresBaseFunc: \"Richiede servizi\"\n  provideBaseFunc: \"Fornisce servizi\"\n  forbiddenBaseFunc: \"Vieta servizi\"\n  lift: \"Ascensore accesso?\"\n  hyper: \"Hyper-wave decoder?\"\n  mind: \"Scudo mentale?\"\n  mindPower: \"Potenza scudo mentale\"\n  grav: \"Scudo grav?\"\n  storage: \"Spazio magazzino\"\n  personnel: \"Spazio abitativo\"\n  aliens: \"Spazio prigione\"\n  crafts: \"Spazio hangar\"\n  labs: \"Spazio laboratorio\"\n  workshops: \"Spazio officina\"\n  psiLabs: \"Spazio Psi-laboratorio\"\n  trainingRooms: \"Spazio palestra\"\n  sightRange: \"Raggio visivo\"\n  sightChance: \"% di visione\"\n  radarRange: \"Raggio radar\"\n  radarChance: \"Chance radar\"\n  defense: \"Valore difesa\"\n  hitRatio: \"% di colpire\"\n  ammoNeeded: \"Munizioni necessarie\"\n  unifiedDamageFormula: \"Nuova formula per danno?\"\n  ammoItem: \"Oggetto per munizioni\"\n  maxAllowedPerBase: \"Massimo per base\"\n  manaRecoveryPerDay: \"Mana al giorno\"\n  healthRecoveryPerDay: \"Salute al giorno\"\n  sickBayAbsoluteBonus: \"Bonus abs. Sickbay\"\n  sickBayRelativeBonus: \"Bonus rel. Sickbay\"\n  prisonType: \"Tipo prigione\"\n  rightClickActionType: \"Azione Tasto destro\"\n  leavesBehindOnSell: \"Lascia alla vendita\"\n  removalTime: \"Tempo rimozione\"\n  canBeBuiltOver: \"Puoi costruire sopra?\"\n  upgradeOnly: \"Solo miglioramento?\"\n  buildOverFacilities: \"Costruzione su edifici\"\n#\n  BFRCT_DEFAULT: \"vanilla default\"\n  BFRCT_PRISON: \"vai a Contenimento Alieno\"\n  BFRCT_ENGINEERING: \"vai a Produzione\"\n  BFRCT_RESEARCH: \"vai a Ricerca\"\n  BFRCT_GYM: \"vai a Addestramento\"\n  BFRCT_PSI_LABS: \"vai a Lab. Psionico\"\n  BFRCT_BARRACKS: \"vai a Caserma\"\n  BFRCT_GREY_MARKET: \"vai a Mercato Grigio\"\n  BFRCT_GEOSCAPE: \"vai a Geoscape\"\n#\n  costRent: \"Affitto\"\n  soldiers: \"Spazio cargo\"\n  maxUnitsLimit: \"Spazio di carico massimo\"\n  pilots: \"Dim. cabina\"\n  pilotMinStatsRequired: \"Stat minime pilota\"\n  pilotSoldierBonusesRequired: \"Richieste per pilota\"\n  vehicles: \"Capacità HWP\"\n  onlyOneSoldierGroupAllowed: \"È consentito un solo gruppo di soldati?\"\n  allowedSoldierGroups: \"Gruppo di soldati consentiti\"\n  allowedArmorGroups: \"Gruppo di armature consentite\"\n  limitArmorGroups: \"Limita gruppi di armature\"\n  maxHWPUnitsLimit: \"Massima capacità per HWP\"\n  maxSmallSoldiers: \"Massimo numero soldati piccoli\"\n  maxLargeSoldiers: \"Massimo numero soldati grandi\"\n  maxSmallVehicles: \"Massimo numero veicoli piccoli\"\n  maxLargeVehicles: \"Massimo numero veicoli grandi\"\n  maxSmallUnits: \"Massimo numero unità piccole\"\n  maxLargeUnits: \"Massimo numero unità grandi\"\n  maxSoldiers: \"Massimo numero soldati\"\n  maxVehicles: \"Massimo numero veicoli\"\n  maxItems: \"Limite equipaggiamento\"\n  maxStorageSpace: \"Spazio magazzino\"\n  maxAltitude: \"Limite altitudine comb.\"\n  weapons: \"Postazioni armi\"\n  weaponStrings: \"Nomi armi\"\n  fixedWeapons: \"Armi fisse\"\n  weaponTypes: \"Tipi armi permesse\"\n  damageMax: \"Capacità danno\"\n  avoidBonus: \"Bonus schivata (base)\"\n  avoidBonus2: \"Bonus schivata 2 (base)\"\n  powerBonus: \"Bonus potenza (base)\"\n  hitBonus: \"Bonus precisione (base)\"\n  fuelMax: \"Capacità carburante\"\n  speedMax: \"Velocità massima\"\n  accel: \"Accelerazione\"\n  shieldCapacity: \"Capacità scudo\"\n  shieldRecharge: \"Ricarica scudo (Comb.)\"\n  shieldRechargeInGeoscape: \"Ricarica scudo (Globo)\"\n  shieldBleedThrough: \"Passaggio scudo\"\n  shieldRechargedAtBase: \"Ricarica scudo (Base)\"\n  refuelItem: \"Rifornimento oggetto\"\n  refuelRate: \"Rateo rifornimento\"\n  repairRate: \"Rateo riparazione\"\n  spacecraft: \"Veicolo finale?\"\n  allowLanding: \"Permette atterraggio?\"\n  notifyWhenRefueled: \"Notifica quando pieno?\"\n  autoPatrol: \"Auto-pattuglia?\"\n  undetectable: \"Non rivelabile?\"\n  patrolWithoutFuel: \"Pattuglia gratuitamente?\"\n  keepCraftAfterFailedMission: \"Paracadutisti?\"\n  _calculatedValues: \"Valori calcolati\"\n  _maxRange: \"Raggio massimo\"\n  _minRange: \"Raggio minimo\"\n  _avgRange: \"Raggio medio\"\n#\n  hunterKillerPercentage: \"chance hunter-killer\"\n  huntMode: \"Modalità caccia\"\n  huntSpeed: \"Velocità caccia\"\n  huntBehavior: \"Comportamento caccia\"\n  range: \"Raggio\"\n  reload: \"Tempo ricarica\"\n  breakOffTime: \"Tempo disingaggio\"\n  score: \"Punteggio\"\n  missionScore: \"Punteggio missione\"\n  craftCustomDeploy: \"Sito UFO\"\n  missionCustomDeploy: \"Sito missione\"\n  _escapeCountdown: \"Contatore fuga\"\n  _fireRate: \"Rateo di fuoco\"\n  _averageDPM: \"DPM medi\"\n#\n  HM_INTERCEPTORS: \"preferisci interc. caccia\"\n  HM_TRANSPORTS: \"preferisci interc. trasporti\"\n  HM_RANDOM: \"casuale\"\n#\n  HB_FLEE: \"fuga quando perdi\"\n  HB_KAMIKAZE: \"combatti fino a distruzione\"\n  HB_RANDOM: \"casuale\"\n#\n  tractorBeamPower: \"Potenza raggio traente\"\n  damage: \"Danno\"\n  shieldDamageModifier: \"Modificatore danno scudo\"\n  accuracy: \"Precisione\"\n  reloadCautious: \"Ricarica (Cauta)\"\n  reloadStandard: \"Ricarica (Standard)\"\n  reloadAggressive: \"Ricarica (Aggressivo)\"\n  launcher: \"Oggetto lanciato\"\n  weaponType: \"Tipo arma\"\n  clip: \"Oggetto caricatore\"\n  ammoMax: \"Turni\"\n  rearmRate: \"Rateo Riarmo\"\n  bulletSaving: \"Risparmio proiettili?\"\n  _damageRange: \"Raggio danno\"\n  _damageRangeBasic: \"Raggio danno (base)\"\n  _averageTotalDamage: \"Danno totale medio\"\n#\n  allowPiloting: \"Permette il pilotaggio?\"\n  costSalary: \"Salario\"\n  costSalarySquaddie: \"Bonus (soldato scelto)\"\n  costSalarySergeant: \"Bonus (sergente)\"\n  costSalaryCaptain: \"Bonus (capitano)\"\n  costSalaryColonel: \"Bonus (colonnello)\"\n  costSalaryCommander: \"Bonus (comandante)\"\n#\n  race: \"Razza\"\n  rank: \"Rango\"\n  livingWeapon: \"È un'arma vivente?\"\n  meleeWeapon: \"Armi mischia\"\n  psiWeapon: \"Arma psi\"\n  _builtInWeaponSets: \"Set di armi?\"\n  _weightedBuiltInWeaponSets: \"Altri set di armi?\"\n  spawnUnit: \"Generato se muore\"\n  _capturable: \"Cattura possibile?\"\n  capturable: \"Catturabile (flag)\"\n  canSurrender: \"Può arrendersi?\"\n  autoSurrender: \"Resa automatica?\"\n  spotter: \"Durata spotter\"\n  sniper: \"Probabilità cecchino?\"\n"
  },
  {
    "path": "bin/common/Language/Technical/ja.yml",
    "content": "ja:\n#=================== Menu ===================\n#TestState.cpp\n  STR_BAD_NODES: \"RMPファイルの中にノード不良発見\"\n  STR_BAD_NODES_DESC: \"マップの境界外に不適切なノードが存在しないかRMPファイルをチェックします。{NEWLINE}この不具合が存在してもゲームをクラッシュさせる事は有りませんが、そのままでは意図通りに動作しなくなる可能性があります。\"\n#\n  STR_MCD_CHECK: \"MCDチェック\"\n  STR_MCD_CHECK_DESC: \"移動コストゼロの床面に対応するMCDファイル、無効なDieMCD/AltMCDへの参照先、無効なLOFTempをチェックします\"\n#\n  STR_PALETTE_CHECK: \"色パレットの整合チェック\"\n  STR_PALETTE_CHECK_DESC: \"Modによって変更されたタイルグラフィックをオリジナルの色パレットと比較し、100％適合しない物を全て報告します。\"\n#\n  STR_SCRIPT_TAGS: \"スクリプトタグのエキスポート\"\n  STR_SCRIPT_TAGS_DESC: \"スクリプトタグをCSVフォーマットでエクスポート\"\n#\n  STR_MAP_RESOURCES: \"マップリソースのチェック\"\n  STR_MAP_RESOURCES_DESC: \"足りない/不要なマップデータとルールセットをチェックします\"\n#\n  STR_CHECKING_TERRAIN: \"地形をチェック中・・・\"\n  STR_CHECKING_UFOS: \"UFOをチェック中・・・\"\n  STR_CHECKING_CRAFT: \"機体をチェック中・・・\"\n#\n  BACKPALS.DAT: \"BACKPALS.DAT\"\n  PAL_GEOSCAPE: \"PAL_GEOSCAPE\"\n  PAL_BASESCAPE: \"PAL_BASESCAPE\"\n  PAL_GRAPHS: \"PAL_GRAPHS\"\n  PAL_UFOPAEDIA: \"PAL_UFOPAEDIA\"\n  PAL_BATTLEPEDIA: \"PAL_BATTLEPEDIA\"\n  PAL_BATTLESCAPE: \"PAL_BATTLESCAPE\"\n  PAL_BATTLESCAPE_1: \"PAL_BATTLESCAPE_1\"\n  PAL_BATTLESCAPE_2: \"PAL_BATTLESCAPE_2\"\n  PAL_BATTLESCAPE_3: \"PAL_BATTLESCAPE_3\"\n#=================== Ufopaedia ===================\n#StatsForNerdsState.cpp\n  BT_NONE: \"なし\"\n  BT_FIREARM: \"銃器\"\n  BT_AMMO: \"弾丸\"\n  BT_MELEE: \"近接武器\"\n  BT_GRENADE: \"手りゅう弾\"\n  BT_PROXIMITYGRENADE: \"時限式手りゅう弾\"\n  BT_MEDIKIT: \"メディキット\"\n  BT_SCANNER: \"モーションスキャナ\"\n  BT_MINDPROBE: \"マインドプローブ\"\n  BT_PSIAMP: \"Psiアンプ\"\n  BT_FLARE: \"フレア\"\n  BT_CORPSE: \"死骸／死体\"\n#\n  DRT_DEFAULT: \"vanillaのデフォルト\"\n  DRT_UFO: \"0-200% で分布\"\n  DRT_TFTD: \"50-150% で分布\"\n  DRT_FLAT: \"固定ダメージ\"\n  DRT_FIRE: \"特殊ダメージ\"\n  DRT_NONE: \"ノーダメージ\"\n  DRT_UFO_WITH_TWO_DICE: \"0-200% で分布（2ダイスロール）\"\n  DRT_EASY: \"50-200% で分布\"\n  DRT_STANDARD: \"通常ダメージ量\"\n  DRT_EXPLOSION: \"爆発ダメージ量\"\n#\n  BFT_NONE: \"なし\"\n  BFT_INSTANT: \"即座\"\n  BFT_SET: \"手動設定\"\n  BFT_FIXED: \"固定時間\"\n#\n  BMT_NORMAL: \"スタンダード（多用途）\"\n  BMT_HEAL: \"HP回復\"\n  BMT_STIMULANT: \"興奮剤\"\n  BMT_PAINKILLER: \"鎮痛剤\"\n#\n  ETM_DEFAULT: \"デフォルト\"\n  ETM_MELEE_100: \"近接攻撃\"\n  ETM_MELEE_50: \"近接（命中率50％）\"\n  ETM_MELEE_33: \"近接（命中率33％）\"\n  ETM_FIRING_100: \"射撃\"\n  ETM_FIRING_50: \"射撃（命中率50％）\"\n  ETM_FIRING_33: \"射撃（命中率33％）\"\n  ETM_THROWING_100: \"投擲\"\n  ETM_THROWING_50: \"投擲（成功率50％）\"\n  ETM_THROWING_33: \"投擲（成功率33％）\"\n  ETM_FIRING_AND_THROWING: \"射撃と投擲\"\n  ETM_FIRING_OR_THROWING: \"射撃か投擲\"\n  ETM_REACTIONS: \"反応速度\"\n  ETM_REACTIONS_AND_MELEE: \"反応と近接\"\n  ETM_REACTIONS_AND_FIRING: \"反応と射撃\"\n  ETM_REACTIONS_AND_THROWING: \"反応と投擲\"\n  ETM_REACTIONS_OR_MELEE: \"反応か近接\"\n  ETM_REACTIONS_OR_FIRING: \"反応か射撃\"\n  ETM_REACTIONS_OR_THROWING: \"反応か投擲\"\n  ETM_BRAVERY: \"士気\"\n  ETM_BRAVERY_2X: \"士気 (x2)\"\n  ETM_BRAVERY_AND_REACTIONS: \"士気と反応\"\n  ETM_BRAVERY_OR_REACTIONS: \"士気か反応\"\n  ETM_BRAVERY_OR_REACTIONS_2X: \"士気か反応(x2)\"\n  ETM_PSI_STRENGTH: \"Psi強度\"\n  ETM_PSI_STRENGTH_2X: \"Psi強度(x2)\"\n  ETM_PSI_SKILL: \"Psiスキル\"\n  ETM_PSI_SKILL_2X: \"Psiスキル(x2)\"\n  ETM_PSI_STRENGTH_AND_SKILL: \"Psi強度とPsiスキル\"\n  ETM_PSI_STRENGTH_AND_SKILL_2X: \"Psi強度とPsiスキル(x2)\"\n  ETM_PSI_STRENGTH_OR_SKILL: \"Psi強度かPsiスキル\"\n  ETM_PSI_STRENGTH_OR_SKILL_2X: \"Psi強度かPsiスキル(x2)\"\n  ETM_NOTHING: \"未訓練\"\n#\n  battleType: \"アイテムの種類\"\n  experienceTrainingMode: \"経験モード\"\n  manaExperience: \"MP経験値\"\n  arcingShot: \"アーク (非射線弾道) を許可するか\"\n  isFireExtinguisher: \"消化器を使用するか\"\n  explodeInventory: \"インベントリ内で爆発可にするか\"\n  waypoints: \"最大ウェイポイント\"\n  sprayWaypoints: \"弾幕のウェイポイント\"\n#\n  shotgunPellets: \"散弾数\"\n  shotgunBehavior: \"ショットガンの挙動\"\n  shotgunSpread: \"散弾の拡散分布\"\n  shotgunChoke: \"散弾の拡散範囲\"\n#\n  underwaterOnly: \"水中のみにするか\"\n  landOnly: \"陸上のみにするか\"\n  psiRequired: \"Psiスキル必須にするか\"\n  targetMatrix: \"アイテムの対象\"\n  convertToCivilian: \"民間人に変化するか\"\n  manaRequired: \"MPを必要とするか\"\n  LOSRequired: \"視認状態を必須にするか\"\n#\n  noLOSAccuracyPenalty: \"視界外対象へのペナルティ\"\n  kneelBonus: \"膝付きボーナスの倍率\"\n  twoHanded: \"両手使用を強要するか\"\n  blockBothHands: \"両手を塞ぐか\"\n  oneHandedPenalty: \"片手使用の際のペナルティ\"\n#\n  minRange: \"最短射程\"\n  maxRange: \"最大射程\"\n  aimRange: \"狙い撃ちの射程\"\n  autoRange: \"連射の射程\"\n  snapRange: \"速射の射程\"\n  dropoff: \"命中率の減少／マス目\"\n#\n  accuracyMultiplier: \"射撃の命中倍率\"\n  accuracyAimed: \"狙い撃ちの命中率\"\n  accuracyAuto: \"連射の命中率\"\n  accuracySnap: \"速射の命中率\"\n  costAimed: \"狙い撃ちのTU消費量\"\n  costAuto: \"連射のTU消費量\"\n  costSnap: \"速射のTU消費量\"\n#\n  meleeMultiplier: \"近接攻撃の成功倍率\"\n  accuracyMelee: \"近接攻撃の成功率\"\n  costMelee: \"近接攻撃のTU消費量\"\n#\n  psiAttackName: \"Psi攻撃の種類\"\n  accuracyUse: \"アクションの成功率\"\n  accuracyMindControl: \"精神支配の成功率\"\n  accuracyPanic: \"恐慌化の成功率\"\n  costUse: \"アクションのTU消費量\"\n  costMindcontrol: \"精神支配のTU消費量\"\n  costPanic: \"恐慌化のTU消費量\"\n#\n  weight: \"重量\"\n  throwRange: \"投てき 最大 (大気中)\"\n  underwaterThrowRange: \"投てき 最大 (水中)\"\n  throwDropoffRange: \"投てき 射程 (大気中)\"\n  underwaterThrowDropoffRange: \"投てき 射程 (水中)\"\n  throwDropoff: \"投てき 落下／マス\"\n  throwMultiplier: \"投擲の成功倍率\"\n  accuracyThrow: \"投擲の成功率\"\n  costThrow: \"投擲のTU消費量\"\n  costPrime: \"起爆の為のTU消費量\"\n  costUnprime: \"起爆解除のTU消費量\"\n#\n  closeQuartersMultiplier: \"隣接時の攻撃成功倍率\"\n  accuracyCloseQuarters: \"隣接時の攻撃成功率\"\n#\n  damageType: \"ダメージタイプ\"\n  power: \"威力\"\n  powerRangeReduction: \"威力の減衰／マス目\"\n  powerRangeThreshold: \"威力減衰の閾値\"\n  damageBonus: \"ダメージボーナス\"\n  blastRadius: \"爆発範囲\"\n  damageAlter: \"追加ダメージ情報：\"\n  meleeType: \"近接ダメージの種類\"\n  meleePower: \"近接攻撃の威力\"\n  meleeBonus: \"近接攻撃の威力ボーナス\"\n  meleeAlter: \"近接攻撃で追加攻撃発生報告：\"\n  FixRadius: \"爆発範囲\"\n  RandomType: \"計算方式\"\n  FireBlastCalc: \"オリジナルX-Comの計算方式にするか\"\n  IgnoreDirection: \"方向を無視\"\n  IgnoreSelfDestruct: \"自爆を無視\"\n  IgnorePainImmunity: \"スタン耐性を無視\"\n  IgnoreNormalMoraleLose: \"vanillaの士気減退を無視\"\n  IgnoreOverKill: \"過剰殺傷力を無視\"\n  ArmorEffectiveness: \"装甲の効率\"\n  RadiusEffectiveness: \"防御範囲\"\n  RadiusReduction: \"ダメージ軽減\"\n  FireThreshold: \"引火する閾値\"\n  SmokeThreshold: \"噴煙発生の閾値\"\n#\n  ToArmorPre: \"装甲のダメージ軽減率\"\n  RandomArmorPre: \"装甲のダメージ軽減率をランダム化するか\"\n  ToArmor: \"装甲のダメージ倍率\"\n  RandomArmor: \"装甲ダメージをランダム化するか\"\n  ToHealth: \"HPダメージ倍率\"\n  RandomHealth: \"HPダメージをランダム化するか\"\n  ToStun: \"スタンダメージ倍率\"\n  RandomStun: \"スタンダメージをランダム化するか\"\n  ToWound: \"負傷率\"\n  RandomWound: \"オリジナルX-Comの様に負傷率をランダム化するか\"\n  ToTime: \"TUダメージ倍率\"\n  RandomTime: \"TUダメージをランダム化するか\"\n  ToEnergy: \"エネルギーダメージ倍率\"\n  RandomEnergy: \"エネルギーダメージをランダム化するか\"\n  ToMorale: \"士気ダメージ倍率\"\n  RandomMorale: \"士気ダメージをランダム化するか\"\n  ToItem: \"アイテムへのダメージ倍率\"\n  RandomItem: \"アイテムへのダメージをランダム化するか\"\n  ToMana: \"使用MP量によるダメージX倍加\"\n  RandomMana: \"MPダメージをランダム化するか\"\n  ToTile: \"地形ダメージ倍率\"\n  RandomTile: \"地形ダメージをランダム化するか\"\n  TileDamageMethod: \"マス目に対するダメージの算出法\"\n  TileDamageLimit: \"\"\n#\n  confAimed: \"狙い撃ちアクション：\"\n  confAuto: \"連射アクション：\"\n  confSnap: \"速射アクション：\"\n  confMelee: \"近接攻撃アクション：\"\n  shots: \"アクション毎の発射数\"\n  spendPerShot: \"消費量/発:\"\n  followProjectiles: \"カメラが弾丸を追うか\"\n  name: \"名\"\n  shortName: \"略称\"\n  ammoSlot: \"弾薬スロット使用済\"\n  ammoZombieUnitChanceOverride: \"ゾンビ化確率\"\n  ammoSpawnUnitChanceOverride: \"ユニット出現率\"\n  ammoSpawnItemChanceOverride: \"アイテム発生率\"\n  arcing: \"アーク (非射線弾道) を許可するか\"\n#\n  clipSize: \"装填数\"\n  isAmmoRechargeable: \"\"\n#\n  primaryAmmo: \"主弾薬スロット\"\n  compatibleAmmo: \"互換弾倉\"\n  tuLoad: \"装弾のTU消費量\"\n  tuUnload: \"弾倉脱着のTU消費量\"\n  ammo[1]: \"予備弾薬スロット #1:\"\n  ammo[2]: \"予備弾薬スロット #2:\"\n  ammo[3]: \"予備弾薬スロット #3:\"\n#\n  armor: \"アーマー\"\n#\n  medikitType: \"メディキットのタイプ\"\n  painKillerActionName: \"\"\n  stimulantActionName: \"\"\n  healActionName: \"\"\n  medikitActionName: \"メディキットのアクション名\"\n  medikitTargetSelf: \"メディキットの自己使用を許可するか\"\n  medikitTargetImmune: \"出血しないユニットへのメディキットの使用を許可するか\"\n  medikitTargetMatrix: \"メディキットの使用対象\"\n  isConsumable: \"消耗品扱いにするか\"\n  painKiller: \"鎮痛剤の数\"\n  heal: \"HP回復の回数\"\n  stimulant: \"興奮剤の数\"\n  woundRecovery: \"負傷の手当\"\n  healthRecovery: \"HPの回復\"\n  stunRecovery: \"スタン解除\"\n  energyRecovery: \"スタミナ回復\"\n  manaRecovery: \"MP回復量\"\n  moraleRecovery: \"士気回復\"\n  painKillerRecovery: \"鎮痛剤の強度\"\n#\n  requires: \"必須テクノロジー\"\n  requiresBuy: \"テクノロジー取得が購入条件\"\n  requiresBuyBaseFunc: \"購入の為に必要な業務\"\n  requiresBuyCountry: \"同盟国が必要\"\n  requiresAward: \"褒章が必要\"\n  requiresBonus: \"ボーナスが必要\"\n  categories: \"カテゴリー\"\n  supportedInventorySections: \"持ち物スロット\"\n#\n  size: \"サイズ\"\n  costBuy: \"価格\"\n  monthlyBuyLimit: \"月間購入上限\"\n  costSell: \"売値\"\n  transferTime: \"輸送時間\"\n  monthlySalary: \"給料／月\"\n  monthlyMaintenance: \"維持費／月\"\n#\n  SPECAB_NONE: \"なし\"\n  SPECAB_EXPLODEONDEATH: \"爆死する\"\n  SPECAB_BURNFLOOR: \"地面を燃やす\"\n  SPECAB_BURN_AND_EXPLODE: \"地面を焼き爆死\"\n#\n  MT_WALK: \"歩行\"\n  MT_FLY: \"飛行\"\n  MT_SLIDE: \"並行移動\"\n  MT_FLOAT: \"浮遊\"\n  MT_SINK: \"潜行\"\n#\n  TORSO_USE_GENDER: \"性別あり\"\n  TORSO_ALWAYS_MALE: \"男のみ\"\n  TORSO_ALWAYS_FEMALE: \"女のみ\"\n#\n  DRAWING_ROUTINE_SOLDIER_SECTOID: \"兵士、セクトイド\"\n  DRAWING_ROUTINE_FLOATER: \"フローター\"\n  DRAWING_ROUTINE_HWP: \"HWP\"\n  DRAWING_ROUTINE_CYBERDISC: \"サイバーディスク\"\n  DRAWING_ROUTINE_CIVILIAN_ETHEREAL: \"民間人、エセリアル\"\n  DRAWING_ROUTINE_SECTOPOD_REAPER: \"セクトイド、リーパー\"\n  DRAWING_ROUTINE_SNAKEMAN: \"スネークマン\"\n  DRAWING_ROUTINE_CHRYSSALID: \"クリサリド\"\n  DRAWING_ROUTINE_SILACOID: \"シリコイド\"\n  DRAWING_ROUTINE_CELATID: \"セラチド\"\n  DRAWING_ROUTINE_MUTON: \"ミュートン\"\n  DRAWING_ROUTINE_SWS: \"水中武器システム\"\n  DRAWING_ROUTINE_HALLUCINOID: \"ハルシノイド\"\n  DRAWING_ROUTINE_AQUANAUTS: \"潜水兵\"\n  DRAWING_ROUTINE_CALCINITE_AND_MORE: \"カルシナイト、深きもの、ロブスターマン、タソス\"\n  DRAWING_ROUTINE_AQUATOID: \"アクアトイド\"\n  DRAWING_ROUTINE_BIO_DRONE: \"バイオドローン\"\n  DRAWING_ROUTINE_TFTD_CIVILIAN_A: \"TFTDの民間人A と TFTDのゾンビ\"\n  DRAWING_ROUTINE_TFTD_CIVILIAN_B: \"TFTDの民間人B\"\n  DRAWING_ROUTINE_TENTACULAT: \"テンタクラット\"\n  DRAWING_ROUTINE_TRISCENE: \"トリシーン\"\n  DRAWING_ROUTINE_XARQUID: \"ザーカッド\"\n  DRAWING_ROUTINE_INVERTED_CYBERDISC: \"サイバーディスクの反転（推進機関を上面に）\"\n#\n  stats: \"ステータス修正\"\n  specab: \"特殊能力\"\n  movementType: \"移動方法\"\n  allowsRunning: \"走行を許可するか\"\n  allowsStrafing: \"水平移動を許可するか\"\n  allowsSneaking: \"隠密化を許可するか\"\n  allowsKneeling: \"膝付きを許可するか\"\n  allowsMoving: \"移送を許可するか\"\n  fearImmune: \"士気減衰なしにするか\"\n  bleedImmune: \"出血なしにするか\"\n  painImmune: \"スタンなしにするか\"\n  zombiImmune: \"ゾンビ化なしにするか\"\n  ignoresMeleeThreat: \"隣接時ペナルティを無視するか\"\n  createsMeleeThreat: \"隣接時ペナルティを発生させるか\"\n  builtInWeapons: \"内蔵アイテム\"\n  specialWeapon: \"特殊兵器\"\n  heatVision: \"視界が煙幕を透過\"\n  visibilityThroughFire: \"視界が火炎を透過\"\n  psiVision: \"Psi感知\"\n  psiCamouflage: \"Psi カモフラージュ\"\n  visibilityAtDay: \"日中の視認度\"\n  visibilityAtDark: \"夜間の視認度\"\n  camouflageAtDay: \"日中の偽装\"\n  camouflageAtDark: \"夜間の偽装\"\n  antiCamouflageAtDay: \"日中の偽装率逓減\"\n  antiCamouflageAtDark: \"夜間の偽装率逓減\"\n  psiDefence: \"Psi防御\"\n  meleeDodge: \"近接攻撃回避\"\n  meleeDodgeBackPenalty: \"近接回避ペナルティ\"\n  recovery: \"ターン毎の回復量：\"\n  time: \"時間\"\n  energy: \"スタミナ\"\n  morale: \"士気\"\n  health: \"HP\"\n  stun: \"気絶\"\n  mana: \"MP\"\n  units: \"互換ユニット\"\n  ranks: \"互換ランク\"\n  frontArmor: \"前面装甲\"\n  sideArmor: \"側面装甲\"\n  leftArmorDiff: \"装甲の差\"\n  rearArmor: \"背面装甲\"\n  underArmor: \"内装甲\"\n#\n  sizeX: \"サイズ： X\"\n  sizeY: \"サイズ： Y\"\n  buildCost: \"建造費\"\n  buildCostItems: \"建材：\"\n  buildTime: \"建造期間\"\n  monthlyCost: \"月間維持費\"\n  refundValue: \"返金額\"\n  requiresBaseFunc: \"該当業務が必要条件\"\n  provideBaseFunc: \"特定の業務内容を提供\"\n  forbiddenBaseFunc: \"無効な業務\"\n  lift: \"アクセスリフトの有無\"\n  hyper: \"ハイパーウェーブ解読器の有無\"\n  mind: \"マインドシールドの有無\"\n  mindPower: \"マインドシールドの強度\"\n  grav: \"重力シールドの有無\"\n  storage: \"倉庫の容量\"\n  personnel: \"居住区の容量\"\n  aliens: \"監獄の容量\"\n  crafts: \"格納庫の容量\"\n  labs: \"研究所の容量\"\n  workshops: \"ワークスペースの容量\"\n  psiLabs: \"Psi研究所の容量\"\n  trainingRooms: \"ジムの容量\"\n  sightRange: \"探索範囲\"\n  sightChance: \"目視する確率\"\n  radarRange: \"レーダー範囲\"\n  radarChance: \"レーダー捕捉率\"\n  defense: \"防御力\"\n  hitRatio: \"命中率\"\n  ammoNeeded: \"要弾薬\"\n  unifiedDamageFormula: \"新しいダメージタイプを用いるか\"\n  ammoItem: \"弾薬\"\n  maxAllowedPerBase: \"基地毎の最大数\"\n  manaRecoveryPerDay: \"一日のMP回復量\"\n  healthRecoveryPerDay: \"一日のHP回復量\"\n  sickBayAbsoluteBonus: \"医療ベイの空きボーナス\"\n  sickBayRelativeBonus: \"医療ベイの連結ボーナス\"\n  prisonType: \"収監タイプ\"\n  rightClickActionType: \"右クリックの動作\"\n  leavesBehindOnSell: \"戦地残存物の売却\"\n  removalTime: \"撤去時間\"\n  canBeBuiltOver: \"既存施設上への建造を可能にするか\"\n  upgradeOnly: \"アップグレードのみかどうか\"\n  buildOverFacilities: \"重複建造された施設\"\n#\n  BFRCT_DEFAULT: \"デフォルト設定\"\n  BFRCT_PRISON: \"エイリアン隔離室へ\"\n  BFRCT_ENGINEERING: \"製造ラインへ\"\n  BFRCT_RESEARCH: \"研究所へ\"\n  BFRCT_GYM: \"武術訓練へ\"\n  BFRCT_PSI_LABS: \"Psi研究所へ\"\n  BFRCT_BARRACKS: \"兵舎へ\"\n  BFRCT_GREY_MARKET: \"グレーマーケットへ\"\n  BFRCT_GEOSCAPE: \"ジオスケープへ\"\n#\n  costRent: \"賃貸費\"\n  soldiers: \"貨物スペース\"\n  maxUnitsLimit: \"最大貨物スペース\"\n  pilots: \"コクピット人員数\"\n  pilotMinStatsRequired: \"パイロットの必要最低ステータス値\"\n  pilotSoldierBonusesRequired: \"パイロットの条件\"\n  vehicles: \"HWP用スペース\"\n  onlyOneSoldierGroupAllowed: \"兵グループを一種のみにするか\"\n  allowedSoldierGroups: \"許可された兵グループ\"\n  allowedArmorGroups: \"許可された装甲グループ\"\n  limitArmorGroups: \"\"\n  maxHWPUnitsLimit: \"HWPの最大保有数\"\n  maxSmallSoldiers: \"小型兵士の最大数\"\n  maxLargeSoldiers: \"大型兵士の最大数\"\n  maxSmallVehicles: \"小型乗り物の最大数\"\n  maxLargeVehicles: \"大型乗り物の最大数\"\n  maxSmallUnits: \"小ユニットの最大数\"\n  maxLargeUnits: \"大ユニットの最大数\"\n  maxSoldiers: \"兵士の最大数\"\n  maxVehicles: \"乗り物の最大数\"\n  maxItems: \"装備品の搭載数\"\n  maxStorageSpace: \"倉庫の容量\"\n  maxAltitude: \"空戦高度の上限\"\n  weapons: \"兵器架数\"\n  weaponStrings: \"兵器の名\"\n  fixedWeapons: \"固定武器\"\n  weaponTypes: \"装着可能な兵器タイプ\"\n  damageMax: \"ダメージ容量\"\n  avoidBonus: \"回避ボーナス (固定)\"\n  avoidBonus2: \"ダメージボーナス (固定)\"\n  powerBonus: \"出力ボーナス (固定)\"\n  hitBonus: \"命中ボーナス (固定)\"\n  fuelMax: \"燃料搭載量\"\n  speedMax: \"最大速度\"\n  accel: \"加速度\"\n  shieldCapacity: \"シールド容量\"\n  shieldRecharge: \"シールドの再充填 (戦闘)\"\n  shieldRechargeInGeoscape: \"シールドの再充填 (球形)\"\n  shieldBleedThrough: \"シールドの形成速度\"\n  shieldRechargedAtBase: \"シールドの再充填 (基地)\"\n  refuelItem: \"燃料用品\"\n  refuelRate: \"給油速度\"\n  repairRate: \"修理速度\"\n  spacecraft: \"最新鋭機を導入するか\"\n  allowLanding: \"着陸を許可するか\"\n  notifyWhenRefueled: \"燃料補給完了時の報告をするか\"\n  autoPatrol: \"自動パトロールをするか\"\n  undetectable: \"発見されない様にするか\"\n  patrolWithoutFuel: \"\"\n  keepCraftAfterFailedMission: \"空挺兵を使用するか\"\n  _calculatedValues: \"算出結果\"\n  _maxRange: \"最大レンジ\"\n  _minRange: \"最短レンジ\"\n  _avgRange: \"平均レンジ\"\n#\n  hunterKillerPercentage: \"ハンターキラーとの遭遇率\"\n  huntMode: \"ハントモード\"\n  huntSpeed: \"ハント速度\"\n  huntBehavior: \"ハンティングの挙動\"\n  range: \"範囲\"\n  reload: \"再装填時間\"\n  breakOffTime: \"離着陸時間\"\n  score: \"スコア\"\n  missionScore: \"ミッションスコア\"\n  craftCustomDeploy: \"UFO目撃現場への対応\"\n  missionCustomDeploy: \"ミッションへの対応\"\n  _escapeCountdown: \"脱出時のカウントダウン\"\n  _fireRate: \"連射速度\"\n  _averageDPM: \"平均与ダメ/分\"\n#\n  HM_INTERCEPTORS: \"インターセプターをつけ狙う\"\n  HM_TRANSPORTS: \"兵員輸送機をつけ狙う\"\n  HM_RANDOM: \"ランダム\"\n#\n  HB_FLEE: \"形勢悪化時は逃亡\"\n  HB_KAMIKAZE: \"前線死守\"\n  HB_RANDOM: \"ランダム\"\n#\n  tractorBeamPower: \"牽引ビームのパワー\"\n  damage: \"ダメージ\"\n  shieldDamageModifier: \"シールドダメージの修正\"\n  accuracy: \"攻撃成功率\"\n  reloadCautious: \"リロード (警戒)\"\n  reloadStandard: \"リロード (通常)\"\n  reloadAggressive: \"リロード (緊急)\"\n  launcher: \"ランチャー用アイテム\"\n  weaponType: \"武器のタイプ\"\n  clip: \"弾倉\"\n  ammoMax: \"バラ弾\"\n  rearmRate: \"再武装の速度\"\n  bulletSaving: \"弾薬の節約をするか\"\n  _damageRange: \"ダメージ幅\"\n  _damageRangeBasic: \"ダメージ幅 (基本)\"\n  _averageTotalDamage: \"平均総合ダメージ\"\n#\n  allowPiloting: \"\"\n  costSalary: \"\"\n  costSalarySquaddie: \"\"\n  costSalarySergeant: \"\"\n  costSalaryCaptain: \"\"\n  costSalaryColonel: \"\"\n  costSalaryCommander: \"\"\n#\n  race: \"\"\n  rank: \"\"\n  livingWeapon: \"\"\n  meleeWeapon: \"近接武器\"\n  psiWeapon: \"\"\n  _builtInWeaponSets: \"\"\n  _weightedBuiltInWeaponSets: \"\"\n  spawnUnit: \"\"\n  _capturable: \"\"\n  capturable: \"\"\n  canSurrender: \"\"\n  autoSurrender: \"\"\n  spotter: \"\"\n  sniper: \"\"\n"
  },
  {
    "path": "bin/common/Language/Technical/ko.yml",
    "content": "ko:\n#=================== Menu ===================\n#TestState.cpp\n  STR_BAD_NODES: \"RMP 파일 내부의 잘못된 노드\"\n  STR_BAD_NODES_DESC: \"지도 경계 바깥의 노드에 대해 RMP 파일을 확인합니다.{NEWLINE}이건 어떠한 충돌도 일으키지 않을 것이나, 그건 게임에서 무시될 것이므로, 의도대로 동작하지 않을 것입니다.\"\n#\n  STR_MCD_CHECK: \"MCD 확인\"\n  STR_MCD_CHECK_DESC: \"이동 비용이 0인 바닥 물체에 대해 MCD 파일을 확인합니다; 또한 무효인 DieMCD/AltMCD 참조도 확인합니다; 또한 무효인 LOFTemps도 확인합니다.\"\n#\n  STR_PALETTE_CHECK: \"팔레트 통일\"\n  STR_PALETTE_CHECK_DESC: \"모드의 이미지에 쓰인 팔레트를 공식 팔레트와 맞추도록 시도하고 100% 일치하지 않는 어떠한 이미지도 보고합니다.\"\n#\n  STR_SCRIPT_TAGS: \"스크립트 태그 추출\"\n  STR_SCRIPT_TAGS_DESC: \"스크립트 태그를 CSV 형식으로 추출합니다.\"\n#\n  STR_MAP_RESOURCES: \"지도 자원 확인\"\n  STR_MAP_RESOURCES_DESC: \"빠졌거나 사용되지 않는 지도 관련 파일 및 룰셋을 확인합니다.\"\n#\n  STR_CHECKING_TERRAIN: \"지형 확인 중...\"\n  STR_CHECKING_UFOS: \"UFO 확인 중...\"\n  STR_CHECKING_CRAFT: \"기체 확인 중...\"\n#\n  BACKPALS.DAT: \"BACKPALS.DAT\"\n  PAL_GEOSCAPE: \"PAL_GEOSCAPE\"\n  PAL_BASESCAPE: \"PAL_BASESCAPE\"\n  PAL_GRAPHS: \"PAL_GRAPHS\"\n  PAL_UFOPAEDIA: \"PAL_UFOPAEDIA\"\n  PAL_BATTLEPEDIA: \"PAL_BATTLEPEDIA\"\n  PAL_BATTLESCAPE: \"PAL_BATTLESCAPE\"\n  PAL_BATTLESCAPE_1: \"PAL_BATTLESCAPE_1\"\n  PAL_BATTLESCAPE_2: \"PAL_BATTLESCAPE_2\"\n  PAL_BATTLESCAPE_3: \"PAL_BATTLESCAPE_3\"\n#=================== Ufopaedia ===================\n#StatsForNerdsState.cpp\n  BT_NONE: \"없음\"\n  BT_FIREARM: \"화기\"\n  BT_AMMO: \"탄약\"\n  BT_MELEE: \"격투 무기\"\n  BT_GRENADE: \"수류탄\"\n  BT_PROXIMITYGRENADE: \"근접 수류탄\"\n  BT_MEDIKIT: \"메디킷\"\n  BT_SCANNER: \"동작 감지기\"\n  BT_MINDPROBE: \"마인드 프로브\"\n  BT_PSIAMP: \"사이오닉 증폭기\"\n  BT_FLARE: \"조명기\"\n  BT_CORPSE: \"시신/시체\"\n#\n  DRT_DEFAULT: \"바닐라 기본\"\n  DRT_UFO: \"0-200% 분포\"\n  DRT_TFTD: \"50-150% 분포\"\n  DRT_FLAT: \"고정 피해\"\n  DRT_FIRE: \"특별 불 피해\"\n  DRT_NONE: \"무피해\"\n  DRT_UFO_WITH_TWO_DICE: \"0-200% 분포(두 번 굴림)\"\n  DRT_EASY: \"50-200% 분포\"\n  DRT_STANDARD: \"표준 피해 범위\"\n  DRT_EXPLOSION: \"폭발 피해 범위\"\n#\n  BFT_NONE: \"없음\"\n  BFT_INSTANT: \"즉시\"\n  BFT_SET: \"수동으로 설정\"\n  BFT_FIXED: \"고정\"\n#\n  BMT_NORMAL: \"표준(다목적)\"\n  BMT_HEAL: \"치료\"\n  BMT_STIMULANT: \"각성제\"\n  BMT_PAINKILLER: \"진통제\"\n#\n  ETM_DEFAULT: \"기본\"\n  ETM_MELEE_100: \"격투술\"\n  ETM_MELEE_50: \"격투술(50% 기회)\"\n  ETM_MELEE_33: \"격투술(33% 기회)\"\n  ETM_FIRING_100: \"사격술\"\n  ETM_FIRING_50: \"사격술(50% 기회)\"\n  ETM_FIRING_33: \"사격술(33% 기회)\"\n  ETM_THROWING_100: \"투척술\"\n  ETM_THROWING_50: \"투척술(50% 기회)\"\n  ETM_THROWING_33: \"투척술(33% 기회)\"\n  ETM_FIRING_AND_THROWING: \"사격술 및 투척술\"\n  ETM_FIRING_OR_THROWING: \"사격술 또는 투척술\"\n  ETM_REACTIONS: \"반응\"\n  ETM_REACTIONS_AND_MELEE: \"반응 및 격투술\"\n  ETM_REACTIONS_AND_FIRING: \"반응 및 사격술\"\n  ETM_REACTIONS_AND_THROWING: \"반응 및 투척술\"\n  ETM_REACTIONS_OR_MELEE: \"반응 또는 격투술\"\n  ETM_REACTIONS_OR_FIRING: \"반응 또는 사격술\"\n  ETM_REACTIONS_OR_THROWING: \"반응 또는 투척술\"\n  ETM_BRAVERY: \"용기\"\n  ETM_BRAVERY_2X: \"용기(x2)\"\n  ETM_BRAVERY_AND_REACTIONS: \"용기 및 반응\"\n  ETM_BRAVERY_OR_REACTIONS: \"용기 또는 반응\"\n  ETM_BRAVERY_OR_REACTIONS_2X: \"용기 또는 반응(x2)\"\n  ETM_PSI_STRENGTH: \"사이오닉 강도\"\n  ETM_PSI_STRENGTH_2X: \"사이오닉 강도(x2)\"\n  ETM_PSI_SKILL: \"사이오닉 기술\"\n  ETM_PSI_SKILL_2X: \"사이오닉 기술(x2)\"\n  ETM_PSI_STRENGTH_AND_SKILL: \"사이오닉 강도 및 기술\"\n  ETM_PSI_STRENGTH_AND_SKILL_2X: \"사이오닉 강도 및 기술(x2)\"\n  ETM_PSI_STRENGTH_OR_SKILL: \"사이오닉 강도 또는 기술\"\n  ETM_PSI_STRENGTH_OR_SKILL_2X: \"사이오닉 강도 또는 기술(x2)\"\n  ETM_NOTHING: \"훈련되는 능력치 없음\"\n#\n  battleType: \"물품 유형\"\n  experienceTrainingMode: \"경험치 모드\"\n  manaExperience: \"마나 경험치\"\n  arcingShot: \"곡사 무기?\"\n  isFireExtinguisher: \"소화기?\"\n  explodeInventory: \"인벤토리 안에서 폭발?\"\n  waypoints: \"최대 경유지\"\n  sprayWaypoints: \"난사 경유지\"\n#\n  shotgunPellets: \"자탄 숫자\"\n  shotgunBehavior: \"산탄총 특성\"\n  shotgunSpread: \"산탄총 분산\"\n  shotgunChoke: \"산탄총 응집계수\"\n#\n  underwaterOnly: \"수중 전용?\"\n  landOnly: \"지상 전용?\"\n  psiRequired: \"사이오닉 기술 요구?\"\n  targetMatrix: \"물품 표적\"\n  convertToCivilian: \"민간인으로 변환?\"\n  manaRequired: \"마나 요구?\"\n  LOSRequired: \"시선 요구?\"\n#\n  noLOSAccuracyPenalty: \"시야 밖 페널티 보정계수\"\n  kneelBonus: \"무릎쏴 보너스 보정계수\"\n  twoHanded: \"양손 물품?\"\n  blockBothHands: \"쌍수 사용 불가?\"\n  oneHandedPenalty: \"한 손 이용 페널티\"\n#\n  minRange: \"최소 사거리\"\n  maxRange: \"최대 사거리\"\n  aimRange: \"조준사격 사거리\"\n  autoRange: \"자동사격 사거리\"\n  snapRange: \"지향사격 사거리\"\n  dropoff: \"정확도 하락/타일\"\n#\n  accuracyMultiplier: \"기본 사격 정확도\"\n  accuracyAimed: \"조준사격 정확도 보정계수\"\n  accuracyAuto: \"자동사격 정확도 보정계수\"\n  accuracySnap: \"지향사격 정확도 보정계수\"\n  costAimed: \"조준사격 비용\"\n  costAuto: \"자동사격 비용\"\n  costSnap: \"지향사격 비용\"\n#\n  meleeMultiplier: \"기본 격투 정확도\"\n  accuracyMelee: \"격투 정확도 보정계수\"\n  costMelee: \"격투 비용\"\n#\n  psiAttackName: \"사이오닉 공격 이름\"\n  accuracyUse: \"행동 정확도 보정계수\"\n  accuracyMindControl: \"정신 지배 정확도 보정계수\"\n  accuracyPanic: \"공포 유발 정확도 보정계수\"\n  costUse: \"행동 비용\"\n  costMindcontrol: \"정신 지배 비용\"\n  costPanic: \"공포 유발 비용\"\n#\n  weight: \"무게\"\n  throwRange: \"최대 투척 사거리(공기중)\"\n  underwaterThrowRange: \"최대 투척 사거리(수중)\"\n  throwDropoffRange: \"투척 사거리(공기중)\"\n  underwaterThrowDropoffRange: \"투척 사거리(수중)\"\n  throwDropoff: \"투척 정확도 하락/타일\"\n  throwMultiplier: \"기본 투척 정확도\"\n  accuracyThrow: \"투척 정확도 보정계수\"\n  costThrow: \"투척 비용\"\n  costPrime: \"신관 설정 비용\"\n  costUnprime: \"신관 해제 비용\"\n#\n  closeQuartersMultiplier: \"기본 CQC 정확도\"\n  accuracyCloseQuarters: \"CQC 정확도 보정계수\"\n#\n  damageType: \"피해 유형\"\n  power: \"위력\"\n  powerRangeReduction: \"위력 감소/타일\"\n  powerRangeThreshold: \"위력 감소 기준거리\"\n  damageBonus: \"피해 보너스\"\n  blastRadius: \"폭발 반경\"\n  damageAlter: \"추가 피해 정보:\"\n  meleeType: \"격투 피해 유형\"\n  meleePower: \"격투 위력\"\n  meleeBonus: \"격투 위력 보너스\"\n  meleeAlter: \"추가 격투 정보:\"\n  FixRadius: \"폭발 반경\"\n  RandomType: \"계산 유형\"\n  FireBlastCalc: \"원본 불 효과?\"\n  IgnoreDirection: \"방향 무시\"\n  IgnoreSelfDestruct: \"자폭 무시\"\n  IgnorePainImmunity: \"기절 면역 무시\"\n  IgnoreNormalMoraleLose: \"원본 사기 손실 무시\"\n  IgnoreOverKill: \"시체 파손 무시\"\n  ArmorEffectiveness: \"장갑 효율\"\n  RadiusEffectiveness: \"동적 폭발 반경 보정계수\"\n  RadiusReduction: \"거리당 피해 감소\"\n  FireThreshold: \"점화 기준점\"\n  SmokeThreshold: \"연막 형성 기준점\"\n#\n  ToArmorPre: \"장갑 사전 피해 보정계수\"\n  RandomArmorPre: \"무작위 장갑 사전 피해?\"\n  ToArmor: \"장갑 피해 보정계수\"\n  RandomArmor: \"무작위 장갑 피해?\"\n  ToHealth: \"체력 피해 보정계수\"\n  RandomHealth: \"무작위 체력 피해?\"\n  ToStun: \"기절 피해 보정계수\"\n  RandomStun: \"무작위 기절 피해?\"\n  ToWound: \"치명상 개수 보정계수\"\n  RandomWound: \"바닐라 치명상 무작위 사용?\"\n  ToTime: \"행동력 피해 보정계수\"\n  RandomTime: \"무작위 행동력 피해?\"\n  ToEnergy: \"기력 피해 보정계수\"\n  RandomEnergy: \"무작위 기력 피해?\"\n  ToMorale: \"사기 피해 보정계수\"\n  RandomMorale: \"무작위 사기 피해?\"\n  ToItem: \"물품 피해 보정계수\"\n  RandomItem: \"무작위 물품 피해?\"\n  ToMana: \"마나 피해 보정계수\"\n  RandomMana: \"무작위 마나 피해?\"\n  ToTile: \"지형 피해 보정계수\"\n  RandomTile: \"무작위 지형 피해?\"\n  TileDamageMethod: \"지형 피해 방식\"\n  TileDamageLimit: \"지형 피해 한도\"\n#\n  confAimed: \"조준사격 행동:\"\n  confAuto: \"자동사격 행동:\"\n  confSnap: \"지향사격 행동:\"\n  confMelee: \"격투 행동:\"\n  shots: \"행동 당 사격 수\"\n  spendPerShot: \"사격 당 탄 소모:\"\n  followProjectiles: \"발사체 따라감?\"\n  name: \"행동 명칭\"\n  shortName: \"행동 약칭\"\n  ammoSlot: \"사용된 탄약 슬롯\"\n  ammoZombieUnitChanceOverride: \"좀비화 확률\"\n  ammoSpawnUnitChanceOverride: \"유닛 발생 확률\"\n  ammoSpawnItemChanceOverride: \"물품 발생 확률\"\n  arcing: \"곡사 무기?\"\n#\n  clipSize: \"탄창 크기\"\n  isAmmoRechargeable: \"탄약 재충전 가능?\"\n#\n  primaryAmmo: \"주 탄약 칸:\"\n  compatibleAmmo: \"호환 탄종\"\n  tuLoad: \"장탄 비용\"\n  tuUnload: \"제거 비용\"\n  ammo[1]: \"추가 탄약 칸 #1:\"\n  ammo[2]: \"추가 탄약 칸 #2:\"\n  ammo[3]: \"추가 탄약 칸 #3:\"\n#\n  armor: \"장갑\"\n#\n  medikitType: \"메디킷 유형\"\n  painKillerActionName: \"진통제 사용 행동 명칭\"\n  stimulantActionName: \"각성제 사용 행동 명칭\"\n  healActionName: \"치료 행동 명칭\"\n  medikitActionName: \"메디킷 행동 명칭\"\n  medikitTargetSelf: \"메디킷 자가 사용 가능?\"\n  medikitTargetImmune: \"출혈 면역에 메디킷?\"\n  medikitTargetMatrix: \"메디킷 표적\"\n  isConsumable: \"사용 시 증발?\"\n  painKiller: \"진통제 사용 횟수\"\n  heal: \"치료 사용 횟수\"\n  stimulant: \"각성제 사용 횟수\"\n  woundRecovery: \"치료하는 치명상 수\"\n  healthRecovery: \"체력 회복량\"\n  stunRecovery: \"기절 회복량\"\n  energyRecovery: \"기력 회복량\"\n  manaRecovery: \"마나 회복량\"\n  moraleRecovery: \"사기 회복량\"\n  painKillerRecovery: \"진통제 강도\"\n#\n  requires: \"요구되는 기술\"\n  requiresBuy: \"구매 시 요구되는 기술\"\n  requiresBuyBaseFunc: \"구매 시 요구되는 기능\"\n  requiresBuyCountry: \"요구되는 동맹국\"\n  requiresAward: \"요구되는 포상\"\n  requiresBonus: \"요구되는 보너스\"\n  categories: \"분류\"\n  supportedInventorySections: \"인벤토리 칸\"\n#\n  size: \"크기\"\n  costBuy: \"구매 비용\"\n  monthlyBuyLimit: \"월 구매 한도\"\n  costSell: \"판매 가격\"\n  transferTime: \"이송에 드는 시간\"\n  monthlySalary: \"급여/월\"\n  monthlyMaintenance: \"유지 비용/월\"\n#\n  SPECAB_NONE: \"없음\"\n  SPECAB_EXPLODEONDEATH: \"죽을 때 폭발\"\n  SPECAB_BURNFLOOR: \"바닥을 태움\"\n  SPECAB_BURN_AND_EXPLODE: \"바닥을 태우고 죽을 때 폭발\"\n#\n  MT_WALK: \"걷기\"\n  MT_FLY: \"날기\"\n  MT_SLIDE: \"미끄러지기\"\n  MT_FLOAT: \"떠다니기\"\n  MT_SINK: \"가라앉기\"\n#\n  TORSO_USE_GENDER: \"성별 사용\"\n  TORSO_ALWAYS_MALE: \"항상 남성\"\n  TORSO_ALWAYS_FEMALE: \"항상 여성\"\n#\n  DRAWING_ROUTINE_SOLDIER_SECTOID: \"섹토이드, 병사\"\n  DRAWING_ROUTINE_FLOATER: \"플로터\"\n  DRAWING_ROUTINE_HWP: \"중화기 차량\"\n  DRAWING_ROUTINE_CYBERDISC: \"사이버디스크\"\n  DRAWING_ROUTINE_CIVILIAN_ETHEREAL: \"민간인, 이더리얼\"\n  DRAWING_ROUTINE_SECTOPOD_REAPER: \"섹토포드, 리퍼\"\n  DRAWING_ROUTINE_SNAKEMAN: \"스네이크맨\"\n  DRAWING_ROUTINE_CHRYSSALID: \"크리살리드\"\n  DRAWING_ROUTINE_SILACOID: \"실라코이드\"\n  DRAWING_ROUTINE_CELATID: \"셀라티드\"\n  DRAWING_ROUTINE_MUTON: \"뮤톤\"\n  DRAWING_ROUTINE_SWS: \"무장 잠수정\"\n  DRAWING_ROUTINE_HALLUCINOID: \"할루시노이드\"\n  DRAWING_ROUTINE_AQUANAUTS: \"잠수요원\"\n  DRAWING_ROUTINE_CALCINITE_AND_MORE: \"캘시나이트, 딥원, 길맨, 랍스터맨, 타소쓰\"\n  DRAWING_ROUTINE_AQUATOID: \"아쿠아토이드\"\n  DRAWING_ROUTINE_BIO_DRONE: \"바이오드론\"\n  DRAWING_ROUTINE_TFTD_CIVILIAN_A: \"TFTD A형 민간인 및 TFTD 좀비\"\n  DRAWING_ROUTINE_TFTD_CIVILIAN_B: \"TFTD B형 민간인\"\n  DRAWING_ROUTINE_TENTACULAT: \"텐타쿨러트\"\n  DRAWING_ROUTINE_TRISCENE: \"트라이신\"\n  DRAWING_ROUTINE_XARQUID: \"자퀴드\"\n  DRAWING_ROUTINE_INVERTED_CYBERDISC: \"반전된 사이버디스크(추진 애니메이션이 위에 있음)\"\n#\n  stats: \"능력치 보정계수\"\n  specab: \"특수 능력\"\n  movementType: \"이동 유형\"\n  allowsRunning: \"달리기 허용?\"\n  allowsStrafing: \"게걸음 허용?\"\n  allowsSneaking: \"살금살금 걷기 허용?\"\n  allowsKneeling: \"무릎꿇기 허용?\"\n  allowsMoving: \"이동 허용?\"\n  fearImmune: \"사기 손실 면역?\"\n  bleedImmune: \"치명상 면역?\"\n  painImmune: \"기절 면역?\"\n  zombiImmune: \"좀비화 면역?\"\n  ignoresMeleeThreat: \"CQC 무시?\"\n  createsMeleeThreat: \"CQC 가능?\"\n  builtInWeapons: \"내장된 물품\"\n  specialWeapon: \"특별 무기\"\n  heatVision: \"연막 하 시야\"\n  visibilityThroughFire: \"화염 하 시야\"\n  psiVision: \"사이오닉 감지\"\n  psiCamouflage: \"사이오닉 위장\"\n  visibilityAtDay: \"주간 시야\"\n  visibilityAtDark: \"야간 시야\"\n  camouflageAtDay: \"주간 위장\"\n  camouflageAtDark: \"야간 위장\"\n  antiCamouflageAtDay: \"주간 위장 무효화\"\n  antiCamouflageAtDark: \"야간 위장 무효화\"\n  psiDefence: \"사이오닉 방어\"\n  meleeDodge: \"격투 회피\"\n  meleeDodgeBackPenalty: \"격투 회피 페널티\"\n  recovery: \"턴 당 회복:\"\n  time: \"행동력\"\n  energy: \"기력\"\n  morale: \"사기\"\n  health: \"체력\"\n  stun: \"기절\"\n  mana: \"마나\"\n  units: \"갑옷 착용 유닛 유형\"\n  ranks: \"갑옷 착용 요구 계급\"\n  frontArmor: \"전면 장갑\"\n  sideArmor: \"측면 장갑\"\n  leftArmorDiff: \"좌측 장갑 편차\"\n  rearArmor: \"후면 장갑\"\n  underArmor: \"하부 장갑\"\n#\n  sizeX: \"X축 크기\"\n  sizeY: \"Y축 크기\"\n  buildCost: \"건설 비용\"\n  buildCostItems: \"건설 재료:\"\n  buildTime: \"건설 기간\"\n  monthlyCost: \"월 비용\"\n  refundValue: \"환불 가격\"\n  requiresBaseFunc: \"요구 기능\"\n  provideBaseFunc: \"제공 기능\"\n  forbiddenBaseFunc: \"금지 기능\"\n  lift: \"출입 승강기?\"\n  hyper: \"하이퍼웨이브 해석기?\"\n  mind: \"정신 방어막?\"\n  mindPower: \"정신 방어막 위력\"\n  grav: \"중력 방어막?\"\n  storage: \"저장 공간\"\n  personnel: \"생활 공간\"\n  aliens: \"수용 공간\"\n  crafts: \"격납고 공간\"\n  labs: \"연구 공간\"\n  workshops: \"작업 공간\"\n  psiLabs: \"사이오닉 연구실 공간\"\n  trainingRooms: \"훈련 공간\"\n  sightRange: \"기지 탐색 범위\"\n  sightChance: \"기지 탐색 확률\"\n  radarRange: \"레이더 탐색 범위\"\n  radarChance: \"레이더 탐색 확률\"\n  defense: \"방위력\"\n  hitRatio: \"명중률\"\n  ammoNeeded: \"필요 탄약\"\n  unifiedDamageFormula: \"새로운 피해 공식?\"\n  ammoItem: \"탄약 물품\"\n  maxAllowedPerBase: \"기지 당 허용되는 최대 개수\"\n  manaRecoveryPerDay: \"매일 회복되는 마나\"\n  healthRecoveryPerDay: \"매일 회복되는 체력\"\n  sickBayAbsoluteBonus: \"의무실 절대 회복량 보너스\"\n  sickBayRelativeBonus: \"의무실 상대 회복량 보너스\"\n  prisonType: \"감옥 유형\"\n  rightClickActionType: \"우클릭 행동\"\n  leavesBehindOnSell: \"매각 시 남겨지는 시설\"\n  removalTime: \"제거 시간\"\n  canBeBuiltOver: \"개수 가능?\"\n  upgradeOnly: \"개수 전용?\"\n  buildOverFacilities: \"개수 대상 시설\"\n#\n  BFRCT_DEFAULT: \"원본 기본\"\n  BFRCT_PRISON: \"외계인 격리실 관리 화면으로 이동\"\n  BFRCT_ENGINEERING: \"제조 화면으로 이동\"\n  BFRCT_RESEARCH: \"연구 화면으로 이동\"\n  BFRCT_GYM: \"군사 훈련 화면으로 이동\"\n  BFRCT_PSI_LABS: \"사이오닉 연구실 화면으로 이동\"\n  BFRCT_BARRACKS: \"병영 화면으로 이동\"\n  BFRCT_GREY_MARKET: \"암시장 화면으로 이동\"\n  BFRCT_GEOSCAPE: \"지구 화면으로 이동\"\n#\n  costRent: \"대여 비용\"\n  soldiers: \"병력 수용량\"\n  maxUnitsLimit: \"최대 병력 수용량\"\n  pilots: \"조종석 크기\"\n  pilotMinStatsRequired: \"조종사 최소 능력치\"\n  pilotSoldierBonusesRequired: \"조종사 요구사항\"\n  vehicles: \"중화기 차량 수용량\"\n  onlyOneSoldierGroupAllowed: \"단일 유형 병사만 허용?\"\n  allowedSoldierGroups: \"허용 병사 그룹\"\n  allowedArmorGroups: \"허용 갑옷 그룹\"\n  limitArmorGroups: \"제한되는 갑옷 그룹\"\n  maxHWPUnitsLimit: \"최대 중화기 차량 수용량\"\n  maxSmallSoldiers: \"최대 소형 병사\"\n  maxLargeSoldiers: \"최대 대형 병사\"\n  maxSmallVehicles: \"최대 소형 차량\"\n  maxLargeVehicles: \"최대 대형 차량\"\n  maxSmallUnits: \"최대 소형 유닛\"\n  maxLargeUnits: \"최대 대형 유닛\"\n  maxSoldiers: \"최대 병사\"\n  maxVehicles: \"최대 차량\"\n  maxItems: \"물품 개수 한도\"\n  maxStorageSpace: \"물품 규모 한도\"\n  maxAltitude: \"공중전 고도 제한\"\n  weapons: \"무장 공간\"\n  weaponStrings: \"무장 이름\"\n  fixedWeapons: \"고정 무기\"\n  weaponTypes: \"허용되는 무기 유형\"\n  damageMax: \"내구도\"\n  avoidBonus: \"회피 보너스(고정)\"\n  avoidBonus2: \"회패 보너스 2(고정)\"\n  powerBonus: \"위력 보너스(고정)\"\n  hitBonus: \"명중 보너스(고정)\"\n  fuelMax: \"연료 용량\"\n  speedMax: \"최대 속도\"\n  accel: \"가속력\"\n  shieldCapacity: \"방어막 용량\"\n  shieldRecharge: \"방어막 재충전(교전)\"\n  shieldRechargeInGeoscape: \"방어막 재충전(지구 화면)\"\n  shieldBleedThrough: \"방어막 소실 시 잔여 피해 흡수율\"\n  shieldRechargedAtBase: \"방어막 재충전(기지)\"\n  refuelItem: \"급유 물품\"\n  refuelRate: \"급유 속도\"\n  repairRate: \"수리 속도\"\n  spacecraft: \"최종 기체?\"\n  allowLanding: \"착륙 허용?\"\n  notifyWhenRefueled: \"급유 완료 통지?\"\n  autoPatrol: \"자동 순찰?\"\n  undetectable: \"탐지불가?\"\n  patrolWithoutFuel: \"순찰 시 연료 소모 없음?\"\n  keepCraftAfterFailedMission: \"병력 강하?\"\n  _calculatedValues: \"산출된 값\"\n  _maxRange: \"최대 작전행동반경\"\n  _minRange: \"최소 작전행동반경\"\n  _avgRange: \"평균 작전행동반경\"\n#\n  hunterKillerPercentage: \"헌터-킬러 확률\"\n  huntMode: \"사냥 모드\"\n  huntSpeed: \"사냥 속도\"\n  huntBehavior: \"사냥 특성\"\n  range: \"사거리\"\n  reload: \"재장전 시간\"\n  breakOffTime: \"교전 이탈 시간\"\n  score: \"평점\"\n  missionScore: \"임무 평점\"\n  craftCustomDeploy: \"UFO 현장 배치\"\n  missionCustomDeploy: \"임무 현장 배치\"\n  _escapeCountdown: \"탈출 카운트다운\"\n  _fireRate: \"발사 속도\"\n  _averageDPM: \"평균 DPM\"\n#\n  HM_INTERCEPTORS: \"요격기 사냥 선호\"\n  HM_TRANSPORTS: \"수송기 사냥 선호\"\n  HM_RANDOM: \"무작위\"\n#\n  HB_FLEE: \"불리할 시 도주\"\n  HB_KAMIKAZE: \"격추될 때까지 교전\"\n  HB_RANDOM: \"무작위\"\n#\n  tractorBeamPower: \"트랙터 빔 위력\"\n  damage: \"피해\"\n  shieldDamageModifier: \"방어막 피해 보정계수\"\n  accuracy: \"명중률\"\n  reloadCautious: \"발사 간격(소극적)\"\n  reloadStandard: \"발사 간격(표준적)\"\n  reloadAggressive: \"발사 간격(적극적)\"\n  launcher: \"발사기 물품\"\n  weaponType: \"무기 유형\"\n  clip: \"탄창 물품\"\n  ammoMax: \"탄수\"\n  rearmRate: \"재무장 속도\"\n  bulletSaving: \"총알 절약?\"\n  _damageRange: \"피해 범위\"\n  _damageRangeBasic: \"피해 범위(기본)\"\n  _averageTotalDamage: \"평균 총 피해\"\n#\n  allowPiloting: \"조종 허용?\"\n  costSalary: \"급여\"\n  costSalarySquaddie: \"보너스(일병)\"\n  costSalarySergeant: \"보너스(하사)\"\n  costSalaryCaptain: \"보너스(대위)\"\n  costSalaryColonel: \"보너스(대령)\"\n  costSalaryCommander: \"보너스(준장)\"\n#\n  race: \"종족\"\n  rank: \"계급\"\n  livingWeapon: \"생체 무기인가?\"\n  meleeWeapon: \"격투 무기\"\n  psiWeapon: \"사이오닉 무기\"\n  _builtInWeaponSets: \"무기 세트?\"\n  _weightedBuiltInWeaponSets: \"다른 무기 세트?\"\n  spawnUnit: \"죽을 때 생성\"\n  _capturable: \"포획 가능?\"\n  capturable: \"포획 가능(플래그)\"\n  canSurrender: \"항복 가능?\"\n  autoSurrender: \"자동 항복?\"\n  spotter: \"감지자 지속기간\"\n  sniper: \"저격수 가능성\"\n"
  },
  {
    "path": "bin/common/Language/Technical/pl.yml",
    "content": "pl:\n#=================== Menu ===================\n#TestState.cpp\n  STR_BAD_NODES: \"Błędne węzły w plikach RMP\"\n  STR_BAD_NODES_DESC: \"Sprawdź pliki RMP pod kątem węzłów leżących poza granicami mapy.{NEWLINE}Takie węzły NIE spowodują zawieszenia gry, ale nie będą brane pod uwagę przez grę, a więc nie będą działały.\"\n#\n  STR_MCD_CHECK: \"Testy MCD\"\n  STR_MCD_CHECK_DESC: \"Przeszukuje pliki MCD pod kątem obiektów podłogowych o zerowym koszcie ruchu; wykrywa też nieprawidłowe odniesienia DieMCD/AltMCD; wykrywa też nieprawidłowe LOFTemps.\"\n#\n  STR_PALETTE_CHECK: \"Dopasowanie palet\"\n  STR_PALETTE_CHECK_DESC: \"Sprawdza dopasowanie palet obrazów w modach do oficjalnych palet gry i zgłasza wszystkie obrazy, które nie są w 100% zgodne.\"\n#\n  STR_SCRIPT_TAGS: \"Eksport znaczników skryptów\"\n  STR_SCRIPT_TAGS_DESC: \"Eksportuje znaczniki skryptów w formacie CSV.\"\n#\n  STR_MAP_RESOURCES: \"Sprawdzanie zasobów map\"\n  STR_MAP_RESOURCES_DESC: \"Wyszukuje brakujące lub nieużywane pliki i wpisy związane z terenem.\"\n#\n  STR_CHECKING_TERRAIN: \"Sprawdzam teren...\"\n  STR_CHECKING_UFOS: \"Sprawdzam UFA...\"\n  STR_CHECKING_CRAFT: \"Sprawdzam pojazdy...\"\n#\n  BACKPALS.DAT: \"BACKPALS.DAT\"\n  PAL_GEOSCAPE: \"PAL_GEOSCAPE\"\n  PAL_BASESCAPE: \"PAL_BASESCAPE\"\n  PAL_GRAPHS: \"PAL_GRAPHS\"\n  PAL_UFOPAEDIA: \"PAL_UFOPAEDIA\"\n  PAL_BATTLEPEDIA: \"PAL_BATTLEPEDIA\"\n  PAL_BATTLESCAPE: \"PAL_BATTLESCAPE\"\n  PAL_BATTLESCAPE_1: \"PAL_BATTLESCAPE_1\"\n  PAL_BATTLESCAPE_2: \"PAL_BATTLESCAPE_2\"\n  PAL_BATTLESCAPE_3: \"PAL_BATTLESCAPE_3\"\n#=================== Ufopaedia ===================\n#StatsForNerdsState.cpp\n  BT_NONE: \"Brak\"\n  BT_FIREARM: \"Broń strzelecka\"\n  BT_AMMO: \"Amunicja\"\n  BT_MELEE: \"Broń biała\"\n  BT_GRENADE: \"Granat\"\n  BT_PROXIMITYGRENADE: \"Granat zbliżeniowy\"\n  BT_MEDIKIT: \"Apteczka\"\n  BT_SCANNER: \"Czytnik ruchu\"\n  BT_MINDPROBE: \"Czytnik umysłu\"\n  BT_PSIAMP: \"Wzmacniacz psi\"\n  BT_FLARE: \"Flara\"\n  BT_CORPSE: \"Ciało\"\n#\n  DRT_DEFAULT: \"domyślne\"\n  DRT_UFO: \"Rozkład 0-200%\"\n  DRT_TFTD: \"Rozkład 50-150%\"\n  DRT_FLAT: \"obrażenia stałe\"\n  DRT_FIRE: \"obrażenia specjalne od ognia\"\n  DRT_NONE: \"brak obrażeń\"\n  DRT_UFO_WITH_TWO_DICE: \"Rozkład 0-200% (2 rzuty kostką)\"\n  DRT_EASY: \"rzut 50-200%\"\n  DRT_STANDARD: \"zakres obrażeń standardowych\"\n  DRT_EXPLOSION: \"zakres obrażeń od wybuchu\"\n#\n  BFT_NONE: \"brak\"\n  BFT_INSTANT: \"natychmiastowe\"\n  BFT_SET: \"ustawienie ręczne\"\n  BFT_FIXED: \"ustalone\"\n#\n  BMT_NORMAL: \"normalne (uniwersalne)\"\n  BMT_HEAL: \"leczenie\"\n  BMT_STIMULANT: \"stymy\"\n  BMT_PAINKILLER: \"środki przeciwbólowe\"\n#\n  ETM_DEFAULT: \"domyślne\"\n  ETM_MELEE_100: \"WALKA WRĘCZ\"\n  ETM_MELEE_50: \"WALKA WRĘCZ (50% szans)\"\n  ETM_MELEE_33: \"WALKA WRĘCZ (33% szans)\"\n  ETM_FIRING_100: \"STRZELANIE\"\n  ETM_FIRING_50: \"STRZELANIE (50% szans)\"\n  ETM_FIRING_33: \"STRZELANIE (33% szans)\"\n  ETM_THROWING_100: \"RZUCANIE\"\n  ETM_THROWING_50: \"RZUCANIE (50% szans)\"\n  ETM_THROWING_33: \"RZUCANIE (33% szans)\"\n  ETM_FIRING_AND_THROWING: \"STRZELANIE i RZUCANIE\"\n  ETM_FIRING_OR_THROWING: \"STRZELANIE lub RZUCANIE\"\n  ETM_REACTIONS: \"REFLEKS\"\n  ETM_REACTIONS_AND_MELEE: \"REFLEKS i WALKA WRĘCZ\"\n  ETM_REACTIONS_AND_FIRING: \"REFLEKS i STRZELANIE\"\n  ETM_REACTIONS_AND_THROWING: \"REFLEKS i RZUCANIE\"\n  ETM_REACTIONS_OR_MELEE: \"REFLEKS lub WALKA WRĘCZ\"\n  ETM_REACTIONS_OR_FIRING: \"REFLEKS lub STRZELANIE\"\n  ETM_REACTIONS_OR_THROWING: \"REFLEKS lub RZUCANIE\"\n  ETM_BRAVERY: \"ODWAGA\"\n  ETM_BRAVERY_2X: \"ODWAGA (x2)\"\n  ETM_BRAVERY_AND_REACTIONS: \"ODWAGA i REFLEKS\"\n  ETM_BRAVERY_OR_REACTIONS: \"ODWAGA lub REFLEKS\"\n  ETM_BRAVERY_OR_REACTIONS_2X: \"ODWAGA lub REFLEKS (x2)\"\n  ETM_PSI_STRENGTH: \"SIŁA PSI\"\n  ETM_PSI_STRENGTH_2X: \"SIŁA PSI (x2)\"\n  ETM_PSI_SKILL: \"ZDOLNOŚĆ PSI\"\n  ETM_PSI_SKILL_2X: \"ZDOLNOŚĆ PSI (x2)\"\n  ETM_PSI_STRENGTH_AND_SKILL: \"SIŁA PSI i ZDOLNOŚĆ PSI\"\n  ETM_PSI_STRENGTH_AND_SKILL_2X: \"SIŁA PSI i ZDOLNOŚĆ PSI (x2)\"\n  ETM_PSI_STRENGTH_OR_SKILL: \"SIŁA PSI lub ZDOLNOŚĆ PSI\"\n  ETM_PSI_STRENGTH_OR_SKILL_2X: \"SIŁA PSI lub ZDOLNOŚĆ PSI (x2)\"\n  ETM_NOTHING: \"bez treningu\"\n#\n  battleType: \"Typ przedmiotu\"\n  experienceTrainingMode: \"Tryb doświadczenia\"\n  manaExperience: \"Punkty doświadczenia dla many\"\n  arcingShot: \"Trajektoria artyleryjska?\"\n  isFireExtinguisher: \"Gaśnica?\"\n  explodeInventory: \"Wybucha w ekwipunku?\"\n  waypoints: \"Limit punktów kontrolnych\"\n  sprayWaypoints: \"Znaczników ognia posiewanego\"\n#\n  shotgunPellets: \"Liczba peletek\"\n  shotgunBehavior: \"Tryb działania strzelby\"\n  shotgunSpread: \"Rozrzut strzelby\"\n  shotgunChoke: \"Zduszenie strzelby\"\n#\n  underwaterOnly: \"Tylko podwodne?\"\n  landOnly: \"Tylko lądowe?\"\n  psiRequired: \"Wymaga zdolności psi?\"\n  targetMatrix: \"Dozwolone cele dla przedmiotu\"\n  convertToCivilian: \"Konwertować do cywila?\"\n  manaRequired: \"Wymaga many?\"\n  LOSRequired: \"Wymaga linii wzroku?\"\n#\n  noLOSAccuracyPenalty: \"Mnożnik kary za brak linii widzenia\"\n  kneelBonus: \"Mnożnik premii za klęczenie\"\n  twoHanded: \"Dwuręczne?\"\n  blockBothHands: \"Blokuje obie ręce?\"\n  oneHandedPenalty: \"Kara za użycie jednorącz\"\n#\n  minRange: \"Minimalny zasięg\"\n  maxRange: \"Maksymalny zasięg\"\n  aimRange: \"Zasięg strzału mierzonego\"\n  autoRange: \"Zasięg strzału serią\"\n  snapRange: \"Zasięg strzału szybkiego\"\n  dropoff: \"Spadek celności za pole\"\n#\n  accuracyMultiplier: \"Mnożnik celności strzeleckiej\"\n  accuracyAimed: \"Celność strzału mierzonego\"\n  accuracyAuto: \"Celność strzału serią\"\n  accuracySnap: \"Celność strzału szybkiego\"\n  costAimed: \"Koszt strzału mierzonego\"\n  costAuto: \"Koszt strzału serią\"\n  costSnap: \"Koszt strzału szybkiego\"\n#\n  meleeMultiplier: \"Mnożnik celności walki wręcz\"\n  accuracyMelee: \"Celność walki wręcz\"\n  costMelee: \"Koszt walki wręcz\"\n#\n  psiAttackName: \"Nazwa ataku psi\"\n  accuracyUse: \"Celność akcji\"\n  accuracyMindControl: \"Celność kontroli umysłu\"\n  accuracyPanic: \"Celność paniki\"\n  costUse: \"Koszt akcji\"\n  costMindcontrol: \"Koszt kontroli umysłu\"\n  costPanic: \"Koszt paniki\"\n#\n  weight: \"Waga\"\n  throwRange: \"Maks. rzut (powierzchnia)\"\n  underwaterThrowRange: \"Maks. rzut (pod wodą)\"\n  throwDropoffRange: \"Zas. rzutu (powierzchnia)\"\n  underwaterThrowDropoffRange: \"Zas. rzutu (pod wodą)\"\n  throwDropoff: \"Spadek celności rzutu za pole\"\n  throwMultiplier: \"Mnożnik celności rzutu\"\n  accuracyThrow: \"Celność rzutu\"\n  costThrow: \"Koszt rzutu\"\n  costPrime: \"Koszt odbezpieczenia\"\n  costUnprime: \"Koszt zabezpieczenia\"\n#\n  closeQuartersMultiplier: \"Mnożnik celności zwarcia\"\n  accuracyCloseQuarters: \"Celność w zwarciu\"\n#\n  damageType: \"Typ obrażeń\"\n  power: \"Siła rażenia\"\n  powerRangeReduction: \"Spadek siły/pole\"\n  powerRangeThreshold: \"Próg redukcji obrażeń\"\n  damageBonus: \"Premia do obrażeń\"\n  blastRadius: \"Promień rażenia\"\n  damageAlter: \"Dodatkowe info o obrażeniach:\"\n  meleeType: \"Typ obrażeń w walce wręcz\"\n  meleePower: \"Siła rażenia w walce wręcz\"\n  meleeBonus: \"Premia do obrażeń w walce wręcz\"\n  meleeAlter: \"Dodatkowe info o walce wręcz:\"\n  FixRadius: \"Promień rażenia\"\n  RandomType: \"Wariant kalkulacji\"\n  FireBlastCalc: \"Klasyczne działanie ognia?\"\n  IgnoreDirection: \"Ignorowanie kierunku\"\n  IgnoreSelfDestruct: \"Ignorowanie samozniszczenia\"\n  IgnorePainImmunity: \"Ignorowanie odp. na oszołomienie\"\n  IgnoreNormalMoraleLose: \"Ignorowanie klasycznej straty morale\"\n  IgnoreOverKill: \"Ignoruj anihilację\"\n  ArmorEffectiveness: \"Efektywność pancerza\"\n  RadiusEffectiveness: \"Efektywność promienia\"\n  RadiusReduction: \"Redukcja obrażeń z promienia\"\n  FireThreshold: \"Próg podpalenia\"\n  SmokeThreshold: \"Ustaw próg zadymienia\"\n#\n  ToArmorPre: \"Mnożnik pancerza przed obrażeniami\"\n  RandomArmorPre: \"Losowe pierwotne uszkodzenia pancerza?\"\n  ToArmor: \"Mnożnik obrażeń na pancerz\"\n  RandomArmor: \"Losowe uszkodzenia pancerza?\"\n  ToHealth: \"Mnożnik obrażeń na zdrowie\"\n  RandomHealth: \"Losowe obrażenia na zdrowie?\"\n  ToStun: \"Mnożnik oszołomienia\"\n  RandomStun: \"Losowe oszołomienie?\"\n  ToWound: \"Mnożnik licznika ran\"\n  RandomWound: \"Losowe rany klasyczne?\"\n  ToTime: \"Mnożnik obrażeń na JC\"\n  RandomTime: \"Losowe obrażenia na JC?\"\n  ToEnergy: \"Mnożnik obrażeń na energię\"\n  RandomEnergy: \"Losowe obrażenia na energię?\"\n  ToMorale: \"Mnożnik obrażeń na morale\"\n  RandomMorale: \"Losowe obrażenia na morale?\"\n  ToItem: \"Mnożnik obrażeń dla przedmiotów\"\n  RandomItem: \"Losowe obrażenia na przedmioty?\"\n  ToMana: \"Mnożnik obrażeń na manę\"\n  RandomMana: \"Losowe obrażenia na manę?\"\n  ToTile: \"Mnożnik obrażeń dla terenu\"\n  RandomTile: \"Losowe obrażenia na teren?\"\n  TileDamageMethod: \"Tryb uszkadzania pól\"\n  TileDamageLimit: \"\"\n#\n  confAimed: \"Akcja mierzona:\"\n  confAuto: \"Akcja seryjna:\"\n  confSnap: \"Akcja szybka:\"\n  confMelee: \"Akcja wręcz:\"\n  shots: \"Strzałów na akcję\"\n  spendPerShot: \"Zużycie na strzał:\"\n  followProjectiles: \"Śledzić pociski?\"\n  name: \"Nazwa\"\n  shortName: \"Krótka nazwa\"\n  ammoSlot: \"Użyte miejsce na amunicję\"\n  ammoZombieUnitChanceOverride: \"Szansa na zombifikację\"\n  ammoSpawnUnitChanceOverride: \"Szansa na utworzenie jednostki\"\n  ammoSpawnItemChanceOverride: \"Szansa na utworzenie przedmiotu\"\n  arcing: \"Trajektoria artyleryjska?\"\n#\n  clipSize: \"Rozmiar magazynka\"\n  isAmmoRechargeable: \"\"\n#\n  primaryAmmo: \"Główne miejsce na amunicję:\"\n  compatibleAmmo: \"Kompatybilna amunicja\"\n  tuLoad: \"Koszt załadowania\"\n  tuUnload: \"Koszt rozładowania\"\n  ammo[1]: \"Dodatkowe miejsce na amunicję #1:\"\n  ammo[2]: \"Dodatkowe miejsce na amunicję #2:\"\n  ammo[3]: \"Dodatkowe miejsce na amunicję #3:\"\n#\n  armor: \"Wytrzymałość\"\n#\n  medikitType: \"Typ apteczki\"\n  painKillerActionName: \"\"\n  stimulantActionName: \"\"\n  healActionName: \"\"\n  medikitActionName: \"Nazwa akcji leczenia\"\n  medikitTargetSelf: \"Użycie apteczki na sobie?\"\n  medikitTargetImmune: \"Użycie apteczki na celach niewrażliwich na krwawienie?\"\n  medikitTargetMatrix: \"Dozwolone cele dla apteczki\"\n  isConsumable: \"Zużywa się?\"\n  painKiller: \"Dawek środków przeciwbólowych\"\n  heal: \"Dawek lekarstw\"\n  stimulant: \"Dawek stymów\"\n  woundRecovery: \"Leczenie ran\"\n  healthRecovery: \"Odzyskanie zdrowia\"\n  stunRecovery: \"Obniżanie oszołomienia\"\n  energyRecovery: \"Odzyskanie energii\"\n  manaRecovery: \"Odzyskanie many\"\n  moraleRecovery: \"Odzyskanie morale\"\n  painKillerRecovery: \"Siła środków przeciwbólowych\"\n#\n  requires: \"Wymagane technologie\"\n  requiresBuy: \"Wymagane technologie do zakupu\"\n  requiresBuyBaseFunc: \"Funkcje wymagane do zakupu\"\n  requiresBuyCountry: \"Wymagany sojusz z państwem\"\n  requiresAward: \"\"\n  requiresBonus: \"\"\n  categories: \"Kategorie\"\n  supportedInventorySections: \"Lokacje w ekwipunku\"\n#\n  size: \"Rozmiar\"\n  costBuy: \"Cena zakupu\"\n  monthlyBuyLimit: \"Miesięczny limit zakupów\"\n  costSell: \"Cena sprzedaży\"\n  transferTime: \"Transfer (w godzinach)\"\n  monthlySalary: \"Wypłata/miesiąc\"\n  monthlyMaintenance: \"Utrzymanie/miesiąc\"\n#\n  SPECAB_NONE: \"Brak\"\n  SPECAB_EXPLODEONDEATH: \"Eksplozja po śmierci\"\n  SPECAB_BURNFLOOR: \"Palenie podłogi\"\n  SPECAB_BURN_AND_EXPLODE: \"Palenie podłogi i eksplozja po śmierci\"\n#\n  MT_WALK: \"Chodzenie\"\n  MT_FLY: \"Latanie\"\n  MT_SLIDE: \"Ślizganie\"\n  MT_FLOAT: \"Unoszenie\"\n  MT_SINK: \"Tonięcie\"\n#\n  TORSO_USE_GENDER: \"Używa płci\"\n  TORSO_ALWAYS_MALE: \"Zawsze mężczyzna\"\n  TORSO_ALWAYS_FEMALE: \"Zawsze kobieta\"\n#\n  DRAWING_ROUTINE_SOLDIER_SECTOID: \"Żołnierz, sektoid\"\n  DRAWING_ROUTINE_FLOATER: \"Lewiton\"\n  DRAWING_ROUTINE_HWP: \"Ciężkie Działa Samobieżne\"\n  DRAWING_ROUTINE_CYBERDISC: \"Cyberdysk\"\n  DRAWING_ROUTINE_CIVILIAN_ETHEREAL: \"Cywil, eterianin\"\n  DRAWING_ROUTINE_SECTOPOD_REAPER: \"Sektopod, żeniec\"\n  DRAWING_ROUTINE_SNAKEMAN: \"Wężownik\"\n  DRAWING_ROUTINE_CHRYSSALID: \"Krysalid\"\n  DRAWING_ROUTINE_SILACOID: \"Silakoid\"\n  DRAWING_ROUTINE_CELATID: \"Celatyd\"\n  DRAWING_ROUTINE_MUTON: \"Muton\"\n  DRAWING_ROUTINE_SWS: \"Podwodne Systemy Uzbrojenia\"\n  DRAWING_ROUTINE_HALLUCINOID: \"Halucynoid\"\n  DRAWING_ROUTINE_AQUANAUTS: \"Akwanauci\"\n  DRAWING_ROUTINE_CALCINITE_AND_MORE: \"Kalcynit, głębion, skrzelak, homaroid, tasot\"\n  DRAWING_ROUTINE_AQUATOID: \"Akwatoid\"\n  DRAWING_ROUTINE_BIO_DRONE: \"Bio-dron\"\n  DRAWING_ROUTINE_TFTD_CIVILIAN_A: \"Cywile z TFTD typ A i zombi z TFTD\"\n  DRAWING_ROUTINE_TFTD_CIVILIAN_B: \"Cywile z TFTD typ B\"\n  DRAWING_ROUTINE_TENTACULAT: \"Mackonóg\"\n  DRAWING_ROUTINE_TRISCENE: \"Tryskon\"\n  DRAWING_ROUTINE_XARQUID: \"Ksarkuid\"\n  DRAWING_ROUTINE_INVERTED_CYBERDISC: \"Odwrócony cyberdysk (animacja napędu na górze)\"\n#\n  stats: \"Modyfikatory statystyk\"\n  specab: \"Zdolność specjalna\"\n  movementType: \"Typ ruchu\"\n  allowsRunning: \"Pozwala biegać?\"\n  allowsStrafing: \"Pozwala chodzić na boki?\"\n  allowsSneaking: \"Pozwala się skradać?\"\n  allowsKneeling: \"Pozwala klękać?\"\n  allowsMoving: \"Pozwala na ruch?\"\n  fearImmune: \"Odporność na stratę morale?\"\n  bleedImmune: \"Odporność na krwawienie?\"\n  painImmune: \"Odporność na oszołomienie?\"\n  zombiImmune: \"Odporność na zombifikację?\"\n  ignoresMeleeThreat: \"Ignoruje walkę w zwarciu?\"\n  createsMeleeThreat: \"Powoduje walkę w zwarciu?\"\n  builtInWeapons: \"Przedmioty wbudowane\"\n  specialWeapon: \"Broń specjalna\"\n  heatVision: \"Widoczność przez dym\"\n  visibilityThroughFire: \"Widoczność przez ogień\"\n  psiVision: \"Zmysł psi\"\n  psiCamouflage: \"Kamuflaż psi\"\n  visibilityAtDay: \"Widoczność w dzień\"\n  visibilityAtDark: \"Widoczność w nocy\"\n  camouflageAtDay: \"Kamuflaż w dzień\"\n  camouflageAtDark: \"Kamuflaż w nocy\"\n  antiCamouflageAtDay: \"Antykamuflaż w dzień\"\n  antiCamouflageAtDark: \"Antykamuflaż w nocy\"\n  psiDefence: \"Obrona psi\"\n  meleeDodge: \"Unik w walce wręcz\"\n  meleeDodgeBackPenalty: \"Kara do uniku w walce wręcz\"\n  recovery: \"Odzyskanie na turę:\"\n  time: \"Czas\"\n  energy: \"Energia\"\n  morale: \"Morale\"\n  health: \"Zdrowie\"\n  stun: \"oszołomienie\"\n  mana: \"Mana\"\n  units: \"Kompatybilne jednostki\"\n  ranks: \"\"\n  frontArmor: \"Pancerz przedni\"\n  sideArmor: \"Pancerz boczny\"\n  leftArmorDiff: \"Pancerz lewy (różnica)\"\n  rearArmor: \"Pancerz tylny\"\n  underArmor: \"Pancerz dolny\"\n#\n  sizeX: \"Rozmiar X\"\n  sizeY: \"Rozmiar Y\"\n  buildCost: \"Koszt budowy\"\n  buildCostItems: \"Materiały do budowy:\"\n  buildTime: \"Czas budowy\"\n  monthlyCost: \"Koszt miesięczny\"\n  refundValue: \"Wartość zwrotu\"\n  requiresBaseFunc: \"Wymaga funkcji\"\n  provideBaseFunc: \"Dostarcza funkcję\"\n  forbiddenBaseFunc: \"Zabrania funkcji\"\n  lift: \"Szyb wejściowy?\"\n  hyper: \"Dekoder hiperfal?\"\n  mind: \"Tarcza umysłowa?\"\n  mindPower: \"Siła tarczy umysłowej\"\n  grav: \"Tarcza grawitacyjna?\"\n  storage: \"Przestrzeń magazynowa\"\n  personnel: \"Przestrzeń mieszkalna\"\n  aliens: \"Cele więzienne\"\n  crafts: \"Hangary\"\n  labs: \"Stanowiska laboratoryjne\"\n  workshops: \"Stanowiska robocze\"\n  psiLabs: \"Stanowiska laboratorium psi\"\n  trainingRooms: \"Przestrzeń treningowa\"\n  sightRange: \"Zasięg wzroku\"\n  sightChance: \"Szansa dostrzeżenia\"\n  radarRange: \"Zasięg radaru\"\n  radarChance: \"Skuteczność radaru\"\n  defense: \"Wartość obronna\"\n  hitRatio: \"Szansa trafienia\"\n  ammoNeeded: \"Potrzeba amunicji\"\n  unifiedDamageFormula: \"Nowy wzór na obrażenia?\"\n  ammoItem: \"Amunicja\"\n  maxAllowedPerBase: \"Maksymalna liczba w bazie\"\n  manaRecoveryPerDay: \"Mana dziennie\"\n  healthRecoveryPerDay: \"Zdrowie dziennie\"\n  sickBayAbsoluteBonus: \"Abs. premia do leczenia\"\n  sickBayRelativeBonus: \"Wzgl. premia do leczenia\"\n  prisonType: \"Typ więzienia\"\n  rightClickActionType: \"Kliknięcie PPM\"\n  leavesBehindOnSell: \"Po sprzedaży pozostaje\"\n  removalTime: \"Czas rozbiórki\"\n  canBeBuiltOver: \"Można na tym budować?\"\n  upgradeOnly: \"\"\n  buildOverFacilities: \"Można zbudować\"\n#\n  BFRCT_DEFAULT: \"domyślne\"\n  BFRCT_PRISON: \"idź do więzień\"\n  BFRCT_ENGINEERING: \"idź do produkcji\"\n  BFRCT_RESEARCH: \"idź do badań\"\n  BFRCT_GYM: \"idź do treningu bojowego\"\n  BFRCT_PSI_LABS: \"idź do laboratorium psi\"\n  BFRCT_BARRACKS: \"idź do baraków\"\n  BFRCT_GREY_MARKET: \"idź na szary rynek\"\n  BFRCT_GEOSCAPE: \"idź do ekranu Ziemi\"\n#\n  costRent: \"Koszt utrzymania\"\n  soldiers: \"Przestrzeń ładunkowa\"\n  maxUnitsLimit: \"Maks. pojemność ładowni\"\n  pilots: \"Rozmiar kabiny\"\n  pilotMinStatsRequired: \"Min. statystyki pilota\"\n  pilotSoldierBonusesRequired: \"Wymagania pilotażu\"\n  vehicles: \"CDS-ów\"\n  onlyOneSoldierGroupAllowed: \"Dozwolona tylko jedna grupa żołnierzy?\"\n  allowedSoldierGroups: \"Dozwolone grupy żołnierzy\"\n  allowedArmorGroups: \"Dozwolone grupy pancerzy\"\n  limitArmorGroups: \"\"\n  maxHWPUnitsLimit: \"Maks. liczba CDS-ów\"\n  maxSmallSoldiers: \"Maks. małych żołnierzy\"\n  maxLargeSoldiers: \"Maks. dużych żołnierzy\"\n  maxSmallVehicles: \"Maks. małych pojazdów\"\n  maxLargeVehicles: \"Maks. dużych pojazdów\"\n  maxSmallUnits: \"Maks. małych jednostek\"\n  maxLargeUnits: \"Maks. dużych jednostek\"\n  maxSoldiers: \"Maks. żołnierzy\"\n  maxVehicles: \"Maks. pojazdów\"\n  maxItems: \"Limit ekwipunku\"\n  maxStorageSpace: \"Przestrzeń magazynowa\"\n  maxAltitude: \"Pułap walki powietrznej\"\n  weapons: \"Mocowań broni\"\n  weaponStrings: \"Nazwy broni\"\n  fixedWeapons: \"Wbudowane bronie\"\n  weaponTypes: \"Dozwolone typy broni\"\n  damageMax: \"Wytrzymałość\"\n  avoidBonus: \"Premia do uników (podstawowa)\"\n  avoidBonus2: \"Premia do uników 2 (podstawowa)\"\n  powerBonus: \"Premia do obrażeń (podstawowa)\"\n  hitBonus: \"Premia do trafienia (podstawowa)\"\n  fuelMax: \"Zapas paliwa\"\n  speedMax: \"Prędkość maksymalna\"\n  accel: \"Przyspieszenie\"\n  shieldCapacity: \"Wartość tarczy\"\n  shieldRecharge: \"Odnowa tarczy (w walce)\"\n  shieldRechargeInGeoscape: \"Odnowa tarczy (na globie)\"\n  shieldBleedThrough: \"Przeciekanie przez tarczę\"\n  shieldRechargedAtBase: \"Odnowa tarczy (w bazie)\"\n  refuelItem: \"Paliwo\"\n  refuelRate: \"Szybkość tankowania\"\n  repairRate: \"Szybkość naprawy\"\n  spacecraft: \"Ostateczny transport?\"\n  allowLanding: \"Może lądować?\"\n  notifyWhenRefueled: \"Powiadamia po zatankowaniu?\"\n  autoPatrol: \"Autopatrol?\"\n  undetectable: \"Niewykrywalne?\"\n  patrolWithoutFuel: \"\"\n  keepCraftAfterFailedMission: \"Desant?\"\n  _calculatedValues: \"Wyliczone wartości\"\n  _maxRange: \"Maksymalny zasięg\"\n  _minRange: \"Minimalny zasięg\"\n  _avgRange: \"Średni zasięg\"\n#\n  hunterKillerPercentage: \"Szansa na myśliwca-mordercę\"\n  huntMode: \"Tryb łowów\"\n  huntSpeed: \"Szybkość łowów\"\n  huntBehavior: \"Tryb działania łowów\"\n  range: \"Zasięg\"\n  reload: \"Czas przeładowania\"\n  breakOffTime: \"Czas oderwania\"\n  score: \"Punkty\"\n  missionScore: \"Punkty za misję\"\n  craftCustomDeploy: \"Układ dla lądowania UFO\"\n  missionCustomDeploy: \"Układ dla misji\"\n  _escapeCountdown: \"Odliczanie ucieczki\"\n  _fireRate: \"Szybkostrzelność\"\n  _averageDPM: \"Średnie obrażenia na minutę\"\n#\n  HM_INTERCEPTORS: \"preferuj łowy na myśliwce\"\n  HM_TRANSPORTS: \"preferuj łowy na transporty\"\n  HM_RANDOM: \"losowo\"\n#\n  HB_FLEE: \"uciekaj gdy przegrywasz\"\n  HB_KAMIKAZE: \"walcz do śmierci\"\n  HB_RANDOM: \"losowo\"\n#\n  tractorBeamPower: \"Moc promienia ściągającego\"\n  damage: \"Obrażenia\"\n  shieldDamageModifier: \"Modyfikator obrażeń tarcz\"\n  accuracy: \"Celność\"\n  reloadCautious: \"Przeładowanie (tryb ostrożny)\"\n  reloadStandard: \"Przeładowanie (tryb standardowy)\"\n  reloadAggressive: \"Przeładowanie (tryb agresywny)\"\n  launcher: \"Obiekt wyrzutni\"\n  weaponType: \"Typ broni\"\n  clip: \"Obiekt amunicji\"\n  ammoMax: \"Pocisków\"\n  rearmRate: \"Szybkość przeładowania\"\n  bulletSaving: \"Zachowywanie amunicji?\"\n  _damageRange: \"Rozrzut obrażeń\"\n  _damageRangeBasic: \"Rozrzut obrażeń (podstawowy)\"\n  _averageTotalDamage: \"Średnie obrażenia całkowite\"\n#\n  allowPiloting: \"\"\n  costSalary: \"\"\n  costSalarySquaddie: \"\"\n  costSalarySergeant: \"\"\n  costSalaryCaptain: \"\"\n  costSalaryColonel: \"\"\n  costSalaryCommander: \"\"\n#\n  race: \"\"\n  rank: \"\"\n  livingWeapon: \"\"\n  meleeWeapon: \"Broń biała\"\n  psiWeapon: \"\"\n  _builtInWeaponSets: \"\"\n  _weightedBuiltInWeaponSets: \"\"\n  spawnUnit: \"\"\n  _capturable: \"\"\n  capturable: \"\"\n  canSurrender: \"\"\n  autoSurrender: \"\"\n  spotter: \"\"\n  sniper: \"\"\n"
  },
  {
    "path": "bin/common/Language/Technical/pt-BR.yml",
    "content": "pt-BR:\n#=================== Menu ===================\n#TestState.cpp\n  STR_BAD_NODES: \"Nodos ruins em arquivos RMP\"\n  STR_BAD_NODES_DESC: \"Verifica arquivos RMP para nodos fora dos limites do mapa.{NEWLINE}Isso NÃO causará nenhum travamento, mas serão ignorados pelo jogo, portanto, não funcionarão como pretendido.\"\n#\n  STR_MCD_CHECK: \"Verificação de MCD\"\n  STR_MCD_CHECK_DESC: \"\"\n#\n  STR_PALETTE_CHECK: \"Verificação de paleta\"\n  STR_PALETTE_CHECK_DESC: \"Tenta corresponder as paletas das imagens modificadas às paletas oficiais e relata quaisquer imagens que não tenham uma correspondência de 100%.\"\n#\n  STR_SCRIPT_TAGS: \"Exportação de tags de script\"\n  STR_SCRIPT_TAGS_DESC: \"Exporta tags de script em formato CSV.\"\n#\n  STR_MAP_RESOURCES: \"Verificação de recursos do mapa\"\n  STR_MAP_RESOURCES_DESC: \"Verifica arquivos e regras relacionadas ao mapa que estão faltando ou não utilizados.\"\n#\n  STR_CHECKING_TERRAIN: \"Verificando terreno...\"\n  STR_CHECKING_UFOS: \"Verificando OVNIs...\"\n  STR_CHECKING_CRAFT: \"Verificando naves...\"\n#\n  BACKPALS.DAT: \"BACKPALS.DAT\"\n  PAL_GEOSCAPE: \"PAL_GEOSCAPE\"\n  PAL_BASESCAPE: \"PAL_BASESCAPE\"\n  PAL_GRAPHS: \"PAL_GRAPHS\"\n  PAL_UFOPAEDIA: \"PAL_UFOPAEDIA\"\n  PAL_BATTLEPEDIA: \"PAL_BATTLEPEDIA\"\n  PAL_BATTLESCAPE: \"PAL_BATTLESCAPE\"\n  PAL_BATTLESCAPE_1: \"PAL_BATTLESCAPE_1\"\n  PAL_BATTLESCAPE_2: \"PAL_BATTLESCAPE_2\"\n  PAL_BATTLESCAPE_3: \"PAL_BATTLESCAPE_3\"\n#=================== Ufopaedia ===================\n#StatsForNerdsState.cpp\n  BT_NONE: \"Nenhum\"\n  BT_FIREARM: \"Arma de fogo\"\n  BT_AMMO: \"Munição\"\n  BT_MELEE: \"Arma corpo a corpo\"\n  BT_GRENADE: \"Granada\"\n  BT_PROXIMITYGRENADE: \"Granada de proximidade\"\n  BT_MEDIKIT: \"Kit médico\"\n  BT_SCANNER: \"Detector de movimento\"\n  BT_MINDPROBE: \"Sonda mental\"\n  BT_PSIAMP: \"Amplificador psíquico\"\n  BT_FLARE: \"Sinalizador\"\n  BT_CORPSE: \"Cadáver/Corpo\"\n#\n  DRT_DEFAULT: \"padrão baunilha\"\n  DRT_UFO: \"dispersão de 0-200%\"\n  DRT_TFTD: \"dispersão de 50-150%\"\n  DRT_FLAT: \"dano fixo\"\n  DRT_FIRE: \"dano especial de fogo\"\n  DRT_NONE: \"sem dano\"\n  DRT_UFO_WITH_TWO_DICE: \"dispersão de 0-200% (rolagem de 2 dados)\"\n  DRT_EASY: \"dispersão de 50-200%\"\n  DRT_STANDARD: \"intervalo de dano padrão\"\n  DRT_EXPLOSION: \"intervalo de dano de explosão\"\n#\n  BFT_NONE: \"nenhum\"\n  BFT_INSTANT: \"instantâneo\"\n  BFT_SET: \"definido manualmente\"\n  BFT_FIXED: \"fixo\"\n#\n  BMT_NORMAL: \"padrão (multiuso)\"\n  BMT_HEAL: \"cura\"\n  BMT_STIMULANT: \"estimulante\"\n  BMT_PAINKILLER: \"analgésico\"\n#\n  ETM_DEFAULT: \"padrão\"\n  ETM_MELEE_100: \"CORPO A CORPO\"\n  ETM_MELEE_50: \"CORPO A CORPO (50% de chance)\"\n  ETM_MELEE_33: \"CORPO A CORPO (33% de chance)\"\n  ETM_FIRING_100: \"DISPARO\"\n  ETM_FIRING_50: \"DISPARO (50% de chance)\"\n  ETM_FIRING_33: \"DISPARO (33% de chance)\"\n  ETM_THROWING_100: \"ARREMESSO\"\n  ETM_THROWING_50: \"ARREMESSO (50% de chance)\"\n  ETM_THROWING_33: \"ARREMESSO (33% de chance)\"\n  ETM_FIRING_AND_THROWING: \"DISPARO e ARREMESSO\"\n  ETM_FIRING_OR_THROWING: \"DISPARO ou ARREMESSO\"\n  ETM_REACTIONS: \"REAÇÕES\"\n  ETM_REACTIONS_AND_MELEE: \"REAÇÕES e CORPO A CORPO\"\n  ETM_REACTIONS_AND_FIRING: \"REAÇÕES e DISPARO\"\n  ETM_REACTIONS_AND_THROWING: \"REAÇÕES e ARREMESSO\"\n  ETM_REACTIONS_OR_MELEE: \"REAÇÕES ou CORPO A CORPO\"\n  ETM_REACTIONS_OR_FIRING: \"REAÇÕES ou DISPARO\"\n  ETM_REACTIONS_OR_THROWING: \"REAÇÕES ou ARREMESSO\"\n  ETM_BRAVERY: \"BRAVURA\"\n  ETM_BRAVERY_2X: \"BRAVURA (x2)\"\n  ETM_BRAVERY_AND_REACTIONS: \"BRAVURA e REAÇÕES\"\n  ETM_BRAVERY_OR_REACTIONS: \"BRAVURA ou REAÇÕES\"\n  ETM_BRAVERY_OR_REACTIONS_2X: \"BRAVURA ou REAÇÕES (x2)\"\n  ETM_PSI_STRENGTH: \"FORÇA PSIÔNICA\"\n  ETM_PSI_STRENGTH_2X: \"FORÇA PSIÔNICA (x2)\"\n  ETM_PSI_SKILL: \"HABILIDADE PSIÔNICA\"\n  ETM_PSI_SKILL_2X: \"HABILIDADE PSIÔNICA (x2)\"\n  ETM_PSI_STRENGTH_AND_SKILL: \"FORÇA PSIÔNICA e HABILIDADE PSIÔNICA\"\n  ETM_PSI_STRENGTH_AND_SKILL_2X: \"FORÇA PSIÔNICA e HABILIDADE PSIÔNICA (x2)\"\n  ETM_PSI_STRENGTH_OR_SKILL: \"FORÇA PSIÔNICA ou HABILIDADE PSIÔNICA\"\n  ETM_PSI_STRENGTH_OR_SKILL_2X: \"FORÇA PSIÔNICA ou HABILIDADE PSIÔNICA (x2)\"\n  ETM_NOTHING: \"sem treinamento\"\n#\n  battleType: \"Tipo de item\"\n  experienceTrainingMode: \"Modo de experiência\"\n  manaExperience: \"Experiência de mana\"\n  arcingShot: \"Tiro arqueado?\"\n  isFireExtinguisher: \"Extintor de incêndio?\"\n  explodeInventory: \"Explode no inventário?\"\n  waypoints: \"Número máximo de pontos de rota\"\n  sprayWaypoints: \"Pontos de rota do tiro disperso\"\n#\n  shotgunPellets: \"Número de projéteis\"\n  shotgunBehavior: \"Comportamento da espingarda\"\n  shotgunSpread: \"Dispersão da espingarda\"\n  shotgunChoke: \"Cano da espingarda\"\n#\n  underwaterOnly: \"Somente subaquático?\"\n  landOnly: \"Somente terrestre?\"\n  psiRequired: \"Habilidade psiônica necessária?\"\n  targetMatrix: \"Alvos do item\"\n  convertToCivilian: \"Converter para civil?\"\n  manaRequired: \"Mana necessária?\"\n  LOSRequired: \"Visão necessária?\"\n#\n  noLOSAccuracyPenalty: \"Mult. de penalidade sem visão\"\n  kneelBonus: \"Multiplicador de bônus ao ajoelhar\"\n  twoHanded: \"Duas mãos?\"\n  blockBothHands: \"Bloqueia ambas as mãos?\"\n  oneHandedPenalty: \"Penalidade de uso com uma mão\"\n#\n  minRange: \"Alcance mínimo\"\n  maxRange: \"Alcance máximo\"\n  aimRange: \"Alcance do tiro preciso\"\n  autoRange: \"Alcance do tiro rajada\"\n  snapRange: \"Alcance do tiro simples\"\n  dropoff: \"Queda de precisão/por ladrilho\\\"\"\n#\n  accuracyMultiplier: \"Multiplicador de precisão de tiro\"\n  accuracyAimed: \"Precisão do tiro preciso\"\n  accuracyAuto: \"Precisão do tiro rajada\"\n  accuracySnap: \"Precisão do tiro simples\"\n  costAimed: \"Custo do tiro preciso\"\n  costAuto: \"Custo do tiro rajada\"\n  costSnap: \"Custo do tiro simples\"\n#\n  meleeMultiplier: \"Multip. de precisão corpo a corpo\"\n  accuracyMelee: \"Precisão corpo a corpo\"\n  costMelee: \"Custo corpo a corpo\"\n#\n  psiAttackName: \"Nome do ataque psíquico\"\n  accuracyUse: \"Precisão da ação\"\n  accuracyMindControl: \"Precisão do controle mental\"\n  accuracyPanic: \"Precisão do pânico\"\n  costUse: \"Custo da ação\"\n  costMindcontrol: \"Custo do controle mental\"\n  costPanic: \"Custo do pânico\"\n#\n  weight: \"Peso\"\n  throwRange: \"\"\n  underwaterThrowRange: \"\"\n  throwDropoffRange: \"\"\n  underwaterThrowDropoffRange: \"\"\n  throwDropoff: \"\"\n  throwMultiplier: \"Multip. de precisão de arremesso\"\n  accuracyThrow: \"Precisão do arremesso\"\n  costThrow: \"Custo do arremesso\"\n  costPrime: \"Custo de preparação\"\n  costUnprime: \"Custo de desativação\"\n#\n  closeQuartersMultiplier: \"Multipl. de precisão em CQB\"\n  accuracyCloseQuarters: \"Precisão em CQB\"\n#\n  damageType: \"Tipo de dano\"\n  power: \"Poder\"\n  powerRangeReduction: \"Redução de poder/por ladrilho\"\n  powerRangeThreshold: \"Limite de redução de poder\"\n  damageBonus: \"Bônus de dano\"\n  blastRadius: \"Raio de explosão\"\n  damageAlter: \"Informação extra de dano:\"\n  meleeType: \"Tipo de dano corpo a corpo\"\n  meleePower: \"Poder corpo a corpo\"\n  meleeBonus: \"Bônus de poder corpo a corpo\"\n  meleeAlter: \"Informação extra de dano corpo a corpo:\"\n  FixRadius: \"Raio de explosão\"\n  RandomType: \"Tipo de cálculo\"\n  FireBlastCalc: \"Efeitos de fogo baunilha?\"\n  IgnoreDirection: \"Ignorar direção\"\n  IgnoreSelfDestruct: \"Ignorar autodestruição\"\n  IgnorePainImmunity: \"Ignorar imunidade a atordoamento\"\n  IgnoreNormalMoraleLose: \"Ignorar perda de moral baunilha\"\n  IgnoreOverKill: \"Ignorar excesso de dano\"\n  ArmorEffectiveness: \"Efetividade da armadura\"\n  RadiusEffectiveness: \"Efetividade do raio\"\n  RadiusReduction: \"Redução de dano por raio\"\n  FireThreshold: \"Limite para pegar fogo\"\n  SmokeThreshold: \"Limite para fazer fumaça\"\n#\n  ToArmorPre: \"Mult. de pré-dano à armadura\"\n  RandomArmorPre: \"Gerador automático de pré-dano à armadura?\"\n  ToArmor: \"Multiplicador de dano à armadura\"\n  RandomArmor: \"Gerador automático de dano à armadura?\"\n  ToHealth: \"Multiplicador de dano a PV\"\n  RandomHealth: \"Gerador automático de dano a PV?\"\n  ToStun: \"Multiplicador de dano de atordoamento\"\n  RandomStun: \"Gerador automático de dano de atordoamento?\"\n  ToWound: \"Multiplicador de contagem de feridas\"\n  RandomWound: \"Gerador automático de feridas baunilha?\"\n  ToTime: \"Multiplicador de dano a UT\"\n  RandomTime: \"Gerador automático de dano a UT?\"\n  ToEnergy: \"Multiplicador de dano a energia\"\n  RandomEnergy: \"Gerador automático de dano a energia?\"\n  ToMorale: \"Multiplicador de dano a moral\"\n  RandomMorale: \"Gerador automático de dano a moral?\"\n  ToItem: \"Multiplicador de dano a itens\"\n  RandomItem: \"Gerador automático de dano a itens?\"\n  ToMana: \"Multiplicador de dano a mana\"\n  RandomMana: \"Gerador automático de dano a mana?\"\n  ToTile: \"Multiplicador de dano ao terreno\"\n  RandomTile: \"Gerador automático de dano ao terreno?\"\n  TileDamageMethod: \"Método de dano ao terreno\"\n  TileDamageLimit: \"\"\n#\n  confAimed: \"Ação precisa:\"\n  confAuto: \"Ação rajada:\"\n  confSnap: \"Ação simples:\"\n  confMelee: \"Ação corpo a corpo:\"\n  shots: \"Tiros por ação\"\n  spendPerShot: \"Gasto por tiro:\"\n  followProjectiles: \"Seguir projéteis?\"\n  name: \"Nome\"\n  shortName: \"Nome curto\"\n  ammoSlot: \"Compartimento de munição usado\"\n  ammoZombieUnitChanceOverride: \"\"\n  ammoSpawnUnitChanceOverride: \"\"\n  ammoSpawnItemChanceOverride: \"\"\n  arcing: \"Tiro arqueado?\"\n#\n  clipSize: \"Tamanho do carregador\"\n  isAmmoRechargeable: \"\"\n#\n  primaryAmmo: \"Compartimento de munição primário:\"\n  compatibleAmmo: \"Munição compatível\"\n  tuLoad: \"Custo de carregamento\"\n  tuUnload: \"Custo de descarregamento\"\n  ammo[1]: \"Compartimento de munição extra Nº 1:\"\n  ammo[2]: \"Compartimento de munição extra Nº 2:\"\n  ammo[3]: \"Compartimento de munição extra Nº 3:\"\n#\n  armor: \"Armadura\"\n#\n  medikitType: \"Tipo de kit médico\"\n  painKillerActionName: \"\"\n  stimulantActionName: \"\"\n  healActionName: \"\"\n  medikitActionName: \"Nome da ação do kit médico\"\n  medikitTargetSelf: \"Kit médico em si mesmo?\"\n  medikitTargetImmune: \"Kit médico em imune a sangramento?\"\n  medikitTargetMatrix: \"Alvos do kit médico\"\n  isConsumable: \"Consumível?\"\n  painKiller: \"Usos de analgésico\"\n  heal: \"Usos de cura\"\n  stimulant: \"Usos de estimulante\"\n  woundRecovery: \"Recuperação de feridas\"\n  healthRecovery: \"Recuperação de saúde\"\n  stunRecovery: \"Recuperação de atordoamento\"\n  energyRecovery: \"Recuperação de energia\"\n  manaRecovery: \"Recuperação de mana\"\n  moraleRecovery: \"Recuperação de moral\"\n  painKillerRecovery: \"Força do analgésico\"\n#\n  requires: \"Tecnologia necessária\"\n  requiresBuy: \"Tecnologia necessária para comprar\"\n  requiresBuyBaseFunc: \"Serviços necessários para comprar\"\n  requiresBuyCountry: \"País aliado necessário\"\n  requiresAward: \"\"\n  requiresBonus: \"\"\n  categories: \"Categorias\"\n  supportedInventorySections: \"Compartimentos de inventário\"\n#\n  size: \"Tamanho\"\n  costBuy: \"Custo de compra\"\n  monthlyBuyLimit: \"Limite de compra mensal\"\n  costSell: \"Custo de venda\"\n  transferTime: \"Horas para transferir\"\n  monthlySalary: \"Salário/mês\"\n  monthlyMaintenance: \"Manutenção/mês\"\n#\n  SPECAB_NONE: \"Nenhum\"\n  SPECAB_EXPLODEONDEATH: \"Explode ao morrer\"\n  SPECAB_BURNFLOOR: \"Incendeia o chão\"\n  SPECAB_BURN_AND_EXPLODE: \"Incendeia o chão e explode ao morrer\"\n#\n  MT_WALK: \"Caminhar\"\n  MT_FLY: \"Voar\"\n  MT_SLIDE: \"Deslizar\"\n  MT_FLOAT: \"Flutuar\"\n  MT_SINK: \"Afundar\"\n#\n  TORSO_USE_GENDER: \"Usar gênero\"\n  TORSO_ALWAYS_MALE: \"Sempre masculino\"\n  TORSO_ALWAYS_FEMALE: \"Sempre feminino\"\n#\n  DRAWING_ROUTINE_SOLDIER_SECTOID: \"Soldado, Sectoide\"\n  DRAWING_ROUTINE_FLOATER: \"Flutuador\"\n  DRAWING_ROUTINE_HWP: \"Plataformas de Armas Pesadas\"\n  DRAWING_ROUTINE_CYBERDISC: \"Ciberdisco\"\n  DRAWING_ROUTINE_CIVILIAN_ETHEREAL: \"Civil, Etéreo\"\n  DRAWING_ROUTINE_SECTOPOD_REAPER: \"Sectópode, Ceifador\"\n  DRAWING_ROUTINE_SNAKEMAN: \"Homem-Cobra\"\n  DRAWING_ROUTINE_CHRYSSALID: \"Crisálida\"\n  DRAWING_ROUTINE_SILACOID: \"Silacoide\"\n  DRAWING_ROUTINE_CELATID: \"Celátido\"\n  DRAWING_ROUTINE_MUTON: \"Muton\"\n  DRAWING_ROUTINE_SWS: \"Sistemas de Armas Submersíveis\"\n  DRAWING_ROUTINE_HALLUCINOID: \"Alucinoide\"\n  DRAWING_ROUTINE_AQUANAUTS: \"Aquanautas\"\n  DRAWING_ROUTINE_CALCINITE_AND_MORE: \"Calcinite, Deep One, Homem-Brânquia, Homem-Lagosta, Tasoth\"\n  DRAWING_ROUTINE_AQUATOID: \"Aquatoide\"\n  DRAWING_ROUTINE_BIO_DRONE: \"Biodrone\"\n  DRAWING_ROUTINE_TFTD_CIVILIAN_A: \"Civis TFTD tipo A e Zumbi TFTD\"\n  DRAWING_ROUTINE_TFTD_CIVILIAN_B: \"Civis TFTD tipo B\"\n  DRAWING_ROUTINE_TENTACULAT: \"Tentaculate\"\n  DRAWING_ROUTINE_TRISCENE: \"Triscênio\"\n  DRAWING_ROUTINE_XARQUID: \"Xarquídeo\"\n  DRAWING_ROUTINE_INVERTED_CYBERDISC: \"Ciberdisco invertido (animação de propulsão no topo)\"\n#\n  stats: \"Modificadores de estatísticas\"\n  specab: \"Habilidade especial\"\n  movementType: \"Tipo de movimento\"\n  allowsRunning: \"Permitir correr?\"\n  allowsStrafing: \"Permitir avançar de lado?\"\n  allowsSneaking: \"Permitir furtividade?\"\n  allowsKneeling: \"Permitir ajoelhar?\"\n  allowsMoving: \"Permitir mover?\"\n  fearImmune: \"Imune à perda de moral?\"\n  bleedImmune: \"Imune a sangramento?\"\n  painImmune: \"Imune a atordoamento?\"\n  zombiImmune: \"Imune a zumbificação?\"\n  ignoresMeleeThreat: \"Ignora Ameaça Corpo a Corpo\"\n  createsMeleeThreat: \"Produz Ameaça Corpo a Corpo?\"\n  builtInWeapons: \"Itens integrados\"\n  specialWeapon: \"Arma especial\"\n  heatVision: \"\"\n  visibilityThroughFire: \"\"\n  psiVision: \"Sentido psíquico\"\n  psiCamouflage: \"Camuflagem psíquica\"\n  visibilityAtDay: \"Visibilidade durante o dia\"\n  visibilityAtDark: \"Visibilidade durante a noite\"\n  camouflageAtDay: \"Camuflagem durante o dia\"\n  camouflageAtDark: \"Camuflagem durante a noite\"\n  antiCamouflageAtDay: \"Anticamuflagem durante o dia\"\n  antiCamouflageAtDark: \"Anticamuflagem durante a noite\"\n  psiDefence: \"Defesa psíquica\"\n  meleeDodge: \"Esquiva corpo a corpo\"\n  meleeDodgeBackPenalty: \"Penalidade de esquiva corpo a corpo\"\n  recovery: \"Recuperação por turno:\"\n  time: \"Tempo\"\n  energy: \"Energia\"\n  morale: \"Moral\"\n  health: \"Saúde\"\n  stun: \"Atordoamento\"\n  mana: \"Mana\"\n  units: \"Unidades compatíveis\"\n  ranks: \"\"\n  frontArmor: \"Armadura frontal\"\n  sideArmor: \"Armadura lateral\"\n  leftArmorDiff: \"Diferença de armadura esquerda\"\n  rearArmor: \"Armadura traseira\"\n  underArmor: \"Armadura inferior\"\n#\n  sizeX: \"Tamanho X\"\n  sizeY: \"Tamanho Y\"\n  buildCost: \"Custo de construção\"\n  buildCostItems: \"Materiais de construção:\"\n  buildTime: \"Tempo de construção\"\n  monthlyCost: \"Custo mensal\"\n  refundValue: \"Valor de reembolso\"\n  requiresBaseFunc: \"Serviços necessários\"\n  provideBaseFunc: \"Serviços fornecidos\"\n  forbiddenBaseFunc: \"Serviços proibidos\"\n  lift: \"Elevador de acesso?\"\n  hyper: \"Decodificador de hiper-onda?\"\n  mind: \"Escudo mental?\"\n  mindPower: \"Poder do escudo mental\"\n  grav: \"Escudo gravitacional?\"\n  storage: \"Espaço de armazenamento\"\n  personnel: \"Espaço para habitação\"\n  aliens: \"Espaço para prisão\"\n  crafts: \"Espaço de hangar\"\n  labs: \"Espaço de laboratório\"\n  workshops: \"Espaço de oficina\"\n  psiLabs: \"Espaço de laboratório psíquico\"\n  trainingRooms: \"Espaço de academia\"\n  sightRange: \"Alcance de visão\"\n  sightChance: \"Chance de visão\"\n  radarRange: \"Alcance do radar\"\n  radarChance: \"Chance de radar\"\n  defense: \"Valor de defesa\"\n  hitRatio: \"Chance de acerto\"\n  ammoNeeded: \"Munição necessária\"\n  unifiedDamageFormula: \"\"\n  ammoItem: \"Item de munição\"\n  maxAllowedPerBase: \"Máximo permitido por base\"\n  manaRecoveryPerDay: \"Mana por dia\"\n  healthRecoveryPerDay: \"Saúde por dia\"\n  sickBayAbsoluteBonus: \"Bônus absoluto da enfermaria\"\n  sickBayRelativeBonus: \"Bônus relativo da enfermaria\"\n  prisonType: \"Tipo de prisão\"\n  rightClickActionType: \"Ação do clique direito\"\n  leavesBehindOnSell: \"Deixa para trás ao vender\"\n  removalTime: \"Tempo de remoção\"\n  canBeBuiltOver: \"Pode ser construído sobre ele?\"\n  upgradeOnly: \"\"\n  buildOverFacilities: \"Instalações de construção\"\n#\n  BFRCT_DEFAULT: \"padrão baunilha\"\n  BFRCT_PRISON: \"ir para Confinamento de Alienígenas\"\n  BFRCT_ENGINEERING: \"ir para Produção\"\n  BFRCT_RESEARCH: \"ir para Pesquisa\"\n  BFRCT_GYM: \"ir para Treinamento Marcial\"\n  BFRCT_PSI_LABS: \"ir para Laboratórios Psíquicos\"\n  BFRCT_BARRACKS: \"ir para Quartéis\"\n  BFRCT_GREY_MARKET: \"ir para Mercado Cinza\"\n  BFRCT_GEOSCAPE: \"ir para Tela Global\"\n#\n  costRent: \"Custo de aluguel\"\n  soldiers: \"Espaço de carga\"\n  maxUnitsLimit: \"Limite máximo de carga\"\n  pilots: \"Tamanho da cabine\"\n  pilotMinStatsRequired: \"\"\n  pilotSoldierBonusesRequired: \"\"\n  vehicles: \"Capacidade de PAP\"\n  onlyOneSoldierGroupAllowed: \"Apenas um grupo de soldados permitido?\"\n  allowedSoldierGroups: \"Grupos de soldados permitidos\"\n  allowedArmorGroups: \"\"\n  limitArmorGroups: \"\"\n  maxHWPUnitsLimit: \"Capacidade máxima de PAP\"\n  maxSmallSoldiers: \"Máximo de soldados pequenos\"\n  maxLargeSoldiers: \"Máximo de soldados grandes\"\n  maxSmallVehicles: \"Máximo de veículos pequenos\"\n  maxLargeVehicles: \"Máximo de veículos grandes\"\n  maxSmallUnits: \"Máximo de unidades pequenas\"\n  maxLargeUnits: \"Máximo de unidades grandes\"\n  maxSoldiers: \"Máximo de soldados\"\n  maxVehicles: \"Máximo de veículos\"\n  maxItems: \"Limite de equipamentos\"\n  maxStorageSpace: \"Espaço de armazenamento\"\n  maxAltitude: \"Limite de altitude de combate\"\n  weapons: \"Sistemas de armas\"\n  weaponStrings: \"Nomes das armas\"\n  fixedWeapons: \"Armas fixas\"\n  weaponTypes: \"Tipos de armas permitidas\"\n  damageMax: \"Capacidade máxima de dano\"\n  avoidBonus: \"Bônus de esquiva (fixo)\"\n  avoidBonus2: \"\"\n  powerBonus: \"Bônus de poder (fixo)\"\n  hitBonus: \"Bônus de acerto (fixo)\"\n  fuelMax: \"Capacidade de combustível\"\n  speedMax: \"Velocidade máxima\"\n  accel: \"Aceleração\"\n  shieldCapacity: \"Capacidade do escudo\"\n  shieldRecharge: \"Recarga do escudo (Combate)\"\n  shieldRechargeInGeoscape: \"Recarga do escudo (Globo)\"\n  shieldBleedThrough: \"Perda de escudo\"\n  shieldRechargedAtBase: \"Recarga do escudo (Base)\"\n  refuelItem: \"Item de reabastecimento\"\n  refuelRate: \"Taxa de reabastecimento\"\n  repairRate: \"Taxa de reparo\"\n  spacecraft: \"Nave final?\"\n  allowLanding: \"Permitir pouso?\"\n  notifyWhenRefueled: \"Notificar quando reabastecido?\"\n  autoPatrol: \"Auto-patrulha?\"\n  undetectable: \"Indetectável?\"\n  patrolWithoutFuel: \"\"\n  keepCraftAfterFailedMission: \"Paraquedistas?\"\n  _calculatedValues: \"Valores calculados\"\n  _maxRange: \"Alcance máximo\"\n  _minRange: \"Alcance mínimo\"\n  _avgRange: \"Alcance médio\"\n#\n  hunterKillerPercentage: \"Chance de caça\"\n  huntMode: \"Modo de caça\"\n  huntSpeed: \"Velocidade de caça\"\n  huntBehavior: \"Comportamento de caça\"\n  range: \"Alcance\"\n  reload: \"Tempo de recarga\"\n  breakOffTime: \"Tempo de afastamento\"\n  score: \"Pontuação\"\n  missionScore: \"Pontuação da missão\"\n  craftCustomDeploy: \"Implantação no local de OVNI\"\n  missionCustomDeploy: \"Implantação no local da missão\"\n  _escapeCountdown: \"Contagem regressiva de fuga\"\n  _fireRate: \"Taxa de disparo\"\n  _averageDPM: \"DPM médio\"\n#\n  HM_INTERCEPTORS: \"preferir caçar interceptores\"\n  HM_TRANSPORTS: \"preferir caçar transportes\"\n  HM_RANDOM: \"aleatório\"\n#\n  HB_FLEE: \"fugir ao perder\"\n  HB_KAMIKAZE: \"lutar até ser destruído\"\n  HB_RANDOM: \"aleatório\"\n#\n  tractorBeamPower: \"Poder do raio trator\"\n  damage: \"Dano\"\n  shieldDamageModifier: \"Modificador de dano do escudo\"\n  accuracy: \"Precisão\"\n  reloadCautious: \"Recarga (Cautelosa)\"\n  reloadStandard: \"Recarga (Padrão)\"\n  reloadAggressive: \"Recarga (Agressiva)\"\n  launcher: \"Item lançador\"\n  weaponType: \"Tipo de arma\"\n  clip: \"Item do pente\"\n  ammoMax: \"Munição máxima\"\n  rearmRate: \"Taxa de rearme\"\n  bulletSaving: \"Economia de balas?\"\n  _damageRange: \"\"\n  _damageRangeBasic: \"\"\n  _averageTotalDamage: \"Dano total médio\"\n#\n  allowPiloting: \"\"\n  costSalary: \"\"\n  costSalarySquaddie: \"\"\n  costSalarySergeant: \"\"\n  costSalaryCaptain: \"\"\n  costSalaryColonel: \"\"\n  costSalaryCommander: \"\"\n#\n  race: \"\"\n  rank: \"\"\n  livingWeapon: \"\"\n  meleeWeapon: \"Arma corpo a corpo\"\n  psiWeapon: \"\"\n  _builtInWeaponSets: \"\"\n  _weightedBuiltInWeaponSets: \"\"\n  spawnUnit: \"\"\n  _capturable: \"\"\n  capturable: \"\"\n  canSurrender: \"\"\n  autoSurrender: \"\"\n  spotter: \"\"\n  sniper: \"\"\n"
  },
  {
    "path": "bin/common/Language/Technical/ro.yml",
    "content": "ro:\n#=================== Menu ===================\n#TestState.cpp\n  STR_BAD_NODES: \"\"\n  STR_BAD_NODES_DESC: \"Verifică fișiere RMP de noduri dinafara marginilor hărții.{NEWLINE} Acestea NU vor cauza crash-uri, dar vor fii ignorate de joc, deci nu vor function corect. \"\n#\n  STR_MCD_CHECK: \"\"\n  STR_MCD_CHECK_DESC: \"\"\n#\n  STR_PALETTE_CHECK: \"\"\n  STR_PALETTE_CHECK_DESC: \"\"\n#\n  STR_SCRIPT_TAGS: \"\"\n  STR_SCRIPT_TAGS_DESC: \"\"\n#\n  STR_MAP_RESOURCES: \"\"\n  STR_MAP_RESOURCES_DESC: \"\"\n#\n  STR_CHECKING_TERRAIN: \"Verficare teren...\"\n  STR_CHECKING_UFOS: \"Verificare OZN-uri...\"\n  STR_CHECKING_CRAFT: \"Verificare navă...\"\n#\n  BACKPALS.DAT: \"\"\n  PAL_GEOSCAPE: \"PAL_GEOSCAPE\"\n  PAL_BASESCAPE: \"PAL_BASESCAPE\"\n  PAL_GRAPHS: \"PAL_GRAPHS\"\n  PAL_UFOPAEDIA: \"PAL_UFOPAEDIA\"\n  PAL_BATTLEPEDIA: \"PAL_BATTLEPEDIA\"\n  PAL_BATTLESCAPE: \"PAL_BATTLESCAPE\"\n  PAL_BATTLESCAPE_1: \"PAL_BATTLESCAPE_1\"\n  PAL_BATTLESCAPE_2: \"PAL_BATTLESCAPE_2\"\n  PAL_BATTLESCAPE_3: \"PAL_BATTLESCAPE_3\"\n#=================== Ufopaedia ===================\n#StatsForNerdsState.cpp\n  BT_NONE: \"\"\n  BT_FIREARM: \"\"\n  BT_AMMO: \"\"\n  BT_MELEE: \"\"\n  BT_GRENADE: \"\"\n  BT_PROXIMITYGRENADE: \"\"\n  BT_MEDIKIT: \"\"\n  BT_SCANNER: \"\"\n  BT_MINDPROBE: \"\"\n  BT_PSIAMP: \"\"\n  BT_FLARE: \"\"\n  BT_CORPSE: \"\"\n#\n  DRT_DEFAULT: \"\"\n  DRT_UFO: \"\"\n  DRT_TFTD: \"\"\n  DRT_FLAT: \"\"\n  DRT_FIRE: \"\"\n  DRT_NONE: \"\"\n  DRT_UFO_WITH_TWO_DICE: \"\"\n  DRT_EASY: \"\"\n  DRT_STANDARD: \"\"\n  DRT_EXPLOSION: \"\"\n#\n  BFT_NONE: \"\"\n  BFT_INSTANT: \"\"\n  BFT_SET: \"\"\n  BFT_FIXED: \"\"\n#\n  BMT_NORMAL: \"\"\n  BMT_HEAL: \"\"\n  BMT_STIMULANT: \"\"\n  BMT_PAINKILLER: \"\"\n#\n  ETM_DEFAULT: \"\"\n  ETM_MELEE_100: \"\"\n  ETM_MELEE_50: \"\"\n  ETM_MELEE_33: \"\"\n  ETM_FIRING_100: \"\"\n  ETM_FIRING_50: \"\"\n  ETM_FIRING_33: \"\"\n  ETM_THROWING_100: \"\"\n  ETM_THROWING_50: \"\"\n  ETM_THROWING_33: \"\"\n  ETM_FIRING_AND_THROWING: \"\"\n  ETM_FIRING_OR_THROWING: \"\"\n  ETM_REACTIONS: \"\"\n  ETM_REACTIONS_AND_MELEE: \"\"\n  ETM_REACTIONS_AND_FIRING: \"\"\n  ETM_REACTIONS_AND_THROWING: \"\"\n  ETM_REACTIONS_OR_MELEE: \"\"\n  ETM_REACTIONS_OR_FIRING: \"\"\n  ETM_REACTIONS_OR_THROWING: \"\"\n  ETM_BRAVERY: \"\"\n  ETM_BRAVERY_2X: \"\"\n  ETM_BRAVERY_AND_REACTIONS: \"\"\n  ETM_BRAVERY_OR_REACTIONS: \"\"\n  ETM_BRAVERY_OR_REACTIONS_2X: \"\"\n  ETM_PSI_STRENGTH: \"\"\n  ETM_PSI_STRENGTH_2X: \"\"\n  ETM_PSI_SKILL: \"\"\n  ETM_PSI_SKILL_2X: \"\"\n  ETM_PSI_STRENGTH_AND_SKILL: \"\"\n  ETM_PSI_STRENGTH_AND_SKILL_2X: \"\"\n  ETM_PSI_STRENGTH_OR_SKILL: \"\"\n  ETM_PSI_STRENGTH_OR_SKILL_2X: \"\"\n  ETM_NOTHING: \"\"\n#\n  battleType: \"\"\n  experienceTrainingMode: \"\"\n  manaExperience: \"\"\n  arcingShot: \"\"\n  isFireExtinguisher: \"\"\n  isExplodingInHands: \"\"\n  waypoints: \"\"\n  sprayWaypoints: \"\"\n#\n  shotgunPellets: \"\"\n  shotgunBehavior: \"\"\n  shotgunSpread: \"\"\n  shotgunChoke: \"\"\n#\n  underwaterOnly: \"\"\n  landOnly: \"\"\n  psiRequired: \"\"\n  targetMatrix: \"\"\n  manaRequired: \"\"\n  LOSRequired: \"\"\n#\n  noLOSAccuracyPenalty: \"\"\n  kneelBonus: \"\"\n  twoHanded: \"\"\n  blockBothHands: \"\"\n  oneHandedPenalty: \"\"\n#\n  minRange: \"\"\n  maxRange: \"\"\n  aimRange: \"\"\n  autoRange: \"\"\n  snapRange: \"\"\n  dropoff: \"\"\n#\n  accuracyMultiplier: \"\"\n  accuracyAimed: \"\"\n  accuracyAuto: \"\"\n  accuracySnap: \"\"\n  costAimed: \"\"\n  costAuto: \"\"\n  costSnap: \"\"\n#\n  meleeMultiplier: \"\"\n  accuracyMelee: \"\"\n  costMelee: \"\"\n#\n  psiAttackName: \"\"\n  accuracyUse: \"\"\n  accuracyMindControl: \"\"\n  accuracyPanic: \"\"\n  costUse: \"\"\n  costMindcontrol: \"\"\n  costPanic: \"\"\n#\n  weight: \"\"\n  throwRange: \"\"\n  underwaterThrowRange: \"\"\n  throwMultiplier: \"\"\n  accuracyThrow: \"\"\n  costThrow: \"\"\n  costPrime: \"\"\n  costUnprime: \"\"\n#\n  closeQuartersMultiplier: \"\"\n  accuracyCloseQuarters: \"\"\n#\n  damageType: \"\"\n  power: \"\"\n  powerRangeReduction: \"\"\n  powerRangeThreshold: \"\"\n  damageBonus: \"\"\n  blastRadius: \"\"\n  damageAlter: \"\"\n  meleeType: \"\"\n  meleePower: \"\"\n  meleeBonus: \"\"\n  meleeAlter: \"\"\n  FixRadius: \"\"\n  RandomType: \"\"\n  FireBlastCalc: \"\"\n  IgnoreDirection: \"\"\n  IgnoreSelfDestruct: \"\"\n  IgnorePainImmunity: \"\"\n  IgnoreNormalMoraleLose: \"\"\n  IgnoreOverKill: \"\"\n  ArmorEffectiveness: \"\"\n  RadiusEffectiveness: \"\"\n  RadiusReduction: \"\"\n  FireThreshold: \"\"\n  SmokeThreshold: \"\"\n#\n  ToArmorPre: \"\"\n  RandomArmorPre: \"\"\n  ToArmor: \"\"\n  RandomArmor: \"\"\n  ToHealth: \"\"\n  RandomHealth: \"\"\n  ToStun: \"\"\n  RandomStun: \"\"\n  ToWound: \"\"\n  RandomWound: \"\"\n  ToTime: \"\"\n  RandomTime: \"\"\n  ToEnergy: \"\"\n  RandomEnergy: \"\"\n  ToMorale: \"\"\n  RandomMorale: \"\"\n  ToItem: \"\"\n  RandomItem: \"\"\n  ToMana: \"\"\n  RandomMana: \"\"\n  ToTile: \"\"\n  RandomTile: \"\"\n  TileDamageMethod: \"\"\n#\n  confAimed: \"\"\n  confAuto: \"\"\n  confSnap: \"\"\n  confMelee: \"\"\n  shots: \"\"\n  spendPerShot: \"\"\n  followProjectiles: \"\"\n  name: \"\"\n  shortName: \"\"\n  ammoSlot: \"\"\n  arcing: \"\"\n#\n  clipSize: \"\"\n#\n  primaryAmmo: \"\"\n  compatibleAmmo: \"\"\n  tuLoad: \"\"\n  tuUnload: \"\"\n  ammo[1]: \"\"\n  ammo[2]: \"\"\n  ammo[3]: \"\"\n#\n  armor: \"\"\n#\n  medikitType: \"\"\n  medikitActionName: \"\"\n  medikitTargetSelf: \"\"\n  medikitTargetImmune: \"\"\n  medikitTargetMatrix: \"\"\n  isConsumable: \"\"\n  painKiller: \"\"\n  heal: \"\"\n  stimulant: \"\"\n  woundRecovery: \"\"\n  healthRecovery: \"\"\n  stunRecovery: \"\"\n  energyRecovery: \"\"\n  manaRecovery: \"\"\n  moraleRecovery: \"\"\n  painKillerRecovery: \"\"\n#\n  requires: \"\"\n  requiresBuy: \"\"\n  requiresBuyBaseFunc: \"\"\n  requiresBuyCountry: \"\"\n  categories: \"\"\n  supportedInventorySections: \"\"\n#\n  size: \"\"\n  costBuy: \"\"\n  monthlyBuyLimit: \"\"\n  costSell: \"\"\n  transferTime: \"\"\n  monthlySalary: \"\"\n  monthlyMaintenance: \"\"\n#\n  SPECAB_NONE: \"\"\n  SPECAB_EXPLODEONDEATH: \"\"\n  SPECAB_BURNFLOOR: \"\"\n  SPECAB_BURN_AND_EXPLODE: \"\"\n#\n  MT_WALK: \"\"\n  MT_FLY: \"\"\n  MT_SLIDE: \"\"\n  MT_FLOAT: \"\"\n  MT_SINK: \"\"\n#\n  TORSO_USE_GENDER: \"\"\n  TORSO_ALWAYS_MALE: \"\"\n  TORSO_ALWAYS_FEMALE: \"\"\n#\n  DRAWING_ROUTINE_SOLDIER_SECTOID: \"\"\n  DRAWING_ROUTINE_FLOATER: \"\"\n  DRAWING_ROUTINE_HWP: \"\"\n  DRAWING_ROUTINE_CYBERDISC: \"\"\n  DRAWING_ROUTINE_CIVILIAN_ETHEREAL: \"\"\n  DRAWING_ROUTINE_SECTOPOD_REAPER: \"\"\n  DRAWING_ROUTINE_SNAKEMAN: \"\"\n  DRAWING_ROUTINE_CHRYSSALID: \"\"\n  DRAWING_ROUTINE_SILACOID: \"\"\n  DRAWING_ROUTINE_CELATID: \"\"\n  DRAWING_ROUTINE_MUTON: \"\"\n  DRAWING_ROUTINE_SWS: \"\"\n  DRAWING_ROUTINE_HALLUCINOID: \"\"\n  DRAWING_ROUTINE_AQUANAUTS: \"\"\n  DRAWING_ROUTINE_CALCINITE_AND_MORE: \"\"\n  DRAWING_ROUTINE_AQUATOID: \"\"\n  DRAWING_ROUTINE_BIO_DRONE: \"\"\n  DRAWING_ROUTINE_TFTD_CIVILIAN_A: \"\"\n  DRAWING_ROUTINE_TFTD_CIVILIAN_B: \"\"\n  DRAWING_ROUTINE_TENTACULAT: \"\"\n  DRAWING_ROUTINE_TRISCENE: \"\"\n  DRAWING_ROUTINE_XARQUID: \"\"\n  DRAWING_ROUTINE_INVERTED_CYBERDISC: \"\"\n#\n  stats: \"\"\n  specab: \"\"\n  movementType: \"\"\n  allowsRunning: \"\"\n  allowsStrafing: \"\"\n  allowsSneaking: \"\"\n  allowsKneeling: \"\"\n  allowsMoving: \"\"\n  fearImmune: \"\"\n  bleedImmune: \"\"\n  painImmune: \"\"\n  zombiImmune: \"\"\n  ignoresMeleeThreat: \"\"\n  createsMeleeThreat: \"\"\n  builtInWeapons: \"\"\n  specialWeapon: \"\"\n  heatVision: \"\"\n  psiVision: \"\"\n  psiCamouflage: \"\"\n  visibilityAtDay: \"\"\n  visibilityAtDark: \"\"\n  camouflageAtDay: \"\"\n  camouflageAtDark: \"\"\n  antiCamouflageAtDay: \"\"\n  antiCamouflageAtDark: \"\"\n  psiDefence: \"\"\n  meleeDodge: \"\"\n  meleeDodgeBackPenalty: \"\"\n  recovery: \"\"\n  time: \"\"\n  energy: \"\"\n  morale: \"\"\n  health: \"\"\n  stun: \"\"\n  mana: \"\"\n  units: \"\"\n  frontArmor: \"\"\n  sideArmor: \"\"\n  leftArmorDiff: \"\"\n  rearArmor: \"\"\n  underArmor: \"\"\n#\n  buildCost: \"\"\n  buildCostItems: \"\"\n  buildTime: \"\"\n  monthlyCost: \"\"\n  refundValue: \"\"\n  requiresBaseFunc: \"\"\n  provideBaseFunc: \"\"\n  forbiddenBaseFunc: \"\"\n  lift: \"\"\n  hyper: \"\"\n  mind: \"\"\n  mindPower: \"\"\n  grav: \"\"\n  storage: \"\"\n  personnel: \"\"\n  aliens: \"\"\n  crafts: \"\"\n  labs: \"\"\n  workshops: \"\"\n  psiLabs: \"\"\n  trainingRooms: \"\"\n  sightRange: \"\"\n  sightChance: \"\"\n  radarRange: \"\"\n  radarChance: \"\"\n  defense: \"\"\n  hitRatio: \"\"\n  ammoNeeded: \"\"\n  ammoItem: \"\"\n  maxAllowedPerBase: \"\"\n  manaRecoveryPerDay: \"\"\n  healthRecoveryPerDay: \"\"\n  sickBayAbsoluteBonus: \"\"\n  sickBayRelativeBonus: \"\"\n  prisonType: \"\"\n  rightClickActionType: \"\"\n  leavesBehindOnSell: \"\"\n  removalTime: \"\"\n  canBeBuiltOver: \"\"\n  buildOverFacilities: \"\"\n#\n  BFRCT_DEFAULT: \"\"\n  BFRCT_PRISON: \"\"\n  BFRCT_ENGINEERING: \"\"\n  BFRCT_RESEARCH: \"\"\n  BFRCT_GYM: \"\"\n  BFRCT_PSI_LABS: \"\"\n  BFRCT_BARRACKS: \"\"\n  BFRCT_GREY_MARKET: \"\"\n  BFRCT_GEOSCAPE: \"\"\n#\n  costRent: \"\"\n  soldiers: \"\"\n  pilots: \"\"\n  vehicles: \"\"\n  maxSmallSoldiers: \"\"\n  maxLargeSoldiers: \"\"\n  maxSmallVehicles: \"\"\n  maxLargeVehicles: \"\"\n  maxSmallUnits: \"\"\n  maxLargeUnits: \"\"\n  maxSoldiers: \"\"\n  maxVehicles: \"\"\n  maxItems: \"\"\n  maxStorageSpace: \"\"\n  maxAltitude: \"\"\n  weapons: \"\"\n  weaponStrings: \"\"\n  fixedWeapons: \"\"\n  weaponTypes: \"\"\n  damageMax: \"\"\n  avoidBonus: \"\"\n  powerBonus: \"\"\n  hitBonus: \"\"\n  fuelMax: \"\"\n  speedMax: \"\"\n  accel: \"\"\n  shieldCapacity: \"\"\n  shieldRecharge: \"\"\n  shieldRechargeInGeoscape: \"\"\n  shieldBleedThrough: \"\"\n  shieldRechargedAtBase: \"\"\n  refuelItem: \"\"\n  refuelRate: \"\"\n  repairRate: \"\"\n  spacecraft: \"\"\n  allowLanding: \"\"\n  notifyWhenRefueled: \"\"\n  autoPatrol: \"\"\n  undetectable: \"\"\n  keepCraftAfterFailedMission: \"\"\n  _calculatedValues: \"\"\n  _maxRange: \"\"\n  _minRange: \"\"\n  _avgRange: \"\"\n#\n  hunterKillerPercentage: \"\"\n  huntMode: \"\"\n  huntSpeed: \"\"\n  huntBehavior: \"\"\n  range: \"\"\n  reload: \"\"\n  breakOffTime: \"\"\n  score: \"\"\n  missionScore: \"\"\n  craftCustomDeploy: \"\"\n  missionCustomDeploy: \"\"\n  _escapeCountdown: \"\"\n  _fireRate: \"\"\n  _averageDPM: \"\"\n#\n  HM_INTERCEPTORS: \"\"\n  HM_TRANSPORTS: \"\"\n  HM_RANDOM: \"\"\n#\n  HB_FLEE: \"\"\n  HB_KAMIKAZE: \"\"\n  HB_RANDOM: \"\"\n#\n  tractorBeamPower: \"\"\n  damage: \"\"\n  shieldDamageModifier: \"\"\n  accuracy: \"\"\n  reloadCautious: \"\"\n  reloadStandard: \"\"\n  reloadAggressive: \"\"\n  launcher: \"\"\n  weaponType: \"\"\n  clip: \"\"\n  ammoMax: \"\"\n  rearmRate: \"\"\n  bulletSaving: \"\"\n  _averageTotalDamage: \"\"\n"
  },
  {
    "path": "bin/common/Language/Technical/ru.yml",
    "content": "ru:\n#=================== Menu ===================\n#TestState.cpp\n  STR_BAD_NODES: \"Ошибочные узлы в файлах RMP\"\n  STR_BAD_NODES_DESC: \"Ищет узлы, расположенные за пределами карты.{NEWLINE}Это не приводит к падению игры, однако ошибочные узлы будут проигн., а значит, поведение игры будет отличаться от запланир.\"\n#\n  STR_MCD_CHECK: \"Проверка MCD\"\n  STR_MCD_CHECK_DESC: \"Проверяет файлы MCD на наличие тайлов, на пересечение которых не расходуются ОД. Также ищет некорректные ссылки DieMCD / AltMCD и проверяет LOFTemps.\"\n#\n  STR_PALETTE_CHECK: \"Сопоставление палитры\"\n  STR_PALETTE_CHECK_DESC: \"Сопоставляет палитры модифицированных изображений с официальными и выводит предупреждение при обнаружении несоответствий.\"\n#\n  STR_SCRIPT_TAGS: \"Экспорт тегов скриптов\"\n  STR_SCRIPT_TAGS_DESC: \"Экспорт тегов скриптов в формате CSV.\"\n#\n  STR_MAP_RESOURCES: \"Проверка ассетов карт\"\n  STR_MAP_RESOURCES_DESC: \"Ищет незадействованные или отсутствующие файлы и рулсеты в картах.\"\n#\n  STR_CHECKING_TERRAIN: \"Проверка ландшафта...\"\n  STR_CHECKING_UFOS: \"Проверка НЛО...\"\n  STR_CHECKING_CRAFT: \"Проверка ТС...\"\n#\n  BACKPALS.DAT: \"BACKPALS.DAT\"\n  PAL_GEOSCAPE: \"ПАЛ_ЗЕМЛЯ\"\n  PAL_BASESCAPE: \"ПАЛ_БАЗА\"\n  PAL_GRAPHS: \"ПАЛ_ГРАФИКИ\"\n  PAL_UFOPAEDIA: \"ПАЛ_УФОПЕДИЯ\"\n  PAL_BATTLEPEDIA: \"ПАЛ_УФОПЕДИЯ_БОЙ\"\n  PAL_BATTLESCAPE: \"ПАЛ_ПОЛЕ_БОЯ\"\n  PAL_BATTLESCAPE_1: \"ПАЛ_ПОЛЕ_БОЯ_1\"\n  PAL_BATTLESCAPE_2: \"ПАЛ_ПОЛЕ_БОЯ_2\"\n  PAL_BATTLESCAPE_3: \"ПАЛ_ПОЛЕ_БОЯ_3\"\n#=================== Ufopaedia ===================\n#StatsForNerdsState.cpp\n  BT_NONE: \"Нет\"\n  BT_FIREARM: \"Огнестрельное оружие\"\n  BT_AMMO: \"Боеприпас\"\n  BT_MELEE: \"Оружие ближнего боя\"\n  BT_GRENADE: \"Граната\"\n  BT_PROXIMITYGRENADE: \"Сенсорная граната\"\n  BT_MEDIKIT: \"Медкомплект\"\n  BT_SCANNER: \"Сенсор\"\n  BT_MINDPROBE: \"Ментальный зонд\"\n  BT_PSIAMP: \"Пси-усилитель\"\n  BT_FLARE: \"Осветитель\"\n  BT_CORPSE: \"Труп/Тело\"\n#\n  DRT_DEFAULT: \"как в оригинале\"\n  DRT_UFO: \"Урон 0-200%\"\n  DRT_TFTD: \"Урон 50-150%\"\n  DRT_FLAT: \"равномерный урон\"\n  DRT_FIRE: \"урон от пламени\"\n  DRT_NONE: \"не наносит урона\"\n  DRT_UFO_WITH_TWO_DICE: \"Урон 0-200% (с 2 бросками кубика)\"\n  DRT_EASY: \"Урон 50-200%\"\n  DRT_STANDARD: \"обычный разброс урона\"\n  DRT_EXPLOSION: \"фугасный разброс урона\"\n#\n  BFT_NONE: \"отсутствует\"\n  BFT_INSTANT: \"мгновен. действия\"\n  BFT_SET: \"устан. вручную\"\n  BFT_FIXED: \"фиксированный\"\n#\n  BMT_NORMAL: \"обычный (многоцелевой)\"\n  BMT_HEAL: \"перевязка\"\n  BMT_STIMULANT: \"стимулятор\"\n  BMT_PAINKILLER: \"обезболивающее\"\n#\n  ETM_DEFAULT: \"стандартный\"\n  ETM_MELEE_100: \"БЛИЖНИЙ БОЙ\"\n  ETM_MELEE_50: \"БЛ. БОЙ (вероятность 50%)\"\n  ETM_MELEE_33: \"БЛ. БОЙ (вероятность 33%)\"\n  ETM_FIRING_100: \"ТОЧН. ВЫСТР.\"\n  ETM_FIRING_50: \"ТОЧН. ВЫСТР. (вероятность 50%)\"\n  ETM_FIRING_33: \"ТОЧН. ВЫСТР. (вероятность 33%)\"\n  ETM_THROWING_100: \"ТОЧН. БРОСКА\"\n  ETM_THROWING_50: \"ТОЧН. БРОСКА (вероятность 50%)\"\n  ETM_THROWING_33: \"ТОЧН. БРОСКА (вероятность 33%)\"\n  ETM_FIRING_AND_THROWING: \"ТОЧН. ВЫСТР. и ТОЧН. БРОСКА\"\n  ETM_FIRING_OR_THROWING: \"ТОЧН. ВЫСТР. или ТОЧН. БРОСКА\"\n  ETM_REACTIONS: \"РЕАКЦИЯ\"\n  ETM_REACTIONS_AND_MELEE: \"РЕАКЦИЯ и БЛИЖНИЙ БОЙ\"\n  ETM_REACTIONS_AND_FIRING: \"РЕАКЦИЯ И ТОЧН. ВЫСТР.\"\n  ETM_REACTIONS_AND_THROWING: \"РЕАКЦИЯ и ТОЧН. БРОСКА\"\n  ETM_REACTIONS_OR_MELEE: \"РЕАКЦИЯ или БЛИЖНИЙ БОЙ\"\n  ETM_REACTIONS_OR_FIRING: \"РЕАКЦИЯ или ТОЧН. ВЫСТР.\"\n  ETM_REACTIONS_OR_THROWING: \"РЕАКЦИЯ или ТОЧН. БРОСКА\"\n  ETM_BRAVERY: \"ХРАБРОСТЬ\"\n  ETM_BRAVERY_2X: \"ХРАБРОСТЬ (x2)\"\n  ETM_BRAVERY_AND_REACTIONS: \"ХРАБРОСТЬ и РЕАКЦИЯ\"\n  ETM_BRAVERY_OR_REACTIONS: \"ХРАБРОСТЬ или РЕАКЦИЯ\"\n  ETM_BRAVERY_OR_REACTIONS_2X: \"ХРАБРОСТЬ или РЕАКЦИЯ (x2)\"\n  ETM_PSI_STRENGTH: \"ПСИ-СИЛА\"\n  ETM_PSI_STRENGTH_2X: \"ПСИ-СИЛА (x2)\"\n  ETM_PSI_SKILL: \"ПСИ-НАВЫК\"\n  ETM_PSI_SKILL_2X: \"ПСИ-НАВЫК (x2)\"\n  ETM_PSI_STRENGTH_AND_SKILL: \"ПСИ-СИЛА и ПСИ-НАВЫК\"\n  ETM_PSI_STRENGTH_AND_SKILL_2X: \"ПСИ-СИЛА и ПСИ-НАВЫК (x2)\"\n  ETM_PSI_STRENGTH_OR_SKILL: \"ПСИ-СИЛА или ПСИ-НАВЫК\"\n  ETM_PSI_STRENGTH_OR_SKILL_2X: \"ПСИ-СИЛА или ПСИ-НАВЫК (x2)\"\n  ETM_NOTHING: \"не тренирует\"\n#\n  battleType: \"Тип предмета\"\n  experienceTrainingMode: \"Режим тренировки\"\n  manaExperience: \"Опыт для маны\"\n  arcingShot: \"Навесная стрельба?\"\n  isFireExtinguisher: \"Тушение огня?\"\n  explodeInventory: \"Взрывается в инвентаре?\"\n  waypoints: \"Макс. точек траектории\"\n  sprayWaypoints: \"Точек веерного огня\"\n#\n  shotgunPellets: \"Количество дроби\"\n  shotgunBehavior: \"Дробовик\"\n  shotgunSpread: \"Разлет дроби\"\n  shotgunChoke: \"Чок-бор для дробовика\"\n#\n  underwaterOnly: \"Только подводное?\"\n  landOnly: \"Только атмосферное?\"\n  psiRequired: \"Требует пси-навыка?\"\n  targetMatrix: \"Предмет действует на\"\n  convertToCivilian: \"Превращает в штатского?\"\n  manaRequired: \"Требует маны?\"\n  LOSRequired: \"Нужна прям. видимость?\"\n#\n  noLOSAccuracyPenalty: \"Множит. штрафа за отсут. прямой видимости\"\n  kneelBonus: \"Множит. бонуса в приседе\"\n  twoHanded: \"Двуручное?\"\n  blockBothHands: \"Занимает обе руки?\"\n  oneHandedPenalty: \"Штраф за наличие предмета в др. руке\"\n#\n  minRange: \"Мин. дальность\"\n  maxRange: \"Макс. дальность\"\n  aimRange: \"Дальн. прицел. стрельбы\"\n  autoRange: \"Дальн. стрельбы очер.\"\n  snapRange: \"Дальн. выстр. навскидку\"\n  dropoff: \"Снижение точности/тайл\"\n#\n  accuracyMultiplier: \"Множит. точн. выстрела\"\n  accuracyAimed: \"Точн. прицел. выстрела\"\n  accuracyAuto: \"Точн. стрельбы очер.\"\n  accuracySnap: \"Точн. выстр. навскидку\"\n  costAimed: \"Стоимость прицельного выстрела\"\n  costAuto: \"Стоимость стрельбы очередью\"\n  costSnap: \"Стоимость выстрела навскидку\"\n#\n  meleeMultiplier: \"Множит. вероятности попадания в бл. бою\"\n  accuracyMelee: \"Вероятность попадания в ближнем бою\"\n  costMelee: \"Стоимость атаки в ближнем бою\"\n#\n  psiAttackName: \"Вид пси-атаки\"\n  accuracyUse: \"Точность использования\"\n  accuracyMindControl: \"Точность контроля сознания\"\n  accuracyPanic: \"Точность вызова паники\"\n  costUse: \"Стоимость использования\"\n  costMindcontrol: \"Стоимость попытки контроля сознания\"\n  costPanic: \"Стоимость попытки вызова паники\"\n#\n  weight: \"Вес\"\n  throwRange: \"Макс. дальн. броска (поверх.)\"\n  underwaterThrowRange: \"Макс. дальн. броска (вода)\"\n  throwDropoffRange: \"Эффективная дальн. броска (поверх.)\"\n  underwaterThrowDropoffRange: \"Эффективная дальн. броска (вода)\"\n  throwDropoff: \"Снижение точности броска/тайл\"\n  throwMultiplier: \"Множит. точности броска\"\n  accuracyThrow: \"Точность броска\"\n  costThrow: \"Стоимость броска\"\n  costPrime: \"Стоимость взведения\"\n  costUnprime: \"Стоимость деактивации\"\n#\n  closeQuartersMultiplier: \"Множит. эффект. боя на кор. дистанции\"\n  accuracyCloseQuarters: \"Точность боя на короткой дистанции\"\n#\n  damageType: \"Вид урона\"\n  power: \"Урон\"\n  powerRangeReduction: \"Снижение урона/тайл\"\n  powerRangeThreshold: \"Порог снижения урона\"\n  damageBonus: \"Бонус к урону\"\n  blastRadius: \"Радиус взрыва\"\n  damageAlter: \"Урон. Доп. информация:\"\n  meleeType: \"Тип урона в ближнем бою\"\n  meleePower: \"Урон в ближнем бою\"\n  meleeBonus: \"Бонус к урону в ближнем бою\"\n  meleeAlter: \"Бл. бой. Доп. информация:\"\n  FixRadius: \"Радиус взрыва\"\n  RandomType: \"Алгоритм расчета вероятного урона\"\n  FireBlastCalc: \"Эффект огня от взрыва как в оригинале?\"\n  IgnoreDirection: \"Игнор. направления\"\n  IgnoreSelfDestruct: \"Игнор. самоуничтожения\"\n  IgnorePainImmunity: \"Игнор. иммунитета к оглушению\"\n  IgnoreNormalMoraleLose: \"Игнорирование снижения морали из оригинала\"\n  IgnoreOverKill: \"Не расчленяет\"\n  ArmorEffectiveness: \"Эффективность брони\"\n  RadiusEffectiveness: \"Радиус эффективности\"\n  RadiusReduction: \"Радиус снижения урона\"\n  FireThreshold: \"Порог воспламенения\"\n  SmokeThreshold: \"Порог образ. дыма\"\n#\n  ToArmorPre: \"Множит. брони до получения урона\"\n  RandomArmorPre: \"Разброс знач. брони до получения урона?\"\n  ToArmor: \"Множитель урона броне\"\n  RandomArmor: \"Разброс урона броне?\"\n  ToHealth: \"Множитель урона ОЗ\"\n  RandomHealth: \"Разброс урона ОЗ?\"\n  ToStun: \"Множит. оглуш. урона\"\n  RandomStun: \"Разброс оглуш. урона?\"\n  ToWound: \"Множит. числа ранений\"\n  RandomWound: \"Разброс ранений из оригинала?\"\n  ToTime: \"Множитель урона ОД\"\n  RandomTime: \"Разброс урона ОД?\"\n  ToEnergy: \"Множит. урона энергии\"\n  RandomEnergy: \"Разброс урона энергии?\"\n  ToMorale: \"Урон морали\"\n  RandomMorale: \"Разброс урона морали?\"\n  ToItem: \"Множитель урона предметам\"\n  RandomItem: \"Разброс урона предметам?\"\n  ToMana: \"Множит. урона мане\"\n  RandomMana: \"Разброс урона мане?\"\n  ToTile: \"Множит. урона местности\"\n  RandomTile: \"Разброс урона местности?\"\n  TileDamageMethod: \"Способ повреждения окружения\"\n  TileDamageLimit: \"Предел урона тайлам\"\n#\n  confAimed: \"Прицельный огонь:\"\n  confAuto: \"Стрельба очередью:\"\n  confSnap: \"Стрельба навскидку:\"\n  confMelee: \"Применение в бл. бою:\"\n  shots: \"Выстрелов в очереди\"\n  spendPerShot: \"Расход на выстрел:\"\n  followProjectiles: \"Отслеж. полета снаряда?\"\n  name: \"Наименование\"\n  shortName: \"Краткое наименование\"\n  ammoSlot: \"Используемый приемник боеприпасов\"\n  ammoZombieUnitChanceOverride: \"Вероятность зомбификации\"\n  ammoSpawnUnitChanceOverride: \"Вероятность генерации боевой единицы\"\n  ammoSpawnItemChanceOverride: \"Вероятность генерации предмета\"\n  arcing: \"Навесная стрельба?\"\n#\n  clipSize: \"Зарядов в магазине\"\n  isAmmoRechargeable: \"Заряд перезаряжается?\"\n#\n  primaryAmmo: \"Главный приемник боеприпасов:\"\n  compatibleAmmo: \"Использ. боеприпасы\"\n  tuLoad: \"ОД на заряжание\"\n  tuUnload: \"ОД на разряжание\"\n  ammo[1]: \"Приемник альтернативных боеприпасов #1:\"\n  ammo[2]: \"Приемник альтернативных боеприпасов #2:\"\n  ammo[3]: \"Приемник альтернативных боеприпасов #3:\"\n#\n  armor: \"Броня\"\n#\n  medikitType: \"Тип медкомплекта\"\n  painKillerActionName: \"Наименование эффекта обезболивающего\"\n  stimulantActionName: \"Наименование эффекта стимулятора\"\n  healActionName: \"Наименование эффекта перевязки\"\n  medikitActionName: \"Действие с аптечкой\"\n  medikitTargetSelf: \"Применение медкомплекта на себе?\"\n  medikitTargetImmune: \"Применение медкомплекта на иммунном к кровотечению?\"\n  medikitTargetMatrix: \"Объекты применения медкомплекта\"\n  isConsumable: \"Расходуется?\"\n  painKiller: \"Кол-во обезболивающих\"\n  heal: \"Количество перевязок\"\n  stimulant: \"Кол-во стимуляторов\"\n  woundRecovery: \"Лечение ран\"\n  healthRecovery: \"Восстан. здоровья\"\n  stunRecovery: \"Восстан. от оглушения\"\n  energyRecovery: \"Восстановление энергии\"\n  manaRecovery: \"Восстановление маны\"\n  moraleRecovery: \"Восстановление морали\"\n  painKillerRecovery: \"Эффективность обезболивающего\"\n#\n  requires: \"Необх. исследование\"\n  requiresBuy: \"Исследование, необх. для покупки\"\n  requiresBuyBaseFunc: \"Функции, необх. для покупки\"\n  requiresBuyCountry: \"Необходима страна-союзник\"\n  requiresAward: \"Требует награды\"\n  requiresBonus: \"Требует бонуса\"\n  categories: \"Категории\"\n  supportedInventorySections: \"Ячейки инвентаря\"\n#\n  size: \"Размер\"\n  costBuy: \"Цена покупки\"\n  monthlyBuyLimit: \"Лимит ежемесячных закупок\"\n  costSell: \"Цена продажи\"\n  transferTime: \"Часов на транспорт.\"\n  monthlySalary: \"Жалованье/месяц\"\n  monthlyMaintenance: \"Обслуживание/месяц\"\n#\n  SPECAB_NONE: \"Нет\"\n  SPECAB_EXPLODEONDEATH: \"Умирая, взрывается\"\n  SPECAB_BURNFLOOR: \"Прожигает поверхность\"\n  SPECAB_BURN_AND_EXPLODE: \"Умирая, прожигает поверхность и взрывается\"\n#\n  MT_WALK: \"Ходьба\"\n  MT_FLY: \"Полет\"\n  MT_SLIDE: \"Проскальзывание\"\n  MT_FLOAT: \"Плавание\"\n  MT_SINK: \"Погружение\"\n#\n  TORSO_USE_GENDER: \"Используется пол\"\n  TORSO_ALWAYS_MALE: \"Всегда мужской\"\n  TORSO_ALWAYS_FEMALE: \"Всегда женский\"\n#\n  DRAWING_ROUTINE_SOLDIER_SECTOID: \"Солдат, сектоид\"\n  DRAWING_ROUTINE_FLOATER: \"Летун\"\n  DRAWING_ROUTINE_HWP: \"Тяжелая боевая платформа\"\n  DRAWING_ROUTINE_CYBERDISC: \"Кибердиск\"\n  DRAWING_ROUTINE_CIVILIAN_ETHEREAL: \"Штатский, эфириал\"\n  DRAWING_ROUTINE_SECTOPOD_REAPER: \"Сектопод, потрошитель\"\n  DRAWING_ROUTINE_SNAKEMAN: \"Человекозмей\"\n  DRAWING_ROUTINE_CHRYSSALID: \"Криссалид\"\n  DRAWING_ROUTINE_SILACOID: \"Силакоид\"\n  DRAWING_ROUTINE_CELATID: \"Целатид\"\n  DRAWING_ROUTINE_MUTON: \"Мутон\"\n  DRAWING_ROUTINE_SWS: \"Подводное оружие\"\n  DRAWING_ROUTINE_HALLUCINOID: \"Галлюциноид\"\n  DRAWING_ROUTINE_AQUANAUTS: \"Акванавты\"\n  DRAWING_ROUTINE_CALCINITE_AND_MORE: \"Кальцинит, глубинник, гиллмен, лобстермен, тасот\"\n  DRAWING_ROUTINE_AQUATOID: \"Акватоид\"\n  DRAWING_ROUTINE_BIO_DRONE: \"Биодрон\"\n  DRAWING_ROUTINE_TFTD_CIVILIAN_A: \"Штатские TFTD, тип A, и зомби TFTD\"\n  DRAWING_ROUTINE_TFTD_CIVILIAN_B: \"Штатские TFTD, тип B\"\n  DRAWING_ROUTINE_TENTACULAT: \"Тентакулат\"\n  DRAWING_ROUTINE_TRISCENE: \"Трисцен\"\n  DRAWING_ROUTINE_XARQUID: \"Ксарквид\"\n  DRAWING_ROUTINE_INVERTED_CYBERDISC: \"Инвертированный кибердиск (сначала анимация перемещения)\"\n#\n  stats: \"Модификаторы показателей\"\n  specab: \"Особенность\"\n  movementType: \"Способ перемещения\"\n  allowsRunning: \"Позволяет бегать?\"\n  allowsStrafing: \"Позволяет двиг. боком?\"\n  allowsSneaking: \"Позволяет двиг. скрытно?\"\n  allowsKneeling: \"Позволяет приседать?\"\n  allowsMoving: \"Позволяет двигаться?\"\n  fearImmune: \"Иммунитет к снижению морали?\"\n  bleedImmune: \"Иммунитет к кровотечению?\"\n  painImmune: \"Иммунитет к оглушению?\"\n  zombiImmune: \"Иммунитет к зомбированию?\"\n  ignoresMeleeThreat: \"Игнорирует механику боя на кор. дистанции?\"\n  createsMeleeThreat: \"Запускает механику боя на кор. дистанции?\"\n  builtInWeapons: \"Встроенные блоки\"\n  specialWeapon: \"Специальное оружие\"\n  heatVision: \"Видимость сквозь дым\"\n  visibilityThroughFire: \"Видимость сквозь огонь\"\n  psiVision: \"Пси-видение\"\n  psiCamouflage: \"Пси-камуфляж\"\n  visibilityAtDay: \"Видимость днем\"\n  visibilityAtDark: \"Видимость ночью\"\n  camouflageAtDay: \"Камуфляж днем\"\n  camouflageAtDark: \"Камуфляж ночью\"\n  antiCamouflageAtDay: \"Различение камуфляжа днем\"\n  antiCamouflageAtDark: \"Различение камуфляжа ночью\"\n  psiDefence: \"Пси-защита\"\n  meleeDodge: \"Уклонение в бл. бою\"\n  meleeDodgeBackPenalty: \"Штраф к уклонению в ближнем бою\"\n  recovery: \"Восстановление за ход:\"\n  time: \"ОД\"\n  energy: \"Выносливость\"\n  morale: \"Мораль\"\n  health: \"Здоровье\"\n  stun: \"Оглушение\"\n  mana: \"Мана\"\n  units: \"Могут использовать\"\n  ranks: \"Доступно званиям\"\n  frontArmor: \"Фронтальная броня\"\n  sideArmor: \"Боковая броня\"\n  leftArmorDiff: \"Бонус к броне слева\"\n  rearArmor: \"Тыловая броня\"\n  underArmor: \"Нижняя броня\"\n#\n  sizeX: \"Размер по оси X\"\n  sizeY: \"Размер по оси Y\"\n  buildCost: \"Цена постройки\"\n  buildCostItems: \"Материалы для строит.:\"\n  buildTime: \"Время постройки\"\n  monthlyCost: \"Ежемесячные затраты\"\n  refundValue: \"Компенсация\"\n  requiresBaseFunc: \"Требует функции\"\n  provideBaseFunc: \"Обеспечивает функции\"\n  forbiddenBaseFunc: \"Блокирует функции\"\n  lift: \"Входной лифт?\"\n  hyper: \"Гиперволновой декодер?\"\n  mind: \"Ментальный щит?\"\n  mindPower: \"Энергия ментального щита\"\n  grav: \"Гравитационный щит?\"\n  storage: \"Объем грузового отсека\"\n  personnel: \"Жилая площадь\"\n  aliens: \"Мест в камерах\"\n  crafts: \"Мест в ангаре\"\n  labs: \"Рабочих мест в лаборатории\"\n  workshops: \"Рабочих мест в мастерских\"\n  psiLabs: \"Мест в пси-лаборатории\"\n  trainingRooms: \"Мест в спортзале\"\n  sightRange: \"Дальность обзора\"\n  sightChance: \"Вероятность обнар. базы приш.\"\n  radarRange: \"Дальность РЛС\"\n  radarChance: \"Вероятность обнар. НЛО\"\n  defense: \"Мощность защиты\"\n  hitRatio: \"Вероятность попадания\"\n  ammoNeeded: \"Кол-во боеприпасов\"\n  unifiedDamageFormula: \"Новая формула расчета урона?\"\n  ammoItem: \"Боеприпас\"\n  maxAllowedPerBase: \"Максимум на базе\"\n  manaRecoveryPerDay: \"Маны в день\"\n  healthRecoveryPerDay: \"ОЗ в день\"\n  sickBayAbsoluteBonus: \"Абс. бонус к скорости лечения\"\n  sickBayRelativeBonus: \"Отн. бонус к скорости лечения\"\n  prisonType: \"Вид камер\"\n  rightClickActionType: \"Действие по правой кнопке мыши\"\n  leavesBehindOnSell: \"Заменяющий модуль\"\n  removalTime: \"Время на снос\"\n  canBeBuiltOver: \"Может надстраиваться?\"\n  upgradeOnly: \"Только улучшение?\"\n  buildOverFacilities: \"Надстраивается над\"\n#\n  BFRCT_DEFAULT: \"как в оригинале\"\n  BFRCT_PRISON: \"Список заключенных\"\n  BFRCT_ENGINEERING: \"Экран производства\"\n  BFRCT_RESEARCH: \"Экран исследований\"\n  BFRCT_GYM: \"Экран боевой подготовки\"\n  BFRCT_PSI_LABS: \"Экран пси-тренировок\"\n  BFRCT_BARRACKS: \"Список бойцов\"\n  BFRCT_GREY_MARKET: \"Экран торговли\"\n  BFRCT_GEOSCAPE: \"Глобус\"\n#\n  costRent: \"Арендная плата\"\n  soldiers: \"Вместимость\"\n  maxUnitsLimit: \"Макс. вместимость\"\n  pilots: \"Размер кабины\"\n  pilotMinStatsRequired: \"Мин. характеристики пилота\"\n  pilotSoldierBonusesRequired: \"Требования к пилоту\"\n  vehicles: \"Мест под ТБП\"\n  onlyOneSoldierGroupAllowed: \"Может перевозить только один тип бойцов?\"\n  allowedSoldierGroups: \"Перевозимые типы бойцов\"\n  allowedArmorGroups: \"Перевозимые виды брони\"\n  limitArmorGroups: \"Лимит на перевозимую броню\"\n  maxHWPUnitsLimit: \"Макс. мест под ТБП\"\n  maxSmallSoldiers: \"Максимум легкой пехоты\"\n  maxLargeSoldiers: \"Максимум тяжелой пехоты\"\n  maxSmallVehicles: \"Максимум легкой техники\"\n  maxLargeVehicles: \"Максимум тяжелой техники\"\n  maxSmallUnits: \"Максимум легких единиц\"\n  maxLargeUnits: \"Максимум тяжелых единиц\"\n  maxSoldiers: \"Максимум бойцов\"\n  maxVehicles: \"Максимум техники\"\n  maxItems: \"Макс. ед. оборудования\"\n  maxStorageSpace: \"Объем грузового отсека\"\n  maxAltitude: \"Макс. высота возд. боя\"\n  weapons: \"Точек подвески\"\n  weaponStrings: \"Наим. орудий\"\n  fixedWeapons: \"Стационарное оружие\"\n  weaponTypes: \"Допуст. типы оружия\"\n  damageMax: \"Прочность\"\n  avoidBonus: \"Бонус к уклон. (равном.)\"\n  avoidBonus2: \"Бонус к уклон. 2 (равном.)\"\n  powerBonus: \"Бонус к урону (равном.)\"\n  hitBonus: \"Бонус к точности (равном.)\"\n  fuelMax: \"Емкость топл. бака\"\n  speedMax: \"Макс. скорость\"\n  accel: \"Ускорение\"\n  shieldCapacity: \"Мощность щитов\"\n  shieldRecharge: \"Восстановление щита (в бою)\"\n  shieldRechargeInGeoscape: \"Восстановление щита (на карте)\"\n  shieldBleedThrough: \"Пробивание щита\"\n  shieldRechargedAtBase: \"Восстановление щита (на базе)\"\n  refuelItem: \"Вид топлива\"\n  refuelRate: \"Время дозаправки\"\n  repairRate: \"Скорость ремонта\"\n  spacecraft: \"Исп-е в решающей битве?\"\n  allowLanding: \"Может приземляться?\"\n  notifyWhenRefueled: \"Оповещение об оконч. дозаправки?\"\n  autoPatrol: \"Автопатрулир.?\"\n  undetectable: \"Не обнаруживается?\"\n  patrolWithoutFuel: \"Патрулирование без топлива?\"\n  keepCraftAfterFailedMission: \"Выброска с парашютом?\"\n  _calculatedValues: \"Расчетные значения\"\n  _maxRange: \"Макс. дальность\"\n  _minRange: \"Мин. дальность\"\n  _avgRange: \"Ср. дальность\"\n#\n  hunterKillerPercentage: \"Вероятность появления охотника\"\n  huntMode: \"Режим преследования\"\n  huntSpeed: \"Скорость преследования\"\n  huntBehavior: \"Действия при преслед.\"\n  range: \"Дальность\"\n  reload: \"Время заряжания\"\n  breakOffTime: \"Время пролета\"\n  score: \"Очков\"\n  missionScore: \"Очков за задание\"\n  craftCustomDeploy: \"Вид подразд. в НЛО\"\n  missionCustomDeploy: \"Вид подразд. на задании\"\n  _escapeCountdown: \"Время до отлета\"\n  _fireRate: \"Скорострельность\"\n  _averageDPM: \"Ср. урон в минуту\"\n#\n  HM_INTERCEPTORS: \"приор. цель - истребители\"\n  HM_TRANSPORTS: \"приор. цель - транспорты\"\n  HM_RANDOM: \"случайно\"\n#\n  HB_FLEE: \"отступл. в случае опасности\"\n  HB_KAMIKAZE: \"бой насмерть\"\n  HB_RANDOM: \"случайные\"\n#\n  tractorBeamPower: \"Мощность притяг. луча\"\n  damage: \"Урон\"\n  shieldDamageModifier: \"Модификатор урона щиту\"\n  accuracy: \"Точность\"\n  reloadCautious: \"Заряжание (остор.)\"\n  reloadStandard: \"Заряжание (обычн.)\"\n  reloadAggressive: \"Заряжание (агрессив.)\"\n  launcher: \"Подвеска\"\n  weaponType: \"Тип оружия\"\n  clip: \"Боеприпасы\"\n  ammoMax: \"Боезапас\"\n  rearmRate: \"Скорость пополнения боекомплекта\"\n  bulletSaving: \"Экономия боеприпасов?\"\n  _damageRange: \"Разброс урона\"\n  _damageRangeBasic: \"Разброс урона (базовый)\"\n  _averageTotalDamage: \"Макс. усредн. урон\"\n#\n  allowPiloting: \"Может пилотировать?\"\n  costSalary: \"Жалованье\"\n  costSalarySquaddie: \"Бонус (как рядового)\"\n  costSalarySergeant: \"Бонус (как сержанта)\"\n  costSalaryCaptain: \"Бонус (как капитана)\"\n  costSalaryColonel: \"Бонус (как полковника)\"\n  costSalaryCommander: \"Бонус (как командующего)\"\n#\n  race: \"Раса\"\n  rank: \"Звание\"\n  livingWeapon: \"Живое оружие?\"\n  meleeWeapon: \"Оружие ближнего боя\"\n  psiWeapon: \"Пси-оружие\"\n  _builtInWeaponSets: \"Варианты укомплектования?\"\n  _weightedBuiltInWeaponSets: \"Пр. варианты укомплектования?\"\n  spawnUnit: \"Порождает при смерти\"\n  _capturable: \"Можно взять в плен?\"\n  capturable: \"Берется в плен (флаг)\"\n  canSurrender: \"Может сдаться?\"\n  autoSurrender: \"Автом. сдача?\"\n  spotter: \"Долгота памяти корректировщика\"\n  sniper: \"Вероятн. снайперского поведения\"\n"
  },
  {
    "path": "bin/common/Language/Technical/sv.yml",
    "content": "sv:\n#=================== Menu ===================\n#TestState.cpp\n  STR_BAD_NODES: \"\"\n  STR_BAD_NODES_DESC: \"\"\n#\n  STR_MCD_CHECK: \"\"\n  STR_MCD_CHECK_DESC: \"\"\n#\n  STR_PALETTE_CHECK: \"\"\n  STR_PALETTE_CHECK_DESC: \"\"\n#\n  STR_SCRIPT_TAGS: \"\"\n  STR_SCRIPT_TAGS_DESC: \"\"\n#\n  STR_MAP_RESOURCES: \"\"\n  STR_MAP_RESOURCES_DESC: \"\"\n#\n  STR_CHECKING_TERRAIN: \"Kontrollerar terräng...\"\n  STR_CHECKING_UFOS: \"\"\n  STR_CHECKING_CRAFT: \"\"\n#\n  BACKPALS.DAT: \"\"\n  PAL_GEOSCAPE: \"\"\n  PAL_BASESCAPE: \"\"\n  PAL_GRAPHS: \"\"\n  PAL_UFOPAEDIA: \"\"\n  PAL_BATTLEPEDIA: \"\"\n  PAL_BATTLESCAPE: \"\"\n  PAL_BATTLESCAPE_1: \"\"\n  PAL_BATTLESCAPE_2: \"\"\n  PAL_BATTLESCAPE_3: \"\"\n#=================== Ufopaedia ===================\n#StatsForNerdsState.cpp\n  BT_NONE: \"Ingen\"\n  BT_FIREARM: \"\"\n  BT_AMMO: \"\"\n  BT_MELEE: \"\"\n  BT_GRENADE: \"Granat\"\n  BT_PROXIMITYGRENADE: \"\"\n  BT_MEDIKIT: \"\"\n  BT_SCANNER: \"\"\n  BT_MINDPROBE: \"\"\n  BT_PSIAMP: \"\"\n  BT_FLARE: \"\"\n  BT_CORPSE: \"\"\n#\n  DRT_DEFAULT: \"\"\n  DRT_UFO: \"\"\n  DRT_TFTD: \"\"\n  DRT_FLAT: \"\"\n  DRT_FIRE: \"\"\n  DRT_NONE: \"ingen skada\"\n  DRT_UFO_WITH_TWO_DICE: \"\"\n  DRT_EASY: \"\"\n  DRT_STANDARD: \"\"\n  DRT_EXPLOSION: \"\"\n#\n  BFT_NONE: \"ingen\"\n  BFT_INSTANT: \"direkt\"\n  BFT_SET: \"manuellt inställd\"\n  BFT_FIXED: \"fast\"\n#\n  BMT_NORMAL: \"\"\n  BMT_HEAL: \"hela\"\n  BMT_STIMULANT: \"\"\n  BMT_PAINKILLER: \"\"\n#\n  ETM_DEFAULT: \"standard\"\n  ETM_MELEE_100: \"\"\n  ETM_MELEE_50: \"\"\n  ETM_MELEE_33: \"\"\n  ETM_FIRING_100: \"\"\n  ETM_FIRING_50: \"\"\n  ETM_FIRING_33: \"\"\n  ETM_THROWING_100: \"\"\n  ETM_THROWING_50: \"\"\n  ETM_THROWING_33: \"\"\n  ETM_FIRING_AND_THROWING: \"\"\n  ETM_FIRING_OR_THROWING: \"\"\n  ETM_REACTIONS: \"\"\n  ETM_REACTIONS_AND_MELEE: \"\"\n  ETM_REACTIONS_AND_FIRING: \"\"\n  ETM_REACTIONS_AND_THROWING: \"\"\n  ETM_REACTIONS_OR_MELEE: \"\"\n  ETM_REACTIONS_OR_FIRING: \"\"\n  ETM_REACTIONS_OR_THROWING: \"\"\n  ETM_BRAVERY: \"\"\n  ETM_BRAVERY_2X: \"\"\n  ETM_BRAVERY_AND_REACTIONS: \"\"\n  ETM_BRAVERY_OR_REACTIONS: \"\"\n  ETM_BRAVERY_OR_REACTIONS_2X: \"\"\n  ETM_PSI_STRENGTH: \"\"\n  ETM_PSI_STRENGTH_2X: \"\"\n  ETM_PSI_SKILL: \"\"\n  ETM_PSI_SKILL_2X: \"\"\n  ETM_PSI_STRENGTH_AND_SKILL: \"\"\n  ETM_PSI_STRENGTH_AND_SKILL_2X: \"\"\n  ETM_PSI_STRENGTH_OR_SKILL: \"\"\n  ETM_PSI_STRENGTH_OR_SKILL_2X: \"\"\n  ETM_NOTHING: \"ingen träning\"\n#\n  battleType: \"\"\n  experienceTrainingMode: \"\"\n  manaExperience: \"\"\n  arcingShot: \"\"\n  isFireExtinguisher: \"Brandsläckare?\"\n  explodeInventory: \"\"\n  waypoints: \"\"\n  sprayWaypoints: \"\"\n#\n  shotgunPellets: \"\"\n  shotgunBehavior: \"\"\n  shotgunSpread: \"\"\n  shotgunChoke: \"\"\n#\n  underwaterOnly: \"\"\n  landOnly: \"\"\n  psiRequired: \"\"\n  targetMatrix: \"\"\n  convertToCivilian: \"\"\n  manaRequired: \"\"\n  LOSRequired: \"\"\n#\n  noLOSAccuracyPenalty: \"\"\n  kneelBonus: \"\"\n  twoHanded: \"\"\n  blockBothHands: \"\"\n  oneHandedPenalty: \"\"\n#\n  minRange: \"\"\n  maxRange: \"\"\n  aimRange: \"\"\n  autoRange: \"\"\n  snapRange: \"\"\n  dropoff: \"\"\n#\n  accuracyMultiplier: \"\"\n  accuracyAimed: \"\"\n  accuracyAuto: \"\"\n  accuracySnap: \"\"\n  costAimed: \"\"\n  costAuto: \"\"\n  costSnap: \"\"\n#\n  meleeMultiplier: \"\"\n  accuracyMelee: \"\"\n  costMelee: \"\"\n#\n  psiAttackName: \"\"\n  accuracyUse: \"\"\n  accuracyMindControl: \"\"\n  accuracyPanic: \"\"\n  costUse: \"\"\n  costMindcontrol: \"\"\n  costPanic: \"\"\n#\n  weight: \"Vikt\"\n  throwRange: \"\"\n  underwaterThrowRange: \"\"\n  throwDropoffRange: \"\"\n  underwaterThrowDropoffRange: \"\"\n  throwDropoff: \"\"\n  throwMultiplier: \"\"\n  accuracyThrow: \"\"\n  costThrow: \"\"\n  costPrime: \"\"\n  costUnprime: \"\"\n#\n  closeQuartersMultiplier: \"\"\n  accuracyCloseQuarters: \"\"\n#\n  damageType: \"Skadetyp\"\n  power: \"\"\n  powerRangeReduction: \"\"\n  powerRangeThreshold: \"\"\n  damageBonus: \"Skadebonus\"\n  blastRadius: \"Sprängradie\"\n  damageAlter: \"\"\n  meleeType: \"\"\n  meleePower: \"\"\n  meleeBonus: \"\"\n  meleeAlter: \"\"\n  FixRadius: \"Sprängradie\"\n  RandomType: \"Beräkningstyp\"\n  FireBlastCalc: \"\"\n  IgnoreDirection: \"\"\n  IgnoreSelfDestruct: \"\"\n  IgnorePainImmunity: \"\"\n  IgnoreNormalMoraleLose: \"\"\n  IgnoreOverKill: \"\"\n  ArmorEffectiveness: \"\"\n  RadiusEffectiveness: \"\"\n  RadiusReduction: \"\"\n  FireThreshold: \"\"\n  SmokeThreshold: \"\"\n#\n  ToArmorPre: \"\"\n  RandomArmorPre: \"\"\n  ToArmor: \"\"\n  RandomArmor: \"\"\n  ToHealth: \"\"\n  RandomHealth: \"\"\n  ToStun: \"\"\n  RandomStun: \"\"\n  ToWound: \"\"\n  RandomWound: \"\"\n  ToTime: \"\"\n  RandomTime: \"\"\n  ToEnergy: \"\"\n  RandomEnergy: \"\"\n  ToMorale: \"\"\n  RandomMorale: \"\"\n  ToItem: \"\"\n  RandomItem: \"\"\n  ToMana: \"\"\n  RandomMana: \"\"\n  ToTile: \"\"\n  RandomTile: \"\"\n  TileDamageMethod: \"\"\n  TileDamageLimit: \"\"\n#\n  confAimed: \"\"\n  confAuto: \"\"\n  confSnap: \"\"\n  confMelee: \"\"\n  shots: \"\"\n  spendPerShot: \"\"\n  followProjectiles: \"\"\n  name: \"Namn\"\n  shortName: \"Kort namn\"\n  ammoSlot: \"\"\n  ammoZombieUnitChanceOverride: \"\"\n  ammoSpawnUnitChanceOverride: \"\"\n  ammoSpawnItemChanceOverride: \"\"\n  arcing: \"\"\n#\n  clipSize: \"\"\n  isAmmoRechargeable: \"\"\n#\n  primaryAmmo: \"\"\n  compatibleAmmo: \"\"\n  tuLoad: \"Lastningskostnad\"\n  tuUnload: \"Avlastningskostnad\"\n  ammo[1]: \"\"\n  ammo[2]: \"\"\n  ammo[3]: \"\"\n#\n  armor: \"\"\n#\n  medikitType: \"\"\n  painKillerActionName: \"\"\n  stimulantActionName: \"\"\n  healActionName: \"\"\n  medikitActionName: \"\"\n  medikitTargetSelf: \"\"\n  medikitTargetImmune: \"\"\n  medikitTargetMatrix: \"\"\n  isConsumable: \"\"\n  painKiller: \"\"\n  heal: \"\"\n  stimulant: \"\"\n  woundRecovery: \"\"\n  healthRecovery: \"\"\n  stunRecovery: \"\"\n  energyRecovery: \"\"\n  manaRecovery: \"\"\n  moraleRecovery: \"\"\n  painKillerRecovery: \"\"\n#\n  requires: \"\"\n  requiresBuy: \"\"\n  requiresBuyBaseFunc: \"\"\n  requiresBuyCountry: \"\"\n  requiresAward: \"\"\n  requiresBonus: \"\"\n  categories: \"Kategorier\"\n  supportedInventorySections: \"\"\n#\n  size: \"Storlek\"\n  costBuy: \"\"\n  monthlyBuyLimit: \"\"\n  costSell: \"\"\n  transferTime: \"\"\n  monthlySalary: \"\"\n  monthlyMaintenance: \"\"\n#\n  SPECAB_NONE: \"Ingen\"\n  SPECAB_EXPLODEONDEATH: \"\"\n  SPECAB_BURNFLOOR: \"\"\n  SPECAB_BURN_AND_EXPLODE: \"\"\n#\n  MT_WALK: \"Gå\"\n  MT_FLY: \"Flyg\"\n  MT_SLIDE: \"\"\n  MT_FLOAT: \"Flyt\"\n  MT_SINK: \"Sjunk\"\n#\n  TORSO_USE_GENDER: \"Använd kön\"\n  TORSO_ALWAYS_MALE: \"Alltid man\"\n  TORSO_ALWAYS_FEMALE: \"Alltid kvinna\"\n#\n  DRAWING_ROUTINE_SOLDIER_SECTOID: \"\"\n  DRAWING_ROUTINE_FLOATER: \"\"\n  DRAWING_ROUTINE_HWP: \"\"\n  DRAWING_ROUTINE_CYBERDISC: \"\"\n  DRAWING_ROUTINE_CIVILIAN_ETHEREAL: \"\"\n  DRAWING_ROUTINE_SECTOPOD_REAPER: \"\"\n  DRAWING_ROUTINE_SNAKEMAN: \"\"\n  DRAWING_ROUTINE_CHRYSSALID: \"\"\n  DRAWING_ROUTINE_SILACOID: \"\"\n  DRAWING_ROUTINE_CELATID: \"\"\n  DRAWING_ROUTINE_MUTON: \"\"\n  DRAWING_ROUTINE_SWS: \"\"\n  DRAWING_ROUTINE_HALLUCINOID: \"\"\n  DRAWING_ROUTINE_AQUANAUTS: \"Aquanauter\"\n  DRAWING_ROUTINE_CALCINITE_AND_MORE: \"\"\n  DRAWING_ROUTINE_AQUATOID: \"\"\n  DRAWING_ROUTINE_BIO_DRONE: \"\"\n  DRAWING_ROUTINE_TFTD_CIVILIAN_A: \"\"\n  DRAWING_ROUTINE_TFTD_CIVILIAN_B: \"\"\n  DRAWING_ROUTINE_TENTACULAT: \"\"\n  DRAWING_ROUTINE_TRISCENE: \"\"\n  DRAWING_ROUTINE_XARQUID: \"\"\n  DRAWING_ROUTINE_INVERTED_CYBERDISC: \"\"\n#\n  stats: \"\"\n  specab: \"\"\n  movementType: \"\"\n  allowsRunning: \"\"\n  allowsStrafing: \"\"\n  allowsSneaking: \"\"\n  allowsKneeling: \"\"\n  allowsMoving: \"\"\n  fearImmune: \"\"\n  bleedImmune: \"\"\n  painImmune: \"\"\n  zombiImmune: \"\"\n  ignoresMeleeThreat: \"\"\n  createsMeleeThreat: \"\"\n  builtInWeapons: \"\"\n  specialWeapon: \"\"\n  heatVision: \"\"\n  visibilityThroughFire: \"\"\n  psiVision: \"\"\n  psiCamouflage: \"\"\n  visibilityAtDay: \"\"\n  visibilityAtDark: \"\"\n  camouflageAtDay: \"\"\n  camouflageAtDark: \"\"\n  antiCamouflageAtDay: \"\"\n  antiCamouflageAtDark: \"\"\n  psiDefence: \"\"\n  meleeDodge: \"\"\n  meleeDodgeBackPenalty: \"\"\n  recovery: \"\"\n  time: \"Tid\"\n  energy: \"Energi\"\n  morale: \"Moral\"\n  health: \"\"\n  stun: \"\"\n  mana: \"\"\n  units: \"\"\n  ranks: \"\"\n  frontArmor: \"\"\n  sideArmor: \"\"\n  leftArmorDiff: \"\"\n  rearArmor: \"\"\n  underArmor: \"\"\n#\n  sizeX: \"Storlek X\"\n  sizeY: \"Storlek Y\"\n  buildCost: \"Byggkostnad\"\n  buildCostItems: \"\"\n  buildTime: \"Byggtid\"\n  monthlyCost: \"\"\n  refundValue: \"\"\n  requiresBaseFunc: \"\"\n  provideBaseFunc: \"\"\n  forbiddenBaseFunc: \"\"\n  lift: \"\"\n  hyper: \"\"\n  mind: \"\"\n  mindPower: \"\"\n  grav: \"\"\n  storage: \"Lagringsutrymme\"\n  personnel: \"\"\n  aliens: \"\"\n  crafts: \"\"\n  labs: \"\"\n  workshops: \"\"\n  psiLabs: \"\"\n  trainingRooms: \"\"\n  sightRange: \"\"\n  sightChance: \"\"\n  radarRange: \"\"\n  radarChance: \"\"\n  defense: \"\"\n  hitRatio: \"\"\n  ammoNeeded: \"\"\n  unifiedDamageFormula: \"\"\n  ammoItem: \"\"\n  maxAllowedPerBase: \"\"\n  manaRecoveryPerDay: \"\"\n  healthRecoveryPerDay: \"\"\n  sickBayAbsoluteBonus: \"\"\n  sickBayRelativeBonus: \"\"\n  prisonType: \"\"\n  rightClickActionType: \"\"\n  leavesBehindOnSell: \"\"\n  removalTime: \"\"\n  canBeBuiltOver: \"\"\n  upgradeOnly: \"\"\n  buildOverFacilities: \"\"\n#\n  BFRCT_DEFAULT: \"\"\n  BFRCT_PRISON: \"\"\n  BFRCT_ENGINEERING: \"\"\n  BFRCT_RESEARCH: \"\"\n  BFRCT_GYM: \"\"\n  BFRCT_PSI_LABS: \"\"\n  BFRCT_BARRACKS: \"\"\n  BFRCT_GREY_MARKET: \"\"\n  BFRCT_GEOSCAPE: \"\"\n#\n  costRent: \"\"\n  soldiers: \"\"\n  maxUnitsLimit: \"\"\n  pilots: \"\"\n  pilotMinStatsRequired: \"\"\n  pilotSoldierBonusesRequired: \"\"\n  vehicles: \"\"\n  onlyOneSoldierGroupAllowed: \"\"\n  allowedSoldierGroups: \"\"\n  allowedArmorGroups: \"\"\n  limitArmorGroups: \"\"\n  maxHWPUnitsLimit: \"\"\n  maxSmallSoldiers: \"\"\n  maxLargeSoldiers: \"\"\n  maxSmallVehicles: \"\"\n  maxLargeVehicles: \"\"\n  maxSmallUnits: \"\"\n  maxLargeUnits: \"\"\n  maxSoldiers: \"Max soldater\"\n  maxVehicles: \"Max fordon\"\n  maxItems: \"\"\n  maxStorageSpace: \"Lagringsutrymme\"\n  maxAltitude: \"\"\n  weapons: \"\"\n  weaponStrings: \"Vapennamn\"\n  fixedWeapons: \"Fasta vapen\"\n  weaponTypes: \"\"\n  damageMax: \"\"\n  avoidBonus: \"\"\n  avoidBonus2: \"\"\n  powerBonus: \"\"\n  hitBonus: \"\"\n  fuelMax: \"Bränslekapacitet\"\n  speedMax: \"Maximal hastighet\"\n  accel: \"\"\n  shieldCapacity: \"\"\n  shieldRecharge: \"\"\n  shieldRechargeInGeoscape: \"\"\n  shieldBleedThrough: \"\"\n  shieldRechargedAtBase: \"\"\n  refuelItem: \"\"\n  refuelRate: \"\"\n  repairRate: \"\"\n  spacecraft: \"\"\n  allowLanding: \"\"\n  notifyWhenRefueled: \"\"\n  autoPatrol: \"\"\n  undetectable: \"\"\n  patrolWithoutFuel: \"\"\n  keepCraftAfterFailedMission: \"\"\n  _calculatedValues: \"\"\n  _maxRange: \"\"\n  _minRange: \"\"\n  _avgRange: \"\"\n#\n  hunterKillerPercentage: \"\"\n  huntMode: \"Jaktläge\"\n  huntSpeed: \"Jakthastighet\"\n  huntBehavior: \"Jaktbeteende\"\n  range: \"\"\n  reload: \"\"\n  breakOffTime: \"\"\n  score: \"Poäng\"\n  missionScore: \"\"\n  craftCustomDeploy: \"\"\n  missionCustomDeploy: \"\"\n  _escapeCountdown: \"\"\n  _fireRate: \"Eldhastighet\"\n  _averageDPM: \"\"\n#\n  HM_INTERCEPTORS: \"\"\n  HM_TRANSPORTS: \"\"\n  HM_RANDOM: \"\"\n#\n  HB_FLEE: \"\"\n  HB_KAMIKAZE: \"\"\n  HB_RANDOM: \"\"\n#\n  tractorBeamPower: \"\"\n  damage: \"Skada\"\n  shieldDamageModifier: \"\"\n  accuracy: \"\"\n  reloadCautious: \"\"\n  reloadStandard: \"\"\n  reloadAggressive: \"\"\n  launcher: \"\"\n  weaponType: \"Vapentyp\"\n  clip: \"\"\n  ammoMax: \"\"\n  rearmRate: \"\"\n  bulletSaving: \"\"\n  _damageRange: \"\"\n  _damageRangeBasic: \"\"\n  _averageTotalDamage: \"\"\n#\n  allowPiloting: \"\"\n  costSalary: \"\"\n  costSalarySquaddie: \"\"\n  costSalarySergeant: \"\"\n  costSalaryCaptain: \"\"\n  costSalaryColonel: \"\"\n  costSalaryCommander: \"\"\n#\n  race: \"\"\n  rank: \"\"\n  livingWeapon: \"\"\n  meleeWeapon: \"\"\n  psiWeapon: \"\"\n  _builtInWeaponSets: \"\"\n  _weightedBuiltInWeaponSets: \"\"\n  spawnUnit: \"\"\n  _capturable: \"\"\n  capturable: \"\"\n  canSurrender: \"\"\n  autoSurrender: \"\"\n  spotter: \"\"\n  sniper: \"\"\n"
  },
  {
    "path": "bin/common/Language/Technical/uk.yml",
    "content": "uk:\n#=================== Menu ===================\n#TestState.cpp\n  STR_BAD_NODES: \"Погані вузли у файлах RMP\"\n  STR_BAD_NODES_DESC: \"Перевіряє файли RMP на наявність вузлів за межами карти.{NEWLINE}Вони НЕ спричинять збоїв, але їх ігноруватиме гра, тому вони не працюватимуть належним чином.\"\n#\n  STR_MCD_CHECK: \"Перевірки MCD\"\n  STR_MCD_CHECK_DESC: \"Перевіряє MCD-файли на наявність об'єктів поверху з нульовою вартістю переміщення; також перевіряє на наявність недійсних посилань DieMCD/AltMCD; також перевіряє на наявність недійсних LOFTemps.\"\n#\n  STR_PALETTE_CHECK: \"Відповідність палітри\"\n  STR_PALETTE_CHECK_DESC: \"Намагається зіставити палітри модифікованих зображень з офіційними палітрами та повідомляє про будь-які зображення, які не мають 100% відповідності.\"\n#\n  STR_SCRIPT_TAGS: \"Експорт тегів сценарію\"\n  STR_SCRIPT_TAGS_DESC: \"Експортує теги скриптів у форматі CSV.\"\n#\n  STR_MAP_RESOURCES: \"Перевірка ресурсів карти\"\n  STR_MAP_RESOURCES_DESC: \"Перевіряє відсутні та невикористані файли, пов'язані з картою, та набір правил.\"\n#\n  STR_CHECKING_TERRAIN: \"Перевірка місцевості...\"\n  STR_CHECKING_UFOS: \"Перевірка НЛО...\"\n  STR_CHECKING_CRAFT: \"Перевірка корабля...\"\n#\n  BACKPALS.DAT: \"BACKPALS.DAT\"\n  PAL_GEOSCAPE: \"PAL_GEOSCAPE\"\n  PAL_BASESCAPE: \"PAL_BASESCAPE\"\n  PAL_GRAPHS: \"PAL_GRAPHS\"\n  PAL_UFOPAEDIA: \"PAL_UFOPAEDIA\"\n  PAL_BATTLEPEDIA: \"PAL_BATTLEPEDIA\"\n  PAL_BATTLESCAPE: \"PAL_BATTLESCAPE\"\n  PAL_BATTLESCAPE_1: \"PAL_BATTLESCAPE_1\"\n  PAL_BATTLESCAPE_2: \"PAL_BATTLESCAPE_2\"\n  PAL_BATTLESCAPE_3: \"PAL_BATTLESCAPE_3\"\n#=================== Ufopaedia ===================\n#StatsForNerdsState.cpp\n  BT_NONE: \"Жоден\"\n  BT_FIREARM: \"Вогнепальна зброя\"\n  BT_AMMO: \"Боєприпаси\"\n  BT_MELEE: \"Зброя ближнього бою\"\n  BT_GRENADE: \"Граната\"\n  BT_PROXIMITYGRENADE: \"Граната блиньої дії\"\n  BT_MEDIKIT: \"Медкомплект\"\n  BT_SCANNER: \"Сканер руху\"\n  BT_MINDPROBE: \"Зонд розуму\"\n  BT_PSIAMP: \"Підсилювач PSI\"\n  BT_FLARE: \"Ракета\"\n  BT_CORPSE: \"Труп/Тіло\"\n#\n  DRT_DEFAULT: \"оригінал за замовчуванням\"\n  DRT_UFO: \"Розкид 0-200%\"\n  DRT_TFTD: \"Розкид 50-150%\"\n  DRT_FLAT: \"пошкодження по площині\"\n  DRT_FIRE: \"спеціальні вогневі пошкодження\"\n  DRT_NONE: \"без пошкоджень\"\n  DRT_UFO_WITH_TWO_DICE: \"Розкид 0-200% (2 кидки)\"\n  DRT_EASY: \"Розкид 50-200%\"\n  DRT_STANDARD: \"стандартний діапазон ураження\"\n  DRT_EXPLOSION: \"фугасний діапазон ураження\"\n#\n  BFT_NONE: \"жоден\"\n  BFT_INSTANT: \"миттєво\"\n  BFT_SET: \"встановлюється вручну\"\n  BFT_FIXED: \"виправлено\"\n#\n  BMT_NORMAL: \"стандартний (багатоцільовий)\"\n  BMT_HEAL: \"аптечка\"\n  BMT_STIMULANT: \"стимулятор\"\n  BMT_PAINKILLER: \"знеболююче\"\n#\n  ETM_DEFAULT: \"за замовчуванням\"\n  ETM_MELEE_100: \"РУКОПАШНИЙ БІЙ\"\n  ETM_MELEE_50: \"РУКОПАШНИЙ БІЙ (50% шанс)\"\n  ETM_MELEE_33: \"РУКОПАШНИЙ БІЙ (33% шанс)\"\n  ETM_FIRING_100: \"СТРІЛЬБА\"\n  ETM_FIRING_50: \"СТРІЛЬБА (50% шанс)\"\n  ETM_FIRING_33: \"СТРІЛЬБА (33% шанс)\"\n  ETM_THROWING_100: \"МЕТАННЯ\"\n  ETM_THROWING_50: \"МЕТАННЯ (50% шанс)\"\n  ETM_THROWING_33: \"МЕТАННЯ (33% шанс)\"\n  ETM_FIRING_AND_THROWING: \"СТРІЛЬБА та МЕТАННЯ\"\n  ETM_FIRING_OR_THROWING: \"СТРІЛЬБА або МЕТАННЯ\"\n  ETM_REACTIONS: \"РЕАКЦІЯ\"\n  ETM_REACTIONS_AND_MELEE: \"РЕАКЦІЯ та РУКОПАШНИЙ БІЙ\"\n  ETM_REACTIONS_AND_FIRING: \"РЕАКЦІЯ та СТРІЛЬБА\"\n  ETM_REACTIONS_AND_THROWING: \"РЕАКЦІЯ та МЕТАННЯ\"\n  ETM_REACTIONS_OR_MELEE: \"РЕАКЦІЯ або РУКОПАШНИЙ БІЙ\"\n  ETM_REACTIONS_OR_FIRING: \"РЕАКЦІЯ та СТРІЛЬБА\"\n  ETM_REACTIONS_OR_THROWING: \"РЕАКЦІЯ або МЕТАННЯ\"\n  ETM_BRAVERY: \"ХОРОБРІСТЬ\"\n  ETM_BRAVERY_2X: \"ХОРОБРІСТЬ (x2)\"\n  ETM_BRAVERY_AND_REACTIONS: \"ХОРОБРІСТЬ та РЕАКЦІЯ\"\n  ETM_BRAVERY_OR_REACTIONS: \"ХОРОБРІСТЬ або РЕАКЦІЯ\"\n  ETM_BRAVERY_OR_REACTIONS_2X: \"ХОРОБРІСТЬ або РЕАКЦІЯ (x2)\"\n  ETM_PSI_STRENGTH: \"PSI-СИЛА\"\n  ETM_PSI_STRENGTH_2X: \"PSI-СИЛА (x2)\"\n  ETM_PSI_SKILL: \"PSI-НАВИК\"\n  ETM_PSI_SKILL_2X: \"PSI-НАВИК (x2)\"\n  ETM_PSI_STRENGTH_AND_SKILL: \"PSI-СИЛА та PSI-НАВИК\"\n  ETM_PSI_STRENGTH_AND_SKILL_2X: \"PSI-СИЛА та PSI-НАВИК (x2)\"\n  ETM_PSI_STRENGTH_OR_SKILL: \"PSI-СИЛА або PSI-НАВИК\"\n  ETM_PSI_STRENGTH_OR_SKILL_2X: \"PSI-СИЛА або PSI-НАВИК (x2)\"\n  ETM_NOTHING: \"без підготовки\"\n#\n  battleType: \"Тип предмета\"\n  experienceTrainingMode: \"Режим для досвідчених\"\n  manaExperience: \"Досвід мани\"\n  arcingShot: \"Освітлювач?\"\n  isFireExtinguisher: \"Вогнегасник?\"\n  explodeInventory: \"Вибухає в інвентарі?\"\n  waypoints: \"Максимальна кількість маршрутних точок\"\n  sprayWaypoints: \"Вогневі точки\"\n#\n  shotgunPellets: \"Кількість гранул\"\n  shotgunBehavior: \"Поведінка рушниці\"\n  shotgunSpread: \"Дальність рушниці\"\n  shotgunChoke: \"Розкид дробовика\"\n#\n  underwaterOnly: \"Тільки підводне?\"\n  landOnly: \"Тільки наземне?\"\n  psiRequired: \"Необхідний PSI-навик?\"\n  targetMatrix: \"Цілі предмета\"\n  convertToCivilian: \"Перевестися в цивільні?\"\n  manaRequired: \"Необхідна мана?\"\n  LOSRequired: \"Необхідна видимість?\"\n#\n  noLOSAccuracyPenalty: \"Штраф за відсутність видимості\"\n  kneelBonus: \"Бонусний за присідання\"\n  twoHanded: \"Дворучне?\"\n  blockBothHands: \"Блокує обидві руки?\"\n  oneHandedPenalty: \"Штраф за використання однією рукою\"\n#\n  minRange: \"Мінімальний діапазон\"\n  maxRange: \"Максимальний діапазон\"\n  aimRange: \"Діапазон прицільного вогню\"\n  autoRange: \"Діапазон автоматичного вогню\"\n  snapRange: \"Діапазон стрільби навмання\"\n  dropoff: \"Точність кидка/кладіння\"\n#\n  accuracyMultiplier: \"Множник точності стрільби\"\n  accuracyAimed: \"Прицільна точність пострілу\"\n  accuracyAuto: \"Автоматична точність пострілу\"\n  accuracySnap: \"Точність пострілу навмання\"\n  costAimed: \"Вартість точного пострілу\"\n  costAuto: \"Вартість автоматичного пострілу\"\n  costSnap: \"Вартість пострілу навмання\"\n#\n  meleeMultiplier: \"Множник точності ближнього бою\"\n  accuracyMelee: \"Точність ближнього бою\"\n  costMelee: \"Вартість ближнього бою\"\n#\n  psiAttackName: \"Назва PSI-атаки\"\n  accuracyUse: \"Точність дії\"\n  accuracyMindControl: \"Точність контролю розуму\"\n  accuracyPanic: \"Точність паніки\"\n  costUse: \"Вартість дії\"\n  costMindcontrol: \"Вартість контролю розуму\"\n  costPanic: \"Вартість паніки\"\n#\n  weight: \"Вага\"\n  throwRange: \"\"\n  underwaterThrowRange: \"\"\n  throwDropoffRange: \"\"\n  underwaterThrowDropoffRange: \"\"\n  throwDropoff: \"\"\n  throwMultiplier: \"Множник точності кидка\"\n  accuracyThrow: \"Точність кидка\"\n  costThrow: \"Вартість кидка\"\n  costPrime: \"Вартість перезарядки\"\n  costUnprime: \"Невиплачувана вартість\"\n#\n  closeQuartersMultiplier: \"Множник точності закритих приміщень\"\n  accuracyCloseQuarters: \"Точність закритих приміщень\"\n#\n  damageType: \"Тип пошкодження\"\n  power: \"Потужність\"\n  powerRangeReduction: \"Зменшення потужності/тайл\"\n  powerRangeThreshold: \"Межа діапазону потужності\"\n  damageBonus: \"Бонус до пошкодження\"\n  blastRadius: \"Радіус вибуху\"\n  damageAlter: \"Інформація про додаткові пошкодження:\"\n  meleeType: \"Тип пошкодження в рукопашному бою\"\n  meleePower: \"Сила ближнього бою\"\n  meleeBonus: \"Бонус до сили ближнього бою\"\n  meleeAlter: \"Додаткова інформація про ближній бій:\"\n  FixRadius: \"Радіус вибуху\"\n  RandomType: \"Тип розрахунку\"\n  FireBlastCalc: \"Вогневі ефекти за промовчанням?\"\n  IgnoreDirection: \"Ігнорувати напрямок\"\n  IgnoreSelfDestruct: \"Ігнорувати самознищення\"\n  IgnorePainImmunity: \"Ігнорувати імунітет до оглушення\"\n  IgnoreNormalMoraleLose: \"Ігнорувати втрату моралі за промовчанням\"\n  IgnoreOverKill: \"Ігнорувати надлишок\"\n  ArmorEffectiveness: \"Ефективність броні\"\n  RadiusEffectiveness: \"Радіус ефективності\"\n  RadiusReduction: \"Зменшення радіусу пошкодження\"\n  FireThreshold: \"Поріг запалювання\"\n  SmokeThreshold: \"Поріг утворення диму\"\n#\n  ToArmorPre: \"Множник попереднього пошкодження броні\"\n  RandomArmorPre: \"Випадкове значення попереднього пошкодження броні?\"\n  ToArmor: \"Множник пошкодження броні\"\n  RandomArmor: \"Випадкове пошкодження броні?\"\n  ToHealth: \"Множник пошкодження здоров'я\"\n  RandomHealth: \"Випадкове пошкодження здоров'я?\"\n  ToStun: \"Множник пошкодження оглушення\"\n  RandomStun: \"Випадкове пошкодження оглушення?\"\n  ToWound: \"Множник підрахунку пошкоджень\"\n  RandomWound: \"Випадкові пошкодження за промовчанням?\"\n  ToTime: \"Множник пошкоджень з часом\"\n  RandomTime: \"Випадкові пошкодження з часом?\"\n  ToEnergy: \"Множник пошкодження енергії\"\n  RandomEnergy: \"Випадкове пошкодження енергії?\"\n  ToMorale: \"Множник пошкодження моралі\"\n  RandomMorale: \"Випадкове пошкодження моралі?\"\n  ToItem: \"Множник пошкодження предметів\"\n  RandomItem: \"Випадкове пошкодження предметів?\"\n  ToMana: \"Множник пошкодження мани\"\n  RandomMana: \"Випадкове пошкодження мани?\"\n  ToTile: \"Множник пошкодження довкілля\"\n  RandomTile: \"Випадкові пошкодження довкілля?\"\n  TileDamageMethod: \"Метод пошкодження тайлів\"\n  TileDamageLimit: \"\"\n#\n  confAimed: \"Точна дія:\"\n  confAuto: \"Автоматична дія:\"\n  confSnap: \"Дія навмання:\"\n  confMelee: \"Дія ближнього бою:\"\n  shots: \"Пострілів за дію\"\n  spendPerShot: \"Витрати на постріл:\"\n  followProjectiles: \"Слідувати за снарядами?\"\n  name: \"Ім'я\"\n  shortName: \"Коротке найменування\"\n  ammoSlot: \"Використовується слот для боєприпасів\"\n  ammoZombieUnitChanceOverride: \"\"\n  ammoSpawnUnitChanceOverride: \"\"\n  ammoSpawnItemChanceOverride: \"\"\n  arcing: \"Освітлювач?\"\n#\n  clipSize: \"Розмір магазину\"\n  isAmmoRechargeable: \"\"\n#\n  primaryAmmo: \"Основний слот для боєприпасів:\"\n  compatibleAmmo: \"Сумісні боєприпаси\"\n  tuLoad: \"Вартість заряджування\"\n  tuUnload: \"Вартість розряджування\"\n  ammo[1]: \"Слот для додаткових боєприпасів #1:\"\n  ammo[2]: \"Слот для додаткових боєприпасів #2:\"\n  ammo[3]: \"Слот для додаткових боєприпасів #3:\"\n#\n  armor: \"Броня\"\n#\n  medikitType: \"Тип аптечки\"\n  painKillerActionName: \"\"\n  stimulantActionName: \"\"\n  healActionName: \"\"\n  medikitActionName: \"Дія з аптечкою\"\n  medikitTargetSelf: \"Лікувати себе?\"\n  medikitTargetImmune: \"Лікувати об'єкт з імунітетом до кровотечі?\"\n  medikitTargetMatrix: \"Цілі для лікування\"\n  isConsumable: \"Витратний?\"\n  painKiller: \"Застосування знеболюючого\"\n  heal: \"Застосування аптечки\"\n  stimulant: \"Застосування стимулятора\"\n  woundRecovery: \"Загоєння ран\"\n  healthRecovery: \"Відновлення здоров'я\"\n  stunRecovery: \"Відновлення оглушення\"\n  energyRecovery: \"Відновлення енергії\"\n  manaRecovery: \"Відновлення мани\"\n  moraleRecovery: \"Відновлення моралі\"\n  painKillerRecovery: \"Сила знеболювання\"\n#\n  requires: \"Необхідна технологія\"\n  requiresBuy: \"Необхідна технологія для покупки\"\n  requiresBuyBaseFunc: \"Необхідні послуги для покупки\"\n  requiresBuyCountry: \"Необхідна країна-союзник\"\n  requiresAward: \"\"\n  requiresBonus: \"\"\n  categories: \"Категорії\"\n  supportedInventorySections: \"Слоти інвентаря\"\n#\n  size: \"Розмір\"\n  costBuy: \"Ціна купівлі\"\n  monthlyBuyLimit: \"Ліміт щомісячних закупівель\"\n  costSell: \"Ціна продажу\"\n  transferTime: \"Годин на транспортування\"\n  monthlySalary: \"Зарплата/місяць\"\n  monthlyMaintenance: \"Технічне обслуговування/місяць\"\n#\n  SPECAB_NONE: \"Жоден\"\n  SPECAB_EXPLODEONDEATH: \"Вибухає при смерті\"\n  SPECAB_BURNFLOOR: \"Підпалює поверхню\"\n  SPECAB_BURN_AND_EXPLODE: \"Підпалює поверхню та вибухає при смерті\"\n#\n  MT_WALK: \"Прогулянка\"\n  MT_FLY: \"Політ\"\n  MT_SLIDE: \"Ковзання\"\n  MT_FLOAT: \"Плавання\"\n  MT_SINK: \"Занурення\"\n#\n  TORSO_USE_GENDER: \"Використовувати стать\"\n  TORSO_ALWAYS_MALE: \"Завжди чоловіки\"\n  TORSO_ALWAYS_FEMALE: \"Завжди жінки\"\n#\n  DRAWING_ROUTINE_SOLDIER_SECTOID: \"Солдат, Сектоїд\"\n  DRAWING_ROUTINE_FLOATER: \"Порт\"\n  DRAWING_ROUTINE_HWP: \"Платформи для важкої зброї\"\n  DRAWING_ROUTINE_CYBERDISC: \"Кібердиск\"\n  DRAWING_ROUTINE_CIVILIAN_ETHEREAL: \"Цивільний, безтілесний\"\n  DRAWING_ROUTINE_SECTOPOD_REAPER: \"Сектопод, Жнець\"\n  DRAWING_ROUTINE_SNAKEMAN: \"Змієлюдина\"\n  DRAWING_ROUTINE_CHRYSSALID: \"Крисалід\"\n  DRAWING_ROUTINE_SILACOID: \"Силакоїд\"\n  DRAWING_ROUTINE_CELATID: \"Целатид\"\n  DRAWING_ROUTINE_MUTON: \"Мутон\"\n  DRAWING_ROUTINE_SWS: \"Системи глибинної зброї\"\n  DRAWING_ROUTINE_HALLUCINOID: \"Галюциноїд\"\n  DRAWING_ROUTINE_AQUANAUTS: \"Акванавти\"\n  DRAWING_ROUTINE_CALCINITE_AND_MORE: \"Кальциніт, Глибинник, Гіллмен, Людина-омар, Тасот\"\n  DRAWING_ROUTINE_AQUATOID: \"Акватоїд\"\n  DRAWING_ROUTINE_BIO_DRONE: \"Біо-дрон\"\n  DRAWING_ROUTINE_TFTD_CIVILIAN_A: \"TFTD Цивільні типу A та TFTD Зомбі\"\n  DRAWING_ROUTINE_TFTD_CIVILIAN_B: \"TFTD Цивільні типу B\"\n  DRAWING_ROUTINE_TENTACULAT: \"Тентакулат\"\n  DRAWING_ROUTINE_TRISCENE: \"Трисцен\"\n  DRAWING_ROUTINE_XARQUID: \"Ксарквід\"\n  DRAWING_ROUTINE_INVERTED_CYBERDISC: \"Перевернутий кібердиск (анімація руху зверху)\"\n#\n  stats: \"Модифікатори статистики\"\n  specab: \"Особливість\"\n  movementType: \"Тип руху\"\n  allowsRunning: \"Дозволити біг?\"\n  allowsStrafing: \"Дозволити обстріл?\"\n  allowsSneaking: \"Дозволяє крастися?\"\n  allowsKneeling: \"Дозволити присідання?\"\n  allowsMoving: \"Дозволити переміщення?\"\n  fearImmune: \"Імунітет до втрати моралі?\"\n  bleedImmune: \"Імунітет до кровотечі?\"\n  painImmune: \"Імунітет до оглушення?\"\n  zombiImmune: \"Імунітет до зомбіфікації?\"\n  ignoresMeleeThreat: \"Ігнорувати загрозу ближнього бою?\"\n  createsMeleeThreat: \"Створювати загрозу ближнього бою?\"\n  builtInWeapons: \"Вбудовані предмети\"\n  specialWeapon: \"Спеціальна зброя\"\n  heatVision: \"\"\n  visibilityThroughFire: \"\"\n  psiVision: \"PSI-чуття\"\n  psiCamouflage: \"PSI-камуфляж\"\n  visibilityAtDay: \"Видимість вдень\"\n  visibilityAtDark: \"Видимість вночі\"\n  camouflageAtDay: \"Камуфляж вдень\"\n  camouflageAtDark: \"Камуфляж вночі\"\n  antiCamouflageAtDay: \"Анти-камуфляж вдень\"\n  antiCamouflageAtDark: \"Анти-камуфляж вночі\"\n  psiDefence: \"PSI-захист\"\n  meleeDodge: \"Ухилення від ближнього бою\"\n  meleeDodgeBackPenalty: \"Штраф до ухилення від ближнього бою\"\n  recovery: \"Відновлення кожного ходу:\"\n  time: \"Час\"\n  energy: \"Енергія\"\n  morale: \"Мораль\"\n  health: \"Здоров'я\"\n  stun: \"Оглушення\"\n  mana: \"Мана\"\n  units: \"Сумісні одиниці\"\n  ranks: \"\"\n  frontArmor: \"Фронтальна броня\"\n  sideArmor: \"Бокова броня\"\n  leftArmorDiff: \"Бонус до броні зліва\"\n  rearArmor: \"Тилова броня\"\n  underArmor: \"Нижня броня\"\n#\n  sizeX: \"Розмір X\"\n  sizeY: \"Розмір Y\"\n  buildCost: \"Вартість будівництва\"\n  buildCostItems: \"Будівельні матеріали:\"\n  buildTime: \"Час побудови\"\n  monthlyCost: \"Місячна вартість\"\n  refundValue: \"Вартість повернення\"\n  requiresBaseFunc: \"Необхідні послуги\"\n  provideBaseFunc: \"Надає послуги\"\n  forbiddenBaseFunc: \"Забороняє послуги\"\n  lift: \"Підйомний ліфт?\"\n  hyper: \"Гіперхвильовий декодер?\"\n  mind: \"Розумовий щит?\"\n  mindPower: \"Сила розумового щита\"\n  grav: \"Гравітаційний щит?\"\n  storage: \"Складський простір\"\n  personnel: \"Жилий простір\"\n  aliens: \"Тюремний простір\"\n  crafts: \"Ангарний простір\"\n  labs: \"Примішення лабораторій\"\n  workshops: \"Приміщення майстерень\"\n  psiLabs: \"Примішення PSI-лабораторій\"\n  trainingRooms: \"Приміщення тренажерних залів\"\n  sightRange: \"Дальність видимості\"\n  sightChance: \"Шанс видимості\"\n  radarRange: \"Радіус дії радара\"\n  radarChance: \"Шанс спрацьовування радару\"\n  defense: \"Рівень оборони\"\n  hitRatio: \"Шанс влучання\"\n  ammoNeeded: \"Необхідні боєприпаси\"\n  unifiedDamageFormula: \"\"\n  ammoItem: \"Боєприпаси\"\n  maxAllowedPerBase: \"Максимально дозволений на базу\"\n  manaRecoveryPerDay: \"Мани в день\"\n  healthRecoveryPerDay: \"Здоров’я в день\"\n  sickBayAbsoluteBonus: \"Абсолютний бонус лікування\"\n  sickBayRelativeBonus: \"Відносний бонус лікування\"\n  prisonType: \"Тип в'язниці\"\n  rightClickActionType: \"Дія клацання правою кнопкою миші\"\n  leavesBehindOnSell: \"Залишки на продаж\"\n  removalTime: \"Час видалення\"\n  canBeBuiltOver: \"Чи можна перебудувати?\"\n  upgradeOnly: \"\"\n  buildOverFacilities: \"Будівельні споруди\"\n#\n  BFRCT_DEFAULT: \"оригінал за замовчуванням\"\n  BFRCT_PRISON: \"перейти до В'язниць\"\n  BFRCT_ENGINEERING: \"перейти до Виробництва\"\n  BFRCT_RESEARCH: \"перейти до Досліджень\"\n  BFRCT_GYM: \"перейти до Бойових тренувань\"\n  BFRCT_PSI_LABS: \"перейти до PSI-лабораторій\"\n  BFRCT_BARRACKS: \"перейти до Казарм\"\n  BFRCT_GREY_MARKET: \"перейти до Чорного ринку\"\n  BFRCT_GEOSCAPE: \"перейти до Планетарного вигляду\"\n#\n  costRent: \"Вартість оренди\"\n  soldiers: \"Вантажний простір\"\n  maxUnitsLimit: \"Максимальний вантажний об'єм\"\n  pilots: \"Розмір кабіни\"\n  pilotMinStatsRequired: \"\"\n  pilotSoldierBonusesRequired: \"\"\n  vehicles: \"Потужність транспортних засобів\"\n  onlyOneSoldierGroupAllowed: \"Допускається лише одна група солдатів?\"\n  allowedSoldierGroups: \"Дозволені групи солдатів\"\n  allowedArmorGroups: \"\"\n  limitArmorGroups: \"\"\n  maxHWPUnitsLimit: \"Максимальна вмістимість транспортних засобів\"\n  maxSmallSoldiers: \"Максимум легкої пехоти\"\n  maxLargeSoldiers: \"Максимум важкої пехоти\"\n  maxSmallVehicles: \"Максимум легкої техніки\"\n  maxLargeVehicles: \"Максимум важкої техніки\"\n  maxSmallUnits: \"Максимум легких одиниць\"\n  maxLargeUnits: \"Максимум важких одиниць\"\n  maxSoldiers: \"Максимум бійців\"\n  maxVehicles: \"Максимум техніки\"\n  maxItems: \"Ліміт екіпірування\"\n  maxStorageSpace: \"Місце для зберігання\"\n  maxAltitude: \"Обмеження висоти повітряного бою\"\n  weapons: \"Склад зброї\"\n  weaponStrings: \"Назва зброї\"\n  fixedWeapons: \"Закріплена зброя\"\n  weaponTypes: \"Дозволені види зброї\"\n  damageMax: \"Можливість пошкодження\"\n  avoidBonus: \"Бонус ухилення (на площині)\"\n  avoidBonus2: \"\"\n  powerBonus: \"Бонус до потужності (на площині)\"\n  hitBonus: \"Бонус за удар (на площині)\"\n  fuelMax: \"Ємність паливного баку\"\n  speedMax: \"Максимальна швидкість\"\n  accel: \"Прискорення\"\n  shieldCapacity: \"Ємність щита\"\n  shieldRecharge: \"Перезарядка щита (Бій)\"\n  shieldRechargeInGeoscape: \"Перезарядка щита (Глобус)\"\n  shieldBleedThrough: \"Наскрізний щит\"\n  shieldRechargedAtBase: \"Перезарядка щита (База)\"\n  refuelItem: \"Елемент заправки\"\n  refuelRate: \"Відсоток заправки\"\n  repairRate: \"Норма ремонту\"\n  spacecraft: \"Фінальний корабель?\"\n  allowLanding: \"Дозволити посадку?\"\n  notifyWhenRefueled: \"Повідомити про заправку?\"\n  autoPatrol: \"Автоматичне патрулювання?\"\n  undetectable: \"Непомітно?\"\n  patrolWithoutFuel: \"\"\n  keepCraftAfterFailedMission: \"Десантуватися?\"\n  _calculatedValues: \"Розрахункові значення\"\n  _maxRange: \"Максимальний діапазон\"\n  _minRange: \"Мінімальний діапазон\"\n  _avgRange: \"Середній діапазон\"\n#\n  hunterKillerPercentage: \"Шанс мисливця-вбивці\"\n  huntMode: \"Режим полювання\"\n  huntSpeed: \"Швидкість полювання\"\n  huntBehavior: \"Поведінка полювання\"\n  range: \"Діапазон\"\n  reload: \"Час перезавантаження\"\n  breakOffTime: \"Час перерви\"\n  score: \"Оцінка\"\n  missionScore: \"Оцінка місії\"\n  craftCustomDeploy: \"Розгортання подробиць НЛО\"\n  missionCustomDeploy: \"Розгортання подробиць місії\"\n  _escapeCountdown: \"Зворотній відлік втечі\"\n  _fireRate: \"Скорострільність\"\n  _averageDPM: \"Середній DPM\"\n#\n  HM_INTERCEPTORS: \"віддавати перевагу мисливським перехоплювачам\"\n  HM_TRANSPORTS: \"віддавати перевагу мисливським транспортам\"\n  HM_RANDOM: \"випадково\"\n#\n  HB_FLEE: \"втікати, коли програєте\"\n  HB_KAMIKAZE: \"боротися до знищення\"\n  HB_RANDOM: \"випадково\"\n#\n  tractorBeamPower: \"Потужність тягового променя\"\n  damage: \"Пошкодження\"\n  shieldDamageModifier: \"Модифікатор пошкодження щита\"\n  accuracy: \"Точність\"\n  reloadCautious: \"Перезавантажити (Обережно)\"\n  reloadStandard: \"Перезавантажити (Стандартно)\"\n  reloadAggressive: \"Перезавантажити (Агресивно)\"\n  launcher: \"Пункт запуску\"\n  weaponType: \"Тип зброї\"\n  clip: \"Магазин\"\n  ammoMax: \"Раунди\"\n  rearmRate: \"Швидкість перезарядки\"\n  bulletSaving: \"Економія боєприпасів?\"\n  _damageRange: \"\"\n  _damageRangeBasic: \"\"\n  _averageTotalDamage: \"Середні сумарні пошкодження\"\n#\n  allowPiloting: \"\"\n  costSalary: \"\"\n  costSalarySquaddie: \"\"\n  costSalarySergeant: \"\"\n  costSalaryCaptain: \"\"\n  costSalaryColonel: \"\"\n  costSalaryCommander: \"\"\n#\n  race: \"\"\n  rank: \"\"\n  livingWeapon: \"\"\n  meleeWeapon: \"Зброя ближнього бою\"\n  psiWeapon: \"\"\n  _builtInWeaponSets: \"\"\n  _weightedBuiltInWeaponSets: \"\"\n  spawnUnit: \"\"\n  _capturable: \"\"\n  capturable: \"\"\n  canSurrender: \"\"\n  autoSurrender: \"\"\n  spotter: \"\"\n  sniper: \"\"\n"
  },
  {
    "path": "bin/common/Language/bg.yml",
    "content": "bg:\n  STR_OPENXCOM: \"OpenXcom\"\n  STR_NEW_GAME: \"Нова игра\"\n  STR_LOAD_SAVED_GAME: \"Продължаване\"\n  STR_SELECT_DIFFICULTY_LEVEL: \"Изберете ниво на трудност\"\n  STR_1_BEGINNER: \"1> За начинаещи\"\n  STR_2_EXPERIENCED: \"2> За напреднали\"\n  STR_3_VETERAN: \"3> За ветерани\"\n  STR_4_GENIUS: \"4> За гении\"\n  STR_5_SUPERHUMAN: \"5> За свръхчовеци\"\n  STR_TIME: \"Час\"\n  STR_DATE: \"Дата\"\n  STR_SELECT_GAME_TO_LOAD: \"Изберете игра за продължаване\"\n  STR_SELECT_SAVE_POSITION: \"Изберете място за запазване\"\n  STR_GAME_OPTIONS: \"НАСТРОЙКИ НА ИГРАТА\"\n  STR_LOAD_GAME: \"ЗАРЕЖДАНЕ\"\n  STR_SAVE_GAME: \"ЗАПАЗВАНЕ\"\n  STR_ABANDON_GAME: \"НАПУСКАНЕ НА ИГРАТА\"\n  STR_ABANDON_GAME_QUESTION: \"НАПУСКАНЕ НА ИГРАТА?\"\n  STR_QUIT: \"Излизане\"\n  STR_SAVING_GAME: \"Играта се запазва\"\n  STR_LOADING_GAME: \"Играта се зарежда\"\n  STR_NO_SAVED_GAME_PRESENT: \"Няма запазена игра\"\n  STR_LOAD_UNSUCCESSFUL: \"Неуспешно зареждане\"\n  STR_SAVE_UNSUCCESSFUL: \"Успешно запаметяване\"\n  STR_LOAD_SUCCESSFUL: \"Зареждането е успешно\"\n  STR_SAVE_SUCCESSFUL: \"Запазването е успешно\"\n  STR_DELETE: \"ИЗТРИВАНЕ\"\n  STR_DELETE_UNSUCCESSFUL: \"Неуспешно изтриване\"\n  STR_IS_IT_OK_TO_DELETE_THE_SAVED_GAME: \"Изтриване на запазената игра?\"\n  STR_ORIGINAL_XCOM: \"Оригинален X-COM\"\n  STR_LOADING: \"Зарежда се...\"\n  STR_DETAILS: \"СЪДЪРЖА> {ALT}{0}\"\n  STR_NEW_BATTLE: \"Нова битка\"\n  STR_OPTIONS: \"Настройки\"\n  STR_RIGHT_CLICK_TO_DELETE: \"Щракнете с десния бутон на мишката за изтриване.\"\n  STR_RESTORE_DEFAULTS: \"Оригинални настр.\"\n  STR_CONTROLS: \"КЛАВИШИ\"\n  STR_GENERAL: \"Общи\"\n  STR_GEOSCAPE: \"Глобална карта\"\n  STR_BATTLESCAPE: \"Бойна карта\"\n  STR_SCREENSHOT: \"Снимка на екрана\"\n  STR_FPS_COUNTER: \"Брояч на кадри-за-секунда\"\n  STR_ROTATE_LEFT: \"Завъртане наляво\"\n  STR_ROTATE_RIGHT: \"Завъртане надясно\"\n  STR_ROTATE_UP: \"Завъртане нагоре\"\n  STR_ROTATE_DOWN: \"Завъртане надолу\"\n  STR_ZOOM_IN: \"Приближаване\"\n  STR_ZOOM_OUT: \"Отдалечаване\"\n  STR_TOGGLE_COUNTRY_DETAIL: \"Вкл/изкл държавните граници\"\n  STR_TOGGLE_RADAR_RANGES: \"Вкл/изкл обсега на локаторите\"\n  STR_SCROLL_LEFT: \"Придвижи картата наляво\"\n  STR_SCROLL_RIGHT: \"Придвижи картата надясно\"\n  STR_SCROLL_UP: \"Придвижи картата нагоре\"\n  STR_SCROLL_DOWN: \"Придвижи картата надолу\"\n  STR_UNIT_LEVEL_ABOVE: \"Качи на по-горно ниво\"\n  STR_UNIT_LEVEL_BELOW: \"Смъкни на по-долно ниво\"\n  STR_VIEW_LEVEL_ABOVE: \"Покажи по-горното ниво\"\n  STR_VIEW_LEVEL_BELOW: \"Покажи по-долното ниво\"\n  STR_CENTER_SELECTED_UNIT: \"Центриране на избраната единица\"\n  STR_PREVIOUS_UNIT: \"Избиране на предишната единица\"\n  STR_NEXT_UNIT: \"Избиране на следващата единица\"\n  STR_DESELECT_UNIT: \"Не избирай единицата отново\"\n  STR_USE_LEFT_HAND: \"Използвай предмет в лявата ръка\"\n  STR_USE_RIGHT_HAND: \"Използвай предмет в дясната ръка\"\n  STR_INVENTORY: \"Инвентар\"\n  STR_MINIMAP: \"Миникарта\"\n  STR_MULTI_LEVEL_VIEW: \"Виж всички нива\"\n  STR_END_TURN: \"Край на хода\"\n  STR_ABORT_MISSION: \"Прекратяване на операцията\"\n  STR_UNIT_STATS: \"Характеристики на единицата\"\n  STR_KNEEL: \"На коляно\"\n  STR_RELOAD: \"Презареди\"\n  STR_TOGGLE_PERSONAL_LIGHTING: \"Вкл/изк на лично осветление\"\n  STR_DONT_RESERVE_TIME_UNITS: \"Не запазвай ВЕ\"\n  STR_RESERVE_TIME_UNITS_FOR_SNAP_SHOT: \"Запази ВЕ за бърз изстрел\"\n  STR_RESERVE_TIME_UNITS_FOR_AIMED_SHOT: \"Запази ВЕ за прицелен изстрел\"\n  STR_RESERVE_TIME_UNITS_FOR_AUTO_SHOT: \"Запази ВЕ за откос\"\n  STR_CENTER_ON_ENEMY_1: \"Центрирай на враг 1\"\n  STR_CENTER_ON_ENEMY_2: \"Центрирай на враг 2\"\n  STR_CENTER_ON_ENEMY_3: \"Центрирай на враг 3\"\n  STR_CENTER_ON_ENEMY_4: \"Центрирай на враг 4\"\n  STR_CENTER_ON_ENEMY_5: \"Центрирай на враг 5\"\n  STR_CENTER_ON_ENEMY_6: \"Центрирай на враг 6\"\n  STR_CENTER_ON_ENEMY_7: \"Центрирай на враг 7\"\n  STR_CENTER_ON_ENEMY_8: \"Центрирай на враг 8\"\n  STR_CENTER_ON_ENEMY_9: \"Центрирай на враг 9\"\n  STR_CENTER_ON_ENEMY_10: \"Центрирай на враг 10\"\n  STR_CREATE_INVENTORY_TEMPLATE: \"Създай шаблон за инвентар\"\n  STR_APPLY_INVENTORY_TEMPLATE: \"Възстанови шаблон за инвентар\"\n  STR_CLEAR_INVENTORY: \"Изпразни инвентара\"\n  STR_AUTO_EQUIP: \"Автоматично екипиране\"\n  STR_QUICK_SAVE: \"Бързо запазване\"\n  STR_QUICK_LOAD: \"Бързо зареждане\"\n  STR_ADVANCED: \"ЕКСПЕРТНИ\"\n  STR_AGGRESSIVERETALIATION: \"Агресивно отвръщане\"\n  STR_AGGRESSIVERETALIATION_DESC: \"НЛО ще се опитват да засекат базите ви по всяко време, без значение на каква мисия са.\"\n  STR_STORAGELIMITSENFORCED: \"Складови ограничения за прибрани предмети\"\n  STR_STORAGELIMITSENFORCED_DESC: \"Налага ограниченията върху капацитета на изолационните и складовите помещения за живи извънземни и предмети прибрани при операции.\"\n  STR_CANSELLLIVEALIENS: \"Продажба на живи извънземни\"\n  STR_CANSELLLIVEALIENS_DESC: \"Позволява продажбата на живи извънземни; препоръчва се ако са в сила складовите граничения.\"\n  STR_ALLOWBUILDINGQUEUE: \"Позволява употребата на последователно строителство\"\n  STR_ALLOWBUILDINGQUEUE_DESC: \"Позволява строежа на нови модули до незавършени такива.\"\n  STR_BATTLEAUTOEND: \"Авто-приключване на битките\"\n  STR_BATTLEAUTOEND_DESC: \"Битките приключват автоматично след обезвреждането на последният жив враг.\"\n  STR_BATTLEINSTANTGRENADE: \"Гранатите избухват веднага\"\n  STR_BATTLEINSTANTGRENADE_DESC: \"Гранатите нагласени да избухнат след 0 хода ще избухнат веднага след хвърлянето им, вместо в края на хода.\"\n  STR_BATTLEUFOEXTENDERACCURACY: \"Точност като в UFO Extender\"\n  STR_BATTLEUFOEXTENDERACCURACY_DESC: \"В зависимост от вида муниция, точността на изстрелите намалява след определено разстояние. Коригираната точност ще бъде посочена на курсора.\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE: \"Прехвърляне в полет\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE_DESC: \"Позволява прехвърлянето на летателни апарати дори когато са в полет.\"\n  STR_CRAFTLAUNCHALWAYS: \"Принудително излитане\"\n  STR_CRAFTLAUNCHALWAYS_DESC: \"Позволява преждевремменото изстрелване на летателни апарати преди те да са готови, незачитайки нуждата от поддръжка.\"\n  STR_CUSTOMINITIALBASE: \"Персонализирана начална база\"\n  STR_CUSTOMINITIALBASE_DESC: \"При започването на нова игра можете да подредите ръчно началните модули на базата вместо да използвате предопределения план.\"\n  STR_GLOBESEASONS: \"Реалистично осветяване на глобуса\"\n  STR_GLOBESEASONS_DESC: \"Използване на по-реалистично слъчево осветление на Глобалната карта според наклона на земната ос.\"\n  STR_PLAYINTRO: \"Показване на интро\"\n  STR_PLAYINTRO_DESC: \"Показване на въвеждащото филмче при пускане на играта.\"\n  STR_SHOWMORESTATSININVENTORYVIEW: \"Характеристики в инвентара\"\n  STR_SHOWMORESTATSININVENTORYVIEW_DESC: \"Показва допълнителна информация за избрания войник на инвентарния екран.\"\n  STR_SNEAKYAI: \"Коварен изкуствен интелект\"\n  STR_SNEAKYAI_DESC: \"Изкуственият интелект се крие доколкото е възможно.\"\n  STR_STRAFE: \"Алтернативни методи на придвижване\"\n  STR_STRAFE_DESC: \"Позволява бягане, движение настрани и независимо завъртане на кулола на танковете със задържане на клавиша CTRL.\"\n  STR_BATTLEEXPLOSIONHEIGHT: \"Височина на взривовете\"\n  STR_BATTLEEXPLOSIONHEIGHT_DESC: \"Промени до каква височна достигат взривовете.{NEWLINE}(Плоски: 0, кръгли: 3)\"\n  STR_AUTOSAVE: \"Автоматично запазване\"\n  STR_AUTOSAVE_DESC: \"Автоматично запазва играта при дадения интервал. Не работи в Железния режим.\"\n  STR_AUTOSAVE_FREQUENCY: \"Честота на автоматичното запазване\"\n  STR_AUTOSAVE_FREQUENCY_DESC: \"Брой ходове след които играта автоматично се запазва.\"\n  STR_ALLOWPSIONICCAPTURE: \"Позволява пси-пленяване\"\n  STR_ALLOWPSIONICCAPTURE_DESC: \"Обсебването на всички останали пришълци води до победа, и те се считат за заловени живи.\"\n  STR_ANYTIMEPSITRAINING: \"Псионична подготовка по всяко време\"\n  STR_ANYTIMEPSITRAINING_DESC: \"Позволява изпращането на войници на псионична подготовка  по всяко време на месеца. Помнете, че първоначалната подготовка отема от 30 до 60 дни.\"\n  STR_SKIPNEXTTURNSCREEN: \"Прескачане на екраните за \\\"следващ ход\\\"\"\n  STR_SKIPNEXTTURNSCREEN_DESC: \"Екраните \\\"следващ ход\\\" по време на битка се затварят автоматично след малко време.\"\n  STR_NOT_ENOUGH_SPACE: \"Няма място!\"\n  STR_WEAPONSELFDESTRUCTION: \"Самоунищожаване на оръжията на пришълците\"\n  STR_WEAPONSELFDESTRUCTION_DESC: \"Оръжията носени от пришълците ще се самоунищожат когато притежателите им бъдат убити, също както в XCOM 2012.\"\n  STR_RETAINCORPSES: \"Запази разпитаните пришълци.\"\n  STR_RETAINCORPSES_DESC: \"След \\\"изследването\\\" на живи пришълци, телата им ще бъдат добавени към складовата наличност, както в XCOM 2012.\"\n  STR_SAVE_VOXEL_VIEW: \"Направи снимка от първо лице\"\n  STR_RESERVE_TIME_UNITS_FOR_KNEEL: \"Запази ВЕ за коленичене\"\n  STR_EXPEND_ALL_TIME_UNITS: \"Използвай всички оставащи Времеви Единици\"\n  STR_PSISTRENGTHEVAL: \"Оценяване на пси-силата\"\n  STR_PSISTRENGTHEVAL_DESC: \"След завършането на подходящото научно изследване всички войници ще получат оценка на псионичната им сила.\"\n  STR_DISABLEAUTOEQUIP: \"Изключи автоматичното снаряжавене\"\n  STR_DISABLEAUTOEQUIP_DESC: \"Изключи автоматичното снаряжаване на нови войници преди битка.\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT: \"Позволява подобряване на пси-силата.\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT_DESC: \"Псионичната сула на войниците може да се подобрява чрез опит и тренировка.\"\n  STR_BATTLESMOOTHCAMERA: \"Плавно проследяване на изстрели\"\n  STR_BATTLESMOOTHCAMERA_DESC: \"Бойната камера проследява изстрели\"\n  STR_BATTLECONFIRMFIREMODE: \"Потвърждаване на стрелбата\"\n  STR_BATTLECONFIRMFIREMODE_DESC: \"Изисква второ цъкване на същото място за потвърждаване на заповяданата стрелба.\"\n  STR_SELECT_BASE_1: \"Избери база 1\"\n  STR_SELECT_BASE_2: \"Избери база 2\"\n  STR_SELECT_BASE_3: \"Избери база 3\"\n  STR_SELECT_BASE_4: \"Избери база 4\"\n  STR_SELECT_BASE_5: \"Избери база 5\"\n  STR_SELECT_BASE_6: \"Избери база 6\"\n  STR_SELECT_BASE_7: \"Избери база 7\"\n  STR_SELECT_BASE_8: \"Избери база 8\"\n  STR_VIDEO: \"ГРАФИКА\"\n  STR_AUDIO: \"ЗВУК\"\n  STR_BATTLESCAPE_UC: \"БОЙНА КАРТА\"\n  STR_MODS_UC: \"МОДИФИКАЦИИ\"\n  STR_MODS: \"Модификации\"\n  STR_DISPLAY_RESOLUTION: \"Размер на екрана\"\n  STR_DISPLAY_RESOLUTION_DESC: \"Променя размера на екрана, размера на играта ще бъде оразмерен подобаващо. Стелките сменят поддържаните размери. Избери, за да напишеш ръзно размера.\"\n  STR_ORIGINAL: \"Възстанови оригиналните настройки\"\n  STR_DISPLAY_MODE: \"Режим на екрана\"\n  STR_WINDOWED: \"В прозорец\"\n  STR_FULLSCREEN: \"На цял екран\"\n  STR_BORDERLESS: \"Без рамка\"\n  STR_DISPLAY_LANGUAGE: \"Език\"\n  STR_DISPLAY_LANGUAGE_DESC: \"Промени езика на текста в играта.\"\n  STR_DISPLAY_FILTER: \"Филтриране на образа\"\n  STR_DISPLAY_FILTER_DESC: \"Променя филтъра, наложен в играта.{NEWLINE}*изисква OpenGL хардуерно ускорение.\"\n  STR_DISPLAY_OPTIONS: \"Настройки на образа\"\n  STR_LETTERBOXED: \"В рамка\"\n  STR_LETTERBOXED_DESC: \"Образът е в рамка, с цел запазване на оригиналните пропорции.\"\n  STR_RESIZABLE: \"Променлив размер\"\n  STR_LOCK_MOUSE: \"Хващане на мишката\"\n  STR_LOCK_MOUSE_DESC: \"Не позволява на курсора на мишката да напусне прозореца на играта. Ctrl+G за вкл/изкл по всяко време.\"\n  STR_FIXED_WINDOW_POSITION: \"Мястото на прозореца не може да се промени\"\n  STR_FIXED_WINDOW_POSITION_DESC: \"Избери мястото за прозореца.\"\n  STR_DISPLAY_SET_WINDOW_POSITION: \"Избери новото начално място за прозореца\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_X: \"Нова лява граница на X:\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_Y: \"Нова горна граница на Y:\"\n  STR_MUSIC_VOLUME: \"Сила на музиката\"\n  STR_MUSIC_VOLUME_DESC: \"Променя силата на фоновата музика.\"\n  STR_SFX_VOLUME: \"Сила на ефектите\"\n  STR_SFX_VOLUME_DESC: \"Променя силата на звуковите ефекти.\"\n  STR_UI_VOLUME: \"Сила на звука по менютата\"\n  STR_UI_VOLUME_DESC: \"Променя силата на звука на тоновете по менютата.\"\n  STR_SCROLL_SPEED: \"Скорост на картата\"\n  STR_SCROLL_SPEED_GEO_DESC: \"Променя скоростта на местене на глобуса.\"\n  STR_SCROLL_SPEED_BATTLE_DESC: \"Променя скоростта на местене на картата.\"\n  STR_DOGFIGHT_SPEED: \"Скорост на въздуш. бой\"\n  STR_DOGFIGHT_SPEED_DESC: \"Променя скоростта на въздушните битки между прехващащи апарати и НЛО. Забавянето може да подобри играта при по-бавни компютри.\"\n  STR_CLOCK_SPEED: \"Скорост на часовника\"\n  STR_CLOCK_SPEED_DESC: \"Променя скоростта на часовника на Глобалната карта. Забавянето може да подобри играта при по-бавни компютри.\"\n  STR_GLOBE_DETAILS: \"Детайли на глобуса\"\n  STR_GLOBE_COUNTRIES: \"Държави\"\n  STR_GLOBE_COUNTRIES_DESC: \"Показва държавите спонсори на глобуса.\"\n  STR_GLOBE_RADARS: \"Радари\"\n  STR_GLOBE_RADARS_DESC: \"Показва обхвата на радарите на глобуса.\"\n  STR_GLOBE_FLIGHT_PATHS: \"Траектория на полетите\"\n  STR_GLOBE_FLIGHT_PATHS_DESC: \"Показва върху глобуса пътищата следвани от летателните апарати.\"\n  STR_CONTROLS_DESC: \"Използвайте ляв бутон на мишката, за да измените клавишна комбинация.{NEWLINE}Използвайте десен бутон, за да я изключите.\"\n  STR_BASE_GAME: \"Основна игра\"\n  STR_MODS_TOOLTIP: \"Версия {0} на {1}.{NEWLINE}{2}\"\n  STR_EDGE_SCROLL: \"Местене по краищата\"\n  STR_EDGE_SCROLL_DESC: \"С бутон: Картата се мести при задържането на левия бутон на мишката върху края на екрана.{NEWLINE}Автоматично: Картата се мести когато мишката е в края на екрана.\"\n  STR_TRIGGER_SCROLL: \"С бутон\"\n  STR_AUTO_SCROLL: \"Автоматично\"\n  STR_DRAG_SCROLL: \"Местене с влачене\"\n  STR_DRAG_SCROLL_DESC: \"Картата се мести със задържане на избрания бутон на мишката и завлачване.\"\n  STR_LEFT_MOUSE_BUTTON: \"Ляв бутон\"\n  STR_MIDDLE_MOUSE_BUTTON: \"Среден бутон\"\n  STR_RIGHT_MOUSE_BUTTON: \"Десен бутон\"\n  STR_FIRE_SPEED: \"Скорост на изстрелите\"\n  STR_FIRE_SPEED_DESC: \"Променя скоростта на изстрелите.\"\n  STR_PLAYER_MOVEMENT_SPEED: \"Скорост на играча\"\n  STR_PLAYER_MOVEMENT_SPEED_DESC: \"Променя скоростта на движение на единиците контролирани от  играча.\"\n  STR_COMPUTER_MOVEMENT_SPEED: \"Скорост на двиение на изкуствения интелект\"\n  STR_COMPUTER_MOVEMENT_SPEED_DESC: \"Променя скоростта на движение на единиците контролирани от изкуствения интелект.\"\n  STR_PATH_PREVIEW: \"Показване на пътя\"\n  STR_PATH_ARROWS: \"Стрелки\"\n  STR_PATH_ARROWS_DESC: \"При щракване се показва пътя по който единицата ще достигне това място. Цветът указва възможните действия: зелено - движение и стрелба; жълто - движение; червено - невъзможно движение.\"\n  STR_PATH_TIME_UNIT_COST: \"Точки действие\"\n  STR_PATH_TIME_UNIT_COST_DESC: \"При щракване се показват точките действие оставащи на единицата след достигане на мястото.\"\n  STR_USER_INTERFACE_OPTIONS: \"Опции на интерфейса\"\n  STR_TOOLTIPS: \"Подсказки\"\n  STR_TOOLTIPS_DESC: \"Показване на описания на бутоните на Бойната карта.\"\n  STR_DEATH_NOTIFICATIONS: \"Съобщаване за смърт\"\n  STR_DEATH_NOTIFICATIONS_DESC: \"Показване на съобщениe всеки път щом един от войниците ви умре.\"\n  STR_SHOW_FUNDS: \"Налични средства\"\n  STR_SHOW_FUNDS_DESC: \"Показва текущите налични средства до часовника на Глобалната карта.\"\n  STR_MISSION_GENERATOR: \"ОПЕРАЦИЯ ПО ЖЕЛАНИЕ\"\n  STR_MAP_OPTIONS: \"ЗАДАДЕНО ЗА КАРТАТА\"\n  STR_ALIEN_OPTIONS: \"ЗАДАДЕНО ЗА ПРИШЪЛЦИТЕ\"\n  STR_MAP_TERRAIN: \"Терен\"\n  STR_MAP_DARKNESS: \"Тъмнина\"\n  STR_MAP_DEPTH: \"Дълбочина\"\n  STR_DIFFICULTY: \"Трудност\"\n  STR_ALIEN_RACE: \"Вид\"\n  STR_ALIEN_TECH_LEVEL: \"Технологично ниво\"\n  STR_RANDOMIZE: \"Случаен избор\"\n  STR_RESTORE_DEFAULTS_QUESTION: \"Сигурни ли сте, че искате да върнете оригиналните настройки?\"\n  STR_DISPLAY_OPTIONS_CONFIRM: \"ИСКАТЕ ЛИ ДА ЗАПАМЕТИТЕ НАСТРОЙКИТЕ ЗА ДИСПЛЕЯ?\"\n  STR_DISPLAY_OPTIONS_REVERT: \"Връщане след 0:{0}\"\n  STR_MISSING_CONTENT_PROMPT: \"ВНИМАНИЕ:{SMALLLINE}Тази запазена игра използва модове които липсват. Отсъстващото съдържание ще бъде премахнато, и играта може да не се зареди.{NEWLINE}Продължаване?\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT: \"Запазване на предварително задействани гранати\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT_DESC: \"Запазва гранатите задействани в инвентарния екран на войниците преди битка.\"\n  STR_NEWSEEDONLOAD: \"Злоупотреба със запазването на игра\"\n  STR_NEWSEEDONLOAD_DESC: \"Зареждането на игра ще генерира нови случайни числа, така че извършването на едно и също действие може да има различен резултат. Не работи в Железния режим.\"\n  STR_CHANGEVALUEBYMOUSEWHEEL: \"Промяна на стойности с колелцето на мишката\"\n  STR_CHANGEVALUEBYMOUSEWHEEL_DESC: \"Позволява използването на колелцето на мишката за увеличаване/намаляване на стойности с това число.\"\n  STR_BATTLEHAIRBLEACH: \"Подобряване на фигурите на войниците\"\n  STR_BATTLEHAIRBLEACH_DESC: \"Променя изображенията на войниците на Бойната карта да съвпадат с показаното на инвернтарния екран.\"\n  STR_DRAGSCROLLINVERT: \"Обръщане на местенето с влачене\"\n  STR_DRAGSCROLLINVERT_DESC: \"Когато е включено, завлачването премества картата в посока обратна на движението на мишката.\"\n  STR_BATTLESCAPE_SCALE: \"Мащаб на бойната карта\"\n  STR_BATTLESCAPE_SCALE_DESC: \"Режим за промяна на мащаба на бойната карта, въз основа на определена резолюция (разтеглена), или въз основа на определена ниво на приближение (разширено да запълни).\"\n  STR_GEOSCAPE_SCALE: \"Мащаб на глобалната карта\"\n  STR_GEOSCAPESCALE_SCALE_DESC: \"Режим за промяна на мащаба на глобалната карта, въз основа на определена резолюция (разтеглена), или въз основа на определена ниво на приближение (разширено да запълни).\"\n  STR_1_5X: \"1.5 пъти по-голям от оригинала\"\n  STR_2X: \"2 пъти по-голям от оригинала\"\n  STR_THIRD_DISPLAY: \"1/3 Екран\"\n  STR_HALF_DISPLAY: \"1/2 Екран\"\n  STR_FULL_DISPLAY: \"Пълен екран\"\n  STR_FPS_LIMIT: \"Ограничение на кадрите-за-секунда\"\n  STR_FPS_LIMIT_DESC: \"Ограничава колко пъти се опреснява екрана за една секунда, 0 за без ограничение. Ако е зададено рисуване с OpenGL, вместо това играта ще използва Vsync.\"\n  STR_FPS_INACTIVE_LIMIT: \"Ограничение на кадрите за секунда на заден план\"\n  STR_FPS_INACTIVE_LIMIT_DESC: \"Ограничава броя на опресняване на екрана за секунда ако OpenXcom е на заден план.\"\n  STR_NOALIENPANICMESSAGES: \"Без съобщения за паникьосани пришълци\"\n  STR_NOALIENPANICMESSAGES_DESC: \"Не се показват съобщения за паника за пришълците които не се виждат от играча.\"\n  STR_ALIENBLEEDING: \"Кървящи пришълци\"\n  STR_ALIENBLEEDING_DESC: \"Позволява нанасянето на смъртоносни рани върху повечето извънземни.\"\n  STR_FIELDPROMOTIONS: \"Полеви повишения\"\n  STR_FIELDPROMOTIONS_DESC: \"Само войниците присъствали на операцията са годни за получаване на повишения.\"\n  STR_MEETINGPOINT: \"Предсказване на тректорията на НЛО\"\n  STR_MEETINGPOINT_DESC: \"Летателните апарати летят към пресечна точка с НЛО в зависимост от неговата траектория.\"\n  STR_IRONMAN: \"ЖЕЛЕЗЕН РЕЖИМ\"\n  STR_IRONMAN_DESC: \"Без ръчно запазване\"\n  STR_SAVE_AND_ABANDON_GAME: \"ЗАПАЗВАНЕ И НАПУСКАНЕ НА ИГРАТА\"\n  STR_MOD_UNSUCCESSFUL: \"Неуспешно зареждане на мод\"\n  STR_NEW_SAVED_GAME_SLOT: \"<NEW SAVED GAME>\"\n  STR_AUTO_SAVE_GEOSCAPE_SLOT: \"<AUTO GEOSCAPE>\"\n  STR_AUTO_SAVE_BATTLESCAPE_SLOT: \"<AUTO BATTLESCAPE>\"\n  STR_QUICK_SAVE_SLOT: \"<QUICKSAVE>\"\n  STR_DISPLAY_MODE_DESC: \"Променя как играта се показва на екрана.\"\n  STR_PREFERRED_MUSIC_FORMAT: \"Формат на музиката\"\n  STR_PREFERRED_MUSIC_FORMAT_DESC: \"Избира предпочитания формат за музиката ако има няколко възможни.{NEWLINE}ЗАБЕЛЕЖКА: Просвирването на MIDI може да е бъгливо под Windows.\"\n  STR_PREFERRED_SFX_FORMAT: \"Формат на ефектите\"\n  STR_PREFERRED_SFX_FORMAT_DESC: \"Избира предпочитаният формат на звуковите ефекти ако има няколко възможни.\"\n  STR_PREFERRED_VIDEO_FORMAT: \"Видео формат\"\n  STR_PREFERRED_VIDEO_FORMAT_DESC: \"Избор на предпочитания видео формат при наличност на повече от един.\"\n  STR_PREFERRED_VIDEO_ANIMATION: \"Анимация\"\n  STR_PREFERRED_VIDEO_SLIDESHOW: \"Преглед в снимки\"\n  STR_PREFERRED_FORMAT_AUTO: \"Автоматичен избор\"\n  STR_CURRENT_FORMAT: \"В момента: {0}\"\n  STR_SOUND_OPTIONS: \"Настройки звук\"\n  STR_BACKGROUND_MUTE: \"Изключване на фонови звуци\"\n  STR_BACKGROUND_MUTE_DESC: \"Изйкючва всички звуци, когато играта не е на преден план.\"\n  STR_FORCE_FIRE: \"Игнориране на видимостта към целта\"\n  STR_FORCE_FIRE_DESC: \"Позволява принуждаването на войниците да стрелят без значение дали имат видимост към целта със задържане на клавиша CTRL.\"\n  STR_NO_AUDIO_HARDWARE_DETECTED: \"Не е открито звуково устройство\"\n  STR_MOUSEWHEEL_SPEED: \"Скорост на разлистване с колелцето на мишката\"\n  STR_MOUSEWHEEL_SPEED_DESC: \"Настройва броя линии, които се се придвижват, когато се използва колелцето на мишката.\"\n  STR_DISABLED: \"Изключено\"\n  STR_MAXIMIZE_INFO_SCREENS: \"Максимизиране на информационните екрани\"\n  STR_MAXIMIZE_INFO_SCREENS_DESC: \"Инвентарният екран и другите подобни ще се показват на цял екран, независимо от настройките за мащабиране.\"\n  STR_DIARY: \"ДНВЕНИК\"\n  STR_KILLED: \"УБИТИ\"\n  STR_STUNNED: \"ЗАШЕМЕТЕНИ\"\n  STR_PANICKED: \"ИЗПАДНАЛИ В ПАНИКА\"\n  STR_MINDCONTROLLED: \"ОБСЕБЕНИ\"\n  STR_REGION_UNKNOWN: \"Неразкрити\"\n  STR_WEAPON_UNKNOWN: \"Импровизация\"\n  STR_UNKNOWN: \"Неизвестен\"\n  STR_VICTORY: \"Победа\"\n  STR_DEFEAT: \"Загуба\"\n  STR_NO_RECORD: \"Няма данни\"\n  STR_HUMAN: \"Човек\"\n  STR_FRIENDLY: \"Приятел\"\n  STR_HOSTILE: \"Враг\"\n  STR_NEUTRAL: \"Неутрален\"\n  STR_RATING_UC: \"ОЦЕНКА\"\n  STR_LOCATION: \"МЯСТО> {ALT}{0}\"\n  STR_DAYLIGHT_TYPE: \"ВРЕМЕ> {ALT}{0}\"\n  STR_RACE_TYPE: \"СЪЗТЕЗАНИЕ> {ALT}{0}\"\n  STR_DAY: \"Ден\"\n  STR_NIGHT: \"Нощ\"\n  STR_DAYS_WOUNDED: \"ДНИ С РАНИ> {ALT}{0}\"\n  STR_COMBAT: \"БИТКА\"\n  STR_PERFORMANCE: \"ПРЕДСТАВЯНЕ\"\n  STR_NEUTRALIZATIONS_BY_RACE: \"НЕУТРАЛИЗАЦИЯ ПО РАСИ\"\n  STR_NEUTRALIZATIONS_BY_RANK: \"НЕУТРАЛИЗАЦИЯ ПО РАНГ\"\n  STR_NEUTRALIZATIONS_BY_WEAPON: \"НЕУТРАЛИЗАЦИЯ ПО ОРЪЖИЕ\"\n  STR_MISSIONS_BY_LOCATION: \"МИСИИ ПО МЕСТОПОЛОЖЕНИЕ\"\n  STR_MISSIONS_BY_TYPE: \"ВИД МИСИИ\"\n  STR_MISSIONS_BY_UFO: \"НЛО МИСИИ\"\n  STR_SCORE_VALUE: \"РЕЗУЛТАТ> {ALT}{0}\"\n  STR_WINS: \"ПОБЕДИ> {ALT}{0}\"\n  STR_STUNS: \"ЗАШЕМЕТЯВАНИЯ> {ALT}{0}\"\n  STR_PANICKS: \"ИЗПАДАНЕ В ПАНИКА> {ALT}{0}\"\n  STR_MINDCONTROLS: \"ОБСЕБВАНЕ> {ALT}{0}\"\n  STR_AWARDS: \"НАГРАДИ\"\n  STR_COMMENDATIONS_UC: \"ПОХВАЛИ\"\n  STR_COMMENDATIONS: \"Похвали\"\n  STR_MEDALS: \"МЕДАЛИ\"\n  STR_LOST_IN_SERVICE: \"ЗАГИНАЛИ ПО ВРЕМЕ НА БИТКА\"\n  STR_MEDAL_NAME: \"Име на медала\"\n  STR_MEDAL_AWARD_LEVEL: \"Ниво на наградата\"\n  STR_MEDAL_DECOR_LEVEL: \"Ниво на ордени\"\n  STR_AWARD_0: \"Първа награда\"\n  STR_AWARD_1: \"Втора награда\"\n  STR_AWARD_2: \"Трета награда\"\n  STR_AWARD_3: \"Четвърта награда\"\n  STR_AWARD_4: \"Пета награда\"\n  STR_AWARD_5: \"Шеста награда\"\n  STR_AWARD_6: \"Седма награда\"\n  STR_AWARD_7: \"Осма награда\"\n  STR_AWARD_8: \"Девета награда\"\n  STR_AWARD_9: \"Десета награда\"\n  STR_AWARD_DECOR_0: \"Няма\"\n  STR_AWARD_DECOR_1: \"Първа бронзова значка\"\n  STR_AWARD_DECOR_2: \"Втора бронзова значка\"\n  STR_AWARD_DECOR_3: \"Трета бронзова значка\"\n  STR_AWARD_DECOR_4: \"Първа сребърна значка\"\n  STR_AWARD_DECOR_5: \"Втора сребърна значка\"\n  STR_AWARD_DECOR_6: \"Трета сребърна значка\"\n  STR_AWARD_DECOR_7: \"Първа златна значка\"\n  STR_AWARD_DECOR_8: \"Втора златна значка\"\n  STR_AWARD_DECOR_9: \"Трета златна значка\"\n  STR_KILLED_IN_ACTION_MALE: \"ПАДНАЛ В БОЙ\"\n  STR_KILLED_IN_ACTION_FEMALE: \"ПАДНАЛ В БОЙ\"\n  STR_MISSING_IN_ACTION_MALE: \"ЛИПСВАЩ ПО ВРЕМЕ НА АКЦИЯ\"\n  STR_MISSING_IN_ACTION_FEMALE: \"ЛИПСВАЩ ПО ВРЕМЕ НА АКЦИЯ\"\n  STR_AVERAGE_MONTHLY_RATING: \"Средна месечна оценка\"\n  STR_TOTAL_INCOME: \"Общо приходи\"\n  STR_TOTAL_EXPENDITURE: \"Общо разходи\"\n  STR_MISSIONS_WON: \"Приключени мисии\"\n  STR_MISSIONS_LOST: \"Провалени мисии\"\n  STR_NIGHT_MISSIONS: \"Нощни мисии\"\n  STR_BEST_RATING: \"Най-висока оценка на мисия\"\n  STR_WORST_RATING: \"Най-ниска оценка на мисия\"\n  STR_ALIEN_KILLS: \"Убити пришълци\"\n  STR_ALIEN_CAPTURES: \"Заловени пришълци\"\n  STR_FRIENDLY_KILLS: \"Приятелски огън\"\n  STR_AVERAGE_ACCURACY: \"Средна точност\"\n  STR_WEAPON_MOST_KILLS: \"Най-ефективно оръжие\"\n  STR_ALIEN_MOST_KILLS: \"Най-смъртоносен пришълец\"\n  STR_LONGEST_SERVICE: \"Най-много месеци в служба\"\n  STR_TOTAL_DAYS_WOUNDED: \"Болнични\"\n  STR_COUNTRIES_LOST: \"Проникване в държави\"\n  STR_TOTAL_TERROR_SITES: \"Терористични атаки\"\n  STR_TOTAL_BASES: \"Построени бази\"\n  STR_TOTAL_CRAFT: \"Притежаване летателни апарати\"\n  STR_TOTAL_SCIENTISTS: \"Наети учени\"\n  STR_TOTAL_ENGINEERS: \"Наети инженери\"\n  STR_TOTAL_RESEARCH: \"Завършени научни проекти\"\n  STR_DIARY_ACCURACY: \"ТОЧНОСТ> {ALT}{0}%\"\n  STR_STATISTICS: \"Статистика\"\n  STR_STATS: \"ИНФО\"\n  STR_TIME_UNITS_ABBREVIATION: \"ВЕ\"\n  STR_STAMINA_ABBREVIATION: \"ИЗД\"\n  STR_HEALTH_ABBREVIATION: \"ТЖ\"\n  STR_BRAVERY_ABBREVIATION: \"СМЕ\"\n  STR_REACTIONS_ABBREVIATION: \"РЕА\"\n  STR_FIRING_ACCURACY_ABBREVIATION: \"ТС\"\n  STR_THROWING_ACCURACY_ABBREVIATION: \"ТХ\"\n  STR_STRENGTH_ABBREVIATION: \"СИЛ\"\n  STR_MELEE_ACCURACY_ABBREVIATION: \"БОЙ\"\n"
  },
  {
    "path": "bin/common/Language/cs.yml",
    "content": "cs:\n  STR_OPENXCOM: \"OpenXcom\"\n  STR_NEW_GAME: \"Nová hra\"\n  STR_LOAD_SAVED_GAME: \"Nahrát hru\"\n  STR_SELECT_DIFFICULTY_LEVEL: \"Vyberte úroveň obtížnosti\"\n  STR_1_BEGINNER: \"1> Začátečník\"\n  STR_2_EXPERIENCED: \"2> Pokročilý\"\n  STR_3_VETERAN: \"3> Veterán\"\n  STR_4_GENIUS: \"4> Génius\"\n  STR_5_SUPERHUMAN: \"5> Nadčlověk\"\n  STR_TIME: \"Čas\"\n  STR_DATE: \"Datum\"\n  STR_SELECT_GAME_TO_LOAD: \"Kterou hru nahrát?\"\n  STR_SELECT_SAVE_POSITION: \"Do které pozice uložit?\"\n  STR_GAME_OPTIONS: \"HERNÍ VOLBY\"\n  STR_LOAD_GAME: \"NÁHRAT HRU\"\n  STR_SAVE_GAME: \"ULOŽIT HRU\"\n  STR_ABANDON_GAME: \"OPUSTIT HRU\"\n  STR_ABANDON_GAME_QUESTION: \"OPUSTIT HRU?\"\n  STR_QUIT: \"Ukončit\"\n  STR_SAVING_GAME: \"Ukládání hry\"\n  STR_LOADING_GAME: \"Nahravání hry\"\n  STR_NO_SAVED_GAME_PRESENT: \"Žádné uložené hry\"\n  STR_LOAD_UNSUCCESSFUL: \"Nahrání selhalo\"\n  STR_SAVE_UNSUCCESSFUL: \"Uložení selhalo\"\n  STR_LOAD_SUCCESSFUL: \"Hra byla nahrána\"\n  STR_SAVE_SUCCESSFUL: \"Hra byla uložena\"\n  STR_DELETE: \"SMAZAT\"\n  STR_DELETE_UNSUCCESSFUL: \"Smazání selhalo\"\n  STR_IS_IT_OK_TO_DELETE_THE_SAVED_GAME: \"Přepsat uloženou hru?\"\n  STR_ORIGINAL_XCOM: \"Původní X-Com\"\n  STR_LOADING: \"Nahrávání...\"\n  STR_DETAILS: \"PODROBNOSTI> {ALT}{0}\"\n  STR_NEW_BATTLE: \"Nová bitva\"\n  STR_OPTIONS: \"Možnosti\"\n  STR_RIGHT_CLICK_TO_DELETE: \"Smazat pravým klikem\"\n  STR_RESTORE_DEFAULTS: \"Obnovit výchozí\"\n  STR_CONTROLS: \"OVLÁDÁNÍ\"\n  STR_GENERAL: \"Hlavní\"\n  STR_GEOSCAPE: \"Glóbus\"\n  STR_BATTLESCAPE: \"Bojiště\"\n  STR_SCREENSHOT: \"Snímek obrazovky\"\n  STR_FPS_COUNTER: \"Počítadlo FPS\"\n  STR_ROTATE_LEFT: \"Otočit vlevo\"\n  STR_ROTATE_RIGHT: \"Otočit vpravo\"\n  STR_ROTATE_UP: \"Otočit nahoru\"\n  STR_ROTATE_DOWN: \"Otočit dolů\"\n  STR_ZOOM_IN: \"Přiblížit\"\n  STR_ZOOM_OUT: \"Oddálit\"\n  STR_TOGGLE_COUNTRY_DETAIL: \"Přepínač detailů země\"\n  STR_TOGGLE_RADAR_RANGES: \"Přepínač dosahů radaru\"\n  STR_SCROLL_LEFT: \"Posunout vlevo\"\n  STR_SCROLL_RIGHT: \"Posunout vpravo\"\n  STR_SCROLL_UP: \"Posunout nahoru\"\n  STR_SCROLL_DOWN: \"Posunout dolu\"\n  STR_UNIT_LEVEL_ABOVE: \"Přesunout jednotku o úroveň výš\"\n  STR_UNIT_LEVEL_BELOW: \"Přesunout jednotku o úroveň níž\"\n  STR_VIEW_LEVEL_ABOVE: \"Pohled o úroveň výš\"\n  STR_VIEW_LEVEL_BELOW: \"Pohled o úroveň níž\"\n  STR_CENTER_SELECTED_UNIT: \"Vycentrovat na vybranou jednotku\"\n  STR_PREVIOUS_UNIT: \"Vybrat předchozí jednotku\"\n  STR_NEXT_UNIT: \"Vybrat další jednotku\"\n  STR_DESELECT_UNIT: \"Zrušit výběr jednotky\"\n  STR_USE_LEFT_HAND: \"Použít předmět v levé ruce\"\n  STR_USE_RIGHT_HAND: \"Použít předmět v pravé ruce\"\n  STR_INVENTORY: \"Inventář\"\n  STR_MINIMAP: \"Minimapa\"\n  STR_MULTI_LEVEL_VIEW: \"Víceroúrovňový pohled\"\n  STR_END_TURN: \"Konec kola\"\n  STR_ABORT_MISSION: \"Zrušit misi\"\n  STR_UNIT_STATS: \"Statistika jednotky\"\n  STR_KNEEL: \"Kleknout\"\n  STR_RELOAD: \"Nabít\"\n  STR_TOGGLE_PERSONAL_LIGHTING: \"Zapnout osobní svítilnu\"\n  STR_DONT_RESERVE_TIME_UNITS: \"Nerezervovat čas\"\n  STR_RESERVE_TIME_UNITS_FOR_SNAP_SHOT: \"Rezervovat čas pro výstřel od boku\"\n  STR_RESERVE_TIME_UNITS_FOR_AIMED_SHOT: \"Rezervovat čas pro zamířený výstřel\"\n  STR_RESERVE_TIME_UNITS_FOR_AUTO_SHOT: \"Rezervovat čas pro výstřel automatem\"\n  STR_CENTER_ON_ENEMY_1: \"Vycentrovat na nepřítele 1\"\n  STR_CENTER_ON_ENEMY_2: \"Vycentrovat na nepřítele 2\"\n  STR_CENTER_ON_ENEMY_3: \"Vycentrovat na nepřítele 3\"\n  STR_CENTER_ON_ENEMY_4: \"Vycentrovat na nepřítele 4\"\n  STR_CENTER_ON_ENEMY_5: \"Vycentrovat na nepřítele 5\"\n  STR_CENTER_ON_ENEMY_6: \"Vycentrovat na nepřítele 6\"\n  STR_CENTER_ON_ENEMY_7: \"Vycentrovat na nepřítele 7\"\n  STR_CENTER_ON_ENEMY_8: \"Vycentrovat na nepřítele 8\"\n  STR_CENTER_ON_ENEMY_9: \"Vycentrovat na nepřítele 9\"\n  STR_CENTER_ON_ENEMY_10: \"Vycentrovat na nepřítele 10\"\n  STR_CREATE_INVENTORY_TEMPLATE: \"Vytvořit šablonu vybavení\"\n  STR_APPLY_INVENTORY_TEMPLATE: \"Použít šablonu vybavení\"\n  STR_CLEAR_INVENTORY: \"Zrušit inventář\"\n  STR_AUTO_EQUIP: \"Automaticky vybavit\"\n  STR_QUICK_SAVE: \"Rychlé uložení\"\n  STR_QUICK_LOAD: \"Rychlé načtení\"\n  STR_ADVANCED: \"DALŠÍ\"\n  STR_AGGRESSIVERETALIATION: \"Agresivní odplata\"\n  STR_AGGRESSIVERETALIATION_DESC: \"UFA se vždy pokusí najít vaše základny bez ohledu na jejich primární misi.\"\n  STR_STORAGELIMITSENFORCED: \"Omezení kapacity skladů pro získané předměty.\"\n  STR_STORAGELIMITSENFORCED_DESC: \"Omezuje počet živých cizáků a artefaktů ukládaných do cizácké cely a skladů\"\n  STR_CANSELLLIVEALIENS: \"Prodej živých cizáků\"\n  STR_CANSELLLIVEALIENS_DESC: \"Povolit prodej živých cizáků - doporučeno při nastavení omezení kapacity skladů.\"\n  STR_ALLOWBUILDINGQUEUE: \"Povolit stavební frontu\"\n  STR_ALLOWBUILDINGQUEUE_DESC: \"Nová zařízení mohou být umístěna vedle nedokončených.\"\n  STR_BATTLEAUTOEND: \"Automatické ukončení bitvy\"\n  STR_BATTLEAUTOEND_DESC: \"Automaticky ukončí bitvu ve chvíli, kdy je poslední živý cizák neutralizován.\"\n  STR_BATTLEINSTANTGRENADE: \"Okamžité granáty\"\n  STR_BATTLEINSTANTGRENADE_DESC: \"Granát vybuchne okamžite při dopadu, místo na konci kola, pokud byl načasován na 0 kol.\"\n  STR_BATTLEUFOEXTENDERACCURACY: \"UFO Extender přesnost\"\n  STR_BATTLEUFOEXTENDERACCURACY_DESC: \"Přesnost střelby se sníží po dosažení určité vzdálenosti, podle druhu střelby. Upravená přesnost bude zobrazena na kurzoru\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE: \"Vzdušné přesuny\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE_DESC: \"Umožní trvalé převedení letícího letadla na jinou základnu.\"\n  STR_CRAFTLAUNCHALWAYS: \"Vynucený start stroje\"\n  STR_CRAFTLAUNCHALWAYS_DESC: \"Plavidla mohou být vyslána na misi, přestože nejsou připravena, tedy bez dokončené údržby.\"\n  STR_CUSTOMINITIALBASE: \"Vlastní návrh startovní základny\"\n  STR_CUSTOMINITIALBASE_DESC: \"Umožní vlastní návrh první základny, místo použití předdefinovaného rozvržení. \"\n  STR_GLOBESEASONS: \"Realistické osvětlení glóbusu\"\n  STR_GLOBESEASONS_DESC: \"Používá realističtější projekci slunečního světla na Glóbus s ohledem na osový náklon Země.\"\n  STR_PLAYINTRO: \"Přehrávat intro.\"\n  STR_PLAYINTRO_DESC: \"Přehraje intro při spuštění hry.\"\n  STR_SHOWMORESTATSININVENTORYVIEW: \"Statistiky inventáře\"\n  STR_SHOWMORESTATSININVENTORYVIEW_DESC: \"Zobrazí v invetáři doplňkové informace o vybraném vojákovi.\"\n  STR_SNEAKYAI: \"Plíživá UI\"\n  STR_SNEAKYAI_DESC: \"UI se bude snažit vyhnout odhalení hráčem.\"\n  STR_STRAFE: \"Alternativní pohybové metody\"\n  STR_STRAFE_DESC: \"Při stisku CTRL umožní pohyb do stran, běhání a nezávislý pohyb věže tanku.\"\n  STR_BATTLEEXPLOSIONHEIGHT: \"Výška exploze\"\n  STR_BATTLEEXPLOSIONHEIGHT_DESC: \"Nastaví způsob šíření explozí do výšky.{NEWLINE}(Pouze v rovině: 0, Kulovitá: 3)\"\n  STR_AUTOSAVE: \"Automatické ukládání\"\n  STR_AUTOSAVE_DESC: \"Automaticky ukládá hru v zadaném intervalu. Nevztahuje se na mód Ironman.\"\n  STR_AUTOSAVE_FREQUENCY: \"Frekvence ukládání\"\n  STR_AUTOSAVE_FREQUENCY_DESC: \"Počet kol, po kterých bude hra automaticky uložena.\"\n  STR_ALLOWPSIONICCAPTURE: \"Povolit psionická zajmutí\"\n  STR_ALLOWPSIONICCAPTURE_DESC: \"Psionické ovládnutí zbývajících cizáků ukončí úspěšně misi. Ovládnutí cizáci jsou zajmuti živí.\"\n  STR_ANYTIMEPSITRAINING: \"Psionický trénink kdykoliv\"\n  STR_ANYTIMEPSITRAINING_DESC: \"Povoluje zařazení vojáků do psionického výcviku kdykoliv v měsíci. Mějte na paměti, že počáteční výcvik trvá 30 až 60 dní.\"\n  STR_SKIPNEXTTURNSCREEN: \"Přeskakovat oznámení nového kola\"\n  STR_SKIPNEXTTURNSCREEN_DESC: \"Oznámení o novém kole automaticky zmizí po krátké prodlevě.\"\n  STR_NOT_ENOUGH_SPACE: \"Nedostatek místa.\"\n  STR_WEAPONSELFDESTRUCTION: \"Sebedestrukce cizáckých zbraní (XCom 2012)\"\n  STR_WEAPONSELFDESTRUCTION_DESC: \"Cizacké zbraně se samy zničí je-li  jejich majitel zabit jako v XCOM 2012.\"\n  STR_RETAINCORPSES: \"Zachovat vyslechnuté cizáky\"\n  STR_RETAINCORPSES_DESC: \"Po \\\"vyzkoumání\\\" živých cizáků budou jejich těla přidána do skladů základny, jako v XCOM 2012\"\n  STR_SAVE_VOXEL_VIEW: \"Uložit snímek obrazovky z pohledu první osoby\"\n  STR_RESERVE_TIME_UNITS_FOR_KNEEL: \"Rezervovat časové jednotky pro zakleknutí\"\n  STR_EXPEND_ALL_TIME_UNITS: \"Spotřebovat všechny časové jednotky\"\n  STR_PSISTRENGTHEVAL: \"Ohodnocení psionické síly\"\n  STR_PSISTRENGTHEVAL_DESC: \"Vyhodnotí psionickou sílu všech vojáků poté, co bude proveden odpovídající výzkum.\"\n  STR_DISABLEAUTOEQUIP: \"Vypnout automatické vybavování\"\n  STR_DISABLEAUTOEQUIP_DESC: \"Vypnout automatické vybavování nových vojáků před bitvou\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT: \"Zlepšování Psionické síly\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT_DESC: \"Psionickou sílu vojáků lze vylepšit zkušenostmi a výcvikem.\"\n  STR_BATTLESMOOTHCAMERA: \"Plynulá kamera při sledování střely\"\n  STR_BATTLESMOOTHCAMERA_DESC: \"Kamera na bojišti bude plynule sledovat letící projektily.\"\n  STR_BATTLECONFIRMFIREMODE: \"Režim potvrzení štřelby\"\n  STR_BATTLECONFIRMFIREMODE_DESC: \"Pro potvrzení rozkazu ke střelbě vyžaduje druhý klik na stejné políčko.\"\n  STR_SELECT_BASE_1: \"Vybrat základnu 1\"\n  STR_SELECT_BASE_2: \"Vybrat základnu 2\"\n  STR_SELECT_BASE_3: \"Vybrat základnu 3\"\n  STR_SELECT_BASE_4: \"Vybrat základnu 4\"\n  STR_SELECT_BASE_5: \"Vybrat základnu 5\"\n  STR_SELECT_BASE_6: \"Vybrat základnu 6\"\n  STR_SELECT_BASE_7: \"Vybrat základnu 7\"\n  STR_SELECT_BASE_8: \"Vybrat základnu 8\"\n  STR_VIDEO: \"VIDEO\"\n  STR_AUDIO: \"ZVUK\"\n  STR_BATTLESCAPE_UC: \"BOJIŠTĚ\"\n  STR_MODS_UC: \"MÓDY\"\n  STR_MODS: \"Módy\"\n  STR_DISPLAY_RESOLUTION: \"Rozlišení obrazovky\"\n  STR_DISPLAY_RESOLUTION_DESC: \"Mění rozlišení monitoru. Zobrazení hry bude změněno tak, aby tomu odpovídalo. Šipky přepínají mezi podporovanými rozlišeními. Klikněte pro vložení vlastního rozlišení.\"\n  STR_ORIGINAL: \"Originální\"\n  STR_DISPLAY_MODE: \"Styl zobrazení\"\n  STR_WINDOWED: \"V okně\"\n  STR_FULLSCREEN: \"Celá obrazovka\"\n  STR_BORDERLESS: \"Bez okrajů\"\n  STR_DISPLAY_LANGUAGE: \"Jazyk\"\n  STR_DISPLAY_LANGUAGE_DESC: \"Mění jazyk herního textu.\"\n  STR_DISPLAY_FILTER: \"Filtr obrazovky\"\n  STR_DISPLAY_FILTER_DESC: \"Mění filtr aplikovaný na zobrazení hry.{NEWLINE}*vyžaduje hardwarovou akceleraci OpenGL.\"\n  STR_DISPLAY_OPTIONS: \"Nastavení zobrazení\"\n  STR_LETTERBOXED: \"Nejlepší poměr\"\n  STR_LETTERBOXED_DESC: \"Maximalizuje obraz tak, že poměr stran je zachován.\"\n  STR_RESIZABLE: \"Měnitelné\"\n  STR_LOCK_MOUSE: \"Zamknout myš\"\n  STR_LOCK_MOUSE_DESC: \"Zabrání kurzoru myši opustit okno hry. Ctrl+G pro přepnutí kdykoliv.\"\n  STR_FIXED_WINDOW_POSITION: \"Ukotvení pozice okna\"\n  STR_FIXED_WINDOW_POSITION_DESC: \"Nastaví pevné ukotvení okna\"\n  STR_DISPLAY_SET_WINDOW_POSITION: \"Nastavit kořenovou pozici pro nové okno\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_X: \"Levý okraj - nové X:\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_Y: \"Horní okraj - nové Y:\"\n  STR_MUSIC_VOLUME: \"Hlasitost hudby\"\n  STR_MUSIC_VOLUME_DESC: \"Mění hlasitost hudby na pozadí.\"\n  STR_SFX_VOLUME: \"Hlasitost zvuku\"\n  STR_SFX_VOLUME_DESC: \"Mění hlasitost zvukových efektů.\"\n  STR_UI_VOLUME: \"Hlasitost UI\"\n  STR_UI_VOLUME_DESC: \"Mění hlasitost pípání rozhraní.\"\n  STR_SCROLL_SPEED: \"Rychlost posunu\"\n  STR_SCROLL_SPEED_GEO_DESC: \"Mění rychlost posunu glóbusu.\"\n  STR_SCROLL_SPEED_BATTLE_DESC: \"Mění rychlost posunu mapy.\"\n  STR_DOGFIGHT_SPEED: \"Rychlost letec. soubojů\"\n  STR_DOGFIGHT_SPEED_DESC: \"Změní rychlost průběhu vzdušných soubojů. Nižší rychlosti mohou zlepšit výkon na pomalých zařízeních.\"\n  STR_CLOCK_SPEED: \"Rychlost hodin\"\n  STR_CLOCK_SPEED_DESC: \"Změní rychlost času Glóbusu. Nižší rychlosti mohou zlepšit výkon pomalých zařízení.\"\n  STR_GLOBE_DETAILS: \"Detaily glóbusu\"\n  STR_GLOBE_COUNTRIES: \"Státy\"\n  STR_GLOBE_COUNTRIES_DESC: \"Zobrazí financující státy na glóbusu.\"\n  STR_GLOBE_RADARS: \"Radary\"\n  STR_GLOBE_RADARS_DESC: \"Zobrazí na glóbusu dosah radarů v základnách.\"\n  STR_GLOBE_FLIGHT_PATHS: \"Letové dráhy\"\n  STR_GLOBE_FLIGHT_PATHS_DESC: \"Zobrazí na glóbusu letové dráhy letounů.\"\n  STR_CONTROLS_DESC: \"Pro změnu zkratky na ni klikněte a zadejte její novou hodnotu.{NEWLINE}Pravým tlačítkem myši zkratku deaktivujete.\"\n  STR_BASE_GAME: \"Základní hra\"\n  STR_MODS_TOOLTIP: \"Verze {0} od {1}.{NEWLINE}{2}\"\n  STR_EDGE_SCROLL: \"Posuv najetím k okraji\"\n  STR_EDGE_SCROLL_DESC: \"Spoušť: Posune mapu, když je na okraji obrazovky stisknuto levé tlačítko myši.{NEWLINE}Auto: Posune mapu, když je kurzor nad okrajem obrazovky.\"\n  STR_TRIGGER_SCROLL: \"Spoušť\"\n  STR_AUTO_SCROLL: \"Auto\"\n  STR_DRAG_SCROLL: \"Posuv táhnutím\"\n  STR_DRAG_SCROLL_DESC: \"Je-li stisknuto specifikované tlačitko myši a kurzorem je taženo, posouvá mapu.\"\n  STR_LEFT_MOUSE_BUTTON: \"Levé tlačítko\"\n  STR_MIDDLE_MOUSE_BUTTON: \"Prostřední tlačítko\"\n  STR_RIGHT_MOUSE_BUTTON: \"Pravé tlačítko\"\n  STR_FIRE_SPEED: \"Rychlost střelby\"\n  STR_FIRE_SPEED_DESC: \"Mění rychlost projektilů vystřelených ze zbraní.\"\n  STR_PLAYER_MOVEMENT_SPEED: \"Rychlost pohybu hráče\"\n  STR_PLAYER_MOVEMENT_SPEED_DESC: \"Mění rychlost pohybu hráčem ovládaných jednotek.\"\n  STR_COMPUTER_MOVEMENT_SPEED: \"Rychlost pohybu AI\"\n  STR_COMPUTER_MOVEMENT_SPEED_DESC: \"Mění rychlost pohybu počítačem ovládaných jednotek.\"\n  STR_PATH_PREVIEW: \"Náhled cesty\"\n  STR_PATH_ARROWS: \"Trasa pohybu\"\n  STR_PATH_ARROWS_DESC: \"Kliknutí zobrazí cestu, kterou se vaše jednotka bude přesouvat do cíle. Barva naznačuje možné úkony: Zelená - možný pohyb a střelba; Žlutá - možný pohyb; Červená - pohyb není možný.\"\n  STR_PATH_TIME_UNIT_COST: \"Časové jednotky\"\n  STR_PATH_TIME_UNIT_COST_DESC: \"Kliknutí zobrazí zbylý čas vaší jednotky po přesunu do cíle.\"\n  STR_USER_INTERFACE_OPTIONS: \"Volby UI\"\n  STR_TOOLTIPS: \"Popisky tlačítek\"\n  STR_TOOLTIPS_DESC: \"Zobrazí popisky k tlačítkům v zobrazení bojiště.\"\n  STR_DEATH_NOTIFICATIONS: \"Zprávy o úmrtí\"\n  STR_DEATH_NOTIFICATIONS_DESC: \"Zobrazí zprávu o úmrtí pokaždé když jeden z vašich vojáků zahyne.\"\n  STR_SHOW_FUNDS: \"Ukázat finance\"\n  STR_SHOW_FUNDS_DESC: \"Zobrazí současné finance vedle hodin Glóbusu.\"\n  STR_MISSION_GENERATOR: \"GENERÁTOR MISÍ\"\n  STR_MAP_OPTIONS: \"VOLBY MAPY\"\n  STR_ALIEN_OPTIONS: \"VOLBY MIMOZEMŠŤANŮ\"\n  STR_MAP_TERRAIN: \"Terén\"\n  STR_MAP_DARKNESS: \"Tma\"\n  STR_MAP_DEPTH: \"Hloubka\"\n  STR_DIFFICULTY: \"Obtížnost\"\n  STR_ALIEN_RACE: \"Rasa\"\n  STR_ALIEN_TECH_LEVEL: \"Technická úroveň\"\n  STR_RANDOMIZE: \"Generovat náhodně\"\n  STR_OXCE_REQUIRED_QUESTION: \"Tento mod pro správnou funkci vyžaduje OpenXcom {0}. Aktivovat tento mod?\"\n  STR_RESTORE_DEFAULTS_QUESTION: \"Opravdu chcete obnovit standardní nastavení?\"\n  STR_DISPLAY_OPTIONS_CONFIRM: \"Chcete zachovat současné nastavení zobrazení?\"\n  STR_DISPLAY_OPTIONS_REVERT: \"Změny se vrátí zpět za 0:{0}\"\n  STR_MISSING_CONTENT_PROMPT: \"VAROVÁNÍ:{SMALLLINE}Tato uložená pozice pracuje s mody, které nejsou dostupné. Chybějící obsah bude odstraněn a načítání nemusí být úspěšné.{NEWLINE}Pokračovat?\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT: \"Ukládání dopředu odjištěných granátů\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT_DESC: \"Ukládá granáty odjištěné v inventáři před bitvou v obrazovce výbavy vojáků.\"\n  STR_NEWSEEDONLOAD: \"Podvádění s ukládáním hry\"\n  STR_NEWSEEDONLOAD_DESC: \"Nahrání hry resetuje náhodná čísla, takže zahrání stejné akce může vést k různým výsledkům. Neplatí pro mód Ironman.\"\n  STR_CHANGEVALUEBYMOUSEWHEEL: \"Změna hodnot pomocí kolečka myši\"\n  STR_CHANGEVALUEBYMOUSEWHEEL_DESC: \"Umožní používat kolečko myši ke zvyšování/snižování hodnot.\"\n  STR_BATTLEHAIRBLEACH: \"Rozšířený vzhled vojáků\"\n  STR_BATTLEHAIRBLEACH_DESC: \"Mění vzhled vojáků tak, aby se shodoval s jejich vzhledem v menu inventáře.\"\n  STR_DRAGSCROLLINVERT: \"Invertovat posouvání tahem\"\n  STR_DRAGSCROLLINVERT_DESC: \"Při zapnutí této možnosti tažením myši přesouváte obrazovku v opačném směru\"\n  STR_BATTLESCAPE_SCALE: \"Měřítko bojiště\"\n  STR_BATTLESCAPE_SCALE_DESC: \"Škáluje zobrazení bojiště na zadané rozlišení. Originál = 320x200px, celá obrazovka plně využije nastavené rozlišení.\"\n  STR_GEOSCAPE_SCALE: \"Měřítko glóbusu\"\n  STR_GEOSCAPESCALE_SCALE_DESC: \"Škáluje zobrazení glóbusu na zadané rozlišení. Originál = 320x200 bodů, celá obrazovka plně využije nastavené rozlišení.\"\n  STR_1_5X: \"1.5x originál\"\n  STR_2X: \"2x originál\"\n  STR_THIRD_DISPLAY: \"1/3 obrazovky\"\n  STR_HALF_DISPLAY: \"1/2 obrazovky\"\n  STR_FULL_DISPLAY: \"Celá obrazovka\"\n  STR_FPS_LIMIT: \"Limit FPS\"\n  STR_FPS_LIMIT_DESC: \"Omezuje počet obnovení obrazovky za vteřinu, 0 znamená bez limitu. Pokud je povoleno OpenGL renderování, hra místo něho použije Vsync.\"\n  STR_FPS_INACTIVE_LIMIT: \"Omezení FPS na pozadí\"\n  STR_FPS_INACTIVE_LIMIT_DESC: \"Omezí obnovovací frekvenci, pokud je OpenXcom na pozadí.\"\n  STR_NOALIENPANICMESSAGES: \"Skrýt zprávy o panice cizáků.\"\n  STR_NOALIENPANICMESSAGES_DESC: \"Nezobrazovat zprávy o panikaření cizáků pokud jsou pro hráče neviditelní.\"\n  STR_ALIENBLEEDING: \"Krvácení cizáků\"\n  STR_ALIENBLEEDING_DESC: \"Umožňuje způsobit smrtelná zranění většině mimozemšťanům.\"\n  STR_FIELDPROMOTIONS: \"Polní povyšování\"\n  STR_FIELDPROMOTIONS_DESC: \"Pouze vojáci přítomní na misi mohou být povýšeni.\"\n  STR_MEETINGPOINT: \"Předvídat trajektorii UFO\"\n  STR_MEETINGPOINT_DESC: \"Stroje přilétají k bodu setkání s UFO na základě jeho současné trajektorie.\"\n  STR_IRONMAN: \"IRONMAN\"\n  STR_IRONMAN_DESC: \"Žádné manuální ukládání\"\n  STR_SAVE_AND_ABANDON_GAME: \"ULOŽIT A OPUSTIT HRU\"\n  STR_MOD_UNSUCCESSFUL: \"Načtení modu selhalo\"\n  STR_NEW_SAVED_GAME_SLOT: \"<Poslední uložená hra>\"\n  STR_AUTO_SAVE_GEOSCAPE_SLOT: \"<AUTO GLOBUS>\"\n  STR_AUTO_SAVE_BATTLESCAPE_SLOT: \"<AUTO BITEVNÍ POLE>\"\n  STR_QUICK_SAVE_SLOT: \"<RYCHLÉ ULOŽENÍ>\"\n  STR_DISPLAY_MODE_DESC: \"Změnit zobrazení hry.\"\n  STR_PREFERRED_MUSIC_FORMAT: \"Formát hudby\"\n  STR_PREFERRED_MUSIC_FORMAT_DESC: \"Vyberte upřednostňovaný hudební formát, pokud jich je k dispozici více. {NEWLINE}Poznámka: MIDI přehrávač na Windows nemusí fungovat.\"\n  STR_PREFERRED_SFX_FORMAT: \"SFX \"\n  STR_PREFERRED_SFX_FORMAT_DESC: \"Vyber preferované zkuvoké efekty, když jich je víc k dispozici.\"\n  STR_PREFERRED_VIDEO_FORMAT: \"Formát zobrazení\"\n  STR_PREFERRED_VIDEO_FORMAT_DESC: \"Určuje upřednostňovaný formát zobrazení, je li jich víc k dispozici. \"\n  STR_PREFERRED_VIDEO_ANIMATION: \"Animace\"\n  STR_PREFERRED_VIDEO_SLIDESHOW: \"Slideshow\"\n  STR_PREFERRED_FORMAT_AUTO: \"Auto\"\n  STR_CURRENT_FORMAT: \"Aktuální: {0}\"\n  STR_SOUND_OPTIONS: \"Zvukové možnosti\"\n  STR_BACKGROUND_MUTE: \"Ztlumení pozadí\"\n  STR_BACKGROUND_MUTE_DESC: \"Ztlumí veškerý zvuk, pokud není okno hry aktivní.\"\n  STR_FORCE_FIRE: \"Přehlížet překázky v linii střelby\"\n  STR_FORCE_FIRE_DESC: \"Dovoluje donutit vojáky střílet podržením CTRL, nezávisle na překážkách v linii střelby.\"\n  STR_NO_AUDIO_HARDWARE_DETECTED: \"Zvuková karta nenalezena.\"\n  STR_MOUSEWHEEL_SPEED: \"Rychlost posouvání kolečkem myši\"\n  STR_MOUSEWHEEL_SPEED_DESC: \"Nastavuje počet řádků o který se seznam posune při jednom otočení kolečkem myši.\"\n  STR_DISABLED: \"Vypnuto\"\n  STR_MAXIMIZE_INFO_SCREENS: \"Maximalizovat informační obrazovky\"\n  STR_MAXIMIZE_INFO_SCREENS_DESC: \"Inventář a další obazovky budou bez ohledu na nastavení škálování zobrazeny přes celou obrazovku\"\n  STR_DIARY: \"DENÍK\"\n  STR_KILLED: \"ZABIT\"\n  STR_STUNNED: \"OMRÁČEN\"\n  STR_PANICKED: \"ZPANIKAŘENO\"\n  STR_MINDCONTROLLED: \"OVLÁDNUT\"\n  STR_REGION_UNKNOWN: \"Neveřejný\"\n  STR_WEAPON_UNKNOWN: \"Improvizace\"\n  STR_UNKNOWN: \"Neznámo\"\n  STR_VICTORY: \"Vítězství\"\n  STR_DEFEAT: \"Porážka\"\n  STR_NO_RECORD: \"Žádný záznam\"\n  STR_HUMAN: \"Člověk\"\n  STR_FRIENDLY: \"Přítel\"\n  STR_HOSTILE: \"Nepřátelský\"\n  STR_NEUTRAL: \"Neutrální\"\n  STR_RATING_UC: \"HODNOCENÍ\"\n  STR_LOCATION: \"LOKACE> {ALT}{0}\"\n  STR_DAYLIGHT_TYPE: \"ČAS> {ALT}{0}\"\n  STR_RACE_TYPE: \"RASA> {ALT}{0}\"\n  STR_DAY: \"Den\"\n  STR_NIGHT: \"Noc\"\n  STR_DAYS_WOUNDED: \"ZRANĚN DNÍ> {ALT}{0}\"\n  STR_COMBAT: \"BOJ\"\n  STR_PERFORMANCE: \"VÝKONNOST\"\n  STR_NEUTRALIZATIONS_BY_RACE: \"ZABITÍ DLE RASY\"\n  STR_NEUTRALIZATIONS_BY_RANK: \"ZABITÍ DLE HODNOSTI\"\n  STR_NEUTRALIZATIONS_BY_WEAPON: \"ZABITÍ DLE ZBRANĚ\"\n  STR_MISSIONS_BY_LOCATION: \"MISE DLE LOKACE\"\n  STR_MISSIONS_BY_TYPE: \"MISE DLE TYPU\"\n  STR_MISSIONS_BY_UFO: \"MISE DLE UFA\"\n  STR_SCORE_VALUE: \"SKÓRE> {ALT}{0}\"\n  STR_WINS: \"VÍTĚZSTVÍ> {ALT}{0}\"\n  STR_STUNS: \"OMRÁČENÍ> {ALT}{0}\"\n  STR_PANICKS: \"ZPANIKAŘENÍ> {ALT}{0}\"\n  STR_MINDCONTROLS: \"OVLÁDNUTÍ> {ALT}{0}\"\n  STR_AWARDS: \"OCENĚNÍ\"\n  STR_COMMENDATIONS_UC: \"VYZNAMENÁNÍ\"\n  STR_COMMENDATIONS: \"Vyznamenání\"\n  STR_MEDALS: \"MEDAILE\"\n  STR_LOST_IN_SERVICE: \"ZTRACENI BĚHEM SLUŽBY\"\n  STR_MEDAL_NAME: \"Název medile\"\n  STR_MEDAL_AWARD_LEVEL: \"Úroveň ocenění\"\n  STR_MEDAL_DECOR_LEVEL: \"Úroveň vyznamenání\"\n  STR_AWARD_0: \"První ocenění\"\n  STR_AWARD_1: \"Druhé ocenění\"\n  STR_AWARD_2: \"Třetí ocenění\"\n  STR_AWARD_3: \"Čtvrté ocenění\"\n  STR_AWARD_4: \"Páte ocenění\"\n  STR_AWARD_5: \"Šesté ocenění\"\n  STR_AWARD_6: \"Sedmé ocenění\"\n  STR_AWARD_7: \"Osmé ocenění\"\n  STR_AWARD_8: \"Deváté ocenění\"\n  STR_AWARD_9: \"Desáté ocenění\"\n  STR_AWARD_DECOR_0: \"Žádné\"\n  STR_AWARD_DECOR_1: \"První bronzový odznak\"\n  STR_AWARD_DECOR_2: \"Druhý bronzový odznak\"\n  STR_AWARD_DECOR_3: \"Třetí bronzový odznak\"\n  STR_AWARD_DECOR_4: \"První stříbrný odznak\"\n  STR_AWARD_DECOR_5: \"Druhý stříbrný odznak\"\n  STR_AWARD_DECOR_6: \"Třetí stříbrný odznak\"\n  STR_AWARD_DECOR_7: \"První zlatý odznak\"\n  STR_AWARD_DECOR_8: \"Druhý zlatý odznak\"\n  STR_AWARD_DECOR_9: \"Třetí zlatý odznak\"\n  STR_KILLED_IN_ACTION_MALE: \"ZABIT V AKCI\"\n  STR_KILLED_IN_ACTION_FEMALE: \"ZABITA V AKCI\"\n  STR_MISSING_IN_ACTION_MALE: \"ZTRACEN V AKCI\"\n  STR_MISSING_IN_ACTION_FEMALE: \"ZTRACENA V AKCI\"\n  STR_AVERAGE_MONTHLY_RATING: \"Průměrné měsíční hodnocení\"\n  STR_TOTAL_INCOME: \"Celkový příjem\"\n  STR_TOTAL_EXPENDITURE: \"Celkové výdaje\"\n  STR_MISSIONS_WON: \"Misí splněno\"\n  STR_MISSIONS_LOST: \"Nezdařených misí\"\n  STR_NIGHT_MISSIONS: \"Nočních misí\"\n  STR_BEST_RATING: \"Nejlepší hodnocení mise\"\n  STR_WORST_RATING: \"Nejhorší hodnocení mise\"\n  STR_ALIEN_KILLS: \"Cizáků zabito\"\n  STR_ALIEN_CAPTURES: \"Cizáků polapeno\"\n  STR_FRIENDLY_KILLS: \"Incidentů střelby do vlastních řad\"\n  STR_AVERAGE_ACCURACY: \"Průměrná přesnost\"\n  STR_WEAPON_MOST_KILLS: \"Nejefektivnější zbraň\"\n  STR_ALIEN_MOST_KILLS: \"Nejvíce smrtonostný cizák\"\n  STR_LONGEST_SERVICE: \"Nejdelší služba v měsících\"\n  STR_TOTAL_DAYS_WOUNDED: \"Dny pracovní neschopnosti\"\n  STR_COUNTRIES_LOST: \"Infiltrováno zemí\"\n  STR_TOTAL_TERROR_SITES: \"Teroristických útoků\"\n  STR_TOTAL_BASES: \"Základen postaveno\"\n  STR_TOTAL_CRAFT: \"Vlastněno dopravních prostředků\"\n  STR_TOTAL_SCIENTISTS: \"Vědců najmuto\"\n  STR_TOTAL_ENGINEERS: \"Inženýrů najmuto\"\n  STR_TOTAL_RESEARCH: \"Výzkum dokončen\"\n  STR_DIARY_ACCURACY: \"PŘESNOST> {ALT}{0}%\"\n  STR_STATISTICS: \"Statistiky\"\n  STR_STATS: \"STATY\"\n  STR_TIME_UNITS_ABBREVIATION: \"ČJ\"\n  STR_STAMINA_ABBREVIATION: \"ODL\"\n  STR_HEALTH_ABBREVIATION: \"ŽVT\"\n  STR_BRAVERY_ABBREVIATION: \"ODV\"\n  STR_REACTIONS_ABBREVIATION: \"REA\"\n  STR_FIRING_ACCURACY_ABBREVIATION: \"MÍŘ\"\n  STR_THROWING_ACCURACY_ABBREVIATION: \"HOD\"\n  STR_STRENGTH_ABBREVIATION: \"SIL\"\n  STR_MELEE_ACCURACY_ABBREVIATION: \"ZBL\"\n  STR_FOLDERS: \"SLOŽKY\"\n  STR_DATA_FOLDER: \"Datová složka (originální zdrojová data)\"\n  STR_USER_FOLDER: \"Uživatelská složka (módy, openxcom.log)\"\n  STR_SAVE_FOLDER: \"Ukládací složka (uložené hry, screenshoty)\"\n  STR_CONFIG_FOLDER: \"Složka s konfigurací (options.cfg)\"\n  STR_DATA_FOLDER_DESC_1: \"Tady OpenXcom hledá originální soubory hry (UFO a/nebo TFTD)\"\n  STR_DATA_FOLDER_DESC_2: \"Vlastní soubory OpenXcom se nachází ve složce 'common'. Zabudované módy OpenXcom se nachází ve složce 'standard'.\"\n  STR_USER_FOLDER_DESC: \"Zde se nachází logovací soubor ('openxcom.log'). Také sem patří všechny přídavné módy (do složky 'mods')\"\n  STR_SAVE_FOLDER_DESC: \"Vaše uložené hry se nachází zde. K tomu sem patří také nastavení generátoru misí ('battle.cfg').\"\n  STR_CONFIG_FOLDER_DESC: \"Zde je uloženo nastavení OpenXcom ('options.cfg'). Standardně stejné jako Uživatelská složka.\"\n"
  },
  {
    "path": "bin/common/Language/da.yml",
    "content": "da:\n  STR_OPENXCOM: \"OpenXcom\"\n  STR_NEW_GAME: \"Nyt spil\"\n  STR_LOAD_SAVED_GAME: \"Hent spil\"\n  STR_SELECT_DIFFICULTY_LEVEL: \"Vælg sværhedsgrad\"\n  STR_1_BEGINNER: \"1> Begynder\"\n  STR_2_EXPERIENCED: \"2> Rutineret\"\n  STR_3_VETERAN: \"3> Veteran\"\n  STR_4_GENIUS: \"4> Geni\"\n  STR_5_SUPERHUMAN: \"5> Overmenneske\"\n  STR_TIME: \"Tid\"\n  STR_DATE: \"Dato\"\n  STR_SELECT_GAME_TO_LOAD: \"Vælg spil der skal hentes\"\n  STR_SELECT_SAVE_POSITION: \"Vælg hvor spillet skal gemmes\"\n  STR_GAME_OPTIONS: \"SPILINDSTILLINGER\"\n  STR_LOAD_GAME: \"HENT SPIL\"\n  STR_SAVE_GAME: \"GEM SPIL\"\n  STR_ABANDON_GAME: \"FORLAD SPIL\"\n  STR_ABANDON_GAME_QUESTION: \"FORLAD SPIL?\"\n  STR_QUIT: \"Forlad spil\"\n  STR_SAVING_GAME: \"Gemmer spil\"\n  STR_LOADING_GAME: \"Henter spil\"\n  STR_NO_SAVED_GAME_PRESENT: \"Der findes ingen gemte spil\"\n  STR_LOAD_UNSUCCESSFUL: \"Indlæsning mislykkedes\"\n  STR_SAVE_UNSUCCESSFUL: \"Kunne ikke gemme\"\n  STR_LOAD_SUCCESSFUL: \"Indlæste\"\n  STR_SAVE_SUCCESSFUL: \"Gemte\"\n  STR_DELETE: \"SLET\"\n  STR_DELETE_UNSUCCESSFUL: \"Kunne ikke slette\"\n  STR_IS_IT_OK_TO_DELETE_THE_SAVED_GAME: \"Er du sikker på, at du ønsker at slette det gemt spil?\"\n  STR_ORIGINAL_XCOM: \"Original X-Com\"\n  STR_LOADING: \"Henter ...\"\n  STR_DETAILS: \"DETALJER> {ALT}{0}\"\n  STR_NEW_BATTLE: \"Ny kamp\"\n  STR_OPTIONS: \"Indstillinger\"\n  STR_RIGHT_CLICK_TO_DELETE: \"Højreklik for at slette.\"\n  STR_RESTORE_DEFAULTS: \"Gendan standarder\"\n  STR_CONTROLS: \"STYRING\"\n  STR_GENERAL: \"Generel\"\n  STR_GEOSCAPE: \"Landkort\"\n  STR_BATTLESCAPE: \"Kampscene\"\n  STR_SCREENSHOT: \"Skærmbillede\"\n  STR_FPS_COUNTER: \"FPS-tæller\"\n  STR_ROTATE_LEFT: \"Roter til venstre\"\n  STR_ROTATE_RIGHT: \"Roter til højre\"\n  STR_ROTATE_UP: \"Roter op\"\n  STR_ROTATE_DOWN: \"Roter ned\"\n  STR_ZOOM_IN: \"Zoom ind\"\n  STR_ZOOM_OUT: \"Zoom ud\"\n  STR_TOGGLE_COUNTRY_DETAIL: \"Slå landegrænser til/fra\"\n  STR_TOGGLE_RADAR_RANGES: \"Slå radar til/fra\"\n  STR_SCROLL_LEFT: \"Rul til venstre\"\n  STR_SCROLL_RIGHT: \"Rul til højre\"\n  STR_SCROLL_UP: \"Rul op\"\n  STR_SCROLL_DOWN: \"Rul ned\"\n  STR_UNIT_LEVEL_ABOVE: \"Flyt enhed til højere niveau\"\n  STR_UNIT_LEVEL_BELOW: \"Flyt enhed til lavere niveau\"\n  STR_VIEW_LEVEL_ABOVE: \"Se højere niveau\"\n  STR_VIEW_LEVEL_BELOW: \"Se lavere niveau\"\n  STR_CENTER_SELECTED_UNIT: \"Centrer på valgt soldat\"\n  STR_PREVIOUS_UNIT: \"Forrige soldat\"\n  STR_NEXT_UNIT: \"Næste soldat\"\n  STR_DESELECT_UNIT: \"Vælg ikke soldat igen\"\n  STR_USE_LEFT_HAND: \"Brug venstre hånds udstyr\"\n  STR_USE_RIGHT_HAND: \"Brug højre hånds udstyr\"\n  STR_INVENTORY: \"Inventar\"\n  STR_MINIMAP: \"Minikort\"\n  STR_MULTI_LEVEL_VIEW: \"Visning af flere niveauer\"\n  STR_END_TURN: \"Afslut runde\"\n  STR_ABORT_MISSION: \"Afbryd mission\"\n  STR_UNIT_STATS: \"Soldatinformation\"\n  STR_KNEEL: \"Knæl\"\n  STR_RELOAD: \"Lad\"\n  STR_TOGGLE_PERSONAL_LIGHTING: \"Slå lygte til/fra\"\n  STR_DONT_RESERVE_TIME_UNITS: \"Reserver Ikke TE\"\n  STR_RESERVE_TIME_UNITS_FOR_SNAP_SHOT: \"Reserver TE til hurtigt skud\"\n  STR_RESERVE_TIME_UNITS_FOR_AIMED_SHOT: \"Reserver TE til sigtet skud\"\n  STR_RESERVE_TIME_UNITS_FOR_AUTO_SHOT: \"Reserver TE til autoskud\"\n  STR_CENTER_ON_ENEMY_1: \"Centrer på fjende 1\"\n  STR_CENTER_ON_ENEMY_2: \"Centrer på fjende 2\"\n  STR_CENTER_ON_ENEMY_3: \"Centrer på fjende 3\"\n  STR_CENTER_ON_ENEMY_4: \"Centrer på fjende 4\"\n  STR_CENTER_ON_ENEMY_5: \"Centrer på fjende 5\"\n  STR_CENTER_ON_ENEMY_6: \"Centrer på fjende 6\"\n  STR_CENTER_ON_ENEMY_7: \"Centrer på fjende 7\"\n  STR_CENTER_ON_ENEMY_8: \"Centrer på fjende 8\"\n  STR_CENTER_ON_ENEMY_9: \"Centrer på fjende 9\"\n  STR_CENTER_ON_ENEMY_10: \"Centrer på fjende 10\"\n  STR_CREATE_INVENTORY_TEMPLATE: \"Opret udstyrsskabelon\"\n  STR_APPLY_INVENTORY_TEMPLATE: \"Anvend udstyrsskabelon\"\n  STR_CLEAR_INVENTORY: \"Ryd udstyr\"\n  STR_AUTO_EQUIP: \"Aktiver automatisk udrustning\"\n  STR_QUICK_SAVE: \"Gem hurtigt\"\n  STR_QUICK_LOAD: \"Indlæs hurtigt\"\n  STR_ADVANCED: \"AVANCERET\"\n  STR_AGGRESSIVERETALIATION: \"Aggressiv hævnaktion\"\n  STR_AGGRESSIVERETALIATION_DESC: \"Ufoer vil altid forsøge at opspore dine baser, uanset hvilken mission de er ved at udføre.\"\n  STR_STORAGELIMITSENFORCED: \"Lagerbegrænsninger for indsamlet udstyr\"\n  STR_STORAGELIMITSENFORCED_DESC: \"Kræver opbevaringsrum for rumvæsener og generelle lagerbegrænsninger for levende rumvæsener og artefakter indsamlet under missioner.\"\n  STR_CANSELLLIVEALIENS: \"Salg af levende rumvæsen\"\n  STR_CANSELLLIVEALIENS_DESC: \"Giver mulighed for at sælge levende rumvæsener, anbefalet når der bruges lagerbegrænsninger.\"\n  STR_ALLOWBUILDINGQUEUE: \"Tillad byggekø\"\n  STR_ALLOWBUILDINGQUEUE_DESC: \"Nye faciliteter kan placeres efter ufærdige.\"\n  STR_BATTLEAUTOEND: \"Afslut automatisk kampen\"\n  STR_BATTLEAUTOEND_DESC: \"Kampe afsluttes automatisk når den sidste levende fjende er neutraliseret.\"\n  STR_BATTLEINSTANTGRENADE: \"Øjeblikkelig granateksplosion\"\n  STR_BATTLEINSTANTGRENADE_DESC: \"Granater sat til at gå af efter 0 runder vil eksplodere lige når de lander i stedet for i slutningen af runden.\"\n  STR_BATTLEUFOEXTENDERACCURACY: \"Ufo-udviders præcision\"\n  STR_BATTLEUFOEXTENDERACCURACY_DESC: \"Præcisionen for skudafvikling efter en bestemt afstand, jævnfør skudtype. Justeret præcision vil blive vist på markøren.\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE: \"Luftbårne overførsler\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE_DESC: \"Fartøj i luften kan overføres.\"\n  STR_CRAFTLAUNCHALWAYS: \"Tving fartøj til start\"\n  STR_CRAFTLAUNCHALWAYS_DESC: \"Fartøjer kan startes selv om de ikke er klar, ignorerer behovet for vedligeholdelse.\"\n  STR_CUSTOMINITIALBASE: \"Tilpasset opstartsbase\"\n  STR_CUSTOMINITIALBASE_DESC: \"Når du starter et spil, så kan du manuelt placere dine startfaciliteter i stedet for at bruge standardlayouttet.\"\n  STR_GLOBESEASONS: \"Realistisk lys på jordkloden\"\n  STR_GLOBESEASONS_DESC: \"Brug mere realistisk projektin af sollys på landkortet jævnfør jordens drejning i forhold til solen.\"\n  STR_PLAYINTRO: \"Afspil introduktion\"\n  STR_PLAYINTRO_DESC: \"Vis biografintroen.\"\n  STR_SHOWMORESTATSININVENTORYVIEW: \"Udstyrsliste\"\n  STR_SHOWMORESTATSININVENTORYVIEW_DESC: \"Vis ekstra information om den valgte soldat i udstyrsskærmen.\"\n  STR_SNEAKYAI: \"Snu computerspiller\"\n  STR_SNEAKYAI_DESC: \"Computerspilleren undgår at vise sig for spilleren når det er muligt.\"\n  STR_STRAFE: \"Alternative bevægelsesmetoder\"\n  STR_STRAFE_DESC: \"Aktiverer sideløb, løb og uafhængig bevægelse af kampvognstårn når CTRL holdes nede.\"\n  STR_BATTLEEXPLOSIONHEIGHT: \"Eksplosionshøjde\"\n  STR_BATTLEEXPLOSIONHEIGHT_DESC: \"Ændr hvor højt eksplosioner kan sprede sig.{NEWLINE}(Flad: 0, runde: 3)\"\n  STR_AUTOSAVE: \"Gem automatisk\"\n  STR_AUTOSAVE_DESC: \"Gem automatisk spillet ved angivne intervaller. Anvendes ikke på niveauet jernmand.\"\n  STR_AUTOSAVE_FREQUENCY: \"Frekvens for gem automatisk\"\n  STR_AUTOSAVE_FREQUENCY_DESC: \"Antallet af runder hvorefter spillet automatisk bliver gemt.\"\n  STR_ALLOWPSIONICCAPTURE: \"Tillad psi-sejr\"\n  STR_ALLOWPSIONICCAPTURE_DESC: \"Sindelagskontrol af alle tilbageværende rumvæsener medfører sejr, da de tæller som levende fanger.\"\n  STR_ANYTIMEPSITRAINING: \"Psi-træning på alle tidspunkter\"\n  STR_ANYTIMEPSITRAINING_DESC: \"Tillader at soldater kan få psi-træning på alle tidspunkter af måneden. Husk, den indledende træning tager fra 30 til 60 dage.\"\n  STR_SKIPNEXTTURNSCREEN: \"Udelad »Næste runde«-skærmen\"\n  STR_SKIPNEXTTURNSCREEN_DESC: \"»Næste runde«-skærm under kamp fortsættes automatisk efter en kort forsinkelse.\"\n  STR_NOT_ENOUGH_SPACE: \"Ikke nok plads!\"\n  STR_WEAPONSELFDESTRUCTION: \"Selvdestruktion af rumvæsenvåben\"\n  STR_WEAPONSELFDESTRUCTION_DESC: \"Våben båret af rumvæsener vil blive destrueret hvis ejeren dræbes, ligesom i XCOM 2012.\"\n  STR_RETAINCORPSES: \"Behold forhørte rumvæsener\"\n  STR_RETAINCORPSES_DESC: \"Efter »forskning« af levende rumvæsener vil kroppen blive tilføjet til basens lager, ligesom i XCOM 2012.\"\n  STR_SAVE_VOXEL_VIEW: \"Gem første persons skærmbillede\"\n  STR_RESERVE_TIME_UNITS_FOR_KNEEL: \"Reserver TE'er til at knæle\"\n  STR_EXPEND_ALL_TIME_UNITS: \"Brug alle tilbageværende tidsenheder\"\n  STR_PSISTRENGTHEVAL: \"Evaluering af psi-styrke\"\n  STR_PSISTRENGTHEVAL_DESC: \"Evaluerer psi-styrken for alle soldater når den passende forskning er udført.\"\n  STR_DISABLEAUTOEQUIP: \"Deaktiver automatisk udrustning\"\n  STR_DISABLEAUTOEQUIP_DESC: \"Deaktiver automatisk udrustning af nye soldater før kamp.\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT: \"Tillad psi-styrkeforbedring\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT_DESC: \"Soldaternes psi-styrke kan blive forbedret igennem træning og erfaring.\"\n  STR_BATTLESMOOTHCAMERA: \"Patronkamera\"\n  STR_BATTLESMOOTHCAMERA_DESC: \"Kampscenens kamera vil være centreret på projektilernes baner.\"\n  STR_BATTLECONFIRMFIREMODE: \"Bekræft skud-tilstand\"\n  STR_BATTLECONFIRMFIREMODE_DESC: \"Kræv et ekstra klik på det samme felt for at bekræfte skudordre.\"\n  STR_SELECT_BASE_1: \"Vælg base 1\"\n  STR_SELECT_BASE_2: \"Vælg base 2\"\n  STR_SELECT_BASE_3: \"Vælg base 3\"\n  STR_SELECT_BASE_4: \"Vælg base 4\"\n  STR_SELECT_BASE_5: \"Vælg base 5\"\n  STR_SELECT_BASE_6: \"Vælg base 6\"\n  STR_SELECT_BASE_7: \"Vælg base 7\"\n  STR_SELECT_BASE_8: \"Vælg base 8\"\n  STR_VIDEO: \"VIDEO\"\n  STR_AUDIO: \"LYD\"\n  STR_BATTLESCAPE_UC: \"Kampscene\"\n  STR_MODS_UC: \"MOD'er\"\n  STR_MODS: \"Mod'er\"\n  STR_DISPLAY_RESOLUTION: \"Skærmopløsning\"\n  STR_DISPLAY_RESOLUTION_DESC: \"Ændrer skærmens opløsning, spilopløsningen vil ændre størrelse for at matche. Piletasterne skifter mellem understøttede opløsninger. Klik for at indtaste en tilpasset opløsning.\"\n  STR_ORIGINAL: \"Original\"\n  STR_DISPLAY_MODE: \"Skærmtilstand\"\n  STR_WINDOWED: \"I et vindue\"\n  STR_FULLSCREEN: \"Fuldskærm\"\n  STR_BORDERLESS: \"Uden omkreds\"\n  STR_DISPLAY_LANGUAGE: \"Vis sprog\"\n  STR_DISPLAY_LANGUAGE_DESC: \"Ændrer sproget for spillets tekst\"\n  STR_DISPLAY_FILTER: \"Skærmfilter\"\n  STR_DISPLAY_FILTER_DESC: \"Ændrer filteret anvendt på spilskærmen.{NEWLINE}*kræver OpenGL-udstyrsacceleration.\"\n  STR_DISPLAY_OPTIONS: \"Skærmindstillinger\"\n  STR_LETTERBOXED: \"Postkasse\"\n  STR_LETTERBOXED_DESC: \"Postkasseopdeler skærmen for at bevare det oprindelige størrelsesforhold.\"\n  STR_RESIZABLE: \"Kan ændre størrelse\"\n  STR_LOCK_MOUSE: \"Fang mus\"\n  STR_LOCK_MOUSE_DESC: \"Holder musemarkøren i spilvinduet. Ctrl+G for at skifte undervejs.\"\n  STR_FIXED_WINDOW_POSITION: \"Fast vinduesposition\"\n  STR_FIXED_WINDOW_POSITION_DESC: \"Angiv fast position for vindue\"\n  STR_DISPLAY_SET_WINDOW_POSITION: \"Angiv ny position for vinduerod\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_X: \"Venstre kant ny X:\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_Y: \"Øvre kant ny Y:\"\n  STR_MUSIC_VOLUME: \"Musiklydstyrke\"\n  STR_MUSIC_VOLUME_DESC: \"Ændrer lydstyrken for baggrundsmusik.\"\n  STR_SFX_VOLUME: \"Effekt-lydstyrke\"\n  STR_SFX_VOLUME_DESC: \"Ændrer lydstyrken for lydeffekter.\"\n  STR_UI_VOLUME: \"Brugerfladelydstyrke\"\n  STR_UI_VOLUME_DESC: \"Ændrer lydstyrken for brugerfladens biplyde.\"\n  STR_SCROLL_SPEED: \"Hastighed for rul\"\n  STR_SCROLL_SPEED_GEO_DESC: \"Ændringer rullehastigheden på globussen.\"\n  STR_SCROLL_SPEED_BATTLE_DESC: \"Ændrer rullehastigheden på kortet.\"\n  STR_DOGFIGHT_SPEED: \"Hastighed for 1-1 kamp\"\n  STR_DOGFIGHT_SPEED_DESC: \"Ændrer hastigheden for forfølgelsesslag mellem fartøjer og ufoer. Langsommere hastighed kan forbedre ydelsen på enheder med lille kapacitet.\"\n  STR_CLOCK_SPEED: \"Ur-hastighed\"\n  STR_CLOCK_SPEED_DESC: \"Ændrer hastigheden for uret. Langsommere hastighed kan forbedre ydelsen på ressourcesvage enheder.\"\n  STR_GLOBE_DETAILS: \"Globusdetaljer\"\n  STR_GLOBE_COUNTRIES: \"Lande\"\n  STR_GLOBE_COUNTRIES_DESC: \"Vis lande der bidrager økonomisk på globussen.\"\n  STR_GLOBE_RADARS: \"Radarer\"\n  STR_GLOBE_RADARS_DESC: \"Vis basernes radardækning på globussen.\"\n  STR_GLOBE_FLIGHT_PATHS: \"Flyruter\"\n  STR_GLOBE_FLIGHT_PATHS_DESC: \"Vis fartøjernes flyveruter på globussen.\"\n  STR_CONTROLS_DESC: \"Venstreklik på en genvej og tryk på en tast for at ændre den.{NEWLINE}Højreklik på en genvej for at deaktivere den.\"\n  STR_BASE_GAME: \"Basespil\"\n  STR_MODS_TOOLTIP: \"Version {0} af {1}.{NEWLINE}{2}\"\n  STR_EDGE_SCROLL: \"Kantrul\"\n  STR_EDGE_SCROLL_DESC: \"Udløser: Rul kort når venstre museknap holdes nede ved skærmens kant.{NEWLINE}Auto: Rul kort når markøren er over skærmkanten.\"\n  STR_TRIGGER_SCROLL: \"Udløser\"\n  STR_AUTO_SCROLL: \"Auto\"\n  STR_DRAG_SCROLL: \"Træk rul\"\n  STR_DRAG_SCROLL_DESC: \"Ruller kortet når den angivne museknap holdes nede og trækkes.\"\n  STR_LEFT_MOUSE_BUTTON: \"Venstre knap\"\n  STR_MIDDLE_MOUSE_BUTTON: \"Midterste knap\"\n  STR_RIGHT_MOUSE_BUTTON: \"Højre knap\"\n  STR_FIRE_SPEED: \"Skudhastighed\"\n  STR_FIRE_SPEED_DESC: \"Ændrer hastighed for våbenprojektiler.\"\n  STR_PLAYER_MOVEMENT_SPEED: \"Hastighed for spillerbevægelse\"\n  STR_PLAYER_MOVEMENT_SPEED_DESC: \"Ændrer bevægelseshastigheden for spillerkontrollerede enheder.\"\n  STR_COMPUTER_MOVEMENT_SPEED: \"Bevægelseshastighed for computeren\"\n  STR_COMPUTER_MOVEMENT_SPEED_DESC: \"Ændre bevægelseshastigheden for computerkontrollerede enheder.\"\n  STR_PATH_PREVIEW: \"Forhåndsvisning af sti\"\n  STR_PATH_ARROWS: \"Piletaster\"\n  STR_PATH_ARROWS_DESC: \"Klik viser stien din enhed vil benytte for at nå destinationen. Farve indikerer tilgængelige handlinger: Grøn - kan bevæge sig og skyde; gul - kan bevæge sig; rød - kan ikke bevæge sig.\"\n  STR_PATH_TIME_UNIT_COST: \"Tidsenheder\"\n  STR_PATH_TIME_UNIT_COST_DESC: \"Klik viser tidsenhederne du har tilbage, efter du er gået til destinationen.\"\n  STR_USER_INTERFACE_OPTIONS: \"Indstillinger for brugerfladen\"\n  STR_TOOLTIPS: \"Værktøjsfik\"\n  STR_TOOLTIPS_DESC: \"Vis værktøjsfif for kampscenens knapper.\"\n  STR_DEATH_NOTIFICATIONS: \"Påmindelse om dødsfald\"\n  STR_DEATH_NOTIFICATIONS_DESC: \"Vis en pop op-påmindelse om hvem som blev dræbt, når en soldat dør.\"\n  STR_SHOW_FUNDS: \"Vis midler\"\n  STR_SHOW_FUNDS_DESC: \"Vis dine nuværende midler ved siden af uret.\"\n  STR_MISSION_GENERATOR: \"MISSIONOPRETTER\"\n  STR_MAP_OPTIONS: \"KORTINDSTILLINGER\"\n  STR_ALIEN_OPTIONS: \"RUMVÆSENINDSTILLINGER\"\n  STR_MAP_TERRAIN: \"Terræn\"\n  STR_MAP_DARKNESS: \"Mørke\"\n  STR_MAP_DEPTH: \"Dybde\"\n  STR_DIFFICULTY: \"Sværhed\"\n  STR_ALIEN_RACE: \"Race\"\n  STR_ALIEN_TECH_LEVEL: \"Tek.-niveau\"\n  STR_RANDOMIZE: \"Vilkårlig\"\n  STR_RESTORE_DEFAULTS_QUESTION: \"Er du sikker på, at du ønsker at gendanne standardindstillingerne?\"\n  STR_DISPLAY_OPTIONS_CONFIRM: \"Ønsker du at bevare de nuværende indstillinger for visningen?\"\n  STR_DISPLAY_OPTIONS_REVERT: \"Vender tilbage om 0:{0}\"\n  STR_MISSING_CONTENT_PROMPT: \"ADVARSEL:{SMALLLINE}Afhænger af mod'er som ikke er tilgængelige. Manglende indhold vil blive fjernet, og indlæsning kan fejle.{NEWLINE}Fortsæt?\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT: \"Gem tidsudløse granater\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT_DESC: \"Gem granater med tidsudløsning under udstyrets før-kamps-overblik i soldatens udstyrslayout.\"\n  STR_NEWSEEDONLOAD: \"Gem scumming\"\n  STR_NEWSEEDONLOAD_DESC: \"Indlæsning af et spil vil nulstille den vilkårlige taloprettelse, så den samme handling kan give forskellige resultater. Bruges ikke ved jernmand.\"\n  STR_CHANGEVALUEBYMOUSEWHEEL: \"Skift værdierne med musehjulet\"\n  STR_CHANGEVALUEBYMOUSEWHEEL_DESC: \"Tillader dig at bruge musehjulet til at øge/reducere værdier med denne værdi.\"\n  STR_BATTLEHAIRBLEACH: \"Forbedret soldattegning\"\n  STR_BATTLEHAIRBLEACH_DESC: \"Ændrer soldaternes kampscene-tegning så den matcher udseendet af deres udstyrsoverblik.\"\n  STR_DRAGSCROLLINVERT: \"Omvendt træk-rulning\"\n  STR_DRAGSCROLLINVERT_DESC: \"Når aktiveret, trækker rulning i den modsatte retning af musen.\"\n  STR_BATTLESCAPE_SCALE: \"Kampscenes skala\"\n  STR_BATTLESCAPE_SCALE_DESC: \"Kampscenes skaleringstilstand, baseret på en fast opløsning (trukket for at passe), eller et fast zoom-niveau (udvidet for at passe).\"\n  STR_GEOSCAPE_SCALE: \"Landkortskala\"\n  STR_GEOSCAPESCALE_SCALE_DESC: \"Landkort-skaleringstilstand, baseret på en fast opløsning (trukket for at passe), eller et fast zoom-niveau (udvidet for at passe).\"\n  STR_1_5X: \"1,5 x original\"\n  STR_2X: \"2 x original\"\n  STR_THIRD_DISPLAY: \"1/3 skærm\"\n  STR_HALF_DISPLAY: \"1/2 skærm\"\n  STR_FULL_DISPLAY: \"Fuld skærm\"\n  STR_FPS_LIMIT: \"FPS-begrænsning\"\n  STR_FPS_LIMIT_DESC: \"Begrænser antallet af skærmopdateringer per sekund. 0 er lig ingen begrænsning. Hvis OpenGL-optegning er valgt bruger spillet Vsync i stedet.\"\n  STR_FPS_INACTIVE_LIMIT: \"FPS-begrænsning for baggrund\"\n  STR_FPS_INACTIVE_LIMIT_DESC: \"Begræns antallet af skærmopdateringer per sekund hvis OpenXcom er i baggrunden.\"\n  STR_NOALIENPANICMESSAGES: \"Undertryk panikbeskeder for rumvæsener.\"\n  STR_NOALIENPANICMESSAGES_DESC: \"Vis ikke panikbeskeder for rumvæsener med mindre at de er synlige for spilleren.\"\n  STR_ALIENBLEEDING: \"Rumvæsen-skader\"\n  STR_ALIENBLEEDING_DESC: \"Tillad at fatale skader kan påføres de fleste rumvæsener.\"\n  STR_FIELDPROMOTIONS: \"Feltforfremmelser\"\n  STR_FIELDPROMOTIONS_DESC: \"Kun soldater som deltog i missionen kan forfremmes.\"\n  STR_MEETINGPOINT: \"Forudsig ufo-rute\"\n  STR_MEETINGPOINT_DESC: \"Send fly mod et mødepunkt med ufoen baseret på dens nuværende rute.\"\n  STR_IRONMAN: \"JERNMAND\"\n  STR_IRONMAN_DESC: \"Ingen mulighed for at gemme manuelt\"\n  STR_SAVE_AND_ABANDON_GAME: \"GEM OG FORLAD SPIL\"\n  STR_MOD_UNSUCCESSFUL: \"Mod kunne ikke indlæses\"\n  STR_NEW_SAVED_GAME_SLOT: \"<NYT GEMT SPIL>\"\n  STR_AUTO_SAVE_GEOSCAPE_SLOT: \"<AUTOMATISK LANDKORT>\"\n  STR_AUTO_SAVE_BATTLESCAPE_SLOT: \"<AUTOMATISK KAMPSCENE>\"\n  STR_QUICK_SAVE_SLOT: \"<GEM HURTIGT>\"\n  STR_DISPLAY_MODE_DESC: \"Ændr hvordan spillet vises på din skærm.\"\n  STR_PREFERRED_MUSIC_FORMAT: \"Musikformat\"\n  STR_PREFERRED_MUSIC_FORMAT_DESC: \"Vælg det foretrukne musikformat når der er flere forskellige tilgængelige{NEWLINE}Bemærk: MIDI-afspilning kan være fejlbehæftet på Windows.\"\n  STR_PREFERRED_SFX_FORMAT: \"SFX-format\"\n  STR_PREFERRED_SFX_FORMAT_DESC: \"Vælg det foretrukne lydeffektformat når der er flere forskellige tilgængelige.\"\n  STR_PREFERRED_VIDEO_FORMAT: \"Videoformat\"\n  STR_PREFERRED_VIDEO_FORMAT_DESC: \"Vælger det foretrukne videoformat når flere er tilgængelige.\"\n  STR_PREFERRED_VIDEO_ANIMATION: \"Animation\"\n  STR_PREFERRED_VIDEO_SLIDESHOW: \"Diasshow\"\n  STR_PREFERRED_FORMAT_AUTO: \"Auto\"\n  STR_CURRENT_FORMAT: \"Nuværende: {0}\"\n  STR_SOUND_OPTIONS: \"Lydinstillinger\"\n  STR_BACKGROUND_MUTE: \"Baggrundslyd slukket\"\n  STR_BACKGROUND_MUTE_DESC: \"Slukker for al lyd når spilvinduet ikke er aktivt.\"\n  STR_FORCE_FIRE: \"Nulstil skudlinje\"\n  STR_FORCE_FIRE_DESC: \"Gør at du kan tvinge dine soldater til at skyde, når du holder CTRL nede, uanset regler for skudlinjen.\"\n  STR_NO_AUDIO_HARDWARE_DETECTED: \"Intet lydudstyr detekteret\"\n  STR_MOUSEWHEEL_SPEED: \"Rullehastighed for musehjulet\"\n  STR_MOUSEWHEEL_SPEED_DESC: \"Juster antallet af linjer rullet i lister med hver øgning af musehjullet.\"\n  STR_DISABLED: \"Deaktiveret\"\n  STR_MAXIMIZE_INFO_SCREENS: \"Maksimer info-skærme\"\n  STR_MAXIMIZE_INFO_SCREENS_DESC: \"Lageret og diverse andre skærme vil blive vist i fuld skærm, uanset indstillinger for skala.\"\n  STR_DIARY: \"DAGBOG\"\n  STR_KILLED: \"DRÆBT\"\n  STR_STUNNED: \"BEDØVET\"\n  STR_PANICKED: \"I PANIK\"\n  STR_MINDCONTROLLED: \"KONTROLLERET\"\n  STR_REGION_UNKNOWN: \"Ikke afsløret\"\n  STR_WEAPON_UNKNOWN: \"Improvisation\"\n  STR_UNKNOWN: \"Ukendt\"\n  STR_VICTORY: \"Sejr\"\n  STR_DEFEAT: \"Nederlag\"\n  STR_NO_RECORD: \"Ingen post\"\n  STR_HUMAN: \"Menneske\"\n  STR_FRIENDLY: \"Venligsindet\"\n  STR_HOSTILE: \"Fjendtlig\"\n  STR_NEUTRAL: \"Neutral\"\n  STR_RATING_UC: \"BEDØMMELSE\"\n  STR_LOCATION: \"PLACERING> {ALT}{0}\"\n  STR_DAYLIGHT_TYPE: \"TID> {ALT}{0}\"\n  STR_RACE_TYPE: \"RACE> {ALT}{0}\"\n  STR_DAY: \"Dag\"\n  STR_NIGHT: \"Nat\"\n  STR_DAYS_WOUNDED: \"DAGE SÅRET> {ALT}{0}\"\n  STR_COMBAT: \"KRIG\"\n  STR_PERFORMANCE: \"YDELSE\"\n  STR_NEUTRALIZATIONS_BY_RACE: \"NEUTRALISERINGER EFTER RACE\"\n  STR_NEUTRALIZATIONS_BY_RANK: \"NEUTRALISERINGER EFTER RANG\"\n  STR_NEUTRALIZATIONS_BY_WEAPON: \"NEUTRALISERINGER EFTER VÅBEN\"\n  STR_MISSIONS_BY_LOCATION: \"MISSIONER EFTER LOKATION\"\n  STR_MISSIONS_BY_TYPE: \"MISSIONER EFTER TYPE\"\n  STR_MISSIONS_BY_UFO: \"MISSIONER EFTER UFO\"\n  STR_SCORE_VALUE: \"BEDØMMELSE> {ALT}{0}\"\n  STR_WINS: \"SEJRE> {ALT}{0}\"\n  STR_STUNS: \"BEDØVELSER> {ALT}{0}\"\n  STR_PANICKS: \"I PANIK> {ALT}{0}\"\n  STR_MINDCONTROLS: \"STYRING> {ALT}{0}\"\n  STR_AWARDS: \"PRÆMIER\"\n  STR_COMMENDATIONS_UC: \"UDMÆRKELSER\"\n  STR_COMMENDATIONS: \"Udmærkelser\"\n  STR_MEDALS: \"MEDALJER\"\n  STR_LOST_IN_SERVICE: \"DØD UNDER KAMP\"\n  STR_MEDAL_NAME: \"Medaljenavn\"\n  STR_MEDAL_AWARD_LEVEL: \"Præmieniveau\"\n  STR_MEDAL_DECOR_LEVEL: \"Dekorationsniveau\"\n  STR_AWARD_0: \"Første præmie\"\n  STR_AWARD_1: \"Anden præmie\"\n  STR_AWARD_2: \"Tredje præmie\"\n  STR_AWARD_3: \"Fjerde præmie\"\n  STR_AWARD_4: \"Femte præmie\"\n  STR_AWARD_5: \"Sjette præmie\"\n  STR_AWARD_6: \"Syvende præmie\"\n  STR_AWARD_7: \"Ottende præmie\"\n  STR_AWARD_8: \"Niende præmie\"\n  STR_AWARD_9: \"Tiende præmie\"\n  STR_AWARD_DECOR_0: \"Ingen\"\n  STR_AWARD_DECOR_1: \"Første bronzenål\"\n  STR_AWARD_DECOR_2: \"Anden bronzenål\"\n  STR_AWARD_DECOR_3: \"Tredje bronzenål\"\n  STR_AWARD_DECOR_4: \"Første sølvnål\"\n  STR_AWARD_DECOR_5: \"Anden sølvnål\"\n  STR_AWARD_DECOR_6: \"Tredje sølvnål\"\n  STR_AWARD_DECOR_7: \"Første guldnål\"\n  STR_AWARD_DECOR_8: \"Anden guldnål\"\n  STR_AWARD_DECOR_9: \"Tredje guldnål\"\n  STR_KILLED_IN_ACTION_MALE: \"DRÆBT I KAMP\"\n  STR_KILLED_IN_ACTION_FEMALE: \"DRÆBT I KAMP\"\n  STR_MISSING_IN_ACTION_MALE: \"SAVNET I KAMP\"\n  STR_MISSING_IN_ACTION_FEMALE: \"SAVNET I KAMP\"\n  STR_AVERAGE_MONTHLY_RATING: \"Gennemsnitlig måned bedømmelse\"\n  STR_TOTAL_INCOME: \"Indkomst i alt\"\n  STR_TOTAL_EXPENDITURE: \"Omkostninger i alt\"\n  STR_MISSIONS_WON: \"Antal missioner\"\n  STR_MISSIONS_LOST: \"Mislykkedes missioner\"\n  STR_NIGHT_MISSIONS: \"Nattemissioner\"\n  STR_BEST_RATING: \"Bedste missionsbedømmelse\"\n  STR_WORST_RATING: \"Værste missionsbedømmelse\"\n  STR_ALIEN_KILLS: \"Rumvæsener dræbt\"\n  STR_ALIEN_CAPTURES: \"Rumvæsener fanget\"\n  STR_FRIENDLY_KILLS: \"Beskydning fra egne\"\n  STR_AVERAGE_ACCURACY: \"Gennemsnitlig præcision\"\n  STR_WEAPON_MOST_KILLS: \"Mest effektive våben\"\n  STR_ALIEN_MOST_KILLS: \"Rumvæsen med flest dræbte\"\n  STR_LONGEST_SERVICE: \"Længste måneder i tjeneste\"\n  STR_TOTAL_DAYS_WOUNDED: \"Sygedage\"\n  STR_COUNTRIES_LOST: \"Lande infiltreret\"\n  STR_TOTAL_TERROR_SITES: \"Terrorangreb\"\n  STR_TOTAL_BASES: \"Antal baser\"\n  STR_TOTAL_CRAFT: \"Antal fly\"\n  STR_TOTAL_SCIENTISTS: \"Hyrede forskere\"\n  STR_TOTAL_ENGINEERS: \"Hyrede ingeniører\"\n  STR_TOTAL_RESEARCH: \"Antal forskningsprojekter\"\n  STR_DIARY_ACCURACY: \"PRÆCISION> {ALT}{0}%\"\n  STR_STATISTICS: \"Statistik\"\n  STR_STATS: \"STATISTIK\"\n  STR_TIME_UNITS_ABBREVIATION: \"TE\"\n  STR_STAMINA_ABBREVIATION: \"UDH\"\n  STR_HEALTH_ABBREVIATION: \"LIV\"\n  STR_BRAVERY_ABBREVIATION: \"MOD\"\n  STR_REACTIONS_ABBREVIATION: \"REA\"\n  STR_FIRING_ACCURACY_ABBREVIATION: \"ACC\"\n  STR_THROWING_ACCURACY_ABBREVIATION: \"THR\"\n  STR_STRENGTH_ABBREVIATION: \"STY\"\n  STR_MELEE_ACCURACY_ABBREVIATION: \"MEL\"\n"
  },
  {
    "path": "bin/common/Language/de.yml",
    "content": "de:\n  STR_OPENXCOM: \"OpenXcom\"\n  STR_NEW_GAME: \"Neues Spiel\"\n  STR_LOAD_SAVED_GAME: \"Spiel Laden\"\n  STR_SELECT_DIFFICULTY_LEVEL: \"Schwierigkeitsgrad wählen\"\n  STR_1_BEGINNER: \"1> Anfänger\"\n  STR_2_EXPERIENCED: \"2> Erfahren\"\n  STR_3_VETERAN: \"3> Könner\"\n  STR_4_GENIUS: \"4> Genie\"\n  STR_5_SUPERHUMAN: \"5> Übermenschlich\"\n  STR_TIME: \"Zeit\"\n  STR_DATE: \"Datum\"\n  STR_SELECT_GAME_TO_LOAD: \"Gesichertes Spiel laden\"\n  STR_SELECT_SAVE_POSITION: \"Speicherplatz wählen\"\n  STR_GAME_OPTIONS: \"SPIELOPTIONEN\"\n  STR_LOAD_GAME: \"SPIEL LADEN\"\n  STR_SAVE_GAME: \"SPIEL SICHERN\"\n  STR_ABANDON_GAME: \"SPIEL AUFGEBEN\"\n  STR_ABANDON_GAME_QUESTION: \"SPIEL AUFGEBEN?\"\n  STR_QUIT: \"Spiel verlassen\"\n  STR_SAVING_GAME: \"Spiel wird gesichert\"\n  STR_LOADING_GAME: \"Spiel wird geladen\"\n  STR_NO_SAVED_GAME_PRESENT: \"Keine gesicherten Spiele vorhanden.\"\n  STR_LOAD_UNSUCCESSFUL: \"Ladevorgang fehlgeschlagen.\"\n  STR_SAVE_UNSUCCESSFUL: \"Speichern fehlgeschlagen\"\n  STR_LOAD_SUCCESSFUL: \"Ladevorgang abgeschlossen.\"\n  STR_SAVE_SUCCESSFUL: \"Speichern erfolgreich\"\n  STR_DELETE: \"LÖSCHEN\"\n  STR_DELETE_UNSUCCESSFUL: \"Löschen fehlgeschlagen.\"\n  STR_IS_IT_OK_TO_DELETE_THE_SAVED_GAME: \"Gesichertes Spiel löschen?\"\n  STR_ORIGINAL_XCOM: \"Original X-Com\"\n  STR_LOADING: \"Ladevorgang...\"\n  STR_DETAILS: \"DETAILS> {ALT}{0}\"\n  STR_NEW_BATTLE: \"Neues Gefecht\"\n  STR_OPTIONS: \"Optionen\"\n  STR_RIGHT_CLICK_TO_DELETE: \"Rechts klicken, um zu Löschen.\"\n  STR_RESTORE_DEFAULTS: \"Zurücksetzen\"\n  STR_CONTROLS: \"STEUERUNG\"\n  STR_GENERAL: \"ALLGEMEIN\"\n  STR_GEOSCAPE: \"WELTKARTE\"\n  STR_BATTLESCAPE: \"GEFECHTSKARTE\"\n  STR_SCREENSHOT: \"Screenshot\"\n  STR_FPS_COUNTER: \"FPS Zähler\"\n  STR_ROTATE_LEFT: \"Nach links drehen\"\n  STR_ROTATE_RIGHT: \"Nach rechts drehen\"\n  STR_ROTATE_UP: \"Nach oben drehen\"\n  STR_ROTATE_DOWN: \"Nach unten drehen\"\n  STR_ZOOM_IN: \"Einzoomen\"\n  STR_ZOOM_OUT: \"Auszoomen\"\n  STR_TOGGLE_COUNTRY_DETAIL: \"Landschafts-Details\"\n  STR_TOGGLE_RADAR_RANGES: \"Radar Reichweite\"\n  STR_SCROLL_LEFT: \"Nach links scrollen\"\n  STR_SCROLL_RIGHT: \"Nach rechts scrollen\"\n  STR_SCROLL_UP: \"Nach oben scrollen\"\n  STR_SCROLL_DOWN: \"Nach unten scrollen\"\n  STR_UNIT_LEVEL_ABOVE: \"Einheit eine Ebene hoch bewegen\"\n  STR_UNIT_LEVEL_BELOW: \"Einheit eine Ebene runter bewegen\"\n  STR_VIEW_LEVEL_ABOVE: \"Nach oben\"\n  STR_VIEW_LEVEL_BELOW: \"Nach unten\"\n  STR_CENTER_SELECTED_UNIT: \"Zentriere Einheit\"\n  STR_PREVIOUS_UNIT: \"Vorherige Einheit\"\n  STR_NEXT_UNIT: \"Nächste Einheit\"\n  STR_DESELECT_UNIT: \"Einheit abwählen\"\n  STR_USE_LEFT_HAND: \"Item aus der linken Hand benutzen\"\n  STR_USE_RIGHT_HAND: \"Item aus der rechten Hand benutzen\"\n  STR_INVENTORY: \"Inventar\"\n  STR_MINIMAP: \"Minikarte\"\n  STR_MULTI_LEVEL_VIEW: \"Mehrebenenansicht\"\n  STR_END_TURN: \"Runde beenden\"\n  STR_ABORT_MISSION: \"Mission abbrechen\"\n  STR_UNIT_STATS: \"Statistik der Einheit\"\n  STR_KNEEL: \"Stehen/Knien\"\n  STR_RELOAD: \"Nachladen\"\n  STR_TOGGLE_PERSONAL_LIGHTING: \"Wechsel zwischen Beleuchtung\"\n  STR_DONT_RESERVE_TIME_UNITS: \"Keine Zeiteinheiten reservieren\"\n  STR_RESERVE_TIME_UNITS_FOR_SNAP_SHOT: \"Zeiteinheiten für Schnellschuss reservieren \"\n  STR_RESERVE_TIME_UNITS_FOR_AIMED_SHOT: \"Zeiteinheiten für Zielschuss reservieren \"\n  STR_RESERVE_TIME_UNITS_FOR_AUTO_SHOT: \"Zeiteinheiten für Auto-Schuss reservieren\"\n  STR_CENTER_ON_ENEMY_1: \"Zentriere Gegner 1\"\n  STR_CENTER_ON_ENEMY_2: \"Zentriere Gegner 2\"\n  STR_CENTER_ON_ENEMY_3: \"Zentriere Gegner 3\"\n  STR_CENTER_ON_ENEMY_4: \"Zentriere Gegner 4\"\n  STR_CENTER_ON_ENEMY_5: \"Zentriere Gegner 5\"\n  STR_CENTER_ON_ENEMY_6: \"Zentriere Gegner 6\"\n  STR_CENTER_ON_ENEMY_7: \"Zentriere Gegner 7\"\n  STR_CENTER_ON_ENEMY_8: \"Zentriere Gegner 8\"\n  STR_CENTER_ON_ENEMY_9: \"Zentriere Gegner 9\"\n  STR_CENTER_ON_ENEMY_10: \"Zentriere Gegner 10\"\n  STR_CREATE_INVENTORY_TEMPLATE: \"Inventar Vorlage erstellen\"\n  STR_APPLY_INVENTORY_TEMPLATE: \"Inventar Vorlage verwenden\"\n  STR_CLEAR_INVENTORY: \"Inventar löschen\"\n  STR_AUTO_EQUIP: \"Automatisches Ausrüsten\"\n  STR_QUICK_SAVE: \"Schnell speichern\"\n  STR_QUICK_LOAD: \"Schnell laden\"\n  STR_ADVANCED: \"ERWEITERT\"\n  STR_AGGRESSIVERETALIATION: \"Agressive Vergeltung\"\n  STR_AGGRESSIVERETALIATION_DESC: \"UFOs können jederzeit Ihre Basen aufspüren, unabhängig ihrer Missionsparameter.\"\n  STR_STORAGELIMITSENFORCED: \"Lagerbegrenzung für geborgene Gegenstände.\"\n  STR_STORAGELIMITSENFORCED_DESC: \"Erzwingt die Einhaltung der Kapazitätsgrenzen für Klimazellen und Hauptlager, für lebende Außerirdische und geborgene Artefakte aus Missionen.\"\n  STR_CANSELLLIVEALIENS: \"Verkauf lebender Aliens\"\n  STR_CANSELLLIVEALIENS_DESC: \"Erlaubt den Verkauf von lebendigen Außerirdischen. Dies wird empfohlen, wenn die Begrenzungen der Klimazelle aktiviert ist.\"\n  STR_ALLOWBUILDINGQUEUE: \"Mehrere Bauaufträge erlauben\"\n  STR_ALLOWBUILDINGQUEUE_DESC: \"Neue Einrichtungen können neben unfertige platziert werden.\"\n  STR_BATTLEAUTOEND: \"Automatisches Beenden der Kämpfe\"\n  STR_BATTLEAUTOEND_DESC: \"Ein Kampf endet automatisch, sobald der letze Gegner betäubt oder getötet wurde.\"\n  STR_BATTLEINSTANTGRENADE: \"Sofortige Explosion der Granaten\"\n  STR_BATTLEINSTANTGRENADE_DESC: \"Die Explosion der Granaten, die nach \\\"0\\\" Runden detonieren sollen, erfolgt unmittelbar nach dem Wurf anstatt zum Ende der Runde.\"\n  STR_BATTLEUFOEXTENDERACCURACY: \"UFO Extender Zielgenauigkeit\"\n  STR_BATTLEUFOEXTENDERACCURACY_DESC: \"Genauigkeit von Schüssen sinkt je nach Feuermodus jenseits einer bestimmten Distanz stark ab. Angepasste Zielgenauigkeit wird am Mauszeiger angezeigt.\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE: \"Lufttransfer\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE_DESC: \"Flugzeuge, die sich aktuell in der Luft befinden, können transferiert werden.\"\n  STR_CRAFTLAUNCHALWAYS: \"Erzwungene Starts der Luftwaffe\"\n  STR_CRAFTLAUNCHALWAYS_DESC: \"Luftfahrzeuge können auch dann gestartet werden, wenn diese normalerweise noch zuvor repariert werden müssten.\"\n  STR_CUSTOMINITIALBASE: \"Benutzerdefinierte Anfangsbasis\"\n  STR_CUSTOMINITIALBASE_DESC: \"Erlaubt die manuelle Platzierung der Starteinrichtungen bei Neustart des Spiels anstatt den vorgefertigten Entwurf der Basis benutzen zu müssen.\"\n  STR_GLOBESEASONS: \"Realistische Globusbeleuchtung\"\n  STR_GLOBESEASONS_DESC: \"Das Spiel verwendet, in Abhängigkeit der axialen Neigung der Erde, eine realistischere Darstellung des Lichteinfalls.\"\n  STR_PLAYINTRO: \"Intro abspielen\"\n  STR_PLAYINTRO_DESC: \"Intro-Video bei Spielstart zeigen.\"\n  STR_SHOWMORESTATSININVENTORYVIEW: \"Inventar Statistik\"\n  STR_SHOWMORESTATSININVENTORYVIEW_DESC: \"Zeigt zusätzliche Informationen über den ausgewählten Soldaten im Inventar-/Ausrüsten- Bildschirm.\"\n  STR_SNEAKYAI: \"Hinterlistige KI\"\n  STR_SNEAKYAI_DESC: \"Die künstliche Intelligenz versucht, so gut wie möglich unbeobachtet zu agieren.\"\n  STR_STRAFE: \"Alternative Bewegungsart\"\n  STR_STRAFE_DESC: \"Befähigt zum seitlichen Gehen, Rennen, unabhängiger Bewegung der Panzer-Waffe, wenn CTRL gedrückt wird.\"\n  STR_BATTLEEXPLOSIONHEIGHT: \"Explosionshöhe\"\n  STR_BATTLEEXPLOSIONHEIGHT_DESC: \"Wie viele Höhenebenen (hoch und runter) hat die Reichweite von Explosionen.{NEWLINE}(Normal: 0, Voluminös: 3)\"\n  STR_AUTOSAVE: \"Automatisches Speichern\"\n  STR_AUTOSAVE_DESC: \"Speichert automatisch das Spiel in bestimmten Intervallen. Gilt nicht für den Ironman-Modus.\"\n  STR_AUTOSAVE_FREQUENCY: \"Speicher-Intervall\"\n  STR_AUTOSAVE_FREQUENCY_DESC: \"Anzahl der Züge, bis das Spiel automatisch gespeichert werden soll.\"\n  STR_ALLOWPSIONICCAPTURE: \"Aktiviere Gefangennahme durch PSI-Gedankenkontrolle\"\n  STR_ALLOWPSIONICCAPTURE_DESC: \"Übernahme eines Aliens durch Gedankenkontrolle über das Missionsende hinaus zählt als Gefangennahme.{NEWLINE}Die Mission ist gewonnen, wenn alle Aliens unter Spielerkontrolle stehen.\"\n  STR_ANYTIMEPSITRAINING: \"Psionisches Training zu jeder Zeit\"\n  STR_ANYTIMEPSITRAINING_DESC: \"Ermöglicht die Zuweisung von Soldaten zum psionischen Training zu jeder Zeit des Monats. Denken Sie daran, Grundausbildung dauert 30 bis 60 Tage.\"\n  STR_SKIPNEXTTURNSCREEN: \"\\\"Nächste Runde\\\" Bildschirm überspringen\"\n  STR_SKIPNEXTTURNSCREEN_DESC: \"\\\"Nächste Runde\\\" - Bildschirme werden während des Gefechts nach einer kurzen Verzögerung automatisch fortgesetzt.\"\n  STR_NOT_ENOUGH_SPACE: \"Nicht genug Platz!\"\n  STR_WEAPONSELFDESTRUCTION: \"Alienwaffen Selbstzerstörung\"\n  STR_WEAPONSELFDESTRUCTION_DESC: \"Die Waffen von Außerirdischen zerstören sich selbst, wenn ihr Besitzer getötet wird, wie in XCOM 2012.\"\n  STR_RETAINCORPSES: \"Verhörte Außerirdische festhalten\"\n  STR_RETAINCORPSES_DESC: \"Nach dem \\\"Untersuchen\\\" lebender Außerirdischer werden die Körper, wie in XCOM 2012, zu den Basislagern hinzugefügt.\"\n  STR_SAVE_VOXEL_VIEW: \"Einheitenansicht abspeichern\"\n  STR_RESERVE_TIME_UNITS_FOR_KNEEL: \"Zeiteinheiten zum Hinknien reservieren\"\n  STR_EXPEND_ALL_TIME_UNITS: \"Alle verbleibenden Zeiteinheiten aufbrauchen\"\n  STR_PSISTRENGTHEVAL: \"Psi-Stärke Auswertung\"\n  STR_PSISTRENGTHEVAL_DESC: \"Die Auswertung der psionischen Stärke ist von allen Soldaten nach der entsprechenden Forschung abgeschlossen.\"\n  STR_DISABLEAUTOEQUIP: \"Automatisches Ausrüsten deaktivieren\"\n  STR_DISABLEAUTOEQUIP_DESC: \"Deaktiviert das automatische Ausrüsten der XCom Einheiten vor jedem Kampf.\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT: \"Psi-Stärke Verbesserung zulassen\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT_DESC: \"Die Psi-Stärke der Soldaten kann durch Erfahrung und Ausbildung verbessert werden.\"\n  STR_BATTLESMOOTHCAMERA: \"Weiche Geschosskamera\"\n  STR_BATTLESMOOTHCAMERA_DESC: \"Projektile bleiben auf der Gefechtskarte während des Fluges zentriert.\"\n  STR_BATTLECONFIRMFIREMODE: \"Bestätige Feuer Modus\"\n  STR_BATTLECONFIRMFIREMODE_DESC: \"Benötigt einen weiteren Klick, um die Feuerfreigabe zu bestätigen.\"\n  STR_SELECT_BASE_1: \"Wähle Basis 1\"\n  STR_SELECT_BASE_2: \"Wähle Basis 2\"\n  STR_SELECT_BASE_3: \"Wähle Basis 3\"\n  STR_SELECT_BASE_4: \"Wähle Basis 4\"\n  STR_SELECT_BASE_5: \"Wähle Basis 5\"\n  STR_SELECT_BASE_6: \"Wähle Basis 6\"\n  STR_SELECT_BASE_7: \"Wähle Basis 7\"\n  STR_SELECT_BASE_8: \"Wähle Basis 8\"\n  STR_VIDEO: \"GRAFIK\"\n  STR_AUDIO: \"SOUND\"\n  STR_BATTLESCAPE_UC: \"GEFECHTSKARTE\"\n  STR_MODS_UC: \"MODS\"\n  STR_MODS: \"Modifikationen\"\n  STR_DISPLAY_RESOLUTION: \"Bildschirmauflösung\"\n  STR_DISPLAY_RESOLUTION_DESC: \"Ändert die Bildschirmauflösung.{SMALLLINE}Für eine benutzerdefinierte Eingabe, direkt anklicken.\"\n  STR_ORIGINAL: \"Original\"\n  STR_DISPLAY_MODE: \"Anzeigemodus\"\n  STR_WINDOWED: \"Fenster\"\n  STR_FULLSCREEN: \"Vollbild\"\n  STR_BORDERLESS: \"Ohne Rand\"\n  STR_DISPLAY_LANGUAGE: \"Sprache\"\n  STR_DISPLAY_LANGUAGE_DESC: \"Spracheinstellung ändern.\"\n  STR_DISPLAY_FILTER: \"Darstellungsfilter\"\n  STR_DISPLAY_FILTER_DESC: \"Grafikfilter auswählen.{NEWLINE}'*' benötigt OpenGL Hardware-Beschleunigung.\"\n  STR_DISPLAY_OPTIONS: \"Darstellungsoptionen\"\n  STR_LETTERBOXED: \"Letterbox-Format\"\n  STR_LETTERBOXED_DESC: \"Verwendet schwarze Balken, um das Seitenverhältnis beizubehalten.\"\n  STR_RESIZABLE: \"Veränderbar\"\n  STR_LOCK_MOUSE: \"Mauszeiger fangen\"\n  STR_LOCK_MOUSE_DESC: \"Verhindert, dass der Mauszeiger das Spielfenster verlässt. Strg+G zum Umschalten.\"\n  STR_FIXED_WINDOW_POSITION: \"Feste Fensterposition\"\n  STR_FIXED_WINDOW_POSITION_DESC: \"Dem Fenster eine feste Position zuweisen.\"\n  STR_DISPLAY_SET_WINDOW_POSITION: \"Hauptfenster neue Position zuweisen\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_X: \"Linker Rand X:\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_Y: \"Oberer Rand Y:\"\n  STR_MUSIC_VOLUME: \"Musiklautstärke\"\n  STR_MUSIC_VOLUME_DESC: \"Ändert die Lautstärke der Hintergrundmusik.\"\n  STR_SFX_VOLUME: \"SFX-Lautstärke\"\n  STR_SFX_VOLUME_DESC: \"Ändert die Lautstärke der Soundeffekte.\"\n  STR_UI_VOLUME: \"Menü-Lautstärke\"\n  STR_UI_VOLUME_DESC: \"Ändert die Lautstärke der Benutzeroberfläche.\"\n  STR_SCROLL_SPEED: \"Scrollgeschwindigkeit\"\n  STR_SCROLL_SPEED_GEO_DESC: \"Ändert die Scrollgeschwindigkeit des Globus.\"\n  STR_SCROLL_SPEED_BATTLE_DESC: \"Ändert die Scrollgeschwindigkeit der taktischen Gefechtskarte.\"\n  STR_DOGFIGHT_SPEED: \"Luftkampfgeschwindigkeit\"\n  STR_DOGFIGHT_SPEED_DESC: \"Ändert die Geschwindigkeit der Abfangaktionen zwischen UFO und Abfangjägern. Niedrigere Geschwindigkeiten können die Leistung auf schwächeren Systemen verbessern.\"\n  STR_CLOCK_SPEED: \"Zeitraffer\"\n  STR_CLOCK_SPEED_DESC: \"Ändert die Geschwindigkeit der Uhr in der Weltkarte. Niedrigere werte können die Leistung auf schwächeren Systemen verbessern.\"\n  STR_GLOBE_DETAILS: \"Globus-Details\"\n  STR_GLOBE_COUNTRIES: \"Länder\"\n  STR_GLOBE_COUNTRIES_DESC: \"Zeigt die geldgebenden Länder auf dem Globus an.\"\n  STR_GLOBE_RADARS: \"Radars\"\n  STR_GLOBE_RADARS_DESC: \"Zeigt die Radarreichweiten auf dem Globus an.\"\n  STR_GLOBE_FLIGHT_PATHS: \"Flugrouten\"\n  STR_GLOBE_FLIGHT_PATHS_DESC: \"Zeigt Flugrouten auf dem Globus an.\"\n  STR_CONTROLS_DESC: \"Linksklicken auf einen Shortcut und anschließende Tastatureingabe, um diesen zu ändern.{NEWLINE}Rechtsklick zum deaktivieren des Shortcuts.\"\n  STR_BASE_GAME: \"Hauptspiel\"\n  STR_MODS_TOOLTIP: \"Version {0} von {1}.{NEWLINE}{2}\"\n  STR_EDGE_SCROLL: \"Scroll-Art\"\n  STR_EDGE_SCROLL_DESC: \"Manuell: Scrollt die Karte, wenn die angegebene Maustaste gedrückt und gehalten wird. Automatisch: Bewegen Sie den Mauszeiger am Randbereich der Karte, um zu Scrollen.\"\n  STR_TRIGGER_SCROLL: \"Manuell\"\n  STR_AUTO_SCROLL: \"Automatisch\"\n  STR_DRAG_SCROLL: \"Scroll-Taste\"\n  STR_DRAG_SCROLL_DESC: \"Scrollt die Karte, wenn die angegebene Maustaste gedrückt und gehalten wird.\"\n  STR_LEFT_MOUSE_BUTTON: \"Linke Maustaste\"\n  STR_MIDDLE_MOUSE_BUTTON: \"Mittlere Maustaste\"\n  STR_RIGHT_MOUSE_BUTTON: \"Rechte Maustaste\"\n  STR_FIRE_SPEED: \"Feuerrate\"\n  STR_FIRE_SPEED_DESC: \"Ändert die Geschwindigkeit der Waffenprojektile.\"\n  STR_PLAYER_MOVEMENT_SPEED: \"XCom-Geschwindigkeit\"\n  STR_PLAYER_MOVEMENT_SPEED_DESC: \"Ändert die Bewegungsgeschwindigkeit der eigenen XCom Einheiten.\"\n  STR_COMPUTER_MOVEMENT_SPEED: \"KI-Geschwindigkeit\"\n  STR_COMPUTER_MOVEMENT_SPEED_DESC: \"Ändert die Bewegungsgeschwindigkeit der Computer-Einheiten.\"\n  STR_PATH_PREVIEW: \"Pfadvorschau\"\n  STR_PATH_ARROWS: \"Pfeile\"\n  STR_PATH_ARROWS_DESC: \"Klicken zeigt den Pfad, den die Einheit nehmen wird. Farbe zeigt verfügbare Optionen: Grün - kann hierher laufen und noch feuern; Gelb - kann hierher laufen; Rot - außer Reichweite.\"\n  STR_PATH_TIME_UNIT_COST: \"Zeiteinheiten\"\n  STR_PATH_TIME_UNIT_COST_DESC: \"Klicken um die TUs der Einheit anzuzeigen die er nach dem Zug zum Ziel noch übrig hat.\"\n  STR_USER_INTERFACE_OPTIONS: \"Optionen\"\n  STR_TOOLTIPS: \"Kurzinfos\"\n  STR_TOOLTIPS_DESC: \"Zeigt Kurzinfos für die Tasten in der Gefechtskarte an.\"\n  STR_DEATH_NOTIFICATIONS: \"Todesbenachrichtigung\"\n  STR_DEATH_NOTIFICATIONS_DESC: \"Zeigt dem Spieler eine Kurzmitteilung für jeden gefallenden Soldaten an.\"\n  STR_SHOW_FUNDS: \"Finanzen anzeigen\"\n  STR_SHOW_FUNDS_DESC: \"Zeigt die aktuellen Finanzen über der Uhr in der Weltkarte an.\"\n  STR_MISSION_GENERATOR: \"MISSIONS-GENERATOR\"\n  STR_MAP_OPTIONS: \"Karten-Optionen\"\n  STR_ALIEN_OPTIONS: \"ALIEN-OPTIONEN\"\n  STR_MAP_TERRAIN: \"Gelände\"\n  STR_MAP_DARKNESS: \"Dunkelheit\"\n  STR_MAP_DEPTH: \"Höhe\"\n  STR_DIFFICULTY: \"Schwierigkeitsgrad\"\n  STR_ALIEN_RACE: \"Volk\"\n  STR_ALIEN_TECH_LEVEL: \"Technologielevel\"\n  STR_RANDOMIZE: \"Zufällig\"\n  STR_OXCE_REQUIRED_QUESTION: \"Dieser Mod erfordert OpenXcom {0}, um korrekt zu laufen. Diesen Mod aktivieren?\"\n  STR_RESTORE_DEFAULTS_QUESTION: \"Wirklich Originaleinstellungen wiederherstellen?\"\n  STR_DISPLAY_OPTIONS_CONFIRM: \"Möchten Sie die aktuelle Darstellungsoptionen beibehalten?\"\n  STR_DISPLAY_OPTIONS_REVERT: \"Wird auf vorherige Einstellung zurückgesetzt in 0:{0}\"\n  STR_MISSING_CONTENT_PROMPT: \"WARNUNG:{SMALLLINE}Der Speicherstand ist abhängig von Modifikationen die derzeit nicht aktiviert sind. Der fehlende Inhalt wird entfernt und es ist möglich, dass der Speicherstand nicht geladen werden kann.{NEWLINE}Fortsetzen?\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT: \"Granatenzündungsstatus im Ausrüstungsbildschirm speicherbar\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT_DESC: \"Speichert vor dem Kampf im Ausrüstungsbildschirm aktivierte Granaten \"\n  STR_NEWSEEDONLOAD: \"Zufallsgenerator zurücksetzen\"\n  STR_NEWSEEDONLOAD_DESC: \"Wenn ein Spielstand geladen wird, wird der Zufallsgenerator zurückgesetzt, sodass dieselbe Aktion zu verschiedenen Ergebnissen führen kann. Dies betrifft nicht den Ironman-Modus.\"\n  STR_CHANGEVALUEBYMOUSEWHEEL: \"Werte durch Drehen am Maus-Rad verändern\"\n  STR_CHANGEVALUEBYMOUSEWHEEL_DESC: \"Einstellbare Werte können um den angegebenen Betrag mithilfe des Mausrads geändert werden.\"\n  STR_BATTLEHAIRBLEACH: \"Verbesserte Soldaten-Darstellung\"\n  STR_BATTLEHAIRBLEACH_DESC: \"Darstellung der Soldaten in der Gefechtskarte entspricht dem Aussehen im Inventar-Bildschirm.\"\n  STR_DRAGSCROLLINVERT: \"Bildschirm-Verschieben invertieren\"\n  STR_DRAGSCROLLINVERT_DESC: \"Wenn aktiviert, wird das Ziehen des Bildschirms mit der Maus invertiert.\"\n  STR_BATTLESCAPE_SCALE: \"Auflösung Gefechtskarte\"\n  STR_BATTLESCAPE_SCALE_DESC: \"Ändert die Ansicht der taktischen Gefechtskarte, basierend an einer festen Auflösung (Bildschirm strecken), oder einer festen Zoomstufe (Vergrößern).\"\n  STR_GEOSCAPE_SCALE: \"Auflösung Weltkarte\"\n  STR_GEOSCAPESCALE_SCALE_DESC: \"Ändert die Ansicht der Weltkarte, basierend an einer festen Auflösung (Bildschirm strecken), oder einer festen Zoomstufe (Vergrößern).\"\n  STR_1_5X: \"1.5x Original\"\n  STR_2X: \"2x Original\"\n  STR_THIRD_DISPLAY: \"1/3 Darstellung\"\n  STR_HALF_DISPLAY: \"1/2 Darstellung\"\n  STR_FULL_DISPLAY: \"Volle Darstellung\"\n  STR_FPS_LIMIT: \"FPS Begrenzung\"\n  STR_FPS_LIMIT_DESC: \"Begrenzt die Anzahl der Bildwiederholungen pro Sekunde. 0 steht für keine Begrenzung. Wenn die OpenGL-Darstellung eingeschaltet ist, benutzt das Spiel Vsync stattdessen.\"\n  STR_FPS_INACTIVE_LIMIT: \"FPS Hintergrund Begrenzung\"\n  STR_FPS_INACTIVE_LIMIT_DESC: \"Begrenzt die Anzahl der Bildwiederholung pro Sekunde, wenn OpenXcom im Hintergrund aktiv ist.\"\n  STR_NOALIENPANICMESSAGES: \"Paniknachrichten für Außerirdische unterdrücken\"\n  STR_NOALIENPANICMESSAGES_DESC: \"Zeigt Paniknachrichten nur für sichtbare Außerirdische an\"\n  STR_ALIENBLEEDING: \"Verblutende Außerirdische\"\n  STR_ALIENBLEEDING_DESC: \"Ein Großteil der Außerirdischen kann tödlich verwundet werden\"\n  STR_FIELDPROMOTIONS: \"Missionsbezogene Beförderung\"\n  STR_FIELDPROMOTIONS_DESC: \"Nur Soldaten, die bei der Mission anwesend waren, sind für eine Beförderung berechtigt.\"\n  STR_MEETINGPOINT: \"UFO-Flugbahn vorausberechnen\"\n  STR_MEETINGPOINT_DESC: \"Schiffe fliegen mit dem UFO zu einem Treffpunkt, basierend auf seiner derzeitigen Flugbahn.\"\n  STR_IRONMAN: \"IRONMAN\"\n  STR_IRONMAN_DESC: \"Kein manuelles Speichern\"\n  STR_SAVE_AND_ABANDON_GAME: \"SPEICHERN UND SPIEL VERLASSEN\"\n  STR_MOD_UNSUCCESSFUL: \"Mod konnte nicht geladen werden\"\n  STR_NEW_SAVED_GAME_SLOT: \"<NEUER SPIELSTAND>\"\n  STR_AUTO_SAVE_GEOSCAPE_SLOT: \"<AUTOSAVE WELTKARTE>\"\n  STR_AUTO_SAVE_BATTLESCAPE_SLOT: \"<AUTOSAVE GEFECHTSKARTE>\"\n  STR_QUICK_SAVE_SLOT: \"<SCHNELLSPEICHERN>\"\n  STR_DISPLAY_MODE_DESC: \"Darstellungsmodus ändern.\"\n  STR_PREFERRED_MUSIC_FORMAT: \"Audio Format\"\n  STR_PREFERRED_MUSIC_FORMAT_DESC: \"Wähle ein bevorzugtes Audio-Format, wenn mehrere zur Verfügung stehen.{NEWLINE}PS: MIDI kann unter Windows fehlerhaft sein.\"\n  STR_PREFERRED_SFX_FORMAT: \"SFX Format\"\n  STR_PREFERRED_SFX_FORMAT_DESC: \"Wähle ein bevorzugtes Audio-Format, wenn mehrere zur Verfügung stehen.\"\n  STR_PREFERRED_VIDEO_FORMAT: \"Video Format\"\n  STR_PREFERRED_VIDEO_FORMAT_DESC: \"Wähle ein bevorzugtes Video Format, wenn mehrere zur Verfügung stehen.\"\n  STR_PREFERRED_VIDEO_ANIMATION: \"Animation\"\n  STR_PREFERRED_VIDEO_SLIDESHOW: \"Diashow\"\n  STR_PREFERRED_FORMAT_AUTO: \"Automatisch\"\n  STR_CURRENT_FORMAT: \"Aktuell: {0}\"\n  STR_SOUND_OPTIONS: \"Audio-Optionen\"\n  STR_BACKGROUND_MUTE: \"Hintergrund Stummschaltung\"\n  STR_BACKGROUND_MUTE_DESC: \"Spiel stummschalten, wenn das Fenster nicht aktiv ist\"\n  STR_FORCE_FIRE: \"Erzwungener Feuerbefehl\"\n  STR_FORCE_FIRE_DESC: \"Aktiviert, zwingt es ihre Soldaten bei gedrückter STRG-Taste zu Schießen, selbst wenn keine freie Schussbahn besteht.\"\n  STR_NO_AUDIO_HARDWARE_DETECTED: \"Keine Soundkarte gefunden\"\n  STR_MOUSEWHEEL_SPEED: \"Mausrad Scrollgeschwindigkeit\"\n  STR_MOUSEWHEEL_SPEED_DESC: \"Bestimmt wie viele Reihen mit jeder Stufe des Mausrades gescrollt werden.\"\n  STR_DISABLED: \"Deaktiviert\"\n  STR_MAXIMIZE_INFO_SCREENS: \"Informationsbildschirme Maximieren\"\n  STR_MAXIMIZE_INFO_SCREENS_DESC: \"Inventar und verschiedene andere Bildschirme werden im Vollbildmodus angezeigt, unabhängig von der Größen Einstellungen.\"\n  STR_DIARY: \"TAGEBUCH\"\n  STR_KILLED: \"GETÖTET\"\n  STR_STUNNED: \"BETÄUBT\"\n  STR_PANICKED: \"IN PANIK\"\n  STR_MINDCONTROLLED: \"GESTEUERT\"\n  STR_REGION_UNKNOWN: \"Geheim\"\n  STR_WEAPON_UNKNOWN: \"Improvisation\"\n  STR_UNKNOWN: \"Unbekannt\"\n  STR_VICTORY: \"Sieg\"\n  STR_DEFEAT: \"Niederlage\"\n  STR_NO_RECORD: \"Keine Aufzeichnungen\"\n  STR_HUMAN: \"Mensch\"\n  STR_FRIENDLY: \"Befreundet\"\n  STR_HOSTILE: \"Feindlich\"\n  STR_NEUTRAL: \"Neutral\"\n  STR_RATING_UC: \"BEWERTUNG\"\n  STR_LOCATION: \"ORT> {ALT}{0}\"\n  STR_DAYLIGHT_TYPE: \"ZEIT> {ALT}{0}\"\n  STR_RACE_TYPE: \"RASSE> {ALT}{0}\"\n  STR_DAY: \"Tag\"\n  STR_NIGHT: \"Nacht\"\n  STR_DAYS_WOUNDED: \"TAGE VERWUNDET> {ALT}{0}\"\n  STR_COMBAT: \"KAMPF\"\n  STR_PERFORMANCE: \"LEISTUNG\"\n  STR_NEUTRALIZATIONS_BY_RACE: \"NEUTRALISIERUNGEN NACH RASSE\"\n  STR_NEUTRALIZATIONS_BY_RANK: \"NEUTRALISIERUNGEN NACH RANG\"\n  STR_NEUTRALIZATIONS_BY_WEAPON: \"NEUTRALISIERUNGEN NACH WAFFE\"\n  STR_MISSIONS_BY_LOCATION: \"MISSIONEN NACH ORT\"\n  STR_MISSIONS_BY_TYPE: \"MISSIONEN NACH TYP\"\n  STR_MISSIONS_BY_UFO: \"MISSIONEN NACH UFO\"\n  STR_SCORE_VALUE: \"PUNKTE>{ALT}{0}\"\n  STR_WINS: \"SIEGE> {ALT}{0}\"\n  STR_STUNS: \"BETÄUBUNGEN>{ALT}{0}\"\n  STR_PANICKS: \"PANIKEN> {ALT}{0}\"\n  STR_MINDCONTROLS: \"STEUERUNGEN> {ALT}{0}\"\n  STR_AWARDS: \"AUSZEICHNUNGEN\"\n  STR_COMMENDATIONS_UC: \"AUSZEICHNUNGEN\"\n  STR_COMMENDATIONS: \"Auszeichnungen\"\n  STR_MEDALS: \"MEDAILLEN\"\n  STR_LOST_IN_SERVICE: \"IM DIENST VERMISST\"\n  STR_MEDAL_NAME: \"Medaillen-Name\"\n  STR_MEDAL_AWARD_LEVEL: \"Auszeichnungs-Grad\"\n  STR_MEDAL_DECOR_LEVEL: \"Orden-Grad\"\n  STR_AWARD_0: \"Erste Auszeichnung\"\n  STR_AWARD_1: \"Zweite Auszeichnung\"\n  STR_AWARD_2: \"Dritte Auszeichnung\"\n  STR_AWARD_3: \"Vierte Auszeichnung\"\n  STR_AWARD_4: \"Fünfte Auszeichnung\"\n  STR_AWARD_5: \"Sechste Auszeichnung\"\n  STR_AWARD_6: \"Siebte Auszeichnung\"\n  STR_AWARD_7: \"Achte Auszeichnung\"\n  STR_AWARD_8: \"Neunte Auszeichnung\"\n  STR_AWARD_9: \"Zehnte Auszeichnung\"\n  STR_AWARD_DECOR_0: \"Keine\"\n  STR_AWARD_DECOR_1: \"Erste Bronzenadel\"\n  STR_AWARD_DECOR_2: \"Zweite Bronzenadel\"\n  STR_AWARD_DECOR_3: \"Dritte Bronzenadel\"\n  STR_AWARD_DECOR_4: \"Erste Silbernadel\"\n  STR_AWARD_DECOR_5: \"Zweite Silbernadel\"\n  STR_AWARD_DECOR_6: \"Dritte Silbernadel\"\n  STR_AWARD_DECOR_7: \"Erste Goldnadel\"\n  STR_AWARD_DECOR_8: \"Zweite Goldnadel\"\n  STR_AWARD_DECOR_9: \"Dritte Goldnadel\"\n  STR_KILLED_IN_ACTION_MALE: \"IM EINSATZ GETÖTET\"\n  STR_KILLED_IN_ACTION_FEMALE: \"IM EINSATZ GETÖTET\"\n  STR_MISSING_IN_ACTION_MALE: \"IM EINSATZ VERMISST\"\n  STR_MISSING_IN_ACTION_FEMALE: \"IM EINSATZ VERMISST\"\n  STR_AVERAGE_MONTHLY_RATING: \"Durchschnittliche monatliche Bewertung\"\n  STR_TOTAL_INCOME: \"Gesamteinkommen\"\n  STR_TOTAL_EXPENDITURE: \"Gesamtausgaben\"\n  STR_MISSIONS_WON: \"Abgeschlossene Missionen\"\n  STR_MISSIONS_LOST: \"Fehlgeschlagene Missionen\"\n  STR_NIGHT_MISSIONS: \"Nachteinsätze\"\n  STR_BEST_RATING: \"Beste Missionsbewertung\"\n  STR_WORST_RATING: \"Schlechteste Missionsbewertung\"\n  STR_ALIEN_KILLS: \"Getötete Außerirdische\"\n  STR_ALIEN_CAPTURES: \"Gefangene Außerirdische\"\n  STR_FRIENDLY_KILLS: \"Vorfälle mit \\\"Friendly fire\\\"\"\n  STR_AVERAGE_ACCURACY: \"Durchschnittliche Genauigkeit\"\n  STR_WEAPON_MOST_KILLS: \"Effektivste Waffe\"\n  STR_ALIEN_MOST_KILLS: \"Tödlichster Außerirdischer\"\n  STR_LONGEST_SERVICE: \"Längste Dienstzeit\"\n  STR_TOTAL_DAYS_WOUNDED: \"Krankheitstage\"\n  STR_COUNTRIES_LOST: \"Infiltrierte Länder\"\n  STR_TOTAL_TERROR_SITES: \"Terrorangriffe\"\n  STR_TOTAL_BASES: \"Gebaute Basen\"\n  STR_TOTAL_CRAFT: \"Fahrzeuge im Besitz\"\n  STR_TOTAL_SCIENTISTS: \"Angeheuerte Wissenschaftler\"\n  STR_TOTAL_ENGINEERS: \"Angeheuerte Ingenieure\"\n  STR_TOTAL_RESEARCH: \"Abgeschlossene Forschungsprojekte\"\n  STR_DIARY_ACCURACY: \"GENAUIGKEIT> {ALT}{0}%\"\n  STR_STATISTICS: \"Statistiken\"\n  STR_STATS: \"STATISTIKEN\"\n  STR_TIME_UNITS_ABBREVIATION: \"ZEs\"\n  STR_STAMINA_ABBREVIATION: \"EN\"\n  STR_HEALTH_ABBREVIATION: \"TP\"\n  STR_BRAVERY_ABBREVIATION: \"MUT\"\n  STR_REACTIONS_ABBREVIATION: \"REA\"\n  STR_FIRING_ACCURACY_ABBREVIATION: \"SG\"\n  STR_THROWING_ACCURACY_ABBREVIATION: \"WG\"\n  STR_STRENGTH_ABBREVIATION: \"STÄ\"\n  STR_MELEE_ACCURACY_ABBREVIATION: \"NK\"\n  STR_FOLDERS: \"VERZEICHNISSE\"\n  STR_DATA_FOLDER: \"Daten-Ordner (original Daten)\"\n  STR_USER_FOLDER: \"Benutzer-Ordner (Mods, openxcom.log)\"\n  STR_SAVE_FOLDER: \"Speicher-Ordner (Spielstände, Screenshots)\"\n  STR_CONFIG_FOLDER: \"Config-Ordner (options.cfg)\"\n  STR_DATA_FOLDER_DESC_1: \"Hier sucht OpenXcom nach den ursprünglichen Spielressourcen (UFO und/oder TFTD).\"\n  STR_DATA_FOLDER_DESC_2: \"OpenXcom-interne Ressourcen befinden sich im 'common'-Ordner. Die in OpenXcom integrierten Mods befinden sich im 'standard'-Ordner \"\n  STR_USER_FOLDER_DESC: \"Die Logdatei ('openxcom.log') wird hier gespeichert. Alle benutzerdefinierten Mods gehören ebenfalls hierher (in den Unterordner 'mods').\"\n  STR_SAVE_FOLDER_DESC: \"Ihre gespeicherten Spielstände befinden sich hier. Auch die Einstellungen für den Missionsgenerator ('battle.cfg') sind hier zu finden.\"\n  STR_CONFIG_FOLDER_DESC: \"Hier werden die OpenXcom-Einstellungen ('options.cfg') gespeichert. Normalerweise ist dies derselbe Ordner wie der Benutzerordner.\"\n"
  },
  {
    "path": "bin/common/Language/el.yml",
    "content": "el:\n  STR_OPENXCOM: \"OpenXcom\"\n  STR_NEW_GAME: \"Νέο Παιχνίδι\"\n  STR_LOAD_SAVED_GAME: \"Φόρτωση Παιχνιδιού\"\n  STR_SELECT_DIFFICULTY_LEVEL: \"Επέλεξε Επίπεδο Δυσκολίας\"\n  STR_1_BEGINNER: \"1> Αρχάριος\"\n  STR_2_EXPERIENCED: \"2> Έμπειρος\"\n  STR_3_VETERAN: \"3> Βετεράνος\"\n  STR_4_GENIUS: \"4> Διάνοια\"\n  STR_5_SUPERHUMAN: \"5> Υπεράνθρωπος\"\n  STR_TIME: \"Ώρα\"\n  STR_DATE: \"Ημέρα\"\n  STR_SELECT_GAME_TO_LOAD: \"Επέλεξε παιχνίδι για φόρτωση\"\n  STR_SELECT_SAVE_POSITION: \"Επέλεξε θέση αποθήκευσης\"\n  STR_GAME_OPTIONS: \"ΕΠΙΛΟΓΕΣ ΠΑΙΧΝΙΔΙΟΥ\"\n  STR_LOAD_GAME: \"ΦΟΡΤΩΣΗ ΠΑΙΧΝΙΔΙΟΥ\"\n  STR_SAVE_GAME: \"ΑΠΟΘΗΚΕΥΣΗ ΠΑΙΧΝΙΔΙΟΥ\"\n  STR_ABANDON_GAME: \"ΕΓΚΑΤΑΛΗΨΗ ΠΑΙΧΝΙΔΙΟΥ\"\n  STR_ABANDON_GAME_QUESTION: \"ΕΓΚΑΤΑΛΗΨΗ ΠΑΙΧΝΙΔΙΟΥ;\"\n  STR_QUIT: \"Παραίτηση\"\n  STR_SAVING_GAME: \"Αποθήκευση Παιχνιδιού\"\n  STR_LOADING_GAME: \"Φόρτωση Παιχνιδιού\"\n  STR_NO_SAVED_GAME_PRESENT: \"Δεν υπάρχουν αποθηκευμένα παιχνίδια\"\n  STR_LOAD_UNSUCCESSFUL: \"Η φόρτωση απέτυχε\"\n  STR_SAVE_UNSUCCESSFUL: \"Η αποθήκευση απέτυχε\"\n  STR_LOAD_SUCCESSFUL: \"Επιτυχής φόρτωση\"\n  STR_SAVE_SUCCESSFUL: \"Επιτυχής αποθήκευση\"\n  STR_DELETE: \"ΔΙΑΓΡΑΦΗ\"\n  STR_DELETE_UNSUCCESSFUL: \"Διαγραφή απέτυχε\"\n  STR_IS_IT_OK_TO_DELETE_THE_SAVED_GAME: \"Είσαι σίγουρος ότι θέλεις να διαγράψεις το αποθηκευμένο παιχνίδι;\"\n  STR_ORIGINAL_XCOM: \"Original X-Com\"\n  STR_LOADING: \"Φόρτωση...\"\n  STR_DETAILS: \"Λεπτομέριες> {ALT}{0}\"\n  STR_NEW_BATTLE: \"Νέα Μάχη\"\n  STR_OPTIONS: \"Επιλογές\"\n  STR_RIGHT_CLICK_TO_DELETE: \"Δεξί κλικ για διαγραφή\"\n  STR_RESTORE_DEFAULTS: \"Επαναφορά Προεπιλογών\"\n  STR_CONTROLS: \"ΧΕΙΡΙΣΜΟΙ\"\n  STR_GENERAL: \"Γενικά\"\n  STR_GEOSCAPE: \"Γεοτοπίο\"\n  STR_BATTLESCAPE: \"Πεδίο Μάχης\"\n  STR_SCREENSHOT: \"Στιγμιότυπο Οθόνης\"\n  STR_FPS_COUNTER: \"Μετρητής FPS\"\n  STR_ROTATE_LEFT: \"Περιστροφή Αριστερά\"\n  STR_ROTATE_RIGHT: \"Περιστροφή Δεξιά\"\n  STR_ROTATE_UP: \"Περιστροφή Πάνω\"\n  STR_ROTATE_DOWN: \"Περιστροφή Κάτω\"\n  STR_ZOOM_IN: \"Μεγέθυνση\"\n  STR_ZOOM_OUT: \"Σμίκρυνση\"\n  STR_TOGGLE_COUNTRY_DETAIL: \"Εμφάνιση Λεπτομερειών Χώρας\"\n  STR_TOGGLE_RADAR_RANGES: \"Εμφάνηση Εμβέλειας Ραντάρ\"\n  STR_SCROLL_LEFT: \"Κύλιση Αριστερά\"\n  STR_SCROLL_RIGHT: \"Κύλιση Δεξιά\"\n  STR_SCROLL_UP: \"Κύλιση Πάνω\"\n  STR_SCROLL_DOWN: \"Κύλιση Κάτω\"\n  STR_UNIT_LEVEL_ABOVE: \"Μετακίνησε την Μονάδα στο Πάνω Επίπεδο \"\n  STR_UNIT_LEVEL_BELOW: \"Μετακίνησε την Μονάδα στο Κάτω Επίπεδο \"\n  STR_VIEW_LEVEL_ABOVE: \"Δες το Πάνω Επίπεδο\"\n  STR_VIEW_LEVEL_BELOW: \"Δες το Κάτω Επίπεδο\"\n  STR_CENTER_SELECTED_UNIT: \"Κέντραρε στην Επιλεγμένη Μονάδα\"\n  STR_PREVIOUS_UNIT: \"Επέλεξε την Προηγούμενη Μονάδα\"\n  STR_NEXT_UNIT: \"Επέλεξε την Επόμενη Μονάδα\"\n  STR_DESELECT_UNIT: \"Μην Ξαναεπιλέξεις τη Μονάδα\"\n  STR_USE_LEFT_HAND: \"Χρήση Αντικειμένου Αριστερού Χεριού\"\n  STR_USE_RIGHT_HAND: \"Χρήση Αντικειμένου Δεξιού Χεριού\"\n  STR_INVENTORY: \"Εξοπλισμός\"\n  STR_MINIMAP: \"Μικρός Χάρτης\"\n  STR_MULTI_LEVEL_VIEW: \"Πολυεπίπεδη Όψη\"\n  STR_END_TURN: \"Τέλος Γύρου\"\n  STR_ABORT_MISSION: \"Ματαίωση Αποστολής\"\n  STR_UNIT_STATS: \"Στατιστικά Μονάδας\"\n  STR_KNEEL: \"Γονάτισε\"\n  STR_RELOAD: \"Ξαναγέμισε\"\n  STR_TOGGLE_PERSONAL_LIGHTING: \"Εμφάνιση Προσωπικού Φωτισμού\"\n  STR_DONT_RESERVE_TIME_UNITS: \"Μην Φυλάς Μονάδες Χρόνου\"\n  STR_RESERVE_TIME_UNITS_FOR_SNAP_SHOT: \"Φύλαξη ΜΧ για Γρήγορη Βολή\"\n  STR_RESERVE_TIME_UNITS_FOR_AIMED_SHOT: \"Φύλαξη ΜΧ για Στοχευμένη Βολή\"\n  STR_RESERVE_TIME_UNITS_FOR_AUTO_SHOT: \"Φύλαξε ΜΧ για Αυτόματη Βολή\"\n  STR_CENTER_ON_ENEMY_1: \"Κέντραρε στον Εχθρό 1\"\n  STR_CENTER_ON_ENEMY_2: \"Κέντραρε στον Εχθρό 2\"\n  STR_CENTER_ON_ENEMY_3: \"Κέντραρε στον Εχθρό 3\"\n  STR_CENTER_ON_ENEMY_4: \"Κέντραρε στον Εχθρό 4\"\n  STR_CENTER_ON_ENEMY_5: \"Κέντραρε στον Εχθρό 5\"\n  STR_CENTER_ON_ENEMY_6: \"Κέντραρε στον Εχθρό 6\"\n  STR_CENTER_ON_ENEMY_7: \"Κέντραρε στον Εχθρό 7\"\n  STR_CENTER_ON_ENEMY_8: \"Κέντραρε στον Εχθρό 8\"\n  STR_CENTER_ON_ENEMY_9: \"Κέντραρε στον Εχθρό 9\"\n  STR_CENTER_ON_ENEMY_10: \"Κέντραρε στον Εχθρό 10\"\n  STR_CREATE_INVENTORY_TEMPLATE: \"Δημιουργία πρότυπου εξοπλισμού\"\n  STR_APPLY_INVENTORY_TEMPLATE: \"Εφαρμογή πρότυπου εξοπλισμού\"\n  STR_CLEAR_INVENTORY: \"Απομάκρυνση εξοπλισμού\"\n  STR_AUTO_EQUIP: \"Άυτο-εφαρμογή\"\n  STR_QUICK_SAVE: \"Γρήγορη Αποθήκευση\"\n  STR_QUICK_LOAD: \"Γρήγορη Φόρτωση\"\n  STR_ADVANCED: \"ΠΡΟΗΓΜΕΝΕΣ\"\n  STR_AGGRESSIVERETALIATION: \"Δυναμική αντεπίθεση\"\n  STR_AGGRESSIVERETALIATION_DESC: \"ΑΤΙΑ θα προσπαθήσουν να εντοπίσουν τις βάσεις σου συνεχώς, ανεξαρτήτως από τις παραμέτρους των αποστολών τους.\"\n  STR_STORAGELIMITSENFORCED: \"Όρια αποθήκευσης για ανακτημένα αντικείμενα\"\n  STR_STORAGELIMITSENFORCED_DESC: \"Επιβάλλει περιορισμό εξωγήινων και γενικά όρια αποθήκευσης για ζωντανούς εξωγήινους και κατασχεμένα αντικείμενα από αποστολές\"\n  STR_CANSELLLIVEALIENS: \"Πώληση ζωντανών εξωγήινων\"\n  STR_CANSELLLIVEALIENS_DESC: \"Επιτρέπει την πώληση ζωντανών εξωγήινων, συνιστάται όταν δεν φτάνουν οι χώροι αποθήκευσης.\"\n  STR_ALLOWBUILDINGQUEUE: \"Επέτρεψε ουρά παραγωγής\"\n  STR_ALLOWBUILDINGQUEUE_DESC: \"Νέες εγκαταστάσεις μπορούν να τοποθετηθούν δίπλα σε ημιτελείς.\"\n  STR_BATTLEAUTOEND: \"Αυτόματος τερματισμος μάχης\"\n  STR_BATTLEAUTOEND_DESC: \"Οι μάχες λήγουν αυτόματα όταν ο τελευταίος εχθρός εξουδετερωθεί.\"\n  STR_BATTLEINSTANTGRENADE: \"Στιγμιαίες Χειροβομβίδες\"\n  STR_BATTLEINSTANTGRENADE_DESC: \"Χειροβομβίδες έτοιμες για ενεργοποίηση σε 0 γύρους θα ανατινάζονται άμεσα οταν ρίχνονται, αντι να το κάνουν στο τέλος το γύρου.\"\n  STR_BATTLEUFOEXTENDERACCURACY: \"Επεκτατής ακρίβειας UFO\"\n  STR_BATTLEUFOEXTENDERACCURACY_DESC: \"Η ακρίβεια των βολών μειώνεται μετά από μια ορισμένη απόσταση, ανάλογα με τον τύπο βολής. Η προσαρμοσμένη ακρίβεια θα εμφανίζεται στον κέρσορα.\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE: \"Αερομεταφορές\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE_DESC: \"Αεροσκάφη εν πτήσει μπορούν να μεταφερθούν.\"\n  STR_CRAFTLAUNCHALWAYS: \"Εξαναγκασμένη εκτόξευση σκαφών\"\n  STR_CRAFTLAUNCHALWAYS_DESC: \"Τα σκάφη μπορούν να εκτοξευθούν ακόμα και όταν δεν είναι έτοιμα, παρακάμπτοντας την ανάγκη συντήρησης.\"\n  STR_CUSTOMINITIALBASE: \"Προσαρμοσμένη αρχική βάση\"\n  STR_CUSTOMINITIALBASE_DESC: \"Όταν ξεκινάτε ένα νέο παιχνίδι, μπορείτε να τοποθετήσετε χειροκίνητα τις εγκαταστάσεις εκκίνησης αντί να χρησιμοποιήσετε την προεπιλεγμένη διάταξη.\"\n  STR_GLOBESEASONS: \"Ρεαλιστικός Φωτισμός Υδρογείου\"\n  STR_GLOBESEASONS_DESC: \"Χρησιμοποιεί πιο ρεαλιστική προβολή του ηλιακού φωτός στο Geoscape σύμφωνα με την αξονική κλίση της Γης.\"\n  STR_PLAYINTRO: \"Δείξε την εισαγωγή\"\n  STR_PLAYINTRO_DESC: \"Εμφάνιση της εισαγωγής κατα την εκκίνηση.\"\n  STR_SHOWMORESTATSININVENTORYVIEW: \"Στατιστικά Εξοπλισμού\"\n  STR_SHOWMORESTATSININVENTORYVIEW_DESC: \"Δείξε επιπλέον πληροφορίες σχετικά με τον επιλεγμένο στρατιώτη στην οθόνη εξοπλισμού.\"\n  STR_SNEAKYAI: \"Ύπουλη τεχνιτή νοημοσύνη\"\n  STR_SNEAKYAI_DESC: \"Η τεχνητή νοημοσύνη αποφεύγει να αποκαλυφθεί στον παίκτη όποτε είναι δυνατόν.\"\n  STR_STRAFE: \"Εναλλακτικοί τρόποι κίνησης\"\n  STR_STRAFE_DESC: \"Επιτρέπει την πλάγεια κίνηση, το τρέξιμο και την ανεξάρτητη κίνηση του πύργου του τανκ όταν κρατάτε πατημένο το CTRL.\"\n  STR_BATTLEEXPLOSIONHEIGHT: \"Ύψος Έκρηξης\"\n  STR_BATTLEEXPLOSIONHEIGHT_DESC: \"Αλλαγή ύψους που μπορούν να εξαπλωθούν οι εκρήξεις.{NEWLINE}(Επίπεδο: 0, Κυκλικό: 3)\"\n  STR_AUTOSAVE: \"ΑΥΤΟΜΑΤΗ ΑΠΟΘΗΚΕΥΣΗ\"\n  STR_AUTOSAVE_DESC: \"Αυτόματη αποθήκευση του παιχνιδιού σε καθορισμένα χρονικά διαστήματα. Δεν ισχύει για το Ironman Mode.\"\n  STR_AUTOSAVE_FREQUENCY: \"Συχνότητα αυτόματης αποθήκευσης\"\n  STR_AUTOSAVE_FREQUENCY_DESC: \"Αριθμός σειρών μετά τις οποίες το παιχνίδι θα αποθηκευτεί αυτόματα.\"\n  STR_ALLOWPSIONICCAPTURE: \"Επέτρεψε την ψυχοαιχμαλωσία\"\n  STR_ALLOWPSIONICCAPTURE_DESC: \"Έλεγχος του νου των εναπομήνοντων εξωγήινων θα έχει ως αποτέλεσμα τη νίκη, και θα μετρούν σαν αιχμάλωτοι. \"\n  STR_ANYTIMEPSITRAINING: \"Ψυονική εξάσκηση οποτεδήποτε\"\n  STR_ANYTIMEPSITRAINING_DESC: \"Επιτρέπει την τοποθέτηση στρατιωτών σε ψυονική εκπαίδευση σε οποιαδήποτε στιγμή του μήνα. Να θυμάστε, η αρχική εκπαίδευση διαρκεί 30 με 60 ημέρες.\"\n  STR_SKIPNEXTTURNSCREEN: \"Παράλειψη της οθόνης \\\"Επόμενη σειρά\\\".\"\n  STR_SKIPNEXTTURNSCREEN_DESC: \"Οι οθόνες \\\"Επόμενη σειρά\\\" κατά τη διάρκεια της μάχης προωθούνται αυτόματα μετά από μια μικρή καθυστέρηση.\"\n  STR_NOT_ENOUGH_SPACE: \"Ανεπαρκής Χώρος!\"\n  STR_WEAPONSELFDESTRUCTION: \"Αυτοκαταστροφή εξωγηινού οπλού\"\n  STR_WEAPONSELFDESTRUCTION_DESC: \"Τα όπλα που φέρουν οι εξωγήινοι θα αυτοκαταστραφούν εάν ο ιδιοκτήτης τους σκοτωθεί, όπως στο XCOM 2012.\"\n  STR_RETAINCORPSES: \"Διατηρήστε τους εξωγήινους που ανακρίθηκαν\"\n  STR_RETAINCORPSES_DESC: \"Μετά από «έρευνα» ζωντανών εξωγήινων, το σώμα θα προστεθεί στα βασικά καταστήματα, όπως στο XCOM 2012.\"\n  STR_SAVE_VOXEL_VIEW: \"Σώσε στιγμιότυπο πρώτου προσώπου\"\n  STR_RESERVE_TIME_UNITS_FOR_KNEEL: \"Φύλαξε ΜΧ για Γονάτισμα\"\n  STR_EXPEND_ALL_TIME_UNITS: \"Χρήση όλων των υπόλοιπων ΜΧ\"\n  STR_PSISTRENGTHEVAL: \"Αξιολόγηση Ψιονικής Δύναμης (Ψι-Δύναμη)\"\n  STR_PSISTRENGTHEVAL_DESC: \"Αξιολογεί την ψυχική ισχύ όλων των στρατιωτών αφού ολοκληρωθεί η κατάλληλη έρευνα.\"\n  STR_DISABLEAUTOEQUIP: \"Απενεργοποίηση αυτόματου εξοπλισμού\"\n  STR_DISABLEAUTOEQUIP_DESC: \"Απενεργοποίηση τού αυτόματoυ εξοπλισμού των νέων στρατιωτών πρίν τη μάχη\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT: \"Επιτρέψτε τη βελτίωση της δύναμης Ψ\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT_DESC: \"Η ψυχική δύναμη των στρατιωτών μπορεί να βελτιωθεί με την εμπειρία και την κατάρτιση.\"\n  STR_BATTLESMOOTHCAMERA: \"Κάμερα Ομαλής Βολίδας\"\n  STR_BATTLESMOOTHCAMERA_DESC: \"Η εικόνα πεδίου μάχης θα παραμείνει κεντραρισμένη στα βλήμματα, όσο αυτά ταξιδεύουν.\"\n  STR_BATTLECONFIRMFIREMODE: \"Επιβεβαίωση μεθόδου πυρός\"\n  STR_BATTLECONFIRMFIREMODE_DESC: \"Απαιτήστε ένα δεύτερο κλικ στο ίδιο εικονίδιο για να επιβεβαιώσετε τις εντολές πυρών.\"\n  STR_SELECT_BASE_1: \"Επιλογή Βάσης 1\"\n  STR_SELECT_BASE_2: \"Επιλογή Βάσης 2\"\n  STR_SELECT_BASE_3: \"Επιλογή Βάσης 3\"\n  STR_SELECT_BASE_4: \"Επιλογή Βάσης 4\"\n  STR_SELECT_BASE_5: \"Επιλογή Βάσης 5\"\n  STR_SELECT_BASE_6: \"Επιλογή Βάσης 6\"\n  STR_SELECT_BASE_7: \"Επιλογή Βάσης 7\"\n  STR_SELECT_BASE_8: \"Επιλογή Βάσης 8\"\n  STR_VIDEO: \"ΕΙΚΟΝΑ\"\n  STR_AUDIO: \"ΗΧΟΣ\"\n  STR_BATTLESCAPE_UC: \"ΠΕΔΙΟ ΜΑΧΗΣ\"\n  STR_MODS_UC: \"MODS\"\n  STR_MODS: \"Mods\"\n  STR_DISPLAY_RESOLUTION: \"Ανάλυση\"\n  STR_DISPLAY_RESOLUTION_DESC: \"Αλλάζει την ανάλυση της οθόνης, η ανάλυση του παιχνιδιού θα αλλάξει για να ταιριάζει. Τα βέλη εναλλάσσονται μεταξύ των υποστηριζόμενων αναλύσεων. Κάντε κλικ για να εισαγάγετε μια προσαρμοσμένη ανάλυση.\"\n  STR_ORIGINAL: \"Αρχικό\"\n  STR_DISPLAY_MODE: \"Τρόπος Προβολής\"\n  STR_WINDOWED: \"Σε παράθυρο\"\n  STR_FULLSCREEN: \"Πλήρης Οθόνη\"\n  STR_BORDERLESS: \"Χωρίς περιθώρια\"\n  STR_DISPLAY_LANGUAGE: \"Γλώσσα Προβολής\"\n  STR_DISPLAY_LANGUAGE_DESC: \"Αλλάζει τη γλώσσα του κειμένου στο παιχνίδι.\"\n  STR_DISPLAY_FILTER: \"Φίλτρο Προβολής\"\n  STR_DISPLAY_FILTER_DESC: \"Αλλάζει το φίλτρο που εφαρμόζεται στην οθόνη του παιχνιδιού.{NEWLINE}*απαιτείται OpenGL hardware acceleration.\"\n  STR_DISPLAY_OPTIONS: \"Επιλογές Προβολής\"\n  STR_LETTERBOXED: \"Γραμματοκιβώτιο\"\n  STR_LETTERBOXED_DESC: \"Χαρακτηρίζει την οθόνη για να διατηρεί την αρχική αναλογία διαστάσεων.\"\n  STR_RESIZABLE: \"Αλλαγή μεγέθους\"\n  STR_LOCK_MOUSE: \"Πιάστε το ποντίκι\"\n  STR_LOCK_MOUSE_DESC: \"Εμποδίζει τον κέρσορα του ποντικιού να φύγει από το παράθυρο του παιχνιδιού. Ctrl+G για εναλλαγή οποιαδήποτε στιγμή.\"\n  STR_FIXED_WINDOW_POSITION: \"Σταθερή θέση παραθύρου\"\n  STR_FIXED_WINDOW_POSITION_DESC: \"Ρυθμίστε τη σταθερή θέση του Παραθύρου.\"\n  STR_DISPLAY_SET_WINDOW_POSITION: \"Ρύθμιση νέας αρχικής θέσης παραθύρου\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_X: \"Αριστερό περίγραμμα νέο X:\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_Y: \"Επάνω περίγραμμα νέο Y:\"\n  STR_MUSIC_VOLUME: \"Ένταση Μουσικής\"\n  STR_MUSIC_VOLUME_DESC: \"Αλλάζει την ένταση της μουσικής παρασκηνίου.\"\n  STR_SFX_VOLUME: \"Ένταση Εφέ\"\n  STR_SFX_VOLUME_DESC: \"Αλλάζει την ένταση των ηχητικών εφέ.\"\n  STR_UI_VOLUME: \"Ήχος Χειρισμού\"\n  STR_UI_VOLUME_DESC: \"Αλλάζει την ένταση των ηχητικών σημάτων της διεπαφής.\"\n  STR_SCROLL_SPEED: \"Ταχύτητα Scroll\"\n  STR_SCROLL_SPEED_GEO_DESC: \"Αλλάζει την ταχύτητα κύλισης της υδρογείου.\"\n  STR_SCROLL_SPEED_BATTLE_DESC: \"Αλλάζει την ταχύτητα κύλισης του χάρτη.\"\n  STR_DOGFIGHT_SPEED: \"Ταχύτητα αερομαχίας\"\n  STR_DOGFIGHT_SPEED_DESC: \"Αλλάζει την ταχύτητα των μαχών αναχαίτισης ανάμεσα σε σκάφη και UFO. Οι χαμηλότερες ταχύτητες μπορούν να βελτιώσουν την απόδοση σε συσκευές χαμηλής τεχνολογίας.\"\n  STR_CLOCK_SPEED: \"Ταχύτητα Ρολογίου\"\n  STR_CLOCK_SPEED_DESC: \"Αλλάζει την ταχύτητα του ρολογιού Geoscape. Οι χαμηλότερες ταχύτητες μπορούν να βελτιώσουν την απόδοση σε συσκευές χαμηλής τεχνολογίας.\"\n  STR_GLOBE_DETAILS: \"Λεπτομέρειες Υδρογείου\"\n  STR_GLOBE_COUNTRIES: \"Χώρες\"\n  STR_GLOBE_COUNTRIES_DESC: \"Εμφανίζει τις χώρες χρηματοδότησης στον κόσμο.\"\n  STR_GLOBE_RADARS: \"Ραντάρ\"\n  STR_GLOBE_RADARS_DESC: \"Εμφανίζει εμβέλεια ραντάρ βάσης στην υδρόγειο.\"\n  STR_GLOBE_FLIGHT_PATHS: \"Δρομολόγιο Πτήσης\"\n  STR_GLOBE_FLIGHT_PATHS_DESC: \"Εμφανίζει διαδρομές πτήσης σκαφών στον κόσμο.\"\n  STR_CONTROLS_DESC: \"Κάντε αριστερό κλικ σε μια συντόμευση και πατήστε ένα πλήκτρο για να την αλλάξετε.{NEWLINE}Κάντε δεξί κλικ σε μια συντόμευση για να την απενεργοποιήσετε.\"\n  STR_BASE_GAME: \"Βασικό παιχνίδι\"\n  STR_MODS_TOOLTIP: \"Έκδοση {0} από {1}.{NEWLINE}{2}\"\n  STR_EDGE_SCROLL: \"Scroll στην άκρη της Οθόνης\"\n  STR_EDGE_SCROLL_DESC: \"Ενεργοποίηση: Κύλιση χάρτη όταν κρατάτε πατημένο το αριστερό κουμπί του ποντικιού σε μια άκρη της οθόνης.{NEWLINE}Αυτόματη: Κύλιση χάρτη όταν ο κέρσορας βρίσκεται πάνω από την άκρη της οθόνης.\"\n  STR_TRIGGER_SCROLL: \"Σκανδάλη\"\n  STR_AUTO_SCROLL: \"Κατά Ριπάς\"\n  STR_DRAG_SCROLL: \"Σύρετε την Κύλιση\"\n  STR_DRAG_SCROLL_DESC: \"Πραγματοποιεί κύλιση στον χάρτη όταν το καθορισμένο κουμπί του ποντικιού κρατηθεί πατημένο και σύρεται.\"\n  STR_LEFT_MOUSE_BUTTON: \"Αριστερό Κομβίο\"\n  STR_MIDDLE_MOUSE_BUTTON: \"Μεσαίο Κομβίο Ποντικιού\"\n  STR_RIGHT_MOUSE_BUTTON: \"Δεξί Κομβίο Ποντικιού\"\n  STR_FIRE_SPEED: \"Ταχύτητα πυρών\"\n  STR_FIRE_SPEED_DESC: \"Αλλάζει την ταχύτητα των βλημάτων.\"\n  STR_PLAYER_MOVEMENT_SPEED: \"Ταχύτητα Μετακίνησης Παίκτη\"\n  STR_PLAYER_MOVEMENT_SPEED_DESC: \"Αλλάζει την ταχύτητα κίνησης των ελεγχόμενων από τον παίκτη μονάδων.\"\n  STR_COMPUTER_MOVEMENT_SPEED: \"Ταχύτητα Κίνησης ΤΝ\"\n  STR_COMPUTER_MOVEMENT_SPEED_DESC: \"Αλλάζει την ταχύτητα κίνησης των ελεγχόμενων από υπολογιστή μονάδων.\"\n  STR_PATH_PREVIEW: \"Προεπισκόπηση Δρομολογίου\"\n  STR_PATH_ARROWS: \"Βέλη\"\n  STR_PATH_ARROWS_DESC: \"Κάνοντας κλικ εμφανίζεται η διαδρομή που θα ακολουθήσει η μονάδα σας μέχρι τον προορισμό. Το χρώμα υποδεικνύει τις διαθέσιμες ενέργειες: Πράσινο - μπορεί να κινηθεί και να ενεργοποιηθεί. Κίτρινο - μπορεί να κινηθεί. Κόκκινο - δεν μπορεί να κινηθεί.\"\n  STR_PATH_TIME_UNIT_COST: \"Μονάδες Χρόνου\"\n  STR_PATH_TIME_UNIT_COST_DESC: \"Κάνοντας κλικ εμφανίζεται η TU που θα έχει απομείνει στη μονάδα σας μετά τη μετάβαση στον προορισμό.\"\n  STR_USER_INTERFACE_OPTIONS: \"Επιλογές Χειρισμού\"\n  STR_TOOLTIPS: \"Επεξηγήσεις εργαλείων\"\n  STR_TOOLTIPS_DESC: \"Προβολή tooltip στα κομβία του Πεδίου Μάχης\"\n  STR_DEATH_NOTIFICATIONS: \"Δείξε ειδοποιήσεις θανάτων\"\n  STR_DEATH_NOTIFICATIONS_DESC: \"Δείξε ειδοποιήσεις κάθε φορά που ένας στρατιώτης σου πεθαίνει.\"\n  STR_SHOW_FUNDS: \"Εμφάνιση Κονδυλίων\"\n  STR_SHOW_FUNDS_DESC: \"Εμφανίζει τα τρέχοντα κεφάλαιά σας δίπλα στο ρολόι του Geoscape.\"\n  STR_MISSION_GENERATOR: \"Δημιουργός Αποστολών\"\n  STR_MAP_OPTIONS: \"Επιλογές Χάρτη\"\n  STR_ALIEN_OPTIONS: \"ΕΠΙΛΟΓΕΣ ΕΞΩΓΗΙΝΩΝ\"\n  STR_MAP_TERRAIN: \"Πεδίο\"\n  STR_MAP_DARKNESS: \"Σκοτεινότητα\"\n  STR_MAP_DEPTH: \"Βάθος\"\n  STR_DIFFICULTY: \"Δυσκολία\"\n  STR_ALIEN_RACE: \"Φυλή\"\n  STR_ALIEN_TECH_LEVEL: \"Επίπεδο Τεχνολογίας\"\n  STR_RANDOMIZE: \"Τυχαία Επιλογή\"\n  STR_OXCE_REQUIRED_QUESTION: \"Αυτό το mod απαιτεί το OpenXcom {0} για να εκτελεστεί σωστά. Ενεργοποίηση αυτού του mod;\"\n  STR_RESTORE_DEFAULTS_QUESTION: \"Είστε βέβαιοι ότι θέλετε να επαναφέρετε τις προεπιλεγμένες επιλογές;\"\n  STR_DISPLAY_OPTIONS_CONFIRM: \"Θέλετε να διατηρήσετε τις τρέχουσες επιλογές εμφάνισης;\"\n  STR_DISPLAY_OPTIONS_REVERT: \"Επαναφορά σε 0:{0}\"\n  STR_MISSING_CONTENT_PROMPT: \"ΠΡΟΕΙΔΟΠΟΙΗΣΗ:{SMALLLINE}Αυτή η αποθήκευση βασίζεται σε mods που δεν είναι διαθέσιμα. Το περιεχόμενο που λείπει θα αφαιρεθεί και ενδέχεται να αποτύχει η φόρτωσή του.{NEWLINE}Συνέχεια;\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT: \"Αποθηκεύστε τις προγεμισμένες χειροβομβίδες\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT_DESC: \"Αποθηκεύει χειροβομβίδες προετοιμασμένες κατά τη διάρκεια της απογραφής πριν από τη μάχη στη διάταξη εξοπλισμού του στρατιώτη.\"\n  STR_NEWSEEDONLOAD: \"Κλέψιμο μέσω Αποθήκευσης\"\n  STR_NEWSEEDONLOAD_DESC: \"Η φόρτωση ενός παιχνιδιού θα επαναφέρει τη σειρά τυχαίων αριθμών, επομένως η ίδια ενέργεια μπορεί να αποφέρει διαφορετικά αποτελέσματα. Δεν ισχύει για τη λειτουργία Ironman.\"\n  STR_CHANGEVALUEBYMOUSEWHEEL: \"Αλλαγή τιμών με τροχό του ποντικιού\"\n  STR_CHANGEVALUEBYMOUSEWHEEL_DESC: \"Σας επιτρέπει να χρησιμοποιήσετε τον τροχό του ποντικιού για να αυξήσετε/μειώσετε τις τιμές κατά αυτό το ποσό.\"\n  STR_BATTLEHAIRBLEACH: \"Βελτιωμένα γραφικά στρατιωτών\"\n  STR_BATTLEHAIRBLEACH_DESC: \"Αλλάζει τα sprites του στρατιώτη Battlescape για να ταιριάζουν με την εμφάνιση αποθέματός τους.\"\n  STR_DRAGSCROLLINVERT: \"Αντιστροφή κύλισης με σύρσιμο\"\n  STR_DRAGSCROLLINVERT_DESC: \"Όταν είναι ενεργοποιημένο, η μεταφορά κύλισης πραγματοποιεί κύλιση προς την αντίθετη κατεύθυνση από το ποντίκι.\"\n  STR_BATTLESCAPE_SCALE: \"Κλίμακα Battlescape\"\n  STR_BATTLESCAPE_SCALE_DESC: \"Λειτουργία κλιμάκωσης θύρας προβολής Battlescape, με βάση μια σταθερή ανάλυση (εκτεταμένη ώστε να ταιριάζει) ή ένα σταθερό επίπεδο ζουμ (επέκταση για πλήρωση).\"\n  STR_GEOSCAPE_SCALE: \"Κλίμακα Geoscape\"\n  STR_GEOSCAPESCALE_SCALE_DESC: \"Λειτουργία κλιμάκωσης θυρίδας προβολής Geoscape, με βάση μια σταθερή ανάλυση (εκτεταμένη ώστε να ταιριάζει) ή ένα σταθερό επίπεδο ζουμ (αναπτύχθηκε για να γεμίσει).\"\n  STR_1_5X: \"1.5 x Αρχικό\"\n  STR_2X: \"2 x Αρχικό\"\n  STR_THIRD_DISPLAY: \"1/3 Προβολή\"\n  STR_HALF_DISPLAY: \"1/2 Προβολή\"\n  STR_FULL_DISPLAY: \"Πλήρης Προβολή\"\n  STR_FPS_LIMIT: \"ΟΡΙΟ FPS\"\n  STR_FPS_LIMIT_DESC: \"Περιορίζει τον αριθμό των ενημερώσεων οθόνης ανά δευτερόλεπτο, 0 χωρίς περιορισμό. Εάν είναι ενεργοποιημένη η απόδοση OpenGL, το παιχνίδι χρησιμοποιεί το Vsync.\"\n  STR_FPS_INACTIVE_LIMIT: \"Υπόβαθρο ορίου FPS\"\n  STR_FPS_INACTIVE_LIMIT_DESC: \"Περιορίζει τον αριθμό των ενημερώσεων οθόνης ανά δευτερόλεπτο εάν το OpenXcom βρίσκεται στο παρασκήνιο.\"\n  STR_NOALIENPANICMESSAGES: \"Απόκρυψη μυνημάτων πανικού εξωγήινων\"\n  STR_NOALIENPANICMESSAGES_DESC: \"Μην εμφανίζετε μηνύματα πανικού για εξωγήινους, εκτός εάν είναι ορατά στον παίκτη.\"\n  STR_ALIENBLEEDING: \"Ο εξωγήινος αιμορραγεί\"\n  STR_ALIENBLEEDING_DESC: \"Επιτρέπει θανατηφόρα τραύματα στους περισσότερους εξωγήινους.\"\n  STR_FIELDPROMOTIONS: \"Προαγωγές Πεδίου Μάχης\"\n  STR_FIELDPROMOTIONS_DESC: \"Μόνο οι στρατιώτες που ήταν παρόντες στο χώρο της αποστολής δικαιούνται προαγωγή.\"\n  STR_MEETINGPOINT: \"Προβλέψτε την τροχιά των ΑΤΙΑ\"\n  STR_MEETINGPOINT_DESC: \"Τα σκάφη πετούν προς ένα σημείο συνάντησης με το UFO με βάση την τρέχουσα τροχιά του.\"\n  STR_IRONMAN: \"IRONMAN\"\n  STR_IRONMAN_DESC: \"Δεν επιτρέπεται η χειροκίνητη αποθήκευση\"\n  STR_SAVE_AND_ABANDON_GAME: \"ΑΠΟΘΉΚΕΥΣΗ ΚΑΙ ΕΓΚΑΤΆΛΕΙΨΗ ΠΑΙΧΝΙΔΙΟΥ\"\n  STR_MOD_UNSUCCESSFUL: \"Το mod απέτυχε να φορτωθεί\"\n  STR_NEW_SAVED_GAME_SLOT: \"<ΝΕΟ ΣΩΣΜΕΝΟ ΠΑΙΧΝΙΔΙ>\"\n  STR_AUTO_SAVE_GEOSCAPE_SLOT: \"<AUTO GEOSCAPE>\"\n  STR_AUTO_SAVE_BATTLESCAPE_SLOT: \"<AUTO BATTLESCAPE>\"\n  STR_QUICK_SAVE_SLOT: \"<ΓΡΗΓΟΡΗ ΑΠΟΘΗΚΕΥΣΗ ΠΑΙΧΝΙΔΙΟΥ>\"\n  STR_DISPLAY_MODE_DESC: \"Αλλαγή τρόπου εμφάνισης παιχνιδιού στην οθόνη\"\n  STR_PREFERRED_MUSIC_FORMAT: \"Διαμόρφωση Μουσικής\"\n  STR_PREFERRED_MUSIC_FORMAT_DESC: \"Επιλέγει την προτιμώμενη μορφή μουσικής για χρήση όταν είναι διαθέσιμες πολλές.{NEWLINE}ΣΗΜΕΙΩΣΗ: Η αναπαραγωγή MIDI ενδέχεται να παρουσιάζει σφάλματα στα Windows.\"\n  STR_PREFERRED_SFX_FORMAT: \"Μορφή SFX\"\n  STR_PREFERRED_SFX_FORMAT_DESC: \"Επιλέγει την προτιμώμενη μορφή ηχητικών εφέ για χρήση όταν είναι διαθέσιμα πολλά.\"\n  STR_PREFERRED_VIDEO_FORMAT: \"Μορφή βίντεο\"\n  STR_PREFERRED_VIDEO_FORMAT_DESC: \"Επιλέγει την προτιμώμενη μορφή βίντεο για χρήση όταν είναι διαθέσιμα πολλά.\"\n  STR_PREFERRED_VIDEO_ANIMATION: \"Κινούμενα σχέδια\"\n  STR_PREFERRED_VIDEO_SLIDESHOW: \"Προβολή διαφανειών\"\n  STR_PREFERRED_FORMAT_AUTO: \"ΚΒ\"\n  STR_CURRENT_FORMAT: \"Τρέχων: {0}\"\n  STR_SOUND_OPTIONS: \"Επιλογές Ήχου\"\n  STR_BACKGROUND_MUTE: \"Σίγαση φόντου\"\n  STR_BACKGROUND_MUTE_DESC: \"Σίγαση όλων των ήχων όταν το παράθυρο του παιχνιδιού δεν είναι ενεργό.\"\n  STR_FORCE_FIRE: \"Παράκαμψη Γραμμής Βολής\"\n  STR_FORCE_FIRE_DESC: \"Επιτρέπει τον εξαναγκασμό των στρατιωτών σας να πυροβολήσουν κρατώντας το CTRL, ανεξάρτητα από τους κανόνες της γραμμής πυρός.\"\n  STR_NO_AUDIO_HARDWARE_DETECTED: \"Δεν εντοπίστηκε συσκευή ήχου\"\n  STR_MOUSEWHEEL_SPEED: \"Ταχύτητα κύλισης τροχού ποντικιού\"\n  STR_MOUSEWHEEL_SPEED_DESC: \"Προσαρμόζει τον αριθμό των γραμμών που μετακινούνται σε λίστες με κάθε αύξηση του τροχού του ποντικιού.\"\n  STR_DISABLED: \"Απενεργοποιημένο\"\n  STR_MAXIMIZE_INFO_SCREENS: \"Μεγιστοποίηση πληροφοριών οθόνης\"\n  STR_MAXIMIZE_INFO_SCREENS_DESC: \"Το απόθεμα και διάφορες άλλες οθόνες θα εμφανιστούν σε πλήρη οθόνη, ανεξάρτητα από τις ρυθμίσεις κλίμακας.\"\n  STR_DIARY: \"ΗΜΕΡΟΛΟΓΙΟ\"\n  STR_KILLED: \"ΣΚΟΤΩΘΗΚΕ\"\n  STR_STUNNED: \"ΖΑΛΙΖΜΕΝΟΣ\"\n  STR_PANICKED: \"ΠΑΝΙΚΟΒΛΗΜΕΝΟΣ\"\n  STR_MINDCONTROLLED: \"ΕΞΟΥΣΙΑΣΜΕΝΟΣ\"\n  STR_REGION_UNKNOWN: \"Μυστικός\"\n  STR_WEAPON_UNKNOWN: \"Αυτοσχεδιασμός\"\n  STR_UNKNOWN: \"Άγνωστο\"\n  STR_VICTORY: \"Νίκη\"\n  STR_DEFEAT: \"Ήττα\"\n  STR_NO_RECORD: \"Κανένα αρχείο\"\n  STR_HUMAN: \"Άνθρωπος\"\n  STR_FRIENDLY: \"Φιλικός\"\n  STR_HOSTILE: \"Εχθρικός\"\n  STR_NEUTRAL: \"Ουδέτερος\"\n  STR_RATING_UC: \"ΙΔΙΟΤΗΤΑ\"\n  STR_LOCATION: \"ΤΟΠΟΘΕΣΙΑ> {ALT}{0}\"\n  STR_DAYLIGHT_TYPE: \"ΩΡΑ> {ALT}{0}\"\n  STR_RACE_TYPE: \"RACE> {ALT}{0}\"\n  STR_DAY: \"Ημέρα\"\n  STR_NIGHT: \"Νύχτα\"\n  STR_DAYS_WOUNDED: \"ΜΕΡΕΣ ΤΡΑΥΜΑΤΙΣΜΟΥ> {ALT}{0}\"\n  STR_COMBAT: \"ΜΑΧΗ\"\n  STR_PERFORMANCE: \"ΕΠΙΔΟΣΗ\"\n  STR_NEUTRALIZATIONS_BY_RACE: \"ΕΞΟΥΔΕΤΕΡΩΣΕΙΣ ΚΑΤΑ ΦΥΛΗ\"\n  STR_NEUTRALIZATIONS_BY_RANK: \"ΕΞΟΥΔΕΤΕΡΩΣΕΙΣ ΚΑΤΑ ΒΑΘΜΟ\"\n  STR_NEUTRALIZATIONS_BY_WEAPON: \"ΑΞΟΥΔΕΤΕΡΩΣΕΙΣ ΚΑΤΑ ΟΠΛΟΥ\"\n  STR_MISSIONS_BY_LOCATION: \"ΑΠΟΣΤΟΛΕΣ ΚΑΤΑ ΤΟΠΟΘΕΣΙΑΣ\"\n  STR_MISSIONS_BY_TYPE: \"ΑΠΟΣΤΟΛΕΣ ΚΑΤΑ ΤΥΠΟΥ\"\n  STR_MISSIONS_BY_UFO: \"ΑΠΟΣΤΟΛΕΣ ΚΑΤΑ ΑΤΙΑ\"\n  STR_SCORE_VALUE: \"ΣΚΟΡ> {ALT}{0}\"\n  STR_WINS: \"ΝΙΚΕΣ> {ALT}{0}\"\n  STR_STUNS: \"ΖΑΛΙΖΜΑΤΑ> {ALT}{0}\"\n  STR_PANICKS: \"ΠΑΝΙΚΟΙ> {ALT}{0}\"\n  STR_MINDCONTROLS: \"ΕΛΕΓΧΟΙ> {ALT}{0}\"\n  STR_AWARDS: \"ΒΡΑΒΕΙΑ\"\n  STR_COMMENDATIONS_UC: \"ΕΠΑΙΝΟΙ\"\n  STR_COMMENDATIONS: \"Επαινοι\"\n  STR_MEDALS: \"Μεντάλια\"\n  STR_LOST_IN_SERVICE: \"ΧΑΘΗΚΕ ΣΤΗΝ ΥΠΗΡΕΣΙΑ\"\n  STR_MEDAL_NAME: \"Όνομα Μενταλίου\"\n  STR_MEDAL_AWARD_LEVEL: \"Επίπεδο Βραβείου\"\n  STR_MEDAL_DECOR_LEVEL: \"Επίπεδο Διακόσμησης\"\n  STR_AWARD_0: \"Πρώτο βραβείο\"\n  STR_AWARD_1: \"Δεύτερο βραβειο\"\n  STR_AWARD_2: \"Τρίτο βραβείο\"\n  STR_AWARD_3: \"Τέταρτο βραβείο\"\n  STR_AWARD_4: \"Πέμπτο βραβείο\"\n  STR_AWARD_5: \"Έκτο βραβείο\"\n  STR_AWARD_6: \"Έβδομο βραβείο\"\n  STR_AWARD_7: \"Όγδοο βραβείο\"\n  STR_AWARD_8: \"Έννατο βραβείο\"\n  STR_AWARD_9: \"Δέκατο βραβείο\"\n  STR_AWARD_DECOR_0: \"Τίποτα\"\n  STR_AWARD_DECOR_1: \"Πρώτη χάλκινη καρφίτσα\"\n  STR_AWARD_DECOR_2: \"Δεύτερη χάλκινη καρφίτσα\"\n  STR_AWARD_DECOR_3: \"Τρίτη χάλκινη καρφίτσα\"\n  STR_AWARD_DECOR_4: \"Πρώτη ασιμένια καρφίτσα\"\n  STR_AWARD_DECOR_5: \"Δεύτερη ασιμένια καρφίτσα\"\n  STR_AWARD_DECOR_6: \"Τρίτη ασιμένια καρφίτσα\"\n  STR_AWARD_DECOR_7: \"Πρώτη χρυσή καρφίτσα\"\n  STR_AWARD_DECOR_8: \"Δεύτερη χρυσή καρφίτσα\"\n  STR_AWARD_DECOR_9: \"Τρίτη χρυσή καρφίτσα\"\n  STR_KILLED_IN_ACTION_MALE: \"ΣΚΟΤΩΘΗΚΕ ΣΤΗ ΔΡΑΣΗ\"\n  STR_KILLED_IN_ACTION_FEMALE: \"ΣΚΟΤΩΘΗΚΕ ΣΤΗ ΔΡΑΣΗ\"\n  STR_MISSING_IN_ACTION_MALE: \"ΑΓΝΟΕΙΤΑΙ\"\n  STR_MISSING_IN_ACTION_FEMALE: \"ΑΓΝΟΕΙΤΑΙ\"\n  STR_AVERAGE_MONTHLY_RATING: \"Μέση μηνιαία βαθμολογία\"\n  STR_TOTAL_INCOME: \"Σύνολο εισοδήματος\"\n  STR_TOTAL_EXPENDITURE: \"Σύνολο δαπανών\"\n  STR_MISSIONS_WON: \"Ολοκληρωμένες αποστολές\"\n  STR_MISSIONS_LOST: \"Αποτυχημένες αποστολές\"\n  STR_NIGHT_MISSIONS: \"Νυχτερινές αποστολές\"\n  STR_BEST_RATING: \"Καλύτερη αξιολόγηση αποστολής\"\n  STR_WORST_RATING: \"Χειρότερη αξιολόγηση αποστολής\"\n  STR_ALIEN_KILLS: \"Εξωγήινοι  που εξουδετερώθηκαν\"\n  STR_ALIEN_CAPTURES: \"Εξωγήινοι που αιχμαλωτίστηκαν\"\n  STR_FRIENDLY_KILLS: \"Συμβάντα φιλικών πυρών\"\n  STR_AVERAGE_ACCURACY: \"Μέση ακρίβεια\"\n  STR_WEAPON_MOST_KILLS: \"Το αποτελεσματικότερο όπλο\"\n  STR_ALIEN_MOST_KILLS: \"Φονικός εξωγήινος\"\n  STR_LONGEST_SERVICE: \"Οι μεγαλύτεροι μήνες στην υπηρεσία\"\n  STR_TOTAL_DAYS_WOUNDED: \"Μέρες ασθενείας\"\n  STR_COUNTRIES_LOST: \"Χώρες διεισδύθηκαν\"\n  STR_TOTAL_TERROR_SITES: \"Τρομοκρατικά χτυπήματα\"\n  STR_TOTAL_BASES: \"Κατασκευασμένες βάσεις\"\n  STR_TOTAL_CRAFT: \"Κατεχόμενο Σκάφος\"\n  STR_TOTAL_SCIENTISTS: \"Επιστήμονες που προσελήφθησαν\"\n  STR_TOTAL_ENGINEERS: \"Μηχανικοί που προσελήφθησαν\"\n  STR_TOTAL_RESEARCH: \"Ολοκληρώθηκε η έρευνα\"\n  STR_DIARY_ACCURACY: \"ΕΥΣΤΟΧΙΑ> {ALT}{0}%\"\n  STR_STATISTICS: \"Στατιστικά\"\n  STR_STATS: \"ΣΤΑΤ\"\n  STR_TIME_UNITS_ABBREVIATION: \"TU\"\n  STR_STAMINA_ABBREVIATION: \"STA\"\n  STR_HEALTH_ABBREVIATION: \"HP\"\n  STR_BRAVERY_ABBREVIATION: \"BRV\"\n  STR_REACTIONS_ABBREVIATION: \"REA\"\n  STR_FIRING_ACCURACY_ABBREVIATION: \"ACC\"\n  STR_THROWING_ACCURACY_ABBREVIATION: \"THR\"\n  STR_STRENGTH_ABBREVIATION: \"STR\"\n  STR_MELEE_ACCURACY_ABBREVIATION: \"MEL\"\n  STR_FOLDERS: \"ΦΑΚΕΛΟΙ\"\n  STR_DATA_FOLDER: \"ΦΑΚΕΛΟΣ ΔΕΔΩΜΕΝΩΝ (αυθεντικοί πόροι)\"\n  STR_USER_FOLDER: \"ΦΑΚΕΛΟΣ ΧΡΗΣΤΗ (mods, openxcom.log)\"\n  STR_SAVE_FOLDER: \"Save Folder (saved games, screenshots)\"\n  STR_CONFIG_FOLDER: \"Config Folder (options.cfg)\"\n  STR_DATA_FOLDER_DESC_1: \"Εδώ είναι που το OpenXcom αναζητά τους αρχικούς πόρους του παιχνιδιού (UFO και/ή TFTD).\"\n  STR_DATA_FOLDER_DESC_2: \"Οι εσωτερικοί πόροι του OpenXcom βρίσκονται στον φάκελο 'common'. Τα ενσωματωμένα mods του OpenXcom βρίσκονται στον φάκελο \\\"standard\\\".\"\n  STR_USER_FOLDER_DESC: \"Το αρχείο καταγραφής ('openxcom.log') αποθηκεύεται εδώ. Όλα τα προσαρμοσμένα mod ανήκουν και αυτά εδώ (στον υποφάκελο 'mods').\"\n  STR_SAVE_FOLDER_DESC: \"Τα αποθηκευμένα παιχνίδια σας βρίσκονται εδώ. Επίσης, μπορείτε να βρείτε τις ρυθμίσεις mission generator settings ('battle.cfg').\"\n  STR_CONFIG_FOLDER_DESC: \"Εδώ αποθηκεύονται οι ρυθμίσεις του OpenXcom ('options.cfg'). Κανονικά το ίδιο με το User Folder.\"\n"
  },
  {
    "path": "bin/common/Language/en-GB.yml",
    "content": "en-GB:\n  STR_OPENXCOM: \"OpenXcom\"\n  STR_NEW_GAME: \"New Game\"\n  STR_LOAD_SAVED_GAME: \"Load Game\"\n  STR_SELECT_DIFFICULTY_LEVEL: \"Select Difficulty Level\"\n  STR_1_BEGINNER: \"1> Beginner\"\n  STR_2_EXPERIENCED: \"2> Experienced\"\n  STR_3_VETERAN: \"3> Veteran\"\n  STR_4_GENIUS: \"4> Genius\"\n  STR_5_SUPERHUMAN: \"5> Superhuman\"\n  STR_TIME: \"Time\"\n  STR_DATE: \"Date\"\n  STR_SELECT_GAME_TO_LOAD: \"Select game to load\"\n  STR_SELECT_SAVE_POSITION: \"Select save position\"\n  STR_GAME_OPTIONS: \"GAME OPTIONS\"\n  STR_LOAD_GAME: \"LOAD GAME\"\n  STR_SAVE_GAME: \"SAVE GAME\"\n  STR_ABANDON_GAME: \"ABANDON GAME\"\n  STR_ABANDON_GAME_QUESTION: \"ABANDON GAME?\"\n  STR_QUIT: \"Quit\"\n  STR_SAVING_GAME: \"Saving game\"\n  STR_LOADING_GAME: \"Loading game\"\n  STR_NO_SAVED_GAME_PRESENT: \"No saved game present\"\n  STR_LOAD_UNSUCCESSFUL: \"Load failed\"\n  STR_SAVE_UNSUCCESSFUL: \"Save failed\"\n  STR_LOAD_SUCCESSFUL: \"Load successful\"\n  STR_SAVE_SUCCESSFUL: \"Save successful\"\n  STR_DELETE: \"DELETE\"\n  STR_DELETE_UNSUCCESSFUL: \"Delete failed\"\n  STR_IS_IT_OK_TO_DELETE_THE_SAVED_GAME: \"Are you sure you want to delete the saved game?\"\n  STR_ORIGINAL_XCOM: \"Original X-Com\"\n  STR_LOADING: \"Loading...\"\n  STR_DETAILS: \"DETAILS> {ALT}{0}\"\n  STR_NEW_BATTLE: \"New Battle\"\n  STR_OPTIONS: \"Options\"\n  STR_RIGHT_CLICK_TO_DELETE: \"Right click to delete.\"\n  STR_RESTORE_DEFAULTS: \"Restore Defaults\"\n  STR_CONTROLS: \"CONTROLS\"\n  STR_GENERAL: \"General\"\n  STR_GEOSCAPE: \"Geoscape\"\n  STR_BATTLESCAPE: \"Battlescape\"\n  STR_SCREENSHOT: \"Screenshot\"\n  STR_FPS_COUNTER: \"FPS Counter\"\n  STR_ROTATE_LEFT: \"Rotate Left\"\n  STR_ROTATE_RIGHT: \"Rotate Right\"\n  STR_ROTATE_UP: \"Rotate Up\"\n  STR_ROTATE_DOWN: \"Rotate Down\"\n  STR_ZOOM_IN: \"Zoom In\"\n  STR_ZOOM_OUT: \"Zoom Out\"\n  STR_TOGGLE_COUNTRY_DETAIL: \"Toggle Country Detail\"\n  STR_TOGGLE_RADAR_RANGES: \"Toggle Radar Ranges\"\n  STR_SCROLL_LEFT: \"Scroll Left\"\n  STR_SCROLL_RIGHT: \"Scroll Right\"\n  STR_SCROLL_UP: \"Scroll Up\"\n  STR_SCROLL_DOWN: \"Scroll Down\"\n  STR_UNIT_LEVEL_ABOVE: \"Move Unit to Level Above\"\n  STR_UNIT_LEVEL_BELOW: \"Move Unit to Level Below\"\n  STR_VIEW_LEVEL_ABOVE: \"View Level Above\"\n  STR_VIEW_LEVEL_BELOW: \"View Level Below\"\n  STR_CENTER_SELECTED_UNIT: \"Centre Selected Unit\"\n  STR_PREVIOUS_UNIT: \"Select Previous Unit\"\n  STR_NEXT_UNIT: \"Select Next Unit\"\n  STR_DESELECT_UNIT: \"Don't Reselect Unit\"\n  STR_USE_LEFT_HAND: \"Use Left Hand Item\"\n  STR_USE_RIGHT_HAND: \"Use Right Hand Item\"\n  STR_INVENTORY: \"Inventory\"\n  STR_MINIMAP: \"Minimap\"\n  STR_MULTI_LEVEL_VIEW: \"Multi-Level View\"\n  STR_END_TURN: \"End Turn\"\n  STR_ABORT_MISSION: \"Abort Mission\"\n  STR_UNIT_STATS: \"Unit Stats\"\n  STR_KNEEL: \"Kneel\"\n  STR_RELOAD: \"Reload\"\n  STR_TOGGLE_PERSONAL_LIGHTING: \"Toggle Personal Lighting\"\n  STR_DONT_RESERVE_TIME_UNITS: \"Don't Reserve TUs\"\n  STR_RESERVE_TIME_UNITS_FOR_SNAP_SHOT: \"Reserve TUs for Snap Shot\"\n  STR_RESERVE_TIME_UNITS_FOR_AIMED_SHOT: \"Reserve TUs for Aimed Shot\"\n  STR_RESERVE_TIME_UNITS_FOR_AUTO_SHOT: \"Reserve TUs for Auto Shot\"\n  STR_CENTER_ON_ENEMY_1: \"Centre on Enemy 1\"\n  STR_CENTER_ON_ENEMY_2: \"Centre on Enemy 2\"\n  STR_CENTER_ON_ENEMY_3: \"Centre on Enemy 3\"\n  STR_CENTER_ON_ENEMY_4: \"Centre on Enemy 4\"\n  STR_CENTER_ON_ENEMY_5: \"Centre on Enemy 5\"\n  STR_CENTER_ON_ENEMY_6: \"Centre on Enemy 6\"\n  STR_CENTER_ON_ENEMY_7: \"Centre on Enemy 7\"\n  STR_CENTER_ON_ENEMY_8: \"Centre on Enemy 8\"\n  STR_CENTER_ON_ENEMY_9: \"Centre on Enemy 9\"\n  STR_CENTER_ON_ENEMY_10: \"Centre on Enemy 10\"\n  STR_CREATE_INVENTORY_TEMPLATE: \"Create inventory template\"\n  STR_APPLY_INVENTORY_TEMPLATE: \"Apply inventory template\"\n  STR_CLEAR_INVENTORY: \"Clear inventory\"\n  STR_AUTO_EQUIP: \"Auto-equip\"\n  STR_QUICK_SAVE: \"Quick Save\"\n  STR_QUICK_LOAD: \"Quick Load\"\n  STR_ADVANCED: \"ADVANCED\"\n  STR_AGGRESSIVERETALIATION: \"Aggressive retaliation\"\n  STR_AGGRESSIVERETALIATION_DESC: \"UFOs will attempt to detect your bases at all times, regardless of their mission parameters.\"\n  STR_STORAGELIMITSENFORCED: \"Storage limits for recovered items\"\n  STR_STORAGELIMITSENFORCED_DESC: \"Enforces alien containment and general store limits for live aliens and artefacts recovered from missions.\"\n  STR_CANSELLLIVEALIENS: \"Live alien sale\"\n  STR_CANSELLLIVEALIENS_DESC: \"Allows the sale of live aliens, recommended when using storage limits.\"\n  STR_ALLOWBUILDINGQUEUE: \"Allow building queue\"\n  STR_ALLOWBUILDINGQUEUE_DESC: \"New facilities can be placed next to unfinished ones.\"\n  STR_BATTLEAUTOEND: \"Auto-end battle\"\n  STR_BATTLEAUTOEND_DESC: \"Battles automatically end when the last living enemy is neutralized.\"\n  STR_BATTLEINSTANTGRENADE: \"Instant grenades\"\n  STR_BATTLEINSTANTGRENADE_DESC: \"Grenades primed to go off in 0 turns will explode immediately when thrown, instead of at the end of the turn.\"\n  STR_BATTLEUFOEXTENDERACCURACY: \"UFO Extender accuracy\"\n  STR_BATTLEUFOEXTENDERACCURACY_DESC: \"Accuracy of shots drops off after a certain distance, according to shot type. Adjusted accuracy will be displayed on the cursor.\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE: \"Airborne transfers\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE_DESC: \"Craft currently in-flight can be transferred.\"\n  STR_CRAFTLAUNCHALWAYS: \"Force craft launch\"\n  STR_CRAFTLAUNCHALWAYS_DESC: \"Craft can be launched even when they aren't ready, overriding the need for maintenance.\"\n  STR_CUSTOMINITIALBASE: \"Custom initial base\"\n  STR_CUSTOMINITIALBASE_DESC: \"When starting a new game, you can manually place your starting facilities instead of using the default layout.\"\n  STR_GLOBESEASONS: \"Realistic globe lighting\"\n  STR_GLOBESEASONS_DESC: \"Uses more realistic projection of sunlight on the Geoscape according to Earth's axial tilt.\"\n  STR_PLAYINTRO: \"Play intro\"\n  STR_PLAYINTRO_DESC: \"Show the intro cinematic on startup.\"\n  STR_SHOWMORESTATSININVENTORYVIEW: \"Inventory Stats\"\n  STR_SHOWMORESTATSININVENTORYVIEW_DESC: \"Show extra information on the selected soldier in the inventory screen.\"\n  STR_SNEAKYAI: \"Sneaky AI\"\n  STR_SNEAKYAI_DESC: \"AI avoids exposing themselves to the player whenever possible.\"\n  STR_STRAFE: \"Alternate movement methods\"\n  STR_STRAFE_DESC: \"Enables strafing, running, and independent tank turret movement when holding CTRL.\"\n  STR_BATTLEEXPLOSIONHEIGHT: \"Explosion height\"\n  STR_BATTLEEXPLOSIONHEIGHT_DESC: \"Change how far height-wise explosions may spread.{NEWLINE}(Flat: 0, Round: 3)\"\n  STR_AUTOSAVE: \"Autosave\"\n  STR_AUTOSAVE_DESC: \"Automatically saves the game at specified intervals. Doesn't apply to Ironman Mode.\"\n  STR_AUTOSAVE_FREQUENCY: \"Autosave Frequency\"\n  STR_AUTOSAVE_FREQUENCY_DESC: \"Amount of turns after which the game will be automatically saved.\"\n  STR_ALLOWPSIONICCAPTURE: \"Allow psi-capture\"\n  STR_ALLOWPSIONICCAPTURE_DESC: \"Mind-controlling all remaining aliens results in victory, and they count as live captures.\"\n  STR_ANYTIMEPSITRAINING: \"Psionic training at any time\"\n  STR_ANYTIMEPSITRAINING_DESC: \"Allows assigning soldiers to psionic training at any time of the month. Remember, initial training takes from 30 to 60 days.\"\n  STR_SKIPNEXTTURNSCREEN: \"Skip \\\"Next Turn\\\" screen\"\n  STR_SKIPNEXTTURNSCREEN_DESC: \"\\\"Next Turn\\\" screens during battle are advanced automatically after a short delay.\"\n  STR_NOT_ENOUGH_SPACE: \"Not Enough Space!\"\n  STR_WEAPONSELFDESTRUCTION: \"Alien weapon self-destruction\"\n  STR_WEAPONSELFDESTRUCTION_DESC: \"Weapons carried by aliens will self-destruct if their owner is killed, like in XCOM 2012.\"\n  STR_RETAINCORPSES: \"Retain interrogated aliens\"\n  STR_RETAINCORPSES_DESC: \"After \\\"researching\\\" living aliens, the body will be added to the base stores, like in XCOM 2012.\"\n  STR_SAVE_VOXEL_VIEW: \"Save First-Person Screenshot\"\n  STR_RESERVE_TIME_UNITS_FOR_KNEEL: \"Reserve TUs for kneeling\"\n  STR_EXPEND_ALL_TIME_UNITS: \"Expend all remaining Time Units\"\n  STR_PSISTRENGTHEVAL: \"Psi-Strength Evaluation\"\n  STR_PSISTRENGTHEVAL_DESC: \"Evaluates the psionic strength of all soldiers after the appropriate research has been completed.\"\n  STR_DISABLEAUTOEQUIP: \"Disable auto-equip\"\n  STR_DISABLEAUTOEQUIP_DESC: \"Disable auto-equipping of new soldiers before battle.\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT: \"Allow Psi-Strength Improvement\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT_DESC: \"Psionic strength of the soldiers can be improved by experience and training.\"\n  STR_BATTLESMOOTHCAMERA: \"Smooth Bullet Camera\"\n  STR_BATTLESMOOTHCAMERA_DESC: \"The Battlescape camera will remain centred on projectiles while in flight.\"\n  STR_BATTLECONFIRMFIREMODE: \"Confirm Fire mode\"\n  STR_BATTLECONFIRMFIREMODE_DESC: \"Require a second click on the same tile to confirm fire orders.\"\n  STR_SELECT_BASE_1: \"Select Base 1\"\n  STR_SELECT_BASE_2: \"Select Base 2\"\n  STR_SELECT_BASE_3: \"Select Base 3\"\n  STR_SELECT_BASE_4: \"Select Base 4\"\n  STR_SELECT_BASE_5: \"Select Base 5\"\n  STR_SELECT_BASE_6: \"Select Base 6\"\n  STR_SELECT_BASE_7: \"Select Base 7\"\n  STR_SELECT_BASE_8: \"Select Base 8\"\n  STR_VIDEO: \"VIDEO\"\n  STR_AUDIO: \"AUDIO\"\n  STR_BATTLESCAPE_UC: \"BATTLESCAPE\"\n  STR_MODS_UC: \"MODS\"\n  STR_MODS: \"Mods\"\n  STR_DISPLAY_RESOLUTION: \"Display Resolution\"\n  STR_DISPLAY_RESOLUTION_DESC: \"Changes the resolution of the display, the game resolution will be resized to match. Arrows switch between supported resolutions. Click to input a custom resolution.\"\n  STR_ORIGINAL: \"Original\"\n  STR_DISPLAY_MODE: \"Display Mode\"\n  STR_WINDOWED: \"Windowed\"\n  STR_FULLSCREEN: \"Fullscreen\"\n  STR_BORDERLESS: \"Borderless\"\n  STR_DISPLAY_LANGUAGE: \"Display Language\"\n  STR_DISPLAY_LANGUAGE_DESC: \"Changes the language of the in-game text.\"\n  STR_DISPLAY_FILTER: \"Display Filter\"\n  STR_DISPLAY_FILTER_DESC: \"Changes the filter applied to the game screen.{NEWLINE}*requires OpenGL hardware acceleration.\"\n  STR_DISPLAY_OPTIONS: \"Display Options\"\n  STR_LETTERBOXED: \"Letterboxed\"\n  STR_LETTERBOXED_DESC: \"Letterboxes the display to maintain the original aspect ratio.\"\n  STR_RESIZABLE: \"Resizable\"\n  STR_LOCK_MOUSE: \"Grab Mouse\"\n  STR_LOCK_MOUSE_DESC: \"Keeps the mouse cursor from leaving the game window. Ctrl+G to toggle at any time.\"\n  STR_FIXED_WINDOW_POSITION: \"Fixed Window Position\"\n  STR_FIXED_WINDOW_POSITION_DESC: \"Set fixed position to Window.\"\n  STR_DISPLAY_SET_WINDOW_POSITION: \"Set new Window Root position\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_X: \"Left border new X:\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_Y: \"Up border new Y:\"\n  STR_MUSIC_VOLUME: \"Music Volume\"\n  STR_MUSIC_VOLUME_DESC: \"Changes the volume of the background music.\"\n  STR_SFX_VOLUME: \"SFX Volume\"\n  STR_SFX_VOLUME_DESC: \"Changes the volume of the sound effects.\"\n  STR_UI_VOLUME: \"UI Volume\"\n  STR_UI_VOLUME_DESC: \"Changes the volume of the interface beeps.\"\n  STR_SCROLL_SPEED: \"Scroll Speed\"\n  STR_SCROLL_SPEED_GEO_DESC: \"Changes the scrolling speed of the globe.\"\n  STR_SCROLL_SPEED_BATTLE_DESC: \"Changes the scrolling speed of the map.\"\n  STR_DOGFIGHT_SPEED: \"Dogfight Speed\"\n  STR_DOGFIGHT_SPEED_DESC: \"Changes the speed of interception battles between crafts and UFOs. Slower speeds can improve performance on low-end devices.\"\n  STR_CLOCK_SPEED: \"Clock Speed\"\n  STR_CLOCK_SPEED_DESC: \"Changes the speed of the Geoscape clock. Slower speeds can improve performance on low-end devices.\"\n  STR_GLOBE_DETAILS: \"Globe Details\"\n  STR_GLOBE_COUNTRIES: \"Countries\"\n  STR_GLOBE_COUNTRIES_DESC: \"Shows funding countries on the globe.\"\n  STR_GLOBE_RADARS: \"Radars\"\n  STR_GLOBE_RADARS_DESC: \"Shows base radar ranges on the globe.\"\n  STR_GLOBE_FLIGHT_PATHS: \"Flight Paths\"\n  STR_GLOBE_FLIGHT_PATHS_DESC: \"Shows craft flight paths on the globe.\"\n  STR_CONTROLS_DESC: \"Left-click a shortcut and press a key to change it.{NEWLINE}Right-click a shortcut to disable it.\"\n  STR_BASE_GAME: \"Base game\"\n  STR_MODS_TOOLTIP: \"Version {0} by {1}.{NEWLINE}{2}\"\n  STR_EDGE_SCROLL: \"Edge Scroll\"\n  STR_EDGE_SCROLL_DESC: \"Trigger: Scroll map when the left mouse button is held down on a screen edge.{NEWLINE}Auto: Scroll map when the cursor is over a screen edge.\"\n  STR_TRIGGER_SCROLL: \"Trigger\"\n  STR_AUTO_SCROLL: \"Auto\"\n  STR_DRAG_SCROLL: \"Drag Scroll\"\n  STR_DRAG_SCROLL_DESC: \"Scrolls the map when the specified mouse button is held down and dragged.\"\n  STR_LEFT_MOUSE_BUTTON: \"Left Button\"\n  STR_MIDDLE_MOUSE_BUTTON: \"Middle Button\"\n  STR_RIGHT_MOUSE_BUTTON: \"Right Button\"\n  STR_FIRE_SPEED: \"Fire Speed\"\n  STR_FIRE_SPEED_DESC: \"Changes the speed of weapon projectiles.\"\n  STR_PLAYER_MOVEMENT_SPEED: \"Player Movement Speed\"\n  STR_PLAYER_MOVEMENT_SPEED_DESC: \"Changes the movement speed of player-controlled units.\"\n  STR_COMPUTER_MOVEMENT_SPEED: \"AI Movement Speed\"\n  STR_COMPUTER_MOVEMENT_SPEED_DESC: \"Changes the movement speed of computer-controlled units.\"\n  STR_PATH_PREVIEW: \"Path Preview\"\n  STR_PATH_ARROWS: \"Arrows\"\n  STR_PATH_ARROWS_DESC: \"Clicking shows the path your unit will take to the destination. Colour indicates available actions: Green - can move and fire; Yellow - can move; Red - can't move.\"\n  STR_PATH_TIME_UNIT_COST: \"Time Units\"\n  STR_PATH_TIME_UNIT_COST_DESC: \"Clicking shows the TUs your unit will have remaining after moving to the destination.\"\n  STR_USER_INTERFACE_OPTIONS: \"UI Options\"\n  STR_TOOLTIPS: \"Tooltips\"\n  STR_TOOLTIPS_DESC: \"Displays tooltips for the Battlescape buttons.\"\n  STR_DEATH_NOTIFICATIONS: \"Death Notifications\"\n  STR_DEATH_NOTIFICATIONS_DESC: \"Pop up a notification detailing who was killed whenever a soldier dies.\"\n  STR_SHOW_FUNDS: \"Show Funds\"\n  STR_SHOW_FUNDS_DESC: \"Shows your current funds next to the Geoscape clock.\"\n  STR_MISSION_GENERATOR: \"MISSION GENERATOR\"\n  STR_MAP_OPTIONS: \"MAP OPTIONS\"\n  STR_ALIEN_OPTIONS: \"ALIEN OPTIONS\"\n  STR_MAP_TERRAIN: \"Terrain\"\n  STR_MAP_DARKNESS: \"Darkness\"\n  STR_MAP_DEPTH: \"Depth\"\n  STR_DIFFICULTY: \"Difficulty\"\n  STR_ALIEN_RACE: \"Race\"\n  STR_ALIEN_TECH_LEVEL: \"Tech Level\"\n  STR_RANDOMIZE: \"Randomize\"\n  STR_OXCE_REQUIRED_QUESTION: \"This mod requires OpenXcom {0} to run correctly. Enable this mod?\"\n  STR_RESTORE_DEFAULTS_QUESTION: \"Are you sure you want to restore the default options?\"\n  STR_DISPLAY_OPTIONS_CONFIRM: \"Do you want to keep the current display options?\"\n  STR_DISPLAY_OPTIONS_REVERT: \"Reverting in 0:{0}\"\n  STR_MISSING_CONTENT_PROMPT: \"WARNING:{SMALLLINE}This save relies on mods that are unavailable. Missing content will be removed, and it may fail to load.{NEWLINE}Continue?\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT: \"Save pre-primed grenades\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT_DESC: \"Saves grenades primed during pre-battle inventory in the soldier's equipment layout.\"\n  STR_NEWSEEDONLOAD: \"Save scumming\"\n  STR_NEWSEEDONLOAD_DESC: \"Loading a game will reset the random number seed, so taking the same action can yield different results. Doesn't apply to Ironman Mode.\"\n  STR_CHANGEVALUEBYMOUSEWHEEL: \"Change values with mouse wheel\"\n  STR_CHANGEVALUEBYMOUSEWHEEL_DESC: \"Allows you to use the mouse wheel to increase/decrease values by this amount.\"\n  STR_BATTLEHAIRBLEACH: \"Enhanced soldier sprites\"\n  STR_BATTLEHAIRBLEACH_DESC: \"Changes soldier Battlescape sprites to match their inventory look.\"\n  STR_DRAGSCROLLINVERT: \"Invert drag-scrolling\"\n  STR_DRAGSCROLLINVERT_DESC: \"When enabled, dragging scrolls in the opposite direction to the mouse.\"\n  STR_BATTLESCAPE_SCALE: \"Battlescape Scale\"\n  STR_BATTLESCAPE_SCALE_DESC: \"Battlescape viewport scaling mode, based on a fixed resolution (stretched to fit), or a fixed zoom level (expanded to fill).\"\n  STR_GEOSCAPE_SCALE: \"Geoscape Scale\"\n  STR_GEOSCAPESCALE_SCALE_DESC: \"Geoscape viewport scaling mode, based on a fixed resolution (stretched to fit), or a fixed zoom level (expanded to fill).\"\n  STR_1_5X: \"1.5x Original\"\n  STR_2X: \"2x Original\"\n  STR_THIRD_DISPLAY: \"1/3 Display\"\n  STR_HALF_DISPLAY: \"1/2 Display\"\n  STR_FULL_DISPLAY: \"Full Display\"\n  STR_FPS_LIMIT: \"FPS limit\"\n  STR_FPS_LIMIT_DESC: \"Limits the number of screen updates per second, 0 for no limit. If OpenGL rendering is enabled, the game uses Vsync instead.\"\n  STR_FPS_INACTIVE_LIMIT: \"FPS limit background\"\n  STR_FPS_INACTIVE_LIMIT_DESC: \"Limits the number of screen updates per second if OpenXcom is in the background.\"\n  STR_NOALIENPANICMESSAGES: \"Suppress panic messages for aliens\"\n  STR_NOALIENPANICMESSAGES_DESC: \"Don't show panic messages for aliens unless they are visible to the player.\"\n  STR_ALIENBLEEDING: \"Alien bleeding\"\n  STR_ALIENBLEEDING_DESC: \"Allows fatal wounds to be inflicted on most aliens.\"\n  STR_FIELDPROMOTIONS: \"Field promotions\"\n  STR_FIELDPROMOTIONS_DESC: \"Only soldiers that were present at the mission site are eligible for promotion.\"\n  STR_MEETINGPOINT: \"Predict UFO trajectory\"\n  STR_MEETINGPOINT_DESC: \"Crafts fly towards a meeting point with the UFO based on its current trajectory.\"\n  STR_IRONMAN: \"IRONMAN\"\n  STR_IRONMAN_DESC: \"No manual saving\"\n  STR_SAVE_AND_ABANDON_GAME: \"SAVE AND ABANDON GAME\"\n  STR_MOD_UNSUCCESSFUL: \"Mod failed to load\"\n  STR_NEW_SAVED_GAME_SLOT: \"<NEW SAVED GAME>\"\n  STR_AUTO_SAVE_GEOSCAPE_SLOT: \"<AUTO GEOSCAPE>\"\n  STR_AUTO_SAVE_BATTLESCAPE_SLOT: \"<AUTO BATTLESCAPE>\"\n  STR_QUICK_SAVE_SLOT: \"<QUICKSAVE>\"\n  STR_DISPLAY_MODE_DESC: \"Change how the game is displayed on your screen.\"\n  STR_PREFERRED_MUSIC_FORMAT: \"Music Format\"\n  STR_PREFERRED_MUSIC_FORMAT_DESC: \"Chooses the preferred music format to use when multiple ones are available.{NEWLINE}NOTE: MIDI playback may be buggy on Windows.\"\n  STR_PREFERRED_SFX_FORMAT: \"SFX Format\"\n  STR_PREFERRED_SFX_FORMAT_DESC: \"Chooses the preferred sound effects format to use when multiple ones are available.\"\n  STR_PREFERRED_VIDEO_FORMAT: \"Video Format\"\n  STR_PREFERRED_VIDEO_FORMAT_DESC: \"Chooses the preferred video format to use when multiple ones are available.\"\n  STR_PREFERRED_VIDEO_ANIMATION: \"Animation\"\n  STR_PREFERRED_VIDEO_SLIDESHOW: \"Slideshow\"\n  STR_PREFERRED_FORMAT_AUTO: \"Auto\"\n  STR_CURRENT_FORMAT: \"Current: {0}\"\n  STR_SOUND_OPTIONS: \"Sound Options\"\n  STR_BACKGROUND_MUTE: \"Background Mute\"\n  STR_BACKGROUND_MUTE_DESC: \"Mutes all sound when the game window is not active.\"\n  STR_FORCE_FIRE: \"Override Line of Fire\"\n  STR_FORCE_FIRE_DESC: \"Enables forcing your soldiers to take a shot when holding CTRL, regardless of line of fire rules.\"\n  STR_NO_AUDIO_HARDWARE_DETECTED: \"No audio hardware detected\"\n  STR_MOUSEWHEEL_SPEED: \"Mouse wheel scroll speed\"\n  STR_MOUSEWHEEL_SPEED_DESC: \"Adjusts the number of lines scrolled in lists with each increment of the mouse wheel.\"\n  STR_DISABLED: \"Disabled\"\n  STR_MAXIMIZE_INFO_SCREENS: \"Maximize info screens\"\n  STR_MAXIMIZE_INFO_SCREENS_DESC: \"Inventory and various other screens will be displayed at full screen, regardless of scale settings.\"\n  STR_DIARY: \"DIARY\"\n  STR_KILLED: \"KILLED\"\n  STR_STUNNED: \"STUNNED\"\n  STR_PANICKED: \"PANICKED\"\n  STR_MINDCONTROLLED: \"CONTROLLED\"\n  STR_REGION_UNKNOWN: \"Undisclosed\"\n  STR_WEAPON_UNKNOWN: \"Improvisation\"\n  STR_UNKNOWN: \"Unknown\"\n  STR_VICTORY: \"Victory\"\n  STR_DEFEAT: \"Defeat\"\n  STR_NO_RECORD: \"No record\"\n  STR_HUMAN: \"Human\"\n  STR_FRIENDLY: \"Friendly\"\n  STR_HOSTILE: \"Hostile\"\n  STR_NEUTRAL: \"Neutral\"\n  STR_RATING_UC: \"RATING\"\n  STR_LOCATION: \"LOCATION> {ALT}{0}\"\n  STR_DAYLIGHT_TYPE: \"TIME> {ALT}{0}\"\n  STR_RACE_TYPE: \"RACE> {ALT}{0}\"\n  STR_DAY: \"Day\"\n  STR_NIGHT: \"Night\"\n  STR_DAYS_WOUNDED: \"DAYS WOUNDED> {ALT}{0}\"\n  STR_COMBAT: \"COMBAT\"\n  STR_PERFORMANCE: \"PERFORMANCE\"\n  STR_NEUTRALIZATIONS_BY_RACE: \"NEUTRALISATIONS BY RACE\"\n  STR_NEUTRALIZATIONS_BY_RANK: \"NEUTRALISATIONS BY RANK\"\n  STR_NEUTRALIZATIONS_BY_WEAPON: \"NEUTRALISATIONS BY WEAPON\"\n  STR_MISSIONS_BY_LOCATION: \"MISSIONS BY LOCATION\"\n  STR_MISSIONS_BY_TYPE: \"MISSIONS BY TYPE\"\n  STR_MISSIONS_BY_UFO: \"MISSIONS BY UFO\"\n  STR_SCORE_VALUE: \"SCORE> {ALT}{0}\"\n  STR_WINS: \"WINS> {ALT}{0}\"\n  STR_STUNS: \"STUNS> {ALT}{0}\"\n  STR_PANICKS: \"PANICKS> {ALT}{0}\"\n  STR_MINDCONTROLS: \"CONTROLS> {ALT}{0}\"\n  STR_AWARDS: \"AWARDS\"\n  STR_COMMENDATIONS_UC: \"COMMENDATIONS\"\n  STR_COMMENDATIONS: \"Commendations\"\n  STR_MEDALS: \"MEDALS\"\n  STR_LOST_IN_SERVICE: \"LOST IN SERVICE\"\n  STR_MEDAL_NAME: \"Medal Name\"\n  STR_MEDAL_AWARD_LEVEL: \"Award Level\"\n  STR_MEDAL_DECOR_LEVEL: \"Decoration Level\"\n  STR_AWARD_0: \"First award\"\n  STR_AWARD_1: \"Second award\"\n  STR_AWARD_2: \"Third award\"\n  STR_AWARD_3: \"Fourth award\"\n  STR_AWARD_4: \"Fifth award\"\n  STR_AWARD_5: \"Sixth award\"\n  STR_AWARD_6: \"Seventh award\"\n  STR_AWARD_7: \"Eighth award\"\n  STR_AWARD_8: \"Ninth award\"\n  STR_AWARD_9: \"Tenth award\"\n  STR_AWARD_DECOR_0: \"None\"\n  STR_AWARD_DECOR_1: \"First bronze pin\"\n  STR_AWARD_DECOR_2: \"Second bronze pin\"\n  STR_AWARD_DECOR_3: \"Third bronze pin\"\n  STR_AWARD_DECOR_4: \"First silver pin\"\n  STR_AWARD_DECOR_5: \"Second silver pin\"\n  STR_AWARD_DECOR_6: \"Third silver pin\"\n  STR_AWARD_DECOR_7: \"First gold pin\"\n  STR_AWARD_DECOR_8: \"Second gold pin\"\n  STR_AWARD_DECOR_9: \"Third gold pin\"\n  STR_KILLED_IN_ACTION_MALE: \"KILLED IN ACTION\"\n  STR_KILLED_IN_ACTION_FEMALE: \"KILLED IN ACTION\"\n  STR_MISSING_IN_ACTION_MALE: \"MISSING IN ACTION\"\n  STR_MISSING_IN_ACTION_FEMALE: \"MISSING IN ACTION\"\n  STR_AVERAGE_MONTHLY_RATING: \"Average monthly rating\"\n  STR_TOTAL_INCOME: \"Total income\"\n  STR_TOTAL_EXPENDITURE: \"Total expenditure\"\n  STR_MISSIONS_WON: \"Missions accomplished\"\n  STR_MISSIONS_LOST: \"Missions failed\"\n  STR_NIGHT_MISSIONS: \"Night missions\"\n  STR_BEST_RATING: \"Best mission rating\"\n  STR_WORST_RATING: \"Worst mission rating\"\n  STR_ALIEN_KILLS: \"Aliens killed\"\n  STR_ALIEN_CAPTURES: \"Aliens captured\"\n  STR_FRIENDLY_KILLS: \"Friendly fire incidents\"\n  STR_AVERAGE_ACCURACY: \"Average accuracy\"\n  STR_WEAPON_MOST_KILLS: \"Most effective weapon\"\n  STR_ALIEN_MOST_KILLS: \"Deadliest alien\"\n  STR_LONGEST_SERVICE: \"Longest months in service\"\n  STR_TOTAL_DAYS_WOUNDED: \"Sick days\"\n  STR_COUNTRIES_LOST: \"Countries infiltrated\"\n  STR_TOTAL_TERROR_SITES: \"Terror attacks\"\n  STR_TOTAL_BASES: \"Bases built\"\n  STR_TOTAL_CRAFT: \"Craft owned\"\n  STR_TOTAL_SCIENTISTS: \"Scientists hired\"\n  STR_TOTAL_ENGINEERS: \"Engineers hired\"\n  STR_TOTAL_RESEARCH: \"Research completed\"\n  STR_DIARY_ACCURACY: \"ACCURACY> {ALT}{0}%\"\n  STR_STATISTICS: \"Statistics\"\n  STR_STATS: \"STATS\"\n  STR_TIME_UNITS_ABBREVIATION: \"TU\"\n  STR_STAMINA_ABBREVIATION: \"STA\"\n  STR_HEALTH_ABBREVIATION: \"HP\"\n  STR_BRAVERY_ABBREVIATION: \"BRV\"\n  STR_REACTIONS_ABBREVIATION: \"REA\"\n  STR_FIRING_ACCURACY_ABBREVIATION: \"ACC\"\n  STR_THROWING_ACCURACY_ABBREVIATION: \"THR\"\n  STR_STRENGTH_ABBREVIATION: \"STR\"\n  STR_MELEE_ACCURACY_ABBREVIATION: \"MEL\"\n  STR_FOLDERS: \"FOLDERS\"\n  STR_DATA_FOLDER: \"Data Folder (original resources)\"\n  STR_USER_FOLDER: \"User Folder (mods, openxcom.log)\"\n  STR_SAVE_FOLDER: \"Save Folder (saved games, screenshots)\"\n  STR_CONFIG_FOLDER: \"Config Folder (options.cfg)\"\n  STR_DATA_FOLDER_DESC_1: \"This is where OpenXcom looks for the original game resources (UFO and/or TFTD).\"\n  STR_DATA_FOLDER_DESC_2: \"OpenXcom internal resources are in the 'common' folder. OpenXcom built-in mods are in the 'standard' folder.\"\n  STR_USER_FOLDER_DESC: \"The log file ('openxcom.log') is stored here. All custom mods belong here too (in the 'mods' sub-folder).\"\n  STR_SAVE_FOLDER_DESC: \"Your saved games are located here. Also, the mission generator settings ('battle.cfg') can be found here.\"\n  STR_CONFIG_FOLDER_DESC: \"This is where OpenXcom settings ('options.cfg') are stored. Normally the same as the User Folder.\"\n"
  },
  {
    "path": "bin/common/Language/en-US.yml",
    "content": "en-US:\n  STR_OPENXCOM: \"OpenXcom\"\n  STR_NEW_GAME: \"New Game\"\n  STR_LOAD_SAVED_GAME: \"Load Game\"\n  STR_SELECT_DIFFICULTY_LEVEL: \"Select Difficulty Level\"\n  STR_1_BEGINNER: \"1> Beginner\"\n  STR_2_EXPERIENCED: \"2> Experienced\"\n  STR_3_VETERAN: \"3> Veteran\"\n  STR_4_GENIUS: \"4> Genius\"\n  STR_5_SUPERHUMAN: \"5> Superhuman\"\n  STR_TIME: \"Time\"\n  STR_DATE: \"Date\"\n  STR_SELECT_GAME_TO_LOAD: \"Select game to load\"\n  STR_SELECT_SAVE_POSITION: \"Select save position\"\n  STR_GAME_OPTIONS: \"GAME OPTIONS\"\n  STR_LOAD_GAME: \"LOAD GAME\"\n  STR_SAVE_GAME: \"SAVE GAME\"\n  STR_ABANDON_GAME: \"ABANDON GAME\"\n  STR_ABANDON_GAME_QUESTION: \"ABANDON GAME?\"\n  STR_QUIT: \"Quit\"\n  STR_SAVING_GAME: \"Saving game\"\n  STR_LOADING_GAME: \"Loading game\"\n  STR_NO_SAVED_GAME_PRESENT: \"No saved game present\"\n  STR_LOAD_UNSUCCESSFUL: \"Load failed\"\n  STR_SAVE_UNSUCCESSFUL: \"Save failed\"\n  STR_LOAD_SUCCESSFUL: \"Load successful\"\n  STR_SAVE_SUCCESSFUL: \"Save successful\"\n  STR_DELETE: \"DELETE\"\n  STR_DELETE_UNSUCCESSFUL: \"Delete failed\"\n  STR_IS_IT_OK_TO_DELETE_THE_SAVED_GAME: \"Are you sure you want to delete the saved game?\"\n  STR_ORIGINAL_XCOM: \"Original X-Com\"\n  STR_LOADING: \"Loading...\"\n  STR_DETAILS: \"DETAILS> {ALT}{0}\"\n  STR_NEW_BATTLE: \"New Battle\"\n  STR_OPTIONS: \"Options\"\n  STR_RIGHT_CLICK_TO_DELETE: \"Right click to delete.\"\n  STR_RESTORE_DEFAULTS: \"Restore Defaults\"\n  STR_CONTROLS: \"CONTROLS\"\n  STR_GENERAL: \"General\"\n  STR_GEOSCAPE: \"Geoscape\"\n  STR_BATTLESCAPE: \"Battlescape\"\n  STR_SCREENSHOT: \"Screenshot\"\n  STR_FPS_COUNTER: \"FPS Counter\"\n  STR_ROTATE_LEFT: \"Rotate Left\"\n  STR_ROTATE_RIGHT: \"Rotate Right\"\n  STR_ROTATE_UP: \"Rotate Up\"\n  STR_ROTATE_DOWN: \"Rotate Down\"\n  STR_ZOOM_IN: \"Zoom In\"\n  STR_ZOOM_OUT: \"Zoom Out\"\n  STR_TOGGLE_COUNTRY_DETAIL: \"Toggle Country Detail\"\n  STR_TOGGLE_RADAR_RANGES: \"Toggle Radar Ranges\"\n  STR_SCROLL_LEFT: \"Scroll Left\"\n  STR_SCROLL_RIGHT: \"Scroll Right\"\n  STR_SCROLL_UP: \"Scroll Up\"\n  STR_SCROLL_DOWN: \"Scroll Down\"\n  STR_UNIT_LEVEL_ABOVE: \"Move Unit to Level Above\"\n  STR_UNIT_LEVEL_BELOW: \"Move Unit to Level Below\"\n  STR_VIEW_LEVEL_ABOVE: \"View Level Above\"\n  STR_VIEW_LEVEL_BELOW: \"View Level Below\"\n  STR_CENTER_SELECTED_UNIT: \"Center Selected Unit\"\n  STR_PREVIOUS_UNIT: \"Select Previous Unit\"\n  STR_NEXT_UNIT: \"Select Next Unit\"\n  STR_DESELECT_UNIT: \"Don't Reselect Unit\"\n  STR_USE_LEFT_HAND: \"Use Left Hand Item\"\n  STR_USE_RIGHT_HAND: \"Use Right Hand Item\"\n  STR_INVENTORY: \"Inventory\"\n  STR_MINIMAP: \"Minimap\"\n  STR_MULTI_LEVEL_VIEW: \"Multi-Level View\"\n  STR_END_TURN: \"End Turn\"\n  STR_ABORT_MISSION: \"Abort Mission\"\n  STR_UNIT_STATS: \"Unit Stats\"\n  STR_KNEEL: \"Kneel\"\n  STR_RELOAD: \"Reload\"\n  STR_TOGGLE_PERSONAL_LIGHTING: \"Toggle Personal Lighting\"\n  STR_DONT_RESERVE_TIME_UNITS: \"Don't Reserve TUs\"\n  STR_RESERVE_TIME_UNITS_FOR_SNAP_SHOT: \"Reserve TUs for Snap Shot\"\n  STR_RESERVE_TIME_UNITS_FOR_AIMED_SHOT: \"Reserve TUs for Aimed Shot\"\n  STR_RESERVE_TIME_UNITS_FOR_AUTO_SHOT: \"Reserve TUs for Auto Shot\"\n  STR_CENTER_ON_ENEMY_1: \"Center on Enemy 1\"\n  STR_CENTER_ON_ENEMY_2: \"Center on Enemy 2\"\n  STR_CENTER_ON_ENEMY_3: \"Center on Enemy 3\"\n  STR_CENTER_ON_ENEMY_4: \"Center on Enemy 4\"\n  STR_CENTER_ON_ENEMY_5: \"Center on Enemy 5\"\n  STR_CENTER_ON_ENEMY_6: \"Center on Enemy 6\"\n  STR_CENTER_ON_ENEMY_7: \"Center on Enemy 7\"\n  STR_CENTER_ON_ENEMY_8: \"Center on Enemy 8\"\n  STR_CENTER_ON_ENEMY_9: \"Center on Enemy 9\"\n  STR_CENTER_ON_ENEMY_10: \"Center on Enemy 10\"\n  STR_CREATE_INVENTORY_TEMPLATE: \"Create inventory template\"\n  STR_APPLY_INVENTORY_TEMPLATE: \"Apply inventory template\"\n  STR_CLEAR_INVENTORY: \"Clear inventory\"\n  STR_AUTO_EQUIP: \"Auto-equip\"\n  STR_QUICK_SAVE: \"Quick Save\"\n  STR_QUICK_LOAD: \"Quick Load\"\n  STR_ADVANCED: \"ADVANCED\"\n  STR_AGGRESSIVERETALIATION: \"Aggressive retaliation\"\n  STR_AGGRESSIVERETALIATION_DESC: \"UFOs will attempt to detect your bases at all times, regardless of their mission parameters.\"\n  STR_STORAGELIMITSENFORCED: \"Storage limits for recovered items\"\n  STR_STORAGELIMITSENFORCED_DESC: \"Enforces alien containment and general store limits for live aliens and artifacts recovered from missions.\"\n  STR_CANSELLLIVEALIENS: \"Live alien sale\"\n  STR_CANSELLLIVEALIENS_DESC: \"Allows the sale of live aliens, recommended when using storage limits.\"\n  STR_ALLOWBUILDINGQUEUE: \"Allow building queue\"\n  STR_ALLOWBUILDINGQUEUE_DESC: \"New facilities can be placed next to unfinished ones.\"\n  STR_BATTLEAUTOEND: \"Auto-end battle\"\n  STR_BATTLEAUTOEND_DESC: \"Battles automatically end when the last living enemy is neutralized.\"\n  STR_BATTLEINSTANTGRENADE: \"Instant grenades\"\n  STR_BATTLEINSTANTGRENADE_DESC: \"Grenades primed to go off in 0 turns will explode immediately when thrown, instead of at the end of the turn.\"\n  STR_BATTLEUFOEXTENDERACCURACY: \"UFO Extender accuracy\"\n  STR_BATTLEUFOEXTENDERACCURACY_DESC: \"Accuracy of shots drops off after a certain distance, according to shot type. Adjusted accuracy will be displayed on the cursor.\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE: \"Airborne transfers\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE_DESC: \"Craft currently in-flight can be transferred.\"\n  STR_CRAFTLAUNCHALWAYS: \"Force craft launch\"\n  STR_CRAFTLAUNCHALWAYS_DESC: \"Craft can be launched even when they aren't ready, overriding the need for maintenance.\"\n  STR_CUSTOMINITIALBASE: \"Custom initial base\"\n  STR_CUSTOMINITIALBASE_DESC: \"When starting a new game, you can manually place your starting facilities instead of using the default layout.\"\n  STR_GLOBESEASONS: \"Realistic globe lighting\"\n  STR_GLOBESEASONS_DESC: \"Uses more realistic projection of sunlight on the Geoscape according to Earth's axial tilt.\"\n  STR_PLAYINTRO: \"Play intro\"\n  STR_PLAYINTRO_DESC: \"Show the intro cinematic on startup.\"\n  STR_SHOWMORESTATSININVENTORYVIEW: \"Inventory Stats\"\n  STR_SHOWMORESTATSININVENTORYVIEW_DESC: \"Show extra information on the selected soldier in the inventory screen.\"\n  STR_SNEAKYAI: \"Sneaky AI\"\n  STR_SNEAKYAI_DESC: \"AI avoids exposing themselves to the player whenever possible.\"\n  STR_STRAFE: \"Alternate movement methods\"\n  STR_STRAFE_DESC: \"Enables strafing, running, and independent tank turret movement when holding CTRL.\"\n  STR_BATTLEEXPLOSIONHEIGHT: \"Explosion height\"\n  STR_BATTLEEXPLOSIONHEIGHT_DESC: \"Change how far height-wise explosions may spread.{NEWLINE}(Flat: 0, Round: 3)\"\n  STR_AUTOSAVE: \"Autosave\"\n  STR_AUTOSAVE_DESC: \"Automatically saves the game at specified intervals. Doesn't apply to Ironman Mode.\"\n  STR_AUTOSAVE_FREQUENCY: \"Autosave Frequency\"\n  STR_AUTOSAVE_FREQUENCY_DESC: \"Amount of turns after which the game will be automatically saved.\"\n  STR_ALLOWPSIONICCAPTURE: \"Allow psi-capture\"\n  STR_ALLOWPSIONICCAPTURE_DESC: \"Mind-controlling all remaining aliens results in victory, and they count as live captures.\"\n  STR_ANYTIMEPSITRAINING: \"Psionic training at any time\"\n  STR_ANYTIMEPSITRAINING_DESC: \"Allows assigning soldiers to psionic training at any time of the month. Remember, initial training takes from 30 to 60 days.\"\n  STR_SKIPNEXTTURNSCREEN: \"Skip \\\"Next Turn\\\" screen\"\n  STR_SKIPNEXTTURNSCREEN_DESC: \"\\\"Next Turn\\\" screens during battle are advanced automatically after a short delay.\"\n  STR_NOT_ENOUGH_SPACE: \"Not Enough Space!\"\n  STR_WEAPONSELFDESTRUCTION: \"Alien weapon self-destruction\"\n  STR_WEAPONSELFDESTRUCTION_DESC: \"Weapons carried by aliens will self-destruct if their owner is killed, like in XCOM 2012.\"\n  STR_RETAINCORPSES: \"Retain interrogated aliens\"\n  STR_RETAINCORPSES_DESC: \"After \\\"researching\\\" living aliens, the body will be added to the base stores, like in XCOM 2012.\"\n  STR_SAVE_VOXEL_VIEW: \"Save First-Person Screenshot\"\n  STR_RESERVE_TIME_UNITS_FOR_KNEEL: \"Reserve TUs for kneeling\"\n  STR_EXPEND_ALL_TIME_UNITS: \"Expend all remaining Time Units\"\n  STR_PSISTRENGTHEVAL: \"Psi-Strength Evaluation\"\n  STR_PSISTRENGTHEVAL_DESC: \"Evaluates the psionic strength of all soldiers after the appropriate research has been completed.\"\n  STR_DISABLEAUTOEQUIP: \"Disable auto-equip\"\n  STR_DISABLEAUTOEQUIP_DESC: \"Disable auto-equipping of new soldiers before battle.\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT: \"Allow Psi-Strength Improvement\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT_DESC: \"Psionic strength of the soldiers can be improved by experience and training.\"\n  STR_BATTLESMOOTHCAMERA: \"Smooth Bullet Camera\"\n  STR_BATTLESMOOTHCAMERA_DESC: \"The Battlescape camera will remain centered on projectiles while in flight.\"\n  STR_BATTLECONFIRMFIREMODE: \"Confirm Fire mode\"\n  STR_BATTLECONFIRMFIREMODE_DESC: \"Require a second click on the same tile to confirm fire orders.\"\n  STR_SELECT_BASE_1: \"Select Base 1\"\n  STR_SELECT_BASE_2: \"Select Base 2\"\n  STR_SELECT_BASE_3: \"Select Base 3\"\n  STR_SELECT_BASE_4: \"Select Base 4\"\n  STR_SELECT_BASE_5: \"Select Base 5\"\n  STR_SELECT_BASE_6: \"Select Base 6\"\n  STR_SELECT_BASE_7: \"Select Base 7\"\n  STR_SELECT_BASE_8: \"Select Base 8\"\n  STR_VIDEO: \"VIDEO\"\n  STR_AUDIO: \"AUDIO\"\n  STR_BATTLESCAPE_UC: \"BATTLESCAPE\"\n  STR_MODS_UC: \"MODS\"\n  STR_MODS: \"Mods\"\n  STR_DISPLAY_RESOLUTION: \"Display Resolution\"\n  STR_DISPLAY_RESOLUTION_DESC: \"Changes the resolution of the display, the game resolution will be resized to match. Arrows switch between supported resolutions. Click to input a custom resolution.\"\n  STR_ORIGINAL: \"Original\"\n  STR_DISPLAY_MODE: \"Display Mode\"\n  STR_WINDOWED: \"Windowed\"\n  STR_FULLSCREEN: \"Fullscreen\"\n  STR_BORDERLESS: \"Borderless\"\n  STR_DISPLAY_LANGUAGE: \"Display Language\"\n  STR_DISPLAY_LANGUAGE_DESC: \"Changes the language of the in-game text.\"\n  STR_DISPLAY_FILTER: \"Display Filter\"\n  STR_DISPLAY_FILTER_DESC: \"Changes the filter applied to the game screen.{NEWLINE}*requires OpenGL hardware acceleration.\"\n  STR_DISPLAY_OPTIONS: \"Display Options\"\n  STR_LETTERBOXED: \"Letterboxed\"\n  STR_LETTERBOXED_DESC: \"Letterboxes the display to maintain the original aspect ratio.\"\n  STR_RESIZABLE: \"Resizable\"\n  STR_LOCK_MOUSE: \"Grab Mouse\"\n  STR_LOCK_MOUSE_DESC: \"Keeps the mouse cursor from leaving the game window. Ctrl+G to toggle at any time.\"\n  STR_FIXED_WINDOW_POSITION: \"Fixed Window Position\"\n  STR_FIXED_WINDOW_POSITION_DESC: \"Set fixed position to Window.\"\n  STR_DISPLAY_SET_WINDOW_POSITION: \"Set new Window Root position\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_X: \"Left border new X:\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_Y: \"Up border new Y:\"\n  STR_MUSIC_VOLUME: \"Music Volume\"\n  STR_MUSIC_VOLUME_DESC: \"Changes the volume of the background music.\"\n  STR_SFX_VOLUME: \"SFX Volume\"\n  STR_SFX_VOLUME_DESC: \"Changes the volume of the sound effects.\"\n  STR_UI_VOLUME: \"UI Volume\"\n  STR_UI_VOLUME_DESC: \"Changes the volume of the interface beeps.\"\n  STR_SCROLL_SPEED: \"Scroll Speed\"\n  STR_SCROLL_SPEED_GEO_DESC: \"Changes the scrolling speed of the globe.\"\n  STR_SCROLL_SPEED_BATTLE_DESC: \"Changes the scrolling speed of the map.\"\n  STR_DOGFIGHT_SPEED: \"Dogfight Speed\"\n  STR_DOGFIGHT_SPEED_DESC: \"Changes the speed of interception battles between crafts and UFOs. Slower speeds can improve performance on low-end devices.\"\n  STR_CLOCK_SPEED: \"Clock Speed\"\n  STR_CLOCK_SPEED_DESC: \"Changes the speed of the Geoscape clock. Slower speeds can improve performance on low-end devices.\"\n  STR_GLOBE_DETAILS: \"Globe Details\"\n  STR_GLOBE_COUNTRIES: \"Countries\"\n  STR_GLOBE_COUNTRIES_DESC: \"Shows funding countries on the globe.\"\n  STR_GLOBE_RADARS: \"Radars\"\n  STR_GLOBE_RADARS_DESC: \"Shows base radar ranges on the globe.\"\n  STR_GLOBE_FLIGHT_PATHS: \"Flight Paths\"\n  STR_GLOBE_FLIGHT_PATHS_DESC: \"Shows craft flight paths on the globe.\"\n  STR_CONTROLS_DESC: \"Left-click a shortcut and press a key to change it.{NEWLINE}Right-click a shortcut to disable it.\"\n  STR_BASE_GAME: \"Base game\"\n  STR_MODS_TOOLTIP: \"Version {0} by {1}.{NEWLINE}{2}\"\n  STR_EDGE_SCROLL: \"Edge Scroll\"\n  STR_EDGE_SCROLL_DESC: \"Trigger: Scroll map when the left mouse button is held down on a screen edge.{NEWLINE}Auto: Scroll map when the cursor is over a screen edge.\"\n  STR_TRIGGER_SCROLL: \"Trigger\"\n  STR_AUTO_SCROLL: \"Auto\"\n  STR_DRAG_SCROLL: \"Drag Scroll\"\n  STR_DRAG_SCROLL_DESC: \"Scrolls the map when the specified mouse button is held down and dragged.\"\n  STR_LEFT_MOUSE_BUTTON: \"Left Button\"\n  STR_MIDDLE_MOUSE_BUTTON: \"Middle Button\"\n  STR_RIGHT_MOUSE_BUTTON: \"Right Button\"\n  STR_FIRE_SPEED: \"Fire Speed\"\n  STR_FIRE_SPEED_DESC: \"Changes the speed of weapon projectiles.\"\n  STR_PLAYER_MOVEMENT_SPEED: \"Player Movement Speed\"\n  STR_PLAYER_MOVEMENT_SPEED_DESC: \"Changes the movement speed of player-controlled units.\"\n  STR_COMPUTER_MOVEMENT_SPEED: \"AI Movement Speed\"\n  STR_COMPUTER_MOVEMENT_SPEED_DESC: \"Changes the movement speed of computer-controlled units.\"\n  STR_PATH_PREVIEW: \"Path Preview\"\n  STR_PATH_ARROWS: \"Arrows\"\n  STR_PATH_ARROWS_DESC: \"Clicking shows the path your unit will take to the destination. Color indicates available actions: Green - can move and fire; Yellow - can move; Red - can't move.\"\n  STR_PATH_TIME_UNIT_COST: \"Time Units\"\n  STR_PATH_TIME_UNIT_COST_DESC: \"Clicking shows the TUs your unit will have remaining after moving to the destination.\"\n  STR_USER_INTERFACE_OPTIONS: \"UI Options\"\n  STR_TOOLTIPS: \"Tooltips\"\n  STR_TOOLTIPS_DESC: \"Displays tooltips for the Battlescape buttons.\"\n  STR_DEATH_NOTIFICATIONS: \"Death Notifications\"\n  STR_DEATH_NOTIFICATIONS_DESC: \"Pop up a notification detailing who was killed whenever a soldier dies.\"\n  STR_SHOW_FUNDS: \"Show Funds\"\n  STR_SHOW_FUNDS_DESC: \"Shows your current funds next to the Geoscape clock.\"\n  STR_MISSION_GENERATOR: \"MISSION GENERATOR\"\n  STR_MAP_OPTIONS: \"MAP OPTIONS\"\n  STR_ALIEN_OPTIONS: \"ALIEN OPTIONS\"\n  STR_MAP_TERRAIN: \"Terrain\"\n  STR_MAP_DARKNESS: \"Darkness\"\n  STR_MAP_DEPTH: \"Depth\"\n  STR_DIFFICULTY: \"Difficulty\"\n  STR_ALIEN_RACE: \"Race\"\n  STR_ALIEN_TECH_LEVEL: \"Tech Level\"\n  STR_RANDOMIZE: \"Randomize\"\n  STR_OXCE_REQUIRED_QUESTION: \"This mod requires OpenXcom {0} to run correctly. Enable this mod?\"\n  STR_RESTORE_DEFAULTS_QUESTION: \"Are you sure you want to restore the default options?\"\n  STR_DISPLAY_OPTIONS_CONFIRM: \"Do you want to keep the current display options?\"\n  STR_DISPLAY_OPTIONS_REVERT: \"Reverting in 0:{0}\"\n  STR_MISSING_CONTENT_PROMPT: \"WARNING:{SMALLLINE}This save relies on mods that are unavailable. Missing content will be removed, and it may fail to load.{NEWLINE}Continue?\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT: \"Save pre-primed grenades\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT_DESC: \"Saves grenades primed during pre-battle inventory in the soldier's equipment layout.\"\n  STR_NEWSEEDONLOAD: \"Save scumming\"\n  STR_NEWSEEDONLOAD_DESC: \"Loading a game will reset the random number seed, so taking the same action can yield different results. Doesn't apply to Ironman Mode.\"\n  STR_CHANGEVALUEBYMOUSEWHEEL: \"Change values with mouse wheel\"\n  STR_CHANGEVALUEBYMOUSEWHEEL_DESC: \"Allows you to use the mouse wheel to increase/decrease values by this amount.\"\n  STR_BATTLEHAIRBLEACH: \"Enhanced soldier sprites\"\n  STR_BATTLEHAIRBLEACH_DESC: \"Changes soldier Battlescape sprites to match their inventory look.\"\n  STR_DRAGSCROLLINVERT: \"Invert drag-scrolling\"\n  STR_DRAGSCROLLINVERT_DESC: \"When enabled, dragging scrolls in the opposite direction to the mouse.\"\n  STR_BATTLESCAPE_SCALE: \"Battlescape Scale\"\n  STR_BATTLESCAPE_SCALE_DESC: \"Battlescape viewport scaling mode, based on a fixed resolution (stretched to fit), or a fixed zoom level (expanded to fill).\"\n  STR_GEOSCAPE_SCALE: \"Geoscape Scale\"\n  STR_GEOSCAPESCALE_SCALE_DESC: \"Geoscape viewport scaling mode, based on a fixed resolution (stretched to fit), or a fixed zoom level (expanded to fill).\"\n  STR_1_5X: \"1.5x Original\"\n  STR_2X: \"2x Original\"\n  STR_THIRD_DISPLAY: \"1/3 Display\"\n  STR_HALF_DISPLAY: \"1/2 Display\"\n  STR_FULL_DISPLAY: \"Full Display\"\n  STR_FPS_LIMIT: \"FPS limit\"\n  STR_FPS_LIMIT_DESC: \"Limits the number of screen updates per second, 0 for no limit. If OpenGL rendering is enabled, the game uses Vsync instead.\"\n  STR_FPS_INACTIVE_LIMIT: \"FPS limit background\"\n  STR_FPS_INACTIVE_LIMIT_DESC: \"Limits the number of screen updates per second if OpenXcom is in the background.\"\n  STR_NOALIENPANICMESSAGES: \"Suppress panic messages for aliens\"\n  STR_NOALIENPANICMESSAGES_DESC: \"Don't show panic messages for aliens unless they are visible to the player.\"\n  STR_ALIENBLEEDING: \"Alien bleeding\"\n  STR_ALIENBLEEDING_DESC: \"Allows fatal wounds to be inflicted on most aliens.\"\n  STR_FIELDPROMOTIONS: \"Field promotions\"\n  STR_FIELDPROMOTIONS_DESC: \"Only soldiers that were present at the mission site are eligible for promotion.\"\n  STR_MEETINGPOINT: \"Predict UFO trajectory\"\n  STR_MEETINGPOINT_DESC: \"Crafts fly towards a meeting point with the UFO based on its current trajectory.\"\n  STR_IRONMAN: \"IRONMAN\"\n  STR_IRONMAN_DESC: \"No manual saving\"\n  STR_SAVE_AND_ABANDON_GAME: \"SAVE AND ABANDON GAME\"\n  STR_MOD_UNSUCCESSFUL: \"Mod failed to load\"\n  STR_NEW_SAVED_GAME_SLOT: \"<NEW SAVED GAME>\"\n  STR_AUTO_SAVE_GEOSCAPE_SLOT: \"<AUTO GEOSCAPE>\"\n  STR_AUTO_SAVE_BATTLESCAPE_SLOT: \"<AUTO BATTLESCAPE>\"\n  STR_QUICK_SAVE_SLOT: \"<QUICKSAVE>\"\n  STR_DISPLAY_MODE_DESC: \"Change how the game is displayed on your screen.\"\n  STR_PREFERRED_MUSIC_FORMAT: \"Music Format\"\n  STR_PREFERRED_MUSIC_FORMAT_DESC: \"Chooses the preferred music format to use when multiple ones are available.{NEWLINE}NOTE: MIDI playback may be buggy on Windows.\"\n  STR_PREFERRED_SFX_FORMAT: \"SFX Format\"\n  STR_PREFERRED_SFX_FORMAT_DESC: \"Chooses the preferred sound effects format to use when multiple ones are available.\"\n  STR_PREFERRED_VIDEO_FORMAT: \"Video Format\"\n  STR_PREFERRED_VIDEO_FORMAT_DESC: \"Chooses the preferred video format to use when multiple ones are available.\"\n  STR_PREFERRED_VIDEO_ANIMATION: \"Animation\"\n  STR_PREFERRED_VIDEO_SLIDESHOW: \"Slideshow\"\n  STR_PREFERRED_FORMAT_AUTO: \"Auto\"\n  STR_CURRENT_FORMAT: \"Current: {0}\"\n  STR_SOUND_OPTIONS: \"Sound Options\"\n  STR_BACKGROUND_MUTE: \"Background Mute\"\n  STR_BACKGROUND_MUTE_DESC: \"Mutes all sound when the game window is not active.\"\n  STR_FORCE_FIRE: \"Override Line of Fire\"\n  STR_FORCE_FIRE_DESC: \"Enables forcing your soldiers to take a shot when holding CTRL, regardless of line of fire rules.\"\n  STR_NO_AUDIO_HARDWARE_DETECTED: \"No audio hardware detected\"\n  STR_MOUSEWHEEL_SPEED: \"Mouse wheel scroll speed\"\n  STR_MOUSEWHEEL_SPEED_DESC: \"Adjusts the number of lines scrolled in lists with each increment of the mouse wheel.\"\n  STR_DISABLED: \"Disabled\"\n  STR_MAXIMIZE_INFO_SCREENS: \"Maximize info screens\"\n  STR_MAXIMIZE_INFO_SCREENS_DESC: \"Inventory and various other screens will be displayed at full screen, regardless of scale settings.\"\n  STR_DIARY: \"DIARY\"\n  STR_KILLED: \"KILLED\"\n  STR_STUNNED: \"STUNNED\"\n  STR_PANICKED: \"PANICKED\"\n  STR_MINDCONTROLLED: \"CONTROLLED\"\n  STR_REGION_UNKNOWN: \"Undisclosed\"\n  STR_WEAPON_UNKNOWN: \"Improvisation\"\n  STR_UNKNOWN: \"Unknown\"\n  STR_VICTORY: \"Victory\"\n  STR_DEFEAT: \"Defeat\"\n  STR_NO_RECORD: \"No record\"\n  STR_HUMAN: \"Human\"\n  STR_FRIENDLY: \"Friendly\"\n  STR_HOSTILE: \"Hostile\"\n  STR_NEUTRAL: \"Neutral\"\n  STR_RATING_UC: \"RATING\"\n  STR_LOCATION: \"LOCATION> {ALT}{0}\"\n  STR_DAYLIGHT_TYPE: \"TIME> {ALT}{0}\"\n  STR_RACE_TYPE: \"RACE> {ALT}{0}\"\n  STR_DAY: \"Day\"\n  STR_NIGHT: \"Night\"\n  STR_DAYS_WOUNDED: \"DAYS WOUNDED> {ALT}{0}\"\n  STR_COMBAT: \"COMBAT\"\n  STR_PERFORMANCE: \"PERFORMANCE\"\n  STR_NEUTRALIZATIONS_BY_RACE: \"NEUTRALIZATIONS BY RACE\"\n  STR_NEUTRALIZATIONS_BY_RANK: \"NEUTRALIZATIONS BY RANK\"\n  STR_NEUTRALIZATIONS_BY_WEAPON: \"NEUTRALIZATIONS BY WEAPON\"\n  STR_MISSIONS_BY_LOCATION: \"MISSIONS BY LOCATION\"\n  STR_MISSIONS_BY_TYPE: \"MISSIONS BY TYPE\"\n  STR_MISSIONS_BY_UFO: \"MISSIONS BY UFO\"\n  STR_SCORE_VALUE: \"SCORE> {ALT}{0}\"\n  STR_WINS: \"WINS> {ALT}{0}\"\n  STR_STUNS: \"STUNS> {ALT}{0}\"\n  STR_PANICKS: \"PANICKS> {ALT}{0}\"\n  STR_MINDCONTROLS: \"CONTROLS> {ALT}{0}\"\n  STR_AWARDS: \"AWARDS\"\n  STR_COMMENDATIONS_UC: \"COMMENDATIONS\"\n  STR_COMMENDATIONS: \"Commendations\"\n  STR_MEDALS: \"MEDALS\"\n  STR_LOST_IN_SERVICE: \"LOST IN SERVICE\"\n  STR_MEDAL_NAME: \"Medal Name\"\n  STR_MEDAL_AWARD_LEVEL: \"Award Level\"\n  STR_MEDAL_DECOR_LEVEL: \"Decoration Level\"\n  STR_AWARD_0: \"First award\"\n  STR_AWARD_1: \"Second award\"\n  STR_AWARD_2: \"Third award\"\n  STR_AWARD_3: \"Fourth award\"\n  STR_AWARD_4: \"Fifth award\"\n  STR_AWARD_5: \"Sixth award\"\n  STR_AWARD_6: \"Seventh award\"\n  STR_AWARD_7: \"Eighth award\"\n  STR_AWARD_8: \"Ninth award\"\n  STR_AWARD_9: \"Tenth award\"\n  STR_AWARD_DECOR_0: \"None\"\n  STR_AWARD_DECOR_1: \"First bronze pin\"\n  STR_AWARD_DECOR_2: \"Second bronze pin\"\n  STR_AWARD_DECOR_3: \"Third bronze pin\"\n  STR_AWARD_DECOR_4: \"First silver pin\"\n  STR_AWARD_DECOR_5: \"Second silver pin\"\n  STR_AWARD_DECOR_6: \"Third silver pin\"\n  STR_AWARD_DECOR_7: \"First gold pin\"\n  STR_AWARD_DECOR_8: \"Second gold pin\"\n  STR_AWARD_DECOR_9: \"Third gold pin\"\n  STR_KILLED_IN_ACTION_MALE: \"KILLED IN ACTION\"\n  STR_KILLED_IN_ACTION_FEMALE: \"KILLED IN ACTION\"\n  STR_MISSING_IN_ACTION_MALE: \"MISSING IN ACTION\"\n  STR_MISSING_IN_ACTION_FEMALE: \"MISSING IN ACTION\"\n  STR_AVERAGE_MONTHLY_RATING: \"Average monthly rating\"\n  STR_TOTAL_INCOME: \"Total income\"\n  STR_TOTAL_EXPENDITURE: \"Total expenditure\"\n  STR_MISSIONS_WON: \"Missions accomplished\"\n  STR_MISSIONS_LOST: \"Missions failed\"\n  STR_NIGHT_MISSIONS: \"Night missions\"\n  STR_BEST_RATING: \"Best mission rating\"\n  STR_WORST_RATING: \"Worst mission rating\"\n  STR_ALIEN_KILLS: \"Aliens killed\"\n  STR_ALIEN_CAPTURES: \"Aliens captured\"\n  STR_FRIENDLY_KILLS: \"Friendly fire incidents\"\n  STR_AVERAGE_ACCURACY: \"Average accuracy\"\n  STR_WEAPON_MOST_KILLS: \"Most effective weapon\"\n  STR_ALIEN_MOST_KILLS: \"Deadliest alien\"\n  STR_LONGEST_SERVICE: \"Longest months in service\"\n  STR_TOTAL_DAYS_WOUNDED: \"Sick days\"\n  STR_COUNTRIES_LOST: \"Countries infiltrated\"\n  STR_TOTAL_TERROR_SITES: \"Terror attacks\"\n  STR_TOTAL_BASES: \"Bases built\"\n  STR_TOTAL_CRAFT: \"Craft owned\"\n  STR_TOTAL_SCIENTISTS: \"Scientists hired\"\n  STR_TOTAL_ENGINEERS: \"Engineers hired\"\n  STR_TOTAL_RESEARCH: \"Research completed\"\n  STR_DIARY_ACCURACY: \"ACCURACY> {ALT}{0}%\"\n  STR_STATISTICS: \"Statistics\"\n  STR_STATS: \"STATS\"\n  STR_TIME_UNITS_ABBREVIATION: \"TU\"\n  STR_STAMINA_ABBREVIATION: \"STA\"\n  STR_HEALTH_ABBREVIATION: \"HP\"\n  STR_BRAVERY_ABBREVIATION: \"BRV\"\n  STR_REACTIONS_ABBREVIATION: \"REA\"\n  STR_FIRING_ACCURACY_ABBREVIATION: \"ACC\"\n  STR_THROWING_ACCURACY_ABBREVIATION: \"THR\"\n  STR_STRENGTH_ABBREVIATION: \"STR\"\n  STR_MELEE_ACCURACY_ABBREVIATION: \"MEL\"\n  STR_FOLDERS: \"FOLDERS\"\n  STR_DATA_FOLDER: \"Data Folder (original resources)\"\n  STR_USER_FOLDER: \"User Folder (mods, openxcom.log)\"\n  STR_SAVE_FOLDER: \"Save Folder (saved games, screenshots)\"\n  STR_CONFIG_FOLDER: \"Config Folder (options.cfg)\"\n  STR_DATA_FOLDER_DESC_1: \"This is where OpenXcom looks for the original game resources (UFO and/or TFTD).\"\n  STR_DATA_FOLDER_DESC_2: \"OpenXcom internal resources are in the 'common' folder. OpenXcom built-in mods are in the 'standard' folder.\"\n  STR_USER_FOLDER_DESC: \"The log file ('openxcom.log') is stored here. All custom mods belong here too (in the 'mods' sub-folder).\"\n  STR_SAVE_FOLDER_DESC: \"Your saved games are located here. Also, the mission generator settings ('battle.cfg') can be found here.\"\n  STR_CONFIG_FOLDER_DESC: \"This is where OpenXcom settings ('options.cfg') are stored. Normally the same as the User Folder.\"\n"
  },
  {
    "path": "bin/common/Language/es-419.yml",
    "content": "es-419:\n  STR_OPENXCOM: \"OpenXcom\"\n  STR_NEW_GAME: \"Nuevo Juego\"\n  STR_LOAD_SAVED_GAME: \"Cargar Juego\"\n  STR_SELECT_DIFFICULTY_LEVEL: \"Seleccione Nivel de Dificultad\"\n  STR_1_BEGINNER: \"1> Principiante\"\n  STR_2_EXPERIENCED: \"2> Experimentado\"\n  STR_3_VETERAN: \"3> Veterano\"\n  STR_4_GENIUS: \"4> Genio\"\n  STR_5_SUPERHUMAN: \"5> Sobrehumano\"\n  STR_TIME: \"Hora\"\n  STR_DATE: \"Día\"\n  STR_SELECT_GAME_TO_LOAD: \"Seleccione un juego para cargar\"\n  STR_SELECT_SAVE_POSITION: \"Seleccione posición de guardado\"\n  STR_GAME_OPTIONS: \"OPCIONES DEL JUEGO\"\n  STR_LOAD_GAME: \"CARGAR JUEGO\"\n  STR_SAVE_GAME: \"GUARDAR JUEGO\"\n  STR_ABANDON_GAME: \"ABANDONAR JUEGO\"\n  STR_ABANDON_GAME_QUESTION: \"¿ABANDONAR EL JUEGO?\"\n  STR_QUIT: \"Salir\"\n  STR_SAVING_GAME: \"Guardando juego\"\n  STR_LOADING_GAME: \"Cargando juego\"\n  STR_NO_SAVED_GAME_PRESENT: \"No hay juego guardado\"\n  STR_LOAD_UNSUCCESSFUL: \"Carga de juego fracasó\"\n  STR_SAVE_UNSUCCESSFUL: \"Guardado de juego fracasó\"\n  STR_LOAD_SUCCESSFUL: \"Cargado exitoso.\"\n  STR_SAVE_SUCCESSFUL: \"Guardado exitoso\"\n  STR_DELETE: \"BORRAR\"\n  STR_DELETE_UNSUCCESSFUL: \"Borrado de juego fracasó\"\n  STR_IS_IT_OK_TO_DELETE_THE_SAVED_GAME: \"¿Quieres borrar el juego guardado?\"\n  STR_ORIGINAL_XCOM: \"X-Com Original\"\n  STR_LOADING: \"Cargando...\"\n  STR_DETAILS: \"DETALLES> {ALT}{0}\"\n  STR_NEW_BATTLE: \"Nueva Batalla\"\n  STR_OPTIONS: \"Opciones\"\n  STR_RIGHT_CLICK_TO_DELETE: \"Presione el botón derecho para borrar.\"\n  STR_RESTORE_DEFAULTS: \"Configuración Original\"\n  STR_CONTROLS: \"CONTROLES\"\n  STR_GENERAL: \"General\"\n  STR_GEOSCAPE: \"Geoescape\"\n  STR_BATTLESCAPE: \"Batalla\"\n  STR_SCREENSHOT: \"Captura de Pantalla\"\n  STR_FPS_COUNTER: \"Contador FPS\"\n  STR_ROTATE_LEFT: \"Rotar Izquierda\"\n  STR_ROTATE_RIGHT: \"Rotar Derecha\"\n  STR_ROTATE_UP: \"Rotar Arriba\"\n  STR_ROTATE_DOWN: \"Rotar Abajo\"\n  STR_ZOOM_IN: \"Acercar\"\n  STR_ZOOM_OUT: \"Alejar\"\n  STR_TOGGLE_COUNTRY_DETAIL: \"Activar Detalle de Paises\"\n  STR_TOGGLE_RADAR_RANGES: \"Activar Rangos de Radar\"\n  STR_SCROLL_LEFT: \"Desplazar Izquierda\"\n  STR_SCROLL_RIGHT: \"Desplazar Derecha\"\n  STR_SCROLL_UP: \"Desplazar Arriba\"\n  STR_SCROLL_DOWN: \"Desplazar Abajo\"\n  STR_UNIT_LEVEL_ABOVE: \"Mover unidad al nivel superior\"\n  STR_UNIT_LEVEL_BELOW: \"Mover unidad al nivel inferior\"\n  STR_VIEW_LEVEL_ABOVE: \"Ver nivel superior\"\n  STR_VIEW_LEVEL_BELOW: \"Ver nivel inferior\"\n  STR_CENTER_SELECTED_UNIT: \"Centrar en Unidad seleccionada\"\n  STR_PREVIOUS_UNIT: \"Unidad Anterior\"\n  STR_NEXT_UNIT: \"Unidad Siguiente\"\n  STR_DESELECT_UNIT: \"Excluir Unidad\"\n  STR_USE_LEFT_HAND: \"Usar objeto en la mano izquierda\"\n  STR_USE_RIGHT_HAND: \"Usar objeto en la mano derecha\"\n  STR_INVENTORY: \"Inventario\"\n  STR_MINIMAP: \"Minimapa\"\n  STR_MULTI_LEVEL_VIEW: \"Vista Multi-nivel\"\n  STR_END_TURN: \"Finalizar Turno\"\n  STR_ABORT_MISSION: \"Abortar Mision\"\n  STR_UNIT_STATS: \"Estadisticas de Unidad\"\n  STR_KNEEL: \"Arrodillarse\"\n  STR_RELOAD: \"Recargar\"\n  STR_TOGGLE_PERSONAL_LIGHTING: \"Activar Iluminacion Personal\"\n  STR_DONT_RESERVE_TIME_UNITS: \"No Reservar UTs\"\n  STR_RESERVE_TIME_UNITS_FOR_SNAP_SHOT: \"Reservar UTs para disparo simple\"\n  STR_RESERVE_TIME_UNITS_FOR_AIMED_SHOT: \"Reservar UTs para disparo de precisión\"\n  STR_RESERVE_TIME_UNITS_FOR_AUTO_SHOT: \"Reservar UTs para rafaga\"\n  STR_CENTER_ON_ENEMY_1: \"Centrar en Enemigo 1\"\n  STR_CENTER_ON_ENEMY_2: \"Centrar en Enemigo 2\"\n  STR_CENTER_ON_ENEMY_3: \"Centrar en Enemigo 3\"\n  STR_CENTER_ON_ENEMY_4: \"Centrar en Enemigo 4\"\n  STR_CENTER_ON_ENEMY_5: \"Centrar en Enemigo 5\"\n  STR_CENTER_ON_ENEMY_6: \"Centrar en Enemigo 6\"\n  STR_CENTER_ON_ENEMY_7: \"Centrar en Enemigo 7\"\n  STR_CENTER_ON_ENEMY_8: \"Centrar en Enemigo 8\"\n  STR_CENTER_ON_ENEMY_9: \"Centrar en Enemigo 9\"\n  STR_CENTER_ON_ENEMY_10: \"Centrar en Enemigo 10\"\n  STR_CREATE_INVENTORY_TEMPLATE: \"Crear plantilla de inventario\"\n  STR_APPLY_INVENTORY_TEMPLATE: \"Aplicar plantilla de inventario\"\n  STR_CLEAR_INVENTORY: \"Limpiar Inventario\"\n  STR_AUTO_EQUIP: \"Equipamiento automático\"\n  STR_QUICK_SAVE: \"Guardado Rápido\"\n  STR_QUICK_LOAD: \"Carga Rápida\"\n  STR_ADVANCED: \"AVANZADO\"\n  STR_AGGRESSIVERETALIATION: \"Represalias agresivas\"\n  STR_AGGRESSIVERETALIATION_DESC: \"Esta opción permite que los OVNIs intenten detectar sus bases en todo momento, independiente de los parámetros de la misión alienígena.\"\n  STR_STORAGELIMITSENFORCED: \"Limite de almacenamiento para items recobrados\"\n  STR_STORAGELIMITSENFORCED_DESC: \"Refuerza los limites de contención y de almacenes generales para alienígenas vivos y artefactos recobrados de misiones.\"\n  STR_CANSELLLIVEALIENS: \"Venta de alienígenas vivos\"\n  STR_CANSELLLIVEALIENS_DESC: \"Permite la venta de alinigenas vivos, recomendado cuando se usa el limite de almacenamiento.\"\n  STR_ALLOWBUILDINGQUEUE: \"Permitir construcción en sequencia\"\n  STR_ALLOWBUILDINGQUEUE_DESC: \"Las nuevas instalaciones se pueden colocar junto a las incompletas.\"\n  STR_BATTLEAUTOEND: \"Batalla - final automático\"\n  STR_BATTLEAUTOEND_DESC: \"Esta opción permite que las batallas terminen automáticamente cuando se neutraliza el último enemigo vivo.\"\n  STR_BATTLEINSTANTGRENADE: \"Granadas instantánea\"\n  STR_BATTLEINSTANTGRENADE_DESC: \"Esta opción permite que las granadas activadas para detonar en 0 turnos explotaran de inmediato cuando se lanzan, en lugar de al final del turno.\"\n  STR_BATTLEUFOEXTENDERACCURACY: \"Precisión basada en Ufo Extender\"\n  STR_BATTLEUFOEXTENDERACCURACY_DESC: \"Precisión de los tiros disminuye después de cierta distancia, de acuerdo al tipo de tiro. La precisión modificada se mostrará en el cursor.\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE: \"Transferencias cuando en vuelo\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE_DESC: \"Esta opción permite que aeronaves que se encuentran en vuelo pueden ser transferidas.\"\n  STR_CRAFTLAUNCHALWAYS: \"Forzar despegue de aeronaves\"\n  STR_CRAFTLAUNCHALWAYS_DESC: \"Aeronaves pueden ser lanzadas incluso cuando no están listas, obviando  la necesidad de mantenimiento.\"\n  STR_CUSTOMINITIALBASE: \"Base inicial personalizada\"\n  STR_CUSTOMINITIALBASE_DESC: \"Esta opción permite al iniciar un nuevo juego, poder colocar manualmente sus instalaciones en lugar de utilizar el diseño predeterminado.\"\n  STR_GLOBESEASONS: \"Iluminacion realista del globo\"\n  STR_GLOBESEASONS_DESC: \"Utiliza proyección más realista de la luz solar sobre el globo en función de la inclinación axial de la Tierra.\"\n  STR_PLAYINTRO: \"Reproducir Introducción\"\n  STR_PLAYINTRO_DESC: \"Esta opción permite mostrar la introducción cinemática al inicio.\"\n  STR_SHOWMORESTATSININVENTORYVIEW: \"Estadísticas en el Inventario\"\n  STR_SHOWMORESTATSININVENTORYVIEW_DESC: \"Esta opción permite mostrar más información sobre el soldado en la pantalla de inventario.\"\n  STR_SNEAKYAI: \"IA Sigilosa\"\n  STR_SNEAKYAI_DESC: \"Esta opción permite que la inteligencia artificial (IA) evite exponer sus unidades al jugador siempre que sea posible.\"\n  STR_STRAFE: \"Métodos de movimiento alternos\"\n  STR_STRAFE_DESC: \"Permite disparar, correr y el movimiento de la torreta del tanque, independiente, al sostener CTRL.\"\n  STR_BATTLEEXPLOSIONHEIGHT: \"Altura de explosión\"\n  STR_BATTLEEXPLOSIONHEIGHT_DESC: \"Esta opción permite cambiar la altura que las explosiones pueden extenderse {NEWLINE} (Plana: 0, Circular: 3)\"\n  STR_AUTOSAVE: \"Guardado Automático\"\n  STR_AUTOSAVE_DESC: \"Guarda automáticamente el juego en los intervalos especificados. No se aplica al modo Ironman.\"\n  STR_AUTOSAVE_FREQUENCY: \" Frecuencia de auto-guardado\"\n  STR_AUTOSAVE_FREQUENCY_DESC: \"Cantidad de turnos después de los cuales el juego se guardará automáticamente.\"\n  STR_ALLOWPSIONICCAPTURE: \"Permitir captura psíquica\"\n  STR_ALLOWPSIONICCAPTURE_DESC: \"Esta opción permite que al controlar mentalmente a todos los alienígena restantes, la misión finaliza automáticamente, y los alienígenas cuentan como las capturas vivas.\"\n  STR_ANYTIMEPSITRAINING: \"Entrenamineto psíquico en cualquier momento\"\n  STR_ANYTIMEPSITRAINING_DESC: \"Permite asignar soldados a la formación psíquica en cualquier momento del mes. Recuerde, el entrenamiento inicial tarda de 30 a 60 días.\"\n  STR_SKIPNEXTTURNSCREEN: \"Omitir pantalla \\\"Siguiente Turno\\\"\"\n  STR_SKIPNEXTTURNSCREEN_DESC: \"Notificaciones \\\"Siguiente Turno\\\" durante combate pasan automaticamente tras un pequeño retrazo.\"\n  STR_NOT_ENOUGH_SPACE: \"¡No hay suficiente espacio!\"\n  STR_WEAPONSELFDESTRUCTION: \"Autodestrucción de armas alienígenas\"\n  STR_WEAPONSELFDESTRUCTION_DESC: \"Armas portadas por los alienígenas se autodestruyen al morir su dueño, como en XCOM 2012.\"\n  STR_RETAINCORPSES: \"Conservar los alienígenas interrogados\"\n  STR_RETAINCORPSES_DESC: \"Después de \\\"investigandos\\\" los alienígenas vivos, se añadirá a los almacenes de la base los cuerpos, como en XCOM 2012.\"\n  STR_SAVE_VOXEL_VIEW: \"Captura de pantalla en primera persona\"\n  STR_RESERVE_TIME_UNITS_FOR_KNEEL: \"Reservar UTs para arrodillarse\"\n  STR_EXPEND_ALL_TIME_UNITS: \"Consumir UTs restantes\"\n  STR_PSISTRENGTHEVAL: \"Evaluación de fuerza psíquica \"\n  STR_PSISTRENGTHEVAL_DESC: \"Evalúa la fuerza psíquica de los soldados después que la debida investigación ha concluido.\"\n  STR_DISABLEAUTOEQUIP: \"Desactivar equipamiento automático\"\n  STR_DISABLEAUTOEQUIP_DESC: \"Desactiva el equipamiento automático de nuevos soldados antes de una batalla\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT: \"Permitir mejora en Fuerza-Psi\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT_DESC: \"La fuerza psíquica de los soldados puede ser mejorada por la experiencia y la formación.\"\n  STR_BATTLESMOOTHCAMERA: \"Visión fluida de balas\"\n  STR_BATTLESMOOTHCAMERA_DESC: \"La cámara se mantendrá centrada en los proyectiles durante la batalla\"\n  STR_BATTLECONFIRMFIREMODE: \"Confirmar Disparo\"\n  STR_BATTLECONFIRMFIREMODE_DESC: \"Requiere presionar dos veces en la misma casilla para confirmar el disparo.\"\n  STR_SELECT_BASE_1: \"Seleccionar Base 1\"\n  STR_SELECT_BASE_2: \"Seleccionar Base 2\"\n  STR_SELECT_BASE_3: \"Seleccionar Base 3\"\n  STR_SELECT_BASE_4: \"Seleccionar Base 4\"\n  STR_SELECT_BASE_5: \"Seleccionar Base 5\"\n  STR_SELECT_BASE_6: \"Seleccionar Base 6\"\n  STR_SELECT_BASE_7: \"Seleccionar Base 7\"\n  STR_SELECT_BASE_8: \"Seleccionar Base 8\"\n  STR_VIDEO: \"VIDEO\"\n  STR_AUDIO: \"AUDIO\"\n  STR_BATTLESCAPE_UC: \"BATALLA\"\n  STR_MODS_UC: \"MODS\"\n  STR_MODS: \"Mods\"\n  STR_DISPLAY_RESOLUTION: \"Resolución de pantalla\"\n  STR_DISPLAY_RESOLUTION_DESC: \"Cambia la resolución de la pantalla, la resolución del juego será redimensionada para que coincida. Las flechas cambiar entre las resoluciones soportadas. Haga clic para introducir una resolución personalizada.\"\n  STR_ORIGINAL: \"Original\"\n  STR_DISPLAY_MODE: \"Modo de visualización\"\n  STR_WINDOWED: \"En ventana\"\n  STR_FULLSCREEN: \"Pantalla completa\"\n  STR_BORDERLESS: \"Sin bordes\"\n  STR_DISPLAY_LANGUAGE: \"Idioma mostrado\"\n  STR_DISPLAY_LANGUAGE_DESC: \"Cambia el idioma del texto mostrado.\"\n  STR_DISPLAY_FILTER: \"Filtro de Pantalla\"\n  STR_DISPLAY_FILTER_DESC: \"Cambia el filtro aplicado a la pantalla de juego.{NEWLINE}*requiere aceleración de hardware OpenGL.\"\n  STR_DISPLAY_OPTIONS: \"Opciones de visualización\"\n  STR_LETTERBOXED: \"Letterbox\"\n  STR_LETTERBOXED_DESC: \"Coloca las barras laterales \\\"Letterbox\\\" para mantener el aspecto original.\"\n  STR_RESIZABLE: \"Redimensionable\"\n  STR_LOCK_MOUSE: \"Tomar raton\"\n  STR_LOCK_MOUSE_DESC: \"Evita que el cursor del ratón salga de la ventana de juego. Ctrl + G para cambiar en cualquier momento.\"\n  STR_FIXED_WINDOW_POSITION: \"Posición de Ventana ajustada\"\n  STR_FIXED_WINDOW_POSITION_DESC: \"Establecer ajuste de ventana.\"\n  STR_DISPLAY_SET_WINDOW_POSITION: \"Establecer nueva posición de ventana Raíz\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_X: \"Borde izquierdo nuevo X:\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_Y: \"Borde superior nuevo Y:\"\n  STR_MUSIC_VOLUME: \"Volumen de la música\"\n  STR_MUSIC_VOLUME_DESC: \"Cambia el volumen de la música. \"\n  STR_SFX_VOLUME: \"Volumen de EdS\"\n  STR_SFX_VOLUME_DESC: \"Cambia el volumen de los efectos de sonido.\"\n  STR_UI_VOLUME: \"Volumen de la interfaz\"\n  STR_UI_VOLUME_DESC: \"Cambia el volumen del sonidos del interfaz\"\n  STR_SCROLL_SPEED: \"Vel. de Desp.\"\n  STR_SCROLL_SPEED_GEO_DESC: \"Cambia la velocidad de desplazamiento del globo.\"\n  STR_SCROLL_SPEED_BATTLE_DESC: \"Cambia la velocidad de desplazamiento del mapa.\"\n  STR_DOGFIGHT_SPEED: \"Velocidad de Caza\"\n  STR_DOGFIGHT_SPEED_DESC: \"Cambia la velocidad de las batallas de interceptación entre los cazas y los ovnis. Las velocidades más bajas pueden mejorar el rendimiento en los dispositivos de gama baja.\"\n  STR_CLOCK_SPEED: \"Velocidad del reloj\"\n  STR_CLOCK_SPEED_DESC: \"Cambia la velocidad del reloj de Geoescape. Las velocidades más bajas pueden mejorar el rendimiento en los dispositivos de gama baja.\"\n  STR_GLOBE_DETAILS: \"Detalles geográficos.\"\n  STR_GLOBE_COUNTRIES: \"Países\"\n  STR_GLOBE_COUNTRIES_DESC: \"Muestra los países financistas en el globo.\"\n  STR_GLOBE_RADARS: \"Radares\"\n  STR_GLOBE_RADARS_DESC: \"Muestra el alcance de radar en el globo.\"\n  STR_GLOBE_FLIGHT_PATHS: \"Rutas de vuelo\"\n  STR_GLOBE_FLIGHT_PATHS_DESC: \"Muestra las rutas de vuelo de las naves.\"\n  STR_CONTROLS_DESC: \"Haga clic izquierdo en un acceso directo y pulse una tecla para cambiarlo. {NEWLINE} Haga clic en un acceso directo para desactivarlo.\"\n  STR_BASE_GAME: \"Juego básico\"\n  STR_MODS_TOOLTIP: \"Versión {0} por {1}. {NEWLINE} {2}\"\n  STR_EDGE_SCROLL: \"Desplazamiento del borde\"\n  STR_EDGE_SCROLL_DESC: \"Forzado: desplaza el mapa cuando se mantiene pulsado el botón izquierdo del ratón sobre un borde de la pantalla {NEWLINE} Automatico: desplaza el mapa cuando el cursor está sobre un borde de la pantalla.\"\n  STR_TRIGGER_SCROLL: \"Forzado\"\n  STR_AUTO_SCROLL: \"Automático\"\n  STR_DRAG_SCROLL: \"Desplazar arrastrando\"\n  STR_DRAG_SCROLL_DESC: \"Se desplaza por el mapa cuando se mantiene pulsado el botón especifico del mouse y se arrastra.\"\n  STR_LEFT_MOUSE_BUTTON: \"Botón izquierdo\"\n  STR_MIDDLE_MOUSE_BUTTON: \"Botón medio\"\n  STR_RIGHT_MOUSE_BUTTON: \"Botón derecho\"\n  STR_FIRE_SPEED: \"Velocidad de disparo\"\n  STR_FIRE_SPEED_DESC: \"Cambia la velocidad de los proyectiles de armas.\"\n  STR_PLAYER_MOVEMENT_SPEED: \"Vel. de mov. del jugador\"\n  STR_PLAYER_MOVEMENT_SPEED_DESC: \"Cambia la velocidad de movimiento de las unidades del jugador\"\n  STR_COMPUTER_MOVEMENT_SPEED: \"Vel. de mov. de la IA\"\n  STR_COMPUTER_MOVEMENT_SPEED_DESC: \"Cambia la velocidad de movimiento de las unidades controladas por el ordenador.\"\n  STR_PATH_PREVIEW: \"Vista previa de camino\"\n  STR_PATH_ARROWS: \"Flechas\"\n  STR_PATH_ARROWS_DESC: \"Al hacer clic muestra la ruta que su unidad tomará a su destino. El color indica las acciones disponibles: Verde - pueden moverse y disparar, Amarillo - puede moverse; Rojo - no puede moverse.\"\n  STR_PATH_TIME_UNIT_COST: \"Unidades de tiempo\"\n  STR_PATH_TIME_UNIT_COST_DESC: \"Al presionarlo muestra las UTs que le quedaran a su unidad después de alcanzar su destino.\"\n  STR_USER_INTERFACE_OPTIONS: \"Opciones de la IU\"\n  STR_TOOLTIPS: \"Tooltips\"\n  STR_TOOLTIPS_DESC: \"Muestra información detallada para los botones en la Batalla.\"\n  STR_DEATH_NOTIFICATIONS: \"Mostrar bajas\"\n  STR_DEATH_NOTIFICATIONS_DESC: \"Esta opción permite mostrar notificaciones cada vez que uno de sus soldados muere.\"\n  STR_SHOW_FUNDS: \"Mostrar fondos\"\n  STR_SHOW_FUNDS_DESC: \"Muestra tus fondos actuales junto al reloj del Geoescape.\"\n  STR_MISSION_GENERATOR: \"GENERADOR DE MISIONES\"\n  STR_MAP_OPTIONS: \"OPCIONES DE MAPA\"\n  STR_ALIEN_OPTIONS: \"OPCIONES ALIENÍGENAS\"\n  STR_MAP_TERRAIN: \"Terreno\"\n  STR_MAP_DARKNESS: \"Oscuridad\"\n  STR_MAP_DEPTH: \"Profundidad\"\n  STR_DIFFICULTY: \"Dificultad\"\n  STR_ALIEN_RACE: \"Raza\"\n  STR_ALIEN_TECH_LEVEL: \"Nivel tecnológico\"\n  STR_RANDOMIZE: \"Selección aleatoria\"\n  STR_OXCE_REQUIRED_QUESTION: \"Este mod requiere OpenXcom {0} para funcionar correctamente. Habilitar este mod?\"\n  STR_RESTORE_DEFAULTS_QUESTION: \"¿Está seguro que desea restaurar las opciones por defecto?\"\n  STR_DISPLAY_OPTIONS_CONFIRM: \"¿Quiere mantener las opciones de visualización actuales?\"\n  STR_DISPLAY_OPTIONS_REVERT: \"Revirtiendo en 0: {0}\"\n  STR_MISSING_CONTENT_PROMPT: \"ADVERTENCIA: {SMALLLINE} Esta partida cuenta con mods que no están disponibles. Contenido faltante será eliminado, y puede no cargar. {NEWLINE} ¿Continuar?\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT: \"Guardar granadas pre-cebadas\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT_DESC: \"Guarda granadas cebadas durante el inventario pre-batalla, en el diagrama de equipamiento de soldados.\"\n  STR_NEWSEEDONLOAD: \"Salvado escoria\"\n  STR_NEWSEEDONLOAD_DESC: \"La carga de un juego restablecerá la base de números aleatorios, por lo que tomar la misma acción puede dar resultados diferentes. No afecta el modo Ironman.\"\n  STR_CHANGEVALUEBYMOUSEWHEEL: \"Cambiar los valores con la rueda del ratón\"\n  STR_CHANGEVALUEBYMOUSEWHEEL_DESC: \"Permite usar la rueda del ratón para aumentar / disminuir los valores indicados.\"\n  STR_BATTLEHAIRBLEACH: \"Sprites de soldado mejorados\"\n  STR_BATTLEHAIRBLEACH_DESC: \"Cambia las sprites de los soldados  en batalla para que coincida con su aspecto de inventario.\"\n  STR_DRAGSCROLLINVERT: \"Inventir desplazamiento arrastrado\"\n  STR_DRAGSCROLLINVERT_DESC: \"Cuando está habilitado, arrastrar desplaza en la dirección opuesta a la del ratón.\"\n  STR_BATTLESCAPE_SCALE: \"Escala en Batalla\"\n  STR_BATTLESCAPE_SCALE_DESC: \"Modo de escala de visualización de Batalla, en base a una resolución fija (estirado para encajar), o un nivel de zoom fijo (ampliado para llenar).\"\n  STR_GEOSCAPE_SCALE: \"Escala de Globo\"\n  STR_GEOSCAPESCALE_SCALE_DESC: \"Modo de escala de visualización de Geoscape, en base a una resolución fija (estirado para encajar), o un nivel de zoom fijo (ampliado para llenar).\"\n  STR_1_5X: \"1.5x Original\"\n  STR_2X: \"2x Original\"\n  STR_THIRD_DISPLAY: \"1/3 de pantalla\"\n  STR_HALF_DISPLAY: \"1/2 de pantalla\"\n  STR_FULL_DISPLAY: \"Pantalla completa\"\n  STR_FPS_LIMIT: \"Limite de FPS\"\n  STR_FPS_LIMIT_DESC: \"Limita el número de actualizaciones de pantalla por segundo, 0 sin límite. Nota: esto sólo afectará a los modos de software, ya que OpenGL lo hace por si misma.\"\n  STR_FPS_INACTIVE_LIMIT: \"Limite de FPS al fondo\"\n  STR_FPS_INACTIVE_LIMIT_DESC: \"Limita el numero de refrescos de pantalla por segundo cuando el juego está de fondo.\"\n  STR_NOALIENPANICMESSAGES: \"Suprimir los mensajes de pánico para los alienigenas\"\n  STR_NOALIENPANICMESSAGES_DESC: \"No muestra mensajes de pánico de los alienigenas a menos que sean visibles para el jugador.\"\n  STR_ALIENBLEEDING: \"Sangrado Alienigena\"\n  STR_ALIENBLEEDING_DESC: \"Permite infligir heridas fatales a la mayoría de los alienigenas\"\n  STR_FIELDPROMOTIONS: \"Promociones en combate\"\n  STR_FIELDPROMOTIONS_DESC: \"Sólo los soldados que estaban presentes en la misión son elegibles para promoción.\"\n  STR_MEETINGPOINT: \"Predecir trayectoria OVNI\"\n  STR_MEETINGPOINT_DESC: \"Las Naves vuelan hacia un punto de encuentro con el OVNI en función de su trayectoria actual.\"\n  STR_IRONMAN: \"IRONMAN\"\n  STR_IRONMAN_DESC: \"No se salvara manualmente\"\n  STR_SAVE_AND_ABANDON_GAME: \"GUARDAR Y ABANDONAR JUEGO\"\n  STR_MOD_UNSUCCESSFUL: \"Carga de Mod fracasó\"\n  STR_NEW_SAVED_GAME_SLOT: \"<NUEVO JUEGO SALVADO>\"\n  STR_AUTO_SAVE_GEOSCAPE_SLOT: \"<AUTO GEOSCAPE>\"\n  STR_AUTO_SAVE_BATTLESCAPE_SLOT: \"<AUTO BATTLESCAPE>\"\n  STR_QUICK_SAVE_SLOT: \"<GUARDADO RAPIDO>\"\n  STR_DISPLAY_MODE_DESC: \"Cambia como se juego se muestra en la pantalla.\"\n  STR_PREFERRED_MUSIC_FORMAT: \"Formato de musica\"\n  STR_PREFERRED_MUSIC_FORMAT_DESC: \"Selecciona el formato de música preferido a usar cuando hay múltiples disponibles.{NEWLINE}NOTA: La reproducción de MIDI podría sonar extraña en Windows.\"\n  STR_PREFERRED_SFX_FORMAT: \"Formato de EdS\"\n  STR_PREFERRED_SFX_FORMAT_DESC: \"Selecciona el efecto de sonido preferido a usar cuando haya más de uno disponible.\"\n  STR_PREFERRED_VIDEO_FORMAT: \"Formato de Video\"\n  STR_PREFERRED_VIDEO_FORMAT_DESC: \"Escoge el formato de vídeo preferido a usar cuando múltiples estén disponibles.\"\n  STR_PREFERRED_VIDEO_ANIMATION: \"Animación\"\n  STR_PREFERRED_VIDEO_SLIDESHOW: \"Diapositivas\"\n  STR_PREFERRED_FORMAT_AUTO: \"Automatico\"\n  STR_CURRENT_FORMAT: \"Actual: {0}\"\n  STR_SOUND_OPTIONS: \"Opciones de Sonido\"\n  STR_BACKGROUND_MUTE: \"Silenciar en segundo Plano\"\n  STR_BACKGROUND_MUTE_DESC: \"Silencia todos los sonidos cuando el juego no esta activo.\"\n  STR_FORCE_FIRE: \"Invalidar línea de fuego\"\n  STR_FORCE_FIRE_DESC: \"Permite forzar a tus soldados a realiza un tiro al sostener CTRL, independientemente de las reglas de línea de tiro. \"\n  STR_NO_AUDIO_HARDWARE_DETECTED: \"No se detecto hardware de audio\"\n  STR_MOUSEWHEEL_SPEED: \"Velocidad de desplazamiento de la rueda del ratón\"\n  STR_MOUSEWHEEL_SPEED_DESC: \"Ajusta el número de líneas desplazado en las listas con cada incremento de la rueda del ratón.\"\n  STR_DISABLED: \"Deshabilitado\"\n  STR_MAXIMIZE_INFO_SCREENS: \"Maximizar pantallas de información\"\n  STR_MAXIMIZE_INFO_SCREENS_DESC: \"El inventario y otras pantallas se mostrarán en pantalla completa, independientemente de los ajustes de escala.\"\n  STR_DIARY: \"DIARIO\"\n  STR_KILLED: \"MUERTO\"\n  STR_STUNNED: \"ATONTADO\"\n  STR_PANICKED: \"EN PANICO\"\n  STR_MINDCONTROLLED: \"CONTROLADO\"\n  STR_REGION_UNKNOWN: \"Divulgado\"\n  STR_WEAPON_UNKNOWN: \"Improvisación\"\n  STR_UNKNOWN: \"Desconocido\"\n  STR_VICTORY: \"Victoria\"\n  STR_DEFEAT: \"Derrota\"\n  STR_NO_RECORD: \"Sin Datos\"\n  STR_HUMAN: \"Humano\"\n  STR_FRIENDLY: \"Amistoso\"\n  STR_HOSTILE: \"Hostil\"\n  STR_NEUTRAL: \"Neutral\"\n  STR_RATING_UC: \"RENDIMIENTO\"\n  STR_LOCATION: \"UBICACIÓN> {ALT}{0}\"\n  STR_DAYLIGHT_TYPE: \"TIEMPO> {ALT}{0}\"\n  STR_RACE_TYPE: \"RAZA> {ALT}{0}\"\n  STR_DAY: \"Día\"\n  STR_NIGHT: \"Noche\"\n  STR_DAYS_WOUNDED: \"DIAS HERIDO> {ALT}{0}\"\n  STR_COMBAT: \"COMBATE\"\n  STR_PERFORMANCE: \"DESEMPEÑO\"\n  STR_NEUTRALIZATIONS_BY_RACE: \"NEUTRALIZACIONES POR RAZA\"\n  STR_NEUTRALIZATIONS_BY_RANK: \"NEUTRALIZACIONES POR RANGO\"\n  STR_NEUTRALIZATIONS_BY_WEAPON: \"NEUTRALIZACIONES POR ARMA\"\n  STR_MISSIONS_BY_LOCATION: \"MISIONES POR UBICACIÓN\"\n  STR_MISSIONS_BY_TYPE: \"MISIONES POR TIPO\"\n  STR_MISSIONS_BY_UFO: \"MISIONES POR OVNI\"\n  STR_SCORE_VALUE: \"PUNTAJE> {ALT}{0}\"\n  STR_WINS: \"TRIUNFOS> {ALT}{0}\"\n  STR_STUNS: \"ATURD> {ALT}{0}\"\n  STR_PANICKS: \"PANICOS> {ALT}{0}\"\n  STR_MINDCONTROLS: \"CONTROLES> {ALT}{0}\"\n  STR_AWARDS: \"PREMIOS\"\n  STR_COMMENDATIONS_UC: \"CONDECORACIONES\"\n  STR_COMMENDATIONS: \"Condecoraciones\"\n  STR_MEDALS: \"MEDALLAS\"\n  STR_LOST_IN_SERVICE: \"PERDIDO EN ACCION\"\n  STR_MEDAL_NAME: \"Nombre de Medalla\"\n  STR_MEDAL_AWARD_LEVEL: \"Nivel de Premio\"\n  STR_MEDAL_DECOR_LEVEL: \"Nivel de Decoración\"\n  STR_AWARD_0: \"Primer Premio\"\n  STR_AWARD_1: \"Segundo Premio\"\n  STR_AWARD_2: \"Tercer Premio\"\n  STR_AWARD_3: \"Cuarto Premio\"\n  STR_AWARD_4: \"Quinto Premio\"\n  STR_AWARD_5: \"Sexto Premio\"\n  STR_AWARD_6: \"Septimo Premio\"\n  STR_AWARD_7: \"Octavo Premio\"\n  STR_AWARD_8: \"Noveno Premio\"\n  STR_AWARD_9: \"Décimo Premio \"\n  STR_AWARD_DECOR_0: \"Ninguno\"\n  STR_AWARD_DECOR_1: \"Primer Pin de bronce\"\n  STR_AWARD_DECOR_2: \"Segundo pin de bronce\"\n  STR_AWARD_DECOR_3: \"Tercer pin de bronce\"\n  STR_AWARD_DECOR_4: \"Primer pin de plata\"\n  STR_AWARD_DECOR_5: \"Segundo pin de plata\"\n  STR_AWARD_DECOR_6: \"Tercer pin de plata\"\n  STR_AWARD_DECOR_7: \"Primer Pin de oro\"\n  STR_AWARD_DECOR_8: \"Segundo pin de oro\"\n  STR_AWARD_DECOR_9: \"Tercer Pin de oro\"\n  STR_KILLED_IN_ACTION_MALE: \"MUERTO EN COMBATE\"\n  STR_KILLED_IN_ACTION_FEMALE: \"MUERTA EN COMBATE\"\n  STR_MISSING_IN_ACTION_MALE: \"DESAPARECIDO EN COMBATE\"\n  STR_MISSING_IN_ACTION_FEMALE: \"DESAPARECIDA EN COMBATE\"\n  STR_AVERAGE_MONTHLY_RATING: \"Valoración media mensual\"\n  STR_TOTAL_INCOME: \"Ingresos totales\"\n  STR_TOTAL_EXPENDITURE: \"Gastos totales\"\n  STR_MISSIONS_WON: \"Misiones cumplidas\"\n  STR_MISSIONS_LOST: \"Misiones fallidas\"\n  STR_NIGHT_MISSIONS: \"Misiones nocturnas\"\n  STR_BEST_RATING: \"Mejor calificación en misiones\"\n  STR_WORST_RATING: \"Peor calificación en misiones\"\n  STR_ALIEN_KILLS: \"Alienígenas muertos\"\n  STR_ALIEN_CAPTURES: \"Alienígenas capturados\"\n  STR_FRIENDLY_KILLS: \"Incidentes de fuego amigo\"\n  STR_AVERAGE_ACCURACY: \"Precisión promedio\"\n  STR_WEAPON_MOST_KILLS: \"Arma más efectiva\"\n  STR_ALIEN_MOST_KILLS: \"Alienígena más letal\"\n  STR_LONGEST_SERVICE: \"Meses más largos de servicio\"\n  STR_TOTAL_DAYS_WOUNDED: \"Días de enfermedad\"\n  STR_COUNTRIES_LOST: \"Países infiltrados\"\n  STR_TOTAL_TERROR_SITES: \"Ataques terroristas\"\n  STR_TOTAL_BASES: \"Bases Construidas\"\n  STR_TOTAL_CRAFT: \"Naves poseidas\"\n  STR_TOTAL_SCIENTISTS: \"Científicos contratados\"\n  STR_TOTAL_ENGINEERS: \"Ingenieros contratados\"\n  STR_TOTAL_RESEARCH: \"Investigaciones finalizadas\"\n  STR_DIARY_ACCURACY: \"PRECISIÓN> {ALT}{0}%\"\n  STR_STATISTICS: \"Estadisticas\"\n  STR_STATS: \"ESTADO\"\n  STR_TIME_UNITS_ABBREVIATION: \"UTs\"\n  STR_STAMINA_ABBREVIATION: \"EST\"\n  STR_HEALTH_ABBREVIATION: \"SAL\"\n  STR_BRAVERY_ABBREVIATION: \"VAL\"\n  STR_REACTIONS_ABBREVIATION: \"REA\"\n  STR_FIRING_ACCURACY_ABBREVIATION: \"PUN\"\n  STR_THROWING_ACCURACY_ABBREVIATION: \"PAR\"\n  STR_STRENGTH_ABBREVIATION: \"FUER\"\n  STR_MELEE_ACCURACY_ABBREVIATION: \"PMaM\"\n"
  },
  {
    "path": "bin/common/Language/es-ES.yml",
    "content": "es-ES:\n  STR_OPENXCOM: \"OpenXcom\"\n  STR_NEW_GAME: \"Partida nueva\"\n  STR_LOAD_SAVED_GAME: \"Cargar partida\"\n  STR_SELECT_DIFFICULTY_LEVEL: \"Seleccionar nivel de dificultad\"\n  STR_1_BEGINNER: \"1> Principiante\"\n  STR_2_EXPERIENCED: \"2> Experimentado\"\n  STR_3_VETERAN: \"3> Veterano\"\n  STR_4_GENIUS: \"4> Genio\"\n  STR_5_SUPERHUMAN: \"5> Superhumano\"\n  STR_TIME: \"Hora\"\n  STR_DATE: \"Fecha\"\n  STR_SELECT_GAME_TO_LOAD: \"Seleccionar una partida para cargar\"\n  STR_SELECT_SAVE_POSITION: \"Seleccionar posición de guardado\"\n  STR_GAME_OPTIONS: \"OPCIONES DEL JUEGO\"\n  STR_LOAD_GAME: \"CARGAR PARTIDA\"\n  STR_SAVE_GAME: \"GUARDAR PARTIDA\"\n  STR_ABANDON_GAME: \"ABANDONAR PARTIDA\"\n  STR_ABANDON_GAME_QUESTION: \"¿ABANDONAR EL JUEGO?\"\n  STR_QUIT: \"Salir\"\n  STR_SAVING_GAME: \"Guardando partida\"\n  STR_LOADING_GAME: \"Cargando partida\"\n  STR_NO_SAVED_GAME_PRESENT: \"No hay ninguna partida guardada\"\n  STR_LOAD_UNSUCCESSFUL: \"No se ha podido cargar la partida.\"\n  STR_SAVE_UNSUCCESSFUL: \"No se ha podido guardar la partida.\"\n  STR_LOAD_SUCCESSFUL: \"La partida se ha cargado.\"\n  STR_SAVE_SUCCESSFUL: \"La partida ha sido guardada.\"\n  STR_DELETE: \"BORRAR\"\n  STR_DELETE_UNSUCCESSFUL: \"No se ha podido borrar la partida.\"\n  STR_IS_IT_OK_TO_DELETE_THE_SAVED_GAME: \"¿Quieres borrar la partida guardada?\"\n  STR_ORIGINAL_XCOM: \"Original X-Com\"\n  STR_LOADING: \"Cargando...\"\n  STR_DETAILS: \"DETALLES>{ALT}{0}\"\n  STR_NEW_BATTLE: \"Nueva Batalla\"\n  STR_OPTIONS: \"Opciones\"\n  STR_RIGHT_CLICK_TO_DELETE: \"Click derecho para borrar.\"\n  STR_RESTORE_DEFAULTS: \"Restaurar Valores Iniciales\"\n  STR_CONTROLS: \"CONTROLES\"\n  STR_GENERAL: \"General\"\n  STR_GEOSCAPE: \"GeoEscape\"\n  STR_BATTLESCAPE: \"BatallaEscape\"\n  STR_SCREENSHOT: \"Captura de Pantalla\"\n  STR_FPS_COUNTER: \"Contador de Imágenes por Segundo\"\n  STR_ROTATE_LEFT: \"Rotar Izquierda\"\n  STR_ROTATE_RIGHT: \"Rotar Derecha\"\n  STR_ROTATE_UP: \"Rotar Arriba\"\n  STR_ROTATE_DOWN: \"Rotar Abajo\"\n  STR_ZOOM_IN: \"Acercar\"\n  STR_ZOOM_OUT: \"Alejar\"\n  STR_TOGGLE_COUNTRY_DETAIL: \"Activar Detalle de Paises\"\n  STR_TOGGLE_RADAR_RANGES: \"Activar Rangos de Radar\"\n  STR_SCROLL_LEFT: \"Desplazar Izquierda\"\n  STR_SCROLL_RIGHT: \"Desplazar Derecha\"\n  STR_SCROLL_UP: \"Desplazar Arriba\"\n  STR_SCROLL_DOWN: \"Desplazar hacia abajo\"\n  STR_UNIT_LEVEL_ABOVE: \"Mover unidad al nivel superior\"\n  STR_UNIT_LEVEL_BELOW: \"Mover unidad al nivel inferior\"\n  STR_VIEW_LEVEL_ABOVE: \"Ver Nivel Arriba\"\n  STR_VIEW_LEVEL_BELOW: \"Ver Nivel Abajo\"\n  STR_CENTER_SELECTED_UNIT: \"Centrar en Unidad Seleccionada\"\n  STR_PREVIOUS_UNIT: \"Unidad Anterior\"\n  STR_NEXT_UNIT: \"Unidad Siguiente\"\n  STR_DESELECT_UNIT: \"Deseleccionar Unidad\"\n  STR_USE_LEFT_HAND: \"Utilizar objeto en Mano Izda.\"\n  STR_USE_RIGHT_HAND: \"Usar el Objeto de la Mano Derecha.\"\n  STR_INVENTORY: \"Inventario\"\n  STR_MINIMAP: \"Minimapa\"\n  STR_MULTI_LEVEL_VIEW: \"Vista Multi-Nivel\"\n  STR_END_TURN: \"Finalizar Turno\"\n  STR_ABORT_MISSION: \"Abortar Mision\"\n  STR_UNIT_STATS: \"Estadisticas de Unidad\"\n  STR_KNEEL: \"Arrodillarse\"\n  STR_RELOAD: \"Recargar\"\n  STR_TOGGLE_PERSONAL_LIGHTING: \"Activar Iluminacion Personal\"\n  STR_DONT_RESERVE_TIME_UNITS: \"No Reservar UTs\"\n  STR_RESERVE_TIME_UNITS_FOR_SNAP_SHOT: \"Reservar UTs para Disparo Rápido\"\n  STR_RESERVE_TIME_UNITS_FOR_AIMED_SHOT: \"Reservar UTs para Disparo Preciso\"\n  STR_RESERVE_TIME_UNITS_FOR_AUTO_SHOT: \"Reservar UTs para Disparo Auto.\"\n  STR_CENTER_ON_ENEMY_1: \"Centrar en Enemigo 1\"\n  STR_CENTER_ON_ENEMY_2: \"Centrar en Enemigo 2\"\n  STR_CENTER_ON_ENEMY_3: \"Centrar en Enemigo 3\"\n  STR_CENTER_ON_ENEMY_4: \"Centrar en Enemigo 4\"\n  STR_CENTER_ON_ENEMY_5: \"Centrar en Enemigo 5\"\n  STR_CENTER_ON_ENEMY_6: \"Centrar en Enemigo 6\"\n  STR_CENTER_ON_ENEMY_7: \"Centrar en Enemigo 7\"\n  STR_CENTER_ON_ENEMY_8: \"Centrar en Enemigo 8\"\n  STR_CENTER_ON_ENEMY_9: \"Centrar en Enemigo 9\"\n  STR_CENTER_ON_ENEMY_10: \"Centrar en Enemigo 10\"\n  STR_CREATE_INVENTORY_TEMPLATE: \"Crear una plantilla de inventario\"\n  STR_APPLY_INVENTORY_TEMPLATE: \"Aplicar plantilla de inventario\"\n  STR_CLEAR_INVENTORY: \"Vaciar inventario\"\n  STR_AUTO_EQUIP: \"Equipar Auto.\"\n  STR_QUICK_SAVE: \"Guardado rápido\"\n  STR_QUICK_LOAD: \"Carga rápida\"\n  STR_ADVANCED: \"AVANZADO\"\n  STR_AGGRESSIVERETALIATION: \"Represalia Agresiva\"\n  STR_AGGRESSIVERETALIATION_DESC: \"Los OVNIs intentarán detectar tus bases siempre, independientemente de sus parametros de misión.\"\n  STR_STORAGELIMITSENFORCED: \"Límite de almacenamiento para objetos recuperados\"\n  STR_STORAGELIMITSENFORCED_DESC: \"Aumenta los limites de contención y de almacenes generales para alienígenas vivos y artefactos recobrados de misiones.\"\n  STR_CANSELLLIVEALIENS: \"Venta de alienígenas vivos\"\n  STR_CANSELLLIVEALIENS_DESC: \"Permite la venta de alinígenas vivos, recomendado cuando se usa el limite de almacenamiento.\"\n  STR_ALLOWBUILDINGQUEUE: \"Permitir cola de construción\"\n  STR_ALLOWBUILDINGQUEUE_DESC: \"Posibilidad de nuevas instalaciones al lado de no terminadas.\"\n  STR_BATTLEAUTOEND: \"Auto-finalizar batalla\"\n  STR_BATTLEAUTOEND_DESC: \"Las batallas finalizan automaticamente cuando el último enemigo vivo es neutralizado.\"\n  STR_BATTLEINSTANTGRENADE: \"Granadas instantaneas\"\n  STR_BATTLEINSTANTGRENADE_DESC: \"Las granadas cuyo temporizador haya sido puesto a 0 turnos explotarán inmediatamente al arrojarlas, en lugar de al final del turno.\"\n  STR_BATTLEUFOEXTENDERACCURACY: \"Precisión como en UFO Extender\"\n  STR_BATTLEUFOEXTENDERACCURACY_DESC: \"La precisión de los disparos disminuye a partir de cierta distancia dependiendo del tipo de disparo. La precisión modificada se mostrará en el cursor.\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE: \"Transferir aeronaves en vuelo\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE_DESC: \"Las aeronaves actualmente en vuelo pueden transferirse.\"\n  STR_CRAFTLAUNCHALWAYS: \"Forzar despegue de aeronave\"\n  STR_CRAFTLAUNCHALWAYS_DESC: \"Las naves pueden despegar incluso cuando no están preparadas, ignorando la necesidad de mantenimiento.\"\n  STR_CUSTOMINITIALBASE: \"Base inicial personalizada\"\n  STR_CUSTOMINITIALBASE_DESC: \"Al empezar una partida nueva podras ubicar manualmente tus instalaciones en lugar de usar la distribución por defecto.\"\n  STR_GLOBESEASONS: \"Iluminación realista del globo terráqueo\"\n  STR_GLOBESEASONS_DESC: \"Utiliza una proyección más realista de la luz del sol sobre la Geoscape de acuerdo con la inclinación del eje de la Tierra.\"\n  STR_PLAYINTRO: \"Mostrar introducción\"\n  STR_PLAYINTRO_DESC: \"Mostrar el video de introducción al empezar.\"\n  STR_SHOWMORESTATSININVENTORYVIEW: \"Estadísticas Inventario\"\n  STR_SHOWMORESTATSININVENTORYVIEW_DESC: \"Muestra información extra en la pantalla de inventario del soldado\"\n  STR_SNEAKYAI: \"IA furtiva\"\n  STR_SNEAKYAI_DESC: \"La IA evita exponerse al jugador siempre que es posible.\"\n  STR_STRAFE: \"Las nuevas instalaciones se pueden colocar al lado de no terminadas.\"\n  STR_STRAFE_DESC: \"Permite desplazarse lateralmente, correr así como mover independientemente la torreta del tanque presionando CTRL.\"\n  STR_BATTLEEXPLOSIONHEIGHT: \"Altura de explosión\"\n  STR_BATTLEEXPLOSIONHEIGHT_DESC: \"Cambia el area de efecto de las explosiones hacia arriba.{NEWLINE}(Plana: 0, Redonda: 3)\"\n  STR_AUTOSAVE: \"Autoguardado\"\n  STR_AUTOSAVE_DESC: \"Graba la partida automáticamente a intervalos específicos. No se aplica en el Modo Ironman\"\n  STR_AUTOSAVE_FREQUENCY: \"Frecuencia de Autoguardado\"\n  STR_AUTOSAVE_FREQUENCY_DESC: \"Número de turnos para grabar automáticamente\"\n  STR_ALLOWPSIONICCAPTURE: \"Permitir captura psiquica\"\n  STR_ALLOWPSIONICCAPTURE_DESC: \"Controlar a todos los alienígenas finaliza con éxito la misión, y cuentan como capturados.\"\n  STR_ANYTIMEPSITRAINING: \"Entrenamiento psiónico en cualquier momento\"\n  STR_ANYTIMEPSITRAINING_DESC: \"Permite asignar soldados al entrenamiento psionico en cualquier momento del mes. Recuerde, el entrenamiento inicial dura entre 30 y 60 días.\"\n  STR_SKIPNEXTTURNSCREEN: \"Omitir pantalla \\\"Siguiente Turno\\\"\"\n  STR_SKIPNEXTTURNSCREEN_DESC: \"Automáticamente, y tras una breve pausa, la pantalla de \\\"Siguiente Turno\\\" se pasa automáticamente.\"\n  STR_NOT_ENOUGH_SPACE: \"¡No hay Suficiente Espacio!\"\n  STR_WEAPONSELFDESTRUCTION: \"Autodestrucción de armas alienígenas\"\n  STR_WEAPONSELFDESTRUCTION_DESC: \"Las armas que llevan los alienígenas se autodestruirán si su portador muere, como en XCOM 2012\"\n  STR_RETAINCORPSES: \"Conservar aliens interrogados\"\n  STR_RETAINCORPSES_DESC: \"Después de \\\"investigar\\\" alienígenas vivos, sus cadáveres serán añadidos a los almacenes de la base, como en XCOM 2012\"\n  STR_SAVE_VOXEL_VIEW: \"Salvar captura de pantalla en primera persona.\"\n  STR_RESERVE_TIME_UNITS_FOR_KNEEL: \"Reservar unidades de tiempo para arrodillarse\"\n  STR_EXPEND_ALL_TIME_UNITS: \"Gastar todas las Unidades de Tiempo restantes\"\n  STR_PSISTRENGTHEVAL: \"Evaluacion Fuerza PSI\"\n  STR_PSISTRENGTHEVAL_DESC: \"Evalua la fuerza psionica de todos los soldados tras la investigacion correspondiente.\"\n  STR_DISABLEAUTOEQUIP: \"Desactivar auto-equipado\"\n  STR_DISABLEAUTOEQUIP_DESC: \"Desactivar auto-equipado de nuevos soldados antes de la batalla\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT: \"Permite mejora de la Fuerza Psiónica\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT_DESC: \"La fuerza Psiónica de los soldados puede ser mejorado con la experiencia y el entrenamiento.\"\n  STR_BATTLESMOOTHCAMERA: \"Seguir Proyectiles\"\n  STR_BATTLESMOOTHCAMERA_DESC: \"La cámara de la Battescape permanecerá centrada en los proyectiles mientras estén en vuelo.\"\n  STR_BATTLECONFIRMFIREMODE: \"Modo de Confirmar Fuego\"\n  STR_BATTLECONFIRMFIREMODE_DESC: \"Requiere un segundo click en el mismo sitio para confirmar la orden de fuego\"\n  STR_SELECT_BASE_1: \"Selecciona Base 1\"\n  STR_SELECT_BASE_2: \"Selecciona Base 2\"\n  STR_SELECT_BASE_3: \"Selecciona Base 3\"\n  STR_SELECT_BASE_4: \"Selecciona Base 4\"\n  STR_SELECT_BASE_5: \"Selecciona Base 5\"\n  STR_SELECT_BASE_6: \"Selecciona Base 6\"\n  STR_SELECT_BASE_7: \"Selecciona Base 7\"\n  STR_SELECT_BASE_8: \"Selecciona Base 8\"\n  STR_VIDEO: \"VIDEO\"\n  STR_AUDIO: \"AUDIO\"\n  STR_BATTLESCAPE_UC: \"BATTLESCAPE\"\n  STR_MODS_UC: \"MODS\"\n  STR_MODS: \"Mods\"\n  STR_DISPLAY_RESOLUTION: \"Resolución de pantalla\"\n  STR_DISPLAY_RESOLUTION_DESC: \"Cambia la resolución de la pantalla, la resolución del juego se modificará para coincidir. Las flechas cambian entre las resoluciones soportadas. Haz click para introducir una resolución personalizada.\"\n  STR_ORIGINAL: \"Original\"\n  STR_DISPLAY_MODE: \"Modo de visualización\"\n  STR_WINDOWED: \"En una ventana\"\n  STR_FULLSCREEN: \"Pantalla completa\"\n  STR_BORDERLESS: \"Sin bordes\"\n  STR_DISPLAY_LANGUAGE: \"Mostrar lenguaje\"\n  STR_DISPLAY_LANGUAGE_DESC: \"Cambia el lenguaje del texto del juego.\"\n  STR_DISPLAY_FILTER: \"Mostrar Filtro\"\n  STR_DISPLAY_FILTER_DESC: \"Cambia el filtro aplicado a la pantalla de juego.{NEWLINE}*necesita acelaración por hardware OpenGL.\"\n  STR_DISPLAY_OPTIONS: \"Opciones de pantalla\"\n  STR_LETTERBOXED: \"Estrechada\"\n  STR_LETTERBOXED_DESC: \"Estrecha la pantalla para mantener la proporción del original.\"\n  STR_RESIZABLE: \"Redimensionable\"\n  STR_LOCK_MOUSE: \"Fijar Ratón\"\n  STR_LOCK_MOUSE_DESC: \"Evita que el cursor del ratón salga de la ventana de juego. Ctrl + G para cambiar en cualquier momento.\"\n  STR_FIXED_WINDOW_POSITION: \"Posición fija del modo ventana\"\n  STR_FIXED_WINDOW_POSITION_DESC: \"Fijar la posición del modo ventana\"\n  STR_DISPLAY_SET_WINDOW_POSITION: \"Posición por defecto del modo ventana\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_X: \"Nuevo valor X del borde izquierdo:\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_Y: \"Nuevo valor Y del borde superior\"\n  STR_MUSIC_VOLUME: \"Volumen de la música\"\n  STR_MUSIC_VOLUME_DESC: \"Cambia el volumen de la música de fondo.\"\n  STR_SFX_VOLUME: \"Volumen de los efectos{NEWLINE}de sonido\"\n  STR_SFX_VOLUME_DESC: \"Cambia el volumen de los efectos sonoros.\"\n  STR_UI_VOLUME: \"Volumen IU\"\n  STR_UI_VOLUME_DESC: \"Cambia el volumen de los bips de la interfaz.\"\n  STR_SCROLL_SPEED: \"Velocidad de desplazamiento\"\n  STR_SCROLL_SPEED_GEO_DESC: \"Cambia la velocidad de desplazamiento del globo terráqueo.\"\n  STR_SCROLL_SPEED_BATTLE_DESC: \"Cambia la velocidad de desplazamiento del mapa.\"\n  STR_DOGFIGHT_SPEED: \"Velocidad Dogfight\"\n  STR_DOGFIGHT_SPEED_DESC: \"Cambia la velocidad de los combates de intercepción entre las naves y los OVNIS. Velocidades más lentas pueden mejorar el comportamiento en dispositivos de bajas prestaciones. \"\n  STR_CLOCK_SPEED: \"Velocidad del reloj\"\n  STR_CLOCK_SPEED_DESC: \"Cambia la velocidad del reloj en la Geoescape. Velocidades más lentas pueden mejorar el comportamiento en dispositivos de bajas prestaciones.\"\n  STR_GLOBE_DETAILS: \"Detalles del globo terráqueo\"\n  STR_GLOBE_COUNTRIES: \"Países\"\n  STR_GLOBE_COUNTRIES_DESC: \"Muestra paises donantes en el globo.\"\n  STR_GLOBE_RADARS: \"Radares\"\n  STR_GLOBE_RADARS_DESC: \"Muestra el alcance de los radares de las bases en el globo terráqueo.\"\n  STR_GLOBE_FLIGHT_PATHS: \"Rutas de vuelo\"\n  STR_GLOBE_FLIGHT_PATHS_DESC: \"Muestra las rutas de vuelo de las naves sobre el globo.\"\n  STR_CONTROLS_DESC: \"Click izquierdo en un acceso directo y presionar una tecla para cambiarlo.{NEWLINE}Click derecho sobre un acceso directo para deshabilitarlo.\"\n  STR_BASE_GAME: \"Juego Base\"\n  STR_MODS_TOOLTIP: \"Versión {0} por {1}. {NEWLINE} {2}\"\n  STR_EDGE_SCROLL: \"Desplazamiento de borde\"\n  STR_EDGE_SCROLL_DESC: \"Manual: Desplaza el mapa cuando el botón izquierdo del ratón se mantiene presionado sobre el borde de la pantalla.{NEWLINE}Auto: Desplaza el mapa cuando el cursor llega al borde de la pantalla.\"\n  STR_TRIGGER_SCROLL: \"Gatillo\"\n  STR_AUTO_SCROLL: \"Auto\"\n  STR_DRAG_SCROLL: \"Desplazamiento por arrastre\"\n  STR_DRAG_SCROLL_DESC: \"Desplaza el mapa cuando el botón especificado del ratón se mantiene presionado.\"\n  STR_LEFT_MOUSE_BUTTON: \"Botón izquierdo\"\n  STR_MIDDLE_MOUSE_BUTTON: \"Botón del medio\"\n  STR_RIGHT_MOUSE_BUTTON: \"Botón derecho\"\n  STR_FIRE_SPEED: \"Velocidad de disparo\"\n  STR_FIRE_SPEED_DESC: \"Cambia la velocidad de los proyectiles de las armas.\"\n  STR_PLAYER_MOVEMENT_SPEED: \"Velocidad del movimiento del jugador\"\n  STR_PLAYER_MOVEMENT_SPEED_DESC: \"Cambia la velocidad de movimiento de las unidades controladas por el jugador.\"\n  STR_COMPUTER_MOVEMENT_SPEED: \"Velocidad de movimiento de la IA \"\n  STR_COMPUTER_MOVEMENT_SPEED_DESC: \"Modifica la velocidad de movimiento de las unidades controladas por el ordenador.\"\n  STR_PATH_PREVIEW: \"Vista previa de la ruta\"\n  STR_PATH_ARROWS: \"Flechas\"\n  STR_PATH_ARROWS_DESC: \"Hacer click muestra la ruta que tu unidad seguirá hasta su destino. El color indica las opciones disponibles: Verde - puede moverse y disparar; Amarillo - puede moverse; Rojo - no puede moverse.\"\n  STR_PATH_TIME_UNIT_COST: \"Unidades de Tiempo\"\n  STR_PATH_TIME_UNIT_COST_DESC: \"Hacer click muestra las UTs que tu unidad tendrá después de moverse hasta el destino.\"\n  STR_USER_INTERFACE_OPTIONS: \"Opciones de Interfaz\"\n  STR_TOOLTIPS: \"Tooltips\"\n  STR_TOOLTIPS_DESC: \"Muestra tooltips sobre los botones en la Battlescape.\"\n  STR_DEATH_NOTIFICATIONS: \"Mostrar notificación de bajas\"\n  STR_DEATH_NOTIFICATIONS_DESC: \"Muestra notificaciones cada vez que un soldado muere.\"\n  STR_SHOW_FUNDS: \"Mostrar fondos\"\n  STR_SHOW_FUNDS_DESC: \"Muestra tus fondos actuales al lado del reloj de la Geoescape.\"\n  STR_MISSION_GENERATOR: \"GENERADOR DE MISIONES\"\n  STR_MAP_OPTIONS: \"OPCIONES DEL MAPA\"\n  STR_ALIEN_OPTIONS: \"OPCIONES DE ALIENÍGENAS\"\n  STR_MAP_TERRAIN: \"Terreno\"\n  STR_MAP_DARKNESS: \"Oscuridad\"\n  STR_MAP_DEPTH: \"Profundidad\"\n  STR_DIFFICULTY: \"Dificultad\"\n  STR_ALIEN_RACE: \"Raza\"\n  STR_ALIEN_TECH_LEVEL: \"Nivel tecnológico\"\n  STR_RANDOMIZE: \"Al azar\"\n  STR_OXCE_REQUIRED_QUESTION: \"Este Mod requiere OpenXcom {0} para funcionar correctamente. ¿ Activo este Mod ?\"\n  STR_RESTORE_DEFAULTS_QUESTION: \"¿Estás seguro de que quieres restaurar las opciones por defecto?\"\n  STR_DISPLAY_OPTIONS_CONFIRM: \"¿Quieres conservar las opciones actuales de pantalla?\"\n  STR_DISPLAY_OPTIONS_REVERT: \"Revirtiendo en 0:{0}\"\n  STR_MISSING_CONTENT_PROMPT: \"ATENCIÓN:{SMALLLINE}Este guardado depende de mods que no están disponibles. El contenido no presente será eliminado y puede fallar al cargar.{NEWLINE}¿Continuar?\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT: \"Guardar granadas pre-activadas\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT_DESC: \"Guarda granadas activadas durante el inventario pre-batalla, en el diagrama de equipamiento de soldados.\"\n  STR_NEWSEEDONLOAD: \"Sucesos aleatorios diferentes al cargar\"\n  STR_NEWSEEDONLOAD_DESC: \"Cargar un juego reseteará el generador de números aleatorios, por lo que realizar la misma acción puede conducir a resultados diferentes. No afecta al modo Ironman.\"\n  STR_CHANGEVALUEBYMOUSEWHEEL: \"Cambia valores con la rueda del ratón\"\n  STR_CHANGEVALUEBYMOUSEWHEEL_DESC: \"Te permite usar la rueda del ratón para incrementar/disminuir valores por esta cantidad\"\n  STR_BATTLEHAIRBLEACH: \"Sprites de soldados mejorados\"\n  STR_BATTLEHAIRBLEACH_DESC: \"Cambia los sprites de los soldados en la Battlescape para ajustarse al aspecto que tienen en la pantalla de inventario.\"\n  STR_DRAGSCROLLINVERT: \"Invertir arrastrar-desplazar\"\n  STR_DRAGSCROLLINVERT_DESC: \"Cuando está habilitado, arrastrar desplaza en la dirección opuesta a la del ratón.\"\n  STR_BATTLESCAPE_SCALE: \"Escala de BatallaEscape\"\n  STR_BATTLESCAPE_SCALE_DESC: \"Modo de escala de visualización Battlescape, en base a una resolución fija (estirado para adaptarse), o un nivel de zoom fijo (ampliadas para llenar).\"\n  STR_GEOSCAPE_SCALE: \"Escala de Geoescape\"\n  STR_GEOSCAPESCALE_SCALE_DESC: \"Modo de escala de visualización del Geoscape, en base a una resolución fija (estirado para adaptarse), o un nivel de zoom fijo (ampliadas para llenar).\"\n  STR_1_5X: \"1.5x Original\"\n  STR_2X: \"2x Original\"\n  STR_THIRD_DISPLAY: \"1/3 de Pantalla\"\n  STR_HALF_DISPLAY: \"1/2 de Pantalla\"\n  STR_FULL_DISPLAY: \"Pantalla Completa\"\n  STR_FPS_LIMIT: \"Límite de FPS\"\n  STR_FPS_LIMIT_DESC: \"Limita el número de actualizaciones de pantalla por segundo, 0 para sin límite. Si el renderizado OPENGL esta conectado el juego usa Vsync en su lugar.\"\n  STR_FPS_INACTIVE_LIMIT: \"Límite de FPS en segundo plano\"\n  STR_FPS_INACTIVE_LIMIT_DESC: \"Limita la cantidad de actualizaciones de imágenes por segundo si OpenXcom está en segundo plano.\"\n  STR_NOALIENPANICMESSAGES: \"Suprime los mensajes de pánico de los alienígenas\"\n  STR_NOALIENPANICMESSAGES_DESC: \"Los mensajes de pánico de los alienígenas no se muentran si éstos no están al alcance de la vista del jugador.\"\n  STR_ALIENBLEEDING: \"Alienígena sangrando\"\n  STR_ALIENBLEEDING_DESC: \"Permite inflingir heridas mortales a la mayoría de los alienígenas\"\n  STR_FIELDPROMOTIONS: \"Ascensos en combate\"\n  STR_FIELDPROMOTIONS_DESC: \"Solo los soldados presentes en la misión son elegibles para ascenso.\"\n  STR_MEETINGPOINT: \"Predecir trayectoria de UFO\"\n  STR_MEETINGPOINT_DESC: \"La naves vuelan hacia el punto de encuentro con el ufo basándose en su trayectoria actual.\"\n  STR_IRONMAN: \"IRONMAN\"\n  STR_IRONMAN_DESC: \"Sin guardado manual\"\n  STR_SAVE_AND_ABANDON_GAME: \"GUARDAR Y ABANDONAR LA PARTIDA\"\n  STR_MOD_UNSUCCESSFUL: \"No se ha podido cargar el mod.\"\n  STR_NEW_SAVED_GAME_SLOT: \"<NUEVO JUEGO SALVADO>\"\n  STR_AUTO_SAVE_GEOSCAPE_SLOT: \"<AUTOMATICO GEOSCAPE>\"\n  STR_AUTO_SAVE_BATTLESCAPE_SLOT: \"<AUTOMATICO BATTLESCAPE>\"\n  STR_QUICK_SAVE_SLOT: \"<GUARDADO RÁPIDO>\"\n  STR_DISPLAY_MODE_DESC: \"Cambia como se muestra el juego en tu pantalla.\"\n  STR_PREFERRED_MUSIC_FORMAT: \"Formato de música\"\n  STR_PREFERRED_MUSIC_FORMAT_DESC: \"Selecciona el formato preferido de música a usar cuando haya varios disponibles.{NEWLINE}NOTA: La reproducción de MIDI podría sonar extraña en Windows.\"\n  STR_PREFERRED_SFX_FORMAT: \"Formato SFX\"\n  STR_PREFERRED_SFX_FORMAT_DESC: \"Selecciona el formato preferido de los efectos de sonido cuando haya más de uno disponible.\"\n  STR_PREFERRED_VIDEO_FORMAT: \"Formato de Video\"\n  STR_PREFERRED_VIDEO_FORMAT_DESC: \"Seleccione el formato de video preferido cuando haya varios disponibles.\"\n  STR_PREFERRED_VIDEO_ANIMATION: \"Animación\"\n  STR_PREFERRED_VIDEO_SLIDESHOW: \"Presentación\"\n  STR_PREFERRED_FORMAT_AUTO: \"Automático\"\n  STR_CURRENT_FORMAT: \"Actual: {0}\"\n  STR_SOUND_OPTIONS: \"Opciones de sonido\"\n  STR_BACKGROUND_MUTE: \"Silenciar música de fondo\"\n  STR_BACKGROUND_MUTE_DESC: \"Silencia todos los sonidos cuando la ventana de juego no está activa.\"\n  STR_FORCE_FIRE: \"Forzar línea de tiro\"\n  STR_FORCE_FIRE_DESC: \"Permite forzar que tus soldados puedan disparar al mantener presionado CTRL, independientemente de las reglas de línea de visión de fuego.\"\n  STR_NO_AUDIO_HARDWARE_DETECTED: \"No se detectó hardware de sonido\"\n  STR_MOUSEWHEEL_SPEED: \"Velocidad de desplazamiento de la rueda del ratón\"\n  STR_MOUSEWHEEL_SPEED_DESC: \"Ajusta el número de líneas desplazado en las listas con cada incremento de la rueda del ratón.\"\n  STR_DISABLED: \"Deshabilitado\"\n  STR_MAXIMIZE_INFO_SCREENS: \"Maximizar pantallas de información\"\n  STR_MAXIMIZE_INFO_SCREENS_DESC: \"El inventario y otras pantallas se mostrarán en pantalla completa, independientemente de los ajustes de escala.\"\n  STR_DIARY: \"DIARIO\"\n  STR_KILLED: \"MUERTO\"\n  STR_STUNNED: \"ATURDIDO\"\n  STR_PANICKED: \"DESCONTROLADO\"\n  STR_MINDCONTROLLED: \"CONTROLADO\"\n  STR_REGION_UNKNOWN: \"Divulgado\"\n  STR_WEAPON_UNKNOWN: \"Improvisación\"\n  STR_UNKNOWN: \"Desconocido\"\n  STR_VICTORY: \"Victoria\"\n  STR_DEFEAT: \"Derrota\"\n  STR_NO_RECORD: \"Sin Datos\"\n  STR_HUMAN: \"Humano\"\n  STR_FRIENDLY: \"Amistoso\"\n  STR_HOSTILE: \"Hostil\"\n  STR_NEUTRAL: \"Neutral\"\n  STR_RATING_UC: \"EVALUACIÓN\"\n  STR_LOCATION: \"UBICACIÓN> {ALT}{0}\"\n  STR_DAYLIGHT_TYPE: \"TIEMPO> {ALT}{0}\"\n  STR_RACE_TYPE: \"RAZA> {ALT}{0}\"\n  STR_DAY: \"Día\"\n  STR_NIGHT: \"Noche\"\n  STR_DAYS_WOUNDED: \"DIAS HERIDO> {ALT}{0}\"\n  STR_COMBAT: \"COMBATE\"\n  STR_PERFORMANCE: \"EXPEDIENTE\"\n  STR_NEUTRALIZATIONS_BY_RACE: \"NEUTRALIZACIONES POR RAZA\"\n  STR_NEUTRALIZATIONS_BY_RANK: \"NEUTRALIZACIONES POR RANGO\"\n  STR_NEUTRALIZATIONS_BY_WEAPON: \"NEUTRALIZACIONES POR ARMA\"\n  STR_MISSIONS_BY_LOCATION: \"MISIONES POR LUGAR\"\n  STR_MISSIONS_BY_TYPE: \"MISIONES POR TIPO\"\n  STR_MISSIONS_BY_UFO: \"MISIONES POR OVNI\"\n  STR_SCORE_VALUE: \"PUNTUACIÓN> {ALT}{0}\"\n  STR_WINS: \"VICTORIAS> {ALT}{0}\"\n  STR_STUNS: \"ATURDIDOS> {ALT}{0}\"\n  STR_PANICKS: \"DESCONTROLES> {ALT}{0}\"\n  STR_MINDCONTROLS: \"CONTROLES> {ALT}{0}\"\n  STR_AWARDS: \"PROMOCIÓN\"\n  STR_COMMENDATIONS_UC: \"CONDECORACIONES\"\n  STR_COMMENDATIONS: \"Condecoraciones\"\n  STR_MEDALS: \"MEDALLAS\"\n  STR_LOST_IN_SERVICE: \"ABATIDOS EN ACCIÓN\"\n  STR_MEDAL_NAME: \"Nombre de Medalla\"\n  STR_MEDAL_AWARD_LEVEL: \"Nivel de Promoción\"\n  STR_MEDAL_DECOR_LEVEL: \"Nivel de Decoración\"\n  STR_AWARD_0: \"1a Promoción\"\n  STR_AWARD_1: \"2a Promoción\"\n  STR_AWARD_2: \"3a Promoción\"\n  STR_AWARD_3: \"4a Promoción\"\n  STR_AWARD_4: \"5a Promoción\"\n  STR_AWARD_5: \"6a Promoción\"\n  STR_AWARD_6: \"7a Promoción\"\n  STR_AWARD_7: \"8a Promoción\"\n  STR_AWARD_8: \"9a Promoción\"\n  STR_AWARD_9: \"10a Promoción\"\n  STR_AWARD_DECOR_0: \"Ninguna\"\n  STR_AWARD_DECOR_1: \"Primer Pin de Bronce\"\n  STR_AWARD_DECOR_2: \"Segundo pin de Bronce\"\n  STR_AWARD_DECOR_3: \"Tercer pin de Bronce\"\n  STR_AWARD_DECOR_4: \"Primer pin de Plata\"\n  STR_AWARD_DECOR_5: \"Segundo pin de Plata\"\n  STR_AWARD_DECOR_6: \"Tercer pin de Plata\"\n  STR_AWARD_DECOR_7: \"Primer Pin de Oro\"\n  STR_AWARD_DECOR_8: \"Segundo pin de Oro\"\n  STR_AWARD_DECOR_9: \"Tercer Pin de Oro\"\n  STR_KILLED_IN_ACTION_MALE: \"ASESINADO EN ACCIÓN\"\n  STR_KILLED_IN_ACTION_FEMALE: \"ASESINADO EN ACCIÓN\"\n  STR_MISSING_IN_ACTION_MALE: \"DESAPARECIDO EN COMBATE\"\n  STR_MISSING_IN_ACTION_FEMALE: \"DESAPARECIDO EN COMBATE\"\n  STR_AVERAGE_MONTHLY_RATING: \"Rendimiento medio mensual\"\n  STR_TOTAL_INCOME: \"Ingresos totales\"\n  STR_TOTAL_EXPENDITURE: \"Gastos totales\"\n  STR_MISSIONS_WON: \"Misión cumplida\"\n  STR_MISSIONS_LOST: \"Misión perdida\"\n  STR_NIGHT_MISSIONS: \"Misiones nocturnas\"\n  STR_BEST_RATING: \"Mejor rendimiento en misión\"\n  STR_WORST_RATING: \"Peor rendimiento de misión\"\n  STR_ALIEN_KILLS: \"Alienígenas muertos\"\n  STR_ALIEN_CAPTURES: \"Alienígenas capturados\"\n  STR_FRIENDLY_KILLS: \"Incidentes de fuego amigo\"\n  STR_AVERAGE_ACCURACY: \"Puntería media\"\n  STR_WEAPON_MOST_KILLS: \"Arma más efectiva\"\n  STR_ALIEN_MOST_KILLS: \"Alienígena más letal\"\n  STR_LONGEST_SERVICE: \"Más meses en servicio\"\n  STR_TOTAL_DAYS_WOUNDED: \"Días de baja\"\n  STR_COUNTRIES_LOST: \"Países inflitrados\"\n  STR_TOTAL_TERROR_SITES: \"Ataques terroristas\"\n  STR_TOTAL_BASES: \"Bases construidas\"\n  STR_TOTAL_CRAFT: \"Aviones gestionados\"\n  STR_TOTAL_SCIENTISTS: \"Científicos contratados\"\n  STR_TOTAL_ENGINEERS: \"Ingenieros contratados\"\n  STR_TOTAL_RESEARCH: \"Investigación completada\"\n  STR_DIARY_ACCURACY: \"PUNTERIA> {ALT}{0}%\"\n  STR_STATISTICS: \"Estadísticas\"\n  STR_STATS: \"ESTADÍSTICAS\"\n  STR_TIME_UNITS_ABBREVIATION: \"UT\"\n  STR_STAMINA_ABBREVIATION: \"STA\"\n  STR_HEALTH_ABBREVIATION: \"PS\"\n  STR_BRAVERY_ABBREVIATION: \"BRV\"\n  STR_REACTIONS_ABBREVIATION: \"REA\"\n  STR_FIRING_ACCURACY_ABBREVIATION: \"PUN\"\n  STR_THROWING_ACCURACY_ABBREVIATION: \"LAN\"\n  STR_STRENGTH_ABBREVIATION: \"FUE\"\n  STR_MELEE_ACCURACY_ABBREVIATION: \"CAC\"\n  STR_FOLDERS: \"CARPETAS\"\n  STR_DATA_FOLDER: \"Carpeta Data (recursos originales)\"\n  STR_USER_FOLDER: \"Carpeta User (mods, openxcom.log)\"\n  STR_SAVE_FOLDER: \"Carpeta Save (partidas guardadas, capturas de pantalla)\"\n  STR_CONFIG_FOLDER: \"Carpeta Config (options.cfg)\"\n  STR_DATA_FOLDER_DESC_1: \"Es donde OpenXcom buscará los recursos originales del juego (UFO y TFTD).\"\n  STR_DATA_FOLDER_DESC_2: \"Los recursos internos de OpenXcom están en la carpeta 'common'. Los mods preconstruidos dentro de OpenXcom están en la carpeta 'standard'.\"\n  STR_USER_FOLDER_DESC: \"El archivo de registro ('openxcom.log') se almacena aquí. Todas las modificaciones personalizadas también van aquí (en la subcarpeta 'mods').\"\n  STR_SAVE_FOLDER_DESC: \"Tus juegos guardados se encuentran aquí. Además, la configuración del generador de misiones ('battle.cfg') se puede encontrar aquí.\"\n  STR_CONFIG_FOLDER_DESC: \"Aquí es donde se almacenan las configuraciones de OpenXcom ('options.cfg'). Normalmente lo mismo que la Carpeta User.\"\n"
  },
  {
    "path": "bin/common/Language/et.yml",
    "content": "et:\n  STR_OPENXCOM: \"OpenXcom\"\n  STR_NEW_GAME: \"Uus Mäng\"\n  STR_LOAD_SAVED_GAME: \"Lae Mäng\"\n  STR_SELECT_DIFFICULTY_LEVEL: \"Vali Raskus Aste\"\n  STR_1_BEGINNER: \"1> Algaja\"\n  STR_2_EXPERIENCED: \"2> Kogenud\"\n  STR_3_VETERAN: \"3> Veteran\"\n  STR_4_GENIUS: \"4> Geenius\"\n  STR_5_SUPERHUMAN: \"5> Üliinimene\"\n  STR_TIME: \"Aeg\"\n  STR_DATE: \"Kuupäev\"\n  STR_SELECT_GAME_TO_LOAD: \"Vali mäng laadimiseks\"\n  STR_SELECT_SAVE_POSITION: \"Vali salvestus\"\n  STR_GAME_OPTIONS: \"MÄNGU VALIKUD\"\n  STR_LOAD_GAME: \"LAE MÄNG\"\n  STR_SAVE_GAME: \"SALVESTA MÄNG\"\n  STR_ABANDON_GAME: \"LOOBU MÄNGUST\"\n  STR_ABANDON_GAME_QUESTION: \"LAHKU MÄNGUST?\"\n  STR_QUIT: \"Loobu\"\n  STR_SAVING_GAME: \"Salvestan mängu\"\n  STR_LOADING_GAME: \"Laen mängu\"\n  STR_NO_SAVED_GAME_PRESENT: \"Salvestatud mäng puudub\"\n  STR_LOAD_UNSUCCESSFUL: \"Laadimine ebaõnnestus\"\n  STR_SAVE_UNSUCCESSFUL: \"Salvestamine ebaõnnestus\"\n  STR_LOAD_SUCCESSFUL: \"Laadimine õnnestus\"\n  STR_SAVE_SUCCESSFUL: \"Salvestamine õnnestus\"\n  STR_DELETE: \"KUSTUTA\"\n  STR_DELETE_UNSUCCESSFUL: \"Kustutamine ebaõnnestus\"\n  STR_IS_IT_OK_TO_DELETE_THE_SAVED_GAME: \"Oled kindel, et soovid kustutada savestatud mängu?\"\n  STR_ORIGINAL_XCOM: \"Originaal X-Com\"\n  STR_LOADING: \"Laen...\"\n  STR_DETAILS: \"DETAILID> {ALT}{0}\"\n  STR_NEW_BATTLE: \"Uus Lahing\"\n  STR_OPTIONS: \"Valikud\"\n  STR_RIGHT_CLICK_TO_DELETE: \"Parem klõps kustutamiseks\"\n  STR_RESTORE_DEFAULTS: \"Taasta tehase seadmed\"\n  STR_CONTROLS: \"NUPUD\"\n  STR_GENERAL: \"Üldine\"\n  STR_GEOSCAPE: \"Maakera\"\n  STR_BATTLESCAPE: \"Lahingumaastik\"\n  STR_SCREENSHOT: \"Kuvatõmmis\"\n  STR_FPS_COUNTER: \"FPS lugeja\"\n  STR_ROTATE_LEFT: \"Keera vasakule\"\n  STR_ROTATE_RIGHT: \"Pööra paremale\"\n  STR_ROTATE_UP: \"Keera alla\"\n  STR_ROTATE_DOWN: \"Pööra alla\"\n  STR_ZOOM_IN: \"Suurenda\"\n  STR_ZOOM_OUT: \"Vähenda\"\n  STR_TOGGLE_COUNTRY_DETAIL: \"Muuda maade detaile\"\n  STR_TOGGLE_RADAR_RANGES: \"Muuda radari vaatevälja\"\n  STR_SCROLL_LEFT: \"Skrolli vasakule\"\n  STR_SCROLL_RIGHT: \"Skrolli paremale\"\n  STR_SCROLL_UP: \"Skrolli üles\"\n  STR_SCROLL_DOWN: \"Skrolli alla\"\n  STR_UNIT_LEVEL_ABOVE: \"Liiguta üksus ülemisele tasandile\"\n  STR_UNIT_LEVEL_BELOW: \"Liiguta üksus alumisele tasandile\"\n  STR_VIEW_LEVEL_ABOVE: \"Vaatle kõrgemalt tasemelt\"\n  STR_VIEW_LEVEL_BELOW: \"Vaatle madalamalt tasemelt\"\n  STR_CENTER_SELECTED_UNIT: \"Posistioneeri üksus\"\n  STR_PREVIOUS_UNIT: \"Väli Eelmine Üksus\"\n  STR_NEXT_UNIT: \"Vali järgmine üksus\"\n  STR_DESELECT_UNIT: \"Ära vali üksust uueseti\"\n  STR_USE_LEFT_HAND: \"Kasuta vasakus käes olevat asja.\"\n  STR_USE_RIGHT_HAND: \"Kasuta paremas käes olevat asja\"\n  STR_INVENTORY: \"Invetar\"\n  STR_MINIMAP: \"Minimap\"\n  STR_MULTI_LEVEL_VIEW: \"Mitmetasandiline vaade\"\n  STR_END_TURN: \"Lõpeta Käik\"\n  STR_ABORT_MISSION: \"Abordi Missioon\"\n  STR_UNIT_STATS: \"Üksuse statistika\"\n  STR_KNEEL: \"Kükita\"\n  STR_RELOAD: \"Lae\"\n  STR_TOGGLE_PERSONAL_LIGHTING: \"Lülita personaalne valgus\"\n  STR_DONT_RESERVE_TIME_UNITS: \"Ära säästa AÜ-d\"\n  STR_RESERVE_TIME_UNITS_FOR_SNAP_SHOT: \"Hoia TUsi kiirlasuks.\"\n  STR_RESERVE_TIME_UNITS_FOR_AIMED_SHOT: \"Hoia AUsi sihitud lasuks.\"\n  STR_RESERVE_TIME_UNITS_FOR_AUTO_SHOT: \"Hoia AUsi valanguks\"\n  STR_CENTER_ON_ENEMY_1: \"Keskendu 1 vaenlasele\"\n  STR_CENTER_ON_ENEMY_2: \"Keskendu 2 vaenlasele\"\n  STR_CENTER_ON_ENEMY_3: \"Keskendu 3 vaenlasele\"\n  STR_CENTER_ON_ENEMY_4: \"Keskendu 4 vaenlasele\"\n  STR_CENTER_ON_ENEMY_5: \"Keskendu 5 vaenlasele\"\n  STR_CENTER_ON_ENEMY_6: \"Keskendu 6 vaenlasele\"\n  STR_CENTER_ON_ENEMY_7: \"Keskendu 7 vaenlasele\"\n  STR_CENTER_ON_ENEMY_8: \"Keskendu 8 vaenlasele\"\n  STR_CENTER_ON_ENEMY_9: \"Keskendu 9 vaenlasele\"\n  STR_CENTER_ON_ENEMY_10: \"Keskendu 10 vaenlasele\"\n  STR_CREATE_INVENTORY_TEMPLATE: \"Tekita varustuse mall\"\n  STR_APPLY_INVENTORY_TEMPLATE: \"Lisa varustuse mall\"\n  STR_CLEAR_INVENTORY: \"Tühjenda varustus\"\n  STR_AUTO_EQUIP: \"Auto-kättevõtmine\"\n  STR_QUICK_SAVE: \"Kiirsalvestus\"\n  STR_QUICK_LOAD: \"Kiirlaadmine\"\n  STR_ADVANCED: \"LAIENDATUD\"\n  STR_AGGRESSIVERETALIATION: \"Agresiivne vastulöök\"\n  STR_AGGRESSIVERETALIATION_DESC: \"Vaatamata ülesannetele Püüavad UFOd alati leida sinu baasi.\"\n  STR_STORAGELIMITSENFORCED: \"Lao limiidid leitud asjadele\"\n  STR_STORAGELIMITSENFORCED_DESC: \"Määrab lao ja tulnukate kinnipidamisaustuse limiidi missioonilt saadud asjadele ning elusatele tulnukatele.\"\n  STR_CANSELLLIVEALIENS: \"Elusate tulnukate müük.\"\n  STR_CANSELLLIVEALIENS_DESC: \"Lubab müüa elusaid tulnukaid, soovitatav siis kui on määratud ladude limiit.\"\n  STR_ALLOWBUILDINGQUEUE: \"Luba ehitiste järjekord\"\n  STR_ALLOWBUILDINGQUEUE_DESC: \"Uusi rajatisi on lubatud lisada ehitusjärgus olevate kõrvale.\"\n  STR_BATTLEAUTOEND: \"Lahingu auto lõpp\"\n  STR_BATTLEAUTOEND_DESC: \"Lahingud lõppevad automaatselt kui viimane vaenlane on neutraliseeritud.\"\n  STR_BATTLEINSTANTGRENADE: \"Silmapilksed granaadid\"\n  STR_BATTLEINSTANTGRENADE_DESC: \"Granaadid, mis on aktiveeritakse 0 käigule plahvatavad kohe peal viskamist mitte käigu lõpus \"\n  STR_BATTLEUFOEXTENDERACCURACY: \"UFO täpsuse täpsustus\"\n  STR_BATTLEUFOEXTENDERACCURACY_DESC: \"Vastavalt lasu tüübile langeb laskude täpsus peale teatud kaugust. Muudetud täpsus kuvatakse kursorile.\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE: \"Õhuüleviimine\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE_DESC: \"Lennus olevaid sõidukeid saab üle viia teise baasi.\"\n  STR_CRAFTLAUNCHALWAYS: \"Sunni sõiduk lahkuma\"\n  STR_CRAFTLAUNCHALWAYS_DESC: \"Sõidukid võivad õhku tõusta ka siis kui nad ei ole veel hooldust või ümberrelvastumist lõpetanud.\"\n  STR_CUSTOMINITIALBASE: \"Valikuline algusbaas\"\n  STR_CUSTOMINITIALBASE_DESC: \"Alustades uut mängu on võimalus baasirajatisi manuaalselt asetada vaikimisi baasiplaani asemel.\"\n  STR_GLOBESEASONS: \"Realistlikum gloobuse valgustus\"\n  STR_GLOBESEASONS_DESC: \"Kasutab realistlikumat päikesevalguse projekteerimist gloobusel vastavalt maakera raadiusele.\"\n  STR_PLAYINTRO: \"Mängi intro\"\n  STR_PLAYINTRO_DESC: \"Näita intro video käivitamisel.\"\n  STR_SHOWMORESTATSININVENTORYVIEW: \"Varustuse andmed\"\n  STR_SHOWMORESTATSININVENTORYVIEW_DESC: \"Näita lisainformatsiooni valitud sõduri varustuse lehel.\"\n  STR_SNEAKYAI: \"Salakaval AI\"\n  STR_SNEAKYAI_DESC: \"AI vädib enda avaldamist mängijale igal võimalikul viisil\"\n  STR_STRAFE: \"Alternatiivses liikumismeetodid\"\n  STR_STRAFE_DESC: \"CTRLi all hoides lubab joosta ning tanki torni iseseisvat liikumist.\"\n  STR_BATTLEEXPLOSIONHEIGHT: \"Plahvatuse kõrgus\"\n  STR_BATTLEEXPLOSIONHEIGHT_DESC: \"Muuda kui kõrgele plahvatus levib.{NEWLINE}(Nullist kolmeni)\"\n  STR_AUTOSAVE: \"Automaatsalvestus\"\n  STR_AUTOSAVE_DESC: \"Automaatselt salvestab mängu teatud intervallide tagant. Ei kehti Raudmehe modes.\"\n  STR_AUTOSAVE_FREQUENCY: \"Automaatsalvestuse tihedus\"\n  STR_AUTOSAVE_FREQUENCY_DESC: \"Käikude arv peale mida mäng salvestatakse automaatselt.\"\n  STR_ALLOWPSIONICCAPTURE: \"Luba Psi-vangistus\"\n  STR_ALLOWPSIONICCAPTURE_DESC: \"Kõikide allesjäänud tulnukate mõistukontrollimine tähendab võitu ning nad lähevad arvesse kui elusalt kinni püütud.\"\n  STR_ANYTIMEPSITRAINING: \"Psi treening igal ajal\"\n  STR_ANYTIMEPSITRAINING_DESC: \"Luba sõduritel psi treenida igal ajal. Arvesta, et esialgne treening võtab aega 30 kuni 60 päeva.\"\n  STR_SKIPNEXTTURNSCREEN: \"Jäta \\\"Järgmise kord\\\" kuvatõmmis vahele\"\n  STR_SKIPNEXTTURNSCREEN_DESC: \"Kuvatõmmisest \\\"Järgmise kord\\\" liigutakse automaatselt edasi mõne aja pärast.\"\n  STR_NOT_ENOUGH_SPACE: \"Ruumi puudus!\"\n  STR_WEAPONSELFDESTRUCTION: \"Isehävivad tulnukate relvad\"\n  STR_WEAPONSELFDESTRUCTION_DESC: \"Nagu XCOM 2012, tulnukate relvad hävinevad kui nende omanik eliminieeritakse\"\n  STR_RETAINCORPSES: \"Jäta ülekuulatud tulnukad alles\"\n  STR_RETAINCORPSES_DESC: \"Peale elusate tulnukate \\\"ülekuulamist\\\" lisatakse nende raibe baasi ladudesse nagu XCOM 2012s.\"\n  STR_SAVE_VOXEL_VIEW: \"Salvesta isiku ekraanipilt.\"\n  STR_RESERVE_TIME_UNITS_FOR_KNEEL: \"Hoia TUsi kükitamiseks\"\n  STR_EXPEND_ALL_TIME_UNITS: \"Kuluta kõik allesolevad TUd\"\n  STR_PSISTRENGTHEVAL: \"Psi-tugevuse hindamine.\"\n  STR_PSISTRENGTHEVAL_DESC: \"Hindab sõdurite psioonilist tugevust peale seda kui vajalikud teadused on leiutatud.\"\n  STR_DISABLEAUTOEQUIP: \"Keela automaatne kasutamine\"\n  STR_DISABLEAUTOEQUIP_DESC: \"Keela uute sõdurite automaatne relvastumine\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT: \"Luba Psi-tugevuse täiustamine\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT_DESC: \"Sõdurite psiooniline tugevus täieneb tänu treenimisele ja kogemusele.\"\n  STR_BATTLESMOOTHCAMERA: \"Ühtlane kuuli kaamera\"\n  STR_BATTLESMOOTHCAMERA_DESC: \"Lahingumaastiku kaamera järgib kuuli lennu teekonda.\"\n  STR_BATTLECONFIRMFIREMODE: \"Kinnita tulistamine.\"\n  STR_BATTLECONFIRMFIREMODE_DESC: \"Nõuab teist klikki samal kohal kinnitamaks tule avamist.\"\n  STR_SELECT_BASE_1: \"Vali esimene baas\"\n  STR_SELECT_BASE_2: \"Vali teine baas\"\n  STR_SELECT_BASE_3: \"Vali kolmas baas\"\n  STR_SELECT_BASE_4: \"Vali neljas baas\"\n  STR_SELECT_BASE_5: \"Vali viies baas\"\n  STR_SELECT_BASE_6: \"Vali kuues baas\"\n  STR_SELECT_BASE_7: \"Vali seitsmes baas\"\n  STR_SELECT_BASE_8: \"Vali kaheksas baas\"\n  STR_VIDEO: \"VIDEO\"\n  STR_AUDIO: \"AUDIO\"\n  STR_BATTLESCAPE_UC: \"LAHINGUMAASTIK\"\n  STR_MODS_UC: \"MODID\"\n  STR_MODS: \"Modid\"\n  STR_DISPLAY_RESOLUTION: \"Ekraani resolutsioon\"\n  STR_DISPLAY_RESOLUTION_DESC: \"Muudab ekraani resulutsiooni, mängu resulutsioon muudetakse vastavaks. Nooled vahetavad toetatavaid resulutsioone. Kliki suvalise resulutsiooni sisestamiseks.\"\n  STR_ORIGINAL: \"Originaal\"\n  STR_DISPLAY_MODE: \"Ekraani suurus\"\n  STR_WINDOWED: \"Aknas\"\n  STR_FULLSCREEN: \"Täisekraan\"\n  STR_BORDERLESS: \"Piiridetu\"\n  STR_DISPLAY_LANGUAGE: \"Kuva keel\"\n  STR_DISPLAY_LANGUAGE_DESC: \"Muudab mängusisese keele.\"\n  STR_DISPLAY_FILTER: \"Kuva filter.\"\n  STR_DISPLAY_FILTER_DESC: \"Vahetab mänguaknale lisatavat filtrit.{NEWLINE}*vajab OpenGL raudvara olemasolu.\"\n  STR_DISPLAY_OPTIONS: \"Näita valikuid\"\n  STR_LETTERBOXED: \"LEtterboxed\"\n  STR_LETTERBOXED_DESC: \"Muudab ekraani suurust, et jälgida ekraani originaalsuhet.\"\n  STR_RESIZABLE: \"Muudetav\"\n  STR_LOCK_MOUSE: \"Raba hiir\"\n  STR_LOCK_MOUSE_DESC: \"Ei luba hiire kursoril mängu aknast lahkuda. Ctrl+G muudab valikuid.\"\n  STR_FIXED_WINDOW_POSITION: \"Fikseeritud akna positsioon\"\n  STR_FIXED_WINDOW_POSITION_DESC: \"Vali aknale fikseeritud positsioon\"\n  STR_DISPLAY_SET_WINDOW_POSITION: \"Määra uus akna juurekoht\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_X: \"Vasakpoolse piiraja uus X:\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_Y: \"Ülemise piiraja uus Y:\"\n  STR_MUSIC_VOLUME: \"Muusika heli tugevus\"\n  STR_MUSIC_VOLUME_DESC: \"Muudab taustamuusika helitugevust.\"\n  STR_SFX_VOLUME: \"SFX heli tugevus\"\n  STR_SFX_VOLUME_DESC: \"Muudab häälte helitugevust.\"\n  STR_UI_VOLUME: \"Liidese helitugevus\"\n  STR_UI_VOLUME_DESC: \"Muudab liidese piiksude helitugevust.\"\n  STR_SCROLL_SPEED: \"Kerimiskiirus\"\n  STR_SCROLL_SPEED_GEO_DESC: \"Muudab maakera kerimiskiirust.\"\n  STR_SCROLL_SPEED_BATTLE_DESC: \"Muudab kaardi kerimiskiirust.\"\n  STR_DOGFIGHT_SPEED: \"Õhulahingu kiirus\"\n  STR_DOGFIGHT_SPEED_DESC: \"Muudab lahingute kiirust UFOde ja neid ründavate õhusõidukite vahel. Madalamad kiirused võivad tõsta aeglasemate aparaatide jõudlust.\"\n  STR_CLOCK_SPEED: \"Kella kiirus\"\n  STR_CLOCK_SPEED_DESC: \"Muuda maakera kella kiirust. Madalamad kiirused võivad tõsta aeglasemate aparaatide jõudlust.\"\n  STR_GLOBE_DETAILS: \"Gloobuse detailid\"\n  STR_GLOBE_COUNTRIES: \"Riigid\"\n  STR_GLOBE_COUNTRIES_DESC: \"Näitab riikide rahastust kaardil.\"\n  STR_GLOBE_RADARS: \"Radarid\"\n  STR_GLOBE_RADARS_DESC: \"Näitab baasi radarite kaugust gloobusel\"\n  STR_GLOBE_FLIGHT_PATHS: \"Lennu trajektoorid\"\n  STR_GLOBE_FLIGHT_PATHS_DESC: \"Näitab õhusõidukite trajektoore maakeral.\"\n  STR_CONTROLS_DESC: \"Vasakklikk lühendile ning vajuta nuppu selle muutmiseks.{NEWLINE}.Paremklikk lühendil selle keelustamiseks.\"\n  STR_BASE_GAME: \"Baasmäng\"\n  STR_MODS_TOOLTIP: \"Versioon {0} {1} poolt. {NEWLINE}{2}\"\n  STR_EDGE_SCROLL: \"Ääre skrollimine\"\n  STR_EDGE_SCROLL_DESC: \"Trigger: liiguta kaarti kui hiire vasakut nuppu hoitakse kaardi serval all.{NEWLINE}Auto: liiguta kaarti siis kui hiire kursor on üle kaardi serva.\"\n  STR_TRIGGER_SCROLL: \"Trigger\"\n  STR_AUTO_SCROLL: \"Automaatne\"\n  STR_DRAG_SCROLL: \"Drag scroll\"\n  STR_DRAG_SCROLL_DESC: \"Liigutab kaarti kui määratud hiire nuppu hoitakse all ning lohistatakse seda.\"\n  STR_LEFT_MOUSE_BUTTON: \"Vasak nupp\"\n  STR_MIDDLE_MOUSE_BUTTON: \"Keskmine nupp\"\n  STR_RIGHT_MOUSE_BUTTON: \"Parem nupp\"\n  STR_FIRE_SPEED: \"LASKMISKIIRUS\"\n  STR_FIRE_SPEED_DESC: \"Muudab relvade laskemoona lennu kiirust.\"\n  STR_PLAYER_MOVEMENT_SPEED: \"Mängija liikumiskiirus\"\n  STR_PLAYER_MOVEMENT_SPEED_DESC: \"Muudab mängija poolt kontrollitud üksuste liikumiskiirust.\"\n  STR_COMPUTER_MOVEMENT_SPEED: \"AI liikumiskiirus\"\n  STR_COMPUTER_MOVEMENT_SPEED_DESC: \"Muudab arvuriga kontrollitavate üksuste kiiruseid\"\n  STR_PATH_PREVIEW: \"Teeraja eelvaade\"\n  STR_PATH_ARROWS: \"Nooled\"\n  STR_PATH_ARROWS_DESC: \"Klikkimine näitab teerada mida sinu üksus läbib sihtkohta jõudmiseks. Värv näitab allesolevaid võimalusi: roheline - saab liikuda ja tulistada; kollane - saab liikuda; punane - liikumine välistatud.\"\n  STR_PATH_TIME_UNIT_COST: \"Ajaühikud\"\n  STR_PATH_TIME_UNIT_COST_DESC: \"Klikkimine näitab peale kohale jõudmist allesjäänud ajaühikuid.\"\n  STR_USER_INTERFACE_OPTIONS: \"UI valikud\"\n  STR_TOOLTIPS: \"Vihjed\"\n  STR_TOOLTIPS_DESC: \"Näitab vihjeid lahingumaastiku nuppudele.\"\n  STR_DEATH_NOTIFICATIONS: \"Näita surma teateid\"\n  STR_DEATH_NOTIFICATIONS_DESC: \"Iga kord kui keegi sõdureist langeb näita hüpikakent detailidega kes surma sai.\"\n  STR_SHOW_FUNDS: \"Finantsolukord\"\n  STR_SHOW_FUNDS_DESC: \"Näitab hetkelist finantseisu maakaardi kella kõrval.\"\n  STR_MISSION_GENERATOR: \"MISSIOONI GENERAATOR\"\n  STR_MAP_OPTIONS: \"KAARDI VALIKUD\"\n  STR_ALIEN_OPTIONS: \"TULNUKATE VALIKUD\"\n  STR_MAP_TERRAIN: \"Maastik\"\n  STR_MAP_DARKNESS: \"Pimedus\"\n  STR_MAP_DEPTH: \"Sügavus\"\n  STR_DIFFICULTY: \"Raskusaste\"\n  STR_ALIEN_RACE: \"Rass\"\n  STR_ALIEN_TECH_LEVEL: \"Tehnotase\"\n  STR_RANDOMIZE: \"Juhuslikusta\"\n  STR_RESTORE_DEFAULTS_QUESTION: \"Olete kindel, et soovite taastada algsed sätted?\"\n  STR_DISPLAY_OPTIONS_CONFIRM: \"Soovid säilitada olemasolevaid ekraanisätteid?\"\n  STR_DISPLAY_OPTIONS_REVERT: \"Tagasi pöördumine 0:{0}\"\n  STR_MISSING_CONTENT_PROMPT: \"HOIATUS:{SMALLLINE}See salvestus sõltub modidest mis pole saadaval. Puuduv sisu eemaldatakse ning taastamine võib ebaõnnestuda.{NEWLINE}Jätkata?\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT: \"Salvesta eelvinnastatud granaadid\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT_DESC: \"Salvestab eelvinnastatud granaadid enne lahingut sõduri varustuse paigutuses.\"\n  STR_NEWSEEDONLOAD: \"Salvestushullus\"\n  STR_NEWSEEDONLOAD_DESC: \"Mängu taastamine muudab juhuslikkuse muutujat, seega sama tegevuse kordamine võib anda teistsuguse tulemuse. Ei kehti IRONMAN taseme kohta.\"\n  STR_CHANGEVALUEBYMOUSEWHEEL: \"Muuda hiire rattaga väärtusi\"\n  STR_CHANGEVALUEBYMOUSEWHEEL_DESC: \"Lubab hiire rattaga suurendada/vähendada väärtusi.\"\n  STR_BATTLEHAIRBLEACH: \"Täiustatud sõdurite spraidid\"\n  STR_BATTLEHAIRBLEACH_DESC: \"Muudab lahingumaastikul kuvatavad sõdurite spraidid vastavaks varustuse leheküljel kuvatavateks\"\n  STR_DRAGSCROLLINVERT: \"Muuda drag-scrollimist\"\n  STR_DRAGSCROLLINVERT_DESC: \"Kui aktiveeritud siis määra hiire lohistamist vastupidiseks.\"\n  STR_BATTLESCAPE_SCALE: \"Lahingumaastiku skaala\"\n  STR_BATTLESCAPE_SCALE_DESC: \"Lahingumaastiku vaate skaleerimine kas fikseeritud resol (pilti venitatakse et mahuks) või suumi tasemest (pilti laiedatakse et täita)\"\n  STR_GEOSCAPE_SCALE: \"Maakera skaala\"\n  STR_GEOSCAPESCALE_SCALE_DESC: \"Maakera vaate skaleerimine kas fikseeritud resol (pilti venitatakse et mahuks) või suumi tasemest (pilti laiedatakse et täita)\"\n  STR_1_5X: \"1.5x originaalist\"\n  STR_2X: \"2x originaalist\"\n  STR_THIRD_DISPLAY: \"1/3 ekraanist\"\n  STR_HALF_DISPLAY: \"1/2 ekraanist\"\n  STR_FULL_DISPLAY: \"Täisekraan\"\n  STR_FPS_LIMIT: \"FPS limiit\"\n  STR_FPS_LIMIT_DESC: \"Limiteerib ekraani uuendusi sekundi jooksul, 0 limiit puudub. Kui OpenGL renderdus on lubatud siis mäng kasutab Vsynci selle asemel.\"\n  STR_FPS_INACTIVE_LIMIT: \"FPS limiidi taust\"\n  STR_FPS_INACTIVE_LIMIT_DESC: \"Limiteerib ekraani uuendusi sekundis kui OpenXcom töötab taustal.\"\n  STR_NOALIENPANICMESSAGES: \"Varja tulnukate paanikateated\"\n  STR_NOALIENPANICMESSAGES_DESC: \"Ära näita teateid hirmunud tulnukaist juhul kui mängija tulnukaid ei näe.\"\n  STR_ALIENBLEEDING: \"Tulnukate veritsemine\"\n  STR_ALIENBLEEDING_DESC: \"Lubab tekitada surmavaid haavu enamus tulnukaile\"\n  STR_FIELDPROMOTIONS: \"Väliülendused\"\n  STR_FIELDPROMOTIONS_DESC: \"Ainult missioonil olnud sõdureid võib esitada ülendusteks\"\n  STR_MEETINGPOINT: \"Ennusta UFO trajektoor\"\n  STR_MEETINGPOINT_DESC: \"Sõidukid lendavad UFOga kohtumispunkti vastavalt hetkelisele trajektoorile.\"\n  STR_IRONMAN: \"IRONMAN\"\n  STR_IRONMAN_DESC: \"Manuaalne salvestamine puudub\"\n  STR_SAVE_AND_ABANDON_GAME: \"Salvesta ja lahku mängust\"\n  STR_MOD_UNSUCCESSFUL: \"Modi laadimine ebaõnnestus\"\n  STR_NEW_SAVED_GAME_SLOT: \"<NEW SAVED GAME>\"\n  STR_AUTO_SAVE_GEOSCAPE_SLOT: \"<AUTO GEOSCAPE>\"\n  STR_AUTO_SAVE_BATTLESCAPE_SLOT: \"<AUTO BATTLESCAPE>\"\n  STR_QUICK_SAVE_SLOT: \"<QUICKSAVE>\"\n  STR_DISPLAY_MODE_DESC: \"Muuda kuidas mängu kuvatakse sinu ekraanil\"\n  STR_PREFERRED_MUSIC_FORMAT: \"Muusika formaat\"\n  STR_PREFERRED_MUSIC_FORMAT_DESC: \"Valib eelistatud muusikaformaadi juhul kui valikus on neid mitu. {NEWLINE} NB: MIDI võib Windowsi all natukene bugine olla.\"\n  STR_PREFERRED_SFX_FORMAT: \"SFX formaat\"\n  STR_PREFERRED_SFX_FORMAT_DESC: \"Valib eelistatud häälefektid juhul kui valikus on rohkem kui üks.\"\n  STR_PREFERRED_VIDEO_FORMAT: \"Video formaat\"\n  STR_PREFERRED_VIDEO_FORMAT_DESC: \"Valib eelistatud videoformaadi kui valikus on erinevaid.\"\n  STR_PREFERRED_VIDEO_ANIMATION: \"Animatsioon\"\n  STR_PREFERRED_VIDEO_SLIDESHOW: \"Slaidid\"\n  STR_PREFERRED_FORMAT_AUTO: \"Automaatne\"\n  STR_CURRENT_FORMAT: \"Hetkel: {0}\"\n  STR_SOUND_OPTIONS: \"Häälte valikud\"\n  STR_BACKGROUND_MUTE: \"Tausta vaigistamine\"\n  STR_BACKGROUND_MUTE_DESC: \"Vaigistab kõik hääled kui mänguaken ei ole aktiivne.\"\n  STR_FORCE_FIRE: \"Ignoreeri tulejoont\"\n  STR_FORCE_FIRE_DESC: \"CTRLi all hoides lubab sõduritel tulistada sihtmärgi pihta ignoreerides tulejoone reegleid\"\n  STR_NO_AUDIO_HARDWARE_DETECTED: \"Ei leitud audio riistvara\"\n  STR_MOUSEWHEEL_SPEED: \"Hiire ratta liikumise kiirus\"\n  STR_MOUSEWHEEL_SPEED_DESC: \"Muudab mitu rida korraga hiire rullikut liigutades edasi liigutakse.\"\n  STR_DISABLED: \"Keelatud\"\n  STR_MAXIMIZE_INFO_SCREENS: \"Maksimeeri infotabelid\"\n  STR_MAXIMIZE_INFO_SCREENS_DESC: \"Inventar ja muid sarnased infobokse näidatakse vaatamata skaalasetetele täisekraanis.\"\n  STR_DIARY: \"Päevik\"\n  STR_KILLED: \"Tapetud\"\n  STR_STUNNED: \"Uimastatud\"\n  STR_PANICKED: \"Paanikasse sattunud\"\n  STR_MINDCONTROLLED: \"Kontrollitud\"\n  STR_REGION_UNKNOWN: \"Salajas hoitud\"\n  STR_WEAPON_UNKNOWN: \"Improvisatsioon\"\n  STR_UNKNOWN: \"Teadmata\"\n  STR_VICTORY: \"Võit\"\n  STR_DEFEAT: \"Kaotus\"\n  STR_NO_RECORD: \"Info puudub\"\n  STR_HUMAN: \"Inimene\"\n  STR_FRIENDLY: \"Sõbralik\"\n  STR_HOSTILE: \"Vaenlane\"\n  STR_NEUTRAL: \"Neutraalne\"\n  STR_RATING_UC: \"Reiting\"\n  STR_LOCATION: \"ASUKOHT> {ALT}{0}\"\n  STR_DAYLIGHT_TYPE: \"AEG> {ALT}{0}\"\n  STR_RACE_TYPE: \"RASS> {ALT}{0}\"\n  STR_DAY: \"Päev\"\n  STR_NIGHT: \"Öö\"\n  STR_DAYS_WOUNDED: \"PÄEVI HAAVATUD> {ALT}{0}\"\n  STR_COMBAT: \"LAHING\"\n  STR_PERFORMANCE: \"SOORITUS\"\n  STR_NEUTRALIZATIONS_BY_RACE: \"NEUTRALISEERINGUD RASSI JÄRGI\"\n  STR_NEUTRALIZATIONS_BY_RANK: \"NEUTRALISEERINGUD AUASTME JÄRGI\"\n  STR_NEUTRALIZATIONS_BY_WEAPON: \"NEUTRALISEERINGUD RELVA JÄRGI\"\n  STR_MISSIONS_BY_LOCATION: \"MISSIOONID ASUKOHA JÄRGI\"\n  STR_MISSIONS_BY_TYPE: \"MISSIOONID TÜÜBI JÄRGI\"\n  STR_MISSIONS_BY_UFO: \"MISSIOONID UFODE JÄRGI\"\n  STR_SCORE_VALUE: \"SKOOR> {ALT}{0}\"\n  STR_WINS: \"VÕITE> {ALT}{0}\"\n  STR_STUNS: \"UIMASTUSI> {ALT}{0}\"\n  STR_PANICKS: \"PAANIKAT> {ALT}{0}\"\n  STR_MINDCONTROLS: \"KONTROLLE> {ALT}{0}\"\n  STR_AWARDS: \"AUTASUD\"\n  STR_COMMENDATIONS_UC: \"KIITUSED\"\n  STR_COMMENDATIONS: \"Kiitused\"\n  STR_MEDALS: \"MEDALID\"\n  STR_LOST_IN_SERVICE: \"TEENISTUSES HUKKUNUD\"\n  STR_MEDAL_NAME: \"Medali nimi\"\n  STR_MEDAL_AWARD_LEVEL: \"Autasu tase\"\n  STR_MEDAL_DECOR_LEVEL: \"Aumärgi tase\"\n  STR_AWARD_0: \"Esimene autasu\"\n  STR_AWARD_1: \"Teine autasu\"\n  STR_AWARD_2: \"Kolmas autasu\"\n  STR_AWARD_3: \"Neljas autasu\"\n  STR_AWARD_4: \"Viies autasu\"\n  STR_AWARD_5: \"Kuues autasu\"\n  STR_AWARD_6: \"Seitsmes autasu\"\n  STR_AWARD_7: \"Kaheksas autasu\"\n  STR_AWARD_8: \"Üheksas autasu\"\n  STR_AWARD_9: \"Kümnes autasu\"\n  STR_AWARD_DECOR_0: \"Mitte midagi\"\n  STR_AWARD_DECOR_1: \"Esimene pronksnõel\"\n  STR_AWARD_DECOR_2: \"Teine pronksnõel\"\n  STR_AWARD_DECOR_3: \"Kolmas pronksnõel\"\n  STR_AWARD_DECOR_4: \"Esimene hõbenõel\"\n  STR_AWARD_DECOR_5: \"Teine hõbenõel\"\n  STR_AWARD_DECOR_6: \"Kolmas hõbenõel\"\n  STR_AWARD_DECOR_7: \"Esimene kuldnõel\"\n  STR_AWARD_DECOR_8: \"Teine kuldnõel\"\n  STR_AWARD_DECOR_9: \"Kolmas kuldnõel\"\n  STR_KILLED_IN_ACTION_MALE: \"Lahingus langenud\"\n  STR_KILLED_IN_ACTION_FEMALE: \"Lahingus langenud\"\n  STR_MISSING_IN_ACTION_MALE: \"Lahingus kadunud\"\n  STR_MISSING_IN_ACTION_FEMALE: \"Lahingus kadunud\"\n  STR_AVERAGE_MONTHLY_RATING: \"Keskmine kuu reiting\"\n  STR_TOTAL_INCOME: \"Kogu sissetulek\"\n  STR_TOTAL_EXPENDITURE: \"Kogu kulud\"\n  STR_MISSIONS_WON: \"Missioon sooritatud\"\n  STR_MISSIONS_LOST: \"Missioon ebaõnnestus\"\n  STR_NIGHT_MISSIONS: \"Öömissioonid\"\n  STR_BEST_RATING: \"Parim missiooni reiting\"\n  STR_WORST_RATING: \"Halvim missiooni reiting\"\n  STR_ALIEN_KILLS: \"Tulnukaid tapetud\"\n  STR_ALIEN_CAPTURES: \"Tulnukaid vangistatud\"\n  STR_FRIENDLY_KILLS: \"Omade tule intsitendid\"\n  STR_AVERAGE_ACCURACY: \"Keskmine täpsus\"\n  STR_WEAPON_MOST_KILLS: \"Efektiivseim relv\"\n  STR_ALIEN_MOST_KILLS: \"Surmavaim tulnukas\"\n  STR_LONGEST_SERVICE: \"Teenistuses olnud kuid\"\n  STR_TOTAL_DAYS_WOUNDED: \"Haigepäevi\"\n  STR_COUNTRIES_LOST: \"Maid üle võetud\"\n  STR_TOTAL_TERROR_SITES: \"Terrorirünnakuid\"\n  STR_TOTAL_BASES: \"Baase ehitatud\"\n  STR_TOTAL_CRAFT: \"Sõidukeid\"\n  STR_TOTAL_SCIENTISTS: \"Teadlasi palgatud\"\n  STR_TOTAL_ENGINEERS: \"Insenere palgatud\"\n  STR_TOTAL_RESEARCH: \"Teadustöid lõpetatud\"\n  STR_DIARY_ACCURACY: \"TÄPSUS> {ALT}{0}%\"\n  STR_STATISTICS: \"Statistika\"\n  STR_STATS: \"Stats\"\n  STR_TIME_UNITS_ABBREVIATION: \"TU\"\n  STR_STAMINA_ABBREVIATION: \"STA\"\n  STR_HEALTH_ABBREVIATION: \"HP\"\n  STR_BRAVERY_ABBREVIATION: \"BRV\"\n  STR_REACTIONS_ABBREVIATION: \"REA\"\n  STR_FIRING_ACCURACY_ABBREVIATION: \"ACC\"\n  STR_THROWING_ACCURACY_ABBREVIATION: \"THR\"\n  STR_STRENGTH_ABBREVIATION: \"STR\"\n  STR_MELEE_ACCURACY_ABBREVIATION: \"MEL\"\n"
  },
  {
    "path": "bin/common/Language/fi.yml",
    "content": "fi:\n  STR_OPENXCOM: \"OpenXcom\"\n  STR_NEW_GAME: \"Uusi peli\"\n  STR_LOAD_SAVED_GAME: \"Lataa peli\"\n  STR_SELECT_DIFFICULTY_LEVEL: \"Valitse vaikeustaso\"\n  STR_1_BEGINNER: \"1> Aloittelija\"\n  STR_2_EXPERIENCED: \"2> Kokenut\"\n  STR_3_VETERAN: \"3> Konkari\"\n  STR_4_GENIUS: \"4> Nero\"\n  STR_5_SUPERHUMAN: \"5> Yli-ihminen\"\n  STR_TIME: \"Aika\"\n  STR_DATE: \"Pvm\"\n  STR_SELECT_GAME_TO_LOAD: \"Valitse ladattava pelitilanne\"\n  STR_SELECT_SAVE_POSITION: \"Valitse tallennustiedosto\"\n  STR_GAME_OPTIONS: \"ASETUKSET\"\n  STR_LOAD_GAME: \"LATAA PELI\"\n  STR_SAVE_GAME: \"TALLENNA PELI\"\n  STR_ABANDON_GAME: \"POISTU PELISTÄ\"\n  STR_ABANDON_GAME_QUESTION: \"POISTUTAANKO PELISTÄ?\"\n  STR_QUIT: \"Lopeta\"\n  STR_SAVING_GAME: \"Tallennetaan peliä\"\n  STR_LOADING_GAME: \"Ladataan pelitilannetta\"\n  STR_NO_SAVED_GAME_PRESENT: \"Ei talletettuja pelitilanteita\"\n  STR_LOAD_UNSUCCESSFUL: \"Pelitilanteen lataus epäonnistui\"\n  STR_SAVE_UNSUCCESSFUL: \"Tallennus epäonnistui\"\n  STR_LOAD_SUCCESSFUL: \"Lataus onnistui\"\n  STR_SAVE_SUCCESSFUL: \"Tallennus onnistui\"\n  STR_DELETE: \"POISTA\"\n  STR_DELETE_UNSUCCESSFUL: \"Poistaminen epäonnistui\"\n  STR_IS_IT_OK_TO_DELETE_THE_SAVED_GAME: \"Oletko varma että haluat poistaa tallennustiedoston?\"\n  STR_ORIGINAL_XCOM: \"Alkuperäinen\"\n  STR_LOADING: \"Ladataan...\"\n  STR_DETAILS: \"YKSITYISKOHDAT> {ALT}{0}\"\n  STR_NEW_BATTLE: \"Uusi taistelu\"\n  STR_OPTIONS: \"Asetukset\"\n  STR_RIGHT_CLICK_TO_DELETE: \"Oikea napsautus poistaa tallennuksen.\"\n  STR_RESTORE_DEFAULTS: \"Palauta oletukset\"\n  STR_CONTROLS: \"OHJAUS\"\n  STR_GENERAL: \"Yleiset\"\n  STR_GEOSCAPE: \"Geomaisema\"\n  STR_BATTLESCAPE: \"Taistelukenttä\"\n  STR_SCREENSHOT: \"Kuvakaappaus\"\n  STR_FPS_COUNTER: \"Kuvataajuuslaskuri (FPS)\"\n  STR_ROTATE_LEFT: \"Käännä vasemmalle\"\n  STR_ROTATE_RIGHT: \"Käännä oikealle\"\n  STR_ROTATE_UP: \"Käännä ylös\"\n  STR_ROTATE_DOWN: \"Käännä alas\"\n  STR_ZOOM_IN: \"Lähennä\"\n  STR_ZOOM_OUT: \"Loitonna\"\n  STR_TOGGLE_COUNTRY_DETAIL: \"Näytä maiden rajat ja kaupungit\"\n  STR_TOGGLE_RADAR_RANGES: \"Näytä tutkien kantama\"\n  STR_SCROLL_LEFT: \"Vieritä vasemmalle\"\n  STR_SCROLL_RIGHT: \"Vieritä oikealle\"\n  STR_SCROLL_UP: \"Vieritä ylös\"\n  STR_SCROLL_DOWN: \"Vieritä alas\"\n  STR_UNIT_LEVEL_ABOVE: \"Siirrä yksikköä ylemmäksi\"\n  STR_UNIT_LEVEL_BELOW: \"Siirrä yksikköä alemmaksi\"\n  STR_VIEW_LEVEL_ABOVE: \"Näytä ylempi taso\"\n  STR_VIEW_LEVEL_BELOW: \"Näytä alempi taso\"\n  STR_CENTER_SELECTED_UNIT: \"Keskitä valittuun yksikköön\"\n  STR_PREVIOUS_UNIT: \"Valitse edellinen yksikkö\"\n  STR_NEXT_UNIT: \"Valitse seuraava yksikkö\"\n  STR_DESELECT_UNIT: \"Valitse seuraava, älä uudelleenvalitse\"\n  STR_USE_LEFT_HAND: \"Käytä vasemman käden esinettä\"\n  STR_USE_RIGHT_HAND: \"Käytä oikean käden esinettä\"\n  STR_INVENTORY: \"Varustenäkymä\"\n  STR_MINIMAP: \"Minikartta\"\n  STR_MULTI_LEVEL_VIEW: \"Näytä kaikki tasot\"\n  STR_END_TURN: \"Lopeta vuoro\"\n  STR_ABORT_MISSION: \"Keskeytä tehtävä\"\n  STR_UNIT_STATS: \"Yksikön ominaisuudet\"\n  STR_KNEEL: \"Polvistu\"\n  STR_RELOAD: \"Lataa uudelleen\"\n  STR_TOGGLE_PERSONAL_LIGHTING: \"Näytä henkilökohtainen valaistus\"\n  STR_DONT_RESERVE_TIME_UNITS: \"Älä varaa AY:itä\"\n  STR_RESERVE_TIME_UNITS_FOR_SNAP_SHOT: \"Varaa AY:t kertatulta varten\"\n  STR_RESERVE_TIME_UNITS_FOR_AIMED_SHOT: \"Varaa AY:t tähdättyä laukausta varten\"\n  STR_RESERVE_TIME_UNITS_FOR_AUTO_SHOT: \"Varaa AY:t sarjatulta varten\"\n  STR_CENTER_ON_ENEMY_1: \"Keskitä viholliseen no 1\"\n  STR_CENTER_ON_ENEMY_2: \"Keskitä viholliseen no 2\"\n  STR_CENTER_ON_ENEMY_3: \"Keskitä viholliseen no 3\"\n  STR_CENTER_ON_ENEMY_4: \"Keskitä viholliseen no 4\"\n  STR_CENTER_ON_ENEMY_5: \"Keskitä viholliseen no 5\"\n  STR_CENTER_ON_ENEMY_6: \"Keskitä viholliseen no 6\"\n  STR_CENTER_ON_ENEMY_7: \"Keskitä viholliseen no 7\"\n  STR_CENTER_ON_ENEMY_8: \"Keskitä viholliseen no 8\"\n  STR_CENTER_ON_ENEMY_9: \"Keskitä viholliseen no 9\"\n  STR_CENTER_ON_ENEMY_10: \"Keskitä viholliseen no 10\"\n  STR_CREATE_INVENTORY_TEMPLATE: \"Luo varustusmalli\"\n  STR_APPLY_INVENTORY_TEMPLATE: \"Käytä varustusmallia\"\n  STR_CLEAR_INVENTORY: \"Riisu varusteet\"\n  STR_AUTO_EQUIP: \"Varusta automaattisesti\"\n  STR_QUICK_SAVE: \"Pikatallennus\"\n  STR_QUICK_LOAD: \"Pikalataus\"\n  STR_ADVANCED: \"LISÄASETUKSET\"\n  STR_AGGRESSIVERETALIATION: \"Agressiivinen vastahyökkäys\"\n  STR_AGGRESSIVERETALIATION_DESC: \"Ufot yrittävät aina löytää tukikohtiasi, riippumatta siitä, minkälainen tehtävä niillä on menossa.\"\n  STR_STORAGELIMITSENFORCED: \"Varastorajat talteen otetulle saaliille\"\n  STR_STORAGELIMITSENFORCED_DESC: \"Valvoo muukalaisten vankilaitosten ja varastojen tilarajoja eläville muukalaisille sekä tehtäviltä talteen otetuille esineille.\"\n  STR_CANSELLLIVEALIENS: \"Elävien muukalaisten myyminen\"\n  STR_CANSELLLIVEALIENS_DESC: \"Sallii elävien muukalaisten myynnin, suositellaan varastorajoja käytettäessä.\"\n  STR_ALLOWBUILDINGQUEUE: \"Salli keskeneräisten rakennusten liittäminen\"\n  STR_ALLOWBUILDINGQUEUE_DESC: \"Uusia laitoksia voidaan sijoittaa keskeneräisten viereen.\"\n  STR_BATTLEAUTOEND: \"Lopeta taistelu automaattisesti\"\n  STR_BATTLEAUTOEND_DESC: \"Taistelut päättyvät automaattisesti, kun viimeinen vihollinen neutralisoidaan.\"\n  STR_BATTLEINSTANTGRENADE: \"Välitön kranaatin toiminta\"\n  STR_BATTLEINSTANTGRENADE_DESC: \"Kranaatit joiden ajastin on asetettu 0:aan, räjähtävät välittömästi heiton jälkeen vuoron lopun sijaan.\"\n  STR_BATTLEUFOEXTENDERACCURACY: \"UFO Extender -tarkkuus\"\n  STR_BATTLEUFOEXTENDERACCURACY_DESC: \"Laukausten osumatarkkuus heikkenee määrätyn etäisyyden jälkeen laukaisutavan mukaan. Korjattu osumatarkkuus näytetään osoittimella.\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE: \"Ilmassa olevia aluksia voidaan siirtää\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE_DESC: \"Hävittäjä / kuljetusalus, joka on ilmassa, voidaan määrätä siirrettäväksi toiseen tukikohtaan.\"\n  STR_CRAFTLAUNCHALWAYS: \"Pakotettu aluksen tehtävä\"\n  STR_CRAFTLAUNCHALWAYS_DESC: \"Alukset voidaan laukaista silloinkin, kun ne eivät ole valmiita, huoltotarpeet ohittaen.\"\n  STR_CUSTOMINITIALBASE: \"Muokattu aloitustukikohta\"\n  STR_CUSTOMINITIALBASE_DESC: \"Uuden pelin alussa voit valita aloituslaitosten paikat tukikohdassa valmiin oletusasettelun sijaan.\"\n  STR_GLOBESEASONS: \"Todenmukainen karttapallon valaistus\"\n  STR_GLOBESEASONS_DESC: \"Käyttää todenmukaisempaa auringonvalon projisointia geomaisemassa maapallon akselin kaltevuuden mukaisesti.\"\n  STR_PLAYINTRO: \"Näytä intro\"\n  STR_PLAYINTRO_DESC: \"Näytä intro käynnistyksen alussa.\"\n  STR_SHOWMORESTATSININVENTORYVIEW: \"Yksikkötiedot varustenäkymässä\"\n  STR_SHOWMORESTATSININVENTORYVIEW_DESC: \"Näytä joitakin tärkeimpiä ominaisuuksia valitusta sotilaasta varustenäkymässä.\"\n  STR_SNEAKYAI: \"Salakavala tekoäly\"\n  STR_SNEAKYAI_DESC: \"Tekoäly pyrkii aina välttämään yksikköjensä paljastamista pelaajalle.\"\n  STR_STRAFE: \"Vaihtoehtoiset liikkumistavat\"\n  STR_STRAFE_DESC: \"Mahdollistaa sivuttaisastunnan, juoksun ja tykkitornien itsenäisen liikkeen, kun CTRL-näppäintä pidetään pohjassa.\"\n  STR_BATTLEEXPLOSIONHEIGHT: \"Räjähdyksen korkeus\"\n  STR_BATTLEEXPLOSIONHEIGHT_DESC: \"Tällä asetuksella asetetaan, kuinka korkealle räjähdys voi yltää.{NEWLINE}(Litteä: 0, Pyöreä: 3)\"\n  STR_AUTOSAVE: \"Automaattitallennus\"\n  STR_AUTOSAVE_DESC: \"Automaattisesti tallentaa pelin määritellyin välein. Ei koske Ironman-tilaa.\"\n  STR_AUTOSAVE_FREQUENCY: \"Automaattitallennuksen toistumistiheys\"\n  STR_AUTOSAVE_FREQUENCY_DESC: \"Säätää, kuinka monen vuoron välein peli automaattisesti tallentuu.\"\n  STR_ALLOWPSIONICCAPTURE: \"Salli psi-kaappaus\"\n  STR_ALLOWPSIONICCAPTURE_DESC: \"Jos kaikki jäljellä olevat viholliset joutuvat mielenhallinnan uhriksi, lasketaan tämä voitoksi, ja mielenhallinnan uhrit eläviksi kaappauksiksi.\"\n  STR_ANYTIMEPSITRAINING: \"Psioninen koulutus milloin tahansa\"\n  STR_ANYTIMEPSITRAINING_DESC: \"Sallii sotilaiden määräämisen psioniseen koulutukseen mihin tahansa aikaan kuukautta. Muista, että aloituskoulutus kestää 30-60 päivää.\"\n  STR_SKIPNEXTTURNSCREEN: \"Ohita \\\"Seuraava vuoro\\\" -ilmoitus\"\n  STR_SKIPNEXTTURNSCREEN_DESC: \"\\\"Seuraava vuoro\\\" -ilmoituksesta edetään automaattisesti pienen viiveen jälkeen taisteluissa.\"\n  STR_NOT_ENOUGH_SPACE: \"Tilaa ei ole riittävästi!\"\n  STR_WEAPONSELFDESTRUCTION: \"Muukalaisten aseiden itsetuhomekanismi\"\n  STR_WEAPONSELFDESTRUCTION_DESC: \"Muukalaisten kantamat aseet räjähtävät kantajansa kuollessa, kuten vuoden 2012 XCOM -pelissä.\"\n  STR_RETAINCORPSES: \"Säilytä kuulustellut muukalaiset\"\n  STR_RETAINCORPSES_DESC: \"Elävien muukalaisten tutkimusprojektien valmistuttua ruumis lisätään tukikohdan varastoihin, kuten vuoden 2012 XCOM-pelissä.\"\n  STR_SAVE_VOXEL_VIEW: \"Kuvakaappaus taistelijan näkymästä\"\n  STR_RESERVE_TIME_UNITS_FOR_KNEEL: \"Varaa AY:t polvistumista varten\"\n  STR_EXPEND_ALL_TIME_UNITS: \"Käytä kaikki jäljellä olevat aikayksiköt\"\n  STR_PSISTRENGTHEVAL: \"Psi-voiman arviointi\"\n  STR_PSISTRENGTHEVAL_DESC: \"Arvioi kaikkien sotilaiden psi-voiman, kun tarvittava tutkimusprojekti on valmis.\"\n  STR_DISABLEAUTOEQUIP: \"Älä varusta automaattisesti\"\n  STR_DISABLEAUTOEQUIP_DESC: \"Älä varusta uusia sotilaita automaattisesti ennen taistelua.\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT: \"Salli psi-voiman kehittäminen\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT_DESC: \"Sotilaiden psionista voimaa voidaan kehittää kokemuksen ja koulutuksen kautta.\"\n  STR_BATTLESMOOTHCAMERA: \"Sulava ammuskamera\"\n  STR_BATTLESMOOTHCAMERA_DESC: \"Taistelukentän kamera pysyy keskitettynä lennossa oleviin ammuksiin.\"\n  STR_BATTLECONFIRMFIREMODE: \"Hyökkäyksen vahvistustila\"\n  STR_BATTLECONFIRMFIREMODE_DESC: \"Hyökkäyskäskyn vahvistamiseksi on hyökättävää ruutua napsautettava toisen kerran.\"\n  STR_SELECT_BASE_1: \"Valitse tukikohta 1\"\n  STR_SELECT_BASE_2: \"Valitse tukikohta 2\"\n  STR_SELECT_BASE_3: \"Valitse tukikohta 3\"\n  STR_SELECT_BASE_4: \"Valitse tukikohta 4\"\n  STR_SELECT_BASE_5: \"Valitse tukikohta 5\"\n  STR_SELECT_BASE_6: \"Valitse tukikohta 6\"\n  STR_SELECT_BASE_7: \"Valitse tukikohta 7\"\n  STR_SELECT_BASE_8: \"Valitse tukikohta 8\"\n  STR_VIDEO: \"NÄYTTÖ\"\n  STR_AUDIO: \"ÄÄNI\"\n  STR_BATTLESCAPE_UC: \"TAISTELUKENTTÄ\"\n  STR_MODS_UC: \"MODIT\"\n  STR_MODS: \"Modit\"\n  STR_DISPLAY_RESOLUTION: \"Näytön tarkkuus\"\n  STR_DISPLAY_RESOLUTION_DESC: \"Vaihtaa näytön tarkkuuden, pelinäytön tarkkuus muutetaan vastaamaan valintaa. Nuolipainikkeet vaihtavat tuettujen tarkkuuksien välillä. Napsauta syöttääksesi tarkkuuden käsin.\"\n  STR_ORIGINAL: \"Alkuperäinen\"\n  STR_DISPLAY_MODE: \"Näytön tila\"\n  STR_WINDOWED: \"Ikkuna\"\n  STR_FULLSCREEN: \"Koko näyttö\"\n  STR_BORDERLESS: \"Reunaton\"\n  STR_DISPLAY_LANGUAGE: \"Näytä kieli\"\n  STR_DISPLAY_LANGUAGE_DESC: \"Vaihtaa pelissä käytettävän tekstin kielen.\"\n  STR_DISPLAY_FILTER: \"Näytön suodatin\"\n  STR_DISPLAY_FILTER_DESC: \"Vaihtaa peliruudulla käytettävää suodatinta.{NEWLINE}*edellyttää laitteiston OpenGL-kiihdytystä.\"\n  STR_DISPLAY_OPTIONS: \"Näyttöasetukset\"\n  STR_LETTERBOXED: \"Letterbox-palkit\"\n  STR_LETTERBOXED_DESC: \"Luo kuvan ympärille mustia palkkeja alkuperäisen kuvasuhteen säilyttämiseksi.\"\n  STR_RESIZABLE: \"Säädettävissä\"\n  STR_LOCK_MOUSE: \"Lukitse hiiri\"\n  STR_LOCK_MOUSE_DESC: \"Estää hiiren osoitinta poistumasta ikkunasta. Kytke päälle/pois milloin vain näppäinyhdistelmällä Ctrl+G.\"\n  STR_FIXED_WINDOW_POSITION: \"Kiinteä ikkunan sijainti\"\n  STR_FIXED_WINDOW_POSITION_DESC: \"Aseta ikkunalle kiinteä sijainti\"\n  STR_DISPLAY_SET_WINDOW_POSITION: \"Aseta uusi ikkunan kantasijainti\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_X: \"Vasen reuna uusi X:\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_Y: \"Yläreuna uusi Y:\"\n  STR_MUSIC_VOLUME: \"Musiikin voimakkuus\"\n  STR_MUSIC_VOLUME_DESC: \"Säätää taustamusiikin äänenvoimakkuutta.\"\n  STR_SFX_VOLUME: \"Ääniefektien voimakkuus\"\n  STR_SFX_VOLUME_DESC: \"Säätää äänitehosteiden äänenvoimakkuutta.\"\n  STR_UI_VOLUME: \"UI-äänenvoimakkuus\"\n  STR_UI_VOLUME_DESC: \"Säätää käyttöliittymän (UI) äänenvoimakkuutta.\"\n  STR_SCROLL_SPEED: \"Vieritysnopeus\"\n  STR_SCROLL_SPEED_GEO_DESC: \"Säätää karttapallon vieritysnopeutta.\"\n  STR_SCROLL_SPEED_BATTLE_DESC: \"Säätää näkymän vieritysnopeutta.\"\n  STR_DOGFIGHT_SPEED: \"Ilmataistelun nopeus\"\n  STR_DOGFIGHT_SPEED_DESC: \"Säätää lentotaisteluiden nopeutta alusten ja ufojen välillä. Pienemmät nopeudet voivat parantaa suorituskykyä hitaammissa koneissa.\"\n  STR_CLOCK_SPEED: \"Kellon nopeus\"\n  STR_CLOCK_SPEED_DESC: \"Säätää geomaiseman kellon nopeutta. Pienemmät nopeudet voivat parantaa suorituskykyä hitaammissa koneissa.\"\n  STR_GLOBE_DETAILS: \"Kartan yksityiskohdat\"\n  STR_GLOBE_COUNTRIES: \"Maat\"\n  STR_GLOBE_COUNTRIES_DESC: \"Näyttää rahoittavat maat karttapallolla.\"\n  STR_GLOBE_RADARS: \"Tutkat\"\n  STR_GLOBE_RADARS_DESC: \"Näyttää tukikohtien tutkien kantamat karttapallolla.\"\n  STR_GLOBE_FLIGHT_PATHS: \"Lentoradat\"\n  STR_GLOBE_FLIGHT_PATHS_DESC: \"Näyttää alusten lentoradat karttapallolla.\"\n  STR_CONTROLS_DESC: \"Napsauta vasemmalla hiirenpainikkeella näppäinoikotietä ja paina jotain näppäintä muuttaaksesi oikotietä.{NEWLINE}Napsauta oikealla painikkeella oikotietä poistaaksesi oikotien.\"\n  STR_BASE_GAME: \"Peruspeli\"\n  STR_MODS_TOOLTIP: \"Versio {0}, tekijä: {1}.{NEWLINE}{2}\"\n  STR_EDGE_SCROLL: \"Reunavieritys\"\n  STR_EDGE_SCROLL_DESC: \"Manuaalinen: Vieritä näkymää, kun vasenta hiirenpainiketta pidetään pohjassa ruudun reunalla.{NEWLINE}Automaattinen: Vieritä näkymää, kun osoitin on ruudun reunalla.\"\n  STR_TRIGGER_SCROLL: \"Manuaalinen\"\n  STR_AUTO_SCROLL: \"Automaattinen\"\n  STR_DRAG_SCROLL: \"Vetovieritys\"\n  STR_DRAG_SCROLL_DESC: \"Vierittää näkymää, kun määritettyä hiiren painiketta pidetään pohjassa ja vedetään.\"\n  STR_LEFT_MOUSE_BUTTON: \"Vasen näppäin\"\n  STR_MIDDLE_MOUSE_BUTTON: \"Keskinäppäin\"\n  STR_RIGHT_MOUSE_BUTTON: \"Oikea näppäin\"\n  STR_FIRE_SPEED: \"Ammusnopeus\"\n  STR_FIRE_SPEED_DESC: \"Säätää aseiden ammusten nopeutta.\"\n  STR_PLAYER_MOVEMENT_SPEED: \"Pelaajan animointinopeus\"\n  STR_PLAYER_MOVEMENT_SPEED_DESC: \"Säätää pelaajan ohjaamien yksiköiden animointinopeutta.\"\n  STR_COMPUTER_MOVEMENT_SPEED: \"Tekoälyn animointinopeus\"\n  STR_COMPUTER_MOVEMENT_SPEED_DESC: \"Säätää tietokoneen ohjaamien yksiköiden animointinopeutta.\"\n  STR_PATH_PREVIEW: \"Polun esikatselu\"\n  STR_PATH_ARROWS: \"Nuolet\"\n  STR_PATH_ARROWS_DESC: \"Napsautus näyttää polun, jota yksikkösi kulkee määränpäähänsä. Väri ilmaisee käytettävissä olevat toiminnot: vihreä - voi liikkua ja ampua; keltainen - voi liikkua; punainen - ei voi liikkua.\"\n  STR_PATH_TIME_UNIT_COST: \"Aikayksiköt\"\n  STR_PATH_TIME_UNIT_COST_DESC: \"Napsauttamalla näet, kuinka monta AY:ä yksiköllesi jää sen saavutettua määränpäänsä. \"\n  STR_USER_INTERFACE_OPTIONS: \"Käyttöliittymäasetukset\"\n  STR_TOOLTIPS: \"Vihjelaatikot\"\n  STR_TOOLTIPS_DESC: \"Näyttää vihjelaatikoita taistelukentän painikkeille.\"\n  STR_DEATH_NOTIFICATIONS: \"Kuolemailmoitukset\"\n  STR_DEATH_NOTIFICATIONS_DESC: \"Näytä sotilaan kuollessa ilmoitus, kuka kuoli.\"\n  STR_SHOW_FUNDS: \"Näytä varat\"\n  STR_SHOW_FUNDS_DESC: \"Näyttää nykyiset varasi geomaiseman kellon vieressä.\"\n  STR_MISSION_GENERATOR: \"TEHTÄVÄNLUOJA\"\n  STR_MAP_OPTIONS: \"KARTTA-ASETUKSET\"\n  STR_ALIEN_OPTIONS: \"MUUKALAISTEN ASETUKSET\"\n  STR_MAP_TERRAIN: \"Maasto\"\n  STR_MAP_DARKNESS: \"Pimeys\"\n  STR_MAP_DEPTH: \"Syvyys\"\n  STR_DIFFICULTY: \"Vaikeustaso\"\n  STR_ALIEN_RACE: \"Laji\"\n  STR_ALIEN_TECH_LEVEL: \"Teknologiataso\"\n  STR_RANDOMIZE: \"Satunnaista\"\n  STR_OXCE_REQUIRED_QUESTION: \"Toimiakseen oikein tämä modi edellyttää OpenXcomin versiota {0}. Otetaanko modi käyttöön?\"\n  STR_RESTORE_DEFAULTS_QUESTION: \"Oletko varma, että haluat palauttaa oletusasetukset?\"\n  STR_DISPLAY_OPTIONS_CONFIRM: \"Haluatko säilyttää nykyiset näyttöasetukset?\"\n  STR_DISPLAY_OPTIONS_REVERT: \"Palautukseen 0:{0}\"\n  STR_MISSING_CONTENT_PROMPT: \"VAROITUS:{SMALLLINE}Tämä tallennus pohjaa asentamattomiin modeihin. Puuttuva sisältö poistetaan, eikä peli välttämättä lataudu.{NEWLINE}Jatketaanko?\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT: \"Tallenna esiajastetut kranaatit\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT_DESC: \"Tallentaa kranaattien ajastustilan taistelua edeltävässä varustenäkymässä.\"\n  STR_NEWSEEDONLOAD: \"Tallennusten sävytys\"\n  STR_NEWSEEDONLOAD_DESC: \"Pelin lataaminen asettaa satunnaislukugeneraattorin siemenluvun uudelleen, joten saman toiminnon tekeminen voi tuottaa eri lopputuloksia. Ei koske Ironman-tilaa.\"\n  STR_CHANGEVALUEBYMOUSEWHEEL: \"Säädä arvoja hiiren rullapainikkeella\"\n  STR_CHANGEVALUEBYMOUSEWHEEL_DESC: \"Sallii hiiren rullapainikkeen käytön vähentämään/kasvattamaan arvoja tämän määrän verran.\"\n  STR_BATTLEHAIRBLEACH: \"Parannellut sotilaiden spritet\"\n  STR_BATTLEHAIRBLEACH_DESC: \"Muuttaa sotilaiden taistelukentän sprite-grafiikat vastaamaan niiden ulkonäköä varustenäkymässä.\"\n  STR_DRAGSCROLLINVERT: \"Käännä vetovierityssuunta\"\n  STR_DRAGSCROLLINVERT_DESC: \"Ominaisuuden ollessa päälle kytkettynä vieritys tapahtuu hiirtä vedettäessä hiireen nähden vastakkaiseen suuntaan.\"\n  STR_BATTLESCAPE_SCALE: \"Taistelukentän skaalaus\"\n  STR_BATTLESCAPE_SCALE_DESC: \"Taistelukentän näyttöruudun skaalaus, joka perustuu joko kiinteään resoluutioon (sovitetaan venyttämällä) tai kiinteään syväykseen (täytetään laajentamalla).\"\n  STR_GEOSCAPE_SCALE: \"Geomaiseman skaalaus\"\n  STR_GEOSCAPESCALE_SCALE_DESC: \"Geomaiseman näyttöruudun skaalaus, joka perustuu joko kiinteään resoluutioon (sovitetaan venyttämällä) tai kiinteään syväykseen (täytetään laajentamalla).\"\n  STR_1_5X: \"1,5x alkuperäisestä\"\n  STR_2X: \"2x alkuperäisestä\"\n  STR_THIRD_DISPLAY: \"1/3 näytöstä\"\n  STR_HALF_DISPLAY: \"1/2 näytöstä\"\n  STR_FULL_DISPLAY: \"Täysi näyttö\"\n  STR_FPS_LIMIT: \"Kuvataajuusrajoitus\"\n  STR_FPS_LIMIT_DESC: \"Rajoittaa ruudunpäivitysten määrää sekunnissa, 0 poistaa rajoituksen. Jos OpenGL-hahmonnus on päällä, peli käyttää pystytahdistusta (Vsync).\"\n  STR_FPS_INACTIVE_LIMIT: \"Tausta-ajon kuvataajuusrajoitus\"\n  STR_FPS_INACTIVE_LIMIT_DESC: \"Rajoittaa ruudunpäivitysten määrää sekunnissa, jos OpenXcomia ajetaan taustalla.\"\n  STR_NOALIENPANICMESSAGES: \"Vaienna muukalaisten paniikkiviestit\"\n  STR_NOALIENPANICMESSAGES_DESC: \"Älä näytä viestejä muukalaisten panikoinnista, ellei pelaaja näe niitä.\"\n  STR_ALIENBLEEDING: \"Muukalaiset vuotavat verta\"\n  STR_ALIENBLEEDING_DESC: \"Mahdollistaa vakavien haavojen tuottamisen useimmille muukalaisille.\"\n  STR_FIELDPROMOTIONS: \"Kenttäylennykset\"\n  STR_FIELDPROMOTIONS_DESC: \"Vain taistelukentällä läsnäolleet sotilaat ovat oikeutettuja ylennykseen.\"\n  STR_MEETINGPOINT: \"Ennusta ufon liikerata\"\n  STR_MEETINGPOINT_DESC: \"Alukset lentävät ufon kohtaamispisteeseen sen silloisen liikeradan perusteella.\"\n  STR_IRONMAN: \"IRONMAN\"\n  STR_IRONMAN_DESC: \"Ei manuaalista tallennusta\"\n  STR_SAVE_AND_ABANDON_GAME: \"TALLENNA JA POISTU PELISTÄ\"\n  STR_MOD_UNSUCCESSFUL: \"Modin lataus epäonnistui\"\n  STR_NEW_SAVED_GAME_SLOT: \"<UUSI TALLENNUS>\"\n  STR_AUTO_SAVE_GEOSCAPE_SLOT: \"<GEOMAISEMAN AUTOMAATTITALLENNUS>\"\n  STR_AUTO_SAVE_BATTLESCAPE_SLOT: \"<TAISTELUKENTÄN AUTOMAATTITALLENNUS>\"\n  STR_QUICK_SAVE_SLOT: \"<PIKATALLENNUS>\"\n  STR_DISPLAY_MODE_DESC: \"Muuttaa tapaa, miten peli näytetään ruudulla.\"\n  STR_PREFERRED_MUSIC_FORMAT: \"Musiikkimuoto\"\n  STR_PREFERRED_MUSIC_FORMAT_DESC: \"Ottaa käyttöön halutun musiikin toistomuodon, kun useita tiedostomuotoja on käytettävissä.{NEWLINE}HUOMAA: MIDI-toisto saattaa olla viallinen Windowsissa.\"\n  STR_PREFERRED_SFX_FORMAT: \"Äänitehostemuoto\"\n  STR_PREFERRED_SFX_FORMAT_DESC: \"Ottaa halutun äänitehostemuodon käyttöön, kun useita muotoja on käytettävissä.\"\n  STR_PREFERRED_VIDEO_FORMAT: \"Näyttömuoto\"\n  STR_PREFERRED_VIDEO_FORMAT_DESC: \"Ottaa halutun näyttömuodon käyttöön, kun useita muotoja on käytettävissä.\"\n  STR_PREFERRED_VIDEO_ANIMATION: \"Animaatio\"\n  STR_PREFERRED_VIDEO_SLIDESHOW: \"Diaesitys\"\n  STR_PREFERRED_FORMAT_AUTO: \"Automaattinen\"\n  STR_CURRENT_FORMAT: \"Nykyinen: {0}\"\n  STR_SOUND_OPTIONS: \"Ääniasetukset\"\n  STR_BACKGROUND_MUTE: \"Taustamykistys\"\n  STR_BACKGROUND_MUTE_DESC: \"Mykistää kaiken äänen, kun peli-ikkuna ei ole aktiivinen.\"\n  STR_FORCE_FIRE: \"Ohita tulilinjasäännöt\"\n  STR_FORCE_FIRE_DESC: \"Mahdollistaa sotilaittesi pakottamisen ampumaan tulilinjasäännöistä huolimatta, kun CTRL-näppäintä pidetään pohjassa.\"\n  STR_NO_AUDIO_HARDWARE_DETECTED: \"Äänilaitetta ei havaittu\"\n  STR_MOUSEWHEEL_SPEED: \"Hiiren rullan vieritysnopeus\"\n  STR_MOUSEWHEEL_SPEED_DESC: \"Säätää vieritettyjen rivien määrää listoissa hiiren rullaa vieritettäessä.\"\n  STR_DISABLED: \"Pois käytöstä\"\n  STR_MAXIMIZE_INFO_SCREENS: \"Suurenna tietonäytöt\"\n  STR_MAXIMIZE_INFO_SCREENS_DESC: \"Varustenäkymä ja erinäiset muut näytöt esitetään koko ruudulla skaalausasetuksista riippumatta.\"\n  STR_DIARY: \"PÄIVÄKIRJA\"\n  STR_KILLED: \"TAPETTU\"\n  STR_STUNNED: \"TAINNUTETTU\"\n  STR_PANICKED: \"PANIKOINUT\"\n  STR_MINDCONTROLLED: \"HALLITTU\"\n  STR_REGION_UNKNOWN: \"Määrittelemätön\"\n  STR_WEAPON_UNKNOWN: \"Improvisaatio\"\n  STR_UNKNOWN: \"Tuntematon\"\n  STR_VICTORY: \"Voitto\"\n  STR_DEFEAT: \"Häviö\"\n  STR_NO_RECORD: \"Ei merkintää\"\n  STR_HUMAN: \"Ihmisten\"\n  STR_FRIENDLY: \"Ystävällinen\"\n  STR_HOSTILE: \"Vihamielinen\"\n  STR_NEUTRAL: \"Neutraali\"\n  STR_RATING_UC: \"ARVIO\"\n  STR_LOCATION: \"SIJAINTI> {ALT}{0}\"\n  STR_DAYLIGHT_TYPE: \"AIKA> {ALT}{0}\"\n  STR_RACE_TYPE: \"LAJI> {ALT}{0}\"\n  STR_DAY: \"Päivä\"\n  STR_NIGHT: \"Yö\"\n  STR_DAYS_WOUNDED: \"SAIRASPÄIVIÄ> {ALT}{0}\"\n  STR_COMBAT: \"TAISTELU\"\n  STR_PERFORMANCE: \"SUORITUS\"\n  STR_NEUTRALIZATIONS_BY_RACE: \"NEUTRALISAATIOT LAJEITTAIN\"\n  STR_NEUTRALIZATIONS_BY_RANK: \"NEUTRALISAATIOT ARVOITTAIN\"\n  STR_NEUTRALIZATIONS_BY_WEAPON: \"NEUTRALISAATIOT ASEITTAIN\"\n  STR_MISSIONS_BY_LOCATION: \"TEHTÄVÄT SIJAINNEITTAIN\"\n  STR_MISSIONS_BY_TYPE: \"TEHTÄVÄT TYYPEITTÄIN\"\n  STR_MISSIONS_BY_UFO: \"TEHTÄVÄT UFOITTAIN\"\n  STR_SCORE_VALUE: \"PISTEET> {ALT}{0}\"\n  STR_WINS: \"VOITOT> {ALT}{0}\"\n  STR_STUNS: \"LAMAUTUKSET> {ALT}{0}\"\n  STR_PANICKS: \"PANIIKKIKOHTAUKSET> {ALT}{0}\"\n  STR_MINDCONTROLS: \"HALLINNAT> {ALT}{0}\"\n  STR_AWARDS: \"TUNNUSTUKSET\"\n  STR_COMMENDATIONS_UC: \"KUNNIAMAININNAT\"\n  STR_COMMENDATIONS: \"Kunniamaininnat\"\n  STR_MEDALS: \"MITALIT\"\n  STR_LOST_IN_SERVICE: \"MENETETTY PALVELUKSESSA\"\n  STR_MEDAL_NAME: \"Mitalin nimi\"\n  STR_MEDAL_AWARD_LEVEL: \"Tunnustuksen taso\"\n  STR_MEDAL_DECOR_LEVEL: \"Kunniamerkin taso\"\n  STR_AWARD_0: \"Ensimmäinen tunnustus\"\n  STR_AWARD_1: \"Toinen tunnustus\"\n  STR_AWARD_2: \"Kolmas tunnustus\"\n  STR_AWARD_3: \"Neljäs tunnustus\"\n  STR_AWARD_4: \"Viides tunnustus\"\n  STR_AWARD_5: \"Kuudes tunnustus\"\n  STR_AWARD_6: \"Seitsemäs tunnustus\"\n  STR_AWARD_7: \"Kahdeksas tunnustus\"\n  STR_AWARD_8: \"Yhdeksäs tunnustus\"\n  STR_AWARD_9: \"Kymmenes tunnustus\"\n  STR_AWARD_DECOR_0: \"Ei mitään\"\n  STR_AWARD_DECOR_1: \"Ensimmäinen pronssimerkki\"\n  STR_AWARD_DECOR_2: \"Toinen pronssimerkki\"\n  STR_AWARD_DECOR_3: \"Kolmas pronssimerkki\"\n  STR_AWARD_DECOR_4: \"Ensimmäinen hopeamerkki\"\n  STR_AWARD_DECOR_5: \"Toinen hopeamerkki\"\n  STR_AWARD_DECOR_6: \"Kolmas hopeamerkki\"\n  STR_AWARD_DECOR_7: \"Ensimmäinen kultamerkki\"\n  STR_AWARD_DECOR_8: \"Toinen kultamerkki\"\n  STR_AWARD_DECOR_9: \"Kolmas kultamerkki\"\n  STR_KILLED_IN_ACTION_MALE: \"KAATUNUT TAISTELUSSA\"\n  STR_KILLED_IN_ACTION_FEMALE: \"KAATUNUT TAISTELUSSA\"\n  STR_MISSING_IN_ACTION_MALE: \"KADONNUT TAISTELUSSA\"\n  STR_MISSING_IN_ACTION_FEMALE: \"KADONNUT TAISTELUSSA\"\n  STR_AVERAGE_MONTHLY_RATING: \"Keskimääräinen kuukausiarvio\"\n  STR_TOTAL_INCOME: \"Tulot yhteensä\"\n  STR_TOTAL_EXPENDITURE: \"Menot yhteensä\"\n  STR_MISSIONS_WON: \"Tehtäviä suoritettu onnistuneesti\"\n  STR_MISSIONS_LOST: \"Tehtäviä epäonnistunut\"\n  STR_NIGHT_MISSIONS: \"Yötehtäviä\"\n  STR_BEST_RATING: \"Paras tehtäväarvio\"\n  STR_WORST_RATING: \"Huonoin tehtäväarvio\"\n  STR_ALIEN_KILLS: \"Muukalaisia tapettu\"\n  STR_ALIEN_CAPTURES: \"Muukalaisia kaapattu\"\n  STR_FRIENDLY_KILLS: \"Omien joukkojen tapot\"\n  STR_AVERAGE_ACCURACY: \"Keskimääräinen tarkkuus\"\n  STR_WEAPON_MOST_KILLS: \"Tehokkain ase\"\n  STR_ALIEN_MOST_KILLS: \"Tappavin muukalainen\"\n  STR_LONGEST_SERVICE: \"Pisin palvelusaika kuukausina\"\n  STR_TOTAL_DAYS_WOUNDED: \"Toipilaspäiviä yhteensä\"\n  STR_COUNTRIES_LOST: \"Maita, joihin soluttauduttu\"\n  STR_TOTAL_TERROR_SITES: \"Terrori-iskuja\"\n  STR_TOTAL_BASES: \"Tukikohtia rakennettu\"\n  STR_TOTAL_CRAFT: \"Aluksia yhteensä\"\n  STR_TOTAL_SCIENTISTS: \"Tiedemiehiä palkattu\"\n  STR_TOTAL_ENGINEERS: \"Teknikkoja palkattu\"\n  STR_TOTAL_RESEARCH: \"Valmiita tutkimusprojekteja\"\n  STR_DIARY_ACCURACY: \"TARKKUUS> {ALT}{0}%\"\n  STR_STATISTICS: \"Tilastot\"\n  STR_STATS: \"JOUKOT\"\n  STR_TIME_UNITS_ABBREVIATION: \"AY\"\n  STR_STAMINA_ABBREVIATION: \"KES\"\n  STR_HEALTH_ABBREVIATION: \"TER\"\n  STR_BRAVERY_ABBREVIATION: \"ROH\"\n  STR_REACTIONS_ABBREVIATION: \"REA\"\n  STR_FIRING_ACCURACY_ABBREVIATION: \"TAR\"\n  STR_THROWING_ACCURACY_ABBREVIATION: \"HEI\"\n  STR_STRENGTH_ABBREVIATION: \"VOI\"\n  STR_MELEE_ACCURACY_ABBREVIATION: \"LÄH\"\n"
  },
  {
    "path": "bin/common/Language/fr-CA.yml",
    "content": "fr-CA:\n  STR_OPENXCOM: \"OpenXcom\"\n  STR_NEW_GAME: \"Nouvelle partie\"\n  STR_LOAD_SAVED_GAME: \"Charger une partie\"\n  STR_SELECT_DIFFICULTY_LEVEL: \"Sélectionnez le niveau de difficulté\"\n  STR_1_BEGINNER: \"1> Débutant\"\n  STR_2_EXPERIENCED: \"2> Expérimenté\"\n  STR_3_VETERAN: \"3> Vétéran\"\n  STR_4_GENIUS: \"4> Génie\"\n  STR_5_SUPERHUMAN: \"5> Surhumain\"\n  STR_TIME: \"Heure\"\n  STR_DATE: \"Date\"\n  STR_SELECT_GAME_TO_LOAD: \"Sélectionnez la partie à charger\"\n  STR_SELECT_SAVE_POSITION: \"Sélectionnez la case de la sauvegarde\"\n  STR_GAME_OPTIONS: \"OPTIONS DU JEU\"\n  STR_LOAD_GAME: \"CHARGER\"\n  STR_SAVE_GAME: \"SAUVEGARDER\"\n  STR_ABANDON_GAME: \"ABANDONNER\"\n  STR_ABANDON_GAME_QUESTION: \"ABANDONNER?\"\n  STR_QUIT: \"Quitter\"\n  STR_SAVING_GAME: \"Sauvegarde de la partie...\"\n  STR_LOADING_GAME: \"Chargement de la partie...\"\n  STR_NO_SAVED_GAME_PRESENT: \"Aucune sauvegarde de disponible\"\n  STR_LOAD_UNSUCCESSFUL: \"Échec du chargement\"\n  STR_SAVE_UNSUCCESSFUL: \"Échec de la sauvegarde\"\n  STR_LOAD_SUCCESSFUL: \"Chargement réussi\"\n  STR_SAVE_SUCCESSFUL: \"Sauvegarde réussie\"\n  STR_DELETE: \"SUPPRIMER\"\n  STR_DELETE_UNSUCCESSFUL: \"Échec de la suppression\"\n  STR_IS_IT_OK_TO_DELETE_THE_SAVED_GAME: \"Voulez-vous vraiment supprimer la sauvegarde?\"\n  STR_ORIGINAL_XCOM: \"X-Com original\"\n  STR_LOADING: \"Chargement en cours...\"\n  STR_DETAILS: \"DÉTAILS> {ALT}{0}\"\n  STR_NEW_BATTLE: \"Nouvelle bataille\"\n  STR_OPTIONS: \"Options\"\n  STR_RIGHT_CLICK_TO_DELETE: \"Faites un clic droit pour supprimer une partie\"\n  STR_RESTORE_DEFAULTS: \"Valeurs par défaut\"\n  STR_CONTROLS: \"CONTRÔLES\"\n  STR_GENERAL: \"Générales\"\n  STR_GEOSCAPE: \"Géoscape\"\n  STR_BATTLESCAPE: \"Battlescape\"\n  STR_SCREENSHOT: \"Prendre un screenshot\"\n  STR_FPS_COUNTER: \"Compteur de FPS\"\n  STR_ROTATE_LEFT: \"Rotation vers la gauche\"\n  STR_ROTATE_RIGHT: \"Rotation vers la droite\"\n  STR_ROTATE_UP: \"Rotation vers le haut\"\n  STR_ROTATE_DOWN: \"Rotation vers le bas\"\n  STR_ZOOM_IN: \"Zoom avant\"\n  STR_ZOOM_OUT: \"Zoom arrière\"\n  STR_TOGGLE_COUNTRY_DETAIL: \"Alterner le détail des pays\"\n  STR_TOGGLE_RADAR_RANGES: \"Alterner la portée des radars\"\n  STR_SCROLL_LEFT: \"Défiler vers la gauche\"\n  STR_SCROLL_RIGHT: \"Défiler vers la droite\"\n  STR_SCROLL_UP: \"Défiler vers le haut\"\n  STR_SCROLL_DOWN: \"Défiler vers le bas\"\n  STR_UNIT_LEVEL_ABOVE: \"Monter l'unité d'un niveau\"\n  STR_UNIT_LEVEL_BELOW: \"Descendre l'unité d'un niveau\"\n  STR_VIEW_LEVEL_ABOVE: \"Voir le niveau supérieur\"\n  STR_VIEW_LEVEL_BELOW: \"Voir le niveau inférieur\"\n  STR_CENTER_SELECTED_UNIT: \"Centrer sur l'unité sélectionnée\"\n  STR_PREVIOUS_UNIT: \"Passer à l'unité précédente\"\n  STR_NEXT_UNIT: \"Passer à l'unité suivante\"\n  STR_DESELECT_UNIT: \"Passer et ne plus resélectionner\"\n  STR_USE_LEFT_HAND: \"Utiliser l'objet de la main gauche\"\n  STR_USE_RIGHT_HAND: \"Utiliser l'objet de la main droite\"\n  STR_INVENTORY: \"Inventaire\"\n  STR_MINIMAP: \"Mini-carte\"\n  STR_MULTI_LEVEL_VIEW: \"Vue multi-niveaux\"\n  STR_END_TURN: \"Fin du tour\"\n  STR_ABORT_MISSION: \"Abandonner la mission\"\n  STR_UNIT_STATS: \"Statistiques de l'unité\"\n  STR_KNEEL: \"S'agenouiller/se relever\"\n  STR_RELOAD: \"Recharger\"\n  STR_TOGGLE_PERSONAL_LIGHTING: \"Alterner l'éclairage personnel\"\n  STR_DONT_RESERVE_TIME_UNITS: \"Ne pas garder d'UT\"\n  STR_RESERVE_TIME_UNITS_FOR_SNAP_SHOT: \"Garder des UT pour un tir rapide\"\n  STR_RESERVE_TIME_UNITS_FOR_AIMED_SHOT: \"Garder des UT pour un tir précis\"\n  STR_RESERVE_TIME_UNITS_FOR_AUTO_SHOT: \"Garder des UT pour un tir auto.\"\n  STR_CENTER_ON_ENEMY_1: \"Centrer sur l'ennemi 1\"\n  STR_CENTER_ON_ENEMY_2: \"Centrer sur l'ennemi 2\"\n  STR_CENTER_ON_ENEMY_3: \"Centrer sur l'ennemi 3\"\n  STR_CENTER_ON_ENEMY_4: \"Centrer sur l'ennemi 4\"\n  STR_CENTER_ON_ENEMY_5: \"Centrer sur l'ennemi 5\"\n  STR_CENTER_ON_ENEMY_6: \"Centrer sur l'ennemi 6\"\n  STR_CENTER_ON_ENEMY_7: \"Centrer sur l'ennemi 7\"\n  STR_CENTER_ON_ENEMY_8: \"Centrer sur l'ennemi 8\"\n  STR_CENTER_ON_ENEMY_9: \"Centrer sur l'ennemi 9\"\n  STR_CENTER_ON_ENEMY_10: \"Centrer sur l'ennemi 10\"\n  STR_CREATE_INVENTORY_TEMPLATE: \"Créer un modèle d'inventaire\"\n  STR_APPLY_INVENTORY_TEMPLATE: \"Appliquer un modèle d'inventaire\"\n  STR_CLEAR_INVENTORY: \"Vider l'inventaire\"\n  STR_AUTO_EQUIP: \"Équipement automatique\"\n  STR_QUICK_SAVE: \"Sauvegarde rapide\"\n  STR_QUICK_LOAD: \"Chargement rapide\"\n  STR_ADVANCED: \"AVANCÉES\"\n  STR_AGGRESSIVERETALIATION: \"Représailles agressives\"\n  STR_AGGRESSIVERETALIATION_DESC: \"Les ovnis vont tenter de détecter vos bases en tout temps, quels que soient leurs paramètres de mission.\"\n  STR_STORAGELIMITSENFORCED: \"Stockage limité aux objets récupérés\"\n  STR_STORAGELIMITSENFORCED_DESC: \"Impose des limites de stockage aux entrepôts et aux chambres de détention d'aliens pour les objets et les aliens vivants récupérés lors des missions.\"\n  STR_CANSELLLIVEALIENS: \"Vente d'aliens vivants\"\n  STR_CANSELLLIVEALIENS_DESC: \"Permet la vente d'aliens vivants, recommandée avec l'utilisation des limites de stockage.\"\n  STR_ALLOWBUILDINGQUEUE: \"Permettre la construction en chaîne\"\n  STR_ALLOWBUILDINGQUEUE_DESC: \"Les nouvelles installations peuvent être placées à côté de celles en construction.\"\n  STR_BATTLEAUTOEND: \"Fin de bataille automatique\"\n  STR_BATTLEAUTOEND_DESC: \"Les batailles se terminent automatiquement lorsque le dernier ennemi vivant est neutralisé.\"\n  STR_BATTLEINSTANTGRENADE: \"Grenades instantanées\"\n  STR_BATTLEINSTANTGRENADE_DESC: \"Les grenades amorcées pour exploser dans 0 tour vont le faire immédiatement après être lancées plutôt qu'à la fin du tour.\"\n  STR_BATTLEUFOEXTENDERACCURACY: \"Étendue de précision des tirs d'ovnis\"\n  STR_BATTLEUFOEXTENDERACCURACY_DESC: \"La précision des tirs diminue après une certaine distance, selon le type de tir. La précision ajustée sera affichée sur le curseur.\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE: \"Transferts en vol\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE_DESC: \"Les vaisseaux en vol peuvent être transférés à une nouvelle base.\"\n  STR_CRAFTLAUNCHALWAYS: \"Forcer le lancement des vaisseaux\"\n  STR_CRAFTLAUNCHALWAYS_DESC: \"Les vaisseaux peuvent être lancés même lorsqu'ils ne sont pas prêts, ignorant le ravitaillement et la maintenance.\"\n  STR_CUSTOMINITIALBASE: \"Personnalisation de la base initiale\"\n  STR_CUSTOMINITIALBASE_DESC: \"Lors du démarrage d'une nouvelle partie, vous pouvez manuellement placer vos installations de départ au-lieu d'utiliser la disposition par défaut.\"\n  STR_GLOBESEASONS: \"Éclairage réaliste du globe\"\n  STR_GLOBESEASONS_DESC: \"Utilise une projection plus réaliste de la lumière du soleil sur le Géoscape en fonction de l'inclinaison axiale de la Terre.\"\n  STR_PLAYINTRO: \"Jouer la séquence d'introduction\"\n  STR_PLAYINTRO_DESC: \"Lance la cinématique d'introduction au démarrage du jeu.\"\n  STR_SHOWMORESTATSININVENTORYVIEW: \"Statistiques d'inventaire\"\n  STR_SHOWMORESTATSININVENTORYVIEW_DESC: \"Affiche de l'information additionnelle sur le soldat sélectionné dans l'écran de l'inventaire.\"\n  STR_SNEAKYAI: \"IA furtive\"\n  STR_SNEAKYAI_DESC: \"L'IA évite de s'exposer au joueur aussi souvent que possible.\"\n  STR_STRAFE: \"Méthodes de déplacement alternatives\"\n  STR_STRAFE_DESC: \"Active le déplacement latéral, la course et le mouvement indépendant de la tourelle du tank en maintenant la touche CTRL.\"\n  STR_BATTLEEXPLOSIONHEIGHT: \"Hauteur des explosions\"\n  STR_BATTLEEXPLOSIONHEIGHT_DESC: \"Change la distance de propagation des explosions en hauteur.{NEWLINE}(Plate : 0, ronde : 3)\"\n  STR_AUTOSAVE: \"Sauvegarde automatique\"\n  STR_AUTOSAVE_DESC: \"Sauvegarde automatiquement la partie à des intervalles spécifiées. Ne s'applique pas au mode Ironman.\"\n  STR_AUTOSAVE_FREQUENCY: \"Fréquence de sauvegarde automatique\"\n  STR_AUTOSAVE_FREQUENCY_DESC: \"Quantité de tours de jeu entre les sauvegardes automatiques des parties.\"\n  STR_ALLOWPSIONICCAPTURE: \"Permettre la capture psionique\"\n  STR_ALLOWPSIONICCAPTURE_DESC: \"Contrôler mentalement tous les aliens restants entraîne une victoire, et ils sont comptés comme capturés vivants.\"\n  STR_ANYTIMEPSITRAINING: \"Entraînement psionique en tout temps\"\n  STR_ANYTIMEPSITRAINING_DESC: \"Permet d'assigner des soldats à l'entraînement psionique n'importe quand dans le mois. Rappelez-vous que l'entraînement initial prend de 30 à 60 jours.\"\n  STR_SKIPNEXTTURNSCREEN: \"Passer les écrans de fin de tour\"\n  STR_SKIPNEXTTURNSCREEN_DESC: \"Les écrans de fin de tour durant les batailles sont avancés automatiquement après un court délai.\"\n  STR_NOT_ENOUGH_SPACE: \"Pas assez de place!\"\n  STR_WEAPONSELFDESTRUCTION: \"Autodestruction d'armes aliens\"\n  STR_WEAPONSELFDESTRUCTION_DESC: \"Les armes transportées par les aliens vont s'autodétruire à la mort de leur possesseur, comme dans XCOM 2012.\"\n  STR_RETAINCORPSES: \"Conserver les aliens interrogés\"\n  STR_RETAINCORPSES_DESC: \"Après avoir \\\"recherché\\\" sur les aliens vivants, leur corps sera ajouté aux stocks de la base, comme dans XCOM 2012.\"\n  STR_SAVE_VOXEL_VIEW: \"Sauvegarder un screenshot d'une vue 3D à la première personne\"\n  STR_RESERVE_TIME_UNITS_FOR_KNEEL: \"Garder des UT pour s'agenouiller\"\n  STR_EXPEND_ALL_TIME_UNITS: \"Dépenser les UT restantes\"\n  STR_PSISTRENGTHEVAL: \"Évaluation de la force psionique\"\n  STR_PSISTRENGTHEVAL_DESC: \"Évalue la force psionique de tous les soldats après que la recherche appropriée a été complétée.\"\n  STR_DISABLEAUTOEQUIP: \"Désactiver l'équipement automatique\"\n  STR_DISABLEAUTOEQUIP_DESC: \"Désactive l'équipement automatique des nouveaux soldats avant la bataille.\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT: \"Permettre l'amélioration de la force psi.\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT_DESC: \"La force psionique des soldats peut être améliorée par l'expérience et l'entraînement.\"\n  STR_BATTLESMOOTHCAMERA: \"Caméra de suivi des tirs sans à-coups\"\n  STR_BATTLESMOOTHCAMERA_DESC: \"La caméra du Battlescape reste centrée continuellement sur les projectiles durant le combat.\"\n  STR_BATTLECONFIRMFIREMODE: \"Confirmation des modes de tir\"\n  STR_BATTLECONFIRMFIREMODE_DESC: \"Un second clic sur la même case est requis pour confirmer l'ordre de tirer.\"\n  STR_SELECT_BASE_1: \"Sélectionner la base 1\"\n  STR_SELECT_BASE_2: \"Sélectionner la base 2\"\n  STR_SELECT_BASE_3: \"Sélectionner la base 3\"\n  STR_SELECT_BASE_4: \"Sélectionner la base 4\"\n  STR_SELECT_BASE_5: \"Sélectionner la base 5\"\n  STR_SELECT_BASE_6: \"Sélectionner la base 6\"\n  STR_SELECT_BASE_7: \"Sélectionner la base 7\"\n  STR_SELECT_BASE_8: \"Sélectionner la base 8\"\n  STR_VIDEO: \"VIDÉO\"\n  STR_AUDIO: \"AUDIO\"\n  STR_BATTLESCAPE_UC: \"BATTLESCAPE\"\n  STR_DISPLAY_RESOLUTION: \"Résolution de l'affichage\"\n  STR_DISPLAY_RESOLUTION_DESC: \"Change la résolution de l'affichage, la résolution du jeu s'ajustera en conséquence. Les flèches font changer entre les résolutions supportées. Cliquez pour saisir une résolution personnalisée.\"\n  STR_ORIGINAL: \"Originale\"\n  STR_DISPLAY_MODE: \"Mode d'affichage\"\n  STR_WINDOWED: \"Fenêtré\"\n  STR_FULLSCREEN: \"Plein écran\"\n  STR_BORDERLESS: \"Sans bordures\"\n  STR_DISPLAY_LANGUAGE: \"Langue de l'interface\"\n  STR_DISPLAY_LANGUAGE_DESC: \"Change la langue des textes du jeu.\"\n  STR_DISPLAY_FILTER: \"Filtre d'affichage\"\n  STR_DISPLAY_FILTER_DESC: \"Change le filtre appliqué à l'écran du jeu.{NEWLINE}*requiert l'accélération matérielle d'OpenGL.\"\n  STR_DISPLAY_OPTIONS: \"Options d'affichage\"\n  STR_LETTERBOXED: \"Letterbox\"\n  STR_LETTERBOXED_DESC: \"Utilise l'affichage au format Letterbox pour conserver les proportions d'origine.\"\n  STR_RESIZABLE: \"Redimensionnable\"\n  STR_LOCK_MOUSE: \"Capture de la souris\"\n  STR_LOCK_MOUSE_DESC: \"Empêche le curseur de la souris de sortir de la fenêtre de jeu. Appuyez sur CTRL+G pour alterner la capture en tout temps.\"\n  STR_FIXED_WINDOW_POSITION: \"Position de fenêtre fixe\"\n  STR_FIXED_WINDOW_POSITION_DESC: \"Définit la position fixe de la fenêtre.\"\n  STR_DISPLAY_SET_WINDOW_POSITION: \"Nouvelle position racine de la fenêtre\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_X: \"Position X du bord gauche :\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_Y: \"Position Y du bord haut :\"\n  STR_MUSIC_VOLUME: \"Volume de la musique\"\n  STR_MUSIC_VOLUME_DESC: \"Change le volume de la musique en arrière-plan.\"\n  STR_SFX_VOLUME: \"Volume des sons\"\n  STR_SFX_VOLUME_DESC: \"Change le volume des effets sonores.\"\n  STR_UI_VOLUME: \"Volume de l'interface\"\n  STR_UI_VOLUME_DESC: \"Change le volume des 'bips' de l'interface.\"\n  STR_SCROLL_SPEED: \"Vitesse de défilement\"\n  STR_SCROLL_SPEED_GEO_DESC: \"Change la vitesse de rotation du globe.\"\n  STR_SCROLL_SPEED_BATTLE_DESC: \"Change la vitesse de défilement sur la carte.\"\n  STR_DOGFIGHT_SPEED: \"Vitesse de l'interception\"\n  STR_DOGFIGHT_SPEED_DESC: \"Change la vitesse des batailles d'interception entre les vaisseaux et les ovnis. Une vitesse plus lente peut améliorer la performance sur d'anciennes machines.\"\n  STR_CLOCK_SPEED: \"Vitesse de l'horloge\"\n  STR_CLOCK_SPEED_DESC: \"Change la vitesse de l'horloge du Géoscape. Une vitesse plus lente peut améliorer la performance sur d'anciennes machines.\"\n  STR_GLOBE_DETAILS: \"Détails du globe\"\n  STR_GLOBE_COUNTRIES: \"Pays\"\n  STR_GLOBE_COUNTRIES_DESC: \"Affiche les pays qui font le financement sur le globe.\"\n  STR_GLOBE_RADARS: \"Radars\"\n  STR_GLOBE_RADARS_DESC: \"Affiche les portées de radar des bases sur le globe.\"\n  STR_GLOBE_FLIGHT_PATHS: \"Trajectoires de vol\"\n  STR_GLOBE_FLIGHT_PATHS_DESC: \"Affiche les trajectoires des vaisseaux en vol sur le globe.\"\n  STR_CONTROLS_DESC: \"Faites un clic gauche sur un raccourci et appuyez sur une touche pour le modifier.{NEWLINE}Faites un clic droit sur un raccourci pour le désactiver.\"\n  STR_MODS_TOOLTIP: \"Version {0} par {1}.{NEWLINE}{2}\"\n  STR_EDGE_SCROLL: \"Défilement aux bords\"\n  STR_EDGE_SCROLL_DESC: \"Sur clic : défile la carte quand le bouton gauche de la souris est maintenu enfoncé sur l'un des bords de l'écran.{NEWLINE}Auto : défile la carte quand le curseur est sur les bords de l'écran.\"\n  STR_TRIGGER_SCROLL: \"Sur clic\"\n  STR_AUTO_SCROLL: \"Auto\"\n  STR_DRAG_SCROLL: \"Cliquer-défiler\"\n  STR_DRAG_SCROLL_DESC: \"La carte défile quand la souris se déplace tout en maintenant le bouton de la souris spécifié enfoncé.\"\n  STR_LEFT_MOUSE_BUTTON: \"Bouton gauche\"\n  STR_MIDDLE_MOUSE_BUTTON: \"Bouton central\"\n  STR_RIGHT_MOUSE_BUTTON: \"Bouton droit\"\n  STR_FIRE_SPEED: \"Vitesse des tirs\"\n  STR_FIRE_SPEED_DESC: \"Change la vitesse des projectiles des armes.\"\n  STR_PLAYER_MOVEMENT_SPEED: \"Vitesse des soldats\"\n  STR_PLAYER_MOVEMENT_SPEED_DESC: \"Change la vitesse de déplacement des unités contrôlées par le joueur.\"\n  STR_COMPUTER_MOVEMENT_SPEED: \"Vitesse des aliens\"\n  STR_COMPUTER_MOVEMENT_SPEED_DESC: \"Change la vitesse de déplacement des unités contrôlées par l'ordinateur.\"\n  STR_PATH_PREVIEW: \"Aperçu des trajets\"\n  STR_PATH_ARROWS: \"Flèches\"\n  STR_PATH_ARROWS_DESC: \"Cliquer montre le trajet que votre unité va prendre vers sa destination. La couleur indique les actions possibles. Vert : peut se déplacer et tirer - Jaune : peut se déplacer - Rouge : trop loin.\"\n  STR_PATH_TIME_UNIT_COST: \"Unités de temps\"\n  STR_PATH_TIME_UNIT_COST_DESC: \"Cliquer montre les UT restantes que votre unité aura après s'être déplacée à sa destination.\"\n  STR_USER_INTERFACE_OPTIONS: \"Options de l'interface\"\n  STR_TOOLTIPS: \"Infobulles\"\n  STR_TOOLTIPS_DESC: \"Affiche des infobulles pour les boutons du Battlescape.\"\n  STR_DEATH_NOTIFICATIONS: \"Annonce des morts\"\n  STR_DEATH_NOTIFICATIONS_DESC: \"Affiche une notification détaillant qui a été tué lorsqu'un soldat meurt.\"\n  STR_SHOW_FUNDS: \"Afficher le budget\"\n  STR_SHOW_FUNDS_DESC: \"Affiche votre budget actuel près de l'horloge du Géoscape.\"\n  STR_MISSION_GENERATOR: \"GÉNÉRATEUR DE MISSION\"\n  STR_MAP_OPTIONS: \"OPTIONS DE LA CARTE\"\n  STR_ALIEN_OPTIONS: \"OPTIONS DES ALIENS\"\n  STR_MAP_TERRAIN: \"Terrain\"\n  STR_MAP_DARKNESS: \"Obscurité\"\n  STR_MAP_DEPTH: \"Profondeur\"\n  STR_DIFFICULTY: \"Difficulté\"\n  STR_ALIEN_RACE: \"Race\"\n  STR_ALIEN_TECH_LEVEL: \"Niveau de technologie\"\n  STR_RANDOMIZE: \"Valeurs aléatoires\"\n  STR_RESTORE_DEFAULTS_QUESTION: \"Voulez-vous vraiment restaurer les options aux valeurs par défaut?\"\n  STR_DISPLAY_OPTIONS_CONFIRM: \"Voulez-vous garder les options d'affichage actuelles?\"\n  STR_DISPLAY_OPTIONS_REVERT: \"Rétablissement dans 0:{0}\"\n  STR_MISSING_CONTENT_PROMPT: \"AVERTISSEMENT : {SMALLLINE}Cette sauvegarde se base sur des mods qui sont indisponibles. Le contenu manquant sera enlevé, et le chargement peut échouer.{NEWLINE}Continuer?\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT: \"Sauvegarder les grenades pré-amorcées\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT_DESC: \"Sauvegarde les grenades amorcées durant l'inventaire de préparation au combat dans la grille d'équipement des soldats.\"\n  STR_NEWSEEDONLOAD: \"Anti-abus de sauvegardes\"\n  STR_NEWSEEDONLOAD_DESC: \"Charger une partie va réinitialiser le seed de nombre aléatoire, alors effectuer la même action peut donner des résultats différents. Ne s'applique pas au mode Ironman.\"\n  STR_CHANGEVALUEBYMOUSEWHEEL: \"Changer les valeurs avec la molette\"\n  STR_CHANGEVALUEBYMOUSEWHEEL_DESC: \"Vous permet d'utiliser la molette de la souris pour augmenter/diminuer les valeurs par cette quantité.\"\n  STR_BATTLEHAIRBLEACH: \"Améliorer les sprites des soldats\"\n  STR_BATTLEHAIRBLEACH_DESC: \"Change les sprites des soldats du Battlescape afin qu'ils correspondent à leur inventaire.\"\n  STR_DRAGSCROLLINVERT: \"Inverser le cliquer-défiler\"\n  STR_DRAGSCROLLINVERT_DESC: \"Lorsque cette option est activée, le défilement par cliquer-défiler est inversé et l'écran défile dans la direction opposée de celle de la souris.\"\n  STR_BATTLESCAPE_SCALE: \"Échelle du Battlescape\"\n  STR_BATTLESCAPE_SCALE_DESC: \"Le mode de mise à l'échelle de la vue du Battlescape, basé sur une résolution fixe (étiré), ou sur un niveau de zoom fixe (agrandi).\"\n  STR_GEOSCAPE_SCALE: \"Échelle du Géoscape\"\n  STR_GEOSCAPESCALE_SCALE_DESC: \"Le mode de mise à l'échelle de la vue du Géoscape, basé sur une résolution fixe (étiré), ou sur un niveau de zoom fixe (agrandi).\"\n  STR_1_5X: \"Originale 1.5x\"\n  STR_2X: \"Originale 2x\"\n  STR_THIRD_DISPLAY: \"Écran 1/3\"\n  STR_HALF_DISPLAY: \"Écran 1/2\"\n  STR_FULL_DISPLAY: \"Plein écran\"\n  STR_FPS_LIMIT: \"Limite des FPS\"\n  STR_FPS_LIMIT_DESC: \"Limite le nombre de frames par seconde, 0 pour aucune limite. Si le rendu OpenGL est activé, le jeu utilise VSync à la place.\"\n  STR_FPS_INACTIVE_LIMIT: \"Limite des FPS en arrière-plan\"\n  STR_FPS_INACTIVE_LIMIT_DESC: \"Limite le nombre de frames par seconde si OpenXcom est en arrière-plan.\"\n  STR_NOALIENPANICMESSAGES: \"Retirer les messages de panique d'aliens\"\n  STR_NOALIENPANICMESSAGES_DESC: \"Empêche d'afficher les messages de panique pour les aliens à moins qu'ils ne soient visibles par les unités du joueur.\"\n  STR_ALIENBLEEDING: \"Saignement des aliens\"\n  STR_ALIENBLEEDING_DESC: \"Permet que des blessures mortelles soient infligées à la plupart des aliens.\"\n  STR_FIELDPROMOTIONS: \"Promotions de bataille\"\n  STR_FIELDPROMOTIONS_DESC: \"Seulement les soldats qui étaient présents sur le terrain de la mission sont éligibles pour une promotion.\"\n  STR_MEETINGPOINT: \"Prédire la trajectoire des ovnis\"\n  STR_MEETINGPOINT_DESC: \"Les vaisseaux volent vers un point de rencontre avec l'ovni en se basant sur sa trajectoire actuelle.\"\n  STR_IRONMAN: \"IRONMAN\"\n  STR_IRONMAN_DESC: \"Aucune sauvegarde manuelle autorisée\"\n  STR_SAVE_AND_ABANDON_GAME: \"SAUVEGARDER ET ABANDONNER\"\n  STR_MOD_UNSUCCESSFUL: \"Le mod a échoué de charger\"\n  STR_NEW_SAVED_GAME_SLOT: \"<NOUVELLE SAUVEGARDE>\"\n  STR_AUTO_SAVE_GEOSCAPE_SLOT: \"<GÉOSCAPE AUTO>\"\n  STR_AUTO_SAVE_BATTLESCAPE_SLOT: \"<BATTLESCAPE AUTO>\"\n  STR_QUICK_SAVE_SLOT: \"<SAUVEGARDE RAPIDE>\"\n  STR_DISPLAY_MODE_DESC: \"Change la façon dont le jeu est affiché sur l'écran.\"\n  STR_PREFERRED_MUSIC_FORMAT: \"Format de la musique\"\n  STR_PREFERRED_MUSIC_FORMAT_DESC: \"Choisissez votre format de musique préféré à utiliser lorsqu'il y en a plusieurs de disponibles.{NEWLINE}NOTE : le format MIDI peut être bogué sur Windows.\"\n  STR_PREFERRED_SFX_FORMAT: \"Format des sons\"\n  STR_PREFERRED_SFX_FORMAT_DESC: \"Choisissez votre format d'effets sonores préféré à utiliser lorsqu'il y en a plusieurs de disponibles.\"\n  STR_PREFERRED_VIDEO_FORMAT: \"Format vidéo\"\n  STR_PREFERRED_VIDEO_FORMAT_DESC: \"Choisissez votre format vidéo préféré à utiliser lorsqu'il y en a plusieurs de disponibles.\"\n  STR_PREFERRED_VIDEO_ANIMATION: \"Animation\"\n  STR_PREFERRED_VIDEO_SLIDESHOW: \"Diaporama\"\n  STR_PREFERRED_FORMAT_AUTO: \"Auto\"\n  STR_CURRENT_FORMAT: \"Actuel : {0}\"\n  STR_FORCE_FIRE: \"Forcer la ligne de tir\"\n  STR_FORCE_FIRE_DESC: \"Force vos soldats à faire feu en maintenant la touche CTRL enfoncée, quelles que soient les règles de ligne de tir.\"\n  STR_NO_AUDIO_HARDWARE_DETECTED: \"Aucun périphérique audio détecté\"\n  STR_MOUSEWHEEL_SPEED: \"Vitesse de défilement de la molette\"\n  STR_MOUSEWHEEL_SPEED_DESC: \"Ajuste le nombre de lignes défilées dans les listes avec chaque incrémentation de la molette de la souris.\"\n  STR_DISABLED: \"Désactivé\"\n  STR_MAXIMIZE_INFO_SCREENS: \"Maximiser les écrans d'information\"\n  STR_MAXIMIZE_INFO_SCREENS_DESC: \"L'inventaire et d'autres écrans variés seront affichés en plein écran, quels que soient les paramètres d'échelle.\"\n  STR_DIARY: \"JOURNAL\"\n  STR_KILLED: \"TUÉ\"\n  STR_STUNNED: \"ASSOMMÉ\"\n  STR_PANICKED: \"PANIQUÉ\"\n  STR_MINDCONTROLLED: \"CONTRÔLÉ\"\n  STR_REGION_UNKNOWN: \"Non révélé\"\n  STR_WEAPON_UNKNOWN: \"Improvisation\"\n  STR_UNKNOWN: \"Inconnu\"\n  STR_VICTORY: \"Victoire\"\n  STR_DEFEAT: \"Défaite\"\n  STR_NO_RECORD: \"Pas de record\"\n  STR_HUMAN: \"Humain\"\n  STR_FRIENDLY: \"Amical\"\n  STR_HOSTILE: \"Hostile\"\n  STR_NEUTRAL: \"Neutre\"\n  STR_RATING_UC: \"CLASSEMENT\"\n  STR_LOCATION: \"EMPLACEMENT> {ALT}{0}\"\n  STR_DAYLIGHT_TYPE: \"TEMPS> {ALT}{0}\"\n  STR_RACE_TYPE: \"RACE> {ALT}{0}\"\n  STR_DAY: \"Jour\"\n  STR_NIGHT: \"Nuit\"\n  STR_DAYS_WOUNDED: \"JOURS BLESSÉ> {ALT}{0}\"\n  STR_COMBAT: \"COMBAT\"\n  STR_PERFORMANCE: \"PERFORMANCE\"\n  STR_NEUTRALIZATIONS_BY_RACE: \"NEUTRALISATIONS PAR RACE\"\n  STR_NEUTRALIZATIONS_BY_RANK: \"NEUTRALISATIONS PAR GRADE\"\n  STR_NEUTRALIZATIONS_BY_WEAPON: \"NEUTRALISATIONS PAR ARME\"\n  STR_MISSIONS_BY_LOCATION: \"MISSIONS PAR EMPLACEMENT\"\n  STR_MISSIONS_BY_TYPE: \"MISSIONS PAR TYPE\"\n  STR_MISSIONS_BY_UFO: \"MISSIONS PAR OVNI\"\n  STR_SCORE_VALUE: \"SCORE> {ALT}{0}\"\n  STR_WINS: \"VICTOIRES> {ALT}{0}\"\n  STR_STUNS: \"ASSOMMAGES> {ALT}{0}\"\n  STR_PANICKS: \"PANIQUES> {ALT}{0}\"\n  STR_MINDCONTROLS: \"CONTRÔLES> {ALT}{0}\"\n  STR_AWARDS: \"RÉCOMPENSES\"\n  STR_COMMENDATIONS_UC: \"DÉCORATIONS\"\n  STR_COMMENDATIONS: \"Décorations\"\n  STR_MEDALS: \"MÉDAILLES\"\n  STR_LOST_IN_SERVICE: \"PERDU EN SERVICE\"\n  STR_MEDAL_NAME: \"Nom de la médaille\"\n  STR_MEDAL_AWARD_LEVEL: \"Niveau de récompense\"\n  STR_MEDAL_DECOR_LEVEL: \"Niveau de décoration\"\n  STR_AWARD_0: \"Première récompense\"\n  STR_AWARD_1: \"Seconde récompense\"\n  STR_AWARD_2: \"Troisième récompense\"\n  STR_AWARD_3: \"Quatrième récompense\"\n  STR_AWARD_4: \"Cinquième récompense\"\n  STR_AWARD_5: \"Sixième récompense\"\n  STR_AWARD_6: \"Septième récompense\"\n  STR_AWARD_7: \"Huitième récompense\"\n  STR_AWARD_8: \"Neuvième récompense\"\n  STR_AWARD_9: \"Dixième récompense\"\n  STR_AWARD_DECOR_0: \"Aucune\"\n  STR_AWARD_DECOR_1: \"Premier insigne de bronze\"\n  STR_AWARD_DECOR_2: \"Deuxième insigne de bronze\"\n  STR_AWARD_DECOR_3: \"Troisième insigne de bronze\"\n  STR_AWARD_DECOR_4: \"Premier insigne d'argent\"\n  STR_AWARD_DECOR_5: \"Deuxième insigne d'argent\"\n  STR_AWARD_DECOR_6: \"Troisième insigne d'argent\"\n  STR_AWARD_DECOR_7: \"Premier insigne d'or\"\n  STR_AWARD_DECOR_8: \"Deuxième insigne d'or\"\n  STR_AWARD_DECOR_9: \"Troisième insigne d'or\"\n  STR_KILLED_IN_ACTION_MALE: \"MORT AU COMBAT\"\n  STR_KILLED_IN_ACTION_FEMALE: \"MORTE AU COMBAT\"\n  STR_MISSING_IN_ACTION_MALE: \"PORTÉ DISPARU\"\n  STR_MISSING_IN_ACTION_FEMALE: \"PORTÉE DISPARUE\"\n  STR_AVERAGE_MONTHLY_RATING: \"Taux mensuel moyen\"\n  STR_TOTAL_INCOME: \"Revenu total\"\n  STR_TOTAL_EXPENDITURE: \"Dépenses totales\"\n  STR_MISSIONS_WON: \"Missions accomplies\"\n  STR_MISSIONS_LOST: \"Missions échouées\"\n  STR_NIGHT_MISSIONS: \"Missions de nuit\"\n  STR_BEST_RATING: \"Meilleure cote de mission\"\n  STR_WORST_RATING: \"Pire cote de mission\"\n  STR_ALIEN_KILLS: \"Aliens tués\"\n  STR_ALIEN_CAPTURES: \"Aliens capturés\"\n  STR_FRIENDLY_KILLS: \"Incidents alliés\"\n  STR_AVERAGE_ACCURACY: \"Précision moyenne\"\n  STR_WEAPON_MOST_KILLS: \"Arme la plus efficace\"\n  STR_ALIEN_MOST_KILLS: \"Alien le plus mortel\"\n  STR_LONGEST_SERVICE: \"Plus longs mois en service\"\n  STR_TOTAL_DAYS_WOUNDED: \"Jours blessé\"\n  STR_COUNTRIES_LOST: \"Pays infiltrés\"\n  STR_TOTAL_TERROR_SITES: \"Attaques de terreur\"\n  STR_TOTAL_BASES: \"Bases construites\"\n  STR_TOTAL_CRAFT: \"Vaisseaux possédés\"\n  STR_TOTAL_SCIENTISTS: \"Scientifiques embauchés\"\n  STR_TOTAL_ENGINEERS: \"Ingénieurs embauchés\"\n  STR_TOTAL_RESEARCH: \"Recherches complétées\"\n  STR_DIARY_ACCURACY: \"PRÉCISION> {ALT}{0} %\"\n  STR_STATISTICS: \"Statistiques\"\n  STR_STATS: \"STATS\"\n  STR_TIME_UNITS_ABBREVIATION: \"UT\"\n  STR_STAMINA_ABBREVIATION: \"END\"\n  STR_HEALTH_ABBREVIATION: \"PV\"\n  STR_BRAVERY_ABBREVIATION: \"BRV\"\n  STR_REACTIONS_ABBREVIATION: \"RÉA\"\n  STR_FIRING_ACCURACY_ABBREVIATION: \"PRÉ\"\n  STR_THROWING_ACCURACY_ABBREVIATION: \"LCR\"\n  STR_STRENGTH_ABBREVIATION: \"FOR\"\n  STR_MELEE_ACCURACY_ABBREVIATION: \"MÊL\"\n"
  },
  {
    "path": "bin/common/Language/fr.yml",
    "content": "fr:\n  STR_OPENXCOM: \"OpenXcom\"\n  STR_NEW_GAME: \"Nouveau Jeu\"\n  STR_LOAD_SAVED_GAME: \"Charger Jeu\"\n  STR_SELECT_DIFFICULTY_LEVEL: \"Sélectionner Niveau de Difficulté\"\n  STR_1_BEGINNER: \"1> Facile\"\n  STR_2_EXPERIENCED: \"2> Moyen\"\n  STR_3_VETERAN: \"3> Difficile\"\n  STR_4_GENIUS: \"4> Très Difficile\"\n  STR_5_SUPERHUMAN: \"5> Impossible\"\n  STR_TIME: \"Heure\"\n  STR_DATE: \"Date\"\n  STR_SELECT_GAME_TO_LOAD: \"Charger une sauvegarde\"\n  STR_SELECT_SAVE_POSITION: \"Sélectionner une sauvegarde\"\n  STR_GAME_OPTIONS: \"OPTIONS\"\n  STR_LOAD_GAME: \"CHARGER\"\n  STR_SAVE_GAME: \"SAUVEGARDER\"\n  STR_ABANDON_GAME: \"ABANDONNER JEU\"\n  STR_ABANDON_GAME_QUESTION: \"ABANDONNER JEU ?\"\n  STR_QUIT: \"Quitter\"\n  STR_SAVING_GAME: \"Sauvegarde en cours\"\n  STR_LOADING_GAME: \"Chargement en cours\"\n  STR_NO_SAVED_GAME_PRESENT: \"Aucune sauvegarde disponible\"\n  STR_LOAD_UNSUCCESSFUL: \"Le chargement a échoué\"\n  STR_SAVE_UNSUCCESSFUL: \"La sauvegarde a échoué\"\n  STR_LOAD_SUCCESSFUL: \"Chargement réussi\"\n  STR_SAVE_SUCCESSFUL: \"Sauvegarde réussie.\"\n  STR_DELETE: \"EFFACER\"\n  STR_DELETE_UNSUCCESSFUL: \"Effacer a échoué.\"\n  STR_IS_IT_OK_TO_DELETE_THE_SAVED_GAME: \"Effacer le jeu sauvegardé ?\"\n  STR_ORIGINAL_XCOM: \"X-Com original\"\n  STR_LOADING: \"Chargement...\"\n  STR_DETAILS: \"DÉTAILS> {ALT}{0}\"\n  STR_NEW_BATTLE: \"Entraînement Tactique\"\n  STR_OPTIONS: \"Options\"\n  STR_RIGHT_CLICK_TO_DELETE: \"Supprimer avec un clic droit.\"\n  STR_RESTORE_DEFAULTS: \"Valeurs par défaut\"\n  STR_CONTROLS: \"COMMANDES\"\n  STR_GENERAL: \"Général\"\n  STR_GEOSCAPE: \"Géoscape\"\n  STR_BATTLESCAPE: \"Mode Tactique\"\n  STR_SCREENSHOT: \"Capture d'écran\"\n  STR_FPS_COUNTER: \"Compteur FPS\"\n  STR_ROTATE_LEFT: \"Pivoter vers la gauche\"\n  STR_ROTATE_RIGHT: \"Pivoter vers la droite\"\n  STR_ROTATE_UP: \"Pivoter vers le haut\"\n  STR_ROTATE_DOWN: \"Pivoter vers le bas\"\n  STR_ZOOM_IN: \"Zoomer\"\n  STR_ZOOM_OUT: \"Dézoomer\"\n  STR_TOGGLE_COUNTRY_DETAIL: \"Afficher/Masquer le détail des pays\"\n  STR_TOGGLE_RADAR_RANGES: \"Afficher/Masquer la portée des radars\"\n  STR_SCROLL_LEFT: \"Défilement Gauche\"\n  STR_SCROLL_RIGHT: \"Défilement Droit\"\n  STR_SCROLL_UP: \"Défilement Haut\"\n  STR_SCROLL_DOWN: \"Défilement Bas\"\n  STR_UNIT_LEVEL_ABOVE: \"Déplacer Unité au Niveau Supérieur\"\n  STR_UNIT_LEVEL_BELOW: \"Déplacer Unité au Niveau Inférieur\"\n  STR_VIEW_LEVEL_ABOVE: \"Voir Niveau Supérieur\"\n  STR_VIEW_LEVEL_BELOW: \"Voir Niveau Inférieur\"\n  STR_CENTER_SELECTED_UNIT: \"Centrer sur l'Unité Sélectionnée\"\n  STR_PREVIOUS_UNIT: \"Unité Précédente\"\n  STR_NEXT_UNIT: \"Unité Suivante\"\n  STR_DESELECT_UNIT: \"Désélectionner\"\n  STR_USE_LEFT_HAND: \"Utiliser Objet Main Gauche\"\n  STR_USE_RIGHT_HAND: \"Utiliser Objet Main Droite\"\n  STR_INVENTORY: \"Inventaire\"\n  STR_MINIMAP: \"Minicarte\"\n  STR_MULTI_LEVEL_VIEW: \"Vue multi-niveaux\"\n  STR_END_TURN: \"Fin de Tour\"\n  STR_ABORT_MISSION: \"Abandonner la Mission\"\n  STR_UNIT_STATS: \"Statistiques de l'Unité\"\n  STR_KNEEL: \"Agenouiller\"\n  STR_RELOAD: \"Recharger\"\n  STR_TOGGLE_PERSONAL_LIGHTING: \"Éclairage des soldats\"\n  STR_DONT_RESERVE_TIME_UNITS: \"Ne pas réserver les UT\"\n  STR_RESERVE_TIME_UNITS_FOR_SNAP_SHOT: \"UT réservées au tir rapide\"\n  STR_RESERVE_TIME_UNITS_FOR_AIMED_SHOT: \"UT réservées au tir précis\"\n  STR_RESERVE_TIME_UNITS_FOR_AUTO_SHOT: \"UT réservées au tir automatique\"\n  STR_CENTER_ON_ENEMY_1: \"Centrer sur l'Ennemi #1\"\n  STR_CENTER_ON_ENEMY_2: \"Centrer sur l'Ennemi #2\"\n  STR_CENTER_ON_ENEMY_3: \"Centrer sur l'Ennemi #3\"\n  STR_CENTER_ON_ENEMY_4: \"Centrer sur l'Ennemi #4\"\n  STR_CENTER_ON_ENEMY_5: \"Centrer sur l'Ennemi #5\"\n  STR_CENTER_ON_ENEMY_6: \"Centrer sur l'Ennemi #6\"\n  STR_CENTER_ON_ENEMY_7: \"Centrer sur l'Ennemi #7\"\n  STR_CENTER_ON_ENEMY_8: \"Centrer sur l'Ennemi #8\"\n  STR_CENTER_ON_ENEMY_9: \"Centrer sur l'Ennemi #9\"\n  STR_CENTER_ON_ENEMY_10: \"Centrer sur l'Ennemi #10\"\n  STR_CREATE_INVENTORY_TEMPLATE: \"Créer un modèle d'inventaire\"\n  STR_APPLY_INVENTORY_TEMPLATE: \"Appliquer un modèle d'inventaire\"\n  STR_CLEAR_INVENTORY: \"Vider l'inventaire\"\n  STR_AUTO_EQUIP: \"Equip. auto\"\n  STR_QUICK_SAVE: \"Sauvegarde rapide\"\n  STR_QUICK_LOAD: \"Chargement rapide\"\n  STR_ADVANCED: \"AVANCÉE\"\n  STR_AGGRESSIVERETALIATION: \"Représailles agressives\"\n  STR_AGGRESSIVERETALIATION_DESC: \"Tous les OVNIs tentent de détecter les bases X-Com, quelle que soit leur mission.\"\n  STR_STORAGELIMITSENFORCED: \"Stockage limité des objets récupérés\"\n  STR_STORAGELIMITSENFORCED_DESC: \"Outrepasse les limites imposées aux constructions de type Détention Extraterrestre ou Entrepôt lors de la phase de récupération (post mission) d'objets ou d'aliens vivants.\"\n  STR_CANSELLLIVEALIENS: \"Vente des aliens vivants\"\n  STR_CANSELLLIVEALIENS_DESC: \"Permet la vente des extraterrestres vivants. Recommandé avec l'utilisation de l'espace de détention limité.\"\n  STR_ALLOWBUILDINGQUEUE: \"Autoriser construction à la chaîne\"\n  STR_ALLOWBUILDINGQUEUE_DESC: \"Les nouvelles installations peuvent être positionnées par anticipation à proximité de celles en cours de construction.\"\n  STR_BATTLEAUTOEND: \"Fin de bataille automatique\"\n  STR_BATTLEAUTOEND_DESC: \"La bataille se termine automatiquement dès que le dernier ennemi est neutralisé.\"\n  STR_BATTLEINSTANTGRENADE: \"Grenades instantanées\"\n  STR_BATTLEINSTANTGRENADE_DESC: \"Les grenades sont armées sans délai et explosent immédiatement après avoir été lancées.\"\n  STR_BATTLEUFOEXTENDERACCURACY: \"Extension du mode de précision X-COM\"\n  STR_BATTLEUFOEXTENDERACCURACY_DESC: \"La précision du tir diminue avec la distance. Le niveau de précision est indiqué sur le curseur en fonction du type de tir.\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE: \"Transférer les vaisseaux en vol\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE_DESC: \"Assigner une nouvelle base à un vaisseau en vol.\"\n  STR_CRAFTLAUNCHALWAYS: \"Forcer le lancement des vaisseaux\"\n  STR_CRAFTLAUNCHALWAYS_DESC: \"Le vaisseau peut effectuer un décollage d'urgence même s'il n'est pas totalement ravitaillé voire réparé.\"\n  STR_CUSTOMINITIALBASE: \"Personnaliser la base initiale\"\n  STR_CUSTOMINITIALBASE_DESC: \"Vous permet de placer les installations librement lors de la création de votre première base.\"\n  STR_GLOBESEASONS: \"Jeux de lumière du globe réaliste\"\n  STR_GLOBESEASONS_DESC: \"Effets de lumière plus réalistes du Géoscape selon l'inclinaison axiale de la terre.\"\n  STR_PLAYINTRO: \"Séquence d'introduction\"\n  STR_PLAYINTRO_DESC: \"Joue la vidéo d'introduction, au démarrage du jeu.\"\n  STR_SHOWMORESTATSININVENTORYVIEW: \"Affichage statistiques supplémentaires\"\n  STR_SHOWMORESTATSININVENTORYVIEW_DESC: \"Certaines caractéristiques du soldat apparaissent sur l'écran d'inventaire.\"\n  STR_SNEAKYAI: \"IA furtive\"\n  STR_SNEAKYAI_DESC: \"L'adversaire IA évite d'évoluer à découvert.\"\n  STR_STRAFE: \"Autres méthodes de déplacement\"\n  STR_STRAFE_DESC: \"Active les mouvements spéciaux (pas latéral, sprint, rotation tourelle) lorsque la touche CTRL est enfoncée.\"\n  STR_BATTLEEXPLOSIONHEIGHT: \"Hauteur des explosions\"\n  STR_BATTLEEXPLOSIONHEIGHT_DESC: \"Change la hauteur et l'aire des explosions.{NEWLINE}(Plate: 0, Ronde: 3)\"\n  STR_AUTOSAVE: \"Sauvegarde automatique\"\n  STR_AUTOSAVE_DESC: \"Sauvegarde automatiquement un jeu selon l'intervalle spécifié. Ne s'applique pas au mode IronMan.\"\n  STR_AUTOSAVE_FREQUENCY: \"Fréquence sauvegarde auto\"\n  STR_AUTOSAVE_FREQUENCY_DESC: \"Nombre de tours entre deux sauvegardes automatiques\"\n  STR_ALLOWPSIONICCAPTURE: \"Victoire par psi-captures\"\n  STR_ALLOWPSIONICCAPTURE_DESC: \"Quand tous les extraterrestres vivants sont sous contrôle mental, la bataille se termine et ils sont considérés comme capturés.\"\n  STR_ANYTIMEPSITRAINING: \"Entraînement psionique à tout moment\"\n  STR_ANYTIMEPSITRAINING_DESC: \"Permet de gérer l'affectation des unités à l'entraînement psionique, et ce à n'importe quel instant dans le mois. Pour rappel, l'entraînement initial dure entre 30 et 60 jours.\"\n  STR_SKIPNEXTTURNSCREEN: \"Passer les écrans de fin de tour\"\n  STR_SKIPNEXTTURNSCREEN_DESC: \"Les écrans de fin de tour restent affichés quelques secondes puis disparaissent.\"\n  STR_NOT_ENOUGH_SPACE: \"Pas assez de place !\"\n  STR_WEAPONSELFDESTRUCTION: \"L'arme extraterrestre s'auto-détruit\"\n  STR_WEAPONSELFDESTRUCTION_DESC: \"Les armes portées par les extraterrestres se détruiront à la mort de leur possesseur, comme dans XCOM 2012.\"\n  STR_RETAINCORPSES: \"Conserver les aliens interrogés\"\n  STR_RETAINCORPSES_DESC: \"Après avoir \\\"recherché\\\" les aliens vivants les corps seront entreposés en stock, comme dans XCOM 2012.\"\n  STR_SAVE_VOXEL_VIEW: \"Sauvegarder une capture d'écran en mode à la première personne\"\n  STR_RESERVE_TIME_UNITS_FOR_KNEEL: \"UT réservées pour s'agenouiller\"\n  STR_EXPEND_ALL_TIME_UNITS: \"Dépenser les UT restantes\"\n  STR_PSISTRENGTHEVAL: \"Évaluation Psionique\"\n  STR_PSISTRENGTHEVAL_DESC: \"Évalue la force psionique de tous les soldats quand la recherche appropriée est terminée.\"\n  STR_DISABLEAUTOEQUIP: \"Désactiver auto-équipement\"\n  STR_DISABLEAUTOEQUIP_DESC: \"Désactiver l'auto-équipement des nouveaux soldats\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT: \"Autoriser l'amélioration de la force psionique.\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT_DESC: \"La force psionique des unités Xcom augmente avec l'expérience, mais peut aussi être améliorée par le biais de l'entraînement psionique.\"\n  STR_BATTLESMOOTHCAMERA: \"Caméra de poursuite pour les tirs\"\n  STR_BATTLESMOOTHCAMERA_DESC: \"Pendant un tir, la caméra reste centrée sur le projectile en vol.\"\n  STR_BATTLECONFIRMFIREMODE: \"Confirmation pour les tirs\"\n  STR_BATTLECONFIRMFIREMODE_DESC: \"Un deuxième clic sur la case sert à confirmer l'ordre de tir.\"\n  STR_SELECT_BASE_1: \"Sélectionner la Base 1\"\n  STR_SELECT_BASE_2: \"Sélectionner la Base 2\"\n  STR_SELECT_BASE_3: \"Sélectionner la Base 3\"\n  STR_SELECT_BASE_4: \"Sélectionner la Base 4\"\n  STR_SELECT_BASE_5: \"Sélectionner la Base 5\"\n  STR_SELECT_BASE_6: \"Sélectionner la Base 6\"\n  STR_SELECT_BASE_7: \"Sélectionner la Base 7\"\n  STR_SELECT_BASE_8: \"Sélectionner la Base 8\"\n  STR_VIDEO: \"VIDEO\"\n  STR_AUDIO: \"AUDIO\"\n  STR_BATTLESCAPE_UC: \"MODE TACTIQUE\"\n  STR_MODS_UC: \"MODs\"\n  STR_MODS: \"Mods\"\n  STR_DISPLAY_RESOLUTION: \"Résolution d'écran\"\n  STR_DISPLAY_RESOLUTION_DESC: \"Modifie la taille d'affichage, la résolution du jeu sera redéfinie en fonction. Les flèches font défiler les tailles prédéfinies. Cliquez pour saisir une taille personnalisée.\"\n  STR_ORIGINAL: \"Originale\"\n  STR_DISPLAY_MODE: \"Mode d'affichage\"\n  STR_WINDOWED: \"Fenêtré\"\n  STR_FULLSCREEN: \"Plein écran\"\n  STR_BORDERLESS: \"Sans bordures\"\n  STR_DISPLAY_LANGUAGE: \"Langue\"\n  STR_DISPLAY_LANGUAGE_DESC: \"Modifie la langue du contenu du jeu.\"\n  STR_DISPLAY_FILTER: \"Filtre graphique\"\n  STR_DISPLAY_FILTER_DESC: \"Choisit un filtre graphique qui s'applique à l'écran de jeu.{NEWLINE}*nécessite une accélaration matérielle OpenGL.\"\n  STR_DISPLAY_OPTIONS: \"Options d'affichage\"\n  STR_LETTERBOXED: \"Letterbox\"\n  STR_LETTERBOXED_DESC: \"Utilise des bandes noires pour conserver les proportions d'origine.\"\n  STR_RESIZABLE: \"Redimensionnable\"\n  STR_LOCK_MOUSE: \"Capturer souris\"\n  STR_LOCK_MOUSE_DESC: \"Empêche le curseur de la souris de sortir de l'écran de jeu. Crtl+G pour basculer à tout moment.\"\n  STR_FIXED_WINDOW_POSITION: \"Fenêtre fixe\"\n  STR_FIXED_WINDOW_POSITION_DESC: \"Définir les coordonnées Fenêtre\"\n  STR_DISPLAY_SET_WINDOW_POSITION: \"Définir nouvelles coordonnées de Fenêtre par défaut\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_X: \"Bord gauche / Valeur X :\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_Y: \"Bord haut / Valeur Y :\"\n  STR_MUSIC_VOLUME: \"Volume musique\"\n  STR_MUSIC_VOLUME_DESC: \"Modifie le volume de la musique d'ambiance.\"\n  STR_SFX_VOLUME: \"Volume bruitages\"\n  STR_SFX_VOLUME_DESC: \"Modifie le volume des effets sonores.\"\n  STR_UI_VOLUME: \"Volume bips\"\n  STR_UI_VOLUME_DESC: \"Modifie le volume des sons des menus.\"\n  STR_SCROLL_SPEED: \"Vitesse de défilement\"\n  STR_SCROLL_SPEED_GEO_DESC: \"Ajuster la vitesse de défilement du globe.\"\n  STR_SCROLL_SPEED_BATTLE_DESC: \"Modifie la vitesse de défilement de la carte.\"\n  STR_DOGFIGHT_SPEED: \"Vitesse combat aérien\"\n  STR_DOGFIGHT_SPEED_DESC: \"Modifie la vitesse des combats lors des interceptions d'OVNIs. Diminuer la vitesse améliore les performances.\"\n  STR_CLOCK_SPEED: \"Vitesse d'horloge\"\n  STR_CLOCK_SPEED_DESC: \"Modifie la vitesse de l'horloge du Géoscape. Diminuer la vitesse améliore les performances.\"\n  STR_GLOBE_DETAILS: \"Détails du globe\"\n  STR_GLOBE_COUNTRIES: \"Pays\"\n  STR_GLOBE_COUNTRIES_DESC: \"Affiche, sur le globe, les frontières des pays qui financent XCOM.\"\n  STR_GLOBE_RADARS: \"Radars\"\n  STR_GLOBE_RADARS_DESC: \"Affiche, sur le globe, la portée radar des bases.\"\n  STR_GLOBE_FLIGHT_PATHS: \"Plans de vol\"\n  STR_GLOBE_FLIGHT_PATHS_DESC: \"Affiche, sur le globe, le plan de vol des vaisseaux.\"\n  STR_CONTROLS_DESC: \"Clic gauche puis appuyer sur une touche pour assigner un raccourci.{NEWLINE}Clic droit pour le supprimer.\"\n  STR_BASE_GAME: \"Jeu de base\"\n  STR_MODS_TOOLTIP: \"Version {0} par {1}.{NEWLINE}{2}\"\n  STR_EDGE_SCROLL: \"Défilement bord écran\"\n  STR_EDGE_SCROLL_DESC: \"Déclencheur : Défilement du terrain quand le bouton gauche de la souris est maintenu enfoncé et le pointeur sur le bord de l'écran.{NEWLINE}Auto:  Défilement du terrain quand le pointeur de la souris est sur le bord de l'écran.\"\n  STR_TRIGGER_SCROLL: \"Sur clic souris\"\n  STR_AUTO_SCROLL: \"Sans clic\"\n  STR_DRAG_SCROLL: \"Bouton défilement\"\n  STR_DRAG_SCROLL_DESC: \"La carte défile quand on déplace la souris en maintenant ce bouton de souris appuyé.\"\n  STR_LEFT_MOUSE_BUTTON: \"Bouton gauche\"\n  STR_MIDDLE_MOUSE_BUTTON: \"Bouton milieu\"\n  STR_RIGHT_MOUSE_BUTTON: \"Bouton droit\"\n  STR_FIRE_SPEED: \"Vitesse de tir\"\n  STR_FIRE_SPEED_DESC: \"Modifie la vitesse des projectiles.\"\n  STR_PLAYER_MOVEMENT_SPEED: \"Vitesse unités XCOM\"\n  STR_PLAYER_MOVEMENT_SPEED_DESC: \"Modifie la vitesse de déplacement des unités contrôlées par le joueur.\"\n  STR_COMPUTER_MOVEMENT_SPEED: \"Vitesse unités IA\"\n  STR_COMPUTER_MOVEMENT_SPEED_DESC: \"Ajuste la vitesse de déplacement des unités contrôlées par l'IA.\"\n  STR_PATH_PREVIEW: \"Aperçu mouvement\"\n  STR_PATH_ARROWS: \"Flèches\"\n  STR_PATH_ARROWS_DESC: \"Affiche le chemin que l'unité s'apprête à suivre. La couleur indique les actions disponibles : Vert - peut se déplacer et tirer ; Jaune - peut se déplacer ; Rouge - trop loin.\"\n  STR_PATH_TIME_UNIT_COST: \"UTs\"\n  STR_PATH_TIME_UNIT_COST_DESC: \"Affiche les UT qui resteront après déplacement.\"\n  STR_USER_INTERFACE_OPTIONS: \"Options de l'interface\"\n  STR_TOOLTIPS: \"Info-bulles\"\n  STR_TOOLTIPS_DESC: \"Affiche des info-bulles pour les boutons de l'interface graphique de combat.\"\n  STR_DEATH_NOTIFICATIONS: \"Notifications de mort\"\n  STR_DEATH_NOTIFICATIONS_DESC: \"Recevoir une notification quand un soldat est tué.\"\n  STR_SHOW_FUNDS: \"Afficher trésorerie\"\n  STR_SHOW_FUNDS_DESC: \"Afficher la trésorerie à côté de l'horloge du Géoscape.\"\n  STR_MISSION_GENERATOR: \"GÉNÉRATEUR DE MISSION\"\n  STR_MAP_OPTIONS: \"OPTIONS CARTE\"\n  STR_ALIEN_OPTIONS: \"OPTIONS ALIEN\"\n  STR_MAP_TERRAIN: \"Terrain\"\n  STR_MAP_DARKNESS: \"Obscurité\"\n  STR_MAP_DEPTH: \"Profondeur\"\n  STR_DIFFICULTY: \"Difficulté\"\n  STR_ALIEN_RACE: \"Race\"\n  STR_ALIEN_TECH_LEVEL: \"Niveau de technologie\"\n  STR_RANDOMIZE: \"Aléatoire\"\n  STR_OXCE_REQUIRED_QUESTION: \"Ce mod requière OpenXcom {0} pour s'exécuter correctement. Activer ce mod ?\"\n  STR_RESTORE_DEFAULTS_QUESTION: \"Êtes-vous sûr de vouloir rétablir les réglages par défaut ?\"\n  STR_DISPLAY_OPTIONS_CONFIRM: \"Souhaitez-vous conserver les options d'affichage actuelles ?\"\n  STR_DISPLAY_OPTIONS_REVERT: \"Annulation dans 0:{0}\"\n  STR_MISSING_CONTENT_PROMPT: \"ATTENTION :{SMALLLINE}Cette sauvegarde utilise des mods qui ne sont plus disponibles. Le contenu manquant va être ignoré, mais le chargement peut échouer.{NEWLINE}Continuer ?\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT: \"Récupère les grenades amorcées\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT_DESC: \"Récupère les grenades amorcées avant la bataille et placées dans l'inventaire.\"\n  STR_NEWSEEDONLOAD: \"Chargement abusif de sauvegarde\"\n  STR_NEWSEEDONLOAD_DESC: \"Vous réinitialisez le générateur d'événements en chargeant une sauvegarde. Une action identique sera donc susceptible d'aboutir à un résultat différent. N'affecte pas le mode Ironman.\"\n  STR_CHANGEVALUEBYMOUSEWHEEL: \"Modifier les valeurs avec la molette souris\"\n  STR_CHANGEVALUEBYMOUSEWHEEL_DESC: \"Permet d'utiliser la molette de la souris pour augmenter ou diminuer les quantités.\"\n  STR_BATTLEHAIRBLEACH: \"Sprites des soldats améliorés\"\n  STR_BATTLEHAIRBLEACH_DESC: \"Modification des sprites du soldat en mode Tactique pour les assortir au menu inventaire.\"\n  STR_DRAGSCROLLINVERT: \"Inverse le défilement\"\n  STR_DRAGSCROLLINVERT_DESC: \"Lorsque cette option est activée, le défilement (via la molette de la souris) est inversé.\"\n  STR_BATTLESCAPE_SCALE: \"Résolution Tactique\"\n  STR_BATTLESCAPE_SCALE_DESC: \"Vue tactique mise à l'échelle, soit en résolution fixe (remplissage), soit sur un niveau de zoom (ajustement).\"\n  STR_GEOSCAPE_SCALE: \"Résolution Géoscape\"\n  STR_GEOSCAPESCALE_SCALE_DESC: \"Vue geoscape mise à l'échelle, soit en résolution fixe (remplissage), soit sur un niveau de zoom (ajustement).\"\n  STR_1_5X: \"Originale 1.5x\"\n  STR_2X: \"Originale 2x\"\n  STR_THIRD_DISPLAY: \"Écran 1/3\"\n  STR_HALF_DISPLAY: \"Écran 1/2\"\n  STR_FULL_DISPLAY: \"Plein Écran\"\n  STR_FPS_LIMIT: \"FPS maximum\"\n  STR_FPS_LIMIT_DESC: \"Limite de la fréquence de rafraîchissement, 0 pour illimité. Note : affecte uniquement les modes software (les modes OpenGL s'auto-régulent).\"\n  STR_FPS_INACTIVE_LIMIT: \"Limite de FPS en arrière plan\"\n  STR_FPS_INACTIVE_LIMIT_DESC: \"Restreint le nombre de rafraîchissements d'écran si OpenXcom s'exécute en tâche de fond.\"\n  STR_NOALIENPANICMESSAGES: \"Supprime l'affichage des E.T. paniqués\"\n  STR_NOALIENPANICMESSAGES_DESC: \"Les messages de panique concernant les extraterrestres s'afficheront seulement si ceux-ci sont dans le champ de vision d'une unité alliée.\"\n  STR_ALIENBLEEDING: \"Extraterrestre blessé\"\n  STR_ALIENBLEEDING_DESC: \"Rend la plupart des extraterrestres sensibles aux blessures\"\n  STR_FIELDPROMOTIONS: \"Champ d'Honneur\"\n  STR_FIELDPROMOTIONS_DESC: \"Seuls les soldats ayant participé à la dernière mission peuvent être promus.\"\n  STR_MEETINGPOINT: \"Prédire la trajectoire des OVNIs\"\n  STR_MEETINGPOINT_DESC: \"Les vaisseaux volent vers un point de rencontre avec l'OVNI estimé grâce à sa trajectoire actuelle.\"\n  STR_IRONMAN: \"IRONMAN\"\n  STR_IRONMAN_DESC: \"Pas de sauvegarde manuelle.\"\n  STR_SAVE_AND_ABANDON_GAME: \"SAUVEGARDER ET ABANDONNER LE JEU\"\n  STR_MOD_UNSUCCESSFUL: \"Le mod n'a pas pu être chargé.\"\n  STR_NEW_SAVED_GAME_SLOT: \"<NOUVELLE SAUVEGARDE>\"\n  STR_AUTO_SAVE_GEOSCAPE_SLOT: \"<GÉOSCAPE AUTO>\"\n  STR_AUTO_SAVE_BATTLESCAPE_SLOT: \"<MODE TACTIQUE AUTO>\"\n  STR_QUICK_SAVE_SLOT: \"<SAUVEGARDE RAPIDE>\"\n  STR_DISPLAY_MODE_DESC: \"Ajuster l'affichage du jeu sur l'écran.\"\n  STR_PREFERRED_MUSIC_FORMAT: \"Format de musique\"\n  STR_PREFERRED_MUSIC_FORMAT_DESC: \"Choisir un format musique par défaut lorsque plusieurs sont disponibles.{NEWLINE}NOTE : sur Windows le format MIDI peut être joué incorrectement.\"\n  STR_PREFERRED_SFX_FORMAT: \"Format des sons\"\n  STR_PREFERRED_SFX_FORMAT_DESC: \"Choisir un format de son par défaut lorsque plusieurs sont disponibles.\"\n  STR_PREFERRED_VIDEO_FORMAT: \"Format Vidéo\"\n  STR_PREFERRED_VIDEO_FORMAT_DESC: \"Sélectionne le format vidéo à utiliser quand plusieurs sont disponibles.\"\n  STR_PREFERRED_VIDEO_ANIMATION: \"Animation\"\n  STR_PREFERRED_VIDEO_SLIDESHOW: \"Diaporama\"\n  STR_PREFERRED_FORMAT_AUTO: \"Auto\"\n  STR_CURRENT_FORMAT: \"ACTUEL : {0}\"\n  STR_SOUND_OPTIONS: \"Options audio\"\n  STR_BACKGROUND_MUTE: \"Muet en arrière-plan\"\n  STR_BACKGROUND_MUTE_DESC: \"Désactive les sons lorsque la fenêtre de jeu n'est pas active.\"\n  STR_FORCE_FIRE: \"Outrepasser la Ligne de Tir\"\n  STR_FORCE_FIRE_DESC: \"En pressant simultanément CTRL, vous pourrez forcer vos unités à tirer, indépendamment des règles de Ligne de Tir.\"\n  STR_NO_AUDIO_HARDWARE_DETECTED: \"Aucune carte audio détectée !\"\n  STR_MOUSEWHEEL_SPEED: \"Vitesse de défilement (molette souris)\"\n  STR_MOUSEWHEEL_SPEED_DESC: \"Ajuste le nombre de lignes, par cran de rotation de la molette, lors du défilement des listes au moyen de la souris\"\n  STR_DISABLED: \"Désactivé(e)\"\n  STR_MAXIMIZE_INFO_SCREENS: \"Maximiser les écrans d'information\"\n  STR_MAXIMIZE_INFO_SCREENS_DESC: \"Différents écrans (dont l'inventaire) seront affichés en plein écran, indépendamment des paramètres d'échelle.\"\n  STR_DIARY: \"JOURNAL\"\n  STR_KILLED: \"TUÉ\"\n  STR_STUNNED: \"ASSOMMÉ\"\n  STR_PANICKED: \"PANIQUÉ\"\n  STR_MINDCONTROLLED: \"CONTRÔLÉ\"\n  STR_REGION_UNKNOWN: \"Non communiqué\"\n  STR_WEAPON_UNKNOWN: \"Improvisation\"\n  STR_UNKNOWN: \"Inconnu\"\n  STR_VICTORY: \"Victoire\"\n  STR_DEFEAT: \"Défaite\"\n  STR_NO_RECORD: \"Pas d'enregistrement\"\n  STR_HUMAN: \"Humain\"\n  STR_FRIENDLY: \"Amical\"\n  STR_HOSTILE: \"Hostile\"\n  STR_NEUTRAL: \"Neutre\"\n  STR_RATING_UC: \"CLASSEMENT\"\n  STR_LOCATION: \"EMPLACEMENT> {ALT}{0}\"\n  STR_DAYLIGHT_TYPE: \"TEMPS> {ALT}{0}\"\n  STR_RACE_TYPE: \"RACE> {ALT}{0}\"\n  STR_DAY: \"Jour\"\n  STR_NIGHT: \"Nuit\"\n  STR_DAYS_WOUNDED: \"JOURS BLESSÉ> {ALT}{0}\"\n  STR_COMBAT: \"COMBAT\"\n  STR_PERFORMANCE: \"PERFORMANCE\"\n  STR_NEUTRALIZATIONS_BY_RACE: \"NEUTRALISATION PAR RACE\"\n  STR_NEUTRALIZATIONS_BY_RANK: \"NEUTRALISATIONS PAR GRADE\"\n  STR_NEUTRALIZATIONS_BY_WEAPON: \"NEUTRALISATIONS PAR ARME\"\n  STR_MISSIONS_BY_LOCATION: \"MISSIONS PAR EMPLACEMENT\"\n  STR_MISSIONS_BY_TYPE: \"MISSIONS PAR TYPE\"\n  STR_MISSIONS_BY_UFO: \"MISSIONS PAR OVNI\"\n  STR_SCORE_VALUE: \"SCORE> {ALT}{0}\"\n  STR_WINS: \"VICTOIRES> {ALT}{0}\"\n  STR_STUNS: \"ASSOMMAGES> {ALT}{0}\"\n  STR_PANICKS: \"PANIQUES> {ALT}{0}\"\n  STR_MINDCONTROLS: \"CONTRÔLES> {ALT}{0}\"\n  STR_AWARDS: \"RÉCOMPENSES\"\n  STR_COMMENDATIONS_UC: \"DISTINCTIONS\"\n  STR_COMMENDATIONS: \"Distinctions\"\n  STR_MEDALS: \"MÉDAILLES\"\n  STR_LOST_IN_SERVICE: \"DISPARU EN SERVICE\"\n  STR_MEDAL_NAME: \"Nom de la Médaille\"\n  STR_MEDAL_AWARD_LEVEL: \"Niveau de Récompense\"\n  STR_MEDAL_DECOR_LEVEL: \"Niveau de Décoration\"\n  STR_AWARD_0: \"Première récompense\"\n  STR_AWARD_1: \"Seconde récompense\"\n  STR_AWARD_2: \"Troisième récompense\"\n  STR_AWARD_3: \"Quatrième récompense\"\n  STR_AWARD_4: \"Cinquième récompense\"\n  STR_AWARD_5: \"Sixième récompense\"\n  STR_AWARD_6: \"Septième récompense\"\n  STR_AWARD_7: \"Huitième récompense\"\n  STR_AWARD_8: \"Neuvième récompense\"\n  STR_AWARD_9: \"Dixième récompense\"\n  STR_AWARD_DECOR_0: \"Aucun\"\n  STR_AWARD_DECOR_1: \"Première broche de bronze\"\n  STR_AWARD_DECOR_2: \"Seconde broche de bronze\"\n  STR_AWARD_DECOR_3: \"Troisième broche de bronze\"\n  STR_AWARD_DECOR_4: \"Première broche d'argent\"\n  STR_AWARD_DECOR_5: \"Seconde broche d'argent\"\n  STR_AWARD_DECOR_6: \"Troisième broche d'argent\"\n  STR_AWARD_DECOR_7: \"Première broche d'or\"\n  STR_AWARD_DECOR_8: \"Seconde broche d'or\"\n  STR_AWARD_DECOR_9: \"Troisième broche d'or\"\n  STR_KILLED_IN_ACTION_MALE: \"MORT EN MISSION\"\n  STR_KILLED_IN_ACTION_FEMALE: \"MORTE EN MISSION\"\n  STR_MISSING_IN_ACTION_MALE: \"DISPARU EN MISSION\"\n  STR_MISSING_IN_ACTION_FEMALE: \"DISPARUE EN MISSION\"\n  STR_AVERAGE_MONTHLY_RATING: \"Score moyen mensuel\"\n  STR_TOTAL_INCOME: \"Revenus totaux\"\n  STR_TOTAL_EXPENDITURE: \"Totaux facturés\"\n  STR_MISSIONS_WON: \"Missions terminés\"\n  STR_MISSIONS_LOST: \"Échecs de missions\"\n  STR_NIGHT_MISSIONS: \"Missions de nuits\"\n  STR_BEST_RATING: \"Meilleur score de mission\"\n  STR_WORST_RATING: \"Pire score de mission \"\n  STR_ALIEN_KILLS: \"Extraterrestres tués\"\n  STR_ALIEN_CAPTURES: \"Extraterrestres capturés\"\n  STR_FRIENDLY_KILLS: \"Tirs accidentels sur alliés\"\n  STR_AVERAGE_ACCURACY: \"Précision moyenne\"\n  STR_WEAPON_MOST_KILLS: \"Arme la plus efficace\"\n  STR_ALIEN_MOST_KILLS: \"Extraterrestre le plus meurtrier\"\n  STR_LONGEST_SERVICE: \"Le plus long service\"\n  STR_TOTAL_DAYS_WOUNDED: \"Jours d'hospitalisation\"\n  STR_COUNTRIES_LOST: \"Pays infiltrés\"\n  STR_TOTAL_TERROR_SITES: \"Attaque terroristes\"\n  STR_TOTAL_BASES: \"Bases construites\"\n  STR_TOTAL_CRAFT: \"Appareils obtenus\"\n  STR_TOTAL_SCIENTISTS: \"Savants recrutés\"\n  STR_TOTAL_ENGINEERS: \"Ingénieurs recrutés\"\n  STR_TOTAL_RESEARCH: \"Recherches terminées\"\n  STR_DIARY_ACCURACY: \"PRÉCISION> {ALT}{0}%\"\n  STR_STATISTICS: \"Statistiques\"\n  STR_STATS: \"STATS\"\n  STR_TIME_UNITS_ABBREVIATION: \"UT\"\n  STR_STAMINA_ABBREVIATION: \"END\"\n  STR_HEALTH_ABBREVIATION: \"SAN\"\n  STR_BRAVERY_ABBREVIATION: \"COU\"\n  STR_REACTIONS_ABBREVIATION: \"RÉA\"\n  STR_FIRING_ACCURACY_ABBREVIATION: \"TIR\"\n  STR_THROWING_ACCURACY_ABBREVIATION: \"LAN\"\n  STR_STRENGTH_ABBREVIATION: \"FOR\"\n  STR_MELEE_ACCURACY_ABBREVIATION: \"MÊL\"\n  STR_FOLDERS: \"DOSSIERS\"\n  STR_DATA_FOLDER: \"Dossier de données (ressources originelles)\"\n  STR_USER_FOLDER: \"Dossier utilisateur (mods, openxcom.log)\"\n  STR_SAVE_FOLDER: \"Dossier de sauvegardes (sauvegardes, captures d'écran)\"\n  STR_CONFIG_FOLDER: \"Dossier de configuration (options.cfg)\"\n  STR_DATA_FOLDER_DESC_1: \"L'emplacement où OpenXcom recherche les ressources originels (XCOM et/ou TFTD)\"\n  STR_DATA_FOLDER_DESC_2: \"Les ressources internes de OpenXcom sont dans le dossier 'common'. Les mods intégrés sont dans le dossier 'standard'.\"\n  STR_USER_FOLDER_DESC: \"Le fichier de log ('openxcom.log') est stoqué ici. Tous les mods personnalisé doivent s'y trouver également (dans le sous-dossier 'mods').\"\n  STR_SAVE_FOLDER_DESC: \"Vos parties sauvegardées se trouveront ici. De plus, les paramètres du générateur de mission ('battle.cfg') s'y trouveront également.\"\n  STR_CONFIG_FOLDER_DESC: \"C'est ici que seront stockées les options de OpenXcom ('options.cfg). Normalement le même emplacement que le dossier utilisateur.\"\n"
  },
  {
    "path": "bin/common/Language/hr.yml",
    "content": "hr:\n  STR_OPENXCOM: \"OpenXcom\"\n  STR_NEW_GAME: \"Nova igra\"\n  STR_LOAD_SAVED_GAME: \"Učitaj Igru\"\n  STR_SELECT_DIFFICULTY_LEVEL: \"Izaberi Razinu Težine\"\n  STR_1_BEGINNER: \"1> Početnik / Početnica\"\n  STR_2_EXPERIENCED: \"2> Iskusan / Iskusna\"\n  STR_3_VETERAN: \"3>Veteran / Veteranka\"\n  STR_4_GENIUS: \"4> Genije\"\n  STR_5_SUPERHUMAN: \"5> Nadčovjek\"\n  STR_TIME: \"Vrijeme\"\n  STR_DATE: \"Datum\"\n  STR_SELECT_GAME_TO_LOAD: \"Izaberi igru za učitavanje\"\n  STR_SELECT_SAVE_POSITION: \"Izaberi gdje snimiti igru\"\n  STR_GAME_OPTIONS: \"IZBORNIK\"\n  STR_LOAD_GAME: \"UČITAJ IGRU\"\n  STR_SAVE_GAME: \"SNIMI IGRU\"\n  STR_ABANDON_GAME: \"NAPUSTI IGRU\"\n  STR_ABANDON_GAME_QUESTION: \"NAPUSTI IGRU?\"\n  STR_QUIT: \"Izlaz\"\n  STR_SAVING_GAME: \"Snimanje igre\"\n  STR_LOADING_GAME: \"Učitavanje igre\"\n  STR_NO_SAVED_GAME_PRESENT: \"Nema snimljene igre\"\n  STR_LOAD_UNSUCCESSFUL: \"Učitavanje neuspješno\"\n  STR_SAVE_UNSUCCESSFUL: \"Snimanje neuspješno\"\n  STR_LOAD_SUCCESSFUL: \"Učitavanje uspješno\"\n  STR_SAVE_SUCCESSFUL: \"Snimanje uspješno\"\n  STR_DELETE: \"IZBRIŠI\"\n  STR_DELETE_UNSUCCESSFUL: \"Brisanje neuspješno\"\n  STR_IS_IT_OK_TO_DELETE_THE_SAVED_GAME: \"Sigurno izbisati snimljenu igru?\"\n  STR_ORIGINAL_XCOM: \"Originalni X-Com\"\n  STR_LOADING: \"Učitavanje...\"\n  STR_DETAILS: \"DETALJI> {ALT}{0}\"\n  STR_NEW_BATTLE: \"Nova bitka\"\n  STR_OPTIONS: \"Opcije\"\n  STR_RIGHT_CLICK_TO_DELETE: \"Desni klik briše.\"\n  STR_RESTORE_DEFAULTS: \"Vrati zadane postavke\"\n  STR_CONTROLS: \"KONTROLE\"\n  STR_GENERAL: \"Općenito\"\n  STR_GEOSCAPE: \"Geoscape\"\n  STR_BATTLESCAPE: \"Battlescape\"\n  STR_SCREENSHOT: \"Snimka zaslona\"\n  STR_FPS_COUNTER: \"Brojilo slika po sekundi\"\n  STR_ROTATE_LEFT: \"Okreni nalijevo\"\n  STR_ROTATE_RIGHT: \"Okreni nadesno\"\n  STR_ROTATE_UP: \"Okreni prema gore\"\n  STR_ROTATE_DOWN: \"Okreni prema dolje\"\n  STR_ZOOM_IN: \"Zumiranje-povećanje\"\n  STR_ZOOM_OUT: \"Zumiranje-smanjenje\"\n  STR_TOGGLE_COUNTRY_DETAIL: \"Podesi Prikaz Detalja o Zemljama\"\n  STR_TOGGLE_RADAR_RANGES: \"Prikaži Domete Radara\"\n  STR_SCROLL_LEFT: \"Klizi Lijevo\"\n  STR_SCROLL_RIGHT: \"Klizi Desno\"\n  STR_SCROLL_UP: \"Klizi Gore\"\n  STR_SCROLL_DOWN: \"Klizi Dolje\"\n  STR_UNIT_LEVEL_ABOVE: \"Pomakni jedinicu na višu razinu\"\n  STR_UNIT_LEVEL_BELOW: \"Pomakni jedinicu na nižu razinu\"\n  STR_VIEW_LEVEL_ABOVE: \"Vidi razinu iznad\"\n  STR_VIEW_LEVEL_BELOW: \"Vidi razinu ispod\"\n  STR_CENTER_SELECTED_UNIT: \"Centriraj na izabranu jedinicu\"\n  STR_PREVIOUS_UNIT: \"Izaberi prethodnu jedinicu\"\n  STR_NEXT_UNIT: \"Izaberi iduću jedinicu\"\n  STR_DESELECT_UNIT: \"Nemoj ponovno izabrati jedinicu\"\n  STR_USE_LEFT_HAND: \"Upotrijebi predmet u lijevoj ruci\"\n  STR_USE_RIGHT_HAND: \"Upotrijebi predmet u desnoj ruci\"\n  STR_INVENTORY: \"Inventar\"\n  STR_MINIMAP: \"Mini mapa\"\n  STR_MULTI_LEVEL_VIEW: \"Višerazinski prikaz\"\n  STR_END_TURN: \"Kraj poteza\"\n  STR_ABORT_MISSION: \"Prekini misiju\"\n  STR_UNIT_STATS: \"Karakteristike jedinice\"\n  STR_KNEEL: \"Klekni/Ustani\"\n  STR_RELOAD: \"Napuni oružje\"\n  STR_TOGGLE_PERSONAL_LIGHTING: \"Uključi/Isključi osobno osvjetljenje\"\n  STR_DONT_RESERVE_TIME_UNITS: \"Ne čuvaj VJ\"\n  STR_RESERVE_TIME_UNITS_FOR_SNAP_SHOT: \"Čuvaj VJ za brzi hitac\"\n  STR_RESERVE_TIME_UNITS_FOR_AIMED_SHOT: \"Čuvaj VJ za ciljanu paljbu\"\n  STR_RESERVE_TIME_UNITS_FOR_AUTO_SHOT: \"Čuvaj VJ za rafalnu paljbu\"\n  STR_CENTER_ON_ENEMY_1: \"Centiraj na Neprijatelja 1\"\n  STR_CENTER_ON_ENEMY_2: \"Centiraj na Neprijatelja 2\"\n  STR_CENTER_ON_ENEMY_3: \"Centiraj na Neprijatelja 3\"\n  STR_CENTER_ON_ENEMY_4: \"Centiraj na Neprijatelja 4\"\n  STR_CENTER_ON_ENEMY_5: \"Centiraj na Neprijatelja 5\"\n  STR_CENTER_ON_ENEMY_6: \"Centiraj na Neprijatelja 6\"\n  STR_CENTER_ON_ENEMY_7: \"Centiraj na Neprijatelja 7\"\n  STR_CENTER_ON_ENEMY_8: \"Centiraj na Neprijatelja 8\"\n  STR_CENTER_ON_ENEMY_9: \"Centiraj na Neprijatelja 9\"\n  STR_CENTER_ON_ENEMY_10: \"Centiraj na Neprijatelja 10\"\n  STR_CREATE_INVENTORY_TEMPLATE: \"Stvori obrazac za inventar\"\n  STR_APPLY_INVENTORY_TEMPLATE: \"Primijeni obrazac za inventar\"\n  STR_CLEAR_INVENTORY: \"Očisti inventar\"\n  STR_QUICK_SAVE: \"Brzo snimanje\"\n  STR_QUICK_LOAD: \"Brzo učitavanje\"\n  STR_ADVANCED: \"NAPREDNO\"\n  STR_AGGRESSIVERETALIATION: \"Agresivna odmazda\"\n  STR_AGGRESSIVERETALIATION_DESC: \"NLO-i će uvijek pokušati pronaći igračeve baze, bez obzira na kojoj su misiji.\"\n  STR_STORAGELIMITSENFORCED: \"Zapljena materijala ograničena slobodnim prostorom u skladištu\"\n  STR_STORAGELIMITSENFORCED_DESC: \"Zarobljavanje živih izvanzemaljaca i zapljena predmeta s bojišta nisu moguće ako nema dovoljno slobodnog prostora u bazi.\"\n  STR_CANSELLLIVEALIENS: \"Prodaja živih izvanzemaljaca\"\n  STR_CANSELLLIVEALIENS_DESC: \"Dozvoljava prodaju živih izvanzemaljaca. Preporučeno ako su postavljena ograničenja na broj zatočenika.\"\n  STR_ALLOWBUILDINGQUEUE: \"Dozvoli red za izgradnju\"\n  STR_ALLOWBUILDINGQUEUE_DESC: \"Omogući gradnju novih prostorija pored onih koje su još u izgradnji.\"\n  STR_BATTLEAUTOEND: \"Automatsko završavanje bitke\"\n  STR_BATTLEAUTOEND_DESC: \"Bitke automatski završe nakon što je neutraliziran posljednji protivnik.\"\n  STR_BATTLEINSTANTGRENADE: \"Trenutno eksplodirajuće bombe\"\n  STR_BATTLEINSTANTGRENADE_DESC: \"Bombe podešene da eksplodiraju nakon 0 poteza, umjesto na kraju poteza, eksplodirat će odmah nakon što su bačene.\"\n  STR_BATTLEUFOEXTENDERACCURACY: \"Preciznost prema UFO Extenderu\"\n  STR_BATTLEUFOEXTENDERACCURACY_DESC: \"Preciznost hitaca postupno opada nakon određene udaljenosti, ovisno o vrsti hica. Podešena vjerojatnost pogotka biti će prikazana na pokazivaču.\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE: \"Transferi u zraku\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE_DESC: \"Moguće je transferirati letjelice koje su trenutno u zraku.\"\n  STR_CRAFTLAUNCHALWAYS: \"Lansiraj letjelice bez obzira na pripravnost\"\n  STR_CRAFTLAUNCHALWAYS_DESC: \"Moguće je lansirati letjelice čak i kada nisu spremne, bez obzira na potrebu za održavanjem.\"\n  STR_CUSTOMINITIALBASE: \"Podesi početnu bazu\"\n  STR_CUSTOMINITIALBASE_DESC: \"Pri početku novu igru, igrač ima priliku ručno odrediti položaj početnih prostorija umjesto korištenja zadanog rasporeda.\"\n  STR_GLOBESEASONS: \"Realistično globalno osvjetljenje\"\n  STR_GLOBESEASONS_DESC: \"Realističnija projekcija sunčeve svjetlosti u Geoscape-u s obzirom na nagib zemljine osi.\"\n  STR_PLAYINTRO: \"Prikaži uvodnu animaciju\"\n  STR_PLAYINTRO_DESC: \"Prikaži uvodni filmić pri pokretanju igre.\"\n  STR_SHOWMORESTATSININVENTORYVIEW: \"Dodatne informacije u inventaru\"\n  STR_SHOWMORESTATSININVENTORYVIEW_DESC: \"Dodatne informacije o izabranom vojniku biti će prikazane na njegvom inventaru\"\n  STR_SNEAKYAI: \"Oprezni protivnici\"\n  STR_SNEAKYAI_DESC: \"Protivnici kojima upravlja računalo nastojat će ostati izvan vidika igračevih jedinica kada god je to moguće.\"\n  STR_STRAFE: \"Alternativni načini kretanja\"\n  STR_STRAFE_DESC: \"Omogućava hodanje u stranu, trčanje i nezavisno pomicanje tenkovskih kupola pomoću pritiskanja tipke CTRL.\"\n  STR_BATTLEEXPLOSIONHEIGHT: \"Visina eksplozije\"\n  STR_BATTLEEXPLOSIONHEIGHT_DESC: \"Promijeni koliko se eksplozije mogu proširiti u visinu.{NEWLINE}(Ravne: 0, Okrugle: 3)\"\n  STR_AUTOSAVE: \"Automatsko snimanje\"\n  STR_AUTOSAVE_DESC: \"Automatski snima igru pri navedenim intervalima. Ne vrijedi za opciju \\\"Čovjek od Čelika\\\".\"\n  STR_AUTOSAVE_FREQUENCY: \"Učestalost automatskog snimanja\"\n  STR_AUTOSAVE_FREQUENCY_DESC: \"Broj poteza nakon čega će igra biti automatski snimljena.\"\n  STR_SKIPNEXTTURNSCREEN: \"Preskoči zaslon \\\"Idući Potez\\\"\"\n  STR_SKIPNEXTTURNSCREEN_DESC: \"Zasloni \\\"Idući Potez\\\" bit će automatski preskočeni nakon kratkog vremena.\"\n  STR_NOT_ENOUGH_SPACE: \"Nema dovoljno prostora!\"\n  STR_WEAPONSELFDESTRUCTION: \"Samouništenja izvanzemaljskog oružja\"\n  STR_WEAPONSELFDESTRUCTION_DESC: \"Izvanzemaljska oružja će se automatski uništiti ako pogine njihov korisnik, kao u XCOM 2012.\"\n  STR_SAVE_VOXEL_VIEW: \"Snimi sliku zaslona iz prvog lica\"\n  STR_RESERVE_TIME_UNITS_FOR_KNEEL: \"Čuvaj VJ za klečanje\"\n  STR_EXPEND_ALL_TIME_UNITS: \"Potroši sve preostale Vremenske jedinice\"\n  STR_DISABLEAUTOEQUIP: \"Onemogući automatsko opremanje\"\n  STR_DISABLEAUTOEQUIP_DESC: \"Onemogućuje automatsko opremanje novih vojnika prije bitke.\"\n  STR_BATTLECONFIRMFIREMODE: \"Potvrdi vrstu paljbe\"\n  STR_SELECT_BASE_1: \"Izaberi Bazu 1\"\n  STR_SELECT_BASE_2: \"Izaberi Bazu 2\"\n  STR_SELECT_BASE_3: \"Izaberi Bazu 3\"\n  STR_SELECT_BASE_4: \"Izaberi Bazu 4\"\n  STR_SELECT_BASE_5: \"Izaberi Bazu 5\"\n  STR_SELECT_BASE_6: \"Izaberi Bazu 6\"\n  STR_SELECT_BASE_7: \"Izaberi Bazu 7\"\n  STR_SELECT_BASE_8: \"Izaberi Bazu 8\"\n  STR_VIDEO: \"VIDEO\"\n  STR_AUDIO: \"AUDIO\"\n  STR_BATTLESCAPE_UC: \"BATTLESCAPE\"\n  STR_DISPLAY_RESOLUTION: \"Rezolucija\"\n  STR_ORIGINAL: \"Originalno\"\n  STR_DISPLAY_MODE: \"Oblik prikazivanja\"\n  STR_WINDOWED: \"U prozoru\"\n  STR_FULLSCREEN: \"Prikaz preko cijelog zaslona\"\n  STR_BORDERLESS: \"Bez granica\"\n  STR_DISPLAY_LANGUAGE: \"Prikaži jezik\"\n  STR_DISPLAY_LANGUAGE_DESC: \"Promijeni jezik teksta u igri.\"\n  STR_DISPLAY_FILTER: \"Filtriranje prikazivanja\"\n  STR_DISPLAY_FILTER_DESC: \"Promijeni filter kojeg igra primjenjuje na zaslon.{NEWLINE}*treba OpenGL hardversko ubrzanje.\"\n  STR_RESIZABLE: \"Promijenjiva veličina\"\n  STR_LOCK_MOUSE: \"Zadrži miša\"\n  STR_LOCK_MOUSE_DESC: \"Onemogućava pokazivač miša da napusti prozor igre. Ovo se može podesiti pritiskom Ctrl+G u bilo koje vrijeme.\"\n  STR_MUSIC_VOLUME: \"Glasnoća glazbe\"\n  STR_MUSIC_VOLUME_DESC: \"Promijeni glasnoću pozadinske glazbe.\"\n  STR_SFX_VOLUME: \"Glasnoća zvučnih efekata\"\n  STR_SFX_VOLUME_DESC: \"Mijenja glasnoću zvučnih efekata.\"\n  STR_UI_VOLUME: \"Glasnoća korisničkog sučelja\"\n  STR_UI_VOLUME_DESC: \"Mijenja glasnoću zvučnih signala / bipova korisničkog sučelja.\"\n  STR_SCROLL_SPEED: \"Brzina pomicanja\"\n  STR_SCROLL_SPEED_GEO_DESC: \"Mijenja brzinu pomicanja globusa.\"\n  STR_SCROLL_SPEED_BATTLE_DESC: \"Mijenja brzinu pomicanja mape.\"\n  STR_DOGFIGHT_SPEED: \"Brzina zračne borbe\"\n  STR_DOGFIGHT_SPEED_DESC: \"Mijenja brzinu borbi kada letjelice presreću NLO-e. Sporije brzine su obično pogodnije za slabija računala.\"\n  STR_CLOCK_SPEED: \"Brzina sata\"\n  STR_CLOCK_SPEED_DESC: \"Mijenja brzinu sata na Geoscapeu. Sporije brzine su obično pogodnije za slabija računala.\"\n  STR_GLOBE_DETAILS: \"Detalji na globusu\"\n  STR_GLOBE_COUNTRIES: \"Zemlje\"\n  STR_GLOBE_COUNTRIES_DESC: \"Pokazuje zemlje-sponzore na globusu.\"\n  STR_GLOBE_RADARS: \"Radar\"\n  STR_GLOBE_RADARS_DESC: \"Prikazuje domet radara u bazama na globusu\"\n  STR_GLOBE_FLIGHT_PATHS: \"Putanje leta\"\n  STR_GLOBE_FLIGHT_PATHS_DESC: \"Prikazuje putanje leta letjelica na globusu.\"\n  STR_CONTROLS_DESC: \"Lijevi klik i pritisak tipke na tipkovnici mijenja prečac.{NEWLINE}Desni klik na prečac ga onesposobljuje.\"\n  STR_MODS_TOOLTIP: \"Verzija {0} autor {1}.{NEWLINE}{2}\"\n  STR_TRIGGER_SCROLL: \"Aktivacija\"\n  STR_AUTO_SCROLL: \"Automatski\"\n  STR_DRAG_SCROLL: \"Klizi Povlačenjem Miša\"\n  STR_DRAG_SCROLL_DESC: \"Pomiče mapu kad je pritisnuta i povučena odgovarajuća tipka na mišu.\"\n  STR_LEFT_MOUSE_BUTTON: \"Lijevi gumb\"\n  STR_MIDDLE_MOUSE_BUTTON: \"Srednji gumb\"\n  STR_RIGHT_MOUSE_BUTTON: \"Desni gumb\"\n  STR_FIRE_SPEED: \"Brzina projektila\"\n  STR_FIRE_SPEED_DESC: \"Mijenja brzinu projektila.\"\n  STR_PLAYER_MOVEMENT_SPEED: \"Brzina micanja igračevih jedinica\"\n  STR_PLAYER_MOVEMENT_SPEED_DESC: \"Mijenja brzinu kretanja jedinica pod kontrolom igrača.\"\n  STR_COMPUTER_MOVEMENT_SPEED: \"Brzina kretanja protivnika\"\n  STR_COMPUTER_MOVEMENT_SPEED_DESC: \"Mijenja brzinu kretanja jedinica pod kontrolom računala.\"\n  STR_PATH_PREVIEW: \"Pregled puta\"\n  STR_PATH_ARROWS: \"Strelice\"\n  STR_PATH_ARROWS_DESC: \"Klik prikazuje put kojim će igračeva jedinica ići do odredišta. Boja označava raspoložive akcije: zelena - može micati i pucati; žuta - može micati; crvena - ne može micati.\"\n  STR_PATH_TIME_UNIT_COST: \"Vremenske jedinice\"\n  STR_PATH_TIME_UNIT_COST_DESC: \"Klik prikazuje preostale VJ koje će jedinica imati nakon što se dođe do odredišta.\"\n  STR_USER_INTERFACE_OPTIONS: \"Opcije korisničkog sučelja\"\n  STR_TOOLTIPS: \"Natuknice za gumbe\"\n  STR_TOOLTIPS_DESC: \"Prikazuje natuknice / tooltips za gumbe na Battlescape-u.\"\n  STR_DEATH_NOTIFICATIONS: \"Obavijesti o smrti\"\n  STR_DEATH_NOTIFICATIONS_DESC: \"Prikaži skočnu / popup notifikaciju kada pogine vojnik.\"\n  STR_SHOW_FUNDS: \"Prikaži sredstva\"\n  STR_SHOW_FUNDS_DESC: \"Prikazuje trenutno raspoloživa novčana sredstva pored sata na Geoscape-u.\"\n  STR_MISSION_GENERATOR: \"GENERATOR MISIJA\"\n  STR_MAP_OPTIONS: \"OPCIJE MAPE\"\n  STR_ALIEN_OPTIONS: \"OPCIJE IZVANZEMALJACA\"\n  STR_MAP_TERRAIN: \"Teren\"\n  STR_MAP_DARKNESS: \"Mrak\"\n  STR_MAP_DEPTH: \"Dubina\"\n  STR_DIFFICULTY: \"Težina\"\n  STR_ALIEN_RACE: \"Rasa\"\n  STR_ALIEN_TECH_LEVEL: \"Tehnološka razina\"\n  STR_RANDOMIZE: \"Randomiziraj / izaberi nasumce\"\n  STR_RESTORE_DEFAULTS_QUESTION: \"Sigurno vratiti izvorne opcije?\"\n  STR_DISPLAY_OPTIONS_CONFIRM: \"Želiš li zadržati trenutne postavke prikazivanja na zaslonu?\"\n  STR_DRAGSCROLLINVERT_DESC: \"Kada je upaljeno, povlačenje miša klizi u suprotnom smjeru od smjera povlačenja.\"\n  STR_BATTLESCAPE_SCALE_DESC: \"Model podešavanja skale Battlescapea, zasnovan na fiksnoj rezoluciji (rastegnuto da ispuni zaslon) ili fiksni nivo zumiranja (prošireno da popuni zaslnon).\"\n  STR_GEOSCAPESCALE_SCALE_DESC: \"Model podešavanja skale Geoscapea, zasnovan na fiksnoj rezoluciji (rastegnuto da ispuni zaslon) ili fiksni nivo zumiranja (prošireno da popuni zaslnon).\"\n  STR_FPS_LIMIT: \"Dopušteno slika u sekundi\"\n  STR_FPS_LIMIT_DESC: \"Ograničava broj ažuriranja zaslona u sekundi. 0 znači bez ograničenja. Ako je automatsko dovršavanje slike putem OpenGLa omogućeno, igra će umjesto toga koristiti Vsync.\"\n  STR_FPS_INACTIVE_LIMIT: \"Dopušteno slika u sekundi - pozadina\"\n  STR_FPS_INACTIVE_LIMIT_DESC: \"Ograničava broj obnavljanja ekrana po sekundi ako je OpenXcom program u pozadini.\"\n  STR_NOALIENPANICMESSAGES: \"Ne prikazuj poruke o izvanzemaljcima koji paničare\"\n  STR_NOALIENPANICMESSAGES_DESC: \"Ne prikazuj poruke o izvanzemaljcima koje je zahvatila panika, osim ako ih igrač vidi.\"\n  STR_ALIENBLEEDING: \"Krvarenje Izvanzemaljaca\"\n  STR_ALIENBLEEDING_DESC: \"Omogućava da se većini izvanzemaljaca nanesu smrtonosne rane.\"\n  STR_IRONMAN: \"ČOVJEK OD ČELIKA\"\n  STR_IRONMAN_DESC: \"Onemogući ručno snimanje igre\"\n  STR_SAVE_AND_ABANDON_GAME: \"SNIMI I NAPUSTI IGRU\"\n  STR_MOD_UNSUCCESSFUL: \"Učitavanje modifikacije neuspješno\"\n  STR_PREFERRED_MUSIC_FORMAT: \"Format Glazbe\"\n  STR_PREFERRED_SFX_FORMAT: \"Format Zvučnih Efekata\"\n  STR_PREFERRED_SFX_FORMAT_DESC: \"Izabiranje preferiranog formata zvučnih efekata u slučaju da ima više raspoloživih.\"\n  STR_PREFERRED_FORMAT_AUTO: \"Automatski\"\n  STR_CURRENT_FORMAT: \"Trenutačno: {0}\"\n  STR_FORCE_FIRE: \"Zanemari Pravila o Vatrenoj Liniji\"\n  STR_FORCE_FIRE_DESC: \"Omogućuje tvojim vojnicima da pucaju ako držiš pritisnutu tipku CTRL, bez obzira na pravila o vatrenoj liniji.\"\n  STR_MOUSEWHEEL_SPEED: \"Brzina klizanja pomoću kotačića miša\"\n  STR_MAXIMIZE_INFO_SCREENS: \"Uvećaj zaslone s informacijama\"\n  STR_MAXIMIZE_INFO_SCREENS_DESC: \"Zaslon za opremanje i drugi zasloni bit će prikazani na punom zaslonu bez obzira na postavke skale.\"\n  STR_AWARD_DECOR_0: \"Ništa\"\n"
  },
  {
    "path": "bin/common/Language/hu.yml",
    "content": "hu:\n  STR_OPENXCOM: \"OpenXcom\"\n  STR_NEW_GAME: \"Új játék\"\n  STR_LOAD_SAVED_GAME: \"Játék betöltése\"\n  STR_SELECT_DIFFICULTY_LEVEL: \"Válassz Nehézségi Szintet\"\n  STR_1_BEGINNER: \"1> Kezdő\"\n  STR_2_EXPERIENCED: \"2> Tapasztalt\"\n  STR_3_VETERAN: \"3> Veterán\"\n  STR_4_GENIUS: \"4> Zseni\"\n  STR_5_SUPERHUMAN: \"5> Emberfeletti\"\n  STR_TIME: \"Idő\"\n  STR_DATE: \"Dátum\"\n  STR_SELECT_GAME_TO_LOAD: \"Válaszd ki a betöltendő állást\"\n  STR_SELECT_SAVE_POSITION: \"Válassz egy helyet a mentésnek\"\n  STR_GAME_OPTIONS: \"JÁTÉKBEÁLLÍTÁSOK\"\n  STR_LOAD_GAME: \"JÁTÉK BETÖLTÉSE\"\n  STR_SAVE_GAME: \"JÁTÉK MENTÉSE\"\n  STR_ABANDON_GAME: \"JÁTÉK ELHAGYÁSA\"\n  STR_ABANDON_GAME_QUESTION: \"ABBAHAGYOD A JÁTÉKOT?\"\n  STR_QUIT: \"Kilépés\"\n  STR_SAVING_GAME: \"Játék mentése\"\n  STR_LOADING_GAME: \"Játék betöltése\"\n  STR_NO_SAVED_GAME_PRESENT: \"Nincs elmentett játék\"\n  STR_LOAD_UNSUCCESSFUL: \"Betöltés sikertelen\"\n  STR_SAVE_UNSUCCESSFUL: \"Elmentés sikertelen\"\n  STR_LOAD_SUCCESSFUL: \"Betöltés sikeres\"\n  STR_SAVE_SUCCESSFUL: \"Elmentés sikeres\"\n  STR_DELETE: \"TÖRLÉS\"\n  STR_DELETE_UNSUCCESSFUL: \"Törlés sikertelen\"\n  STR_IS_IT_OK_TO_DELETE_THE_SAVED_GAME: \"Biztosan törölni akarod a mentett játékot?\"\n  STR_ORIGINAL_XCOM: \"Eredeti X-Com\"\n  STR_LOADING: \"Betöltés...\"\n  STR_DETAILS: \"RÉSZLETEK> {ALT}{0}\"\n  STR_NEW_BATTLE: \"Új csata\"\n  STR_OPTIONS: \"Opciók\"\n  STR_RIGHT_CLICK_TO_DELETE: \"Jobb klikk a törléshez.\"\n  STR_RESTORE_DEFAULTS: \"Alapértékek visszaállítása\"\n  STR_CONTROLS: \"VEZÉRLÉS\"\n  STR_GENERAL: \"Általános\"\n  STR_GEOSCAPE: \"Földgömb\"\n  STR_BATTLESCAPE: \"Csatamező\"\n  STR_SCREENSHOT: \"Képernyőkép Mentése\"\n  STR_FPS_COUNTER: \"FPS Számláló\"\n  STR_ROTATE_LEFT: \"Forgatás Balra\"\n  STR_ROTATE_RIGHT: \"Forgatás Jobbra\"\n  STR_ROTATE_UP: \"Forgatás Fel\"\n  STR_ROTATE_DOWN: \"Forgatás Le\"\n  STR_ZOOM_IN: \"Közelítés\"\n  STR_ZOOM_OUT: \"Távolítás\"\n  STR_TOGGLE_COUNTRY_DETAIL: \"Kapcsoló: Országok Részletesen\"\n  STR_TOGGLE_RADAR_RANGES: \"Kapcsoló: Radar Hatókörök\"\n  STR_SCROLL_LEFT: \"Görgetés Balra\"\n  STR_SCROLL_RIGHT: \"Görgetés Jobbra\"\n  STR_SCROLL_UP: \"Görgetés Fel\"\n  STR_SCROLL_DOWN: \"Görgetés Le\"\n  STR_UNIT_LEVEL_ABOVE: \"Egység egy Szinttel feljebb mozgatása\"\n  STR_UNIT_LEVEL_BELOW: \"Egység egy Szinttel lejjebb mozgatása\"\n  STR_VIEW_LEVEL_ABOVE: \"Nézetet Egy Szinttel Fel\"\n  STR_VIEW_LEVEL_BELOW: \"Nézetet Egy Szinttel Le\"\n  STR_CENTER_SELECTED_UNIT: \"Kiválasztott Egységet Középre\"\n  STR_PREVIOUS_UNIT: \"Előző Egység\"\n  STR_NEXT_UNIT: \"Következő Egység\"\n  STR_DESELECT_UNIT: \"Ne válassza ki újra az egységet\"\n  STR_USE_LEFT_HAND: \"Bal kézben lévő eszközt használ\"\n  STR_USE_RIGHT_HAND: \"Jobb kézben lévő eszközt használ\"\n  STR_INVENTORY: \"Felszerelés\"\n  STR_MINIMAP: \"Mini-Térkép\"\n  STR_MULTI_LEVEL_VIEW: \"Többszintes Nézet\"\n  STR_END_TURN: \"Kör Befejezése\"\n  STR_ABORT_MISSION: \"Küldetés Megszakítása\"\n  STR_UNIT_STATS: \"Egység Tulajdonságai\"\n  STR_KNEEL: \"Térdelés\"\n  STR_RELOAD: \"Újratöltés\"\n  STR_TOGGLE_PERSONAL_LIGHTING: \"Kapcsoló: Személyi Világítás\"\n  STR_DONT_RESERVE_TIME_UNITS: \"Ne Tartson Fenn IE-eket\"\n  STR_RESERVE_TIME_UNITS_FOR_SNAP_SHOT: \"IE-ek Fenntartása Kapáslövésre\"\n  STR_RESERVE_TIME_UNITS_FOR_AIMED_SHOT: \"IE-ek Fenntartása Célzott Lövésre\"\n  STR_RESERVE_TIME_UNITS_FOR_AUTO_SHOT: \"IE-ek Fenntartása Auto. Lövésre\"\n  STR_CENTER_ON_ENEMY_1: \"Ellenség-1-et Középre\"\n  STR_CENTER_ON_ENEMY_2: \"Ellenség-2-t Középre\"\n  STR_CENTER_ON_ENEMY_3: \"Ellenség-3-at Középre\"\n  STR_CENTER_ON_ENEMY_4: \"Ellenség-4-et Középre\"\n  STR_CENTER_ON_ENEMY_5: \"Ellenség-5-öt Középre\"\n  STR_CENTER_ON_ENEMY_6: \"Ellenség-6-ot Középre\"\n  STR_CENTER_ON_ENEMY_7: \"Ellenség-7-et Középre\"\n  STR_CENTER_ON_ENEMY_8: \"Ellenség-8-at Középre\"\n  STR_CENTER_ON_ENEMY_9: \"Ellenség-9-et Középre\"\n  STR_CENTER_ON_ENEMY_10: \"Ellenség-10-et Középre\"\n  STR_CREATE_INVENTORY_TEMPLATE: \"Új felszerelés sablon\"\n  STR_APPLY_INVENTORY_TEMPLATE: \"Felszerelés sablon alkalmazása\"\n  STR_CLEAR_INVENTORY: \"Felszerelés törlése\"\n  STR_AUTO_EQUIP: \"Auto-felszerelés\"\n  STR_QUICK_SAVE: \"Gyorsmentés\"\n  STR_QUICK_LOAD: \"Gyorstöltés\"\n  STR_ADVANCED: \"HALADÓ\"\n  STR_AGGRESSIVERETALIATION: \"Aggresszív megtorlás\"\n  STR_AGGRESSIVERETALIATION_DESC: \"Az UFO-k - küldetésüktől függetlenül - minden alkalommal kíserletet tesznek a bázisod helyének kiderítésére.\"\n  STR_STORAGELIMITSENFORCED: \"Tárolási korlátok a begyűjtött tételekre\"\n  STR_STORAGELIMITSENFORCED_DESC: \"A küldetéseken begyűjtött élő idegenekre és szerkezetekre kikényszeríti az Idegen Tároló és a Raktár korlátait.\"\n  STR_CANSELLLIVEALIENS: \"Élő idegen eladhatósága\"\n  STR_CANSELLLIVEALIENS_DESC: \"Engedélyezi az élő idegenek eladását. Tárolási korlátok használata esetén javasolt.\"\n  STR_ALLOWBUILDINGQUEUE: \"Épület-emelés sorba állíthatósága\"\n  STR_ALLOWBUILDINGQUEUE_DESC: \"Új épületek építhetőek az el nem készültek mellé.\"\n  STR_BATTLEAUTOEND: \"Csata automatikus befejezése\"\n  STR_BATTLEAUTOEND_DESC: \"A csaták automatikusan befejeződnek, amint az utolsó élő ellenség is semlegesítve lesz.\"\n  STR_BATTLEINSTANTGRENADE: \"Azonnali gránátok\"\n  STR_BATTLEINSTANTGRENADE_DESC: \"A 0-ra időzített gránátok azonnal felrobbannak eldobást követően, ahelyett, hogy a kör végén robbannának.\"\n  STR_BATTLEUFOEXTENDERACCURACY: \"UFO Extender pontosság\"\n  STR_BATTLEUFOEXTENDERACCURACY_DESC: \"A lövések egy bizonyos távolság után pontatlanok lesznek a kiválasztott lövés-típusától függően. A pontosság a kurzornál fog majd megjelenni.\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE: \"Repülő jármű átcsoportosíthatósága\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE_DESC: \"Jelenleg levegőben lévő járművet át lehet csoportosítani.\"\n  STR_CRAFTLAUNCHALWAYS: \"Repülőgépek mindig elindíthatóak\"\n  STR_CRAFTLAUNCHALWAYS_DESC: \"A repülőgépek elindíthatóak akkor is, ha nem állnak még készen, felülírva a karbantartás szükségét.\"\n  STR_CUSTOMINITIALBASE: \"Egyéni kezdő-bázis\"\n  STR_CUSTOMINITIALBASE_DESC: \"Amikor új játékot indítasz, akkor egyesével helyezheted el a kezdő-épületeidet az alap elrendezés helyett.\"\n  STR_GLOBESEASONS: \"Valósághű bolygó megvilágítás\"\n  STR_GLOBESEASONS_DESC: \"Valósághűbb napfény kivetítést használ a Földgömbön a Föld tengelyferdeségének megfelelően.\"\n  STR_PLAYINTRO: \"Bevezető lejátszása\"\n  STR_PLAYINTRO_DESC: \"A bevezető képsorok mutatása indításkor.\"\n  STR_SHOWMORESTATSININVENTORYVIEW: \"Felszerelés adatok\"\n  STR_SHOWMORESTATSININVENTORYVIEW_DESC: \"A kiválasztott katonáról extra információkat mutat a felszerelés képernyőjén.\"\n  STR_SNEAKYAI: \"Sunyi MI\"\n  STR_SNEAKYAI_DESC: \"A Mesterséges Intelligencia - amikor csak lehetséges - elkerüli, hogy felfedje az egységeit a játékos számára.\"\n  STR_STRAFE: \"Alternatív mozgási lehetőségek\"\n  STR_STRAFE_DESC: \"Lehetővé teszi az oldalazást, futást, és a független tank-torony mozgatást a CTRL nyomvatartása mellett.\"\n  STR_BATTLEEXPLOSIONHEIGHT: \"Robbanások magassága\"\n  STR_BATTLEEXPLOSIONHEIGHT_DESC: \"Megváltoztatja a robbanások magassági terjedését.{NEWLINE}(Sima: 0, Kör: 3)\"\n  STR_AUTOSAVE: \"Automentés\"\n  STR_AUTOSAVE_DESC: \"Automatikus mentés rendszeres időközönként. Vasember módra nem vonatkozik.\"\n  STR_AUTOSAVE_FREQUENCY: \"Automatikus mentés gyakorisága\"\n  STR_AUTOSAVE_FREQUENCY_DESC: \"Hány körönként történjen automatikus mentés.\"\n  STR_ALLOWPSIONICCAPTURE: \"Pszi-elfogás engedélyezése\"\n  STR_ALLOWPSIONICCAPTURE_DESC: \"Az összes megmaradt élő idegen elmekontroll alá vonása a csata győzelmét eredményezi, és mindegyik élve elfogott idegennek számít.\"\n  STR_ANYTIMEPSITRAINING: \"Pszionikus képzés bármikor\"\n  STR_ANYTIMEPSITRAINING_DESC: \"A katonákat hónap közben bármikor beoszthatod pszionikus képzésre. Ne felejtsd, a kezdeti képzés 30-tól 60 napig tarthat.\"\n  STR_SKIPNEXTTURNSCREEN: \"\\\"Következő kör\\\" képernyő kihagyása\"\n  STR_SKIPNEXTTURNSCREEN_DESC: \"A \\\"Következő kör\\\" képernyők harc alatt kis várakozás után automatikusan továbblépnek.\"\n  STR_NOT_ENOUGH_SPACE: \"Nincs elég hely!\"\n  STR_WEAPONSELFDESTRUCTION: \"Idegen fegyverek önmegsemmisítése\"\n  STR_WEAPONSELFDESTRUCTION_DESC: \"Az idegenek fegyverei önmegsemmisítőek, mint az XCOM 2012-ben.\"\n  STR_RETAINCORPSES: \"Kihallgatott idegenek megtartása\"\n  STR_RETAINCORPSES_DESC: \"Az élő idegnek \\\"kivizsgálása\\\" után a testet a raktárhoz adja, úgy, mint az XCOM 2012-ben.\"\n  STR_SAVE_VOXEL_VIEW: \"Képernyőkép mentése az egység szemszögéből\"\n  STR_RESERVE_TIME_UNITS_FOR_KNEEL: \"Időegységek fenntartása térdelésre\"\n  STR_EXPEND_ALL_TIME_UNITS: \"A maradék Időegységek eldobása\"\n  STR_PSISTRENGTHEVAL: \"Pszi-Erősség kiértékelése\"\n  STR_PSISTRENGTHEVAL_DESC: \"Minden katona Pszionikus Erőssége kiértékelődik, miután a megfelelő kutatás befejeződött.\"\n  STR_DISABLEAUTOEQUIP: \"Auto-felszerelés letiltása\"\n  STR_DISABLEAUTOEQUIP_DESC: \"Új katonák csata előtti automata-felszerelését letiltja\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT: \"Pszi-Erősség fejlesztésének engedélyezése\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT_DESC: \"A katonák pszionikus erőssége tapasztalattal és gyakorlással fejleszthető.\"\n  STR_BATTLESMOOTHCAMERA: \"Folytonos lövedékkövetés\"\n  STR_BATTLESMOOTHCAMERA_DESC: \"A lövések útját folyamatosan a lövésekre fókuszálva követi végig a kamera a csaták során.\"\n  STR_BATTLECONFIRMFIREMODE: \"Tüzelés megerősítése mód\"\n  STR_BATTLECONFIRMFIREMODE_DESC: \"A csatamezőn egy második kattintás szükséges ugyanarra a mezőre a tüzelés megerősítéséhez.\"\n  STR_SELECT_BASE_1: \"1. Bázis kiválasztása\"\n  STR_SELECT_BASE_2: \"2. Bázis kiválasztása\"\n  STR_SELECT_BASE_3: \"3. Bázis kiválasztása\"\n  STR_SELECT_BASE_4: \"4. Bázis kiválasztása\"\n  STR_SELECT_BASE_5: \"5. Bázis kiválasztása\"\n  STR_SELECT_BASE_6: \"6. Bázis kiválasztása\"\n  STR_SELECT_BASE_7: \"7. Bázis kiválasztása\"\n  STR_SELECT_BASE_8: \"8. Bázis kiválasztása\"\n  STR_VIDEO: \"VIDEÓ\"\n  STR_AUDIO: \"HANG\"\n  STR_BATTLESCAPE_UC: \"CSATAMEZŐ\"\n  STR_MODS_UC: \"MODOK\"\n  STR_MODS: \"Modok\"\n  STR_DISPLAY_RESOLUTION: \"Kijelző Felbontása\"\n  STR_DISPLAY_RESOLUTION_DESC: \"A megjelenítés felbontását változtatja meg, a játék felbontása átméretezésre kerül, hogy egyezzen. A nyilak váltanak a támogatott felbontások között. Egyéni felbontáshoz kattints rá.\"\n  STR_ORIGINAL: \"Eredeti\"\n  STR_DISPLAY_MODE: \"Kijelző Mód\"\n  STR_WINDOWED: \"Ablakos\"\n  STR_FULLSCREEN: \"Teljesképernyős\"\n  STR_BORDERLESS: \"Szélek nélküli\"\n  STR_DISPLAY_LANGUAGE: \"Megjelenítés nyelve\"\n  STR_DISPLAY_LANGUAGE_DESC: \"A játékbeli szövegek nyelvét változtatja meg.\"\n  STR_DISPLAY_FILTER: \"Megjelenítő Szűrő\"\n  STR_DISPLAY_FILTER_DESC: \"A játék képernyőjére alkalmazott szűrőt változtatja meg.{NEWLINE}*Hardveres OpenGL gyorsítást igényel.\"\n  STR_DISPLAY_OPTIONS: \"Megjelenítési Opciók\"\n  STR_LETTERBOXED: \"Letterbox\"\n  STR_LETTERBOXED_DESC: \"Letterbox megjelenítés, hogy az eredeti képarány megmaradjon.\"\n  STR_RESIZABLE: \"Átméretezhető\"\n  STR_LOCK_MOUSE: \"Egér Megragadása\"\n  STR_LOCK_MOUSE_DESC: \"Megakadályozza, hogy az egérkurzor elhagyhassa a játék ablakát. Ki/Be kapcsolni bármikor: Ctrl+G\"\n  STR_FIXED_WINDOW_POSITION: \"Rögzített ablak pozíció\"\n  STR_FIXED_WINDOW_POSITION_DESC: \"Rögzített pozíció beállítása az ablak számára.\"\n  STR_DISPLAY_SET_WINDOW_POSITION: \"Add meg az ablak új gyökér pozícióját\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_X: \"Bal szegély új X:\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_Y: \"Felső szegély új Y:\"\n  STR_MUSIC_VOLUME: \"Zene hangerő\"\n  STR_MUSIC_VOLUME_DESC: \"A háttérzene hangerejét változtatja meg.\"\n  STR_SFX_VOLUME: \"Effektek hangerő\"\n  STR_SFX_VOLUME_DESC: \"A hangeffektek hangerejét változtatja meg.\"\n  STR_UI_VOLUME: \"FF Hangerő\"\n  STR_UI_VOLUME_DESC: \"A felhasználói felület pityegésének hangerejét változtatja meg.\"\n  STR_SCROLL_SPEED: \"Görgetési Sebesség\"\n  STR_SCROLL_SPEED_GEO_DESC: \"A Földgömb görgetési sebességét változtatja meg.\"\n  STR_SCROLL_SPEED_BATTLE_DESC: \"A térkép görgetési sebességét változtatja meg.\"\n  STR_DOGFIGHT_SPEED: \"Repülőharc Sebessége\"\n  STR_DOGFIGHT_SPEED_DESC: \"A repülőgépek és UFOk közötti légicsaták sebességét változtatja meg. Az alacsonyabb sebességek javíthatják a teljesítményt az alsó kategóriás eszközökön.\"\n  STR_CLOCK_SPEED: \"Óra Sebessége\"\n  STR_CLOCK_SPEED_DESC: \"A Földgömb órájának sebességét változtatja meg. Az alacsonyabb sebességek javíthatják a teljesítményt az alsó kategóriás eszközökön.\"\n  STR_GLOBE_DETAILS: \"Földgömb Beállítások\"\n  STR_GLOBE_COUNTRIES: \"Országok\"\n  STR_GLOBE_COUNTRIES_DESC: \"A támogató országokat mutatja a Földgömbön.\"\n  STR_GLOBE_RADARS: \"Radarok\"\n  STR_GLOBE_RADARS_DESC: \"A bázisok radarjainak hatótávjait mutatja a Földgömbön.\"\n  STR_GLOBE_FLIGHT_PATHS: \"Repülők Útvonala\"\n  STR_GLOBE_FLIGHT_PATHS_DESC: \"A repülőgépek repülési útvonalát mutatja a Földgömbön.\"\n  STR_CONTROLS_DESC: \"Megváltoztatáshoz bal egérgombbal kell kattintani egy sorra, majd egy billentyűt kell lenyomni.{NEWLINE}Kikapcsoláshoz jobb egérgombbal kell rákattintani.\"\n  STR_BASE_GAME: \"Alapjáték\"\n  STR_MODS_TOOLTIP: \"Verzió: {0} Készítő: {1}.{NEWLINE}{2}\"\n  STR_EDGE_SCROLL: \"Szegély Görgetés\"\n  STR_EDGE_SCROLL_DESC: \"Kézi: A térkép görgetése ha a bal egérgomb le van nyomva és a kurzor a képernyő szélén van.{NEWLINE}Automata: A térkép görgetése ha a kurzor a képernyő szélén van.\"\n  STR_TRIGGER_SCROLL: \"Kézi\"\n  STR_AUTO_SCROLL: \"Automata\"\n  STR_DRAG_SCROLL: \"Vonszoló Görgetés\"\n  STR_DRAG_SCROLL_DESC: \"A térképet görgeti, ha a meghatározott egérgomb le van nyomva és vonszoljuk.\"\n  STR_LEFT_MOUSE_BUTTON: \"Bal Egérgomb\"\n  STR_MIDDLE_MOUSE_BUTTON: \"Középső Egérgomb\"\n  STR_RIGHT_MOUSE_BUTTON: \"Jobb Egérgomb\"\n  STR_FIRE_SPEED: \"Tüzelési Sebesség\"\n  STR_FIRE_SPEED_DESC: \"A lőfegyverek lövedékeinek sebességét változtatja meg.\"\n  STR_PLAYER_MOVEMENT_SPEED: \"Játékos mozgási sebess.\"\n  STR_PLAYER_MOVEMENT_SPEED_DESC: \"A játékos által irányított egységek mozgási sebességét változtatja meg.\"\n  STR_COMPUTER_MOVEMENT_SPEED: \"MI mozgási sebessége\"\n  STR_COMPUTER_MOVEMENT_SPEED_DESC: \"A számítógép által irányított egységek mozgási sebességét változtatja meg.\"\n  STR_PATH_PREVIEW: \"Útvonal Előnézet\"\n  STR_PATH_ARROWS: \"Nyilak\"\n  STR_PATH_ARROWS_DESC: \"Egy kattintásra mutatja az egységed útvonalának előnézetét a választott célig. Szín jelöli a lehetséges műveleteket: Zöld - mozoghat és lőhet; Sárga - mozoghat; Piros - nem mozoghat.\"\n  STR_PATH_TIME_UNIT_COST: \"Időegység\"\n  STR_PATH_TIME_UNIT_COST_DESC: \"Egy kattintásra mutatja az egységed számára mozgás után megmaradó IE-eket.\"\n  STR_USER_INTERFACE_OPTIONS: \"Kezelőfelület Opciók\"\n  STR_TOOLTIPS: \"Tippek\"\n  STR_TOOLTIPS_DESC: \"Tippeket mutat a Csatamező gombjaihoz.\"\n  STR_DEATH_NOTIFICATIONS: \"Haláleset-értesítés\"\n  STR_DEATH_NOTIFICATIONS_DESC: \"Értesítő üzenet jelenik meg, valahányszor elhalálozik egy katonád.\"\n  STR_SHOW_FUNDS: \"Tőke mutatása\"\n  STR_SHOW_FUNDS_DESC: \"A jelenleg rendelkezésre álló tőke megjelenik az óra mellett.\"\n  STR_MISSION_GENERATOR: \"KÜLDETÉS GENERÁTOR\"\n  STR_MAP_OPTIONS: \"TÉRKÉP OPCIÓK\"\n  STR_ALIEN_OPTIONS: \"IDEGENEK OPCIÓI\"\n  STR_MAP_TERRAIN: \"Terep\"\n  STR_MAP_DARKNESS: \"Sötétség\"\n  STR_MAP_DEPTH: \"Mélység\"\n  STR_DIFFICULTY: \"Nehézség\"\n  STR_ALIEN_RACE: \"Faj\"\n  STR_ALIEN_TECH_LEVEL: \"Tech. Szint\"\n  STR_RANDOMIZE: \"Véletlenszerű\"\n  STR_OXCE_REQUIRED_QUESTION: \"Ennek a modnak a megfelelő működéséhez az OpenXcom {0} szükséges. Engedélyezed a modot?\"\n  STR_RESTORE_DEFAULTS_QUESTION: \"Biztos, hogy vissza akarod állítani az alapbeállításokat?\"\n  STR_DISPLAY_OPTIONS_CONFIRM: \"Meg akarod tartani a jelenlegi megjelenítési beállításokat?\"\n  STR_DISPLAY_OPTIONS_REVERT: \"Visszaállítás: 0:{0}\"\n  STR_MISSING_CONTENT_PROMPT: \"VIGYÁZAT:{SMALLLINE}Ez a mentés olyan modokra hivatkozik, amik nem elérhetők. A hivatkozások törlődni fognak, a mentés pedig nem biztos, hogy betöltődik.{NEWLINE}Mehet?\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT: \"Előre időzített gránátok mentése\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT_DESC: \"Elmenti a csata előtt beállított gránát-időzítéseket a katonák felszerelés-elrendezésébe.\"\n  STR_NEWSEEDONLOAD: \"Mentéssel visszaélés\"\n  STR_NEWSEEDONLOAD_DESC: \"Egy játék betöltése átállítja a találomszám-generátort (random seed), így ugyanazon művelet mindig mást eredményezhet. Vasember módra nem vonatkozik.\"\n  STR_CHANGEVALUEBYMOUSEWHEEL: \"Értékváltoztatás az egérgörgővel\"\n  STR_CHANGEVALUEBYMOUSEWHEEL_DESC: \"Lehetővé teszi, hogy az egérgörgőt használd egyes értékek növelésére/csökkentésére, a beállított mennyiséggel.\"\n  STR_BATTLEHAIRBLEACH: \"Fejlettebb képek a katonákról\"\n  STR_BATTLEHAIRBLEACH_DESC: \"Megváltoztatja a csatamezőn a katonák képeit, hogy egyezzenek a felszerelési kinézetükkel.\"\n  STR_DRAGSCROLLINVERT: \"Fordított vonszoló-görgetés\"\n  STR_DRAGSCROLLINVERT_DESC: \"Ha be van kapcsolva, akkor a Vonszoló Görgetés az egérmozgatással ellentétes irányban történik.\"\n  STR_BATTLESCAPE_SCALE: \"Csatamező Skálázás\"\n  STR_BATTLESCAPE_SCALE_DESC: \"A Csatamező nézet skálázási módja, mely egy fix felbontáson alapszik (méretre nyújtja), vagy egy fix nagyítási szinten (kiegészíti a széleket).\"\n  STR_GEOSCAPE_SCALE: \"Földgömb Skálázás\"\n  STR_GEOSCAPESCALE_SCALE_DESC: \"A Földgömb nézet skálázási módja, mely egy fix felbontáson alapszik (méretre nyújtja), vagy egy fix nagyítási szinten (kiegészíti a széleket).\"\n  STR_1_5X: \"1.5x Eredeti\"\n  STR_2X: \"2x Eredeti\"\n  STR_THIRD_DISPLAY: \"1/3 Megjelenítés\"\n  STR_HALF_DISPLAY: \"1/2 Megjelenítés\"\n  STR_FULL_DISPLAY: \"Teljes Megjelenítés\"\n  STR_FPS_LIMIT: \"FPS korlát\"\n  STR_FPS_LIMIT_DESC: \"A másodpercenkénti képfrissítések számát korlátozza, 0 a korlátlanság. Ha az OpenGL renderelés be van kapcsolva, a játék a Vsync-et használja helyette.\"\n  STR_FPS_INACTIVE_LIMIT: \"FPS korlát háttérben\"\n  STR_FPS_INACTIVE_LIMIT_DESC: \"A képfrissítések másodpercenkénti korlátja amikor az OpenXcom a háttérben fut.\"\n  STR_NOALIENPANICMESSAGES: \"Pánik üzenetek elnyomása az idegeneknél\"\n  STR_NOALIENPANICMESSAGES_DESC: \"Ne mutasson pánik üzeneteket az idegenekre, hacsak nem látható az idegen a játékos számára.\"\n  STR_ALIENBLEEDING: \"Idegenek elvérzése\"\n  STR_ALIENBLEEDING_DESC: \"Engedélyezi, hogy a legtöbb idegenre hatással legyenek a végzetes sebek.\"\n  STR_FIELDPROMOTIONS: \"Harctéri előléptetések\"\n  STR_FIELDPROMOTIONS_DESC: \"Csak a küldetésben részt vett katonák kaphatnak előléptetést.\"\n  STR_MEETINGPOINT: \"UFO röppályájának megbecslése\"\n  STR_MEETINGPOINT_DESC: \"A repülőgépek az UFO-val együtt, annak aktuális röppályája alapján, egy közös találkozási pont felé haladnak.\"\n  STR_IRONMAN: \"VASEMBER\"\n  STR_IRONMAN_DESC: \"Nincs kézi mentési lehetőség\"\n  STR_SAVE_AND_ABANDON_GAME: \"JÁTÉK MENTÉSE ÉS ELHAGYÁSA\"\n  STR_MOD_UNSUCCESSFUL: \"Mod betöltése sikertelen\"\n  STR_NEW_SAVED_GAME_SLOT: \"<ÚJ MENTETT JÁTÉK>\"\n  STR_AUTO_SAVE_GEOSCAPE_SLOT: \"<FÖLDGÖMB AUTOMENTÉS>\"\n  STR_AUTO_SAVE_BATTLESCAPE_SLOT: \"<CSATAMEZŐ AUTOMENTÉS>\"\n  STR_QUICK_SAVE_SLOT: \"<GYORSMENTÉS>\"\n  STR_DISPLAY_MODE_DESC: \"Megváltoztatja, hogy a játék hogyan jelenik meg a képernyőn.\"\n  STR_PREFERRED_MUSIC_FORMAT: \"Zene Formátum\"\n  STR_PREFERRED_MUSIC_FORMAT_DESC: \"Az előnyben részesített zene formátumot választja amikor többféle áll rendelkezésre.{NEWLINE}MEGJEGYZÉS: A MIDI lejátszása hibás (bugos) lehet Windows-on.\"\n  STR_PREFERRED_SFX_FORMAT: \"Hangeffekt Formátum\"\n  STR_PREFERRED_SFX_FORMAT_DESC: \"Az előnyben részesített hangeffekt formátumot választja amikor többféle áll rendelkezésre.\"\n  STR_PREFERRED_VIDEO_FORMAT: \"Videó Formátum\"\n  STR_PREFERRED_VIDEO_FORMAT_DESC: \"Az előnyben részesített videó formátumot választja, amikor többféle lehetőség áll rendelkezésre.\"\n  STR_PREFERRED_VIDEO_ANIMATION: \"Animáció\"\n  STR_PREFERRED_VIDEO_SLIDESHOW: \"Diasor\"\n  STR_PREFERRED_FORMAT_AUTO: \"Automatikus\"\n  STR_CURRENT_FORMAT: \"Jelenleg: {0}\"\n  STR_SOUND_OPTIONS: \"Hangbeállítások\"\n  STR_BACKGROUND_MUTE: \"Némítás a háttérben\"\n  STR_BACKGROUND_MUTE_DESC: \"Minden hangot elnémít, ha a játékablak nem aktív.\"\n  STR_FORCE_FIRE: \"Tűzvonal felülbírálása\"\n  STR_FORCE_FIRE_DESC: \"Lehetővé teszi a katonáid számára, - CTRL nyomvatartása mellett - hogy lőjenek tekintet nélkül a tűzvonal szabályaira.\"\n  STR_NO_AUDIO_HARDWARE_DETECTED: \"Hangeszköz nem található\"\n  STR_MOUSEWHEEL_SPEED: \"Egérgörgő görgetési sebessége\"\n  STR_MOUSEWHEEL_SPEED_DESC: \"Az egérgörgővel görgetendő sorok mennyiségét állítja. (Listák esetén)\"\n  STR_DISABLED: \"Kikapcsolva\"\n  STR_MAXIMIZE_INFO_SCREENS: \"Info képernyők maximalizálása\"\n  STR_MAXIMIZE_INFO_SCREENS_DESC: \"A felszerelés és más különféle képernyők teljes képernyőn jelennek meg, a skálázási beállításoktól függetlenül.\"\n  STR_DIARY: \"NAPLÓ\"\n  STR_KILLED: \"HALOTT\"\n  STR_STUNNED: \"ELKÁBÍTVA\"\n  STR_PANICKED: \"PÁNIKOL\"\n  STR_MINDCONTROLLED: \"IRÁNYÍTÁS ALATT\"\n  STR_REGION_UNKNOWN: \"Nem közölt\"\n  STR_WEAPON_UNKNOWN: \"Rögtönzés\"\n  STR_UNKNOWN: \"Ismeretlen\"\n  STR_VICTORY: \"Győzelem\"\n  STR_DEFEAT: \"Vereség\"\n  STR_NO_RECORD: \"Nincs feljegyzés\"\n  STR_HUMAN: \"Ember\"\n  STR_FRIENDLY: \"Barát\"\n  STR_HOSTILE: \"Ellenséges\"\n  STR_NEUTRAL: \"Semleges\"\n  STR_RATING_UC: \"BESOROLÁS\"\n  STR_LOCATION: \"HELYSZÍN>{ALT}{0}\"\n  STR_DAYLIGHT_TYPE: \"IDŐ> {ALT}{0}\"\n  STR_RACE_TYPE: \"FAJ> {ALT}{0}\"\n  STR_DAY: \"Nappal\"\n  STR_NIGHT: \"Éjszaka\"\n  STR_DAYS_WOUNDED: \"SÉRÜLT NAPOK> {ALT}{0}\"\n  STR_COMBAT: \"HARC\"\n  STR_PERFORMANCE: \"TELJESÍTÉS\"\n  STR_NEUTRALIZATIONS_BY_RACE: \"SEMLEGESÍTÉS FAJOK SZERINT\"\n  STR_NEUTRALIZATIONS_BY_RANK: \"SEMLEGESÍTÉS RANG SZERINT\"\n  STR_NEUTRALIZATIONS_BY_WEAPON: \"SEMLEGESÍTÉS FEGYVER SZERINT\"\n  STR_MISSIONS_BY_LOCATION: \"Küldetések helyszín szerint\"\n  STR_MISSIONS_BY_TYPE: \"Küldetések típus szerint\"\n  STR_MISSIONS_BY_UFO: \"Küldetések UFO szerint\"\n  STR_SCORE_VALUE: \"PONTSZÁM>{ALT}{0}\"\n  STR_WINS: \"GYŐZELMEK> {ALT}{0}\"\n  STR_STUNS: \"ELKÁBÍTÁSOK> {ALT}{0}\"\n  STR_PANICKS: \"BEPÁNIKOLÁSOK> {ALT}{0}\"\n  STR_MINDCONTROLS: \"ÁTVETT IRÁNYÍTÁSOK> {ALT}{0}\"\n  STR_AWARDS: \"DÍJAK\"\n  STR_COMMENDATIONS_UC: \"ELISMERÉSEK\"\n  STR_COMMENDATIONS: \"Elismerések\"\n  STR_MEDALS: \"KITÜNTETÉSEK\"\n  STR_LOST_IN_SERVICE: \"SZOLGÁLATBAN ELHUNYT\"\n  STR_MEDAL_NAME: \"Kitüntetés neve\"\n  STR_MEDAL_AWARD_LEVEL: \"Díj szintje\"\n  STR_MEDAL_DECOR_LEVEL: \"Dekoráltsági szint\"\n  STR_AWARD_0: \"Első díj\"\n  STR_AWARD_1: \"Második díj\"\n  STR_AWARD_2: \"Harmadik díj\"\n  STR_AWARD_3: \"Negyedik díj\"\n  STR_AWARD_4: \"Ötödik díj\"\n  STR_AWARD_5: \"Hatodik díj\"\n  STR_AWARD_6: \"Hetedik díj\"\n  STR_AWARD_7: \"Nyolcadik díj\"\n  STR_AWARD_8: \"Kilencedik díj\"\n  STR_AWARD_9: \"Tizedik díj\"\n  STR_AWARD_DECOR_0: \"Nincs\"\n  STR_AWARD_DECOR_1: \"Első bronz jelzés\"\n  STR_AWARD_DECOR_2: \"Második bronz jelzés\"\n  STR_AWARD_DECOR_3: \"Harmadik bronz jelzés\"\n  STR_AWARD_DECOR_4: \"Első ezüst jelzés\"\n  STR_AWARD_DECOR_5: \"Második ezüst jelzés\"\n  STR_AWARD_DECOR_6: \"Harmadik ezüst jelzés\"\n  STR_AWARD_DECOR_7: \"Első arany jelzés\"\n  STR_AWARD_DECOR_8: \"Második arany jelzés\"\n  STR_AWARD_DECOR_9: \"Harmadik arany jelzés\"\n  STR_KILLED_IN_ACTION_MALE: \"BEVETÉS SORÁN MEGHALT\"\n  STR_KILLED_IN_ACTION_FEMALE: \"BEVETÉS SORÁN MEGHALT\"\n  STR_MISSING_IN_ACTION_MALE: \"BEVETÉS SORÁN ELTŰNT\"\n  STR_MISSING_IN_ACTION_FEMALE: \"BEVETÉS SORÁN ELTŰNT\"\n  STR_AVERAGE_MONTHLY_RATING: \"Átlagos havi értékelés\"\n  STR_TOTAL_INCOME: \"Teljes bevétel\"\n  STR_TOTAL_EXPENDITURE: \"Teljes kiadás\"\n  STR_MISSIONS_WON: \"Teljesített küldetés\"\n  STR_MISSIONS_LOST: \"Elbukott küldetés\"\n  STR_NIGHT_MISSIONS: \"Éjszakai küldetések\"\n  STR_BEST_RATING: \"Legjobb küldetés értékelése\"\n  STR_WORST_RATING: \"Legrosszabb küldetés értékelése\"\n  STR_ALIEN_KILLS: \"Idegen megölve\"\n  STR_ALIEN_CAPTURES: \"Idegen elfogva\"\n  STR_FRIENDLY_KILLS: \"Barátságos tűz incidensek\"\n  STR_AVERAGE_ACCURACY: \"Átlagos pontosság\"\n  STR_WEAPON_MOST_KILLS: \"Leghatékonyabb fegyver\"\n  STR_ALIEN_MOST_KILLS: \"Leghalálosabb idegen\"\n  STR_LONGEST_SERVICE: \"Legtöbb hónap szolgálatban\"\n  STR_TOTAL_DAYS_WOUNDED: \"Betegszabadság\"\n  STR_COUNTRIES_LOST: \"Beszivárgás az országokba\"\n  STR_TOTAL_TERROR_SITES: \"Terror támadások\"\n  STR_TOTAL_BASES: \"Épített bázisok\"\n  STR_TOTAL_CRAFT: \"Birtokolt repülőgépek\"\n  STR_TOTAL_SCIENTISTS: \"Tudós felvéve\"\n  STR_TOTAL_ENGINEERS: \"Mérnök felvéve\"\n  STR_TOTAL_RESEARCH: \"Kutatás befejezve\"\n  STR_DIARY_ACCURACY: \"PONTOSSÁG> {ALT}{0}%\"\n  STR_STATISTICS: \"Statisztikák\"\n  STR_STATS: \"STATOK\"\n  STR_TIME_UNITS_ABBREVIATION: \"IE\"\n  STR_STAMINA_ABBREVIATION: \"ÁLL\"\n  STR_HEALTH_ABBREVIATION: \"EP\"\n  STR_BRAVERY_ABBREVIATION: \"BÁT\"\n  STR_REACTIONS_ABBREVIATION: \"REA\"\n  STR_FIRING_ACCURACY_ABBREVIATION: \"PTS\"\n  STR_THROWING_ACCURACY_ABBREVIATION: \"DOB\"\n  STR_STRENGTH_ABBREVIATION: \"ERŐ\"\n  STR_MELEE_ACCURACY_ABBREVIATION: \"KÖZ\"\n  STR_FOLDERS: \"MAPPÁK\"\n  STR_DATA_FOLDER: \"Adatmappa (eredeti erőforrások)\"\n  STR_USER_FOLDER: \"Felhasználói mappa (modok, openxcom.log)\"\n  STR_SAVE_FOLDER: \"Mentések mappája (mentett játékok, képernyőképek)\"\n  STR_CONFIG_FOLDER: \"Konfigurációs mappa (options.cfg)\"\n  STR_DATA_FOLDER_DESC_1: \"Ez az a hely, ahol az OpenXcom keresi az eredeti játékerőforrásokat (UFO és/vagy TFTD).\"\n  STR_DATA_FOLDER_DESC_2: \"Az OpenXcom belső erőforrásai a 'common' mappában találhatók. Az OpenXcom beépített modjai a 'standard' mappában találhatók.\"\n  STR_USER_FOLDER_DESC: \"A naplófájl ('openxcom.log') itt található. Az összes egyedi mod is ide kerül (a 'mods' almappába).\"\n  STR_SAVE_FOLDER_DESC: \"A mentett játékaid itt találhatók. A küldetésgenerátor beállításai ('battle.cfg') is itt találhatók.\"\n  STR_CONFIG_FOLDER_DESC: \"Itt találhatók az OpenXcom beállításai (‘options.cfg’), ami általában megegyezik a ‘Felhasználói mappával’.\"\n"
  },
  {
    "path": "bin/common/Language/it.yml",
    "content": "it:\n  STR_OPENXCOM: \"OpenXcom\"\n  STR_NEW_GAME: \"Nuova Partita\"\n  STR_LOAD_SAVED_GAME: \"Carica Partita\"\n  STR_SELECT_DIFFICULTY_LEVEL: \"Seleziona Livello di Difficoltà\"\n  STR_1_BEGINNER: \"1> Principiante\"\n  STR_2_EXPERIENCED: \"2> Esperto\"\n  STR_3_VETERAN: \"3> Veterano\"\n  STR_4_GENIUS: \"4> Genio\"\n  STR_5_SUPERHUMAN: \"5> Superuomo\"\n  STR_TIME: \"Ora\"\n  STR_DATE: \"Data\"\n  STR_SELECT_GAME_TO_LOAD: \"Seleziona partita da caricare\"\n  STR_SELECT_SAVE_POSITION: \"Seleziona posizione di salvataggio\"\n  STR_GAME_OPTIONS: \"OPZIONI DI GIOCO\"\n  STR_LOAD_GAME: \"CARICA PARTITA\"\n  STR_SAVE_GAME: \"SALVA PARTITA\"\n  STR_ABANDON_GAME: \"ABBANDONA PARTITA\"\n  STR_ABANDON_GAME_QUESTION: \"ABBANDONARE PARTITA?\"\n  STR_QUIT: \"Esci\"\n  STR_SAVING_GAME: \"Salvataggio\"\n  STR_LOADING_GAME: \"Caricamento\"\n  STR_NO_SAVED_GAME_PRESENT: \"Nessuna partita salvata\"\n  STR_LOAD_UNSUCCESSFUL: \"Caricamento non riuscito\"\n  STR_SAVE_UNSUCCESSFUL: \"Salvataggio non riuscito\"\n  STR_LOAD_SUCCESSFUL: \"Caricamento riuscito\"\n  STR_SAVE_SUCCESSFUL: \"Salvataggio riuscito\"\n  STR_DELETE: \"ELIMINARE\"\n  STR_DELETE_UNSUCCESSFUL: \"Eliminazione non riuscita\"\n  STR_IS_IT_OK_TO_DELETE_THE_SAVED_GAME: \"Sei sicuro di voler eliminare la partita salvata?\"\n  STR_ORIGINAL_XCOM: \"X-Com Originale\"\n  STR_LOADING: \"Caricamento...\"\n  STR_DETAILS: \"DETTAGLI> {ALT}{0}\"\n  STR_NEW_BATTLE: \"Nuova Battaglia\"\n  STR_OPTIONS: \"Opzioni\"\n  STR_RIGHT_CLICK_TO_DELETE: \"Tasto destro del mouse per eliminare.\"\n  STR_RESTORE_DEFAULTS: \"Ripristina\"\n  STR_CONTROLS: \"CONTROLLI\"\n  STR_GENERAL: \"Generale\"\n  STR_GEOSCAPE: \"Geoscape\"\n  STR_BATTLESCAPE: \"Battlescape\"\n  STR_SCREENSHOT: \"Cattura Schermata\"\n  STR_FPS_COUNTER: \"Contatore FPS\"\n  STR_ROTATE_LEFT: \"Ruota a Sinistra\"\n  STR_ROTATE_RIGHT: \"Ruota a Destra\"\n  STR_ROTATE_UP: \"Ruota in Alto\"\n  STR_ROTATE_DOWN: \"Ruota in Basso\"\n  STR_ZOOM_IN: \"Zoom +\"\n  STR_ZOOM_OUT: \"Zoom -\"\n  STR_TOGGLE_COUNTRY_DETAIL: \"Attiva Dettaglio Nazioni\"\n  STR_TOGGLE_RADAR_RANGES: \"Attiva Raggi Radar\"\n  STR_SCROLL_LEFT: \"Scorri a Sinistra\"\n  STR_SCROLL_RIGHT: \"Scorri a Destra\"\n  STR_SCROLL_UP: \"Scorri in Alto\"\n  STR_SCROLL_DOWN: \"Scorri in Basso\"\n  STR_UNIT_LEVEL_ABOVE: \"Muovi Unità al Livello Superiore\"\n  STR_UNIT_LEVEL_BELOW: \"Muovi Unità al Livello Inferiore\"\n  STR_VIEW_LEVEL_ABOVE: \"Mostra Livello Superiore\"\n  STR_VIEW_LEVEL_BELOW: \"Mostra Livello Inferiore\"\n  STR_CENTER_SELECTED_UNIT: \"Centra Unità Selezionata\"\n  STR_PREVIOUS_UNIT: \"Seleziona Unità Precedente\"\n  STR_NEXT_UNIT: \"Seleziona Unità Successiva\"\n  STR_DESELECT_UNIT: \"Deseleziona Unità\"\n  STR_USE_LEFT_HAND: \"Usa Oggetto nella Mano SX\"\n  STR_USE_RIGHT_HAND: \"Usa Oggetto nella Mano DX\"\n  STR_INVENTORY: \"Inventario\"\n  STR_MINIMAP: \"Minimappa\"\n  STR_MULTI_LEVEL_VIEW: \"Vista Multi-Livello\"\n  STR_END_TURN: \"Termina Turno\"\n  STR_ABORT_MISSION: \"Abbandona Missione\"\n  STR_UNIT_STATS: \"Statistiche Unità\"\n  STR_KNEEL: \"Inginocchiati\"\n  STR_RELOAD: \"Ricarica\"\n  STR_TOGGLE_PERSONAL_LIGHTING: \"Attiva Illuminazione Personale\"\n  STR_DONT_RESERVE_TIME_UNITS: \"Non Riservare UdT\"\n  STR_RESERVE_TIME_UNITS_FOR_SNAP_SHOT: \"Riserva UdT per Colpo Immediato\"\n  STR_RESERVE_TIME_UNITS_FOR_AIMED_SHOT: \"Riserva UdT per Colpo Mirato\"\n  STR_RESERVE_TIME_UNITS_FOR_AUTO_SHOT: \"Riserva UdT per Colpo Automatico\"\n  STR_CENTER_ON_ENEMY_1: \"Centra su Nemico 1\"\n  STR_CENTER_ON_ENEMY_2: \"Centra su Nemico 2\"\n  STR_CENTER_ON_ENEMY_3: \"Centra su Nemico 3\"\n  STR_CENTER_ON_ENEMY_4: \"Centra su Nemico 4\"\n  STR_CENTER_ON_ENEMY_5: \"Centra su Nemico 5\"\n  STR_CENTER_ON_ENEMY_6: \"Centra su Nemico 6\"\n  STR_CENTER_ON_ENEMY_7: \"Centra su Nemico 7\"\n  STR_CENTER_ON_ENEMY_8: \"Centra su Nemico 8\"\n  STR_CENTER_ON_ENEMY_9: \"Centra su Nemico 9\"\n  STR_CENTER_ON_ENEMY_10: \"Centra su Nemico 10\"\n  STR_CREATE_INVENTORY_TEMPLATE: \"Crea modello inventario\"\n  STR_APPLY_INVENTORY_TEMPLATE: \"Applica modello inventario\"\n  STR_CLEAR_INVENTORY: \"Sgombra inventario\"\n  STR_AUTO_EQUIP: \"Equipaggiamento automatico\"\n  STR_QUICK_SAVE: \"Salvataggio rapido\"\n  STR_QUICK_LOAD: \"Caricamento rapido\"\n  STR_ADVANCED: \"AVANZATE\"\n  STR_AGGRESSIVERETALIATION: \"Rappresaglia aggressiva\"\n  STR_AGGRESSIVERETALIATION_DESC: \"Gli UFO cercheranno di individuare le tue basi in ogni momento, a prescindere dai loro parametri di missione.\"\n  STR_STORAGELIMITSENFORCED: \"Limiti di immagazzinamento per gli oggetti recuperati\"\n  STR_STORAGELIMITSENFORCED_DESC: \"Rispetta i limiti di capacità del contenimento alieni e dei magazzini per gli alieni vivi e gli artefatti recuperati durante le missioni.\"\n  STR_CANSELLLIVEALIENS: \"Vendita degli alieni vivi\"\n  STR_CANSELLLIVEALIENS_DESC: \"Permette la vendita di alieni vivi, consigliato quando si utilizzano i limiti di immagazzinamento.\"\n  STR_ALLOWBUILDINGQUEUE: \"Consenti coda di costruzione\"\n  STR_ALLOWBUILDINGQUEUE_DESC: \"Nuove strutture possono essere piazzate accanto a quelle non ancora terminate.\"\n  STR_BATTLEAUTOEND: \"Fine automatica delle battaglie\"\n  STR_BATTLEAUTOEND_DESC: \"Le battaglie finiscono automaticamente quando l'ultimo nemico vivente viene neutralizzato.\"\n  STR_BATTLEINSTANTGRENADE: \"Granate immediate\"\n  STR_BATTLEINSTANTGRENADE_DESC: \"Le granate innescate per esplodere in 0 turni esploderanno immediatamente quando lanciate, invece che alla fine del turno.\"\n  STR_BATTLEUFOEXTENDERACCURACY: \"Precisione Estesa UFO\"\n  STR_BATTLEUFOEXTENDERACCURACY_DESC: \"La precisione degli spari diminuisce oltre una certa distanza a seconda del tipo di sparo. La precisione reale verrà visualizzata sul cursore.\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE: \"Trasferimenti aerei\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE_DESC: \"I veicoli attualmente in volo possono essere trasferiti.\"\n  STR_CRAFTLAUNCHALWAYS: \"Forza il decollo dei veicoli\"\n  STR_CRAFTLAUNCHALWAYS_DESC: \"I veicoli si possono far decollare anche se non sono pronti, ignorando l'esigenza di manutenzione.\"\n  STR_CUSTOMINITIALBASE: \"Base iniziale personalizzata\"\n  STR_CUSTOMINITIALBASE_DESC: \"Quando si inizia una partita, è possibile posizionare manualmente le strutture iniziali invece di utilizzare il layout predefinito.\"\n  STR_GLOBESEASONS: \"Illuminazione realistica del globo\"\n  STR_GLOBESEASONS_DESC: \"Usa una proiezione della luce del Sole più realistica sul Geoscape, basata sull'inclinazione dell'asse terrestre.\"\n  STR_PLAYINTRO: \"Vedi introduzione\"\n  STR_PLAYINTRO_DESC: \"Visualizza l'introduzione cinematografica all'avvio.\"\n  STR_SHOWMORESTATSININVENTORYVIEW: \"Statistiche inventario\"\n  STR_SHOWMORESTATSININVENTORYVIEW_DESC: \"Mostra altre informazioni sul soldato selezionato nella schermata dell'inventario.\"\n  STR_SNEAKYAI: \"IA subdola\"\n  STR_SNEAKYAI_DESC: \"L'IA evita di esporsi al giocatore quando possibile.\"\n  STR_STRAFE: \"Metodi di movimento alternativi\"\n  STR_STRAFE_DESC: \"Abilita i movimenti laterali, la corsa e il movimento indipendente della torretta del carro armato quando si tiene premuto CTRL.\"\n  STR_BATTLEEXPLOSIONHEIGHT: \"Altezza di esplosione\"\n  STR_BATTLEEXPLOSIONHEIGHT_DESC: \"Modifica quanto lontano in altezza possono diffondersi le esplosioni.{NEWLINE}(Piatto: 0, Rotondo: 3)\"\n  STR_AUTOSAVE: \"Autosalvataggio\"\n  STR_AUTOSAVE_DESC: \"Salva automaticamente il gioco a intervalli determinati. Non si applica alla modalità Ironman.\"\n  STR_AUTOSAVE_FREQUENCY: \"Frequenza Autosalvataggio\"\n  STR_AUTOSAVE_FREQUENCY_DESC: \"Numero di turni dopo cui il gioco sarà salvato automaticamente.\"\n  STR_ALLOWPSIONICCAPTURE: \"Consenti cattura psi\"\n  STR_ALLOWPSIONICCAPTURE_DESC: \"Controllare mentalmente tutti gli alieni rimanenti porta alla vittoria, e questi contano come alieni catturati vivi.\"\n  STR_ANYTIMEPSITRAINING: \"Allenamento psionico totale\"\n  STR_ANYTIMEPSITRAINING_DESC: \"Permette di assegnare i soldati all'allenamento psionico per tutto il mese. Ricorda, l'allenamento iniziale dura dai 30 ai 60 giorni.\"\n  STR_SKIPNEXTTURNSCREEN: \"Salta schermata \\\"Prossimo Turno\\\"\"\n  STR_SKIPNEXTTURNSCREEN_DESC: \"Le schermate \\\"Prossimo Turno\\\" durante la battaglia vengono attivate automaticamente dopo una breve attesa.\"\n  STR_NOT_ENOUGH_SPACE: \"Spazio Insufficiente!\"\n  STR_WEAPONSELFDESTRUCTION: \"Autodistruzione armi aliene\"\n  STR_WEAPONSELFDESTRUCTION_DESC: \"Le armi portate dagli alieni si autodistruggeranno se il loro possessore viene ucciso, come in XCOM 2012.\"\n  STR_RETAINCORPSES: \"Conserva alieni interrogati\"\n  STR_RETAINCORPSES_DESC: \"Dopo aver \\\"ricercato\\\" alieni vivi, i loro corpi saranno aggiunti ai magazzini della base, come in XCOM 2012.\"\n  STR_SAVE_VOXEL_VIEW: \"Salva uno Screenshot in Prima Persona\"\n  STR_RESERVE_TIME_UNITS_FOR_KNEEL: \"Riserva UT per inginocchiamento\"\n  STR_EXPEND_ALL_TIME_UNITS: \"Impiega tutte le rimanenti Unità di Tempo\"\n  STR_PSISTRENGTHEVAL: \"Stima Forza Psionica\"\n  STR_PSISTRENGTHEVAL_DESC: \"Valuta la forza psionica di tutti i soldati dopo che la specifica ricerca è stata completata.\"\n  STR_DISABLEAUTOEQUIP: \"Disabilita l'equipaggiamento automatico\"\n  STR_DISABLEAUTOEQUIP_DESC: \"Disabilita l'equipaggiamento automatico dei nuovi soldati prima della battaglia.\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT: \"Consenti Miglioramento Forza Psionica\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT_DESC: \"La Forza Psionica dei soldati può essere migliorata da esperienza e addestramento.\"\n  STR_BATTLESMOOTHCAMERA: \"Videocamera per i Proiettili\"\n  STR_BATTLESMOOTHCAMERA_DESC: \"La telecamera del Battlescape rimarrà centrata sui proiettili in volo.\"\n  STR_BATTLECONFIRMFIREMODE: \"Modalità Conferma Fuoco\"\n  STR_BATTLECONFIRMFIREMODE_DESC: \"Richiedi un secondo click sullo stesso riquadro per confermare gli ordini di far fuoco.\"\n  STR_SELECT_BASE_1: \"Scegli Base 1\"\n  STR_SELECT_BASE_2: \"Scegli Base 2\"\n  STR_SELECT_BASE_3: \"Scegli Base 3\"\n  STR_SELECT_BASE_4: \"Scegli Base 4\"\n  STR_SELECT_BASE_5: \"Scegli Base 5\"\n  STR_SELECT_BASE_6: \"Scegli Base 6\"\n  STR_SELECT_BASE_7: \"Scegli Base 7\"\n  STR_SELECT_BASE_8: \"Scegli Base 8\"\n  STR_VIDEO: \"VIDEO\"\n  STR_AUDIO: \"AUDIO\"\n  STR_BATTLESCAPE_UC: \"BATTLESCAPE\"\n  STR_MODS_UC: \"MODS\"\n  STR_MODS: \"Mods\"\n  STR_DISPLAY_RESOLUTION: \"Risoluzione Schermo\"\n  STR_DISPLAY_RESOLUTION_DESC: \"Cambia la risoluzione dello schermo, la risoluzione del gioco verrà adattata. Le frecce permettono di scegliere tra le risoluzioni supportate. Clicca per inserire una risoluzione personalizzata.\"\n  STR_ORIGINAL: \"Originale\"\n  STR_DISPLAY_MODE: \"Modalità Schermo\"\n  STR_WINDOWED: \"In finestra\"\n  STR_FULLSCREEN: \"Schermo intero\"\n  STR_BORDERLESS: \"Senza bordi\"\n  STR_DISPLAY_LANGUAGE: \"Lingua di gioco\"\n  STR_DISPLAY_LANGUAGE_DESC: \"Modifica la lingua dei testi del gioco.\"\n  STR_DISPLAY_FILTER: \"Filtro Visualizzazione\"\n  STR_DISPLAY_FILTER_DESC: \"Modifica il filtro applicato alla schermata del gioco.{NEWLINE}*richiede accelerazione hardware OpenGL.\"\n  STR_DISPLAY_OPTIONS: \"Opzioni Schermo\"\n  STR_LETTERBOXED: \"Imbucato\"\n  STR_LETTERBOXED_DESC: \"Visualizza delle bande nere per mantenere il rapporto d'aspetto originale.\"\n  STR_RESIZABLE: \"Ridimensionabile\"\n  STR_LOCK_MOUSE: \"Cattura Mouse\"\n  STR_LOCK_MOUSE_DESC: \"Impedisce al cursore del mouse di lasciare la finestra di gioco. Ctrl+G per cambiare in ogni momento.\"\n  STR_FIXED_WINDOW_POSITION: \"Posizione Finestra Fissata\"\n  STR_FIXED_WINDOW_POSITION_DESC: \"Imposta una posizione fissa alla Finestra.\"\n  STR_DISPLAY_SET_WINDOW_POSITION: \"Imposta nuova posizione Iniziale della Finestra\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_X: \"Bordo sinistro nuova X:\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_Y: \"Bordo superiore nuova Y:\"\n  STR_MUSIC_VOLUME: \"Volume della Musica\"\n  STR_MUSIC_VOLUME_DESC: \"Cambia il volume della musica di sottofondo.\"\n  STR_SFX_VOLUME: \"Volume Effetti Sonori\"\n  STR_SFX_VOLUME_DESC: \"Cambia il volume degli effetti sonori.\"\n  STR_UI_VOLUME: \"Volume UI\"\n  STR_UI_VOLUME_DESC: \"Cambia il volume dei suoni dell'interfaccia.\"\n  STR_SCROLL_SPEED: \"Velocità Scorrimento\"\n  STR_SCROLL_SPEED_GEO_DESC: \"Modifica la velocità di scorrimento del globo.\"\n  STR_SCROLL_SPEED_BATTLE_DESC: \"Modifica la velocità di scorrimento della mappa.\"\n  STR_DOGFIGHT_SPEED: \"Velocità Combattimento Aereo\"\n  STR_DOGFIGHT_SPEED_DESC: \"Cambia la velocità delle battaglie di intercettazione tra scafi ed UFO. Velocità ridotte possono migliorare le prestazioni su sistemi meno prestanti.\"\n  STR_CLOCK_SPEED: \"Velocità Orologio\"\n  STR_CLOCK_SPEED_DESC: \"Modifica la velocità dell'orologio del Geoscape. Velocità ridotte possono migliorare le prestazioni su sistemi meno prestanti.\"\n  STR_GLOBE_DETAILS: \"Dettagli del Globo\"\n  STR_GLOBE_COUNTRIES: \"Nazioni\"\n  STR_GLOBE_COUNTRIES_DESC: \"Mostra le nazioni finanziatrici sul globo.\"\n  STR_GLOBE_RADARS: \"Radar\"\n  STR_GLOBE_RADARS_DESC: \"Mostra il raggio dei radar delle basi sul globo.\"\n  STR_GLOBE_FLIGHT_PATHS: \"Traiettorie di Volo\"\n  STR_GLOBE_FLIGHT_PATHS_DESC: \"Mostra le traiettorie di volo dei veicoli sul globo.\"\n  STR_CONTROLS_DESC: \"Clicca col sinistro su una scorciatoia e premi un tasto per cambiarla.{NEWLINE}Clicca col destro su una scorciatoia per disabilitarla.\"\n  STR_BASE_GAME: \"Gioco base\"\n  STR_MODS_TOOLTIP: \"Versione {0} di {1}.{NEWLINE}{2}\"\n  STR_EDGE_SCROLL: \"Scorrimento ai Bordi\"\n  STR_EDGE_SCROLL_DESC: \"Manuale: Scorre la mappa quando il tasto sinistro del mouse viene mantenuto premuto sul bordo.{NEWLINE}Automatico: Scorre la mappa quando il cursore si trova sul bordo.\"\n  STR_TRIGGER_SCROLL: \"Manuale\"\n  STR_AUTO_SCROLL: \"Automatico\"\n  STR_DRAG_SCROLL: \"Trascina per Scorrere\"\n  STR_DRAG_SCROLL_DESC: \"Scorre la mappa quando il pulsante specificato del mouse viene mantenuto premuto e trascinato.\"\n  STR_LEFT_MOUSE_BUTTON: \"Pulsante Sinistro\"\n  STR_MIDDLE_MOUSE_BUTTON: \"Pulsante Centrale\"\n  STR_RIGHT_MOUSE_BUTTON: \"Pulsante Destro\"\n  STR_FIRE_SPEED: \"Velocità Fuoco\"\n  STR_FIRE_SPEED_DESC: \"Cambia la velocità dei proiettili delle armi.\"\n  STR_PLAYER_MOVEMENT_SPEED: \"Velocità Movim. Giocatore\"\n  STR_PLAYER_MOVEMENT_SPEED_DESC: \"Cambia la velocità di movimento delle unità controllate dal giocatore.\"\n  STR_COMPUTER_MOVEMENT_SPEED: \"Velocità Movimento IA\"\n  STR_COMPUTER_MOVEMENT_SPEED_DESC: \"Cambia la velocità di movimento delle unità controllate dal computer.\"\n  STR_PATH_PREVIEW: \"Anteprima Percorso\"\n  STR_PATH_ARROWS: \"Frecce\"\n  STR_PATH_ARROWS_DESC: \"Cliccando viene visualizzato il percorso che la tua unità farà per arrivare a destinazione. Il colore indica le azioni disponibili: Verde - muoversi e sparare; Giallo - muoversi; Rosso - non può muoversi.\"\n  STR_PATH_TIME_UNIT_COST: \"Unità di Tempo\"\n  STR_PATH_TIME_UNIT_COST_DESC: \"Cliccando vengono mostrate le UdT che rimarranno alla tua unità dopo essersi spostata fino alla destinazione.\"\n  STR_USER_INTERFACE_OPTIONS: \"Opzioni UI\"\n  STR_TOOLTIPS: \"Suggerimenti\"\n  STR_TOOLTIPS_DESC: \"Visualizza i suggerimenti per i pulsanti del Battlescape.\"\n  STR_DEATH_NOTIFICATIONS: \"Notifica Decessi\"\n  STR_DEATH_NOTIFICATIONS_DESC: \"Mostra una notifica precisando chi è stato ucciso ogni volta che uno dei tuoi soldati muore.\"\n  STR_SHOW_FUNDS: \"Mostra Fondi\"\n  STR_SHOW_FUNDS_DESC: \"Mostra i fondi attuali accanto all'orologio del Geoscape.\"\n  STR_MISSION_GENERATOR: \"GENERATORE MISSIONE\"\n  STR_MAP_OPTIONS: \"OPZIONI MAPPA\"\n  STR_ALIEN_OPTIONS: \"OPZIONI ALIENI\"\n  STR_MAP_TERRAIN: \"Terreno\"\n  STR_MAP_DARKNESS: \"Oscurità\"\n  STR_MAP_DEPTH: \"Profondità\"\n  STR_DIFFICULTY: \"Difficoltà\"\n  STR_ALIEN_RACE: \"Razza\"\n  STR_ALIEN_TECH_LEVEL: \"Livello Tecnologico\"\n  STR_RANDOMIZE: \"Randomizza\"\n  STR_OXCE_REQUIRED_QUESTION: \"Questa mod necessita OpenXcom {0} per eseguirsi correttamente. Abilitare questa mod?\"\n  STR_RESTORE_DEFAULTS_QUESTION: \"Sicuro di voler ripristinare i valori predefiniti?\"\n  STR_DISPLAY_OPTIONS_CONFIRM: \"Vuoi mantenere le attuali opzioni di visualizzazione?\"\n  STR_DISPLAY_OPTIONS_REVERT: \"Ritorno in 0:{0}\"\n  STR_MISSING_CONTENT_PROMPT: \"ATTENZIONE:{SMALLLINE}Questo salvataggio utilizza mod non disponibili. Il contenuto mancante verrà rimosso e potrebbe non essere possibile caricarlo.{NEWLINE}Continuare?\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT: \"Conserva le granate pre-innescate\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT_DESC: \"Salva nella disposizione dell'equipaggiamento del soldato le granate innescate durante l'inventario pre-battaglia.\"\n  STR_NEWSEEDONLOAD: \"Save Scum\"\n  STR_NEWSEEDONLOAD_DESC: \"Caricando una partita si genereranno nuovi numeri casuali, quindi la stessa azione può produrre risultati diversi. Non si applica alla modalità Ironman.\"\n  STR_CHANGEVALUEBYMOUSEWHEEL: \"Cambia i valori con la rotella del mouse\"\n  STR_CHANGEVALUEBYMOUSEWHEEL_DESC: \"Permette di usare la rotella del mouse per aumentare/diminuire i valori di questa quantità.\"\n  STR_BATTLEHAIRBLEACH: \"Aspetto grafico dei soldati migliorato\"\n  STR_BATTLEHAIRBLEACH_DESC: \"Cambia l'aspetto dei soldati sul Battlescape per farlo coincidere con l'aspetto del loro inventario.\"\n  STR_DRAGSCROLLINVERT: \"Inverti lo scorrimento per trascinamento\"\n  STR_DRAGSCROLLINVERT_DESC: \"Quando abilitato, il trascinamento scorre lo schermo nella direzione opposta del mouse.\"\n  STR_BATTLESCAPE_SCALE: \"Scala Battlescape\"\n  STR_BATTLESCAPE_SCALE_DESC: \"Modalità ridimensionamento riquadro Battlescape, basato su risoluzione fissa (stirato per adattarsi), o livello di zoom fisso (allargato fino a riempire).\"\n  STR_GEOSCAPE_SCALE: \"Scala Geoscape\"\n  STR_GEOSCAPESCALE_SCALE_DESC: \"Modalità ridimensionamento riquadro Geoscape, basato su risoluzione fissa (stirato per adattarsi), o livello di zoom fisso (allargato fino a riempire).\"\n  STR_1_5X: \"1.5x Originale\"\n  STR_2X: \"2x Originale\"\n  STR_THIRD_DISPLAY: \"1/3 Schermo\"\n  STR_HALF_DISPLAY: \"1/2 Schermo\"\n  STR_FULL_DISPLAY: \"Schermo Intero\"\n  STR_FPS_LIMIT: \"Limite FPS\"\n  STR_FPS_LIMIT_DESC: \"Limita il numero di aggiornamenti dello schermo al secondo, 0 per nessun limite. Nota: quest'opzione influirà solo in modalità software, dal momento che OpenGL lo gestisce da sé.\"\n  STR_FPS_INACTIVE_LIMIT: \"Limite FPS in background\"\n  STR_FPS_INACTIVE_LIMIT_DESC: \"Limita la frequenza di aggiornamento dei fotogrammi se OpenXcom è in background.\"\n  STR_NOALIENPANICMESSAGES: \"Rimuovi i messaggi di panico degli alieni\"\n  STR_NOALIENPANICMESSAGES_DESC: \"Non visualizzare i messaggi di panico per gli alieni a meno che non siano visibili al giocatore.\"\n  STR_ALIENBLEEDING: \"Sanguinamento alieni\"\n  STR_ALIENBLEEDING_DESC: \"Consente di infliggere ferite mortali alla maggior parte degli alieni.\"\n  STR_FIELDPROMOTIONS: \"Promozioni sul campo\"\n  STR_FIELDPROMOTIONS_DESC: \"Solo i soldati presenti sul sito della missione sono idonei per una promozione.\"\n  STR_MEETINGPOINT: \"Calcola la traiettoria degli UFO\"\n  STR_MEETINGPOINT_DESC: \"I velivoli tentano di intercettare un UFO basandosi sulla sua traiettoria.\"\n  STR_IRONMAN: \"IRONMAN\"\n  STR_IRONMAN_DESC: \"Nessun salvataggio manuale\"\n  STR_SAVE_AND_ABANDON_GAME: \"SALVA ED ABBANDONA PARTITA\"\n  STR_MOD_UNSUCCESSFUL: \"Mod non caricata\"\n  STR_NEW_SAVED_GAME_SLOT: \"<NUOVO SALVATAGGIO>\"\n  STR_AUTO_SAVE_GEOSCAPE_SLOT: \"<AUTO GEOSCAPE>\"\n  STR_AUTO_SAVE_BATTLESCAPE_SLOT: \"<AUTO BATTLESCAPE>\"\n  STR_QUICK_SAVE_SLOT: \"<SALVATAGGIO RAPIDO>\"\n  STR_DISPLAY_MODE_DESC: \"Modificare come il gioco viene visualizzato sullo schermo.\"\n  STR_PREFERRED_MUSIC_FORMAT: \"Formato Musica\"\n  STR_PREFERRED_MUSIC_FORMAT_DESC: \"Scegli il formato preferito della musica da utilizzare quando ne sono disponibili diversi.{NEWLINE}NOTA: la riproduzione MIDI potrebbe avere problemi su Windows.\"\n  STR_PREFERRED_SFX_FORMAT: \"Formato Effetti Sonori\"\n  STR_PREFERRED_SFX_FORMAT_DESC: \"Scegli il formato preferito degli effetti sonori da utilizzare quando ne sono disponibili diversi.\"\n  STR_PREFERRED_VIDEO_FORMAT: \"Formato Video\"\n  STR_PREFERRED_VIDEO_FORMAT_DESC: \"Scegli il formato preferito dei video da utilizzare quando ne sono disponibili diversi.\"\n  STR_PREFERRED_VIDEO_ANIMATION: \"Animazione\"\n  STR_PREFERRED_VIDEO_SLIDESHOW: \"Presentazione\"\n  STR_PREFERRED_FORMAT_AUTO: \"Automatico\"\n  STR_CURRENT_FORMAT: \"Attuale: {0}\"\n  STR_SOUND_OPTIONS: \"Opzioni Audio\"\n  STR_BACKGROUND_MUTE: \"Background Muto\"\n  STR_BACKGROUND_MUTE_DESC: \"Non riprodurre audio se la finestra del gioco non è attiva.\"\n  STR_FORCE_FIRE: \"Ignora Linea di Fuoco\"\n  STR_FORCE_FIRE_DESC: \"Abilita la forzatura per far sparare ai tuoi soldati quando CTRL è premuto, senza tener conto delle regole sulla linea di fuoco.\"\n  STR_NO_AUDIO_HARDWARE_DETECTED: \"Nessun hardware audio trovato\"\n  STR_MOUSEWHEEL_SPEED: \"Velocità di scorrimento rotella del mouse\"\n  STR_MOUSEWHEEL_SPEED_DESC: \"Regola il numero di linee scorse nelle liste ad ogni scatto della rotella del mouse.\"\n  STR_DISABLED: \"Disabilitato\"\n  STR_MAXIMIZE_INFO_SCREENS: \"Ingrandisci le schermate informative\"\n  STR_MAXIMIZE_INFO_SCREENS_DESC: \"L'inventario ed altre varie schermate verranno visualizzate a schermo intero, indipendentemente dalle impostazioni di scala.\"\n  STR_DIARY: \"DIARIO\"\n  STR_KILLED: \"UCCISO\"\n  STR_STUNNED: \"STORDITO\"\n  STR_PANICKED: \"SPAVENTATO\"\n  STR_MINDCONTROLLED: \"CONTROLLATO\"\n  STR_REGION_UNKNOWN: \"Segreto\"\n  STR_WEAPON_UNKNOWN: \"Improvvisazione\"\n  STR_UNKNOWN: \"Sconosciuto\"\n  STR_VICTORY: \"Vittoria\"\n  STR_DEFEAT: \"Sconfitta\"\n  STR_NO_RECORD: \"Nessuna registrazione\"\n  STR_HUMAN: \"Umano\"\n  STR_FRIENDLY: \"Amico\"\n  STR_HOSTILE: \"Ostile\"\n  STR_NEUTRAL: \"Neutrale\"\n  STR_RATING_UC: \"VALUTAZIONE\"\n  STR_LOCATION: \"LUOGO> {ALT}{0}\"\n  STR_DAYLIGHT_TYPE: \"ORA> {ALT}{0}\"\n  STR_RACE_TYPE: \"RAZZA> {ALT}{0}\"\n  STR_DAY: \"Giorno\"\n  STR_NIGHT: \"Notte\"\n  STR_DAYS_WOUNDED: \"GIORNI FERITE> {ALT}{0}\"\n  STR_COMBAT: \"COMBATTIMENTO\"\n  STR_PERFORMANCE: \"PRESTAZIONE\"\n  STR_NEUTRALIZATIONS_BY_RACE: \"NEUTRALIZZAZIONI PER RAZZA\"\n  STR_NEUTRALIZATIONS_BY_RANK: \"NEUTRALIZZAZIONI PER GRADO\"\n  STR_NEUTRALIZATIONS_BY_WEAPON: \"NEUTRALIZZAZIONI PER ARMA\"\n  STR_MISSIONS_BY_LOCATION: \"MISSIONI PER LUOGO\"\n  STR_MISSIONS_BY_TYPE: \"MISSIONI PER TIPO\"\n  STR_MISSIONS_BY_UFO: \"MISSIONI PER UFO\"\n  STR_SCORE_VALUE: \"PUNTI> {ALT}{0}\"\n  STR_WINS: \"VITTORIE> {ALT}{0}\"\n  STR_STUNS: \"STORDITI> {ALT}{0}\"\n  STR_PANICKS: \"SPAVENTATI> {ALT}{0}\"\n  STR_MINDCONTROLS: \"CONTROLLATI> {ALT}{0}\"\n  STR_AWARDS: \"PREMI\"\n  STR_COMMENDATIONS_UC: \"ENCOMI\"\n  STR_COMMENDATIONS: \"Encomi\"\n  STR_MEDALS: \"MEDAGLIE\"\n  STR_LOST_IN_SERVICE: \"PERSO IN BATTAGLIA\"\n  STR_MEDAL_NAME: \"Nome Medaglia\"\n  STR_MEDAL_AWARD_LEVEL: \"Livello Premio\"\n  STR_MEDAL_DECOR_LEVEL: \"Livello Decorazione\"\n  STR_AWARD_0: \"1° premio\"\n  STR_AWARD_1: \"2° premio\"\n  STR_AWARD_2: \"3° premio\"\n  STR_AWARD_3: \"4° premio\"\n  STR_AWARD_4: \"5° premio\"\n  STR_AWARD_5: \"6° premio\"\n  STR_AWARD_6: \"7° premio\"\n  STR_AWARD_7: \"8° premio\"\n  STR_AWARD_8: \"9° premio\"\n  STR_AWARD_9: \"10° premio\"\n  STR_AWARD_DECOR_0: \"Nessuno\"\n  STR_AWARD_DECOR_1: \"1° spilla di bronzo\"\n  STR_AWARD_DECOR_2: \"2° spilla di bronzo\"\n  STR_AWARD_DECOR_3: \"3° spilla di bronzo\"\n  STR_AWARD_DECOR_4: \"1° spilla d`argento\"\n  STR_AWARD_DECOR_5: \"2° spilla d`argento\"\n  STR_AWARD_DECOR_6: \"3° spilla d`argento\"\n  STR_AWARD_DECOR_7: \"1° spilla d`oro\"\n  STR_AWARD_DECOR_8: \"2° spilla d`oro\"\n  STR_AWARD_DECOR_9: \"3° spilla d`oro\"\n  STR_KILLED_IN_ACTION_MALE: \"UCCISO IN AZIONE\"\n  STR_KILLED_IN_ACTION_FEMALE: \"UCCISO IN AZIONE\"\n  STR_MISSING_IN_ACTION_MALE: \"PERSO IN AZIONE\"\n  STR_MISSING_IN_ACTION_FEMALE: \"PERSO IN AZIONE\"\n  STR_AVERAGE_MONTHLY_RATING: \"Punteggio mensile medio\"\n  STR_TOTAL_INCOME: \"Totale entrate\"\n  STR_TOTAL_EXPENDITURE: \"Totale uscite\"\n  STR_MISSIONS_WON: \"Missioni completate\"\n  STR_MISSIONS_LOST: \"Missioni fallite\"\n  STR_NIGHT_MISSIONS: \"Missioni notturne\"\n  STR_BEST_RATING: \"Migliore punteggio missione\"\n  STR_WORST_RATING: \"Peggiore punteggio missione\"\n  STR_ALIEN_KILLS: \"Alieni uccisi\"\n  STR_ALIEN_CAPTURES: \"Alieni catturati\"\n  STR_FRIENDLY_KILLS: \"Episodi di fuoco amico\"\n  STR_AVERAGE_ACCURACY: \"Precisione media\"\n  STR_WEAPON_MOST_KILLS: \"Arma più efficace\"\n  STR_ALIEN_MOST_KILLS: \"Alieno più letale\"\n  STR_LONGEST_SERVICE: \"Mesi di servizio maggiore\"\n  STR_TOTAL_DAYS_WOUNDED: \"Giorni di malattia\"\n  STR_COUNTRIES_LOST: \"Paesi infiltrati\"\n  STR_TOTAL_TERROR_SITES: \"Attacchi del terrore\"\n  STR_TOTAL_BASES: \"Basi realizzate\"\n  STR_TOTAL_CRAFT: \"Veicoli posseduti\"\n  STR_TOTAL_SCIENTISTS: \"Scienziati ingaggiati\"\n  STR_TOTAL_ENGINEERS: \"Ingegneri ingaggiati\"\n  STR_TOTAL_RESEARCH: \"Ricerche completate\"\n  STR_DIARY_ACCURACY: \"PRECISIONE> {ALT}{0}%\"\n  STR_STATISTICS: \"Statistiche\"\n  STR_STATS: \"PROGRES\"\n  STR_TIME_UNITS_ABBREVIATION: \"UdT\"\n  STR_STAMINA_ABBREVIATION: \"STA\"\n  STR_HEALTH_ABBREVIATION: \"SAL\"\n  STR_BRAVERY_ABBREVIATION: \"COR\"\n  STR_REACTIONS_ABBREVIATION: \"REA\"\n  STR_FIRING_ACCURACY_ABBREVIATION: \"MIR\"\n  STR_THROWING_ACCURACY_ABBREVIATION: \"TIR\"\n  STR_STRENGTH_ABBREVIATION: \"FOR\"\n  STR_MELEE_ACCURACY_ABBREVIATION: \"MIS\"\n  STR_FOLDERS: \"CARTELLE\"\n  STR_DATA_FOLDER: \"Cartella Dati (risorse originali)\"\n  STR_USER_FOLDER: \"Cartella Utente (mod, openxcom.log)\"\n  STR_SAVE_FOLDER: \"Cartella Salvataggi (partite salvate, screenshot)\"\n  STR_CONFIG_FOLDER: \"Cartella Opzioni (options.cfg)\"\n  STR_DATA_FOLDER_DESC_1: \"Dove OpenXcom cerca le risorse dei giochi originali (UFO e/o TFTD)\"\n  STR_DATA_FOLDER_DESC_2: \"Le risorse interne di OpenXcom sono nella cartella \\\"common\\\". I mod inclusi in OpenXcom sono nella cartella \\\"standard\\\".\"\n  STR_USER_FOLDER_DESC: \"Il file di log (\\\"openxcom.log\\\") si trova qui. Anche tutte le mod personalizzate appartengono a questa cartella (nella sottocartella \\\"mods\\\").\"\n  STR_SAVE_FOLDER_DESC: \"I tuoi salvataggi si trovano qui, ed anche le impostazioni del generatore di missioni (\\\"battle.cfg\\\").\"\n  STR_CONFIG_FOLDER_DESC: \"Qui sono memorizzate le impostazioni di OpenXcom (\\\"options.cfg\\\"). Di oslito coincide con la cartella User.\"\n"
  },
  {
    "path": "bin/common/Language/ja.yml",
    "content": "ja:\n  STR_OPENXCOM: \"OpenXCom\"\n  STR_NEW_GAME: \"新規キャンペーン\"\n  STR_LOAD_SAVED_GAME: \"ゲームのロード\"\n  STR_SELECT_DIFFICULTY_LEVEL: \"難易度の選択\"\n  STR_1_BEGINNER: \"1> 初心者\"\n  STR_2_EXPERIENCED: \"2> 経験者\"\n  STR_3_VETERAN: \"3> ベテラン\"\n  STR_4_GENIUS: \"4> 天　才\"\n  STR_5_SUPERHUMAN: \"5> 超　人\"\n  STR_TIME: \"時間\"\n  STR_DATE: \"日付\"\n  STR_SELECT_GAME_TO_LOAD: \"ロードするゲームを選択する\"\n  STR_SELECT_SAVE_POSITION: \"保存位置を選択する\"\n  STR_GAME_OPTIONS: \"ゲーム・オプション\"\n  STR_LOAD_GAME: \"ゲームをロードする\"\n  STR_SAVE_GAME: \"ゲームを保存する\"\n  STR_ABANDON_GAME: \"ゲームを終了\"\n  STR_ABANDON_GAME_QUESTION: \"ゲームを終了しますか?\"\n  STR_QUIT: \"終了\"\n  STR_SAVING_GAME: \"ゲームをセーブ中\"\n  STR_LOADING_GAME: \"ゲームをロード中\"\n  STR_NO_SAVED_GAME_PRESENT: \"セーブデータがありません\"\n  STR_LOAD_UNSUCCESSFUL: \"ロード失敗\"\n  STR_SAVE_UNSUCCESSFUL: \"セーブ失敗\"\n  STR_LOAD_SUCCESSFUL: \"ロード完了\"\n  STR_SAVE_SUCCESSFUL: \"セーブ完了\"\n  STR_DELETE: \"消去\"\n  STR_DELETE_UNSUCCESSFUL: \"消去に失敗しました\"\n  STR_IS_IT_OK_TO_DELETE_THE_SAVED_GAME: \"保存されているデータを{NEWLINE}消去しても良いですか?\"\n  STR_ORIGINAL_XCOM: \"オリジナルのX-Com\"\n  STR_LOADING: \"ロード中...\"\n  STR_DETAILS: \"詳細> {ALT} {0}\"\n  STR_NEW_BATTLE: \"スカーミッシュ\"\n  STR_OPTIONS: \"オプション\"\n  STR_RIGHT_CLICK_TO_DELETE: \"右クリックで削除\"\n  STR_RESTORE_DEFAULTS: \"デフォルトに戻す\"\n  STR_CONTROLS: \"ショートカットキー\"\n  STR_GENERAL: \"全般\"\n  STR_GEOSCAPE: \"ジオスケープ\"\n  STR_BATTLESCAPE: \"バトルスケープ\"\n  STR_SCREENSHOT: \"スクリーンショット\"\n  STR_FPS_COUNTER: \"FPS表示\"\n  STR_ROTATE_LEFT: \"左へ回す\"\n  STR_ROTATE_RIGHT: \"右へ回す\"\n  STR_ROTATE_UP: \"上へ回す\"\n  STR_ROTATE_DOWN: \"下へ回す\"\n  STR_ZOOM_IN: \"ズームイン\"\n  STR_ZOOM_OUT: \"ズームアウト\"\n  STR_TOGGLE_COUNTRY_DETAIL: \"国名を表示する\"\n  STR_TOGGLE_RADAR_RANGES: \"レーダー範囲表示切替\"\n  STR_SCROLL_LEFT: \"左にスクロール\"\n  STR_SCROLL_RIGHT: \"右にスクロール\"\n  STR_SCROLL_UP: \"スクロールアップ\"\n  STR_SCROLL_DOWN: \"スクロールダウン\"\n  STR_UNIT_LEVEL_ABOVE: \"1階層下にユニットを移動\"\n  STR_UNIT_LEVEL_BELOW: \"1階層上にユニットを移動\"\n  STR_VIEW_LEVEL_ABOVE: \"上階層表示\"\n  STR_VIEW_LEVEL_BELOW: \"下階層表示\"\n  STR_CENTER_SELECTED_UNIT: \"選択ユニットを中央に表示\"\n  STR_PREVIOUS_UNIT: \"前のユニットを選択\"\n  STR_NEXT_UNIT: \"次ユニットを選択\"\n  STR_DESELECT_UNIT: \"指示済みユニットを再選択しない\"\n  STR_USE_LEFT_HAND: \"左手の道具を使用\"\n  STR_USE_RIGHT_HAND: \"右手の道具を使用\"\n  STR_INVENTORY: \"インベントリ\"\n  STR_MINIMAP: \"ミニマップ\"\n  STR_MULTI_LEVEL_VIEW: \"多階層表示\"\n  STR_END_TURN: \"ターン終了\"\n  STR_ABORT_MISSION: \"任務中断\"\n  STR_UNIT_STATS: \"ユニットデータ\"\n  STR_KNEEL: \"屈む\"\n  STR_RELOAD: \"リロード\"\n  STR_TOGGLE_PERSONAL_LIGHTING: \"個人照明の切り替え\"\n  STR_DONT_RESERVE_TIME_UNITS: \"TU をリザーブしない\"\n  STR_RESERVE_TIME_UNITS_FOR_SNAP_SHOT: \"急速射撃分のTUをリザーブする\"\n  STR_RESERVE_TIME_UNITS_FOR_AIMED_SHOT: \"精密射撃分のTUをリザーブする\"\n  STR_RESERVE_TIME_UNITS_FOR_AUTO_SHOT: \"3連射撃分のTUをリザーブする\"\n  STR_CENTER_ON_ENEMY_1: \"敵1を中央に\"\n  STR_CENTER_ON_ENEMY_2: \"敵2を中央に\"\n  STR_CENTER_ON_ENEMY_3: \"敵3を中央に\"\n  STR_CENTER_ON_ENEMY_4: \"敵4を中央に\"\n  STR_CENTER_ON_ENEMY_5: \"敵5を中央に\"\n  STR_CENTER_ON_ENEMY_6: \"敵6を中央に\"\n  STR_CENTER_ON_ENEMY_7: \"敵7を中央に\"\n  STR_CENTER_ON_ENEMY_8: \"敵8を中央に\"\n  STR_CENTER_ON_ENEMY_9: \"敵9を中央に\"\n  STR_CENTER_ON_ENEMY_10: \"敵10を中央に\"\n  STR_CREATE_INVENTORY_TEMPLATE: \"装備パターンを作成\"\n  STR_APPLY_INVENTORY_TEMPLATE: \"装備パターンを適用\"\n  STR_CLEAR_INVENTORY: \"全装備を外す\"\n  STR_AUTO_EQUIP: \"自動装備\"\n  STR_QUICK_SAVE: \"クイックセーブ\"\n  STR_QUICK_LOAD: \"クイックロード\"\n  STR_ADVANCED: \"上級\"\n  STR_AGGRESSIVERETALIATION: \"エイリアンは基地探索を優先\"\n  STR_AGGRESSIVERETALIATION_DESC: \"UFOは任務の内容に関わらず常にあなたの基地を探し出そうとする\"\n  STR_STORAGELIMITSENFORCED: \"回収アイテムのストレージ制限\"\n  STR_STORAGELIMITSENFORCED_DESC: \"ミッションで回収された生きたエイリアンと遺物に対しても拘束室と倉庫の容量の{NEWLINE}制限が適用される\"\n  STR_CANSELLLIVEALIENS: \"生きたエイリアンの売却\"\n  STR_CANSELLLIVEALIENS_DESC: \"ストレージの制限を適用しているときは生存エイリアンの売却を許す\"\n  STR_ALLOWBUILDINGQUEUE: \"建築の予約を許可\"\n  STR_ALLOWBUILDINGQUEUE_DESC: \"新しい施設を未完成の施設の隣に設置することができる\"\n  STR_BATTLEAUTOEND: \"戦闘の自動終了\"\n  STR_BATTLEAUTOEND_DESC: \"最後の敵が無力化された時点で戦闘が自動的に終了する\"\n  STR_BATTLEINSTANTGRENADE: \"着発式グレネード\"\n  STR_BATTLEINSTANTGRENADE_DESC: \"0ターン設定で投げられた手榴弾はターン終了時ではなくすぐ爆発する\"\n  STR_BATTLEUFOEXTENDERACCURACY: \"UFO Extender式命中精度\"\n  STR_BATTLEUFOEXTENDERACCURACY_DESC: \"射撃のタイプに応じて、一定の距離以遠から射撃精度が低下する。低下が加味され{NEWLINE}た射撃精度はカーソル上に表示される\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE: \"航空機は他の基地へ直接移動可能\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE_DESC: \"航空機を直接移送、配備可能にする\"\n  STR_CRAFTLAUNCHALWAYS: \"補給/修理中の航空機の再発進\"\n  STR_CRAFTLAUNCHALWAYS_DESC: \"準備ができていなくても輸送機は整備の必要性を無視して出撃することができる\"\n  STR_CUSTOMINITIALBASE: \"カスタム初期基地\"\n  STR_CUSTOMINITIALBASE_DESC: \"新規ゲームを開始する際、標準のレイアウトを使用せずに手動で施設の配置ができる{NEWLINE}様にする\"\n  STR_GLOBESEASONS: \"リアルな地球の投影\"\n  STR_GLOBESEASONS_DESC: \"地球の地軸を考慮し、ジオスケープ上の太陽光の投影をよりリアルにする\"\n  STR_PLAYINTRO: \"オープニングを再生\"\n  STR_PLAYINTRO_DESC: \"起動時にイントロムービーを再生する\"\n  STR_SHOWMORESTATSININVENTORYVIEW: \"インベントリ情報\"\n  STR_SHOWMORESTATSININVENTORYVIEW_DESC: \"インベントリー画面に幾つかの情報を追加\"\n  STR_SNEAKYAI: \"狡猾なAI\"\n  STR_SNEAKYAI_DESC: \"A.I. は可能な限り、プレイヤーに発見されることを避ける\"\n  STR_STRAFE: \"車両の移動方式変更\"\n  STR_STRAFE_DESC: \"CTRLキーを押すことで戦車の砲塔を独立させて回転し走行方向を変えずに射撃を可{NEWLINE}能にする\"\n  STR_BATTLEEXPLOSIONHEIGHT: \"Z軸の爆発範囲の設定\"\n  STR_BATTLEEXPLOSIONHEIGHT_DESC: \"爆発がどのくらいの高さまで広がるかを変更する{NEWLINE}(平坦: 0, 球状: 3)\"\n  STR_AUTOSAVE: \"自動保存\"\n  STR_AUTOSAVE_DESC: \"定期的に自動保存する\"\n  STR_AUTOSAVE_FREQUENCY: \"自動保存の頻度\"\n  STR_AUTOSAVE_FREQUENCY_DESC: \"何ターン毎に自動保存するか\"\n  STR_ALLOWPSIONICCAPTURE: \"精神捕縛を許可する\"\n  STR_ALLOWPSIONICCAPTURE_DESC: \"戦闘に勝利した際にマインドコントロール中のエイリアンを捕獲したとみなす\"\n  STR_ANYTIMEPSITRAINING: \"いつでもサイオニック訓練\"\n  STR_ANYTIMEPSITRAINING_DESC: \"その月の任意のときに兵士をサイオニック訓練につかせることができるが、初期訓練{NEWLINE}に30~60日かかることを忘れないように\"\n  STR_SKIPNEXTTURNSCREEN: \"”次のターン”画面をスキップする\"\n  STR_SKIPNEXTTURNSCREEN_DESC: \"戦闘中”次のターン”画面を少し遅れた後に自動的に進める\"\n  STR_NOT_ENOUGH_SPACE: \"スペースがありません!\"\n  STR_WEAPONSELFDESTRUCTION: \"エイリアン武器の自爆\"\n  STR_WEAPONSELFDESTRUCTION_DESC: \"XCOM 2012 のように、殺害されたエイリアンが所持していた武器は自壊する\"\n  STR_RETAINCORPSES: \"尋問済みのエイリアンを保持する\"\n  STR_RETAINCORPSES_DESC: \"XCOM 2012 のように、'研究後'のエイリアンの死体を倉庫に残す\"\n  STR_SAVE_VOXEL_VIEW: \"一人称視点スクリーンショットの保存\"\n  STR_RESERVE_TIME_UNITS_FOR_KNEEL: \"屈むためのTUをリザーブする\"\n  STR_EXPEND_ALL_TIME_UNITS: \"残り全てのTUを使う\"\n  STR_PSISTRENGTHEVAL: \"PSI強度評価\"\n  STR_PSISTRENGTHEVAL_DESC: \"該当の研究が完了するタイミングで、全ての戦闘員のサイオニック能力が再評価される\"\n  STR_DISABLEAUTOEQUIP: \"自動装備無効\"\n  STR_DISABLEAUTOEQUIP_DESC: \"戦闘前に自動的に新兵へ装備を追加しない\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT: \"Psi能力の訓練の有無\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT_DESC: \"Psi能力の訓練を可能にするか\"\n  STR_BATTLESMOOTHCAMERA: \"スムーズな銃弾カメラ\"\n  STR_BATTLESMOOTHCAMERA_DESC: \"バトルスケープのカメラは飛行中の発射体を画面の中央にとどめようとする\"\n  STR_BATTLECONFIRMFIREMODE: \"射撃モードの確認\"\n  STR_BATTLECONFIRMFIREMODE_DESC: \"射撃命令の確認には同じマスへ2回クリックすることを要求する\"\n  STR_SELECT_BASE_1: \"基地1を選択\"\n  STR_SELECT_BASE_2: \"基地2を選択\"\n  STR_SELECT_BASE_3: \"基地3を選択\"\n  STR_SELECT_BASE_4: \"基地4を選択\"\n  STR_SELECT_BASE_5: \"基地5を選択\"\n  STR_SELECT_BASE_6: \"基地6を選択\"\n  STR_SELECT_BASE_7: \"基地7を選択\"\n  STR_SELECT_BASE_8: \"基地8を選択\"\n  STR_VIDEO: \"ビデオ\"\n  STR_AUDIO: \"オーディオ\"\n  STR_BATTLESCAPE_UC: \"バトルスケープ\"\n  STR_MODS_UC: \"MOD\"\n  STR_MODS: \"MOD\"\n  STR_DISPLAY_RESOLUTION: \"ディスプレイ解像度\"\n  STR_DISPLAY_RESOLUTION_DESC: \"ディスプレイの解像度を変更し、ゲーム画面が一致するようにリサイズされます{NEWLINE}矢印でサポートされている解像度に切り替えます{NEWLINE}カスタム解像度を入力するにはクリックします\"\n  STR_ORIGINAL: \"オリジナル\"\n  STR_DISPLAY_MODE: \"ディスプレイモード\"\n  STR_WINDOWED: \"ウィンドウモード\"\n  STR_FULLSCREEN: \"フルスクリーン\"\n  STR_BORDERLESS: \"ボーダーレス\"\n  STR_DISPLAY_LANGUAGE: \"表示言語\"\n  STR_DISPLAY_LANGUAGE_DESC: \"ゲーム内のテキスト言語を変更する\"\n  STR_DISPLAY_FILTER: \"ディスプレイフィルター\"\n  STR_DISPLAY_FILTER_DESC: \"ゲーム画面に適用されるフィルタを変更します{NEWLINE}※OpenGLのハードウェアアクセラレーションを必要とします\"\n  STR_DISPLAY_OPTIONS: \"ディスプレイオプション\"\n  STR_LETTERBOXED: \"レターボックス化\"\n  STR_LETTERBOXED_DESC: \"元のアスペクト比を維持するため、表示をレターボックスにする\"\n  STR_RESIZABLE: \"リサイズ可能\"\n  STR_LOCK_MOUSE: \"マウスカーソルのロック\"\n  STR_LOCK_MOUSE_DESC: \"ゲーム画面からマウスカーソルが外れないようにする{NEWLINE}※Ctrl+Gでいつでも切り替えらます\"\n  STR_FIXED_WINDOW_POSITION: \"ウインドウ位置固定\"\n  STR_FIXED_WINDOW_POSITION_DESC: \"ウインドウ位置の設定\"\n  STR_DISPLAY_SET_WINDOW_POSITION: \"ウインドウの基点を新たに設定\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_X: \"左端の座標 X:\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_Y: \"上端の座標 Y:\"\n  STR_MUSIC_VOLUME: \"BGM音量\"\n  STR_MUSIC_VOLUME_DESC: \"BGMのボリュームの変更\"\n  STR_SFX_VOLUME: \"効果音音量\"\n  STR_SFX_VOLUME_DESC: \"効果音のボリューム変更\"\n  STR_UI_VOLUME: \"UIボリューム\"\n  STR_UI_VOLUME_DESC: \"インターフェースのビープ音のボリュームを変更\"\n  STR_SCROLL_SPEED: \"スクロールの速度\"\n  STR_SCROLL_SPEED_GEO_DESC: \"地球の自転速度を変更する\"\n  STR_SCROLL_SPEED_BATTLE_DESC: \"マップのスクロール速度の変更\"\n  STR_DOGFIGHT_SPEED: \"空中戦の早さ\"\n  STR_DOGFIGHT_SPEED_DESC: \"航空機のUFO迎撃時の速度を変更する。遅くするとローエンドデバイスのパフォーマ{NEWLINE}ンスが向上する\"\n  STR_CLOCK_SPEED: \"クロックスピード\"\n  STR_CLOCK_SPEED_DESC: \"ジオスケープの時計の速度を遅くすることでローエンドデバイスのパフォーマンスが{NEWLINE}向上する\"\n  STR_GLOBE_DETAILS: \"地球の詳細\"\n  STR_GLOBE_COUNTRIES: \"国\"\n  STR_GLOBE_COUNTRIES_DESC: \"資金提供国を表示する\"\n  STR_GLOBE_RADARS: \"レーダー\"\n  STR_GLOBE_RADARS_DESC: \"基地のレーダー範囲を表示する\"\n  STR_GLOBE_FLIGHT_PATHS: \"飛行経路\"\n  STR_GLOBE_FLIGHT_PATHS_DESC: \"航空機の地球上の経路を示す\"\n  STR_CONTROLS_DESC: \"ショートカットを左クリックし変更するキーを押す{NEWLINE}無効にするには右クリックする\"\n  STR_BASE_GAME: \"ベースゲーム\"\n  STR_MODS_TOOLTIP: \"バージョン {0} 開発： {1}.{NEWLINE}{2}\"\n  STR_EDGE_SCROLL: \"エッジスクロール\"\n  STR_EDGE_SCROLL_DESC: \"トリガー：左マウスボタンを押し続けると画面の端までマップがスクロールする{NEWLINE}自動：画面の端にカーソルを置くとマップがスクロールする\"\n  STR_TRIGGER_SCROLL: \"トリガー\"\n  STR_AUTO_SCROLL: \"自動\"\n  STR_DRAG_SCROLL: \"ドラッグスクロール\"\n  STR_DRAG_SCROLL_DESC: \"指定されたマウスボタンを押したままドラッグするときマップをスクロールする\"\n  STR_LEFT_MOUSE_BUTTON: \"左ボタン\"\n  STR_MIDDLE_MOUSE_BUTTON: \"中央ボタン\"\n  STR_RIGHT_MOUSE_BUTTON: \"右ボタン\"\n  STR_FIRE_SPEED: \"弾丸の速度\"\n  STR_FIRE_SPEED_DESC: \"武器の発射速度を変更する\"\n  STR_PLAYER_MOVEMENT_SPEED: \"プレイヤーの移動速度\"\n  STR_PLAYER_MOVEMENT_SPEED_DESC: \"プレイヤーがコントロールしているユニットの移動速度を変更する\"\n  STR_COMPUTER_MOVEMENT_SPEED: \"AI移動速度\"\n  STR_COMPUTER_MOVEMENT_SPEED_DESC: \"コンピュータがコントロールするユニットの移動速度の変更\"\n  STR_PATH_PREVIEW: \"経路のプレビュー\"\n  STR_PATH_ARROWS: \"矢印\"\n  STR_PATH_ARROWS_DESC: \"クリックすると目的地までのユニットの経路が表示される。色によって可能な行動を表{NEWLINE}示する：緑－移動と射撃が可能：黄色－移動が可能：赤－移動不可\"\n  STR_PATH_TIME_UNIT_COST: \"時間ユニット\"\n  STR_PATH_TIME_UNIT_COST_DESC: \"クリックすると目的地に移動したあとに残っているユニットのTUを示す\"\n  STR_USER_INTERFACE_OPTIONS: \"UIオプション\"\n  STR_TOOLTIPS: \"ツールチップ\"\n  STR_TOOLTIPS_DESC: \"バトルスケープボタンのツールチップを表示する\"\n  STR_DEATH_NOTIFICATIONS: \"死亡を通知する\"\n  STR_DEATH_NOTIFICATIONS_DESC: \"兵士が死亡する度にその詳細を知らせる\"\n  STR_SHOW_FUNDS: \"資金を表示する\"\n  STR_SHOW_FUNDS_DESC: \"ジオスケープの時計の上に現在の資金を表示する\"\n  STR_MISSION_GENERATOR: \"ミッションジェネレータ\"\n  STR_MAP_OPTIONS: \"マップオプション\"\n  STR_ALIEN_OPTIONS: \"エイリアンオプション\"\n  STR_MAP_TERRAIN: \"地形\"\n  STR_MAP_DARKNESS: \"暗闇\"\n  STR_MAP_DEPTH: \"深度\"\n  STR_DIFFICULTY: \"難易度\"\n  STR_ALIEN_RACE: \"種族\"\n  STR_ALIEN_TECH_LEVEL: \"技術レベル\"\n  STR_RANDOMIZE: \"ランダム化\"\n  STR_OXCE_REQUIRED_QUESTION: \"このModは以下のMod:' {0} 'が適用されていないと正常に動作しません。適用しますか？\"\n  STR_RESTORE_DEFAULTS_QUESTION: \"デフォルトのオプションを復元してもよろしいですか？\"\n  STR_DISPLAY_OPTIONS_CONFIRM: \"現在のディスプレイオプションを保持しますか？\"\n  STR_DISPLAY_OPTIONS_REVERT: \"0:{0}に戻す\"\n  STR_MISSING_CONTENT_PROMPT: \"警告:{SMALLLINE}このセーブデータは無効なMODに依存しています。{NEWLINE}不足しているコンテンツがある為ロードに失敗する{NEWLINE}可能性があります。それでも続行しますか？\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT: \"時限設定した手榴弾を保持する\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT_DESC: \"戦闘前の兵士装備画面のインベントリで手りゅう弾の時限設定を保持できる\"\n  STR_NEWSEEDONLOAD: \"セーブスカミングあり\"\n  STR_NEWSEEDONLOAD_DESC: \"ゲームをロードする度に乱数シードをリセットしてスカミングを可能にする{NEWLINE}※鉄人モードでは適用されません\"\n  STR_CHANGEVALUEBYMOUSEWHEEL: \"マウスホイールによる量の変更\"\n  STR_CHANGEVALUEBYMOUSEWHEEL_DESC: \"マウスホイールで指定量の増減を可能にする\"\n  STR_BATTLEHAIRBLEACH: \"兵士の外観表示の強化\"\n  STR_BATTLEHAIRBLEACH_DESC: \"装備に合わせて兵士の外観を変更する\"\n  STR_DRAGSCROLLINVERT: \"ドラッグ＆スクロールを反転\"\n  STR_DRAGSCROLLINVERT_DESC: \"有効にするとマウスのドラッグ方向と逆にスクロールする\"\n  STR_BATTLESCAPE_SCALE: \"バトルスケープスケール\"\n  STR_BATTLESCAPE_SCALE_DESC: \"バトルスケープの画面表示を解像度の倍率（引き伸ばし）かズームの倍率（拡大）{NEWLINE}に基づいて設定\"\n  STR_GEOSCAPE_SCALE: \"ジオスケープスケール\"\n  STR_GEOSCAPESCALE_SCALE_DESC: \"ジオスケープの画面表示を解像度の倍率（引き伸ばし）かズームの倍率（拡大）{NEWLINE}に基づいて設定\"\n  STR_1_5X: \"オリジナルの1.5倍\"\n  STR_2X: \"オリジナルの2倍\"\n  STR_THIRD_DISPLAY: \"1/3ディスプレイ\"\n  STR_HALF_DISPLAY: \"1/2ディスプレイ\"\n  STR_FULL_DISPLAY: \"フルディスプレイ\"\n  STR_FPS_LIMIT: \"FPS制限\"\n  STR_FPS_LIMIT_DESC: \"一秒当たりの画面更新の回数を制限する（0で無制限）{NEWLINE}OpenGL によるレンダリングが有効になっている場合、ゲームは垂直同期を使用する\"\n  STR_FPS_INACTIVE_LIMIT: \"非アクティブ時のFPS制限\"\n  STR_FPS_INACTIVE_LIMIT_DESC: \"ゲームが非アクティブ時のFPSの上限を指定する\"\n  STR_NOALIENPANICMESSAGES: \"エイリアンのパニック状態を隠す\"\n  STR_NOALIENPANICMESSAGES_DESC: \"プレイヤーに視認されない限り、エイリアンのパニック状態は表示されない\"\n  STR_ALIENBLEEDING: \"エイリアンの出血\"\n  STR_ALIENBLEEDING_DESC: \"ほとんどのエイリアンに致命傷を与えることが可能\"\n  STR_FIELDPROMOTIONS: \"戦地昇進\"\n  STR_FIELDPROMOTIONS_DESC: \"昇進の資格はそのミッションにいた兵士のうち一人にだけ与えられる\"\n  STR_MEETINGPOINT: \"UFOの軌道予測\"\n  STR_MEETINGPOINT_DESC: \"航空機は現在のUFOの軌道を基準にして遭遇ポイントへ向かう\"\n  STR_IRONMAN: \"鉄人モード\"\n  STR_IRONMAN_DESC: \"手動セーブなし\"\n  STR_SAVE_AND_ABANDON_GAME: \"セーブしてゲームを中断する\"\n  STR_MOD_UNSUCCESSFUL: \"MODの読み込みに失敗しました\"\n  STR_NEW_SAVED_GAME_SLOT: \"新しいセーブ\"\n  STR_AUTO_SAVE_GEOSCAPE_SLOT: \"ジオスケープの自動保存\"\n  STR_AUTO_SAVE_BATTLESCAPE_SLOT: \"バトルスケープの自動保存\"\n  STR_QUICK_SAVE_SLOT: \"<クイックセーブ>\"\n  STR_DISPLAY_MODE_DESC: \"ゲーム画面の表示方法の変更\"\n  STR_PREFERRED_MUSIC_FORMAT: \"音楽フォーマット\"\n  STR_PREFERRED_MUSIC_FORMAT_DESC: \"複数利用可能な場合音楽フォーマットを選択する{NEWLINE}※WindowsでのMIDI再生にはバグが有ります\"\n  STR_PREFERRED_SFX_FORMAT: \"SFXフォーマット\"\n  STR_PREFERRED_SFX_FORMAT_DESC: \"複数選択可能なときは好みの効果音フォーマットを選ぶ\"\n  STR_PREFERRED_VIDEO_FORMAT: \"ビデオフォーマット\"\n  STR_PREFERRED_VIDEO_FORMAT_DESC: \"優先使用するムービーシーンのビデオフォーマットを選択する\"\n  STR_PREFERRED_VIDEO_ANIMATION: \"アニメーション\"\n  STR_PREFERRED_VIDEO_SLIDESHOW: \"スライドショー\"\n  STR_PREFERRED_FORMAT_AUTO: \"自動\"\n  STR_CURRENT_FORMAT: \"現在値: {0}\"\n  STR_SOUND_OPTIONS: \"サウンドのオプション\"\n  STR_BACKGROUND_MUTE: \"インアクティブ時ミュート\"\n  STR_BACKGROUND_MUTE_DESC: \"ゲームウインドウのフォーカスを失った時サウンドをミュート\"\n  STR_FORCE_FIRE: \"射線を無視する\"\n  STR_FORCE_FIRE_DESC: \"CTRLキーを押しながら射線上の障害を無視して射撃できるようにする\"\n  STR_NO_AUDIO_HARDWARE_DETECTED: \"オーディオハードウェアが検出されませんでした\"\n  STR_MOUSEWHEEL_SPEED: \"マウスホイールのスクロール速度\"\n  STR_MOUSEWHEEL_SPEED_DESC: \"マウスホイールの回転に合わせて、リストは指定行数分スクロールする\"\n  STR_DISABLED: \"無効\"\n  STR_MAXIMIZE_INFO_SCREENS: \"情報画面の最大化\"\n  STR_MAXIMIZE_INFO_SCREENS_DESC: \"インベントリ、そのほか様々な画面は、スケールの設定に関わらずフルスクリーンで{NEWLINE}表示される\"\n  STR_DIARY: \"日誌\"\n  STR_KILLED: \"倒した数\"\n  STR_STUNNED: \"気絶\"\n  STR_PANICKED: \"パニック\"\n  STR_MINDCONTROLLED: \"洗脳状態\"\n  STR_REGION_UNKNOWN: \"未公開\"\n  STR_WEAPON_UNKNOWN: \"改良\"\n  STR_UNKNOWN: \"0%\"\n  STR_VICTORY: \"勝利\"\n  STR_DEFEAT: \"敗北\"\n  STR_NO_RECORD: \"記録なし\"\n  STR_HUMAN: \"人類\"\n  STR_FRIENDLY: \"味方\"\n  STR_HOSTILE: \"敵\"\n  STR_NEUTRAL: \"中立\"\n  STR_RATING_UC: \"評価\"\n  STR_LOCATION: \"位置> {ALT}{0}\"\n  STR_DAYLIGHT_TYPE: \"時間 > {ALT}{0}\"\n  STR_RACE_TYPE: \"種族 > {ALT}{0}\"\n  STR_DAY: \"昼間\"\n  STR_NIGHT: \"夜間\"\n  STR_DAYS_WOUNDED: \"傷病期間> {ALT}{0}\"\n  STR_COMBAT: \"戦闘\"\n  STR_PERFORMANCE: \"戦績\"\n  STR_NEUTRALIZATIONS_BY_RACE: \"種族別殺害数\"\n  STR_NEUTRALIZATIONS_BY_RANK: \"階級別殺害数\"\n  STR_NEUTRALIZATIONS_BY_WEAPON: \"武器別殺害数\"\n  STR_MISSIONS_BY_LOCATION: \"ミッション区分：位置\"\n  STR_MISSIONS_BY_TYPE: \"ミッション区分：タイプ\"\n  STR_MISSIONS_BY_UFO: \"ミッション区分：UFO\"\n  STR_SCORE_VALUE: \"スコア > {ALT}{0}\"\n  STR_WINS: \"勝利数　> {ALT}{0}\"\n  STR_STUNS: \"気絶させた数 > {ALT}{0}\"\n  STR_PANICKS: \"パニック回数 > {ALT}{0}\"\n  STR_MINDCONTROLS: \"洗脳操作回数 > {ALT}{0}\"\n  STR_AWARDS: \"賞与\"\n  STR_COMMENDATIONS_UC: \"表彰\"\n  STR_COMMENDATIONS: \"表彰\"\n  STR_MEDALS: \"メダル\"\n  STR_LOST_IN_SERVICE: \"殉職者\"\n  STR_MEDAL_NAME: \"メダルの種類\"\n  STR_MEDAL_AWARD_LEVEL: \"授賞レベル\"\n  STR_MEDAL_DECOR_LEVEL: \"受勲レベル\"\n  STR_AWARD_0: \"一等級授賞\"\n  STR_AWARD_1: \"二等級授賞\"\n  STR_AWARD_2: \"三等級授賞\"\n  STR_AWARD_3: \"四等級授賞\"\n  STR_AWARD_4: \"五等級授賞\"\n  STR_AWARD_5: \"六等級授賞\"\n  STR_AWARD_6: \"七等級授賞\"\n  STR_AWARD_7: \"八等級授賞\"\n  STR_AWARD_8: \"九等級授賞\"\n  STR_AWARD_9: \"十等級授賞\"\n  STR_AWARD_DECOR_0: \"なし\"\n  STR_AWARD_DECOR_1: \"一等銅章\"\n  STR_AWARD_DECOR_2: \"二等銅章\"\n  STR_AWARD_DECOR_3: \"三等銅章\"\n  STR_AWARD_DECOR_4: \"一等銀章\"\n  STR_AWARD_DECOR_5: \"二等銀章\"\n  STR_AWARD_DECOR_6: \"三等銀章\"\n  STR_AWARD_DECOR_7: \"一等金章\"\n  STR_AWARD_DECOR_8: \"二等金章\"\n  STR_AWARD_DECOR_9: \"三等金章\"\n  STR_KILLED_IN_ACTION_MALE: \"戦死\"\n  STR_KILLED_IN_ACTION_FEMALE: \"戦死\"\n  STR_MISSING_IN_ACTION_MALE: \"行方不明\"\n  STR_MISSING_IN_ACTION_FEMALE: \"行方不明\"\n  STR_AVERAGE_MONTHLY_RATING: \"月間評価の平均\"\n  STR_TOTAL_INCOME: \"総収入\"\n  STR_TOTAL_EXPENDITURE: \"総支出額\"\n  STR_MISSIONS_WON: \"達成したミッション数\"\n  STR_MISSIONS_LOST: \"失敗したミッション数\"\n  STR_NIGHT_MISSIONS: \"夜間ミッション数\"\n  STR_BEST_RATING: \"ミッションの最高評価\"\n  STR_WORST_RATING: \"ミッションの最低評価\"\n  STR_ALIEN_KILLS: \"倒したエイリアンの数\"\n  STR_ALIEN_CAPTURES: \"捕えたエイリアンの数\"\n  STR_FRIENDLY_KILLS: \"味方への誤射数\"\n  STR_AVERAGE_ACCURACY: \"平均命中率\"\n  STR_WEAPON_MOST_KILLS: \"最も効果の高い武器\"\n  STR_ALIEN_MOST_KILLS: \"最も危険なエイリアン\"\n  STR_LONGEST_SERVICE: \"最長従軍期間\"\n  STR_TOTAL_DAYS_WOUNDED: \"傷病期間\"\n  STR_COUNTRIES_LOST: \"侵入された国の数\"\n  STR_TOTAL_TERROR_SITES: \"エイリアンのテロ事件数\"\n  STR_TOTAL_BASES: \"基地の数\"\n  STR_TOTAL_CRAFT: \"航空機数\"\n  STR_TOTAL_SCIENTISTS: \"雇用中の科学者\"\n  STR_TOTAL_ENGINEERS: \"雇用中の技術者\"\n  STR_TOTAL_RESEARCH: \"完了した研究\"\n  STR_DIARY_ACCURACY: \"命中精度 > {ALT}{0}%\"\n  STR_STATISTICS: \"統計\"\n  STR_STATS: \"兵の成長\"\n  STR_TIME_UNITS_ABBREVIATION: \"TU\"\n  STR_STAMINA_ABBREVIATION: \"スタミナ\"\n  STR_HEALTH_ABBREVIATION: \"HP\"\n  STR_BRAVERY_ABBREVIATION: \"士気\"\n  STR_REACTIONS_ABBREVIATION: \"反応\"\n  STR_FIRING_ACCURACY_ABBREVIATION: \"命中\"\n  STR_THROWING_ACCURACY_ABBREVIATION: \"投擲\"\n  STR_STRENGTH_ABBREVIATION: \"筋力\"\n  STR_MELEE_ACCURACY_ABBREVIATION: \"近接\"\n  STR_FOLDERS: \"フォルダ\"\n  STR_DATA_FOLDER: \"データフォルダ (オリジナルのリソース)\"\n  STR_USER_FOLDER: \"ユーザーフォルダ (modやopenxcom.log)\"\n  STR_SAVE_FOLDER: \"セーブフォルダ (セーブデータ, スクリーンショット)\"\n  STR_CONFIG_FOLDER: \"コンフィグフォルダ (options.cfg)\"\n  STR_DATA_FOLDER_DESC_1: \"OpenXcomがオリジナルゲームのリソースを参照する先です (UFO / TFTD)\"\n  STR_DATA_FOLDER_DESC_2: \"OpenXcomの内部リソースは 'common' フォルダに、OpenXcom本体に統合済みのmodは 'standard' フォルダに格納されています。\"\n  STR_USER_FOLDER_DESC: \"ログファイル ('openxcom.log') が収められています。全てのカスタムmodもこのフォルダ (サブフォルダの 'mods' 内) に置かれます。\"\n  STR_SAVE_FOLDER_DESC: \"あなたのセーブデータが置かれる場所で、ミッション生成の設定 ('battle.cfg') もここに格納されます。\"\n  STR_CONFIG_FOLDER_DESC: \"OpenXcomのオプション設定 ('options.cfg') が収められているフォルダで、通常はユーザーフォルダが該当します。\"\n"
  },
  {
    "path": "bin/common/Language/ko.yml",
    "content": "ko:\n  STR_OPENXCOM: \"오픈엑스컴\"\n  STR_NEW_GAME: \"새 게임\"\n  STR_LOAD_SAVED_GAME: \"게임 불러오기\"\n  STR_SELECT_DIFFICULTY_LEVEL: \"난이도 선택\"\n  STR_1_BEGINNER: \"1> 초보자\"\n  STR_2_EXPERIENCED: \"2> 경험자\"\n  STR_3_VETERAN: \"3> 전문가\"\n  STR_4_GENIUS: \"4> 천재\"\n  STR_5_SUPERHUMAN: \"5> 초인\"\n  STR_TIME: \"시간\"\n  STR_DATE: \"날짜\"\n  STR_SELECT_GAME_TO_LOAD: \"불러올 게임 선택\"\n  STR_SELECT_SAVE_POSITION: \"저장할 위치 선택\"\n  STR_GAME_OPTIONS: \"게임 설정\"\n  STR_LOAD_GAME: \"게임 불러오기\"\n  STR_SAVE_GAME: \"게임 저장하기\"\n  STR_ABANDON_GAME: \"게임 포기하기\"\n  STR_ABANDON_GAME_QUESTION: \"게임을 포기합니까?\"\n  STR_QUIT: \"나가기\"\n  STR_SAVING_GAME: \"게임 저장하는 중\"\n  STR_LOADING_GAME: \"게임 불러오는 중\"\n  STR_NO_SAVED_GAME_PRESENT: \"저장된 게임 없음\"\n  STR_LOAD_UNSUCCESSFUL: \"불러오기 실패\"\n  STR_SAVE_UNSUCCESSFUL: \"저장하기 실패\"\n  STR_LOAD_SUCCESSFUL: \"불러오기 성공\"\n  STR_SAVE_SUCCESSFUL: \"저장하기 성공\"\n  STR_DELETE: \"삭제하기\"\n  STR_DELETE_UNSUCCESSFUL: \"삭제하기 실패\"\n  STR_IS_IT_OK_TO_DELETE_THE_SAVED_GAME: \"저장된 게임의 삭제를 원하는 게 확실합니까?\"\n  STR_ORIGINAL_XCOM: \"원본 X-Com\"\n  STR_LOADING: \"불러오는 중...\"\n  STR_DETAILS: \"세부사항> {ALT}{0}\"\n  STR_NEW_BATTLE: \"새로운 전투\"\n  STR_OPTIONS: \"설정\"\n  STR_RIGHT_CLICK_TO_DELETE: \"삭제하려면 오른쪽 클릭.\"\n  STR_RESTORE_DEFAULTS: \"기본값으로 복원\"\n  STR_CONTROLS: \"입력\"\n  STR_GENERAL: \"일반\"\n  STR_GEOSCAPE: \"지구 화면\"\n  STR_BATTLESCAPE: \"전투 화면\"\n  STR_SCREENSHOT: \"스크린샷\"\n  STR_FPS_COUNTER: \"FPS 표시\"\n  STR_ROTATE_LEFT: \"왼쪽으로 회전\"\n  STR_ROTATE_RIGHT: \"오른쪽으로 회전\"\n  STR_ROTATE_UP: \"위쪽으로 회전\"\n  STR_ROTATE_DOWN: \"아래쪽으로 회전\"\n  STR_ZOOM_IN: \"확대\"\n  STR_ZOOM_OUT: \"축소\"\n  STR_TOGGLE_COUNTRY_DETAIL: \"국가 세부 켜고 끄기\"\n  STR_TOGGLE_RADAR_RANGES: \"레이더 범위 켜고 끄기\"\n  STR_SCROLL_LEFT: \"왼쪽으로 스크롤\"\n  STR_SCROLL_RIGHT: \"오른쪽으로 스크롤\"\n  STR_SCROLL_UP: \"위쪽으로 스크롤\"\n  STR_SCROLL_DOWN: \"아래쪽으로 스크롤\"\n  STR_UNIT_LEVEL_ABOVE: \"위 층으로 유닛 이동\"\n  STR_UNIT_LEVEL_BELOW: \"아래 층으로 유닛 이동\"\n  STR_VIEW_LEVEL_ABOVE: \"위 층 보기\"\n  STR_VIEW_LEVEL_BELOW: \"아래 층 보기\"\n  STR_CENTER_SELECTED_UNIT: \"선택된 유닛을 화면 중앙에\"\n  STR_PREVIOUS_UNIT: \"이전 유닛을 선택\"\n  STR_NEXT_UNIT: \"다음 유닛을 선택\"\n  STR_DESELECT_UNIT: \"재선택 금지\"\n  STR_USE_LEFT_HAND: \"왼손의 물품 사용\"\n  STR_USE_RIGHT_HAND: \"오른손의 물품 사용\"\n  STR_INVENTORY: \"소지품\"\n  STR_MINIMAP: \"미니맵\"\n  STR_MULTI_LEVEL_VIEW: \"다층 표시\"\n  STR_END_TURN: \"턴 종료\"\n  STR_ABORT_MISSION: \"임무 중단\"\n  STR_UNIT_STATS: \"유닛 능력치\"\n  STR_KNEEL: \"무릎꿇기\"\n  STR_RELOAD: \"재장전\"\n  STR_TOGGLE_PERSONAL_LIGHTING: \"개인 조명 켜고 끄기\"\n  STR_DONT_RESERVE_TIME_UNITS: \"행동력을 남기지 않음\"\n  STR_RESERVE_TIME_UNITS_FOR_SNAP_SHOT: \"지향사격에 쓸 행동력 보전\"\n  STR_RESERVE_TIME_UNITS_FOR_AIMED_SHOT: \"조준사격에 쓸 행동력 보전\"\n  STR_RESERVE_TIME_UNITS_FOR_AUTO_SHOT: \"자동사격에 쓸 행동력 보전\"\n  STR_CENTER_ON_ENEMY_1: \"1번 적을 화면 중앙에\"\n  STR_CENTER_ON_ENEMY_2: \"2번 적을 화면 중앙에\"\n  STR_CENTER_ON_ENEMY_3: \"3번 적을 화면 중앙에\"\n  STR_CENTER_ON_ENEMY_4: \"4번 적을 화면 중앙에\"\n  STR_CENTER_ON_ENEMY_5: \"5번 적을 화면 중앙에\"\n  STR_CENTER_ON_ENEMY_6: \"6번 적을 화면 중앙에\"\n  STR_CENTER_ON_ENEMY_7: \"7번 적을 화면 중앙에\"\n  STR_CENTER_ON_ENEMY_8: \"8번 적을 화면 중앙에\"\n  STR_CENTER_ON_ENEMY_9: \"9번 적을 화면 중앙에\"\n  STR_CENTER_ON_ENEMY_10: \"10번 적을 화면 중앙에\"\n  STR_CREATE_INVENTORY_TEMPLATE: \"소지품 템플릿 생성\"\n  STR_APPLY_INVENTORY_TEMPLATE: \"소지품 템플릿 적용\"\n  STR_CLEAR_INVENTORY: \"소지품 비우기\"\n  STR_AUTO_EQUIP: \"자동 장비\"\n  STR_QUICK_SAVE: \"빠른 저장하기\"\n  STR_QUICK_LOAD: \"빠른 불러오기\"\n  STR_ADVANCED: \"고급\"\n  STR_AGGRESSIVERETALIATION: \"적극적 보복\"\n  STR_AGGRESSIVERETALIATION_DESC: \"자기 임무 설정과 상관 없이, UFO는 언제나 당신의 기지를 탐지하려 할 것입니다.\"\n  STR_STORAGELIMITSENFORCED: \"회수된 물품의 보관 제한\"\n  STR_STORAGELIMITSENFORCED_DESC: \"살아있는 외계인과 임무에서 회수한 유물에 대해 외계인 격리실 및 일반 창고의 제한을 강제로 적용합니다.\"\n  STR_CANSELLLIVEALIENS: \"살아있는 외계인 판매\"\n  STR_CANSELLLIVEALIENS_DESC: \"보관 제한을 이용하고 있을 때 추천되는 것으로, 살아있는 외계인의 판매를 허용합니다.\"\n  STR_ALLOWBUILDINGQUEUE: \"건설 대기열 허용\"\n  STR_ALLOWBUILDINGQUEUE_DESC: \"새로운 시설은 미완성된 시설 옆에 배치될 수 있습니다.\"\n  STR_BATTLEAUTOEND: \"전투 자동 종료\"\n  STR_BATTLEAUTOEND_DESC: \"전투는 살아있는 마지막 적이 무력화될 때 자동으로 종료됩니다.\"\n  STR_BATTLEINSTANTGRENADE: \"즉발 수류탄\"\n  STR_BATTLEINSTANTGRENADE_DESC: \"0턴에 터지도록 점화된 수류탄은 해당 턴의 끝이 아니라, 던졌을 때 즉시 폭발할 것입니다.\"\n  STR_BATTLEUFOEXTENDERACCURACY: \"UFO 익스텐더 정확도\"\n  STR_BATTLEUFOEXTENDERACCURACY_DESC: \"사격 유형에 따라, 사격의 정확도는 특정 거리 이후에 떨어집니다. 조정된 정확도는 마우스 커서에 표시될 것입니다.\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE: \"공중 이송\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE_DESC: \"현재 비행 중인 기체가 이송될 수 있습니다.\"\n  STR_CRAFTLAUNCHALWAYS: \"강제 기체 출격\"\n  STR_CRAFTLAUNCHALWAYS_DESC: \"유지 보수 필요성을 대체하는 것으로, 기체는 준비되지 않았을 때조차 출격할 수 있습니다.\"\n  STR_CUSTOMINITIALBASE: \"첫 기지 꾸미기\"\n  STR_CUSTOMINITIALBASE_DESC: \"새로운 게임을 시작할 때, 당신은 기본 배치를 이용하는 대신 시작 시설을 수동으로 배치할 수 있습니다.\"\n  STR_GLOBESEASONS: \"현실적 지구 조명\"\n  STR_GLOBESEASONS_DESC: \"지구의 자전축 기울어짐에 따라 지구 화면 상에 더 현실적인 태양광 투시를 이용합니다.\"\n  STR_PLAYINTRO: \"인트로 재생\"\n  STR_PLAYINTRO_DESC: \"게임 시작 시 인트로 영상을 보여줍니다.\"\n  STR_SHOWMORESTATSININVENTORYVIEW: \"소지품 화면 능력치\"\n  STR_SHOWMORESTATSININVENTORYVIEW_DESC: \"소지품 화면에서 선택된 병사에 대한 추가 정보를 보여 줍니다.\"\n  STR_SNEAKYAI: \"은밀한 AI\"\n  STR_SNEAKYAI_DESC: \"AI는 가능한 언제나 플레이어에게 자신을 노출하는 걸 피합니다.\"\n  STR_STRAFE: \"대체 이동 방식\"\n  STR_STRAFE_DESC: \"CTRL을 누르고 있을 때 게걸음, 달리기 및 독립적인 탱크 포탑 회전을 할 수 있게 한다.\"\n  STR_BATTLEEXPLOSIONHEIGHT: \"폭발 높이\"\n  STR_BATTLEEXPLOSIONHEIGHT_DESC: \"폭발이 높이 방향으로 얼마나 멀리 퍼질 지 변경합니다.{NEWLINE}(평면: 0, 구체: 3)\"\n  STR_AUTOSAVE: \"자동 저장\"\n  STR_AUTOSAVE_DESC: \"특정 간격마다 게임을 자동으로 저장합니다. 철인 모드에서는 적용되지 않습니다.\"\n  STR_AUTOSAVE_FREQUENCY: \"자동 저장 빈도\"\n  STR_AUTOSAVE_FREQUENCY_DESC: \"게임이 자동으로 저장될 턴의 간격을 정합니다.\"\n  STR_ALLOWPSIONICCAPTURE: \"사이오닉 포획 허용\"\n  STR_ALLOWPSIONICCAPTURE_DESC: \"모든 남아 있는 외계인을 정신 지배하는 것은 승리로 이어지고, 그들은 살아있는 포로로 간주합니다.\"\n  STR_ANYTIMEPSITRAINING: \"사이오닉 훈련 상시화\"\n  STR_ANYTIMEPSITRAINING_DESC: \"어느 시점에서도 병사를 사이오닉 훈련에 할당하도록 허용합니다. 기억하세요, 초기 훈련은 30에서 60일이 걸립니다.\"\n  STR_SKIPNEXTTURNSCREEN: \"\\\"다음 턴\\\" 화면을 넘김\"\n  STR_SKIPNEXTTURNSCREEN_DESC: \"전투 중 \\\"다음 턴\\\" 화면이 짧은 지연 후 자동으로 넘어갑니다.\"\n  STR_NOT_ENOUGH_SPACE: \"공간이 부족하다!\"\n  STR_WEAPONSELFDESTRUCTION: \"외계인 무기 자폭\"\n  STR_WEAPONSELFDESTRUCTION_DESC: \"XCOM 2012와 비슷하게, 외계인이 든 무기는 소유자가 죽으면 자폭할 것입니다.\"\n  STR_RETAINCORPSES: \"심문한 외계인 유지\"\n  STR_RETAINCORPSES_DESC: \"XCOM 2012와 비슷하게, 살아있는 외계인을 \\\"연구한\\\" 후, 그 시체가 기지 창고에 추가될 것입니다.\"\n  STR_SAVE_VOXEL_VIEW: \"1인칭 스크린샷 저장\"\n  STR_RESERVE_TIME_UNITS_FOR_KNEEL: \"무릎꿇기에 필요한 행동력 보전\"\n  STR_EXPEND_ALL_TIME_UNITS: \"남아있는 모든 행동력 소진\"\n  STR_PSISTRENGTHEVAL: \"사이오닉 강도 평가\"\n  STR_PSISTRENGTHEVAL_DESC: \"적절한 연구가 완료된 후 모든 병사의 사이오닉 강도를 평가합니다.\"\n  STR_DISABLEAUTOEQUIP: \"자동 장비 장착 비활성화\"\n  STR_DISABLEAUTOEQUIP_DESC: \"전투 전에 새로운 병사의 자동 장비 장착을 비활성화합니다.\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT: \"사이오닉 강도 성장 허용\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT_DESC: \"병사의 사이오닉 강도는 경험과 훈련에 의해 개선될 수 있습니다.\"\n  STR_BATTLESMOOTHCAMERA: \"매끄러운 총알 카메라\"\n  STR_BATTLESMOOTHCAMERA_DESC: \"전투 화면의 카메라는 발사체가 날아가는 동안 발사체를 따라갈 것입니다.\"\n  STR_BATTLECONFIRMFIREMODE: \"사격 확정 모드\"\n  STR_BATTLECONFIRMFIREMODE_DESC: \"사격 명령을 확정하기 위해 같은 타일을 두 번 누르는 걸 요구합니다.\"\n  STR_SELECT_BASE_1: \"기지 1 선택\"\n  STR_SELECT_BASE_2: \"기지 2 선택\"\n  STR_SELECT_BASE_3: \"기지 3 선택\"\n  STR_SELECT_BASE_4: \"기지 4 선택\"\n  STR_SELECT_BASE_5: \"기지 5 선택\"\n  STR_SELECT_BASE_6: \"기지 6 선택\"\n  STR_SELECT_BASE_7: \"기지 7 선택\"\n  STR_SELECT_BASE_8: \"기지 8 선택\"\n  STR_VIDEO: \"비디오\"\n  STR_AUDIO: \"오디오\"\n  STR_BATTLESCAPE_UC: \"전투 화면\"\n  STR_MODS_UC: \"모드\"\n  STR_MODS: \"모드\"\n  STR_DISPLAY_RESOLUTION: \"해상도 표시\"\n  STR_DISPLAY_RESOLUTION_DESC: \"화면의 해상도를 변경하고, 게임 해상도는 그에 맞추어 재조정될 것입니다. 화살표는 모니터가 지원하는 해상도로 전환합니다. 맞춤형 해상도를 입력하려면 숫자를 누르세요.\"\n  STR_ORIGINAL: \"원본\"\n  STR_DISPLAY_MODE: \"표시 모드\"\n  STR_WINDOWED: \"창 모드\"\n  STR_FULLSCREEN: \"전체 화면\"\n  STR_BORDERLESS: \"경계선 없는 창 모드\"\n  STR_DISPLAY_LANGUAGE: \"표시 언어\"\n  STR_DISPLAY_LANGUAGE_DESC: \"게임 내 텍스트의 문자를 변경합니다.\"\n  STR_DISPLAY_FILTER: \"화면 필터\"\n  STR_DISPLAY_FILTER_DESC: \"게임 화면에 적용되는 필터를 변경합니다.{NEWLINE}* 붙은 옵션은 OpenGL 하드웨어 가속이 필요합니다.\"\n  STR_DISPLAY_OPTIONS: \"표시 설정\"\n  STR_LETTERBOXED: \"레터박스\"\n  STR_LETTERBOXED_DESC: \"원래 종횡비를 유지하도록 화면을 레터박스화합니다.\"\n  STR_RESIZABLE: \"크기 조정 가능\"\n  STR_LOCK_MOUSE: \"마우스 가두기\"\n  STR_LOCK_MOUSE_DESC: \"마우스 커서가 게임 창을 나가지 않도록 막습니다. CTRL+G로 언제나 켜고 끌 수 있습니다.\"\n  STR_FIXED_WINDOW_POSITION: \"창 위치 고정\"\n  STR_FIXED_WINDOW_POSITION_DESC: \"윈도우에서 화면의 위치를 특정 위치로 고정합니다.\"\n  STR_DISPLAY_SET_WINDOW_POSITION: \"새로운 게임 화면 시작점 설정\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_X: \"왼쪽 끝의 X좌표:\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_Y: \"위쪽 끝의 Y좌표:\"\n  STR_MUSIC_VOLUME: \"음악 음량\"\n  STR_MUSIC_VOLUME_DESC: \"배경 음악의 음량을 변경합니다.\"\n  STR_SFX_VOLUME: \"효과음 음량\"\n  STR_SFX_VOLUME_DESC: \"효과음의 음량을 변경합니다.\"\n  STR_UI_VOLUME: \"UI 음량\"\n  STR_UI_VOLUME_DESC: \"인터페이스 클릭음의 음량을 변경합니다.\"\n  STR_SCROLL_SPEED: \"스크롤 속도\"\n  STR_SCROLL_SPEED_GEO_DESC: \"지구의 스크롤 속도를 변경합니다.\"\n  STR_SCROLL_SPEED_BATTLE_DESC: \"전투 맵의 스크롤 속도를 변경합니다.\"\n  STR_DOGFIGHT_SPEED: \"공중전 속도\"\n  STR_DOGFIGHT_SPEED_DESC: \"기체와 UFO 사이의 공중전 속도를 변경합니다. 더 느린 속도는 저사양 기기에서 성능을 개선할 수 있습니다.\"\n  STR_CLOCK_SPEED: \"시계 속도\"\n  STR_CLOCK_SPEED_DESC: \"지구 화면 시계의 진행 속도를 변경합니다. 더 느린 속도는 저사양 기기에서 성능을 개선할 수 있습니다.\"\n  STR_GLOBE_DETAILS: \"지구 세부\"\n  STR_GLOBE_COUNTRIES: \"국가\"\n  STR_GLOBE_COUNTRIES_DESC: \"지구에 있는 자금 지원 국가를 보여줍니다.\"\n  STR_GLOBE_RADARS: \"레이더\"\n  STR_GLOBE_RADARS_DESC: \"지구에서 기지의 레이더 탐지 반경을 보여줍니다.\"\n  STR_GLOBE_FLIGHT_PATHS: \"비행 경로\"\n  STR_GLOBE_FLIGHT_PATHS_DESC: \"지구에서 기체의 비행 경로를 보여줍니다.\"\n  STR_CONTROLS_DESC: \"단축키를 변경하려면 단축키 항목을 마우스 왼쪽 버튼으로 누르고 키를 입력합니다.{NEWLINE}단축키를 비활성화하려면 단축키 항목을 마우스 오른쪽 버튼으로 누릅니다.\"\n  STR_BASE_GAME: \"기본 게임\"\n  STR_MODS_TOOLTIP: \"버전: {0}, 제작자: {1}.{NEWLINE}{2}\"\n  STR_EDGE_SCROLL: \"모서리 스크롤\"\n  STR_EDGE_SCROLL_DESC: \"클릭으로: 화면의 모서리에서 마우스 왼쪽 버튼을 누르고 있을 때 지도가 스크롤됩니다.{NEWLINE}자동으로: 커서가 화면의 모서리에 있을 때 지도가 스크린됩니다.\"\n  STR_TRIGGER_SCROLL: \"클릭으로\"\n  STR_AUTO_SCROLL: \"자동으로\"\n  STR_DRAG_SCROLL: \"드래그 스크롤\"\n  STR_DRAG_SCROLL_DESC: \"특정 마우스 버튼을 누르고 끌었을 때 지도가 스크롤됩니다.\"\n  STR_LEFT_MOUSE_BUTTON: \"왼쪽 버튼\"\n  STR_MIDDLE_MOUSE_BUTTON: \"가운데 버튼\"\n  STR_RIGHT_MOUSE_BUTTON: \"오른쪽 버튼\"\n  STR_FIRE_SPEED: \"발사체 속도\"\n  STR_FIRE_SPEED_DESC: \"무기 발사체의 속도를 변경합니다.\"\n  STR_PLAYER_MOVEMENT_SPEED: \"플레이어 이동 속도\"\n  STR_PLAYER_MOVEMENT_SPEED_DESC: \"플레이어가 조종하는 유닛의 이동 속도를 변경합니다.\"\n  STR_COMPUTER_MOVEMENT_SPEED: \"AI 이동 속도\"\n  STR_COMPUTER_MOVEMENT_SPEED_DESC: \"컴퓨터가 조종하는 유닛의 이동 속도를 변경합니다.\"\n  STR_PATH_PREVIEW: \"경로 미리보기\"\n  STR_PATH_ARROWS: \"화살표\"\n  STR_PATH_ARROWS_DESC: \"선택하면 당신의 유닛이 목적지까지 움직일 경로를 보여줍니다. 색상은 할 수 있는 행동을 나타냅니다: 녹색 - 이동 및 사격 가능; 황색 - 이동 가능; 적색 - 이동 불가능.\"\n  STR_PATH_TIME_UNIT_COST: \"행동력\"\n  STR_PATH_TIME_UNIT_COST_DESC: \"선택하면 당신의 유닛이 목적지까지 이동한 후 남아 있을 행동력을 보여줍니다.\"\n  STR_USER_INTERFACE_OPTIONS: \"UI 설정\"\n  STR_TOOLTIPS: \"툴팁\"\n  STR_TOOLTIPS_DESC: \"전투 화면 버튼에 대한 설명을 표시합니다.\"\n  STR_DEATH_NOTIFICATIONS: \"사망 알림\"\n  STR_DEATH_NOTIFICATIONS_DESC: \"병사가 죽을 때마다 누가 죽었는지 자세한 알림을 띄웁니다.\"\n  STR_SHOW_FUNDS: \"자금 표시\"\n  STR_SHOW_FUNDS_DESC: \"지구 화면의 시계 위에 현재 자금을 보여줍니다.\"\n  STR_MISSION_GENERATOR: \"임무 생성기\"\n  STR_MAP_OPTIONS: \"지도 옵션\"\n  STR_ALIEN_OPTIONS: \"외계인 옵션\"\n  STR_MAP_TERRAIN: \"지형\"\n  STR_MAP_DARKNESS: \"조명\"\n  STR_MAP_DEPTH: \"높이\"\n  STR_DIFFICULTY: \"난이도\"\n  STR_ALIEN_RACE: \"종족\"\n  STR_ALIEN_TECH_LEVEL: \"기술 수준\"\n  STR_RANDOMIZE: \"무작위\"\n  STR_OXCE_REQUIRED_QUESTION: \"이 모드는 올바로 실행하려면 OpenXcom {0}를 요구합니다. 이 모드를 켭니까?\"\n  STR_RESTORE_DEFAULTS_QUESTION: \"기본 설정으로 복원하길 원하는 게 확실합니까?\"\n  STR_DISPLAY_OPTIONS_CONFIRM: \"현재 화면 설정을 유지하길 원합니까?\"\n  STR_DISPLAY_OPTIONS_REVERT: \"0:{0}초 후 되돌립니다\"\n  STR_MISSING_CONTENT_PROMPT: \"경고:{SMALLLINE}이 저장된 게임은 쓸 수 없는 모드에 의존합니다. 잃어버린 요소는 제거될 것이며, 불러오기가 실패할 지도 모릅니다.{NEWLINE}계속 합니까?\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT: \"사전 점화된 수류탄 소지\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT_DESC: \"전투 전 소지품 화면에서 병사의 장비 배치 중에 점화된 수류탄을 보관하게 합니다.\"\n  STR_NEWSEEDONLOAD: \"저장질\"\n  STR_NEWSEEDONLOAD_DESC: \"게임을 불러오면 무작위 수를 결정하는 시드가 재설정되므로, 동일한 행동을 해도 다른 결과를 얻을 수 있습니다. 철인 모드에는 적용하지 않습니다.\"\n  STR_CHANGEVALUEBYMOUSEWHEEL: \"마우스 휠로 값 변경\"\n  STR_CHANGEVALUEBYMOUSEWHEEL_DESC: \"마우스 휠을 이용해 옆에 적힌 양만큼 값을 증가/감소하도록 합니다.\"\n  STR_BATTLEHAIRBLEACH: \"향상된 병사 조형\"\n  STR_BATTLEHAIRBLEACH_DESC: \"병사의 전투 화면 조형을 소지품 화면의 외관에 맞추어 변경합니다.\"\n  STR_DRAGSCROLLINVERT: \"드래그 스크롤 반전\"\n  STR_DRAGSCROLLINVERT_DESC: \"켜졌을 때, 드래그 스크롤은 마우스의 이동 방향과 반대 방향이 됩니다.\"\n  STR_BATTLESCAPE_SCALE: \"전투 화면 스케일\"\n  STR_BATTLESCAPE_SCALE_DESC: \"고정 해상도(맞추기 위해 늘어남), 또는 고정 확대 수준(채우기 위해 확대됨)에 기반한, 전투 화면의 화면 크기 조정 모드입니다.\"\n  STR_GEOSCAPE_SCALE: \"지구 화면 스케일\"\n  STR_GEOSCAPESCALE_SCALE_DESC: \"고정 해상도(맞추기 위해 늘어남), 또는 고정 확대 수준(채우기 위해 확대됨)에 기반한, 지구 화면의 화면 크기 조정 모드입니다.\"\n  STR_1_5X: \"원본의 1.5배\"\n  STR_2X: \"원본의 2배\"\n  STR_THIRD_DISPLAY: \"화면 해상도의 1/3\"\n  STR_HALF_DISPLAY: \"화면 해상도의 1/2\"\n  STR_FULL_DISPLAY: \"화면 해상도\"\n  STR_FPS_LIMIT: \"FPS 제한\"\n  STR_FPS_LIMIT_DESC: \"초당 화면 업데이트 숫자를 제한합니다. 0은 제한이 없는 것입니다. OpenGL 렌더링이 켜지면 이 옵션 대신 Vsync를 이용합니다.\"\n  STR_FPS_INACTIVE_LIMIT: \"백그라운드 FPS 제한\"\n  STR_FPS_INACTIVE_LIMIT_DESC: \"오픈엑스컴이 백그라운드 상태일 때 초당 화면 갱신 회수를 제한합니다.\"\n  STR_NOALIENPANICMESSAGES: \"외계인의 공황 메시지 억제\"\n  STR_NOALIENPANICMESSAGES_DESC: \"외계인이 플레이어에게 보이지 않는 한 외계인에 대한 공황 메시지를 보여 주지 않습니다.\"\n  STR_ALIENBLEEDING: \"외계인 출혈\"\n  STR_ALIENBLEEDING_DESC: \"대다수 외계인이 치명상을 입도록 허용합니다.\"\n  STR_FIELDPROMOTIONS: \"현장 진급\"\n  STR_FIELDPROMOTIONS_DESC: \"오직 임무에 출석했던 병사만 진급 자격이 있습니다.\"\n  STR_MEETINGPOINT: \"UFO 경로 예상\"\n  STR_MEETINGPOINT_DESC: \"기체는 UFO의 현재 궤적에 기반해 만나는 지점을 향해 날아갑니다.\"\n  STR_IRONMAN: \"철인\"\n  STR_IRONMAN_DESC: \"수동 저장 불가능\"\n  STR_SAVE_AND_ABANDON_GAME: \"저장 후 게임 종료\"\n  STR_MOD_UNSUCCESSFUL: \"모드 불러오기 실패\"\n  STR_NEW_SAVED_GAME_SLOT: \"<NEW SAVED GAME>\"\n  STR_AUTO_SAVE_GEOSCAPE_SLOT: \"<AUTO GEOSCAPE>\"\n  STR_AUTO_SAVE_BATTLESCAPE_SLOT: \"<AUTO BATTLESCAPE>\"\n  STR_QUICK_SAVE_SLOT: \"<QUICKSAVE>\"\n  STR_DISPLAY_MODE_DESC: \"게임이 화면에 어떻게 표시되는지 변경합니다.\"\n  STR_PREFERRED_MUSIC_FORMAT: \"음악 형식\"\n  STR_PREFERRED_MUSIC_FORMAT_DESC: \"여러 가지 음악 형식을 쓸 수 있을 때 선호하는 음악 형식을 선택합니다.{NEWLINE}주의: 미디 재생은 윈도우에서 버그가 있을 수 있습니다.\"\n  STR_PREFERRED_SFX_FORMAT: \"효과음 형식\"\n  STR_PREFERRED_SFX_FORMAT_DESC: \"여러 가지 효과음 형식을 쓸 수 있을 때 선호하는 효과음 형식을 선택합니다.\"\n  STR_PREFERRED_VIDEO_FORMAT: \"비디오 형식\"\n  STR_PREFERRED_VIDEO_FORMAT_DESC: \"여러 가지 비디오 형식을 쓸 수 있을 때 선호하는 비디오 형식을 선택합니다.\"\n  STR_PREFERRED_VIDEO_ANIMATION: \"애니메이션\"\n  STR_PREFERRED_VIDEO_SLIDESHOW: \"슬라이드쇼\"\n  STR_PREFERRED_FORMAT_AUTO: \"자동\"\n  STR_CURRENT_FORMAT: \"현재: {0}\"\n  STR_SOUND_OPTIONS: \"소리 설정\"\n  STR_BACKGROUND_MUTE: \"백그라운드 음소거\"\n  STR_BACKGROUND_MUTE_DESC: \"게임 윈도우가 활성화되지 않았을 때는 모든 소리를 끕니다.\"\n  STR_FORCE_FIRE: \"사선 규칙 무시\"\n  STR_FORCE_FIRE_DESC: \"사선 규칙과 상관 없이, 당신의 병사가 CTRL을 누르고 있을 때 사격을 하도록 강제할 수 있게 합니다.\"\n  STR_NO_AUDIO_HARDWARE_DETECTED: \"오디오 하드웨어를 탐지하지 못했습니다.\"\n  STR_MOUSEWHEEL_SPEED: \"마우스 휠 스크롤 속도\"\n  STR_MOUSEWHEEL_SPEED_DESC: \"마우스 휠의 증감 시 움직이는 텍스트 라인의 수를 조정합니다.\"\n  STR_DISABLED: \"비활성화\"\n  STR_MAXIMIZE_INFO_SCREENS: \"정보 화면 최대화\"\n  STR_MAXIMIZE_INFO_SCREENS_DESC: \"스케일 설정에 상관 없이, 소지품 및 기타 다양한 화면이 전체 화면으로 표시될 것입니다.\"\n  STR_DIARY: \"일지\"\n  STR_KILLED: \"죽임\"\n  STR_STUNNED: \"기절시킴\"\n  STR_PANICKED: \"공황 유발\"\n  STR_MINDCONTROLLED: \"정신 지배\"\n  STR_REGION_UNKNOWN: \"미발견지\"\n  STR_WEAPON_UNKNOWN: \"즉석 무기\"\n  STR_UNKNOWN: \"알려지지 않음\"\n  STR_VICTORY: \"승리\"\n  STR_DEFEAT: \"패배\"\n  STR_NO_RECORD: \"기록 없음\"\n  STR_HUMAN: \"인간\"\n  STR_FRIENDLY: \"우호\"\n  STR_HOSTILE: \"적대\"\n  STR_NEUTRAL: \"중립\"\n  STR_RATING_UC: \"평가\"\n  STR_LOCATION: \"위치>{ALT}{0}\"\n  STR_DAYLIGHT_TYPE: \"시간>{ALT}{0}\"\n  STR_RACE_TYPE: \"종족>{ALT}{0}\"\n  STR_DAY: \"낮\"\n  STR_NIGHT: \"밤\"\n  STR_DAYS_WOUNDED: \"부상 기간>{ALT}{0}\"\n  STR_COMBAT: \"전투\"\n  STR_PERFORMANCE: \"활동\"\n  STR_NEUTRALIZATIONS_BY_RACE: \"종족별 처치 수\"\n  STR_NEUTRALIZATIONS_BY_RANK: \"계급별 처치 수\"\n  STR_NEUTRALIZATIONS_BY_WEAPON: \"무기별 처치 수\"\n  STR_MISSIONS_BY_LOCATION: \"지역별 임무 수\"\n  STR_MISSIONS_BY_TYPE: \"유형별 임무 수\"\n  STR_MISSIONS_BY_UFO: \"UFO별 임무 수\"\n  STR_SCORE_VALUE: \"평점>{ALT}{0}\"\n  STR_WINS: \"승리>{ALT}{0}\"\n  STR_STUNS: \"기절>{ALT}{0}\"\n  STR_PANICKS: \"공황>{ALT}{0}\"\n  STR_MINDCONTROLS: \"정신지배>{ALT}{0}\"\n  STR_AWARDS: \"포상\"\n  STR_COMMENDATIONS_UC: \"상훈\"\n  STR_COMMENDATIONS: \"상훈\"\n  STR_MEDALS: \"훈장\"\n  STR_LOST_IN_SERVICE: \"복무 중 손실\"\n  STR_MEDAL_NAME: \"훈장 이름\"\n  STR_MEDAL_AWARD_LEVEL: \"포상 등급\"\n  STR_MEDAL_DECOR_LEVEL: \"장식 등급\"\n  STR_AWARD_0: \"1번째 수상\"\n  STR_AWARD_1: \"2번째 수상\"\n  STR_AWARD_2: \"3번째 수상\"\n  STR_AWARD_3: \"4번째 수상\"\n  STR_AWARD_4: \"5번째 수상\"\n  STR_AWARD_5: \"6번째 수상\"\n  STR_AWARD_6: \"7번째 수상\"\n  STR_AWARD_7: \"8번째 수상\"\n  STR_AWARD_8: \"9번째 수상\"\n  STR_AWARD_9: \"10번째 수상\"\n  STR_AWARD_DECOR_0: \"없음\"\n  STR_AWARD_DECOR_1: \"1번째 동장식\"\n  STR_AWARD_DECOR_2: \"2번째 동장식\"\n  STR_AWARD_DECOR_3: \"3번째 동장식\"\n  STR_AWARD_DECOR_4: \"1번째 은장식\"\n  STR_AWARD_DECOR_5: \"2번째 은장식\"\n  STR_AWARD_DECOR_6: \"3번째 은장식\"\n  STR_AWARD_DECOR_7: \"1번째 금장식\"\n  STR_AWARD_DECOR_8: \"2번째 금장식\"\n  STR_AWARD_DECOR_9: \"3번째 금장식\"\n  STR_KILLED_IN_ACTION_MALE: \"작전 중 사망\"\n  STR_KILLED_IN_ACTION_FEMALE: \"작전 중 사망\"\n  STR_MISSING_IN_ACTION_MALE: \"작전 중 실종\"\n  STR_MISSING_IN_ACTION_FEMALE: \"작전 중 실종\"\n  STR_AVERAGE_MONTHLY_RATING: \"평균 월간 평점\"\n  STR_TOTAL_INCOME: \"총 수입\"\n  STR_TOTAL_EXPENDITURE: \"총 지출\"\n  STR_MISSIONS_WON: \"완수한 임무\"\n  STR_MISSIONS_LOST: \"실패한 임무\"\n  STR_NIGHT_MISSIONS: \"야간 임무\"\n  STR_BEST_RATING: \"최고 임무 평점\"\n  STR_WORST_RATING: \"최악 임무 평점\"\n  STR_ALIEN_KILLS: \"사살한 외계인\"\n  STR_ALIEN_CAPTURES: \"포획한 외계인\"\n  STR_FRIENDLY_KILLS: \"아군 오사 사고\"\n  STR_AVERAGE_ACCURACY: \"평균 명중률\"\n  STR_WEAPON_MOST_KILLS: \"가장 효과적인 무기\"\n  STR_ALIEN_MOST_KILLS: \"가장 위험한 외계인\"\n  STR_LONGEST_SERVICE: \"최장 복무 기간\"\n  STR_TOTAL_DAYS_WOUNDED: \"부상 기간\"\n  STR_COUNTRIES_LOST: \"적에게 넘어간 국가\"\n  STR_TOTAL_TERROR_SITES: \"테러 공격\"\n  STR_TOTAL_BASES: \"건설한 기지\"\n  STR_TOTAL_CRAFT: \"보유한 기체\"\n  STR_TOTAL_SCIENTISTS: \"고용한 과학자\"\n  STR_TOTAL_ENGINEERS: \"고용한 기술자\"\n  STR_TOTAL_RESEARCH: \"완료한 연구\"\n  STR_DIARY_ACCURACY: \"명중률>{ALT}{0}%\"\n  STR_STATISTICS: \"통계\"\n  STR_STATS: \"능력치\"\n  STR_TIME_UNITS_ABBREVIATION: \"TU\"\n  STR_STAMINA_ABBREVIATION: \"STA\"\n  STR_HEALTH_ABBREVIATION: \"HP\"\n  STR_BRAVERY_ABBREVIATION: \"BRV\"\n  STR_REACTIONS_ABBREVIATION: \"REA\"\n  STR_FIRING_ACCURACY_ABBREVIATION: \"ACC\"\n  STR_THROWING_ACCURACY_ABBREVIATION: \"THR\"\n  STR_STRENGTH_ABBREVIATION: \"STR\"\n  STR_MELEE_ACCURACY_ABBREVIATION: \"MEL\"\n  STR_FOLDERS: \"폴더\"\n  STR_DATA_FOLDER: \"자료 폴더(원본 자료)\"\n  STR_USER_FOLDER: \"사용자 폴더(모드, openxcom.log)\"\n  STR_SAVE_FOLDER: \"저장 폴더(저장된 게임, 스크린샷)\"\n  STR_CONFIG_FOLDER: \"설정 폴더(options.cfg)\"\n  STR_DATA_FOLDER_DESC_1: \"오픈엑스컴이 원본 게임 자료를 찾는 곳입니다(UFO 및/또는 TFTD).\"\n  STR_DATA_FOLDER_DESC_2: \"오픈엑스컴 내부 자료는 'common' 폴더 안에 있습니다. 오픈엑스컴 내장 모드는 'standard'폴더 안에 있습니다.\"\n  STR_USER_FOLDER_DESC: \"기록 파일('openxcom.log')는 여기 저장됩니다. 모든 개인 모드도 여기에 들어갑니다('mods' 하위 폴더 안에).\"\n  STR_SAVE_FOLDER_DESC: \"여러분이 저장된 게임은 여기 들어갑니다. 임무 생성기 설정도('battle.cfg') 여기서 찾을 수 있습니다.\"\n  STR_CONFIG_FOLDER_DESC: \"오픈엑스컴 설정이('options.cfg') 보관되는 곳입니다. 보통은 사용자 폴더와 같습니다.\"\n"
  },
  {
    "path": "bin/common/Language/lb.yml",
    "content": "lb:\n  STR_OPENXCOM: \"OpenXcom\"\n  STR_NEW_GAME: \"Neit Spill\"\n  STR_LOAD_SAVED_GAME: \"Spill lueden\"\n  STR_SELECT_DIFFICULTY_LEVEL: \"Schwieregkeetsgrad wielen\"\n  STR_1_BEGINNER: \"1> Ufänger\"\n  STR_2_EXPERIENCED: \"2> Erfahren\"\n  STR_3_VETERAN: \"3> Veteran\"\n  STR_4_GENIUS: \"4> Genie\"\n  STR_5_SUPERHUMAN: \"5> Supermënsch\"\n  STR_TIME: \"Zäit\"\n  STR_DATE: \"Datum\"\n  STR_SELECT_GAME_TO_LOAD: \"Wiel e Spillstand fir ze lueden\"\n  STR_SELECT_SAVE_POSITION: \"Wiel eng Späicherpositioun\"\n  STR_GAME_OPTIONS: \"SPILLOPTIOUNEN\"\n  STR_LOAD_GAME: \"SPILL LUEDEN\"\n  STR_SAVE_GAME: \"SPILL SPAICHERN\"\n  STR_ABANDON_GAME: \"SPILL OFBRIECHEN\"\n  STR_ABANDON_GAME_QUESTION: \"SPILL OFBRIECHEN?\"\n  STR_QUIT: \"Rausgoen\"\n  STR_SAVING_GAME: \"Späichern d'Spill\"\n  STR_LOADING_GAME: \"Lueden d'Spill\"\n  STR_NO_SAVED_GAME_PRESENT: \"Keng Späicherspillstänn do\"\n  STR_LOAD_UNSUCCESSFUL: \"Konnt net lueden\"\n  STR_SAVE_UNSUCCESSFUL: \"Konnt net späichern\"\n  STR_LOAD_SUCCESSFUL: \"Gelueden\"\n  STR_SAVE_SUCCESSFUL: \"Späichern ofgeschloss\"\n  STR_DELETE: \"LÄSCHEN\"\n  STR_DELETE_UNSUCCESSFUL: \"Net geläscht ginn\"\n  STR_IS_IT_OK_TO_DELETE_THE_SAVED_GAME: \"Bassde sécher, dass du dësen Späicherstand wëlls läschen?\"\n  STR_ORIGINAL_XCOM: \"Original X-Com\"\n  STR_LOADING: \"Lueden...\"\n  STR_DETAILS: \"DETAILER> {ALT}{0}\"\n  STR_NEW_BATTLE: \"Neie Kampf\"\n  STR_OPTIONS: \"Optiounen\"\n  STR_RIGHT_CLICK_TO_DELETE: \"Riets-Klick fir ze läschen.\"\n  STR_RESTORE_DEFAULTS: \"Standarter lueden\"\n  STR_CONTROLS: \"KONTROLL\"\n  STR_GENERAL: \"Generell\"\n  STR_GEOSCAPE: \"Geoscape\"\n  STR_BATTLESCAPE: \"Battlescape\"\n  STR_SCREENSHOT: \"Screenshot\"\n  STR_FPS_COUNTER: \"FPS Zieler\"\n  STR_ROTATE_LEFT: \"No lénks dréinen\"\n  STR_ROTATE_RIGHT: \"No Riets dréinen\"\n  STR_ROTATE_UP: \"No uewen dréinen\"\n  STR_ROTATE_DOWN: \"Rof dréinen\"\n  STR_ZOOM_IN: \"Ranzoomen\"\n  STR_ZOOM_OUT: \"Rauszoomen\"\n  STR_TOGGLE_COUNTRY_DETAIL: \"Lännerdetailer wiesselen\"\n  STR_TOGGLE_RADAR_RANGES: \"Radarreechwäit un/ausschalten\"\n  STR_SCROLL_LEFT: \"No lénks scrollen\"\n  STR_SCROLL_RIGHT: \"No riets scrollen\"\n  STR_SCROLL_UP: \"No uewen scrollen\"\n  STR_SCROLL_DOWN: \"Rofscrollen\"\n  STR_UNIT_LEVEL_ABOVE: \"Eenheet e Stack ropbewegen\"\n  STR_UNIT_LEVEL_BELOW: \"Eenheet e Stack rofbewegen\"\n  STR_VIEW_LEVEL_ABOVE: \"Ieweschte Stack uweisen\"\n  STR_VIEW_LEVEL_BELOW: \"Ënneschte Stack uweisen\"\n  STR_CENTER_SELECTED_UNIT: \"Ugewielten Eenheet zentréiren\"\n  STR_PREVIOUS_UNIT: \"Firescht Eenheet auswielen\"\n  STR_NEXT_UNIT: \"Nächsten Eenheet auswielen\"\n  STR_DESELECT_UNIT: \"Eenheet net nach emol auswielen\"\n  STR_USE_LEFT_HAND: \"Lénks-Hand Géigenstand benotzen\"\n  STR_USE_RIGHT_HAND: \"Riets-Hand Géigenstand benotzen\"\n  STR_INVENTORY: \"Inventar\"\n  STR_MINIMAP: \"Minikaart\"\n  STR_MULTI_LEVEL_VIEW: \"Multi-Level Usiicht\"\n  STR_END_TURN: \"Tuer fäerdeg\"\n  STR_ABORT_MISSION: \"Missioun ofbriechen\"\n  STR_UNIT_STATS: \"Eenheetestatistik\"\n  STR_KNEEL: \"Knéien\"\n  STR_RELOAD: \"Nolueden\"\n  STR_TOGGLE_PERSONAL_LIGHTING: \"Wiessel tëscht Beliichtung\"\n  STR_DONT_RESERVE_TIME_UNITS: \"Keng ZE reservéieren\"\n  STR_RESERVE_TIME_UNITS_FOR_SNAP_SHOT: \"ZE fir e Schnellschoss reservéieren\"\n  STR_RESERVE_TIME_UNITS_FOR_AIMED_SHOT: \"ZE fir e gezilte Schoss reservéieren\"\n  STR_RESERVE_TIME_UNITS_FOR_AUTO_SHOT: \"ZE fir en Autoschoss reservéieren\"\n  STR_CENTER_ON_ENEMY_1: \"Op Géigner 1 zentréiren\"\n  STR_CENTER_ON_ENEMY_2: \"Op Géigner 2 zentréiren\"\n  STR_CENTER_ON_ENEMY_3: \"Op Géigner 3 zentréiren\"\n  STR_CENTER_ON_ENEMY_4: \"Op Géigner 4 zentréiren\"\n  STR_CENTER_ON_ENEMY_5: \"Op Géigner 5 zentréiren\"\n  STR_CENTER_ON_ENEMY_6: \"Op Géigner 6 zentréiren\"\n  STR_CENTER_ON_ENEMY_7: \"Op Géigner 7 zentréiren\"\n  STR_CENTER_ON_ENEMY_8: \"Op Géigner 8 zentréiren\"\n  STR_CENTER_ON_ENEMY_9: \"Op Géigner 9 zentréiren\"\n  STR_CENTER_ON_ENEMY_10: \"Op Géigner 10 zentréiren\"\n  STR_CREATE_INVENTORY_TEMPLATE: \"Inventartemplate erstellen\"\n  STR_APPLY_INVENTORY_TEMPLATE: \"Inventartemplate uwennen\"\n  STR_CLEAR_INVENTORY: \"Inventar eidel man\"\n  STR_AUTO_EQUIP: \"Auto-Equipéiren\"\n  STR_QUICK_SAVE: \"Schnellspäichern\"\n  STR_QUICK_LOAD: \"Schnelllueden\"\n  STR_ADVANCED: \"ERWEIDERT\"\n  STR_AGGRESSIVERETALIATION: \"Aggressiv Géigewier\"\n  STR_AGGRESSIVERETALIATION_DESC: \"UFOen probéiren ëmmer deng Basis ze fannen, egal wat hier Missioun ass.\"\n  STR_STORAGELIMITSENFORCED: \"Lagerlimit fir gebuergen Saachen\"\n  STR_STORAGELIMITSENFORCED_DESC: \"Lieweg Alien an Artefakter déi an enger Missioun gebuerge ginn, musse Plaz an enger Zell oder Lager hunn.\"\n  STR_CANSELLLIVEALIENS: \"Verkaf vun liewegen Alien\"\n  STR_CANSELLLIVEALIENS_DESC: \"Erlabt d'Verkafen vun liewegen Alien, recommandéiert wann ee Lagerlimite benotzt.\"\n  STR_ALLOWBUILDINGQUEUE: \"Baureiefolleg erlaben\"\n  STR_ALLOWBUILDINGQUEUE_DESC: \"Nei Infrastrukturen kënnen nierft déi, déi nach am Bau sinn, gebaut ginn.\"\n  STR_BATTLEAUTOEND: \"Kampf automatesch ophalen\"\n  STR_BATTLEAUTOEND_DESC: \"Schlachten sinn automatesch eriwwer wann den leschten liewegen Géigner neutraliséiert gouf.\"\n  STR_BATTLEINSTANTGRENADE: \"Direkt Granaten\"\n  STR_BATTLEINSTANTGRENADE_DESC: \"Granaten déi den Zünder op 0 stoen hunn, explodéiren direkt nodems se geworf goufen, amplaz um Enn vum Tuer.\"\n  STR_BATTLEUFOEXTENDERACCURACY: \"UFO Extender Genauegkeet\"\n  STR_BATTLEUFOEXTENDERACCURACY_DESC: \"Treffergenauegkeet geet ab enger gewësser Distanz erof, je no Schosstyp. Adaptéiert Genaugkeet gëtt um Cursor gewisen.\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE: \"Lofttransferen\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE_DESC: \"Fligeren déi ennerwee sinn kënnen transferéiert ginn.\"\n  STR_CRAFTLAUNCHALWAYS: \"Fliger emmer starten\"\n  STR_CRAFTLAUNCHALWAYS_DESC: \"Fliger kann gestart ginn, och wann en nach net fäerdeg mam Service ass.\"\n  STR_CUSTOMINITIALBASE: \"Eischt Basis selwer designen.\"\n  STR_CUSTOMINITIALBASE_DESC: \"Wann en neit Spill gestart gëtt, kanns du selwer deng Infrastruktur plazéiren, amplaz dass den Standardlayout benotzt gëtt.\"\n  STR_GLOBESEASONS: \"Realistesch Globusbeliichtung\"\n  STR_GLOBESEASONS_DESC: \"Benotzt eng méi realistesch Beliichtung vum Globus mat Aberechnung vun der Äerdneigung.\"\n  STR_PLAYINTRO: \"Intro ofspillen\"\n  STR_PLAYINTRO_DESC: \"Weis den Introfilm beim Start\"\n  STR_SHOWMORESTATSININVENTORYVIEW: \"Inventar Statistik\"\n  STR_SHOWMORESTATSININVENTORYVIEW_DESC: \"Weis zousätzlech Informatiounen fir den ausgewielten Zaldot am Inventarschierm un.\"\n  STR_SNEAKYAI: \"Tückesch KI\"\n  STR_SNEAKYAI_DESC: \"KI probéiert sech dem Spiller net ze weisen, wann méiglech.\"\n  STR_STRAFE: \"Alternativ Bewegungsmethoden\"\n  STR_STRAFE_DESC: \"Schalt strafen, lafen an onofhängeg Panzertuermbewegungen un andems CTRL gedréckt bleift.\"\n  STR_BATTLEEXPLOSIONHEIGHT: \"Explosiounshéicht\"\n  STR_BATTLEEXPLOSIONHEIGHT_DESC: \"Änner wéi wäit eng Explosioun déi an d'Héicht geet sech ausbreet.{NEWLINE}(Flaach: 0, Ronn: 3)\"\n  STR_AUTOSAVE: \"Autospäicher Modus\"\n  STR_AUTOSAVE_DESC: \"Späichert d'Spill automatesch a bestëmmten Intervallen. Zielt net fir den Ironman Modus.\"\n  STR_AUTOSAVE_FREQUENCY: \"Autosavefrequenz\"\n  STR_AUTOSAVE_FREQUENCY_DESC: \"Unzuel un Tier no denen d'Spill automatesch gespäichert gëtt.\"\n  STR_ALLOWPSIONICCAPTURE: \"Psi-Capture erlaben\"\n  STR_ALLOWPSIONICCAPTURE_DESC: \"Wann een all iwreg Alien per Gedankesteierung ënner Kontroll huet, gëllt dëst als gewonnen an déi Alien zielen als lieweg Gefaangener.\"\n  STR_ANYTIMEPSITRAINING: \"Psi-Training allzäit\"\n  STR_ANYTIMEPSITRAINING_DESC: \"Erlabt Zaldoten zu all Zäit vum Mount ze trainéieren. Denk drun, déi éischt Trainingen daueren tëschend 30 an 60 Deeg.\"\n  STR_SKIPNEXTTURNSCREEN: \"Iwwersprang \\\"Nächsten Tuer\\\" Schierm\"\n  STR_SKIPNEXTTURNSCREEN_DESC: \"\\\"Nächsten Tuer\\\" Schiermer während dem Kampf ginn automatesch weider no enger kuerzer Paus\"\n  STR_NOT_ENOUGH_SPACE: \"Net genuch Plaz!\"\n  STR_WEAPONSELFDESTRUCTION: \"Alien Waffen Selbstzerstéirung\"\n  STR_WEAPONSELFDESTRUCTION_DESC: \"Waffen déi vun Alien gedro ginn, zerstéiren sech selwer wann den Besëtzer stierwt, wéi an XCOM 2012.\"\n  STR_RETAINCORPSES: \"Verhéiert Alien behalen\"\n  STR_RETAINCORPSES_DESC: \"Nom \\\"erfuerschen\\\" vun liewëgen Alien, kënnt de Kierper zréck an d'Inventar, wéi am XCOM 2012\"\n  STR_SAVE_VOXEL_VIEW: \"First-Person Screenshot späichern\"\n  STR_RESERVE_TIME_UNITS_FOR_KNEEL: \"Zäiteenheeten fir ze knéien reservéiren\"\n  STR_EXPEND_ALL_TIME_UNITS: \"All iwwreg Zäiteenheeten lassginn\"\n  STR_PSISTRENGTHEVAL: \"Psi-Stäerkt Evaluatioun\"\n  STR_PSISTRENGTHEVAL_DESC: \"Evaluéiert d'Psi-Stäerkt vun all den Zaldoten nodems déi entspriechend Fuerschung fäerdeg ginn ass.\"\n  STR_DISABLEAUTOEQUIP: \"Auto-Equipéiren ausschalten\"\n  STR_DISABLEAUTOEQUIP_DESC: \"Auto-Equipéiren vun den Zaldoten firum Kampf ausschalten\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT: \"Erlab Psi-Stäerkt-Verbesserungen\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT_DESC: \"Psi-Stäerkt vun den Zaldote kann durch Erfahrung an Training verbessert ginn.\"\n  STR_BATTLESMOOTHCAMERA: \"Roueg Kugelkamera\"\n  STR_BATTLESMOOTHCAMERA_DESC: \"D'Battlescapekamera bleiwt op Kugelen zentréiert während dem Fluch.\"\n  STR_BATTLECONFIRMFIREMODE: \"Schossmodus bestätegen\"\n  STR_BATTLECONFIRMFIREMODE_DESC: \"Benéidegt en zweeten Klick op dat selwëscht Feld fir en Ueder ze konfirméiren.\"\n  STR_SELECT_BASE_1: \"Basis 1 auswielen\"\n  STR_SELECT_BASE_2: \"Basis 2auswielen\"\n  STR_SELECT_BASE_3: \"Basis 3 auswielen\"\n  STR_SELECT_BASE_4: \"Basis 4 auswielen\"\n  STR_SELECT_BASE_5: \"Basis 5 auswielen\"\n  STR_SELECT_BASE_6: \"Basis 6 auswielen\"\n  STR_SELECT_BASE_7: \"Basis 7 auswielen\"\n  STR_SELECT_BASE_8: \"Basis 8 auswielen\"\n  STR_VIDEO: \"VIDEO\"\n  STR_AUDIO: \"AUDIO\"\n  STR_BATTLESCAPE_UC: \"BATTLESCAPE\"\n  STR_MODS_UC: \"MODS\"\n  STR_MODS: \"Mods\"\n  STR_DISPLAY_RESOLUTION: \"Opléisung uweisen\"\n  STR_DISPLAY_RESOLUTION_DESC: \"Ännert d'Opléisung vum Display, d'Spillopléisung gëtt ugepasst.\\nD'Feiler wiesselen tëschend den ënnerstetzten Opléisungen. Klick fir eng eegen Opléisung anzeginn.\"\n  STR_ORIGINAL: \"Original\"\n  STR_DISPLAY_MODE: \"Display Modus\"\n  STR_WINDOWED: \"Fënstermodus\"\n  STR_FULLSCREEN: \"Vollbild\"\n  STR_BORDERLESS: \"Ouni Rumm\"\n  STR_DISPLAY_LANGUAGE: \"Display Sprooch\"\n  STR_DISPLAY_LANGUAGE_DESC: \"Ännert d'Sprooch vum Spilltext.\"\n  STR_DISPLAY_FILTER: \"Display Filter\"\n  STR_DISPLAY_FILTER_DESC: \"Ännert de Filter den op de Spillschierm ugewand gëtt.{NEWLINE}*brauch eng OpenGL Hardwarebeschleunegung.\"\n  STR_DISPLAY_OPTIONS: \"Display Optiounen\"\n  STR_LETTERBOXED: \"Letterbox\"\n  STR_LETTERBOXED_DESC: \"Den Display gëtt an den Letterbox Format gestallt fir d'originalt Bildverhältnis ze behalen.\"\n  STR_RESIZABLE: \"Verännerbar\"\n  STR_LOCK_MOUSE: \"Mauszeiger fänken\"\n  STR_LOCK_MOUSE_DESC: \"Hënnert den Mauszeiger dorun aus der Spillfënster rauszegoen. Ctrl+G fir emzewiesselen.\"\n  STR_FIXED_WINDOW_POSITION: \"Fest Fënster Positioun\"\n  STR_FIXED_WINDOW_POSITION_DESC: \"Der Fënster eng fest Positioun ginn\"\n  STR_DISPLAY_SET_WINDOW_POSITION: \"Ufankspositioun fir eng nei Fënster festleeën\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_X: \"Lénkse Rand, neien X-Wert:\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_Y: \"Iewëchte Rand, neien X-Wert:\"\n  STR_MUSIC_VOLUME: \"Musik Volume\"\n  STR_MUSIC_VOLUME_DESC: \"Ännert de Volume vun der Hannergrondmusik.\"\n  STR_SFX_VOLUME: \"SFX Volume\"\n  STR_SFX_VOLUME_DESC: \"Ännert de Volume vun de Soundeffekter.\"\n  STR_UI_VOLUME: \"UI Volume\"\n  STR_UI_VOLUME_DESC: \"Ännert de Volume vun den Interface Beepen.\"\n  STR_SCROLL_SPEED: \"SCROLLGESCHWINDEGKEET\"\n  STR_SCROLL_SPEED_GEO_DESC: \"Ännert d'Scrollgeschwindegkeet vum Globus.\"\n  STR_SCROLL_SPEED_BATTLE_DESC: \"Ännert d'Scrollgeschwindegkeet vun der Kaart.\"\n  STR_DOGFIGHT_SPEED: \"Dogfight Geschwindegkeet\"\n  STR_DOGFIGHT_SPEED_DESC: \"Ännert d'Geschwindegkeet vum Kampf tëscht Fliger an UFO. Méi kleng Geschwindegkeeten kënnen d'Performance op lowend Geräter verbessern.\"\n  STR_CLOCK_SPEED: \"Geschwindegkeet vun der Auer\"\n  STR_CLOCK_SPEED_DESC: \"Ännert d'Geschwindegkeet vun der Geoscape Auer. Méi kleng Geschwindegkeeten kënnen d'Performance op lowend Geräter verbessern.\"\n  STR_GLOBE_DETAILS: \"Globus Detailer\"\n  STR_GLOBE_COUNTRIES: \"Länner\"\n  STR_GLOBE_COUNTRIES_DESC: \"Weist fördernd Länner um Globus un.\"\n  STR_GLOBE_RADARS: \"Radaren\"\n  STR_GLOBE_RADARS_DESC: \"Weist Standardradardistanz um Globus un\"\n  STR_GLOBE_FLIGHT_PATHS: \"Fluchweeër\"\n  STR_GLOBE_FLIGHT_PATHS_DESC: \"Weist Fluchweeër um Globus un\"\n  STR_CONTROLS_DESC: \"Klick eng Ofkierzung un an eng Tast fir en ze änneren.{NEWLINE}Riets-Klick op d'Ofkierzung fir se auszeschalten.\"\n  STR_BASE_GAME: \"Basisspill\"\n  STR_MODS_TOOLTIP: \"Version {0} vun {1}.{NEWLINE}{2}\"\n  STR_EDGE_SCROLL: \"Scrollen um Rand\"\n  STR_EDGE_SCROLL_DESC: \"Trigger: Scrollt d'Kaart wann déi lénks Maustast um Rand vum Schiermgedréckt gëtt.{NEWLINE}Auto: Scroltl d'Kaart wann ee mat der Maus un de Rand geréit.\"\n  STR_TRIGGER_SCROLL: \"SCROLLEN AUSLEISEN\"\n  STR_AUTO_SCROLL: \"Automatesch\"\n  STR_DRAG_SCROLL: \"ZEISCROLLEN\"\n  STR_DRAG_SCROLL_DESC: \"Scrollt d'Kaart per gedréckter Maustast déi gezu gëtt.\"\n  STR_LEFT_MOUSE_BUTTON: \"Lénks Tast\"\n  STR_MIDDLE_MOUSE_BUTTON: \"Mëtteltast\"\n  STR_RIGHT_MOUSE_BUTTON: \"Riets Tast\"\n  STR_FIRE_SPEED: \"SCHEISSGESCHWINDEGKEET\"\n  STR_FIRE_SPEED_DESC: \"Ännert d'Geschwindegkeet vu Waffeprojektiler.\"\n  STR_PLAYER_MOVEMENT_SPEED: \"Geschwindegkeet vun der Spillerbewegung\"\n  STR_PLAYER_MOVEMENT_SPEED_DESC: \"Ännert d'Geschwindegkeet vun Eenheete vum Spiller.\"\n  STR_COMPUTER_MOVEMENT_SPEED: \"KI Bewegungsgeschwindegkeet\"\n  STR_COMPUTER_MOVEMENT_SPEED_DESC: \"Ännert d'Geschwindegkeet vun Eenheete vum Computer.\"\n  STR_PATH_PREVIEW: \"Wee-Virschau\"\n  STR_PATH_ARROWS: \"Feiler\"\n  STR_PATH_ARROWS_DESC: \"Nom Klicken gëtt den Wee ugewisen deen d'Eenheet wäerd goen. Eng Faarw weist méiglech Aktiounen un: Gréng - kann sech bewegen an schéissen; Giel - kann sech bewegen; Roud - kann sech net bewegen.\"\n  STR_PATH_TIME_UNIT_COST: \"Zäiteenheeten\"\n  STR_PATH_TIME_UNIT_COST_DESC: \"Bei Klick ginn d'ZE vun der Eenheet ugewisen déi nod er Bewegung iwwreg bleiwen .\"\n  STR_USER_INTERFACE_OPTIONS: \"UI Optiounen\"\n  STR_TOOLTIPS: \"Tooltips\"\n  STR_TOOLTIPS_DESC: \"Weist tooltips fir d'Battlescapeknäppercher un.\"\n  STR_DEATH_NOTIFICATIONS: \"Doudesnotifikatiounen\"\n  STR_DEATH_NOTIFICATIONS_DESC: \"Eng Notiz popupen déi detailléiert wann en Zaldot gestuerwen ass.\"\n  STR_SHOW_FUNDS: \"Gelder uweisen\"\n  STR_SHOW_FUNDS_DESC: \"Weist déi aktuell Gelder nierft der Geoscapeauer un.\"\n  STR_MISSION_GENERATOR: \"MISSIOUNEGENERATOR\"\n  STR_MAP_OPTIONS: \"KAARTENOPTIOUNEN\"\n  STR_ALIEN_OPTIONS: \"ALIENOPTIOUNEN\"\n  STR_MAP_TERRAIN: \"Terrain\"\n  STR_MAP_DARKNESS: \"Donkelheet\"\n  STR_MAP_DEPTH: \"Déift\"\n  STR_DIFFICULTY: \"Schwieregkeet\"\n  STR_ALIEN_RACE: \"Rass\"\n  STR_ALIEN_TECH_LEVEL: \"Tech-Level\"\n  STR_RANDOMIZE: \"Zoufälleg\"\n  STR_OXCE_REQUIRED_QUESTION: \"Dëse Mod brauch OpenXcom {0} fir korrekt ze lafen. Mod uschalten?\"\n  STR_RESTORE_DEFAULTS_QUESTION: \"Sécher, dass d'Standardoptioune solle geluede ginn?\"\n  STR_DISPLAY_OPTIONS_CONFIRM: \"Sollen déi aktuell Displayoptioune bäibehale ginn?\"\n  STR_DISPLAY_OPTIONS_REVERT: \"Zrécksetzen an: 0:{0}\"\n  STR_MISSING_CONTENT_PROMPT: \"WARNUNG:{SMALLLINE}Dëse Späicherstand benotzt Mods déi net verfügbar sinn. Den Content gëtt ewechgeholl, an et kann Problemer beim lueden ginn.{NEWLINE}Weiderman?\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT: \"Scharf Granate späichern\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT_DESC: \"Späichert scharf Granaten am Inventar am Zaldot sengem Equipment Layout.\"\n  STR_NEWSEEDONLOAD: \"Save scumming\"\n  STR_NEWSEEDONLOAD_DESC: \"Wann e Spill geluede gëtt, gëtt den Zoufallsgenerator zréckgesat, sou dass eng selwëscht Actioun verschiddenen Resultater kann hunn. Gëllt net fir Ironman-Modus.\"\n  STR_CHANGEVALUEBYMOUSEWHEEL: \"Werter mam Mausrad änneren\"\n  STR_CHANGEVALUEBYMOUSEWHEEL_DESC: \"Erlabt engem mam Mausrad Wäerter em dëse Montant ze änneren.\"\n  STR_BATTLEHAIRBLEACH: \"Erweidert Zaldote-Sprites\"\n  STR_BATTLEHAIRBLEACH_DESC: \"Änndert Zaldote Battlescape Sprites, dass se passend zum Inventarlook ausgesin.\"\n  STR_DRAGSCROLLINVERT: \"Invertéiert Zéi-Scrollen\"\n  STR_DRAGSCROLLINVERT_DESC: \"Wann ugeschalt, gëtt an déi géigesätzlech Richtung gescrollt wéi mat der Maus gezunn.\"\n  STR_BATTLESCAPE_SCALE: \"Battlescape-Skala\"\n  STR_BATTLESCAPE_SCALE_DESC: \"Battlescape Skaléiermodus, baséirend op enger fixer Opléisung (strecken dass et passt), oder e fixe Zoomlevel (auseneenzéie fir ze fëllen).\"\n  STR_GEOSCAPE_SCALE: \"Geoscape-Skala\"\n  STR_GEOSCAPESCALE_SCALE_DESC: \"Geoscape Skaléiermodus, baséirend op enger fixer Opléisung (strecken dass et passt), oder e fixe Zoomlevel (auseneenzéie fir ze fëllen).\"\n  STR_1_5X: \"1.5x Original\"\n  STR_2X: \"2x Original\"\n  STR_THIRD_DISPLAY: \"1/3 Display\"\n  STR_HALF_DISPLAY: \"1/2 Display\"\n  STR_FULL_DISPLAY: \"Vollen Display\"\n  STR_FPS_LIMIT: \"FPS Limit\"\n  STR_FPS_LIMIT_DESC: \"Limitéiert d'Biller pro Sekonn, 0 fir keng Limit ze setzen. Wann OpenGL ugewielt gouf, get Vsync vum Spill benotzt.\"\n  STR_FPS_INACTIVE_LIMIT: \"FPS Limit Hannergrond\"\n  STR_FPS_INACTIVE_LIMIT_DESC: \"Limitéiert d'Biller pro Sekonn, wann OpenXcom am Hannergrond leeft.\"\n  STR_NOALIENPANICMESSAGES: \"Panikmessagen vun Alien ënnerdrécken\"\n  STR_NOALIENPANICMESSAGES_DESC: \"Keng Panikmessagen vun den Alien uweisen, ausser se sinn a Sichtwäit vum Spiller.\"\n  STR_ALIENBLEEDING: \"Alienbluddung\"\n  STR_ALIENBLEEDING_DESC: \"Erlabt et dene meeschten Alien fatal Wonnen zouzeféiren.\"\n  STR_FIELDPROMOTIONS: \"Feldpromotiounen\"\n  STR_FIELDPROMOTIONS_DESC: \"Nëmmen Zaldoten déi um Missiounssite ware, kënnen eng Promotioun kréien.\"\n  STR_MEETINGPOINT: \"UFO Trajectoire virausgesinn\"\n  STR_MEETINGPOINT_DESC: \"Fliger fléien op e Meetingpunkt anhand vun dem UFO sénger aktueller Trajectoire.\"\n  STR_IRONMAN: \"IRONMAN\"\n  STR_IRONMAN_DESC: \"Kee manuellt Späichern\"\n  STR_SAVE_AND_ABANDON_GAME: \"SPAICHERN AN SPILL OFBRIECHEN\"\n  STR_MOD_UNSUCCESSFUL: \"Mod konnt net gelued ginn\"\n  STR_NEW_SAVED_GAME_SLOT: \"<NEIT GESPAICHERT SPILL>\"\n  STR_AUTO_SAVE_GEOSCAPE_SLOT: \"<AUTO GEOSCAPE>\"\n  STR_AUTO_SAVE_BATTLESCAPE_SLOT: \"<AUTO BATTLESCAPE>\"\n  STR_QUICK_SAVE_SLOT: \"<SCHNELLSPAICHERN>\"\n  STR_DISPLAY_MODE_DESC: \"Art vun Duerstellung um Bildschierm änneren.\"\n  STR_PREFERRED_MUSIC_FORMAT: \"Musik-Format\"\n  STR_PREFERRED_MUSIC_FORMAT_DESC: \"Wielt den Musik Format den soll benotzt ginn, wann der e puer verfügbar sinn.{NEWLINE}N.B: MIDI kann ënner Windows verbuggt sinn.\"\n  STR_PREFERRED_SFX_FORMAT: \"SFX-Format\"\n  STR_PREFERRED_SFX_FORMAT_DESC: \"Wielt den Sound Effekt den soll benotzt ginn, wann der e puer verfügbar sinn.\"\n  STR_PREFERRED_VIDEO_FORMAT: \"Video-Format\"\n  STR_PREFERRED_VIDEO_FORMAT_DESC: \"Wielt de préferéierte Video-Format aus wann et der e puer gëtt.\"\n  STR_PREFERRED_VIDEO_ANIMATION: \"Animatioun\"\n  STR_PREFERRED_VIDEO_SLIDESHOW: \"Slideshow\"\n  STR_PREFERRED_FORMAT_AUTO: \"Auto\"\n  STR_CURRENT_FORMAT: \"Momentan: {0}\"\n  STR_SOUND_OPTIONS: \"Soundoptiounen\"\n  STR_BACKGROUND_MUTE: \"Hannergrond stomm\"\n  STR_BACKGROUND_MUTE_DESC: \"All Sounds stomm schalten wann d'Fënster net aktiv ass.\"\n  STR_FORCE_FIRE: \"Schosslinn ignoréiren\"\n  STR_FORCE_FIRE_DESC: \"Erlabt Zaldoten per gedréckter CTRL-Tast ze schéissen och wann keng Schosslinn do ass.\"\n  STR_NO_AUDIO_HARDWARE_DETECTED: \"Keng Audio Hardware fonnt\"\n  STR_MOUSEWHEEL_SPEED: \"Mausrad Scrollgeschwindegkeet\"\n  STR_MOUSEWHEEL_SPEED_DESC: \"Definéiert wéivill Linnen op eemol gescrollt ginn mam Mausrad.\"\n  STR_DISABLED: \"Ausgeschalt\"\n  STR_MAXIMIZE_INFO_SCREENS: \"Infoschiermer maximiséiren\"\n  STR_MAXIMIZE_INFO_SCREENS_DESC: \"Inventar an verschidden aner Schiermer ginn am Vollbild ugewisen, egal wéi d'Skaléirung agestallt ass.\"\n  STR_DIARY: \"TAGEBUCH\"\n  STR_KILLED: \"EMBRUED\"\n  STR_STUNNED: \"BETÄUBT\"\n  STR_PANICKED: \"PANIKÉIERT\"\n  STR_MINDCONTROLLED: \"KONTROLLÉIERT\"\n  STR_REGION_UNKNOWN: \"Net genannt\"\n  STR_WEAPON_UNKNOWN: \"Improvisioun\"\n  STR_UNKNOWN: \"Onbekannt\"\n  STR_VICTORY: \"Triumph\"\n  STR_DEFEAT: \"Néierlag\"\n  STR_NO_RECORD: \"Näischt virzeweisen\"\n  STR_HUMAN: \"Mënsch\"\n  STR_FRIENDLY: \"Frëndlech\"\n  STR_HOSTILE: \"Feindlech\"\n  STR_NEUTRAL: \"Neutral\"\n  STR_RATING_UC: \"BEWERTUNG\"\n  STR_LOCATION: \"PLAZ> {ALT}{0}\"\n  STR_DAYLIGHT_TYPE: \"ZÄIT> {ALT}{0}\"\n  STR_RACE_TYPE: \"RASS> {ALT}{0}\"\n  STR_DAY: \"Dag\"\n  STR_NIGHT: \"Nuet\"\n  STR_DAYS_WOUNDED: \"DEEG VERWOND> {ALT}{0}\"\n  STR_COMBAT: \"KAMPF\"\n  STR_PERFORMANCE: \"PERFORMANCE\"\n  STR_NEUTRALIZATIONS_BY_RACE: \"NEUTRALISÉIRUNGEN NO RASS\"\n  STR_NEUTRALIZATIONS_BY_RANK: \"NEUTRALISÉIRUNGEN NO RANG\"\n  STR_NEUTRALIZATIONS_BY_WEAPON: \"NEUTRALISÉIRUNGEN NO WAFF\"\n  STR_MISSIONS_BY_LOCATION: \"MISSIOUNEN NO PLAZ\"\n  STR_MISSIONS_BY_TYPE: \"MISSIOUNEN NO TYP\"\n  STR_MISSIONS_BY_UFO: \"MISSIOUNEN NO UFO\"\n  STR_SCORE_VALUE: \"PUNKTEN> {ALT}{0}\"\n  STR_WINS: \"GEWONNEN> {ALT}{0}\"\n  STR_STUNS: \"BETÄUBT> {ALT}{0}\"\n  STR_PANICKS: \"PANIKEN> {ALT}{0}\"\n  STR_MINDCONTROLS: \"KONTROLLEN> {ALT}{0}\"\n  STR_AWARDS: \"AUSZEECHNUNGEN\"\n  STR_COMMENDATIONS_UC: \"KOMMENDATIOUNEN\"\n  STR_COMMENDATIONS: \"Kommendatiounen\"\n  STR_MEDALS: \"MEDAILLEN\"\n  STR_LOST_IN_SERVICE: \"AM KAMPF VERLUER GAANG\"\n  STR_MEDAL_NAME: \"Medaillennumm\"\n  STR_MEDAL_AWARD_LEVEL: \"Auszeechnungsniveau\"\n  STR_MEDAL_DECOR_LEVEL: \"Éirenauszeechnungslevel\"\n  STR_AWARD_0: \"Éischt Auszeechnung\"\n  STR_AWARD_1: \"Zweet Auszeechnung\"\n  STR_AWARD_2: \"Drëtt Auszeechnung\"\n  STR_AWARD_3: \"Véiert Auszeechnung\"\n  STR_AWARD_4: \"Fënneft Auszeechnung\"\n  STR_AWARD_5: \"Sechst Auszeechnung\"\n  STR_AWARD_6: \"Siwent Auszeechnung\"\n  STR_AWARD_7: \"Aacht Auszeechnung\"\n  STR_AWARD_8: \"Néngt Auszeechnung\"\n  STR_AWARD_9: \"Zéngt Auszeechnung\"\n  STR_AWARD_DECOR_0: \"Keng\"\n  STR_AWARD_DECOR_1: \"Éischte bronze Pin\"\n  STR_AWARD_DECOR_2: \"Zweete bronze Pin\"\n  STR_AWARD_DECOR_3: \"Drëtte bronze Pin\"\n  STR_AWARD_DECOR_4: \"Éischte sëlwer Pin\"\n  STR_AWARD_DECOR_5: \"Zweete sëlwer Pin\"\n  STR_AWARD_DECOR_6: \"Drëtte sëlwer Pin\"\n  STR_AWARD_DECOR_7: \"Éischte gëllene Pin\"\n  STR_AWARD_DECOR_8: \"Zweete gëllene Pin\"\n  STR_AWARD_DECOR_9: \"Drëtte gëllene Pin\"\n  STR_KILLED_IN_ACTION_MALE: \"AM KAMPF GESTUERWEN\"\n  STR_KILLED_IN_ACTION_FEMALE: \"AM KAMPF GESTUERWEN\"\n  STR_MISSING_IN_ACTION_MALE: \"AM KAMPF VERMËSST\"\n  STR_MISSING_IN_ACTION_FEMALE: \"AM KAMPF VERMËSST\"\n  STR_AVERAGE_MONTHLY_RATING: \"Duerchschnëttsbewertung am Mount\"\n  STR_TOTAL_INCOME: \"Totalt Akommes\"\n  STR_TOTAL_EXPENDITURE: \"Total Ausgaben\"\n  STR_MISSIONS_WON: \"Missiounen ofgeschloss\"\n  STR_MISSIONS_LOST: \"Missioune verluer\"\n  STR_NIGHT_MISSIONS: \"Nuetsmissiounen\"\n  STR_BEST_RATING: \"Bescht Missiounebewertung\"\n  STR_WORST_RATING: \"Schlechste Missiounebewertung\"\n  STR_ALIEN_KILLS: \"Alien embrued\"\n  STR_ALIEN_CAPTURES: \"Alien gefaangen\"\n  STR_FRIENDLY_KILLS: \"Beschoss durch eege Leit\"\n  STR_AVERAGE_ACCURACY: \"Duerchschnëttsgenauegkeet\"\n  STR_WEAPON_MOST_KILLS: \"Effektivste Waff\"\n  STR_ALIEN_MOST_KILLS: \"Déidlegsten Alien\"\n  STR_LONGEST_SERVICE: \"Meeschte Méint am Asaz\"\n  STR_TOTAL_DAYS_WOUNDED: \"Krank Deeg\"\n  STR_COUNTRIES_LOST: \"Länner infiltréiert\"\n  STR_TOTAL_TERROR_SITES: \"Terrorattacken\"\n  STR_TOTAL_BASES: \"Base gebaut\"\n  STR_TOTAL_CRAFT: \"Fligerbesëtz\"\n  STR_TOTAL_SCIENTISTS: \"Wëssenschaftler agestallt\"\n  STR_TOTAL_ENGINEERS: \"Ingenieuren agestallt\"\n  STR_TOTAL_RESEARCH: \"Fuerschungen ofgeschloss\"\n  STR_DIARY_ACCURACY: \"GENAUEGKEET> {ALT}{0}%\"\n  STR_STATISTICS: \"Statistiken\"\n  STR_STATS: \"STATS\"\n  STR_TIME_UNITS_ABBREVIATION: \"ZE\"\n  STR_STAMINA_ABBREVIATION: \"AUS\"\n  STR_HEALTH_ABBREVIATION: \"LP\"\n  STR_BRAVERY_ABBREVIATION: \"COU\"\n  STR_REACTIONS_ABBREVIATION: \"REA\"\n  STR_FIRING_ACCURACY_ABBREVIATION: \"GEN\"\n  STR_THROWING_ACCURACY_ABBREVIATION: \"WRF\"\n  STR_STRENGTH_ABBREVIATION: \"STR\"\n  STR_MELEE_ACCURACY_ABBREVIATION: \"NOK\"\n  STR_FOLDERS: \"DOSSIEREN\"\n  STR_DATA_FOLDER: \"Daten Dossier (Original Ressourcen)\"\n  STR_USER_FOLDER: \"Benotzer Dossier (Mods, openxcom.log)\"\n  STR_SAVE_FOLDER: \"Späicherdossier (gespäichert Spiller, Screenshoten)\"\n  STR_CONFIG_FOLDER: \"Konfiguratiouns Dossier (options.cfg)\"\n  STR_DATA_FOLDER_DESC_1: \"Hei sicht OpenXcom no den original Dateien (UFO an/oder TFTD)\"\n  STR_DATA_FOLDER_DESC_2: \"D'original intern Ressourcen  fir OpenXcom sinn am 'common' Dossier. OpenXcom built-in Mods sinn am 'standard' Dossier.\"\n  STR_USER_FOLDER_DESC: \"Hei fënnt een d'Logdatei ('openxcom.log'). All custom Mods kommen och hei eran (an den 'mods' Ënnerdossier).\"\n  STR_SAVE_FOLDER_DESC: \"Hei stinn d'Späicherstänn. Hei fënnt een och d'Missiounsgeneratorastellungen ('battle.cfg').\"\n  STR_CONFIG_FOLDER_DESC: \"Hei stinn d'OpenXcom Astellungen ('options.cfg'). Normalerweis dat selwescht wéi de Benotzerdossier.\"\n"
  },
  {
    "path": "bin/common/Language/lv.yml",
    "content": "lv:\n  STR_LOAD_SAVED_GAME: \"Ielādēt spēli\"\n  STR_SELECT_DIFFICULTY_LEVEL: \"Izvēlieties Grūtības Līmeni\"\n  STR_1_BEGINNER: \"1>Iesācējs\"\n  STR_2_EXPERIENCED: \"2> Pieredzējis\"\n  STR_3_VETERAN: \"3> Veterāns\"\n  STR_4_GENIUS: \"4> Ģēnijs\"\n  STR_5_SUPERHUMAN: \"5> Supercilvēks\"\n  STR_DATE: \"Datums\"\n  STR_SELECT_GAME_TO_LOAD: \"Izvēlēties kuru spēli ielādēt\"\n  STR_SELECT_SAVE_POSITION: \"Izvēlies pozīciju saglabāšanai\"\n  STR_LOAD_GAME: \"IELĀDĒT SPĒLI\"\n  STR_SAVE_GAME: \"SAGLABĀT SPĒLI\"\n  STR_ABANDON_GAME: \"PAMEST SPĒLI\"\n  STR_ABANDON_GAME_QUESTION: \"PAMEST SPĒLI?\"\n  STR_QUIT: \"Beigt\"\n  STR_LOAD_UNSUCCESSFUL: \"Ielāde neizdevās\"\n  STR_SAVE_UNSUCCESSFUL: \"Saglabāšana neizdevās\"\n  STR_LOAD_SUCCESSFUL: \"Ielāde veiksmīga\"\n  STR_SAVE_SUCCESSFUL: \"Saglabāšana veiksmīga\"\n  STR_DELETE_UNSUCCESSFUL: \"Dzēšana neizdevās\"\n  STR_IS_IT_OK_TO_DELETE_THE_SAVED_GAME: \"Vai esat pārliecināti ka gribat izdzēst šo saglabāto spēli?\"\n  STR_OPTIONS: \"Izvēles\"\n  STR_GENERAL: \"Generālis\"\n  STR_FPS_COUNTER: \"FPS Skaitītājs\"\n  STR_ROTATE_LEFT: \"Rotēt pa Kreisi\"\n  STR_ROTATE_RIGHT: \"Pagriezt pa labi\"\n  STR_ROTATE_DOWN: \"Rotēt uz leju\"\n  STR_ZOOM_IN: \"Tuvināt\"\n  STR_ZOOM_OUT: \"Tālināt\"\n  STR_TOGGLE_RADAR_RANGES: \"Pārslēgt Radaru diapazoni\"\n  STR_SCROLL_LEFT: \"Ritināt pa kreisi\"\n  STR_SCROLL_DOWN: \"Ritināt uz leju\"\n  STR_UNIT_LEVEL_ABOVE: \"Virzīt vienību līmeni augstāk\"\n  STR_PREVIOUS_UNIT: \"Izvēlēties Iepriekšējo Vienību\"\n  STR_NEXT_UNIT: \"Izvēlēties Nākamo Vienību\"\n  STR_USE_LEFT_HAND: \"Izmantot Kreisās Rokas ierīci\"\n  STR_USE_RIGHT_HAND: \"Izmantot Labās Rokas Ierīci\"\n  STR_INVENTORY: \"Inventārs\"\n  STR_MINIMAP: \"Sīkkarte\"\n  STR_END_TURN: \"Pabeigt gājienu\"\n  STR_KNEEL: \"Piecelties/Pietupties\"\n  STR_RESERVE_TIME_UNITS_FOR_AUTO_SHOT: \"Atlikt laika vienības šāvienu kārtai\"\n  STR_QUICK_SAVE: \"Ātrā saglabāšana\"\n  STR_ADVANCED: \"PAPILDUS\"\n  STR_BATTLEAUTOEND: \"Kaujas auto-beigšana\"\n  STR_BATTLEAUTOEND_DESC: \"Kaujas tiek automātiski pārtrauktas, kad pēdējais dzīvais pretinieks ir neitralizēts.\"\n  STR_BATTLEINSTANTGRENADE: \"Tūlītējās granātas\"\n  STR_BATTLEINSTANTGRENADE_DESC: \"Granātas uzstādītas uzsprāgt pēc 0 kārtām nekavējoties eksplodēs, kad tiks aizmestas, nevis kārtas beigās.\"\n  STR_BATTLEUFOEXTENDERACCURACY_DESC: \"Šāvienu precizitāte nokrītas pēc noteikta attāluma, saskaņā ar šāviena veidu. Koriģētā precizitāte tiks parādīta uz kursora.\"\n  STR_PLAYINTRO: \"Rādīt ievada filmu\"\n  STR_PLAYINTRO_DESC: \"Rādīt kino uzsākot spēli.\"\n  STR_SHOWMORESTATSININVENTORYVIEW: \"Inventāra Statistika\"\n  STR_SHOWMORESTATSININVENTORYVIEW_DESC: \"Parādīt papildus informāciju par izvēlēto karavīru inventāra ekrānā.\"\n  STR_AUTOSAVE: \"Auto-saglabāšanas režīms\"\n  STR_ALLOWPSIONICCAPTURE: \"Atļaut psi-notveršanu\"\n  STR_ANYTIMEPSITRAINING: \"Psioniskais treniņš jebkurā laikā\"\n  STR_ANYTIMEPSITRAINING_DESC: \"Ļaut piešķirt karavīrus uz Psionic mācībām jebkurā mēneša laikā. Atcerieties, ka sākotnējā apmācība ilgst no 30 līdz 60 dienām.\"\n  STR_SKIPNEXTTURNSCREEN: \"Izlaist \\\"Nākamo Gājienu\\\" ekrāns\"\n  STR_WEAPONSELFDESTRUCTION: \"Citplanētiešu ieroču paš-iznīcināšana\"\n  STR_WEAPONSELFDESTRUCTION_DESC: \"Ieroči, kurus izmanto citplanētieši paš iznīcināsies, ja to īpašnieks ir nogalināts, līdzīgi kā kā XCOM 2012.\"\n  STR_EXPEND_ALL_TIME_UNITS: \"Iztērēt atlikušās laika  vienības\"\n  STR_DISABLEAUTOEQUIP: \"Atslēgt automātisko aprīkošanu\"\n  STR_DISABLEAUTOEQUIP_DESC: \"Atslēgt automātisko aprīkošana jaunajiem karavīriem pirms kaujas.\"\n  STR_BATTLECONFIRMFIREMODE: \"Apstiprināt Šaušanas režīmu\"\n  STR_BATTLECONFIRMFIREMODE_DESC: \"Vajag uzklikšķināt divas reizes uz vienas flīzes, lai apstiprinātu šaušanas pavēles.\"\n  STR_DISPLAY_RESOLUTION: \"Displeja izšķirtspēja\"\n  STR_MUSIC_VOLUME: \"Mūzikas skaļums\"\n  STR_DRAG_SCROLL: \"RITINĀŠANA VELKOT\"\n  STR_FIRE_SPEED: \"ŠAUŠANAS ĀTRUMS\"\n  STR_DEATH_NOTIFICATIONS_DESC: \"Parādīt ziņojumu, kur detalizēts kurš tika nogalināts, kad kāds karavīrs nomira.\"\n  STR_FPS_LIMIT: \"FPS limits\"\n  STR_FPS_LIMIT_DESC: \"Ierobežot  ekrāna atjauninājumus skaitu vienā sekundē, 0 nozīmē, bez ierobežojuma. Ja OpenGL ir iespējots, spēle izmantos tā vietā Vsync.\"\n  STR_FPS_INACTIVE_LIMIT: \"FPS fona limits\"\n  STR_NOALIENPANICMESSAGES_DESC: \"Nerādīt panikas ziņojumus par citplanētiešiem, ja vien tie ir redzami XCOM aģentiem.\"\n  STR_IRONMAN_DESC: \"Nav manuālās saglabāšanas\"\n  STR_SAVE_AND_ABANDON_GAME: \"SAGLABĀT UN PAMEST SPĒLI\"\n  STR_MOD_UNSUCCESSFUL: \"Neizdevās ielādēt modifikāciju\"\n  STR_NO_AUDIO_HARDWARE_DETECTED: \"Nekāda aparatūra netika konstatēta\"\n  STR_MAXIMIZE_INFO_SCREENS: \"Maksimizēt informācijas ekrānus\"\n  STR_MAXIMIZE_INFO_SCREENS_DESC: \"Inventāris un dažādi citi ekrāni tiks rādīti pilnā ekrānā, neatkarīgi no mēroga iestatījumiem.\"\n  STR_UNKNOWN: \"Nezināms\"\n  STR_AWARD_DECOR_0: \"Nekāds\"\n"
  },
  {
    "path": "bin/common/Language/nl.yml",
    "content": "nl:\n  STR_OPENXCOM: \"OpenXcom\"\n  STR_NEW_GAME: \"Nieuw Spel\"\n  STR_LOAD_SAVED_GAME: \"Spel Laden\"\n  STR_SELECT_DIFFICULTY_LEVEL: \"Kies Moeilijkheidsgraad\"\n  STR_1_BEGINNER: \"1> Beginner\"\n  STR_2_EXPERIENCED: \"2> Ervaren\"\n  STR_3_VETERAN: \"3> Veteraan\"\n  STR_4_GENIUS: \"4> Genie\"\n  STR_5_SUPERHUMAN: \"5> Supermens\"\n  STR_TIME: \"Tijd\"\n  STR_DATE: \"Datum\"\n  STR_SELECT_GAME_TO_LOAD: \"Kies te laden spel\"\n  STR_SELECT_SAVE_POSITION: \"Kies opslagpositie\"\n  STR_GAME_OPTIONS: \"SPELOPTIES\"\n  STR_LOAD_GAME: \"SPEL LADEN\"\n  STR_SAVE_GAME: \"SPEL OPSLAAN\"\n  STR_ABANDON_GAME: \"SPEL AFBREKEN\"\n  STR_ABANDON_GAME_QUESTION: \"SPEL AFBREKEN?\"\n  STR_QUIT: \"Afsluiten\"\n  STR_SAVING_GAME: \"Opslaan spel\"\n  STR_LOADING_GAME: \"Laden spel\"\n  STR_NO_SAVED_GAME_PRESENT: \"Geen opgeslagen spel\"\n  STR_LOAD_UNSUCCESSFUL: \"Spel niet geladen\"\n  STR_SAVE_UNSUCCESSFUL: \"Spel niet opgeslagen\"\n  STR_LOAD_SUCCESSFUL: \"Spel geladen\"\n  STR_SAVE_SUCCESSFUL: \"Spel opgeslagen\"\n  STR_DELETE: \"VERWIJDER\"\n  STR_DELETE_UNSUCCESSFUL: \"Niet verwijderd\"\n  STR_IS_IT_OK_TO_DELETE_THE_SAVED_GAME: \"Opgeslagen spel verwijderen?\"\n  STR_ORIGINAL_XCOM: \"Originele X-Com\"\n  STR_LOADING: \"Laden...\"\n  STR_DETAILS: \"DETAILS> {ALT}{0}\"\n  STR_NEW_BATTLE: \"Nieuw Gevecht\"\n  STR_OPTIONS: \"Opties\"\n  STR_RIGHT_CLICK_TO_DELETE: \"Rechtsklikken verwijdert een spel\"\n  STR_RESTORE_DEFAULTS: \"Standaardinstellingen\"\n  STR_CONTROLS: \"BESTURING\"\n  STR_GENERAL: \"Algemeen\"\n  STR_GEOSCAPE: \"Globe\"\n  STR_BATTLESCAPE: \"Gevechtsscherm\"\n  STR_SCREENSHOT: \"Schermafbeelding\"\n  STR_FPS_COUNTER: \"FPS-teller\"\n  STR_ROTATE_LEFT: \"Linksom Draaien\"\n  STR_ROTATE_RIGHT: \"Rechtsom Draaien\"\n  STR_ROTATE_UP: \"Omhoog Draaien\"\n  STR_ROTATE_DOWN: \"Omlaag Draaien\"\n  STR_ZOOM_IN: \"Inzoomen\"\n  STR_ZOOM_OUT: \"Uitzoomen\"\n  STR_TOGGLE_COUNTRY_DETAIL: \"Landen wel/niet in detail tonen\"\n  STR_TOGGLE_RADAR_RANGES: \"Radarbereik wel/niet weergeven\"\n  STR_SCROLL_LEFT: \"Links Schuiven\"\n  STR_SCROLL_RIGHT: \"Rechts Schuiven\"\n  STR_SCROLL_UP: \"Omhoog Schuiven\"\n  STR_SCROLL_DOWN: \"Omlaag Schuiven\"\n  STR_UNIT_LEVEL_ABOVE: \"Eenheid naar Bovenliggend Niveau Verplaatsen\"\n  STR_UNIT_LEVEL_BELOW: \"Eenheid naar Onderliggend Niveau Verplaatsen\"\n  STR_VIEW_LEVEL_ABOVE: \"Bovenliggend Niveau Tonen\"\n  STR_VIEW_LEVEL_BELOW: \"Onderliggend Niveau Tonen\"\n  STR_CENTER_SELECTED_UNIT: \"Geselecteerde Eenheid Centreren\"\n  STR_PREVIOUS_UNIT: \"Vorige Eenheid Selecteren\"\n  STR_NEXT_UNIT: \"Volgende Eenheid Selecteren\"\n  STR_DESELECT_UNIT: \"Eenheid Niet Herselecteren\"\n  STR_USE_LEFT_HAND: \"Gebruik Linkerhands Voorwerp\"\n  STR_USE_RIGHT_HAND: \"Gebruik Rechterhands Voorwerp\"\n  STR_INVENTORY: \"Inventaris\"\n  STR_MINIMAP: \"Mini-kaart\"\n  STR_MULTI_LEVEL_VIEW: \"Meerdere Niveaus Tonen\"\n  STR_END_TURN: \"Beurt Beëindigen\"\n  STR_ABORT_MISSION: \"Missie Afbreken\"\n  STR_UNIT_STATS: \"Eigenschappen van Eenheden\"\n  STR_KNEEL: \"Knielen\"\n  STR_RELOAD: \"Herladen\"\n  STR_TOGGLE_PERSONAL_LIGHTING: \"Persoonlijke Belichting Aan/Uitzetten\"\n  STR_DONT_RESERVE_TIME_UNITS: \"Geen AP Reserveren\"\n  STR_RESERVE_TIME_UNITS_FOR_SNAP_SHOT: \"AP Reserveren voor Vlug Schot\"\n  STR_RESERVE_TIME_UNITS_FOR_AIMED_SHOT: \"AP Reserveren voor Gericht Schot\"\n  STR_RESERVE_TIME_UNITS_FOR_AUTO_SHOT: \"AP Reserveren voor Autom. Schot\"\n  STR_CENTER_ON_ENEMY_1: \"Centreren op Vijand 1\"\n  STR_CENTER_ON_ENEMY_2: \"Centreren op Vijand 2\"\n  STR_CENTER_ON_ENEMY_3: \"Centreren op Vijand 3\"\n  STR_CENTER_ON_ENEMY_4: \"Centreren op Vijand 4\"\n  STR_CENTER_ON_ENEMY_5: \"Centreren op Vijand 5\"\n  STR_CENTER_ON_ENEMY_6: \"Centreren op Vijand 6\"\n  STR_CENTER_ON_ENEMY_7: \"Centreren op Vijand 7\"\n  STR_CENTER_ON_ENEMY_8: \"Centreren op Vijand 8\"\n  STR_CENTER_ON_ENEMY_9: \"Centreren op Vijand 9\"\n  STR_CENTER_ON_ENEMY_10: \"Centreren op Vijand 10\"\n  STR_CREATE_INVENTORY_TEMPLATE: \"Maak inventaris sjabloon\"\n  STR_APPLY_INVENTORY_TEMPLATE: \"Pas inventaris sjabloon toe\"\n  STR_CLEAR_INVENTORY: \"Wis inventaris\"\n  STR_AUTO_EQUIP: \"Automatisch uitrusten\"\n  STR_QUICK_SAVE: \"Snel Opslaan\"\n  STR_QUICK_LOAD: \"Snel Laden\"\n  STR_ADVANCED: \"GEAVANCEERD\"\n  STR_AGGRESSIVERETALIATION: \"Aggressieve wraakacties\"\n  STR_AGGRESSIVERETALIATION_DESC: \"UFO's zullen altijd proberen je basissen op te sporen, onafhankelijk van de parameters van hun missie.\"\n  STR_STORAGELIMITSENFORCED: \"Opslaglimieten voor gevonden voorwerpen\"\n  STR_STORAGELIMITSENFORCED_DESC: \"Handhaaft limieten voor inperking van aliens en algemene opslag voor levende aliens en in beslag genomen artefacten uit missies.\"\n  STR_CANSELLLIVEALIENS: \"Verkoop levende buitenaardsen\"\n  STR_CANSELLLIVEALIENS_DESC: \"Laat de verkoop van levende aliens toe, aanbevolen wanneer er opslaglimieten worden toegepast.\"\n  STR_ALLOWBUILDINGQUEUE: \"Aanbouwplanning\"\n  STR_ALLOWBUILDINGQUEUE_DESC: \"Nieuwe faciliteiten kunnen naast onafgewerkte worden geplaatst.\"\n  STR_BATTLEAUTOEND: \"Automatische gevechtsbeëindiging\"\n  STR_BATTLEAUTOEND_DESC: \"Gevechten eindigen vanzelf wanneer de laatste levende vijand is geneutraliseerd.\"\n  STR_BATTLEINSTANTGRENADE: \"Instant-granaten\"\n  STR_BATTLEINSTANTGRENADE_DESC: \"Granaten die ingesteld zijn op 0 beurten zullen direct ontploffen na het gooien in plaats van aan het eind van de beury.\"\n  STR_BATTLEUFOEXTENDERACCURACY: \"Nauwkeurigheid UFO Extender\"\n  STR_BATTLEUFOEXTENDERACCURACY_DESC: \"Accuraatheid van schoten vermindert na een zekere afstand, afhankelijk van het schottype. Bijgestelde accuraatheid zal worden weergegeven op de cursor.\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE: \"Vliegende overdracht\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE_DESC: \"Vaartuigen die zich op dit moment in de lucht bevinden kunnen worden overgedragen.\"\n  STR_CRAFTLAUNCHALWAYS: \"Vaartuigen geforceerd lanceren\"\n  STR_CRAFTLAUNCHALWAYS_DESC: \"Vaartuigen kunnen zelfs als ze nog niet klaar zijn gelanceerd worden, waardoor onderhoud niet nodig is.\"\n  STR_CUSTOMINITIALBASE: \"Afwijkende startbasis\"\n  STR_CUSTOMINITIALBASE_DESC: \"Als je een nieuw spel begint kun je handmatig je initiële faciliteiten bepalen in plaats van de standaardindeling.\"\n  STR_GLOBESEASONS: \"Realistische wereldbolbelichting\"\n  STR_GLOBESEASONS_DESC: \"Gebruikt een realistischer projectie van zonlicht op de Geoscape overeenkomstig met de axiale variatie van de Aarde.\"\n  STR_PLAYINTRO: \"Intro spelen\"\n  STR_PLAYINTRO_DESC: \"Toont de cinematische introductie bij het opstarten.\"\n  STR_SHOWMORESTATSININVENTORYVIEW: \"Inventaris Statistieken\"\n  STR_SHOWMORESTATSININVENTORYVIEW_DESC: \"Extra informatie tonen over de geselecteerde soldaat in het inventaris-scherm.\"\n  STR_SNEAKYAI: \"Sluipende AI\"\n  STR_SNEAKYAI_DESC: \"De AI voorkomt, wanneer mogelijk, dat hij zijn locatie onthult aan de speler.\"\n  STR_STRAFE: \"Alternatieve manieren van bewegen\"\n  STR_STRAFE_DESC: \"Activeert zijwaarts bewegen, rennen en het onafhankelijk bewegen van tankgeschuttoren als je CTRL ingedrukt houdt.\"\n  STR_BATTLEEXPLOSIONHEIGHT: \"Explosie-hoogte\"\n  STR_BATTLEEXPLOSIONHEIGHT_DESC: \"Stel in hoe ver explosies de hoogte in mogen gaan.{NEWLINE}(Plat: 0, Rond: 3)\"\n  STR_AUTOSAVE: \"Automatisch opslaan\"\n  STR_AUTOSAVE_DESC: \"Slaat automatisch het spel op op bepaalde tijdstippen. Niet van toepassing op IJzerman-modus.\"\n  STR_AUTOSAVE_FREQUENCY: \"Frequentie van automatisch opslaan\"\n  STR_AUTOSAVE_FREQUENCY_DESC: \"De hoeveelheid beurten waarna het spel automatisch wordt opgeslagen.\"\n  STR_ALLOWPSIONICCAPTURE: \"Toestaan psi-vangst\"\n  STR_ALLOWPSIONICCAPTURE_DESC: \"Door alle overgebleven buitenaardsen te hersenspoelen behaal je een overwinning, omdat dit telt als een gevangenneming.\"\n  STR_ANYTIMEPSITRAINING: \"Psionische training op ieder moment\"\n  STR_ANYTIMEPSITRAINING_DESC: \"Staat het toewijzen van soldaten aan psionische training de hele maand toe. Onthoud dat de eerste training 30 tot 60 dagen in beslag neemt.\"\n  STR_SKIPNEXTTURNSCREEN: \"Sla \\\"Volgende beurt\\\" scherm over\"\n  STR_SKIPNEXTTURNSCREEN_DESC: \"''Volgende Beurt'' schermen tijdens gevechten worden automatisch doorgeschakeld na een korte vertraging.\"\n  STR_NOT_ENOUGH_SPACE: \"Onvoldoende Ruimte!\"\n  STR_WEAPONSELFDESTRUCTION: \"Zelfvernietigende buitenaardse wapens\"\n  STR_WEAPONSELFDESTRUCTION_DESC: \"Wapens gedragen door aliens vernietigen zichzelf als hun eigenaar gedood is, net zoals in XCOM 2012.\"\n  STR_RETAINCORPSES: \"Ondervraagde aliens behouden\"\n  STR_RETAINCORPSES_DESC: \"Na \\\"onderzoek\\\" van levende aliens zal het lichaam worden toegevoegd aan de opslagplaatsen van de basis, zoals in XCOM 2012.\"\n  STR_SAVE_VOXEL_VIEW: \"Schermafbeelding van Gezichtsveld\"\n  STR_RESERVE_TIME_UNITS_FOR_KNEEL: \"AP Reserveren voor Knielen\"\n  STR_EXPEND_ALL_TIME_UNITS: \"Alle resterende actiepunten opmaken\"\n  STR_PSISTRENGTHEVAL: \"Evaluatie Psi-kracht\"\n  STR_PSISTRENGTHEVAL_DESC: \"Evalueert de psionische kracht van alle soldaten nadat het geschikte onderzoek voltooid is.\"\n  STR_DISABLEAUTOEQUIP: \"Automatisch uitrusten uitschakelen\"\n  STR_DISABLEAUTOEQUIP_DESC: \"Automatisch uitrusten van nieuwe soldaten voor een gevecht uitschakelen\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT: \"Laat bevordering van Psi-kracht toe\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT_DESC: \"Psionische kracht van de soldaten kan worden bevorderd door ervaring en training.\"\n  STR_BATTLESMOOTHCAMERA: \"Effen Kogel Camera\"\n  STR_BATTLESMOOTHCAMERA_DESC: \"De camera van het gevechtsscherm blijft gecentreerd op projectielen terwijl ze vliegen.\"\n  STR_BATTLECONFIRMFIREMODE: \"Bevestig vuurmodus\"\n  STR_BATTLECONFIRMFIREMODE_DESC: \"Vereis een tweede klik op dezelfde plek om vuurorders te bevestigen.\"\n  STR_SELECT_BASE_1: \"Selecteer Basis 1\"\n  STR_SELECT_BASE_2: \"Selecteer Basis 2\"\n  STR_SELECT_BASE_3: \"Selecteer Basis 3\"\n  STR_SELECT_BASE_4: \"Selecteer Basis 4\"\n  STR_SELECT_BASE_5: \"Selecteer Basis 5\"\n  STR_SELECT_BASE_6: \"Selecteer Basis 6\"\n  STR_SELECT_BASE_7: \"Selecteer Basis 7\"\n  STR_SELECT_BASE_8: \"Selecteer Basis 8\"\n  STR_VIDEO: \"VIDEO\"\n  STR_AUDIO: \"AUDIO\"\n  STR_BATTLESCAPE_UC: \"GEVECHTSSCHERM\"\n  STR_MODS_UC: \"MODS\"\n  STR_MODS: \"Mods\"\n  STR_DISPLAY_RESOLUTION: \"Schermresolutie\"\n  STR_DISPLAY_RESOLUTION_DESC: \"Wijzigt de resolutie van het scherm; de resolutie van het spel zal hiernaar worden aangepast. Pijltjes schakelen tussen ondersteunde resoluties. Klik op een aangepaste resolutie in te voeren.\"\n  STR_ORIGINAL: \"Orgineel\"\n  STR_DISPLAY_MODE: \"Scherm-modus\"\n  STR_WINDOWED: \"Venster\"\n  STR_FULLSCREEN: \"Volledig scherm\"\n  STR_BORDERLESS: \"Zonder rand\"\n  STR_DISPLAY_LANGUAGE: \"Weergavetaal\"\n  STR_DISPLAY_LANGUAGE_DESC: \"Wijzigt de taal van de tekst in het spel.\"\n  STR_DISPLAY_FILTER: \"Weergavefilter\"\n  STR_DISPLAY_FILTER_DESC: \"Wijzigt de filter die wordt toegepast op het spelscherm.{NEWLINE}*vereist OpenGL hardwareacceleratie.\"\n  STR_DISPLAY_OPTIONS: \"Weergaveopties\"\n  STR_LETTERBOXED: \"Geletterboxt\"\n  STR_LETTERBOXED_DESC: \"Letterboxt het scherm om het originele aspectratio te behouden.\"\n  STR_RESIZABLE: \"Aanpasbaar\"\n  STR_LOCK_MOUSE: \"Grijp Muis\"\n  STR_LOCK_MOUSE_DESC: \"Voorkomt dat de muis cursor uit het scherm gaat. Ctrl+G om om te schakelen op elk moment.\"\n  STR_FIXED_WINDOW_POSITION: \"Vaste vensterpositie\"\n  STR_FIXED_WINDOW_POSITION_DESC: \"Zet vaste positie naar venster.\"\n  STR_DISPLAY_SET_WINDOW_POSITION: \"Zet nieuwe kernpositie voor het venster\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_X: \"Linkse rand nieuwe X:\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_Y: \"Bovenste rand nieuwe Y:\"\n  STR_MUSIC_VOLUME: \"Volumne Muziek\"\n  STR_MUSIC_VOLUME_DESC: \"Wijzigt het volume van de achtergrondmuziek.\"\n  STR_SFX_VOLUME: \"Volume Effecten\"\n  STR_SFX_VOLUME_DESC: \"Wijzigt het volume van de geluidseffecten.\"\n  STR_UI_VOLUME: \"Gebruikersinterface volume\"\n  STR_UI_VOLUME_DESC: \"Wijzigt het volume van de interface signalen.\"\n  STR_SCROLL_SPEED: \"VERSCHUIVINGSSNELHEID\"\n  STR_SCROLL_SPEED_GEO_DESC: \"Wijzigt de verschuivingssnelheid van de wereldbol.\"\n  STR_SCROLL_SPEED_BATTLE_DESC: \"Wijzigt de verschuivingssnelheid van de kaart.\"\n  STR_DOGFIGHT_SPEED: \"Vechtpartij snelheid\"\n  STR_DOGFIGHT_SPEED_DESC: \"Wijzigt de snelheid van de onderscheppingsgevechten tussen vaartuigen en UFO's. Tragere snelheden kunnen performantie op low-end toestellen verbeteren.\"\n  STR_CLOCK_SPEED: \"Kloksnelheid\"\n  STR_CLOCK_SPEED_DESC: \"Wijzigt de snelheid van de Geoscape-klok. Tragere snelheden kunnen performantie op low-end toestellen verbeteren.\"\n  STR_GLOBE_DETAILS: \"Wereld details\"\n  STR_GLOBE_COUNTRIES: \"Landen\"\n  STR_GLOBE_COUNTRIES_DESC: \"Toont financierende landen op de wereldbol.\"\n  STR_GLOBE_RADARS: \"Radars\"\n  STR_GLOBE_RADARS_DESC: \"Toont radarbereik van de basis op de wereldbol.\"\n  STR_GLOBE_FLIGHT_PATHS: \"Vliegroutes\"\n  STR_GLOBE_FLIGHT_PATHS_DESC: \"Toont vliegroutes van vaartuigen op de wereldbol.\"\n  STR_CONTROLS_DESC: \"Klik links op een sneltoets en druk op een toets om het te wijzigen.{NEWLINE}Klik rechts op een sneltoets om hem uit te schakelen.\"\n  STR_BASE_GAME: \"Basisspel\"\n  STR_MODS_TOOLTIP: \"Versie {0} door {1}.{NEWLINE}{2}\"\n  STR_EDGE_SCROLL: \"Randverschuiving\"\n  STR_EDGE_SCROLL_DESC: \"Trigger: Beweeg kaart wanneer de linkermuis knop is ingedrukt aan de rand van een scherm.{NEWLINE}Auto: Beweeg kaart wanneer de aanwijzer over de rand  van een scherm is.\"\n  STR_TRIGGER_SCROLL: \"KLIK OM TE VERSCHUIVEN\"\n  STR_AUTO_SCROLL: \"AUTOMATISCH VERSCHUIVEN\"\n  STR_DRAG_SCROLL: \"SLEEP OM TE VERSCHUIVEN\"\n  STR_DRAG_SCROLL_DESC: \"Beweeg de kaart wanneer de aangegeven muisknop is ingedrukt en wordt gesleept.\"\n  STR_LEFT_MOUSE_BUTTON: \"Linkermuisknop\"\n  STR_MIDDLE_MOUSE_BUTTON: \"Middelmuisknop\"\n  STR_RIGHT_MOUSE_BUTTON: \"Rechtermuisknop\"\n  STR_FIRE_SPEED: \"VUURSNELHEID\"\n  STR_FIRE_SPEED_DESC: \"Verandert de snelheid van wapenprojectielen.\"\n  STR_PLAYER_MOVEMENT_SPEED: \"Bewegingssnelheid van speler\"\n  STR_PLAYER_MOVEMENT_SPEED_DESC: \"Verandert de bewegingssnelheid van eenheden die door de speler worden bestuurd.\"\n  STR_COMPUTER_MOVEMENT_SPEED: \"Bewegingssnelheid van AI\"\n  STR_COMPUTER_MOVEMENT_SPEED_DESC: \"Verandert de bewegingssnelheid van eenheden die door de computer worden bestuurd.\"\n  STR_PATH_PREVIEW: \"Voorbeeldpad\"\n  STR_PATH_ARROWS: \"Pijltjes\"\n  STR_PATH_ARROWS_DESC: \"Door te klikken zie je het pad dat je eenheid naar zijn bestemming zal nemen. De kleur duidt op beschikbare acties: Groen - kan zich bewegen en schieten; Geel - kan zich bewegen; Rood - kan zich niet bewegen.\"\n  STR_PATH_TIME_UNIT_COST: \"Tijdseenheden\"\n  STR_PATH_TIME_UNIT_COST_DESC: \"Klikken toont de TUs die je eenheid over heeft na bewegen naar doel.\"\n  STR_USER_INTERFACE_OPTIONS: \"Gebruikersinterface-opties\"\n  STR_TOOLTIPS: \"Tooltips\"\n  STR_TOOLTIPS_DESC: \"Toon tooltips voor de Battlescape knoppen.\"\n  STR_DEATH_NOTIFICATIONS: \"Toon Sterfmeldingen\"\n  STR_DEATH_NOTIFICATIONS_DESC: \"Laat iedere keer een melding zien als een van je soldaten sterft.\"\n  STR_SHOW_FUNDS: \"Toon geld\"\n  STR_SHOW_FUNDS_DESC: \"Toon je huidige kapitaal naast de Geoscape klok\"\n  STR_MISSION_GENERATOR: \"MISSIE GENERATOR\"\n  STR_MAP_OPTIONS: \"KAARTOPTIES\"\n  STR_ALIEN_OPTIONS: \"ALIEN OPTIES\"\n  STR_MAP_TERRAIN: \"Terrein\"\n  STR_MAP_DARKNESS: \"Donkerheid\"\n  STR_MAP_DEPTH: \"Diepte\"\n  STR_DIFFICULTY: \"Moeilijkheidsgraad\"\n  STR_ALIEN_RACE: \"Ras\"\n  STR_ALIEN_TECH_LEVEL: \"Technologieniveau\"\n  STR_RANDOMIZE: \"Willekeurig\"\n  STR_OXCE_REQUIRED_QUESTION: \"Deze mod vereist OpenXcom [0] om correct te werken. Deze mod inschakelen?\"\n  STR_RESTORE_DEFAULTS_QUESTION: \"Weet je zeker dat je de standaardopties wil herstellen?\"\n  STR_DISPLAY_OPTIONS_CONFIRM: \"Wil je de huidige weergaveopties behouden?\"\n  STR_DISPLAY_OPTIONS_REVERT: \"Wordt teruggezet in 0:{0}\"\n  STR_MISSING_CONTENT_PROMPT: \"WAARSCHUWING:{SMALLLINE}Het opgeslagen spel gebruikt mods die niet beschikbaar zijn. Ontbrekende inhoud wordt verwijderd en het inladen kan mislukken.{NEWLINE}Doorgaan?\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT: \"Sla geactiveerde granaten op\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT_DESC: \"Slaat geactiveerde granaten op gedurende pre-gevecht inventaris van de soldaten.\"\n  STR_NEWSEEDONLOAD: \"Veel opslaan valsspelen\"\n  STR_NEWSEEDONLOAD_DESC: \"Een spel laden zal de random-nummer seed resetten, zodat de zelfde genomen actie een ander resultaat kan hebben. Niet van toepassing op Ijzerman mode.\"\n  STR_CHANGEVALUEBYMOUSEWHEEL: \"Wijzig waarden met muiswiel\"\n  STR_CHANGEVALUEBYMOUSEWHEEL_DESC: \"Staat toe de muiswiel te gebruiken om met deze waarden te verhogen/verlagen.\"\n  STR_BATTLEHAIRBLEACH: \"Verbeterde soldaatsprites\"\n  STR_BATTLEHAIRBLEACH_DESC: \"Verandert soldaat Battlescape plaatjes aan bijpassende inventaris uitstraling.\"\n  STR_DRAGSCROLLINVERT: \"Omgekeerd sleep scrollen\"\n  STR_DRAGSCROLLINVERT_DESC: \"Wanneer ingeschakeld, sleept scrollen in tegenovergestelde richting van de muis\"\n  STR_BATTLESCAPE_SCALE: \"Gevechtsscherm schaal\"\n  STR_BATTLESCAPE_SCALE_DESC: \"Gevechts-scape zichtspoort schaal mode, gebaseerd op een vaste resolutie(gestrekt om te passen), of een vast zoom niveau(uitgebreid om te vullen).\"\n  STR_GEOSCAPE_SCALE: \"Geoscape schaal\"\n  STR_GEOSCAPESCALE_SCALE_DESC: \"Globaal-scape zichtspoort schaal mode, gebaseerd op een vaste resolutie(gestrekt om te passen), of een vast zoom niveau(uitgebreid om te vullen).\"\n  STR_1_5X: \"1.5x origineel\"\n  STR_2X: \"2x origineel\"\n  STR_THIRD_DISPLAY: \"1/3 scherm\"\n  STR_HALF_DISPLAY: \"1/2 scherm\"\n  STR_FULL_DISPLAY: \"Volledig scherm\"\n  STR_FPS_LIMIT: \"FPS limiet\"\n  STR_FPS_LIMIT_DESC: \"Beperkt het aantal scherm updates per seconde, 0 voor geen limiet. Als OpenGL rendering is ingeschakeld, maakt het spel inplaats gebruik van Vsync.\"\n  STR_FPS_INACTIVE_LIMIT: \"FPS limiet achtergrond\"\n  STR_FPS_INACTIVE_LIMIT_DESC: \"Beperkt het aantal scherm verversingen per seconden wanneer OpenXcom in de achterground draait\"\n  STR_NOALIENPANICMESSAGES: \"Onderdruk paniek berichten voor buitenaardse wezens\"\n  STR_NOALIENPANICMESSAGES_DESC: \"Laat geen paniek berichten zien voor aliens tenzij deze zichtbaar zijn voor de speler.\"\n  STR_ALIENBLEEDING: \"Buitenaards wezen bloedt\"\n  STR_ALIENBLEEDING_DESC: \"Laat fatale wonden ook voorkomen bij de meeste aliens.\"\n  STR_FIELDPROMOTIONS: \"Veld promoties\"\n  STR_FIELDPROMOTIONS_DESC: \"Enkel soldaten die aanwezig zijn op de missie locatie komen in aanmerking voor promotie\"\n  STR_MEETINGPOINT: \"Voorspel UFO baan\"\n  STR_MEETINGPOINT_DESC: \"Voertuig vliegt naar een ontmoetingspunt met de UFO gebasseerd op de huidige baan\"\n  STR_IRONMAN: \"IJZERMAN\"\n  STR_IRONMAN_DESC: \"Geen handmatig opslaan\"\n  STR_SAVE_AND_ABANDON_GAME: \"SPEL OPSLAAN EN AFSLUITEN\"\n  STR_MOD_UNSUCCESSFUL: \"Mod is niet geladen\"\n  STR_NEW_SAVED_GAME_SLOT: \"<NIEUW OPGESLAGEN SPEL>\"\n  STR_AUTO_SAVE_GEOSCAPE_SLOT: \"<AUTO GEOSCAPE>\"\n  STR_AUTO_SAVE_BATTLESCAPE_SLOT: \"<AUTO BATTLESCAPE>\"\n  STR_QUICK_SAVE_SLOT: \"<QUICKSAVE> <Snelle Save>\"\n  STR_DISPLAY_MODE_DESC: \"Verander hoe het spel word weergegeven op het scherm.\"\n  STR_PREFERRED_MUSIC_FORMAT: \"Muziek formaat\"\n  STR_PREFERRED_MUSIC_FORMAT_DESC: \"Kiest het voorkeurs muziekformaat te gebruiken wanneer er meerdere beschikbaar zijn.{NEWLINE}OPMERKING: Afspelen van MIDI kan onstabiel zijn voor Windows.\"\n  STR_PREFERRED_SFX_FORMAT: \"Geluids Effecten Formaat\"\n  STR_PREFERRED_SFX_FORMAT_DESC: \"Kiest formaat voorkeurs geluidseffecten  te gebruiken wanneer er meerdere beschikbaar zijn\"\n  STR_PREFERRED_VIDEO_FORMAT: \"Video Formaat\"\n  STR_PREFERRED_VIDEO_FORMAT_DESC: \"Kiest voorkeurs video formaat te gebruiken wanneer er meerdere beschikbaar zijn.\"\n  STR_PREFERRED_VIDEO_ANIMATION: \"Animatie\"\n  STR_PREFERRED_VIDEO_SLIDESHOW: \"Dia show\"\n  STR_PREFERRED_FORMAT_AUTO: \"AUTOMATISCH VERSCHUIVEN\"\n  STR_CURRENT_FORMAT: \"Huidige: {0}\"\n  STR_SOUND_OPTIONS: \"Geluidsopties\"\n  STR_BACKGROUND_MUTE: \"Achtergrond geluid uitzetten\"\n  STR_BACKGROUND_MUTE_DESC: \"Alle geluids uitzetten wanneer het spelscherm niet actief is.\"\n  STR_FORCE_FIRE: \"Negeer vuurlinie\"\n  STR_FORCE_FIRE_DESC: \"Sta toe je soldaten te dwingen een schot te nemen wanneer CTRL is ingehouden en de vuurlinie regels te negeren.\"\n  STR_NO_AUDIO_HARDWARE_DETECTED: \"Geen audio hardware gedetecteerd\"\n  STR_MOUSEWHEEL_SPEED: \"Muiswiel rol snelheid\"\n  STR_MOUSEWHEEL_SPEED_DESC: \"Pas het aantal lijnen waarmee wordt gerold in de lijst aan met het muiswiel\"\n  STR_DISABLED: \"Uitgeschakeld\"\n  STR_MAXIMIZE_INFO_SCREENS: \"Maximalizeer Info Schermen\"\n  STR_MAXIMIZE_INFO_SCREENS_DESC: \"Inventaris en diverse andere schermen zullen op volledig scherm worden afgebeeld, ongeacht van schaal instellingen.\"\n  STR_DIARY: \"DAGBOEK\"\n  STR_KILLED: \"GEDOOD\"\n  STR_STUNNED: \"WEZENLOOS GERAAKT\"\n  STR_PANICKED: \"IN PANIEK GERAAKT\"\n  STR_MINDCONTROLLED: \"GECONTROLLEERD\"\n  STR_REGION_UNKNOWN: \"Geheim\"\n  STR_WEAPON_UNKNOWN: \"Improvisatie\"\n  STR_UNKNOWN: \"Onbekend\"\n  STR_VICTORY: \"Overwinning\"\n  STR_DEFEAT: \"Verslagen\"\n  STR_NO_RECORD: \"Geen informatie\"\n  STR_HUMAN: \"Mens\"\n  STR_FRIENDLY: \"Vriendelijk\"\n  STR_HOSTILE: \"Vijandig\"\n  STR_NEUTRAL: \"Neutraal\"\n  STR_RATING_UC: \"Beoordeling\"\n  STR_LOCATION: \"LOCATIE> {ALT}{0}\"\n  STR_DAYLIGHT_TYPE: \"TIJD> {ALT}{0}\"\n  STR_RACE_TYPE: \"RAS> {ALT}{0}\"\n  STR_DAY: \"Dag\"\n  STR_NIGHT: \"Nacht\"\n  STR_DAYS_WOUNDED: \"DAGEN GEWOND> {ALT}{0}\"\n  STR_COMBAT: \"GEVECHT\"\n  STR_PERFORMANCE: \"PRESTATIE\"\n  STR_NEUTRALIZATIONS_BY_RACE: \"UITSCHAKELINGEN DOOR RAS\"\n  STR_NEUTRALIZATIONS_BY_RANK: \"UITSCHAKELINGEN DOOR RANG\"\n  STR_NEUTRALIZATIONS_BY_WEAPON: \"UITSCHAKELINGEN DOOR WAPEN\"\n  STR_MISSIONS_BY_LOCATION: \"MISSIES PER LOCATIE\"\n  STR_MISSIONS_BY_TYPE: \"MISSIES PER TYPE\"\n  STR_MISSIONS_BY_UFO: \"MISSIES PER UFO\"\n  STR_SCORE_VALUE: \"SCORE> {ALT}{0}\"\n  STR_WINS: \"OVERWINNINGEN> {ALT}{0}\"\n  STR_STUNS: \"WEZENLOOS> {ALT}{0}\"\n  STR_PANICKS: \"IN PANIEK GERAAKT> {ALT}{0}\"\n  STR_MINDCONTROLS: \"ONDER CONTROLE GERAAKT> {ALT}{0}\"\n  STR_AWARDS: \"ONDERSCHEIDINGEN\"\n  STR_COMMENDATIONS_UC: \"AANBEVELINGEN\"\n  STR_COMMENDATIONS: \"aanbevelingen\"\n  STR_MEDALS: \"MEDAILLES\"\n  STR_LOST_IN_SERVICE: \"VERLOREN IN DIENST\"\n  STR_MEDAL_NAME: \"Medaille Naam\"\n  STR_MEDAL_AWARD_LEVEL: \"Onderscheidingen Niveau\"\n  STR_MEDAL_DECOR_LEVEL: \"Ereteken Niveau\"\n  STR_AWARD_0: \"Eerste onderscheiding\"\n  STR_AWARD_1: \"Tweede onderscheiding\"\n  STR_AWARD_2: \"Derde onderscheiding\"\n  STR_AWARD_3: \"Vierde onderscheiding\"\n  STR_AWARD_4: \"Vijfde onderscheiding\"\n  STR_AWARD_5: \"Zesde onderscheiding\"\n  STR_AWARD_6: \"Zevende onderscheiding\"\n  STR_AWARD_7: \"Achtste onderscheiding\"\n  STR_AWARD_8: \"Negende onderscheiding\"\n  STR_AWARD_9: \"Tiende onderscheiding\"\n  STR_AWARD_DECOR_0: \"Geen\"\n  STR_AWARD_DECOR_1: \"Eerste bronzen insigne\"\n  STR_AWARD_DECOR_2: \"Tweede bronzen insigne\"\n  STR_AWARD_DECOR_3: \"Derdebronzen insigne\"\n  STR_AWARD_DECOR_4: \"Eerste zilveren insigne\"\n  STR_AWARD_DECOR_5: \"Tweede zilveren insigne\"\n  STR_AWARD_DECOR_6: \"Derde zilveren insigne\"\n  STR_AWARD_DECOR_7: \"Vierde zilveren insigne\"\n  STR_AWARD_DECOR_8: \"Tweede gouden insigne\"\n  STR_AWARD_DECOR_9: \"Derde gouden insigne\"\n  STR_KILLED_IN_ACTION_MALE: \"VERMOORD IN ACTIE\"\n  STR_KILLED_IN_ACTION_FEMALE: \"VERMOORD IN ACTIE\"\n  STR_MISSING_IN_ACTION_MALE: \"VERMIST IN ACTIE\"\n  STR_MISSING_IN_ACTION_FEMALE: \"VERMIST IN ACTIE\"\n  STR_AVERAGE_MONTHLY_RATING: \"Gemiddelde maandelijkse beoordeling\"\n  STR_TOTAL_INCOME: \"Totale inkomen\"\n  STR_TOTAL_EXPENDITURE: \"Totale uitgaven\"\n  STR_MISSIONS_WON: \"Missie geslaagd\"\n  STR_MISSIONS_LOST: \"Missie gefaald\"\n  STR_NIGHT_MISSIONS: \"Nacht missies\"\n  STR_BEST_RATING: \"Beste missie beoordeling\"\n  STR_WORST_RATING: \"slechtste missie beoordeling\"\n  STR_ALIEN_KILLS: \"Buitenaardse Wezens Gedood\"\n  STR_ALIEN_CAPTURES: \"Buitenaardse wezens gevangen\"\n  STR_FRIENDLY_KILLS: \"Vriendschappelijk vuur incidenten\"\n  STR_AVERAGE_ACCURACY: \"Gemiddelde nauwkeurigheid\"\n  STR_WEAPON_MOST_KILLS: \"Meest effectieve wapen\"\n  STR_ALIEN_MOST_KILLS: \"Dodelijkste buitenaardse wezen\"\n  STR_LONGEST_SERVICE: \"Meest aantal maanden in dienst\"\n  STR_TOTAL_DAYS_WOUNDED: \"Dagen ziek\"\n  STR_COUNTRIES_LOST: \"Landen geinfiltreerd\"\n  STR_TOTAL_TERROR_SITES: \"Terreur aanvallen\"\n  STR_TOTAL_BASES: \"Basissen gebouwd\"\n  STR_TOTAL_CRAFT: \"Voertuigen in bezit gehad\"\n  STR_TOTAL_SCIENTISTS: \"Wetenschappers ingehuurd\"\n  STR_TOTAL_ENGINEERS: \"Ingenieurs ingehuurd\"\n  STR_TOTAL_RESEARCH: \"Onderzoek voltooid\"\n  STR_DIARY_ACCURACY: \"NAUWKEURIGHEID> {ALT}{0}%\"\n  STR_STATISTICS: \"Statistieken\"\n  STR_STATS: \"STATS\"\n  STR_TIME_UNITS_ABBREVIATION: \"AP\"\n  STR_STAMINA_ABBREVIATION: \"STA\"\n  STR_HEALTH_ABBREVIATION: \"HP\"\n  STR_BRAVERY_ABBREVIATION: \"BRV\"\n  STR_REACTIONS_ABBREVIATION: \"REA\"\n  STR_FIRING_ACCURACY_ABBREVIATION: \"ACC\"\n  STR_THROWING_ACCURACY_ABBREVIATION: \"THR\"\n  STR_STRENGTH_ABBREVIATION: \"STR\"\n  STR_MELEE_ACCURACY_ABBREVIATION: \"MEL\"\n  STR_FOLDERS: \"MAPPEN\"\n  STR_DATA_FOLDER: \"Data Map (originele bestanden)\"\n  STR_USER_FOLDER: \"Gebruiker Map (mods, openxcom.log)\"\n  STR_SAVE_FOLDER: \"Opslag Map (opgeslagen spellen, schermafdrukken)\"\n  STR_CONFIG_FOLDER: \"Configuratie Map (options.cfg)\"\n  STR_DATA_FOLDER_DESC_1: \"Dit is waar OpenXcom zoekt naar de originele spelbestanden (UFO en/of TFTD).\"\n  STR_DATA_FOLDER_DESC_2: \"OpenXcom interne bestanden zijn in de 'common' map. OpenXcom ingebouwde mods zijn in de 'standard' map.\"\n  STR_USER_FOLDER_DESC: \"Het logbestand ('openxcom.log') is hier opgeslagen. Alle aangepaste mods behoren hier (in de 'mods' submap).\"\n  STR_SAVE_FOLDER_DESC: \"Hier bevinden zich jouw opgeslagen spellen en de opties voor de missiegenerator (battle.cfg).\"\n  STR_CONFIG_FOLDER_DESC: \"Dit is waar OpenXcom opties ('options.cfg') zijn opgeslagen. Normaal gezien is dit dezelfde map als de Gebruiker Map.\"\n"
  },
  {
    "path": "bin/common/Language/no.yml",
    "content": "\"no\":\n  STR_OPENXCOM: \"OpenXcom\"\n  STR_NEW_GAME: \"Nytt Spill\"\n  STR_LOAD_SAVED_GAME: \"Last Spill\"\n  STR_SELECT_DIFFICULTY_LEVEL: \"Vanskelighetsgrad\"\n  STR_1_BEGINNER: \"1> Nybegynner\"\n  STR_2_EXPERIENCED: \"2> Erfaren\"\n  STR_3_VETERAN: \"3> Veteran\"\n  STR_4_GENIUS: \"4> Geni\"\n  STR_5_SUPERHUMAN: \"5> Supermenneske\"\n  STR_TIME: \"Tid\"\n  STR_DATE: \"Dato\"\n  STR_SELECT_GAME_TO_LOAD: \"Velg spill som skal hentes\"\n  STR_SELECT_SAVE_POSITION: \"Velg lagrings-posisjon\"\n  STR_GAME_OPTIONS: \"INNSTILLINGER\"\n  STR_LOAD_GAME: \"LAST SPILL\"\n  STR_SAVE_GAME: \"LAGRE SPILL\"\n  STR_ABANDON_GAME: \"FORLAT SPILLET\"\n  STR_ABANDON_GAME_QUESTION: \"FORLATE SPILLET?\"\n  STR_QUIT: \"Avslutt\"\n  STR_SAVING_GAME: \"Lagrer spill\"\n  STR_LOADING_GAME: \"Laster spill\"\n  STR_NO_SAVED_GAME_PRESENT: \"Ingen lagrede spill\"\n  STR_LOAD_UNSUCCESSFUL: \"Lasting feilet\"\n  STR_SAVE_UNSUCCESSFUL: \"Lagring feilet\"\n  STR_LOAD_SUCCESSFUL: \"Lasting vellykket\"\n  STR_SAVE_SUCCESSFUL: \"Lagring vellykket\"\n  STR_DELETE: \"SLETT\"\n  STR_DELETE_UNSUCCESSFUL: \"Sletting feilet\"\n  STR_IS_IT_OK_TO_DELETE_THE_SAVED_GAME: \"Er du sikker på at du vil slette det lagrede spillet?\"\n  STR_ORIGINAL_XCOM: \"Originale X-Com\"\n  STR_LOADING: \"Laster...\"\n  STR_DETAILS: \"DETALJER> {ALT}{0}\"\n  STR_NEW_BATTLE: \"Nytt Oppdrag\"\n  STR_OPTIONS: \"Instillinger\"\n  STR_RIGHT_CLICK_TO_DELETE: \"Høyre-klikk for å slette.\"\n  STR_RESTORE_DEFAULTS: \"Gjenopprett Standard\"\n  STR_CONTROLS: \"SPILLKONTROLL\"\n  STR_GENERAL: \"Generelt\"\n  STR_GEOSCAPE: \"Jordklode\"\n  STR_BATTLESCAPE: \"Slagmark\"\n  STR_SCREENSHOT: \"Skjermbilde\"\n  STR_FPS_COUNTER: \"FPS Teller\"\n  STR_ROTATE_LEFT: \"Roter mot Venstre\"\n  STR_ROTATE_RIGHT: \"Roter mot Høyre\"\n  STR_ROTATE_UP: \"Roter Opp\"\n  STR_ROTATE_DOWN: \"Roter Ned\"\n  STR_ZOOM_IN: \"Zoom Inn\"\n  STR_ZOOM_OUT: \"Zoom Ut\"\n  STR_TOGGLE_COUNTRY_DETAIL: \"Slå Av/På Nasjondetaljer\"\n  STR_TOGGLE_RADAR_RANGES: \"Slå Av/På Radargrenser\"\n  STR_SCROLL_LEFT: \"Skroll Venstre \"\n  STR_SCROLL_RIGHT: \"Skroll Høyre\"\n  STR_SCROLL_UP: \"Skroll Opp\"\n  STR_SCROLL_DOWN: \"Skroll Ned\"\n  STR_UNIT_LEVEL_ABOVE: \"Flytt Enheten Opp\"\n  STR_UNIT_LEVEL_BELOW: \"Flytt Enheten Ned\"\n  STR_VIEW_LEVEL_ABOVE: \"Vis Ovenfor\"\n  STR_VIEW_LEVEL_BELOW: \"Vis Nedenfor\"\n  STR_CENTER_SELECTED_UNIT: \"Sentrer på Valgt Enhet\"\n  STR_PREVIOUS_UNIT: \"Velg Forrige Enhet\"\n  STR_NEXT_UNIT: \"Velg Neste Enhet\"\n  STR_DESELECT_UNIT: \"Ferdig med Enhet\"\n  STR_USE_LEFT_HAND: \"Bruk Gjenstand i Venstre Hånd\"\n  STR_USE_RIGHT_HAND: \"Bruk Gjenstand i Høyre Hånd\"\n  STR_INVENTORY: \"Oppakning\"\n  STR_MINIMAP: \"Minikart\"\n  STR_MULTI_LEVEL_VIEW: \"Se Alle Høydenivå\"\n  STR_END_TURN: \"Avslutt Runde\"\n  STR_ABORT_MISSION: \"Avbryt Oppdrag\"\n  STR_UNIT_STATS: \"Enhetens Nøkkeltall\"\n  STR_KNEEL: \"Knestående\"\n  STR_RELOAD: \"Lad om\"\n  STR_DONT_RESERVE_TIME_UNITS: \"Ikke Reserver Tid\"\n  STR_RESERVE_TIME_UNITS_FOR_SNAP_SHOT: \"Reserver Tid for Slengskudd\"\n  STR_RESERVE_TIME_UNITS_FOR_AIMED_SHOT: \"Reserver Tid for Siktet Skudd\"\n  STR_RESERVE_TIME_UNITS_FOR_AUTO_SHOT: \"Reserver Tid for Skuddserie (3)\"\n  STR_CENTER_ON_ENEMY_1: \"Vis Fiende 1\"\n  STR_CENTER_ON_ENEMY_2: \"Vis Fiende 2\"\n  STR_CENTER_ON_ENEMY_3: \"Vis Fiende 3\"\n  STR_CENTER_ON_ENEMY_4: \"Vis Fiende 4\"\n  STR_CENTER_ON_ENEMY_5: \"Vis Fiende 5\"\n  STR_CENTER_ON_ENEMY_6: \"Vis Fiende 6\"\n  STR_CENTER_ON_ENEMY_7: \"Vis Fiende 7\"\n  STR_CENTER_ON_ENEMY_8: \"Vis Fiende 8\"\n  STR_CENTER_ON_ENEMY_9: \"Vis Fiende 9\"\n  STR_CENTER_ON_ENEMY_10: \"Vis Fiende 10\"\n  STR_CREATE_INVENTORY_TEMPLATE: \"Lagre mal\"\n  STR_APPLY_INVENTORY_TEMPLATE: \"Benytt mal\"\n  STR_CLEAR_INVENTORY: \"Tøm opppakning\"\n  STR_AUTO_EQUIP: \"Auto-oppakning\"\n  STR_QUICK_SAVE: \"Hurtig Lagring\"\n  STR_QUICK_LOAD: \"Hurtig Lasting\"\n  STR_ADVANCED: \"AVANSERT\"\n  STR_AGGRESSIVERETALIATION: \"Aggressivt Motangrep\"\n  STR_AGGRESSIVERETALIATION_DESC: \"UFOer vil konstant forsøke å finne dine baser, uansett hvilke oppdrag de er ute på.\"\n  STR_STORAGELIMITSENFORCED: \"Lagergrenser for bergede gjenstander\"\n  STR_STORAGELIMITSENFORCED_DESC: \"Håndhever alien- og lagergrenser for levende aliens og bergede gjenstander.\"\n  STR_CANSELLLIVEALIENS: \"Salg av levende aliens\"\n  STR_CANSELLLIVEALIENS_DESC: \"Tillat salg av levende aliens. Anbefalt ved bruk av lagergrenser\"\n  STR_ALLOWBUILDINGQUEUE: \"Tillat bygnings-kø\"\n  STR_ALLOWBUILDINGQUEUE_DESC: \"Nye fasiliteter kan plasseres ved siden av uferdige.\"\n  STR_BATTLEAUTOEND: \"Auto-Avslutt oppdrag\"\n  STR_BATTLEAUTOEND_DESC: \"Oppdrag avsluttes automatisk når alle fiender er nøytralisert\"\n  STR_BATTLEINSTANTGRENADE: \"Øyeblikkelig granat detonasjon\"\n  STR_BATTLEINSTANTGRENADE_DESC: \"Granater satt til 0 rundetid eksploderer samme runden de kastes, istedenfor neste runde.\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE: \"Luftbårne overføringer\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE_DESC: \"Luftfartøy kan overføres til baser selv etter avgang-\"\n  STR_CRAFTLAUNCHALWAYS: \"Tving avgang\"\n  STR_CRAFTLAUNCHALWAYS_DESC: \"Fly-enheter kan tvinges til avgang, selv ved pågående vedlikehold.\"\n  STR_CUSTOMINITIALBASE: \"Tilpasset startbase\"\n  STR_CUSTOMINITIALBASE_DESC: \"Ved starten av ett nytt spill får du muligheten til å selv konstruere den første basen din\"\n  STR_GLOBESEASONS: \"Realistisk globus-belysning\"\n  STR_GLOBESEASONS_DESC: \"Mer realistisk belysning av jorden ifølge den vinkling\"\n  STR_PLAYINTRO: \"Vis intro\"\n  STR_PLAYINTRO_DESC: \"Vise intro sekvensen ved oppstart.\"\n  STR_SHOWMORESTATSININVENTORYVIEW_DESC: \"Vis ekstra informasjon om den valgte soldaten på oppaknings-oversikten.\"\n  STR_SNEAKYAI: \"Snikende AI\"\n  STR_SNEAKYAI_DESC: \"AI vil forsøke å forbli uoppdaget, så langt den anser mulighet for det.\"\n  STR_STRAFE: \"Alternative bevegelses-metoder\"\n  STR_STRAFE_DESC: \"Tillater sides vis bevegelse, løping, samt at kanonvinkler på kjøretøy forblir uavhengig av travers-retning\"\n  STR_BATTLEEXPLOSIONHEIGHT: \"Eksplosjonshøyde\"\n  STR_BATTLEEXPLOSIONHEIGHT_DESC: \"Vertikal effekt ved eksplosjoner. [NEWLINE}(Flat: 0, Rund: 3)\"\n  STR_AUTOSAVE: \"Automatisk Lagring\"\n  STR_AUTOSAVE_DESC: \"Lagrer spillet automatisk ved satt interval- Gjelder ikke i \\\"Ironman\\\" modus.\"\n  STR_AUTOSAVE_FREQUENCY: \"Autolagring Frekvens\"\n  STR_AUTOSAVE_FREQUENCY_DESC: \"Antall runder mellom autolagringer.\"\n  STR_ALLOWPSIONICCAPTURE: \"Tillat  psi-arrest\"\n  STR_ALLOWPSIONICCAPTURE_DESC: \"Ved tankekontroll av av gjenværende fiender resulterer det i seier, og de regnes for som levende fanger.\"\n  STR_SKIPNEXTTURNSCREEN: \"Hopp over \\\"Neste runde\\\" skjerm\"\n  STR_SKIPNEXTTURNSCREEN_DESC: \"\\\"Neste Runde\\\" skjermer hoppes går automatisk videre etter kort tid.\"\n  STR_NOT_ENOUGH_SPACE: \"Ikke Nok Ledig Plass!\"\n  STR_WEAPONSELFDESTRUCTION: \"Selv-destruerende alien-våpen\"\n  STR_WEAPONSELFDESTRUCTION_DESC: \"Som i XCOM 2012, ødelegges våpen som ble båret av en alien, dersom alien' blir drept.\"\n  STR_RETAINCORPSES: \"Behold forhørte aliens\"\n  STR_RETAINCORPSES_DESC: \"Som i XCOM 2012, så blir forhørte aliens overført levende til basens lager forråd.\"\n  STR_SAVE_VOXEL_VIEW: \"Lagre Førstepersons Skjermbilde\"\n  STR_RESERVE_TIME_UNITS_FOR_KNEEL: \"Reserver Tid for Kneling\"\n  STR_EXPEND_ALL_TIME_UNITS: \"Slett resterende Tid\"\n  STR_PSISTRENGTHEVAL: \"Vurdert PSI-Styrke\"\n  STR_DISABLEAUTOEQUIP: \"Deaktiver automatisk utrustning\"\n  STR_DISABLEAUTOEQUIP_DESC: \"Deaktiver auto-utrustning av nye soldater før kamp\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT: \"Tillat Psi-Styrkeforbedring\"\n  STR_BATTLESMOOTHCAMERA: \"Prosjektil-fokusert Kamera\"\n  STR_BATTLESMOOTHCAMERA_DESC: \"Kameraet på slagmarken vil følge prosjektiler ved avfyring.\"\n  STR_BATTLECONFIRMFIREMODE: \"Bekreft Skudd modus\"\n  STR_BATTLECONFIRMFIREMODE_DESC: \"Krev to klikk på samme målet for å bekrefte ordre om avfyring av skudd.\"\n  STR_SELECT_BASE_1: \"Velg Base 1\"\n  STR_SELECT_BASE_2: \"Velg Base 2\"\n  STR_SELECT_BASE_3: \"Velg Base 3\"\n  STR_SELECT_BASE_4: \"Velg Base 4\"\n  STR_SELECT_BASE_5: \"Velg Base 5\"\n  STR_SELECT_BASE_6: \"Velg Base 6\"\n  STR_SELECT_BASE_7: \"Velg Base 7\"\n  STR_SELECT_BASE_8: \"Velg Base 8\"\n  STR_VIDEO: \"SKJERM\"\n  STR_AUDIO: \"LYD\"\n  STR_BATTLESCAPE_UC: \"SLAGMARK\"\n  STR_MODS_UC: \"MODIFIKASJONER\"\n  STR_DISPLAY_RESOLUTION: \"Skjermoppløsning\"\n  STR_ORIGINAL: \"Original\"\n  STR_DISPLAY_MODE: \"Skjerm-Modus\"\n  STR_WINDOWED: \"Vindu\"\n  STR_FULLSCREEN: \"Fullskjerm\"\n  STR_BORDERLESS: \"Rammeløst Vindu\"\n  STR_DISPLAY_LANGUAGE: \"Velg Språk\"\n  STR_DISPLAY_LANGUAGE_DESC: \"Forandrer språket i selve spillet.\"\n  STR_DISPLAY_FILTER: \"Skjerm-Filter\"\n  STR_DISPLAY_FILTER_DESC: \"Forandrer filteret som spill-skjermen behandles med.{NEWLINE}*krever OpenGL maskinvare-akselerasjon.\"\n  STR_DISPLAY_OPTIONS: \"Skjerm-Alternativer\"\n  STR_LETTERBOXED: \"Brevsprekk\"\n  STR_LETTERBOXED_DESC: \"Legger til svart ramme for å beholde originalt størrelseforhold.\"\n  STR_RESIZABLE: \"Variabel Størrelse\"\n  STR_LOCK_MOUSE: \"Fang Muspeker\"\n  STR_LOCK_MOUSE_DESC: \"Hindrer muspekeren fra å forlate spill vinduet. Du kan trykke Ctrl+G for å slå av og på dette når som helst.\"\n  STR_FIXED_WINDOW_POSITION: \"Fast Vinduposisjon\"\n  STR_FIXED_WINDOW_POSITION_DESC: \"Sett fast vinduposisjon.\"\n  STR_DISPLAY_SET_WINDOW_POSITION: \"Sett ny grunnposisjon for vindu\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_X: \"Horisontal plassering:\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_Y: \"Vertikal plassering:\"\n  STR_MUSIC_VOLUME: \"Musikk Volum\"\n  STR_MUSIC_VOLUME_DESC: \"Stiller volumet på bakgrunnsmusikk.\"\n  STR_SFX_VOLUME: \"Lydeffekt Volum\"\n  STR_SFX_VOLUME_DESC: \"Stiller volumet på lydeffekter.\"\n  STR_UI_VOLUME: \"Grensesnitt Volum\"\n  STR_UI_VOLUME_DESC: \"Stiller volumet på lyder fra grensesnittet.\"\n  STR_SCROLL_SPEED: \"Skroll Hastighet\"\n  STR_SCROLL_SPEED_GEO_DESC: \"Endrer skrollehastigeten på jordkloden.\"\n  STR_SCROLL_SPEED_BATTLE_DESC: \"Endrer skrollehastigeten på kartet.\"\n  STR_DOGFIGHT_SPEED: \"Luftstrid Hastighet\"\n  STR_CLOCK_SPEED: \"Klokkefrekvens\"\n  STR_GLOBE_DETAILS: \"Jordklode-Detaljer\"\n  STR_GLOBE_COUNTRIES: \"Nasjoner\"\n  STR_GLOBE_COUNTRIES_DESC: \"Viser finansierende nasjoner på kloden.\"\n  STR_GLOBE_RADARS: \"Radarer\"\n  STR_GLOBE_RADARS_DESC: \"Viser radargrenser på kloden.\"\n  STR_GLOBE_FLIGHT_PATHS: \"Luftbaner\"\n  STR_GLOBE_FLIGHT_PATHS_DESC: \"Vise fartøyenes rute på kloden. \"\n  STR_MODS_TOOLTIP: \"Versjon {0} av {1}.{NEWLINE}{2}\"\n  STR_EDGE_SCROLL: \"Kant Skroll\"\n  STR_AUTO_SCROLL: \"Auto\"\n  STR_DRAG_SCROLL: \"Slepe-Skroll\"\n  STR_DRAG_SCROLL_DESC: \"Skroller kartet dersom den valgte museknappen holdes inne mens pekeren flyttes. \"\n  STR_LEFT_MOUSE_BUTTON: \"Venstre Knapp\"\n  STR_MIDDLE_MOUSE_BUTTON: \"Midterste Knapp\"\n  STR_RIGHT_MOUSE_BUTTON: \"Høyre Knapp\"\n  STR_FIRE_SPEED: \"Skudd Hastighet\"\n  STR_FIRE_SPEED_DESC: \"Endrer hastigheten på avfyrte prosjektiler.\"\n  STR_PLAYER_MOVEMENT_SPEED: \"Spillers Forflytninghastighet\"\n  STR_PLAYER_MOVEMENT_SPEED_DESC: \"Endrer forflytninghastighet på spiller-kontrollerte enheter.\"\n  STR_COMPUTER_MOVEMENT_SPEED: \"AI's Forflytninghastighet\"\n  STR_COMPUTER_MOVEMENT_SPEED_DESC: \"Endrer forflytninghastighet på maskin-kontrollerte enheter.\"\n  STR_PATH_PREVIEW: \"Forhåndsvisning Rute\"\n  STR_PATH_ARROWS: \"Piler\"\n  STR_PATH_TIME_UNIT_COST: \"Tidsenheter\"\n  STR_USER_INTERFACE_OPTIONS: \"Grensesnitt Alternativer\"\n  STR_TOOLTIPS: \"Verktøytips\"\n  STR_TOOLTIPS_DESC: \"Vise verktøytips på knapper brukt på slagmarken.\"\n  STR_DEATH_NOTIFICATIONS: \"Døds-Annonsering\"\n  STR_DEATH_NOTIFICATIONS_DESC: \"Vis detaljert varsling om hvem det var som omkom når en soldat dør.\"\n  STR_SHOW_FUNDS: \"Vis Midler\"\n  STR_SHOW_FUNDS_DESC: \"Viser tilgjengelige midler ved siden av Jordklodens klokke.\"\n  STR_MISSION_GENERATOR: \"OPPDRAGS-GENERATOR\"\n  STR_MAP_OPTIONS: \"KART INNSTILLINGER\"\n  STR_ALIEN_OPTIONS: \"ALIENS INNSTILLINGER\"\n  STR_MAP_TERRAIN: \"Terreng\"\n  STR_MAP_DARKNESS: \"Mørke\"\n  STR_MAP_DEPTH: \"Dybde\"\n  STR_DIFFICULTY: \"Vanskelighetsgrad\"\n  STR_ALIEN_RACE: \"Rase\"\n  STR_ALIEN_TECH_LEVEL: \"Teknologi-Nivå\"\n  STR_RANDOMIZE: \"Tilfeldig\"\n  STR_RESTORE_DEFAULTS_QUESTION: \"Er du sikker på at du ønsker gjenopprette standardinnstillinger?\"\n  STR_DISPLAY_OPTIONS_CONFIRM: \"Ønsker du benytte denne skjerminnstillingen?\"\n  STR_DISPLAY_OPTIONS_REVERT: \"Endrer tilbake om 0:{0}\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT: \"Beholde avsikrede granater\"\n  STR_CHANGEVALUEBYMOUSEWHEEL: \"Endre verdier med mushjulet\"\n  STR_CHANGEVALUEBYMOUSEWHEEL_DESC: \"Gjør det mulig å benytte mushjulet til øke/redusere verdier med dette antallet.\"\n  STR_DRAGSCROLLINVERT: \"Omvendt slepe-skrolling\"\n  STR_BATTLESCAPE_SCALE: \"Slagmark Skala\"\n  STR_GEOSCAPE_SCALE: \"Jordklode Skala\"\n  STR_1_5X: \"1.5x Opprinnelig\"\n  STR_2X: \"2x Opprinnelig\"\n  STR_THIRD_DISPLAY: \"1/3 Visning\"\n  STR_HALF_DISPLAY: \"1/2 Visning\"\n  STR_FULL_DISPLAY: \"Full Visning\"\n  STR_FPS_LIMIT: \"FPS grense\"\n  STR_FPS_LIMIT_DESC: \"Begrenser antall ganger skjermen oppdateres per sekund. 0 for ubegrenset antall. Dersom OpenGL-gjengivelse er valgt, benytter spillet istedet skjermens Vsync-frekvens.\"\n  STR_FPS_INACTIVE_LIMIT: \"FPS grense i bakgrunn\"\n  STR_FPS_INACTIVE_LIMIT_DESC: \"Begrenser antall skjermoppdateringer i sekundet når OpenXcom kjører i bakgrunnen.\"\n  STR_NOALIENPANICMESSAGES: \"Gjem panikk-varsler for aliens\"\n  STR_NOALIENPANICMESSAGES_DESC: \"Ikke vis panikk-varsler for aliens dersom de ikke er synlige for spilleren.\"\n  STR_ALIENBLEEDING: \"Blødende Aliens\"\n  STR_ALIENBLEEDING_DESC: \"Aliens kan ta skade ved påførte forblødninger.\"\n  STR_FIELDPROMOTIONS: \"Felt-forfremmelse\"\n  STR_FIELDPROMOTIONS_DESC: \"Kun enheter som var til stede på slagmarken vil kunne motta forfremmelser.\"\n  STR_MEETINGPOINT: \"Forutsi UFO retning\"\n  STR_MEETINGPOINT_DESC: \"Luftfartøy flyr mot ett antatt konfrontasjonpunkt basert på UFOers retning og hastighet.\"\n  STR_IRONMAN: \"IRONMAN\"\n  STR_IRONMAN_DESC: \"Ingen manuell lagring\"\n  STR_SAVE_AND_ABANDON_GAME: \"LAGRE OG AVSLUTT SPILL\"\n  STR_MOD_UNSUCCESSFUL: \"Modifikasjonen kunne ikke lastes inn\"\n  STR_NEW_SAVED_GAME_SLOT: \"<NYTT LAGRET SPILL>\"\n  STR_AUTO_SAVE_GEOSCAPE_SLOT: \"<AUTO GEOSCAPE>\"\n  STR_AUTO_SAVE_BATTLESCAPE_SLOT: \"<AUTO BATTLESCAPE>\"\n  STR_QUICK_SAVE_SLOT: \"<HURTIGLAGRING>\"\n  STR_DISPLAY_MODE_DESC: \"Endre hvordan spillet vises på skjermen.\"\n  STR_PREFERRED_MUSIC_FORMAT: \"Foretrukket Musikkformat\"\n  STR_PREFERRED_MUSIC_FORMAT_DESC: \"Velger foretrukket format som skal benyttes på musikk dersom flere er tilgjengelige.{NEWLINE}Obs: MIDI avspilling kan ha defekter på Windows.\"\n  STR_PREFERRED_SFX_FORMAT: \"Foretrukket Lydeffekt Format\"\n  STR_PREFERRED_SFX_FORMAT_DESC: \"Velger foretrukket format som skal benyttes på lydeffekter dersom flere er tilgjengelige.\"\n  STR_PREFERRED_VIDEO_FORMAT: \"Foretrukket Videoformat\"\n  STR_PREFERRED_VIDEO_FORMAT_DESC: \"Velger foretrukket format som skal benyttes på videoer dersom flere er tilgjengelige.\"\n  STR_PREFERRED_VIDEO_ANIMATION: \"Animasjon\"\n  STR_PREFERRED_VIDEO_SLIDESHOW: \"Lysbildeserie\"\n  STR_PREFERRED_FORMAT_AUTO: \"Autovalgt\"\n  STR_CURRENT_FORMAT: \"Nåværende: {0}\"\n  STR_FORCE_FIRE: \"Overstyr Skuddlinje\"\n  STR_FORCE_FIRE_DESC: \"Tillat avfyring av skudd selv ved manglende skuddlinje ved å holde inne CTRL for å tvinge enheter til å skyte.\"\n  STR_NO_AUDIO_HARDWARE_DETECTED: \"Fant ingen maskinvare for lyd\"\n  STR_DISABLED: \"Deaktivert\"\n  STR_DIARY: \"DAGBOK\"\n  STR_KILLED: \"DREPTE\"\n  STR_STUNNED: \"LAMSLÅTT\"\n  STR_PANICKED: \"SKREKKSLAGEN\"\n  STR_MINDCONTROLLED: \"KONTROLLERTE\"\n  STR_REGION_UNKNOWN: \"Ikke Oppgitt\"\n  STR_WEAPON_UNKNOWN: \"Improvisasjon\"\n  STR_UNKNOWN: \"Ukjent\"\n  STR_VICTORY: \"Seier\"\n  STR_DEFEAT: \"Nederlag\"\n  STR_HUMAN: \"Menneske\"\n  STR_FRIENDLY: \"Vennlig\"\n  STR_HOSTILE: \"Fiendtlig\"\n  STR_NEUTRAL: \"Nøytral\"\n  STR_RATING_UC: \"VURDERING\"\n  STR_LOCATION: \"STED> {ALT}{0}\"\n  STR_DAYLIGHT_TYPE: \"TID> {ALT}{0}\"\n  STR_RACE_TYPE: \"RASE> {ALT}{0}\"\n  STR_DAY: \"Dag\"\n  STR_NIGHT: \"Natt\"\n  STR_DAYS_WOUNDED: \"DAGER SKADD> {ALT}{0}\"\n  STR_COMBAT: \"KAMP\"\n  STR_PERFORMANCE: \"YTELSE\"\n  STR_SCORE_VALUE: \"POENG> {ALT}{0}\"\n  STR_WINS: \"SEIERE> {ALT}{0}\"\n  STR_AWARDS: \"UTMERKELSER\"\n  STR_COMMENDATIONS_UC: \"LOVORD\"\n  STR_COMMENDATIONS: \"Lovord\"\n  STR_MEDALS: \"MEDALJER\"\n  STR_LOST_IN_SERVICE: \"TAPT I TJENESTE\"\n  STR_MEDAL_NAME: \"Medaljenavn\"\n  STR_MEDAL_AWARD_LEVEL: \"Utmerkelsenivå\"\n  STR_MEDAL_DECOR_LEVEL: \"Dekorasjonsnivå\"\n  STR_AWARD_0: \"Første utmerkelse\"\n  STR_AWARD_1: \"Andre utmerkelse\"\n  STR_AWARD_2: \"Tredje utmerkelse\"\n  STR_AWARD_3: \"Fjerde utmerkelse\"\n  STR_AWARD_4: \"Femte utmerkelse\"\n  STR_AWARD_5: \"Sjette utmerkelse\"\n  STR_AWARD_6: \"Syvende utmerkelse\"\n  STR_AWARD_7: \"Åttende utmerkelse\"\n  STR_AWARD_8: \"Niende utmerkelse\"\n  STR_AWARD_9: \"Tiende utmerkelse\"\n  STR_AWARD_DECOR_0: \"Ingen\"\n  STR_AWARD_DECOR_1: \"Første bronse pin\"\n  STR_AWARD_DECOR_2: \"Andre bronse pin\"\n  STR_AWARD_DECOR_3: \"Tredje bronse pin\"\n  STR_AWARD_DECOR_4: \"Første sølv pin\"\n  STR_AWARD_DECOR_5: \"Andre sølv pin\"\n  STR_AWARD_DECOR_6: \"Tredge sølv pin\"\n  STR_AWARD_DECOR_7: \"Første gull pin\"\n  STR_AWARD_DECOR_8: \"Andre gull pin\"\n  STR_AWARD_DECOR_9: \"Tredje gull pin\"\n  STR_KILLED_IN_ACTION_MALE: \"DREPT I TJENESTE\"\n  STR_KILLED_IN_ACTION_FEMALE: \"DREPT I TJENESTE\"\n  STR_MISSING_IN_ACTION_MALE: \"SAVNET I TJENESTE\"\n  STR_MISSING_IN_ACTION_FEMALE: \"SAVNET I TJENESTE\"\n  STR_AVERAGE_MONTHLY_RATING: \"Månedlig gjennomsnitts vurdering\"\n  STR_TOTAL_INCOME: \"Inntekt totalt\"\n  STR_TOTAL_EXPENDITURE: \"Totalutgift\"\n  STR_MISSIONS_WON: \"Oppdrager utført\"\n  STR_MISSIONS_LOST: \"Oppdrager tapt\"\n  STR_NIGHT_MISSIONS: \"Nattoppdrag\"\n  STR_BEST_RATING: \"Beste prestasjon\"\n  STR_WORST_RATING: \"Dårligste prestasjon\"\n  STR_ALIEN_KILLS: \"Aliens drept\"\n  STR_ALIEN_CAPTURES: \"Aliens fanget\"\n  STR_FRIENDLY_KILLS: \"Vennlig Ild-forekomster\"\n  STR_AVERAGE_ACCURACY: \"Gjennomsnittlig treffsikkerhet\"\n  STR_WEAPON_MOST_KILLS: \"Mest effektive våpen\"\n  STR_ALIEN_MOST_KILLS: \"Mest dødelige alien\"\n  STR_LONGEST_SERVICE: \"Lengst tjenestetid\"\n  STR_TOTAL_DAYS_WOUNDED: \"Sykefravær\"\n  STR_COUNTRIES_LOST: \"Infiltrerte nasjoner\"\n  STR_TOTAL_TERROR_SITES: \"Terrorangrep\"\n  STR_TOTAL_BASES: \"Baser bygd\"\n  STR_TOTAL_CRAFT: \"Fartøy eigd\"\n  STR_TOTAL_SCIENTISTS: \"Forskere ansatt\"\n  STR_TOTAL_ENGINEERS: \"Ingeniører ansatt\"\n  STR_TOTAL_RESEARCH: \"Forskninger fullført\"\n  STR_DIARY_ACCURACY: \"TREFFSIKKERHET> {ALT}{0}%\"\n  STR_STATISTICS: \"Statistikk\"\n  STR_STATS: \"STATI\"\n  STR_TIME_UNITS_ABBREVIATION: \"TE\"\n  STR_STAMINA_ABBREVIATION: \"UTH\"\n  STR_HEALTH_ABBREVIATION: \"HP\"\n  STR_BRAVERY_ABBREVIATION: \"MOT\"\n"
  },
  {
    "path": "bin/common/Language/pl.yml",
    "content": "pl:\n  STR_OPENXCOM: \"OpenXcom\"\n  STR_NEW_GAME: \"Nowa gra\"\n  STR_LOAD_SAVED_GAME: \"Wczytaj grę\"\n  STR_SELECT_DIFFICULTY_LEVEL: \"Wybierz poziom trudności\"\n  STR_1_BEGINNER: \"Początkujący\"\n  STR_2_EXPERIENCED: \"Doświadczony\"\n  STR_3_VETERAN: \"Weteran\"\n  STR_4_GENIUS: \"Geniusz\"\n  STR_5_SUPERHUMAN: \"Nadczłowiek\"\n  STR_TIME: \"Godzina\"\n  STR_DATE: \"Data\"\n  STR_SELECT_GAME_TO_LOAD: \"Wybierz grę do wczytania\"\n  STR_SELECT_SAVE_POSITION: \"Wybierz miejsce zapisu\"\n  STR_GAME_OPTIONS: \"OPCJE GRY\"\n  STR_LOAD_GAME: \"WCZYTAJ GRĘ\"\n  STR_SAVE_GAME: \"ZAPISZ GRĘ\"\n  STR_ABANDON_GAME: \"OPUŚĆ GRĘ\"\n  STR_ABANDON_GAME_QUESTION: \"ZAKOŃCZYĆ GRĘ?\"\n  STR_QUIT: \"Wyjdź do systemu\"\n  STR_SAVING_GAME: \"Zapisywanie gry...\"\n  STR_LOADING_GAME: \"Wczytywanie gry...\"\n  STR_NO_SAVED_GAME_PRESENT: \"Brak zapisanych gier\"\n  STR_LOAD_UNSUCCESSFUL: \"Wczytywanie nieudane\"\n  STR_SAVE_UNSUCCESSFUL: \"Zapisywanie nieudane\"\n  STR_LOAD_SUCCESSFUL: \"Wczytywanie udane\"\n  STR_SAVE_SUCCESSFUL: \"Zapisywanie udane\"\n  STR_DELETE: \"USUŃ\"\n  STR_DELETE_UNSUCCESSFUL: \"Usuwanie nieudane\"\n  STR_IS_IT_OK_TO_DELETE_THE_SAVED_GAME: \"Czy na pewno chcesz usunąć wybraną zapisaną grę?\"\n  STR_ORIGINAL_XCOM: \"UFO: Nieznany wróg\"\n  STR_LOADING: \"Wczytywanie...\"\n  STR_DETAILS: \"SZCZEGÓŁY> {ALT}{0}\"\n  STR_NEW_BATTLE: \"Nowa bitwa\"\n  STR_OPTIONS: \"Opcje\"\n  STR_RIGHT_CLICK_TO_DELETE: \"Kliknij prawym przyciskiem myszy na wybranej zapisanej grze, by ją usunąć.\"\n  STR_RESTORE_DEFAULTS: \"Przywróć domyślne\"\n  STR_CONTROLS: \"STEROWANIE\"\n  STR_GENERAL: \"Ogólne\"\n  STR_GEOSCAPE: \"Ekran Ziemi\"\n  STR_BATTLESCAPE: \"Ekran bitwy\"\n  STR_SCREENSHOT: \"Zrzut ekranu\"\n  STR_FPS_COUNTER: \"Licznik klatek na sekundę\"\n  STR_ROTATE_LEFT: \"Obrót w lewo\"\n  STR_ROTATE_RIGHT: \"Obrót w prawo\"\n  STR_ROTATE_UP: \"Obrót w górę\"\n  STR_ROTATE_DOWN: \"Obrót w dół\"\n  STR_ZOOM_IN: \"Przybliż widok\"\n  STR_ZOOM_OUT: \"Oddal widok\"\n  STR_TOGGLE_COUNTRY_DETAIL: \"Pokazuj dane krajów sponsorujących\"\n  STR_TOGGLE_RADAR_RANGES: \"Pokazuj zasięg radarów\"\n  STR_SCROLL_LEFT: \"Przewinięcie w lewo\"\n  STR_SCROLL_RIGHT: \"Przewinięcie w prawo\"\n  STR_SCROLL_UP: \"Przewinięcie w górę\"\n  STR_SCROLL_DOWN: \"Przewinięcie w dół\"\n  STR_UNIT_LEVEL_ABOVE: \"Przesuń jednostkę o poziom wyżej\"\n  STR_UNIT_LEVEL_BELOW: \"Przesuń jednostkę o poziom niżej\"\n  STR_VIEW_LEVEL_ABOVE: \"Widok na poziom wyżej\"\n  STR_VIEW_LEVEL_BELOW: \"Widok na poziom niżej\"\n  STR_CENTER_SELECTED_UNIT: \"Wyśrodkuj widok na wybranej jednostce\"\n  STR_PREVIOUS_UNIT: \"Wybierz poprzednią jednostkę\"\n  STR_NEXT_UNIT: \"Wybierz następną jednostkę\"\n  STR_DESELECT_UNIT: \"Nie wybieraj ponownie tej jednostki\"\n  STR_USE_LEFT_HAND: \"Użyj przedmiotu z lewej dłoni\"\n  STR_USE_RIGHT_HAND: \"Użyj przedmiotu z prawej dłoni\"\n  STR_INVENTORY: \"Ekwipunek\"\n  STR_MINIMAP: \"Minimapa\"\n  STR_MULTI_LEVEL_VIEW: \"Widok wielopoziomowy\"\n  STR_END_TURN: \"Zakończ turę\"\n  STR_ABORT_MISSION: \"Przerwij misję\"\n  STR_UNIT_STATS: \"Statystyki jednostki\"\n  STR_KNEEL: \"Klęknij/Powstań\"\n  STR_RELOAD: \"Przeładuj\"\n  STR_TOGGLE_PERSONAL_LIGHTING: \"Przełącz oświetlenie żołnierza\"\n  STR_DONT_RESERVE_TIME_UNITS: \"Nie rezerwuj JC\"\n  STR_RESERVE_TIME_UNITS_FOR_SNAP_SHOT: \"Rezerwuj JC na strzał pojedynczy\"\n  STR_RESERVE_TIME_UNITS_FOR_AIMED_SHOT: \"Rezerwuj JC na strzał celowany\"\n  STR_RESERVE_TIME_UNITS_FOR_AUTO_SHOT: \"Rezerwuj JC na strzał serią\"\n  STR_CENTER_ON_ENEMY_1: \"Wyśrodkuj na przeciwniku nr 1\"\n  STR_CENTER_ON_ENEMY_2: \"Wyśrodkuj na przeciwniku nr 2\"\n  STR_CENTER_ON_ENEMY_3: \"Wyśrodkuj na przeciwniku nr 3\"\n  STR_CENTER_ON_ENEMY_4: \"Wyśrodkuj na przeciwniku nr 4\"\n  STR_CENTER_ON_ENEMY_5: \"Wyśrodkuj na przeciwniku nr 5\"\n  STR_CENTER_ON_ENEMY_6: \"Wyśrodkuj na przeciwniku nr 6\"\n  STR_CENTER_ON_ENEMY_7: \"Wyśrodkuj na przeciwniku nr 7\"\n  STR_CENTER_ON_ENEMY_8: \"Wyśrodkuj na przeciwniku nr 8\"\n  STR_CENTER_ON_ENEMY_9: \"Wyśrodkuj na przeciwniku nr 9\"\n  STR_CENTER_ON_ENEMY_10: \"Wyśrodkuj na przeciwniku nr 10\"\n  STR_CREATE_INVENTORY_TEMPLATE: \"Stwórz szablon ekwipunku\"\n  STR_APPLY_INVENTORY_TEMPLATE: \"Zastosuj szablon ekwipunku\"\n  STR_CLEAR_INVENTORY: \"Wyczyść ekwipunek\"\n  STR_AUTO_EQUIP: \"Automatyczny przydział sprzętu\"\n  STR_QUICK_SAVE: \"Szybkie zapisanie gry\"\n  STR_QUICK_LOAD: \"Szybkie wczytanie gry\"\n  STR_ADVANCED: \"ZAAWANSOWANE\"\n  STR_AGGRESSIVERETALIATION: \"Agresywne akcje odwetowe obcych\"\n  STR_AGGRESSIVERETALIATION_DESC: \"Obcy będą za wszelką cenę próbować wykryć Twoje bazy bez względu na to, jaki jest ich główny cel danej misji. \"\n  STR_STORAGELIMITSENFORCED: \"Limit magazynów na zdobyte przedmioty\"\n  STR_STORAGELIMITSENFORCED_DESC: \"Wymusza limity w celach dla obcych i magazynach dla znalezionych podczas misji żywych obcych i artefaktów\"\n  STR_CANSELLLIVEALIENS: \"Sprzedaż żywych obcych\"\n  STR_CANSELLLIVEALIENS_DESC: \"Pozwala na sprzedaż żywych obcych. Opcja zalecana przy włączonym limicie dla magazynów.\"\n  STR_ALLOWBUILDINGQUEUE: \"Zezwalaj na kolejkowaną rozbudowę bazy\"\n  STR_ALLOWBUILDINGQUEUE_DESC: \"Umożliwia stawianie nowych instalacji obok nieukończonych.\"\n  STR_BATTLEAUTOEND: \"Automatycznie zakończaj bitwę \"\n  STR_BATTLEAUTOEND_DESC: \"Bitwa zakończy się automatycznie, gdy ostatni żywy obcy zostanie zneutralizowany.\"\n  STR_BATTLEINSTANTGRENADE: \"Natychmiastowe granaty\"\n  STR_BATTLEINSTANTGRENADE_DESC: \"Granaty ustawione na 0 tur będą wybuchać natychmiast po rzucie, zamiast na końcu tury.\"\n  STR_BATTLEUFOEXTENDERACCURACY: \"Celowanie jak w modyfikacji 'UFO Extender'\"\n  STR_BATTLEUFOEXTENDERACCURACY_DESC: \"Celność strzałów spada wraz z odległością, w zależności od ich typu. Aktualna celność będzie zawsze wyświetlana obok kursora.\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE: \"Transfer w trakcie lotu\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE_DESC: \"Możliwy będzie transfer dowolnego samolotu/statku będącego aktualnie poza bazą.\"\n  STR_CRAFTLAUNCHALWAYS: \"Wymuszaj start samolotów i łodzi\"\n  STR_CRAFTLAUNCHALWAYS_DESC: \"Zezwala na wymuszenie startu samolotów i łodzi bez konieczności ich całkowitego zatankowania i dozbrojenia.\"\n  STR_CUSTOMINITIALBASE: \"Własne rozmieszczenie nowej bazy\"\n  STR_CUSTOMINITIALBASE_DESC: \"Po rozpoczęciu nowej gry będzie można ręcznie rozmieścić początkowe instalacje, zamiast mieć je w standardowym{NEWLINE}układzie w nowej bazie.\"\n  STR_GLOBESEASONS: \"Pory roku na ekranie Ziemi\"\n  STR_GLOBESEASONS_DESC: \"Rzeczywiste odwzorowanie oświetlenia słonecznego na ekranie Ziemi w zależności od pory roku.\"\n  STR_PLAYINTRO: \"Odtwarzaj wprowadzenie do gry\"\n  STR_PLAYINTRO_DESC: \"Pokazuj animowane wprowadzenie po uruchomieniu OpenXcoma.\"\n  STR_SHOWMORESTATSININVENTORYVIEW: \"Statystyki zołnierza/akwanauty na ekranie ekwipunku\"\n  STR_SHOWMORESTATSININVENTORYVIEW_DESC: \"Pokazuj dodatkowe informacje dotyczące wybranego żołnierza/akwanauty na ekranie ekwipunku.\"\n  STR_SNEAKYAI: \"Podstępna sztuczna inteligencja\"\n  STR_SNEAKYAI_DESC: \"Sztuczna inteligencja w miarę możliwości stara się uniknąć narażania swoich jednostek na ostrzał ze strony gracza oraz próbuje pozostawać poza jego zasięgiem w trakcie swojej tury.\"\n  STR_STRAFE: \"Alternatywna metoda ruchu\"\n  STR_STRAFE_DESC: \"Włącz tryb chodzenia w bok, biegania oraz jazdy z niezależnym ukierunkowaniem wieżyczki w czołgu.{NEWLINE}Przytrzymaj klawisz 'CTRL', by użyć alternatywnej metody ruchu.\"\n  STR_BATTLEEXPLOSIONHEIGHT: \"Rozmiar eksplozji\"\n  STR_BATTLEEXPLOSIONHEIGHT_DESC: \"Ustawienie pionowego rozprzestrzeniania się eksplozji.{NEWLINE}(Płasko: 0, kuliście: 3)\"\n  STR_AUTOSAVE: \"Automatycznie zapisuj grę\"\n  STR_AUTOSAVE_DESC: \"Umożliwia automatyczne zapisanie gry w określonych odstępach. Nie dotyczy trybu 'Człowiek z żelaza'.\"\n  STR_AUTOSAVE_FREQUENCY: \"Częstotliwość automatycznego zapisywania\"\n  STR_AUTOSAVE_FREQUENCY_DESC: \"Ustal, po ilu turach nastąpi automatyczne zapisanie gry.\"\n  STR_ALLOWPSIONICCAPTURE: \"Zezwalaj na przejęcie psioniczne\"\n  STR_ALLOWPSIONICCAPTURE_DESC: \"Kontrola umysłu nad wszystkimi pozostałymi przy życiu obcymi pozwala zakończyć misję. Są oni traktowani jako zneutralizowani i schwytani żywcem.\"\n  STR_ANYTIMEPSITRAINING: \"Szkolenie psioniczne w dowolnym momencie\"\n  STR_ANYTIMEPSITRAINING_DESC: \"Możesz w każdej chwili wysłać żołnierzy/akwanautów na szkolenie psioniczne/kontroli molekularnej lub też ich odwołać. Pamiętaj, że szkolenie początkowe trwa od 30 do 60 dni.\"\n  STR_SKIPNEXTTURNSCREEN: \"Pomijaj ekran 'Następna tura'\"\n  STR_SKIPNEXTTURNSCREEN_DESC: \"Ekran 'Następna tura' będzie po krótkiej chwili pomijany automatycznie.\"\n  STR_NOT_ENOUGH_SPACE: \"Brakuje miejsca!\"\n  STR_WEAPONSELFDESTRUCTION: \"Automatyczne zniszczenie broni obcych\"\n  STR_WEAPONSELFDESTRUCTION_DESC: \"Broń używana przez obcych ulegnie automatycznemu zniszczeniu, jeśli jej właściciel zostanie zabity, tak jak w XCOM: Enemy Unknown od Firaxis Games.\"\n  STR_RETAINCORPSES: \"Zachowaj przesłuchanych obcych\"\n  STR_RETAINCORPSES_DESC: \"Po przebadaniu żywych obcych, ciała będą dodane do magazynów, tak jak w XCOM 2012.\"\n  STR_SAVE_VOXEL_VIEW: \"Zrzut ekranu w widoku pierwszoosobowym\"\n  STR_RESERVE_TIME_UNITS_FOR_KNEEL: \"Rezerwuj JC na klęknięcie\"\n  STR_EXPEND_ALL_TIME_UNITS: \"Wykorzystaj wszystkie posiadane JC\"\n  STR_PSISTRENGTHEVAL: \"Oszacuj siłę psioniczną/molekularną\"\n  STR_PSISTRENGTHEVAL_DESC: \"Szacuje siłę psioniczną/molekularną wszystkich żołnierzy/akwanautów po zakończeniu właściwych badań.\"\n  STR_DISABLEAUTOEQUIP: \"Zablokuj automatyczne wyposażanie\"\n  STR_DISABLEAUTOEQUIP_DESC: \"Blokuje automatyczne wyposażanie nowych żołnierzy/akwanautów przed bitwą.\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT: \"Pozwalaj na własne rozwijanie siły psionicznej/molekularnej\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT_DESC: \"Siłę psioniczną/molekularną żołnierzy/akwanautów będzie można podnosić przez zdobywanie doświadczenia i trening.\"\n  STR_BATTLESMOOTHCAMERA: \"Płynna kamera strzału\"\n  STR_BATTLESMOOTHCAMERA_DESC: \"Podczas bitwy kamera będzie płynnie pokazywać lecące pociski.\"\n  STR_BATTLECONFIRMFIREMODE: \"Potwierdzanie strzału\"\n  STR_BATTLECONFIRMFIREMODE_DESC: \"Wymagaj ponownego kliknięcia na wybranym celu, aby potwierdzić strzał.\"\n  STR_SELECT_BASE_1: \"Wybierz bazę nr 1\"\n  STR_SELECT_BASE_2: \"Wybierz bazę nr 2\"\n  STR_SELECT_BASE_3: \"Wybierz bazę nr 3\"\n  STR_SELECT_BASE_4: \"Wybierz bazę nr 4\"\n  STR_SELECT_BASE_5: \"Wybierz bazę nr 5\"\n  STR_SELECT_BASE_6: \"Wybierz bazę nr 6\"\n  STR_SELECT_BASE_7: \"Wybierz bazę nr 7\"\n  STR_SELECT_BASE_8: \"Wybierz bazę nr 8\"\n  STR_VIDEO: \"OBRAZ\"\n  STR_AUDIO: \"DŹWIĘK\"\n  STR_BATTLESCAPE_UC: \"EKRAN BITWY\"\n  STR_MODS_UC: \"MODYFIKACJE\"\n  STR_MODS: \"Modyfikacje\"\n  STR_DISPLAY_RESOLUTION: \"Rozdzielczość ekranu\"\n  STR_DISPLAY_RESOLUTION_DESC: \"Zmienia rozdzielczość gry. Rozdzielczość ta będzie przeskalowana do pasującej. Strzałki przełączają pomiędzy dostępnymi rozdzielczościami. Kliknij, aby wprowadzić własną rozdzielczość.\"\n  STR_ORIGINAL: \"Oryginalny\"\n  STR_DISPLAY_MODE: \"Tryb wyświetlania\"\n  STR_WINDOWED: \"W oknie\"\n  STR_FULLSCREEN: \"Pełny ekran\"\n  STR_BORDERLESS: \"Bezramkowy\"\n  STR_DISPLAY_LANGUAGE: \"Język X-Comów i OpenXcoma\"\n  STR_DISPLAY_LANGUAGE_DESC: \"Zmienia język gier 'UFO: Nieznany wróg' oraz 'X-Com: Terror z głębin' oraz samego OpenXcoma.\"\n  STR_DISPLAY_FILTER: \"Filtr wyświetlania\"\n  STR_DISPLAY_FILTER_DESC: \"Zmienia filtr nałożony na ekran.{NEWLINE}*wymaga wspomagania sprzętowego OpenGL.\"\n  STR_DISPLAY_OPTIONS: \"Opcje wyświetlania\"\n  STR_LETTERBOXED: \"Format skrzynki na listy\"\n  STR_LETTERBOXED_DESC: \"Aby zachować oryginalne proporcje obrazu, będzie on wyświetlany w trybie 'skrzynki na listy'.\"\n  STR_RESIZABLE: \"Skalowalny\"\n  STR_LOCK_MOUSE: \"Złap myszkę\"\n  STR_LOCK_MOUSE_DESC: \"Uniemożliwia przesunięcie kursora myszy poza okno gry. Wciśnij Ctrl+G, by przełączyć tę funkcję w dowolnym momencie.\"\n  STR_FIXED_WINDOW_POSITION: \"Stała pozycja okna\"\n  STR_FIXED_WINDOW_POSITION_DESC: \"Ustawia stałą pozycję Okna.\"\n  STR_DISPLAY_SET_WINDOW_POSITION: \"Ustaw nową pozycję Okna Głównego\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_X: \"Nowy X lewej krawędzi:\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_Y: \"Nowy Y górnej krawędzi:\"\n  STR_MUSIC_VOLUME: \"Głośność muzyki\"\n  STR_MUSIC_VOLUME_DESC: \"Zmienia głośność muzyki w tle.\"\n  STR_SFX_VOLUME: \"Głośność efektów dźw.\"\n  STR_SFX_VOLUME_DESC: \"Zmienia głośność efektów dźwiękowych.\"\n  STR_UI_VOLUME: \"Głośność interfejsu\"\n  STR_UI_VOLUME_DESC: \"Zmienia głośność dźwięków interfejsu użytkownika.\"\n  STR_SCROLL_SPEED: \"Prędkość przewijania\"\n  STR_SCROLL_SPEED_GEO_DESC: \"Zmienia prędkość przewijania na ekranie Ziemi.\"\n  STR_SCROLL_SPEED_BATTLE_DESC: \"Zmienia prędkość przewijania mapy na ekranie bitwy.\"\n  STR_DOGFIGHT_SPEED: \"Prędkość walki przech.\"\n  STR_DOGFIGHT_SPEED_DESC: \"Zmienia prędkość walk przechwytujących pomiędzy samolotami/łodziami X-Comu a UFO/USO. Mniejsze prędkości mogą zwiększyć wydajność na słabszym sprzęcie.\"\n  STR_CLOCK_SPEED: \"Prędkość zegara\"\n  STR_CLOCK_SPEED_DESC: \"Zmienia prędkość zegara na ekranie Ziemi. Mniejsze prędkości mogą zwiększyć wydajność na słabszym sprzęcie.\"\n  STR_GLOBE_DETAILS: \"Szczegóły ekranu Ziemi\"\n  STR_GLOBE_COUNTRIES: \"Kraje\"\n  STR_GLOBE_COUNTRIES_DESC: \"Pokaże fundusze ze wszystkich krajów sponsorujących organizację X-Com na ekranie Ziemi.\"\n  STR_GLOBE_RADARS: \"Radary/Sonary\"\n  STR_GLOBE_RADARS_DESC: \"Pokazuje zasięg radarów/sonarów danej bazy na ekranie Ziemi.\"\n  STR_GLOBE_FLIGHT_PATHS: \"Tor lotu/płynięcia\"\n  STR_GLOBE_FLIGHT_PATHS_DESC: \"Pokazuje trasę samolotu/łodzi na ekranie Ziemi.\"\n  STR_CONTROLS_DESC: \"By zmienić, kliknij l.p.m. na skrócie, a następnie wybrany klawisz.{NEWLINE}Kliknij p.p.m. na skrócie, by go usunąć.\"\n  STR_BASE_GAME: \"Podstawowa gra\"\n  STR_MODS_TOOLTIP: \"Wersja {0}; Autor: {1}.{NEWLINE}{2}\"\n  STR_EDGE_SCROLL: \"Przewijanie krawędzi\"\n  STR_EDGE_SCROLL_DESC: \"Przełączane: Przesuwa mapę, jeśli l.p.m. będzie przytrzymany na krawędzi ekranu.{NEWLINE}Automatyczne: Przesuwa mapę gdy kursor myszy wyjdzie poza ekran.\"\n  STR_TRIGGER_SCROLL: \"Przełączane\"\n  STR_AUTO_SCROLL: \"Automatyczne\"\n  STR_DRAG_SCROLL: \"Przewijanie przeciągane\"\n  STR_DRAG_SCROLL_DESC: \"Przewija mapę gdy określony przycisk myszy jest wciśnięty i przytrzymany podczas przeciągania myszy.\"\n  STR_LEFT_MOUSE_BUTTON: \"Lewy p.m.\"\n  STR_MIDDLE_MOUSE_BUTTON: \"Środkowy p.m.\"\n  STR_RIGHT_MOUSE_BUTTON: \"Prawy p.m.\"\n  STR_FIRE_SPEED: \"Prędkość strzałów\"\n  STR_FIRE_SPEED_DESC: \"Zmienia prędkość pocisków.\"\n  STR_PLAYER_MOVEMENT_SPEED: \"Prędkość ruchu gracza\"\n  STR_PLAYER_MOVEMENT_SPEED_DESC: \"Zmienia prędkość poruszania się jednostek kontrolowanych przez gracza.\"\n  STR_COMPUTER_MOVEMENT_SPEED: \"Prędkość ruchu obcych\"\n  STR_COMPUTER_MOVEMENT_SPEED_DESC: \"Zmienia prędkość poruszania się jednostek kontrolowanych przez komputer.\"\n  STR_PATH_PREVIEW: \"Podgląd trasy\"\n  STR_PATH_ARROWS: \"Strzałki\"\n  STR_PATH_ARROWS_DESC: \"Kliknięcie pokaże trasę, którą podąży dana jednostka. Kolor wskazuje dostępne akcje: zielony -- może iść i strzelać; żółty -- może tylko iść; czerwony -- nie może iść.\"\n  STR_PATH_TIME_UNIT_COST: \"Jednostki czasu\"\n  STR_PATH_TIME_UNIT_COST_DESC: \"Kliknięcie pokaże pozostałą liczbę JC, które będzie miała jednostka po przybyciu do miejsca przeznaczenia.\"\n  STR_USER_INTERFACE_OPTIONS: \"Opcje interfejsu\"\n  STR_TOOLTIPS: \"Pokazuj podpowiedzi\"\n  STR_TOOLTIPS_DESC: \"Wyświetla podpowiedzi dla przycisków interfejsu potyczki taktycznej.\"\n  STR_DEATH_NOTIFICATIONS: \"Powiadamiaj o śmierci\"\n  STR_DEATH_NOTIFICATIONS_DESC: \"Wyświetla powiadomienie za każdym razem, gdy jeden z twoich żołnierzy umiera.\"\n  STR_SHOW_FUNDS: \"Pokazuj fundusze\"\n  STR_SHOW_FUNDS_DESC: \"Pokazuje aktualne fundusze nad zegarem na ekranie globu.\"\n  STR_MISSION_GENERATOR: \"GENERATOR MISJI\"\n  STR_MAP_OPTIONS: \"OPCJE MAPY\"\n  STR_ALIEN_OPTIONS: \"OPCJE OBCYCH\"\n  STR_MAP_TERRAIN: \"Teren\"\n  STR_MAP_DARKNESS: \"Ciemność\"\n  STR_MAP_DEPTH: \"Głębokość\"\n  STR_DIFFICULTY: \"Poziom trudności\"\n  STR_ALIEN_RACE: \"Rasa\"\n  STR_ALIEN_TECH_LEVEL: \"Poziom techniczny\"\n  STR_RANDOMIZE: \"Losuj\"\n  STR_OXCE_REQUIRED_QUESTION: \"Ta modyfikacja do poprawnego działania wymaga OpenXcom {0}. Uruchomić modyfikację?\"\n  STR_RESTORE_DEFAULTS_QUESTION: \"Czy na pewno chcesz przywrócić domyślne ustawienia?\"\n  STR_DISPLAY_OPTIONS_CONFIRM: \"Czy chcesz zachować obecne opcje wyświetlania?\"\n  STR_DISPLAY_OPTIONS_REVERT: \"Przywracam za 0:{0}\"\n  STR_MISSING_CONTENT_PROMPT: \"OSTRZEŻENIE:{SMALLLINE}Ten zapis zależy od modyfikacji, które są niedostępne. Brakująca treść będzie usunięta, a wczytanie tego zapisu może być nieudane.{NEWLINE}Kontynuować?\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT: \"Zapamiętuj status granatów\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT_DESC: \"Status granatów (zabezpieczony/odbezpieczony), ustawiony w menu ekwipowania oddziału przed bitwą będzie na stałe przypisywany do ekwipunku danego żołnierza/akwanauty.\"\n  STR_NEWSEEDONLOAD: \"Nowa losowość po wczytaniu danej gry\"\n  STR_NEWSEEDONLOAD_DESC: \"Wczytanie gry spowoduje ponowne ustawienie źródła liczb losowych, tak więc podjęcie tej samej akcji może przynieść inne rezultaty. Nie dotyczy trybu 'Człowiek z żelaza'.\"\n  STR_CHANGEVALUEBYMOUSEWHEEL: \"Umożliwiaj zmianę wartości rolką myszy\"\n  STR_CHANGEVALUEBYMOUSEWHEEL_DESC: \"Zezwala na użycie rolki myszy, by zwiększyć/zmniejszyć wartość kwoty.\"\n  STR_BATTLEHAIRBLEACH: \"Ulepszone grafiki żołnierzy/akwanautów\"\n  STR_BATTLEHAIRBLEACH_DESC: \"Zmienia grafiki zołnierza/akwanauty na ekranie bitwy tak, by pasowały do jego wyglądu wyposażenia\"\n  STR_DRAGSCROLLINVERT: \"Odwrócenie przewijania przeciąganego\"\n  STR_DRAGSCROLLINVERT_DESC: \"Odwraca kierunek przewijania przeciąganego. Gdy funkcja jest włączona, przewijaj w kierunku celu. Gdy funkcja jest wyłączona, przewijaj w drugą stronę.\"\n  STR_BATTLESCAPE_SCALE: \"Skala ekranu bitwy\"\n  STR_BATTLESCAPE_SCALE_DESC: \"Tryb skalowania ekranu bitwy. Bazuje na stałej rozdzielczości lub stałym poziomie przybliżenia.\"\n  STR_GEOSCAPE_SCALE: \"Skala ekranu Ziemi\"\n  STR_GEOSCAPESCALE_SCALE_DESC: \"Tryb skalowania ekranu Ziemi. Bazuje na stałej rozdzielczości lub stałym poziomie przybliżenia.\"\n  STR_1_5X: \"1,5.x oryginał\"\n  STR_2X: \"2x oryginał\"\n  STR_THIRD_DISPLAY: \"1/3 ekranu\"\n  STR_HALF_DISPLAY: \"1/2 ekranu\"\n  STR_FULL_DISPLAY: \"Pełny ekran\"\n  STR_FPS_LIMIT: \"Limit klatek na sekundę\"\n  STR_FPS_LIMIT_DESC: \"Ogranicza liczbę odświeżeń ekranu na sekundę, 0 - bez limitu. Jeśli renderowanie OpenGL jest włączone, OpenXcom używa zamiast tego synchronizacji pionowej.\"\n  STR_FPS_INACTIVE_LIMIT: \"Limit klatek na sekundę w tle\"\n  STR_FPS_INACTIVE_LIMIT_DESC: \"Ogranicza liczbę odświeżeń ekranu na sekundę, gdy OpenXcom działa w tle.\"\n  STR_NOALIENPANICMESSAGES: \"Nie pokazuj komunikatów o spanikowanych obcych\"\n  STR_NOALIENPANICMESSAGES_DESC: \"Wyłącza wiadomości o panice obcych, chyba że są oni widoczni dla gracza.\"\n  STR_ALIENBLEEDING: \"Wykrwawianie się obcych\"\n  STR_ALIENBLEEDING_DESC: \"Pozwala na zadawanie śmiertelnych ran większości obcym.\"\n  STR_FIELDPROMOTIONS: \"Awans polowy\"\n  STR_FIELDPROMOTIONS_DESC: \"Tylko żołnierze biorący udział w misji kwalifikują się do awansu.\"\n  STR_MEETINGPOINT: \"Prognozuj trajektorię UFO\"\n  STR_MEETINGPOINT_DESC: \"Pojazd kieruje się do punktu przechwycenia UFO według jego obecnej trajektorii.\"\n  STR_IRONMAN: \"CZŁOWIEK Z ŻELAZA\"\n  STR_IRONMAN_DESC: \"Brak ręcznego zapisywania\"\n  STR_SAVE_AND_ABANDON_GAME: \"ZAPISZ I OPUŚĆ GRĘ\"\n  STR_MOD_UNSUCCESSFUL: \"Wczytanie modyfikacji nieudane\"\n  STR_NEW_SAVED_GAME_SLOT: \"<NOWY ZAPIS GRY>\"\n  STR_AUTO_SAVE_GEOSCAPE_SLOT: \"<AUTOMATYCZNY EKRAN ZIEMI>\"\n  STR_AUTO_SAVE_BATTLESCAPE_SLOT: \"<AUTOMATYCZNY EKRAN BITWY>\"\n  STR_QUICK_SAVE_SLOT: \"<SZYBKI ZAPIS>\"\n  STR_DISPLAY_MODE_DESC: \"Zmienia sposób wyświetlania gry na Twoim ekranie.\"\n  STR_PREFERRED_MUSIC_FORMAT: \"Format muzyki\"\n  STR_PREFERRED_MUSIC_FORMAT_DESC: \"Wybiera preferowany format muzyki, który będzie używany w przypadku, gdy będzie dostępnych kilka innych.{NEWLINE}UWAGA: system Windows może niepoprawnie odtwarzać format MIDI.\"\n  STR_PREFERRED_SFX_FORMAT: \"Format efektów dźw.\"\n  STR_PREFERRED_SFX_FORMAT_DESC: \"Wybiera preferowany format efektów dźwiękowych, kiedy dostępnych jest więcej formatów.\"\n  STR_PREFERRED_VIDEO_FORMAT: \"Format wideo\"\n  STR_PREFERRED_VIDEO_FORMAT_DESC: \"Wybiera preferowany format wideo, gdy dostępnych jest ich więcej.\"\n  STR_PREFERRED_VIDEO_ANIMATION: \"Animacja\"\n  STR_PREFERRED_VIDEO_SLIDESHOW: \"Pokaz slajdów\"\n  STR_PREFERRED_FORMAT_AUTO: \"Automatyczny\"\n  STR_CURRENT_FORMAT: \"Aktualne: {0}\"\n  STR_SOUND_OPTIONS: \"Opcje dźwiękowe\"\n  STR_BACKGROUND_MUTE: \"Wyciszenie w tle\"\n  STR_BACKGROUND_MUTE_DESC: \"Wycisza wszystkie dźwięki, kiedy okno gry nie jest aktywne.\"\n  STR_FORCE_FIRE: \"Zignoruj linię strzału\"\n  STR_FORCE_FIRE_DESC: \"Wymusza otwarcie ognia, gdy przytrzymujesz klawisz 'Ctrl', niezależnie od reguł linii strzału.\"\n  STR_NO_AUDIO_HARDWARE_DETECTED: \"Nie wykryto sprzętu audio\"\n  STR_MOUSEWHEEL_SPEED: \"Prędkość przewijania rolką myszy\"\n  STR_MOUSEWHEEL_SPEED_DESC: \"Ustawia liczbę linii przewijanych za pomocą rolki myszy na listach.\"\n  STR_DISABLED: \"Zablokowane\"\n  STR_MAXIMIZE_INFO_SCREENS: \"Maksymalizuj ekrany z informacjami\"\n  STR_MAXIMIZE_INFO_SCREENS_DESC: \"Ekwipunek i inne różne ekrany będą wyświetlane na pełnym ekranie, niezależnie od ustawień skalowania.\"\n  STR_DIARY: \"DZIENNIK\"\n  STR_KILLED: \"ZABITY\"\n  STR_STUNNED: \"OGŁUSZONY\"\n  STR_PANICKED: \"SPANIKOWANY\"\n  STR_MINDCONTROLLED: \"PRZEJĘTO KONTROLĘ\"\n  STR_REGION_UNKNOWN: \"Niejawna\"\n  STR_WEAPON_UNKNOWN: \"Improwizacja\"\n  STR_UNKNOWN: \"Nieznany\"\n  STR_VICTORY: \"Zwycięstwo\"\n  STR_DEFEAT: \"Porażka\"\n  STR_NO_RECORD: \"Brak danych\"\n  STR_HUMAN: \"Człowiek\"\n  STR_FRIENDLY: \"Przyjazny\"\n  STR_HOSTILE: \"Wrogi\"\n  STR_NEUTRAL: \"Neutranly\"\n  STR_RATING_UC: \"OCENA\"\n  STR_LOCATION: \"POŁOŻENIE> {ALT}{0}\"\n  STR_DAYLIGHT_TYPE: \"CZAS> {ALT}{0}\"\n  STR_RACE_TYPE: \"RASA> {ALT}{0}\"\n  STR_DAY: \"Dzień\"\n  STR_NIGHT: \"Noc\"\n  STR_DAYS_WOUNDED: \"RANNY DNI> {ALT}{0}\"\n  STR_COMBAT: \"WALKA\"\n  STR_PERFORMANCE: \"DOŚWIADCZENIE\"\n  STR_NEUTRALIZATIONS_BY_RACE: \"ZNEUTRALIZOWANO WG. RASY\"\n  STR_NEUTRALIZATIONS_BY_RANK: \"ZNEUTRALIZOWANO WG. RANGI\"\n  STR_NEUTRALIZATIONS_BY_WEAPON: \"ZNEUTRALIZOWANO WG. BRONI\"\n  STR_MISSIONS_BY_LOCATION: \"MISJE WG. OBSZARU\"\n  STR_MISSIONS_BY_TYPE: \"MISJE WG. TYPU\"\n  STR_MISSIONS_BY_UFO: \"MISJE WG. UFO\"\n  STR_SCORE_VALUE: \"WYNIK> {ALT}{0}\"\n  STR_WINS: \"WYGRANYCH> {ALT}{0}\"\n  STR_STUNS: \"OGŁUSZONYCH> {ALT}{0}\"\n  STR_PANICKS: \"SPANIKOWANYCH> {ALT}{0}\"\n  STR_MINDCONTROLS: \"PRZEJĘTO KONTROLĘ> {ALT}{0}\"\n  STR_AWARDS: \"NAGRODY\"\n  STR_COMMENDATIONS_UC: \"WYRÓŻNIENIA\"\n  STR_COMMENDATIONS: \"Wyróżnienia\"\n  STR_MEDALS: \"MEDALE\"\n  STR_LOST_IN_SERVICE: \"Straceni na służbie\"\n  STR_MEDAL_NAME: \"Nazwa medalu\"\n  STR_MEDAL_AWARD_LEVEL: \"Klasa orderu\"\n  STR_MEDAL_DECOR_LEVEL: \"Stopień odznaczenia\"\n  STR_AWARD_0: \"Pierwszy order\"\n  STR_AWARD_1: \"Drugi order\"\n  STR_AWARD_2: \"Trzeci order\"\n  STR_AWARD_3: \"Czwarty order\"\n  STR_AWARD_4: \"Piąty order\"\n  STR_AWARD_5: \"Szósty order\"\n  STR_AWARD_6: \"Siódmy order\"\n  STR_AWARD_7: \"Ósmy order\"\n  STR_AWARD_8: \"Dziewiąty order\"\n  STR_AWARD_9: \"Dziesiąty order\"\n  STR_AWARD_DECOR_0: \"Brak\"\n  STR_AWARD_DECOR_1: \"Pierwsze brązowe odznaczenie\"\n  STR_AWARD_DECOR_2: \"Drugie brązowe odznaczenie\"\n  STR_AWARD_DECOR_3: \"Trzecie brązowe odznaczenie\"\n  STR_AWARD_DECOR_4: \"Pierwsze srebrne odznaczenie\"\n  STR_AWARD_DECOR_5: \"Drugie srebrne odznaczenie\"\n  STR_AWARD_DECOR_6: \"Trzecie srebrne odznaczenie\"\n  STR_AWARD_DECOR_7: \"Pierwsze złote odznaczenie\"\n  STR_AWARD_DECOR_8: \"Drugie złote odznaczenie\"\n  STR_AWARD_DECOR_9: \"Trzecie złote odznaczenie\"\n  STR_KILLED_IN_ACTION_MALE: \"ZABITY W AKCJI\"\n  STR_KILLED_IN_ACTION_FEMALE: \"ZABITA W AKCJI\"\n  STR_MISSING_IN_ACTION_MALE: \"ZAGINIONY W AKCJI\"\n  STR_MISSING_IN_ACTION_FEMALE: \"ZAGINIONA W AKCJI\"\n  STR_AVERAGE_MONTHLY_RATING: \"Średnia ocena miesięczna\"\n  STR_TOTAL_INCOME: \"Całkowity przychód\"\n  STR_TOTAL_EXPENDITURE: \"Całkowite wydatki\"\n  STR_MISSIONS_WON: \"Misje zakończone sukcesem\"\n  STR_MISSIONS_LOST: \"Misje zakończone porażką\"\n  STR_NIGHT_MISSIONS: \"Misje nocne\"\n  STR_BEST_RATING: \"Najwyższa ocena misji\"\n  STR_WORST_RATING: \"Najniższa ocena misji\"\n  STR_ALIEN_KILLS: \"Zabito obcych\"\n  STR_ALIEN_CAPTURES: \"Schwytano obcych\"\n  STR_FRIENDLY_KILLS: \"Przypadki ognia bratobójczego\"\n  STR_AVERAGE_ACCURACY: \"Średnia celność\"\n  STR_WEAPON_MOST_KILLS: \"Najskuteczniejsza broń\"\n  STR_ALIEN_MOST_KILLS: \"Najbardziej zabójczy obcy\"\n  STR_LONGEST_SERVICE: \"Miesięcy najdłuższej służby\"\n  STR_TOTAL_DAYS_WOUNDED: \"Dni choroby\"\n  STR_COUNTRIES_LOST: \"Państwa zinfiltrowane\"\n  STR_TOTAL_TERROR_SITES: \"Ataków terroru\"\n  STR_TOTAL_BASES: \"Zbudowano baz\"\n  STR_TOTAL_CRAFT: \"Posiadanych samolotów/łodzi\"\n  STR_TOTAL_SCIENTISTS: \"Wynajęto naukowców\"\n  STR_TOTAL_ENGINEERS: \"Wynajęto inżynierów\"\n  STR_TOTAL_RESEARCH: \"Badania zakończone\"\n  STR_DIARY_ACCURACY: \"CELNOŚĆ> {ALT}{0}%\"\n  STR_STATISTICS: \"Statystyki\"\n  STR_STATS: \"STAT.\"\n  STR_TIME_UNITS_ABBREVIATION: \"JC\"\n  STR_STAMINA_ABBREVIATION: \"KON\"\n  STR_HEALTH_ABBREVIATION: \"PŻ\"\n  STR_BRAVERY_ABBREVIATION: \"ODW\"\n  STR_REACTIONS_ABBREVIATION: \"REF\"\n  STR_FIRING_ACCURACY_ABBREVIATION: \"STR\"\n  STR_THROWING_ACCURACY_ABBREVIATION: \"RZC\"\n  STR_STRENGTH_ABBREVIATION: \"SIŁ\"\n  STR_MELEE_ACCURACY_ABBREVIATION: \"WW\"\n  STR_FOLDERS: \"FOLDERY\"\n  STR_DATA_FOLDER: \"Folder danych (oryginalne zasoby)\"\n  STR_USER_FOLDER: \"Folder użytkownika (mody, openxcom.log)\"\n  STR_SAVE_FOLDER: \"Folder zapisów (sejwy, zrzuty ekranu)\"\n  STR_CONFIG_FOLDER: \"Folder konfiguracyjny (options.cfg)\"\n  STR_DATA_FOLDER_DESC_1: \"Tam OpenXcom szuka oryginalnych zasobów gry (UFO i/lub TFTD).\"\n  STR_DATA_FOLDER_DESC_2: \"Wewnętrzne zasoby OpenXcom znajdują się w folderze 'common'. Mody wbudowane w OpenXcom są w folderze 'standard'.\"\n  STR_USER_FOLDER_DESC: \"Tu znajduje się plik z l;ogami ('openxcom.log'). Tu powinny trafiać też dodatkowe mody (w podfolderze 'mods').\"\n  STR_SAVE_FOLDER_DESC: \"Tu znajdują się zapisane gry. A także ustawienia generatora misji ('battle.cfg').\"\n  STR_CONFIG_FOLDER_DESC: \"Tu znajdują się ustawienia OpenXcom ('options.cfg'). Zwykle ten sam, co folder użytkownika.\"\n"
  },
  {
    "path": "bin/common/Language/pt-BR.yml",
    "content": "pt-BR:\n  STR_OPENXCOM: \"OpenXcom\"\n  STR_NEW_GAME: \"Novo Jogo\"\n  STR_LOAD_SAVED_GAME: \"Carregar Jogo\"\n  STR_SELECT_DIFFICULTY_LEVEL: \"Selecione o Nível de Dificuldade\"\n  STR_1_BEGINNER: \"1> Iniciante\"\n  STR_2_EXPERIENCED: \"2> Experiente\"\n  STR_3_VETERAN: \"3> Veterano\"\n  STR_4_GENIUS: \"4> Gênio\"\n  STR_5_SUPERHUMAN: \"5> Sobre-humano\"\n  STR_TIME: \"Hora\"\n  STR_DATE: \"Data\"\n  STR_SELECT_GAME_TO_LOAD: \"Selecionar jogo para carregar\"\n  STR_SELECT_SAVE_POSITION: \"Selecionar espaço de salvamento\"\n  STR_GAME_OPTIONS: \"OPÇÕES DO JOGO\"\n  STR_LOAD_GAME: \"CARREGAR JOGO\"\n  STR_SAVE_GAME: \"SALVAR JOGO\"\n  STR_ABANDON_GAME: \"ABANDONAR JOGO\"\n  STR_ABANDON_GAME_QUESTION: \"ABANDONAR JOGO?\"\n  STR_QUIT: \"Sair\"\n  STR_SAVING_GAME: \"Salvando jogo\"\n  STR_LOADING_GAME: \"Carregando jogo\"\n  STR_NO_SAVED_GAME_PRESENT: \"Não há partida gravada\"\n  STR_LOAD_UNSUCCESSFUL: \"Falha no carregamento\"\n  STR_SAVE_UNSUCCESSFUL: \"Falha na gravação\"\n  STR_LOAD_SUCCESSFUL: \"Carregamento bem sucedido\"\n  STR_SAVE_SUCCESSFUL: \"Gravação bem sucedida\"\n  STR_DELETE: \"APAGAR\"\n  STR_DELETE_UNSUCCESSFUL: \"Falha na exclusão\"\n  STR_IS_IT_OK_TO_DELETE_THE_SAVED_GAME: \"Tem certeza que deseja apagar a partida gravada?\"\n  STR_ORIGINAL_XCOM: \"X-Com Original\"\n  STR_LOADING: \"Carregando...\"\n  STR_DETAILS: \"DETALHES> {ALT}{0}\"\n  STR_NEW_BATTLE: \"Nova Batalha\"\n  STR_OPTIONS: \"Opções\"\n  STR_RIGHT_CLICK_TO_DELETE: \"Botão direito para apagar.\"\n  STR_RESTORE_DEFAULTS: \"Restaurar Padrões\"\n  STR_CONTROLS: \"CONTROLES\"\n  STR_GENERAL: \"Tela Geral\"\n  STR_GEOSCAPE: \"Tela Global\"\n  STR_BATTLESCAPE: \"Tela de Combate\"\n  STR_SCREENSHOT: \"Capturar Tela\"\n  STR_FPS_COUNTER: \"Contador de FPS\"\n  STR_ROTATE_LEFT: \"Girar à Esquerda\"\n  STR_ROTATE_RIGHT: \"Girar à Direita\"\n  STR_ROTATE_UP: \"Girar Acima\"\n  STR_ROTATE_DOWN: \"Girar Abaixo\"\n  STR_ZOOM_IN: \"Aumentar o Zoom\"\n  STR_ZOOM_OUT: \"Diminuir o Zoom\"\n  STR_TOGGLE_COUNTRY_DETAIL: \"Desativar/Ativar Detalhes do País\"\n  STR_TOGGLE_RADAR_RANGES: \"Desativar/Ativar Alcance de Radar\"\n  STR_SCROLL_LEFT: \"Deslocar para Esquerda\"\n  STR_SCROLL_RIGHT: \"Deslocar para Direita\"\n  STR_SCROLL_UP: \"Deslocar para Cima\"\n  STR_SCROLL_DOWN: \"Deslocar para Baixo\"\n  STR_UNIT_LEVEL_ABOVE: \"Mover Unidade para o Nível Acima\"\n  STR_UNIT_LEVEL_BELOW: \"Mover Unidade para o Nível Abaixo\"\n  STR_VIEW_LEVEL_ABOVE: \"Ver Nível Acima\"\n  STR_VIEW_LEVEL_BELOW: \"Ver Nível Abaixo\"\n  STR_CENTER_SELECTED_UNIT: \"Centralizar na Unidade\"\n  STR_PREVIOUS_UNIT: \"Selecionar Unidade Anterior\"\n  STR_NEXT_UNIT: \"Selecionar Próxima Unidade\"\n  STR_DESELECT_UNIT: \"Marcar como não selecionável\"\n  STR_USE_LEFT_HAND: \"Usar Item da Mão Esquerda\"\n  STR_USE_RIGHT_HAND: \"Usar Item da Mão Direita\"\n  STR_INVENTORY: \"Inventário\"\n  STR_MINIMAP: \"Minimapa\"\n  STR_MULTI_LEVEL_VIEW: \"Ver Todos os Níveis\"\n  STR_END_TURN: \"Finalizar Turno\"\n  STR_ABORT_MISSION: \"Abortar Missão\"\n  STR_UNIT_STATS: \"Status da Unidade\"\n  STR_KNEEL: \"Ajoelhar\"\n  STR_RELOAD: \"Recarregar\"\n  STR_TOGGLE_PERSONAL_LIGHTING: \"Desativar/Ativar Luz Pessoal\"\n  STR_DONT_RESERVE_TIME_UNITS: \"Não Reservar UTs\"\n  STR_RESERVE_TIME_UNITS_FOR_SNAP_SHOT: \"Reservar UTs para Tiro Simples\"\n  STR_RESERVE_TIME_UNITS_FOR_AIMED_SHOT: \"Reservar UTs para Tiro Preciso\"\n  STR_RESERVE_TIME_UNITS_FOR_AUTO_SHOT: \"Reservar UTs para Tiro Rajada\"\n  STR_CENTER_ON_ENEMY_1: \"Centralizar no Inimigo 1\"\n  STR_CENTER_ON_ENEMY_2: \"Centralizar no Inimigo 2\"\n  STR_CENTER_ON_ENEMY_3: \"Centralizar no Inimigo 3\"\n  STR_CENTER_ON_ENEMY_4: \"Centralizar no Inimigo 4\"\n  STR_CENTER_ON_ENEMY_5: \"Centralizar no Inimigo 5\"\n  STR_CENTER_ON_ENEMY_6: \"Centralizar no Inimigo 6\"\n  STR_CENTER_ON_ENEMY_7: \"Centralizar no Inimigo 7\"\n  STR_CENTER_ON_ENEMY_8: \"Centralizar no Inimigo 8\"\n  STR_CENTER_ON_ENEMY_9: \"Centralizar no Inimigo 9\"\n  STR_CENTER_ON_ENEMY_10: \"Centralizar no Inimigo 10\"\n  STR_CREATE_INVENTORY_TEMPLATE: \"Criar modelo de inventário\"\n  STR_APPLY_INVENTORY_TEMPLATE: \"Aplicar modelo de inventário\"\n  STR_CLEAR_INVENTORY: \"Limpar inventário\"\n  STR_AUTO_EQUIP: \"Auto-equipar\"\n  STR_QUICK_SAVE: \"Salvamento Rápido\"\n  STR_QUICK_LOAD: \"Carregamento Rápido\"\n  STR_ADVANCED: \"AVANÇADO\"\n  STR_AGGRESSIVERETALIATION: \"Retaliação agressiva\"\n  STR_AGGRESSIVERETALIATION_DESC: \"OVNIs tentarão detectar suas bases em todos os momentos, independentemente de seus parâmetros de missão.\"\n  STR_STORAGELIMITSENFORCED: \"Limites de armazenamento para itens recuperados\"\n  STR_STORAGELIMITSENFORCED_DESC: \"Reforça os limites da contenção de alienígenas e dos depósitos para alienígenas vivos e artefatos recuperados de missões.\"\n  STR_CANSELLLIVEALIENS: \"Vender alienígenas vivos\"\n  STR_CANSELLLIVEALIENS_DESC: \"Permitir a venda de alienígenas vivos. Recomenda-se o uso deste parâmetro caso a opção de limites de armazenamento esteja igualmente ativada.\"\n  STR_ALLOWBUILDINGQUEUE: \"Permitir construções em espera\"\n  STR_ALLOWBUILDINGQUEUE_DESC: \"Novas instalações podem ser colocadas ao lado das inacabadas.\"\n  STR_BATTLEAUTOEND: \"Terminar combates automaticamente\"\n  STR_BATTLEAUTOEND_DESC: \"As batalhas encerram-se automaticamente quando o último inimigo vivo é neutralizado.\"\n  STR_BATTLEINSTANTGRENADE: \"Granadas instantâneas\"\n  STR_BATTLEINSTANTGRENADE_DESC: \"Granadas armadas para 0 turnos explodirão logo após serem arremessadas, em vez de no fim do turno.\"\n  STR_BATTLEUFOEXTENDERACCURACY: \"Precisão como em UFO Extender\"\n  STR_BATTLEUFOEXTENDERACCURACY_DESC: \"Precisão de tiros diminui depois de uma certa distância, de acordo com o tipo de tiro. O valor de precisão ajustado será mostrado no cursor.\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE: \"Transferências aéreas\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE_DESC: \"Aeronave em voo pode ser transferida.\"\n  STR_CRAFTLAUNCHALWAYS: \"Forçar lançamento de aeronave\"\n  STR_CRAFTLAUNCHALWAYS_DESC: \"Naves podem ser lançadas, mesmo quando não estão prontas, ignorando a necessidade de manutenção.\"\n  STR_CUSTOMINITIALBASE: \"Base inicial personalizada\"\n  STR_CUSTOMINITIALBASE_DESC: \"Ao iniciar um novo jogo, você pode colocar manualmente as suas instalações inicias em vez de usar o layout padrão.\"\n  STR_GLOBESEASONS: \"Iluminação realística do globo\"\n  STR_GLOBESEASONS_DESC: \"Usa projeção mais realista da luz solar sobre o Globo de acordo com a inclinação axial da Terra.\"\n  STR_PLAYINTRO: \"Exibir introdução\"\n  STR_PLAYINTRO_DESC: \"Exibe vídeo de introdução na inicialização.\"\n  STR_SHOWMORESTATSININVENTORYVIEW: \"Estatísticas do Inventário\"\n  STR_SHOWMORESTATSININVENTORYVIEW_DESC: \"Mostra informações adicionais sobre o soldado selecionado na tela de inventário.\"\n  STR_SNEAKYAI: \"Inteligência artificial defensiva\"\n  STR_SNEAKYAI_DESC: \"A Inteligência Artificial tentará evitar expor-se ao inimigo tanto quanto possível.\"\n  STR_STRAFE: \"Métodos de movimento alternativo\"\n  STR_STRAFE_DESC: \"Permite metralhar, correr e movimentar a torre do tanque quando segurar o CTRL.\"\n  STR_BATTLEEXPLOSIONHEIGHT: \"Alcance vertical de explosão\"\n  STR_BATTLEEXPLOSIONHEIGHT_DESC: \"Altera a altura e proporção das explosões.{NEWLINE}(Planas: 0, Esféricas: 3)\"\n  STR_AUTOSAVE: \"Salvar jogo automaticamente\"\n  STR_AUTOSAVE_DESC: \"Salvar o jogo automaticamente em intervalos definidos. Não aplicável no modo \\\"Homem de Ferro\\\".\"\n  STR_AUTOSAVE_FREQUENCY: \"Intervalo do salvamento automático\"\n  STR_AUTOSAVE_FREQUENCY_DESC: \"Quantidade de turnos que o jogo será salvo automaticamente.\"\n  STR_ALLOWPSIONICCAPTURE: \"Permitir captura psíquica\"\n  STR_ALLOWPSIONICCAPTURE_DESC: \"Controlar a mente de todos os alienígenas restantes resulta em vitória, e eles contam como capturas vivas.\"\n  STR_ANYTIMEPSITRAINING: \"Treinamento psiônico a qualquer momento\"\n  STR_ANYTIMEPSITRAINING_DESC: \"Permite a designação de soldados para o treinamento psiônico em qualquer época do mês. Lembre-se, a formação inicial leva de 30 a 60 dias.\"\n  STR_SKIPNEXTTURNSCREEN: \"Pular tela de \\\"Próximo Turno\\\"\"\n  STR_SKIPNEXTTURNSCREEN_DESC: \"Telas \\\"Próximo Turno\\\" durante a batalha são avançados automaticamente após um pequeno tempo.\"\n  STR_NOT_ENOUGH_SPACE: \"Espaço Insuficiente!\"\n  STR_WEAPONSELFDESTRUCTION: \"Autodestruição de arma alienígena\"\n  STR_WEAPONSELFDESTRUCTION_DESC: \"Armas levadas por alienígenas se autodestruirão se o seu proprietário for morto, como no XCOM 2012.\"\n  STR_RETAINCORPSES: \"Reter alienígenas interrogados\"\n  STR_RETAINCORPSES_DESC: \"Depois de \\\"investigar\\\" alienígenas vivos, o seu corpo será adicionado aos depósitos, como no XCOM 2012.\"\n  STR_SAVE_VOXEL_VIEW: \"Capturar Tela em Primeira Pessoa\"\n  STR_RESERVE_TIME_UNITS_FOR_KNEEL: \"Reservar UTs para Ajoelhar\"\n  STR_EXPEND_ALL_TIME_UNITS: \"Gastar todas UTs restantes\"\n  STR_PSISTRENGTHEVAL: \"Avaliação da Força Psi\"\n  STR_PSISTRENGTHEVAL_DESC: \"Avalia a força psiônica de todos os soldados, após a conclusão da pesquisa adequada.\"\n  STR_DISABLEAUTOEQUIP: \"Desativar seleção automática de equipamento\"\n  STR_DISABLEAUTOEQUIP_DESC: \"Desativar a seleção automática de equipamento para novos soldados antes do combate\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT: \"Permitir melhoria da força psíquica\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT_DESC: \"Força psiônica dos soldados pode ser melhorado pela experiência e treinamento.\"\n  STR_BATTLESMOOTHCAMERA: \"Câmera acompanha projéteis\"\n  STR_BATTLESMOOTHCAMERA_DESC: \"A câmera na Tela de Combate permanecerá centralizada em projéteis durante o seu trajeto.\"\n  STR_BATTLECONFIRMFIREMODE: \"Modo de Confirmação de Disparo\"\n  STR_BATTLECONFIRMFIREMODE_DESC: \"Exige um segundo clique no mesmo objeto para confirmar ordens de fogo.\"\n  STR_SELECT_BASE_1: \"Selecionar Base 1\"\n  STR_SELECT_BASE_2: \"Selecionar Base 2\"\n  STR_SELECT_BASE_3: \"Selecionar Base 3\"\n  STR_SELECT_BASE_4: \"Selecionar Base 4\"\n  STR_SELECT_BASE_5: \"Selecionar Base 5\"\n  STR_SELECT_BASE_6: \"Selecionar Base 6\"\n  STR_SELECT_BASE_7: \"Selecionar Base 7\"\n  STR_SELECT_BASE_8: \"Selecionar Base 8\"\n  STR_VIDEO: \"VÍDEO\"\n  STR_AUDIO: \"ÁUDIO\"\n  STR_BATTLESCAPE_UC: \"TELA DE COMBATE\"\n  STR_MODS_UC: \"MODIFICAÇÕES\"\n  STR_MODS: \"Modificações\"\n  STR_DISPLAY_RESOLUTION: \"Resolução de Vídeo\"\n  STR_DISPLAY_RESOLUTION_DESC: \"Altera a resolução da tela. A resolução do jogo será redimensionada. As setas alternam entre as resoluções suportadas. Clique para inserir uma resolução personalizada.\"\n  STR_ORIGINAL: \"Tamanho Original\"\n  STR_DISPLAY_MODE: \"Modo de Exibição\"\n  STR_WINDOWED: \"Modo Janela\"\n  STR_FULLSCREEN: \"Tela Cheia\"\n  STR_BORDERLESS: \"Sem Bordas\"\n  STR_DISPLAY_LANGUAGE: \"Idioma do Jogo\"\n  STR_DISPLAY_LANGUAGE_DESC: \"Muda o idioma do texto do jogo.\"\n  STR_DISPLAY_FILTER: \"Filtro Gráfico\"\n  STR_DISPLAY_FILTER_DESC: \"Altera o filtro aplicado à tela do jogo.{NEWLINE}*requer aceleração de hardware OpenGL.\"\n  STR_DISPLAY_OPTIONS: \"Opções de Visualização\"\n  STR_LETTERBOXED: \"Manter Escala\"\n  STR_LETTERBOXED_DESC: \"Formata a tela para manter a proporção original.\"\n  STR_RESIZABLE: \"Redimensionável\"\n  STR_LOCK_MOUSE: \"Travar Mouse\"\n  STR_LOCK_MOUSE_DESC: \"Impede que o cursor do mouse deixe a janela do jogo. Ctrl+G para habilitar/desabilitar a qualquer momento.\"\n  STR_FIXED_WINDOW_POSITION: \"Fixar posição da Janela\"\n  STR_FIXED_WINDOW_POSITION_DESC: \"Define uma posição fixa para a janela.\"\n  STR_DISPLAY_SET_WINDOW_POSITION: \"Define a posição padrão do modo janela\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_X: \"Valor X do canto esquerdo:\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_Y: \"Valor Y do canto superior:\"\n  STR_MUSIC_VOLUME: \"Volume da Música\"\n  STR_MUSIC_VOLUME_DESC: \"Altera o volume da música de fundo.\"\n  STR_SFX_VOLUME: \"Volume dos Efeitos\"\n  STR_SFX_VOLUME_DESC: \"Altera o volume dos efeitos sonoros.\"\n  STR_UI_VOLUME: \"Volume da Interface\"\n  STR_UI_VOLUME_DESC: \"Altera o volume dos sinais sonoros da interface.\"\n  STR_SCROLL_SPEED: \"Velocidade de Rolagem\"\n  STR_SCROLL_SPEED_GEO_DESC: \"Altera a velocidade de rolagem do globo.\"\n  STR_SCROLL_SPEED_BATTLE_DESC: \"Altera a velocidade de rolagem do mapa.\"\n  STR_DOGFIGHT_SPEED: \"Velocidade de Combate\"\n  STR_DOGFIGHT_SPEED_DESC: \"Altera a velocidade das batalhas de interceptação entre naves e OVNIs. Velocidades mais lentas podem melhorar o desempenho em dispositivos mais lentos.\"\n  STR_CLOCK_SPEED: \"Velocidade do Relógio\"\n  STR_CLOCK_SPEED_DESC: \"Altera a velocidade do relógio no menu de Controle Global\"\n  STR_GLOBE_DETAILS: \"Detalhes do Globo\"\n  STR_GLOBE_COUNTRIES: \"Países\"\n  STR_GLOBE_COUNTRIES_DESC: \"Mostra países patrocinadores no globo.\"\n  STR_GLOBE_RADARS: \"Radares\"\n  STR_GLOBE_RADARS_DESC: \"Exibe alcance dos radares das bases no globo.\"\n  STR_GLOBE_FLIGHT_PATHS: \"Trajetos de Voo\"\n  STR_GLOBE_FLIGHT_PATHS_DESC: \"Exibe trajetos de voo das naves no globo.\"\n  STR_CONTROLS_DESC: \"Clique com o botão esquerdo em um atalho e pressione uma tecla para alterá-lo.{NEWLINE}Clique com o botão direito em um atalho para desativá-lo.\"\n  STR_BASE_GAME: \"Jogo base\"\n  STR_MODS_TOOLTIP: \"Versão {0} por {1}.{NEWLINE}{2}\"\n  STR_EDGE_SCROLL: \"Rolagem da Tela\"\n  STR_EDGE_SCROLL_DESC: \"Clique: Arrasta o mapa quando o botão esquerdo do mouse é pressionado sobre o canto da tela.{NEWLINE}Auto: Arrasta o mapa com o cursor no canto da tela.\"\n  STR_TRIGGER_SCROLL: \"Clique\"\n  STR_AUTO_SCROLL: \"Automático\"\n  STR_DRAG_SCROLL: \"Rolar Arrastando\"\n  STR_DRAG_SCROLL_DESC: \"Desloca o mapa quando o botão especificado do mouse é pressionado e arrastado.\"\n  STR_LEFT_MOUSE_BUTTON: \"Botão Esquerdo\"\n  STR_MIDDLE_MOUSE_BUTTON: \"Botão do Meio\"\n  STR_RIGHT_MOUSE_BUTTON: \"Botão Direito\"\n  STR_FIRE_SPEED: \"Velocidade do Tiro\"\n  STR_FIRE_SPEED_DESC: \"Muda a velocidade dos projéteis das armas.\"\n  STR_PLAYER_MOVEMENT_SPEED: \"Velocidade do Jogador\"\n  STR_PLAYER_MOVEMENT_SPEED_DESC: \"Muda a velocidade de movimento de unidades controladas pelo jogador.\"\n  STR_COMPUTER_MOVEMENT_SPEED: \"Velocidade da IA\"\n  STR_COMPUTER_MOVEMENT_SPEED_DESC: \"Muda a velocidade de movimento de unidades controladas pelo computador.\"\n  STR_PATH_PREVIEW: \"Pré-visualizar Percurso\"\n  STR_PATH_ARROWS: \"Setas\"\n  STR_PATH_ARROWS_DESC: \"Clicar mostra o caminho que a sua unidade vai utilizar até o destino. A cor indica ações disponíveis: Verde - pode mover e atirar; Amarelo - pode mover; Vermelho - não pode se mover.\"\n  STR_PATH_TIME_UNIT_COST: \"Unidades de Tempo\"\n  STR_PATH_TIME_UNIT_COST_DESC: \"Clicar mostra as UTs restantes que a sua unidade terá após se mover para o destino.\"\n  STR_USER_INTERFACE_OPTIONS: \"Opções de Interface\"\n  STR_TOOLTIPS: \"Descrições\"\n  STR_TOOLTIPS_DESC: \"Apresentar descrições dos botões do menu tático ao mover o cursor sobre os mesmos.\"\n  STR_DEATH_NOTIFICATIONS: \"Notificar Mortes\"\n  STR_DEATH_NOTIFICATIONS_DESC: \"Exibir uma notificação cada vez que um de seus soldados morre.\"\n  STR_SHOW_FUNDS: \"Mostrar Fundos\"\n  STR_SHOW_FUNDS_DESC: \"Mostra seus fundos atuais ao lado do relógio da Tela Global.\"\n  STR_MISSION_GENERATOR: \"GERADOR DE MISSÕES\"\n  STR_MAP_OPTIONS: \"OPÇÕES DO MAPA\"\n  STR_ALIEN_OPTIONS: \"OPÇÕES ALIENÍGENAS\"\n  STR_MAP_TERRAIN: \"Terreno\"\n  STR_MAP_DARKNESS: \"Escuridão\"\n  STR_MAP_DEPTH: \"Profundidade\"\n  STR_DIFFICULTY: \"Dificuldade\"\n  STR_ALIEN_RACE: \"Raça\"\n  STR_ALIEN_TECH_LEVEL: \"Nível Tecnológico\"\n  STR_RANDOMIZE: \"Aleatório\"\n  STR_OXCE_REQUIRED_QUESTION: \"Esse mod requer OpenXcom {0} para funcionar corretamente. Ligar esse mod ?\"\n  STR_RESTORE_DEFAULTS_QUESTION: \"Tem certeza de que deseja restaurar as opções padrão?\"\n  STR_DISPLAY_OPTIONS_CONFIRM: \"Você quer manter as opções de exibição atuais?\"\n  STR_DISPLAY_OPTIONS_REVERT: \"Revertendo em 0:{0}\"\n  STR_MISSING_CONTENT_PROMPT: \"AVISO:{SMALLLINE}Este jogo salvo depende de mods que não estão disponíveis. Conteúdo faltante será removido e poderá falhar ao carregar.{NEWLINE}Continuar?\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT: \"Guardar granadas pré-ativadas\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT_DESC: \"Guardar granadas ativadas após o fim de uma missão.\"\n  STR_NEWSEEDONLOAD: \"Recalcular valores aleatórios ao carregar jogo\"\n  STR_NEWSEEDONLOAD_DESC: \"Recalcular os números aleatórios utilizados para determinar eventos ou ações sempre que o jogo é recarregado, produzindo resultados diferentes. Opção inválida no modo \\\"Homem de Ferro\\\".\"\n  STR_CHANGEVALUEBYMOUSEWHEEL: \"Alterar os valores com a roda do mouse\"\n  STR_CHANGEVALUEBYMOUSEWHEEL_DESC: \"Permite que você use a roda do mouse para aumentar/diminuir os valores nesta quantidade.\"\n  STR_BATTLEHAIRBLEACH: \"Gráficos aprimorados dos soldados\"\n  STR_BATTLEHAIRBLEACH_DESC: \"Esta opção atribuí as características físicas presentes no retrato individual de cada soldado (tom de pele, cor do cabelo, etc.) às respectivas animações na Tela de Combate.\"\n  STR_DRAGSCROLLINVERT: \"Inverter arrastar para rolar a tela\"\n  STR_DRAGSCROLLINVERT_DESC: \"Quando habilitado, o deslizamento da tela ocorre na direção inversa a do mouse.\"\n  STR_BATTLESCAPE_SCALE: \"Tela de Combate\"\n  STR_BATTLESCAPE_SCALE_DESC: \"Modo de dimensionamento da janela da Tela de Combate, com base em uma resolução fixa (esticado para caber), ou um nível de zoom fixo (expandido para preencher).\"\n  STR_GEOSCAPE_SCALE: \"Tela Global\"\n  STR_GEOSCAPESCALE_SCALE_DESC: \"Modo de dimensionamento da janela da Tela Global, com base em uma resolução fixa (esticado para caber), ou um nível de zoom fixo (expandido para preencher).\"\n  STR_1_5X: \"1.5 vezes o original\"\n  STR_2X: \"2 vezes o original\"\n  STR_THIRD_DISPLAY: \"1/3 da tela\"\n  STR_HALF_DISPLAY: \"Metade da tela\"\n  STR_FULL_DISPLAY: \"Tela cheia\"\n  STR_FPS_LIMIT: \"Limitar FPS\"\n  STR_FPS_LIMIT_DESC: \"Limita o número de quadros de animação por segundo, 0 para ilimitado. Se a renderização OpenGL estiver habilitada, o jogo usará a sincronia vertical em seu lugar.\"\n  STR_FPS_INACTIVE_LIMIT: \"Limitar FPS em segundo plano\"\n  STR_FPS_INACTIVE_LIMIT_DESC: \"Limita o número de quadros de animação por segundo se o OpenXcom estiver em segundo plano.\"\n  STR_NOALIENPANICMESSAGES: \"Eliminar mensagens de aliens em pânico\"\n  STR_NOALIENPANICMESSAGES_DESC: \"Não exibe mensagens de alienígenas em pânico a menos que eles sejam visíveis ao jogador.\"\n  STR_ALIENBLEEDING: \"Ferimentos graves em alienígenas\"\n  STR_ALIENBLEEDING_DESC: \"Esta opção faz com que as unidades alienígenas sejam suscetíveis de sofrer ferimentos graves.\"\n  STR_FIELDPROMOTIONS: \"Promover apenas soldados em missão\"\n  STR_FIELDPROMOTIONS_DESC: \"Apenas os soldados presentes em missões de campo são elegíveis para receber promoções.\"\n  STR_MEETINGPOINT: \"Predizer trajetória do OVNI\"\n  STR_MEETINGPOINT_DESC: \"As naves voam para um ponto de encontro com o OVNI baseando-se em sua trajetória atual.\"\n  STR_IRONMAN: \"HOMEM DE FERRO\"\n  STR_IRONMAN_DESC: \"Bloqueia a opção de salvar o jogo manualmente\"\n  STR_SAVE_AND_ABANDON_GAME: \"SALVAR E ABANDONAR JOGO\"\n  STR_MOD_UNSUCCESSFUL: \"Falha ao carregar o Mod\"\n  STR_NEW_SAVED_GAME_SLOT: \"<NOVA PARTIDA SALVA>\"\n  STR_AUTO_SAVE_GEOSCAPE_SLOT: \"<AUTOSALVAMENTO NO GLOBO>\"\n  STR_AUTO_SAVE_BATTLESCAPE_SLOT: \"<AUTOSALVAMENTO EM COMBATE>\"\n  STR_QUICK_SAVE_SLOT: \"<SALVAMENTO RÁPIDO>\"\n  STR_DISPLAY_MODE_DESC: \"Alterar a forma como o jogo é exibido na tela.\"\n  STR_PREFERRED_MUSIC_FORMAT: \"Formato da Música\"\n  STR_PREFERRED_MUSIC_FORMAT_DESC: \"Escolhe o formato de música preferido para usar quando vários estiverem disponíveis.{NEWLINE}NOTA: A reprodução de MIDI sofrer problemas no Windows.\"\n  STR_PREFERRED_SFX_FORMAT: \"Efeitos Sonoros\"\n  STR_PREFERRED_SFX_FORMAT_DESC: \"Escolhe o formato de efeitos sonoros preferido para usar quando vários estiverem disponíveis.\"\n  STR_PREFERRED_VIDEO_FORMAT: \"Formato do Vídeo\"\n  STR_PREFERRED_VIDEO_FORMAT_DESC: \"Escolha o formato do vídeo preferido para usar quando múltiplos estejam disponíveis.\"\n  STR_PREFERRED_VIDEO_ANIMATION: \"Animação\"\n  STR_PREFERRED_VIDEO_SLIDESHOW: \"Exibição de slides\"\n  STR_PREFERRED_FORMAT_AUTO: \"Automático\"\n  STR_CURRENT_FORMAT: \"ATUAL: {0}\"\n  STR_SOUND_OPTIONS: \"Opções de Som\"\n  STR_BACKGROUND_MUTE: \"Silenciar em Segundo Plano\"\n  STR_BACKGROUND_MUTE_DESC: \"Silencia todo o som quando a janela do jogo não está ativa.\"\n  STR_FORCE_FIRE: \"Ignorar obstáculos na linha de fogo\"\n  STR_FORCE_FIRE_DESC: \"Permiti forçar um soldado a ignorar obstáculos na sua linha de fogo se o jogador mantiver a tecla CTRL pressionada.\"\n  STR_NO_AUDIO_HARDWARE_DETECTED: \"Dispositivo de som não detectado\"\n  STR_MOUSEWHEEL_SPEED: \"Velocidade de rolagem da roda do mouse\"\n  STR_MOUSEWHEEL_SPEED_DESC: \"Ajusta o número de linhas deslocadas nas listas a cada incremento da roda do mouse.\"\n  STR_DISABLED: \"Desabilitado\"\n  STR_MAXIMIZE_INFO_SCREENS: \"Maximizar telas de informação\"\n  STR_MAXIMIZE_INFO_SCREENS_DESC: \"Inventário e várias outras telas serão exibidas em tela cheia, independente das configurações de escala.\"\n  STR_DIARY: \"DIÁRIO\"\n  STR_KILLED: \"MORTO\"\n  STR_STUNNED: \"ATORDOADO\"\n  STR_PANICKED: \"EM PÂNICO\"\n  STR_MINDCONTROLLED: \"CONTROLADO\"\n  STR_REGION_UNKNOWN: \"Divulgado\"\n  STR_WEAPON_UNKNOWN: \"Improvisação\"\n  STR_UNKNOWN: \"Desconhecido\"\n  STR_VICTORY: \"Vitória\"\n  STR_DEFEAT: \"Derrota\"\n  STR_NO_RECORD: \"Sem Dados\"\n  STR_HUMAN: \"Humano\"\n  STR_FRIENDLY: \"Amistoso\"\n  STR_HOSTILE: \"Hostil\"\n  STR_NEUTRAL: \"Neutro\"\n  STR_RATING_UC: \"AVALIAÇÃO\"\n  STR_LOCATION: \"LOCALIZAÇÃO> {ALT}{0}\"\n  STR_DAYLIGHT_TYPE: \"TEMPO> {ALT}{0}\"\n  STR_RACE_TYPE: \"RAÇA> {ALT}{0}\"\n  STR_DAY: \"Dia\"\n  STR_NIGHT: \"Noite\"\n  STR_DAYS_WOUNDED: \"DIAS FERIDO> {ALT}{0}\"\n  STR_COMBAT: \"COMBATE\"\n  STR_PERFORMANCE: \"DESEMPENHO\"\n  STR_NEUTRALIZATIONS_BY_RACE: \"NEUTRALIZAÇÕES POR ESPÉCIE\"\n  STR_NEUTRALIZATIONS_BY_RANK: \"NEUTRALIZAÇÕES POR POSTO\"\n  STR_NEUTRALIZATIONS_BY_WEAPON: \"NEUTRALIZAÇÕES POR ARMA\"\n  STR_MISSIONS_BY_LOCATION: \"MISSÕES POR LOCAL\"\n  STR_MISSIONS_BY_TYPE: \"MISSÕES POR TIPO\"\n  STR_MISSIONS_BY_UFO: \"MISSÕES POR OVNI\"\n  STR_SCORE_VALUE: \"PONTUAÇÃO> {ALT}{0}\"\n  STR_WINS: \"VITÓRIAS> {ALT}{0}\"\n  STR_STUNS: \"ALVOS ATORDOADOS> {ALT}{0}\"\n  STR_PANICKS: \"PÂNICOS> {ALT}{0}\"\n  STR_MINDCONTROLS: \"ALVOS CONTROLADOS> {ALT}{0}\"\n  STR_AWARDS: \"DISTINÇÕES\"\n  STR_COMMENDATIONS_UC: \"CONDECORAÇÕES\"\n  STR_COMMENDATIONS: \"Condecorações\"\n  STR_MEDALS: \"MEDALHAS\"\n  STR_LOST_IN_SERVICE: \"PERDIDOS EM AÇÃO\"\n  STR_MEDAL_NAME: \"Nome da medalha\"\n  STR_MEDAL_AWARD_LEVEL: \"Nível de distinção\"\n  STR_MEDAL_DECOR_LEVEL: \"Nível de condecoração\"\n  STR_AWARD_0: \"Prim. distinção\"\n  STR_AWARD_1: \"Seg. distinção\"\n  STR_AWARD_2: \"Terc. distinção\"\n  STR_AWARD_3: \"Quarta distinção\"\n  STR_AWARD_4: \"Quinta distinção\"\n  STR_AWARD_5: \"Sexta distinção\"\n  STR_AWARD_6: \"Sétima distinção\"\n  STR_AWARD_7: \"Oitava distinção\"\n  STR_AWARD_8: \"Nona distinção\"\n  STR_AWARD_9: \"Déc. distinção\"\n  STR_AWARD_DECOR_0: \"Nenhuma\"\n  STR_AWARD_DECOR_1: \"Primeira medalha de bronze\"\n  STR_AWARD_DECOR_2: \"Segunda medalha de bronze\"\n  STR_AWARD_DECOR_3: \"Terceira medalha de bronze\"\n  STR_AWARD_DECOR_4: \"Primeira medalha de prata\"\n  STR_AWARD_DECOR_5: \"Segunda medalha de prata\"\n  STR_AWARD_DECOR_6: \"Terceira medalha de prata\"\n  STR_AWARD_DECOR_7: \"Primeira medalha de ouro\"\n  STR_AWARD_DECOR_8: \"Segunda medalha de ouro\"\n  STR_AWARD_DECOR_9: \"Terceira medalha de ouro\"\n  STR_KILLED_IN_ACTION_MALE: \"MORTO EM COMBATE\"\n  STR_KILLED_IN_ACTION_FEMALE: \"MORTA EM COMBATE\"\n  STR_MISSING_IN_ACTION_MALE: \"DESAPARECIDO EM COMBATE\"\n  STR_MISSING_IN_ACTION_FEMALE: \"DESAPARECIDA EM COMBATE\"\n  STR_AVERAGE_MONTHLY_RATING: \"Avaliação média mensal\"\n  STR_TOTAL_INCOME: \"Receita total\"\n  STR_TOTAL_EXPENDITURE: \"Despesa total\"\n  STR_MISSIONS_WON: \"Missões concluídas\"\n  STR_MISSIONS_LOST: \"Missões fracassadas\"\n  STR_NIGHT_MISSIONS: \"Missões noturnas\"\n  STR_BEST_RATING: \"Melhor avaliação em missão\"\n  STR_WORST_RATING: \"Pior avaliação em missão\"\n  STR_ALIEN_KILLS: \"Alienígenas mortos\"\n  STR_ALIEN_CAPTURES: \"Alienígenas capturados\"\n  STR_FRIENDLY_KILLS: \"Incidentes com fogo amigo\"\n  STR_AVERAGE_ACCURACY: \"Média de precisão\"\n  STR_WEAPON_MOST_KILLS: \"Arma mais eficaz\"\n  STR_ALIEN_MOST_KILLS: \"Alienígena mais mortífero\"\n  STR_LONGEST_SERVICE: \"Mais meses em serviço\"\n  STR_TOTAL_DAYS_WOUNDED: \"Dias de baixa\"\n  STR_COUNTRIES_LOST: \"Países infiltrados\"\n  STR_TOTAL_TERROR_SITES: \"Ataques de terror\"\n  STR_TOTAL_BASES: \"Bases construídas\"\n  STR_TOTAL_CRAFT: \"Veículos possuídos\"\n  STR_TOTAL_SCIENTISTS: \"Cientistas contratados\"\n  STR_TOTAL_ENGINEERS: \"Engenheiros contratados\"\n  STR_TOTAL_RESEARCH: \"Pesquisa concluída\"\n  STR_DIARY_ACCURACY: \"PRECISÃO> {ALT}{0}%\"\n  STR_STATISTICS: \"Estatísticas\"\n  STR_STATS: \"ESTAT.\"\n  STR_TIME_UNITS_ABBREVIATION: \"UT\"\n  STR_STAMINA_ABBREVIATION: \"VIG\"\n  STR_HEALTH_ABBREVIATION: \"SAÚ\"\n  STR_BRAVERY_ABBREVIATION: \"BRA\"\n  STR_REACTIONS_ABBREVIATION: \"REA\"\n  STR_FIRING_ACCURACY_ABBREVIATION: \"PRE\"\n  STR_THROWING_ACCURACY_ABBREVIATION: \"ARR\"\n  STR_STRENGTH_ABBREVIATION: \"FOR\"\n  STR_MELEE_ACCURACY_ABBREVIATION: \"CRP\"\n  STR_FOLDERS: \"PASTAS\"\n  STR_DATA_FOLDER: \"Pasta Data (original resources)\"\n  STR_USER_FOLDER: \"Pasta User (mods, openxcom.log)\"\n  STR_SAVE_FOLDER: \"Pasta Save (saved games, screenshots)\"\n  STR_CONFIG_FOLDER: \"Pasta Config (options.cfg)\"\n  STR_DATA_FOLDER_DESC_1: \"É aqui que o OpenXcom procura os recursos originais do jogo (UFO and/or TFTD).\"\n  STR_DATA_FOLDER_DESC_2: \"Os recursos internos do OpenXcom estão na pasta 'common'. Os mods internos do OpenXcom estão na pasta 'standard'.\"\n  STR_USER_FOLDER_DESC: \"O arquivo de log ('openxcom.log') é armazenado aqui. Todos os mods personalizados também pertencem aqui (na subpasta 'mods').\"\n  STR_SAVE_FOLDER_DESC: \"Seus jogos salvos estão localizados aqui. Além disso, as configurações do gerador de missões ('battle.cfg') podem ser encontradas aqui.\"\n  STR_CONFIG_FOLDER_DESC: \"É aqui que as configurações do OpenXcom ('options.cfg') são armazenadas. Normalmente o mesmo que a Pasta User.\"\n"
  },
  {
    "path": "bin/common/Language/pt-PT.yml",
    "content": "pt-PT:\n  STR_OPENXCOM: \"OpenXcom\"\n  STR_NEW_GAME: \"Novo jogo\"\n  STR_LOAD_SAVED_GAME: \"Carregar jogo\"\n  STR_SELECT_DIFFICULTY_LEVEL: \"Selecionar nível de dificuldade\"\n  STR_1_BEGINNER: \"1> Principiante\"\n  STR_2_EXPERIENCED: \"2> Experiente\"\n  STR_3_VETERAN: \"3> Veterano\"\n  STR_4_GENIUS: \"4> Génio\"\n  STR_5_SUPERHUMAN: \"5> Sobre-Humano\"\n  STR_TIME: \"Hora\"\n  STR_DATE: \"Data\"\n  STR_SELECT_GAME_TO_LOAD: \"Selecionar o jogo a carregar\"\n  STR_SELECT_SAVE_POSITION: \"Selecione uma posição para guardar\"\n  STR_GAME_OPTIONS: \"OPÇÕES DE JOGO\"\n  STR_LOAD_GAME: \"CARREGAR JOGO\"\n  STR_SAVE_GAME: \"GUARDAR JOGO\"\n  STR_ABANDON_GAME: \"ABANDONAR JOGO\"\n  STR_ABANDON_GAME_QUESTION: \"ABANDONAR JOGO?\"\n  STR_QUIT: \"Sair\"\n  STR_SAVING_GAME: \"A guardar jogo\"\n  STR_LOADING_GAME: \"A carregar jogo\"\n  STR_NO_SAVED_GAME_PRESENT: \"Nenhum ficheiro de jogo guardado\"\n  STR_LOAD_UNSUCCESSFUL: \"Erro ao carregar jogo\"\n  STR_SAVE_UNSUCCESSFUL: \"Falha ao guardar jogo\"\n  STR_LOAD_SUCCESSFUL: \"Jogo guardado com sucesso\"\n  STR_SAVE_SUCCESSFUL: \"Jogo guardado com sucesso\"\n  STR_DELETE: \"ELIMINAR\"\n  STR_DELETE_UNSUCCESSFUL: \"Falha ao eliminar jogo\"\n  STR_IS_IT_OK_TO_DELETE_THE_SAVED_GAME: \"Deseja apagar este jogo guardado?\"\n  STR_ORIGINAL_XCOM: \"Original\"\n  STR_LOADING: \"A carregar...\"\n  STR_DETAILS: \"DETALHES> {ALT}{0}\"\n  STR_NEW_BATTLE: \"Novo combate\"\n  STR_OPTIONS: \"Opções\"\n  STR_RIGHT_CLICK_TO_DELETE: \"Clique no botão direito para apagar o ficheiro\"\n  STR_RESTORE_DEFAULTS: \"Usar predefinições\"\n  STR_CONTROLS: \"CONTROLES\"\n  STR_GENERAL: \"Geral\"\n  STR_GEOSCAPE: \"Globo\"\n  STR_BATTLESCAPE: \"Combate\"\n  STR_SCREENSHOT: \"Captura de ecrã\"\n  STR_FPS_COUNTER: \"Contador de FPS\"\n  STR_ROTATE_LEFT: \"Rodar para a esquerda\"\n  STR_ROTATE_RIGHT: \"Rodar para a direita\"\n  STR_ROTATE_UP: \"Rodar para cima\"\n  STR_ROTATE_DOWN: \"Rodar para baixo\"\n  STR_ZOOM_IN: \"Aumentar Zoom\"\n  STR_ZOOM_OUT: \"Diminuir Zoom\"\n  STR_TOGGLE_COUNTRY_DETAIL: \"Mostrar detalhes de países\"\n  STR_TOGGLE_RADAR_RANGES: \"Mostrar alcance de radar\"\n  STR_SCROLL_LEFT: \"Navegar para a esquerda\"\n  STR_SCROLL_RIGHT: \"Navegar para a direita\"\n  STR_SCROLL_UP: \"Navegar para cima\"\n  STR_SCROLL_DOWN: \"Navegar para baixo\"\n  STR_UNIT_LEVEL_ABOVE: \"Subir um nível\"\n  STR_UNIT_LEVEL_BELOW: \"Descer um nível\"\n  STR_VIEW_LEVEL_ABOVE: \"Ver nível acima\"\n  STR_VIEW_LEVEL_BELOW: \"Ver nível abaixo\"\n  STR_CENTER_SELECTED_UNIT: \"Centrar em unidade selecionada\"\n  STR_PREVIOUS_UNIT: \"Unidade anterior\"\n  STR_NEXT_UNIT: \"Unidade seguinte\"\n  STR_DESELECT_UNIT: \"Marcar como não-selecionável \"\n  STR_USE_LEFT_HAND: \"Usar item da mão esquerda\"\n  STR_USE_RIGHT_HAND: \"Usar item da mão direita\"\n  STR_INVENTORY: \"Equipamento\"\n  STR_MINIMAP: \"Minimapa\"\n  STR_MULTI_LEVEL_VIEW: \"Ver todos os níveis\"\n  STR_END_TURN: \"Fim de turno\"\n  STR_ABORT_MISSION: \"Abortar missão\"\n  STR_UNIT_STATS: \"Informações da unidade\"\n  STR_KNEEL: \"Ajoelhar\"\n  STR_RELOAD: \"Recarregar\"\n  STR_TOGGLE_PERSONAL_LIGHTING: \"Ligar/Desligar luz de presença\"\n  STR_DONT_RESERVE_TIME_UNITS: \"Não reservar UTs\"\n  STR_RESERVE_TIME_UNITS_FOR_SNAP_SHOT: \"Reservar UTs para Tiro simples\"\n  STR_RESERVE_TIME_UNITS_FOR_AIMED_SHOT: \"Reservar UTs para Tiro preciso\"\n  STR_RESERVE_TIME_UNITS_FOR_AUTO_SHOT: \"Reservar UTs para Rajada\"\n  STR_CENTER_ON_ENEMY_1: \"Centrar em inimigo 1\"\n  STR_CENTER_ON_ENEMY_2: \"Centrar em inimigo 2\"\n  STR_CENTER_ON_ENEMY_3: \"Centrar em inimigo 3\"\n  STR_CENTER_ON_ENEMY_4: \"Centrar em inimigo 4\"\n  STR_CENTER_ON_ENEMY_5: \"Centrar em inimigo 5\"\n  STR_CENTER_ON_ENEMY_6: \"Centrar em inimigo 6\"\n  STR_CENTER_ON_ENEMY_7: \"Centrar em inimigo 7\"\n  STR_CENTER_ON_ENEMY_8: \"Centrar em inimigo 8\"\n  STR_CENTER_ON_ENEMY_9: \"Centrar em inimigo 9\"\n  STR_CENTER_ON_ENEMY_10: \"Centrar em inimigo 10\"\n  STR_CREATE_INVENTORY_TEMPLATE: \"Criar modelo de equipamento\"\n  STR_APPLY_INVENTORY_TEMPLATE: \"Aplicar modelo de equipamento\"\n  STR_CLEAR_INVENTORY: \"Limpar equipamento\"\n  STR_AUTO_EQUIP: \"Autoequipar\"\n  STR_QUICK_SAVE: \"Gravação rápida\"\n  STR_QUICK_LOAD: \"Carregamento rápido\"\n  STR_ADVANCED: \"AVANÇADAS\"\n  STR_AGGRESSIVERETALIATION: \"Retaliação agressiva\"\n  STR_AGGRESSIVERETALIATION_DESC: \"Todos os OVNIs tentarão detetar bases X-Com, independentemente das suas diretivas.\"\n  STR_STORAGELIMITSENFORCED: \"Limitar armazenamento para itens recuperados\"\n  STR_STORAGELIMITSENFORCED_DESC: \"Esta opção impõe limites de armazenamento para alienígenas vivos capturados e artefactos recuperados durante missões.\"\n  STR_CANSELLLIVEALIENS: \"Vender alienígenas vivos\"\n  STR_CANSELLLIVEALIENS_DESC: \"Permitir a venda de alienígenas vivos. Recomenda-se o uso deste parâmetro caso a opção de limites de armazenamento esteja igualmente ativada.\"\n  STR_ALLOWBUILDINGQUEUE: \"Permitir construções em espera\"\n  STR_ALLOWBUILDINGQUEUE_DESC: \"Permitir a construção de novas instalações adjacente a outras estruturas em processo de construção. \"\n  STR_BATTLEAUTOEND: \"Terminar combates automaticamente\"\n  STR_BATTLEAUTOEND_DESC: \"Os combates terminam automaticamente assim que último inimigo for neutralizado.\"\n  STR_BATTLEINSTANTGRENADE: \"Detonação instantânea\"\n  STR_BATTLEINSTANTGRENADE_DESC: \"Explosivos programados para 0 turnos detonam imediatamente após serem lançados.\"\n  STR_BATTLEUFOEXTENDERACCURACY: \"Precisão de fogo realista\"\n  STR_BATTLEUFOEXTENDERACCURACY_DESC: \"A precisão de fogo é exponencialmente reduzida após uma certa distância, de acordo com o modo de tiro selecionado. O valor de precisão ajustado será mostrado no cursor.\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE: \"Transferência de aeronaves em voo\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE_DESC: \"Permitir a transferência de aeronaves durante voo.\"\n  STR_CRAFTLAUNCHALWAYS: \"Forçar descolagem\"\n  STR_CRAFTLAUNCHALWAYS_DESC: \"Esta opção permite ao jogador enviar aeronaves em missão, mesmo que estas não estejam completamente reabastecidas, reparadas ou rearmadas.\"\n  STR_CUSTOMINITIALBASE: \"Personalizar base inicial\"\n  STR_CUSTOMINITIALBASE_DESC: \"Permitir a colocação manual das instalações da primeira base ao iniciar o jogo, em vez de forçar o modelo padrão.\"\n  STR_GLOBESEASONS: \"Projeção solar realista\"\n  STR_GLOBESEASONS_DESC: \"Reproduzir um modelo de projeção solar realista no globo, de acordo com a inclinação axial da Terra.\"\n  STR_PLAYINTRO: \"Reproduzir introdução\"\n  STR_PLAYINTRO_DESC: \"Reproduzir o vídeo de introdução ao iniciar o jogo.\"\n  STR_SHOWMORESTATSININVENTORYVIEW: \"Informações adicionais no menu de equipamento\"\n  STR_SHOWMORESTATSININVENTORYVIEW_DESC: \"Adicionar informações sobre o soldado selecionado ao menu de equipamento.\"\n  STR_SNEAKYAI: \"IA Defensiva\"\n  STR_SNEAKYAI_DESC: \"A IA tentará evitar expor-se ao inimigo tanto quanto possível.\"\n  STR_STRAFE: \"Modos alternativos de movimento\"\n  STR_STRAFE_DESC: \"Se ativada, esta opção permite movimento lateral e passo de corrida em tropas em campo. Permite igualmente o movimento rotativo da torre de um tanque. (CTRL + botões do rato).\"\n  STR_BATTLEEXPLOSIONHEIGHT: \"Alcance vertical de explosão\"\n  STR_BATTLEEXPLOSIONHEIGHT_DESC: \"Altera a altura e proporção das explosões.{NEWLINE}(Planas: 0; esféricas: 3)\"\n  STR_AUTOSAVE: \"Guardar jogo automaticamente\"\n  STR_AUTOSAVE_DESC: \"Guardar o jogo automaticamente em intervalos definidos. Não aplicável no modo \\\"Homem de Ferro\\\".\"\n  STR_AUTOSAVE_FREQUENCY: \"Intervalo de gravação automática\"\n  STR_AUTOSAVE_FREQUENCY_DESC: \"Especificar o número de turnos após os quais o jogo é guardado automaticamente.\"\n  STR_ALLOWPSIONICCAPTURE: \"Captura psíquica\"\n  STR_ALLOWPSIONICCAPTURE_DESC: \"O jogador vence a missão se todos os inimigos restantes estiverem sob controlo mental, sendo capturados vivos.\"\n  STR_ANYTIMEPSITRAINING: \"Iniciar treino psíquico em qualquer altura\"\n  STR_ANYTIMEPSITRAINING_DESC: \"Permitir a atribuição de soldados ao programa de treino psíquico em qualquer altura do mês. Os soldados podem levar desde 30 a 60 dias para completar o programa de treino inicial.\"\n  STR_SKIPNEXTTURNSCREEN: \"Saltar ecrãs de fim de turno automaticamente\"\n  STR_SKIPNEXTTURNSCREEN_DESC: \"Durante situações de combate, o jogo salta automaticamente os ecrãs de fim de turno.\"\n  STR_NOT_ENOUGH_SPACE: \"Não há espaço suficiente!\"\n  STR_WEAPONSELFDESTRUCTION: \"Autodestruição de armas alienígenas\"\n  STR_WEAPONSELFDESTRUCTION_DESC: \"Se um alienígena for morto, todas as armas que transporta são automaticamente destruídas.\"\n  STR_RETAINCORPSES: \"Manter alienígenas interrogados\"\n  STR_RETAINCORPSES_DESC: \"Após a interrogação de alienígenas vivos, os cadáveres serão adicionados aos armazéns.\"\n  STR_SAVE_VOXEL_VIEW: \"Captura de ecrã (plano subjetivo)\"\n  STR_RESERVE_TIME_UNITS_FOR_KNEEL: \"Reservar UTs para Ajoelhar\"\n  STR_EXPEND_ALL_TIME_UNITS: \"Usar UTs restantes\"\n  STR_PSISTRENGTHEVAL: \"Avaliação psíquica\"\n  STR_PSISTRENGTHEVAL_DESC: \"Avaliar o Poder Psíquico de todos os soldados após a conclusão dos projetos de investigação necessários.\"\n  STR_DISABLEAUTOEQUIP: \"Desativar seleção automática de equipamento\"\n  STR_DISABLEAUTOEQUIP_DESC: \"Desativar a seleção automática de equipamento para novos soldados antes do combate.\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT: \"Permitir evolução de Poder Psíquico\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT_DESC: \"Permitir a evolução do Poder Psíquico dos agentes X-Com através de treino e experiência.\"\n  STR_BATTLESMOOTHCAMERA: \"Centrar câmara em projétil\"\n  STR_BATTLESMOOTHCAMERA_DESC: \"Centrar a câmara em projéteis em movimento.\"\n  STR_BATTLECONFIRMFIREMODE: \"Modo de confirmação de tiro\"\n  STR_BATTLECONFIRMFIREMODE_DESC: \"Ativar a opção para confirmar todas as ordens relativas a disparar armas com um duplo clique do botão do rato.\"\n  STR_SELECT_BASE_1: \"Selecionar base 1\"\n  STR_SELECT_BASE_2: \"Selecionar base 2\"\n  STR_SELECT_BASE_3: \"Selecionar base 3\"\n  STR_SELECT_BASE_4: \"Selecionar base 4\"\n  STR_SELECT_BASE_5: \"Selecionar base 5\"\n  STR_SELECT_BASE_6: \"Selecionar base 6\"\n  STR_SELECT_BASE_7: \"Selecionar base 7\"\n  STR_SELECT_BASE_8: \"Selecionar base 8\"\n  STR_VIDEO: \"VÍDEO\"\n  STR_AUDIO: \"ÁUDIO\"\n  STR_BATTLESCAPE_UC: \"COMBATE\"\n  STR_MODS_UC: \"MODIFICAÇÕES\"\n  STR_MODS: \"Modificações\"\n  STR_DISPLAY_RESOLUTION: \"Resolução de ecrã\"\n  STR_DISPLAY_RESOLUTION_DESC: \"Alterar a resolução da janela utilizando as setas ou inserindo valores. A resolução da tela de jogo será automaticamente redimensionada de acordo com o valor selecionado. \"\n  STR_ORIGINAL: \"Original\"\n  STR_DISPLAY_MODE: \"Modo de ecrã\"\n  STR_WINDOWED: \"Janela\"\n  STR_FULLSCREEN: \"Ecrã cheio\"\n  STR_BORDERLESS: \"Sem bordas\"\n  STR_DISPLAY_LANGUAGE: \"Idioma\"\n  STR_DISPLAY_LANGUAGE_DESC: \"Altera o idioma de apresentação do jogo.\"\n  STR_DISPLAY_FILTER: \"Filtro gráfico\"\n  STR_DISPLAY_FILTER_DESC: \"Alterar o filtro gráfico aplicado ao ecrã de jogo.{NEWLINE}*Esta opção utiliza aceleração de hardware com base na biblioteca OpenGL.\"\n  STR_DISPLAY_OPTIONS: \"Opções de visualização\"\n  STR_LETTERBOXED: \"Barras horizontais\"\n  STR_LETTERBOXED_DESC: \"Adicionar barras horizontais na aresta inferior e superior do ecrã, de maneira a manter a proporção de tela original. \"\n  STR_RESIZABLE: \"Redimensionável\"\n  STR_LOCK_MOUSE: \"Bloquear cursor\"\n  STR_LOCK_MOUSE_DESC: \"Impedir a saída do cursor do rato para fora da aplicação enquanto o jogo estiver a correr em modo de janela. Usar Ctrl+G para ativar / desativar em qualquer altura.\"\n  STR_FIXED_WINDOW_POSITION: \"Fixar posição de janela\"\n  STR_FIXED_WINDOW_POSITION_DESC: \"Selecionar posição fixa de janela\"\n  STR_DISPLAY_SET_WINDOW_POSITION: \"Selecionar nova posição de raiz para janela\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_X: \"Margem esquerda - eixo X:\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_Y: \"Margem superior - eixo Y:\"\n  STR_MUSIC_VOLUME: \"Volume: banda sonora\"\n  STR_MUSIC_VOLUME_DESC: \"Alterar o volume da banda sonora.\"\n  STR_SFX_VOLUME: \"Volume: efeitos sonoros\"\n  STR_SFX_VOLUME_DESC: \"Alterar o volume dos efeitos sonoros.\"\n  STR_UI_VOLUME: \"Volume: interface\"\n  STR_UI_VOLUME_DESC: \"Alterar o volume dos efeitos sonoros produzidos através da interação com a interface de jogo.\"\n  STR_SCROLL_SPEED: \"Deslizamento\"\n  STR_SCROLL_SPEED_GEO_DESC: \"Esta opção altera a velocidade de deslizamento do globo no menu de Controle Global.\"\n  STR_SCROLL_SPEED_BATTLE_DESC: \"Alterar a velocidade de deslizamento do mapa.\"\n  STR_DOGFIGHT_SPEED: \"Velocidade de interceção\"\n  STR_DOGFIGHT_SPEED_DESC: \"Alterar a velocidade de interceção. Reduzir a velocidade pode ajudar a melhorar o desempenho do jogo em dispositivos de baixa gama.\"\n  STR_CLOCK_SPEED: \"Velocidade do relógio\"\n  STR_CLOCK_SPEED_DESC: \"Alterar a velocidade do relógio no menu de Controlo Global\"\n  STR_GLOBE_DETAILS: \"Detalhes do globo\"\n  STR_GLOBE_COUNTRIES: \"Países\"\n  STR_GLOBE_COUNTRIES_DESC: \"Mostrar os nomes das nações financiadoras no globo.\"\n  STR_GLOBE_RADARS: \"Radares\"\n  STR_GLOBE_RADARS_DESC: \"Mostrar alcance de radar no globo.\"\n  STR_GLOBE_FLIGHT_PATHS: \"Trajetórias de voo\"\n  STR_GLOBE_FLIGHT_PATHS_DESC: \"Mostrar trajetórias de voo de aeronaves em movimento no globo.\"\n  STR_CONTROLS_DESC: \"Clique com o botão esquerdo do rato para editar um atalho.{NEWLINE}Clique com o botão direito para apagar a configuração atual.\"\n  STR_BASE_GAME: \"Jogo base\"\n  STR_MODS_TOOLTIP: \"Versão {0} por {1}.{NEWLINE}{2}\"\n  STR_EDGE_SCROLL: \"Deslizar nas bordas\"\n  STR_EDGE_SCROLL_DESC: \"Manual: pressionar o botão esquerdo do rato junto à borda da tela para deslizar o mapa. Automático: mover o cursor sobre a borda da tela para deslizar o mapa.\"\n  STR_TRIGGER_SCROLL: \"MANUAL\"\n  STR_AUTO_SCROLL: \"AUTOMÁTICO\"\n  STR_DRAG_SCROLL: \"Deslizar por arrasto\"\n  STR_DRAG_SCROLL_DESC: \"Navegar pelo mapa ao pressionar e arrastar o botão do rato especificado.\"\n  STR_LEFT_MOUSE_BUTTON: \"Botão esquerdo\"\n  STR_MIDDLE_MOUSE_BUTTON: \"Botão do meio\"\n  STR_RIGHT_MOUSE_BUTTON: \"Botão direito\"\n  STR_FIRE_SPEED: \"Animações de tiro\"\n  STR_FIRE_SPEED_DESC: \"Alterar a velocidade de animação de projéteis.\"\n  STR_PLAYER_MOVEMENT_SPEED: \"Animações X-Com\"\n  STR_PLAYER_MOVEMENT_SPEED_DESC: \"Alterar a velocidade de movimento das unidades controladas pelo jogador.\"\n  STR_COMPUTER_MOVEMENT_SPEED: \"Animações IA\"\n  STR_COMPUTER_MOVEMENT_SPEED_DESC: \"Alterar a velocidade de movimento das unidades controladas pelo computador.\"\n  STR_PATH_PREVIEW: \"Pré-visualizar percurso\"\n  STR_PATH_ARROWS: \"Setas\"\n  STR_PATH_ARROWS_DESC: \"Visualizar percursos através de setas coloridas que representam as ações possiveis conforme as UTs restantes: verde - movimento e abrir fogo; amarelo - movimento; vermelho - ação impossível.\"\n  STR_PATH_TIME_UNIT_COST: \"Unidades de tempo\"\n  STR_PATH_TIME_UNIT_COST_DESC: \"Este modo de pré-visualização apresenta o número de unidades de tempo restantes por cada espaço percorrido com a unidade selecionada.\"\n  STR_USER_INTERFACE_OPTIONS: \"Opções de interface\"\n  STR_TOOLTIPS: \"Descrições\"\n  STR_TOOLTIPS_DESC: \"Apresentar descrições dos botões do menu tático ao mover o cursor sobre os mesmos.\"\n  STR_DEATH_NOTIFICATIONS: \"Confirmações de morte\"\n  STR_DEATH_NOTIFICATIONS_DESC: \"Exibir uma mensagem de cada vez que um soldado X-Com morre em combate.\"\n  STR_SHOW_FUNDS: \"Indicador de fundos\"\n  STR_SHOW_FUNDS_DESC: \"Apresentar um indicador com os fundos monetários atuais ao pé do relógio do menu de Controle Global.\"\n  STR_MISSION_GENERATOR: \"CRIAR MISSÃO\"\n  STR_MAP_OPTIONS: \"OPÇÕES DO MAPA\"\n  STR_ALIEN_OPTIONS: \"OPÇÕES DOS ALIENÍGENAS\"\n  STR_MAP_TERRAIN: \"Tipo de terreno\"\n  STR_MAP_DARKNESS: \"Escuridão\"\n  STR_MAP_DEPTH: \"Profundidade\"\n  STR_DIFFICULTY: \"Nível de dificuldade\"\n  STR_ALIEN_RACE: \"Espécie\"\n  STR_ALIEN_TECH_LEVEL: \"Nível de armamento\"\n  STR_RANDOMIZE: \"Aleatório\"\n  STR_OXCE_REQUIRED_QUESTION: \"Esta modificação requer OpenXcom {0} para funcionar correctamente. Activar esta modificação?\"\n  STR_RESTORE_DEFAULTS_QUESTION: \"Tem a certeza de que deseja restaurar os valores padrão?\"\n  STR_DISPLAY_OPTIONS_CONFIRM: \"Deseja manter as opções de visualização atuais?\"\n  STR_DISPLAY_OPTIONS_REVERT: \"A reverter em 0:{0}\"\n  STR_MISSING_CONTENT_PROMPT: \"AVISO:{SMALLLINE}Este jogo guardado depende de modificações que não estão disponíveis. Todos os conteúdos em falta serão removidos, o que pode impedir o jogo de carregar.{NEWLINE}Deseja continuar?\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT: \"Guardar granadas pré-programadas\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT_DESC: \"Guardar explosivos programados após o fim de uma missão.\"\n  STR_NEWSEEDONLOAD: \"Recalcular valores aleatórios ao carregar jogo\"\n  STR_NEWSEEDONLOAD_DESC: \"Recalcular os números aleatórios utilizados para determinar eventos ou ações sempre que o jogo é recarregado, produzindo resultados diferentes. Opção inválida no modo \\\"Homem de Ferro\\\".\"\n  STR_CHANGEVALUEBYMOUSEWHEEL: \"Alterar valores com a roda do rato\"\n  STR_CHANGEVALUEBYMOUSEWHEEL_DESC: \"Permitir o uso da roda do rato para aumentar ou diminuir valores conforme o número especificado.\"\n  STR_BATTLEHAIRBLEACH: \"Adicionar detalhes às animações de soldados\"\n  STR_BATTLEHAIRBLEACH_DESC: \"Esta opção atribuí as características físicas presentes no retrato individual de cada soldado (tom de pele, cor do cabelo, etc) às respetivas animações no modo de combate.\"\n  STR_DRAGSCROLLINVERT: \"Inverter deslizamento por arrasto\"\n  STR_DRAGSCROLLINVERT_DESC: \"Inverter a direção do deslizamento de ecrã por arrasto.\"\n  STR_BATTLESCAPE_SCALE: \"Escala de ecrã: combate\"\n  STR_BATTLESCAPE_SCALE_DESC: \"Alterar a escala de visualização de combate com base numa resolução fixa (esticar) ou num parâmetro de zoom fixo (expandir). \"\n  STR_GEOSCAPE_SCALE: \"Escala de ecrã: globo\"\n  STR_GEOSCAPESCALE_SCALE_DESC: \"Alterar a escala de visualização do menu de controle global com base numa resolução fixa (esticar) ou num parâmetro de zoom fixo (expandir). \"\n  STR_1_5X: \"1,5x Original\"\n  STR_2X: \"2x Original\"\n  STR_THIRD_DISPLAY: \"Tela 1/3\"\n  STR_HALF_DISPLAY: \"Tela 1/2\"\n  STR_FULL_DISPLAY: \"Tela cheia\"\n  STR_FPS_LIMIT: \"Limite de FPS\"\n  STR_FPS_LIMIT_DESC: \"Limitar o número de atualizações feitas ao ecrã de jogo por segundo (0 = sem limites). Se a opção de renderização por OpenGL estiver ativada, a aplicação utilizará o modo Vsync.\"\n  STR_FPS_INACTIVE_LIMIT: \"Limitar FPS em plano de fundo\"\n  STR_FPS_INACTIVE_LIMIT_DESC: \"Limitar o número de FPS se a aplicação estiver aberta em plano de fundo.\"\n  STR_NOALIENPANICMESSAGES: \"Eliminar mensagens de pânico para alienígenas\"\n  STR_NOALIENPANICMESSAGES_DESC: \"Não mostrar mensagens de confirmação de pânico relativas a unidades inimigas, a menos que estas estejam no campo de visão do jogador.\"\n  STR_ALIENBLEEDING: \"Ferimentos graves em alienígenas\"\n  STR_ALIENBLEEDING_DESC: \"Esta opção faz com que as unidades alienígenas sejam suscetíveis de sofrer ferimentos graves.\"\n  STR_FIELDPROMOTIONS: \"Promover apenas soldados em missão\"\n  STR_FIELDPROMOTIONS_DESC: \"Apenas os soldados presentes em missões de campo são elegíveis para receber promoções.\"\n  STR_MEETINGPOINT: \"Prever trajetória do OVNI\"\n  STR_MEETINGPOINT_DESC: \"Aeronaves voam até um ponto de encontro com o OVNI, baseadas na sua trajetória atual.\"\n  STR_IRONMAN: \"\\\"HOMEM DE FERRO\\\"\"\n  STR_IRONMAN_DESC: \"Bloquear a opção para guardar o jogo manualmente\"\n  STR_SAVE_AND_ABANDON_GAME: \"GUARDAR E ABANDONAR JOGO\"\n  STR_MOD_UNSUCCESSFUL: \"Erro ao carregar modificação\"\n  STR_NEW_SAVED_GAME_SLOT: \"<NOVO FICHEIRO>\"\n  STR_AUTO_SAVE_GEOSCAPE_SLOT: \"<AUTO - GLOBO>\"\n  STR_AUTO_SAVE_BATTLESCAPE_SLOT: \"<AUTO - COMBATE>\"\n  STR_QUICK_SAVE_SLOT: \"<GRAVAÇÃO RÁPIDA>\"\n  STR_DISPLAY_MODE_DESC: \"Alterar o modo de apresentação do ecrã de jogo.\"\n  STR_PREFERRED_MUSIC_FORMAT: \"Formato: banda sonora\"\n  STR_PREFERRED_MUSIC_FORMAT_DESC: \"Esta opção permite selecionar o formato da banda sonora quando várias opções estiverem disponíveis. NOTA: a versão MIDI pode sofrer problemas no sistema operativo Windows.\"\n  STR_PREFERRED_SFX_FORMAT: \"Formato: efeitos sonoros\"\n  STR_PREFERRED_SFX_FORMAT_DESC: \"Esta opção permite selecionar o formato dos efeitos sonoros quando várias opções estiverem disponíveis\"\n  STR_PREFERRED_VIDEO_FORMAT: \"Formato: vídeo\"\n  STR_PREFERRED_VIDEO_FORMAT_DESC: \"Esta opção permite selecionar o formato de vídeo quando várias opções estiverem disponíveis.\"\n  STR_PREFERRED_VIDEO_ANIMATION: \"Animação\"\n  STR_PREFERRED_VIDEO_SLIDESHOW: \"Diaporama\"\n  STR_PREFERRED_FORMAT_AUTO: \"Automático\"\n  STR_CURRENT_FORMAT: \"Atual: {0}\"\n  STR_SOUND_OPTIONS: \"Opções de som\"\n  STR_BACKGROUND_MUTE: \"Silenciar janela\"\n  STR_BACKGROUND_MUTE_DESC: \"Silenciar o volume da janela de jogo quando colocada em plano de fundo.\"\n  STR_FORCE_FIRE: \"Ignorar obstáculos na linha de fogo\"\n  STR_FORCE_FIRE_DESC: \"Permitir a opção para forçar um soldado a ignorar obstáculos na sua linha de fogo se o jogador mantiver a tecla CTRL pressionada.\"\n  STR_NO_AUDIO_HARDWARE_DETECTED: \"Não foram detetados dispositivos de áudio\"\n  STR_MOUSEWHEEL_SPEED: \"Velocidade da roda do rato\"\n  STR_MOUSEWHEEL_SPEED_DESC: \"Ajustar o número de linhas deslocadas em listas por cada movimento da roda do rato.\"\n  STR_DISABLED: \"Desativado\"\n  STR_MAXIMIZE_INFO_SCREENS: \"Maximizar menus informativos\"\n  STR_MAXIMIZE_INFO_SCREENS_DESC: \"O menu de equipamento e várias outras telas serão exibidas em modo de ecrã cheio, independentemente das configurações de resolução.\"\n  STR_DIARY: \"REGISTO\"\n  STR_KILLED: \"MORTO\"\n  STR_STUNNED: \"ATORDOADO\"\n  STR_PANICKED: \"EM PÂNICO\"\n  STR_MINDCONTROLLED: \"CONTROLADO\"\n  STR_REGION_UNKNOWN: \"Não revelado\"\n  STR_WEAPON_UNKNOWN: \"Improvisação\"\n  STR_UNKNOWN: \"Desconhecido\"\n  STR_VICTORY: \"Vitória\"\n  STR_DEFEAT: \"Derrota\"\n  STR_NO_RECORD: \"Sem registo\"\n  STR_HUMAN: \"Humano\"\n  STR_FRIENDLY: \"Amigável\"\n  STR_HOSTILE: \"Hostil\"\n  STR_NEUTRAL: \"Neutro\"\n  STR_RATING_UC: \"AVALIAÇÃO\"\n  STR_LOCATION: \"LOCALIZAÇÃO>{ALT}{0}\"\n  STR_DAYLIGHT_TYPE: \"TEMPO> {ALT}{0}\"\n  STR_RACE_TYPE: \"RAÇA> {ALT}{0}\"\n  STR_DAY: \"Dia\"\n  STR_NIGHT: \"Noite\"\n  STR_DAYS_WOUNDED: \"DIAS FERIDO> {ALT}{0}\"\n  STR_COMBAT: \"COMBATE\"\n  STR_PERFORMANCE: \"DESEMPENHO\"\n  STR_NEUTRALIZATIONS_BY_RACE: \"NEUTRALIZAÇÕES POR ESPÉCIE\"\n  STR_NEUTRALIZATIONS_BY_RANK: \"NEUTRALIZAÇÕES POR POSTO\"\n  STR_NEUTRALIZATIONS_BY_WEAPON: \"NEUTRALIZAÇÕES POR ARMA\"\n  STR_MISSIONS_BY_LOCATION: \"MISSÕES POR LOCAL\"\n  STR_MISSIONS_BY_TYPE: \"MISSÕES POR TIPO\"\n  STR_MISSIONS_BY_UFO: \"MISSÕES POR OVNI\"\n  STR_SCORE_VALUE: \"PONTUAÇÃO> {ALT}{0}\"\n  STR_WINS: \"VITÓRIAS> {ALT}{0}\"\n  STR_STUNS: \"ALVOS ATORDOADOS> {ALT}{0}\"\n  STR_PANICKS: \"PÂNICOS> {ALT}{0}\"\n  STR_MINDCONTROLS: \"ALVOS CONTROLADOS> {ALT}{0}\"\n  STR_AWARDS: \"DISTINÇÕES\"\n  STR_COMMENDATIONS_UC: \"LOUVOURES\"\n  STR_COMMENDATIONS: \"Louvores\"\n  STR_MEDALS: \"MEDALHAS\"\n  STR_LOST_IN_SERVICE: \"BAIXAS\"\n  STR_MEDAL_NAME: \"Nome da medalha\"\n  STR_MEDAL_AWARD_LEVEL: \"Nível de distinção\"\n  STR_MEDAL_DECOR_LEVEL: \"Nível de condecoração\"\n  STR_AWARD_0: \"Primeira distinção\"\n  STR_AWARD_1: \"Segunda distinção\"\n  STR_AWARD_2: \"Terceira distinção\"\n  STR_AWARD_3: \"Quarta distinção\"\n  STR_AWARD_4: \"Quinta distinção\"\n  STR_AWARD_5: \"Sexta distinção\"\n  STR_AWARD_6: \"Sétima distinção\"\n  STR_AWARD_7: \"Oitava distinção\"\n  STR_AWARD_8: \"Nona distinção\"\n  STR_AWARD_9: \"Décima distinção\"\n  STR_AWARD_DECOR_0: \"Nenhum\"\n  STR_AWARD_DECOR_1: \"Primeira medalha de bronze\"\n  STR_AWARD_DECOR_2: \"Segunda medalha de bronze\"\n  STR_AWARD_DECOR_3: \"Terceira medalha de bronze\"\n  STR_AWARD_DECOR_4: \"Primeira medalha de prata\"\n  STR_AWARD_DECOR_5: \"Segunda medalha de prata\"\n  STR_AWARD_DECOR_6: \"Terceira medalha de prata\"\n  STR_AWARD_DECOR_7: \"Primeira medalha de ouro\"\n  STR_AWARD_DECOR_8: \"Segunda medalha de ouro\"\n  STR_AWARD_DECOR_9: \"Terceira medalha de ouro\"\n  STR_KILLED_IN_ACTION_MALE: \"MORTO EM COMBATE\"\n  STR_KILLED_IN_ACTION_FEMALE: \"MORTA EM COMBATE\"\n  STR_MISSING_IN_ACTION_MALE: \"DESAPARECIDO EM COMBATE\"\n  STR_MISSING_IN_ACTION_FEMALE: \"DESAPARECIDA EM COMBATE\"\n  STR_AVERAGE_MONTHLY_RATING: \"Avaliação média mensal\"\n  STR_TOTAL_INCOME: \"Receita total\"\n  STR_TOTAL_EXPENDITURE: \"Despesa total\"\n  STR_MISSIONS_WON: \"Missões concluídas\"\n  STR_MISSIONS_LOST: \"Missões falhadas\"\n  STR_NIGHT_MISSIONS: \"Missões noturnas\"\n  STR_BEST_RATING: \"Melhor classificação em missão\"\n  STR_WORST_RATING: \"Pior classificação em missão\"\n  STR_ALIEN_KILLS: \"Alienígenas mortos\"\n  STR_ALIEN_CAPTURES: \"Alienígenas capturados\"\n  STR_FRIENDLY_KILLS: \"Incidentes com fogo amigável\"\n  STR_AVERAGE_ACCURACY: \"Média de precisão\"\n  STR_WEAPON_MOST_KILLS: \"Arma mais eficaz\"\n  STR_ALIEN_MOST_KILLS: \"Alienígena mais mortífero\"\n  STR_LONGEST_SERVICE: \"Mais meses em serviço\"\n  STR_TOTAL_DAYS_WOUNDED: \"Dias de baixa\"\n  STR_COUNTRIES_LOST: \"Países infiltrados\"\n  STR_TOTAL_TERROR_SITES: \"Ataques terroristas\"\n  STR_TOTAL_BASES: \"Bases construídas\"\n  STR_TOTAL_CRAFT: \"Veículos possuídos\"\n  STR_TOTAL_SCIENTISTS: \"Cientistas contratados\"\n  STR_TOTAL_ENGINEERS: \"Engenheiros contratados\"\n  STR_TOTAL_RESEARCH: \"Pesquisa concluída\"\n  STR_DIARY_ACCURACY: \"PRECISÃO> {ALT}{0}%\"\n  STR_STATISTICS: \"Estatísticas\"\n  STR_STATS: \"INFORMAÇÕES\"\n  STR_TIME_UNITS_ABBREVIATION: \"UTs\"\n  STR_STAMINA_ABBREVIATION: \"R\"\n  STR_HEALTH_ABBREVIATION: \"PV\"\n  STR_BRAVERY_ABBREVIATION: \"CRG\"\n  STR_REACTIONS_ABBREVIATION: \"REA\"\n  STR_FIRING_ACCURACY_ABBREVIATION: \"PRE\"\n  STR_THROWING_ACCURACY_ABBREVIATION: \"PA\"\n  STR_STRENGTH_ABBREVIATION: \"F\"\n  STR_MELEE_ACCURACY_ABBREVIATION: \"CC\"\n  STR_FOLDERS: \"PASTAS\"\n  STR_DATA_FOLDER: \"Pasta dos Dados (recursos originais)\"\n  STR_USER_FOLDER: \"Pasta do Utilizador (mods, openxcom.log)\"\n  STR_SAVE_FOLDER: \"Pasta dos Jogos (jogos guardados, capturas de ecrã)\"\n  STR_CONFIG_FOLDER: \"Pasta da Configuração (options.cfg)\"\n  STR_DATA_FOLDER_DESC_1: \"Esta pasta é onde OpenXcom procura os ficheiros do jogo original (UFO e/ou TFTD).\"\n  STR_DATA_FOLDER_DESC_2: \"Os recursos do OpenXcom estão na pasta 'common'. Os mods do OpenXcom estão na pasta 'standard'.\"\n  STR_USER_FOLDER_DESC: \"O ficheiro de registo ('openxcom.log') é guardado aqui. Todos os mods de utilizador também estão aqui (na pasta 'mods').\"\n  STR_SAVE_FOLDER_DESC: \"Os teus jogos são guardados aqui. As definições do gerador de batalhas ('battle.cfg') também são guardadas aqui.\"\n  STR_CONFIG_FOLDER_DESC: \"A tua configuração do OpenXcom ('options.cfg') é guardada aqui. Normalmente igual à Pasta do Utilizador.\"\n"
  },
  {
    "path": "bin/common/Language/ro.yml",
    "content": "ro:\n  STR_OPENXCOM: \"OpenXcom\"\n  STR_NEW_GAME: \"Joc Nou\"\n  STR_LOAD_SAVED_GAME: \"Încărcare Joc\"\n  STR_SELECT_DIFFICULTY_LEVEL: \"Alegere Nivel Dificultate\"\n  STR_1_BEGINNER: \"1> Începător\"\n  STR_2_EXPERIENCED: \"2> Experimentat\"\n  STR_3_VETERAN: \"3> Veteran\"\n  STR_4_GENIUS: \"4> Geniu\"\n  STR_5_SUPERHUMAN: \"5> Supraom\"\n  STR_TIME: \"Timp\"\n  STR_DATE: \"Dată\"\n  STR_SELECT_GAME_TO_LOAD: \"Alegere joc de încărcat\"\n  STR_SELECT_SAVE_POSITION: \"Alegere locație de salvat\"\n  STR_GAME_OPTIONS: \"OPȚIUNI JOC\"\n  STR_LOAD_GAME: \"ÎNCĂRCARE JOC\"\n  STR_SAVE_GAME: \"SALVARE JOC\"\n  STR_ABANDON_GAME: \"PĂRĂSIRE JOC\"\n  STR_ABANDON_GAME_QUESTION: \"PĂRĂSIȚI JOCUL?\"\n  STR_QUIT: \"Părăsire Joc\"\n  STR_SAVING_GAME: \"Salvare joc\"\n  STR_LOADING_GAME: \"Încărcare joc\"\n  STR_NO_SAVED_GAME_PRESENT: \"Nu există joc salvat\"\n  STR_LOAD_UNSUCCESSFUL: \"Încărcare eșuată\"\n  STR_SAVE_UNSUCCESSFUL: \"Salvare eșuată\"\n  STR_LOAD_SUCCESSFUL: \"Încărcare reușită\"\n  STR_SAVE_SUCCESSFUL: \"Salvare reușită\"\n  STR_DELETE: \"ȘTERGERE\"\n  STR_DELETE_UNSUCCESSFUL: \"Ștergere eșuată\"\n  STR_IS_IT_OK_TO_DELETE_THE_SAVED_GAME: \"Sigur se poate șterge salvarea?\"\n  STR_ORIGINAL_XCOM: \"X-Com Original\"\n  STR_LOADING: \"Încărcare...\"\n  STR_DETAILS: \"DETALII> {ALT}{0}\"\n  STR_NEW_BATTLE: \"Luptă Nouă\"\n  STR_OPTIONS: \"Opțiuni\"\n  STR_RIGHT_CLICK_TO_DELETE: \"Click dreapta pentru ștergere.\"\n  STR_RESTORE_DEFAULTS: \"Valori Inițiale\"\n  STR_CONTROLS: \"COMENZI\"\n  STR_GENERAL: \"General\"\n  STR_GEOSCAPE: \"Geosferă\"\n  STR_BATTLESCAPE: \"Câmp Luptă\"\n  STR_SCREENSHOT: \"Captură Ecran\"\n  STR_FPS_COUNTER: \"Contor FPS\"\n  STR_ROTATE_LEFT: \"Rotire Stânga\"\n  STR_ROTATE_RIGHT: \"Rotire Dreapta\"\n  STR_ROTATE_UP: \"Rotire Sus\"\n  STR_ROTATE_DOWN: \"Rotire Jos\"\n  STR_ZOOM_IN: \"Apropiere\"\n  STR_ZOOM_OUT: \"Depărtare\"\n  STR_TOGGLE_COUNTRY_DETAIL: \"Comutare Detalii Țări\"\n  STR_TOGGLE_RADAR_RANGES: \"Comutare Zone Radar\"\n  STR_SCROLL_LEFT: \"Glisare Stânga\"\n  STR_SCROLL_RIGHT: \"Glisare Dreapta\"\n  STR_SCROLL_UP: \"Glisare Sus\"\n  STR_SCROLL_DOWN: \"Glisare Jos\"\n  STR_UNIT_LEVEL_ABOVE: \"Mutare Soldat la Nivel Superior\"\n  STR_UNIT_LEVEL_BELOW: \"Mutare Soldat la Nivel Inferior\"\n  STR_VIEW_LEVEL_ABOVE: \"Afișare Nivel Superior\"\n  STR_VIEW_LEVEL_BELOW: \"Afișare Nivel Inferior\"\n  STR_CENTER_SELECTED_UNIT: \"Centrare Soldat Selectat\"\n  STR_PREVIOUS_UNIT: \"Selectare Soldat Precedent\"\n  STR_NEXT_UNIT: \"Selectare Soldat Următor\"\n  STR_DESELECT_UNIT: \"Deselectare Soldat\"\n  STR_USE_LEFT_HAND: \"Folosire Obiect din Mâna Stângă\"\n  STR_USE_RIGHT_HAND: \"Folosire Obiect din Mâna Dreaptă\"\n  STR_INVENTORY: \"Inventar\"\n  STR_MINIMAP: \"Mini-Hartă\"\n  STR_MULTI_LEVEL_VIEW: \"Vedere De Ansamblu\"\n  STR_END_TURN: \"Finalizare Rundă\"\n  STR_ABORT_MISSION: \"Abandonare Misiune\"\n  STR_UNIT_STATS: \"Abilități Unitate\"\n  STR_KNEEL: \"Îngenunchere\"\n  STR_RELOAD: \"Reîncărcare\"\n  STR_TOGGLE_PERSONAL_LIGHTING: \"Comutare Iluminare Personală\"\n  STR_DONT_RESERVE_TIME_UNITS: \"Fără rezervare UT\"\n  STR_RESERVE_TIME_UNITS_FOR_SNAP_SHOT: \"Rezervare UT pentru Foc Rapid\"\n  STR_RESERVE_TIME_UNITS_FOR_AIMED_SHOT: \"Rezervare UT pentru Foc Ochit\"\n  STR_RESERVE_TIME_UNITS_FOR_AUTO_SHOT: \"Rezervare UT pentru Foc Automat\"\n  STR_CENTER_ON_ENEMY_1: \"Centrare Inamicul 1\"\n  STR_CENTER_ON_ENEMY_2: \"Centrare Inamicul 2\"\n  STR_CENTER_ON_ENEMY_3: \"Centrare Inamicul 3\"\n  STR_CENTER_ON_ENEMY_4: \"Centrare Inamicul 4\"\n  STR_CENTER_ON_ENEMY_5: \"Centrare Inamicul 5\"\n  STR_CENTER_ON_ENEMY_6: \"Centrare Inamicul 6\"\n  STR_CENTER_ON_ENEMY_7: \"Centrare Inamicul 7\"\n  STR_CENTER_ON_ENEMY_8: \"Centrare Inamicul 8\"\n  STR_CENTER_ON_ENEMY_9: \"Centrare Inamicul 9\"\n  STR_CENTER_ON_ENEMY_10: \"Centrare Inamicul 10\"\n  STR_CREATE_INVENTORY_TEMPLATE: \"Creare șablon inventar\"\n  STR_APPLY_INVENTORY_TEMPLATE: \"Aplicare șablon inventar\"\n  STR_CLEAR_INVENTORY: \"Golire inventar\"\n  STR_AUTO_EQUIP: \"Auto-echipare\"\n  STR_QUICK_SAVE: \"Salvare Rapidă\"\n  STR_QUICK_LOAD: \"Încărcare Rapidă\"\n  STR_ADVANCED: \"AVANSAT\"\n  STR_AGGRESSIVERETALIATION: \"Represalii agresive\"\n  STR_AGGRESSIVERETALIATION_DESC: \"OZNurile vor încerca să îți detecteze bazele întotdeauna, indiferent de parametrii misiunii lor.\"\n  STR_STORAGELIMITSENFORCED: \"Limite depozite pentru articole recuperate\"\n  STR_STORAGELIMITSENFORCED_DESC: \"Impune limite în carantina extratereștrilor și depozite generale pentru extratereștri vii și artefactele recuperate din misiuni.\"\n  STR_CANSELLLIVEALIENS: \"Vânzare extratereștrii vii\"\n  STR_CANSELLLIVEALIENS_DESC: \"Permite vânzarea extratereștrilor vii, recomandat când se utilizează limite depozitare.\"\n  STR_ALLOWBUILDINGQUEUE: \"Ordine de construcție\"\n  STR_ALLOWBUILDINGQUEUE_DESC: \"Construcțiile noi pot fi plasate lângă cele neterminate.\"\n  STR_BATTLEAUTOEND: \"Încheiere automată a luptei\"\n  STR_BATTLEAUTOEND_DESC: \"Lupta se termină automat în momentul în care ultimul inamic este neutralizat.\"\n  STR_BATTLEINSTANTGRENADE: \"Grenade instant\"\n  STR_BATTLEINSTANTGRENADE_DESC: \"Grenadele amorsate pentru explozie în 0 runde vor exploda imediat ce sunt aruncate și nu la finalul rundei.\"\n  STR_BATTLEUFOEXTENDERACCURACY: \"Precizie tip UFO Extender\"\n  STR_BATTLEUFOEXTENDERACCURACY_DESC: \"Precizia de foc scade după o anumită distanță, în funcție de modul de tragere. Precizia calculată va fi afișată lângă cursor.\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE: \"Transferuri aeriene\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE_DESC: \"Aeronavele pot fi transferate în timpul zborului.\"\n  STR_CRAFTLAUNCHALWAYS: \"Forțare lansare aeronave\"\n  STR_CRAFTLAUNCHALWAYS_DESC: \"Aeronavele pot fi lansate chiar și când nu sunt pregătite, neluând în seamă nevoia de mentenanță.\"\n  STR_CUSTOMINITIALBASE: \"Bază inițială particularizată\"\n  STR_CUSTOMINITIALBASE_DESC: \"La începerea unui joc nou, construcțiile de start se vor plasa manual în loc să se folosească așezarea implicită.\"\n  STR_GLOBESEASONS: \"Iluminare realistică pe glob\"\n  STR_GLOBESEASONS_DESC: \"Activează proiecția realistică a luminii solare pe Geosferă conform înclinării axei Pământului.\"\n  STR_PLAYINTRO: \"Rulare introducere\"\n  STR_PLAYINTRO_DESC: \"Rulează filmul de introducere la pornire.\"\n  STR_SHOWMORESTATSININVENTORYVIEW: \"Statistici Inventar\"\n  STR_SHOWMORESTATSININVENTORYVIEW_DESC: \"Afișare informații suplimentare în inventarul soldatului selectat.\"\n  STR_SNEAKYAI: \"AI viclean\"\n  STR_SNEAKYAI_DESC: \"Unitățile AI evită pe cât posibil expunerea în fața jucătorului.\"\n  STR_STRAFE: \"Metode alternative de deplasare\"\n  STR_STRAFE_DESC: \"Activează pasul lateral, fuga, rotirea independentă a turelei tancului atunci când se ține apasată tasta CTRL.\"\n  STR_BATTLEEXPLOSIONHEIGHT: \"Înălțime explozii\"\n  STR_BATTLEEXPLOSIONHEIGHT_DESC: \"Modifică distanța pe înălțime la care pot ajunge exploziile.{NEWLINE}(Plată: 0, Sferică: 3)\"\n  STR_AUTOSAVE: \"Salvare automată\"\n  STR_AUTOSAVE_DESC: \"Jocul se salvează în mod automat la intervale specificate. Nu se aplică în modul Ironman.\"\n  STR_AUTOSAVE_FREQUENCY: \"Frecvență salvare automată\"\n  STR_AUTOSAVE_FREQUENCY_DESC: \"Numărul de runde după care jocul se va salva în mod automat.\"\n  STR_ALLOWPSIONICCAPTURE: \"Permitere captură psi\"\n  STR_ALLOWPSIONICCAPTURE_DESC: \"Controlul mental al tuturor extratereștrilor rămași finalizează automat misiunea și capturarea acestora ca fiind vii.\"\n  STR_ANYTIMEPSITRAINING: \"Antrenament psi în orice moment\"\n  STR_ANYTIMEPSITRAINING_DESC: \"Soldații pot fi trimiși (sau scoși de) la antrenament psionic în orice moment al lunii. De reținut, antrenamentul inițial durează între 30 și 60 de zile.\"\n  STR_SKIPNEXTTURNSCREEN: \"Închidere ecran \\\"Runda Următoare\\\"\"\n  STR_SKIPNEXTTURNSCREEN_DESC: \"În timpul luptei, ecranele ce anunță \\\"Runda Următoare\\\" se închid automat după o scurtă pauză.\"\n  STR_NOT_ENOUGH_SPACE: \"Spațiu Insuficient!\"\n  STR_WEAPONSELFDESTRUCTION: \"Autodistrugere arme extraterestre\"\n  STR_WEAPONSELFDESTRUCTION_DESC: \"Armele cărate de extratereștrii se autodistrug dacă posesorul este omorât, precum în XCOM 2012.\"\n  STR_RETAINCORPSES: \"Reținere extratereștri interogați\"\n  STR_RETAINCORPSES_DESC: \"După \\\"cercetarea\\\" extratereștrilor vii, cadavrele acestora vor fi adăugate în depozitele bazei, precum în XCOM 2012.\"\n  STR_SAVE_VOXEL_VIEW: \"Salvează Vedere la Persoana-Întâi\"\n  STR_RESERVE_TIME_UNITS_FOR_KNEEL: \"Rezervare UT pentru Îngenunchere\"\n  STR_EXPEND_ALL_TIME_UNITS: \"Consumă toate UT rămase\"\n  STR_PSISTRENGTHEVAL: \"Evaluare Rezistență Psionică\"\n  STR_PSISTRENGTHEVAL_DESC: \"Evaluează rezistența psionică a tuturor soldaților, după ce s-a realizat cercetarea subiectului corespunzător.\"\n  STR_DISABLEAUTOEQUIP: \"Dezactivare auto-echipare\"\n  STR_DISABLEAUTOEQUIP_DESC: \"Dezactivarea echipării automate a soldaților noi înaintea unei lupte.\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT: \"Permite îmbunătățire Rezistență Psionică\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT_DESC: \"Rezistența psionică a soldaților poate fi îmbunătățită prin experiență și antrenament.\"\n  STR_BATTLESMOOTHCAMERA: \"Urmărire fluentă a proiectilelor\"\n  STR_BATTLESMOOTHCAMERA_DESC: \"Pe câmpul de luptă camera rămâne centrată pe proiectilele aflate în zbor.\"\n  STR_BATTLECONFIRMFIREMODE: \"Confirmare ordin de tragere\"\n  STR_BATTLECONFIRMFIREMODE_DESC: \"Sunt necesare două click-uri pentru a confirma ordinul de tragere.\"\n  STR_SELECT_BASE_1: \"Selectare Baza 1\"\n  STR_SELECT_BASE_2: \"Selectare Baza 2\"\n  STR_SELECT_BASE_3: \"Selectare Baza 3\"\n  STR_SELECT_BASE_4: \"Selectare Baza 4\"\n  STR_SELECT_BASE_5: \"Selectare Baza 5\"\n  STR_SELECT_BASE_6: \"Selectare Baza 6\"\n  STR_SELECT_BASE_7: \"Selectare Baza 7\"\n  STR_SELECT_BASE_8: \"Selectare Baza 8\"\n  STR_VIDEO: \"VIDEO\"\n  STR_AUDIO: \"AUDIO\"\n  STR_BATTLESCAPE_UC: \"CÂMP LUPTĂ\"\n  STR_MODS_UC: \"MODIFICĂRI\"\n  STR_MODS: \"Modificări\"\n  STR_DISPLAY_RESOLUTION: \"Rezoluție Afișare\"\n  STR_DISPLAY_RESOLUTION_DESC: \"Modifică rezoluția afișajului, cea jocului adaptându-se la aceasta. Săgețile comută între rezolutiile suportate. Click pentru introducerea unei rezoluții personalizate.\"\n  STR_ORIGINAL: \"Original\"\n  STR_DISPLAY_MODE: \"Mod Afișare\"\n  STR_WINDOWED: \"Fereastră\"\n  STR_FULLSCREEN: \"Ecran Complet\"\n  STR_BORDERLESS: \"Ascundere Rame\"\n  STR_DISPLAY_LANGUAGE: \"Limba Folosită\"\n  STR_DISPLAY_LANGUAGE_DESC: \"Modifică limba în care este scris textul jocului.\"\n  STR_DISPLAY_FILTER: \"Filtru Afișaj\"\n  STR_DISPLAY_FILTER_DESC: \"Modifică filtrul aplicat afișajului jocului.{NEWLINE}*necesită accelerare hardware OpenGL.\"\n  STR_DISPLAY_OPTIONS: \"Opțiuni Afișare\"\n  STR_LETTERBOXED: \"Încadrare\"\n  STR_LETTERBOXED_DESC: \"Afișează benzi negre orizontale în partea superioară și inferioară a afișajului pentru a menține aspectul original.\"\n  STR_RESIZABLE: \"Redimensionare\"\n  STR_LOCK_MOUSE: \"Blocare Mouse\"\n  STR_LOCK_MOUSE_DESC: \"Împiedică mouse-ul să părăsească fereastra jocului. Ctrl+G pentru a comuta în orice moment.\"\n  STR_FIXED_WINDOW_POSITION: \"Poziție Fixă a Ferestrei\"\n  STR_FIXED_WINDOW_POSITION_DESC: \"Stabilirea poziției fixe a Ferestrei.\"\n  STR_DISPLAY_SET_WINDOW_POSITION: \"Stabilirea noii Origini a Ferestrei\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_X: \"Noul X latura stângă:\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_Y: \"Noul Y latura superioară:\"\n  STR_MUSIC_VOLUME: \"Volum Muzică\"\n  STR_MUSIC_VOLUME_DESC: \"Modifică volumul muzicii din fundal.\"\n  STR_SFX_VOLUME: \"Volum Sunete\"\n  STR_SFX_VOLUME_DESC: \"Modifică volumul efectelor sonore.\"\n  STR_UI_VOLUME: \"Volum Interfață\"\n  STR_UI_VOLUME_DESC: \"Modifică volumul semnalelor sonore ale interfeței.\"\n  STR_SCROLL_SPEED: \"Viteză Glisare\"\n  STR_SCROLL_SPEED_GEO_DESC: \"Modifică viteza de glisare a globului.\"\n  STR_SCROLL_SPEED_BATTLE_DESC: \"Modifică viteza de glisare pe hartă.\"\n  STR_DOGFIGHT_SPEED: \"Viteză Lupte Aeriene\"\n  STR_DOGFIGHT_SPEED_DESC: \"Modifică viteza luptelor aeriene dintre nave și OZNuri. Viteze mai mici pot îmbunătăți performanța pe dispozitive mai slabe.\"\n  STR_CLOCK_SPEED: \"Viteză Ceas\"\n  STR_CLOCK_SPEED_DESC: \"Modifică viteza ceasului în modul Geosferă. Viteze mai mici pot îmbunătăți performanța pe dispozitive mai slabe.\"\n  STR_GLOBE_DETAILS: \"Detalii Glob\"\n  STR_GLOBE_COUNTRIES: \"Țări\"\n  STR_GLOBE_COUNTRIES_DESC: \"Afișează tările finanțatoare pe glob.\"\n  STR_GLOBE_RADARS: \"Radare\"\n  STR_GLOBE_RADARS_DESC: \"Afișează zonele radar pe glob.\"\n  STR_GLOBE_FLIGHT_PATHS: \"Rute de Zbor\"\n  STR_GLOBE_FLIGHT_PATHS_DESC: \"Afișează rutele de zbor pe glob.\"\n  STR_CONTROLS_DESC: \"Click stânga pe o scurtătură și apăsați o tastă pentru a o schimba.{NEWLINE}Click dreapta pe o scurtătură pentru a o dezactiva.\"\n  STR_BASE_GAME: \"Jocul de bază\"\n  STR_MODS_TOOLTIP: \"Versiunea {0} de către {1}.{NEWLINE}{2}\"\n  STR_EDGE_SCROLL: \"Glisare la Margine\"\n  STR_EDGE_SCROLL_DESC: \"Declanșată: Glisează harta când butonul stâng este ținut apăsat la marginea ecranului.{NEWLINE}Automată: Când butonul stâng este ținut liber la marginea ecranului.\"\n  STR_TRIGGER_SCROLL: \"Declanșată\"\n  STR_AUTO_SCROLL: \"Automată\"\n  STR_DRAG_SCROLL: \"Glisare Manuală\"\n  STR_DRAG_SCROLL_DESC: \"Glisează harta când butonul de mouse specificat este ținut apăsat și mișcat.\"\n  STR_LEFT_MOUSE_BUTTON: \"Buton Stânga\"\n  STR_MIDDLE_MOUSE_BUTTON: \"Buton Mijloc\"\n  STR_RIGHT_MOUSE_BUTTON: \"Buton Dreapta\"\n  STR_FIRE_SPEED: \"Viteză Proiectile\"\n  STR_FIRE_SPEED_DESC: \"Modifică viteza proiectilelor armelor.\"\n  STR_PLAYER_MOVEMENT_SPEED: \"Viteză Mișcare Jucător\"\n  STR_PLAYER_MOVEMENT_SPEED_DESC: \"Modifică viteza de deplasare a unităților controlate de jucător.\"\n  STR_COMPUTER_MOVEMENT_SPEED: \"Viteză Mișcare AI\"\n  STR_COMPUTER_MOVEMENT_SPEED_DESC: \"Modifică viteza de deplasare a unităților controlate de computer.\"\n  STR_PATH_PREVIEW: \"Previzualizare Rută\"\n  STR_PATH_ARROWS: \"Săgeți\"\n  STR_PATH_ARROWS_DESC: \"La apăsare afișează ruta urmată de unitate pentru a ajunge la destinație. Culoarea indică acțiunile disponibile: Verde - se poate mișca și trage; Galben - se poate mișca; Roșu - nu se poate mișca.\"\n  STR_PATH_TIME_UNIT_COST: \"Unități Timp\"\n  STR_PATH_TIME_UNIT_COST_DESC: \"Afișează UT ce vor rămâne de folosit după ajungerea la destinație.\"\n  STR_USER_INTERFACE_OPTIONS: \"Opțiuni Interfață\"\n  STR_TOOLTIPS: \"Etichete\"\n  STR_TOOLTIPS_DESC: \"Afișează etichetele pentru butoanele de pe Câmpul de Luptă.\"\n  STR_DEATH_NOTIFICATIONS: \"Notificări decese\"\n  STR_DEATH_NOTIFICATIONS_DESC: \"Afișează o notificare detaliind cine a decedat oricând un soldat propriu moare.\"\n  STR_SHOW_FUNDS: \"Afișare Fonduri\"\n  STR_SHOW_FUNDS_DESC: \"Afișează fondurile curente lângă ceasul din Geosferă.\"\n  STR_MISSION_GENERATOR: \"GENERATOR MISIUNE\"\n  STR_MAP_OPTIONS: \"OPȚIUNI HARTĂ\"\n  STR_ALIEN_OPTIONS: \"OPȚIUNI EXTRATEREȘTRI\"\n  STR_MAP_TERRAIN: \"Teren\"\n  STR_MAP_DARKNESS: \"Întuneric\"\n  STR_MAP_DEPTH: \"Adâncime\"\n  STR_DIFFICULTY: \"Dificultate\"\n  STR_ALIEN_RACE: \"Rasă\"\n  STR_ALIEN_TECH_LEVEL: \"Nivel Tehnologic\"\n  STR_RANDOMIZE: \"Aleator\"\n  STR_OXCE_REQUIRED_QUESTION: \"Această modificare necesită OpenXcom {0} pentru a funcționa corect. Activăm modificarea?\"\n  STR_RESTORE_DEFAULTS_QUESTION: \"Sigur se restaurează opțiunile implicite?\"\n  STR_DISPLAY_OPTIONS_CONFIRM: \"Se păstrează opțiunile de afișare curente?\"\n  STR_DISPLAY_OPTIONS_REVERT: \"Revenire în 0:{0}\"\n  STR_MISSING_CONTENT_PROMPT: \"ATENȚIE:{SMALLLINE}Această salvare folosește modificări care nu sunt disponibile. Conținutul lipsă va fi înlăturat, iar încărcarea poate eșua.{NEWLINE}Continuați?\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT: \"Salvare grenade amorsate\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT_DESC: \"Salvează starea grenadelor amorsate în inventarul dinaintea luptei în schema de echipare a soldatului.\"\n  STR_NEWSEEDONLOAD: \"Împiedicare exploatare salvări\"\n  STR_NEWSEEDONLOAD_DESC: \"Încărcarea unui joc va reseta rezultatele, prin urmare realizarea aceleiași mutări poate avea alte consecințe. Nu se aplică în modul Ironman.\"\n  STR_CHANGEVALUEBYMOUSEWHEEL: \"Modificare valori cu rotița mouse-ului\"\n  STR_CHANGEVALUEBYMOUSEWHEEL_DESC: \"Permite folosirea rotiței mouse-ului pentru a crește/scădea cantitățile.\"\n  STR_BATTLEHAIRBLEACH: \"Îmbunătățire înfățișare soldați\"\n  STR_BATTLEHAIRBLEACH_DESC: \"Modifică înfățișarea soldaților de pe Câmpul de Luptă pentru a fi asemenea celei din ecranul de inventar.\"\n  STR_DRAGSCROLLINVERT: \"Direcție glisare inversată\"\n  STR_DRAGSCROLLINVERT_DESC: \"Când este activată, glisarea se face în direcția opusă mișcării mouse-ului.\"\n  STR_BATTLESCAPE_SCALE: \"Scalare Câmp Luptă\"\n  STR_BATTLESCAPE_SCALE_DESC: \"Mod de scalare afisaj Câmp de Luptă, bazat pe o rezoluție fixă (întins pentru a se potrivi), sau pe un nivel de zoom fix (extins pentru a umple).\"\n  STR_GEOSCAPE_SCALE: \"Scalare Geosferă\"\n  STR_GEOSCAPESCALE_SCALE_DESC: \"Mod de scalare afisaj Geosferă, bazat pe o rezoluție fixă (întins pentru a se potrivi), sau pe un nivel de zoom fix (extins pentru a umple).\"\n  STR_1_5X: \"1.5x Original\"\n  STR_2X: \"2x Original\"\n  STR_THIRD_DISPLAY: \"1/3 Afișaj\"\n  STR_HALF_DISPLAY: \"1/2 Afișaj\"\n  STR_FULL_DISPLAY: \"Complet\"\n  STR_FPS_LIMIT: \"Limitare FPS\"\n  STR_FPS_LIMIT_DESC: \"Limitează numărul de actualizări pe secundă ale ecranului, cu 0 pentru nelimitat. Dacă este activată randarea OpenGL jocul va utiliza Vsync.\"\n  STR_FPS_INACTIVE_LIMIT: \"Limitare FPS fundal\"\n  STR_FPS_INACTIVE_LIMIT_DESC: \"Limitează numărul de actualizări pe secundă ale ecranului dacă fereastra OpenXcom se află în fundal.\"\n  STR_NOALIENPANICMESSAGES: \"Înlăturare mesaje panică extratereștrii\"\n  STR_NOALIENPANICMESSAGES_DESC: \"Nu afișează mesajele de panică pentru extratereștrii decât dacă aceștia sunt văzuți de către jucător.\"\n  STR_ALIENBLEEDING: \"Sângerare extratereștrii\"\n  STR_ALIENBLEEDING_DESC: \"Permite cauzarea de răni grave majorității extratereștrilor.\"\n  STR_FIELDPROMOTIONS: \"Promovări pe teren\"\n  STR_FIELDPROMOTIONS_DESC: \"Numai soldații care au luat parte la misiune sunt eligibili pentru a fi promovați.\"\n  STR_MEETINGPOINT: \"Estimare traiectorie OZN\"\n  STR_MEETINGPOINT_DESC: \"Navele vor zbura către un punct de întâlnire cu OZNul bazându-se pe traiectoria curentă a acestuia.\"\n  STR_IRONMAN: \"IRONMAN\"\n  STR_IRONMAN_DESC: \"Nu este posibilă salvarea manuală\"\n  STR_SAVE_AND_ABANDON_GAME: \"SALVARE ȘI PĂRĂSIRE JOC\"\n  STR_MOD_UNSUCCESSFUL: \"Încărcarea modificării a eșuat\"\n  STR_NEW_SAVED_GAME_SLOT: \"<SALVARE NOUĂ>\"\n  STR_AUTO_SAVE_GEOSCAPE_SLOT: \"<AUTO GEOSFERĂ>\"\n  STR_AUTO_SAVE_BATTLESCAPE_SLOT: \"<AUTO CÂMP LUPTĂ>\"\n  STR_QUICK_SAVE_SLOT: \"<SALVARE RAPIDĂ>\"\n  STR_DISPLAY_MODE_DESC: \"Schimbă modul în care este afișat jocul pe ecran.\"\n  STR_PREFERRED_MUSIC_FORMAT: \"Format Muzică\"\n  STR_PREFERRED_MUSIC_FORMAT_DESC: \"Selectează formatul preferat pentru muzică, utilizat atunci când sunt mai multe disponibile.{NEWLINE}NOTĂ: Redarea MIDI este problematică în Windows.\"\n  STR_PREFERRED_SFX_FORMAT: \"Format Sunete\"\n  STR_PREFERRED_SFX_FORMAT_DESC: \"Selectează formatul preferat pentru efectele sonore, utilizat atunci când sunt mai multe disponibile.\"\n  STR_PREFERRED_VIDEO_FORMAT: \"Format Video\"\n  STR_PREFERRED_VIDEO_FORMAT_DESC: \"Selectează formatul preferat pentru video, utilizat atunci când sunt mai multe disponibile.\"\n  STR_PREFERRED_VIDEO_ANIMATION: \"Animat\"\n  STR_PREFERRED_VIDEO_SLIDESHOW: \"Succesiune imagini\"\n  STR_PREFERRED_FORMAT_AUTO: \"Automat\"\n  STR_CURRENT_FORMAT: \"Activ: {0}\"\n  STR_SOUND_OPTIONS: \"Opțiuni Sunet\"\n  STR_BACKGROUND_MUTE: \"Sunet Fundal Dezactivat\"\n  STR_BACKGROUND_MUTE_DESC: \"Dezactivează sunetul când fereastra jocului nu este activă.\"\n  STR_FORCE_FIRE: \"Suprimare Linie de Tragere\"\n  STR_FORCE_FIRE_DESC: \"Permite soldatului să tragă forțat atunci când se ține apăsată tasta CTRL, indiferent de regulile ce se aplică liniei de tragere.\"\n  STR_NO_AUDIO_HARDWARE_DETECTED: \"Hardware audio nedetectat\"\n  STR_MOUSEWHEEL_SPEED: \"Viteză derulare rotiță mouse\"\n  STR_MOUSEWHEEL_SPEED_DESC: \"Modifică numărul de linii derulate în liste cu fiecare mișcare a rotiței mouse-ului.\"\n  STR_DISABLED: \"Dezactivată\"\n  STR_MAXIMIZE_INFO_SCREENS: \"Maximizare ecrane informative\"\n  STR_MAXIMIZE_INFO_SCREENS_DESC: \"Inventarul și alte ecrane informative vor fi afișate pe tot ecranul, indiferent de setările de scalare.\"\n  STR_DIARY: \"JURNAL\"\n  STR_KILLED: \"UCIS\"\n  STR_STUNNED: \"PARALIZAT\"\n  STR_PANICKED: \"PANICAT\"\n  STR_MINDCONTROLLED: \"CONTROLAT\"\n  STR_REGION_UNKNOWN: \"Nedezvăluită\"\n  STR_WEAPON_UNKNOWN: \"Improvizație\"\n  STR_UNKNOWN: \"Necunoscut\"\n  STR_VICTORY: \"Victorie\"\n  STR_DEFEAT: \"Înfrângere\"\n  STR_NO_RECORD: \"Neînregistrat\"\n  STR_HUMAN: \"Uman\"\n  STR_FRIENDLY: \"Amical\"\n  STR_HOSTILE: \"Ostil\"\n  STR_NEUTRAL: \"Neutru\"\n  STR_RATING_UC: \"EVALUARE\"\n  STR_LOCATION: \"LOCAȚIA> {ALT}{0}\"\n  STR_DAYLIGHT_TYPE: \"MOMENTUL> {ALT}{0}\"\n  STR_RACE_TYPE: \"SPECIA> {ALT}{0}\"\n  STR_DAY: \"Ziua\"\n  STR_NIGHT: \"Noaptea\"\n  STR_DAYS_WOUNDED: \"ZILE SPITAL> {ALT}{0}\"\n  STR_COMBAT: \"LUPTĂ\"\n  STR_PERFORMANCE: \"RANDAMENT\"\n  STR_NEUTRALIZATIONS_BY_RACE: \"NEUTRALIZĂRI PER SPECIE\"\n  STR_NEUTRALIZATIONS_BY_RANK: \"NEUTRALIZĂRI PER RANG\"\n  STR_NEUTRALIZATIONS_BY_WEAPON: \"NEUTRALIZĂRI PER ARMĂ\"\n  STR_MISSIONS_BY_LOCATION: \"MISIUNI PER LOCAȚIE\"\n  STR_MISSIONS_BY_TYPE: \"MISIUNI PER TIP\"\n  STR_MISSIONS_BY_UFO: \"MISIUNI PER OZN\"\n  STR_SCORE_VALUE: \"PUNCTAJ> {ALT}{0}\"\n  STR_WINS: \"VICTORII> {ALT}{0}\"\n  STR_STUNS: \"PARALIZĂRI> {ALT}{0}\"\n  STR_PANICKS: \"PANICĂRI> {ALT}{0}\"\n  STR_MINDCONTROLS: \"CONTOLĂRI> {ALT}{0}\"\n  STR_AWARDS: \"DISTINCȚII\"\n  STR_COMMENDATIONS_UC: \"DISTINCȚII\"\n  STR_COMMENDATIONS: \"Distincții\"\n  STR_MEDALS: \"EMBLEME\"\n  STR_LOST_IN_SERVICE: \"PIERDUT ÎN SERVICIU\"\n  STR_MEDAL_NAME: \"Emblema\"\n  STR_MEDAL_AWARD_LEVEL: \"Nivelul Emblemei\"\n  STR_MEDAL_DECOR_LEVEL: \"Nivelul Distincției\"\n  STR_AWARD_0: \"Clasa întâi\"\n  STR_AWARD_1: \"Clasa doi\"\n  STR_AWARD_2: \"Clasa trei\"\n  STR_AWARD_3: \"Clasa patru\"\n  STR_AWARD_4: \"Clasa cinci\"\n  STR_AWARD_5: \"Clasa șase\"\n  STR_AWARD_6: \"Clasa șapte\"\n  STR_AWARD_7: \"Clasa opt\"\n  STR_AWARD_8: \"Clasa nouă\"\n  STR_AWARD_9: \"Clasa zece\"\n  STR_AWARD_DECOR_0: \"Niciuna\"\n  STR_AWARD_DECOR_1: \"Insignă bronz cl.1\"\n  STR_AWARD_DECOR_2: \"Insignă bronz cl.2\"\n  STR_AWARD_DECOR_3: \"Insignă bronz cl.3\"\n  STR_AWARD_DECOR_4: \"Insignă argint cl.1\"\n  STR_AWARD_DECOR_5: \"Insignă argint cl.2\"\n  STR_AWARD_DECOR_6: \"Insignă argint cl.3\"\n  STR_AWARD_DECOR_7: \"Insignă aur cl.1\"\n  STR_AWARD_DECOR_8: \"Insignă aur cl.2\"\n  STR_AWARD_DECOR_9: \"Insignă aur cl.3\"\n  STR_KILLED_IN_ACTION_MALE: \"UCIS ÎN MISIUNE\"\n  STR_KILLED_IN_ACTION_FEMALE: \"UCISĂ ÎN MISIUNE\"\n  STR_MISSING_IN_ACTION_MALE: \"DISPĂRUT ÎN MISIUNE\"\n  STR_MISSING_IN_ACTION_FEMALE: \"DISPĂRUTĂ ÎN MISIUNE\"\n  STR_AVERAGE_MONTHLY_RATING: \"Punctaj lunar mediu\"\n  STR_TOTAL_INCOME: \"Venituri totale\"\n  STR_TOTAL_EXPENDITURE: \"Cheltuieli totale\"\n  STR_MISSIONS_WON: \"Misiuni îndeplinite\"\n  STR_MISSIONS_LOST: \"Misiuni eșuate\"\n  STR_NIGHT_MISSIONS: \"Misiuni nocturne\"\n  STR_BEST_RATING: \"Cel mai bun punctaj\"\n  STR_WORST_RATING: \"Cel mai slab punctaj\"\n  STR_ALIEN_KILLS: \"Extratereștri uciși\"\n  STR_ALIEN_CAPTURES: \"Extratereștri capturați\"\n  STR_FRIENDLY_KILLS: \"Incidente colaterale\"\n  STR_AVERAGE_ACCURACY: \"Precizie medie\"\n  STR_WEAPON_MOST_KILLS: \"Cea mai eficientă armă\"\n  STR_ALIEN_MOST_KILLS: \"Cel mai mortal E.T.\"\n  STR_LONGEST_SERVICE: \"Cea mai lungă perioadă în serviciu\"\n  STR_TOTAL_DAYS_WOUNDED: \"Zile de spitalizare\"\n  STR_COUNTRIES_LOST: \"Țări infiltrate\"\n  STR_TOTAL_TERROR_SITES: \"Atacuri teroriste\"\n  STR_TOTAL_BASES: \"Baze construite\"\n  STR_TOTAL_CRAFT: \"Nave deținute\"\n  STR_TOTAL_SCIENTISTS: \"Cercetători angajați\"\n  STR_TOTAL_ENGINEERS: \"Ingineri angajați\"\n  STR_TOTAL_RESEARCH: \"Cercetări completate\"\n  STR_DIARY_ACCURACY: \"PRECIZIE> {ALT}{0}%\"\n  STR_STATISTICS: \"Statistici\"\n  STR_STATS: \"STAT.\"\n  STR_TIME_UNITS_ABBREVIATION: \"UT\"\n  STR_STAMINA_ABBREVIATION: \"ENR\"\n  STR_HEALTH_ABBREVIATION: \"SĂN\"\n  STR_BRAVERY_ABBREVIATION: \"VIT\"\n  STR_REACTIONS_ABBREVIATION: \"REA\"\n  STR_FIRING_ACCURACY_ABBREVIATION: \"PRE\"\n  STR_THROWING_ACCURACY_ABBREVIATION: \"ARU\"\n  STR_STRENGTH_ABBREVIATION: \"FRȚ\"\n  STR_MELEE_ACCURACY_ABBREVIATION: \"MEL\"\n  STR_FOLDERS: \"DIRECTOARE\"\n  STR_DATA_FOLDER: \"Director Date (resursele originale)\"\n  STR_USER_FOLDER: \"Director Utilizator (modificări, openxcom.log)\"\n  STR_SAVE_FOLDER: \"Director Salvări (jocuri salvate, capturi de ecran)\"\n  STR_CONFIG_FOLDER: \"Director Configurări (options.cfg)\"\n  STR_DATA_FOLDER_DESC_1: \"Aici va căuta OpenXcom resursele originale ale jocului (UFO și/sau TFTD)\"\n  STR_DATA_FOLDER_DESC_2: \"Resursele interne OpenXcom sunt situate în directorul 'common'. Modificările incorporate în OpenXcom sunt situate în directorul 'standard'.\"\n  STR_USER_FOLDER_DESC: \"Fișierul jurnal ('openxcom.log') este localizat aici. Toate modificările personalizate sunt localizate tot aici (în sub-directorul 'mods').\"\n  STR_SAVE_FOLDER_DESC: \"Jocurile salvate sunt localizate aici. De asemenea, setările generatorului de misiuni ('battle.cfg') se poate găsi aici.\"\n  STR_CONFIG_FOLDER_DESC: \"Aici sunt stocate setările OpenXcom ('options.cfg'). În mod uzual este identic cu Directorul Utilizator.\"\n"
  },
  {
    "path": "bin/common/Language/ru.yml",
    "content": "ru:\n  STR_OPENXCOM: \"OpenXcom\"\n  STR_NEW_GAME: \"Новая игра\"\n  STR_LOAD_SAVED_GAME: \"Загрузить игру\"\n  STR_SELECT_DIFFICULTY_LEVEL: \"Выберите уровень сложности\"\n  STR_1_BEGINNER: \"1> Новобранец\"\n  STR_2_EXPERIENCED: \"2> Опытный\"\n  STR_3_VETERAN: \"3> Ветеран\"\n  STR_4_GENIUS: \"4> Гений\"\n  STR_5_SUPERHUMAN: \"5> Сверхчеловек\"\n  STR_TIME: \"Время\"\n  STR_DATE: \"Дата\"\n  STR_SELECT_GAME_TO_LOAD: \"Выберите сохранение для загрузки\"\n  STR_SELECT_SAVE_POSITION: \"Выберите слот для сохранения\"\n  STR_GAME_OPTIONS: \"НАСТРОЙКИ ИГРЫ\"\n  STR_LOAD_GAME: \"ЗАГРУЗИТЬ ИГРУ\"\n  STR_SAVE_GAME: \"СОХРАНИТЬ ИГРУ\"\n  STR_ABANDON_GAME: \"ПОКИНУТЬ ИГРУ\"\n  STR_ABANDON_GAME_QUESTION: \"ВЫЙТИ ИЗ ИГРЫ?\"\n  STR_QUIT: \"Выход\"\n  STR_SAVING_GAME: \"Сохранение игры\"\n  STR_LOADING_GAME: \"Загрузка игры\"\n  STR_NO_SAVED_GAME_PRESENT: \"Нет сохраненных игр\"\n  STR_LOAD_UNSUCCESSFUL: \"Ошибка загрузки\"\n  STR_SAVE_UNSUCCESSFUL: \"Сохранить не удалось\"\n  STR_LOAD_SUCCESSFUL: \"Загрузка успешно завершена\"\n  STR_SAVE_SUCCESSFUL: \"Сохранение выполнено успешно\"\n  STR_DELETE: \"УДАЛИТЬ\"\n  STR_DELETE_UNSUCCESSFUL: \"Удалить не удалось\"\n  STR_IS_IT_OK_TO_DELETE_THE_SAVED_GAME: \"Вы уверены, что хотите удалить сохраненную игру?\"\n  STR_ORIGINAL_XCOM: \"Старый X-Com\"\n  STR_LOADING: \"Загрузка...\"\n  STR_DETAILS: \"ПОДРОБНО> {ALT}{0}\"\n  STR_NEW_BATTLE: \"Новая битва\"\n  STR_OPTIONS: \"Настройки\"\n  STR_RIGHT_CLICK_TO_DELETE: \"Щелкните правой кнопкой мыши, чтобы удалить.\"\n  STR_RESTORE_DEFAULTS: \"Сбросить настройки\"\n  STR_CONTROLS: \"УПРАВЛЕНИЕ\"\n  STR_GENERAL: \"Общие\"\n  STR_GEOSCAPE: \"Глобальный вид\"\n  STR_BATTLESCAPE: \"Поле боя\"\n  STR_SCREENSHOT: \"Снимок экрана\"\n  STR_FPS_COUNTER: \"Счетчик кадров в секунду\"\n  STR_ROTATE_LEFT: \"Повернуть влево\"\n  STR_ROTATE_RIGHT: \"Повернуть вправо\"\n  STR_ROTATE_UP: \"Повернуть вверх\"\n  STR_ROTATE_DOWN: \"Повернуть вниз\"\n  STR_ZOOM_IN: \"Приблизить\"\n  STR_ZOOM_OUT: \"Отдалить\"\n  STR_TOGGLE_COUNTRY_DETAIL: \"Вкл./выкл. границы стран\"\n  STR_TOGGLE_RADAR_RANGES: \"Вкл./выкл. зоны радаров\"\n  STR_SCROLL_LEFT: \"Скроллинг влево\"\n  STR_SCROLL_RIGHT: \"Скроллинг вправо\"\n  STR_SCROLL_UP: \"Скроллинг вверх\"\n  STR_SCROLL_DOWN: \"Скроллинг вниз\"\n  STR_UNIT_LEVEL_ABOVE: \"Подняться выше\"\n  STR_UNIT_LEVEL_BELOW: \"Спуститься ниже\"\n  STR_VIEW_LEVEL_ABOVE: \"Показать уровень выше\"\n  STR_VIEW_LEVEL_BELOW: \"Показать уровень ниже\"\n  STR_CENTER_SELECTED_UNIT: \"Центр на выбранном бойце\"\n  STR_PREVIOUS_UNIT: \"Предыдущий боец\"\n  STR_NEXT_UNIT: \"Следующий боец\"\n  STR_DESELECT_UNIT: \"След. боец (больше не выделять)\"\n  STR_USE_LEFT_HAND: \"В левой руке\"\n  STR_USE_RIGHT_HAND: \"В правой руке\"\n  STR_INVENTORY: \"Инвентарь\"\n  STR_MINIMAP: \"Мини-карта\"\n  STR_MULTI_LEVEL_VIEW: \"Показ всех уровней\"\n  STR_END_TURN: \"Конец хода\"\n  STR_ABORT_MISSION: \"Покинуть поле боя\"\n  STR_UNIT_STATS: \"Экран характеристик\"\n  STR_KNEEL: \"Встать/Присесть\"\n  STR_RELOAD: \"Перезарядка\"\n  STR_TOGGLE_PERSONAL_LIGHTING: \"Вкл./выкл. перс. освещение\"\n  STR_DONT_RESERVE_TIME_UNITS: \"Не резервировать ОД\"\n  STR_RESERVE_TIME_UNITS_FOR_SNAP_SHOT: \"Резервировать ОД для выстрела навскидку\"\n  STR_RESERVE_TIME_UNITS_FOR_AIMED_SHOT: \"Резервировать ОД для прицельного выстрела\"\n  STR_RESERVE_TIME_UNITS_FOR_AUTO_SHOT: \"Резервировать ОД для стрельбы очередью\"\n  STR_CENTER_ON_ENEMY_1: \"Центр на противнике 1\"\n  STR_CENTER_ON_ENEMY_2: \"Центр на противнике 2\"\n  STR_CENTER_ON_ENEMY_3: \"Центр на противнике 3\"\n  STR_CENTER_ON_ENEMY_4: \"Центр на противнике 4\"\n  STR_CENTER_ON_ENEMY_5: \"Центр на противнике 5\"\n  STR_CENTER_ON_ENEMY_6: \"Центр на противнике 6\"\n  STR_CENTER_ON_ENEMY_7: \"Центр на противнике 7\"\n  STR_CENTER_ON_ENEMY_8: \"Центр на противнике 8\"\n  STR_CENTER_ON_ENEMY_9: \"Центр на противнике 9\"\n  STR_CENTER_ON_ENEMY_10: \"Центр на противнике 10\"\n  STR_CREATE_INVENTORY_TEMPLATE: \"Создать шаблон инвентаря\"\n  STR_APPLY_INVENTORY_TEMPLATE: \"Применить шаблон инвентаря\"\n  STR_CLEAR_INVENTORY: \"Очистить инвентарь\"\n  STR_AUTO_EQUIP: \"Автоэкипировка\"\n  STR_QUICK_SAVE: \"Быстрое сохранение\"\n  STR_QUICK_LOAD: \"Быстрая загрузка\"\n  STR_ADVANCED: \"ДОПОЛНИТЕЛЬНО\"\n  STR_AGGRESSIVERETALIATION: \"Агрессивное возмездие\"\n  STR_AGGRESSIVERETALIATION_DESC: \"НЛО будут активно искать вашу базу вне зависимости от выполняемого ими задания.\"\n  STR_STORAGELIMITSENFORCED: \"Лимиты складов для найденных предметов\"\n  STR_STORAGELIMITSENFORCED_DESC: \"Включает количественное ограничение объемов изоляторов и складов для захваченных в ходе заданий пришельцев и артефактов.\"\n  STR_CANSELLLIVEALIENS: \"Продажа живых пришельцев\"\n  STR_CANSELLLIVEALIENS_DESC: \"Разрешить продажу живых пришельцев. Рекомендуется при включении лимитов складов.\"\n  STR_ALLOWBUILDINGQUEUE: \"Включить очередь строительства\"\n  STR_ALLOWBUILDINGQUEUE_DESC: \"Новые модули могут возводиться рядом с еще не достроенными.\"\n  STR_BATTLEAUTOEND: \"Автозавершение боя\"\n  STR_BATTLEAUTOEND_DESC: \"При включении бой будет автоматически завершаться после нейтрализации последнего противника.\"\n  STR_BATTLEINSTANTGRENADE: \"Мгновенные гранаты\"\n  STR_BATTLEINSTANTGRENADE_DESC: \"Гранаты с задержкой 0 ходов будут взрываться сразу же после броска, а не в конце хода. \"\n  STR_BATTLEUFOEXTENDERACCURACY: \"Точность выстрела, как в UFO Extender\"\n  STR_BATTLEUFOEXTENDERACCURACY_DESC: \"Точность выстрела уменьшается, начиная с определенной дистанции (зависит от режима стрельбы). Вероятность попадания отображается над курсором.\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE: \"Переназначение в полете\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE_DESC: \"Транспортное средство, выполняющее задание, можно приписать к другой базе.\"\n  STR_CRAFTLAUNCHALWAYS: \"Форсированный запуск ТС\"\n  STR_CRAFTLAUNCHALWAYS_DESC: \"ТС можно запускать, даже если они не полностью подготовлены.\"\n  STR_CUSTOMINITIALBASE: \"Свободный дизайн первой базы\"\n  STR_CUSTOMINITIALBASE_DESC: \"Начиная новую игру, игрок может самостоятельно выбрать расположение доступных ему модулей вместо обычной схемы застройки.\"\n  STR_GLOBESEASONS: \"Реалистичное освещение земного шара\"\n  STR_GLOBESEASONS_DESC: \"Использовать астрономически верное освещение земного шара, учитывающее наклон оси вращения Земли.\"\n  STR_PLAYINTRO: \"Показывать заставку\"\n  STR_PLAYINTRO_DESC: \"Показывать заставку при запуске игры.\"\n  STR_SHOWMORESTATSININVENTORYVIEW: \"Характеристики бойца на экране снаряжения\"\n  STR_SHOWMORESTATSININVENTORYVIEW_DESC: \"Показывать дополнительную информацию о выбранном бойце на экране снаряжения.\"\n  STR_SNEAKYAI: \"Скрытный ИИ\"\n  STR_SNEAKYAI_DESC: \"ИИ всеми способами старается действовать скрытно.\"\n  STR_STRAFE: \"Альтернативные способы движения\"\n  STR_STRAFE_DESC: \"Позволяет двигаться боком (стрейфиться), бежать и вращать башню танка независимо от шасси при нажатой Ctrl.\"\n  STR_BATTLEEXPLOSIONHEIGHT: \"Высота взрыва\"\n  STR_BATTLEEXPLOSIONHEIGHT_DESC: \"Изменение радиуса взрыва по вертикали.{NEWLINE}(плоский: 0, объемный: 3)\"\n  STR_AUTOSAVE: \"Автоматическое сохранение игры\"\n  STR_AUTOSAVE_DESC: \"Автоматически сохраняет игру с заданной периодичностью. Не действует в режиме «Стальная воля».\"\n  STR_AUTOSAVE_FREQUENCY: \"Периодичность автосохранения\"\n  STR_AUTOSAVE_FREQUENCY_DESC: \"Количество ходов, после которых будет производиться автоматическое сохранение.\"\n  STR_ALLOWPSIONICCAPTURE: \"Разрешить пси-захват\"\n  STR_ALLOWPSIONICCAPTURE_DESC: \"Если все живые пришельцы находятся под пси-контролем, игроку засчитывается победа, и они считаются захваченными в плен.\"\n  STR_ANYTIMEPSITRAINING: \"Псионическая тренировка в любое время\"\n  STR_ANYTIMEPSITRAINING_DESC: \"Позволяет назначать бойцов на псионическую тренировку в любой день месяца. Начальная подготовка всегда занимает от 30 до 60 дней.\"\n  STR_SKIPNEXTTURNSCREEN: \"Пропускать заставку «Следующий ход»\"\n  STR_SKIPNEXTTURNSCREEN_DESC: \"Экран «Следующий ход» в тактической фазе закрывается автоматически через некоторое время.\"\n  STR_NOT_ENOUGH_SPACE: \"Недостаточно места!\"\n  STR_WEAPONSELFDESTRUCTION: \"Самоуничтожение оружия пришельцев\"\n  STR_WEAPONSELFDESTRUCTION_DESC: \"Если пришелец убит, его оружие самоуничтожается, как в XCOM 2012.\"\n  STR_RETAINCORPSES: \"Оставлять допрошенных пришельцев\"\n  STR_RETAINCORPSES_DESC: \"По окончании допроса живых пришельцев их тела будут перемещаться на склад, как в XCOM 2012.\"\n  STR_SAVE_VOXEL_VIEW: \"Сделать снимок экрана от первого лица\"\n  STR_RESERVE_TIME_UNITS_FOR_KNEEL: \"Резервировать ОД, чтобы присесть\"\n  STR_EXPEND_ALL_TIME_UNITS: \"Обнулить очки действия\"\n  STR_PSISTRENGTHEVAL: \"Оценка псионической силы\"\n  STR_PSISTRENGTHEVAL_DESC: \"Пси-сила всех бойцов отображается по завершении соответствующего исследования.\"\n  STR_DISABLEAUTOEQUIP: \"Отключить автоэкипировку\"\n  STR_DISABLEAUTOEQUIP_DESC: \"Отключить автоэкипировку новых бойцов перед боем.\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT: \"Позволить развивать псионическую силу\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT_DESC: \"Псионическая сила бойцов может расти в процессе тренировок и с получением боевого опыта.\"\n  STR_BATTLESMOOTHCAMERA: \"Плавная проводка выстрела\"\n  STR_BATTLESMOOTHCAMERA_DESC: \"Камера будет плавно отслеживать поражающие элементы, пока они двигаются.\"\n  STR_BATTLECONFIRMFIREMODE: \"Подтверждение выстрела\"\n  STR_BATTLECONFIRMFIREMODE_DESC: \"При включении потребуется второй щелчок мыши по выбранной клетке, чтобы открыть огонь.\"\n  STR_SELECT_BASE_1: \"Выбрать базу 1\"\n  STR_SELECT_BASE_2: \"Выбрать базу 2\"\n  STR_SELECT_BASE_3: \"Выбрать базу 3\"\n  STR_SELECT_BASE_4: \"Выбрать базу 4\"\n  STR_SELECT_BASE_5: \"Выбрать базу 5\"\n  STR_SELECT_BASE_6: \"Выбрать базу 6\"\n  STR_SELECT_BASE_7: \"Выбрать базу 7\"\n  STR_SELECT_BASE_8: \"Выбрать базу 8\"\n  STR_VIDEO: \"ВИДЕО\"\n  STR_AUDIO: \"АУДИО\"\n  STR_BATTLESCAPE_UC: \"ПОЛЕ БОЯ\"\n  STR_MODS_UC: \"МОДЫ\"\n  STR_MODS: \"Моды\"\n  STR_DISPLAY_RESOLUTION: \"Разрешение окна\"\n  STR_DISPLAY_RESOLUTION_DESC: \"Изменение разрешения экрана, которому сопоставляется разрешение изображения. Стрелки переключают полноэкранные разрешения. Для ввода нестандартных значений щелкните мышью по цифрам.\"\n  STR_ORIGINAL: \"Оригинальное\"\n  STR_DISPLAY_MODE: \"Режим отображения\"\n  STR_WINDOWED: \"Оконный\"\n  STR_FULLSCREEN: \"Полноэкранный\"\n  STR_BORDERLESS: \"Без рамки\"\n  STR_DISPLAY_LANGUAGE: \"Язык\"\n  STR_DISPLAY_LANGUAGE_DESC: \"Изменение языка игры.\"\n  STR_DISPLAY_FILTER: \"Фильтр изображения\"\n  STR_DISPLAY_FILTER_DESC: \"Применение эффекта постобработки изображения в игре.{NEWLINE}*Требуется аппаратное ускорение OpenGL.\"\n  STR_DISPLAY_OPTIONS: \"Настройки экрана\"\n  STR_LETTERBOXED: \"Сохранять пропорции\"\n  STR_LETTERBOXED_DESC: \"Добавляет черные полосы по краям экрана для сохранения исходного соотношения сторон изображения.\"\n  STR_RESIZABLE: \"Оконный изм.\"\n  STR_LOCK_MOUSE: \"Захват мыши\"\n  STR_LOCK_MOUSE_DESC: \"При включении курсор мыши остается внутри активного окна игры. Чтобы включить / выключить захват курсора, нажмите Ctrl-G.\"\n  STR_FIXED_WINDOW_POSITION: \"Фикс. положение окна\"\n  STR_FIXED_WINDOW_POSITION_DESC: \"Установка фиксированного положения окна.\"\n  STR_DISPLAY_SET_WINDOW_POSITION: \"Укажите новую позицию окна:\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_X: \"Отступ слева:\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_Y: \"Отступ сверху:\"\n  STR_MUSIC_VOLUME: \"Громкость музыки\"\n  STR_MUSIC_VOLUME_DESC: \"Изменение громкости фоновой музыки.\"\n  STR_SFX_VOLUME: \"Громкость эффектов\"\n  STR_SFX_VOLUME_DESC: \"Изменение уровня громкости звуковых эффектов.\"\n  STR_UI_VOLUME: \"Громкость интерфейса\"\n  STR_UI_VOLUME_DESC: \"Изменение громкости нажатий по элементам интерфейса.\"\n  STR_SCROLL_SPEED: \"Скорость скроллинга\"\n  STR_SCROLL_SPEED_GEO_DESC: \"Изменение скорости вращения земного шара.\"\n  STR_SCROLL_SPEED_BATTLE_DESC: \"Изменение скорости скроллинга карты.\"\n  STR_DOGFIGHT_SPEED: \"Скорость возд. боев\"\n  STR_DOGFIGHT_SPEED_DESC: \"Изменение скорости воздушных боев между ЛА X-Com и НЛО. Выбор более низкой скорости может улучшить производительность на слабых устройствах.\"\n  STR_CLOCK_SPEED: \"Скорость игровых часов\"\n  STR_CLOCK_SPEED_DESC: \"Изменение скорости часов на стратегической карте. Выбор более низкой скорости может улучшить производительность на слабых устройствах.\"\n  STR_GLOBE_DETAILS: \"Стратегическая карта\"\n  STR_GLOBE_COUNTRIES: \"Страны\"\n  STR_GLOBE_COUNTRIES_DESC: \"Отображение названий финансирующих государств на стратегической карте.\"\n  STR_GLOBE_RADARS: \"Радары\"\n  STR_GLOBE_RADARS_DESC: \"Отображение радиуса действия радаров базы на стратегической карте.\"\n  STR_GLOBE_FLIGHT_PATHS: \"Маршруты полета\"\n  STR_GLOBE_FLIGHT_PATHS_DESC: \"Отображение маршрутов ТС на стратегической карте.\"\n  STR_CONTROLS_DESC: \"Щелкните левой кнопкой мыши по элементу и нажмите нужную клавишу для переназначения. Щелчок правой кнопкой очищает назначенную клавишу.\"\n  STR_BASE_GAME: \"Базовая игра\"\n  STR_MODS_TOOLTIP: \"Версия {0} от {1}.{NEWLINE}{2}\"\n  STR_EDGE_SCROLL: \"Скроллинг по краю\"\n  STR_EDGE_SCROLL_DESC: \"По нажатию: скроллинг карты при нажатой левой кнопке на краю экрана.{NEWLINE}Авто: скроллинг карты при приближении курсора к краю экрана.\"\n  STR_TRIGGER_SCROLL: \"По нажатию\"\n  STR_AUTO_SCROLL: \"Авто\"\n  STR_DRAG_SCROLL: \"Скроллинг удержанием\"\n  STR_DRAG_SCROLL_DESC: \"Скроллинг карты при зажатой указанной кнопке мыши.\"\n  STR_LEFT_MOUSE_BUTTON: \"Левая кнопка\"\n  STR_MIDDLE_MOUSE_BUTTON: \"Средняя кнопка\"\n  STR_RIGHT_MOUSE_BUTTON: \"Правая кнопка\"\n  STR_FIRE_SPEED: \"Скорость выстрелов\"\n  STR_FIRE_SPEED_DESC: \"Изменение скорости анимации полета поражающих элементов.\"\n  STR_PLAYER_MOVEMENT_SPEED: \"Скорость игрока\"\n  STR_PLAYER_MOVEMENT_SPEED_DESC: \"Изменение скорости перемещения управляемых игроком боевых единиц.\"\n  STR_COMPUTER_MOVEMENT_SPEED: \"Скорость движения ИИ\"\n  STR_COMPUTER_MOVEMENT_SPEED_DESC: \"Изменение скорости перемещения управляемых ИИ боевых единиц.\"\n  STR_PATH_PREVIEW: \"Предпросмотр пути\"\n  STR_PATH_ARROWS: \"Стрелки\"\n  STR_PATH_ARROWS_DESC: \"Щелчком выводится путь до точки назначения. Цвета обозначают возможные действия: {ALT}зеленый{ALT} - может выдвинуться и открыть огонь; {ALT}желтый{ALT} - может переместиться; {ALT}красный{ALT} - недостижимая точка.\"\n  STR_PATH_TIME_UNIT_COST: \"Очки действия\"\n  STR_PATH_TIME_UNIT_COST_DESC: \"По щелчку мыши будут отображаться оставшиеся после передвижения ОД бойца.\"\n  STR_USER_INTERFACE_OPTIONS: \"Настройки интерфейса\"\n  STR_TOOLTIPS: \"Подсказки\"\n  STR_TOOLTIPS_DESC: \"Отображение подсказок для кнопок в режиме боя.\"\n  STR_DEATH_NOTIFICATIONS: \"Сообщать имя убитого\"\n  STR_DEATH_NOTIFICATIONS_DESC: \"Отображение сообщения с именем убитого бойца в случае его гибели.\"\n  STR_SHOW_FUNDS: \"Показывать финансы\"\n  STR_SHOW_FUNDS_DESC: \"Отображение текущих финансов рядом с часами.\"\n  STR_MISSION_GENERATOR: \"ГЕНЕРАТОР МИССИЙ\"\n  STR_MAP_OPTIONS: \"НАСТРОЙКИ КАРТЫ\"\n  STR_ALIEN_OPTIONS: \"НАСТРОЙКИ ПРИШЕЛЬЦЕВ\"\n  STR_MAP_TERRAIN: \"Местность\"\n  STR_MAP_DARKNESS: \"Затемнение\"\n  STR_MAP_DEPTH: \"Глубина\"\n  STR_DIFFICULTY: \"Сложность\"\n  STR_ALIEN_RACE: \"Раса\"\n  STR_ALIEN_TECH_LEVEL: \"Технологический уровень\"\n  STR_RANDOMIZE: \"Случайно\"\n  STR_OXCE_REQUIRED_QUESTION: \"Для корректной работы этого мода требуется OpenXcom {0}. Включить мод?\"\n  STR_RESTORE_DEFAULTS_QUESTION: \"Вы уверены, что хотите восстановить настройки по умолчанию?\"\n  STR_DISPLAY_OPTIONS_CONFIRM: \"Оставить текущие настройки экрана?\"\n  STR_DISPLAY_OPTIONS_REVERT: \"Восстановление прежних настроек через 0:{0}\"\n  STR_MISSING_CONTENT_PROMPT: \"ВНИМАНИЕ!{SMALLLINE}Файл сохранения ссылается на недоступный мод. Отсутствующее содержимое будет отключено, что может привести к ошибкам.{NEWLINE}Продолжить?\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT: \"Сохранять предварительно взведенные гранаты\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT_DESC: \"Сохраняет состояние детонатора гранат, если они были взведены в ходе экипировки бойцов на базе.\"\n  STR_NEWSEEDONLOAD: \"Читерство с сохранениями\"\n  STR_NEWSEEDONLOAD_DESC: \"При загрузке сохранения будет сбрасываться генератор случайных чисел: одно и то же действие будет приводить к разным результатам. Не влияет на режим «Стальная воля».\"\n  STR_CHANGEVALUEBYMOUSEWHEEL: \"Изменение значений колесом мыши\"\n  STR_CHANGEVALUEBYMOUSEWHEEL_DESC: \"С помощью колеса мыши становится возможным увеличение / уменьшение значений на указанную величину (при наведении курсора на стрелки напротив соответствующей позиции).\"\n  STR_BATTLEHAIRBLEACH: \"Улучшенные спрайты бойцов\"\n  STR_BATTLEHAIRBLEACH_DESC: \"При включении спрайты бойцов на поле боя соответствуют изображению на экране инвентаря.\"\n  STR_DRAGSCROLLINVERT: \"Инвертирование скроллинга удержанием\"\n  STR_DRAGSCROLLINVERT_DESC: \"При включении карта прокручивается в направлении, противоположном движению мыши.\"\n  STR_BATTLESCAPE_SCALE: \"Масштаб поля боя\"\n  STR_BATTLESCAPE_SCALE_DESC: \"Режим масштабирования окна поля боя: на основе фиксированного разрешения (растяжение изображения) или фиксированного коэффициента увеличения (заполнение окна).\"\n  STR_GEOSCAPE_SCALE: \"Масштаб глоб. вида\"\n  STR_GEOSCAPESCALE_SCALE_DESC: \"Метод масштабирования стратегической карты: на основе фиксированного разрешения (растяжение изображения) или фиксированного коэффициента увеличения (заполнение окна).\"\n  STR_1_5X: \"480x300\"\n  STR_2X: \"640x400\"\n  STR_THIRD_DISPLAY: \"Расширенное x3\"\n  STR_HALF_DISPLAY: \"Расширенное x2\"\n  STR_FULL_DISPLAY: \"Расширенное x1\"\n  STR_FPS_LIMIT: \"Ограничение кадров в секунду\"\n  STR_FPS_LIMIT_DESC: \"Ограничение количества обновлений экрана в секунду. 0 - без ограничений. При использовании OpenGL заменяется вертикальной синхронизацией.\"\n  STR_FPS_INACTIVE_LIMIT: \"Ограничение кадров в секунду в фоне\"\n  STR_FPS_INACTIVE_LIMIT_DESC: \"Ограничение количества обновлений экрана в секунду, когда окно OpenXcom не активно.\"\n  STR_NOALIENPANICMESSAGES: \"Не показывать сообщения о панике пришельцев\"\n  STR_NOALIENPANICMESSAGES_DESC: \"Не показывать сообщения о паникующих пришельцах, которых не видят бойцы игрока.\"\n  STR_ALIENBLEEDING: \"Пришельцы истекают кровью\"\n  STR_ALIENBLEEDING_DESC: \"Позволяет наносить смертельные ранения большинству пришельцев.\"\n  STR_FIELDPROMOTIONS: \"Боевые повышения\"\n  STR_FIELDPROMOTIONS_DESC: \"Повышение могут получить только те бойцы, которые находились на задании.\"\n  STR_MEETINGPOINT: \"Упреждение траектории НЛО\"\n  STR_MEETINGPOINT_DESC: \"Транспортное средство выдвинется в предполагаемую точку встречи, вычисленную на основе текущей траектории НЛО.\"\n  STR_IRONMAN: \"СТАЛЬНАЯ ВОЛЯ\"\n  STR_IRONMAN_DESC: \"Сохранение вручную отключено\"\n  STR_SAVE_AND_ABANDON_GAME: \"СОХРАНИТЬ И ПОКИНУТЬ ИГРУ\"\n  STR_MOD_UNSUCCESSFUL: \"Не удалось загрузить мод\"\n  STR_NEW_SAVED_GAME_SLOT: \"<НОВОЕ СОХРАНЕНИЕ>\"\n  STR_AUTO_SAVE_GEOSCAPE_SLOT: \"<АВТОСОХРАНЕНИЕ СТРАТЕГИЧЕСКОЙ КАРТЫ>\"\n  STR_AUTO_SAVE_BATTLESCAPE_SLOT: \"<АВТОСОХРАНЕНИЕ ПОЛЯ БОЯ>\"\n  STR_QUICK_SAVE_SLOT: \"<БЫСТРОЕ СОХРАНЕНИЕ>\"\n  STR_DISPLAY_MODE_DESC: \"Изменение режима отображения игры на экране.\"\n  STR_PREFERRED_MUSIC_FORMAT: \"Формат музыки\"\n  STR_PREFERRED_MUSIC_FORMAT_DESC: \"Формат музыки при наличии файлов в различных форматах.{NEWLINE}ПРИМЕЧАНИЕ: Воспроизведение формата MIDI в Windows может работать некорректно.\"\n  STR_PREFERRED_SFX_FORMAT: \"Формат эффектов\"\n  STR_PREFERRED_SFX_FORMAT_DESC: \"Предпочтительный формат аудиоэффектов при наличии файлов в нескольких форматах.\"\n  STR_PREFERRED_VIDEO_FORMAT: \"Формат видео\"\n  STR_PREFERRED_VIDEO_FORMAT_DESC: \"Предпочтительный формат видео при наличии файлов в нескольких форматах.\"\n  STR_PREFERRED_VIDEO_ANIMATION: \"Анимация\"\n  STR_PREFERRED_VIDEO_SLIDESHOW: \"Слайд-фильм\"\n  STR_PREFERRED_FORMAT_AUTO: \"Авто\"\n  STR_CURRENT_FORMAT: \"Текущий: {0}\"\n  STR_SOUND_OPTIONS: \"Настройки звука\"\n  STR_BACKGROUND_MUTE: \"Заглушать в фоне\"\n  STR_BACKGROUND_MUTE_DESC: \"Отключение воспроизведения звуков игры, если окно OpenXcom не активно.\"\n  STR_FORCE_FIRE: \"Игнорировать линию огня\"\n  STR_FORCE_FIRE_DESC: \"При включении позволяет при нажатой Ctrl произвести выстрел даже при отсутствии линии огня.\"\n  STR_NO_AUDIO_HARDWARE_DETECTED: \"Звуковая карта не обнаружена\"\n  STR_MOUSEWHEEL_SPEED: \"Скорость прокрутки колесом мыши\"\n  STR_MOUSEWHEEL_SPEED_DESC: \"Изменение числа строк, на которое прокручиваются списки при использовании колеса мыши.\"\n  STR_DISABLED: \"Отключено\"\n  STR_MAXIMIZE_INFO_SCREENS: \"Информационные окна на весь экран\"\n  STR_MAXIMIZE_INFO_SCREENS_DESC: \"При включении окно инвентаря и некоторые другие всегда растягивается на весь экран, независимо от настроек масштабирования.\"\n  STR_DIARY: \"ЖУРНАЛ\"\n  STR_KILLED: \"УБИТО\"\n  STR_STUNNED: \"ОГЛУШЕНО\"\n  STR_PANICKED: \"ПАНИКОВАЛ(А)\"\n  STR_MINDCONTROLLED: \"ПОД КОНТРОЛЕМ\"\n  STR_REGION_UNKNOWN: \"Секретно\"\n  STR_WEAPON_UNKNOWN: \"Импровизация\"\n  STR_UNKNOWN: \"Неизвестно\"\n  STR_VICTORY: \"Победа\"\n  STR_DEFEAT: \"Поражение\"\n  STR_NO_RECORD: \"Нет записей\"\n  STR_HUMAN: \"Человек\"\n  STR_FRIENDLY: \"Союзник\"\n  STR_HOSTILE: \"Противник\"\n  STR_NEUTRAL: \"Нейтральный\"\n  STR_RATING_UC: \"РЕЙТИНГ\"\n  STR_LOCATION: \"РЕГИОН> {ALT}{0}\"\n  STR_DAYLIGHT_TYPE: \"ВРЕМЯ> {ALT}{0}\"\n  STR_RACE_TYPE: \"РАСА> {ALT}{0}\"\n  STR_DAY: \"День\"\n  STR_NIGHT: \"Ночь\"\n  STR_DAYS_WOUNDED: \"ДН. ЛАЗАРЕТА> {ALT}{0}\"\n  STR_COMBAT: \"РЕЗУЛЬТАТЫ\"\n  STR_PERFORMANCE: \"АКТИВНОСТЬ\"\n  STR_NEUTRALIZATIONS_BY_RACE: \"НЕЙТРАЛИЗАЦИЙ ПО РАСЕ\"\n  STR_NEUTRALIZATIONS_BY_RANK: \"НЕЙТРАЛИЗАЦИЙ ПО РАНГУ\"\n  STR_NEUTRALIZATIONS_BY_WEAPON: \"НЕЙТРАЛИЗАЦИЙ ПО ВИДУ ОРУЖИЯ\"\n  STR_MISSIONS_BY_LOCATION: \"МИССИЙ ПО РЕГИОНУ\"\n  STR_MISSIONS_BY_TYPE: \"МИССИЙ ПО ТИПУ\"\n  STR_MISSIONS_BY_UFO: \"МИССИЙ ПО ТС ПРОТИВНИКА\"\n  STR_SCORE_VALUE: \"РЕЙТИНГ> {ALT}{0}\"\n  STR_WINS: \"ПОБЕД> {ALT}{0}\"\n  STR_STUNS: \"ОГЛУШЕНИЙ> {ALT}{0}\"\n  STR_PANICKS: \"ПАНИК> {ALT}{0}\"\n  STR_MINDCONTROLS: \"ПОД КОНТРОЛЕМ> {ALT}{0}\"\n  STR_AWARDS: \"НАГРАДЫ\"\n  STR_COMMENDATIONS_UC: \"ПООЩРЕНИЯ\"\n  STR_COMMENDATIONS: \"Поощрения\"\n  STR_MEDALS: \"МЕДАЛИ\"\n  STR_LOST_IN_SERVICE: \"ПАВШИЕ В БОЮ\"\n  STR_MEDAL_NAME: \"Имя медали\"\n  STR_MEDAL_AWARD_LEVEL: \"Уровень награды\"\n  STR_MEDAL_DECOR_LEVEL: \"Уровень знаков отличия\"\n  STR_AWARD_0: \"Первая награда\"\n  STR_AWARD_1: \"Вторая награда\"\n  STR_AWARD_2: \"Третья награда\"\n  STR_AWARD_3: \"Четвертая награда\"\n  STR_AWARD_4: \"Пятая награда\"\n  STR_AWARD_5: \"Шестая награда\"\n  STR_AWARD_6: \"Седьмая награда\"\n  STR_AWARD_7: \"Восьмая награда\"\n  STR_AWARD_8: \"Девятая награда\"\n  STR_AWARD_9: \"Десятая награда\"\n  STR_AWARD_DECOR_0: \"Нет\"\n  STR_AWARD_DECOR_1: \"Первый бронзовый знак\"\n  STR_AWARD_DECOR_2: \"Второй бронзовый знак\"\n  STR_AWARD_DECOR_3: \"Третий бронзовый знак\"\n  STR_AWARD_DECOR_4: \"Первый серебряный знак\"\n  STR_AWARD_DECOR_5: \"Второй серебряный знак\"\n  STR_AWARD_DECOR_6: \"Третий серебряный знак\"\n  STR_AWARD_DECOR_7: \"Первый золотой знак\"\n  STR_AWARD_DECOR_8: \"Второй золотой знак\"\n  STR_AWARD_DECOR_9: \"Третий золотой знак\"\n  STR_KILLED_IN_ACTION_MALE: \"УБИТ В БОЮ\"\n  STR_KILLED_IN_ACTION_FEMALE: \"УБИТА В БОЮ\"\n  STR_MISSING_IN_ACTION_MALE: \"ПРОПАЛ БЕЗ ВЕСТИ\"\n  STR_MISSING_IN_ACTION_FEMALE: \"ПРОПАЛА БЕЗ ВЕСТИ\"\n  STR_AVERAGE_MONTHLY_RATING: \"Среднемесячный рейтинг\"\n  STR_TOTAL_INCOME: \"Общие доходы\"\n  STR_TOTAL_EXPENDITURE: \"Общие расходы\"\n  STR_MISSIONS_WON: \"Миссий выполнено\"\n  STR_MISSIONS_LOST: \"Миссий провалено\"\n  STR_NIGHT_MISSIONS: \"Ночных миссий\"\n  STR_BEST_RATING: \"Лучший рейтинг за миссию\"\n  STR_WORST_RATING: \"Худший рейтинг за миссию\"\n  STR_ALIEN_KILLS: \"Пришельцев убито\"\n  STR_ALIEN_CAPTURES: \"Пришельцев захвачено\"\n  STR_FRIENDLY_KILLS: \"Эпизодов огня по своим\"\n  STR_AVERAGE_ACCURACY: \"Средняя точность\"\n  STR_WEAPON_MOST_KILLS: \"Наиболее эффективное оружие\"\n  STR_ALIEN_MOST_KILLS: \"Наиболее смертоносный пришелец\"\n  STR_LONGEST_SERVICE: \"Наибольшее число месяцев в строю\"\n  STR_TOTAL_DAYS_WOUNDED: \"Дней в лазарете\"\n  STR_COUNTRIES_LOST: \"Стран потеряно\"\n  STR_TOTAL_TERROR_SITES: \"Террористических атак\"\n  STR_TOTAL_BASES: \"Баз построено\"\n  STR_TOTAL_CRAFT: \"Всего ТС\"\n  STR_TOTAL_SCIENTISTS: \"Ученых нанято\"\n  STR_TOTAL_ENGINEERS: \"Инженеров нанято\"\n  STR_TOTAL_RESEARCH: \"Исследований завершено\"\n  STR_DIARY_ACCURACY: \"ТОЧНОСТЬ> {ALT}{0}%\"\n  STR_STATISTICS: \"Статистика\"\n  STR_STATS: \"СТАТЫ\"\n  STR_TIME_UNITS_ABBREVIATION: \"ОД\"\n  STR_STAMINA_ABBREVIATION: \"ВЫН\"\n  STR_HEALTH_ABBREVIATION: \"ЗД\"\n  STR_BRAVERY_ABBREVIATION: \"ХРА\"\n  STR_REACTIONS_ABBREVIATION: \"РЕА\"\n  STR_FIRING_ACCURACY_ABBREVIATION: \"ТОЧ\"\n  STR_THROWING_ACCURACY_ABBREVIATION: \"БРО\"\n  STR_STRENGTH_ABBREVIATION: \"СИЛ\"\n  STR_MELEE_ACCURACY_ABBREVIATION: \"РУК\"\n  STR_FOLDERS: \"ПАПКИ\"\n  STR_DATA_FOLDER: \"Папка данных (original resources)\"\n  STR_USER_FOLDER: \"Папка пользователя (mods, openxcom.log)\"\n  STR_SAVE_FOLDER: \"Папка сохранений (saved games, screenshots)\"\n  STR_CONFIG_FOLDER: \"Папка конфигурации (options.cfg)\"\n  STR_DATA_FOLDER_DESC_1: \"Папка, содержащая ассеты оригинальных игр (UFO и/или TFTD).\"\n  STR_DATA_FOLDER_DESC_2: \"Собственные ресурсы OpenXcom находятся в папке 'common'. Встроенные моды OpenXcom находятся в папке 'standard'.\"\n  STR_USER_FOLDER_DESC: \"Папка хранения файла журнала OpenXcom ('openxcom.log'), а также пользовательских модов (подпапка 'mods').\"\n  STR_SAVE_FOLDER_DESC: \"Папка сохранений игры, а также хранения файла настроек генератора миссий ('battle.cfg').\"\n  STR_CONFIG_FOLDER_DESC: \"Папка настроек OpenXcom ('options.cfg'). Обычно совпадает с пользовательской папкой.\"\n"
  },
  {
    "path": "bin/common/Language/sk.yml",
    "content": "sk:\n  STR_OPENXCOM: \"OpenXcom\"\n  STR_NEW_GAME: \"Nová hra\"\n  STR_LOAD_SAVED_GAME: \"Nahraj hru\"\n  STR_SELECT_DIFFICULTY_LEVEL: \"Vyberte stupeň obťažnosti\"\n  STR_1_BEGINNER: \"1> Začiatočník\"\n  STR_2_EXPERIENCED: \"2> Skúsený\"\n  STR_3_VETERAN: \"3> Veterán\"\n  STR_4_GENIUS: \"4> Génius\"\n  STR_5_SUPERHUMAN: \"5> Nadčlovek\"\n  STR_TIME: \"Čas\"\n  STR_DATE: \"Dátum\"\n  STR_SELECT_GAME_TO_LOAD: \"Vyber uloženú pozíciu\"\n  STR_SELECT_SAVE_POSITION: \"Vyber pozíciu na uloženie\"\n  STR_GAME_OPTIONS: \"NASTAVENIA HRY\"\n  STR_LOAD_GAME: \"NAHRAŤ HRU\"\n  STR_SAVE_GAME: \"ULOŽIŤ HRU\"\n  STR_ABANDON_GAME: \"OPUSTIŤ HRU\"\n  STR_ABANDON_GAME_QUESTION: \"OPUSTIŤ HRU?\"\n  STR_QUIT: \"Koniec\"\n  STR_SAVING_GAME: \"Ukladám hru\"\n  STR_LOADING_GAME: \"Nahrávam hru\"\n  STR_NO_SAVED_GAME_PRESENT: \"Žiadna uložená pozícia\"\n  STR_LOAD_UNSUCCESSFUL: \"Načítanie neúspešné\"\n  STR_SAVE_UNSUCCESSFUL: \"Uloženie zlyhalo\"\n  STR_LOAD_SUCCESSFUL: \"Načítanie úspešné\"\n  STR_SAVE_SUCCESSFUL: \"Uloženie úspešné\"\n  STR_DELETE: \"VYMAZAŤ\"\n  STR_DELETE_UNSUCCESSFUL: \"Neúspešné zmazanie\"\n  STR_IS_IT_OK_TO_DELETE_THE_SAVED_GAME: \"Naozaj chceš vymazať uloženú pozíciu?\"\n  STR_ORIGINAL_XCOM: \"Pôvodný X-Com\"\n  STR_LOADING: \"Nahrávam...\"\n  STR_DETAILS: \"PODROBNOSTI> {ALT}{0}\"\n  STR_NEW_BATTLE: \"Nová bitka\"\n  STR_OPTIONS: \"Nastavenia\"\n  STR_RIGHT_CLICK_TO_DELETE: \"Pravým kliknutím vymazať.\"\n  STR_RESTORE_DEFAULTS: \"Obnov pôvodné\"\n  STR_CONTROLS: \"NASTAVENIA\"\n  STR_GENERAL: \"Hlavné\"\n  STR_GEOSCAPE: \"Glóbus\"\n  STR_BATTLESCAPE: \"Bojisko\"\n  STR_SCREENSHOT: \"Screenshot\"\n  STR_FPS_COUNTER: \"Počítadlo FPS\"\n  STR_ROTATE_LEFT: \"Otočiť vľavo\"\n  STR_ROTATE_RIGHT: \"Otočiť vpravo\"\n  STR_ROTATE_UP: \"Otočiť hore\"\n  STR_ROTATE_DOWN: \"Otočiť dole\"\n  STR_ZOOM_IN: \"Priblížiť\"\n  STR_ZOOM_OUT: \"Oddiaľiť\"\n  STR_TOGGLE_COUNTRY_DETAIL: \"Zapnúť detail krajiny\"\n  STR_TOGGLE_RADAR_RANGES: \"Zapnúť zobrazenie dosahu radarov\"\n  STR_SCROLL_LEFT: \"Posunúť doľava\"\n  STR_SCROLL_RIGHT: \"Posuň doprava\"\n  STR_SCROLL_UP: \"Posunúť hore\"\n  STR_SCROLL_DOWN: \"Posunúť nadol\"\n  STR_UNIT_LEVEL_ABOVE: \"Presunúť jednotku o úroveň vyššie\"\n  STR_UNIT_LEVEL_BELOW: \"Presunúť jednotku o úroveň nižšie\"\n  STR_VIEW_LEVEL_ABOVE: \"Zobraziť úroveň nad\"\n  STR_VIEW_LEVEL_BELOW: \"Zobraziť úroveň pod\"\n  STR_CENTER_SELECTED_UNIT: \"Vycentrovať na označenú jednotku\"\n  STR_PREVIOUS_UNIT: \"Vybrať predchádzajúcu jednotku\"\n  STR_NEXT_UNIT: \"Vybrať nasledujúcu jednotku\"\n  STR_DESELECT_UNIT: \"Neoznačovať jednotku znova\"\n  STR_USE_LEFT_HAND: \"Použiť predmet v ľavej ruke\"\n  STR_USE_RIGHT_HAND: \"Použiť predmet v pravej ruke\"\n  STR_INVENTORY: \"Inventár\"\n  STR_MINIMAP: \"Minimapa\"\n  STR_MULTI_LEVEL_VIEW: \"Viacúrovňový pohľad\"\n  STR_END_TURN: \"Koniec kola\"\n  STR_ABORT_MISSION: \"Zrušiť misiu\"\n  STR_UNIT_STATS: \"Vlastnosti jednotky\"\n  STR_KNEEL: \"Pokľaknúť\"\n  STR_RELOAD: \"Nabiť\"\n  STR_TOGGLE_PERSONAL_LIGHTING: \"Nastaviť osobné osvetlenie\"\n  STR_DONT_RESERVE_TIME_UNITS: \"Nerezervovať AB\"\n  STR_RESERVE_TIME_UNITS_FOR_SNAP_SHOT: \"Rezervovať AB pre rýchlu streľbu\"\n  STR_RESERVE_TIME_UNITS_FOR_AIMED_SHOT: \"Rezervovať AB pre mierenú strelu\"\n  STR_RESERVE_TIME_UNITS_FOR_AUTO_SHOT: \"Rezervovať AB pre automatickú streľbu\"\n  STR_CENTER_ON_ENEMY_1: \"Vycentrovať na nepriateľa 1\"\n  STR_CENTER_ON_ENEMY_2: \"Vycentrovať na nepriateľa 2\"\n  STR_CENTER_ON_ENEMY_3: \"Vycentrovať na nepriateľa 3\"\n  STR_CENTER_ON_ENEMY_4: \"Vycentrovať na nepriateľa 4\"\n  STR_CENTER_ON_ENEMY_5: \"Vycentrovať na nepriateľa 5\"\n  STR_CENTER_ON_ENEMY_6: \"Vycentrovať na nepriateľa 6\"\n  STR_CENTER_ON_ENEMY_7: \"Vycentrovať na nepriateľa 7\"\n  STR_CENTER_ON_ENEMY_8: \"Vycentrovať na nepriateľa 8\"\n  STR_CENTER_ON_ENEMY_9: \"Vycentrovať na nepriateľa 9\"\n  STR_CENTER_ON_ENEMY_10: \"Vycentrovať na nepriateľa 10\"\n  STR_CREATE_INVENTORY_TEMPLATE: \"Vytvor šablónu inventára\"\n  STR_APPLY_INVENTORY_TEMPLATE: \"Potvrď šablónu inventára\"\n  STR_CLEAR_INVENTORY: \"Vyčistiť inventár\"\n  STR_AUTO_EQUIP: \"Automatické vybavenie\"\n  STR_QUICK_SAVE: \"Rýchle uloženie\"\n  STR_QUICK_LOAD: \"Rýchle nahranie\"\n  STR_ADVANCED: \"POKROČILÉ\"\n  STR_AGGRESSIVERETALIATION: \"Agresívna odplata\"\n  STR_AGGRESSIVERETALIATION_DESC: \"UFO sa bude snažiť vždy vyhľadávať vašu základňu bez ohľadu na parametre jeho misie.\"\n  STR_STORAGELIMITSENFORCED: \"Limity skladových priestorov pre získané predmety\"\n  STR_STORAGELIMITSENFORCED_DESC: \"Zapne limity na zajatých živých mimozemšťanov a predmety získané v misiách v zadržiavacej cele mimozemšťanov a pre sklady\"\n  STR_CANSELLLIVEALIENS: \"Predaj živého mimozemšťana\"\n  STR_CANSELLLIVEALIENS_DESC: \"Umožní predávať živých mimozemšťanov, odporúča sa používať spolu s obmedzením skladových priestorov.\"\n  STR_ALLOWBUILDINGQUEUE: \"Povoliť stavebný rad\"\n  STR_ALLOWBUILDINGQUEUE_DESC: \"Nové zariadenia môžu byť postavené vedľa ešte nedokončených miestností.\"\n  STR_BATTLEAUTOEND: \"Automaticky ukončiť boj\"\n  STR_BATTLEAUTOEND_DESC: \"Boj automaticky skončí keď je posledný živý mimozemšťan neutralizovaný.\"\n  STR_BATTLEINSTANTGRENADE: \"Okamžité granáty\"\n  STR_BATTLEINSTANTGRENADE_DESC: \"Pokiaľ bol granát načasovaný na výbuch v 0 kole, vybuchne okamžite namiesto toho aby vybuchol až na konci kola.\"\n  STR_BATTLEUFOEXTENDERACCURACY: \"UFO Extender - Presnosť streľby\"\n  STR_BATTLEUFOEXTENDERACCURACY_DESC: \"Presnosť streľby klesá v závislosti na vzdialenosti a typu streľby. Upravená precíznosť streľby sa bude zobrazovať na kurzore.\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE: \"Presun vo vzduchu\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE_DESC: \"Plavidlo vo vzduchu môže byť presunuté.\"\n  STR_CRAFTLAUNCHALWAYS: \"Vynútený štart plavidla X-Com\"\n  STR_CRAFTLAUNCHALWAYS_DESC: \"Lietadlu môže byť povolený štart aj keď nie je pripravené, zrušením nutnosti údržby.\"\n  STR_CUSTOMINITIALBASE: \"Vlastné rozvrhnutie prvej základne\"\n  STR_CUSTOMINITIALBASE_DESC: \"Na začiatku novej hry vám umožní vytvoriť si vlastné usporiadanie zariadení prvej základne namiesto preddefinovaného rozvrhnutia. \"\n  STR_GLOBESEASONS: \"Realistické nasvietenie glóbusu\"\n  STR_GLOBESEASONS_DESC: \"Používa realistickejšiu projekciu slnečného svetla na Glóbus s ohľadom na osové naklonenie Zeme.\"\n  STR_PLAYINTRO: \"Prehraj intro\"\n  STR_PLAYINTRO_DESC: \"Ukáže úvodné intro pri zapnutí hry.\"\n  STR_SHOWMORESTATSININVENTORYVIEW: \"Zobraziť štatistiky v inventári\"\n  STR_SHOWMORESTATSININVENTORYVIEW_DESC: \"Zobrazí v inventári doplnkové informácie o vybranom vojakovi.\"\n  STR_SNEAKYAI: \"Prefíkaná AI\"\n  STR_SNEAKYAI_DESC: \"Umelá inteligencia sa bude snažiť vyhýbať odhaleniu hráčom, kedykoľvek to je možné.\"\n  STR_STRAFE: \"Alternatívne metódy pohybu\"\n  STR_STRAFE_DESC: \"Pri držaní klávesy CTRL umožní pohyb jednotky do strán, behanie, rovnako aj nezávislý pohyb veže tanku.\"\n  STR_BATTLEEXPLOSIONHEIGHT: \"Výška explózie\"\n  STR_BATTLEEXPLOSIONHEIGHT_DESC: \"Nastavenie spôsobu šírenia explózií do výšky.{NEWLINE}(Plocha: 0, Guľatá: 3)\"\n  STR_AUTOSAVE: \"Autouloženie\"\n  STR_AUTOSAVE_DESC: \"Automaticky uloží hru v zadaných intervaloch. Neplatí pre mód Ironman.\"\n  STR_AUTOSAVE_FREQUENCY: \"Frekvencia autouloženia\"\n  STR_AUTOSAVE_FREQUENCY_DESC: \"Počet ťahov, po ktorých sa hra automaticky uloží.\"\n  STR_ALLOWPSIONICCAPTURE: \"Povolenie psionického zajatia\"\n  STR_ALLOWPSIONICCAPTURE_DESC: \"Ovládnutie mysle zvyšných mimozemšťanov znamená víťazstvo a títo sa potom počítajú ako živí zajatci.\"\n  STR_ANYTIMEPSITRAINING: \"Umožni kedykoľvek nastúpiť do psionického tréningu\"\n  STR_ANYTIMEPSITRAINING_DESC: \"Umožní priradiť vojakov do psionického tréningu v ktorýkoľvek deň v mesiaci. Pamätajte však, že prvotný tréning trvá od 30 do 60 dní.\"\n  STR_SKIPNEXTTURNSCREEN: \"Preskočiť obrazovku \\\"Ďalšie kolo\\\"\"\n  STR_SKIPNEXTTURNSCREEN_DESC: \"Obrazovka oznámenia o ďalšom kole zmizne automaticky po krátkom čase.\"\n  STR_NOT_ENOUGH_SPACE: \"Nedostatok miesta!\"\n  STR_WEAPONSELFDESTRUCTION: \"Samozničenie mimozemských zbraní\"\n  STR_WEAPONSELFDESTRUCTION_DESC: \"Zbrane, ktoré majú mimozemšťania sa pri ich zabití zničia, podobne ako v hre XCOM 2012.\"\n  STR_RETAINCORPSES: \"Ponechať vypočutých mimozemšťanov\"\n  STR_RETAINCORPSES_DESC: \"Po \\\"preskúmaní\\\" živých mimozemšťanov sa ich telá objavia v skladoch na základni; tak ako v XCOM 2012.\"\n  STR_SAVE_VOXEL_VIEW: \"Ulož snímku obrazovky z pohladu prvej osoby\"\n  STR_RESERVE_TIME_UNITS_FOR_KNEEL: \"Rezervovať časové jednotky na kľaknutie\"\n  STR_EXPEND_ALL_TIME_UNITS: \"Použi všetky ostávajúce akčné body\"\n  STR_PSISTRENGTHEVAL: \"Vyhodnotenie Psionických schopností\"\n  STR_PSISTRENGTHEVAL_DESC: \"Vyhodnotí psionickú odolnosť všetkých vojakov až vtedy keď bude dokončený príslušný výskum.\"\n  STR_DISABLEAUTOEQUIP: \"Vypnúť automatické vybavovanie\"\n  STR_DISABLEAUTOEQUIP_DESC: \"Vypnúť automatické vybavovanie nových vojakov pred bojom\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT: \"Povoliť zlepšovanie psionickej odolnosti\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT_DESC: \"Psionická odolnosť vojakov sa môže zlepšovať skúsenosťami a tréningom.\"\n  STR_BATTLESMOOTHCAMERA: \"Plynulá kamera projektilu\"\n  STR_BATTLESMOOTHCAMERA_DESC: \"Kamera na mape bojiska ostane zacentrovaná na letiaci projektil.\"\n  STR_BATTLECONFIRMFIREMODE: \"Potvrďte mód streľby\"\n  STR_BATTLECONFIRMFIREMODE_DESC: \"Na potvrdenie streľby vyžaduje druhý klik na rovnaké políčko.\"\n  STR_SELECT_BASE_1: \"Zvoľ základňu 1\"\n  STR_SELECT_BASE_2: \"Zvoľ základňu 2\"\n  STR_SELECT_BASE_3: \"Zvoľ základňu 3\"\n  STR_SELECT_BASE_4: \"Zvoľ základňu 4\"\n  STR_SELECT_BASE_5: \"Zvoľ základňu 5\"\n  STR_SELECT_BASE_6: \"Zvoľ základňu 6\"\n  STR_SELECT_BASE_7: \"Zvoľ základňu 7\"\n  STR_SELECT_BASE_8: \"Zvoľ základňu 8\"\n  STR_VIDEO: \"VIDEO\"\n  STR_AUDIO: \"ZVUK\"\n  STR_BATTLESCAPE_UC: \"BOJISKO\"\n  STR_MODS_UC: \"MODY\"\n  STR_MODS: \"Mody\"\n  STR_DISPLAY_RESOLUTION: \"Rozlíšenie obrazovky\"\n  STR_DISPLAY_RESOLUTION_DESC: \"Mení rozlíšenie monitora. Rozlíšenie hry bude prispôsobené vybranému rozlíšeniu. Šípky prepínajú medzi podporovanými rozlíšeniami. Kliknite pre zadanie vlastného rozlíšenia.\"\n  STR_ORIGINAL: \"Originál [320x200]\"\n  STR_DISPLAY_MODE: \"Zobrazenie\"\n  STR_WINDOWED: \"V okne\"\n  STR_FULLSCREEN: \"Celá obrazovka\"\n  STR_BORDERLESS: \"Bez okrajov\"\n  STR_DISPLAY_LANGUAGE: \"Jazyk\"\n  STR_DISPLAY_LANGUAGE_DESC: \"Zmení jazyk textu v hre.\"\n  STR_DISPLAY_FILTER: \"Filter obrazovky\"\n  STR_DISPLAY_FILTER_DESC: \"Mení filter aplikovaný na okno hry.{NEWLINE}*vyžaduje hardvérovú akceleráciu OpenGL.\"\n  STR_DISPLAY_OPTIONS: \"Nastavenia obrazovky\"\n  STR_LETTERBOXED: \"Letterbox\"\n  STR_LETTERBOXED_DESC: \"Zväčší šírku obrazu tak, aby ostal zachovaný pôvodný pomer strán.\"\n  STR_RESIZABLE: \"Meniteľná\"\n  STR_LOCK_MOUSE: \"Zamknúť kurzor\"\n  STR_LOCK_MOUSE_DESC: \"Zabráni kurzoru myši opustiť okno hry. Nastavenie sa dá zmeniť kedykoľvek stlačením kombinácie Ctrl+G.\"\n  STR_FIXED_WINDOW_POSITION: \"Ukotvenie pozície okna\"\n  STR_FIXED_WINDOW_POSITION_DESC: \"Nastaviť pevné ukotvenie okna.\"\n  STR_DISPLAY_SET_WINDOW_POSITION: \"Nastaviť novú pozíciu pre základné okno.\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_X: \"Ľavý okraj nová X:\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_Y: \"Horný okraj nová Y:\"\n  STR_MUSIC_VOLUME: \"Hlasitosť hudby\"\n  STR_MUSIC_VOLUME_DESC: \"Mení hlasitosť hudby.\"\n  STR_SFX_VOLUME: \"Hlasitosť zvuku\"\n  STR_SFX_VOLUME_DESC: \"Mení hlasitosť zvukových efektov\"\n  STR_UI_VOLUME: \"Hlasitosť rozhrania\"\n  STR_UI_VOLUME_DESC: \"Mení hlasitosť zvukov používateľského rozhrania.\"\n  STR_SCROLL_SPEED: \"Rýchlosť posunu\"\n  STR_SCROLL_SPEED_GEO_DESC: \"Mení skrolovaciu rýchlosť glóbusu.\"\n  STR_SCROLL_SPEED_BATTLE_DESC: \"Mení rýchlosť posunu mapy.\"\n  STR_DOGFIGHT_SPEED: \"Rýchlosť vzduš. súbojov\"\n  STR_DOGFIGHT_SPEED_DESC: \"Nastavuje rýchlosť vzdušných súbojov medzi plavidlami X-Com a UFO. Pomalejšie rýchlosti môžu zvýšiť výkon hry na menej výkonných zariadeniach.\"\n  STR_CLOCK_SPEED: \"Rýchlosť hodín\"\n  STR_CLOCK_SPEED_DESC: \"Nastavuje rýchlosť hodín glóbusu. Pomalejšie rýchlosti môžu zvýšiť výkon hry na menej výkonných zariadeniach.\"\n  STR_GLOBE_DETAILS: \"Detaily glóbusu\"\n  STR_GLOBE_COUNTRIES: \"Krajiny\"\n  STR_GLOBE_COUNTRIES_DESC: \"Zobrazí financujúce štáty na glóbuse.\"\n  STR_GLOBE_RADARS: \"Radary\"\n  STR_GLOBE_RADARS_DESC: \"Zobrazí základný radarový dosah na glóbuse.\"\n  STR_GLOBE_FLIGHT_PATHS: \"Trajektória letu\"\n  STR_GLOBE_FLIGHT_PATHS_DESC: \"Zobrazuje trajektóriu letu plavidiel na glóbuse.\"\n  STR_CONTROLS_DESC: \"Ak chcete zmeniť skratku, kliknite na ňu a zadajte jej novú hodnotu.{NEWLINE}Pravým tlačidlom myši skratku deaktivujete. \"\n  STR_BASE_GAME: \"Základná hra\"\n  STR_MODS_TOOLTIP: \"Verzia {0}, autor: {1}.{NEWLINE}{2}\"\n  STR_EDGE_SCROLL: \"Posun pri okraji\"\n  STR_EDGE_SCROLL_DESC: \"Spúšť: Posunie mapu v prípade, že je na okraji obrazovky stlačené ľavé tlačítko myši.{NEWLINE}Auto: Posunie mapu, keď je kurzor na okraji obrazovky.\"\n  STR_TRIGGER_SCROLL: \"Na  tlačítko\"\n  STR_AUTO_SCROLL: \"Auto\"\n  STR_DRAG_SCROLL: \"Posun ťahaním\"\n  STR_DRAG_SCROLL_DESC: \"Posun mapy potiahnutím je možný vtedy ak je podržané špecifické tlačidlo myši.\"\n  STR_LEFT_MOUSE_BUTTON: \"Ľavé tlačidlo\"\n  STR_MIDDLE_MOUSE_BUTTON: \"Stredné tlačidlo\"\n  STR_RIGHT_MOUSE_BUTTON: \"Pravé tlačidlo\"\n  STR_FIRE_SPEED: \"Rýchlosť streľby\"\n  STR_FIRE_SPEED_DESC: \"Mení rýchlosť letu projektilov zo zbraní.\"\n  STR_PLAYER_MOVEMENT_SPEED: \"Rýchlosť pohybu hráča\"\n  STR_PLAYER_MOVEMENT_SPEED_DESC: \"Upravuje rýchlosť pohybuje hráčom ovládaných jednotiek.\"\n  STR_COMPUTER_MOVEMENT_SPEED: \"Rýchlosť pohybu AI\"\n  STR_COMPUTER_MOVEMENT_SPEED_DESC: \"Upravuje rýchlosť pohybu počítačom ovládaných jednotiek.\"\n  STR_PATH_PREVIEW: \"Zobrazenie krokov\"\n  STR_PATH_ARROWS: \"Šípky\"\n  STR_PATH_ARROWS_DESC: \"Kliknutie zobrazí cestu, po ktorej sa vaša jednotka bude presúvať k cieľu. Farba označuje následné možné úkony: Zelená - môže strielať a hýbať sa; Žltá - môže sa hýbať; Červená - nie je možný pohyb.\"\n  STR_PATH_TIME_UNIT_COST: \"Akčné body\"\n  STR_PATH_TIME_UNIT_COST_DESC: \"Kliknutím sa zobrazujú AB, ktoré jednotke ostanú po presune na cieľové miesto.\"\n  STR_USER_INTERFACE_OPTIONS: \"Nastavenia rozhrania\"\n  STR_TOOLTIPS: \"Popisy\"\n  STR_TOOLTIPS_DESC: \"Zobrazí popisy k ikonám na obrazovke bojiska.\"\n  STR_DEATH_NOTIFICATIONS: \"Oznámenie o smrti\"\n  STR_DEATH_NOTIFICATIONS_DESC: \"Zobrazí správu o úmrtí vždy keď jeden z vašich vojakov umrie.\"\n  STR_SHOW_FUNDS: \"Ukáž financovanie\"\n  STR_SHOW_FUNDS_DESC: \"Zobrazí aktuálne financie veďla hodín na obrazovke glóbusu.\"\n  STR_MISSION_GENERATOR: \"GENERÁTOR MISIÍ\"\n  STR_MAP_OPTIONS: \"NASTAVENIA MAPY\"\n  STR_ALIEN_OPTIONS: \"NASTAVENIA MIMOZEMŠŤANOV\"\n  STR_MAP_TERRAIN: \"Terén\"\n  STR_MAP_DARKNESS: \"Tma\"\n  STR_MAP_DEPTH: \"Hĺbka\"\n  STR_DIFFICULTY: \"Obťažnosť\"\n  STR_ALIEN_RACE: \"Druh\"\n  STR_ALIEN_TECH_LEVEL: \"Úroveň technológie\"\n  STR_RANDOMIZE: \"Náhodne\"\n  STR_OXCE_REQUIRED_QUESTION: \"Tento mod vyžaduje OpenXcom {0}. Aktivovať tento mod?\"\n  STR_RESTORE_DEFAULTS_QUESTION: \"Naozaj chceš obnoviť pôvodné nastavenia?\"\n  STR_DISPLAY_OPTIONS_CONFIRM: \"Chcete zachovať súčasné nastavenia zobrazenia?\"\n  STR_DISPLAY_OPTIONS_REVERT: \"Pôvodné nastavenia sa vrátia za 0:{0}\"\n  STR_MISSING_CONTENT_PROMPT: \"UPOZORNENIE:{SMALLLINE}Táto uložená pozícia je závislá na modoch, ktoré nie sú prítomné alebo aktivované. Chýbajúci obsah bude odstránený a môže spôsobiť neúspešné načítanie hry.{NEWLINE}Pokračovať?\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT: \"Ulož pripravené granáty\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT_DESC: \"Zapamätá si pripravenie (odistenie) granátu nastavené v inventári pri príprave pred bojom.\"\n  STR_NEWSEEDONLOAD: \"Podvádzanie s ukladaním hry\"\n  STR_NEWSEEDONLOAD_DESC: \"Pri nahraní hry sa vygeneruje nový základ pre výpočet náhodných čísiel, takže rovnaké akcie môžu viesť k rozdielnym výsledkom. Neplatí pre herný mód Ironman.\"\n  STR_CHANGEVALUEBYMOUSEWHEEL: \"Meníte hodnoty pomocou kolieska myši.\"\n  STR_CHANGEVALUEBYMOUSEWHEEL_DESC: \"Umožní používať koliesko myši na zvyšovanie/znižovanie hodnôt. \"\n  STR_BATTLEHAIRBLEACH: \"Vylepšený vzhľad vojakov\"\n  STR_BATTLEHAIRBLEACH_DESC: \"Mení grafiku vojakov na bojisku tak, aby výzor zodpovedal ich výzoru v inventári. \"\n  STR_DRAGSCROLLINVERT: \"Prevrátiť posúvanie ťahom\"\n  STR_DRAGSCROLLINVERT_DESC: \"Keď je táto možnosť aktivovaná, posúvanie funguje opačným smerom ako ťahanie myšou. \"\n  STR_BATTLESCAPE_SCALE: \"Rozlíšenie bojiska\"\n  STR_BATTLESCAPE_SCALE_DESC: \"Úprava veľkosti obrazovky bojiska založená buď na fixnom rozlíšení (natiahnutím) alebo fixnom priblížení (roztiahnutím).\"\n  STR_GEOSCAPE_SCALE: \"Rozlíšenie glóbusu\"\n  STR_GEOSCAPESCALE_SCALE_DESC: \"Úprava veľkosti obrazovky glóbusu založená buď na fixnom rozlíšení (natiahnutím) alebo fixnom priblížení (roztiahnutím).\"\n  STR_1_5X: \"480x300\"\n  STR_2X: \"640x400\"\n  STR_THIRD_DISPLAY: \"Celá plocha (3x zoom)\"\n  STR_HALF_DISPLAY: \"Celá plocha (2x zoom)\"\n  STR_FULL_DISPLAY: \"Celá plocha\"\n  STR_FPS_LIMIT: \"Limit FPS\"\n  STR_FPS_LIMIT_DESC: \"Obmedzuje množstvo obnovení obrazovky za sekundu, 0 bez obmedzenia. Ak je zapnuté OpenGL renderovanie, hra využíva namiesto toho Vsync.\"\n  STR_FPS_INACTIVE_LIMIT: \"FPS limit na pozadí\"\n  STR_FPS_INACTIVE_LIMIT_DESC: \"Limituje počet obnovení obrazovky za sekundu v prípade, že je OpenXcom minimalizovaný.\"\n  STR_NOALIENPANICMESSAGES: \"Zakázať informácie o panike mimozemšťanov\"\n  STR_NOALIENPANICMESSAGES_DESC: \"Nezobrazuj informácie o panike mimozemšťanov pokiaľ ich hráč nevidí.\"\n  STR_ALIENBLEEDING: \"Krvácanie mimozemšťanov\"\n  STR_ALIENBLEEDING_DESC: \"Dovoľuje spôsobiť smrteľné zranenia väčšine mimozemšťanov.\"\n  STR_FIELDPROMOTIONS: \"Povýšenie v poli\"\n  STR_FIELDPROMOTIONS_DESC: \"Iba vojaci prítomný na misii sú kandidátmi na povýšenie.\"\n  STR_MEETINGPOINT: \"Predvídať trajektóriu letu UFO\"\n  STR_MEETINGPOINT_DESC: \"Plavidlá poletia k predpokladanému miestu stretnutia s UFO na základe aktuálnej trajektórie letu UFO.\"\n  STR_IRONMAN: \"IRONMAN\"\n  STR_IRONMAN_DESC: \"Bez manuálneho ukladania\"\n  STR_SAVE_AND_ABANDON_GAME: \"ULOŽIŤ A OPUSTIŤ HRU\"\n  STR_MOD_UNSUCCESSFUL: \"Neúspešné načítanie modu\"\n  STR_NEW_SAVED_GAME_SLOT: \"<NOVÁ ULOŽENÁ POZÍCIA>\"\n  STR_AUTO_SAVE_GEOSCAPE_SLOT: \"<AUTOULOŽENIE GLÓBUSU>\"\n  STR_AUTO_SAVE_BATTLESCAPE_SLOT: \"<AUTOULOŽENIE BOJISKA>\"\n  STR_QUICK_SAVE_SLOT: \"<RÝCHLE ULOŽENIE>\"\n  STR_DISPLAY_MODE_DESC: \"Mení ako sa hra zobrazuje na obrazovke.\"\n  STR_PREFERRED_MUSIC_FORMAT: \"Formát hudby\"\n  STR_PREFERRED_MUSIC_FORMAT_DESC: \"Určuje preferovaný formát hudobných súborov, ak je k dispozícii viac ako jeden. {NEWLINE}POZNÁMKA: Prehrávanie MIDI môže vykazovať v systéme Windows chyby.\"\n  STR_PREFERRED_SFX_FORMAT: \"Formát zvuku\"\n  STR_PREFERRED_SFX_FORMAT_DESC: \"Určuje preferovaný formát zvuku, ak je k dispozícií viac ako jeden.\"\n  STR_PREFERRED_VIDEO_FORMAT: \"Formát videa\"\n  STR_PREFERRED_VIDEO_FORMAT_DESC: \"Určuje preferovaný formát videa, ak je k dispozícii viac ako jeden.\"\n  STR_PREFERRED_VIDEO_ANIMATION: \"Animácia\"\n  STR_PREFERRED_VIDEO_SLIDESHOW: \"Slideshow\"\n  STR_PREFERRED_FORMAT_AUTO: \"Automaticky\"\n  STR_CURRENT_FORMAT: \"Aktuálny formát: {0}\"\n  STR_SOUND_OPTIONS: \"Nastavenia zvuku\"\n  STR_BACKGROUND_MUTE: \"Stíšiť na pozadí\"\n  STR_BACKGROUND_MUTE_DESC: \"Stíši všetky zvuky, keď okno hry nie je aktívne.\"\n  STR_FORCE_FIRE: \"Ignorovať prekážku v dráhe strely\"\n  STR_FORCE_FIRE_DESC: \"Podržaním klávesu CTRL umožní vašim vojakom vystreliť bez ohľadu na prekážku v dráhe strely.\"\n  STR_NO_AUDIO_HARDWARE_DETECTED: \"Nenašiel sa zvukový hardvér\"\n  STR_MOUSEWHEEL_SPEED: \"Rýchlosť posunu kolieskom myši\"\n  STR_MOUSEWHEEL_SPEED_DESC: \"Nastavuje počet riadkov v zozname posunutých s každým pohybom kolieska myši. \"\n  STR_DISABLED: \"Vypnuté\"\n  STR_MAXIMIZE_INFO_SCREENS: \"Maximalizuj info obrazovky\"\n  STR_MAXIMIZE_INFO_SCREENS_DESC: \"Obrazovka inventára a niektoré ostatné obrazovky budú vždy zobrazené na celú plochu monitora nezávisle od nastavení veľkosti.\"\n  STR_DIARY: \"DENNÍK\"\n  STR_KILLED: \"ZABITÝ\"\n  STR_STUNNED: \"OMRÁČENÝ\"\n  STR_PANICKED: \"SPANIKÁRENÝ\"\n  STR_MINDCONTROLLED: \"OVLÁDNUTÝ\"\n  STR_REGION_UNKNOWN: \"Nezverejnené\"\n  STR_WEAPON_UNKNOWN: \"Improvizácia\"\n  STR_UNKNOWN: \"Nevedno\"\n  STR_VICTORY: \"Víťazstvo\"\n  STR_DEFEAT: \"Porážka\"\n  STR_NO_RECORD: \"Bez záznamu\"\n  STR_HUMAN: \"Človek\"\n  STR_FRIENDLY: \"Priateľ\"\n  STR_HOSTILE: \"Nepriateľ\"\n  STR_NEUTRAL: \"Nestranný\"\n  STR_RATING_UC: \"HODNOTENIE\"\n  STR_LOCATION: \"POLOHA> {ALT}{0}\"\n  STR_DAYLIGHT_TYPE: \"ČAS> {ALT}{0}\"\n  STR_RACE_TYPE: \"DRUH> {ALT}{0}\"\n  STR_DAY: \"Deň\"\n  STR_NIGHT: \"Noc\"\n  STR_DAYS_WOUNDED: \"DNI V ŠPITÁLI> {ALT}{0}\"\n  STR_COMBAT: \"BOJ\"\n  STR_PERFORMANCE: \"VÝKONNOSŤ\"\n  STR_NEUTRALIZATIONS_BY_RACE: \"ZNEŠKODNENIA PODĽA RASY\"\n  STR_NEUTRALIZATIONS_BY_RANK: \"ZNEŠKODNENIA PODĽA HODNOSTI\"\n  STR_NEUTRALIZATIONS_BY_WEAPON: \"ZNEŠKODNENIA PODĽA ZBRANE\"\n  STR_MISSIONS_BY_LOCATION: \"MISIE PODĽA POLOHY\"\n  STR_MISSIONS_BY_TYPE: \"MISIE PODĽA TYPU\"\n  STR_MISSIONS_BY_UFO: \"MISIE PODĽA UFO\"\n  STR_SCORE_VALUE: \"SKÓRE> {ALT}{0}\"\n  STR_WINS: \"VÝHRY> {ALT}{0}\"\n  STR_STUNS: \"OMRÁČENIA> {ALT}{0}\"\n  STR_PANICKS: \"SPANIKÁRENIA> {ALT}{0}\"\n  STR_MINDCONTROLS: \"OVLÁDNUTIA> {ALT}{0}\"\n  STR_AWARDS: \"VYZNAMENANIA\"\n  STR_COMMENDATIONS_UC: \"UZNANIA\"\n  STR_COMMENDATIONS: \"Uznania\"\n  STR_MEDALS: \"MEDAILY\"\n  STR_LOST_IN_SERVICE: \"PADLI V SLUŽBE\"\n  STR_MEDAL_NAME: \"Názov medaily\"\n  STR_MEDAL_AWARD_LEVEL: \"Úroveň vyznamenania\"\n  STR_MEDAL_DECOR_LEVEL: \"Úroveň dekorácie\"\n  STR_AWARD_0: \"Prvé ocenenie\"\n  STR_AWARD_1: \"Druhé ocenenie\"\n  STR_AWARD_2: \"Tretie ocenenie\"\n  STR_AWARD_3: \"Štvrté ocenenie\"\n  STR_AWARD_4: \"Piate ocenenie\"\n  STR_AWARD_5: \"Šieste ocenenie\"\n  STR_AWARD_6: \"Siedme ocenenie\"\n  STR_AWARD_7: \"Ôsme ocenenie\"\n  STR_AWARD_8: \"Deviate ocenenie\"\n  STR_AWARD_9: \"Desiate ocenenie\"\n  STR_AWARD_DECOR_0: \"Žiadne\"\n  STR_AWARD_DECOR_1: \"Prvá bronzová frčka\"\n  STR_AWARD_DECOR_2: \"Druhá bronzová frčka\"\n  STR_AWARD_DECOR_3: \"Tretia bronzová frčka\"\n  STR_AWARD_DECOR_4: \"Prvá strieborná frčka\"\n  STR_AWARD_DECOR_5: \"Druhá strieborná frčka\"\n  STR_AWARD_DECOR_6: \"Tretia strieborná frčka\"\n  STR_AWARD_DECOR_7: \"Prvá zlatá frčka\"\n  STR_AWARD_DECOR_8: \"Druhá zlatá frčka\"\n  STR_AWARD_DECOR_9: \"Tretia zlatá frčka\"\n  STR_KILLED_IN_ACTION_MALE: \"ZABITÝ V AKCII\"\n  STR_KILLED_IN_ACTION_FEMALE: \"ZABITÁ V AKCII\"\n  STR_MISSING_IN_ACTION_MALE: \"STRATENÝ V AKCII\"\n  STR_MISSING_IN_ACTION_FEMALE: \"STRATENÁ V AKCII\"\n  STR_AVERAGE_MONTHLY_RATING: \"Priemerné mesačné hodnotenie\"\n  STR_TOTAL_INCOME: \"Celkový príjem\"\n  STR_TOTAL_EXPENDITURE: \"Celkové výdavky\"\n  STR_MISSIONS_WON: \"Ukončené misie\"\n  STR_MISSIONS_LOST: \"Neúspešné misie\"\n  STR_NIGHT_MISSIONS: \"Nočné misie\"\n  STR_BEST_RATING: \"Najlepšie hodnotenie misie\"\n  STR_WORST_RATING: \"Najhoršie hodnotenie misie\"\n  STR_ALIEN_KILLS: \"Zabitých mimozemšťanov\"\n  STR_ALIEN_CAPTURES: \"Zajatých mimozemšťanov\"\n  STR_FRIENDLY_KILLS: \"Incidentov priateľskej streľby\"\n  STR_AVERAGE_ACCURACY: \"Priemerná presnosť\"\n  STR_WEAPON_MOST_KILLS: \"Najefektívnejšia zbraň\"\n  STR_ALIEN_MOST_KILLS: \"Najsmrteľnejší mimozemšťan\"\n  STR_LONGEST_SERVICE: \"Najdlhšie v službe\"\n  STR_TOTAL_DAYS_WOUNDED: \"Dni na maródke\"\n  STR_COUNTRIES_LOST: \"Infiltrované krajiny\"\n  STR_TOTAL_TERROR_SITES: \"Teroristických útokov\"\n  STR_TOTAL_BASES: \"Postavených základní\"\n  STR_TOTAL_CRAFT: \"Vlastnených lietadiel\"\n  STR_TOTAL_SCIENTISTS: \"Najatých vedcov\"\n  STR_TOTAL_ENGINEERS: \"Najatých inžinierov\"\n  STR_TOTAL_RESEARCH: \"Ukončených výskumov\"\n  STR_DIARY_ACCURACY: \"PRESNOSŤ> {ALT}{0}%\"\n  STR_STATISTICS: \"Štatistika\"\n  STR_STATS: \"STATS\"\n  STR_TIME_UNITS_ABBREVIATION: \"AB\"\n  STR_STAMINA_ABBREVIATION: \"VÝD\"\n  STR_HEALTH_ABBREVIATION: \"ZDR\"\n  STR_BRAVERY_ABBREVIATION: \"UDA\"\n  STR_REACTIONS_ABBREVIATION: \"REA\"\n  STR_FIRING_ACCURACY_ABBREVIATION: \"PRE\"\n  STR_THROWING_ACCURACY_ABBREVIATION: \"VRH\"\n  STR_STRENGTH_ABBREVIATION: \"SIL\"\n  STR_MELEE_ACCURACY_ABBREVIATION: \"BOJ\"\n  STR_FOLDERS: \"PRIEČINKY\"\n  STR_DATA_FOLDER: \"Dátový priečinok (súbory pôvodnej hry)\"\n  STR_USER_FOLDER: \"Používateľský priečinok (mody, logy)\"\n  STR_SAVE_FOLDER: \"Priečinok na ukladanie (sejvy, screenshoty)\"\n  STR_CONFIG_FOLDER: \"Konfiguračný priečinok (options.cfg)\"\n  STR_DATA_FOLDER_DESC_1: \"V tomto priečinku OpenXcom očakáva súbory z pôvodnej hry (UFO a/alebo TFTD).\"\n  STR_DATA_FOLDER_DESC_2: \"Priečinok 'common' obsahuje interné súbory OpenXcom-u. Priečinok 'standard' obsahuje mody štandardne dodávané spolu s OpenXcom-om.\"\n  STR_USER_FOLDER_DESC: \"Tu nájdete súbor s logmi ('openxcom.log'). Taktiež sem patria všetky stiahnuté mody (do podpriečinka 'mods').\"\n  STR_SAVE_FOLDER_DESC: \"Tu nájdete vaše uložené hry. Taktiež sa tu nachádza súbor nastavení generátora bitiek ('battle.cfg').\"\n  STR_CONFIG_FOLDER_DESC: \"Tu nájdete súbor s nastaveniami OpenXcom-u ('options.cfg'). Väčšinou je to rovnaký priečinok ako používateľský priečinok.\"\n"
  },
  {
    "path": "bin/common/Language/sv.yml",
    "content": "sv:\n  STR_OPENXCOM: \"OpenXcom\"\n  STR_NEW_GAME: \"Nytt spel\"\n  STR_LOAD_SAVED_GAME: \"Läs in spel\"\n  STR_SELECT_DIFFICULTY_LEVEL: \"Välj svårighetsgrad\"\n  STR_1_BEGINNER: \"1> Nybörjare\"\n  STR_2_EXPERIENCED: \"2> Erfaren\"\n  STR_3_VETERAN: \"3> Veteran\"\n  STR_4_GENIUS: \"4> Geni\"\n  STR_5_SUPERHUMAN: \"5> Övermänsklig\"\n  STR_TIME: \"Tid\"\n  STR_DATE: \"Datum\"\n  STR_SELECT_GAME_TO_LOAD: \"Välj spel att läsa in\"\n  STR_SELECT_SAVE_POSITION: \"Välj sparposition\"\n  STR_GAME_OPTIONS: \"SPELINSTÄLLNINGAR\"\n  STR_LOAD_GAME: \"LÄS IN SPEL\"\n  STR_SAVE_GAME: \"SPARA SPEL\"\n  STR_ABANDON_GAME: \"ÖVERGE SPEL\"\n  STR_ABANDON_GAME_QUESTION: \"ÖVERGE SPEL?\"\n  STR_QUIT: \"Avsluta\"\n  STR_SAVING_GAME: \"Sparar spel\"\n  STR_LOADING_GAME: \"Läser in spel\"\n  STR_NO_SAVED_GAME_PRESENT: \"Inga sparade spel\"\n  STR_LOAD_UNSUCCESSFUL: \"Inläsning misslyckades\"\n  STR_SAVE_UNSUCCESSFUL: \"Sparning misslyckades\"\n  STR_LOAD_SUCCESSFUL: \"Inläsning lyckades\"\n  STR_SAVE_SUCCESSFUL: \"Sparning lyckades!\"\n  STR_DELETE: \"TA BORT\"\n  STR_DELETE_UNSUCCESSFUL: \"Borttagning misslyckades\"\n  STR_IS_IT_OK_TO_DELETE_THE_SAVED_GAME: \"Är du säker på att du vill radera det sparade spelet?\"\n  STR_ORIGINAL_XCOM: \"Original X-Com\"\n  STR_LOADING: \"Läser in...\"\n  STR_DETAILS: \"DETALJER>{ALT}{0}\"\n  STR_NEW_BATTLE: \"Ny strid\"\n  STR_OPTIONS: \"Alternativ\"\n  STR_RIGHT_CLICK_TO_DELETE: \"Högerklicka för att radera.\"\n  STR_RESTORE_DEFAULTS: \"Återställ standardinställningar\"\n  STR_CONTROLS: \"KONTROLLER\"\n  STR_GENERAL: \"Allmänt\"\n  STR_GEOSCAPE: \"Geovy\"\n  STR_BATTLESCAPE: \"Stridsvy\"\n  STR_SCREENSHOT: \"Skärmbild\"\n  STR_FPS_COUNTER: \"FPS-räknare\"\n  STR_ROTATE_LEFT: \"Rotera vänster\"\n  STR_ROTATE_RIGHT: \"Rotera höger\"\n  STR_ROTATE_UP: \"Rotera upp\"\n  STR_ROTATE_DOWN: \"Rotera ner\"\n  STR_ZOOM_IN: \"Zooma in\"\n  STR_ZOOM_OUT: \"Zooma ut\"\n  STR_TOGGLE_COUNTRY_DETAIL: \"Växla landsdetaljer\"\n  STR_TOGGLE_RADAR_RANGES: \"Växla radarräckvidder\"\n  STR_SCROLL_LEFT: \"Rulla vänster\"\n  STR_SCROLL_RIGHT: \"Rulla höger\"\n  STR_SCROLL_UP: \"Rulla uppåt\"\n  STR_SCROLL_DOWN: \"Rulla neråt\"\n  STR_UNIT_LEVEL_ABOVE: \"Flytta enhet till nivå ovan\"\n  STR_UNIT_LEVEL_BELOW: \"Flytta enhet till nivå under\"\n  STR_VIEW_LEVEL_ABOVE: \"Visa nivå över\"\n  STR_VIEW_LEVEL_BELOW: \"Visa nivå under\"\n  STR_CENTER_SELECTED_UNIT: \"Centrera vald enhet\"\n  STR_PREVIOUS_UNIT: \"Välj föregående enhet\"\n  STR_NEXT_UNIT: \"Välj nästa enhet\"\n  STR_DESELECT_UNIT: \"Välj inte enheten igen\"\n  STR_USE_LEFT_HAND: \"Använd föremål i vänster hand\"\n  STR_USE_RIGHT_HAND: \"Använd föremål i höger hand\"\n  STR_INVENTORY: \"Inventarie\"\n  STR_MINIMAP: \"Minikarta\"\n  STR_MULTI_LEVEL_VIEW: \"Visa flera nivåer\"\n  STR_END_TURN: \"Avsluta runda\"\n  STR_ABORT_MISSION: \"Avbryt uppdrag\"\n  STR_UNIT_STATS: \"Enhetsstatistik\"\n  STR_KNEEL: \"Knästående ställning\"\n  STR_RELOAD: \"Ladda om\"\n  STR_TOGGLE_PERSONAL_LIGHTING: \"Ställ in Personlig Ljussättning\"\n  STR_DONT_RESERVE_TIME_UNITS: \"Reservera inte TE\"\n  STR_RESERVE_TIME_UNITS_FOR_SNAP_SHOT: \"Reservera TE för snabbskott\"\n  STR_RESERVE_TIME_UNITS_FOR_AIMED_SHOT: \"Reservera TE för välriktat skott\"\n  STR_RESERVE_TIME_UNITS_FOR_AUTO_SHOT: \"Reservera TE för automateld\"\n  STR_CENTER_ON_ENEMY_1: \"Centrera på Fiende 1\"\n  STR_CENTER_ON_ENEMY_2: \"Centrera på Fiende 2\"\n  STR_CENTER_ON_ENEMY_3: \"Centrera på Fiende 3\"\n  STR_CENTER_ON_ENEMY_4: \"Centrera på Fiende 4\"\n  STR_CENTER_ON_ENEMY_5: \"Centrera på Fiende 5\"\n  STR_CENTER_ON_ENEMY_6: \"Centrera på Fiende 6\"\n  STR_CENTER_ON_ENEMY_7: \"Centrera på Fiende 7\"\n  STR_CENTER_ON_ENEMY_8: \"Centrera på Fiende 8\"\n  STR_CENTER_ON_ENEMY_9: \"Centrera på Fiende 9\"\n  STR_CENTER_ON_ENEMY_10: \"Centrera på Fiende 10\"\n  STR_CREATE_INVENTORY_TEMPLATE: \"Skapa inventariemall\"\n  STR_APPLY_INVENTORY_TEMPLATE: \"Tillämpa inventariemall\"\n  STR_CLEAR_INVENTORY: \"Töm inventarier\"\n  STR_AUTO_EQUIP: \"Auto-utrusta\"\n  STR_QUICK_SAVE: \"Snabbsparning\"\n  STR_QUICK_LOAD: \"Snabbinläsning\"\n  STR_ADVANCED: \"AVANCERAT\"\n  STR_AGGRESSIVERETALIATION: \"Aggressiv vedergällning\"\n  STR_AGGRESSIVERETALIATION_DESC: \"UFO:n försöker alltid lokalisera din bas, oberoende vilket uppdrag de har.\"\n  STR_STORAGELIMITSENFORCED: \"Förvaringsbegränsning för insamlade föremål\"\n  STR_STORAGELIMITSENFORCED_DESC: \"Begränsar antalet levande utomjordingar och främmande artefakter som samlats in från uppdrag beroende på utrymmet i utomjordingsförvaringen respektive lagerutrymme.\"\n  STR_CANSELLLIVEALIENS: \"Försäljning av levande utomjording\"\n  STR_CANSELLLIVEALIENS_DESC: \"Tillåter försäljning av levande utomjordingar, rekommenderas när begränsade förvaringsmöjligheter är aktiverat.\"\n  STR_ALLOWBUILDINGQUEUE: \"Tillåt byggkö\"\n  STR_ALLOWBUILDINGQUEUE_DESC: \"Nya anläggningar kan placeras bredvid ofärdigbyggda.\"\n  STR_BATTLEAUTOEND: \"Avsluta strider automatiskt\"\n  STR_BATTLEAUTOEND_DESC: \"Strider avslutas automatisk när den sista fienden är neutraliserad.\"\n  STR_BATTLEINSTANTGRENADE: \"Direkta granater\"\n  STR_BATTLEINSTANTGRENADE_DESC: \"Granater inställda på att sprängas på 0 rundor sprängs omedelbart när de slängs, istället för i slutet av rundan.\"\n  STR_BATTLEUFOEXTENDERACCURACY: \"Träffsäkerhet för UFO Extender\"\n  STR_BATTLEUFOEXTENDERACCURACY_DESC: \"Träffsäkerheten för skott minskar efter ett visst avstånd beroende på eldgivningstyp. Träffjusteringen visas på muspekaren.\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE: \"Luftburna överföringar\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE_DESC: \"Flygfarkoster kan bli överförda under pågående flygningar.\"\n  STR_CRAFTLAUNCHALWAYS: \"Tvinga farkost att lyfta\"\n  STR_CRAFTLAUNCHALWAYS_DESC: \"Farkoster kan starta även när de inte är fulltankade eller helt reparerade.\"\n  STR_CUSTOMINITIALBASE: \"Anpassad startbas\"\n  STR_CUSTOMINITIALBASE_DESC: \"När du påbörjar ett nytt spel kan du placera ut dina basanläggningar själv istället för att ha den vanliga layouten.\"\n  STR_GLOBESEASONS: \"Realistisk belysning av jordgloben\"\n  STR_GLOBESEASONS_DESC: \"Använder mer realistisk projektion av solljus i Geovyn beroende på Jordens axellutning.\"\n  STR_PLAYINTRO: \"Spela intro\"\n  STR_PLAYINTRO_DESC: \"Visa introfilmen vid start.\"\n  STR_SHOWMORESTATSININVENTORYVIEW: \"Inventariestatistik\"\n  STR_SHOWMORESTATSININVENTORYVIEW_DESC: \"Visa extra information angående den valda soldaten i inventarieskärmen.\"\n  STR_SNEAKYAI: \"Smygande AI\"\n  STR_SNEAKYAI_DESC: \"AI:n undviker att visa sig för spelaren närhelst den kan.\"\n  STR_STRAFE: \"Alternativ förflyttningsmetod\"\n  STR_STRAFE_DESC: \"Tillåter sidoförflyttning och språng för soldater samt oberoende riktning på stridvagnars kanontorn genom att hålla ner CTRL-knappen.\"\n  STR_BATTLEEXPLOSIONHEIGHT: \"Explosionshöjd\"\n  STR_BATTLEEXPLOSIONHEIGHT_DESC: \"Ändra hur långt höjdmässigt explosioner kan spridas.{NEWLINE}(Platt: 0, Runtom: 3)\"\n  STR_AUTOSAVE: \"Automatiskt sparläge\"\n  STR_AUTOSAVE_DESC: \"Spelet sparas automatiskt vid specificerade intervaller. Inte tillämpligt i Ironman Mode.\"\n  STR_AUTOSAVE_FREQUENCY: \"Frekvens för autosparning\"\n  STR_AUTOSAVE_FREQUENCY_DESC: \"Antalet rundor efter vilka spelet automatiskt sparas.\"\n  STR_ALLOWPSIONICCAPTURE: \"Tillåt psi-infångst\"\n  STR_ALLOWPSIONICCAPTURE_DESC: \"Att tankekontrollera alla återstående utomjordingar resulterar i seger samt att de räknas som infångade.\"\n  STR_ANYTIMEPSITRAINING: \"Psionisk träning när som helst\"\n  STR_ANYTIMEPSITRAINING_DESC: \"Tillåter att tilldela soldater psionisk träning vid valfritt tillfälle under månaden. Kom ihåg att första träningstillfället kan ta 30 till 60 dagar.\"\n  STR_SKIPNEXTTURNSCREEN: \"Hoppa över \\\"Nästa runda\\\"-skärmen\"\n  STR_SKIPNEXTTURNSCREEN_DESC: \"\\\"Nästa runda\\\"-skärmen växlar framåt automatiskt efter en kort tids väntan.\"\n  STR_NOT_ENOUGH_SPACE: \"Inte tillräckligt med utrymme!\"\n  STR_WEAPONSELFDESTRUCTION: \"Självdestruktion av utomjordiska vapen\"\n  STR_WEAPONSELFDESTRUCTION_DESC: \"Vapen burna av utomjordingar självförstörs om deras ägare omkommer, som i XCOM 2012.\"\n  STR_RETAINCORPSES: \"Håll kvar förhörd utomjording\"\n  STR_RETAINCORPSES_DESC: \"Efter att \\\"forskning\\\" utförts på levande utomjord behålls kroppen i basens förråd som i XCOM 2012.\"\n  STR_SAVE_VOXEL_VIEW: \"Spara skärmbild som förstaperson\"\n  STR_RESERVE_TIME_UNITS_FOR_KNEEL: \"Reservera TE för knäställning\"\n  STR_EXPEND_ALL_TIME_UNITS: \"Använd alla kvarvarande TE\"\n  STR_PSISTRENGTHEVAL: \"Utvärdering av Psi-styrka\"\n  STR_PSISTRENGTHEVAL_DESC: \"Utvärderar de psioniska styrkorna hos alla soldater efter att tillämplig forskning slutförts.\"\n  STR_DISABLEAUTOEQUIP: \"Inaktivera automatisk utrustning\"\n  STR_DISABLEAUTOEQUIP_DESC: \"Inaktivera automatisk utrustning för nya soldater innan strid.\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT: \"TIllåt förbättringar av Psi-styrka\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT_DESC: \"Soldatens psioniska styrka kan förbättras genom användning eller träning.\"\n  STR_BATTLESMOOTHCAMERA: \"Mjuk skottkamera\"\n  STR_BATTLESMOOTHCAMERA_DESC: \"Centrerar stridsvyskameran på projektiler under dess färd.\"\n  STR_BATTLECONFIRMFIREMODE: \"Bekräfta eld-läge\"\n  STR_BATTLECONFIRMFIREMODE_DESC: \"Skjutorder kräver två musklick på samma ruta för att utföras.\"\n  STR_SELECT_BASE_1: \"Välj Bas 1\"\n  STR_SELECT_BASE_2: \"Välj Bas 2\"\n  STR_SELECT_BASE_3: \"Välj Bas 3\"\n  STR_SELECT_BASE_4: \"Välj Bas 4\"\n  STR_SELECT_BASE_5: \"Välj Bas 5\"\n  STR_SELECT_BASE_6: \"Välj Bas 6\"\n  STR_SELECT_BASE_7: \"Välj Bas 7\"\n  STR_SELECT_BASE_8: \"Välj Bas 8\"\n  STR_VIDEO: \"VIDEO\"\n  STR_AUDIO: \"LJUD\"\n  STR_BATTLESCAPE_UC: \"STRIDSVY\"\n  STR_MODS_UC: \"MODDAR\"\n  STR_MODS: \"Moddar\"\n  STR_DISPLAY_RESOLUTION: \"Skärmupplösning\"\n  STR_DISPLAY_RESOLUTION_DESC: \"Ändrar upplösningen på skärmen, spelets upplösning kommer ändras för att passa. Pilar byter mellan upplösningar som stöds. Klicka för att lägga in en egen upplösning.\"\n  STR_ORIGINAL: \"Original\"\n  STR_DISPLAY_MODE: \"Skärmläge\"\n  STR_WINDOWED: \"Fönster\"\n  STR_FULLSCREEN: \"Helskärm\"\n  STR_BORDERLESS: \"Ramlös\"\n  STR_DISPLAY_LANGUAGE: \"Visningsspråk\"\n  STR_DISPLAY_LANGUAGE_DESC: \"Ändrar språket i spelets text.\"\n  STR_DISPLAY_FILTER: \"Skärmfilter\"\n  STR_DISPLAY_FILTER_DESC: \"Ändrar filtret på skärmen.{NEWLINE}*kräver OpenGL hårdvaruacceleration\"\n  STR_DISPLAY_OPTIONS: \"Skärmalternativ\"\n  STR_LETTERBOXED: \"Letterboxed\"\n  STR_LETTERBOXED_DESC: \"Tillämpar letterboxes för att behålla originalets bildförhållande.\"\n  STR_RESIZABLE: \"Justerbar\"\n  STR_LOCK_MOUSE: \"Fånga mus\"\n  STR_LOCK_MOUSE_DESC: \"Gör att muspekaren inte kan lämna spelfönstret. Aktivera med Ctrl+G när som helst.\"\n  STR_FIXED_WINDOW_POSITION: \"Fast fönsterposition\"\n  STR_FIXED_WINDOW_POSITION_DESC: \"Ställ in fast position för fönster.\"\n  STR_DISPLAY_SET_WINDOW_POSITION: \"Ställ in ny fast fönsterposition.\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_X: \"Vänstra kantens nya X:\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_Y: \"Övre kantens nya Y:\"\n  STR_MUSIC_VOLUME: \"Musikvolym\"\n  STR_MUSIC_VOLUME_DESC: \"Ändrar volymen på bakgrundsmusiken.\"\n  STR_SFX_VOLUME: \"Ljudeffektsvolym\"\n  STR_SFX_VOLUME_DESC: \"Ändrar ljudeffekternas volym.\"\n  STR_UI_VOLUME: \"Gränssnittsvolym\"\n  STR_UI_VOLUME_DESC: \"Ändrar volymen på gränssnittsljud.\"\n  STR_SCROLL_SPEED: \"Rullhastighet\"\n  STR_SCROLL_SPEED_GEO_DESC: \"Ändrar rotationshastigheten på globen.\"\n  STR_SCROLL_SPEED_BATTLE_DESC: \"Ändrar förflyttningshastigheten på kartan.\"\n  STR_DOGFIGHT_SPEED: \"Luftstridshastighet\"\n  STR_DOGFIGHT_SPEED_DESC: \"Ändrar hastigheten på luftstrider mellan flygfarkoster och UFOn. Långsammare hastigheter kan förbättra spelets prestanda på långsammare användarenheter.\"\n  STR_CLOCK_SPEED: \"Klockhastighet\"\n  STR_CLOCK_SPEED_DESC: \"Ändrar hastigheten på Geovyns klocka. Lägre hastighet kan öka prestandan på långsammare spelenheter.\"\n  STR_GLOBE_DETAILS: \"Globdetaljer\"\n  STR_GLOBE_COUNTRIES: \"Länder\"\n  STR_GLOBE_COUNTRIES_DESC: \"Visar finansierande länder på jordgloben.\"\n  STR_GLOBE_RADARS: \"Radar\"\n  STR_GLOBE_RADARS_DESC: \"Visar basers radarområden på jordgloben.\"\n  STR_GLOBE_FLIGHT_PATHS: \"Flygvägar\"\n  STR_GLOBE_FLIGHT_PATHS_DESC: \"Visar farkosters flygrutter på jordgloben.\"\n  STR_CONTROLS_DESC: \"Vänsterklicka en genväg och tryck på en knapp för att ändra den.{NEWLINE}Högeklicka en genväg för att stänga av den.\"\n  STR_BASE_GAME: \"Basspel\"\n  STR_MODS_TOOLTIP: \"Version {0} av {1}.{NEWLINE}{2}\"\n  STR_EDGE_SCROLL: \"Kantrullning\"\n  STR_EDGE_SCROLL_DESC: \"Utlösare: Rulla kartan när vänstra musknappen hålls ner medan muspekaren rör vid en skärmkant.{NEWLINE}Auto: Rulla kartan när muspekaren flyttas till skärmkanten.\"\n  STR_TRIGGER_SCROLL: \"Utlösare\"\n  STR_AUTO_SCROLL: \"Auto\"\n  STR_DRAG_SCROLL: \"Dragrullning\"\n  STR_DRAG_SCROLL_DESC: \"Rullar kartan när den angivna musknappen hålls ner och musen dras.\"\n  STR_LEFT_MOUSE_BUTTON: \"Vänsterknapp\"\n  STR_MIDDLE_MOUSE_BUTTON: \"Mittenknapp\"\n  STR_RIGHT_MOUSE_BUTTON: \"Högerknapp\"\n  STR_FIRE_SPEED: \"Eldhastighet\"\n  STR_FIRE_SPEED_DESC: \"Ändrar hastigheten för vapenprojektiler.\"\n  STR_PLAYER_MOVEMENT_SPEED: \"Spelarens förflyttning\"\n  STR_PLAYER_MOVEMENT_SPEED_DESC: \"Ändrar förflyttningshastigheten på spelarens enheter.\"\n  STR_COMPUTER_MOVEMENT_SPEED: \"AI:ns förflyttning\"\n  STR_COMPUTER_MOVEMENT_SPEED_DESC: \"Ändrar förflyttningshastigheten på datorkontrollerade enheter.\"\n  STR_PATH_PREVIEW: \"Förhandsvisa väg\"\n  STR_PATH_ARROWS: \"Pilar\"\n  STR_PATH_ARROWS_DESC: \"Ett klick visar vägen din enhet kommer ta till destinationen. Färgen visar tillgängliga handlingar: Grön - kan gå och skjuta; Gul - kan gå; Röd - kan inte gå.\"\n  STR_PATH_TIME_UNIT_COST: \"Tidsenheter (TE)\"\n  STR_PATH_TIME_UNIT_COST_DESC: \"Klicka för att visa tidsenheter din soldat eller stridsvagn kommer ha kvar efter förflyttning.\"\n  STR_USER_INTERFACE_OPTIONS: \"Gränssnittsalternativ\"\n  STR_TOOLTIPS: \"Knappinfo\"\n  STR_TOOLTIPS_DESC: \"Visar hjälprutor för Stridsvyns knappar.\"\n  STR_DEATH_NOTIFICATIONS: \"Dödsaviseringar\"\n  STR_DEATH_NOTIFICATIONS_DESC: \"Visa avisering varje gång en av dina soldater dör.\"\n  STR_SHOW_FUNDS: \"Visa ekonomi\"\n  STR_SHOW_FUNDS_DESC: \"Visar dina finansiella tillgångar bredvid Geovyns klocka.\"\n  STR_MISSION_GENERATOR: \"UPPDRAGSGENERATOR\"\n  STR_MAP_OPTIONS: \"KARTALTERNATIV\"\n  STR_ALIEN_OPTIONS: \"UTOMJORDINGSALTERNATIV\"\n  STR_MAP_TERRAIN: \"Terräng\"\n  STR_MAP_DARKNESS: \"Mörker\"\n  STR_MAP_DEPTH: \"Djup\"\n  STR_DIFFICULTY: \"Svårighetsgrad\"\n  STR_ALIEN_RACE: \"Ras\"\n  STR_ALIEN_TECH_LEVEL: \"Tekniknivå\"\n  STR_RANDOMIZE: \"Slumpa\"\n  STR_OXCE_REQUIRED_QUESTION: \"Denna modifikation kräver OpenXcom {0} för att kunna köras korrekt. Aktivera denna modifiering?\"\n  STR_RESTORE_DEFAULTS_QUESTION: \"Är du säker på att du vill återställa standardinställningarna?\"\n  STR_DISPLAY_OPTIONS_CONFIRM: \"Vill du behålla de nuvarande grafikinställningarna? \"\n  STR_DISPLAY_OPTIONS_REVERT: \"Återgår inom 0:{0}\"\n  STR_MISSING_CONTENT_PROMPT: \"VARNING!{SMALLLINE}Denna sparning använder modifieringar som är otillgängliga. Otillgängligt material kommer tas bort och spelet kan misslyckas med att läsas in.{NEWLINE}Fortsätt?\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT: \"Spara förapterade granater\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT_DESC: \"Sparar granater som osäkrats under förberedelseinventariet i soldatens utrustningslayout.\"\n  STR_NEWSEEDONLOAD: \"Sparskumning\"\n  STR_NEWSEEDONLOAD_DESC: \"När ett spel läses in slumpas nummergeneratorns värde för handlingar, så samma handling kan få olika utgångar varje gång samma sparning laddas om. Inte tillämpligt på Ironman-läget.\"\n  STR_CHANGEVALUEBYMOUSEWHEEL: \"Ändra värden med mushjulet\"\n  STR_CHANGEVALUEBYMOUSEWHEEL_DESC: \"Tillåter dig att ändra värden med mushjulet med denna mängd för varje dragning.\"\n  STR_BATTLEHAIRBLEACH: \"Förbättrade soldatmodeller\"\n  STR_BATTLEHAIRBLEACH_DESC: \"Ändrar soldaternas stridsvymodeller för att matcha deras utseende i inventariet.\"\n  STR_DRAGSCROLLINVERT: \"Inverterad drag-rullning.\"\n  STR_DRAGSCROLLINVERT_DESC: \"Tillåter inverterad förflyttning av vyn vid knappförflyttning.\"\n  STR_BATTLESCAPE_SCALE: \"Skala för stridsvy\"\n  STR_BATTLESCAPE_SCALE_DESC: \"Stridsvyns synfält kan skalas antingen till en fast upplösning (Utsträckt för att passa skärmen) eller en fast inzoomad nivå (Expanderad för att fylla).\"\n  STR_GEOSCAPE_SCALE: \"Skala för Geovy\"\n  STR_GEOSCAPESCALE_SCALE_DESC: \"Geovyns synfält är skalbar antingen till en fast upplösning (Utsträckt för att passa) eller till en fast inzoomad nivå (Expanderad för att fylla).\"\n  STR_1_5X: \"1,5x Original\"\n  STR_2X: \"2x Original\"\n  STR_THIRD_DISPLAY: \"1/3 Skärm\"\n  STR_HALF_DISPLAY: \"1/2 Skärm\"\n  STR_FULL_DISPLAY: \"Helskärm\"\n  STR_FPS_LIMIT: \"FPS-gräns\"\n  STR_FPS_LIMIT_DESC: \"Begränsar antalet skärmuppdateringar per sekund, 0 för ingen begränsning. Om OpenGL-rendering är på använder spelet Vsync istället.\"\n  STR_FPS_INACTIVE_LIMIT: \"FPS-begränsning i bakgrund\"\n  STR_FPS_INACTIVE_LIMIT_DESC: \"Begränsar antalet bilduppdateringar per sekund i spelet om OpenXcom används i bakgrunden exempelvis på skrivbordet.\"\n  STR_NOALIENPANICMESSAGES: \"Dölj panikmeddelanden för utomjordlingar\"\n  STR_NOALIENPANICMESSAGES_DESC: \"Döljer panikmeddelanden för utomjordlingar förutom om de är synliga.\"\n  STR_ALIENBLEEDING: \"Utomjordisk blödning\"\n  STR_ALIENBLEEDING_DESC: \"Tillåt dödliga sår på de flesta utomjordlingarna.\"\n  STR_FIELDPROMOTIONS: \"Fältbefordran\"\n  STR_FIELDPROMOTIONS_DESC: \"Enbart soldater som var på uppdragsplatsen kan bli befordrade.\"\n  STR_MEETINGPOINT: \"Beräkna UFOs flygbana\"\n  STR_MEETINGPOINT_DESC: \"Stridsflyg flyger mot en mötespunkt med UFOt baserat på dess nuvarande flygbana.\"\n  STR_IRONMAN: \"IRONMAN\"\n  STR_IRONMAN_DESC: \"Ingen manuell sparning\"\n  STR_SAVE_AND_ABANDON_GAME: \"SPARA OCH ÖVERGE SPEL\"\n  STR_MOD_UNSUCCESSFUL: \"Modifiering gick inte att läsa in.\"\n  STR_NEW_SAVED_GAME_SLOT: \"<NYTT SPARAT SPEL>\"\n  STR_AUTO_SAVE_GEOSCAPE_SLOT: \"<AUTO GEOSCAPE>\"\n  STR_AUTO_SAVE_BATTLESCAPE_SLOT: \"<AUTO BATTLESCAPE>\"\n  STR_QUICK_SAVE_SLOT: \"<QUICKSAVE>\"\n  STR_DISPLAY_MODE_DESC: \"Ändra hur spelet visas på skärmen.\"\n  STR_PREFERRED_MUSIC_FORMAT: \"Musikformat\"\n  STR_PREFERRED_MUSIC_FORMAT_DESC: \"Väljer det föredragna musikformatet när flera finns tillgängliga.{NEWLINE}Observera att MIDI kan vara buggigt i Windows.\"\n  STR_PREFERRED_SFX_FORMAT: \"SFX-format\"\n  STR_PREFERRED_SFX_FORMAT_DESC: \"Väljer det föredragna ljudeffektsformatet när flera finns tillgängliga.\"\n  STR_PREFERRED_VIDEO_FORMAT: \"Videoformat\"\n  STR_PREFERRED_VIDEO_FORMAT_DESC: \"Väljer det videoformat som bör användas om flera finns tillgängliga.\"\n  STR_PREFERRED_VIDEO_ANIMATION: \"Animation\"\n  STR_PREFERRED_VIDEO_SLIDESHOW: \"Bildspel\"\n  STR_PREFERRED_FORMAT_AUTO: \"Auto\"\n  STR_CURRENT_FORMAT: \"Nuvarande: {0}\"\n  STR_SOUND_OPTIONS: \"Ljudinställningar\"\n  STR_BACKGROUND_MUTE: \"Tysta bakgrundsljud\"\n  STR_BACKGROUND_MUTE_DESC: \"Stänger av allt ljud när spelfönstret inte är aktivt.\"\n  STR_FORCE_FIRE: \"Åsidosätt skottlinje\"\n  STR_FORCE_FIRE_DESC: \"Låter dina soldater skjuta mot en viss punkt när CTRL hålls ner, oberoende på om eldsikt finns.\"\n  STR_NO_AUDIO_HARDWARE_DETECTED: \"Ingen ljudhårdvara hittades\"\n  STR_MOUSEWHEEL_SPEED: \"Mushjulets rullhastighet\"\n  STR_MOUSEWHEEL_SPEED_DESC: \"Justera mängden rader som bläddras vid varje rullning av mushjulet.\"\n  STR_DISABLED: \"Inaktiverad\"\n  STR_MAXIMIZE_INFO_SCREENS: \"Maximera infoskärm\"\n  STR_MAXIMIZE_INFO_SCREENS_DESC: \"Inventarie och olika fönster kommer visas i helskärm, oberoende av skärmens storleksinställningar.\"\n  STR_DIARY: \"DAGBOK\"\n  STR_KILLED: \"DÖDADE\"\n  STR_STUNNED: \"BEDÖVADE\"\n  STR_PANICKED: \"PANIKDRABBADE\"\n  STR_MINDCONTROLLED: \"KONTROLLERADE\"\n  STR_REGION_UNKNOWN: \"Hemliga\"\n  STR_WEAPON_UNKNOWN: \"Improvisation\"\n  STR_UNKNOWN: \"Okänd\"\n  STR_VICTORY: \"Seger\"\n  STR_DEFEAT: \"Nederlag\"\n  STR_NO_RECORD: \"Inga uppgifter\"\n  STR_HUMAN: \"Människa\"\n  STR_FRIENDLY: \"Vänlig\"\n  STR_HOSTILE: \"Fientlig\"\n  STR_NEUTRAL: \"Neutral\"\n  STR_RATING_UC: \"BETYG\"\n  STR_LOCATION: \"PLATS> {ALT}{0}\"\n  STR_DAYLIGHT_TYPE: \"TID> {ALT}{0}\"\n  STR_RACE_TYPE: \"RAS> {ALT}{0}\"\n  STR_DAY: \"Dag\"\n  STR_NIGHT: \"Natt\"\n  STR_DAYS_WOUNDED: \"DAGAR SKADAD> {ALT}{0}\"\n  STR_COMBAT: \"STRID\"\n  STR_PERFORMANCE: \"PRESTATION\"\n  STR_NEUTRALIZATIONS_BY_RACE: \"NEUTRALISERING AV RAS\"\n  STR_NEUTRALIZATIONS_BY_RANK: \"NEUTRALISERING AV RANK\"\n  STR_NEUTRALIZATIONS_BY_WEAPON: \"NEUTRALISERING AV VAPEN\"\n  STR_MISSIONS_BY_LOCATION: \"UPPDRAG EFTER PLATS\"\n  STR_MISSIONS_BY_TYPE: \"UPPDRAG EFTER TYP\"\n  STR_MISSIONS_BY_UFO: \"UPPDRAG EFTER UFO\"\n  STR_SCORE_VALUE: \"POÄNG> {ALT}{0}\"\n  STR_WINS: \"VINST> {ALT}{0}\"\n  STR_STUNS: \"BEDÖVNING> {ALT}{0}\"\n  STR_PANICKS: \"PANIK> {ALT}{0}\"\n  STR_MINDCONTROLS: \"KONTROLL> {ALT}{0}\"\n  STR_AWARDS: \"UTMÄRKELSER\"\n  STR_COMMENDATIONS_UC: \"LOVORD\"\n  STR_COMMENDATIONS: \"Lovord\"\n  STR_MEDALS: \"MEDALJER\"\n  STR_LOST_IN_SERVICE: \"FÖRLORADE I TJÄNST\"\n  STR_MEDAL_NAME: \"Medaljnamn\"\n  STR_MEDAL_AWARD_LEVEL: \"Utmärkelsenivå\"\n  STR_MEDAL_DECOR_LEVEL: \"Dekorationsnivå\"\n  STR_AWARD_0: \"Första utmärkelse\"\n  STR_AWARD_1: \"Andra utmärkelse\"\n  STR_AWARD_2: \"Tredje utmärkelse\"\n  STR_AWARD_3: \"Fjärde utmärkelse\"\n  STR_AWARD_4: \"Femte utmärkelse\"\n  STR_AWARD_5: \"Sjätte utmärkelse\"\n  STR_AWARD_6: \"Sjunde utmärkelse\"\n  STR_AWARD_7: \"Åttonde utmärkelse\"\n  STR_AWARD_8: \"Nionde utmärkelse\"\n  STR_AWARD_9: \"Tionde utmärkelse\"\n  STR_AWARD_DECOR_0: \"Inga\"\n  STR_AWARD_DECOR_1: \"Första bronsmärke\"\n  STR_AWARD_DECOR_2: \"Andra bronsmärke\"\n  STR_AWARD_DECOR_3: \"Tredje bronsmärke\"\n  STR_AWARD_DECOR_4: \"Förste silvermärke\"\n  STR_AWARD_DECOR_5: \"Andra  silvermärke\"\n  STR_AWARD_DECOR_6: \"Tredje silvermärke\"\n  STR_AWARD_DECOR_7: \"Första guldmärke\"\n  STR_AWARD_DECOR_8: \"Andra guldmärke\"\n  STR_AWARD_DECOR_9: \"Tredje guldmärke\"\n  STR_KILLED_IN_ACTION_MALE: \"DÖDAD I STRID\"\n  STR_KILLED_IN_ACTION_FEMALE: \"DÖDAD I STRID\"\n  STR_MISSING_IN_ACTION_MALE: \"SAKNAD I STRID\"\n  STR_MISSING_IN_ACTION_FEMALE: \"SAKNAD I STRID\"\n  STR_AVERAGE_MONTHLY_RATING: \"Genomsnittsbetyg per månad\"\n  STR_TOTAL_INCOME: \"Totala inkomster\"\n  STR_TOTAL_EXPENDITURE: \"Totala utgifter\"\n  STR_MISSIONS_WON: \"Uppdrag slutförda\"\n  STR_MISSIONS_LOST: \"Uppdrag misslyckade\"\n  STR_NIGHT_MISSIONS: \"Nattuppdrag\"\n  STR_BEST_RATING: \"Högsta uppdragsbetyg\"\n  STR_WORST_RATING: \"Lägsta uppdragsbetyg\"\n  STR_ALIEN_KILLS: \"Utomjordingar dödade\"\n  STR_ALIEN_CAPTURES: \"Utomjordingar fångade\"\n  STR_FRIENDLY_KILLS: \"Vådaskottsincidenter\"\n  STR_AVERAGE_ACCURACY: \"Genomsnittlig träffsäkerhet\"\n  STR_WEAPON_MOST_KILLS: \"Mest effektiva vapen\"\n  STR_ALIEN_MOST_KILLS: \"Dödligaste utomjording\"\n  STR_LONGEST_SERVICE: \"Flest månader i tjänst\"\n  STR_TOTAL_DAYS_WOUNDED: \"Sjukdagar\"\n  STR_COUNTRIES_LOST: \"Länder infiltrerade\"\n  STR_TOTAL_TERROR_SITES: \"Terrorattacker\"\n  STR_TOTAL_BASES: \"Baser byggda\"\n  STR_TOTAL_CRAFT: \"Farkoster ägda\"\n  STR_TOTAL_SCIENTISTS: \"Forskare anställda\"\n  STR_TOTAL_ENGINEERS: \"Ingenjörer anställda\"\n  STR_TOTAL_RESEARCH: \"Forskning fullgjord\"\n  STR_DIARY_ACCURACY: \"TRÄFFSÄKERHET> {ALT}{0}%\"\n  STR_STATISTICS: \"Statistik\"\n  STR_STATS: \"STATS\"\n  STR_TIME_UNITS_ABBREVIATION: \"TE\"\n  STR_STAMINA_ABBREVIATION: \"STA\"\n  STR_HEALTH_ABBREVIATION: \"HP\"\n  STR_BRAVERY_ABBREVIATION: \"MOD\"\n  STR_REACTIONS_ABBREVIATION: \"REA\"\n  STR_FIRING_ACCURACY_ABBREVIATION: \"TRF\"\n  STR_THROWING_ACCURACY_ABBREVIATION: \"KAS\"\n  STR_STRENGTH_ABBREVIATION: \"STY\"\n  STR_MELEE_ACCURACY_ABBREVIATION: \"NÄR\"\n  STR_FOLDERS: \"MAPPAR\"\n  STR_DATA_FOLDER: \"Datakatalog (originalresurser)\"\n  STR_USER_FOLDER: \"Användarmapp (modifieringar, openxcom.log)\"\n  STR_SAVE_FOLDER: \"Sparningsmapp (sparade spel, skärmavbildningar)\"\n  STR_CONFIG_FOLDER: \"Konfigurationsmapp (options.cfg)\"\n  STR_DATA_FOLDER_DESC_1: \"Var OpenXcom letar efter originalspelets resurser (UFO och/eller TFTD).\"\n  STR_DATA_FOLDER_DESC_2: \"OpenXcoms interna resurser finns i mappen 'common'. OpenXcoms inbyggda modifieringar finns i mappen 'standard'.\"\n  STR_USER_FOLDER_DESC: \"Loggfilen ('openxcom.log') lagras här. Alla anpassade modifieringar hör också hemma här (i undermappen 'mods').\"\n  STR_SAVE_FOLDER_DESC: \"Dina sparade spelsessioner lagras här. Uppdragsgeneratorns inställningar ('battle.cfg') lagras också här.\"\n  STR_CONFIG_FOLDER_DESC: \"OpenXcoms inställningar ('options.cfg') lagras här. I normala fall samma som användarmappen.\"\n"
  },
  {
    "path": "bin/common/Language/tr.yml",
    "content": "tr:\n  STR_OPENXCOM: \"OpenXcom\"\n  STR_NEW_GAME: \"Yeni Oyun\"\n  STR_LOAD_SAVED_GAME: \"Oyun Yükle\"\n  STR_SELECT_DIFFICULTY_LEVEL: \"Zorluk Seviyesini Seçin\"\n  STR_1_BEGINNER: \"1> Acemi\"\n  STR_2_EXPERIENCED: \"2> Tecrübeli\"\n  STR_3_VETERAN: \"3> Kıdemli\"\n  STR_4_GENIUS: \"4> Dahi\"\n  STR_5_SUPERHUMAN: \"5> İnsanüstü\"\n  STR_TIME: \"Zaman\"\n  STR_DATE: \"Tarih\"\n  STR_SELECT_GAME_TO_LOAD: \"Yüklenecek oyunu seçin\"\n  STR_SELECT_SAVE_POSITION: \"Kayıt yerini seç\"\n  STR_GAME_OPTIONS: \"OYUN AYARLARI\"\n  STR_LOAD_GAME: \"OYUN YÜKLE\"\n  STR_SAVE_GAME: \"OYUNU KAYDET\"\n  STR_ABANDON_GAME: \"OYUNU TERKET\"\n  STR_ABANDON_GAME_QUESTION: \"OYUN TERK EDİLSİN Mİ?\"\n  STR_QUIT: \"Çıkış\"\n  STR_SAVING_GAME: \"Oyun kaydediliyor\"\n  STR_LOADING_GAME: \"Oyun yükleniyor\"\n  STR_NO_SAVED_GAME_PRESENT: \"Kayıtlı oyun yok\"\n  STR_LOAD_UNSUCCESSFUL: \"Yükleme başarısız\"\n  STR_SAVE_UNSUCCESSFUL: \"Kayıt başarısız\"\n  STR_LOAD_SUCCESSFUL: \"Başarıyla yüklendi\"\n  STR_SAVE_SUCCESSFUL: \"Kayıt başarılı\"\n  STR_DELETE: \"SİL\"\n  STR_DELETE_UNSUCCESSFUL: \"Silinemedi\"\n  STR_IS_IT_OK_TO_DELETE_THE_SAVED_GAME: \"Kayıtlı oyunu silmek istediğinize emin misiniz?\"\n  STR_ORIGINAL_XCOM: \"Orijinal X-Com\"\n  STR_LOADING: \"Yükleniyor...\"\n  STR_DETAILS: \"DETAYLAR> {ALT}{0}\"\n  STR_NEW_BATTLE: \"Yeni Çatışma\"\n  STR_OPTIONS: \"Ayarlar\"\n  STR_RIGHT_CLICK_TO_DELETE: \"Silmek için sağ tıklayın.\"\n  STR_RESTORE_DEFAULTS: \"Varsayılan Ayarlar\"\n  STR_CONTROLS: \"KONTROLLER\"\n  STR_GENERAL: \"Genel\"\n  STR_GEOSCAPE: \"Yerküre\"\n  STR_BATTLESCAPE: \"Ermeydanı\"\n  STR_SCREENSHOT: \"Ekran Görüntüsü\"\n  STR_FPS_COUNTER: \"FPS Sayacı\"\n  STR_ROTATE_LEFT: \"Sola Döndür\"\n  STR_ROTATE_RIGHT: \"Sağa Döndür\"\n  STR_ROTATE_UP: \"Yukarı Döndür\"\n  STR_ROTATE_DOWN: \"Aşağı Döndür\"\n  STR_ZOOM_IN: \"Yaklaştır\"\n  STR_ZOOM_OUT: \"Uzaklaştır\"\n  STR_TOGGLE_COUNTRY_DETAIL: \"Ülke Detayını Aç/Kapa\"\n  STR_TOGGLE_RADAR_RANGES: \"Radar Menzillerini Aç/Kapa\"\n  STR_SCROLL_LEFT: \"Sola Kaydır\"\n  STR_SCROLL_RIGHT: \"Sağa Kaydır\"\n  STR_SCROLL_UP: \"Yukarı Kaydır\"\n  STR_SCROLL_DOWN: \"Aşağı Kaydır\"\n  STR_UNIT_LEVEL_ABOVE: \"Üniteyi Üst Kata Çıkart\"\n  STR_UNIT_LEVEL_BELOW: \"Üniteyi Alt Kata İndir\"\n  STR_VIEW_LEVEL_ABOVE: \"Üst Katı Görüntüle\"\n  STR_VIEW_LEVEL_BELOW: \"Alt Katı Görüntüle\"\n  STR_CENTER_SELECTED_UNIT: \"Seçili Üniteyi Ortala\"\n  STR_PREVIOUS_UNIT: \"Önceki Üniteyi Seç\"\n  STR_NEXT_UNIT: \"Sonraki Üniteyi Seç\"\n  STR_DESELECT_UNIT: \"Bu Üniteyi Atla\"\n  STR_USE_LEFT_HAND: \"Sol Eldeki Ekipmanı Kullan\"\n  STR_USE_RIGHT_HAND: \"Sağ Eldeki Ekipmanı Kullan\"\n  STR_INVENTORY: \"Envanter\"\n  STR_MINIMAP: \"Mini harita\"\n  STR_MULTI_LEVEL_VIEW: \"Çoklu Kat Görünümü\"\n  STR_END_TURN: \"Turu Sonlandır\"\n  STR_ABORT_MISSION: \"Harekatı Bırak\"\n  STR_UNIT_STATS: \"Ünite Bilgileri\"\n  STR_KNEEL: \"Diz çök\"\n  STR_RELOAD: \"Silah doldur\"\n  STR_TOGGLE_PERSONAL_LIGHTING: \"Bireysel Aydınlatmayı Aç/Kapat\"\n  STR_DONT_RESERVE_TIME_UNITS: \"Zaman Ünitesi ayırma\"\n  STR_RESERVE_TIME_UNITS_FOR_SNAP_SHOT: \"Ani atış için ZÜ ayır\"\n  STR_RESERVE_TIME_UNITS_FOR_AIMED_SHOT: \"Keskin atış için ZÜ ayır\"\n  STR_RESERVE_TIME_UNITS_FOR_AUTO_SHOT: \"Otomatik Atış için ZÜ ayır\"\n  STR_CENTER_ON_ENEMY_1: \"1. Düşmana Odaklan\"\n  STR_CENTER_ON_ENEMY_2: \"2. Düşmana Odaklan\"\n  STR_CENTER_ON_ENEMY_3: \"3. Düşmana Odaklan\"\n  STR_CENTER_ON_ENEMY_4: \"4. Düşmana Odaklan\"\n  STR_CENTER_ON_ENEMY_5: \"5. Düşmana Odaklan\"\n  STR_CENTER_ON_ENEMY_6: \"6. Düşmana Odaklan\"\n  STR_CENTER_ON_ENEMY_7: \"7. Düşmana Odaklan\"\n  STR_CENTER_ON_ENEMY_8: \"8. Düşmana Odaklan\"\n  STR_CENTER_ON_ENEMY_9: \"9. Düşmana Odaklan\"\n  STR_CENTER_ON_ENEMY_10: \"10. Düşmana Odaklan\"\n  STR_CREATE_INVENTORY_TEMPLATE: \"Envanter şablonu oluştur\"\n  STR_APPLY_INVENTORY_TEMPLATE: \"Envanter şablonunu uygula\"\n  STR_CLEAR_INVENTORY: \"Envanteri Boşalt\"\n  STR_AUTO_EQUIP: \"Otomatik Teçhizat\"\n  STR_QUICK_SAVE: \"Hızlı Kaydet\"\n  STR_QUICK_LOAD: \"Hızlı Yükle\"\n  STR_ADVANCED: \"GELİŞMİŞ\"\n  STR_AGGRESSIVERETALIATION: \"Amansız karşı taarruz\"\n  STR_AGGRESSIVERETALIATION_DESC: \"Görevleri ne olursa olsun tüm UFO'lar, sürekli olarak üslerinizin yerini keşfetmeye çalışır.\"\n  STR_STORAGELIMITSENFORCED: \"Katı depolama limitleri\"\n  STR_STORAGELIMITSENFORCED_DESC: \"Harekat sonunda ele geçirilen canlı Yabancılar ve levazımat için karantina ve depolama limitleri katı biçimde uygulanır.\"\n  STR_CANSELLLIVEALIENS: \"Canlı Yabancı satışı\"\n  STR_CANSELLLIVEALIENS_DESC: \"Tutsak canlı Yabancılar satışa sürülebilir. Depolama limitleri aktifken kullanılması önerilir.\"\n  STR_ALLOWBUILDINGQUEUE: \"İnşaat kuyruğuna izin ver\"\n  STR_ALLOWBUILDINGQUEUE_DESC: \"Yeni tesisler, henüz tamamlanmamış tesislerin yanında inşa edilebilir.\"\n  STR_BATTLEAUTOEND: \"Çatışmayı otomatik sonlandır\"\n  STR_BATTLEAUTOEND_DESC: \"Çatışmalar, kalan en son canlı düşman etkisiz hale getirildiğinde otomatik olarak sonlandırılır.\"\n  STR_BATTLEINSTANTGRENADE: \"Anında patlayan el bombaları\"\n  STR_BATTLEINSTANTGRENADE_DESC: \"Aynı turda patlamak üzere kurulan el bombaları, tur sonunda değil, atılır atılmaz infilak eder.\"\n  STR_BATTLEUFOEXTENDERACCURACY: \"\\\"UFO Extender\\\" tipi isabetlilik hesabı\"\n  STR_BATTLEUFOEXTENDERACCURACY_DESC: \"İsabetlilik oranı, atış tipine bağlı olarak belli bir menzilden sonra düşüş gösterir. Hesaplanan nihai isabetlilik, imleç üzerinde görüntülenir.\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE: \"Havadayken transfer\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE_DESC: \"Halihazırda uçuşta olan araçların da başka üsse transfer edilmesine izin verilir.\"\n  STR_CRAFTLAUNCHALWAYS: \"Uçakları havalanmaya zorla\"\n  STR_CRAFTLAUNCHALWAYS_DESC: \"Hava araçlarına, hazır olmasalar da, bakım ihtiyaçlarını göz ardı ederek uçuş emri verilebilir.\"\n  STR_CUSTOMINITIALBASE: \"İsteğe özel başlangıç üssü\"\n  STR_CUSTOMINITIALBASE_DESC: \"Yeni bir oyuna başlarken, hazır üs tasarımını kullanmak yerine, başlangıç tesislerini istediğiniz gibi yerleştirmenize izin verilir.\"\n  STR_GLOBESEASONS: \"Gerçekçi yerküre ışıklandırması\"\n  STR_GLOBESEASONS_DESC: \"Güneş ışığı, dünyanın eksen eğimine uygun biçimde daha gerçekçi biçimde görüntülenir.\"\n  STR_PLAYINTRO: \"Açılış videosu\"\n  STR_PLAYINTRO_DESC: \"Başlangıçta açılış videosu görüntülenir.\"\n  STR_SHOWMORESTATSININVENTORYVIEW: \"Envanter Bilgileri\"\n  STR_SHOWMORESTATSININVENTORYVIEW_DESC: \"Envanter ekranında, seçili asker hakkında ilave bilgiler görüntülenir.\"\n  STR_SNEAKYAI: \"Sinsi YZ\"\n  STR_SNEAKYAI_DESC: \"Yapay Zeka, mümkün olduğunca kendini oyuncuya göstermemeye çalışır.\"\n  STR_STRAFE: \"Alternatif hareket yöntemleri\"\n  STR_STRAFE_DESC: \"CTRL tuşuna basılı tutarak yan yan yürüme, koşma ve tank taretlerinin bağımsız dönmesi gibi hareketlere izin verilir.\"\n  STR_BATTLEEXPLOSIONHEIGHT: \"Dikey patlama etkisi\"\n  STR_BATTLEEXPLOSIONHEIGHT_DESC: \"Patlamaların, dikey eksende ne kadar alana etki edeceğini belirler.{NEWLINE}(0: Sadece yanlara doğru etki, 3: küresel etki)\"\n  STR_AUTOSAVE: \"Otomatik oyun kaydı\"\n  STR_AUTOSAVE_DESC: \"Oyunu otomatik olarak belirlenen sıklıkta kaydeder. Demiradam modunda dikkate alınmaz.\"\n  STR_AUTOSAVE_FREQUENCY: \"Otomatik Kayıt Sıklığı\"\n  STR_AUTOSAVE_FREQUENCY_DESC: \"Otomatik oyun kaydının kaç turda bir yapılacağını belirler.\"\n  STR_ALLOWPSIONICCAPTURE: \"Zihin kontrolüyle esir almaya izin ver\"\n  STR_ALLOWPSIONICCAPTURE_DESC: \"Kalan tüm Yabancıların zihin kontrolü altına alınması, harekatın zaferle sonuçlanmasını sağlar. Kontrol altındaki Yabancılar, canlı ele geçirilmiş olur.\"\n  STR_ANYTIMEPSITRAINING: \"Serbest psionik eğitim dönemleri\"\n  STR_ANYTIMEPSITRAINING_DESC: \"Askerlerin psionik eğitim giriş-çıkışlarının ay içinde her zaman yapılabilmesine izin verilir. İlk eğitim sürecinin 30 ila 60 gün sürdüğünü unutmayın.\"\n  STR_SKIPNEXTTURNSCREEN: \"\\\"Sonraki Tur\\\" ekranını geç\"\n  STR_SKIPNEXTTURNSCREEN_DESC: \"Çatışma esnasında, \\\"Sonraki Tur\\\" ekranları, kısa bir gecikmeyle otomatik olarak atlanır.\"\n  STR_NOT_ENOUGH_SPACE: \"Yeterli Boş Yer Yok!\"\n  STR_WEAPONSELFDESTRUCTION: \"Kendini imha eden Yabancı silahları\"\n  STR_WEAPONSELFDESTRUCTION_DESC: \"XCOM 2012'de olduğu gibi, yabancıların taşıdığı silahlar, sahipleri öldürüldüğünde kendi kendini imha eder.\"\n  STR_RETAINCORPSES: \"Yabancı cesetlerini muhafaza et\"\n  STR_RETAINCORPSES_DESC: \"XCOM 2012'de olduğu gibi, canlı yabancılar üzerinde \\\"araştırma\\\" yapıldıktan sonra cesetlerinin depolarda saklanmasına izin verilir.\"\n  STR_SAVE_VOXEL_VIEW: \"Bakış Açısından Görüntü Kaydet\"\n  STR_RESERVE_TIME_UNITS_FOR_KNEEL: \"Diz çökmek için Zaman Ünitesi ayır\"\n  STR_EXPEND_ALL_TIME_UNITS: \"Kalan tüm Zaman Ünitelerini harca\"\n  STR_PSISTRENGTHEVAL: \"Psi-Direnç Değerlendirme\"\n  STR_PSISTRENGTHEVAL_DESC: \"İlgili araştırmalar tamamlandığında, tüm askerlerin psionik direnç değerlendirmesi derhal gerçekleştirilir.\"\n  STR_DISABLEAUTOEQUIP: \"Otomatik teçhizat devre dışı\"\n  STR_DISABLEAUTOEQUIP_DESC: \"Yeni askerlerin teçhizatı, mücadele öncesinde otomatik olarak tahsis edilmez.\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT: \"Psi-Direnç gelişimine izin ver\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT_DESC: \"Tecrübe ve eğitim yoluyla askerlerin psionik dirençlerini güçlendirmelerine izin verilir.\"\n  STR_BATTLESMOOTHCAMERA: \"Akıcı Mermi Kamerası\"\n  STR_BATTLESMOOTHCAMERA_DESC: \"Ermeydanı kamerası, hareket halindeki mermileri akıcı bir şekilde takip eder.\"\n  STR_BATTLECONFIRMFIREMODE: \"Kontrollü Atış modu\"\n  STR_BATTLECONFIRMFIREMODE_DESC: \"Ateş emirlerini onaylamak için aynı kare üzerinde iki kez tıklama gerekir.\"\n  STR_SELECT_BASE_1: \"1. Üssü Seç\"\n  STR_SELECT_BASE_2: \"2. Üssü Seç\"\n  STR_SELECT_BASE_3: \"3. Üssü Seç\"\n  STR_SELECT_BASE_4: \"4. Üssü Seç\"\n  STR_SELECT_BASE_5: \"5. Üssü Seç\"\n  STR_SELECT_BASE_6: \"6. Üssü Seç\"\n  STR_SELECT_BASE_7: \"7. Üssü Seç\"\n  STR_SELECT_BASE_8: \"8. Üssü Seç\"\n  STR_VIDEO: \"VİDEO\"\n  STR_AUDIO: \"SES\"\n  STR_BATTLESCAPE_UC: \"ERMEYDANI\"\n  STR_MODS_UC: \"MODLAR\"\n  STR_MODS: \"Modlar\"\n  STR_DISPLAY_RESOLUTION: \"Görüntü Çözünürlüğü\"\n  STR_DISPLAY_RESOLUTION_DESC: \"Ekran çözünürlüğünü belirler. Oyun çözünürlüğü, uyum sağlayacak şekilde değiştirilecektir. Butonlarla desteklenen değerler arasından seçim yapabilir, sayıların üzerine tıklayarak özel değer girebilirsiniz.\"\n  STR_ORIGINAL: \"Orijinal\"\n  STR_DISPLAY_MODE: \"Görüntü Modu\"\n  STR_WINDOWED: \"Pencere\"\n  STR_FULLSCREEN: \"Tam Ekran\"\n  STR_BORDERLESS: \"Çerçevesiz\"\n  STR_DISPLAY_LANGUAGE: \"Lisan\"\n  STR_DISPLAY_LANGUAGE_DESC: \"Oyun içi metinlerin hangi dilde görüntüleneceğini belirler.\"\n  STR_DISPLAY_FILTER: \"Görüntü Filtresi\"\n  STR_DISPLAY_FILTER_DESC: \"Oyun görüntüsüne uygulanacak efekt filtresini belirler.{NEWLINE}* OpenGL donanım desteği gerektirir.\"\n  STR_DISPLAY_OPTIONS: \"Görüntü Ayarları\"\n  STR_LETTERBOXED: \"Sinemaskop\"\n  STR_LETTERBOXED_DESC: \"Orijinal görüntü oranlarını korumak için ekranın kenarlarında boşluk bırakılır.\"\n  STR_RESIZABLE: \"Serbest Büyüklük\"\n  STR_LOCK_MOUSE: \"Sınırlı İmleç\"\n  STR_LOCK_MOUSE_DESC: \"Fare imlecinin oyun penceresini terketmesini engeller. İstediğinizde Ctrl-G ile açıp kapatabilirsiniz.\"\n  STR_FIXED_WINDOW_POSITION: \"Sabit Pencere Konumu\"\n  STR_FIXED_WINDOW_POSITION_DESC: \"Pencere için sabit bir konum belirler.\"\n  STR_DISPLAY_SET_WINDOW_POSITION: \"Pencere için yeni konum belirleyin.\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_X: \"Sol çerçeve X konumu:\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_Y: \"Üst çerçeve Y konumu:\"\n  STR_MUSIC_VOLUME: \"Müzik\"\n  STR_MUSIC_VOLUME_DESC: \"Arka plan müzik volümünü belirler.\"\n  STR_SFX_VOLUME: \"Ses Efektleri\"\n  STR_SFX_VOLUME_DESC: \"Ses efektlerinin volümünü belirler.\"\n  STR_UI_VOLUME: \"Arabirim Sesleri\"\n  STR_UI_VOLUME_DESC: \"Kullanıcı arabirimine ait buton seslerinin volümünü belirler.\"\n  STR_SCROLL_SPEED: \"Kaydırma Hızı\"\n  STR_SCROLL_SPEED_GEO_DESC: \"Yerküre görünümünde kaydırma hızını belirler.\"\n  STR_SCROLL_SPEED_BATTLE_DESC: \"Haritanın kaydırma hızını belirler.\"\n  STR_DOGFIGHT_SPEED: \"Hava Çatışması Hızı\"\n  STR_DOGFIGHT_SPEED_DESC: \"UFO'lar ve hava araçları arasındaki çatışmaların hızını belirler. Daha düşük hızlar, yavaş sistemlerde performans artışı sağlayabilir.\"\n  STR_CLOCK_SPEED: \"Saat Hızı\"\n  STR_CLOCK_SPEED_DESC: \"Yerküre saatinin güncellenme hızını belirler. Daha düşük hızlar, yavaş sistemlerde performansı artışı sağlayabilir.\"\n  STR_GLOBE_DETAILS: \"Yerküre Detayları\"\n  STR_GLOBE_COUNTRIES: \"Ülkeler\"\n  STR_GLOBE_COUNTRIES_DESC: \"Yerkürede ülke ve şehir adları görüntülenir.\"\n  STR_GLOBE_RADARS: \"Radarlar\"\n  STR_GLOBE_RADARS_DESC: \"Yerkürede üslerin radar menzilleri görüntülenir.\"\n  STR_GLOBE_FLIGHT_PATHS: \"Uçuş Güzergahları\"\n  STR_GLOBE_FLIGHT_PATHS_DESC: \"Yerküre üzerinde araçların uçuş güzergahları görüntülenir.\"\n  STR_CONTROLS_DESC: \"Bir kısayol üzerinde sol tıklayarak değiştirin.{NEWLINE}Sağ tıklayarak devre dışı bırakın.\"\n  STR_BASE_GAME: \"Temel Oyun\"\n  STR_MODS_TOOLTIP: \"Versiyon {0} - {1}.{NEWLINE}{2}\"\n  STR_EDGE_SCROLL: \"Kenardan Kaydırma\"\n  STR_EDGE_SCROLL_DESC: \"Butonla: Ekranın kenarında sol fare butonu basılı tutarak kaydırma.{NEWLINE}Otomatik: İmleç ekranın kenarına geldiğinde otomatik kaydırma.\"\n  STR_TRIGGER_SCROLL: \"Butonla\"\n  STR_AUTO_SCROLL: \"Otomatik\"\n  STR_DRAG_SCROLL: \"Sürükleyerek Kaydırma\"\n  STR_DRAG_SCROLL_DESC: \"Haritayı kaydırmak için, belirtilen fare butonu basılı tutularak sürükleme yapılır.\"\n  STR_LEFT_MOUSE_BUTTON: \"Sol Buton\"\n  STR_MIDDLE_MOUSE_BUTTON: \"Orta Buton\"\n  STR_RIGHT_MOUSE_BUTTON: \"Sağ Buton\"\n  STR_FIRE_SPEED: \"Mermi Hızı\"\n  STR_FIRE_SPEED_DESC: \"Mermilerin hareket hızını belirler.\"\n  STR_PLAYER_MOVEMENT_SPEED: \"Oyuncu Hareket Hızı\"\n  STR_PLAYER_MOVEMENT_SPEED_DESC: \"Oyuncu tarafından kontrol edilen birimlerin hareket hızını belirler.\"\n  STR_COMPUTER_MOVEMENT_SPEED: \"YZ Hareket Hızı\"\n  STR_COMPUTER_MOVEMENT_SPEED_DESC: \"Bilgisayar tarafından kontrol edilen birimlerin hareket hızını belirler.\"\n  STR_PATH_PREVIEW: \"Yol Bulma Görünümü\"\n  STR_PATH_ARROWS: \"Oklar\"\n  STR_PATH_ARROWS_DESC: \"Tıkladığınızda, ünitenin hedefe gitmek için izleyeceği yol görüntülenir. Renkler, olası aksiyonları gösterir: Yeşil - hareket ve ateş edilebilir; Sarı - hareket edilebilir; Kırmızı - hareket edilemez.\"\n  STR_PATH_TIME_UNIT_COST: \"Zaman Üniteleri\"\n  STR_PATH_TIME_UNIT_COST_DESC: \"Hedefe tıklandığında ünite hareket ettikten sonra geride kaç ZÜ kalacağı görüntülenir.\"\n  STR_USER_INTERFACE_OPTIONS: \"Arabirim Seçenekleri\"\n  STR_TOOLTIPS: \"İpuçları\"\n  STR_TOOLTIPS_DESC: \"Ermeydanı ikonları için ipuçları görüntülenir.\"\n  STR_DEATH_NOTIFICATIONS: \"Ölüm Bildirimleri\"\n  STR_DEATH_NOTIFICATIONS_DESC: \"Ölen her bir askeriniz için bildirim mesajı görüntülenir.\"\n  STR_SHOW_FUNDS: \"Finansman Görüntüle\"\n  STR_SHOW_FUNDS_DESC: \"Yerküre saat görünümünde mevcut para miktarı görüntülenir.\"\n  STR_MISSION_GENERATOR: \"GÖREV PARAMETRELERİ\"\n  STR_MAP_OPTIONS: \"HARİTA SEÇENEKLERİ\"\n  STR_ALIEN_OPTIONS: \"DÜŞMAN SEÇENEKLERİ\"\n  STR_MAP_TERRAIN: \"Savaş Alanı\"\n  STR_MAP_DARKNESS: \"Karanlık\"\n  STR_MAP_DEPTH: \"Derinlik\"\n  STR_DIFFICULTY: \"Zorluk Seviyesi\"\n  STR_ALIEN_RACE: \"Irk\"\n  STR_ALIEN_TECH_LEVEL: \"Teknoloji Seviyesi\"\n  STR_RANDOMIZE: \"Rastgele\"\n  STR_OXCE_REQUIRED_QUESTION: \"Bu mod, OpenXcom {0} gerektiriyor. Aktifleştirilsin mi?\"\n  STR_RESTORE_DEFAULTS_QUESTION: \"Varsayılan ayarlara dönmek istediğinize emin misiniz?\"\n  STR_DISPLAY_OPTIONS_CONFIRM: \"Mevcut görüntü ayarlarını kullanmak istiyor musunuz?\"\n  STR_DISPLAY_OPTIONS_REVERT: \"{0} sn. içinde geri dönülecek.\"\n  STR_MISSING_CONTENT_PROMPT: \"DİKKAT:{SMALLLINE}Bu oyun kaydı, şu an kurulu olmayan modlara ihtiyaç duyuyor. Eksik içerik nedeniyle oyun yüklenirken hata oluşabilir.{NEWLINE}Devam?\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT: \"Pimi çekilmiş el bombalarını kaydet\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT_DESC: \"Çatışma öncesi envanter ekranında pimi çekilmiş el bombalarının asker ekipman dizilimiyle kaydedilmesini sağlar.\"\n  STR_NEWSEEDONLOAD: \"Oyun kaydı suistimali\"\n  STR_NEWSEEDONLOAD_DESC: \"Kayıtlı bir oyun yüklendiğinde rastgele sayı üreteci sıfırlanır, böylece aynı hareket farklı sonuçlar üretebilir. Demiradam modunda geçerli değildir.\"\n  STR_CHANGEVALUEBYMOUSEWHEEL: \"Değerleri fare tekeriyle değiştir\"\n  STR_CHANGEVALUEBYMOUSEWHEEL_DESC: \"Sayısal değerleri fare tekeriyle bu adım sayısı kadar arttırıp azaltmaya imkan sağlar.\"\n  STR_BATTLEHAIRBLEACH: \"Gelişmiş asker figürleri\"\n  STR_BATTLEHAIRBLEACH_DESC: \"Ermeydanı'ndaki asker figürleri, envanter görünümlerine benzer biçimde görüntülenir.\"\n  STR_DRAGSCROLLINVERT: \"Tersine sürükleyerek kaydır\"\n  STR_DRAGSCROLLINVERT_DESC: \"Aktif olduğunda, fare ile sürükleyerek kaydırma, hareket yönünün tersine yapılır.\"\n  STR_BATTLESCAPE_SCALE: \"Ermeydanı Oranları\"\n  STR_BATTLESCAPE_SCALE_DESC: \"Ermeydanı görünümünün ölçekleme modunu değiştirir. Sabit çözünürlük (esnetme) ve sabit yakınlaştırma oranı (büyütme) seçenekleri mevcuttur.\"\n  STR_GEOSCAPE_SCALE: \"Yerküre Oranları\"\n  STR_GEOSCAPESCALE_SCALE_DESC: \"Yerküre görünümünün ölçekleme modunu değiştirir. Sabit çözünürlük (esnetme) ve sabit yakınlaştırma oranı (büyütme) seçenekleri mevcuttur.\"\n  STR_1_5X: \"1.5x Orijinal\"\n  STR_2X: \"2x Orijinal\"\n  STR_THIRD_DISPLAY: \"1/3 Görünüm\"\n  STR_HALF_DISPLAY: \"1/2 Görünüm\"\n  STR_FULL_DISPLAY: \"Tam Görünüm\"\n  STR_FPS_LIMIT: \"FPS sınırı\"\n  STR_FPS_LIMIT_DESC: \"Saniye başına ekran tazeleme sayısını sınırlandırır. 0 sınırsız anlamına gelir. OpenGL etkinse oyun bu sınırlandırma yerine Vsync kullanır.\"\n  STR_FPS_INACTIVE_LIMIT: \"Arka plan FPS sınırı\"\n  STR_FPS_INACTIVE_LIMIT_DESC: \"OpenXcom arka planda çalışırken saniye başına ekran tazeleme sayısını sınırlandırır.\"\n  STR_NOALIENPANICMESSAGES: \"Yabancı panik mesajlarını kısıtla\"\n  STR_NOALIENPANICMESSAGES_DESC: \"Oyuncunun görüş alanı dışındaki yabancıların paniğe kapıldığına dair bildirimler görüntülenmez.\"\n  STR_ALIENBLEEDING: \"Yabancı kan kaybı\"\n  STR_ALIENBLEEDING_DESC: \"Yabancıların da ölümcül yara alabilmesine izin verilir\"\n  STR_FIELDPROMOTIONS: \"Saha terfileri\"\n  STR_FIELDPROMOTIONS_DESC: \"Harekat sonrasında, sadece sahada aktif görev almış askerler terfi ettirilebilir.\"\n  STR_MEETINGPOINT: \"UFO gidiş yolunu tahmin et\"\n  STR_MEETINGPOINT_DESC: \"Avcı araçlar, takip ettikleri UFO'nun gidişatına göre tahmini bir buluşma noktasını hedeflerler.\"\n  STR_IRONMAN: \"DEMİRADAM\"\n  STR_IRONMAN_DESC: \"Manuel oyun kaydetmenize izin verilmez.\"\n  STR_SAVE_AND_ABANDON_GAME: \"KAYDET VE OYUNU TERKET\"\n  STR_MOD_UNSUCCESSFUL: \"Mod yüklenemedi\"\n  STR_NEW_SAVED_GAME_SLOT: \"<YENİ KAYIT>\"\n  STR_AUTO_SAVE_GEOSCAPE_SLOT: \"<YERKÜRE OTOMATİK>\"\n  STR_AUTO_SAVE_BATTLESCAPE_SLOT: \"<ERMEYDANI OTOMATİK>\"\n  STR_QUICK_SAVE_SLOT: \"<HIZLI KAYIT>\"\n  STR_DISPLAY_MODE_DESC: \"Oyunun ne şekilde görüntüleneceğini belirler.\"\n  STR_PREFERRED_MUSIC_FORMAT: \"Müzik Formatı\"\n  STR_PREFERRED_MUSIC_FORMAT_DESC: \"Farklı müzik formatları mevcut olduğunda tercih edilen seçeneği belirler.{NEWLINE}NOT: Windows platformunda MIDI seçeneği sorunlu olabilir.\"\n  STR_PREFERRED_SFX_FORMAT: \"Ses Efekt Formatı\"\n  STR_PREFERRED_SFX_FORMAT_DESC: \"Farklı ses efekt formatları mevcut olduğunda tercih edilen seçeneği belirler.\"\n  STR_PREFERRED_VIDEO_FORMAT: \"Video Formatı\"\n  STR_PREFERRED_VIDEO_FORMAT_DESC: \"Birden fazla video formatı kullanılabileceği durumlarda tercih edilen formatı belirler.\"\n  STR_PREFERRED_VIDEO_ANIMATION: \"Animasyon\"\n  STR_PREFERRED_VIDEO_SLIDESHOW: \"Slayt Gösterisi\"\n  STR_PREFERRED_FORMAT_AUTO: \"Otomatik\"\n  STR_CURRENT_FORMAT: \"Mevcut: {0}\"\n  STR_SOUND_OPTIONS: \"Ses Ayarları\"\n  STR_BACKGROUND_MUTE: \"Arkaplanda Sessiz\"\n  STR_BACKGROUND_MUTE_DESC: \"Oyun penceresi aktif değilken tüm sesleri kapatır.\"\n  STR_FORCE_FIRE: \"Görüş açısını göz ardı et\"\n  STR_FORCE_FIRE_DESC: \"CTRL tuşuna basılı tutarak, askerleri hedefi göremedikleri durumlarda bile ateş etmeye zorlayabilirsiniz.\"\n  STR_NO_AUDIO_HARDWARE_DETECTED: \"Ses donanımı bulunamadı\"\n  STR_MOUSEWHEEL_SPEED: \"Fare tekerleği kaydırma hızı\"\n  STR_MOUSEWHEEL_SPEED_DESC: \"Fare tekerleğinin her hareketinde listelerin kaç satır kaydırılacağını belirler.\"\n  STR_DISABLED: \"Pasif\"\n  STR_MAXIMIZE_INFO_SCREENS: \"Tam ekran bilgi panelleri\"\n  STR_MAXIMIZE_INFO_SCREENS_DESC: \"Envanter ve diğer bazı bilgi panelleri, ekran ölçekleme ayarlarından bağımsız olarak, tam ekran boyutunda görüntülenir.\"\n  STR_DIARY: \"GÜNLÜK\"\n  STR_KILLED: \"ÖLDÜRÜLEN\"\n  STR_STUNNED: \"BAYILTILAN\"\n  STR_PANICKED: \"PANİKLETİLEN\"\n  STR_MINDCONTROLLED: \"KONTROL ALTINA ALINAN\"\n  STR_REGION_UNKNOWN: \"Gizli\"\n  STR_WEAPON_UNKNOWN: \"İmprovize\"\n  STR_UNKNOWN: \"Bilinmiyor\"\n  STR_VICTORY: \"Galibiyet\"\n  STR_DEFEAT: \"Mağlubiyet\"\n  STR_NO_RECORD: \"Kayıt yok\"\n  STR_HUMAN: \"İnsan\"\n  STR_FRIENDLY: \"Dost\"\n  STR_HOSTILE: \"Düşman\"\n  STR_NEUTRAL: \"Tarafsız\"\n  STR_RATING_UC: \"DEĞERLENDİRME\"\n  STR_LOCATION: \"KONUM> {ALT}{0}\"\n  STR_DAYLIGHT_TYPE: \"ZAMAN> {ALT}{0}\"\n  STR_RACE_TYPE: \"IRK> {ALT}{0}\"\n  STR_DAY: \"Gündüz\"\n  STR_NIGHT: \"Gece\"\n  STR_DAYS_WOUNDED: \"MALÜLİYET> {ALT}{0}\"\n  STR_COMBAT: \"ÇATIŞMA\"\n  STR_PERFORMANCE: \"PERFORMANS\"\n  STR_NEUTRALIZATIONS_BY_RACE: \"IRKLARA GÖRE İMHA ETTİĞİ DÜŞMAN SAYISI\"\n  STR_NEUTRALIZATIONS_BY_RANK: \"RÜTBELERE GÖRE İMHA ETTİĞİ DÜŞMAN SAYISI\"\n  STR_NEUTRALIZATIONS_BY_WEAPON: \"DÜŞMAN İMHASINDA KULLANDIĞI SİLAHLAR\"\n  STR_MISSIONS_BY_LOCATION: \"GÖREV YERLERİ\"\n  STR_MISSIONS_BY_TYPE: \"GÖREV TİPLERİ\"\n  STR_MISSIONS_BY_UFO: \"UFOLAR\"\n  STR_SCORE_VALUE: \"SKOR> {ALT}{0}\"\n  STR_WINS: \"ZAFERLER> {ALT}{0}\"\n  STR_STUNS: \"BAYILT.> {ALT}{0}\"\n  STR_PANICKS: \"PANİKLER> {ALT}{0}\"\n  STR_MINDCONTROLS: \"KONTROLLER> {ALT}{0}\"\n  STR_AWARDS: \"ÖDÜLLER\"\n  STR_COMMENDATIONS_UC: \"TAKDİRNAMELER\"\n  STR_COMMENDATIONS: \"Takdirnameler\"\n  STR_MEDALS: \"MADALYALAR\"\n  STR_LOST_IN_SERVICE: \"GÖREV BAŞINDA ŞEHİT\"\n  STR_MEDAL_NAME: \"Madalya\"\n  STR_MEDAL_AWARD_LEVEL: \"Ödül Seviyesi\"\n  STR_MEDAL_DECOR_LEVEL: \"Nişan Seviyesi\"\n  STR_AWARD_0: \"İlk ödül\"\n  STR_AWARD_1: \"İkinci ödül\"\n  STR_AWARD_2: \"Üçüncü ödül\"\n  STR_AWARD_3: \"Dördüncü ödül\"\n  STR_AWARD_4: \"Beşinci ödül\"\n  STR_AWARD_5: \"Altıncı ödül\"\n  STR_AWARD_6: \"Yedinci ödül\"\n  STR_AWARD_7: \"Sekizinci ödül\"\n  STR_AWARD_8: \"Dokuzuncu ödül\"\n  STR_AWARD_9: \"Onuncu ödül\"\n  STR_AWARD_DECOR_0: \"Yok\"\n  STR_AWARD_DECOR_1: \"İlk bronz rozet\"\n  STR_AWARD_DECOR_2: \"İkinci bronz rozet\"\n  STR_AWARD_DECOR_3: \"Üçüncü bronz rozet\"\n  STR_AWARD_DECOR_4: \"İlk gümüş rozet\"\n  STR_AWARD_DECOR_5: \"İkinci gümüş rozet\"\n  STR_AWARD_DECOR_6: \"Üçüncü gümüş rozet\"\n  STR_AWARD_DECOR_7: \"İlk altın rozet\"\n  STR_AWARD_DECOR_8: \"İkinci altın rozet\"\n  STR_AWARD_DECOR_9: \"Üçüncü altın rozet\"\n  STR_KILLED_IN_ACTION_MALE: \"ÇATIŞMADA ŞEHİT\"\n  STR_KILLED_IN_ACTION_FEMALE: \"ÇATIŞMADA ŞEHİT\"\n  STR_MISSING_IN_ACTION_MALE: \"ÇATIŞMADA KAYIP\"\n  STR_MISSING_IN_ACTION_FEMALE: \"ÇATIŞMADA KAYIP\"\n  STR_AVERAGE_MONTHLY_RATING: \"Ortalama aylık değerlendirme\"\n  STR_TOTAL_INCOME: \"Toplam gelir\"\n  STR_TOTAL_EXPENDITURE: \"Toplam harcama\"\n  STR_MISSIONS_WON: \"Başarılı görevler\"\n  STR_MISSIONS_LOST: \"Başarısız görevler\"\n  STR_NIGHT_MISSIONS: \"Gece görevleri\"\n  STR_BEST_RATING: \"En yüksek görev değerlendirmesi\"\n  STR_WORST_RATING: \"En düşük görev değerlendirmesi\"\n  STR_ALIEN_KILLS: \"Öldürülen Yabancılar\"\n  STR_ALIEN_CAPTURES: \"Ele geçirilen Yabancılar\"\n  STR_FRIENDLY_KILLS: \"Dost ateşi vukuatı\"\n  STR_AVERAGE_ACCURACY: \"Ortalama isabetlilik\"\n  STR_WEAPON_MOST_KILLS: \"En etkin silah\"\n  STR_ALIEN_MOST_KILLS: \"En ölümcül yabancı\"\n  STR_LONGEST_SERVICE: \"En uzun görev süresi\"\n  STR_TOTAL_DAYS_WOUNDED: \"Malüliyet süresi\"\n  STR_COUNTRIES_LOST: \"Sızılan ülkeler\"\n  STR_TOTAL_TERROR_SITES: \"Terör saldırıları\"\n  STR_TOTAL_BASES: \"İnşa edilen üsler\"\n  STR_TOTAL_CRAFT: \"Envanterdeki araçlar\"\n  STR_TOTAL_SCIENTISTS: \"İşe alınan bilim insanları\"\n  STR_TOTAL_ENGINEERS: \"İşe alınan mühendisler\"\n  STR_TOTAL_RESEARCH: \"Tamamlanan araştırma konuları\"\n  STR_DIARY_ACCURACY: \"İSABET> {ALT}{0}%\"\n  STR_STATISTICS: \"İstatistikler\"\n  STR_STATS: \"İST.\"\n  STR_TIME_UNITS_ABBREVIATION: \"ZÜ\"\n  STR_STAMINA_ABBREVIATION: \"DAY\"\n  STR_HEALTH_ABBREVIATION: \"SP\"\n  STR_BRAVERY_ABBREVIATION: \"CES\"\n  STR_REACTIONS_ABBREVIATION: \"TEP\"\n  STR_FIRING_ACCURACY_ABBREVIATION: \"İSB\"\n  STR_THROWING_ACCURACY_ABBREVIATION: \"FIR\"\n  STR_STRENGTH_ABBREVIATION: \"KUV\"\n  STR_MELEE_ACCURACY_ABBREVIATION: \"DÖV\"\n  STR_FOLDERS: \"DİZİNLER\"\n  STR_DATA_FOLDER: \"Veri Dizini (orijinal kaynaklar)\"\n  STR_USER_FOLDER: \"Kullanıcı Dizini (modlar, openxcom.log)\"\n  STR_SAVE_FOLDER: \"Kayıt Dizini (kayıtlı oyunlar, ekran görüntüleri)\"\n  STR_CONFIG_FOLDER: \"Ayarlar Dizini (options.cfg)\"\n  STR_DATA_FOLDER_DESC_1: \"OpenXcom'un orijinal oyun (UFO ve/ya TFTD) kaynaklarını aradığı konumdur.\"\n  STR_DATA_FOLDER_DESC_2: \"OpenXcom'ın kendi kaynakları 'common' dizininde, OpenXcom'un standart modları da 'standard' dizininde bulunur.\"\n  STR_USER_FOLDER_DESC: \"Kütük dosyası ('openxcom.log') burada tutulur. Ayrıca tüm ilave modlar da buraya ('mods' alt dizinine) kurulmalıdır.\"\n  STR_SAVE_FOLDER_DESC: \"Kayıtlı oyunlarınız burada bulunur. Ayrıca, görev üretici ayarları da ('battle.cfg') burada saklanır.\"\n  STR_CONFIG_FOLDER_DESC: \"OpenXcom ayarlarının tutulduğu dosya ('options.cfg') burada depolanır. Normalde Kullanıcı Dizini ile aynıdır.\"\n"
  },
  {
    "path": "bin/common/Language/uk.yml",
    "content": "uk:\n  STR_OPENXCOM: \"OpenXcom\"\n  STR_NEW_GAME: \"Нова гра\"\n  STR_LOAD_SAVED_GAME: \"Завантажити гру\"\n  STR_SELECT_DIFFICULTY_LEVEL: \"Виберіть рівень складності\"\n  STR_1_BEGINNER: \"1> Початківець\"\n  STR_2_EXPERIENCED: \"2> Досвідчений\"\n  STR_3_VETERAN: \"3> Ветеран\"\n  STR_4_GENIUS: \"4> Геній\"\n  STR_5_SUPERHUMAN: \"5> Надлюдина\"\n  STR_TIME: \"Час\"\n  STR_DATE: \"Дата\"\n  STR_SELECT_GAME_TO_LOAD: \"Виберіть гру для завантаження\"\n  STR_SELECT_SAVE_POSITION: \"Виберіть слот для збереження\"\n  STR_GAME_OPTIONS: \"НАЛАШТУВАННЯ\"\n  STR_LOAD_GAME: \"ЗАВАНТАЖИТИ ГРУ\"\n  STR_SAVE_GAME: \"ЗБЕРЕГТИ ГРУ\"\n  STR_ABANDON_GAME: \"ВІДМОВИТИСЬ ВІД ГРИ\"\n  STR_ABANDON_GAME_QUESTION: \"ВІДМОВИТИСЬ ВІД ГРИ?\"\n  STR_QUIT: \"Вийти\"\n  STR_SAVING_GAME: \"Збереження гри\"\n  STR_LOADING_GAME: \"Завантаження гри\"\n  STR_NO_SAVED_GAME_PRESENT: \"Немає збереженої гри\"\n  STR_LOAD_UNSUCCESSFUL: \"Завантаження не вдалось\"\n  STR_SAVE_UNSUCCESSFUL: \"Збереження не вдалось\"\n  STR_LOAD_SUCCESSFUL: \"Завантаження завершено\"\n  STR_SAVE_SUCCESSFUL: \"Збереження завершено\"\n  STR_DELETE: \"ВИДАЛИТИ\"\n  STR_DELETE_UNSUCCESSFUL: \"Видалити не вдалось\"\n  STR_IS_IT_OK_TO_DELETE_THE_SAVED_GAME: \"Точно видалити збережену гру?\"\n  STR_ORIGINAL_XCOM: \"Ориг. X-Com\"\n  STR_LOADING: \"Завантаження...\"\n  STR_DETAILS: \"ДЕТАЛІ> {ALT}{0}\"\n  STR_NEW_BATTLE: \"Нова битва\"\n  STR_OPTIONS: \"Налаштування\"\n  STR_RIGHT_CLICK_TO_DELETE: \"Клацніть правою кнопкою миші щоб видалити.\"\n  STR_RESTORE_DEFAULTS: \"Відновити початкові\"\n  STR_CONTROLS: \"УПРАВЛІННЯ\"\n  STR_GENERAL: \"Загальні\"\n  STR_GEOSCAPE: \"Глобус\"\n  STR_BATTLESCAPE: \"Тактичний бій\"\n  STR_SCREENSHOT: \"Знімок екрана\"\n  STR_FPS_COUNTER: \"Лічильник FPS\"\n  STR_ROTATE_LEFT: \"Обертати вліво\"\n  STR_ROTATE_RIGHT: \"Обертати вправо\"\n  STR_ROTATE_UP: \"Обертати вгору\"\n  STR_ROTATE_DOWN: \"Обертати вниз\"\n  STR_ZOOM_IN: \"Наблизити\"\n  STR_ZOOM_OUT: \"Віддалити\"\n  STR_TOGGLE_COUNTRY_DETAIL: \"Деталі країн Вкл./Викл.\"\n  STR_TOGGLE_RADAR_RANGES: \"Радіус радарів Вкл./Викл.\"\n  STR_SCROLL_LEFT: \"Камера вліво\"\n  STR_SCROLL_RIGHT: \"Камера вправо\"\n  STR_SCROLL_UP: \"Камера вгору\"\n  STR_SCROLL_DOWN: \"Камера вниз\"\n  STR_UNIT_LEVEL_ABOVE: \"Перейти на рівень вище\"\n  STR_UNIT_LEVEL_BELOW: \"Перейти на рівень нижче\"\n  STR_VIEW_LEVEL_ABOVE: \"Камера на 1 рівень вище\"\n  STR_VIEW_LEVEL_BELOW: \"Камера на 1 рівень нижче\"\n  STR_CENTER_SELECTED_UNIT: \"Центрувати на вибраного бійця\"\n  STR_PREVIOUS_UNIT: \"Попередній боєць\"\n  STR_NEXT_UNIT: \"Наступний боєць\"\n  STR_DESELECT_UNIT: \"Не обирати бійця повторно\"\n  STR_USE_LEFT_HAND: \"Викор. предмет в лівій руці\"\n  STR_USE_RIGHT_HAND: \"Викор. предмет в правій руці\"\n  STR_INVENTORY: \"Інвентар\"\n  STR_MINIMAP: \"Міні-карта\"\n  STR_MULTI_LEVEL_VIEW: \"Багаторівневий вид\"\n  STR_END_TURN: \"Завершити хід\"\n  STR_ABORT_MISSION: \"Перервати завдання\"\n  STR_UNIT_STATS: \"Характеристики бійця\"\n  STR_KNEEL: \"Встати на коліна\"\n  STR_RELOAD: \"Перезарядка\"\n  STR_TOGGLE_PERSONAL_LIGHTING: \"Особистий ліхтар Вкл./Викл.\"\n  STR_DONT_RESERVE_TIME_UNITS: \"Не залишати ОД (Одиниці Дій)\"\n  STR_RESERVE_TIME_UNITS_FOR_SNAP_SHOT: \"Залишити ОЧ для пострілу Навмання\"\n  STR_RESERVE_TIME_UNITS_FOR_AIMED_SHOT: \"Залишити ОЧ для Прицільного пострілу\"\n  STR_RESERVE_TIME_UNITS_FOR_AUTO_SHOT: \"Залишити ОЧ для пострілу Чергою\"\n  STR_CENTER_ON_ENEMY_1: \"Центрувати на ворога 1\"\n  STR_CENTER_ON_ENEMY_2: \"Центрувати на ворога 2\"\n  STR_CENTER_ON_ENEMY_3: \"Центрувати на ворога 3\"\n  STR_CENTER_ON_ENEMY_4: \"Центрувати на ворога 4\"\n  STR_CENTER_ON_ENEMY_5: \"Центрувати на ворога 5\"\n  STR_CENTER_ON_ENEMY_6: \"Центрувати на ворога 6\"\n  STR_CENTER_ON_ENEMY_7: \"Центрувати на ворога 7\"\n  STR_CENTER_ON_ENEMY_8: \"Центрувати на ворога 8\"\n  STR_CENTER_ON_ENEMY_9: \"Центрувати на ворога 9\"\n  STR_CENTER_ON_ENEMY_10: \"Центрувати на ворога 10\"\n  STR_CREATE_INVENTORY_TEMPLATE: \"Створити шаблон інвентаря\"\n  STR_APPLY_INVENTORY_TEMPLATE: \"Застосувати шаблон інвентаря\"\n  STR_CLEAR_INVENTORY: \"Очистити інвентар\"\n  STR_AUTO_EQUIP: \"Авто-спорядження\"\n  STR_QUICK_SAVE: \"Швидке збереження\"\n  STR_QUICK_LOAD: \"Швидке завантаження\"\n  STR_ADVANCED: \"ДОДАТКОВІ\"\n  STR_AGGRESSIVERETALIATION: \"Агресивна відплата\"\n  STR_AGGRESSIVERETALIATION_DESC: \"НЛО завжди будуть намагатись знайти Вашу базу, незалежно від їхнього завдання.\"\n  STR_STORAGELIMITSENFORCED: \"Ліміти складів для спорядження\"\n  STR_STORAGELIMITSENFORCED_DESC: \"Обмежує місткість тюрем та складів, для захоплених на місіях живих прибульців та знайдених артефактів.\"\n  STR_CANSELLLIVEALIENS: \"Продаж живих прибульців\"\n  STR_CANSELLLIVEALIENS_DESC: \"Дозволяє продаж живих прибульців, рекомендовано коли виключені ліміти складів.\"\n  STR_ALLOWBUILDINGQUEUE: \"Дозволити чергу будівництва\"\n  STR_ALLOWBUILDINGQUEUE_DESC: \"Нові модулі бази можна закладати біля тих, будівництво яких ще не завершено.\"\n  STR_BATTLEAUTOEND: \"Авто-завершення бою\"\n  STR_BATTLEAUTOEND_DESC: \"Тактичний бій завершується автоматично, після смерті останнього ворога. \"\n  STR_BATTLEINSTANTGRENADE: \"Миттєвий вибух гранат\"\n  STR_BATTLEINSTANTGRENADE_DESC: \"Гранати активовані з таймером на 0 ходів вибухають одразу після кидання, а не в кінці ходу.\"\n  STR_BATTLEUFOEXTENDERACCURACY: \"Точність як в UFO Extender\"\n  STR_BATTLEUFOEXTENDERACCURACY_DESC: \"Точність пострілів падає після певної відстані, залежно від типу пострілу. Скорегована точність буде зображена над курсором.\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE: \"Передачі в польоті\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE_DESC: \"Дозволити передачу кораблів, що перебувають в польоті.\"\n  STR_CRAFTLAUNCHALWAYS: \"Примусовий запуск кораблів\"\n  STR_CRAFTLAUNCHALWAYS_DESC: \"Корабель може бути запущений навіть коли він ще не готовий, ігноруючи потреби ремонту чи дозаправки.\"\n  STR_CUSTOMINITIALBASE: \"Своя початкова база\"\n  STR_CUSTOMINITIALBASE_DESC: \"Коли починається нова гра, Ви самі розставляєте початкові модулі, замість використання стандартної схеми.\"\n  STR_GLOBESEASONS: \"Реалістичне освітлення глобуса \"\n  STR_GLOBESEASONS_DESC: \"Використовувати більш реалістичну проекцію сонячних променів на глобус, згідно з нахилом земною осі.\"\n  STR_PLAYINTRO: \"Показувати вступний ролик\"\n  STR_PLAYINTRO_DESC: \"Показувати вступний ролик при кожному запуску гри.\"\n  STR_SHOWMORESTATSININVENTORYVIEW: \"Статистика в інвентарі\"\n  STR_SHOWMORESTATSININVENTORYVIEW_DESC: \"Показувати характеристики солдата на екрані інвентарю.\"\n  STR_SNEAKYAI: \"Підлий ШІ\"\n  STR_SNEAKYAI_DESC: \"ШІ (Штучний Інтелект) намагатиметься не показувати себе гравцю, наскільки це буде можливо.\"\n  STR_STRAFE: \"Альтернативні способи переміщення\"\n  STR_STRAFE_DESC: \"Дозволяє стрільбу, пересування та незалежний рух гармати коли утримується CTRL.\"\n  STR_BATTLEEXPLOSIONHEIGHT: \"Висота вибухів\"\n  STR_BATTLEEXPLOSIONHEIGHT_DESC: \"Змініть як далеко по вертикалі поширюватимуться вибухи.{NEWLINE}(Плоский: 0, Сферичний: 3)\"\n  STR_AUTOSAVE: \"Автозбереження\"\n  STR_AUTOSAVE_DESC: \"Автоматично зберігає гру згідно з вказаним інтервалом. Не стосується режиму Залізної Людини.\"\n  STR_AUTOSAVE_FREQUENCY: \"Частота автозбереження\"\n  STR_AUTOSAVE_FREQUENCY_DESC: \"Кількість ходів після якої гра буде автоматично збережена.\"\n  STR_ALLOWPSIONICCAPTURE: \"Дозволити псі-захоплення\"\n  STR_ALLOWPSIONICCAPTURE_DESC: \"Псі-контроль над всіма прибульцями, що залишились, означає перемогу і вони рахуються як захоплені живими.\"\n  STR_ANYTIMEPSITRAINING: \"Псі-тренування в будь-який час\"\n  STR_ANYTIMEPSITRAINING_DESC: \"Дозволяє призначати солдатів на псіонічні тренування в будь-який час місяця. Пам'ятайте, початкове тренування потребує від 30 до 60 днів.\"\n  STR_SKIPNEXTTURNSCREEN: \"Пропускати екран \\\"Наступний хід\\\"\"\n  STR_SKIPNEXTTURNSCREEN_DESC: \"Екран \\\"Наступний хід\\\", під час тактичного бою, буде зникати сам, після короткої затримки.\"\n  STR_NOT_ENOUGH_SPACE: \"Не достатньо вільного місця!\"\n  STR_WEAPONSELFDESTRUCTION: \"Самознищення зброї прибульців\"\n  STR_WEAPONSELFDESTRUCTION_DESC: \"Зброя прибульців буде самознищуватись, якщо її власник вбитий, як в XCOM 2012.\"\n  STR_RETAINCORPSES: \"Зберегати допитаних прибульців\"\n  STR_RETAINCORPSES_DESC: \"Після \\\"дослідження\\\" живих прибульців, тіло буде додано до сховища бази, як в XCOM 2012.\"\n  STR_SAVE_VOXEL_VIEW: \"Зберегти знімок екрану від першого лиця\"\n  STR_RESERVE_TIME_UNITS_FOR_KNEEL: \"Резервувати ОД для вставання на коліна\"\n  STR_EXPEND_ALL_TIME_UNITS: \"Витрачати всі доступні Очки Дій\"\n  STR_PSISTRENGTHEVAL: \"Оцінка Псі-сили\"\n  STR_PSISTRENGTHEVAL_DESC: \"Оцінює псіонічну силу всіх солдатів після завершення відповідного дослідження.\"\n  STR_DISABLEAUTOEQUIP: \"Вимкнути авто-спорядження\"\n  STR_DISABLEAUTOEQUIP_DESC: \"Вимкнути авто-спорядження солдатів перед боєм.\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT: \"Дозволити покращення Псі-сили\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT_DESC: \"Псіонічна сила солдатів може бути покращена досвідом та тренуванням.\"\n  STR_BATTLESMOOTHCAMERA: \"Плавна камера пострілів\"\n  STR_BATTLESMOOTHCAMERA_DESC: \"Камера в Режимі Тактичного Бою залишається центрованою на снарядах, допоки вони видимі.\"\n  STR_BATTLECONFIRMFIREMODE: \"Режим підтвердження пострілів\"\n  STR_BATTLECONFIRMFIREMODE_DESC: \"Потрібен повторний клік по клітинці для підтвердження наказу стріляти.\"\n  STR_SELECT_BASE_1: \"Вибрати базу 1\"\n  STR_SELECT_BASE_2: \"Вибрати базу 2\"\n  STR_SELECT_BASE_3: \"Вибрати базу 3\"\n  STR_SELECT_BASE_4: \"Вибрати базу 4\"\n  STR_SELECT_BASE_5: \"Вибрати базу 5\"\n  STR_SELECT_BASE_6: \"Вибрати базу 6\"\n  STR_SELECT_BASE_7: \"Вибрати базу 7\"\n  STR_SELECT_BASE_8: \"Вибрати базу 8\"\n  STR_VIDEO: \"ВІДЕО\"\n  STR_AUDIO: \"ЗВУК\"\n  STR_BATTLESCAPE_UC: \"ТАКТИЧНИЙ БІЙ\"\n  STR_MODS_UC: \"МОДИ\"\n  STR_MODS: \"Моди\"\n  STR_DISPLAY_RESOLUTION: \"Роздільна здатність\"\n  STR_DISPLAY_RESOLUTION_DESC: \"Змінює роздільну здатність екрану, роздільна здатність гри буде змінена відповідно. Стрілки перемикають між підтримуваними значеннями. Клікніть мишкою щоб ввести власне значення.\"\n  STR_ORIGINAL: \"Оригінал\"\n  STR_DISPLAY_MODE: \"Режим екрану\"\n  STR_WINDOWED: \"Віконний\"\n  STR_FULLSCREEN: \"Повноекранний\"\n  STR_BORDERLESS: \"Без рамки\"\n  STR_DISPLAY_LANGUAGE: \"Мова\"\n  STR_DISPLAY_LANGUAGE_DESC: \"Змінює мову текстів у грі.\"\n  STR_DISPLAY_FILTER: \"Екранний фільтр\"\n  STR_DISPLAY_FILTER_DESC: \"Змінює фільтр застосований до ігрового екрану.{NEWLINE}*вимагає апаратне прискорення OpenGL.\"\n  STR_DISPLAY_OPTIONS: \"Налаштування екрану\"\n  STR_LETTERBOXED: \"Леттербоксинг\"\n  STR_LETTERBOXED_DESC: \"Додає чорні смуги для збереження оригінального співвідношення сторін зображення.\"\n  STR_RESIZABLE: \"Змінювати розміри\"\n  STR_LOCK_MOUSE: \"Захопити мишку\"\n  STR_LOCK_MOUSE_DESC: \"Утримувати курсор миші в межах вікна гри. Ctrl+G для переключення цього режиму в будь-який час.\"\n  STR_FIXED_WINDOW_POSITION: \"Фікс. позиція вікна\"\n  STR_FIXED_WINDOW_POSITION_DESC: \"Встановити фiксовану позицiю Вiкна\"\n  STR_DISPLAY_SET_WINDOW_POSITION: \"Встановити нову Корінну позицію вікна\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_X: \"Лівої  межі новий X:\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_Y: \"Верхньої межі новий Y:\"\n  STR_MUSIC_VOLUME: \"Гучність музики\"\n  STR_MUSIC_VOLUME_DESC: \"Змінює гучність фонової музики.\"\n  STR_SFX_VOLUME: \"Гучність ефектів\"\n  STR_SFX_VOLUME_DESC: \"Змінює гучність звукових ефектів\"\n  STR_UI_VOLUME: \"Гучність інтерфейсу\"\n  STR_UI_VOLUME_DESC: \"Змінює гучність пікання кнопок інтерфейсу.\"\n  STR_SCROLL_SPEED: \"Швидкість прокрутки\"\n  STR_SCROLL_SPEED_GEO_DESC: \"Змінює швидкість прокрутки глобуса.\"\n  STR_SCROLL_SPEED_BATTLE_DESC: \"Змінює швидкість прокрутки карти.\"\n  STR_DOGFIGHT_SPEED: \"Швидкість повітрян. бою\"\n  STR_DOGFIGHT_SPEED_DESC: \"Змінює швидкість повітряних боїв перехоплення між винищувачами та НЛО. Менші швидкості можуть покращити швидкодію на слабких системах. \"\n  STR_CLOCK_SPEED: \"Швидкість годинника\"\n  STR_CLOCK_SPEED_DESC: \"Змінює швидкість годинника в Режимі Глобуса. Менші швидкості можуть покращити швидкодію на слабких системах.\"\n  STR_GLOBE_DETAILS: \"Деталі глобуса\"\n  STR_GLOBE_COUNTRIES: \"Країни\"\n  STR_GLOBE_COUNTRIES_DESC: \"Показує фінансуючі країни на глобусі.\"\n  STR_GLOBE_RADARS: \"Радари\"\n  STR_GLOBE_RADARS_DESC: \"Показує дальність радарів баз на глобусі.\"\n  STR_GLOBE_FLIGHT_PATHS: \"Маршрути польотів\"\n  STR_GLOBE_FLIGHT_PATHS_DESC: \"Показує маршрути польотів кораблів на глобусі.\"\n  STR_CONTROLS_DESC: \"Натисніть лівою кнопкою миші на скорочення, а потім клавішу яку ви хочете призначити.{NEWLINE}Натисніть правою кнопкою на скорочення для відключення.\"\n  STR_BASE_GAME: \"Основна гра\"\n  STR_MODS_TOOLTIP: \"Версія {0} від {1}.{NEWLINE}{2}\"\n  STR_EDGE_SCROLL: \"Прокрутка на краях\"\n  STR_EDGE_SCROLL_DESC: \"Тригер: Прокручувати карту коли ліва кнопка миші затиснута на краю екрану.{NEWLINE}Авто: Прокручувати карту коли вказівник миші на краю екрану.\"\n  STR_TRIGGER_SCROLL: \"Тригер\"\n  STR_AUTO_SCROLL: \"Авто\"\n  STR_DRAG_SCROLL: \"Прокрутка перетягуванням\"\n  STR_DRAG_SCROLL_DESC: \"Прокручує карту, перетягуючи курсор затиснувши вказану кнопку миші.\"\n  STR_LEFT_MOUSE_BUTTON: \"Ліва кнопка\"\n  STR_MIDDLE_MOUSE_BUTTON: \"Середня (колесо)\"\n  STR_RIGHT_MOUSE_BUTTON: \"Права кнопка\"\n  STR_FIRE_SPEED: \"Швидкість вогню\"\n  STR_FIRE_SPEED_DESC: \"Змінює швидкість польоту пострілів зі зброї.\"\n  STR_PLAYER_MOVEMENT_SPEED: \"Швидкість руху гравця\"\n  STR_PLAYER_MOVEMENT_SPEED_DESC: \"Змінює швидкість руху одиниць керованих гравцем.\"\n  STR_COMPUTER_MOVEMENT_SPEED: \"Швидкість руху ШІ\"\n  STR_COMPUTER_MOVEMENT_SPEED_DESC: \"Змінює швидкість пересування одиниць керованих комп'ютетром.\"\n  STR_PATH_PREVIEW: \"Перегляд шляху\"\n  STR_PATH_ARROWS: \"Стрілки\"\n  STR_PATH_ARROWS_DESC: \"Клік показує шлях яким одиниця піде до цілі. Колір позначає доступні дії: Зелений - може рухатись та стріляти; Жовтий - може рухатись; Червоний - не може рухатись.\"\n  STR_PATH_TIME_UNIT_COST: \"Одиниці дій\"\n  STR_PATH_TIME_UNIT_COST_DESC: \"Клік показує кількість Одиниць Дій, що залишаться після руху у вказану точку.\"\n  STR_USER_INTERFACE_OPTIONS: \"Налаштування інтерфейсу\"\n  STR_TOOLTIPS: \"Підказки\"\n  STR_TOOLTIPS_DESC: \"Показує підказки для кнопок в режимі Тактичного Бою.\"\n  STR_DEATH_NOTIFICATIONS: \"Cповіщення про смерть\"\n  STR_DEATH_NOTIFICATIONS_DESC: \"Показувати сповіщення про смерть кожного разу, коли помирає хтось із ваших солдатів.\"\n  STR_SHOW_FUNDS: \"Показувати фонди\"\n  STR_SHOW_FUNDS_DESC: \"Показує ваші фонди біля годинника в режимі Глобуса.\"\n  STR_MISSION_GENERATOR: \"ГЕНЕРАТОР МІСІЙ\"\n  STR_MAP_OPTIONS: \"НАЛАШТУВАННЯ КАРТИ\"\n  STR_ALIEN_OPTIONS: \"НАЛАШТУВАННЯ ПРИБУЛЬЦІВ\"\n  STR_MAP_TERRAIN: \"Місцевість\"\n  STR_MAP_DARKNESS: \"Темрява\"\n  STR_MAP_DEPTH: \"Глибина\"\n  STR_DIFFICULTY: \"Складність\"\n  STR_ALIEN_RACE: \"Раса\"\n  STR_ALIEN_TECH_LEVEL: \"Технічний рівень\"\n  STR_RANDOMIZE: \"Випадково\"\n  STR_OXCE_REQUIRED_QUESTION: \"Для коректної роботи цього моду потрібен OpenXcom {0}. Ввімкнути мод?\"\n  STR_RESTORE_DEFAULTS_QUESTION: \"Ви дійсно хочете відновити налаштування по замовчуванню?\"\n  STR_DISPLAY_OPTIONS_CONFIRM: \"Ви бажаєте зберегти поточні налаштування екрану?\"\n  STR_DISPLAY_OPTIONS_REVERT: \"Повернення налаштувань через 0:{0}\"\n  STR_MISSING_CONTENT_PROMPT: \"ПОПЕРЕДЖЕННЯ:{SMALLLINE}Це збереження залежить від модів, які зараз не доступні. Відсутній вміст буде видалено, при завантаженні можливий збій.{NEWLINE}Продовжувати?\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT: \"Зберігати активовані гранати\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT_DESC: \"Зберігати гранати, попередньо активовані на екрані інвентарю перед боєм, в шаблоні спорядження бійця.\"\n  STR_NEWSEEDONLOAD: \"Чітерство зі збереженнями\"\n  STR_NEWSEEDONLOAD_DESC: \"Завантаження гри буде скидати посів генератора випадкових чисел, тому та сама дія може мати інші результати. Не стосується Режиму Залізної Людини.\"\n  STR_CHANGEVALUEBYMOUSEWHEEL: \"Змінювати значення за допом. колеса миші\"\n  STR_CHANGEVALUEBYMOUSEWHEEL_DESC: \"Дозволяє використовувати колесо миші для збільшення/зменшення значень на вказану величину.\"\n  STR_BATTLEHAIRBLEACH: \"Покращені спрайти бійців\"\n  STR_BATTLEHAIRBLEACH_DESC: \"Змінює спрайти солдатів в Режимі Тактичного Бою, щоб відповідати їх вигляду в інвентарі.\"\n  STR_DRAGSCROLLINVERT: \"Інвертувати прокрутку перетягуванням\"\n  STR_DRAGSCROLLINVERT_DESC: \"Коли увімкнено, перетягування прокручує екран в протилежному напрямку.\"\n  STR_BATTLESCAPE_SCALE: \"Масштаб в реж. Бою\"\n  STR_BATTLESCAPE_SCALE_DESC: \"Область перегляду Режиму Тактичного Бою, на основі фіксованої роздільної здатності (розтягувати, щоб вмістити), або фіксоване збільшення (розширювати, щоб заповнити).\"\n  STR_GEOSCAPE_SCALE: \"Масштаб в реж. Глобуса\"\n  STR_GEOSCAPESCALE_SCALE_DESC: \"Область перегляду Режиму Глобуса, на основі фіксованої роздільної здатності (розтягувати, щоб вмістити), або фіксоване збільшення (розширювати, щоб заповнити).\"\n  STR_1_5X: \"1.5x оригіналу\"\n  STR_2X: \"2x оригіналу\"\n  STR_THIRD_DISPLAY: \"1/3 екрану\"\n  STR_HALF_DISPLAY: \"1/2 екрану\"\n  STR_FULL_DISPLAY: \"Повний екран\"\n  STR_FPS_LIMIT: \"Ліміт кадрів (FPS)\"\n  STR_FPS_LIMIT_DESC: \"Обмеження кількості оновлень екрану за секунду. 0 - без ліміту. Якщо увімкнено режим OpenGL, гра використовує Вертикальну Синхронізацію (VSync).\"\n  STR_FPS_INACTIVE_LIMIT: \"Ліміт кадрів у фоновому режимі (FPS)\"\n  STR_FPS_INACTIVE_LIMIT_DESC: \"Обмежує кількість оновлень екрану в секунду, коли OpenXcom в фоновому режимі.\"\n  STR_NOALIENPANICMESSAGES: \"Придушити повідомлення про паніку прибульців\"\n  STR_NOALIENPANICMESSAGES_DESC: \"Не показувати повідомлення про паніку прибульців, поки їх не бачить гравець.\"\n  STR_ALIENBLEEDING: \"Кровотечі у прибульців\"\n  STR_ALIENBLEEDING_DESC: \"Дозволяє нанесення фатальних ран більшості прибульців\"\n  STR_FIELDPROMOTIONS: \"Польові підвищення\"\n  STR_FIELDPROMOTIONS_DESC: \"Тільки солдати які побували на місці висадки мають право на підвищення.\"\n  STR_MEETINGPOINT: \"Передбачити траекторію НЛО\"\n  STR_MEETINGPOINT_DESC: \"Літаки літять в точку зустрічи з НЛО на підставі їх поточної таекторії\"\n  STR_IRONMAN: \"ЗАЛІЗНА ЛЮДИНА\"\n  STR_IRONMAN_DESC: \"Без ручного збереження.\"\n  STR_SAVE_AND_ABANDON_GAME: \"ЗБЕРЕГТИ ТА ПОКИНУТИ ГРУ\"\n  STR_MOD_UNSUCCESSFUL: \"Помилка при завантаженні моду\"\n  STR_NEW_SAVED_GAME_SLOT: \"<НОВА ЗБЕРЕЖЕНА ГРА>\"\n  STR_AUTO_SAVE_GEOSCAPE_SLOT: \"<АВТОЗБЕРЕЖЕННЯ ГЛОБУСУ>\"\n  STR_AUTO_SAVE_BATTLESCAPE_SLOT: \"<АВТОЗБЕРЕЖЕННЯ БИТВИ>\"\n  STR_QUICK_SAVE_SLOT: \"<ШВИДКЕ ЗБЕРЕЖЕННЯ>\"\n  STR_DISPLAY_MODE_DESC: \"Змінює те, як гра відображається на екрані.\"\n  STR_PREFERRED_MUSIC_FORMAT: \"Формат музики\"\n  STR_PREFERRED_MUSIC_FORMAT_DESC: \"Встановлює бажаний формат музики, якщо доступно кілька варіантів.{NEWLINE}УВАГА: відтворення MIDI може мати проблеми на Windows.\"\n  STR_PREFERRED_SFX_FORMAT: \"Формат звук. ефектів\"\n  STR_PREFERRED_SFX_FORMAT_DESC: \"Встановлює бажаний формат звукових ефектів, якщо доступно кілька.\"\n  STR_PREFERRED_VIDEO_FORMAT: \"Відео формат\"\n  STR_PREFERRED_VIDEO_FORMAT_DESC: \"Обирає переважний відео формат для використання коли доступно декілька\"\n  STR_PREFERRED_VIDEO_ANIMATION: \"Анімація\"\n  STR_PREFERRED_VIDEO_SLIDESHOW: \"Слайд-шоу\"\n  STR_PREFERRED_FORMAT_AUTO: \"Авто\"\n  STR_CURRENT_FORMAT: \"Поточне: {0}\"\n  STR_SOUND_OPTIONS: \"Налаштування звуку\"\n  STR_BACKGROUND_MUTE: \"Вимкнути звук у фоні\"\n  STR_BACKGROUND_MUTE_DESC: \"Вимкнути всі звуки коли вікно гри не активне.\"\n  STR_FORCE_FIRE: \"Ігнорувати лінію вогню\"\n  STR_FORCE_FIRE_DESC: \"Дозволяє змушувати ваших солдат стріляти тримаючи CTRL, незалежно від наявності лінії вогню.\"\n  STR_NO_AUDIO_HARDWARE_DETECTED: \"Не знайдено звукового обладнання\"\n  STR_MOUSEWHEEL_SPEED: \"Швидкість прокрукти мишкою\"\n  STR_MOUSEWHEEL_SPEED_DESC: \"Задати кількість рядків на які прокручуються списки за допомогою колеса миші.\"\n  STR_DISABLED: \"Відключено\"\n  STR_MAXIMIZE_INFO_SCREENS: \"Максимізувати інформаційні екрани\"\n  STR_MAXIMIZE_INFO_SCREENS_DESC: \"Інвентар та різні інші екрани будуть показані на весь екран, незалежно від налаштувань масштабування.\"\n  STR_DIARY: \"Щоденник\"\n  STR_KILLED: \"ВБИТО \"\n  STR_STUNNED: \"ПРИГОЛОМШЕНИЙ\"\n  STR_PANICKED: \"ЗПАНІКУВАВ\"\n  STR_MINDCONTROLLED: \"ПІД КОНТРОЛЕМ\"\n  STR_REGION_UNKNOWN: \"Нерозкритий\"\n  STR_WEAPON_UNKNOWN: \"Імпровізація\"\n  STR_UNKNOWN: \"Невідомий\"\n  STR_VICTORY: \"Перемога\"\n  STR_DEFEAT: \"Поразка\"\n  STR_NO_RECORD: \"Нема запису\"\n  STR_HUMAN: \"Людина\"\n  STR_FRIENDLY: \"Дружний\"\n  STR_HOSTILE: \"Ворожий\"\n  STR_NEUTRAL: \"Нейтральний \"\n  STR_RATING_UC: \"Рейтинг\"\n  STR_LOCATION: \"ЛОКАЦІЯ> {ALT}{0}\"\n  STR_DAYLIGHT_TYPE: \"ЧАС> {ALT}{0}\"\n  STR_RACE_TYPE: \"РАСА> {ALT}{0}\"\n  STR_DAY: \"День\"\n  STR_NIGHT: \"Ніч\"\n  STR_DAYS_WOUNDED: \"ДНІВ ПОРАН.> {ALT}{0}\"\n  STR_COMBAT: \"БІЙ\"\n  STR_PERFORMANCE: \"ШВИДКІСТЬ\"\n  STR_NEUTRALIZATIONS_BY_RACE: \"ЗНЕШКОДЖЕННЯ ЗА РАСОЮ\"\n  STR_NEUTRALIZATIONS_BY_RANK: \"ЗНЕШКОДЖЕННЯ ЗА ЗВАННЯМ\"\n  STR_NEUTRALIZATIONS_BY_WEAPON: \"ЗНЕШКОДЖЕННЯ ЗА ЗБРОЄЮ\"\n  STR_MISSIONS_BY_LOCATION: \"МІСІЙ ЗА ЛОКАЦІЄЮ\"\n  STR_MISSIONS_BY_TYPE: \"МІСІЙ ЗА ТИПОМ\"\n  STR_MISSIONS_BY_UFO: \"МІСІЙ ЗА НЛО\"\n  STR_SCORE_VALUE: \"РАХУНОК> {ALT}{0}\"\n  STR_WINS: \"ПЕРЕМОГ> {ALT}{0}\"\n  STR_STUNS: \"ПРИГОЛОМШЕНЬ> {ALT}{0}\"\n  STR_PANICKS: \"ПАНІК> {ALT}{0}\"\n  STR_MINDCONTROLS: \"КОНТРОЛІВ> {ALT}{0}\"\n  STR_AWARDS: \"НАГОРОД\"\n  STR_COMMENDATIONS_UC: \"УХВАЛ\"\n  STR_COMMENDATIONS: \"Ухвал\"\n  STR_MEDALS: \"Медалей\"\n  STR_LOST_IN_SERVICE: \"ЗАГИНУВ ПРИ ВИКОНАННІ\"\n  STR_MEDAL_NAME: \"Назва медалі\"\n  STR_MEDAL_AWARD_LEVEL: \"Рівень нагороди\"\n  STR_MEDAL_DECOR_LEVEL: \"Рівень Декорації\"\n  STR_AWARD_0: \"Перша нагорода\"\n  STR_AWARD_1: \"Друга нагорода\"\n  STR_AWARD_2: \"Третя нагорода\"\n  STR_AWARD_3: \"Четверта нагорода\"\n  STR_AWARD_4: \"П'ята нагорода\"\n  STR_AWARD_5: \"Шоста нагорода\"\n  STR_AWARD_6: \"Сьома нагоррда\"\n  STR_AWARD_7: \"Восьма нагорода\"\n  STR_AWARD_8: \"Дев'ята нагорода\"\n  STR_AWARD_9: \"Десята нагорода\"\n  STR_AWARD_DECOR_0: \"Ніц\"\n  STR_AWARD_DECOR_1: \"Перший бронзовий знак\"\n  STR_AWARD_DECOR_2: \"Другий бронзовий знак\"\n  STR_AWARD_DECOR_3: \"Третій бронзовий знак\"\n  STR_AWARD_DECOR_4: \"Перший срібний знак\"\n  STR_AWARD_DECOR_5: \"Другий срібний знак\"\n  STR_AWARD_DECOR_6: \"Третій срібний знак\"\n  STR_AWARD_DECOR_7: \"Перший золотий знак\"\n  STR_AWARD_DECOR_8: \"Другий золотий знак\"\n  STR_AWARD_DECOR_9: \"Третій золотий знак\"\n  STR_KILLED_IN_ACTION_MALE: \"ВБИТИЙ НА ЗАВДАННІ\"\n  STR_KILLED_IN_ACTION_FEMALE: \"ВБИТА  НА ЗАВДАННІ\"\n  STR_MISSING_IN_ACTION_MALE: \"ЗНИК БЕЗВІСТІ\"\n  STR_MISSING_IN_ACTION_FEMALE: \"ЗНИКЛА БЕЗВІСТІ\"\n  STR_AVERAGE_MONTHLY_RATING: \"Середній місячний рейтинг\"\n  STR_TOTAL_INCOME: \"Загальне надходження\"\n  STR_TOTAL_EXPENDITURE: \"Загальні витрати\"\n  STR_MISSIONS_WON: \"Завдання виконане\"\n  STR_MISSIONS_LOST: \"Завдання провалене\"\n  STR_NIGHT_MISSIONS: \"Нічні завдання\"\n  STR_BEST_RATING: \"Найкращій рейтинг завдань\"\n  STR_WORST_RATING: \"Найгірший рейтинг завдань\"\n  STR_ALIEN_KILLS: \"Прибульців вбито\"\n  STR_ALIEN_CAPTURES: \"Прибульців захоплено\"\n  STR_FRIENDLY_KILLS: \"Випадків дружнього вогню\"\n  STR_AVERAGE_ACCURACY: \"Середня влучність\"\n  STR_WEAPON_MOST_KILLS: \"Найефективніша зброя\"\n  STR_ALIEN_MOST_KILLS: \"Смертоносний прибулець \"\n  STR_LONGEST_SERVICE: \"Найдовше місяців в строю\"\n  STR_TOTAL_DAYS_WOUNDED: \"Днів лікування\"\n  STR_COUNTRIES_LOST: \"Країн з проникненням\"\n  STR_TOTAL_TERROR_SITES: \"Терористичних атак\"\n  STR_TOTAL_BASES: \"Баз збудовано\"\n  STR_TOTAL_CRAFT: \"Всього літаків\"\n  STR_TOTAL_SCIENTISTS: \"Вчених найнято\"\n  STR_TOTAL_ENGINEERS: \"Інженерів найнято\"\n  STR_TOTAL_RESEARCH: \"Дослідження завершено\"\n  STR_DIARY_ACCURACY: \"ВЛУЧНІСТЬ> {ALT}{0}%\"\n  STR_STATISTICS: \"Статистика\"\n  STR_STATS: \"ПОКАЗН.\"\n  STR_TIME_UNITS_ABBREVIATION: \"ОД\"\n  STR_STAMINA_ABBREVIATION: \"ВИТ\"\n  STR_HEALTH_ABBREVIATION: \"ЗД\"\n  STR_BRAVERY_ABBREVIATION: \"ХОР\"\n  STR_REACTIONS_ABBREVIATION: \"РЕА\"\n  STR_FIRING_ACCURACY_ABBREVIATION: \"ВЛУ\"\n  STR_THROWING_ACCURACY_ABBREVIATION: \"КИД\"\n  STR_STRENGTH_ABBREVIATION: \"СИЛ\"\n  STR_MELEE_ACCURACY_ABBREVIATION: \"РУК\"\n  STR_FOLDERS: \"ТЕКИ\"\n  STR_DATA_FOLDER: \"Папка даних (оригінальні ресурси)\"\n  STR_USER_FOLDER: \"Папка користувача (модифікації, openxcom.log)\"\n  STR_SAVE_FOLDER: \"Папка збереження (збережені ігри, скріншоти)\"\n  STR_CONFIG_FOLDER: \"Папка конфігурації (options.cfg)\"\n  STR_DATA_FOLDER_DESC_1: \"Тут OpenXcom шукає оригінальні ігрові ресурси (UFO та/або TFTD).\"\n  STR_DATA_FOLDER_DESC_2: \"Внутрішні ресурси OpenXcom знаходяться у теці 'common'. Вбудовані модифікації OpenXcom знаходяться у теці «standard».\"\n  STR_USER_FOLDER_DESC: \"Тут зберігається файл журналу ('openxcom.log'). Всі модифікації, створені користувачем, також знаходяться тут (у підтеці 'mods').\"\n  STR_SAVE_FOLDER_DESC: \"Тут знаходяться ваші збережені ігри. Також тут можна знайти налаштування генератора місій ('battle.cfg').\"\n  STR_CONFIG_FOLDER_DESC: \"Це місце, де зберігаються налаштування OpenXcom ('options.cfg'). Зазвичай це та сама тека, що і тека користувача.\"\n"
  },
  {
    "path": "bin/common/Language/zh-CN.yml",
    "content": "zh-CN:\n  STR_OPENXCOM: \"OpenXcom\"\n  STR_NEW_GAME: \"新游戏\"\n  STR_LOAD_SAVED_GAME: \"读取游戏\"\n  STR_SELECT_DIFFICULTY_LEVEL: \"选择难度\"\n  STR_1_BEGINNER: \"1> 新手\"\n  STR_2_EXPERIENCED: \"2> 老手\"\n  STR_3_VETERAN: \"3> 老兵\"\n  STR_4_GENIUS: \"4> 天才\"\n  STR_5_SUPERHUMAN: \"5> 超人\"\n  STR_TIME: \"时间\"\n  STR_DATE: \"日期\"\n  STR_SELECT_GAME_TO_LOAD: \"选择游戏载入\"\n  STR_SELECT_SAVE_POSITION: \"选择存档位置\"\n  STR_GAME_OPTIONS: \"选项\"\n  STR_LOAD_GAME: \"读取游戏\"\n  STR_SAVE_GAME: \"保存游戏\"\n  STR_ABANDON_GAME: \"离开游戏\"\n  STR_ABANDON_GAME_QUESTION: \"确认离开游戏？\"\n  STR_QUIT: \"退出\"\n  STR_SAVING_GAME: \"保存游戏\"\n  STR_LOADING_GAME: \"正在读取游戏\"\n  STR_NO_SAVED_GAME_PRESENT: \"暂无存档\"\n  STR_LOAD_UNSUCCESSFUL: \"读取失败\"\n  STR_SAVE_UNSUCCESSFUL: \"保存失败\"\n  STR_LOAD_SUCCESSFUL: \"读取成功\"\n  STR_SAVE_SUCCESSFUL: \"保存成功\"\n  STR_DELETE: \"删除\"\n  STR_DELETE_UNSUCCESSFUL: \"删除失败\"\n  STR_IS_IT_OK_TO_DELETE_THE_SAVED_GAME: \"你确定想删除此存档？\"\n  STR_ORIGINAL_XCOM: \"原版Xcom\"\n  STR_LOADING: \"正在加载……\"\n  STR_DETAILS: \"详细>{ALT}{0}\"\n  STR_NEW_BATTLE: \"新战斗\"\n  STR_OPTIONS: \"选项\"\n  STR_RIGHT_CLICK_TO_DELETE: \"删除请单击右键。\"\n  STR_RESTORE_DEFAULTS: \"恢复默认\"\n  STR_CONTROLS: \"控制\"\n  STR_GENERAL: \"总览\"\n  STR_GEOSCAPE: \"世界地图\"\n  STR_BATTLESCAPE: \"战场\"\n  STR_SCREENSHOT: \"截取屏幕\"\n  STR_FPS_COUNTER: \"FPS计数器\"\n  STR_ROTATE_LEFT: \"左转\"\n  STR_ROTATE_RIGHT: \"向右转\"\n  STR_ROTATE_UP: \"向上转动\"\n  STR_ROTATE_DOWN: \"向下旋转\"\n  STR_ZOOM_IN: \"放大\"\n  STR_ZOOM_OUT: \"缩小\"\n  STR_TOGGLE_COUNTRY_DETAIL: \"切换国家细节\"\n  STR_TOGGLE_RADAR_RANGES: \"切换雷达距离\"\n  STR_SCROLL_LEFT: \"向左滚动\"\n  STR_SCROLL_RIGHT: \"向右卷动\"\n  STR_SCROLL_UP: \"向上卷动\"\n  STR_SCROLL_DOWN: \"下拉\"\n  STR_UNIT_LEVEL_ABOVE: \"单位上升\"\n  STR_UNIT_LEVEL_BELOW: \"单位下降\"\n  STR_VIEW_LEVEL_ABOVE: \"视野上升\"\n  STR_VIEW_LEVEL_BELOW: \"视野下降\"\n  STR_CENTER_SELECTED_UNIT: \"将选中的单位置中显示\"\n  STR_PREVIOUS_UNIT: \"选择前一个单位\"\n  STR_NEXT_UNIT: \"选择下一个单位\"\n  STR_DESELECT_UNIT: \"不要重复选中单位\"\n  STR_USE_LEFT_HAND: \"使用左手物品\"\n  STR_USE_RIGHT_HAND: \"使用右手物品\"\n  STR_INVENTORY: \"物品\"\n  STR_MINIMAP: \"小地图\"\n  STR_MULTI_LEVEL_VIEW: \"多层视图\"\n  STR_END_TURN: \"结束回合\"\n  STR_ABORT_MISSION: \"放弃任务\"\n  STR_UNIT_STATS: \"单位统计\"\n  STR_KNEEL: \"跪下\"\n  STR_RELOAD: \"装填\"\n  STR_TOGGLE_PERSONAL_LIGHTING: \"开启个人照明装置。\"\n  STR_DONT_RESERVE_TIME_UNITS: \"不预留时间\"\n  STR_RESERVE_TIME_UNITS_FOR_SNAP_SHOT: \"保留TU用于概略射击\"\n  STR_RESERVE_TIME_UNITS_FOR_AIMED_SHOT: \"保留TU用于瞄准射击\"\n  STR_RESERVE_TIME_UNITS_FOR_AUTO_SHOT: \"保留TU用于自动射击\"\n  STR_CENTER_ON_ENEMY_1: \"将敌人1置中显示\"\n  STR_CENTER_ON_ENEMY_2: \"将敌人2置中显示\"\n  STR_CENTER_ON_ENEMY_3: \"将敌人3置中显示\"\n  STR_CENTER_ON_ENEMY_4: \"将敌人4置中显示\"\n  STR_CENTER_ON_ENEMY_5: \"将敌人5置中显示\"\n  STR_CENTER_ON_ENEMY_6: \"将敌人6置中显示\"\n  STR_CENTER_ON_ENEMY_7: \"将敌人7置中显示\"\n  STR_CENTER_ON_ENEMY_8: \"将敌人8置中显示\"\n  STR_CENTER_ON_ENEMY_9: \"将敌人9置中显示\"\n  STR_CENTER_ON_ENEMY_10: \"将敌人10置中显示\"\n  STR_CREATE_INVENTORY_TEMPLATE: \"创建物品栏模板\"\n  STR_APPLY_INVENTORY_TEMPLATE: \"套用物品栏模板\"\n  STR_CLEAR_INVENTORY: \"清除物品栏\"\n  STR_AUTO_EQUIP: \"自动装备\"\n  STR_QUICK_SAVE: \"快速保存\"\n  STR_QUICK_LOAD: \"快速存档\"\n  STR_ADVANCED: \"高级\"\n  STR_AGGRESSIVERETALIATION: \"报复行动\"\n  STR_AGGRESSIVERETALIATION_DESC: \"UFO会试图寻找你的基地位置，不论其任务参数如何。\"\n  STR_STORAGELIMITSENFORCED: \"缴获物品的存储上限\"\n  STR_STORAGELIMITSENFORCED_DESC: \"外星人研究室和存储仓库都将有存储限制。\"\n  STR_CANSELLLIVEALIENS: \"出售活体异形\"\n  STR_CANSELLLIVEALIENS_DESC: \"允许出售活的外星人，推荐使用存储区的空间。\"\n  STR_ALLOWBUILDINGQUEUE: \"启用建筑队列\"\n  STR_ALLOWBUILDINGQUEUE_DESC: \"新的建筑可以建在未完工的建筑旁边\"\n  STR_BATTLEAUTOEND: \"自动结束战斗\"\n  STR_BATTLEAUTOEND_DESC: \"当最后一个敌人被击毙后，战斗会自动结束。\"\n  STR_BATTLEINSTANTGRENADE: \"即时手榴弹\"\n  STR_BATTLEINSTANTGRENADE_DESC: \"手榴弹设定在0回合时将在投掷出后立即爆炸，而不会在当回合结束后爆炸。\"\n  STR_BATTLEUFOEXTENDERACCURACY: \"UFO精度衰减\"\n  STR_BATTLEUFOEXTENDERACCURACY_DESC: \"依据选择的射击类型，射击精度将随距离下降。最终的命中率显示在光标旁边。\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE: \"空运\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE_DESC: \"在飞行中的飞行器能被转移到其他基地。\"\n  STR_CRAFTLAUNCHALWAYS: \"强行起飞\"\n  STR_CRAFTLAUNCHALWAYS_DESC: \"战机可以强制起飞，即使维护没有完成。\"\n  STR_CUSTOMINITIALBASE: \"自定义初始基地\"\n  STR_CUSTOMINITIALBASE_DESC: \"开始新游戏时，你可以手动设置初始设施的位置。\"\n  STR_GLOBESEASONS: \"写实的光照\"\n  STR_GLOBESEASONS_DESC: \"为世界地图使用较为真实的光照阴影，考虑地轴倾角。\"\n  STR_PLAYINTRO: \"播放片头动画\"\n  STR_PLAYINTRO_DESC: \"显示启动时的介绍影片。\"\n  STR_SHOWMORESTATSININVENTORYVIEW: \"物品栏状态\"\n  STR_SHOWMORESTATSININVENTORYVIEW_DESC: \"在物品栏界面为选中的士兵显示额外信息。\"\n  STR_SNEAKYAI: \"行动隐匿的AI\"\n  STR_SNEAKYAI_DESC: \"人工智能尽可能避免让自己暴露在玩家面前。\"\n  STR_STRAFE: \"额外行动\"\n  STR_STRAFE_DESC: \"按下CTRL键时，启用扫射，奔跑，以及独立的坦克炮塔运动。\"\n  STR_BATTLEEXPLOSIONHEIGHT: \"爆炸高度\"\n  STR_BATTLEEXPLOSIONHEIGHT_DESC: \"改变爆炸影响高度{NEWLINE}(Flat: 0, Round: 3)\"\n  STR_AUTOSAVE: \"自动存档\"\n  STR_AUTOSAVE_DESC: \"在一些特定的节点自动保存游戏。不适用于铁人模式。\"\n  STR_AUTOSAVE_FREQUENCY: \"自动保存频率\"\n  STR_AUTOSAVE_FREQUENCY_DESC: \"自动保存之间的回合数间隔。\"\n  STR_ALLOWPSIONICCAPTURE: \"允许精神控制\"\n  STR_ALLOWPSIONICCAPTURE_DESC: \"所有剩下的异形被精神控制后算胜利，被精神控制的异形成为俘虏。\"\n  STR_ANYTIMEPSITRAINING: \"随时接受灵能训练\"\n  STR_ANYTIMEPSITRAINING_DESC: \"在一个月的任何时刻都可以指派士兵去接受灵能训练。注意，初始训练需耗时30至60天。\"\n  STR_SKIPNEXTTURNSCREEN: \"跳过“下回合”画面\"\n  STR_SKIPNEXTTURNSCREEN_DESC: \"“下一回合”提示将在短暂的延迟后自动消失。\"\n  STR_NOT_ENOUGH_SPACE: \"没有足够空间\"\n  STR_WEAPONSELFDESTRUCTION: \"外星武器自毁\"\n  STR_WEAPONSELFDESTRUCTION_DESC: \"外星人携带的武器将会在携带者死亡后自毁，就像在XCOM2012版里一样。\"\n  STR_RETAINCORPSES_DESC: \"在对活体外星人进行研究后，其身体会被添加进基地商店以供出售，类似XCOM 2012。\"\n  STR_SAVE_VOXEL_VIEW: \"保存第一人称截屏照片\"\n  STR_RESERVE_TIME_UNITS_FOR_KNEEL: \"预留蹲下时间\"\n  STR_EXPEND_ALL_TIME_UNITS: \"消耗所有剩余的TU\"\n  STR_PSISTRENGTHEVAL: \"灵能力量评估\"\n  STR_PSISTRENGTHEVAL_DESC: \"在适当的研究完成后，可以评估所有士兵的灵能力量。\"\n  STR_DISABLEAUTOEQUIP: \"关闭自动分配装备\"\n  STR_DISABLEAUTOEQUIP_DESC: \"在战斗开始前不自动为士兵分配装备\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT: \"允许灵能力量提升\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT_DESC: \"士兵的灵能力量可以由训练和实战得到提升。\"\n  STR_BATTLESMOOTHCAMERA: \"镜头跟踪弹头\"\n  STR_BATTLESMOOTHCAMERA_DESC: \"在弹头飞行过程中，战场镜头将一直聚焦于弹头。\"\n  STR_BATTLECONFIRMFIREMODE: \"确认开火模式\"\n  STR_BATTLECONFIRMFIREMODE_DESC: \"在同一个目标上点击第二次以确认开火命令。\"\n  STR_SELECT_BASE_1: \"选择基地1\"\n  STR_SELECT_BASE_2: \"选择基地2\"\n  STR_SELECT_BASE_3: \"选择基地3\"\n  STR_SELECT_BASE_4: \"选择基地4\"\n  STR_SELECT_BASE_5: \"选择基地5\"\n  STR_SELECT_BASE_6: \"选择基地6\"\n  STR_SELECT_BASE_7: \"选择基地7\"\n  STR_SELECT_BASE_8: \"选择基地8\"\n  STR_VIDEO: \"视频\"\n  STR_AUDIO: \"音频\"\n  STR_BATTLESCAPE_UC: \"战场\"\n  STR_MODS_UC: \"模组\"\n  STR_MODS: \"模组\"\n  STR_DISPLAY_RESOLUTION: \"显示分辨率\"\n  STR_DISPLAY_RESOLUTION_DESC: \"改变显示分辨率，可以选择支持的分辨率或者输入指定的分辨率。\"\n  STR_ORIGINAL: \"原始设置\"\n  STR_DISPLAY_MODE: \"显示模式\"\n  STR_WINDOWED: \"窗口化\"\n  STR_FULLSCREEN: \"全屏\"\n  STR_BORDERLESS: \"宽屏\"\n  STR_DISPLAY_LANGUAGE: \"显示语言\"\n  STR_DISPLAY_LANGUAGE_DESC: \"改变游戏内文本的语言。\"\n  STR_DISPLAY_FILTER: \"显示过滤\"\n  STR_DISPLAY_FILTER_DESC: \"改变用于游戏屏幕的过滤器。{NEWLINE}*需要OpenGL硬件加速。\"\n  STR_DISPLAY_OPTIONS: \"显示选项\"\n  STR_LETTERBOXED: \"宽屏\"\n  STR_LETTERBOXED_DESC: \"宽屏并保持原有长宽比\"\n  STR_RESIZABLE: \"重新设定尺寸\"\n  STR_LOCK_MOUSE: \"拾取鼠标指针\"\n  STR_LOCK_MOUSE_DESC: \"阻止鼠标指针移出游戏窗口，使用Ctrl+G切换开关。\"\n  STR_FIXED_WINDOW_POSITION: \"固定窗口位置\"\n  STR_MUSIC_VOLUME: \"音乐音量\"\n  STR_MUSIC_VOLUME_DESC: \"改变背景音乐的音量。\"\n  STR_SFX_VOLUME: \"背景音乐音量\"\n  STR_SFX_VOLUME_DESC: \"改变音效的音量。\"\n  STR_UI_VOLUME: \"UI音量\"\n  STR_UI_VOLUME_DESC: \"改变界面提示音的音量。\"\n  STR_SCROLL_SPEED: \"卷轴速度\"\n  STR_SCROLL_SPEED_GEO_DESC: \"改变世界地图的卷动速度。\"\n  STR_SCROLL_SPEED_BATTLE_DESC: \"改变战场地图的卷动速度。\"\n  STR_DOGFIGHT_SPEED: \"空战显示速度\"\n  STR_DOGFIGHT_SPEED_DESC: \"改变拦截机与UFO的空战显示速度。较低的速度可以在性能较差的设备上提高游戏运行表现。\"\n  STR_CLOCK_SPEED: \"时钟速度\"\n  STR_CLOCK_SPEED_DESC: \"改变世界地图上时钟的速度。较慢的速度可以在性能较差的设备上提高游戏运行表现。\"\n  STR_GLOBE_DETAILS: \"世界地图细节\"\n  STR_GLOBE_COUNTRIES: \"国家\"\n  STR_GLOBE_COUNTRIES_DESC: \"在世界地图上显示资助国家\"\n  STR_GLOBE_RADARS: \"雷达\"\n  STR_GLOBE_RADARS_DESC: \"在世界地图上显示雷达探测范围\"\n  STR_GLOBE_FLIGHT_PATHS: \"飞行路径\"\n  STR_GLOBE_FLIGHT_PATHS_DESC: \"在世界地图上显示飞行路径\"\n  STR_CONTROLS_DESC: \"左键单击并按所需的键来更改快捷键。{NEWLINE}右键单击一个快捷键来禁用它。\"\n  STR_BASE_GAME: \"游戏本体\"\n  STR_MODS_TOOLTIP: \"版本{0}作者{1}。{NEWLINE}{2}\"\n  STR_EDGE_SCROLL: \"边缘卷动\"\n  STR_EDGE_SCROLL_DESC: \"触发：鼠标置于屏幕边缘并按下左键以卷动地图。{NEWLINE}自动：鼠标光标置于屏幕边缘时自动卷动。\"\n  STR_TRIGGER_SCROLL: \"触发\"\n  STR_AUTO_SCROLL: \"自动\"\n  STR_DRAG_SCROLL: \"拖动卷动\"\n  STR_DRAG_SCROLL_DESC: \"当特定的鼠标按键被按住不放并拖动鼠标时卷动地图。\"\n  STR_LEFT_MOUSE_BUTTON: \"鼠标左键\"\n  STR_MIDDLE_MOUSE_BUTTON: \"鼠标中键\"\n  STR_RIGHT_MOUSE_BUTTON: \"鼠标右键\"\n  STR_FIRE_SPEED: \"弹药速度\"\n  STR_FIRE_SPEED_DESC: \"改变弹药的飞行速度。\"\n  STR_PLAYER_MOVEMENT_SPEED: \"玩家移动速度\"\n  STR_PLAYER_MOVEMENT_SPEED_DESC: \"改变玩家单位的移动速度。\"\n  STR_COMPUTER_MOVEMENT_SPEED: \"AI移动速度\"\n  STR_COMPUTER_MOVEMENT_SPEED_DESC: \"改变AI单位的移动速度。\"\n  STR_PATH_PREVIEW: \"路径预览\"\n  STR_PATH_ARROWS: \"箭头\"\n  STR_PATH_ARROWS_DESC: \"点击显示单位的移动路线。颜色指示了许可的行动：绿色-可以移动并开火；黄色-可以移动；红色-不能移动。\"\n  STR_PATH_TIME_UNIT_COST: \"时间单位TU\"\n  STR_PATH_TIME_UNIT_COST_DESC: \"点击显示单位到达目的地后剩余的TU。\"\n  STR_USER_INTERFACE_OPTIONS: \"UI选项\"\n  STR_TOOLTIPS: \"提示\"\n  STR_TOOLTIPS_DESC: \"为战场按钮显示提示。\"\n  STR_DEATH_NOTIFICATIONS: \"显示阵亡通知单\"\n  STR_DEATH_NOTIFICATIONS_DESC: \"任何时间当你的士兵死亡现实提示信息\"\n  STR_SHOW_FUNDS: \"显示资金状况\"\n  STR_SHOW_FUNDS_DESC: \"在时钟旁显示当前资金状况。\"\n  STR_MISSION_GENERATOR: \"任务生成器\"\n  STR_MAP_OPTIONS: \"地图选项\"\n  STR_ALIEN_OPTIONS: \"外星人选项\"\n  STR_MAP_TERRAIN: \"地形\"\n  STR_MAP_DARKNESS: \"暗度\"\n  STR_MAP_DEPTH: \"深度\"\n  STR_DIFFICULTY: \"难度\"\n  STR_ALIEN_RACE: \"种族\"\n  STR_ALIEN_TECH_LEVEL: \"技术等级\"\n  STR_RANDOMIZE: \"随机\"\n  STR_RESTORE_DEFAULTS_QUESTION: \"确定要使用默认设置？\"\n  STR_DISPLAY_OPTIONS_CONFIRM: \"是否保留当前的显示设置？\"\n  STR_DISPLAY_OPTIONS_REVERT: \"{0}秒后返回之前的设置\"\n  STR_MISSING_CONTENT_PROMPT: \"警告：{SMALLLINE}该存档所使用的模组不可用。丢失的内容将被移除，且读取可能失败。{NEWLINE}继续？\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT: \"保留待发手雷\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT_DESC: \"保留于放置在士兵物品栏中的待发手雷。\"\n  STR_NEWSEEDONLOAD: \"重新生成随机数种子\"\n  STR_NEWSEEDONLOAD_DESC: \"读取游戏存档时将重置随机数种子，这样同一个动作将有不同的结果。不适用于铁人模式。\"\n  STR_CHANGEVALUEBYMOUSEWHEEL: \"使用鼠标滚轮来改变值\"\n  STR_CHANGEVALUEBYMOUSEWHEEL_DESC: \"允许你使用鼠标滚轮来增减数值。\"\n  STR_BATTLEHAIRBLEACH: \"士兵图像效果增强\"\n  STR_BATTLEHAIRBLEACH_DESC: \"改变战场上士兵的图像效果，与其所持物品相契合。\"\n  STR_DRAGSCROLLINVERT: \"反转拖动卷屏方向\"\n  STR_DRAGSCROLLINVERT_DESC: \"当启用时，卷屏方向将与与鼠标移动方向相反。\"\n  STR_BATTLESCAPE_SCALE: \"战场尺寸\"\n  STR_BATTLESCAPE_SCALE_DESC: \"战斗场景的显示模式，固定分辨率（将拉伸画面以填满屏幕）或者是固定放大等级（将扩展可视区域以填满屏幕）。\"\n  STR_GEOSCAPE_SCALE: \"世界地图尺寸\"\n  STR_GEOSCAPESCALE_SCALE_DESC: \"地理地图的显示模式，固定分辨率（将拉伸画面以填满屏幕）或者是固定放大等级（将扩展可视区域以填满屏幕）。\"\n  STR_1_5X: \"1.5倍原始值\"\n  STR_2X: \"2倍原始值\"\n  STR_THIRD_DISPLAY: \"1/3显示\"\n  STR_HALF_DISPLAY: \"1/2显示\"\n  STR_FULL_DISPLAY: \"全显示\"\n  STR_FPS_LIMIT: \"帧率限制\"\n  STR_FPS_LIMIT_DESC: \"每秒屏幕画面更新次数的限制，设为0则没有限制。如果启用OpenGL 渲染，游戏将使用垂直同步代替这项设置。\"\n  STR_FPS_INACTIVE_LIMIT: \"后台帧率限制\"\n  STR_FPS_INACTIVE_LIMIT_DESC: \"当OpenXcom后台运行时，限制帧率。\"\n  STR_NOALIENPANICMESSAGES: \"不显示外星人处于恐惧状态的信息\"\n  STR_NOALIENPANICMESSAGES_DESC: \"在外星人不可见时，不显示这些外星人处于恐惧状态的提示。\"\n  STR_ALIENBLEEDING: \"外星人正在流血\"\n  STR_ALIENBLEEDING_DESC: \"可以使大多数外星人受到致命伤害。\"\n  STR_FIELDPROMOTIONS: \"晋升\"\n  STR_FIELDPROMOTIONS_DESC: \"只有出现在任务地点的士兵可以得到晋升。\"\n  STR_MEETINGPOINT: \"预计的UFO飞行轨迹\"\n  STR_MEETINGPOINT_DESC: \"战机将按UFO当前轨迹飞向一个能与之交汇的地点。\"\n  STR_IRONMAN: \"铁人\"\n  STR_IRONMAN_DESC: \"禁止手动保存\"\n  STR_SAVE_AND_ABANDON_GAME: \"保存并离开游戏\"\n  STR_MOD_UNSUCCESSFUL: \"模组载入失败\"\n  STR_NEW_SAVED_GAME_SLOT: \"<新的游戏存档>\"\n  STR_AUTO_SAVE_GEOSCAPE_SLOT: \"<自动世界地图>\"\n  STR_AUTO_SAVE_BATTLESCAPE_SLOT: \"<自动战场地图>\"\n  STR_QUICK_SAVE_SLOT: \"<快速保存>\"\n  STR_DISPLAY_MODE_DESC: \"改变游戏在屏幕中的显示方式。\"\n  STR_PREFERRED_MUSIC_FORMAT: \"音乐格式\"\n  STR_PREFERRED_MUSIC_FORMAT_DESC: \"当存在多种音乐格式时，选择要使用的一种。{NEWLINE}提示：MIDI格式在Windows下不稳定。\"\n  STR_PREFERRED_SFX_FORMAT: \"音效格式\"\n  STR_PREFERRED_SFX_FORMAT_DESC: \"当存在多种音效格式时，选择要使用的一种。\"\n  STR_PREFERRED_VIDEO_FORMAT: \"视频格式\"\n  STR_PREFERRED_VIDEO_FORMAT_DESC: \"当存在多种视频格式时，选择需要使用的一种。\"\n  STR_PREFERRED_VIDEO_ANIMATION: \"动画\"\n  STR_PREFERRED_FORMAT_AUTO: \"自动\"\n  STR_CURRENT_FORMAT: \"当前:{0}\"\n  STR_SOUND_OPTIONS: \"声音选项\"\n  STR_BACKGROUND_MUTE: \"后台运行时静音\"\n  STR_BACKGROUND_MUTE_DESC: \"在游戏窗口不活动时关闭所有声音。\"\n  STR_FORCE_FIRE: \"无视射界\"\n  STR_FORCE_FIRE_DESC: \"允许你在按下CTRL键时命令士兵强制开火，无视射界规则。\"\n  STR_NO_AUDIO_HARDWARE_DETECTED: \"没有检测到音频硬件\"\n  STR_MOUSEWHEEL_SPEED: \"鼠标滚轮滚动速度\"\n  STR_MOUSEWHEEL_SPEED_DESC: \"调整鼠标滚轮滚动一次使画面滚动的行数。\"\n  STR_DISABLED: \"禁用\"\n  STR_MAXIMIZE_INFO_SCREENS: \"最大化信息栏\"\n  STR_MAXIMIZE_INFO_SCREENS_DESC: \"不论设置如何，物品界面和其他一些界面将会全屏显示。\"\n  STR_DIARY: \"日志\"\n  STR_KILLED: \"阵亡\"\n  STR_STUNNED: \"昏迷\"\n  STR_PANICKED: \"恐慌\"\n  STR_MINDCONTROLLED: \"受到心灵控制\"\n  STR_REGION_UNKNOWN: \"未暴露\"\n  STR_UNKNOWN: \"未知\"\n  STR_VICTORY: \"赢啦\"\n  STR_DEFEAT: \"输咯\"\n  STR_NO_RECORD: \"无记录\"\n  STR_HUMAN: \"人类\"\n  STR_FRIENDLY: \"友好\"\n  STR_HOSTILE: \"敌对\"\n  STR_NEUTRAL: \"中立\"\n  STR_RATING_UC: \"评价\"\n  STR_LOCATION: \"地点>{ALT}{0}\"\n  STR_DAYLIGHT_TYPE: \"时间>{ALT}{0}\"\n  STR_RACE_TYPE: \"种族>{ALT}{0}\"\n  STR_DAY: \"昼间\"\n  STR_NIGHT: \"夜间\"\n  STR_DAYS_WOUNDED: \"归队时间>{ALT}{0}\"\n  STR_COMBAT: \"战斗\"\n  STR_PERFORMANCE: \"表现\"\n  STR_NEUTRALIZATIONS_BY_RACE: \"歼敌，按种族排列\"\n  STR_NEUTRALIZATIONS_BY_RANK: \"歼敌，按等级排列\"\n  STR_NEUTRALIZATIONS_BY_WEAPON: \"歼敌，按武器排列\"\n  STR_MISSIONS_BY_LOCATION: \"任务，按地点排列\"\n  STR_MISSIONS_BY_TYPE: \"任务，按种类排列\"\n  STR_MISSIONS_BY_UFO: \"任务，按UFO类型排列\"\n  STR_SCORE_VALUE: \"分数>{ALT}{0}\"\n  STR_WINS: \"胜利>{ALT}{0}\"\n  STR_STUNS: \"昏迷>{ALT}{0}\"\n  STR_PANICKS: \"恐慌>{ALT}{0}\"\n  STR_MINDCONTROLS: \"受到心灵控制>{ALT}{0}\"\n  STR_AWARDS: \"奖励\"\n  STR_COMMENDATIONS_UC: \"奖励\"\n  STR_COMMENDATIONS: \"奖励\"\n  STR_MEDALS: \"勋章\"\n  STR_LOST_IN_SERVICE: \"与服务器断开连接\"\n  STR_MEDAL_NAME: \"勋章名称\"\n  STR_MEDAL_AWARD_LEVEL: \"奖励等级\"\n  STR_AWARD_0: \"第一奖励\"\n  STR_AWARD_1: \"第二奖励\"\n  STR_AWARD_2: \"第三奖励\"\n  STR_AWARD_3: \"第四奖励\"\n  STR_AWARD_4: \"第五奖励\"\n  STR_AWARD_5: \"第六奖励\"\n  STR_AWARD_6: \"第七奖励\"\n  STR_AWARD_7: \"第八奖励\"\n  STR_AWARD_8: \"第九奖励\"\n  STR_AWARD_9: \"第十奖励\"\n  STR_AWARD_DECOR_0: \"无\"\n  STR_KILLED_IN_ACTION_MALE: \"阵亡\"\n  STR_KILLED_IN_ACTION_FEMALE: \"阵亡\"\n  STR_MISSING_IN_ACTION_MALE: \"失踪\"\n  STR_MISSING_IN_ACTION_FEMALE: \"失踪\"\n  STR_AVERAGE_MONTHLY_RATING: \"月均评级\"\n  STR_TOTAL_INCOME: \"总收入\"\n  STR_TOTAL_EXPENDITURE: \"总支出\"\n  STR_MISSIONS_WON: \"任务成功\"\n  STR_MISSIONS_LOST: \"任务失败\"\n  STR_NIGHT_MISSIONS: \"夜间任务\"\n  STR_BEST_RATING: \"最佳评级\"\n  STR_WORST_RATING: \"最低评级\"\n  STR_ALIEN_KILLS: \"干掉外星人\"\n  STR_ALIEN_CAPTURES: \"俘获外星人\"\n  STR_FRIENDLY_KILLS: \"误伤\"\n  STR_AVERAGE_ACCURACY: \"射击散布\"\n  STR_WEAPON_MOST_KILLS: \"最佳武器\"\n  STR_ALIEN_MOST_KILLS: \"致命的外星人！\"\n  STR_LONGEST_SERVICE: \"最长服役月数\"\n  STR_TOTAL_DAYS_WOUNDED: \"患病岁月～\"\n  STR_COUNTRIES_LOST: \"已潜入地区\"\n  STR_TOTAL_TERROR_SITES: \"恐怖袭击\"\n  STR_TOTAL_BASES: \"基地已建造\"\n  STR_TOTAL_CRAFT: \"飞船已拥有\"\n  STR_TOTAL_SCIENTISTS: \"科学家已收编\"\n  STR_TOTAL_ENGINEERS: \"工程师已收编\"\n  STR_TOTAL_RESEARCH: \"研究完毕\"\n  STR_DIARY_ACCURACY: \"射击散布> {ALT}{0}%\"\n  STR_STATISTICS: \"收获统计\"\n  STR_STATS: \"数据统计\"\n  STR_TIME_UNITS_ABBREVIATION: \"时间单位\"\n  STR_STAMINA_ABBREVIATION: \"耐力\"\n  STR_HEALTH_ABBREVIATION: \"体力\"\n  STR_BRAVERY_ABBREVIATION: \"勇气\"\n  STR_REACTIONS_ABBREVIATION: \"反应\"\n  STR_FIRING_ACCURACY_ABBREVIATION: \"速度\"\n  STR_THROWING_ACCURACY_ABBREVIATION: \"投掷\"\n  STR_STRENGTH_ABBREVIATION: \"力量\"\n  STR_MELEE_ACCURACY_ABBREVIATION: \"灵能\"\n"
  },
  {
    "path": "bin/common/Language/zh-TW.yml",
    "content": "zh-TW:\n  STR_OPENXCOM: \"OpenXcom\"\n  STR_NEW_GAME: \"開始新遊戲\"\n  STR_LOAD_SAVED_GAME: \"載入進度\"\n  STR_SELECT_DIFFICULTY_LEVEL: \"選擇難度\"\n  STR_1_BEGINNER: \"1> 初學者\"\n  STR_2_EXPERIENCED: \"2> 熟練者\"\n  STR_3_VETERAN: \"3> 老手級\"\n  STR_4_GENIUS: \"4> 天才級\"\n  STR_5_SUPERHUMAN: \"5> 超人級\"\n  STR_TIME: \"時間\"\n  STR_DATE: \"日期\"\n  STR_SELECT_GAME_TO_LOAD: \"選擇載入的遊戲進度\"\n  STR_SELECT_SAVE_POSITION: \"選擇儲存位置\"\n  STR_GAME_OPTIONS: \"遊戲選項\"\n  STR_LOAD_GAME: \"載入進度\"\n  STR_SAVE_GAME: \"儲存進度\"\n  STR_ABANDON_GAME: \"放棄現在的進度\"\n  STR_ABANDON_GAME_QUESTION: \"放棄進度？\"\n  STR_QUIT: \"退出\"\n  STR_SAVING_GAME: \"正在儲存遊戲\"\n  STR_LOADING_GAME: \"正在載入遊戲\"\n  STR_NO_SAVED_GAME_PRESENT: \"沒有遊戲存檔\"\n  STR_LOAD_UNSUCCESSFUL: \"載入失敗\"\n  STR_SAVE_UNSUCCESSFUL: \"儲存失敗\"\n  STR_LOAD_SUCCESSFUL: \"載入成功\"\n  STR_SAVE_SUCCESSFUL: \"儲存成功\"\n  STR_DELETE: \"刪除\"\n  STR_DELETE_UNSUCCESSFUL: \"刪除失敗\"\n  STR_IS_IT_OK_TO_DELETE_THE_SAVED_GAME: \"是否確定刪除存檔？\"\n  STR_ORIGINAL_XCOM: \"原版X-Com\"\n  STR_LOADING: \"載入中...\"\n  STR_DETAILS: \"詳情> {ALT}{0}\"\n  STR_NEW_BATTLE: \"新的戰鬥\"\n  STR_OPTIONS: \"選項\"\n  STR_RIGHT_CLICK_TO_DELETE: \"按滑鼠右鍵刪除。\"\n  STR_RESTORE_DEFAULTS: \"回歸預設值\"\n  STR_CONTROLS: \"控制\"\n  STR_GENERAL: \"一般\"\n  STR_GEOSCAPE: \"地球界面\"\n  STR_BATTLESCAPE: \"戰鬥界面\"\n  STR_SCREENSHOT: \"截圖\"\n  STR_FPS_COUNTER: \"FPS計數器\"\n  STR_ROTATE_LEFT: \"轉左\"\n  STR_ROTATE_RIGHT: \"轉右\"\n  STR_ROTATE_UP: \"轉上\"\n  STR_ROTATE_DOWN: \"轉下\"\n  STR_ZOOM_IN: \"放大\"\n  STR_ZOOM_OUT: \"縮小\"\n  STR_TOGGLE_COUNTRY_DETAIL: \"切換國家細節\"\n  STR_TOGGLE_RADAR_RANGES: \"切換雷達範圍\"\n  STR_SCROLL_LEFT: \"往左捲動\"\n  STR_SCROLL_RIGHT: \"往右捲動\"\n  STR_SCROLL_UP: \"往上捲動\"\n  STR_SCROLL_DOWN: \"往下捲動\"\n  STR_UNIT_LEVEL_ABOVE: \"將單位上移\"\n  STR_UNIT_LEVEL_BELOW: \"將單位下移\"\n  STR_VIEW_LEVEL_ABOVE: \"檢視上層\"\n  STR_VIEW_LEVEL_BELOW: \"檢視下層\"\n  STR_CENTER_SELECTED_UNIT: \"將指定單位置中\"\n  STR_PREVIOUS_UNIT: \"選擇上個單位\"\n  STR_NEXT_UNIT: \"選擇下個單位\"\n  STR_DESELECT_UNIT: \"不重新選擇單位\"\n  STR_USE_LEFT_HAND: \"使用左手物品\"\n  STR_USE_RIGHT_HAND: \"使用右手物品\"\n  STR_INVENTORY: \"庫存\"\n  STR_MINIMAP: \"小地圖\"\n  STR_MULTI_LEVEL_VIEW: \"多層檢視\"\n  STR_END_TURN: \"結束回合\"\n  STR_ABORT_MISSION: \"放棄任務\"\n  STR_UNIT_STATS: \"單位狀態\"\n  STR_KNEEL: \"跪姿\"\n  STR_RELOAD: \"重新裝填\"\n  STR_TOGGLE_PERSONAL_LIGHTING: \"切換個人照明\"\n  STR_DONT_RESERVE_TIME_UNITS: \"不要保留TU\"\n  STR_RESERVE_TIME_UNITS_FOR_SNAP_SHOT: \"為快速射擊保留TU\"\n  STR_RESERVE_TIME_UNITS_FOR_AIMED_SHOT: \"為精密射擊保留TU\"\n  STR_RESERVE_TIME_UNITS_FOR_AUTO_SHOT: \"為自動射擊保留TU\"\n  STR_CENTER_ON_ENEMY_1: \"將1號敵人置中\"\n  STR_CENTER_ON_ENEMY_2: \"將2號敵人置中\"\n  STR_CENTER_ON_ENEMY_3: \"將3號敵人置中\"\n  STR_CENTER_ON_ENEMY_4: \"將4號敵人置中\"\n  STR_CENTER_ON_ENEMY_5: \"將5號敵人置中\"\n  STR_CENTER_ON_ENEMY_6: \"將6號敵人置中\"\n  STR_CENTER_ON_ENEMY_7: \"將7號敵人置中\"\n  STR_CENTER_ON_ENEMY_8: \"將8號敵人置中\"\n  STR_CENTER_ON_ENEMY_9: \"將9號敵人置中\"\n  STR_CENTER_ON_ENEMY_10: \"將10號敵人置中\"\n  STR_CREATE_INVENTORY_TEMPLATE: \"建立庫存模板\"\n  STR_APPLY_INVENTORY_TEMPLATE: \"套用庫存模板\"\n  STR_CLEAR_INVENTORY: \"清除庫存\"\n  STR_AUTO_EQUIP: \"自動裝備\"\n  STR_QUICK_SAVE: \"快速存檔\"\n  STR_QUICK_LOAD: \"快速讀檔\"\n  STR_ADVANCED: \"進階\"\n  STR_AGGRESSIVERETALIATION: \"積極反擊\"\n  STR_AGGRESSIVERETALIATION_DESC: \"不論他們的任務為何，UFO會持續嘗試偵測您的基地。\"\n  STR_STORAGELIMITSENFORCED: \"尋獲物品的貯存上限\"\n  STR_STORAGELIMITSENFORCED_DESC: \"強迫外星生物收容室和倉庫從任務中回收外星活體生物、文物等容器的上限。\"\n  STR_CANSELLLIVEALIENS: \"販售活體外星生物\"\n  STR_CANSELLLIVEALIENS_DESC: \"允許販售活體外星生物，推薦已設定貯存上限時。\"\n  STR_ALLOWBUILDINGQUEUE: \"允許建築序列\"\n  STR_ALLOWBUILDINGQUEUE_DESC: \"新設施可置於未完成的設施旁。\"\n  STR_BATTLEAUTOEND: \"自動結束戰鬥\"\n  STR_BATTLEAUTOEND_DESC: \"當最後一名敵人失去敵意時，戰鬥自動結束。\"\n  STR_BATTLEINSTANTGRENADE: \"即效手榴彈\"\n  STR_BATTLEINSTANTGRENADE_DESC: \"手榴彈將會於拋出後立即爆炸，而非回合結束時。\"\n  STR_BATTLEUFOEXTENDERACCURACY: \"UFO強化命中率\"\n  STR_BATTLEUFOEXTENDERACCURACY_DESC: \"命中率會與距離成反比，並與射擊類別有關。校正後的命中率會顯示於游標。\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE: \"空運\"\n  STR_CANTRANSFERCRAFTSWHILEAIRBORNE_DESC: \"飛行中的載具可以被傳輸。\"\n  STR_CRAFTLAUNCHALWAYS: \"強制發射載具\"\n  STR_CRAFTLAUNCHALWAYS_DESC: \"載具於維修中也可以被發射。\"\n  STR_CUSTOMINITIALBASE: \"自訂初始基地\"\n  STR_CUSTOMINITIALBASE_DESC: \"當開始新遊戲時，您可以手動設定起始設施，而非使用預設值。\"\n  STR_GLOBESEASONS: \"真實球體照明\"\n  STR_GLOBESEASONS_DESC: \"根據地軸傾斜，顯示更真實的日照。\"\n  STR_PLAYINTRO: \"播放開場動畫\"\n  STR_PLAYINTRO_DESC: \"啟動時播放開場動畫。\"\n  STR_SHOWMORESTATSININVENTORYVIEW: \"庫存狀態\"\n  STR_SHOWMORESTATSININVENTORYVIEW_DESC: \"在庫存畫面顯示已選士兵的額外資訊。\"\n  STR_SNEAKYAI: \"匿蹤AI\"\n  STR_SNEAKYAI_DESC: \"AI會盡可能不曝露自己的行蹤。\"\n  STR_STRAFE: \"另類移動方式\"\n  STR_STRAFE_DESC: \"允許按住CTRL鍵時獨立操作砲塔、掃射、和跑步。\"\n  STR_BATTLEEXPLOSIONHEIGHT: \"爆炸高度\"\n  STR_BATTLEEXPLOSIONHEIGHT_DESC: \"設定爆炸影響高度。{NEWLINE}(平地:0 圓形:3)\"\n  STR_AUTOSAVE: \"自動存檔\"\n  STR_AUTOSAVE_DESC: \"於指定時間間隔自動存檔。不適用於鐵人模式。\"\n  STR_AUTOSAVE_FREQUENCY: \"自動存檔頻率\"\n  STR_AUTOSAVE_FREQUENCY_DESC: \"每隔多少回合自動存檔。\"\n  STR_ALLOWPSIONICCAPTURE: \"允許心智捕獲\"\n  STR_ALLOWPSIONICCAPTURE_DESC: \"勝利時心靈控制所有活著的外星生物，並將它們計算為生擒。\"\n  STR_ANYTIMEPSITRAINING: \"彈性心智訓練\"\n  STR_ANYTIMEPSITRAINING_DESC: \"允許於每月的任意時刻安排士兵進行新制訓練。請謹記，初始訓練將耗時30至60天。\"\n  STR_SKIPNEXTTURNSCREEN: \"忽略「下個回合」畫面\"\n  STR_SKIPNEXTTURNSCREEN_DESC: \"戰鬥中的「下個回合」畫面將自動以短暫的停滯取代。\"\n  STR_NOT_ENOUGH_SPACE: \"空間不夠!\"\n  STR_WEAPONSELFDESTRUCTION: \"自動銷毀外星生物武器\"\n  STR_WEAPONSELFDESTRUCTION_DESC: \"被外星生物持有的武器將於其持主死亡後自毀，如同XCOM 2012中的設定。\"\n  STR_RETAINCORPSES: \"保留外星生物遺骸\"\n  STR_RETAINCORPSES_DESC: \"當完成外星活體生物「研究」後，遺骸將置入基地倉庫，如同XCOM 2012的設定。\"\n  STR_SAVE_VOXEL_VIEW: \"貯存第一人稱截圖\"\n  STR_RESERVE_TIME_UNITS_FOR_KNEEL: \"保留跪姿的TU\"\n  STR_EXPEND_ALL_TIME_UNITS: \"消耗所有剩餘TU\"\n  STR_PSISTRENGTHEVAL: \"PSI強度評估\"\n  STR_PSISTRENGTHEVAL_DESC: \"當適當的科技研發後，評估所有的士兵心智強度。\"\n  STR_DISABLEAUTOEQUIP: \"關閉自動裝備\"\n  STR_DISABLEAUTOEQUIP_DESC: \"關閉戰鬥前為新士兵自動裝備。\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT: \"允許提升心智強度\"\n  STR_ALLOWPSISTRENGTHIMPROVEMENT_DESC: \"士兵的心智強度可被訓練或隨經驗強化。\"\n  STR_BATTLESMOOTHCAMERA: \"平滑彈道攝影\"\n  STR_BATTLESMOOTHCAMERA_DESC: \"當彈藥飛行時，攝影機會被置中。\"\n  STR_BATTLECONFIRMFIREMODE: \"確認開火模式\"\n  STR_BATTLECONFIRMFIREMODE_DESC: \"需要第二次點擊以確認開火模式。\"\n  STR_SELECT_BASE_1: \"選擇1號基地\"\n  STR_SELECT_BASE_2: \"選擇2號基地\"\n  STR_SELECT_BASE_3: \"選擇3號基地\"\n  STR_SELECT_BASE_4: \"選擇4號基地\"\n  STR_SELECT_BASE_5: \"選擇5號基地\"\n  STR_SELECT_BASE_6: \"選擇6號基地\"\n  STR_SELECT_BASE_7: \"選擇7號基地\"\n  STR_SELECT_BASE_8: \"選擇8號基地\"\n  STR_VIDEO: \"視訊\"\n  STR_AUDIO: \"音效\"\n  STR_BATTLESCAPE_UC: \"戰鬥畫面\"\n  STR_MODS_UC: \"模組\"\n  STR_MODS: \"模組\"\n  STR_DISPLAY_RESOLUTION: \"解像度\"\n  STR_DISPLAY_RESOLUTION_DESC: \"改變解析度，遊戲畫面將會重新取樣以符合尺寸。箭頭按鈕可在支援的解析度間切換。點擊以輸入自訂解析度。\"\n  STR_ORIGINAL: \"原始\"\n  STR_DISPLAY_MODE: \"顯示模式\"\n  STR_WINDOWED: \"視窗\"\n  STR_FULLSCREEN: \"全螢幕\"\n  STR_BORDERLESS: \"無邊框\"\n  STR_DISPLAY_LANGUAGE: \"顯示語言\"\n  STR_DISPLAY_LANGUAGE_DESC: \"改變遊戲中文字的語言。\"\n  STR_DISPLAY_FILTER: \"顯示濾鏡\"\n  STR_DISPLAY_FILTER_DESC: \"改變遊戲畫面使用的濾鏡。{NEWLINE}*需要OpenGL硬體加速。\"\n  STR_DISPLAY_OPTIONS: \"顯示選項\"\n  STR_LETTERBOXED: \"字幕框\"\n  STR_LETTERBOXED_DESC: \"顯示字幕框以保持原顯示比例。\"\n  STR_RESIZABLE: \"可調整尺寸\"\n  STR_LOCK_MOUSE: \"滑鼠邊框\"\n  STR_LOCK_MOUSE_DESC: \"將游標移動範圍限制在遊戲視窗內。可隨時以Ctrl+G開關此設定。\"\n  STR_FIXED_WINDOW_POSITION: \"固定視窗位置\"\n  STR_FIXED_WINDOW_POSITION_DESC: \"固定視窗位置。\"\n  STR_DISPLAY_SET_WINDOW_POSITION: \"設定新的視窗初始位置\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_X: \"左邊界新X座標:\"\n  STR_DISPLAY_WINDOW_POSITION_NEW_Y: \"上邊界新Y座標:\"\n  STR_MUSIC_VOLUME: \"音樂音量\"\n  STR_MUSIC_VOLUME_DESC: \"改變背景音樂音量。\"\n  STR_SFX_VOLUME: \"效果聲音量\"\n  STR_SFX_VOLUME_DESC: \"改變音效音量。\"\n  STR_UI_VOLUME: \"使用者介面音量\"\n  STR_UI_VOLUME_DESC: \"改變介面的嗶聲。\"\n  STR_SCROLL_SPEED: \"滾動速度\"\n  STR_SCROLL_SPEED_GEO_DESC: \"改變旋轉球體的速度。\"\n  STR_SCROLL_SPEED_BATTLE_DESC: \"改變捲動地圖的速度。\"\n  STR_DOGFIGHT_SPEED: \"戰鬥速度\"\n  STR_DOGFIGHT_SPEED_DESC: \"改變載具間的截擊戰速度。低速可改善低階硬體設備的效能。\"\n  STR_CLOCK_SPEED: \"時頻\"\n  STR_CLOCK_SPEED_DESC: \"改變球體介面的時間流逝率。低速可改善低階硬體設備的效能。\"\n  STR_GLOBE_DETAILS: \"球體細節\"\n  STR_GLOBE_COUNTRIES: \"國家\"\n  STR_GLOBE_COUNTRIES_DESC: \"在球體顯示資助的國家。\"\n  STR_GLOBE_RADARS: \"雷達\"\n  STR_GLOBE_RADARS_DESC: \"在球體顯示基地的雷達感測範圍。\"\n  STR_GLOBE_FLIGHT_PATHS: \"飛行路徑\"\n  STR_GLOBE_FLIGHT_PATHS_DESC: \"在球體顯示載具航道。\"\n  STR_CONTROLS_DESC: \"左擊捷徑並輸入一個按鍵以改變它。{NEWLINE}右擊捷徑以關閉。\"\n  STR_BASE_GAME: \"基於遊戲\"\n  STR_MODS_TOOLTIP: \"{1}的版本{0}。{NEWLINE}{2}\"\n  STR_EDGE_SCROLL: \"邊緣捲動\"\n  STR_EDGE_SCROLL_DESC: \"觸動: 當游標在螢幕邊緣時按住滑鼠左鍵不放。{NEWLINE}自動: 當游標在螢幕邊緣時，自動捲動地圖。\"\n  STR_TRIGGER_SCROLL: \"觸動\"\n  STR_AUTO_SCROLL: \"自動\"\n  STR_DRAG_SCROLL: \"拖曳捲動\"\n  STR_DRAG_SCROLL_DESC: \"當按壓並拖曳特定滑鼠按鍵時，捲動地圖。\"\n  STR_LEFT_MOUSE_BUTTON: \"左鍵\"\n  STR_MIDDLE_MOUSE_BUTTON: \"中鍵\"\n  STR_RIGHT_MOUSE_BUTTON: \"右鍵\"\n  STR_FIRE_SPEED: \"射擊速度\"\n  STR_FIRE_SPEED_DESC: \"改變彈道的速度。\"\n  STR_PLAYER_MOVEMENT_SPEED: \"玩家移動速度\"\n  STR_PLAYER_MOVEMENT_SPEED_DESC: \"改變玩家的單位移動速度。\"\n  STR_COMPUTER_MOVEMENT_SPEED: \"AI移動速度\"\n  STR_COMPUTER_MOVEMENT_SPEED_DESC: \"改變電腦控制的單位移動速度。\"\n  STR_PATH_PREVIEW: \"路徑預覽\"\n  STR_PATH_ARROWS: \"箭頭\"\n  STR_PATH_ARROWS_DESC: \"點擊以顯示您的單位到目的地的路徑。顏色表示可能的行動：綠色-可以開火及射擊；黃色-可以移動；紅色-不可移動。\"\n  STR_PATH_TIME_UNIT_COST: \"時間單位TU\"\n  STR_PATH_TIME_UNIT_COST_DESC: \"點擊以顯示您的單位到目的地後還剩多少TU。\"\n  STR_USER_INTERFACE_OPTIONS: \"使用者介面選項\"\n  STR_TOOLTIPS: \"工具提示\"\n  STR_TOOLTIPS_DESC: \"顯示戰鬥畫面按鈕的工具提示。\"\n  STR_DEATH_NOTIFICATIONS: \"死亡提示\"\n  STR_DEATH_NOTIFICATIONS_DESC: \"不論士兵何時死亡，跳出誰死亡的提示詳情。\"\n  STR_SHOW_FUNDS: \"顯示基金\"\n  STR_SHOW_FUNDS_DESC: \"在地景時鐘旁顯示您的當前基金。\"\n  STR_MISSION_GENERATOR: \"任務產生器\"\n  STR_MAP_OPTIONS: \"地圖選項\"\n  STR_ALIEN_OPTIONS: \"外星生物選項\"\n  STR_MAP_TERRAIN: \"地形\"\n  STR_MAP_DARKNESS: \"暗影\"\n  STR_MAP_DEPTH: \"深度\"\n  STR_DIFFICULTY: \"難度\"\n  STR_ALIEN_RACE: \"種族\"\n  STR_ALIEN_TECH_LEVEL: \"科技等級\"\n  STR_RANDOMIZE: \"隨機\"\n  STR_OXCE_REQUIRED_QUESTION: \"模組正常執行需要 OpenXcom {0}. 啟動這個模組?\"\n  STR_RESTORE_DEFAULTS_QUESTION: \"您確定要恢復預設選項？\"\n  STR_DISPLAY_OPTIONS_CONFIRM: \"您想要保留當前顯示設定？\"\n  STR_DISPLAY_OPTIONS_REVERT: \"在 0:{0} 後還原\"\n  STR_MISSING_CONTENT_PROMPT: \"警告：{SMALLLINE}此存檔需要無法使用的模組。遺失的內容將被移除，並可能讀取失敗。{NEWLINE}是否繼續？\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT: \"儲存預設定時器的手榴彈\"\n  STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT_DESC: \"儲存在戰前道具欄，士兵的裝備畫面裡預拔撞針的手榴彈。\"\n  STR_NEWSEEDONLOAD: \"變數儲存\"\n  STR_NEWSEEDONLOAD_DESC: \"讀取遊戲會重製隨機種子，所以同樣的動作會產生不同的結果。不適用於鐵人模式。\"\n  STR_CHANGEVALUEBYMOUSEWHEEL: \"用滑鼠滾輪改變數量\"\n  STR_CHANGEVALUEBYMOUSEWHEEL_DESC: \"允許您透過滑鼠滾輪增減此額度的數量。\"\n  STR_BATTLEHAIRBLEACH: \"強化的士兵外觀\"\n  STR_BATTLEHAIRBLEACH_DESC: \"改變戰鬥畫面中的外觀以符合裝備。\"\n  STR_DRAGSCROLLINVERT: \"反向拖曳捲動\"\n  STR_DRAGSCROLLINVERT_DESC: \"啟用時，捲動方向將與滑鼠拖曳方向相反。\"\n  STR_BATTLESCAPE_SCALE: \"戰鬥畫面縮放\"\n  STR_BATTLESCAPE_SCALE_DESC: \"戰鬥畫面縮放模式，將以固定解析度(延展以符合解析度)或固定縮放程度(延伸以填滿畫面)。\"\n  STR_GEOSCAPE_SCALE: \"球體畫面縮放\"\n  STR_GEOSCAPESCALE_SCALE_DESC: \"球體畫面縮放模式，將以固定解析度(延展以符合解析度)或固定縮放程度(延伸以填滿畫面)。\"\n  STR_1_5X: \"原始大小1.5倍\"\n  STR_2X: \"原始大小2倍\"\n  STR_THIRD_DISPLAY: \"顯示1/3\"\n  STR_HALF_DISPLAY: \"顯示1/2\"\n  STR_FULL_DISPLAY: \"完整顯示\"\n  STR_FPS_LIMIT: \"FPS限制\"\n  STR_FPS_LIMIT_DESC: \"限制每秒更新幀數(FPS)，0代表不限制。若已啟用OpenGL繪圖，遊戲將會使用Vsync。\"\n  STR_FPS_INACTIVE_LIMIT: \"FPS背景限制\"\n  STR_FPS_INACTIVE_LIMIT_DESC: \"OpenXcom在背景模式的FPS限制。\"\n  STR_NOALIENPANICMESSAGES: \"降低外星生物恐慌訊息\"\n  STR_NOALIENPANICMESSAGES_DESC: \"除非外星生物出現在玩家視野，否則不顯示外星生物恐慌訊息。\"\n  STR_ALIENBLEEDING: \"外星生物傷口出血\"\n  STR_ALIENBLEEDING_DESC: \"允許多數的外星生物會受到致命重傷。\"\n  STR_FIELDPROMOTIONS: \"戰場晉升\"\n  STR_FIELDPROMOTIONS_DESC: \"只有出勤的士兵可獲得晉升。\"\n  STR_MEETINGPOINT: \"預測UFO航線\"\n  STR_MEETINGPOINT_DESC: \"載具前往UFO當前航線的匯集點。\"\n  STR_IRONMAN: \"鐵人\"\n  STR_IRONMAN_DESC: \"無手動存檔功能\"\n  STR_SAVE_AND_ABANDON_GAME: \"存檔並放棄遊戲\"\n  STR_MOD_UNSUCCESSFUL: \"無法讀取MOD\"\n  STR_NEW_SAVED_GAME_SLOT: \"<新的遊戲存檔>\"\n  STR_AUTO_SAVE_GEOSCAPE_SLOT: \"<AUTO GEOSCAPE>\"\n  STR_AUTO_SAVE_BATTLESCAPE_SLOT: \"<AUTO BATTLESCAPE>\"\n  STR_QUICK_SAVE_SLOT: \"<QUICKSAVE>\"\n  STR_DISPLAY_MODE_DESC: \"改變遊戲在您的螢幕顯示的方式。\"\n  STR_PREFERRED_MUSIC_FORMAT: \"音樂格式\"\n  STR_PREFERRED_MUSIC_FORMAT_DESC: \"當有多種格式時，選擇您偏好的音樂格式。{NEWLINE}注意：MIDI播放在IWINDOWS系統可能會出錯。\"\n  STR_PREFERRED_SFX_FORMAT: \"音效格式\"\n  STR_PREFERRED_SFX_FORMAT_DESC: \"有多種格式時，選擇您偏好的音效格式。\"\n  STR_PREFERRED_VIDEO_FORMAT: \"視訊格式\"\n  STR_PREFERRED_VIDEO_FORMAT_DESC: \"當有多種視訊格式時，選擇您偏好的格式。\"\n  STR_PREFERRED_VIDEO_ANIMATION: \"動畫\"\n  STR_PREFERRED_VIDEO_SLIDESHOW: \"投影片\"\n  STR_PREFERRED_FORMAT_AUTO: \"自動\"\n  STR_CURRENT_FORMAT: \"當前:{0}\"\n  STR_SOUND_OPTIONS: \"音效選項\"\n  STR_BACKGROUND_MUTE: \"背景時靜音\"\n  STR_BACKGROUND_MUTE_DESC: \"當遊戲視窗於背景時靜音。\"\n  STR_FORCE_FIRE: \"無視火線原則\"\n  STR_FORCE_FIRE_DESC: \"當射擊時按下CTRL鍵，無視火線原則。\"\n  STR_NO_AUDIO_HARDWARE_DETECTED: \"未偵測到音效硬體\"\n  STR_MOUSEWHEEL_SPEED: \"滑鼠滾輪捲動速度\"\n  STR_MOUSEWHEEL_SPEED_DESC: \"調整每次滾動滑鼠滾輪捲動的清單行數。\"\n  STR_DISABLED: \"禁用\"\n  STR_MAXIMIZE_INFO_SCREENS: \"最大化資訊螢幕\"\n  STR_MAXIMIZE_INFO_SCREENS_DESC: \"無視縮放設定，已全螢幕視窗檢視倉庫和其他畫面。\"\n  STR_DIARY: \"摘要\"\n  STR_KILLED: \"殺害\"\n  STR_STUNNED: \"擊暈\"\n  STR_PANICKED: \"驚慌\"\n  STR_MINDCONTROLLED: \"控制\"\n  STR_REGION_UNKNOWN: \"未發現\"\n  STR_WEAPON_UNKNOWN: \"改進\"\n  STR_UNKNOWN: \"未知\"\n  STR_VICTORY: \"勝利\"\n  STR_DEFEAT: \"失敗\"\n  STR_NO_RECORD: \"無紀錄\"\n  STR_HUMAN: \"人類\"\n  STR_FRIENDLY: \"友善\"\n  STR_HOSTILE: \"敵對\"\n  STR_NEUTRAL: \"中立\"\n  STR_RATING_UC: \"評價\"\n  STR_LOCATION: \"地點>{ALT}{0}\"\n  STR_DAYLIGHT_TYPE: \"時間>{ALT}{0}\"\n  STR_RACE_TYPE: \"種族>{ALT}{0}\"\n  STR_DAY: \"日\"\n  STR_NIGHT: \"夜\"\n  STR_DAYS_WOUNDED: \"受傷天數>{ALT}{0}\"\n  STR_COMBAT: \"戰鬥\"\n  STR_PERFORMANCE: \"績效\"\n  STR_NEUTRALIZATIONS_BY_RACE: \"依種族顯示擊殺\"\n  STR_NEUTRALIZATIONS_BY_RANK: \"依階級顯示擊殺\"\n  STR_NEUTRALIZATIONS_BY_WEAPON: \"依武器顯示擊殺\"\n  STR_MISSIONS_BY_LOCATION: \"依地點顯示任務\"\n  STR_MISSIONS_BY_TYPE: \"依類別顯示任務\"\n  STR_MISSIONS_BY_UFO: \"依UFO顯示任務\"\n  STR_SCORE_VALUE: \"成績>{ALT}{0}\"\n  STR_WINS: \"勝利>{ALT}{0}\"\n  STR_STUNS: \"擊昏>{ALT}{0}\"\n  STR_PANICKS: \"恐慌>{ALT}{0}\"\n  STR_MINDCONTROLS: \"控制>{ALT}{0}\"\n  STR_AWARDS: \"獎項\"\n  STR_COMMENDATIONS_UC: \"獎賞\"\n  STR_COMMENDATIONS: \"獎賞\"\n  STR_MEDALS: \"獎牌\"\n  STR_LOST_IN_SERVICE: \"服勤中失蹤\"\n  STR_MEDAL_NAME: \"獎牌名稱\"\n  STR_MEDAL_AWARD_LEVEL: \"獎勵等級\"\n  STR_MEDAL_DECOR_LEVEL: \"裝飾等級\"\n  STR_AWARD_0: \"第一獎勵\"\n  STR_AWARD_1: \"第二獎勵\"\n  STR_AWARD_2: \"第三獎勵\"\n  STR_AWARD_3: \"第四獎勵\"\n  STR_AWARD_4: \"第五獎勵\"\n  STR_AWARD_5: \"第六獎勵\"\n  STR_AWARD_6: \"第七獎勵\"\n  STR_AWARD_7: \"第八獎勵\"\n  STR_AWARD_8: \"第九獎勵\"\n  STR_AWARD_9: \"第十獎勵\"\n  STR_AWARD_DECOR_0: \"無\"\n  STR_AWARD_DECOR_1: \"第一銅針\"\n  STR_AWARD_DECOR_2: \"第二銅針\"\n  STR_AWARD_DECOR_3: \"第三銅針\"\n  STR_AWARD_DECOR_4: \"第一銀針\"\n  STR_AWARD_DECOR_5: \"第二銀針\"\n  STR_AWARD_DECOR_6: \"第三銀針\"\n  STR_AWARD_DECOR_7: \"第一金針\"\n  STR_AWARD_DECOR_8: \"第二金針\"\n  STR_AWARD_DECOR_9: \"第三金針\"\n  STR_KILLED_IN_ACTION_MALE: \"任務中喪命\"\n  STR_KILLED_IN_ACTION_FEMALE: \"任務中喪命\"\n  STR_MISSING_IN_ACTION_MALE: \"任務中失蹤\"\n  STR_MISSING_IN_ACTION_FEMALE: \"任務中失蹤\"\n  STR_AVERAGE_MONTHLY_RATING: \"平均每月評等\"\n  STR_TOTAL_INCOME: \"總收入\"\n  STR_TOTAL_EXPENDITURE: \"總花費\"\n  STR_MISSIONS_WON: \"已完成任務\"\n  STR_MISSIONS_LOST: \"已失敗任務\"\n  STR_NIGHT_MISSIONS: \"夜間任務\"\n  STR_BEST_RATING: \"最佳任務評等\"\n  STR_WORST_RATING: \"最差任務評等\"\n  STR_ALIEN_KILLS: \"總殺害外星生物\"\n  STR_ALIEN_CAPTURES: \"總生擒外星生物\"\n  STR_FRIENDLY_KILLS: \"誤擊友軍\"\n  STR_AVERAGE_ACCURACY: \"平均命中率\"\n  STR_WEAPON_MOST_KILLS: \"最佳效能武器\"\n  STR_ALIEN_MOST_KILLS: \"最致命外星生物\"\n  STR_LONGEST_SERVICE: \"最長服勤月數\"\n  STR_TOTAL_DAYS_WOUNDED: \"病假\"\n  STR_COUNTRIES_LOST: \"被滲透的國家\"\n  STR_TOTAL_TERROR_SITES: \"恐怖攻擊\"\n  STR_TOTAL_BASES: \"已建築基地\"\n  STR_TOTAL_CRAFT: \"擁有載具\"\n  STR_TOTAL_SCIENTISTS: \"已僱用科學家\"\n  STR_TOTAL_ENGINEERS: \"已雇用工程師\"\n  STR_TOTAL_RESEARCH: \"已完成研發\"\n  STR_DIARY_ACCURACY: \"命中率>{ALT}{0}\"\n  STR_STATISTICS: \"統計\"\n  STR_STATS: \"狀態\"\n  STR_TIME_UNITS_ABBREVIATION: \"時間\"\n  STR_STAMINA_ABBREVIATION: \"體力\"\n  STR_HEALTH_ABBREVIATION: \"健康\"\n  STR_BRAVERY_ABBREVIATION: \"勇氣\"\n  STR_REACTIONS_ABBREVIATION: \"反應\"\n  STR_FIRING_ACCURACY_ABBREVIATION: \"射撃\"\n  STR_THROWING_ACCURACY_ABBREVIATION: \"投擲\"\n  STR_STRENGTH_ABBREVIATION: \"強度\"\n  STR_MELEE_ACCURACY_ABBREVIATION: \"近戰\"\n  STR_FOLDERS: \"目錄\"\n  STR_DATA_FOLDER: \"資料目錄 （原始遊戲來源）\"\n  STR_USER_FOLDER: \"使用者目錄 （模組, 日誌）\"\n  STR_SAVE_FOLDER: \"存檔目錄 （遊戲存檔, 截圖）\"\n  STR_CONFIG_FOLDER: \"設定檔目錄 （options.cfg）\"\n  STR_DATA_FOLDER_DESC_1: \"OpenXcom 尋找原始遊戲資源 （UFO 和/或 TFTD） 的路徑。\"\n  STR_DATA_FOLDER_DESC_2: \"OpenXcom 內部資源位於 'common' 資料夾中。 OpenXcom 內建模組位於 'standard' 資料夾中。\"\n  STR_USER_FOLDER_DESC: \"日誌檔案 （'openxcom.log'） 儲存的目錄。所有自訂模組也儲存在此處 （位於“mods”子目錄中）。\"\n  STR_SAVE_FOLDER_DESC: \"遊戲存檔的目錄。此外，任務產生器設定 （“battle.cfg”） 也位於此處。\"\n  STR_CONFIG_FOLDER_DESC: \"OpenXcom設定檔 （'options.cfg'） 的儲存位置。通常與使用者資料夾相同。\"\n"
  },
  {
    "path": "bin/common/Palettes/TFTD-JASC/BACKPALS.DAT.pal",
    "content": "JASC-PAL\n0100\n256\n168 252 0\n148 236 0\n128 220 0\n112 204 0\n96 192 0\n80 176 0\n68 160 0\n56 148 0\n36 136 0\n16 120 0\n4 108 0\n0 92 0\n0 76 8\n0 64 12\n0 48 16\n0 36 16\n0 164 152\n0 156 144\n0 148 136\n0 140 128\n0 132 120\n0 124 112\n0 116 104\n0 108 96\n0 100 88\n0 92 80\n0 84 72\n0 76 64\n0 68 56\n0 60 48\n0 56 40\n0 48 32\n212 132 124\n200 116 108\n192 104 96\n180 92 84\n172 80 72\n164 72 60\n152 60 52\n144 52 40\n132 44 32\n124 36 24\n116 28 20\n104 20 12\n96 16 8\n84 12 4\n76 8 0\n68 4 0\n224 224 80\n212 204 68\n200 184 60\n188 168 52\n176 148 44\n164 132 36\n152 116 28\n140 96 24\n128 84 16\n116 68 12\n104 56 8\n92 44 4\n80 32 4\n68 24 0\n56 12 0\n44 8 0\n88 180 124\n76 168 112\n68 160 100\n60 148 88\n48 140 76\n44 132 68\n36 120 56\n28 112 48\n24 104 40\n16 96 32\n8 84 20\n4 72 12\n4 60 8\n0 48 4\n0 36 0\n0 28 0\n192 164 80\n180 152 72\n172 140 80\n160 136 80\n136 128 96\n112 120 108\n96 112 108\n84 104 112\n72 96 112\n60 84 120\n48 76 116\n36 64 116\n24 56 112\n16 44 112\n4 32 108\n0 24 108\n60 148 252\n52 136 236\n48 124 224\n44 112 212\n40 104 200\n36 96 188\n32 84 176\n28 76 164\n24 68 152\n20 60 136\n16 52 124\n8 36 108\n4 20 92\n0 12 80\n0 4 64\n0 0 52\n196 140 0\n184 120 0\n176 104 0\n168 88 0\n156 72 0\n148 60 0\n140 48 0\n132 36 0\n120 28 0\n112 20 0\n104 16 0\n96 8 0\n84 4 0\n76 4 0\n68 0 0\n60 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n"
  },
  {
    "path": "bin/common/Palettes/TFTD-JASC/PAL_BASESCAPE.pal",
    "content": "JASC-PAL\n0100\n256\n0 0 0\n244 236 236\n216 204 212\n192 176 188\n164 144 164\n136 112 144\n112 80 120\n84 52 96\n60 20 72\n252 24 24\n216 16 16\n180 12 12\n140 8 8\n104 0 0\n192 0 0\n252 0 252\n252 252 196\n232 240 188\n216 224 180\n200 212 172\n184 200 160\n172 188 156\n156 176 144\n144 164 136\n132 152 128\n120 144 116\n112 132 108\n100 124 96\n92 116 88\n84 108 80\n72 100 72\n64 92 64\n56 84 56\n52 76 48\n44 68 40\n36 60 36\n28 52 28\n24 44 24\n16 36 16\n12 28 12\n8 20 8\n252 240 184\n252 232 160\n252 224 136\n252 216 116\n252 204 92\n252 196 68\n252 184 48\n228 236 176\n200 220 152\n168 208 132\n136 196 116\n104 180 96\n80 168 92\n68 156 96\n52 140 92\n40 128 88\n32 116 88\n20 100 84\n12 88 80\n8 72 76\n4 52 60\n0 32 48\n0 20 36\n252 240 184\n244 220 156\n240 192 128\n236 160 100\n232 124 76\n228 84 52\n224 40 24\n220 4 16\n192 4 16\n168 0 20\n144 0 20\n120 0 20\n96 0 16\n72 0 12\n48 0 8\n24 0 4\n252 252 144\n196 224 104\n140 200 76\n84 176 48\n32 152 24\n8 128 28\n0 104 40\n228 252 252\n208 240 240\n192 228 228\n176 216 216\n160 204 204\n148 192 196\n132 184 188\n120 176 180\n104 168 172\n92 160 164\n80 152 156\n72 144 148\n60 136 140\n52 128 132\n44 120 124\n36 112 116\n28 104 108\n20 92 96\n16 84 88\n8 76 76\n4 68 68\n4 56 60\n0 48 48\n0 40 40\n0 32 32\n160 204 248\n128 180 224\n100 156 200\n76 136 180\n56 120 156\n40 100 132\n28 88 116\n16 76 104\n8 64 88\n4 56 76\n0 44 60\n0 36 48\n0 32 40\n0 28 36\n0 24 28\n0 20 24\n204 252 252\n180 240 244\n156 232 236\n136 220 228\n116 208 220\n96 196 216\n84 188 208\n72 176 200\n56 160 192\n48 148 184\n36 136 180\n28 124 172\n16 112 164\n8 100 156\n4 88 148\n0 80 144\n252 132 252\n232 116 240\n212 100 228\n196 88 216\n176 76 204\n156 64 192\n140 52 180\n120 44 168\n104 32 156\n88 24 144\n72 20 132\n56 12 120\n44 8 108\n32 4 96\n20 0 84\n12 0 72\n252 244 192\n252 232 124\n252 224 60\n252 212 0\n224 168 0\n200 132 0\n176 100 0\n144 80 0\n116 60 0\n88 44 0\n68 40 0\n48 32 0\n28 28 0\n8 20 0\n0 16 0\n0 8 0\n240 184 160\n228 160 128\n220 140 96\n208 124 68\n200 108 40\n188 96 16\n180 88 0\n160 76 0\n144 68 0\n128 56 0\n108 48 0\n92 40 0\n76 32 0\n56 24 0\n40 16 0\n24 8 0\n240 252 252\n212 232 232\n188 212 212\n164 192 192\n140 172 172\n120 152 152\n100 132 132\n84 116 116\n64 100 100\n48 88 88\n32 76 76\n20 64 64\n12 52 52\n4 40 40\n0 28 28\n0 16 16\n232 180 144\n208 164 132\n188 152 124\n168 136 112\n148 124 100\n128 108 88\n108 92 76\n88 76 64\n72 68 56\n56 60 48\n44 52 44\n24 44 36\n8 36 28\n0 28 24\n0 20 16\n0 12 8\n200 120 144\n184 112 136\n168 104 124\n152 96 116\n136 88 108\n120 84 100\n104 76 92\n88 68 80\n72 60 72\n56 52 64\n40 48 56\n24 40 48\n8 32 40\n0 24 32\n0 16 20\n0 8 12\n244 248 252\n216 228 240\n192 208 228\n164 188 220\n144 164 208\n120 144 196\n100 128 188\n84 108 176\n64 88 164\n52 68 156\n36 52 144\n24 36 136\n12 20 124\n4 8 112\n0 0 104\n108 112 116\n"
  },
  {
    "path": "bin/common/Palettes/TFTD-JASC/PAL_BATTLESCAPE.pal",
    "content": "JASC-PAL\n0100\n256\n0 0 0\n255 255 255\n227 227 227\n191 191 215\n135 135 179\n83 111 147\n75 107 147\n23 23 99\n0 0 0\n255 27 27\n219 19 19\n183 15 15\n143 11 11\n107 0 0\n195 0 0\n0 0 0\n255 251 15\n239 235 11\n223 219 11\n207 207 11\n195 191 11\n179 175 7\n163 163 7\n147 147 7\n135 131 7\n119 115 7\n103 103 7\n87 87 7\n55 75 0\n23 55 0\n0 35 0\n0 19 11\n255 255 199\n239 239 187\n223 223 175\n207 207 163\n195 195 151\n179 179 139\n163 163 127\n147 147 115\n135 135 103\n119 119 91\n103 103 79\n87 87 67\n67 75 55\n51 63 47\n35 47 35\n15 23 23\n255 255 255\n239 239 239\n223 223 223\n207 207 207\n195 195 195\n179 179 179\n163 163 163\n147 147 147\n135 135 135\n119 119 119\n103 103 103\n87 87 87\n75 75 75\n59 59 59\n43 43 43\n27 27 27\n155 123 55\n143 115 51\n135 107 47\n127 99 43\n119 91 39\n107 83 39\n99 79 35\n91 71 31\n79 63 27\n71 55 23\n59 43 19\n51 31 19\n43 23 15\n31 19 15\n23 11 11\n15 7 7\n191 255 71\n179 239 67\n167 223 63\n155 207 55\n143 195 51\n135 179 47\n123 163 43\n111 147 39\n99 135 35\n87 119 31\n79 103 27\n67 87 23\n39 75 15\n7 55 0\n0 35 15\n0 15 23\n51 255 179\n47 239 167\n43 223 155\n39 207 147\n39 195 135\n35 179 123\n31 163 115\n27 147 103\n27 135 95\n23 119 83\n19 103 71\n15 87 35\n7 75 11\n23 63 7\n35 43 0\n27 15 0\n35 0 0\n15 23 0\n0 11 7\n0 11 7\n0 11 7\n0 7 7\n0 7 0\n0 7 0\n0 7 0\n0 7 0\n0 7 0\n1 1 1\n1 1 1\n1 1 1\n1 1 1\n1 1 1\n255 219 0\n239 203 0\n223 191 0\n207 179 0\n195 167 0\n179 155 0\n163 147 0\n147 139 0\n131 127 0\n111 115 0\n87 103 0\n67 87 0\n51 75 0\n35 63 0\n19 47 0\n7 35 0\n255 255 123\n239 231 107\n227 207 95\n211 187 79\n179 175 7\n155 155 7\n131 135 7\n107 115 0\n83 95 0\n55 75 0\n247 107 0\n159 71 0\n99 43 0\n187 127 207\n143 67 167\n83 43 95\n255 175 11\n239 163 7\n223 151 7\n207 143 7\n195 131 7\n179 123 7\n163 111 7\n147 103 7\n135 91 7\n119 79 7\n103 71 0\n87 59 0\n75 63 0\n63 55 0\n35 39 0\n11 27 0\n247 91 0\n231 83 0\n215 79 0\n203 75 0\n187 67 0\n171 63 0\n159 59 0\n143 51 0\n131 47 0\n115 39 0\n99 35 0\n87 31 0\n75 27 0\n63 27 0\n51 23 0\n39 19 0\n239 247 255\n211 219 227\n187 195 203\n163 171 179\n139 147 155\n115 119 131\n91 99 107\n71 75 83\n63 67 75\n55 59 63\n47 51 55\n43 43 47\n35 35 39\n27 27 31\n15 23 27\n7 23 15\n235 163 127\n219 151 119\n207 143 111\n191 131 103\n179 123 95\n163 115 87\n151 103 79\n135 95 71\n123 83 67\n111 75 59\n95 67 51\n83 59 39\n79 51 31\n67 43 23\n59 39 15\n51 35 11\n243 163 187\n227 151 175\n211 143 163\n199 135 151\n183 123 143\n171 115 131\n155 103 119\n143 95 107\n127 87 99\n111 75 87\n99 67 75\n83 55 63\n71 47 55\n59 39 55\n43 31 47\n27 23 39\n0 255 255\n0 239 239\n0 223 223\n0 207 207\n0 191 191\n0 175 175\n0 159 159\n0 143 143\n0 127 127\n0 111 111\n0 95 95\n0 79 79\n0 63 63\n0 51 51\n0 39 39\n0 5 4\n"
  },
  {
    "path": "bin/common/Palettes/TFTD-JASC/PAL_BATTLESCAPE_1.pal",
    "content": "JASC-PAL\n0100\n256\n0 0 0\n255 255 255\n227 227 227\n191 191 215\n135 135 179\n83 111 147\n75 107 147\n23 23 99\n0 0 0\n255 27 27\n219 19 19\n183 15 15\n143 11 11\n107 0 0\n195 0 0\n2 27 89\n255 251 15\n239 235 35\n223 219 55\n211 207 71\n195 191 83\n179 171 95\n163 155 103\n151 143 103\n127 131 107\n107 119 119\n87 107 127\n70 94 129\n52 80 132\n35 67 134\n17 53 137\n0 40 139\n255 255 199\n239 239 187\n223 223 179\n195 207 179\n171 195 179\n143 183 179\n111 171 175\n79 163 171\n69 149 163\n60 134 154\n50 120 146\n40 104 145\n30 88 143\n20 72 142\n10 56 140\n0 40 139\n255 255 255\n223 247 251\n195 239 247\n171 235 247\n143 227 243\n119 219 239\n87 211 231\n59 195 223\n52 177 208\n45 158 193\n38 140 178\n30 120 170\n23 100 162\n15 80 155\n8 60 147\n0 40 139\n155 123 55\n143 119 63\n135 111 67\n127 103 75\n119 99 87\n111 95 87\n99 91 91\n91 99 87\n80 93 89\n69 86 91\n58 80 93\n46 72 102\n35 64 111\n23 56 121\n12 48 130\n0 40 139\n191 255 71\n179 239 71\n167 223 75\n155 207 79\n143 195 83\n123 179 91\n99 163 99\n88 150 100\n77 137 100\n67 125 101\n56 112 101\n45 98 109\n34 83 116\n22 69 124\n11 54 131\n0 40 139\n51 255 179\n47 239 179\n43 223 179\n39 207 179\n35 195 179\n31 191 179\n27 183 175\n23 175 171\n20 159 163\n18 143 154\n15 127 146\n12 110 145\n9 92 143\n6 75 142\n3 57 140\n0 40 139\n0 0 7\n0 0 11\n0 0 19\n0 0 27\n0 7 35\n0 7 39\n0 11 47\n0 15 55\n0 19 61\n1 23 67\n0 27 79\n0 30 91\n0 32 103\n0 35 115\n0 37 127\n0 40 139\n255 219 0\n228 202 0\n201 185 0\n173 169 0\n146 152 0\n119 135 0\n103 123 0\n87 111 11\n71 95 27\n79 87 23\n63 79 55\n50 71 72\n38 63 89\n25 56 105\n13 48 122\n0 40 139\n255 255 123\n239 231 107\n227 207 95\n211 187 79\n179 175 7\n154 155 6\n129 135 4\n105 115 3\n80 95 1\n55 75 0\n247 107 2\n159 69 2\n97 43 2\n187 125 204\n143 67 164\n83 40 95\n255 175 11\n231 155 0\n207 131 0\n187 119 15\n171 111 27\n151 103 35\n131 87 43\n115 79 51\n95 67 51\n79 59 51\n63 51 51\n50 49 69\n38 47 86\n25 44 104\n13 42 121\n0 40 139\n247 91 0\n231 95 0\n219 95 7\n203 95 19\n191 99 31\n175 99 43\n158 94 49\n140 89 55\n123 84 61\n106 79 67\n89 74 74\n71 67 87\n53 60 100\n36 54 113\n18 47 126\n0 40 139\n203 211 215\n184 199 206\n165 186 197\n146 174 187\n127 161 178\n108 149 169\n98 139 161\n88 130 153\n79 120 146\n69 111 138\n59 101 130\n47 89 132\n35 77 134\n24 64 135\n12 52 137\n0 40 139\n235 163 127\n219 151 119\n207 143 115\n191 131 115\n179 123 119\n163 123 127\n147 116 125\n131 108 122\n115 101 120\n99 93 118\n83 86 116\n66 77 121\n50 68 125\n33 58 130\n17 49 134\n0 40 139\n243 163 187\n227 151 175\n211 143 163\n199 135 155\n195 123 155\n175 123 155\n155 119 155\n138 111 149\n121 103 144\n104 95 138\n87 87 132\n70 78 133\n52 68 135\n35 59 136\n17 49 138\n0 40 139\n0 255 255\n0 239 243\n0 227 235\n0 211 227\n0 199 219\n0 183 207\n0 170 197\n0 156 186\n1 143 176\n1 129 166\n1 116 156\n1 101 153\n1 86 149\n0 70 146\n0 55 142\n0 10 34\n"
  },
  {
    "path": "bin/common/Palettes/TFTD-JASC/PAL_BATTLESCAPE_2.pal",
    "content": "JASC-PAL\n0100\n256\n0 0 0\n255 255 255\n227 227 227\n191 191 215\n135 135 179\n83 111 147\n75 107 147\n23 23 99\n0 0 0\n255 27 27\n219 19 19\n183 15 15\n143 11 11\n107 0 0\n195 0 0\n8 28 71\n255 251 15\n231 235 31\n211 215 51\n187 195 63\n167 175 71\n147 155 79\n131 135 79\n111 119 79\n95 99 75\n87 99 103\n71 91 99\n59 83 99\n47 75 99\n35 63 99\n23 51 99\n8 36 99\n255 255 201\n225 238 192\n196 220 184\n166 203 175\n137 186 166\n107 169 157\n78 151 149\n48 134 140\n42 117 133\n39 103 128\n32 92 125\n25 80 122\n19 68 116\n14 58 111\n9 45 104\n6 34 97\n255 255 255\n224 244 248\n193 232 241\n163 221 235\n132 209 228\n101 198 221\n70 186 214\n62 165 200\n55 145 186\n48 125 180\n41 105 173\n34 91 158\n28 77 143\n21 64 129\n15 50 114\n8 36 99\n155 123 55\n140 116 58\n126 109 60\n111 102 63\n96 95 66\n81 88 69\n67 81 71\n52 74 74\n46 65 76\n40 56 77\n35 48 80\n29 40 92\n24 39 94\n19 38 96\n13 37 97\n8 36 99\n191 255 71\n169 239 73\n146 223 75\n124 208 78\n124 208 78\n79 176 82\n57 160 84\n51 142 84\n45 124 84\n39 107 92\n34 90 100\n29 79 100\n24 68 100\n18 58 99\n13 47 99\n8 36 99\n51 255 179\n45 239 174\n39 224 169\n33 208 164\n26 192 159\n20 176 154\n14 161 149\n8 145 144\n7 127 137\n9 110 130\n8 94 133\n8 76 135\n8 66 126\n8 56 117\n8 46 108\n8 36 99\n0 0 7\n0 0 11\n0 0 19\n0 0 27\n0 7 35\n0 6 40\n0 6 44\n0 5 49\n0 5 53\n1 5 66\n2 5 78\n3 11 82\n4 17 86\n6 24 91\n7 30 95\n8 36 99\n255 219 0\n224 200 4\n194 181 8\n163 162 13\n133 143 17\n102 124 21\n80 113 26\n57 102 30\n50 89 37\n45 78 45\n39 66 61\n33 60 69\n27 54 76\n20 48 84\n14 42 91\n8 36 99\n255 255 123\n239 231 107\n227 207 95\n211 187 79\n179 175 7\n154 155 6\n129 135 4\n105 115 3\n80 95 1\n55 75 0\n247 107 2\n159 69 2\n97 43 2\n187 125 204\n143 67 164\n83 40 95\n255 175 11\n228 164 16\n201 153 21\n174 142 26\n147 130 32\n120 119 37\n93 108 42\n66 97 47\n58 85 52\n50 73 57\n42 61 62\n35 56 69\n28 51 77\n22 46 84\n15 41 92\n8 36 99\n247 91 0\n219 89 7\n191 88 14\n163 86 21\n135 84 27\n107 83 34\n79 81 41\n70 72 46\n62 63 51\n54 55 64\n46 47 77\n38 45 81\n31 43 86\n23 40 90\n16 38 95\n8 36 99\n203 211 215\n182 197 207\n161 183 200\n140 169 192\n120 156 185\n99 142 177\n78 128 170\n57 114 162\n50 100 153\n45 87 144\n39 79 137\n33 70 129\n27 62 122\n20 53 114\n14 45 107\n8 36 99\n235 163 127\n211 153 125\n186 142 122\n162 132 120\n137 122 118\n113 111 115\n102 101 118\n92 90 120\n81 80 123\n70 69 125\n60 59 128\n50 54 122\n39 50 116\n29 45 111\n18 41 105\n8 36 99\n243 163 187\n218 152 180\n192 142 172\n167 131 165\n142 121 158\n117 110 151\n91 100 143\n66 89 136\n58 78 130\n51 68 132\n43 57 133\n36 53 126\n29 49 119\n22 44 113\n15 40 106\n8 36 99\n2 255 255\n2 238 247\n3 222 240\n3 205 232\n3 189 225\n3 172 217\n4 155 209\n4 139 202\n4 122 194\n4 106 187\n5 89 179\n5 72 171\n6 63 153\n7 54 135\n7 45 117\n2 9 24\n"
  },
  {
    "path": "bin/common/Palettes/TFTD-JASC/PAL_BATTLESCAPE_3.pal",
    "content": "JASC-PAL\n0100\n256\n0 0 0\n255 255 255\n227 227 227\n191 191 215\n135 135 179\n83 111 147\n75 107 147\n23 23 99\n0 0 0\n255 27 27\n219 19 19\n183 15 15\n143 11 11\n107 0 0\n195 0 0\n0 0 0\n245 240 5\n218 218 0\n181 192 0\n159 167 0\n131 135 11\n115 115 19\n99 99 27\n79 79 47\n59 63 67\n47 51 59\n35 43 55\n23 31 51\n15 23 47\n7 15 43\n0 7 39\n0 0 32\n245 245 191\n223 223 170\n197 197 154\n160 175 144\n128 154 138\n95 133 128\n53 112 117\n15 96 106\n0 80 96\n0 64 90\n0 53 80\n0 42 69\n0 31 63\n0 16 48\n0 10 37\n0 0 32\n245 245 245\n207 229 234\n170 213 223\n138 202 213\n101 186 202\n69 170 191\n31 154 175\n0 128 159\n0 106 138\n0 80 122\n0 58 106\n0 37 90\n0 16 74\n0 0 58\n0 0 42\n0 0 32\n144 112 47\n127 101 47\n111 85 42\n95 69 42\n79 58 47\n63 47 37\n42 32 32\n21 26 16\n5 16 26\n0 10 21\n0 0 16\n0 0 15\n0 0 10\n0 0 5\n1 1 1\n1 1 1\n181 245 63\n160 223 53\n143 197 48\n122 175 47\n101 154 37\n74 128 42\n42 106 42\n10 95 48\n0 79 69\n0 64 79\n0 48 74\n0 32 74\n0 21 74\n0 0 48\n0 0 42\n0 0 32\n42 240 170\n31 223 160\n16 197 154\n5 175 144\n0 154 138\n0 143 128\n0 127 117\n0 111 106\n0 95 96\n0 79 90\n0 58 80\n0 37 69\n0 15 58\n0 0 47\n0 0 42\n0 0 32\n0 0 5\n0 0 5\n0 0 5\n0 0 5\n0 0 5\n0 0 5\n1 1 1\n1 1 1\n1 1 1\n1 1 1\n1 1 1\n1 1 1\n1 1 1\n1 1 1\n1 1 1\n1 1 1\n245 208 0\n213 186 0\n181 165 0\n149 144 0\n122 127 0\n90 106 0\n58 95 0\n32 80 0\n10 69 0\n0 58 0\n0 37 0\n0 21 0\n0 5 0\n1 1 1\n1 1 1\n1 1 1\n255 255 122\n239 229 106\n224 207 95\n208 186 79\n176 175 5\n154 154 5\n128 133 5\n106 112 0\n80 95 0\n53 74 0\n245 106 0\n159 69 0\n96 42 0\n186 127 207\n143 64 165\n80 42 95\n245 165 0\n213 138 0\n181 106 0\n149 85 0\n117 79 0\n90 64 0\n58 53 0\n37 47 0\n16 37 5\n0 31 10\n0 21 15\n0 15 16\n0 0 21\n0 0 26\n0 0 31\n0 0 32\n239 80 0\n213 79 0\n192 69 0\n165 63 0\n149 58 0\n127 48 0\n106 42 0\n85 31 0\n63 16 5\n32 10 10\n0 0 15\n0 0 16\n0 0 21\n0 0 26\n0 0 31\n0 0 32\n229 239 245\n192 208 223\n159 181 207\n117 159 186\n74 138 176\n26 117 160\n0 96 143\n0 80 127\n0 64 101\n0 47 95\n0 31 79\n0 15 64\n0 0 47\n0 0 31\n0 0 15\n1 1 1\n224 159 117\n202 133 101\n181 117 95\n159 96 79\n138 80 79\n117 74 79\n96 63 79\n69 48 80\n48 37 69\n31 26 63\n5 15 48\n0 0 37\n0 0 21\n0 0 10\n1 1 1\n1 1 1\n229 154 176\n208 133 159\n186 117 138\n165 101 122\n154 80 112\n127 74 106\n96 63 96\n79 48 85\n53 37 74\n31 26 63\n10 15 48\n0 0 32\n0 0 26\n0 0 15\n1 1 1\n1 1 1\n0 255 255\n0 223 239\n0 192 223\n0 170 207\n0 144 192\n0 122 176\n0 101 160\n0 80 144\n0 64 133\n0 48 117\n0 37 101\n0 26 85\n0 16 74\n0 15 48\n0 5 26\n2 0 24\n"
  },
  {
    "path": "bin/common/Palettes/TFTD-JASC/PAL_GEOSCAPE.pal",
    "content": "JASC-PAL\n0100\n256\n0 0 0\n252 252 252\n224 224 224\n188 188 212\n132 132 176\n80 108 144\n72 104 144\n20 20 96\n0 0 0\n252 24 24\n216 16 16\n180 12 12\n140 8 8\n104 0 0\n192 0 0\n0 0 0\n152 172 0\n152 168 0\n152 164 0\n152 160 0\n152 160 0\n152 156 0\n152 152 4\n152 152 4\n148 144 4\n144 140 4\n144 136 4\n140 132 4\n136 124 4\n132 120 4\n132 116 4\n128 112 8\n124 108 8\n124 104 8\n120 100 8\n116 96 8\n112 92 8\n112 88 8\n108 84 8\n104 80 8\n104 76 8\n100 72 12\n96 68 12\n92 68 12\n92 64 12\n88 60 12\n84 56 12\n84 56 12\n152 192 208\n124 168 188\n100 148 172\n76 124 156\n60 104 140\n40 84 124\n28 64 108\n16 48 92\n12 44 88\n8 40 84\n8 36 80\n4 32 80\n4 28 76\n0 24 72\n0 20 68\n0 20 68\n96 176 200\n84 156 184\n68 136 168\n60 120 156\n48 100 140\n40 84 128\n28 68 112\n24 56 100\n16 48 92\n12 44 84\n8 40 76\n4 36 72\n4 32 64\n0 28 56\n0 24 48\n0 20 44\n88 196 100\n68 188 100\n32 172 68\n32 128 56\n32 112 52\n28 96 48\n20 76 40\n92 176 216\n84 164 216\n76 156 212\n68 144 212\n60 136 212\n52 124 208\n44 116 208\n36 104 204\n28 96 204\n52 120 180\n40 104 164\n32 88 148\n24 72 132\n16 60 116\n12 44 100\n8 36 84\n4 32 76\n4 28 72\n4 24 64\n0 20 60\n0 16 52\n0 16 48\n0 12 44\n0 8 36\n0 8 32\n0 0 0\n252 164 212\n192 112 152\n252 128 0\n192 92 0\n252 252 252\n192 192 192\n0 252 0\n0 192 0\n0 252 252\n0 192 192\n252 252 0\n192 192 0\n252 0 0\n192 0 0\n252 252 252\n200 212 172\n156 176 144\n228 160 128\n220 140 96\n168 136 112\n8 76 76\n4 68 68\n4 56 60\n72 176 200\n56 160 192\n36 136 180\n28 124 172\n16 112 164\n60 136 140\n0 80 144\n216 252 0\n252 252 120\n236 228 104\n224 204 92\n208 184 76\n176 172 4\n152 152 4\n128 132 4\n104 112 0\n80 92 0\n52 72 0\n244 104 0\n156 68 0\n96 40 0\n184 124 204\n140 64 164\n80 40 92\n8 28 60\n8 32 64\n8 36 72\n8 40 80\n8 44 88\n8 48 96\n8 56 100\n8 60 108\n8 68 116\n8 72 124\n8 80 132\n8 96 152\n8 116 172\n8 84 136\n8 56 104\n8 36 72\n180 92 0\n172 68 0\n164 44 0\n156 24 0\n144 20 4\n128 16 12\n116 16 16\n92 12 20\n80 8 24\n64 8 28\n56 4 36\n40 4 36\n28 0 32\n24 0 8\n12 0 4\n0 0 0\n20 84 200\n12 76 180\n8 68 164\n4 60 148\n0 52 132\n0 44 116\n0 40 100\n0 36 88\n0 24 76\n0 20 68\n0 12 60\n0 8 52\n0 4 40\n0 0 32\n0 0 24\n0 0 16\n20 76 140\n16 56 128\n12 40 120\n8 28 108\n8 16 100\n4 4 88\n12 4 80\n16 4 76\n12 4 64\n8 4 56\n8 0 44\n4 0 36\n4 0 24\n0 0 16\n0 0 4\n0 0 0\n168 252 0\n148 236 0\n128 220 0\n112 204 0\n96 192 0\n80 176 0\n68 160 0\n56 148 0\n36 136 0\n16 120 0\n4 108 0\n0 92 0\n0 76 8\n0 64 12\n0 48 16\n0 36 16\n168 216 228\n44 160 212\n24 136 192\n4 68 120\n0 8 32\n24 220 140\n20 184 112\n16 148 84\n12 112 60\n8 76 40\n4 44 20\n4 4 40\n252 252 164\n220 232 140\n192 212 120\n164 192 104\n"
  },
  {
    "path": "bin/common/Palettes/TFTD-JASC/PAL_GRAPHS.pal",
    "content": "JASC-PAL\n0100\n256\n0 0 0\n252 252 252\n224 224 224\n188 188 212\n132 132 176\n80 108 144\n44 44 84\n20 20 40\n0 0 0\n252 24 24\n216 16 16\n180 12 12\n140 8 8\n104 0 0\n40 40 40\n24 24 24\n252 252 0\n216 208 0\n180 168 0\n144 128 0\n108 92 0\n72 60 0\n96 84 0\n72 60 0\n252 0 0\n212 0 0\n176 0 0\n136 0 0\n100 0 0\n64 0 0\n88 0 0\n64 0 0\n0 252 0\n0 212 0\n0 176 0\n0 136 0\n0 100 0\n0 64 0\n0 88 0\n0 64 0\n0 124 252\n0 100 208\n0 76 168\n0 52 124\n0 32 84\n0 16 44\n0 28 72\n0 16 44\n0 252 252\n0 212 212\n0 172 172\n0 132 132\n0 92 92\n0 56 56\n0 84 84\n0 56 56\n252 132 208\n208 96 164\n164 68 128\n120 44 88\n76 24 56\n36 8 24\n64 20 44\n36 8 24\n252 112 0\n212 84 0\n172 56 0\n132 36 0\n92 20 0\n52 8 0\n80 16 0\n52 8 0\n252 172 88\n216 144 72\n184 120 56\n152 96 44\n120 72 28\n88 52 20\n108 64 28\n88 52 20\n184 120 252\n152 92 220\n124 68 188\n96 44 156\n72 28 124\n52 16 92\n68 24 112\n52 16 92\n132 184 196\n104 152 164\n80 120 136\n56 88 104\n36 60 76\n20 36 48\n32 52 68\n20 36 48\n252 252 252\n216 216 216\n180 180 180\n144 144 144\n108 108 108\n76 76 76\n100 100 100\n76 76 76\n24 220 140\n20 184 112\n16 148 84\n12 112 60\n8 76 40\n4 44 20\n8 68 32\n4 44 20\n224 128 100\n188 96 72\n152 64 48\n116 40 28\n80 20 12\n48 8 4\n72 16 8\n48 8 4\n200 168 200\n164 132 164\n128 100 128\n92 68 92\n56 40 56\n24 16 24\n48 32 48\n24 16 24\n192 164 68\n160 132 48\n128 104 36\n100 76 20\n68 52 12\n40 28 4\n60 44 8\n40 28 4\n252 148 148\n208 112 112\n164 80 80\n124 52 52\n80 32 32\n40 12 12\n68 24 24\n40 12 12\n252 252 120\n236 228 104\n224 204 92\n208 184 76\n176 172 4\n152 152 4\n128 132 4\n104 112 0\n80 92 0\n52 72 0\n244 104 0\n156 68 0\n96 40 0\n184 124 204\n140 64 164\n80 40 92\n0 68 0\n0 56 0\n0 44 0\n0 32 0\n0 24 0\n96 96 96\n96 96 96\n96 96 96\n96 96 96\n96 96 96\n96 96 96\n96 96 96\n96 96 96\n96 96 96\n96 96 96\n96 96 96\n136 244 224\n120 228 208\n108 216 192\n96 200 176\n80 188 160\n72 172 148\n60 160 132\n52 148 120\n0 76 160\n0 64 144\n0 56 132\n0 48 120\n0 40 104\n0 32 92\n0 24 80\n0 20 68\n60 156 188\n44 124 168\n32 92 148\n20 68 128\n12 44 108\n4 24 88\n0 4 68\n0 0 52\n52 112 44\n40 100 32\n28 92 24\n20 84 16\n12 76 8\n4 68 4\n0 60 0\n0 52 0\n0 76 192\n0 72 184\n0 68 180\n0 68 172\n0 64 168\n0 64 160\n0 60 156\n0 56 148\n0 56 144\n0 52 136\n0 52 132\n0 48 124\n0 44 120\n0 44 116\n0 40 108\n0 40 104\n192 168 216\n176 156 200\n160 144 188\n144 132 176\n128 120 164\n112 108 152\n96 100 140\n88 92 128\n76 76 120\n68 68 112\n56 56 104\n44 44 96\n32 32 88\n20 20 80\n8 8 72\n0 0 32\n0 20 68\n8 44 100\n28 76 136\n60 116 168\n96 156 204\n144 204 240\n160 160 160\n132 132 132\n100 100 100\n72 72 72\n40 40 40\n8 8 8\n28 28 28\n8 8 8\n192 212 120\n164 192 104\n"
  },
  {
    "path": "bin/common/Palettes/TFTD-JASC-SAFE/PAL_BACKGROUND_SAFE.pal",
    "content": "JASC-PAL\n0100\n256\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n168 252 0\n148 236 0\n128 220 0\n112 204 0\n96 192 0\n80 176 0\n68 160 0\n56 148 0\n36 136 0\n16 120 0\n4 108 0\n0 92 0\n0 76 8\n0 64 12\n0 48 16\n0 36 16\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n"
  },
  {
    "path": "bin/common/Palettes/TFTD-JASC-SAFE/PAL_BASESCAPE_SAFE.pal",
    "content": "JASC-PAL\n0100\n256\n0 255 0\n244 236 236\n216 204 212\n192 176 188\n164 144 164\n136 112 144\n112 80 120\n84 52 96\n60 20 72\n252 24 24\n216 16 16\n180 12 12\n140 8 8\n104 0 0\n192 0 0\n252 0 252\n252 252 196\n232 240 188\n216 224 180\n200 212 172\n184 200 160\n172 188 156\n156 176 144\n144 164 136\n132 152 128\n120 144 116\n112 132 108\n100 124 96\n92 116 88\n84 108 80\n72 100 72\n64 92 64\n56 84 56\n52 76 48\n44 68 40\n36 60 36\n28 52 28\n24 44 24\n16 36 16\n12 28 12\n8 20 8\n252 240 184\n252 232 160\n252 224 136\n252 216 116\n252 204 92\n252 196 68\n252 184 48\n228 236 176\n200 220 152\n168 208 132\n136 196 116\n104 180 96\n80 168 92\n68 156 96\n52 140 92\n40 128 88\n32 116 88\n20 100 84\n12 88 80\n8 72 76\n4 52 60\n0 32 48\n0 20 36\n252 240 184\n244 220 156\n240 192 128\n236 160 100\n232 124 76\n228 84 52\n224 40 24\n220 4 16\n192 4 16\n168 0 20\n144 0 20\n120 0 20\n96 0 16\n72 0 12\n48 0 8\n24 0 4\n252 252 144\n196 224 104\n140 200 76\n84 176 48\n32 152 24\n8 128 28\n0 104 40\n228 252 252\n208 240 240\n192 228 228\n176 216 216\n160 204 204\n148 192 196\n132 184 188\n120 176 180\n104 168 172\n92 160 164\n80 152 156\n72 144 148\n60 136 140\n52 128 132\n44 120 124\n36 112 116\n28 104 108\n20 92 96\n16 84 88\n8 76 76\n4 68 68\n4 56 60\n0 48 48\n0 40 40\n0 32 32\n160 204 248\n128 180 224\n100 156 200\n76 136 180\n56 120 156\n40 100 132\n28 88 116\n16 76 104\n8 64 88\n4 56 76\n0 44 60\n0 36 48\n0 32 40\n0 28 36\n0 24 28\n0 20 24\n204 252 252\n180 240 244\n156 232 236\n136 220 228\n116 208 220\n96 196 216\n84 188 208\n72 176 200\n56 160 192\n48 148 184\n36 136 180\n28 124 172\n16 112 164\n8 100 156\n4 88 148\n0 80 144\n252 132 252\n232 116 240\n212 100 228\n196 88 216\n176 76 204\n156 64 192\n140 52 180\n120 44 168\n104 32 156\n88 24 144\n72 20 132\n56 12 120\n44 8 108\n32 4 96\n20 0 84\n12 0 72\n252 244 192\n252 232 124\n252 224 60\n252 212 0\n224 168 0\n200 132 0\n176 100 0\n144 80 0\n116 60 0\n88 44 0\n68 40 0\n48 32 0\n28 28 0\n8 20 0\n0 16 0\n0 8 0\n240 184 160\n228 160 128\n220 140 96\n208 124 68\n200 108 40\n188 96 16\n180 88 0\n160 76 0\n144 68 0\n128 56 0\n108 48 0\n92 40 0\n76 32 0\n56 24 0\n40 16 0\n24 8 0\n240 252 252\n212 232 232\n188 212 212\n164 192 192\n140 172 172\n120 152 152\n100 132 132\n84 116 116\n64 100 100\n48 88 88\n32 76 76\n20 64 64\n12 52 52\n4 40 40\n0 28 28\n0 16 16\n232 180 144\n208 164 132\n188 152 124\n168 136 112\n148 124 100\n128 108 88\n108 92 76\n88 76 64\n72 68 56\n56 60 48\n44 52 44\n24 44 36\n8 36 28\n0 28 24\n0 20 16\n0 12 8\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n244 248 252\n216 228 240\n192 208 228\n164 188 220\n144 164 208\n120 144 196\n100 128 188\n84 108 176\n64 88 164\n52 68 156\n36 52 144\n24 36 136\n12 20 124\n4 8 112\n0 0 104\n108 112 116\n"
  },
  {
    "path": "bin/common/Palettes/TFTD-JASC-SAFE/PAL_BATTLESCAPE_1_SAFE.pal",
    "content": "JASC-PAL\n0100\n256\n0 255 0\n255 255 255\n227 227 227\n191 191 215\n135 135 179\n83 111 147\n75 107 147\n23 23 99\n0 0 0\n255 27 27\n219 19 19\n183 15 15\n143 11 11\n107 0 0\n195 0 0\n2 27 89\n255 251 15\n239 235 35\n223 219 55\n211 207 71\n195 191 83\n179 171 95\n163 155 103\n151 143 103\n127 131 107\n107 119 119\n87 107 127\n70 94 129\n52 80 132\n35 67 134\n17 53 137\n0 40 139\n255 255 199\n239 239 187\n223 223 179\n195 207 179\n171 195 179\n143 183 179\n111 171 175\n79 163 171\n69 149 163\n60 134 154\n50 120 146\n40 104 145\n30 88 143\n20 72 142\n10 56 140\n0 40 139\n255 255 255\n223 247 251\n195 239 247\n171 235 247\n143 227 243\n119 219 239\n87 211 231\n59 195 223\n52 177 208\n45 158 193\n38 140 178\n30 120 170\n23 100 162\n15 80 155\n8 60 147\n0 40 139\n155 123 55\n143 119 63\n135 111 67\n127 103 75\n119 99 87\n111 95 87\n99 91 91\n91 99 87\n80 93 89\n69 86 91\n58 80 93\n46 72 102\n35 64 111\n23 56 121\n12 48 130\n0 40 139\n191 255 71\n179 239 71\n167 223 75\n155 207 79\n143 195 83\n123 179 91\n99 163 99\n88 150 100\n77 137 100\n67 125 101\n56 112 101\n45 98 109\n34 83 116\n22 69 124\n11 54 131\n0 40 139\n51 255 179\n47 239 179\n43 223 179\n39 207 179\n35 195 179\n31 191 179\n27 183 175\n23 175 171\n20 159 163\n18 143 154\n15 127 146\n12 110 145\n9 92 143\n6 75 142\n3 57 140\n0 40 139\n0 0 7\n0 0 11\n0 0 19\n0 0 27\n0 7 35\n0 7 39\n0 11 47\n0 15 55\n0 19 61\n1 23 67\n0 27 79\n0 30 91\n0 32 103\n0 35 115\n0 37 127\n0 40 139\n255 219 0\n228 202 0\n201 185 0\n173 169 0\n146 152 0\n119 135 0\n103 123 0\n87 111 11\n71 95 27\n79 87 23\n63 79 55\n50 71 72\n38 63 89\n25 56 105\n13 48 122\n0 40 139\n255 255 123\n239 231 107\n227 207 95\n211 187 79\n179 175 7\n154 155 6\n129 135 4\n105 115 3\n80 95 1\n55 75 0\n247 107 2\n159 69 2\n97 43 2\n187 125 204\n143 67 164\n83 40 95\n255 175 11\n231 155 0\n207 131 0\n187 119 15\n171 111 27\n151 103 35\n131 87 43\n115 79 51\n95 67 51\n79 59 51\n63 51 51\n50 49 69\n38 47 86\n25 44 104\n13 42 121\n0 40 139\n247 91 0\n231 95 0\n219 95 7\n203 95 19\n191 99 31\n175 99 43\n158 94 49\n140 89 55\n123 84 61\n106 79 67\n89 74 74\n71 67 87\n53 60 100\n36 54 113\n18 47 126\n0 40 139\n203 211 215\n184 199 206\n165 186 197\n146 174 187\n127 161 178\n108 149 169\n98 139 161\n88 130 153\n79 120 146\n69 111 138\n59 101 130\n47 89 132\n35 77 134\n24 64 135\n12 52 137\n0 40 139\n235 163 127\n219 151 119\n207 143 115\n191 131 115\n179 123 119\n163 123 127\n147 116 125\n131 108 122\n115 101 120\n99 93 118\n83 86 116\n66 77 121\n50 68 125\n33 58 130\n17 49 134\n0 40 139\n243 163 187\n227 151 175\n211 143 163\n199 135 155\n195 123 155\n175 123 155\n155 119 155\n138 111 149\n121 103 144\n104 95 138\n87 87 132\n70 78 133\n52 68 135\n35 59 136\n17 49 138\n0 40 139\n0 255 255\n0 239 243\n0 227 235\n0 211 227\n0 199 219\n0 183 207\n0 170 197\n0 156 186\n1 143 176\n1 129 166\n1 116 156\n1 101 153\n1 86 149\n0 70 146\n0 55 142\n0 10 34\n"
  },
  {
    "path": "bin/common/Palettes/TFTD-JASC-SAFE/PAL_BATTLESCAPE_2_SAFE.pal",
    "content": "JASC-PAL\n0100\n256\n0 255 0\n255 255 255\n227 227 227\n191 191 215\n135 135 179\n83 111 147\n75 107 147\n23 23 99\n0 0 0\n255 27 27\n219 19 19\n183 15 15\n143 11 11\n107 0 0\n195 0 0\n8 28 71\n255 251 15\n231 235 31\n211 215 51\n187 195 63\n167 175 71\n147 155 79\n131 135 79\n111 119 79\n95 99 75\n87 99 103\n71 91 99\n59 83 99\n47 75 99\n35 63 99\n23 51 99\n8 36 99\n255 255 201\n225 238 192\n196 220 184\n166 203 175\n137 186 166\n107 169 157\n78 151 149\n48 134 140\n42 117 133\n39 103 128\n32 92 125\n25 80 122\n19 68 116\n14 58 111\n9 45 104\n6 34 97\n255 255 255\n224 244 248\n193 232 241\n163 221 235\n132 209 228\n101 198 221\n70 186 214\n62 165 200\n55 145 186\n48 125 180\n41 105 173\n34 91 158\n28 77 143\n21 64 129\n15 50 114\n8 36 99\n155 123 55\n140 116 58\n126 109 60\n111 102 63\n96 95 66\n81 88 69\n67 81 71\n52 74 74\n46 65 76\n40 56 77\n35 48 80\n29 40 92\n24 39 94\n19 38 96\n13 37 97\n8 36 99\n191 255 71\n169 239 73\n146 223 75\n124 208 78\n124 208 78\n79 176 82\n57 160 84\n51 142 84\n45 124 84\n39 107 92\n34 90 100\n29 79 100\n24 68 100\n18 58 99\n13 47 99\n8 36 99\n51 255 179\n45 239 174\n39 224 169\n33 208 164\n26 192 159\n20 176 154\n14 161 149\n8 145 144\n7 127 137\n9 110 130\n8 94 133\n8 76 135\n8 66 126\n8 56 117\n8 46 108\n8 36 99\n0 0 7\n0 0 11\n0 0 19\n0 0 27\n0 7 35\n0 6 40\n0 6 44\n0 5 49\n0 5 53\n1 5 66\n2 5 78\n3 11 82\n4 17 86\n6 24 91\n7 30 95\n8 36 99\n255 219 0\n224 200 4\n194 181 8\n163 162 13\n133 143 17\n102 124 21\n80 113 26\n57 102 30\n50 89 37\n45 78 45\n39 66 61\n33 60 69\n27 54 76\n20 48 84\n14 42 91\n8 36 99\n255 255 123\n239 231 107\n227 207 95\n211 187 79\n179 175 7\n154 155 6\n129 135 4\n105 115 3\n80 95 1\n55 75 0\n247 107 2\n159 69 2\n97 43 2\n187 125 204\n143 67 164\n83 40 95\n255 175 11\n228 164 16\n201 153 21\n174 142 26\n147 130 32\n120 119 37\n93 108 42\n66 97 47\n58 85 52\n50 73 57\n42 61 62\n35 56 69\n28 51 77\n22 46 84\n15 41 92\n8 36 99\n247 91 0\n219 89 7\n191 88 14\n163 86 21\n135 84 27\n107 83 34\n79 81 41\n70 72 46\n62 63 51\n54 55 64\n46 47 77\n38 45 81\n31 43 86\n23 40 90\n16 38 95\n8 36 99\n203 211 215\n182 197 207\n161 183 200\n140 169 192\n120 156 185\n99 142 177\n78 128 170\n57 114 162\n50 100 153\n45 87 144\n39 79 137\n33 70 129\n27 62 122\n20 53 114\n14 45 107\n8 36 99\n235 163 127\n211 153 125\n186 142 122\n162 132 120\n137 122 118\n113 111 115\n102 101 118\n92 90 120\n81 80 123\n70 69 125\n60 59 128\n50 54 122\n39 50 116\n29 45 111\n18 41 105\n8 36 99\n243 163 187\n218 152 180\n192 142 172\n167 131 165\n142 121 158\n117 110 151\n91 100 143\n66 89 136\n58 78 130\n51 68 132\n43 57 133\n36 53 126\n29 49 119\n22 44 113\n15 40 106\n8 36 99\n2 255 255\n2 238 247\n3 222 240\n3 205 232\n3 189 225\n3 172 217\n4 155 209\n4 139 202\n4 122 194\n4 106 187\n5 89 179\n5 72 171\n6 63 153\n7 54 135\n7 45 117\n2 9 24\n"
  },
  {
    "path": "bin/common/Palettes/TFTD-JASC-SAFE/PAL_BATTLESCAPE_3_SAFE.pal",
    "content": "JASC-PAL\n0100\n256\n0 255 0\n255 255 255\n227 227 227\n191 191 215\n135 135 179\n83 111 147\n75 107 147\n23 23 99\n0 0 0\n255 27 27\n219 19 19\n183 15 15\n143 11 11\n107 0 0\n195 0 0\n0 0 0\n245 240 5\n218 218 0\n181 192 0\n159 167 0\n131 135 11\n115 115 19\n99 99 27\n79 79 47\n59 63 67\n47 51 59\n35 43 55\n23 31 51\n15 23 47\n7 15 43\n0 7 39\n0 0 32\n245 245 191\n223 223 170\n197 197 154\n160 175 144\n128 154 138\n95 133 128\n53 112 117\n15 96 106\n0 80 96\n0 64 90\n0 53 80\n0 42 69\n0 31 63\n0 16 48\n0 10 37\n0 0 32\n245 245 245\n207 229 234\n170 213 223\n138 202 213\n101 186 202\n69 170 191\n31 154 175\n0 128 159\n0 106 138\n0 80 122\n0 58 106\n0 37 90\n0 16 74\n0 0 58\n0 0 42\n0 0 32\n144 112 47\n127 101 47\n111 85 42\n95 69 42\n79 58 47\n63 47 37\n42 32 32\n21 26 16\n5 16 26\n0 10 21\n0 0 16\n0 0 15\n0 0 10\n0 0 5\n1 1 1\n1 1 1\n181 245 63\n160 223 53\n143 197 48\n122 175 47\n101 154 37\n74 128 42\n42 106 42\n10 95 48\n0 79 69\n0 64 79\n0 48 74\n0 32 74\n0 21 74\n0 0 48\n0 0 42\n0 0 32\n42 240 170\n31 223 160\n16 197 154\n5 175 144\n0 154 138\n0 143 128\n0 127 117\n0 111 106\n0 95 96\n0 79 90\n0 58 80\n0 37 69\n0 15 58\n0 0 47\n0 0 42\n0 0 32\n0 0 5\n0 0 5\n0 0 5\n0 0 5\n0 0 5\n0 0 5\n1 1 1\n1 1 1\n1 1 1\n1 1 1\n1 1 1\n1 1 1\n1 1 1\n1 1 1\n1 1 1\n1 1 1\n245 208 0\n213 186 0\n181 165 0\n149 144 0\n122 127 0\n90 106 0\n58 95 0\n32 80 0\n10 69 0\n0 58 0\n0 37 0\n0 21 0\n0 5 0\n1 1 1\n1 1 1\n1 1 1\n255 255 122\n239 229 106\n224 207 95\n208 186 79\n176 175 5\n154 154 5\n128 133 5\n106 112 0\n80 95 0\n53 74 0\n245 106 0\n159 69 0\n96 42 0\n186 127 207\n143 64 165\n80 42 95\n245 165 0\n213 138 0\n181 106 0\n149 85 0\n117 79 0\n90 64 0\n58 53 0\n37 47 0\n16 37 5\n0 31 10\n0 21 15\n0 15 16\n0 0 21\n0 0 26\n0 0 31\n0 0 32\n239 80 0\n213 79 0\n192 69 0\n165 63 0\n149 58 0\n127 48 0\n106 42 0\n85 31 0\n63 16 5\n32 10 10\n0 0 15\n0 0 16\n0 0 21\n0 0 26\n0 0 31\n0 0 32\n229 239 245\n192 208 223\n159 181 207\n117 159 186\n74 138 176\n26 117 160\n0 96 143\n0 80 127\n0 64 101\n0 47 95\n0 31 79\n0 15 64\n0 0 47\n0 0 31\n0 0 15\n1 1 1\n224 159 117\n202 133 101\n181 117 95\n159 96 79\n138 80 79\n117 74 79\n96 63 79\n69 48 80\n48 37 69\n31 26 63\n5 15 48\n0 0 37\n0 0 21\n0 0 10\n1 1 1\n1 1 1\n229 154 176\n208 133 159\n186 117 138\n165 101 122\n154 80 112\n127 74 106\n96 63 96\n79 48 85\n53 37 74\n31 26 63\n10 15 48\n0 0 32\n0 0 26\n0 0 15\n1 1 1\n1 1 1\n0 255 255\n0 223 239\n0 192 223\n0 170 207\n0 144 192\n0 122 176\n0 101 160\n0 80 144\n0 64 133\n0 48 117\n0 37 101\n0 26 85\n0 16 74\n0 15 48\n0 5 26\n2 0 24\n"
  },
  {
    "path": "bin/common/Palettes/TFTD-JASC-SAFE/PAL_BATTLESCAPE_SAFE.pal",
    "content": "JASC-PAL\n0100\n256\n0 255 0\n255 255 255\n227 227 227\n191 191 215\n135 135 179\n83 111 147\n75 107 147\n23 23 99\n0 0 0\n255 27 27\n219 19 19\n183 15 15\n143 11 11\n107 0 0\n195 0 0\n0 0 0\n255 251 15\n239 235 11\n223 219 11\n207 207 11\n195 191 11\n179 175 7\n163 163 7\n147 147 7\n135 131 7\n119 115 7\n103 103 7\n87 87 7\n55 75 0\n23 55 0\n0 35 0\n0 19 11\n255 255 199\n239 239 187\n223 223 175\n207 207 163\n195 195 151\n179 179 139\n163 163 127\n147 147 115\n135 135 103\n119 119 91\n103 103 79\n87 87 67\n67 75 55\n51 63 47\n35 47 35\n15 23 23\n255 255 255\n239 239 239\n223 223 223\n207 207 207\n195 195 195\n179 179 179\n163 163 163\n147 147 147\n135 135 135\n119 119 119\n103 103 103\n87 87 87\n75 75 75\n59 59 59\n43 43 43\n27 27 27\n155 123 55\n143 115 51\n135 107 47\n127 99 43\n119 91 39\n107 83 39\n99 79 35\n91 71 31\n79 63 27\n71 55 23\n59 43 19\n51 31 19\n43 23 15\n31 19 15\n23 11 11\n15 7 7\n191 255 71\n179 239 67\n167 223 63\n155 207 55\n143 195 51\n135 179 47\n123 163 43\n111 147 39\n99 135 35\n87 119 31\n79 103 27\n67 87 23\n39 75 15\n7 55 0\n0 35 15\n0 15 23\n51 255 179\n47 239 167\n43 223 155\n39 207 147\n39 195 135\n35 179 123\n31 163 115\n27 147 103\n27 135 95\n23 119 83\n19 103 71\n15 87 35\n7 75 11\n23 63 7\n35 43 0\n27 15 0\n35 0 0\n15 23 0\n0 11 7\n0 11 7\n0 11 7\n0 7 7\n0 7 0\n0 7 0\n0 7 0\n0 7 0\n0 7 0\n1 1 1\n1 1 1\n1 1 1\n1 1 1\n1 1 1\n255 219 0\n239 203 0\n223 191 0\n207 179 0\n195 167 0\n179 155 0\n163 147 0\n147 139 0\n131 127 0\n111 115 0\n87 103 0\n67 87 0\n51 75 0\n35 63 0\n19 47 0\n7 35 0\n255 255 123\n239 231 107\n227 207 95\n211 187 79\n179 175 7\n155 155 7\n131 135 7\n107 115 0\n83 95 0\n55 75 0\n247 107 0\n159 71 0\n99 43 0\n187 127 207\n143 67 167\n83 43 95\n255 175 11\n239 163 7\n223 151 7\n207 143 7\n195 131 7\n179 123 7\n163 111 7\n147 103 7\n135 91 7\n119 79 7\n103 71 0\n87 59 0\n75 63 0\n63 55 0\n35 39 0\n11 27 0\n247 91 0\n231 83 0\n215 79 0\n203 75 0\n187 67 0\n171 63 0\n159 59 0\n143 51 0\n131 47 0\n115 39 0\n99 35 0\n87 31 0\n75 27 0\n63 27 0\n51 23 0\n39 19 0\n239 247 255\n211 219 227\n187 195 203\n163 171 179\n139 147 155\n115 119 131\n91 99 107\n71 75 83\n63 67 75\n55 59 63\n47 51 55\n43 43 47\n35 35 39\n27 27 31\n15 23 27\n7 23 15\n235 163 127\n219 151 119\n207 143 111\n191 131 103\n179 123 95\n163 115 87\n151 103 79\n135 95 71\n123 83 67\n111 75 59\n95 67 51\n83 59 39\n79 51 31\n67 43 23\n59 39 15\n51 35 11\n243 163 187\n227 151 175\n211 143 163\n199 135 151\n183 123 143\n171 115 131\n155 103 119\n143 95 107\n127 87 99\n111 75 87\n99 67 75\n83 55 63\n71 47 55\n59 39 55\n43 31 47\n27 23 39\n0 255 255\n0 239 239\n0 223 223\n0 207 207\n0 191 191\n0 175 175\n0 159 159\n0 143 143\n0 127 127\n0 111 111\n0 95 95\n0 79 79\n0 63 63\n0 51 51\n0 39 39\n0 5 4\n"
  },
  {
    "path": "bin/common/Palettes/TFTD-JASC-SAFE/PAL_GEOSCAPE_SAFE.pal",
    "content": "JASC-PAL\n0100\n256\n0 255 0\n252 252 252\n224 224 224\n188 188 212\n132 132 176\n80 108 144\n72 104 144\n20 20 96\n0 0 0\n252 24 24\n216 16 16\n180 12 12\n140 8 8\n104 0 0\n192 0 0\n0 0 0\n152 172 0\n152 168 0\n152 164 0\n152 160 0\n152 160 0\n152 156 0\n152 152 4\n152 152 4\n148 144 4\n144 140 4\n144 136 4\n140 132 4\n136 124 4\n132 120 4\n132 116 4\n128 112 8\n124 108 8\n124 104 8\n120 100 8\n116 96 8\n112 92 8\n112 88 8\n108 84 8\n104 80 8\n104 76 8\n100 72 12\n96 68 12\n92 68 12\n92 64 12\n88 60 12\n84 56 12\n84 56 12\n152 192 208\n124 168 188\n100 148 172\n76 124 156\n60 104 140\n40 84 124\n28 64 108\n16 48 92\n12 44 88\n8 40 84\n8 36 80\n4 32 80\n4 28 76\n0 24 72\n0 20 68\n0 20 68\n96 176 200\n84 156 184\n68 136 168\n60 120 156\n48 100 140\n40 84 128\n28 68 112\n24 56 100\n16 48 92\n12 44 84\n8 40 76\n4 36 72\n4 32 64\n0 28 56\n0 24 48\n0 20 44\n88 196 100\n68 188 100\n32 172 68\n32 128 56\n32 112 52\n28 96 48\n20 76 40\n92 176 216\n84 164 216\n76 156 212\n68 144 212\n60 136 212\n52 124 208\n44 116 208\n36 104 204\n28 96 204\n52 120 180\n40 104 164\n32 88 148\n24 72 132\n16 60 116\n12 44 100\n8 36 84\n4 32 76\n4 28 72\n4 24 64\n0 20 60\n0 16 52\n0 16 48\n0 12 44\n0 8 36\n0 8 32\n0 0 0\n252 164 212\n192 112 152\n252 128 0\n192 92 0\n252 252 252\n192 192 192\n0 252 0\n0 192 0\n0 252 252\n0 192 192\n252 252 0\n192 192 0\n252 0 0\n192 0 0\n252 252 252\n200 212 172\n156 176 144\n228 160 128\n220 140 96\n168 136 112\n8 76 76\n4 68 68\n4 56 60\n72 176 200\n56 160 192\n36 136 180\n28 124 172\n16 112 164\n60 136 140\n0 80 144\n216 252 0\n252 252 120\n236 228 104\n224 204 92\n208 184 76\n176 172 4\n152 152 4\n128 132 4\n104 112 0\n80 92 0\n52 72 0\n244 104 0\n156 68 0\n96 40 0\n184 124 204\n140 64 164\n80 40 92\n8 28 60\n8 32 64\n8 36 72\n8 40 80\n8 44 88\n8 48 96\n8 56 100\n8 60 108\n8 68 116\n8 72 124\n8 80 132\n8 96 152\n8 116 172\n8 84 136\n8 56 104\n8 36 72\n180 92 0\n172 68 0\n164 44 0\n156 24 0\n144 20 4\n128 16 12\n116 16 16\n92 12 20\n80 8 24\n64 8 28\n56 4 36\n40 4 36\n28 0 32\n24 0 8\n12 0 4\n0 0 0\n20 84 200\n12 76 180\n8 68 164\n4 60 148\n0 52 132\n0 44 116\n0 40 100\n0 36 88\n0 24 76\n0 20 68\n0 12 60\n0 8 52\n0 4 40\n0 0 32\n0 0 24\n0 0 16\n20 76 140\n16 56 128\n12 40 120\n8 28 108\n8 16 100\n4 4 88\n12 4 80\n16 4 76\n12 4 64\n8 4 56\n8 0 44\n4 0 36\n4 0 24\n0 0 16\n0 0 4\n0 0 0\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n168 216 228\n44 160 212\n24 136 192\n4 68 120\n0 8 32\n24 220 140\n20 184 112\n16 148 84\n12 112 60\n8 76 40\n4 44 20\n4 4 40\n252 252 164\n220 232 140\n192 212 120\n164 192 104\n"
  },
  {
    "path": "bin/common/Palettes/TFTD-JASC-SAFE/PAL_GRAPHS_SAFE.pal",
    "content": "JASC-PAL\n0100\n256\n0 255 0\n252 252 252\n224 224 224\n188 188 212\n132 132 176\n80 108 144\n44 44 84\n20 20 40\n0 0 0\n252 24 24\n216 16 16\n180 12 12\n140 8 8\n104 0 0\n40 40 40\n24 24 24\n252 252 0\n216 208 0\n180 168 0\n144 128 0\n108 92 0\n72 60 0\n96 84 0\n72 60 0\n252 0 0\n212 0 0\n176 0 0\n136 0 0\n100 0 0\n64 0 0\n88 0 0\n64 0 0\n0 252 0\n0 212 0\n0 176 0\n0 136 0\n0 100 0\n0 64 0\n0 88 0\n0 64 0\n0 124 252\n0 100 208\n0 76 168\n0 52 124\n0 32 84\n0 16 44\n0 28 72\n0 16 44\n0 252 252\n0 212 212\n0 172 172\n0 132 132\n0 92 92\n0 56 56\n0 84 84\n0 56 56\n252 132 208\n208 96 164\n164 68 128\n120 44 88\n76 24 56\n36 8 24\n64 20 44\n36 8 24\n252 112 0\n212 84 0\n172 56 0\n132 36 0\n92 20 0\n52 8 0\n80 16 0\n52 8 0\n252 172 88\n216 144 72\n184 120 56\n152 96 44\n120 72 28\n88 52 20\n108 64 28\n88 52 20\n184 120 252\n152 92 220\n124 68 188\n96 44 156\n72 28 124\n52 16 92\n68 24 112\n52 16 92\n132 184 196\n104 152 164\n80 120 136\n56 88 104\n36 60 76\n20 36 48\n32 52 68\n20 36 48\n252 252 252\n216 216 216\n180 180 180\n144 144 144\n108 108 108\n76 76 76\n100 100 100\n76 76 76\n24 220 140\n20 184 112\n16 148 84\n12 112 60\n8 76 40\n4 44 20\n8 68 32\n4 44 20\n224 128 100\n188 96 72\n152 64 48\n116 40 28\n80 20 12\n48 8 4\n72 16 8\n48 8 4\n200 168 200\n164 132 164\n128 100 128\n92 68 92\n56 40 56\n24 16 24\n48 32 48\n24 16 24\n192 164 68\n160 132 48\n128 104 36\n100 76 20\n68 52 12\n40 28 4\n60 44 8\n40 28 4\n252 148 148\n208 112 112\n164 80 80\n124 52 52\n80 32 32\n40 12 12\n68 24 24\n40 12 12\n252 252 120\n236 228 104\n224 204 92\n208 184 76\n176 172 4\n152 152 4\n128 132 4\n104 112 0\n80 92 0\n52 72 0\n244 104 0\n156 68 0\n96 40 0\n184 124 204\n140 64 164\n80 40 92\n0 68 0\n0 56 0\n0 44 0\n0 32 0\n0 24 0\n96 96 96\n96 96 96\n96 96 96\n96 96 96\n96 96 96\n96 96 96\n96 96 96\n96 96 96\n96 96 96\n96 96 96\n96 96 96\n136 244 224\n120 228 208\n108 216 192\n96 200 176\n80 188 160\n72 172 148\n60 160 132\n52 148 120\n0 76 160\n0 64 144\n0 56 132\n0 48 120\n0 40 104\n0 32 92\n0 24 80\n0 20 68\n60 156 188\n44 124 168\n32 92 148\n20 68 128\n12 44 108\n4 24 88\n0 4 68\n0 0 52\n52 112 44\n40 100 32\n28 92 24\n20 84 16\n12 76 8\n4 68 4\n0 60 0\n0 52 0\n0 76 192\n0 72 184\n0 68 180\n0 68 172\n0 64 168\n0 64 160\n0 60 156\n0 56 148\n0 56 144\n0 52 136\n0 52 132\n0 48 124\n0 44 120\n0 44 116\n0 40 108\n0 40 104\n192 168 216\n176 156 200\n160 144 188\n144 132 176\n128 120 164\n112 108 152\n96 100 140\n88 92 128\n76 76 120\n68 68 112\n56 56 104\n44 44 96\n32 32 88\n20 20 80\n8 8 72\n0 0 32\n0 20 68\n8 44 100\n28 76 136\n60 116 168\n96 156 204\n144 204 240\n160 160 160\n132 132 132\n100 100 100\n72 72 72\n40 40 40\n8 8 8\n28 28 28\n8 8 8\n192 212 120\n164 192 104\n"
  },
  {
    "path": "bin/common/Palettes/UFO-JASC/BACKPALS.DAT.pal",
    "content": "JASC-PAL\n0100\n256\n104 124 68\n104 116 64\n100 108 60\n100 104 56\n96 96 52\n92 88 52\n84 76 48\n76 68 44\n72 60 40\n64 52 36\n60 44 32\n52 40 28\n44 32 24\n40 24 24\n32 20 20\n28 16 16\n132 120 120\n124 104 104\n116 92 92\n108 76 76\n100 68 68\n96 56 56\n88 44 44\n80 36 36\n72 28 28\n64 20 20\n60 16 16\n52 8 8\n44 4 4\n36 0 0\n28 0 0\n24 0 0\n220 100 0\n204 76 0\n192 52 4\n180 36 8\n164 20 8\n152 12 16\n140 12 28\n124 16 40\n112 16 44\n100 16 48\n84 16 52\n72 12 48\n60 12 44\n44 8 40\n32 8 28\n20 4 20\n184 136 120\n172 120 112\n160 108 104\n148 96 96\n136 88 92\n124 80 88\n112 72 84\n100 64 76\n88 56 72\n76 48 64\n64 40 56\n52 32 48\n40 24 36\n28 16 28\n20 12 16\n8 4 8\n40 92 116\n36 92 108\n32 92 104\n32 96 100\n28 92 92\n28 88 80\n24 84 72\n24 76 60\n20 72 52\n20 68 44\n16 60 36\n16 56 28\n12 52 24\n12 44 16\n8 40 12\n8 36 8\n192 4 0\n180 0 4\n168 0 12\n156 0 20\n144 0 32\n132 0 36\n120 0 44\n112 0 48\n100 0 48\n88 0 48\n76 0 48\n64 0 44\n52 0 40\n40 0 36\n28 0 28\n20 0 20\n200 132 100\n188 124 88\n176 116 76\n164 108 64\n152 100 52\n140 92 44\n128 88 36\n120 80 28\n108 72 20\n96 68 16\n84 60 8\n72 56 4\n60 48 4\n48 40 0\n36 32 0\n28 24 0\n28 88 140\n28 68 132\n28 52 124\n28 40 116\n28 24 108\n36 24 100\n44 24 92\n48 24 84\n52 20 76\n52 20 68\n52 20 60\n52 16 52\n44 16 44\n36 12 32\n32 8 24\n24 8 16\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n0 0 0\n"
  },
  {
    "path": "bin/common/Palettes/UFO-JASC/PAL_BASESCAPE.pal",
    "content": "JASC-PAL\n0100\n256\n0 0 0\n252 252 252\n232 232 232\n216 216 216\n196 196 196\n176 176 176\n160 160 160\n140 140 140\n124 124 124\n104 104 104\n88 88 88\n68 68 68\n52 52 52\n32 32 32\n12 12 12\n0 0 0\n252 208 0\n240 184 0\n228 160 0\n216 140 0\n204 120 0\n192 104 0\n180 84 0\n168 72 0\n156 56 0\n144 44 0\n132 32 0\n120 24 0\n108 12 0\n96 4 0\n84 0 0\n72 0 0\n252 120 120\n240 104 104\n228 92 92\n216 80 80\n204 68 68\n192 60 60\n180 48 48\n168 40 40\n156 32 32\n144 24 24\n132 16 16\n120 12 12\n108 4 4\n96 4 4\n84 0 0\n72 0 0\n208 228 96\n184 212 84\n164 196 72\n144 184 60\n124 168 48\n104 156 40\n88 140 32\n72 124 24\n56 112 20\n40 96 12\n28 84 8\n16 68 4\n8 52 0\n4 40 0\n0 24 0\n0 12 0\n236 236 248\n216 216 232\n200 200 220\n184 184 208\n172 168 196\n156 152 184\n144 140 172\n132 124 160\n120 112 148\n108 100 132\n96 88 120\n84 76 108\n72 64 96\n64 52 84\n52 44 72\n44 36 60\n248 248 248\n232 228 224\n220 208 208\n204 192 188\n192 176 172\n180 156 152\n164 140 136\n152 128 120\n136 112 104\n124 100 92\n112 84 80\n96 72 64\n84 60 52\n68 48 44\n56 36 32\n44 28 24\n240 196 72\n228 176 64\n212 156 52\n200 136 48\n188 120 40\n176 104 32\n164 88 28\n152 72 20\n140 60 16\n128 48 12\n116 32 8\n104 24 4\n92 16 4\n80 8 0\n68 0 0\n56 0 0\n200 184 172\n188 172 156\n180 160 144\n168 148 132\n160 140 120\n152 128 108\n128 96 80\n120 76 68\n112 60 56\n104 48 52\n96 40 48\n88 32 48\n80 24 48\n72 16 48\n64 12 48\n56 8 48\n168 208 240\n148 192 228\n132 176 220\n116 160 208\n100 148 200\n88 132 192\n72 116 180\n60 104 172\n48 92 160\n40 76 152\n28 64 144\n20 52 132\n12 44 124\n4 32 112\n0 24 104\n0 16 96\n252 252 120\n240 232 104\n228 216 92\n216 196 80\n204 180 68\n196 160 60\n184 144 48\n172 128 40\n160 112 32\n148 96 24\n140 80 16\n128 64 12\n116 52 8\n104 40 4\n92 28 0\n84 20 0\n184 160 88\n172 144 76\n160 128 64\n148 112 56\n136 96 44\n124 80 36\n112 68 28\n104 56 24\n92 44 16\n80 32 12\n68 20 8\n56 12 4\n44 8 0\n32 4 0\n20 0 0\n12 0 0\n248 220 212\n236 200 192\n224 180 176\n212 160 160\n200 144 148\n188 128 136\n176 116 124\n164 104 116\n152 88 104\n136 72 96\n124 60 88\n112 48 80\n100 36 72\n88 28 64\n76 16 60\n48 0 40\n100 64 92\n96 60 88\n88 56 88\n84 52 84\n80 52 80\n72 48 76\n64 44 72\n60 40 68\n52 40 64\n48 36 60\n40 32 56\n36 28 52\n32 28 48\n28 24 44\n24 20 40\n20 20 36\n248 220 212\n232 232 232\n184 184 184\n136 136 136\n88 88 88\n44 44 44\n216 216 132\n176 168 100\n140 120 72\n100 80 48\n64 44 28\n132 176 220\n80 124 180\n40 80 140\n12 44 100\n0 16 60\n84 44 128\n64 36 104\n56 32 100\n44 28 92\n36 24 88\n28 20 84\n20 16 76\n12 12 72\n8 12 64\n4 12 60\n4 12 56\n4 12 48\n0 12 44\n0 12 36\n0 12 32\n0 12 28\n0 0 0\n0 0 0\n236 200 192\n196 128 132\n156 80 100\n116 40 80\n76 16 60\n180 148 232\n136 100 184\n100 60 136\n68 28 88\n32 8 40\n252 252 164\n220 232 140\n192 212 120\n164 192 104\n"
  },
  {
    "path": "bin/common/Palettes/UFO-JASC/PAL_BATTLEPEDIA.pal",
    "content": "JASC-PAL\n0100\n256\n0 0 0\n252 252 252\n232 232 232\n216 216 216\n196 196 196\n176 176 176\n160 160 160\n140 140 140\n124 124 124\n104 104 104\n88 88 88\n68 68 68\n52 52 52\n32 32 32\n12 12 12\n0 0 0\n252 208 0\n236 180 0\n224 160 0\n208 136 0\n196 116 0\n180 96 0\n168 80 0\n152 64 0\n140 52 0\n124 36 0\n112 28 0\n96 16 0\n84 8 0\n72 4 0\n56 0 0\n44 0 0\n252 120 120\n236 104 104\n224 92 92\n208 76 76\n196 68 68\n184 56 56\n168 44 44\n156 36 36\n140 28 28\n128 20 20\n116 12 12\n100 8 8\n88 4 4\n72 0 0\n60 0 0\n48 0 0\n160 224 132\n136 208 116\n116 196 100\n92 184 84\n72 172 72\n60 160 64\n48 144 60\n40 132 56\n28 120 56\n20 108 52\n16 96 48\n8 80 44\n4 68 40\n0 56 36\n0 44 28\n0 32 24\n208 228 96\n184 212 84\n164 196 72\n144 184 60\n124 168 48\n104 156 40\n88 140 32\n72 124 24\n56 112 20\n40 96 12\n28 84 8\n16 68 4\n8 52 0\n4 40 0\n0 24 0\n0 12 0\n248 248 248\n232 224 224\n220 208 204\n204 188 184\n192 172 168\n176 156 148\n164 140 132\n148 124 116\n136 108 100\n120 92 88\n108 80 72\n92 68 60\n80 56 48\n68 44 40\n52 32 28\n40 24 20\n240 196 72\n224 176 64\n212 156 52\n200 136 48\n188 120 40\n176 104 32\n160 84 24\n148 72 20\n136 56 16\n124 44 12\n112 32 8\n96 20 4\n84 12 4\n72 4 0\n60 0 0\n48 0 0\n140 176 200\n128 160 188\n112 144 176\n104 128 164\n92 112 152\n80 100 144\n72 84 132\n60 72 120\n52 60 108\n44 48 96\n36 36 88\n32 28 76\n28 24 64\n24 16 52\n20 12 40\n16 8 32\n168 208 240\n148 188 224\n128 172 212\n112 152 200\n96 136 188\n80 120 172\n64 104 160\n52 88 148\n40 72 132\n28 60 120\n20 48 108\n12 36 96\n8 24 80\n4 16 68\n0 8 56\n0 4 44\n252 252 120\n236 228 104\n224 204 92\n208 184 76\n196 160 68\n184 140 56\n168 120 44\n156 100 36\n140 80 28\n128 64 20\n116 48 12\n100 32 8\n88 20 4\n72 8 0\n60 4 0\n48 0 0\n184 160 88\n172 144 76\n160 128 64\n148 112 56\n136 96 44\n124 80 36\n112 68 28\n104 56 24\n92 44 16\n80 32 12\n68 20 8\n56 12 4\n44 8 0\n32 4 0\n20 0 0\n12 0 0\n248 220 212\n232 196 192\n220 176 172\n208 152 152\n192 136 140\n180 120 128\n168 104 120\n152 92 108\n140 76 100\n128 64 92\n112 52 84\n100 44 76\n88 32 68\n72 24 60\n60 16 52\n48 12 44\n216 196 252\n200 172 236\n184 148 224\n172 128 208\n160 108 196\n152 92 180\n140 76 168\n132 60 152\n124 48 140\n116 36 124\n108 24 112\n96 16 96\n84 8 80\n72 4 60\n56 0 44\n44 0 32\n64 196 252\n56 172 236\n48 148 224\n40 128 208\n32 108 196\n28 88 184\n24 72 168\n16 52 156\n12 40 140\n8 24 128\n4 16 116\n4 4 100\n4 0 88\n4 0 72\n8 0 60\n8 0 48\n236 236 248\n216 216 232\n196 196 220\n180 180 208\n164 164 192\n148 144 180\n136 132 168\n120 116 152\n108 100 140\n96 88 128\n84 76 112\n72 64 100\n60 52 88\n52 40 72\n40 32 60\n32 24 48\n160 184 216\n128 148 180\n96 120 144\n68 88 108\n44 60 76\n116 184 252\n80 144 208\n52 108 168\n28 76 124\n12 48 84\n68 76 80\n64 68 72\n252 252 164\n220 232 140\n192 212 120\n164 192 104\n"
  },
  {
    "path": "bin/common/Palettes/UFO-JASC/PAL_BATTLESCAPE.pal",
    "content": "JASC-PAL\n0100\n256\n0 0 0\n252 252 252\n232 232 232\n216 216 216\n196 196 196\n176 176 176\n160 160 160\n140 140 140\n124 124 124\n104 104 104\n88 88 88\n68 68 68\n52 52 52\n32 32 32\n12 12 12\n0 0 0\n252 208 0\n236 180 0\n224 160 0\n208 136 0\n196 116 0\n180 96 0\n168 80 0\n152 64 0\n140 52 0\n124 36 0\n112 28 0\n96 16 0\n84 8 0\n72 4 0\n56 0 0\n44 0 0\n252 120 120\n236 104 104\n224 92 92\n208 76 76\n196 68 68\n184 56 56\n168 44 44\n156 36 36\n140 28 28\n128 20 20\n116 12 12\n100 8 8\n88 4 4\n72 0 0\n60 0 0\n48 0 0\n160 224 132\n136 208 116\n116 196 100\n92 184 84\n72 172 72\n60 160 64\n48 144 60\n40 132 56\n28 120 56\n20 108 52\n16 96 48\n8 80 44\n4 68 40\n0 56 36\n0 44 28\n0 32 24\n208 228 96\n184 212 84\n164 196 72\n144 184 60\n124 168 48\n104 156 40\n88 140 32\n72 124 24\n56 112 20\n40 96 12\n28 84 8\n16 68 4\n8 52 0\n4 40 0\n0 24 0\n0 12 0\n248 248 248\n232 224 224\n220 208 204\n204 188 184\n192 172 168\n176 156 148\n164 140 132\n148 124 116\n136 108 100\n120 92 88\n108 80 72\n92 68 60\n80 56 48\n68 44 40\n52 32 28\n40 24 20\n240 196 72\n224 176 64\n212 156 52\n200 136 48\n188 120 40\n176 104 32\n160 84 24\n148 72 20\n136 56 16\n124 44 12\n112 32 8\n96 20 4\n84 12 4\n72 4 0\n60 0 0\n48 0 0\n140 176 200\n128 160 188\n112 144 176\n104 128 164\n92 112 152\n80 100 144\n72 84 132\n60 72 120\n52 60 108\n44 48 96\n36 36 88\n32 28 76\n28 24 64\n24 16 52\n20 12 40\n16 8 32\n168 208 240\n148 188 224\n128 172 212\n112 152 200\n96 136 188\n80 120 172\n64 104 160\n52 88 148\n40 72 132\n28 60 120\n20 48 108\n12 36 96\n8 24 80\n4 16 68\n0 8 56\n0 4 44\n252 252 120\n236 228 104\n224 204 92\n208 184 76\n196 160 68\n184 140 56\n168 120 44\n156 100 36\n140 80 28\n128 64 20\n116 48 12\n100 32 8\n88 20 4\n72 8 0\n60 4 0\n48 0 0\n184 160 88\n172 144 76\n160 128 64\n148 112 56\n136 96 44\n124 80 36\n112 68 28\n104 56 24\n92 44 16\n80 32 12\n68 20 8\n56 12 4\n44 8 0\n32 4 0\n20 0 0\n12 0 0\n248 220 212\n232 196 192\n220 176 172\n208 152 152\n192 136 140\n180 120 128\n168 104 120\n152 92 108\n140 76 100\n128 64 92\n112 52 84\n100 44 76\n88 32 68\n72 24 60\n60 16 52\n48 12 44\n216 196 252\n200 172 236\n184 148 224\n172 128 208\n160 108 196\n152 92 180\n140 76 168\n132 60 152\n124 48 140\n116 36 124\n108 24 112\n96 16 96\n84 8 80\n72 4 60\n56 0 44\n44 0 32\n64 196 252\n56 172 236\n48 148 224\n40 128 208\n32 108 196\n28 88 184\n24 72 168\n16 52 156\n12 40 140\n8 24 128\n4 16 116\n4 4 100\n4 0 88\n4 0 72\n8 0 60\n8 0 48\n236 236 248\n216 216 232\n196 196 220\n180 180 208\n164 164 192\n148 144 180\n136 132 168\n120 116 152\n108 100 140\n96 88 128\n84 76 112\n72 64 100\n60 52 88\n52 40 72\n40 32 60\n32 24 48\n140 152 148\n132 136 140\n116 124 132\n108 116 124\n92 104 108\n84 92 100\n76 80 92\n56 68 84\n48 56 68\n40 48 56\n32 36 48\n24 28 32\n16 20 24\n8 12 16\n3 4 8\n3 3 6\n"
  },
  {
    "path": "bin/common/Palettes/UFO-JASC/PAL_BATTLE_COMMON.pal",
    "content": "JASC-PAL\n0100\n256\n0 0 0\n252 252 252\n232 232 232\n216 216 216\n196 196 196\n176 176 176\n160 160 160\n140 140 140\n124 124 124\n104 104 104\n88 88 88\n68 68 68\n52 52 52\n32 32 32\n12 12 12\n0 0 0\n252 208 0\n236 180 0\n224 160 0\n208 136 0\n196 116 0\n180 96 0\n168 80 0\n152 64 0\n140 52 0\n124 36 0\n112 28 0\n96 16 0\n84 8 0\n72 4 0\n56 0 0\n44 0 0\n252 120 120\n236 104 104\n224 92 92\n208 76 76\n196 68 68\n184 56 56\n168 44 44\n156 36 36\n140 28 28\n128 20 20\n116 12 12\n100 8 8\n88 4 4\n72 0 0\n60 0 0\n48 0 0\n160 224 132\n136 208 116\n116 196 100\n92 184 84\n72 172 72\n60 160 64\n48 144 60\n40 132 56\n28 120 56\n20 108 52\n16 96 48\n8 80 44\n4 68 40\n0 56 36\n0 44 28\n0 32 24\n208 228 96\n184 212 84\n164 196 72\n144 184 60\n124 168 48\n104 156 40\n88 140 32\n72 124 24\n56 112 20\n40 96 12\n28 84 8\n16 68 4\n8 52 0\n4 40 0\n0 24 0\n0 12 0\n248 248 248\n232 224 224\n220 208 204\n204 188 184\n192 172 168\n176 156 148\n164 140 132\n148 124 116\n136 108 100\n120 92 88\n108 80 72\n92 68 60\n80 56 48\n68 44 40\n52 32 28\n40 24 20\n240 196 72\n224 176 64\n212 156 52\n200 136 48\n188 120 40\n176 104 32\n160 84 24\n148 72 20\n136 56 16\n124 44 12\n112 32 8\n96 20 4\n84 12 4\n72 4 0\n60 0 0\n48 0 0\n140 176 200\n128 160 188\n112 144 176\n104 128 164\n92 112 152\n80 100 144\n72 84 132\n60 72 120\n52 60 108\n44 48 96\n36 36 88\n32 28 76\n28 24 64\n24 16 52\n20 12 40\n16 8 32\n168 208 240\n148 188 224\n128 172 212\n112 152 200\n96 136 188\n80 120 172\n64 104 160\n52 88 148\n40 72 132\n28 60 120\n20 48 108\n12 36 96\n8 24 80\n4 16 68\n0 8 56\n0 4 44\n252 252 120\n236 228 104\n224 204 92\n208 184 76\n196 160 68\n184 140 56\n168 120 44\n156 100 36\n140 80 28\n128 64 20\n116 48 12\n100 32 8\n88 20 4\n72 8 0\n60 4 0\n48 0 0\n184 160 88\n172 144 76\n160 128 64\n148 112 56\n136 96 44\n124 80 36\n112 68 28\n104 56 24\n92 44 16\n80 32 12\n68 20 8\n56 12 4\n44 8 0\n32 4 0\n20 0 0\n12 0 0\n248 220 212\n232 196 192\n220 176 172\n208 152 152\n192 136 140\n180 120 128\n168 104 120\n152 92 108\n140 76 100\n128 64 92\n112 52 84\n100 44 76\n88 32 68\n72 24 60\n60 16 52\n48 12 44\n216 196 252\n200 172 236\n184 148 224\n172 128 208\n160 108 196\n152 92 180\n140 76 168\n132 60 152\n124 48 140\n116 36 124\n108 24 112\n96 16 96\n84 8 80\n72 4 60\n56 0 44\n44 0 32\n64 196 252\n56 172 236\n48 148 224\n40 128 208\n32 108 196\n28 88 184\n24 72 168\n16 52 156\n12 40 140\n8 24 128\n4 16 116\n4 4 100\n4 0 88\n4 0 72\n8 0 60\n8 0 48\n236 236 248\n216 216 232\n196 196 220\n180 180 208\n164 164 192\n148 144 180\n136 132 168\n120 116 152\n108 100 140\n96 88 128\n84 76 112\n72 64 100\n60 52 88\n52 40 72\n40 32 60\n32 24 48\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n"
  },
  {
    "path": "bin/common/Palettes/UFO-JASC/PAL_GEOSCAPE.pal",
    "content": "JASC-PAL\n0100\n256\n0 0 0\n252 164 212\n192 112 152\n252 128 0\n192 92 0\n252 252 252\n192 192 192\n0 252 0\n0 192 0\n0 252 252\n0 192 192\n252 252 0\n192 192 0\n252 0 0\n192 0 0\n0 0 0\n0 128 44\n0 120 40\n0 116 36\n0 108 36\n0 104 32\n0 100 32\n0 92 28\n0 88 28\n0 80 24\n0 76 24\n0 72 20\n0 64 20\n0 60 16\n0 52 16\n0 48 12\n0 44 12\n116 156 44\n100 148 36\n88 140 32\n76 132 28\n60 124 24\n52 116 20\n40 108 16\n28 104 12\n20 96 8\n12 88 4\n4 80 4\n4 72 4\n0 64 8\n0 56 8\n0 48 8\n0 44 12\n172 164 0\n160 152 0\n152 144 0\n144 136 0\n136 124 0\n124 116 0\n116 108 0\n108 100 0\n96 88 0\n88 80 0\n80 72 0\n72 64 0\n60 56 0\n52 48 0\n44 40 0\n36 32 0\n148 164 48\n136 152 44\n128 144 40\n120 136 36\n112 128 32\n100 120 28\n92 108 28\n84 100 24\n76 92 20\n68 84 16\n60 76 16\n52 64 12\n44 56 8\n36 48 8\n32 40 4\n24 32 4\n124 244 216\n112 228 220\n104 196 208\n92 164 192\n84 132 176\n72 104 160\n64 80 144\n56 56 128\n56 48 112\n56 40 96\n216 252 0\n160 212 0\n116 172 0\n76 132 0\n44 92 0\n20 56 0\n204 188 204\n184 168 184\n168 152 168\n148 132 152\n132 116 136\n116 100 120\n96 84 100\n80 68 84\n64 52 68\n48 40 52\n28 72 116\n216 252 0\n188 232 0\n160 212 0\n136 196 0\n116 176 0\n96 160 0\n88 152 0\n80 144 0\n76 136 0\n68 132 0\n64 124 0\n60 116 0\n52 108 0\n48 104 0\n44 96 0\n40 88 0\n36 84 0\n32 76 0\n28 68 0\n24 60 0\n20 56 0\n252 0 0\n252 0 0\n252 0 0\n252 0 0\n252 0 0\n252 0 0\n100 204 188\n60 164 144\n28 128 100\n8 88 64\n0 52 32\n168 188 80\n128 152 56\n96 120 40\n64 84 24\n36 52 12\n176 148 68\n168 140 68\n160 132 68\n148 124 68\n140 116 68\n128 108 64\n120 100 64\n108 92 60\n100 84 56\n88 76 52\n80 68 48\n68 60 44\n60 52 40\n52 44 36\n40 36 28\n32 28 24\n152 176 176\n144 168 168\n136 160 160\n128 148 148\n120 140 140\n112 128 128\n104 120 120\n96 108 108\n84 100 100\n76 88 88\n68 80 80\n60 68 68\n52 60 60\n44 52 52\n36 40 40\n28 32 32\n112 48 132\n104 44 120\n96 40 112\n88 36 104\n80 32 96\n72 28 84\n64 24 76\n56 24 68\n48 20 60\n40 16 48\n32 12 40\n28 8 32\n20 4 24\n12 4 12\n4 0 4\n0 0 0\n0 36 116\n0 32 112\n0 32 112\n0 32 108\n0 32 108\n0 32 104\n0 32 104\n0 28 100\n0 28 100\n0 28 96\n0 28 96\n0 28 92\n0 28 92\n0 28 88\n0 24 88\n0 24 84\n0 24 84\n0 24 80\n0 24 80\n0 24 76\n0 20 76\n0 20 72\n0 20 72\n0 20 68\n0 20 68\n0 20 68\n0 16 64\n0 16 64\n0 16 60\n0 16 60\n0 16 56\n0 16 56\n104 124 68\n104 116 64\n100 108 60\n100 104 56\n96 96 52\n92 88 52\n84 76 48\n76 68 44\n72 60 40\n64 52 36\n60 44 32\n52 40 28\n44 32 24\n40 24 24\n32 20 20\n28 16 16\n64 176 108\n52 140 84\n40 108 64\n28 76 44\n16 44 24\n128 188 228\n104 160 204\n88 136 184\n68 112 164\n52 92 140\n40 68 120\n28 52 100\n252 252 164\n220 232 140\n192 212 120\n164 192 104\n"
  },
  {
    "path": "bin/common/Palettes/UFO-JASC/PAL_GRAPHS.pal",
    "content": "JASC-PAL\n0100\n256\n0 0 0\n252 252 252\n236 236 236\n216 216 216\n200 200 200\n184 184 184\n168 168 168\n152 152 152\n136 136 136\n120 120 120\n104 104 104\n88 88 88\n72 72 72\n56 56 56\n40 40 40\n24 24 24\n252 252 0\n216 208 0\n180 168 0\n144 128 0\n108 92 0\n72 60 0\n96 84 0\n72 60 0\n252 0 0\n212 0 0\n176 0 0\n136 0 0\n100 0 0\n64 0 0\n88 0 0\n64 0 0\n0 252 0\n0 212 0\n0 176 0\n0 136 0\n0 100 0\n0 64 0\n0 88 0\n0 64 0\n0 124 252\n0 100 208\n0 76 168\n0 52 124\n0 32 84\n0 16 44\n0 28 72\n0 16 44\n0 252 252\n0 212 212\n0 172 172\n0 132 132\n0 92 92\n0 56 56\n0 84 84\n0 56 56\n252 132 208\n208 96 164\n164 68 128\n120 44 88\n76 24 56\n36 8 24\n64 20 44\n36 8 24\n252 112 0\n212 84 0\n172 56 0\n132 36 0\n92 20 0\n52 8 0\n80 16 0\n52 8 0\n252 172 88\n216 144 72\n184 120 56\n152 96 44\n120 72 28\n88 52 20\n108 64 28\n88 52 20\n184 120 252\n152 92 220\n124 68 188\n96 44 156\n72 28 124\n52 16 92\n68 24 112\n52 16 92\n132 184 196\n104 152 164\n80 120 136\n56 88 104\n36 60 76\n20 36 48\n32 52 68\n20 36 48\n252 252 252\n216 216 216\n180 180 180\n144 144 144\n108 108 108\n76 76 76\n100 100 100\n76 76 76\n24 220 140\n20 184 112\n16 148 84\n12 112 60\n8 76 40\n4 44 20\n8 68 32\n4 44 20\n224 128 100\n188 96 72\n152 64 48\n116 40 28\n80 20 12\n48 8 4\n72 16 8\n48 8 4\n200 168 200\n164 132 164\n128 100 128\n92 68 92\n56 40 56\n24 16 24\n48 32 48\n24 16 24\n192 164 68\n160 132 48\n128 104 36\n100 76 20\n68 52 12\n40 28 4\n60 44 8\n40 28 4\n252 148 148\n208 112 112\n164 80 80\n124 52 52\n80 32 32\n40 12 12\n68 24 24\n40 12 12\n208 32 128\n172 20 104\n136 8 84\n104 4 60\n68 0 40\n36 0 20\n60 0 32\n36 0 20\n160 160 160\n128 128 128\n96 96 96\n68 68 68\n36 36 36\n8 8 8\n28 28 28\n8 8 8\n0 68 0\n0 56 0\n0 44 0\n0 32 0\n0 24 0\n96 96 96\n96 96 96\n96 96 96\n96 96 96\n96 96 96\n96 96 96\n96 96 96\n96 96 96\n96 96 96\n96 96 96\n96 96 96\n136 244 224\n120 228 208\n108 216 192\n96 200 176\n80 188 160\n72 172 148\n60 160 132\n52 148 120\n0 76 160\n0 64 144\n0 56 132\n0 48 120\n0 40 104\n0 32 92\n0 24 80\n0 20 68\n60 156 188\n44 124 168\n32 92 148\n20 68 128\n12 44 108\n4 24 88\n0 4 68\n0 0 52\n52 112 44\n40 100 32\n28 92 24\n20 84 16\n12 76 8\n4 68 4\n0 60 0\n0 52 0\n0 76 192\n0 72 184\n0 68 180\n0 68 172\n0 64 168\n0 64 160\n0 60 156\n0 56 148\n0 56 144\n0 52 136\n0 52 132\n0 48 124\n0 44 120\n0 44 116\n0 40 108\n0 40 104\n12 76 8\n8 72 4\n8 68 4\n4 64 4\n4 60 4\n4 56 4\n4 52 0\n4 48 0\n0 44 0\n0 40 0\n0 36 0\n0 32 0\n0 28 0\n0 24 0\n0 20 0\n0 16 0\n0 20 68\n8 44 100\n28 76 136\n60 116 168\n96 156 204\n144 204 240\n96 96 96\n96 96 96\n96 96 96\n96 96 96\n96 96 96\n96 96 96\n252 252 164\n220 232 140\n192 212 120\n164 192 104\n"
  },
  {
    "path": "bin/common/Palettes/UFO-JASC/PAL_UFOPAEDIA.pal",
    "content": "JASC-PAL\n0100\n256\n0 0 0\n252 252 228\n252 248 216\n252 248 204\n252 244 192\n252 240 184\n252 236 172\n252 228 160\n252 220 152\n252 216 140\n252 208 128\n252 196 116\n252 188 108\n252 176 96\n252 164 84\n252 152 76\n252 232 0\n248 212 0\n244 200 0\n244 184 0\n240 168 0\n236 152 0\n236 136 0\n232 124 0\n228 108 0\n228 96 0\n216 84 0\n204 72 0\n192 60 0\n180 48 0\n168 40 0\n156 32 0\n252 252 236\n244 244 228\n236 236 220\n228 232 216\n216 224 208\n212 220 200\n200 212 196\n192 204 188\n184 200 180\n176 192 176\n168 184 168\n164 180 164\n156 172 160\n152 168 156\n144 160 152\n136 152 144\n132 148 140\n124 140 136\n120 136 132\n112 128 124\n108 120 120\n100 116 116\n96 108 108\n88 100 104\n84 92 96\n76 84 88\n72 76 84\n64 72 76\n60 64 68\n56 56 64\n48 48 56\n44 44 52\n236 252 124\n212 236 108\n192 224 96\n172 212 80\n152 200 68\n132 188 60\n112 172 48\n96 160 40\n80 148 32\n64 136 24\n48 124 16\n32 108 8\n20 96 4\n12 84 4\n4 72 0\n0 60 0\n236 236 248\n224 224 240\n212 212 232\n204 204 224\n196 192 220\n184 184 212\n176 172 204\n164 160 196\n156 152 188\n148 144 184\n140 132 176\n136 128 168\n128 116 164\n120 108 156\n112 104 148\n108 96 144\n104 92 136\n96 84 132\n88 76 124\n84 68 116\n80 64 108\n72 56 104\n68 52 96\n64 48 88\n56 40 84\n52 36 76\n48 32 68\n40 28 60\n36 24 56\n32 20 48\n28 16 40\n24 12 36\n252 208 252\n240 192 240\n232 176 232\n224 160 224\n212 144 216\n204 132 208\n196 120 196\n184 108 188\n176 96 180\n168 84 172\n156 72 164\n148 64 152\n140 56 144\n128 48 136\n120 40 128\n112 32 120\n204 236 252\n192 224 244\n180 216 240\n168 208 232\n156 200 228\n148 192 220\n136 180 216\n128 172 208\n116 164 204\n108 156 196\n96 148 192\n92 140 184\n84 132 180\n76 124 172\n68 116 168\n60 108 160\n56 100 156\n48 92 148\n44 88 144\n40 80 136\n32 72 132\n28 68 128\n24 60 120\n20 56 116\n16 52 112\n12 44 104\n8 40 100\n4 36 92\n4 32 88\n0 28 84\n0 24 76\n0 20 72\n248 220 212\n232 196 192\n220 176 172\n208 152 152\n192 136 140\n180 120 128\n168 104 120\n152 92 108\n140 76 100\n128 64 92\n112 52 84\n100 44 76\n88 32 68\n72 24 60\n60 16 52\n48 12 44\n252 228 184\n244 216 172\n240 208 160\n232 200 148\n228 192 140\n224 184 128\n216 176 116\n212 164 108\n204 156 100\n200 148 88\n196 140 80\n188 132 72\n184 124 64\n176 116 56\n172 108 52\n168 100 44\n212 180 108\n200 168 100\n192 156 92\n184 144 88\n172 132 80\n164 124 72\n156 112 68\n144 104 64\n136 92 56\n128 84 52\n116 76 48\n108 64 40\n100 56 36\n88 48 32\n80 40 28\n72 36 24\n164 56 0\n148 40 0\n136 32 0\n124 20 0\n108 12 0\n96 4 0\n84 0 0\n72 0 0\n204 248 192\n168 224 156\n132 204 120\n104 184 92\n76 160 64\n48 140 44\n28 120 24\n12 100 12\n244 220 204\n232 204 188\n220 192 172\n208 176 156\n200 164 144\n188 152 132\n176 140 116\n164 128 104\n156 116 96\n144 104 84\n132 96 72\n124 84 64\n112 76 56\n100 64 44\n88 56 36\n80 48 32\n156 148 188\n124 120 148\n92 92 108\n60 60 68\n28 28 32\n140 204 184\n104 164 152\n72 124 120\n44 80 84\n20 40 44\n252 0 252\n252 0 252\n252 252 164\n220 232 140\n192 212 120\n164 192 104\n"
  },
  {
    "path": "bin/common/Palettes/UFO-JASC-SAFE/PAL_BACKGROUND_SAFE.pal",
    "content": "JASC-PAL\n0100\n256\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n104 124 68\n104 116 64\n100 108 60\n100 104 56\n96 96 52\n92 88 52\n84 76 48\n76 68 44\n72 60 40\n64 52 36\n60 44 32\n52 40 28\n44 32 24\n40 24 24\n32 20 20\n28 16 16\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n"
  },
  {
    "path": "bin/common/Palettes/UFO-JASC-SAFE/PAL_BASESCAPE_SAFE.pal",
    "content": "JASC-PAL\n0100\n256\n0 255 0\n252 252 252\n232 232 232\n216 216 216\n196 196 196\n176 176 176\n160 160 160\n140 140 140\n124 124 124\n104 104 104\n88 88 88\n68 68 68\n52 52 52\n32 32 32\n12 12 12\n0 0 0\n252 208 0\n240 184 0\n228 160 0\n216 140 0\n204 120 0\n192 104 0\n180 84 0\n168 72 0\n156 56 0\n144 44 0\n132 32 0\n120 24 0\n108 12 0\n96 4 0\n84 0 0\n72 0 0\n252 120 120\n240 104 104\n228 92 92\n216 80 80\n204 68 68\n192 60 60\n180 48 48\n168 40 40\n156 32 32\n144 24 24\n132 16 16\n120 12 12\n108 4 4\n96 4 4\n84 0 0\n72 0 0\n208 228 96\n184 212 84\n164 196 72\n144 184 60\n124 168 48\n104 156 40\n88 140 32\n72 124 24\n56 112 20\n40 96 12\n28 84 8\n16 68 4\n8 52 0\n4 40 0\n0 24 0\n0 12 0\n236 236 248\n216 216 232\n200 200 220\n184 184 208\n172 168 196\n156 152 184\n144 140 172\n132 124 160\n120 112 148\n108 100 132\n96 88 120\n84 76 108\n72 64 96\n64 52 84\n52 44 72\n44 36 60\n248 248 248\n232 228 224\n220 208 208\n204 192 188\n192 176 172\n180 156 152\n164 140 136\n152 128 120\n136 112 104\n124 100 92\n112 84 80\n96 72 64\n84 60 52\n68 48 44\n56 36 32\n44 28 24\n240 196 72\n228 176 64\n212 156 52\n200 136 48\n188 120 40\n176 104 32\n164 88 28\n152 72 20\n140 60 16\n128 48 12\n116 32 8\n104 24 4\n92 16 4\n80 8 0\n68 0 0\n56 0 0\n200 184 172\n188 172 156\n180 160 144\n168 148 132\n160 140 120\n152 128 108\n128 96 80\n120 76 68\n112 60 56\n104 48 52\n96 40 48\n88 32 48\n80 24 48\n72 16 48\n64 12 48\n56 8 48\n168 208 240\n148 192 228\n132 176 220\n116 160 208\n100 148 200\n88 132 192\n72 116 180\n60 104 172\n48 92 160\n40 76 152\n28 64 144\n20 52 132\n12 44 124\n4 32 112\n0 24 104\n0 16 96\n252 252 120\n240 232 104\n228 216 92\n216 196 80\n204 180 68\n196 160 60\n184 144 48\n172 128 40\n160 112 32\n148 96 24\n140 80 16\n128 64 12\n116 52 8\n104 40 4\n92 28 0\n84 20 0\n184 160 88\n172 144 76\n160 128 64\n148 112 56\n136 96 44\n124 80 36\n112 68 28\n104 56 24\n92 44 16\n80 32 12\n68 20 8\n56 12 4\n44 8 0\n32 4 0\n20 0 0\n12 0 0\n248 220 212\n236 200 192\n224 180 176\n212 160 160\n200 144 148\n188 128 136\n176 116 124\n164 104 116\n152 88 104\n136 72 96\n124 60 88\n112 48 80\n100 36 72\n88 28 64\n76 16 60\n48 0 40\n100 64 92\n96 60 88\n88 56 88\n84 52 84\n80 52 80\n72 48 76\n64 44 72\n60 40 68\n52 40 64\n48 36 60\n40 32 56\n36 28 52\n32 28 48\n28 24 44\n24 20 40\n20 20 36\n248 220 212\n232 232 232\n184 184 184\n136 136 136\n88 88 88\n44 44 44\n216 216 132\n176 168 100\n140 120 72\n100 80 48\n64 44 28\n132 176 220\n80 124 180\n40 80 140\n12 44 100\n0 16 60\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n0 0 0\n0 0 0\n236 200 192\n196 128 132\n156 80 100\n116 40 80\n76 16 60\n180 148 232\n136 100 184\n100 60 136\n68 28 88\n32 8 40\n252 252 164\n220 232 140\n192 212 120\n164 192 104\n"
  },
  {
    "path": "bin/common/Palettes/UFO-JASC-SAFE/PAL_BATTLEPEDIA_SAFE.pal",
    "content": "JASC-PAL\n0100\n256\n0 255 0\n252 252 252\n232 232 232\n216 216 216\n196 196 196\n176 176 176\n160 160 160\n140 140 140\n124 124 124\n104 104 104\n88 88 88\n68 68 68\n52 52 52\n32 32 32\n12 12 12\n0 0 0\n252 208 0\n236 180 0\n224 160 0\n208 136 0\n196 116 0\n180 96 0\n168 80 0\n152 64 0\n140 52 0\n124 36 0\n112 28 0\n96 16 0\n84 8 0\n72 4 0\n56 0 0\n44 0 0\n252 120 120\n236 104 104\n224 92 92\n208 76 76\n196 68 68\n184 56 56\n168 44 44\n156 36 36\n140 28 28\n128 20 20\n116 12 12\n100 8 8\n88 4 4\n72 0 0\n60 0 0\n48 0 0\n160 224 132\n136 208 116\n116 196 100\n92 184 84\n72 172 72\n60 160 64\n48 144 60\n40 132 56\n28 120 56\n20 108 52\n16 96 48\n8 80 44\n4 68 40\n0 56 36\n0 44 28\n0 32 24\n208 228 96\n184 212 84\n164 196 72\n144 184 60\n124 168 48\n104 156 40\n88 140 32\n72 124 24\n56 112 20\n40 96 12\n28 84 8\n16 68 4\n8 52 0\n4 40 0\n0 24 0\n0 12 0\n248 248 248\n232 224 224\n220 208 204\n204 188 184\n192 172 168\n176 156 148\n164 140 132\n148 124 116\n136 108 100\n120 92 88\n108 80 72\n92 68 60\n80 56 48\n68 44 40\n52 32 28\n40 24 20\n240 196 72\n224 176 64\n212 156 52\n200 136 48\n188 120 40\n176 104 32\n160 84 24\n148 72 20\n136 56 16\n124 44 12\n112 32 8\n96 20 4\n84 12 4\n72 4 0\n60 0 0\n48 0 0\n140 176 200\n128 160 188\n112 144 176\n104 128 164\n92 112 152\n80 100 144\n72 84 132\n60 72 120\n52 60 108\n44 48 96\n36 36 88\n32 28 76\n28 24 64\n24 16 52\n20 12 40\n16 8 32\n168 208 240\n148 188 224\n128 172 212\n112 152 200\n96 136 188\n80 120 172\n64 104 160\n52 88 148\n40 72 132\n28 60 120\n20 48 108\n12 36 96\n8 24 80\n4 16 68\n0 8 56\n0 4 44\n252 252 120\n236 228 104\n224 204 92\n208 184 76\n196 160 68\n184 140 56\n168 120 44\n156 100 36\n140 80 28\n128 64 20\n116 48 12\n100 32 8\n88 20 4\n72 8 0\n60 4 0\n48 0 0\n184 160 88\n172 144 76\n160 128 64\n148 112 56\n136 96 44\n124 80 36\n112 68 28\n104 56 24\n92 44 16\n80 32 12\n68 20 8\n56 12 4\n44 8 0\n32 4 0\n20 0 0\n12 0 0\n248 220 212\n232 196 192\n220 176 172\n208 152 152\n192 136 140\n180 120 128\n168 104 120\n152 92 108\n140 76 100\n128 64 92\n112 52 84\n100 44 76\n88 32 68\n72 24 60\n60 16 52\n48 12 44\n216 196 252\n200 172 236\n184 148 224\n172 128 208\n160 108 196\n152 92 180\n140 76 168\n132 60 152\n124 48 140\n116 36 124\n108 24 112\n96 16 96\n84 8 80\n72 4 60\n56 0 44\n44 0 32\n64 196 252\n56 172 236\n48 148 224\n40 128 208\n32 108 196\n28 88 184\n24 72 168\n16 52 156\n12 40 140\n8 24 128\n4 16 116\n4 4 100\n4 0 88\n4 0 72\n8 0 60\n8 0 48\n236 236 248\n216 216 232\n196 196 220\n180 180 208\n164 164 192\n148 144 180\n136 132 168\n120 116 152\n108 100 140\n96 88 128\n84 76 112\n72 64 100\n60 52 88\n52 40 72\n40 32 60\n32 24 48\n160 184 216\n128 148 180\n96 120 144\n68 88 108\n44 60 76\n116 184 252\n80 144 208\n52 108 168\n28 76 124\n12 48 84\n68 76 80\n64 68 72\n252 252 164\n220 232 140\n192 212 120\n164 192 104\n"
  },
  {
    "path": "bin/common/Palettes/UFO-JASC-SAFE/PAL_BATTLESCAPE_SAFE.pal",
    "content": "JASC-PAL\n0100\n256\n0 255 0\n252 252 252\n232 232 232\n216 216 216\n196 196 196\n176 176 176\n160 160 160\n140 140 140\n124 124 124\n104 104 104\n88 88 88\n68 68 68\n52 52 52\n32 32 32\n12 12 12\n0 0 0\n252 208 0\n236 180 0\n224 160 0\n208 136 0\n196 116 0\n180 96 0\n168 80 0\n152 64 0\n140 52 0\n124 36 0\n112 28 0\n96 16 0\n84 8 0\n72 4 0\n56 0 0\n44 0 0\n252 120 120\n236 104 104\n224 92 92\n208 76 76\n196 68 68\n184 56 56\n168 44 44\n156 36 36\n140 28 28\n128 20 20\n116 12 12\n100 8 8\n88 4 4\n72 0 0\n60 0 0\n48 0 0\n160 224 132\n136 208 116\n116 196 100\n92 184 84\n72 172 72\n60 160 64\n48 144 60\n40 132 56\n28 120 56\n20 108 52\n16 96 48\n8 80 44\n4 68 40\n0 56 36\n0 44 28\n0 32 24\n208 228 96\n184 212 84\n164 196 72\n144 184 60\n124 168 48\n104 156 40\n88 140 32\n72 124 24\n56 112 20\n40 96 12\n28 84 8\n16 68 4\n8 52 0\n4 40 0\n0 24 0\n0 12 0\n248 248 248\n232 224 224\n220 208 204\n204 188 184\n192 172 168\n176 156 148\n164 140 132\n148 124 116\n136 108 100\n120 92 88\n108 80 72\n92 68 60\n80 56 48\n68 44 40\n52 32 28\n40 24 20\n240 196 72\n224 176 64\n212 156 52\n200 136 48\n188 120 40\n176 104 32\n160 84 24\n148 72 20\n136 56 16\n124 44 12\n112 32 8\n96 20 4\n84 12 4\n72 4 0\n60 0 0\n48 0 0\n140 176 200\n128 160 188\n112 144 176\n104 128 164\n92 112 152\n80 100 144\n72 84 132\n60 72 120\n52 60 108\n44 48 96\n36 36 88\n32 28 76\n28 24 64\n24 16 52\n20 12 40\n16 8 32\n168 208 240\n148 188 224\n128 172 212\n112 152 200\n96 136 188\n80 120 172\n64 104 160\n52 88 148\n40 72 132\n28 60 120\n20 48 108\n12 36 96\n8 24 80\n4 16 68\n0 8 56\n0 4 44\n252 252 120\n236 228 104\n224 204 92\n208 184 76\n196 160 68\n184 140 56\n168 120 44\n156 100 36\n140 80 28\n128 64 20\n116 48 12\n100 32 8\n88 20 4\n72 8 0\n60 4 0\n48 0 0\n184 160 88\n172 144 76\n160 128 64\n148 112 56\n136 96 44\n124 80 36\n112 68 28\n104 56 24\n92 44 16\n80 32 12\n68 20 8\n56 12 4\n44 8 0\n32 4 0\n20 0 0\n12 0 0\n248 220 212\n232 196 192\n220 176 172\n208 152 152\n192 136 140\n180 120 128\n168 104 120\n152 92 108\n140 76 100\n128 64 92\n112 52 84\n100 44 76\n88 32 68\n72 24 60\n60 16 52\n48 12 44\n216 196 252\n200 172 236\n184 148 224\n172 128 208\n160 108 196\n152 92 180\n140 76 168\n132 60 152\n124 48 140\n116 36 124\n108 24 112\n96 16 96\n84 8 80\n72 4 60\n56 0 44\n44 0 32\n64 196 252\n56 172 236\n48 148 224\n40 128 208\n32 108 196\n28 88 184\n24 72 168\n16 52 156\n12 40 140\n8 24 128\n4 16 116\n4 4 100\n4 0 88\n4 0 72\n8 0 60\n8 0 48\n236 236 248\n216 216 232\n196 196 220\n180 180 208\n164 164 192\n148 144 180\n136 132 168\n120 116 152\n108 100 140\n96 88 128\n84 76 112\n72 64 100\n60 52 88\n52 40 72\n40 32 60\n32 24 48\n140 152 148\n132 136 140\n116 124 132\n108 116 124\n92 104 108\n84 92 100\n76 80 92\n56 68 84\n48 56 68\n40 48 56\n32 36 48\n24 28 32\n16 20 24\n8 12 16\n3 4 8\n3 3 6\n"
  },
  {
    "path": "bin/common/Palettes/UFO-JASC-SAFE/PAL_BATTLE_COMMON_SAFE.pal",
    "content": "JASC-PAL\n0100\n256\n0 255 0\n252 252 252\n232 232 232\n216 216 216\n196 196 196\n176 176 176\n160 160 160\n140 140 140\n124 124 124\n104 104 104\n88 88 88\n68 68 68\n52 52 52\n32 32 32\n12 12 12\n0 0 0\n252 208 0\n236 180 0\n224 160 0\n208 136 0\n196 116 0\n180 96 0\n168 80 0\n152 64 0\n140 52 0\n124 36 0\n112 28 0\n96 16 0\n84 8 0\n72 4 0\n56 0 0\n44 0 0\n252 120 120\n236 104 104\n224 92 92\n208 76 76\n196 68 68\n184 56 56\n168 44 44\n156 36 36\n140 28 28\n128 20 20\n116 12 12\n100 8 8\n88 4 4\n72 0 0\n60 0 0\n48 0 0\n160 224 132\n136 208 116\n116 196 100\n92 184 84\n72 172 72\n60 160 64\n48 144 60\n40 132 56\n28 120 56\n20 108 52\n16 96 48\n8 80 44\n4 68 40\n0 56 36\n0 44 28\n0 32 24\n208 228 96\n184 212 84\n164 196 72\n144 184 60\n124 168 48\n104 156 40\n88 140 32\n72 124 24\n56 112 20\n40 96 12\n28 84 8\n16 68 4\n8 52 0\n4 40 0\n0 24 0\n0 12 0\n248 248 248\n232 224 224\n220 208 204\n204 188 184\n192 172 168\n176 156 148\n164 140 132\n148 124 116\n136 108 100\n120 92 88\n108 80 72\n92 68 60\n80 56 48\n68 44 40\n52 32 28\n40 24 20\n240 196 72\n224 176 64\n212 156 52\n200 136 48\n188 120 40\n176 104 32\n160 84 24\n148 72 20\n136 56 16\n124 44 12\n112 32 8\n96 20 4\n84 12 4\n72 4 0\n60 0 0\n48 0 0\n140 176 200\n128 160 188\n112 144 176\n104 128 164\n92 112 152\n80 100 144\n72 84 132\n60 72 120\n52 60 108\n44 48 96\n36 36 88\n32 28 76\n28 24 64\n24 16 52\n20 12 40\n16 8 32\n168 208 240\n148 188 224\n128 172 212\n112 152 200\n96 136 188\n80 120 172\n64 104 160\n52 88 148\n40 72 132\n28 60 120\n20 48 108\n12 36 96\n8 24 80\n4 16 68\n0 8 56\n0 4 44\n252 252 120\n236 228 104\n224 204 92\n208 184 76\n196 160 68\n184 140 56\n168 120 44\n156 100 36\n140 80 28\n128 64 20\n116 48 12\n100 32 8\n88 20 4\n72 8 0\n60 4 0\n48 0 0\n184 160 88\n172 144 76\n160 128 64\n148 112 56\n136 96 44\n124 80 36\n112 68 28\n104 56 24\n92 44 16\n80 32 12\n68 20 8\n56 12 4\n44 8 0\n32 4 0\n20 0 0\n12 0 0\n248 220 212\n232 196 192\n220 176 172\n208 152 152\n192 136 140\n180 120 128\n168 104 120\n152 92 108\n140 76 100\n128 64 92\n112 52 84\n100 44 76\n88 32 68\n72 24 60\n60 16 52\n48 12 44\n216 196 252\n200 172 236\n184 148 224\n172 128 208\n160 108 196\n152 92 180\n140 76 168\n132 60 152\n124 48 140\n116 36 124\n108 24 112\n96 16 96\n84 8 80\n72 4 60\n56 0 44\n44 0 32\n64 196 252\n56 172 236\n48 148 224\n40 128 208\n32 108 196\n28 88 184\n24 72 168\n16 52 156\n12 40 140\n8 24 128\n4 16 116\n4 4 100\n4 0 88\n4 0 72\n8 0 60\n8 0 48\n236 236 248\n216 216 232\n196 196 220\n180 180 208\n164 164 192\n148 144 180\n136 132 168\n120 116 152\n108 100 140\n96 88 128\n84 76 112\n72 64 100\n60 52 88\n52 40 72\n40 32 60\n32 24 48\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n"
  },
  {
    "path": "bin/common/Palettes/UFO-JASC-SAFE/PAL_GEOSCAPE_SAFE.pal",
    "content": "JASC-PAL\n0100\n256\n0 255 0\n252 164 212\n192 112 152\n252 128 0\n192 92 0\n252 252 252\n192 192 192\n0 252 0\n0 192 0\n0 252 252\n0 192 192\n252 252 0\n192 192 0\n252 0 0\n192 0 0\n0 0 0\n0 128 44\n0 120 40\n0 116 36\n0 108 36\n0 104 32\n0 100 32\n0 92 28\n0 88 28\n0 80 24\n0 76 24\n0 72 20\n0 64 20\n0 60 16\n0 52 16\n0 48 12\n0 44 12\n116 156 44\n100 148 36\n88 140 32\n76 132 28\n60 124 24\n52 116 20\n40 108 16\n28 104 12\n20 96 8\n12 88 4\n4 80 4\n4 72 4\n0 64 8\n0 56 8\n0 48 8\n0 44 12\n172 164 0\n160 152 0\n152 144 0\n144 136 0\n136 124 0\n124 116 0\n116 108 0\n108 100 0\n96 88 0\n88 80 0\n80 72 0\n72 64 0\n60 56 0\n52 48 0\n44 40 0\n36 32 0\n148 164 48\n136 152 44\n128 144 40\n120 136 36\n112 128 32\n100 120 28\n92 108 28\n84 100 24\n76 92 20\n68 84 16\n60 76 16\n52 64 12\n44 56 8\n36 48 8\n32 40 4\n24 32 4\n124 244 216\n112 228 220\n104 196 208\n92 164 192\n84 132 176\n72 104 160\n64 80 144\n56 56 128\n56 48 112\n56 40 96\n216 252 0\n160 212 0\n116 172 0\n76 132 0\n44 92 0\n20 56 0\n204 188 204\n184 168 184\n168 152 168\n148 132 152\n132 116 136\n116 100 120\n96 84 100\n80 68 84\n64 52 68\n48 40 52\n28 72 116\n216 252 0\n188 232 0\n160 212 0\n136 196 0\n116 176 0\n96 160 0\n88 152 0\n80 144 0\n76 136 0\n68 132 0\n64 124 0\n60 116 0\n52 108 0\n48 104 0\n44 96 0\n40 88 0\n36 84 0\n32 76 0\n28 68 0\n24 60 0\n20 56 0\n252 0 0\n252 0 0\n252 0 0\n252 0 0\n252 0 0\n252 0 0\n100 204 188\n60 164 144\n28 128 100\n8 88 64\n0 52 32\n168 188 80\n128 152 56\n96 120 40\n64 84 24\n36 52 12\n176 148 68\n168 140 68\n160 132 68\n148 124 68\n140 116 68\n128 108 64\n120 100 64\n108 92 60\n100 84 56\n88 76 52\n80 68 48\n68 60 44\n60 52 40\n52 44 36\n40 36 28\n32 28 24\n152 176 176\n144 168 168\n136 160 160\n128 148 148\n120 140 140\n112 128 128\n104 120 120\n96 108 108\n84 100 100\n76 88 88\n68 80 80\n60 68 68\n52 60 60\n44 52 52\n36 40 40\n28 32 32\n112 48 132\n104 44 120\n96 40 112\n88 36 104\n80 32 96\n72 28 84\n64 24 76\n56 24 68\n48 20 60\n40 16 48\n32 12 40\n28 8 32\n20 4 24\n12 4 12\n4 0 4\n0 0 0\n0 36 116\n0 32 112\n0 32 112\n0 32 108\n0 32 108\n0 32 104\n0 32 104\n0 28 100\n0 28 100\n0 28 96\n0 28 96\n0 28 92\n0 28 92\n0 28 88\n0 24 88\n0 24 84\n0 24 84\n0 24 80\n0 24 80\n0 24 76\n0 20 76\n0 20 72\n0 20 72\n0 20 68\n0 20 68\n0 20 68\n0 16 64\n0 16 64\n0 16 60\n0 16 60\n0 16 56\n0 16 56\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n255 0 255\n64 176 108\n52 140 84\n40 108 64\n28 76 44\n16 44 24\n128 188 228\n104 160 204\n88 136 184\n68 112 164\n52 92 140\n40 68 120\n28 52 100\n252 252 164\n220 232 140\n192 212 120\n164 192 104\n"
  },
  {
    "path": "bin/common/Palettes/UFO-JASC-SAFE/PAL_GRAPHS_SAFE.pal",
    "content": "JASC-PAL\n0100\n256\n0 255 0\n252 252 252\n236 236 236\n216 216 216\n200 200 200\n184 184 184\n168 168 168\n152 152 152\n136 136 136\n120 120 120\n104 104 104\n88 88 88\n72 72 72\n56 56 56\n40 40 40\n24 24 24\n252 252 0\n216 208 0\n180 168 0\n144 128 0\n108 92 0\n72 60 0\n96 84 0\n72 60 0\n252 0 0\n212 0 0\n176 0 0\n136 0 0\n100 0 0\n64 0 0\n88 0 0\n64 0 0\n0 252 0\n0 212 0\n0 176 0\n0 136 0\n0 100 0\n0 64 0\n0 88 0\n0 64 0\n0 124 252\n0 100 208\n0 76 168\n0 52 124\n0 32 84\n0 16 44\n0 28 72\n0 16 44\n0 252 252\n0 212 212\n0 172 172\n0 132 132\n0 92 92\n0 56 56\n0 84 84\n0 56 56\n252 132 208\n208 96 164\n164 68 128\n120 44 88\n76 24 56\n36 8 24\n64 20 44\n36 8 24\n252 112 0\n212 84 0\n172 56 0\n132 36 0\n92 20 0\n52 8 0\n80 16 0\n52 8 0\n252 172 88\n216 144 72\n184 120 56\n152 96 44\n120 72 28\n88 52 20\n108 64 28\n88 52 20\n184 120 252\n152 92 220\n124 68 188\n96 44 156\n72 28 124\n52 16 92\n68 24 112\n52 16 92\n132 184 196\n104 152 164\n80 120 136\n56 88 104\n36 60 76\n20 36 48\n32 52 68\n20 36 48\n252 252 252\n216 216 216\n180 180 180\n144 144 144\n108 108 108\n76 76 76\n100 100 100\n76 76 76\n24 220 140\n20 184 112\n16 148 84\n12 112 60\n8 76 40\n4 44 20\n8 68 32\n4 44 20\n224 128 100\n188 96 72\n152 64 48\n116 40 28\n80 20 12\n48 8 4\n72 16 8\n48 8 4\n200 168 200\n164 132 164\n128 100 128\n92 68 92\n56 40 56\n24 16 24\n48 32 48\n24 16 24\n192 164 68\n160 132 48\n128 104 36\n100 76 20\n68 52 12\n40 28 4\n60 44 8\n40 28 4\n252 148 148\n208 112 112\n164 80 80\n124 52 52\n80 32 32\n40 12 12\n68 24 24\n40 12 12\n208 32 128\n172 20 104\n136 8 84\n104 4 60\n68 0 40\n36 0 20\n60 0 32\n36 0 20\n160 160 160\n128 128 128\n96 96 96\n68 68 68\n36 36 36\n8 8 8\n28 28 28\n8 8 8\n0 68 0\n0 56 0\n0 44 0\n0 32 0\n0 24 0\n96 96 96\n96 96 96\n96 96 96\n96 96 96\n96 96 96\n96 96 96\n96 96 96\n96 96 96\n96 96 96\n96 96 96\n96 96 96\n136 244 224\n120 228 208\n108 216 192\n96 200 176\n80 188 160\n72 172 148\n60 160 132\n52 148 120\n0 76 160\n0 64 144\n0 56 132\n0 48 120\n0 40 104\n0 32 92\n0 24 80\n0 20 68\n60 156 188\n44 124 168\n32 92 148\n20 68 128\n12 44 108\n4 24 88\n0 4 68\n0 0 52\n52 112 44\n40 100 32\n28 92 24\n20 84 16\n12 76 8\n4 68 4\n0 60 0\n0 52 0\n0 76 192\n0 72 184\n0 68 180\n0 68 172\n0 64 168\n0 64 160\n0 60 156\n0 56 148\n0 56 144\n0 52 136\n0 52 132\n0 48 124\n0 44 120\n0 44 116\n0 40 108\n0 40 104\n12 76 8\n8 72 4\n8 68 4\n4 64 4\n4 60 4\n4 56 4\n4 52 0\n4 48 0\n0 44 0\n0 40 0\n0 36 0\n0 32 0\n0 28 0\n0 24 0\n0 20 0\n0 16 0\n0 20 68\n8 44 100\n28 76 136\n60 116 168\n96 156 204\n144 204 240\n96 96 96\n96 96 96\n96 96 96\n96 96 96\n96 96 96\n96 96 96\n252 252 164\n220 232 140\n192 212 120\n164 192 104\n"
  },
  {
    "path": "bin/common/Palettes/UFO-JASC-SAFE/PAL_UFOPAEDIA_SAFE.pal",
    "content": "JASC-PAL\n0100\n256\n0 255 0\n252 252 228\n252 248 216\n252 248 204\n252 244 192\n252 240 184\n252 236 172\n252 228 160\n252 220 152\n252 216 140\n252 208 128\n252 196 116\n252 188 108\n252 176 96\n252 164 84\n252 152 76\n252 232 0\n248 212 0\n244 200 0\n244 184 0\n240 168 0\n236 152 0\n236 136 0\n232 124 0\n228 108 0\n228 96 0\n216 84 0\n204 72 0\n192 60 0\n180 48 0\n168 40 0\n156 32 0\n252 252 236\n244 244 228\n236 236 220\n228 232 216\n216 224 208\n212 220 200\n200 212 196\n192 204 188\n184 200 180\n176 192 176\n168 184 168\n164 180 164\n156 172 160\n152 168 156\n144 160 152\n136 152 144\n132 148 140\n124 140 136\n120 136 132\n112 128 124\n108 120 120\n100 116 116\n96 108 108\n88 100 104\n84 92 96\n76 84 88\n72 76 84\n64 72 76\n60 64 68\n56 56 64\n48 48 56\n44 44 52\n236 252 124\n212 236 108\n192 224 96\n172 212 80\n152 200 68\n132 188 60\n112 172 48\n96 160 40\n80 148 32\n64 136 24\n48 124 16\n32 108 8\n20 96 4\n12 84 4\n4 72 0\n0 60 0\n236 236 248\n224 224 240\n212 212 232\n204 204 224\n196 192 220\n184 184 212\n176 172 204\n164 160 196\n156 152 188\n148 144 184\n140 132 176\n136 128 168\n128 116 164\n120 108 156\n112 104 148\n108 96 144\n104 92 136\n96 84 132\n88 76 124\n84 68 116\n80 64 108\n72 56 104\n68 52 96\n64 48 88\n56 40 84\n52 36 76\n48 32 68\n40 28 60\n36 24 56\n32 20 48\n28 16 40\n24 12 36\n252 208 252\n240 192 240\n232 176 232\n224 160 224\n212 144 216\n204 132 208\n196 120 196\n184 108 188\n176 96 180\n168 84 172\n156 72 164\n148 64 152\n140 56 144\n128 48 136\n120 40 128\n112 32 120\n204 236 252\n192 224 244\n180 216 240\n168 208 232\n156 200 228\n148 192 220\n136 180 216\n128 172 208\n116 164 204\n108 156 196\n96 148 192\n92 140 184\n84 132 180\n76 124 172\n68 116 168\n60 108 160\n56 100 156\n48 92 148\n44 88 144\n40 80 136\n32 72 132\n28 68 128\n24 60 120\n20 56 116\n16 52 112\n12 44 104\n8 40 100\n4 36 92\n4 32 88\n0 28 84\n0 24 76\n0 20 72\n248 220 212\n232 196 192\n220 176 172\n208 152 152\n192 136 140\n180 120 128\n168 104 120\n152 92 108\n140 76 100\n128 64 92\n112 52 84\n100 44 76\n88 32 68\n72 24 60\n60 16 52\n48 12 44\n252 228 184\n244 216 172\n240 208 160\n232 200 148\n228 192 140\n224 184 128\n216 176 116\n212 164 108\n204 156 100\n200 148 88\n196 140 80\n188 132 72\n184 124 64\n176 116 56\n172 108 52\n168 100 44\n212 180 108\n200 168 100\n192 156 92\n184 144 88\n172 132 80\n164 124 72\n156 112 68\n144 104 64\n136 92 56\n128 84 52\n116 76 48\n108 64 40\n100 56 36\n88 48 32\n80 40 28\n72 36 24\n164 56 0\n148 40 0\n136 32 0\n124 20 0\n108 12 0\n96 4 0\n84 0 0\n72 0 0\n204 248 192\n168 224 156\n132 204 120\n104 184 92\n76 160 64\n48 140 44\n28 120 24\n12 100 12\n244 220 204\n232 204 188\n220 192 172\n208 176 156\n200 164 144\n188 152 132\n176 140 116\n164 128 104\n156 116 96\n144 104 84\n132 96 72\n124 84 64\n112 76 56\n100 64 44\n88 56 36\n80 48 32\n156 148 188\n124 120 148\n92 92 108\n60 60 68\n28 28 32\n140 204 184\n104 164 152\n72 124 120\n44 80 84\n20 40 44\n252 0 252\n252 0 252\n252 252 164\n220 232 140\n192 212 120\n164 192 104\n"
  },
  {
    "path": "bin/common/Shaders/5xBR_Rounded.OpenGL.shader",
    "content": "# <!--\n   # Hyllian's 5xBR v3.7a Shader\n\n   # Copyright (C) 2011, 2012 Hyllian/Jararaca - sergiogdb@gmail.com\n   # Copyright (C) 2012 crazy46guy (GLSL conversion)\n\n   # This program is free software; you can redistribute it and/or\n   # modify it under the terms of the GNU General Public License\n   # as published by the Free Software Foundation; either version 2\n   # of the License, or (at your option) any later version.\n\n   # This program is distributed in the hope that it will be useful,\n   # but WITHOUT ANY WARRANTY; without even the implied warranty of\n   # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n   # GNU General Public License for more details.\n\n   # You should have received a copy of the GNU General Public License\n   # along with this program; if not, write to the Free Software\n   # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n\n   # (The original Cg version of the xBR family of shaders is available on\n   # Github: https://github.com/twinaphex/common-shaders/tree/master/xBR )\n# -->\nlanguage: \"GLSL\"\nvertex: |\n    uniform vec2 rubyTextureSize;\n\n    void main() {\n      float dx = 1.0 / rubyTextureSize.x;\n      float dy = 1.0 / rubyTextureSize.y;\n\n      //     A1 B1 C1\n      //  A0  A  B  C C4\n      //  D0  D  E  F F4\n      //  G0  G  H  I I4\n      //     G5 H5 I5\n\n      gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n      gl_TexCoord[0] = gl_MultiTexCoord0;\n      gl_TexCoord[1] = gl_MultiTexCoord0.xxxy + vec4(    -dx,   0,  dx, -2.0*dy);  //  A1 B1 C1\n      gl_TexCoord[2] = gl_MultiTexCoord0.xxxy + vec4(    -dx,   0,  dx,     -dy);  //   A  B  C\n      gl_TexCoord[3] = gl_MultiTexCoord0.xxxy + vec4(    -dx,   0,  dx,       0);  //   D  E  F\n      gl_TexCoord[4] = gl_MultiTexCoord0.xxxy + vec4(    -dx,   0,  dx,      dy);  //   G  H  I\n      gl_TexCoord[5] = gl_MultiTexCoord0.xxxy + vec4(    -dx,   0,  dx,  2.0*dy);  //  G5 H5 I5\n      gl_TexCoord[6] = gl_MultiTexCoord0.xyyy + vec4(-2.0*dx, -dy,   0,      dy);  //  A0 D0 G0\n      gl_TexCoord[7] = gl_MultiTexCoord0.xyyy + vec4( 2.0*dx, -dy,   0,      dy);  //  C4 F4 I4\n    }\nfragment: |\n    uniform sampler2D rubyTexture;\n    uniform vec2 rubyTextureSize;\n\n    const float coef = 2.0;\n\n    const float y_weight = 48.0;\n    const float u_weight = 7.0;\n    const float v_weight = 6.0;\n\n    const mat3 yuv = mat3(0.299, 0.587, 0.114, -0.169, -0.331, 0.499, 0.499, -0.418, -0.0813);\n    const mat3 yuv_weighted = mat3(y_weight * yuv[0], u_weight * yuv[1], v_weight * yuv[2]);\n\n    vec4 RGBtoYUV(vec3 v0, vec3 v1, vec3 v2, vec3 v3) {\n      float a = yuv_weighted[0].x * v0.x + yuv_weighted[0].y * v0.y + yuv_weighted[0].z * v0.z;\n      float b = yuv_weighted[0].x * v1.x + yuv_weighted[0].y * v1.y + yuv_weighted[0].z * v1.z;\n      float c = yuv_weighted[0].x * v2.x + yuv_weighted[0].y * v2.y + yuv_weighted[0].z * v2.z;\n      float d = yuv_weighted[0].x * v3.x + yuv_weighted[0].y * v3.y + yuv_weighted[0].z * v3.z;\n\n      return vec4(a, b, c, d);\n    }\n\n    bvec4 _and_(bvec4 A, bvec4 B) {\n      return bvec4(A.x && B.x, A.y && B.y, A.z && B.z, A.w && B.w);\n    }\n\n    bvec4 _or_(bvec4 A, bvec4 B) {\n      return bvec4(A.x || B.x, A.y || B.y, A.z || B.z, A.w || B.w);\n    }\n\n    vec4 df(vec4 A, vec4 B) {\n      return vec4(abs(A - B));\n    }\n\n    vec4 weighted_distance(vec4 a, vec4 b, vec4 c, vec4 d, vec4 e, vec4 f, vec4 g, vec4 h) {\n      return (df(a, b) + df(a, c) + df(d, e) + df(d, f) + 4.0 * df(g, h));\n    }\n\n    void main() {\n      vec2 fp = fract(gl_TexCoord[0].xy * rubyTextureSize);\n\n      vec3 A1 = texture2D(rubyTexture, gl_TexCoord[1].xw).rgb;\n      vec3 B1 = texture2D(rubyTexture, gl_TexCoord[1].yw).rgb;\n      vec3 C1 = texture2D(rubyTexture, gl_TexCoord[1].zw).rgb;\n\n      vec3 A  = texture2D(rubyTexture, gl_TexCoord[2].xw).rgb;\n      vec3 B  = texture2D(rubyTexture, gl_TexCoord[2].yw).rgb;\n      vec3 C  = texture2D(rubyTexture, gl_TexCoord[2].zw).rgb;\n\n      vec3 D  = texture2D(rubyTexture, gl_TexCoord[3].xw).rgb;\n      vec3 E  = texture2D(rubyTexture, gl_TexCoord[3].yw).rgb;\n      vec3 F  = texture2D(rubyTexture, gl_TexCoord[3].zw).rgb;\n\n      vec3 G  = texture2D(rubyTexture, gl_TexCoord[4].xw).rgb;\n      vec3 H  = texture2D(rubyTexture, gl_TexCoord[4].yw).rgb;\n      vec3 I  = texture2D(rubyTexture, gl_TexCoord[4].zw).rgb;\n\n      vec3 G5 = texture2D(rubyTexture, gl_TexCoord[5].xw).rgb;\n      vec3 H5 = texture2D(rubyTexture, gl_TexCoord[5].yw).rgb;\n      vec3 I5 = texture2D(rubyTexture, gl_TexCoord[5].zw).rgb;\n\n      vec3 A0 = texture2D(rubyTexture, gl_TexCoord[6].xy).rgb;\n      vec3 D0 = texture2D(rubyTexture, gl_TexCoord[6].xz).rgb;\n      vec3 G0 = texture2D(rubyTexture, gl_TexCoord[6].xw).rgb;\n\n      vec3 C4 = texture2D(rubyTexture, gl_TexCoord[7].xy).rgb;\n      vec3 F4 = texture2D(rubyTexture, gl_TexCoord[7].xz).rgb;\n      vec3 I4 = texture2D(rubyTexture, gl_TexCoord[7].xw).rgb;\n\n      vec4 b = RGBtoYUV(B, D, H, F);\n      vec4 c = RGBtoYUV(C, A, G, I);\n      vec4 e = RGBtoYUV(E, E, E, E);\n      vec4 d = b.yzwx;\n      vec4 f = b.wxyz;\n      vec4 g = c.zwxy;\n      vec4 h = b.zwxy;\n      vec4 i = c.wxyz;\n\n      vec4 i4 = RGBtoYUV(I4, C1, A0, G5);\n      vec4 i5 = RGBtoYUV(I5, C4, A1, G0);\n      vec4 h5 = RGBtoYUV(H5, F4, B1, D0);\n      vec4 f4 = h5.yzwx;\n\n      vec4 Ao = vec4( 1.0, -1.0, -1.0,  1.0 );\n      vec4 Bo = vec4( 1.0,  1.0, -1.0, -1.0 );\n      vec4 Co = vec4( 1.5,  0.5, -0.5,  0.5 );\n      vec4 Ax = vec4( 1.0, -1.0, -1.0,  1.0 );\n      vec4 Bx = vec4( 0.5,  2.0, -0.5, -2.0 );\n      vec4 Cx = vec4( 1.0,  1.0, -0.5,  0.0 );\n      vec4 Ay = vec4( 1.0, -1.0, -1.0,  1.0 );\n      vec4 By = vec4( 2.0,  0.5, -2.0, -0.5 );\n      vec4 Cy = vec4( 2.0,  0.0, -1.0,  0.5 );\n\n      // These inequations define the line below which interpolation occurs\n      bvec4 fx      = greaterThan(Ao * fp.y + Bo * fp.x, Co);\n      bvec4 fx_left = greaterThan(Ax * fp.y + Bx * fp.x, Cx);\n      bvec4 fx_up   = greaterThan(Ay * fp.y + By * fp.x, Cy);\n\n      bvec4 interp_restriction_lv1      = _and_( notEqual(e, f), notEqual(e, h) );\n      bvec4 interp_restriction_lv2_left = _and_( notEqual(e, g), notEqual(d, g) );\n      bvec4 interp_restriction_lv2_up   = _and_( notEqual(e, c), notEqual(b, c) );\n\n      bvec4 edr      = _and_( lessThan(weighted_distance(e, c, g, i, h5, f4, h, f),\n                                       weighted_distance(h, d, i5, f, i4, b, e, i)), interp_restriction_lv1 );\n      bvec4 edr_left = _and_( lessThanEqual(coef * df(f, g), df(h, c)), interp_restriction_lv2_left );\n      bvec4 edr_up   = _and_( greaterThanEqual(df(f, g), coef * df(h, c)), interp_restriction_lv2_up );\n\n      bvec4 nc = _and_( edr, _or_( _or_( fx, _and_(edr_left, fx_left) ), _and_(edr_up, fx_up) ) );\n\n      bvec4 px = lessThanEqual(df(e, f), df(e, h));\n\n      vec3 res = nc.x ? px.x ? F : H : nc.y ? px.y ? B : F : nc.z ? px.z ? D : B : nc.w ? px.w ? H : D : E;\n\n      gl_FragColor.rgb = res;\n      gl_FragColor.a = 1.0;\n    }\nlinear: false"
  },
  {
    "path": "bin/common/Shaders/5xBR_Semi-Rounded.OpenGL.shader",
    "content": "# <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n# <!--\n    # Hyllian's 5xBR v3.7b (semi-rounded) Shader\n\n   # Copyright (C) 2011, 2012 Hyllian/Jararaca - sergiogdb@gmail.com\n   # Copyright (C) 2012 crazy46guy (GLSL conversion)\n\n   # This program is free software; you can redistribute it and/or\n   # modify it under the terms of the GNU General Public License\n   # as published by the Free Software Foundation; either version 2\n   # of the License, or (at your option) any later version.\n\n   # This program is distributed in the hope that it will be useful,\n   # but WITHOUT ANY WARRANTY; without even the implied warranty of\n   # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n   # GNU General Public License for more details.\n\n   # You should have received a copy of the GNU General Public License\n   # along with this program; if not, write to the Free Software\n   # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n\n   # (The original Cg version of the xBR family of shaders is available on\n   # Github: https://github.com/twinaphex/common-shaders/tree/master/xBR )\n# -->\nlanguage: \"GLSL\"\nvertex: |\n    uniform vec2 rubyTextureSize;\n\n    void main() {\n      float dx = 1.0 / rubyTextureSize.x;\n      float dy = 1.0 / rubyTextureSize.y;\n\n      //     A1 B1 C1\n      //  A0  A  B  C C4\n      //  D0  D  E  F F4\n      //  G0  G  H  I I4\n      //     G5 H5 I5\n\n      gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n      gl_TexCoord[0] = gl_MultiTexCoord0;\n      gl_TexCoord[1] = gl_MultiTexCoord0.xxxy + vec4(    -dx,   0,  dx, -2.0*dy);  //  A1 B1 C1\n      gl_TexCoord[2] = gl_MultiTexCoord0.xxxy + vec4(    -dx,   0,  dx,     -dy);  //   A  B  C\n      gl_TexCoord[3] = gl_MultiTexCoord0.xxxy + vec4(    -dx,   0,  dx,       0);  //   D  E  F\n      gl_TexCoord[4] = gl_MultiTexCoord0.xxxy + vec4(    -dx,   0,  dx,      dy);  //   G  H  I\n      gl_TexCoord[5] = gl_MultiTexCoord0.xxxy + vec4(    -dx,   0,  dx,  2.0*dy);  //  G5 H5 I5\n      gl_TexCoord[6] = gl_MultiTexCoord0.xyyy + vec4(-2.0*dx, -dy,   0,      dy);  //  A0 D0 G0\n      gl_TexCoord[7] = gl_MultiTexCoord0.xyyy + vec4( 2.0*dx, -dy,   0,      dy);  //  C4 F4 I4\n    }\nfragment: |\n    uniform sampler2D rubyTexture;\n    uniform vec2 rubyTextureSize;\n\n    const float coef = 2.0;\n\n    const float threshold = 15.0;\n\n    const float y_weight = 48.0;\n    const float u_weight = 7.0;\n    const float v_weight = 6.0;\n\n    const mat3 yuv = mat3(0.299, 0.587, 0.114, -0.169, -0.331, 0.499, 0.499, -0.418, -0.0813);\n    const mat3 yuv_weighted = mat3(y_weight * yuv[0], u_weight * yuv[1], v_weight * yuv[2]);\n\n    vec4 RGBtoYUV(vec3 v0, vec3 v1, vec3 v2, vec3 v3) {\n      float a = yuv_weighted[0].x * v0.x + yuv_weighted[0].y * v0.y + yuv_weighted[0].z * v0.z;\n      float b = yuv_weighted[0].x * v1.x + yuv_weighted[0].y * v1.y + yuv_weighted[0].z * v1.z;\n      float c = yuv_weighted[0].x * v2.x + yuv_weighted[0].y * v2.y + yuv_weighted[0].z * v2.z;\n      float d = yuv_weighted[0].x * v3.x + yuv_weighted[0].y * v3.y + yuv_weighted[0].z * v3.z;\n\n      return vec4(a, b, c, d);\n    }\n\n    bvec4 _and_(bvec4 A, bvec4 B) {\n      return bvec4(A.x && B.x, A.y && B.y, A.z && B.z, A.w && B.w);\n    }\n\n    bvec4 _or_(bvec4 A, bvec4 B) {\n      return bvec4(A.x || B.x, A.y || B.y, A.z || B.z, A.w || B.w);\n    }\n\n    vec4 df(vec4 A, vec4 B) {\n      return vec4(abs(A - B));\n    }\n\n    bvec4 close(vec4 A, vec4 B) {\n      return (lessThan(df(A, B), vec4(threshold)));\n    }\n\n    vec4 weighted_distance(vec4 a, vec4 b, vec4 c, vec4 d, vec4 e, vec4 f, vec4 g, vec4 h) {\n      return (df(a, b) + df(a, c) + df(d, e) + df(d, f) + 4.0 * df(g, h));\n    }\n\n    void main() {\n      vec2 fp = fract(gl_TexCoord[0].xy * rubyTextureSize);\n\n      vec3 A1 = texture2D(rubyTexture, gl_TexCoord[1].xw).rgb;\n      vec3 B1 = texture2D(rubyTexture, gl_TexCoord[1].yw).rgb;\n      vec3 C1 = texture2D(rubyTexture, gl_TexCoord[1].zw).rgb;\n\n      vec3 A  = texture2D(rubyTexture, gl_TexCoord[2].xw).rgb;\n      vec3 B  = texture2D(rubyTexture, gl_TexCoord[2].yw).rgb;\n      vec3 C  = texture2D(rubyTexture, gl_TexCoord[2].zw).rgb;\n\n      vec3 D  = texture2D(rubyTexture, gl_TexCoord[3].xw).rgb;\n      vec3 E  = texture2D(rubyTexture, gl_TexCoord[3].yw).rgb;\n      vec3 F  = texture2D(rubyTexture, gl_TexCoord[3].zw).rgb;\n\n      vec3 G  = texture2D(rubyTexture, gl_TexCoord[4].xw).rgb;\n      vec3 H  = texture2D(rubyTexture, gl_TexCoord[4].yw).rgb;\n      vec3 I  = texture2D(rubyTexture, gl_TexCoord[4].zw).rgb;\n\n      vec3 G5 = texture2D(rubyTexture, gl_TexCoord[5].xw).rgb;\n      vec3 H5 = texture2D(rubyTexture, gl_TexCoord[5].yw).rgb;\n      vec3 I5 = texture2D(rubyTexture, gl_TexCoord[5].zw).rgb;\n\n      vec3 A0 = texture2D(rubyTexture, gl_TexCoord[6].xy).rgb;\n      vec3 D0 = texture2D(rubyTexture, gl_TexCoord[6].xz).rgb;\n      vec3 G0 = texture2D(rubyTexture, gl_TexCoord[6].xw).rgb;\n\n      vec3 C4 = texture2D(rubyTexture, gl_TexCoord[7].xy).rgb;\n      vec3 F4 = texture2D(rubyTexture, gl_TexCoord[7].xz).rgb;\n      vec3 I4 = texture2D(rubyTexture, gl_TexCoord[7].xw).rgb;\n\n      vec4 b = RGBtoYUV(B, D, H, F);\n      vec4 c = RGBtoYUV(C, A, G, I);\n      vec4 e = RGBtoYUV(E, E, E, E);\n      vec4 d = b.yzwx;\n      vec4 f = b.wxyz;\n      vec4 g = c.zwxy;\n      vec4 h = b.zwxy;\n      vec4 i = c.wxyz;\n\n      vec4 i4 = RGBtoYUV(I4, C1, A0, G5);\n      vec4 i5 = RGBtoYUV(I5, C4, A1, G0);\n      vec4 h5 = RGBtoYUV(H5, F4, B1, D0);\n      vec4 f4 = h5.yzwx;\n\n      vec4 Ao = vec4( 1.0, -1.0, -1.0,  1.0 );\n      vec4 Bo = vec4( 1.0,  1.0, -1.0, -1.0 );\n      vec4 Co = vec4( 1.5,  0.5, -0.5,  0.5 );\n      vec4 Ax = vec4( 1.0, -1.0, -1.0,  1.0 );\n      vec4 Bx = vec4( 0.5,  2.0, -0.5, -2.0 );\n      vec4 Cx = vec4( 1.0,  1.0, -0.5,  0.0 );\n      vec4 Ay = vec4( 1.0, -1.0, -1.0,  1.0 );\n      vec4 By = vec4( 2.0,  0.5, -2.0, -0.5 );\n      vec4 Cy = vec4( 2.0,  0.0, -1.0,  0.5 );\n\n      // These inequations define the line below which interpolation occurs\n      bvec4 fx      = greaterThan(Ao * fp.y + Bo * fp.x, Co);\n      bvec4 fx_left = greaterThan(Ax * fp.y + Bx * fp.x, Cx);\n      bvec4 fx_up   = greaterThan(Ay * fp.y + By * fp.x, Cy);\n\n      bvec4 t1 = _and_( notEqual(e, f), notEqual(e, h) );\n      bvec4 t2 = _and_( not(close(f, b)), not(close(h, d)) );\n      bvec4 t3 = _and_( _and_( close(e, i), not(close(f, i4)) ), not(close(h, i5)) );\n      bvec4 t4 = _or_( close(e, g), close(e, c) );\n      bvec4 interp_restriction_lv1 = _and_( t1, _or_( _or_(t2, t3), t4 ) );\n\n      bvec4 interp_restriction_lv2_left = _and_( notEqual(e, g), notEqual(d, g) );\n      bvec4 interp_restriction_lv2_up   = _and_( notEqual(e, c), notEqual(b, c) );\n\n      bvec4 edr      = _and_( lessThan(weighted_distance(e, c, g, i, h5, f4, h, f),\n                                       weighted_distance(h, d, i5, f, i4, b, e, i)), interp_restriction_lv1 );\n      bvec4 edr_left = _and_( lessThanEqual(coef * df(f, g), df(h, c)), interp_restriction_lv2_left );\n      bvec4 edr_up   = _and_( greaterThanEqual(df(f, g), coef * df(h, c)), interp_restriction_lv2_up );\n\n      bvec4 nc = _and_( edr, _or_( _or_( fx, _and_(edr_left, fx_left) ), _and_(edr_up, fx_up) ) );\n\n      bvec4 px = lessThanEqual(df(e, f), df(e, h));\n\n      vec3 res = nc.x ? px.x ? F : H : nc.y ? px.y ? B : F : nc.z ? px.z ? D : B : nc.w ? px.w ? H : D : E;\n\n      gl_FragColor.rgb = res;\n      gl_FragColor.a = 1.0;\n    }\nlinear: false"
  },
  {
    "path": "bin/common/Shaders/5xBR_Squared.OpenGL.shader",
    "content": "# <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n# <!--\n    # Hyllian's 5xBR v3.7c (squared) Shader\n\n   # Copyright (C) 2011, 2012 Hyllian/Jararaca - sergiogdb@gmail.com\n   # Copyright (C) 2012 crazy46guy (GLSL conversion)\n\n   # This program is free software; you can redistribute it and/or\n   # modify it under the terms of the GNU General Public License\n   # as published by the Free Software Foundation; either version 2\n   # of the License, or (at your option) any later version.\n\n   # This program is distributed in the hope that it will be useful,\n   # but WITHOUT ANY WARRANTY; without even the implied warranty of\n   # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n   # GNU General Public License for more details.\n\n   # You should have received a copy of the GNU General Public License\n   # along with this program; if not, write to the Free Software\n   # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n\n   # (The original Cg version of the xBR family of shaders is available on\n   # Github: https://github.com/twinaphex/common-shaders/tree/master/xBR )\n# -->\nlanguage: \"GLSL\"\nvertex: |\n    uniform vec2 rubyTextureSize;\n\n    void main() {\n      float dx = 1.0 / rubyTextureSize.x;\n      float dy = 1.0 / rubyTextureSize.y;\n\n      //     A1 B1 C1\n      //  A0  A  B  C C4\n      //  D0  D  E  F F4\n      //  G0  G  H  I I4\n      //     G5 H5 I5\n\n      gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n      gl_TexCoord[0] = gl_MultiTexCoord0;\n      gl_TexCoord[1] = gl_MultiTexCoord0.xxxy + vec4(    -dx,   0,  dx, -2.0*dy);  //  A1 B1 C1\n      gl_TexCoord[2] = gl_MultiTexCoord0.xxxy + vec4(    -dx,   0,  dx,     -dy);  //   A  B  C\n      gl_TexCoord[3] = gl_MultiTexCoord0.xxxy + vec4(    -dx,   0,  dx,       0);  //   D  E  F\n      gl_TexCoord[4] = gl_MultiTexCoord0.xxxy + vec4(    -dx,   0,  dx,      dy);  //   G  H  I\n      gl_TexCoord[5] = gl_MultiTexCoord0.xxxy + vec4(    -dx,   0,  dx,  2.0*dy);  //  G5 H5 I5\n      gl_TexCoord[6] = gl_MultiTexCoord0.xyyy + vec4(-2.0*dx, -dy,   0,      dy);  //  A0 D0 G0\n      gl_TexCoord[7] = gl_MultiTexCoord0.xyyy + vec4( 2.0*dx, -dy,   0,      dy);  //  C4 F4 I4\n    }\nfragment: |\n    uniform sampler2D rubyTexture;\n    uniform vec2 rubyTextureSize;\n\n    const float coef = 2.0;\n\n    const float threshold = 15.0;\n\n    const float y_weight = 48.0;\n    const float u_weight = 7.0;\n    const float v_weight = 6.0;\n\n    const mat3 yuv = mat3(0.299, 0.587, 0.114, -0.169, -0.331, 0.499, 0.499, -0.418, -0.0813);\n    const mat3 yuv_weighted = mat3(y_weight * yuv[0], u_weight * yuv[1], v_weight * yuv[2]);\n\n    vec4 RGBtoYUV(vec3 v0, vec3 v1, vec3 v2, vec3 v3) {\n      float a = yuv_weighted[0].x * v0.x + yuv_weighted[0].y * v0.y + yuv_weighted[0].z * v0.z;\n      float b = yuv_weighted[0].x * v1.x + yuv_weighted[0].y * v1.y + yuv_weighted[0].z * v1.z;\n      float c = yuv_weighted[0].x * v2.x + yuv_weighted[0].y * v2.y + yuv_weighted[0].z * v2.z;\n      float d = yuv_weighted[0].x * v3.x + yuv_weighted[0].y * v3.y + yuv_weighted[0].z * v3.z;\n\n      return vec4(a, b, c, d);\n    }\n\n    bvec4 _and_(bvec4 A, bvec4 B) {\n      return bvec4(A.x && B.x, A.y && B.y, A.z && B.z, A.w && B.w);\n    }\n\n    bvec4 _or_(bvec4 A, bvec4 B) {\n      return bvec4(A.x || B.x, A.y || B.y, A.z || B.z, A.w || B.w);\n    }\n\n    vec4 df(vec4 A, vec4 B) {\n      return vec4(abs(A - B));\n    }\n\n    bvec4 close(vec4 A, vec4 B) {\n      return (lessThan(df(A, B), vec4(threshold)));\n    }\n\n    vec4 weighted_distance(vec4 a, vec4 b, vec4 c, vec4 d, vec4 e, vec4 f, vec4 g, vec4 h) {\n      return (df(a, b) + df(a, c) + df(d, e) + df(d, f) + 4.0 * df(g, h));\n    }\n\n    void main() {\n      vec2 fp = fract(gl_TexCoord[0].xy * rubyTextureSize);\n\n      vec3 A1 = texture2D(rubyTexture, gl_TexCoord[1].xw).rgb;\n      vec3 B1 = texture2D(rubyTexture, gl_TexCoord[1].yw).rgb;\n      vec3 C1 = texture2D(rubyTexture, gl_TexCoord[1].zw).rgb;\n\n      vec3 A  = texture2D(rubyTexture, gl_TexCoord[2].xw).rgb;\n      vec3 B  = texture2D(rubyTexture, gl_TexCoord[2].yw).rgb;\n      vec3 C  = texture2D(rubyTexture, gl_TexCoord[2].zw).rgb;\n\n      vec3 D  = texture2D(rubyTexture, gl_TexCoord[3].xw).rgb;\n      vec3 E  = texture2D(rubyTexture, gl_TexCoord[3].yw).rgb;\n      vec3 F  = texture2D(rubyTexture, gl_TexCoord[3].zw).rgb;\n\n      vec3 G  = texture2D(rubyTexture, gl_TexCoord[4].xw).rgb;\n      vec3 H  = texture2D(rubyTexture, gl_TexCoord[4].yw).rgb;\n      vec3 I  = texture2D(rubyTexture, gl_TexCoord[4].zw).rgb;\n\n      vec3 G5 = texture2D(rubyTexture, gl_TexCoord[5].xw).rgb;\n      vec3 H5 = texture2D(rubyTexture, gl_TexCoord[5].yw).rgb;\n      vec3 I5 = texture2D(rubyTexture, gl_TexCoord[5].zw).rgb;\n\n      vec3 A0 = texture2D(rubyTexture, gl_TexCoord[6].xy).rgb;\n      vec3 D0 = texture2D(rubyTexture, gl_TexCoord[6].xz).rgb;\n      vec3 G0 = texture2D(rubyTexture, gl_TexCoord[6].xw).rgb;\n\n      vec3 C4 = texture2D(rubyTexture, gl_TexCoord[7].xy).rgb;\n      vec3 F4 = texture2D(rubyTexture, gl_TexCoord[7].xz).rgb;\n      vec3 I4 = texture2D(rubyTexture, gl_TexCoord[7].xw).rgb;\n\n      vec4 b = RGBtoYUV(B, D, H, F);\n      vec4 c = RGBtoYUV(C, A, G, I);\n      vec4 e = RGBtoYUV(E, E, E, E);\n      vec4 d = b.yzwx;\n      vec4 f = b.wxyz;\n      vec4 g = c.zwxy;\n      vec4 h = b.zwxy;\n      vec4 i = c.wxyz;\n\n      vec4 i4 = RGBtoYUV(I4, C1, A0, G5);\n      vec4 i5 = RGBtoYUV(I5, C4, A1, G0);\n      vec4 h5 = RGBtoYUV(H5, F4, B1, D0);\n      vec4 f4 = h5.yzwx;\n\n      vec4 Ao = vec4( 1.0, -1.0, -1.0,  1.0 );\n      vec4 Bo = vec4( 1.0,  1.0, -1.0, -1.0 );\n      vec4 Co = vec4( 1.5,  0.5, -0.5,  0.5 );\n      vec4 Ax = vec4( 1.0, -1.0, -1.0,  1.0 );\n      vec4 Bx = vec4( 0.5,  2.0, -0.5, -2.0 );\n      vec4 Cx = vec4( 1.0,  1.0, -0.5,  0.0 );\n      vec4 Ay = vec4( 1.0, -1.0, -1.0,  1.0 );\n      vec4 By = vec4( 2.0,  0.5, -2.0, -0.5 );\n      vec4 Cy = vec4( 2.0,  0.0, -1.0,  0.5 );\n\n      // These inequations define the line below which interpolation occurs\n      bvec4 fx      = greaterThan(Ao * fp.y + Bo * fp.x, Co);\n      bvec4 fx_left = greaterThan(Ax * fp.y + Bx * fp.x, Cx);\n      bvec4 fx_up   = greaterThan(Ay * fp.y + By * fp.x, Cy);\n\n      bvec4 t1 = _and_( notEqual(e, f), notEqual(e, h) );\n      bvec4 t2 = _and_( not(close(f, b)), not(close(f, c)) );\n      bvec4 t3 = _and_( not(close(h, d)), not(close(h, g)) );\n      bvec4 t4 = _and_( not(close(f, f4)), not(close(f, i4)) );\n      bvec4 t5 = _and_( not(close(h, h5)), not(close(h, i5)) );\n      bvec4 t6 = _and_( close(e, i), _or_(t4, t5) );\n      bvec4 t7 = _or_( close(e, g), close(e, c) );\n      bvec4 interp_restriction_lv1 = _and_( t1, _or_( _or_( _or_(t2, t3), t6 ), t7 ) );\n\n      bvec4 interp_restriction_lv2_left = _and_( notEqual(e, g), notEqual(d, g) );\n      bvec4 interp_restriction_lv2_up   = _and_( notEqual(e, c), notEqual(b, c) );\n\n      bvec4 edr      = _and_( lessThan(weighted_distance(e, c, g, i, h5, f4, h, f),\n                                       weighted_distance(h, d, i5, f, i4, b, e, i)), interp_restriction_lv1 );\n      bvec4 edr_left = _and_( lessThanEqual(coef * df(f, g), df(h, c)), interp_restriction_lv2_left );\n      bvec4 edr_up   = _and_( greaterThanEqual(df(f, g), coef * df(h, c)), interp_restriction_lv2_up );\n\n      bvec4 nc = _and_( edr, _or_( _or_( fx, _and_(edr_left, fx_left) ), _and_(edr_up, fx_up) ) );\n\n      bvec4 px = lessThanEqual(df(e, f), df(e, h));\n\n      vec3 res = nc.x ? px.x ? F : H : nc.y ? px.y ? B : F : nc.z ? px.z ? D : B : nc.w ? px.w ? H : D : E;\n\n      gl_FragColor.rgb = res;\n      gl_FragColor.a = 1.0;\n    }\nlinear: false"
  },
  {
    "path": "bin/common/Shaders/CRT-Lottes-Warp.OpenGL.shader",
    "content": "#<!--\n# PUBLIC DOMAIN CRT STYLED SCAN-LINE SHADER\n#\n#   by Timothy Lottes\n#\n# This is more along the style of a really good CGA arcade monitor.\n# With RGB inputs instead of NTSC.\n# The shadow mask example has the mask rotated 90 degrees for less chromatic aberration.\n#\n# Left it unoptimized to show the theory behind the algorithm.\n#\n# It is an example what I personally would want as a display option for pixel art games.\n# Please take and use, change, or whatever.\n#\n# Version with screen curvature emulation ('warp')\n# Adapted for OpenXcom by somnolik\n#-->\nlanguage: GLSL\nvertex: |\n        #version 110\n        uniform vec2 rubyOutputSize;\n\n        varying vec2 v_texCoord;\n        varying vec2 screenPixel;\n\n        void main(void)\n        {\n                gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n                v_texCoord = gl_MultiTexCoord0.xy;\n                screenPixel = gl_Position.xy * rubyOutputSize;\n        }\nlinear: false\nfragment: |\n        #version 110\n        uniform sampler2D rubyTexture;\n        uniform vec2 rubyTextureSize;\n        uniform vec2 rubyInputSize;\n\n        varying vec2 v_texCoord;\n        varying vec2 screenPixel;\n\n\n        /*\n        // Shader parameters for RetroArch\n        // Syntax:\n        // #pragma parameter <shortName> <longName> <defaultValue> <min> <max> <step>\n\n        #pragma parameter hardScan \"hardScan\" -8.0 -20.0 0.0 1.0\n        #pragma parameter hardPix \"hardPix\" -3.0 -20.0 0.0 1.0\n\n        #pragma parameter warpX \"warpX\" 0.031 0.0 0.125 0.01\n        #pragma parameter warpY \"warpY\" 0.041 0.0 0.125 0.01\n\n        #pragma parameter maskDark \"maskDark\" 0.5 0.0 2.0 0.1\n        #pragma parameter maskLight \"maskLight\" 1.5 0.0 2.0 0.1\n        #pragma parameter shadowMask \"shadowMask\" 3.0 0.0 4.0 1.0\n        #pragma parameter brightBoost \"brightness boost\" 1.0 0.0 2.0 0.05\n\n        #pragma parameter hardBloomPix \"bloom-x soft\" -1.5 -2.0 -0.5 0.1\n        #pragma parameter hardBloomScan \"bloom-y soft\" -2.0 -4.0 -1.0 0.1\n        #pragma parameter bloomAmount \"bloom ammount\" 0.15 0.0 1.0 0.05\n        #pragma parameter shape \"filter kernel shape\" 2.0 0.0 10.0 0.05\n        */\n\n        #define hardScan -8.0        // decrease for better distinction of scanlines\n        #define hardPix -5.0         // decrease for better distinction of individual pixels\n\n        #define warpX 0.031          // increase for stronger screen curvature\n        #define warpY 0.041          // increase for stronger screen curvature\n\n        #define maskDark 0.8         // > 1 amplifies, < 1 attenuates other color channels: green and blue for a red pixel, etc.\n        #define maskLight 1.5        // > 1 amplifies, < 1 attenuates own color channel: red for a red pixel, etc.\n        #define shadowMask 3.0       // 0 - disable; 1 - TV-style; 2 - Aperture grille; 3 - stretched VGA; 4 - VGA\n        #define brightBoost 1.0      // > 1 amplifies, < 1 attenuates general brightness; using maskDark and maskLight often looks nicer\n\n        #define hardBloomPix -1.5    // increase for a larger horizontal bloom effect\n        #define hardBloomScan -2.0   // increase for a larger vertical bloom effect\n        #define bloomAmount 0.15     // increase for a stronger bloom effect\n        #define shape 2.0\n\n\n        float ToLinear1(float c)\n        {\n                return (c <= 0.04045) ? c / 12.92 : pow((c + 0.055) / 1.055, 2.4);\n        }\n\n        vec3 ToLinear(vec3 c)\n        {\n                return vec3(ToLinear1(c.r), ToLinear1(c.g), ToLinear1(c.b));\n        }\n\n        // Linear to sRGB.\n        // Assuming using sRGB typed textures this should not be needed.\n        float ToSrgb1(float c)\n        {\n                return (c < 0.0031308 ? c * 12.92 : 1.055 * pow(c, 0.41666) - 0.055);\n        }\n\n        vec3 ToSrgb(vec3 c)\n        {\n                return vec3(ToSrgb1(c.r), ToSrgb1(c.g), ToSrgb1(c.b));\n        }\n\n\n        // Nearest emulated sample given floating point position and texel offset.\n        // Also zero's off screen.\n        vec3 Fetch(vec2 pos, vec2 off){\n                pos = (floor(pos * rubyTextureSize + off) + vec2(0.5, 0.5)) / rubyTextureSize;\n                // pos = (floor(pos * rubyInputSize + off) + vec2(0.5, 0.5)) / rubyInputSize;\n                return ToLinear(brightBoost * texture2D(rubyTexture, pos.xy).rgb);\n        }\n\n        // Distance in emulated pixels to nearest texel.\n        vec2 Dist(vec2 pos)\n        {\n                pos = pos * rubyTextureSize;\n                // pos = pos * rubyInputSize;\n                \n                return -((pos - floor(pos)) - vec2(0.5));\n        }\n\n        // 1D Gaussian.\n        float Gaus(float pos, float scale)\n        {\n                return exp2(scale * pow(abs(pos), shape));\n        }\n\n        // 3-tap Gaussian filter along horz line.\n        vec3 Horz3(vec2 pos, float off)\n        {\n                vec3 b    = Fetch(pos, vec2(-1.0, off));\n                vec3 c    = Fetch(pos, vec2( 0.0, off));\n                vec3 d    = Fetch(pos, vec2( 1.0, off));\n                float dst = Dist(pos).x;\n\n                // Convert distance to weight.\n                float scale = hardPix;\n                float wb = Gaus(dst - 1.0, scale);\n                float wc = Gaus(dst + 0.0, scale);\n                float wd = Gaus(dst + 1.0, scale);\n\n                // Return filtered sample.\n                return (b*wb + c*wc + d*wd) / (wb + wc + wd);\n        }\n\n        // 5-tap Gaussian filter along horz line.\n        vec3 Horz5(vec2 pos,float off){\n                vec3 a = Fetch(pos, vec2(-2.0, off));\n                vec3 b = Fetch(pos, vec2(-1.0, off));\n                vec3 c = Fetch(pos, vec2( 0.0, off));\n                vec3 d = Fetch(pos, vec2( 1.0, off));\n                vec3 e = Fetch(pos, vec2( 2.0, off));\n                \n                float dst = Dist(pos).x;\n                // Convert distance to weight.\n                float scale = hardPix;\n                float wa = Gaus(dst - 2.0, scale);\n                float wb = Gaus(dst - 1.0, scale);\n                float wc = Gaus(dst + 0.0, scale);\n                float wd = Gaus(dst + 1.0, scale);\n                float we = Gaus(dst + 2.0, scale);\n                \n                // Return filtered sample.\n                return (a*wa + b*wb + c*wc + d*wd + e*we) / (wa + wb + wc + wd + we);\n        }\n\n        // 7-tap Gaussian filter along horz line.\n        vec3 Horz7(vec2 pos,float off)\n        {\n                vec3 a = Fetch(pos, vec2(-3.0, off));\n                vec3 b = Fetch(pos, vec2(-2.0, off));\n                vec3 c = Fetch(pos, vec2(-1.0, off));\n                vec3 d = Fetch(pos, vec2( 0.0, off));\n                vec3 e = Fetch(pos, vec2( 1.0, off));\n                vec3 f = Fetch(pos, vec2( 2.0, off));\n                vec3 g = Fetch(pos, vec2( 3.0, off));\n\n                float dst = Dist(pos).x;\n                // Convert distance to weight.\n                float scale = hardBloomPix;\n                float wa = Gaus(dst - 3.0, scale);\n                float wb = Gaus(dst - 2.0, scale);\n                float wc = Gaus(dst - 1.0, scale);\n                float wd = Gaus(dst + 0.0, scale);\n                float we = Gaus(dst + 1.0, scale);\n                float wf = Gaus(dst + 2.0, scale);\n                float wg = Gaus(dst + 3.0, scale);\n\n                // Return filtered sample.\n                return (a*wa + b*wb + c*wc + d*wd + e*we + f*wf + g*wg) / (wa + wb + wc + wd + we + wf + wg);\n        }\n\n        // Return scanline weight.\n        float Scan(vec2 pos, float off)\n        {\n                float dst = Dist(pos).y;\n\n                return Gaus(dst + off, hardScan);\n        }\n\n        // Return scanline weight for bloom.\n        float BloomScan(vec2 pos, float off)\n        {\n                float dst = Dist(pos).y;\n                \n                return Gaus(dst + off, hardBloomScan);\n        }\n\n        vec3 Tri(vec2 pos)\n        {\n                vec3 sample = Fetch(pos, vec2(0.0, 0.0));\n\n                vec3 a = Horz3(pos,-1.0);\n                vec3 b = Horz5(pos, 0.0);\n                vec3 c = Horz3(pos, 1.0);\n                \n                float wa = Scan(pos,-1.0); \n                float wb = Scan(pos, 0.0);\n                float wc = Scan(pos, 1.0);\n                \n                return a*wa + b*wb + c*wc;\n                        \n                // return sample;\n        }\n\n        // Small bloom.\n        vec3 Bloom(vec2 pos)\n        {\n                vec3 a = Horz5(pos,-2.0);\n                vec3 b = Horz7(pos,-1.0);\n                vec3 c = Horz7(pos, 0.0);\n                vec3 d = Horz7(pos, 1.0);\n                vec3 e = Horz5(pos, 2.0);\n\n                float wa = BloomScan(pos,-2.0);\n                float wb = BloomScan(pos,-1.0); \n                float wc = BloomScan(pos, 0.0);\n                float wd = BloomScan(pos, 1.0);\n                float we = BloomScan(pos, 2.0);\n\n                return a*wa + b*wb + c*wc + d*wd + e*we;\n        }\n\n        // Distortion of scanlines, and end of screen alpha.\n        vec2 Warp(vec2 pos)\n        {\n                pos  = pos * 2.0 - 1.0;    \n                pos *= vec2(1.0 + (pos.y * pos.y) * warpX, 1.0 + (pos.x * pos.x) * warpY);\n                \n                return pos * 0.5 + 0.5;\n        }\n\n        // Shadow mask.\n        vec3 Mask(vec2 pos)\n        {\n                vec3 mask = vec3(maskDark, maskDark, maskDark);\n                \n                // Very compressed TV style shadow mask.\n                if (shadowMask == 1.0) \n                {\n                        float line = maskLight;\n                        float odd = 0.0;\n                        \n                        if (fract(pos.x*0.166666666) < 0.5) odd = 1.0;\n                        if (fract((pos.y + odd) * 0.5) < 0.5) line = maskDark;  \n                        \n                        pos.x = fract(pos.x*0.333333333);\n\n                        if      (pos.x < 0.333) mask.r = maskLight;\n                        else if (pos.x < 0.666) mask.g = maskLight;\n                        else                    mask.b = maskLight;\n                        mask *= line;  \n                } \n\n                // Aperture-grille.\n                else if (shadowMask == 2.0) \n                {\n                        pos.x = fract(pos.x*0.333333333);\n\n                        if      (pos.x < 0.333) mask.r = maskLight;\n                        else if (pos.x < 0.666) mask.g = maskLight;\n                        else                    mask.b = maskLight;\n                } \n\n                // Stretched VGA style shadow mask (same as prior shaders).\n                else if (shadowMask == 3.0) \n                {\n                        pos.x += pos.y * 3.0;\n                        pos.x  = fract(pos.x * 0.166666666);\n\n                        if      (pos.x < 0.333) mask.r = maskLight;\n                        else if (pos.x < 0.666) mask.g = maskLight;\n                        else                    mask.b = maskLight;\n                }\n\n                // VGA style shadow mask.\n                else if (shadowMask == 4.0) \n                {\n                        pos.xy  = floor(pos.xy * vec2(1.0, 0.5));\n                        pos.x  += pos.y * 3.0;\n                        pos.x   = fract(pos.x * 0.166666666);\n\n                        if      (pos.x < 0.333) mask.r = maskLight;\n                        else if (pos.x < 0.666) mask.g = maskLight;\n                        else                    mask.b = maskLight;\n                }\n\n                return mask;\n        }\n\n        void main() {\n                vec2 pos = Warp(v_texCoord.xy * (rubyTextureSize / rubyInputSize)) * (rubyInputSize / rubyTextureSize);\n                vec3 outColor = Tri(pos);\n\n                // Add Bloom\n                outColor.rgb += Bloom(pos) * bloomAmount;\n\n                if (shadowMask > 0.0)\n                {\n                        outColor.rgb *= Mask(screenPixel);\n                }\n\n                gl_FragColor = vec4(ToSrgb(outColor.rgb), 1.0);\n        }\n"
  },
  {
    "path": "bin/common/Shaders/CRT-Lottes.OpenGL.shader",
    "content": "#<!--\n# PUBLIC DOMAIN CRT STYLED SCAN-LINE SHADER\n#\n#   by Timothy Lottes\n#\n# This is more along the style of a really good CGA arcade monitor.\n# With RGB inputs instead of NTSC.\n# The shadow mask example has the mask rotated 90 degrees for less chromatic aberration.\n#\n# Left it unoptimized to show the theory behind the algorithm.\n#\n# It is an example what I personally would want as a display option for pixel art games.\n# Please take and use, change, or whatever.\n#\n# Version without screen curvature emulation ('warp')\n# Adapted for OpenXcom by somnolik\n#-->\nlanguage: GLSL\nvertex: |\n        #version 110\n        uniform vec2 rubyOutputSize;\n\n        varying vec2 v_texCoord;\n        varying vec2 screenPixel;\n\n        void main(void)\n        {\n                gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n                v_texCoord = gl_MultiTexCoord0.xy;\n                screenPixel = gl_Position.xy * rubyOutputSize;\n        }\nlinear: false\nfragment: |\n        #version 110\n        uniform sampler2D rubyTexture;\n        uniform vec2 rubyTextureSize;\n\n        varying vec2 v_texCoord;\n        varying vec2 screenPixel;\n\n\n        /*\n        // Shader parameters for RetroArch\n        // Syntax:\n        // #pragma parameter <shortName> <longName> <defaultValue> <min> <max> <step>\n\n        #pragma parameter hardScan \"hardScan\" -8.0 -20.0 0.0 1.0\n        #pragma parameter hardPix \"hardPix\" -3.0 -20.0 0.0 1.0\n\n        #pragma parameter maskDark \"maskDark\" 0.5 0.0 2.0 0.1\n        #pragma parameter maskLight \"maskLight\" 1.5 0.0 2.0 0.1\n        #pragma parameter shadowMask \"shadowMask\" 3.0 0.0 4.0 1.0\n        #pragma parameter brightBoost \"brightness boost\" 1.0 0.0 2.0 0.05\n\n        #pragma parameter hardBloomPix \"bloom-x soft\" -1.5 -2.0 -0.5 0.1\n        #pragma parameter hardBloomScan \"bloom-y soft\" -2.0 -4.0 -1.0 0.1\n        #pragma parameter bloomAmount \"bloom ammount\" 0.15 0.0 1.0 0.05\n        #pragma parameter shape \"filter kernel shape\" 2.0 0.0 10.0 0.05\n        */\n\n        #define hardScan -8.0        // decrease for better distinction of scanlines\n        #define hardPix -5.0         // decrease for better distinction of individual pixels\n\n        #define maskDark 0.8         // > 1 amplifies, < 1 attenuates other color channels: green and blue for a red pixel, etc.\n        #define maskLight 1.5        // > 1 amplifies, < 1 attenuates own color channel: red for a red pixel, etc.\n        #define shadowMask 3.0       // 0 - disable; 1 - TV-style; 2 - Aperture grille; 3 - stretched VGA; 4 - VGA\n        #define brightBoost 1.0      // > 1 amplifies, < 1 attenuates general brightness; using maskDark and maskLight often looks nicer\n\n        #define hardBloomPix -1.5    // increase for a larger horizontal bloom effect\n        #define hardBloomScan -2.0   // increase for a larger vertical bloom effect\n        #define bloomAmount 0.15     // increase for a stronger bloom effect\n        #define shape 2.0\n\n\n        float ToLinear1(float c)\n        {\n                return (c <= 0.04045) ? c / 12.92 : pow((c + 0.055) / 1.055, 2.4);\n        }\n\n        vec3 ToLinear(vec3 c)\n        {\n                return vec3(ToLinear1(c.r), ToLinear1(c.g), ToLinear1(c.b));\n        }\n\n        // Linear to sRGB.\n        // Assuming using sRGB typed textures this should not be needed.\n        float ToSrgb1(float c)\n        {\n                return (c < 0.0031308 ? c * 12.92 : 1.055 * pow(c, 0.41666) - 0.055);\n        }\n\n        vec3 ToSrgb(vec3 c)\n        {\n                return vec3(ToSrgb1(c.r), ToSrgb1(c.g), ToSrgb1(c.b));\n        }\n\n\n        // Nearest emulated sample given floating point position and texel offset.\n        // Also zero's off screen.\n        vec3 Fetch(vec2 pos, vec2 off){\n                pos = (floor(pos * rubyTextureSize + off) + vec2(0.5, 0.5)) / rubyTextureSize;\n                return ToLinear(brightBoost * texture2D(rubyTexture, pos.xy).rgb);\n        }\n\n        // Distance in emulated pixels to nearest texel.\n        vec2 Dist(vec2 pos)\n        {\n                pos = pos * rubyTextureSize;\n                \n                return -((pos - floor(pos)) - vec2(0.5));\n        }\n\n        // 1D Gaussian.\n        float Gaus(float pos, float scale)\n        {\n                return exp2(scale * pow(abs(pos), shape));\n        }\n\n        // 3-tap Gaussian filter along horz line.\n        vec3 Horz3(vec2 pos, float off)\n        {\n                vec3 b    = Fetch(pos, vec2(-1.0, off));\n                vec3 c    = Fetch(pos, vec2( 0.0, off));\n                vec3 d    = Fetch(pos, vec2( 1.0, off));\n                float dst = Dist(pos).x;\n\n                // Convert distance to weight.\n                float scale = hardPix;\n                float wb = Gaus(dst - 1.0, scale);\n                float wc = Gaus(dst + 0.0, scale);\n                float wd = Gaus(dst + 1.0, scale);\n\n                // Return filtered sample.\n                return (b*wb + c*wc + d*wd) / (wb + wc + wd);\n        }\n\n        // 5-tap Gaussian filter along horz line.\n        vec3 Horz5(vec2 pos,float off){\n                vec3 a = Fetch(pos, vec2(-2.0, off));\n                vec3 b = Fetch(pos, vec2(-1.0, off));\n                vec3 c = Fetch(pos, vec2( 0.0, off));\n                vec3 d = Fetch(pos, vec2( 1.0, off));\n                vec3 e = Fetch(pos, vec2( 2.0, off));\n                \n                float dst = Dist(pos).x;\n                // Convert distance to weight.\n                float scale = hardPix;\n                float wa = Gaus(dst - 2.0, scale);\n                float wb = Gaus(dst - 1.0, scale);\n                float wc = Gaus(dst + 0.0, scale);\n                float wd = Gaus(dst + 1.0, scale);\n                float we = Gaus(dst + 2.0, scale);\n                \n                // Return filtered sample.\n                return (a*wa + b*wb + c*wc + d*wd + e*we) / (wa + wb + wc + wd + we);\n        }\n\n        // 7-tap Gaussian filter along horz line.\n        vec3 Horz7(vec2 pos,float off)\n        {\n                vec3 a = Fetch(pos, vec2(-3.0, off));\n                vec3 b = Fetch(pos, vec2(-2.0, off));\n                vec3 c = Fetch(pos, vec2(-1.0, off));\n                vec3 d = Fetch(pos, vec2( 0.0, off));\n                vec3 e = Fetch(pos, vec2( 1.0, off));\n                vec3 f = Fetch(pos, vec2( 2.0, off));\n                vec3 g = Fetch(pos, vec2( 3.0, off));\n\n                float dst = Dist(pos).x;\n                // Convert distance to weight.\n                float scale = hardBloomPix;\n                float wa = Gaus(dst - 3.0, scale);\n                float wb = Gaus(dst - 2.0, scale);\n                float wc = Gaus(dst - 1.0, scale);\n                float wd = Gaus(dst + 0.0, scale);\n                float we = Gaus(dst + 1.0, scale);\n                float wf = Gaus(dst + 2.0, scale);\n                float wg = Gaus(dst + 3.0, scale);\n\n                // Return filtered sample.\n                return (a*wa + b*wb + c*wc + d*wd + e*we + f*wf + g*wg) / (wa + wb + wc + wd + we + wf + wg);\n        }\n\n        // Return scanline weight.\n        float Scan(vec2 pos, float off)\n        {\n                float dst = Dist(pos).y;\n\n                return Gaus(dst + off, hardScan);\n        }\n\n        // Return scanline weight for bloom.\n        float BloomScan(vec2 pos, float off)\n        {\n                float dst = Dist(pos).y;\n                \n                return Gaus(dst + off, hardBloomScan);\n        }\n\n        vec3 Tri(vec2 pos)\n        {\n                vec3 sample = Fetch(pos, vec2(0.0, 0.0));\n\n                vec3 a = Horz3(pos,-1.0);\n                vec3 b = Horz5(pos, 0.0);\n                vec3 c = Horz3(pos, 1.0);\n                \n                float wa = Scan(pos,-1.0); \n                float wb = Scan(pos, 0.0);\n                float wc = Scan(pos, 1.0);\n                \n                return a*wa + b*wb + c*wc;\n                        \n                // return sample;\n        }\n\n        // Small bloom.\n        vec3 Bloom(vec2 pos)\n        {\n                vec3 a = Horz5(pos,-2.0);\n                vec3 b = Horz7(pos,-1.0);\n                vec3 c = Horz7(pos, 0.0);\n                vec3 d = Horz7(pos, 1.0);\n                vec3 e = Horz5(pos, 2.0);\n\n                float wa = BloomScan(pos,-2.0);\n                float wb = BloomScan(pos,-1.0); \n                float wc = BloomScan(pos, 0.0);\n                float wd = BloomScan(pos, 1.0);\n                float we = BloomScan(pos, 2.0);\n\n                return a*wa + b*wb + c*wc + d*wd + e*we;\n        }\n\n        // Shadow mask.\n        vec3 Mask(vec2 pos)\n        {\n                vec3 mask = vec3(maskDark, maskDark, maskDark);\n                \n                // Very compressed TV style shadow mask.\n                if (shadowMask == 1.0) \n                {\n                        float line = maskLight;\n                        float odd = 0.0;\n                        \n                        if (fract(pos.x*0.166666666) < 0.5) odd = 1.0;\n                        if (fract((pos.y + odd) * 0.5) < 0.5) line = maskDark;  \n                        \n                        pos.x = fract(pos.x*0.333333333);\n\n                        if      (pos.x < 0.333) mask.r = maskLight;\n                        else if (pos.x < 0.666) mask.g = maskLight;\n                        else                    mask.b = maskLight;\n                        mask *= line;  \n                } \n\n                // Aperture-grille.\n                else if (shadowMask == 2.0) \n                {\n                        pos.x = fract(pos.x*0.333333333);\n\n                        if      (pos.x < 0.333) mask.r = maskLight;\n                        else if (pos.x < 0.666) mask.g = maskLight;\n                        else                    mask.b = maskLight;\n                } \n\n                // Stretched VGA style shadow mask (same as prior shaders).\n                else if (shadowMask == 3.0) \n                {\n                        pos.x += pos.y * 3.0;\n                        pos.x  = fract(pos.x * 0.166666666);\n\n                        if      (pos.x < 0.333) mask.r = maskLight;\n                        else if (pos.x < 0.666) mask.g = maskLight;\n                        else                    mask.b = maskLight;\n                }\n\n                // VGA style shadow mask.\n                else if (shadowMask == 4.0) \n                {\n                        pos.xy  = floor(pos.xy * vec2(1.0, 0.5));\n                        pos.x  += pos.y * 3.0;\n                        pos.x   = fract(pos.x * 0.166666666);\n\n                        if      (pos.x < 0.333) mask.r = maskLight;\n                        else if (pos.x < 0.666) mask.g = maskLight;\n                        else                    mask.b = maskLight;\n                }\n\n                return mask;\n        }\n\n        void main() {\n                vec2 pos = v_texCoord.xy;\n                vec3 outColor = Tri(pos);\n\n                // Add Bloom\n                outColor.rgb += Bloom(pos) * bloomAmount;\n\n                if (shadowMask > 0.0)\n                {\n                        outColor.rgb *= Mask(screenPixel);\n                }\n\n                gl_FragColor = vec4(ToSrgb(outColor.rgb), 1.0);\n        }\n"
  },
  {
    "path": "bin/common/Shaders/CRT-interlaced.OpenGL.shader",
    "content": "#<!--\n#    CRT-interlaced shader\n#\n#    Like the standard CRT shader, but detects when the emulator is outputting\n#    interlaced frames and draws each field at the appropriate location.\n#\n#    Copyright (C) 2010-2012 cgwg, Themaister and DOLLS\n#\n#    This program is free software; you can redistribute it and/or modify it\n#    under the terms of the GNU General Public License as published by the Free\n#    Software Foundation; either version 2 of the License, or (at your option)\n#    any later version.\n#\n#    (cgwg gave their consent to have the original version of this shader\n#    distributed under the GPL in this message:\n#\n#        http://board.byuu.org/viewtopic.php?p=26075#p26075\n#\n#        \"Feel free to distribute my shaders under the GPL. After all, the\n#        barrel distortion code was taken from the Curvature shader, which is\n#        under the GPL.\"\n#    )\n#    -->\nlanguage: \"GLSL\"\nlinear: false\nvertex: |\n        varying float CRTgamma;\n        varying float monitorgamma;\n        varying vec2 overscan;\n        varying vec2 aspect;\n        varying float d;\n        varying float R;\n        varying float cornersize;\n        varying float cornersmooth;\n\n        varying vec3 stretch;\n        varying vec2 sinangle;\n        varying vec2 cosangle;\n\n        uniform vec2 rubyInputSize;\n        uniform vec2 rubyOutputSize;\n        uniform vec2 rubyTextureSize;\n\n        varying vec2 texCoord;\n        varying vec2 one;\n        varying float mod_factor;\n        varying vec2 ilfac;\n\n        #define FIX(c) max(abs(c), 1e-5);\n\n        float intersect(vec2 xy)\n        {\n                float A = dot(xy,xy)+d*d;\n                float B = 2.0*(R*(dot(xy,sinangle)-d*cosangle.x*cosangle.y)-d*d);\n                float C = d*d + 2.0*R*d*cosangle.x*cosangle.y;\n                return (-B-sqrt(B*B-4.0*A*C))/(2.0*A);\n        }\n\n        vec2 bkwtrans(vec2 xy)\n        {\n                float c = intersect(xy);\n                vec2 point = vec2(c)*xy;\n                point -= vec2(-R)*sinangle;\n                point /= vec2(R);\n                vec2 tang = sinangle/cosangle;\n                vec2 poc = point/cosangle;\n                float A = dot(tang,tang)+1.0;\n                float B = -2.0*dot(poc,tang);\n                float C = dot(poc,poc)-1.0;\n                float a = (-B+sqrt(B*B-4.0*A*C))/(2.0*A);\n                vec2 uv = (point-a*sinangle)/cosangle;\n                float r = R*acos(a);\n                return uv*r/sin(r/R);\n        }\n\n        vec2 fwtrans(vec2 uv)\n        {\n                float r = FIX(sqrt(dot(uv,uv)));\n                uv *= sin(r/R)/r;\n                float x = 1.0-cos(r/R);\n                float D = d/R + x*cosangle.x*cosangle.y+dot(uv,sinangle);\n                return d*(uv*cosangle-x*sinangle)/D;\n        }\n\n        vec3 maxscale()\n        {\n                vec2 c = bkwtrans(-R * sinangle / (1.0 + R/d*cosangle.x*cosangle.y));\n                vec2 a = vec2(0.5,0.5)*aspect;\n                vec2 lo = vec2(fwtrans(vec2(-a.x,c.y)).x,\n                             fwtrans(vec2(c.x,-a.y)).y)/aspect;\n                vec2 hi = vec2(fwtrans(vec2(+a.x,c.y)).x,\n                             fwtrans(vec2(c.x,+a.y)).y)/aspect;\n                return vec3((hi+lo)*aspect*0.5,max(hi.x-lo.x,hi.y-lo.y));\n        }\n\n\n        void main()\n        {\n                // START of parameters\n\n                // gamma of simulated CRT\n                CRTgamma = 2.4;\n                // gamma of display monitor (typically 2.2 is correct)\n                monitorgamma = 2.2;\n                // overscan (e.g. 1.02 for 2% overscan)\n                overscan = vec2(1.01,1.01);\n                // aspect ratio\n                aspect = vec2(1.0, 0.625);\n                // lengths are measured in units of (approximately) the width\n                // of the monitor simulated distance from viewer to monitor\n                d = 2.0;\n                // radius of curvature\n                R = 1.9;\n                // tilt angle in radians\n                // (behavior might be a bit wrong if both components are\n                // nonzero)\n                const vec2 angle = vec2(0.0,-0.01);\n                // size of curved corners\n                cornersize = 0.01;\n                // border smoothness parameter\n                // decrease if borders are too aliased\n                cornersmooth = 1000.0;\n\n                // END of parameters\n\n                // Do the standard vertex processing.\n                gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n\n                // Precalculate a bunch of useful values we'll need in the fragment\n                // shader.\n                sinangle = sin(angle);\n                cosangle = cos(angle);\n                stretch = maxscale();\n\n                // Texture coords.\n                texCoord = gl_MultiTexCoord0.xy;\n\n                ilfac = vec2(1.0,floor(rubyInputSize.y/200.0));\n\n                // The size of one texel, in texture-coordinates.\n                one = ilfac / rubyTextureSize;\n\n                // Resulting X pixel-coordinate of the pixel we're drawing.\n                mod_factor = texCoord.x * rubyTextureSize.x * rubyOutputSize.x / rubyInputSize.x;\n        }\nfragment: |\n        // Comment the next line to disable interpolation in linear gamma (and\n        // gain speed).\n        #define LINEAR_PROCESSING\n\n        // Enable screen curvature.\n        #define CURVATURE\n\n        // Enable 3x oversampling of the beam profile\n        #define OVERSAMPLE\n\n        // Use the older, purely gaussian beam profile\n        //#define USEGAUSSIAN\n\n        // Macros.\n        #define FIX(c) max(abs(c), 1e-5);\n        #define PI 3.141592653589\n\n        #ifdef LINEAR_PROCESSING\n        #       define TEX2D(c) pow(texture2D(rubyTexture, (c)), vec4(CRTgamma))\n        #else\n        #       define TEX2D(c) texture2D(rubyTexture, (c))\n        #endif\n\n        uniform sampler2D rubyTexture;\n        uniform vec2 rubyInputSize;\n        uniform vec2 rubyTextureSize;\n        uniform int rubyFrameCount;\n\n        varying vec2 texCoord;\n        varying vec2 one;\n        varying float mod_factor;\n        varying vec2 ilfac;\n\n        varying float CRTgamma;\n        varying float monitorgamma;\n\n        varying vec2 overscan;\n        varying vec2 aspect;\n\n        varying float d;\n        varying float R;\n\n        varying float cornersize;\n        varying float cornersmooth;\n\n        varying vec3 stretch;\n        varying vec2 sinangle;\n        varying vec2 cosangle;\n\n        float intersect(vec2 xy)\n        {\n                float A = dot(xy,xy)+d*d;\n                float B = 2.0*(R*(dot(xy,sinangle)-d*cosangle.x*cosangle.y)-d*d);\n                float C = d*d + 2.0*R*d*cosangle.x*cosangle.y;\n                return (-B-sqrt(B*B-4.0*A*C))/(2.0*A);\n        }\n\n        vec2 bkwtrans(vec2 xy)\n        {\n                float c = intersect(xy);\n                vec2 point = vec2(c)*xy;\n                point -= vec2(-R)*sinangle;\n                point /= vec2(R);\n                vec2 tang = sinangle/cosangle;\n                vec2 poc = point/cosangle;\n                float A = dot(tang,tang)+1.0;\n                float B = -2.0*dot(poc,tang);\n                float C = dot(poc,poc)-1.0;\n                float a = (-B+sqrt(B*B-4.0*A*C))/(2.0*A);\n                vec2 uv = (point-a*sinangle)/cosangle;\n                float r = FIX(R*acos(a));\n                return uv*r/sin(r/R);\n        }\n\n        vec2 transform(vec2 coord)\n        {\n                coord *= rubyTextureSize / rubyInputSize;\n                coord = (coord-vec2(0.5))*aspect*stretch.z+stretch.xy;\n                return (bkwtrans(coord)/overscan/aspect+vec2(0.5)) * rubyInputSize / rubyTextureSize;\n        }\n\n        float corner(vec2 coord)\n        {\n                coord *= rubyTextureSize / rubyInputSize;\n                coord = (coord - vec2(0.5)) * overscan + vec2(0.5);\n                coord = min(coord, vec2(1.0)-coord) * aspect;\n                vec2 cdist = vec2(cornersize);\n                coord = (cdist - min(coord,cdist));\n                float dist = sqrt(dot(coord,coord));\n                return clamp((cdist.x-dist)*cornersmooth,0.0, 1.0);\n        }\n\n        // Calculate the influence of a scanline on the current pixel.\n        //\n        // 'distance' is the distance in texture coordinates from the current\n        // pixel to the scanline in question.\n        // 'color' is the colour of the scanline at the horizontal location of\n        // the current pixel.\n        vec4 scanlineWeights(float distance, vec4 color)\n        {\n                // \"wid\" controls the width of the scanline beam, for each RGB\n                // channel The \"weights\" lines basically specify the formula\n                // that gives you the profile of the beam, i.e. the intensity as\n                // a function of distance from the vertical center of the\n                // scanline. In this case, it is gaussian if width=2, and\n                // becomes nongaussian for larger widths. Ideally this should\n                // be normalized so that the integral across the beam is\n                // independent of its width. That is, for a narrower beam\n                // \"weights\" should have a higher peak at the center of the\n                // scanline than for a wider beam.\n        #ifdef USEGAUSSIAN\n                vec4 wid = 0.3 + 0.1 * pow(color, vec4(3.0));\n                vec4 weights = vec4(distance / wid);\n                return 0.4 * exp(-weights * weights) / wid;\n        #else\n                vec4 wid = 2.0 + 2.0 * pow(color, vec4(4.0));\n                vec4 weights = vec4(distance / 0.3);\n                return 1.4 * exp(-pow(weights * inversesqrt(0.5 * wid), wid)) / (0.6 + 0.2 * wid);\n        #endif\n        }\n\n        void main()\n        {\n                // Here's a helpful diagram to keep in mind while trying to\n                // understand the code:\n                //\n                //  |      |      |      |      |\n                // -------------------------------\n                //  |      |      |      |      |\n                //  |  01  |  11  |  21  |  31  | <-- current scanline\n                //  |      | @    |      |      |\n                // -------------------------------\n                //  |      |      |      |      |\n                //  |  02  |  12  |  22  |  32  | <-- next scanline\n                //  |      |      |      |      |\n                // -------------------------------\n                //  |      |      |      |      |\n                //\n                // Each character-cell represents a pixel on the output\n                // surface, \"@\" represents the current pixel (always somewhere\n                // in the bottom half of the current scan-line, or the top-half\n                // of the next scanline). The grid of lines represents the\n                // edges of the texels of the underlying texture.\n\n                // Texture coordinates of the texel containing the active pixel.\n        #ifdef CURVATURE\n                vec2 xy = transform(texCoord);\n        #else\n                vec2 xy = texCoord;\n        #endif\n                float cval = corner(xy);\n\n                // Of all the pixels that are mapped onto the texel we are\n                // currently rendering, which pixel are we currently rendering?\n                vec2 ilvec = vec2(0.0,ilfac.y > 1.5 ? mod(float(rubyFrameCount),2.0) : 0.0);\n                vec2 ratio_scale = (xy * rubyTextureSize - vec2(0.5) + ilvec)/ilfac;\n        #ifdef OVERSAMPLE\n                float filter = fwidth(ratio_scale.y);\n        #endif\n                vec2 uv_ratio = fract(ratio_scale);\n\n                // Snap to the center of the underlying texel.\n                xy = (floor(ratio_scale)*ilfac + vec2(0.5) - ilvec) / rubyTextureSize;\n\n                // Calculate Lanczos scaling coefficients describing the effect\n                // of various neighbour texels in a scanline on the current\n                // pixel.\n                vec4 coeffs = PI * vec4(1.0 + uv_ratio.x, uv_ratio.x, 1.0 - uv_ratio.x, 2.0 - uv_ratio.x);\n\n                // Prevent division by zero.\n                coeffs = FIX(coeffs);\n\n                // Lanczos2 kernel.\n                coeffs = 2.0 * sin(coeffs) * sin(coeffs / 2.0) / (coeffs * coeffs);\n\n                // Normalize.\n                coeffs /= dot(coeffs, vec4(1.0));\n\n                // Calculate the effective colour of the current and next\n                // scanlines at the horizontal location of the current pixel,\n                // using the Lanczos coefficients above.\n                vec4 col  = clamp(mat4(\n                        TEX2D(xy + vec2(-one.x, 0.0)),\n                        TEX2D(xy),\n                        TEX2D(xy + vec2(one.x, 0.0)),\n                        TEX2D(xy + vec2(2.0 * one.x, 0.0))) * coeffs,\n                        0.0, 1.0);\n                vec4 col2 = clamp(mat4(\n                        TEX2D(xy + vec2(-one.x, one.y)),\n                        TEX2D(xy + vec2(0.0, one.y)),\n                        TEX2D(xy + one),\n                        TEX2D(xy + vec2(2.0 * one.x, one.y))) * coeffs,\n                        0.0, 1.0);\n\n        #ifndef LINEAR_PROCESSING\n                col  = pow(col , vec4(CRTgamma));\n                col2 = pow(col2, vec4(CRTgamma));\n        #endif\n\n                // Calculate the influence of the current and next scanlines on\n                // the current pixel.\n                vec4 weights  = scanlineWeights(uv_ratio.y, col);\n                vec4 weights2 = scanlineWeights(1.0 - uv_ratio.y, col2);\n        #ifdef OVERSAMPLE\n                uv_ratio.y =uv_ratio.y+1.0/3.0*filter;\n                weights = (weights+scanlineWeights(uv_ratio.y, col))/3.0;\n                weights2=(weights2+scanlineWeights(abs(1.0-uv_ratio.y), col2))/3.0;\n                uv_ratio.y =uv_ratio.y-2.0/3.0*filter;\n                weights=weights+scanlineWeights(abs(uv_ratio.y), col)/3.0;\n                weights2=weights2+scanlineWeights(abs(1.0-uv_ratio.y), col2)/3.0;\n        #endif\n                vec3 mul_res  = (col * weights + col2 * weights2).rgb * vec3(cval);\n\n                // dot-mask emulation:\n                // Output pixels are alternately tinted green and magenta.\n                vec3 dotMaskWeights = mix(\n                        vec3(1.0, 0.7, 1.0),\n                        vec3(0.7, 1.0, 0.7),\n                        floor(mod(mod_factor, 2.0))\n                    );\n\n                mul_res *= dotMaskWeights;\n\n                // Convert the image gamma for display on our output device.\n                mul_res = pow(mul_res, vec3(1.0 / monitorgamma));\n\n                // Color the texel.\n                gl_FragColor = vec4(mul_res, 1.0);\n        }\n"
  },
  {
    "path": "bin/common/Shaders/CRT-simple.OpenGL.shader",
    "content": "#<!--\n#    CRT-simple shader\n#\n#    Copyright (C) 2011 DOLLS. Based on cgwg's CRT shader.\n#\n#    This program is free software; you can redistribute it and/or modify it\n#    under the terms of the GNU General Public License as published by the Free\n#    Software Foundation; either version 2 of the License, or (at your option)\n#    any later version.\n#    -->\nlanguage: GLSL\nvertex: |\n        uniform vec2 rubyInputSize;\n        uniform vec2 rubyOutputSize;\n        uniform vec2 rubyTextureSize;\n\n        // Define some calculations that will be used in fragment shader.\n        varying vec2 texCoord;\n        varying vec2 one;\n        varying float mod_factor;\n\n        void main()\n        {\n                // Do the standard vertex processing.\n                gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n\n                // Precalculate a bunch of useful values we'll need in the fragment\n                // shader.\n\n                // Texture coords.\n                texCoord = gl_MultiTexCoord0.xy;\n\n                // The size of one texel, in texture-coordinates.\n                one = 1.0 / rubyTextureSize;\n\n                // Resulting X pixel-coordinate of the pixel we're drawing.\n                mod_factor = texCoord.x * rubyTextureSize.x * rubyOutputSize.x / rubyInputSize.x;\n        }\nlinear: true\nfragment: |\n        uniform sampler2D rubyTexture;\n        uniform vec2 rubyInputSize;\n        uniform vec2 rubyOutputSize;\n        uniform vec2 rubyTextureSize;\n\n        varying vec2 texCoord;\n        varying vec2 one;\n        varying float mod_factor;\n\n        // Enable screen curvature.\n        #define CURVATURE\n\n        // Controls the intensity of the barrel distortion used to emulate the\n        // curvature of a CRT. 0.0 is perfectly flat, 1.0 is annoyingly\n        // distorted, higher values are increasingly ridiculous.\n        #define distortion 0.1\n\n        // Simulate a CRT gamma of 2.4.\n        #define inputGamma  2.4\n\n        // Compensate for the standard sRGB gamma of 2.2.\n        #define outputGamma 2.2\n\n        // Macros.\n        #define TEX2D(c) pow(texture2D(rubyTexture, (c)), vec4(inputGamma))\n        #define PI 3.141592653589\n\n        // Apply radial distortion to the given coordinate.\n        vec2 radialDistortion(vec2 coord)\n        {\n                coord *= rubyTextureSize / rubyInputSize;\n                vec2 cc = coord - 0.5;\n                float dist = dot(cc, cc) * distortion;\n                return (coord + cc * (1.0 + dist) * dist) * rubyInputSize / rubyTextureSize;\n        }\n\n        // Calculate the influence of a scanline on the current pixel.\n        //\n        // 'distance' is the distance in texture coordinates from the current\n        // pixel to the scanline in question.\n        // 'color' is the colour of the scanline at the horizontal location of\n        // the current pixel.\n        vec4 scanlineWeights(float distance, vec4 color)\n        {\n                // The \"width\" of the scanline beam is set as 2*(1 + x^4) for\n                // each RGB channel.\n                vec4 wid = 2.0 + 2.0 * pow(color, vec4(4.0));\n\n                // The \"weights\" lines basically specify the formula that gives\n                // you the profile of the beam, i.e. the intensity as\n                // a function of distance from the vertical center of the\n                // scanline. In this case, it is gaussian if width=2, and\n                // becomes nongaussian for larger widths. Ideally this should\n                // be normalized so that the integral across the beam is\n                // independent of its width. That is, for a narrower beam\n                // \"weights\" should have a higher peak at the center of the\n                // scanline than for a wider beam.\n                vec4 weights = vec4(distance / 0.3);\n                return 1.4 * exp(-pow(weights * inversesqrt(0.5 * wid), wid)) / (0.6 + 0.2 * wid);\n        }\n\n        void main()\n        {\n                // Here's a helpful diagram to keep in mind while trying to\n                // understand the code:\n                //\n                //  |      |      |      |      |\n                // -------------------------------\n                //  |      |      |      |      |\n                //  |  01  |  11  |  21  |  31  | <-- current scanline\n                //  |      | @    |      |      |\n                // -------------------------------\n                //  |      |      |      |      |\n                //  |  02  |  12  |  22  |  32  | <-- next scanline\n                //  |      |      |      |      |\n                // -------------------------------\n                //  |      |      |      |      |\n                //\n                // Each character-cell represents a pixel on the output\n                // surface, \"@\" represents the current pixel (always somewhere\n                // in the bottom half of the current scan-line, or the top-half\n                // of the next scanline). The grid of lines represents the\n                // edges of the texels of the underlying texture.\n\n                // Texture coordinates of the texel containing the active pixel.\n        #ifdef CURVATURE\n                vec2 xy = radialDistortion(texCoord);\n        #else\n                vec2 xy = texCoord;\n        #endif\n\n                // Of all the pixels that are mapped onto the texel we are\n                // currently rendering, which pixel are we currently rendering?\n                vec2 ratio_scale = xy * rubyTextureSize - vec2(0.5);\n                vec2 uv_ratio = fract(ratio_scale);\n\n                // Snap to the center of the underlying texel.\n                xy.y = (floor(ratio_scale.y) + 0.5) / rubyTextureSize.y;\n\n                // Calculate the effective colour of the current and next\n                // scanlines at the horizontal location of the current pixel.\n                vec4 col  = TEX2D(xy);\n                vec4 col2 = TEX2D(xy + vec2(0.0, one.y));\n\n                // Calculate the influence of the current and next scanlines on\n                // the current pixel.\n                vec4 weights  = scanlineWeights(uv_ratio.y, col);\n                vec4 weights2 = scanlineWeights(1.0 - uv_ratio.y, col2);\n                vec3 mul_res  = (col * weights + col2 * weights2).rgb;\n\n                // dot-mask emulation:\n                // Output pixels are alternately tinted green and magenta.\n                vec3 dotMaskWeights = mix(\n                        vec3(1.0, 0.7, 1.0),\n                        vec3(0.7, 1.0, 0.7),\n                        floor(mod(mod_factor, 2.0))\n                    );\n\n                mul_res *= dotMaskWeights;\n\n                gl_FragColor = vec4(pow(mul_res, vec3(1.0 / outputGamma)), 1.0);\n        }\n"
  },
  {
    "path": "bin/common/Shaders/CRT.OpenGL.shader",
    "content": "#<!--\n#    CRT shader\n#\n#    Copyright (C) 2010-2012 cgwg, Themaister and DOLLS\n#\n#    This program is free software; you can redistribute it and/or modify it\n#    under the terms of the GNU General Public License as published by the Free\n#    Software Foundation; either version 2 of the License, or (at your option)\n#    any later version.\n#\n#    (cgwg gave their consent to have the original version of this shader\n#    distributed under the GPL in this message:\n#\n#        http://board.byuu.org/viewtopic.php?p=26075#p26075\n#\n#        \"Feel free to distribute my shaders under the GPL. After all, the\n#        barrel distortion code was taken from the Curvature shader, which is\n#        under the GPL.\"\n#    )\n#    -->\nlanguage: GLSL\nvertex: |\n        varying float CRTgamma;\n        varying float monitorgamma;\n        varying vec2 overscan;\n        varying vec2 aspect;\n        varying float d;\n        varying float R;\n        varying float cornersize;\n        varying float cornersmooth;\n\n        varying vec3 stretch;\n        varying vec2 sinangle;\n        varying vec2 cosangle;\n\n        uniform vec2 rubyInputSize;\n        uniform vec2 rubyOutputSize;\n        uniform vec2 rubyTextureSize;\n\n        varying vec2 texCoord;\n        varying vec2 one;\n        varying float mod_factor;\n\n        #define FIX(c) max(abs(c), 1e-5);\n\n        float intersect(vec2 xy)\n        {\n                float A = dot(xy,xy)+d*d;\n                float B = 2.0*(R*(dot(xy,sinangle)-d*cosangle.x*cosangle.y)-d*d);\n                float C = d*d + 2.0*R*d*cosangle.x*cosangle.y;\n                return (-B-sqrt(B*B-4.0*A*C))/(2.0*A);\n        }\n\n        vec2 bkwtrans(vec2 xy)\n        {\n                float c = intersect(xy);\n                vec2 point = vec2(c)*xy;\n                point -= vec2(-R)*sinangle;\n                point /= vec2(R);\n                vec2 tang = sinangle/cosangle;\n                vec2 poc = point/cosangle;\n                float A = dot(tang,tang)+1.0;\n                float B = -2.0*dot(poc,tang);\n                float C = dot(poc,poc)-1.0;\n                float a = (-B+sqrt(B*B-4.0*A*C))/(2.0*A);\n                vec2 uv = (point-a*sinangle)/cosangle;\n                float r = R*acos(a);\n                return uv*r/sin(r/R);\n        }\n\n        vec2 fwtrans(vec2 uv)\n        {\n                float r = FIX(sqrt(dot(uv,uv)));\n                uv *= sin(r/R)/r;\n                float x = 1.0-cos(r/R);\n                float D = d/R + x*cosangle.x*cosangle.y+dot(uv,sinangle);\n                return d*(uv*cosangle-x*sinangle)/D;\n        }\n\n        vec3 maxscale()\n        {\n                vec2 c = bkwtrans(-R * sinangle / (1.0 + R/d*cosangle.x*cosangle.y));\n                vec2 a = vec2(0.5,0.5)*aspect;\n                vec2 lo = vec2(fwtrans(vec2(-a.x,c.y)).x,\n                             fwtrans(vec2(c.x,-a.y)).y)/aspect;\n                vec2 hi = vec2(fwtrans(vec2(+a.x,c.y)).x,\n                             fwtrans(vec2(c.x,+a.y)).y)/aspect;\n                return vec3((hi+lo)*aspect*0.5,max(hi.x-lo.x,hi.y-lo.y));\n        }\n\n\n        void main()\n        {\n                // START of parameters\n\n                // gamma of simulated CRT\n                CRTgamma = 2.4;\n                // gamma of display monitor (typically 2.2 is correct)\n                monitorgamma = 2.2;\n                // overscan (e.g. 1.02 for 2% overscan)\n                overscan = vec2(1.01,1.01);\n                // aspect ratio\n                aspect = vec2(1.0, 0.75);\n                // lengths are measured in units of (approximately) the width\n                // of the monitor simulated distance from viewer to monitor\n                d = 2.0;\n                // radius of curvature\n                R = 1.5;\n                // tilt angle in radians\n                // (behavior might be a bit wrong if both components are\n                // nonzero)\n                const vec2 angle = vec2(0.0,0.01);\n                // size of curved corners\n                cornersize = 0.03;\n                // border smoothness parameter\n                // decrease if borders are too aliased\n                cornersmooth = 1000.0;\n\n                // END of parameters\n\n                // Do the standard vertex processing.\n                gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n\n                // Precalculate a bunch of useful values we'll need in the fragment\n                // shader.\n                sinangle = sin(angle);\n                cosangle = cos(angle);\n                stretch = maxscale();\n\n                // Texture coords.\n                texCoord = gl_MultiTexCoord0.xy;\n\n                // The size of one texel, in texture-coordinates.\n                one = 1.0 / rubyTextureSize;\n\n                // Resulting X pixel-coordinate of the pixel we're drawing.\n                mod_factor = texCoord.x * rubyTextureSize.x * rubyOutputSize.x / rubyInputSize.x;\n        }\nlinear: false\nfragment: |\n        // Comment the next line to disable interpolation in linear gamma (and\n        // gain speed).\n        #define LINEAR_PROCESSING\n\n        // Enable screen curvature.\n        #define CURVATURE\n\n        // Enable 3x oversampling of the beam profile\n        #define OVERSAMPLE\n\n        // Use the older, purely gaussian beam profile\n        //#define USEGAUSSIAN\n\n        // Macros.\n        #define FIX(c) max(abs(c), 1e-5);\n        #define PI 3.141592653589\n\n        #ifdef LINEAR_PROCESSING\n        #       define TEX2D(c) pow(texture2D(rubyTexture, (c)), vec4(CRTgamma))\n        #else\n        #       define TEX2D(c) texture2D(rubyTexture, (c))\n        #endif\n\n        uniform sampler2D rubyTexture;\n        uniform vec2 rubyInputSize;\n        uniform vec2 rubyTextureSize;\n\n        varying vec2 texCoord;\n        varying vec2 one;\n        varying float mod_factor;\n\n        varying float CRTgamma;\n        varying float monitorgamma;\n\n        varying vec2 overscan;\n        varying vec2 aspect;\n\n        varying float d;\n        varying float R;\n\n        varying float cornersize;\n        varying float cornersmooth;\n\n        varying vec3 stretch;\n        varying vec2 sinangle;\n        varying vec2 cosangle;\n\n        float intersect(vec2 xy)\n        {\n                float A = dot(xy,xy)+d*d;\n                float B = 2.0*(R*(dot(xy,sinangle)-d*cosangle.x*cosangle.y)-d*d);\n                float C = d*d + 2.0*R*d*cosangle.x*cosangle.y;\n                return (-B-sqrt(B*B-4.0*A*C))/(2.0*A);\n        }\n\n        vec2 bkwtrans(vec2 xy)\n        {\n                float c = intersect(xy);\n                vec2 point = vec2(c)*xy;\n                point -= vec2(-R)*sinangle;\n                point /= vec2(R);\n                vec2 tang = sinangle/cosangle;\n                vec2 poc = point/cosangle;\n                float A = dot(tang,tang)+1.0;\n                float B = -2.0*dot(poc,tang);\n                float C = dot(poc,poc)-1.0;\n                float a = (-B+sqrt(B*B-4.0*A*C))/(2.0*A);\n                vec2 uv = (point-a*sinangle)/cosangle;\n                float r = FIX(R*acos(a));\n                return uv*r/sin(r/R);\n        }\n\n        vec2 transform(vec2 coord)\n        {\n                coord *= rubyTextureSize / rubyInputSize;\n                coord = (coord-vec2(0.5))*aspect*stretch.z+stretch.xy;\n                return (bkwtrans(coord)/overscan/aspect+vec2(0.5)) * rubyInputSize / rubyTextureSize;\n        }\n\n        float corner(vec2 coord)\n        {\n                coord *= rubyTextureSize / rubyInputSize;\n                coord = (coord - vec2(0.5)) * overscan + vec2(0.5);\n                coord = min(coord, vec2(1.0)-coord) * aspect;\n                vec2 cdist = vec2(cornersize);\n                coord = (cdist - min(coord,cdist));\n                float dist = sqrt(dot(coord,coord));\n                return clamp((cdist.x-dist)*cornersmooth,0.0, 1.0);\n        }\n\n        // Calculate the influence of a scanline on the current pixel.\n        //\n        // 'distance' is the distance in texture coordinates from the current\n        // pixel to the scanline in question.\n        // 'color' is the colour of the scanline at the horizontal location of\n        // the current pixel.\n        vec4 scanlineWeights(float distance, vec4 color)\n        {\n                // \"wid\" controls the width of the scanline beam, for each RGB\n                // channel The \"weights\" lines basically specify the formula\n                // that gives you the profile of the beam, i.e. the intensity as\n                // a function of distance from the vertical center of the\n                // scanline. In this case, it is gaussian if width=2, and\n                // becomes nongaussian for larger widths. Ideally this should\n                // be normalized so that the integral across the beam is\n                // independent of its width. That is, for a narrower beam\n                // \"weights\" should have a higher peak at the center of the\n                // scanline than for a wider beam.\n        #ifdef USEGAUSSIAN\n                vec4 wid = 0.3 + 0.1 * pow(color, vec4(3.0));\n                vec4 weights = vec4(distance / wid);\n                return 0.4 * exp(-weights * weights) / wid;\n        #else\n                vec4 wid = 2.0 + 2.0 * pow(color, vec4(4.0));\n                vec4 weights = vec4(distance / 0.3);\n                return 1.4 * exp(-pow(weights * inversesqrt(0.5 * wid), wid)) / (0.6 + 0.2 * wid);\n        #endif\n        }\n\n        void main()\n        {\n                // Here's a helpful diagram to keep in mind while trying to\n                // understand the code:\n                //\n                //  |      |      |      |      |\n                // -------------------------------\n                //  |      |      |      |      |\n                //  |  01  |  11  |  21  |  31  | <-- current scanline\n                //  |      | @    |      |      |\n                // -------------------------------\n                //  |      |      |      |      |\n                //  |  02  |  12  |  22  |  32  | <-- next scanline\n                //  |      |      |      |      |\n                // -------------------------------\n                //  |      |      |      |      |\n                //\n                // Each character-cell represents a pixel on the output\n                // surface, \"@\" represents the current pixel (always somewhere\n                // in the bottom half of the current scan-line, or the top-half\n                // of the next scanline). The grid of lines represents the\n                // edges of the texels of the underlying texture.\n\n                // Texture coordinates of the texel containing the active pixel.\n        #ifdef CURVATURE\n                vec2 xy = transform(texCoord);\n        #else\n                vec2 xy = texCoord;\n        #endif\n                float cval = corner(xy);\n\n                // Of all the pixels that are mapped onto the texel we are\n                // currently rendering, which pixel are we currently rendering?\n                vec2 ratio_scale = xy * rubyTextureSize - vec2(0.5);\n        #ifdef OVERSAMPLE\n                float filter = fwidth(ratio_scale.y);\n        #endif\n                vec2 uv_ratio = fract(ratio_scale);\n\n                // Snap to the center of the underlying texel.\n                xy = (floor(ratio_scale) + vec2(0.5)) / rubyTextureSize;\n\n                // Calculate Lanczos scaling coefficients describing the effect\n                // of various neighbour texels in a scanline on the current\n                // pixel.\n                vec4 coeffs = PI * vec4(1.0 + uv_ratio.x, uv_ratio.x, 1.0 - uv_ratio.x, 2.0 - uv_ratio.x);\n\n                // Prevent division by zero.\n                coeffs = FIX(coeffs);\n\n                // Lanczos2 kernel.\n                coeffs = 2.0 * sin(coeffs) * sin(coeffs / 2.0) / (coeffs * coeffs);\n\n                // Normalize.\n                coeffs /= dot(coeffs, vec4(1.0));\n\n                // Calculate the effective colour of the current and next\n                // scanlines at the horizontal location of the current pixel,\n                // using the Lanczos coefficients above.\n                vec4 col  = clamp(mat4(\n                        TEX2D(xy + vec2(-one.x, 0.0)),\n                        TEX2D(xy),\n                        TEX2D(xy + vec2(one.x, 0.0)),\n                        TEX2D(xy + vec2(2.0 * one.x, 0.0))) * coeffs,\n                        0.0, 1.0);\n                vec4 col2 = clamp(mat4(\n                        TEX2D(xy + vec2(-one.x, one.y)),\n                        TEX2D(xy + vec2(0.0, one.y)),\n                        TEX2D(xy + one),\n                        TEX2D(xy + vec2(2.0 * one.x, one.y))) * coeffs,\n                        0.0, 1.0);\n\n        #ifndef LINEAR_PROCESSING\n                col  = pow(col , vec4(CRTgamma));\n                col2 = pow(col2, vec4(CRTgamma));\n        #endif\n\n                // Calculate the influence of the current and next scanlines on\n                // the current pixel.\n                vec4 weights  = scanlineWeights(uv_ratio.y, col);\n                vec4 weights2 = scanlineWeights(1.0 - uv_ratio.y, col2);\n        #ifdef OVERSAMPLE\n                uv_ratio.y =uv_ratio.y+1.0/3.0*filter;\n                weights = (weights+scanlineWeights(uv_ratio.y, col))/3.0;\n                weights2=(weights2+scanlineWeights(abs(1.0-uv_ratio.y), col2))/3.0;\n                uv_ratio.y =uv_ratio.y-2.0/3.0*filter;\n                weights=weights+scanlineWeights(abs(uv_ratio.y), col)/3.0;\n                weights2=weights2+scanlineWeights(abs(1.0-uv_ratio.y), col2)/3.0;\n        #endif\n                vec3 mul_res  = (col * weights + col2 * weights2).rgb * vec3(cval);\n\n                // dot-mask emulation:\n                // Output pixels are alternately tinted green and magenta.\n                vec3 dotMaskWeights = mix(\n                        vec3(1.0, 0.7, 1.0),\n                        vec3(0.7, 1.0, 0.7),\n                        floor(mod(mod_factor, 2.0))\n                    );\n\n                mul_res *= dotMaskWeights;\n\n                // Convert the image gamma for display on our output device.\n                mul_res = pow(mul_res, vec3(1.0 / monitorgamma));\n\n                // Color the texel.\n                gl_FragColor = vec4(mul_res, 1.0);\n        }\n"
  },
  {
    "path": "bin/common/Shaders/Curvature.OpenGL.shader",
    "content": "language: \"GLSL\"\nlinear: true\nfragment: |\n  uniform sampler2D rubyTexture;\n  uniform vec2 rubyInputSize;\n  uniform vec2 rubyTextureSize;\n\n  #define distortion 0.2\n\n  vec2 barrelDistortion(vec2 coord) {\n    vec2 cc = coord - 0.5;\n    float dist = dot(cc, cc);\n    return coord + cc * (dist + distortion * dist * dist) * distortion;\n  }\n\n  void main(void) {\n    vec2 coord = barrelDistortion (gl_TexCoord[0] * rubyTextureSize / rubyInputSize) * rubyInputSize / rubyTextureSize;\n\n    gl_FragColor = texture2D(rubyTexture, coord);\n  }\n"
  },
  {
    "path": "bin/common/Shaders/HQ2x.OpenGL.shader",
    "content": "language: GLSL\nvertex: |\n  uniform vec2 rubyTextureSize;\n\n  void main() {\n    float x = 0.5 * (1.0 / rubyTextureSize.x);\n    float y = 0.5 * (1.0 / rubyTextureSize.y);\n    vec2 dg1 = vec2( x, y);\n    vec2 dg2 = vec2(-x, y);\n    vec2 dx = vec2(x, 0.0);\n    vec2 dy = vec2(0.0, y);\n\n    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n    gl_TexCoord[0] = gl_MultiTexCoord0;\n    gl_TexCoord[1].xy = gl_TexCoord[0].xy - dg1;\n    gl_TexCoord[1].zw = gl_TexCoord[0].xy - dy;\n    gl_TexCoord[2].xy = gl_TexCoord[0].xy - dg2;\n    gl_TexCoord[2].zw = gl_TexCoord[0].xy + dx;\n    gl_TexCoord[3].xy = gl_TexCoord[0].xy + dg1;\n    gl_TexCoord[3].zw = gl_TexCoord[0].xy + dy;\n    gl_TexCoord[4].xy = gl_TexCoord[0].xy + dg2;\n    gl_TexCoord[4].zw = gl_TexCoord[0].xy - dx;\n  }\nlinear: false\nfragment: |\n  uniform sampler2D rubyTexture;\n\n  const float mx = 0.325;      // start smoothing wt.\n  const float k = -0.250;      // wt. decrease factor\n  const float max_w = 0.25;    // max filter weigth\n  const float min_w =-0.05;    // min filter weigth\n  const float lum_add = 0.25;  // effects smoothing\n\n  void main() {\n    vec3 c00 = texture2D(rubyTexture, gl_TexCoord[1].xy).xyz;\n    vec3 c10 = texture2D(rubyTexture, gl_TexCoord[1].zw).xyz;\n    vec3 c20 = texture2D(rubyTexture, gl_TexCoord[2].xy).xyz;\n    vec3 c01 = texture2D(rubyTexture, gl_TexCoord[4].zw).xyz;\n    vec3 c11 = texture2D(rubyTexture, gl_TexCoord[0].xy).xyz;\n    vec3 c21 = texture2D(rubyTexture, gl_TexCoord[2].zw).xyz;\n    vec3 c02 = texture2D(rubyTexture, gl_TexCoord[4].xy).xyz;\n    vec3 c12 = texture2D(rubyTexture, gl_TexCoord[3].zw).xyz;\n    vec3 c22 = texture2D(rubyTexture, gl_TexCoord[3].xy).xyz;\n    vec3 dt = vec3(1.0, 1.0, 1.0);\n\n    float md1 = dot(abs(c00 - c22), dt);\n    float md2 = dot(abs(c02 - c20), dt);\n\n    float w1 = dot(abs(c22 - c11), dt) * md2;\n    float w2 = dot(abs(c02 - c11), dt) * md1;\n    float w3 = dot(abs(c00 - c11), dt) * md2;\n    float w4 = dot(abs(c20 - c11), dt) * md1;\n\n    float t1 = w1 + w3;\n    float t2 = w2 + w4;\n    float ww = max(t1, t2) + 0.0001;\n\n    c11 = (w1 * c00 + w2 * c20 + w3 * c22 + w4 * c02 + ww * c11) / (t1 + t2 + ww);\n\n    float lc1 = k / (0.12 * dot(c10 + c12 + c11, dt) + lum_add);\n    float lc2 = k / (0.12 * dot(c01 + c21 + c11, dt) + lum_add);\n\n    w1 = clamp(lc1 * dot(abs(c11 - c10), dt) + mx, min_w, max_w);\n    w2 = clamp(lc2 * dot(abs(c11 - c21), dt) + mx, min_w, max_w);\n    w3 = clamp(lc1 * dot(abs(c11 - c12), dt) + mx, min_w, max_w);\n    w4 = clamp(lc2 * dot(abs(c11 - c01), dt) + mx, min_w, max_w);\n\n    gl_FragColor.xyz = w1 * c10 + w2 * c21 + w3 * c12 + w4 * c01 + (1.0 - w1 - w2 - w3 - w4) * c11;\n  }\n"
  },
  {
    "path": "bin/common/Shaders/Openxcom.OpenGL.shader",
    "content": "#<!--\n#   Standard Openxcom shader file\n#\n#   Copyright (C) 2013 - Openxcom Project - https://openxcom.org/\n#\n#   AUTHOR: Powerc80\n#\n#   DESCRIPTION: This shader is designed to smooth rough edges, while\n#   maintaining a semi-pixellated feel similar to the original X-com.\n#   This code was based guest(r)'s 4xGLSLHqFilter OpenGL shader.\n#\n#   =======================LEGAL INFORMATION=========================\n#\n#   This program is free software; you can redistribute it and/or\n#   modify it under the terms of the GNU General Public License\n#   as published by the Free Software Foundation; either version 3\n#   of the License, or (at your option) any later version.\n#\n#   This program is distributed in the hope that it will be useful,\n#   but WITHOUT ANY WARRANTY; without even the implied warranty of\n#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#   GNU General Public License for more details.\n#\n#   For more information --> http://www.gnu.org/licenses/gpl.html\n#\n#   =================================================================\n#\n#-->\nlanguage: \"GLSL\"\nvertex: |\n        #version 110\n        uniform vec2 rubyTextureSize;\n\n        void main()\n        {\n                //////////////////////////////////////////////////\n                //X_VALUE and Y_VALUE: these values refer to the//\n                //length & width of the view-window rectangle   //\n                //(i.e. the x and y dimensions of the screen). A//\n                //value of 0.0001 produces a result close to the//\n                //original resolution of X-com, while a value of//\n                //0.001 produces a slightly smoother screen.    //\n                //Values higher than 0.002 are not recommended. //\n                //////////////////////////////////////////////////\n                const float x_value = 0.00077;\n                const float y_value = 0.00077;\n\n                //////////////////////////////////////////////////\n                //Here we define several vertices that are used //\n                //as an overlay rectangle for the screens/menus.//\n                //                                              //\n                //Where tr = top-right vertex                   //\n                //      tl = top-left vertex                    //\n                //      br = bottom-right vertex                //\n                //      bl = bottom-left vertex                 //\n                //////////////////////////////////////////////////\n                const vec2 tr = vec2(x_value,y_value);\n                const vec2 tl = vec2(-x_value,y_value);\n                const vec2 br = vec2(x_value,0.0);\n                const vec2 bl = vec2(-x_value,0.0);\n\n                ////////////////////////////////////////////////////////\n                //Defines screen position and initial texture coord's.//\n                ////////////////////////////////////////////////////////\n                gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n                gl_TexCoord[0] = gl_MultiTexCoord0;\n\n                //////////////////////////////////////////////////////\n                //Defines the x-y section of the texture coordinate.//\n                //////////////////////////////////////////////////////\n                gl_TexCoord[1].xy = gl_TexCoord[0].xy - (tr * 0.55);\n                gl_TexCoord[2].xy = gl_TexCoord[0].xy - (tl * 0.55);\n                gl_TexCoord[3].xy = gl_TexCoord[0].xy + (tr * 0.55);\n                gl_TexCoord[4].xy = gl_TexCoord[0].xy + (tl * 0.55);\n                gl_TexCoord[5].xy = gl_TexCoord[0].xy - tr;\n                gl_TexCoord[6].xy = gl_TexCoord[0].xy + tr;\n\n                //////////////////////////////////////////////////////\n                //Defines the z-w section of the texture coordinate.//\n                //////////////////////////////////////////////////////\n                gl_TexCoord[1].zw = gl_TexCoord[0].xy - bl;\n                gl_TexCoord[2].zw = gl_TexCoord[0].xy + br;\n                gl_TexCoord[3].zw = gl_TexCoord[0].xy + bl;\n                gl_TexCoord[4].zw = gl_TexCoord[0].xy - br;\n                gl_TexCoord[5].zw = gl_TexCoord[0].xy - tl;\n                gl_TexCoord[6].zw = gl_TexCoord[0].xy + tl;\n        }\nfragment: |\n        #version 110\n        uniform sampler2D rubyTexture;\n\n        ///////////////////////////////////////////////////////////\n        //Initial Vertex: the first value of the texture coord's,//\n        //which is used as a 'centre' for all the other values.  //\n        ///////////////////////////////////////////////////////////\n        vec3 centre = texture2D(rubyTexture, gl_TexCoord[0].xy).xyz;\n\n        ///////////////////////////////////////////////////////////////\n        //Reference Vertex: used later when calculating dot-products.//\n        ///////////////////////////////////////////////////////////////\n        const vec3 ref = vec3(1.0,1.0,1.0);\n\n        //////////////////////////////////////////////////////////////\n        //WEIGHT VARIABLES: Several variables are declared here     //\n        //to be used to precisely define the various filter weights.//\n        //                                                          //\n        //Where start_weight = starting weight                      //\n        //                 k = weight decreasing factor             //\n        //        max_weight = maximum filter weight                //\n        //        min_weight = minimum filter weight                //\n        //////////////////////////////////////////////////////////////\n        const float start_weight =  1.04;\n        const float k            = -1.07;\n        const float max_weight   =  0.73;\n        const float min_weight   =  0.05;\n\n        ////////////////////////////////////////////////////////////////////\n        //DP FUNCTION: Returns the adjusted dot-product of a given vertex.//\n        ////////////////////////////////////////////////////////////////////\n        float dp(vec3 v) {return dot(abs(v-centre),ref);}\n\n        void main()\n        {\n              /////////////////////////////////////////////////////////\n              //Attaches the defined coordinates of gl_TextCoord     //\n              //to sampler2D to allow for modification via filtering.//\n              /////////////////////////////////////////////////////////\n              vec3 i1 = texture2D(rubyTexture, gl_TexCoord[1].xy).xyz;\n              vec3 i2 = texture2D(rubyTexture, gl_TexCoord[2].xy).xyz;\n              vec3 i3 = texture2D(rubyTexture, gl_TexCoord[3].xy).xyz;\n              vec3 i4 = texture2D(rubyTexture, gl_TexCoord[4].xy).xyz;\n              vec3 o1 = texture2D(rubyTexture, gl_TexCoord[5].xy).xyz;\n              vec3 o3 = texture2D(rubyTexture, gl_TexCoord[6].xy).xyz;\n              vec3 o2 = texture2D(rubyTexture, gl_TexCoord[5].zw).xyz;\n              vec3 o4 = texture2D(rubyTexture, gl_TexCoord[6].zw).xyz;\n              vec3 s1 = texture2D(rubyTexture, gl_TexCoord[1].zw).xyz;\n              vec3 s2 = texture2D(rubyTexture, gl_TexCoord[2].zw).xyz;\n              vec3 s3 = texture2D(rubyTexture, gl_TexCoord[3].zw).xyz;\n              vec3 s4 = texture2D(rubyTexture, gl_TexCoord[4].zw).xyz;\n\n              ////////////////////////////////////////////////////////////\n              //FILTER WEIGHTS: These are the weights which will be used//\n              //by the filter to produce the intended result.           //\n              ////////////////////////////////////////////////////////////\n              float w1 = min(dot(abs(i2-i4),ref), max(dp(o2),dp(o4)));\n              float w2 = min(dot(abs(i1-i3),ref), max(dp(o1),dp(o3)));\n              float w3 = min(dot(abs(i2-i4),ref), max(dp(o2),dp(o4)));\n              float w4 = min(dot(abs(i1-i3),ref), max(dp(o1),dp(o3)));\n\n              //////////////////////////////////////////////////////////////////\n              //Adjusts the weight values, based on the previous dot-products.//\n              //////////////////////////////////////////////////////////////////\n              if (dp(o3) < dp(o1)) w1 *= dp(o3) / dp(o1);\n              if (dp(o4) < dp(o2)) w2 *= dp(o4) / dp(o2);\n              if (dp(o1) < dp(o3)) w3 *= dp(o1) / dp(o3);\n              if (dp(o2) < dp(o4)) w4 *= dp(o2) / dp(o4);\n\n              //////////////////////////////////////////////////////////////\n              //Adjusts the value of centre, based on the current weights.//\n              //////////////////////////////////////////////////////////////\n              centre = (w1*o1+w2*o2+w3*o3+w4*o4+0.00077*centre) / (w1+w2+w3+w4+0.00077);\n\n              /////////////////////////////////////////////////////////////////\n              //The weights are then adjusted based on the decreasing factor,//\n              //k, and the effects smoothing factor, FX_add.                 //\n              /////////////////////////////////////////////////////////////////\n              w1 = k*dot(abs(i1-centre)+abs(i3-centre),ref) / (0.125*dot(i1+i3,ref));\n              w2 = k*dot(abs(i2-centre)+abs(i4-centre),ref) / (0.125*dot(i2+i4,ref));\n              w3 = k*dot(abs(s1-centre)+abs(s3-centre),ref) / (0.125*dot(s1+s3,ref));\n              w4 = k*dot(abs(s2-centre)+abs(s4-centre),ref) / (0.125*dot(s2+s4,ref));\n\n              ////////////////////////////////////////////////////////////////////\n              //Weights w1 to w4 are clamped between the min and the max weight,//\n              //preventing them from aversely being too high or too low.        //\n              ////////////////////////////////////////////////////////////////////\n              w1 = clamp(w1+start_weight, min_weight, max_weight);\n              w2 = clamp(w2+start_weight, min_weight, max_weight);\n              w3 = clamp(w3+start_weight, min_weight, max_weight);\n              w4 = clamp(w4+start_weight, min_weight, max_weight);\n\n              ///////////////////////////////////////////////////////////////////////////\n              //Applies the weights to filter the screen, and then displays the result.//\n              ///////////////////////////////////////////////////////////////////////////\n              gl_FragColor.xyz = (w1*(i1+i3)+w2*(i2+i4)+w3*(s1+s3)+w4*(s2+s4)+centre) / (2.0*(w1+w2+w3+w4)+1.0);\n              gl_FragColor.a   = 1.0;\n        }\nlinear: false\n"
  },
  {
    "path": "bin/common/Shaders/Phosphor-simple.OpenGL.shader",
    "content": "#<!--\n#   Plain (and obviously inaccurate) phosphor.\n#   Author: Themaister\n#   License: Public Domain\n#-->\nlanguage: \"GLSL\"\nlinear: true\nfragment: |\n      uniform sampler2D rubyTexture;\n      uniform vec2 rubyTextureSize;\n\n      vec3 to_focus(float pixel)\n      {\n         pixel = mod(pixel + 3.0, 3.0);\n         if (pixel >= 2.0) // Blue\n            return vec3(pixel - 2.0, 0.0, 3.0 - pixel);\n         else if (pixel >= 1.0) // Green\n            return vec3(0.0, 2.0 - pixel, pixel - 1.0);\n         else // Red\n            return vec3(1.0 - pixel, pixel, 0.0);\n      }\n\n      void main()\n      {\n         float y = mod(gl_TexCoord[0].y * rubyTextureSize.y, 1.0);\n         float intensity = exp(-0.2 * y);\n\n         vec2 one_x = vec2(1.0 / (3.0 * rubyTextureSize.x), 0.0);\n\n         vec3 color = texture2D(rubyTexture, gl_TexCoord[0].xy - 0.0 * one_x).rgb;\n         vec3 color_prev = texture2D(rubyTexture, gl_TexCoord[0].xy - 1.0 * one_x).rgb;\n         vec3 color_prev_prev = texture2D(rubyTexture, gl_TexCoord[0].xy - 2.0 * one_x).rgb;\n\n         float pixel_x = 3.0 * gl_TexCoord[0].x * rubyTextureSize.x;\n\n         vec3 focus = to_focus(pixel_x - 0.0);\n         vec3 focus_prev = to_focus(pixel_x - 1.0);\n         vec3 focus_prev_prev = to_focus(pixel_x - 2.0);\n\n         vec3 result =\n            0.8 * color * focus +\n            0.6 * color_prev * focus_prev +\n            0.3 * color_prev_prev * focus_prev_prev;\n\n         result = 2.3 * pow(result, vec3(1.4));\n\n         gl_FragColor = vec4(intensity * result, 1.0);\n      }\n"
  },
  {
    "path": "bin/common/Shaders/Pixellate.OpenGL.shader",
    "content": "language: \"GLSL\"\nvertex: |\n  void main() {\n    gl_Position    = ftransform();\n    gl_TexCoord[0] = gl_MultiTexCoord0;\n  }\nlinear: false\nfragment: |\n  uniform sampler2D rubyTexture;\n  uniform vec2      rubyTextureSize;\n\n  void main() {\n    vec2 texelSize = 1.0 / rubyTextureSize;\n\n    vec2 range;\n    range.x = dFdx(gl_TexCoord[0].x) / 2.0 * 0.99;\n    range.y = dFdy(gl_TexCoord[0].y) / 2.0 * 0.99;\n\n    float left   = gl_TexCoord[0].x - range.x;\n    float top    = gl_TexCoord[0].y + range.y;\n    float right  = gl_TexCoord[0].x + range.x;\n    float bottom = gl_TexCoord[0].y - range.y;\n\n    vec4 topLeftColor     = texture2D(rubyTexture, (floor(vec2(left, top)     / texelSize) + 0.5) * texelSize);\n    vec4 bottomRightColor = texture2D(rubyTexture, (floor(vec2(right, bottom) / texelSize) + 0.5) * texelSize);\n    vec4 bottomLeftColor  = texture2D(rubyTexture, (floor(vec2(left, bottom)  / texelSize) + 0.5) * texelSize);\n    vec4 topRightColor    = texture2D(rubyTexture, (floor(vec2(right, top)    / texelSize) + 0.5) * texelSize);\n\n    vec2 border = clamp(round(gl_TexCoord[0] / texelSize) * texelSize, vec2(left, bottom), vec2(right, top));\n\n    float totalArea = 4.0 * range.x * range.y;\n\n    vec4 averageColor;\n    averageColor  = ((border.x - left)  * (top - border.y)    / totalArea) * topLeftColor;\n    averageColor += ((right - border.x) * (border.y - bottom) / totalArea) * bottomRightColor;\n    averageColor += ((border.x - left)  * (border.y - bottom) / totalArea) * bottomLeftColor;\n    averageColor += ((right - border.x) * (top - border.y)    / totalArea) * topRightColor;\n\n    gl_FragColor = averageColor;\n  }\n"
  },
  {
    "path": "bin/common/Shaders/Quilez.OpenGL.shader",
    "content": "#<!--\n#    Fragment shader based on \"Improved texture interpolation\" by Iñigo Quílez\n#\n#    Original description:\n#        http://www.iquilezles.org/www/articles/texture/texture.htm\n#-->\nlanguage: GLSL\nlinear: true\nfragment: |\n        uniform sampler2D rubyTexture;\n        uniform vec2 rubyInputSize;\n        uniform vec2 rubyOutputSize;\n        uniform vec2 rubyTextureSize;\n\n        vec4 getTexel(vec2 p)\n        {\n                p = p * rubyTextureSize + vec2(0.5);\n\n                vec2 i = floor(p);\n                vec2 f = p - i;\n                f = f * f * f * (f * (f * 6.0 - vec2(15.0)) + vec2(10.0));\n                p = i + f;\n\n                p = (p - vec2(0.5)) / rubyTextureSize;\n                return texture2D(rubyTexture, p);\n        }\n\n        void main(void)\n        {\n                gl_FragColor = getTexel(gl_TexCoord[0].xy);\n        }\n"
  },
  {
    "path": "bin/common/Shaders/Raw.OpenGL.shader",
    "content": "#<!--\n#    Blank shader to allow Vsync without changing anything.\n#-->\nlanguage: GLSL\nlinear: false\nfragment: |\n        uniform sampler2D rubyTexture;\n\n        void main(void)\n        {\n                gl_FragColor = texture2D(rubyTexture, gl_TexCoord[0].xy);\n        }\n"
  },
  {
    "path": "bin/common/Shaders/SABR-XCOMified.OpenGL.shader",
    "content": "#<!--\n#   SABR XCOMified v1.3 Shader\n#\n#   Copyright (C) 2011, 2012 Hyllian/Jararaca - sergiogdb@gmail.com (5xBR)\n#   Copyright (C) 2012 crazy46guy (GLSL conversion)\n#   Copyright (C) 2012 Joshua Street (SABR)\n#   Copyright (c) 2014 Daemonjax (XCOMification)\n#\n#   Portions of this algorithm were taken from Hyllian's 5xBR v3.7c\n#   shader and Joshua Street's SABR v3.0 shader.\n#\n#   This program is free software; you can redistribute it and/or\n#   modify it under the terms of the GNU General Public License\n#   as published by the Free Software Foundation; either version 2\n#   of the License, or (at your option) any later version.\n#\n#   This program is distributed in the hope that it will be useful,\n#   but WITHOUT ANY WARRANTY; without even the implied warranty of\n#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n#   GNU General Public License for more details.\n#\n#   You should have received a copy of the GNU General Public License\n#   along with this program; if not, write to the Free Software\n#   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n#\n#-->\n\nlanguage: \"GLSL\"\nvertex: |\n    uniform vec2 rubyTextureSize;\n\n    varying vec2 tc;\n    varying vec4 xyp_e1_e2_e3;\n    varying vec4 xyp_f1_f2_f3;\n    varying vec4 xyp_g1_g2_g3;\n    varying vec4 xyp_h1_h2_h3;\n    varying vec4 xyp_a_b_c_d;\n    varying vec4 xyp_1_2_3;\n    varying vec4 xyp_5_10_15;\n    varying vec4 xyp_6_7_8;\n    varying vec4 xyp_9_14_9;\n    varying vec4 xyp_11_12_13;\n    varying vec4 xyp_16_17_18;\n    varying vec4 xyp_21_22_23;\n\n    void main() {\n      gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n\n      float x = 1.0 / rubyTextureSize.x;\n      float y = 1.0 / rubyTextureSize.y;\n\n      /* Mask for algorhithm\n         -4x  -3x  -2x   -x    0    x   2x   3x   4x\n        +----+----+----+----+----+----+----+----+----+\n             |    |    |    |    |    |    |    |    | -4y\n        +----+----+----+----+----+----+----+----+----+\n             |    |    | e1 | e2 | e3 |    |    |    | -3y\n        +----+----+----+----+----+----+----+----+----+\n             |    |  a |  1 |  2 |  3 |  b |    |    | -2y\n        +----+----+----+----+----+----+----+----+----+\n             | h1 |  5 |  6 |  7 |  8 |  9 | f1 |    |  -y\n        +----+----+----+----+----+----+----+----+----+\n             | h2 | 10 | 11 | 12 | 13 | 14 | f2 |    |   0\n        +----+----+----+----+----+----+----+----+----+\n             | h3 | 15 | 16 | 17 | 18 | 19 | f3 |    |   y\n        +----+----+----+----+----+----+----+----+----+\n             |    |  c | 21 | 22 | 23 |  d |    |    |  2y\n        +----+----+----+----+----+----+----+----+----+\n             |    |    | g1 | g2 | g3 |    |    |    |  3y\n        +----+----+----+----+----+----+----+----+----+\n             |    |    |    |    |    |    |    |    |  4y\n        +----+----+----+----+----+----+----+----+----+\n      */\n\n      tc = gl_MultiTexCoord0.xy;\n\n      /*\n      xyp_e1_e2_e3 = tc.xxxy + vec4(      -x, 0.0,   x, -3.0 * y);\n      xyp_f1_f2_f3 = tc.xyyy + vec4( 3.0 * x,  -y, 0.0,        y);\n      xyp_g1_g2_g3 = tc.xxxy + vec4(      -x, 0.0,   x,  3.0 * y);\n      xyp_h1_h2_h3 = tc.xyyy + vec4(-3.0 * x,  -y, 0.0,        y);\n      xyp_a_b_c_d  = tc.xxyy + vec4(-2.0 * x, 2.0  * x, -2.0 * y, 2.0 * y);\n      */\n      xyp_1_2_3    = tc.xxxy + vec4(      -x, 0.0,   x, -2.0 * y);\n      xyp_6_7_8    = tc.xxxy + vec4(      -x, 0.0,   x,       -y);\n      xyp_11_12_13 = tc.xxxy + vec4(      -x, 0.0,   x,      0.0);\n      xyp_16_17_18 = tc.xxxy + vec4(      -x, 0.0,   x,        y);\n      xyp_21_22_23 = tc.xxxy + vec4(      -x, 0.0,   x,  2.0 * y);\n      xyp_5_10_15  = tc.xyyy + vec4(-2.0 * x,  -y, 0.0,        y);\n      xyp_9_14_9   = tc.xyyy + vec4( 2.0 * x,  -y, 0.0,        y);\n    }\nlinear: false\nfragment: |\n    /* Uniforms\n      - rubyTexture: texture sampler\n      - rubyTextureSize: size of the texture before rendering\n    */\n    uniform sampler2D rubyTexture;\n    uniform vec2 rubyTextureSize;\n\n    /* Varying attributes\n      - tc: coordinate of the texel being processed\n      - xyp_[]_[]_[]: a packed coordinate for 3 or 4 areas within the texture\n    */\n\n\n    varying vec2 tc;\n    /*\n    varying vec4 xyp_e1_e2_e3;\n    varying vec4 xyp_f1_f2_f3;\n    varying vec4 xyp_g1_g2_g3;\n    varying vec4 xyp_h1_h2_h3;\n    varying vec4 xyp_a_b_c_d;\n    */\n    varying vec4 xyp_1_2_3;\n    varying vec4 xyp_5_10_15;\n    varying vec4 xyp_6_7_8;\n    varying vec4 xyp_9_14_9;\n    varying vec4 xyp_11_12_13;\n    varying vec4 xyp_16_17_18;\n    varying vec4 xyp_21_22_23;\n\n    /* Constants\n    */\n\n    // Pallete colors used in exclusion rules\n     const vec3 ex1_Yellow = vec3(252.0, 252.0,   0.0) / 255.0;\n     const vec3 ex1_Red1   = vec3(192.0,   0.0,   0.0) / 255.0;\n     const vec3 ex1_Red2   = vec3(252.0,   0.0,   0.0) / 255.0;\n     const vec3 ex1_Cyan1  = vec3(0.0  , 192.0, 192.0) / 255.0;\n     const vec3 ex1_Cyan2  = vec3(0.0  , 252.0, 252.0) / 255.0;\n     const vec3 ex_Pink1   = vec3(252.0, 164.0, 212.0) / 255.0;\n     const vec3 ex_Pink2   = vec3(192.0, 112.0, 152.0) / 255.0;\n\n    // Inequation coefficients for interpolation\n    //    Equations are in the form: Ay + Bx = C\n    //    45, 30, and 60 denote the angle from x each line the cooeficient variable set builds\n\n    const vec4 Ai  = vec4(1.0, -1.0, -1.0,  1.0);\n    const vec4 B45 = vec4(1.0,  1.0, -1.0, -1.0);\n    const vec4 C45 = vec4(1.5,  0.5, -0.5,  0.5);\n    const vec4 B30 = vec4(0.5,  2.0, -0.5, -2.0);\n    const vec4 C30 = vec4(1.0,  1.0, -0.5,  0.0);\n    const vec4 B60 = vec4(2.0,  0.5, -2.0, -0.5);\n    const vec4 C60 = vec4(2.0,  0.0, -1.0,  0.5);\n\n    const vec4 M45 = vec4(0.4,  0.4,  0.4,  0.4);\n    const vec4 M30 = vec4(0.2,  0.4,  0.2,  0.4);\n    const vec4 M60 = M30.yxwz;\n    const vec4 Mshift = vec4(0.2);\n\n    const float coef = 2.0; // Coefficient for weighted edge detection\n\n    const vec4 threshold = vec4(43.34); // Threshold for if luminance values are \"equal\"\n\n    const float colorMax = 255.0; // pallete colors only seem to have an effective RGB range of [0 - 252.0], should we use 252 or 255 as mult for lum?\n    // Conversion from RGB to Luminance (most accurate way I found so far)\n    const vec3 lum = vec3(0.241, 0.691, 0.068) * colorMax * colorMax; // openxcom uses original color pallete converted to RGB color, which is then converted to percentage [0.0 - 1.0]\n\n    /* Helper functions\n    */\n\n\n    bvec4 _and_(bvec4 A, bvec4 B) { // Performs same logic operation as && for vectors\n      return bvec4(A.x && B.x, A.y && B.y, A.z && B.z, A.w && B.w);\n    }\n\n    bvec4 _or_(bvec4 A, bvec4 B) { // Performs same logic operation as || for vectors\n      return bvec4(A.x || B.x, A.y || B.y, A.z || B.z, A.w || B.w);\n    }\n\n    float get_lum(vec3 v) { // returns approximated luminance value of a color\n      vec3 temp = vec3(v.x * v.x * lum.x, v.y * v.y * lum.y, v.z * v.z * lum.z);\n      return sqrt(temp.x + temp.y + temp.z);\n    }\n\n    vec4 RGBtoLum4(vec3 v0, vec3 v1, vec3 v2, vec3 v3) { // returns approximated luminance value of 4 colors\n      return vec4(get_lum(v0), get_lum(v1), get_lum(v2), get_lum(v3));\n    }\n\n    vec4 getLumDifference(vec4 A, vec4 B) { // Gets the difference between 2 4-value luminance vectors\n      return abs(A - B);\n    }\n\n    bvec4 lumClose2(vec4 A, vec4 B) { // Determines if 2 4-value luminance vectors are \"equal\" based on threshold\n      return lessThan(getLumDifference(A, B), threshold);\n    }\n\n    vec4 lum_wd(vec4 a, vec4 b, vec4 c, vec4 d, vec4 e, vec4 f, vec4 g, vec4 h) {\n      return getLumDifference(a, b) + getLumDifference(a, c) + getLumDifference(d, e) + getLumDifference(d, f) + 4.0 * getLumDifference(g, h);\n    }\n\n    bool colorsEqual2(vec3 A, vec3 B) { //returns true if the two RGB color vectors are equal\n         return all(equal(A, B));\n    }\n\n    bool colors3_eq(vec3 A, vec3 B, vec3 C) { //returns true if the four RGB color vectors are equal\n        return colorsEqual2(A, B) && colorsEqual2(B, C);\n    }\n\n    bool colorsEqual4(vec3 A, vec3 B, vec3 C, vec3 D) {  //returns true if the four RGB color vectors are equal\n        return colors3_eq(A, B, C) && colorsEqual2(C, D);\n    }\n\n    //bool colorsEqual5(vec3 A, vec3 B, vec3 C, vec3 D, vec3 E) { //returns true if the four RGB color vectors are equal\n    //    return colors3_eq(A, B, C) && colors3_eq(C, D, E);\n    //}\n\n    float colors2_Diff(vec3 c1, vec3 c2) { // Gets the difference between 2 3-value rgb colors\n      vec3 df = abs(c1 - c2);\n      return df.r + df.g + df.b;\n    }\n\n    void main() {\n      // Get mask values by performing texture lookup with the uniform sampler\n\n      /*\n      vec3 Ph1 = texture2D(rubyTexture, xyp_h1_h2_h3.xy).rgb;\n      vec3 Ph2 = texture2D(rubyTexture, xyp_h1_h2_h3.xz).rgb;\n      vec3 Ph3 = texture2D(rubyTexture, xyp_h1_h2_h3.xw).rgb;\n\n      vec3 Pg1 = texture2D(rubyTexture, xyp_g1_g2_g3.xw).rgb;\n      vec3 Pg2 = texture2D(rubyTexture, xyp_g1_g2_g3.yw).rgb;\n      vec3 Pg3 = texture2D(rubyTexture, xyp_g1_g2_g3.zw).rgb;\n\n      vec3 Pf1 = texture2D(rubyTexture, xyp_f1_f2_f3.xy).rgb;\n      vec3 Pf2 = texture2D(rubyTexture, xyp_f1_f2_f3.xz).rgb;\n      vec3 Pf3 = texture2D(rubyTexture, xyp_f1_f2_f3.xw).rgb;\n\n      vec3 Pe1 = texture2D(rubyTexture, xyp_e1_e2_e3.xw).rgb;\n      vec3 Pe2 = texture2D(rubyTexture, xyp_e1_e2_e3.yw).rgb;\n      vec3 Pe3 = texture2D(rubyTexture, xyp_e1_e2_e3.zw).rgb;\n\n      vec3 Pa  = texture2D(rubyTexture, xyp_a_b_c_d.xz ).rgb;\n      vec3 Pb  = texture2D(rubyTexture, xyp_a_b_c_d.yz ).rgb;\n      vec3 Pc  = texture2D(rubyTexture, xyp_a_b_c_d.xw ).rgb;\n      vec3 Pd  = texture2D(rubyTexture, xyp_a_b_c_d.yw ).rgb;\n      */\n      vec3 P1  = texture2D(rubyTexture, xyp_1_2_3.xw   ).rgb;\n      vec3 P2  = texture2D(rubyTexture, xyp_1_2_3.yw   ).rgb;\n      vec3 P3  = texture2D(rubyTexture, xyp_1_2_3.zw   ).rgb;\n\n      vec3 P6  = texture2D(rubyTexture, xyp_6_7_8.xw   ).rgb;\n      vec3 P7  = texture2D(rubyTexture, xyp_6_7_8.yw   ).rgb;\n      vec3 P8  = texture2D(rubyTexture, xyp_6_7_8.zw   ).rgb;\n\n      vec3 P11 = texture2D(rubyTexture, xyp_11_12_13.xw).rgb;\n      vec3 P12 = texture2D(rubyTexture, xyp_11_12_13.yw).rgb;\n      vec3 P13 = texture2D(rubyTexture, xyp_11_12_13.zw).rgb;\n\n      vec3 P16 = texture2D(rubyTexture, xyp_16_17_18.xw).rgb;\n      vec3 P17 = texture2D(rubyTexture, xyp_16_17_18.yw).rgb;\n      vec3 P18 = texture2D(rubyTexture, xyp_16_17_18.zw).rgb;\n\n      vec3 P21 = texture2D(rubyTexture, xyp_21_22_23.xw).rgb;\n      vec3 P22 = texture2D(rubyTexture, xyp_21_22_23.yw).rgb;\n      vec3 P23 = texture2D(rubyTexture, xyp_21_22_23.zw).rgb;\n\n      vec3 P5  = texture2D(rubyTexture, xyp_5_10_15.xy ).rgb;\n      vec3 P10 = texture2D(rubyTexture, xyp_5_10_15.xz ).rgb;\n      vec3 P15 = texture2D(rubyTexture, xyp_5_10_15.xw ).rgb;\n\n      vec3 P9  = texture2D(rubyTexture, xyp_9_14_9.xy  ).rgb;\n      vec3 P14 = texture2D(rubyTexture, xyp_9_14_9.xz  ).rgb;\n      vec3 P19 = texture2D(rubyTexture, xyp_9_14_9.xw  ).rgb;\n\n      /* Mask for algorhithm\n         -4x  -3x  -2x   -x    0    x   2x   3x   4x\n        +----+----+----+----+----+----+----+----+----+\n             |    |    |    |    |    |    |    |    | -4y\n        +----+----+----+----+----+----+----+----+----+\n             |    |    | e1 | e2 | e3 |    |    |    | -3y\n        +----+----+----+----+----+----+----+----+----+\n             |    |  a |  1 |  2 |  3 |  b |    |    | -2y\n        +----+----+----+----+----+----+----+----+----+\n             | h1 |  5 |  6 |  7 |  8 |  9 | f1 |    |  -y\n        +----+----+----+----+----+----+----+----+----+\n             | h2 | 10 | 11 | 12 | 13 | 14 | f2 |    |   0\n        +----+----+----+----+----+----+----+----+----+\n             | h3 | 15 | 16 | 17 | 18 | 19 | f3 |    |   y\n        +----+----+----+----+----+----+----+----+----+\n             |    |  c | 21 | 22 | 23 |  d |    |    |  2y\n        +----+----+----+----+----+----+----+----+----+\n             |    |    | g1 | g2 | g3 |    |    |    |  3y\n        +----+----+----+----+----+----+----+----+----+\n             |    |    |    |    |    |    |    |    |  4y\n        +----+----+----+----+----+----+----+----+----+\n      */\n\n      // Store luminance values of each point in groups of 4\n      // so that we may operate on all four corners at once\n      vec4 p7  = RGBtoLum4(P7,  P11, P17, P13);   // 45 - tight - 7 11 17 13\n      vec4 p8  = RGBtoLum4(P8,  P6,  P16, P18);   // 90 - tight - 8  6 16 18\n      vec4 p11 = p7.yzwx;                      // 45 - tight - 11 17 13 7 - duplicate\n      vec4 p12 = RGBtoLum4(P12, P12, P12, P12);   //  0 - center\n      vec4 p13 = p7.wxyz;                      // 45 - tight - 13 7 11 17 - duplicate\n      vec4 p14 = RGBtoLum4(P14, P2,  P10, P22);   // 45 - wide  - 14 2 10 22\n      vec4 p16 = p8.zwxy;                      // 90 - tight - 16 18 8  6 - duplicate\n      vec4 p17 = p7.zwxy;                      // 45 - tight - 17 13 7 11 - duplicate\n      vec4 p18 = p8.wxyz;                      // 90 - tight - 18  8 6 16 - duplicate\n      vec4 p19 = RGBtoLum4(P19, P3,  P5,  P21);   // 36 - wide  - 19  3 5 21\n      vec4 p22 = p14.wxyz;                     // 45 - wide  - 22 14 2 10 - duplicate\n      vec4 p23 = RGBtoLum4(P23, P9,  P1,  P15);   // 36 - wide  - 23 9  1 15\n\n      // Scale current texel coordinate to [0..1]\n      vec2 fp = fract(tc * rubyTextureSize);\n\n      // Determine amount of \"smoothing\" or mixing that could be done on texel corners\n      vec4 ma45 = smoothstep(C45 - M45, C45 + M45, Ai * fp.y + B45 * fp.x);\n      vec4 ma30 = smoothstep(C30 - M30, C30 + M30, Ai * fp.y + B30 * fp.x);\n      vec4 ma60 = smoothstep(C60 - M60, C60 + M60, Ai * fp.y + B60 * fp.x);\n      vec4 marn = smoothstep(C45 - M45 + Mshift, C45 + M45 + Mshift, Ai * fp.y + B45 * fp.x);\n\n      // Perform edge weight calculations\n      vec4 e45   = lum_wd(p12, p8, p16, p18, p22, p14, p17, p13);\n      vec4 econt = lum_wd(p17, p11, p23, p13, p7, p19, p12, p18);\n      vec4 e30   = getLumDifference(p13, p16);\n      vec4 e60   = getLumDifference(p8, p17);\n\n      // Calculate rule results for interpolation\n      bvec4 r45_1   = _and_(notEqual(p12, p13), notEqual(p12, p17));\n      bvec4 r45_2   = _and_(not(lumClose2(p13, p7)), not(lumClose2(p13, p8)));\n      bvec4 r45_3   = _and_(not(lumClose2(p17, p11)), not(lumClose2(p17, p16)));\n      bvec4 r45_4_1 = _and_(not(lumClose2(p13, p14)), not(lumClose2(p13, p19)));\n      bvec4 r45_4_2 = _and_(not(lumClose2(p17, p22)), not(lumClose2(p17, p23)));\n      bvec4 r45_4   = _and_(lumClose2(p12, p18), _or_(r45_4_1, r45_4_2));\n      bvec4 r45_5   = _or_(lumClose2(p12, p16), lumClose2(p12, p8));\n      bvec4 r45     = _and_(r45_1, _or_(_or_(_or_(r45_2, r45_3), r45_4), r45_5));\n      bvec4 r30     = _and_(notEqual(p12, p16), notEqual(p11, p16));\n      bvec4 r60     = _and_(notEqual(p12, p8), notEqual(p7, p8));\n\n      // Combine rules with edge weights\n      bvec4 edr45 = _and_(lessThan(e45, econt), r45);\n      bvec4 edrrn = lessThanEqual(e45, econt);\n      bvec4 edr30 = _and_(lessThanEqual(coef * e30, e60), r30);\n      bvec4 edr60 = _and_(lessThanEqual(coef * e60, e30), r60);\n\n      // Finalize interpolation rules and cast to float (0.0 for false, 1.0 for true)\n      vec4 final45 = vec4(_and_(_and_(not(edr30), not(edr60)), edr45));\n      vec4 final30 = vec4(_and_(_and_(edr45, not(edr60)), edr30));\n      vec4 final60 = vec4(_and_(_and_(edr45, not(edr30)), edr60));\n      vec4 final36 = vec4(_and_(_and_(edr60, edr30), edr45));\n      vec4 finalrn = vec4(_and_(not(edr45), edrrn));\n\n      // Determine the color to mix with for each corner\n      vec4 px = step(getLumDifference(p12, p17), getLumDifference(p12, p13));\n\n      /* Mask for algorhithm\n         -4x  -3x  -2x   -x    0    x   2x   3x   4x\n        +----+----+----+----+----+----+----+----+----+\n             |    |    |    |    |    |    |    |    | -4y\n        +----+----+----+----+----+----+----+----+----+\n             |    |    |Pe1 |Pe2 |Pe3 |    |    |    | -3y\n        +----+----+----+----+----+----+----+----+----+\n             |    | Pa | P1 | P2 | P3 | Pb |    |    | -2y\n        +----+----+----+----+----+----+----+----+----+\n             |Ph1 | P5 | P6 | P7 | P8 | P9 |Pf1 |    |  -y\n        +----+----+----+----+----+----+----+----+----+\n             |Ph2 |P10 |P11 |P12 |P13 |P14 |Pf2 |    |   0\n        +----+----+----+----+----+----+----+----+----+\n             |Ph3 |P15 |P16 |P17 |P18 |P19 |Pf3 |    |   y\n        +----+----+----+----+----+----+----+----+----+\n             |    | Pc |P21 |P22 |P23 | Pd |    |    |  2y\n        +----+----+----+----+----+----+----+----+----+\n             |    |    |Pg1 |Pg2 |Pg3 |    |    |    |  3y\n        +----+----+----+----+----+----+----+----+----+\n             |    |    |    |    |    |    |    |    |  4y\n        +----+----+----+----+----+----+----+----+----+\n      */\n\n      // XCom Excuclsion Rule 1 = Geoscape: cities, bases, terror sites, ufos\n\n      bool exclusionRule = !(((all(equal(P6 , ex1_Cyan1))  || all(equal(P6 , ex1_Cyan2))) && any(notEqual(P12, P6)) && (colorsEqual4(P6, P8, P16, P18))) || // Gooey base center\n                              (all(equal(P12, ex1_Yellow)) && all(equal(P7, ex1_Red1))    &&  all(equal(P7, P17)))  || // juicy yellow center\n                              (all(equal(P12, ex1_Red1))   || all(equal(P12, ex1_Red2)))  ||   // all red (cities, terror sites, ufos)\n                              (all(equal(P17, ex1_Red1))   || all(equal(P17, ex1_Red2)))  || // above red top\n                              (all(equal(P7 , ex1_Red1))   || all(equal(P7, ex1_Red2)))   || // below red bottom (\n                              (all(equal(P13, ex1_Red1))   || all(equal(P13, ex1_Red2)))  || // left of red\n                              (all(equal(P11, ex1_Red1))   || all(equal(P11, ex1_Red2)))  || // right of red\n                              (all(equal(P12, ex1_Cyan1))  || all(equal(P12, ex1_Cyan2))) || // base\n                              (all(equal(P11, ex_Pink1))   || all(equal(P11, ex_Pink2))   || all(equal(P13 , ex_Pink1)) || all(equal(P13, ex_Pink2))) || // terror site pink (all around)\n                              (all(equal(P7 , ex_Pink1))   || all(equal(P7 , ex_Pink2))   || all(equal(P17 , ex_Pink1)) || all(equal(P17, ex_Pink2)))\n                            );\n\n      // Determine the mix amounts by combining the final rule result and correspondingix amount for the rule in each corner\n      vec4 mac = (final36 * max(ma30, ma60) + final30 * ma30 + final60 * ma60 + final45 * ma45 + finalrn * marn) * float(exclusionRule);\n\n      /* Calculate the resulting color by traversing clockwise and counter-clockwise around the corners of the texel.\n         Finally choose the result that has the largest difference from the texel's original color.\n      */\n      vec3 res1 = P12;\n      res1 = mix(res1, mix(P13, P17, px.x), mac.x);\n      res1 = mix(res1, mix(P7, P13, px.y), mac.y);\n      res1 = mix(res1, mix(P11, P7, px.z), mac.z);\n      res1 = mix(res1, mix(P17, P11, px.w), mac.w);\n\n      vec3 res2 = P12;\n      res2 = mix(res2, mix(P17, P11, px.w), mac.w);\n      res2 = mix(res2, mix(P11, P7, px.z), mac.z);\n      res2 = mix(res2, mix(P7, P13, px.y), mac.y);\n      res2 = mix(res2, mix(P13, P17, px.x), mac.x);\n\n      gl_FragColor = vec4(vec3(mix(res1, res2, step(colors2_Diff(P12, res1), colors2_Diff(P12, res2)))), 1.0);\n    }\n"
  },
  {
    "path": "bin/common/Shaders/SABR.OpenGL.shader",
    "content": "#<!--\n#   SABR v3.0 Shader\n#\n#   Copyright (C) 2012 Joshua Street\n#   Copyright (C) 2011, 2012 Hyllian/Jararaca - sergiogdb@gmail.com\n#   Copyright (C) 2012 crazy46guy (GLSL conversion)\n#\n#   Portions of this algorithm were taken from Hyllian's 5xBR v3.7c\n#   shader.\n#\n#   This program is free software; you can redistribute it and/or\n#   modify it under the terms of the GNU General Public License\n#   as published by the Free Software Foundation; either version 2\n#   of the License, or (at your option) any later version.\n#\n#   This program is distributed in the hope that it will be useful,\n#   but WITHOUT ANY WARRANTY; without even the implied warranty of\n#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n#   GNU General Public License for more details.\n#\n#   You should have received a copy of the GNU General Public License\n#   along with this program; if not, write to the Free Software\n#   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n#\n#-->\nlanguage: \"GLSL\"\nvertex: |\n    uniform vec2 rubyTextureSize;\n\n    varying vec2 tc;\n    varying vec4 xyp_1_2_3;\n    varying vec4 xyp_5_10_15;\n    varying vec4 xyp_6_7_8;\n    varying vec4 xyp_9_14_9;\n    varying vec4 xyp_11_12_13;\n    varying vec4 xyp_16_17_18;\n    varying vec4 xyp_21_22_23;\n\n    void main() {\n      gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n\n      float x = 1.0 / rubyTextureSize.x;\n      float y = 1.0 / rubyTextureSize.y;\n\n\n\n      /*\n        Mask for algorhithm\n        +-----+-----+-----+-----+-----+\n        |     |  1  |  2  |  3  |     |\n        +-----+-----+-----+-----+-----+\n        |  5  |  6  |  7  |  8  |  9  |\n        +-----+-----+-----+-----+-----+\n        | 10  | 11  | 12  | 13  | 14  |\n        +-----+-----+-----+-----+-----+\n        | 15  | 16  | 17  | 18  | 19  |\n        +-----+-----+-----+-----+-----+\n        |     | 21  | 22  | 23  |     |\n        +-----+-----+-----+-----+-----+\n      */\n\n      tc = gl_MultiTexCoord0.xy;\n\n      xyp_1_2_3    = tc.xxxy + vec4(      -x, 0.0,   x, -2.0 * y);\n      xyp_6_7_8    = tc.xxxy + vec4(      -x, 0.0,   x,       -y);\n      xyp_11_12_13 = tc.xxxy + vec4(      -x, 0.0,   x,      0.0);\n      xyp_16_17_18 = tc.xxxy + vec4(      -x, 0.0,   x,        y);\n      xyp_21_22_23 = tc.xxxy + vec4(      -x, 0.0,   x,  2.0 * y);\n      xyp_5_10_15  = tc.xyyy + vec4(-2.0 * x,  -y, 0.0,        y);\n      xyp_9_14_9   = tc.xyyy + vec4( 2.0 * x,  -y, 0.0,        y);\n    }\nlinear: false\nfragment: |\n    /*\n      Uniforms\n      - rubyTexture: texture sampler\n      - rubyTextureSize: size of the texture before rendering\n    */\n    uniform sampler2D rubyTexture;\n    uniform vec2 rubyTextureSize;\n\n    /*\n      Varying attributes\n      - tc: coordinate of the texel being processed\n      - xyp_[]_[]_[]: a packed coordinate for 3 areas within the texture\n    */\n    varying vec2 tc;\n    varying vec4 xyp_1_2_3;\n    varying vec4 xyp_5_10_15;\n    varying vec4 xyp_6_7_8;\n    varying vec4 xyp_9_14_9;\n    varying vec4 xyp_11_12_13;\n    varying vec4 xyp_16_17_18;\n    varying vec4 xyp_21_22_23;\n\n    /*\n      Constants\n    */\n    /*\n      Inequation coefficients for interpolation\n        Equations are in the form: Ay + Bx = C\n        45, 30, and 60 denote the angle from x each line the cooeficient variable set builds\n    */\n    const vec4 Ai  = vec4( 1.0, -1.0, -1.0,  1.0);\n    const vec4 B45 = vec4( 1.0,  1.0, -1.0, -1.0);\n    const vec4 C45 = vec4( 1.5,  0.5, -0.5,  0.5);\n    const vec4 B30 = vec4( 0.5,  2.0, -0.5, -2.0);\n    const vec4 C30 = vec4( 1.0,  1.0, -0.5,  0.0);\n    const vec4 B60 = vec4( 2.0,  0.5, -2.0, -0.5);\n    const vec4 C60 = vec4( 2.0,  0.0, -1.0,  0.5);\n\n    const vec4 M45 = vec4(0.4, 0.4, 0.4, 0.4);\n    const vec4 M30 = vec4(0.2, 0.4, 0.2, 0.4);\n    const vec4 M60 = M30.yxwz;\n    const vec4 Mshift = vec4(0.2);\n\n    // Coefficient for weighted edge detection\n    const float coef = 2.0;\n    // Threshold for if luminance values are \"equal\"\n    const vec4 threshold = vec4(0.32);\n\n    // Conversion from RGB to Luminance (from GIMP)\n    const vec3 lum = vec3(0.21, 0.72, 0.07);\n\n    // Performs same logic operation as && for vectors\n    bvec4 _and_(bvec4 A, bvec4 B) {\n      return bvec4(A.x && B.x, A.y && B.y, A.z && B.z, A.w && B.w);\n    }\n\n    // Performs same logic operation as || for vectors\n    bvec4 _or_(bvec4 A, bvec4 B) {\n      return bvec4(A.x || B.x, A.y || B.y, A.z || B.z, A.w || B.w);\n    }\n\n    // Converts 4 3-color vectors into 1 4-value luminance vector\n    vec4 lum_to(vec3 v0, vec3 v1, vec3 v2, vec3 v3) {\n      return vec4(dot(lum, v0), dot(lum, v1), dot(lum, v2), dot(lum, v3));\n    }\n\n    // Gets the difference between 2 4-value luminance vectors\n    vec4 lum_df(vec4 A, vec4 B) {\n      return abs(A - B);\n    }\n\n    // Determines if 2 4-value luminance vectors are \"equal\" based on threshold\n    bvec4 lum_eq(vec4 A, vec4 B) {\n      return lessThan(lum_df(A, B), threshold);\n    }\n\n    vec4 lum_wd(vec4 a, vec4 b, vec4 c, vec4 d, vec4 e, vec4 f, vec4 g, vec4 h) {\n      return lum_df(a, b) + lum_df(a, c) + lum_df(d, e) + lum_df(d, f) + 4.0 * lum_df(g, h);\n    }\n\n    // Gets the difference between 2 3-value rgb colors\n    float c_df(vec3 c1, vec3 c2) {\n      vec3 df = abs(c1 - c2);\n      return df.r + df.g + df.b;\n    }\n\n    void main() {\n      /*\n        Mask for algorhithm\n        +-----+-----+-----+-----+-----+\n        |     |  1  |  2  |  3  |     |\n        +-----+-----+-----+-----+-----+\n        |  5  |  6  |  7  |  8  |  9  |\n        +-----+-----+-----+-----+-----+\n        | 10  | 11  | 12  | 13  | 14  |\n        +-----+-----+-----+-----+-----+\n        | 15  | 16  | 17  | 18  | 19  |\n        +-----+-----+-----+-----+-----+\n        |     | 21  | 22  | 23  |     |\n        +-----+-----+-----+-----+-----+\n      */\n      // Get mask values by performing texture lookup with the uniform sampler\n      vec3 P1  = texture2D(rubyTexture, xyp_1_2_3.xw   ).rgb;\n      vec3 P2  = texture2D(rubyTexture, xyp_1_2_3.yw   ).rgb;\n      vec3 P3  = texture2D(rubyTexture, xyp_1_2_3.zw   ).rgb;\n\n      vec3 P6  = texture2D(rubyTexture, xyp_6_7_8.xw   ).rgb;\n      vec3 P7  = texture2D(rubyTexture, xyp_6_7_8.yw   ).rgb;\n      vec3 P8  = texture2D(rubyTexture, xyp_6_7_8.zw   ).rgb;\n\n      vec3 P11 = texture2D(rubyTexture, xyp_11_12_13.xw).rgb;\n      vec3 P12 = texture2D(rubyTexture, xyp_11_12_13.yw).rgb;\n      vec3 P13 = texture2D(rubyTexture, xyp_11_12_13.zw).rgb;\n\n      vec3 P16 = texture2D(rubyTexture, xyp_16_17_18.xw).rgb;\n      vec3 P17 = texture2D(rubyTexture, xyp_16_17_18.yw).rgb;\n      vec3 P18 = texture2D(rubyTexture, xyp_16_17_18.zw).rgb;\n\n      vec3 P21 = texture2D(rubyTexture, xyp_21_22_23.xw).rgb;\n      vec3 P22 = texture2D(rubyTexture, xyp_21_22_23.yw).rgb;\n      vec3 P23 = texture2D(rubyTexture, xyp_21_22_23.zw).rgb;\n\n      vec3 P5  = texture2D(rubyTexture, xyp_5_10_15.xy ).rgb;\n      vec3 P10 = texture2D(rubyTexture, xyp_5_10_15.xz ).rgb;\n      vec3 P15 = texture2D(rubyTexture, xyp_5_10_15.xw ).rgb;\n\n      vec3 P9  = texture2D(rubyTexture, xyp_9_14_9.xy  ).rgb;\n      vec3 P14 = texture2D(rubyTexture, xyp_9_14_9.xz  ).rgb;\n      vec3 P19 = texture2D(rubyTexture, xyp_9_14_9.xw  ).rgb;\n\n      // Store luminance values of each point in groups of 4\n      // so that we may operate on all four corners at once\n      vec4 p7  = lum_to(P7,  P11, P17, P13);\n      vec4 p8  = lum_to(P8,  P6,  P16, P18);\n      vec4 p11 = p7.yzwx;                      // P11, P17, P13, P7\n      vec4 p12 = lum_to(P12, P12, P12, P12);\n      vec4 p13 = p7.wxyz;                      // P13, P7,  P11, P17\n      vec4 p14 = lum_to(P14, P2,  P10, P22);\n      vec4 p16 = p8.zwxy;                      // P16, P18, P8,  P6\n      vec4 p17 = p7.zwxy;                      // P17, P13, P7,  P11\n      vec4 p18 = p8.wxyz;                      // P18, P8,  P6,  P16\n      vec4 p19 = lum_to(P19, P3,  P5,  P21);\n      vec4 p22 = p14.wxyz;                     // P22, P14, P2,  P10\n      vec4 p23 = lum_to(P23, P9,  P1,  P15);\n\n      // Scale current texel coordinate to [0..1]\n      vec2 fp = fract(tc * rubyTextureSize);\n\n      // Determine amount of \"smoothing\" or mixing that could be done on texel corners\n      vec4 ma45 = smoothstep(C45 - M45, C45 + M45, Ai * fp.y + B45 * fp.x);\n      vec4 ma30 = smoothstep(C30 - M30, C30 + M30, Ai * fp.y + B30 * fp.x);\n      vec4 ma60 = smoothstep(C60 - M60, C60 + M60, Ai * fp.y + B60 * fp.x);\n      vec4 marn = smoothstep(C45 - M45 + Mshift, C45 + M45 + Mshift, Ai * fp.y + B45 * fp.x);\n\n      // Perform edge weight calculations\n      vec4 e45   = lum_wd(p12, p8, p16, p18, p22, p14, p17, p13);\n      vec4 econt = lum_wd(p17, p11, p23, p13, p7, p19, p12, p18);\n      vec4 e30   = lum_df(p13, p16);\n      vec4 e60   = lum_df(p8, p17);\n\n      // Calculate rule results for interpolation\n      bvec4 r45_1   = _and_(notEqual(p12, p13), notEqual(p12, p17));\n      bvec4 r45_2   = _and_(not(lum_eq(p13, p7)), not(lum_eq(p13, p8)));\n      bvec4 r45_3   = _and_(not(lum_eq(p17, p11)), not(lum_eq(p17, p16)));\n      bvec4 r45_4_1 = _and_(not(lum_eq(p13, p14)), not(lum_eq(p13, p19)));\n      bvec4 r45_4_2 = _and_(not(lum_eq(p17, p22)), not(lum_eq(p17, p23)));\n      bvec4 r45_4   = _and_(lum_eq(p12, p18), _or_(r45_4_1, r45_4_2));\n      bvec4 r45_5   = _or_(lum_eq(p12, p16), lum_eq(p12, p8));\n      bvec4 r45     = _and_(r45_1, _or_(_or_(_or_(r45_2, r45_3), r45_4), r45_5));\n      bvec4 r30 = _and_(notEqual(p12, p16), notEqual(p11, p16));\n      bvec4 r60 = _and_(notEqual(p12, p8), notEqual(p7, p8));\n\n      // Combine rules with edge weights\n      bvec4 edr45 = _and_(lessThan(e45, econt), r45);\n      bvec4 edrrn = lessThanEqual(e45, econt);\n      bvec4 edr30 = _and_(lessThanEqual(coef * e30, e60), r30);\n      bvec4 edr60 = _and_(lessThanEqual(coef * e60, e30), r60);\n\n      // Finalize interpolation rules and cast to float (0.0 for false, 1.0 for true)\n      vec4 final45 = vec4(_and_(_and_(not(edr30), not(edr60)), edr45));\n      vec4 final30 = vec4(_and_(_and_(edr45, not(edr60)), edr30));\n      vec4 final60 = vec4(_and_(_and_(edr45, not(edr30)), edr60));\n      vec4 final36 = vec4(_and_(_and_(edr60, edr30), edr45));\n      vec4 finalrn = vec4(_and_(not(edr45), edrrn));\n\n      // Determine the color to mix with for each corner\n      vec4 px = step(lum_df(p12, p17), lum_df(p12, p13));\n\n      // Determine the mix amounts by combining the final rule result and corresponding\n      // mix amount for the rule in each corner\n      vec4 mac = final36 * max(ma30, ma60) + final30 * ma30 + final60 * ma60 + final45 * ma45 + finalrn * marn;\n\n      /*\n        Calculate the resulting color by traversing clockwise and counter-clockwise around\n        the corners of the texel\n\n        Finally choose the result that has the largest difference from the texel's original\n        color\n      */\n      vec3 res1 = P12;\n      res1 = mix(res1, mix(P13, P17, px.x), mac.x);\n      res1 = mix(res1, mix(P7, P13, px.y), mac.y);\n      res1 = mix(res1, mix(P11, P7, px.z), mac.z);\n      res1 = mix(res1, mix(P17, P11, px.w), mac.w);\n\n      vec3 res2 = P12;\n      res2 = mix(res2, mix(P17, P11, px.w), mac.w);\n      res2 = mix(res2, mix(P11, P7, px.z), mac.z);\n      res2 = mix(res2, mix(P7, P13, px.y), mac.y);\n      res2 = mix(res2, mix(P13, P17, px.x), mac.x);\n\n      gl_FragColor = vec4(mix(res1, res2, step(c_df(P12, res1), c_df(P12, res2))), 1.0);\n    }\n"
  },
  {
    "path": "bin/common/Shaders/Scale2x.OpenGL.shader",
    "content": "language: \"GLSL\"\nvertex: |\n    uniform vec2 rubyTextureSize;\n\n    void main() {\n      vec4 offsetx;\n      vec4 offsety;\n\n      gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n\n      offsetx.x = 1.0 / rubyTextureSize.x;\n      offsetx.y = 0.0;\n      offsetx.w = 0.0;\n      offsetx.z = 0.0;\n      offsety.y = 1.0 / rubyTextureSize.y;\n      offsety.x = 0.0;\n      offsety.w = 0.0;\n      offsety.z = 0.0;\n\n      gl_TexCoord[0] = gl_MultiTexCoord0;         //center\n      gl_TexCoord[1] = gl_TexCoord[0] - offsetx;  //left\n      gl_TexCoord[2] = gl_TexCoord[0] + offsetx;  //right\n      gl_TexCoord[3] = gl_TexCoord[0] - offsety;  //top\n      gl_TexCoord[4] = gl_TexCoord[0] + offsety;  //bottom\n    }\nfragment: |\n    uniform sampler2D rubyTexture;\n    uniform vec2 rubyTextureSize;\n\n    void main() {\n      vec4 colD, colF, colB, colH, col, tmp;\n      vec2 sel;\n\n      col  = texture2DProj(rubyTexture, gl_TexCoord[0]);  //central (can be E0-E3)\n      colD = texture2DProj(rubyTexture, gl_TexCoord[1]);  //D (left)\n      colF = texture2DProj(rubyTexture, gl_TexCoord[2]);  //F (right)\n      colB = texture2DProj(rubyTexture, gl_TexCoord[3]);  //B (top)\n      colH = texture2DProj(rubyTexture, gl_TexCoord[4]);  //H (bottom)\n\n      sel = fract(gl_TexCoord[0].xy * rubyTextureSize.xy);       //where are we (E0-E3)?\n                                                                 //E0 is default\n      if(sel.y >= 0.5) { tmp = colB; colB = colH; colH = tmp; }  //E1 (or E3): swap B and H\n      if(sel.x >= 0.5) { tmp = colF; colF = colD; colD = tmp; }  //E2 (or E3): swap D and F\n\n      if(colB == colD && colB != colF && colD != colH) {  //do the Scale2x rule\n        col = colD;\n      }\n\n      gl_FragColor = col;\n    }\nlinear: false"
  },
  {
    "path": "bin/common/Shaders/Scale4xHQ.OpenGL.shader",
    "content": "#<!--\n#   4xGLSLHqFilter shader\n#\n#   Copyright (C) 2005 guest(r) - guest.r@gmail.com\n#\n#   This program is free software; you can redistribute it and/or\n#   modify it under the terms of the GNU General Public License\n#   as published by the Free Software Foundation; either version 2\n#   of the License, or (at your option) any later version.\n#\n#   This program is distributed in the hope that it will be useful,\n#   but WITHOUT ANY WARRANTY; without even the implied warranty of\n#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#   GNU General Public License for more details.\n#\n#   You should have received a copy of the GNU General Public License\n#   along with this program; if not, write to the Free Software\n#   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\n#\n#-->\nlanguage: \"GLSL\"\nvertex: |\n        uniform vec2 rubyTextureSize;\n\n        void main()\n        {\n                float x = 0.001;\n                float y = 0.001;\n\n                vec2 dg1 = vec2( x,y);  vec2 dg2 = vec2(-x,y);\n                vec2 sd1 = dg1*0.5;     vec2 sd2 = dg2*0.5;\n                vec2 ddx = vec2(x,0.0); vec2 ddy = vec2(0.0,y);\n\n                gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n                gl_TexCoord[0] = gl_MultiTexCoord0;\n                gl_TexCoord[1].xy = gl_TexCoord[0].xy - sd1;\n                gl_TexCoord[2].xy = gl_TexCoord[0].xy - sd2;\n                gl_TexCoord[3].xy = gl_TexCoord[0].xy + sd1;\n                gl_TexCoord[4].xy = gl_TexCoord[0].xy + sd2;\n                gl_TexCoord[5].xy = gl_TexCoord[0].xy - dg1;\n                gl_TexCoord[6].xy = gl_TexCoord[0].xy + dg1;\n                gl_TexCoord[5].zw = gl_TexCoord[0].xy - dg2;\n                gl_TexCoord[6].zw = gl_TexCoord[0].xy + dg2;\n                gl_TexCoord[1].zw = gl_TexCoord[0].xy - ddy;\n                gl_TexCoord[2].zw = gl_TexCoord[0].xy + ddx;\n                gl_TexCoord[3].zw = gl_TexCoord[0].xy + ddy;\n                gl_TexCoord[4].zw = gl_TexCoord[0].xy - ddx;\n        }\nfragment: |\n        uniform sampler2D rubyTexture;\n\n        const float mx = 1.00;      // start smoothing wt.\n        const float k = -1.10;      // wt. decrease factor\n        const float max_w = 0.75;   // max filter weigth\n        const float min_w = 0.03;   // min filter weigth\n        const float lum_add = 0.33; // effects smoothing\n\n        void main()\n        {\n                vec3 c  = texture2D(rubyTexture, gl_TexCoord[0].xy).xyz;\n                vec3 i1 = texture2D(rubyTexture, gl_TexCoord[1].xy).xyz;\n                vec3 i2 = texture2D(rubyTexture, gl_TexCoord[2].xy).xyz;\n                vec3 i3 = texture2D(rubyTexture, gl_TexCoord[3].xy).xyz;\n                vec3 i4 = texture2D(rubyTexture, gl_TexCoord[4].xy).xyz;\n                vec3 o1 = texture2D(rubyTexture, gl_TexCoord[5].xy).xyz;\n                vec3 o3 = texture2D(rubyTexture, gl_TexCoord[6].xy).xyz;\n                vec3 o2 = texture2D(rubyTexture, gl_TexCoord[5].zw).xyz;\n                vec3 o4 = texture2D(rubyTexture, gl_TexCoord[6].zw).xyz;\n                vec3 s1 = texture2D(rubyTexture, gl_TexCoord[1].zw).xyz;\n                vec3 s2 = texture2D(rubyTexture, gl_TexCoord[2].zw).xyz;\n                vec3 s3 = texture2D(rubyTexture, gl_TexCoord[3].zw).xyz;\n                vec3 s4 = texture2D(rubyTexture, gl_TexCoord[4].zw).xyz;\n                vec3 dt = vec3(1.0,1.0,1.0);\n\n                float ko1=dot(abs(o1-c),dt);\n                float ko2=dot(abs(o2-c),dt);\n                float ko3=dot(abs(o3-c),dt);\n                float ko4=dot(abs(o4-c),dt);\n\n                float k1=min(dot(abs(i1-i3),dt),max(ko1,ko3));\n                float k2=min(dot(abs(i2-i4),dt),max(ko2,ko4));\n\n                float w1 = k2; if(ko3<ko1) w1*=ko3/ko1;\n                float w2 = k1; if(ko4<ko2) w2*=ko4/ko2;\n                float w3 = k2; if(ko1<ko3) w3*=ko1/ko3;\n                float w4 = k1; if(ko2<ko4) w4*=ko2/ko4;\n\n                c=(w1*o1+w2*o2+w3*o3+w4*o4+0.001*c)/(w1+w2+w3+w4+0.001);\n\n                w1 = k*dot(abs(i1-c)+abs(i3-c),dt)/(0.125*dot(i1+i3,dt)+lum_add);\n                w2 = k*dot(abs(i2-c)+abs(i4-c),dt)/(0.125*dot(i2+i4,dt)+lum_add);\n                w3 = k*dot(abs(s1-c)+abs(s3-c),dt)/(0.125*dot(s1+s3,dt)+lum_add);\n                w4 = k*dot(abs(s2-c)+abs(s4-c),dt)/(0.125*dot(s2+s4,dt)+lum_add);\n\n                w1 = clamp(w1+mx,min_w,max_w);\n                w2 = clamp(w2+mx,min_w,max_w);\n                w3 = clamp(w3+mx,min_w,max_w);\n                w4 = clamp(w4+mx,min_w,max_w);\n\n                gl_FragColor.xyz=(w1*(i1+i3)+w2*(i2+i4)+w3*(s1+s3)+w4*(s2+s4)+c)/(2.0*(w1+w2+w3+w4)+1.0);\n                gl_FragColor.a = 1.0;\n        }\nlinear: false\n"
  },
  {
    "path": "bin/common/Shaders/dot_n_bloom.OpenGL.shader",
    "content": "#<!--\n#     Dot 'n bloom shader\n#     Author: Themaister\n#     License: Public domain\n#-->\nlanguage: GLSL\nvertex: |\n      varying vec2 c00;\n      varying vec2 c10;\n      varying vec2 c20;\n      varying vec2 c01;\n      varying vec2 c11;\n      varying vec2 c21;\n      varying vec2 c02;\n      varying vec2 c12;\n      varying vec2 c22;\n      varying vec2 pixel_no;\n      uniform vec2 rubyTextureSize;\n      uniform vec2 rubyOutputSize;\n      uniform vec2 rubyInputSize;\n\n      void main()\n      {\n         gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n         float dx = 1.0 / rubyTextureSize.x;\n         float dy = 1.0 / rubyTextureSize.y;\n\n         vec2 tex = gl_MultiTexCoord0.xy;\n         c00 = tex + vec2(-dx, -dy);\n         c10 = tex + vec2(  0, -dy);\n         c20 = tex + vec2( dx, -dy);\n         c01 = tex + vec2(-dx,   0);\n         c11 = tex + vec2(  0,   0);\n         c21 = tex + vec2( dx,   0);\n         c02 = tex + vec2(-dx,  dy);\n         c12 = tex + vec2(  0,  dy);\n         c22 = tex + vec2( dx,  dy);\n         pixel_no = tex * rubyTextureSize;\n      }\nlinear: false\nfragment: |\n      uniform vec2 rubyTextureSize;\n      uniform sampler2D rubyTexture;\n      varying vec2 c00;\n      varying vec2 c10;\n      varying vec2 c20;\n      varying vec2 c01;\n      varying vec2 c11;\n      varying vec2 c21;\n      varying vec2 c02;\n      varying vec2 c12;\n      varying vec2 c22;\n      varying vec2 pixel_no;\n\n      const float gamma = 2.4;\n      const float shine = 0.50;\n      const float blend = 0.25;\n\n      float dist(vec2 coord, vec2 source)\n      {\n         vec2 delta = coord - source;\n         return sqrt(dot(delta, delta));\n      }\n\n      float color_bloom(vec3 color)\n      {\n         const vec3 gray_coeff = vec3(0.30, 0.59, 0.11);\n         float bright = dot(color, gray_coeff);\n         return mix(1.0 + shine, 1.0 - shine, bright);\n      }\n\n      vec3 lookup(float offset_x, float offset_y, vec2 coord)\n      {\n         vec2 offset = vec2(offset_x, offset_y);\n         vec3 color = texture2D(rubyTexture, coord).rgb;\n         float delta = dist(fract(pixel_no), offset + vec2(0.5));\n         return color * exp(-gamma * delta * color_bloom(color));\n      }\n\n      void main()\n      {\n         vec3 mid_color = lookup(0.0, 0.0, c11);\n         vec3 color = vec3(0.0);\n         color += lookup(-1.0, -1.0, c00);\n         color += lookup( 0.0, -1.0, c10);\n         color += lookup( 1.0, -1.0, c20);\n         color += lookup(-1.0,  0.0, c01);\n         color += mid_color;\n         color += lookup( 1.0,  0.0, c21);\n         color += lookup(-1.0,  1.0, c02);\n         color += lookup( 0.0,  1.0, c12);\n         color += lookup( 1.0,  1.0, c22);\n         vec3 out_color = mix(1.2 * mid_color, color, blend);\n\n         gl_FragColor = vec4(out_color, 1.0);\n      }\n"
  },
  {
    "path": "bin/common/Shaders/heavybloom.OpenGL.shader",
    "content": "#<!--\n#WhateverMan's Bloom Shader\n#Copyright (c) 2010 WhateverMan\n#\n#This program is free software; you can redistribute it and/or\n#modify it under the terms of the GNU General Public License\n#as published by the Free Software Foundation; either version 2\n#of the License, or (at your option) any later version.\n#\n#This program is distributed in the hope that it will be useful,\n#but WITHOUT ANY WARRANTY; without even the implied warranty of\n#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#GNU General Public License for more details.\n#\n#You should have received a copy of the GNU General Public License\n#along with this program; if not, write to the Free Software\n#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\n#-->\nlanguage: \"GLSL\"\nvertex: |\n      void main()\n      {\n         gl_Position    = ftransform();\n         gl_TexCoord[0] = gl_MultiTexCoord0;\n      }\nlinear: false\nfragment: |\n      uniform sampler2D texture;\n      #define glarebasesize 0.42\n      #define power 0.50 // 0.50 is good\n\n      uniform vec2 rubyTextureSize;\n\n      void main()\n      {\n         vec4 sum = vec4(0.0);\n         vec4 bum = vec4(0.0);\n         vec2 texcoord = vec2(gl_TexCoord[0]);\n         int j;\n         int i;\n\n         vec2 glaresize = vec2(glarebasesize) / rubyTextureSize;\n\n         for(i = -2; i < 5; i++)\n         {\n            for (j = -1; j < 1; j++)\n            {\n               sum += texture2D(texture, texcoord + vec2(-i, j)*glaresize) * power;\n               bum += texture2D(texture, texcoord + vec2(j, i)*glaresize) * power;\n            }\n         }\n\n         if (texture2D(texture, texcoord).r < 2.0)\n         {\n            gl_FragColor = sum*sum*sum*0.001+bum*bum*bum*0.0080 + texture2D(texture, texcoord);\n         }\n      }\n"
  },
  {
    "path": "bin/common/Shaders/scanline-3x.OpenGL.shader",
    "content": "# <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n# <!--\n    # Scanline 3x Shader\n    # Copyright (C) 2011 hunterk\n\n# This program is free software; you can redistribute it and/or\n# modify it under the terms of the GNU General Public License\n# as published by the Free Software Foundation; either version 2\n# of the License, or (at your option) any later version.\n\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n\n# You should have received a copy of the GNU General Public License\n# along with this program; if not, write to the Free Software\n# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\n\n# This shader works best at scale 3x or else the pixels don't match up correctly.\n# -->\nlanguage: \"GLSL\"\nvertex: |\n    void main(void) {\n      gl_Position = ftransform();\n      gl_TexCoord[0] = gl_MultiTexCoord0;\n    }\nfragment: |\n    uniform sampler2D rubyTexture;\n\n    void main(void) {\n      vec4 rgb = texture2D(rubyTexture, gl_TexCoord[0].xy);\n      vec4 intens ;\n      if (fract(gl_FragCoord.y * (0.5*4.0/3.0)) > 0.5)\n        intens = vec4(0);\n        else\n        intens = smoothstep(0.2,0.8,rgb) + normalize(vec4(rgb.xyz, 1.0));\n        float level = (4.0-gl_TexCoord[0].z) * 0.19;\n      gl_FragColor = intens * (0.5-level) + rgb * 1.1 ;\n    }\nlinear: false"
  },
  {
    "path": "bin/common/Shaders/scanline-4x.OpenGL.shader",
    "content": "# <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n# <!--\n    # Scanline 4x Shader\n    # Copyright (C) 2011 hunterk\n\n# This program is free software; you can redistribute it and/or\n# modify it under the terms of the GNU General Public License\n# as published by the Free Software Foundation; either version 2\n# of the License, or (at your option) any later version.\n\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n\n# You should have received a copy of the GNU General Public License\n# along with this program; if not, write to the Free Software\n# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\n\n# This shader works best at scale 4x or else the pixels don't match up correctly.\n# -->\nlanguage: \"GLSL\"\nvertex: |\n    void main(void) {\n      gl_Position = ftransform();\n      gl_TexCoord[0] = gl_MultiTexCoord0;\n    }\nfragment: |\n    uniform sampler2D rubyTexture;\n\n    void main(void) {\n      vec4 rgb = texture2D(rubyTexture, gl_TexCoord[0].xy);\n      vec4 intens ;\n      if (fract(gl_FragCoord.y * 0.25) > 0.5)\n        intens = vec4(0);\n        else\n        intens = smoothstep(0.2,0.8,rgb) + normalize(vec4(rgb.xyz, 1.0));\n        float level = (4.0-gl_TexCoord[0].z) * 0.19;\n      gl_FragColor = intens * (0.5-level) + rgb * 1.1 ;\n    }\nlinear: false\n"
  },
  {
    "path": "bin/common/Shaders/simplebloom.OpenGL.shader",
    "content": "#<!--\n#WhateverMan's Bloom Shader\n#Copyright (c) 2010 WhateverMan\n#\n#This program is free software; you can redistribute it and/or\n#modify it under the terms of the GNU General Public License\n#as published by the Free Software Foundation; either version 2\n#of the License, or (at your option) any later version.\n#\n#This program is distributed in the hope that it will be useful,\n#but WITHOUT ANY WARRANTY; without even the implied warranty of\n#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#GNU General Public License for more details.\n#\n#You should have received a copy of the GNU General Public License\n#along with this program; if not, write to the Free Software\n#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\n#-->\nlanguage: \"GLSL\"\nvertex: |\n      void main()\n      {\n         gl_Position    = ftransform();\n         gl_TexCoord[0] = gl_MultiTexCoord0;\n      }\nlinear: false\nfragment: |\n      uniform sampler2D texture;\n      #define glarebasesize 0.896\n      #define power 0.65 // 0.50 is good\n\n      uniform vec2 rubyTextureSize;\n\n      void main()\n      {\n         vec4 sum = vec4(0.0);\n         vec4 bum = vec4(0.0);\n         vec2 texcoord = vec2(gl_TexCoord[0]);\n         int j;\n         int i;\n\n         vec2 glaresize = vec2(glarebasesize) / rubyTextureSize;\n\n         for(i = -2; i < 2; i++)\n         {\n            for (j = -1; j < 1; j++)\n            {\n               sum += texture2D(texture, texcoord + vec2(-i, j)*glaresize) * power;\n               bum += texture2D(texture, texcoord + vec2(j, i)*glaresize) * power;\n            }\n         }\n\n         if (texture2D(texture, texcoord).r < 2.0)\n         {\n            gl_FragColor = sum*sum*sum*0.001+bum*bum*bum*0.0080 + texture2D(texture, texcoord);\n         }\n      }\n"
  },
  {
    "path": "bin/common/SoldierName/American.nam",
    "content": "lookWeights:\n  - 30\n  - 30\n  - 20\n  - 20\nmaleFirst:\n  - Aaron\n  - Adam\n  - Adrian\n  - Alfredo\n  - Austin\n  - Brandon\n  - Brian\n  - Calvin\n  - Carl\n  - Chance\n  - Charlie\n  - Clarence\n  - Cody\n  - Connor\n  - Damian\n  - Donald\n  - Dwight\n  - Dylan\n  - Ed\n  - Eduardo\n  - Elliott\n  - Ethan\n  - Evan\n  - Ezekiel\n  - Garrett\n  - George\n  - Giovanni\n  - Grayson\n  - James\n  - Jason\n  - Jay\n  - Jeremy\n  - Joel\n  - John\n  - Joshua\n  - Keith\n  - Kevin\n  - Lester\n  - Liam\n  - Mark\n  - Omar\n  - Oscar\n  - Owen\n  - Parker\n  - Pete\n  - Rick\n  - Robert\n  - Samuel\n  - Santiago\n  - Saul\n  - Scott\n  - Seth\n  - Shawn\n  - Simon\n  - Spencer\n  - Steven\n  - Timothy\n  - Tom\n  - Tucker\n  - Victor\n  - Vincent\n  - Virgil\nfemaleFirst:\n  - Adriana\n  - Alexandra\n  - Alexis\n  - Allison\n  - Angela\n  - Anna\n  - Audrey\n  - Barbara\n  - Bethany\n  - Brianna\n  - Cadence\n  - Catherine\n  - Chelsea\n  - Chloe\n  - Cora\n  - Denise\n  - Esperanza\n  - Esther\n  - Evelyn\n  - Faith\n  - Gabrielle\n  - Georgia\n  - Guadalupe\n  - Isabel\n  - Jasmine\n  - Jillian\n  - Julia\n  - Kaitlyn\n  - Kara\n  - Karen\n  - Kelly\n  - Layla\n  - Lily\n  - Lucy\n  - Madeline\n  - Madison\n  - Margaret\n  - Maria\n  - Melanie\n  - Melissa\n  - Mia\n  - Michelle\n  - Miranda\n  - Olivia\n  - Paige\n  - Patricia\n  - Reese\n  - Riley\n  - Sarah\n  - Savannah\n  - Selena\n  - Sigourney\n  - Taylor\n  - Tiffany\n  - Vanessa\n  - Violet\n  - Zoey\nmaleLast:\n  - Becker\n  - Benedict\n  - Bowers\n  - Bradley\n  - Brewster\n  - Bryant\n  - Burroughs\n  - Carlton\n  - Carr\n  - Carter\n  - Chase\n  - Childers\n  - Colby\n  - Crawley\n  - Crossett\n  - Daley\n  - Davies\n  - Dodge\n  - Evans\n  - Gallagher\n  - Gates\n  - Goddard\n  - Grady\n  - Griffith\n  - Gutierrez\n  - Harding\n  - Harper\n  - Hicks\n  - Horton\n  - Hudson\n  - Hunt\n  - Johnson\n  - Kay\n  - Kellogg\n  - Kemp\n  - Kendrick\n  - King\n  - Kirk\n  - Lawson\n  - Machado\n  - McNeil\n  - Meador\n  - Miller\n  - Mitchell\n  - Morris\n  - Nash\n  - North\n  - O'Connell\n  - Ortiz\n  - Palacios\n  - Partridge\n  - Patrick\n  - Perkins\n  - Porter\n  - Prewitt\n  - Rapp\n  - Ritchie\n  - Rooney\n  - Rossi\n  - Salomon\n  - Scroggins\n  - Shelley\n  - Smiley\n  - Sorensen\n  - Stein\n  - Stephens\n  - Stoddard\n  - Thompson\n  - Tirado\n  - Underwood\n  - Wade\n  - Wagner\n  - Webb\n"
  },
  {
    "path": "bin/common/SoldierName/Arabic.nam",
    "content": "lookWeights:\n  - 0\n  - 1\n  - 99\n  - 0\nmaleFirst:\n  - Abdullah\n  - Abu\n  - Ahmed\n  - Ali\n  - Bilal\n  - Fadil\n  - Farid\n  - Faysal\n  - Ghassan\n  - Habib\n  - Hakim\n  - Hassan\n  - Ibrahim\n  - Khalid\n  - Mahmoud\n  - Muhammad\n  - Najib\n  - Nasir\n  - Omar\n  - Rashid\n  - Tariq\n  - Yusuf\nfemaleFirst:\n  - Alia\n  - Amirah\n  - Asma\n  - Farah\n  - Fatima\n  - Ghaliya\n  - Hafsa\n  - Haniya\n  - Iman\n  - Jalila\n  - Jawahir\n  - Karima\n  - Laila\n  - Latifa\n  - Malaika\n  - Maryam\n  - Mona\n  - Nadia\n  - Noor\n  - Rafiqa\n  - Samira\n  - Sumayya\nmaleLast:\n  - Abdullah\n  - Ahmed\n  - El-Amin\n  - Hakim\n  - Hussain\n  - Karim\n  - Muhammad\n  - Sultan\n  - Qureshi\n  - Malouf\n  - Hajjar\n  - Asaf\n  - Khouri\n  - Tahan\n  - Wasem\n  - Mustafa\n  - Hadad\n  - Kanaan\n  - Islam\n  - Nasri\n  - Kassab\n  - Ibrahim\n"
  },
  {
    "path": "bin/common/SoldierName/Argentina.nam",
    "content": "lookWeights:\n  - 30\n  - 88\n  - 4\n  - 20\nmaleFirst:\n  - Agustin\n  - Alberto\n  - Alejandro\n  - Alejo\n  - Andres\n  - Angel\n  - Antonio\n  - Argentino\n  - Bautista\n  - Beto\n  - Benjamin\n  - Carlos\n  - Cesar\n  - Che\n  - Cholo\n  - Daniel\n  - Dario\n  - David\n  - Diego\n  - Eduardo\n  - Eladio\n  - Elias\n  - Enrique\n  - Enzo\n  - Emanuel\n  - Ernesto\n  - Esteban\n  - Ezequiel\n  - Fabio\n  - Felipe\n  - Fernando\n  - Fidel\n  - Francisco\n  - Gabriel\n  - Geronimo\n  - Gonzalo\n  - Hipolito\n  - Hugo\n  - Humberto\n  - Ignacio\n  - Ivan\n  - Javier\n  - Jesus\n  - Joaquin\n  - Joel\n  - Jorge\n  - Jose\n  - Juan\n  - Julian\n  - Julio\n  - Lalo\n  - Leo\n  - Leonardo\n  - Lionel\n  - Lucas\n  - Luis\n  - Manuel\n  - Marcos\n  - Martin\n  - Matias\n  - Mateo\n  - Mauro\n  - Maxi\n  - Miguel\n  - Nacho\n  - Nestor\n  - Nico\n  - Nicolas\n  - Octavio\n  - Oscar\n  - Oso\n  - Pablo\n  - Pedro\n  - Pepe\n  - Rafael\n  - Ramon\n  - Raul\n  - Rene\n  - Ricardo\n  - Roberto\n  - Rolo\n  - Salvador\n  - Santiago\n  - Santino\n  - Sebastian\n  - Sergio\n  - Stefano\n  - Teo\n  - Tito\n  - Tomas\n  - Valentin\n  - Valentino\n  - Vicentino\n  - Victor\n  - Walter\nfemaleFirst:\n  - Adriana\n  - Aida\n  - Alejandra\n  - Alina\n  - Alma\n  - Ana\n  - Angela\n  - Angelica\n  - Aurora\n  - Barbara\n  - Beatriz\n  - Brenda\n  - Carina\n  - Carla\n  - Carolina\n  - Casandra\n  - Catalina\n  - Claudia\n  - Cristina\n  - Dolores\n  - Dora\n  - Elda\n  - Elena\n  - Eliana\n  - Emma\n  - Esmeralda\n  - Eugenia\n  - Eva\n  - Felicia\n  - Gabriela\n  - Gloria\n  - Guada\n  - Ines\n  - Isabel\n  - Jesica\n  - Juana\n  - Justina\n  - Karen\n  - Laura\n  - Lidia\n  - Liliana\n  - Linda\n  - Lisa\n  - Lorena\n  - Malena\n  - Marcela\n  - Margarita\n  - Maria\n  - Mariana\n  - Marisol\n  - Martina\n  - Micaela\n  - Mirta\n  - Monica\n  - Nadia\n  - Nancy\n  - Natalia\n  - Noemi\n  - Olivia\n  - Patricia\n  - Paulina\n  - Raquel\n  - Romina\n  - Rosa\n  - Sofia\n  - Sol\n  - Sonia\n  - Susana\n  - Talia\n  - Tatiana\n  - Teresa\n  - Vanesa\n  - Veronica\n  - Victoria\n  - Vilma\n  - Yolanda\nmaleLast:\n  - Aguilar\n  - Alcaraz\n  - Alonso\n  - Alvarado\n  - Alvarez\n  - Avila\n  - Barrios\n  - Calderon\n  - Campos\n  - Castelar\n  - Castellanos\n  - Cervantes\n  - Chavez\n  - Cortez\n  - Cruz\n  - Culasso\n  - Diaz\n  - Dominguez\n  - Escobar\n  - Falcioni\n  - Fernandez\n  - Figueroa\n  - Flores\n  - Forni\n  - Fuentes\n  - Gallo\n  - Garcia\n  - Gili\n  - Gomez\n  - Gonzalez\n  - Guerrero\n  - Gutierrez\n  - Guzman\n  - Hernandez\n  - Herrera\n  - Jimenez\n  - Juarez\n  - Legrand\n  - Lescano\n  - Lima\n  - Lopez\n  - Loyola\n  - Lucerna\n  - Luna\n  - Macri\n  - Martinez\n  - Medina\n  - Mejia\n  - Mendez\n  - Mendoza\n  - Miranda\n  - Montero\n  - Montes\n  - Morales\n  - Moreno\n  - Munoz\n  - Navarro\n  - Nunez\n  - Ortega\n  - Ortiz\n  - Pacheco\n  - Pairola\n  - Perez\n  - Ramirez\n  - Ramos\n  - Reyes\n  - Rios\n  - Rivera\n  - Rodriguez\n  - Romero\n  - Rosso\n  - Ruffener\n  - Ruiz\n  - Sanchez\n  - Sandoval\n  - SantaCruz\n  - Santana\n  - Santos\n  - Sosa\n  - Spesso\n  - Suarez\n  - Tapia\n  - Torres\n  - Trejo\n  - Troglio\n  - Trucco\n  - Valdez\n  - Vasquez\n  - Vega\n  - Velasquez\n  - Visintini\n \n"
  },
  {
    "path": "bin/common/SoldierName/Belgium.nam",
    "content": "# Simplified: Belgium has two main languages regions, the\n# Flemish(Dutch) speaking part and the Walloon(French) speaking region.\n# This difference is reflected in the names. I used the 60% Flemish vs 40% French\n# ratio\n# Distribution of lastNames can be visualised at http://www.familienaam.be\n# 12 Flemish/8 French (names from statbel.fgov.be)\nlookWeights:\n  - 70\n  - 28\n  - 1\n  - 1\nmaleFirst:\n  - Nathan\n  - Wouter\n  - Seppe\n  - Robbe\n  - Kobe\n  - Bart\n  - Ruben\n  - Mark\n  - David\n  - Jef\n  - Emiel\n  - Lowie\n  - Pierre\n  - Victor\n  - Jules\n  - Leo\n  - Mathieu\n  - Emilien\n  - Bastien\n  - Quentin\nfemaleFirst:\n  - Lotte\n  - Kato\n  - Julie\n  - Noor\n  - Els\n  - Wendy\n  - Laura\n  - Sarah\n  - Charlotte\n  - Emma\n  - Marie\n  - Lisa\n  - Clara\n  - Emma\n  - Elise\n  - Louise\n  - Ines\n  - Justine\n  - Laura\n  - Lucie\nmaleLast:\n  - Peeters\n  - Janssens\n  - Maes\n  - Jacobs\n  - Willems\n  - Mertens\n  - Claes\n  - Wouters\n  - Goossens\n  - De Smet\n  - Vermeulen\n  - Pauwels\n  - Dubois\n  - Lambert\n  - Martin\n  - Dupont\n  - Simon\n  - Leclercq\n  - Leroy\n  - Lejeune\n\n"
  },
  {
    "path": "bin/common/SoldierName/British.nam",
    "content": "lookWeights:\n  - 35\n  - 35\n  - 20\n  - 10\nmaleFirst:\n  - Adam\n  - Adrian\n  - Aidan\n  - Alan\n  - Alexander\n  - Alistair\n  - Andrew\n  - Arthur\n  - Ben\n  - Benjamin\n  - Bradley\n  - Brendan\n  - Brett\n  - Bruce\n  - Carl\n  - Charles\n  - Charlie\n  - Christopher\n  - Colin\n  - Connor\n  - Craig\n  - Damien\n  - Daniel\n  - David\n  - Declan\n  - Derek\n  - Desmond\n  - Donald\n  - Dylan\n  - Edmund\n  - Edward\n  - Euan\n  - Frank\n  - Francis\n  - Gareth\n  - Gary\n  - Geoffrey\n  - George\n  - Graeme\n  - Graham\n  - Grant\n  - Gregor\n  - Gregory\n  - Hamish\n  - Harold\n  - Harry\n  - Ian\n  - Iain\n  - James\n  - Jason\n  - John\n  - Jordan\n  - Keith\n  - Ken\n  - Kenneth\n  - Lewis\n  - Liam\n  - Malcolm\n  - Mark\n  - Michael\n  - Neil\n  - Patrick\n  - Paul\n  - Peter\n  - Raymond\n  - Rhys\n  - Richard\n  - Robert\n  - Rory\n  - Roy\n  - Ryan\n  - Samuel\n  - Scott\n  - Simon\n  - Stephen\n  - Steven\n  - Thomas\n  - William\nfemaleFirst:\n  - Abigail\n  - Aileen\n  - Ailsa\n  - Alice\n  - Alison\n  - Amy\n  - Andrea\n  - Ann\n  - Anna\n  - Annabel\n  - Anne\n  - Bridget\n  - Carol\n  - Catherine\n  - Clara\n  - Claire\n  - Clare\n  - Courtney\n  - Cynthia\n  - Eleanor\n  - Elizabeth\n  - Emily\n  - Emma\n  - Fiona\n  - Frances\n  - Gail\n  - Gemma\n  - Gillian\n  - Gilly\n  - Grace\n  - Hanna\n  - Hannah\n  - Harriet\n  - Heather\n  - Helen\n  - Holly\n  - Isabel\n  - Isobel\n  - Isla\n  - Jade\n  - Jane\n  - Janet\n  - Janice\n  - Janine\n  - Jayne\n  - Jean\n  - Jenna\n  - Jennifer\n  - Jenny\n  - Jessica\n  - Jill\n  - Joyce\n  - Kate\n  - Katie\n  - Kimberley\n  - Kirsten\n  - Kirsty\n  - Kylie\n  - Lauren\n  - Lesley\n  - Leslie\n  - Lilleth\n  - Lillian\n  - Lindsay\n  - Lisa\n  - Lorna\n  - Lucy\n  - Lynn\n  - Lynette\n  - Margaret\n  - Maria\n  - Mary\n  - Megan\n  - Moira\n  - Murron\n  - Patricia\n  - Rebecca\n  - Samantha\n  - Sarah\n  - Shannon\n  - Siobhan\n  - Stacey\n  - Theresa\n  - Victoria\nmaleLast:\n  - Adams\n  - Anderson\n  - Atkinson\n  - Bailey\n  - Baird\n  - Baker\n  - Barker\n  - Ball\n  - Barnes\n  - Bell\n  - Blake\n  - Blair\n  - Boyd\n  - Brook\n  - Brooks\n  - Brown\n  - Burns\n  - Butler\n  - Cameron\n  - Carter\n  - Chapman\n  - Clark\n  - Clarke\n  - Clyde\n  - Cole\n  - Collins\n  - Cook\n  - Cooper\n  - Cox\n  - Davies\n  - Davis\n  - Dawson\n  - Day\n  - Dixon\n  - Douglas\n  - Drummond\n  - Elliot\n  - Erskine\n  - Evans\n  - Ferguson\n  - Fisher\n  - Fletcher\n  - Forbes\n  - Ford\n  - Forsythe\n  - Foster\n  - Fox\n  - Fraser\n  - Garrow\n  - Gibson\n  - Gray\n  - Green\n  - Hall\n  - Harris\n  - Harrison\n  - Harvey\n  - Heaton\n  - Hill\n  - Holmes\n  - Howard\n  - Hughes\n  - Hunt\n  - Hunter\n  - Jackson\n  - Jenkins\n  - Johnson\n  - Jones\n  - Jonlan\n  - Kerr\n  - King\n  - Knight\n  - Knox\n  - Lawrence\n  - Lee\n  - Lennox\n  - Loy\n  - MacCallum\n  - MacCay\n  - MacColl\n  - MacIntyre\n  - Mackendrick\n  - Mackenzie\n  - MacRae\n  - Marion\n  - Marshall\n  - Martin\n  - Mason\n  - Matthews\n  - Middleton\n  - Milne\n  - Mills\n  - Mitchell\n  - Moore\n  - Mumford\n  - Owen\n  - Owens\n  - Paddon\n  - Parker\n  - Palmer\n  - Payne\n  - Pearce\n  - Pearson\n  - Peters\n  - Peterson\n  - Powell\n  - Price\n  - Pritchard\n  - Ramsay\n  - Reynolds\n  - Richards\n  - Richardson\n  - Roberts\n  - Robertson\n  - Robinson\n  - Rogers\n  - Rory\n  - Ross\n  - Rowe\n  - Russell\n  - Saunders\n  - Sharpe\n  - Shaw\n  - Smith\n  - Stevens\n  - Stewart\n  - Taylor\n  - Thompson\n  - Turner\n  - Varley\n  - Walker\n  - Wallace\n  - Walsh\n  - Ward\n  - Watson\n  - Webb\n  - West\n  - White\n  - Wilkinson\n  - Williams\n  - Wright\n  - Wood\n  - Young\n  - Yates\n"
  },
  {
    "path": "bin/common/SoldierName/Bulgarian.nam",
    "content": "lookWeights:\n  - 50\n  - 50\n  - 0\n  - 0\nmaleFirst:\n  - Aleksandar\n  - Andon\n  - Andrey\n  - Andrian\n  - Anton\n  - Antoni\n  - Angel\n  - Apostol\n  - Atanas\n  - Bogdan\n  - Bogomil\n  - Borislav\n  - Boyko\n  - Damyan\n  - Danail\n  - Desislav\n  - Dimitar\n  - Dragomir\n  - Gavrail\n  - Georgi\n  - Hristo\n  - Ilian\n  - Iliya\n  - Ivan\n  - Ivaylo\n  - Ivo\n  - Kaloyan\n  - Kiril\n  - Konstantin\n  - Krasimir\n  - Krastyo\n  - Lyuben\n  - Lyubomir\n  - Lyudmil\n  - Marko\n  - Miroslav\n  - Momchil\n  - Nikola\n  - Ognyan\n  - Penko\n  - Petar\n  - Plamen\n  - Radomir\n  - Samuil\n  - Spas\n  - Stanimir\n  - Stanislav\n  - Stoyan\n  - Teodor\n  - Tihomir\n  - Todor\n  - Toma\n  - Tsvetan\n  - Vasil\n  - Ventsislav\n  - Viktor\n  - Vladimir\n  - Vladislav\n  - Yanko\n  - Yoan\n  - Yordan\n  - Yosif\n  - Zahari\n  - Zhivko\n  - Zlatko\nfemaleFirst:\n  - Ana\n  - Antonia\n  - Bilyana\n  - Bisera\n  - Bogomila\n  - Borislava\n  - Boyana\n  - Desislava\n  - Elisaveta\n  - Emiliya\n  - Gergana\n  - Hristina\n  - Iva\n  - Ivana\n  - Ivelina\n  - Ivet\n  - Izabela\n  - Krasimira\n  - Lidiya\n  - Lilyana\n  - Lyubina\n  - Lyubomira\n  - Lyudmila\n  - Maya\n  - Mirela\n  - Miroslava\n  - Nadejda\n  - Nevena\n  - Nikolina\n  - Pavla\n  - Pavlina\n  - Radomira\n  - Radoslava\n  - Radostina\n  - Rayna\n  - Rosa\n  - Rositsa\n  - Silviya\n  - Simona\n  - Snezhana\n  - Sofiya\n  - Stanislava\n  - Stanka\n  - Stoyanka\n  - Svetla\n  - Svetlana\n  - Tanya\n  - Tatyana\n  - Teodora\n  - Tereza\n  - Tsveta\n  - Tsvetelina\n  - Veselina\n  - Viktoria\n  - Violeta\n  - Vladimira\n  - Yana\n  - Yoana\n  - Yordanka\nmaleLast:\n  - Aleksandrov\n  - Andonov\n  - Andreev\n  - Antonov\n  - Antoniev\n  - Angelov\n  - Apostolov\n  - Atanasov\n  - Bogdanov\n  - Bogomilov\n  - Borislavov\n  - Boykov\n  - Damyanov\n  - Danailov\n  - Desislavov\n  - Dimitrov\n  - Dragomirov\n  - Gavrailov\n  - Georgiev\n  - Hristov\n  - Ilianov\n  - Iliev\n  - Ivanov\n  - Ivaylov\n  - Kaloyan\n  - Kirilov\n  - Konstantinov\n  - Krasimirov\n  - Lyubenov\n  - Lyubomirov\n  - Lyudmilov\n  - Markov\n  - Miroslavov\n  - Momchilov\n  - Nikolaev\n  - Ognyanov\n  - Penkov\n  - Petrov\n  - Plamenov\n  - Radomirov\n  - Samuilov\n  - Spasov\n  - Stanimirov\n  - Stanislavov\n  - Stoyanov\n  - Teodorov\n  - Tihomirov\n  - Todorov\n  - Tomov\n  - Tsvetanov\n  - Vasilev\n  - Ventsislavov\n  - Vladimirov\n  - Vladislavov\n  - Yordanov\n  - Yosifov\n  - Zahariev\n  - Zhivkov\n  - Zlatkov\nfemaleLast:\n  - Aleksandrova\n  - Andonova\n  - Andreeva\n  - Antonova\n  - Antonieva\n  - Angelova\n  - Apostolova\n  - Atanasova\n  - Bogdanova\n  - Bogomilova\n  - Borislavova\n  - Boykova\n  - Damyanova\n  - Danailova\n  - Desislavova\n  - Dimitrova\n  - Dragomirova\n  - Gavrailova\n  - Georgieva\n  - Hristova\n  - Ilianova\n  - Ilieva\n  - Ivanova\n  - Ivaylova\n  - Kaloyana\n  - Kirilova\n  - Konstantinova\n  - Krasimirova\n  - Lyubenova\n  - Lyubomirova\n  - Lyudmilova\n  - Markova\n  - Miroslavova\n  - Momchilova\n  - Nikolaeva\n  - Ognyanova\n  - Penkova\n  - Petrova\n  - Plamenova\n  - Radomirova\n  - Samuilova\n  - Stanimirova\n  - Stanislavova\n  - Stoyanova\n  - Stoykova\n  - Teodorova\n  - Tihomirova\n  - Todorova\n  - Tomova\n  - Tsvetanova\n  - Vasileva\n  - Ventsislavova\n  - Vladimirova\n  - Vladislavova\n  - Yordanova\n  - Yosifova\n  - Zaharieva\n  - Zhivkova\n  - Zlatkov\n  - Petrova\n  - Popova\n  - Romanova\n  - Semyonova\n  - Sergeeva\n  - Smirnova\n  - Sokolova\n  - Solovyova\n  - Stepanova\n  - Vasilyeva\n  - Volkova\n  - Vorobyova\n  - Yakovleva\n  - Zaitseva\n  - Zaharova\n"
  },
  {
    "path": "bin/common/SoldierName/Chinese.nam",
    "content": "# Note: \"first\" names here are family names, \"last\" names are given names.\nlookWeights:\n  - 1\n  - 1\n  - 93\n  - 5\nmaleFirst:\n  - An\n  - Ang\n  - Ao\n  - Au\n  - Au Yeung\n  - Bai\n  - Ban\n  - Bao\n  - Bau\n  - Bi\n  - Bo\n  - Bu\n  - Cai\n  - Cao\n  - Cha\n  - Chai\n  - Cham\n  - Chan\n  - Chang\n  - Chao\n  - Chau\n  - Che\n  - Cheah\n  - Chee\n  - Chen\n  - Cheng\n  - Cheong\n  - Chern\n  - Cheung\n  - Chew\n  - Chi\n  - Chia\n  - Chiang\n  - Chiao\n  - Chien\n  - Chim\n  - Chin\n  - Ching\n  - Chiong\n  - Chiou\n  - Chiu\n  - Cho\n  - Choi\n  - Chong\n  - Choo\n  - Chou\n  - Chow\n  - Choy\n  - Chu\n  - Chua\n  - Cheang\n  - Chui\n  - Chun\n  - Chung\n  - Cong\n  - Cui\n  - Dai\n  - Dang\n  - Dea\n  - Deng\n  - Ding\n  - Do\n  - Dong\n  - Doo\n  - Du\n  - Duan\n  - Dung\n  - Eng\n  - Fan\n  - Fang\n  - Fei\n  - Feng\n  - Fok\n  - Fong\n  - Foo\n  - Fu\n  - Fung\n  - Gan\n  - Gang\n  - Gao\n  - Gau\n  - Ge\n  - Geng\n  - Go\n  - Goh\n  - Gong\n  - Gu\n  - Guan\n  - Guo\n  - Ha\n  - Hai\n  - Han\n  - Hang\n  - Hao\n  - Hau\n  - He\n  - Ho\n  - Hoh\n  - Hom\n  - Hon\n  - Hong\n  - Hoo\n  - Hou\n  - Hsi\n  - Hsia\n  - Hsiao\n  - Hsieh\n  - Hsiung\n  - Hsu\n  - Hsueh\n  - Hu\n  - Hua\n  - Huang\n  - Hui\n  - Huie\n  - Hum\n  - Hung\n  - Huo\n  - Hwang\n  - Hy\n  - Ing\n  - Ip\n  - Jan\n  - Jang\n  - Jen\n  - Jeng\n  - Jeung\n  - Jew\n  - Ji\n  - Jia\n  - Jian\n  - Jiang\n  - Jiao\n  - Jim\n  - Jin\n  - Jing\n  - Jo\n  - Joe\n  - Jong\n  - Joo\n  - Jou\n  - Jow\n  - Ju\n  - Jue\n  - Jung\n  - Kam\n  - Kan\n  - Kang\n  - Kao\n  - Kau\n  - Ke\n  - Keng\n  - Kho\n  - Khoo\n  - Kiang\n  - King\n  - Ko\n  - Koh\n  - Kong\n  - Koo\n  - Kook\n  - Kou\n  - Ku\n  - Kuan\n  - Kuang\n  - Kuk\n  - Kung\n  - Kuang\n  - Kuo\n  - Kwan\n  - Kwock\n  - Kwok\n  - Kwon\n  - Kwong\n  - Lai\n  - Lam\n  - Lan\n  - Lang\n  - Lao\n  - Lau\n  - Lee\n  - Lei\n  - Leng\n  - Leong\n  - Leung\n  - Lew\n  - Li\n  - Lian\n  - Liang\n  - Liao\n  - Liaw\n  - Lien\n  - Liew\n  - Lim\n  - Lin\n  - Ling\n  - Liou\n  - Liu\n  - Lo\n  - Loh\n  - Lok\n  - Long\n  - Loo\n  - Lou\n  - Louie\n  - Lu\n  - Lua\n  - Lui\n  - Luk\n  - Lum\n  - Lung\n  - Luo\n  - Ma\n  - Mah\n  - Mai\n  - Mak\n  - Man\n  - Mao\n  - Mar\n  - Mau\n  - May\n  - Mei\n  - Meng\n  - Miao\n  - Min\n  - Ming\n  - Miu\n  - Mo\n  - Mok\n  - Mon\n  - Mou\n  - Moy\n  - Mu\n  - Mui\n  - Na\n  - Ng\n  - Ngai\n  - Ngan\n  - Ngo\n  - Ni\n  - Nie\n  - Ning\n  - Niu\n  - On\n  - Ong\n  - Ou\n  - Ou Yang\n  - Ow\n  - Owyang\n  - Pan\n  - Pang\n  - Pao\n  - Pei\n  - Peng\n  - Pi\n  - Ping\n  - Po\n  - Pon\n  - Pong\n  - Poon\n  - Pu\n  - Pun\n  - Qi\n  - Qian\n  - Qiao\n  - Qin\n  - Qiu\n  - Qu\n  - Quan\n  - Que\n  - Rao\n  - Ren\n  - Rong\n  - Ruan\n  - Sam\n  - San\n  - Sang\n  - Seto\n  - Sha\n  - Sham\n  - Shan\n  - Shang\n  - Shao\n  - Shaw\n  - Shek\n  - Shen\n  - Sheng\n  - Sheu\n  - Shi\n  - Shiau\n  - Shieh\n  - Shih\n  - Shing\n  - Shiu\n  - Shu\n  - Shum\n  - Shy\n  - Shyu\n  - Si\n  - Sieh\n  - Sin\n  - Sing\n  - Sit\n  - Situ\n  - Siu\n  - So\n  - Soh\n  - Song\n  - Soo\n  - Soo Hoo\n  - Soon\n  - Soong\n  - Su\n  - Suen\n  - Sui\n  - Sum\n  - Sun\n  - Sung\n  - Sze\n  - Szeto\n  - Tai\n  - Tam\n  - Tan\n  - Tang\n  - Tao\n  - Tay\n  - Te\n  - Teh\n  - Teng\n  - Teo\n  - Tian\n  - Tien\n  - Tin\n  - Ting\n  - Tiu\n  - To\n  - Toh\n  - Tom\n  - Tong\n  - Tsai\n  - Tsang\n  - Tsao\n  - Tsay\n  - Tse\n  - Tseng\n  - Tso\n  - Tsoi\n  - Tsou\n  - Tsu\n  - Tsui\n  - Tu\n  - Tuan\n  - Tung\n  - Tzeng\n  - U\n  - Un\n  - Ung\n  - Wah\n  - Wai\n  - Wan\n  - Wang\n  - Wee\n  - Wei\n  - Wen\n  - Weng\n  - Wing\n  - Wong\n  - Woo\n  - Woon\n  - Wu\n  - Xi\n  - Xia\n  - Xiang\n  - Xiao\n  - Xie\n  - Xin\n  - Xing\n  - Xiong\n  - Xu\n  - Xue\n  - Yam\n  - Yan\n  - Yang\n  - Yao\n  - Yap\n  - Yau\n  - Yaw\n  - Ye\n  - Yee\n  - Yeh\n  - Yen\n  - Yep\n  - Yeung\n  - Yi\n  - Yim\n  - Yin\n  - Ying\n  - Yip\n  - Yiu\n  - Yong\n  - Yoo\n  - Yoon\n  - You\n  - Young\n  - Yu\n  - Yuan\n  - Yue\n  - Yuen\n  - Yun\n  - Yung\n  - Zang\n  - Zeng\n  - Zha\n  - Zhan\n  - Zhang\n  - Zhao\n  - Zhen\n  - Zheng\n  - Zhong\n  - Zhou\n  - Zhu\n  - Zhuang\n  - Zhuo\n  - Zong\n  - Zou\nfemaleFirst:\n  - An\n  - Ang\n  - Ao\n  - Au\n  - Au Yeung\n  - Bai\n  - Ban\n  - Bao\n  - Bau\n  - Bi\n  - Bo\n  - Bu\n  - Cai\n  - Cao\n  - Cha\n  - Chai\n  - Cham\n  - Chan\n  - Chang\n  - Chao\n  - Chau\n  - Che\n  - Cheah\n  - Chee\n  - Chen\n  - Cheng\n  - Cheong\n  - Chern\n  - Cheung\n  - Chew\n  - Chi\n  - Chia\n  - Chiang\n  - Chiao\n  - Chien\n  - Chim\n  - Chin\n  - Ching\n  - Chiong\n  - Chiou\n  - Chiu\n  - Cho\n  - Choi\n  - Chong\n  - Choo\n  - Chou\n  - Chow\n  - Choy\n  - Chu\n  - Chua\n  - Cheang\n  - Chui\n  - Chun\n  - Chung\n  - Cong\n  - Cui\n  - Dai\n  - Dang\n  - Dea\n  - Deng\n  - Ding\n  - Do\n  - Dong\n  - Doo\n  - Du\n  - Duan\n  - Dung\n  - Eng\n  - Fan\n  - Fang\n  - Fei\n  - Feng\n  - Fok\n  - Fong\n  - Foo\n  - Fu\n  - Fung\n  - Gan\n  - Gang\n  - Gao\n  - Gau\n  - Ge\n  - Geng\n  - Go\n  - Goh\n  - Gong\n  - Gu\n  - Guan\n  - Guo\n  - Ha\n  - Hai\n  - Han\n  - Hang\n  - Hao\n  - Hau\n  - He\n  - Ho\n  - Hoh\n  - Hom\n  - Hon\n  - Hong\n  - Hoo\n  - Hou\n  - Hsi\n  - Hsia\n  - Hsiao\n  - Hsieh\n  - Hsiung\n  - Hsu\n  - Hsueh\n  - Hu\n  - Hua\n  - Huang\n  - Hui\n  - Huie\n  - Hum\n  - Hung\n  - Huo\n  - Hwang\n  - Hy\n  - Ing\n  - Ip\n  - Jan\n  - Jang\n  - Jen\n  - Jeng\n  - Jeung\n  - Jew\n  - Ji\n  - Jia\n  - Jian\n  - Jiang\n  - Jiao\n  - Jim\n  - Jin\n  - Jing\n  - Jo\n  - Joe\n  - Jong\n  - Joo\n  - Jou\n  - Jow\n  - Ju\n  - Jue\n  - Jung\n  - Kam\n  - Kan\n  - Kang\n  - Kao\n  - Kau\n  - Ke\n  - Keng\n  - Kho\n  - Khoo\n  - Kiang\n  - King\n  - Ko\n  - Koh\n  - Kong\n  - Koo\n  - Kook\n  - Kou\n  - Ku\n  - Kuan\n  - Kuang\n  - Kuk\n  - Kung\n  - Kuang\n  - Kuo\n  - Kwan\n  - Kwock\n  - Kwok\n  - Kwon\n  - Kwong\n  - Lai\n  - Lam\n  - Lan\n  - Lang\n  - Lao\n  - Lau\n  - Lee\n  - Lei\n  - Leng\n  - Leong\n  - Leung\n  - Lew\n  - Li\n  - Lian\n  - Liang\n  - Liao\n  - Liaw\n  - Lien\n  - Liew\n  - Lim\n  - Lin\n  - Ling\n  - Liou\n  - Liu\n  - Lo\n  - Loh\n  - Lok\n  - Long\n  - Loo\n  - Lou\n  - Louie\n  - Lu\n  - Lua\n  - Lui\n  - Luk\n  - Lum\n  - Lung\n  - Luo\n  - Ma\n  - Mah\n  - Mai\n  - Mak\n  - Man\n  - Mao\n  - Mar\n  - Mau\n  - May\n  - Mei\n  - Meng\n  - Miao\n  - Min\n  - Ming\n  - Miu\n  - Mo\n  - Mok\n  - Mon\n  - Mou\n  - Moy\n  - Mu\n  - Mui\n  - Na\n  - Ng\n  - Ngai\n  - Ngan\n  - Ngo\n  - Ni\n  - Nie\n  - Ning\n  - Niu\n  - On\n  - Ong\n  - Ou\n  - Ou Yang\n  - Ow\n  - Owyang\n  - Pan\n  - Pang\n  - Pao\n  - Pei\n  - Peng\n  - Pi\n  - Ping\n  - Po\n  - Pon\n  - Pong\n  - Poon\n  - Pu\n  - Pun\n  - Qi\n  - Qian\n  - Qiao\n  - Qin\n  - Qiu\n  - Qu\n  - Quan\n  - Que\n  - Rao\n  - Ren\n  - Rong\n  - Ruan\n  - Sam\n  - San\n  - Sang\n  - Seto\n  - Sha\n  - Sham\n  - Shan\n  - Shang\n  - Shao\n  - Shaw\n  - Shek\n  - Shen\n  - Sheng\n  - Sheu\n  - Shi\n  - Shiau\n  - Shieh\n  - Shih\n  - Shing\n  - Shiu\n  - Shu\n  - Shum\n  - Shy\n  - Shyu\n  - Si\n  - Sieh\n  - Sin\n  - Sing\n  - Sit\n  - Situ\n  - Siu\n  - So\n  - Soh\n  - Song\n  - Soo\n  - Soo Hoo\n  - Soon\n  - Soong\n  - Su\n  - Suen\n  - Sui\n  - Sum\n  - Sun\n  - Sung\n  - Sze\n  - Szeto\n  - Tai\n  - Tam\n  - Tan\n  - Tang\n  - Tao\n  - Tay\n  - Te\n  - Teh\n  - Teng\n  - Teo\n  - Tian\n  - Tien\n  - Tin\n  - Ting\n  - Tiu\n  - To\n  - Toh\n  - Tom\n  - Tong\n  - Tsai\n  - Tsang\n  - Tsao\n  - Tsay\n  - Tse\n  - Tseng\n  - Tso\n  - Tsoi\n  - Tsou\n  - Tsu\n  - Tsui\n  - Tu\n  - Tuan\n  - Tung\n  - Tzeng\n  - U\n  - Un\n  - Ung\n  - Wah\n  - Wai\n  - Wan\n  - Wang\n  - Wee\n  - Wei\n  - Wen\n  - Weng\n  - Wing\n  - Wong\n  - Woo\n  - Woon\n  - Wu\n  - Xi\n  - Xia\n  - Xiang\n  - Xiao\n  - Xie\n  - Xin\n  - Xing\n  - Xiong\n  - Xu\n  - Xue\n  - Yam\n  - Yan\n  - Yang\n  - Yao\n  - Yap\n  - Yau\n  - Yaw\n  - Ye\n  - Yee\n  - Yeh\n  - Yen\n  - Yep\n  - Yeung\n  - Yi\n  - Yim\n  - Yin\n  - Ying\n  - Yip\n  - Yiu\n  - Yong\n  - Yoo\n  - Yoon\n  - You\n  - Young\n  - Yu\n  - Yuan\n  - Yue\n  - Yuen\n  - Yun\n  - Yung\n  - Zang\n  - Zeng\n  - Zha\n  - Zhan\n  - Zhang\n  - Zhao\n  - Zhen\n  - Zheng\n  - Zhong\n  - Zhou\n  - Zhu\n  - Zhuang\n  - Zhuo\n  - Zong\n  - Zou\nmaleLast:\n  - An\n  - Bao\n  - Bo\n  - Bing\n  - Cai\n  - Chen\n  - Cheng\n  - Chung\n  - Confucius\n  - Cong\n  - De\n  - Deshi\n  - Dewei\n  - Dong\n  - Feng\n  - Fo-hai\n  - Fo-hsing\n  - Gan\n  - Gan\n  - Gao\n  - Genjo\n  - Guo\n  - Ho\n  - Hsin\n  - Hu\n  - Hui\n  - Hui-chao\n  - Huik'o\n  - Jian\n  - Jiang\n  - Jie\n  - Jin\n  - Jing\n  - Jun\n  - Kang\n  - Kong\n  - Lao-Tzu\n  - Lee\n  - Lei\n  - Li\n  - Liang\n  - Liko\n  - Li-liang\n  - Long\n  - Manchu\n  - Meng\n  - Ming\n  - Niao-ka\n  - Ning\n  - On\n  - Peng\n  - Qiang\n  - Qing-Nan\n  - Quon\n  - Shen\n  - Shi\n  - Shing\n  - Song\n  - Sun\n  - Tao\n  - Tian\n  - Tung\n  - Uang\n  - Wang\n  - Wei\n  - Wen\n  - Woo\n  - Wu-pen\n  - Xiaoping\n  - Yao\n  - Ye\n  - Yo\n  - Yong\n  - Yu\n  - Yuan\n  - Zong\n  - Zhu\n  - Zhuang\nfemaleLast:\n  - Ah lam\n  - Ai\n  - An\n  - Bao\n  - Bi\n  - Cai\n  - Chan\n  - Chen\n  - Chen-chio\n  - Chen-tao\n  - Chow\n  - Chu hua\n  - Chun\n  - Chyou\n  - Cui\n  - Dai\n  - Da-Shin\n  - Dan\n  - Da-xia\n  - E\n  - Fai\n  - Fang\n  - Fang hua\n  - Feng\n  - Genji\n  - Guanyin\n  - Hong\n  - Hua\n  - Huan\n  - Hui\n  - Hui fang\n  - Jiao\n  - Jing Wei\n  - Ju\n  - Juan\n  - Jun\n  - Kimora\n  - Lan\n  - Le\n  - Lee\n  - Lei\n  - Lian\n  - Lien\n  - Li Hua\n  - Li Mei\n  - Li Ming\n  - Lin\n  - Ling\n  - Lixue\n  - Mee\n  - Mei\n  - Mingmei\n  - Quan\n  - Shu Fang\n  - Ting\n  - Ushi\n  - Xiang\n  - Xiao-Niao\n  - Xiao-Xing\n  - Xin\n  - Xiu Mei\n  - Yin\n  - Yu\n  - Zan\n  - Zhengqiu\n  - Zhi\n  - Zhijuan\n  - Zi\n"
  },
  {
    "path": "bin/common/SoldierName/Congolese.nam",
    "content": "lookWeights:\n  - 0\n  - 0\n  - 0\n  - 100\nmaleFirst:\n  - Aimé Dorian\n  - Alban\n  - Ange\n  - Annoud Prestige\n  - Appollinaire\n  - Arcel\n  - Archange\n  - Aristide\n  - Armand\n  - Arthur\n  - Awax\n  - Baurion\n  - Ben\n  - Benjamin\n  - Bensadaa\n  - Bonte\n  - Boris\n  - Bouse\n  - Calice\n  - Céléstin\n  - Chatel\n  - Cherald\n  - Cherubin\n  - Chriss\n  - Christian\n  - Claude\n  - Davy\n  - Dbacom\n  - Donnel\n  - Dorian\n  - Dos\n  - Dulcine\n  - Eden\n  - Edvin\n  - Elyse\n  - Eudes\n  - Evrard\n  - Fred\n  - Fresnel\n  - Gata\n  - Geslin\n  - Giordani\n  - Guychel\n  - Harold\n  - Heldora\n  - Hilde\n  - Japhet\n  - Joad Louad\n  - Jules\n  - Julle\n  - Karome\n  - Leonce\n  - Lima\n  - Lionel\n  - Lucien\n  - Mack\n  - Marzin\n  - Mbayo\n  - Milan\n  - Murphy\n  - Oudry\n  - Pascal\n  - Paterne\n  - Patrick\n  - Prevner\n  - Prince\n  - Ray\n  - Régis\n  - Resnik\n  - Rishi\n  - Rodrigue\n  - Rudolf\n  - Sajila\n  - Severin\n  - Shabani\n  - Stanis\n  - Stephane\n  - Sylvio\n  - Thierry\n  - Van Carrel\n  - Yohan\nfemaleFirst:\n  - Arich\n  - Arrielle\n  - Ashley\n  - Aubierge\n  - Aude\n  - Belcha\n  - Belvie\n  - Brunelle\n  - Capricia\n  - Carole\n  - Cecile\n  - Celvie\n  - Chanfrelle\n  - Christelle\n  - Christiane\n  - Clavidia\n  - Darlène\n  - Deborah\n  - Diche\n  - Dina\n  - Docile\n  - Djany\n  - Emmanuelle\n  - Estelle\n  - Fallone\n  - Fernande\n  - Florèse\n  - Gaelle\n  - Garcia\n  - Geanna\n  - Giovanna\n  - Gloire\n  - Grace\n  - Granie\n  - Jaelle\n  - Jannie\n  - Jeanny\n  - Jelvie\n  - Jessica\n  - Jen\n  - Jodrey\n  - Jolienne\n  - Judith\n  - Julie\n  - Jupsie\n  - Keicha\n  - Liu\n  - Lys\n  - Melaine\n  - Merveille\n  - Michelle\n  - Parfaite\n  - Patrique\n  - Polly\n  - Privel\n  - Lirna\n  - Madelenne\n  - Manu\n  - Mary\n  - Mbeko\n  - Milyne\n  - Monia\n  - Nardelie\n  - Nathalie\n  - Nel\n  - Nicia\n  - Nuptia\n  - Opportune\n  - Patricia\n  - Pitchou\n  - Raan-sady\n  - Reine\n  - Rose\n  - Rosa\n  - Rudelle\n  - Sabrina\n  - Sagely\n  - Sidorelle\n  - Sony\n  - Staelle\n  - Synthyche\n  - Tan\n  - Vanessa\n  - Winnie\n  - Yornella\nmaleLast:\n  - Akindele\n  - Alphonse\n  - Anaclet\n  - Augustin\n  - Aurelie\n  - Axele\n  - Badibanga\n  - Bakaji\n  - Bakwamba\n  - Bangamba\n  - Bantu\n  - Biampata\n  - Bilenga\n  - Bilenge\n  - Bilengi\n  - Bilonda\n  - Bilumbu\n  - Bitala\n  - Bitelu\n  - Biumba\n  - Buabu\n  - Buikalu\n  - Bukaka\n  - Buluba\n  - Busasa\n  - Buta\n  - Dikembe\n  - Dikengu\n  - Dikiyu\n  - Dishi\n  - Diyoka\n  - Evariste\n  - Felicien\n  - Francky\n  - Francois\n  - Gabriel\n  - Ganeramba\n  - Gaston\n  - Gilbert\n  - Gourmand\n  - Henri\n  - Honore\n  - Ilunga\n  - Jean\n  - Joseph\n  - Justin\n  - Kabala\n  - Kabamba\n  - Kabanda\n  - Kabanga\n  - Kabasela\n  - Kabemba\n  - Kabeya\n  - Kaboka\n  - Kabombo\n  - Kabongo\n  - Kabukala\n  - Kabunda\n  - Kabundangoji\n  - Kabungama\n  - Kabwa\n  - Kabwaya\n  - Kadilu\n  - Kadimu\n  - Kajangala\n  - Kajila\n  - Kajimba\n  - Kakokopo\n  - Kalala\n  - Kalanga\n  - Kalawanda\n  - Kalengedi\n  - Kaleuka\n  - Kalombo\n  - Kalonji\n  - Kalubi\n  - Kalunguji\n  - Kamanga\n  - Kambaja\n  - Kambala\n  - Kamulete\n  - Kamwania\n  - Kanda\n  - Kankolongo\n  - Kankonda\n  - Kanku\n  - Kanungu\n  - Kanyandu\n  - Kanyinda\n  - Kapinga\n  - Kapongo\n  - Kasala\n  - Kasampu\n  - Kasenga\n  - Kasongo\n  - Kasuku\n  - Kasulu\n  - Kaswaswa\n  - Katamba\n  - Katanda\n  - Katanga\n  - Katekelayi\n  - Katuku\n  - Katundu\n  - Kayemba\n  - Kayembe\n  - Kayowa\n  - Kilunsila\n  - Kimba\n  - Kishi\n  - Koloyi\n  - Komba\n  - Konji\n  - Kulondi\n  - Kutemba\n  - Lala\n  - Lemba\n  - Lengela\n  - Leonard\n  - Lisa\n  - Londa\n  - Longa\n  - Luadia\n  - Luamba\n  - Luangoyi\n  - Lubanga\n  - Lubanza\n  - Lubuya\n  - Lukodi\n  - Lukoji\n  - Lukusa\n  - Luluabourg\n  - Lumbala\n  - Lumbombo\n  - Lupenzu\n  - Lusamba\n  - Lutexa\n  - Lutonga\n  - Lutundula\n  - Mabele\n  - Mabixa\n  - Malumba\n  - Mampuya\n  - Manyangana\n  - Martin\n  - Matamba\n  - Matembela\n  - Mayi\n  - Mbayi\n  - Mbimbi\n  - Mbiya\n  - Mbiyamuenza\n  - Mbiye\n  - Mbombo\n  - Mbuyamba\n  - Mbuyangudi\n  - Mbuyi\n  - Mbwaya\n  - Meso\n  - Meta\n  - Mfunyi\n  - Miabi\n  - Mianbabu\n  - Milabi\n  - Misenga\n  - Moise\n  - Mokola\n  - Moyo\n  - Mpala\n  - Mpanda\n  - Mpoloto\n  - Mpoyi\n  - Mpuka\n  - Mpunga\n  - Mpungapoyi\n  - Muadi\n  - Muamba\n  - Muanza\n  - Mubenga\n  - Mubiayi\n  - Mubimalu\n  - Mubitende\n  - Mudiayi\n  - Mudipuekesha\n  - Mufika\n  - Mufonkola\n  - Mufuansanyi\n  - Mujinga\n  - Mukadi\n  - Mukala\n  - Mukanda\n  - Mukanya\n  - Mukendi\n  - Mukenga\n  - Mukinda\n  - Mukuma\n  - Mulaja\n  - Mulanga\n  - Mulelalupu\n  - Mulenda\n  - Mulombo\n  - Mulopo\n  - Mulopue\n  - Mulowaluendu\n  - Muluila\n  - Mulumba\n  - Mundamunya\n  - Munsense\n  - Muntshiamba\n  - Munyampala\n  - Mupompa\n  - Mupoyi\n  - Musalu\n  - Musebela\n  - Mushikila\n  - Mushiya\n  - Musuamba\n  - Mutombo\n  - Muya\n  - Mvita\n  - Mwamba\n  - Mwanankesa\n  - Mwenza\n  - Mwepu\n  - Ndanda\n  - Ndaya\n  - Ndelela\n  - Ngalula\n  - Ngandu\n  - Ngeleka\n  - Ngelema\n  - Ngomba\n  - Ngonga\n  - Ngoyi\n  - Ninette\n  - Nkanda\n  - Nkitabungi\n  - Nkomo\n  - Nkongolo\n  - Noel\n  - Norbert\n  - Nseya\n  - Nshila\n  - Nshinga\n  - Nsombamanya\n  - Nsudila\n  - Ntalaja\n  - Ntambwe\n  - Ntita\n  - Ntombolo\n  - Ntondolo\n  - Ntumba\n  - Nyanzala\n  - Nyenyempa\n  - Nyoka\n  - Nzambi\n  - Nzangula\n  - Nzemba\n  - Odia\n  - Phillipe\n  - Pierre\n  - Rachelle\n  - Samuela\n  - Shaddai\n  - Stella\n  - Talatala\n  - Thomas\n  - Tshanda\n  - Tshiabu\n  - Tshialu\n  - Tshiamanina\n  - Tshiambi\n  - Tshiambula\n  - Tshiambwaya\n  - Tshianzambonga\n  - Tshibaka\n  - Tshibala\n  - Tshibalabala\n  - Tshibangu\n  - Tshibelu\n  - Tshibola\n  - Tshibwabwa\n  - Tshidibi\n  - Tshidindu\n  - Tshidingi\n  - Tshiebelela\n  - Tshiepela\n  - Tshifunka\n  - Tshikondo\n  - Tshikulu\n  - Tshikumini\n  - Tshilenga\n  - Tshimanga\n  - Tshimbi\n  - Tshimbombo\n  - Tshimini\n  - Tshiminyi\n  - Tshimowa\n  - Tshimpaka\n  - Tshimwena\n  - Tshipanda\n  - Tshipayayi\n  - Tshisekedi\n  - Tshiswaka\n  - Tshitambala\n  - Tshitoko\n  - Tshiula\n  - Tshiyola\n  - Tuendela\n  - Yabukalanga\n  - Yamba\n  - Yampanya\n  - Yowa\n"
  },
  {
    "path": "bin/common/SoldierName/Czech.nam",
    "content": "lookWeights:\n  - 50\n  - 50\n  - 0\n  - 0\nmaleFirst:\n  - Ales\n  - Alexandr\n  - Alexej\n  - Ambroz\n  - Andrej\n  - Antonin\n  - Arnost\n  - Artur\n  - Augustyn\n  - Bartolomej\n  - Bedrich\n  - Benedikt\n  - Bernard\n  - Blahoslav\n  - Blazej\n  - Bohdan\n  - Bohumil\n  - Bohumir\n  - Bohuslav\n  - Boleslav\n  - Bonifac\n  - Borek\n  - Boris\n  - Borivoj\n  - Bretislav\n  - Bronislav\n  - Bruno\n  - Cenek\n  - Cestmir\n  - Ctibor\n  - Ctirad\n  - Dalibor\n  - Dalimil\n  - David\n  - Dobroslav\n  - Dominik\n  - Drahoslav\n  - Dusan\n  - Eduard\n  - Emil\n  - Erik\n  - Evzen\n  - Felix\n  - Ferdinand\n  - Filip\n  - Frantisek\n  - Gustav\n  - Hanus\n  - Havel\n  - Herman\n  - Hubert\n  - Hugo\n  - Hynek\n  - Ignac\n  - Igor\n  - Ilja\n  - Ivan\n  - Ivo\n  - Jachym\n  - Jakub\n  - Jan\n  - Jarmil\n  - Jaromir\n  - Jaroslav\n  - Jeronym\n  - Jindrich\n  - Jiri\n  - Jonas\n  - Josef\n  - Jozef\n  - Julius\n  - Kamil\n  - Karel\n  - Kazimir\n  - Klement\n  - Kristian\n  - Krystof\n  - Kvetoslav\n  - Kvido\n  - Ladislav\n  - Leopold\n  - Leos\n  - Libor\n  - Lubomir\n  - Lubor\n  - Lubos\n  - Ludek\n  - Ludvik\n  - Lukas\n  - Lumir\n  - Marcel\n  - Marek\n  - Marian\n  - Martin\n  - Matej\n  - Matous\n  - Maxmilian\n  - Medard\n  - Michal\n  - Mikulas\n  - Milan\n  - Milos\n  - Miloslav\n  - Miroslav\n  - Mojmir\n  - Oldrich\n  - Oleg\n  - Oliver\n  - Ondrej\n  - Oskar\n  - Otakar\n  - Otmar\n  - Oto\n  - Pankrac\n  - Patrik\n  - Pavel\n  - Petr\n  - Pravoslav\n  - Premysl\n  - Prokop\n  - Radek\n  - Radim\n  - Radomir\n  - Radoslav\n  - Radovan\n  - Rehor\n  - Roman\n  - Rostislav\n  - Rudolf\n  - Samuel\n  - Servac\n  - Silvestr\n  - Simon\n  - Slavomir\n  - Sobeslav\n  - Stanislav\n  - Stefan\n  - Stepan\n  - Svatopluk\n  - Svatoslav\n  - Tadeas\n  - Teodor\n  - Tibor\n  - Tomas\n  - Vaclav\n  - Valdemar\n  - Valentyn\n  - Vavrinec\n  - Venceslav\n  - Vendelin\n  - Veroslav\n  - Viktor\n  - Vilem\n  - Vincenc\n  - Vit\n  - Vitezslav\n  - Vladan\n  - Vladimir\n  - Vladislav\n  - Vlastimil\n  - Vlastislav\n  - Vojtech\n  - Vratislav\n  - Zbynek\n  - Zbysek\n  - Zdenek\n  - Zikmund\nfemaleFirst:\n  - Adela\n  - Adriena\n  - Agata\n  - Alena\n  - Alica\n  - Alzbeta\n  - Ana\n  - Ancika\n  - Andela\n  - Aneta\n  - Anezka\n  - Anna\n  - Antoinetta\n  - Antonie\n  - Bara\n  - Barbora\n  - Barcinka\n  - Barunka\n  - Baruska\n  - Blanka\n  - Bohdana\n  - Bohumila\n  - Bohuslava\n  - Bora\n  - Bozena\n  - Branislava\n  - Dagmar\n  - Dalibora\n  - Dominika\n  - Drahomira\n  - Drahoslava\n  - Dusana\n  - Dusanka\n  - Edita\n  - Eliska\n  - Elita\n  - Emilia\n  - Eva\n  - Frantiska\n  - Gabina\n  - Hana\n  - Hedvika\n  - Helena\n  - Irena\n  - Irina\n  - Iva\n  - Ivana\n  - Izabela\n  - Jana\n  - Jarmila\n  - Jaromila\n  - Jaroslava\n  - Jindriska\n  - Jirina\n  - Jitka\n  - Johana\n  - Jolana\n  - Josefa\n  - Judita\n  - Julia\n  - Kamila\n  - Karina\n  - Karolina\n  - Katarina\n  - Katerina\n  - Katica\n  - Kristyna\n  - Kunigunde\n  - Kveta\n  - Ladislava\n  - Lenka\n  - Leona\n  - Libena\n  - Libuse\n  - Lida\n  - Lidmila\n  - Lubomira\n  - Lucie\n  - Lucina\n  - Ludmila\n  - Lydie\n  - Madlenka\n  - Magdalena\n  - Maria\n  - Marie\n  - Marketa\n  - Matylda\n  - Michaela\n  - Milada\n  - Milana\n  - Milena\n  - Miloslava\n  - Monika\n  - Nada\n  - Nadezda\n  - Otilie\n  - Pavla\n  - Pavlina\n  - Petra\n  - Radka\n  - Radomila\n  - Radomira\n  - Radoslava\n  - Ruzena\n  - Sara\n  - Simona\n  - Sobeska\n  - Sobeslava\n  - Stanislava\n  - Stefanija\n  - Stepanka\n  - Svetlana\n  - Tatana\n  - Tereza\n  - Ursula\n  - Vaclava\n  - Vendula\n  - Vera\n  - Veronika\n  - Vladimira\n  - Vlasta\n  - Zdenka\n  - Zofie\n  - Zoja\n  - Zuzana\nmaleLast:\n  - Bartos\n  - Benda\n  - Benes\n  - Beran\n  - Blaha\n  - Blazek\n  - Broz\n  - Bures\n  - Carda\n  - Cech\n  - Cermak\n  - Cerny\n  - Cervenka\n  - Cizek\n  - Dobrynsky\n  - Dolezal\n  - Dusek\n  - Dvorak\n  - Fiala\n  - Fiser\n  - Hajek\n  - Havlicek\n  - Hlavacek\n  - Hoffmann\n  - Holub\n  - Horak\n  - Hruby\n  - Hruska\n  - Janda\n  - Janecek\n  - Janousek\n  - Jelinek\n  - Jezek\n  - Kadlec\n  - Kaspar\n  - Klaus\n  - Klima\n  - Kohout\n  - Kolar\n  - Kopecky\n  - Kovar\n  - Kovarik\n  - Krajan\n  - Kral\n  - Kratochvil\n  - Kraus\n  - Krejci\n  - Kriz\n  - Kubis\n  - Kucera\n  - Kvitoslav\n  - Machacek\n  - Maly\n  - Mares\n  - Marny\n  - Martinek\n  - Masek\n  - Matejka\n  - Matousek\n  - Moravec\n  - Mueller\n  - Musil\n  - Nadinicky\n  - Navratil\n  - Necesal\n  - Nemec\n  - Nemecek\n  - Neumann\n  - Nemy\n  - Novak\n  - Novotny\n  - Pesek\n  - Pokorny\n  - Polak\n  - Pospisil\n  - Prochazka\n  - Richter\n  - Riha\n  - Rosa\n  - Ruzicka\n  - Sedlacek\n  - Sichy\n  - Simek\n  - Skala\n  - Slavik\n  - Smid\n  - Soucek\n  - Soukup\n  - Stanek\n  - Stastny\n  - Stepanek\n  - Stransky\n  - Strnad\n  - Sulc\n  - Svoboda\n  - Sykora\n  - Tuma\n  - Tycka\n  - Urban\n  - Vacek\n  - Valenta\n  - Vanek\n  - Vavra\n  - Vesely\n  - Vlcek\n  - Zelenka\n  - Zeman\nfemaleLast:\n  - Bartosova\n  - Brozova\n  - Cermakova\n  - Hruba\n  - Kolarova\n  - Komyrova\n  - Konecna\n  - Kovacova\n  - Kratochvilova\n  - Krejci\n  - Krizna\n  - Mala\n  - Maskova\n  - Matusova\n  - Musilova\n  - Navratilova\n  - Olhova\n  - Petrova\n  - Polakova\n  - Romanova\n  - Soukupova\n  - Stastna\n  - Stejskalova\n  - Ticha\n  - Tkadlecova\n  - Trojska\n  - Tumova\n  - Urbanova\n  - Vaskova\n  - Vavrova\n  - Vlazkova\n  - Zakova\n  - Zemanova\n"
  },
  {
    "path": "bin/common/SoldierName/Danish.nam",
    "content": "lookWeights:\n  - 49\n  - 49\n  - 2\n  - 0\nmaleFirst:\n  - Absalon\n  - Adam\n  - Adolf\n  - Albert\n  - Alex\n  - Alexander\n  - Alf\n  - Alfred\n  - Allan\n  - Anders\n  - Andreas\n  - Anker\n  - Anton\n  - Arne\n  - Arnold\n  - Aron\n  - Arthur\n  - Arvid\n  - Asbjoorn\n  - Asger\n  - Aske\n  - Asmus\n  - August\n  - Axel\n  - Bendt\n  - Benjamin\n  - Benny\n  - Bent\n  - Bernhard\n  - Bernt\n  - Bertel\n  - Berthel\n  - Bertram\n  - Birger\n  - Bjarke\n  - Bjarne\n  - Bjork\n  - Bjorn\n  - Bo\n  - Boje\n  - Borge\n  - Boye\n  - Brian\n  - Bruno\n  - Carsten\n  - Casper\n  - Chresten\n  - Chris\n  - Christen\n  - Christian\n  - Christoffer\n  - Christopher\n  - Claus\n  - Daniel\n  - Danni\n  - Danny\n  - David\n  - Dennis\n  - Ditlev\n  - Edvard\n  - Edvin\n  - Egon\n  - Eigil\n  - Ejgil\n  - Ejnar\n  - Ejner\n  - Ejvind\n  - Elias\n  - Elmer\n  - Elo\n  - Emanuel\n  - Emil\n  - Erik\n  - Erland\n  - Erling\n  - Ernst\n  - Esajas\n  - Esben\n  - Eskild\n  - Evald\n  - Ferdinand\n  - Filip\n  - Finn\n  - Flemming\n  - Frands\n  - Frank\n  - Frans\n  - Freddy\n  - Frede\n  - Frederik\n  - Frithiof\n  - Frithjof\n  - Frits\n  - Frode\n  - Georg\n  - Gerhard\n  - Germund\n  - Gert\n  - Gorm\n  - Gotfred\n  - Gregers\n  - Gunder\n  - Gunnar\n  - Gunner\n  - Gustav\n  - Harald\n  - Hardy\n  - Harry\n  - Helge\n  - Helmer\n  - Hemming\n  - Henning\n  - Henrik\n  - Henry\n  - Herman\n  - Hjalmar\n  - Hjalte\n  - Holger\n  - Hugo\n  - Immanuel\n  - Ingolf\n  - Ivan\n  - Ivar\n  - Iver\n  - Jacob\n  - Jakob\n  - Jan\n  - Jannick\n  - Jannik\n  - Jens\n  - Jeppe\n  - Jeremias\n  - Jes\n  - Jesper\n  - Jim\n  - Jimmi\n  - Jimmy\n  - Joachim\n  - Joakim\n  - Joel\n  - Johan\n  - Johannes\n  - John\n  - Johnny\n  - Jon\n  - Jonas\n  - Jonatan\n  - Jonathan\n  - Jorgen\n  - Jorn\n  - Josef\n  - Jul\n  - Julian\n  - Julius\n  - Just\n  - Kaj\n  - Kaleb\n  - Karl\n  - Karsten\n  - Kasper\n  - Keld\n  - Ken\n  - Kenneth\n  - Kent\n  - Kevin\n  - Kim\n  - Kjeld\n  - Klaus\n  - Knud\n  - Kresten\n  - Kristen\n  - Kristian\n  - Kristoffer\n  - Kurt\n  - Lars\n  - Lasse\n  - Lau\n  - Lauge\n  - Laurids\n  - Laurits\n  - Lauritz\n  - Laurs\n  - Laust\n  - Lave\n  - Leif\n  - Lennart\n  - Leo\n  - Leon\n  - Lucas\n  - Ludvig\n  - Lukas\n  - Lykke\n  - Mads\n  - Magnus\n  - Malte\n  - Malthe\n  - Marc\n  - Marcus\n  - Marinus\n  - Marius\n  - Mark\n  - Markus\n  - Martin\n  - Mathias\n  - Mathies\n  - Matthaeus\n  - Matthias\n  - Max\n  - Michael\n  - Mikael\n  - Mike\n  - Mikkel\n  - Mogens\n  - Morten\n  - Mourits\n  - Nick\n  - Nicki\n  - Nicklas\n  - Nicolai\n  - Nicolaj\n  - Niels\n  - Niklas\n  - Nikolai\n  - Nikolaj\n  - Nils\n  - Nis\n  - Noah\n  - Olaf\n  - Olav\n  - Ole\n  - Oliver\n  - Oluf\n  - Orla\n  - Oscar\n  - Oskar\n  - Osvald\n  - Otto\n  - Ove\n  - Palle\n  - Patrick\n  - Paul\n  - Paulus\n  - Paw\n  - Peder\n  - Per\n  - Peter\n  - Philip\n  - Phillip\n  - Poul\n  - Povl\n  - Preben\n  - Rasmus\n  - Rene\n  - Richard\n  - Robert\n  - Robin\n  - Rolf\n  - Ronald\n  - Ronni\n  - Ronnie\n  - Rune\n  - Samuel\n  - Sebastian\n  - Severin\n  - Sigfred\n  - Sigurd\n  - Silas\n  - Simon\n  - Sofus\n  - Sonny\n  - Sophus\n  - Soren\n  - Steen\n  - Stefan\n  - Steffen\n  - Sten\n  - Stephan\n  - Steven\n  - Stig\n  - Storm\n  - Sune\n  - Svend\n  - Tage\n  - Teddy\n  - Theis\n  - Theodor\n  - Thomas\n  - Thor\n  - Thorbjorn\n  - Thorkild\n  - Thorvald\n  - Thyge\n  - Tim\n  - Tobias\n  - Toke\n  - Tom\n  - Tomas\n  - Tommy\n  - Tonni\n  - Tonny\n  - Tony\n  - Torben\n  - Torkild\n  - Torsten\n  - Troels\n  - Tue\n  - Uffe\n  - Ulf\n  - Ulrik\n  - Vagn\n  - Valdemar\n  - Valentin\n  - Verner\n  - Victor\n  - Viggo\n  - Viktor\n  - Vilhelm\n  - Villads\n  - Villy\n  - William\n  - Willy\n  - Zacharias\n  - Zakarias\n  - Hans\nfemaleFirst:\n  - Abellona\n  - Abelone\n  - Abigale\n  - Adela\n  - Agneta\n  - Alberte\n  - Albertha\n  - Alisa\n  - Almeta\n  - Alvilda\n  - Ane\n  - Anesa\n  - Anina\n  - Annalisa\n  - Anndrea\n  - Annelise\n  - Annemette\n  - Annina\n  - Aren\n  - Arisje\n  - Arvada\n  - Asa\n  - Astrid\n  - Belenda\n  - Belinde\n  - Bente\n  - Bergitte\n  - Bergliot\n  - Birgita\n  - Birgitte\n  - Birte\n  - Britta\n  - Brunhilde\n  - Caia\n  - Caja\n  - Cathrine\n  - Clady\n  - Dagmar\n  - Dana\n  - Ditte\n  - Dorete\n  - Dorothea\n  - Ebba\n  - Elle\n  - Else\n  - Eva\n  - Federikke\n  - Freja\n  - Freya\n  - Fritz\n  - Gelsomina\n  - Gerdi\n  - Gitte\n  - Gjerta\n  - Greta\n  - Grete\n  - Grethe\n  - Gry\n  - Gudrun\n  - Gulla\n  - Gullan\n  - Gunilla\n  - Gytha\n  - Hanne\n  - Helle\n  - Ide\n  - Idunn\n  - Inga\n  - Ingeborg\n  - Ingelise\n  - Inger\n  - Ingred\n  - Janne\n  - Jannicke\n  - Jensine\n  - Johanne\n  - Kaia\n  - Kaja\n  - Karen\n  - Karin\n  - Karon\n  - Karoline\n  - Karren\n  - Karrin\n  - Karyn\n  - Katrine\n  - Kirsten\n  - Kolinka\n  - Kristine\n  - Laila\n  - Larina\n  - Larine\n  - Laerke\n  - Lecia\n  - Lisbet\n  - Lise\n  - Lone\n  - Lovise\n  - Magdalone\n  - Malene\n  - Maren\n  - Margareta\n  - Margarete\n  - Margaretha\n  - Margarethe\n  - Margerethe\n  - Marika\n  - Marike\n  - Mathilde\n  - Matilde\n  - Merete\n  - Meta\n  - Metalise\n  - Mettalisa\n  - Mettalise\n  - Mia\n  - Pernille\n  - Rebekka\n  - Rikke\n  - Silje\n  - Solvej\n  - Stefania\n  - Thorbjorg\n  - Thorborg\n  - Thordis\n  - Thorid\n  - Thurid\n  - Torbjorg\n  - Torid\n  - Toril\n  - Ulrica\n  - Ulrike\n  - Urd\n  - Vibeke\n  - Anne\n  - Mette\n  - Anna\n  - Susanne\n  - Lene\n  - Inge\n  - Maria\n  - Marianne\n  - Camilla\n  - Pia\n  - Jette\n  - Charlotte\n  - Louise\nmaleLast:\n  - Adriansen\n  - Andersen\n  - Andreasen\n  - Andresen\n  - Any\n  - Arge\n  - Arneborg\n  - Assenbjerg\n  - Auken\n  - Bach\n  - Bak\n  - Bang\n  - Bau\n  - Bech\n  - Beck\n  - Bekker\n  - Berg\n  - Bertelsen\n  - Berthelsen\n  - Billes\n  - Binzer\n  - Bjerregaard\n  - Blach\n  - Bock\n  - Bogedal\n  - Bondo\n  - Bonnikson\n  - Brahe\n  - Brandhorst\n  - Brandt\n  - Branstedt\n  - Broberg\n  - Brondun\n  - Bruun\n  - Burmeister\n  - Cabble\n  - Carlsen\n  - Carstensen\n  - Ceder\n  - Chemnitz\n  - Christensen\n  - Christiansen\n  - Christoffersen\n  - Clahn\n  - Clausen\n  - Claussen\n  - Colding\n  - Crumlin\n  - Dahl\n  - Dalum\n  - Dam\n  - Damgaard\n  - Damsgaard\n  - Danielsen\n  - Danielsson\n  - Didenksen\n  - Drusse\n  - Ebel\n  - Eberlein\n  - Ejlersgaard\n  - Eldjarn\n  - Ellegaard\n  - Eriksen\n  - Espersen\n  - Fajl\n  - Falkoner\n  - Fallingborg\n  - Fenger\n  - Fetterlein\n  - Fine\n  - Fog\n  - Follerup\n  - Frandsen\n  - Frandson\n  - Frederiksen\n  - Fredskild\n  - Friis\n  - Fynbo\n  - Gade\n  - Gimsing\n  - Glob\n  - Goldbaek\n  - Gram\n  - Gran\n  - Gregersen\n  - Greve\n  - Grimlot\n  - Gruntvig\n  - Guildenstern\n  - Guldbrandsen\n  - Haeg\n  - Halkenhvad\n  - Hamburger\n  - Hammer\n  - Hamsun\n  - Hannestad\n  - Hansen\n  - Hardenberg\n  - Hasso\n  - Hedegaard\n  - Hedhoft\n  - Heiberg\n  - Heintze\n  - Helveg\n  - Henriksen\n  - Hermansen\n  - Hjelmslev\n  - Hoegh\n  - Hogh\n  - Holby\n  - Holm\n  - Holst\n  - Horby\n  - Hoyer\n  - Hvass\n  - Hviid\n  - Hylgaard\n  - Iversen\n  - Jacobsen\n  - Jakkelsen\n  - Jakobsen\n  - Jamissen\n  - Jaspersen\n  - Jensen\n  - Jeppesen\n  - Jepsen\n  - Jespersen\n  - Jessen\n  - Johannsen\n  - Johansen\n  - Johansson\n  - Johnsen\n  - Jorgensen\n  - Juhl\n  - Junge\n  - Karlsen\n  - Karseffni\n  - Kaustrop\n  - Kingo\n  - Kirkeby\n  - Kjaer\n  - Kjeldsen\n  - Kjolbye\n  - Klausen\n  - Klindt\n  - Knudsen\n  - Knutzen\n  - Koch\n  - Kock\n  - Kofod\n  - Kolb\n  - Kotzebue\n  - Krak\n  - Kristensen\n  - Kristiansen\n  - Kristoffersen\n  - Krogh\n  - Kruhl\n  - Kruse\n  - Lagermann\n  - Lander\n  - Langvardt\n  - Larsen\n  - Lassen\n  - Laudrup\n  - Laugeson\n  - Laundsen\n  - Lauridsen\n  - Lauritsen\n  - Lauritzen\n  - Laursen\n  - Lavrsen\n  - Licht\n  - Lillesoe\n  - Lind\n  - Lobing\n  - Lorenz\n  - Loyen\n  - Lund\n  - Lundgaard\n  - Lundgard\n  - Lundvall\n  - Lynnerup\n  - Madsen\n  - Maj\n  - Majland\n  - Mandelbrot\n  - Markert\n  - Mathiasen\n  - Mathiesen\n  - Meindl\n  - Meinert\n  - Meling\n  - Meulengracht\n  - Mikkelsen\n  - Milling\n  - Moesgaard\n  - Mogensen\n  - Moller\n  - Molnar\n  - Moltke\n  - Mortensen\n  - Most\n  - Munk\n  - Nerhus\n  - Niebuhr\n  - Nielsen\n  - Nielson\n  - Nilsson\n  - Nissen\n  - Norgaard\n  - Nygaard\n  - Nylen\n  - Obel\n  - Olesen\n  - Olrik\n  - Olsen\n  - Orum\n  - Ostergaard\n  - Ostgerg\n  - Ottesen\n  - Overgaard\n  - Pallesen\n  - Palsson\n  - Paulsen\n  - Pedersen\n  - Petersen\n  - Piechnik\n  - Pilegaard\n  - Poertner\n  - Poulsen\n  - Qvist\n  - Raaby\n  - Rasmussen\n  - Ravn\n  - Reuter\n  - Rieper\n  - Riis\n  - Rink\n  - Riseger\n  - Roesdahl\n  - Rohrmann\n  - Ronholt\n  - Ronne\n  - Rosenkrantz\n  - Rriis\n  - Rude\n  - Sand\n  - Sandstrod\n  - Schjonberg\n  - Schmeichel\n  - Schmidt\n  - Schou\n  - Schultz\n  - Seidenfaden\n  - Sellevold\n  - Simonsen\n  - Skaarup\n  - Skou\n  - Skov\n  - Skovgaard\n  - Soerensen\n  - Solvig\n  - Sondergaard\n  - Sonne\n  - Sorensen\n  - Sponneck\n  - Staer\n  - Steffensen\n  - Steincke\n  - Stenger\n  - Storegaard\n  - Stubbe\n  - Stuer\n  - Svendsen\n  - Tarnovius\n  - Teglbjaerg\n  - Telling\n  - Thodberg\n  - Thomsen\n  - Thornom\n  - Thorsen\n  - Thunmark\n  - Thygesen\n  - Thyregod\n  - Tilling\n  - Toefting\n  - Toft\n  - Toksvig\n  - Tommen\n  - Tyllesen\n  - Uhre\n  - Vestergaard\n  - Vilfort\n  - Villadsen\n  - Villumsen\n  - Ving\n  - Virl\n  - Wain\n  - Werlauff\n  - Wieghorst\n  - Willadsen\n  - Winther\n  - Witzke\n  - Wiuff\n  - Zinck\n  - Zoega\n"
  },
  {
    "path": "bin/common/SoldierName/Dutch.nam",
    "content": "# A good article about dutch firstnames can be found at\n# http://www.historischnieuwsblad.nl/nl/artikel/5849/voornamen-in-nederland.html\nlookWeights:\n  - 45\n  - 45\n  - 5\n  - 5\nmaleFirst:\n  - Jan\n  - Piet\n  - Henk\n  - Peter\n  - Hans\n  - Kees\n  - Wim\n  - Cor\n  - Gerard\n  - Gerrit\n  - Johan\n  - Rudi\nfemaleFirst:\n  - Annie\n  - Emma\n  - Marietje\n  - Mien\n  - Willie\n  - Eva\n  - Corrie\n  - Lenie\n  - Greetje\n  - Hanna\n  - Sofie\n  - Ansje\nmaleLast:\n  - de Jong\n  - Jansen\n  - de Vries\n  - van de Berg\n  - van Dijk\n  - Bakker\n  - Janssen\n  - Visser\n  - Smit\n  - Meyer\n  - de Boer\n  - Mulder\n  - de Groot\n  - Bos\n  - Vos\n  - Peters\n  - Hendriks\n  - van Leeuwen\n  - Dekker\n  - Brouwer\n  - de Wit\n  - Dijkstra\n  - Smits\n  - de Graaf\n  - van der Meer\n  - van der Linden\n  - Kok\n  - Jacobs\n  - de Haan\n  - Vermeulen\n  - van den Heuvel\n  - van der Veen\n  - van den Broek\n  - de Bruyn\n"
  },
  {
    "path": "bin/common/SoldierName/Ethiopian.nam",
    "content": "# Note: It's not a coincidence that the last names mirror the male names, traditionally \"last\" names in ethiopia are the father or grandfather's first name.\nlookWeights:\n  - 0\n  - 0\n  - 0\n  - 100\nmaleFirst:\n  - Abebe\n  - Adamu\n  - Ahadu\n  - Alem\n  - Alemu\n  - Alem Neh\n  - Amara\n  - Amare\n  - Assefa\n  - Asnake\n  - Bekele\n  - Berhanu\n  - Berihun\n  - Bogale\n  - Brehan\n  - Brehanu\n  - Dabir\n  - Dahnay\n  - Daniachew\n  - Dawit\n  - Demeke\n  - Demissie\n  - Desta\n  - Gebra Hana\n  - Gebre Kiristos\n  - Gere Mariam\n  - Geriel\n  - Getachew\n  - Geteye\n  - Girma\n  - Hagos\n  - Hakim\n  - Iskinder\n  - Kaleb\n  - Kebede\n  - Kelile\n  - Lake\n  - Lebna\n  - Lemma\n  - Li'ol\n  - Mebrete\n  - Mebreatu\n  - Mechela\n  - Melku\n  - Mulu Alem\n  - Negasi\n  - Nigus\n  - Tesfa\n  - Tesfaye\n  - Wendimu\n  - Werkneh\n  - Yonas\nfemaleFirst:\n  - Aamina\n  - Abeba\n  - Abebech\n  - Abrihet\n  - Adina\n  - Afework\n  - Afeworki\n  - Aisha\n  - Alem Nesh\n  - Amira\n  - Asnaku\n  - Aster\n  - Ayana\n  - Berta\n  - Bogalech\n  - Brehane\n  - Brihan\n  - Dahnay\n  - Demeku\n  - Desta\n  - Edom\n  - Eldana\n  - Eleni\n  - Elhanan\n  - Elsa\n  - Gabra\n  - Genet\n  - Hagos\n  - Helen\n  - Kassa\n  - Kebedech\n  - Lakech\n  - Lielit\n  - Makeda\n  - Martha\n  - Melke\n  - Meseret\n  - Mihret\n  - Mulu Ken\n  - Nigest\n  - Rahel\n  - Samrawit\n  - Sara\n  - Tenagne\n  - Werknesh\n  - Yenee\n  - Zema\nmaleLast:\n  - Abebe\n  - Adamu\n  - Ahadu\n  - Alem\n  - Alemu\n  - Alem Neh\n  - Amara\n  - Amare\n  - Assefa\n  - Asnake\n  - Bekele\n  - Berhanu\n  - Berihun\n  - Bogale\n  - Brehan\n  - Brehanu\n  - Dabir\n  - Dahnay\n  - Daniachew\n  - Dawit\n  - Demeke\n  - Demissie\n  - Desta\n  - Gebra Hana\n  - Gebre Kiristos\n  - Gere Mariam\n  - Geriel\n  - Getachew\n  - Geteye\n  - Girma\n  - Hagos\n  - Hakim\n  - Iskinder\n  - Kaleb\n  - Kebede\n  - Kelile\n  - Lake\n  - Lebna\n  - Lemma\n  - Li'ol\n  - Mebrete\n  - Mebreatu\n  - Mechela\n  - Melku\n  - Mulu Alem\n  - Negasi\n  - Nigus\n  - Tesfa\n  - Tesfaye\n  - Wendimu\n  - Werkneh\n  - Yonas\n"
  },
  {
    "path": "bin/common/SoldierName/Finnish.nam",
    "content": "lookWeights:\n  - 49\n  - 49\n  - 1\n  - 1\nmaleFirst:\n  - Aaro\n  - Aatu\n  - Akseli\n  - Aleksi\n  - Antti\n  - Arttu\n  - Atte\n  - Eemeli\n  - Eero\n  - Eino\n  - Esko\n  - Elias\n  - Erkki\n  - Heikki\n  - Henrikki\n  - Ilmari\n  - Jaakko\n  - Jere\n  - Jesse\n  - Joel\n  - Joona\n  - Juhani\n  - Juho\n  - Julius\n  - Jussi\n  - Juuso\n  - Kalle\n  - Konsta\n  - Lauri\n  - Leevi\n  - Markku\n  - Matias\n  - Matti\n  - Mika\n  - Mikael\n  - Mikko\n  - Niilo\n  - Niklas\n  - Niko\n  - Onni\n  - Oskari\n  - Roope\n  - Sami\n  - Santeri\n  - Tapani\n  - Tommi\n  - Tuomas\n  - Valtteri\n  - Viljo\n  - Ville\nfemaleFirst:\n  - Aino\n  - Anja\n  - Anna\n  - Anneli\n  - Anni\n  - Eila\n  - Elina\n  - Elisa\n  - Emilia\n  - Emma\n  - Emmi\n  - Eveliina\n  - Hanna\n  - Hannele\n  - Helena\n  - Helmi\n  - Iida\n  - Iina\n  - Ilona\n  - Jenni\n  - Johanna\n  - Julia\n  - Kaarina\n  - Karoliina\n  - Katariina\n  - Kristiina\n  - Laura\n  - Leena\n  - Liisa\n  - Maarit\n  - Maija\n  - Maria\n  - Marjatta\n  - Martta\n  - Milla\n  - Minna\n  - Noora\n  - Oona\n  - Pauliina\n  - Pirjo\n  - Riitta\n  - Ritva\n  - Saara\n  - Sanni\n  - Sari\n  - Sofia\n  - Susanna\n  - Tuula\n  - Tuuli\n  - Veera\nmaleLast:\n  - Aalto\n  - Aaltonen\n  - Aho\n  - Ahola\n  - Ahonen\n  - Anttila\n  - Arvola\n  - Eskola\n  - Haapala\n  - Haavisto\n  - Hakala\n  - Halonen\n  - Harju\n  - Hartikainen\n  - Heikkinen\n  - Heino\n  - Heinonen\n  - Heiskanen\n  - Hietala\n  - Hiltunen\n  - Hirvonen\n  - Honkanen\n  - Huttunen\n  - Ikonen\n  - Immonen\n  - Jalonen\n  - Jokinen\n  - Kallio\n  - Karhu\n  - Karjalainen\n  - Karppinen\n  - Kauppinen\n  - Kemppainen\n  - Kettunen\n  - Kinnunen\n  - Kiviniemi\n  - Koivisto\n  - Kokko\n  - Kokkonen\n  - Koponen\n  - Korhonen\n  - Korpela\n  - Koskela\n  - Koski\n  - Koskinen\n  - Laakso\n  - Laaksonen\n  - Lahti\n  - Lahtinen\n  - Laine\n  - Laitinen\n  - Lappalainen\n  - Lehtinen\n  - Lehto\n  - Lehtonen\n  - Leino\n  - Leinonen\n  - Lindholm\n  - Manninen\n  - Mattila\n  - Miettinen\n  - Mikkola\n  - Mikkonen\n  - Moilanen\n  - Mustonen\n  - Niemi\n  - Nieminen\n  - Niskanen\n  - Nurmi\n  - Nurminen\n  - Nyman\n  - Ojala\n  - Oksanen\n  - Partanen\n  - Peltola\n  - Peltonen\n  - Pesonen\n  - Pulkkinen\n  - Rajala\n  - Rantala\n  - Rantanen\n  - Rautiainen\n  - Rautio\n  - Rissanen\n  - Saari\n  - Saarinen\n  - Saimi\n  - Salminen\n  - Salo\n  - Salonen\n  - Savolainen\n  - Suominen\n  - Toivonen\n  - Tuominen\n  - Turunen\n  - Uusitalo\n  - Vainio\n  - Virtanen\n  - Vuorinen\n  - Ylitalo\n"
  },
  {
    "path": "bin/common/SoldierName/French.nam",
    "content": "lookWeights:\n  - 43\n  - 42\n  - 2\n  - 13\nmaleFirst:\n  - Alain\n  - Alban\n  - Armand\n  - Benoit\n  - Bruno\n  - Calvin\n  - Christian\n  - Claude\n  - Corentin\n  - Damien\n  - Denis\n  - Emile\n  - Etienne\n  - Ethan\n  - Fabien\n  - Francis\n  - Frederic\n  - Gaston\n  - Gerard\n  - Guillaume\n  - Henri\n  - Hugo\n  - Jacques\n  - Jean\n  - Jules\n  - Leon\n  - Lionel\n  - Louis\n  - Lucas\n  - Mathis\n  - Marc\n  - Marcel\n  - Michel\n  - Nathan\n  - Nicolas\n  - Olivier\n  - Pascal\n  - Paul\n  - Pierre\n  - Philippe\n  - Quentin\n  - Raphael\n  - Remi\n  - Rene\n  - Robert\n  - Roger\n  - Sebastien\n  - Simon\n  - Sylvain\n  - Thibault\n  - Victor\n  - Vincent\n  - Yves\nfemaleFirst:\n  - Anne\n  - Audrey\n  - Brigitte\n  - Camille\n  - Catherine\n  - Chantal\n  - Claire\n  - Clara\n  - Cloe\n  - Danielle\n  - Dominique\n  - Elisabeth\n  - Eva\n  - Florence\n  - Francoise\n  - Gaelle\n  - Geraldine\n  - Helene\n  - Isabelle\n  - Ludivine\n  - Lydia\n  - Jacqueline\n  - Jeanne\n  - Julie\n  - Laure\n  - Lina\n  - Lilou\n  - Maelys\n  - Marie\n  - Marion\n  - Marguerite\n  - Maud\n  - Murielle\n  - Nathalie\n  - Odile\n  - Rachel\n  - Rose\n  - Sabine\n  - Sandrine\n  - Stephanie\n  - Sonia\n  - Sylvie\n  - Valerie\n  - Veronique\n  - Zoe\nmaleLast:\n  - Andre\n  - Berger\n  - Bernard\n  - Bertrand\n  - Bonnet\n  - Bouissou\n  - Bourgeois\n  - Bouton\n  - Bouvier\n  - Blanc\n  - Blondel\n  - Buchard\n  - Caron\n  - Chevalier\n  - Coicard\n  - Collet\n  - Collignon\n  - Coste\n  - Couturier\n  - Clement\n  - Cuvelier\n  - Dagallier\n  - Delorme\n  - Dreyfus\n  - Dubois\n  - Ducourtioux\n  - Dujardin\n  - Dumont\n  - Dupuis\n  - Dupre\n  - Duval\n  - Fabre\n  - Faure\n  - Fontaine\n  - Fournier\n  - Gaillard\n  - Garcia\n  - Gaudrin\n  - Gautier\n  - Gressier\n  - Guerin\n  - Guillot\n  - Girard\n  - Giraudon\n  - Heroin\n  - Lacroix\n  - Laroyenne\n  - Lambert\n  - Laroche\n  - Larue\n  - Laurent\n  - Leclerc\n  - Lecointe\n  - Lecomte\n  - Leduc\n  - Lefevre\n  - Legrand\n  - Leroy\n  - Luget\n  - Marcelle\n  - Martin\n  - Menardier\n  - Mercier\n  - Meunier\n  - Moreau\n  - Morel\n  - Morin\n  - Mathieu\n  - Muller\n  - Pecheux\n  - Pelletier\n  - Perrin\n  - Perrot\n  - Petit\n  - Picar\n  - Roussel\n  - Revenu\n  - Roux\n  - Richard\n  - Simon\n  - Thomas\n  - Verdier\n"
  },
  {
    "path": "bin/common/SoldierName/German.nam",
    "content": "lookWeights:\n  - 44\n  - 44\n  - 9\n  - 3\nmaleFirst:\n  - Thomas\n  - Andreas\n  - Michael\n  - Frank\n  - Peter\n  - Joerg\n  - Uwe\n  - Matthias\n  - Stefan\n  - Juergen\n  - Ralf\n  - Bernd\n  - Klaus\n  - Torsten\n  - Hans\n  - Rainer\n  - Jens\n  - Martin\n  - Dirk\n  - Wolfgang\n  - Norbert\n  - Holger\n  - Kai\n  - Joachim\n  - Christian\n  - Karsten\n  - Dieter\nfemaleFirst:\n  - Susanne\n  - Sabine\n  - Petra\n  - Birgit\n  - Andrea\n  - Gabriele\n  - Martina\n  - Heike\n  - Ute\n  - Barbara\n  - Bettina\n  - Karin\n  - Angelika\n  - Monika\n  - Angela\nmaleLast:\n  - Mueller\n  - Schmidt\n  - Schneider\n  - Fischer\n  - Weber\n  - Meyer\n  - Wagner\n  - Becker\n  - Schulz\n  - Hoffmann\n  - Schaefer\n  - Koch\n  - Bauer\n  - Richter\n  - Klein\n  - Wolf\n  - Schroeder\n  - Neumann\n  - Schwarz\n  - Zimmermann\n  - Braun\n  - Krueger\n  - Hartmann\n  - Lange\n  - Schmitz\n  - Krause\n  - Meier\n"
  },
  {
    "path": "bin/common/SoldierName/Greek.nam",
    "content": "lookWeights:\n  - 50\n  - 49\n  - 1\n  - 0\nmaleFirst:\n  - Abderus\n  - Absyrtus\n  - Abydos\n  - Acastus\n  - Achates\n  - Achelous\n  - Acheron\n  - Achilles\n  - Achlys\n  - Acrisius\n  - Actaeon\n  - Acteon\n  - Adelphos\n  - Admes\n  - Admetus\n  - Adonis\n  - Adras\n  - Adrastos\n  - Adrastus\n  - Adrian\n  - Aeacus\n  - Aeetes\n  - Aegeus\n  - Aegis\n  - Aegisthus\n  - Aegyptus\n  - Aeneas\n  - Aeolus\n  - Aesculapius\n  - Aeson\n  - Aetos\n  - Agamedes\n  - Agape\n  - Agatone\n  - Aindreas\n  - Aindriu\n  - Ajax\n  - Akil\n  - Alasd\n  - Alcander\n  - Alcinoos\n  - Alcinous\n  - Alcnaeon\n  - Alcyoneus\n  - Alddes\n  - Alessandro\n  - Alex\n  - Alexander\n  - Alexandras\n  - Alexandros\n  - Alexandrukas\n  - Alexei\n  - Alexio\n  - Alix\n  - Aloeus\n  - Alpheus\n  - Altair\n  - Amaoebus\n  - Ambrocio\n  - Ambrose\n  - Ambrus\n  - Amphiaraus\n  - Amphion\n  - Amphitryon\n  - Ampyx\n  - Amycus\n  - Anastagio\n  - Anastasio\n  - Anastasios\n  - Anastasius\n  - Anasztaz\n  - Anatol\n  - Anatole\n  - Anatoli\n  - Anatolijus\n  - Anatolio\n  - Ancaeus\n  - Anchises\n  - Andor\n  - Andreas\n  - Andres\n  - Andreus\n  - Andrew\n  - Andries\n  - Androgeus\n  - Androu\n  - Anstice\n  - Anstiss\n  - Antaeus\n  - Antares\n  - Anteros\n  - Antilochus\n  - Antinous\n  - Antiphates\n  - Anton\n  - Antony\n  - Aonghas\n  - Apollo\n  - Apoloniusz\n  - Apostolos\n  - Arcadicus\n  - Arcas\n  - Arcenio\n  - Archemorus\n  - Ares\n  - Argo\n  - Argos\n  - Argus\n  - Arion\n  - Aristaeus\n  - Aristo\n  - Arsen\n  - Arsenio\n  - Artemas\n  - Artemesio\n  - Artemus\n  - Ascalaphus\n  - Asklepios\n  - Asopus\n  - Athamas\n  - Athan\n  - Athanasios\n  - Athanasius\n  - Atlas\n  - Atreus\n  - Attis\n  - Autolycus\n  - Avernus\n  - Baccaus\n  - Baccus\n  - Balasi\n  - Baltsaros\n  - Baptiste\n  - Basil\n  - Basile\n  - Basilio\n  - Baste\n  - Bastiaan\n  - Bastien\n  - Baucis\n  - Bazyli\n  - Bemus\n  - Biton\n  - Boreas\n  - Brasidas\n  - Briareus\n  - Brygus\n  - Butades\n  - Cadmus\n  - Caesare\n  - Calchas\n  - Calisto\n  - Capaneus\n  - Caseareo\n  - Castor\n  - Cecrops\n  - Celeus\n  - Cenon\n  - Cephalus\n  - Cepheus\n  - Cesare\n  - Cetus\n  - Ceyx\n  - Chris\n  - Christan\n  - Christiano\n  - Christoph\n  - Christopher\n  - Christophoros\n  - Christos\n  - Chruse\n  - Chrysostom\n  - Cimon\n  - Cirio\n  - Ciro\n  - Claas\n  - Claus\n  - Cleobis\n  - Cleon\n  - Cletus\n  - Cleytus\n  - Clio\n  - Cocytus\n  - Coeus\n  - Coireall\n  - Cole\n  - Colin\n  - Colum\n  - Corban\n  - Coridan\n  - Corybantes\n  - Corydon\n  - Cos\n  - Cosmas\n  - Cosmo\n  - Cottus\n  - Creon\n  - Cretien\n  - Cristoforo\n  - Cristophe\n  - Cronus\n  - Ctesippus\n  - Cyrano\n  - Cyrek\n  - Cyril\n  - Cyrus\n  - Cyryl\n  - Damae\n  - Damalis\n  - Damaris\n  - Damaskenos\n  - Damaskinos\n  - Damen\n  - Dameon\n  - Damian\n  - Damion\n  - Damon\n  - Danaus\n  - Dardanus\n  - Darian\n  - Darien\n  - Darion\n  - Darrian\n  - Darrien\n  - Darrion\n  - Daymon\n  - Deke\n  - Dekel\n  - Dekle\n  - Delbin\n  - Demetre\n  - Demetri\n  - Demetrios\n  - Demetrius\n  - Demitri\n  - Demitrius\n  - Demodocus\n  - Demophon\n  - Demoritus\n  - Denes\n  - Dennis\n  - Deo\n  - Deucalion\n  - Doran\n  - Dorian\n  - Dorion\n  - Drakon\n  - Drew\n  - Dymas\n  - Eachann\n  - Efterpi\n  - Egidio\n  - Eleftherios\n  - Elek\n  - Eleutherios\n  - Eli\n  - Enceladus\n  - Endre\n  - Endymion\n  - Eneas\n  - Eoghan\n  - Epeius\n  - Erasmus\n  - Erebus\n  - Erechtheus\n  - Erichthonius\n  - Erymanthus\n  - Erysichthon\n  - Eryx\n  - Estevao\n  - Eteocles\n  - Etor\n  - Eubuleus\n  - Eugen\n  - Eugene\n  - Eugenio\n  - Eugenios\n  - Eumaeus\n  - Eupeithes\n  - Euphrosyne\n  - Eurus\n  - Euryalus\n  - Eurylochus\n  - Eurymachus\n  - Eurypylus\n  - Eurystheus\n  - Euryton\n  - Eusebius\n  - Eustace\n  - Eustachy\n  - Eustis\n  - Evan\n  - Evzen\n  - Fedor\n  - Feodor\n  - Feodras\n  - Filippo\n  - Filips\n  - Flip\n  - Fulop\n  - Gaelan\n  - Galan\n  - Galen\n  - Galinthias\n  - Galyn\n  - Gelasius\n  - Georg\n  - George\n  - Georges\n  - Giles\n  - Glaucus\n  - Goran\n  - Graeae\n  - Gregoire\n  - Gregoly\n  - Gregor\n  - Gregorie\n  - Gregorior\n  - Gregory\n  - Gregos\n  - Grigor\n  - Grigorov\n  - Gruev\n  - Guilio\n  - Gyes\n  - Gyoergy\n  - Gyorgy\n  - Gyuri\n  - Haemon\n  - Hali\n  - Halithersis\n  - Hector\n  - Helios\n  - Herodotus\n  - Homar\n  - Homer\n  - Homeros\n  - Homerus\n  - Hypnos\n  - Ibycus\n  - Icarius\n  - Icarus\n  - Icelos\n  - Icos\n  - Idas\n  - Igorr\n  - Inachus\n  - Iorgas\n  - Iphitus\n  - Istvan\n  - Ivan\n  - Ivankor\n  - Ixion\n  - Jaison\n  - Jase\n  - Jasen\n  - Jason\n  - Jayce\n  - Jayr\n  - Jaysen\n  - Jayson\n  - Jencir\n  - Jeno\n  - Jeroenr\n  - Jerome\n  - Jerzyr\n  - Jirkar\n  - Jorenr\n  - Julius\n  - Jurgisr\n  - Kadmus\n  - Kairos\n  - Khristos\n  - Khrystiyanr\n  - Kit\n  - Klaasr\n  - Klaus\n  - Korudon\n  - Kosmosr\n  - Kratos\n  - Krikor\n  - Krischnan\n  - Kristian\n  - Kristofr\n  - Krystupasr\n  - Krzysztofr\n  - Kuirilr\n  - Kyrillos\n  - Kyrillosr\n  - Kyros\n  - Ladon\n  - Laertes\n  - Laestrygones\n  - Laius\n  - Lander\n  - Laocoon\n  - Laomedon\n  - Leander\n  - Leandro\n  - Leonidas\n  - Lichas\n  - Linus\n  - Lippio\n  - Lotus\n  - Loxias\n  - Luke\n  - Lycaon\n  - Lycomedes\n  - Lycurgus\n  - Lynceus\n  - Lysander\n  - Marcario\n  - Maurice\n  - Medus\n  - Melampus\n  - Melancton\n  - Melanthius\n  - Menelaus\n  - Menoeceus\n  - Mentor\n  - Midas\n  - Mikolas\n  - Miles\n  - Milo\n  - Minos\n  - Momus\n  - Mopsus\n  - Moses\n  - Myles\n  - Myron\n  - Narkis\n  - Nauplius\n  - Neleus\n  - Nemo\n  - Nemos\n  - Neo\n  - Nicholas\n  - Nicholaus\n  - Nicias\n  - Nick\n  - Nicodemus\n  - Nicolas\n  - Nicolaus\n  - Nik\n  - Nike\n  - Niklaus\n  - Nikodem\n  - Nikolai\n  - Nikolajis\n  - Nikolos\n  - Niles\n  - Nilo\n  - Nilos\n  - Nisus\n  - Notus\n  - Obiareus\n  - Oighrig\n  - Oles\n  - Orrin\n  - Orthros\n  - Otis\n  - Pan\n  - Panagiotis\n  - Pancratius\n  - Panos\n  - Panteleimon\n  - Papandrou\n  - Paris\n  - Patroclus\n  - Patroklos\n  - Pavlos\n  - Peadair\n  - Peder\n  - Pegeen\n  - Peleus\n  - Pelias\n  - Pello\n  - Pelops\n  - Pero\n  - Perrin\n  - Peterke\n  - Petrelis\n  - Petros\n  - Petter\n  - Phantasos\n  - Phaon\n  - Philemon\n  - Philip\n  - Philipp\n  - Philippe\n  - Phillip\n  - Philo\n  - Phineas\n  - Phineus\n  - Phrixus\n  - Phylo\n  - Piero\n  - Pierro\n  - Pieter\n  - Pietr\n  - Pietro\n  - Pilib\n  - Piotr\n  - Pippo\n  - Pirithous\n  - Pirro\n  - Pittheus\n  - Plato\n  - Platon\n  - Plexippus\n  - Plutus\n  - Pollux\n  - Poseidon\n  - Preben\n  - Priam\n  - Priapus\n  - Procrustes\n  - Prokopios\n  - Prometheus\n  - Prophyrios\n  - Protesilaus\n  - Ptolemy\n  - Pyramus\n  - Rasmus\n  - Rhodes\n  - Risto\n  - Sabastian\n  - Salmoneus\n  - Scopas\n  - Sebasten\n  - Sebastian\n  - Sebastiano\n  - Simon\n  - Sinon\n  - Socrates\n  - Sofronio\n  - Soterios\n  - Spyridon\n  - Stamitos\n  - Stavros\n  - Steafan\n  - Stefan\n  - Stefano\n  - Stefanos\n  - Stefford\n  - Stefon\n  - Stephano\n  - Stephanos\n  - Stephen\n  - Stephon\n  - Steven\n  - Steverino\n  - Takis\n  - Talos\n  - Talus\n  - Tantalus\n  - Tarasios\n  - Teague\n  - Telamon\n  - Telegonus\n  - Telemachus\n  - Telephus\n  - Tellus\n  - Teodors\n  - Teofile\n  - Teuthras\n  - Thad\n  - Thaddeus\n  - Thaddius\n  - Thadeus\n  - Thais\n  - Thanatos\n  - Thanos\n  - Thaumas\n  - Theo\n  - Theociymenus\n  - Theodon\n  - Theodore\n  - Theodosios\n  - Theodrekr\n  - Theodric\n  - Theon\n  - Theophile\n  - Theophilus\n  - Theron\n  - Therron\n  - Thersites\n  - Theseus\n  - Thomas\n  - Thyestes\n  - Tiege\n  - Tim\n  - Timeus\n  - Timmy\n  - Timocrates\n  - Timoleon\n  - Timon\n  - Timotheos\n  - Timothy\n  - Timun\n  - Tiomoid\n  - Tito\n  - Titos\n  - Titus\n  - Tityus\n  - Tivadar\n  - Todor\n  - Toxeus\n  - Triton\n  - Trophonius\n  - Turannos\n  - Tydeus\n  - Tylissus\n  - Tymek\n  - Tymon\n  - Tyndareus\n  - Typhoeus\n  - Typhon\n  - Tyrone\n  - Ulysses\n  - Urian\n  - Vasileios\n  - Vasilios\n  - Vasilis\n  - Vasos\n  - VasyItso\n  - Vasyklo\n  - Vasyl\n  - Xanthus\n  - Xeno\n  - Xenophon\n  - Xenos\n  - Xerxes\n  - Xuthus\n  - Xylon\n  - Yanni\n  - Yehor\n  - Yuri\n  - Zale\n  - Zarek\n  - Zelotes\n  - Zeno\n  - Zenobio\n  - Zenon\n  - Zenos\n  - Zephyr\n  - Zero\n  - Zerro\n  - Zetes\n  - Zoltan\n  - Zoltar\n  - Zorba\n  - Zotico\nfemaleFirst:\n  - Acacia\n  - Acantha\n  - Aegea\n  - Aeola\n  - Agalia\n  - Alala\n  - Aldora\n  - Aleni\n  - Anatolia\n  - Andrianna\n  - Anemone\n  - Angeline\n  - Aphrodite\n  - Athena\n  - Athenagora\n  - Calantha\n  - Calida\n  - Cassia\n  - Cyra\n  - Damia\n  - Daphne\n  - Deianira\n  - Delia\n  - Dido\n  - Dimitra\n  - Echo\n  - Elma\n  - Elpida\n  - Emalia\n  - Erianthe\n  - Euphemia\n  - Euphenia\n  - Evadne\n  - Evanthe\n  - Fotini\n  - Galatea\n  - Georgia\n  - Halcyone\n  - Helena\n  - Helia\n  - Hera\n  - Hermione\n  - Isadora\n  - Jocasta\n  - Kalidas\n  - Kaligenia\n  - Kalligenia\n  - Kallirrhoe\n  - Kalonice\n  - Kyriakoula\n  - Lalage\n  - Leandra\n  - Leda\n  - Lycoris\n  - Lyris\n  - Marina\n  - Medora\n  - Melantha\n  - Melina\n  - Melissa\n  - Mona\n  - Neola\n  - Neona\n  - Nerissa\n  - Niobe\n  - Olga\n  - Orthia\n  - Pandora\n  - Pangiota\n  - Pelagia\n  - Penelope\n  - Persephone\n  - Philantha\n  - Philomela\n  - Philomena\n  - Philothea\n  - Phoebe\n  - Rhea\n  - Saphhira\n  - Sofronia\n  - Stamata\n  - Stella\n  - Tassia\n  - Tassula\n  - Tessa\n  - Thaddea\n  - Thalassa\n  - Tharsia\n  - Theodosia\n  - Theophilia\n  - Thetis\n  - Timothea\n  - Toula\n  - Xantippe\n  - Yana\n  - Zenaida\n  - Zenobia\n  - Zephyra\n  - Zoe\nmaleLast:\n  - Alexopoulos\n  - Anagyros\n  - Anastassios\n  - Andreadis\n  - Andreos\n  - Andriopoulos\n  - Andronikos\n  - Andros\n  - Androuchelli\n  - Androupolos\n  - Androutsos\n  - Angelis\n  - Angelomatis\n  - Angelos\n  - Anistonopoulos\n  - Anninos\n  - Antikatzides\n  - Antonatos\n  - Antonious\n  - Argyra\n  - Athanasiadis\n  - Athanassiadi\n  - Averoff\n  - Axelos\n  - Bakirdzis\n  - Bakogianni\n  - Balanos\n  - Bazignos\n  - Bessarion\n  - Bizos\n  - Borbokis\n  - Botsaris\n  - Boudouris\n  - Bourgani\n  - Capodistria\n  - Carides\n  - Castriota\n  - Catalactus\n  - Chacoliades\n  - Chakiris\n  - Christodoulos\n  - Clerides\n  - Constandouros\n  - Constantinis\n  - Cosmatos\n  - Costanduros\n  - Costi\n  - Cotsadis\n  - Couloumbis\n  - Coulouris\n  - Deligiannis\n  - Deligiorgis\n  - Delivorias\n  - Dellas\n  - Demertzis\n  - Demosthenous\n  - Dimas\n  - Dimitrakos\n  - Dimitriades\n  - Dimitris\n  - Dimotsios\n  - Diomedes\n  - Dontas\n  - Doxiadis\n  - Dukakis\n  - Duvis\n  - Economakis\n  - Economos\n  - Eliades\n  - Elipandas\n  - Ellinas\n  - Farakos\n  - Fettas\n  - Florakis\n  - Galonopoulas\n  - Gatsioudis\n  - Gatzioudis\n  - Gavrielides\n  - Gennadios\n  - Genovelis\n  - Georghios\n  - Giorgiou\n  - Gislenus\n  - Gizikis\n  - Glezos\n  - Gogos\n  - Gonatas\n  - Goulandris\n  - Gounaris\n  - Gousetti\n  - Grivas\n  - Hagiorgis\n  - Hajiyanni\n  - Halara\n  - Harteros\n  - Iakovakis\n  - Iakovos\n  - Iatrides\n  - Ioannidis\n  - Ioannos\n  - Issigonis\n  - Joakimides\n  - Kairis\n  - Kaklamanakis\n  - Kakoulli\n  - Kalergi\n  - Kallabis\n  - Kalvos\n  - Kanaris\n  - Kanellopoulos\n  - Kaphandaris\n  - Karahi\n  - Karaiskakis\n  - Karamanlis\n  - Karatossos\n  - Karoki\n  - Karyoti\n  - Kasomoulis\n  - Katsantonis\n  - Katsaris\n  - Kenteris\n  - Khadjikyriakos\n  - Klaras\n  - Kochalakos\n  - Koffa\n  - Kokkinos\n  - Kokotis\n  - Kolettis\n  - Kollias\n  - Kolokotronis\n  - Kondylis\n  - Kontoghiorghes\n  - Korais\n  - Korkizoglu\n  - Korres\n  - Koryzis\n  - Koskotas\n  - Kostanopoulos\n  - Kostopulos\n  - Kotaridos\n  - Koukodimos\n  - Koukoudimos\n  - Koumoundouros\n  - Koundouriotis\n  - Kourniakis\n  - Kousoulas\n  - Kozani\n  - Kritopoulos\n  - Kyprianos\n  - Kyriacos\n  - Kyriakos\n  - Kyriazis\n  - Lambrakis\n  - Lambrianos\n  - Lambrinos\n  - Lathouris\n  - Lazardis\n  - Leonidis\n  - Lianis\n  - Logotheti\n  - Louca\n  - Louganis\n  - Louvaris\n  - Lyssarides\n  - Maganas\n  - Magos\n  - Maharis\n  - Makarezos\n  - Makrigiannis\n  - Malachias\n  - Maliagros\n  - Mangakis\n  - Marcoullides\n  - Mardas\n  - Marinatos\n  - Markezinis\n  - Markoulides\n  - Markoullides\n  - Marsolais\n  - Martis\n  - Matacena\n  - Mavridos\n  - Mavrogordatos\n  - Mavrokordatos\n  - Mavromikhalis\n  - Mavros\n  - Mavroudis\n  - Maximos\n  - Melas\n  - Meletoglos\n  - Melikis\n  - Melissanides\n  - Mercouri\n  - Merukides\n  - Messimeris\n  - Metaxas\n  - Michaelis\n  - Mikalis\n  - Mikhalakopoulos\n  - Militis\n  - Mitros\n  - Mitsotakis\n  - Monomachus\n  - Moscopolis\n  - Moumoulidis\n  - Muscouri\n  - Mylonas\n  - Nafpliotis\n  - Negris\n  - Niarkhos\n  - Nikolaides\n  - Onassis\n  - Orphanides\n  - Oxinos\n  - Palamas\n  - Pallis\n  - Panagiatopoulos\n  - Panagiopoulos\n  - Panagiotopos\n  - Panagou\n  - Panagoulias\n  - Panagoulis\n  - Panaotis\n  - Panavoglos\n  - Panayi\n  - Panayides\n  - Panayiotopoulos\n  - Panayiotos\n  - Pangalos\n  - Papadakis\n  - Papademetrios\n  - Papadias\n  - Papadopolos\n  - Papadopoulos\n  - Papadoupolos\n  - Papafagos\n  - Papageorgios\n  - Papagos\n  - Papakostas\n  - Papamichael\n  - Papanastasiou\n  - Papandreou\n  - Papasotiriou\n  - Papatamelis\n  - Papathanassios\n  - Papoulias\n  - Pappas\n  - Parastadidis\n  - Pattakos\n  - Pavlakakis\n  - Pentzopoulos\n  - Pesmazoglos\n  - Pheraios\n  - Philipousis\n  - Pierides\n  - Pietris\n  - Pipinelis\n  - Pittakis\n  - Pittakys\n  - Plastiras\n  - Polides\n  - Polycarpous\n  - Polychroniadis\n  - Polychronios\n  - Polydoros\n  - Polymeropoulos\n  - Polymeros\n  - Polyzos\n  - Popotas\n  - Porpurogenitos\n  - Pratkanis\n  - Prevalakis\n  - Primikynos\n  - Psara\n  - Psaros\n  - Psaroulakis\n  - Rallis\n  - Saltsidis\n  - Samos\n  - Sampras\n  - Sanassis\n  - Sarakatsani\n  - Saraphis\n  - Sardzetakis\n  - Sarris\n  - Sartzetakis\n  - Sarus\n  - Savakis\n  - Savalos\n  - Savvides\n  - Sbokos\n  - Senteildis\n  - Siantos\n  - Sicilianos\n  - Simopoulos\n  - Sirtis\n  - Skandalis\n  - Skiotis\n  - Skouloudis\n  - Skouphas\n  - Solomos\n  - Sophoulis\n  - Souvaltzis\n  - Stamanakis\n  - Stasi\n  - Stavrakis\n  - Stavrianakis\n  - Stavrianos\n  - Stephanopoulos\n  - Stoikos\n  - Strapoudopolos\n  - Stratis\n  - Stroubakos\n  - Taliadoros\n  - Tathouris\n  - Tavoularis\n  - Terzin\n  - Theodopoulos\n  - Theodorakis\n  - Theophanous\n  - Theothanos\n  - Theotokis\n  - Touliatos\n  - Tournikiotis\n  - Tragianopoulos\n  - Trikoupis\n  - Tsakolov\n  - Tsaldaris\n  - Tsatsos\n  - Tsavdaridos\n  - Tsiamita\n  - Tsigakos\n  - Tsikouna\n  - Tsiolakoudi\n  - Tsirigolis\n  - Tsirimokos\n  - Tsolakoglos\n  - Tsoni\n  - Tsouderos\n  - Tsougarakis\n  - Tsoutsouvas\n  - Tsyoma\n  - Tzannetakis\n  - Tzivas\n  - Vadeki\n  - Valaoritis\n  - Valvis\n  - Vaphiadis\n  - Vardakastanis\n  - Varvaressos\n  - Vasdeki\n  - Vasdekis\n  - Vasiliou\n  - Vassilides\n  - Vatatzes\n  - Veloukhiotis\n  - Venizelos\n  - Verdanis\n  - Vergopoulos\n  - Vlakhos\n  - Voulgaris\n  - Voulgaropoulos\n  - Vouris\n  - Xanthos\n  - Xenakis\n  - Xydis\n  - Yannopoulos\n  - Yialouris\n  - Ypsilantis\n  - Zafiropoulos\n  - Zaimis\n  - Zakhariadis\n  - Zarikos\n  - Zervakos\n  - Zervas\n  - Zikos\n  - Zindilis\n  - Zisimides\n  - Zographas\n  - Zoitakis\n  - Zolotas\n"
  },
  {
    "path": "bin/common/SoldierName/Hindi.nam",
    "content": "lookWeights:\n  - 1\n  - 1\n  - 80\n  - 18\nmaleFirst:\n  - Abhijay\n  - Adil\n  - Chandresh\n  - Dev\n  - Dinesh\n  - Govinda\n  - Jaideep\n  - Kanak\n  - Mahesh\n  - Neelam\n  - Om\n  - Pallav\n  - Parmesh\n  - Rajesh\n  - Ranjit\n  - Samir\n  - Sanjiv\n  - Sudeep\n  - Vihaan\n  - Yogendra\n  - Sachin\n  - Rahul\n  - Anil\n  - Virender\n  - Kapil\n  - Sourav\n  - Harbhajan\nfemaleFirst:\n  - Ajita\n  - Amma\n  - Avinashi\n  - Deepti\n  - Gulab\n  - Hina\n  - Indira\n  - Jasweer\n  - Kalinda\n  - Keva\n  - Madhuri\n  - Meera\n  - Neela\n  - Parvati\n  - Priti\n  - Ranhita\n  - Roshan\n  - Savitri\n  - Sitesh\n  - Ushma\n  - Vritika\n  - Zahra\nmaleLast:\n  - Sharma\n  - Verma\n  - Chowdhury\n  - Singh\n  - Misra\n  - Kumar\n  - Gupta\n  - Malik\n  - Chopra\n  - Prasad\n  - Acharya\n  - Agarwal\n  - Malhotra\n  - Jain\n  - Saini\n  - Khan\n  - Shah\n  - Narayan\n  - Mistry\n  - Joshi\n  - Goyal\n  - Roy\n  - Tendulkar\n  - Dravid\n  - Kumble\n  - Sehwag\n  - Dev\n  - Ganguly\n"
  },
  {
    "path": "bin/common/SoldierName/Hungarian.nam",
    "content": "lookWeights:\n  - 50\n  - 50\n  - 0\n  - 0\nmaleFirst:\n  - Abel\n  - Adam\n  - Adrian\n  - Akos\n  - Albert\n  - Alex\n  - Andor\n  - Andras\n  - Antal\n  - Arnold\n  - Aron\n  - Arpad\n  - Attila\n  - Balazs\n  - Balint\n  - Barna\n  - Barnabas\n  - Bela\n  - Bence\n  - Bendeguz\n  - Benedek\n  - Benjamin\n  - Bertalan\n  - Botond\n  - Csaba\n  - Csongor\n  - Daniel\n  - David\n  - Denes\n  - Dezso\n  - Dominik\n  - Elemer\n  - Emil\n  - Endre\n  - Erik\n  - Erno\n  - Ervin\n  - Ferenc\n  - Gabor\n  - Gergely\n  - Gergo\n  - Geza\n  - Gusztav\n  - Gyorgy\n  - Gyozo\n  - Gyula\n  - Henrik\n  - Imre\n  - Istvan\n  - Ivan\n  - Janos\n  - Jeno\n  - Jozsef\n  - Kalman\n  - Karoly\n  - Kevin\n  - Kornel\n  - Kristof\n  - Krisztian\n  - Krisztofer\n  - Lajos\n  - Laszlo\n  - Levente\n  - Lorant\n  - Marcell\n  - Mark\n  - Martin\n  - Marton\n  - Mate\n  - Matyas\n  - Mihaly\n  - Miklos\n  - Milan\n  - Nandor\n  - Noel\n  - Norbert\n  - Oliver\n  - Otto\n  - Pal\n  - Patrik\n  - Peter\n  - Richard\n  - Robert\n  - Roland\n  - Rudolf\n  - Sandor\n  - Szabolcs\n  - Szilard\n  - Szilveszter\n  - Tamas\n  - Tibor\n  - Tivadar\n  - Viktor\n  - Vilmos\n  - Vince\n  - Zalan\n  - Zoltan\n  - Zsigmond\n  - Zsolt\n  - Zsombor\nfemaleFirst:\n  - Adrienn\n  - Agi\n  - Agnes\n  - Agota\n  - Alberta\n  - Alexa\n  - Alexandra\n  - Aliz\n  - Anasztazia\n  - Andrea\n  - Anett\n  - Angyalka\n  - Aniko\n  - Anita\n  - Anna\n  - Annamaria\n  - Aranka\n  - Aurelia\n  - Barbara\n  - Beata\n  - Beatrix\n  - Bella\n  - Bernadett\n  - Berta\n  - Bettina\n  - Bianka\n  - Boglarka\n  - Bora\n  - Borbala\n  - Boriska\n  - Borka\n  - Brigitta\n  - Cili\n  - Csilla\n  - Dia\n  - Diana\n  - Dora\n  - Dorina\n  - Dorottya\n  - Edina\n  - Edit\n  - Emese\n  - Emma\n  - Eniko\n  - Erika\n  - Ernesztina\n  - Erzsebet\n  - Erzsi\n  - Eszter\n  - Etel\n  - Etelka\n  - Eva\n  - Evelin\n  - Fanni\n  - Franciska\n  - Gabriella\n  - Gitta\n  - Gizella\n  - Gyongyi\n  - Gyorgyi\n  - Hajna\n  - Hajnalka\n  - Hanna\n  - Henrietta\n  - Ibolya\n  - Ica\n  - Ildiko\n  - Ilka\n  - Ilona\n  - Iren\n  - Irenke\n  - Irma\n  - Janka\n  - Jolan\n  - Judit\n  - Julia\n  - Julianna\n  - Juliska\n  - Karola\n  - Karolina\n  - Katalin\n  - Katarina\n  - Kati\n  - Katinka\n  - Kinga\n  - Kitti\n  - Klara\n  - Klaudia\n  - Kriszta\n  - Krisztina\n  - Laura\n  - Lili\n  - Lilla\n  - Linka\n  - Liza\n  - Magdolna\n  - Mara\n  - Margit\n  - Margo\n  - Maria\n  - Mariann\n  - Marianna\n  - Marika\n  - Marta\n  - Melinda\n  - Monika\n  - Nikolett\n  - Nikoletta\n  - Noemi\n  - Nora\n  - Olga\n  - Orsolya\n  - Petra\n  - Piroska\n  - Reka\n  - Renata\n  - Rita\n  - Roza\n  - Rozalia\n  - Rozsa\n  - Sara\n  - Sarolta\n  - Szabina\n  - Szilvia\n  - Terez\n  - Terezia\n  - Timea\n  - Tunde\n  - Valeria\n  - Veronika\n  - Viktoria\n  - Virag\n  - Vivien\n  - Zita\n  - ZsaZsa\n  - Zsanett\n  - Zsofia\n  - Zsuzska\n  - Zsuzsanna\n  - Zsuzsi\nmaleLast:\n  - Alfoldi\n  - Andrassy\n  - Annus\n  - Antal\n  - Arany\n  - Bakos\n  - Balassa\n  - Balazs\n  - Balint\n  - Balla\n  - Balog\n  - Balogh\n  - Barati\n  - Barna\n  - Barsony\n  - Barta\n  - Bartok\n  - Bathory\n  - Berzevicky\n  - Biro\n  - Bocskay\n  - Bodnar\n  - Bogdan\n  - Bognar\n  - Borbely\n  - Bori\n  - Boros\n  - Budai\n  - Csillag\n  - Csollany\n  - Csonka\n  - Csurgo\n  - Czako\n  - Czene\n  - Czobor\n  - Dardai\n  - Daroczy\n  - Deak\n  - Dobos\n  - Doczi\n  - Dombi\n  - Dozsa\n  - Dudas\n  - Egerszegi\n  - Eotvos\n  - Fabian\n  - Farago\n  - Farkas\n  - Fazekas\n  - Feher\n  - Fekete\n  - Ferenczy\n  - Fodor\n  - Forgach\n  - Forgacs\n  - Fulop\n  - Gal\n  - Gaspar\n  - Gazdag\n  - Gero\n  - Guba\n  - Gulyas\n  - Gyorffy\n  - Gyulai\n  - Hajdu\n  - Halasz\n  - Halmai\n  - Hamori\n  - Hankiss\n  - Hedervary\n  - Hegedus\n  - Hollo\n  - Horanszky\n  - Horthy\n  - Horvath\n  - Hrutka\n  - Hunyadi\n  - Illes\n  - Illeshazy\n  - Ilyes\n  - Istvanffy\n  - Jagadics\n  - Jakab\n  - Jaszi\n  - Jokai\n  - Jonas\n  - Joo\n  - Juhasz\n  - Kalanyos\n  - Kaldi\n  - Kallay\n  - Kammerer\n  - Karolyi\n  - Katona\n  - Kazinczy\n  - Kelemen\n  - Kemeny\n  - Kerekes\n  - Kertes\n  - Kiraly\n  - Kis\n  - Kiss\n  - Knesevich\n  - Koban\n  - Kocsis\n  - Kodaly\n  - Koranyi\n  - Kortosi\n  - Kossuth\n  - Kovacs\n  - Kovago\n  - Kozma\n  - Kulcsar\n  - Kun\n  - Kurti\n  - Kurtosi\n  - Kurutz\n  - Kuti\n  - Kutsera\n  - Lajtos\n  - Lakatos\n  - Laszlo\n  - Lehotka\n  - Lengyel\n  - Ligeti\n  - Liptak\n  - Lisztes\n  - Lugosi\n  - Lukacs\n  - Madar\n  - Magyar\n  - Major\n  - Malek\n  - Mandula\n  - Markovits\n  - Mate\n  - Matyus\n  - Mecs\n  - Meszaros\n  - Mindszenty\n  - Molnar\n  - Munkacsy\n  - Nadasdy\n  - Nagy\n  - Nemes\n  - Nemeth\n  - Noszaly\n  - Novak\n  - Nyilas\n  - Nyilasi\n  - Olah\n  - Onodi\n  - Orban\n  - Orczy\n  - Orosz\n  - Orsos\n  - Pal\n  - Palagyi\n  - Pandy\n  - Pap\n  - Papp\n  - Partos\n  - Pasztor\n  - Pataki\n  - Pazmany\n  - Pecely\n  - Perneky\n  - Peter\n  - Petofi\n  - Pinter\n  - Pongratz\n  - Pulszky\n  - Racz\n  - Rakosi\n  - Redik\n  - Revay\n  - Rezessy\n  - Ronay\n  - Rosner\n  - Rosza\n  - Rubik\n  - Safar\n  - Sandor\n  - Sebok\n  - Sereny\n  - Simon\n  - Sipos\n  - Soltesz\n  - Solti\n  - Solymosi\n  - Somogyi\n  - Soos\n  - Supola\n  - Suto\n  - Svarcz\n  - Szabo\n  - Szalai\n  - Szalay\n  - Szatmary\n  - Szechenyi\n  - Szekely\n  - Szekeres\n  - Szelepcsenyi\n  - Szeman\n  - Szemere\n  - Szilagyi\n  - Szoke\n  - Szucs\n  - Szuhay\n  - Tabory\n  - Takacs\n  - Tamas\n  - Teleki\n  - Temesvari\n  - Tessedik\n  - Thurzo\n  - Tisza\n  - Tokes\n  - Tokody\n  - Tolgyesi\n  - Torok\n  - Toth\n  - Ujlaky\n  - Urbanik\n  - Vajda\n  - Vamosi\n  - Varadi\n  - Varga\n  - Varkonyi\n  - Vass\n  - Vegh\n  - Verboczy\n  - Veres\n  - Vidrai\n  - Vincze\n  - Virag\n  - Voros\n  - Wessely\n  - Zatony\n  - Zavadszky\n  - Zrinyi\n  - Zsivozky\n  - Zsoldos\n"
  },
  {
    "path": "bin/common/SoldierName/Irish.nam",
    "content": "lookWeights:\n  - 48\n  - 48\n  - 2\n  - 2\nmaleFirst:\n  - Aidan\n  - Andrew\n  - Brendon\n  - Cathal\n  - Cian\n  - Cillian\n  - Conor\n  - Cormac\n  - Daniel\n  - Darragh\n  - David\n  - Donal\n  - Eoghan\n  - Eoin\n  - Finn\n  - Jack\n  - James\n  - John\n  - Liam\n  - Luke\n  - Michael\n  - Mick\n  - Oisin\n  - Owen\n  - Paddy\n  - Padraig\n  - Pat\n  - Patrick\n  - Pete\n  - Ronan\n  - Rory\n  - Sean\n  - Thomas\nfemaleFirst:\n  - Aine\n  - Aisling\n  - Aoife\n  - Caoimhe\n  - Ciara\n  - Clara\n  - Fiona\n  - Grainne\n  - Karen\n  - Kate\n  - Kathleen\n  - Lisa\n  - Lorna\n  - Mary\n  - Michelle\n  - Niamh\n  - Orla\n  - Rachel\n  - Roisin\n  - Saoirse\n  - Sarah\n  - Shauna\n  - Sinead\n  - Siobhan\nmaleLast:\n  - Brennan\n  - Burke\n  - Byrne\n  - Campbell\n  - Clarke\n  - Collins\n  - Doherty\n  - Doyle\n  - Dunn\n  - Duffy\n  - Farrell\n  - Flanagan\n  - Fitzgerald\n  - Fitzpatrick\n  - Flynn\n  - Gallagher\n  - Kavanagh\n  - Kelly\n  - Kennedy\n  - Lynch\n  - Maguire\n  - McCarthy\n  - McGrath\n  - Moore\n  - Murphy\n  - O'Brien\n  - O'Donnell\n  - O'Neill\n  - Quinn\n  - Reilly\n  - Ryan\n  - Sullivan\n  - Walsh\n  - Whelan\n"
  },
  {
    "path": "bin/common/SoldierName/Italian.nam",
    "content": "lookWeights:\n  - 47\n  - 50\n  - 2\n  - 1\nmaleFirst:\n  - Francesco\n  - Alessandro\n  - Andrea\n  - Lorenzo\n  - Matteo\n  - Mattia\n  - Gabriele\n  - Riccardo\n  - Davide\n  - Leonardo\n  - Federico\n  - Luca\n  - Marco\n  - Giuseppe\n  - Tommaso\n  - Antonio\n  - Simone\n  - Giovanni\n  - Samuele\n  - Christian\n  - Alessio\n  - Nicola\n  - Diego\n  - Pietro\n  - Filippo\n  - Edoardo\n  - Cristian\n  - Daniele\n  - Emanuele\n  - Michele\n  - Gennaro\n  - Vincenzo\n  - Pasquale\n  - Carmine\n  - Carmelo\n  - Paolo\nfemaleFirst:\n  - Sofia\n  - Giulia\n  - Sara\n  - Martina\n  - Giorgia\n  - Chiara\n  - Aurora\n  - Alice\n  - Emma\n  - Alessia\n  - Anna\n  - Francesca\n  - Noemi\n  - Elisa\n  - Matilde\n  - Giada\n  - Gaia\n  - Greta\n  - Elena\n  - Beatrice\n  - Viola\n  - Rebecca\n  - Nicole\n  - Arianna\n  - Ginevra\n  - Vittoria\n  - Asia\n  - Ilaria\n  - Federica\n  - Marta\nmaleLast:\n  - Rossi\n  - Russo\n  - Ferrari\n  - Esposito\n  - Bianchi\n  - Romano\n  - Colombo\n  - Ricci\n  - Marino\n  - Greco\n  - Bruno\n  - Gallo\n  - Conti\n  - De Luca\n  - Mancini\n  - Costa\n  - Giordano\n  - Rizzo\n  - Lombardi\n  - Moretti\n  - Barbieri\n  - Fontana\n  - Santoro\n  - Mariani\n  - Rinaldi\n  - Caruso\n  - Ferrara\n  - Galli\n  - Martini\n  - Leone\n  - Abate\n  - De Simone\n  - Albanese\n  - Genovese\n  - Sansone\n  - Zanon\n"
  },
  {
    "path": "bin/common/SoldierName/Japanese.nam",
    "content": "lookWeight:\n  - 2\n  - 3\n  - 94\n  - 1\nmaleFirst:\n  - Akinori\n  - Akira\n  - Daisuke\n  - Hachiro\n  - Hayate\n  - Hibiki\n  - Hideo\n  - Ichiro\n  - Isamu\n  - Isao\n  - Jungo\n  - Katsuo\n  - Kenji\n  - Masaharu\n  - Masanori\n  - Naohiro\n  - Ren\n  - Ryo\n  - Saburo\n  - Shigeo\n  - Shigeru\n  - Shin\n  - Shinobu\n  - Shuji\n  - Shun\n  - Takashi\n  - Tatsuo\n  - Toshio\n  - Yasuaki\n  - Yataka\n  - Yoshiro\n  - Yuzo\nfemaleFirst:\n  - Aiko\n  - Akane\n  - Ayako\n  - Fuyuko\n  - Haruko\n  - Hitomi\n  - Junko\n  - Kokoro\n  - Mako\n  - Mariko\n  - Michiko\n  - Midori\n  - Misato\n  - Mitsuko\n  - Miu\n  - Miyako\n  - Naomi\n  - Natsumi\n  - Reiko\n  - Sakiko\n  - Sata\n  - Sayoko\n  - Shun\n  - Sumie\n  - Tsukiko\n  - Ume\n  - Yoko\n  - Yoshi\n  - Yumiko\n  - Yuriko\nmaleLast:\n  - Abe\n  - Chiba\n  - Eguchi\n  - Fujimoto\n  - Fujita\n  - Fujiwara\n  - Hasegawa\n  - Hashimoto\n  - Hirano\n  - Ikeda\n  - Ishii\n  - Ito\n  - Iwahara\n  - Iwasaki\n  - Kato\n  - Kawakami\n  - Kikuchi\n  - Kimura\n  - Kobayashi\n  - Kojima\n  - Kondo\n  - Koyama\n  - Masuda\n  - Matsuda\n  - Matsui\n  - Matsumura\n  - Matsushita\n  - Minase\n  - Miyamoto\n  - Miyazaki\n  - Mori\n  - Morita\n  - Musashi\n  - Nakajima\n  - Nakamura\n  - Nakano\n  - Noguchi\n  - Ogawa\n  - Okabe\n  - Okamoto\n  - Ono\n  - Saito\n  - Sato\n  - Shibata\n  - Shimada\n  - Shimaoka\n  - Shizuma\n  - Shoji\n  - Suzuki\n  - Takahashi\n  - Tanaka\n  - Tanida\n  - Tanikawa\n  - Uchida\n  - Ueda\n  - Ukita\n  - Watanabe\n  - Yamanaka\n  - Yamashita\n  - Yamazaki\n  - Yoshimiya\n"
  },
  {
    "path": "bin/common/SoldierName/Kenyan.nam",
    "content": "lookWeights:\n  - 0\n  - 0\n  - 1\n  - 99\nmaleFirst:\n  - Abasi\n  - Adin\n  - Akili\n  - Amali\n  - Amaziah\n  - Ashura\n  - Chege\n  - Chilemba\n  - Chitundu\n  - Chiumbo\n  - Darweshi\n  - Etana\n  - Fadhili\n  - Feruzi\n  - Gachora\n  - Gacoki\n  - Gakere\n  - Gakuru\n  - Gatete\n  - Gathee\n  - Gathii\n  - Gatimu\n  - Gethii\n  - Gichinga\n  - Gicicio\n  - Gikuyu\n  - Githinji\n  - Githogori\n  - Gitonga\n  - Haji\n  - Hala\n  - Hamisi\n  - Hiuhu\n  - Ikinya\n  - Iregi\n  - Irungu\n  - Ita\n  - Itimu\n  - Jaramogi\n  - Jalil\n  - Jimiyu\n  - Jomo\n  - Jamil\n  - Juahar\n  - Jimiyu\n  - Jina\n  - Jirani\n  - Jomo\n  - Kafil\n  - Kagai\n  - Kagunda\n  - Kahiga\n  - Kairu\n  - Kamau\n  - Kamili\n  - Kanja\n  - Kanoro\n  - Karani\n  - Karega\n  - Kariuki\n  - Kereenyaga\n  - Kiambiroiro\n  - Kianjahe\n  - Kiano\n  - Kianyandaarwa\n  - Kiara\n  - Kifimbo\n  - Kihara\n  - Kihiga\n  - Kimathi\n  - Kimotho\n  - Kinoro\n  - Kinyua\n  - Kioi\n  - Kirimi\n  - Kirinyaga\n  - Kithingi\n  - Kiwonto\n  - Koigi\n  - Kuguru\n  - Kwasi\n  - Lipapwiche\n  - Lisimba\n  - Lusala\n  - Macaria\n  - Maina\n  - Maitho\n  - Makalani\n  - Makori\n  - Mathaathi\n  - Matu\n  - Matunde\n  - Maundu\n  - Mbogo\n  - Mbui\n  - Miano\n  - Migwi\n  - Mokabi\n  - Morani\n  - Mosi\n  - Muenda\n  - Muga\n  - Mugendi\n  - Mugi\n  - Mugo\n  - Muiru\n  - Muiruri\n  - Mukanda\n  - Mukiri\n  - Mukuru\n  - Munene\n  - Munoru\n  - Muraguri\n  - Murathi\n  - Muraya\n  - Muriithi\n  - Murimi\n  - Muriu\n  - Muriuki\n  - Muroki\n  - Muruthi\n  - Mutahi\n  - Mutegi\n  - Mutemi\n  - Muthee\n  - Muthemba\n  - Muthengi\n  - Mutheru\n  - Muthomi\n  - Muthuri\n  - Mutira\n  - Mutiri\n  - Mutitu\n  - Mutonyi\n  - Mutua\n  - Muturi\n  - Muugi\n  - Mwaka\n  - Mwangi\n  - Mwara\n  - Mwarania\n  - Mwaria\n  - Mwenda\n  - Nangila\n  - Nangwaya\n  - Ndegwa\n  - Ndemi\n  - Nderu\n  - Ndwiga\n  - Ngare\n  - Ngigi\n  - Ngumo\n  - Njama\n  - Njanu\n  - Njata\n  - Njau\n  - Njiraini\n  - Njiru\n  - Njogu\n  - Njora\n  - Njowga\n  - Njururi\n  - Nyachae\n  - Nyaga\n  - Nyamu\n  - Nyatui\n  - Nyoike\n  - Obama\n  - Obuya\n  - Ochieng\n  - Odikinyi\n  - Odinga\n  - Odonga\n  - Odour\n  - Ohon\n  - Ojwang\n  - Okello\n  - Okeyo\n  - Okoth\n  - Oluoch\n  - Omariba\n  - Omondi\n  - Omwancha\n  - Ongweng\n  - Onindo\n  - Onkwani\n  - Onyango\n  - Opiyo\n  - Osogo\n  - Othiambo\n  - Otenio\n  - Owino\n  - Owiti\n  - Owuor\n  - Pili\n  - Radhi\n  - Riitho\n  - Ruguru\n  - Ruhiu\n  - Runo\n  - Sabra\n  - Safi\n  - Shamim\n  - Shani\n  - Simba\n  - Sokoro\n  - Thabiti\n  - Tumaini\n  - Tuwile\n  - Wachiru\n  - Waga\n  - Waithaka\n  - Waitimu\n  - Waiyaki\n  - Wamai\n  - Wambua\n  - Wamugunda\n  - Wamukota\n  - Wamwara\n  - Wangombe\n  - Wangondu\n  - Wanjala\n  - Wanjohi\n  - Wanyanga\n  - Waruhiu\n  - Warui\n  - Waweru\n  - Wekesa\nfemaleFirst:\n  - Aaliyah\n  - Adhra\n  - Adila\n  - Adimu\n  - Adin\n  - Adla\n  - Afaafa\n  - Afifa\n  - Afifah\n  - Afiya\n  - Afrika\n  - Afya\n  - Ahadi\n  - Aida\n  - Ainra\n  - Ajia\n  - Akello\n  - Akila\n  - Akilah\n  - Akili\n  - Aliya\n  - Almasi\n  - Aluna\n  - Amali\n  - Amana\n  - Amaziah\n  - Amina\n  - Aminah\n  - Aminali\n  - Aminifu\n  - Amira\n  - Amne\n  - Angavu\n  - Anisun\n  - Arafa\n  - Arifa\n  - Arusi\n  - Asali\n  - Asatira\n  - Asha\n  - Ashura\n  - Asilia\n  - Asiya\n  - Asma\n  - Asmahani\n  - Asumini\n  - Asya\n  - Awena\n  - Aza\n  - Aziza\n  - Badriya\n  - Bahati\n  - Bahiya\n  - Barke\n  - Basha\n  - Bashaam\n  - Bashira\n  - Basma\n  - Basmah\n  - Batuuli\n  - Baya\n  - Bayyina\n  - Bebi\n  - Bia\n  - Bimbaya\n  - Bimdogo\n  - Bimkubwa\n  - Bimnono\n  - Bishara\n  - Bitisururu\n  - Bititi\n  - Biubwa\n  - Buqisi\n  - Busara\n  - Bushira\n  - Chaniya\n  - Chausiku\n  - Chiku\n  - Chuki\n  - Dabiku\n  - Dafina\n  - Dalila\n  - Dalili\n  - Damisi\n  - Dhakiya\n  - Dhambizao\n  - Dhuriya\n  - Dodo\n  - Ducha\n  - Duni\n  - Durah\n  - Durra\n  - Eidi\n  - Eshe\n  - Etana\n  - Fadhila\n  - Fadhili\n  - Fadiya\n  - Fadari\n  - Fahima\n  - Fahimah\n  - Faida\n  - Faika\n  - Faiza\n  - Faizah\n  - Fanaka\n  - Fanikia\n  - Faraja\n  - Farashuu\n  - Farida\n  - Farisi\n  - Fasaha\n  - Fathiya\n  - Fatima\n  - Fatuma\n  - Fauziya\n  - Feruzi\n  - Fila\n  - Firdawsi\n  - Firyali\n  - Fujo\n  - Furaha\n  - Gasira\n  - Ghalyela\n  - Ghanima\n  - Gharibuu\n  - Gheche\n  - Ghinjo\n  - Ghipe\n  - Habeebah\n  - Habiba\n  - Habibah\n  - Hadhi\n  - Hadiya\n  - Hafidha\n  - Hafsa\n  - Hafsah\n  - Haiba\n  - Haifa\n  - Hakika\n  - Hakima\n  - Hala\n  - Halili\n  - Halima\n  - Halisi\n  - Hamida\n  - Hanaa\n  - Hanifa\n  - Hanuni\n  - Haoniyao\n  - Harbuu\n  - Hartha\n  - Hasanati\n  - Hashiki\n  - Hasijna\n  - Hasina\n  - Hasnaa\n  - Hawa\n  - Hawla\n  - Hazina\n  - Hediye\n  - Hiari\n  - Hiba\n  - Hidaya\n  - Himidi\n  - Hisani\n  - Huruma\n  - Ibtisam\n  - Ikinya\n  - Ilham\n  - Inaya\n  - Intisar\n  - Ita\n  - Itidal\n  - Jaha\n  - Jahi\n  - Jamila\n  - Jana\n  - Jauhar\n  - Jina\n  - Jirani\n  - Johanna\n  - Johari\n  - Jokha\n  - Jumapili\n  - Juwayria\n  - Kabisa\n  - Kadija\n  - Kainda\n  - Kamaria\n  - Kamili\n  - Kanai\n  - Kanika\n  - Karama\n  - Karima\n  - Karimu\n  - Kaweria\n  - Kesi\n  - Khadija\n  - Kibibi\n  - Kifimbo\n  - Kijakazi\n  - Kinaya\n  - Kioni\n  - Kipenzi\n  - Kisima\n  - Kito\n  - Lamia\n  - Latifa\n  - Latifah\n  - Latifu\n  - Layla\n  - Lela\n  - Lila\n  - Madaha\n  - Madiha\n  - Maisha\n  - Makena\n  - Makini\n  - Malaika\n  - Malia\n  - Malika\n  - Malkia\n  - Mariamu\n  - Marini\n  - Marjani\n  - Mashavu\n  - Masika\n  - Maskini\n  - Maulidi\n  - Merah\n  - Mila\n  - Mosi\n  - Muna\n  - Munira\n  - Murua\n  - Mwajuma\n  - Mwamini\n  - Mwasaa\n  - Nabila\n  - Nadra\n  - Nafula\n  - Naima\n  - Najia\n  - Najma\n  - Nana\n  - Ndege\n  - Neema\n  - Nena\n  - Ngina\n  - Nia\n  - Niara\n  - Njeri\n  - Nuha\n  - Nura\n  - Nuru\n  - Paka\n  - Panya\n  - Pasua\n  - Pili\n  - Rabia\n  - Radhi\n  - Rahma\n  - Ramla\n  - Raziya\n  - Reem\n  - Rehema\n  - Rim\n  - Rukiya\n  - Ruqayah\n  - Saada\n  - Sabiha\n  - Sabra\n  - Sadaka\n  - Sadiki\n  - Saida\n  - Sakina\n  - Sala\n  - Salama\n  - Salima\n  - Samiha\n  - Samira\n  - Sanaa\n  - Sanura\n  - Sauda\n  - Shahida\n  - Shamim\n  - Shani\n  - Sharifa\n  - Shawana\n  - Shukura\n  - Siham\n  - Sikudhani\n  - Siri\n  - Sisya\n  - Siti\n  - Subira\n  - Suhaila\n  - Tabia\n  - Tamasha\n  - Tatu\n  - Tawa\n  - Tuhfa\n  - Tumaini\n  - Wambui\n  - Waseme\n  - Yumna\n  - Pusra\n  - Zahra\n  - Zaida\n  - Zaina\n  - Zainabu\n  - Zakiya\n  - Zalika\n  - Zarifa\n  - Zarina\n  - Zawadi\n  - Zera\n  - Zulaykha\n  - Zulekha\n  - Zuwena\nmaleLast:\n  - Abdullah\n  - Aga\n  - Ahmed\n  - Akina\n  - Ali\n  - Amanaka\n  - Ambani\n  - Amin\n  - Aneko\n  - Asoyo\n  - Atieno\n  - Audi\n  - Badat\n  - Barasa\n  - Bhudia\n  - Bilali\n  - Birir\n  - Biwott\n  - Boit\n  - Chege\n  - Chelimo\n  - Chepchumba\n  - Chudasama\n  - Daar\n  - Echesa\n  - Ekhalie\n  - Ereng\n  - Gikonyo\n  - Inkera\n  - Irungu\n  - Itote\n  - Jakoyo\n  - Janmohamed\n  - Jesani\n  - Kagwe\n  - Kamande\n  - Kamaru\n  - Kamau\n  - Kamotho\n  - Karanja\n  - Karim\n  - Kariuki\n  - Karumba\n  - Kayange\n  - Keino\n  - Kenga\n  - Kenyatta\n  - Kiano\n  - Kibaki\n  - Kijana\n  - Kimathi\n  - Kimunya\n  - Kipketer\n  - Kipyego\n  - Kitur\n  - Koinange\n  - Konde\n  - Lagat\n  - Loroupe\n  - Luseno\n  - Luvutsi\n  - Macharia\n  - Machogu\n  - Magugu\n  - Makacha\n  - Maruti\n  - Masai\n  - Mathenge\n  - Matiba\n  - Mazrui\n  - Mboya\n  - Mdawida\n  - Mehta\n  - Michucki\n  - Migai\n  - Misiani\n  - Modi\n  - Moi\n  - Muchoki\n  - Mudavadi\n  - Muiruri\n  - Mulama\n  - Muliro\n  - Mumba\n  - Murumbi\n  - Murunga\n  - Murungaru\n  - Musyoka\n  - Muttendango\n  - Mwangi\n  - Mwariama\n  - Mwatha\n  - Ndege\n  - Ndereba\n  - Ngei\n  - Ngoche\n  - Ngugi\n  - Njenga\n  - Njonjo\n  - Njoroge\n  - Njue\n  - Ntalami\n  - Nyachae\n  - Nyandoro\n  - Obama\n  - Obanda\n  - Obuya\n  - Ochieng\n  - Odera\n  - Odhiambo\n  - Odinga\n  - Odumbe\n  - Oduol\n  - Oduor\n  - Ogola\n  - Ogot\n  - Okayo\n  - Okoth\n  - Okumu\n  - Oliech\n  - Olum\n  - Omondi\n  - Ongondo\n  - Onyango\n  - Orengo\n  - Origi\n  - Osiako\n  - Otieno\n  - Otunga\n  - Ouko\n  - Ouma\n  - Oyuga\n  - Patel\n  - Pinto\n  - Quaraishy\n  - Ramrakha\n  - Ring\n  - Rombo\n  - Rono\n  - Rubia\n  - Sadiq\n  - Sande\n  - Santos\n  - Serry\n  - Shah\n  - Shaheen\n  - Sharma\n  - Sheikh\n  - Sorongo\n  - Suji\n  - Tergat\n  - Thuku\n  - Tikolo\n  - Tiyoi\n  - Varaiya\n  - Waciuri\n  - Wainaina\n  - Wainana\n  - Wakiihuri\n  - Wambugu\n  - Wanga\n  - Wangila\n  - Wanja\n  - Wanjiru\n  - Wanyama\n  - Wanyoike\n  - Waruinge\n  - Wa Thiongo\n  - Wa Wamwere\n  - Wa Wanjau\n"
  },
  {
    "path": "bin/common/SoldierName/Korean.nam",
    "content": "lookWeights:\n  - 0\n  - 0\n  - 100\n  - 0\nmaleFirst:\n  - Do-hyun\n  - Dong-hyun\n  - Hyun-jun\n  - Hyun-woo\n  - Ji-hoon\n  - Ji-hu\n  - Jun-seo\n  - Jun-young\n  - Joon-ho\n  - Kun-woo\n  - Min-jae\n  - Min-jun\n  - Min-kyu\n  - Seung-hyun\n  - Sung-hyun\n  - Sung-min\n  - Woo-jin\n  - Ye-jun\nfemaleFirst:\n  - Eun-ji\n  - Ha-eun\n  - Hye-jin\n  - Ji-hye\n  - Ji-hyun\n  - Ji-eun\n  - Ji-min\n  - Ji-young\n  - Ji-woo\n  - Min-ji\n  - Min-seo\n  - Seo-hyeon\n  - Seo-yeon\n  - Seo-yun\n  - Seul-ki\n  - Soo-jin\n  - Su-bin\n  - Ye-eun\n  - Yu-jin\n  - Yun-seo\nmaleLast:\n  - A\n  - An\n  - Ae\n  - Bak\n  - Ban\n  - Bang\n  - Bae\n  - Baek\n  - Beom\n  - Byeon\n  - Bok\n  - Bong\n  - Bu\n  - Bi\n  - Bin\n  - Bing\n  - Cha\n  - Chang\n  - Chae\n  - Cheon\n  - Cho\n  - Choe\n  - Chu\n  - Dae\n  - Dan\n  - Dam\n  - Dang\n  - Do\n  - Dokgo\n  - Don\n  - Dong\n  - Dongbang\n  - Du\n  - Eo\n  - Eogeum\n  - Eom\n  - Eun\n  - Eum\n  - Ga\n  - Gae\n  - Gan\n  - Gal\n  - Gam\n  - Gang\n  - Gangjeon\n  - Gyeon\n  - Gyeong\n  - Gye\n  - Go\n  - Gok\n  - Gong\n  - Gwak\n  - Gyo\n  - Gu\n  - Guk\n  - Gun\n  - Gung\n  - Gwok\n  - Gwon\n  - Geun\n  - Geum\n  - Gi\n  - Gil\n  - Gim\n  - Ha\n  - Hak\n  - Han\n  - Ham\n  - Hae\n  - Heo\n  - Hyeon\n  - Hyeong\n  - Ho\n  - Hong\n  - Hwa\n  - Hwan\n  - Hwang\n  - Hwangbo\n  - Hu\n  - Heung\n  - I\n  - In\n  - Im\n  - Ja\n  - Jang\n  - Janggok\n  - Jeo\n  - Jeon\n  - Jeom\n  - Jeong\n  - Je\n  - Jegal\n  - Jo\n  - Jong\n  - Jwa\n  - Ju\n  - Jun\n  - Jeup\n  - Jeung\n  - Ji\n  - Jin\n  - Ma\n  - Mae\n  - Maeng\n  - Man\n  - Mangjeol\n  - Myeong\n  - Mo\n  - Moj\n  - Myo\n  - Muk\n  - Mun\n  - Mi\n  - Min\n  - Na\n  - Nae\n  - Nan\n  - Nam\n  - Namgung\n  - Nang\n  - No\n  - Noe\n  - Nu\n  - O\n  - Ok\n  - On\n  - Ong\n  - Pan\n  - Paeng\n  - Pyeon\n  - Pyeong\n  - Po\n  - Pyo\n  - Pung\n  - Pi\n  - Pil\n  - Ra\n  - Ran\n  - Rang\n  - Ri\n  - Rim\n  - Ro\n  - Roe\n  - Ru\n  - Ryeo\n  - Ryeon\n  - Ryeom\n  - Ryong\n  - Ryu\n  - Ryuk\n  - Sa\n  - Sagong\n  - Sam\n  - Sang\n  - Seo\n  - Seomun\n  - Seok\n  - Seon\n  - Seonu\n  - Seol\n  - Seop\n  - Seong\n  - So\n  - Sobong\n  - Son\n  - Song\n  - Su\n  - Sun\n  - Seung\n  - Si\n  - Sin\n  - Sim\n  - Sip\n  - Tak\n  - Tan\n  - Tae\n  - U\n  - Un\n  - Wang\n  - Won\n  - Wi\n  - Ya\n  - Yang\n  - Ye\n  - Yeo\n  - Yeon\n  - Yeom\n  - Yeop\n  - Yeong\n  - Yo\n  - Yong\n  - Yu\n  - Yuk\n  - Yun\n"
  },
  {
    "path": "bin/common/SoldierName/Nigerian.nam",
    "content": "lookWeight:\n  - 0\n  - 0\n  - 0\n  - 100\nmaleFirst:\n  - Abassi\n  - Abayomi\n  - Abejide\n  - Abiodun\n  - Abiola\n  - Adebayo\n  - Adejola\n  - Adisa\n  - Adunbi\n  - Ajala\n  - Ajani\n  - Akanni\n  - Akin\n  - Akinlabi\n  - Akinlana\n  - Akins\n  - Akono\n  - Amadi\n  - Aniweta\n  - Apara\n  - Ayodele\n  - Azagba\n  - Babafemi\n  - Bem\n  - Boseda\n  - Chidike\n  - Chijioke\n  - Chike\n  - Chukwuma\n  - Dada\n  - David\n  - Dumaka\n  - Ehioze\n  - Ekundayo\n  - Emeka\n  - Emmanuel\n  - Ewansiha\n  - Ezekiel\n  - Fasina\n  - Gowo\n  - Idowu\n  - Imarogbe\n  - Isah\n  - Iyapo\n  - Jaja\n  - Jumoke\n  - Kayode\n  - Kehinde\n  - Kosoko\n  - Kwame\n  - Madu\n  - Mazi\n  - Modupe\n  - Morihinze\n  - Moses\n  - Ndulu\n  - Ngozi\n  - Nosakhere\n  - Nwabudike\n  - Obasi\n  - Obataiye\n  - Obayana\n  - Obi\n  - Obike\n  - Ode\n  - Odion\n  - Ogbonna\n  - Okechuku\n  - Okpara\n  - Oladele\n  - Olafemi\n  - Olaniyan\n  - Olawale\n  - Olawutobi\n  - Olubayo\n  - Olufemi\n  - Olugbala\n  - Olujimi\n  - Olumide\n  - Olumiji\n  - Olushola\n  - Oluwa\n  - Oluwaseyi\n  - Oluyemi\n  - Omolara\n  - Omorede\n  - Onuwachi\n  - Opeyemi\n  - Osahar\n  - Osakwe\n  - Osayaba\n  - Osayande\n  - Osayimwese\n  - Osaze\n  - Samuel\n  - Stanley\n  - Sunday\n  - Taiwo\n  - Tobi\n  - Echechi\n  - Uzoma\n  - Weke\n  - Worie\nfemaleFirst:\n  - Abagbe\n  - Abagebe\n  - Abayomi\n  - Abebi\n  - Abegbe\n  - Abeje\n  - Abeke\n  - Abena\n  - Abeo\n  - Abidemi\n  - Abimbola\n  - Abiona\n  - Abisola\n  - Adamma\n  - Adanna\n  - Adanya\n  - Adebola\n  - Adebomi\n  - Adedagbo\n  - Adedewe\n  - Adedoja\n  - Adeleke\n  - Adenrele\n  - Adeola\n  - Aderinola\n  - Adesimbo\n  - Adesina\n  - Adeyemi\n  - Adio\n  - Adjoa\n  - Aduke\n  - Aina\n  - Aiyetoro\n  - Ajala\n  - Ajani\n  - Akanke\n  - Alaba\n  - Alke\n  - Ama\n  - Amonke\n  - Annakiya\n  - Anuli\n  - Arria\n  - Asabi\n  - Auta\n  - Ayo\n  - Ayobami\n  - Ayobunmi\n  - Ayodele\n  - Ayofemi\n  - Ayoka\n  - Ayoluwa\n  - Ayomide\n  - Ayoola\n  - Azalee\n  - Baderinwa\n  - Baina\n  - Bayo\n  - Becca\n  - Bekide\n  - Binah\n  - Bolade\n  - Bolanile\n  - Bunmi\n  - Chidimma\n  - Chika\n  - Chinonso\n  - Chinue\n  - Chioma\n  - Chisom\n  - Chizoba\n  - Cynthia\n  - Dada\n  - Danuwa\n  - Daurama\n  - Dayo\n  - Dubaku\n  - Dumaka\n  - Ebele\n  - Ebun\n  - Edenausegbo\n  - Ehizemen\n  - Ekaghogho\n  - Exenesenarh\n  - Enomwoyi\n  - Esosa\n  - Etinosa\n  - Fabayo\n  - Faraa\n  - Farih\n  - Fayola\n  - Fayolla\n  - Femi\n  - Fola\n  - Folade\n  - Folami\n  - Folashade\n  - Dolayan\n  - Foluke\n  - Gimbya\n  - Hanna\n  - Hasana\n  - Hazika\n  - Hembadoon\n  - Idowu\n  - Ifama\n  - Ife\n  - Ifetayo\n  - Ige\n  - Ijaba\n  - Ikuseghan\n  - Innya\n  - Irawagbon\n  - Isoke\n  - Iverem\n  - Iyabo\n  - Izegbe\n  - Joy\n  - Jumoke\n  - Kehinde\n  - Kinah\n  - Kiziah\n  - Kokumo\n  - Limber\n  - Lina\n  - Lisha\n  - Marjorie\n  - Mbafor\n  - Mbeke\n  - Mhonum\n  - Monifa\n  - Morayo\n  - Natashenka\n  - Ngozi\n  - Nkiruka\n  - Nneka\n  - Nnenaya\n  - Nnenia\n  - Nsia\n  - Nourbese\n  - Nwakaeo\n  - Obioma\n  - Ode\n  - Ofure\n  - Olabunmi\n  - Olaniyi\n  - Olateju\n  - Olayinka\n  - Olubayo\n  - Olubunmi\n  - Olufemi\n  - Olufunke\n  - Olufunmilayo\n  - Oluremi\n  - Omalara\n  - Omolara\n  - Omorenoniwara\n  - Omorose\n  - Omosede\n  - Omosupe\n  - omusupe\n  - Oni\n  - Onyeka\n  - Osayioniwabo\n  - Osemweoyenmwen\n  - Oseye\n  - Sade\n  - Shade\n  - Shiminege\n  - Tanisha\n  - Thema\n  - Theresa\n  - Titilayo\n  - Tobi\n  - Uchefuna\n  - Urbi\n  - Yahimba\n  - Yejide\n  - Yetunde\n  - Yewande\n  - Zuna\nmaleLast:\n  - Abdul\n  - Abiodun\n  - Abubakar\n  - Achebe\n  - Adebayo\n  - Adebiyi\n  - Adeyemi\n  - Ahmadu\n  - Aimeihi\n  - Ajuonuma\n  - Akubueze\n  - Alamieyeseigha\n  - Alli\n  - Alvana\n  - Amadi\n  - Amaechi\n  - Amaka\n  - Anakobe\n  - Anjola\n  - Anyene\n  - Arokoyo\n  - Awani\n  - Awiyetu\n  - Awolowo\n  - Aynaw\n  - Ayoola\n  - Babangida\n  - Bugaje\n  - Chidinma\n  - Chinwe\n  - Chukwu\n  - Claaseen\n  - Dhose\n  - Ebuka\n  - Ehi\n  - Ehimen\n  - Ejogo\n  - Eke\n  - Ekwensi\n  - Enuma\n  - Eseoghene\n  - Eventus\n  - Eze\n  - Ezugo\n  - Falmata\n  - Farida\n  - Femi\n  - Garba\n  - Hope\n  - Ibe\n  - Ibori\n  - Ibrahim\n  - Ibru\n  - Ibukun\n  - Iheme\n  - Iniebong\n  - Inusa\n  - Itsifanus\n  - Jangana\n  - Jonathan\n  - Jolawole\n  - Lamidi\n  - Lawal\n  - Madaki\n  - Mahmud\n  - Maikudi\n  - Mantakari\n  - Martins\n  - Mbana\n  - Mbanefo\n  - Memuna\n  - Mohammed\n  - Mshelia\n  - Ngwube\n  - Njoku\n  - Obiola\n  - Obrutse\n  - Ochigbo\n  - Ochonogo\n  - Ogechi\n  - Okah\n  - Okafor\n  - Okeke\n  - Okere\n  - Okereke\n  - Okonkwo\n  - Okoye\n  - Olaoluwa\n  - Olugbenga\n  - Olukayode\n  - Olumide\n  - Olumodeji\n  - Olusanmi\n  - Oluwadamilare\n  - Oluwakemi\n  - Oluwayomi\n  - Oni\n  - Onita\n  - Onyinjuke\n  - Opara\n  - Orakwe\n  - Otaru\n  - Otatoru\n  - Rajuli\n  - Raphael\n  - Saraki\n  - Sekibo\n  - Shuta\n  - Sunny\n  - Temitope\n  - Tosin\n  - Uba\n  - Udoh\n  - Ugbabio\n  - Usman\n  - Wale\n  - Yar-adua\n  - Yindadi\n"
  },
  {
    "path": "bin/common/SoldierName/Norwegian.nam",
    "content": "lookWeights:\n  - 50\n  - 43\n  - 7\n  - 0\nmaleFirst:\n  - Adrian\n  - Aleksander\n  - Alexander\n  - Alf\n  - Alfred\n  - Anders\n  - Andreas\n  - Anton\n  - Arne\n  - Artur\n  - Arvid\n  - Asbjoorn\n  - Atle\n  - Balder\n  - Baldur\n  - Benjamin\n  - Bjorn\n  - Boone\n  - Borg\n  - Brander\n  - Burnaby\n  - Burr\n  - Busby\n  - Cadby\n  - Canute\n  - Carr\n  - Cawley\n  - Christian\n  - Christoffer\n  - Colby\n  - Dag\n  - Danby\n  - Delling\n  - Daniel\n  - Didrik\n  - Edvard\n  - Einar\n  - Eirik\n  - Elvis\n  - Emil\n  - Eric\n  - Erik\n  - Erlend\n  - Erling\n  - Espen\n  - Even\n  - Fredrik\n  - Frode\n  - Gunnar\n  - Haakon\n  - Haavard\n  - Hans\n  - Harald\n  - Havard\n  - Henning\n  - Henrik\n  - Inge\n  - Ivar\n  - Jakob\n  - Jan\n  - Jens\n  - Joachim\n  - Joakim\n  - Johan\n  - Jokkum\n  - Jon\n  - Jonas\n  - Jorgen\n  - Julius\n  - Kare\n  - Karl\n  - Kjell\n  - Knut\n  - knute\n  - Kristian\n  - Kristoffer\n  - Lars\n  - Leif\n  - Ludvik\n  - Mads\n  - Magnus\n  - Marcus\n  - Marius\n  - Martin\n  - Martinus\n  - Mathias\n  - Matias\n  - Mats\n  - Mikkel\n  - Mons\n  - Nikolai\n  - Nils\n  - Olaf\n  - Olan\n  - Ole\n  - Pal\n  - Paul\n  - Peder\n  - Per\n  - Petter\n  - Reidar\n  - Rolf\n  - Sander\n  - Sebastian\n  - Sigurd\n  - Simen\n  - Sindre\n  - Stian\n  - Svein\n  - Svend\n  - Sverre\n  - Thomas\n  - Thor\n  - Tobias\n  - Tomas\n  - Tor\n  - Vegar\n  - Vegard\nfemaleFirst:\n  - Abigael\n  - Adelis\n  - Agot\n  - Alberte\n  - Alfhild\n  - Ane\n  - Annbjorg\n  - Annborg\n  - Arnbjorg\n  - Asdis\n  - Aslaug\n  - Benedikte\n  - Bergit\n  - Bergliot\n  - Berit\n  - Brigit\n  - Canutte\n  - Cathrine\n  - Dagrun\n  - Fredrika\n  - Gerdy\n  - Grete\n  - Grethe\n  - Gry\n  - Gudlaug\n  - Gunnhild\n  - Gunnvor\n  - Halldora\n  - Hege\n  - Heidrun\n  - Hjordis\n  - Idunn\n  - Ingebjorg\n  - Ingfrid\n  - Inghild\n  - Ingvild\n  - Janne\n  - Johanne\n  - Jorunn\n  - Kanutte\n  - Kari\n  - Karita\n  - Karoline\n  - Kirsten\n  - Kjellfrid\n  - Kjersti\n  - Kjerstin\n  - Kristi\n  - Kristine\n  - Lise\n  - Lovise\n  - Magnhild\n  - Margarete\n  - Margarethe\n  - Margrethe\n  - Marit\n  - Rebekka\n  - Silje\n  - Sofia\n  - Solaug\n  - Thorbjorg\n  - Torbjorg\n  - Torhilda\n  - Torid\n  - Toril\n  - Urd\n  - Valdis\n  - Vendela\n  - Vibeke\n  - Viva\n  - Waldis\n  - Yngvild\nmaleLast:\n  - Aamodt\n  - Aas\n  - Aasen\n  - Aasgaard\n  - Abel\n  - Abrahamsen\n  - Alsgaard\n  - Alving\n  - Amundsen\n  - Amundson\n  - Andersen\n  - Andreassen\n  - Andresen\n  - Andsnes\n  - Antonisen\n  - Antonsen\n  - Arnesen\n  - Arup\n  - Asheim\n  - Aune\n  - Bakke\n  - Bakken\n  - Balle\n  - Baltzersen\n  - Berg\n  - Berge\n  - Berntsen\n  - Birkeland\n  - Birknes\n  - Bjoenkaer\n  - Bjoerndalen\n  - Bjone\n  - Bjordal\n  - Bjorlo\n  - Bjornebye\n  - Bjornson\n  - Bjornstad\n  - Blix\n  - Bo\n  - Bocklin\n  - Boe\n  - Borkman\n  - Brack\n  - Brandes\n  - Brat\n  - Brataas\n  - Bredesen\n  - Brekke\n  - Brenden\n  - Brogger\n  - Brovik\n  - Buraas\n  - Burass\n  - Christensen\n  - Christiansen\n  - Daehle\n  - Daehlie\n  - Dahl\n  - Dahn\n  - Dahue\n  - Danielsen\n  - Dybendahl\n  - Edvardsen\n  - Eftevang\n  - Eggen\n  - Eide\n  - Eliassen\n  - Elieson\n  - Ellingsen\n  - Elvsted\n  - Engen\n  - Enger\n  - Englund\n  - Engstrand\n  - Eriksen\n  - Ertzgard\n  - Evensen\n  - Fagerberg\n  - Fagernes\n  - Falck\n  - Fjaerestad\n  - Fjortoft\n  - Flemmen\n  - Flo\n  - Folkow\n  - Fosli\n  - Franck\n  - Fredriksen\n  - Fretheim\n  - Fuglesang\n  - Fuglestad\n  - Furuseth\n  - Gabler\n  - Gabrielsen\n  - Garborg\n  - Gimle\n  - Gjeldnes\n  - Gjelland\n  - Gjessing\n  - Grieg\n  - Grimseth\n  - Grimsmo\n  - Gritdal\n  - Grodas\n  - Groenvold\n  - Gronelv\n  - Guidon\n  - Gulbrandsen\n  - Gundersen\n  - Gunderson\n  - Gunnestad\n  - Gylfason\n  - Haakonsen\n  - Haarberg\n  - Haarland\n  - Haartz\n  - Hagen\n  - Halskar\n  - Halvorsen\n  - Hammer\n  - Hanevold\n  - Hanke\n  - Hansen\n  - Hanssen\n  - Hanstveit\n  - Hartmark\n  - Hasso\n  - Hasund\n  - Haug\n  - Hauge\n  - Haugen\n  - Haugland\n  - Haugsrud\n  - Heiberg\n  - Helgeland\n  - Helgerod\n  - Helland\n  - Helmer\n  - Henriksen\n  - Herdal\n  - Heyerdahl\n  - Hoan\n  - Hoeg\n  - Hoen\n  - Holm\n  - Holmann\n  - Holth\n  - Hopen\n  - Horn\n  - Hultgreen\n  - Hustveit\n  - Ibsen\n  - Ingebriktsson\n  - Ingstad\n  - Isaksen\n  - Iversen\n  - Jacobsen\n  - Jagge\n  - Jakobsen\n  - Jasperson\n  - Jelesens\n  - Jensen\n  - Jenssen\n  - Jevne\n  - Johannessen\n  - Johansen\n  - Johnsen\n  - Jorgensen\n  - Juell\n  - Kaland\n  - Karlan\n  - Karlsen\n  - Kase\n  - Kildal\n  - Kippe\n  - Kjeldaas\n  - Kjelstrup\n  - Kjorestad\n  - Kjorsvik\n  - Klovstod\n  - Knudsen\n  - Knutsen\n  - Koht\n  - Koss\n  - Krafft\n  - Kristensen\n  - Kristiansen\n  - Kristoffersen\n  - Krogstad\n  - Kultin\n  - Kvarme\n  - Landa\n  - Langslet\n  - Lanser\n  - Larsen\n  - Leirfall\n  - Leonhardsen\n  - Lid\n  - Lie\n  - Lien\n  - Lier\n  - Lind\n  - Lindahl\n  - Linde\n  - Listow\n  - Ljoekelsoey\n  - Loevaas\n  - Lorch\n  - Lous\n  - Lovborg\n  - Ludwigsen\n  - Lund\n  - Lunde\n  - Lyen\n  - Malmros\n  - Malmstrom\n  - Manders\n  - Marken\n  - Martinsen\n  - Mathiesen\n  - Mathisen\n  - Meling\n  - Meyer\n  - Midttun\n  - Mikkelsen\n  - Mikkelsplass\n  - Mo\n  - Moen\n  - Mork\n  - Mostue\n  - Munch\n  - Myhre\n  - Mykland\n  - Myklebust\n  - Myrland\n  - Naess\n  - Nanstveit\n  - Naustvik\n  - Neilsen\n  - Nerhus\n  - Nielsen\n  - Nilsen\n  - Njerve\n  - Njos\n  - Noberg\n  - Nore\n  - Nyberg\n  - Nygard\n  - Odegard\n  - Oedegaard\n  - Oesten\n  - Olsen\n  - Omholt\n  - Orden\n  - Orthe\n  - Ostenstad\n  - Ottesen\n  - Paldan\n  - Paulsen\n  - Pedersen\n  - Pederssen\n  - Pettersen\n  - Poulsen\n  - Prydz\n  - Ramsfeld\n  - Ramsfjell\n  - Rank\n  - Ranning\n  - Rasmussen\n  - Ratkje\n  - Rekdal\n  - Resi\n  - Retter\n  - Ribur\n  - Riseth\n  - Rodahl\n  - Rovlund\n  - Ruud\n  - Saeterstoel\n  - Saether\n  - Salvesen\n  - Sandvik\n  - Schei\n  - Schjerven\n  - Schroder\n  - Schwane\n  - Schytte\n  - Selle\n  - Selling\n  - Selvik\n  - Sikveland\n  - Simonsen\n  - Sivertsen\n  - Sivertson\n  - Sivlee\n  - Sjo\n  - Sjovold\n  - Skarsgaard\n  - Skarsgard\n  - Skavlan\n  - Skjelbraid\n  - Skjolsvold\n  - Skovgaard\n  - Skreien\n  - Smilla\n  - Solbakken\n  - Solbakker\n  - Solberg\n  - Solheim\n  - Solness\n  - Solskaer\n  - Sondral\n  - Sorensen\n  - Stamso\n  - Steen\n  - Stensrud\n  - Stianson\n  - Stirner\n  - Storelid\n  - Stram\n  - Strand\n  - Strandli\n  - Svasand\n  - Svendson\n  - Svenoy\n  - Syversen\n  - Tangen\n  - Tangvik\n  - Tesman\n  - Thomassen\n  - Thonstad\n  - Thoresen\n  - Thorsen\n  - Thue\n  - Thulesius\n  - Thune\n  - Thymann\n  - Tobiassen\n  - Tonder\n  - Tonsberg\n  - Torgereen\n  - Torp\n  - Traa\n  - Tunold\n  - Tveit\n  - Ulstein\n  - Ulving\n  - Utskjoer\n  - Veitberg\n  - Vigeland\n  - Vik\n  - Vind\n  - Waldum\n  - Wangel\n  - Wangen\n  - Wassmo\n  - Wikborg\n  - Wullum\n  - Yons\n  - Ytterhus\n  - Zakariassen\n"
  },
  {
    "path": "bin/common/SoldierName/Polish.nam",
    "content": "lookWeights:\n  - 50\n  - 50\n  - 0\n  - 0\nmaleFirst:\n  - Jan\n  - Andrzej\n  - Piotr\n  - Krzysztof\n  - Stanislaw\n  - Tomasz\n  - Pawel\n  - Jozef\n  - Marcin\n  - Marek\n  - Michal\n  - Grzegorz\n  - Jerzy\n  - Tadeusz\n  - Adam\n  - Lukasz\n  - Zbigniew\n  - Ryszard\n  - Dariusz\n  - Henryk\n  - Mariusz\n  - Kazimierz\n  - Wojciech\n  - Robert\n  - Mateusz\n  - Marian\n  - Rafal\n  - Jacek\n  - Janusz\n  - Miroslaw\nfemaleFirst:\n  - Anna\n  - Maria\n  - Katarzyna\n  - Malgorzata\n  - Agnieszka\n  - Krystyna\n  - Barbara\n  - Ewa\n  - Elzbieta\n  - Zofia\n  - Janina\n  - Teresa\n  - Joanna\n  - Magdalena\n  - Monika\n  - Jadwiga\n  - Danuta\n  - Irena\n  - Halina\n  - Helena\n  - Beata\n  - Aleksandra\n  - Marta\n  - Dorota\n  - Marianna\n  - Grazyna\n  - Jolanta\n  - Stanislawa\n  - Iwona\n  - Karolina\nmaleLast:\n  - Nowak\n  - Kowalski\n  - Wisniewski\n  - Dabrowski\n  - Lewandowski\n  - Wojcik\n  - Kaminski\n  - Kowalczyk\n  - Zielinski\n  - Szymanski\n  - Wozniak\n  - Kozlowski\n  - Jankowski\n  - Wojciechowski\n  - Kwiatkowski\n  - Kaczmarek\n  - Mazur\n  - Krawczyk\n  - Piotrowski\n  - Grabowski\n  - Nowakowski\n  - Pawlowski\n  - Michalski\n  - Nowicki\n  - Adamczyk\n  - Dudek\n  - Zajac\n  - Wieczorek\n  - Jablonski\n  - Krol\nfemaleLast:\n  - Nowak\n  - Kowalska\n  - Wisniewska\n  - Dabrowska\n  - Lewandowska\n  - Wojcik\n  - Kaminska\n  - Kowalczyk\n  - Zielinska\n  - Szymanska\n  - Wozniak\n  - Kozlowska\n  - Jankowska\n  - Wojciechowska\n  - Kwiatkowska\n  - Kaczmarek\n  - Mazur\n  - Krawczyk\n  - Piotrowska\n  - Grabowska\n  - Nowakowska\n  - Pawlowska\n  - Michalska\n  - Nowicka\n  - Adamczyk\n  - Dudek\n  - Zajac\n  - Wieczorek\n  - Jablonska\n  - Krol\n"
  },
  {
    "path": "bin/common/SoldierName/Polynesia.nam",
    "content": "lookWeights:\n  - 0\n  - 2\n  - 49\n  - 49\nmaleFirst:\n  - Aata\n  - Ata\n  - Atawhai\n  - Ahia\n  - Ahinariki\n  - Ahipene\n  - Apirana\n  - Apera\n  - Aperahama\n  - Arapeta\n  - Etera\n  - Hahona\n  - Haimona\n  - Haki\n  - Hara\n  - Hari\n  - Hatarei\n  - Hau\n  - Hehu\n  - Heketoro\n  - Hemi\n  - Hirini\n  - Hiruharama\n  - Hohepa\n  - Honi\n  - Honoiwairua\n  - Hukarere\n  - Hunapo\n  - Iarere\n  - Iehohapata\n  - Ieni\n  - Ietepere\n  - Ietoro\n  - Ihaia\n  - Ihaka\n  - Iharaira\n  - Ihimaera\n  - Ihipa\n  - Ihu\n  - Ikaroa\n  - Inoke\n  - Iorama\n  - Iorangi\n  - Iotama\n  - Ira\n  - Iraia\n  - Iwi\n  - Kai\n  - Kaihautu\n  - Kaili\n  - Kale\n  - Kamaka\n  - Kapena\n  - Kapono\n  - Keahi\n  - Keanu\n  - Kiritowha\n  - Konala\n  - Loe\n  - Mana\n  - Marama\n  - Matiu\n  - Maui\n  - Pio\n  - Piripi\n  - Rangi\n  - Ra\n  - Rameka\n  - Rapata\n  - Rongo\n  - Ruru\n  - Taine\n  - Tama\n  - Tamati\n  - Tane\n  - Tanemahuta\n  - Hatfacoa\n  - Tangi\n  - Tautoru\n  - Tui\n  - Wi\n  - Wiremu\n  - Wiri\n  - Wirimu\nfemaleFirst:\n  - Ahere\n  - Ahorangi\n  - Ahuaiti\n  - Ahurewa\n  - Alamea\n  - Aolani\n  - Aratiki\n  - Arikiwi\n  - Aroha\n  - Arorangi\n  - Aruhe\n  - Awa\n  - Awi\n  - Ehetere\n  - Emauha\n  - Emere\n  - Emiri\n  - Epa\n  - Erena\n  - Erene\n  - Erenora\n  - Eruini\n  - Haeata\n  - Hahana\n  - Hakeke\n  - Hanga\n  - Harakeke\n  - Harata\n  - Haukiwaho\n  - Hauku\n  - Haumiaroa\n  - Hauora\n  - Haupuku\n  - Haurahi\n  - Hekeheke\n  - Heni\n  - Hepetema\n  - Hera\n  - Herene\n  - Hihiri\n  - Hinapouri\n  - Hine\n  - Hineana\n  - Hinemoana\n  - Hiri\n  - Hoane\n  - Hoata\n  - Hokioi\n  - Honemoana\n  - Horiana\n  - Horowai\n  - Hotoke\n  - Huhana\n  - Huia\n  - Hukapapa\n  - Ihapera\n  - Inia\n  - Iolana\n  - Irapeta\n  - Irihapeti\n  - Iritana\n  - Irueca\n  - Iucihi\n  - Iwa\n  - Iwalani\n  - Kahikatoa\n  - Kahu\n  - Kahurangi\n  - Kaiarahi\n  - Kaihautu\n  - Kaitaka\n  - Kakama\n  - Kakarauri\n  - Kakariki\n  - Kalea\n  - Kamea\n  - Keoni\n  - Kieli\n  - Kinipela\n  - Kiri\n  - Konane\n  - Kowhai\n  - Mariama\n  - Lahela\n  - Lani\n  - Lealani\n  - Leiko\n  - Liko\n  - Liliha\n  - Luana\n  - Lulani\n  - Maile\n  - Makani\n  - Mahinaarangi\n  - Maleah\n  - Malo\n  - Manaia\n  - Mele\n  - Miliani\n  - Moana\n  - Nalanie\n  - Ngaire\n  - Nohealani\n  - Oke\n  - Onaona\n  - Papatuanuku\n  - Peata\n  - Petani\n  - Palila\n  - Pekelo\n  - Pilialoha\n  - Tama\n  - Tino Aroha\n  - Ulani\n  - Wiki\n  - Wikitoria\nmaleLast:\n  - Amai\n  - Aperahama\n  - Atama\n  - Ahipene\n  - Ahitana\n  - Ahuriri\n  - Aihue\n  - Akara\n  - Akariri\n  - Akuhata\n  - Alana\n  - Amohanga\n  - Anaha\n  - Anaru\n  - Aotea\n  - Apatari\n  - Acatui\n  - Ariari\n  - A Tau\n  - Atutahi\n  - Awanui\n  - Awatere\n  - Ema\n  - Eparaima\n  - Erueti\n  - Haehae\n  - Haira\n  - Hakaraia\n  - Hakopa\n  - Hale\n  - Hamahona\n  - Hape\n  - Hapeta\n  - Hapi\n  - Hapimana\n  - Hapuku\n  - Harakeke\n  - Harata\n  - Harawira\n  - Hari\n  - Hatarini\n  - Hatata\n  - Hati\n  - Haturini\n  - Hau\n  - Haua\n  - Hauiti\n  - Haukamau\n  - Hauraki\n  - Hautapu\n  - Hautonga\n  - Hautu\n  - Hawea\n  - Heka\n  - Hekekia\n  - Hemania\n  - Hemara\n  - Henare\n  - Herangi\n  - Herekiuha\n  - Hereora\n  - Heretini\n  - Herewini\n  - Heta\n  - Hetaraka\n  - Heteriki\n  - Hikawai\n  - Himiona\n  - Hinekura\n  - Hinerangi\n  - Hinerau\n  - Hinga\n  - Hireme\n  - Hirini\n  - Hita\n  - Hoani\n  - Hoepo\n  - Hoera\n  - Hoeta\n  - Hohaia\n  - Hohapata\n  - Hohepa\n  - Hohia\n  - Hokianga\n  - Hokotoki\n  - Hona\n  - Hone\n  - Honetana\n  - Hongi\n  - Hoori\n  - Hopa\n  - Hori\n  - Horohau\n  - Horomona\n  - Horua\n  - Hoterene\n  - Hotu\n  - Huatahi\n  - Huhu\n  - Huiarangia\n  - Huka\n  - Humana\n  - Hunua\n  - Hura\n  - Huritu\n  - Huriwaka\n  - Ihaea\n  - Ihaia\n  - Iona\n  - Irihapete\n  - Irimana\n  - Iti\n  - Kahale\n  - Kahananui\n  - Kahele\n  - Kahiwai\n  - Kahiwirori\n  - Kahue\n  - Kahukakanui\n  - Kahukura\n  - Kaihau\n  - Kaimoana\n  - Kainamu\n  - Kaingariro\n  - Kainuku\n  - Kaipapa\n  - Kairau\n  - Kaire\n  - Kaiteke\n  - Kaiwi\n  - Kakewahine\n  - Kalama\n  - Kalani\n  - Kalawai'a\n  - Kalili\n  - Kalua\n  - Kama\n  - Kamaka\n  - Kamealoha\n  - Kamira\n  - Kamuwai\n  - Kaneri\n  - Kanuta\n  - Kapene\n  - Kaponga\n  - Kapule\n  - Karahina\n  - Karaitiana\n  - Karaka\n  - Karakiakore\n  - Karamaena\n  - Kararene\n  - Karati\n  - Karekare\n  - Kareko\n  - Karena\n  - Katene\n  - Katete\n  - Katipa\n  - Kauamo\n  - Kaui\n  - Kaukau\n  - Kaura\n  - Kautarewa\n  - Kawana\n  - Kawai\n  - Kawau\n  - Ka'ana'ana\n  - Ka'aukai\n  - Ka'uhane\n  - Kawiti\n  - Keahi\n  - Kealoha\n  - Keawe\n  - Kepa\n  - Kekoa\n  - Kelekolio\n  - Keli'i\n  - Kena\n  - Keno\n  - Kepa\n  - Kerapa\n  - Kereama\n  - Kerei\n  - Keremeneta\n  - Kereoma\n  - Kereopa\n  - Kerepeti\n  - Kereru\n  - Kereti\n  - Kewa\n  - Kiarie\n  - Kimura\n  - Kingi\n  - Kinihe\n  - Kino Te Ahiwaka\n  - Kirikino\n  - Kirikiri\n  - Kiriwi\n  - Kiwara\n  - Koha\n  - Kohena\n  - Kohikikko\n  - Kohu\n  - Kokiri\n  - Komene\n  - Koni\n  - Koperau\n  - Kopiri\n  - Koroheke\n  - Korohunga\n  - Koroi Ngawhau\n  - Kotuhi\n  - Kouku\n  - Kupa\n  - Kurawhatia\n  - Kuru\n  - Kuti\n  - Kane\n  - Maaka\n  - Maeka\n  - Maere\n  - Mahaka\n  - Mahauariki\n  - Mahelona\n  - Mahe'ai\n  - Mahia\n  - Mahima\n  - Mahoe\n  - Mahoe\n  - Mahu\n  - Mahuta\n  - Mahutoto\n  - Maihi\n  - Maipi\n  - Maka\n  - Makara\n  - Makatea\n  - Makawe\n  - Makiha\n  - Makiri\n  - Manawaroa\n  - Mane\n  - Mangu\n  - Mania\n  - Maniapoto\n  - Manihera\n  - Mare\n  - Mareroa\n  - Marino\n  - Marore\n  - Marupo\n  - Matakorama\n  - Matene\n  - Matenga\n  - Materoa\n  - Matewhitu\n  - Mau\n  - Mauhana\n  - Mauheni\n  - Maukau\n  - Mauwhata\n  - Mawe\n  - Mawhiu\n  - Metua\n  - Mihinui\n  - Mikaere\n  - Miki\n  - Minapara\n  - Mio\n  - Moananui\n  - Moeahu\n  - Moera\n  - Meoroa\n  - Mohi\n  - Moka\n  - Moke\n  - Moke Te Ora\n  - Monita\n  - Morehu\n  - Morete\n  - Morunga\n  - Motutere\n  - Muriwai\n  - Muru\n  - Munu\n  - Natana\n  - Nawaia\n  - Neho\n  - Nehua\n  - Nene\n  - Nepia\n  - Ngahere\n  - Ngahiwi\n  - Ngahoro\n  - Ngaia\n  - Ngaio\n  - Ngakaho\n  - Ngamoenga\n  - Ngamoki\n  - Ngamu\n  - Ngapune\n  - Ngare\n  - Ngarara\n  - Ngata\n  - Ngatai\n  - Ngataierua\n  - Ngataki\n  - Ngatoko\n  - Ngatono\n  - Ngawe\n  - Ngawharau\n  - Ngerengere\n  - Ngohe\n  - Ngoungou\n  - Nikau\n  - Nikora\n  - Nuitone\n  - Nukaiahu\n  - Nutana\n  - Nutira\n  - Ohutu\n  - Oketopa\n  - Oneroa\n  - Otene\n  - Otimi\n  - Paekou\n  - Paenga\n  - Paerata\n  - Paewai\n  - Pahau\n  - Pahi\n  - Pahua\n  - Pai\n  - Paipa\n  - Pairama\n  - Pakau\n  - Paki\n  - Pakinui\n  - Pakira\n  - Paku\n  - Palakiko\n  - Panapa\n  - Panera\n  - Panina\n  - Panoho\n  - Paora\n  - Papa Titore\n  - Paparangi\n  - Paraeroa\n  - Paraha\n  - Paraihe\n  - Paranihi\n  - Paranihihi\n  - Paraone\n  - Parata\n  - Paratene\n  - Paratini\n  - Pare\n  - Parehe\n  - Parekaremu\n  - Pareraukawa\n  - Paringatai\n  - Patariki\n  - Patihana\n  - Patu\n  - Patuone\n  - Patuwai\n  - Patuwairua\n  - Paura\n  - Pauro\n  - Pawhau\n  - Peehikuru\n  - Pepe\n  - Peita\n  - Peka\n  - Peneha\n  - Penehare\n  - Peneta\n  - Penetito\n  - Pepene\n  - Pera\n  - Peraniko\n  - Perawiti\n  - Pereki\n  - Perepe\n  - Peri\n  - Pihama\n  - Pikari\n  - Pio\n  - Pirere\n  - Pirika\n  - Piripi\n  - Piwari\n  - Poa\n  - Poaro\n  - Pohe\n  - Pohio\n  - Pohopohe\n  - Poiakino\n  - Poihipi\n  - Pokai\n  - Pomana\n  - Pomare\n  - Popata\n  - Potaka\n  - Potangaroa\n  - Potatau\n  - Poti\n  - Potiki\n  - Pouhiki\n  - Pourewa\n  - Pouwhare\n  - Puanga\n  - Puano\n  - Puhi\n  - Phutaniwharau\n  - Puku\n  - Puna\n  - Pura\n  - Puru\n  - Purukama\n  - Puti\n  - Purutanga\n  - Raharuhi\n  - Raihania\n  - Rakete\n  - Raki\n  - Rakiraki\n  - Rako\n  - Ranana\n  - Rangihaeata\n  - Rangimakere\n  - Rangipaeroa\n  - Rangiatakaiwaho\n  - Rangitaura\n  - Rangitukiwaho\n  - Rangiwai\n  - Rapana\n  - Rapihana\n  - Rapira\n  - Raponi\n  - Rarere\n  - Ratahi\n  - Ratima\n  - Rauhihi\n  - Rautangi\n  - Rawiri\n  - Rehanga\n  - Rehutai\n  - Rei\n  - Reihana\n  - Remaha\n  - Remi\n  - Remihana\n  - Renata\n  - Rerekura\n  - Reweti\n  - Rewi\n  - Rewiti\n  - Ria\n  - Rihari\n  - Rihia\n  - Riki\n  - Rikirangi\n  - Riwhi\n  - Romana\n  - Rona\n  - Ronaki\n  - Ropata\n  - Rotoatara\n  - Tuatara\n  - Ruawai\n  - Ruepena\n  - Ruka\n  - Rukutai\n  - Rupaha\n  - Rurawhe\n  - Ruru\n  - Ruwhiu\n  - Te Puke Nui\n  - Tare\n  - Taekata\n  - Tahana\n  - Tahere\n  - Tai\n  - Taiapa\n  - Taiaroa\n  - Taimana\n  - Taimona\n  - Taipari\n  - Taite\n  - Taitimu\n  - Taitua\n  - Tautuha\n  - Taka\n  - Takao\n  - Takarangi\n  - Takimoana\n  - Takitimu\n  - Takoto\n  - Takuira\n  - Tamahana\n  - Tamaikoha\n  - Tamainu\n  - Tamaiparea\n  - Tamaka\n  - Tamakaha\n  - Tamaki\n  - Tamaoho\n  - Tamapahore\n  - Tamarau\n  - Tamatea\n  - Tamati\n  - Tamawaru\n  - Tamihana\n  - Tamihaua\n  - Tanara\n  - Tangaroa\n  - Tangipo\n  - Tangohau\n  - Taniora\n  - Taniwha\n  - Tarakaho\n  - Taranui\n  - Taratoa\n  - Tareha\n  - Tareuke\n  - tata\n  - Tau\n  - Taua\n  - Tauhore\n  - taui\n  - Taira\n  - Taukamo\n  - Taumatahera\n  - Taupo\n  - Taurua\n  - Tautari\n  - Tautuhi\n  - Tawera\n  - Tawhai\n  - Tawhara\n  - Te Ahwaka\n  - Te Aho\n  - Te Akau\n  - Te Ao\n  - Te Apa\n  - Te Aranui\n  - Te Atua\n  - Te Awa\n  - Te Hae\n  - Te Huia\n  - Te Kanawa\n  - Te Kataua\n  - Te Kepa\n  - Te Mana\n  - Te Nga\n  - Te Owai\n  - Te Papa\n  - Te Peke\n  - Te Tuhi\n  - Tei\n  - Tekoikoi\n  - Tepeke\n  - Tepere\n  - Teraki\n  - Teriroa\n  - Teremai\n  - Timu\n  - Tipene\n  - Toia\n  - Tokona\n  - Tongariro\n  - Taumaunu\n  - Tuhapo\n  - Tuke\n  - Tupe\n  - Turei\n  - Wahi\n  - Waka\n  - Wara\n  - Waiariki\n  - Waiata\n  - Waihape\n  - Wainohu\n  - Waiohenga\n  - Waipa\n  - Waipouri\n  - Wairua\n  - Waitara\n  - Waitoa\n  - Waitokia\n  - Waiwiri\n  - Wanoa\n  - Wanui\n  - Warakihi\n  - Warana\n  - Warauri\n  - Warena\n  - Watene\n  - Wati\n  - Wehipeihana\n  - Wepiha\n  - Whanga\n  - Whaekiri\n  - Whaitiri\n  - Whakaari\n  - Whakaata\n  - Whanaupunga\n  - Whangapirita\n  - Wharekawa\n  - Wharekiri\n  - Wharepapa\n  - Wharerau\n  - Whati\n  - Whetu\n  - Whiu\n  - Wihapi\n  - Wikaire\n  - Wikitapu\n  - Witana\n  - Witehira\n  - Witika\n  - \"'Akamu\"\n"
  },
  {
    "path": "bin/common/SoldierName/Portuguese.nam",
    "content": "lookWeight:\n  - 2\n  - 88\n  - 2\n  - 8\nmaleFirst:\n  - Afonso\n  - Alberto\n  - Alexandre\n  - Alvaro\n  - Andre\n  - Antonio\n  - Augusto\n  - Bernardo\n  - Bruno\n  - Carlos\n  - Cristiano\n  - Daniel\n  - David\n  - Diogo\n  - Duarte\n  - Eduardo\n  - Fabio\n  - Fernando\n  - Filipe\n  - Flavio\n  - Francisco\n  - Frederico\n  - Gabriel\n  - Goncalo\n  - Guilherme\n  - Gustavo\n  - Helder\n  - Henrique\n  - Hugo\n  - Ivo\n  - Jaime\n  - Joao\n  - Joaquim\n  - Jorge\n  - Jose\n  - Julio\n  - Leonardo\n  - Leonel\n  - Luis\n  - Manuel\n  - Marcelo\n  - Marcio\n  - Marco\n  - Mario\n  - Miguel\n  - Nelson\n  - Nuno\n  - Orlando\n  - Paulo\n  - Pedro\n  - Rafael\n  - Raul\n  - Ricardo\n  - Roberto\n  - Rodolfo\n  - Rodrigo\n  - Rui\n  - Samuel\n  - Sergio\n  - Tiago\n  - Telmo\n  - Tomas\n  - Vasco\n  - Vitor\nfemaleFirst:\n  - Alice\n  - Ana\n  - Anabela\n  - Andreia\n  - Angela\n  - Aurora\n  - Barbara\n  - Beatriz\n  - Bia\n  - Carina\n  - Carla\n  - Carolina\n  - Catarina\n  - Catia\n  - Celeste\n  - Celia\n  - Celina\n  - Clara\n  - Claudia\n  - Cristiana\n  - Cristina\n  - Daniela\n  - Dalia\n  - Debora\n  - Diana\n  - Dulce\n  - Elsa\n  - Eva\n  - Fatima\n  - Fernanda\n  - Filipa\n  - Filomena\n  - Flavia\n  - Florbela\n  - Francisca\n  - Gabriela\n  - Gloria\n  - Helena\n  - Ilda\n  - Ines\n  - Irene\n  - Isabel\n  - Joana\n  - Josefina\n  - Julia\n  - Lara\n  - Laura\n  - Leonor\n  - Liliana\n  - Luisa\n  - Madalena\n  - Mafalda\n  - Manuela\n  - Margarida\n  - Maria\n  - Mariana\n  - Marina\n  - Marisa\n  - Marta\n  - Matilde\n  - Monica\n  - Natalia\n  - Nadia\n  - Olivia\n  - Patricia\n  - Paula\n  - Rafaela\n  - Raquel\n  - Rita\n  - Rute\n  - Sandra\n  - Sara\n  - Sofia\n  - Sonia\n  - Soraia\n  - Susana\n  - Tania\n  - Teresa\n  - Telma\n  - Vanessa\n  - Vera\nmaleLast:\n  - Abrantes\n  - Abreu\n  - Agostinho\n  - Albano\n  - Albuquerque\n  - Aleixo\n  - Almeida\n  - Alves\n  - Amaro\n  - Amaral\n  - Andrade\n  - Anjos\n  - Antunes\n  - Araujo\n  - Assis\n  - Azevedo\n  - Barata\n  - Barreiras\n  - Barreto\n  - Barros\n  - Barroso\n  - Bastos\n  - Bento\n  - Beja\n  - Borges\n  - Brandao\n  - Brito\n  - Cabral\n  - Cadete\n  - Caetano\n  - Caldeira\n  - Campos\n  - Cardoso\n  - Carneiro\n  - Carrico\n  - Carrilho\n  - Carvalho\n  - Castro\n  - Cavaco\n  - Cavaleiro\n  - Chaves\n  - Coelho\n  - Conceicao\n  - Correia\n  - Cortes\n  - Costa\n  - Coutinho\n  - Couto\n  - Crespo\n  - Cristovao\n  - Cruz\n  - Cunha\n  - Cunhal\n  - Delgado\n  - Dias\n  - Dinis\n  - Dionisio\n  - Domingos\n  - Duarte\n  - Esteves\n  - Farinha\n  - Fernandes\n  - Ferreira\n  - Figueira\n  - Figueiredo\n  - Fitas\n  - Fragoso\n  - Fragata\n  - Francisco\n  - Franco\n  - Freire\n  - Freitas\n  - Fonseca\n  - Fontes\n  - Fortes\n  - Furtado\n  - Galvao\n  - Gama\n  - Garcia\n  - Godinho\n  - Gomes\n  - Goncalves\n  - Gouveia\n  - Graca\n  - Grilo\n  - Guedes\n  - Guerra\n  - Guerreiro\n  - Guimaraes\n  - Henriques\n  - Homem\n  - Horta\n  - Jacinto\n  - Jesus\n  - Lameiras\n  - Laranjeiro\n  - Leal\n  - Lima\n  - Lopes\n  - Lourenco\n  - Luz\n  - Macedo\n  - Machado\n  - Madeira\n  - Maia\n  - Magalhaes\n  - Marques\n  - Martinho\n  - Martins\n  - Marujo\n  - Mateus\n  - Matias\n  - Matos\n  - Maximo\n  - Meireles\n  - Melo\n  - Mendes\n  - Mendonca\n  - Mestre\n  - Mira\n  - Miranda\n  - Moniz\n  - Monteiro\n  - Morais\n  - Moreira\n  - Morgado\n  - Mota\n  - Moura\n  - Mourinho\n  - Nascimento\n  - Neto\n  - Neves\n  - Nobrega\n  - Nogueira\n  - Noronha\n  - Nunes\n  - Oliveira\n  - Pacheco\n  - Pais\n  - Paiva\n  - Parreira\n  - Pato\n  - Peixe\n  - Peixoto\n  - Pereira\n  - Pessoa\n  - Pimentel\n  - Pinheiro\n  - Pinho\n  - Pinto\n  - Pires\n  - Portugal\n  - Povoa\n  - Prata\n  - Queiros\n  - Raimundo\n  - Ramalho\n  - Ramos\n  - Raposo\n  - Rato\n  - Real\n  - Rebelo\n  - Reis\n  - Relvas\n  - Ribeiro\n  - Rio\n  - Rocha\n  - Rodrigues\n  - Ronaldo\n  - Rosario\n  - Roseiro\n  - Salgado\n  - Salgueiro\n  - Sampaio\n  - Sanches\n  - Santana\n  - Santos\n  - Sebastiao\n  - Semedo\n  - Sequeira\n  - Serra\n  - Serrao\n  - Serras\n  - Silva\n  - Silvestre\n  - Silvino\n  - Simoes\n  - Soares\n  - Sobral\n  - Sousa\n  - Tavares\n  - Teixeira\n  - Teles\n  - Torres\n  - Valadas\n  - Valente\n  - Varandas\n  - Varela\n  - Vasconcelos\n  - Vaz\n  - Veloso\n  - Viana\n  - Vicente\n  - Vidal\n  - Vieira\n  - Viegas\n  - Vitorino\n  - Xavier\n"
  },
  {
    "path": "bin/common/SoldierName/Romanian.nam",
    "content": "lookWeights:\n  - 49\n  - 50\n  - 1\n  - 0\nmaleFirst:\n  - Adrian\n  - Alexandru\n  - Andrei\n  - Bogdan\n  - Catalin\n  - Claudiu\n  - Constantin\n  - Cornel\n  - Cosmin\n  - Daniel\n  - Dragos\n  - Dumitru\n  - Emil\n  - Eugen\n  - Florin\n  - Gabriel\n  - George\n  - Gheorghe\n  - Ilie\n  - Ion\n  - Liviu\n  - Lucian\n  - Marian\n  - Marius\n  - Mihai\n  - Nicu\n  - Octavian\n  - Ovidiu\n  - Petre\n  - Radu\n  - Robert\n  - Sergiu\n  - Silviu\n  - Sorin\n  - Stefan\n  - Tiberiu\n  - Tudor\n  - Vasile\n  - Viorel\n  - Vlad\nfemaleFirst:\n  - Adelina\n  - Alexandra\n  - Alina\n  - Ana\n  - Andreea\n  - Angela\n  - Carmen\n  - Catalina\n  - Claudia\n  - Corina\n  - Dana\n  - Daniela\n  - Doina\n  - Elena\n  - Elisabeta\n  - Felicia\n  - Florentina\n  - Gabriela\n  - Georgiana\n  - Gina\n  - Ileana\n  - Ioana\n  - Irina\n  - Iulia\n  - Laura\n  - Magda\n  - Maria\n  - Mariana\n  - Mihaela\n  - Mirela\n  - Monica\n  - Nadia\n  - Nicoleta\n  - Oana\n  - Rodica\n  - Roxana\n  - Simona\n  - Stefania\n  - Violeta\n  - Viorica\nmaleLast:\n  - Anton\n  - Banica\n  - Barbu\n  - Cojocaru\n  - Constantin\n  - Cristea\n  - Dobre\n  - Dragomir\n  - Dumitru\n  - Ene\n  - Florea\n  - Georgescu\n  - Iancu\n  - Ilie\n  - Ionescu\n  - Iordan\n  - Lazar\n  - Luca\n  - Marinescu\n  - Mihalcea\n  - Munteanu\n  - Nastase\n  - Nicolae\n  - Nistor\n  - Olaru\n  - Olteanu\n  - Parvu\n  - Petre\n  - Popescu\n  - Preda\n  - Radu\n  - Sabau\n  - Savu\n  - Serban\n  - Stanciu\n  - Stanescu\n  - Tanase\n  - Tudor\n  - Ungureanu\n  - Voinea\n"
  },
  {
    "path": "bin/common/SoldierName/Russian.nam",
    "content": "lookWeights:\n  - 50\n  - 50\n  - 0\n  - 0\nmaleFirst:\n  - Aleksandr\n  - Aleksey\n  - Anatoliy\n  - Andrey\n  - Anton\n  - Artem\n  - Artur\n  - Boris\n  - Denis\n  - Dmitriy\n  - Eduard\n  - Evgeniy\n  - Gennadiy\n  - Georgiy\n  - Grigoriy\n  - Igor\n  - Ilya\n  - Ivan\n  - Konstantin\n  - Leonid\n  - Maxim\n  - Mihail\n  - Nikolay\n  - Oleg\n  - Pavel\n  - Petr\n  - Roman\n  - Ruslan\n  - Sergey\n  - Stanislav\n  - Vadim\n  - Valentin\n  - Valeriy\n  - Vasiliy\n  - Viktor\n  - Vitaliy\n  - Vladimir\n  - Vladislav\n  - Vyacheslav\n  - Yuriy\nfemaleFirst:\n  - Albina\n  - Aleksandra\n  - Alla\n  - Alyona\n  - Anastasiya\n  - Anna\n  - Antonina\n  - Darya\n  - Ekaterina\n  - Elena\n  - Evgeniya\n  - Galina\n  - Inna\n  - Irina\n  - Kristina\n  - Kseniya\n  - Larisa\n  - Lidiya\n  - Liliya\n  - Lyubov\n  - Lyudmila\n  - Margarita\n  - Marina\n  - Mariya\n  - Nadezhda\n  - Natalya\n  - Nina\n  - Oksana\n  - Olesya\n  - Olga\n  - Raisa\n  - Svetlana\n  - Tamara\n  - Tatyana\n  - Valentina\n  - Varvara\n  - Vera\n  - Viktoriya\n  - Yulia\n  - Zinaida\n  - Zoya\nmaleLast:\n  - Alekseev\n  - Andreev\n  - Antonov\n  - Borisov\n  - Fedorov\n  - Egorov\n  - Grigoryev\n  - Gromov\n  - Ivanov\n  - Komarov\n  - Korolyov\n  - Kozlov\n  - Kuzmin\n  - Kuznetsov\n  - Lebedev\n  - Makarov\n  - Mihailov\n  - Morozov\n  - Nikitin\n  - Nikolaev\n  - Novikov\n  - Orlov\n  - Pavlov\n  - Petrov\n  - Popov\n  - Romanov\n  - Semyonov\n  - Sergeev\n  - Smirnov\n  - Sokolov\n  - Solovyov\n  - Stepanov\n  - Vasilyev\n  - Volkov\n  - Vorobyov\n  - Yakovlev\n  - Zaitsev\n  - Zaharov\nfemaleLast:\n  - Alekseeva\n  - Andreeva\n  - Antonova\n  - Borisova\n  - Fedorova\n  - Egorova\n  - Grigoryeva\n  - Gromova\n  - Ivanova\n  - Komarova\n  - Korolyova\n  - Kozlova\n  - Kuzmina\n  - Kuznetsova\n  - Lebedeva\n  - Makarova\n  - Mihailova\n  - Morozova\n  - Nikitina\n  - Nikolaeva\n  - Novikova\n  - Orlova\n  - Pavlova\n  - Petrova\n  - Popova\n  - Romanova\n  - Semyonova\n  - Sergeeva\n  - Smirnova\n  - Sokolova\n  - Solovyova\n  - Stepanova\n  - Vasilyeva\n  - Volkova\n  - Vorobyova\n  - Yakovleva\n  - Zaitseva\n  - Zaharova\n"
  },
  {
    "path": "bin/common/SoldierName/Slovak.nam",
    "content": "lookWeights:\n  - 45\n  - 55\n  - 0\n  - 0\nmaleFirst:\n  - Andrej\n  - Arpad\n  - Branislav\n  - Ctibor\n  - David\n  - Dusan\n  - Frantisek\n  - Jakub\n  - Jan\n  - Jaroslav\n  - Jozef\n  - Juraj\n  - Julius\n  - Ladislav\n  - Lubomir\n  - Lubos\n  - Ludovit\n  - Lukas\n  - Martin\n  - Matej\n  - Michal\n  - Milan\n  - Miroslav\n  - Mojmir\n  - Ondrej\n  - Pavol\n  - Peter\n  - Radomir\n  - Radoslav\n  - Rastislav\n  - Richard\n  - Roman\n  - Slavomir\n  - Stanislav\n  - Tomas\n  - Vladimir\n  - Vratko\n  - Zdeno\nfemaleFirst:\n  - Adela\n  - Agata\n  - Andrea\n  - Anna\n  - Dasa\n  - Elena\n  - Eva\n  - Hana\n  - Helena\n  - Ivana\n  - Jarmila\n  - Jaroslava\n  - Katarina\n  - Karolina\n  - Kristina\n  - Kvetoslava\n  - Lenka\n  - Linda\n  - Lucia\n  - Ludmila\n  - Maria\n  - Michaela\n  - Milena\n  - Monika\n  - Natalia\n  - Nela\n  - Petra\n  - Tatiana\n  - Tereza\n  - Veronika\n  - Viera\n  - Zdenka\n  - Zoja\n  - Zora\n  - Zuzana\nmaleLast:\n  - Baca\n  - Banik\n  - Beno\n  - Bezdicka\n  - Bondra\n  - Bosansky\n  - Brezina\n  - Cernuska\n  - Cyprich\n  - Dano\n  - Dula\n  - Filip\n  - Gernic\n  - Gregor\n  - Gregus\n  - Goga\n  - Halak\n  - Halda\n  - Haluska\n  - Hascak\n  - Holub\n  - Horvath\n  - Janik\n  - Janosik\n  - Janoska\n  - Jurina\n  - Keniz\n  - Kmet\n  - Kolesar\n  - Kolnik\n  - Kostrec\n  - Kovac\n  - Liptak\n  - Liska\n  - Lukac\n  - Majesky\n  - Marian\n  - Medved\n  - Mihalik\n  - Mikus\n  - Mojzis\n  - Molnar\n  - Nagy\n  - Nemec\n  - Novak\n  - Ondrejkovic\n  - Ondrus\n  - Oravec\n  - Pasko\n  - Pavlas\n  - Pavuk\n  - Prochazka\n  - Rakocz\n  - Senko\n  - Skokan\n  - Slezak\n  - Sloboda\n  - Slovak\n  - Szabo\n  - Toma\n  - Valovsky\n  - Varga\n  - Vaskovic\n  - Viktorin\nfemaleLast:\n  - Adamcova\n  - Banasova\n  - Dubovska\n  - Durianova\n  - Farkasovska\n  - Ficova\n  - Filipova\n  - Haluskova\n  - Heckova\n  - Hubinska\n  - Janosikova\n  - Kocisova\n  - Kovacikova\n  - Kovacova\n  - Kovacova\n  - Krajcirova\n  - Kubincova\n  - Luptakova\n  - Mala\n  - Malachovska\n  - Martinova\n  - Matusova\n  - Melcerova\n  - Mikusova\n  - Moravcova\n  - Nemcova\n  - Oravcova\n  - Patrikova\n  - Peskova\n  - Petrovicka\n  - Plchova\n  - Puchertova\n  - Rusova\n  - Senkova\n  - Simekova\n  - Slobodova\n  - Sturova\n  - Vacvalova\n"
  },
  {
    "path": "bin/common/SoldierName/Spanish.nam",
    "content": "lookWeights:\n  - 4\n  - 88\n  - 4\n  - 4\nmaleFirst:\n  - Aaron\n  - Adan\n  - Alberto\n  - Alejandro\n  - Alfonso\n  - Andres\n  - Angel\n  - Antonio\n  - Augusto\n  - Benedicto\n  - Benjamin\n  - Carlos\n  - Daniel\n  - David\n  - Diego\n  - Eduardo\n  - Elias\n  - Eliseo\n  - Enrique\n  - Emanuel\n  - Eric\n  - Ernesto\n  - Esteban\n  - Fabio\n  - Felipe\n  - Felix\n  - Fernando\n  - Fidel\n  - Fortunato\n  - Francisco\n  - Gabriel\n  - Gerardo\n  - Hugo\n  - Humberto\n  - Ismael\n  - Ivan\n  - Jacobo\n  - Jaime\n  - Javier\n  - Jesus\n  - Joel\n  - Jorge\n  - Jose\n  - Juan\n  - Julian\n  - Leo\n  - Leonardo\n  - Lucas\n  - Luis\n  - Manuel\n  - Marco\n  - Marcos\n  - Martin\n  - Matias\n  - Mateo\n  - Maximiliano\n  - Miguel\n  - Nataniel\n  - Nicolas\n  - Noe\n  - Octavio\n  - Orlando\n  - Oscar\n  - Pablo\n  - Pedro\n  - Rafael\n  - Ramon\n  - Raul\n  - Rene\n  - Ricardo\n  - Roberto\n  - Rolando\n  - Salvador\n  - Santiago\n  - Sebastian\n  - Sergio\n  - Silvestre\n  - Stefano\n  - Teodoro\n  - Tito\n  - Tomas\n  - Valentin\n  - Vicente\n  - Victor\n  - Xavier\nfemaleFirst:\n  - Adriana\n  - Aida\n  - Alejandra\n  - Alexia\n  - Alma\n  - Ana\n  - Angela\n  - Angelica\n  - Aurora\n  - Barbara\n  - Bianca\n  - Brenda\n  - Carina\n  - Carla\n  - Carolina\n  - Casandra\n  - Catalina\n  - Claudia\n  - Cristina\n  - Dolores\n  - Dora\n  - Elena\n  - Eliana\n  - Elvira\n  - Ema\n  - Esmeralda\n  - Eva\n  - Felicia\n  - Fiona\n  - Gabriela\n  - Gloria\n  - Guadalupe\n  - Ines\n  - Isabel\n  - Jesica\n  - Juana\n  - Laura\n  - Lidia\n  - Liliana\n  - Linda\n  - Lisa\n  - Lorena\n  - Magdalena\n  - Marcela\n  - Margarita\n  - Maria\n  - Mariana\n  - Marisol\n  - Monica\n  - Nadia\n  - Nancy\n  - Natalia\n  - Noemi\n  - Olivia\n  - Patricia\n  - Paulina\n  - Raquel\n  - Rosa\n  - Selena\n  - Sofia\n  - Sonia\n  - Talia\n  - Tatiana\n  - Teresa\n  - Vanesa\n  - Veronica\n  - Victoria\n  - Yolanda\nmaleLast:\n  - Aguilar\n  - Alba\n  - Alonso\n  - Alvarado\n  - Alvarez\n  - Avila\n  - Calderon\n  - Campos\n  - Cardenas\n  - Castilla\n  - Cervantes\n  - Chavez\n  - Cortez\n  - Cruz\n  - De La Cruz\n  - De La Rosa\n  - De Soto\n  - Diaz\n  - Dominguez\n  - Estrada\n  - Falcon\n  - Fernandez\n  - Figueroa\n  - Flores\n  - Fuentes\n  - Garcia\n  - Garza\n  - Gomez\n  - Gonzalez\n  - Guerrero\n  - Gutierrez\n  - Guzman\n  - Hernandez\n  - Herrera\n  - Jimenez\n  - Juarez\n  - Leon\n  - Lima\n  - Lopez\n  - Loya\n  - Lucio\n  - Luna\n  - Martinez\n  - Medina\n  - Mejia\n  - Mendez\n  - Mendoza\n  - Miranda\n  - Montero\n  - Montes\n  - Morales\n  - Moreno\n  - Munoz\n  - Navarro\n  - Nunez\n  - Ortega\n  - Ortiz\n  - Pacheco\n  - Pascual\n  - Perez\n  - Ramirez\n  - Ramos\n  - Reyes\n  - Rios\n  - Rivera\n  - Rodriguez\n  - Romero\n  - Rosa\n  - Ruiz\n  - Sanchez\n  - Sandoval\n  - Santa Cruz\n  - Santana\n  - Santiago\n  - Santos\n  - Sosa\n  - Suarez\n  - Tapia\n  - Torres\n  - Trejo\n  - Trevino\n  - Trujillo\n  - Valdez\n  - Vasquez\n  - Vega\n  - Velasquez\n"
  },
  {
    "path": "bin/common/SoldierName/Swedish.nam",
    "content": "lookWeight:\n  - 60\n  - 40\n  - 0\n  - 0\nmaleFirst:\n  - Johan\n  - Fredrik\n  - Sten\n  - Olof\n  - Anders\n  - Sven\n  - Mattias\n  - Jesper\n  - David\n  - Henrik\n  - Lars\n  - Mikael\n  - Andreas\n  - Robin\n  - Christian\n  - Joakim\n  - John\n  - Linus\n  - Mats\n  - Tommy\n  - Per\n  - Sebastian\n  - Edvin\n  - Bo\n  - Leif\n  - Jens\n  - Jonas\n  - Peter\n  - Thomas\n  - Erik\nfemaleFirst:\n  - Christine\n  - Annika\n  - Isabel\n  - Anna\n  - Lena\n  - Mia\n  - Pia\n  - Petra\n  - Madeleine\n  - Johanna\n  - Gunilla\n  - Eva\n  - Ellinor\n  - Elisabet\n  - Amanda\n  - Carin\n  - Mikaela\n  - Magdalena\n  - Ellen\n  - Ingrid\n  - Inger\n  - Linda\n  - Karin\n  - Maria\n  - Sara\n  - Emma\n  - Marie\nmaleLast:\n  - Linder\n  - Olofsson\n  - Holmqvist\n  - Andersson\n  - Lindberg\n  - Lindqvist\n  - Gustafsson\n  - Larsson\n  - Lindgren\n  - Lind\n  - Eklund\n  - Holm\n  - Claesson\n  - Viklund\n  - Lund\n  - Falk\n  - Blom\n  - Ek\n  - Norberg\n  - Sundqvist\n  - Sjoborg\n  - Ivarsson\n  - Hedlund\n  - Holmgren\n  - Hedlund\n  - Nordin\n  - Berggren\n  - Svensson\n  - Lindgren\n  - Eklund\n  - Axelsson\n"
  },
  {
    "path": "bin/common/SoldierName/Turkish.nam",
    "content": "lookWeights:\n  - 8\n  - 16\n  - 8\n  - 1\nmaleFirst:\n  - Abdullah\n  - Adem\n  - Adil\n  - Adnan\n  - Ahmet\n  - Akif\n  - Ali\n  - Alp\n  - Alper\n  - Altan\n  - Arda\n  - Arif\n  - Atilla\n  - Aydemir\n  - Ayhan\n  - Aykut\n  - Aziz\n  - Baha\n  - Bahri\n  - Barlas\n  - Bedri\n  - Bekir\n  - Berk\n  - Bilal\n  - Birol\n  - Bora\n  - Burak\n  - Burhan\n  - Cahit\n  - Can\n  - Caner\n  - Cem\n  - Cemal\n  - Cengiz\n  - Cenk\n  - Cihan\n  - Cumhur\n  - Davut\n  - Doruk\n  - Dursun\n  - Efe\n  - Ekrem\n  - Emin\n  - Emrah\n  - Emre\n  - Engin\n  - Enver\n  - Erdal\n  - Eren\n  - Erhan\n  - Erkan\n  - Erol\n  - Ethem\n  - Fahri\n  - Faruk\n  - Fatih\n  - Fehmi\n  - Ferdi\n  - Ferhat\n  - Feridun\n  - Fikret\n  - Furkan\n  - Hakan\n  - Halil\n  - Haluk\n  - Hamdi\n  - Hamza\n  - Harun\n  - Hasan\n  - Hayri\n  - Hikmet\n  - Hilmi\n  - Kaan\n  - Kadir\n  - Kemal\n  - Kenan\n  - Kerem\n  - Koray\n  - Korhan\n  - Levent\n  - Mahir\n  - Mahmut\n  - Mehmet\n  - Melih\n  - Mert\n  - Mete\n  - Metin\n  - Mithat\n  - Muammer\n  - Muhammet\n  - Muhsin\n  - Murat\n  - Musa\n  - Mustafa\n  - Muzaffer\n  - Naci\n  - Nazmi\n  - Necdet\n  - Nihat\n  - Niyazi\n  - Nuri\n  - Okan\n  - Oktay\n  - Onur\n  - Orhan\n  - Osman\n  - Ozan\n  - Ramazan\n  - Remzi\n  - Sabri\n  - Salih\n  - Sedat\n  - Selim\n  - Semih\n  - Sercan\n  - Serdar\n  - Serhat\n  - Serkan\n  - Sinan\n  - Soner\n  - Taha\n  - Tahir\n  - Tahsin\n  - Taner\n  - Tarkan\n  - Tayfun\n  - Tayyar\n  - Temel\n  - Teoman\n  - Tevfik\n  - Timur\n  - Tolga\n  - Tosun\n  - Tuna\n  - Tuncay\n  - Turan\n  - Turgut\n  - Ufuk\n  - Umut\n  - Utku\n  - Uzay\n  - Vedat\n  - Veli\n  - Veysel\n  - Volkan\n  - Vural\n  - Yahya\n  - Yakup\n  - Yasin\n  - Yavuz\n  - Yusuf\n  - Zafer\n  - Zeki\n  - Zeynel\n  - Ziya\nfemaleFirst:\n  - Adile\n  - Alev\n  - Arzu\n  - Asena\n  - Ayda\n  - Aydan\n  - Ayla\n  - Aylin\n  - Aysel\n  - Aysu\n  - Aysun\n  - Bahar\n  - Bengi\n  - Bilge\n  - Birsen\n  - Burcu\n  - Canan\n  - Ceren\n  - Ceyda\n  - Damla\n  - Demet\n  - Deniz\n  - Didem\n  - Dilara\n  - Duygu\n  - Ebru\n  - Ece\n  - Eda\n  - Elif\n  - Emel\n  - Emine\n  - Esra\n  - Evrim\n  - Eylem\n  - Ezgi\n  - Fatma\n  - Filiz\n  - Gamze\n  - Gizem\n  - Hande\n  - Hatice\n  - Irmak\n  - Jale\n  - Lale\n  - Leyla\n  - Melis\n  - Meltem\n  - Meral\n  - Merve\n  - Meryem\n  - Nalan\n  - Nazan\n  - Nesrin\n  - Nezihe\n  - Nihan\n  - Nil\n  - Nur\n  - Olcay\n  - Oya\n  - Pervin\n  - Rabia\n  - Reyhan\n  - Sabiha\n  - Safiye\n  - Sanem\n  - Seda\n  - Selma\n  - Semiha\n  - Sevgi\n  - Sevil\n  - Sevim\n  - Sibel\n  - Sinem\n  - Suna\n  - Yaprak\n  - Yasemin\n  - Yeliz\n  - Yonca\n  - Zehra\n  - Zekiye\n  - Zeynep\nmaleLast:\n  - Acar\n  - Ak\n  - Akarsu\n  - Akkaya\n  - Aksoy\n  - Akturan\n  - Albayrak\n  - Alkan\n  - Alpsoy\n  - Altay\n  - Altuner\n  - Aras\n  - Arslan\n  - Atakan\n  - Atalay\n  - Atasoy\n  - Atik\n  - Atmaca\n  - Ay\n  - Ayaz\n  - Balaban\n  - Barlas\n  - Batu\n  - Baycan\n  - Bayraktar\n  - Bozkurt\n  - Bulut\n  - Can\n  - Canatan\n  - Cansu\n  - Cesur\n  - Davulcu\n  - Demirci\n  - Dikmen\n  - Doruk\n  - Durak\n  - Durmaz\n  - Dursun\n  - Durukan\n  - Eker\n  - Ekinci\n  - Elvan\n  - Erdem\n  - Eren\n  - Erken\n  - Erkmen\n  - Erkulu\n  - Ersoy\n  - Eser\n  - Gencer\n  - Gezer\n  - Hakyemez\n  - Hamarat\n  - Haznedar\n  - Kahraman\n  - Kalender\n  - Kalyoncu\n  - Kaplan\n  - Kara\n  - Karabulut\n  - Karaca\n  - Karaduman\n  - Karakaya\n  - Karakurt\n  - Karaman\n  - Karatay\n  - Karpuzcu\n  - Kartal\n  - Kavlak\n  - Kavuncu\n  - Kaya\n  - Kayahan\n  - Kayhan\n  - Kaymaz\n  - Kazak\n  - Kazan\n  - Kesen\n  - Keskin\n  - Kocaman\n  - Konuk\n  - Koparan\n  - Korkmaz\n  - Korkusuz\n  - Korkut\n  - Koyuncu\n  - Kozan\n  - Kurt\n  - Kutlu\n  - Kuyumcu\n  - Kuzucu\n  - Mercan\n  - Mutlu\n  - Nurlu\n  - Ocak\n  - Okan\n  - Okuyan\n  - Okyay\n  - Olcay\n  - Oray\n  - Ordu\n  - Pala\n  - Pehlivan\n  - Peker\n  - Polat\n  - Poyraz\n  - Sancaktar\n  - Sayan\n  - Saydam\n  - Sazak\n  - Semerci\n  - Sert\n  - Seymen\n  - Sezer\n  - Solak\n  - Solmaz\n  - Soysal\n  - Sunay\n  - Sungur\n  - Sur\n  - Tahmaz\n  - Tan\n  - Tarhan\n  - Tekcan\n  - Tekin\n  - Tezcan\n  - Tezel\n  - Topal\n  - Toprak\n  - Torun\n  - Tufan\n  - Tuncer\n  - Turna\n  - Ulucan\n  - Ulusoy\n  - Ural\n  - Uslu\n  - Usta\n  - Uyar\n  - Uygun\n  - Uysal\n  - Uzel\n  - Uzuner\n  - Varan\n  - Vardar\n  - Vural\n  - Vurgun\n  - Yalman\n  - Yaman\n  - Yazgan\n  - Yener\n  - Yolcu\n  - Yorulmaz\n  - Yurdakul\n  - Yurtseven\n  - Zeren\n  - Zorlu\n"
  },
  {
    "path": "bin/common/dont-touch.me",
    "content": "version: 8.6.0\n"
  },
  {
    "path": "bin/standard/Aliens_Pick_Up_Weapons/Aliens_Pick_Up_Weapons.rul",
    "content": "# Make aliens try to pick up weapons they dropped\nitems:\n  - type: STR_HEAVY_PLASMA\n    attraction: 10\n  - type: STR_HEAVY_PLASMA_CLIP\n    attraction: 10\n  - type: STR_PLASMA_RIFLE\n    attraction: 10\n  - type: STR_PLASMA_RIFLE_CLIP\n    attraction: 10\n  - type: STR_PLASMA_PISTOL\n    attraction: 10\n  - type: STR_PLASMA_PISTOL_CLIP\n    attraction: 10\n  - type: STR_BLASTER_LAUNCHER\n    attraction: 10\n  - type: STR_BLASTER_BOMB\n    attraction: 10\n  - type: STR_SMALL_LAUNCHER\n    attraction: 10\n  - type: STR_STUN_BOMB\n    attraction: 10\n  - type: STR_MIND_PROBE\n    attraction: 10\n  - type: STR_ALIEN_GRENADE\n    attraction: 6 # pick up grenades they're standing on, but don't chase after ones they throw"
  },
  {
    "path": "bin/standard/Aliens_Pick_Up_Weapons/metadata.yml",
    "content": "#\n# metadata.yaml for Aliens Pick Up Weapons\n\nname: \"Aliens Pick Up Weapons\"\nversion: 1.0\ndescription: \"The AI will try to pick up weapons they dropped if they find themselves unarmed (e.g. from panic or mind control).\"\nauthor: the OpenXcom team\n\nmaster: xcom1\n"
  },
  {
    "path": "bin/standard/Aliens_Pick_Up_Weapons_TFTD/Aliens_Pick_Up_Weapons.rul",
    "content": "# Make aliens try to pick up weapons they dropped\nitems:\n  - type: STR_DART_PISTOL\n    attraction: 10\n  - type: STR_JET_HARPOON\n    attraction: 10\n  - type: STR_GAS_CANNON\n    attraction: 10\n  - type: STR_HYDRO_JET_CANNON\n    attraction: 10\n  - type: STR_TORPEDO_LAUNCHER\n    attraction: 10\n  - type: STR_GAUSS_PISTOL\n    attraction: 10\n  - type: STR_GAUSS_RIFLE\n    attraction: 10\n  - type: STR_HEAVY_GAUSS\n    attraction: 10\n  - type: STR_SONIC_CANNON\n    attraction: 10\n  - type: STR_SONIC_BLASTA_RIFLE\n    attraction: 10\n  - type: STR_SONIC_PISTOL\n    attraction: 10\n  - type: STR_DISRUPTOR_PULSE_LAUNCHER\n    attraction: 10\n  - type: STR_THERMAL_SHOK_LAUNCHER\n    attraction: 10\n  - type: STR_GAUSS_PISTOL_CLIP\n    attraction: 10\n  - type: STR_GAUSS_RIFLE_CLIP\n    attraction: 10\n  - type: STR_HEAVY_GAUSS_CLIP\n    attraction: 10\n  - type: STR_CANNON_POWER_CLIP\n    attraction: 10\n  - type: STR_BLASTA_POWER_CLIP\n    attraction: 10\n  - type: STR_PISTOL_POWER_CLIP\n    attraction: 10\n  - type: STR_SONIC_PULSER\n    attraction: 6 # pick up grenades they're standing on, but don't chase after ones they throw\n"
  },
  {
    "path": "bin/standard/Aliens_Pick_Up_Weapons_TFTD/metadata.yml",
    "content": "#\n# metadata.yaml for Aliens Pick Up Weapons\n\nname: \"Aliens Pick Up Weapons\"\nversion: 1.0\ndescription: \"The AI will try to pick up weapons they dropped if they find themselves unarmed (e.g. from panic or mind control).\"\nauthor: the OpenXcom team\n\nmaster: xcom2\n"
  },
  {
    "path": "bin/standard/Demigod_Difficulty/demigod.rul",
    "content": "# enable the in-game flag to force spawns\ndifficultyDemigod: true\n\n# slight change in spawn order for terror missions:\n# spawn large units first to give a more even distribution\n\nalienDeployments:\n  - type: STR_TERROR_MISSION\n    data:\n      - alienRank: 6\n        lowQty: 1\n        highQty: 3\n        dQty: 2\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 7\n        lowQty: 1\n        highQty: 3\n        dQty: 2\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 5\n        lowQty: 4\n        highQty: 6\n        dQty: 1\n        percentageOutsideUfo: 70\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_HEAVY_PLASMA_CLIP\n      - alienRank: 4\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_HEAVY_PLASMA_CLIP\n      - alienRank: 3\n        lowQty: 1\n        highQty: 1\n        dQty: 1\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_SMALL_LAUNCHER\n            - STR_STUN_BOMB\n            - STR_STUN_BOMB\n            - STR_STUN_BOMB\n      - alienRank: 2\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_HEAVY_PLASMA_CLIP\n      - alienRank: 1\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_HEAVY_PLASMA_CLIP\n    width: 50\n    length: 50\n    height: 4\n    civilians: 16\n    terrains:\n      - URBAN\n    alert: STR_ALIENS_TERRORISE\n    alertBackground: BACK03.SCR\n    briefing:\n      palette: 2\n      music: GMENBASE\n    markerName: STR_TERROR_SITE\n    duration: [4, 10]\n    despawnPenalty: 1000\n"
  },
  {
    "path": "bin/standard/Demigod_Difficulty/metadata.yml",
    "content": "#\n# metadata.yaml for Demigod Difficulty\n\nname: \"Demigod Difficulty\"\nversion: 1.0\ndescription: \"Force maximum alien spawns\"\nauthor: the OpenXcom team\n\nmaster: xcom1\n"
  },
  {
    "path": "bin/standard/Demigod_Difficulty_TFTD/demigod.rul",
    "content": "# enable the in-game flag to force spawns\ndifficultyDemigod: true\n\n# slight change in spawn order for terror missions:\n# spawn large units first to give a more even distribution\n\nalienDeployments:\n  - type: STR_PORT_TERROR\n    data:\n      - alienRank: 6\n        lowQty: 1\n        highQty: 3\n        dQty: 2\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 7\n        lowQty: 1\n        highQty: 3\n        dQty: 2\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 5\n        lowQty: 4\n        highQty: 6\n        dQty: 1\n        percentageOutsideUfo: 70\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n      - alienRank: 4\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_MC_READER\n      - alienRank: 3\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_MC_READER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_SONIC_PULSER\n      - alienRank: 2\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_THERMIC_LANCE\n          -\n            - STR_HEAVY_THERMIC_LANCE\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n      - alienRank: 1\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n    width: 50\n    length: 50\n    height: 4\n    civilians: 16\n    terrains:\n      - PORT\n    script: PORT_TERROR\n    briefing:\n      palette: 4\n      music: GMISPOSH\n    alert: STR_ALIENS_LAUNCH_PORT_TERROR\n    alertBackground: BACK03.SCR\n    markerName: STR_TERROR_SITE\n    duration: [4, 10]\n    despawnPenalty: 1000\n  - type: STR_ISLAND_TERROR\n    data:\n      - alienRank: 6\n        lowQty: 1\n        highQty: 3\n        dQty: 2\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 7\n        lowQty: 1\n        highQty: 3\n        dQty: 2\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 5\n        lowQty: 4\n        highQty: 6\n        dQty: 1\n        percentageOutsideUfo: 70\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n      - alienRank: 4\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_MC_READER\n      - alienRank: 3\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_MC_READER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_SONIC_PULSER\n      - alienRank: 2\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_THERMIC_LANCE\n          -\n            - STR_HEAVY_THERMIC_LANCE\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n      - alienRank: 1\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n    width: 50\n    length: 50\n    height: 4\n    civilians: 16\n    terrains:\n      - ISLAND\n    script: ISLAND_TERROR\n    briefing:\n      palette: 4\n      music: GMISPOSH\n    alert: STR_ALIENS_LAUNCH_ISLAND_TERROR\n    alertBackground: BACK03.SCR\n    markerName: STR_TERROR_SITE\n    duration: [4, 10]\n    despawnPenalty: 1000\n  - type: STR_CARGO_SHIP_P1\n    data:\n      - alienRank: 6\n        lowQty: 1\n        highQty: 3\n        dQty: 2\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 7\n        lowQty: 1\n        highQty: 3\n        dQty: 2\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 5\n        lowQty: 4\n        highQty: 6\n        dQty: 1\n        percentageOutsideUfo: 70\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n      - alienRank: 4\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_MC_READER\n      - alienRank: 3\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_MC_READER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_SONIC_PULSER\n      - alienRank: 2\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_VIBRO_BLADE\n          -\n            - STR_THERMIC_LANCE\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n      - alienRank: 1\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n    width: 30\n    length: 70\n    height: 4\n    civilians: 16\n    script: SHIP_P1\n    terrains:\n      - CARGO\n    nextStage: STR_CARGO_SHIP_P2\n    briefing:\n      title: STR_SHIP_RESCUE_MISSION\n      desc: STR_SHIP_RESCUE_P1_BRIEFING\n      palette: 4\n      music: GMISPOSH\n    alert: STR_ALIENS_ATTACK_SHIPPING_ROUTE\n    alertBackground: BACK03.SCR\n    markerName: STR_TERROR_SITE\n    duration: [4, 10]\n    despawnPenalty: 1000\n  - type: STR_CARGO_SHIP_P2\n    data:\n      - alienRank: 6\n        lowQty: 1\n        highQty: 3\n        dQty: 2\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 7\n        lowQty: 1\n        highQty: 3\n        dQty: 2\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 5\n        lowQty: 4\n        highQty: 6\n        dQty: 1\n        percentageOutsideUfo: 70\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n      - alienRank: 4\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_MC_READER\n      - alienRank: 3\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_MC_READER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_SONIC_PULSER\n      - alienRank: 2\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_VIBRO_BLADE\n          -\n            - STR_THERMIC_LANCE\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n      - alienRank: 1\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n    width: 30\n    length: 70\n    height: 4\n    civilians: 16\n    script: SHIP_P2\n    terrains:\n      - CARGO\n    shade: 0\n    briefing:\n      title: STR_SHIP_RESCUE_MISSION\n      desc: STR_SHIP_RESCUE_P2_BRIEFING\n      palette: 4\n      music: GMISPOSH\n      background: BACK01.SCR\n    markerName: STR_TERROR_SITE\n  - type: STR_CRUISE_SHIP_P1\n    data:\n      - alienRank: 6\n        lowQty: 1\n        highQty: 3\n        dQty: 2\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 7\n        lowQty: 1\n        highQty: 3\n        dQty: 2\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 5\n        lowQty: 4\n        highQty: 6\n        dQty: 1\n        percentageOutsideUfo: 70\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n      - alienRank: 4\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_MC_READER\n      - alienRank: 3\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_MC_READER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_SONIC_PULSER\n      - alienRank: 2\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_THERMIC_LANCE\n          -\n            - STR_HEAVY_THERMIC_LANCE\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n      - alienRank: 1\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n    width: 30\n    length: 70\n    height: 4\n    civilians: 16\n    script: SHIP_P1\n    terrains:\n      - LINERT\n    nextStage: STR_CRUISE_SHIP_P2\n    briefing:\n      title: STR_SHIP_RESCUE_MISSION\n      desc: STR_SHIP_RESCUE_P1_BRIEFING\n      palette: 4\n      music: GMISPOSH\n    alert: STR_ALIENS_ATTACK_SHIPPING_ROUTE\n    alertBackground: BACK03.SCR\n    markerName: STR_TERROR_SITE\n    duration: [4, 10]\n    despawnPenalty: 1000\n  - type: STR_CRUISE_SHIP_P2\n    data:\n      - alienRank: 6\n        lowQty: 1\n        highQty: 3\n        dQty: 2\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 7\n        lowQty: 1\n        highQty: 3\n        dQty: 2\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 5\n        lowQty: 4\n        highQty: 6\n        dQty: 1\n        percentageOutsideUfo: 70\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n      - alienRank: 4\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_MC_READER\n      - alienRank: 3\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_MC_READER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_SONIC_PULSER\n      - alienRank: 2\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_VIBRO_BLADE\n          -\n            - STR_THERMIC_LANCE\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n      - alienRank: 1\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n    width: 30\n    length: 70\n    height: 4\n    civilians: 16\n    script: SHIP_P2\n    terrains:\n      - LINERB\n    shade: 0\n    briefing:\n      title: STR_SHIP_RESCUE_MISSION\n      desc: STR_SHIP_RESCUE_P2_BRIEFING\n      palette: 4\n      music: GMISPOSH\n      background: BACK01.SCR\n    markerName: STR_TERROR_SITE\n  - type: STR_ARTIFACT_SITE_P1\n    data:\n      - alienRank: 6\n        lowQty: 1\n        highQty: 3\n        dQty: 2\n        extraQty: 2\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 7\n        lowQty: 1\n        highQty: 3\n        dQty: 2\n        extraQty: 2\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 5\n        lowQty: 4\n        highQty: 6\n        dQty: 1\n        extraQty: 2\n        percentageOutsideUfo: 70\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n      - alienRank: 4\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        extraQty: 2\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_MC_READER\n      - alienRank: 3\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        extraQty: 2\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_MC_READER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_SONIC_PULSER\n      - alienRank: 2\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        extraQty: 2\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_THERMIC_LANCE\n          -\n            - STR_HEAVY_THERMIC_LANCE\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n      - alienRank: 1\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        extraQty: 2\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n    width: 50\n    length: 50\n    height: 4\n    terrains:\n      - ALART\n    script: ARTIFACT_P1\n    nextStage: STR_ARTIFACT_SITE_P2\n    briefing:\n      title: STR_ALIEN_CONTACT_SITE_MISSION\n      palette: 4\n      music: GMATTBAS\n    alert: STR_ALIEN_ACTIVITY_DETECTED\n    alertBackground: BACK03.SCR\n    markerName: STR_ARTIFACT_SITE\n    duration: [4, 10]\n    despawnPenalty: 2000\n    objectiveFailed: [STR_ALIEN_SYNOMIUM_DEVICE_FAILED, -750]\n  - type: STR_ARTIFACT_SITE_P2\n    data:\n      - alienRank: 6\n        lowQty: 1\n        highQty: 3\n        dQty: 2\n        extraQty: 2\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 7\n        lowQty: 1\n        highQty: 3\n        dQty: 2\n        extraQty: 2\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 5\n        lowQty: 4\n        highQty: 6\n        dQty: 1\n        extraQty: 2\n        percentageOutsideUfo: 70\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n      - alienRank: 4\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        extraQty: 2\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_MC_READER\n      - alienRank: 3\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        extraQty: 2\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_MC_READER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_SONIC_PULSER\n      - alienRank: 2\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        extraQty: 2\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_THERMIC_LANCE\n          -\n            - STR_HEAVY_THERMIC_LANCE\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n      - alienRank: 1\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        extraQty: 2\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n    width: 40\n    length: 40\n    height: 4\n    terrains:\n      - GRUNGE\n    shade: 15\n    depth: [3, 3]\n    script: ARTIFACT_P2\n    briefing:\n      title: STR_ALIEN_CONTACT_SITE_MISSION\n      palette: 4\n      music: GMATTBAS\n      background: BACK01.SCR\n    markerName: STR_ARTIFACT_SITE\n    objectiveType: 3\n    objectivesRequired: 1\n    objectiveComplete: [STR_ALIEN_SYNOMIUM_DEVICE_DESTROYED, 750]\n    objectiveFailed: [STR_ALIEN_SYNOMIUM_DEVICE_FAILED, -750]\n    objectivePopup: STR_CONTROL_CENTER_DESTROYED\n"
  },
  {
    "path": "bin/standard/Demigod_Difficulty_TFTD/metadata.yml",
    "content": "#\n# metadata.yaml for Demigod Difficulty\n\nname: \"Demigod Difficulty\"\nversion: 1.0\ndescription: \"Force maximum alien spawns\"\nauthor: the OpenXcom team\n\nmaster: xcom2\n"
  },
  {
    "path": "bin/standard/Limit_Craft_Item_Capacities/Limit_Craft_Item_Capacities.rul",
    "content": "# Enforce the old 80 item limit on crafts.\n# includes the interceptor and firestorm in this list in case people are using the interceptor/firestorm maps\ncrafts:\n  - type: STR_SKYRANGER\n    maxItems: 80\n  - type: STR_INTERCEPTOR\n    maxItems: 80\n  - type: STR_FIRESTORM\n    maxItems: 80\n  - type: STR_LIGHTNING\n    maxItems: 80\n  - type: STR_AVENGER\n    maxItems: 80"
  },
  {
    "path": "bin/standard/Limit_Craft_Item_Capacities/metadata.yml",
    "content": "#\n# metadata.yaml for Limit Craft Item Capacities\n\nname: \"Limit Craft Item Capacities\"\nversion: 1.0\ndescription: \"Limits the number of items you can take on a craft to 80.\"\nauthor: the OpenXcom team\n\nmaster: xcom1\n"
  },
  {
    "path": "bin/standard/Limit_Craft_Item_Capacities_TFTD/Limit_Craft_Item_Capacities.rul",
    "content": "# Enforce the old 80 item limit on crafts.\ncrafts:\n  - type: STR_TRITON\n    maxItems: 80\n  - type: STR_HAMMERHEAD\n    maxItems: 80\n  - type: STR_LEVIATHAN\n    maxItems: 80\n  - type: STR_BARRACUDA\n    maxItems: 80\n  - type: STR_MANTA\n    maxItems: 80\n"
  },
  {
    "path": "bin/standard/Limit_Craft_Item_Capacities_TFTD/metadata.yml",
    "content": "#\n# metadata.yaml for Limit Craft Item Capacities\n\nname: \"Limit Craft Item Capacities\"\nversion: 1.0\ndescription: \"Limits the number of items you can take on a craft to 80.\"\nauthor: the OpenXcom team\n\nmaster: xcom2\n"
  },
  {
    "path": "bin/standard/OpenXCom_Unlimited_Waypoints/OpenXCom_Unlimited_Waypoints.rul",
    "content": "items:\n  - type: STR_HOVERTANK_LAUNCHER\n    waypoints: -1\n  - type: STR_BLASTER_LAUNCHER\n    waypoints: -1"
  },
  {
    "path": "bin/standard/OpenXCom_Unlimited_Waypoints/metadata.yml",
    "content": "#\n# metadata.yaml for Unlimited Waypoints\n\nname: \"OpenXCom: Unlimited Waypoints\"\nversion: 1.0\ndescription: \"Allows unlimited waypoints, Aliens will be limited by difficulty.\"\nauthor: the OpenXcom team\n\nmaster: xcom1"
  },
  {
    "path": "bin/standard/OpenXCom_Unlimited_Waypoints_TFTD/OpenXCom_Unlimited_Waypoints.rul",
    "content": "items:\n  - type: STR_DISPLACER_PWT\n    waypoints: -1\n  - type: STR_DISRUPTOR_PULSE_LAUNCHER\n    waypoints: -1"
  },
  {
    "path": "bin/standard/OpenXCom_Unlimited_Waypoints_TFTD/metadata.yml",
    "content": "#\n# metadata.yaml for Unlimited Waypoints\n\nname: \"OpenXCom: Unlimited Waypoints\"\nversion: 1.0\ndescription: \"Allows unlimited waypoints, Aliens will be limited by difficulty.\"\nauthor: the OpenXcom team\n\nmaster: xcom2"
  },
  {
    "path": "bin/standard/PSX_Static_Cydonia_Map/PSX_Static_Cydonia_Map.rul",
    "content": "mapScripts:\n  - type: BOSSBATTLE\n    commands:\n    - type: addBlock\n      groups: 2\n      executions: 2\n      rects:\n        - [1, 0, 1, 1]\n        - [3, 2, 1, 1]\n    - type: addBlock\n      blocks: 15\n      rects:\n        - [2, 3, 2, 2]\n    - type: addBlock\n      blocks: 3\n      executions: 2\n      rects:\n        - [0, 1, 2, 2]\n        - [4, 3, 2, 2]\n    - type: addBlock\n      blocks: 2\n      executions: 2\n      rects:\n        - [2, 0, 2, 2]\n        - [4, 0, 2, 2]\n    - type: addBlock\n      blocks: 8\n      executions: 2\n      rects:\n        - [2, 2, 1, 1]\n        - [2, 5, 1, 1]\n    - type: addBlock\n      blocks: 10\n      executions: 2\n      rects:\n        - [0, 3, 1, 1]\n        - [5, 5, 1, 1]\n    - type: addBlock\n      blocks: 13\n      executions: 2\n      rects:\n        - [1, 4, 1, 1]\n        - [4, 5, 1, 1]\n    - type: addBlock\n      blocks: 14\n      executions: 2\n      rects:\n        - [1, 5, 1, 1]\n        - [3, 5, 1, 1]\n    - type: addBlock\n      blocks: 11\n      rects:\n        - [4, 2, 1, 1]\n    - type: addBlock\n      blocks: 6\n      rects:\n        - [0, 5, 1, 1]\n    - type: fillArea\n      blocks: 7\n    - type: digTunnel\n      direction: both\n      tunnelData:\n        level: 0\n        MCDReplacements:\n          - type: westWall\n            set: 2\n            entry: 18\n          - type: northWall\n            set: 2\n            entry: 17\n          - type: corner\n            set: 2\n            entry: 19\n          - type: floor\n            set: 1\n            entry: 63"
  },
  {
    "path": "bin/standard/PSX_Static_Cydonia_Map/metadata.yml",
    "content": "#\n# metadata.yaml for PSX Static Cydonia Map\n\nname: \"PSX Static Cydonia Map\"\nversion: 1.0\ndescription: \"Uses the Cydonia map from the PSX version of X-Com: UFO Defense.\"\nauthor: the OpenXcom team\n\nmaster: xcom1\n"
  },
  {
    "path": "bin/standard/Smarter_Equip/1_Smarter_Equip.rul",
    "content": "# 1. Use inventory slots defined by individual items\nitems:\n  - type: STR_HIGH_EXPLOSIVE\n    defaultInventorySlot: STR_RIGHT_LEG\n  - type: STR_MOTION_SCANNER\n    defaultInventorySlot: STR_BELT\n  - type: STR_MEDI_KIT\n    defaultInventorySlot: STR_BELT\n  - type: STR_BLASTER_BOMB\n    defaultInventorySlot: STR_LEFT_HAND\n\n# 2. Use inventory slots defined by item categories\ndisplayCustomCategories: 1\n\nitemCategories:\n  - type: OXCE_CRAFT_WEAPONS\n  - type: OXCE_HWPS\n  - type: OXCE_MAIN_WEAPONS\n    invOrder: [STR_RIGHT_HAND, STR_LEFT_HAND, STR_BACK_PACK]\n  - type: OXCE_SIDE_WEAPONS\n    invOrder: [STR_LEFT_HAND, STR_BELT, STR_BACK_PACK, STR_RIGHT_HAND]\n  - type: OXCE_AMMO\n    invOrder: [STR_BELT, STR_LEFT_LEG, STR_RIGHT_LEG]\n  - type: OXCE_GRENADES\n    invOrder: [STR_RIGHT_SHOULDER, STR_LEFT_SHOULDER, STR_BELT, STR_LEFT_LEG, STR_RIGHT_LEG, STR_LEFT_HAND, STR_RIGHT_HAND, STR_BACK_PACK]\n  - type: OXCE_ARMORS_AND_CORPSES\n    invOrder: [STR_LEFT_HAND, STR_RIGHT_HAND, STR_BACK_PACK]\n  - type: OXCE_PRISONERS\n    invOrder: [STR_LEFT_HAND, STR_RIGHT_HAND, STR_BACK_PACK]\n  - type: OXCE_COMPONENTS\n    invOrder: [STR_LEFT_HAND, STR_BELT, STR_BACK_PACK]\n\n# 3. Use inventory slots ordered by listOrder (instead of alphabetical order)\nconstants:\n  extendedInventorySlotSorting: true\n\ninvs:\n  - id: STR_RIGHT_SHOULDER\n    listOrder: 10\n  - id: STR_LEFT_SHOULDER\n    listOrder: 20\n  - id: STR_BELT\n    listOrder: 30\n  - id: STR_LEFT_LEG\n    listOrder: 40\n  - id: STR_RIGHT_LEG\n    listOrder: 50\n  - id: STR_BACK_PACK\n    listOrder: 60\n# let's keep the hands low (or at least after the backpack, so that aliens don't auto-equip things like mind probes in hands)\n  - id: STR_RIGHT_HAND\n    listOrder: 70\n  - id: STR_LEFT_HAND\n    listOrder: 80\n  - id: STR_GROUND\n    listOrder: 90\n\n# end of file\n"
  },
  {
    "path": "bin/standard/Smarter_Equip/2_Smarter_Equip_Item_Categorization.rul",
    "content": "items:\n  - type: STR_STINGRAY_LAUNCHER\n    categories: !add [OXCE_CRAFT_WEAPONS]\n  - type: STR_STINGRAY_MISSILES\n    categories: !add [OXCE_CRAFT_WEAPONS]\n  - type: STR_AVALANCHE_LAUNCHER\n    categories: !add [OXCE_CRAFT_WEAPONS]\n  - type: STR_AVALANCHE_MISSILES\n    categories: !add [OXCE_CRAFT_WEAPONS]\n  - type: STR_CANNON\n    categories: !add [OXCE_CRAFT_WEAPONS]\n  - type: STR_CANNON_ROUNDS_X50\n    categories: !add [OXCE_CRAFT_WEAPONS]\n  - type: STR_FUSION_BALL_LAUNCHER\n    categories: !add [OXCE_CRAFT_WEAPONS]\n  - type: STR_FUSION_BALL\n    categories: !add [OXCE_CRAFT_WEAPONS]\n  - type: STR_LASER_CANNON\n    categories: !add [OXCE_CRAFT_WEAPONS]\n  - type: STR_PLASMA_BEAM\n    categories: !add [OXCE_CRAFT_WEAPONS]\n  - type: STR_TANK_CANNON\n    categories: !add [OXCE_HWPS]\n  - type: STR_HWP_CANNON_SHELLS\n    categories: !add [OXCE_HWPS]\n  - type: STR_TANK_ROCKET_LAUNCHER\n    categories: !add [OXCE_HWPS]\n  - type: STR_HWP_ROCKETS\n    categories: !add [OXCE_HWPS]\n  - type: STR_TANK_LASER_CANNON\n    categories: !add [OXCE_HWPS]\n  - type: STR_HOVERTANK_PLASMA\n    categories: !add [OXCE_HWPS]\n  - type: STR_HOVERTANK_LAUNCHER\n    categories: !add [OXCE_HWPS]\n  - type: STR_HWP_FUSION_BOMB\n    categories: !add [OXCE_HWPS]\n  - type: STR_PISTOL\n    categories: !add [OXCE_SIDE_WEAPONS]\n  - type: STR_PISTOL_CLIP\n    categories: !add [OXCE_AMMO, OXCE_SIDE_WEAPONS]\n  - type: STR_RIFLE\n    categories: !add [OXCE_MAIN_WEAPONS]\n  - type: STR_RIFLE_CLIP\n    categories: !add [OXCE_AMMO, OXCE_MAIN_WEAPONS]\n  - type: STR_HEAVY_CANNON\n    categories: !add [OXCE_MAIN_WEAPONS]\n  - type: STR_HC_AP_AMMO\n    categories: !add [OXCE_AMMO, OXCE_MAIN_WEAPONS]\n  - type: STR_HC_HE_AMMO\n    categories: !add [OXCE_AMMO, OXCE_MAIN_WEAPONS]\n  - type: STR_HC_I_AMMO\n    categories: !add [OXCE_AMMO, OXCE_MAIN_WEAPONS]\n  - type: STR_AUTO_CANNON\n    categories: !add [OXCE_MAIN_WEAPONS]\n  - type: STR_AC_AP_AMMO\n    categories: !add [OXCE_AMMO, OXCE_MAIN_WEAPONS]\n  - type: STR_AC_HE_AMMO\n    categories: !add [OXCE_AMMO, OXCE_MAIN_WEAPONS]\n  - type: STR_AC_I_AMMO\n    categories: !add [OXCE_AMMO, OXCE_MAIN_WEAPONS]\n  - type: STR_ROCKET_LAUNCHER\n    categories: !add [OXCE_MAIN_WEAPONS]\n  - type: STR_SMALL_ROCKET\n    categories: !add [OXCE_AMMO, OXCE_MAIN_WEAPONS]\n  - type: STR_LARGE_ROCKET\n    categories: !add [OXCE_AMMO, OXCE_MAIN_WEAPONS]\n  - type: STR_INCENDIARY_ROCKET\n    categories: !add [OXCE_AMMO, OXCE_MAIN_WEAPONS]\n  - type: STR_LASER_PISTOL\n    categories: !add [OXCE_SIDE_WEAPONS]\n  - type: STR_LASER_RIFLE\n    categories: !add [OXCE_MAIN_WEAPONS]\n  - type: STR_HEAVY_LASER\n    categories: !add [OXCE_MAIN_WEAPONS]\n  - type: STR_GRENADE\n    categories: !add [OXCE_GRENADES]\n  - type: STR_SMOKE_GRENADE\n    categories: !add [OXCE_GRENADES]\n  - type: STR_PROXIMITY_GRENADE\n    categories: !add [OXCE_GRENADES]\n  - type: STR_HIGH_EXPLOSIVE\n    categories: !add [OXCE_GRENADES]\n  - type: STR_MOTION_SCANNER\n    categories: !add [OXCE_SIDE_WEAPONS]\n  - type: STR_MEDI_KIT\n    categories: !add [OXCE_SIDE_WEAPONS]\n  - type: STR_PSI_AMP\n    categories: !add [OXCE_SIDE_WEAPONS]\n  - type: STR_STUN_ROD\n    categories: !add [OXCE_SIDE_WEAPONS]\n  - type: STR_ELECTRO_FLARE\n    categories: !add [OXCE_GRENADES]\n  - type: STR_HEAVY_PLASMA\n    categories: !add [OXCE_MAIN_WEAPONS]\n  - type: STR_HEAVY_PLASMA_CLIP\n    categories: !add [OXCE_AMMO, OXCE_MAIN_WEAPONS]\n  - type: STR_PLASMA_RIFLE\n    categories: !add [OXCE_MAIN_WEAPONS]\n  - type: STR_PLASMA_RIFLE_CLIP\n    categories: !add [OXCE_AMMO, OXCE_MAIN_WEAPONS]\n  - type: STR_PLASMA_PISTOL\n    categories: !add [OXCE_SIDE_WEAPONS]\n  - type: STR_PLASMA_PISTOL_CLIP\n    categories: !add [OXCE_AMMO, OXCE_SIDE_WEAPONS]\n  - type: STR_BLASTER_LAUNCHER\n    categories: !add [OXCE_MAIN_WEAPONS]\n  - type: STR_BLASTER_BOMB\n    categories: !add [OXCE_AMMO, OXCE_MAIN_WEAPONS]\n  - type: STR_SMALL_LAUNCHER\n    categories: !add [OXCE_MAIN_WEAPONS]\n  - type: STR_STUN_BOMB\n    categories: !add [OXCE_AMMO, OXCE_MAIN_WEAPONS]\n  - type: STR_ALIEN_GRENADE\n    categories: !add [OXCE_GRENADES]\n  - type: STR_ELERIUM_115\n    categories: !add [OXCE_COMPONENTS]\n  - type: STR_MIND_PROBE\n    categories: !add [OXCE_SIDE_WEAPONS]\n  - type: STR_SECTOID_CORPSE\n    categories: !add [OXCE_ARMORS_AND_CORPSES]\n  - type: STR_SNAKEMAN_CORPSE\n    categories: !add [OXCE_ARMORS_AND_CORPSES]\n  - type: STR_ETHEREAL_CORPSE\n    categories: !add [OXCE_ARMORS_AND_CORPSES]\n  - type: STR_MUTON_CORPSE\n    categories: !add [OXCE_ARMORS_AND_CORPSES]\n  - type: STR_FLOATER_CORPSE\n    categories: !add [OXCE_ARMORS_AND_CORPSES]\n  - type: STR_CELATID_CORPSE\n    categories: !add [OXCE_ARMORS_AND_CORPSES]\n  - type: STR_SILACOID_CORPSE\n    categories: !add [OXCE_ARMORS_AND_CORPSES]\n  - type: STR_CHRYSSALID_CORPSE\n    categories: !add [OXCE_ARMORS_AND_CORPSES]\n  - type: STR_REAPER_CORPSE\n    categories: !add [OXCE_ARMORS_AND_CORPSES]\n  - type: STR_SECTOPOD_CORPSE\n    categories: !add [OXCE_ARMORS_AND_CORPSES]\n  - type: STR_CYBERDISC_CORPSE\n    categories: !add [OXCE_ARMORS_AND_CORPSES]\n  - type: STR_UFO_POWER_SOURCE\n    categories: !add [OXCE_COMPONENTS]\n  - type: STR_UFO_NAVIGATION\n    categories: !add [OXCE_COMPONENTS]\n  - type: STR_UFO_CONSTRUCTION\n    categories: !add [OXCE_COMPONENTS]\n  - type: STR_ALIEN_FOOD\n    categories: !add [OXCE_COMPONENTS]\n  - type: STR_ALIEN_REPRODUCTION\n    categories: !add [OXCE_COMPONENTS]\n  - type: STR_ALIEN_ENTERTAINMENT\n    categories: !add [OXCE_COMPONENTS]\n  - type: STR_ALIEN_SURGERY\n    categories: !add [OXCE_COMPONENTS]\n  - type: STR_EXAMINATION_ROOM\n    categories: !add [OXCE_COMPONENTS]\n  - type: STR_ALIEN_ALLOYS\n    categories: !add [OXCE_COMPONENTS]\n  - type: STR_ALIEN_HABITAT\n    categories: !add [OXCE_COMPONENTS]\n  - type: STR_PERSONAL_ARMOR\n    categories: !add [OXCE_ARMORS_AND_CORPSES]\n  - type: STR_POWER_SUIT\n    categories: !add [OXCE_ARMORS_AND_CORPSES]\n  - type: STR_FLYING_SUIT\n    categories: !add [OXCE_ARMORS_AND_CORPSES]\n  - type: STR_SECTOID_COMMANDER\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_SECTOID_LEADER\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_SECTOID_ENGINEER\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_SECTOID_MEDIC\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_SECTOID_NAVIGATOR\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_SECTOID_SOLDIER\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_SNAKEMAN_COMMANDER\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_SNAKEMAN_LEADER\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_SNAKEMAN_ENGINEER\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_SNAKEMAN_NAVIGATOR\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_SNAKEMAN_SOLDIER\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_ETHEREAL_COMMANDER\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_ETHEREAL_LEADER\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_ETHEREAL_SOLDIER\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_MUTON_ENGINEER\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_MUTON_NAVIGATOR\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_MUTON_SOLDIER\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_FLOATER_COMMANDER\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_FLOATER_LEADER\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_FLOATER_ENGINEER\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_FLOATER_MEDIC\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_FLOATER_NAVIGATOR\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_FLOATER_SOLDIER\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_CELATID_TERRORIST\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_SILACOID_TERRORIST\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_CHRYSSALID_TERRORIST\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_REAPER_TERRORIST\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_SECTOPOD_TERRORIST\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_CYBERDISC_TERRORIST\n    categories: !add [OXCE_PRISONERS]\n\n# end of file\n"
  },
  {
    "path": "bin/standard/Smarter_Equip/Language/cs.yml",
    "content": "cs:\n  OXCE_CRAFT_WEAPONS: \"Palubní zbraně\"\n  OXCE_HWPS: \"TZS\"\n  OXCE_MAIN_WEAPONS: \"Hlavní zbraně\"\n  OXCE_SIDE_WEAPONS: \"Boční zbraně\"\n  OXCE_AMMO: \"Munice\"\n  OXCE_GRENADES: \"Granáty\"\n  OXCE_ARMORS_AND_CORPSES: \"Zbroj a mrtvoly\"\n  OXCE_PRISONERS: \"Vězni\"\n  OXCE_COMPONENTS: \"Komponenty\"\n"
  },
  {
    "path": "bin/standard/Smarter_Equip/Language/de.yml",
    "content": "en-US:\n  OXCE_CRAFT_WEAPONS: \"Raumschiffwaffen\"\n  OXCE_HWPS: \"SWT\"\n  OXCE_MAIN_WEAPONS: \"Hauptwaffen\"\n  OXCE_SIDE_WEAPONS: \"Seitenwaffen\"\n  OXCE_AMMO: \"Munition\"\n  OXCE_GRENADES: \"Granaten\"\n  OXCE_ARMORS_AND_CORPSES: \"Rüstungen & Leichen\"\n  OXCE_PRISONERS: \"Gefangene\"\n  OXCE_COMPONENTS: \"Komponenten\"\n"
  },
  {
    "path": "bin/standard/Smarter_Equip/Language/en-GB.yml",
    "content": "en-GB:\n  OXCE_CRAFT_WEAPONS: \"Craft weapons\"\n  OXCE_HWPS: \"HWPs\"\n  OXCE_MAIN_WEAPONS: \"Main weapons\"\n  OXCE_SIDE_WEAPONS: \"Side weapons\"\n  OXCE_AMMO: \"Ammo\"\n  OXCE_GRENADES: \"Grenades\"\n  OXCE_ARMORS_AND_CORPSES: \"Armors & Corpses\"\n  OXCE_PRISONERS: \"Prisoners\"\n  OXCE_COMPONENTS: \"Components\"\n"
  },
  {
    "path": "bin/standard/Smarter_Equip/Language/en-US.yml",
    "content": "en-US:\n  OXCE_CRAFT_WEAPONS: \"Craft weapons\"\n  OXCE_HWPS: \"HWPs\"\n  OXCE_MAIN_WEAPONS: \"Main weapons\"\n  OXCE_SIDE_WEAPONS: \"Side weapons\"\n  OXCE_AMMO: \"Ammo\"\n  OXCE_GRENADES: \"Grenades\"\n  OXCE_ARMORS_AND_CORPSES: \"Armors & Corpses\"\n  OXCE_PRISONERS: \"Prisoners\"\n  OXCE_COMPONENTS: \"Components\"\n"
  },
  {
    "path": "bin/standard/Smarter_Equip/Language/it.yml",
    "content": "it:\n  OXCE_CRAFT_WEAPONS: \"Armi da vascello\"\n  OXCE_HWPS: \"TANK\"\n  OXCE_MAIN_WEAPONS: \"Armi principali\"\n  OXCE_SIDE_WEAPONS: \"Armi secondarie\"\n  OXCE_AMMO: \"Munizioni\"\n  OXCE_GRENADES: \"Granate\"\n  OXCE_ARMORS_AND_CORPSES: \"Armature & Cadaveri\"\n  OXCE_PRISONERS: \"Progionieri\"\n  OXCE_COMPONENTS: \"Componenti\"\n"
  },
  {
    "path": "bin/standard/Smarter_Equip/Language/pl.yml",
    "content": "en-US:\n  OXCE_CRAFT_WEAPONS: \"Broń pokładowa\"\n  OXCE_HWPS: \"CDS-y\"\n  OXCE_MAIN_WEAPONS: \"Uzbrojenie główne\"\n  OXCE_SIDE_WEAPONS: \"Uzbrojenie boczne\"\n  OXCE_AMMO: \"Amunicja\"\n  OXCE_GRENADES: \"Granaty\"\n  OXCE_ARMORS_AND_CORPSES: \"Pancerze i zwłoki\"\n  OXCE_PRISONERS: \"Więźniowie\"\n  OXCE_COMPONENTS: \"Komponenty\"\n"
  },
  {
    "path": "bin/standard/Smarter_Equip/Language/ru.yml",
    "content": "ru:\n  OXCE_CRAFT_WEAPONS: \"Бортовое вооружение\"\n  OXCE_HWPS: \"ТБП\"\n  OXCE_MAIN_WEAPONS: \"Основное оружие\"\n  OXCE_SIDE_WEAPONS: \"Вспом. оружие\"\n  OXCE_AMMO: \"Боеприпасы\"\n  OXCE_GRENADES: \"Гранаты\"\n  OXCE_ARMORS_AND_CORPSES: \"Броня и трупы\"\n  OXCE_PRISONERS: \"Заключённые\"\n  OXCE_COMPONENTS: \"Компоненты\"\n"
  },
  {
    "path": "bin/standard/Smarter_Equip/Language/uk.yml",
    "content": "uk:\n  OXCE_CRAFT_WEAPONS: \"Бортове озброєння\"\n  OXCE_HWPS: \"ВБП\"\n  OXCE_MAIN_WEAPONS: \"Основна зброя\"\n  OXCE_SIDE_WEAPONS: \"Допоміжна зброя\"\n  OXCE_AMMO: \"Набої\"\n  OXCE_GRENADES: \"Гранати\"\n  OXCE_ARMORS_AND_CORPSES: \"Броня та трупи\"\n  OXCE_PRISONERS: \"В'язні\"\n  OXCE_COMPONENTS: \"Компоненти\"\n"
  },
  {
    "path": "bin/standard/Smarter_Equip/metadata.yml",
    "content": "#\n# metadata.yaml for Smarter Equip\n\nname: \"Smarter Equip\"\nversion: 1.1\ndescription: \"Custom priority order of inventory slots for auto-equip and ctrl-click-equip.\"\nauthor: Meridian\n\nmaster: xcom1\n"
  },
  {
    "path": "bin/standard/Smarter_Equip_TFTD/1_Smarter_Equip.rul",
    "content": "# 1. Use inventory slots defined by individual items\nitems:\n  - type: STR_MAGNA_PACK_EXPLOSIVE\n    defaultInventorySlot: STR_RIGHT_LEG\n  - type: STR_PARTICLE_DISTURBANCE_SENSOR\n    defaultInventorySlot: STR_BELT\n  - type: STR_MEDI_KIT\n    defaultInventorySlot: STR_BELT\n  - type: STR_DISRUPTOR_AMMO\n    defaultInventorySlot: STR_LEFT_HAND\n\n# 2. Use inventory slots defined by item categories\ndisplayCustomCategories: 1\n\nitemCategories:\n  - type: OXCE_CRAFT_WEAPONS\n  - type: OXCE_HWPS\n  - type: OXCE_MAIN_WEAPONS\n    invOrder: [STR_RIGHT_HAND, STR_LEFT_HAND, STR_BACK_PACK]\n  - type: OXCE_SIDE_WEAPONS\n    invOrder: [STR_LEFT_HAND, STR_BELT, STR_BACK_PACK, STR_RIGHT_HAND]\n  - type: OXCE_AMMO\n    invOrder: [STR_BELT, STR_LEFT_LEG, STR_RIGHT_LEG]\n  - type: OXCE_GRENADES\n    invOrder: [STR_RIGHT_SHOULDER, STR_LEFT_SHOULDER, STR_BELT, STR_LEFT_LEG, STR_RIGHT_LEG, STR_LEFT_HAND, STR_RIGHT_HAND, STR_BACK_PACK]\n  - type: OXCE_ARMORS_AND_CORPSES\n    invOrder: [STR_LEFT_HAND, STR_RIGHT_HAND, STR_BACK_PACK]\n  - type: OXCE_PRISONERS\n    invOrder: [STR_LEFT_HAND, STR_RIGHT_HAND, STR_BACK_PACK]\n  - type: OXCE_COMPONENTS\n    invOrder: [STR_LEFT_HAND, STR_BELT, STR_BACK_PACK]\n\n# 3. Use inventory slots ordered by listOrder (instead of alphabetical order)\nconstants:\n  extendedInventorySlotSorting: true\n\ninvs:\n  - id: STR_RIGHT_SHOULDER\n    listOrder: 10\n  - id: STR_LEFT_SHOULDER\n    listOrder: 20\n  - id: STR_BELT\n    listOrder: 30\n  - id: STR_LEFT_LEG\n    listOrder: 40\n  - id: STR_RIGHT_LEG\n    listOrder: 50\n  - id: STR_BACK_PACK\n    listOrder: 60\n# let's keep the hands low (or at least after the backpack, so that aliens don't auto-equip things like mind probes in hands)\n  - id: STR_RIGHT_HAND\n    listOrder: 70\n  - id: STR_LEFT_HAND\n    listOrder: 80\n  - id: STR_GROUND\n    listOrder: 90\n\n# end of file\n"
  },
  {
    "path": "bin/standard/Smarter_Equip_TFTD/2_Smarter_Equip_Item_Categorization.rul",
    "content": "items:\n  - type: STR_AJAX_LAUNCHER\n    categories: !add [OXCE_CRAFT_WEAPONS]\n  - type: STR_AJAX_TORPEDOES\n    categories: !add [OXCE_CRAFT_WEAPONS]\n  - type: STR_DUP_HEAD_LAUNCHER\n    categories: !add [OXCE_CRAFT_WEAPONS]\n  - type: STR_DUP_HEAD_TORPEDOES\n    categories: !add [OXCE_CRAFT_WEAPONS]\n  - type: STR_CRAFT_GAS_CANNON\n    categories: !add [OXCE_CRAFT_WEAPONS]\n  - type: STR_CRAFT_GAS_CANNON_ROUNDS_X50\n    categories: !add [OXCE_CRAFT_WEAPONS]\n  - type: STR_GAUSS_CANNON\n    categories: !add [OXCE_CRAFT_WEAPONS]\n  - type: STR_GAUSS_CANNON_AMMO\n    categories: !add [OXCE_CRAFT_WEAPONS, OXCE_HWPS]\n  - type: STR_SONIC_OSCILLATOR\n    categories: !add [OXCE_CRAFT_WEAPONS]\n  - type: STR_PWT_CANNON\n    categories: !add [OXCE_CRAFT_WEAPONS]\n  - type: STR_PULSE_WAVE_TORPEDOES\n    categories: !add [OXCE_CRAFT_WEAPONS]\n  - type: STR_COELACANTH_GAS_CANNON\n    categories: !add [OXCE_HWPS]\n  - type: STR_HWP_SOLID_HARPOON_BOLTS\n    categories: !add [OXCE_HWPS]\n  - type: STR_COELACANTH_AQUA_JET\n    categories: !add [OXCE_HWPS]\n  - type: STR_HWP_AQUA_JET_MISSILES\n    categories: !add [OXCE_HWPS]\n  - type: STR_COELACANTH_GAUSS\n    categories: !add [OXCE_HWPS]\n  - type: STR_DISPLACER_SONIC\n    categories: !add [OXCE_HWPS]\n  - type: STR_DISPLACER_PWT\n    categories: !add [OXCE_HWPS]\n  - type: STR_HWP_DISPLACER_PWT\n    categories: !add [OXCE_HWPS]\n  - type: STR_DART_PISTOL\n    categories: !add [OXCE_SIDE_WEAPONS]\n  - type: STR_DART_POD\n    categories: !add [OXCE_AMMO, OXCE_SIDE_WEAPONS]\n  - type: STR_JET_HARPOON\n    categories: !add [OXCE_MAIN_WEAPONS]\n  - type: STR_HARPOON_POD\n    categories: !add [OXCE_AMMO, OXCE_MAIN_WEAPONS]\n  - type: STR_GAS_CANNON\n    categories: !add [OXCE_MAIN_WEAPONS]\n  - type: STR_GC_AP_AMMO\n    categories: !add [OXCE_AMMO, OXCE_MAIN_WEAPONS]\n  - type: STR_GC_HE_AMMO\n    categories: !add [OXCE_AMMO, OXCE_MAIN_WEAPONS]\n  - type: STR_GC_P_AMMO\n    categories: !add [OXCE_AMMO, OXCE_MAIN_WEAPONS]\n  - type: STR_HYDRO_JET_CANNON\n    categories: !add [OXCE_MAIN_WEAPONS]\n  - type: STR_HJC_AP_AMMO\n    categories: !add [OXCE_AMMO, OXCE_MAIN_WEAPONS]\n  - type: STR_HJC_HE_AMMO\n    categories: !add [OXCE_AMMO, OXCE_MAIN_WEAPONS]\n  - type: STR_HJC_P_AMMO\n    categories: !add [OXCE_AMMO, OXCE_MAIN_WEAPONS]\n  - type: STR_TORPEDO_LAUNCHER\n    categories: !add [OXCE_MAIN_WEAPONS]\n  - type: STR_SMALL_TORPEDO\n    categories: !add [OXCE_AMMO, OXCE_MAIN_WEAPONS]\n  - type: STR_LARGE_TORPEDO\n    categories: !add [OXCE_AMMO, OXCE_MAIN_WEAPONS]\n  - type: STR_PHOSPHOROUS_TORPEDO\n    categories: !add [OXCE_AMMO, OXCE_MAIN_WEAPONS]\n  - type: STR_GAUSS_PISTOL\n    categories: !add [OXCE_SIDE_WEAPONS]\n  - type: STR_GAUSS_PISTOL_CLIP\n    categories: !add [OXCE_AMMO, OXCE_SIDE_WEAPONS]\n  - type: STR_GAUSS_RIFLE\n    categories: !add [OXCE_MAIN_WEAPONS]\n  - type: STR_GAUSS_RIFLE_CLIP\n    categories: !add [OXCE_AMMO, OXCE_MAIN_WEAPONS]\n  - type: STR_HEAVY_GAUSS\n    categories: !add [OXCE_MAIN_WEAPONS]\n  - type: STR_HEAVY_GAUSS_CLIP\n    categories: !add [OXCE_AMMO, OXCE_MAIN_WEAPONS]\n  - type: STR_MAGNA_BLAST_GRENADE\n    categories: !add [OXCE_GRENADES]\n  - type: STR_DYE_GRENADE\n    categories: !add [OXCE_GRENADES]\n  - type: STR_PARTICLE_DISTURBANCE_GRENADE\n    categories: !add [OXCE_GRENADES]\n  - type: STR_MAGNA_PACK_EXPLOSIVE\n    categories: !add [OXCE_GRENADES]\n  - type: STR_PARTICLE_DISTURBANCE_SENSOR\n    categories: !add [OXCE_SIDE_WEAPONS]\n  - type: STR_MEDI_KIT\n    categories: !add [OXCE_SIDE_WEAPONS]\n  - type: STR_MC_DISRUPTOR\n    categories: !add [OXCE_SIDE_WEAPONS]\n  - type: STR_THERMAL_TAZER\n    categories: !add [OXCE_SIDE_WEAPONS]\n  - type: STR_CHEMICAL_FLARE\n    categories: !add [OXCE_GRENADES]\n  - type: STR_SONIC_CANNON\n    categories: !add [OXCE_MAIN_WEAPONS]\n  - type: STR_CANNON_POWER_CLIP\n    categories: !add [OXCE_AMMO, OXCE_MAIN_WEAPONS]\n  - type: STR_SONIC_BLASTA_RIFLE\n    categories: !add [OXCE_MAIN_WEAPONS]\n  - type: STR_BLASTA_POWER_CLIP\n    categories: !add [OXCE_AMMO, OXCE_MAIN_WEAPONS]\n  - type: STR_SONIC_PISTOL\n    categories: !add [OXCE_SIDE_WEAPONS]\n  - type: STR_PISTOL_POWER_CLIP\n    categories: !add [OXCE_AMMO, OXCE_SIDE_WEAPONS]\n  - type: STR_DISRUPTOR_PULSE_LAUNCHER\n    categories: !add [OXCE_MAIN_WEAPONS]\n  - type: STR_DISRUPTOR_AMMO\n    categories: !add [OXCE_AMMO, OXCE_MAIN_WEAPONS]\n  - type: STR_THERMAL_SHOK_LAUNCHER\n    categories: !add [OXCE_MAIN_WEAPONS]\n  - type: STR_THERMAL_SHOK_BOMB\n    categories: !add [OXCE_AMMO, OXCE_MAIN_WEAPONS]\n  - type: STR_SONIC_PULSER\n    categories: !add [OXCE_GRENADES]\n  - type: STR_ZRBITE\n    categories: !add [OXCE_COMPONENTS]\n  - type: STR_MC_READER\n    categories: !add [OXCE_SIDE_WEAPONS]\n  - type: STR_VIBRO_BLADE\n    categories: !add [OXCE_SIDE_WEAPONS]\n  - type: STR_THERMIC_LANCE\n    categories: !add [OXCE_SIDE_WEAPONS]\n  - type: STR_HEAVY_THERMIC_LANCE\n    categories: !add [OXCE_SIDE_WEAPONS]\n  - type: STR_AQUATOID_CORPSE\n    categories: !add [OXCE_ARMORS_AND_CORPSES]\n  - type: STR_DEEP_ONE_CORPSE\n    categories: !add [OXCE_ARMORS_AND_CORPSES]\n  - type: STR_GILLMAN_CORPSE\n    categories: !add [OXCE_ARMORS_AND_CORPSES]\n  - type: STR_TASOTH_CORPSE\n    categories: !add [OXCE_ARMORS_AND_CORPSES]\n  - type: STR_CALCINITE_CORPSE\n    categories: !add [OXCE_ARMORS_AND_CORPSES]\n  - type: STR_TENTACULAT_CORPSE\n    categories: !add [OXCE_ARMORS_AND_CORPSES]\n  - type: STR_LOBSTERMAN_CORPSE\n    categories: !add [OXCE_ARMORS_AND_CORPSES]\n  - type: STR_BIODRONE_CORPSE\n    categories: !add [OXCE_ARMORS_AND_CORPSES]\n  - type: STR_XARQUID_CORPSE\n    categories: !add [OXCE_ARMORS_AND_CORPSES]\n  - type: STR_HALLUCINOID_CORPSE\n    categories: !add [OXCE_ARMORS_AND_CORPSES]\n  - type: STR_TRISCENE_CORPSE\n    categories: !add [OXCE_ARMORS_AND_CORPSES]\n  - type: STR_ION_BEAM_ACCELERATORS\n    categories: !add [OXCE_COMPONENTS]\n  - type: STR_MAGNETIC_NAVIGATION\n    categories: !add [OXCE_COMPONENTS]\n  - type: STR_ALIEN_SUB_CONSTRUCTION\n    categories: !add [OXCE_COMPONENTS]\n  - type: STR_ALIEN_CRYOGENICS\n    categories: !add [OXCE_COMPONENTS]\n  - type: STR_ALIEN_CLONING\n    categories: !add [OXCE_COMPONENTS]\n  - type: STR_ALIEN_LEARNING_ARRAYS\n    categories: !add [OXCE_COMPONENTS]\n  - type: STR_ALIEN_IMPLANTER\n    categories: !add [OXCE_COMPONENTS]\n  - type: STR_EXAMINATION_ROOM\n    categories: !add [OXCE_COMPONENTS]\n  - type: STR_ALIEN_REANIMATION_ZONE\n    categories: !add [OXCE_COMPONENTS]\n  - type: STR_AQUA_PLASTICS\n    categories: !add [OXCE_COMPONENTS]\n  - type: STR_PLASTIC_AQUA_ARMOR\n    categories: !add [OXCE_ARMORS_AND_CORPSES]\n  - type: STR_ION_ARMOR\n    categories: !add [OXCE_ARMORS_AND_CORPSES]\n  - type: STR_MAGNETIC_ION_ARMOR\n    categories: !add [OXCE_ARMORS_AND_CORPSES]\n  - type: STR_AQUATOID_SOLDIER\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_AQUATOID_SQUAD_LEADER\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_AQUATOID_TECHNICIAN\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_AQUATOID_MEDIC\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_AQUATOID_NAVIGATOR\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_AQUATOID_COMMANDER\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_HALLUCINOID_TERRORIST\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_CALCINITE_TERRORIST\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_GILLMAN_SOLDIER\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_GILLMAN_SQUAD_LEADER\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_GILLMAN_TECHNICIAN\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_GILLMAN_COMMANDER\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_DEEP_ONE_TERRORIST\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_XARQUID_TERRORIST\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_TASOTH_SOLDIER\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_TASOTH_SQUAD_LEADER\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_TRISCENE_TERRORIST\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_BIODRONE_TERRORIST\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_TENTACULAT_TERRORIST\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_LOBSTERMAN_SOLDIER\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_LOBSTERMAN_SQUAD_LEADER\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_LOBSTERMAN_TECHNICIAN\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_LOBSTERMAN_NAVIGATOR\n    categories: !add [OXCE_PRISONERS]\n  - type: STR_LOBSTERMAN_COMMANDER\n    categories: !add [OXCE_PRISONERS]\n\n# end of file\n"
  },
  {
    "path": "bin/standard/Smarter_Equip_TFTD/Language/cs.yml",
    "content": "cs:\n  OXCE_CRAFT_WEAPONS: \"Palubní zbraně\"\n  OXCE_HWPS: \"PZS\"\n  OXCE_MAIN_WEAPONS: \"Hlavní zbraně\"\n  OXCE_SIDE_WEAPONS: \"Boční zbraně\"\n  OXCE_AMMO: \"Munice\"\n  OXCE_GRENADES: \"Granáty\"\n  OXCE_ARMORS_AND_CORPSES: \"Zbroj a mrtvoly\"\n  OXCE_PRISONERS: \"Vězni\"\n  OXCE_COMPONENTS: \"Komponenty\"\n"
  },
  {
    "path": "bin/standard/Smarter_Equip_TFTD/Language/de.yml",
    "content": "en-US:\n  OXCE_CRAFT_WEAPONS: \"U-waffen\"\n  OXCE_HWPS: \"UWS\"\n  OXCE_MAIN_WEAPONS: \"Hauptwaffen\"\n  OXCE_SIDE_WEAPONS: \"Seitenwaffen\"\n  OXCE_AMMO: \"Munition\"\n  OXCE_GRENADES: \"Granaten\"\n  OXCE_ARMORS_AND_CORPSES: \"Rüstungen & Leichen\"\n  OXCE_PRISONERS: \"Gefangene\"\n  OXCE_COMPONENTS: \"Komponenten\"\n"
  },
  {
    "path": "bin/standard/Smarter_Equip_TFTD/Language/en-GB.yml",
    "content": "en-GB:\n  OXCE_CRAFT_WEAPONS: \"Craft weapons\"\n  OXCE_HWPS: \"SWSs\"\n  OXCE_MAIN_WEAPONS: \"Main weapons\"\n  OXCE_SIDE_WEAPONS: \"Side weapons\"\n  OXCE_AMMO: \"Ammo\"\n  OXCE_GRENADES: \"Grenades\"\n  OXCE_ARMORS_AND_CORPSES: \"Armors & Corpses\"\n  OXCE_PRISONERS: \"Prisoners\"\n  OXCE_COMPONENTS: \"Components\"\n"
  },
  {
    "path": "bin/standard/Smarter_Equip_TFTD/Language/en-US.yml",
    "content": "en-US:\n  OXCE_CRAFT_WEAPONS: \"Craft weapons\"\n  OXCE_HWPS: \"SWSs\"\n  OXCE_MAIN_WEAPONS: \"Main weapons\"\n  OXCE_SIDE_WEAPONS: \"Side weapons\"\n  OXCE_AMMO: \"Ammo\"\n  OXCE_GRENADES: \"Grenades\"\n  OXCE_ARMORS_AND_CORPSES: \"Armors & Corpses\"\n  OXCE_PRISONERS: \"Prisoners\"\n  OXCE_COMPONENTS: \"Components\"\n"
  },
  {
    "path": "bin/standard/Smarter_Equip_TFTD/Language/it.yml",
    "content": "it:\n  OXCE_CRAFT_WEAPONS: \"Armi da vascello\"\n  OXCE_HWPS: \"SAS\"\n  OXCE_MAIN_WEAPONS: \"Armi principali\"\n  OXCE_SIDE_WEAPONS: \"Armi secondarie\"\n  OXCE_AMMO: \"Munizioni\"\n  OXCE_GRENADES: \"Granate\"\n  OXCE_ARMORS_AND_CORPSES: \"Armature & Cadaveri\"\n  OXCE_PRISONERS: \"Progionieri\"\n  OXCE_COMPONENTS: \"Componenti\"\n"
  },
  {
    "path": "bin/standard/Smarter_Equip_TFTD/Language/pl.yml",
    "content": "en-US:\n  OXCE_CRAFT_WEAPONS: \"Broń pokładowa\"\n  OXCE_HWPS: \"PSB-y\"\n  OXCE_MAIN_WEAPONS: \"Uzbrojenie główne\"\n  OXCE_SIDE_WEAPONS: \"Uzbrojenie boczne\"\n  OXCE_AMMO: \"Amunicja\"\n  OXCE_GRENADES: \"Granaty\"\n  OXCE_ARMORS_AND_CORPSES: \"Pancerze i zwłoki\"\n  OXCE_PRISONERS: \"Więźniowie\"\n  OXCE_COMPONENTS: \"Komponenty\"\n"
  },
  {
    "path": "bin/standard/Smarter_Equip_TFTD/Language/ru.yml",
    "content": "ru:\n  OXCE_CRAFT_WEAPONS: \"Бортовое вооружение\"\n  OXCE_HWPS: \"ПБС\"\n  OXCE_MAIN_WEAPONS: \"Основное оружие\"\n  OXCE_SIDE_WEAPONS: \"Вспом. оружие\"\n  OXCE_AMMO: \"Боеприпасы\"\n  OXCE_GRENADES: \"Гранаты\"\n  OXCE_ARMORS_AND_CORPSES: \"Броня и трупы\"\n  OXCE_PRISONERS: \"Заключённые\"\n  OXCE_COMPONENTS: \"Компоненты\"\n"
  },
  {
    "path": "bin/standard/Smarter_Equip_TFTD/Language/uk.yml",
    "content": "uk:\n  OXCE_CRAFT_WEAPONS: \"Бортове озброєння\"\n  OXCE_HWPS: \"ПБС\"\n  OXCE_MAIN_WEAPONS: \"Основна зброя\"\n  OXCE_SIDE_WEAPONS: \"Допоміжна зброя\"\n  OXCE_AMMO: \"Набої\"\n  OXCE_GRENADES: \"Гранати\"\n  OXCE_ARMORS_AND_CORPSES: \"Броня та трупи\"\n  OXCE_PRISONERS: \"В'язні\"\n  OXCE_COMPONENTS: \"Компоненти\"\n"
  },
  {
    "path": "bin/standard/Smarter_Equip_TFTD/metadata.yml",
    "content": "#\n# metadata.yaml for Smarter Equip\n\nname: \"Smarter Equip\"\nversion: 1.1\ndescription: \"Custom priority order of inventory slots for auto-equip and ctrl-click-equip.\"\nauthor: Meridian\n\nmaster: xcom2\n"
  },
  {
    "path": "bin/standard/StrategyCore_Swap_Small_USOs_TFTD/StrategyCore_Swap_Small_USOs_TFTD.rul",
    "content": "# Swaps the maps and interception images for the survey ship and escort.\nufos:\n  - type: STR_SURVEY_SHIP\n    sprite: 1\n    battlescapeTerrainData:\n      name: UFO02\n      mapDataSets:\n        - BLANKS\n        - UEXT2\n        - UEXT3\n        - UINT1\n        - UINT2\n        - UINT3\n      mapBlocks:\n        - name: UFO02\n          width: 10\n          length: 10\n          items:\n            STR_ZRBITE:\n              - [2, 2, 0]\n  - type: STR_ESCORT\n    sprite: 0\n    battlescapeTerrainData:\n      name: UFO01\n      mapDataSets:\n        - BLANKS\n        - UEXT2\n        - UEXT3\n        - UINT1\n        - UINT2\n        - UINT3\n      mapBlocks:\n        - name: UFO01\n          width: 10\n          length: 10\nufopaedia:\n  - id: STR_SURVEY_SHIP\n    image_id: UP094.BDY\n  - id: STR_ESCORT\n    image_id: UP093.BDY"
  },
  {
    "path": "bin/standard/StrategyCore_Swap_Small_USOs_TFTD/metadata.yml",
    "content": "#\n# metadata.yaml for Swap Small USOs\n\nname: \"StrategyCore Swap Small USOs\"\nversion: 1.0\ndescription: \"Swaps the maps and interception images for the two small USOs to better suit what they represent.\"\nauthor: Zombie\n\nmaster: xcom2\n"
  },
  {
    "path": "bin/standard/TFTD_Damage/TFTD_Damage.rul",
    "content": "# increase the damage range to 50%-150%\nconstants:\n  - damageRange: 50"
  },
  {
    "path": "bin/standard/TFTD_Damage/metadata.yml",
    "content": "#\n# metadata.yaml for TFTD Damage Model\n\nname: \"TFTD Damage Model\"\nversion: 1.0\ndescription: \"Direct-fire weapons do 50-150% of their damage instead of 0-200%. WARNING: makes sectopods extremely hard to kill!\"\nauthor: the OpenXcom team\n\nmaster: xcom1\n"
  },
  {
    "path": "bin/standard/UFOextender_Gun_Melee/UFOextender_Gun_Melee.rul",
    "content": "# Based on UFOextender by Seb76 and Tycho\nitems:\n  - type: STR_PISTOL\n    meleeType: 6\n    meleePower: 20\n    tuMelee: 15\n    accuracyMelee: 100\n  - type: STR_RIFLE\n    meleeType: 6\n    meleePower: 50\n    tuMelee: 40\n    accuracyMelee: 100\n  - type: STR_HEAVY_CANNON\n    meleeType: 6\n    meleePower: 65\n    tuMelee: 50\n    accuracyMelee: 100\n  - type: STR_AUTO_CANNON\n    meleeType: 6\n    meleePower: 65\n    tuMelee: 50\n    accuracyMelee: 100\n  - type: STR_ROCKET_LAUNCHER\n    meleeType: 6\n    meleePower: 80\n    tuMelee: 80\n    accuracyMelee: 100\n  - type: STR_LASER_PISTOL\n    meleeType: 6\n    meleePower: 20\n    tuMelee: 15\n    accuracyMelee: 100\n  - type: STR_LASER_RIFLE\n    meleeType: 6\n    meleePower: 50\n    tuMelee: 40\n    accuracyMelee: 100\n  - type: STR_HEAVY_LASER\n    meleeType: 6\n    meleePower: 65\n    tuMelee: 50\n    accuracyMelee: 100\n  - type: STR_HEAVY_PLASMA\n    meleeType: 6\n    meleePower: 65\n    tuMelee: 50\n    accuracyMelee: 100\n  - type: STR_PLASMA_RIFLE\n    meleeType: 6\n    meleePower: 50\n    tuMelee: 40\n    accuracyMelee: 100\n  - type: STR_PLASMA_PISTOL\n    meleeType: 6\n    meleePower: 20\n    tuMelee: 15\n    accuracyMelee: 100\n  - type: STR_BLASTER_LAUNCHER\n    meleeType: 6\n    meleePower: 80\n    tuMelee: 80\n    accuracyMelee: 100\n  - type: STR_SMALL_LAUNCHER\n    meleeType: 6\n    meleePower: 50\n    tuMelee: 40\n    accuracyMelee: 100"
  },
  {
    "path": "bin/standard/UFOextender_Gun_Melee/metadata.yml",
    "content": "#\n# metadata.yaml for UFOextender Gun Melee\n\nname: \"UFOextender: Gun Melee\"\nversion: 1.0\ndescription: \"Adds a stun melee attack to every weapon (called Stun Fest in UFOextender). The TU/Damage is based on the weapon's class.\"\nauthor: the OpenXcom team\n\nmaster: xcom1\n"
  },
  {
    "path": "bin/standard/UFOextender_Gun_Melee_TFTD/UFOextender_Gun_Melee.rul",
    "content": "# Based on UFOextender by Seb76 and Tycho\nitems:\n  - type: STR_DART_PISTOL\n    meleeType: 6\n    meleePower: 20\n    tuMelee: 15\n    accuracyMelee: 100\n  - type: STR_JET_HARPOON\n    meleeType: 6\n    meleePower: 50\n    tuMelee: 40\n    accuracyMelee: 100\n  - type: STR_GAS_CANNON\n    meleeType: 6\n    meleePower: 65\n    tuMelee: 50\n    accuracyMelee: 100\n  - type: STR_HYDRO_JET_CANNON\n    meleeType: 6\n    meleePower: 65\n    tuMelee: 50\n    accuracyMelee: 100\n  - type: STR_TORPEDO_LAUNCHER\n    meleeType: 6\n    meleePower: 80\n    tuMelee: 80\n    accuracyMelee: 100\n  - type: STR_GAUSS_PISTOL\n    meleeType: 6\n    meleePower: 20\n    tuMelee: 15\n    accuracyMelee: 100\n  - type: STR_GAUSS_RIFLE\n    meleeType: 6\n    meleePower: 50\n    tuMelee: 40\n    accuracyMelee: 100\n  - type: STR_HEAVY_GAUSS\n    meleeType: 6\n    meleePower: 65\n    tuMelee: 50\n    accuracyMelee: 100\n  - type: STR_SONIC_CANNON\n    meleeType: 6\n    meleePower: 65\n    tuMelee: 50\n    accuracyMelee: 100\n  - type: STR_SONIC_BLASTA_RIFLE\n    meleeType: 6\n    meleePower: 50\n    tuMelee: 40\n    accuracyMelee: 100\n  - type: STR_SONIC_PISTOL\n    meleeType: 6\n    meleePower: 20\n    tuMelee: 15\n    accuracyMelee: 100\n  - type: STR_DISRUPTOR_PULSE_LAUNCHER\n    meleeType: 6\n    meleePower: 80\n    tuMelee: 80\n    accuracyMelee: 100\n  - type: STR_THERMAL_SHOK_LAUNCHER\n    meleeType: 6\n    meleePower: 50\n    tuMelee: 40\n    accuracyMelee: 100\n"
  },
  {
    "path": "bin/standard/UFOextender_Gun_Melee_TFTD/metadata.yml",
    "content": "#\n# metadata.yaml for UFOextender Gun Melee\n\nname: \"UFOextender: Gun Melee\"\nversion: 1.0\ndescription: \"Adds a stun melee attack to every weapon (called Stun Fest in UFOextender). The TU/Damage is based on the weapon's class.\"\nauthor: the OpenXcom team\n\nmaster: xcom2\n"
  },
  {
    "path": "bin/standard/UFOextender_Psionic_Line_Of_Fire/UFOextender_Psionic_Line_Of_Fire.rul",
    "content": "# Based on UFOextender by Seb76 and Tycho\nitems:\n  - type: STR_PSI_AMP\n    LOSRequired: true\n  - type: STR_MIND_PROBE\n    LOSRequired: true\n  - type: ALIEN_PSI_WEAPON\n    LOSRequired: true"
  },
  {
    "path": "bin/standard/UFOextender_Psionic_Line_Of_Fire/metadata.yml",
    "content": "#\n# metadata.yaml for UFOextender Psionic Line Of Fire\n\nname: \"UFOextender: Psionic Line Of Fire\"\nversion: 1.0\ndescription: \"Psionic weapons (both X-COM and aliens) can only be used with direct line-of-sight to the target.\"\nauthor: the OpenXcom team\n\nmaster: xcom1\n"
  },
  {
    "path": "bin/standard/UFOextender_Psionic_Line_Of_Fire_TFTD/UFOextender_Psionic_Line_Of_Fire.rul",
    "content": "# Based on UFOextender by Seb76 and Tycho\nitems:\n  - type: STR_MC_DISRUPTOR\n    LOSRequired: true\n  - type: STR_MC_READER\n    LOSRequired: true\n  - type: ALIEN_PSI_WEAPON\n    LOSRequired: true\n"
  },
  {
    "path": "bin/standard/UFOextender_Psionic_Line_Of_Fire_TFTD/metadata.yml",
    "content": "#\n# metadata.yaml for UFOextender Psionic Line Of Fire\n\nname: \"UFOextender: Psionic Line Of Fire\"\nversion: 1.0\ndescription: \"Psionic weapons (both X-COM and aliens) can only be used with direct line-of-sight to the target.\"\nauthor: the OpenXcom team\n\nmaster: xcom2\n"
  },
  {
    "path": "bin/standard/UFOextender_Starting_Avalanches/UFOextender_Starting_Avalanches.rul",
    "content": "# Based on UFOextender by Seb76 and Tycho\nstartingBase:\n  crafts:\n    - type: STR_SKYRANGER\n      id: 1\n      fuel: 1500\n      damage: 0\n      items:\n        STR_GRENADE: 8\n        STR_HC_AP_AMMO: 2\n        STR_HC_HE_AMMO: 2\n        STR_HEAVY_CANNON: 1\n        STR_PISTOL: 3\n        STR_PISTOL_CLIP: 5\n        STR_RIFLE: 6\n        STR_RIFLE_CLIP: 12\n      status: STR_READY\n    - type: STR_INTERCEPTOR\n      id: 1\n      fuel: 1000\n      damage: 0\n      weapons:\n        - type: STR_AVALANCHE\n          ammo: 3\n        - type: STR_AVALANCHE\n          ammo: 3\n      status: STR_READY\n    - type: STR_INTERCEPTOR\n      id: 2\n      fuel: 1000\n      damage: 0\n      weapons:\n        - type: STR_AVALANCHE\n          ammo: 3\n        - type: STR_AVALANCHE\n          ammo: 3\n  items:\n    STR_AC_AP_AMMO: 6\n    STR_AUTO_CANNON: 1\n    STR_AVALANCHE_LAUNCHER: 2\n    STR_AVALANCHE_MISSILES: 15\n    STR_GRENADE: 5\n    STR_HC_AP_AMMO: 6\n    STR_HEAVY_CANNON: 1\n    STR_PISTOL: 2\n    STR_PISTOL_CLIP: 8\n    STR_RIFLE: 2\n    STR_RIFLE_CLIP: 8\n    STR_ROCKET_LAUNCHER: 1\n    STR_SMALL_ROCKET: 4\n    STR_SMOKE_GRENADE: 5"
  },
  {
    "path": "bin/standard/UFOextender_Starting_Avalanches/metadata.yml",
    "content": "#\n# metadata.yaml for UFOextender Starting Avalanches\n\nname: \"UFOextender: Starting Avalanches\"\nversion: 1.0\ndescription: \"All starting X-COM craft come with Avalanche Missiles equipped.\"\nauthor: the OpenXcom team\n\nmaster: xcom1\n"
  },
  {
    "path": "bin/standard/XCOM_Damage/XCOM_Damage.rul",
    "content": "# increase the damage range to 0%-200%\nconstants:\n  - damageRange: 100"
  },
  {
    "path": "bin/standard/XCOM_Damage/metadata.yml",
    "content": "#\n# metadata.yaml for UFO Defense Damage Model\n\nname: \"UFO Defense Damage Model\"\nversion: 1.0\ndescription: \"Direct-fire weapons do 0-200% of their damage instead of 50-150%.\"\nauthor: the OpenXcom team\n\nmaster: xcom2\n"
  },
  {
    "path": "bin/standard/XcomUtil_Always_Daytime/XcomUtil_Always_Daytime.rul",
    "content": "# Based on XcomUtil by Scott Jones and BladeFireLight\nalienDeployments:\n  - type: STR_SMALL_SCOUT\n    shade: 0\n  - type: STR_MEDIUM_SCOUT\n    shade: 0\n  - type: STR_LARGE_SCOUT\n    shade: 0\n  - type: STR_HARVESTER\n    shade: 0\n  - type: STR_ABDUCTOR\n    shade: 0\n  - type: STR_TERROR_SHIP\n    shade: 0\n  - type: STR_BATTLESHIP\n    shade: 0\n  - type: STR_SUPPLY_SHIP\n    shade: 0\n  - type: STR_TERROR_MISSION\n    shade: 0\n  - type: STR_ALIEN_BASE_ASSAULT\n    shade: 0\n  - type: STR_BASE_DEFENSE\n    shade: 0\n  - type: STR_MARS_CYDONIA_LANDING\n    shade: 0\n  - type: STR_MARS_THE_FINAL_ASSAULT\n    shade: 0"
  },
  {
    "path": "bin/standard/XcomUtil_Always_Daytime/metadata.yml",
    "content": "#\n# metadata.yaml for XcomUtil Always Daytime\n\nname: \"XcomUtil: Always Daytime\"\nversion: 1.0\ndescription: \"Forces all ground missions to daytime.\"\nauthor: the OpenXcom team\n\nmaster: xcom1\n"
  },
  {
    "path": "bin/standard/XcomUtil_Always_Daytime_TFTD/XcomUtil_Always_Daytime.rul",
    "content": "# Based on XcomUtil by Scott Jones and BladeFireLight\nalienDeployments:\n  - type: STR_SURVEY_SHIP\n    shade: 0\n  - type: STR_ESCORT\n    shade: 0\n  - type: STR_CRUISER\n    shade: 0\n  - type: STR_HEAVY_CRUISER\n    shade: 0\n  - type: STR_HUNTER\n    shade: 0\n  - type: STR_BATTLESHIP\n    shade: 0\n  - type: STR_DREADNOUGHT\n    shade: 0\n  - type: STR_FLEET_SUPPLY_CRUISER\n    shade: 0\n  - type: STR_PORT_TERROR\n    shade: 0\n  - type: STR_ISLAND_TERROR\n    shade: 0\n  - type: STR_CARGO_SHIP_P1\n    shade: 0\n  - type: STR_CRUISE_SHIP_P1\n    shade: 0\n  - type: STR_CARGO_SHIP_P2\n    shade: 0\n  - type: STR_CRUISE_SHIP_P2\n    shade: 0\n  - type: STR_ARTIFACT_SITE_P1\n    shade: 0\n  - type: STR_ARTIFACT_SITE_P2\n    shade: 0\n  - type: STR_ALIEN_BASE_ASSAULT\n    shade: 0\n  - type: STR_ALIEN_COLONY_P2\n    shade: 0\n  - type: STR_BASE_DEFENSE\n    shade: 0\n  - type: STR_TLETH_P1\n    shade: 0\n  - type: STR_TLETH_P2\n    shade: 0\n  - type: STR_TLETH_P3\n    shade: 0"
  },
  {
    "path": "bin/standard/XcomUtil_Always_Daytime_TFTD/metadata.yml",
    "content": "#\n# metadata.yaml for XcomUtil Always Daytime\n\nname: \"XcomUtil: Always Daytime\"\nversion: 1.0\ndescription: \"Forces all ground missions to daytime.\"\nauthor: the OpenXcom team\n\nmaster: xcom2\n"
  },
  {
    "path": "bin/standard/XcomUtil_Always_Nighttime/XcomUtil_Always_Nighttime.rul",
    "content": "# Based on XcomUtil by Scott Jones and BladeFireLight\nalienDeployments:\n  - type: STR_SMALL_SCOUT\n    shade: 15\n  - type: STR_MEDIUM_SCOUT\n    shade: 15\n  - type: STR_LARGE_SCOUT\n    shade: 15\n  - type: STR_HARVESTER\n    shade: 15\n  - type: STR_ABDUCTOR\n    shade: 15\n  - type: STR_TERROR_SHIP\n    shade: 15\n  - type: STR_BATTLESHIP\n    shade: 15\n  - type: STR_SUPPLY_SHIP\n    shade: 15\n  - type: STR_TERROR_MISSION\n    shade: 15\n  - type: STR_ALIEN_BASE_ASSAULT\n    shade: 15\n  - type: STR_BASE_DEFENSE\n    shade: 15\n  - type: STR_MARS_CYDONIA_LANDING\n    shade: 15\n  - type: STR_MARS_THE_FINAL_ASSAULT\n    shade: 15"
  },
  {
    "path": "bin/standard/XcomUtil_Always_Nighttime/metadata.yml",
    "content": "#\n# metadata.yaml for XcomUtil Always Nighttime\n\nname: \"XcomUtil: Always Nighttime\"\nversion: 1.0\ndescription: \"Forces all ground missions to nighttime.\"\nauthor: the OpenXcom team\n\nmaster: xcom1\n"
  },
  {
    "path": "bin/standard/XcomUtil_Always_Nighttime_TFTD/XcomUtil_Always_Nighttime.rul",
    "content": "# Based on XcomUtil by Scott Jones and BladeFireLight\nalienDeployments:\n  - type: STR_SURVEY_SHIP\n    shade: 15\n  - type: STR_ESCORT\n    shade: 15\n  - type: STR_CRUISER\n    shade: 15\n  - type: STR_HEAVY_CRUISER\n    shade: 15\n  - type: STR_HUNTER\n    shade: 15\n  - type: STR_BATTLESHIP\n    shade: 15\n  - type: STR_DREADNOUGHT\n    shade: 15\n  - type: STR_FLEET_SUPPLY_CRUISER\n    shade: 15\n  - type: STR_PORT_TERROR\n    shade: 15\n  - type: STR_ISLAND_TERROR\n    shade: 15\n  - type: STR_CARGO_SHIP_P1\n    shade: 15\n  - type: STR_CRUISE_SHIP_P1\n    shade: 15\n  - type: STR_CARGO_SHIP_P2\n    shade: 15\n  - type: STR_CRUISE_SHIP_P2\n    shade: 15\n  - type: STR_ARTIFACT_SITE_P1\n    shade: 15\n  - type: STR_ARTIFACT_SITE_P2\n    shade: 15\n  - type: STR_ALIEN_BASE_ASSAULT\n    shade: 15\n  - type: STR_ALIEN_COLONY_P2\n    shade: 15\n  - type: STR_BASE_DEFENSE\n    shade: 15\n  - type: STR_TLETH_P1\n    shade: 15\n  - type: STR_TLETH_P2\n    shade: 15\n  - type: STR_TLETH_P3\n    shade: 15"
  },
  {
    "path": "bin/standard/XcomUtil_Always_Nighttime_TFTD/metadata.yml",
    "content": "#\n# metadata.yaml for XcomUtil Always Nighttime\n\nname: \"XcomUtil: Always Nighttime\"\nversion: 1.0\ndescription: \"Forces all ground missions to nighttime.\"\nauthor: the OpenXcom team\n\nmaster: xcom2\n"
  },
  {
    "path": "bin/standard/XcomUtil_Fighter_Transports/XcomUtil_Fighter_Transports.rul",
    "content": "# Based on XcomUtil by Scott Jones and BladeFireLight\ncrafts:\n  - type: STR_INTERCEPTOR\n    soldiers: 6\n    vehicles: 1\n    battlescapeTerrainData:\n      name: INTERC\n      mapDataSets:\n        - BLANKS\n        - PLANE\n      mapBlocks:\n        - name: INTERC\n          width: 10\n          length: 10\n  - type: STR_FIRESTORM\n    soldiers: 10\n    vehicles: 1\n    battlescapeTerrainData:\n      name: FIRES\n      mapDataSets:\n        - BLANKS\n        - LIGHTNIN\n      mapBlocks:\n        - name: FIRES\n          width: 10\n          length: 10\n    deployment:\n      - [5, 3, 1, 2]\n      - [5, 4, 1, 2]\n      - [4, 3, 1, 2]\n      - [4, 4, 1, 2]\n      - [4, 2, 1, 2]\n      - [4, 5, 1, 2]\n      - [3, 2, 1, 2]\n      - [3, 5, 1, 2]\n      - [2, 3, 1, 2]\n      - [2, 4, 1, 2]\n"
  },
  {
    "path": "bin/standard/XcomUtil_Fighter_Transports/metadata.yml",
    "content": "#\n# metadata.yaml for XcomUtil Fighter Transports\n\nname: \"XcomUtil: Fighter Transports\"\nversion: 1.0\ndescription: \"Allows fighter craft (Interceptor and Firestorm) to carry soldiers and tanks to ground missions.\"\nauthor: the OpenXcom team\n\nmaster: xcom1\n"
  },
  {
    "path": "bin/standard/XcomUtil_Fighter_Transports_TFTD/XcomUtil_Fighter_Transports_TFTD.rul",
    "content": "# Based on XcomUtil by Scott Jones and BladeFireLight\ncrafts:\n  - type: STR_BARRACUDA\n    soldiers: 6\n    vehicles: 1\n    battlescapeTerrainData:\n      name: BARRACUD\n      mapDataSets:\n        - BLANKS\n        - TRITON\n      mapBlocks:\n        - name: BARRACUD\n          width: 10\n          length: 10\n    deployment:\n      - [5, 6, 0, 4]\n      - [4, 6, 0, 4]\n      - [5, 5, 0, 4]\n      - [4, 5, 0, 4]\n      - [3, 6, 0, 4]\n      - [3, 5, 0, 4]\n  - type: STR_MANTA\n    soldiers: 9\n    vehicles: 1\n    battlescapeTerrainData:\n      name: MANTA\n      mapDataSets:\n        - BLANKS\n        - HAMMER\n      mapBlocks:\n        - name: MANTA\n          width: 10\n          length: 10\n    deployment:\n      - [5, 5, 0, 4]\n      - [4, 5, 0, 4]\n      - [5, 4, 0, 4]\n      - [4, 4, 0, 4]\n      - [5, 3, 0, 4]\n      - [4, 3, 0, 4]\n      - [3, 5, 0, 4]\n      - [3, 4, 0, 4]\n      - [3, 3, 0, 4]\n"
  },
  {
    "path": "bin/standard/XcomUtil_Fighter_Transports_TFTD/metadata.yml",
    "content": "#\n# metadata.yaml for XcomUtil Fighter Transports\n\nname: \"XcomUtil: Fighter Transports\"\nversion: 1.0\ndescription: \"Allows fighter subs (Barracuda and Manta) to carry soldiers and SWS to ground missions.\"\nauthor: the OpenXcom team\n\nmaster: xcom2\n"
  },
  {
    "path": "bin/standard/XcomUtil_High_Explosive_Damage/XcomUtil_High_Explosive_Damage.rul",
    "content": "# Based on XcomUtil by Scott Jones and BladeFireLight\nitems:\n  - type: STR_HIGH_EXPLOSIVE\n    power: 200\n    blastRadius: 10"
  },
  {
    "path": "bin/standard/XcomUtil_High_Explosive_Damage/metadata.yml",
    "content": "#\n# metadata.yaml for XcomUtil High Explosive Damage\n\nname: \"XcomUtil: High Explosive Damage\"\nversion: 1.0\ndescription: \"Increases the High Explosive damage to 200, letting it pierce UFO walls.\"\nauthor: the OpenXcom team\n\nmaster: xcom1\n"
  },
  {
    "path": "bin/standard/XcomUtil_High_Explosive_Damage_TFTD/XcomUtil_High_Explosive_Damage.rul",
    "content": "# Based on XcomUtil by Scott Jones and BladeFireLight\nitems:\n  - type: STR_MAGNA_PACK_EXPLOSIVE\n    power: 200\n    blastRadius: 10\n"
  },
  {
    "path": "bin/standard/XcomUtil_High_Explosive_Damage_TFTD/metadata.yml",
    "content": "#\n# metadata.yaml for XcomUtil High Explosive Damage\n\nname: \"XcomUtil: High Explosive Damage\"\nversion: 1.0\ndescription: \"Increases the Magna Pack Explosive damage to 200, letting it pierce USO walls.\"\nauthor: the OpenXcom team\n\nmaster: xcom2\n"
  },
  {
    "path": "bin/standard/XcomUtil_Improved_Gauss/TFTD_Improved_Gauss.rul",
    "content": "# Based on XcomUtil by Scott Jones and BladeFireLight\nitems:\n  - type: STR_GAUSS_RIFLE_CLIP\n    clipSize: 30\n  - type: STR_HEAVY_GAUSS_CLIP\n    power: 80\n    clipSize: 20"
  },
  {
    "path": "bin/standard/XcomUtil_Improved_Gauss/metadata.yml",
    "content": "#\n# metadata.yaml for XcomUtil Improved Gauss\n\nname: \"XcomUtil: Improved Gauss\"\nversion: 1.0\ndescription: \"Increases Gauss Rifle and Heavy Gauss clip size, increases Heavy Gauss damage to 80\"\nauthor: the OpenXcom team\n\nmaster: xcom2"
  },
  {
    "path": "bin/standard/XcomUtil_Improved_Ground_Tanks/XcomUtil_Improved_Ground_Tanks.rul",
    "content": "# Based on XcomUtil by Scott Jones and BladeFireLight\narmors:\n  - type: TANK_ARMOR\n    frontArmor: 130\n    sideArmor: 130\n    rearArmor: 130\n    underArmor: 100\nunits:\n  - type: STR_TANK_CANNON\n    stats:\n      tu: 100\n      stamina: 100\n      health: 90\n      bravery: 110\n      reactions: 30\n      firing: 60\n      throwing: 0\n      strength: 60\n      psiStrength: 100\n      psiSkill: 0\n      melee: 70\n  - type: STR_TANK_ROCKET_LAUNCHER\n    race: STR_TANK_ROCKET_LAUNCHER\n    stats:\n      tu: 100\n      stamina: 100\n      health: 90\n      bravery: 110\n      reactions: 30\n      firing: 60\n      throwing: 0\n      strength: 60\n      psiStrength: 100\n      psiSkill: 0\n      melee: 70\n  - type: STR_TANK_LASER_CANNON\n    race: STR_TANK_LASER_CANNON\n    stats:\n      tu: 100\n      stamina: 100\n      health: 90\n      bravery: 110\n      reactions: 30\n      firing: 60\n      throwing: 0\n      strength: 60\n      psiStrength: 100\n      psiSkill: 0\n      melee: 70"
  },
  {
    "path": "bin/standard/XcomUtil_Improved_Ground_Tanks/metadata.yml",
    "content": "#\n# metadata.yaml for XcomUtil Improved Ground Tanks\n\nname: \"XcomUtil: Improved Ground Tanks\"\nversion: 1.0\ndescription: \"Gives ground Tanks the same stats as Hovertanks.\"\nauthor: the OpenXcom team\n\nmaster: xcom1\n"
  },
  {
    "path": "bin/standard/XcomUtil_Improved_Heavy_Laser/XcomUtil_Improved_Heavy_Laser.rul",
    "content": "# Based on XcomUtil by Scott Jones and BladeFireLight\nitems:\n  - type: STR_HEAVY_LASER\n    power: 120\n    accuracySnap: 75\n    accuracyAimed: 110\n    tuSnap: 33\n    tuAimed: 60"
  },
  {
    "path": "bin/standard/XcomUtil_Improved_Heavy_Laser/metadata.yml",
    "content": "#\n# metadata.yaml for XcomUtil Improved Heavy Laser\n\nname: \"XcomUtil: Improved Heavy Laser\"\nversion: 1.0\ndescription: \"Increases the damage and accuracy of the Heavy Laser.\"\nauthor: the OpenXcom team\n\nmaster: xcom1\n"
  },
  {
    "path": "bin/standard/XcomUtil_Infinite_Gauss/TFTD_Infinite_Gauss.rul",
    "content": "# Based on XcomUtil by Scott Jones and BladeFireLight\nitems:\n  - type: STR_GAUSS_PISTOL\n    hitSound: 31\n    hitAnimation: 46\n    power: 45\n    damageType: 4\n    clipSize: -1\n    vaporColor: 2\n    vaporDensity: 5\n    compatibleAmmo: []\n  - delete: STR_GAUSS_PISTOL_CLIP\n  - type: STR_GAUSS_RIFLE\n    hitSound: 31\n    hitAnimation: 46\n    power: 60\n    damageType: 4\n    clipSize: -1\n    vaporColor: 2\n    vaporDensity: 10\n    compatibleAmmo: []\n  - delete: STR_GAUSS_RIFLE_CLIP\n  - type: STR_HEAVY_GAUSS\n    hitSound: 31\n    hitAnimation: 46\n    power: 80\n    damageType: 4\n    clipSize: -1\n    vaporColor: 2\n    vaporDensity: 15\n    compatibleAmmo: []\n  - delete: STR_HEAVY_GAUSS_CLIP\nresearch:\n  - delete: STR_GAUSS_PISTOL_CLIP\n  - delete: STR_GAUSS_RIFLE_CLIP\n  - delete: STR_HEAVY_GAUSS_CLIP\n  - name: STR_GAUSS_CANNON\n    dependencies:\n      - STR_HEAVY_GAUSS\nufopaedia:\n  - delete: STR_GAUSS_PISTOL_CLIP\n  - delete: STR_GAUSS_RIFLE_CLIP\n  - delete: STR_HEAVY_GAUSS_CLIP\nmanufacture:\n  - delete: STR_GAUSS_PISTOL_CLIP\n  - delete: STR_GAUSS_RIFLE_CLIP\n  - delete: STR_HEAVY_GAUSS_CLIP"
  },
  {
    "path": "bin/standard/XcomUtil_Infinite_Gauss/metadata.yml",
    "content": "#\n# metadata.yaml for XcomUtil Infinite Gauss\n\nname: \"XcomUtil: Infinite Gauss\"\nversion: 1.0\ndescription: \"Removes ammo limit for Gauss weapons, increases Heavy Gauss damage to 80\"\nauthor: the OpenXcom team\n\nmaster: xcom2"
  },
  {
    "path": "bin/standard/XcomUtil_No_Psionics/XcomUtil_No_Psionics.rul",
    "content": "# Based on XcomUtil by Scott Jones and BladeFireLight\nfacilities:\n  - delete: STR_PSIONIC_LABORATORY\n  - delete: STR_MIND_SHIELD\nitems:\n  - delete: STR_PSI_AMP\n# can't remove this weapon\n  - type: ALIEN_PSI_WEAPON\n    tuUse: 999\nresearch:\n  - delete: STR_MIND_SHIELD\n  - delete: STR_PSI_LAB\n  - delete: STR_PSI_AMP\n# fix lab unlockers\n  - name: STR_ETHEREAL_COMMANDER\n    unlocks:\n      - STR_LEADER_PLUS\n      - STR_COMMANDER_PLUS\n      - STR_ALIEN_ORIGINS\n  - name: STR_ETHEREAL_LEADER\n    unlocks:\n      - STR_LEADER_PLUS\n      - STR_ALIEN_ORIGINS\n  - name: STR_ETHEREAL_SOLDIER\n    unlocks:\n      - STR_ALIEN_ORIGINS\n  - name: STR_SECTOID_LEADER\n    unlocks:\n      - STR_LEADER_PLUS\n      - STR_ALIEN_ORIGINS\n  - name: STR_SECTOID_COMMANDER\n    unlocks:\n      - STR_LEADER_PLUS\n      - STR_COMMANDER_PLUS\n      - STR_ALIEN_ORIGINS\nmanufacture:\n  - delete: STR_PSI_AMP\nufopaedia:\n  - delete: STR_PSI_AMP\n  - delete: STR_PSIONIC_LABORATORY\n  - delete: STR_MIND_SHIELD"
  },
  {
    "path": "bin/standard/XcomUtil_No_Psionics/metadata.yml",
    "content": "#\n# metadata.yaml for XcomUtil No Psionics\n\nname: \"XcomUtil: No Psionics\"\nversion: 1.0\ndescription: \"Removes all Psi tech and items from the game, both X-COM and alien.\"\nauthor: the OpenXcom team\n\nmaster: xcom1\n"
  },
  {
    "path": "bin/standard/XcomUtil_No_Psionics_TFTD/XcomUtil_No_Psionics.rul",
    "content": "# Based on XcomUtil by Scott Jones and BladeFireLight\nfacilities:\n  - delete: STR_MC_LAB\n  - delete: STR_MC_GENERATOR\nitems:\n  - delete: STR_MC_DISRUPTOR\n# can't remove this weapon\n  - type: ALIEN_PSI_WEAPON\n    tuUse: 9999\nresearch:\n  - delete: STR_MC_DISRUPTOR\n  - delete: STR_MC_GENERATOR\n  - delete: STR_MC_LAB\n# fix lab unlockers\n  - name: STR_CALCINITE_TERRORIST\n    unlocks:\n      - STR_ALIEN_ORIGINS\n  - name: STR_HALLUCINOID_TERRORIST\n    unlocks:\n      - STR_ALIEN_ORIGINS\n  - name: STR_DEEP_ONE_TERRORIST\n    unlocks:\n      - STR_ALIEN_ORIGINS\n  - name: STR_XARQUID_TERRORIST\n    unlocks:\n      - STR_ALIEN_ORIGINS\n  - name: STR_TENTACULAT_TERRORIST\n    unlocks:\n      - STR_ALIEN_ORIGINS\n  - name: STR_BIODRONE_TERRORIST\n    unlocks:\n      - STR_ALIEN_ORIGINS\n  - name: STR_TRISCENE_TERRORIST\n    unlocks:\n      - STR_ALIEN_ORIGINS\n  - name: STR_MC_READER\n    dependencies: []\nmanufacture:\n  - delete: STR_MC_DISRUPTOR\nufopaedia:\n  - delete: STR_MC_DISRUPTOR\n  - delete: STR_MC_GENERATOR\n  - delete: STR_MC_LAB"
  },
  {
    "path": "bin/standard/XcomUtil_No_Psionics_TFTD/metadata.yml",
    "content": "#\n# metadata.yaml for XcomUtil No Psionics\n\nname: \"XcomUtil: No Psionics\"\nversion: 1.0\ndescription: \"Removes all Psi tech and items from the game, both X-COM and alien.\"\nauthor: the OpenXcom team\n\nmaster: xcom2\n"
  },
  {
    "path": "bin/standard/XcomUtil_Pistol_Auto_Shot/XcomUtil_Pistol_Auto_Shot.rul",
    "content": "# Based on XcomUtil by Scott Jones and BladeFireLight\nitems:\n  - type: STR_PISTOL\n    accuracyAuto: 60\n    tuAuto: 54"
  },
  {
    "path": "bin/standard/XcomUtil_Pistol_Auto_Shot/metadata.yml",
    "content": "#\n# metadata.yaml for XcomUtil Pistol Auto Shot\n\nname: \"XcomUtil: Pistol Auto Shot\"\nversion: 1.0\ndescription: \"Gives the standard-issue Pistol an auto shot.\"\nauthor: the OpenXcom team\n\nmaster: xcom1\n"
  },
  {
    "path": "bin/standard/XcomUtil_Pistol_Auto_Shot_TFTD/XcomUtil_Pistol_Auto_Shot.rul",
    "content": "# Based on XcomUtil by Scott Jones and BladeFireLight\nitems:\n  - type: STR_DART_PISTOL\n    accuracyAuto: 60\n    tuAuto: 54\n"
  },
  {
    "path": "bin/standard/XcomUtil_Pistol_Auto_Shot_TFTD/metadata.yml",
    "content": "#\n# metadata.yaml for XcomUtil Pistol Auto Shot\n\nname: \"XcomUtil: Dart Pistol Auto Shot\"\nversion: 1.0\ndescription: \"Gives the standard-issue Dart Pistol an auto shot.\"\nauthor: the OpenXcom team\n\nmaster: xcom2\n"
  },
  {
    "path": "bin/standard/XcomUtil_Skyranger_Weapon_Slot/XcomUtil_Skyranger_Weapon_Slot.rul",
    "content": "# Based on XcomUtil by Scott Jones and BladeFireLight\ncrafts:\n  - type: STR_SKYRANGER\n    weapons: 1"
  },
  {
    "path": "bin/standard/XcomUtil_Skyranger_Weapon_Slot/metadata.yml",
    "content": "#\n# metadata.yaml for XcomUtil Skyranger Weapon Slot\n\nname: \"XcomUtil: Skyranger Weapon Slot\"\nversion: 1.0\ndescription: \"Gives the Skyranger a craft weapon slot.\"\nauthor: the OpenXcom team\n\nmaster: xcom1\n"
  },
  {
    "path": "bin/standard/XcomUtil_Starting_Defensive_Base/XcomUtil_Starting_Defensive_Base.rul",
    "content": "# Based on XcomUtil by Scott Jones and BladeFireLight\nstartingBase:\n  facilities:\n      - type: STR_ACCESS_LIFT\n        x: 0\n        y: 2\n      - type: STR_HANGAR\n        x: 0\n        y: 0\n      - type: STR_HANGAR\n        x: 2\n        y: 0\n      - type: STR_HANGAR\n        x: 4\n        y: 0\n      - type: STR_GENERAL_STORES\n        x: 0\n        y: 3\n      - type: STR_LIVING_QUARTERS\n        x: 0\n        y: 4\n      - type: STR_LABORATORY\n        x: 1\n        y: 4\n      - type: STR_WORKSHOP\n        x: 2\n        y: 4\n      - type: STR_SMALL_RADAR_SYSTEM\n        x: 3\n        y: 4"
  },
  {
    "path": "bin/standard/XcomUtil_Starting_Defensive_Base/metadata.yml",
    "content": "#\n# metadata.yaml for XcomUtil Starting Defensive Base\n\nname: \"XcomUtil: Starting Defensive Base\"\nversion: 1.0\ndescription: \"Moves the starting 3 Hangars to the top to make the base easier to defend in Base Defense missions.\"\nauthor: the OpenXcom team\n\nmaster: xcom1\n"
  },
  {
    "path": "bin/standard/XcomUtil_Starting_Defensive_Base_TFTD/XcomUtil_Starting_Defensive_Base.rul",
    "content": "# Based on XcomUtil by Scott Jones and BladeFireLight\nstartingBase:\n  facilities:\n      - type: STR_AIR_LOCK\n        x: 0\n        y: 2\n      - type: STR_SUB_PEN\n        x: 0\n        y: 0\n      - type: STR_SUB_PEN\n        x: 2\n        y: 0\n      - type: STR_SUB_PEN\n        x: 4\n        y: 0\n      - type: STR_GENERAL_STORES\n        x: 0\n        y: 3\n      - type: STR_LIVING_QUARTERS\n        x: 0\n        y: 4\n      - type: STR_LABORATORY\n        x: 1\n        y: 4\n      - type: STR_WORKSHOP\n        x: 2\n        y: 4\n      - type: STR_STANDARD_SONAR\n        x: 3\n        y: 4\n"
  },
  {
    "path": "bin/standard/XcomUtil_Starting_Defensive_Base_TFTD/metadata.yml",
    "content": "#\n# metadata.yaml for XcomUtil Starting Defensive Base\n\nname: \"XcomUtil: Starting Defensive Base\"\nversion: 1.0\ndescription: \"Moves the starting 3 Sub Pens to the top to make the base easier to defend in Base Defense missions.\"\nauthor: the OpenXcom team\n\nmaster: xcom2\n"
  },
  {
    "path": "bin/standard/XcomUtil_Starting_Defensive_Improved_Base/XcomUtil_Starting_Defensive_Improved_Base.rul",
    "content": "# Based on XcomUtil by Scott Jones and BladeFireLight\nstartingBase:\n  facilities:\n      - type: STR_ACCESS_LIFT\n        x: 0\n        y: 2\n      - type: STR_HANGAR\n        x: 0\n        y: 0\n      - type: STR_HANGAR\n        x: 2\n        y: 0\n      - type: STR_HANGAR\n        x: 4\n        y: 0\n      - type: STR_GENERAL_STORES\n        x: 0\n        y: 3\n      - type: STR_LIVING_QUARTERS\n        x: 0\n        y: 4\n      - type: STR_LABORATORY\n        x: 1\n        y: 4\n      - type: STR_ALIEN_CONTAINMENT\n        x: 2\n        y: 4\n      - type: STR_WORKSHOP\n        x: 3\n        y: 4\n      - type: STR_LIVING_QUARTERS\n        x: 4\n        y: 4\n      - type: STR_LARGE_RADAR_SYSTEM\n        x: 5\n        y: 4\n  scientists: 50\n  engineers: 20"
  },
  {
    "path": "bin/standard/XcomUtil_Starting_Defensive_Improved_Base/metadata.yml",
    "content": "#\n# metadata.yaml for XcomUtil Starting Defensive Improved Base\n\nname: \"XcomUtil: Starting Defensive Improved Base\"\nversion: 1.0\ndescription: \"Combines the Starting Defensive Base mod with the Starting Improved Base mod.\"\nauthor: the OpenXcom team\n\nmaster: xcom1\n"
  },
  {
    "path": "bin/standard/XcomUtil_Starting_Defensive_Improved_Base_TFTD/XcomUtil_Starting_Defensive_Improved_Base.rul",
    "content": "# Based on XcomUtil by Scott Jones and BladeFireLight\nstartingBase:\n  facilities:\n      - type: STR_AIR_LOCK\n        x: 0\n        y: 2\n      - type: STR_SUB_PEN\n        x: 0\n        y: 0\n      - type: STR_SUB_PEN\n        x: 2\n        y: 0\n      - type: STR_SUB_PEN\n        x: 4\n        y: 0\n      - type: STR_GENERAL_STORES\n        x: 0\n        y: 3\n      - type: STR_LIVING_QUARTERS\n        x: 0\n        y: 4\n      - type: STR_LABORATORY\n        x: 1\n        y: 4\n      - type: STR_ALIEN_CONTAINMENT\n        x: 2\n        y: 4\n      - type: STR_WORKSHOP\n        x: 3\n        y: 4\n      - type: STR_LIVING_QUARTERS\n        x: 4\n        y: 4\n      - type: STR_WIDE_ARRAY_SONAR\n        x: 5\n        y: 4\n  scientists: 50\n  engineers: 20\n"
  },
  {
    "path": "bin/standard/XcomUtil_Starting_Defensive_Improved_Base_TFTD/metadata.yml",
    "content": "#\n# metadata.yaml for XcomUtil Starting Defensive Improved Base\n\nname: \"XcomUtil: Starting Defensive Improved Base\"\nversion: 1.0\ndescription: \"Combines the Starting Defensive Base mod with the Starting Improved Base mod.\"\nauthor: the OpenXcom team\n\nmaster: xcom2\n"
  },
  {
    "path": "bin/standard/XcomUtil_Starting_Improved_Base/XcomUtil_Starting_Improved_Base.rul",
    "content": "# Based on XcomUtil by Scott Jones and BladeFireLight\nstartingBase:\n  facilities:\n      - type: STR_ACCESS_LIFT\n        x: 3\n        y: 3\n      - type: STR_HANGAR\n        x: 2\n        y: 4\n      - type: STR_LIVING_QUARTERS\n        x: 2\n        y: 3\n      - type: STR_LABORATORY\n        x: 3\n        y: 2\n      - type: STR_WORKSHOP\n        x: 4\n        y: 2\n      - type: STR_HANGAR\n        x: 4\n        y: 0\n      - type: STR_GENERAL_STORES\n        x: 2\n        y: 2\n      - type: STR_LARGE_RADAR_SYSTEM\n        x: 1\n        y: 2\n      - type: STR_HANGAR\n        x: 0\n        y: 0\n      - type: STR_LIVING_QUARTERS\n        x: 1\n        y: 3\n      - type: STR_ALIEN_CONTAINMENT\n        x: 0\n        y: 3\n  scientists: 50\n  engineers: 20"
  },
  {
    "path": "bin/standard/XcomUtil_Starting_Improved_Base/metadata.yml",
    "content": "#\n# metadata.yaml for XcomUtil Starting Improved Base\n\nname: \"XcomUtil: Starting Improved Base\"\nversion: 1.0\ndescription: \"Gives the starting base a Large Radar, Alien Containment, 50 scientists and 20 engineers.\"\nauthor: the OpenXcom team\n\nmaster: xcom1\n"
  },
  {
    "path": "bin/standard/XcomUtil_Starting_Improved_Base_TFTD/XcomUtil_Starting_Improved_Base.rul",
    "content": "# Based on XcomUtil by Scott Jones and BladeFireLight\nstartingBase:\n  facilities:\n      - type: STR_AIR_LOCK\n        x: 3\n        y: 3\n      - type: STR_SUB_PEN\n        x: 2\n        y: 4\n      - type: STR_LIVING_QUARTERS\n        x: 2\n        y: 3\n      - type: STR_LABORATORY\n        x: 3\n        y: 2\n      - type: STR_WORKSHOP\n        x: 4\n        y: 2\n      - type: STR_SUB_PEN\n        x: 4\n        y: 0\n      - type: STR_GENERAL_STORES\n        x: 2\n        y: 2\n      - type: STR_WIDE_ARRAY_SONAR\n        x: 1\n        y: 2\n      - type: STR_SUB_PEN\n        x: 0\n        y: 0\n      - type: STR_LIVING_QUARTERS\n        x: 1\n        y: 3\n      - type: STR_ALIEN_CONTAINMENT\n        x: 0\n        y: 3\n  scientists: 50\n  engineers: 20\n"
  },
  {
    "path": "bin/standard/XcomUtil_Starting_Improved_Base_TFTD/metadata.yml",
    "content": "#\n# metadata.yaml for XcomUtil Starting Improved Base\n\nname: \"XcomUtil: Starting Improved Base\"\nversion: 1.0\ndescription: \"Gives the starting base a Wide Sonar, Alien Containment, 50 scientists and 20 engineers.\"\nauthor: the OpenXcom team\n\nmaster: xcom2\n"
  },
  {
    "path": "bin/standard/XcomUtil_Statstrings/XcomUtil_Statstrings.rul",
    "content": "# Based on XcomUtil by Scott Jones and BladeFireLight\n# See http://ufopaedia.org/index.php?title=Statstrings\n# These are the default statStrings from XcomUtil.\n# Melee has been added as a value that can be reported by statstrings.  Use \"melee:\" as the criteria.\n# Psionic Training has been added as a value that can be reported by statstrings.  Use \"psiTraining:\" as the criteria, values will be ignored.\n  statStrings:\n  - string: \"x\"\n    psiStrength: [~, 30]\n  - string: \"P\"\n    psiStrength: [80, ~]\n  - string: \"p\"\n    psiStrength: [60, 79]\n  - string: \"K\"\n    psiSkill: [60, ~]\n  - string: \"k\"\n    psiSkill: [30, 59]\n  - string: \"b\"\n    bravery: [60, ~]\n  - string: \"c\"\n    bravery: [~, 10]\n  - string: \"w\"\n    strength: [~, 25]\n  - string: \"Snpr\"\n    firing: [60, ~]\n    reactions: [60, ~]\n  - string: \"M\"\n    firing: [70, ~]\n  - string: \"m\"\n    firing: [60, 69]\n  - string: \"Sct\"\n    reactions: [50, ~]\n    tu: [60, ~]\n  - string: \"R\"\n    reactions: [60, ~]\n  - string: \"r\"\n    reactions: [50, 59]\n"
  },
  {
    "path": "bin/standard/XcomUtil_Statstrings/metadata.yml",
    "content": "#\n# metadata.yaml for XcomUtil Statstrings\n\nname: \"XcomUtil: Statstrings\"\nversion: 1.0\ndescription: \"Adds abbreviated notations to the end of a soldier's name to highlight the soldier's notable statistics\"\nauthor: the OpenXcom team\n\nmaster: xcom1\n"
  },
  {
    "path": "bin/standard/XcomUtil_Statstrings_TFTD/XcomUtil_Statstrings.rul",
    "content": "# Based on XcomUtil by Scott Jones and BladeFireLight\n# See http://ufopaedia.org/index.php?title=Statstrings\n# These are the default statStrings from XcomUtil.\n# Melee has been added as a value that can be reported by statstrings.  Use \"melee:\" as the criteria.\n# Psionic Training has been added as a value that can be reported by statstrings.  Use \"psiTraining:\" as the criteria, values will be ignored.\n  statStrings:\n  - string: \"x\"\n    psiStrength: [~, 30]\n  - string: \"P\"\n    psiStrength: [80, ~]\n  - string: \"p\"\n    psiStrength: [60, 79]\n  - string: \"K\"\n    psiSkill: [60, ~]\n  - string: \"k\"\n    psiSkill: [30, 59]\n  - string: \"b\"\n    bravery: [60, ~]\n  - string: \"c\"\n    bravery: [~, 10]\n  - string: \"w\"\n    strength: [~, 25]\n  - string: \"Snpr\"\n    firing: [60, ~]\n    reactions: [60, ~]\n  - string: \"M\"\n    firing: [70, ~]\n  - string: \"m\"\n    firing: [60, 69]\n  - string: \"Sct\"\n    reactions: [50, ~]\n    tu: [60, ~]\n  - string: \"R\"\n    reactions: [60, ~]\n  - string: \"r\"\n    reactions: [50, 59]\n"
  },
  {
    "path": "bin/standard/XcomUtil_Statstrings_TFTD/metadata.yml",
    "content": "#\n# metadata.yaml for XcomUtil Statstrings\n\nname: \"XcomUtil: Statstrings\"\nversion: 1.0\ndescription: \"Adds abbreviated notations to the end of a soldier's name to highlight the soldier's notable statistics\"\nauthor: the OpenXcom team\n\nmaster: xcom2\n"
  },
  {
    "path": "bin/standard/XcomUtil_Triton_Weapon_Slot/XcomUtil_Triton_Weapon_Slot.rul",
    "content": "# Based on XcomUtil by Scott Jones and BladeFireLight\ncrafts:\n  - type: STR_TRITON\n    weapons: 1"
  },
  {
    "path": "bin/standard/XcomUtil_Triton_Weapon_Slot/metadata.yml",
    "content": "#\n# metadata.yaml for XcomUtil Triton Weapon Slot\n\nname: \"XcomUtil: Triton Weapon Slot\"\nversion: 1.0\ndescription: \"Gives the Triton a craft weapon slot.\"\nauthor: the OpenXcom team\n\nmaster: xcom2\n"
  },
  {
    "path": "bin/standard/xcom1/Language/OXCE/cs.yml",
    "content": "cs:\n  STR_FACILITY_IN_USE_STORAGE: \"ZAŘÍZENÍ SE POUŽÍVÁ!{SMALLLINE}Nedostatek úložného prostoru.\"\n  STR_FACILITY_IN_USE_QUARTERS: \"ZAŘÍZENÍ SE POUŽÍVÁ!{SMALLLINE}Nedostatek ubytovacího prostoru.\"\n  STR_FACILITY_IN_USE_LABORATORIES: \"ZAŘÍZENÍ SE POUŽÍVÁ!{SMALLLINE}Nedostatek laboratorních míst.\"\n  STR_FACILITY_IN_USE_WORKSHOPS: \"ZAŘÍZENÍ SE POUŽÍVÁ!{SMALLLINE}Nedostatek pracovního místa.\"\n  STR_FACILITY_IN_USE_HANGARS: \"ZAŘÍZENÍ SE POUŽÍVÁ!{SMALLLINE}Nedostatek hangárů.\"\n  STR_FACILITY_IN_USE_PSI_LABS: \"ZAŘÍZENÍ SE POUŽÍVÁ!{SMALLLINE}Nedostatek míst v psi laboratoři.\"\n  STR_FACILITY_IN_USE_GYMS: \"ZAŘÍZENÍ SE POUŽÍVÁ!{SMALLLINE}Nedostatek míst v tělocvičnách.\"\n  STR_FACILITY_IN_USE_PRISONS: \"ZAŘÍZENÍ SE POUŽÍVÁ!{SMALLLINE}Nedostatek místa v cizáckých celách.\"\n  STR_AVATAR_NAME_1: \"#01 Muž, Blondýn\"\n  STR_AVATAR_NAME_2: \"#02 Muž, Hnědovlasý\"\n  STR_AVATAR_NAME_3: \"#03 Muž, Asiat\"\n  STR_AVATAR_NAME_4: \"#04 Muž, Afričan\"\n  STR_AVATAR_NAME_5: \"#05 Žena, Blondýna\"\n  STR_AVATAR_NAME_6: \"#06 Žena, Hnědovláska\"\n  STR_AVATAR_NAME_7: \"#07 Žena, Asiatka\"\n  STR_AVATAR_NAME_8: \"#08 Žena, Afričanka\"\n  STR_PSI_SHORT: \"PSI>{ALT}{0}/{1}\"\n  STR_EVASIVE_MANEUVERS: \"ÚHYBNÉ MANÉVRY\"\n  STR_UFO_DESTROYED_BY_SPLASHDOWN: \"UFO ZNIČENO PŘI DOPADU NA ZEM!\"\n  STR_UFO_SURVIVED_SPLASHDOWN: \"UFO PŘI HAVÁRII NEBYLO ZNIČENO!\"\n  STR_UFO_HAS_LANDED: \"UFO přistálo v{NEWLINE}{0}\"\n  GMGEO1: \"Hudba glóbusu č. 1\"\n  GMGEO2: \"Hudba glóbusu č. 2\"\n  GMTACTIC: \"Hudba bojiště\"\n  GMINTER: \"Hudba honička\"\n  GLOBE_TEXTURE_0: \"Les/džungle 1\"\n  GLOBE_TEXTURE_1: \"Farma 1\"\n  GLOBE_TEXTURE_2: \"Farma 2\"\n  GLOBE_TEXTURE_3: \"Farma 3\"\n  GLOBE_TEXTURE_4: \"Farma 4\"\n  GLOBE_TEXTURE_5: \"Hory\"\n  GLOBE_TEXTURE_6: \"Les/džungle 2\"\n  GLOBE_TEXTURE_7: \"Poušť 1\"\n  GLOBE_TEXTURE_8: \"Poušť 2\"\n  GLOBE_TEXTURE_9: \"Polární 1\"\n  GLOBE_TEXTURE_10: \"Les/džungle 3\"\n  GLOBE_TEXTURE_11: \"Les/džungle 4\"\n  GLOBE_TEXTURE_12: \"Polární 2\"\n  STR_LANDED: \"Přistálo\"\n  STR_SHOT_TYPE_AUTO: \"Auto (x{0})\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/OXCE/da.yml",
    "content": "da:\n  STR_AVATAR_NAME_1: \"#01 mand, blond\"\n  STR_AVATAR_NAME_2: \"#02 mand, brun hår\"\n  STR_AVATAR_NAME_3: \"#03 mand, asiatisk\"\n  STR_AVATAR_NAME_4: \"#04 mand, afrikansk\"\n  STR_AVATAR_NAME_5: \"#05 kvinde, blond\"\n  STR_AVATAR_NAME_6: \"#06 kvinde, brunt hår\"\n  STR_AVATAR_NAME_7: \"#07 kvinde, asiatisk\"\n  STR_AVATAR_NAME_8: \"#08 kvinde, afrikansk\"\n  STR_PSI_SHORT: \"PSI>{ALT}{0}/{1}\"\n  STR_EVASIVE_MANEUVERS: \"UNDVIGENDE MANØVRER\"\n  STR_UFO_HAS_LANDED: \"UFO er landet ved{NEWLINE}{0}\"\n  STR_SHOT_TYPE_AUTO: \"Auto (x{0})\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/OXCE/de.yml",
    "content": "de:\n  STR_FACILITY_IN_USE_STORAGE: \"EINRICHTUNG IN GEBRAUCH!{SMALLLINE}Nicht genügend Lagerraum.\"\n  STR_FACILITY_IN_USE_QUARTERS: \"EINRICHTUNG IN GEBRAUCH!{SMALLLINE}Nicht genügend Quartiere.\"\n  STR_FACILITY_IN_USE_LABORATORIES: \"EINRICHTUNG IN GEBRAUCH!{SMALLLINE}Nicht genügend Labore.\"\n  STR_FACILITY_IN_USE_WORKSHOPS: \"EINRICHTUNG IN GEBRAUCH!{SMALLLINE}Nicht genügend Werkstätten.\"\n  STR_FACILITY_IN_USE_HANGARS: \"EINRICHTUNG IN GEBRAUCH!{SMALLLINE}Nicht genügend Hangare.\"\n  STR_FACILITY_IN_USE_PSI_LABS: \"EINRICHTUNG IN GEBRAUCH!{SMALLLINE}Nicht genügend Psi-Labore.\"\n  STR_FACILITY_IN_USE_GYMS: \"EINRICHTUNG IN GEBRAUCH!{SMALLLINE}Nicht genügend Gyms.\"\n  STR_FACILITY_IN_USE_PRISONS: \"EINRICHTUNG IN GEBRAUCH!{SMALLLINE}Nicht genügend Außerirdischen-Klimazellen.\"\n  STR_NOT_ENOUGH_HWP_CAPACITY: \"NICHT GENUG SWT-KAPAZITÄT VERFÜGBAR!{SMALLLINE}Verwenden Sie ein anderes Modul oder reduzieren Sie die Anzahl der zugewiesenen SWTs.\"\n  STR_AVATAR_NAME_1: \"#01 Männlich, Blond\"\n  STR_AVATAR_NAME_2: \"#02 Männlich, Braunhaarig\"\n  STR_AVATAR_NAME_3: \"#03 Männlich, Asiatisch\"\n  STR_AVATAR_NAME_4: \"#04 Männlich, Afrikanisch\"\n  STR_AVATAR_NAME_5: \"#05 Weiblich, Blond\"\n  STR_AVATAR_NAME_6: \"#06 Weiblich, Braunhaarig\"\n  STR_AVATAR_NAME_7: \"#07 Weiblich, Asiatisch\"\n  STR_AVATAR_NAME_8: \"#08 Weiblich, Afrikanisch\"\n  STR_PSI_SHORT: \"PSI>{ALT}{0}/{1}\"\n  STR_EVASIVE_MANEUVERS: \"AUSWEICHMANÖVER\"\n  STR_UFO_DESTROYED_BY_SPLASHDOWN: \"UFO beim Aufprall zerstört!\"\n  STR_UFO_SURVIVED_SPLASHDOWN: \"UFO hat Aufprall überstanden\"\n  STR_UFO_HAS_LANDED: \"UFO gelandet an{NEWLINE}{0}\"\n  GMGEO1: \"Weltkarte Track #1\"\n  GMGEO2: \"Weltkarte Track #2\"\n  GMTACTIC: \"Gefechtskarte Track #1\"\n  GMINTER: \"Luftkampf Musiktitel\"\n  GLOBE_TEXTURE_0: \"Wald/Jungle 1\"\n  GLOBE_TEXTURE_1: \"Bauernhof 1\"\n  GLOBE_TEXTURE_2: \"Bauernhof 2\"\n  GLOBE_TEXTURE_3: \"Bauernhof 3\"\n  GLOBE_TEXTURE_4: \"Bauernhof 4\"\n  GLOBE_TEXTURE_5: \"Gebirge\"\n  GLOBE_TEXTURE_6: \"Wald/Jungle 2\"\n  GLOBE_TEXTURE_7: \"Wüste 1\"\n  GLOBE_TEXTURE_8: \"Wüste 2\"\n  GLOBE_TEXTURE_9: \"Arktis 1\"\n  GLOBE_TEXTURE_10: \"Wald/Jungle 3\"\n  GLOBE_TEXTURE_11: \"Wald/Jungle 4\"\n  GLOBE_TEXTURE_12: \"Arktis 2\"\n  STR_SHOT_TYPE_AUTO: \"Autoschuss (x{0})\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/OXCE/el.yml",
    "content": "el:\n  STR_FACILITY_IN_USE_STORAGE: \"ΕΓΚΑΤΑΣΤΑΣΗ ΣΕ ΧΡΗΣΗ!{SMALLLINE}Ανεπαρκής χώρος αποθήκευσης.\"\n  STR_FACILITY_IN_USE_QUARTERS: \"ΕΓΚΑΤΑΣΤΑΣΗ ΣΕ ΧΡΗΣΗ!{SMALLLINE}Ανεπαρκής χώροι διαβίωσης.\"\n  STR_FACILITY_IN_USE_LABORATORIES: \"ΕΓΚΑΤΑΣΤΑΣΗ ΣΕ ΧΡΗΣΗ!{SMALLLINE}Ανεπαρκής εργαστηριακός χώρος.\"\n  STR_FACILITY_IN_USE_WORKSHOPS: \"ΕΓΚΑΤΑΣΤΑΣΗ ΣΕ ΧΡΗΣΗ!{SMALLLINE}Ανεπαρκής βιοτεχνικός χώρος.\"\n  STR_FACILITY_IN_USE_HANGARS: \"ΕΓΚΑΤΑΣΤΑΣΗ ΣΕ ΧΡΗΣΗ!{SMALLLINE}Ανεπαρκής υπόστεγα.\"\n  STR_FACILITY_IN_USE_PSI_LABS: \"ΕΓΚΑΤΑΣΤΑΣΗ ΣΕ ΧΡΗΣΗ!{SMALLLINE}Ανεπαρκής εργαστήρια τηλεπάθειας.\"\n  STR_FACILITY_IN_USE_GYMS: \"ΕΓΚΑΤΑΣΤΑΣΗ ΣΕ ΧΡΗΣΗ!{SMALLLINE}Ανεπαρκής γυμναστήρια.\"\n  STR_FACILITY_IN_USE_PRISONS: \"ΕΓΚΑΤΑΣΤΑΣΗ ΣΕ ΧΡΗΣΗ!{SMALLLINE}Ανεπαρκής χώρος περιορισμού εξωγήινων.\"\n  STR_NOT_ENOUGH_HWP_CAPACITY: \"ΑΝΕΠΑΡΚΕΙΣ ΘΕΣΕΙΣ ΠΒΟ ΔΙΑΘΕΣΗΜΕΣ!{SMALLLINE}Χρησιμοποιήστε διαφορετική μονάδα ή μειώστε τον αριθμό των εκχωρημένων ΠΒΟ.\"\n  STR_AVATAR_NAME_1: \"#01 Άντρας, Ξανθός\"\n  STR_AVATAR_NAME_2: \"#02 Άντρας, Καφέ μαλί\"\n  STR_AVATAR_NAME_3: \"#03 Άντρας, Ασιάτης\"\n  STR_AVATAR_NAME_4: \"#04 Άντρας, Αφρικανός\"\n  STR_AVATAR_NAME_5: \"#05 Γυναίκα, Ξανθιά\"\n  STR_AVATAR_NAME_6: \"#06 Γυναίκα, Καφέ μαλί\"\n  STR_AVATAR_NAME_7: \"#07 Γυναίκα, Ασιάτισσα\"\n  STR_AVATAR_NAME_8: \"#08 Γυναίκα, Αφρικανή\"\n  STR_PSI_SHORT: \"Ψ>{ALT}{0}/{1}\"\n  STR_EVASIVE_MANEUVERS: \"ΕΛΙΓΜΟΙ ΑΠΟΦΥΓΗΣ\"\n  STR_UFO_DESTROYED_BY_SPLASHDOWN: \"ΤΟ ΑΤΙΑ ΚΑΤΑΣΤΡΑΦΗΚΕ ΑΠΟ ΤΗΝ ΠΡΟΣΘΑΛΑΣΩΣΗ!\"\n  STR_UFO_SURVIVED_SPLASHDOWN: \"ΤΟ ΑΤΙΑ ΕΠΕΖΗΣΕ ΑΠΟ ΤΗΝ ΠΡΟΣΘΑΛΑΣΩΣΗ!\"\n  STR_UFO_HAS_LANDED: \"Το ΑΤΙΑ προσγειώθηκε στο{NEWLINE}{0}\"\n  GMGEO1: \"Υδρόγειος τροχιά #1\"\n  GMGEO2: \"Υδρόγειος τροχιά #2\"\n  GMTACTIC: \"Τροχιά Πεδίου Μάχης\"\n  GMINTER: \"Τροχιά Αερομαχίας\"\n  GLOBE_TEXTURE_0: \"Δάσος/Ζούγκλα 1\"\n  GLOBE_TEXTURE_1: \"Αγροτική γη 1\"\n  GLOBE_TEXTURE_2: \"Αγροτική γη 2\"\n  GLOBE_TEXTURE_3: \"Αγροτική γη 3\"\n  GLOBE_TEXTURE_4: \"Αγροτική γη 4\"\n  GLOBE_TEXTURE_5: \"Βουνά\"\n  GLOBE_TEXTURE_6: \"Δάσος/Ζούγκλα 2\"\n  GLOBE_TEXTURE_7: \"Έρημος 1\"\n  GLOBE_TEXTURE_8: \"Έρημος 2\"\n  GLOBE_TEXTURE_9: \"Πολικό 1\"\n  GLOBE_TEXTURE_10: \"Δάσος/Ζούγκλα 3\"\n  GLOBE_TEXTURE_11: \"Δάσος/Ζούγκλα 4\"\n  GLOBE_TEXTURE_12: \"Πολικό 2\"\n  STR_LANDED: \"Προσγειώθηκε\"\n  STR_SHOT_TYPE_AUTO: \"Αύτο (x{0})\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/OXCE/en-GB.yml",
    "content": "en-GB:\n#=================== Basescape ===================\n#BasescapeState.cpp\n  STR_FACILITY_IN_USE_STORAGE: \"FACILITY IN USE!{SMALLLINE}Not enough storage space.\"\n  STR_FACILITY_IN_USE_QUARTERS: \"FACILITY IN USE!{SMALLLINE}Not enough living quarters.\"\n  STR_FACILITY_IN_USE_LABORATORIES: \"FACILITY IN USE!{SMALLLINE}Not enough lab space.\"\n  STR_FACILITY_IN_USE_WORKSHOPS: \"FACILITY IN USE!{SMALLLINE}Not enough workshop space.\"\n  STR_FACILITY_IN_USE_HANGARS: \"FACILITY IN USE!{SMALLLINE}Not enough hangars.\"\n  STR_FACILITY_IN_USE_PSI_LABS: \"FACILITY IN USE!{SMALLLINE}Not enough psi labs.\"\n  STR_FACILITY_IN_USE_GYMS: \"FACILITY IN USE!{SMALLLINE}Not enough gyms.\"\n  STR_FACILITY_IN_USE_PRISONS: \"FACILITY IN USE!{SMALLLINE}Not enough alien containment.\"\n#CraftWeaponsState.cpp\n  STR_NOT_ENOUGH_HWP_CAPACITY: \"NOT ENOUGH HWP CAPACITY AVAILABLE!{SMALLLINE}Use a different module or reduce the number of assigned HWPs.\"\n#SoldierAvatarState.cpp\n  STR_AVATAR_NAME_1: \"#01 Male, Blonde\"\n  STR_AVATAR_NAME_2: \"#02 Male, Brown hair\"\n  STR_AVATAR_NAME_3: \"#03 Male, Asian\"\n  STR_AVATAR_NAME_4: \"#04 Male, African\"\n  STR_AVATAR_NAME_5: \"#05 Female, Blonde\"\n  STR_AVATAR_NAME_6: \"#06 Female, Brown hair\"\n  STR_AVATAR_NAME_7: \"#07 Female, Asian\"\n  STR_AVATAR_NAME_8: \"#08 Female, African\"\n#=================== Battlescape ===================\n#InventoryState.cpp\n  STR_PSI_SHORT: \"PSI>{ALT}{0}/{1}\"\n#=================== Geoscape ===================\n#DogfightState.cpp\n  STR_EVASIVE_MANEUVERS: \"EVASIVE MANEUVERS\"\n  STR_UFO_DESTROYED_BY_SPLASHDOWN: \"UFO DESTROYED BY SPLASHDOWN!\"\n  STR_UFO_SURVIVED_SPLASHDOWN: \"UFO SURVIVED SPLASHDOWN!\"\n#GeoscapeState.cpp\n  STR_UFO_HAS_LANDED: \"UFO has landed at{NEWLINE}{0}\"\n#SelectMusicTrackState.cpp\n  GMGEO1: \"Geoscape Track #1\"\n  GMGEO2: \"Geoscape Track #2\"\n  GMTACTIC: \"Battlescape Track\"\n  GMINTER: \"Dogfight Track\"\n#=================== Menu ===================\n#NewBattleState.cpp\n  GLOBE_TEXTURE_0: \"Forest/Jungle 1\"\n  GLOBE_TEXTURE_1: \"Farmland 1\"\n  GLOBE_TEXTURE_2: \"Farmland 2\"\n  GLOBE_TEXTURE_3: \"Farmland 3\"\n  GLOBE_TEXTURE_4: \"Farmland 4\"\n  GLOBE_TEXTURE_5: \"Mountains\"\n  GLOBE_TEXTURE_6: \"Forest/Jungle 2\"\n  GLOBE_TEXTURE_7: \"Desert 1\"\n  GLOBE_TEXTURE_8: \"Desert 2\"\n  GLOBE_TEXTURE_9: \"Polar 1\"\n  GLOBE_TEXTURE_10: \"Forest/Jungle 3\"\n  GLOBE_TEXTURE_11: \"Forest/Jungle 4\"\n  GLOBE_TEXTURE_12: \"Polar 2\"\n  STR_LANDED: \"Landed\"\n#==================================================================================================================\n  STR_SHOT_TYPE_AUTO: \"Auto (x{0})\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/OXCE/en-US.yml",
    "content": "en-US:\n#=================== Basescape ===================\n#BasescapeState.cpp\n  STR_FACILITY_IN_USE_STORAGE: \"FACILITY IN USE!{SMALLLINE}Not enough storage space.\"\n  STR_FACILITY_IN_USE_QUARTERS: \"FACILITY IN USE!{SMALLLINE}Not enough living quarters.\"\n  STR_FACILITY_IN_USE_LABORATORIES: \"FACILITY IN USE!{SMALLLINE}Not enough lab space.\"\n  STR_FACILITY_IN_USE_WORKSHOPS: \"FACILITY IN USE!{SMALLLINE}Not enough workshop space.\"\n  STR_FACILITY_IN_USE_HANGARS: \"FACILITY IN USE!{SMALLLINE}Not enough hangars.\"\n  STR_FACILITY_IN_USE_PSI_LABS: \"FACILITY IN USE!{SMALLLINE}Not enough psi labs.\"\n  STR_FACILITY_IN_USE_GYMS: \"FACILITY IN USE!{SMALLLINE}Not enough gyms.\"\n  STR_FACILITY_IN_USE_PRISONS: \"FACILITY IN USE!{SMALLLINE}Not enough alien containment.\"\n#CraftWeaponsState.cpp\n  STR_NOT_ENOUGH_HWP_CAPACITY: \"NOT ENOUGH HWP CAPACITY AVAILABLE!{SMALLLINE}Use a different module or reduce the number of assigned HWPs.\"\n#SoldierAvatarState.cpp\n  STR_AVATAR_NAME_1: \"#01 Male, Blonde\"\n  STR_AVATAR_NAME_2: \"#02 Male, Brown hair\"\n  STR_AVATAR_NAME_3: \"#03 Male, Asian\"\n  STR_AVATAR_NAME_4: \"#04 Male, African\"\n  STR_AVATAR_NAME_5: \"#05 Female, Blonde\"\n  STR_AVATAR_NAME_6: \"#06 Female, Brown hair\"\n  STR_AVATAR_NAME_7: \"#07 Female, Asian\"\n  STR_AVATAR_NAME_8: \"#08 Female, African\"\n#=================== Battlescape ===================\n#InventoryState.cpp\n  STR_PSI_SHORT: \"PSI>{ALT}{0}/{1}\"\n#=================== Geoscape ===================\n#DogfightState.cpp\n  STR_EVASIVE_MANEUVERS: \"EVASIVE MANEUVERS\"\n  STR_UFO_DESTROYED_BY_SPLASHDOWN: \"UFO DESTROYED BY SPLASHDOWN!\"\n  STR_UFO_SURVIVED_SPLASHDOWN: \"UFO SURVIVED SPLASHDOWN!\"\n#GeoscapeState.cpp\n  STR_UFO_HAS_LANDED: \"UFO has landed at{NEWLINE}{0}\"\n#SelectMusicTrackState.cpp\n  GMGEO1: \"Geoscape Track #1\"\n  GMGEO2: \"Geoscape Track #2\"\n  GMTACTIC: \"Battlescape Track\"\n  GMINTER: \"Dogfight Track\"\n#=================== Menu ===================\n#NewBattleState.cpp\n  GLOBE_TEXTURE_0: \"Forest/Jungle 1\"\n  GLOBE_TEXTURE_1: \"Farmland 1\"\n  GLOBE_TEXTURE_2: \"Farmland 2\"\n  GLOBE_TEXTURE_3: \"Farmland 3\"\n  GLOBE_TEXTURE_4: \"Farmland 4\"\n  GLOBE_TEXTURE_5: \"Mountains\"\n  GLOBE_TEXTURE_6: \"Forest/Jungle 2\"\n  GLOBE_TEXTURE_7: \"Desert 1\"\n  GLOBE_TEXTURE_8: \"Desert 2\"\n  GLOBE_TEXTURE_9: \"Polar 1\"\n  GLOBE_TEXTURE_10: \"Forest/Jungle 3\"\n  GLOBE_TEXTURE_11: \"Forest/Jungle 4\"\n  GLOBE_TEXTURE_12: \"Polar 2\"\n  STR_LANDED: \"Landed\"\n#==================================================================================================================\n  STR_SHOT_TYPE_AUTO: \"Auto (x{0})\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/OXCE/es-419.yml",
    "content": "es-419:\n  STR_AVATAR_NAME_1: \"#01 Hombre, Rubio\"\n  STR_AVATAR_NAME_2: \"#02 Hombre, Pelo Castaño\"\n  STR_AVATAR_NAME_3: \"#03 Hombre, Asiático\"\n  STR_AVATAR_NAME_4: \"#04 Hombre, Africano\"\n  STR_AVATAR_NAME_5: \"#05 Mujer, Rubia\"\n  STR_AVATAR_NAME_6: \"#06 Mujer, Pelo Castaño\"\n  STR_AVATAR_NAME_7: \"#07 Mujer, Asiática\"\n  STR_AVATAR_NAME_8: \"#08 Mujer, Africana\"\n  STR_PSI_SHORT: \"PSI>{ALT}{0}/{1}\"\n  STR_EVASIVE_MANEUVERS: \"MANIOBRAS EVASIVAS\"\n  STR_UFO_DESTROYED_BY_SPLASHDOWN: \"OVNI DESTRUIDO AL ESTRELLARSE!\"\n  STR_UFO_SURVIVED_SPLASHDOWN: \"EL OVNI SOBREVIVIÓ EL IMPACTO!\"\n  STR_UFO_HAS_LANDED: \"OVNI ha aterrizado en{NEWLINE}{0}\"\n  GMGEO1: \"Pista Geoscape #1\"\n  GMGEO2: \"Pista Geoscape #2\"\n  GMTACTIC: \"Pista Battlescape\"\n  STR_SHOT_TYPE_AUTO: \"Auto (x{0})\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/OXCE/es-ES.yml",
    "content": "es-ES:\n  STR_NOT_ENOUGH_HWP_CAPACITY: \"¡NO HAY SUFICIENTE CAPACIDAD DE PAP DISPONIBLE!{SMALLLINE}Utilice un módulo diferente o reduzca la cantidad de PAP asignados.\"\n  STR_EVASIVE_MANEUVERS: \"MANIOBRAS EVASIVAS\"\n  STR_UFO_DESTROYED_BY_SPLASHDOWN: \"¡OVNI DESTRUIDO AL AMERIZAR!\"\n  STR_UFO_SURVIVED_SPLASHDOWN: \"¡OVNI SOBREVIVIÓ AL AMERIZAJE!\"\n  STR_UFO_HAS_LANDED: \"OVNI ha aterrizado en{NEWLINE}{0}\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/OXCE/et.yml",
    "content": "et:\n  STR_AVATAR_NAME_1: \"#01 Mees, blond\"\n  STR_AVATAR_NAME_2: \"#02 Mees, pruunipealine\"\n  STR_AVATAR_NAME_3: \"#03 Mees, asiaat\"\n  STR_AVATAR_NAME_4: \"#04 Mees, aafriklane\"\n  STR_AVATAR_NAME_5: \"#05 Naine, blond\"\n  STR_AVATAR_NAME_6: \"#06 Naine, pruunipealine\"\n  STR_AVATAR_NAME_7: \"#07 Naine, asiaat\"\n  STR_AVATAR_NAME_8: \"#08 Naine, aafriklane\"\n  STR_PSI_SHORT: \"PSI>{ALT}{0}/{1}\"\n  STR_EVASIVE_MANEUVERS: \"VÄLTIV MANÖÖVER VAJALIK\"\n  STR_UFO_DESTROYED_BY_SPLASHDOWN: \"VETTELARTSATUS HÄVITAS UFO!\"\n  STR_UFO_SURVIVED_SPLASHDOWN: \"UFO ELAS VETTELARTSATUSE ÜLE!\"\n  STR_UFO_HAS_LANDED: \"UFO on maandunud {NEWLINE}{0} juures\"\n  GMGEO1: \"Maakera lugu #1\"\n  GMGEO2: \"Maakera lugu #2\"\n  GMTACTIC: \"Lahingmaastiku lugu\"\n  STR_SHOT_TYPE_AUTO: \"Auto (x{0})\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/OXCE/fi.yml",
    "content": "fi:\n  STR_AVATAR_NAME_1: \"#01 Mies, vaaleahiuksinen\"\n  STR_AVATAR_NAME_2: \"#02 Mies, ruskeahiuksinen\"\n  STR_AVATAR_NAME_3: \"#03 Mies, aasialainen\"\n  STR_AVATAR_NAME_4: \"#04 Mies, afrikkalainen\"\n  STR_AVATAR_NAME_5: \"#05 Nainen, vaaleahiuksinen\"\n  STR_AVATAR_NAME_6: \"#06 Nainen, ruskeahiuksinen\"\n  STR_AVATAR_NAME_7: \"#07 Nainen, aasialainen\"\n  STR_AVATAR_NAME_8: \"#08 Nainen, afrikkalainen\"\n  STR_PSI_SHORT: \"PSI>{ALT}{0}/{1}\"\n  STR_EVASIVE_MANEUVERS: \"VÄISTÖLIIKKEET\"\n  STR_UFO_DESTROYED_BY_SPLASHDOWN: \"UFO TUHOUTUI VETEENSYÖKSYSSÄ!\"\n  STR_UFO_SURVIVED_SPLASHDOWN: \"UFO SELVIYTYI VETEENSYÖKSYSTÄ!\"\n  STR_UFO_HAS_LANDED: \"Ufo on laskeutunut sijainnissa{NEWLINE}{0}\"\n  GMGEO1: \"Geomaisemakappale #1\"\n  GMGEO2: \"Geomaisemakappale #2\"\n  GMTACTIC: \"Taistelukenttäkappale\"\n  GMINTER: \"Ilmataisteluraita\"\n  STR_SHOT_TYPE_AUTO: \"Sarja ({0})\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/OXCE/fr.yml",
    "content": "fr:\n  STR_FACILITY_IN_USE_STORAGE: \"INSTALLATION UTILISÉE!{SMALLLINE}Pas assez d'espace de stockage.\"\n  STR_FACILITY_IN_USE_QUARTERS: \"INSTALLATION UTILISÉE!{SMALLLINE}Pas assez d'espace de vie.\"\n  STR_FACILITY_IN_USE_LABORATORIES: \"INSTALLATION UTILISÉE!{SMALLLINE}Pas assez d'espace de labo.\"\n  STR_FACILITY_IN_USE_WORKSHOPS: \"INSTALLATION UTILISÉE!{SMALLLINE}Pas assez d'espace d'atelier.\"\n  STR_FACILITY_IN_USE_HANGARS: \"INSTALLATION UTILISÉE!{SMALLLINE}Pas assez de hangars.\"\n  STR_FACILITY_IN_USE_PSI_LABS: \"INSTALLATION UTILISÉE!{SMALLLINE}Pas assez de labo PSI.\"\n  STR_FACILITY_IN_USE_GYMS: \"INSTALLATION UTILISÉE!{SMALLLINE}Pas assez de salles de sport.\"\n  STR_FACILITY_IN_USE_PRISONS: \"INSTALLATION UTILISÉE!{SMALLLINE}Pas assez de confinement E.T.\"\n  STR_NOT_ENOUGH_HWP_CAPACITY: \"PAS ASSEZ DE CAPACITÉ PAL DISPONIBLE !{SMALLLINE}Utilisez un module différent ou réduisez le nombre de PAL assignés.\"\n  STR_AVATAR_NAME_1: \"#01 Masculin, Blond\"\n  STR_AVATAR_NAME_2: \"#02 Masculin, Cheveux bruns\"\n  STR_AVATAR_NAME_3: \"#03 Masculin, Asiatique\"\n  STR_AVATAR_NAME_4: \"#04 Masculin, Africain\"\n  STR_AVATAR_NAME_5: \"#05 Féminin, Blonde\"\n  STR_AVATAR_NAME_6: \"#06 Féminin, Cheveux bruns\"\n  STR_AVATAR_NAME_7: \"#07 Féminin, Asiatique\"\n  STR_AVATAR_NAME_8: \"#08 Féminin, Africaine\"\n  STR_PSI_SHORT: \"PSI>{ALT}{0}/{1}\"\n  STR_EVASIVE_MANEUVERS: \"MANŒUVRES ÉVASIVES\"\n  STR_UFO_DESTROYED_BY_SPLASHDOWN: \"OVNI DÉTRUIT LORS DE L'AMERRISSAGE!\"\n  STR_UFO_SURVIVED_SPLASHDOWN: \"L'OVNI A SURVÉCU À L'AMERRISSAGE!\"\n  STR_UFO_HAS_LANDED: \"L'OVNI a atterri à{NEWLINE}{0}\"\n  GMGEO1: \"Géoscape Piste #1\"\n  GMGEO2: \"Géoscape Piste #2\"\n  GMTACTIC: \"Piste Tactique\"\n  GMINTER: \"Piste de Combat aérien\"\n  GLOBE_TEXTURE_0: \"Forêt/Jungle 1\"\n  GLOBE_TEXTURE_1: \"Terre agricole 1\"\n  GLOBE_TEXTURE_2: \"Terre agricole 2\"\n  GLOBE_TEXTURE_3: \"Terre agricole 3\"\n  GLOBE_TEXTURE_4: \"Terre agricole 4\"\n  GLOBE_TEXTURE_5: \"Montagnes\"\n  GLOBE_TEXTURE_6: \"Forêt/Jungle 2\"\n  GLOBE_TEXTURE_7: \"Désert 1\"\n  GLOBE_TEXTURE_8: \"Désert 2\"\n  GLOBE_TEXTURE_9: \"Polaire 1\"\n  GLOBE_TEXTURE_10: \"Forêt/Jungle 3\"\n  GLOBE_TEXTURE_11: \"Forêt/Jungle 4\"\n  GLOBE_TEXTURE_12: \"Polaire 2\"\n  STR_LANDED: \"Attéri\"\n  STR_SHOT_TYPE_AUTO: \"Auto (x{0})\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/OXCE/hu.yml",
    "content": "hu:\n  STR_AVATAR_NAME_1: \"#01 Férfi, Szőke\"\n  STR_AVATAR_NAME_2: \"#02 Férfi, Barna haj\"\n  STR_AVATAR_NAME_3: \"#03 Férfi, Ázsiai\"\n  STR_AVATAR_NAME_4: \"#04 Férfi, Afrikai\"\n  STR_AVATAR_NAME_5: \"# 05 Nő, Szőke\"\n  STR_AVATAR_NAME_6: \"# 06 Nő, Barna haj\"\n  STR_AVATAR_NAME_7: \"# 07 Nõ, Ázsiai\"\n  STR_AVATAR_NAME_8: \"# 08 Nõ, Afrikai\"\n  STR_PSI_SHORT: \"PSI>{ALT}{0}/{1}\"\n  STR_EVASIVE_MANEUVERS: \"KITÉRŐ MANŐVEREK\"\n  STR_UFO_HAS_LANDED: \"UFO leszállt{NEWLINE}{0}\"\n  GMGEO1: \"Földgömb háttérzene #1\"\n  GMGEO2: \"Földgömb háttérzene #2\"\n  GMTACTIC: \"Harci háttérzene\"\n  STR_SHOT_TYPE_AUTO: \"Auto (x{0})\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/OXCE/it.yml",
    "content": "it:\n  STR_FACILITY_IN_USE_STORAGE: \"STRUTTURA IN USO!{SMALLLINE}Non ci sono abbastanza spazi di magazzino.\"\n  STR_FACILITY_IN_USE_QUARTERS: \"STRUTTURA IN USO!{SMALLLINE}Non ci sono abbastanza alloggi.\"\n  STR_FACILITY_IN_USE_LABORATORIES: \"STRUTTURA IN USO!{SMALLLINE}Non ci sono abbastanza laboratori.\"\n  STR_FACILITY_IN_USE_WORKSHOPS: \"STRUTTURA IN USO!{SMALLLINE}Non ci sono abbastanza officine.\"\n  STR_FACILITY_IN_USE_HANGARS: \"STRUTTURA IN USO!{SMALLLINE}Non ci sono abbastanza hangar.\"\n  STR_FACILITY_IN_USE_PSI_LABS: \"STRUTTURA IN USO!{SMALLLINE}Non ci sono abbastanza laboratori psionici.\"\n  STR_FACILITY_IN_USE_GYMS: \"STRUTTURA IN USO!{SMALLLINE}Non ci sono abbastanza palestre.\"\n  STR_FACILITY_IN_USE_PRISONS: \"STRUTTURA IN USO!{SMALLLINE}Non ci sono abbastanza contenimenti alieni.\"\n  STR_NOT_ENOUGH_HWP_CAPACITY: \"CAPACITÀ PER HWP INSUFFICIENTE!{SMALLLINE}Usa un modulo diverso o riduci il numero di HWP assegnati.\"\n  STR_AVATAR_NAME_1: \" #01 Maschio, Biondo\"\n  STR_AVATAR_NAME_2: \"#02 Maschio, Castano\"\n  STR_AVATAR_NAME_3: \"#03 Maschio, Asiatico\"\n  STR_AVATAR_NAME_4: \"#04 Maschio, Africano\"\n  STR_AVATAR_NAME_5: \"#05 Femmina, Bionda\"\n  STR_AVATAR_NAME_6: \"#06 Femmina, Castana\"\n  STR_AVATAR_NAME_7: \"#07 Femmina, Asiatica\"\n  STR_AVATAR_NAME_8: \"#08 Femmina, Africana\"\n  STR_PSI_SHORT: \"PSI>{ALT}{0}/{1}\"\n  STR_EVASIVE_MANEUVERS: \"MANOVRE EVASIVE\"\n  STR_UFO_DESTROYED_BY_SPLASHDOWN: \"UFO DISTRUTTO ALL'IMPATTO!\"\n  STR_UFO_SURVIVED_SPLASHDOWN: \"UFO SOPRAVVIVE ALL'IMPATTO!\"\n  STR_UFO_HAS_LANDED: \"L'UFO è atterrato a{NEWLINE}{0}\"\n  GMGEO1: \"Traccia Geoscape #1\"\n  GMGEO2: \"Traccia Geoscape #2\"\n  GMTACTIC: \"Traccia Battlescape\"\n  GMINTER: \"Traccia Intercettazione\"\n  GLOBE_TEXTURE_0: \"Foresta/Giungla 1\"\n  GLOBE_TEXTURE_1: \"Fattoria 1\"\n  GLOBE_TEXTURE_2: \"Fattoria 2\"\n  GLOBE_TEXTURE_3: \"Fattoria 3\"\n  GLOBE_TEXTURE_4: \"Fattoria 4\"\n  GLOBE_TEXTURE_5: \"Montagne\"\n  GLOBE_TEXTURE_6: \"Foresta/Giungla 2\"\n  GLOBE_TEXTURE_7: \"Deserto 1\"\n  GLOBE_TEXTURE_8: \"Deserto 2\"\n  GLOBE_TEXTURE_9: \"Polare 1\"\n  GLOBE_TEXTURE_10: \"Foresta/Giungla 3\"\n  GLOBE_TEXTURE_11: \"Foresta/Giungla 4\"\n  GLOBE_TEXTURE_12: \"Polare 2\"\n  STR_LANDED: \"Atterrato\"\n  STR_SHOT_TYPE_AUTO: \"Auto (x{0})\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/OXCE/ja.yml",
    "content": "ja:\n  STR_FACILITY_IN_USE_STORAGE: \"施設は使用中！{SMALLLINE}倉庫のスペースが足りません\"\n  STR_FACILITY_IN_USE_QUARTERS: \"施設は使用中！{SMALLLINE}居住スペースが足りません\"\n  STR_FACILITY_IN_USE_LABORATORIES: \"施設は使用中！{SMALLLINE}研究スペースが足りません\"\n  STR_FACILITY_IN_USE_WORKSHOPS: \"施設は使用中！{SMALLLINE}ワークショップのスペースが足りません\"\n  STR_FACILITY_IN_USE_HANGARS: \"施設は使用中！{SMALLLINE}格納スペースが足りません\"\n  STR_FACILITY_IN_USE_PSI_LABS: \"施設は使用中！{SMALLLINE}Psi研究所が足りません\"\n  STR_FACILITY_IN_USE_GYMS: \"施設は使用中！{SMALLLINE}ジムが足りません\"\n  STR_FACILITY_IN_USE_PRISONS: \"施設は使用中！{SMALLLINE}エイリアン隔離スペースが足りません\"\n  STR_NOT_ENOUGH_HWP_CAPACITY: \"HWP格納スペースが足りません！{SMALLLINE}異なる車体を選ぶか台数を減らしてください\"\n  STR_AVATAR_NAME_1: \"#01 男、金髪\"\n  STR_AVATAR_NAME_2: \"#02 男、茶髪\"\n  STR_AVATAR_NAME_3: \"#03 男、アジア人\"\n  STR_AVATAR_NAME_4: \"#04 男、アフリカン\"\n  STR_AVATAR_NAME_5: \"#05 女、金髪\"\n  STR_AVATAR_NAME_6: \"#06 女、茶髪\"\n  STR_AVATAR_NAME_7: \"#07 女、アジア人\"\n  STR_AVATAR_NAME_8: \"#08 女、アフリカン\"\n  STR_PSI_SHORT: \"PSI>{ALT}{0}/{1}\"\n  STR_EVASIVE_MANEUVERS: \"回避行動\"\n  STR_UFO_DESTROYED_BY_SPLASHDOWN: \"UFOが着水時に爆発！\"\n  STR_UFO_SURVIVED_SPLASHDOWN: \"UFOが着水に成功！\"\n  STR_UFO_HAS_LANDED: \"UFOが着陸>{NEWLINE}{0}\"\n  GMGEO1: \"ジオスケープの記録 #1\"\n  GMGEO2: \"ジオスケープの記録 #2\"\n  GMTACTIC: \"バトルスケープの記録\"\n  GMINTER: \"空戦の軌跡\"\n  GLOBE_TEXTURE_0: \"森/密林 1\"\n  GLOBE_TEXTURE_1: \"農地 1\"\n  GLOBE_TEXTURE_2: \"農地 2\"\n  GLOBE_TEXTURE_3: \"農地 3\"\n  GLOBE_TEXTURE_4: \"農地 4\"\n  GLOBE_TEXTURE_5: \"山地\"\n  GLOBE_TEXTURE_6: \"森/密林 2\"\n  GLOBE_TEXTURE_7: \"砂漠 1\"\n  GLOBE_TEXTURE_8: \"砂漠 2\"\n  GLOBE_TEXTURE_9: \"極地 1\"\n  GLOBE_TEXTURE_10: \"森/密林 3\"\n  GLOBE_TEXTURE_11: \"森/密林 4\"\n  GLOBE_TEXTURE_12: \"極地 2\"\n  STR_LANDED: \"着陸地点\"\n  STR_SHOT_TYPE_AUTO: \"自動 (x{0})\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/OXCE/ko.yml",
    "content": "ko:\n  STR_FACILITY_IN_USE_STORAGE: \"시설을 이용 중이다!{SMALLLINE}저장 공간이 충분하지 않다.\"\n  STR_FACILITY_IN_USE_QUARTERS: \"시설을 이용 중이다!{SMALLLINE}생활관 공간이 충분하지 않다.\"\n  STR_FACILITY_IN_USE_LABORATORIES: \"시설을 이용 중이다!{SMALLLINE}연구 공간이 충분하지 않다.\"\n  STR_FACILITY_IN_USE_WORKSHOPS: \"시설을 이용 중이다!{SMALLLINE}작업 공간이 충분하지 않다.\"\n  STR_FACILITY_IN_USE_HANGARS: \"시설을 이용 중이다!{SMALLLINE}격납고가 충분하지 않다.\"\n  STR_FACILITY_IN_USE_PSI_LABS: \"시설을 이용 중이다!{SMALLLINE}사이오닉 연구실 공간이 충분하지 않다.\"\n  STR_FACILITY_IN_USE_GYMS: \"시설을 이용 중이다!{SMALLLINE}체육관 공간이 충분하지 않다.\"\n  STR_FACILITY_IN_USE_PRISONS: \"시설을 이용 중이다!{SMALLLINE}외계인 격리실 공간이 충분하지 않다.\"\n  STR_NOT_ENOUGH_HWP_CAPACITY: \"쓸 수 있는 중화기 차량 수용량이 충분하지 않다!{SMALLLINE}다른 기체를 이용하거나 할당된 중화기 차량을 줄여라.\"\n  STR_AVATAR_NAME_1: \"#01 남자, 금발\"\n  STR_AVATAR_NAME_2: \"#02 남자, 갈색 머리\"\n  STR_AVATAR_NAME_3: \"#03 남자, 아시아인\"\n  STR_AVATAR_NAME_4: \"#04 남자, 아프리카인\"\n  STR_AVATAR_NAME_5: \"#05 여자, 금발\"\n  STR_AVATAR_NAME_6: \"#06 여자, 갈색 머리\"\n  STR_AVATAR_NAME_7: \"#07 여자, 아시아인\"\n  STR_AVATAR_NAME_8: \"#08 여자, 아프리카인\"\n  STR_PSI_SHORT: \"PSI>{ALT}{0}/{1}\"\n  STR_EVASIVE_MANEUVERS: \"회피 기동\"\n  STR_UFO_DESTROYED_BY_SPLASHDOWN: \"UFO가 물에 추락해 파괴됨!\"\n  STR_UFO_SURVIVED_SPLASHDOWN: \"UFO가 물에 추락해서 살아남음!\"\n  STR_UFO_HAS_LANDED: \"{0}{NEWLINE}에 UFO가 착륙했다\"\n  GMGEO1: \"지구화면 음악 #1\"\n  GMGEO2: \"지구화면 음악 #2\"\n  GMTACTIC: \"전투화면 음악\"\n  GMINTER: \"공중전 음악\"\n  GLOBE_TEXTURE_0: \"숲/정글 1\"\n  GLOBE_TEXTURE_1: \"농장 1\"\n  GLOBE_TEXTURE_2: \"농장 2\"\n  GLOBE_TEXTURE_3: \"농장 3\"\n  GLOBE_TEXTURE_4: \"농장 4\"\n  GLOBE_TEXTURE_5: \"산악\"\n  GLOBE_TEXTURE_6: \"숲/정글 2\"\n  GLOBE_TEXTURE_7: \"사막 1\"\n  GLOBE_TEXTURE_8: \"사막 2\"\n  GLOBE_TEXTURE_9: \"극지 1\"\n  GLOBE_TEXTURE_10: \"숲/정글 3\"\n  GLOBE_TEXTURE_11: \"숲/정글 4\"\n  GLOBE_TEXTURE_12: \"극지 2\"\n  STR_LANDED: \"착륙\"\n  STR_SHOT_TYPE_AUTO: \"자동사격 (x{0})\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/OXCE/nl.yml",
    "content": "nl:\n  STR_FACILITY_IN_USE_STORAGE: \"FACILITEIT IN GEBRUIK{SMALLLINE}Niet genoeg opslagplaats.\"\n  STR_FACILITY_IN_USE_QUARTERS: \"FACILITEIT IN GEBRUIK{SMALLLINE}Niet genoeg leefruimte.\"\n  STR_FACILITY_IN_USE_LABORATORIES: \"FACILITEIT IN GEBRUIK{SMALLLINE}Niet genoeg laboratoriumruimte.\"\n  STR_FACILITY_IN_USE_WORKSHOPS: \"FACILITEIT IN GEBRUIK{SMALLLINE}Niet genoeg werkplaatsruimte.\"\n  STR_FACILITY_IN_USE_HANGARS: \"FACILITEIT IN GEBRUIK{SMALLLINE}Niet genoeg hangaars.\"\n  STR_FACILITY_IN_USE_PSI_LABS: \"FACILITEIT IN GEBRUIK{SMALLLINE}Niet genoeg psionische laboratoriums.\"\n  STR_FACILITY_IN_USE_GYMS: \"FACILITEIT IN GEBRUIK{SMALLLINE}Niet genoeg fitnesscentra.\"\n  STR_FACILITY_IN_USE_PRISONS: \"FACILITEIT IN GEBRUIK{SMALLLINE}Niet genoeg buitenaardse klimaatcellen.\"\n  STR_NOT_ENOUGH_HWP_CAPACITY: \"NIET GENOEG HWP CAPACITEIT BESCHIKBAAR{SMALLLINE}Gebruik een andere module of verminder het aantal toegewezen HWP's\"\n  STR_AVATAR_NAME_1: \"#01 Man, Blond\"\n  STR_AVATAR_NAME_2: \"#02 Man, Bruin haar\"\n  STR_AVATAR_NAME_3: \"#03 Man, Aziatisch\"\n  STR_AVATAR_NAME_4: \"#04 Man, Afrikaans\"\n  STR_AVATAR_NAME_5: \"#05 Vrouw, Blond\"\n  STR_AVATAR_NAME_6: \"#06 Vrouw, Bruin haar\"\n  STR_AVATAR_NAME_7: \"#07 Vrouw, Aziatisch\"\n  STR_AVATAR_NAME_8: \"#08 Vrouw, Afrikaans\"\n  STR_PSI_SHORT: \"PSI>{ALT}{0}/{1}\"\n  STR_EVASIVE_MANEUVERS: \"ONTWIJKENDE MANEUVERS\"\n  STR_UFO_DESTROYED_BY_SPLASHDOWN: \"UFO VERNIETIGD DOOR SPLASHDOWN!\"\n  STR_UFO_SURVIVED_SPLASHDOWN: \"UFO OVERLEEFDE SPLASHDOWN!\"\n  STR_UFO_HAS_LANDED: \"UFO is geland op{NEWLINE}{0}\"\n  GMGEO1: \"Geoscape Muziekstuk #1\"\n  GMGEO2: \"Geoscape Muziekstuk #2\"\n  GMTACTIC: \"Battlescape Muziekstuk\"\n  GMINTER: \"Luchtgevecht Muziekstuk\"\n  GLOBE_TEXTURE_0: \"Bos/Oerwoud 1\"\n  GLOBE_TEXTURE_1: \"Landbouwgrond 1\"\n  GLOBE_TEXTURE_2: \"Landbouwgrond 2\"\n  GLOBE_TEXTURE_3: \"Landbouwgrond 3\"\n  GLOBE_TEXTURE_4: \"Landbouwgrond 4\"\n  GLOBE_TEXTURE_5: \"Bergen\"\n  GLOBE_TEXTURE_6: \"Bos/Oerwoud 2\"\n  GLOBE_TEXTURE_7: \"Woestijn 1\"\n  GLOBE_TEXTURE_8: \"Woestijn 2\"\n  GLOBE_TEXTURE_9: \"Pool 1\"\n  GLOBE_TEXTURE_10: \"Bos/Oerwoud 3\"\n  GLOBE_TEXTURE_11: \"Bos/Oerwoud 4\"\n  GLOBE_TEXTURE_12: \"Pool 2\"\n  STR_LANDED: \"Geland\"\n  STR_SHOT_TYPE_AUTO: \"Auto (x{0})\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/OXCE/pl.yml",
    "content": "pl:\n  STR_FACILITY_IN_USE_STORAGE: \"INSTALACJA W UŻYCIU!{SMALLLINE}Za mało miejsca w magazynach.\"\n  STR_FACILITY_IN_USE_QUARTERS: \"INSTALACJA W UŻYCIU!{SMALLLINE}Za mało kwater mieszkalnych.\"\n  STR_FACILITY_IN_USE_LABORATORIES: \"INSTALACJA W UŻYCIU!{SMALLLINE}Za mało stanowisk badawczych.\"\n  STR_FACILITY_IN_USE_WORKSHOPS: \"INSTALACJA W UŻYCIU!{SMALLLINE}Za mało stanowisk produkcyjnych.\"\n  STR_FACILITY_IN_USE_HANGARS: \"INSTALACJA W UŻYCIU!{SMALLLINE}Za mało hangarów.\"\n  STR_FACILITY_IN_USE_PSI_LABS: \"INSTALACJA W UŻYCIU!{SMALLLINE}Za mało laboratoriów psionicznych.\"\n  STR_FACILITY_IN_USE_GYMS: \"INSTALACJA W UŻYCIU!{SMALLLINE}Za mało stanowisk treningowych.\"\n  STR_FACILITY_IN_USE_PRISONS: \"INSTALACJA W UŻYCIU!{SMALLLINE}Za mało cel.\"\n  STR_NOT_ENOUGH_HWP_CAPACITY: \"ZA MAŁO MIEJSC DLA CDS!{SMALLLINE}Użyj innego modułu lub zmniejsz liczbę przydzielonych CDS-ów.\"\n  STR_AVATAR_NAME_1: \"#01 mężczyzna, blond\"\n  STR_AVATAR_NAME_2: \"#02 mężczyzna, szatyn\"\n  STR_AVATAR_NAME_3: \"#03 mężczyzna, Azjata\"\n  STR_AVATAR_NAME_4: \"#04 mężczyzna, Afrykanin\"\n  STR_AVATAR_NAME_5: \"#05 kobieta, blond\"\n  STR_AVATAR_NAME_6: \"#06 kobieta, szatynka\"\n  STR_AVATAR_NAME_7: \"#07 kobieta, Azjatka\"\n  STR_AVATAR_NAME_8: \"#08 kobieta, Afrykanka\"\n  STR_PSI_SHORT: \"PSI>{ALT}{0}/{1}\"\n  STR_EVASIVE_MANEUVERS: \"MANEWRY UNIKOWE\"\n  STR_UFO_DESTROYED_BY_SPLASHDOWN: \"UFO ZNISZCZONE PRZY WODOWANIU!\"\n  STR_UFO_SURVIVED_SPLASHDOWN: \"UFO PRZETRWAŁO WODOWANIE!\"\n  STR_UFO_HAS_LANDED: \"UFO wylądowało w{NEWLINE}{0}\"\n  GMGEO1: \"Ekran globu: motyw #1\"\n  GMGEO2: \"Ekran globu: motyw #2\"\n  GMTACTIC: \"Motyw z ekranu bitwy\"\n  GMINTER: \"Motyw walki powietrznej\"\n  GLOBE_TEXTURE_0: \"Las/Dżungla 1\"\n  GLOBE_TEXTURE_1: \"Teren rolniczy 1\"\n  GLOBE_TEXTURE_2: \"Teren rolniczy 2\"\n  GLOBE_TEXTURE_3: \"Teren rolniczy 3\"\n  GLOBE_TEXTURE_4: \"Teren rolniczy 4\"\n  GLOBE_TEXTURE_5: \"Góry\"\n  GLOBE_TEXTURE_6: \"Las/Dżungla 2\"\n  GLOBE_TEXTURE_7: \"Pustynia 1\"\n  GLOBE_TEXTURE_8: \"Pustynia 2\"\n  GLOBE_TEXTURE_9: \"Polarny 1\"\n  GLOBE_TEXTURE_10: \"Las/Dżungla 3\"\n  GLOBE_TEXTURE_11: \"Las/Dżungla 4\"\n  GLOBE_TEXTURE_12: \"Polarny 2\"\n  STR_LANDED: \"Lądowanie\"\n  STR_SHOT_TYPE_AUTO: \"Seria (x{0})\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/OXCE/pt-BR.yml",
    "content": "pt-BR:\n  STR_FACILITY_IN_USE_STORAGE: \"INSTALAÇÃO EM USO!{SMALLLINE}Espaço de armazenamento insuficiente.\"\n  STR_FACILITY_IN_USE_QUARTERS: \"INSTALAÇÃO EM USO!{SMALLLINE}Habitações insuficientes.\"\n  STR_FACILITY_IN_USE_LABORATORIES: \"INSTALAÇÃO EM USO!{SMALLLINE}Espaço de laboratório insuficiente.\"\n  STR_FACILITY_IN_USE_WORKSHOPS: \"INSTALAÇÃO EM USO!{SMALLLINE}Espaço de oficina insuficiente.\"\n  STR_FACILITY_IN_USE_HANGARS: \"INSTALAÇÃO EM USO!{SMALLLINE}Espaço de hangar insuficiente.\"\n  STR_FACILITY_IN_USE_PSI_LABS: \"INSTALAÇÃO EM USO!{SMALLLINE}Laboratórios psíquicos insuficientes.\"\n  STR_FACILITY_IN_USE_GYMS: \"INSTALAÇÃO EM USO!{SMALLLINE}Academias insuficientes.\"\n  STR_FACILITY_IN_USE_PRISONS: \"INSTALAÇÃO EM USO!{SMALLLINE}Contenção alienígena insuficiente.\"\n  STR_NOT_ENOUGH_HWP_CAPACITY: \"CAPACIDADE DE PAP INSUFICIENTE DISPONÍVEL!{SMALLLINE}Use um módulo diferente ou reduza o número de PAPs atribuídas.\"\n  STR_AVATAR_NAME_1: \"N° 01 Masculino, Loiro\"\n  STR_AVATAR_NAME_2: \"N° 02 Masculino, Cabelo Castanho\"\n  STR_AVATAR_NAME_3: \"N° 03 Masculino, Asiático\"\n  STR_AVATAR_NAME_4: \"N° 04 Masculino, Africano\"\n  STR_AVATAR_NAME_5: \"N° 05 Feminino, Loira\"\n  STR_AVATAR_NAME_6: \"N° 06 Feminino, Cabelo Castanho\"\n  STR_AVATAR_NAME_7: \"N° 07 Feminino, Asiática\"\n  STR_AVATAR_NAME_8: \"N° 08 Feminino, Africana\"\n  STR_PSI_SHORT: \"PSI>{ALT}{0}/{1}\"\n  STR_EVASIVE_MANEUVERS: \"MANOBRAS EVASIVAS\"\n  STR_UFO_DESTROYED_BY_SPLASHDOWN: \"OVNI DESTRUÍDO PELO IMPACTO!\"\n  STR_UFO_SURVIVED_SPLASHDOWN: \"OVNI SOBREVIVEU AO IMPACTO AQUÁTICO!\"\n  STR_UFO_HAS_LANDED: \"OVNI pousou em{NEWLINE}{0}\"\n  GMGEO1: \"Faixa nº 1 da Tela Global\"\n  GMGEO2: \"Faixa nº 2 da Tela Global\"\n  GMTACTIC: \"Faixa da Tela de Combate\"\n  GMINTER: \"Faixa do Combate Aéreo\"\n  GLOBE_TEXTURE_0: \"Floresta/Selva 1\"\n  GLOBE_TEXTURE_1: \"Terras agrícola 1\"\n  GLOBE_TEXTURE_2: \"Terras agrícola 2\"\n  GLOBE_TEXTURE_3: \"Terras agrícola 3\"\n  GLOBE_TEXTURE_4: \"Terras agrícola 4\"\n  GLOBE_TEXTURE_5: \"Montanhas\"\n  GLOBE_TEXTURE_6: \"Floresta/Selva 2\"\n  GLOBE_TEXTURE_7: \"Deserto 1\"\n  GLOBE_TEXTURE_8: \"Deserto 2\"\n  GLOBE_TEXTURE_9: \"Polar 1\"\n  GLOBE_TEXTURE_10: \"Floresta/Selva 3\"\n  GLOBE_TEXTURE_11: \"Floresta/Selva 4\"\n  GLOBE_TEXTURE_12: \"Polar 2\"\n  STR_LANDED: \"Pousado \"\n  STR_SHOT_TYPE_AUTO: \"Auto (x{0})\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/OXCE/ro.yml",
    "content": "ro:\n  STR_AVATAR_NAME_1: \"#01 Barbat, Blond\"\n  STR_AVATAR_NAME_2: \"$01 Barbat, Șaten\"\n  STR_AVATAR_NAME_3: \"#03 Barbat, Asiatic\"\n  STR_AVATAR_NAME_4: \"#04 Barbat, African\"\n  STR_AVATAR_NAME_5: \"#05 Femeie, Blondă\"\n  STR_AVATAR_NAME_6: \"#06 Femeie, Șatenă\"\n  STR_AVATAR_NAME_7: \"#07 Femeie, Asiatică\"\n  STR_AVATAR_NAME_8: \"#08 Femeie, Africană\"\n  STR_PSI_SHORT: \"PSI>{ALT}{0}/{1}\"\n  STR_EVASIVE_MANEUVERS: \"MANEVRE EVAZIVE\"\n  STR_UFO_HAS_LANDED: \"OZN-ul a aterizat la{NEWLINE}{0}\"\n  GMGEO1: \"Geosferă Pista #1\"\n  GMGEO2: \"Geosferă Pista #2\"\n  GMTACTIC: \"Pista Câmp Luptă\"\n  STR_SHOT_TYPE_AUTO: \"Auto (x{0})\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/OXCE/ru.yml",
    "content": "ru:\n  STR_FACILITY_IN_USE_STORAGE: \"МОДУЛЬ ИСПОЛЬЗУЕТСЯ!{SMALLLINE}Недостаточно места на складе.\"\n  STR_FACILITY_IN_USE_QUARTERS: \"МОДУЛЬ ИСПОЛЬЗУЕТСЯ!{SMALLLINE}Недостаточно места в жилых модулях.\"\n  STR_FACILITY_IN_USE_LABORATORIES: \"МОДУЛЬ ИСПОЛЬЗУЕТСЯ!{SMALLLINE}Недостаточно рабочего пространства в лаборатории.\"\n  STR_FACILITY_IN_USE_WORKSHOPS: \"МОДУЛЬ ИСПОЛЬЗУЕТСЯ!{SMALLLINE}Недостаточно рабочего пространства в мастерской.\"\n  STR_FACILITY_IN_USE_HANGARS: \"МОДУЛЬ ИСПОЛЬЗУЕТСЯ!{SMALLLINE}Недостаточно места в ангарах.\"\n  STR_FACILITY_IN_USE_PSI_LABS: \"МОДУЛЬ ИСПОЛЬЗУЕТСЯ!{SMALLLINE}Недостаточно пространства в пси-лаборатории.\"\n  STR_FACILITY_IN_USE_GYMS: \"МОДУЛЬ ИСПОЛЬЗУЕТСЯ!{SMALLLINE}Недостаточно места в спортзале.\"\n  STR_FACILITY_IN_USE_PRISONS: \"МОДУЛЬ ИСПОЛЬЗУЕТСЯ!{SMALLLINE}Недостаточно места в изоляторе пришельцев.\"\n  STR_NOT_ENOUGH_HWP_CAPACITY: \"НЕДОСТАТОЧНО МЕСТ ПОД ТБП!{SMALLLINE}Установите другой грузовой отсек или уберите часть ТБП.\"\n  STR_AVATAR_NAME_1: \"#01 Муж, Блондин\"\n  STR_AVATAR_NAME_2: \"#02 Муж, Шатен\"\n  STR_AVATAR_NAME_3: \"#03 Муж, Азиат\"\n  STR_AVATAR_NAME_4: \"#04 Муж, Темнокожий\"\n  STR_AVATAR_NAME_5: \"#05 Жен, Блондинка\"\n  STR_AVATAR_NAME_6: \"#06 Жен, Брюнетка\"\n  STR_AVATAR_NAME_7: \"#07 Жен, Азиатка\"\n  STR_AVATAR_NAME_8: \"#08 Жен, Темнокожая\"\n  STR_PSI_SHORT: \"ПСИ>{ALT}{0}/{1}\"\n  STR_EVASIVE_MANEUVERS: \"УКЛОНЕНИЕ\"\n  STR_UFO_DESTROYED_BY_SPLASHDOWN: \"НЛО РАЗБИЛСЯ ПРИ ПРИВОДНЕНИИ!\"\n  STR_UFO_SURVIVED_SPLASHDOWN: \"НЛО ПРИВОДНИЛСЯ!\"\n  STR_UFO_HAS_LANDED: \"НЛО приземлился.{NEWLINE}Место: {NEWLINE}{0}\"\n  GMGEO1: \"Трек #1 в страт. режиме\"\n  GMGEO2: \"Трек #2 в страт. режиме\"\n  GMTACTIC: \"Трек в страт. режиме\"\n  GMINTER: \"Трек перехвата\"\n  GLOBE_TEXTURE_0: \"Лес/Джунгли 1\"\n  GLOBE_TEXTURE_1: \"Сельхозугодья 1\"\n  GLOBE_TEXTURE_2: \"Сельхозугодья 2\"\n  GLOBE_TEXTURE_3: \"Сельхозугодья 3\"\n  GLOBE_TEXTURE_4: \"Сельхозугодья 4\"\n  GLOBE_TEXTURE_5: \"Горы\"\n  GLOBE_TEXTURE_6: \"Лес/Джунгли 2\"\n  GLOBE_TEXTURE_7: \"Пустыня 1\"\n  GLOBE_TEXTURE_8: \"Пустыня 2\"\n  GLOBE_TEXTURE_9: \"Заполярье 1\"\n  GLOBE_TEXTURE_10: \"Лес/Джунгли 3\"\n  GLOBE_TEXTURE_11: \"Лес/Джунгли 4\"\n  GLOBE_TEXTURE_12: \"Заполярье 2\"\n  STR_LANDED: \"Посадка\"\n  STR_SHOT_TYPE_AUTO: \"Очер. (x{0})\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/OXCE/sv.yml",
    "content": "sv:\n  STR_AVATAR_NAME_1: \"#01 Man, ljushårig\"\n  STR_AVATAR_NAME_2: \"#02 Man, brunhårig\"\n  STR_AVATAR_NAME_3: \"#03 Man, asiatisk\"\n  STR_AVATAR_NAME_4: \"#04 Man, afrikansk\"\n  STR_AVATAR_NAME_5: \"#05 Kvinna, ljushårig\"\n  STR_AVATAR_NAME_6: \"#06 Kvinna, brunhårig\"\n  STR_AVATAR_NAME_7: \"#07 Kvinna, asiatisk\"\n  STR_AVATAR_NAME_8: \"#08 Kvinna, afrikansk\"\n  STR_UFO_DESTROYED_BY_SPLASHDOWN: \"UFO FÖRSTÖRDES UNDER HAVSLANDNINGEN!\"\n  STR_UFO_SURVIVED_SPLASHDOWN: \"UFO ÖVERLEVDE HAVSLANDNINGEN!\"\n  STR_LANDED: \"Landat\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/OXCE/uk.yml",
    "content": "uk:\n  STR_FACILITY_IN_USE_STORAGE: \"СПОРУДА ВИКОРИСТОВУЄТЬСЯ!{SMALLLINE}Не вистачає місця для зберігання.\"\n  STR_FACILITY_IN_USE_QUARTERS: \"СПОРУДА ВИКОРИСТОВУЄТЬСЯ!{SMALLLINE}Недостатньо житлових приміщень.\"\n  STR_FACILITY_IN_USE_LABORATORIES: \"СПОРУДА ВИКОРИСТОВУЄТЬСЯ!{SMALLLINE}Недостатньо місця в лабораторії.\"\n  STR_FACILITY_IN_USE_WORKSHOPS: \"СПОРУДА ВИКОРИСТОВУЄТЬСЯ!{SMALLLINE}Не вистачає місця в майстерні.\"\n  STR_FACILITY_IN_USE_HANGARS: \"СПОРУДА ВИКОРИСТОВУЄТЬСЯ!{SMALLLINE}Не вистачає ангарів.\"\n  STR_FACILITY_IN_USE_PSI_LABS: \"СПОРУДА ВИКОРИСТОВУЄТЬСЯ!{SMALLLINE}Не вистачає псі-лабораторій.\"\n  STR_FACILITY_IN_USE_GYMS: \"СПОРУДА ВИКОРИСТОВУЄТЬСЯ!{SMALLLINE}Не вистачає спортзалів.\"\n  STR_FACILITY_IN_USE_PRISONS: \"СПОРУДА ВИКОРИСТОВУЄТЬСЯ!{SMALLLINE}Недостатньо захисту від прибульців.\"\n  STR_NOT_ENOUGH_HWP_CAPACITY: \"НЕ ДОСТАТНЬО МІСТКОСТІ ДЛЯ ВБП!{SMALLLINE}Використайте інший модуль або зменшіть кількість призначених ВБП.\"\n  STR_AVATAR_NAME_1: \"#01 Чоловік, Блондин\"\n  STR_AVATAR_NAME_2: \"#02 Чоловік, Брюнет\"\n  STR_AVATAR_NAME_3: \"#03 Чоловік, Азіат\"\n  STR_AVATAR_NAME_4: \"#04 Чоловік, Африканець\"\n  STR_AVATAR_NAME_5: \"#05 Жінка, Блондинка\"\n  STR_AVATAR_NAME_6: \"#06 Жінка, Брюнетка\"\n  STR_AVATAR_NAME_7: \"#07 Жінка, Азіатка\"\n  STR_AVATAR_NAME_8: \"#08 Жінка, Африканка\"\n  STR_PSI_SHORT: \"PSI>{ALT}{0}/{1}\"\n  STR_EVASIVE_MANEUVERS: \"УХИЛЬНІ МАНЕВРИ\"\n  STR_UFO_DESTROYED_BY_SPLASHDOWN: \"НЛО БУЛО ЗНИЩЕНО ПРИ ПРИВОДНЕННІ!\"\n  STR_UFO_SURVIVED_SPLASHDOWN: \"НЛО ПЕРЕЖИЛО ПРИВОДНЕННЯ!\"\n  STR_UFO_HAS_LANDED: \"НЛО приземлилося в {NEWLINE}{0}\"\n  GMGEO1: \"Трек планетарного вигляду #1\"\n  GMGEO2: \"Трек планетарного вигляду #2\"\n  GMTACTIC: \"Трек поля бою\"\n  GMINTER: \"Трек перехоплення\"\n  GLOBE_TEXTURE_0: \"Ліс/Джунглі 1\"\n  GLOBE_TEXTURE_1: \"Сільськогосподарські землі 1\"\n  GLOBE_TEXTURE_2: \"Сільськогосподарські землі 2\"\n  GLOBE_TEXTURE_3: \"Сільськогосподарські землі 3\"\n  GLOBE_TEXTURE_4: \"Сільськогосподарські землі 4\"\n  GLOBE_TEXTURE_5: \"Гори\"\n  GLOBE_TEXTURE_6: \"Ліс/Джунглі 2\"\n  GLOBE_TEXTURE_7: \"Пустеля 1\"\n  GLOBE_TEXTURE_8: \"Пустеля 2\"\n  GLOBE_TEXTURE_9: \"Сніги 1\"\n  GLOBE_TEXTURE_10: \"Ліс/Джунглі 3\"\n  GLOBE_TEXTURE_11: \"Ліс/Джунглі 4\"\n  GLOBE_TEXTURE_12: \"Сніги 2\"\n  STR_LANDED: \"Приземлився\"\n  STR_SHOT_TYPE_AUTO: \"Авто (x{0})\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/bg.yml",
    "content": "bg:\n  STR_AVENGER_UFOPEDIA: \"ТРАНСПОРТЕН И БОЕН КОСМИЧЕСКИ КОРАБ.  ПОСЛЕДНАТА ДУМА В ПРИЛОЖЕНИЕТО НА ИЗВЪНЗЕМНИ ТЕХНОЛОГИИ.\"\n  STR_INTERCEPTOR_UFOPEDIA: \"БОЕН САМОЛЕТ С ДВА ИМПУЛСНО-ВЗРИВНИ ДВИГАТЕЛЯ И СПЕЦИАЛНО ЗАЩИТЕНИ ЕЛЕКТРОННИ СИСТЕМИ.  НАЙ-ДОБРАТА НАЛИЧНА ЗЕМНА ТЕХНОЛОГИЯ.\"\n  STR_LIGHTNING_UFOPEDIA: \"ВОЕННО-ТРАНПОРТЕН И БОЕН САМОЛЕТ.  ГРУБО, НО ЕФЕКТИВНО КОПИЕ НА ИЗВЪНЗЕМНИТЕ ДВИГАТЕЛНИ СИСТЕМИ.\"\n  STR_SKYRANGER_UFOPEDIA: \"ВОЕННО-ТРАНСПОРТЕН САМОЛЕТ.  НАЙ-БЪРЗИЯТ ОТ ВИДА СИ, С ВЪЗМОЖНОСТ ЗА ВЕРТИКАЛНО ИЗЛИТАНЕ И КАЦАНЕ (В.И.И.К).\"\n  STR_FIRESTORM_UFOPEDIA: \"БОЕН САМОЛЕТ. ЕДНОМЕСТЕН ИЗТРЕБИТЕЛ КОПИРАЩ КЛАСИЧЕСКАТА ЛЕТЯЩА ЧИНИЯ, С ЕДИН ДВИГАТЕЛ В ЦЕНТЪРА.\"\n  STR_STINGRAY_UFOPEDIA: \"УСЪВЪРШЕНСТВАНА РАКЕТА \\\"ВЪЗДУХ-ВЪЗДУХ\\\" СЪС СПЕЦИАЛНО ЗАЩИТЕНА ЕЛЕКТРОНИКА.\"\n  STR_AVALANCHE_UFOPEDIA: \"РАКЕТА \\\"ВЪЗДУХ-ВЪЗДУХ\\\" С ЯДРЕНА БОЙНА ГЛАВА. СВЪХ ТЕЖКА.\"\n  STR_CANNON_UFOPEDIA: \"МОЩНО ОРЪДИЕ ИЗСТРЕЛВАЩО БРОНЕБОЙНИ СНАРЯДИ, СПОСОБНИ ДА ПРОБИЯТ 400ММ СТОМАНА.\"\n  STR_FUSION_BALL_UFOPEDIA: \"ТАЗИ УСТАНОВКА ИЗСТРЕЛВА КЪЛБОВИДНА РАКЕТА ЗАДВИЖВАНА ОТ АНТИМАТЕРИЯ.  КЪЛБОТО УНИЩОЖАВА ЦЕЛТА С ГРАВИТАЦИОННО-ВЪЛНОВА ИМПЛОЗИЯ.\"\n  STR_LASER_CANNON_UFOPEDIA: \"СТАНДАРТЕН ЛАЗЕРЕН ЛЪЧ ЗАХРАНВАН ОТ КАМЕРА С АНТИМАТЕРИЯ.\"\n  STR_PLASMA_BEAM_UFOPEDIA: \"ГРАВИТАЦИОННИЯТ ЛЪЧ НАСОЧВА ПРЕЦИЗНО КАНАЛИЗИРАНО ИМПЛОЗИВНО ГРАВИТАЦИОННО ПОЛЕ.\"\n  STR_SECTOID_UFOPEDIA: \"Сектоидната йерархия се простира от войници до лидери с мощни псионични способности.  Тези псионични сили могат да деморализират и дори обсебят умовере на войниците ни по време на битка.  Сектоидите имат склонност към отвличане на хора и осакатяване на добитък.  Отвличането се използва за извличане на генетичен материал с цел създаване на хибриди и разработката на клонинги, които да проникнат в човешкото общество.  Добитъкът осигурява питание и генетичен материал.  Изглежда тази раса иска да отгледа изключителни генетични хибриди, за да подобри ефективността на кошероподобното им общество.\"\n  STR_SECTOID_AUTOPSY: \"Аутопсия на сектоид\"\n  STR_SECTOID_AUTOPSY_UFOPEDIA: \"Аутопсията разкрива закърнели храносмилателни органи и просто устройство.  Мозъкът и очите са много добре развити.  Устройството сочи към генно модифициране или мутация.  Малките нос и уста привидно нямат значима функция.  Ципите между пръстите и плоските стъпала сочат към воден произход.  Липсват размножителни органи и не е ясно как видът се размножава.  Най-вероятно са продукт на генно инженерство.\"\n  STR_SNAKEMAN_UFOPEDIA: \"Тази раса се е развила в изключително враждебна среда.  Те са изключително издържливи и могат да понесат на ектремни температурни промени.  Пoдвижността им се осигурява от гигантски змиеподобен 'крак', който защитава всички жизненоважни органи.  Целите им изглеждат чисто хищнически и те явно са под контрола на някакъв друг интелект, който насочва техните военизирани набези на Земята.\"\n  STR_SNAKEMAN_AUTOPSY: \"Аутопсия на змиечовек\"\n  STR_SNAKEMAN_AUTOPSY_UFOPEDIA: \"Кожата е изключително здрава и устойчива на топлина.  Сърдечно-съдовата им система е част от мускулната, която работи на хидравличен принцип.  Единственият истински мускул е 'сърцето'.  Размножителната им система изглежда много ефикасна.  Размножаването е безполово, като всеки змиечовек носи до петдесет яйца в тялото си по всяко време.  Оставен без контрол този вид би бил голяма заплаха за живота на Земята.\"\n  STR_ETHEREAL_UFOPEDIA: \"Това същество има страховити умствени сили, които позволяват телепатично общуване и телекинетични способности.  Привидно слабите физически способности на съществото са поддържани от умствените му сили.  Не разбираме как работят тези телекинетични сили, тъй като на пръв поглед те противоречат на известните закони на физиката.  Тези същества са изключетлно опасни във всяка бойна ситуация, защото използват умствените си сили да се бият.  Рядко се появяват на Земята, тъй като явно използват други раси да постигнат своите цели.\"\n  STR_ETHEREAL_AUTOPSY: \"Аутопсия на ефирен\"\n  STR_ETHEREAL_AUTOPSY_UFOPEDIA: \"Физиката на това същество е закърняла и изглежда неспособна да поддържа някакви жизнени функции.  Мускулите са силно атрофирали, а вътрешните органи изглеждат недоразвити.  Сетивните органи, включително очите, изглежда въобще не работят.  Мозъкът обаче е добре развит и черпи голяма част от телесното кръвообращение.  Остава загадка как това същество може да преживява без външна помощ.\"\n  STR_MUTON_UFOPEDIA: \"Тези хуманоидни същества са интелигентни и физически силни.  Те имат особено изострен апетит към поглъщането на всякакъв вид сурова плът, която използват за препитание като земните месоядни.  Те зависят от телепатичните команди на раса известна като 'ефирните'.  Щом бъдат отделени от тази телепатична връзка, умствената им система явно се разпада и те умират.  Кибернетичните импланти служат да подобрят бойните им характеристики.  Ясно е, че те са само пешки на по-висш интелект.\"\n  STR_MUTON_AUTOPSY: \"Аутопсия на мутон\"\n  STR_MUTON_AUTOPSY_UFOPEDIA: \"Изглежда че 'кожата' на това същество всъщност е създадена по органичен път защитна броня, която е присадена върху тялото.  Има многобройни кибернетични импланти подсилващи сърдечно-съдовата система и сетивата.  Размножителни органи изглежда са били хирургически отстранени.  Явно животът на тези злочести създания е ограничен до битки и завоевания.  Бронебойните муниции не са много ефективни срещу усилената им кожа.\"\n  STR_CELATID_UFOPEDIA: \"Тази форма на живот притежава загадъчната естествена способност да се носи във въздуха.  Изглежда, че тя улавя човешките мозъчни вълни и ще се насочи към човешка цел дори и тя е добре скрита.  Щом бъде намерена цел, целатидът каца и изстрелва малки топки изключително разяждаща отрова.  Съществото е способно да се клонира с тревожна честота.  То придружава мутонската раса в нейните скитания.\"\n  STR_CELATID_AUTOPSY: \"Аутопсия на целатид\"\n  STR_CELATID_AUTOPSY_UFOPEDIA: \"Вътрешността съдържа малко биомеханично устройство, което явно е развила се по естествен път антигравитационна двигателна система.  Мехурът с отрова е най-големият орган и на пръв поглед липсва отделна мозъчна структура.  Няма отличима храносмилателна или размножителна система.  Малък орган съдържа ембриони, от които могат бързо да израстнат нови същества.\"\n  STR_SILACOID_UFOPEDIA: \"Тази силициева форма на живот поражда огромно количество топлина.  Съществото е достатъчно силно да разтрошава скали, които след това могат да бъдат погълнати от горещото ядро.  Притежава примитивен интелект и може да бъде контролирана чрез импланти или от телепатични същества.  Работи заедно с извънземната раса на мутоните.\"\n  STR_SILACOID_AUTOPSY: \"Аутопсия на силакоид\"\n  STR_SILACOID_AUTOPSY_UFOPEDIA: \"Ядрото на съществото е изключително горещо и явно е в основата на храносмилателна система.  Уникалната мускулна система притежава неимоверна бързина и сила.  Подобната на скала кожа не се наранява от огън или запалителни муниции.\"\n  STR_CHRYSSALID_UFOPEDIA: \"Ракоподобните щипки на това същество са мощно оръжие при близък бой.  Неговите високи метаболизъм и сила му придават бързина и сръчност.  Вместо да убие жертвата си, то снася в нея яйце и я инжектира с отрова която я превръща в крачещо зомби.  Нов хрисалид ще изскочи от жертвата скоро след яцеполагането.  Хрисалидите са асоциирани с расата на Змиетелите.\"\n  STR_CHRYSSALID_AUTOPSY: \"Аутопсия на хрисалид\"\n  STR_CHRYSSALID_AUTOPSY_UFOPEDIA: \"Екзоскелетът на това същество е изключително як, но и изненадващо уязвим за експлодиращи муниции.  Има добре развит мозък и много бърз клетъчен растеж.  Носи двадесет яйца, които снася в други организми.  Това същество е много ефективно оръжие за терор.\"\n  STR_FLOATER_UFOPEDIA: \"Левитаторите са главно войници и инструменти за терор. Те са хищни зверове по природа, генетично променени и кибернетично подобрени за да бъдат страховити войни.  Долната половина от тялото и повечето вътрешни органи са хирургически премахнати и заместени с животоподдържаща система.  Този имплант съдържа антигравитационна уредба която позволява на съществото да се носи, макар и нестабилно, във въздуха.\"\n  STR_FLOATER_AUTOPSY: \"Аутопсия на левитатор\"\n  STR_FLOATER_AUTOPSY_UFOPEDIA: \"Съществото е било драстично променено по хирургичен път.  Устройството което оформя сърцевината на тялото е животоподдържаща система, заместила функциите на сърце, дробове и храносмилателна система.  Това позволява на съществото да оцелява в изключително враждебна среда.  Мозъкът е по-малък от нашия, но сетивните органи са добре развити.\"\n  STR_REAPER_UFOPEDIA: \"Това двуного месоядно има мощни челюсти и неутолим апетит.  То притежава известен брой мозъчни импланти, които служат за управление на действията му.  Примитивните хищнически инстинкти на това същество не са годни за нищо друго освен за разрушения и терор.  Разкъсвачите обикновено са асоциирани с левитаторите.\"\n  STR_REAPER_AUTOPSY: \"Аутопсия на разкъсвач\"\n  STR_REAPER_AUTOPSY_UFOPEDIA: \"Разкъсвачът има два 'мозъка' и две 'сърца', което му позволява да действа дори и когато е тежко ранен.  За сметка на това покритата му с козина кожа е изключително лесно запалима, което го прави уязвим за запалителни оръжия.\"\n  STR_SECTOPOD_UFOPEDIA: \"Сектоподите са робо-същества въоръжени с мощни лазерни лъчи.  Управлението на тези механични зверове става чрез телепатична връзка с контролиращите ги Ефирни.  Сектоподите са най-мощното оръжие за терор което силите на пришълците имат под ръка.\"\n  STR_SECTOPOD_AUTOPSY: \"Аутопсия на сектопод\"\n  STR_SECTOPOD_AUTOPSY_UFOPEDIA: \"Роботът е солидно устроен, със захранвана броня която е способна да издържа на повечето видове атаки и особено на плазмени оръжия.  За сметка на това сензорните елементи изглеждат особено уязвими за лазерни лъчи.\"\n  STR_CYBERDISC_UFOPEDIA: \"Тази миниатюрна летяща чиния е автоматизирано оръжие за терор въоръжено с мощен плазмен лъч.  Антигравитационното задвижване му носи голямо предимство на труден терен.  Основната му функция е да пръска ужас и разрушение в служба на сектоидската раса.\"\n  STR_CYBERDISC_AUTOPSY: \"Аутопсия на кибердиск\"\n  STR_CYBERDISC_AUTOPSY_UFOPEDIA: \"Кибердискът е добре защитен и е особено устойчив на експлозивни муниции.  Главата антигравитационна система е твърде лошо повредена за да можем да разберем нейната работа.\"\n  STR_UFO_POWER_SOURCE_UFOPEDIA: \"Енергийният източник на извънземните кораби е реактор за антиматерия, който използва Елерий (елемент 115) за да създава мощни гравитационни вълни и други форми на енергия.  Превръщането на материя в енергия има невероятния КПД от 99%, което означава, че малки количества Елерий могат да доставят огромни мощности.  Устройството лесно може да бъде възпроизведено използвайки извъземни сплави.\"\n  STR_UFO_NAVIGATION_UFOPEDIA: \"Извънземните кораби използват сложни компютри за навигация на Земята и в космоса.  В основата на системата са оптически процесори свързани в мрежа.  Управлението е относително просто - навигаторът управлява посоката на гравитационните вълни, създавани от енергийния източник, за да насочва кораба в произволна посока.  Системата лесно може да се използва и от хора, и може да бъде възпроизведена от извънземни сплави и други елементи.\"\n  STR_UFO_CONSTRUCTION_UFOPEDIA: \"Извънземните кораби се състоят от три главни елемента - източник на енергия, навигационна система и корпус от извънземни сплави.  Корпусът е направен така, че да позволя гравитационните вълни да бъдат насочвани и контролирани.  Освен това е необходимо и малко количество Елерий да захранва източника на енергия.  Веднага щом устройството е напълно разбрано, а функциите на всеки елемент - изучени, ще е възможно създаването на летателни апарати от този тип.\"\n  STR_ALIEN_FOOD_UFOPEDIA: \"Тези капсули съдържат различни ензими, които се използват за разлагането на части от добитък, други животни и дори хора.  След това течността се консумира като вече смелена храна - вероятно директно в кръвообръщението.  Това сочи известна зависимост от Земята за храна - вид симбиоза между Земята и извънземното общество.\"\n  STR_ALIEN_REPRODUCTION_UFOPEDIA: \"Тези капсули съдържат извънземни ембриони.  Устройството на съдовете наглед сочи че извънземните използващи този процес разчитат напълно на лабораторно размножаване.  Богатите хранителни вещества осигурявт бързото развитие на ембриона.  Такава конвейерна система може да създаде за кратко време хиляди клонинги на извънцемни.  Процесът лесно може да бъде нагоден за отглеждането на хора или на кръстоски на хора с извънземни.\"\n  STR_ALIEN_ENTERTAINMENT_UFOPEDIA: \"Най-вероятната функция на тези сфери е развлекателна.  Псионичните им вериги стимулират различни центрове на мозъка.  Ефектът е сходен с този на халюциногенните наркотици.  Това е единствената улика, че извънземните имат някакви културни или развлекателни забавления.\"\n  STR_ALIEN_SURGERY_UFOPEDIA: \"Тези хирургически съоръжения използват лазерни резачи за извличането на определени части на тялото от добитък и други животни.  Тази странна извънземна дейност обяснява широко разпространените осакатявания на добитъка.  Вероятно частите се използват за хранителни или генетични цели.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"В миналото хиляди хора са твърдели, че са били отвлечени от извънземни, понякога многократно.  Истината е много по-ужасяваща.  Хора са отвичани, изучавани и наблюдавани.  От най-добрите екземпляри е извличан генетичен материал.  В жени са имплантирани ембриони на кръстоски на хора и извънземни, които са изваждани след няклоко месеца.  Кой знае що за зловещи мотиви движат пришълците?\"\n  STR_ALIEN_ALLOYS_UFOPEDIA: \"Извънземните кораби са построени от специални сплави с уникални качества.  Те са изключително леки и яки и могат да се оформят по електромагнитен път.  Можем да възпроизведем материала и да го използваме в множество производствени процеси.\"\n  STR_ELERIUM_115_UFOPEDIA: \"Този елемент има необичайно свойство - образува антиматерия когато е бомбардиран с определи частици.  Това създава гравитационни вълни и други форми на енергия.  Не се среща в природата в нашата слънчева система и не може да бъде изкуствено възпроизведен.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"Става ясно, че рано или късно ще загубим битката на Земята.  Извънземните орди имат съкрушително числено превъзходство.  Най-доброто което можем да постигнем е да забавим напредъка им.  Единствената надежда за човечеството е да ги пресечем от източника.  Нашите изследвания подсказват наличието на оперативна база наблизо в нашата Слънчева система.  Пришълци сочат това място за център на древна цивилизация която предхожда човешката история.  Трябва да открием къде е възможно най-скоро.  Но за да добием по-подробна информация трябва да пленим и разпитаме лидер на пришълците.  По-големите НЛО вероятно съдържат поне по един извънземен лидер.\"\n  STR_THE_MARTIAN_SOLUTION_UFOPEDIA: \"Научният ни труд до този момент сочи, че пришълците идва от Марс. Базата им е добре скрита и съдържа цялото им производствено и клониращо оборудване необходимо за нашествието им на земята. Също така изглежда, че има някакъв контролиращ компютър, който ръководи цялата дейност. Изглежда, че кошеро-подобното общество на пришълците има някакъв вид \\\"царица пчела\\\". Това е и основната им слабост - ако елиминираме \\\"мозъка\\\" тогава тялото ще умре. Трябва да ускорим научния труд преди да стане твърде късно. За да продължим труда трябва да пленим най-висшия ешелон от прищълците - командирите - които се намират само в техните бази и линейни кораби.\"\n  STR_CYDONIA_OR_BUST_UFOPEDIA: \"Вече е ясно, че извънземните орди са контролирани от подземна база в Кидония - необичаен район на Марс който съдържа петоъгълни пирамиди и голямо образувание, напомнящо на човешко лице.  В Кидония някога е процъфтяла марсианска цивилизация, но не знаем защо е измряла, или каква е нейната връзка със сегашната извънземна дейност там.  Каквато и да е тя, ние трябва да изпратим експедиция в Кидония.  Това е единственият начин да победим пришълците.  Трябва да унищожим контролиращият ги главен 'мозък'.  Ще ни е нужен апарат тип Отмъстител, снабден с най-страхотно разрушителните сили които имаме под ръка.  Тук не можем да научим нищо повече - ще трябва да изчакаме резултата от щурмуването на Кидония.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"ЦЕНТРИРАНЕ-ВРЕМЕ=5 сек\"\n  STR_CANCEL_UC: \"ОТКАЗ\"\n  STR_NONE: \"Няма\"\n  STR_UNKNOWN: \"Неизвестен\"\n  STR_POOR: \"Слаб\"\n  STR_AVERAGE: \"Среден\"\n  STR_GOOD: \"Добър\"\n  STR_EXCELLENT: \"Отличен\"\n  STR_BUILD_NEW_BASE_UC: \"НОВА БАЗА\"\n  STR_BASE_INFORMATION: \"ИНФОРМАЦИЯ ЗА БАЗАТА\"\n  STR_EQUIP_CRAFT: \"ЕКИПИРАНЕ НА АПАРАТИ\"\n  STR_BUILD_FACILITIES: \"СТРОЕЖ НА МОДУЛИ\"\n  STR_RESEARCH: \"ИЗСЛЕДВАНЕ\"\n  STR_MANUFACTURE: \"ИЗРАБОТКА\"\n  STR_TRANSFER_UC: \"ПРЕХВЪРЛЯНЕ\"\n  STR_PURCHASE_RECRUIT: \"КУПУВАНЕ/НАЕМАНЕ\"\n  STR_SACK: \"УВОЛНЯВАНЕ\"\n  STR_SELL_SACK_UC: \"ПРОДАВАНЕ/УВОЛНЯВАНЕ\"\n  STR_GEOSCAPE_UC: \"ГЛОБАЛНА КАРТА\"\n  STR_NAME: \"Име\"\n  STR_AREA: \"Регион\"\n  STR_BUILD_NEW_BASE: \"Build New Base\"\n  STR_CANCEL: \"Отказ\"\n  STR_COST_UC: \"ЦЕНА>\"\n  STR_CONSTRUCTION_TIME_UC: \"ВРЕМЕ ЗА СТРОЕЖ>\"\n  STR_DAY:\n    one: \"{N} ден\"\n    other: \"{N} дни\"\n  STR_HOUR:\n    one: \"{N} час\"\n    other: \"{N} часа\"\n  STR_MAINTENANCE_UC: \"ПОДДРЪЖКА>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Инсталиране\"\n  STR_CURRENT_RESEARCH: \"ТЕКУЩИ ИЗСЛЕДВАНИЯ\"\n  STR_SCIENTISTS_AVAILABLE: \"Свободни учени>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Заети учени>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Свободна лабораторна площ>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"НАУЧЕН ПРОЕКТ\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"АНГАЖИРАНИ УЧЕНИ\"\n  STR_PROGRESS: \"НАПРЕДЪК\"\n  STR_NEW_PROJECT: \"Нов проект\"\n  STR_CANCEL_PROJECT: \"СПРЕТЕ ПРОЕКТА\"\n  STR_NEW_RESEARCH_PROJECTS: \"НОВИ НАУЧНИ ПРОЕКТИ\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"СВОБОДНИ УЧЕНИ>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"СВОБОДНА ЛАБОРАТОРНА ПЛОЩ>{ALT}{0}\"\n  STR_INCREASE: \"Увеличаване\"\n  STR_DECREASE: \"Намаляване\"\n  STR_START_PROJECT: \"ЗАПОЧНЕТЕ ПРОЕКТА\"\n  STR_CURRENT_PRODUCTION: \"ТЕКУЩО ПРОИЗВОДСТВО\"\n  STR_ENGINEERS_AVAILABLE: \"Свободни инженери>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Заети инженери>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Свободна работна площ>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Текущи средства>{ALT}{0}\"\n  STR_ITEM: \"АРТИКУЛ\"\n  STR_ENGINEERS__ALLOCATED: \"Заети{NEWLINE}инженери\"\n  STR_UNITS_PRODUCED: \"Изработени{NEWLINE}изделия\"\n  STR_TOTAL_TO_PRODUCE: \"Общо за изработка\"\n  STR_COST__PER__UNIT: \"Един{NEWLINE}ична{NEWLINE}цена\"\n  STR_DAYS_HOURS_LEFT: \"Оставащи{NEWLINE}дни/часове\"\n  STR_NEW_PRODUCTION: \"Нова партида\"\n  STR_PRODUCTION_ITEMS: \"Въможни изделия\"\n  STR_CATEGORY: \"КАТЕГОРИЯ\"\n  STR_START_PRODUCTION: \"ЗАПОЧНЕТЕ ИЗРАБОТКА\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} човекочаса за изработката на една бройка\"\n  STR_COST_PER_UNIT_: \"Единична цена>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Нужна работна площ>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"ИЗИСКВАТ СЕ СПЕЦИАЛНИ МАТЕРИАЛИ\"\n  STR_ITEM_REQUIRED: \"НЕОБХОДИМИ ЕЛЕМЕНТИ\"\n  STR_UNITS_REQUIRED: \"НЕОБХОДИМО КОЛИЧЕСТВО\"\n  STR_UNITS_AVAILABLE: \"НАЛИЧНО КОЛИЧЕСТВО\"\n  STR_STOP_PRODUCTION: \"СПРЕТЕ ИЗРАБОТКА\"\n  STR_ENGINEERS_AVAILABLE_UC: \"СВОБОДНИ ИНЖЕНЕРИ>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"СВОБОДНА РАБОТНА ПЛОЩ>{ALT}{0}\"\n  STR_INCREASE_UC: \"УВЕЛИЧАВАНЕ\"\n  STR_DECREASE_UC: \"НАМАЛЯВАНЕ\"\n  STR_UNITS_TO_PRODUCE: \"Бройки за изработка\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Закупуване/Наемане на персонал\"\n  STR_COST_OF_PURCHASES: \"Цена на покупките>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"ЕДИНИЧНА ЦЕНА\"\n  STR_QUANTITY_UC: \"КОЛИЧ-ВО\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"СВОБОДЕН ПЕРСОНАЛ:ОБЩО ПЕРСОНАЛ>\"\n  STR_SOLDIERS: \"Войници\"\n  STR_SCIENTISTS: \"Учени\"\n  STR_ENGINEERS: \"Инженери\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"ИЗПОЛЗВАНА ПЛОЩ:ОБЩА ПЛОЩ>\"\n  STR_LIVING_QUARTERS: \"Жилища\"\n  STR_STORES: \"Запаси\"\n  STR_LABORATORIES: \"Лаборатории\"\n  STR_WORK_SHOPS: \"Работилници\"\n  STR_HANGARS: \"Хангари\"\n  STR_SHORT_RANGE_DETECTION: \"Локатори (близо)\"\n  STR_DEFENSE_STRENGTH: \"Сила на защитата\"\n  STR_TRANSFERS_UC: \"ПРИСТИГАЩИ\"\n  STR_TRANSFERS: \"Пристигащи\"\n  STR_ARRIVAL_TIME_HOURS: \"Пристигане след (часа)\"\n  STR_COST_: \"Цена>{ALT}{0}\"\n  STR_AREA_: \"Регион>{ALT}{0}\"\n  STR_BASE_NAME: \"Име на базата?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"ИЗБЕРЕТЕ МЯСТО ЗА ВХОДНАТА ШАХТА\"\n  STR_TRANSFER: \"Прехвърляне\"\n  STR_AMOUNT_TO_TRANSFER: \"ИЗПРАЩАНО{NEWLINE}КОЛИЧ-ВО\"\n  STR_SELECT_DESTINATION_BASE: \"Прехвърляне в коя база?\"\n  STR_COST: \"Цена\"\n  STR_VICTORY_1: \"Влизайки в камерата виждате извънземният мозък - целта на задачата ви. Преди да откриете огън той се обръща към вас чрез екран в основата си. Той ви умолява да изслушате доводите му за оцеляване преди да решите да дръпнете спусъка...\"\n  STR_VICTORY_2: \"Мозъкът проговаря: 'Преди милиони години планетата, която наричате Марс, беше жива.  Животът бе донесен на тази пуста планета от нашата цивилизация, както и на вашата.  Милиони години посещавахме вашата планета и развивахме генетично вашият вид.  Не можете да ни убиете, вие сте част от нас...\"\n  STR_VICTORY_3: \"Тук е центърът на марсианската цивилизация - пирамидите, построени милиони години преди вашите - от вид, който е ваш прародител. Няма планета извън обхвата ни. Тази мощ скоро може да е ваша. Искаме само вашето съдействие...\"\n  STR_GAME_OVER_1: \"Пришълците се опитват да изтребят цялото човечество, унищожават цели градове и отравят въздуха и морето.  Съпротивата на земните армии е напразна срещу неимоверното им технологично превъзходство.  Оцелелите поколения страдат от ужасни мутации бягайки от извънземното опустошение.  Те са затваряни в робски лагери, за да помогнат с превръщането на Земята в извънземна колония, част от някаква незнайна империя.\"\n  STR_VICTORY_4: \"Извънземният мозък бива прекъснат от кълбо гореща плазма. Извънземните сили са напълно победени.\"\n  STR_YOU_HAVE_FAILED: \"Не успявате да спрете настъплението на пришълците.  Една по една финансиращите нации сключват споразумения с пришълци обещаващи технология, мир и просперитет.  Обаче скоро става ясно, че извънземните имат съвсем други намерения...\"\n  STR_TOTAL_UC: \"ОБЩО\"\n  STR_INCOME: \"Приходи\"\n  STR_EXPENDITURE: \"Разходи\"\n  STR_MAINTENANCE: \"Поддръжка\"\n  STR_BALANCE: \"Салдо\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"Активност на НЛО по региони\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"Активност на НЛО по страни\"\n  STR_FINANCE: \"Финанси\"\n  STR_DATE_FIRST: \"{0}ви\"\n  STR_DATE_SECOND: \"{0}ри\"\n  STR_DATE_THIRD: \"{0}ти\"\n  STR_DATE_FOURTH: \"{0}и\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Няма достатъчно специални материали за изработката на{NEWLINE}{0}{NEWLINE}в{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Няма достатъчно средства за изработката на{NEWLINE}{0}{NEWLINE}в{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"Изработката на{NEWLINE}{0}{NEWLINE}в{NEWLINE}{1}{NEWLINE}приключи\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"Построяването на{NEWLINE}{0}{NEWLINE}в{NEWLINE}{1}{NEWLINE}приключи\"\n  STR_OK_5_SECONDS: \"ОК - 5 сек\"\n  STR_RESEARCH_COMPLETED: \"Завършихме изследване\"\n  STR_VIEW_REPORTS: \"РЕЗУЛТАТИ\"\n  STR_WE_CAN_NOW_RESEARCH: \"Вече можем да проучим\"\n  STR_WE_CAN_NOW_PRODUCE: \"Вече можем да изработваме\"\n  STR_SUNDAY: \"НЕДЕЛЯ\"\n  STR_MONDAY: \"ПОНЕДЕЛНИК\"\n  STR_TUESDAY: \"ВТОРНИК\"\n  STR_WEDNESDAY: \"СРЯДА\"\n  STR_THURSDAY: \"ЧЕТВЪРТЪК\"\n  STR_FRIDAY: \"ПЕТЪК\"\n  STR_SATURDAY: \"СЪБОТА\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Недостатъчно {0} да презаредим {1} в {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Недостатъчно {0} да въоръжим {1} в {2}\"\n  STR_UFO_IS_NOT_RECOVERED: \"Неуспешно разчистване на НЛО\"\n  STR_UFO_IS_RECOVERED: \"Успешно разчистване на НЛО\"\n  STR_CRAFT_IS_LOST: \"Загубен е летателен апарат\"\n  STR_TERROR_CONTINUES: \"Терорът продължава\"\n  STR_ALIENS_DEFEATED: \"Пришълци претърпяват поражение\"\n  STR_BASE_IS_LOST: \"Загубена е база\"\n  STR_BASE_IS_SAVED: \"Спасена е база\"\n  STR_ALIEN_BASE_STILL_INTACT: \"База на пришълците оцелява\"\n  STR_ALIEN_BASE_DESTROYED: \"База на пришълците е разрушена\"\n  STR_ALIENS_KILLED: \"УБИТИ ИЗВЪНЗЕМНИ\"\n  STR_ALIEN_CORPSES_RECOVERED: \"ПРИБРАНИ ИЗВЪНЗЕМНИ ТРУПОВЕ\"\n  STR_LIVE_ALIENS_RECOVERED: \"ПРИБРАНИ ЖИВИ ИЗВЪНЗЕМНИ\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"ПРИБРАНИ ИЗВЪНЗЕМНИ АРТЕФАКТИ\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"УНИЩОЖЕН КОНТРОЛЕН ЦЕНТЪР\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"ЦИВИЛНИ УБИТИ ОТ ИЗВЪНЗЕМНИ\"\n  STR_CIVILIANS_SAVED: \"СПАСЕНИ ЦИВИЛНИ\"\n  STR_TANKS_DESTROYED: \"РАЗРУШЕНИ ТАНКОВЕ\"\n  STR_UFO_RECOVERY: \"ПРИБРАНО ОТ НЛО\"\n  STR_ALIEN_BASE_RECOVERY: \"ПРИБРАНО ОТ БАЗАТА\"\n  STR_BASE_UNDER_ATTACK: \"Нападение над {0}!\"\n  STR_BASE_DEFENSES_INITIATED: \"ЗАДЕЙСТВА СЕ ЗАЩИТАТА НА БАЗАТА\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"ГРАВ-ЩИТ ОТХВЪРЛЯ НЛО!\"\n  STR_HIT: \"ПОПАДЕНИЕ!\"\n  STR_UFO_DESTROYED: \"НЛО СЕ ВЗРИВИ!\"\n  STR_MISSED: \"НЕ УЛУЧИ!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Продажба/Уволняване на персонал\"\n  STR_VALUE_OF_SALES: \"СТОЙНОСТ НА ПРОДАЖБИТЕ> {ALT}{0}\"\n  STR_FUNDS: \"СРЕДСТВА> {ALT}{0}\"\n  STR_SELL_SACK: \"Прод./Увол.\"\n  STR_VALUE: \"Стойност\"\n  STR_CRAFT_: \"АПАРАТ> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"РАЗЧИСТВАНЕ НА КАТАСТРОФА\"\n  STR_UFO_GROUND_ASSAULT: \"ЩУРМУВАНЕ НА НЛО\"\n  STR_BASE_DEFENSE: \"ОТБРАНА НА БАЗА\"\n  STR_BASE_UC_: \"БАЗА> {0}\"\n  STR_ALIEN_BASE_ASSAULT: \"ЩУРМУВАНЕ НА БАЗА\"\n  STR_CYDONIA_BRIEFING: \"След пристигането ви в Кидония проникнахте в голям подземен комплекс близо до марсианския Сфинкс.  Трябва да унищожите извънземния Мозък който управлява цялата дейност на пришълците.  Съдбата на човечеството е във вашите ръце....\"\n  STR_TERROR_MISSION: \"ПРЕКРАТЯВАНЕ НА ТЕРОР\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"НЯМА СВОБОДНИ ХАНГАРИ ЗА ИЗРАБОТКА НА АПАРАТИ!{SMALLLINE}Нужен е по един хангар за всеки летателен апарат зачислен към база, прехвърлян във база, пристигащ след закупуване или в процес на изработка.  Постройте нов хангар или прехвърлете апарат в друга база.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"НЯМА СВОБОДНИ ХАНГАРИ ЗА ЗАКУПУВАНЕ НА АПАРАТИ!{SMALLLINE}Нужен е по един хангар за всеки летателен апарат зачислен към база, прехвърлян във база, пристигащ след закупуване или в процес на изработка.  Постройте нов хангар или прехвърлете апарат в друга база.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"НЯМА СВОБОДНИ ХАНГАРИ ЗА ПРЕХВЪРЛЯНЕ!{SMALLLINE}Нужен е по един хангар за всеки летателен апарат зачислен към база, прехвърлян във база, пристигащ след закупуване или в процес на изработка.  Постройте нов хангар или прехвърлете апарат в друга база.\"\n  STR_CANNOT_BUILD_HERE: \"ИНСТАЛАЦИЯТА НЕВЪЗМОЖНА!{SMALLLINE}Можете да строите само непосредствено до съществуващ базов модул.\"\n  STR_NO_FREE_ACCOMODATION: \"НЯМА СВОБОДНИ ЖИЛИЩА!{SMALLLINE}В жилищните помещения на целевата база няма достатъчно място.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"НЕ ДОСТИГА РАБОТНА ПЛОЩ!{SMALLLINE}Простоете нова работилница или намалете работата по други проекти.\"\n  STR_NOT_ENOUGH_MONEY: \"НЕ ДОСТИГАТ СРЕДСТВА!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"НЕ ДОСТИГА СКЛАДОВА ПЛОЩ!{SMALLLINE}Построете още складови помещения или прехвърлете наличните запаси в други бази.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"НЕ ДОСТИГА ЖИЛИЩНА ПЛОЩ!{SMALLLINE}Построете още жилищни помещения или прехвърлете личен състав в други бази.\"\n  STR_LAUNCH_INTERCEPTION: \"ИЗПРАЩАНЕ НА ПРЕХВАЩАЧИ\"\n  STR_CRAFT: \"ЛЕТАТЕЛЕН АПАРАТ\"\n  STR_STATUS: \"СЪСТОЯНИЕ\"\n  STR_BASE: \"БАЗА\"\n  STR_READY: \"ГОТОВНОСТ\"\n  STR_OUT: \"В ПОЛЕТ\"\n  STR_REPAIRS: \"ПОПРАВКИ\"\n  STR_REFUELLING: \"ПРЕЗАРЕЖДАНЕ\"\n  STR_REARMING: \"ВЪОРЪЖАВАНЕ\"\n  STR_TARGET: \"ЦЕЛ: {0}\"\n  STR_WAY_POINT: \"УСЛОВНА ТОЧКА\"\n  STR_ARE_YOU_SURE_CYDONIA: \"Наистина ли ще изпратим този апарат на операция в Кидония?\"\n  STR_YES: \"ДА\"\n  STR_NO: \"НЕ\"\n  STR_SELECT_DESTINATION: \"ИЗБОР НА ЦЕЛ\"\n  STR_CYDONIA: \"КИДОНИЯ\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"ИЗБЕРЕТЕ МЯСТО ЗА НОВА БАЗА\"\n  STR_RETURN_TO_BASE: \"ЗАВРЪЩАНЕ В БАЗАТА\"\n  STR_SELECT_NEW_TARGET: \"ИЗБОР НА НОВА ЦЕЛ\"\n  STR_PATROL: \"ПАТРУЛИРАНЕ\"\n  STR_STATUS_: \"СЪСТОЯНИЕ>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"ЗАВРЪЩА СЕ - ПОВРЕДИ\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"ЗАВРЪЩА СЕ - МАЛКО ГОРИВО\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"КРАЙ НА МИСИЯТА - ЗАВРЪЩА СЕ\"\n  STR_PATROLLING: \"ПАТРУЛИРА\"\n  STR_TAILING_UFO: \"СЛЕДВА НЛО\"\n  STR_INTERCEPTING_UFO: \"ПРЕХВАЩА НЛО-{0}\"\n  STR_RETURNING_TO_BASE: \"ЗАВРЪЩА СЕ В БАЗАТА\"\n  STR_DESTINATION_UC_: \"ЦЕЛ: {0}\"\n  STR_BASE_UC: \"БАЗА>{ALT}{0}\"\n  STR_SPEED_: \"СКОРОСТ>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"МАКСИМАЛНА СКОРОСТ>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"ВИСОЧИНА>{ALT}{0}\"\n  STR_VERY_LOW: \"МНОГО НИСКО\"\n  STR_LOW_UC: \"НИСКО\"\n  STR_HIGH_UC: \"ВИСОКО\"\n  STR_VERY_HIGH: \"МНОГО ВИСОКО\"\n  STR_FUEL: \"ГОРИВО>{ALT}{0}\"\n  STR_WEAPON_ONE: \"ОРЪЖИЕ-1>{ALT}{0}\"\n  STR_NONE_UC: \"НЯМА\"\n  STR_ROUNDS_: \"МУНИЦИИ>{ALT}{0}\"\n  STR_WEAPON_TWO: \"ОРЪЖИЕ-2>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"ЛЕТАТЕЛНИ АПАРАТИ\"\n  STR_BASE_: \"База>{0}\"\n  STR_NAME_UC: \"ИМЕ\"\n  STR_AMMO_: \"МУНИЦИИ>{ALT}{0}\"\n  STR_CREW: \"ЕКИПАЖ\"\n  STR_EQUIPMENT_UC: \"СНАРЯЖЕНИЕ\"\n  STR_ARMOR: \"БРОНЯ\"\n  STR_MAX: \"МАКС>{ALT}{0}\"\n  STR_ROOKIE: \"Новобранец\"\n  STR_SQUADDIE: \"Ветеран\"\n  STR_SERGEANT: \"Сержант\"\n  STR_CAPTAIN: \"Капитан\"\n  STR_COLONEL: \"Полковник\"\n  STR_COMMANDER: \"Командир\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Екипаж на {0}\"\n  STR_SPACE_AVAILABLE: \"СВОБОДНИ МЕСТА>{ALT}{0}\"\n  STR_SPACE_USED: \"ЗАЕТИ МЕСТА>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"ЗАЕТА ПЛОЩ\"\n  STR_RANK: \"РАНГ\"\n  STR_WOUNDED: \"ЛЕКУВА СЕ\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Снаряжение в {0}\"\n  STR_DEFENSE_VALUE: \"Защитна стойност\"\n  STR_HIT_RATIO: \"Вероятност за попадение\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}в готовност за{NEWLINE}приземяване до{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"Започване на операция?\"\n  STR_SELECT_ARMAMENT: \"Избор на въоръжение\"\n  STR_AMMUNITION_AVAILABLE: \"НАЛИЧНИ МУНИЦИИ\"\n  STR_ARMAMENT: \"ВЪОРЪЖЕНИЕ\"\n  STR_NOT_AVAILABLE: \"НЯМА\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"ИЗБОР НА БРОНЯ ЗА{NEWLINE}{0}\"\n  STR_TYPE: \"ВИД\"\n  STR_PERSONAL_ARMOR_UC: \"ЛИЧНА БРОНЯ\"\n  STR_POWER_SUIT_UC: \"СИЛОВА БРОНЯ\"\n  STR_FLYING_SUIT_UC: \"ЛЕТЯЩА БРОНЯ\"\n  STR_SELECT_ARMOR: \"Избор на броня\"\n  STR_NORTH: \"СЕВЕР\"\n  STR_NORTH_EAST: \"СЕВЕРОИЗТОК\"\n  STR_EAST: \"ИЗТОК\"\n  STR_SOUTH_EAST: \"ЮГОИЗТОК\"\n  STR_SOUTH: \"ЮГ\"\n  STR_SOUTH_WEST: \"ЮГОЗАПАД\"\n  STR_WEST: \"ЗАПАД\"\n  STR_NORTH_WEST: \"СЕВЕРОЗАПАД\"\n  STR_SELECT_ACTION: \"ИЗБЕРИ ДЕЙСТВИЕ\"\n  STR_VERY_LARGE: \"МНОГО ГОЛЯМ\"\n  STR_LARGE: \"ГОЛЯМ\"\n  STR_MEDIUM_UC: \"СРЕДЕН\"\n  STR_SMALL: \"МАЛЪК\"\n  STR_VERY_SMALL: \"МНОГО МАЛЪК\"\n  STR_GROUNDED: \"НА ЗЕМЯТА\"\n  STR_DETECTED: \"Засечено\"\n  STR_SIZE_UC: \"РАЗМЕР\"\n  STR_ALTITUDE: \"ВИСОЧИНА\"\n  STR_HEADING: \"НАПРАВЛЕНИЕ\"\n  STR_SPEED: \"СКОРОСТ\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"ЦЕНТРИРАНЕ-ВРЕМЕ=5 сек\"\n  STR_TRACKING_LOST: \"ЗАГУБЕН БЕ КОНТАКТ\"\n  STR_REDIRECT_CRAFT: \"ПРЕНАСОЧВАНЕ\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"КЪМ ПОСЛЕДНАТА ПОЗИЦИЯ НА НЛО\"\n  STR_UFO_: \"НЛО-{0}\"\n  STR_ALIEN_BASE_: \"ИЗВЪНЗЕМНА БАЗА-{0}\"\n  STR_CRASH_SITE_: \"РАЗБИВАНЕ-{0}\"\n  STR_LANDING_SITE_: \"ПРИЗЕМЯВАНЕ-{0}\"\n  STR_WAY_POINT_: \"УСЛОВНА ТОЧКА-{0}\"\n  STR_TERROR_SITE: \"ТЕРОР-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}достигна{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"и в момента патрулира\"\n  STR_ALIEN_ORIGINS: \"Произход на пришълците\"\n  STR_THE_MARTIAN_SOLUTION: \"Марсианското решение\"\n  STR_CYDONIA_OR_BUST: \"Кидония или смърт\"\n  STR_UFOPAEDIA: \"НЛОпедия\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"САМОХОДНИ ОРЪЖЕЙНИ ПЛАТФОРМИ\"\n  STR_WEAPONS_AND_EQUIPMENT: \"ОРЪЖИЯ И СНАРЯЖЕНИЕ\"\n  STR_ALIEN_ARTIFACTS: \"ИЗВЪНЗЕМНИ АРТЕФАКТИ\"\n  STR_BASE_FACILITIES: \"НАЗЕМНИ СЪОРЪЖЕНИЯ\"\n  STR_ALIEN_LIFE_FORMS: \"ИЗВЪНЗЕМНИ ФОРМИ НА ЖИВОТ\"\n  STR_ALIEN_RESEARCH_UC: \"ИЗСЛЕДВАНИЯ ВЪРХУ ПРИШЪЛЦИТЕ\"\n  STR_UFO_COMPONENTS: \"ЧАСТИ НА НЛО\"\n  STR_UFOS: \"ВИДОВЕ НЛО\"\n  STR_SELECT_ITEM: \"ИЗБЕРЕТЕ ТЕМА\"\n  STR_ACCELERATION: \"УСКОРЕНИЕ>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"ГОРИВЕН ЗАПАС>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"ОРЪЖЕЙНИ ГНЕЗДА>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"ПОНЕСИМИ ПОРАЖЕНИЯ>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"ТОВАРЕН КАПАЦИТЕТ>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"МЕСТА ЗА СОП>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Поражения\"\n  STR_RANGE: \"Обсег\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Точност\"\n  STR_RE_LOAD_TIME: \"Презарежда за\"\n  STR_SECONDS: \"{0}s\"\n  STR_DAMAGE_ARMOR_PIERCING: \"БРОНЕБОЕН\"\n  STR_DAMAGE_INCENDIARY: \"ЗАПАЛИТЕЛЕН\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"ЕКСПЛОЗИВЕН\"\n  STR_DAMAGE_LASER_BEAM: \"ЛАЗЕРЕН\"\n  STR_DAMAGE_PLASMA_BEAM: \"ПЛАЗМЕН\"\n  STR_DAMAGE_STUN: \"ЗАШЕМЕТЯВАЩ\"\n  STR_DAMAGE_MELEE: \"МЕХАНИЧЕН\"\n  STR_DAMAGE_ACID: \"КИСЕЛИНЕН\"\n  STR_DAMAGE_SMOKE: \"ДИМ\"\n  STR_SHOT_TYPE: \"ВИД ИЗСТРЕЛ\"\n  STR_ACCURACY_UC: \"ТОЧНОСТ\"\n  STR_TIME_UNIT_COST: \"НУЖНИ ТД\"\n  STR_DAMAGE_UC: \"ЕФЕКТ\"\n  STR_AMMO: \"МУНИЦИИ\"\n  STR_SHOT_TYPE_AUTO: \"Откос\"\n  STR_SHOT_TYPE_SNAP: \"Припрян\"\n  STR_SHOT_TYPE_AIMED: \"Прицелен\"\n  STR_CONSTRUCTION_TIME: \"Време за построяване\"\n  STR_CONSTRUCTION_COST: \"Цена за построяване\"\n  STR_MAINTENANCE_COST: \"Цена за поддръжка\"\n  STR_CRAFT_WEAPON: \"Авиационно оръжие\"\n  STR_CRAFT_AMMUNITION: \"Авиационни боеприпаси\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Самоходна огнева платформа\"\n  STR_WEAPON: \"Оръжие\"\n  STR_AMMUNITION: \"Боеприпаси\"\n  STR_EQUIPMENT: \"Снаряжение\"\n  STR_ALIEN_CORPSE: \"Труп на извънземно\"\n  STR_UFO_COMPONENT: \"Елемент на НЛО\"\n  STR_PERSONAL_ARMOR: \"Лична броня\"\n  STR_RAW_MATERIALS: \"Суровини\"\n  STR_HWP_CANNON_SHELLS: \"Снаряди за СОП\"\n  STR_ALIEN: \"Извънземно\"\n  STR_SECTOID: \"Сектоид\"\n  STR_SNAKEMAN: \"Змиетел\"\n  STR_ETHEREAL: \"Ефирен\"\n  STR_MUTON: \"Мутон\"\n  STR_FLOATER: \"Левитатор\"\n  STR_CELATID: \"Целатид\"\n  STR_SILACOID: \"Силакоид\"\n  STR_CHRYSSALID: \"Хрисалид\"\n  STR_ZOMBIE: \"Зомби\"\n  STR_REAPER: \"Разкъсвач\"\n  STR_SECTOPOD: \"Сектопод\"\n  STR_CYBERDISC: \"Кибердиск\"\n  STR_LIVE_COMMANDER: \"Командир\"\n  STR_LIVE_LEADER: \"Лидер\"\n  STR_LIVE_ENGINEER: \"Инженер\"\n  STR_LIVE_MEDIC: \"Медик\"\n  STR_LIVE_NAVIGATOR: \"Навигатор\"\n  STR_LIVE_SOLDIER: \"Войник\"\n  STR_LIVE_TERRORIST: \"Терорист\"\n  STR_FLOATER_SOLDIER: \"Левитаторски войник\"\n  STR_FLOATER_NAVIGATOR: \"Левитаторски навигатор\"\n  STR_FLOATER_MEDIC: \"Левитаторски медик\"\n  STR_FLOATER_ENGINEER: \"Левитаторски инженер\"\n  STR_FLOATER_LEADER: \"Левитаторски лидер\"\n  STR_FLOATER_COMMANDER: \"Левитаторски командир\"\n  STR_SECTOID_SOLDIER: \"Сектоидски войник\"\n  STR_SECTOID_NAVIGATOR: \"Сектоидски навигатор\"\n  STR_SECTOID_MEDIC: \"Сектоидски медик\"\n  STR_SECTOID_ENGINEER: \"Сектоидски инженер\"\n  STR_SECTOID_LEADER: \"Сектоидски лидер\"\n  STR_SECTOID_COMMANDER: \"Сектоидски командир\"\n  STR_SNAKEMAN_SOLDIER: \"Змиетелски войник\"\n  STR_SNAKEMAN_NAVIGATOR: \"Змиетелски навигатор\"\n  STR_SNAKEMAN_ENGINEER: \"Змиетелски инженер\"\n  STR_SNAKEMAN_LEADER: \"Змиетелски лидер\"\n  STR_SNAKEMAN_COMMANDER: \"Змиетелски командир\"\n  STR_MUTON_SOLDIER: \"Мутонски войник\"\n  STR_MUTON_NAVIGATOR: \"Мутонски навигатор\"\n  STR_MUTON_ENGINEER: \"Мутонски инженер\"\n  STR_ETHEREAL_SOLDIER: \"Ефирен войник\"\n  STR_ETHEREAL_LEADER: \"Ефирен лидер\"\n  STR_ETHEREAL_COMMANDER: \"Ефирен командир\"\n  STR_CYBERDISC_TERRORIST: \"Кибердиск-терорист\"\n  STR_REAPER_TERRORIST: \"Разкъсвач-терорист\"\n  STR_CHRYSSALID_TERRORIST: \"Хрисалид-терорист\"\n  STR_CELATID_TERRORIST: \"Целатид-терорист\"\n  STR_SILACOID_TERRORIST: \"Силакоид-терорист\"\n  STR_SECTOPOD_TERRORIST: \"Сектопод Terrorist\"\n  STR_UFO_POWER_SOURCE: \"Енергиен източник\"\n  STR_UFO_NAVIGATION: \"Навигационна конзола\"\n  STR_UFO_CONSTRUCTION: \"Устройство на НЛО\"\n  STR_ALIEN_FOOD: \"Извънземна храна\"\n  STR_ALIEN_REPRODUCTION: \"Извънземен инкубатор\"\n  STR_ALIEN_ENTERTAINMENT: \"Извънземни забавления\"\n  STR_ALIEN_SURGERY: \"Извънземна операционна\"\n  STR_EXAMINATION_ROOM: \"Операционна маса\"\n  STR_ALIEN_ALLOYS: \"Извънземни сплави\"\n  STR_ALIEN_HABITAT: \"Извънземен биотоп\"\n  STR_POWER_SUIT: \"Силова броня\"\n  STR_FLYING_SUIT: \"Летяща броня\"\n  STR_HWP_ROCKETS: \"Ракети за СОП\"\n  STR_HWP_FUSION_BOMB: \"Синтезна бомба за СОП\"\n  STR_LASER_WEAPONS: \"Лазерни оръжия\"\n  STR_NEW_FIGHTER_CRAFT: \"Нов изтребител\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Нов изтребител/транспорт\"\n  STR_ULTIMATE_CRAFT: \"Върховен апарат\"\n  STR_LASER_PISTOL: \"Лазерен пистолет\"\n  STR_LASER_RIFLE: \"Лазерна карабина\"\n  STR_HEAVY_LASER: \"Тежък лазер\"\n  STR_LASER_CANNON: \"Лазерно оръдие\"\n  STR_PLASMA_CANNON: \"Плазмено оръдие\"\n  STR_FUSION_MISSILE: \"Синтезна ракета\"\n  STR_LASER_DEFENSE: \"Отбрана с лазери\"\n  STR_PLASMA_DEFENSE: \"Отбрана с плазма\"\n  STR_FUSION_DEFENSE: \"Отбрана със синтезни кълба\"\n  STR_GRAV_SHIELD: \"Грав-щит\"\n  STR_MIND_SHIELD: \"Пси-щит\"\n  STR_PSI_LAB: \"Псионична лаборатория\"\n  STR_MOTION_SCANNER: \"Локатор\"\n  STR_MEDI_KIT: \"Аптечка\"\n  STR_TANK_CANNON: \"Танк/Оръдие\"\n  STR_TANK_ROCKET_LAUNCHER: \"Танк/Ракети\"\n  STR_TANK_LASER_CANNON: \"Танк/Лазер\"\n  STR_HOVERTANK_PLASMA: \"Ховъртанк/Плазма\"\n  STR_HOVERTANK_LAUNCHER: \"Ховъртанк/Бомбомет\"\n  STR_STINGRAY_LAUNCHER: \"Установка \\\"Стършел\\\"\"\n  STR_AVALANCHE_LAUNCHER: \"Установка \\\"Лавина\\\"\"\n  STR_CANNON: \"Оръдие\"\n  STR_FUSION_BALL_LAUNCHER: \"Синтезен кълбомет\"\n  STR_PLASMA_BEAM: \"Плазмен лъч\"\n  STR_STINGRAY_MISSILES: \"Ракети \\\"Стършел\\\"\"\n  STR_AVALANCHE_MISSILES: \"Ракети \\\"Лавина\\\"\"\n  STR_CANNON_ROUNDS_X50: \"Авиационни снаряди(x50)\"\n  STR_FUSION_BALL: \"Синтезно кълбо\"\n  STR_SOLDIER: \"Войник\"\n  STR_SCIENTIST: \"Учен\"\n  STR_ENGINEER: \"Инженер\"\n  STR_NORTH_AMERICA: \"Северна Америка\"\n  STR_ARCTIC: \"Арктика\"\n  STR_ANTARCTICA: \"Антарктика\"\n  STR_SOUTH_AMERICA: \"Южна Америка\"\n  STR_EUROPE: \"Европа\"\n  STR_NORTH_AFRICA: \"Северна Африка\"\n  STR_SOUTHERN_AFRICA: \"Южна Африка\"\n  STR_CENTRAL_ASIA: \"Централна Азия\"\n  STR_SOUTH_EAST_ASIA: \"Югоизточна Азия\"\n  STR_SIBERIA: \"Сибир\"\n  STR_AUSTRALASIA: \"Австралазия\"\n  STR_PACIFIC: \"Тихи океан\"\n  STR_NORTH_ATLANTIC: \"Северен Атлантик\"\n  STR_SOUTH_ATLANTIC: \"Южен Атлантик\"\n  STR_INDIAN_OCEAN: \"Индийски океан\"\n  STR_ALIEN_RESEARCH: \"Изследователска дейност\"\n  STR_ALIEN_HARVEST: \"Прибиране на реколтата\"\n  STR_ALIEN_ABDUCTION: \"Отвличане на хора\"\n  STR_ALIEN_INFILTRATION: \"Внедряване на пришълци\"\n  STR_ALIEN_BASE: \"Строеж на база\"\n  STR_ALIEN_TERROR: \"Тероризиране\"\n  STR_ALIEN_RETALIATION: \"Ответни мерки\"\n  STR_ALIEN_SUPPLY: \"Снабдяване\"\n  STR_MAXIMUM_SPEED: \"Максимална скорост\"\n  STR_HYPER_WAVE_DECODER_UC: \"ХИПЕРВЪЛНОВ ПРИЕМНИК\"\n  STR_SKYRANGER: \"СКИТАЛЕЦ\"\n  STR_LIGHTNING: \"МЪЛНИЯ\"\n  STR_AVENGER: \"ОТМЪСТИТЕЛ\"\n  STR_INTERCEPTOR: \"ПРЕХВАЩАЧ\"\n  STR_FIRESTORM: \"БУРЯ\"\n  STR_UFO: \"НЛО\"\n  STR_STINGRAY: \"СТЪРШЕЛ\"\n  STR_AVALANCHE: \"ЛАВИНА\"\n  STR_CANNON_UC: \"ОРЪДИЕ\"\n  STR_FUSION_BALL_UC: \"КЪЛБОМЕТ\"\n  STR_LASER_CANNON_UC: \"ЛАЗЕРНО ОРЪДИЕ\"\n  STR_PLASMA_BEAM_UC: \"ПЛАЗМЕН ЛЪЧ\"\n  STR_DAMAGE_CAPACITY: \"Понесими поражения\"\n  STR_WEAPON_POWER: \"Огнева мощ\"\n  STR_WEAPON_RANGE: \"Оръжеен обсег\"\n  STR_ACCESS_LIFT: \"Входна шахта\"\n  STR_LABORATORY: \"Лаборатория\"\n  STR_WORKSHOP: \"Работилница\"\n  STR_SMALL_RADAR_SYSTEM: \"Малък радар\"\n  STR_LARGE_RADAR_SYSTEM: \"Мощен радар\"\n  STR_MISSILE_DEFENSES: \"Ракетна батарея\"\n  STR_GENERAL_STORES: \"Складово помещение\"\n  STR_ALIEN_CONTAINMENT: \"Изолационна\"\n  STR_LASER_DEFENSES: \"Лазерна батарея\"\n  STR_PLASMA_DEFENSES: \"Плазмена батарея\"\n  STR_FUSION_BALL_DEFENSES: \"Синтезна батарея\"\n  STR_PSIONIC_LABORATORY: \"Псионична лаборатория\"\n  STR_HYPER_WAVE_DECODER: \"Хипервълнов приемник\"\n  STR_HANGAR: \"Хангар\"\n  STR_USA: \"САЩ\"\n  STR_RUSSIA: \"РУСИЯ\"\n  STR_UK: \"ВЕЛИКОБРИТАНИЯ\"\n  STR_FRANCE: \"ФРАНЦИЯ\"\n  STR_GERMANY: \"ГЕРМАНИЯ\"\n  STR_ITALY: \"ИТАЛИЯ\"\n  STR_SPAIN: \"ИСПАНИЯ\"\n  STR_CHINA: \"КИТАЙ\"\n  STR_JAPAN: \"ЯПОНИЯ\"\n  STR_INDIA: \"ИНДИЯ\"\n  STR_BRAZIL: \"БРАЗИЛИЯ\"\n  STR_AUSTRALIA: \"АВСТРАЛИЯ\"\n  STR_NIGERIA: \"НИГЕРИЯ\"\n  STR_SOUTH_AFRICA: \"ЮАР\"\n  STR_EGYPT: \"ЕГИПЕТ\"\n  STR_CANADA: \"КАНАДА\"\n  STR_TANK: \"Танк\"\n  STR_CIVILIAN: \"Цивилно лице\"\n  STR_JAN: \"яну\"\n  STR_FEB: \"фев\"\n  STR_MAR: \"мар\"\n  STR_APR: \"апр\"\n  STR_MAY: \"май\"\n  STR_JUN: \"юни\"\n  STR_JUL: \"юли\"\n  STR_AUG: \"авг\"\n  STR_SEP: \"сеп\"\n  STR_OCT: \"окт\"\n  STR_NOV: \"ное\"\n  STR_DEC: \"дек\"\n  STR_INTERNATIONAL_RELATIONS: \"МЕЖДУНАРОДНИ ОТНОШЕНИЯ\"\n  STR_COUNTRY: \"Страна\"\n  STR_FUNDING: \"Финансиране\"\n  STR_CHANGE: \"Промяна\"\n  STR_WEAPON_SYSTEMS: \"ОРЪЖЕЙНИ СИСТЕМИ\"\n  STR_HWPS: \"СОПи\"\n  STR_DAMAGE_UC_: \"ПОВРЕДИ>{ALT}{0}\"\n  STR_ACCESS_LIFT_UFOPEDIA: \"Входната шахта позволява вкарването и изкарването на припаси и персонал от подземна база.  Това е първият модул, който се строи в нова база.  Шахтата е точка уязвима към нахлуване от потенциална враждебна сила.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Всеки жилищен модул поддържа до 50 жители.  Съоръжението предлага помещения за сън, хранене и почивка.\"\n  STR_LABORATORY_UFOPEDIA: \"До 50 учени могат да работят в един лабораторен модул.  Лабораториите са снабдени с последните технологии за материални, биохимични и космологични изследвания.  Осигурен е достъп с предимство до най-добрите изследователски лаборатории по света, включително и военни такива.\"\n  STR_WORKSHOP_UFOPEDIA: \"Една работилница съдържа всички инструменти необходими за изработката на изделията проектирани в научинте лаборатории.  До 50 инженери могат да работят в една работилница, но и изработваните изделия също заемат известно място.\"\n  STR_MISSILE_DEFENSES_UFOPEDIA: \"Ракетната батарея осигурява известна защита срещу набези на враждебни летателни апарати опитващи се да кацнат близо до базата.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"Цялата екипировка, оръжейни системи, муниции, прибран материал и Самоходни оръжейни платформи се държат в складовите помещения, включително и оборудването зачислено към летателни апарати в хангарите.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"Живите извънземни вероятно ще изискват специална среда която да поддържа биологичните им процеси.  Изолационната може да държи до 10 извънземни форми на живот в самостоятелни помещения.\"\n  STR_LASER_DEFENSES_UFOPEDIA: \"Лазерната батарея осигурява защита срещу нахлуването на враждебни летателни апарати.\"\n  STR_PLASMA_DEFENSES_UFOPEDIA: \"Плазмената батарея осигурява мощна и ефективна защита срещу нахлуване на враждебни летателни апарати.\"\n  STR_FUSION_BALL_DEFENSES_UFOPEDIA: \"Синтезните ракети осигуряват най-ефективната защита срещу извънземни атаки.  Те създават имплозия на анти-материя която унищожава всичко в определен радиус.\"\n  STR_GRAV_SHIELD_UFOPEDIA: \"Гравитационният щит отблъсква извънземните кораби, опитващи се да кацнат близо до базата, позволявайки на всички защитни установки да стрелят още веднъж.  На практика това удвоява ефективността на защитните системи на базата.\"\n  STR_MIND_SHIELD_UFOPEDIA: \"Тъй като летателните апарати на пришълците разчитат на мозъчни вълни да усещат присъствието на хора, най-ефективното противодействие е екранирането на мозъчните вълни от базата.  Това съоръжение драстично ще намали шансовете базата да бъде засечена от извънземни апарати.\"\n  STR_PSIONIC_LABORATORY_UFOPEDIA: \"Псионичната лаборатория е способна да оценява псионичния потенциал на войниците в базата и да им дава необходимата подготовка да използват своите псионични умения.  Всяка лаборатория може да подготвя до десет войника.  Подготовката се задава в края на всеки месец.  Псионичните умения в комбинация с пси-усилвател могат да се използват за псионични атаки по време на бой.\"\n  STR_HYPER_WAVE_DECODER_UFOPEDIA: \"Комуникациите на пришълците използват над-пространствена вълна, която се движи почти мигновено.  Декодиращото съоръжение прехваща предавания от НЛО и разшифрова информацията.  Тя показва вида НЛО, извънземната раса и вида извънземна дейност.\"\n  STR_RIFLE_UFOPEDIA: \"Високоточна 6.7mm автоматична карабина с лазерен мерник, използваща пълнители от 20 патрона.\"\n  STR_HEAVY_CANNON_UFOPEDIA: \"Ръчното оръдие е унищожително, но тежко оръжие.  Неговата универсалност е в това, че може да използва три вида муниции - бронебойни, запалителни и експлоадиращи.\"\n  STR_AUTO_CANNON_UFOPEDIA: \"Авто-оръдието съчетава многостранната мощ на ръчното оръдие с по-голяма скорост на стрелба.\"\n  STR_ROCKET_LAUNCHER_UFOPEDIA: \"Ракетохвъргачката използва лазерна система за насочване и може да изстрелва три различни вида ракети.\"\n  STR_LASER_PISTOL_UFOPEDIA: \"Лазерният пистолет е сполучливо въплъщение на новите технологии.  Съчетава удобството на пистолет с по-бърза и по-точна стрелба.\"\n  STR_LASER_RIFLE_UFOPEDIA: \"Лазерната карабина е по-мощна и по-точна версия на по-раншния пистолетен проект.\"\n  STR_HEAVY_LASER_UFOPEDIA: \"Тежкият лазер е тромав, но изключително ефективен.\"\n  STR_GRENADE_UFOPEDIA: \"Стандартна граната с точен и усложнен забавител за прецизен контрол.\"\n  STR_SMOKE_GRENADE_UFOPEDIA: \"Димните гранати са полезни за осигуряване на прикритие при бой на открит терен.  Използвайте ги внимателно, защото ефектът им може да бъде благоприятен и за противника.\"\n  STR_PROXIMITY_GRENADE_UFOPEDIA: \"Минната граната се хвърля като обикновена граната, но след приземяването си се задейства от близки движения.  Правилната употреба на тези устройства изисква много умение и внимание.\"\n  STR_HIGH_EXPLOSIVE_UFOPEDIA: \"Този експлозивен заряд трябва да се използва само за разрушителни работи.  Дръжте личния състав далеч от центъра на експлозията.\"\n  STR_MOTION_SCANNER_UFOPEDIA: \"Сложно устройство което използва набор от сензори и усъвършенствани компютърни алгоритми да засича движещи се вражески единици. Въпреки това ефективната му употреба изисква практика. Щракнете на иконата на локатора на тактическия дисплей. Изберете 'Сканиране' от менюто.  Дисплеят на детектора показва стрелка в центъра, която сочи посоката накъдето е обърнат войника (север е нагоре). Мигащите петна показват единици, които са мърдали наскоро. По-големи или по-бързи единици образуват по-големи петна. Неподвижните единици не се показват.\"\n  STR_MEDI_KIT_UFOPEDIA: \"Аптечката комбинира диагностично-превързочно устройство с аналгетици и стимуланти. Използващият войник трябва да е обърнат към пациента, а ако пациентът е в безсъзнание, трябва да е застанал над тялото.  Щракнете на иконата на аптечката и изберете 'Преглед' от менюто.{NEWLINE}ПРЕВРЪЗКА> В червено са частите на тялото със смъртоносни рани. Щракнете на някоя ранена част. Щракнете на бутона 'Превръзка'. Раната ще бъде излекувана, а част от здравето - възстановена.{NEWLINE}СТИМУЛАНТ> Възстановява енергия и съживява войници в безсъзнание. За да освестите зашеметен войник трябва да стоите точно над тялото.{NEWLINE}АНАЛГЕТИК> Възстановява бойния дух на ранени войници, най-много с толкова, колкото е загубеното Здраве.\"\n  STR_PSI_AMP_UFOPEDIA: \"Пси-усилвателят може да бъде използван само от войници с псионични умения. По време на бой, щракнете на пси-усилвателя, изберете вида атака и след това изберете цел с показалеца. Има два вида псионични атаки:{NEWLINE}ПАНИКА> Ако атаката е успешна, тя ще смъкне бойния дух на целта и може да я накара да изпадне в паника.{NEWLINE}ОБСЕБВАНЕ> Ако е успешно, ще получите незабавно контрол над вражеската единица сякаш е една от вашите собствени. Този вид атака по-трудно завършва с успех.\"\n  STR_STUN_ROD_UFOPEDIA: \"Това устройство е приложимо само в близък бой, но може да зашеметява живи организми без да ги убива, с помощта на електрически шокове.\"\n  STR_PLASMA_PISTOL_UFOPEDIA: \"Плазмените пистолети са смъртоносно извънземно оръжие, основаващо се на ускоряване на частици в миниатюрно антигравитационно поле.\"\n  STR_PLASMA_RIFLE_UFOPEDIA: \"Това е съкрушително мощно оръжие, основаващо се на ускоряване на частици в миниатюрно антигравитационно поле.\"\n  STR_HEAVY_PLASMA_UFOPEDIA: \"Това е съкрушително мощно оръжие, основаващо се на ускоряване на частици в миниатюрно антигравитационно поле.\"\n  STR_BLASTER_LAUNCHER_UFOPEDIA: \"Това е извънземна бомбохвъргачка за управляеми снаряди, която изстрелва мощни 'супербомби'. Когато щраквате за да стреляте с оръжието, това ще създава 'пътни точки' описващи пътя на супербомбата.  Щом разположите достатъчно точки, щракнете на специална икона за изстрелване.\"\n  STR_SMALL_LAUNCHER_UFOPEDIA: \"Малък бомбомет, изстрелващ зашеметяващи бомбички.  Много полезен за залавяне на живи извънземни.\"\n  STR_ALIEN_GRENADE_UFOPEDIA: \"Това устройство работи по същия начин като земните гранати - с изключение на това, че е по-мощно.\"\n  STR_SMALL_SCOUT: \"Малък разузнавач\"\n  STR_MEDIUM_SCOUT: \"Среден разузнавач\"\n  STR_LARGE_SCOUT: \"Голям разузнавач\"\n  STR_HARVESTER: \"Събирач\"\n  STR_ABDUCTOR: \"Похитител\"\n  STR_TERROR_SHIP: \"Тероризатор\"\n  STR_BATTLESHIP: \"Боен кораб\"\n  STR_SUPPLY_SHIP: \"Снабдител\"\n  STR_RATING: \"ОЦЕНКА> {0}\"\n  STR_RATING_TERRIBLE: \"УЖАСНА!\"\n  STR_RATING_POOR: \"ЛОША!\"\n  STR_RATING_OK: \"БИВА\"\n  STR_RATING_GOOD: \"ДОБРА!\"\n  STR_RATING_EXCELLENT: \"ОТЛИЧНА!\"\n  STR_SCORE: \"ТОЧКИ\"\n  STR_MONTH: \"Месец> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"Съветът на финансиращите нации засега намира нашия напредък за задоволителен.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"Съветът на финансиращите нации е много доволен от нашия отличен напредък. Нека продължаваме в същия дух.\"\n  STR_COUNCIL_IS_DISSATISFIED: \"Съветът на финансиращите нации е недоволен от работата ни.  Необходимо е да подобрим ефективността си в справянето с извънземната заплаха, или рискуваме прекратяване на проекта.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"Не успяхме да се справим с извънземното нашествие и съветът на финансиращите нации за съжаление реши да прекрати проекта.  Всяка нация ще решава сама за себе си какво да прави с проблема.  Можем само да се надяваме, че ще можем да постигнем някакво разбирателство с тези очевидно враждебни сили и че населението ще се примири с извънземните посетители.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"Управниците на {0} са особено доволни от способността ни да се справяме с локализираната заплаха и са съгласни да увеличат отпусканите от тях средства.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} са особено щастливи от напредъка ни в борбата с местните набези на пришълците и са съгласни да увеличат отпусканите от тях средства.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} и {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"Управниците на {0} са недоволни от способността ни да се справяме с извънземната дейност на тяхна територия и са решили да намалят финансовия си принос.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} са недоволни от способността ни да се справяме с извънземна дейност на тяхна територия и са решили да намалят отпусканите от тях средства.\"\n  STR_KNOTS: \"{0} взл.\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"Управниците на {0} са сключили тайно споразумение с неизвестни извънземни сили и се изтеглят от проекта.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} са подписали тайно споразумение с неизвестни извънземни сили и се изтеглят от проекта.\"\n  STR_MONTHLY_RATING: \"Месечна оценка> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Промяна във финансирането> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"Съветът на донорите е недоволен от финансовото ни състояние.  Трябва да намалим дълговете си под $1 милион или проектът ще бъде закрит.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"РАЗШИФРОВАНИ СА ХИПЕРВЪЛНОВИ ПРЕДАВАНИЯ\"\n  STR_CRAFT_TYPE: \"ТИП КОРАБ\"\n  STR_RACE: \"ВИД\"\n  STR_MISSION: \"МИСИЯ\"\n  STR_ZONE: \"РЕГИОН\"\n  STR_ALLOCATE_RESEARCH: \"Задаване на изследвания\"\n  STR_ALLOCATE_MANUFACTURE: \"Задаване на изработка\"\n  STR_NEW_YORK: \"Ню Йорк\"\n  STR_WASHINGTON: \"Вашингтон\"\n  STR_LOS_ANGELES: \"Лос Анджелис\"\n  STR_MONTREAL: \"Монреал\"\n  STR_HAVANA: \"Хавана\"\n  STR_MEXICO_CITY: \"Мексико\"\n  STR_CHICAGO: \"Чикаго\"\n  STR_VANCOUVER: \"Ванкувър\"\n  STR_DALLAS: \"Далас\"\n  STR_BRASILIA: \"Бразилия\"\n  STR_BOGOTA: \"Богота\"\n  STR_BUENOS_AIRES: \"Буенос Айрес\"\n  STR_SANTIAGO: \"Сантяго\"\n  STR_RIO_DE_JANEIRO: \"Рио де Жанейро\"\n  STR_LIMA: \"Лима\"\n  STR_CARACAS: \"Каракас\"\n  STR_LONDON: \"Лондон\"\n  STR_PARIS: \"Париж\"\n  STR_BERLIN: \"Берлин\"\n  STR_MOSCOW: \"Москва\"\n  STR_ROME: \"Рим\"\n  STR_MADRID: \"Мадрид\"\n  STR_BUDAPEST: \"Будапеща\"\n  STR_LAGOS: \"Лагос\"\n  STR_CAIRO: \"Кайро\"\n  STR_CASABLANCA: \"Казабланка\"\n  STR_PRETORIA: \"Претория\"\n  STR_NAIROBI: \"Найроби\"\n  STR_CAPE_TOWN: \"Кейптаун\"\n  STR_KINSHASA: \"Киншаса\"\n  STR_ANKARA: \"Анкара\"\n  STR_DELHI: \"Делхи\"\n  STR_KARACHI: \"Карачи\"\n  STR_BAGHDAD: \"Багдад\"\n  STR_TEHRAN: \"Техеран\"\n  STR_BOMBAY: \"Бомбай\"\n  STR_CALCUTTA: \"Калкута\"\n  STR_TOKYO: \"Токио\"\n  STR_BEIJING: \"Бейджин\"\n  STR_BANGKOK: \"Банкок\"\n  STR_MANILA: \"Манила\"\n  STR_SEOUL: \"Сеул\"\n  STR_SINGAPORE: \"Сингапур\"\n  STR_JAKARTA: \"Джакарта\"\n  STR_SHANGHAI: \"Шанхай\"\n  STR_HONG_KONG: \"Хонконг\"\n  STR_NOVOSIBIRSK: \"Новосибирск\"\n  STR_CANBERRA: \"Канбера\"\n  STR_WELLINGTON: \"Уелингтън\"\n  STR_MELBOURNE: \"Мелбърн\"\n  STR_PERTH: \"Пърт\"\n  STR_PSIONIC_TRAINING: \"ПСИОНИЧНА ПОДГОТОВКА\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Оставащи свободни места> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"Псионична{NEWLINE}сила\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"Псионично умение{NEWLINE}/Подобрение\"\n  STR_PSI_AMP: \"Пси-усилвател\"\n  STR_IN_TRAINING: \"За{NEWLINE}обучение?\"\n  STR_TARGETTED_BY: \"В МОМЕНТА ЦЕЛ НА:\"\n  STR_WEAPONS_CREW_HWPS: \"ОРЪЖИЯ/{NEWLINE}ЕКИПАЖ/СОПи\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"привършва горивото,{NEWLINE}завръща се в базата\"\n  STR_SOLDIER_LIST: \"Списък на бойците\"\n  STR_RANK_: \"РАНГ> {ALT}{0}\"\n  STR_MISSIONS: \"ОПЕРАЦИИ> {ALT}{0}\"\n  STR_KILLS: \"УБИТИ> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"ИЗЛЕКУВАНЕ СЛЕД> {ALT}{0}\"\n  STR_TIME_UNITS: \"ТОЧКИ ЗА ДЕЙСТВИЕ\"\n  STR_STAMINA: \"ИЗДЪРЖЛИВОСТ\"\n  STR_HEALTH: \"ЗДРАВЕ\"\n  STR_BRAVERY: \"СМЕЛОСТ\"\n  STR_REACTIONS: \"РЕАКЦИИ\"\n  STR_FIRING_ACCURACY: \"ТОЧНОСТ НА СТРЕЛБА\"\n  STR_THROWING_ACCURACY: \"ТОЧНОСТ НА ХВЪРЛЯНЕ\"\n  STR_STRENGTH: \"ФИЗИЧЕСКА СИЛА\"\n  STR_PSIONIC_STRENGTH: \"ПСИОНИЧНА СИЛА\"\n  STR_PSIONIC_SKILL: \"ПСИОНИЧНО УМЕНИЕ\"\n  STR_NEW_RANK: \"НОВ РАНГ\"\n  STR_PROMOTIONS: \"Повишения\"\n  STR_SOLDIERS_UC: \"ВОЙНИЦИ\"\n  STR_TANK_ROCKET_LAUNCHER_UFOPEDIA: \"Тази автоматизирана самоходна оръжейна платформа е въоръжена с мощни ракети.  Това ще бъде съкрушително за всеки извънземен враг.  Погрижете се складовете да поддържат в наличност ракети за СОП.\"\n  STR_TANK_LASER_CANNON_UFOPEDIA: \"Лазерните оръжия са полезно допълнение към СОПи.  Съчетават голяма огнева мощ с неограничен брой изстрели.\"\n  STR_HOVERTANK_PLASMA_UFOPEDIA: \"Извънземната технология даде нов живот на СОП.  Допълнителната маневреност на левитацията и огневата мощ на плазмените лъчи образуват смъртоносно съчетание.\"\n  STR_HOVERTANK_LAUNCHER_UFOPEDIA: \"Този ховъртанк има синтезен кълбомет с огромна разрушителна сила.  Използвайте го много внимателно.  Ще трябва да произвеждате синтезните бомби нужни за въоръжаването на тези СОПи.  Синтезната бомба е интелигентно насочвано оръжие.  За стрелба е нужно да поставите няколко 'междинни точки' с курсора и след това да щракнете на иконата за изстрелване.\"\n  STR_HEAVY_PLASMA_CLIP_UFOPEDIA: \"Това компактно устройство служи за муниции на тежко плазмено оръжие.  Съдържа малко количество Елерий.\"\n  STR_PLASMA_RIFLE_CLIP_UFOPEDIA: \"Този малък предмет служи за източник на захранване на плазмена пушка - средно по мощност извънземно оръжие. Съдържа малко количество Елерий.\"\n  STR_PLASMA_PISTOL_CLIP_UFOPEDIA: \"Енергиен източник за малкия извънземен плазмен пистолет.  Съдържа Елерий, източникът на цялата извънземна мощ.\"\n  STR_STUN_BOMB_UFOPEDIA: \"Зашеметяващата бомбичка се използва за заляването на живи човешки образци, но може да бъде употребявана и срещу повечето извънземни видове. Изстрелва се с Малък бомбомет.\"\n  STR_ALIEN_HARVEST_UFOPEDIA: \"Пришълците намират множество приложения за земната фауна.  Отвличат се животни и се връщат с премахнати органи.  Съобщенията за осакатявания на добитък обикновено съпътстват тези за НЛО.  Този вид извънземна дейност причинява голяма загриженост у управляващите и значителна тревога сред населението.  Това се прави предимно на земеделска земя.  Хипотезата за 'събиране на реколтата' предполага, че извънземни раси първоначално са 'засели' планетата с нейната флора и фауна и сега се завръщат да пожънат засятата от тях реколта.\"\n  STR_ALIEN_ABDUCTION_UFOPEDIA: \"Това е най-подлата форма на извънземна дейност.  Отвличането от пришълци бива широко огласено, независимо от опитите на пришълците да изтрият преживяното от умовете на жертвите си.  Отвлечените съобщават, че са били обект на унизителни медицински манипулации, включително присаждането на извънземни ембриони и странни генетични експерименти.  Намеренията зад тази дейност изглежда са свързани с генетична мутация и манипулация на собствения генетичен материал на пришълците.  Тази дейност е причина за голяма тревога и става в градове или населени райони.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"След като една база на пришълците е завършена, тя бива снабдявана редовно от специален снабдителен съд.  Ако един от тези съдове е засечен да каца, със сигурност наблизо има база на пришълците.\"\n  STR_SMALL_SCOUT_UFOPEDIA: \"Този миниатюрен апарат се използва главно за разузнаване или проучвания.  Обикновено предшества по-големи съдове в началото на извънземна операция.\"\n  STR_MEDIUM_SCOUT_UFOPEDIA: \"Средноголям разузнавателен съд който не представлява заплаха за земните сили.  Обикновено се появява преди по-големи съдове по време на операция.\"\n  STR_LARGE_SCOUT_UFOPEDIA: \"Най-големият разузнавателен апарат на пришълците е универсален съд който се използва във всички видове техни операции.\"\n  STR_HARVESTER_UFOPEDIA: \"Събирачът има люк в основата си и е снабден с подемна техника за вдигането на добитък или други животни.  Лазерни резачки извличат търсения материал и трупът се изхвърля на земята.  Носи и контейнери за съхраняване на органи.\"\n  STR_ABDUCTOR_UFOPEDIA: \"Този съд е снабден с операционна зала за извършването на ужасяващи експерименти върху човешки обекти.  Обикновено жертвата бива парализирана с телепатични сили, но остава в съзнание върху операционната маса.\"\n  STR_TERROR_SHIP_UFOPEDIA: \"Тероризаторският кораб е пригоден за пренасянето на големи извънземни същества или оръжия за терор.  Използва се за доставянето на тези терористични единици в населени райони.\"\n  STR_BATTLESHIP_UFOPEDIA: \"Бойният кораб е най-големият и най-могъщ апарат на пришълците.  Обикновено е главният апарат в дадена тяхна операция и е снабден с мощни оръжия и многоброен екипаж.\"\n  STR_SUPPLY_SHIP_UFOPEDIA: \"Снабдителният съд се използва по време на строежа на бази на пришълците или за снабдяването на съществуващи такива.  Носи контейнери с извънземна храна и камери за размножаване.\"\n  STR_DISMANTLE: \"Демонтиране на\"\n  STR_FACILITY_IN_USE: \"МОДУЛЪТ СЕ ИЗПОЛЗВА\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"ДЕМОНТИРАНЕТО Е НЕВЪЗМОЖНО!{SMALLLINE}Всички модули на базата трябва да бъдат свързани с входната шахта.\"\n  STR_TRANSFER_ITEMS_TO: \"Изпращане в {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"НЯМА МЯСТО В ИЗОЛАЦИОННА ЗА ПРЕХВЪРЛЯНЕ!{SMALLLINE}Заловените живи извънземни се нуждаят от изолационен модул за да оцелеят.\"\n  STR_AMOUNT_AT_DESTINATION: \"КОЛИЧ-ВО{NEWLINE}ТАМ\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"Извънземното умира, тъй като липсва изолационна за извънземни\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"НЯМА СВОБОДНИ ЖИЛИЩА!{SMALLLINE}В жилищните помещения на целевата база няма достатъчно място за екипажа зачислен на апарата.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"НЕ ДОСТИГА СКЛАДОВА ПЛОЩ!{SMALLLINE}В складовите помещения на целевата база няма достатъчно място за снаряжението зачислено към апарата.\"\n  STR_ITEMS_ARRIVING: \"Получена пратка\"\n  STR_DESTINATION_UC: \"ЦЕЛ\"\n  STR_PISTOL: \"Пистолет\"\n  STR_PISTOL_CLIP: \"Пълнител за пистолет\"\n  STR_RIFLE: \"Карабина\"\n  STR_RIFLE_CLIP: \"Пълнител за карабина\"\n  STR_HEAVY_CANNON: \"Ръчно оръдие\"\n  STR_HC_AP_AMMO: \"РО-ББ муниции\"\n  STR_HC_HE_AMMO: \"РО-ЕК муниции\"\n  STR_HC_I_AMMO: \"РО-ЗА муниции\"\n  STR_AUTO_CANNON: \"Авто-оръдие\"\n  STR_AC_AP_AMMO: \"АО-ББ муниции\"\n  STR_AC_HE_AMMO: \"АО-ЕК муниции\"\n  STR_AC_I_AMMO: \"АО-ЗА муниции\"\n  STR_ROCKET_LAUNCHER: \"Ракетохвъргачка\"\n  STR_SMALL_ROCKET: \"Малка ракета\"\n  STR_LARGE_ROCKET: \"Голяма ракета\"\n  STR_INCENDIARY_ROCKET: \"Запалителна ракета\"\n  STR_GRENADE: \"Граната\"\n  STR_SMOKE_GRENADE: \"Димна граната\"\n  STR_PROXIMITY_GRENADE: \"Минна граната\"\n  STR_HIGH_EXPLOSIVE: \"Експлозиви\"\n  STR_STUN_ROD: \"Шоков прът\"\n  STR_HEAVY_PLASMA: \"Тежка плазма\"\n  STR_HEAVY_PLASMA_CLIP: \"Пълнител за тежка плазма\"\n  STR_PLASMA_RIFLE: \"Плазмена пушка\"\n  STR_PLASMA_RIFLE_CLIP: \"Пълнител за плазмена пушка\"\n  STR_PLASMA_PISTOL: \"Плазмен пистолет\"\n  STR_PLASMA_PISTOL_CLIP: \"Пълнител за плазмен пистолет\"\n  STR_BLASTER_LAUNCHER: \"Тежък бомбомет\"\n  STR_BLASTER_BOMB: \"Супербомба\"\n  STR_SMALL_LAUNCHER: \"Малък бомбомет\"\n  STR_STUN_BOMB: \"Зашеметяваща бомба\"\n  STR_ALIEN_GRENADE: \"Извънземна граната\"\n  STR_ELERIUM_115: \"Елерий-115\"\n  STR_MIND_PROBE: \"Психосонда\"\n  STR_SECTOID_CORPSE: \"Труп на сектоид\"\n  STR_SNAKEMAN_CORPSE: \"Труп на змиетел\"\n  STR_ETHEREAL_CORPSE: \"Труп на ефирен\"\n  STR_MUTON_CORPSE: \"Труп на мутон\"\n  STR_FLOATER_CORPSE: \"Труп на левитатор\"\n  STR_CELATID_CORPSE: \"Труп на целатид\"\n  STR_SILACOID_CORPSE: \"Труп на силакоид\"\n  STR_CHRYSSALID_CORPSE: \"Труп на хрисалид\"\n  STR_REAPER_CORPSE: \"Труп на разкъсвач\"\n  STR_SECTOPOD_CORPSE: \"Останки от сектопод\"\n  STR_CYBERDISC_CORPSE: \"Останки от кибердиск\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Недостиг за пълно снаряжаване на отряда\"\n  STR_MARS_CYDONIA_LANDING: \"Марс: Кацане в Кидония\"\n  STR_MARS_CYDONIA_LANDING_BRIEFING: \"Вашият Отмъстител се приземи в местността Кидония на повърхността на Марс.  Източниците ни сочат, че в една от пирамидалните постройки има зелен подемник който води към подземен комплекс.  Щом съберете всичките си бойци в зоната на подемника, натиснете иконата 'прекратяване на операцията' за да започнете следващия етап.\"\n  STR_MARS_THE_FINAL_ASSAULT: \"Марс: Последният щурм\"\n  STR_MARS_THE_FINAL_ASSAULT_BRIEFING: \"Подемникът на пирамидата отвежда вашите уморени от боя войници дълбоко под повърхността на планетата, в сърцето на голям комплекс от камери и тунели.  Извънземният мозък е скрит някъде в този лабиринт.  За да не бъде Земята поробена от пришълците, той трябва да бъде унищожен.{NEWLINE}{NEWLINE}Късмет!\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Ще трябва да проучим{NEWLINE}{0}{NEWLINE}за да можем да изработваме{NEWLINE}{1}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"Незащитаваната база {0} бе унищожена от пришълците\"\n  STR_STANDOFF: \"НАБЛЮДЕНИЕ\"\n  STR_CAUTIOUS_ATTACK: \"ПРЕДПАЗЛИВА АТАКА\"\n  STR_STANDARD_ATTACK: \"СТАНДАРТНА АТАКА\"\n  STR_AGGRESSIVE_ATTACK: \"АГРЕСИВНА АТАКА\"\n  STR_DISENGAGING: \"ОТТЕГЛЯНЕ\"\n  STR_UFO_HIT: \"ПОПАДЕНИЕ В НЛО!\"\n  STR_UFO_CRASH_LANDS: \"НЛО СЕ РАЗБИ!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Смаляване само при наблюдение\"\n  STR_UFO_RETURN_FIRE: \"НЛО ОТВРЪЩА НА ОГЪНЯ!\"\n  STR_INTERCEPTOR_DAMAGED: \">>> ПРЕХВАЩАЧЪТ БЕ ПОВРЕДЕН <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> ПРЕХВАЩАЧЪТ БЕ УНИЩОЖЕН <<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"НЛО БЯГА ОТ ПРЕХВАЩАЧА!\"\n  STR_ALIENS_TERRORISE: \"ИЗВЪНЗЕМНИ ТЕРОРИЗИРАТ\"\n  STR_LONG_RANGE_DETECTION: \"Локатори (далеч)\"\n  STR_STORES_UC: \"ЗАПАСИ\"\n  STR_DIFFICULTY_LEVEL: \"Ниво на трудност\"\n  STR_INTERCEPT: \"ПРЕХВАЩАНЕ\"\n  STR_BASES: \"БАЗИ\"\n  STR_GRAPHS: \"СТАТИСТИКА\"\n  STR_UFOPAEDIA_UC: \"НЛОПЕДИЯ\"\n  STR_OPTIONS_UC: \"НАСТРОЙКИ\"\n  STR_FUNDING_UC: \"ФИНАНСИРАНЕ\"\n  STR_5_SECONDS: \"5 сек\"\n  STR_1_MINUTE: \"1 мин\"\n  STR_5_MINUTES: \"5 мин\"\n  STR_30_MINUTES: \"30 мин\"\n  STR_1_HOUR: \"1 час\"\n  STR_1_DAY: \"1 ден\"\n  STR_ENTER_NAME: \"Въведи име\"\n  STR_VICTORY_DATE: \"Дата на победата\"\n  STR_ELECTRO_FLARE: \"Електро-святка\"\n  STR_ELECTRO_FLARE_UFOPEDIA: \"Това компактно устройство започва да излъчва ярка светлина след като бъде хвърлено.  Така по време на нощни операции оказалите се близо до него вражески единици ще бъдат осветени.\"\n  STR_MONTHLY_COSTS: \"Месечни разходи\"\n  STR_CRAFT_RENTAL: \"Наем за летателни апарати\"\n  STR_SALARIES: \"Заплати\"\n  STR_BASE_MAINTENANCE: \"Поддръжка на базата\"\n  STR_COST_PER_UNIT: \"Единична цена\"\n  STR_QUANTITY: \"Количество\"\n  STR_TOTAL: \"Общо\"\n  STR_IN_PSIONIC_TRAINING: \"Участва в псионична подготовка\"\n  STR_BLASTER_BOMB_UFOPEDIA: \"Това устройство представлява експлозивен снаряд с интелигентна система за насочване.  Изстрелва се с тежък бомбомет.\"\n  STR_FRONT_ARMOR: \"Защита отпред\"\n  STR_LEFT_ARMOR: \"Защита отляво\"\n  STR_RIGHT_ARMOR: \"Защита отдясно\"\n  STR_REAR_ARMOR: \"Защита отзад\"\n  STR_UNDER_ARMOR: \"Защита отдолу\"\n  STR_ROUNDS: \"Изстрели\"\n  STR_UNIT: \"ЕДИНИЦА> {0}\"\n  STR_ENERGY: \"ЕНЕРГИЯ\"\n  STR_MORALE: \"БОЕН ДУХ\"\n  STR_ARMOR_: \"БРОНЯ> {0}\"\n  STR_FRONT_ARMOR_UC: \"ЗАЩИТА ОТПРЕД\"\n  STR_LEFT_ARMOR_UC: \"ЗАЩИТА ОТЛЯВО\"\n  STR_RIGHT_ARMOR_UC: \"ЗАЩИТА ОТДЯСНО\"\n  STR_REAR_ARMOR_UC: \"ЗАЩИТА ОТЗАД\"\n  STR_SKILLS: \"УМЕНИЯ> {0}\"\n  STR_LEVEL: \"НИВО> {0}\"\n  STR_HEAD: \"ГЛАВА\"\n  STR_TORSO: \"ТОРС\"\n  STR_RIGHT_ARM: \"ДЯСНА РЪКА\"\n  STR_LEFT_ARM: \"ЛЯВА РЪКА\"\n  STR_RIGHT_LEG: \"ДЕСЕН КРАК\"\n  STR_LEFT_LEG: \"ЛЯВ КРАК\"\n  STR_PAIN_KILLER: \"АНАЛГЕТИК\"\n  STR_STIMULANT: \"СТИМУЛАНТ\"\n  STR_HEAL: \"ПРЕВРЪЗКА\"\n  STR_TIME_UNITS_SHORT: \"ТД>{ALT}{0}\"\n  STR_WEIGHT: \"Тегло>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"Реакц>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"П.умен>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"П.сил>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Извънземен артефакт\"\n  STR_AMMO_ROUNDS_LEFT: \"МУНИЦИИ:{NEWLINE}ОСТАВАТ={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Аналг>{ALT}{0}{ALT}{NEWLINE}Стим>{ALT}{1}{ALT}{NEWLINE}Превр>{ALT}{2}\"\n  STR_THROW: \"Хвърляне\"\n  STR_AUTO_SHOT: \"Откос\"\n  STR_SNAP_SHOT: \"Припрян\"\n  STR_AIMED_SHOT: \"Прицелен\"\n  STR_STUN: \"Зашеметяване\"\n  STR_PRIME_GRENADE: \"Задействане\"\n  STR_USE_SCANNER: \"Сканиране\"\n  STR_USE_MEDI_KIT: \"Преглед\"\n  STR_LAUNCH_MISSILE: \"Изстрелване\"\n  STR_ACCURACY_SHORT: \"Точ>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Не достигат точки за действие!\"\n  STR_NOT_ENOUGH_ENERGY: \"Не достига енергия!\"\n  STR_NO_ROUNDS_LEFT: \"Няма повече муниции!\"\n  STR_NO_AMMUNITION_LOADED: \"Оръжието не е заредено!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Неподходящи муниции за това оръжие!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"Оръжието вече е заредено!\"\n  STR_NO_LINE_OF_FIRE: \"Няма видимост към целта!\"\n  STR_GRENADE_IS_ACTIVATED: \"Гранатата е задействана!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Гранатата е обезвредена!\"\n  STR_THERE_IS_NO_ONE_THERE: \"Няма никой тук!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Извънземният артефакт не е проучен!\"\n  STR_OUT_OF_RANGE: \"Извън обсег!\"\n  STR_UNABLE_TO_THROW_HERE: \"Не може да хвърли тук!\"\n  STR_SET_TIMER: \"Забавяне\"\n  STR_HIDDEN_MOVEMENT: \"СКРИТИ ДВИЖЕНИЯ\"\n  STR_TURN: \"ХОД> {0}\"\n  STR_SIDE: \"СТРАНА> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Натиснете клавиш да продължите\"\n  STR_MIND_CONTROL: \"Обсебване\"\n  STR_PANIC_UNIT: \"Паника\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Бойният дух бе снижен!\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Целта е обсебена\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}изпадна в бяс\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}изпадна в бяс\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}изпадна в паника\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}изпадна в паника\"\n  STR_ALIENS: \"Пришълци\"\n  STR_RIGHT_HAND: \"ДЯСНА РЪКА\"\n  STR_LEFT_HAND: \"ЛЯВА РЪКА\"\n  STR_RIGHT_SHOULDER: \"ДЯСНО РАМО\"\n  STR_LEFT_SHOULDER: \"ЛЯВО РАМО\"\n  STR_BACK_PACK: \"РАНИЦА\"\n  STR_BELT: \"КОЛАН\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}е под извънземен контрол\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}е под извънземен контрол\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}изпадна в безсъзнание\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}изпадна в безсъзнание\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}умря заради смъртоносна рана\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}умря заради смъртоносна рана\"\n  STR_USE_MIND_PROBE: \"Психосондиране\"\n  STR_FATAL_WOUNDS: \"СМЪРТОНОСНИ РАНИ\"\n  STR_UNDER_ARMOR_UC: \"ЗАЩИТА ОТДОЛУ\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Точките действие са запазени за припрян изстрел\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Точките действие са запазени за откос\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Точките действие са запазени за прицелен изстрел\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Точките действие са запазени за коленичене\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"ТД са запазени за стрелба от коляно\"\n  STR_ABORT_MISSION_QUESTION: \"Изтегляне от операцията?\"\n  STR_CORPSE: \"Труп\"\n  STR_UNLOAD_CRAFT: \"Разтоварване\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}беше убит\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}беше убита\"\n  STR_HIT_MELEE: \"Удар\"\n  STR_GROUND: \"НА ЗЕМЯТА\"\n  STR_LIVING_QUARTERS_PLURAL: \"Жилища\"\n  STR_LIST_ITEM: \"АРТИКУЛ\"\n  STR_PERSONAL_ARMOR_UFOPEDIA: \"Приложение на новооткритите Извънземни сплави. Тази броня ще изравни донякъде шансовете на нашите хора срещу извънземната заплаха.\"\n  STR_POWER_SUIT_UFOPEDIA: \"Ново, мощно защитно бойно облекло. Тази броня се захранва от елериев енергиен източник и предлага най-добрата засега защита на бойните единици.\"\n  STR_FLYING_SUIT_UFOPEDIA: \"Модифицирана версия на Силовата броня, използваща извънземната антигравитационна технология за пълна свобода на движение по бойното поле.\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"Всички пришълци са загинали,{NEWLINE}събирането протича спокойно\"\n  STR_RESET: \"Изчистване\"\n  STR_MEMORIAL: \"Мемориал\"\n  STR_DATE_UC: \"ДАТА\"\n  MAP_CULTA: \"Ферма\"\n  MAP_FOREST: \"Горски\"\n  MAP_JUNGLE: \"Джунгла\"\n  MAP_MOUNT: \"Планински\"\n  MAP_DESERT: \"Пустинен\"\n  MAP_POLAR: \"Полярен\"\n  MAP_UBASE: \"Строеж на база\"\n  STR_MIXED: \"Смесица\"\n  STR_REMOVE_SELECTED: \"Изваждане на избраните\"\n  STR_CONTAINMENT_EXCEEDED: \"ИЗОЛАЦИОННИТЕ СА ПРЕПЪЛНЕНИ!{SMALLLINE}Не достига място в изолационните на {0}. Трябва да извадите от тях излишните извънземни (което ще причини смъртта им).\"\n  STR_MANAGE_CONTAINMENT: \"Задържани под изолация\"\n  STR_STORAGE_EXCEEDED: \"НАДВИШАВАНЕ НА КАПАЦИТЕТА!{SMALLLINE}Не достига място за съхранение в {0}. Трябва да продадете излишните неща.\"\n  STR_GO_TO_BASE: \"Показване на базата\"\n  STR_MELEE_ACCURACY: \"ТОЧНОСТ ПРИ РЪКОПАШЕН БОЙ\"\n  STR_SELL_PRODUCTION: \"ПРОДАВАНЕ\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"И двете ръце трябва да са свободни!\"\n  STR_ALL_ITEMS: \"ВСИЧКИ ПРЕДМЕТИ\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/cs.yml",
    "content": "cs:\n  STR_AVENGER_UFOPEDIA: \"TRANSPORTNÍ A BITEVNÍ KOSMICKÁ LOĎ. DOKONALÉ NAPODOBENÍ CIZÁCKÉ TECHNOLOGIE.\"\n  STR_INTERCEPTOR_UFOPEDIA: \"BITEVNÍ LETOUN S DVOJITÝM PULSNĚ-DETONAČNÍM MOTOREM A SPECIÁLNĚ STÍNĚNÝMI ELEKTRONICKÝMI SYSTÉMY. NEJLEPŠÍ DOSTUPNÁ POZEMSKÁ TECHNIKA.\"\n  STR_LIGHTNING_UFOPEDIA: \"TRANSPORTNÍ A BITEVNÍ KOSMICKÉ PLAVIDLO. HRUBÁ ALE EFEKTIVNÍ KOPIE CIZÁCKÝCH PROPULSNÍCH SYSTÉMŮ.\"\n  STR_SKYRANGER_UFOPEDIA: \"TRANSPORTÉR PĚCHOTY. NEJRYCHLEJŠÍ SVÉHO DRUHU, S MOŽNOSTÍ SVISLÉHO VZLETU A PŘISTÁNÍ.\"\n  STR_FIRESTORM_UFOPEDIA: \"BITEVNÍ LETOUN. TATO JEDNOMÍSTNÁ STÍHAČKA NAPODOBUJE KLASICKÝ TVAR CIZÁCKÉHO LETAJICÍHO TALÍŘE, S CENTRÁLNÍ PROPULSNÍ JEDNOTKOU.\"\n  STR_STINGRAY_UFOPEDIA: \"POKROČILÁ RAKETA VZDUCH-VZDUCH SE SPECIÁLNĚ STÍNĚNOU ELEKTRONIKOU.\"\n  STR_AVALANCHE_UFOPEDIA: \"RAKETA VZDUCH-VZDUCH S NUKLEARNÍ HLAVICÍ, ALE VYSOKOU VÁHOU.\"\n  STR_CANNON_UFOPEDIA: \"VYSOCE VÝKONNÉ DĚLO, STŘÍLEJÍCÍ PRŮBOJNÉ STŘELY SCHOPNÉ PRORAZIT 400MM SILNOU OCEL.\"\n  STR_FUSION_BALL_UFOPEDIA: \"TOTO ODPALOVACÍ ZAŘÍZENÍ STŘILÍ KULOVITÉ STŘELY HNANÉ REAKCÍ ANTIHMOTY. KOULE NIČÍ CÍL IMPLOZÍ ZPŮSOBENOU GRAVITAČNÍMI VLNAMI.\"\n  STR_LASER_CANNON_UFOPEDIA: \"TENTO KONVENČNÍ LASEROVÝ PAPRSEK JE NAPÁJEN REAKČNÍ KOMOROU ANTIHMOTY.\"\n  STR_PLASMA_BEAM_UFOPEDIA: \"GRAVITAČNÍ SVAZEK SMĚRUJE PŘESNĚ ZAOSTŘENÉ IMPLODUJÍCÍ GRAVITAČNÍ POLE.\"\n  STR_SECTOID_UFOPEDIA: \"Hierarchie sektanů sahá od vojáků až po vůdce s mocnými psionickými schopnostmi. Tyto psionické síly mohou být použity k demoralizaci vojáků v boji, nebo dokonce k ovládnutí jejich myslí. Jsou zapleteni do únosů lidí a mrzačení skotu. Únosy jsou používány pro získání genetického materiálu pro křížení a vývoj klonů vhodných k infiltraci lidské společnosti. Dobytek poskytuje jednak potravu, jednak genetický materiál. Zdá se, že tato rasa chce vyvinout vysoce kvalitní genetické hybridy, vhodné pro zvyšení efektivity jejich společnosti, která se strukturou podobá roji.\"\n  STR_SECTOID_AUTOPSY: \"Pitva sektana\"\n  STR_SECTOID_AUTOPSY_UFOPEDIA: \"Pitva odhalila zakrnělé trávící orgány a jednoduché ústrojí. Mozek a oči jsou velmi dobře vyvinuty. Dle struktury lze odhadovat genetickou alteraci nebo mutaci. Malá ústa a nos již neplní původní funkci. Blána mezi prsty a plochá chodila naznačují vodní původ. Tělo neobsahuje žádné pohlavní orgány a nebyly nalezeny žádné náznaky způsobu rozmnožování. Jde s vysokou pravděpodobností o geneticky upravené druhy.\"\n  STR_SNAKEMAN_UFOPEDIA: \"Tato rasa se vyvinula v extrémně nepříznivém prostředí. Jsou neobyčejně odolní a snesou extremní výkyvy teploty. Pohybují se pomocí obrovské 'nohy' podobné tělu hada, která chrani všechny jejich životně důležité orgány. Jejich cíle jsou pravděpodobně pouze predátorské a náznaky ukazují na vliv jiné Inteligence, která řídí jejich militantní nájezdy na zemi.\"\n  STR_SNAKEMAN_AUTOPSY: \"Pitva hadoma\"\n  STR_SNAKEMAN_AUTOPSY_UFOPEDIA: \"Kůže je extrémně tuhá a odolná proti žáru. Kardiovaskulární systém je částí pohybového ústrojí, které používá pro vznik pohybu hydraulický princip. Jediný skutečným svalem je 'srdce'. Reprodukční ústrojí je pravděpodobně vysoce efektivní. Rozmnožování je bezpohlavní; každý Hadom nese uvnitř svého těla najednou až 50 vajíčekk. Ponechán svému osudu by tento druh byl nebezpečným ohrožením pozemského života.\"\n  STR_ETHEREAL_UFOPEDIA: \"Tato bytost dispnonuje vysoce vyvinutými mentálními schopnostmi. Zdánlivě slabé fyzické schopnosti tohoto tvora jsou vyrovnány jeho mentální silou. Princip těchto telekinetickych sil nám není znám; zdá se, že porušují fyzikální zákony tak, jak je známe. Etheralové jsou extrémně nebezpeční v jakýchkoliv bojových situacích, ve kterých spolehají na své bojové mentální schopnosti. Na zemi se objevují zřídka a zdá se, že často spoléhají na jiné rasy k dosažení svých cílů.\"\n  STR_ETHEREAL_AUTOPSY: \"Pitva etherala\"\n  STR_ETHEREAL_AUTOPSY_UFOPEDIA: \"Tato bytost je fyzicky nevyvinutá a vypadá to, že není schopna udržet žádné životní funkce. Svaly jsou těžce atrofované a vnitřní orgány vypadají velmi málo vyvinuté.Vypadá to, že smyslové orgány, včetně očí vůbec nefungují. Naopak mozek je velmi dobře vyvinut a spotřebovává velkou část z krevního zásobení. Je záhadou, jak tato bytost může přežívat bez vnější podpory.\"\n  STR_MUTON_UFOPEDIA: \"Tento humanoidni tvor je fyzicky silný a inteligentní. Má zvláštní chuť ke konzumaci syrového masa jekéhokoliv druhu, které potřebují pro výživu stejně jako pozemští masožravci. Zjevně jsou zavislí na telepatických povelech rasy znamé jako 'Etheralové'. Je-li toto telepatické spojení přerušeno, jejich mentální systém se rozpadá a jedinec umírá. Kybernetické implantáty jsou určeny k vylepšení jejich výkonu v boji. Jde zjevně o pěšáky ve službách vyšší inteligence.\"\n  STR_MUTON_AUTOPSY: \"Pitva mutona\"\n  STR_MUTON_AUTOPSY_UFOPEDIA: \"'Kůže' tohoto tvora je organicky vytvořená ochranná zbroj, začleněná do organismu. Lze nalézt množství kybernetických implantátů, jejichž účelem je vylepšit kardiovaskulární soustavu a smysly. Rozmnožovací orgány byly pravděpodobně chirurgicky odstraněny. Tito nešťastní tvorové jsou zjevně předurčeni pro válku a boj. Průbojné střely nejsou proti jejich zesílené kůži příliš účinné.\"\n  STR_CELATID_UFOPEDIA: \"Tato forma života má záhadnou přirozenou schopnost vznášet se ve vzduchu. Pravděpodobně detekuje vlny lidského mozku a objeví tak i skrytého člověka. Jakmile najde cíl, Celatid přistává a vystřeluje malé globule extrémně korozivního jedu. Tento tvor má schopnost klonovat sám sebe alarmující rychlostí. Doprovazí rasu Mutonů na jejich misích.\"\n  STR_CELATID_AUTOPSY: \"Pitva celatida\"\n  STR_CELATID_AUTOPSY_UFOPEDIA: \"Jádro obsahuje malé biomechanické zařízení, jež je pravděpodobně přirozeně vyvinutým antigravitačním propulsním systémem. Největším orgánem je vak jedu; nelze nalézt samostanou mozkovou strukturu. Taktéž tělo neobsahuje specializovanou trávící nebo rozmnožovací soustavu. Malý orgán obsahuje embrya, která se mohou rychle vyvinout v nového jedince.\"\n  STR_SILACOID_UFOPEDIA: \"Tato forma života, založená na křemíku, generuje enormní množství tepla. Má dost síly k rozdrcení kamenů, jež pak tráví horkým jádrem. Má primitivní inteligenci a může být kontrolována telepatickými bytostmi nebo pomocí implantátů. Doprovází rasu Mutonů.\"\n  STR_SILACOID_AUTOPSY: \"Pitva silacoida\"\n  STR_SILACOID_AUTOPSY_UFOPEDIA: \"Jádro tvora je extrémně horké a zdá se být základem trávící soustavy. Jeho ojedinělý svalový aparát má ohromnou sílu a rychlost. Jeho skále podobná kůže je necitlivá k ohni nebo zápalné munici.\"\n  STR_CHRYSSALID_UFOPEDIA: \"Klepeta této kreatury, podobná krabím, jsou výbornou zbraní pro boj zblízka.  Rychlý metabolismus a síla dávaji tomuto tvoru rychlost a obratnost. Místo zabíjeni své kořisti, ji 'oplodni' vajíčkem a vstříkne jed, jež oběť změní v chodící zombii. Nový Krysklad z oběti vyhřezne velmi brzy po nakladení vajíčka. Kryskladi jsou spojeni s rasou Hadomů.\"\n  STR_CHRYSSALID_AUTOPSY: \"Pitva krysklada\"\n  STR_CHRYSSALID_AUTOPSY_UFOPEDIA: \"Vnější kostra tohoto tvora je extrémně tvrdá, ale překvapivě citlivá na explozivní munici. Mozek je dobře vyvinut a buňky organizmu se obnovují velmi rychle. Tvor nese dvacet vajíček, jež jsou kladeny do jiných organismu. Tento tvor je velmi efektivni zbraní teroru.\"\n  STR_FLOATER_UFOPEDIA: \"Leviti jsou hlavně vojáci a teroristi. Jsou přirozenými predátorskými šelmami. Genetické úpravy a kybernetická vylepšení z nich dělá nebezpečné válečníky. Spodní polovina těla a většina vnitřních orgánů je chirurgicky odstraněna a místo nich je nainstalován systém, který je udržuje při životě. Tento implantát obsahuje antigravitační jednotku, jež tvoru umožňuje se volně ačkoli nepříliš pevně vznášet vzduchem.\"\n  STR_FLOATER_AUTOPSY: \"Pitva levita\"\n  STR_FLOATER_AUTOPSY_UFOPEDIA: \"Tvor byl drasticky změněn chirurgickým zákrokem. Zařízení, jež zdánlivě tvoří jádro těla, je podpůrný systém nahrazující činnost srdce, žláz a trávící soustavy. To umožňuje tvorovi přežívat i v extrémně nepříznivých prostředích. Mozek je menší než náš, ale smyslové orgány jsou dobře vyvinuté.\"\n  STR_REAPER_UFOPEDIA: \"Tento dvounohý masožravec má silné čelisti a nenasytný apetit. Je vybaven množstvím mozkových implantátů, jež jsou používány k jeho ovládání. Priminitvní lovecké instinkty tohoto tvora nemaji jiné využití než terorizování a ničení. Páráci běžně doprovázejí levity.\"\n  STR_REAPER_AUTOPSY: \"Pitva páráka\"\n  STR_REAPER_AUTOPSY_UFOPEDIA: \"Párák má dva 'mozky' a dvě 'srdce', což mu umožňuje pokračovat v boji i s velmi těžkým zraněním. Nicméně jeho chlupatá kůže je vysoce vznětlivá, což činí tuto kreaturu zranitelnou zápalnými zbraněmi.\"\n  STR_SECTOPOD_UFOPEDIA: \"Sektopodi jsou roboti vybavení zbraní produkující silný laserový paprsek. Tyto mechanické nestvůry jsou ovládány telepatickým spojením s jejich vůdci, etheraly.  Sektopodi jsou nejsilnější teroristické zbraně které mají cizáci k dispozici.\"\n  STR_SECTOPOD_AUTOPSY: \"Pitva sektopoda\"\n  STR_SECTOPOD_AUTOPSY_UFOPEDIA: \"Robot je robustně konstruován a pokryt energickou zbrojí schopnou odolat většině typů útoku. Je obzvlášť odolný proti plasmovým zbraním. Smyslové obvody jsou ale velmi citlivé na laserové zbraně.\"\n  STR_CYBERDISC_UFOPEDIA: \"Tento miniaturní létající talíř je automatizovanou zbraní teroru, vyzbrojený výkonným plasmovým dělem. Antigravitační pohonný systém mu dává velkou výhodu v náročném terénu. Primárním účelem Kyberdisku je destrukce a teror ve službách sektanů.\"\n  STR_CYBERDISC_AUTOPSY: \"Pitva kyberdisku\"\n  STR_CYBERDISC_AUTOPSY_UFOPEDIA: \"Kyberdisk je dobře opancéřován a je zvláště odolný proti explozivní munici. Primarní antigravitační systém je bohužel příliš poškozen na to, aby bylo možno prozkoumat jeho princip.\"\n  STR_UFO_POWER_SOURCE_UFOPEDIA: \"Jako zdroj energie pro cizácké stroje slouží reaktor na antihmotu, který používá Elerium (115. prvek) ke generování silných gravitačních vln, a také jiných forem energie. Přeměna hmoty v energii je učinná na neuvěřitelných 99%, takže minimální množství Eleria je schopno vyprodukovat ohromné množství energie. Tato jednotka může být jednoduše reprodukována za použití cizáckých slitin.\"\n  STR_UFO_NAVIGATION_UFOPEDIA: \"Cizacké lodě používají sofistikované počítače k navigaci na Zemi i ve vesmíru. Systém je založen na sítích optických procesorů. Ovládací rozhraní je poměrně jednoduché - navigátor ovládá směr gravitačních vln generovaných zdrojem energie a tak pohybuje strojem v libovolném směru. Tento systém muže být lehce používán lidmi a muže být reprodukován za použití cizáckých slitin a jiných komponent.\"\n  STR_UFO_CONSTRUCTION_UFOPEDIA: \"Cizácká loď se skládá ze tří hlavních komponent - zdroje energie, navigačního systému a skořepiny z cizáckých slitin. Skořepina je specialně tvarovaná tak, aby mohly být gravitační vlny usměrňovány a ovládány. Navíc je nutné malé množství Eleria jako palivo pro zdroj energie. Jakmile porozumíme principům konstrukce a fuknce každé z komponent, bude možné stavět tyto typy letounů.\"\n  STR_ALIEN_FOOD_UFOPEDIA: \"Tyto nádrže obsahují rozličné enzymy, jež tráví části těl skotu, jiných zvířat a dokonce i lidí. Tekutina je pak konzumována jako už strávené jídlo - pravděpodobně přímo do krevního oběhu. To naznačuje určitou závislost na potravě pozemského původu - symbiózu mezi Zemí a cizáckou společností.\"\n  STR_ALIEN_REPRODUCTION_UFOPEDIA: \"Tyto komory obsahují cizácké zárodky. Z konstrukce těchto zásobníků se dá předpokládat, že cizáci používající tento proces, jsou plně závislí na laboratorním rozmnožování. Výživné látky zajišťují rychlý vývoj zárodku. Tento, tovární lince podobný, systém je schopen vytvářet tisíce cizáckých klonů v krátkém časovém úseku. Postup může být jednoduše přizpůsoben pro rozmnožování lidí nebo cizácko-lidských hybridů.\"\n  STR_ALIEN_ENTERTAINMENT_UFOPEDIA: \"Nejpravděpodobnější funkce těchto koulí je oddychová. Psionické obvody stimulují různá centra mozku. Efekt je podobný halucinogenním drogám. Je to jediný doklad o tom, že cizáci mají přestávky na kulturu nebo odpočinek.\"\n  STR_ALIEN_SURGERY_UFOPEDIA: \"Toto chirurgické zařízení používá laserové skalpely k získání určitých částí těla ze skotu nebo jiných zvířat. Široce rozšířená postižení skotu mohou být přičtena na vrub této bizardní cizácké činnosti. Získané části jsou pravděpodobně použity pro účely výživy nebo genetiky.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"Během mnoha minulých tisíciletí lidé tvrdili, že byli uneseni cizáky, někdy opakovaně. Pravda je mnohem hrůznější. Lidé jsou unášeni, zkoumáni a pozorováni. Z nejlepších exemplářů je extrahován genetický materiál. Ženám jsou implantovány hybridní lidsko-cizácké zárodky a pak odejmuty po několika měsících. Kdo ví, jaké zlověstné motivy cizáci mají.\"\n  STR_ALIEN_ALLOYS_UFOPEDIA: \"Cizácké lodě jsou konstruovány ze speciálních slitin s jedinečnými vlastnostmi. Jsou extrémně lehké a odolné. Mohou být taveny elektromagnetickými metodami. Tento materiál může být reprodukován a používán v mnoha různých výrobních postupech.\"\n  STR_ELERIUM_115_UFOPEDIA: \"Tento prvek má neobyčejnou vlastnost - je-li bombardován určitými částicemi, generuje antigravitační energii. To vytváří gravitační vlny a jiné formy energie. V naší sluneční soustavě se původně nenachází a nemůže být reprodukován.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"Je zřejmé, že na Zemi bojujeme předem prohranou bitvu. Cizácké hordy nás početně převyšují. Jediná naděje lidstva je potlačit cizáky v jejich zdroji. Náš výzkum ukazuje na nedalekou operační základnu v našem slunečním systému. Dle cizáků je toto místo centrem staré civilizace, datovanou před lidskou historii. Musíme určit toto místo co nejdříve. Nicméně musíme zajmout a vyslechnout cizáckého vůdce, abychom získali detailnější informace. Na palubě větších lodí UFO se pravděpodobně nachází alespoň jeden cizácký vůdce.\"\n  STR_THE_MARTIAN_SOLUTION_UFOPEDIA: \"Náš výzkum nyní ukazuje k Marsu jako základně cizackých operací. Základna je dobře ukrytá a obsahuje všechny výrobní a klonovací kapacity nutné k zásobování infiltrace Země. Zdá se též, že obsahuje řídící počítač nějakého typu, jež ovládá celou operaci. Roji podobná cizácká společnost má zřejmě nějakou \\\"včelí královnu\\\". To je jejich základní slabina - budeme-li schopni zneškodnit \\\"mozek\\\", tělo zemře též. Musíme posílit naše výzkumné snahy než bude příliš pozdě. Abychom mohli pokročit, je nutné zajmout cizáky s nejvyšší hodností - velitele; ti sídlí pouze v cizáckých základnách a na bitevních lodích.\"\n  STR_CYDONIA_OR_BUST_UFOPEDIA: \"Nyní je zřejmé, že hordy cizáků jsou kontrolovány z podzemní základny v Cydonii - což je neobvyklá oblast Marsu s pětistěnnými pyramidami a rozsáhlým útvarem připomínajícím lidský obličej. Kdysi - před mnoha miliony let - kvetla na Marsu Cydonijská civilizace. Nevíme proč vymizela, nebo jaká je spojitost s aktivitou cizáků v této oblasti v poslední době. Ať už je vysvětlení jakékoliv, musíme do Cydonie vyslat expedici. Je to jedina možnost, jak porazit cizáky. Musíme zničit centrální všeovládající \\\"mozek\\\". Budeme potřebovat lod typu Mstitel, vybavenou tou nejschopnější destruktivní silou. Zde se již nedozvíme nic moc dalšího - musíme počkat na výsledky útoku na Cydonii.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"VYSTŘEDIT NA POZICI-ČAS=5 sek\"\n  STR_CANCEL_UC: \"ZRUŠIT\"\n  STR_NONE: \"Žádný\"\n  STR_UNKNOWN: \"Neznámo\"\n  STR_POOR: \"Ubohý\"\n  STR_AVERAGE: \"Průměrný\"\n  STR_GOOD: \"Dobrý\"\n  STR_EXCELLENT: \"Výborný\"\n  STR_BUILD_NEW_BASE_UC: \"ZALOŽIT NOVOU ZÁKLADNU \"\n  STR_BASE_INFORMATION: \"INFORMACE O ZÁKLADNĚ \"\n  STR_EQUIP_CRAFT: \"VYBAVIT LOĎ\"\n  STR_BUILD_FACILITIES: \"VYBUDOVAT ZAŘÍZENÍ\"\n  STR_RESEARCH: \"VÝZKUM\"\n  STR_MANUFACTURE: \"VÝROBA\"\n  STR_TRANSFER_UC: \"PŘESUN\"\n  STR_PURCHASE_RECRUIT: \"NÁKUP/NÁBOR\"\n  STR_SACK: \"PROPUSTIT\"\n  STR_SELL_SACK_UC: \"PRODEJ/PROPOUŠTĚNÍ\"\n  STR_GEOSCAPE_UC: \"GLÓBUS\"\n  STR_NAME: \"Jméno\"\n  STR_AREA: \"Oblast\"\n  STR_BUILD_NEW_BASE: \"Postavit novou základnu\"\n  STR_CANCEL: \"Zrušit\"\n  STR_COST_UC: \"CENA>\"\n  STR_CONSTRUCTION_TIME_UC: \"DOBA STAVBY>\"\n  STR_DAY:\n    one: \"{N} den\"\n    few: \"{N} dny\"\n    many: \"{N} dní\"\n    other: \"{N} dní\"\n  STR_HOUR:\n    one: \"{N} hodina\"\n    few: \"{N} hodiny\"\n    many: \"{N} hodin\"\n    other: \"{N} hodin\"\n  STR_MAINTENANCE_UC: \"ÚDRŽBA>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Instalace\"\n  STR_CURRENT_RESEARCH: \"SOUČASNÝ VÝZKUM\"\n  STR_SCIENTISTS_AVAILABLE: \"Vědců k dispozici>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Přirazeno vědců>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Místo v laboratoři k dispozici>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"VÝZKUMNÝ PROJEKT\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"PŘIDĚLENÝCH VĚDCŮ\"\n  STR_PROGRESS: \"POKROK\"\n  STR_NEW_PROJECT: \"Nový projekt\"\n  STR_CANCEL_PROJECT: \"ZRUŠIT PROJEKT\"\n  STR_NEW_RESEARCH_PROJECTS: \"NOVÉ VÝZKUMNÉ PROJEKTY\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"VĚDCŮ K DISPOZICI>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"VOLNÉ MÍSTO V LABORATOŘI>{ALT}{0}\"\n  STR_INCREASE: \"Zvýšit\"\n  STR_DECREASE: \"Snížit\"\n  STR_START_PROJECT: \"ZAHÁJIT PROJEKT\"\n  STR_CURRENT_PRODUCTION: \"SOUČASNÁ VÝROBA\"\n  STR_ENGINEERS_AVAILABLE: \"Inženýrů k dispozici>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Přiděleno inženýrů>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Místo v dílně k dispozici>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Aktuální finance>{ALT}{0}\"\n  STR_ITEM: \"POLOŽKA\"\n  STR_ENGINEERS__ALLOCATED: \"Přiděleno inženýrů\"\n  STR_UNITS_PRODUCED: \"Vyrobeno jednotek\"\n  STR_TOTAL_TO_PRODUCE: \"Celkově vyrobit\"\n  STR_COST__PER__UNIT: \"Cena{NEWLINE}za{NEWLINE}jednotku\"\n  STR_DAYS_HOURS_LEFT: \"Dní/Hodin zůstává\"\n  STR_NEW_PRODUCTION: \"Nová výroba\"\n  STR_PRODUCTION_ITEMS: \"Vyrobitelné předměty\"\n  STR_CATEGORY: \"KATEGORIE\"\n  STR_START_PRODUCTION: \"ZAHÁJIT PRODUKCI\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} člověkohodin na jednotku\"\n  STR_COST_PER_UNIT_: \"Cena za jednotku>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Požadovaný pracovní prostor>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"VYŽADOVÁNY SPECIÁLNÍ MATERIÁLY\"\n  STR_ITEM_REQUIRED: \"POŽADOVANÁ POLOŽKA\"\n  STR_UNITS_REQUIRED: \"POŽADOVANÝCH JEDNOTEK\"\n  STR_UNITS_AVAILABLE: \"JEDNOTEK K DISPOZICI\"\n  STR_STOP_PRODUCTION: \"UKONČIT VÝROBU\"\n  STR_ENGINEERS_AVAILABLE_UC: \"INŽENÝŘŮ K DISPOZICI>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"VOLNÉ MÍSTO V DÍLNĚ>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"MĚSÍČNÍ ZISK>{ALT}{0}\"\n  STR_INCREASE_UC: \"ZVÝŠIT\"\n  STR_DECREASE_UC: \"SNÍŽIT\"\n  STR_UNITS_TO_PRODUCE: \"Vyrobit jednotek\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Nákup/Nábor\"\n  STR_COST_OF_PURCHASES: \"Cena za nákup>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"CENA ZA JEDNOTKU\"\n  STR_QUANTITY_UC: \"MNOŽSTVÍ\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"VOLNÝ PERSONÁL:PERSONÁLU CELKEM>\"\n  STR_SOLDIERS: \"Vojáků\"\n  STR_SCIENTISTS: \"Vědců\"\n  STR_ENGINEERS: \"Inženýři\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"VYUŽITÝ PROSTOR:VOLNÝ PROSTOR>\"\n  STR_LIVING_QUARTERS: \"Obytné buňky\"\n  STR_STORES: \"Sklady\"\n  STR_LABORATORIES: \"Laboratoře\"\n  STR_WORK_SHOPS: \"Dílny\"\n  STR_HANGARS: \"Hangáry\"\n  STR_SHORT_RANGE_DETECTION: \"Detekce kratkého dosahu\"\n  STR_DEFENSE_STRENGTH: \"Síla obrany\"\n  STR_TRANSFERS_UC: \"PŘESUNY\"\n  STR_TRANSFERS: \"Přesuny\"\n  STR_ARRIVAL_TIME_HOURS: \"Doba dodání (hodin)\"\n  STR_COST_: \"Cena>{ALT}{0}\"\n  STR_AREA_: \"Oblast>{ALT}{0}\"\n  STR_BASE_NAME: \"Jméno základny?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"ZVOLTE POZICI PŘÍSTUPOVÉHO VÝTAHU\"\n  STR_TRANSFER: \"Přesun\"\n  STR_AMOUNT_TO_TRANSFER: \"MNOŽSTVÍ K PŘESUNU\"\n  STR_SELECT_DESTINATION_BASE: \"Zvolte cílovou základnu \"\n  STR_COST: \"Cena\"\n  STR_VICTORY_1: \"Jakmile jsi vstoupil do velké místnosti, uviděl jsi cizácký mozek - cíl výpravy. Než jsi stačil vypálit, začal s tebou komunikovat prostřednictvím obrazovky ve své základně. Přiměje tě naslouchat jeho argumentům pro přežití, ještě než se rozhodneš stisknout spoušť...\"\n  STR_VICTORY_2: \"Mozek začal hovořit: 'Před mnoha miliony let byla planeta, jež nazýváte Marsem, živá. Tento život byl na pustou planetu přinesen naší civilizací a stejně tak byl přinesen i na vaši planetu. Po miliony let jsme navštěvovali vaši planetu a geneticky rozvíjeli váš druh. Nemůžete nás zabít, jste naší součástí...\"\n  STR_VICTORY_3: \"Zde je centrum marťanské civilizace - pyramidy postavené miliony let před těmi pozemskými - druhem, jenž je vaším předkem. Žádná planeta nám není nedosažitelná. Tato moc může být zanedlouho i vaše. Vše, co žádáme na oplátku, je vaše spolupráce...\"\n  STR_GAME_OVER_1: \"Cizáci chtějí zlikvidovat veškeré lidstvo; ničí města, otravují vzduch a moře. Odpor pozemských armád je smešný tvaří v tvář mnohem dokonalejším technologiím. Přeživší generace, která uprchla před cizáckým ničením, trpí hroznými mutacemi. Jsou zavřeni do pracovních táborů, aby pomohli přeměnit Zemi v cizáckou kolonii, která je součástí jakéhosi neznámého impéria.\"\n  STR_GAME_OVER_2: \"Znalosti získané projektem X-Com jsou navždy ztraceny. Selhal jsi a nedokázal zachránit zemi.\"\n  STR_VICTORY_4: \"Cizácký mozek je přerušen paprskem horké plasmy. Veškeré cizácké síly jsou poraženy.\"\n  STR_VICTORY_5: \"Ztrátou Marsu ztratili cizáci i Zemi. Výzkumy X-Com umožnili lidstvu znovu vzkvést a zachovat si Mars pro sebe. Cizácký přízrak zmizel, ale kdo ví, na jak dlouho...\"\n  STR_YOU_HAVE_FAILED: \"Nedokázal jsi zastavit mimozemský nápor. Členské státy rady jeden po druhém podepsaly s cizáky dohodu slibující prosperitu, technologie a mír. Avšak brzy se ukázalo, že cizáci mají jiné plány...\"\n  STR_TOTAL_UC: \"CELKEM\"\n  STR_INCOME: \"Příjmy\"\n  STR_EXPENDITURE: \"Výdaje\"\n  STR_MAINTENANCE: \"Údržba\"\n  STR_BALANCE: \"Zůstatek\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"Aktivita UFO v oblastech\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"Aktivita UFO ve státech\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"Aktivita X-Com v oblastech\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"Aktivita X-Com ve státech\"\n  STR_FINANCE: \"Finance\"\n  STR_DATE_FIRST: \"{0}.\"\n  STR_DATE_SECOND: \"{0}.\"\n  STR_DATE_THIRD: \"{0}.\"\n  STR_DATE_FOURTH: \"{0}.\"\n  STR_FINANCE_THOUSANDS: \"$1000\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Nedostatek speciálních materiálů k výrobě{NEWLINE}{0}{NEWLINE}v{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Nedostatek peněz k výrobě{NEWLINE}{0}{NEWLINE}v{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"Výroba {NEWLINE}{0}{NEWLINE}na{NEWLINE}{1}{NEWLINE}dokončena\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"Výstavba{NEWLINE}{0}{NEWLINE}na{NEWLINE}{1}{NEWLINE}hotová\"\n  STR_OK_5_SECONDS: \"OK - 5 sek\"\n  STR_RESEARCH_COMPLETED: \"Výzkum dokončen\"\n  STR_VIEW_REPORTS: \"ČÍST VÝSLEDKY\"\n  STR_WE_CAN_NOW_RESEARCH: \"Nyní lze zkoumat:\"\n  STR_WE_CAN_NOW_PRODUCE: \"Nyní lze vyrábět:\"\n  STR_SUNDAY: \"NEDĚLE\"\n  STR_MONDAY: \"PONDĚLÍ\"\n  STR_TUESDAY: \"ÚTERÝ\"\n  STR_WEDNESDAY: \"STŘEDA\"\n  STR_THURSDAY: \"ČTVRTEK\"\n  STR_FRIDAY: \"PÁTEK\"\n  STR_SATURDAY: \"SOBOTA\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Schází {0} pro doplnění paliva stroje {1} v {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Nedosatatek {0} na přezbrojení {1} na {2}\"\n  STR_UFO_IS_NOT_RECOVERED: \"UFO nebylo zajištěno.\"\n  STR_UFO_IS_RECOVERED: \"UFO bylo zajištěno.\"\n  STR_CRAFT_IS_LOST: \"Letoun je ztracen\"\n  STR_TERROR_CONTINUES: \"Teror pokračuje\"\n  STR_ALIENS_DEFEATED: \"Cizáci jsou poraženi\"\n  STR_BASE_IS_LOST: \"Základna je ztracena\"\n  STR_BASE_IS_SAVED: \"Základna je zachráněna\"\n  STR_ALIEN_BASE_STILL_INTACT: \"Cizacká základna zůstala nepoškozena\"\n  STR_ALIEN_BASE_DESTROYED: \"Cizácká základna zničena\"\n  STR_ALIENS_KILLED: \"CIZÁKŮ ZABITO\"\n  STR_ALIEN_CORPSES_RECOVERED: \"CIZÁCKÝCH MRTVOL ZÍSKÁNO\"\n  STR_LIVE_ALIENS_RECOVERED: \"ŽIVÝCH CIZÁKŮ ZÍSKÁNO\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"CIZÁCKÝCH ARTEFAKTŮ ZÍSKÁNO\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"ŘÍZENÍ CIZÁCKÉ ZÁKLADNY ZNIČENO\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"CIVILISTŮ ZABITO CIZÁKY\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"CIVILISTŮ ZABITO PŘÍSLUŠNÍKY X-COM\"\n  STR_CIVILIANS_SAVED: \"CIVILISTŮ ZACHRÁNĚNO\"\n  STR_XCOM_OPERATIVES_KILLED: \"PŘÍSLUŠNÍKŮ X-COM ZABITO\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"PŘÍSLUŠNÍKŮ X-COM ZTRACENO V AKCI\"\n  STR_TANKS_DESTROYED: \"ZNIČENO TANKŮ\"\n  STR_XCOM_CRAFT_LOST: \"DOPRAVNÍ STROJ X-COM ZNIČEN\"\n  STR_UFO_RECOVERY: \"ZÍSKÁNO Z UFO\"\n  STR_ALIEN_BASE_RECOVERY: \"ZAJIŠTĚNÍ CIZÁCKÉ ZÁKLADNY\"\n  STR_BASE_UNDER_ATTACK: \"{0} je napadena!\"\n  STR_BASE_DEFENSES_INITIATED: \"OBRANA ZÁKLADNY ZAHÁJENA\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"GRAV. ŠTÍT ODPUZUJE UFO!\"\n  STR_FIRING: \"STŘÍLÍ\"\n  STR_HIT: \"ZÁSAH!\"\n  STR_UFO_DESTROYED: \"UFO ZNIČENO!\"\n  STR_MISSED: \"MINULA!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Prodat/propustit\"\n  STR_VALUE_OF_SALES: \"HODNOTA PRODEJE> {ALT}{0}\"\n  STR_FUNDS: \"FINANCE> {ALT}{0}\"\n  STR_SELL_SACK: \"Prodat/propustit\"\n  STR_VALUE: \"Hodnota\"\n  STR_CRAFT_: \"STROJ> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"ZAJIŠTĚNÍ HAVAROVANÉHO UFO\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"Nejvyšší opatrnost - V UFO, nebo v okolí místa havárie se mohou pohybovat cizí agenti. Mise bude úspěšná, budou-li veškeré nepřátelské jednotky eliminovány či zneškodněny. Poté bude zahájeno zajišťění zbytků UFO, artefaktů a cizáckých mrtvol. Chcete-li předčasně ukončit misi, navraťte se s příslušníky X-Com do transportéru a klikněte na ikonu 'Zrušit misi'.\"\n  STR_UFO_GROUND_ASSAULT: \"POZEMNÍ ÚTOK NA UFO\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"Prozkoumejte místo přistání a pokud možno získejte přístup do UFO. Mise bude úspěšná, budou-li veškeré nepřátelské jednotky eliminovány či zneškodněny. Poté bude zahájeno zajištění zbytků UFO, artefaktů a cizáckých mrtvol. Chcete-li předčasně ukončit misi, navraťte se s příslušníky X-Com do transportéru a klikněte na ikonu 'Zrušit misi'.\"\n  STR_BASE_DEFENSE: \"OBRANA ZÁKLADNY \"\n  STR_BASE_UC_: \"ZÁKLADNA> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"Cizácký koráb přistál v blízkosti zařízení X-Com. Základna je ve velkém nebezpečí. Všichni civilní zaměstnanci a letadla byla včas evakuována. Cizácké jednotky mohou proniknout do základny dveřmi hangáru nebo přístupovým výtahem. Ubraňte základnu a její životně důležité zařízení za každou cenu - toto je boj na život a na smrt. Kliknete-li na ikonu 'Zrušit misi', ztratíte základnu.\"\n  STR_ALIEN_BASE_ASSAULT: \"ÚTOK NA CIZÁCKOU ZÁKLADNU \"\n  STR_ALIEN_BASE_ASSAULT_BRIEFING: \"Jednotky X-Com získaly přístup do cizácké základny. Musíte zničit řídící centrum, čímž bude provoz základny přerušen. Mise bude ukončena, budou-li všichni nepřátelé eliminováni, nebo vrátí-li se jednotka do zelené únikové oblasti (únik z bojiště bude zahájen kliknutím na ikonu 'Zrušit misi').\"\n  STR_CYDONIA_BRIEFING: \"Přistáli jste v Cydonii. Získali jste přístup k rozlehlému podzemnímu komplexu pobliž Marťanské Sfingy. Musíte zničit Cizácký Mozek, který řídí cizáckou invazi. Osud lidstva leží ve vašich rukou...\"\n  STR_TERROR_MISSION: \"PROTITERORISTICKÁ MISE\"\n  STR_TERROR_MISSION_BRIEFING: \"Mise bude úspěšná, budou-li veškeré nepřátelské jednotky eliminovány nebo zneškodněny. Musíte zachránit životy civilistů v této oblasti neutralizací cizacké hrozby. Chcete-li ukončit misi předčasně, přesuňte jednotky X-Com zpět do transportéru, pak klikněte na ikonu \\\"Zrušit misi\\\".\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"ŽÁDNÉ VOLNÉ HANGÁRY PRO VÝROBU STROJE!{SMALLLINE}Každý stroj náležející základně, přepravovaný do základny, zakoupený nebo konstruovaný zaujímá jeden hangár. Vybudujte nový hangár nebo přesuňte stroj do jiné základny.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"ŽÁDNÉ VOLNÉ HANGÁRY PRO ZAKOUPENÝ STROJ!{SMALLLINE}Každý stroj náležející základně, přepravovaný do základny, zakoupený nebo konstruovaný zaujímá jeden hangár. Vybudujte nový hangár nebo přesuňte stroj do jiné základny.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"ŽÁDNÉ VOLNÉ HANGÁRY PRO PŘESUN STROJE!{SMALLLINE}Každý stroj náležející základně, přepravovaný do základny, zakoupený nebo konstruovaný zaujímá jeden hangár. Vybudujte nový hangár nebo přesuňte stroj do jiné základny.\"\n  STR_CANNOT_BUILD_HERE: \"ZDE NENÍ MOŽNO STAVĚT!{SMALLLINE}Můžete stavět pouze vedle dostavěných zařízení.\"\n  STR_NO_FREE_ACCOMODATION: \"NEDOSTEK UBYTOVACÍHO PROSTORU!{SMALLLINE}Cílová základna nedisponuje dostatkem místa v obytných buňkách.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"NEDOSTATEK PRACOVNÍHO PROSTORU!{SMALLLINE}Vybudujte novou dílnu nebo omezte práci na jiných projektech.\"\n  STR_NOT_ENOUGH_MONEY: \"NEDOSTATEK PENĚZ!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"NEDOSTATEK SKLADOVACÍHO PROSTORU!{SMALLLINE}Vybudujte nové skladové prostory nebo přesuňte současné zásoby do jiných základen.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"NEDOSTATEČNÁ UBYTOVACÍ KAPACITA!{SMALLLINE}Vybudujte nové obytné buňky nebo přesuňte zaměstnance do jiné základny.\"\n  STR_LAUNCH_INTERCEPTION: \"ZAHÁJIT PRONÁSLEDOVÁNÍ\"\n  STR_CRAFT: \"STROJ\"\n  STR_STATUS: \"STAV\"\n  STR_BASE: \"ZÁKLADNA\"\n  STR_READY: \"PŘIPRAVEN\"\n  STR_OUT: \"MIMO\"\n  STR_REPAIRS: \"OPRAVY\"\n  STR_REFUELLING: \"TANKOVÁNÍ\"\n  STR_REARMING: \"PŘEZBROJOVÁNÍ\"\n  STR_TARGET: \"CÍL: {0}\"\n  STR_WAY_POINT: \"VYTYČENÝ BOD\"\n  STR_ARE_YOU_SURE_CYDONIA: \"Jste si jist, že chceš poslat tento stroj na misi do Cydonie?\"\n  STR_YES: \"ANO\"\n  STR_NO: \"NE\"\n  STR_SELECT_DESTINATION: \"ZVOL CÍL\"\n  STR_CYDONIA: \"CYDONIE\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"VYBER UMÍSTĚNÍ NOVÉ ZÁKLADNY \"\n  STR_RETURN_TO_BASE: \"VRAŤ SE DO ZÁKLADNY\"\n  STR_SELECT_NEW_TARGET: \"VYBER NOVÝ CÍL\"\n  STR_PATROL: \"HLÍDKA\"\n  STR_STATUS_: \"STAV>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"POŠKOZEN - NÁVRAT DO ZÁKLADNY \"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"MÁLO PALIVA - NÁVRAT DO ZÁKLADNY\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"MISE DOKONČENA - NÁVRAT NA ZÁKLADNU\"\n  STR_PATROLLING: \"HLÍDKUJE\"\n  STR_TAILING_UFO: \"SLEDUJE UFO\"\n  STR_INTERCEPTING_UFO: \"PRONÁSLEDUJE UFO-{0}\"\n  STR_RETURNING_TO_BASE: \"NÁVRAT DO ZÁKLADNY\"\n  STR_DESTINATION_UC_: \"CÍL: {0}\"\n  STR_BASE_UC: \"ZÁKLADNA> {ALT}{0}\"\n  STR_SPEED_: \"RYCHLOST>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"MAXIMÁLNÍ RYCHLOST>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"VÝŠKA>{ALT}{0}\"\n  STR_VERY_LOW: \"VELMI NÍZKO\"\n  STR_LOW_UC: \"NÍZKO\"\n  STR_HIGH_UC: \"VYSOKO\"\n  STR_VERY_HIGH: \"VELMI VYSOKO\"\n  STR_FUEL: \"PALIVO>{ALT}{0}\"\n  STR_WEAPON_ONE: \"ZBRAŇ-1>{ALT}{0}\"\n  STR_NONE_UC: \"ŽÁDNÁ\"\n  STR_ROUNDS_: \"NÁBOJŮ>{ALT}{0}\"\n  STR_WEAPON_TWO: \"ZBRAŇ-2>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"STÍHACÍ STROJ\"\n  STR_BASE_: \"Základna> {0}\"\n  STR_NAME_UC: \"JMÉNO\"\n  STR_AMMO_: \"NÁBOJE>{ALT}{0}\"\n  STR_CREW: \"POSÁDKA\"\n  STR_EQUIPMENT_UC: \"VYBAVENÍ\"\n  STR_ARMOR: \"ZBROJ\"\n  STR_MAX: \"MAX>{ALT}{0}\"\n  STR_ROOKIE: \"Vojín\"\n  STR_SQUADDIE: \"Četař\"\n  STR_SERGEANT: \"Seržant\"\n  STR_CAPTAIN: \"Kapitán\"\n  STR_COLONEL: \"Plukovník\"\n  STR_COMMANDER: \"Generál\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Vyberte bojovou skupinu pro {0}\"\n  STR_SORT_BY: \"ŘADIT DLE...\"\n  STR_ORIGINAL_ORDER: \"PŮVODNÍ ŘAZENÍ\"\n  STR_MISSIONS2: \"MISE\"\n  STR_KILLS2: \"ZABITÍ\"\n  STR_WOUND_RECOVERY2: \"DOBA ZOTAVENÍ\"\n  STR_SPACE_AVAILABLE: \"MÍSTO K DISPOZICI>{ALT}{0}\"\n  STR_SPACE_USED: \"POUŽITÉ MÍSTO>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"POUŽITÉ MÍSTO\"\n  STR_RANK: \"HODNOST\"\n  STR_WOUNDED: \"ZRANĚN\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Vybavení pro {0}\"\n  STR_DEFENSE_VALUE: \"Kvalita obrany\"\n  STR_HIT_RATIO: \"Pravděpodobnost zásahu\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}je připraven{NEWLINE}přistát u{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"Zahájit misi?\"\n  STR_SELECT_ARMAMENT: \"Vyber výzbroj\"\n  STR_AMMUNITION_AVAILABLE: \"MUNICE K DISPOZICI\"\n  STR_ARMAMENT: \"VÝZBROJ\"\n  STR_NOT_AVAILABLE: \"ŽÁDNÁ\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"VYBERTE ZBROJ PRO{NEWLINE}{0}\"\n  STR_TYPE: \"TYP\"\n  STR_PERSONAL_ARMOR_UC: \"OSOBNÍ ZBROJ\"\n  STR_POWER_SUIT_UC: \"ENERGICKÝ SKAFANDR\"\n  STR_FLYING_SUIT_UC: \"LÉTAJÍCÍ SKAFANDR\"\n  STR_SELECT_ARMOR: \"Vyber zbroj\"\n  STR_NORTH: \"SEVER\"\n  STR_NORTH_EAST: \"SEVEROVÝCHOD\"\n  STR_EAST: \"VÝCHOD\"\n  STR_SOUTH_EAST: \"JIHOVÝCHOD\"\n  STR_SOUTH: \"JIH\"\n  STR_SOUTH_WEST: \"JIHOZÁPAD\"\n  STR_WEST: \"ZÁPAD\"\n  STR_NORTH_WEST: \"SEVEROZÁPAD\"\n  STR_SELECT_ACTION: \"VYBER AKCI\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"POKRAČOVAT V ÚTOKU\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"SLEDOVAT A NEÚTOČIT\"\n  STR_VERY_LARGE: \"VELMI VELKÉ\"\n  STR_LARGE: \"VELKÉ\"\n  STR_MEDIUM_UC: \"STŘEDNÍ\"\n  STR_SMALL: \"MALÉ\"\n  STR_VERY_SMALL: \"VELMI MALÉ\"\n  STR_GROUNDED: \"ZEMĚ\"\n  STR_DETECTED: \"Detekováno\"\n  STR_SIZE_UC: \"VELIKOST\"\n  STR_ALTITUDE: \"VÝŠKA\"\n  STR_HEADING: \"SMĚR\"\n  STR_SPEED: \"RYCHLOST\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"VYSTŘEDIT NA UFO-ČAS=5 sek\"\n  STR_TRACKING_LOST: \"STOPA UFO ZTRACENA\"\n  STR_REDIRECT_CRAFT: \"NOVÝ CÍL\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"LETĚT NA POSLEDNÍ ZNÁMOU POZICI UFO\"\n  STR_UFO_: \"UFO-{0}\"\n  STR_ALIEN_BASE_: \"CIZÁCKÁ ZÁKLADNA-{0}\"\n  STR_CRASH_SITE_: \"MÍSTO HAVÁRIE-{0}\"\n  STR_LANDING_SITE_: \"MÍSTO PŘISTÁNÍ-{0}\"\n  STR_WAY_POINT_: \"VYTYČENÝ BOD-{0}\"\n  STR_TERROR_SITE: \"MÍSTO TERORU-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}dosáhl místa určení:{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"Hlídkuje\"\n  STR_ALIEN_ORIGINS: \"Původ cizáků\"\n  STR_THE_MARTIAN_SOLUTION: \"Marťanské řešení\"\n  STR_CYDONIA_OR_BUST: \"Cydonie nebo zmar\"\n  STR_UFOPAEDIA: \"UFOpedie\"\n  STR_XCOM_CRAFT_ARMAMENT: \"STROJE A VÝZBROJ X-COM\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"TĚŽKÉ ZBRAŇOVÉ SYSTÉMY\"\n  STR_WEAPONS_AND_EQUIPMENT: \"ZBRANĚ A VYBAVENÍ\"\n  STR_ALIEN_ARTIFACTS: \"CIZACKÉ ARTEFAKTY\"\n  STR_BASE_FACILITIES: \"ZAŘÍZENÍ ZÁKLADNY\"\n  STR_ALIEN_LIFE_FORMS: \"CIZÁCKÉ FORMY ŽIVOTA\"\n  STR_ALIEN_RESEARCH_UC: \"CIZÁCKÝ VÝZKUM\"\n  STR_UFO_COMPONENTS: \"KOMPONENTY UFO\"\n  STR_UFOS: \"TYPY UFO\"\n  STR_SELECT_ITEM: \"VYBER POLOŽKU\"\n  STR_ACCELERATION: \"ZRYCHLENÍ>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"KAPACITA NÁDRŽE>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"NOSIČE ZBRANÍ>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"ODOLNOST PROTI POŠKOZENÍ>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"NÁKLADNÍ PROSTOR>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"MÍSTA PRO T.Z.S.>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Síla\"\n  STR_RANGE: \"Dostřel\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Přesnost\"\n  STR_RE_LOAD_TIME: \"Doba znovunabití\"\n  STR_SECONDS: \"{0}s\"\n  STR_DAMAGE_ARMOR_PIERCING: \"PRŮRAZNÉ\"\n  STR_DAMAGE_INCENDIARY: \"ZÁPALNÉ\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"EXPLOZIVNÍ\"\n  STR_DAMAGE_LASER_BEAM: \"LASEROVÝ PAPRSEK\"\n  STR_DAMAGE_PLASMA_BEAM: \"PLASMOVÝ PAPRSEK\"\n  STR_DAMAGE_STUN: \"OMRÁČENÍ\"\n  STR_DAMAGE_MELEE: \"ZBLÍZKA\"\n  STR_DAMAGE_ACID: \"KYSELINA\"\n  STR_DAMAGE_SMOKE: \"KOUŘOVÁ\"\n  STR_SHOT_TYPE: \"TYP STŘELBY\"\n  STR_ACCURACY_UC: \"PŘESNOST\"\n  STR_TIME_UNIT_COST: \"ČASOVÁ NÁROČNOST\"\n  STR_DAMAGE_UC: \"ÚČINEK\"\n  STR_AMMO: \"MUNICE\"\n  STR_SHOT_TYPE_AUTO: \"Automat\"\n  STR_SHOT_TYPE_SNAP: \"Od boku\"\n  STR_SHOT_TYPE_AIMED: \"Mířená\"\n  STR_CONSTRUCTION_TIME: \"Doba výstavby\"\n  STR_CONSTRUCTION_COST: \"Náklady na výstavbu\"\n  STR_MAINTENANCE_COST: \"Náklady na údržbu\"\n  STR_LOW: \"Nízké\"\n  STR_MEDIUM: \"Střední\"\n  STR_HIGH: \"Vysoké\"\n  STR_CRAFT_WEAPON: \"Palubní zbraň\"\n  STR_CRAFT_AMMUNITION: \"Palubní munice\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Těžký zbraňový systém\"\n  STR_WEAPON: \"Zbraň\"\n  STR_AMMUNITION: \"Munice\"\n  STR_EQUIPMENT: \"Vybavení\"\n  STR_ALIEN_CORPSE: \"Cizácká mrtvola\"\n  STR_UFO_COMPONENT: \"Komponenta UFO\"\n  STR_PERSONAL_ARMOR: \"Osobní zbroj\"\n  STR_RAW_MATERIALS: \"Suroviny\"\n  STR_HWP_CANNON_SHELLS: \"Patrona do TZS kanónu\"\n  STR_ALIEN: \"Cizák\"\n  STR_SECTOID: \"Sektan\"\n  STR_SNAKEMAN: \"Hadom\"\n  STR_ETHEREAL: \"Etheral\"\n  STR_MUTON: \"Muton\"\n  STR_FLOATER: \"Levit\"\n  STR_CELATID: \"Celatid\"\n  STR_SILACOID: \"Silakoid\"\n  STR_CHRYSSALID: \"Krysklad\"\n  STR_ZOMBIE: \"Zombie\"\n  STR_REAPER: \"Párák\"\n  STR_SECTOPOD: \"Sektopod\"\n  STR_CYBERDISC: \"Kyberdisk\"\n  STR_LIVE_COMMANDER: \"Velitel\"\n  STR_LIVE_LEADER: \"Vůdce\"\n  STR_LIVE_ENGINEER: \"Inženýr\"\n  STR_LIVE_MEDIC: \"Medik\"\n  STR_LIVE_NAVIGATOR: \"Navigátor\"\n  STR_LIVE_SOLDIER: \"Voják\"\n  STR_LIVE_TERRORIST: \"Terorista\"\n  STR_FLOATER_SOLDIER: \"Levit voják\"\n  STR_FLOATER_NAVIGATOR: \"Levit navigátor\"\n  STR_FLOATER_MEDIC: \"Levit medik\"\n  STR_FLOATER_ENGINEER: \"Levit inženýr\"\n  STR_FLOATER_LEADER: \"Levit vůdce\"\n  STR_FLOATER_COMMANDER: \"Levit velitel\"\n  STR_SECTOID_SOLDIER: \"Sektan voják\"\n  STR_SECTOID_NAVIGATOR: \"Sektan navigátor\"\n  STR_SECTOID_MEDIC: \"Sektan medik\"\n  STR_SECTOID_ENGINEER: \"Sektan inženýr\"\n  STR_SECTOID_LEADER: \"Sektan vůdce\"\n  STR_SECTOID_COMMANDER: \"Sektan velitel\"\n  STR_SNAKEMAN_SOLDIER: \"Hadom voják\"\n  STR_SNAKEMAN_NAVIGATOR: \"Hadom navigátor\"\n  STR_SNAKEMAN_ENGINEER: \"Hadom Inženýr\"\n  STR_SNAKEMAN_LEADER: \"Hadom vůdce\"\n  STR_SNAKEMAN_COMMANDER: \"Hadom velitel\"\n  STR_MUTON_SOLDIER: \"Muton voják\"\n  STR_MUTON_NAVIGATOR: \"Muton navigátor\"\n  STR_MUTON_ENGINEER: \"Muton inženýr\"\n  STR_ETHEREAL_SOLDIER: \"Etheral voják\"\n  STR_ETHEREAL_LEADER: \"Etheral vůdce\"\n  STR_ETHEREAL_COMMANDER: \"Etheral velitel\"\n  STR_CYBERDISC_TERRORIST: \"Kyberdisk terorista\"\n  STR_REAPER_TERRORIST: \"Párák terorista\"\n  STR_CHRYSSALID_TERRORIST: \"Krysklad terorista\"\n  STR_CELATID_TERRORIST: \"Celatid terorista\"\n  STR_SILACOID_TERRORIST: \"Silacoid terorista\"\n  STR_SECTOPOD_TERRORIST: \"Sektopod terorista\"\n  STR_UFO_POWER_SOURCE: \"Zdroj energie UFO\"\n  STR_UFO_NAVIGATION: \"Navigace UFO\"\n  STR_UFO_CONSTRUCTION: \"Konstrukce UFO\"\n  STR_ALIEN_FOOD: \"Cizácká potrava\"\n  STR_ALIEN_REPRODUCTION: \"Cizacké rozmnožování\"\n  STR_ALIEN_ENTERTAINMENT: \"Cizacká zábava\"\n  STR_ALIEN_SURGERY: \"Cizácká chirurgie\"\n  STR_EXAMINATION_ROOM: \"Výzkumná místnost\"\n  STR_ALIEN_ALLOYS: \"Cizácké slitiny\"\n  STR_ALIEN_HABITAT: \"Cizácké prostředí\"\n  STR_POWER_SUIT: \"Energetický skafandr\"\n  STR_FLYING_SUIT: \"Létající skafandr\"\n  STR_HWP_ROCKETS: \"Rakety do TZS\"\n  STR_HWP_FUSION_BOMB: \"Fúzní bomby do TZS\"\n  STR_LASER_WEAPONS: \"Laserové zbraně\"\n  STR_NEW_FIGHTER_CRAFT: \"Nový stíhací stroj\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Nový stíhací transportér\"\n  STR_ULTIMATE_CRAFT: \"Dokonalý stroj\"\n  STR_LASER_PISTOL: \"Laserová pistole\"\n  STR_LASER_RIFLE: \"Laserová puška\"\n  STR_HEAVY_LASER: \"Težký laser\"\n  STR_LASER_CANNON: \"Laserové dělo\"\n  STR_PLASMA_CANNON: \"Plasmové dělo\"\n  STR_FUSION_MISSILE: \"Fúzní střela\"\n  STR_LASER_DEFENSE: \"Laserová obrana\"\n  STR_PLASMA_DEFENSE: \"Plasmová obrana\"\n  STR_FUSION_DEFENSE: \"Fúzní obrana\"\n  STR_GRAV_SHIELD: \"Gravitační štít\"\n  STR_MIND_SHIELD: \"Myšlenkový štít\"\n  STR_PSI_LAB: \"Psi-laboratoř\"\n  STR_MOTION_SCANNER: \"Detektor pohybu\"\n  STR_MEDI_KIT: \"Medkit\"\n  STR_TANK_CANNON: \"Tank s dělem\"\n  STR_TANK_ROCKET_LAUNCHER: \"Tank s raketometem\"\n  STR_TANK_LASER_CANNON: \"Tank s laserovým dělem\"\n  STR_HOVERTANK_PLASMA: \"Vznášedlo s plasmou\"\n  STR_HOVERTANK_LAUNCHER: \"Vznášedlo s odpalovačem\"\n  STR_STINGRAY_LAUNCHER: \"Odpalovač střel Žihadlo\"\n  STR_AVALANCHE_LAUNCHER: \"Odpalovač střel Lavina\"\n  STR_CANNON: \"Kanón\"\n  STR_FUSION_BALL_LAUNCHER: \"Odpalovač fúzních koulí\"\n  STR_PLASMA_BEAM: \"Plasmový paprsek\"\n  STR_STINGRAY_MISSILES: \"Rakety Žihadlo\"\n  STR_AVALANCHE_MISSILES: \"Rakety Lavina\"\n  STR_CANNON_ROUNDS_X50: \"Střely do kanónu(x50)\"\n  STR_FUSION_BALL: \"Fúzní koule \"\n  STR_SOLDIER: \"Voják\"\n  STR_SCIENTIST: \"Vědec\"\n  STR_ENGINEER: \"Inženýr\"\n  STR_NORTH_AMERICA: \"Severní Amerika\"\n  STR_ARCTIC: \"Arktida\"\n  STR_ANTARCTICA: \"Antarktida\"\n  STR_SOUTH_AMERICA: \"Jižní Amerika\"\n  STR_EUROPE: \"Evropa\"\n  STR_NORTH_AFRICA: \"Severní Afrika\"\n  STR_SOUTHERN_AFRICA: \"Jižní Afrika\"\n  STR_CENTRAL_ASIA: \"Střední Asie\"\n  STR_SOUTH_EAST_ASIA: \"Jihovýchodní Asie\"\n  STR_SIBERIA: \"Sibiř\"\n  STR_AUSTRALASIA: \"Australásie\"\n  STR_PACIFIC: \"Pacifik\"\n  STR_NORTH_ATLANTIC: \"Severní Atlantik\"\n  STR_SOUTH_ATLANTIC: \"Jižní Atlantik\"\n  STR_INDIAN_OCEAN: \"Indický ocean\"\n  STR_ALIEN_RESEARCH: \"Cizácký výzkum\"\n  STR_ALIEN_HARVEST: \"Cizácké žně\"\n  STR_ALIEN_ABDUCTION: \"Cizácké únosy\"\n  STR_ALIEN_INFILTRATION: \"Cizácká infiltrace\"\n  STR_ALIEN_BASE: \"Cizacká základna\"\n  STR_ALIEN_TERROR: \"Cizácký teror\"\n  STR_ALIEN_RETALIATION: \"Cizácká odplata\"\n  STR_ALIEN_SUPPLY: \"Cizácké zásobování\"\n  STR_MAXIMUM_SPEED: \"Maximální rychlost\"\n  STR_HYPER_WAVE_DECODER_UC: \"DEKODÉR HYPER VLN\"\n  STR_SKYRANGER: \"ZÁŠKODNÍK\"\n  STR_LIGHTNING: \"BLESK\"\n  STR_AVENGER: \"MSTITEL\"\n  STR_INTERCEPTOR: \"INTERCEPTOR\"\n  STR_FIRESTORM: \"BOUŘE\"\n  STR_UFO: \"UFO\"\n  STR_STINGRAY: \"ŽIHADLO\"\n  STR_AVALANCHE: \"LAVINA\"\n  STR_CANNON_UC: \"KANÓN\"\n  STR_FUSION_BALL_UC: \"FÚZNÍ KOULE\"\n  STR_LASER_CANNON_UC: \"LASEROVÉ DĚLO\"\n  STR_PLASMA_BEAM_UC: \"PLASMOVÝ PAPRSEK\"\n  STR_DAMAGE_CAPACITY: \"Odolnost proti poškození\"\n  STR_WEAPON_POWER: \"Účinek zbraní\"\n  STR_WEAPON_RANGE: \"Dostřel\"\n  STR_ACCESS_LIFT: \"Přístupový výtah\"\n  STR_LABORATORY: \"Laboratoř\"\n  STR_WORKSHOP: \"Dílna\"\n  STR_SMALL_RADAR_SYSTEM: \"Malý radarový systém\"\n  STR_LARGE_RADAR_SYSTEM: \"Velký radarový systém\"\n  STR_MISSILE_DEFENSES: \"Raketová obrana\"\n  STR_GENERAL_STORES: \"Sklady\"\n  STR_ALIEN_CONTAINMENT: \"Cizacká cela\"\n  STR_LASER_DEFENSES: \"Laserová obrana\"\n  STR_PLASMA_DEFENSES: \"Plazmová obrana\"\n  STR_FUSION_BALL_DEFENSES: \"Fúzní obrana\"\n  STR_PSIONIC_LABORATORY: \"Psionická Laboratoř\"\n  STR_HYPER_WAVE_DECODER: \"Dekodér hyper vln\"\n  STR_HANGAR: \"Hangár\"\n  STR_USA: \"USA\"\n  STR_RUSSIA: \"RUSKO\"\n  STR_UK: \"BRITÁNIE\"\n  STR_FRANCE: \"FRANCIE\"\n  STR_GERMANY: \"NĚMECKO\"\n  STR_ITALY: \"ITÁLIE\"\n  STR_SPAIN: \"ŠPANĚLSKO\"\n  STR_CHINA: \"ČÍNA\"\n  STR_JAPAN: \"JAPONSKO\"\n  STR_INDIA: \"INDIE\"\n  STR_BRAZIL: \"BRAZÍLIE\"\n  STR_AUSTRALIA: \"AUSTRÁLIE\"\n  STR_NIGERIA: \"NIGÉRIE\"\n  STR_SOUTH_AFRICA: \"JIŽNÍ AFRIKA\"\n  STR_EGYPT: \"EGYPT\"\n  STR_CANADA: \"KANADA\"\n  STR_TANK: \"Tank\"\n  STR_CIVILIAN: \"Civilista\"\n  STR_JAN: \"Led\"\n  STR_FEB: \"Úno\"\n  STR_MAR: \"Bře\"\n  STR_APR: \"Dub\"\n  STR_MAY: \"Kvě\"\n  STR_JUN: \"Čvn\"\n  STR_JUL: \"Čvc\"\n  STR_AUG: \"Srp\"\n  STR_SEP: \"Zář\"\n  STR_OCT: \"Říj\"\n  STR_NOV: \"Lis\"\n  STR_DEC: \"Pro\"\n  STR_INTERNATIONAL_RELATIONS: \"Mezinárodní vztahy\"\n  STR_COUNTRY: \"Stát\"\n  STR_FUNDING: \"Financování\"\n  STR_CHANGE: \"Změna\"\n  STR_WEAPON_SYSTEMS: \"ZBRAŇOVÉ SYSTÉMY\"\n  STR_HWPS: \"TZS\"\n  STR_DAMAGE_UC_: \"POŠKOZENÍ>{ALT}{0}\"\n  STR_ACCESS_LIFT_UFOPEDIA: \"Přístupový výtah umožňuje transportovat vybavení a zaměstnance dovnitř či ven z podzemní základny. Je to vždy prvni zařízení, které je v nové základně postaveno. Oblast výtahu je jeden z přístupových bodů pro cizácký výsadek.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Každý obytný blok poskytuje ubytování až pro 50 osob. Mimo míst ke spánku disponuje také vybavením pro volný čas a stravovaní.\"\n  STR_LABORATORY_UFOPEDIA: \"V jedné laboratoři může pracovat až 50 vědců. Laboratoře jsou vybaveny nejmodernějšími technologiemi pro výzkům materiálů, biochemie a kosmologie. Je vám poskytnut privilegovaný přístup do nejlepších výzkumných laboratoří světa, včetně vojenských.\"\n  STR_WORKSHOP_UFOPEDIA: \"Dílna obsahuje veškeré zařízení nutné k výrobě vybavení podle plánů vytvořených ve vědeckých laboratořích. V dílně může pracovat až 50 inženýrů. Je nutné počítat s tím, že vyráběné předměty rovněž zabírají nějaké místo.\"\n  STR_SMALL_RADAR_SYSTEM_UFOPEDIA: \"Malý detekční systém disponuje radarem o efektivním dosahu 300 namořních mil, je spojen se satelitními systémy pro pozemní vyhledávání. Každý systém ma 10% šanci detekovat objekt průměrné velikosti každých 30 minut.\"\n  STR_LARGE_RADAR_SYSTEM_UFOPEDIA: \"Velký detekční systém disponuje radarem o efektivním dosahu 450 namořních mil, který je spojen se satelitními systémy pro pozemní vyhledávání. Každý systém má 20% šanci detekovat objekt průměrné velikosti každých 30 minut.\"\n  STR_MISSILE_DEFENSES_UFOPEDIA: \"Raketová obrana poskytuje částečnou ochranu před nepřátelským výsadkem, který by se pokusil přistát v blízkosti základny.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"Veškeré vybavení, zbraňové systémy, munice, posbíraný materiál a těžká zbraňová technika jsou umístěny ve skladech, včetně vybavení přiřazeného k letounům v hangárech.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"Aby bylo možné živé cizáky udržet při životě, je potřeba je umístit do speciálního prostředí. V této cele je možné v oddělených kójích zadržovat až 10 cizáckých forem života.\"\n  STR_LASER_DEFENSES_UFOPEDIA: \"Laserová obrana poskytuje dobrou ochranu před cizáckým výsadkem.\"\n  STR_PLASMA_DEFENSES_UFOPEDIA: \"Plazmová obrana poskytuje výkonnou a efektivní ochranu před cizáckým výsadkem.\"\n  STR_FUSION_BALL_DEFENSES_UFOPEDIA: \"Fúzní střely poskytují nejefektivnější možnou obranu před cizackými výsadky. Tyto střely vytvářejí implozi antihmoty, která ničí vše v dosahu.\"\n  STR_GRAV_SHIELD_UFOPEDIA: \"Gravitační štít znesnadňuje přistání cizáckého stroje a následný útok na základnu natolik, že veškeré obranné systemy mohou vystřelit dvakrát.\"\n  STR_MIND_SHIELD_UFOPEDIA: \"Detekce lidské přítomnosti cizáckými loděmi je založena na mozkových vlnách. Proto je nejefektivnějším opatřením odstínit mozkové vlny ze základny. Toto zařízení výrazně sníži šanci cizácké lodě odhalit základnu.\"\n  STR_PSIONIC_LABORATORY_UFOPEDIA: \"Psionická laboratoř umožňuje odhalit psionické nadání jakéhokoliv vojáka v základně a poskytnout mu nutný výcvik pro využití jeho psionických dovedností. Každá laboratoř může najednou cvičit až 10 vojáků. Výcvik je rozvržen vždy na konci měsíce. Bojové využití psioniky umožňuje zařízení Psi-amp.\"\n  STR_HYPER_WAVE_DECODER_UFOPEDIA: \"Cizácká komunikace využívá hyper-dimenzionální vlny, které se šíří prakticky okamžitě. Zařízení dekodéru zachytává vysílání UFO a dekóduje informace. Tak lze odhalit typ UFO, cizáckou rasu a typ aktivity.\"\n  STR_HANGAR_UFOPEDIA: \"V každém hangáru muže být umístěn jeden stroj. Je v něm umístěno též vybavení pro udržbu, tankovaní a opravu stroje. Každý stroj umístněný na základně musí mít svůj vlastní hangár, který nemůže být současně využíván jiným strojem, a to ani tehdy, je-li přiřazený stroj právě na misi mimo základnu.\"\n  STR_PISTOL_UFOPEDIA: \"Standardní pistole X-Com je vysoce výkonná, poloautomatická zbraň, se zásobníkem na 12 nábojů.\"\n  STR_RIFLE_UFOPEDIA: \"Tato vysoce přesná odstřelovací puška má laserový zameřovač a zasobník na 20 nábojů ráže 6.7mm.\"\n  STR_HEAVY_CANNON_UFOPEDIA: \"Težký kanón(TK) je ničivou, avšak těžkopádnou zbraní. Umožnuje střílet třemi typy munice - průbojnou, zápalnou a explozivní.\"\n  STR_AUTO_CANNON_UFOPEDIA: \"Gatling (GT) kombinuje všestrannost a sílu těžkého kanónu s rychlejší kadencí.\"\n  STR_ROCKET_LAUNCHER_UFOPEDIA: \"Ruční raketomet je laserem naváděný systém, schopný odpalovat tři různé typy raket.\"\n  STR_LASER_PISTOL_UFOPEDIA: \"Laserová pistole je efektivní implementací nové technologie. Kombinuje výhody pistole s rychlejší a přesnější střelbou.\"\n  STR_LASER_RIFLE_UFOPEDIA: \"Laserová puška je silnější a přesnější verzí předešlého návrhu pistole.\"\n  STR_HEAVY_LASER_UFOPEDIA: \"Težký laser je těžkopádný, ale extrémně efektivní.\"\n  STR_GRENADE_UFOPEDIA: \"Tento standardní granát má přesný časovač pro precizní načasování výbuchu.\"\n  STR_SMOKE_GRENADE_UFOPEDIA: \"Kouřové granáty jsou vhodné pro krytí v otevřeném terénu. Je třeba ale počítat s tím, že poskytují krytí oběma stranám. \"\n  STR_PROXIMITY_GRENADE_UFOPEDIA: \"Miny mohou být vrženy stejně jako běžný granát, ale po dopadu jsou aktivovány blízkým pohybem. Pro správné použití těchto zařízení je nutný dostatek dovednosti a opatrnosti.\"\n  STR_HIGH_EXPLOSIVE_UFOPEDIA: \"Tato výbušnina je určena pro demoliční účely. Obsluha se musí zdržovat v dostatečné vzdálenosti od demolovaných objektů.\"\n  STR_MOTION_SCANNER_UFOPEDIA: \"Toto sofistikované zařízení používá rozmanitých detektorů a počítačových algoritmů k identifikaci pohybujících se nepřátelských jednotek. Nicméně k efektivnímu využití je třeba určité praxe. Na taktické obrazovce klikněte na ikonu skaneru pohybu. Z menu vyberte 'Použít skaner'. Displej skaneru zobrazuje ve středu šipku, která určike natočení vojáka (nahoře je sever). Blikající tečky značí jednotky, které se nedávno pohnuly. Velké nebo rychle se pohybující jednotky jsou znázorněny většími tečkami. Statické jednotky nejsou detekovány.\"\n  STR_MEDI_KIT_UFOPEDIA: \"Medkit kombinuje léčivé prostředky s analgetiky a stimulanty. Pro správné použití medkitu je nutné být natočen k ošetřovanému vojákovi. Je-li voják ochromen, je nutné stát nad jeho tělem. Klikněte na ikonu medkitu a zvolte v menu položku 'použít medkit'.{NEWLINE}UZDRAVIT> Červené části těla utrpěly smrtelná zranění. Klikněte na zraněnou část těla, pak na tlačítko 'Léčba'. To vyléčí cíli jedno ze smrtelných zranění a obnoví část zdraví.{NEWLINE}STIMULOVAT> Obnoví energii a probere vojáka z bezvědomí (omráčení). Aby bylo možné probrat vojáka z bezvědomí, je nutné stát přesně nad jeho tělem.{NEWLINE}UTIŠIT> Obnoví morálku zraněného vojáka až na hranici ekvivalentní ztraceného zdraví.\"\n  STR_PSI_AMP_UFOPEDIA: \"Psi-amp mohou používat pouze vojáci kteří prošli psionickým výcvikem. Během boje klikněte na Psi-amp, vyberte typ útoku a pak vyberte cíl pomocí kurzoru. K dispozici jsou dva typy psionických útoků:{NEWLINE}ZPANIKAŘIT> Je-li útok úspěšný, morálka cíle klesne a může způsobit že zpanikaří.{NEWLINE}OVLÁDNUTÍ MYSLI> Je-li toto úspěšné, okamžitě získáváte kontrolu nad cílem, jakoby to byla jedna z vaších jednotek. Tento typ útoku je náročnější.\"\n  STR_STUN_ROD_UFOPEDIA: \"Toto zařízení může být použito pouze v boji zblízka. Ochromí, ale nezabije, nepřítele silným elektrickým výbojem.\"\n  STR_MIND_PROBE_UFOPEDIA: \"Čtečka mysli je cizácké komunikační zařízení, používané ke čtení informací přímo z mozku. Jednotky X-Com mohou použít toto zařízení v boji k získání charakteristiky cizáka. Klikněte na čtečku mysli, poté na volbu \\\"Použít čtečku mysli\\\". Pak umístěte kurzor na cizáka a znovu klikněte.\"\n  STR_PLASMA_PISTOL_UFOPEDIA: \"Plazmové pistole jsou smrtící cizácké zbraně, založené na částicích akcelerovaných v dočasném antigravitačním poli.\"\n  STR_PLASMA_RIFLE_UFOPEDIA: \"Tato zkázonosná zbraň je založena na částicích akcelerovaných v dočasném antigravitačním poli.\"\n  STR_HEAVY_PLASMA_UFOPEDIA: \"Tato ničivá zbraň je založená na akcelerování částic v dočasném antigravitačním poli.\"\n  STR_BLASTER_LAUNCHER_UFOPEDIA: \"Jde o odpalovač cizáckých naváděných střel, střílející výkonné \\\"ďábelské bomby\\\". Vystřelíte-li z této zbraně, budete moci určit body trajektorie střely. Po naplánování trajektorie klikněte na speciální odpalovací ikonu.\"\n  STR_SMALL_LAUNCHER_UFOPEDIA: \"Malý odpalovač, střílející ochromující bomby. Velmi užitečné pro zajímání živých cizáků.\"\n  STR_ALIEN_GRENADE_UFOPEDIA: \"Toto zařízení funguje stejně jako pozemský granát - pouze je výkonnější.\"\n  STR_SMALL_SCOUT: \"Malý zvěd\"\n  STR_MEDIUM_SCOUT: \"Střední zvěd\"\n  STR_LARGE_SCOUT: \"Velký zvěd\"\n  STR_HARVESTER: \"Kombajn\"\n  STR_ABDUCTOR: \"Uchvatitel\"\n  STR_TERROR_SHIP: \"Teroristická loď\"\n  STR_BATTLESHIP: \"Bitevní loď\"\n  STR_SUPPLY_SHIP: \"Zásobovací loď\"\n  STR_RATING: \"HODNOCENÍ> {0}\"\n  STR_RATING_TERRIBLE: \"OTŘESNÉ!\"\n  STR_RATING_POOR: \"UBOHÉ!\"\n  STR_RATING_OK: \"OK\"\n  STR_RATING_GOOD: \"DOBRÉ!\"\n  STR_RATING_EXCELLENT: \"VÝBORNÉ!\"\n  STR_SCORE: \"SKÓRE\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"MĚSÍČNÍ HLÁŠENÍ PROJEKTU X-COM\"\n  STR_MONTH: \"Měsíc> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"Rada členských států je celkem spokojena s vaším pokrokem.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"Rada členských států je velmi potěšena vaším výborným dosavadním pokrokem. Pokračujte v kvalitní práci.\"\n  STR_COUNCIL_IS_DISSATISFIED: \"Rada členských států je nespokojena s vaším výkonem. Pokud nezvýšíte efektivitu v boji s cizáckou hrozbou, bude projekt X-Com ukončen.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"Neuspěl jste v boji s cizáckou invazí a rada členských států se neodvolatelně rozhodla ukončit projekt X-Com. Každý stát se vypořádá s problémem dle svého mínění. Můžeme pouze doufat, že s těmito zjevně nepřátelskými silami nalezneme nějaký modus vivendi a že obyvatelstvo přistoupí na podmínky cizáckých návštěvníků.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} obzvlášť vyjadřuje spokojenost s vaší schopností se vypořádat s lokálním ohrožením a zvyšuje své příspěvky.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} jsou obzvláště spokojeni s vaším pokrokem s lokální invazí a souhlasí se zvýšením financování.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} a {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} projevuje nespokojenost s vaší schopností poradit si s aktivitou cizaků na jejich území a proto snížuje své finanční příspěvky.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} nejsou spokojeni s vaší schopností poradit si s aktivitou cizaků na jejich územích a proto se rozhodli snížit své finanční příspěvky.\"\n  STR_KNOTS: \"{0} uzlů\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0}: Byla podepsána tajná dohoda s neznámymi cizáckými silami a od projektu X-Com bylo odstoupeno.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0}: Byly podepsány tajné dohody s neznámymi cizáckými silami a z projektu X-Com bylo odstoupeno.\"\n  STR_MONTHLY_RATING: \"Měsíční hodnocení> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Změna financování> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"Společenství financujících národů není spokojeno s vaší finanční situací. Musíte své dluhy zredukovat pod $1 million dolarů, jinak bude projekt ukončen.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"VYSÍLÁNÍ NA HYPER VLNÁCH JE DEKÓDOVÁNO\"\n  STR_CRAFT_TYPE: \"TYP STROJE\"\n  STR_RACE: \"RASA\"\n  STR_MISSION: \"MISE\"\n  STR_ZONE: \"ZÓNA\"\n  STR_ALLOCATE_RESEARCH: \"Přidělit výzkum\"\n  STR_ALLOCATE_MANUFACTURE: \"Naplánovat výrobu\"\n  STR_NEW_YORK: \"New York\"\n  STR_WASHINGTON: \"Washington\"\n  STR_LOS_ANGELES: \"Los Angeles\"\n  STR_MONTREAL: \"Montréal\"\n  STR_HAVANA: \"Havana\"\n  STR_MEXICO_CITY: \"Mexico City\"\n  STR_CHICAGO: \"Chicago\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_DALLAS: \"Dallas\"\n  STR_BRASILIA: \"Brazílie\"\n  STR_BOGOTA: \"Bogota\"\n  STR_BUENOS_AIRES: \"Buenos Aires\"\n  STR_SANTIAGO: \"Santiago\"\n  STR_RIO_DE_JANEIRO: \"Rio De Janeiro\"\n  STR_LIMA: \"Lima\"\n  STR_CARACAS: \"Caracas\"\n  STR_LONDON: \"Londýn\"\n  STR_PARIS: \"Paříž\"\n  STR_BERLIN: \"Berlín\"\n  STR_MOSCOW: \"Moskva\"\n  STR_ROME: \"Řím\"\n  STR_MADRID: \"Madrid\"\n  STR_BUDAPEST: \"Budapešť\"\n  STR_LAGOS: \"Lagos\"\n  STR_CAIRO: \"Káhira\"\n  STR_CASABLANCA: \"Casablanka\"\n  STR_PRETORIA: \"Pretoria\"\n  STR_NAIROBI: \"Nairobi\"\n  STR_CAPE_TOWN: \"Kapské město\"\n  STR_KINSHASA: \"Kinshasa\"\n  STR_ANKARA: \"Ankara\"\n  STR_DELHI: \"Dillí\"\n  STR_KARACHI: \"Karáčí\"\n  STR_BAGHDAD: \"Bagdád\"\n  STR_TEHRAN: \"Teherán\"\n  STR_BOMBAY: \"Bombaj\"\n  STR_CALCUTTA: \"Kalkata\"\n  STR_TOKYO: \"Tokio\"\n  STR_BEIJING: \"Peking\"\n  STR_BANGKOK: \"Bangkok\"\n  STR_MANILA: \"Manila\"\n  STR_SEOUL: \"Soul\"\n  STR_SINGAPORE: \"Singapur\"\n  STR_JAKARTA: \"Jakarta\"\n  STR_SHANGHAI: \"Šangaj\"\n  STR_HONG_KONG: \"Hong Kong\"\n  STR_NOVOSIBIRSK: \"Novosibirsk\"\n  STR_CANBERRA: \"Canberra\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_MELBOURNE: \"Melbourne\"\n  STR_PERTH: \"Perth\"\n  STR_PSI_TRAINING: \"Psionický výcvik\"\n  STR_PSIONIC_TRAINING: \"PSIONICKÝ VÝCVIK\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Volné místo v psionické laboratoři> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"Psionická{NEWLINE}síla\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"Psion. dovednost{NEWLINE}/zlepšení\"\n  STR_PSI_AMP: \"Psi-amp\"\n  STR_IN_TRAINING: \"Má{NEWLINE}trénovat?\"\n  STR_TARGETTED_BY: \"ZACÍLENO:\"\n  STR_WEAPONS_CREW_HWPS: \"ZBRANĚ/{NEWLINE}POSÁDKA/TZS\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"má málo paliva,{NEWLINE}navrací se na základnu\"\n  STR_SOLDIER_LIST: \"Seznam vojáků\"\n  STR_RANK_: \"HODNOST> {ALT}{0}\"\n  STR_MISSIONS: \"MISÍ> {ALT}{0}\"\n  STR_KILLS: \"ZABITÍ> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"UZDRAVENÍ ZRANĚNÍ> {ALT}{0}\"\n  STR_TIME_UNITS: \"ČASOVÝCH JEDNOTEK\"\n  STR_STAMINA: \"ENERGIE\"\n  STR_HEALTH: \"ZDRAVÍ\"\n  STR_BRAVERY: \"ODVAHA\"\n  STR_REACTIONS: \"REAKCE\"\n  STR_FIRING_ACCURACY: \"PŘESNOST STŘELBY\"\n  STR_THROWING_ACCURACY: \"PŘESNOST HODU\"\n  STR_STRENGTH: \"SÍLA\"\n  STR_PSIONIC_STRENGTH: \"PSIONICKÁ SÍLA\"\n  STR_PSIONIC_SKILL: \"PSIONICKÁ DOVEDNOST \"\n  STR_NEW_RANK: \"NOVÁ HODNOST\"\n  STR_PROMOTIONS: \"Povýšení\"\n  STR_SOLDIERS_UC: \"VOJÁCI\"\n  STR_TANK_CANNON_UFOPEDIA: \"Automatizovaná těžká technika je navržena pro podporu vojáků X-Com. Kombinace těžkých zbraní a silného pancéřování činí tyto jednotky cennými pomocníky pro boj v otevřeném terénu. Ujistěte se jen, že máte ve skladech dostatek dělových nábojů pro plné znovuvyzbrojení tanků. Tanky jsou vyzbrojovány automaticky, jakmile je přidělíte k jednotce.\"\n  STR_TANK_ROCKET_LAUNCHER_UFOPEDIA: \"Tato automatizovaná těžká technika je vyzbrojena výkonnými raketami s ničivým účinkem proti jakémukoliv cizáckému cíli. Je ale nutné zajistit dostatečnou zásobu příslušných raket ve vašich skladech.\"\n  STR_TANK_LASER_CANNON_UFOPEDIA: \"Laserové zbraně jsou výtečným vylepšením TZS. Kombinují vysoký účinek střelby s neomezenou municí.\"\n  STR_HOVERTANK_PLASMA_UFOPEDIA: \"Cizacké technologie vdechly nový život těžkým zbraňovým systémům. Zvýšená manévrovatelnost díky anti-gravitaci a síla plasmových svazků, jsou vskutku smrtelnou kombinací.\"\n  STR_HOVERTANK_LAUNCHER_UFOPEDIA: \"Tento anti-gravitační tank je vyzbrojen odpalovačem extrémně ničivých fúzních koulí. Používejte je s velkou opatrností. Pro tento TZS je nutné vyrobit fúzní koule. Fúzní koule je inteligentně naváděná zbraň. Vytyčte body trajektorie střely a poté klikněte na ikonu odpálení.\"\n  STR_HEAVY_PLASMA_CLIP_UFOPEDIA: \"Toto kompaktní zařizení slouží jako zasobník pro plazmový kulomet. Obsahuje malé množství Eleria.\"\n  STR_PLASMA_RIFLE_CLIP_UFOPEDIA: \"Tento malý předmět slouží jako zdroj energie pro plazmovou pušku - středně výkonnou cizáckou zbraň. Obsahuje malé množství Eleria.\"\n  STR_PLASMA_PISTOL_CLIP_UFOPEDIA: \"Zdroj energie pro malou cizáckou pistoli. Obsahuje Elerium - zdroj veškeré cizácké energie.\"\n  STR_STUN_BOMB_UFOPEDIA: \"Ochromující bomba je používána cizáky k zajímání živých lidských exemplařů, nic ale nevylučuje její použití proti většině cizáckých ras. Je vystřelována z Malého odpalovače.\"\n  STR_ALIEN_RESEARCH_UFOPEDIA: \"Cizácká výzkumná mise shromažďuje základní data o Zemi a jejich obyvatelích. Jsou používány především malá plavidla, která občas přistávají na opuštěných místech. Tento typ cizácké aktivity představuje pro X-Com nejmenší nebezpečí a je mu věnováná malá pozornost ze strany vlád i veřejnosti.\"\n  STR_ALIEN_HARVEST_UFOPEDIA: \"Cizáci mají pro pozemskou faunu mnoho využití. Zvířata jsou tajně unášena, a poté nacházena s chybějícími orgány. Znetvoření skotu jsou hlášena především v oblastech, kde jsou často hlášeny i pozorování UFO. Tento druh cizácké aktivity způsobuje u vlád a veřejnosti velké obavy a znepokojení. Odehrává se především v zemědělské krajině. Teorie o 'cizácké sklizni' naznačuje, že cizáci původně 'osili' naši planetu svou florou a faunou a nyní se vrátili, aby svou úrodu sklidili.\"\n  STR_ALIEN_ABDUCTION_UFOPEDIA: \"Toto je nejzákeřnější forma cizácké aktivity. Únosy cizáky jsou hlášeny z mnoha míst, bez ohledu na pokusy cizáků vymazat zážitky z paměti obětí. Unešení hlásí, že byli oběťmi ponižujících fyzických výzkumů, včetně oplodnění cizáckými zárodky a hrůzných genetických experimentů. Účel těchto aktivit se zdá být spojen s genetickými mutacemi a manipulacemi s jejich vlastním cizáckým genetickým materiálem. Tato aktivita způsobuje významný rozruch; odehrává se v obydlených oblastech nebo městech.\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"Pozemnské vlády mohou být infiltrovány cizáckými agenty s lidským vzhledem. To může vést k oficiálním jednáním mezi cizáky a vládami na nejvyšší úrovni. Vyvrcholení této aktivity je charakterizováno intenzivní činnosti UFO v blízkosti velkých měst. Cizáci se pokusí uzavřít s pozemní vládou smlouvu, ve které nabídnou své znalosti a vyspělé technologie. Vláda na oplátku povolí cizákům provozovat nerušeně jejich činnost. Tyto cizácké mise představují pro X-Com největší nebezpečí. Pokud vláda podepíše pakt, ukončí financování projektu.\"\n  STR_ALIEN_BASE_UFOPEDIA: \"Cizáci staví tajné podzemní základny na odlehlých místech. Po několika počátečních průzkumných letech dojde v důsledku budování základny k intenzivní aktivitě UFO. Je známo, že tyto základny obsahují experimentální laboratoře pro unesené lidi a zásoby pro další aktivitu v oblasti. Přítomnost cizácké základny zvyšuje cizáckou aktivitu v oblasti, aniž by byly hlášeny výskyty UFO. Aby bylo možné zjistit polohu základny, musí stroj X-Com střežit oblast po dobu několika hodin.\"\n  STR_ALIEN_TERROR_UFOPEDIA: \"Když cizáci terorizují město, vysazují zvláštní jednotky s hrůznými schopnostmi. Civilisté jsou v přímém ohrožení a vlády jsou přinuceny evakuovat celé oblasti. Hlavní smyslem těchto útoků je však způsobit hysterii a přimět tak vlády omezit podporu projektu X-Com.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"Jsou-li stíhače X-Com zvláště úspěšné v sestřelování UFO, mohou cizáci zahájit odvetnou akci. To může vést až k přímému útoku na základnu X-Com. Nicméně cizáci musí nejprve základnu najít. Pokud jsou UFO úspěšně odrážena, je toto nebezpečí malé.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"Jakmile je cizácká základna postavena, je pravidelně zásobována specializovanými zásobovacími plavidly. Je-li detekováno přistání některé z těchto lodí, je téměř jisté, že se v blízkosti nachází cizácká základna.\"\n  STR_SMALL_SCOUT_UFOPEDIA: \"Tento maličký stroj je primárně užíván k průzkumným a výzkumným účelům. Obvykle je používán jako předvoj před většími loděmi.\"\n  STR_MEDIUM_SCOUT_UFOPEDIA: \"Středně velká průzkumná loď nepředstavuje pro pozemské sily významné nebezpečí. Obvykle je používán jako předvoj před většími loděmi.\"\n  STR_LARGE_SCOUT_UFOPEDIA: \"Největší cizácká průzkumná loď je používána pro všechny typy cizackých misí.\"\n  STR_HARVESTER_UFOPEDIA: \"Kombajn má na spodní straně padací dveře a je vybaven výtahem pro vyzdvihování dobytka nebo jiných zvířat. Laserové skalpely se používají pro získání požadovaného materiálu a mršina je vyhozena zpět na zem. Na lodi lze též nalézt skladovací kontejnery pro získaný materiál. \"\n  STR_ABDUCTOR_UFOPEDIA: \"Tato loď je vybavena výzkumnou místností pro provádění hrůzných experimentů na lidských jedincích. Oběť je úplně paralyzována telepatickými silami, ale zůstává při vědomí dokonce i na operačním stole.\"\n  STR_TERROR_SHIP_UFOPEDIA: \"Teroristická loď je vybavena kontejnery pro velké cizácké teroristické zbraně nebo kreatury. Používá se k jejich transportu do osídlených oblastí.\"\n  STR_BATTLESHIP_UFOPEDIA: \"Bitevní loď je největším a nejsilnějším cizáckým strojem. Je obvykle hlavní lodí cizáckých misí; je vybavena ničivými zbraněmi a početnou posádkou.\"\n  STR_SUPPLY_SHIP_UFOPEDIA: \"Zásobovací loď je používána během konstruování cizáckých základen nebo pro zásobování základen již existujících. Přepravuje kontejnery s cizáckou potravou a reprodukční komory.\"\n  STR_DISMANTLE: \"Odstranit:\"\n  STR_FACILITY_IN_USE: \"ZAŘÍZENÍ JE POUŽÍVÁNO\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"ZAŘÍZENÍ NELZE ODSTRANIT!{SMALLLINE}Každé zařízení v základně musí mít spojení s přístupovým výtahem.\"\n  STR_TRANSFER_ITEMS_TO: \"Přesun položek do {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"CHYBÍ CELA PRO CIZÁKY!{SMALLLINE}Živí cizáci potřebují pro své přežití speciální celu.\"\n  STR_AMOUNT_AT_DESTINATION: \"MNOŽTVÍ{NEWLINE}V CÍLI\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"Cizák zemřel, neboť není k dispozici cizácká cela\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"OBYTNÝ PROSTOR JE PLNÝ!{SMALLLINE}Cílová základna nemá dostatek místa v obytných buňkách pro posádku stroje.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"NEDOSTATEK MÍSTA! {SMALLLINE} Cílová základna nemá dostatek místa pro vybavení přiděleného stroje.\"\n  STR_ITEMS_ARRIVING: \"Dodané předměty\"\n  STR_DESTINATION_UC: \"CÍL\"\n  STR_PISTOL: \"Pistole\"\n  STR_PISTOL_CLIP: \"Zásobník pistole\"\n  STR_RIFLE: \"Puška\"\n  STR_RIFLE_CLIP: \"Zásobník pušky\"\n  STR_HEAVY_CANNON: \"Těžký kanón\"\n  STR_HC_AP_AMMO: \"TK-průbojné\"\n  STR_HC_HE_AMMO: \"TK-explozivní\"\n  STR_HC_I_AMMO: \"TK-zápalné\"\n  STR_AUTO_CANNON: \"Gatling\"\n  STR_AC_AP_AMMO: \"GT-průbojné\"\n  STR_AC_HE_AMMO: \"GT-explozivní\"\n  STR_AC_I_AMMO: \"GT-zápalné\"\n  STR_ROCKET_LAUNCHER: \"Ruční raketomet\"\n  STR_SMALL_ROCKET: \"Malá raketa\"\n  STR_LARGE_ROCKET: \"Velká raketa\"\n  STR_INCENDIARY_ROCKET: \"Zápalná raketa\"\n  STR_GRENADE: \"Granát\"\n  STR_SMOKE_GRENADE: \"Kouřový granát\"\n  STR_PROXIMITY_GRENADE: \"Mina\"\n  STR_HIGH_EXPLOSIVE: \"Silná výbušnina\"\n  STR_STUN_ROD: \"Elektrický obušek\"\n  STR_HEAVY_PLASMA: \"Plazmový kulomet\"\n  STR_HEAVY_PLASMA_CLIP: \"Zásobník plazm. kulometu\"\n  STR_PLASMA_RIFLE: \"Plazmová puška\"\n  STR_PLASMA_RIFLE_CLIP: \"Zásobník plazmové pušky\"\n  STR_PLASMA_PISTOL: \"Plazmová pistole\"\n  STR_PLASMA_PISTOL_CLIP: \"Zásobník plazmové pistole\"\n  STR_BLASTER_LAUNCHER: \"Ďábelský odpalovač\"\n  STR_BLASTER_BOMB: \"Ďábelská bomba\"\n  STR_SMALL_LAUNCHER: \"Malý odpalovač\"\n  STR_STUN_BOMB: \"Ochromující bomba\"\n  STR_ALIEN_GRENADE: \"Cizácký granát\"\n  STR_ELERIUM_115: \"Elerium-115\"\n  STR_MIND_PROBE: \"Čtečka mysli\"\n  STR_SECTOID_CORPSE: \"Mrtvola sektana\"\n  STR_SNAKEMAN_CORPSE: \"Mrtvola hadoma\"\n  STR_ETHEREAL_CORPSE: \"Mrtvola etherala\"\n  STR_MUTON_CORPSE: \"Mrtvola mutona\"\n  STR_FLOATER_CORPSE: \"Mrtvola levita\"\n  STR_CELATID_CORPSE: \"Mrtvola celatida\"\n  STR_SILACOID_CORPSE: \"Mrtvola silacoida\"\n  STR_CHRYSSALID_CORPSE: \"Mrtvola krysklada\"\n  STR_REAPER_CORPSE: \"Mrtvola páráka\"\n  STR_SECTOPOD_CORPSE: \"Mrtvola sektopoda\"\n  STR_CYBERDISC_CORPSE: \"Mrtvola kyberdisku\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"Nedostatek munice pro TZS{SMALLLINE}Pro každý TZS je třeba {0} {1}.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Nedostatek vybavení k plnému znovuvybavení jednotky\"\n  STR_MARS_CYDONIA_LANDING: \"Mars: přistání v Cydonii\"\n  STR_MARS_CYDONIA_LANDING_BRIEFING: \"Váš Mstitel přistál v oblasti Cydonie na povrchu Marsu. Naše informace ukazují, že jedna z pyramidových konstrukcí obsahuje zelený přístupový výtah do podzemního komplexu. Jakmile shromáždíte všechny své vojáky v oblasti výtahu, klikněte na ikonu 'Zrušit misi'. Budete pokračovat další fází.\"\n  STR_MARS_THE_FINAL_ASSAULT: \"Mars: konečný útok\"\n  STR_MARS_THE_FINAL_ASSAULT_BRIEFING: \"Výtah v pyramidě dopravil vaše bitvami protřelé vojáky hluboko pod povrch planety. Ocitli se v srdci rozlehlého komplexu tunelů a místností. Cizácký mozek je ukryt někde v tomto labyrintu. Má-li být Země uchráněna před cizáckou porobou, musí být mozek zničen.{NEWLINE}{NEWLINE}Mnoho štěstí!\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Je nutné vyzkoumat{NEWLINE}{0}{NEWLINE}, aby bylo možné vyrobit{NEWLINE}{1}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"Cizáci zničili nebráněnou základnu {0}\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"Agenti X-Com lokalizovali cizáckou základnu v oblasti {0}\"\n  STR_STANDOFF: \"DISTANCE\"\n  STR_CAUTIOUS_ATTACK: \"OPATRNÝ ÚTOK\"\n  STR_STANDARD_ATTACK: \"STANDARDNÍ ÚTOK\"\n  STR_AGGRESSIVE_ATTACK: \"AGRESIVNÍ ÚTOK\"\n  STR_DISENGAGING: \"ODPOUTÁNÍ\"\n  STR_UFO_HIT: \"UFO ZASAŽENO!\"\n  STR_UFO_CRASH_LANDS: \"UFO HAVAROVALO!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Minimalizace pouze na distanční vzdálenosti\"\n  STR_UFO_RETURN_FIRE: \"UFO OPĚTUJE PALBU\"\n  STR_INTERCEPTOR_DAMAGED: \">>> STÍHAČKA POŠKOZENA <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> STÍHAČKA ZNIČENA <<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"UFO UNIKÁ STÍHAČCE!\"\n  STR_ALIENS_TERRORISE: \"CIZÁCI TERORIZUJÍ\"\n  STR_LONG_RANGE_DETECTION: \"Detekce velkého dosahu\"\n  STR_STORES_UC: \"SKLADY\"\n  STR_DIFFICULTY_LEVEL: \"Úroveň obtížnosti\"\n  STR_INTERCEPT: \"PRONÁSLEDOVAT\"\n  STR_BASES: \"ZÁKLADNY\"\n  STR_GRAPHS: \"GRAFY\"\n  STR_UFOPAEDIA_UC: \"UFOPEDIE\"\n  STR_OPTIONS_UC: \"MOŽNOSTI\"\n  STR_FUNDING_UC: \"FINANCOVÁNÍ\"\n  STR_5_SECONDS: \"5 sek\"\n  STR_1_MINUTE: \"1 min\"\n  STR_5_MINUTES: \"5 min\"\n  STR_30_MINUTES: \"30 min\"\n  STR_1_HOUR: \"1 hod\"\n  STR_1_DAY: \"1 den\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"Rozpiska výkonu X-Com\"\n  STR_ENTER_NAME: \"Vlož jméno\"\n  STR_PERFORMANCE_RATING: \"Hodnocení výkonu\"\n  STR_VICTORY_DATE: \"Datum vítězství\"\n  STR_ELECTRO_FLARE: \"Světlice\"\n  STR_ELECTRO_FLARE_UFOPEDIA: \"Po dopadu vyzařuje toto kompaktní zařízení jasné světlo. Umožňuje tak osvětlit nepřátelské jednotky v jeho blízkosti během nočních misí.\"\n  STR_MONTHLY_COSTS: \"Měsíční náklady\"\n  STR_CRAFT_RENTAL: \"Pronájem letadel\"\n  STR_SALARIES: \"Platy\"\n  STR_BASE_MAINTENANCE: \"Údržba základny \"\n  STR_COST_PER_UNIT: \"Cena za jednotku\"\n  STR_QUANTITY: \"Množství\"\n  STR_TOTAL: \"Celkem\"\n  STR_IN_PSIONIC_TRAINING: \"V psionickém výcviku\"\n  STR_BLASTER_BOMB_UFOPEDIA: \"Toto zařízení je vysoce explozivní střelou s inteligentním naváděcím systémem. Je vystřelována z Ďábelského odpalovače.\"\n  STR_FRONT_ARMOR: \"Přední zbroj\"\n  STR_LEFT_ARMOR: \"Levá zbroj\"\n  STR_RIGHT_ARMOR: \"Pravá zbroj\"\n  STR_REAR_ARMOR: \"Zadní zbroj\"\n  STR_UNDER_ARMOR: \"Spodní zbroj\"\n  STR_ROUNDS: \"Nábojů\"\n  STR_UNIT: \"JEDNOTKA> {0}\"\n  STR_ENERGY: \"ENERGIE\"\n  STR_MORALE: \"MORÁLKA\"\n  STR_ARMOR_: \"ZBROJ> {0}\"\n  STR_FRONT_ARMOR_UC: \"PŘEDNÍ ZBROJ\"\n  STR_LEFT_ARMOR_UC: \"LEVÁ ZBROJ\"\n  STR_RIGHT_ARMOR_UC: \"PRAVÁ ZBROJ\"\n  STR_REAR_ARMOR_UC: \"ZADNÍ ZBROJ\"\n  STR_SKILLS: \"DOVEDNOSTI> {0}\"\n  STR_LEVEL: \"ÚROVEŇ> {0}\"\n  STR_HEAD: \"HLAVA\"\n  STR_TORSO: \"TĚLO\"\n  STR_RIGHT_ARM: \"PRAVÁ PAŽE\"\n  STR_LEFT_ARM: \"LEVÁ PAŽE\"\n  STR_RIGHT_LEG: \"PRAVÁ NOHA\"\n  STR_LEFT_LEG: \"LEVÁ NOHA\"\n  STR_PAIN_KILLER: \"UTIŠIT\"\n  STR_STIMULANT: \"STIMULOVAT\"\n  STR_HEAL: \"UZDRAVIT\"\n  STR_TIME_UNITS_SHORT: \"ČJ>{ALT}{0}\"\n  STR_WEIGHT: \"Zátěž>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"Reak.>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"P.Dov.>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"P.Síla>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Cizácký artefakt\"\n  STR_AMMO_ROUNDS_LEFT: \"NÁBOJE:{NEWLINE}ZBÝVÁ{NEWLINE}VÝSTŘELŮ={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Utišovač>{ALT}{0}{ALT}{NEWLINE}Stimulant>{ALT}{1}{ALT}{NEWLINE}Léčení>{ALT}{2}\"\n  STR_THROW: \"Hodit\"\n  STR_AUTO_SHOT: \"Automat\"\n  STR_SNAP_SHOT: \"Od boku\"\n  STR_AIMED_SHOT: \"Zamířit\"\n  STR_STUN: \"Omráčit\"\n  STR_PRIME_GRENADE: \"Odjistit granát\"\n  STR_USE_SCANNER: \"Použít skener\"\n  STR_USE_MEDI_KIT: \"Použít Medkit\"\n  STR_LAUNCH_MISSILE: \"Vypustit střelu\"\n  STR_ACCURACY_SHORT: \"Zás>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Nedostatek časových jednotek!\"\n  STR_NOT_ENOUGH_ENERGY: \"Nedostatek energie!\"\n  STR_NO_ROUNDS_LEFT: \"Došly náboje!\"\n  STR_NO_AMMUNITION_LOADED: \"Není nabito!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Munice neodpovídá typu zbraně!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"Zbraň je již nabitá!\"\n  STR_NO_LINE_OF_FIRE: \"Překažka v linii střelby!\"\n  STR_GRENADE_IS_ACTIVATED: \"Granát je odjištěn!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Granát zajištěn!\"\n  STR_THERE_IS_NO_ONE_THERE: \"Tam nikdo není!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Nevyzkoumaný cizácký předmět nelze použít!\"\n  STR_OUT_OF_RANGE: \"Mimo dostřel!\"\n  STR_UNABLE_TO_THROW_HERE: \"Překážka v trajektorii hodu!\"\n  STR_SET_TIMER: \"Nastav časovač\"\n  STR_HIDDEN_MOVEMENT: \"SKRYTÝ POHYB\"\n  STR_TURN: \"KOLO> {0}\"\n  STR_SIDE: \"STRANA> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Pro pokračování stiskni tlačítko\"\n  STR_MIND_CONTROL: \"Ovládnutí mysli\"\n  STR_PANIC_UNIT: \"Zpanikařit jednotku\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Podlomení morálky bylo úspěšné\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Ovládnutí mysli se zdařilo\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}propadl amoku\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}propadla amoku\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}zpanikařil\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}zpanikařila\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Cizáci\"\n  STR_RIGHT_HAND: \"PRAVÁ RUKA\"\n  STR_LEFT_HAND: \"LEVÁ RUKA\"\n  STR_RIGHT_SHOULDER: \"PRAVÉ RAMENO \"\n  STR_LEFT_SHOULDER: \"LEVÉ RAMENO\"\n  STR_BACK_PACK: \"TORNA\"\n  STR_BELT: \"OPASEK\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}je pod cizáckou kontrolou\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}je pod cizáckou kontrolou\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}omdlel\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}omdlela\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}zemřel na smrtelné zranění\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}zemřela na smrtelné zranění\"\n  STR_USE_MIND_PROBE: \"Použít čtečku mysli\"\n  STR_FATAL_WOUNDS: \"SMRTELNÁ ZRANĚNÍ\"\n  STR_UNDER_ARMOR_UC: \"SPODNÍ ZBROJ\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Čas vyhrazen pro výstřel od boku\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Čas vyhrazen pro automatickou střelbu\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Čas vyhrazen pro mířenou střelbu\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Časové jednotky rezervované na zakleknutí\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"Časové jednotky rezervovány na zakleknutí a střelbu\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} jednotka v letounu X-Com\"\n    few: \"{N} jednotky v letounu X-Com\"\n    many: \"{N} jednotek v letounu X-Com\"\n    other: \"{N} jednotek v X-Com letounu\"\n  STR_UNITS_OUTSIDE:\n    one: \"{N} jednotka zanechána venku\"\n    few: \"{N} jednotky zanechány venku\"\n    many: \"{N} jednotek zanecháno venku\"\n    other: \"{N} jednotek zanecháno venku\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} jednotka ve vchodu\"\n    few: \"{N} jednotky ve vchodu\"\n    many: \"{N} jednotek ve vchodu\"\n    other: \"{N} jednotek ve vchodu\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} jednotka v cílovém východu\"\n    few: \"{N} jednotky v cílovém východu\"\n    many: \"{N} jednotek v cílovém východu\"\n    other: \"{N} jednotek v cílovém východu\"\n  STR_ABORT_MISSION_QUESTION: \"Přerušit misi?\"\n  STR_CORPSE: \"Mrtvola\"\n  STR_UNLOAD_CRAFT: \"Vyndat náboje\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}byl zabit\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}byla zabita\"\n  STR_HIT_MELEE: \"Zásah\"\n  STR_GROUND: \"ZEMĚ\"\n  STR_LIVING_QUARTERS_PLURAL: \"Obytné buňky\"\n  STR_LIST_ITEM: \"POLOŽKA\"\n  STR_PERSONAL_ARMOR_UFOPEDIA: \"S použitím právě objevených cizáckých slitin tato nová zbroj zvyšuje šance našich vojáků v boji proti mimozemské hrozbě.\"\n  STR_POWER_SUIT_UFOPEDIA: \"Nová výkonná zbroj napájená eleriovým zdrojem energie, která značně zvyšuje rychlost a sílu nositele a poskytuje zatím nejlepší ochranu pro bojové jednotky.\"\n  STR_FLYING_SUIT_UFOPEDIA: \"Vylepšená verze energického skafandru se zabudovanou cizáckou antigravitační navigační technologií umožňující plnou svobodu pohybu po bojovém poli.\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"Všichni cizáci byli zabiti při havárii,{NEWLINE}automatické zajištění zbytků spuštěno\"\n  STR_RESET: \"Reset\"\n  STR_MEMORIAL: \"Památník\"\n  STR_DATE_UC: \"DATUM\"\n  STR_SOLDIERS_RECRUITED_UC: \"VOJÁKŮ NAVERBOVÁNO>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"VOJÁKŮ ZTRACENO>{ALT}{0}\"\n  MAP_CULTA: \"Farma\"\n  MAP_FOREST: \"Les\"\n  MAP_JUNGLE: \"Džungle\"\n  MAP_MOUNT: \"Hory\"\n  MAP_DESERT: \"Poušť\"\n  MAP_POLAR: \"Polární\"\n  MAP_URBAN: \"Město\"\n  MAP_UBASE: \"Cizacká základna\"\n  MAP_XBASE: \"Základna X-Com\"\n  MAP_MARS: \"Mars\"\n  STR_MIXED: \"Smíšený\"\n  STR_REMOVE_SELECTED: \"Odstranit zvolené\"\n  STR_LIVE_ALIENS: \"Živí{NEWLINE}tvorové\"\n  STR_DEAD_ALIENS: \"Vyřazení{NEWLINE}tvorové\"\n  STR_UNDER_INTERROGATION: \"Nyní{NEWLINE}zkoumaní\"\n  STR_CONTAINMENT_EXCEEDED: \"Překročena kapacita cizáckých cel!{SMALLLINE}nedostatecny prostor v celách{0}. Musíš odstranit přebytečné cizáky z cel (budou zabiti)\"\n  STR_MANAGE_CONTAINMENT: \"Spravovat cizácké cely\"\n  STR_STORAGE_EXCEEDED: \"PŘEPLNĚNÉ SKLADY!{SMALLLINE}Nedostatek místa v {0}. Musíš prodat nadbytečné předměty.\"\n  STR_GO_TO_BASE: \"Zobrazit základnu\"\n  STR_MELEE_ACCURACY: \"PŘESNOST ZBLÍZKA\"\n  STR_SELL_PRODUCTION: \"PRODAT\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Obě ruce musí být prázdné!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Nedostatek kusů pro zkopírování šablony\"\n  STR_UNLOAD_WEAPON: \"Vybít zbraň\"\n  STR_ALL_ITEMS: \"Všechny věci\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"NENÍ POVOLENO VÍCE VYBAVENÍ.{SMALLLINE}Maximálně {N} kus vybavení  můžete dát do tohoto stroje.\"\n    few: \"NENÍ POVOLENO VÍCE VYBAVENÍ.{SMALLLINE}Maximálně {N} kusy vybavení můžete dát do tohoto stroje.\"\n    many: \"ŽÁDNÉ DALŠÍ VYBAVENÍ NELZE VZÍT NA PALUBU!{SMALLLINE}Do tohoto stroje můžete vzít maximálně {N} kusů vybavení.\"\n    other: \"ŽÁDNÉ DALŠÍ VYBAVENÍ NELZE VZÍT NA PALUBU!{SMALLLINE}Do tohoto stroje můžete vzít maximálně {N} kusů vybavení.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}ŘÍDÍCÍ CENTRUM ZNIČENO{NEWLINE}Dostaňte se k východu a přerušte misi.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"Zařízení X-COM nelze stavět pod vodou.\"\n  STR_LEVEL_SHORT: \"{0}\"\n  STR_PERSONNEL: \"Personál\"\n  STR_CRAFT_ARMAMENT: \"Letadla a výzbroj\"\n  STR_COMPONENTS: \"Komponenty\"\n  STR_SOLDIERS_RECRUITED: \"Vojáků rekrutováno\"\n  STR_SOLDIERS_LOST: \"Vojáků ztraceno\"\n  STR_TOTAL_UFOS: \"Detekovaná UFA\"\n  STR_TOTAL_ALIEN_BASES: \"Cizáckých základen objeveno\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"PSL\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"PDV\"\n  FEMALE_CIVILIAN: \"Civilistka\"\n  MALE_CIVILIAN: \"Civilista\"\n  CYBERDISC_WEAPON: \"Zbraň Kyberdisku\"\n  REAPER_WEAPON: \"Zbraň Páráka\"\n  CHRYSSALID_WEAPON: \"Zbraň Krysklada\"\n  CELATID_WEAPON: \"Zbraň Celatida\"\n  SILACOID_WEAPON: \"Zbraň Silacoida\"\n  SECTOPOD_WEAPON: \"Zbraň Sektopoda\"\n  ZOMBIE_WEAPON: \"Zbraň Zombie\"\n  ALIEN_PSI_WEAPON: \"Cizácká psionická zbraň\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/da.yml",
    "content": "da:\n  STR_AVENGER_UFOPEDIA: \"TRANSPORT- OG KAMPFLY.  DEN ULTIMATIVE REPLIKATION AF RUMVÆSENERNES TEKNOLOGI.\"\n  STR_INTERCEPTOR_UFOPEDIA: \"KAMPFLY MED DUAL PULSDETONATIONSMOTORER OG SPECIELT ELEKTRONISK BESKYTTEDE SYSTEMER.  DEN BEDST TILGÆNGELIGE JORDBASERET TEKNOLOGI.\"\n  STR_LIGHTNING_UFOPEDIA: \"TRANSPORT- OG KAMPFLY.  EN RÅ MEN EFFEKTIV REPLIKATION AF RUMVÆSENERNES FREMDRIFTSTEKNOLOGI.\"\n  STR_SKYRANGER_UFOPEDIA: \"TROPPETRANSPORT.  DEN HURTIGSTE AF SIN SLAGS MED LODRET LET- OG LANDINGSMULIGHEDER (L.L.O.L.).\"\n  STR_FIRESTORM_UFOPEDIA: \"KAMPFLY.  DETTE ENMANDSFLY REPLIKERER DET KLASSISKE TALLERKENFORMEDE DESIGN HOS RUMVÆSENERNE MED EN CENTRAL FREMDRIFTSENHED.\"\n  STR_STINGRAY_UFOPEDIA: \"AVANCERET LUFT TIL LUFT-MISSIL MED SPECIELT BESKYTTET ELEKTRONIK.\"\n  STR_AVALANCHE_UFOPEDIA: \"LUFT TIL LUFT-MISSIL MED NUKLEART SPRÆNGNINGSHOVED, MEN EKSTREMT TUNGT.\"\n  STR_CANNON_UFOPEDIA: \"KANON, MED HØJ KALIBER, SOM SKYDER MED PANSERGENNEMBRYDENDE SKUD, SOM KAN TRÆNGE IGENNEM 40,6 CM STÅL.\"\n  STR_FUSION_BALL_UFOPEDIA: \"DENNE MISSILAFFYRER SKYDER ET KUGLEFORMET MISSIL, SOM FÅR SIN KRAFT FRA EN ANTISTOF-REAKTION.  KUGLEN TILINTETGØR MÅLET MED EN TYNGDEKRAFTSIMPLOSION.\"\n  STR_LASER_CANNON_UFOPEDIA: \"DENNE KONVENTIONELLE LASERSTRÅLE FÅR SIN KRAFT FRA ET ANTISTOF-REAKTIONSKAMMER.\"\n  STR_PLASMA_BEAM_UFOPEDIA: \"TYNDGEKRAFTSTRÅLEN SENDER ET PRÆCIST KANALISERENDE FELT AF IMPLODERENDE TYNGDEKRAFT.\"\n  STR_SECTOID_UFOPEDIA: \"Det sektoide hieraki går fra soldater til ledere med kraftfulde psykiske egenskaber.  Disse psykiske krafter kan bruges til at demoralisere soldater i kamp, eller overtage deres sind.  De er normalt involveret i bortførsel af mennesker og mishandling af køer.  Disse bortførelser bruges til at udvinde genmateriale, som bruges til at avle på tværs af arterne og udvikle kloner til infiltration af menneskesamfundet. Køerne giver både næring og genmateriale.  Denne race vil formodentligt gerne udvikle højere gen-hybrider for at øge effektiviteten af deres bikube-agtige samfund.\"\n  STR_SECTOID_AUTOPSY: \"Obduktion - sektoid\"\n  STR_SECTOID_AUTOPSY_UFOPEDIA: \"Obduktionen afslører rudimentære fordøjelsesorganerne og en enkel struktur. Hjerne og øjne er meget veludviklet. Strukturen antyder genetisk ændring eller mutation. Den lille mund og næse synes ikke at have en funktion. Svømmehuden mellem fingrene, og de flade fødder tyder på akvatisk oprindelse. Der er ingen reproduktive organer, og ingen fingerpeg om, hvordan denne art kan reproducere sig selv. De er sandsynligvis en genetisk manipuleret art.\"\n  STR_SNAKEMAN_UFOPEDIA: \"Denne race udviklede sig i et ekstremt fjendtligt miljø. De er ekstrem hårde og kan modstå ekstreme temperatursvingninger. Deres mobilitet afhænger en slange-lignende »gigantfod«, som beskytter alle de vitale organer. Deres formål synes at være rent aggressiv og de ​​synes at være under kommando af en anden intelligens, som dirigerer deres indtrængen på jorden i militær stil.\"\n  STR_SNAKEMAN_AUTOPSY: \"Obduktion - slangemand\"\n  STR_SNAKEMAN_AUTOPSY_UFOPEDIA: \"Huden er ekstrem sej og modstandsdygtig over for varme. Hjerte kar-systemet er en del af det muskuløse system, der anvender det hydrauliske princip til at skabe bevægelse. Den eneste reelle muskel er »hjertet«. Det reproduktive system synes at være meget effektiv. Formering er ukønnet, hvor hver slangemand bærer op til halvtreds æg inde i sin krop på et givet tidspunkt. Ved fri bevægelse på jorden vil denne art være en alvorlig trussel for livet på jorden.\"\n  STR_ETHEREAL_UFOPEDIA: \"Dette væsen har imponerende mentale kræfter, der giver mulighed for telepatisk kommunikation og telekinetiske evner. De tilsyneladende svage fysiske evner i denne skabning er båret af de mentale kræfter. Vi forstår ikke, hvordan disse telekinetiske kræfter virker, fordi de synes at trodse fysikkens love, som vi kender dem. De er ekstremt farlige i enhver kampsituation, hvor de er afhængige af deres mentale kræfter til kamp. De vises sig sjældent på jorden, da de synes at stole på at andre racer forfølger deres mål.\"\n  STR_ETHEREAL_AUTOPSY: \"Obduktion - ethereal\"\n  STR_ETHEREAL_AUTOPSY_UFOPEDIA: \"Dette væsen er fysisk retarderet og virker ude af stand til at opretholde nogen livsfunktioner. Musklerne er alvorligt forkrøblede og de indre organer virker som om de er underudviklet. De sansende organer, herunder øjnene, virker slet ikke til at være funktionelle. Hjernen derimod er godt udviklet og trækker på en høj andel af kroppens blodforsyning. Det er et mysterie hvordan dette væsen kan opretholde liv uden ekstern støtte.\"\n  STR_MUTON_UFOPEDIA: \"Dette menneskelignende væsen er fysisk stærkt og intelligent. Det har en særlig appetit for råt kød af enhver slags som det, ligesom jordbaserede kødædere, har brug for, for at få næring. De ser ud til, at støtte sig til telepatiske kommandoer fra en race kendt som »ethereals«. Når de bliver adskilt fra denne telepatiske forbindelse ser deres mentale system ud til at bryde sammen, og de dør. De kybernetiske implantater bliver brugt til at forbedre deres præstation i kamp. De er tydeligvis fodsoldater for en højere intelligens.\"\n  STR_MUTON_AUTOPSY: \"Obduktion - muton\"\n  STR_MUTON_AUTOPSY_UFOPEDIA: \"»Huden« på dette væsen virker til at være en, organisk skabt, beskyttende rustning der er indopereret i kroppen. Der er adskillige kybernetiske implantater, der bliver bliver brugt til at forbedre hjerte-kar-systemet og sanserne. kønsorganerne virker til at være blevet fjernet kirurgisk. Øjensynligt er disse uheldige væsner begrænset til at føre krig og erobre. Panserbrydende ammunition er ikke særlig effektiv mod deres hærdede hud.\"\n  STR_CELATID_UFOPEDIA: \"Denne livsform har den mystiske naturlige evne til at svæve gennem luften. Den ser ud til at detektere menneskelige hjernebølger og vil bevæge sig mod et menneskeligt mål, selvom godt skjult. Når et mål er detekteret lander celatiden og affyrer små kugler med ekstremt ætsende gift. Væsenet har evnen til at klone sig selv i et alarmerende tempo. Den ledsager racen muton i sine vandringer.\"\n  STR_CELATID_AUTOPSY: \"Obduktion - celatid\"\n  STR_CELATID_AUTOPSY_UFOPEDIA: \"Kernen indeholder en lille bio-mekanisk anordning, der synes at være et naturligt udviklet antityngde fremdrivningssystem. Sækken af gift er det største organ, og der synes ikke at være en separat hjernestruktur. Der er intet mærkbart fordøjelsessystem eller noget reproduktivt system. En lille organ indeholder embryoner, som hurtigt kan vokse til et nyt individ.\"\n  STR_SILACOID_UFOPEDIA: \"Denne silikone-baserede livsform genererer en enorm mængde varme. Den har styrken til at knuse sten, som derefter kan blive indtaget af den varme kerne. Den har en primitiv intelligens og kan blive kontrolleret af implantater eller telepatiske væsener. Den arbejder sammen med rumvæsenracen muton.\"\n  STR_SILACOID_AUTOPSY: \"Obduktion - silacoid\"\n  STR_SILACOID_AUTOPSY_UFOPEDIA: \"Det indre hos væsenet er ekstremt varmt, og synes at være grundlaget for et fordøjelsessystem. Dets unikke muskelsystem har enorm kraft og hastighed. Dens klippe-lignende hud skades ikke af ild eller brændbar ammunition.\"\n  STR_CHRYSSALID_UFOPEDIA: \"De krabbe-lignende kløer hos denne skabning er et magtfuldt våben i nærkamp. Det høje stofskifte og styrken hos ​​denne skabning giver den hastighed og fingerfærdighed. I stedet for at dræbe sit offer imprægnerer chryssaliden det med et æg og injicerer en gift, som forvandler det til en omvandrende zombie. En ny chryssalid vil briste fra offeret kort efter imprægnering. Chryssalider er forbundet med racen slangemand.\"\n  STR_CHRYSSALID_AUTOPSY: \"Obduktion - chryssalid\"\n  STR_CHRYSSALID_AUTOPSY_UFOPEDIA: \"Exoskelettet hos denne skabning er ekstremt hårdt, men overraskende sårbar over for eksplosiv ammunition. Hjernen er veludviklet, og hastigheden for cellevækst meget hurtig. Væsenet bærer tyve æg, som lægges inde i andre organismer. Dette væsen er et meget effektivt terrorvåben.\"\n  STR_FLOATER_UFOPEDIA: \"Flydere er primært soldater og terroragenter. De er naturligt aggressiv bæster, gensplejsede og kybernetisk forbedret til formidable krigere. Den nederste halvdel af kroppen og de fleste indre organer fjernes kirurgisk, og et livsunderstøttelsessystem installeres. Dette implantat indeholder en antityngdekraft-enhed, der gør det muligt for væsenet til at flyde, omend usikkert, gennem luften.\"\n  STR_FLOATER_AUTOPSY: \"Obduktion - flyder\"\n  STR_FLOATER_AUTOPSY_UFOPEDIA: \"Dette væsen er blevet drastisk ændret ved operation. Den anordning, som ser ud til at udgøre kernen i kroppen er et livsunderstøttelsessystem, der overtager funktionerne for ​​hjerte, lunger og fordøjelsessystem. Dette gør det muligt for skabningen at overleve i meget fjendtlige miljøer. Hjernen er mindre end vores, men sanseorganer er veludviklede.\"\n  STR_REAPER_UFOPEDIA: \"Denne tobenede kødæder har stærke kæber og en grum appetit. Den har nogle hjerneimplantater, der bruges til at styre dens adfærd. Dens primitive jægerinstinkter bliver ikke brugt til andet end at terrorisere og ødelægge. Reapere bliver i almindelighed associeret med flydere.\"\n  STR_REAPER_AUTOPSY: \"Obduktion - reaper\"\n  STR_REAPER_AUTOPSY_UFOPEDIA: \"Reaperen har to »hjerner« og to »hjerter«,, som gør det muligt for den at fungere, selv når den er stærkt såret. Men dens lodne hud er meget brandfarligt, hvilket gør væsenet sårbar over brandvåben.\"\n  STR_SECTOPOD_UFOPEDIA: \"Sectopoder er robotvæsener udstyret med et kraftigt laservåben. Kontrollen over disse mekaniske bæster foregår via en telepatisk forbindelse til deres operatører, racen ethereal. Sectopoder er det absolut kraftigste terrorvåben i rumvæsenernes arsenal.\"\n  STR_SECTOPOD_AUTOPSY: \"Obduktion - sectopod\"\n  STR_SECTOPOD_AUTOPSY_UFOPEDIA: \"Robotten er solidt konstrueret og har en rustning med strøm, som kan modstå de fleste former for angreb, især plasmavåben. Men sensorkredsløbet synes særligt sårbart over for laservåben.\"\n  STR_CYBERDISC_UFOPEDIA: \"Denne mini flyvende tallerken er et automatiseret terrorvåben bevæbnet med en kraftfuld plasmastråle. Den anti-tyngdekraft fremdrift giver det en stor fordel i vanskeligt terræn. Dens primære funktion er ødelæggelse og terror i tjeneste hos racen sectoid.\"\n  STR_CYBERDISC_AUTOPSY: \"Obduktion - cyberdisk\"\n  STR_CYBERDISC_AUTOPSY_UFOPEDIA: \"Cyberdisken er godt beskyttet og er især god til at modstå eksplosiv ammunition. Det primære anti-tyngdekraft system er for beskadiget til at få en forståelse af dets funktion.\"\n  STR_UFO_POWER_SOURCE_UFOPEDIA: \"Kraftkilden i ufoerne er en anti-stof reaktor, der bruger elerium (element 115) til at generere kraftige gravitationsbølger så vel som andre former for energi. Omsætningen fra stof til energi er på utrolige 99 % effektivitet, derved kan bittesmå mængder elerium producere enorme mængder energi. Denne enhed kan nemt reproduceres ved brug af rumvæsenernes legeringer.\"\n  STR_UFO_NAVIGATION_UFOPEDIA: \"Rumvæsenernes fartøj benytter sofistikerede computere til at navigere på jorden og i rummet. Systemet er baseret på optiske processorer og er arrangeret i en netværkslignende konfiguration. Kontrolmekanismen er forholdsvis simpel - Navigatøren kontrollerer retningen på tyngdefeltet der genereres af kraftkilden og er på den måde i stand til at bevæge skibet i en hvilken som helst retning. Dette system kan uden besvær benyttes af mennesker og det kan produceres af rumvæsenernes legeringer samt andre komponenter.\"\n  STR_UFO_CONSTRUCTION_UFOPEDIA: \"Rumvæsenernes fartøj består af tre hovedkomponenter - en strømkilde, et navigationssystem og et skrog bygget af rumvæsenernes legeringer. Skroget er specielt designet til at hjælpe gravitationsbølger med at blive ledt og kontrolleret. Desuden kræves en lille mængde elerium som brændstofkilde. Når principperne for konstruktion bliver forstået, og funktionerne for hver komponent er kendt, så er det muligt at bygge disse flytyper.\"\n  STR_ALIEN_FOOD_UFOPEDIA: \"Disse kamre indeholder forskellige enzymer, der anvendes til at fordøje kropsdele fra kvæg og andre dyr og endda mennesker. Væsken bliver derefter indtaget som klar fordøjet mad - sandsynligvis direkte til blodbanen. Dette tyder på en vis afhængighed af jorden til mad - en symbiose mellem jorden og rumvæsenernes samfund.\"\n  STR_ALIEN_REPRODUCTION_UFOPEDIA: \"Disse kamre indeholder rumvæsenfostre. Designet på disse beholdere antyder at rumvæsenerne, der benytter denne proces er helt afhængige af reproduktion i laboratoriet. De rige næringsstoffer sikrer en hurtig udvikling af fostret. Denne fabrikslinje kan generere tusindvis af kloner på kort tid. Denne proces kan nemt blive tilpasset til menneskelig reproduktion, eller til rumvæsen-menneske hybrider.\"\n  STR_ALIEN_ENTERTAINMENT_UFOPEDIA: \"Den mest sandsynlige anvendelse af disse sfærer er til rekreativ underholdning. De overnaturlige kredsløb stimulerer forskellige centre i hjernen. Effekten ligner hallucinogen narkotika. Dette er det eneste der bevidner, at de fremmede kan have nogen som helst form for kulturelle eller rekreative fritidsinteresser.\"\n  STR_ALIEN_SURGERY_UFOPEDIA: \"Dette kirurgiske instrument bruger en laserskærer til at udtrække bestemte kropsdele fra kvæg og andre dyr. Den udbredte kvægmishandling kan tilskrives denne bizarre aktivitet hos rumvæsenerne. Det er sandsynligt, at disse kropsdele bruges til ernæring eller genetiske formål.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"Igennem tiderne har tusindvis af mennesker påstået, at de har været bortført af rumvæsener, undertiden gentagne gange. Sandheden er langt mere frygtelig. Mennesker bortføres, er forsøgsdyr og overvåges. De bedste eksemplarer får genetisk materiale udtrukket. Kvinder får hybrider af fostre mellem mennesker og rumvæsener implanteret, og de fjernes så flere måneder senere. Hvem ved hvilke dunkle motiver rumvæsenerne har?\"\n  STR_ALIEN_ALLOYS_UFOPEDIA: \"Rumvæsenernes luftfartøjer er konstrueret af specielle legeringer med unikke egenskaber. De er ekstreme lette og holdbare og kan formes via elektromagnetiske metoder. Dette materiale kan genskabet og bruges i mange slags produktionsprocesser.\"\n  STR_ELERIUM_115_UFOPEDIA: \"Dette element har den usædvanlige egenskab at generere anti-stof strøm når bombarderet med visse partikler. Dette skaber tyngdekraftbølger og andre former for energi. Det findes ikke naturligt i vores solsystem og kan ikke reproduceres.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"Det er klart, at vi kæmper en forgæves kamp på jorden. De fremmede horder er overvældende i antal. Det bedste vi kan gøre, er at bremse deres udvikling. Det eneste håb for menneskeheden er at angribe rumvæsenerne ved kilden. Vores efterforskning tyder på en nærliggende operationsbase inden for vores solsystem. Rumvæsenerne angiver dette sted som centrum for en gammel civilisation, der går forud menneskets historie. Vi må finde dette sted så hurtigt som muligt. Men vi er nødt til at fange og afhøre en leder blandt rumvæsenerne for at få mere detaljerede oplysninger. De større ufoer har sandsynligvis mindst én leder.\"\n  STR_THE_MARTIAN_SOLUTION_UFOPEDIA: \"Vores forskning peger nu på Mars som base for rumvæsenernes operationer. Basen er godt skjult, og indeholder de produktionsfaciliteter og kloningsfaciliteter, der skal bruges, til infiltration af jorden. Det synes også at indeholde en styrende computer af en slags, der kontrollerer hele operationen. Det ser ud til, at det bikube-lignende samfund har en slags »bidronning«. Dette er deres fundamentale svaghed - hvis vi kan eliminere den »hjerne«, så vil kroppen dø. Vi skal øge vores forskningsindsats, før det er for sent. For at komme videre skal vi fange de højest rangerende rumvæsener - de chefer - som kun kan fanges i deres baser.\"\n  STR_CYDONIA_OR_BUST_UFOPEDIA: \"Det er nu klart, at rumvæsenernes horder bliver styret fra en underjordisk base i Cydonia - hvilket er et usædvanlig område på Mars, som har pyramider med fem sider og en stor formation, der ligner et menneskeansigt. Cydonians civilisation blomstrede på Mars for mange millioner år siden, men vi ved ikke, hvorfor den uddøde, eller hvad forbindelsen er til den seneste aktivitet blandt rumvæsener der.. Hvad forklaringen end er, så skal vi sende en ekspedition til Cydonia. Det er den eneste måde, vi kan besejre rumvæsenerne på. Vi skal ødelægge den kontrollerende »hjerne«. Vi får brug for en Avenger udstyret med den mest imponerende destruktive kraft vi har til rådighed. Der er ikke mere vi kan lære - vi må afvente resultatet af angrebet på Cydonian.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"CENTRER PÅ STED-TID=5 sek\"\n  STR_CANCEL_UC: \"ANNULLER\"\n  STR_NONE: \"Ingen\"\n  STR_UNKNOWN: \"Ukendt\"\n  STR_POOR: \"Dårligt\"\n  STR_AVERAGE: \"Gennemsnitligt\"\n  STR_GOOD: \"Godt\"\n  STR_EXCELLENT: \"Fantastisk\"\n  STR_BUILD_NEW_BASE_UC: \"BYG NY BASE\"\n  STR_BASE_INFORMATION: \"BASEINFORMATION\"\n  STR_EQUIP_CRAFT: \"UDSTYR FLY\"\n  STR_BUILD_FACILITIES: \"BYG FACILITETER\"\n  STR_RESEARCH: \"UDFORSK\"\n  STR_MANUFACTURE: \"PRODUCER\"\n  STR_TRANSFER_UC: \"OVERFØR\"\n  STR_PURCHASE_RECRUIT: \"KØB/ANSÆT\"\n  STR_SACK: \"FYR\"\n  STR_SELL_SACK_UC: \"SÆLG/FYR\"\n  STR_GEOSCAPE_UC: \"LANDKORT\"\n  STR_NAME: \"Navn\"\n  STR_AREA: \"Område\"\n  STR_BUILD_NEW_BASE: \"Byg ny base\"\n  STR_CANCEL: \"Annuller\"\n  STR_COST_UC: \"PRIS>\"\n  STR_CONSTRUCTION_TIME_UC: \"PRODUKTIONSTID>\"\n  STR_DAY:\n    one: \"{N} dag\"\n    other: \"{N} dage\"\n  STR_HOUR:\n    one: \"{N} time\"\n    other: \"{N} timer\"\n  STR_MAINTENANCE_UC: \"VEDLIGEHOLDELSE>\"\n  STR_OK: \"O.k.\"\n  STR_INSTALLATION: \"Installation\"\n  STR_CURRENT_RESEARCH: \"NUVÆRENDE FORSKNING\"\n  STR_SCIENTISTS_AVAILABLE: \"Videnskabsmænd til rådighed>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Forskere tildelt>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Laboratorieplads til rådighed>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"FORSKNINGSPROJEKT\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"FORSKERE TILDELT\"\n  STR_PROGRESS: \"STATUS\"\n  STR_NEW_PROJECT: \"Nyt projekt\"\n  STR_CANCEL_PROJECT: \"AFBRYD PROJEKT\"\n  STR_NEW_RESEARCH_PROJECTS: \"NYE FORSKNINGSPROJEKTER\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"Forskere til rådighed>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"TILGÆNGELIG LABORATORIEPLADS>{ALT}{0}\"\n  STR_INCREASE: \"Flere\"\n  STR_DECREASE: \"Færre\"\n  STR_START_PROJECT: \"START PROJEKT\"\n  STR_CURRENT_PRODUCTION: \"NUVÆRENDE PRODUKTION\"\n  STR_ENGINEERS_AVAILABLE: \"Ingeniører til rådighed>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Ingeniører tildelt>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Tilgængelig værkstedsplads>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Nuværende midler>{ALT}{0}\"\n  STR_ITEM: \"UDSTYR\"\n  STR_ENGINEERS__ALLOCATED: \"Ingeniører tildelt\"\n  STR_UNITS_PRODUCED: \"Enheder produceret\"\n  STR_TOTAL_TO_PRODUCE: \"I alt til produktion\"\n  STR_COST__PER__UNIT: \"Pris{NEWLINE}per{NEWLINE}enhed\"\n  STR_DAYS_HOURS_LEFT: \"Resterende dage/timer\"\n  STR_NEW_PRODUCTION: \"Ny produktion\"\n  STR_PRODUCTION_ITEMS: \"Enheder der kan produceres\"\n  STR_CATEGORY: \"KATEGORI\"\n  STR_START_PRODUCTION: \"START PRODUKTION\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} ingeniørtimer til at fremstille en enhed\"\n  STR_COST_PER_UNIT_: \"Pris pr. enhed>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Påkrævet arbejdsareal>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"SPECIELLE MATERIALER ER KRÆVET\"\n  STR_ITEM_REQUIRED: \"UDSTYR KRÆVET\"\n  STR_UNITS_REQUIRED: \"ENHEDER KRÆVET\"\n  STR_UNITS_AVAILABLE: \"ENHEDER TIL RÅDIGHED\"\n  STR_STOP_PRODUCTION: \"STOP PRODUKTION\"\n  STR_ENGINEERS_AVAILABLE_UC: \"INGENIØRER TIL RÅDIGHED>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"VÆRKSTEDSAREAL TIL RÅDIGHED>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"MÅNEDLIG PROFIT>{ALT}{0}\"\n  STR_INCREASE_UC: \"FLERE\"\n  STR_DECREASE_UC: \"FÆRRE\"\n  STR_UNITS_TO_PRODUCE: \"Enheder at producere\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Køb/ansæt personale\"\n  STR_COST_OF_PURCHASES: \"Pris for indkøb>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"PRIS PER ENHED\"\n  STR_QUANTITY_UC: \"ANTAL\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"TILGÆNGELIG PERSONALE:PERSONALE I ALT>\"\n  STR_SOLDIERS: \"Soldater\"\n  STR_SCIENTISTS: \"Forskere\"\n  STR_ENGINEERS: \"Ingeniører\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"ANVENDT PLADS:TILGÆNGELIG PLADS>\"\n  STR_LIVING_QUARTERS: \"Beboelsesrum\"\n  STR_STORES: \"Lager\"\n  STR_LABORATORIES: \"Laboratorier\"\n  STR_WORK_SHOPS: \"Værksted\"\n  STR_HANGARS: \"Hangar\"\n  STR_SHORT_RANGE_DETECTION: \"Kortrækkende detektion\"\n  STR_DEFENSE_STRENGTH: \"Forsvarsstyrke\"\n  STR_TRANSFERS_UC: \"OVERFØRSLER\"\n  STR_TRANSFERS: \"Overførsler\"\n  STR_ARRIVAL_TIME_HOURS: \"Ankomsttid (timer)\"\n  STR_COST_: \"Pris>{ALT}{0}\"\n  STR_AREA_: \"Område>{ALT}{0}\"\n  STR_BASE_NAME: \"Navngiv basen?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"VÆLG ADGANGSLIFTENS POSITION \"\n  STR_TRANSFER: \"Overfør\"\n  STR_AMOUNT_TO_TRANSFER: \"MÆNGDE DER SKAL OVERFØRES\"\n  STR_SELECT_DESTINATION_BASE: \"Vælg destinationsbase\"\n  STR_COST: \"Pris\"\n  STR_VICTORY_1: \"Da du træder ind i kammeret, ser du den fremmede hjerne - genstand for din søgen. Før du kan skyde kommunikerer den til dig via en skærm på sin base. Den bønfalder dig om at lytte til dens argumenter for at overleve, før du foretager beslutningen om at trykke på aftrækkeren ...\"\n  STR_VICTORY_2: \"Hjernen taler: For mange millioner af år siden var planeten, du kalder Mars, i live. Dette liv blev bragt til en gold planet af vores civilisation, som det blev til din. I millioner af år har vi besøgt din planet og genetisk udviklet dine arter. Du kan ikke slå os ihjel, du er en del af os ...\"\n  STR_VICTORY_3: \"Her er centrum for Mars' civilisation - pyramiderne bygget millioner af år før dit liv - af en art, der er din forfader. Ingen planet er uden for vores rækkevidde. Denne magt kunne blive din inden længe. Det eneste, vi beder om, er dit samarbejde ...\"\n  STR_GAME_OVER_1: \"De fremmede forsøger at udrydde hele menneskeheden ved at destruere byer og forgifte luften og havet. Modstanden fra jordens styrker er nyttesløs i kampen mod umådelig overlegen teknologi. Overlevende generationer lider under frygtelige mutationer mens de flygter fra rumvæsenernes ødelæggelse. De bliver indfanget i slavelejre og bliver tvunget til at hjælpe med at omdanne jorden til en koloni for de fremmede, der er en del af et ukendt imperium.\"\n  STR_GAME_OVER_2: \"Den viden, der er opnået igennem X-COM-projektet, er tabt for altid. Du har fejlet i din mission for at redde jorden.\"\n  STR_VICTORY_4: \"Rumvæsenets hjerne bliver afbrudt af en udladning varm plasma, og hele rumvæsenernes styrke er besejret.\"\n  STR_VICTORY_5: \"Når rumvæsenerne har mistet Mars, så har de mistet jorden. Inden længe vil XCom-forskning gøre, at menneskeheden igen kan blomstre, og hævde Mars for sig selv. Den fremmede trussel er væk, men hvor længe, ved ingen ...\"\n  STR_YOU_HAVE_FAILED: \"Du har fejlet i at stoppe rumvæsenernes angreb. En efter en har de finansierende lande underskrevet pagter med rumvæsenerne, mod løfter om teknologi, velstand og fred, men det står snart klart at rumvæsenerne har andre planer ...\"\n  STR_TOTAL_UC: \"I ALT\"\n  STR_INCOME: \"Indtægter\"\n  STR_EXPENDITURE: \"Udgifter\"\n  STR_MAINTENANCE: \"Vedligeholdelse\"\n  STR_BALANCE: \"Resultat\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"Ufo-aktivitet i områder\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"Ufo-aktivitet i lande\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"XCom-aktivitet i områder\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"XCom-aktivitet i lande\"\n  STR_FINANCE: \"Finanser\"\n  STR_DATE_FIRST: \"{0}.\"\n  STR_DATE_SECOND: \"{0}.\"\n  STR_DATE_THIRD: \"{0}.\"\n  STR_DATE_FOURTH: \"{0}.\"\n  STR_FINANCE_THOUSANDS: \"i 1.000 kr.\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Ikke nok specielle materialer til at fremstille{NEWLINE}{0}{NEWLINE}på{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Ikke nok penge til at producere{NEWLINE}{0}{NEWLINE}på{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"Produktion af{NEWLINE}{0}{NEWLINE}på{NEWLINE}{1}{NEWLINE}er færdig\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"Konstruktion af{NEWLINE}{0}{NEWLINE}på{NEWLINE}{1}{NEWLINE}er færdig\"\n  STR_OK_5_SECONDS: \"O.k. - 5 sek.\"\n  STR_RESEARCH_COMPLETED: \"Forskning fuldendt\"\n  STR_VIEW_REPORTS: \"GENNEMSE RAPPORTER\"\n  STR_WE_CAN_NOW_RESEARCH: \"Vi kan nu forske i\"\n  STR_WE_CAN_NOW_PRODUCE: \"Vi kan nu producere\"\n  STR_SUNDAY: \"SØNDAG\"\n  STR_MONDAY: \"MANDAG\"\n  STR_TUESDAY: \"TIRSDAG\"\n  STR_WEDNESDAY: \"ONSDAG\"\n  STR_THURSDAY: \"TORSDAG\"\n  STR_FRIDAY: \"FREDAG\"\n  STR_SATURDAY: \"LØRDAG\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Ikke tilstrækkelig {0} til at tanke {1} på {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Ikke nok {0} til at udruste {1} på {2}\"\n  STR_UFO_IS_NOT_RECOVERED: \"Ufo blev ikke fundet\"\n  STR_UFO_IS_RECOVERED: \"Ufo er fundet\"\n  STR_CRAFT_IS_LOST: \"Flyet er tabt\"\n  STR_TERROR_CONTINUES: \"Terroren fortsætter\"\n  STR_ALIENS_DEFEATED: \"Rumvæsener besejret\"\n  STR_BASE_IS_LOST: \"Basen er tabt\"\n  STR_BASE_IS_SAVED: \"Base er reddet\"\n  STR_ALIEN_BASE_STILL_INTACT: \"Rumvæsenernes base er stadig intakt\"\n  STR_ALIEN_BASE_DESTROYED: \"Rumvæsenernes base er ødelagt\"\n  STR_ALIENS_KILLED: \"RUMVÆSENER DRÆBT\"\n  STR_ALIEN_CORPSES_RECOVERED: \"FUNDNE RUMVÆSENLIG\"\n  STR_LIVE_ALIENS_RECOVERED: \"RUMVÆSENER FANGET I LIVE\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"UDSTYR FRA RUMVÆSENER BJÆRGET\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"RUMVÆSENERNES KONTROLBASE ER ØDELAGT\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"CIVILE DRÆBT AF RUMVÆSENER\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"CIVILE DRÆBT AF X-COM-SOLDATER\"\n  STR_CIVILIANS_SAVED: \"CIVILE REDDET\"\n  STR_XCOM_OPERATIVES_KILLED: \"X-COM-SOLDATER DRÆBT\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"X-COM-SOLDATER FORSVUNDET I KAMP\"\n  STR_TANKS_DESTROYED: \"KAMPVOGN TILINTETGJORT\"\n  STR_XCOM_CRAFT_LOST: \"X-COM-FLY MISTET\"\n  STR_UFO_RECOVERY: \"UFO-BJÆRGNING\"\n  STR_ALIEN_BASE_RECOVERY: \"RUMVÆSENERNES BASE FUNDET\"\n  STR_BASE_UNDER_ATTACK: \"{0} under angreb!\"\n  STR_BASE_DEFENSES_INITIATED: \"BASEFORSVAR INITIERET\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"GRAV.-SKJOLD AFVISER UFO!\"\n  STR_FIRING: \"SKYDER\"\n  STR_HIT: \"RAMT!\"\n  STR_UFO_DESTROYED: \"UFO TILINTETGJORT!\"\n  STR_MISSED: \"FORBIER!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Sælg udstyr/fyr personale\"\n  STR_VALUE_OF_SALES: \"SALGSVÆRDI> {ALT}{0}\"\n  STR_FUNDS: \"MIDLER> {ALT}{0}\"\n  STR_SELL_SACK: \"Sælg/fyr\"\n  STR_VALUE: \"VÆRDI\"\n  STR_CRAFT_: \"FARTØJ>{ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"BJÆRGNING VED UFO-STYRT\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"Vær forsigtig - der kan være folk i ufoen eller omkring nedstyrtningsstedet. Missionen er succesfuld når alle fjendtlige enheder er blevet elimineret eller neutraliseret. Bjærgning af rester fra ufoen, udstyr og rumvæsenernes lig kan så påbegyndes. For at afbryde missionen skal du returnere X-Com-mandskabet til transportfartøjet og klikke på ikonet »Afbryd mission«.\"\n  STR_UFO_GROUND_ASSAULT: \"UFO-LANDANGREB\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"Udforsk landingsstedet, og hvis det er muligt, skaf dig adgang til ufoen. Missionen vil være en succes, når alle fjendtlige enheder er blevet elimineret eller neutraliseret. Bjærgning af ufo, udstyr og rumvæsenernes lig kan derefter igangsættes. For at afbryde missionen skal du returnere dine X-Com-soldater til transportflyet og klik på ikonet »Afbryd mission«.\"\n  STR_BASE_DEFENSE: \"BASEFORSVAR\"\n  STR_BASE_UC_: \"BASE> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"Et af rumvæsenernes fartøjer er landet i området. Vores base er i alvorlig fare. Som standardprocedure er alt ikkemilitært personel og X-Com-fartøjer blevet evakueret. Rumvæsenerne vil angribe basen via hangardøre eller indgangspartiet. Forsvar basen og dens vitale installationer uanset omkostningerne - dette er en kamp til døden. Hvis du klikker på ikonet »afbryd mission« bliver du besejret og mister basen.\"\n  STR_ALIEN_BASE_ASSAULT: \"BASEANGREB MOD RUMVÆSENERNE\"\n  STR_ALIEN_BASE_ASSAULT_BRIEFING: \"X-Com-soldater har fået adgang til en af rumvæsenernes baser. Kontrolcentret skal destrueres for at gøre basen ubrugelig. Missionen ophører, når alle fjender er elimineret, eller når dit hold er vendt tilbage til det grønne forlad-område (klik på ikonet »Afbryd mission« for at flygte).\"\n  STR_CYDONIA_BRIEFING: \"Du er ankommet i Cydonien. Du har fået adgang til et stort underjordisk kompleks nær sfinksen på Mars. Du skal ødelægge rumvæsenernes hjerne som kontrollerer al aktivitet blandt rumvæsenerne. Menneskehedens skæbne er i dine hænder ...\"\n  STR_TERROR_MISSION: \"TERRORMISSION\"\n  STR_TERROR_MISSION_BRIEFING: \"Mission vil være en succes, når alle fjendtlige enheder er blevet elimineret eller neutraliseret. Du skal forsøge at redde livet for eventuelle civile i området ved at neutralisere truslen fra rummet. For at afbryde missionen skal du returnere alle X-Com-soldater til transportflyet og klikke på ikonet »Afbryd mission«.\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"INGEN LEDIGE HANGARER TIL FLYPRODUKTION!{SMALLLINE}Hvert fartøj tildelt en base, overført til en base, købt eller konstrueret bruger én hangar. Byg en ny hangar eller overfør et fartøj til en anden base.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"INGEN LEDIGE HANGARER TIL INDKØBET!{SMALLLINE}Hvert fartøj der er tildelt en base, overført til en base, eller er købt eller konstrueret på en base bruger én hangar. Byg en ny hangar eller overfør et fartøj til en anden base.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"INGEN LEDIGE HANGARER TIL OVERFØRSEL!{SMALLLINE}Hvert fartøj der er tildelt en base, overført til en base, eller er købt eller konstrueret på en base bruger én hangar. Byg en ny hangar eller overfør et fartøj til en anden base.\"\n  STR_CANNOT_BUILD_HERE: \"DU KAN IKKE BYGGE HER!{SMALLLINE}Du er nødt til at bygge ved siden af en eksisterende facilitet.\"\n  STR_NO_FREE_ACCOMODATION: \"INGEN LEDIGE RUM!{SMALLLINE}Destinationsbasen har ikke plads nok i beboelsesområdet.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"IKKE NOK TILGÆNGELIGT ARBEJDSAREAL!{SMALLLINE}Byg et nyt værksted eller reducer arbejdet på andre projekter.\"\n  STR_NOT_ENOUGH_MONEY: \"IKKE NOK PENGE!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"IKKE NOK LAGERRUM!{SMALLLINE}Byg et nyt lagerrum eller overfør eksisterende udstyr til andre baser.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"IKKE NOK BEBOELSESRUM!{SMALLLINE}Byg nye beboelsesområder eller overfør personale til andre baser.\"\n  STR_LAUNCH_INTERCEPTION: \"PÅBEGYND ANGREB\"\n  STR_CRAFT: \"FLY\"\n  STR_STATUS: \"STATUS\"\n  STR_BASE: \"BASE\"\n  STR_READY: \"KLAR\"\n  STR_OUT: \"UD\"\n  STR_REPAIRS: \"REPARATIONER\"\n  STR_REFUELLING: \"TANKER OP\"\n  STR_REARMING: \"LADER\"\n  STR_TARGET: \"MÅL: {0}\"\n  STR_WAY_POINT: \"VIA-PUNKT\"\n  STR_ARE_YOU_SURE_CYDONIA: \"Er du sikker på, at du vil sende dette fartøj på en mission til Cydonien?\"\n  STR_YES: \"JA\"\n  STR_NO: \"NEJ\"\n  STR_SELECT_DESTINATION: \"VÆLG DESTINATION\"\n  STR_CYDONIA: \"CYDONIEN\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"VÆLG PLACERING AF NY BASE\"\n  STR_RETURN_TO_BASE: \"RETURNER TIL BASEN\"\n  STR_SELECT_NEW_TARGET: \"VÆLG NYT MÅL\"\n  STR_PATROL: \"PATRULJE\"\n  STR_STATUS_: \"STATUS>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"BESKADIGET - RETURNERER TIL BASEN\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"LAVT BRÆNDSTOFNIVEAU - RETURNERER TIL BASEN\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"MISSION FULDENDT - RETURNERER TIL BASEN\"\n  STR_PATROLLING: \"PATRULJERER\"\n  STR_TAILING_UFO: \"FØLGER UFO\"\n  STR_INTERCEPTING_UFO: \"ANGRIBER UFO-{0}\"\n  STR_RETURNING_TO_BASE: \"RETURNERER TIL BASEN\"\n  STR_DESTINATION_UC_: \"Destination: {0}\"\n  STR_BASE_UC: \"BASE>{ALT}{0}\"\n  STR_SPEED_: \"HASTIGHED>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"MAKSIMAL HASTIGHED>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"HØJDE>{ALT}{0}\"\n  STR_VERY_LOW: \"MEGET LAVT\"\n  STR_LOW_UC: \"LAVT\"\n  STR_HIGH_UC: \"HØJT\"\n  STR_VERY_HIGH: \"MEGET HØJT\"\n  STR_FUEL: \"BRÆNDSTOF>{ALT}{0}\"\n  STR_WEAPON_ONE: \"VÅBEN-1>{ALT}{0}\"\n  STR_NONE_UC: \"INGEN\"\n  STR_ROUNDS_: \"SKUD>{ALT}{0}\"\n  STR_WEAPON_TWO: \"VÅBEN-2>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"KORTRÆKKENDE JAGERFLY\"\n  STR_BASE_: \"Base>{0}\"\n  STR_NAME_UC: \"NAVN\"\n  STR_AMMO_: \"AMMO>{ALT}{0}\"\n  STR_CREW: \"BESÆTNING\"\n  STR_EQUIPMENT_UC: \"UDSTYR\"\n  STR_ARMOR: \"RUSTNING\"\n  STR_MAX: \"MAKS>{ALT}{0}\"\n  STR_ROOKIE: \"Konstabel\"\n  STR_SQUADDIE: \"Overkonstabel\"\n  STR_SERGEANT: \"Sergent\"\n  STR_CAPTAIN: \"Kaptajn\"\n  STR_COLONEL: \"Oberst\"\n  STR_COMMANDER: \"Øverstbefalende\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Vælg hold til {0}\"\n  STR_SORT_BY: \"SORTER EFTER ...\"\n  STR_ORIGINAL_ORDER: \"OPRINDELIG RÆKKEFØLGE\"\n  STR_MISSIONS2: \"MISSIONER\"\n  STR_KILLS2: \"DRAB\"\n  STR_WOUND_RECOVERY2: \"SÅRGENDANNELSE\"\n  STR_SPACE_AVAILABLE: \"TILGÆNGELIG PLADS>{ALT}{0}\"\n  STR_SPACE_USED: \"ANVENDT PLADS>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"ANVENDT PLADS\"\n  STR_RANK: \"RANG\"\n  STR_WOUNDED: \"SÅRET\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Udstyr til {0}\"\n  STR_DEFENSE_VALUE: \"Forsvarsværdi\"\n  STR_HIT_RATIO: \"TRÆFNINGSSUCCES\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}klar til{NEWLINE}landing nær{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"Begynd mission?\"\n  STR_SELECT_ARMAMENT: \"Vælg udrustning\"\n  STR_AMMUNITION_AVAILABLE: \"AMMUNITION TIL RÅDIGHED\"\n  STR_ARMAMENT: \"BEVÆBNING\"\n  STR_NOT_AVAILABLE: \"-\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"VÆLG RUSTNING FOR{NEWLINE}{0}\"\n  STR_TYPE: \"TYPE\"\n  STR_PERSONAL_ARMOR_UC: \"PERSONLIG RUSTNING\"\n  STR_POWER_SUIT_UC: \"KRAFTVEST\"\n  STR_FLYING_SUIT_UC: \"FLYVENDE VEST\"\n  STR_SELECT_ARMOR: \"Vælg rustning\"\n  STR_NORTH: \"NORD\"\n  STR_NORTH_EAST: \"NORDØST\"\n  STR_EAST: \"ØST\"\n  STR_SOUTH_EAST: \"SYDØST\"\n  STR_SOUTH: \"SYD\"\n  STR_SOUTH_WEST: \"SYDVEST\"\n  STR_WEST: \"VEST\"\n  STR_NORTH_WEST: \"NORDVEST\"\n  STR_SELECT_ACTION: \"VÆLG HANDLING\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"FORTSÆT FORFØLGELSEN AF UFOEN\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"EFTERFØLG UDEN AT ANGRIBE\"\n  STR_VERY_LARGE: \"MEGET STOR\"\n  STR_LARGE: \"STOR\"\n  STR_MEDIUM_UC: \"MELLEM\"\n  STR_SMALL: \"LILLE\"\n  STR_VERY_SMALL: \"MEGET LILLE\"\n  STR_GROUNDED: \"JORDEN\"\n  STR_DETECTED: \"Detekteret\"\n  STR_SIZE_UC: \"STØRRELSE\"\n  STR_ALTITUDE: \"HØJDE\"\n  STR_HEADING: \"RETNING\"\n  STR_SPEED: \"HASTIGHED\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"CENTRER PÅ UFO-TID=5 sek.\"\n  STR_TRACKING_LOST: \"SIGNAL MISTET\"\n  STR_REDIRECT_CRAFT: \"OMDIRIGER FLY\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"FORTSÆT TIL UFOENS SIDST KENDTE POSITION\"\n  STR_UFO_: \"UFO-{0}\"\n  STR_ALIEN_BASE_: \"RUMVÆSENBASE-{0}\"\n  STR_CRASH_SITE_: \"NEDSTYRTNINGSOMRÅDE-{0}\"\n  STR_LANDING_SITE_: \"LANDINGSSTED-{0}\"\n  STR_WAY_POINT_: \"VIA-PUNKT-{0}\"\n  STR_TERROR_SITE: \"TERRORSTED-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}er ankommet{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"Patruljerer nu\"\n  STR_ALIEN_ORIGINS: \"Rumvæsenernes oprindelse\"\n  STR_THE_MARTIAN_SOLUTION: \"Mars-løsningen\"\n  STR_CYDONIA_OR_BUST: \"Cydonien eller døden\"\n  STR_UFOPAEDIA: \"UFOpædi\"\n  STR_XCOM_CRAFT_ARMAMENT: \"X-COM-FLY & UDRUSTNING\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"TUNGE VÅBENPLATFORME\"\n  STR_WEAPONS_AND_EQUIPMENT: \"VÅBEN OG UDSTYR\"\n  STR_ALIEN_ARTIFACTS: \"RUMVÆSENERNES UDSTYR\"\n  STR_BASE_FACILITIES: \"BASEFACILITETER\"\n  STR_ALIEN_LIFE_FORMS: \"RUMVÆSENERNES LIVSFORMER\"\n  STR_ALIEN_RESEARCH_UC: \"RUMVÆSENFORSKNING\"\n  STR_UFO_COMPONENTS: \"UFO-KOMPONENTER\"\n  STR_UFOS: \"Ufoer\"\n  STR_SELECT_ITEM: \"VÆLG PUNKT\"\n  STR_ACCELERATION: \"ACCELERATION>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"BRÆNDSTOFKAPACITET>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"VÅBENPLADSER>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"SKADE-KAPACITET>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"LASTRUM>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"KAPACITET FOR TUNGE VÅBEN>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Skade\"\n  STR_RANGE: \"Afstand\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Præcision\"\n  STR_RE_LOAD_TIME: \"Ladetid\"\n  STR_SECONDS: \"{0}er\"\n  STR_DAMAGE_ARMOR_PIERCING: \"PANSERBRYDENDE\"\n  STR_DAMAGE_INCENDIARY: \"BRANDSTIFTENDE\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"DYNAMIT\"\n  STR_DAMAGE_LASER_BEAM: \"LASERSTRÅLE\"\n  STR_DAMAGE_PLASMA_BEAM: \"PLASMASTRÅLE\"\n  STR_DAMAGE_STUN: \"BEDØV\"\n  STR_DAMAGE_MELEE: \"NÆRKAMP\"\n  STR_DAMAGE_ACID: \"SYRE\"\n  STR_DAMAGE_SMOKE: \"RØG\"\n  STR_SHOT_TYPE: \"SKUDTYPE\"\n  STR_ACCURACY_UC: \"TRÆFSIKKERHED\"\n  STR_TIME_UNIT_COST: \"TE-FORBRUG\"\n  STR_DAMAGE_UC: \"SKADE\"\n  STR_AMMO: \"AMMO\"\n  STR_SHOT_TYPE_AUTO: \"Automatisk\"\n  STR_SHOT_TYPE_SNAP: \"Hurtig\"\n  STR_SHOT_TYPE_AIMED: \"Sigtet\"\n  STR_CONSTRUCTION_TIME: \"Konstruktionstid\"\n  STR_CONSTRUCTION_COST: \"Konstruktionsomkostninger\"\n  STR_MAINTENANCE_COST: \"Vedligeholdelsesomkostninger\"\n  STR_LOW: \"Lav\"\n  STR_MEDIUM: \"Mellem\"\n  STR_HIGH: \"Høj\"\n  STR_CRAFT_WEAPON: \"Våben til fly\"\n  STR_CRAFT_AMMUNITION: \"Ammunition til fly\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Tung våbenplatform\"\n  STR_WEAPON: \"Våben\"\n  STR_AMMUNITION: \"Ammunition\"\n  STR_EQUIPMENT: \"Udstyr\"\n  STR_ALIEN_CORPSE: \"Rumvæsenlig\"\n  STR_UFO_COMPONENT: \"Ufo-komponent\"\n  STR_PERSONAL_ARMOR: \"Personlig vest\"\n  STR_RAW_MATERIALS: \"Råmaterialer\"\n  STR_HWP_CANNON_SHELLS: \"TVP - granater\"\n  STR_ALIEN: \"Rumvæsen\"\n  STR_SECTOID: \"Sectoid\"\n  STR_SNAKEMAN: \"Slangemand\"\n  STR_ETHEREAL: \"Ethereal\"\n  STR_MUTON: \"Muton\"\n  STR_FLOATER: \"Flyder\"\n  STR_CELATID: \"Celatid\"\n  STR_SILACOID: \"Silacoid\"\n  STR_CHRYSSALID: \"Chryssalid\"\n  STR_ZOMBIE: \"Zombie\"\n  STR_REAPER: \"Reaper\"\n  STR_SECTOPOD: \"Sectopod\"\n  STR_CYBERDISC: \"Cyberdisk\"\n  STR_LIVE_COMMANDER: \"Øverstbefalende\"\n  STR_LIVE_LEADER: \"Leder\"\n  STR_LIVE_ENGINEER: \"Ingenør\"\n  STR_LIVE_MEDIC: \"Samarit\"\n  STR_LIVE_NAVIGATOR: \"Navigatør\"\n  STR_LIVE_SOLDIER: \"Soldat\"\n  STR_LIVE_TERRORIST: \"Terrorist\"\n  STR_FLOATER_SOLDIER: \"Flyder - soldat\"\n  STR_FLOATER_NAVIGATOR: \"Flyder - navigatør\"\n  STR_FLOATER_MEDIC: \"Flyder - samarit\"\n  STR_FLOATER_ENGINEER: \"Flyder - ingeniør\"\n  STR_FLOATER_LEADER: \"Flyder - leder\"\n  STR_FLOATER_COMMANDER: \"Flyder - øverstbefalende\"\n  STR_SECTOID_SOLDIER: \"Sektoid - soldat\"\n  STR_SECTOID_NAVIGATOR: \"Sektoid - navigatør\"\n  STR_SECTOID_MEDIC: \"Sectoid- samarit\"\n  STR_SECTOID_ENGINEER: \"Sektoid - ingeniør\"\n  STR_SECTOID_LEADER: \"Sektoid - leder\"\n  STR_SECTOID_COMMANDER: \"Sektoid - øverstbefalende\"\n  STR_SNAKEMAN_SOLDIER: \"Slangemand - soldat\"\n  STR_SNAKEMAN_NAVIGATOR: \"Slangemand - navigatør\"\n  STR_SNAKEMAN_ENGINEER: \"Slangemand - ingeniør\"\n  STR_SNAKEMAN_LEADER: \"Slangemand - leder\"\n  STR_SNAKEMAN_COMMANDER: \"Slangemand - øverstbefalende\"\n  STR_MUTON_SOLDIER: \"Muton - soldat\"\n  STR_MUTON_NAVIGATOR: \"Muton - navigatør\"\n  STR_MUTON_ENGINEER: \"Muton - ingeniør\"\n  STR_ETHEREAL_SOLDIER: \"Ethereal - soldat\"\n  STR_ETHEREAL_LEADER: \"Ethereal - leder\"\n  STR_ETHEREAL_COMMANDER: \"Ethereal - øverstbefalende\"\n  STR_CYBERDISC_TERRORIST: \"Cyberdisk - terrorist\"\n  STR_REAPER_TERRORIST: \"Reaper - terrorist\"\n  STR_CHRYSSALID_TERRORIST: \"Chryssalid - terrorist\"\n  STR_CELATID_TERRORIST: \"Celatid - terrorist\"\n  STR_SILACOID_TERRORIST: \"Silacoid - terrorist\"\n  STR_SECTOPOD_TERRORIST: \"Sectopod - terrorist\"\n  STR_UFO_POWER_SOURCE: \"Ufo-strømkilde\"\n  STR_UFO_NAVIGATION: \"Ufo-navigation\"\n  STR_UFO_CONSTRUCTION: \"Ufo-konstruktion\"\n  STR_ALIEN_FOOD: \"Rumvæsenmad\"\n  STR_ALIEN_REPRODUCTION: \"Rumvæsenreproduktion\"\n  STR_ALIEN_ENTERTAINMENT: \"Rumvæsenunderholdning\"\n  STR_ALIEN_SURGERY: \"Rumvæsenoperation\"\n  STR_EXAMINATION_ROOM: \"Undersøgelseslokale\"\n  STR_ALIEN_ALLOYS: \"Rumvæsenlegering\"\n  STR_ALIEN_HABITAT: \"Rumvæsenhabitat\"\n  STR_POWER_SUIT: \"Kraftvest\"\n  STR_FLYING_SUIT: \"Flyvevest\"\n  STR_HWP_ROCKETS: \"TVP-raketter\"\n  STR_HWP_FUSION_BOMB: \"TVP-fusionsbombe\"\n  STR_LASER_WEAPONS: \"Laservåben\"\n  STR_NEW_FIGHTER_CRAFT: \"Nyt kampfly\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Nyt kampfly/transportfly\"\n  STR_ULTIMATE_CRAFT: \"Ultimativt fly\"\n  STR_LASER_PISTOL: \"Laserpistol\"\n  STR_LASER_RIFLE: \"Lasergevær\"\n  STR_HEAVY_LASER: \"Tung laser\"\n  STR_LASER_CANNON: \"Laserkanon\"\n  STR_PLASMA_CANNON: \"Plasmakanon\"\n  STR_FUSION_MISSILE: \"Fusionmissil\"\n  STR_LASER_DEFENSE: \"Laserforsvar\"\n  STR_PLASMA_DEFENSE: \"Plasmaforsvar\"\n  STR_FUSION_DEFENSE: \"Fusionforsvar\"\n  STR_GRAV_SHIELD: \"Grav.-skjold\"\n  STR_MIND_SHIELD: \"Hjerneskjold\"\n  STR_PSI_LAB: \"Psi-lab.\"\n  STR_MOTION_SCANNER: \"Bevægelsesskanner\"\n  STR_MEDI_KIT: \"Førstehjælpssæt\"\n  STR_TANK_CANNON: \"Kampvogn/kanon\"\n  STR_TANK_ROCKET_LAUNCHER: \"Tank/raketstyr\"\n  STR_TANK_LASER_CANNON: \"Tank/laserkanon\"\n  STR_HOVERTANK_PLASMA: \"Hovertank/plasma\"\n  STR_HOVERTANK_LAUNCHER: \"Hovertank/raketstyr\"\n  STR_STINGRAY_LAUNCHER: \"Pilrokke-raketstyr\"\n  STR_AVALANCHE_LAUNCHER: \"Avalanche-raketstyr\"\n  STR_CANNON: \"Kanon\"\n  STR_FUSION_BALL_LAUNCHER: \"Fusionskugle-raketstyr\"\n  STR_PLASMA_BEAM: \"Plasmastråle\"\n  STR_STINGRAY_MISSILES: \"Pilrokke-missiler\"\n  STR_AVALANCHE_MISSILES: \"Avalanche-missiler\"\n  STR_CANNON_ROUNDS_X50: \"Kanonskud(x50)\"\n  STR_FUSION_BALL: \"Fusionskugle\"\n  STR_SOLDIER: \"Soldat\"\n  STR_SCIENTIST: \"Forsker\"\n  STR_ENGINEER: \"Ingeniør\"\n  STR_NORTH_AMERICA: \"Nordamerika\"\n  STR_ARCTIC: \"Arktis\"\n  STR_ANTARCTICA: \"Antarktis\"\n  STR_SOUTH_AMERICA: \"Sydamerika\"\n  STR_EUROPE: \"Europa\"\n  STR_NORTH_AFRICA: \"Nordafrika\"\n  STR_SOUTHERN_AFRICA: \"Sydlige Afrika\"\n  STR_CENTRAL_ASIA: \"Centralasien\"\n  STR_SOUTH_EAST_ASIA: \"Sydøstlige Asien\"\n  STR_SIBERIA: \"Siberien\"\n  STR_AUSTRALASIA: \"Australasien\"\n  STR_PACIFIC: \"Stillehavet\"\n  STR_NORTH_ATLANTIC: \"Nordatlanterhavet\"\n  STR_SOUTH_ATLANTIC: \"Sydatlanterhavet\"\n  STR_INDIAN_OCEAN: \"Indiske Ocean\"\n  STR_ALIEN_RESEARCH: \"Rumvæsen-forskning\"\n  STR_ALIEN_HARVEST: \"Rumvæsen-høst\"\n  STR_ALIEN_ABDUCTION: \"Rumvæsen-bortførelse\"\n  STR_ALIEN_INFILTRATION: \"Rumvæsen-infiltration\"\n  STR_ALIEN_BASE: \"Rumvæsen-base\"\n  STR_ALIEN_TERROR: \"Rumvæsen-terror\"\n  STR_ALIEN_RETALIATION: \"Rumvæsen-gengældelse\"\n  STR_ALIEN_SUPPLY: \"Rumvæsen-forsyninger\"\n  STR_MAXIMUM_SPEED: \"Maksimalt hastighed\"\n  STR_HYPER_WAVE_DECODER_UC: \"HYPERBØLGE-AFKODER\"\n  STR_SKYRANGER: \"SKYRANGER\"\n  STR_LIGHTNING: \"LYNET\"\n  STR_AVENGER: \"HÆVNER\"\n  STR_INTERCEPTOR: \"KORTRÆKKENDE JAGERFLY\"\n  STR_FIRESTORM: \"ILDSTORM\"\n  STR_UFO: \"UFO\"\n  STR_STINGRAY: \"PILROKKE\"\n  STR_AVALANCHE: \"AVALANCHE\"\n  STR_CANNON_UC: \"KANON\"\n  STR_FUSION_BALL_UC: \"FUSIONSKUGLE\"\n  STR_LASER_CANNON_UC: \"LASERKANON\"\n  STR_PLASMA_BEAM_UC: \"PLASMASTRÅLE\"\n  STR_DAMAGE_CAPACITY: \"Skadeskapacitet\"\n  STR_WEAPON_POWER: \"Våbenkraft\"\n  STR_WEAPON_RANGE: \"Våbenafstand\"\n  STR_ACCESS_LIFT: \"Adgangslift\"\n  STR_LABORATORY: \"Laboratorium\"\n  STR_WORKSHOP: \"Værksted\"\n  STR_SMALL_RADAR_SYSTEM: \"Lille radarsystem\"\n  STR_LARGE_RADAR_SYSTEM: \"Stort radarsystem\"\n  STR_MISSILE_DEFENSES: \"Missilforsvar\"\n  STR_GENERAL_STORES: \"Lager\"\n  STR_ALIEN_CONTAINMENT: \"Opb.rum til rumvæsener\"\n  STR_LASER_DEFENSES: \"Laserforsvar\"\n  STR_PLASMA_DEFENSES: \"Plasmaforsvar\"\n  STR_FUSION_BALL_DEFENSES: \"Fusionkugleforsvar\"\n  STR_PSIONIC_LABORATORY: \"Laboratorium for overnaturlige evner\"\n  STR_HYPER_WAVE_DECODER: \"Hyperbølge-afkoder\"\n  STR_HANGAR: \"Hangar\"\n  STR_USA: \"USA\"\n  STR_RUSSIA: \"RUSLAND\"\n  STR_UK: \"STORBRITANNIEN\"\n  STR_FRANCE: \"FRANKRIG\"\n  STR_GERMANY: \"TYSKLAND\"\n  STR_ITALY: \"ITALIEN\"\n  STR_SPAIN: \"SPANIEN\"\n  STR_CHINA: \"KINA\"\n  STR_JAPAN: \"JAPAN\"\n  STR_INDIA: \"INDIEN\"\n  STR_BRAZIL: \"BRASILIEN\"\n  STR_AUSTRALIA: \"AUSTRALIEN\"\n  STR_NIGERIA: \"NIGERIA\"\n  STR_SOUTH_AFRICA: \"SYDAFRIKA\"\n  STR_EGYPT: \"ÆGYPTEN\"\n  STR_CANADA: \"CANADA\"\n  STR_TANK: \"Kampvogn\"\n  STR_CIVILIAN: \"Civilist\"\n  STR_JAN: \"Jan\"\n  STR_FEB: \"Feb\"\n  STR_MAR: \"Mar\"\n  STR_APR: \"Apr\"\n  STR_MAY: \"Maj\"\n  STR_JUN: \"Jun\"\n  STR_JUL: \"Jul\"\n  STR_AUG: \"Aug\"\n  STR_SEP: \"Sep\"\n  STR_OCT: \"Okt\"\n  STR_NOV: \"Nov\"\n  STR_DEC: \"Dec\"\n  STR_INTERNATIONAL_RELATIONS: \"Internationale relationer\"\n  STR_COUNTRY: \"Land\"\n  STR_FUNDING: \"Midler\"\n  STR_CHANGE: \"Ændr\"\n  STR_WEAPON_SYSTEMS: \"VÅBENSYSTEMER\"\n  STR_HWPS: \"TVP'er\"\n  STR_DAMAGE_UC_: \"ØDELÆGGELSE>{ALT}{0}\"\n  STR_ACCESS_LIFT_UFOPEDIA: \"Adgangsliften giver mulighed for at udstyr og personale kan føres ind og ud af en underjordisk base. Det er altid det første anlæg, der skal bygges på et nyt sted. Indgangspartiet er sårbart over for indtrængen fra enhver potentiel fjendtlig styrke.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Hvert indkvarteringsafsnit giver op to 50 personer soveplads, spiseplads og rekreative områder.\"\n  STR_LABORATORY_UFOPEDIA: \"Op til 50 videnskabsmænd kan arbejde i et laboratorium. Laboratorier er udstyret med den seneste teknologi for forskning i materialer, biokemi og kosmologi. Der er privilegeret adgang til de bedste forskningslaboratorier udover hele verden, inklusive militære faciliteter.\"\n  STR_WORKSHOP_UFOPEDIA: \"Et værksted indeholder alt det nødvendige udstyr til at fremstille udstyr, som er baseret på design fra forskernes laboratorier. Op til 50 ingeniører kan opholde sig i et værksted, men tingene som er under produktion, optager også noget plads.\"\n  STR_SMALL_RADAR_SYSTEM_UFOPEDIA: \"Et lille radarsystem har en effektiv rækkevidde på 300 nautiske mil og er forbundet med satellitsystemer til afsøgning af landjorden. Hvert system har en 10 % sandsynlighed for at detektere et objekt med gennemsnitligt størrelse hvert 30. minut.\"\n  STR_LARGE_RADAR_SYSTEM_UFOPEDIA: \"Et stort radarsystem har en effektiv rækkevidde på 450 sømil og er forbundet med et satellitsystem for søgning på jorden. Hvert system har en 20 % sandsynlighed for at detektere et objekt med gennemsnitlig størrelse hver 30 minut.\"\n  STR_MISSILE_DEFENSES_UFOPEDIA: \"Missilforsvar tilbyder beskyttelse mod angreb fra fjendtlige fly, som forsøger at lange nær basen.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"Alt udstyr, våbensystemer, ammunition, opsamlede materialer og tunge våbenplatforme placeres i lagerrum, inklusive udstyr for dine fly.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"Levende rumvæsener vil sandsynligvis have brug for et særligt miljø for at opretholde deres livsfunktioner. Opbevaringsanlægget kan huse op til 10 forskellige rumvæsener i uafhængige afdelinger.\"\n  STR_LASER_DEFENSES_UFOPEDIA: \"Laserforsvar tilbyder beskyttelse mod angreb fra fjendtlige fly.\"\n  STR_PLASMA_DEFENSES_UFOPEDIA: \"Plasmaforsvaret yder et stærkt og effektivt forsvar mod angreb fra fjendtlige fly.\"\n  STR_FUSION_BALL_DEFENSES_UFOPEDIA: \"Fusionmissiler yder det bedste forsvar mod angreb fra rumvæsenerne. Disse missiler opretter en antistof-implosion, som ødelægger alt indenfor en bestemt radius.\"\n  STR_GRAV_SHIELD_UFOPEDIA: \"Tyngdekraft-skjoldet afviser rumvæsenernes flys forsøg på at lande nær basen længe nok til at alle forsvarssystemer kan skyde igen. I praksis vil dette fordoble effektivitet for alle vores forsvarssystemer på basen.\"\n  STR_MIND_SHIELD_UFOPEDIA: \"Da rumvæsenernes fly afhænger af hjernebølger for at opfange vores tilstedeværelse, er den mest effektive modforanstaltning at skærme hjernebølger fra basen. Denne facilitet vil drastisk reducere risikoen for detektion fra rumvæsenernes fly.\"\n  STR_PSIONIC_LABORATORY_UFOPEDIA: \"Laboratoriet for overnaturlige evner kan udnytte potentialet hos alle soldater på basen, og give dem den nødvendige træning i at udnytte dette potentiale. Hvert laboratorium kan træne op til ti soldater. Træning er allokeret i slutningen af hver måned. Evnerne, brugt i sammenhæng med en psy-fs, kan bruges til angreb under kamp.\"\n  STR_HYPER_WAVE_DECODER_UFOPEDIA: \"Rumvæsenernes kommunikation afhænger af en supra-dimensionel bølge, som overføres næsten øjeblikkeligt. Afkodningsenheden opfanger ufo-transmission og afkoder denne information. Dette vil vise ufo-typen, racen på rumvæsenerne og aktivitetstypen.\"\n  STR_HANGAR_UFOPEDIA: \"Hver hangar kan rumme et fartøj. En hangar indeholder faciliteter til vedligeholdelse, tankning og reparation af X-Coms fartøjer. Hvert fartøj stationeret på en base skal have tildelt en hangar, der så ikke kan benyttes af andre fartøjer, selv hvis fartøjet der har fået tildelt hangaren er ude på mission.\"\n  STR_PISTOL_UFOPEDIA: \"X-Coms standardpistol er en kraftig semiautomatisk pistol med op til 12 skud i magasinet.\"\n  STR_RIFLE_UFOPEDIA: \"Den meget præcise snigskytteriffel har laserstyring, bruger 6,7 mm ammunition og har 20 skud i magasinet.\"\n  STR_HEAVY_CANNON_UFOPEDIA: \"Den tunge kanon er ødelæggende, men tung. Dens alsidighed beror på at den kan anvende tre slags ammunition - panserbrydende, brandbomber og dynamit.\"\n  STR_AUTO_CANNON_UFOPEDIA: \"Auto-kanonen kombinerer alsidigheden og kraften i den tunge kanon med en hurtigere skudhastighed.\"\n  STR_ROCKET_LAUNCHER_UFOPEDIA: \"Raketkasteren er et laserstyret system, der kan affyre missiler i tre forskellige størrelser.\"\n  STR_LASER_PISTOL_UFOPEDIA: \"Laserpistolen er en effektiv implementering af ny teknologi. Den giver fordelen af en pistol med hurtigere og mere præcis skudafgivelse.\"\n  STR_LASER_RIFLE_UFOPEDIA: \"Laserriflen er en mere kraftig og præcis version af det tidligere pistoldesign.\"\n  STR_HEAVY_LASER_UFOPEDIA: \"Den tunge laser er svær at håndtere, men særdeles effektiv.\"\n  STR_GRENADE_UFOPEDIA: \"Denne standardhåndgranat har en præcis og sofistikeret tidsudløser til præcisionskontrol.\"\n  STR_SMOKE_GRENADE_UFOPEDIA: \"Røggranater er velegnede til at give et ekstra dække i en ellers eksponeret kampsituation. Brug med omtanke, da fjenden også kan få gavn af dem.\"\n  STR_PROXIMITY_GRENADE_UFOPEDIA: \"En bevægelsesgranat kan kastes som en almindelig granat, men udløses af nærliggende bevægelse efter den lander. Stor dygtighed og omhu er nødvendig for at bruge disse enheder korrekt.\"\n  STR_HIGH_EXPLOSIVE_UFOPEDIA: \"Dette sprængstof bør kun bruges til nedrivning. Hold personel på afstand af sprængningsområdet.\"\n  STR_MOTION_SCANNER_UFOPEDIA: \"Denne sofistikerede anordning bruger en række sensorer og avancerede computeralgoritmer til at identificere fjendtlige enheder i bevægelse. Den kræver dog noget øvelse at bruge effektivt. Klik på ikonet for bevægelsesskanneren på den taktiske skærm, og vælg dernæst »Brug skanner« på menuen. Skannerens display viser en pil i midten, hvilket viser den retning soldaten kigger (nord er opad). De blinkende pletter viser enheder, der har bevæget sig for nyligt. Store enheder, eller hurtige enheder resulterer i større pletter. Stillestående enheder bliver ikke opfattet.\"\n  STR_MEDI_KIT_UFOPEDIA: \"Førstehjælpskassen kombinerer en helbredende facilitet med smertestillende medicin og stimulanser. For at kunne bruge førstehjælpskassen skal du vende mod den soldat, der skal bruge behandling. Hvis soldaten er bedøvet, skal du stå over kroppen. Klik på ikonet førstehjælpskasse og vælg »Brug førstehjælp« i menuen.{NEWLINE}HELBRED> Røde kropsdele viser dødelige sår. Klik på en kropsdel​​, der er såret. Klik på knappen »Helbred«. Et fatalt sår vil blive helbredt og noget liv genoprettet.{NEWLINE}STIMULANS> Dette vil genoprette energi og genoplive bedøvede soldater. For at genoplive en bevidstløs soldat skal du stå direkte over kroppen.{NEWLINE}SMERTESTILLENDE> Denne handling vil genoprette moralen hos sårede soldater op til et beløb svarende til soldatens tabte liv.\"\n  STR_PSI_AMP_UFOPEDIA: \"Psi-amp kan kun bruges af soldater med overnaturlige evner. Under kamp, skal du klikke på psi-amp, vælge angrebstype, og vælge en målenhed med markøren. Der er to typer af overnaturlige angreb:{NEWLINE}SKAB PANIK> Hvis angrebet lykkes vil det reducere ofrets moral, og kan få det til at gå i panik.{NEWLINE}TANKEKONTROL> Hvis dette lykkes, så vil du få umiddelbar kontrol over den fjendtlige enhed, som hvis det var en af ​​dine egne. Det er vanskeligere at få succes med denne type angreb.\"\n  STR_STUN_ROD_UFOPEDIA: \"Denne anordning kan kun bruges i nærkamp, men vil lamme en levende organisme uden at slå den ihjel ved brug af elektrisk stød.\"\n  STR_MIND_PROBE_UFOPEDIA: \"Sindelagssonden er en kommunikationsenhed, rumvæsenerne anvender, og som bruges til at indhente information direkte fra hjernebølger. X-Com-enheder kan bruge denne enhed i kamp for at vise karakteristika på et rumvæsen. Klik på sindelagssonden og valgmuligheden »anvend«. Klik så på et rumvæsen med markøren.\"\n  STR_PLASMA_PISTOL_UFOPEDIA: \"Plasmapistoler et et dødeligt våben blandt rumvæsenerne baseret på accelererende partikler inden fra et anti-tyngdekraftfelt. \"\n  STR_PLASMA_RIFLE_UFOPEDIA: \"Dette er et frygteligt kraftigt våben baseret på accelererende partikler, kommende indefra et minut anti-tyngdekraftfelt\"\n  STR_HEAVY_PLASMA_UFOPEDIA: \"Dette er et frygteligt kraftigt våben baseret på accelererende partikler, kommende indefra et minut anti-tyngdekraftfelt\"\n  STR_BLASTER_LAUNCHER_UFOPEDIA: \"Dette er en guidet missilraketstyr hos rumvæsenerne som affyrer kraftige »blasterbomber«. Når du klikker for at affyre våbenet vil det oprette via-punkter som blaserbomben følger. Når du har placeret nok via-punkter, klikker du på det specielle startikon.\"\n  STR_SMALL_LAUNCHER_UFOPEDIA: \"Et lille raketstyr, som affyrer en lille bedøvelsesbombe. Meget praktisk til at fange rumvæsener.\"\n  STR_ALIEN_GRENADE_UFOPEDIA: \"Denne enhed virker på samme måde som en jordbaseret håndgranat - ud over at den er langt mere kraftfuld.\"\n  STR_SMALL_SCOUT: \"Lille spejder\"\n  STR_MEDIUM_SCOUT: \"Medium spejder\"\n  STR_LARGE_SCOUT: \"Stor spejder\"\n  STR_HARVESTER: \"Høster\"\n  STR_ABDUCTOR: \"Bortfører\"\n  STR_TERROR_SHIP: \"Terrorskib\"\n  STR_BATTLESHIP: \"Kampskib\"\n  STR_SUPPLY_SHIP: \"Forsyningsskib\"\n  STR_RATING: \"BEDØMMELSE> {0}\"\n  STR_RATING_TERRIBLE: \"FORFÆRDELIGT!\"\n  STR_RATING_POOR: \"DÅRLIG!\"\n  STR_RATING_OK: \"O.k.\"\n  STR_RATING_GOOD: \"GODT!\"\n  STR_RATING_EXCELLENT: \"FANTASTISK!\"\n  STR_SCORE: \"POINT\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"DEN MÅNEDLIGE RAPPORT FOR X-COM-PROJEKTET\"\n  STR_MONTH: \"Måned> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"Rådet af de økonomisk støttende nationer er generelt tilfredse med din fremgang indtil videre.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"Rådet af de økonomisk støttende nationer er godt tilfredse med din udmærkede præstation. Fortsæt det gode arbejde.\"\n  STR_COUNCIL_IS_DISSATISFIED: \"Rådet af de økonomisk støttende nationer er utilfredse med din indsats. Du må håndtere den fremmede trussel mere effektivt eller risikere, at projektet lukkes ned.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"Du har fejlet i at håndtere truslen fra rumvæsenerne, og rådet af økonomisk støttende nationer har desværre besluttet sig for at lukke projektet. Hver nation vil selv tage sig af problemet på måder de selv finder fordelagtige. Vi kan kun håbe, at vi i sidste ende får tilpasset os disse åbenbart fjendtlige styrker, og at befolkningen som helhed kan affinde sig med de fremmede.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} er særlig tilfreds med din evne til at håndtere den lokalbestemte trussel og har indvilget i at øge deres bidrag.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} er særligt tilfredse med dine fremskridt i at håndtere rumvæsenernes indtrængen på deres område og er gået med til at øge deres bidrag. \"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} og {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} er utilfreds med din evne til at håndtere rumvæsenernes aktivitet i deres område og har besluttet at reducere deres økonomiske bidrag.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} er ikke tilfreds med din evne til at håndtere rumvæsenernes aktivitet i deres område og har derfor besluttet at reducere deres bidrag.\"\n  STR_KNOTS: \"{0} knob\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} har underskrevet en hemmelig pagt med ukendte fremmede kræfter og har trukket sin støtte til projektet.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} har underskrevet en hemmelig pagt med en ukendt styrke af rumvæsener og har trukket sig fra projektet.\"\n  STR_MONTHLY_RATING: \"Månedlig bedømmelse> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Ændring i bidrag> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"Rådet af økonomisk støttende nationer er ikke tilfredse med din finansielle position. Du er blevet pålagt at reducere din gæld til under $1 million, ellers vil projektet blive nedlagt.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"HYPERBØLGE-TRANSMISSIONER ER AFKODET\"\n  STR_CRAFT_TYPE: \"FLYTYPE\"\n  STR_RACE: \"RACE\"\n  STR_MISSION: \"MISSION\"\n  STR_ZONE: \"ZONE\"\n  STR_ALLOCATE_RESEARCH: \"Start forskning\"\n  STR_ALLOCATE_MANUFACTURE: \"Start produktion\"\n  STR_NEW_YORK: \"New York\"\n  STR_WASHINGTON: \"Washington\"\n  STR_LOS_ANGELES: \"Los Angeles\"\n  STR_MONTREAL: \"Montreal\"\n  STR_HAVANA: \"Havana\"\n  STR_MEXICO_CITY: \"Mexico City\"\n  STR_CHICAGO: \"Chicago\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_DALLAS: \"Dallas\"\n  STR_BRASILIA: \"Brasilia\"\n  STR_BOGOTA: \"Bogota\"\n  STR_BUENOS_AIRES: \"Buenos Aires\"\n  STR_SANTIAGO: \"Santiago\"\n  STR_RIO_DE_JANEIRO: \"Rio De Janeiro\"\n  STR_LIMA: \"Lima\"\n  STR_CARACAS: \"Caracas\"\n  STR_LONDON: \"London\"\n  STR_PARIS: \"Paris\"\n  STR_BERLIN: \"Berlin\"\n  STR_MOSCOW: \"Moskva\"\n  STR_ROME: \"Rom\"\n  STR_MADRID: \"Madrid\"\n  STR_BUDAPEST: \"Budapest\"\n  STR_LAGOS: \"Lagos\"\n  STR_CAIRO: \"Kairo\"\n  STR_CASABLANCA: \"Casablanca\"\n  STR_PRETORIA: \"Pretoria\"\n  STR_NAIROBI: \"Nairobi\"\n  STR_CAPE_TOWN: \"Cape Town\"\n  STR_KINSHASA: \"Kinshasa\"\n  STR_ANKARA: \"Ankara\"\n  STR_DELHI: \"Delhi\"\n  STR_KARACHI: \"Karachi\"\n  STR_BAGHDAD: \"Bagdad\"\n  STR_TEHRAN: \"Teheran\"\n  STR_BOMBAY: \"Bombay\"\n  STR_CALCUTTA: \"Calcutta\"\n  STR_TOKYO: \"Tokyo\"\n  STR_BEIJING: \"Beijing\"\n  STR_BANGKOK: \"Bangkok\"\n  STR_MANILA: \"Manila\"\n  STR_SEOUL: \"Seoul\"\n  STR_SINGAPORE: \"Singapore\"\n  STR_JAKARTA: \"Jakarta\"\n  STR_SHANGHAI: \"Shanghai\"\n  STR_HONG_KONG: \"Hong Kong\"\n  STR_NOVOSIBIRSK: \"Novosibirsk\"\n  STR_CANBERRA: \"Canberra\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_MELBOURNE: \"Melbourne\"\n  STR_PERTH: \"Perth\"\n  STR_PSI_TRAINING: \"Psi-træning\"\n  STR_PSIONIC_TRAINING: \"PSI-TRÆNING\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Resterende Psi-lab-kapacitet> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"Psi{NEWLINE}Styrke\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"Psi-evne{NEWLINE}/Forbedringer\"\n  STR_PSI_AMP: \"Psi-amp\"\n  STR_IN_TRAINING: \"I{NEWLINE}Træning?\"\n  STR_TARGETTED_BY: \"RETTET MOD:\"\n  STR_WEAPONS_CREW_HWPS: \"VÅBEN/{NEWLINE}MANDSKAB/TVP'er\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"mangler brændstof,{NEWLINE}vender tilbage til basen\"\n  STR_SOLDIER_LIST: \"Soldaterliste\"\n  STR_RANK_: \"RANG> {ALT}{0}\"\n  STR_MISSIONS: \"MISSIONER> {ALT}{0}\"\n  STR_KILLS: \"DRÆBT> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"SÅRGENDANNELSE> {ALT}{0}\"\n  STR_TIME_UNITS: \"TIDSENHEDER\"\n  STR_STAMINA: \"UDHOLDENHED\"\n  STR_HEALTH: \"HELBRED\"\n  STR_BRAVERY: \"MOD\"\n  STR_REACTIONS: \"REAKTION\"\n  STR_FIRING_ACCURACY: \"PRÆCISION VED SKUD\"\n  STR_THROWING_ACCURACY: \"PRÆCISION VED KAST\"\n  STR_STRENGTH: \"STYRKE\"\n  STR_PSIONIC_STRENGTH: \"PSI-STYRKE\"\n  STR_PSIONIC_SKILL: \"PSI-FÆRDIGHED\"\n  STR_NEW_RANK: \"NY RANG\"\n  STR_PROMOTIONS: \"Forfremmelser\"\n  STR_SOLDIERS_UC: \"SOLDATER\"\n  STR_TANK_CANNON_UFOPEDIA: \"Automatiserede tunge våbenplatforme er designet til at komplementære en X-Com-indsatsstyrke. Kombinationen af stor skudstyrke og stærk armering gør disse enheder værdifulde i åben terræn. Husk at have nok med granater på lager, så du kan lade tanken igen, når den løber tør. De lades automatisk, når du tildeler dem til en indsatsstyrke.\"\n  STR_TANK_ROCKET_LAUNCHER_UFOPEDIA: \"Denne automatiserede tunge våbenplatform er armeret med kraftfulde raketter. Denne vil være altødelæggende for enhver fjende fra rummet. Vær sikker på, at dit lager altid indeholder TVP-raketter.\"\n  STR_TANK_LASER_CANNON_UFOPEDIA: \"Laservåben er en nyttig tilføjelse for TVP'er. De har tung ildkraft uden krav om ammunition.\"\n  STR_HOVERTANK_PLASMA_UFOPEDIA: \"Rumvæsenteknologi har givet TVP'en nye anvendelsesmuligheder. Den forbedrede manøvredygtighed der opnås gennem luftfart og plasmastrålers styrke er en dødelig kombination.\"\n  STR_HOVERTANK_LAUNCHER_UFOPEDIA: \"Denne hovertank har et raketstyr for fusionskugler, som kan skabe enorme ødelæggelser. Brug den med stor omhu. Du skal producere fusionskugler for at holde disse TVP'e fuldt armerede. En fusionskugle er et intelligent guidet våben. For at skyde skal du vælge en række »via-punkter« med markøren og så klikke på startikonet for at affyre fusionskuglen. \"\n  STR_HEAVY_PLASMA_CLIP_UFOPEDIA: \"Denne kompakte anordning bliver brugt som ammunition til den tunge plasmapistol. Den indeholder en lille mængde elerium.\"\n  STR_PLASMA_RIFLE_CLIP_UFOPEDIA: \"Denne lille genstand bliver brugt som en energikilde til en plasmariffel - et våben af medium styrke hos rumvæsenerne. Indeholder en lille mængde elerium.\"\n  STR_PLASMA_PISTOL_CLIP_UFOPEDIA: \"Strømkilde for rumvæsenernes lille plasmapistol. Indeholder elerium - kilden til rumvæsenernes energi.\"\n  STR_STUN_BOMB_UFOPEDIA: \"Bedøvelsesbomben bruges til at fange individer i live, men kan også bruges med rumvæsenerne. Den affyres fra et lille raketstyr.\"\n  STR_ALIEN_RESEARCH_UFOPEDIA: \"Rumvæsenernes forskningsmission bruges til at indsamle grundlæggende data om jorden og dens beboere. Der bruges hovedsagelig små køretøjer, undertiden med landinger i øde områder. Denne type aktivitet hos rumvæsenerne udgør den mindste trussel for X-Com, med lille bekymring fra regeringer eller offentligheden.\"\n  STR_ALIEN_HARVEST_UFOPEDIA: \"Rumvæsenerne har mange anvendelsesområder for jordens fauna. Dyr bortføres i hemmelighed, og returneres med diverse fjernede organer. Kvæglemlæstelser rapporteres ofte sammen med ufo-observationer. Denne type af aktivitet blandt rumvæsenerne vækker stor bekymring hos regeringer og stor ængstelse i befolkningen. Denne type aktivitet forekommer hovedsagelig i landbrugsområder. Teorien bag »Rumvæsen - høst« antyder, at fremmede racer oprindelig »beplantede« jordens flora og fauna, og nu er vendt tilbage for at høste, det de har sået.\"\n  STR_ALIEN_ABDUCTION_UFOPEDIA: \"Dette er den mest snigende form for aktivitet blandt rumvæsenerne. Rumvæsenernes bortførsler er almindeligt rapporteret, på trods af rumvæsenernes forsøg på at slette erfaringerne fra deres ofres erindringer. Bortførte rapporterer at være underlagt ydmygende fysiske undersøgelser, herunder imprægnering af fremmede fostre og bizarre genetiske eksperimenter. Formålet bag denne aktivitet ser ud til at være forbundet med genetisk mutation og manipulation af rumvæsenernes eget genetiske materiale. Denne aktivitet medfører stor alarm, og forekommer i befolkede områder eller byer.\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"Jordens regeringer kan blive infiltreret af rumvæsenernes agenter der ligner mennesker i udseende. Dette kan resultere i officiel kontakt imellem rumvæsener og regeringernes højeste niveau. Højdepunktet af denne aktivitet vil være karakteriseret af intens ufo-aktivitet i nærheden af store byer. Rumvæsenerne vil forsøge at indgå en pagt med jordens regeringer ved at tilbyde viden om deres overlegne teknologi. Til gengæld vil regeringerne tillade rumvæsenernes aktivitet i deres område uden at gribe ind. Denne del af rumvæsenernes mission repræsenterer den største trussel mod X-Com. Hvis en regering indgår en pagt vil deres økonomiske støtte til X-Com ophøre.\"\n  STR_ALIEN_BASE_UFOPEDIA: \"Rumvæsenerne vil konstruere hemmelige undergrundsbaser på øde steder. Efter nogle rekognosceringer vil der opstå mere omfattende ufo-aktivitet når basen bliver bygget. Disse baser er kendt for at indeholde laboratorier der udfører forsøg på mennesker, der er blevet bortført og stå for leverancerne i forhold til yderligere aktivitet i området. Tilstedeværelsen af rumvæsenbaser vil skabe en masse rapporter vedrørende aktivitet blandt rumvæsenerne uden tilstedeværelsen af ufoer. For at finde en base skal et X-Com-fly patruljere i et område i nogle timer for at øge muligheden for detektering.\"\n  STR_ALIEN_TERROR_UFOPEDIA: \"Når rumvæsenerne terroriserer en by, vil de udsende nogle specielle styrker. Civile bliver direkte truet, og regeringerne vil blive tvunget til at evakuere hele områder. Hovedformålet bag denne aktivitet er, at generere tilstrækkelig offentlig hysteri, så regeringer vil true X-Com-projektet.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"Hvis X-Coms jagerfly har været meget succesfulde i deres nedkæmpning af ufoer vil rumvæsenerne måske iværksætte gengældelsesaktioner. Dette kan resultere i et direkte angreb på en X-Com-base, dog skal rumvæsenerne først finde en base for at kunne angribe den, hvis ufoerne bliver holdt på afstand vil der dog være en meget lille risiko for et angreb.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"Når først rumvæsenerne har anlagt en base, så forsynes den med regulære intervaller af et specielt forsyningsfly. Hvis et af disse fly detekteres under landing, så er det sikkert, at en af rumvæsenernes base ligger i området.\"\n  STR_SMALL_SCOUT_UFOPEDIA: \"Dette lille fartøj bruges primært til rekognoscering eller forskning. Det følges normalt efterfølgende af større fartøjer i begyndelsen af en rumvæsen-mission.\"\n  STR_MEDIUM_SCOUT_UFOPEDIA: \"Et mellemstort spejderfartøj der ikke udgør nogen særlig trussel for jordens styrker. Ses normalt inden større fartøjer under missioner.\"\n  STR_LARGE_SCOUT_UFOPEDIA: \"Det største af rumvæsenernes rekognosceringsfartøjer er et bredt anvendeligt fartøj som rumvæsenerne derfor bruger til alle typer missioner.\"\n  STR_HARVESTER_UFOPEDIA: \"Høsteren har en faldlem i sin base og er udstyret med løftegrej til at trække kvæg eller andre dyr op. Laserskærere bruges til at udvinde det ønskede materiale og kroppen dumpes på jorden. Der er også opbevaringsbeholdere for kropsdele.\"\n  STR_ABDUCTOR_UFOPEDIA: \"Dette fartøj er udstyret med et undersøgelsesrum til grusomme eksperimenter på mennesker. Offeret er normalt lammet af telepatiske kræfter men forbliver ved bevidsthed, mens det befinder sig på operationsbordet.\"\n  STR_TERROR_SHIP_UFOPEDIA: \"Terrorskibet har en opbevaringsfacilitet for store terrorvåben eller rumvæsener. Det bruges til at transportere disse rumvæsen-terrorister ind i befolkede områder.\"\n  STR_BATTLESHIP_UFOPEDIA: \"Slagskibet er det største og kraftigste fartøj hos rumvæsenerne. Det er normalt det primære missionsfartøj hos rumvæsenerne med kraftfulde våben og utallige besætningsmedlemmer.\"\n  STR_SUPPLY_SHIP_UFOPEDIA: \"Dette forsyningsfartøj bliver brugt til konstruktionen af rumvæsenernes baser og til at forsyne allerede etablerede baser. Det er læsset med rumvæsenernes fødevarer og reproduktionskamre.\"\n  STR_DISMANTLE: \"Nedlæg\"\n  STR_FACILITY_IN_USE: \"FACILITET ER I BRUG\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"KAN IKKE NEDLÆGGE FACILITET!{SMALLLINE}Alle basefaciliteter skal være forbundet til indgangspartiet.\"\n  STR_TRANSFER_ITEMS_TO: \"Overfør udstyr til {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"INTET OPB.RUM FOR RUMVÆSENER!{SMALLLINE}Levende rumvæsener kræver et opbevaringsrum for rumvæsener for at overleve.\"\n  STR_AMOUNT_AT_DESTINATION: \"MÆNGDE VED{NEWLINE}DESTINATION\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"Rumvæsenet dør, da der ikke er noget opbevaringsrum for rumvæsener\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"INGEN LEDIGE BEBOELSESRUM!{SMALLLINE}Destinationsbasen indeholder ikke nok plads til beboelsesplads til det mandskab, som er tildelt fartøjet.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"IKKE NOK LAGERRUM!{SMALLLINE}Destinationsbasen har ikke nok lagerrum for det udstyr, som er tildelt fartøjet.\"\n  STR_ITEMS_ARRIVING: \"Udstyr ankommer\"\n  STR_DESTINATION_UC: \"DESTINATION\"\n  STR_PISTOL: \"Pistol\"\n  STR_PISTOL_CLIP: \"Pistolmagasin\"\n  STR_RIFLE: \"Gevær\"\n  STR_RIFLE_CLIP: \"Geværmagasin\"\n  STR_HEAVY_CANNON: \"Tung kanon\"\n  STR_HC_AP_AMMO: \"HC-AP-ammunition\"\n  STR_HC_HE_AMMO: \"HC-HE-ammunition\"\n  STR_HC_I_AMMO: \"HCI-I-ammunition\"\n  STR_AUTO_CANNON: \"Maskinkanon\"\n  STR_AC_AP_AMMO: \"AC-AP-ammunition\"\n  STR_AC_HE_AMMO: \"MK-HE-ammunition\"\n  STR_AC_I_AMMO: \"AC-I-ammunition\"\n  STR_ROCKET_LAUNCHER: \"Raketstyr\"\n  STR_SMALL_ROCKET: \"Lille raket\"\n  STR_LARGE_ROCKET: \"Stor raket\"\n  STR_INCENDIARY_ROCKET: \"Ildraket\"\n  STR_GRENADE: \"Håndgranat\"\n  STR_SMOKE_GRENADE: \"Røggranat\"\n  STR_PROXIMITY_GRENADE: \"Afstandsgranat\"\n  STR_HIGH_EXPLOSIVE: \"Højeksplosiver\"\n  STR_STUN_ROD: \"Bedøvelsesstav\"\n  STR_HEAVY_PLASMA: \"Tung plasma\"\n  STR_HEAVY_PLASMA_CLIP: \"Tung plasmamagasin\"\n  STR_PLASMA_RIFLE: \"Plasmagevær\"\n  STR_PLASMA_RIFLE_CLIP: \"Plasmagevær-magasin\"\n  STR_PLASMA_PISTOL: \"Plasmapistol\"\n  STR_PLASMA_PISTOL_CLIP: \"Plasmapistol-magasin\"\n  STR_BLASTER_LAUNCHER: \"Blaster-raketstyr\"\n  STR_BLASTER_BOMB: \"Blaster-bombe\"\n  STR_SMALL_LAUNCHER: \"Lille raketstyr\"\n  STR_STUN_BOMB: \"Bedøvelsesbombe\"\n  STR_ALIEN_GRENADE: \"Rumvæsengranat\"\n  STR_ELERIUM_115: \"Elerium-115\"\n  STR_MIND_PROBE: \"Sindelagssonde\"\n  STR_SECTOID_CORPSE: \"Sectoid-lig\"\n  STR_SNAKEMAN_CORPSE: \"Slangemand-lig\"\n  STR_ETHEREAL_CORPSE: \"Ethereal-lig\"\n  STR_MUTON_CORPSE: \"Muton-lig\"\n  STR_FLOATER_CORPSE: \"Flyder-lig\"\n  STR_CELATID_CORPSE: \"Celatid-lig Lig\"\n  STR_SILACOID_CORPSE: \"Silacoid-lig\"\n  STR_CHRYSSALID_CORPSE: \"Chryssalid-lig\"\n  STR_REAPER_CORPSE: \"Reaper-lig\"\n  STR_SECTOPOD_CORPSE: \"Sektopod-lig\"\n  STR_CYBERDISC_CORPSE: \"Cyberdisk-lig\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"Ikke nok ammunition til at armere HWP{SMALLLINE}Hver  TVP kræver {0} {1}.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Ikke nok udstyr til din indsatsstyrke\"\n  STR_MARS_CYDONIA_LANDING: \"Mars: Landing i Cydonien\"\n  STR_MARS_CYDONIA_LANDING_BRIEFING: \"Dit Hævnerfartøj er landet i Cydonien på Mars' overflade. Vores information indikerer at den ene af pyramidekonstruktionerne indeholder en grøn adgangslift til et underjordisk anlæg. Når du har samlet alle dine soldater i elevatoren, skal du klikke på knappen »afbryd mission« for at fortsætte til det næste niveau.\"\n  STR_MARS_THE_FINAL_ASSAULT: \"Mars: Den afgørende kamp\"\n  STR_MARS_THE_FINAL_ASSAULT_BRIEFING: \"Pyramideelevatoren tager din kamptrætte soldater dybt under planetens overflade. De ankommer i hjertet af et stort kompleks af tunneller og kamre. Rumvæsenhjernen er skjult et sted i labyrinten. Det skal knuses, hvis jorden skal frelses fra rumvæsenernes slaveri.{NEWLINE}{NEWLINE}Held og lykke!\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Du skal forske i{NEWLINE}{0}{NEWLINE}for at producere{NEWLINE}{1}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"Rumvæsenerne har destrueret den ubeskyttede base {0}\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"X-Com-agenter har lokaliseret en fjendtlig base i {0}\"\n  STR_STANDOFF: \"AFVENTENDE\"\n  STR_CAUTIOUS_ATTACK: \"FORSIGTIGT ANGREB\"\n  STR_STANDARD_ATTACK: \"STANDARDANGREB\"\n  STR_AGGRESSIVE_ATTACK: \"AGGRESSIVT ANGREB\"\n  STR_DISENGAGING: \"AFSLUTTER ANGREB\"\n  STR_UFO_HIT: \"UFO RAMT!\"\n  STR_UFO_CRASH_LANDS: \"UFO STYRTER!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Minimer kun ved afventende afstand\"\n  STR_UFO_RETURN_FIRE: \"UFO SKYDER IGEN!\"\n  STR_INTERCEPTOR_DAMAGED: \">>> KORTR. JAGERFLY SKADET <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>>KORTR. JAGERFLY SKUDT NED<<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"UFO FLYGTER FRA KORTR. JAGERFLY!\"\n  STR_ALIENS_TERRORISE: \"RUMVÆSENER TERRORISERER\"\n  STR_LONG_RANGE_DETECTION: \"Stor detektionsradius\"\n  STR_STORES_UC: \"LAGRE\"\n  STR_DIFFICULTY_LEVEL: \"Sværhedsgrad\"\n  STR_INTERCEPT: \"ANGRIB\"\n  STR_BASES: \"BASER\"\n  STR_GRAPHS: \"GRAFER\"\n  STR_UFOPAEDIA_UC: \"UFOPÆDI\"\n  STR_OPTIONS_UC: \"INDSTILLINGER\"\n  STR_FUNDING_UC: \"FINANSIERING\"\n  STR_5_SECONDS: \"5 sek.\"\n  STR_1_MINUTE: \"1 min.\"\n  STR_5_MINUTES: \"5 min.\"\n  STR_30_MINUTES: \"30 min.\"\n  STR_1_HOUR: \"1 time\"\n  STR_1_DAY: \"1 dag\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"X-Com-præstationsliste\"\n  STR_ENTER_NAME: \"Indtast navn\"\n  STR_PERFORMANCE_RATING: \"Præstationsbedømmelse\"\n  STR_VICTORY_DATE: \"Dato for sejr\"\n  STR_ELECTRO_FLARE: \"Elektro-blus\"\n  STR_ELECTRO_FLARE_UFOPEDIA: \"Denne kompakte anordning producerer et skarpt lysskær, når den bliver kastet. Dette vil fremhæve fjendtlige enheder i nærheden af det elektriske signallys under natmissioner.\"\n  STR_MONTHLY_COSTS: \"Månedlige udgifter\"\n  STR_CRAFT_RENTAL: \"Leje af fly\"\n  STR_SALARIES: \"Lønninger\"\n  STR_BASE_MAINTENANCE: \"Basevedligeholdelse\"\n  STR_COST_PER_UNIT: \"Pris per enhed\"\n  STR_QUANTITY: \"Mængde\"\n  STR_TOTAL: \"I alt\"\n  STR_IN_PSIONIC_TRAINING: \"I psi-træning\"\n  STR_BLASTER_BOMB_UFOPEDIA: \"Denne enhed er et højeksplosivt missil, som har et intelligent styringssystem.  Den bliver affyret fra et blaster-raketstyr.\"\n  STR_FRONT_ARMOR: \"Frontpanser\"\n  STR_LEFT_ARMOR: \"Venstre panser\"\n  STR_RIGHT_ARMOR: \"Højre panser\"\n  STR_REAR_ARMOR: \"Rygpanser\"\n  STR_UNDER_ARMOR: \"Underliggende panser\"\n  STR_ROUNDS: \"Skud\"\n  STR_UNIT: \"Enhed> {0}\"\n  STR_ENERGY: \"ENERGI\"\n  STR_MORALE: \"MORAL\"\n  STR_ARMOR_: \"Panser> {0}\"\n  STR_FRONT_ARMOR_UC: \"FRONTPANSER\"\n  STR_LEFT_ARMOR_UC: \"VENSTRE PANSER\"\n  STR_RIGHT_ARMOR_UC: \"HØJRE PANSER\"\n  STR_REAR_ARMOR_UC: \"BAGPANSER\"\n  STR_SKILLS: \"EVNER> {0}\"\n  STR_LEVEL: \"NIVEAU> {0}\"\n  STR_HEAD: \"HOVED\"\n  STR_TORSO: \"OVERKROP\"\n  STR_RIGHT_ARM: \"HØJRE ARM\"\n  STR_LEFT_ARM: \"VENSTRE ARM\"\n  STR_RIGHT_LEG: \"HØJRE BEN\"\n  STR_LEFT_LEG: \"VENSTRE BEN\"\n  STR_PAIN_KILLER: \"SMERTESTILLENDE\"\n  STR_STIMULANT: \"STIMULANS\"\n  STR_HEAL: \"HELBRED\"\n  STR_TIME_UNITS_SHORT: \"TE>{ALT}{0}\"\n  STR_WEIGHT: \"Vægt>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"Reak.>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"P.-evne>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"P.-styrke>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"RUMVÆSENARTEFAKT\"\n  STR_AMMO_ROUNDS_LEFT: \"AMMO:{NEWLINE}SKUD{NEWLINE}LEFT={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Smerte>{ALT}{0}{ALT}{NEWLINE}Stim.>{ALT}{1}{ALT}{NEWLINE}Behandl>{ALT}{2}\"\n  STR_THROW: \"Kast\"\n  STR_AUTO_SHOT: \"Auto-skud\"\n  STR_SNAP_SHOT: \"Hurtigt skud\"\n  STR_AIMED_SHOT: \"Sigtet skud\"\n  STR_STUN: \"Bedøv\"\n  STR_PRIME_GRENADE: \"Aktiver granat\"\n  STR_USE_SCANNER: \"Brug skanner\"\n  STR_USE_MEDI_KIT: \"Brug førstehjælpskasse\"\n  STR_LAUNCH_MISSILE: \"Affyr missil\"\n  STR_ACCURACY_SHORT: \"Acc>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Ikke nok tidsenheder!\"\n  STR_NOT_ENOUGH_ENERGY: \"Ikke nok energi!\"\n  STR_NO_ROUNDS_LEFT: \"Ingen skud tilbage!\"\n  STR_NO_AMMUNITION_LOADED: \"Ingen ammunition!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Forkert ammunitionstype til dette våben!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"Våbnet er allerede ladt!\"\n  STR_NO_LINE_OF_FIRE: \"Intet frit skud!\"\n  STR_GRENADE_IS_ACTIVATED: \"Granat er aktiveret!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Granat deaktiveret!\"\n  STR_THERE_IS_NO_ONE_THERE: \"Der er ingen!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Umuligt at bruge rumvæsenartefakt indtil det er undersøgt!\"\n  STR_OUT_OF_RANGE: \"Uden for rækkevidde!\"\n  STR_UNABLE_TO_THROW_HERE: \"Umuligt at kaste hertil!\"\n  STR_SET_TIMER: \"Sæt tidsudløser\"\n  STR_HIDDEN_MOVEMENT: \"SKJULT BEVÆGELSE\"\n  STR_TURN: \"RUNDE> {0}\"\n  STR_SIDE: \"SIDE> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Tryk på en tast for at fortsætte\"\n  STR_MIND_CONTROL: \"Sindelagskontrol\"\n  STR_PANIC_UNIT: \"Gør enhed panisk\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Moralangreb udført med succes\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Sindelagskontrol udført med succes\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}er gået bersærk\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}er gået besærk\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}er gået i panik\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}er gået i panik\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Rumvæsener\"\n  STR_RIGHT_HAND: \"HØJRE HÅND\"\n  STR_LEFT_HAND: \"VENSTRE HÅND\"\n  STR_RIGHT_SHOULDER: \"HØJRE SKULDER\"\n  STR_LEFT_SHOULDER: \"VENSTRE SKULDER\"\n  STR_BACK_PACK: \"RYGSÆK\"\n  STR_BELT: \"BÆLTE\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}er under rumvæsenernes kontrol\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}er under rumvæsenernes kontrol\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}er blevet bevidstløs\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}er blevet bevidstløs\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}er død af kritiske sår\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}er død af et kritisk sår\"\n  STR_USE_MIND_PROBE: \"Brug sindelagssonde \"\n  STR_FATAL_WOUNDS: \"FATALE SÅR\"\n  STR_UNDER_ARMOR_UC: \"UNDERPANSER\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Tidsenheder reserveret til hurtigt skud\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Tidsenheder reserveret til autoskud\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Tidsenheder reserveret til sigtet skud\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Tidsenheder reserveret til at knæle\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"TE'er reserveret til at knæle og skyde\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} enhed i X-Com-fly\"\n    other: \"{N} enheder i X-Com-fly\"\n  STR_UNITS_OUTSIDE:\n    one: \"{N} enhed efterladt udenfor\"\n    other: \"{N} enheder efterladt udenfor\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} enhed i indgangsparti\"\n    other: \"{N} enheder i indgangsparti\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} enhed i måludgang\"\n    other: \"{N} enheder i måludgang\"\n  STR_ABORT_MISSION_QUESTION: \"Afslut mission?\"\n  STR_CORPSE: \"Lig\"\n  STR_UNLOAD_CRAFT: \"Aflad\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}er blevet dræbt\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}er blevet dræbt\"\n  STR_HIT_MELEE: \"Ramte\"\n  STR_GROUND: \"JORDEN\"\n  STR_LIVING_QUARTERS_PLURAL: \"Beboelsesrum\"\n  STR_LIST_ITEM: \"UDSTYR\"\n  STR_PERSONAL_ARMOR_UFOPEDIA: \"Med brug af den nye legering fra rumvæsenerne som panser får dine mænd en ny chance i kampen mod rumvæsenernes trussel.\"\n  STR_POWER_SUIT_UFOPEDIA: \"En stærk ny beskyttelse til soldater. Denne pansring bliver forsynet af en elerium-energikilde, og forstærker soldatens hastighed og styrke kraftigt. Dette er den absolut bedste beskyttelse vores kamptropper kan udstyres med.\"\n  STR_FLYING_SUIT_UFOPEDIA: \"En forbedret version af kraftvesten, der indarbejder rumvæsenernes antityngdekraft-navigationsteknologi til fuld bevægelsesfrihed på slagmarken.\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"Alle rumvæsener dræbt i styrtet,{NEWLINE}Automatisk bjærgning påbegyndt\"\n  STR_RESET: \"Nulstil\"\n  STR_MEMORIAL: \"Gravskrift\"\n  STR_DATE_UC: \"DATO\"\n  STR_SOLDIERS_RECRUITED_UC: \"SOLDATER REKRUTTERET>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"MISTEDE SOLDATER>{ALT}{0}\"\n  MAP_CULTA: \"Gård\"\n  MAP_FOREST: \"Skov\"\n  MAP_JUNGLE: \"Jungle\"\n  MAP_MOUNT: \"Bjerg\"\n  MAP_DESERT: \"Ørken\"\n  MAP_POLAR: \"Polarområde\"\n  MAP_URBAN: \"By\"\n  MAP_UBASE: \"Rumvæsenbase\"\n  MAP_XBASE: \"X-Com-base\"\n  MAP_MARS: \"Mars\"\n  STR_MIXED: \"Blandet\"\n  STR_REMOVE_SELECTED: \"Fjern valgte\"\n  STR_LIVE_ALIENS: \"Levende{NEWLINE}Eksemplarer\"\n  STR_DEAD_ALIENS: \"Afviste{NEWLINE}Eksemplarer\"\n  STR_UNDER_INTERROGATION: \"Under {NEWLINE}Undersøgelse\"\n  STR_CONTAINMENT_EXCEEDED: \"OPBEVARINGSRUMMET FOR RUMVÆSENER ER FULD!{SMALLLINE}Der er ikke nok opbevaringsrum på {0}. De skal fjerne overskydende rumvæsener fra opbevaringsrummet (som så vil dø).\"\n  STR_MANAGE_CONTAINMENT: \"Håndter rumvæsenernes opbevaringsrum\"\n  STR_STORAGE_EXCEEDED: \"LAGERET ER FYLDT!{SMALLLINE}Der er ikke nok lagerrum på {0}. Du kan sælge eventuelt overskudsudstyr.\"\n  STR_GO_TO_BASE: \"Gå til base\"\n  STR_MELEE_ACCURACY: \"NÆRKAMPSPRÆCISION\"\n  STR_SELL_PRODUCTION: \"SÆLG\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Begge hænder skal være tomme!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Ikke nok udstyr til at kopiere skabelon!\"\n  STR_UNLOAD_WEAPON: \"Aflad våben\"\n  STR_ALL_ITEMS: \"Alt udstyr\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"IKKE MERE UDSTYR TILLADT OMBORD!{SMALLLINE}Du må kun medtage maksimal {N} enhed med udstyr på dette fartøj.\"\n    other: \"IKKE MERE UDSTYR TILLADT OMBORD!{SMALLLINE}Du må kun medtage maksimal {N} enheder med udstyr på dette fartøj.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}KONTROLCENTER ØDELAGT{NEWLINE}Gå til indgangen og afbryd.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"X-Com-faciliteter kan ikke bygges under vand\"\n  STR_LEVEL_SHORT: \"{0}\"\n  STR_PERSONNEL: \"Personale\"\n  STR_CRAFT_ARMAMENT: \"Fly og udrustning\"\n  STR_COMPONENTS: \"Komponenter\"\n  STR_SOLDIERS_RECRUITED: \"Soldater rekrutteret\"\n  STR_SOLDIERS_LOST: \"Mistede soldater\"\n  STR_TOTAL_UFOS: \"Ufoer registreret\"\n  STR_TOTAL_ALIEN_BASES: \"Rumvæsenbaser registreret\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"PST\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"PSK\"\n  FEMALE_CIVILIAN: \"Civil, kvinde\"\n  MALE_CIVILIAN: \"Civil, mand\"\n  CYBERDISC_WEAPON: \"Cyberdiskvåben\"\n  REAPER_WEAPON: \"Reapervåben\"\n  CHRYSSALID_WEAPON: \"Chryssalidvåben\"\n  CELATID_WEAPON: \"Celatidvåben\"\n  SILACOID_WEAPON: \"Silacoidvåben\"\n  SECTOPOD_WEAPON: \"Sectopodvåben\"\n  ZOMBIE_WEAPON: \"Zombievåben\"\n  ALIEN_PSI_WEAPON: \"Rumvæsen-psi-våben\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/de.yml",
    "content": "de:\n  STR_AVENGER_UFOPEDIA: \"TRANSPORT- UND KAMPFRAUMSCHIFF. DIE ULTIMATIVE NACHBILDUNG AUSSERIRDISCHER TECHNOLOGIE.\"\n  STR_INTERCEPTOR_UFOPEDIA: \"KAMPFRAUMSCHIFF MIT DOPPELIMPULS - DETONATIONSTRIEBWERKEN UND SPEZIELL ABGESCHIRMTEN ELEKTRONISCHEN SYSTEMEN.  DIE BESTE TECHNOLOGIE, DIE DIE ERDE ZU BIETEN HAT.\"\n  STR_LIGHTNING_UFOPEDIA: \"TRANSPORT- UND KAMPFRAUMSCHIFF.  EIN EINFACHER, ABER WIRKUNGSVOLLER NACHBAU DER AUSSERIRDISCHEN ANTRIEBSSYSTEME.\"\n  STR_SKYRANGER_UFOPEDIA: \"TRUPPENTRANSPORTER.  DER SCHNELLSTE SEINER ART, MIT DER MÖGLICHKEIT ZU SENKRECHTSTART UND -LANDUNG (V.T.O.L.).\"\n  STR_FIRESTORM_UFOPEDIA: \"KAMPFRAUMSCHIFF.  DIESER EIN-MANN-KAMPFFLIEGER KOPIERT DAS KLASSISCHE AUSSERIRDISCHE UNTERTASSEN-DESIGN, MIT ZENTRALANTRIEBSEINHEIT.\"\n  STR_STINGRAY_UFOPEDIA: \"FORTSCHRITTLICHE LUFTKAMPF-RAKETE MIT SPEZIELL ABGESCHIRMTER ELEKTRONIK.\"\n  STR_AVALANCHE_UFOPEDIA: \"LUFTKAMPF-RAKETE MIT ATOMSPRENGKOPF, DOCH EXTREM HOHEM GEWICHT.\"\n  STR_CANNON_UFOPEDIA: \"HOCHLEISTUNGSGESCHÜTZ FÜR PANZERBRECHENDE GESCHOSSE, DIE STAHL VON 16 ZOLL DICKE DURCHDRINGEN KÖNNEN.\"\n  STR_FUSION_BALL_UFOPEDIA: \"DIESE ABSCHUSSVORRICHTUNG FEUERT EIN KUGELGESCHOSS AB, DAS DURCH ANTIMATERIE-REAKTION ANGETRIEBEN WIRD. DIE KUGEL ZERSTÖRT DAS ZIEL MIT EINER GRAVITATIONSWELLEN-IMPLOSION.\"\n  STR_LASER_CANNON_UFOPEDIA: \"DIESER HERKÖMMLICHE LASERSTRAHL WIRD VON EINER ANTIMATERIE-REAKTIONS-KAMMER GESPEIST.\"\n  STR_PLASMA_BEAM_UFOPEDIA: \"DER GRAVITATIONSSTRAHL SETZT EIN GENAU AUSGERICHTETES IMPLODIERENDES GRAVITATIONSFELD EIN.\"\n  STR_SECTOID_UFOPEDIA: \"Die Hierarchie der Sektoiden reicht von Soldaten bis zu Anführern mit starken psionischen Kräften.  Diese Kräfte können eingesetzt werden, um Soldaten im Kampf zu demoralisieren oder sogar ihre Gedanken zu kontrollieren.  Sektoiden entführen gern Menschen und verstümmeln Rinder.  Die Entführungen dienen der Gewinnung genetischen Materials, aus dem sie Hybrid-Züchtungen und Klonen entwickeln und in die menschliche Gesellschaft einschleusen.  Dieses Volk scheint überlegene genetische Mischformen entwickeln zu wollen, um die Effektivität seiner bienenstockartigen Gesellschaft zu erhöhen.\"\n  STR_SECTOID_AUTOPSY: \"Sektoid-Autopsie\"\n  STR_SECTOID_AUTOPSY_UFOPEDIA: \"Die Autopsie zeigt rudimentäre Verdauungsorgane und eine einfache Struktur.  Das Gehirn und die Augen sind sehr stark entwickelt.  Die Struktur weist auf genetische Veränderung oder Mutation hin.  Der kleine Mund und die ebenso winzige Nase scheinen kaum eine Funktion zu haben.  Die Haut zwischen den Fingern und die flachen Füße deuten auf aquatische Herkunft hin.  Es gibt keine Fortpflanzungsorgane und keinen Hinweis darauf, wie sich diese Spezies vermehrt.  Vermutlich handelt es sich um eine genetisch manipulierte Spezies.\"\n  STR_SNAKEMAN_UFOPEDIA: \"Diese Spezies hat sich in einer äußerst feindseligen Umwelt entwickelt.  Die Geschöpfe sind sehr widerstandsfähig und können hohe Temperaturschwankungen überstehen.  Ihre Mobilität verdanken sie einem riesigen schlangenähnlichen 'Fuß', der alle wichtigen Organe schützt.  Ihre Absichten scheinen rein räuberischer Natur zu sein, und sie werden vermutlich von einer anderen Intelligenz gelenkt, die die militärischen Übergriffe auf die Erde steuert.\"\n  STR_SNAKEMAN_AUTOPSY: \"Schlangenmensch-Autopsie\"\n  STR_SNAKEMAN_AUTOPSY_UFOPEDIA: \"Die Haut ist äußerst fest und hitzebeständig.  Das Herz- und Kreislaufsystem ist Bestandteil des Muskelsystems, das nach dem hydraulischen Prinzip Bewegungen erzeugt.  Der einzige wirkliche Muskel ist das 'Herz'.  Das Fortpflanzungssystem scheint sehr effektiv zu sein.  Die Fortpflanzung geschieht asexuell: Jeder Schlangenmensch trägt ständig bis zu fünfzig Eier in seinem Körper.  Ließe man diese Spezies gewähren, würde sie eine ernsthafte Bedrohung für das Leben auf der Erde darstellen.\"\n  STR_ETHEREAL_UFOPEDIA: \"Dieses Wesen hat eindrucksvolle mentale Kräfte, die die telepathische Kommunikation und telekinetische Fähigkeiten ermöglichen.  Der schwache Körper dieser Kreaturen wird durch ihre geistigen Kräfte erhalten.  Wir wissen nicht, wie diese telekinetischen Kräfte funktionieren, da sie den physikalischen Gesetzen, wie wir sie kennen, zuwiderzulaufen scheinen.  Im Kampf, wo sie ihre mentalen Kräfte einsetzen, sind diese Wesen äußerst gefährlich.  Sie erscheinen selten selbst auf der Erde, da sie anscheinend andere Völker dafür einzusetzen scheinen, ihre Ziele zu verfolgen.\"\n  STR_ETHEREAL_AUTOPSY: \"Ätherer-Autopsie\"\n  STR_ETHEREAL_AUTOPSY_UFOPEDIA: \"Dieses Wesen ist körperlich kaum entwickelt und scheint nicht in der Lage zu sein, Lebensfunktionen zu erhalten.  Die Muskeln sind stark verkümmert, die inneren Organe kaum ausgebildet.  Die Wahrnehmungsorgane, einschließlich der Augen, scheinen völlig funktionsuntüchtig zu sein.  Das Gehirn dagegen ist gut entwickelt und zieht einen Großteil der Blutversorgung des Körpers auf sich.  Es ist ein Rätsel, wie sich diese Kreatur ohne äußere Hilfe am Leben erhalten kann.\"\n  STR_MUTON_UFOPEDIA: \"Diese humanoiden Geschöpfe besitzen Körperkraft und Intelligenz.  Sie verzehren besonders gern rohes Fleisch jeder Art, das ähnlich den Raubtieren auf der Erde ihre Nahrung bildet.  Sie scheinen von den telepathischen Befehlen eines als 'Ätherer' bekannten Volkes abhängig zu sein.  Sobald diese telepathische Verbindung gelöst wird, brechen ihre Gehirnfunktionen zusammen, und sie sterben. Die kybernetischen Implantate verbessern ihre Kampfleistung.  Diese Wesen dienen eindeutig als Ausführungsorgane einer höheren Intelligenz.\"\n  STR_MUTON_AUTOPSY: \"Mutone-Autopsie\"\n  STR_MUTON_AUTOPSY_UFOPEDIA: \"Die 'Haut' dieses Wesens scheint eine organisch geschaffene Schutzpanzerung zu sein, die auf den Körper aufgepflanzt ist.  Es sind zahlreiche kybernetische Implantate vorhanden, die das Herz-Kreislauf-System und die Sinne stärken.  Die Fortpflanzungsorgane scheinen chirurgisch entfernt worden zu sein.  Offensichtlich sind diese unglückseligen Geschöpfe für ein Leben des Kampfes und der Eroberung bestimmt.  Panzerbrechende Munition ist gegen ihre verstärkte Außenhaut wenig wirksam.\"\n  STR_CELATID_UFOPEDIA: \"Diese Lebensform hat die geheimnisvolle natürliche Fähigkeit, durch die Luft zu schweben.  Sie scheinen menschliche Gehirnwellen zu spüren und bewegen sich auf ihr Ziel zu, selbst wenn es gut versteckt ist.  Sobald der Celatid ein Ziel entdeckt hat, landet er und feuert kleine Kugeln mit stark ätzendem Gift ab.  Das Geschöpf kann sich mit erschreckender Geschwindigkeit selbst klonen.  Es begleitet das Volk der Mutonen bei seinen Wanderungen.\"\n  STR_CELATID_AUTOPSY: \"Celatid-Autopsie\"\n  STR_CELATID_AUTOPSY_UFOPEDIA: \"Im Kern befindet sich eine kleine biomechanische Vorrichtung, bei der es sich um ein natürlich entwickeltes Antischwerkraft-Antriebssystem handelt.  Der Giftbeutel ist das größte Organ, und es scheint keine separate Gehirnstruktur zu geben.  Verdauungs- oder Fortpflanzungssysteme sind nicht zu entdecken.  Ein kleines Organ enthält Embryos, die rasch zu neuen Wesen heranwachsen können.\"\n  STR_SILACOID_UFOPEDIA: \"Diese Lebensform auf Silikonbasis erzeugt eine ungeheure Hitze.  Sie hat die Kraft, Felsen zu zertrümmern, die dann von ihrem heißen Kern verzehrt werden können.  Sie besitzt eine primitive Intelligenz, die durch Implantate oder telepathische Wesen kontrolliert werden kann.  Sie arbeitet mit den Mutonen zusammen.\"\n  STR_SILACOID_AUTOPSY: \"Silakoid-Autopsie \"\n  STR_SILACOID_AUTOPSY_UFOPEDIA: \"Der Kern dieser Geschöpfe ist sehr heiß und scheint die Grundlage für ihr Verdauungssystem zu bilden.  Ihr einzigartiges Muskelsystem besitzt ungeheure Kraft und Geschwindigkeit.  Ihre felsenartige Haut kann weder durch Feuer noch durch Brandmunition verletzt werden.\"\n  STR_CHRYSSALID_UFOPEDIA: \"Die Krebsscheren dieses Wesens sind eine mächtige Waffe im Nahkampf.  Ein schneller Stoffwechsel und außergewöhnliche Körperkraft verleihen diesem Geschöpf Schnelligkeit und Gewandtheit.  Anstatt seine Opfer zu töten, legt es ein Ei in ihnen ab und injiziert ein Gift, das sie zu wandelnden Zombies macht.  Kurz nach dieser Befruchtung bricht ein neuer Chryssalid aus dem Opfer hervor.  Die Chryssaliden arbeiten mit den Schlangenmenschen zusammen.\"\n  STR_CHRYSSALID_AUTOPSY: \"Chryssalid-Autopsie\"\n  STR_CHRYSSALID_AUTOPSY_UFOPEDIA: \"Das Außenskelett dieses Wesens ist äußerst hart, jedoch erstaunlich empfindlich gegenüber Sprengstoffen.  Das Gehirn ist gut entwickelt und die Wachstumsrate der Zellen sehr hoch.  Das Wesen trägt zwanzig Eier bei sich, die es in anderen Organismen ablegt.  Diese Kreatur ist eine tödliche Terror-Waffe.\"\n  STR_FLOATER_UFOPEDIA: \"Die Schweber sind vorwiegend Soldaten und Terror-Agenten.  Sie sind von Natur aus räuberisch veranlagt, jedoch durch genetische und kybernetische Veränderungen in furchterregende Krieger verwandelt worden.  Die untere Körperhälfte und die meisten inneren Organe wurden chirurgisch entfernt und durch ein Lebenserhaltungssystem ersetzt.  Dieses Implantat enthält eine Antischwerkraft-Einheit, die dem Wesen ermöglicht, mehr oder weniger sicher durch die Luft zu schweben.\"\n  STR_FLOATER_AUTOPSY: \"Schweber-Autopsie\"\n  STR_FLOATER_AUTOPSY_UFOPEDIA: \"Das Geschöpf wurde durch chirurgische Eingriffe stark verändert.  Den Kern des Körpers scheint ein Lebenserhaltungssystem zu bilden, das die Funktionen von Herz, Lunge und Verdauungstrakt übernimmt.  Dadurch kann das Wesen in einer äußerst feindseligen Umwelt überleben.  Das Gehirn ist kleiner als unseres, doch die Sinnesorgane sind gut entwickelt.\"\n  STR_REAPER_UFOPEDIA: \"Dieser zweibeinige Fleischfresser hat mächtige Kiefer und einen ungeheuren Appetit.  Seine Handlungen werden durch eine Reihe von Gehirn-Implantaten gesteuert.  Die primitiven räuberischen Instinkte dieses Geschöpfes können lediglich für Terror- und Vernichtungsakte genutzt werden.  Schnitter werden im allgemeinen mit Schwebern in Verbindung gebracht.\"\n  STR_REAPER_AUTOPSY: \"Schnitter-Autopsie\"\n  STR_REAPER_AUTOPSY_UFOPEDIA: \"Der Schnitter besitzt zwei 'Herzen' und zwei 'Gehirne' und kann daher auch dann noch weiter agieren, wenn er schwer verwundet ist.  Die fellbedeckte Haut ist jedoch leicht entflammbar, was dieses Wesen gegenüber Brandwaffen sehr empfindlich macht.\"\n  STR_SECTOPOD_UFOPEDIA: \"Die Sektopods sind roboterartige Kreaturen, mit einer leistungsstarken Laserstrahl-Waffe. Kontrolliert werden diese mechanischen Monster über Telepathie durch die Ätherer. Ein Sektopod ist die stärkste Waffe der Außerirdischen für den Terror auf der Erde.\"\n  STR_SECTOPOD_AUTOPSY: \"Sektopod-Autopsie\"\n  STR_SECTOPOD_AUTOPSY_UFOPEDIA: \"Der Roboter ist stabil konstruiert und seine verstärkte Panzerung kann den meisten Angriffen widerstehen, insbesondere Plasmawaffen. Die sensorischen Schaltkreise scheinen jedoch sehr empfindlich gegen Laserwaffen zu sein.\"\n  STR_CYBERDISC_UFOPEDIA: \"Diese fliegende Untertasse im Kleinformat ist eine mit einem mächtigen Plasmastrahl ausgerüstete Terrorwaffe.  Der Antischwerkraft-Antrieb bringt ihr große Vorteile in schwierigem Gelände.  Ihre Hauptaufgaben sind Zerstörung und Terror im Auftrag des Sektoiden-Volkes.\"\n  STR_CYBERDISC_AUTOPSY: \"Cyberdisc-Autopsie \"\n  STR_CYBERDISC_AUTOPSY_UFOPEDIA: \"Die Cyberdisc besitzt wirksame Schutzschilde und ist vor allem vor Sprengstoffangriffen gut geschützt.  Das Antischwerkraft-System ist zu stark beschädigt, um seine Funktionsweise erkennen zu können.\"\n  STR_UFO_POWER_SOURCE_UFOPEDIA: \"Die Energiequelle der außerirdischen Raumschiffe ist ein Antimaterie-Reaktor, der Elerium (Element 115) einsetzt, um mächtige Gravitationswellen und andere Energieformen zu erzeugen. Die Konvertierung von Materie in Energie beträgt unglaubliche 99%, daher können kleine Mengen von Elerium eine gewaltige Energie erzeugen. Diese Einheit kann mit Hilfe von außerirdischen Legierungen leicht nachgebaut werden.\"\n  STR_UFO_NAVIGATION_UFOPEDIA: \"Die außerirdischen Raumschiffe benutzen fortschrittliche Computer, um auf der Erde und im Weltraum zu navigieren. Das System beruht auf optischen Prozessoren, die in einem Netzwerk miteinander verbunden sind. Die Schnittstelle funktioniert relativ einfach: Der Navigator steuert die Richtung der durch die Energiequelle erzeugten Gravitationswellen, um das Raumschiff zu lenken. Dieses System kann problemlos von Menschen bedient und mit Hilfe von außerirdischen Legierungen und anderen Bestandteilen nachgebaut werden.\"\n  STR_UFO_CONSTRUCTION_UFOPEDIA: \"Außerirdische Raumschiffe setzen sich aus drei Hauptbestandteilen zusammen: einer Energiequelle, einem Navigationssystem und einem aus außerirdischen Legierungen bestehenden Rumpf. Der Rumpf ist so konstruiert, daß Gravitationswellen gelenkt und kontrolliert werden können. Außerdem wird eine kleine Menge Elerium benötigt, um die Energiequelle anzutreiben. Sobald wir die Prinzipien der Konstruktion verstanden haben und die Funktionen der Bestandteile kennen, wird es möglich sein, diese Raumschiffe nachzubauen.\"\n  STR_ALIEN_FOOD_UFOPEDIA: \"Diese Kammern enthalten verschiedene Enzyme, die benutzt werden, um Körperteile von Rindern, anderen Tieren oder sogar Menschen zu verdauen. Die Flüssigkeit wird dann als fertig verdaute Nahrung aufgenommen, möglicherweise direkt ins Blut. Dies weist auf eine gewisse Abhängigkeit von irdischer Nahrung hin, eine Symbiose zwischen den Außerirdischen und der Erde.\"\n  STR_ALIEN_REPRODUCTION_UFOPEDIA: \"Diese Kammern enthalten außerirdische Föten. Die Konstruktion dieser Behälter deutet darauf hin, daß die Außerirdischen, die diese Methode benutzen, zur Fortpflanzung auf Labore angewiesen sind. Die reichen Nährlösungen garantieren die rasche Entwicklung des Fötus. Diese fabrikmäßige Aufzucht könnte innerhalb kürzester Zeit Tausende von außerirdischen Klonen erzeugen. Der Prozeß kann leicht auf die Fortpflanzung von Menschen oder Mischformen angewendet werden.\"\n  STR_ALIEN_ENTERTAINMENT_UFOPEDIA: \"Diese Kugeln dienen wahrscheinlich der Freizeitgestaltung.  Die psionischen Schaltkreise stimulieren verschiedene Gehirnzentren. Die Wirkung ähnelt der von halluzinogenen Drogen. Dies ist der einzige Nachweis dafür, daß die Außerirdischen Freizeitbeschäftigungen haben.\"\n  STR_ALIEN_SURGERY_UFOPEDIA: \"Dieses chirurgische Instrument setzt Lasermesser ein, um Rindern und anderen Tieren bestimmte Körperteile zu entfernen. Auf diese bizarre Beschäftigung der Außerirdischen sind wohl die vielen Verstümmelungen von Rindern zurückzuführen. Wahrscheinlich werden diese Körperteile als Nahrung oder für genetische Zwecke benutzt.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"Viele Tausende von Menschen haben schon behauptet, von Außerirdischen entführt worden zu sein, oft sogar mehrfach. Die Wahrheit ist weitaus erschreckender. Menschen werden entführt, untersucht und überwacht. Den besten Exemplaren wird genetisches Material entnommen. Frauen werden außerirdisch-menschliche Mischlingsföten eingepflanzt und Monate später wieder entfernt. Wer weiß, welche finsteren Absichten die Außerirdischen damit verfolgen?\"\n  STR_ALIEN_ALLOYS_UFOPEDIA: \"Außerirdische Raumschiffe werden aus Speziallegierungen hergestellt, die einzigartige Eigenschaften besitzen.  Sie sind besonders leicht und dauerhaft und können mit elektromagnetischen Methoden geformt werden. Dieses Material kann reproduziert und in vielfältigen Herstellungsprozessen verwendet werden.\"\n  STR_ELERIUM_115_UFOPEDIA: \"Dieses Element besitzt die ungewöhnliche Eigenschaft, Antimaterie-Energie zu erzeugen, wenn es mit gewissen Teilchen beschossen wird.  Dadurch entstehen Gravitationswellen und andere Energieformen.  Das Element kommt in unserem Sonnensystem nicht vor und kann auch nicht reproduziert werden.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"Es wird deutlich, daß wir den Kampf auf der Erde verlieren. Die Horden der Außerirdischen sind uns zahlenmäßig zu stark überlegen. Es könnte uns lediglich gelingen, den Strom zu verlangsamen. Wir müssen die Außerirdischen an der Quelle bekämpfen, das ist unsere einzige Chance. Unsere Forschungen weisen auf eine nahegelegene Operationsbasis in unserem Sonnensystem hin. Die Außerirdischen geben an, daß dieser Ort das Zentrum einer alten Zivilisation vor der Entwicklung der Menschheit ist. Wir müssen diesen Ort so bald wie möglich finden. Dazu müssen wir einen Anführer der Außerirdischen fangen und verhören, um genauere Informationen zu erhalten. An Bord der größeren UFOs befindet sich vermutlich mindestens einer ihrer Anführer.\"\n  STR_THE_MARTIAN_SOLUTION_UFOPEDIA: \"Unsere Untersuchungen deuten darauf hin, dass sich die Operationsbasis der Außerirdischen auf dem Mars befindet. Die Basis ist gut versteckt und verfügt über alle Produktions- und Cloning-Anlagen, um die Infiltration der Erde am Laufen zu halten. Sie scheint auch eine Art Kontrollcomputer zu beinhalten, der die ganze Operation überwacht. Es scheint, als ob in der schwarmartigen Kultur der Außerirdischen eine Art 'Königsbiene' existiert. Das ist ihre grundlegende Schwachstelle - wenn wir das 'Gehirn' ausschalten können, wird auch der Körper sterben. Wir müssen unsere Forschungsanstrengungen verstärken, bevor es zu spät ist. Um voranzukommen, müssen wir die höchstrangigen Außerirdischen gefangennehmen - die Kommandeure - die sich ausschließlich in den außerirdischen Basen und auf den Kriegsschiffen aufhalten.\"\n  STR_CYDONIA_OR_BUST_UFOPEDIA: \"Es ist inzwischen deutlich geworden, daß der außerirdische Schwarm von einem unter der Oberfläche gelegenen Stützpunkt in Cydonia aus gelenkt werden, einem ungewöhnlichen Gebiet auf dem Mars mit fünfseitigen Pyramiden und einer großen Formation, die einem menschlichen Gesicht gleicht. Die cydonische Zivilisation lebte vor Millionen von Jahren auf dem Mars, doch wir wissen nicht, warum sie ausstarb oder welche Verbindung zu den neuesten Aktivitäten der Außerirdischen besteht. Auf jeden Fall müssen wir eine Expedition nach Cydonia durchführen. Nur so können wir die Außerirdischen besiegen. Wir müssen das 'Gehirn' vernichten, das sie steuert. Wir werden ein Avenger-Raumschiff mit den tödlichsten Waffen brauchen, die uns zur Verfügung stehen. Hier kommen wir nicht weiter - wir müssen den Ausgang des Angriffs auf Cydonia abwarten.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"AUF STANDORT ZENTRIEREN-ZEIT=5 Sek.\"\n  STR_CANCEL_UC: \"ABBRECHEN\"\n  STR_NONE: \"k.A.\"\n  STR_UNKNOWN: \"Unbekannt\"\n  STR_POOR: \"Schlecht\"\n  STR_AVERAGE: \"Durchschnittlich\"\n  STR_GOOD: \"Gut\"\n  STR_EXCELLENT: \"Hervorragend\"\n  STR_BUILD_NEW_BASE_UC: \"NEUER STÜTZPUNKT\"\n  STR_BASE_INFORMATION: \"STÜTZPUNKT-INFORMATIONEN\"\n  STR_EQUIP_CRAFT: \"RAUMSCHIFF AUSRÜSTEN\"\n  STR_BUILD_FACILITIES: \"EINRICHTUNGEN BAUEN\"\n  STR_RESEARCH: \"FORSCHUNG\"\n  STR_MANUFACTURE: \"PRODUKTION\"\n  STR_TRANSFER_UC: \"TRANSFER\"\n  STR_PURCHASE_RECRUIT: \"KAUFEN/REKRUTIEREN\"\n  STR_SACK: \"ENTLASSEN\"\n  STR_SELL_SACK_UC: \"VERKAUFEN/ENTLASSEN\"\n  STR_GEOSCAPE_UC: \"WELTKARTE\"\n  STR_NAME: \"Name\"\n  STR_AREA: \"Gebiet\"\n  STR_BUILD_NEW_BASE: \"Neuer Stützpunkt\"\n  STR_CANCEL: \"Abbrechen\"\n  STR_COST_UC: \"KOSTEN>\"\n  STR_CONSTRUCTION_TIME_UC: \"BAUZEIT>\"\n  STR_DAY:\n    one: \"{N} Tag\"\n    other: \"{N} Tage\"\n  STR_HOUR:\n    one: \"{N} Stunde\"\n    other: \"{N} Stunden\"\n  STR_MAINTENANCE_UC: \"INSTANDHALTUNG>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Einrichtung\"\n  STR_CURRENT_RESEARCH: \"FORSCHUNGSSTAND\"\n  STR_SCIENTISTS_AVAILABLE: \"Wissenschaftler verfügbar>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Wissenschaftler eingesetzt>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Laborraum>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"FORSCHUNGSPROJEKT\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"WISSENSCHAFTLER EINGESETZT\"\n  STR_PROGRESS: \"FORTSCHRITTE\"\n  STR_NEW_PROJECT: \"Neues Projekt\"\n  STR_CANCEL_PROJECT: \"PROJEKT ABBRECHEN\"\n  STR_NEW_RESEARCH_PROJECTS: \"NEUE FORSCHUNGSPROJEKTE\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"WISSENSCHAFTLER VERFÜGBAR>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"LABORRAUM VERFÜGBAR>{ALT}{0}\"\n  STR_INCREASE: \"Erhöhen\"\n  STR_DECREASE: \"Reduzieren\"\n  STR_START_PROJECT: \"PROJEKT STARTEN\"\n  STR_CURRENT_PRODUCTION: \"PRODUKTIONSSTAND\"\n  STR_ENGINEERS_AVAILABLE: \"Ingenieure verfügbar>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Ingenieure eingesetzt>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Werkstattraum>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Verfügbare Gelder>{ALT}{0}\"\n  STR_ITEM: \"GEGENSTAND\"\n  STR_ENGINEERS__ALLOCATED: \"Ingenieure eingesetzt\"\n  STR_UNITS_PRODUCED: \"Produzierte Einheiten\"\n  STR_TOTAL_TO_PRODUCE: \"Gesamt zu produzieren\"\n  STR_COST__PER__UNIT: \"Kosten{NEWLINE}pro{NEWLINE}Einheit\"\n  STR_DAYS_HOURS_LEFT: \"Verbleibende Tage/Std.\"\n  STR_NEW_PRODUCTION: \"Neue Produktion\"\n  STR_PRODUCTION_ITEMS: \"Herstellung\"\n  STR_CATEGORY: \"KATEGORIE\"\n  STR_START_PRODUCTION: \"PRODUKTION STARTEN\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} Ingenieur Stunden um eine Einheit zu produzieren\"\n  STR_COST_PER_UNIT_: \"Kosten pro Einheit>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Benötigter Werkstattraum>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"BENÖTIGTES SPEZIALMATERIAL\"\n  STR_ITEM_REQUIRED: \"GEGENSTAND ERFORDERLICH\"\n  STR_UNITS_REQUIRED: \"EINHEITEN BENÖTIGT\"\n  STR_UNITS_AVAILABLE: \"EINHEITEN VERFÜGBAR\"\n  STR_STOP_PRODUCTION: \"PRODUKTION STOPPEN\"\n  STR_ENGINEERS_AVAILABLE_UC: \"INGENIEURE VERFÜGBAR>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"WERKSTATTRAUM>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"MONATLICHER PROFIT>{ALT}{0}\"\n  STR_INCREASE_UC: \"ERHÖHEN\"\n  STR_DECREASE_UC: \"REDUZIEREN\"\n  STR_UNITS_TO_PRODUCE: \"Gesamt-produktion\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Kaufen/Rekrutieren\"\n  STR_COST_OF_PURCHASES: \"Kaufpreis>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"KOSTEN PRO EINHEIT\"\n  STR_QUANTITY_UC: \"MENGE\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"PERSONAL VERFÜGBAR:PERSONAL GESAMT>\"\n  STR_SOLDIERS: \"Soldaten\"\n  STR_SCIENTISTS: \"Wissenschaftler\"\n  STR_ENGINEERS: \"Ingenieure\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"PLATZ GENUTZT:PLATZ VERFÜGBAR>\"\n  STR_LIVING_QUARTERS: \"Quartiere\"\n  STR_STORES: \"Lager\"\n  STR_LABORATORIES: \"Labore\"\n  STR_WORK_SHOPS: \"Werkstätten\"\n  STR_HANGARS: \"Hangars\"\n  STR_SHORT_RANGE_DETECTION: \"Kurzstrecken-Radar\"\n  STR_DEFENSE_STRENGTH: \"Verteidigungsstärke\"\n  STR_TRANSFERS_UC: \"TRANSFERS\"\n  STR_TRANSFERS: \"Transfers\"\n  STR_ARRIVAL_TIME_HOURS: \"Ankunftszeit (Stunden)\"\n  STR_COST_: \"Kosten>{ALT}{0}\"\n  STR_AREA_: \"Gebiet>{ALT}{0}\"\n  STR_BASE_NAME: \"Stützpunktname?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"POSITION FÜR HAUPTAUFZUG WÄHLEN\"\n  STR_TRANSFER: \"Transfer\"\n  STR_AMOUNT_TO_TRANSFER: \"TRANSPORT MENGE\"\n  STR_SELECT_DESTINATION_BASE: \"Zielstützpunkt wählen\"\n  STR_COST: \"Kosten\"\n  STR_VICTORY_1: \"Als Sie den Raum betreten, sehen Sie das außerirdische Gehirn, das Ziel Ihrer Suche.  Bevor Sie feuern können, beginnt es über einen Bildschirm mit Ihnen zu kommunizieren.  Es fleht Sie an, ihm zuzuhören, bevor Sie sich entschließen, abzudrücken...\"\n  STR_VICTORY_2: \"Das Gehirn spricht: 'Vor vielen Millionen Jahren gab es Leben auf dem Planeten, den Ihr Mars nennt.  Es wurde von unserer Zivilisation auf diesen nun öden Planeten und auch auf die Erde gebracht.  Millionen Jahre lang haben wir euren Planeten besucht und eure Spezies weiterentwickelt.  Ihr könnt uns nicht töten, ihr seid ein Teil von uns...\"\n  STR_VICTORY_3: \"Die Pyramiden sind das Zentrum der marsianischen Zivilisation.  Sie wurden Millionen von Jahren vor euren gebaut - von einer Spezies, aus der eure Vorfahren stammen.  Wir können jeden Planeten erreichen, und diese Macht könnte in naher Zukunft euch gehören.  Wir bitten nur um eure Kooperation...\"\n  STR_GAME_OVER_1: \"Die Außerirdischen versuchen, die Menschheit auszurotten, sie zerstören Städte und vergiften die Luft und die Meere. Der Widerstand der Armeen der Erde ist sinnlos im Angesicht derartig überlegener Technologien. Die überlebenden Generationen erleiden entsetzliche Mutationen, als sie vor der außerirdischen Vernichtung flüchten. Sie werden in Sklavenlagern zusammengetrieben, um den Außerirdischen dabei zu helfen, die Erde in die Kolonie eines unbekannten Reiches zu verwandeln.\"\n  STR_GAME_OVER_2: \"Das Wissen, das die XCom angesammelt hat, ist für immer verloren. Sie haben es nicht geschafft, die Erde zu retten.\"\n  STR_VICTORY_4: \"Das außerirdische Gehirn wird durch einen heißen Plasmastoß von der Außerirdischen-Armee getrennt, die dadurch besiegt ist.\"\n  STR_VICTORY_5: \"Mit dem Verlust des Planeten Mars haben die Außerirdischen auch die Erde verloren. Bald blüht die Menschheit dank der XCom-Forschung wieder auf und ergreift selbst Besitz vom Mars. Die Bedrohung durch die Außerirdischen ist abgewendet, doch niemand weiß, für wie lange...\"\n  STR_YOU_HAVE_FAILED: \"Es ist Ihnen nicht gelungen, den Ansturm der Außerirdischen zu stoppen. Eine Geldgebernation nach der anderen unterzeichnet Verträge mit den Außerirdischen, die Technologie, Reichtum und Frieden versprechen. Doch schon bald wird deutlich, daß die Außerirdischen andere Pläne haben...\"\n  STR_TOTAL_UC: \"GESAMT\"\n  STR_INCOME: \"Einkommen\"\n  STR_EXPENDITURE: \"Ausgaben\"\n  STR_MAINTENANCE: \"Erhaltung\"\n  STR_BALANCE: \"Saldo\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"UFO-Aktivitäten in bestimmten Gebieten\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"UFO-Aktivitäten in bestimmten Ländern\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"XCom-Aktivitäten in bestimmten Gebieten\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"XCom-Aktivitäten in bestimmten Ländern\"\n  STR_FINANCE: \"Finanzen\"\n  STR_DATE_FIRST: \"{0}.\"\n  STR_DATE_SECOND: \"{0}.\"\n  STR_DATE_THIRD: \"{0}.\"\n  STR_DATE_FOURTH: \"{0}.\"\n  STR_FINANCE_THOUSANDS: \"$1000er\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Nicht genug Spezialmaterial zur Produktion von{NEWLINE}{0}{NEWLINE}in{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Nicht genug Geld zur Produktion von{NEWLINE}{0}{NEWLINE}in{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"Produktion abgeschlossen: {NEWLINE}{0}{NEWLINE}in{NEWLINE}{1}\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"Bau von {NEWLINE}{0}{NEWLINE}in{NEWLINE}{1}{NEWLINE}ist abgeschlossen\"\n  STR_OK_5_SECONDS: \"OK - 5 Sek.\"\n  STR_RESEARCH_COMPLETED: \"Forschung abgeschlossen\"\n  STR_VIEW_REPORTS: \"BERICHTE\"\n  STR_WE_CAN_NOW_RESEARCH: \"Wir können jetzt folgendes erforschen:\"\n  STR_WE_CAN_NOW_PRODUCE: \"Wir können jetzt folgendes {NEWLINE} produzieren:\"\n  STR_SUNDAY: \"SONNTAG\"\n  STR_MONDAY: \"MONTAG\"\n  STR_TUESDAY: \"DIENSTAG\"\n  STR_WEDNESDAY: \"MITTWOCH\"\n  STR_THURSDAY: \"DONNERSTAG\"\n  STR_FRIDAY: \"FREITAG\"\n  STR_SATURDAY: \"SAMSTAG\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Nicht genug {0} zum Auftanken von {1} in {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Nicht genug {0} zum Bewaffnen von {1} in {2}\"\n  STR_UFO_IS_NOT_RECOVERED: \"UFO wurde nicht geborgen\"\n  STR_UFO_IS_RECOVERED: \"UFO wurde geborgen\"\n  STR_CRAFT_IS_LOST: \"Raumschiff ist verloren\"\n  STR_TERROR_CONTINUES: \"Terror wird fortgesetzt\"\n  STR_ALIENS_DEFEATED: \"Außerirdische besiegt\"\n  STR_BASE_IS_LOST: \"Stützpunkt ist verloren\"\n  STR_BASE_IS_SAVED: \"Stützpunkt ist gerettet\"\n  STR_ALIEN_BASE_STILL_INTACT: \"Außerirdischen-Stützpunkt noch funktionsfähig\"\n  STR_ALIEN_BASE_DESTROYED: \"Außerirdischen-Stützpunkt zerstört\"\n  STR_ALIENS_KILLED: \"GETÖTETE AUSSERIRDISCHE\"\n  STR_ALIEN_CORPSES_RECOVERED: \"TOTE AUSSERIRDISCHE GEBORGEN\"\n  STR_LIVE_ALIENS_RECOVERED: \"LEBENDE AUSSERIRDISCHE GEBORGEN\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"AUSSERIRDISCHE ARTEFAKTE GEBORGEN\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"AUSSERIRDISCHEN-STÜTZPUNKTKONTROLLE ZERSTÖRT\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"VON AUSSERIRDISCHEN GETÖTETE ZIVILISTEN\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"VON XCOM-MITARBEITERN GETÖTETE ZIVILISTEN\"\n  STR_CIVILIANS_SAVED: \"GERETTETE ZIVILISTEN\"\n  STR_XCOM_OPERATIVES_KILLED: \"XCOM-MITARBEITER GETÖTET\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"XCOM-MITARBEITER VERMISST\"\n  STR_TANKS_DESTROYED: \"PANZER ZERSTÖRT\"\n  STR_XCOM_CRAFT_LOST: \"XCOM-RAUMSCHIFFE VERLOREN\"\n  STR_UFO_RECOVERY: \"UFO-BERGUNG\"\n  STR_ALIEN_BASE_RECOVERY: \"BERGUNG EINES AUSSERIRDISCHEN-STÜTZPUNKTES\"\n  STR_BASE_UNDER_ATTACK: \"{0} wird angegriffen!\"\n  STR_BASE_DEFENSES_INITIATED: \"STÜTZPUNKT-VERTEIDIGUNG AKTIVIERT\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"GRAVITATIONSSCHILD HÄLT UFO AB!\"\n  STR_FIRING: \"FEUER\"\n  STR_HIT: \"TREFFER!\"\n  STR_UFO_DESTROYED: \"UFO ZERSTÖRT!\"\n  STR_MISSED: \"VERFEHLT!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Gegenstände verkaufen/Personal entlassen\"\n  STR_VALUE_OF_SALES: \"VERKAUFSWERT> {ALT}{0}\"\n  STR_FUNDS: \"GELDER> {ALT}{0}\"\n  STR_SELL_SACK: \"Verkaufen/Entlassen\"\n  STR_VALUE: \"     Wert\"\n  STR_CRAFT_: \"RAUMSCHIFF> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"UFO-WRACKBERGUNG\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"Vorsicht - Im UFO oder an der Absturzstelle können sich XCom-Mitarbeiter befinden. Einsatz ist erfolgreich abgeschlossen, wenn alle gegnerischen Einheiten eliminiert oder neutralisiert sind. Danach kann die Bergung der Wrackteile, Artefakte und toten Außerirdischen beginnen. Um die Mission abzubrechen, lassen Sie die XCom-Mitarbeiter in den Transporter zurückkehren und klicken das Icon 'Mission abbrechen' an.\"\n  STR_UFO_GROUND_ASSAULT: \"UFO-BODENANGRIFF\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"Landeplatz untersuchen und, wenn möglich, Zugang zum UFO verschaffen. Einsatz ist erfolgreich abgeschlossen, wenn alle gegnerischen Einheiten eliminiert oder neutralisiert sind. Danach kann mit der Bergung des UFOs, der Artefakte und toten Außerirdischen begonnen werden. Um die Mission abzubrechen, bringen Sie die XCom-Mitarbeiter zum Transporter zurück und klicken das Icon 'Mission abbrechen' an.\"\n  STR_BASE_DEFENSE: \"STÜTZPUNKTVERTEIDIGUNG\"\n  STR_BASE_UC_: \"STÜTZPUNKT> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"Ein außerirdisches Raumschiff ist in der Nähe gelandet. Unser Stützpunkt ist in großer Gefahr. Laut Standardverfahren wurden sämtliche Zivilpersonen und XCom-Raumschiffe evakuiert. Die außerirdischen Einheiten werden den Stützpunkt über die Hangartüren oder den Hauptaufzug betreten. Verteidigen Sie den Stützpunkt und seine Einrichtungen um jeden Preis - es ist ein Kampf auf Leben und Tod. Wenn Sie das Icon 'Mission abbrechen' anklicken, verlieren Sie den Kampf und den Stützpunkt.\"\n  STR_ALIEN_BASE_ASSAULT: \"ANGRIFF AUF AUSSERIRDISCHEN-STÜTZPUNKT\"\n  STR_ALIEN_BASE_ASSAULT_BRIEFING: \"XCom-Mitarbeiter sind in einen Stützpunkt der Außerirdischen eingedrungen. Das Kontrollzentrum muß zerstört werden, um den Stützpunkt funktionsunfähig zu machen. Der Einsatz endet, wenn alle Gegner eliminiert sind oder Ihre Einsatztruppe zum grünen Ausgangsbereich zurückgekehrt ist. (Für eine Flucht das Icon 'Mission abbrechen' anklicken.)\"\n  STR_CYDONIA_BRIEFING: \"Sie haben Cydonia erreicht.  Sie dringen in einen großen unterirdischen Komplex in der Nähe der Mars-Sphinx ein.  Sie müssen das Außerirdische Gehirn vernichten, das alle Aktivitäten der Eindringlinge steuert.  Das Schicksal der Menschheit liegt in Ihrer Hand....\"\n  STR_TERROR_MISSION: \"TERRORISTEN-MISSION\"\n  STR_TERROR_MISSION_BRIEFING: \"Die Mission ist erfolgreich abgeschlossen, wenn alle gegnerischen Einheiten eliminiert oder neutralisiert wurden. Versuchen Sie unbedingt, das Leben aller Zivilisten in dem Gebiet zu retten, indem Sie die außerirdische Gefahr ausschalten. Um den Einsatz abzubrechen, bringen Sie Ihre Männer zum Transporter zurück und klicken das Icon 'Mission abbrechen' an.\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"KEINE FREIEN HANGARS FÜR RAUMSCHIFFPRODUKTION!{SMALLLINE}Jedes Raumschiff, das verlegt, gekauft oder gebaut wird, benötigt einen Hangar.  Bauen Sie einen neuen Hangar, oder verlegen Sie das Raumschiff auf einen anderen Stützpunkt.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"KEINE FREIEN HANGARS FÜR DEN KAUF!{SMALLLINE}Jedes Raumschiff, das verlegt, gekauft oder gebaut wird, benötigt einen Hangar.  Bauen Sie einen neuen Hangar, oder verlegen Sie das Raumschiff auf einen anderen Stützpunkt.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"KEINE FREIEN HANGARS FÜR DEN TRANSFER!{SMALLLINE}Jedes Raumschiff, das verlegt, gekauft oder gebaut wird, benötigt einen Hangar.  Bauen Sie einen neuen Hangar, oder verlegen Sie das Raumschiff auf einen anderen Stützpunkt.\"\n  STR_CANNOT_BUILD_HERE: \"KANN HIER NICHT GEBAUT WERDEN!{SMALLLINE}Sie müssen neben einer bereits bestehenden Stützpunkt-Einrichtung bauen.\"\n  STR_NO_FREE_ACCOMODATION: \"KEINE FREIEN QUARTIERE!{SMALLLINE}Der Zielstützpunkt hat nicht genug Platz in den Wohnquartieren.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"NICHT GENUG ARBEITSRAUM VERFÜGBAR!{SMALLLINE}Bauen Sie eine neue Werkstatt, oder reduzieren Sie die Arbeit an anderen Projekten.\"\n  STR_NOT_ENOUGH_MONEY: \"NICHT GENUG GELD!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"NICHT GENUG LAGERPLATZ!{SMALLLINE}Bauen Sie neue Lager, oder transferieren Sie gelagerte Güter auf andere Stützpunkte.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"NICHT GENUG QUARTIERE!{SMALLLINE}Bauen Sie neue Wohnquartiere, oder verlegen Sie Personal auf andere Stützpunkte.\"\n  STR_LAUNCH_INTERCEPTION: \"ABFANGMANÖVER STARTEN\"\n  STR_CRAFT: \"RAUMSCHIFF\"\n  STR_STATUS: \"STATUS\"\n  STR_BASE: \"STÜTZPUNKT\"\n  STR_READY: \"BEREIT\"\n  STR_OUT: \"UNTERWEGS\"\n  STR_REPAIRS: \"REPARATUR\"\n  STR_REFUELLING: \"AUFTANKEN\"\n  STR_REARMING: \"BEWAFFNEN\"\n  STR_TARGET: \"ZIEL: {0}\"\n  STR_WAY_POINT: \"WEGMARKE\"\n  STR_ARE_YOU_SURE_CYDONIA: \"Sind Sie sicher, daß Sie dieses Raumschiff auf eine Mission nach Cydonia schicken wollen?\"\n  STR_YES: \"JA\"\n  STR_NO: \"NEIN\"\n  STR_SELECT_DESTINATION: \"ZIEL WÄHLEN\"\n  STR_CYDONIA: \"CYDONIA\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"STÜTZPUNKT-STANDORT WÄHLEN\"\n  STR_RETURN_TO_BASE: \"ZURÜCK ZUM STÜTZPUNKT\"\n  STR_SELECT_NEW_TARGET: \"NEUES ZIEL WÄHLEN\"\n  STR_PATROL: \"PATROUILLIEREN\"\n  STR_STATUS_: \"STATUS>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"BESCHÄDIGT - RÜCKKEHR{NEWLINE}ZUM STÜTZPUNKT\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"ZU WENIG TREIBSTOFF -{NEWLINE}RÜCKKEHR ZUM STÜTZPUNKT\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"MISSION KOMPLETT - RÜCKKEHR ZUM STÜTZPUNKT\"\n  STR_PATROLLING: \"PATROUILLIERT\"\n  STR_TAILING_UFO: \"VERFOLGT UFO\"\n  STR_INTERCEPTING_UFO: \"ABFANGVORGANG UFO-{0}\"\n  STR_RETURNING_TO_BASE: \"RÜCKKEHR ZUM STÜTZPUNKT\"\n  STR_DESTINATION_UC_: \"ZIEL: {0}\"\n  STR_BASE_UC: \"STÜTZPUNKT>{ALT}{0}\"\n  STR_SPEED_: \"GESCHWINDIGKEIT>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"HÖCHSTGESCHWINDIGKEIT>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"HÖHE>{ALT}{0}\"\n  STR_VERY_LOW: \"SEHR NIEDRIG\"\n  STR_LOW_UC: \"NIEDRIG\"\n  STR_HIGH_UC: \"HOCH\"\n  STR_VERY_HIGH: \"SEHR HOCH\"\n  STR_FUEL: \"TREIBSTOFF>{ALT}{0}\"\n  STR_WEAPON_ONE: \"WAFFE-1>{ALT}{0}\"\n  STR_NONE_UC: \"OHNE\"\n  STR_ROUNDS_: \"SCHUSS>{ALT}{0}\"\n  STR_WEAPON_TWO: \"WAFFE-2>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"ABFANGJÄGER\"\n  STR_BASE_: \"Stützpunkt>{0}\"\n  STR_NAME_UC: \"NAME\"\n  STR_AMMO_: \"MUNITION>{ALT}{0}\"\n  STR_CREW: \"BESATZUNG\"\n  STR_EQUIPMENT_UC: \"AUSRÜSTUNG\"\n  STR_ARMOR: \"RÜSTUNG\"\n  STR_MAX: \"MAX>{ALT}{0}\"\n  STR_ROOKIE: \"Einfacher Soldat\"\n  STR_SQUADDIE: \"Gefreiter\"\n  STR_SERGEANT: \"Feldwebel\"\n  STR_CAPTAIN: \"Hauptmann\"\n  STR_COLONEL: \"Oberst\"\n  STR_COMMANDER: \"Kommandant\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Einsatztruppe wählen für {0}\"\n  STR_SORT_BY: \"SORTIERE NACH...\"\n  STR_ORIGINAL_ORDER: \"ORIGINALE REIHENFOLGE\"\n  STR_MISSIONS2: \"MISSIONEN\"\n  STR_KILLS2: \"ABSCHÜSSE\"\n  STR_WOUND_RECOVERY2: \"WUNDHEILUNG\"\n  STR_SPACE_AVAILABLE: \"PLATZ VERFÜGBAR>{ALT}{0}\"\n  STR_SPACE_USED: \"PLATZ GENUTZT>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"PLATZ GENUTZT\"\n  STR_RANK: \"RANG\"\n  STR_WOUNDED: \"VERWUNDET\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Ausrüstung für {0}\"\n  STR_DEFENSE_VALUE: \"Verteidigungswert\"\n  STR_HIT_RATIO: \"Trefferquote\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}bereit zur Landung{NEWLINE}in der Nähe von{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"Mission beginnen?\"\n  STR_SELECT_ARMAMENT: \"Bewaffnung wählen\"\n  STR_AMMUNITION_AVAILABLE: \"MUNITION VERFÜGBAR\"\n  STR_ARMAMENT: \"BEWAFFNUNG\"\n  STR_NOT_AVAILABLE: \"-\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"RÜSTUNG WÄHLEN FÜR{NEWLINE}{0}\"\n  STR_TYPE: \"TYP\"\n  STR_PERSONAL_ARMOR_UC: \"PERSÖNLICHE RÜSTUNG\"\n  STR_POWER_SUIT_UC: \"ENERGIEANZUG\"\n  STR_FLYING_SUIT_UC: \"FLUGANZUG\"\n  STR_SELECT_ARMOR: \"Rüstung wählen\"\n  STR_NORTH: \"NORDEN\"\n  STR_NORTH_EAST: \"NORDOSTEN\"\n  STR_EAST: \"OSTEN\"\n  STR_SOUTH_EAST: \"SÜDOSTEN\"\n  STR_SOUTH: \"SÜDEN\"\n  STR_SOUTH_WEST: \"SÜDWESTEN\"\n  STR_WEST: \"WESTEN\"\n  STR_NORTH_WEST: \"NORDWESTEN\"\n  STR_SELECT_ACTION: \"HANDLUNG WÄHLEN\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"ABFANGMANÖVER FORTSETZEN\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"VERFOLGUNG FORTSETZEN\"\n  STR_VERY_LARGE: \"SEHR GROSS\"\n  STR_LARGE: \"GROSS\"\n  STR_MEDIUM_UC: \"MITTELGROSS\"\n  STR_SMALL: \"KLEIN\"\n  STR_VERY_SMALL: \"SEHR KLEIN\"\n  STR_GROUNDED: \"BODEN\"\n  STR_DETECTED: \"Entdeckt\"\n  STR_SIZE_UC: \"GRÖSSE\"\n  STR_ALTITUDE: \"HÖHE\"\n  STR_HEADING: \"KURS\"\n  STR_SPEED: \"GESCHWINDIGKEIT\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"UFO ZENTRIEREN-ZEIT=5 Sek.\"\n  STR_TRACKING_LOST: \"SPUR VERLOREN\"\n  STR_REDIRECT_CRAFT: \"RAUMSCHIFF UMLEITEN\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"ZURÜCK ZUR LETZTEN BEKANNTEN UFO-POSITION\"\n  STR_UFO_: \"UFO-{0}\"\n  STR_ALIEN_BASE_: \"AUSSERIRDISCHEN-STÜTZPUNKT-{0}\"\n  STR_CRASH_SITE_: \"ABSTURZSTELLE-{0}\"\n  STR_LANDING_SITE_: \"LANDEPLATZ-{0}\"\n  STR_WAY_POINT_: \"WEGMARKE-{0}\"\n  STR_TERROR_SITE: \"Terroristenlager-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}erreicht{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"Patrouilliert jetzt\"\n  STR_ALIEN_ORIGINS: \"Außerirdische Ursprünge\"\n  STR_THE_MARTIAN_SOLUTION: \"Die Marsianische Lösung\"\n  STR_CYDONIA_OR_BUST: \"Cydonia oder Tod\"\n  STR_UFOPAEDIA: \"UFOpedia\"\n  STR_XCOM_CRAFT_ARMAMENT: \"XCOM-RAUMSCHIFFE & BEWAFFNUNG\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"SCHWERE WAFFENTRÄGER\"\n  STR_WEAPONS_AND_EQUIPMENT: \"WAFFEN UND AUSRÜSTUNG\"\n  STR_ALIEN_ARTIFACTS: \"AUSSERIRDISCHE ARTEFAKTE\"\n  STR_BASE_FACILITIES: \"STÜTZPUNKT-EINRICHTUNGEN\"\n  STR_ALIEN_LIFE_FORMS: \"AUSSERIRDISCHE LEBENSFORMEN\"\n  STR_ALIEN_RESEARCH_UC: \"AUSSERIRDISCHENFORSCHUNG\"\n  STR_UFO_COMPONENTS: \"UFO-TEILE\"\n  STR_UFOS: \"UFOs\"\n  STR_SELECT_ITEM: \"GEGENSTAND WÄHLEN\"\n  STR_ACCELERATION: \"BESCHLEUNIGUNG>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"TREIBSTOFFKAPAZITÄT>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"WAFFENBEHÄLTER>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"SCHADENSKAPAZITÄT>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"FRACHTRAUM>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"SWT KAPAZITÄT>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Schaden\"\n  STR_RANGE: \"Reichweite\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Genauigkeit\"\n  STR_RE_LOAD_TIME: \"Nachladezeit\"\n  STR_SECONDS: \"{0}s\"\n  STR_DAMAGE_ARMOR_PIERCING: \"PANZERBRECHEND\"\n  STR_DAMAGE_INCENDIARY: \"BRANDSATZ\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"HOCHEXPLOSIV\"\n  STR_DAMAGE_LASER_BEAM: \"LASERSTRAHL\"\n  STR_DAMAGE_PLASMA_BEAM: \"PLASMASTRAHL\"\n  STR_DAMAGE_STUN: \"BETÄUBT\"\n  STR_DAMAGE_MELEE: \"NAHKAMPF\"\n  STR_DAMAGE_ACID: \"SÄURE\"\n  STR_DAMAGE_SMOKE: \"RAUCH\"\n  STR_SHOT_TYPE: \"SCHUSSART\"\n  STR_ACCURACY_UC: \"GENAUIGKEIT\"\n  STR_TIME_UNIT_COST: \"ZE-KOSTEN\"\n  STR_DAMAGE_UC: \"SCHADEN\"\n  STR_AMMO: \"MUNITION\"\n  STR_SHOT_TYPE_AUTO: \"Auto-Schuss  \"\n  STR_SHOT_TYPE_SNAP: \"Schnellschuss\"\n  STR_SHOT_TYPE_AIMED: \"Zielschuss\"\n  STR_CONSTRUCTION_TIME: \"Bauzeit\"\n  STR_CONSTRUCTION_COST: \"Baukosten\"\n  STR_MAINTENANCE_COST: \"Instandhaltungskosten\"\n  STR_LOW: \"Niedrig\"\n  STR_MEDIUM: \"Mittel\"\n  STR_HIGH: \"Hoch\"\n  STR_CRAFT_WEAPON: \"Raumschiffwaffe\"\n  STR_CRAFT_AMMUNITION: \"Raumschiffmunition\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Schwerer Waffenträger\"\n  STR_WEAPON: \"Waffe\"\n  STR_AMMUNITION: \"Munition\"\n  STR_EQUIPMENT: \"Ausrüstung\"\n  STR_ALIEN_CORPSE: \"Toter Außerirdischer\"\n  STR_UFO_COMPONENT: \"UFO-Bauteil\"\n  STR_PERSONAL_ARMOR: \"Persönliche Rüstung\"\n  STR_RAW_MATERIALS: \"Rohmaterial\"\n  STR_HWP_CANNON_SHELLS: \"SWT-Geschützmunition\"\n  STR_ALIEN: \"Außerirdischer\"\n  STR_SECTOID: \"Sektoid\"\n  STR_SNAKEMAN: \"Schlangenmensch\"\n  STR_ETHEREAL: \"Ätherer\"\n  STR_MUTON: \"Mutone\"\n  STR_FLOATER: \"Schweber\"\n  STR_CELATID: \"Celatid\"\n  STR_SILACOID: \"Silakoid\"\n  STR_CHRYSSALID: \"Chryssalid\"\n  STR_ZOMBIE: \"Zombie\"\n  STR_REAPER: \"Schnitter\"\n  STR_SECTOPOD: \"Sektopod\"\n  STR_CYBERDISC: \"Cyberdisc\"\n  STR_LIVE_COMMANDER: \"Kommandant\"\n  STR_LIVE_LEADER: \"Anführer\"\n  STR_LIVE_ENGINEER: \"Ingenieur\"\n  STR_LIVE_MEDIC: \"Arzt\"\n  STR_LIVE_NAVIGATOR: \"Navigator\"\n  STR_LIVE_SOLDIER: \"Soldat\"\n  STR_LIVE_TERRORIST: \"Terrorist\"\n  STR_FLOATER_SOLDIER: \"Schweber-Soldat\"\n  STR_FLOATER_NAVIGATOR: \"Schweber-Navigator\"\n  STR_FLOATER_MEDIC: \"Schweber-Arzt\"\n  STR_FLOATER_ENGINEER: \"Schweber-Ingenieur\"\n  STR_FLOATER_LEADER: \"Schweber-Anführer\"\n  STR_FLOATER_COMMANDER: \"Schweber-Kommandant\"\n  STR_SECTOID_SOLDIER: \"Sektoid-Soldat\"\n  STR_SECTOID_NAVIGATOR: \"Sektoid-Navigator\"\n  STR_SECTOID_MEDIC: \"Sektoid-Arzt\"\n  STR_SECTOID_ENGINEER: \"Sektoid-Ingenieur\"\n  STR_SECTOID_LEADER: \"Sektoid-Anführer\"\n  STR_SECTOID_COMMANDER: \"Sektoid-Kommandant\"\n  STR_SNAKEMAN_SOLDIER: \"Schlangenmensch-Soldat\"\n  STR_SNAKEMAN_NAVIGATOR: \"Schlangenmensch-Navigator\"\n  STR_SNAKEMAN_ENGINEER: \"Schlangenmensch-Ingenieur\"\n  STR_SNAKEMAN_LEADER: \"Schlangenmensch-Anführer\"\n  STR_SNAKEMAN_COMMANDER: \"Schlangenmensch-Kommandant\"\n  STR_MUTON_SOLDIER: \"Mutone-Soldat\"\n  STR_MUTON_NAVIGATOR: \"Mutone-Navigator\"\n  STR_MUTON_ENGINEER: \"Mutone-Ingenieur\"\n  STR_ETHEREAL_SOLDIER: \"Ätherer-Soldat\"\n  STR_ETHEREAL_LEADER: \"Ätherer-Anführer\"\n  STR_ETHEREAL_COMMANDER: \"Ätherer-Kommandant\"\n  STR_CYBERDISC_TERRORIST: \"Cyberdisc-Terrorist\"\n  STR_REAPER_TERRORIST: \"Schnitter-Terrorist\"\n  STR_CHRYSSALID_TERRORIST: \"Chryssalid-Terrorist\"\n  STR_CELATID_TERRORIST: \"Celatid-Terrorist\"\n  STR_SILACOID_TERRORIST: \"Silakoid-Terrorist\"\n  STR_SECTOPOD_TERRORIST: \"Sektopod-Terrorist\"\n  STR_UFO_POWER_SOURCE: \"UFO-Energiequelle\"\n  STR_UFO_NAVIGATION: \"UFO-Navigation\"\n  STR_UFO_CONSTRUCTION: \"UFO-Konstruktion\"\n  STR_ALIEN_FOOD: \"Außerirdische Nahrung\"\n  STR_ALIEN_REPRODUCTION: \"Außerirdische Fortpflanzung\"\n  STR_ALIEN_ENTERTAINMENT: \"Außerirdische Unterhaltung\"\n  STR_ALIEN_SURGERY: \"Außerirdische Chirurgie\"\n  STR_EXAMINATION_ROOM: \"Untersuchungsraum\"\n  STR_ALIEN_ALLOYS: \"Außerirdische Legierungen\"\n  STR_ALIEN_HABITAT: \"Außerirdisches Habitat\"\n  STR_POWER_SUIT: \"Energieanzug\"\n  STR_FLYING_SUIT: \"Fluganzug\"\n  STR_HWP_ROCKETS: \"SWT-Raketen\"\n  STR_HWP_FUSION_BOMB: \"SWT-Fusionsbombe\"\n  STR_LASER_WEAPONS: \"Laserwaffen\"\n  STR_NEW_FIGHTER_CRAFT: \"Neuer Kampfjäger\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Neuer Kampfjäger-Transporter\"\n  STR_ULTIMATE_CRAFT: \"Top-Raumschiff\"\n  STR_LASER_PISTOL: \"Laserpistole\"\n  STR_LASER_RIFLE: \"Lasergewehr\"\n  STR_HEAVY_LASER: \"Schwerer Laser\"\n  STR_LASER_CANNON: \"Lasergeschütz\"\n  STR_PLASMA_CANNON: \"Plasmageschütz\"\n  STR_FUSION_MISSILE: \"Fusionsrakete\"\n  STR_LASER_DEFENSE: \"Laser-Abwehr\"\n  STR_PLASMA_DEFENSE: \"Plasma-Abwehr\"\n  STR_FUSION_DEFENSE: \"Fusionsabwehr\"\n  STR_GRAV_SHIELD: \"Gravitationsschild\"\n  STR_MIND_SHIELD: \"Gedankenschild\"\n  STR_PSI_LAB: \"Psi-Labor\"\n  STR_MOTION_SCANNER: \"Bewegungsscanner\"\n  STR_MEDI_KIT: \"Sani-Tasche\"\n  STR_TANK_CANNON: \"Panzer/Geschütz\"\n  STR_TANK_ROCKET_LAUNCHER: \"Panzer/Raketenwerfer\"\n  STR_TANK_LASER_CANNON: \"Panzer/Lasergeschütz\"\n  STR_HOVERTANK_PLASMA: \"Schwebepanzer/Plasma\"\n  STR_HOVERTANK_LAUNCHER: \"Schwebepanzer/ Werfer\"\n  STR_STINGRAY_LAUNCHER: \"Stingray-Raketenwerfer\"\n  STR_AVALANCHE_LAUNCHER: \"Avalanche-Raketenwerfer\"\n  STR_CANNON: \"Geschütz\"\n  STR_FUSION_BALL_LAUNCHER: \"Fusionskugelwerfer\"\n  STR_PLASMA_BEAM: \"Plasmastrahl\"\n  STR_STINGRAY_MISSILES: \"Stingray-Rakete\"\n  STR_AVALANCHE_MISSILES: \"Avalanche-Rakete\"\n  STR_CANNON_ROUNDS_X50: \"Schuß für Geschütz (x50)\"\n  STR_FUSION_BALL: \"Fusionskugel\"\n  STR_SOLDIER: \"Soldat\"\n  STR_SCIENTIST: \"Wissenschaftler\"\n  STR_ENGINEER: \"Ingenieur\"\n  STR_NORTH_AMERICA: \"Nordamerika\"\n  STR_ARCTIC: \"Arktis\"\n  STR_ANTARCTICA: \"Antarktis\"\n  STR_SOUTH_AMERICA: \"Südamerika\"\n  STR_EUROPE: \"Europa\"\n  STR_NORTH_AFRICA: \"Nordafrika\"\n  STR_SOUTHERN_AFRICA: \"Südliches Afrika\"\n  STR_CENTRAL_ASIA: \"Zentralasien\"\n  STR_SOUTH_EAST_ASIA: \"Südostasien\"\n  STR_SIBERIA: \"Sibirien\"\n  STR_AUSTRALASIA: \"Australien\"\n  STR_PACIFIC: \"Pazifik\"\n  STR_NORTH_ATLANTIC: \"Nordatlantik\"\n  STR_SOUTH_ATLANTIC: \"Südatlantik\"\n  STR_INDIAN_OCEAN: \"Indischer Ozean\"\n  STR_ALIEN_RESEARCH: \"Außerirdische Forschung\"\n  STR_ALIEN_HARVEST: \"Außerirdische Ernte\"\n  STR_ALIEN_ABDUCTION: \"Außerirdische Entführung\"\n  STR_ALIEN_INFILTRATION: \"Außerirdische Infiltration\"\n  STR_ALIEN_BASE: \"Außerirdischen-Stützpunkt\"\n  STR_ALIEN_TERROR: \"Außerirdischer Terror\"\n  STR_ALIEN_RETALIATION: \"Außerirdischen-Vergeltung\"\n  STR_ALIEN_SUPPLY: \"Außerirdischen-Versorgung\"\n  STR_MAXIMUM_SPEED: \"Höchstgeschwindigkeit\"\n  STR_HYPER_WAVE_DECODER_UC: \"HYPERWELLEN-DECODER\"\n  STR_SKYRANGER: \"SKYRANGER\"\n  STR_LIGHTNING: \"LIGHTNING\"\n  STR_AVENGER: \"AVENGER\"\n  STR_INTERCEPTOR: \"ABFANGJÄGER\"\n  STR_FIRESTORM: \"FIRESTORM\"\n  STR_UFO: \"UFO\"\n  STR_STINGRAY: \"STINGRAY\"\n  STR_AVALANCHE: \"AVALANCHE\"\n  STR_CANNON_UC: \"GESCHÜTZ\"\n  STR_FUSION_BALL_UC: \"FUSIONSKUGEL\"\n  STR_LASER_CANNON_UC: \"LASERGESCHÜTZ\"\n  STR_PLASMA_BEAM_UC: \"PLASMASTRAHL\"\n  STR_DAMAGE_CAPACITY: \"Schadenskapazität\"\n  STR_WEAPON_POWER: \"Waffenstärke\"\n  STR_WEAPON_RANGE: \"Reichweite der Waffen\"\n  STR_ACCESS_LIFT: \"Hauptaufzug\"\n  STR_LABORATORY: \"Labor\"\n  STR_WORKSHOP: \"Werkstatt\"\n  STR_SMALL_RADAR_SYSTEM: \"Kleines Radarsystem\"\n  STR_LARGE_RADAR_SYSTEM: \"Großes Radarsystem\"\n  STR_MISSILE_DEFENSES: \"Raketenabwehr\"\n  STR_GENERAL_STORES: \"Hauptlager\"\n  STR_ALIEN_CONTAINMENT: \"Außerirdischen-Klimazelle\"\n  STR_LASER_DEFENSES: \"Laser-Abwehr\"\n  STR_PLASMA_DEFENSES: \"Plasma-Abwehr\"\n  STR_FUSION_BALL_DEFENSES: \"Fusionskugel-Abwehr\"\n  STR_PSIONIC_LABORATORY: \"Psionisches Labor\"\n  STR_HYPER_WAVE_DECODER: \"Hyperwellen-Decoder\"\n  STR_HANGAR: \"Hangar\"\n  STR_USA: \"USA\"\n  STR_RUSSIA: \"RUSSLAND\"\n  STR_UK: \"GB\"\n  STR_FRANCE: \"FRANKREICH\"\n  STR_GERMANY: \"DEUTSCHLAND\"\n  STR_ITALY: \"ITALIEN\"\n  STR_SPAIN: \"SPANIEN\"\n  STR_CHINA: \"CHINA\"\n  STR_JAPAN: \"JAPAN\"\n  STR_INDIA: \"INDIEN\"\n  STR_BRAZIL: \"BRASILIEN\"\n  STR_AUSTRALIA: \"AUSTRALIEN\"\n  STR_NIGERIA: \"NIGERIA\"\n  STR_SOUTH_AFRICA: \"SÜDAFRIKA\"\n  STR_EGYPT: \"ÄGYPTEN\"\n  STR_CANADA: \"KANADA\"\n  STR_TANK: \"Panzer\"\n  STR_CIVILIAN: \"Zivilist\"\n  STR_JAN: \"Jan\"\n  STR_FEB: \"Feb\"\n  STR_MAR: \"Mär\"\n  STR_APR: \"Apr\"\n  STR_MAY: \"Mai\"\n  STR_JUN: \"Jun\"\n  STR_JUL: \"Jul\"\n  STR_AUG: \"Aug\"\n  STR_SEP: \"Sep\"\n  STR_OCT: \"Okt\"\n  STR_NOV: \"Nov\"\n  STR_DEC: \"Dez\"\n  STR_INTERNATIONAL_RELATIONS: \"Internationale Beziehungen\"\n  STR_COUNTRY: \"Land\"\n  STR_FUNDING: \"Gelder\"\n  STR_CHANGE: \"Differenz\"\n  STR_WEAPON_SYSTEMS: \"WAFFEN-SYSTEME\"\n  STR_HWPS: \"SWTs\"\n  STR_DAMAGE_UC_: \"SCHADEN>{ALT}{0}\"\n  STR_ACCESS_LIFT_UFOPEDIA: \"Über den Hauptaufzug gelangen Personal und Ausrüstung in den unterirdischen Stützpunkt.  Er ist daher immer die erste Einrichtung, die auf einem neuen Stützpunkt gebaut wird.  Der Aufzug ist der empfindlichste Punkt bei feindlichen Angriffen.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"In jedem Wohnblock leben bis zu 50 Personen.  Die Anlage umfaßt die wichtigsten Erholungseinrichtungen, Nahrungsmittel und Schlafbereiche.\"\n  STR_LABORATORY_UFOPEDIA: \"In den Labors können sich bis zu 50 Wissenschaftler aufhalten.  Die Labors sind mit den neuesten Technologien ausgestattet, um Forschungen im Bereich der Materialwissenschaft, Kosmologie und Biochemie durchzuführen.  Sie erhalten außerdem bevorzugten Zutritt zu den besten Labors der Welt, einschließlich militärischer Einrichtungen.\"\n  STR_WORKSHOP_UFOPEDIA: \"In den Werkstätten werden die in den Forschungslabors entwickelten Ausrüstungen hergestellt.  Bis zu 50 Ingenieure können sich dort gleichzeitig aufhalten, jedoch nimmt auch die Konstruktion der Gegenstände Platz in Anspruch.\"\n  STR_SMALL_RADAR_SYSTEM_UFOPEDIA: \"Ein kleines Radarsystem hat eine effektive Reichweite von 300 Seemeilen und ist für die Bodensuche an ein Satellitensystem gekoppelt. Jedes System kann mit einer Wahrscheinlichkeit von 10% alle 30 Minuten ein Objekt durchschnittlicher Größe entdecken.\"\n  STR_LARGE_RADAR_SYSTEM_UFOPEDIA: \"Ein großes Radarsystem hat eine effektive Reichweite von 450 Seemeilen und ist für die Bodensuche an ein Satellitensystem gekoppelt. Jedes System kann mit einer Wahrscheinlichkeit von 20% alle 30 Minuten ein Objekt durchschnittlicher Größe entdecken.\"\n  STR_MISSILE_DEFENSES_UFOPEDIA: \"Raketenabwehreinrichtungen bieten etwas Schutz vor gegnerischen Raumschiffen, die versuchen, in der Nähe des Stützpunktes zu landen.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"Die gesamte Ausrüstung, Waffensysteme, Munition, geborgene Gegenstände und SWT werden in Lagern aufbewahrt, inklusive dem Material, das einem Raumschiff zugeordnet ist.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"Lebende Außerirdische benötigen einen besonderen Lebensraum, um ihre Systeme auf der Erde zu erhalten.  In den abgeschlossenen Klimazellen ist Platz für bis zu 10 verschiedene Lebensformen.\"\n  STR_LASER_DEFENSES_UFOPEDIA: \"Die Laser-Abwehr bietet Schutz vor dem Eindringen gegnerischer Raumschiffe.\"\n  STR_PLASMA_DEFENSES_UFOPEDIA: \"Die Plasmastrahl-Abwehr bildet einen mächtigen und wirkungsvollen Schutz vor gegnerischen Raumschiffen.\"\n  STR_FUSION_BALL_DEFENSES_UFOPEDIA: \"Fusionsraketen bieten die effektivste Verteidigung gegen Angriffe der Außerirdischen. Sie erzeugen eine Antimaterie-Implosion, die alles in einem bestimmten Radius zerstört.\"\n  STR_GRAV_SHIELD_UFOPEDIA: \"Die Gravitationsschilde wehren so lange alle außerirdischen Raumschiffe ab, bis die Verteidigungssysteme wieder feuern können. Dadurch wird die Wirksamkeit der Verteidigungssysteme Ihres Stützpunktes praktisch verdoppelt.\"\n  STR_MIND_SHIELD_UFOPEDIA: \"Die Außerirdischen stellen die Anwesenheit von Menschen anhand von Gehirnströmen fest. Daher ist es sinnvoll, als Gegenmaßnahme Gehirnstromschilde um den Stützpunkt zu errichten. Damit wird die Gefahr der Entdeckung durch außerirdische Raumschiffe stark verringert.\"\n  STR_PSIONIC_LABORATORY_UFOPEDIA: \"Die Psi-Labors beurteilen das Psi-Potential aller Soldaten des Stützpunktes und ermöglichen die weitere Ausbildung dieser Fähigkeiten.  In jedem Labor können bis zu 10 Soldaten gleichzeitig trainiert werden.  Der Trainingsplan wird am Ende des Monats aufgestellt.  Psionische Fähigkeiten können im Kampf eingesetzt werden, wenn gleichzeitig ein Psi-Verstärker benutzt wird.\"\n  STR_HYPER_WAVE_DECODER_UFOPEDIA: \"Die Kommunikationssysteme der Außerirdischen nutzen supra-dimensionale Wellen, die sich sehr schnell ausbreiten. Dabei werden die Nachrichten von den UFOs aufgenommen und decodiert. Die Nachricht enthält außerdem Informationen über den Typ des UFOs, sein Volk und dessen Aktivitäten.\"\n  STR_HANGAR_UFOPEDIA: \"Jeder Hangar kann ein XCom-Raumschiff aufnehmen. Es gibt Einrichtungen für dessen Wartung, Reparatur und das Tanken. Jedes auf einem Stützpunkt stationierte Raumschiff muß einen freien Hangar haben, den kein anderes Raumschiff benutzen kann, selbst wenn dieses im Einsatz ist.\"\n  STR_PISTOL_UFOPEDIA: \"Die Standardwaffe der XCom ist eine halbautomatische Pistole mit einer Kapazität von 12 Schuss.\"\n  STR_RIFLE_UFOPEDIA: \"Dieses hochpräzise Scharfschützengewehr verfügt über ein lasergesteuertes Zielfernrohr und feuert 6,7-mm-Munition aus einem Magazin mit je 20 Schuss.\"\n  STR_HEAVY_CANNON_UFOPEDIA: \"Dieses schwerfällige Geschütz hat eine verheerende Wirkung.  Es ist vielseitig einsetzbar, denn es kann drei verschiedene Typen von Munition abfeuern: panzerbrechende und hochexplosive Munition sowie Brandsätze.\"\n  STR_AUTO_CANNON_UFOPEDIA: \"Das automatische Geschütz verbindet Vielseitigkeit und Stärke eines schweren Geschützes mit einer schnellen Feuerrate.\"\n  STR_ROCKET_LAUNCHER_UFOPEDIA: \"Der Raketenwerfer ist ein lasergelenktes System, das drei verschiedene Größen von Raketen abfeuern kann.\"\n  STR_LASER_PISTOL_UFOPEDIA: \"Die Laserpistole ist eine wirkungsvolle Waffe auf der Grundlage einer neuen Technologie.  Sie hat die Vorteile einer Pistole, ist jedoch schneller und genauer.\"\n  STR_LASER_RIFLE_UFOPEDIA: \"Das Lasergewehr ist eine stärkere und genauere Version des älteren Pistolendesigns.\"\n  STR_HEAVY_LASER_UFOPEDIA: \"Der schwere Laser ist unhandlich, doch äußerst wirkungsvoll.\"\n  STR_GRENADE_UFOPEDIA: \"Diese Standardgranate ist mit einem zuverlässigen und hochentwickelten Zeitzünder ausgestattet.\"\n  STR_SMOKE_GRENADE_UFOPEDIA: \"Rauchgranaten können willkommene Deckung in ungeschützten Kampfsituationen bieten.  Setzen Sie sie vorsichtig ein, denn sie bieten auch dem Gegner Schutz.\"\n  STR_PROXIMITY_GRENADE_UFOPEDIA: \"Eine Granate mit Annäherungszünder kann wie jede andere Granate geworfen werden.  Sie reagiert jedoch nach dem Auftreffen auf dem Boden ausschließlich auf Bewegungen.  Nutzen Sie diese Waffe geschickt und mit Vorsicht.\"\n  STR_HIGH_EXPLOSIVE_UFOPEDIA: \"Dieser Sprengstoff sollte nur für Abrißarbeiten eingesetzt werden. Halten Sie das Personal von der Einsatzstelle fern.\"\n  STR_MOTION_SCANNER_UFOPEDIA: \"Dieses moderne Gerät nutzt verschiedene Detektoren und Computeralgorithmen, um gegnerische Einheiten in Bewegung zu identifizieren. Es bedarf jedoch einiger Übung, um es richtig bedienen zu können. Klicken Sie das Bewegungsscanner-Icon auf der taktischen Anzeige an. Wählen Sie aus dem Menü die Option 'Scanner einsetzen'. In der Mitte der Scanner-Anzeige können Sie dann einen Pfeil in Blickrichtung des Soldaten sehen (Norden ist oben). Die blinkenden Punkte stellen Einheiten dar, die sich vor kurzem noch bewegt haben. Große oder sich schnell bewegende Einheiten sind durch größere Punkte dargestellt. Stationäre Einheiten werden nicht gezeigt.\"\n  STR_MEDI_KIT_UFOPEDIA: \"Die Sani-Tasche enthält Heil- und Schmerz- sowie Stimulansmittel. Um die Sani-Tasche nutzen zu können, müssen Sie in die Richtung blicken, in der sich der verwundete Soldat befindet. Ist der Soldat betäubt, dann müssen Sie sich über ihn stellen. Klicken Sie das Sani-Taschen-Icon an, und wählen Sie aus dem Menü die Option 'Sani-Tasche nutzen'.{NEWLINE}HEILEN> Rote Körperteile zeigen an, daß sie schwer verletzt sind. Klicken Sie den entsprechenden Körperteil und dann den Knopf 'Heilen' an. Damit wird eine tödliche Wunde geheilt und neue Gesundheit zugeführt.{NEWLINE}STIMULANS> Regeneriert Energie und belebt bewußtlose (betäubte) Soldaten. Um einen bewußtlosen Soldaten wiederzubeleben, müssen Sie sich direkt über ihn stellen.{NEWLINE}SCHMERZMITTEL> Erhöht die Moral verwundeter Soldaten bis zu einer Stufe, die dem alten Gesundheitsniveau entspricht.\"\n  STR_PSI_AMP_UFOPEDIA: \"Die Psi-Verstärker können nur von Soldaten mit Psi-Fähigkeiten verwendet werden. Klicken Sie während des kampfes auf den Psi-Verstärker, wählen Sie die Art des Angriffs und wählen Sie ein Ziel-Gerät mit dem Cursor. Es gibt zwei Arten von Psi-Angriffen:{NEWLINE}PANIK AUSLÖSEN> Wenn der Angriff erfolgreich ist, verringert sich die Moral des Ziels und es kann zur Panik kommen.{NEWLINE}GEDANKEN KONTROLLE> Wenn der Angriff erfolgreich ist, dann erhaltet Ihr sofort die Kontrolle über die feindliche Einheit, als ob sie eure eigene ist. Es ist sehr schwer, mit dieser Art von Angriff erfolgreich zu sein.\"\n  STR_STUN_ROD_UFOPEDIA: \"Dieses Gerät kann nur im Nahkampf eingesetzt werden.  Es betäubt lebende Organismen durch Elektroschocks, ohne sie zu töten.\"\n  STR_MIND_PROBE_UFOPEDIA: \"Die Gedankensonde ist ein Kommunikationsgerät der Außerirdischen, mit dem Informationen aus Gehirnströmen entnommen werden. XCom-Einheiten können sie im Kampf einsetzen, um die Merkmale eines Außerirdischen zu identifizieren. Klicken Sie erst die Gedankensonde, dann die Option 'Nutzen' und anschließend den Außerirdischen an.\"\n  STR_PLASMA_PISTOL_UFOPEDIA: \"Plasmapistolen sind tödliche Waffen der Außerirdischen, mit denen Teilchen aus einem winzigen Anti-Gravitationsfeld beschleunigt werden.\"\n  STR_PLASMA_RIFLE_UFOPEDIA: \"Plasmagewehre sind Waffen der Außerirdischen, deren verheerende Zerstörungskraft auf Teilchen beruht, die aus einem winzigen Anti-Gravitationsfeld beschleunigt werden.\"\n  STR_HEAVY_PLASMA_UFOPEDIA: \"Hierbei handelt es sich um eine vernichtend starke Waffe, mit welcher Teilchen aus einem winzigen Anti-Gravitationsfeld beschleunigt werden.\"\n  STR_BLASTER_LAUNCHER_UFOPEDIA: \"Dies ist ein gelenkter Raketenwerfer der Außerirdischen, der mächtige 'Blasterbomben' abfeuert. Wenn Sie die Waffe zum Abfeuern anklicken, werden für die Bombe 'Wegmarken' erstellt, denen sie folgen soll. Haben Sie genug Wegmarken gesetzt, dann klicken Sie das Spezial-Abschuss-Icon an.\"\n  STR_SMALL_LAUNCHER_UFOPEDIA: \"Eine kleine Abschussrampe, die Betäubungsbomben abfeuert.  Sehr nützlich, um Außerirdische lebend zu fangen.\"\n  STR_ALIEN_GRENADE_UFOPEDIA: \"Dieses Gerät funktioniert wie eine terrestrische Granate, es hat jedoch eine wesentlich stärkere Wirkung.\"\n  STR_SMALL_SCOUT: \"Kleiner Aufklärer\"\n  STR_MEDIUM_SCOUT: \"Mittlerer Aufklärer\"\n  STR_LARGE_SCOUT: \"Großer Aufklärer\"\n  STR_HARVESTER: \"Erntemaschine\"\n  STR_ABDUCTOR: \"Entführer\"\n  STR_TERROR_SHIP: \"Überfallraumschiff\"\n  STR_BATTLESHIP: \"Kampfraumschiff\"\n  STR_SUPPLY_SHIP: \"Versorgungsraumschiff\"\n  STR_RATING: \"BEWERTUNG> {0}\"\n  STR_RATING_TERRIBLE: \"MISERABEL!\"\n  STR_RATING_POOR: \"SCHLECHT!\"\n  STR_RATING_OK: \"OK\"\n  STR_RATING_GOOD: \"GUT!\"\n  STR_RATING_EXCELLENT: \"AUSGEZEICHNET!\"\n  STR_SCORE: \"PUNKTE\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"XCOM-PROJEKT-MONATSBERICHT\"\n  STR_MONTH: \"Monat> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"Der Rat der geldgebenden Nationen ist mit Ihrem bisherigen Fortschritt im Allgemeinen zufrieden.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"Der Rat der geldgebenden Nationen ist mit Ihrem bisherigen Fortschritt sehr zufrieden.  Machen Sie weiter so.\"\n  STR_COUNCIL_IS_DISSATISFIED: \"Der Rat der geldgebenden Nationen ist mit Ihrem bisherigen Fortschritt nicht zufrieden. Sie müssen effektiver handeln, um die Bedrohung durch die Außerirdischen abzuwenden, andernfalls wird das Projekt abgebrochen.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"Es ist Ihnen nicht gelungen, die Invasion der Außerirdischen abzuwenden. Der Rat der Geldgebenden Nationen hat leider entschieden, das Projekt abzubrechen. Jede Nation muß dieses Problem nun nach eigenem Ermessen lösen. Wir hoffen, daß wir mit diesen feindlich gesinnten Mächten auskommen und die Bevölkerung nicht unter der Invasion leiden muß.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} ist sehr zufrieden mit Ihren Fortschritten bei der Bekämpfung der außerirdischen Eindringlinge und hat eine Erhöhung der Gelder eingeleitet.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} ist besonders von Ihrer Fähigkeit beeindruckt, auf die Bedrohung vor Ort zu reagieren, und hat eine Erhöhung der Gelder geplant.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} und {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} ist unzufrieden mit Ihrer Fähigkeit, die außerirdischen Aktivitäten im Land zu unterbinden, und hat entschieden, die finanzielle Beteiligung zu reduzieren.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} sind unzufrieden mit Ihrer Fähigkeit, die außerirdischen Aktivitäten im Land zu unterbinden und haben entschieden, die finanzielle Beteiligung zu reduzieren.\"\n  STR_KNOTS: \"{0} Knoten\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} hat einen Geheimvertrag mit einer unbekannten außerirdischen Macht geschlossen und hat sich aus dem Projekt zurückgezogen.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} haben einen Geheimvertrag mit den Außerirdischen Invasoren geschlossen und haben sich aus dem Projekt zurückgezogen.\"\n  STR_MONTHLY_RATING: \"Monatswertung> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Finanzierungsänderung> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"Der Rat der Geldgeber ist nicht zufrieden mit Ihrer finanziellen Situation. Sie müssen Ihre Schulden unter $1 millionen bekommen oder das Projekt wird beendet.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"HYPERWELLEN-TRANSMISSIONEN WURDEN ENTSCHLÜSSELT\"\n  STR_CRAFT_TYPE: \"RAUMSCHIFFTYP\"\n  STR_RACE: \"VOLK\"\n  STR_MISSION: \"MISSION\"\n  STR_ZONE: \"ZONE\"\n  STR_ALLOCATE_RESEARCH: \"Forschung einleiten\"\n  STR_ALLOCATE_MANUFACTURE: \"Produktion einleiten\"\n  STR_NEW_YORK: \"New York\"\n  STR_WASHINGTON: \"Washington\"\n  STR_LOS_ANGELES: \"Los Angeles\"\n  STR_MONTREAL: \"Montreal\"\n  STR_HAVANA: \"Havanna\"\n  STR_MEXICO_CITY: \"Mexiko-Stadt\"\n  STR_CHICAGO: \"Chicago\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_DALLAS: \"Dallas\"\n  STR_BRASILIA: \"Brasilia\"\n  STR_BOGOTA: \"Bogota\"\n  STR_BUENOS_AIRES: \"Buenos Aires\"\n  STR_SANTIAGO: \"Santiago\"\n  STR_RIO_DE_JANEIRO: \"Rio de Janeiro\"\n  STR_LIMA: \"Lima\"\n  STR_CARACAS: \"Caracas\"\n  STR_LONDON: \"London\"\n  STR_PARIS: \"Paris\"\n  STR_BERLIN: \"Berlin\"\n  STR_MOSCOW: \"Moskau\"\n  STR_ROME: \"Rom\"\n  STR_MADRID: \"Madrid\"\n  STR_BUDAPEST: \"Budapest\"\n  STR_LAGOS: \"Lagos\"\n  STR_CAIRO: \"Kairo\"\n  STR_CASABLANCA: \"Casablanca\"\n  STR_PRETORIA: \"Pretoria\"\n  STR_NAIROBI: \"Nairobi\"\n  STR_CAPE_TOWN: \"Kapstadt\"\n  STR_KINSHASA: \"Kinshasa\"\n  STR_ANKARA: \"Ankara\"\n  STR_DELHI: \"Neu-Delhi\"\n  STR_KARACHI: \"Karachi\"\n  STR_BAGHDAD: \"Bagdad\"\n  STR_TEHRAN: \"Teheran\"\n  STR_BOMBAY: \"Mumbai\"\n  STR_CALCUTTA: \"Kalkutta\"\n  STR_TOKYO: \"Tokyo\"\n  STR_BEIJING: \"Peking\"\n  STR_BANGKOK: \"Bangkok\"\n  STR_MANILA: \"Manila\"\n  STR_SEOUL: \"Seoul\"\n  STR_SINGAPORE: \"Singapur\"\n  STR_JAKARTA: \"Jakarta\"\n  STR_SHANGHAI: \"Shanghai\"\n  STR_HONG_KONG: \"Hongkong\"\n  STR_NOVOSIBIRSK: \"Nowosibirsk\"\n  STR_CANBERRA: \"Canberra\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_MELBOURNE: \"Melbourne\"\n  STR_PERTH: \"Perth\"\n  STR_PSI_TRAINING: \"Psi Training\"\n  STR_PSIONIC_TRAINING: \"PSIONISCHES TRAINING\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Restkapazität Psi-Labore > {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"Psionische{NEWLINE}  Stärke\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"Psi-Fähigk. /{NEWLINE}Fortschritte\"\n  STR_PSI_AMP: \"Psi-Verstärker\"\n  STR_IN_TRAINING: \"  Im{NEWLINE}Training?\"\n  STR_TARGETTED_BY: \"IM VISIER VON:\"\n  STR_WEAPONS_CREW_HWPS: \"WAFFEN/{NEWLINE}CREW/SWTs\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"hat zu wenig Treibstoff,{NEWLINE}kehrt zum Stützpunkt zurück\"\n  STR_SOLDIER_LIST: \"Soldatenliste\"\n  STR_RANK_: \"RANG> {ALT}{0}\"\n  STR_MISSIONS: \"MISSIONEN> {ALT}{0}\"\n  STR_KILLS: \"ABSCHÜSSE> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"WUNDHEILUNG> {ALT}{0}\"\n  STR_TIME_UNITS: \"ZEITEINHEITEN\"\n  STR_STAMINA: \"ENERGIE\"\n  STR_HEALTH: \"GESUNDHEIT\"\n  STR_BRAVERY: \"MUT\"\n  STR_REACTIONS: \"REAKTION\"\n  STR_FIRING_ACCURACY: \"SCHUSSGENAUIGKEIT\"\n  STR_THROWING_ACCURACY: \"WURFGENAUIGKEIT\"\n  STR_STRENGTH: \"STÄRKE\"\n  STR_PSIONIC_STRENGTH: \"PSIONISCHE STÄRKE\"\n  STR_PSIONIC_SKILL: \"PSIONISCHE FÄHIGKEITEN\"\n  STR_NEW_RANK: \"NEUER RANG\"\n  STR_PROMOTIONS: \"Beförderungen\"\n  STR_SOLDIERS_UC: \"SOLDATEN\"\n  STR_TANK_CANNON_UFOPEDIA: \"Schwere Waffenträger (SWT) wurden entwickelt, um XCom-Einheiten zu unterstützen. Die Kombination aus hoher Feuerkraft und starker Panzerung macht diese zu wertvollen Kampfeinheiten im offenen Terrain. Vergewissern Sie sich, daß sich genügend Geschützmunition in Ihren Lagern befindet, um die Panzer neu zu bewaffnen. Dies geschieht automatisch, wenn sie einer Einsatztruppe zugeordnet werden.\"\n  STR_TANK_ROCKET_LAUNCHER_UFOPEDIA: \"Dieser automatisierte SWT ist mit mächtigen Raketen ausgestattet, die den Gegner vernichten sollen.  Vergewissern Sie sich, daß in den Lagern genügend SWT-Raketen vorrätig sind.\"\n  STR_TANK_LASER_CANNON_UFOPEDIA: \"Laserwaffen sind nützliche Ergänzungen für SWTs.  Sie besitzen eine starke Feuerkraft und uneingeschränkte Mengen Munition.\"\n  STR_HOVERTANK_PLASMA_UFOPEDIA: \"Dank der Außerirdischen-Technologie haben die SWTs eine neue Bedeutung erhalten. Die bessere Manövrierfähigkeit und die Stärke der Plasmastrahlen bilden eine tödliche Kombination.\"\n  STR_HOVERTANK_LAUNCHER_UFOPEDIA: \"Die Fusionskugel-Abschussrampe dieses Schwebepanzers verursacht starke Zerstörungen.  Setzen Sie sie sehr vorsichtig ein.  Sie müssen außerdem Fusionskugeln herstellen, um diese SWT bewaffnen zu können.  Eine Fusionskugel ist eine intelligente gelenkte Waffe.  Um sie abzufeuern, müssen Sie mehrere 'Wegmarken' mit dem Cursor auswählen und dann das Abschuss-Icon anklicken.\"\n  STR_HEAVY_PLASMA_CLIP_UFOPEDIA: \"Dieses kompakte Gerät wird als Munition für schwere Plasmageschütze verwendet.  Es enthält eine kleine Menge Elerium.\"\n  STR_PLASMA_RIFLE_CLIP_UFOPEDIA: \"Dieser kleine Gegenstand wird als Energiequelle für Plasmagewehre verwendet, eine Außerirdischenwaffe mittlerer Feuerkraft. Er enthält eine kleine Menge Elerium.\"\n  STR_PLASMA_PISTOL_CLIP_UFOPEDIA: \"Energiequelle für die kleine Plasmapistole der Außerirdischen. Enthält Elerium - die Energiequelle der Außerirdischen.\"\n  STR_STUN_BOMB_UFOPEDIA: \"Die Betäubungsbombe wird zum Fangen von Menschenexemplaren verwendet, kann jedoch auch gegen die meisten Außerirdischenvölker eingesetzt werden. Sie wird von einer kleinen Abschussrampe aus abgefeuert.\"\n  STR_ALIEN_RESEARCH_UFOPEDIA: \"Die Forschungsmission der Außerirdischen dient der Sammlung grundlegender Daten über die Erde und ihre Bewohner. Es werden vornehmlich kleine Raumschiffe eingesetzt, die gelegentlich in einsamen Gebieten landen. Diese Aktivitäten der Außerirdischen stellen nur geringe Gefahren für die XCom dar, und die Regierungen und Öffentlichkeit fühlen sich nicht bedroht.\"\n  STR_ALIEN_HARVEST_UFOPEDIA: \"Die Außerirdischen haben verschiedene Nutzungsmöglichkeiten für die Lebewesen der Erde. Tiere werden heimlich entführt und nach der Entnahme bestimmter Organe wieder zurückgebracht. Im Zusammenhang mit UFO-Entdeckungen hört man häufig Meldungen über verstümmelte Rinder. Diese Aktivitäten der Außerirdischen beunruhigen die Regierungen und die Öffentlichkeit in beträchtlichem Maße. Sie treten häufig in landwirtschaftlichen Gebieten auf. Eine Theorie vermutet, daß die Außerirdischen auf dem Planeten ursprünglich Fauna und Flora 'gesät' haben und nun zurückkehren, um die 'Ernte' einzufahren.\"\n  STR_ALIEN_ABDUCTION_UFOPEDIA: \"Dies ist die heimtückischste unter den Aktivitäten der Außerirdischen. Die Entführung von Menschen durch Außerirdische ist weit verbreitet. Trotz der Versuche, Details aus aus dem Gedächtnis der Opfer zu löschen, berichten die Entführten von demütigenden Untersuchungen ihrer Körper, einschließlich der Einpflanzung außerirdischer Föten und bizarrer genetischer Experimente. Zweck dieser Aktivitäten scheinen genetische Mutationen und die Manipulation des genetischen Materials der Außerirdischen selbst zu sein. Diese Aktivitäten verursachen große Beunruhigung und treten vor allem in bewohnten Gebieten oder Städten auf.\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"Es kann vorkommen, daß die Regierungen der Erde von den Agenten der Außerirdischen, die das Aussehen von Menschen angenommen haben, infiltriert werden. Dadurch kommen offizielle Kontakte in höchsten Regierungskreisen zustande. Den Höhepunkt dieser Aktivitäten bilden zahlreiche Erscheinungen von UFOs in der Nähe größerer Städte. Die Außerirdischen versuchen, Verträge mit den Regierungen abzuschließen, indem sie ihnen Erkenntnisse ihrer überlegenen Technologien anbieten. Als Gegenleistung soll die jeweilige Regierung den Außerirdischen gestatten, ihre Aktivitäten ungehindert auszuführen. Diese Missionen stellen die größte Bedrohung für die XCom dar. Stimmt eine Regierung einem Abkommen zu, dann wird sie der XCom keine finanziellen Mittel mehr zur Verfügung stellen.\"\n  STR_ALIEN_BASE_UFOPEDIA: \"Die Außerirdischen richten unterirdische Stützpunkte in abgelegenen Gegenden ein. Nach einigen Aufklärungsflügen häufen sich die UFO-Aktivitäten, während der Stützpunkt ausgebaut wird. Man weiß, daß es in diesen Stützpunkten Labors zur Untersuchung entführter Menschen und Versorgungsmittel für weitere Aktivitäten in der Umgebung gibt. Das Vorhandensein von Stützpunkten der Außerirdischen hat deren verstärkte Aktivität zur Folge, ohne daß dabei UFOs gesichtet werden. Um einen Stützpunkt überhaupt lokalisieren zu können, muß ein XCom-Raumschiff mehrere Stunden lang ein bestimmtes Gebiet patrouillieren.\"\n  STR_ALIEN_TERROR_UFOPEDIA: \"Die Außerirdischen setzen ihre furchtbaren Kräfte ein, wenn sie eine Stadt terrorisieren. Zivilisten werden direkt bedroht, und Regierungen werden gezwungen, ganze Gebiete zu räumen. Hauptzweck dieser Aktivitäten ist die Erzeugung einer Massenhysterie, damit die Regierungen von der Unterstützung des XCom-Projektes absehen.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"Gelingt es den Abfangjägern der XCom, viele UFOs abzuschießen, dann üben die Außerirdischen Vergeltung, indem sie zum Beispiel einen XCom-Stützpunkt direkt angreifen. Jedoch müssen die Außerirdischen einen solchen erst finden, und wenn die UFOs bei ihren Flügen abgefangen werden, ist die Gefahr eines Angriffs relativ gering.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"Haben die Außerirdischen einen Stützpunkt errichtet, dann wird er regelmäßig von speziellen Raumschiffen versorgt. Wird ein solches Raumschiff bei der Landung entdeckt, kann man sicher sein, daß sich in der Nähe des Landeplatzes ein Stützpunkt befindet.\"\n  STR_SMALL_SCOUT_UFOPEDIA: \"Dieses kleine Raumschiff wird vornehmlich für die Aufklärung oder Forschung eingesetzt.  Es kündigt normalerweise außerirdische Missionen mit größeren Schiffen an.\"\n  STR_MEDIUM_SCOUT_UFOPEDIA: \"Ein ungefährliches, mittelgroßes Aufklärungsschiff der Außerirdischen, das in Einsätzen vor den größeren Raumschiffen erscheint.\"\n  STR_LARGE_SCOUT_UFOPEDIA: \"Das größte Aufklärungsschiff der Außerirdischen ist ein Mehrzweckraumschiff. Die Außerirdischen setzen es bei allen Arten von Missionen ein.\"\n  STR_HARVESTER_UFOPEDIA: \"Die Erntemaschine hat eine Falltür im Unterteil ihres Rumpfes und ist mit einem Kran ausgerüstet, mit dem Rinder und anderes Vieh aufgenommen werden können.  Anschließend werden die gewünschten Körperteile mit Lasermessern herausgeschnitten und der Rest auf dem Boden zurückgelassen.  Die Organe werden in besonderen Behältern aufbewahrt.\"\n  STR_ABDUCTOR_UFOPEDIA: \"Dieses Raumschiff ist mit einem Forschungsraum für die Ausführung gräßlicher Experimente an Menschen ausgerüstet.  Dabei wird das Opfer mit Hilfe telepathischer Kräfte gelähmt, bleibt jedoch während der Operation bei Bewußtsein.\"\n  STR_TERROR_SHIP_UFOPEDIA: \"Das Überfallraumschiff hat einen Laderaum, in dem große Terrorwaffen oder außerirdische Terroristen aufgenommen und in bewohnte Gebiete transportiert werden können.\"\n  STR_BATTLESHIP_UFOPEDIA: \"Das Kampfschiff ist das größte und mächtigste Raumschiff der Außerirdischen.  Es ist das wichtigste Werkzeug ihrer Missionen, ausgerüstet mit gefährlichen Waffen sowie zahlreichen Besatzungsmitgliedern.\"\n  STR_SUPPLY_SHIP_UFOPEDIA: \"Das Versorgungsschiff wird beim Bau von Stützpunkten der Außerirdischen oder für die Versorgung bereits errichteter Stützpunkte eingesetzt. Es transportiert Lebensmittelbehälter und Reproduktionskammern.\"\n  STR_DISMANTLE: \"Demontieren\"\n  STR_FACILITY_IN_USE: \"EINRICHTUNG IN GEBRAUCH\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"KANN EINRICHTUNG NICHT DEMONTIEREN!{SMALLLINE}Alle Stützpunkteinrichtungen müssen mit dem Hauptaufzug verbunden sein.\"\n  STR_TRANSFER_ITEMS_TO: \"Gegenstände transportieren nach {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"KEINE KLIMAZELLE FÜR TRANSFER!{SMALLLINE}Lebende Außerirdische benötigen zum Überleben eine Klimazelle \"\n  STR_AMOUNT_AT_DESTINATION: \"MENGE AM{NEWLINE}ZIEL\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"Außerirdischer stirbt, da keine Außerirdischen-Klimazelle vorhanden ist.\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"KEINE FREIEN QUARTIERE!{SMALLLINE}Zielstützpunkt hat nicht genügend Quartiere für die dem Raumschiff zugewiesene Besatzung.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"NICHT GENUG LAGERKAPAZITÄT!{SMALLLINE}Der gewählte Stützpunkt hat nicht genug Lagerfläche für die sich in diesem Raumschiff befindende Ausrüstung.\"\n  STR_ITEMS_ARRIVING: \"Ankommende Gegenstände\"\n  STR_DESTINATION_UC: \"ZIEL\"\n  STR_PISTOL: \"Pistole\"\n  STR_PISTOL_CLIP: \"Pistolen-Magazin\"\n  STR_RIFLE: \"Gewehr\"\n  STR_RIFLE_CLIP: \"Gewehr-Magazin\"\n  STR_HEAVY_CANNON: \"Schweres Geschütz\"\n  STR_HC_AP_AMMO: \"SG-PB-Munition\"\n  STR_HC_HE_AMMO: \"SG-HE-Munition\"\n  STR_HC_I_AMMO: \"SG-B-Munition\"\n  STR_AUTO_CANNON: \"Autom. Geschütz\"\n  STR_AC_AP_AMMO: \"AG-PB-Munition\"\n  STR_AC_HE_AMMO: \"AG-HE-Munition\"\n  STR_AC_I_AMMO: \"AG-B-Munition\"\n  STR_ROCKET_LAUNCHER: \"Raketenwerfer\"\n  STR_SMALL_ROCKET: \"Kleine Rakete\"\n  STR_LARGE_ROCKET: \"Große Rakete\"\n  STR_INCENDIARY_ROCKET: \"Brandrakete\"\n  STR_GRENADE: \"Granate\"\n  STR_SMOKE_GRENADE: \"Rauchgranate\"\n  STR_PROXIMITY_GRENADE: \"Granate mit Annäherungszünder\"\n  STR_HIGH_EXPLOSIVE: \"Brisanz-Sprengstoff\"\n  STR_STUN_ROD: \"Betäubungsstab\"\n  STR_HEAVY_PLASMA: \"Schweres Plasmagewehr\"\n  STR_HEAVY_PLASMA_CLIP: \"Schweres Plasmagewehr-Magazin\"\n  STR_PLASMA_RIFLE: \"Plasmagewehr\"\n  STR_PLASMA_RIFLE_CLIP: \"Plasmagewehr-Magazin\"\n  STR_PLASMA_PISTOL: \"Plasmapistole\"\n  STR_PLASMA_PISTOL_CLIP: \"Plasmapistolen-Magazin\"\n  STR_BLASTER_LAUNCHER: \"Blaster-Abschussrampe\"\n  STR_BLASTER_BOMB: \"Blaster-Bombe\"\n  STR_SMALL_LAUNCHER: \"Kleine Abschussrampe\"\n  STR_STUN_BOMB: \"Betäubungsbombe\"\n  STR_ALIEN_GRENADE: \"Außerirdischen-Granate\"\n  STR_ELERIUM_115: \"Elerium-115\"\n  STR_MIND_PROBE: \"Gedankensonde\"\n  STR_SECTOID_CORPSE: \"Toter Sektoid\"\n  STR_SNAKEMAN_CORPSE: \"Toter Schlangenmensch\"\n  STR_ETHEREAL_CORPSE: \"Toter Ätherer\"\n  STR_MUTON_CORPSE: \"Toter Mutone\"\n  STR_FLOATER_CORPSE: \"Toter Schweber\"\n  STR_CELATID_CORPSE: \"Toter Celatid\"\n  STR_SILACOID_CORPSE: \"Toter Silakoid\"\n  STR_CHRYSSALID_CORPSE: \"Toter Chryssalid\"\n  STR_REAPER_CORPSE: \"Toter Schnitter\"\n  STR_SECTOPOD_CORPSE: \"Sektopod Wrack\"\n  STR_CYBERDISC_CORPSE: \"Cyberdisc Wrack\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"Nicht genug Munition zum Ausrüsten der SWT vorhanden{SMALLLINE}Jede SWT benötigt {0} {1}.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Nicht genügend Ausrüstung für die Truppe\"\n  STR_MARS_CYDONIA_LANDING: \"Mars: Cydonia-Landung\"\n  STR_MARS_CYDONIA_LANDING_BRIEFING: \"Ihr Avenger-Raumschiff ist auf dem Mars in der Region Cydonia gelandet.  Informationen zufolge befindet sich in einer der Pyramiden ein grüner Aufzug, über den man in den unterirdischen Komplex gelangen kann.  Sobald Sie alle Soldaten in der Nähe des Aufzugs gesammelt haben, klicken Sie das Icon 'Mission abbrechen' an, um zur nächsten Stufe weiterzugehen.\"\n  STR_MARS_THE_FINAL_ASSAULT: \"Mars: Der endgültige Überfall\"\n  STR_MARS_THE_FINAL_ASSAULT_BRIEFING: \"Der Aufzug bringt Ihre kampfmüden Soldaten tief unter die Planetenoberfläche in das Zentrum eines großen Komplexes aus Tunneln und Kammern. Das Gehirn der Außerirdischen ist irgendwo in diesem Labyrinth versteckt. Es muß vernichtet werden, um die Erde vor der Sklaverei durch die Außerirdischen zu bewahren.{NEWLINE}{NEWLINE}Viel Glück! \"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Zur Nutzung oder Produktion von{NEWLINE}{1}{NEWLINE}müssen Sie folgendes erforschen{NEWLINE}{0}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"Die Außerirdischen haben den wehrlosen Stützpunkt {0} zerstört.\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"XCom-Agenten haben einen Stützpunkt der Außerirdischen in {0} entdeckt.\"\n  STR_STANDOFF: \"ABSTAND HALTEN\"\n  STR_CAUTIOUS_ATTACK: \"FERNANGRIFF\"\n  STR_STANDARD_ATTACK: \"STANDARDANGRIFF\"\n  STR_AGGRESSIVE_ATTACK: \"AGGRESSIVER ANGRIFF\"\n  STR_DISENGAGING: \"ABBRUCH\"\n  STR_UFO_HIT: \"UFO GETROFFEN!\"\n  STR_UFO_CRASH_LANDS: \"UFO ABGESTÜRZT!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Verkleinerung nur bei Fernangriff\"\n  STR_UFO_RETURN_FIRE: \"UFO ERWIDERT FEUER!\"\n  STR_INTERCEPTOR_DAMAGED: \">>> ABFANGJÄGER BESCHÄDIGT <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> ABFANGJÄGER ZERSTÖRT <<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"UFO ENTKOMMT!\"\n  STR_ALIENS_TERRORISE: \"TERRORANGRIFF DER AUSSERIRDISCHEN {NEWLINE}\"\n  STR_LONG_RANGE_DETECTION: \"Langstrecken-Radar\"\n  STR_STORES_UC: \"LAGER\"\n  STR_DIFFICULTY_LEVEL: \"Schwierigkeitsgrad\"\n  STR_INTERCEPT: \"ABFANGEN\"\n  STR_BASES: \"STÜTZPUNKTE\"\n  STR_GRAPHS: \"DIAGRAMME\"\n  STR_UFOPAEDIA_UC: \"UFOPEDIA\"\n  STR_OPTIONS_UC: \"OPTIONEN\"\n  STR_FUNDING_UC: \"GELDER\"\n  STR_5_SECONDS: \"5 Sek.\"\n  STR_1_MINUTE: \"1 Min.\"\n  STR_5_MINUTES: \"5 Min.\"\n  STR_30_MINUTES: \"30 Min.\"\n  STR_1_HOUR: \"1 Std.\"\n  STR_1_DAY: \"1 Tag\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"XCom-Bewertungsliste\"\n  STR_ENTER_NAME: \"Namen eingeben\"\n  STR_PERFORMANCE_RATING: \"Leistungsbewertung\"\n  STR_VICTORY_DATE: \"Datum des Sieges\"\n  STR_ELECTRO_FLARE: \"E-Leuchtkörper\"\n  STR_ELECTRO_FLARE_UFOPEDIA: \"Dieses Gerät erzeugt einen hellen Lichtschein, wenn es geworfen wird.  Damit können in der Dunkelheit gegnerische Einheiten sichtbar gemacht werden.\"\n  STR_MONTHLY_COSTS: \"Kosten pro Monat\"\n  STR_CRAFT_RENTAL: \"Raumschiff-Mietgebühren\"\n  STR_SALARIES: \"Gehälter\"\n  STR_BASE_MAINTENANCE: \"Stützpunkt-Erhaltungskosten\"\n  STR_COST_PER_UNIT: \"Kosten pro Einheit\"\n  STR_QUANTITY: \" Menge\"\n  STR_TOTAL: \"Gesamt\"\n  STR_IN_PSIONIC_TRAINING: \"Im psionischen Training\"\n  STR_BLASTER_BOMB_UFOPEDIA: \"Hierbei handelt es sich um eine hochexplosive Rakete mit einem intelligenten Lenksystem.  Sie wird mit Hilfe einer Blaster-Vorrichtung abgeschossen.\"\n  STR_FRONT_ARMOR: \"RÜSTUNG VORN\"\n  STR_LEFT_ARMOR: \"RÜSTUNG LINKS\"\n  STR_RIGHT_ARMOR: \"RÜSTUNG RECHTS\"\n  STR_REAR_ARMOR: \"RÜSTUNG HINTEN\"\n  STR_UNDER_ARMOR: \"RÜSTUNG UNTEN\"\n  STR_ROUNDS: \"Schüsse\"\n  STR_UNIT: \"EINHEIT> {0}\"\n  STR_ENERGY: \"ENERGIE\"\n  STR_MORALE: \"MORAL\"\n  STR_ARMOR_: \"RÜSTUNG> {0}\"\n  STR_FRONT_ARMOR_UC: \"RÜSTUNG VORN\"\n  STR_LEFT_ARMOR_UC: \"RÜSTUNG LINKS\"\n  STR_RIGHT_ARMOR_UC: \"RÜSTUNG RECHTS\"\n  STR_REAR_ARMOR_UC: \"RÜSTUNG HINTEN\"\n  STR_SKILLS: \"FÄHIGKEITEN> {0}\"\n  STR_LEVEL: \"Schwierigkeitsgrad> {0}\"\n  STR_HEAD: \"KOPF\"\n  STR_TORSO: \"RUMPF\"\n  STR_RIGHT_ARM: \"RECHTER ARM\"\n  STR_LEFT_ARM: \"LINKER ARM\"\n  STR_RIGHT_LEG: \"RECHTES BEIN\"\n  STR_LEFT_LEG: \"LINKES BEIN\"\n  STR_PAIN_KILLER: \"SCHMERZMITTEL\"\n  STR_STIMULANT: \"STIMULANS\"\n  STR_HEAL: \"HEILEN\"\n  STR_TIME_UNITS_SHORT: \"ZE>{ALT}{0}\"\n  STR_WEIGHT: \"Gewicht>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"Reakt.>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"P.Fäh.>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"P.Stä.>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Außerirdisches Artefakt\"\n  STR_AMMO_ROUNDS_LEFT: \"MUNITION:{NEWLINE}VERBLEIBENDE{NEWLINE}SCHÜSSE={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Schmerz>{ALT}{0}{ALT}{NEWLINE}Stimulans>{ALT}{1}{ALT}{NEWLINE}Heilung>{ALT}{2}\"\n  STR_THROW: \"Werfen\"\n  STR_AUTO_SHOT: \"Auto-Schuss\"\n  STR_SNAP_SHOT: \"Schnellschuss\"\n  STR_AIMED_SHOT: \"Zielschuss\"\n  STR_STUN: \"Treffer\"\n  STR_PRIME_GRENADE: \"Granate scharf machen\"\n  STR_USE_SCANNER: \"Scanner einsetzen\"\n  STR_USE_MEDI_KIT: \"Sani-Tasche benutzen\"\n  STR_LAUNCH_MISSILE: \"Rakete feuern\"\n  STR_ACCURACY_SHORT: \"SG>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Nicht genug Zeiteinheiten!\"\n  STR_NOT_ENOUGH_ENERGY: \"Nicht genug Energie!\"\n  STR_NO_ROUNDS_LEFT: \"Nicht genug Munition!\"\n  STR_NO_AMMUNITION_LOADED: \"Keine Munition geladen!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Falsche Munition für diese Waffe!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"Waffe ist bereits geladen!\"\n  STR_NO_LINE_OF_FIRE: \"Keine Schusslinie!\"\n  STR_GRENADE_IS_ACTIVATED: \"Granate ist aktiviert!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Granate ist deaktiviert!\"\n  STR_THERE_IS_NO_ONE_THERE: \"Dort ist niemand!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Artefakt muß erst untersucht werden!\"\n  STR_OUT_OF_RANGE: \"Außer Reichweite!\"\n  STR_UNABLE_TO_THROW_HERE: \"Kann hier nicht werfen!\"\n  STR_SET_TIMER: \"Zeit einstellen\"\n  STR_HIDDEN_MOVEMENT: \"VERSTECKTE BEWEGUNG\"\n  STR_TURN: \"RUNDE> {0}\"\n  STR_SIDE: \"SEITE> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Zum Fortfahren Knopf drücken\"\n  STR_MIND_CONTROL: \"Gedankenkontrolle\"\n  STR_PANIC_UNIT: \"Einheit in Panik stürzen\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Moral Angriff erfolgreich\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Gedankenkontrolle erfolgreich\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}hat einen Tobsuchtsanfall\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}hat einen Tobsuchtsanfall\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}ist in Panik ausgebrochen\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}ist in Panik ausgebrochen\"\n  STR_XCOM: \"XCom\"\n  STR_ALIENS: \"Außerirdische\"\n  STR_RIGHT_HAND: \"RECHTE HAND\"\n  STR_LEFT_HAND: \"LINKE HAND\"\n  STR_RIGHT_SHOULDER: \"RECHTE SCHULTER\"\n  STR_LEFT_SHOULDER: \"LINKE SCHULTER\"\n  STR_BACK_PACK: \"RUCKSACK\"\n  STR_BELT: \"GÜRTEL\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}wird von den Außerirdischen kontrolliert\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}wird von den Außerirdischen kontrolliert\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}ist bewusstlos\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}ist bewusstlos\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}Ist an einer Verletzung gestorben\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}ist an ihren Verletzungen gestorben\"\n  STR_USE_MIND_PROBE: \"Gedankensonde einsetzen\"\n  STR_FATAL_WOUNDS: \"TÖDLICHE WUNDEN\"\n  STR_UNDER_ARMOR_UC: \"RÜSTUNG UNTEN\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Zeiteinheiten sind für Schnellschuss reserviert\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Zeiteinheiten sind für Auto-Schuss reserviert\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Zeiteinheiten sind für Zielschuss reserviert\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Zeiteinheiten sind zum Aufstehen/Hinknien reserviert\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"Zeiteinheiten sind zum Hinknien und Feuern reserviert\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} Einheit im Ausgangsbereich\"\n    other: \"{N} Einheiten im Ausgangsbereich\"\n  STR_UNITS_OUTSIDE:\n    one: \"{N} Einheit außerhalb des Ausgangsbereichs\"\n    other: \"{N} Einheiten außerhalb des Ausgangsbereichs\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} Einheit im Eingang\"\n    other: \"{N} Einheiten im Eingang\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} Einheit im Zielausgang\"\n    other: \"{N} Einheiten im Zielausgang\"\n  STR_ABORT_MISSION_QUESTION: \"Mission abbrechen?\"\n  STR_CORPSE: \"Toter\"\n  STR_UNLOAD_CRAFT: \"Entladen\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}wurde getötet\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}wurde getötet\"\n  STR_HIT_MELEE: \"Treffer\"\n  STR_GROUND: \"BODEN\"\n  STR_LIVING_QUARTERS_PLURAL: \"Quartiere\"\n  STR_LIST_ITEM: \"GEGENSTAND\"\n  STR_PERSONAL_ARMOR_UFOPEDIA: \"Mit der Alien Legierung und der daraus neu hervorgekommen Rüstung, haben unsere Männer eine größere Chance gegen die außerirdische Bedrohung.\"\n  STR_POWER_SUIT_UFOPEDIA: \"Ein neuer wirksamer Schutz für Soldaten. Diese Rüstung wird mit Elerium betrieben und verbessert die Geschwindigkeit und die Stärke des Trägers. Derzeit der beste Schutz für Soldaten.\"\n  STR_FLYING_SUIT_UFOPEDIA: \"Der verbesserte Energieanzug, wurde mit der Anti-Schwerkraft-Technologie ausgerüstet um völlige Bewegungsfreiheit auf dem Schlachtfeld zu ermöglichen.\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"Alle Außerirdischen wurden durch den Absturz getötet,{NEWLINE}Automatische Bergung eingeleitet\"\n  STR_RESET: \"Zurücksetzen\"\n  STR_MEMORIAL: \"Gedenkstätte\"\n  STR_DATE_UC: \"DATUM\"\n  STR_SOLDIERS_RECRUITED_UC: \"REKRUTIERTE SOLDATEN>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"GEFALLENE SOLDATEN>{ALT}{0}\"\n  MAP_CULTA: \"Bauernhof\"\n  MAP_FOREST: \"Wald\"\n  MAP_JUNGLE: \"Dschungel\"\n  MAP_MOUNT: \"Berg\"\n  MAP_DESERT: \"Wüste\"\n  MAP_POLAR: \"Arktis\"\n  MAP_URBAN: \"Stadt\"\n  MAP_UBASE: \"Alien Basis\"\n  MAP_XBASE: \"XCom Basis\"\n  MAP_MARS: \"Mars\"\n  STR_MIXED: \"Gemischt\"\n  STR_REMOVE_SELECTED: \"Ausgewählte entfernen\"\n  STR_LIVE_ALIENS: \"Lebende{NEWLINE}Exemplare\"\n  STR_DEAD_ALIENS: \"Exemplare{NEWLINE}Abgelehnt\"\n  STR_UNDER_INTERROGATION: \"Derzeit{NEWLINE}Untersucht.\"\n  STR_CONTAINMENT_EXCEEDED: \"KAPAZITÄT DER AUßERIRDISCHEN-KLIMAZELLE ÜBERSCHRITTEN!{SMALLLINE}Nicht genug Platz in der Klimazelle von {0}. Du musst überzählige Ausserirdische aus der Klimazelle entfernen (diese werden sterben).\"\n  STR_MANAGE_CONTAINMENT: \"Außerirdischen-Klimazelle verwalten\"\n  STR_STORAGE_EXCEEDED: \"LAGERKAPAZITÄT ÜBERSCHRITTEN!{SMALLLINE}Nicht genügend Lagerfläche in {0}. Sie müssen überschüssige Gegenstände verkaufen.\"\n  STR_GO_TO_BASE: \"Geh zur Basis\"\n  STR_MELEE_ACCURACY: \"NAHKAMPFGENAUIGKEIT\"\n  STR_SELL_PRODUCTION: \"VERKAUFEN\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Beide Hände müssen frei sein!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Nicht genug Ausrüstung um Vorlage zu kopieren!\"\n  STR_UNLOAD_WEAPON: \"Waffe entladen\"\n  STR_ALL_ITEMS: \"Alle Artikel\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"KEINE WEITERE AUSRÜSTUNG AN BORD ERLAUBT!{SMALLLINE}Sie dürfen höchstens {N} Ausrüstungsgegenstände auf eine Mission mitnehmen.\"\n    other: \"KEINE WEITERE AUSRÜSTUNG AN BORD ERLAUBT!{SMALLLINE}Sie dürfen höchstens {N} Ausrüstungsgegenstände auf eine Mission mitnehmen.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}KOMMANDOZENTRUM ZERSTÖRT {NEWLINE} Begeben Sie sich zum Eingang um abzubrechen.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"XCom-Anlagen können nicht unter Wasser gebaut werden\"\n  STR_LEVEL_SHORT: \"{0}\"\n  STR_PERSONNEL: \"Personal\"\n  STR_CRAFT_ARMAMENT: \"Raumschiffe & Bewaffnung\"\n  STR_COMPONENTS: \"Bauteile\"\n  STR_SOLDIERS_RECRUITED: \"Rekrutierte Soldaten\"\n  STR_SOLDIERS_LOST: \"Gefallene Soldaten\"\n  STR_TOTAL_UFOS: \"Entdeckte UFOs\"\n  STR_TOTAL_ALIEN_BASES: \"Entdeckte außerirdische Basen\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"PST\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"PFÄ\"\n  FEMALE_CIVILIAN: \"Zivilistin, Weiblich\"\n  MALE_CIVILIAN: \"Zivilist, Männlich\"\n  CYBERDISC_WEAPON: \"Cyberdisc-Waffe\"\n  REAPER_WEAPON: \"Schnitter-Waffe\"\n  CHRYSSALID_WEAPON: \"Chryssalid-Waffe\"\n  CELATID_WEAPON: \"Celatid-Waffe\"\n  SILACOID_WEAPON: \"Silakoid-Waffe\"\n  SECTOPOD_WEAPON: \"Sektopod-Waffe\"\n  ZOMBIE_WEAPON: \"Zombie-Waffe\"\n  ALIEN_PSI_WEAPON: \"Außerirdischen-Psi-Waffe\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/el.yml",
    "content": "el:\n  STR_AVENGER_UFOPEDIA: \"ΜΕΤΑΓΩΓΙΚΟ ΚΑΙ ΜΑΧΗΤΙΚΟ ΔΙΑΣΤΗΜΟΠΛΟΙΟ. Η ΑΠΟΛΥΤΗ ΑΝΑΠΑΡΑΓΩΓΗ ΕΞΩΓΗΙΝΗΣ ΤΕΧΝΟΛΟΓΙΑΣ.\"\n  STR_INTERCEPTOR_UFOPEDIA: \"ΠΟΛΕΜΙΚΟ ΑΕΡΟΣΚΑΦΟΣ ΜΕ ΔΥΟ ΜΗΧΑΝΕΣ ΠΑΛΜΙΚΗΣ ΕΚΠΥΡΣΟΚΡΟΤΗΣΗΣ ΚΑΙ ΕΙΔΙΚΑ ΘΩΡΑΚΙΣΜΕΝΑ ΗΛΕΚΤΡΟΝΙΚΑ ΣΥΣΤΗΜΑΤΑ. ΟΤΙ ΚΑΛΥΤΕΡΟ ΕΧΕΙ ΝΑ ΠΡΟΣΦΕΡΕΙ Η ΓΗΙΝΗ ΤΕΧΝΟΛΟΓΙΑ.\"\n  STR_LIGHTNING_UFOPEDIA: \"ΜΕΤΑΦΟΡΙΚΟ ΚΑΙ ΜΑΧΗΤΙΚΟ ΑΕΡΟΣΚΑΦΟΣ. ΜΙΑ ΑΤΕΧΝΗ ΑΛΛΑ ΑΠΟΤΕΛΕΣΜΑΤΙΚΗ ΠΡΟΣΟΜΟΙΩΣΗ ΤΟΥ ΕΞΩΓΗΙΝΟΥ ΣΥΣΤΗΜΑΤΩΣ ΠΡΟΩΘΗΣΗΣ.\"\n  STR_SKYRANGER_UFOPEDIA: \"ΜΕΤΑΓΩΓΙΚΟ ΑΕΡΟΣΚΑΦΟΣ. ΤΟ ΤΑΧΥΤΕΡΟ ΤΟΥ ΕΙΔΟΥΣ ΤΟΥ, ΜΕ ΙΚΑΝΟΤΗΤΑ ΚΑΘΕΤΗΣ ΠΡΟΣΓΕΙΩΣΗΣ ΚΑΙ ΑΠΟΓΕΙΩΣΗΣ (V.T.O.L.).\"\n  STR_FIRESTORM_UFOPEDIA: \"ΜΑΧΗΤΙΚΟ ΑΕΡΟΣΚΑΦΟΣ. ΑΥΤΟΣ Ο ΜΟΝΟΘΕΣΙΟΣ ΠΟΛΕΜΙΣΤΗΣ ΑΠΟΤΕΛΕΙ ΤΟ ΚΛΑΣΙΚΟ ΣΧΕΔΙΟ ΑΤΙΑ, ΜΕ ΚΕΝΤΡΙΚΗ ΜΟΝΑΔΑ ΠΡΟΩΘΗΣΗΣ.\"\n  STR_STINGRAY_UFOPEDIA: \"ΕΞΕΛIΓΜΕΝΟΣ ΠΥΡΑΥΛΟΣ ΑΕΡΟΣ-ΑΕΡΟΣ ΜΕ ΕΙΔΙΚΑ ΘΩΡΑΚΙΣΜΕΝΑ  ΗΛΕΚΤΡΟΝΙΚΑ.\"\n  STR_AVALANCHE_UFOPEDIA: \"ΠΥΡΑΥΛΟΣ ΑΕΡΟΣ-ΑΕΡΟΣ ΜΕ ΠΥΡΗΝΙΚΗ ΚΕΦΑΛΗ, ΑΛΛΑ ΜΕ ΕΞΑΙΡΕΤΙΚΑ ΒΑΡΥ ΦΟΡΤΙΟ.\"\n  STR_CANNON_UFOPEDIA: \"ΠΥΡΒΟΛΟ ΥΨΗΛΗΣ ΙΣΧΥΣ ΠΟΥ ΧΡΗΣΙΜΟΠΙΟΙ ΔΙΑΤΡΙΤΙΚΑ ΒΛΗΜΑΤΑ ΜΕ ΙΚΑΝΟΤΙΤΑ ΔΙΕΙΣΔΥΣΕΙΣ 16 ΙΝΤΣΕΣ ΑΤΣΑΛΙ.\"\n  STR_FUSION_BALL_UFOPEDIA: \"ΑΥΤΟΣ Ο ΠΡΟΩΘΗΤΗΣ ΕΚΤΟΞΕΥΕΙ ΠΥΡΑΥΛΟ ΣΕ ΣΧΗΜΑ ΜΠΑΛΑΣ ΠΟΥ ΤΡΟΦΟΔΟΤΕΙΤΕ ΑΠΟ ΑΝΤΙΔΡΑΣΗ ΤΗΣ ΑΝΤΙ-ΥΛΗΣ. Η ΜΠΑΛΑ ΚΑΤΑΣΤΡΕΦΕΙ ΤΟΝ ΣΤΟΧΟ ΜΕ ΕΚΡΗΞΗ ΒΑΡΥΤΙΚΟΥ ΚΥΜΑΤΟΣ.\"\n  STR_LASER_CANNON_UFOPEDIA: \"ΑΥΤΗ Η ΣΥΜΒΑΤΙΚΗ ΑΚΤΙΝΑ ΛΕΪΖΕΡ ΤΡΟΦΟΔΟΤΕΙΤΑΙ ΑΠΟ ΕΝΑΝ ΑΝΤΙΔΡΑΣΤΗΡΑ ΑΝΤΙ-ΥΛΗΣ.\"\n  STR_PLASMA_BEAM_UFOPEDIA: \"Η ΑΚΤΙΝΑ ΒΑΡΥΤΗΤΑΣ ΚΑΤΕΥΘΥΝΕΙ ΑΠΕΙΡΟΕΛΑΧΙΣΤΑ ΕΝΑ ΣΥΝΘΛΙΒΟΜΕΝΟ ΠΡΟΣ ΤΑ ΜΕΣΑ ΒΑΡΥΤΙΚΟ ΠΕΔΙΟ.\"\n  STR_SECTOID_UFOPEDIA: \"Η Sectoid ιεραρχία κυμαίνεται από στρατιώτες σε ηγέτες με ισχυρές psionic ικανότητες. Αυτές psionic δυνάμεις μπορεί να χρησιμοποιηθεί για κατάρρευση του ηθικού στρατιωτών στη μάχη, ή ακόμη και πάρουν τον έλεγχο του μυαλού τους. Έχουν την τάση να απολαύσουν απαγωγές ανθρώπων και ακρωτηριασμό ζώων. Η απαγωγή χρησιμοποιείται για να εξάγει το γενετικό υλικό για διασταυρούμενη αναπαραγωγή και την ανάπτυξη κλώνων για διεισδύοντας ανθρώπινη κοινωνία. Τα βοοειδή παρέχουν τόσο τη διατροφή και το γενετικό υλικό. Αυτή η αγώνα φαίνεται να θέλουν να αναπτύξουν την ανώτερη γενετική υβρίδια να αυξηθεί η αποτελεσματικότητα της κυψέλης-όπως και η κοινωνία τους.\"\n  STR_SECTOID_AUTOPSY: \"Αυτοψία Σεκτοειδή\"\n  STR_SECTOID_AUTOPSY_UFOPEDIA: \"Η αυτοψία αποκαλύπτει υπολείμματα πεπτικών οργάνων και μια απλή δομή. Ο εγκέφαλος και τα μάτια είναι πολύ καλά αναπτυγμένα. Η δομή υποδηλώνει γενετική τροποποίηση ή μετάλλαξη. Το μικρό στόμα και η μύτη φαίνεται να έχουν ελάχιστη λειτουργία. Ο ιστός ανάμεσα στα δάχτυλα και η πλατυποδία υποδηλώνουν υδρόβια προέλευση. Δεν υπάρχουν αναπαραγωγικά όργανα και δεν υπάρχουν ενδείξεις για το πώς αυτό το είδος μπορεί να αναπαραχθεί. Πιθανότατα είναι ένα είδος γενετικά τροποποιημένο.\"\n  STR_SNAKEMAN_UFOPEDIA: \"Η φυλή αυτή αναπτύχθηκε σε ένα εξαιρετικά εχθρικό περιβάλλον. Είναι εξαιρετικά ανθεκτικά και μπορούν να αντέχουν σε ακραίες διακυμάνσεις θερμοκρασίας. Η κινητικότητά τους εξαρτάται από ένα γιγάντιο «πόδι» που μοιάζει με φίδι το οποίο προστατεύει όλα τα ζωτικά όργανα. Οι στόχοι τους φαίνεται να είναι καθαρά αρπακτικοί και φαίνεται να βρίσκονται υπό τις διαταγές κάποιας άλλης νοημοσύνης που κατευθύνει τις στρατιωτικού τύπου επιδρομές τους στη γη.\"\n  STR_SNAKEMAN_AUTOPSY: \"Αυτοψία Φιδάνθρωπου\"\n  STR_SNAKEMAN_AUTOPSY_UFOPEDIA: \"Το δέρμα είναι εξαιρετικά σκληρό και ανθεκτικό στη θερμότητα. Το καρδιαγγειακό σύστημα είναι μέρος του μυϊκού συστήματος που χρησιμοποιεί την υδραυλική αρχή για να δημιουργήσει κίνηση. Ο μόνος αληθινός μυς είναι η «καρδιά». Το αναπαραγωγικό σύστημα φαίνεται να είναι πολύ αποτελεσματικό. Η αναπαραγωγή είναι ασεξουαλική, με κάθε φιδάνθρωπο να μεταφέρει έως και πενήντα αυγά μέσα στο σώμα του ανά πάσα στιγμή. Αν αφεθεί στην τύχη του αυτό το είδος θα αποτελούσε σοβαρή απειλή για τη ζωή στη γη.\"\n  STR_ETHEREAL_UFOPEDIA: \"Αυτό το ον έχει τρομερές νοητικές δυνάμεις που επιτρέπουν τηλεπαθητική επικοινωνία και τηλεκινητικές ικανότητες. Οι φαινομενικά αδύναμες φυσικές ικανότητες αυτού του πλάσματος συντηρούνται από τις νοητικές του δυνάμεις. Δεν καταλαβαίνουμε πώς λειτουργούν αυτές οι τηλεκινητικές δυνάμεις, αφού φαίνεται να αψηφούν τους νόμους της φυσικής όπως τους γνωρίζουμε. Είναι εξαιρετικά επικίνδυνοι σε οποιαδήποτε κατάσταση μάχης, όπου βασίζονται στις ψυχικές τους δυνάμεις για τη μάχη. Σπάνια εμφανίζονται στη γη αφού φαίνεται να βασίζονται σε άλλες φυλές για την επιδίωξη των στόχων τους.\"\n  STR_ETHEREAL_AUTOPSY: \"Αυτοψία Αιθέριου\"\n  STR_ETHEREAL_AUTOPSY_UFOPEDIA: \"Αυτό το ον είναι σωματικά καθυστερημένο και φαίνεται ανίκανο να διατηρήσει οποιεσδήποτε λειτουργίες ζωής. Οι μύες είναι σοβαρά ατροφημένοι και τα εσωτερικά όργανα φαίνεται ότι δεν έχουν αναπτυχθεί. Τα αισθητήρια όργανα, συμπεριλαμβανομένων των ματιών, φαίνεται ότι δεν λειτουργούν καθόλου. Ο εγκέφαλος, ωστόσο, είναι καλά ανεπτυγμένος και αντλεί μεγάλο ποσοστό της παροχής αίματος του σώματος. Είναι ένα μυστήριο για το πώς αυτό το πλάσμα μπορεί να συντηρηθεί χωρίς εξωτερική υποστήριξη.\"\n  STR_MUTON_UFOPEDIA: \"Αυτό το ανθρωπόμορφο πλάσμα είναι σωματικά ισχυρό και έξυπνο. Έχουν ιδιαίτερη όρεξη να καταναλώνουν ωμή σάρκα οποιασδήποτε μορφής, την οποία χρειάζονται για διατροφή, όπως τα σαρκοφάγα στη γή. Φαίνεται να βασίζονται σε τηλεπαθητικές εντολές από μια φυλή που είναι γνωστή ως «Αιθέριοι». Μόλις διαχωριστούν από αυτόν τον τηλεπαθητικό σύνδεσμο, το νοητικό τους σύστημα φαίνεται να καταρρέει και πεθαίνουν. Τα αυτοματοποιημένα τεχνητά εμφυτεύματα χρησιμοποιούνται για να βελτιώσουν τις πολεμικές τους επιδόσεις. Προφανώς είναι οι στρατιώτες μίας ανώτερης ευφυίας.\"\n  STR_MUTON_AUTOPSY: \"Αυτοψία Μάτον\"\n  STR_MUTON_AUTOPSY_UFOPEDIA: \"Το 'δέρμα' αυτού του πλάσματος φαίνεται να είναι μια οργανικά κατασκευαζόμενη προστατευτική πανοπλία η οποία μεταμοσχεύεται στο σώμα. Υπάρχουν πολλά κυβερνητικά εμφυτεύματα τα οποία χρησιμοποιούνται για να βελτιώσουν την λειτουργία του καρδιαγγειακού συστήματος και των αισθήσεων. Τα αναπαραγωγικά όργανα φαίνονται να έχουν αφαιρεθεί χειρουργικά. Προφανώς αυτά τα ατυχή πλάσματα περιορίζονται σε μια ζωή πολέμου και κατάκτησης. Οι διατρητικές σφαίρες δεν είναι αποτελεσματικές ενάντια στο σκληρό δέρμα τους.\"\n  STR_CELATID_UFOPEDIA: \"Αυτή η μορφή ζωής έχει τη μυστηριώδη φυσική ικανότητα να επιπλέει στον αέρα. Φαίνεται να ανιχνεύει ανθρώπινα εγκεφαλικά κύματα και θα κινηθεί προς έναν ανθρώπινο στόχο ακόμα κι αν είναι καλά κρυμμένος. Μόλις εντοπιστεί ένας στόχος, οι Κελατίδες προσγειώνονται και εκτοξεύουν μικρά σφαιρίδια με εξαιρετικά διαβρωτικό δηλητήριο. Το πλάσμα έχει την ικανότητα να κλωνοποιεί τον εαυτό του με ανησυχητικό ρυθμό. Συνοδεύει τη φυλή Μάτον στις περιπλανήσεις της.\"\n  STR_CELATID_AUTOPSY: \"Αυτοψία Κελατίδας\"\n  STR_CELATID_AUTOPSY_UFOPEDIA: \"Ο πυρήνας περιέχει μια μικρή βιομηχανική συσκευή, η οποία φαίνεται να αναπτύχθηκε μεσω ενος συστήματος αντιβαρύτητας. Ο σάκος του δηλητηρίου είναι το μεγαλύτερο όργανο και δεν φαίνεται να είναι μια ξεχωριστή δομή του εγκεφάλου. Δεν υπάρχει σαφής πεπτικό ή αναπαραγωγικό σύστημα. Ένα μικρό όργανο περιέχει έμβρυα που μπορούν να αναπτυχθούν γρήγορα σε ένα νέο ον.\"\n  STR_SILACOID_UFOPEDIA: \"Αυτή η μορφή ζωής βασίζεται στην σιλικόνη, και παράγει τεράστια ποσά θερμότητας. Έχει την ισχύ να συνθλίψει βράχους, τους οποίους και καταναλώνει στο καυτό εσωτερικό του. Έχει μόνο βασική νοημοσύνη και ελέγχεται μέσω εμφυτευμάτων ή τηλεπαθητικών όντων. Συνεργάζεται με τους Μάτονς.\"\n  STR_SILACOID_AUTOPSY: \"Αυτοψία Σίλακοϊντ\"\n  STR_SILACOID_AUTOPSY_UFOPEDIA: \"Τα σωθικά του πλάσματος είναι εξαιρετικά καυτά, και φαίνεται να είναι η βάση για το πεπτικό του σύστημα. Το μοναδικό σύστημα μυών του έχει τεράστια δύναμη και ταχύτητα. Το δέρμα του δεν βλάπτεται από τη φωτιά ή εμπρηστικά πυρομαχικά.\"\n  STR_CHRYSSALID_UFOPEDIA: \"Τα καβούρια είναι ένα ισχυρό όπλο σε στενή μάχη. Ο υψηλός μεταβολισμός και η δύναμη αυτού του πλάσματος του δίνουν  ταχύτητα και επιδεξιότητα. Αντί να σκοτώσει το θύμα του, το εμποτίζει με ένα αυγό και εγχέει ένα δηλητήριο που το μετατρέπει σε ένα ζόμπι. Μια νέα Χρυσαλιδα θα σκάσει από το θύμα λίγο μετά τον εμποτισμό. Οι Χρυσαλιδες συνδέονται με τον αγώνα Snakeman.\"\n  STR_CHRYSSALID_AUTOPSY: \"Αυτοψία Χρυσαλλίδας\"\n  STR_CHRYSSALID_AUTOPSY_UFOPEDIA: \"Ο σκελετος από αυτό το πλάσμα είναι εξαιρετικά σκληρός, αλλά εκπληκτικά ευάλωτος σε εκρηκτικά πυρομαχικά. Ο εγκέφαλος έχει αναπτυχθεί καλά, και ο ρυθμός ανάπτυξης του κυττάρου του πολύ γρήγορα. Το πλάσμα μεταφέρει είκοσι αυγά που τοποθετούνται μέσα σε άλλους οργανισμούς. Αυτό το πλάσμα είναι ένα πολύ αποτελεσματικό όπλο τρομοκρατίας.\"\n  STR_FLOATER_UFOPEDIA: \"Οι Αιωρητές είναι κυρίως στρατιώτες και πράκτορες τρομοκρατίας. Είναι από φυσικού αρπακτικά όντα, γενετικά και κυβερνητικά ενισχυμένα ώστε να είναι τρομεροί πολεμιστές. Το κάτω μισό του σώματος τους και τα πιο εσωτερικά όργανα είναι χειρουργικά αφαιρεμένα, και ένα σύστημα υποστήριξης ζωής είναι εγκατεστημένο. Αυτό το εμφύτευμα περιέχει μία μονάδα αντιβαρύτητας η οποία επιτρέπει στο πλάσμα να επιπλέει, έστω και ασταθώς, στον αέρα.\"\n  STR_FLOATER_AUTOPSY: \"Αυτοψία Αιωρητή\"\n  STR_FLOATER_AUTOPSY_UFOPEDIA: \"Το πλάσμα έχει αλλάξει δραστικά με χειρουργική επέμβαση. Η διάταξη η οποία φαίνεται να σχηματίζει τον πυρήνα του σώματος είναι ένα σύστημα υποστήριξης της ζωής και αναλαμβάνει την λειτουργία της καρδιάς, των πνευμόνων και του πεπτικού συστήματος. Αυτό θα επιτρέψει στο πλάσμα να επιβιώσει σε εξαιρετικά εχθρικό περιβάλλον. Ο εγκέφαλος είναι μικρότερος από τον δικό μας, αλλά τα αισθητήρια όργανα έχουν αναπτυχθεί καλά.\"\n  STR_REAPER_UFOPEDIA: \"Αυτό το δίποδο σαρκοφάγο έχει ισχυρά σαγόνια και μια ακόρεστη όρεξη. Έχει μια σειρά από εγκεφαλικά εμφυτεύματα που χρησιμοποιούνται για να ελέγχουν τις δραστηριότητες του. Τα πρωτόγονα ένστικτα αρπακτικού του πλάσματος έχουν μικρή χρησιμότητα εκτός από το να τρομοκρατήσουν και να καταστρέψουν. Οι Θεριστές είναι συνήθως μαζί με Αιωρητές.\"\n  STR_REAPER_AUTOPSY: \"Αυτοψία Θεριστή\"\n  STR_REAPER_AUTOPSY_UFOPEDIA: \"Ο Θεριστής περιέχει δύο 'εγκέφαλους' και δύο 'καρδιές', τα οποία του επιτρέπουν να λειτουργεί ακόμα και όταν είναι βαριά τραυματισμένος. Ωστόσο το γούνινο δέρμα του είναι εξαιρετικά εύφλεκτο, καθιστώντας το πλάσμα ευάλωτο σε εμπρηστικά όπλα.\"\n  STR_SECTOPOD_UFOPEDIA: \"Τα Sectopods είναι πλάσματα ρομπότ με ισχυρό όπλο ακτίνα λέιζερ. Ο έλεγχος αυτών των μηχανικών θηρίων είναι μέσω τηλεπαθητικής σύνδεσης με τους ελεγκτές του, τα Ethereals. Τα Sectopods είναι το πιο ισχυρό στη διάθεση των ξένων δυνάμεων όπλο τρομοκρατίας.\"\n  STR_SECTOPOD_AUTOPSY: \"Αυτοψία Sectopod\"\n  STR_SECTOPOD_AUTOPSY_UFOPEDIA: \"Το ρομπότ είναι γερά κατασκευασμένο με μηχανοκίνητη πανοπλία σε θέση να αντέχει τις περισσότερες μορφές επίθεσεων, ιδίως όπλα πλάσματος. Ωστόσο, το κύκλωμα αίσθησης φαίνεται να είναι ιδιαίτερα ευάλωτο στα όπλα λέιζερ.\"\n  STR_CYBERDISC_UFOPEDIA: \"Αυτή η μικρογραφία ιπτάμενου δίσκου είναι ένα αυτοματοποιημένο όπλο τρομοκρατίας οπλισμένο με ένα ισχυρό δέσμης πλάσματος. Η προώθηση της αντι-βαρύτητας του δίνει ένα μεγάλο πλεονέκτημα σε δύσκολα εδάφη. Η κύρια λειτουργία του είναι η καταστροφή και ο τρόμος στην υπηρεσία της Sectoid φυλής.\"\n  STR_CYBERDISC_AUTOPSY: \"Αυτοψία Κυβερνοδίσκου\"\n  STR_CYBERDISC_AUTOPSY_UFOPEDIA: \"Το Cyberdisc είναι καλά θωρακισμένο και είναι ιδιαίτερα καλό στο να αντέχει εκρηκτικά πυρομαχικά. Το πρωτεύον σύστημα αντι-βαρύτητας είναι πολύ κατεστραμμένο για να κερδίσει οποιοδήποτε κατανόηση της λειτουργίας του.\"\n  STR_UFO_POWER_SOURCE_UFOPEDIA: \"The power source of alien craft is an anti-matter reactor which uses Elerium (element 115) to generate powerful gravity waves as well as other forms of energy.  The conversion of matter to energy is an incredible 99% efficient, therefore tiny quantities of Elerium can produce a huge amount of power.  This unit can be reproduced easily using alien alloys.\"\n  STR_UFO_NAVIGATION_UFOPEDIA: \"Τα εξωγήινα σκάφη χρησιμοποιούν εξελιγμένους υπολογιστές για τη πλοήγηση τους στη Γη καθώς και στο διάστημα. Το σύστημα βασίζεται σε οπτικούς επεξεργαστές κατανεμημένους σε δίκτυο. Ο χειρισμός τους είναι απλοϊκός - ο πλοηγός χειρίζεται τη κατεύθυνση των κυμάτων βαρύτητας από τη πηγή ενέργειας για να κατευθύνει το σκάφος σε οποιαδήποτε κατεύθυνση. Το σύστημα αυτό μπορεί εύκολα να χρησιμοποιηθεί από ανθρώπους, και μπορεί να ανακατασκευαστεί χρησιμοποιώντας εξωγήινα μέταλλα και άλλα εξαρτήματα.\"\n  STR_UFO_CONSTRUCTION_UFOPEDIA: \"Εξωγήινο σκάφος αποτελείται από τρία κύρια συστατικά - μια πηγή ενέργειας, ένα σύστημα πλοήγησης και ένα σκάφος που χτίστηκε από ξένα κράματα. Η γάστρα έχει σχεδιαστεί ειδικά για να επιτρέψει κύματα βαρύτητας να κατευθύνεται και να ελέγχεται. Επιπλέον, μία μικρή ποσότητα Elerium απαιτείται για να τροφοδοτήσει την πηγή τροφοδοσίας. Από τη στιγμή που οι αρχές κατασκευής κατανοητές, και οι λειτουργίες του κάθε συστατικού είναι γνωστές, τότε είναι δυνατή η οικοδόμηση αυτού του είδους των σκαφών.\"\n  STR_ALIEN_FOOD_UFOPEDIA: \"Αυτοί οι θάλαμοι περιέχουν διάφορα ένζυμα που χρησιμοποιούνται για την πέψη των τμημάτων του σώματος των βοοειδών, άλλα ζώα και ακόμη και ανθρώπους. Το υγρό στη συνέχεια καταναλώνεται ως έτοιμη πέψη των τροφίμων - πιθανώς απευθείας στην κυκλοφορία του αίματος. Αυτό υποδηλώνει μια ορισμένη εξάρτηση στη γη για τρόφιμα - μια συμβίωση μεταξύ της Γης και ξένης κοινωνίας.\"\n  STR_ALIEN_REPRODUCTION_UFOPEDIA: \"Αυτοί οι θάλαμοι περιέχουν ξένα έμβρυα. Ο σχεδιασμός αυτών των δοχείων φαίνεται να προκύπτει ότι οι εξωγήινοι που χρησιμοποιούν αυτή τη διαδικασία έχουν πλήρη εμπιστοσύνη στην εργαστηριακή αναπαραγωγή. Τα πλούσια θρεπτικά συστατικά εξασφαλίζουν την ταχεία ανάπτυξη του εμβρύου. Αυτό το σύστημα της γραμμής εργοστασίου θα μπορούσε να παράγει χιλιάδες των ξένων κλώνων σε ένα σύντομο χρονικό διάστημα. Η διαδικασία θα μπορούσε εύκολα να προσαρμοστεί για την ανθρώπινη αναπαραγωγή, ή ξένα ανθρώπινα υβρίδια.\"\n  STR_ALIEN_ENTERTAINMENT_UFOPEDIA: \"Η πιο πιθανή λειτουργία αυτών των σφαιρών είναι ψυχαγωγίας. Το psionic κύκλωμα διεγείρει διάφορα κέντρα του εγκεφάλου. Τα αποτέλεσμα είναι παρόμοιο με παραισθησιογόνα ναρκωτικά. Αυτή είναι η μόνη απόδειξη ότι οι εξωγήινοι έχουν κάποιες πολιτιστικές και ψυχαγωγικές ενασχολήσεις.\"\n  STR_ALIEN_SURGERY_UFOPEDIA: \"Αυτος ο χειρουργικος εξοπλισμός χρησιμοποιεί κόφτες λέιζερ για την εξαγωγή ορισμένων τμημάτων του σώματος από βοοειδή και άλλα ζώα. Οι ακρωτηριασμοί διαδεδομένων βοοειδών μπορουν να εξηγηθουν από αυτή την περίεργη εξωγήινη δραστηριότητα. Είναι πιθανό ότι αυτά τα μέρη χρησιμοποιούνται για θρεπτικούς ή γενετικους σκοπούς.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"Στο παρελθόν, πολλές χιλιάδες άνθρωποι έχουν υποστηρίξει ότι είχαν απαχθεί από εξωγήινους, μερικές φορές κατ 'επανάληψη. Η αλήθεια είναι πολύ πιο τρομακτική. Άνθρωποι απαγάγονται, ερευνώνται και να παρακολουθούνται. Το γενετικό υλικό από τα καλύτερα δείγματα εξάγεται. Ανθρώπινα-εξωγήινα υβριδικά έμβρυα εμφυτεύονται σε γυναίκες, και στη συνέχεια αφαιρούνται αρκετούς μήνες αργότερα. Ποιος ξέρει τι απαίσιο κίνητρα έχουν οι εξωγήινοι;\"\n  STR_ALIEN_ALLOYS_UFOPEDIA: \"Τα εξωγήινα αεροσκάφη κατασκευάζονται από ειδικά κράματα με μοναδικές ιδιότητες. Είναι πολύ ελαφριά και ανθεκτικά, και μπορούν να φορμαριστούν με ηλεκτρομαγνητικές μεθόδους. Αυτό το υλικό μπορεί να ανακατασκευαστεί και να χρησιμοποιηθεί σε πολλά είδη παρασκευαστικών διαδικασιών.\"\n  STR_ELERIUM_115_UFOPEDIA: \"Το στοιχείο αυτό έχει την ασυνήθιστη ιδιότητα της παραγωγής ηλεκτρικής ενέργειας αντι-ύλης, όταν βομβαρδίζεται με ορισμένα σωματίδια. Αυτό δημιουργεί κύματα βαρύτητας και άλλες μορφές ενέργειας. Δεν βρίσκεται φυσικά στο ηλιακό μας σύστημα και δεν μπορεί να αναπαραχθεί.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"Είναι σαφές ότι αγωνιζόμαστε για μια χαμένη μάχη στη γη. Οι ξένες ορδές είναι συντριπτικες σε αριθμό. Το καλύτερο που μπορούμε να κάνουμε είναι να επιβραδύνουμε την πρόοδό τους. Η μόνη ελπίδα για την ανθρωπότητα είναι η αντιμετώπιση των εξωγήινων στην πηγή τους. Η έρευνά μας φαίνεται να δείχνει ένα κοντινό ορμητήριο μέσα στο ηλιακό μας σύστημα. Μεταναστες δείχνουν ότι ο τόπος είναι το κέντρο του αρχαίου πολιτισμού ανθρώπινης ιστορίας. Πρέπει να εντοπίσετε αυτό το μέρος, το συντομότερο δυνατόν. Ωστόσο, θα πρέπει να συλλάβετε και να ανακρίνετε έναν εξωγήινο ηγέτη για να αποκτήσετε πιο λεπτομερείς πληροφορίες. Τα μεγαλύτερα UFO ίσως περιέχουν τουλάχιστον έναν ξένο ηγέτη.\"\n  STR_THE_MARTIAN_SOLUTION_UFOPEDIA: \"Η έρευνά μας τώρα δείχνει τον Άρη ως τη βάση των εξωγήινων επιχειρήσεων. Η βάση είναι καλά κρυμμένη και περιέχει όλες τις εγκαταστάσεις κατασκευής και κλωνοποίησης για την τροφοδοσία της διείσδυσης της γης. Φαίνεται επίσης να περιέχει κάποιου είδους υπολογιστή ελέγχου που ελέγχει ολόκληρη τη επιχείρηση. Φαίνεται ότι η κοινωνία των εξωγήινων μοιάζει πολύ με κυψέλη μελισσών, έχει κάποιο είδος «βασίλισσας μέλισσας». Αυτή είναι η θεμελιώδης αδυναμία τους - αν καταφέρουμε να εξαλείψουμε τον «εγκέφαλο», τότε το σώμα θα πεθάνει. Πρέπει να εντείνουμε τις ερευνητικές μας προσπάθειες πριν να είναι πολύ αργά. Για να προοδεύσουμε πρέπει να συλλάβουμε τους υψηλότερους εξωγήινους -τους διοικητές- που βρίσκουμε μόνο σε βάσεις και μεγάλα διαστημόπλοια εξωγήινων.\"\n  STR_CYDONIA_OR_BUST_UFOPEDIA: \"Είναι πλέον σαφές ότι οι αλλοδαπες ορδές ελέγχονται από μια υπόγεια βάση στην Κυδωνία - η οποία είναι μια ασυνήθιστη περιοχή του Άρη με πέντε όψεων πυραμίδες και ένα μεγάλο σχηματισμό που μοιάζει με ανθρώπινο πρόσωπο. Ο Κυδωνικος πολιτισμός άνθιζε κάποτε στον Άρη πολλά εκατομμύρια χρόνια πριν, αλλά δεν ξέρουμε γιατί πέθανε, ή ποια είναι η σύνδεση είναι με την τελευταία ξένη δραστηριότητα εκεί. Όποια και αν είναι η εξήγηση πρέπει να στείλουμε μια αποστολή στην Κυδωνία. Αυτός είναι ο μόνος τρόπος που μπορούμε να νικήσουμε τους εξωγήινους. Θα πρέπει να καταστρέψουμε τον εγκεφάλο». Θα χρειαστούμε ένα σκάφος Avenger εξοπλισμένο με την πιο τρομερή καταστρεπτική δύναμη που διαθέτουμε. Δεν υπάρχει τίποτα περισσότερο που μπορούμε να μάθουμε εδώ - πρέπει να περιμένουμε το αποτέλεσμα της επίθεσης.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"ΚΕΝΤΡΑΡΕ ΣΤΗΝ ΤΟΠΟΘΕΣΙΑ - ΧΡΟΝΟΣ = 5 Δευτ.\"\n  STR_CANCEL_UC: \"ΑΚΥΡΟ\"\n  STR_NONE: \"Τίποτα\"\n  STR_UNKNOWN: \"Άγνωστο\"\n  STR_POOR: \"Φτωχά\"\n  STR_AVERAGE: \"Μέσος\"\n  STR_GOOD: \"Καλά\"\n  STR_EXCELLENT: \"Άριστα\"\n  STR_BUILD_NEW_BASE_UC: \"ΧΤΙΣΕ ΝΕΑ ΒΑΣΗ\"\n  STR_BASE_INFORMATION: \"ΠΛΗΡΟΦΟΡΙΕΣ ΒΑΣΗΣ\"\n  STR_EQUIP_CRAFT: \"ΕΞΟΠΛΙΣΜΟΣ ΣΚΑΦΩΝ\"\n  STR_BUILD_FACILITIES: \"ΚΑΤΑΣΚΕΥΗ ΕΓΚΑΤΑΣΤΑΣΕΩΝ\"\n  STR_RESEARCH: \"ΕΡΕΥΝΑ\"\n  STR_MANUFACTURE: \"ΠΑΡΑΓΩΓΗ\"\n  STR_TRANSFER_UC: \"ΜΕΤΑΦΟΡΑ\"\n  STR_PURCHASE_RECRUIT: \"ΑΓΟΡΑ/ΠΡΟΣΛΗΨΗ\"\n  STR_SACK: \"ΑΠΟΛΥΣΕ\"\n  STR_SELL_SACK_UC: \"ΠΩΛΗΣΗ/ΑΠΟΛΥΣΗ\"\n  STR_GEOSCAPE_UC: \"ΓΕΩΣΚΟΠΙΟ\"\n  STR_NAME: \"Όνομα\"\n  STR_AREA: \"Περιοχή\"\n  STR_BUILD_NEW_BASE: \"Χτίσε Νέα Βάση\"\n  STR_CANCEL: \"Άκυρο\"\n  STR_COST_UC: \"ΚΟΣΤΟΣ>\"\n  STR_CONSTRUCTION_TIME_UC: \"ΧΡΟΝΟΣ ΚΑΤΑΣΚΕΥΗΣ>\"\n  STR_DAY:\n    one: \"{N} μέρα\"\n    other: \"{N} μέρες\"\n  STR_HOUR:\n    one: \"{N} ώρα\"\n    other: \"{N} ώρες\"\n  STR_MAINTENANCE_UC: \"ΣΥΝΤΗΡΗΣΗ>\"\n  STR_OK: \"ΟΚ\"\n  STR_INSTALLATION: \"ΕΓΚΑΤΑΣΤΑΣΕΙΣ\"\n  STR_CURRENT_RESEARCH: \"ΤΡΕΧΟΥΣΑ ΕΡΕΥΝΑ\"\n  STR_SCIENTISTS_AVAILABLE: \"Διαθέσιμοι Επιστήμονες>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Κατανεμημένοι Επιστήμονες>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Ελεύθερος Χώρος Εργαστηρίου>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"ΕΡΕΥΝΗΤΙΚΟ ΠΡΟΓΡΑΜΜΑ\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"ΚΑΤΑΝΕΜΗΜΕΝΟΙ ΕΠΙΣΤΗΜΟΝΕΣ\"\n  STR_PROGRESS: \"ΠΡΟΟΔΟΣ\"\n  STR_NEW_PROJECT: \"Νέο Πρόγραμμα\"\n  STR_CANCEL_PROJECT: \"ΑΚΥΡΩΣΗ ΕΡΓΟΥ\"\n  STR_NEW_RESEARCH_PROJECTS: \"ΝΕΑ ΕΡΕΥΝΗΤΙΚΑ ΠΡΟΓΡΑΜΜΑΤΑ\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"ΔΙΑΘΕΣΙΜΟΙ ΕΠΙΣΤΗΜΟΝΕΣ>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"ΕΛΕΥΘΕΡΟΣ ΧΩΡΟΣ ΕΡΓΑΣΤΗΡΙΟΥ>{ALT}{0}\"\n  STR_INCREASE: \"Αύξησε\"\n  STR_DECREASE: \"Μείωσε\"\n  STR_START_PROJECT: \"ΕΝΑΡΞΗ\"\n  STR_CURRENT_PRODUCTION: \"ΤΡΕΧΟΥΣΑ ΠΑΡΑΓΩΓΗ\"\n  STR_ENGINEERS_AVAILABLE: \"Διαθέσιμοι Μηχανικοί>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Κατανεμημένοι Μηχανικοί>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Ελεύθερος χώρος>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Τρέχοντα Κονδύλια>{ALT}{0}\"\n  STR_ITEM: \"ΑΝΤΙΚΕΙΜΕΝΟ\"\n  STR_ENGINEERS__ALLOCATED: \"Μηχανικοί\"\n  STR_UNITS_PRODUCED: \"Παραγμένες Μονάδες\"\n  STR_TOTAL_TO_PRODUCE: \"Σύνολο Παραγωγής\"\n  STR_COST__PER__UNIT: \"Κόστος{NEWLINE}ανά{NEWLINE}Μονάδα\"\n  STR_DAYS_HOURS_LEFT: \"Υπόλοιπες Μέρες/Ώρες\"\n  STR_NEW_PRODUCTION: \"Νέα Παραγωγή\"\n  STR_PRODUCTION_ITEMS: \"Αντικείμενα Παραγωγής\"\n  STR_CATEGORY: \"ΚΑΤΗΓΟΡΙΑ\"\n  STR_START_PRODUCTION: \"ΕΝΑΡΞΗ ΠΑΡΑΓΩΓΗΣ\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} Εργατοώρες για την παραγωγή μίας μονάδας\"\n  STR_COST_PER_UNIT_: \"Κόστος ανά μονάδα>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Απαιτούμενος Χώρος>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"ΑΠΑΙΤΟΥΝΤΑΙ ΕΙΔΙΚΑ ΥΛΙΚΑ\"\n  STR_ITEM_REQUIRED: \"ΑΠΑΙΤΟΥΜΕΝΑ ΑΝΤΙΚΕΙΜΕΝΑ\"\n  STR_UNITS_REQUIRED: \"ΑΠΑΙΤΟΥΜΕΝΕΣ ΜΟΝΑΔΕΣ\"\n  STR_UNITS_AVAILABLE: \"ΔΙΑΘΕΣΙΜΕΣ ΜΟΝΑΔΕΣ\"\n  STR_STOP_PRODUCTION: \"ΤΕΛΟΣ ΠΑΡΑΓΩΓΗΣ\"\n  STR_ENGINEERS_AVAILABLE_UC: \"ΔΙΑΘΕΣΙΜΟΙ ΜΗΧΑΝΙΚΟΙ>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"ΕΛΕΥΘΕΡΟΣ ΧΩΡΟΣ ΜΗΧΑΝΟΥΡΓΕΙΟΥ>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"ΜΗΝΙΑΙΟ ΚΕΡΔΟΣ>{ALT}{0}\"\n  STR_INCREASE_UC: \"ΑΥΞΗΣΕ\"\n  STR_DECREASE_UC: \"ΜΕΙΩΣΕ\"\n  STR_UNITS_TO_PRODUCE: \"Μονάδες να Παραχθούν\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"ΑΓΟΡΕΣ/ΠΡΟΣΛΗΨΕΙΣ ΠΡΟΣΩΠΙΚΟΥ\"\n  STR_COST_OF_PURCHASES: \"Κόστος Αγορών>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"ΚΟΣΤΟΣ ΑΝΑ ΜΟΝΑΔΑ\"\n  STR_QUANTITY_UC: \"ΠΟΣΟΤΗΤΑ\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"ΔΙΑΘΕΣΙΜΟ ΠΡΟΣΩΠΙΚΟ:ΣΥΝΟΛΙΚΟ ΠΡΟΣΩΠΙΚΟ>\"\n  STR_SOLDIERS: \"Στρατιώτες\"\n  STR_SCIENTISTS: \"Επιστήμονες\"\n  STR_ENGINEERS: \"Μηχανικοί\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"ΧΡΗΣΙΜΟΠΟΙΟΥΜΕΝΟΣ ΧΩΡΟΣ:ΕΛΕΥΘΕΡΟΣ ΧΩΡΟΣ>\"\n  STR_LIVING_QUARTERS: \"Κοιτώνες\"\n  STR_STORES: \"Αποθήκες\"\n  STR_LABORATORIES: \"Εργαστήρια\"\n  STR_WORK_SHOPS: \"Μηχανουργεία\"\n  STR_HANGARS: \"Υπόστεγα\"\n  STR_SHORT_RANGE_DETECTION: \"Ανίχνευση Μικρής Εμβ.\"\n  STR_DEFENSE_STRENGTH: \"Αμυντική Δύναμη\"\n  STR_TRANSFERS_UC: \"ΜΕΤΑΦΟΡΕΣ\"\n  STR_TRANSFERS: \"Μεταφορές\"\n  STR_ARRIVAL_TIME_HOURS: \"ΩΡΑ ΑΦΙΞΗΣ (hours)\"\n  STR_COST_: \"Κόστος>{ALT}{0}\"\n  STR_AREA_: \"Περιοχή>{ALT}{0}\"\n  STR_BASE_NAME: \"Όνομα Βάσης;\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"ΕΠΕΛΕΞΕ ΘΕΣΗ ΑΝΕΛΚΥΣΤΗΡΑ ΠΡΟΣΒΑΣΗΣ\"\n  STR_TRANSFER: \"Μεταφορά\"\n  STR_AMOUNT_TO_TRANSFER: \"ΠΟΣΟΤΗΤΑ ΜΕΤΑΦΟΡΑΣ\"\n  STR_SELECT_DESTINATION_BASE: \"Επέλεξε Βάση Προορισμού\"\n  STR_COST: \"Κόστος\"\n  STR_VICTORY_1: \"Καθώς εισέρχεστε στο δωμάτιο βλέπετε έναν εξωγήινο εγκέφαλο, τον αντικειμενικό σκοπό της εκστρατείας! Πριν όμως πυροβολήσετε, επικοινωνεί μαζί σας μέσω μιας οθόνης στην βάση του. Σας καλεί να αφουγκραστείτε τα επιχειρήματα του για επιβίωση, πριν πάρετε την απόφαση να τραβήξετε την σκανδάλη...\"\n  STR_VICTORY_2: \"Ο εγκέφαλος μιλάει και λέει:' Πολλά εκατομμύρια χρόνια πριν, ο πλανήτης ο οποίος εσείς αποκαλείτε Άρη ήταν ζωντανός. Η ζωή ήρθε σε αυτόν τον έρημο πλανήτη από τον πολιτισμό μας, όπως ακριβώς και στον δικό σας. Για εκατομμύρια χρόνια επισκεπτόμασταν τον πλανήτη σας και αναπτύξαμε γενετικά το είδος σας. Δεν μπορείτε να μας σκοτώσετε, είστε κομμάτι μας....\"\n  STR_VICTORY_3: \"Εδώ είναι το κέντρο του πολιτισμού στον Άρη - οι πυραμίδες κατασκευάστηκαν εκατομμύρια χρόνια πριν από τις δικες σας - από ένα είδος το οποίο είναι πρόγονος σας. Κανένας πλανήτης δεν βρίσκεται πέραν των δυνατοτήτων μας. Αυτή η δύναμη θα μπορούσε να είναι η δική σας πριν από καιρό. Το μόνο που ζητάμε είναι η συνεργασία σας...\"\n  STR_GAME_OVER_1: \"Οι εξωγήινοι επιχειρούν να εξολοθρεύσουν την ανθρωπότητα, καταστρέφοντας πόλεις και δηλητηριάζοντας τον αέρα και την θάλασσα. Η ένοπλη αντίσταση των γήινων είναι μάταιη απέναντι στην τρομερά ανώτερη τεχνολογία των εχθρών τους. Οι επόμενες γενιές γίνονται θύματα τρομακτικών μεταλλάξεων στην προσπάθεια τους να ξεφύγουν από την εξωγήινη καταστροφή. Φυλακίζονται σε στρατόπεδα αιχμαλώτων, και αναγκάζονται να  βοηθήσουν για την μετατροπή της γης σε μια ξένη αποικία, κομμάτι μιας άγνωστης αυτοκρατορίας.\"\n  STR_GAME_OVER_2: \"Οι γνώσεις που αποκτήθηκαν μέσω του προτζεκτ X-Com χάθηκαν για πάντα. Δεν κατάφερες να σώσεις τη γη.\"\n  STR_VICTORY_4: \"Ο εξωγήινος εγκέφαλος διακόπτεται από μια ριπή καυτού πλάσματος, και το σύνολο των εξωγήινων δυνάμεων ηττούνται.\"\n  STR_VICTORY_5: \"Από τη στιγμή που οι εξωγήινοι έχουν χάσει τον Άρη, έχουν χάσει τη γη. Σύντομα, η έρευνα X-Com επιτρέπει στην ανθρωπότητα να ανθίσει ξανά και να διεκδικήσει τον Άρη για τον εαυτό της. Η εξωγήινη απειλή έχει φύγει, αλλά για πόσο καιρό κανείς δεν ξέρει...\"\n  STR_YOU_HAVE_FAILED: \"Δεν κατάφερες να σταματήσεις την εξωγήινη σφαγή. Ένα ένα, τα έθνη χορηγοί υπογράφουν μυστικές συμφωνίες με τους εξωγήινους που τους υπόσχονται τεχνολογία, ευημερία και ειρήνη. Σύντομα όμως γίνεται φανερό ότι οι εξωγήινοι έχουν άλλα σχέδια...\"\n  STR_TOTAL_UC: \"ΣΥΝΟΛΟ\"\n  STR_INCOME: \"Έσοδα\"\n  STR_EXPENDITURE: \"Έξοδα\"\n  STR_MAINTENANCE: \"Συντήρηση\"\n  STR_BALANCE: \"Ταμείο\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"Δραστηριότητα ΑΤΙΑ ανά περιοχές\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"Δραστηριότητα ΑΤΙΑ ανά Χώρες\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"XCOM Δραστηριότητα ανά Περιοχές\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"XCOM Δραστηριότητα σε Χώρες\"\n  STR_FINANCE: \"Οικονομικά\"\n  STR_DATE_FIRST: \"{0}η\"\n  STR_DATE_SECOND: \"{0}η\"\n  STR_DATE_THIRD: \"{0}η\"\n  STR_DATE_FOURTH: \"{0}η\"\n  STR_FINANCE_THOUSANDS: \"$1000's\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Ανεπαρκή υλικά για την παραγωγή {NEWLINE}{0}{NEWLINE}στη{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Ανεπαρκή λεφτά για την παραγωγή {NEWLINE}{0}{NEWLINE}στη{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"Η παραγωγή{NEWLINE}{0}{NEWLINE}στη{NEWLINE}{1}{NEWLINE}τελείωσε\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"Η κατασκευή {NEWLINE}{0}{NEWLINE} στη {NEWLINE}{1}{NEWLINE} τελείωσε\"\n  STR_OK_5_SECONDS: \"ΟΚ - 5 δεύτερα\"\n  STR_RESEARCH_COMPLETED: \"Έρευνα Ολοκληρώθηκε\"\n  STR_VIEW_REPORTS: \"ΔΕΙΞΕ ΑΝΑΦΟΡΕΣ\"\n  STR_WE_CAN_NOW_RESEARCH: \"Πλέον μπορούμε να ερευνήσουμε\"\n  STR_WE_CAN_NOW_PRODUCE: \"Πλέον μπορούμε να παράγουμε\"\n  STR_SUNDAY: \"ΚΥΡΙΑΚΗ\"\n  STR_MONDAY: \"ΔΕΥΤΕΡΑ\"\n  STR_TUESDAY: \"ΤΡΙΤΗ\"\n  STR_WEDNESDAY: \"ΤΕΤΑΡΤΗ\"\n  STR_THURSDAY: \"ΠΕΜΠΤΗ\"\n  STR_FRIDAY: \"ΠΑΡΑΣΚΕΥΗ\"\n  STR_SATURDAY: \"ΣΑΒΒΑΤΟ\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Ανεπαρκή {0} για ανεφοδιασμό {1} στη {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Ανεπαρκή {0} για να ξαναοπλιστεί {1} στη {2}\"\n  STR_UFO_IS_NOT_RECOVERED: \"Το ΑΤΙΑ δεν ανακτήθηκε\"\n  STR_UFO_IS_RECOVERED: \"Το ΑΤΙΑ ανακτήθηκε\"\n  STR_CRAFT_IS_LOST: \"Το Σκάφος Έχει Χαθεί\"\n  STR_TERROR_CONTINUES: \"Η τρομοκρατία συνεχίζετε\"\n  STR_ALIENS_DEFEATED: \"Οι Εξωγήινοι Νικήθηκαν\"\n  STR_BASE_IS_LOST: \"Η βάση χάθηκε\"\n  STR_BASE_IS_SAVED: \"Η βάση σώθηκε\"\n  STR_ALIEN_BASE_STILL_INTACT: \"Η Εξωγήινη Βάση είναι ακόμα ανέπαφη\"\n  STR_ALIEN_BASE_DESTROYED: \"Η εξωγήινη βάση καταστράφηκε\"\n  STR_ALIENS_KILLED: \"ΕΞΩΓΗΙΝΟΙ ΠΟΥ ΣΚΟΤΩΘΗΚΑΝ\"\n  STR_ALIEN_CORPSES_RECOVERED: \"ΕΞΩΓΗΙΝΑ ΠΤΩΜΑΤΑ ΑΝΑΣΥΡΘΗΚΑΝ\"\n  STR_LIVE_ALIENS_RECOVERED: \"ΖΩΝΤΑΝΟΙ ΕΞΩΓΗΙΝΟΙ ΑΝΑΣΥΡΘΗΚΑΝ\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"ΑΝΕΚΤΗΜΕΝΑ ΕΞΩΓΗΙΝΑ ΕΥΡΗΜΑΤΑ\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"ΚΕΝΤΡΟ ΕΛΕΓΧΟΥ ΒΑΣΗΣ ΚΑΤΑΣΤΡΑΦΗΚΕ\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"ΠΟΛΙΤΕΣ ΠΟΥ ΣΚΟΤΩΘΗΚΑΝ ΑΠΟ ΕΞΩΓΗΙΝΟΥΣ\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"ΠΟΛΙΤΕΣ ΠΟΥ ΣΚΟΤΩΘΗΚΑΝ ΑΠΟ ΠΡΑΚΤΟΡΕΣ X-COM\"\n  STR_CIVILIANS_SAVED: \"ΠΟΛΙΤΕΣ ΠΟΥ ΣΩΘΗΚΑΝ\"\n  STR_XCOM_OPERATIVES_KILLED: \"ΠΡΑΚΤΟΡΕΣ X-COM ΣΚΟΤΩΘΗΚΑΝ\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"X-COM ΠΡΑΚΤΟΡΕΣ ΠΟΥ ΑΓΝΟΟΥΝΤΑΙ\"\n  STR_TANKS_DESTROYED: \"ΚΑΤΕΣΤΡΑΜΜΕΝΑ ΑΡΜΑΤΑ\"\n  STR_XCOM_CRAFT_LOST: \"X-COM ΣΚΑΦΟΣ ΧΑΘΗΚΕ\"\n  STR_UFO_RECOVERY: \"ΑΝΑΚΤΗΣΗ ΑΤΙΑ\"\n  STR_ALIEN_BASE_RECOVERY: \"ΑΝΑΚΤΗΣΗ ΕΞΩΓΗΙΝΗΣ ΒΑΣΗΣ\"\n  STR_BASE_UNDER_ATTACK: \"{0} δέχεται επίθεση!\"\n  STR_BASE_DEFENSES_INITIATED: \"ΑΜΥΝΕΣ ΒΑΣΗΣ ΕΝΕΡΓΟΠΟΙΗΘΗΚΑΝ\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"Η ΒΑΡΥΤΙΚΗ ΑΣΠΙΔΑ ΑΠΩΘΕΙ ΤΟ ΑΤΙΑ!\"\n  STR_FIRING: \"ΠΥΡΟΒΟΛΕΙ\"\n  STR_HIT: \"ΧΤΥΠΗΜΑ!\"\n  STR_UFO_DESTROYED: \"ΑΤΙΑ ΚΑΤΑΣΤΡΑΦΗΚΕ!\"\n  STR_MISSED: \"ΑΣΤΟΧΗΣΕ!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Πώληση Αντικειμένων/Απολύσεις\"\n  STR_VALUE_OF_SALES: \"Αξία Πωλήσεων> {ALT}{0}\"\n  STR_FUNDS: \"Κονδύλια> {ALT}{0}\"\n  STR_SELL_SACK: \"Πώληση/Απόλυση\"\n  STR_VALUE: \"Αξία\"\n  STR_CRAFT_: \"ΣΚΑΦΟΣ> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"ΑΝΑΚΤΗΣΗ ΣΥΝΤΕΤΡΙΜΜΕΝΟΥ ΑΤΙΑ\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"Να είστε προσεκτικοί - Μπορεί να υπάρχουν πράκτορες στο UFO ή γύρω από τον τόπο συντριβής. Η αποστολή θα είναι επιτυχής όταν όλες οι μονάδες του εχθρού έχουν εξαλειφθεί ή εξουδετερωθεί. Η ανάκτηση των απομεινάριων , τεχνουργημάτων και εξωγήινων πτωμάτων του UFO μπορούν στη συνέχεια να ξεκινήσουν. Για να ακυρώσετε την αποστολή, οι πράκτορες X-Com θα πρέπει να επιστρέψουν στο όχημα και να κάνετε κλικ στο εικονίδιο «Ακύρωση αποστολής».\"\n  STR_UFO_GROUND_ASSAULT: \"ΕΦΟΔΟΣ ΕΔΑΦΟΥΣ ΣΕ ΑΤΙΑ\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"Εξερευνήστε τον τόπο προσγείωσης και, εάν είναι δυνατόν, αποκτήστε είσοδο στο ΑΤΙΑ. Η αποστολή θα είναι επιτυχής όταν όλες οι εχθρικές μονάδες έχουν εξαλειφθεί ή εξουδετερωθεί. Στη συνέχεια, μπορεί να ξεκινήσει η ανάκτηση του ΑΤΙΑ, αντικειμένων και πτωμάτων εξωγήινων. Για να ματαιώσετε την αποστολή, επιστρέψτε τους X-Com πράκτορες στο μεταφορικό όχημα και κάντε κλικ στο εικονίδιο 'Ακύρωση αποστολής'.\"\n  STR_BASE_DEFENSE: \"ΑΜΥΝΑ ΒΑΣΗΣ\"\n  STR_BASE_UC_: \"ΒΑΣΗ> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"Ένα σκάφος εξωγήινων προσγειώθηκε σε κοντινή απόσταση. Η βάση μας κινδυνεύει σοβαρά. Σύμφωνα με την τυπική διαδικασία, όλο το μη μάχιμο προσωπικό και τα σκάφη X-Com έχουν εκκενωθεί. Οι μονάδες εξωγήινων θα εισέλθουν στη βάση μέσω των θυρών υπόστεγου ή του ανελκυστήρα πρόσβασης. Υπερασπιστείτε τη βάση και τις ζωτικής σημασίας εγκαταστάσεις της με κάθε κόστος - αυτός είναι αγώνας μέχρι θανάτου. Εάν κάνετε κλικ στο εικονίδιο «ΑΚΥΡΩΣΗ ΑΠΟΣΤΟΛΗΣ», θα παραδεχτείτε την ήττα και θα χάσετε τη βάση.\"\n  STR_ALIEN_BASE_ASSAULT: \"ΕΠΙΘΕΣΗ ΕΞΩΓΗΙΝΗΣ ΒΑΣΗΣ\"\n  STR_ALIEN_BASE_ASSAULT_BRIEFING: \"Οι πράκτορες X-Com έχουν αποκτήσει πρόσβαση σε μια εξωγήινη βάση. Το κέντρο ελέγχου πρέπει να καταστραφεί για να τεθεί η βάση εκτός λειτουργίας. Η αποστολή θα τερματιστεί όταν εξαλειφθούν όλοι οι εχθροί ή όταν η ομάδα σας επιστρέψει στην πράσινη περιοχή εξόδου (κάντε κλικ στο εικονίδιο \\\"ακύρωση αποστολής\\\" για να ξεφύγετε).\"\n  STR_CYDONIA_BRIEFING: \"Έφτασες στην Κυδωνία. Μπήκες σε ένα μεγάλο υπόγειο συγκρότημα κοντά στην Αρειανή Σφίγγα. Θα πρέπει να καταστρέψεις τον Εξωγήινο Εγκέφαλο που ελέγχει όλες τις εξωγήινες δραστηριότητες. Η μοίρα της ανθρωπότητας είναι στα χέρια σου ....\"\n  STR_TERROR_MISSION: \"ΑΠΟΣΤΟΛΗ ΤΡΟΜΟΚΡΑΤΙΑΣ\"\n  STR_TERROR_MISSION_BRIEFING: \"Η αποστολή θα είναι επιτυχής όταν όλες οι μονάδες του εχθρού έχουν εξαλειφθεί ή εξουδετερωθεί. Πρέπει να προσπαθήσετε να σώσετε τις ζωές των πολιτών στην περιοχή εξουδετερώνοντας την εξωγήινη απειλή. Για να ακυρώσετε την αποστολή, επιστρέψτε τους πράκτορες X-Com στο μεταφορικό όχημα και κάντε κλικ στο εικονίδιο «ακύρωση αποστολής».\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"ΔΕΝ ΥΠΑΡΧΟΥΝ ΕΛΕΥΘΕΡΑ ΥΠΟΣΤΕΓΑ ΓΙΑ ΤΗ ΠΑΡΑΓΩΓΗ!{SMALLLINE}Κάθε σκάφος έχει που ανατεθεί, μεταφέρεται, αγοράστηκε ή κατασκευάστηκε σε μία βάση χρησιμοποιεί ένα υπόστεγο. Κατασκεύασε ένα νέο υπόστεγο ή να μετέφερε ένα σκάφος σε άλλη βάση.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"ΔΕΝ ΥΠΑΡΧΟΥΝ ΕΛΕΥΘΕΡΑ ΥΠΟΣΤΕΓΑ ΓΙΑ ΤΗΝ ΑΓΟΡΑ!{SMALLLINE}Κάθε σκάφος έχει που ανατεθεί, μεταφέρεται, αγοράστηκε ή κατασκευάστηκε σε μία βάση χρησιμοποιεί ένα υπόστεγο. Κατασκεύασε ένα νέο υπόστεγο ή να μετέφερε ένα σκάφος σε άλλη βάση.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"ΔΕΝ ΥΠΑΡΧΟΥΝ ΕΛΕΥΘΕΡΑ ΥΠΟΣΤΕΓΑ ΓΙΑ ΤΗ ΜΕΤΑΦΟΡΑ!{SMALLLINE}Κάθε σκάφος έχει που ανατεθεί, μεταφέρεται, αγοράστηκε ή κατασκευάστηκε σε μία βάση χρησιμοποιεί ένα υπόστεγο. Κατασκεύασε ένα νέο υπόστεγο ή να μετέφερε ένα σκάφος σε άλλη βάση.\"\n  STR_CANNOT_BUILD_HERE: \"ΑΔΥΝΑΜΙΑ ΚΑΤΑΣΚΕΥΗΣ ΕΔΩ!{SMALLLINE}Πρέπει να χτίσεις δίπλα σε υπάρχουσες εγκαταστάσεις.\"\n  STR_NO_FREE_ACCOMODATION: \"ΑΝΕΠΑΡΚΕΙΣ ΧΩΡΟΣ ΔΙΑΜΟΝΗΣ{SMALLLINE}Η βάση προορισμού δεν έχει αρκετό χώρο στους κοιτώνες για το πλήρωμα που έχει ανατεθεί στο σκάφος.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"ΔΕΝ ΥΠΑΡΧΕΙ ΑΡΚΕΤΟΣ ΧΩΡΟΣ ΕΡΓΑΣΙΑΣ!{SMALLLINE}Χτίσε καινούργια μηχανουργεία ή μείωσε τη δουλεία σε άλλα έργα.\"\n  STR_NOT_ENOUGH_MONEY: \"ΑΝΕΠΑΡΚΗ ΚΕΦΑΛΑΙΑ\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"ΑΝΕΠΑΡΚΕΙΣ ΧΩΡΟΣ ΔΙΑΒΙΩΣΗΣ!{SMALLLINE}Φτιάξτε νέους κοιτώνες ή μεταφερετε προσωπικό σε άλλες βάσεις.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"ΑΝΕΠΑΡΚΕΙΣ ΧΩΡΟΣ ΔΙΑΒΙΩΣΗΣ!{SMALLLINE}Φτιάξε νέους κοιτώνες ή μετέφερε προσωπικό σε άλλες βάσεις.\"\n  STR_LAUNCH_INTERCEPTION: \"ΑΠΟΓΕΙΩΣΗ ΑΝΑΧΑΙΤΙΣΤΙΚΟΥ\"\n  STR_CRAFT: \"ΣΚΑΦΟΣ\"\n  STR_STATUS: \"ΚΑΤΑΣΤΑΣΗ\"\n  STR_BASE: \"ΒΑΣΗ\"\n  STR_READY: \"ETOIMO\"\n  STR_OUT: \"ΕΞΩ\"\n  STR_REPAIRS: \"ΕΠΙΣΚΕΥΕΣ\"\n  STR_REFUELLING: \"ΑΝΕΦΟΔΙΑΣΜΟΣ\"\n  STR_REARMING: \"ΑΝΑΤΡΟΦΟΔΟΤΗΣΗ\"\n  STR_TARGET: \"ΣΤΟΧΟΣ: {0}\"\n  STR_WAY_POINT: \"ΣΗΜΕΙΟ\"\n  STR_ARE_YOU_SURE_CYDONIA: \"Είσαι σίγουρος ότι θέλεις να στείλεις αυτό το σκάφος σε αποστολή στην Κυδωνία;\"\n  STR_YES: \"ΝΑΙ\"\n  STR_NO: \"ΟΧΙ\"\n  STR_SELECT_DESTINATION: \"ΕΠΕΛΕΞΕ ΠΡΟΟΡΙΣΜΟ\"\n  STR_CYDONIA: \"ΚΥΔΩΝΙΑ\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"ΕΠΙΛΟΓΗ ΠΕΡΙΟΧΗΣ ΓΙΑ ΝΕΑ ΒΑΣΗ\"\n  STR_RETURN_TO_BASE: \"ΕΠΙΣΤΡΟΦΗ ΣΤΗ ΒΑΣΗ\"\n  STR_SELECT_NEW_TARGET: \"ΕΠΙΛΟΓΗ ΝΕΟΥ ΣΤΟΧΟΥ\"\n  STR_PATROL: \"ΠΕΡΙΠΟΛΙΑ\"\n  STR_STATUS_: \"ΚΑΤΑΣΤΑΣΗ>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"ΧΤΥΠΗΜΕΝΟ - ΕΠΙΣΤΡΟΦΗ ΣΤΗ ΒΑΣΗ\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"ΧΑΜΗΛΑ ΚΑΥΣΙΜΑ - ΕΠΙΣΤΡΕΦΕΙ ΣΤΗ ΒΑΣΗ\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"Η ΑΠΟΣΤΟΛΗ ΟΛΟΚΛΗΡΩΘΗΚΕ - ΕΠΙΣΤΡΟΦΗ ΣΤΗ ΒΑΣΗ\"\n  STR_PATROLLING: \"ΠΕΡΙΠΟΛΕΙ\"\n  STR_TAILING_UFO: \"ΠΑΡΑΚΟΛΟΥΘΗΣΗ ΑΤΙΑ\"\n  STR_INTERCEPTING_UFO: \"ΑΝΑΧΑΙΤΙΣΗ ΑΤΙΑ-{0}\"\n  STR_RETURNING_TO_BASE: \"ΕΠΙΣΤΡΟΦΗ ΣΤΗ ΒΑΣΗ\"\n  STR_DESTINATION_UC_: \"ΠΡΟΟΡΙΣΜΟΣ: {0}\"\n  STR_BASE_UC: \"ΒΑΣΗ>{ALT}{0}\"\n  STR_SPEED_: \"ΤΑΧΥΤΗΤΑ>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"ΜΕΓΙΣΤΗ ΤΑΧΥΤΗΤΑ>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"ΥΨΟΜΕΤΡΟ>{ALT}{0}\"\n  STR_VERY_LOW: \"ΠΟΛΥ ΧΑΜΗΛΑ\"\n  STR_LOW_UC: \"ΧΑΜΗΛΟ\"\n  STR_HIGH_UC: \"ΨΗΛΑ\"\n  STR_VERY_HIGH: \"ΠΟΛΥ ΨΗΛΑ\"\n  STR_FUEL: \"ΚΑΥΣΙΜΑ>{ALT}{0}\"\n  STR_WEAPON_ONE: \"ΟΠΛΟ-1>{ALT}{0}\"\n  STR_NONE_UC: \"ΚΑΝΕΝΑ\"\n  STR_ROUNDS_: \"ΒΟΛΕΣ>{ALT}{0}\"\n  STR_WEAPON_TWO: \"ΟΠΛΟ-2>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"ΣΚΑΦΟΣ ΑΝΑΧΑΙΤΙΣΗΣ\"\n  STR_BASE_: \"Βάση>{0} \"\n  STR_NAME_UC: \"ΟΝΟΜΑ\"\n  STR_AMMO_: \"ΠΥΡ/ΧΙΚA>{ALT}{0}\"\n  STR_CREW: \"ΠΛΗΡΩΜΑ\"\n  STR_EQUIPMENT_UC: \"ΕΞΟΠΛΙΣΜΟΣ\"\n  STR_ARMOR: \"ΠΑΝΟΠΛΙΑ\"\n  STR_MAX: \"ΜΕΓΙΣΤΟ>{ALT}{0}\"\n  STR_ROOKIE: \"Αρχάριος\"\n  STR_SQUADDIE: \"Φαντάρος\"\n  STR_SERGEANT: \"Λοχίας\"\n  STR_CAPTAIN: \"Λοχαγός\"\n  STR_COLONEL: \"Συνταγματάρχης\"\n  STR_COMMANDER: \"Διοικητής\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Επέλεξε Ομάδα για {0}\"\n  STR_SORT_BY: \"ΤΑΞΙΝΟΜΗΣΗ ΚΑΤΑ...\"\n  STR_ORIGINAL_ORDER: \"ΑΡΧΙΚΗ ΔΙΑΤΑΓΗ\"\n  STR_MISSIONS2: \"ΑΠΟΣΤΟΛΕΣ\"\n  STR_KILLS2: \"ΘΑΝΑΤΟΙ\"\n  STR_WOUND_RECOVERY2: \"ΑΝΑΡΡΩΣΗ ΑΠΟ ΤΡΑΥΜΑ\"\n  STR_SPACE_AVAILABLE: \"ΔΙΑΘΕΣΙΜΟΣ ΧΩΡΟΣ>{ALT}{0}\"\n  STR_SPACE_USED: \"ΚΑΤΕΙΛΗΜΜΕΝΟΣ>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"ΚΑΤ/ΜΕΝΟΣ ΧΩΡ.\"\n  STR_RANK: \"ΒΑΘΜΙΔΑ\"\n  STR_WOUNDED: \"ΤΡΑΥΜΑΤΙΑΣ\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Εξοπλισμός για {0}\"\n  STR_DEFENSE_VALUE: \"Αμυντική Αξία\"\n  STR_HIT_RATIO: \"Πιθανότητα Προσβολής\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}έτοιμο να{NEWLINE}προσγειωθεί κοντά σε{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"Άρχισε Αποστολή;\"\n  STR_SELECT_ARMAMENT: \"Επιλογή Οπλισμού\"\n  STR_AMMUNITION_AVAILABLE: \"ΔΙΑΘΕΣΙΜΑ ΠΥΡΟΜΑΧΙΚΑ\"\n  STR_ARMAMENT: \"ΟΠΛΙΣΜΟΣ\"\n  STR_NOT_AVAILABLE: \"Δ/Ι\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"ΕΠΙΛΟΓΗ ΠΑΝΟΠΛΙΑΣ ΓΙΑ{NEWLINE}{0}\"\n  STR_TYPE: \"ΤΥΠΟΣ\"\n  STR_PERSONAL_ARMOR_UC: \"ΠΡΟΣΩΠΙΚΗ ΘΩΡΑΚΙΣΗ\"\n  STR_POWER_SUIT_UC: \"ΕΝΕΡΓΕΙΑΚΗ ΠΑΝΟΠΛΙΑ\"\n  STR_FLYING_SUIT_UC: \"ΙΠΤΑΜΕΝΗ ΣΤΟΛΗ\"\n  STR_SELECT_ARMOR: \"Επιλογή Πανοπλίας\"\n  STR_NORTH: \"ΒΟΡΡΑΣ\"\n  STR_NORTH_EAST: \"ΒΟΡΕΙΟΑΝΑΤΟΛΙΚΑ\"\n  STR_EAST: \"ΑΝΑΤΟΛΗ\"\n  STR_SOUTH_EAST: \"ΝΟΤΙΟΑΝΑΤΟΛΙΚΑ\"\n  STR_SOUTH: \"ΝΟΤΟΣ\"\n  STR_SOUTH_WEST: \"ΝΟΤΙΟΔΥΤΙΚΑ\"\n  STR_WEST: \"ΔΥΣΗ\"\n  STR_NORTH_WEST: \"ΒΟΡΕΙΟΔΥΤΙΚΑ\"\n  STR_SELECT_ACTION: \"ΕΠΙΛΟΓΗ ΕΝΕΡΓΕΙΑΣ\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"ΣΥΝΕΧΙΣΕ ΑΝΑΧΑΙΤΙΣΤΙΚΗ ΚΑΤΑΔΙΩΞΗ\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"ΚΑΤΑΔΙΩΞΗ ΧΩΡΙΣ ΑΝΑΧΑΙΤΙΣΗ\"\n  STR_VERY_LARGE: \"ΠΟΛΥ ΜΕΓΑΛΟ\"\n  STR_LARGE: \"ΜΕΓΑΛΟ\"\n  STR_MEDIUM_UC: \"ΜΕΣΑΙΟ\"\n  STR_SMALL: \"ΜΙΚΡΟ\"\n  STR_VERY_SMALL: \"ΠΟΛΥ ΜΙΚΡΟ\"\n  STR_GROUNDED: \"ΕΔΑΦΟΣ\"\n  STR_DETECTED: \"Ανιχνεύτηκε\"\n  STR_SIZE_UC: \"ΜΕΓΕΘΟΣ\"\n  STR_ALTITUDE: \"ΥΨΟΣ\"\n  STR_HEADING: \"ΠΡΟΟΡΙΣΜΟΣ\"\n  STR_SPEED: \"ΤΑΧΥΤΗΤΑ\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"ΚΕΝΤΡΑΡΕ ΣΤΟ ΑΤΙΑ - ΧΡΟΝΟΣ = 5 Δευτ.\"\n  STR_TRACKING_LOST: \"ΙΧΝΟΣ ΧΑΘΗΚΕ\"\n  STR_REDIRECT_CRAFT: \"ΝΕΑ ΠΟΡΕΙΑ ΣΚΑΦΟΥΣ\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"ΠΗΓΑΙΝΕ ΣΤΗΝ ΤΕΛΕΥΤΑΙΑ ΓΝΩΣΤΗ ΘΕΣΗ ΑΤΙΑ\"\n  STR_UFO_: \"ΑΤΙΑ-{0}\"\n  STR_ALIEN_BASE_: \"ΕΞΩΓΗΙΝΗ ΒΑΣΗ-{0}\"\n  STR_CRASH_SITE_: \"ΣΗΜΕΙΟ ΣΥΝΤΡΙΒΗΣ-{0}\"\n  STR_LANDING_SITE_: \"ΣΗΜΕΙΟ ΠΡΟΣΓΕΙΩΣΗΣ-{0}\"\n  STR_WAY_POINT_: \"ΣΗΜΕΙΟ-{0}\"\n  STR_TERROR_SITE: \"ΤΡΟΜΟΚΡΑΤΙΚΟ ΧΤΥΠΗΜΑ-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}έφτασε{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"Τώρα περιπολεί\"\n  STR_ALIEN_ORIGINS: \"Προέλευση Εξωγήινων\"\n  STR_THE_MARTIAN_SOLUTION: \"Η Αριανή Λύση\"\n  STR_CYDONIA_OR_BUST: \"Κυδωνία ή Αποτυχία\"\n  STR_UFOPAEDIA: \"ΟΥΦΟπαιδεία\"\n  STR_XCOM_CRAFT_ARMAMENT: \"XCOM ΣΚΑΦΗ & ΟΠΛΙΣΜΟΣ\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"ΕΞΕΔΡΕΣ ΒΑΡΕΩΝ ΟΠΛΩΝ\"\n  STR_WEAPONS_AND_EQUIPMENT: \"ΟΠΛΑ ΚΑΙ ΕΞΟΠΛΙΣΜΟΙ\"\n  STR_ALIEN_ARTIFACTS: \"ΕΞΩΓΗΙΝΑ ΕΥΡΗΜΑΤΑ\"\n  STR_BASE_FACILITIES: \"ΕΓΚΑΤΑΣΤΑΣΕΙΣ ΒΑΣΗΣ\"\n  STR_ALIEN_LIFE_FORMS: \"ΕΞΩΓΗΙΝΕΣ ΜΟΡΦΕΣ ΖΩΗΣ\"\n  STR_ALIEN_RESEARCH_UC: \"ΕΞΩΓΗΙΝΗ ΕΡΕΥΝΑ\"\n  STR_UFO_COMPONENTS: \"ΕΞΑΡΤΗΜΑΤΑ ΑΤΙΑ\"\n  STR_UFOS: \"ΑΤΙΑ\"\n  STR_SELECT_ITEM: \"ΕΠΕΛΕΞΕ ΑΝΤΙΚΕΙΜΕΝΟ\"\n  STR_ACCELERATION: \"ΕΠΙΤΑΧΥΝΣΗ>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"ΧΩΡΗΤΙΚΟΤΗΤΑ ΚΑΥΣΙΜΩΝ>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"ΘΕΣΕΙΣ ΟΠΛΩΝ>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"ΑΝΟΧΗ ΖΗΜΙΑΣ>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"ΧΩΡΟΣ ΦΟΡΤΙΟΥ>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"ΧΩΡΗΤΙΚΟΤΗΤΑ ΕΒΟ>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Ζημιά\"\n  STR_RANGE: \"Εμβέλεια\"\n  STR_KILOMETERS: \"{0} χλμ\"\n  STR_ACCURACY: \"Ευστοχία\"\n  STR_RE_LOAD_TIME: \"Χρόνος επαναγέμισης Όπλου\"\n  STR_SECONDS: \"{0}δ\"\n  STR_DAMAGE_ARMOR_PIERCING: \"ΔΙΑΤΡΗΤΙΚΟ\"\n  STR_DAMAGE_INCENDIARY: \"ΕΜΠΡΗΣΤΙΚΟ\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"ΕΚΡΗΚΤΙΚΟ\"\n  STR_DAMAGE_LASER_BEAM: \"ΔΕΣΜΗ ΛΕΙΖΕΡ\"\n  STR_DAMAGE_PLASMA_BEAM: \"ΑΚΤΙΝΑ ΠΛΑΣΜΑΤΟΣ\"\n  STR_DAMAGE_STUN: \"Αναισθησία\"\n  STR_DAMAGE_MELEE: \"ΣΥΜΠΛΟΚΗ\"\n  STR_DAMAGE_ACID: \"ΟΞΥ\"\n  STR_DAMAGE_SMOKE: \"ΚΑΠΝΟΣ\"\n  STR_SHOT_TYPE: \"ΤΥΠΟΣ ΒΟΛΗΣ\"\n  STR_ACCURACY_UC: \"ΕΥΣΤΟΧΙΑ\"\n  STR_TIME_UNIT_COST: \"Κόστος ΧΜ\"\n  STR_DAMAGE_UC: \"ΖΗΜΙΑ\"\n  STR_AMMO: \"ΠΥΡ/ΧΙΚΑ\"\n  STR_SHOT_TYPE_AUTO: \"Αυτόματη\"\n  STR_SHOT_TYPE_SNAP: \"Γρήγορη\"\n  STR_SHOT_TYPE_AIMED: \"Στοχευμένη\"\n  STR_CONSTRUCTION_TIME: \"Χρόνος Κατασκευής\"\n  STR_CONSTRUCTION_COST: \"Κόστος Κατασκευής\"\n  STR_MAINTENANCE_COST: \"Κόστος Συντήρησης\"\n  STR_LOW: \"Χαμηλό\"\n  STR_MEDIUM: \"Μεσαίο\"\n  STR_HIGH: \"Ψηλά\"\n  STR_CRAFT_WEAPON: \"Όπλο Σκάφους\"\n  STR_CRAFT_AMMUNITION: \"Πυρομαχικά Σκάφους\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Εξέδρα Βαρέων Όπλων\"\n  STR_WEAPON: \"Όπλο\"\n  STR_AMMUNITION: \"Πυρομαχικά\"\n  STR_EQUIPMENT: \"Εξοπλισμός\"\n  STR_ALIEN_CORPSE: \"Εξωγήινο Πτώμα\"\n  STR_UFO_COMPONENT: \"Εξάρτημα ΑΤΙΑ\"\n  STR_PERSONAL_ARMOR: \"Προσωπική Θωράκιση\"\n  STR_RAW_MATERIALS: \"Πρώτες Ύλες\"\n  STR_HWP_CANNON_SHELLS: \"ΕΒΟ Οβίδες Κανονιού\"\n  STR_ALIEN: \"Εξωγήινος\"\n  STR_SECTOID: \"Σεκτόιντ\"\n  STR_SNAKEMAN: \"Φιδάνθρωπος\"\n  STR_ETHEREAL: \"Αιθέριος\"\n  STR_MUTON: \"Μάτον\"\n  STR_FLOATER: \"Αιωρητής\"\n  STR_CELATID: \"Celatid\"\n  STR_SILACOID: \"Σίλακοϊντ\"\n  STR_CHRYSSALID: \"Χρυσαλλίδα\"\n  STR_ZOMBIE: \"Ζόμπι\"\n  STR_REAPER: \"Θεριστής\"\n  STR_SECTOPOD: \"Sectopod\"\n  STR_CYBERDISC: \"Κυβερνοδίσκος\"\n  STR_LIVE_COMMANDER: \"Διοικητής\"\n  STR_LIVE_LEADER: \"Αρχηγός\"\n  STR_LIVE_ENGINEER: \"Μηχανικός\"\n  STR_LIVE_MEDIC: \"Γιατρός\"\n  STR_LIVE_NAVIGATOR: \"Πλοηγός\"\n  STR_LIVE_SOLDIER: \"Στρατιώτης\"\n  STR_LIVE_TERRORIST: \"Τρομοκράτης\"\n  STR_FLOATER_SOLDIER: \"Αιωρητής Στρατιώτης\"\n  STR_FLOATER_NAVIGATOR: \"Αιωρητής Πλοηγός\"\n  STR_FLOATER_MEDIC: \"Αιωρητής Γιατρός\"\n  STR_FLOATER_ENGINEER: \"Αιωρητής Μηχανικός\"\n  STR_FLOATER_LEADER: \"Αιωρητής Αρχηγός\"\n  STR_FLOATER_COMMANDER: \"Αιωρητής Διοικητής\"\n  STR_SECTOID_SOLDIER: \"Σεκτόιντ Στρατιώτης\"\n  STR_SECTOID_NAVIGATOR: \"Σεκτόιντ Πλοηγός\"\n  STR_SECTOID_MEDIC: \"Σεκτόιντ Γιατρός\"\n  STR_SECTOID_ENGINEER: \"Σεκτόιντ Μηχανικος\"\n  STR_SECTOID_LEADER: \"Σεκτόιντ Αρχηγός\"\n  STR_SECTOID_COMMANDER: \"Σεκτόιντ Διοικητής\"\n  STR_SNAKEMAN_SOLDIER: \"Φιδάνθρωπος Στρατιώτης\"\n  STR_SNAKEMAN_NAVIGATOR: \"Φιδάνθρωπος Πλοηγός\"\n  STR_SNAKEMAN_ENGINEER: \"Φιδάνθρωπος Μηχανικός\"\n  STR_SNAKEMAN_LEADER: \"Φιδάνθρωπος Αρχηγός\"\n  STR_SNAKEMAN_COMMANDER: \"Φιδάνθρωπος Διοικητής\"\n  STR_MUTON_SOLDIER: \"Μάτον Στρατιώτης\"\n  STR_MUTON_NAVIGATOR: \"Μάτον Πλοηγός\"\n  STR_MUTON_ENGINEER: \"Μάτον Μηχανικός\"\n  STR_ETHEREAL_SOLDIER: \"Αιθέριος Στρατιώτης\"\n  STR_ETHEREAL_LEADER: \"Αιθέριος Αρχηγός\"\n  STR_ETHEREAL_COMMANDER: \"Αιθέριος Διοικητής\"\n  STR_CYBERDISC_TERRORIST: \"Κυβερνοδίσκος τρομοκράτης\"\n  STR_REAPER_TERRORIST: \"Θεριστής Τρομοκράτης\"\n  STR_CHRYSSALID_TERRORIST: \"Χρυσαλίδα Τρομοκράτης\"\n  STR_CELATID_TERRORIST: \"Τρομοκράτης Celatid\"\n  STR_SILACOID_TERRORIST: \"Σίλακοϊντ Τρομοκράτης\"\n  STR_SECTOPOD_TERRORIST: \"Τρομοκράτης Sectopod\"\n  STR_UFO_POWER_SOURCE: \"Πηγή Ισχύος ΑΤΙΑ\"\n  STR_UFO_NAVIGATION: \"Πλοήγηση ΑΤΙΑ\"\n  STR_UFO_CONSTRUCTION: \"Κατασκευή ΑΤΙΑ\"\n  STR_ALIEN_FOOD: \"Εξωγήινη Τροφή\"\n  STR_ALIEN_REPRODUCTION: \"Εξωγήινη Αναπαραγωγή\"\n  STR_ALIEN_ENTERTAINMENT: \"Εξωγήινη Διασκέδαση\"\n  STR_ALIEN_SURGERY: \"Εξωγήινο Χειρουργείο\"\n  STR_EXAMINATION_ROOM: \"Δωμάτιο Εξέτασης\"\n  STR_ALIEN_ALLOYS: \"Εξωγήινα Κράματα\"\n  STR_ALIEN_HABITAT: \"Εξωγήινη Κατοικία\"\n  STR_POWER_SUIT: \"Ενεργειακή πανοπλία\"\n  STR_FLYING_SUIT: \"Ιπτάμενη Στολή\"\n  STR_HWP_ROCKETS: \"ΕΒΟ Ρουκέτες\"\n  STR_HWP_FUSION_BOMB: \"ΕΒΟ Σφαίρες Σύντηξης\"\n  STR_LASER_WEAPONS: \"Όπλα Λέιζερ\"\n  STR_NEW_FIGHTER_CRAFT: \"Νέο Μαχητικό Σκάφος\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Νέο Μαχητικό/Μεταγωγικό\"\n  STR_ULTIMATE_CRAFT: \"Ύστατο Σκάφος\"\n  STR_LASER_PISTOL: \"Πιστόλι Λέιζερ\"\n  STR_LASER_RIFLE: \"Τυφέκιο Λέιζερ\"\n  STR_HEAVY_LASER: \"Βαρύ Λέιζερ\"\n  STR_LASER_CANNON: \"Κανόνι Λέιζερ\"\n  STR_PLASMA_CANNON: \"Κανόνι Πλάσματος\"\n  STR_FUSION_MISSILE: \"Πύραυλος Σύντυξης\"\n  STR_LASER_DEFENSE: \"Άμυνες Λέιζερ\"\n  STR_PLASMA_DEFENSE: \"Άμυνες Πλάσμα\"\n  STR_FUSION_DEFENSE: \"Άμυνες Σύντηξης\"\n  STR_GRAV_SHIELD: \"Ασπίδα Βαρύτητας\"\n  STR_MIND_SHIELD: \"Ασπίδα Νου\"\n  STR_PSI_LAB: \"Ψ-Εργαστήριο\"\n  STR_MOTION_SCANNER: \"Ανιχνευτής Κίνησης\"\n  STR_MEDI_KIT: \"Κυτίο Α' Βοηθειών\"\n  STR_TANK_CANNON: \"Άρμα/Κανόνι\"\n  STR_TANK_ROCKET_LAUNCHER: \"Άρμα/Πυραυλοβόλο\"\n  STR_TANK_LASER_CANNON: \"Άρμα/Κανόνι Λέιζερ\"\n  STR_HOVERTANK_PLASMA: \"Ιπτάμενο Άρμα/Πλάσμα\"\n  STR_HOVERTANK_LAUNCHER: \"Ιπτάμενο Άρμα/Σφαίρες Σύντηξης\"\n  STR_STINGRAY_LAUNCHER: \"Εκτοξευτής Stingray\"\n  STR_AVALANCHE_LAUNCHER: \"Εκτοξευτής Χιονοστιβάδων\"\n  STR_CANNON: \"Κανόνι\"\n  STR_FUSION_BALL_LAUNCHER: \"Εκτ/τής Σφαιρών Σύντηξης\"\n  STR_PLASMA_BEAM: \"Ακτίνα Πλάσματος\"\n  STR_STINGRAY_MISSILES: \"Βλήμματα Stingray\"\n  STR_AVALANCHE_MISSILES: \"Βλήμματα Avalanche(Χιονοστιβάδας)\"\n  STR_CANNON_ROUNDS_X50: \"Σφαίρες Κανονιού(x50)\"\n  STR_FUSION_BALL: \"Σφαίρα Σύντηξης\"\n  STR_SOLDIER: \"Στρατιώτης\"\n  STR_SCIENTIST: \"Επιστήμονας\"\n  STR_ENGINEER: \"Μηχανικός\"\n  STR_NORTH_AMERICA: \"Βόρεια Αμερική\"\n  STR_ARCTIC: \"Αρκτική\"\n  STR_ANTARCTICA: \"Ανταρκτική\"\n  STR_SOUTH_AMERICA: \"Νότια Αμερική\"\n  STR_EUROPE: \"Ευρώπη\"\n  STR_NORTH_AFRICA: \"Βόρεια Αφρική\"\n  STR_SOUTHERN_AFRICA: \"Νότια Αφρική\"\n  STR_CENTRAL_ASIA: \"Κεντρική Ασία\"\n  STR_SOUTH_EAST_ASIA: \"ΝΑ Ασία\"\n  STR_SIBERIA: \"Σιβηρία\"\n  STR_AUSTRALASIA: \"Αυστραλασία\"\n  STR_PACIFIC: \"Ειρηνικός\"\n  STR_NORTH_ATLANTIC: \"Β. Ατλαντικός\"\n  STR_SOUTH_ATLANTIC: \"Ν. Ατλαντικός\"\n  STR_INDIAN_OCEAN: \"Ινδικός Ωκεανός\"\n  STR_ALIEN_RESEARCH: \"Εξωγήινη Έρευνα\"\n  STR_ALIEN_HARVEST: \"Εξωγήινη Συγκομιδή\"\n  STR_ALIEN_ABDUCTION: \"Εξωγήινη Απαγωγή\"\n  STR_ALIEN_INFILTRATION: \"Εξωγήινη Διείσδυση\"\n  STR_ALIEN_BASE: \"Εξωγήινη Βάση \"\n  STR_ALIEN_TERROR: \"Εξωγήινη Τρομοκρατία\"\n  STR_ALIEN_RETALIATION: \"Αντίποινα Εξωγήινων\"\n  STR_ALIEN_SUPPLY: \"Εξωγήινος Ανεφοδιασμός\"\n  STR_MAXIMUM_SPEED: \"Μέγιστη Ταχύτητα\"\n  STR_HYPER_WAVE_DECODER_UC: \"ΥΠΕΡΚΥΜΑΤΙΚΟΣ ΑΠΟΚΩΔΙΚΟΠΟΙΗΤΗΣ\"\n  STR_SKYRANGER: \"ΑΕΡΟΦΥΛΑΚΑΣ\"\n  STR_LIGHTNING: \"ΚΕΡΑΥΝΟΣ\"\n  STR_AVENGER: \"ΕΚΔΙΚΗΤΗΣ\"\n  STR_INTERCEPTOR: \"ΑΝΑΧΑΙΤΙΣΤΙΚΟ\"\n  STR_FIRESTORM: \"FIRESTORM\"\n  STR_UFO: \"ΑΤΙΑ\"\n  STR_STINGRAY: \"STINGRAY\"\n  STR_AVALANCHE: \"ΧΙΟΝΟΣΤΙΒΑΔΑ\"\n  STR_CANNON_UC: \"ΚΑΝΟΝΙ\"\n  STR_FUSION_BALL_UC: \"ΣΦΑΙΡΑ ΣΥΝΤΗΞΗΣ\"\n  STR_LASER_CANNON_UC: \"ΚΑΝΟΝΙ ΛΕΙΖΕΡ\"\n  STR_PLASMA_BEAM_UC: \"Ακτίνα Πλάσματος\"\n  STR_DAMAGE_CAPACITY: \"Ανοχή Ζημίας\"\n  STR_WEAPON_POWER: \"Δύναμη Όπλου\"\n  STR_WEAPON_RANGE: \"Εμβέλεια Όπλου\"\n  STR_ACCESS_LIFT: \"Ανελκυστήρας Πρόσβασης\"\n  STR_LABORATORY: \"Εργαστήριο\"\n  STR_WORKSHOP: \"Μηχανουργείο\"\n  STR_SMALL_RADAR_SYSTEM: \"Μικρό Σύστημα Ραντάρ\"\n  STR_LARGE_RADAR_SYSTEM: \"Μεγάλο Σύστημα Ραντάρ\"\n  STR_MISSILE_DEFENSES: \"Άμυνες Πυραύλων\"\n  STR_GENERAL_STORES: \"Γενικές Αποθήκες\"\n  STR_ALIEN_CONTAINMENT: \"Μονάδα Περιορισμού Εξωγήινων\"\n  STR_LASER_DEFENSES: \"Άμυνες Λέιζερ\"\n  STR_PLASMA_DEFENSES: \"Άμυνες Πλάσμα\"\n  STR_FUSION_BALL_DEFENSES: \"Άμυνες Σφαιρών Σύντηξης\"\n  STR_PSIONIC_LABORATORY: \"Ψυονικό Εργαστήριο\"\n  STR_HYPER_WAVE_DECODER: \"Υπερκυματικός Αποκωδικοποιητής\"\n  STR_HANGAR: \"Υπόστεγο\"\n  STR_USA: \"ΗΠΑ\"\n  STR_RUSSIA: \"ΡΩΣΙΑ\"\n  STR_UK: \"ΗΒ\"\n  STR_FRANCE: \"ΓΑΛΛΙΑ\"\n  STR_GERMANY: \"ΓΕΡΜΑΝΙΑ\"\n  STR_ITALY: \"ΙΤΑΛΙΑ\"\n  STR_SPAIN: \"ΙΣΠΑΝΙΑ\"\n  STR_CHINA: \"ΚΙΝΑ\"\n  STR_JAPAN: \"ΙΑΠΩΝΙΑ\"\n  STR_INDIA: \"ΙΝΔΙΑ\"\n  STR_BRAZIL: \"ΒΡΑΖΙΛΙΑ\"\n  STR_AUSTRALIA: \"ΑΥΣΤΡΑΛΙΑ\"\n  STR_NIGERIA: \"ΝΙΓΗΡΙΑ\"\n  STR_SOUTH_AFRICA: \"ΝΟΤΙΑ ΑΦΡΙΚΗ\"\n  STR_EGYPT: \"ΑΙΓΥΠΤΟΣ\"\n  STR_CANADA: \"ΚΑΝΑΔΑΣ\"\n  STR_TANK: \"Άρμα\"\n  STR_CIVILIAN: \"Πολίτης\"\n  STR_JAN: \"Ιαν\"\n  STR_FEB: \"Φεβ\"\n  STR_MAR: \"Μαρ\"\n  STR_APR: \"Απρ\"\n  STR_MAY: \"Μαΐος\"\n  STR_JUN: \"Ιουν\"\n  STR_JUL: \"Ιουλ\"\n  STR_AUG: \"Αυγ\"\n  STR_SEP: \"Σεπτ\"\n  STR_OCT: \"Οκτ\"\n  STR_NOV: \"Νοεμ\"\n  STR_DEC: \"Δεκ\"\n  STR_INTERNATIONAL_RELATIONS: \"Διεθνείς Σχέσεις\"\n  STR_COUNTRY: \"Χώρα\"\n  STR_FUNDING: \"Χρηματοδότηση\"\n  STR_CHANGE: \"Αλλαγή\"\n  STR_WEAPON_SYSTEMS: \"ΟΠΛΙΚΑ ΣΥΣΤΗΜΑΤΑ\"\n  STR_HWPS: \"ΕΒΟ\"\n  STR_DAMAGE_UC_: \"ΖΗΜΙΑ>{ALT}{0}\"\n  STR_ACCESS_LIFT_UFOPEDIA: \"Ο ανελκυστήρας πρόσβασης επιτρέπει τον εξοπλισμό και το προσωπικό που πρόκειται να μεταφερθεί μέσα ή έξω από μια υπόγεια βάση. Είναι πάντα η πρώτη μονάδα που θα κατασκευαστεί σε μια νέα τοποθεσία. Η περιοχή ανελκυστήρα είναι ευάλωτη στην εισβολή από την οποιαδήποτε πιθανή εχθρική δύναμη.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Κάθε κοιτώνας έχει χώρο για 50 άτομα. Οι εγκαταστάσεις ικανοποιούν βασικές ανάγκες σε ψυχαγωφία, φαγήτο και ανάπαυση.\"\n  STR_LABORATORY_UFOPEDIA: \"Έως 50 επιστήμονες μπορούν να εργαστούν σε ένα εργαστηριο. Τα εργαστήρια είναι εξοπλισμένα με την τελευταία λέξη της τεχνολογίας για έρευνα σε υλικά, βιοχημεία και την κοσμολογία. Υπάρχει προνομιακή πρόσβαση στα καλύτερα ερευνητικά εργαστήρια σε όλο τον κόσμο, συμπεριλαμβανομένων και στρατιωτικών εγκαταστάσεων.\"\n  STR_WORKSHOP_UFOPEDIA: \"Το μηχανουργείο περιέχει όλο τον εξοπλισμό που είναι απαραίτητος για την κατασκευή εξοπλισμού που βασίζεται σε σχέδια των εργαστηρίων. Μέχρι 50 μηχανικοί μπορούν να δουλέψουν σε ένα μηχανουργείο, αν και τα αντικείμενα υπό κατασκευή θα καταναλώνουν επίσης κάποιο χώρο.\"\n  STR_SMALL_RADAR_SYSTEM_UFOPEDIA: \"Ένα μικρό σύστημα ανίχνευσης έχει αποτελεσματικό εύρος ραντάρ 300 ναυτικών μιλίων και συνδέεται με δορυφορικά συστήματα για την αναζήτηση στο έδαφος. Κάθε σύστημα έχει 10% πιθανότητα ανίχνευσης ενός αντικειμένου μέσου μεγέθους κάθε 30 λεπτά.\"\n  STR_LARGE_RADAR_SYSTEM_UFOPEDIA: \"Ένα ευρύ σύστημα ανίχνευσης έχει αποτελεσματική εμβέλεια 450 ναυτικών μιλίων και είναι συνδεδεμένο με δορυφορικά συστήματα για αναζήτηση στο έδαφος. Κάθε σύστημα έχει 20% πιθανότητα να ανιχνεύει ένα μεσαίου μεγέθους αντικείμενο κάθε 30 λεπτά.\"\n  STR_MISSILE_DEFENSES_UFOPEDIA: \"Πυραύλοι παρέχουν κάποια προστασία κατά της εισβολής εχθρικών σκαφων που προσπαθούν να προσγειωθούν κοντά στη βάση.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"Όλος ο εξοπλισμός, οπλικά συστήματα, πυρομαχικά, ανακτημένα υλικά και οι Εξέδρες Βαρέων Όπλων τοποθετούνται σε αποθήκες, συμπεριλαμβανομένου και του εξοπλισμού που έχει ανατεθεί σε σκάφη σε υπόστεγα.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"Ζωντανοί εξωγήινοι πιθανότατα θα χρειάζονται ιδιαίτερα περιβάλλνοτα για να διατηρούνται εν ζωή. Η Εγκατάσταση Απομόνωσης μπορεί να διατηρεί έως 10 εξωγήινες μορφές ζωής σε αυτοσυντηρούμενες μονάδες.\"\n  STR_LASER_DEFENSES_UFOPEDIA: \"Οι άμυνες λέιζερ παρέχουν προστασία εναντίων εχθρικών σκάφων.\"\n  STR_PLASMA_DEFENSES_UFOPEDIA: \"Η άμυνα ακτίνων πλάσματος παρέχει ισχυρή και αποτελεσματική προστασία ενάντια σε επιδρομές απο εχθρικά σκάφη.\"\n  STR_FUSION_BALL_DEFENSES_UFOPEDIA: \"Βλήματα σύντηξης παρέχουν την πλέον αποτελεσματική άμυνα εναντίον ξένων επιθέσεων. Οι πύραυλοι αυτοί δημιουργούν μια κατάρρευση αντι-ύλης, που καταστρέφει τα πάντα που βρίσκονται σε συγκεκριμένη ακτίνα.\"\n  STR_GRAV_SHIELD_UFOPEDIA: \"Η ασπίδα βαρύτητας απωθεί εξωγήινα σκάφη που προσπαθούν να προσγειωθούν κοντά στη βάση για αρκετά μεγάλο χρονικό διάστημα ωστε όλα τα συστήματα άμυνας να ανασυγκροτηθουν. Στην πράξη αυτό θα διπλασιάσει την αποτελεσματικότητα των αμυντικών συστημάτων στη βάση σας.\"\n  STR_MIND_SHIELD_UFOPEDIA: \"Επειδή τα εξωγήινα σκάφη βασίζονται σε εγκεφαλικά κύματα για την ανίχνευση ανθρώπινης παρουσίας, το πιο αποτελεσματικό αντίμετρο είναι να προστατεύσετε τα εγκεφαλικά κύματα από τη βάση. Η διευκόλυνση αυτή θα μειώσει δραματικά τις πιθανότητες εντοπισμού από εξωγήινα διαστημόπλοια.\"\n  STR_PSIONIC_LABORATORY_UFOPEDIA: \"Το εργαστήριο psionics μπορεί να εκτιμήσει την psionic δυναμικό όλων των στρατιωτών στη βάση και να τους δώσει την απαραίτητη κατάρτιση για να χρησιμοποιήσουν τις ικανότητές τους psionic. Κάθε εργαστήριο μπορεί να εκπαιδεύσει έως δέκα στρατιώτες. Η εκπαίδευση κατανέμεται κατά το τέλος κάθε μήνα. Psionic δεξιότητες που χρησιμοποιούνται σε συνδυασμό με ένα Psi-ενισχυτή μπορεί να χρησιμοποιηθεί για psionic επιθέσεων κατά τη διάρκεια της μάχης.\"\n  STR_HYPER_WAVE_DECODER_UFOPEDIA: \"Οι εξωγήινες επικοινωνίες βασίζονται σε υπέρ-διαστατικά κύματα τα οποία ταξιδεύουν σχεδών στιγμαία. H εγκατάσταση αποκωδικοποιήσης συλλαμβάνει τις εξωγήινες εκπομπές και αποκοδικοποιεί τα δεδομένα. Αυτό μας πληροφορεί για το τύπο του ΑΤΙΑ, τη εξωγηίνη φυλή που το χειρίζεται, και το είδος της αποστολής που βρίσκεται. \"\n  STR_HANGAR_UFOPEDIA: \"Κάθε υπόστεγο μπορεί να φιλοξενήσει ένα σκάφος. Υπάρχουν εγκαταστάσεις για τη συντήρηση, τον ανεφοδιασμό και την επισκευή των σκαφών X-Com. Κάθε σκάφος που σταθμεύει σε μια βάση πρέπει να έχει ένα ελεύθερο υπόστεγο, το οποίο δεν μπορεί να χρησιμοποιηθεί από άλλα σκάφη, ακόμα κι αν το σκάφος που του έχει ανατεθεί βρίσκεται σε αποστολή.\"\n  STR_PISTOL_UFOPEDIA: \"Το πρότυπο πιστόλι στο XCOM είναι ένα υψηλής απόδοσης ημι-αυτόματο με χωρητικότητα 12 σφαιρων.\"\n  STR_RIFLE_UFOPEDIA: \"Αυτό το υψηλής ακρίβειας τυφέκιο ελεύθερου σκοπευτή κατευθύνεται με λέιζερ και παίρνει 6,7 χιλιοστών πυρομαχικά σε 20 στρογγυλά κλιπ.\"\n  STR_HEAVY_CANNON_UFOPEDIA: \"Το βαρύ κανόνι είναι ένα καταστροφικό, αλλά δυσκίνητο, όπλο. Η ευελιξία του προέρχεται από το γεγονός ότι μπορεί να πάρει τρεις τύπους πυρομαχικών - διατριτικό, εμπρηστικό και εκρηκτικό.\"\n  STR_AUTO_CANNON_UFOPEDIA: \"Το αυτόματο κανόνι συνδυάζει την ευελιξία και τη δύναμη του βαρέως κανονιού με ταχύτερο ρυθμό βολής.\"\n  STR_ROCKET_LAUNCHER_UFOPEDIA: \"Το ρουκετοβόλο είναι ένα σύστημα, κατευθυνόμενο με λέιζερ, που μπορεί να εκτοξεύσει τρία διαφορετικά μεγέθη πυραύλων.\"\n  STR_LASER_PISTOL_UFOPEDIA: \"Το πιστόλι laser είναι μια καλή εφαρμογή της νέας τεχνολογίας. Έχει τις ανέσεις ενός πιστολιού, μαζί με γρηγορότερα και ποιο εύστοχα πυρά.\"\n  STR_LASER_RIFLE_UFOPEDIA: \"Το τυφέκιο λέιζερ είναι μια πιο ισχυρή και ακριβή έκδοση του προηγούμενου σχεδιασμού πιστολιού.\"\n  STR_HEAVY_LASER_UFOPEDIA: \"Το βαρύ λέιζερ είναι δυσκίνιτο, αλλά εξαιρετικά αποτελεσματικό.\"\n  STR_GRENADE_UFOPEDIA: \"Η βασική χειροβομβίδα έχει έναν ακριβή και εξελιγμένο χρονοδιακόπτη για τον έλεγχο της.\"\n  STR_SMOKE_GRENADE_UFOPEDIA: \"Οι χειροβομβίδες καπνού είναι χρήσιμες για την παροχή κάλυψης σε εκτεθειμένες συνθήκες μάχης. Χρησιμοποιησέ τες με προσοχή καθώς μπορούν να ωφελήσουν και τον εχθρό.\"\n  STR_PROXIMITY_GRENADE_UFOPEDIA: \"Μια χειροβομβίδα εγγύτητας μπορεί να πεταχτεί σαν μια συνηθισμένη χειροβομβίδα, αλλά ενεργοποιείται από κοντά και μετά προσγειώνεται. Μεγάλη ικανότητα και φροντίδα απαιτείται για τη χρήση αυτών των συσκευών.\"\n  STR_HIGH_EXPLOSIVE_UFOPEDIA: \"Αυτό το εκρηκτικό θα πρέπει να χρησιμοποιείται μόνο γιά κατεδαφίσεις. Το προσωπικό πρέπει να κρατάει απόσταση ασφαλείας.\"\n  STR_MOTION_SCANNER_UFOPEDIA: \"Αυτή η εξελιγμένη συσκευή χρησιμοποιεί πληθώρα της ανιχνευτών και προηγμένων αλγορίθμων υπολογιστών για να αναγνωρίζουν κινούμενες μονάδες του εχθρού. Ωστόσο, αυτό απαιτεί κάποια πρακτική για αποτελεσματική χρήση. Κάντε κλικ στο εικονίδιο του σαρωτή κίνησης στην οθόνη τακτικής. Επιλέξτε \\\"Χρήση σαρωτή» από το μενού. Η οθόνη σαρωτή δείχνει ένα βέλος στο κέντρο, η οποία είναι η κατεύθυνση που ο στρατιώτης πολεμαει (Βόρρας είναι στην κορυφή). Οι μονάδες κηλίδων που αναβοσβήνουν δείχνουν οποιων έχουν μετακινηθεί πρόσφατα. Μεγάλες μονάδες, ή γρήγορη μετακίνηση μονάδων, θα παράγουν μεγαλύτερες σταγόνες. Στατικές μονάδες δεν θα πρέπει να ανιχνεύονται.\"\n  STR_MEDI_KIT_UFOPEDIA: \"Το Medi-κιτ συνδυάζει μια εγκατάσταση επούλωσης με αναλγητικά και διεγερτικά. Για να χρησιμοποιήσετε το Medi-κιτ θα πρέπει να στρέφεται προς τον στρατιώτη που απαιτεί θεραπεία. Αν ο στρατιώτης είναι ζαλισμένος θα πρέπει να σταθεί πάνω από το σώμα. Κάντε κλικ στο εικονίδιο Medi-kit και επιλέξτε «χρήση Medi-κιτ από το μενού. {} NEWLINE ΘΕΡΑΠΕΙΑ> Κόκκινα μέρη του σώματος δείχνουν θανατηφόρα τραύματα. Κάντε κλικ σε ένα μέρος του σώματος που τραυματίζεται. Κάντε κλικ στο κουμπί \\\"θεραπεύσει\\\". Ένα μοιραίο τραύμα θα θεραπευτεί και μερικοί υγεία αποκατασταθεί. {} NEWLINE διεγερτικό> Αυτό θα αποκαταστήσει την ενέργεια και αναγέννηση τις αισθήσεις του (ζαλισμένος) στρατιώτες. Για να αναβιώσει ο αναίσθητος στρατιώτης θα πρέπει να διακρίνεται ακριβώς πάνω από το σώμα. {} NEWLINE παυσίπονο> Αυτή η θα αποκαταστήσει το ηθικό των τραυματισμένων στρατιωτών μέχρι ποσότητα ισοδύναμη με έχασε την υγεία του στρατιώτη.\"\n  STR_PSI_AMP_UFOPEDIA: \"Ο ενισχυτής Psi μπορεί να χρησιμοποιηθεί μόνο από στρατιώτες με ψυχοθεραπευτική ικανότητα. Κατά τη διάρκεια της μάχης, κάντε κλικ στο Psi-amp, επιλέξτε τον τύπο της επίθεσης και επιλέξτε μια μονάδα στόχο με τον κέρσορα. Υπάρχουν δύο τύποι ψυχικής επίθεσης:{NEWLINE}ΜΟΝΑΔΑ ΠΑΝΙΚΟΥ> Εάν η επίθεση είναι επιτυχής, θα μειώσει το ηθικό του στόχου και μπορεί να του προκαλέσει πανικό.{NEWLINE}ΕΛΕΓΧΟΣ ΜΥΑΛΟΥ> Εάν αυτό είναι επιτυχές, θα αποκτήσετε άμεσο έλεγχο της εχθρική μονάδα σαν να ήταν μια δική σου. Είναι πιο δύσκολο να πετύχεις με αυτού του είδος επιθέσεις.\"\n  STR_STUN_ROD_UFOPEDIA: \"Αυτή η συσκευή μπορεί να χρησιμοποιηθεί μόνο σε μάχες, αλλά θα αναισθητοποιήσει έναν ζωντανό οργανισμό χωρίς να τον σκοτώσει χρησιμοποιώντας ηλεκτροσόκ.\"\n  STR_MIND_PROBE_UFOPEDIA: \"Ο ανιχνευτής μυαλού είναι μια συσκευή επικοινωνίας εξωγήινων που χρησιμοποιείται για τη λήψη πληροφοριών απευθείας από τα εγκεφαλικά κύματα. Οι μονάδες X-Com μπορούν να χρησιμοποιήσουν αυτήν τη συσκευή στη μάχη για να εμφανίσουν τα χαρακτηριστικά ενός εξωγήινου. Κάντε κλικ στον ανιχνευτή νου και στην επιλογή «χρήση». Στη συνέχεια, κάντε κλικ σε έναν εξωγήινο με τον κέρσορα.\"\n  STR_PLASMA_PISTOL_UFOPEDIA: \"Τα πιστόλια πλάσματος είναι ένα φονικό εξωγήινο όπλο που βασίζεται σε επιταχυνόμενα σωματίδια μέσα σε ένα λεπτό αντιβαρυτικό πεδίο.\"\n  STR_PLASMA_RIFLE_UFOPEDIA: \"Αυτό είναι ένα καταστροφικά ισχυρό όπλο που βασίζεται στην επιτάχυνση σωματιδίων μέσα από ένα μικροσκοπικό πεδίο αντι-βαρύτητας\"\n  STR_HEAVY_PLASMA_UFOPEDIA: \"Αυτό είναι ένα καταστροφικά ίσχυρο όπλο το οποίο βασίζεται στην επιτάχυνση σωματιδίων μέσα από ένα μικροσκοπικό αντι-βαρυτικό πεδίο.\"\n  STR_BLASTER_LAUNCHER_UFOPEDIA: \"Αυτός είναι ένας εξωγήινος εκτοξευτής κατευθυνόμενων πυραύλων που εκτοξεύει ισχυρές «βόμβες πυροδότησης». Όταν κάνετε κλικ για να πυροδοτήσετε το όπλο, θα δημιουργήσει «σημεία διαδρομής» για να ακολουθήσει η βόμβα εκρήξεων. Όταν έχετε τοποθετήσει αρκετά σημεία διαδρομής, κάντε κλικ στο ειδικό εικονίδιο εκκίνησης.\"\n  STR_SMALL_LAUNCHER_UFOPEDIA: \"Ένας μικρός εκτοξευτήρας που εκτοξέυει βόμβες ζάλης. Πολύ χρήσιμο για τη σύλληψη ζωντανών εξωγήινων.\"\n  STR_ALIEN_GRENADE_UFOPEDIA: \"Αυτή η συσκευή λειτουργεί με τον ίδιο τρόπο όπως μια χερσαία χειροβομβίδα - με τη διαφορά ότι είναι πιο ισχυρή.\"\n  STR_SMALL_SCOUT: \"Μικρό Αναγνωριστικό\"\n  STR_MEDIUM_SCOUT: \"Μεσαίο Αναγνωριστικό\"\n  STR_LARGE_SCOUT: \"Μεγάλο Αναγνωριστικό\"\n  STR_HARVESTER: \"Σκάφος Συγκομιδής\"\n  STR_ABDUCTOR: \"Απαγωγέας\"\n  STR_TERROR_SHIP: \"Σκάφος Τρόμου\"\n  STR_BATTLESHIP: \"Θωρυκτό\"\n  STR_SUPPLY_SHIP: \"Σκάφος Ανεφοδιασμού\"\n  STR_RATING: \"ΑΞΙΟΛΟΓΗΣΗ> {0}\"\n  STR_RATING_TERRIBLE: \"ΑΘΛΙΑ!\"\n  STR_RATING_POOR: \"ΦΤΩΧΑ!\"\n  STR_RATING_OK: \"ΟΚ\"\n  STR_RATING_GOOD: \"ΚΑΛΑ!\"\n  STR_RATING_EXCELLENT: \"ΑΡΙΣΤΑ!\"\n  STR_SCORE: \"ΠΟΝΤΟΙ\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"X-COM ΜΗΝΙΑΙΑ ΕΚΘΕΣΗ ΑΝΑΦΟΡΑΣ\"\n  STR_MONTH: \"Μήνας> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"Το συμβούλιο χρηματοδότησης των εθνών είναι γενικά ικανοποιημένο με την πρόοδό σου μέχρι τώρα.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"Το συμβούλιο χρηματοδότησης των εθνών είναι πολύ ικανοποιημένο με εξαιρετική πρόοδο σου. Συνεχίσε την καλή δουλειά.\"\n  STR_COUNCIL_IS_DISSATISFIED: \"Το συμβούλιο χρηματοδότησης των εθνών δεν είναι ικανοποιημένο με την απόδοσή σου. Πρέπει να βελτιώσεις την αποτελεσματικότητά σου στην αντιμετώπιση της εξωγήινη απειλή ή κινδυνεύεις με τον τερματισμό του προγράμματος.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"Δεν κατάφερες να αντιμετωπίσεις την εξωγήινη εισβολή και το συμβούλιο των χρηματοδοτικών εθνών αποφάσισε δυστυχώς να τερματίσει το πρόγραμμα. Κάθε έθνος θα αντιμετωπίσει το πρόβλημα κατά το δοκούν. Μπορούμε μόνο να ελπίζουμε οτι θα καταλήξουμε σε κάποιο συμβιβασμό με αυτές τις προφανώς εχθρικές δυνάμεις, και οτι ο γενικός πλυθησμός θα συμβιβαστεί με τους εξωγήινους επισκέπτες.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} είναι ιδιαίτερα ικανοποιημένη με την ικανότητά σου να αντιμετωπίσεις την τοπική απειλή και συμφώνησε να αυξήσει τη χρηματοδότησή της.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} είναι ιδιαίτερα ευχαριστημένοι με την πρόοδο στην αντιμετώπιση των τοπικών εξωγήινων εισβολών και συμφώνησαν να αυξήσουν τη χρηματοδότησή τους.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} και {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} είναι δυσαρεστημένη με την ικανότητά σου να αντιμετωπίσεις την εξωγήινη δραστηριότητα στην περιοχή της και αποφάσισε να μειώσει τη χρηματοδότησή της.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} είναι δυσαρεστημένοι με την ικανότητά σου να αντιμετωπίσεις την εξωγήινη δραστηριότητα στην περιοχή τους και αποφάσισαν να μειώσουν τη χρηματοδότησή τους.\"\n  STR_KNOTS: \"{0} κόμβοι\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} έχει υπογράψει μια μυστική συμφωνία με άγνωστες εξωγήινες δυνάμεις και αποσύρθηκε από το πρόγραμμα.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} έχουν υπογράψει μια μυστική συμφωνία με άγνωστες εξωγήινες δυνάμεις και αποσύρθηκαν από το πρόγραμμα.\"\n  STR_MONTHLY_RATING: \"Μηνιαία Βα8μολογία> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Αλλαγή χρηματοδότησης> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"Το Συμβουλίο χρηματοδότησης δεν είναι ευχαριστημένο με την οικονομική σου θέση. Πρέπει να μειώσεις τα χρέη κάτω από $1 εκατ. ή το πρόγραμμα θα τερματιστεί.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"ΥΠΕΡΚΥΜΑΤΙΚΕΣ ΕΠΙΚΟΙΝΩΝΙΕΣ ΑΠΟΚΩΔΙΚΟΠΟΙΗΘΗΚΑΝ\"\n  STR_CRAFT_TYPE: \"ΤΥΠΟΣ ΣΚΑΦΟΥΣ\"\n  STR_RACE: \"ΦΥΛΗ\"\n  STR_MISSION: \"ΑΠΟΣΤΟΛΗ\"\n  STR_ZONE: \"ΖΩΝΗ\"\n  STR_ALLOCATE_RESEARCH: \"Κατανομή Έρευνας\"\n  STR_ALLOCATE_MANUFACTURE: \"Κατανομή  Παραγωγής\"\n  STR_NEW_YORK: \"Νέα Υόρκη\"\n  STR_WASHINGTON: \"Ουάσινγκτον\"\n  STR_LOS_ANGELES: \"Λος Άντζελες\"\n  STR_MONTREAL: \"Μοντρεάλ\"\n  STR_HAVANA: \"Αβάνα\"\n  STR_MEXICO_CITY: \"Πόλη του Μεξικό\"\n  STR_CHICAGO: \"Σικάγο\"\n  STR_VANCOUVER: \"Βανκούβερ\"\n  STR_DALLAS: \"Ντάλας\"\n  STR_BRASILIA: \"Μπρασίλια\"\n  STR_BOGOTA: \"Μπογκοτά\"\n  STR_BUENOS_AIRES: \"Μπουένος Άιρες \"\n  STR_SANTIAGO: \"Σαντιάγκο\"\n  STR_RIO_DE_JANEIRO: \"Ρίο ντε Τζανέιρο\"\n  STR_LIMA: \"Λίμα\"\n  STR_CARACAS: \"Καράκας\"\n  STR_LONDON: \"Λονδίνο\"\n  STR_PARIS: \"Παρίσι\"\n  STR_BERLIN: \"Βερολίνο\"\n  STR_MOSCOW: \"Μόσχα\"\n  STR_ROME: \"Ρώμη\"\n  STR_MADRID: \"Μαδρίτη\"\n  STR_BUDAPEST: \"Βουδαπέστη\"\n  STR_LAGOS: \"Λάγος\"\n  STR_CAIRO: \"Κάϊρο\"\n  STR_CASABLANCA: \"Καζαμπλάνκα\"\n  STR_PRETORIA: \"Πρετόρια\"\n  STR_NAIROBI: \"Ναϊρόμπι\"\n  STR_CAPE_TOWN: \"Κέιπ Τάουν\"\n  STR_KINSHASA: \"Κινσάσα\"\n  STR_ANKARA: \"Άγκυρα\"\n  STR_DELHI: \"Δελχί\"\n  STR_KARACHI: \"Καράχι\"\n  STR_BAGHDAD: \"Βαγδάτη\"\n  STR_TEHRAN: \"Τεχεράνη\"\n  STR_BOMBAY: \"Βομβάη\"\n  STR_CALCUTTA: \"Καλκούτα\"\n  STR_TOKYO: \"Τόκιο\"\n  STR_BEIJING: \"Πεκίνο\"\n  STR_BANGKOK: \"Μπανγκόκ\"\n  STR_MANILA: \"Μανίλα\"\n  STR_SEOUL: \"Σεούλ\"\n  STR_SINGAPORE: \"Σινγκαπούρη\"\n  STR_JAKARTA: \"Τζακάρτα\"\n  STR_SHANGHAI: \"Σαγκάη\"\n  STR_HONG_KONG: \"Χονγκ Κονγκ\"\n  STR_NOVOSIBIRSK: \"Νοβοσιμπίρσκ\"\n  STR_CANBERRA: \"Κανμπέρα\"\n  STR_WELLINGTON: \"Γουέλινγκτον\"\n  STR_MELBOURNE: \"Μελβούρνη\"\n  STR_PERTH: \"Περθ\"\n  STR_PSI_TRAINING: \"Εκπαίδευση Ψι\"\n  STR_PSIONIC_TRAINING: \"ΨΥΟΝΙΚΗ ΕΞΑΣΚΗΣΗ\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Διαθέσιμος χώρος Ψ-Εργ.> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"Ψυονική{NEWLINE}Δύναμη\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"Ψυονική Ικανότ.{NEWLINE}/Βελτιώση\"\n  STR_PSI_AMP: \"Ψυχ-Εν\"\n  STR_IN_TRAINING: \"Σε{NEWLINE}Εξάσκηση;\"\n  STR_TARGETTED_BY: \"ΣΤΟΧΕΥΜΕΝΟ ΑΠΟ:\"\n  STR_WEAPONS_CREW_HWPS: \"ΟΠΛΑ/{NEWLINE}ΠΛΗΡΩΜΑ/ΕΒΟ\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"έχει χαμήλα καύσιμα,{NEWLINE}επιστροφή στη βάση\"\n  STR_SOLDIER_LIST: \"Λίστα Στρατιωτών\"\n  STR_RANK_: \"ΒΑΘΜΙΔΑ> {ALT}{0}\"\n  STR_MISSIONS: \"ΑΠΟΣΤΟΛΕΣ> {ALT}{0}\"\n  STR_KILLS: \"ΘΑΝΑΤΟΙ> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"ΑΝΑΡΡΩΣΗ ΤΡΑΥΜΑΤΩΝ> {ALT}{0}\"\n  STR_TIME_UNITS: \"ΜΟΝΑΔΕΣ ΧΡΟΝΟΥ\"\n  STR_STAMINA: \"ΑΝΤΟΧΗ\"\n  STR_HEALTH: \"ΥΓΕΙΑ\"\n  STR_BRAVERY: \"ΘΑΡΡΟΣ\"\n  STR_REACTIONS: \"ΑΝΤΙΔΡΑΣΕΙΣ\"\n  STR_FIRING_ACCURACY: \"ΕΥΣΤΟΧΙΑ ΒΟΛΗΣ\"\n  STR_THROWING_ACCURACY: \"ΕΥΣΤΟΧΙΑ ΡΙΨΗΣ\"\n  STR_STRENGTH: \"ΔΥΝΑΜΗ\"\n  STR_PSIONIC_STRENGTH: \"ΨΥΟΝΙΚΗ ΔΥΝΑΜΗ\"\n  STR_PSIONIC_SKILL: \"ΨΥΟΝΙΚΗ ΙΚΑΝΟΤΗΤΑ\"\n  STR_NEW_RANK: \"ΝΕΑ ΒΑΘΜΙΔΑ\"\n  STR_PROMOTIONS: \"Προαγωγές\"\n  STR_SOLDIERS_UC: \"ΣΤΡΑΤΙΩΤΕΣ\"\n  STR_TANK_CANNON_UFOPEDIA: \"Οι αυτοματοποιημένες πλατφόρμες βαρέων όπλων έχουν σχεδιαστεί για να συμπληρώνουν μια ομάδα X-Com. Ο συνδυασμός υψηλής ισχύος πυρός και ισχυρής θωράκισης καθιστά αυτές τις μονάδες πολύτιμες για μάχες σε ανοιχτό περιβάλον. Βεβαιωθείτε ότι υπάρχουν επαρκείς οβίδες στα αποθέματά σας για να επανοπλίσετε τα άρματα μάχης. Οπλίζονται αυτόματα όταν τους εκχωρείτε σε μια ομάδα.\"\n  STR_TANK_ROCKET_LAUNCHER_UFOPEDIA: \"Αυτή η αυτοματοποιημένη εξέδρα βαρέων όπλων είναι οπλισμένη με ισχυρές ρουκέτες, καταστροφικές για κάθε εξωγήινο εχθρό. Βεβαιωθείτε ότι οι αποθήκες διατηρούν απόθεμα ρουκετών ΕΒΟ.\"\n  STR_TANK_LASER_CANNON_UFOPEDIA: \"Τα όπλα λέιζερ είναι μια χρήσιμη προσθήκη στις ΕΒΟ. Συνδυάζουν βαριά δύναμη πυρός χωρίς περιορισμούς πυρομαχικών.\"\n  STR_HOVERTANK_PLASMA_UFOPEDIA: \"Η εξωγήινη τεχνολογία έχει δώσει στις ΕΒΟ μια νέα επέκταση ζωής. Η προστιθέμενη ευελιξία της πτήσης και η δύναμη πυρός του πλάσματος είναι ένας θανατηφόρος συνδυασμός.\"\n  STR_HOVERTANK_LAUNCHER_UFOPEDIA: \"Αυτό το ιπτάμενο άρμα έχει έναν εκτοξευτή σφαιρών σύντηξης που είναι ικανός για τεράστια καταστροφή. Χρησιμοποιήσε το με μεγάλη προσοχή. Θα πρέπει να κατασκευάσεις τις σφαίρες σύντηξης για να εξοπλήσεις αυτά τα ΕΒΟ. Οι σφαίρες σύντηξης είναι έξυπνα κατευθυνόμενα όπλα. Για να πυροβολήσεις επιλέξετε έναν αριθμό από «σημεία διαδρομής» με τον κέρσορα και στη συνέχεια πάτα στο εικονίδιο εκτόξευσης της σφαίρας σύντηξης.\"\n  STR_HEAVY_PLASMA_CLIP_UFOPEDIA: \"Αυτή η συμπαγής συσκευή χρησιμοποιείται ως πυρομαχικά για το όπλο βαρέως πλάσματος. Περιέχει μια μικρή ποσότητα Ελέριουμ.\"\n  STR_PLASMA_RIFLE_CLIP_UFOPEDIA: \"Αυτό το μικρό αντικείμενο χρησιμοποιείται ως πηγή ενέργειας για το τυφέκιο πλάσμα - ένα μεσέας δύναμης εξωγήινο όπλο. Περιέχει μια μικρή ποσότητα Ελέριουμ.\"\n  STR_PLASMA_PISTOL_CLIP_UFOPEDIA: \"Πηγή ενέργειας για το μικρό εξωγήινο πιστόλι πλάσματος. Περιέχει Ελέριουμ - τη πηγή όλης της εξωγήινης δύναμης.\"\n  STR_STUN_BOMB_UFOPEDIA: \"Η βόμβα αναισθητοποίησης χρησιμοποιείται για τη σύλληψη ζωντανών δειγμάτων ανθρώπου, αλλά μπορεί επίσης να χρησιμοποιηθεί ενάντια στις περισσότερες εξωγήινες φυλές. Εκτοξεύεται από Μικρό Εκτοξευτή.\"\n  STR_ALIEN_RESEARCH_UFOPEDIA: \"Η αποστολή εξωγήινης έρευνας χρησιμοποιείται για τη συλλογή βασικών δεδομένων για τη γη και τους κατοίκους της. Τα μικρά οχήματα χρησιμοποιούνται κατά κύριο λόγο, με περιστασιακές προσγειώσεις σε ερημικές περιοχές. Αυτός ο τύπος εξωγήινης δραστηριότητας αποτελεί την ελάχιστη απειλή για την X-Com, με ελάχιστη ανησυχία από τις κυβερνήσεις ή το κοινό.\"\n  STR_ALIEN_HARVEST_UFOPEDIA: \"Οι εξωγήινοι έχουν πολλές χρήσεις για την πανίδα της γης. Τα ζώα απάγονται κρυφά και επιστρέφονται με διάφορα όργανα που έχουν αφαιρεθεί. Οι ακρωτηριασμοί των βοοειδών αναφέρθηκαν κατά κύριο λόγο μαζί με τις εμφανίσεις UFO. Αυτός ο τύπος εξωγήινης δραστηριότητας προκαλεί μεγάλη ανησυχία για τις κυβερνήσεις και σημαντική ανησυχία μεταξύ του πληθυσμού. Αυτός ο τύπος δραστηριότητας συμβαίνει κυρίως στη γεωργική γη. Η θεωρία πίσω από την «εξωγήινη συγκομιδή» υποδηλώνει ότι οι εξωγήινες φυλές αρχικά «σπείραν» τον πλανήτη με τη χλωρίδα και την πανίδα και τώρα έχουν επιστρέψει για να καρπωθούν τη συγκομιδή που έχουν σπείρει.\"\n  STR_ALIEN_ABDUCTION_UFOPEDIA: \"Αυτή είναι η πιο ύπουλη μορφή εξωγήινης δραστηριότητας. Η απαγωγή από εξωγήινους αναφέρεται ευρέως, παρά τις προσπάθειες των εξωγήινων να σβήσουν την εμπειρία από τις μνήμες των θυμάτων τους. Οι απαχθέντες αναφέρουν ότι υποβλήθηκαν σε εξευτελιστικές σωματικές εξετάσεις, συμπεριλαμβανομένου εμποτισμού εξωγήινων εμβρύων και περίεργων γενετικών πειραμάτων. Ο σκοπός πίσω από αυτή τη δραστηριότητα φαίνεται να συνδέεται με τη γενετική μετάλλαξη και τον χειρισμό του γενετικού υλικού των εξωγήινων. Αυτή η δραστηριότητα προκαλεί μεγάλη ανησυχία και εμφανίζεται σε κατοικημένες περιοχές ή πόλεις\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"Οι κυβερνήσεις της γης μπορούν να διεισδυθούν από εξωγήινους πράκτορες που είναι ανθρώπινοι σε εμφάνιση. Αυτό μπορεί να οδηγήσει σε επίσημη επαφή μεταξύ εξωγήινων και κυβερνήσεων στο υψηλότερο επίπεδο. Η κορύφωση αυτής της δραστηριότητας χαρακτηρίζεται από έντονη δραστηριότητα UFO κοντά σε μεγάλες πόλεις. Οι εξωγήινοι θα προσπαθήσουν να υπογράψουν ένα σύμφωνο με μια κυβέρνηση της γης προσφέροντας γνώση της ανώτερης τεχνολογίας τους. Σε αντάλλαγμα, η κυβέρνηση θα επιτρέψει στους εξωγήινους να ασκήσουν τη δραστηριότητά τους ανεμπόδιστα. Αυτή η εξωγήινη αποστολή αντιπροσωπεύει τη χειρότερη απειλή για την X-Com. Αν έρθει σε συμφωνία μια κυβέρνηση με τους εξωγήινους, τότε η χρηματοδότηση της θα σταματήσει.\"\n  STR_ALIEN_BASE_UFOPEDIA: \"Οι εξωγήινοι θα κατασκευάσουν μυστικές υπόγειες βάσεις σε απομακρυσμένες τοποθεσίες. Μετά από μερικές αρχικές αναγνωριστικές πτήσεις θα εμφανιστεί κάποια έντονη δραστηριότητα UFO καθώς θα κατασκευάζεται η βάση. Αυτές οι βάσεις είναι γνωστό ότι περιέχουν πειραματικά εργαστήρια για ανθρώπους απαχθέντες και προμήθειες για περαιτέρω δραστηριότητα στην περιοχή. Η παρουσία βάσεων εξωγήινων θα δημιουργήσει μια μεγάλη ποσότητα αναφερόμενης εξωγήινης δραστηριότητας χωρίς την παρουσία UFO. Για να εντοπίσει μια βάση, ένα σκάφος X-Com πρέπει να περιπολεί μια περιοχή για μερικές ώρες για να έχει κάποιες πιθανότητες εντοπισμού.\"\n  STR_ALIEN_TERROR_UFOPEDIA: \"Όταν οι εξωγήινοι τρομοκρατούν μια πόλη, θα αναπτύξουν μερικές ειδικές δυνάμεις με τρομερή ισχύ. Οι άμαχοι θα απειληθούν άμεσα και οι κυβερνήσεις θα αναγκαστούν να εκκενώσουν ολόκληρες περιοχές. Ο κύριος σκοπός πίσω από αυτή τη δραστηριότητα είναι να δημιουργήσει επαρκή δημόσια υστερία, έτσι ώστε οι κυβερνήσεις να απειλήσουν το έργο της X-Com.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"Εάν οι αναχαιτιστές X-Com είναι ιδιαίτερα επιτυχείς στην κατάρριψη UFO, τότε οι εξωγήινοι ενδέχεται να λάβουν κάποια αντίποινα. Αυτό θα μπορούσε να οδηγήσει σε άμεση επίθεση εναντίον μιας βάσης X-Com. Ωστόσο, οι εξωγήινοι πρέπει να βρουν μια βάση X-Com για να της επιτεθούν, και εφόσον τα UFO κρατηθούν μακριά, τότε θα υπάρχει μικρός κίνδυνος επίθεσης.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"Μόλις κατασκευαστεί μια βάση εξωγήινων, ανεφοδιάζεται σε τακτική βάση από ένα ειδικό σκάφος ανεφοδιασμού. Εάν ένα από αυτά τα σκάφη εντοπιστεί κατά την προσγείωση, τότε είναι βέβαιο ότι υπάρχει μια βάση εξωγήινων κοντά.\"\n  STR_SMALL_SCOUT_UFOPEDIA: \"Αυτό το μικρό σκάφος κυρίως χρησιμοποιείται για αναγνώριση ή έρευνα. Προηγείται συνήθως μεγαλυτέρων σκαφών στην αρχή μίας εξωγήινης αποστολής.\"\n  STR_MEDIUM_SCOUT_UFOPEDIA: \"Ένα μεσαίου μεγέθους αναγνωριστικό που συνιστά μικρή απειλή για τις γήινες δυνάμεις. Κανονικά εμφανίζεται πριν από μεγαλύτερα σκάφη κατά τη διάρκεια των αποστολών.\"\n  STR_LARGE_SCOUT_UFOPEDIA: \"Το μεγαλύτερο εξωγήινο αναγνωριστικό είναι γενικού σκοπού σκάφος που χρησιμοποιείται σε όλους τους τύπους των εξωγήινων αποστολών.\"\n  STR_HARVESTER_UFOPEDIA: \"Το σκάφος συγκομιδής έχει μια καταπακτή στη βάση του και είναι εξοπλισμένο με ανυψωτικούς μηχανισμούς για να μεταφέρει βοοειδή ή άλλα ζώα. Κόπτες λέιζερ χρησιμοποιούνται για να εξάγουν τα επιθυμητά μέρη και το κουφάρι πετιέται στο έδαφος. Επίσης υπάρχουν δοχεία αποθήκευσης για μέρη από σώματα.\"\n  STR_ABDUCTOR_UFOPEDIA: \"Αυτό το σκάφος είναι εξοπλισμένο με μια αίθουσα εξέτασης για την πραγματοποίηση φρικτών πειραμάτων σε ανθρώπινα υποκείμενα. Το θύμα συνήθως παραλύει από τηλεπαθητικές δυνάμεις, αλλά διατηρεί τις αισθήσεις του ενώ βρίσκεται στο χειρουργικό τραπέζι.\"\n  STR_TERROR_SHIP_UFOPEDIA: \"Το πλοίο τρόμου έχει μια εγκατάσταση περιορισμού για μεγάλα όπλα ή πλάσματα εξωγήινων τρομοκρατών. Χρησιμοποιείται για να μεταφέρει αυτούς τους εξωγήινους τρομοκράτες σε κατοικημένες περιοχές.\"\n  STR_BATTLESHIP_UFOPEDIA: \"Το θωρηκτό διαστημόπλοιο είναι το μεγαλύτερο και πιο ισχυρό σκάφος εξωγήινων. Είναι συνήθως το κύριο σκάφος αποστολής εξωγήινων, εξοπλισμένο με ισχυρά όπλα και πολλά μέλη πληρώματος.\"\n  STR_SUPPLY_SHIP_UFOPEDIA: \"Το σκάφος εφοδιασμού χρησιμοποιείται κατά τη διάρκεια κατασκευής εξωγήινων βάσεων ή για τον εφοδιασμό υφιστάμενων. Μεταφέρει εξωγήινα δοχεία τροφίμων και θαλάμους αναπαραγωγής.\"\n  STR_DISMANTLE: \"Διάλυση\"\n  STR_FACILITY_IN_USE: \"ΕΓΚΑΤΑΣΤΑΣΗ ΣΕ ΧΡΗΣΗ\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"ΑΔΥΝΑΜΙΑ ΔΙΑΛΥΣΗΣ ΕΓΚΑΤΑΣΤΑΣΗΣ!{SMALLLINE}Όλες οι εγκαταστάσεις στη βάση πρέπει να συνδέονται με τον ανελκυστήρα πρόσβασης.\"\n  STR_TRANSFER_ITEMS_TO: \"Μεταφορά Αντικειμένου σε {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"ΔΕΝ ΥΠΑΡΧΕΙ ΜΟΝΑΔΑ ΠΕΡΙΟΡΙΣΜΟΥ ΕΞΩΓΗΙΝΩΝ ΓΙΑ ΜΕΤΑΦΟΡΑ!{SMALLLINE}Οι ζωντανοί εξωγήινοι χρειάζονται μονάδα περιορισμού για να επιβιώσουν.\"\n  STR_AMOUNT_AT_DESTINATION: \"ΠΟΣΟΤΗΤΑ{NEWLINE}ΠΡΟΟΡΙΣΜΟY\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"Εξωγήινος πέθανε καθώς δεν υπάρχει μονάδα περιορισμού εξωγήινων\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"ΑΝΕΠΑΡΚΕΙΣ ΧΩΡΟΣ ΔΙΑΜΟΝΗΣ{SMALLLINE}Η βάση προορισμού δεν έχει αρκετό χώρο στους κοιτώνες για το πλήρωμα που έχει ανατεθεί στο σκάφος.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"ΑΝΕΠΑΡΚΕΙΣ ΑΠΟΘΗΚΕΥΤΙΚΟΣ ΧΟΡΟΣ!{SMALLLINE}Η βάση προορισμού δεν έχει αρκετό αποθηκευτικό χώρο για τον εξοπλισμό που έχει εκχωρηθεί στο σκάφος.\"\n  STR_ITEMS_ARRIVING: \"Άφηση Αντικειμένων\"\n  STR_DESTINATION_UC: \"ΠΡΟΟΡΙΣΜΟΣ\"\n  STR_PISTOL: \"Πιστόλι\"\n  STR_PISTOL_CLIP: \"Γεμιστήρας Πιστολιού\"\n  STR_RIFLE: \"Τυφέκιο\"\n  STR_RIFLE_CLIP: \"Γεμιστήρας Τυφεκιού\"\n  STR_HEAVY_CANNON: \"Βαρύ Κανόνι\"\n  STR_HC_AP_AMMO: \"ΥΤ-ΔΘ ΠΥΡ/ΚΑ\"\n  STR_HC_HE_AMMO: \"HC-HE Πυρομαχικό\"\n  STR_HC_I_AMMO: \"HC-I Πυρομαχικό\"\n  STR_AUTO_CANNON: \"Αυτόματο Κανόνι\"\n  STR_AC_AP_AMMO: \"ΑΚ-ΔΤ Πυρομαχικό\"\n  STR_AC_HE_AMMO: \"ΑΚ-ΥΕ Πυρομαχικό\"\n  STR_AC_I_AMMO: \"ΑΚ-ΕΜ Πυρομαχικό\"\n  STR_ROCKET_LAUNCHER: \"Ρουκετοβόλο\"\n  STR_SMALL_ROCKET: \"Μικρή Ρουκέτα\"\n  STR_LARGE_ROCKET: \"Μεγάλη Ρουκέτα\"\n  STR_INCENDIARY_ROCKET: \"Εμπρηστική Ρουκέτα\"\n  STR_GRENADE: \"Χειροβομβίδα\"\n  STR_SMOKE_GRENADE: \"Χειροβομβίδα Καπνού\"\n  STR_PROXIMITY_GRENADE: \"Χειροβομβίδα Εγγύτητας\"\n  STR_HIGH_EXPLOSIVE: \"Εκρηκτικό\"\n  STR_STUN_ROD: \"Ραβδί ακινητοποίησης\"\n  STR_HEAVY_PLASMA: \"Βαρύ όπλο πλάσματος\"\n  STR_HEAVY_PLASMA_CLIP: \"Γεμιστήρας βαρέου όπλου πλάσματος\"\n  STR_PLASMA_RIFLE: \"Τυφέκιο Πλάσματος\"\n  STR_PLASMA_RIFLE_CLIP: \"Γεμιστήρας Τυφεκίου Πλάσματος\"\n  STR_PLASMA_PISTOL: \"Πιστόλι Πλάσμα\"\n  STR_PLASMA_PISTOL_CLIP: \"Γεμιστήρας Πιστολιού Πλάσματος\"\n  STR_BLASTER_LAUNCHER: \"Εξωγηίνος εκτοξευτής\"\n  STR_BLASTER_BOMB: \"Blaster Bomb\"\n  STR_SMALL_LAUNCHER: \"Μικρός Εκτοξευτής\"\n  STR_STUN_BOMB: \"βόμβα αναισθησίας\"\n  STR_ALIEN_GRENADE: \"Εξωγήινη Χειροβομβίδα\"\n  STR_ELERIUM_115: \"Ελέριο-115\"\n  STR_MIND_PROBE: \"Διερευνητής Νου\"\n  STR_SECTOID_CORPSE: \"Πτώμα Σεκτόιντ\"\n  STR_SNAKEMAN_CORPSE: \"Πτώμα Φιδάνθρωπου\"\n  STR_ETHEREAL_CORPSE: \"Πτώμα Αιθέριου\"\n  STR_MUTON_CORPSE: \"Πτώμα Μάτον\"\n  STR_FLOATER_CORPSE: \"Πτώμα Αιωρητή\"\n  STR_CELATID_CORPSE: \"Πτώμα Celatid\"\n  STR_SILACOID_CORPSE: \"Πτώμα Σίλακοϊντ\"\n  STR_CHRYSSALID_CORPSE: \"Πτώμα Χρυσαλίδας\"\n  STR_REAPER_CORPSE: \"Πτώμα Θεριστή\"\n  STR_SECTOPOD_CORPSE: \"Πτώμα Sectopod\"\n  STR_CYBERDISC_CORPSE: \"πτώμα κυβερνοδίσκου\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"Δεν υπάρχουν αρκετά πυρομαχικά για τον οπλισμό HWP{SMALLLINE}Κάθε HWP απαιτεί {0} {1}.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Ανεπαρκή εφόδια για πλήρη ανεφοδιασμό ομάδας\"\n  STR_MARS_CYDONIA_LANDING: \"Άρης: Προσγείωση στην Κυδώνια\"\n  STR_MARS_CYDONIA_LANDING_BRIEFING: \"Το σκάφος σας Avenger προσγειώθηκε στην περιοχή της Κυδωνίας στην επιφάνεια του Άρη. Οι πληροφορίες μας αναφέρουν ότι μία από τις πυραμίδες περιέχει έναν πράσινο ανελκυστήρα πρόσβασης σε ένα υπόγειο συγκρότημα. Αφού συγκεντρώσετε όλους τους στρατιώτες σας στην περιοχή του ανελκυστήρα, κάντε κλικ στο εικονίδιο «ακύρωση αποστολής» για να συνεχίσετε στο επόμενο στάδιο.\"\n  STR_MARS_THE_FINAL_ASSAULT: \"Άρης: Η Τελική Επίθεση\"\n  STR_MARS_THE_FINAL_ASSAULT_BRIEFING: \"Ο ανελκυστήρας πυραμίδας οδηγεί τους κουρασμένους στρατιώτες σας βαθιά κάτω από την επιφάνεια του πλανήτη. Φτάνουν στην καρδιά ενός μεγάλου συγκροτήματος τούνελ και θαλάμων. Ο εγκέφαλος των εξωγήινων είναι κρυμμένος κάπου στον λαβύρινθο. Πρέπει να καταστραφεί για να σωθεί η γη από την εξωγήινη υποδούλωση.{NEWLINE}{NEWLINE}Καλή τύχη!\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Πρέπει να ερευνήσεις {NEWLINE}{0}{NEWLINE} προκειμένου να παράγεις {NEWLINE}{1}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"Οι εξωγήινοι κατέστρεψαν την απροστάτευτη βάση {0}\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"Οι πράκτορες της X-Com εντόπισαν μια βάση εξωγήινων στο {0}\"\n  STR_STANDOFF: \"ΚΡΑΤΑ ΑΠΟΣΤΑΣΗ\"\n  STR_CAUTIOUS_ATTACK: \"ΠΡΟΣΕΚΤΙΚΗ ΕΠΙΘΕΣΗ\"\n  STR_STANDARD_ATTACK: \"ΚΑΝΟΝΙΚΗ ΕΠΙΘΕΣΗ\"\n  STR_AGGRESSIVE_ATTACK: \"ΔΥΝΑΜΙΚΗ ΕΠΙΘΕΣΗ\"\n  STR_DISENGAGING: \"ΑΠΕΜΠΛΟΚΗ\"\n  STR_UFO_HIT: \"ΑΤΙΑ ΧΤΥΠΗΘΗΚΕ!\"\n  STR_UFO_CRASH_LANDS: \"ΤΟ ΑΤΙΑ ΣΥΝΕΤΡΙΒΗ!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Σμίκρυνση μόνο όταν Κρατάς Απόσταση\"\n  STR_UFO_RETURN_FIRE: \"ΤΟ ΑΤΙΑ ΑΝΤΑΠΩΔΙΔΕΙ ΠΥΡΑ!\"\n  STR_INTERCEPTOR_DAMAGED: \">> ΤΟ ΑΝΑΧΑΙΤΙΣΤΙΚΟ ΧΤΥΠΗΘΗΚΕ <<\"\n  STR_INTERCEPTOR_DESTROYED: \">> ΑΝΑΧΑΙΤΙΣΤΙΚΟ ΚΑΤΑΣΤΡΑΦΗΚΕ <<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"ΤΟ ΑΤΙΑ ΞΕΦΥΓΕ ΑΠΟ ΤΟ ΑΝΑΧΑΙΤΙΣΤΙΚΟ!\"\n  STR_ALIENS_TERRORISE: \"ΟΙ ΕΞΩΓΗΙΝΟΙ ΤΡΟΜΟΚΡΑΤΟΥΝ\"\n  STR_LONG_RANGE_DETECTION: \"Ανίχνευση Μεγάλης Εμβ.\"\n  STR_STORES_UC: \"ΑΠΟΘΗΚΕΣ\"\n  STR_DIFFICULTY_LEVEL: \"Επίπεδο Δυσκολίας\"\n  STR_INTERCEPT: \"ΑΝΑΧΑΙΤΙΣΕ\"\n  STR_BASES: \"ΒΑΣΕΙΣ\"\n  STR_GRAPHS: \"ΓΡΑΦΙΜΑΤΑ\"\n  STR_UFOPAEDIA_UC: \"ΟΥΦΟΠΑΙΔΕΙΑ\"\n  STR_OPTIONS_UC: \"ΕΠΙΛΟΓΕΣ\"\n  STR_FUNDING_UC: \"ΧΡΗΜΑΤΟΔΟΤΗΣΗ\"\n  STR_5_SECONDS: \"5 δευτ.\"\n  STR_1_MINUTE: \"1 Λεπτό\"\n  STR_5_MINUTES: \"5 Λεπτ.\"\n  STR_30_MINUTES: \"30 Λεπ.\"\n  STR_1_HOUR: \"1 Ώρα\"\n  STR_1_DAY: \"1 Μέρα\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"Πίνακας Επίδοσης X-Com\"\n  STR_ENTER_NAME: \"Καταχώρηση Ονόματος\"\n  STR_PERFORMANCE_RATING: \"Αξιολόγηση Απόδοσης\"\n  STR_VICTORY_DATE: \"Ημερομηνία Νίκης\"\n  STR_ELECTRO_FLARE: \"Ηλεκτρική φωτοβολίδα\"\n  STR_ELECTRO_FLARE_UFOPEDIA: \"Αυτή η συμπαγής συσκευή παράγει ένα έντονο φως αναλαμπής όταν εκτοξεύεται. Αυτό θα φωτίσει τις εχθρικές μονάδες κοντά στην ηλεκτροφλόγα κατά τις νυχτερινές αποστολές.\"\n  STR_MONTHLY_COSTS: \"Μηνιαία Έξοδα\"\n  STR_CRAFT_RENTAL: \"Ενοίκια Σκαφών\"\n  STR_SALARIES: \"Μισθοί\"\n  STR_BASE_MAINTENANCE: \"Συντήρηση Βάσης\"\n  STR_COST_PER_UNIT: \"Κόστος/μονάδα\"\n  STR_QUANTITY: \"Ποσότητα\"\n  STR_TOTAL: \"Σύνολο\"\n  STR_IN_PSIONIC_TRAINING: \"Σε Ψυονική Εξάσκηση\"\n  STR_BLASTER_BOMB_UFOPEDIA: \"Η συσκευή αυτή είναι ένας πολύ ισχυρός πύραυλος με έξυπνο σύστημα καθοδήγησης. Εκτοξεύεται απο το εξωγήινο εκτοξευτή\"\n  STR_FRONT_ARMOR: \"Μπροστά Θωράκιση\"\n  STR_LEFT_ARMOR: \"Αριστερή Θωράκιση\"\n  STR_RIGHT_ARMOR: \"Δεξιά Θωράκιση\"\n  STR_REAR_ARMOR: \"Πίσω Θωράκιση\"\n  STR_UNDER_ARMOR: \"Κάτω Θωράκιση\"\n  STR_ROUNDS: \"Βολές\"\n  STR_UNIT: \"ΜΟΝΑΔΑ> {0}\"\n  STR_ENERGY: \"ΕΝΕΡΓΕΙΑ\"\n  STR_MORALE: \"ΗΘΙΚΟ\"\n  STR_ARMOR_: \"ΠΑΝΟΠΛΙΑ> {0}\"\n  STR_FRONT_ARMOR_UC: \"ΜΠΡΟΣΤΑ ΘΩΡΑΚΙΣΗ\"\n  STR_LEFT_ARMOR_UC: \"ΑΡΙΣΤΕΡΗ ΘΩΡΑΚΙΣΗ\"\n  STR_RIGHT_ARMOR_UC: \"ΔΕΞΙΑ ΘΩΡΑΚΙΣΗ\"\n  STR_REAR_ARMOR_UC: \"ΠΙΣΩ ΘΩΡΑΚΙΣΗ\"\n  STR_SKILLS: \"ΙΚΑΝΟΤΗΤΕΣ> {0}\"\n  STR_LEVEL: \"ΕΠΙΠΕΔΟ> {0}\"\n  STR_HEAD: \"ΚΕΦΑΛΗ\"\n  STR_TORSO: \"ΚΟΡΜΟΣ\"\n  STR_RIGHT_ARM: \"ΔΕΞΙ ΧΕΡΙ\"\n  STR_LEFT_ARM: \"ΑΡΙΣΤΕΡΟ ΧΕΡΙ\"\n  STR_RIGHT_LEG: \"ΔΕΞΙ ΠΟΔΙ\"\n  STR_LEFT_LEG: \"ΑΡΙΣΤΕΡΟ ΠΟΔΙ\"\n  STR_PAIN_KILLER: \"ΠΑΥΣΙΠΟΝΟ\"\n  STR_STIMULANT: \"ΔΙΕΓΕΡΤΙΚΟ\"\n  STR_HEAL: \"ΕΠΟΥΛΩΣΗ\"\n  STR_TIME_UNITS_SHORT: \"ΧΜ>{ALT}{0}\"\n  STR_WEIGHT: \"Βάρος>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"Αντιδρ.>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"Ψι.Ικαν>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"Ψι.Δυν>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Εξωγήινο Εύρημα\"\n  STR_AMMO_ROUNDS_LEFT: \"Πυρομαχικά:{NEWLINE}ROUNDS{NEWLINE}LEFT={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"ΠΟΝΟΣ>{ALT}{0}{ALT}{NEWLINE}ΕΝΕΣΗ>{ALT}{1}{ALT}{NEWLINE}ΙΑΣΗ>{ALT}{2}\"\n  STR_THROW: \"Ρήξε\"\n  STR_AUTO_SHOT: \"Αυτόματη Βολή\"\n  STR_SNAP_SHOT: \"Γρήγορη Βολή\"\n  STR_AIMED_SHOT: \"Στοχ/μένη Βολή\"\n  STR_STUN: \"Αναισθησία\"\n  STR_PRIME_GRENADE: \"Όπλισε Χειροβομβίδα\"\n  STR_USE_SCANNER: \"Χρήση Σαρωτή\"\n  STR_USE_MEDI_KIT: \"Χρήση Πρώτων Βοηθειών\"\n  STR_LAUNCH_MISSILE: \"Εκτόξευσε Πύραυλο\"\n  STR_ACCURACY_SHORT: \"Ευσ>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Ανεπαρκείς Μονάδες Χρόνου!\"\n  STR_NOT_ENOUGH_ENERGY: \"Ανεπαρκής Ενέργεια!\"\n  STR_NO_ROUNDS_LEFT: \"Χωρίς πυρομαχικά!\"\n  STR_NO_AMMUNITION_LOADED: \"Χωρίς Πυρομαχικά!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Λάθος Πυρομαχικό για αυτο το Όπλο!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"Το όπλο είναι ήδη γεμάτο!\"\n  STR_NO_LINE_OF_FIRE: \"Καμία Γραμμή Βολής!\"\n  STR_GRENADE_IS_ACTIVATED: \"Η χειροβομβίδα ενεργοποιήθηκε!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Η χειροβομβίδα απενεργοποιήθηκε!\"\n  STR_THERE_IS_NO_ONE_THERE: \"Δεν είναι κανείς εκεί!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Η χρήση εξωγήινων ευρημάτων είιναι αδύνατη προτού αναλυθούν!\"\n  STR_OUT_OF_RANGE: \"Εκτός Εμβέλειας!\"\n  STR_UNABLE_TO_THROW_HERE: \"Αδύνατο να ρίξει εκεί\"\n  STR_SET_TIMER: \"Θέσε χρονοδιακόπτη\"\n  STR_HIDDEN_MOVEMENT: \"ΚΡΥΦΕΣ ΚΙΝΗΣΕΙΣ\"\n  STR_TURN: \"ΓΥΡΟΣ> {0}\"\n  STR_SIDE: \"ΠΛΕΥΡΑ> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Πάτησε κουμπί για συνέχεια\"\n  STR_MIND_CONTROL: \"Έλεγχος Σκέψης\"\n  STR_PANIC_UNIT: \"Πανικόβλησε μονάδα\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Επίθεση κατά του Ηθικού Επιτυχής\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Επιτυχής Έλεγχος Σκέψης\"\n  STR_HAS_GONE_BERSERK_MALE: \"Ο/Η {0}{NEWLINE} τρελάθηκε\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"Ο/Η {0}{NEWLINE} τρελάθηκε\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}πανικοβληθηκε\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}πανικοβλήθηκε\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Εξωγήινοι\"\n  STR_RIGHT_HAND: \"ΔΕΞΙ ΧΕΡΙ\"\n  STR_LEFT_HAND: \"ΑΡΙΣΤΕΡΟ ΧΕΡΙ\"\n  STR_RIGHT_SHOULDER: \"ΔΕΞΙΟΣ ΩΜΟΣ\"\n  STR_LEFT_SHOULDER: \"ΑΡΙΣΤΕΡΟΣ ΩΜΟΣ\"\n  STR_BACK_PACK: \"ΣΑΚΙΔΙΟ\"\n  STR_BELT: \"ΖΩΝΗ\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}είναι υπό εξωγήινο έλεγχο\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}είναι υπό εξωγήινο έλεγχο\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}έχασε τις αισθήσεις\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}έχασε τισ αισθήσεις\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}πέθανε από θανάσιμο τραύμα\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}πέθανε από θανάσιμο τράυμα\"\n  STR_USE_MIND_PROBE: \"Χρήση Διερευνητή Νου\"\n  STR_FATAL_WOUNDS: \"ΘΑΝΑΣΙΜΑ ΤΡΑΥΜΑΤΑ\"\n  STR_UNDER_ARMOR_UC: \"ΚΑΤΩ ΘΩΡΑΚΙΣΗ\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Μονάδες Χρόνου φυλαγμένες για Γρήγορη Βολή\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Μονάδες Χρόνου φυλαγμένες για Αυτόματη Βολή\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Μονάδες Χρόνου φυλαγμένες για Στοχευμένη Βολή\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Μονάδες Χρόνου φυλαγμένες για Γονάτισμα\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"ΜΧ φυλαγμένες για Γονάτισμα και Πύρ\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} Μονάδες στο X-Com Craft\"\n    other: \"{N} Μονάδες στο X-Com Craft\"\n  STR_UNITS_OUTSIDE:\n    one: \"{N} Μονάδες που έμειναν έξω\"\n    other: \"{N} Μονάδες που έμειναν έξω\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} Μονάδες στην είσοδο\"\n    other: \"{N} Μονάδες στην είσοδο\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} Μονάδες σε έξοδο στόχου\"\n    other: \"{N} Μονάδες σε έξοδο στόχου\"\n  STR_ABORT_MISSION_QUESTION: \"Ματαίωση Αποστολής;\"\n  STR_CORPSE: \"Πτώμα\"\n  STR_UNLOAD_CRAFT: \"Ξεφόρτωσε\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}σκοτώθηκε\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}σκοτώθηκε\"\n  STR_HIT_MELEE: \"Χτύπημα\"\n  STR_GROUND: \"ΈΔΑΦΟΣ\"\n  STR_LIVING_QUARTERS_PLURAL: \"Κοιτώνες\"\n  STR_LIST_ITEM: \"ΑΝΤΙΚΕΙΜΕΝΟ\"\n  STR_PERSONAL_ARMOR_UFOPEDIA: \"Χρησιμοποιώντας τα πρόσφατα ανακαλυφθέντα κράματα εξωγήινων, αυτή η νέα πανοπλία δίνει στους άντρες μας μια ευκαιρία να πολεμήσουν ενάντια στην εξωγήινη απειλή.\"\n  STR_POWER_SUIT_UFOPEDIA: \"Μια νέα πανίσχυρη προστασία για τους στρατιώτες, αυτή η πανοπλία χρησιμοποιεί πηγή ενέργειας Elerium και ενισχύει την ταχύτητα και δύναμη των κατόχων τους, προσφέροντας την μέχρι στιγμής καλύτερη προστασία για τις ομάδες  μάχης.\"\n  STR_FLYING_SUIT_UFOPEDIA: \"Εξελιγμένη έκδοση της ενεργιακής πανοπλίας, ενσωματωνει εξωγήινη τεχνολογία αντιβαρύτικης πλοήγησης για να επιτρέπει πλήρη ελευθερία μετακίνησης σε όλο το πεδίο της μάχης. \"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"Όλοι οι εξωγήινη πέθαναν στη σύγκρουση,{NEWLINE}Αυτόματη ανάκτηση άρχισε\"\n  STR_RESET: \"Επαναφορά\"\n  STR_MEMORIAL: \"Μνημείο\"\n  STR_DATE_UC: \"ΗΡΕΜΟΜΗΝΙΑ\"\n  STR_SOLDIERS_RECRUITED_UC: \"ΣΤΡΑΤΙΩΤΕΣ ΣΤΡΑΤΟΛΟΓΗΘΗΚΑΝ>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"ΣΤΡΑΤΙΩΤΕΣ ΧΑΘΗΚΑΝ>{ALT}{0}\"\n  MAP_CULTA: \"Φάρμα\"\n  MAP_FOREST: \"Δάσος\"\n  MAP_JUNGLE: \"Ζούγκλα\"\n  MAP_MOUNT: \"Βουνό\"\n  MAP_DESERT: \"Έρημος\"\n  MAP_POLAR: \"Πολικός\"\n  MAP_URBAN: \"Πόλη\"\n  MAP_UBASE: \"Εξωγήινη Βάση\"\n  MAP_XBASE: \"Βάση X-Com\"\n  MAP_MARS: \"Άρης\"\n  STR_MIXED: \"Μικτά\"\n  STR_REMOVE_SELECTED: \"Αφαίρεση Επιλεγμένου\"\n  STR_LIVE_ALIENS: \"Ζωντανά{NEWLINE}Δείγματα\"\n  STR_DEAD_ALIENS: \"Απορριφθέντα{NEWLINE}Δείγματα\"\n  STR_UNDER_INTERROGATION: \"Δείγμα{NEWLINE}Υπο Μελέτη\"\n  STR_CONTAINMENT_EXCEEDED: \"ΥΠΕΡΒΑΣΗ ΑΡΙΘΜΟΥ ΚΡΑΤΗΣΗΣ ΕΞΩΓΕΝΩΝ!{SMALLLINE}Ανεπαρκής χώρος περιορισμού στο {0}. Πρέπει να αφαιρέσετε τους πλεονάζοντες εξωγήινους από τον περιορισμό (οι οποίοι θα πεθάνουν στη συνέχεια).\"\n  STR_MANAGE_CONTAINMENT: \"Διαχείριση Μονάδας περιορισμού Εξωγήινων\"\n  STR_STORAGE_EXCEEDED: \"ΥΠΕΡΒΑΣΗ ΑΠΟΘΗΚΕΥΤΙΚΟΥ ΧΩΡΟΥ!{SMALLLINE}Ανεπαρκής χώρος αποθήκευσης στο {0}. Πρέπει να πουλήσετε τα περιττά αντικείμενα.\"\n  STR_GO_TO_BASE: \"Πήγαινε στη Βάση\"\n  STR_MELEE_ACCURACY: \"ΑΚΡΙΒΕΙΑ ΜΑΧΗΣ ΣΩΜΑ ΜΕ ΣΩΜΑ\"\n  STR_SELL_PRODUCTION: \"ΠΩΛΗΣΗ\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Και τα δυο χέρια πρέπει να είναι άδεια!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Δεν υπάρχουν αρκετά στοιχεία για αντιγραφή προτύπου!\"\n  STR_UNLOAD_WEAPON: \"Αφόπληση όπλου\"\n  STR_ALL_ITEMS: \"Ολα τα αντικείμενα\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"ΔΕΝ ΕΠΙΤΡΕΠΕΤΑΙ ΑΛΛΟΣ ΕΞΟΠΛΙΣΜΟΣ ΣΤΟ ΚΑΤΑΣΤΡΩΜΑ!{SMALLLINE}Επιτρέπεται να πάρετε έως και {N} είδη εξοπλισμού σε αυτό το σκάφος.\"\n    other: \"ΔΕΝ ΕΠΙΤΡΕΠΕΤΑΙ ΑΛΛΟΣ ΕΞΟΠΛΙΣΜΟΣ ΣΤΟ ΚΑΤΑΣΤΡΩΜΑ!{SMALLLINE}Επιτρέπεται να πάρετε έως και {N} είδη εξοπλισμού σε αυτό το σκάφος.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}ΚΕΝΤΡΟ ΕΛΕΓΧΟΥ ΚΑΤΑΣΤΡΕΦΘΗΚΕ{NEWLINE}Προχωρήστε στην είσοδο και ματαιώστε.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"Οι εγκαταστάσεις X-Com δεν μπορούν να κατασκευαστούν υποβρύχια\"\n  STR_LEVEL_SHORT: \"{0}\"\n  STR_PERSONNEL: \"Προσωπικό\"\n  STR_CRAFT_ARMAMENT: \"Χειροτεχνία & Οπλισμός\"\n  STR_COMPONENTS: \"Εξαρτήματα\"\n  STR_SOLDIERS_RECRUITED: \"Στρατιώτες που στρατολογήθηκαν\"\n  STR_SOLDIERS_LOST: \"Στρατιώτες χάθηκαν\"\n  STR_TOTAL_UFOS: \"UFO που εντοπίστηκαν\"\n  STR_TOTAL_ALIEN_BASES: \"Εξωγήινες βάσεις που εντοπίστηκαν\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"PST\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"PSK\"\n  FEMALE_CIVILIAN: \"Πολίτης, θυλικιά\"\n  MALE_CIVILIAN: \"Πολίτης, Αρσενικός\"\n  CYBERDISC_WEAPON: \"Όπλο Κυβερνοδίσκου\"\n  REAPER_WEAPON: \"Όπλο Θεριστή\"\n  CHRYSSALID_WEAPON: \"Όπλο Χρυσαλλίδας\"\n  CELATID_WEAPON: \"Όπλο Celatid\"\n  SILACOID_WEAPON: \"Όπλο Σίλακοϊντ\"\n  SECTOPOD_WEAPON: \"Όπλο Sectopod\"\n  ZOMBIE_WEAPON: \"Όπλο Ζόμπι\"\n  ALIEN_PSI_WEAPON: \"Εξωγήινο Psi όπλο\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/en-GB.yml",
    "content": "en-GB:\n  STR_AVENGER_UFOPEDIA: \"TRANSPORTER AND COMBAT SPACECRAFT. THE ULTIMATE REPLICATION OF ALIEN TECHNOLOGY.\"\n  STR_INTERCEPTOR_UFOPEDIA: \"COMBAT AIRCRAFT WITH DUAL PULSE DETONATION ENGINES AND SPECIALLY SHIELDED ELECTRONIC SYSTEMS. THE BEST AVAILABLE EARTH BASED TECHNOLOGY.\"\n  STR_LIGHTNING_UFOPEDIA: \"TRANSPORTER AND COMBAT CRAFT. A CRUDE BUT EFFECTIVE REPLICATION OF ALIEN PROPULSION SYSTEMS.\"\n  STR_SKYRANGER_UFOPEDIA: \"TROOP TRANSPORTER. THE FASTEST OF ITS KIND, WITH VERTICAL TAKE OFF AND LANDING (V.T.O.L) CAPABILITY.\"\n  STR_FIRESTORM_UFOPEDIA: \"COMBAT CRAFT. THIS ONE-MAN FIGHTER REPLICATES THE CLASSIC ALIEN FLYING SAUCER DESIGN, WITH CENTRAL PROPULSION UNIT.\"\n  STR_STINGRAY_UFOPEDIA: \"ADVANCED AIR TO AIR MISSILE WITH SPECIALLY SHIELDED ELECTRONICS.\"\n  STR_AVALANCHE_UFOPEDIA: \"AIR TO AIR MISSILE WITH NUCLEAR WARHEAD, BUT AN EXTREMELY HEAVY LOAD.\"\n  STR_CANNON_UFOPEDIA: \"HIGH POWERED CANNON WHICH FIRES ARMOUR PIERCING ROUNDS CAPABLE OF PENETRATING 16 INCHES OF STEEL.\"\n  STR_FUSION_BALL_UFOPEDIA: \"THIS LAUNCHER FIRES A BALL SHAPED MISSILE POWERED BY ANTI-MATTER REACTION. THE BALL DESTROYS THE TARGET WITH A GRAVITY WAVE IMPLOSION.\"\n  STR_LASER_CANNON_UFOPEDIA: \"THIS CONVENTIONAL LASER BEAM IS POWERED BY AN ANTI-MATTER REACTION CHAMBER.\"\n  STR_PLASMA_BEAM_UFOPEDIA: \"THE GRAVITY BEAM DIRECTS A FINELY CHANNELLED IMPLODING GRAVITY FIELD.\"\n  STR_SECTOID_UFOPEDIA: \"The Sectoid hierarchy ranges from soldiers to leaders with powerful psionic abilities. These psionic powers can be used to demoralise soldiers in combat, or even take control of their minds. They tend to indulge in human abductions and cattle mutilation. The abduction is used to extract genetic material for cross breeding and developing clones for infiltrating human society. The cattle provide both nutrition and genetic material. This race appears to want to develop superior genetic hybrids to increase the efficiency of their hive-like society.\"\n  STR_SECTOID_AUTOPSY: \"Sectoid autopsy\"\n  STR_SECTOID_AUTOPSY_UFOPEDIA: \"The autopsy reveals vestigial digestive organs and a simple structure. The brain and eyes are very well developed. The structure suggests genetic alteration or mutation. The small mouth and nose appear to have little function. The webbing between the fingers, and the flat feet suggest aquatic origins. There are no reproductive organs, and no clues as to how this species can reproduce. They are most probably a genetically engineered species.\"\n  STR_SNAKEMAN_UFOPEDIA: \"This race developed in an extremely hostile environment. They are extremely tough and can resist extreme temperature variations. Their mobility depends on a snake-like giant 'foot' which protects all the vital organs. Their objectives appear to be purely predatory and they appear to be under the command of some other intelligence which directs their military-style incursions on earth.\"\n  STR_SNAKEMAN_AUTOPSY: \"Snakeman autopsy\"\n  STR_SNAKEMAN_AUTOPSY_UFOPEDIA: \"The skin is extremely tough and heat resistant. The cardio-vascular system is part of the muscular system which uses the hydraulic principle to create motion. The only true muscle is the 'heart'. The reproductive system appears to be very efficient. Reproduction is asexual, with each snakeman carrying up to fifty eggs inside its body at any one time. Left to its own devices this species would be a severe threat to life on earth.\"\n  STR_ETHEREAL_UFOPEDIA: \"This being has awesome mental powers which allow for telepathic communication and telekinetic abilities. The apparently weak physical abilities of this creature are sustained by its mental powers. We do not understand how these telekinetic powers work, since they seem to defy the laws of physics as we know them. They are extremely dangerous in any combat situation, where they rely on their mental powers for combat. They rarely appear on earth since they seem to rely on other races to pursue their objectives.\"\n  STR_ETHEREAL_AUTOPSY: \"Ethereal autopsy\"\n  STR_ETHEREAL_AUTOPSY_UFOPEDIA: \"This being is physically retarded and seems incapable of sustaining any life functions. The muscles are severely atrophied and the internal organs appear to be under-developed. The sensory organs, including the eyes, do not appear to function at all. The brain, however, is well developed and draws on a high proportion of the body's blood supply. It is a mystery as to how this creature can sustain itself without external support.\"\n  STR_MUTON_UFOPEDIA: \"This humanoid creature is physically powerful and intelligent. They have a particular appetite for consuming raw flesh of any kind, which they need for sustenance like earth based carnivores. They appear to rely on telepathic commands from a race known as 'Ethereals'. Once separated from this telepathic link their mental system appears to break down and they die. The cybernetic implants are used to enhance their combat performance. They are clearly the foot soldiers for a higher intelligence.\"\n  STR_MUTON_AUTOPSY: \"Muton autopsy\"\n  STR_MUTON_AUTOPSY_UFOPEDIA: \"The 'skin' of this creature appears to be an organically created protective armour which is grafted onto the body. There are numerous cybernetic implants which are used to enhance the cardio-vascular system and the senses. The reproductive organs appear to have been surgically removed. Evidently these unfortunate creatures are limited to a life of warfare and conquest. Armour piercing ammunition is not very effective against their toughened skin.\"\n  STR_CELATID_UFOPEDIA: \"This life-form has the mysterious natural ability to float through the air. It appears to detect human brain waves and will move towards a human target even if well hidden. Once a target is detected the Celatid lands and fires small globules of extremely corrosive venom. The creature has the ability to clone itself at an alarming rate. It accompanies the Muton race in its wanderings.\"\n  STR_CELATID_AUTOPSY: \"Celatid autopsy\"\n  STR_CELATID_AUTOPSY_UFOPEDIA: \"The core contains a small bio-mechanical device which appears to be a naturally evolved anti-gravity propulsion system. The sac of venom is the largest organ and there does not appear to be a separate brain structure. There is no discernible digestive or reproductive system. A small organ contains embryos which can grow rapidly into a new being.\"\n  STR_SILACOID_UFOPEDIA: \"This silicon based life form generates an enormous amount of heat. It has the strength to crush rocks which can then be ingested by the hot core. It has a primitive intelligence and can be controlled by implants or telepathic beings. It works with the Muton alien race.\"\n  STR_SILACOID_AUTOPSY: \"Silacoid autopsy\"\n  STR_SILACOID_AUTOPSY_UFOPEDIA: \"The core of the creature is extremely hot, and seems to be the basis for a digestive system. Its unique muscle system has tremendous power and speed. Its rock-like skin is not harmed by fire or incendiary ammunition.\"\n  STR_CHRYSSALID_UFOPEDIA: \"The crab-like claws of this creature are a powerful weapon in close combat. The high metabolism and strength of this creature give it speed and dexterity. Instead of killing its victim it impregnates it with an egg and injects a venom which turns it into a walking zombie. A new Chryssalid will burst from the victim shortly after impregnation. Chryssalids are associated with the Snakeman race.\"\n  STR_CHRYSSALID_AUTOPSY: \"Chryssalid autopsy\"\n  STR_CHRYSSALID_AUTOPSY_UFOPEDIA: \"The exoskeleton of this creature is extremely tough, but surprisingly vulnerable to explosive ammunition. The brain is well developed, and its cell growth rate very fast. The creature carries twenty eggs which are laid inside other organisms. This creature is a very effective terror weapon.\"\n  STR_FLOATER_UFOPEDIA: \"The Floaters are primarily soldiers and terror agents. They are naturally predatory beasts, genetically engineered and cybernetically enhanced to make formidable warriors. The lower half of the body and most internal organs are surgically removed, and a life support system is installed. This implant contains an anti-gravity unit which enables the creature to float, albeit unsteadily, through the air.\"\n  STR_FLOATER_AUTOPSY: \"Floater autopsy\"\n  STR_FLOATER_AUTOPSY_UFOPEDIA: \"The creature has been drastically altered by surgery. The device which seems to form the core of the body is a life support system, taking over the function of heart, lungs and digestive system. This would enable the creature to survive in extremely hostile environments. The brain is smaller than ours, but the sensory organs are well developed.\"\n  STR_REAPER_UFOPEDIA: \"This bipedal carnivore has powerful jaws and a voracious appetite. It has a number of brain implants which are used to control its activity. The primitive predatory instincts of this creature are of little use except to terrorise and destroy. Reapers are commonly associated with Floaters.\"\n  STR_REAPER_AUTOPSY: \"Reaper autopsy\"\n  STR_REAPER_AUTOPSY_UFOPEDIA: \"The Reaper contains two 'brains' and two 'hearts' which allow it to function even when heavily wounded. However, its furry skin is highly flammable, making the creature vulnerable to incendiary weapons.\"\n  STR_SECTOPOD_UFOPEDIA: \"Sectopods are robot creatures with a powerful laser beam weapon. The control of these mechanical beasts is via a telepathic link to their controllers, the Ethereals. Sectopods are the most powerful terror weapon available to the alien forces.\"\n  STR_SECTOPOD_AUTOPSY: \"Sectopod autopsy\"\n  STR_SECTOPOD_AUTOPSY_UFOPEDIA: \"The robot is sturdily constructed with powered armour capable of resisting most forms of attack, in particular plasma weapons. However, the sensing circuitry seems particularly vulnerable to laser weapons.\"\n  STR_CYBERDISC_UFOPEDIA: \"This miniature flying saucer is an automated terror weapon armed with a powerful plasma beam. The anti-gravity propulsion gives it a big advantage in difficult terrain. Its primary function is destruction and terror in the service of the Sectoid race.\"\n  STR_CYBERDISC_AUTOPSY: \"Cyberdisc autopsy\"\n  STR_CYBERDISC_AUTOPSY_UFOPEDIA: \"The Cyberdisc is well shielded and is particularly good at withstanding explosive ammunition. The primary anti-gravity system is too badly damaged to gain any understanding of its functioning.\"\n  STR_UFO_POWER_SOURCE_UFOPEDIA: \"The power source of alien craft is an anti-matter reactor which uses Elerium (element 115) to generate powerful gravity waves as well as other forms of energy. The conversion of matter to energy is an incredible 99% efficient, therefore tiny quantities of Elerium can produce a huge amount of power. This unit can be reproduced easily using alien alloys.\"\n  STR_UFO_NAVIGATION_UFOPEDIA: \"Alien craft use sophisticated computers to navigate on earth and through space. The system is based on optical processors arranged in network fashion. The control interface is relatively simple - the navigator controls the direction of gravity waves generated by the power source to move the craft in any direction. This system can be used easily by humans, and it can be reproduced using alien alloys and other components.\"\n  STR_UFO_CONSTRUCTION_UFOPEDIA: \"Alien craft consist of three main components - a power source, a navigation system and a hull built from alien alloys. The hull is specially designed to allow gravity waves to be directed and controlled. In addition a small quantity of Elerium is required to fuel the power source. Once the principles of construction are understood, and the functions of each component are known, then it is possible to build these types of craft.\"\n  STR_ALIEN_FOOD_UFOPEDIA: \"These chambers contain various enzymes which are used to digest the body parts of cattle, other animals and even humans. The liquid is then consumed as ready digested food - probably direct to the bloodstream. This suggests a certain dependence on earth for food - a symbiosis between earth and alien society.\"\n  STR_ALIEN_REPRODUCTION_UFOPEDIA: \"These chambers contain alien foetuses. The design of these containers seems to suggest that the aliens which use this process rely completely on laboratory reproduction. The rich nutrients ensure rapid development of the foetus. This factory line system could generate thousands of alien clones in a short space of time. The process could be easily adapted for human reproduction, or alien-human hybrids.\"\n  STR_ALIEN_ENTERTAINMENT_UFOPEDIA: \"The most likely function of these spheres is recreational. The psionic circuitry stimulates various centres of the brain. The effect is similar to hallucinogenic drugs. This is the only evidence that aliens have any cultural or recreational pastimes.\"\n  STR_ALIEN_SURGERY_UFOPEDIA: \"This surgical equipment uses laser cutters to extract certain body parts from cattle and other animals. The widespread cattle mutilations can be accounted for by this bizarre alien activity. It is likely that these parts are used for nutritional or genetic purposes.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"In the past many thousands of people have claimed to have been abducted by aliens, sometimes repeatedly. The truth is far more horrific. Humans are abducted, researched and monitored. The best specimens have genetic material extracted. Women have human-alien hybrid foetuses implanted, and then removed several months later. Who knows what sinister motives the aliens have?\"\n  STR_ALIEN_ALLOYS_UFOPEDIA: \"Alien craft are constructed from special alloys with unique properties. They are extremely light and durable, and can be moulded by electro-magnetic methods. This material can be reproduced and used in many kinds of manufacturing processes.\"\n  STR_ELERIUM_115_UFOPEDIA: \"This element has the unusual property of generating anti-matter power when bombarded with certain particles. This creates gravity waves and other forms of energy. It is not naturally found in our solar system and cannot be reproduced.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"It is clear that we are fighting a losing battle on earth. The alien hordes are overwhelming in number. The best we can do is slow down their progress. The only hope for humanity is to tackle the aliens at their source. Our research seems to indicate a nearby base of operations within our solar system. Aliens indicate this place to be the centre of an ancient civilisation that pre-dates human history. We must locate this place as soon as possible. However, we need to capture and interrogate an alien leader to gain more detailed information. The larger UFOs probably contain at least one alien leader.\"\n  STR_THE_MARTIAN_SOLUTION_UFOPEDIA: \"Our research now points to Mars as the base of alien operations. The base is well hidden, and contains all the manufacturing and cloning facilities to fuel the infiltration of earth. It also seems to contain a controlling computer of some kind that controls the whole operation. It seems that the hive-like alien society has some kind of 'queen bee'. This is their fundamental weakness - if we can eliminate the 'brain' then the body will die. We must step up our research efforts before it is too late. In order to progress we must capture the highest ranking aliens - the commanders - which only reside in alien bases and battleships.\"\n  STR_CYDONIA_OR_BUST_UFOPEDIA: \"It is now clear that the alien hordes are being controlled from an underground base in Cydonia - which is an unusual area of Mars featuring five sided pyramids and a large formation resembling a human face. Cydonian civilisation once flourished on Mars many millions of years ago, but we do not know why it died out, or what the connection is with the latest alien activity there. Whatever the explanation we must send an expedition to Cydonia. This is the only way that we can defeat the aliens. We must destroy the controlling master 'brain'. We will need an Avenger craft equipped with the most awesome destructive power at our disposal. There is nothing more we can learn here - we must await the outcome of the Cydonian assault.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"CENTRE ON SITE-TIME=5 Secs\"\n  STR_CANCEL_UC: \"CANCEL\"\n  STR_NONE: \"None\"\n  STR_UNKNOWN: \"Unknown\"\n  STR_POOR: \"Poor\"\n  STR_AVERAGE: \"Average\"\n  STR_GOOD: \"Good\"\n  STR_EXCELLENT: \"Excellent\"\n  STR_BUILD_NEW_BASE_UC: \"BUILD NEW BASE\"\n  STR_BASE_INFORMATION: \"BASE INFORMATION\"\n  STR_EQUIP_CRAFT: \"EQUIP CRAFT\"\n  STR_BUILD_FACILITIES: \"BUILD FACILITIES\"\n  STR_RESEARCH: \"RESEARCH\"\n  STR_MANUFACTURE: \"MANUFACTURE\"\n  STR_TRANSFER_UC: \"TRANSFER\"\n  STR_PURCHASE_RECRUIT: \"PURCHASE/RECRUIT\"\n  STR_SACK: \"SACK\"\n  STR_SELL_SACK_UC: \"SELL/SACK\"\n  STR_GEOSCAPE_UC: \"GEOSCAPE\"\n  STR_NAME: \"Name\"\n  STR_AREA: \"Area\"\n  STR_BUILD_NEW_BASE: \"Build New Base\"\n  STR_CANCEL: \"Cancel\"\n  STR_COST_UC: \"COST>\"\n  STR_CONSTRUCTION_TIME_UC: \"CONSTRUCTION TIME>\"\n  STR_DAY:\n    one: \"{N} day\"\n    other: \"{N} days\"\n  STR_HOUR:\n    one: \"{N} hour\"\n    other: \"{N} hours\"\n  STR_MAINTENANCE_UC: \"MAINTENANCE>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Installation\"\n  STR_CURRENT_RESEARCH: \"CURRENT RESEARCH\"\n  STR_SCIENTISTS_AVAILABLE: \"Scientists Available>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Scientists Allocated>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Laboratory Space Available>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"RESEARCH PROJECT\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"SCIENTISTS ALLOCATED\"\n  STR_PROGRESS: \"PROGRESS\"\n  STR_NEW_PROJECT: \"New Project\"\n  STR_CANCEL_PROJECT: \"CANCEL PROJECT\"\n  STR_NEW_RESEARCH_PROJECTS: \"NEW RESEARCH PROJECTS\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"SCIENTISTS AVAILABLE>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"LABORATORY SPACE AVAILABLE>{ALT}{0}\"\n  STR_INCREASE: \"Increase\"\n  STR_DECREASE: \"Decrease\"\n  STR_START_PROJECT: \"START PROJECT\"\n  STR_CURRENT_PRODUCTION: \"CURRENT PRODUCTION\"\n  STR_ENGINEERS_AVAILABLE: \"Engineers Available>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Engineers Allocated>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Workshop Space Available>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Current Funds>{ALT}{0}\"\n  STR_ITEM: \"ITEM\"\n  STR_ENGINEERS__ALLOCATED: \"Engineers Allocated\"\n  STR_UNITS_PRODUCED: \"Units Produced\"\n  STR_TOTAL_TO_PRODUCE: \"Total to Produce\"\n  STR_COST__PER__UNIT: \"Cost{NEWLINE}per{NEWLINE}Unit\"\n  STR_DAYS_HOURS_LEFT: \"Days/Hours Left\"\n  STR_NEW_PRODUCTION: \"New Production\"\n  STR_PRODUCTION_ITEMS: \"Production Items\"\n  STR_CATEGORY: \"CATEGORY\"\n  STR_START_PRODUCTION: \"START PRODUCTION\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} Engineer hours to produce one unit\"\n  STR_COST_PER_UNIT_: \"Cost per unit>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Work Space Required>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"SPECIAL MATERIALS REQUIRED\"\n  STR_ITEM_REQUIRED: \"ITEM REQUIRED\"\n  STR_UNITS_REQUIRED: \"UNITS REQUIRED\"\n  STR_UNITS_AVAILABLE: \"UNITS AVAILABLE\"\n  STR_STOP_PRODUCTION: \"STOP PRODUCTION\"\n  STR_ENGINEERS_AVAILABLE_UC: \"ENGINEERS AVAILABLE>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"WORKSHOP SPACE AVAILABLE>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"MONTHLY PROFIT>{ALT}{0}\"\n  STR_INCREASE_UC: \"INCREASE\"\n  STR_DECREASE_UC: \"DECREASE\"\n  STR_UNITS_TO_PRODUCE: \"Units to Produce\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Purchase/Hire Personnel\"\n  STR_COST_OF_PURCHASES: \"Cost of Purchases>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"COST PER UNIT\"\n  STR_QUANTITY_UC: \"QUANTITY\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"PERSONNEL AVAILABLE:PERSONNEL TOTAL>\"\n  STR_SOLDIERS: \"Soldiers\"\n  STR_SCIENTISTS: \"Scientists\"\n  STR_ENGINEERS: \"Engineers\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"SPACE USED:SPACE AVAILABLE>\"\n  STR_LIVING_QUARTERS: \"Living Quarters\"\n  STR_STORES: \"Stores\"\n  STR_LABORATORIES: \"Laboratories\"\n  STR_WORK_SHOPS: \"Work Shops\"\n  STR_HANGARS: \"Hangars\"\n  STR_SHORT_RANGE_DETECTION: \"Short Range Detection\"\n  STR_DEFENSE_STRENGTH: \"Defence Strength\"\n  STR_TRANSFERS_UC: \"TRANSFERS\"\n  STR_TRANSFERS: \"Transfers\"\n  STR_ARRIVAL_TIME_HOURS: \"Arrival Time (hours)\"\n  STR_COST_: \"Cost>{ALT}{0}\"\n  STR_AREA_: \"Area>{ALT}{0}\"\n  STR_BASE_NAME: \"Base Name?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"SELECT POSITION FOR ACCESS LIFT\"\n  STR_TRANSFER: \"Transfer\"\n  STR_AMOUNT_TO_TRANSFER: \"AMOUNT TO TRANSFER\"\n  STR_SELECT_DESTINATION_BASE: \"Select Destination Base\"\n  STR_COST: \"Cost\"\n  STR_VICTORY_1: \"As you enter the chamber you see the alien brain - the object of your quest. Before you can fire it communicates to you via a screen at its base. It implores you to listen to its arguments for survival before you make the decision to pull the trigger...\"\n  STR_VICTORY_2: \"The brain speaks: 'Many millions of years ago the planet you call Mars was alive. This life was brought to a barren planet by our civilisation as it was to yours. For millions of years we have visited your planet and genetically developed your species. You cannot kill us, you are part of us...\"\n  STR_VICTORY_3: \"Here is the centre of Martian civilisation - the pyramids built millions of years before yours - by a species which is your ancestor. No planet is beyond our reach. This power could be yours before long. All we ask is your co-operation...\"\n  STR_GAME_OVER_1: \"The aliens attempt to exterminate all humanity, destroying cities and poisoning the air and sea. The resistance of earth armies is futile in the face of vastly superior technology. Surviving generations suffer terrible mutations as they flee alien destruction. They are rounded up into slave camps to help transform earth into an alien colony which is part of some unknown empire.\"\n  STR_GAME_OVER_2: \"The knowledge gained through the X-Com project is lost forever. You have failed to save the earth.\"\n  STR_VICTORY_4: \"The alien brain is interrupted by a burst of hot plasma, and the entire alien force is defeated.\"\n  STR_VICTORY_5: \"Once the aliens have lost Mars they have lost the earth. Before long the X-Com research allows humanity to flourish once more, and claim Mars for itself. The alien menace has gone, but for how long, no one knows...\"\n  STR_YOU_HAVE_FAILED: \"You have failed to stop the alien onslaught. One by one the funding nations sign pacts with aliens promising technology, prosperity and peace. However it soon becomes clear that the aliens have other plans...\"\n  STR_TOTAL_UC: \"TOTAL\"\n  STR_INCOME: \"Income\"\n  STR_EXPENDITURE: \"Expenditure\"\n  STR_MAINTENANCE: \"Maintenance\"\n  STR_BALANCE: \"Balance\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"UFO Activity in Areas\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"UFO Activity in Countries\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"X-Com Activity in Areas\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"X-Com Activity in Countries\"\n  STR_FINANCE: \"Finance\"\n  STR_DATE_FIRST: \"{0}st\"\n  STR_DATE_SECOND: \"{0}nd\"\n  STR_DATE_THIRD: \"{0}rd\"\n  STR_DATE_FOURTH: \"{0}th\"\n  STR_FINANCE_THOUSANDS: \"$1000's\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Not enough special materials to produce{NEWLINE}{0}{NEWLINE}at{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Not enough money to produce{NEWLINE}{0}{NEWLINE}at{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"Production of{NEWLINE}{0}{NEWLINE}at{NEWLINE}{1}{NEWLINE}is complete\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"Construction of{NEWLINE}{0}{NEWLINE}at{NEWLINE}{1}{NEWLINE}is complete\"\n  STR_OK_5_SECONDS: \"OK - 5 secs\"\n  STR_RESEARCH_COMPLETED: \"Research Completed\"\n  STR_VIEW_REPORTS: \"VIEW REPORTS\"\n  STR_WE_CAN_NOW_RESEARCH: \"We can now research\"\n  STR_WE_CAN_NOW_PRODUCE: \"We can now produce\"\n  STR_SUNDAY: \"SUNDAY\"\n  STR_MONDAY: \"MONDAY\"\n  STR_TUESDAY: \"TUESDAY\"\n  STR_WEDNESDAY: \"WEDNESDAY\"\n  STR_THURSDAY: \"THURSDAY\"\n  STR_FRIDAY: \"FRIDAY\"\n  STR_SATURDAY: \"SATURDAY\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Not enough {0} to refuel {1} at {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Not enough {0} to rearm {1} at {2}\"\n  STR_UFO_IS_NOT_RECOVERED: \"UFO is not recovered\"\n  STR_UFO_IS_RECOVERED: \"UFO is recovered\"\n  STR_CRAFT_IS_LOST: \"Craft is lost\"\n  STR_TERROR_CONTINUES: \"Terror continues\"\n  STR_ALIENS_DEFEATED: \"Aliens defeated\"\n  STR_BASE_IS_LOST: \"Base is lost\"\n  STR_BASE_IS_SAVED: \"Base is saved\"\n  STR_ALIEN_BASE_STILL_INTACT: \"Alien Base still intact\"\n  STR_ALIEN_BASE_DESTROYED: \"Alien Base destroyed\"\n  STR_ALIENS_KILLED: \"ALIENS KILLED\"\n  STR_ALIEN_CORPSES_RECOVERED: \"ALIEN CORPSES RECOVERED\"\n  STR_LIVE_ALIENS_RECOVERED: \"LIVE ALIENS RECOVERED\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"ALIEN ARTEFACTS RECOVERED\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"ALIEN BASE CONTROL DESTROYED\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"CIVILIANS KILLED BY ALIENS\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"CIVILIANS KILLED BY X-COM OPERATIVES\"\n  STR_CIVILIANS_SAVED: \"CIVILIANS SAVED\"\n  STR_XCOM_OPERATIVES_KILLED: \"X-COM OPERATIVES KILLED\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"X-COM OPERATIVES MISSING IN ACTION\"\n  STR_TANKS_DESTROYED: \"TANKS DESTROYED\"\n  STR_XCOM_CRAFT_LOST: \"X-COM CRAFT LOST\"\n  STR_UFO_RECOVERY: \"UFO RECOVERY\"\n  STR_ALIEN_BASE_RECOVERY: \"ALIEN BASE RECOVERY\"\n  STR_BASE_UNDER_ATTACK: \"{0} under attack!\"\n  STR_BASE_DEFENSES_INITIATED: \"BASE DEFENCES INITIATED\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"GRAV SHIELD REPELS UFO!\"\n  STR_FIRING: \"FIRING\"\n  STR_HIT: \"HIT!\"\n  STR_UFO_DESTROYED: \"UFO DESTROYED!\"\n  STR_MISSED: \"MISSED!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Sell Items/Sack Personnel\"\n  STR_VALUE_OF_SALES: \"VALUE OF SALES> {ALT}{0}\"\n  STR_FUNDS: \"FUNDS> {ALT}{0}\"\n  STR_SELL_SACK: \"Sell/Sack\"\n  STR_VALUE: \"Value\"\n  STR_CRAFT_: \"CRAFT> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"UFO CRASH RECOVERY\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"Exercise caution - There may be operatives in the UFO or around the crash site. Mission will be successful when all enemy units have been eliminated or neutralised. Recovery of UFO remains, artefacts and alien corpses can then be initiated. To abort the mission return X-Com operatives to transport vehicle and click on the 'Abort Mission' icon.\"\n  STR_UFO_GROUND_ASSAULT: \"UFO GROUND ASSAULT\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"Explore landing site and, if possible, gain entry to the UFO. Mission will be successful when all enemy units have been eliminated or neutralised. Recovery of UFO, artefacts and alien corpses can then be initiated. To abort the mission return X-Com operatives to transport vehicle and click on the 'Abort Mission' icon.\"\n  STR_BASE_DEFENSE: \"BASE DEFENCE\"\n  STR_BASE_UC_: \"BASE> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"An Alien vessel has landed nearby. Our base is in severe danger. As per standard procedure all non-combat personnel and X-Com craft have been evacuated. Alien units will enter the base via hangar doors or the access lift. Defend the base and its vital installations at all costs - this is a fight to the death. If you click on the 'abort mission' icon you will concede defeat and lose the base.\"\n  STR_ALIEN_BASE_ASSAULT: \"ALIEN BASE ASSAULT\"\n  STR_ALIEN_BASE_ASSAULT_BRIEFING: \"X-Com operatives have gained entrance to an alien base. The control centre must be destroyed to render the base inoperative. The mission will terminate when all enemies are eliminated, or when your squad has returned to the green exit area (click on the 'abort mission' icon to escape).\"\n  STR_CYDONIA_BRIEFING: \"You have arrived in Cydonia. You gain entry to a large underground complex near the Martian Sphinx. You must destroy the Alien Brain that controls all alien activity. The fate of humanity is in your hands....\"\n  STR_TERROR_MISSION: \"TERROR MISSION\"\n  STR_TERROR_MISSION_BRIEFING: \"Mission will be successful when all enemy units have been eliminated or neutralised. You must attempt to save the lives of any civilians in the area by neutralising the alien menace. To abort the mission return X-Com operatives to transport vehicle and click on the 'Abort Mission' icon.\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"NO FREE HANGARS FOR CRAFT PRODUCTION!{SMALLLINE}Each craft assigned to a base, transferred to a base, purchased or constructed uses one hangar. Build a new hangar or transfer a craft to another base.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"NO FREE HANGARS FOR PURCHASE!{SMALLLINE}Each craft assigned to a base, transferred to a base, purchased or constructed uses one hangar. Build a new hangar or transfer a craft to another base.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"NO FREE HANGARS FOR TRANSFER!{SMALLLINE}Each craft assigned to a base, transferred to a base, purchased or constructed uses one hangar. Build a new hangar or transfer a craft to another base.\"\n  STR_CANNOT_BUILD_HERE: \"CANNOT BUILD HERE!{SMALLLINE}You must build next to an existing base facility.\"\n  STR_NO_FREE_ACCOMODATION: \"NO FREE ACCOMMODATION!{SMALLLINE}The destination base does not have enough space in living quarters.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"NOT ENOUGH WORK SPACE AVAILABLE!{SMALLLINE}Build a new workshop or reduce work on other projects.\"\n  STR_NOT_ENOUGH_MONEY: \"NOT ENOUGH MONEY!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"NOT ENOUGH STORE SPACE!{SMALLLINE}Build a new store facility or transfer existing stores to other bases.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"NOT ENOUGH LIVING SPACE!{SMALLLINE}Build new living quarters or transfer personnel to other bases.\"\n  STR_LAUNCH_INTERCEPTION: \"LAUNCH INTERCEPTION\"\n  STR_CRAFT: \"CRAFT\"\n  STR_STATUS: \"STATUS\"\n  STR_BASE: \"BASE\"\n  STR_READY: \"READY\"\n  STR_OUT: \"OUT\"\n  STR_REPAIRS: \"REPAIRS\"\n  STR_REFUELLING: \"REFUELLING\"\n  STR_REARMING: \"REARMING\"\n  STR_TARGET: \"TARGET: {0}\"\n  STR_WAY_POINT: \"WAY POINT\"\n  STR_ARE_YOU_SURE_CYDONIA: \"Are you sure you want to send this craft on a mission to Cydonia?\"\n  STR_YES: \"YES\"\n  STR_NO: \"NO\"\n  STR_SELECT_DESTINATION: \"SELECT DESTINATION\"\n  STR_CYDONIA: \"CYDONIA\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"SELECT SITE FOR NEW BASE\"\n  STR_RETURN_TO_BASE: \"RETURN TO BASE\"\n  STR_SELECT_NEW_TARGET: \"SELECT NEW TARGET\"\n  STR_PATROL: \"PATROL\"\n  STR_STATUS_: \"STATUS>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"DAMAGED - RETURNING TO BASE\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"LOW FUEL - RETURNING TO BASE\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"MISSION COMPLETE - RETURNING TO BASE\"\n  STR_PATROLLING: \"PATROLLING\"\n  STR_TAILING_UFO: \"TAILING UFO\"\n  STR_INTERCEPTING_UFO: \"INTERCEPTING UFO-{0}\"\n  STR_RETURNING_TO_BASE: \"RETURNING TO BASE\"\n  STR_DESTINATION_UC_: \"DESTINATION: {0}\"\n  STR_BASE_UC: \"BASE>{ALT}{0}\"\n  STR_SPEED_: \"SPEED>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"MAXIMUM SPEED>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"ALTITUDE>{ALT}{0}\"\n  STR_VERY_LOW: \"VERY LOW\"\n  STR_LOW_UC: \"LOW\"\n  STR_HIGH_UC: \"HIGH\"\n  STR_VERY_HIGH: \"VERY HIGH\"\n  STR_FUEL: \"FUEL>{ALT}{0}\"\n  STR_WEAPON_ONE: \"WEAPON-1>{ALT}{0}\"\n  STR_NONE_UC: \"NONE\"\n  STR_ROUNDS_: \"ROUNDS>{ALT}{0}\"\n  STR_WEAPON_TWO: \"WEAPON-2>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"INTERCEPTION CRAFT\"\n  STR_BASE_: \"Base>{0}\"\n  STR_NAME_UC: \"NAME\"\n  STR_AMMO_: \"AMMO>{ALT}{0}\"\n  STR_CREW: \"CREW\"\n  STR_EQUIPMENT_UC: \"EQUIPMENT\"\n  STR_ARMOR: \"ARMOUR\"\n  STR_MAX: \"MAX>{ALT}{0}\"\n  STR_ROOKIE: \"Rookie\"\n  STR_SQUADDIE: \"Squaddie\"\n  STR_SERGEANT: \"Sergeant\"\n  STR_CAPTAIN: \"Captain\"\n  STR_COLONEL: \"Colonel\"\n  STR_COMMANDER: \"Commander\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Select Squad for {0}\"\n  STR_SORT_BY: \"SORT BY...\"\n  STR_ORIGINAL_ORDER: \"ORIGINAL ORDER\"\n  STR_MISSIONS2: \"MISSIONS\"\n  STR_KILLS2: \"KILLS\"\n  STR_WOUND_RECOVERY2: \"WOUND RECOVERY\"\n  STR_SPACE_AVAILABLE: \"SPACE AVAILABLE>{ALT}{0}\"\n  STR_SPACE_USED: \"SPACE USED>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"SPACE USED\"\n  STR_RANK: \"RANK\"\n  STR_WOUNDED: \"WOUNDED\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Equipment for {0}\"\n  STR_DEFENSE_VALUE: \"Defence Value\"\n  STR_HIT_RATIO: \"Hit Ratio\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}ready to{NEWLINE}land near{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"Begin Mission?\"\n  STR_SELECT_ARMAMENT: \"Select Armament\"\n  STR_AMMUNITION_AVAILABLE: \"AMMUNITION AVAILABLE\"\n  STR_ARMAMENT: \"ARMAMENT\"\n  STR_NOT_AVAILABLE: \"N.A.\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"SELECT ARMOUR FOR{NEWLINE}{0}\"\n  STR_TYPE: \"TYPE\"\n  STR_PERSONAL_ARMOR_UC: \"PERSONAL ARMOUR\"\n  STR_POWER_SUIT_UC: \"POWER SUIT\"\n  STR_FLYING_SUIT_UC: \"FLYING SUIT\"\n  STR_SELECT_ARMOR: \"Select Armour\"\n  STR_NORTH: \"NORTH\"\n  STR_NORTH_EAST: \"NORTH EAST\"\n  STR_EAST: \"EAST\"\n  STR_SOUTH_EAST: \"SOUTH EAST\"\n  STR_SOUTH: \"SOUTH\"\n  STR_SOUTH_WEST: \"SOUTH WEST\"\n  STR_WEST: \"WEST\"\n  STR_NORTH_WEST: \"NORTH WEST\"\n  STR_SELECT_ACTION: \"SELECT ACTION\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"CONTINUE INTERCEPTION PURSUIT\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"PURSUE WITHOUT INTERCEPTION\"\n  STR_VERY_LARGE: \"VERY LARGE\"\n  STR_LARGE: \"LARGE\"\n  STR_MEDIUM_UC: \"MEDIUM\"\n  STR_SMALL: \"SMALL\"\n  STR_VERY_SMALL: \"VERY SMALL\"\n  STR_GROUNDED: \"GROUND\"\n  STR_DETECTED: \"Detected\"\n  STR_SIZE_UC: \"SIZE\"\n  STR_ALTITUDE: \"ALTITUDE\"\n  STR_HEADING: \"HEADING\"\n  STR_SPEED: \"SPEED\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"CENTRE ON UFO-TIME=5 Secs\"\n  STR_TRACKING_LOST: \"TRACKING LOST\"\n  STR_REDIRECT_CRAFT: \"REDIRECT CRAFT\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"GO TO LAST KNOWN UFO POSITION\"\n  STR_UFO_: \"UFO-{0}\"\n  STR_ALIEN_BASE_: \"ALIEN BASE-{0}\"\n  STR_CRASH_SITE_: \"CRASH SITE-{0}\"\n  STR_LANDING_SITE_: \"LANDING SITE-{0}\"\n  STR_WAY_POINT_: \"WAY POINT-{0}\"\n  STR_TERROR_SITE: \"TERROR SITE-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}has reached{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"Now patrolling\"\n  STR_ALIEN_ORIGINS: \"Alien Origins\"\n  STR_THE_MARTIAN_SOLUTION: \"The Martian Solution\"\n  STR_CYDONIA_OR_BUST: \"Cydonia or Bust\"\n  STR_UFOPAEDIA: \"UFOpaedia\"\n  STR_XCOM_CRAFT_ARMAMENT: \"X-COM CRAFT & ARMAMENT\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"HEAVY WEAPONS PLATFORMS\"\n  STR_WEAPONS_AND_EQUIPMENT: \"WEAPONS AND EQUIPMENT\"\n  STR_ALIEN_ARTIFACTS: \"ALIEN ARTEFACTS\"\n  STR_BASE_FACILITIES: \"BASE FACILITIES\"\n  STR_ALIEN_LIFE_FORMS: \"ALIEN LIFE FORMS\"\n  STR_ALIEN_RESEARCH_UC: \"ALIEN RESEARCH\"\n  STR_UFO_COMPONENTS: \"UFO COMPONENTS\"\n  STR_UFOS: \"UFOs\"\n  STR_SELECT_ITEM: \"SELECT ITEM\"\n  STR_ACCELERATION: \"ACCELERATION>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"FUEL CAPACITY>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"WEAPON PODS>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"DAMAGE CAPACITY>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"CARGO SPACE>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"HWP CAPACITY>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Damage\"\n  STR_RANGE: \"Range\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Accuracy\"\n  STR_RE_LOAD_TIME: \"Re-load time\"\n  STR_SECONDS: \"{0}s\"\n  STR_DAMAGE_ARMOR_PIERCING: \"ARMOUR PIERCING\"\n  STR_DAMAGE_INCENDIARY: \"INCENDIARY\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"HIGH EXPLOSIVE\"\n  STR_DAMAGE_LASER_BEAM: \"LASER BEAM\"\n  STR_DAMAGE_PLASMA_BEAM: \"PLASMA BEAM\"\n  STR_DAMAGE_STUN: \"STUN\"\n  STR_DAMAGE_MELEE: \"MELEE\"\n  STR_DAMAGE_ACID: \"ACID\"\n  STR_DAMAGE_SMOKE: \"SMOKE\"\n  STR_SHOT_TYPE: \"SHOT TYPE\"\n  STR_ACCURACY_UC: \"ACCURACY\"\n  STR_TIME_UNIT_COST: \"TU COST\"\n  STR_DAMAGE_UC: \"DAMAGE\"\n  STR_AMMO: \"AMMO\"\n  STR_SHOT_TYPE_AUTO: \"Auto\"\n  STR_SHOT_TYPE_SNAP: \"Snap\"\n  STR_SHOT_TYPE_AIMED: \"Aimed\"\n  STR_CONSTRUCTION_TIME: \"Construction Time\"\n  STR_CONSTRUCTION_COST: \"Construction Cost\"\n  STR_MAINTENANCE_COST: \"Maintenance Cost\"\n  STR_LOW: \"Low\"\n  STR_MEDIUM: \"Medium\"\n  STR_HIGH: \"High\"\n  STR_CRAFT_WEAPON: \"Craft Weapon\"\n  STR_CRAFT_AMMUNITION: \"Craft Ammunition\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Heavy Weapons Platform\"\n  STR_WEAPON: \"Weapon\"\n  STR_AMMUNITION: \"Ammunition\"\n  STR_EQUIPMENT: \"Equipment\"\n  STR_ALIEN_CORPSE: \"Alien Corpse\"\n  STR_UFO_COMPONENT: \"UFO component\"\n  STR_PERSONAL_ARMOR: \"Personal Armour\"\n  STR_RAW_MATERIALS: \"Raw Materials\"\n  STR_HWP_CANNON_SHELLS: \"HWP Cannon Shells\"\n  STR_ALIEN: \"Alien\"\n  STR_SECTOID: \"Sectoid\"\n  STR_SNAKEMAN: \"Snakeman\"\n  STR_ETHEREAL: \"Ethereal\"\n  STR_MUTON: \"Muton\"\n  STR_FLOATER: \"Floater\"\n  STR_CELATID: \"Celatid\"\n  STR_SILACOID: \"Silacoid\"\n  STR_CHRYSSALID: \"Chryssalid\"\n  STR_ZOMBIE: \"Zombie\"\n  STR_REAPER: \"Reaper\"\n  STR_SECTOPOD: \"Sectopod\"\n  STR_CYBERDISC: \"Cyberdisc\"\n  STR_LIVE_COMMANDER: \"Commander\"\n  STR_LIVE_LEADER: \"Leader\"\n  STR_LIVE_ENGINEER: \"Engineer\"\n  STR_LIVE_MEDIC: \"Medic\"\n  STR_LIVE_NAVIGATOR: \"Navigator\"\n  STR_LIVE_SOLDIER: \"Soldier\"\n  STR_LIVE_TERRORIST: \"Terrorist\"\n  STR_FLOATER_SOLDIER: \"Floater Soldier\"\n  STR_FLOATER_NAVIGATOR: \"Floater Navigator\"\n  STR_FLOATER_MEDIC: \"Floater Medic\"\n  STR_FLOATER_ENGINEER: \"Floater Engineer\"\n  STR_FLOATER_LEADER: \"Floater Leader\"\n  STR_FLOATER_COMMANDER: \"Floater Commander\"\n  STR_SECTOID_SOLDIER: \"Sectoid Soldier\"\n  STR_SECTOID_NAVIGATOR: \"Sectoid Navigator\"\n  STR_SECTOID_MEDIC: \"Sectoid Medic\"\n  STR_SECTOID_ENGINEER: \"Sectoid Engineer\"\n  STR_SECTOID_LEADER: \"Sectoid Leader\"\n  STR_SECTOID_COMMANDER: \"Sectoid Commander\"\n  STR_SNAKEMAN_SOLDIER: \"Snakeman Soldier\"\n  STR_SNAKEMAN_NAVIGATOR: \"Snakeman Navigator\"\n  STR_SNAKEMAN_ENGINEER: \"Snakeman Engineer\"\n  STR_SNAKEMAN_LEADER: \"Snakeman Leader\"\n  STR_SNAKEMAN_COMMANDER: \"Snakeman Commander\"\n  STR_MUTON_SOLDIER: \"Muton Soldier\"\n  STR_MUTON_NAVIGATOR: \"Muton Navigator\"\n  STR_MUTON_ENGINEER: \"Muton Engineer\"\n  STR_ETHEREAL_SOLDIER: \"Ethereal Soldier\"\n  STR_ETHEREAL_LEADER: \"Ethereal Leader\"\n  STR_ETHEREAL_COMMANDER: \"Ethereal Commander\"\n  STR_CYBERDISC_TERRORIST: \"Cyberdisc Terrorist\"\n  STR_REAPER_TERRORIST: \"Reaper Terrorist\"\n  STR_CHRYSSALID_TERRORIST: \"Chryssalid Terrorist\"\n  STR_CELATID_TERRORIST: \"Celatid Terrorist\"\n  STR_SILACOID_TERRORIST: \"Silacoid Terrorist\"\n  STR_SECTOPOD_TERRORIST: \"Sectopod Terrorist\"\n  STR_UFO_POWER_SOURCE: \"UFO Power Source\"\n  STR_UFO_NAVIGATION: \"UFO Navigation\"\n  STR_UFO_CONSTRUCTION: \"UFO Construction\"\n  STR_ALIEN_FOOD: \"Alien Food\"\n  STR_ALIEN_REPRODUCTION: \"Alien Reproduction\"\n  STR_ALIEN_ENTERTAINMENT: \"Alien Entertainment\"\n  STR_ALIEN_SURGERY: \"Alien Surgery\"\n  STR_EXAMINATION_ROOM: \"Examination Room\"\n  STR_ALIEN_ALLOYS: \"Alien Alloys\"\n  STR_ALIEN_HABITAT: \"Alien Habitat\"\n  STR_POWER_SUIT: \"Power Suit\"\n  STR_FLYING_SUIT: \"Flying Suit\"\n  STR_HWP_ROCKETS: \"HWP Rockets\"\n  STR_HWP_FUSION_BOMB: \"HWP Fusion Bomb\"\n  STR_LASER_WEAPONS: \"Laser Weapons\"\n  STR_NEW_FIGHTER_CRAFT: \"New Fighter Craft\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"New Fighter-Transporter\"\n  STR_ULTIMATE_CRAFT: \"Ultimate Craft\"\n  STR_LASER_PISTOL: \"Laser Pistol\"\n  STR_LASER_RIFLE: \"Laser Rifle\"\n  STR_HEAVY_LASER: \"Heavy Laser\"\n  STR_LASER_CANNON: \"Laser Cannon\"\n  STR_PLASMA_CANNON: \"Plasma Cannon\"\n  STR_FUSION_MISSILE: \"Fusion Missile\"\n  STR_LASER_DEFENSE: \"Laser Defence\"\n  STR_PLASMA_DEFENSE: \"Plasma Defence\"\n  STR_FUSION_DEFENSE: \"Fusion Defence\"\n  STR_GRAV_SHIELD: \"Grav Shield\"\n  STR_MIND_SHIELD: \"Mind Shield\"\n  STR_PSI_LAB: \"Psi-Lab\"\n  STR_MOTION_SCANNER: \"Motion Scanner\"\n  STR_MEDI_KIT: \"Medi-Kit\"\n  STR_TANK_CANNON: \"Tank/Cannon\"\n  STR_TANK_ROCKET_LAUNCHER: \"Tank/Rocket Launcher\"\n  STR_TANK_LASER_CANNON: \"Tank/Laser Cannon\"\n  STR_HOVERTANK_PLASMA: \"Hovertank/Plasma\"\n  STR_HOVERTANK_LAUNCHER: \"Hovertank/Launcher\"\n  STR_STINGRAY_LAUNCHER: \"Stingray Launcher\"\n  STR_AVALANCHE_LAUNCHER: \"Avalanche Launcher\"\n  STR_CANNON: \"Cannon\"\n  STR_FUSION_BALL_LAUNCHER: \"Fusion Ball Launcher\"\n  STR_PLASMA_BEAM: \"Plasma Beam\"\n  STR_STINGRAY_MISSILES: \"Stingray Missile\"\n  STR_AVALANCHE_MISSILES: \"Avalanche Missile\"\n  STR_CANNON_ROUNDS_X50: \"Cannon Rounds(x50)\"\n  STR_FUSION_BALL: \"Fusion Ball\"\n  STR_SOLDIER: \"Soldier\"\n  STR_SCIENTIST: \"Scientist\"\n  STR_ENGINEER: \"Engineer\"\n  STR_NORTH_AMERICA: \"North America\"\n  STR_ARCTIC: \"Arctic\"\n  STR_ANTARCTICA: \"Antarctica\"\n  STR_SOUTH_AMERICA: \"South America\"\n  STR_EUROPE: \"Europe\"\n  STR_NORTH_AFRICA: \"North Africa\"\n  STR_SOUTHERN_AFRICA: \"Southern Africa\"\n  STR_CENTRAL_ASIA: \"Central Asia\"\n  STR_SOUTH_EAST_ASIA: \"South East Asia\"\n  STR_SIBERIA: \"Siberia\"\n  STR_AUSTRALASIA: \"Australasia\"\n  STR_PACIFIC: \"Pacific\"\n  STR_NORTH_ATLANTIC: \"North Atlantic\"\n  STR_SOUTH_ATLANTIC: \"South Atlantic\"\n  STR_INDIAN_OCEAN: \"Indian Ocean\"\n  STR_ALIEN_RESEARCH: \"Alien Research\"\n  STR_ALIEN_HARVEST: \"Alien Harvest\"\n  STR_ALIEN_ABDUCTION: \"Alien Abduction\"\n  STR_ALIEN_INFILTRATION: \"Alien Infiltration\"\n  STR_ALIEN_BASE: \"Alien Base\"\n  STR_ALIEN_TERROR: \"Alien Terror\"\n  STR_ALIEN_RETALIATION: \"Alien Retaliation\"\n  STR_ALIEN_SUPPLY: \"Alien Supply\"\n  STR_MAXIMUM_SPEED: \"Maximum Speed\"\n  STR_HYPER_WAVE_DECODER_UC: \"HYPER-WAVE DECODER\"\n  STR_SKYRANGER: \"SKYRANGER\"\n  STR_LIGHTNING: \"LIGHTNING\"\n  STR_AVENGER: \"AVENGER\"\n  STR_INTERCEPTOR: \"INTERCEPTOR\"\n  STR_FIRESTORM: \"FIRESTORM\"\n  STR_UFO: \"UFO\"\n  STR_STINGRAY: \"STINGRAY\"\n  STR_AVALANCHE: \"AVALANCHE\"\n  STR_CANNON_UC: \"CANNON\"\n  STR_FUSION_BALL_UC: \"FUSION BALL\"\n  STR_LASER_CANNON_UC: \"LASER CANNON\"\n  STR_PLASMA_BEAM_UC: \"PLASMA BEAM\"\n  STR_DAMAGE_CAPACITY: \"Damage Capacity\"\n  STR_WEAPON_POWER: \"Weapon Power\"\n  STR_WEAPON_RANGE: \"Weapon Range\"\n  STR_ACCESS_LIFT: \"Access Lift\"\n  STR_LABORATORY: \"Laboratory\"\n  STR_WORKSHOP: \"Workshop\"\n  STR_SMALL_RADAR_SYSTEM: \"Small Radar System\"\n  STR_LARGE_RADAR_SYSTEM: \"Large Radar System\"\n  STR_MISSILE_DEFENSES: \"Missile Defences\"\n  STR_GENERAL_STORES: \"General Stores\"\n  STR_ALIEN_CONTAINMENT: \"Alien Containment\"\n  STR_LASER_DEFENSES: \"Laser Defences\"\n  STR_PLASMA_DEFENSES: \"Plasma Defences\"\n  STR_FUSION_BALL_DEFENSES: \"Fusion Ball Defences\"\n  STR_PSIONIC_LABORATORY: \"Psionic Laboratory\"\n  STR_HYPER_WAVE_DECODER: \"Hyper-wave Decoder\"\n  STR_HANGAR: \"Hangar\"\n  STR_USA: \"USA\"\n  STR_RUSSIA: \"RUSSIA\"\n  STR_UK: \"UK\"\n  STR_FRANCE: \"FRANCE\"\n  STR_GERMANY: \"GERMANY\"\n  STR_ITALY: \"ITALY\"\n  STR_SPAIN: \"SPAIN\"\n  STR_CHINA: \"CHINA\"\n  STR_JAPAN: \"JAPAN\"\n  STR_INDIA: \"INDIA\"\n  STR_BRAZIL: \"BRAZIL\"\n  STR_AUSTRALIA: \"AUSTRALIA\"\n  STR_NIGERIA: \"NIGERIA\"\n  STR_SOUTH_AFRICA: \"SOUTH AFRICA\"\n  STR_EGYPT: \"EGYPT\"\n  STR_CANADA: \"CANADA\"\n  STR_TANK: \"Tank\"\n  STR_CIVILIAN: \"Civilian\"\n  STR_JAN: \"Jan\"\n  STR_FEB: \"Feb\"\n  STR_MAR: \"Mar\"\n  STR_APR: \"Apr\"\n  STR_MAY: \"May\"\n  STR_JUN: \"Jun\"\n  STR_JUL: \"Jul\"\n  STR_AUG: \"Aug\"\n  STR_SEP: \"Sep\"\n  STR_OCT: \"Oct\"\n  STR_NOV: \"Nov\"\n  STR_DEC: \"Dec\"\n  STR_INTERNATIONAL_RELATIONS: \"International Relations\"\n  STR_COUNTRY: \"Country\"\n  STR_FUNDING: \"Funding\"\n  STR_CHANGE: \"Change\"\n  STR_WEAPON_SYSTEMS: \"WEAPON SYSTEMS\"\n  STR_HWPS: \"HWPs\"\n  STR_DAMAGE_UC_: \"DAMAGE>{ALT}{0}\"\n  STR_ACCESS_LIFT_UFOPEDIA: \"The access lift allows equipment and personnel to be transferred into or out of an underground base. It is always the first facility to be constructed on a new site. The lift area is vulnerable to intrusion from any potential hostile force.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Each accommodation block provides for up to 50 personnel. The facility provides basic recreation, food and sleeping areas.\"\n  STR_LABORATORY_UFOPEDIA: \"Up to 50 scientists can work in a laboratory facility. Laboratories are equipped with the latest technology for research into materials, biochemistry and cosmology. There is privileged access to the best research labs throughout the world, including military establishments.\"\n  STR_WORKSHOP_UFOPEDIA: \"A workshop contains all the equipment necessary to manufacture equipment based on designs from the science labs. Up to 50 engineers can occupy a workshop, although items under construction will also consume some space.\"\n  STR_SMALL_RADAR_SYSTEM_UFOPEDIA: \"A small detection system has an effective radar range of 300 nautical miles and is linked to satellite systems for ground search. Each system has a 10% chance of detecting an average sized object every 30 minutes.\"\n  STR_LARGE_RADAR_SYSTEM_UFOPEDIA: \"A large detection system has an effective range of 450 nautical miles and is linked to satellite systems for ground search. Each system has a 20% chance of detecting an average sized object every 30 minutes.\"\n  STR_MISSILE_DEFENSES_UFOPEDIA: \"Missile defences provide some protection against incursion by hostile craft which are attempting to land near the base.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"All equipment, weapons systems, munitions, recovered material and Heavy Weapons Platforms are placed in stores, including equipment assigned to craft in hangars.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"Living aliens are likely to require a special habitat to maintain their life systems. The containment facility can keep up to 10 alien life forms in self-contained units.\"\n  STR_LASER_DEFENSES_UFOPEDIA: \"Laser defences provide protection against incursion by hostile craft.\"\n  STR_PLASMA_DEFENSES_UFOPEDIA: \"Plasma beam defences provide powerful and efficient protection against incursion by hostile craft.\"\n  STR_FUSION_BALL_DEFENSES_UFOPEDIA: \"Fusion missiles provide the most effective defence against alien attacks. These missiles create an anti-matter implosion which destroys everything within a specific radius.\"\n  STR_GRAV_SHIELD_UFOPEDIA: \"The Gravity shield repels alien craft attempting to land near the base long enough for all defence systems to fire again. In practice this will double the effectiveness of any defence systems at your base.\"\n  STR_MIND_SHIELD_UFOPEDIA: \"Since alien craft rely on brain waves to detect human presence then the most effective counter measure is to shield brain waves from the base. This facility will drastically reduce the chances of detection by alien craft.\"\n  STR_PSIONIC_LABORATORY_UFOPEDIA: \"The psionics lab can assess the psionic potential of all soldiers at the base and give them the necessary training to utilise their psionic skills. Each lab can train up to ten soldiers. Training is allocated at the end of each month. Psionic skills used in conjunction with a Psi-amp can be used for psionic attacks during combat.\"\n  STR_HYPER_WAVE_DECODER_UFOPEDIA: \"Alien communications rely on a supra-dimensional wave which travels almost instantaneously. The decoder facility intercepts UFO transmissions and decodes the information. This will show the type of UFO, the alien race and the type of activity.\"\n  STR_HANGAR_UFOPEDIA: \"Each hangar can accommodate one craft. There are facilities for maintenance, refuelling and repair of X-Com craft. Each craft stationed at a base must have a free hangar assigned to it which cannot be used by other craft, even if the assigned craft is out on a mission.\"\n  STR_PISTOL_UFOPEDIA: \"The standard issue X-Com pistol is a high powered semi-automatic with a 12 round capacity.\"\n  STR_RIFLE_UFOPEDIA: \"This highly accurate sniper rifle has laser guided sights and takes 6.7mm ammunition in 20 round clips.\"\n  STR_HEAVY_CANNON_UFOPEDIA: \"The heavy cannon is a devastating, but cumbersome, weapon. Its versatility comes from the fact that it can take three types of ammunition - armour piercing, incendiary and high explosive.\"\n  STR_AUTO_CANNON_UFOPEDIA: \"The auto-cannon combines the versatility and power of a heavy cannon with a faster fire rate.\"\n  STR_ROCKET_LAUNCHER_UFOPEDIA: \"The rocket launcher is a laser guided system which can fire three different sizes of missile.\"\n  STR_LASER_PISTOL_UFOPEDIA: \"The laser pistol is an effective implementation of new technology. It has the convenience of a pistol with faster and more accurate firing.\"\n  STR_LASER_RIFLE_UFOPEDIA: \"The laser rifle is a more powerful and accurate version of the earlier pistol design.\"\n  STR_HEAVY_LASER_UFOPEDIA: \"The heavy laser is cumbersome, but extremely effective.\"\n  STR_GRENADE_UFOPEDIA: \"This standard issue grenade has an accurate and sophisticated timer for precision control.\"\n  STR_SMOKE_GRENADE_UFOPEDIA: \"Smoke grenades are useful for providing cover in exposed combat situations. Use with care because they can benefit the enemy as well.\"\n  STR_PROXIMITY_GRENADE_UFOPEDIA: \"A proximity grenade can be thrown like an ordinary grenade but is triggered by nearby movement after it lands. Great skill and care is required to use these devices properly.\"\n  STR_HIGH_EXPLOSIVE_UFOPEDIA: \"This explosive should only be used for demolition purposes. Keep personnel clear of demolition sites.\"\n  STR_MOTION_SCANNER_UFOPEDIA: \"This sophisticated device uses a variety of detectors and advanced computer algorithms to identify moving enemy units. However, it requires some practice to use effectively. Click on the motion scanner icon on the tactical display. Select 'Use Scanner' from the menu. The Scanner display shows an arrow in the centre which is the direction the soldier is facing (North is at the top). The flashing blobs show units which have moved recently. Large units, or fast moving units, will produce larger blobs. Static units will not be detected.\"\n  STR_MEDI_KIT_UFOPEDIA: \"The medi-kit combines a healing facility with pain killers and stimulants. In order to use the medi-kit you must face towards the soldier requiring treatment. If the soldier is stunned you must stand over the body. Click on the medi-kit icon and select 'use medi-kit' from the menu.{NEWLINE}HEALING> Red body parts show fatal wounds. Click on a body part that is wounded. Click on the 'Heal' button. One fatal wound will be cured and some health restored.{NEWLINE}STIMULANT> This will restore energy and revive unconscious (stunned) soldiers. In order to revive an unconscious soldier you must stand directly over the body.{NEWLINE}PAIN KILLER> This will restore the morale of wounded soldiers up to an amount equivalent to the soldier's lost health.\"\n  STR_PSI_AMP_UFOPEDIA: \"The Psi-amp can only be used by soldiers with psionic skill. During combat, click on the Psi-amp, select the type of attack, and select a target unit with the cursor. There are two types of psionic attack:{NEWLINE}PANIC UNIT> If the attack is successful it will reduce the target's morale and may cause it to panic.{NEWLINE}MIND CONTROL> If this is successful then you will gain immediate control of the enemy unit as if it was one of your own. It is more difficult to be successful with this type of attack.\"\n  STR_STUN_ROD_UFOPEDIA: \"This device can only be used in close combat, but will stun a living organism without killing it by using electric shocks.\"\n  STR_MIND_PROBE_UFOPEDIA: \"The mind probe is an alien communication device which is used to take information directly from brain waves. X-Com units can use this device in combat to display an alien's characteristics. Click on the mind probe and the 'use' option. Then click on an alien with the cursor.\"\n  STR_PLASMA_PISTOL_UFOPEDIA: \"Plasma Pistols are a lethal alien weapon based on accelerating particles from within a minute anti-gravity field.\"\n  STR_PLASMA_RIFLE_UFOPEDIA: \"This is a devastatingly powerful weapon based on accelerating particles from within a minute anti-gravity field.\"\n  STR_HEAVY_PLASMA_UFOPEDIA: \"This is a devastatingly powerful weapon based on accelerating particles from within a minute anti-gravity field.\"\n  STR_BLASTER_LAUNCHER_UFOPEDIA: \"This is an alien guided missile launcher which fires powerful 'blaster bombs'. When you click to fire the weapon it will generate 'way points' for the blaster bomb to follow. When you have positioned enough way points click on the special launch icon.\"\n  STR_SMALL_LAUNCHER_UFOPEDIA: \"A small launcher which fires stun bombs. Very useful for capturing live aliens.\"\n  STR_ALIEN_GRENADE_UFOPEDIA: \"This device works in the same way as a terrestrial grenade - except that it is more powerful.\"\n  STR_SMALL_SCOUT: \"Small Scout\"\n  STR_MEDIUM_SCOUT: \"Medium Scout\"\n  STR_LARGE_SCOUT: \"Large Scout\"\n  STR_HARVESTER: \"Harvester\"\n  STR_ABDUCTOR: \"Abductor\"\n  STR_TERROR_SHIP: \"Terror ship\"\n  STR_BATTLESHIP: \"Battleship\"\n  STR_SUPPLY_SHIP: \"Supply ship\"\n  STR_RATING: \"RATING> {0}\"\n  STR_RATING_TERRIBLE: \"TERRIBLE!\"\n  STR_RATING_POOR: \"POOR!\"\n  STR_RATING_OK: \"OK\"\n  STR_RATING_GOOD: \"GOOD!\"\n  STR_RATING_EXCELLENT: \"EXCELLENT!\"\n  STR_SCORE: \"SCORE\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"X-COM PROJECT MONTHLY REPORT\"\n  STR_MONTH: \"Month> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"The council of funding nations is generally satisfied with your progress so far.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"The council of funding nations is very pleased with your excellent progress. Keep up the good work.\"\n  STR_COUNCIL_IS_DISSATISFIED: \"The council of funding nations is dissatisfied with your performance. You must improve your effectiveness in dealing with the alien menace or risk termination of the project.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"You have not succeeded in dealing with the alien invasion and the council of funding nations has regrettably decided to terminate the project. Each nation shall deal with the problem as they see fit. We can only hope that we can come to some accommodation with these apparently hostile forces, and that the general population will come to terms with the alien visitors.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} is particularly pleased with your ability to deal with the localised threat and has agreed to increase its funding.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} are particularly happy with your progress in dealing with local alien incursion and have agreed to increase their funding.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} and {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} is unhappy with your ability to deal with alien activity in its territory and has decided to reduce its financial commitment.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} are unhappy with your ability to deal with alien activity in their territory and have decided to reduce their funding.\"\n  STR_KNOTS: \"{0} knots\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} has signed a secret pact with unknown alien forces and has withdrawn from the project.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} have signed a secret pact with unknown alien forces and have withdrawn from the project.\"\n  STR_MONTHLY_RATING: \"Monthly Rating> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Funding change> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"The funding council is not happy with your financial position. You must reduce your debts below $2million or the project will be terminated.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"HYPER-WAVE TRANSMISSIONS ARE DECODED\"\n  STR_CRAFT_TYPE: \"CRAFT TYPE\"\n  STR_RACE: \"RACE\"\n  STR_MISSION: \"MISSION\"\n  STR_ZONE: \"ZONE\"\n  STR_ALLOCATE_RESEARCH: \"Allocate Research\"\n  STR_ALLOCATE_MANUFACTURE: \"Allocate Manufacture\"\n  STR_NEW_YORK: \"New York\"\n  STR_WASHINGTON: \"Washington\"\n  STR_LOS_ANGELES: \"Los Angeles\"\n  STR_MONTREAL: \"Montreal\"\n  STR_HAVANA: \"Havana\"\n  STR_MEXICO_CITY: \"Mexico City\"\n  STR_CHICAGO: \"Chicago\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_DALLAS: \"Dallas\"\n  STR_BRASILIA: \"Brasilia\"\n  STR_BOGOTA: \"Bogota\"\n  STR_BUENOS_AIRES: \"Buenos Aires\"\n  STR_SANTIAGO: \"Santiago\"\n  STR_RIO_DE_JANEIRO: \"Rio De Janeiro\"\n  STR_LIMA: \"Lima\"\n  STR_CARACAS: \"Caracas\"\n  STR_LONDON: \"London\"\n  STR_PARIS: \"Paris\"\n  STR_BERLIN: \"Berlin\"\n  STR_MOSCOW: \"Moscow\"\n  STR_ROME: \"Rome\"\n  STR_MADRID: \"Madrid\"\n  STR_BUDAPEST: \"Budapest\"\n  STR_LAGOS: \"Lagos\"\n  STR_CAIRO: \"Cairo\"\n  STR_CASABLANCA: \"Casablanca\"\n  STR_PRETORIA: \"Pretoria\"\n  STR_NAIROBI: \"Nairobi\"\n  STR_CAPE_TOWN: \"Cape Town\"\n  STR_KINSHASA: \"Kinshasa\"\n  STR_ANKARA: \"Ankara\"\n  STR_DELHI: \"Delhi\"\n  STR_KARACHI: \"Karachi\"\n  STR_BAGHDAD: \"Baghdad\"\n  STR_TEHRAN: \"Tehran\"\n  STR_BOMBAY: \"Bombay\"\n  STR_CALCUTTA: \"Calcutta\"\n  STR_TOKYO: \"Tokyo\"\n  STR_BEIJING: \"Beijing\"\n  STR_BANGKOK: \"Bangkok\"\n  STR_MANILA: \"Manila\"\n  STR_SEOUL: \"Seoul\"\n  STR_SINGAPORE: \"Singapore\"\n  STR_JAKARTA: \"Jakarta\"\n  STR_SHANGHAI: \"Shanghai\"\n  STR_HONG_KONG: \"Hong Kong\"\n  STR_NOVOSIBIRSK: \"Novosibirsk\"\n  STR_CANBERRA: \"Canberra\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_MELBOURNE: \"Melbourne\"\n  STR_PERTH: \"Perth\"\n  STR_PSI_TRAINING: \"Psi Training\"\n  STR_PSIONIC_TRAINING: \"PSIONIC TRAINING\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Remaining Psi-lab capacity> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"Psionic{NEWLINE}Strength\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"Psionic Skill{NEWLINE}/Improvement\"\n  STR_PSI_AMP: \"Psi-Amp\"\n  STR_IN_TRAINING: \"In{NEWLINE}Training?\"\n  STR_TARGETTED_BY: \"TARGETTED BY:\"\n  STR_WEAPONS_CREW_HWPS: \"WEAPONS/{NEWLINE}CREW/HWPs\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"is low on fuel,{NEWLINE}returning to base\"\n  STR_SOLDIER_LIST: \"Soldier List\"\n  STR_RANK_: \"RANK> {ALT}{0}\"\n  STR_MISSIONS: \"MISSIONS> {ALT}{0}\"\n  STR_KILLS: \"KILLS> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"WOUND RECOVERY> {ALT}{0}\"\n  STR_TIME_UNITS: \"TIME UNITS\"\n  STR_STAMINA: \"STAMINA\"\n  STR_HEALTH: \"HEALTH\"\n  STR_BRAVERY: \"BRAVERY\"\n  STR_REACTIONS: \"REACTIONS\"\n  STR_FIRING_ACCURACY: \"FIRING ACCURACY\"\n  STR_THROWING_ACCURACY: \"THROWING ACCURACY\"\n  STR_STRENGTH: \"STRENGTH\"\n  STR_PSIONIC_STRENGTH: \"PSIONIC STRENGTH\"\n  STR_PSIONIC_SKILL: \"PSIONIC SKILL\"\n  STR_NEW_RANK: \"NEW RANK\"\n  STR_PROMOTIONS: \"Promotions\"\n  STR_SOLDIERS_UC: \"SOLDIERS\"\n  STR_TANK_CANNON_UFOPEDIA: \"Automated Heavy Weapons Platforms are designed to complement an X-Com squad. The combination of high fire power and strong armour makes these units valuable for open terrain fire fights. Make sure that there are sufficient cannon shells in your stores to re-arm tanks. They are armed automatically when you assign them to a squad.\"\n  STR_TANK_ROCKET_LAUNCHER_UFOPEDIA: \"This automated Heavy Weapons Platform is armed with powerful rockets. This will be devastating for any alien foe. Make sure your stores are kept supplied with HWP rockets.\"\n  STR_TANK_LASER_CANNON_UFOPEDIA: \"Laser weapons are a useful addition for HWPs. It combines heavy firepower with no ammunition restrictions.\"\n  STR_HOVERTANK_PLASMA_UFOPEDIA: \"Alien technology has given the HWP a new lease of life. The added manoeuvrability of air travel and the power of plasma beams is a lethal combination.\"\n  STR_HOVERTANK_LAUNCHER_UFOPEDIA: \"This hovertank has a fusion ball launcher that is capable of immense devastation. Use it with great care. You will have to manufacture the fusion balls to keep these HWPs fully armed. A fusion ball is an intelligent guided weapon. In order to fire it you select a number of 'way points' with the cursor and then click on the launch icon to fire the fusion ball.\"\n  STR_HEAVY_PLASMA_CLIP_UFOPEDIA: \"This compact device is used as ammunition for a Heavy Plasma Gun. It contains a small quantity of Elerium.\"\n  STR_PLASMA_RIFLE_CLIP_UFOPEDIA: \"This small object is used as a power source for a Plasma Rifle - a medium powered alien weapon. Contains a small quantity of Elerium.\"\n  STR_PLASMA_PISTOL_CLIP_UFOPEDIA: \"Power source for the small alien Plasma Pistol. Contains Elerium - the source of all alien power.\"\n  STR_STUN_BOMB_UFOPEDIA: \"The Stun Bomb is used for capturing live human specimens, but it can also be used against most alien races. It is fired from a Small Launcher.\"\n  STR_ALIEN_RESEARCH_UFOPEDIA: \"The alien research mission is used for collecting basic data on earth and its inhabitants. Small vehicles are predominantly used, with occasional landings in deserted areas. This type of alien activity poses the least threat to X-Com, with little concern from governments or the public.\"\n  STR_ALIEN_HARVEST_UFOPEDIA: \"The aliens have many uses for earth's fauna. Animals are abducted secretly, and returned with various organs removed. Cattle mutilations are predominantly reported along with UFO sightings. This type of alien activity causes great concern for governments and considerable anxiety amongst the population. This type of activity occurs mainly in farming land. The theory behind the 'alien harvest' suggests that alien races originally 'seeded' the planet with its flora and fauna, and now they have returned to reap the harvest they have sown.\"\n  STR_ALIEN_ABDUCTION_UFOPEDIA: \"This is the most insidious form of alien activity. The abduction by aliens is widely reported, despite the aliens' attempts to erase the experience from their victims' memories. Abductees report being subject to humiliating physical examinations, including impregnation of alien foetuses and bizarre genetic experiments. The purpose behind this activity appears to be linked to genetic mutation and manipulation of the aliens' own genetic material. This activity causes great alarm, and occurs in populated areas or cities\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"Earth governments can be infiltrated by alien agents which are human in appearance. This can result in official contact between aliens and governments at the highest level. The climax of this activity is characterised by intense UFO activity in the vicinity of major cities. The aliens will attempt to sign a pact with an earth government by offering knowledge of their superior technology. In return the government will allow the aliens to conduct their activity unhindered. This alien mission represents the worst threat to X-Com. If a government agrees to a pact then its funding will cease.\"\n  STR_ALIEN_BASE_UFOPEDIA: \"Aliens will construct secret underground bases in remote locations. After some initial reconnaissance flights some intense UFO activity will occur as the base is being built. These bases are known to contain experimental labs for human abductees, and supplies for further activity in the region. The presence of alien bases will generate a large amount of reported alien activity without the presence of UFOs. In order to locate a base an X-Com craft must patrol an area for a few hours to stand some chance of detection.\"\n  STR_ALIEN_TERROR_UFOPEDIA: \"When the aliens terrorise a city they will deploy some special forces with awesome powers. Civilians will be directly threatened, and governments will be forced to evacuate whole areas. The main purpose behind this activity is to generate sufficient public hysteria so that governments will threaten the X-Com project.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"If X-Com interceptors are being particularly successful in shooting down UFOs then the aliens may take some retaliatory action. This could result in a direct attack against an X-Com base. However, the aliens have to find an X-Com base in order to attack it, and provided UFOs are kept away then there should be little danger of an assault.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"Once an alien base is constructed then it is resupplied on a regular basis by a special supply vessel. If one of these vessels is detected while landing then it is certain that an alien base is nearby.\"\n  STR_SMALL_SCOUT_UFOPEDIA: \"This tiny craft is primarily used for reconnaissance or research. It normally precedes larger vessels at the start of an alien mission.\"\n  STR_MEDIUM_SCOUT_UFOPEDIA: \"A medium sized scout vessel that poses little threat to earth forces. Normally appears before larger vessels during missions.\"\n  STR_LARGE_SCOUT_UFOPEDIA: \"The largest alien scout craft is a general purpose vessel that is used in all types of alien mission.\"\n  STR_HARVESTER_UFOPEDIA: \"The harvester has a trap door in its base and is equipped with lifting gear to haul up cattle or other beasts. Laser cutters are used to extract the desired material and the carcass is dumped on the ground. There are also storage containers for body parts.\"\n  STR_ABDUCTOR_UFOPEDIA: \"This vessel is equipped with an examination room for performing horrific experiments on human subjects. The victim is normally paralysed by telepathic powers, but remains conscious while on the operating table.\"\n  STR_TERROR_SHIP_UFOPEDIA: \"The terror ship has a containment facility for large alien terror weapons or creatures. It is used to transport these alien terrorists into populated areas.\"\n  STR_BATTLESHIP_UFOPEDIA: \"The battleship is the largest and most powerful alien craft. It is normally the primary alien mission craft, equipped with powerful weapons and numerous crew members.\"\n  STR_SUPPLY_SHIP_UFOPEDIA: \"The supply vessel is used during the construction of alien bases or for supplying existing bases. It carries alien food containers and reproduction chambers.\"\n  STR_DISMANTLE: \"Dismantle\"\n  STR_FACILITY_IN_USE: \"FACILITY IN USE\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"CANNOT DISMANTLE FACILITY!{SMALLLINE}All base facilities must be linked to the access lift.\"\n  STR_TRANSFER_ITEMS_TO: \"Transfer Items to {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"NO ALIEN CONTAINMENT FOR TRANSFER!{SMALLLINE}Live aliens need an alien containment facility in order to survive \"\n  STR_AMOUNT_AT_DESTINATION: \"AMOUNT AT{NEWLINE}DESTINATION\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"Alien dies as there is no alien containment facility\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"NO FREE ACCOMMODATION!{SMALLLINE}The destination base does not have enough space in the living quarters for the crew assigned to the craft.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"NOT ENOUGH STORE SPACE!{SMALLLINE}The destination base does not have enough store space for the equipment assigned to the craft.\"\n  STR_ITEMS_ARRIVING: \"Items Arriving\"\n  STR_DESTINATION_UC: \"DESTINATION\"\n  STR_PISTOL: \"Pistol\"\n  STR_PISTOL_CLIP: \"Pistol Clip\"\n  STR_RIFLE: \"Rifle\"\n  STR_RIFLE_CLIP: \"Rifle Clip\"\n  STR_HEAVY_CANNON: \"Heavy Cannon\"\n  STR_HC_AP_AMMO: \"HC-AP Ammo\"\n  STR_HC_HE_AMMO: \"HC-HE Ammo\"\n  STR_HC_I_AMMO: \"HC-I Ammo\"\n  STR_AUTO_CANNON: \"Auto-Cannon\"\n  STR_AC_AP_AMMO: \"AC-AP Ammo\"\n  STR_AC_HE_AMMO: \"AC-HE Ammo\"\n  STR_AC_I_AMMO: \"AC-I Ammo\"\n  STR_ROCKET_LAUNCHER: \"Rocket Launcher\"\n  STR_SMALL_ROCKET: \"Small Rocket\"\n  STR_LARGE_ROCKET: \"Large Rocket\"\n  STR_INCENDIARY_ROCKET: \"Incendiary Rocket\"\n  STR_GRENADE: \"Grenade\"\n  STR_SMOKE_GRENADE: \"Smoke Grenade\"\n  STR_PROXIMITY_GRENADE: \"Proximity Grenade\"\n  STR_HIGH_EXPLOSIVE: \"High Explosive\"\n  STR_STUN_ROD: \"Stun Rod\"\n  STR_HEAVY_PLASMA: \"Heavy Plasma\"\n  STR_HEAVY_PLASMA_CLIP: \"Heavy Plasma Clip\"\n  STR_PLASMA_RIFLE: \"Plasma Rifle\"\n  STR_PLASMA_RIFLE_CLIP: \"Plasma Rifle Clip\"\n  STR_PLASMA_PISTOL: \"Plasma Pistol\"\n  STR_PLASMA_PISTOL_CLIP: \"Plasma Pistol Clip\"\n  STR_BLASTER_LAUNCHER: \"Blaster Launcher\"\n  STR_BLASTER_BOMB: \"Blaster Bomb\"\n  STR_SMALL_LAUNCHER: \"Small Launcher\"\n  STR_STUN_BOMB: \"Stun Bomb\"\n  STR_ALIEN_GRENADE: \"Alien Grenade\"\n  STR_ELERIUM_115: \"Elerium-115\"\n  STR_MIND_PROBE: \"Mind Probe\"\n  STR_SECTOID_CORPSE: \"Sectoid Corpse\"\n  STR_SNAKEMAN_CORPSE: \"Snakeman Corpse\"\n  STR_ETHEREAL_CORPSE: \"Ethereal Corpse\"\n  STR_MUTON_CORPSE: \"Muton Corpse\"\n  STR_FLOATER_CORPSE: \"Floater Corpse\"\n  STR_CELATID_CORPSE: \"Celatid Corpse\"\n  STR_SILACOID_CORPSE: \"Silacoid Corpse\"\n  STR_CHRYSSALID_CORPSE: \"Chryssalid Corpse\"\n  STR_REAPER_CORPSE: \"Reaper Corpse\"\n  STR_SECTOPOD_CORPSE: \"Sectopod Corpse\"\n  STR_CYBERDISC_CORPSE: \"Cyberdisc Corpse\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"Not enough ammunition to arm HWP{SMALLLINE}Each HWP requires {0} {1}.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Not enough equipment to fully re-equip squad\"\n  STR_MARS_CYDONIA_LANDING: \"Mars: Cydonia Landing\"\n  STR_MARS_CYDONIA_LANDING_BRIEFING: \"Your Avenger craft has landed in the region of Cydonia on the surface of Mars. Our information indicates that one of the pyramid constructions contains a green access lift to an underground complex. Once you have assembled all your soldiers in the lift area click on the 'abort mission' icon to continue to the next stage.\"\n  STR_MARS_THE_FINAL_ASSAULT: \"Mars: The Final Assault\"\n  STR_MARS_THE_FINAL_ASSAULT_BRIEFING: \"The pyramid lift takes your battle weary soldiers deep below the planet's surface. They arrive in the heart of a large complex of tunnels and chambers. The alien brain is hidden somewhere in the labyrinth. It must be destroyed if the earth is to be saved from alien enslavement.{NEWLINE}{NEWLINE}Good Luck!\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"You will need to research a{NEWLINE}{0}{NEWLINE}in order to produce the{NEWLINE}{1}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"The aliens have destroyed the undefended base {0}\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"X-Com agents have located an alien base in {0}\"\n  STR_STANDOFF: \"STANDOFF\"\n  STR_CAUTIOUS_ATTACK: \"CAUTIOUS ATTACK\"\n  STR_STANDARD_ATTACK: \"STANDARD ATTACK\"\n  STR_AGGRESSIVE_ATTACK: \"AGGRESSIVE ATTACK\"\n  STR_DISENGAGING: \"DISENGAGING\"\n  STR_UFO_HIT: \"UFO HIT!\"\n  STR_UFO_CRASH_LANDS: \"UFO CRASH LANDS!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Minimise at Standoff Range Only\"\n  STR_UFO_RETURN_FIRE: \"UFO RETURNS FIRE!\"\n  STR_INTERCEPTOR_DAMAGED: \">>> INTERCEPTOR DAMAGED <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> INTERCEPTOR DESTROYED <<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"UFO OUTRUNNING INTERCEPTOR!\"\n  STR_ALIENS_TERRORISE: \"ALIENS TERRORISE\"\n  STR_LONG_RANGE_DETECTION: \"Long Range Detection\"\n  STR_STORES_UC: \"STORES\"\n  STR_DIFFICULTY_LEVEL: \"Difficulty Level\"\n  STR_INTERCEPT: \"INTERCEPT\"\n  STR_BASES: \"BASES\"\n  STR_GRAPHS: \"GRAPHS\"\n  STR_UFOPAEDIA_UC: \"UFOPAEDIA\"\n  STR_OPTIONS_UC: \"OPTIONS\"\n  STR_FUNDING_UC: \"FUNDING\"\n  STR_5_SECONDS: \"5 Secs\"\n  STR_1_MINUTE: \"1 Min\"\n  STR_5_MINUTES: \"5 Mins\"\n  STR_30_MINUTES: \"30 Mins\"\n  STR_1_HOUR: \"1 Hour\"\n  STR_1_DAY: \"1 Day\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"X-Com Performance Roster\"\n  STR_ENTER_NAME: \"Enter Name\"\n  STR_PERFORMANCE_RATING: \"Performance Rating\"\n  STR_VICTORY_DATE: \"Victory Date\"\n  STR_ELECTRO_FLARE: \"Electro-flare\"\n  STR_ELECTRO_FLARE_UFOPEDIA: \"This compact device produces a bright flare light when it is thrown. This will highlight enemy units in the vicinity of the electro-flare during night time missions.\"\n  STR_MONTHLY_COSTS: \"Monthly Costs\"\n  STR_CRAFT_RENTAL: \"Craft Rental\"\n  STR_SALARIES: \"Salaries\"\n  STR_BASE_MAINTENANCE: \"Base maintenance\"\n  STR_COST_PER_UNIT: \"Cost per unit\"\n  STR_QUANTITY: \"Quantity\"\n  STR_TOTAL: \"Total\"\n  STR_IN_PSIONIC_TRAINING: \"In Psionic Training\"\n  STR_BLASTER_BOMB_UFOPEDIA: \"This device is a highly explosive missile that has an intelligent guidance system. It is fired from a Blaster Launcher.\"\n  STR_FRONT_ARMOR: \"Front Armour\"\n  STR_LEFT_ARMOR: \"Left Armour\"\n  STR_RIGHT_ARMOR: \"Right Armour\"\n  STR_REAR_ARMOR: \"Rear Armour\"\n  STR_UNDER_ARMOR: \"Under Armour\"\n  STR_ROUNDS: \"Rounds\"\n  STR_UNIT: \"UNIT> {0}\"\n  STR_ENERGY: \"ENERGY\"\n  STR_MORALE: \"MORALE\"\n  STR_ARMOR_: \"ARMOR> {0}\"\n  STR_FRONT_ARMOR_UC: \"FRONT ARMOUR\"\n  STR_LEFT_ARMOR_UC: \"LEFT ARMOUR\"\n  STR_RIGHT_ARMOR_UC: \"RIGHT ARMOUR\"\n  STR_REAR_ARMOR_UC: \"REAR ARMOUR\"\n  STR_SKILLS: \"SKILLS> {0}\"\n  STR_LEVEL: \"LEVEL> {0}\"\n  STR_HEAD: \"HEAD\"\n  STR_TORSO: \"TORSO\"\n  STR_RIGHT_ARM: \"RIGHT ARM\"\n  STR_LEFT_ARM: \"LEFT ARM\"\n  STR_RIGHT_LEG: \"RIGHT LEG\"\n  STR_LEFT_LEG: \"LEFT LEG\"\n  STR_PAIN_KILLER: \"PAIN KILLER\"\n  STR_STIMULANT: \"STIMULANT\"\n  STR_HEAL: \"HEAL\"\n  STR_TIME_UNITS_SHORT: \"TU>{ALT}{0}\"\n  STR_WEIGHT: \"Weight>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"React>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"P.Skill>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"P.Str>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Alien Artefact\"\n  STR_AMMO_ROUNDS_LEFT: \"AMMO:{NEWLINE}ROUNDS{NEWLINE}LEFT={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Pain>{ALT}{0}{ALT}{NEWLINE}Stim>{ALT}{1}{ALT}{NEWLINE}Heal>{ALT}{2}\"\n  STR_THROW: \"Throw\"\n  STR_AUTO_SHOT: \"Auto Shot\"\n  STR_SNAP_SHOT: \"Snap Shot\"\n  STR_AIMED_SHOT: \"Aimed Shot\"\n  STR_STUN: \"Stun\"\n  STR_PRIME_GRENADE: \"Prime Grenade\"\n  STR_USE_SCANNER: \"Use Scanner\"\n  STR_USE_MEDI_KIT: \"Use Medi-kit\"\n  STR_LAUNCH_MISSILE: \"Launch Missile\"\n  STR_ACCURACY_SHORT: \"Acc>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Not Enough Time Units!\"\n  STR_NOT_ENOUGH_ENERGY: \"Not Enough Energy!\"\n  STR_NO_ROUNDS_LEFT: \"No Rounds left!\"\n  STR_NO_AMMUNITION_LOADED: \"No Ammunition Loaded!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Wrong Ammunition for this Weapon!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"Weapon is already loaded!\"\n  STR_NO_LINE_OF_FIRE: \"No Line of Fire!\"\n  STR_GRENADE_IS_ACTIVATED: \"Grenade is Activated!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Grenade De-activated!\"\n  STR_THERE_IS_NO_ONE_THERE: \"There is no one there!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Unable to use alien artefact until researched!\"\n  STR_OUT_OF_RANGE: \"Out of Range!\"\n  STR_UNABLE_TO_THROW_HERE: \"Unable to throw here!\"\n  STR_SET_TIMER: \"Set Timer\"\n  STR_HIDDEN_MOVEMENT: \"HIDDEN MOVEMENT\"\n  STR_TURN: \"TURN> {0}\"\n  STR_SIDE: \"SIDE> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Press button to continue\"\n  STR_MIND_CONTROL: \"Mind Control\"\n  STR_PANIC_UNIT: \"Panic Unit\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Morale Attack Successful\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Mind Control Successful\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}has gone Berserk\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}has gone Berserk\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}has Panicked\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}has Panicked\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Aliens\"\n  STR_RIGHT_HAND: \"RIGHT HAND\"\n  STR_LEFT_HAND: \"LEFT HAND\"\n  STR_RIGHT_SHOULDER: \"RIGHT SHOULDER\"\n  STR_LEFT_SHOULDER: \"LEFT SHOULDER\"\n  STR_BACK_PACK: \"BACK PACK\"\n  STR_BELT: \"BELT\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}is under alien control\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}is under alien control\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}has become unconscious\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}has become unconscious\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}has died from a fatal wound\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}has died from a fatal wound\"\n  STR_USE_MIND_PROBE: \"Use Mind Probe\"\n  STR_FATAL_WOUNDS: \"FATAL WOUNDS\"\n  STR_UNDER_ARMOR_UC: \"UNDER ARMOUR\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Time Units reserved for Snap Shot\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Time Units reserved for Auto Shot\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Time Units reserved for Aimed Shot\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Time Units reserved for Kneeling\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"TUs reserved for Kneeling and Firing\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} Unit in X-Com Craft\"\n    other: \"{N} Units in X-Com Craft\"\n  STR_UNITS_OUTSIDE:\n    one: \"{N} Unit left outside\"\n    other: \"{N} Units left outside\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} Unit in Entrance\"\n    other: \"{N} Units in Entrance\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} Unit in Target Exit\"\n    other: \"{N} Units in Target Exit\"\n  STR_ABORT_MISSION_QUESTION: \"Abort Mission?\"\n  STR_CORPSE: \"Corpse\"\n  STR_UNLOAD_CRAFT: \"Unload\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}has been killed\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}has been killed\"\n  STR_HIT_MELEE: \"Hit\"\n  STR_GROUND: \"GROUND\"\n  STR_LIVING_QUARTERS_PLURAL: \"Living Quarters\"\n  STR_LIST_ITEM: \"ITEM\"\n  STR_PERSONAL_ARMOR_UFOPEDIA: \"Using the newly discovered Alien Alloys, this new armour gives our men a fighting chance against the alien threat.\"\n  STR_POWER_SUIT_UFOPEDIA: \"A powerful new protection for soldiers, this armour is powered by an Elerium energy source and greatly amplifies the speed and strength of the wearer, it offers the best protection yet for combat troops.\"\n  STR_FLYING_SUIT_UFOPEDIA: \"An enhanced version of the Power Suit, incorporating alien anti-gravity navigation technology to allow full freedom of movement across the battlefield.\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"All Aliens killed in crash,{NEWLINE}Auto recovery initiated\"\n  STR_RESET: \"Reset\"\n  STR_MEMORIAL: \"Memorial\"\n  STR_DATE_UC: \"DATE\"\n  STR_SOLDIERS_RECRUITED_UC: \"SOLDIERS RECRUITED>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"SOLDIERS LOST>{ALT}{0}\"\n  MAP_CULTA: \"Farm\"\n  MAP_FOREST: \"Forest\"\n  MAP_JUNGLE: \"Jungle\"\n  MAP_MOUNT: \"Mountain\"\n  MAP_DESERT: \"Desert\"\n  MAP_POLAR: \"Polar\"\n  MAP_URBAN: \"City\"\n  MAP_UBASE: \"Alien Base\"\n  MAP_XBASE: \"X-Com Base\"\n  MAP_MARS: \"Mars\"\n  STR_MIXED: \"Mixed\"\n  STR_REMOVE_SELECTED: \"Remove Selected\"\n  STR_LIVE_ALIENS: \"Live{NEWLINE}Specimens\"\n  STR_DEAD_ALIENS: \"Rejected{NEWLINE}Specimens\"\n  STR_UNDER_INTERROGATION: \"Being{NEWLINE}Studied\"\n  STR_CONTAINMENT_EXCEEDED: \"ALIEN CONTAINMENT LIMITS EXCEEDED!{SMALLLINE}Insufficient containment space at {0}. You must remove excess aliens from containment (who will then die).\"\n  STR_MANAGE_CONTAINMENT: \"Manage Alien Containment\"\n  STR_STORAGE_EXCEEDED: \"STORAGE SPACE EXCEEDED!{SMALLLINE}Insufficient storage space at {0}. You must sell off excess items.\"\n  STR_GO_TO_BASE: \"Go to Base\"\n  STR_MELEE_ACCURACY: \"MELEE ACCURACY\"\n  STR_SELL_PRODUCTION: \"SELL\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Both hands must be empty!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Not enough items to copy template!\"\n  STR_UNLOAD_WEAPON: \"Unload weapon\"\n  STR_ALL_ITEMS: \"All Items\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"NO MORE EQUIPMENT ALLOWED ON BOARD!{SMALLLINE}You are only allowed to take a maximum of {N} item of equipment on this craft.\"\n    other: \"NO MORE EQUIPMENT ALLOWED ON BOARD!{SMALLLINE}You are only allowed to take a maximum of {N} items of equipment on this craft.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}CONTROL CENTER DESTROYED{NEWLINE}Make your way to the entrance and abort.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"X-Com facilities cannot be built underwater\"\n  STR_LEVEL_SHORT: \"{0}\"\n  STR_PERSONNEL: \"Personnel\"\n  STR_CRAFT_ARMAMENT: \"Craft & Armament\"\n  STR_COMPONENTS: \"Components\"\n  STR_SOLDIERS_RECRUITED: \"Soldiers recruited\"\n  STR_SOLDIERS_LOST: \"Soldiers lost\"\n  STR_TOTAL_UFOS: \"UFOs detected\"\n  STR_TOTAL_ALIEN_BASES: \"Alien bases discovered\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"PST\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"PSK\"\n  FEMALE_CIVILIAN: \"Civilian, Female\"\n  MALE_CIVILIAN: \"Civilian, Male\"\n  CYBERDISC_WEAPON: \"Cyberdisc Weapon\"\n  REAPER_WEAPON: \"Reaper Weapon\"\n  CHRYSSALID_WEAPON: \"Chryssalid Weapon\"\n  CELATID_WEAPON: \"Celatid Weapon\"\n  SILACOID_WEAPON: \"Silacoid Weapon\"\n  SECTOPOD_WEAPON: \"Sectopod Weapon\"\n  ZOMBIE_WEAPON: \"Zombie Weapon\"\n  ALIEN_PSI_WEAPON: \"Alien Psi Weapon\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/en-US.yml",
    "content": "en-US:\n  STR_AVENGER_UFOPEDIA: \"TRANSPORTER AND COMBAT SPACECRAFT. THE ULTIMATE REPLICATION OF ALIEN TECHNOLOGY.\"\n  STR_INTERCEPTOR_UFOPEDIA: \"COMBAT AIRCRAFT WITH DUAL PULSE DETONATION ENGINES AND SPECIALLY SHIELDED ELECTRONIC SYSTEMS. THE BEST AVAILABLE EARTH BASED TECHNOLOGY.\"\n  STR_LIGHTNING_UFOPEDIA: \"TRANSPORTER AND COMBAT CRAFT. A CRUDE BUT EFFECTIVE REPLICATION OF ALIEN PROPULSION SYSTEMS.\"\n  STR_SKYRANGER_UFOPEDIA: \"TROOP TRANSPORTER. THE FASTEST OF ITS KIND, WITH VERTICAL TAKE OFF AND LANDING (V.T.O.L.) CAPABILITY.\"\n  STR_FIRESTORM_UFOPEDIA: \"COMBAT CRAFT. THIS ONE-MAN FIGHTER REPLICATES THE CLASSIC ALIEN FLYING SAUCER DESIGN, WITH CENTRAL PROPULSION UNIT.\"\n  STR_STINGRAY_UFOPEDIA: \"ADVANCED AIR TO AIR MISSILE WITH SPECIALLY SHIELDED ELECTRONICS.\"\n  STR_AVALANCHE_UFOPEDIA: \"AIR TO AIR MISSILE WITH NUCLEAR WARHEAD, BUT AN EXTREMELY HEAVY LOAD.\"\n  STR_CANNON_UFOPEDIA: \"HIGH POWERED CANNON WHICH FIRES ARMOR PIERCING ROUNDS CAPABLE OF PENETRATING 16 INCHES OF STEEL.\"\n  STR_FUSION_BALL_UFOPEDIA: \"THIS LAUNCHER FIRES A BALL SHAPED MISSILE POWERED BY ANTI-MATTER REACTION. THE BALL DESTROYS THE TARGET WITH A GRAVITY WAVE IMPLOSION.\"\n  STR_LASER_CANNON_UFOPEDIA: \"THIS CONVENTIONAL LASER BEAM IS POWERED BY AN ANTI-MATTER REACTION CHAMBER.\"\n  STR_PLASMA_BEAM_UFOPEDIA: \"THE GRAVITY BEAM DIRECTS A FINELY CHANNELED IMPLODING GRAVITY FIELD.\"\n  STR_SECTOID_UFOPEDIA: \"The Sectoid hierarchy ranges from soldiers to leaders with powerful psionic abilities. These psionic powers can be used to demoralize soldiers in combat, or even take control of their minds. They tend to indulge in human abductions and cattle mutilation. The abduction is used to extract genetic material for cross breeding and developing clones for infiltrating human society. The cattle provide both nutrition and genetic material. This race appears to want to develop superior genetic hybrids to increase the efficiency of their hive-like society.\"\n  STR_SECTOID_AUTOPSY: \"Sectoid autopsy\"\n  STR_SECTOID_AUTOPSY_UFOPEDIA: \"The autopsy reveals vestigial digestive organs and a simple structure. The brain and eyes are very well developed. The structure suggests genetic alteration or mutation. The small mouth and nose appear to have little function. The webbing between the fingers, and the flat feet suggest aquatic origins. There are no reproductive organs, and no clues as to how this species can reproduce. They are most probably a genetically engineered species.\"\n  STR_SNAKEMAN_UFOPEDIA: \"This race developed in an extremely hostile environment. They are extremely tough and can resist extreme temperature variations. Their mobility depends on a snake-like giant 'foot' which protects all the vital organs. Their objectives appear to be purely predatory and they appear to be under the command of some other intelligence which directs their military-style incursions on earth.\"\n  STR_SNAKEMAN_AUTOPSY: \"Snakeman autopsy\"\n  STR_SNAKEMAN_AUTOPSY_UFOPEDIA: \"The skin is extremely tough and heat resistant. The cardio-vascular system is part of the muscular system which uses the hydraulic principle to create motion. The only true muscle is the 'heart'. The reproductive system appears to be very efficient. Reproduction is asexual, with each snakeman carrying up to fifty eggs inside its body at any one time. Left to its own devices this species would be a severe threat to life on earth.\"\n  STR_ETHEREAL_UFOPEDIA: \"This being has awesome mental powers which allow for telepathic communication and telekinetic abilities. The apparently weak physical abilities of this creature are sustained by its mental powers. We do not understand how these telekinetic powers work, since they seem to defy the laws of physics as we know them. They are extremely dangerous in any combat situation, where they rely on their mental powers for combat. They rarely appear on earth since they seem to rely on other races to pursue their objectives.\"\n  STR_ETHEREAL_AUTOPSY: \"Ethereal autopsy\"\n  STR_ETHEREAL_AUTOPSY_UFOPEDIA: \"This being is physically retarded and seems incapable of sustaining any life functions. The muscles are severely atrophied and the internal organs appear to be under-developed. The sensory organs, including the eyes, do not appear to function at all. The brain, however, is well developed and draws on a high proportion of the body's blood supply. It is a mystery as to how this creature can sustain itself without external support.\"\n  STR_MUTON_UFOPEDIA: \"This humanoid creature is physically powerful and intelligent. They have a particular appetite for consuming raw flesh of any kind, which they need for sustenance like earth based carnivores. They appear to rely on telepathic commands from a race known as 'Ethereals'. Once separated from this telepathic link their mental system appears to break down and they die. The cybernetic implants are used to enhance their combat performance. They are clearly the foot soldiers for a higher intelligence.\"\n  STR_MUTON_AUTOPSY: \"Muton autopsy\"\n  STR_MUTON_AUTOPSY_UFOPEDIA: \"The 'skin' of this creature appears to be an organically created protective armor which is grafted onto the body. There are numerous cybernetic implants which are used to enhance the cardio-vascular system and the senses. The reproductive organs appear to have been surgically removed. Evidently these unfortunate creatures are limited to a life of warfare and conquest. Armor piercing ammunition is not very effective against their toughened skin.\"\n  STR_CELATID_UFOPEDIA: \"This life-form has the mysterious natural ability to float through the air. It appears to detect human brain waves and will move towards a human target even if well hidden. Once a target is detected the Celatid lands and fires small globules of extremely corrosive venom. The creature has the ability to clone itself at an alarming rate. It accompanies the Muton race in its wanderings.\"\n  STR_CELATID_AUTOPSY: \"Celatid autopsy\"\n  STR_CELATID_AUTOPSY_UFOPEDIA: \"The core contains a small bio-mechanical device which appears to be a naturally evolved anti-gravity propulsion system. The sac of venom is the largest organ and there does not appear to be a separate brain structure. There is no discernible digestive or reproductive system. A small organ contains embryos which can grow rapidly into a new being.\"\n  STR_SILACOID_UFOPEDIA: \"This silicon based life form generates an enormous amount of heat. It has the strength to crush rocks which can then be ingested by the hot core. It has a primitive intelligence and can be controlled by implants or telepathic beings. It works with the Muton alien race.\"\n  STR_SILACOID_AUTOPSY: \"Silacoid autopsy\"\n  STR_SILACOID_AUTOPSY_UFOPEDIA: \"The core of the creature is extremely hot, and seems to be the basis for a digestive system. Its unique muscle system has tremendous power and speed. Its rock-like skin is not harmed by fire or incendiary ammunition.\"\n  STR_CHRYSSALID_UFOPEDIA: \"The crab-like claws of this creature are a powerful weapon in close combat. The high metabolism and strength of this creature give it speed and dexterity. Instead of killing its victim it impregnates it with an egg and injects a venom which turns it into a walking zombie. A new Chryssalid will burst from the victim shortly after impregnation. Chryssalids are associated with the Snakeman race.\"\n  STR_CHRYSSALID_AUTOPSY: \"Chryssalid autopsy\"\n  STR_CHRYSSALID_AUTOPSY_UFOPEDIA: \"The exoskeleton of this creature is extremely tough, but surprisingly vulnerable to explosive ammunition. The brain is well developed, and its cell growth rate very fast. The creature carries twenty eggs which are laid inside other organisms. This creature is a very effective terror weapon.\"\n  STR_FLOATER_UFOPEDIA: \"The Floaters are primarily soldiers and terror agents. They are naturally predatory beasts, genetically engineered and cybernetically enhanced to make formidable warriors. The lower half of the body and most internal organs are surgically removed, and a life support system is installed. This implant contains an anti-gravity unit which enables the creature to float, albeit unsteadily, through the air.\"\n  STR_FLOATER_AUTOPSY: \"Floater autopsy\"\n  STR_FLOATER_AUTOPSY_UFOPEDIA: \"The creature has been drastically altered by surgery. The device which seems to form the core of the body is a life support system, taking over the function of heart, lungs and digestive system. This would enable the creature to survive in extremely hostile environments. The brain is smaller than ours, but the sensory organs are well developed.\"\n  STR_REAPER_UFOPEDIA: \"This bipedal carnivore has powerful jaws and a voracious appetite. It has a number of brain implants which are used to control its activity. The primitive predatory instincts of this creature are of little use except to terrorize and destroy. Reapers are commonly associated with Floaters.\"\n  STR_REAPER_AUTOPSY: \"Reaper autopsy\"\n  STR_REAPER_AUTOPSY_UFOPEDIA: \"The Reaper contains two 'brains' and two 'hearts' which allow it to function even when heavily wounded. However, its furry skin is highly flammable, making the creature vulnerable to incendiary weapons.\"\n  STR_SECTOPOD_UFOPEDIA: \"Sectopods are robot creatures with a powerful laser beam weapon. The control of these mechanical beasts is via a telepathic link to their controllers, the Ethereals. Sectopods are the most powerful terror weapon available to the alien forces.\"\n  STR_SECTOPOD_AUTOPSY: \"Sectopod autopsy\"\n  STR_SECTOPOD_AUTOPSY_UFOPEDIA: \"The robot is sturdily constructed with powered armor capable of resisting most forms of attack, in particular plasma weapons. However, the sensing circuitry seems particularly vulnerable to laser weapons.\"\n  STR_CYBERDISC_UFOPEDIA: \"This miniature flying saucer is an automated terror weapon armed with a powerful plasma beam. The anti-gravity propulsion gives it a big advantage in difficult terrain. Its primary function is destruction and terror in the service of the Sectoid race.\"\n  STR_CYBERDISC_AUTOPSY: \"Cyberdisc autopsy\"\n  STR_CYBERDISC_AUTOPSY_UFOPEDIA: \"The Cyberdisc is well shielded and is particularly good at withstanding explosive ammunition. The primary anti-gravity system is too badly damaged to gain any understanding of its functioning.\"\n  STR_UFO_POWER_SOURCE_UFOPEDIA: \"The power source of alien craft is an anti-matter reactor which uses Elerium (element 115) to generate powerful gravity waves as well as other forms of energy. The conversion of matter to energy is an incredible 99% efficient, therefore tiny quantities of Elerium can produce a huge amount of power. This unit can be reproduced easily using alien alloys.\"\n  STR_UFO_NAVIGATION_UFOPEDIA: \"Alien craft use sophisticated computers to navigate on earth and through space. The system is based on optical processors arranged in network fashion. The control interface is relatively simple - the navigator controls the direction of gravity waves generated by the power source to move the craft in any direction. This system can be used easily by humans, and it can be reproduced using alien alloys and other components.\"\n  STR_UFO_CONSTRUCTION_UFOPEDIA: \"Alien craft consist of three main components - a power source, a navigation system and a hull built from alien alloys. The hull is specially designed to allow gravity waves to be directed and controlled. In addition a small quantity of Elerium is required to fuel the power source. Once the principles of construction are understood, and the functions of each component are known, then it is possible to build these types of craft.\"\n  STR_ALIEN_FOOD_UFOPEDIA: \"These chambers contain various enzymes which are used to digest the body parts of cattle, other animals and even humans. The liquid is then consumed as ready digested food - probably direct to the bloodstream. This suggests a certain dependence on earth for food - a symbiosis between earth and alien society.\"\n  STR_ALIEN_REPRODUCTION_UFOPEDIA: \"These chambers contain alien fetuses. The design of these containers seems to suggest that the aliens which use this process rely completely on laboratory reproduction. The rich nutrients ensure rapid development of the fetus. This factory line system could generate thousands of alien clones in a short space of time. The process could be easily adapted for human reproduction, or alien-human hybrids.\"\n  STR_ALIEN_ENTERTAINMENT_UFOPEDIA: \"The most likely function of these spheres is recreational. The psionic circuitry stimulates various centers of the brain. The effect is similar to hallucinogenic drugs. This is the only evidence that aliens have any cultural or recreational pastimes.\"\n  STR_ALIEN_SURGERY_UFOPEDIA: \"This surgical equipment uses laser cutters to extract certain body parts from cattle and other animals. The widespread cattle mutilations can be accounted for by this bizarre alien activity. It is likely that these parts are used for nutritional or genetic purposes.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"In the past many thousands of people have claimed to have been abducted by aliens, sometimes repeatedly. The truth is far more horrific. Humans are abducted, researched and monitored. The best specimens have genetic material extracted. Women have human-alien hybrid fetuses implanted, and then removed several months later. Who knows what sinister motives the aliens have?\"\n  STR_ALIEN_ALLOYS_UFOPEDIA: \"Alien craft are constructed from special alloys with unique properties. They are extremely light and durable, and can be molded by electro-magnetic methods. This material can be reproduced and used in many kinds of manufacturing processes.\"\n  STR_ELERIUM_115_UFOPEDIA: \"This element has the unusual property of generating anti-matter power when bombarded with certain particles. This creates gravity waves and other forms of energy. It is not naturally found in our solar system and cannot be reproduced.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"It is clear that we are fighting a losing battle on earth. The alien hordes are overwhelming in number. The best we can do is slow down their progress. The only hope for humanity is to tackle the aliens at their source. Our research seems to indicate a nearby base of operations within our solar system. Aliens indicate this place to be the center of an ancient civilization that pre-dates human history. We must locate this place as soon as possible. However, we need to capture and interrogate an alien leader to gain more detailed information. The larger UFOs probably contain at least one Alien leader.\"\n  STR_THE_MARTIAN_SOLUTION_UFOPEDIA: \"Our research now points to Mars as the base of alien operations. The base is well hidden, and contains all the manufacturing and cloning facilities to fuel the infiltration of earth. It also seems to contain a controlling computer of some kind that controls the whole operation. It seems that the hive-like alien society has some kind of 'queen bee'. This is their fundamental weakness - if we can eliminate the 'brain' then the body will die. We must step up our research efforts before it is too late. In order to progress we must capture the highest ranking aliens - the commanders - which only reside in alien bases and battleships.\"\n  STR_CYDONIA_OR_BUST_UFOPEDIA: \"It is now clear that the alien hordes are being controlled from an underground base in Cydonia - which is an unusual area of Mars featuring five sided pyramids and a large formation resembling a human face. Cydonian civilization once flourished on Mars many millions of years ago, but we do not know why it died out, or what the connection is with the latest alien activity there. Whatever the explanation we must send an expedition to Cydonia. This is the only way that we can defeat the aliens. We must destroy the controlling master 'brain'. We will need an Avenger craft equipped with the most awesome destructive power at our disposal. There is nothing more we can learn here - we must await the outcome of the Cydonian assault.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"CENTER ON SITE-TIME=5 Secs\"\n  STR_CANCEL_UC: \"CANCEL\"\n  STR_NONE: \"None\"\n  STR_UNKNOWN: \"Unknown\"\n  STR_POOR: \"Poor\"\n  STR_AVERAGE: \"Average\"\n  STR_GOOD: \"Good\"\n  STR_EXCELLENT: \"Excellent\"\n  STR_BUILD_NEW_BASE_UC: \"BUILD NEW BASE\"\n  STR_BASE_INFORMATION: \"BASE INFORMATION\"\n  STR_EQUIP_CRAFT: \"EQUIP CRAFT\"\n  STR_BUILD_FACILITIES: \"BUILD FACILITIES\"\n  STR_RESEARCH: \"RESEARCH\"\n  STR_MANUFACTURE: \"MANUFACTURE\"\n  STR_TRANSFER_UC: \"TRANSFER\"\n  STR_PURCHASE_RECRUIT: \"PURCHASE/RECRUIT\"\n  STR_SACK: \"SACK\"\n  STR_SELL_SACK_UC: \"SELL/SACK\"\n  STR_GEOSCAPE_UC: \"GEOSCAPE\"\n  STR_NAME: \"Name\"\n  STR_AREA: \"Area\"\n  STR_BUILD_NEW_BASE: \"Build New Base\"\n  STR_CANCEL: \"Cancel\"\n  STR_COST_UC: \"COST>\"\n  STR_CONSTRUCTION_TIME_UC: \"CONSTRUCTION TIME>\"\n  STR_DAY:\n    one: \"{N} day\"\n    other: \"{N} days\"\n  STR_HOUR:\n    one: \"{N} hour\"\n    other: \"{N} hours\"\n  STR_MAINTENANCE_UC: \"MAINTENANCE>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Installation\"\n  STR_CURRENT_RESEARCH: \"CURRENT RESEARCH\"\n  STR_SCIENTISTS_AVAILABLE: \"Scientists Available>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Scientists Allocated>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Laboratory Space Available>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"RESEARCH PROJECT\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"SCIENTISTS ALLOCATED\"\n  STR_PROGRESS: \"PROGRESS\"\n  STR_NEW_PROJECT: \"New Project\"\n  STR_CANCEL_PROJECT: \"CANCEL PROJECT\"\n  STR_NEW_RESEARCH_PROJECTS: \"NEW RESEARCH PROJECTS\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"SCIENTISTS AVAILABLE>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"LABORATORY SPACE AVAILABLE>{ALT}{0}\"\n  STR_INCREASE: \"Increase\"\n  STR_DECREASE: \"Decrease\"\n  STR_START_PROJECT: \"START PROJECT\"\n  STR_CURRENT_PRODUCTION: \"CURRENT PRODUCTION\"\n  STR_ENGINEERS_AVAILABLE: \"Engineers Available>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Engineers Allocated>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Workshop Space Available>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Current Funds>{ALT}{0}\"\n  STR_ITEM: \"ITEM\"\n  STR_ENGINEERS__ALLOCATED: \"Engineers Allocated\"\n  STR_UNITS_PRODUCED: \"Units Produced\"\n  STR_TOTAL_TO_PRODUCE: \"Total to Produce\"\n  STR_COST__PER__UNIT: \"Cost{NEWLINE}per{NEWLINE}Unit\"\n  STR_DAYS_HOURS_LEFT: \"Days/Hours Left\"\n  STR_NEW_PRODUCTION: \"New Production\"\n  STR_PRODUCTION_ITEMS: \"Production Items\"\n  STR_CATEGORY: \"CATEGORY\"\n  STR_START_PRODUCTION: \"START PRODUCTION\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} Engineer hours to produce one unit\"\n  STR_COST_PER_UNIT_: \"Cost per unit>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Work Space Required>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"SPECIAL MATERIALS REQUIRED\"\n  STR_ITEM_REQUIRED: \"ITEM REQUIRED\"\n  STR_UNITS_REQUIRED: \"UNITS REQUIRED\"\n  STR_UNITS_AVAILABLE: \"UNITS AVAILABLE\"\n  STR_STOP_PRODUCTION: \"STOP PRODUCTION\"\n  STR_ENGINEERS_AVAILABLE_UC: \"ENGINEERS AVAILABLE>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"WORKSHOP SPACE AVAILABLE>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"MONTHLY PROFIT>{ALT}{0}\"\n  STR_INCREASE_UC: \"INCREASE\"\n  STR_DECREASE_UC: \"DECREASE\"\n  STR_UNITS_TO_PRODUCE: \"Units to Produce\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Purchase/Hire Personnel\"\n  STR_COST_OF_PURCHASES: \"Cost of Purchases>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"COST PER UNIT\"\n  STR_QUANTITY_UC: \"QUANTITY\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"PERSONNEL AVAILABLE:PERSONNEL TOTAL>\"\n  STR_SOLDIERS: \"Soldiers\"\n  STR_SCIENTISTS: \"Scientists\"\n  STR_ENGINEERS: \"Engineers\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"SPACE USED:SPACE AVAILABLE>\"\n  STR_LIVING_QUARTERS: \"Living Quarters\"\n  STR_STORES: \"Stores\"\n  STR_LABORATORIES: \"Laboratories\"\n  STR_WORK_SHOPS: \"Work Shops\"\n  STR_HANGARS: \"Hangars\"\n  STR_SHORT_RANGE_DETECTION: \"Short Range Detection\"\n  STR_DEFENSE_STRENGTH: \"Defense Strength\"\n  STR_TRANSFERS_UC: \"TRANSFERS\"\n  STR_TRANSFERS: \"Transfers\"\n  STR_ARRIVAL_TIME_HOURS: \"Arrival Time (hours)\"\n  STR_COST_: \"Cost>{ALT}{0}\"\n  STR_AREA_: \"Area>{ALT}{0}\"\n  STR_BASE_NAME: \"Base Name?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"SELECT POSITION FOR ACCESS LIFT\"\n  STR_TRANSFER: \"Transfer\"\n  STR_AMOUNT_TO_TRANSFER: \"AMOUNT TO TRANSFER\"\n  STR_SELECT_DESTINATION_BASE: \"Select Destination Base\"\n  STR_COST: \"Cost\"\n  STR_VICTORY_1: \"As you enter the chamber you see the alien brain - the object of your quest. Before you can fire it communicates to you via a screen at its base. It implores you to listen to its arguments for survival before you make the decision to pull the trigger...\"\n  STR_VICTORY_2: \"The brain speaks: 'Many millions of years ago the planet you call Mars was alive. This life was brought to a barren planet by our civilization as it was to yours. For millions of years we have visited your planet and genetically developed your species. You cannot kill us, you are part of us...\"\n  STR_VICTORY_3: \"Here is the center of Martian civilization - the pyramids built millions of years before yours - by a species which is your ancestor. No planet is beyond our reach. This power could be yours before long. All we ask is your co-operation...\"\n  STR_GAME_OVER_1: \"The aliens attempt to exterminate all humanity, destroying cities and poisoning the air and sea. The resistance of earth armies is futile in the face of vastly superior technology. Surviving generations suffer terrible mutations as they flee alien destruction. They are rounded up into slave camps to help transform earth into an alien colony which is part of some unknown empire.\"\n  STR_GAME_OVER_2: \"The knowledge gained through the X-Com project is lost forever. You have failed to save the earth.\"\n  STR_VICTORY_4: \"The alien brain is interrupted by a burst of hot plasma, and the entire alien force is defeated.\"\n  STR_VICTORY_5: \"Once the aliens have lost Mars they have lost the earth. Before long the X-Com research allows humanity to flourish once more, and claim Mars for itself. The alien menace has gone, but for how long, no one knows...\"\n  STR_YOU_HAVE_FAILED: \"You have failed to stop the alien onslaught. One by one the funding nations sign pacts with aliens promising technology, prosperity and peace. However it soon becomes clear that the aliens have other plans...\"\n  STR_TOTAL_UC: \"TOTAL\"\n  STR_INCOME: \"Income\"\n  STR_EXPENDITURE: \"Expenditure\"\n  STR_MAINTENANCE: \"Maintenance\"\n  STR_BALANCE: \"Balance\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"UFO Activity in Areas\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"UFO Activity in Countries\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"X-Com Activity in Areas\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"X-Com Activity in Countries\"\n  STR_FINANCE: \"Finance\"\n  STR_DATE_FIRST: \"{0}st\"\n  STR_DATE_SECOND: \"{0}nd\"\n  STR_DATE_THIRD: \"{0}rd\"\n  STR_DATE_FOURTH: \"{0}th\"\n  STR_FINANCE_THOUSANDS: \"$1000's\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Not enough special materials to produce{NEWLINE}{0}{NEWLINE}at{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Not enough money to produce{NEWLINE}{0}{NEWLINE}at{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"Production of{NEWLINE}{0}{NEWLINE}at{NEWLINE}{1}{NEWLINE}is complete\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"Construction of{NEWLINE}{0}{NEWLINE}at{NEWLINE}{1}{NEWLINE}is complete\"\n  STR_OK_5_SECONDS: \"OK - 5 secs\"\n  STR_RESEARCH_COMPLETED: \"Research Completed\"\n  STR_VIEW_REPORTS: \"VIEW REPORTS\"\n  STR_WE_CAN_NOW_RESEARCH: \"We can now research\"\n  STR_WE_CAN_NOW_PRODUCE: \"We can now produce\"\n  STR_SUNDAY: \"SUNDAY\"\n  STR_MONDAY: \"MONDAY\"\n  STR_TUESDAY: \"TUESDAY\"\n  STR_WEDNESDAY: \"WEDNESDAY\"\n  STR_THURSDAY: \"THURSDAY\"\n  STR_FRIDAY: \"FRIDAY\"\n  STR_SATURDAY: \"SATURDAY\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Not enough {0} to refuel {1} at {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Not enough {0} to rearm {1} at {2}\"\n  STR_UFO_IS_NOT_RECOVERED: \"UFO is not recovered\"\n  STR_UFO_IS_RECOVERED: \"UFO is recovered\"\n  STR_CRAFT_IS_LOST: \"Craft is lost\"\n  STR_TERROR_CONTINUES: \"Terror continues\"\n  STR_ALIENS_DEFEATED: \"Aliens defeated\"\n  STR_BASE_IS_LOST: \"Base is lost\"\n  STR_BASE_IS_SAVED: \"Base is saved\"\n  STR_ALIEN_BASE_STILL_INTACT: \"Alien Base still intact\"\n  STR_ALIEN_BASE_DESTROYED: \"Alien Base destroyed\"\n  STR_ALIENS_KILLED: \"ALIENS KILLED\"\n  STR_ALIEN_CORPSES_RECOVERED: \"ALIEN CORPSES RECOVERED\"\n  STR_LIVE_ALIENS_RECOVERED: \"LIVE ALIENS RECOVERED\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"ALIEN ARTIFACTS RECOVERED\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"ALIEN BASE CONTROL DESTROYED\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"CIVILIANS KILLED BY ALIENS\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"CIVILIANS KILLED BY X-COM OPERATIVES\"\n  STR_CIVILIANS_SAVED: \"CIVILIANS SAVED\"\n  STR_XCOM_OPERATIVES_KILLED: \"X-COM OPERATIVES KILLED\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"X-COM OPERATIVES MISSING IN ACTION\"\n  STR_TANKS_DESTROYED: \"TANKS DESTROYED\"\n  STR_XCOM_CRAFT_LOST: \"X-COM CRAFT LOST\"\n  STR_UFO_RECOVERY: \"UFO RECOVERY\"\n  STR_ALIEN_BASE_RECOVERY: \"ALIEN BASE RECOVERY\"\n  STR_BASE_UNDER_ATTACK: \"{0} under attack!\"\n  STR_BASE_DEFENSES_INITIATED: \"BASE DEFENSES INITIATED\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"GRAV SHIELD REPELS UFO!\"\n  STR_FIRING: \"FIRING\"\n  STR_HIT: \"HIT!\"\n  STR_UFO_DESTROYED: \"UFO DESTROYED!\"\n  STR_MISSED: \"MISSED!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Sell Items/Sack Personnel\"\n  STR_VALUE_OF_SALES: \"VALUE OF SALES> {ALT}{0}\"\n  STR_FUNDS: \"FUNDS> {ALT}{0}\"\n  STR_SELL_SACK: \"Sell/Sack\"\n  STR_VALUE: \"Value\"\n  STR_CRAFT_: \"CRAFT> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"UFO CRASH RECOVERY\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"Exercise caution - There may be operatives in the UFO or around the crash site. Mission will be successful when all enemy units have been eliminated or neutralized. Recovery of UFO remains, artifacts and alien corpses can then be initiated. To abort the mission return X-Com operatives to transport vehicle and click on the 'Abort Mission' icon.\"\n  STR_UFO_GROUND_ASSAULT: \"UFO GROUND ASSAULT\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"Explore landing site and, if possible, gain entry to the UFO. Mission will be successful when all enemy units have been eliminated or neutralized. Recovery of UFO, artifacts and alien corpses can then be initiated. To abort the mission return X-Com operatives to transport vehicle and click on the 'Abort Mission' icon.\"\n  STR_BASE_DEFENSE: \"BASE DEFENSE\"\n  STR_BASE_UC_: \"BASE> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"An Alien vessel has landed nearby. Our base is in severe danger. As per standard procedure all non-combat personnel and X-Com craft have been evacuated. Alien units will enter the base via hangar doors or the access lift. Defend the base and its vital installations at all costs - this is a fight to the death. If you click on the 'abort mission' icon you will concede defeat and lose the base.\"\n  STR_ALIEN_BASE_ASSAULT: \"ALIEN BASE ASSAULT\"\n  STR_ALIEN_BASE_ASSAULT_BRIEFING: \"X-Com operatives have gained entrance to an alien base. The control center must be destroyed to render the base inoperative. The mission will terminate when all enemies are eliminated, or when your squad has returned to the green exit area (click on the 'abort mission' icon to escape).\"\n  STR_CYDONIA_BRIEFING: \"You have arrived in Cydonia. You gain entry to a large underground complex near the Martian Sphinx. You must destroy the Alien Brain that controls all alien activity. The fate of humanity is in your hands....\"\n  STR_TERROR_MISSION: \"TERROR MISSION\"\n  STR_TERROR_MISSION_BRIEFING: \"Mission will be successful when all enemy units have been eliminated or neutralized. You must attempt to save the lives of any civilians in the area by neutralizing the alien menace. To abort the mission return X-Com operatives to transport vehicle and click on the 'Abort Mission' icon.\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"NO FREE HANGARS FOR CRAFT PRODUCTION!{SMALLLINE}Each craft assigned to a base, transferred to a base, purchased or constructed uses one hangar. Build a new hangar or transfer a craft to another base.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"NO FREE HANGARS FOR PURCHASE!{SMALLLINE}Each craft assigned to a base, transferred to a base, purchased or constructed uses one hangar. Build a new hangar or transfer a craft to another base.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"NO FREE HANGARS FOR TRANSFER!{SMALLLINE}Each craft assigned to a base, transferred to a base, purchased or constructed uses one hangar. Build a new hangar or transfer a craft to another base.\"\n  STR_CANNOT_BUILD_HERE: \"CANNOT BUILD HERE!{SMALLLINE}You must build next to an existing base facility.\"\n  STR_NO_FREE_ACCOMODATION: \"NO FREE ACCOMMODATION!{SMALLLINE}The destination base does not have enough space in living quarters.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"NOT ENOUGH WORK SPACE AVAILABLE!{SMALLLINE}Build a new workshop or reduce work on other projects.\"\n  STR_NOT_ENOUGH_MONEY: \"NOT ENOUGH MONEY!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"NOT ENOUGH STORE SPACE!{SMALLLINE}Build a new store facility or transfer existing stores to other bases.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"NOT ENOUGH LIVING SPACE!{SMALLLINE}Build new living quarters or transfer personnel to other bases.\"\n  STR_LAUNCH_INTERCEPTION: \"LAUNCH INTERCEPTION\"\n  STR_CRAFT: \"CRAFT\"\n  STR_STATUS: \"STATUS\"\n  STR_BASE: \"BASE\"\n  STR_READY: \"READY\"\n  STR_OUT: \"OUT\"\n  STR_REPAIRS: \"REPAIRS\"\n  STR_REFUELLING: \"REFUELING\"\n  STR_REARMING: \"REARMING\"\n  STR_TARGET: \"TARGET: {0}\"\n  STR_WAY_POINT: \"WAY POINT\"\n  STR_ARE_YOU_SURE_CYDONIA: \"Are you sure you want to send this craft on a mission to Cydonia?\"\n  STR_YES: \"YES\"\n  STR_NO: \"NO\"\n  STR_SELECT_DESTINATION: \"SELECT DESTINATION\"\n  STR_CYDONIA: \"CYDONIA\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"SELECT SITE FOR NEW BASE\"\n  STR_RETURN_TO_BASE: \"RETURN TO BASE\"\n  STR_SELECT_NEW_TARGET: \"SELECT NEW TARGET\"\n  STR_PATROL: \"PATROL\"\n  STR_STATUS_: \"STATUS>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"DAMAGED - RETURNING TO BASE\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"LOW FUEL - RETURNING TO BASE\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"MISSION COMPLETE - RETURNING TO BASE\"\n  STR_PATROLLING: \"PATROLLING\"\n  STR_TAILING_UFO: \"TAILING UFO\"\n  STR_INTERCEPTING_UFO: \"INTERCEPTING UFO-{0}\"\n  STR_RETURNING_TO_BASE: \"RETURNING TO BASE\"\n  STR_DESTINATION_UC_: \"DESTINATION: {0}\"\n  STR_BASE_UC: \"BASE>{ALT}{0}\"\n  STR_SPEED_: \"SPEED>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"MAXIMUM SPEED>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"ALTITUDE>{ALT}{0}\"\n  STR_VERY_LOW: \"VERY LOW\"\n  STR_LOW_UC: \"LOW\"\n  STR_HIGH_UC: \"HIGH\"\n  STR_VERY_HIGH: \"VERY HIGH\"\n  STR_FUEL: \"FUEL>{ALT}{0}\"\n  STR_WEAPON_ONE: \"WEAPON-1>{ALT}{0}\"\n  STR_NONE_UC: \"NONE\"\n  STR_ROUNDS_: \"ROUNDS>{ALT}{0}\"\n  STR_WEAPON_TWO: \"WEAPON-2>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"INTERCEPTION CRAFT\"\n  STR_BASE_: \"Base>{0}\"\n  STR_NAME_UC: \"NAME\"\n  STR_AMMO_: \"AMMO>{ALT}{0}\"\n  STR_CREW: \"CREW\"\n  STR_EQUIPMENT_UC: \"EQUIPMENT\"\n  STR_ARMOR: \"ARMOR\"\n  STR_MAX: \"MAX>{ALT}{0}\"\n  STR_ROOKIE: \"Rookie\"\n  STR_SQUADDIE: \"Squaddie\"\n  STR_SERGEANT: \"Sergeant\"\n  STR_CAPTAIN: \"Captain\"\n  STR_COLONEL: \"Colonel\"\n  STR_COMMANDER: \"Commander\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Select Squad for {0}\"\n  STR_SORT_BY: \"SORT BY...\"\n  STR_ORIGINAL_ORDER: \"ORIGINAL ORDER\"\n  STR_MISSIONS2: \"MISSIONS\"\n  STR_KILLS2: \"KILLS\"\n  STR_WOUND_RECOVERY2: \"WOUND RECOVERY\"\n  STR_SPACE_AVAILABLE: \"SPACE AVAILABLE>{ALT}{0}\"\n  STR_SPACE_USED: \"SPACE USED>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"SPACE USED\"\n  STR_RANK: \"RANK\"\n  STR_WOUNDED: \"WOUNDED\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Equipment for {0}\"\n  STR_DEFENSE_VALUE: \"Defense Value\"\n  STR_HIT_RATIO: \"Hit Ratio\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}ready to{NEWLINE}land near{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"Begin Mission?\"\n  STR_SELECT_ARMAMENT: \"Select Armament\"\n  STR_AMMUNITION_AVAILABLE: \"AMMUNITION AVAILABLE\"\n  STR_ARMAMENT: \"ARMAMENT\"\n  STR_NOT_AVAILABLE: \"N.A.\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"SELECT ARMOR FOR{NEWLINE}{0}\"\n  STR_TYPE: \"TYPE\"\n  STR_PERSONAL_ARMOR_UC: \"PERSONAL ARMOR\"\n  STR_POWER_SUIT_UC: \"POWER SUIT\"\n  STR_FLYING_SUIT_UC: \"FLYING SUIT\"\n  STR_SELECT_ARMOR: \"Select Armor\"\n  STR_NORTH: \"NORTH\"\n  STR_NORTH_EAST: \"NORTH EAST\"\n  STR_EAST: \"EAST\"\n  STR_SOUTH_EAST: \"SOUTH EAST\"\n  STR_SOUTH: \"SOUTH\"\n  STR_SOUTH_WEST: \"SOUTH WEST\"\n  STR_WEST: \"WEST\"\n  STR_NORTH_WEST: \"NORTH WEST\"\n  STR_SELECT_ACTION: \"SELECT ACTION\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"CONTINUE INTERCEPTION PURSUIT\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"PURSUE WITHOUT INTERCEPTION\"\n  STR_VERY_LARGE: \"VERY LARGE\"\n  STR_LARGE: \"LARGE\"\n  STR_MEDIUM_UC: \"MEDIUM\"\n  STR_SMALL: \"SMALL\"\n  STR_VERY_SMALL: \"VERY SMALL\"\n  STR_GROUNDED: \"GROUND\"\n  STR_DETECTED: \"Detected\"\n  STR_SIZE_UC: \"SIZE\"\n  STR_ALTITUDE: \"ALTITUDE\"\n  STR_HEADING: \"HEADING\"\n  STR_SPEED: \"SPEED\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"CENTER ON UFO-TIME=5 Secs\"\n  STR_TRACKING_LOST: \"TRACKING LOST\"\n  STR_REDIRECT_CRAFT: \"REDIRECT CRAFT\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"GO TO LAST KNOWN UFO POSITION\"\n  STR_UFO_: \"UFO-{0}\"\n  STR_ALIEN_BASE_: \"ALIEN BASE-{0}\"\n  STR_CRASH_SITE_: \"CRASH SITE-{0}\"\n  STR_LANDING_SITE_: \"LANDING SITE-{0}\"\n  STR_WAY_POINT_: \"WAY POINT-{0}\"\n  STR_TERROR_SITE: \"TERROR SITE-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}has reached{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"Now patrolling\"\n  STR_ALIEN_ORIGINS: \"Alien Origins\"\n  STR_THE_MARTIAN_SOLUTION: \"The Martian Solution\"\n  STR_CYDONIA_OR_BUST: \"Cydonia or Bust\"\n  STR_UFOPAEDIA: \"UFOpedia\"\n  STR_XCOM_CRAFT_ARMAMENT: \"X-COM CRAFT & ARMAMENT\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"HEAVY WEAPONS PLATFORMS\"\n  STR_WEAPONS_AND_EQUIPMENT: \"WEAPONS AND EQUIPMENT\"\n  STR_ALIEN_ARTIFACTS: \"ALIEN ARTIFACTS\"\n  STR_BASE_FACILITIES: \"BASE FACILITIES\"\n  STR_ALIEN_LIFE_FORMS: \"ALIEN LIFE FORMS\"\n  STR_ALIEN_RESEARCH_UC: \"ALIEN RESEARCH\"\n  STR_UFO_COMPONENTS: \"UFO COMPONENTS\"\n  STR_UFOS: \"UFOs\"\n  STR_SELECT_ITEM: \"SELECT ITEM\"\n  STR_ACCELERATION: \"ACCELERATION>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"FUEL CAPACITY>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"WEAPON PODS>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"DAMAGE CAPACITY>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"CARGO SPACE>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"HWP CAPACITY>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Damage\"\n  STR_RANGE: \"Range\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Accuracy\"\n  STR_RE_LOAD_TIME: \"Re-load time\"\n  STR_SECONDS: \"{0}s\"\n  STR_DAMAGE_ARMOR_PIERCING: \"ARMOR PIERCING\"\n  STR_DAMAGE_INCENDIARY: \"INCENDIARY\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"HIGH EXPLOSIVE\"\n  STR_DAMAGE_LASER_BEAM: \"LASER BEAM\"\n  STR_DAMAGE_PLASMA_BEAM: \"PLASMA BEAM\"\n  STR_DAMAGE_STUN: \"STUN\"\n  STR_DAMAGE_MELEE: \"MELEE\"\n  STR_DAMAGE_ACID: \"ACID\"\n  STR_DAMAGE_SMOKE: \"SMOKE\"\n  STR_SHOT_TYPE: \"SHOT TYPE\"\n  STR_ACCURACY_UC: \"ACCURACY\"\n  STR_TIME_UNIT_COST: \"TU COST\"\n  STR_DAMAGE_UC: \"DAMAGE\"\n  STR_AMMO: \"AMMO\"\n  STR_SHOT_TYPE_AUTO: \"Auto\"\n  STR_SHOT_TYPE_SNAP: \"Snap\"\n  STR_SHOT_TYPE_AIMED: \"Aimed\"\n  STR_CONSTRUCTION_TIME: \"Construction Time\"\n  STR_CONSTRUCTION_COST: \"Construction Cost\"\n  STR_MAINTENANCE_COST: \"Maintenance Cost\"\n  STR_LOW: \"Low\"\n  STR_MEDIUM: \"Medium\"\n  STR_HIGH: \"High\"\n  STR_CRAFT_WEAPON: \"Craft Weapon\"\n  STR_CRAFT_AMMUNITION: \"Craft Ammunition\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Heavy Weapons Platform\"\n  STR_WEAPON: \"Weapon\"\n  STR_AMMUNITION: \"Ammunition\"\n  STR_EQUIPMENT: \"Equipment\"\n  STR_ALIEN_CORPSE: \"Alien Corpse\"\n  STR_UFO_COMPONENT: \"UFO component\"\n  STR_PERSONAL_ARMOR: \"Personal Armor\"\n  STR_RAW_MATERIALS: \"Raw Materials\"\n  STR_HWP_CANNON_SHELLS: \"HWP Cannon Shells\"\n  STR_ALIEN: \"Alien\"\n  STR_SECTOID: \"Sectoid\"\n  STR_SNAKEMAN: \"Snakeman\"\n  STR_ETHEREAL: \"Ethereal\"\n  STR_MUTON: \"Muton\"\n  STR_FLOATER: \"Floater\"\n  STR_CELATID: \"Celatid\"\n  STR_SILACOID: \"Silacoid\"\n  STR_CHRYSSALID: \"Chryssalid\"\n  STR_ZOMBIE: \"Zombie\"\n  STR_REAPER: \"Reaper\"\n  STR_SECTOPOD: \"Sectopod\"\n  STR_CYBERDISC: \"Cyberdisc\"\n  STR_LIVE_COMMANDER: \"Commander\"\n  STR_LIVE_LEADER: \"Leader\"\n  STR_LIVE_ENGINEER: \"Engineer\"\n  STR_LIVE_MEDIC: \"Medic\"\n  STR_LIVE_NAVIGATOR: \"Navigator\"\n  STR_LIVE_SOLDIER: \"Soldier\"\n  STR_LIVE_TERRORIST: \"Terrorist\"\n  STR_FLOATER_SOLDIER: \"Floater Soldier\"\n  STR_FLOATER_NAVIGATOR: \"Floater Navigator\"\n  STR_FLOATER_MEDIC: \"Floater Medic\"\n  STR_FLOATER_ENGINEER: \"Floater Engineer\"\n  STR_FLOATER_LEADER: \"Floater Leader\"\n  STR_FLOATER_COMMANDER: \"Floater Commander\"\n  STR_SECTOID_SOLDIER: \"Sectoid Soldier\"\n  STR_SECTOID_NAVIGATOR: \"Sectoid Navigator\"\n  STR_SECTOID_MEDIC: \"Sectoid Medic\"\n  STR_SECTOID_ENGINEER: \"Sectoid Engineer\"\n  STR_SECTOID_LEADER: \"Sectoid Leader\"\n  STR_SECTOID_COMMANDER: \"Sectoid Commander\"\n  STR_SNAKEMAN_SOLDIER: \"Snakeman Soldier\"\n  STR_SNAKEMAN_NAVIGATOR: \"Snakeman Navigator\"\n  STR_SNAKEMAN_ENGINEER: \"Snakeman Engineer\"\n  STR_SNAKEMAN_LEADER: \"Snakeman Leader\"\n  STR_SNAKEMAN_COMMANDER: \"Snakeman Commander\"\n  STR_MUTON_SOLDIER: \"Muton Soldier\"\n  STR_MUTON_NAVIGATOR: \"Muton Navigator\"\n  STR_MUTON_ENGINEER: \"Muton Engineer\"\n  STR_ETHEREAL_SOLDIER: \"Ethereal Soldier\"\n  STR_ETHEREAL_LEADER: \"Ethereal Leader\"\n  STR_ETHEREAL_COMMANDER: \"Ethereal Commander\"\n  STR_CYBERDISC_TERRORIST: \"Cyberdisc Terrorist\"\n  STR_REAPER_TERRORIST: \"Reaper Terrorist\"\n  STR_CHRYSSALID_TERRORIST: \"Chryssalid Terrorist\"\n  STR_CELATID_TERRORIST: \"Celatid Terrorist\"\n  STR_SILACOID_TERRORIST: \"Silacoid Terrorist\"\n  STR_SECTOPOD_TERRORIST: \"Sectopod Terrorist\"\n  STR_UFO_POWER_SOURCE: \"UFO Power Source\"\n  STR_UFO_NAVIGATION: \"UFO Navigation\"\n  STR_UFO_CONSTRUCTION: \"UFO Construction\"\n  STR_ALIEN_FOOD: \"Alien Food\"\n  STR_ALIEN_REPRODUCTION: \"Alien Reproduction\"\n  STR_ALIEN_ENTERTAINMENT: \"Alien Entertainment\"\n  STR_ALIEN_SURGERY: \"Alien Surgery\"\n  STR_EXAMINATION_ROOM: \"Examination Room\"\n  STR_ALIEN_ALLOYS: \"Alien Alloys\"\n  STR_ALIEN_HABITAT: \"Alien Habitat\"\n  STR_POWER_SUIT: \"Power Suit\"\n  STR_FLYING_SUIT: \"Flying Suit\"\n  STR_HWP_ROCKETS: \"HWP Rockets\"\n  STR_HWP_FUSION_BOMB: \"HWP Fusion Bomb\"\n  STR_LASER_WEAPONS: \"Laser Weapons\"\n  STR_NEW_FIGHTER_CRAFT: \"New Fighter Craft\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"New Fighter-Transporter\"\n  STR_ULTIMATE_CRAFT: \"Ultimate Craft\"\n  STR_LASER_PISTOL: \"Laser Pistol\"\n  STR_LASER_RIFLE: \"Laser Rifle\"\n  STR_HEAVY_LASER: \"Heavy Laser\"\n  STR_LASER_CANNON: \"Laser Cannon\"\n  STR_PLASMA_CANNON: \"Plasma Cannon\"\n  STR_FUSION_MISSILE: \"Fusion Missile\"\n  STR_LASER_DEFENSE: \"Laser Defense\"\n  STR_PLASMA_DEFENSE: \"Plasma Defense\"\n  STR_FUSION_DEFENSE: \"Fusion Defense\"\n  STR_GRAV_SHIELD: \"Grav Shield\"\n  STR_MIND_SHIELD: \"Mind Shield\"\n  STR_PSI_LAB: \"Psi-Lab\"\n  STR_MOTION_SCANNER: \"Motion Scanner\"\n  STR_MEDI_KIT: \"Medi-Kit\"\n  STR_TANK_CANNON: \"Tank/Cannon\"\n  STR_TANK_ROCKET_LAUNCHER: \"Tank/Rocket Launcher\"\n  STR_TANK_LASER_CANNON: \"Tank/Laser Cannon\"\n  STR_HOVERTANK_PLASMA: \"Hovertank/Plasma\"\n  STR_HOVERTANK_LAUNCHER: \"Hovertank/Launcher\"\n  STR_STINGRAY_LAUNCHER: \"Stingray Launcher\"\n  STR_AVALANCHE_LAUNCHER: \"Avalanche Launcher\"\n  STR_CANNON: \"Cannon\"\n  STR_FUSION_BALL_LAUNCHER: \"Fusion Ball Launcher\"\n  STR_PLASMA_BEAM: \"Plasma Beam\"\n  STR_STINGRAY_MISSILES: \"Stingray Missiles\"\n  STR_AVALANCHE_MISSILES: \"Avalanche Missiles\"\n  STR_CANNON_ROUNDS_X50: \"Cannon Rounds(x50)\"\n  STR_FUSION_BALL: \"Fusion Ball\"\n  STR_SOLDIER: \"Soldier\"\n  STR_SCIENTIST: \"Scientist\"\n  STR_ENGINEER: \"Engineer\"\n  STR_NORTH_AMERICA: \"North America\"\n  STR_ARCTIC: \"Arctic\"\n  STR_ANTARCTICA: \"Antarctica\"\n  STR_SOUTH_AMERICA: \"South America\"\n  STR_EUROPE: \"Europe\"\n  STR_NORTH_AFRICA: \"North Africa\"\n  STR_SOUTHERN_AFRICA: \"Southern Africa\"\n  STR_CENTRAL_ASIA: \"Central Asia\"\n  STR_SOUTH_EAST_ASIA: \"South East Asia\"\n  STR_SIBERIA: \"Siberia\"\n  STR_AUSTRALASIA: \"Australasia\"\n  STR_PACIFIC: \"Pacific\"\n  STR_NORTH_ATLANTIC: \"North Atlantic\"\n  STR_SOUTH_ATLANTIC: \"South Atlantic\"\n  STR_INDIAN_OCEAN: \"Indian Ocean\"\n  STR_ALIEN_RESEARCH: \"Alien Research\"\n  STR_ALIEN_HARVEST: \"Alien Harvest\"\n  STR_ALIEN_ABDUCTION: \"Alien Abduction\"\n  STR_ALIEN_INFILTRATION: \"Alien Infiltration\"\n  STR_ALIEN_BASE: \"Alien Base\"\n  STR_ALIEN_TERROR: \"Alien Terror\"\n  STR_ALIEN_RETALIATION: \"Alien Retaliation\"\n  STR_ALIEN_SUPPLY: \"Alien Supply\"\n  STR_MAXIMUM_SPEED: \"Maximum Speed\"\n  STR_HYPER_WAVE_DECODER_UC: \"HYPER-WAVE DECODER\"\n  STR_SKYRANGER: \"SKYRANGER\"\n  STR_LIGHTNING: \"LIGHTNING\"\n  STR_AVENGER: \"AVENGER\"\n  STR_INTERCEPTOR: \"INTERCEPTOR\"\n  STR_FIRESTORM: \"FIRESTORM\"\n  STR_UFO: \"UFO\"\n  STR_STINGRAY: \"STINGRAY\"\n  STR_AVALANCHE: \"AVALANCHE\"\n  STR_CANNON_UC: \"CANNON\"\n  STR_FUSION_BALL_UC: \"FUSION BALL\"\n  STR_LASER_CANNON_UC: \"LASER CANNON\"\n  STR_PLASMA_BEAM_UC: \"PLASMA BEAM\"\n  STR_DAMAGE_CAPACITY: \"Damage Capacity\"\n  STR_WEAPON_POWER: \"Weapon Power\"\n  STR_WEAPON_RANGE: \"Weapon Range\"\n  STR_ACCESS_LIFT: \"Access Lift\"\n  STR_LABORATORY: \"Laboratory\"\n  STR_WORKSHOP: \"Workshop\"\n  STR_SMALL_RADAR_SYSTEM: \"Small Radar System\"\n  STR_LARGE_RADAR_SYSTEM: \"Large Radar System\"\n  STR_MISSILE_DEFENSES: \"Missile Defenses\"\n  STR_GENERAL_STORES: \"General Stores\"\n  STR_ALIEN_CONTAINMENT: \"Alien Containment\"\n  STR_LASER_DEFENSES: \"Laser Defenses\"\n  STR_PLASMA_DEFENSES: \"Plasma Defenses\"\n  STR_FUSION_BALL_DEFENSES: \"Fusion Ball Defenses\"\n  STR_PSIONIC_LABORATORY: \"Psionic Laboratory\"\n  STR_HYPER_WAVE_DECODER: \"Hyper-wave Decoder\"\n  STR_HANGAR: \"Hangar\"\n  STR_USA: \"USA\"\n  STR_RUSSIA: \"RUSSIA\"\n  STR_UK: \"UK\"\n  STR_FRANCE: \"FRANCE\"\n  STR_GERMANY: \"GERMANY\"\n  STR_ITALY: \"ITALY\"\n  STR_SPAIN: \"SPAIN\"\n  STR_CHINA: \"CHINA\"\n  STR_JAPAN: \"JAPAN\"\n  STR_INDIA: \"INDIA\"\n  STR_BRAZIL: \"BRAZIL\"\n  STR_AUSTRALIA: \"AUSTRALIA\"\n  STR_NIGERIA: \"NIGERIA\"\n  STR_SOUTH_AFRICA: \"SOUTH AFRICA\"\n  STR_EGYPT: \"EGYPT\"\n  STR_CANADA: \"CANADA\"\n  STR_TANK: \"Tank\"\n  STR_CIVILIAN: \"Civilian\"\n  STR_JAN: \"Jan\"\n  STR_FEB: \"Feb\"\n  STR_MAR: \"Mar\"\n  STR_APR: \"Apr\"\n  STR_MAY: \"May\"\n  STR_JUN: \"Jun\"\n  STR_JUL: \"Jul\"\n  STR_AUG: \"Aug\"\n  STR_SEP: \"Sep\"\n  STR_OCT: \"Oct\"\n  STR_NOV: \"Nov\"\n  STR_DEC: \"Dec\"\n  STR_INTERNATIONAL_RELATIONS: \"International Relations\"\n  STR_COUNTRY: \"Country\"\n  STR_FUNDING: \"Funding\"\n  STR_CHANGE: \"Change\"\n  STR_WEAPON_SYSTEMS: \"WEAPON SYSTEMS\"\n  STR_HWPS: \"HWPs\"\n  STR_DAMAGE_UC_: \"DAMAGE>{ALT}{0}\"\n  STR_ACCESS_LIFT_UFOPEDIA: \"The access lift allows equipment and personnel to be transferred into or out of an underground base. It is always the first facility to be constructed on a new site. The lift area is vulnerable to intrusion from any potential hostile force.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Each accommodation block provides for up to 50 personnel. The facility provides basic recreation, food and sleeping areas.\"\n  STR_LABORATORY_UFOPEDIA: \"Up to 50 scientists can work in a laboratory facility. Laboratories are equipped with the latest technology for research into materials, biochemistry and cosmology. There is privileged access to the best research labs throughout the world, including military establishments.\"\n  STR_WORKSHOP_UFOPEDIA: \"A workshop contains all the equipment necessary to manufacture equipment based on designs from the science labs. Up to 50 engineers can occupy a workshop, although items under construction will also consume some space.\"\n  STR_SMALL_RADAR_SYSTEM_UFOPEDIA: \"A small detection system has an effective radar range of 300 nautical miles and is linked to satellite systems for ground search. Each system has a 10% chance of detecting an average sized object every 30 minutes.\"\n  STR_LARGE_RADAR_SYSTEM_UFOPEDIA: \"A large detection system has an effective range of 450 nautical miles and is linked to satellite systems for ground search. Each system has a 20% chance of detecting an average sized object every 30 minutes.\"\n  STR_MISSILE_DEFENSES_UFOPEDIA: \"Missile defenses provide some protection against incursion by hostile craft which are attempting to land near the base.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"All equipment, weapons systems, munitions, recovered material and Heavy Weapons Platforms are placed in stores, including equipment assigned to craft in hangars.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"Living aliens are likely to require a special habitat to maintain their life systems. The containment facility can keep up to 10 alien life forms in self-contained units.\"\n  STR_LASER_DEFENSES_UFOPEDIA: \"Laser defenses provide protection against incursion by hostile craft.\"\n  STR_PLASMA_DEFENSES_UFOPEDIA: \"Plasma beam defenses provide powerful and efficient protection against incursion by hostile craft.\"\n  STR_FUSION_BALL_DEFENSES_UFOPEDIA: \"Fusion missiles provide the most effective defense against alien attacks. These missiles create an anti-matter implosion which destroys everything within a specific radius.\"\n  STR_GRAV_SHIELD_UFOPEDIA: \"The Gravity shield repels alien craft attempting to land near the base long enough for all defense systems to fire again. In practice this will double the effectiveness of any defense systems at your base.\"\n  STR_MIND_SHIELD_UFOPEDIA: \"Since alien craft rely on brain waves to detect human presence then the most effective counter measure is to shield brain waves from the base. This facility will drastically reduce the chances of detection by alien craft.\"\n  STR_PSIONIC_LABORATORY_UFOPEDIA: \"The psionics lab can assess the psionic potential of all soldiers at the base and give them the necessary training to utilize their psionic skills. Each lab can train up to ten soldiers. Training is allocated at the end of each month. Psionic skills used in conjunction with a Psi-amp can be used for psionic attacks during combat.\"\n  STR_HYPER_WAVE_DECODER_UFOPEDIA: \"Alien communications rely on a supra-dimensional wave which travels almost instantaneously. The decoder facility intercepts UFO transmissions and decodes the information. This will show the type of UFO, the alien race and the type of activity.\"\n  STR_HANGAR_UFOPEDIA: \"Each hangar can accommodate one craft. There are facilities for maintenance, refueling and repair of X-Com craft. Each craft stationed at a base must have a free hangar assigned to it which cannot be used by other craft, even if the assigned craft is out on a mission.\"\n  STR_PISTOL_UFOPEDIA: \"The standard issue X-Com pistol is a high powered semi-automatic with a 12 round capacity.\"\n  STR_RIFLE_UFOPEDIA: \"This highly accurate sniper rifle has laser guided sights and takes 6.7mm ammunition in 20 round clips.\"\n  STR_HEAVY_CANNON_UFOPEDIA: \"The heavy cannon is a devastating, but cumbersome, weapon. Its versatility comes from the fact that it can take three types of ammunition - armor piercing, incendiary and high explosive.\"\n  STR_AUTO_CANNON_UFOPEDIA: \"The auto-cannon combines the versatility and power of a heavy cannon with a faster fire rate.\"\n  STR_ROCKET_LAUNCHER_UFOPEDIA: \"The rocket launcher is a laser guided system which can fire three different sizes of missile.\"\n  STR_LASER_PISTOL_UFOPEDIA: \"The laser pistol is an effective implementation of new technology. It has the convenience of a pistol with faster and more accurate firing.\"\n  STR_LASER_RIFLE_UFOPEDIA: \"The laser rifle is a more powerful and accurate version of the earlier pistol design.\"\n  STR_HEAVY_LASER_UFOPEDIA: \"The heavy laser is cumbersome, but extremely effective.\"\n  STR_GRENADE_UFOPEDIA: \"This standard issue grenade has an accurate and sophisticated timer for precision control.\"\n  STR_SMOKE_GRENADE_UFOPEDIA: \"Smoke grenades are useful for providing cover in exposed combat situations. Use with care because they can benefit the enemy as well.\"\n  STR_PROXIMITY_GRENADE_UFOPEDIA: \"A proximity grenade can be thrown like an ordinary grenade but is triggered by nearby movement after it lands. Great skill and care is required to use these devices properly.\"\n  STR_HIGH_EXPLOSIVE_UFOPEDIA: \"This explosive should only be used for demolition purposes. Keep personnel clear of demolition sites.\"\n  STR_MOTION_SCANNER_UFOPEDIA: \"This sophisticated device uses a variety of detectors and advanced computer algorithms to identify moving enemy units. However, it requires some practice to use effectively. Click on the motion scanner icon on the tactical display. Select 'Use Scanner' from the menu. The Scanner display shows an arrow in the center which is the direction the soldier is facing (North is at the top). The flashing blobs show units which have moved recently. Large units, or fast moving units, will produce larger blobs. Static units will not be detected.\"\n  STR_MEDI_KIT_UFOPEDIA: \"The medi-kit combines a healing facility with pain killers and stimulants. In order to use the medi-kit you must face towards the soldier requiring treatment. If the soldier is stunned you must stand over the body. Click on the medi-kit icon and select 'use medi-kit' from the menu.{NEWLINE}HEALING> Red body parts show fatal wounds. Click on a body part that is wounded. Click on the 'Heal' button. One fatal wound will be cured and some health restored.{NEWLINE}STIMULANT> This will restore energy and revive unconscious (stunned) soldiers. In order to revive an unconscious soldier you must stand directly over the body.{NEWLINE}PAIN KILLER> This will restore the morale of wounded soldiers up to an amount equivalent to the soldier's lost health.\"\n  STR_PSI_AMP_UFOPEDIA: \"The Psi-amp can only be used by soldiers with psionic skill. During combat, click on the Psi-amp, select the type of attack, and select a target unit with the cursor. There are two types of psionic attack:{NEWLINE}PANIC UNIT> If the attack is successful it will reduce the target's morale and may cause it to panic.{NEWLINE}MIND CONTROL> If this is successful then you will gain immediate control of the enemy unit as if it was one of your own. It is more difficult to be successful with this type of attack.\"\n  STR_STUN_ROD_UFOPEDIA: \"This device can only be used in close combat, but will stun a living organism without killing it by using electric shocks.\"\n  STR_MIND_PROBE_UFOPEDIA: \"The mind probe is an alien communication device which is used to take information directly from brain waves. X-Com units can use this device in combat to display an alien's characteristics. Click on the mind probe and the 'use' option. Then click on an alien with the cursor.\"\n  STR_PLASMA_PISTOL_UFOPEDIA: \"Plasma Pistols are a lethal alien weapon based on accelerating particles from within a minute anti-gravity field.\"\n  STR_PLASMA_RIFLE_UFOPEDIA: \"This is a devastatingly powerful weapon based on accelerating particles from within a minute anti-gravity field.\"\n  STR_HEAVY_PLASMA_UFOPEDIA: \"This is a devastatingly powerful weapon based on accelerating particles from within a minute anti-gravity field.\"\n  STR_BLASTER_LAUNCHER_UFOPEDIA: \"This is an alien guided missile launcher which fires powerful 'blaster bombs'. When you click to fire the weapon it will generate 'way points' for the blaster bomb to follow. When you have positioned enough way points click on the special launch icon.\"\n  STR_SMALL_LAUNCHER_UFOPEDIA: \"A small launcher which fires stun bombs. Very useful for capturing live aliens.\"\n  STR_ALIEN_GRENADE_UFOPEDIA: \"This device works in the same way as a terrestrial grenade - except that it is more powerful.\"\n  STR_SMALL_SCOUT: \"Small Scout\"\n  STR_MEDIUM_SCOUT: \"Medium Scout\"\n  STR_LARGE_SCOUT: \"Large Scout\"\n  STR_HARVESTER: \"Harvester\"\n  STR_ABDUCTOR: \"Abductor\"\n  STR_TERROR_SHIP: \"Terror ship\"\n  STR_BATTLESHIP: \"Battleship\"\n  STR_SUPPLY_SHIP: \"Supply ship\"\n  STR_RATING: \"RATING> {0}\"\n  STR_RATING_TERRIBLE: \"TERRIBLE!\"\n  STR_RATING_POOR: \"POOR!\"\n  STR_RATING_OK: \"OK\"\n  STR_RATING_GOOD: \"GOOD!\"\n  STR_RATING_EXCELLENT: \"EXCELLENT!\"\n  STR_SCORE: \"SCORE\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"X-COM PROJECT MONTHLY REPORT\"\n  STR_MONTH: \"Month> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"The council of funding nations is generally satisfied with your progress so far.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"The council of funding nations is very pleased with your excellent progress. Keep up the good work.\"\n  STR_COUNCIL_IS_DISSATISFIED: \"The council of funding nations is dissatisfied with your performance. You must improve your effectiveness in dealing with the alien menace or risk termination of the project.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"You have not succeeded in dealing with the alien invasion and the council of funding nations has regrettably decided to terminate the project. Each nation shall deal with the problem as they see fit. We can only hope that we can come to some accommodation with these apparently hostile forces, and that the general population will come to terms with the alien visitors.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} is particularly pleased with your ability to deal with the localized threat and has agreed to increase its funding.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} are particularly happy with your progress in dealing with local alien incursion and have agreed to increase their funding.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} and {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} is unhappy with your ability to deal with alien activity in its territory and has decided to reduce its financial commitment.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} are unhappy with your ability to deal with alien activity in their territory and have decided to reduce their funding.\"\n  STR_KNOTS: \"{0} knots\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} has signed a secret pact with unknown alien forces and has withdrawn from the project.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} have signed a secret pact with unknown alien forces and have withdrawn from the project.\"\n  STR_MONTHLY_RATING: \"Monthly Rating> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Funding change> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"The funding council is not happy with your financial position. You must reduce your debts below $1 million or the project will be terminated.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"HYPER-WAVE TRANSMISSIONS ARE DECODED\"\n  STR_CRAFT_TYPE: \"CRAFT TYPE\"\n  STR_RACE: \"RACE\"\n  STR_MISSION: \"MISSION\"\n  STR_ZONE: \"ZONE\"\n  STR_ALLOCATE_RESEARCH: \"Allocate Research\"\n  STR_ALLOCATE_MANUFACTURE: \"Allocate Manufacture\"\n  STR_NEW_YORK: \"New York\"\n  STR_WASHINGTON: \"Washington\"\n  STR_LOS_ANGELES: \"Los Angeles\"\n  STR_MONTREAL: \"Montreal\"\n  STR_HAVANA: \"Havana\"\n  STR_MEXICO_CITY: \"Mexico City\"\n  STR_CHICAGO: \"Chicago\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_DALLAS: \"Dallas\"\n  STR_BRASILIA: \"Brasilia\"\n  STR_BOGOTA: \"Bogota\"\n  STR_BUENOS_AIRES: \"Buenos Aires\"\n  STR_SANTIAGO: \"Santiago\"\n  STR_RIO_DE_JANEIRO: \"Rio De Janeiro\"\n  STR_LIMA: \"Lima\"\n  STR_CARACAS: \"Caracas\"\n  STR_LONDON: \"London\"\n  STR_PARIS: \"Paris\"\n  STR_BERLIN: \"Berlin\"\n  STR_MOSCOW: \"Moscow\"\n  STR_ROME: \"Rome\"\n  STR_MADRID: \"Madrid\"\n  STR_BUDAPEST: \"Budapest\"\n  STR_LAGOS: \"Lagos\"\n  STR_CAIRO: \"Cairo\"\n  STR_CASABLANCA: \"Casablanca\"\n  STR_PRETORIA: \"Pretoria\"\n  STR_NAIROBI: \"Nairobi\"\n  STR_CAPE_TOWN: \"Cape Town\"\n  STR_KINSHASA: \"Kinshasa\"\n  STR_ANKARA: \"Ankara\"\n  STR_DELHI: \"Delhi\"\n  STR_KARACHI: \"Karachi\"\n  STR_BAGHDAD: \"Baghdad\"\n  STR_TEHRAN: \"Tehran\"\n  STR_BOMBAY: \"Bombay\"\n  STR_CALCUTTA: \"Calcutta\"\n  STR_TOKYO: \"Tokyo\"\n  STR_BEIJING: \"Beijing\"\n  STR_BANGKOK: \"Bangkok\"\n  STR_MANILA: \"Manila\"\n  STR_SEOUL: \"Seoul\"\n  STR_SINGAPORE: \"Singapore\"\n  STR_JAKARTA: \"Jakarta\"\n  STR_SHANGHAI: \"Shanghai\"\n  STR_HONG_KONG: \"Hong Kong\"\n  STR_NOVOSIBIRSK: \"Novosibirsk\"\n  STR_CANBERRA: \"Canberra\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_MELBOURNE: \"Melbourne\"\n  STR_PERTH: \"Perth\"\n  STR_PSI_TRAINING: \"Psi Training\"\n  STR_PSIONIC_TRAINING: \"PSIONIC TRAINING\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Remaining Psi-lab capacity> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"Psionic{NEWLINE}Strength\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"Psionic Skill{NEWLINE}/Improvement\"\n  STR_PSI_AMP: \"Psi-Amp\"\n  STR_IN_TRAINING: \"In{NEWLINE}Training?\"\n  STR_TARGETTED_BY: \"TARGETTED BY:\"\n  STR_WEAPONS_CREW_HWPS: \"WEAPONS/{NEWLINE}CREW/HWPs\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"is low on fuel,{NEWLINE}returning to base\"\n  STR_SOLDIER_LIST: \"Soldier List\"\n  STR_RANK_: \"RANK> {ALT}{0}\"\n  STR_MISSIONS: \"MISSIONS> {ALT}{0}\"\n  STR_KILLS: \"KILLS> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"WOUND RECOVERY> {ALT}{0}\"\n  STR_TIME_UNITS: \"TIME UNITS\"\n  STR_STAMINA: \"STAMINA\"\n  STR_HEALTH: \"HEALTH\"\n  STR_BRAVERY: \"BRAVERY\"\n  STR_REACTIONS: \"REACTIONS\"\n  STR_FIRING_ACCURACY: \"FIRING ACCURACY\"\n  STR_THROWING_ACCURACY: \"THROWING ACCURACY\"\n  STR_STRENGTH: \"STRENGTH\"\n  STR_PSIONIC_STRENGTH: \"PSIONIC STRENGTH\"\n  STR_PSIONIC_SKILL: \"PSIONIC SKILL\"\n  STR_NEW_RANK: \"NEW RANK\"\n  STR_PROMOTIONS: \"Promotions\"\n  STR_SOLDIERS_UC: \"SOLDIERS\"\n  STR_TANK_CANNON_UFOPEDIA: \"Automated Heavy Weapons Platforms are designed to complement an X-Com squad. The combination of high fire power and strong armor makes these units valuable for open terrain fire fights. Make sure that there are sufficient cannon shells in your stores to re-arm tanks. They are armed automatically when you assign them to a squad.\"\n  STR_TANK_ROCKET_LAUNCHER_UFOPEDIA: \"This automated Heavy Weapons Platform is armed with powerful rockets. This will be devastating for any alien foe. Make sure your stores are kept supplied with HWP rockets.\"\n  STR_TANK_LASER_CANNON_UFOPEDIA: \"Laser weapons are a useful addition for HWPs. It combines heavy firepower with no ammunition restrictions.\"\n  STR_HOVERTANK_PLASMA_UFOPEDIA: \"Alien technology has given the HWP a new lease of life. The added maneuverability of air travel and the power of plasma beams is a lethal combination.\"\n  STR_HOVERTANK_LAUNCHER_UFOPEDIA: \"This hovertank has a fusion ball launcher that is capable of immense devastation. Use it with great care. You will have to manufacture the fusion balls to keep these HWPs fully armed. A fusion ball is an intelligent guided weapon. In order to fire it you select a number of 'way points' with the cursor and then click on the launch icon to fire the fusion ball.\"\n  STR_HEAVY_PLASMA_CLIP_UFOPEDIA: \"This compact device is used as ammunition for a Heavy Plasma Gun. It contains a small quantity of Elerium.\"\n  STR_PLASMA_RIFLE_CLIP_UFOPEDIA: \"This small object is used as a power source for a Plasma Rifle - a medium powered alien weapon. Contains a small quantity of Elerium.\"\n  STR_PLASMA_PISTOL_CLIP_UFOPEDIA: \"Power source for the small alien Plasma Pistol. Contains Elerium - the source of all alien power.\"\n  STR_STUN_BOMB_UFOPEDIA: \"The Stun Bomb is used for capturing live human specimens, but it can also be used against most alien races. It is fired from a Small Launcher.\"\n  STR_ALIEN_RESEARCH_UFOPEDIA: \"The alien research mission is used for collecting basic data on earth and its inhabitants. Small vehicles are predominantly used, with occasional landings in deserted areas. This type of alien activity poses the least threat to X-Com, with little concern from governments or the public.\"\n  STR_ALIEN_HARVEST_UFOPEDIA: \"The aliens have many uses for earth's fauna. Animals are abducted secretly, and returned with various organs removed. Cattle mutilations are predominantly reported along with UFO sightings. This type of alien activity causes great concern for governments and considerable anxiety amongst the population. This type of activity occurs mainly in farming land. The theory behind the 'alien harvest' suggests that alien races originally 'seeded' the planet with its flora and fauna, and now they have returned to reap the harvest they have sown.\"\n  STR_ALIEN_ABDUCTION_UFOPEDIA: \"This is the most insidious form of alien activity. The abduction by aliens is widely reported, despite the aliens' attempts to erase the experience from their victims' memories. Abductees report being subject to humiliating physical examinations, including impregnation of alien fetuses and bizarre genetic experiments. The purpose behind this activity appears to be linked to genetic mutation and manipulation of the aliens' own genetic material. This activity causes great alarm, and occurs in populated areas or cities\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"Earth governments can be infiltrated by alien agents which are human in appearance. This can result in official contact between aliens and governments at the highest level. The climax of this activity is characterized by intense UFO activity in the vicinity of major cities. The aliens will attempt to sign a pact with an earth government by offering knowledge of their superior technology. In return the government will allow the aliens to conduct their activity unhindered. This alien mission represents the worst threat to X-Com. If a government agrees to a pact then its funding will cease.\"\n  STR_ALIEN_BASE_UFOPEDIA: \"Aliens will construct secret underground bases in remote locations. After some initial reconnaissance flights some intense UFO activity will occur as the base is being built. These bases are known to contain experimental labs for human abductees, and supplies for further activity in the region. The presence of alien bases will generate a large amount of reported alien activity without the presence of UFOs. In order to locate a base an X-Com craft must patrol an area for a few hours to stand some chance of detection.\"\n  STR_ALIEN_TERROR_UFOPEDIA: \"When the aliens terrorize a city they will deploy some special forces with awesome powers. Civilians will be directly threatened, and governments will be forced to evacuate whole areas. The main purpose behind this activity is to generate sufficient public hysteria so that governments will threaten the X-Com project.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"If X-Com interceptors are being particularly successful in shooting down UFOs then the aliens may take some retaliatory action. This could result in a direct attack against an X-Com base. However, the aliens have to find an X-Com base in order to attack it, and provided UFOs are kept away then there should be little danger of an assault.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"Once an alien base is constructed then it is resupplied on a regular basis by a special supply vessel. If one of these vessels is detected while landing then it is certain that an alien base is nearby.\"\n  STR_SMALL_SCOUT_UFOPEDIA: \"This tiny craft is primarily used for reconnaissance or research. It normally precedes larger vessels at the start of an alien mission.\"\n  STR_MEDIUM_SCOUT_UFOPEDIA: \"A medium sized scout vessel that poses little threat to earth forces. Normally appears before larger vessels during missions.\"\n  STR_LARGE_SCOUT_UFOPEDIA: \"The largest alien scout craft is a general purpose vessel that is used in all types of alien mission.\"\n  STR_HARVESTER_UFOPEDIA: \"The harvester has a trap door in its base and is equipped with lifting gear to haul up cattle or other beasts. Laser cutters are used to extract the desired material and the carcass is dumped on the ground. There are also storage containers for body parts.\"\n  STR_ABDUCTOR_UFOPEDIA: \"This vessel is equipped with an examination room for performing horrific experiments on human subjects. The victim is normally paralyzed by telepathic powers, but remains conscious while on the operating table.\"\n  STR_TERROR_SHIP_UFOPEDIA: \"The terror ship has a containment facility for large alien terror weapons or creatures. It is used to transport these alien terrorists into populated areas.\"\n  STR_BATTLESHIP_UFOPEDIA: \"The battleship is the largest and most powerful alien craft. It is normally the primary alien mission craft, equipped with powerful weapons and numerous crew members.\"\n  STR_SUPPLY_SHIP_UFOPEDIA: \"The supply vessel is used during the construction of alien bases or for supplying existing bases. It carries alien food containers and reproduction chambers.\"\n  STR_DISMANTLE: \"Dismantle\"\n  STR_FACILITY_IN_USE: \"FACILITY IN USE\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"CANNOT DISMANTLE FACILITY!{SMALLLINE}All base facilities must be linked to the access lift.\"\n  STR_TRANSFER_ITEMS_TO: \"Transfer Items to {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"NO ALIEN CONTAINMENT FOR TRANSFER!{SMALLLINE}Live aliens need an alien containment facility in order to survive.\"\n  STR_AMOUNT_AT_DESTINATION: \"AMOUNT AT{NEWLINE}DESTINATION\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"Alien dies as there is no alien containment facility\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"NO FREE ACCOMMODATION!{SMALLLINE}The destination base does not have enough space in the living quarters for the crew assigned to the craft.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"NOT ENOUGH STORE SPACE!{SMALLLINE}The destination base does not have enough store space for the equipment assigned to the craft.\"\n  STR_ITEMS_ARRIVING: \"Items Arriving\"\n  STR_DESTINATION_UC: \"DESTINATION\"\n  STR_PISTOL: \"Pistol\"\n  STR_PISTOL_CLIP: \"Pistol Clip\"\n  STR_RIFLE: \"Rifle\"\n  STR_RIFLE_CLIP: \"Rifle Clip\"\n  STR_HEAVY_CANNON: \"Heavy Cannon\"\n  STR_HC_AP_AMMO: \"HC-AP Ammo\"\n  STR_HC_HE_AMMO: \"HC-HE Ammo\"\n  STR_HC_I_AMMO: \"HC-I Ammo\"\n  STR_AUTO_CANNON: \"Auto-Cannon\"\n  STR_AC_AP_AMMO: \"AC-AP Ammo\"\n  STR_AC_HE_AMMO: \"AC-HE Ammo\"\n  STR_AC_I_AMMO: \"AC-I Ammo\"\n  STR_ROCKET_LAUNCHER: \"Rocket Launcher\"\n  STR_SMALL_ROCKET: \"Small Rocket\"\n  STR_LARGE_ROCKET: \"Large Rocket\"\n  STR_INCENDIARY_ROCKET: \"Incendiary Rocket\"\n  STR_GRENADE: \"Grenade\"\n  STR_SMOKE_GRENADE: \"Smoke Grenade\"\n  STR_PROXIMITY_GRENADE: \"Proximity Grenade\"\n  STR_HIGH_EXPLOSIVE: \"High Explosive\"\n  STR_STUN_ROD: \"Stun Rod\"\n  STR_HEAVY_PLASMA: \"Heavy Plasma\"\n  STR_HEAVY_PLASMA_CLIP: \"Heavy Plasma Clip\"\n  STR_PLASMA_RIFLE: \"Plasma Rifle\"\n  STR_PLASMA_RIFLE_CLIP: \"Plasma Rifle Clip\"\n  STR_PLASMA_PISTOL: \"Plasma Pistol\"\n  STR_PLASMA_PISTOL_CLIP: \"Plasma Pistol Clip\"\n  STR_BLASTER_LAUNCHER: \"Blaster Launcher\"\n  STR_BLASTER_BOMB: \"Blaster Bomb\"\n  STR_SMALL_LAUNCHER: \"Small Launcher\"\n  STR_STUN_BOMB: \"Stun Bomb\"\n  STR_ALIEN_GRENADE: \"Alien Grenade\"\n  STR_ELERIUM_115: \"Elerium-115\"\n  STR_MIND_PROBE: \"Mind Probe\"\n  STR_SECTOID_CORPSE: \"Sectoid Corpse\"\n  STR_SNAKEMAN_CORPSE: \"Snakeman Corpse\"\n  STR_ETHEREAL_CORPSE: \"Ethereal Corpse\"\n  STR_MUTON_CORPSE: \"Muton Corpse\"\n  STR_FLOATER_CORPSE: \"Floater Corpse\"\n  STR_CELATID_CORPSE: \"Celatid Corpse\"\n  STR_SILACOID_CORPSE: \"Silacoid Corpse\"\n  STR_CHRYSSALID_CORPSE: \"Chryssalid Corpse\"\n  STR_REAPER_CORPSE: \"Reaper Corpse\"\n  STR_SECTOPOD_CORPSE: \"Sectopod Corpse\"\n  STR_CYBERDISC_CORPSE: \"Cyberdisc Corpse\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"Not enough ammunition to arm HWP{SMALLLINE}Each HWP requires {0} {1}.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Not enough equipment to fully re-equip squad\"\n  STR_MARS_CYDONIA_LANDING: \"Mars: Cydonia Landing\"\n  STR_MARS_CYDONIA_LANDING_BRIEFING: \"Your Avenger craft has landed in the region of Cydonia on the surface of Mars. Our information indicates that one of the pyramid constructions contains a green access lift to an underground complex. Once you have assembled all your soldiers in the lift area click on the 'abort mission' icon to continue to the next stage.\"\n  STR_MARS_THE_FINAL_ASSAULT: \"Mars: The Final Assault\"\n  STR_MARS_THE_FINAL_ASSAULT_BRIEFING: \"The pyramid lift takes your battle weary soldiers deep below the planet's surface. They arrive in the heart of a large complex of tunnels and chambers. The alien brain is hidden somewhere in the labyrinth. It must be destroyed if the earth is to be saved from alien enslavement.{NEWLINE}{NEWLINE}Good Luck!\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"You will need to research a{NEWLINE}{0}{NEWLINE}in order to produce the{NEWLINE}{1}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"The aliens have destroyed the undefended base {0}\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"X-Com agents have located an alien base in {0}\"\n  STR_STANDOFF: \"STANDOFF\"\n  STR_CAUTIOUS_ATTACK: \"CAUTIOUS ATTACK\"\n  STR_STANDARD_ATTACK: \"STANDARD ATTACK\"\n  STR_AGGRESSIVE_ATTACK: \"AGGRESSIVE ATTACK\"\n  STR_DISENGAGING: \"DISENGAGING\"\n  STR_UFO_HIT: \"UFO HIT!\"\n  STR_UFO_CRASH_LANDS: \"UFO CRASH LANDS!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Minimize at Standoff Range Only\"\n  STR_UFO_RETURN_FIRE: \"UFO RETURNS FIRE!\"\n  STR_INTERCEPTOR_DAMAGED: \">>> INTERCEPTOR DAMAGED <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> INTERCEPTOR DESTROYED <<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"UFO OUTRUNNING INTERCEPTOR!\"\n  STR_ALIENS_TERRORISE: \"ALIENS TERRORIZE\"\n  STR_LONG_RANGE_DETECTION: \"Long Range Detection\"\n  STR_STORES_UC: \"STORES\"\n  STR_DIFFICULTY_LEVEL: \"Difficulty Level\"\n  STR_INTERCEPT: \"INTERCEPT\"\n  STR_BASES: \"BASES\"\n  STR_GRAPHS: \"GRAPHS\"\n  STR_UFOPAEDIA_UC: \"UFOPEDIA\"\n  STR_OPTIONS_UC: \"OPTIONS\"\n  STR_FUNDING_UC: \"FUNDING\"\n  STR_5_SECONDS: \"5 Secs\"\n  STR_1_MINUTE: \"1 Min\"\n  STR_5_MINUTES: \"5 Mins\"\n  STR_30_MINUTES: \"30 Mins\"\n  STR_1_HOUR: \"1 Hour\"\n  STR_1_DAY: \"1 Day\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"X-Com Performance Roster\"\n  STR_ENTER_NAME: \"Enter Name\"\n  STR_PERFORMANCE_RATING: \"Performance Rating\"\n  STR_VICTORY_DATE: \"Victory Date\"\n  STR_ELECTRO_FLARE: \"Electro-flare\"\n  STR_ELECTRO_FLARE_UFOPEDIA: \"This compact device produces a bright flare light when it is thrown. This will highlight enemy units in the vicinity of the electro-flare during night time missions.\"\n  STR_MONTHLY_COSTS: \"Monthly Costs\"\n  STR_CRAFT_RENTAL: \"Craft Rental\"\n  STR_SALARIES: \"Salaries\"\n  STR_BASE_MAINTENANCE: \"Base maintenance\"\n  STR_COST_PER_UNIT: \"Cost per unit\"\n  STR_QUANTITY: \"Quantity\"\n  STR_TOTAL: \"Total\"\n  STR_IN_PSIONIC_TRAINING: \"In Psionic Training\"\n  STR_BLASTER_BOMB_UFOPEDIA: \"This device is a highly explosive missile that has an intelligent guidance system. It is fired from a Blaster Launcher.\"\n  STR_FRONT_ARMOR: \"Front Armor\"\n  STR_LEFT_ARMOR: \"Left Armor\"\n  STR_RIGHT_ARMOR: \"Right Armor\"\n  STR_REAR_ARMOR: \"Rear Armor\"\n  STR_UNDER_ARMOR: \"Under Armor\"\n  STR_ROUNDS: \"Rounds\"\n  STR_UNIT: \"UNIT> {0}\"\n  STR_ENERGY: \"ENERGY\"\n  STR_MORALE: \"MORALE\"\n  STR_ARMOR_: \"ARMOR> {0}\"\n  STR_FRONT_ARMOR_UC: \"FRONT ARMOR\"\n  STR_LEFT_ARMOR_UC: \"LEFT ARMOR\"\n  STR_RIGHT_ARMOR_UC: \"RIGHT ARMOR\"\n  STR_REAR_ARMOR_UC: \"REAR ARMOR\"\n  STR_SKILLS: \"SKILLS> {0}\"\n  STR_LEVEL: \"LEVEL> {0}\"\n  STR_HEAD: \"HEAD\"\n  STR_TORSO: \"TORSO\"\n  STR_RIGHT_ARM: \"RIGHT ARM\"\n  STR_LEFT_ARM: \"LEFT ARM\"\n  STR_RIGHT_LEG: \"RIGHT LEG\"\n  STR_LEFT_LEG: \"LEFT LEG\"\n  STR_PAIN_KILLER: \"PAIN KILLER\"\n  STR_STIMULANT: \"STIMULANT\"\n  STR_HEAL: \"HEAL\"\n  STR_TIME_UNITS_SHORT: \"TU>{ALT}{0}\"\n  STR_WEIGHT: \"Weight>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"React>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"P.Skill>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"P.Str>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Alien Artifact\"\n  STR_AMMO_ROUNDS_LEFT: \"AMMO:{NEWLINE}ROUNDS{NEWLINE}LEFT={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Pain>{ALT}{0}{ALT}{NEWLINE}Stim>{ALT}{1}{ALT}{NEWLINE}Heal>{ALT}{2}\"\n  STR_THROW: \"Throw\"\n  STR_AUTO_SHOT: \"Auto Shot\"\n  STR_SNAP_SHOT: \"Snap Shot\"\n  STR_AIMED_SHOT: \"Aimed Shot\"\n  STR_STUN: \"Stun\"\n  STR_PRIME_GRENADE: \"Prime Grenade\"\n  STR_USE_SCANNER: \"Use Scanner\"\n  STR_USE_MEDI_KIT: \"Use Medi-kit\"\n  STR_LAUNCH_MISSILE: \"Launch Missile\"\n  STR_ACCURACY_SHORT: \"Acc>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Not Enough Time Units!\"\n  STR_NOT_ENOUGH_ENERGY: \"Not Enough Energy!\"\n  STR_NO_ROUNDS_LEFT: \"No Rounds left!\"\n  STR_NO_AMMUNITION_LOADED: \"No Ammunition Loaded!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Wrong Ammunition for this Weapon!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"Weapon is already loaded!\"\n  STR_NO_LINE_OF_FIRE: \"No Line of Fire!\"\n  STR_GRENADE_IS_ACTIVATED: \"Grenade is Activated!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Grenade De-activated!\"\n  STR_THERE_IS_NO_ONE_THERE: \"There is no one there!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Unable to use alien artifact until researched!\"\n  STR_OUT_OF_RANGE: \"Out of Range!\"\n  STR_UNABLE_TO_THROW_HERE: \"Unable to throw here!\"\n  STR_SET_TIMER: \"Set Timer\"\n  STR_HIDDEN_MOVEMENT: \"HIDDEN MOVEMENT\"\n  STR_TURN: \"TURN> {0}\"\n  STR_SIDE: \"SIDE> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Press button to continue\"\n  STR_MIND_CONTROL: \"Mind Control\"\n  STR_PANIC_UNIT: \"Panic Unit\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Morale Attack Successful\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Mind Control Successful\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}has gone Berserk\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}has gone Berserk\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}has Panicked\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}has Panicked\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Aliens\"\n  STR_RIGHT_HAND: \"RIGHT HAND\"\n  STR_LEFT_HAND: \"LEFT HAND\"\n  STR_RIGHT_SHOULDER: \"RIGHT SHOULDER\"\n  STR_LEFT_SHOULDER: \"LEFT SHOULDER\"\n  STR_BACK_PACK: \"BACK PACK\"\n  STR_BELT: \"BELT\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}is under alien control\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}is under alien control\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}has become unconscious\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}has become unconscious\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}has died from a fatal wound\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}has died from a fatal wound\"\n  STR_USE_MIND_PROBE: \"Use Mind Probe\"\n  STR_FATAL_WOUNDS: \"FATAL WOUNDS\"\n  STR_UNDER_ARMOR_UC: \"UNDER ARMOR\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Time Units reserved for Snap Shot\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Time Units reserved for Auto Shot\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Time Units reserved for Aimed Shot\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Time Units reserved for Kneeling\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"TUs reserved for Kneeling and Firing\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} Unit in X-Com Craft\"\n    other: \"{N} Units in X-Com Craft\"\n  STR_UNITS_OUTSIDE:\n    one: \"{N} Unit left outside\"\n    other: \"{N} Units left outside\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} Unit in Entrance\"\n    other: \"{N} Units in Entrance\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} Unit in Target Exit\"\n    other: \"{N} Units in Target Exit\"\n  STR_ABORT_MISSION_QUESTION: \"Abort Mission?\"\n  STR_CORPSE: \"Corpse\"\n  STR_UNLOAD_CRAFT: \"Unload\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}has been killed\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}has been killed\"\n  STR_HIT_MELEE: \"Hit\"\n  STR_GROUND: \"GROUND\"\n  STR_LIVING_QUARTERS_PLURAL: \"Living Quarters\"\n  STR_LIST_ITEM: \"ITEM\"\n  STR_PERSONAL_ARMOR_UFOPEDIA: \"Using the newly discovered Alien Alloys, this new armor gives our men a fighting chance against the alien threat.\"\n  STR_POWER_SUIT_UFOPEDIA: \"A powerful new protection for soldiers, this armor is powered by an Elerium energy source and greatly amplifies the speed and strength of the wearer, it offers the best protection yet for combat troops.\"\n  STR_FLYING_SUIT_UFOPEDIA: \"An enhanced version of the Power Suit, incorporating alien anti-gravity navigation technology to allow full freedom of movement across the battlefield.\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"All Aliens killed in crash,{NEWLINE}Auto recovery initiated\"\n  STR_RESET: \"Reset\"\n  STR_MEMORIAL: \"Memorial\"\n  STR_DATE_UC: \"DATE\"\n  STR_SOLDIERS_RECRUITED_UC: \"SOLDIERS RECRUITED>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"SOLDIERS LOST>{ALT}{0}\"\n  MAP_CULTA: \"Farm\"\n  MAP_FOREST: \"Forest\"\n  MAP_JUNGLE: \"Jungle\"\n  MAP_MOUNT: \"Mountain\"\n  MAP_DESERT: \"Desert\"\n  MAP_POLAR: \"Polar\"\n  MAP_URBAN: \"City\"\n  MAP_UBASE: \"Alien Base\"\n  MAP_XBASE: \"X-Com Base\"\n  MAP_MARS: \"Mars\"\n  STR_MIXED: \"Mixed\"\n  STR_REMOVE_SELECTED: \"Remove Selected\"\n  STR_LIVE_ALIENS: \"Live{NEWLINE}Specimens\"\n  STR_DEAD_ALIENS: \"Rejected{NEWLINE}Specimens\"\n  STR_UNDER_INTERROGATION: \"Being{NEWLINE}Studied\"\n  STR_CONTAINMENT_EXCEEDED: \"ALIEN CONTAINMENT LIMITS EXCEEDED!{SMALLLINE}Insufficient containment space at {0}. You must remove excess aliens from containment (who will then die).\"\n  STR_MANAGE_CONTAINMENT: \"Manage Alien Containment\"\n  STR_STORAGE_EXCEEDED: \"STORAGE SPACE EXCEEDED!{SMALLLINE}Insufficient storage space at {0}. You must sell off excess items.\"\n  STR_GO_TO_BASE: \"Go to Base\"\n  STR_MELEE_ACCURACY: \"MELEE ACCURACY\"\n  STR_SELL_PRODUCTION: \"SELL\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Both hands must be empty!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Not enough items to copy template!\"\n  STR_UNLOAD_WEAPON: \"Unload weapon\"\n  STR_ALL_ITEMS: \"All Items\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"NO MORE EQUIPMENT ALLOWED ON BOARD!{SMALLLINE}You are only allowed to take a maximum of {N} item of equipment on this craft.\"\n    other: \"NO MORE EQUIPMENT ALLOWED ON BOARD!{SMALLLINE}You are only allowed to take a maximum of {N} items of equipment on this craft.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}CONTROL CENTER DESTROYED{NEWLINE}Make your way to the entrance and abort.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"X-Com facilities cannot be built underwater\"\n  STR_LEVEL_SHORT: \"{0}\"\n  STR_PERSONNEL: \"Personnel\"\n  STR_CRAFT_ARMAMENT: \"Craft & Armament\"\n  STR_COMPONENTS: \"Components\"\n  STR_SOLDIERS_RECRUITED: \"Soldiers recruited\"\n  STR_SOLDIERS_LOST: \"Soldiers lost\"\n  STR_TOTAL_UFOS: \"UFOs detected\"\n  STR_TOTAL_ALIEN_BASES: \"Alien bases discovered\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"PST\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"PSK\"\n  FEMALE_CIVILIAN: \"Civilian, Female\"\n  MALE_CIVILIAN: \"Civilian, Male\"\n  CYBERDISC_WEAPON: \"Cyberdisc Weapon\"\n  REAPER_WEAPON: \"Reaper Weapon\"\n  CHRYSSALID_WEAPON: \"Chryssalid Weapon\"\n  CELATID_WEAPON: \"Celatid Weapon\"\n  SILACOID_WEAPON: \"Silacoid Weapon\"\n  SECTOPOD_WEAPON: \"Sectopod Weapon\"\n  ZOMBIE_WEAPON: \"Zombie Weapon\"\n  ALIEN_PSI_WEAPON: \"Alien Psi Weapon\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/es-419.yml",
    "content": "es-419:\n  STR_AVENGER_UFOPEDIA: \"NAVE ESPACIAL DE TRANSPORTE Y COMBATE. ESTA NAVE ES LA ADAPTACIÓN DEFINITIVA DE LA TECNOLOGÍA ALIENÍGENA.\"\n  STR_INTERCEPTOR_UFOPEDIA: \"NAVE DE COMBATE CON DOBLE TURBINA DE DETONACION DE PULSO Y SISTEMAS ELECTRONICOS ESPECIALMENTE PROTEGIDOS. ESTA ES LA MEJOR TECNOLOGIA TERRESTRE DISPONIBLE.\"\n  STR_LIGHTNING_UFOPEDIA: \"NAVE DE TRANSPORTE Y COMBATE. UNA ADAPTACIÓN CRUDA PERO EFICAZ DEL SISTEMA DE PROPULSIÓN ALIENÍGENA.\"\n  STR_SKYRANGER_UFOPEDIA: \"NAVE DE TRANSPORTE. EL MÁS RÁPIDO DE SU CLASE, CON DESPEGUE Y ATERRIZAJE VERTICAL (V.T.O.L.)\"\n  STR_FIRESTORM_UFOPEDIA: \"NAVE DE COMBATE, ESTA NAVE DE CAZA MONOPLAZA ES UNA RÉPLICA DEL CLASICO DISEÑO DEL PLATILLO VOLADOR ALIENÍGENA CON PROPULSION CENTRAL. \"\n  STR_STINGRAY_UFOPEDIA: \"MISIL AVANZADO DE AIRE-AIRE CON COMPONENTES ELECTRONICOS ESPECIALMENTE PROTEGIDOS.\"\n  STR_AVALANCHE_UFOPEDIA: \"MISIL DE AIRE-AIRE CON CABEZA NUCLEAR, PERO EXTREMADAMENTE PESADO. \"\n  STR_CANNON_UFOPEDIA: \"CAÑÓN DE GRAN POTENCIA QUE DISPARA MUNICIÓN PERFORANTE CAPAZ DE ATRAVESAR 16 PULGADAS DE ACERO.\"\n  STR_FUSION_BALL_UFOPEDIA: \"ESTE LANZACOHETES DISPARA UN MISIL DE FORMA ESFÉRICA IMPULSADA POR UNA REACCIÓN DE ANTI-MATERIA. ESTE MISIL DESTRUYE EL BLANCO CON UNA IMPLOSIÓN DE ONDA GRAVITATORIA.\"\n  STR_LASER_CANNON_UFOPEDIA: \"ESTE RAYO LÁSER CONVENCIONAL SE ACCIONA POR UNA CÁMARA DE REACCIÓN DE ANTIMATERIA.\"\n  STR_PLASMA_BEAM_UFOPEDIA: \"EL RAYO GRAVITATORIO DIRIGE LA IMPLOSIÓN DE UN CAMPO GRAVITACIONAL FINAMENTE CALIBRADO.\"\n  STR_SECTOID_UFOPEDIA: \"Los rangos de jerarquía Sectoide van desde soldados hasta lideres los cuales poseen poderosas habilidades psíquicas. Estas pueden ser usadas para desmoralizar soldados en combate e incluso controlar sus mentes. Tienden a realizar abducciones de humanos para obtener material genético, realizar cruces raciales y crear clones para infiltrarse en la sociedad humana. También realizan mutilaciones de ganado para proveerse alimentos al igual que material genético. Parece que esta raza quiere desarrollar híbridos genéticamente superiores para mejorar la eficacia de su sociedad tipo colmena.\"\n  STR_SECTOID_AUTOPSY: \"Autopsia de Sectoide\"\n  STR_SECTOID_AUTOPSY_UFOPEDIA: \"La autopsia revela vestigios de órganos digestivos y una estructura sencilla. El cerebro y los ojos están muy desarrollados. La estructura sugiere una alteración genética o mutación. Una boca y nariz pequeñas parecen tener poca utilidad. Las membranas entre los dedos y los pies planos sugieren un origen acuático. No hay órganos reproductivos o indicios cómo se reproduce esta especie. Lo más probable es que sea una especie creada por ingeniería genética.\"\n  STR_SNAKEMAN_UFOPEDIA: \"Esta raza se ha desarrollado en un medio extremadamente hostil. Son muy resistentes y pueden aguantar cambios extremos de temperatura. Su movilidad depende de una enorme parte inferior similar a una serpiente y protege todos los órganos vitales. Sus objetivos parecen ser meramente predatorios y parecen estar bajo el control de alguna otra raza que dirige sus incursiones de estilo militar en la Tierra.\"\n  STR_SNAKEMAN_AUTOPSY: \"Autopsia de Hombre-Serpiente\"\n  STR_SNAKEMAN_AUTOPSY_UFOPEDIA: \"La piel es extremadamente dura y resistente al calor. El sistema cardio-vascular es parte del sistema muscular, el cual usa principios hidráulicos para crear movimiento. El único músculo verdadero es el \\\"corazón\\\". El sistema reproductor parece ser muy eficiente, la reproducción es asexual; cada hombre-serpiente lleva cincuenta huevos dentro de su cuerpo en todo momento. Si se les dejara actuar, esta especie supondría una amenaza muy seria para la vida en la Tierra.\"\n  STR_ETHEREAL_UFOPEDIA: \"Este ser tiene poderes mentales asombrosos que le permiten comunicarse telepáticamente y usar habilidades telequineticas. Las aparentes debilidades físicas de esta criatura se compensan gracias a estos poderes mentales. No comprendemos cómo funcionan estos poderes telequinéticos, ya que parecen desafiar las leyes de física como la conocemos, y por ello son muy peligrosos en combate. Es muy raro verlos en la Tierra, pues parecen confiar en otras razas para conseguir sus objetivos.\"\n  STR_ETHEREAL_AUTOPSY: \"Autopsia de Etéreo\"\n  STR_ETHEREAL_AUTOPSY_UFOPEDIA: \"Este ser esta físicamente subdesarrollado y parece ser incapaz de realizar ninguna función vital. Los músculos están severamente atrofiados y parece que los órganos internos están poco desarrollados. Los órganos sensoriales, incluyendo los ojos, parecen no funcionar. Sin embargo, su cerebro está bien desarrollado y utiliza una gran parte del suministro sanguíneo del cuerpo. Es un misterio cómo esta criatura puede sobrevivir sin apoyo externo.\"\n  STR_MUTON_UFOPEDIA: \"Esta criatura humanoide es inteligente y tiene una constitución física muy fuerte. Tiene un apetito particular por carne cruda de cualquier tipo, la cual necesita para sobrevivir como los carnívoros de la Tierra. Parece que dependen en órdenes telepáticas enviadas por una raza conocida como \\\"Etéreos\\\". Cuando este lazo telepático se rompe su sistema cognitivo parece fallar y mueren. Esta raza tiene implantes cibernéticos que sirven para mejorar su eficacia en combate, son claramente la infantería una inteligencia superior.\"\n  STR_MUTON_AUTOPSY: \"Autopsia de Muton\"\n  STR_MUTON_AUTOPSY_UFOPEDIA: \"La \\\"piel\\\" de esta criatura parece ser una armadura creada orgánicamente e injerta en el cuerpo. Hay numerosos implantes cibernéticos que sirven para mejorar el sistema cardio-vascular y los sentidos. Los órganos reproductores han sido extirpados quirurgicamente. Evidentemente la vida de estas desafortunadas criaturas se limita a la guerra y la conquista. La munición perforante no es muy eficaz contra su piel reforzada.\"\n  STR_CELATID_UFOPEDIA: \"Esta forma de vida tiene la misteriosa habilidad natural de flotar y parece detectar las ondas mentales humanas, gracias a lo cual puede encontrar a su blanco aunque éste esté bien escondido. Una vez que ha detectado el blanco, el celátido aterriza y dispara pequeños glóbulos de veneno altamente corrosivo. Esta criatura es capaz de crear clones de sí misma a un ritmo alarmante y suele acompañar a la raza \\\"Muton\\\" en sus incursiones.\"\n  STR_CELATID_AUTOPSY: \"Autopsia de Celátido\"\n  STR_CELATID_AUTOPSY_UFOPEDIA: \"En el núcleo hay un pequeño dispositivo biomecánico que parece ser resultado de la evolución natural de la criatura y actúa como un sistema de propulsión antigravitatorio. La vejiga de veneno es el órgano más grande y no parece haber ninguna estructura cerebral independiente, además no se distingue ningún sistema digestivo ni reproductivo. También se descubrió un pequeño órgano contiene embriones capaces de crecer y convertirse rápidamente en criaturas adultas.\"\n  STR_SILACOID_UFOPEDIA: \"Esta forma de vida basada en silicio genera una cantidad enorme de energía térmica. Es capaz de demoler rocas y digerirlas en su núcleo a alta temperatura. Se trata de una inteligencia primitiva que puede ser controlada con implantes o por seres con poderes telepáticos. Esta criatura acompaña a la raza \\\"Muton\\\".\"\n  STR_SILACOID_AUTOPSY: \"Autopsia de Silacoide\"\n  STR_SILACOID_AUTOPSY_UFOPEDIA: \"El interior de esta criatura es muy caliente, lo que parece ser la base de su sistema digestivo. El Silacido tiene un sistema muscular unico que le permite ser extremadamente fuerte y rápido. Su piel, dura como la piedra, no se ve afectada por la munición incendiaria ni por el fuego.\"\n  STR_CHRYSSALID_UFOPEDIA: \"Las tenazas de esta criatura son un arma poderosa en el combate cuerpo a cuerpo. Su avanzado metabolismo y gran fuerza proporcionan gran velocidad y destreza. No obstante en vez de matar a su víctima la impregna un huevo y le inyecta una toxina que la convierte en un zombi. Poco después de que la víctima ha sido infectada una nueva *Crisálido* surgirá de ella. Las crisálidas están asociadas con la raza de los hombres-serpiente.\"\n  STR_CHRYSSALID_AUTOPSY: \"Autopsia de Crisálido\"\n  STR_CHRYSSALID_AUTOPSY_UFOPEDIA: \"El dermatoesqueleto de esta criatura es muy duro pero sorprendentemente vulnerable a la munición explosiva. El cerebro está muy desarrollado al igual que el ritmo de crecimiento de sus células. Esta criatura lleva veinte huevos, que deposita en otros organismos y constituye un elemento muy eficaz para aterrorizar a la población.\"\n  STR_FLOATER_UFOPEDIA: \"Los flotadores son soldados usados para sembrar el pánico entre los ciudadanos. Son bestias depredadoras por naturaleza, mejorados cibernética y genéticamente para convertirlos en guerreros formidables. Se les ha extirpado la parte inferior del cuerpo y la mayoría de los órganos internos, reemplazandolos con un sistema artifical de soporte vital. Este implante contiene una unidad antigravitatoria la cual permite que la criatura flote, aunque de forma inestable.\"\n  STR_FLOATER_AUTOPSY: \"Autopsia de Flotador\"\n  STR_FLOATER_AUTOPSY_UFOPEDIA: \"Esta criatura ha sido alterada drásticamente por medios quirúrgicos. El aparato que parece formar el núcleo de su cuerpo es un sistema de soporte vital que reemplaza al corazón, pulmones y aparato digestivo. Dicho aparato permite a la criatura sobrevivir en entornos extremadamente hostiles. El cerebro es más pequeño que el nuestro, pero sus órganos sensoriales están muy desarrollados.\"\n  STR_REAPER_UFOPEDIA: \"Este carnívoro bípedo tiene unas mandíbulas poderosas y un apetito voraz. Tiene varios implantes cerebrales que sirven para controlar sus actividades. Los instintos depredadores de esta criatura son de poca utilidad, excepto para aterrorizar y destruir. Los Devorador suelen asociarse con los Flotadores.\"\n  STR_REAPER_AUTOPSY: \"Autopsia de Devorador\"\n  STR_REAPER_AUTOPSY_UFOPEDIA: \"El Devorador tiene dos cerebros y dos corazones, los cuales le permiten seguir moviéndose incluso cuando está gravemente herido. Sin embargo, su piel peluda es altamente inflamable, por lo que esta criatura es vulnerable a las armas incendiarias.\"\n  STR_SECTOPOD_UFOPEDIA: \"Los Sectopodos son robots equipados con una poderosa arma de rayo laser. El control de estas bestias mecánicas se realiza mediante un vinculo telepático con sus controladores: los Etereos. Los sectopodos son el arma de terror mas poderosa disponible para las fuerzas alienígenas.\"\n  STR_SECTOPOD_AUTOPSY: \"Examen de Sectópodo\"\n  STR_SECTOPOD_AUTOPSY_UFOPEDIA: \"El robot esta sólidamente construido con un blindaje reforzado capaz de resistir la mayoría de formas de ataque, sobretodo las armas de plasma. No obstante sus circuitos sensores parecen ser particularmente vulnerables a las armas láser.\"\n  STR_CYBERDISC_UFOPEDIA: \"Este disco cibernetico es una replicate a escala del tipico platillo volador, está equipado con un potente rayo de plasma y es usado para aterrorizar a la población. Su propulsión antigravitatoria le da una gran ventaja en terrenos difíciles. Su función principal es la destrucción y aterrorizar al servicio de los sectoides.\"\n  STR_CYBERDISC_AUTOPSY: \"Examen de Ciberdisco\"\n  STR_CYBERDISC_AUTOPSY_UFOPEDIA: \"Los discos cibernetico tienen un blindaje muy bueno, especialmente resistente a los ataques con munición explosiva. El sistema de antigravedad de este ejemplar está demasiado dañado como para averiguar su funcionamiento.\"\n  STR_UFO_POWER_SOURCE_UFOPEDIA: \"La planta de energia de las naves alienígenas consiste en un reactor de antimateria que utiliza elerio (elemento 115) para crear poderosas ondas gravitatorias así como otras formas de energía. La conversión de materia a energía tiene una eficacia del 99%, gracias a lo cual pequeñas cantidades de elerio producen cantidades enormes de energía. Este reactor se puede reproducir fácilmente usando aleaciones alienígenas.\"\n  STR_UFO_NAVIGATION_UFOPEDIA: \"Las naves alienígenas utilizan sofisticadas computadoras para navegar por la Tierra y por el espacio. El sistema está basado en procesadores ópticos que se distribuyen formando una red. El interfaz de control es relativamente sencilla: el Navegante controla la dirección de las ondas de gravedad generadas por la planta de energía para mover la nave en cualquier dirección. Los humanos pueden utilizar fácilmente este sistema, y se puede reproducir utilizando aleaciones alienígenas y otros elementos.\"\n  STR_UFO_CONSTRUCTION_UFOPEDIA: \"Las naves alienígenas constan de tres elementos principales: un reactor, un sistema de navegación y un casco hecho de aleaciones alienígenas. El casco está especialmente diseñado para permitir que las ondas de gravedad sean dirigidas y controladas. También necesita una pequeña cantidad de elerio para alimentar el reactor. Una vez que comprendamos los principios de su construcción y conoscamos las funciones de cada componente, podremos construir este tipo de naves.\"\n  STR_ALIEN_FOOD_UFOPEDIA: \"Estas cámaras contienen varias enzimas que sirven para digerir las partes del cuerpo del ganado, otros animales e incluso humanos. El líquido resultante es consumido como alimento ya digerido, probablemente de forma intravenosa. Esto sugiere una cierta dependencia de la Tierra para su alimentación: una simbiosis entre la Tierra y la sociedad alienígena.\"\n  STR_ALIEN_REPRODUCTION_UFOPEDIA: \"Estas cámaras contienen fetos alienígenas. El diseño de estos recipientes sugiere que los alienígenas que utilizan este proceso dependen totalmente de la reproducción en laboratorio. Los nutrientes aseguran el rápido desarrollo de los fetos. Este sistema de producción en cadena podría generar miles de clones alienigenas en corto plazo. El proceso podría ser adoptado fácilmente para la reproducción de humanos o de híbridos humano-alienígena.\"\n  STR_ALIEN_ENTERTAINMENT_UFOPEDIA: \"Despues de estudiar este aparato hemos determinado que lo más probable es que estas esferas tengan una función recreativa. El circuito psíquico estimula varios centros nerviosos del cerebro. El efecto es parecido al de los alucinógenos. Es la única prueba de que los alienígenas tienen pasatiempos culturales o recreativos. \"\n  STR_ALIEN_SURGERY_UFOPEDIA: \"Este equipo quirúrgico utiliza rayos láser para cortar y extraer ciertas partes del cuerpo del ganado y otros animales. La famosa mutilación de ganado se debe a esta extraña actividad alienígena. Es probable que estas partes se utilicen para fines alimenticios o genéticos.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"En el pasado miles de personas declararon haber sido secuestradas por alienígenas; algunas repetidamente. La verdad es mucho más horrible. Los humanos son abducidos para ser objeto de investigaciones y observaciones. A los mejores especímenes se les extrae material genético. A las mujeres las implregnan con fetos híbridos humano-alienígena y los extraen varios meses después. Quién sabe cuál es su siniestro propósito.\"\n  STR_ALIEN_ALLOYS_UFOPEDIA: \"Las naves alienígenas están hechas de aleaciones especiales con propiedades únicas. Son muy ligeras y resistentes, y son maleables por medios electromagnéticos. Este material se puede reproducir y utilizar en muchos procesos de fabricación.\"\n  STR_ELERIUM_115_UFOPEDIA: \"Este elemento tiene la propiedad poco común de generar energía antimateria cuando es bombardeado con ciertas partículas, lo cual genera ondas gravitatorias y otras formas de energía. No se lo encuentra naturalmente en nuestro sistema solar y no puede ser reproducido.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"Está claro que estamos luchando una batalla perdida en la Tierra. Las hordas alienígenas nos superan en número. Lo mejor que podemos hacer es retrasar su avance. La única esperanza para la humanidad es atacar a los alienígenas en su origen. Nuestra investigación indica la existencia de una base de operaciones dentro de nuestro sistema solar. Los alienígenas afirman que este lugar es el centro de una civilización que precede a la existencia humana. Tenemos que descubrir ese sitio lo antes posible. Pero antes debemos de capturar e interrogar a un lider alienígena para conseguir información detallada. Seguramente en los ovnis grandes debe haber, al menos, un lider alienigena.\"\n  STR_THE_MARTIAN_SOLUTION_UFOPEDIA: \"Nuestra investigación apunta ahora a Marte como base de operaciones alienígenas. La base está bien escondida y contiene todas las instalaciones de fabricación y clonación necesarias para la infiltración en la Tierra. También parece haber una computadora de control que dirige toda la operación. Parece ser que en la sociedad tipo colmena de los alienígenas hay una especie de \\\"abeja reina\\\". Esa es su mayor debilidad: si eliminamos el \\\"cerebro\\\", el cuerpo morirá. Hay que acelerar nuestros esfuerzos antes de que sea demasiado tarde. Para progresar tenemos que capturar a alienígenas de alto rango - los comandantes - que sólo residen en bases y acorazados. \"\n  STR_CYDONIA_OR_BUST_UFOPEDIA: \"Ahora está claro que las hordas alienígenas son controladas desde una base subterránea en Cydonia - una zona curiosa de Marte en la que hay pirámides de cinco lados y una estructura enorme similar a una cara humana. La civilización de Cydonia floreció en Marte hace muchos millones de años, pero no sabemos por qué desapareció o qué conexión tiene con la reciente actividad alienígena. Cualquiera que sea la explicación, tenemos que mandar una expedición a Cydonia, esta es la única forma de derrotar a los alienígenas. Tenemos que destruir su 'cerebro' dirigente. Necesitaremos una nave Avenger equipada con las mejores armas destructivas de que dispongamos. No hay nada más que podamos averiguar, sólo queda esperar el resultado del asalto en Cydonia.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"CENTRAR EN SITIO - TIEMPO = 5 Seg\"\n  STR_CANCEL_UC: \"CANCELAR\"\n  STR_NONE: \"Ninguno\"\n  STR_UNKNOWN: \"Desconocido\"\n  STR_POOR: \"Pobre\"\n  STR_AVERAGE: \"Normal\"\n  STR_GOOD: \"Bueno\"\n  STR_EXCELLENT: \"Excelente\"\n  STR_BUILD_NEW_BASE_UC: \"NUEVA BASE\"\n  STR_BASE_INFORMATION: \"INFORMACIÓN DE BASE\"\n  STR_EQUIP_CRAFT: \"ABASTECER NAVES\"\n  STR_BUILD_FACILITIES: \"CONSTRUIR INSTALACIONES\"\n  STR_RESEARCH: \"INVESTIGAR\"\n  STR_MANUFACTURE: \"MANOFACTURAR\"\n  STR_TRANSFER_UC: \"TRANSFERIR\"\n  STR_PURCHASE_RECRUIT: \"COMPRAR/RECLUTAR\"\n  STR_SACK: \"DESPEDIR\"\n  STR_SELL_SACK_UC: \"VENDER/DESPEDIR\"\n  STR_GEOSCAPE_UC: \"GEOESCAPE\"\n  STR_NAME: \"Nombre\"\n  STR_AREA: \"Zona\"\n  STR_BUILD_NEW_BASE: \"Construir Nueva Base\"\n  STR_CANCEL: \"Cancelar\"\n  STR_COST_UC: \"COSTO> \"\n  STR_CONSTRUCTION_TIME_UC: \"TIEMPO DE CONSTRUCCIÓN> \"\n  STR_DAY:\n    one: \"{N} día\"\n    many: \"{N} días\"\n    other: \"{N} días\"\n  STR_HOUR:\n    one: \"{N} hora\"\n    many: \"{N} horas\"\n    other: \"{N} horas\"\n  STR_MAINTENANCE_UC: \"MANTENIMIENTO> \"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Instalación\"\n  STR_CURRENT_RESEARCH: \"INVESTIGACIÓN ACTUAL\"\n  STR_SCIENTISTS_AVAILABLE: \"Científicos Disponibles>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Científicos Asignados>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Espacio de Laboratorio Disponible>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"PROYECTO\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"CIENTÍFICOS ASIGNADOS\"\n  STR_PROGRESS: \"PROGRESO\"\n  STR_NEW_PROJECT: \"Nuevo Proyecto\"\n  STR_CANCEL_PROJECT: \"CANCELAR PROYECTO\"\n  STR_NEW_RESEARCH_PROJECTS: \"NUEVOS PROYECTOS DE INVESTIGACIÓN\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"CIENTÍFICOS DISPONIBLES>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"ESPACIO DE LABORATORIO DISPONIBLE>{ALT}{0}\"\n  STR_INCREASE: \"Aumentar\"\n  STR_DECREASE: \"Disminuir\"\n  STR_START_PROJECT: \"INICIAR PROYECTO\"\n  STR_CURRENT_PRODUCTION: \"PRODUCCIÓN ACTUAL\"\n  STR_ENGINEERS_AVAILABLE: \"Ingenieros Disponibles>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Ingenieros Asignados>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Espacio de Taller Disponible>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Fondos Actuales>{ALT}{0}\"\n  STR_ITEM: \"ARTÍCULO\"\n  STR_ENGINEERS__ALLOCATED: \"Ingenieros Asignados\"\n  STR_UNITS_PRODUCED: \"Unidades Producidas\"\n  STR_TOTAL_TO_PRODUCE: \"Total a Producir\"\n  STR_COST__PER__UNIT: \"Costo{NEWLINE}p/U\"\n  STR_DAYS_HOURS_LEFT: \"Dias/Horas Restantes\"\n  STR_NEW_PRODUCTION: \"Nueva Producción\"\n  STR_PRODUCTION_ITEMS: \"Artículos Disponibles\"\n  STR_CATEGORY: \"CATEGORÍA\"\n  STR_START_PRODUCTION: \"INICIAR PRODUCCIÓN\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} Horas para producir una unidad\"\n  STR_COST_PER_UNIT_: \"Costo por unidad>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Espacio de trabajo requerido>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"MATERIALES REQUERIDOS\"\n  STR_ITEM_REQUIRED: \"ARTÍCULOS NECESARIOS\"\n  STR_UNITS_REQUIRED: \"UNIDADES REQUERIDAS\"\n  STR_UNITS_AVAILABLE: \"UNIDADES DISPONIBLES\"\n  STR_STOP_PRODUCTION: \"DETENER PRODUCCIÓN\"\n  STR_ENGINEERS_AVAILABLE_UC: \"INGENIEROS DISPONIBLES>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"ESPACIO DE TALLER DISPONIBLE>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"UTILIDAD MENSUAL>{ALT}{0}\"\n  STR_INCREASE_UC: \"INCREMENTAR\"\n  STR_DECREASE_UC: \"DISMINUIR\"\n  STR_UNITS_TO_PRODUCE: \"Unidades a Producir\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Comprar/Contratar Personal\"\n  STR_COST_OF_PURCHASES: \"Costo>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"COSTO P/U\"\n  STR_QUANTITY_UC: \"CANTIDAD\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"DISPONIBLE : TOTAL> \"\n  STR_SOLDIERS: \"Soldados\"\n  STR_SCIENTISTS: \"Científicos\"\n  STR_ENGINEERS: \"Ingenieros\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"OCUPADO : DISPONIBLE> \"\n  STR_LIVING_QUARTERS: \"Viviendas\"\n  STR_STORES: \"Almacenes\"\n  STR_LABORATORIES: \"Laboratorios\"\n  STR_WORK_SHOPS: \"Talleres\"\n  STR_HANGARS: \"Hangares\"\n  STR_SHORT_RANGE_DETECTION: \"Radar de Corto Alcanze\"\n  STR_DEFENSE_STRENGTH: \"Fuerza Defensiva\"\n  STR_TRANSFERS_UC: \"TRANSFERENCIAS\"\n  STR_TRANSFERS: \"Transferencias\"\n  STR_ARRIVAL_TIME_HOURS: \"Tiempo De Llegada (horas)\"\n  STR_COST_: \"Costo>{ALT}{0}\"\n  STR_AREA_: \"Zona>{ALT}{0}\"\n  STR_BASE_NAME: \"¿Nombre de la Base?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"SELECCIONE UBICACIÓN DEL ASCENSOR DE ACCESO\"\n  STR_TRANSFER: \"Transferir\"\n  STR_AMOUNT_TO_TRANSFER: \"CANTIDAD PARA TRANSFERIR\"\n  STR_SELECT_DESTINATION_BASE: \"Seleccione Destino\"\n  STR_COST: \"Costo\"\n  STR_VICTORY_1: \"Al entrar en la cámara se puede ver al cerebro alienígena: el objeto de su búsqueda. Antes de dispararle, se comunica con usted mediante una pantalla que hay en su base. Le implora que antes de apretar el gatillo escuches las razones por las que deberías dejarle vivir.\"\n  STR_VICTORY_2: \"El cerebro dice: \\\"Hace millones de años el planeta al que llama Marte tenia vida. Nuestra civilización trajo vida a un planeta estéril al igual que la llevó al tuyo. Durante millones de años hemos visitado su planeta y desarrollado genéticamente su especie. No puedes matarnos, son parte de nosotros...\"\n  STR_VICTORY_3: \"Este es el centro de la civilización marciana. Estas pirámides fueron levantadas millones de años antes que las sullas por una especie de la que ustedes procendén. Ningún planeta está fuera de nuestro alcance. Este poder podría ser sullo dentro de poco, todo lo que pedimos es su cooperación.\"\n  STR_GAME_OVER_1: \"Los alienígenas intentan exterminar a la humanidad destruyendo las ciudades y envenenando el aire y el mar. La resistencia de los ejércitos de la Tierra es inútil frente a su enorme superioridad tecnológica. Las generaciones que sobreviven sufren terribles mutaciones mientras intentan escapar de la destrucción alienígena,son encerradas en campos de esclavos para que ayuden a transformar la Tierra en una colonia alienígena que forma parte de algun imperio desconocido.\"\n  STR_GAME_OVER_2: \"Los conocimientos adquiridos durante el proyecto X-Com se han perdido para siempre. Ha fracasado en su intento por salvar la Tierra.\"\n  STR_VICTORY_4: \"El cerebro alienígena es interrumpido por una ráfaga de plasma caliente y la totalidad de las fuerzas alienígenas es derrotada.\"\n  STR_VICTORY_5: \"Una vez que los alienígenas pierden Marte, pierden también la Tierra. El proyecto de investigación X-Com no tarda mucho en hacer posible una vez más el florecimiento de la humanidad, y ésta asume el control de Marte. La amenaza alienígena ha desaparecido, pero ¿por cuánto tiempo? Nadie lo sabe...\"\n  STR_YOU_HAVE_FAILED: \"Ha fracasado en su misión de detener la acometida alienígena. Las naciones patrocinadoras, una tras otra, firman pactos con los alienígenas en los que éstos les prometen tecnología, prosperidad y paz. Sin embargo pronto se dan cuenta de que los invasores tienen planes muy diferentes...\"\n  STR_TOTAL_UC: \"TOTAL\"\n  STR_INCOME: \"Ingresos \"\n  STR_EXPENDITURE: \"Gastos\"\n  STR_MAINTENANCE: \"Mantenimiento\"\n  STR_BALANCE: \"Saldo\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"Actividad OVNI en Zonas\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"Actividad OVNI en Países\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"Actividad X-Com en Zonas\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"Actividad X-Com en Países\"\n  STR_FINANCE: \"Finanzas\"\n  STR_DATE_FIRST: \"{0}º\"\n  STR_DATE_SECOND: \"{0}º\"\n  STR_DATE_THIRD: \"{0}.º\"\n  STR_DATE_FOURTH: \"{0}.º\"\n  STR_FINANCE_THOUSANDS: \"$1000's\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Insuficientes materiales para producir{NEWLINE}{0}{NEWLINE}at{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Insuficiente dinero para producir{NEWLINE}{0}{NEWLINE}en{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"Producción de{NEWLINE}{0}{NEWLINE}en{NEWLINE}{1}{NEWLINE}ha terminado\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"Construcción de{NEWLINE}{0}{NEWLINE}en{NEWLINE}{1}{NEWLINE}finalizada\"\n  STR_OK_5_SECONDS: \"OK - 5 seg\"\n  STR_RESEARCH_COMPLETED: \"Investigación Finalizada\"\n  STR_VIEW_REPORTS: \"VER INFORMES\"\n  STR_WE_CAN_NOW_RESEARCH: \"Podemos investigar\"\n  STR_WE_CAN_NOW_PRODUCE: \"Podemos fabricar\"\n  STR_SUNDAY: \"DOMINGO\"\n  STR_MONDAY: \"LUNES\"\n  STR_TUESDAY: \"MARTES\"\n  STR_WEDNESDAY: \"MIÉRCOLES\"\n  STR_THURSDAY: \"JUEVES\"\n  STR_FRIDAY: \"VIERNES\"\n  STR_SATURDAY: \"SÁBADO\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Insuficiente {0} para repostar {1} en {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Insuficientes {0} para rearmar {1} en {2}\"\n  STR_UFO_IS_NOT_RECOVERED: \"OVNI no fue recuperado\"\n  STR_UFO_IS_RECOVERED: \"OVNI recuperado\"\n  STR_CRAFT_IS_LOST: \"Nave destruida\"\n  STR_TERROR_CONTINUES: \"La Incursión continúa\"\n  STR_ALIENS_DEFEATED: \"Alienígenas derrotados\"\n  STR_BASE_IS_LOST: \"Se ha perdido la base\"\n  STR_BASE_IS_SAVED: \"Hemos defendido la base\"\n  STR_ALIEN_BASE_STILL_INTACT: \"Base Alienígena intacta\"\n  STR_ALIEN_BASE_DESTROYED: \"Base Alienígena destruida\"\n  STR_ALIENS_KILLED: \"BAJAS ALIENÍGENAS\"\n  STR_ALIEN_CORPSES_RECOVERED: \"CADÁVERES ALIENÍGENAS RECUPERADOS\"\n  STR_LIVE_ALIENS_RECOVERED: \"ALIENÍGENAS VIVOS CAPTURADOS\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"ARTEFACTOS ALIENÍGENAS RECUPERADOS\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"CONTROL DE LA BASE ALIENÍGENA DESTRUIDO\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"BAJAS CIVILES CAUSADAS POR LOS ALIENÍGENAS\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"BAJAS CIVILES CAUSADAS POR X-COM\"\n  STR_CIVILIANS_SAVED: \"CIVILES RESCATADOS\"\n  STR_XCOM_OPERATIVES_KILLED: \"BAJAS X-COM\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"OPERATIVOS X-COM DESAPARECIDOS EN COMBATE\"\n  STR_TANKS_DESTROYED: \"TANQUES DESTRUIDOS\"\n  STR_XCOM_CRAFT_LOST: \"NAVE X-COM DESTRUIDA\"\n  STR_UFO_RECOVERY: \"RECUPERACIÓN DE OVNI\"\n  STR_ALIEN_BASE_RECOVERY: \"RECUPERACIÓN DE BASE ALIENÍGENA\"\n  STR_BASE_UNDER_ATTACK: \"¡{0} bajo ataque!\"\n  STR_BASE_DEFENSES_INITIATED: \"DEFENSA DE LA BASE INICIADA\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"¡ESCUDO DE GRAV. REPELE OVNI!\"\n  STR_FIRING: \"DISPARANDO\"\n  STR_HIT: \"¡IMPACTO!\"\n  STR_UFO_DESTROYED: \"¡OVNI DESTRUIDO!\"\n  STR_MISSED: \"¡DISPARO FALLÓ!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Vender/Despedir \"\n  STR_VALUE_OF_SALES: \"VALOR DE VENTAS> {ALT}{0}\"\n  STR_FUNDS: \"FONDOS> {ALT}{0}\"\n  STR_SELL_SACK: \"Vender/Despedir\"\n  STR_VALUE: \"Valor\"\n  STR_CRAFT_: \"NAVE> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"RECUPERACIÓN DE OVNI DERRIBADO\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"Extreme la precaución - Es posible que haya operativos en el OVNI o alrededor del lugar del accidente. La Misión tendrá éxito cuando todas las unidades enemigas hayan sido eliminadas o neutralizadas. La recuperación de restos del OVNI, artefactos y cadáveres alienígenas puede entonces ser iniciada. Para abortar la misión regrese los operativos X-Com al vehículo de transporte y haga clic en el icono 'Abortar Misión'.\"\n  STR_UFO_GROUND_ASSAULT: \"ASALTO A OVNI ATERRIZADO\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"Explore el punto de amerizaje y, si es posible, gane acceso al OVNI. Esta misión se completará cuando todas las unidades enemigas hayan sido eliminadas o neutralizadas. La recuperación de restos OVNI, tecnología y cadáveres alienígenas podrá entonces ser iniciada. Para abortar la misión regrese los operativos X-Com al vehículo de transporte y haga clic en el icono 'Abortar Misión'.\"\n  STR_BASE_DEFENSE: \"DEFENSA DE BASE\"\n  STR_BASE_UC_: \"BASE>{0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"Una nave alienígena ha aterrizado muy cerca. Nuestra base está en peligro. Según el procedimiento habitual, se ha evacuado todo el personal no combatiente y las naves de X-Com. Los alienígenas accederán a la base por las puertas del hangar o por el ascensor de acceso. Defienda la base y sus instalaciones vitales a toda costa, es una lucha a vida o muerte. Si presiona en el icono de 'Abortar misión' aceptará la derrota y perderá la base.\"\n  STR_ALIEN_BASE_ASSAULT: \"ASALTO A BASE ALIENÍGENA\"\n  STR_ALIEN_BASE_ASSAULT_BRIEFING: \"Los operativos X-COM han entrado en una base alienígena. Hay que destruir el centro de control para que la base quede inservible. El objetivo de la misión estara completo cuando elimine a todos los enemigos o cuando regrese sus hombres al área verde de salida (presione el icono de 'Abortar misión' para escapar).\"\n  STR_CYDONIA_BRIEFING: \"Ha llegado a Cydonia. Entra en un gran complejo subterráneo cercano a la Esfinge Marciana. Tienes que destruir al cerebro alienígena que controla todas las actividades alienígenas. El destino de la humanidad está en sus manos.\"\n  STR_TERROR_MISSION: \"MISIÓN DE INCURSIÓN\"\n  STR_TERROR_MISSION_BRIEFING: \"El objetivo de la misión es eliminar o neutralizar todas las unidades enemigas. Debe intentar salvar a cualquier civil que haya en el área. Para abortar la misión, regrese los operativos X-Com al vehículo de transporte y presione el icono de 'Abortar misión'.\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"¡NO HAY HANGARES LIBRES PARA CONSTRUIR NAVES!{SMALLLINE}Cada nave asignada o transferida a una base, comprada o construida ocupa un hangar. Construya un nuevo hangar o traslade una nave a otra base.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"¡NO HAY HANGARES LIBRES PARA COMPRAR NAVES!{SMALLLINE}Cada nave asignada o transferida a una base, comprada o construida ocupa un hangar. Construya un nuevo hangar o traslade una nave a otra base.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"¡NO HAY HANGARES LIBRES PARA TRASLADAR NAVES{SMALLLINE}Cada nave asignada o transferida a una base, comprada o construida ocupa un hangar. Construya un nuevo hangar o traslade una nave a otra base.\"\n  STR_CANNOT_BUILD_HERE: \"¡NO PUEDE CONSTRUIR AQUÍ!{SMALLLINE}Sólo junto a una instalación finalizada.\"\n  STR_NO_FREE_ACCOMODATION: \"¡NO HAY ESPACIO DISPONIBLE!{SMALLLINE}La base de destino no tiene espacio suficiente en las viviendas.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"¡NO HAY ESPACIO PARA TRABAJAR!{SMALLLINE}Construya un taller nuevo o redusca los técnicos de otros proyectos.\"\n  STR_NOT_ENOUGH_MONEY: \"¡NO HAY DINERO SUFICIENTE!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"¡NO HAY SUFICIENTE ESPACIO DE ALMACENAJE!{SMALLLINE}Construya un almacén nuevo o traslade artículos a otras bases.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"¡NO HAY SUFICIENTE ESPACIO HABITABLE!{SMALLLINE}Construya nuevas viviendas o traslade personal a otras bases.\"\n  STR_LAUNCH_INTERCEPTION: \"INICIAR INTERCEPCIÓN\"\n  STR_CRAFT: \"NAVE\"\n  STR_STATUS: \"SITUACIÓN\"\n  STR_BASE: \"BASE\"\n  STR_READY: \"LISTO\"\n  STR_OUT: \"FUERA\"\n  STR_REPAIRS: \"REPARACIONES\"\n  STR_REFUELLING: \"REPOSTANDO\"\n  STR_REARMING: \"REARMANDO\"\n  STR_TARGET: \"OBJETIVO: {0}\"\n  STR_WAY_POINT: \"DESTINO\"\n  STR_ARE_YOU_SURE_CYDONIA: \"¿Estás seguro de que quieres mandar esta nave a Cydonia en una misión?\"\n  STR_YES: \"SÍ\"\n  STR_NO: \"NO\"\n  STR_SELECT_DESTINATION: \"SELECCIONE DESTINO\"\n  STR_CYDONIA: \"CYDONIA\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"SELECCIONE UBICACIÓN DE LA{NEWLINE}NUEVA BASE\"\n  STR_RETURN_TO_BASE: \"REGRESAR A LA BASE\"\n  STR_SELECT_NEW_TARGET: \"SELECCIONE OTRO BLANCO\"\n  STR_PATROL: \"PATRULLAR\"\n  STR_STATUS_: \"SITUACIÓN>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"AVERIADO - REGRESANDO A LA BASE\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"POCO COMBUSTIBLE - REGRESANDO A LA BASE\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"MISIÓN COMPLETA - REGRESANDO A BASE\"\n  STR_PATROLLING: \"PATRULLANDO\"\n  STR_TAILING_UFO: \"SIGUIENDO A UN OVNI\"\n  STR_INTERCEPTING_UFO: \"INTERCEPTANDO OVNI-{0}\"\n  STR_RETURNING_TO_BASE: \"REGRESANDO A LA BASE\"\n  STR_DESTINATION_UC_: \"DESTINO: {0}\"\n  STR_BASE_UC: \"BASE>{ALT}{0}\"\n  STR_SPEED_: \"VELOCIDAD>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"VELOCIDAD MÁXIMA>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"ALTITUD>{ALT}{0}\"\n  STR_VERY_LOW: \"MUY BAJA\"\n  STR_LOW_UC: \"BAJA\"\n  STR_HIGH_UC: \"ALTA\"\n  STR_VERY_HIGH: \"MUY ALTA\"\n  STR_FUEL: \"COMBUSTIBLE>{ALT}{0}\"\n  STR_WEAPON_ONE: \"ARMA-1>{ALT}{0}\"\n  STR_NONE_UC: \"NINGUNA\"\n  STR_ROUNDS_: \"BALAS>{ALT}{0}\"\n  STR_WEAPON_TWO: \"ARMA-2>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"NAVE  DE CAZA\"\n  STR_BASE_: \"Base>{0}\"\n  STR_NAME_UC: \"NOMBRE\"\n  STR_AMMO_: \"MUNICIÓN>{ALT}{0}\"\n  STR_CREW: \"TRIPULACIÓN\"\n  STR_EQUIPMENT_UC: \"ARMAMENTO\"\n  STR_ARMOR: \"ARMADURA\"\n  STR_MAX: \"MAX>{ALT}{0}\"\n  STR_ROOKIE: \"Recluta\"\n  STR_SQUADDIE: \"Soldado raso\"\n  STR_SERGEANT: \"Sargento\"\n  STR_CAPTAIN: \"Capitán\"\n  STR_COLONEL: \"Coronel\"\n  STR_COMMANDER: \"Comandante\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Elija el escuadrón para {0}\"\n  STR_SORT_BY: \"ORDENAR POR...\"\n  STR_ORIGINAL_ORDER: \"ORDEN ORIGINAL\"\n  STR_MISSIONS2: \"MISIÓNES\"\n  STR_KILLS2: \"MUERTES\"\n  STR_WOUND_RECOVERY2: \"RECUPERACIÓN DE HERIDA\"\n  STR_SPACE_AVAILABLE: \"ESPACIO DISPONIBLE>{ALT}{0}\"\n  STR_SPACE_USED: \"ESPACIO USADO>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"ESPACIO USADO\"\n  STR_RANK: \"RANGO\"\n  STR_WOUNDED: \"HERIDO\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Equipo para {0}\"\n  STR_DEFENSE_VALUE: \"Valor defensivo\"\n  STR_HIT_RATIO: \"Proporción\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}listo para{NEWLINE}aterrizar cerca de{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"¿Iniciar la misión?\"\n  STR_SELECT_ARMAMENT: \"Seleccione Armamento\"\n  STR_AMMUNITION_AVAILABLE: \"MUNICIÓN DISPONIBLE\"\n  STR_ARMAMENT: \"ARMAMENTO\"\n  STR_NOT_AVAILABLE: \"N.D.\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"SELECCIONAR ARMADURA PARA{NEWLINE}{0}\"\n  STR_TYPE: \"TIPO\"\n  STR_PERSONAL_ARMOR_UC: \"ARMADURA PERSONAL\"\n  STR_POWER_SUIT_UC: \"ARMADURA MECÁNICA\"\n  STR_FLYING_SUIT_UC: \"ARMADURA VOLADORA\"\n  STR_SELECT_ARMOR: \"Seleccione Armadura\"\n  STR_NORTH: \"NORTE\"\n  STR_NORTH_EAST: \"NORESTE\"\n  STR_EAST: \"ESTE\"\n  STR_SOUTH_EAST: \"SURESTE\"\n  STR_SOUTH: \"SUR\"\n  STR_SOUTH_WEST: \"SUROESTE\"\n  STR_WEST: \"OESTE\"\n  STR_NORTH_WEST: \"NOROESTE\"\n  STR_SELECT_ACTION: \"SELECCIONE ACCIÓN\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"CONTINUAR PERSECUCIÓN\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"PERSECUCIÓN SIN INTERCEPCIÓN\"\n  STR_VERY_LARGE: \"MUY GRANDE\"\n  STR_LARGE: \"GRANDE\"\n  STR_MEDIUM_UC: \"NORMAL\"\n  STR_SMALL: \"PEQUEÑO\"\n  STR_VERY_SMALL: \"MUY PEQUEÑO\"\n  STR_GROUNDED: \"DERRIBADO\"\n  STR_DETECTED: \"Detectado\"\n  STR_SIZE_UC: \"TAMAÑO\"\n  STR_ALTITUDE: \"ALTITUD\"\n  STR_HEADING: \"RUMBO\"\n  STR_SPEED: \"VELOCIDAD\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"CENTRAR EN OVNI - TIEMPO = 5 Seg\"\n  STR_TRACKING_LOST: \"RASTRO PERDIDO\"\n  STR_REDIRECT_CRAFT: \"CAMBIAR RUMBO\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"IR A ÚLTIMA POSICIÓN CONOCIDA DEL OVNI \"\n  STR_UFO_: \"OVNI-{0}\"\n  STR_ALIEN_BASE_: \"BASE ALIENÍGENA-{0}\"\n  STR_CRASH_SITE_: \"SITIO DE CHOQUE-{0}\"\n  STR_LANDING_SITE_: \"SITIO DE ATERRIZAJE-{0}\"\n  STR_WAY_POINT_: \"DESTINO-{0}\"\n  STR_TERROR_SITE: \"LUGAR DE INCURSIÓN-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}ha llegado a{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"Está patrullando\"\n  STR_ALIEN_ORIGINS: \"Origen de los Alienígenas\"\n  STR_THE_MARTIAN_SOLUTION: \"La Solución Marciana\"\n  STR_CYDONIA_OR_BUST: \"Cydonia o reventar!\"\n  STR_UFOPAEDIA: \"Ovnipedia\"\n  STR_XCOM_CRAFT_ARMAMENT: \"NAVES Y ARMAS DE X-COM\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"PLATAFORMAS DE ARMAS PESADAS\"\n  STR_WEAPONS_AND_EQUIPMENT: \"EQUIPO Y ARMAS\"\n  STR_ALIEN_ARTIFACTS: \"ARTEFACTOS ALIENÍGENAS\"\n  STR_BASE_FACILITIES: \"INSTALACIONES DE LA BASE\"\n  STR_ALIEN_LIFE_FORMS: \"CRIATURAS ALIENÍGENAS\"\n  STR_ALIEN_RESEARCH_UC: \"INVESTIGACIÓN ALIENÍGENA\"\n  STR_UFO_COMPONENTS: \"COMPONENTES OVNI\"\n  STR_UFOS: \"OVNIs\"\n  STR_SELECT_ITEM: \"SELECCIONE ARTÍCULO\"\n  STR_ACCELERATION: \"ACELERACIÓN>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"CAPACIDAD DE COMBUSTIBLE>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"TORRE DE ARMAS>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"RESISTENCIA>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"ESPACIO DE CARGA>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"CAPACIDAD PAP>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Daño\"\n  STR_RANGE: \"Alcance\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Precisión\"\n  STR_RE_LOAD_TIME: \"Tiempo de recarga\"\n  STR_SECONDS: \"{0}s\"\n  STR_DAMAGE_ARMOR_PIERCING: \"PERFORANTE\"\n  STR_DAMAGE_INCENDIARY: \"INCENDIARIO\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"EXPLOSIVO\"\n  STR_DAMAGE_LASER_BEAM: \"RAYO LÁSER\"\n  STR_DAMAGE_PLASMA_BEAM: \"RAYO PLASMA\"\n  STR_DAMAGE_STUN: \"ATURDIR\"\n  STR_DAMAGE_MELEE: \"CUERPO A CUERPO\"\n  STR_DAMAGE_ACID: \"ÁCIDO\"\n  STR_DAMAGE_SMOKE: \"HUMO\"\n  STR_SHOT_TYPE: \"TIPO DE TIRO\"\n  STR_ACCURACY_UC: \"PUNTERÍA\"\n  STR_TIME_UNIT_COST: \"COSTO UT\"\n  STR_DAMAGE_UC: \"DAÑO\"\n  STR_AMMO: \"MUNICIÓN\"\n  STR_SHOT_TYPE_AUTO: \"Automático\"\n  STR_SHOT_TYPE_SNAP: \"Simple\"\n  STR_SHOT_TYPE_AIMED: \"Precisión\"\n  STR_CONSTRUCTION_TIME: \"Tiempo de construcción\"\n  STR_CONSTRUCTION_COST: \"Costo de construcción\"\n  STR_MAINTENANCE_COST: \"Costo de mantenimiento\"\n  STR_LOW: \"Bajo\"\n  STR_MEDIUM: \"Mediano\"\n  STR_HIGH: \"Pesado\"\n  STR_CRAFT_WEAPON: \"Arma de nave\"\n  STR_CRAFT_AMMUNITION: \"Munición de la nave\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Plataforma de Armas Pesadas\"\n  STR_WEAPON: \"Arma\"\n  STR_AMMUNITION: \"Munición\"\n  STR_EQUIPMENT: \"Equipo\"\n  STR_ALIEN_CORPSE: \"Cadáver Alienígena\"\n  STR_UFO_COMPONENT: \"Componente de OVNI\"\n  STR_PERSONAL_ARMOR: \"Armadura Personal\"\n  STR_RAW_MATERIALS: \"Materias Primas\"\n  STR_HWP_CANNON_SHELLS: \"Proyectiles de cañón PAP\"\n  STR_ALIEN: \"Alienígena\"\n  STR_SECTOID: \"Sectoide\"\n  STR_SNAKEMAN: \"Hombre-Serpiente\"\n  STR_ETHEREAL: \"Etéreo\"\n  STR_MUTON: \"Muton\"\n  STR_FLOATER: \"Flotador\"\n  STR_CELATID: \"Celátido\"\n  STR_SILACOID: \"Silacoide\"\n  STR_CHRYSSALID: \"Crisálida\"\n  STR_ZOMBIE: \"Zombi\"\n  STR_REAPER: \"Devorador\"\n  STR_SECTOPOD: \"Sectópodo\"\n  STR_CYBERDISC: \"Ciberdisco\"\n  STR_LIVE_COMMANDER: \"Comandante\"\n  STR_LIVE_LEADER: \"Líder\"\n  STR_LIVE_ENGINEER: \"Técnico\"\n  STR_LIVE_MEDIC: \"Médico\"\n  STR_LIVE_NAVIGATOR: \"Navegante\"\n  STR_LIVE_SOLDIER: \"Soldado\"\n  STR_LIVE_TERRORIST: \"Terrorista\"\n  STR_FLOATER_SOLDIER: \"Soldado Flotador\"\n  STR_FLOATER_NAVIGATOR: \"Navegante Flotador\"\n  STR_FLOATER_MEDIC: \"Médico Flotador\"\n  STR_FLOATER_ENGINEER: \"Técnico Flotador\"\n  STR_FLOATER_LEADER: \"Lider Flotador\"\n  STR_FLOATER_COMMANDER: \"Comandante Flotador\"\n  STR_SECTOID_SOLDIER: \"Soldado Sectoide\"\n  STR_SECTOID_NAVIGATOR: \"Navegante Sectoide\"\n  STR_SECTOID_MEDIC: \"Médico Sectoide\"\n  STR_SECTOID_ENGINEER: \"Técnico Sectoide\"\n  STR_SECTOID_LEADER: \"Lider Sectoide\"\n  STR_SECTOID_COMMANDER: \"Comandante Sectoide\"\n  STR_SNAKEMAN_SOLDIER: \"Soldado Hombre-Serpiente\"\n  STR_SNAKEMAN_NAVIGATOR: \"Navegante Hombre-Serpiente\"\n  STR_SNAKEMAN_ENGINEER: \"Técnico Hombre-Serpiente\"\n  STR_SNAKEMAN_LEADER: \"Lider Hombre-Serpiente\"\n  STR_SNAKEMAN_COMMANDER: \"Comandante Hombre-Serpiente\"\n  STR_MUTON_SOLDIER: \"Soldado Muton\"\n  STR_MUTON_NAVIGATOR: \"Navegador Mutante\"\n  STR_MUTON_ENGINEER: \"Técnico Muton\"\n  STR_ETHEREAL_SOLDIER: \"Soldado Etéreo\"\n  STR_ETHEREAL_LEADER: \"Lider Etéreo\"\n  STR_ETHEREAL_COMMANDER: \"Comandante Etéreo\"\n  STR_CYBERDISC_TERRORIST: \"Terrorista Ciberdisco\"\n  STR_REAPER_TERRORIST: \"Terrorista Devorador\"\n  STR_CHRYSSALID_TERRORIST: \"Terrorista Crisálida\"\n  STR_CELATID_TERRORIST: \"Terrorista Celátido\"\n  STR_SILACOID_TERRORIST: \"Terrorista Silacoide\"\n  STR_SECTOPOD_TERRORIST: \"Terrorista Sectópodo\"\n  STR_UFO_POWER_SOURCE: \"Reactor de OVNI\"\n  STR_UFO_NAVIGATION: \"Navegación de OVNI\"\n  STR_UFO_CONSTRUCTION: \"Construcción de OVNI\"\n  STR_ALIEN_FOOD: \"Comida Alienígena\"\n  STR_ALIEN_REPRODUCTION: \"Reproducción Alienígena\"\n  STR_ALIEN_ENTERTAINMENT: \"Diversión Alienígena\"\n  STR_ALIEN_SURGERY: \"Cirugía Alienígena\"\n  STR_EXAMINATION_ROOM: \"Sala de Exámenes\"\n  STR_ALIEN_ALLOYS: \"Aleaciones Alienígenas\"\n  STR_ALIEN_HABITAT: \"Hábitat Alienígena\"\n  STR_POWER_SUIT: \"Armadura Mecánica\"\n  STR_FLYING_SUIT: \"Armadura Voladora\"\n  STR_HWP_ROCKETS: \"Cohetes PAP\"\n  STR_HWP_FUSION_BOMB: \"Bombas de Fusión PAP\"\n  STR_LASER_WEAPONS: \"Armas de Rayos Láser\"\n  STR_NEW_FIGHTER_CRAFT: \"Nueva Nave Caza\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Nuevo Caza-Transporte\"\n  STR_ULTIMATE_CRAFT: \"La Última Nave\"\n  STR_LASER_PISTOL: \"Pistola Láser\"\n  STR_LASER_RIFLE: \"Fusil Láser\"\n  STR_HEAVY_LASER: \"Láser Avanzado\"\n  STR_LASER_CANNON: \"Cañón Láser\"\n  STR_PLASMA_CANNON: \"Cañón de Plasma\"\n  STR_FUSION_MISSILE: \"Misil de Fusión\"\n  STR_LASER_DEFENSE: \"Defensas Láser\"\n  STR_PLASMA_DEFENSE: \"Defensas de Plasma\"\n  STR_FUSION_DEFENSE: \"Defensas de Fusión\"\n  STR_GRAV_SHIELD: \"Escudo de Gravedad\"\n  STR_MIND_SHIELD: \"Escudo Mental\"\n  STR_PSI_LAB: \"Laboratorio Psíquico\"\n  STR_MOTION_SCANNER: \"Escáner de Movimiento\"\n  STR_MEDI_KIT: \"Botiquín\"\n  STR_TANK_CANNON: \"Tanque/Cañón\"\n  STR_TANK_ROCKET_LAUNCHER: \"Tanque/Lanzacohetes\"\n  STR_TANK_LASER_CANNON: \"Tanque/Cañón Láser\"\n  STR_HOVERTANK_PLASMA: \"Tanque volador/Plasma\"\n  STR_HOVERTANK_LAUNCHER: \"Tanque volador/Lanzador\"\n  STR_STINGRAY_LAUNCHER: \"Lanzamisiles Stingray\"\n  STR_AVALANCHE_LAUNCHER: \"Lanzamisiles Avalancha\"\n  STR_CANNON: \"Cañón\"\n  STR_FUSION_BALL_LAUNCHER: \"Lanzador de Bolas de Fusión\"\n  STR_PLASMA_BEAM: \"Rayo de Plasma\"\n  STR_STINGRAY_MISSILES: \"Misil Stingray\"\n  STR_AVALANCHE_MISSILES: \"Misil Avalancha\"\n  STR_CANNON_ROUNDS_X50: \"Balas del Cañón(x50)\"\n  STR_FUSION_BALL: \"Bola de Fusión\"\n  STR_SOLDIER: \"Soldados\"\n  STR_SCIENTIST: \"Científico\"\n  STR_ENGINEER: \"Ingenieros\"\n  STR_NORTH_AMERICA: \"Norteamérica\"\n  STR_ARCTIC: \"Ártico\"\n  STR_ANTARCTICA: \"Antártida\"\n  STR_SOUTH_AMERICA: \"Sudamérica\"\n  STR_EUROPE: \"Europa\"\n  STR_NORTH_AFRICA: \"Norte de África\"\n  STR_SOUTHERN_AFRICA: \"Sur de África\"\n  STR_CENTRAL_ASIA: \"Asia Central\"\n  STR_SOUTH_EAST_ASIA: \"Sureste de Asia\"\n  STR_SIBERIA: \"Siberia\"\n  STR_AUSTRALASIA: \"Australia\"\n  STR_PACIFIC: \"Océano Pacífico\"\n  STR_NORTH_ATLANTIC: \"Atlántico Norte\"\n  STR_SOUTH_ATLANTIC: \"Atlántico Sur\"\n  STR_INDIAN_OCEAN: \"Océano Índico\"\n  STR_ALIEN_RESEARCH: \"Investigación Alienígena\"\n  STR_ALIEN_HARVEST: \"Cosecha Alienígena\"\n  STR_ALIEN_ABDUCTION: \"Abducción Alienígena\"\n  STR_ALIEN_INFILTRATION: \"Infiltración Alienígena\"\n  STR_ALIEN_BASE: \"Base Alienígena\"\n  STR_ALIEN_TERROR: \"Incursión Alienígena\"\n  STR_ALIEN_RETALIATION: \"Represalia Alienígena\"\n  STR_ALIEN_SUPPLY: \"Suministro Alienígena\"\n  STR_MAXIMUM_SPEED: \"Velocidad Máxima\"\n  STR_HYPER_WAVE_DECODER_UC: \"DESCODIFICADOR DE HIPERONDAS\"\n  STR_SKYRANGER: \"SKYRANGER\"\n  STR_LIGHTNING: \"LIGHTNING\"\n  STR_AVENGER: \"AVENGER\"\n  STR_INTERCEPTOR: \"INTERCEPTOR\"\n  STR_FIRESTORM: \"FIRESTORM\"\n  STR_UFO: \"OVNI\"\n  STR_STINGRAY: \"STINGRAY\"\n  STR_AVALANCHE: \"AVALANCHA\"\n  STR_CANNON_UC: \"CAÑÓN\"\n  STR_FUSION_BALL_UC: \"BOLA DE FUSIÓN\"\n  STR_LASER_CANNON_UC: \"CAÑÓN LÁSER\"\n  STR_PLASMA_BEAM_UC: \"RAYO PLASMA\"\n  STR_DAMAGE_CAPACITY: \"Resistencia\"\n  STR_WEAPON_POWER: \"Potencia del Arma\"\n  STR_WEAPON_RANGE: \"Alcance del Arma\"\n  STR_ACCESS_LIFT: \"Ascensor de Acceso\"\n  STR_LABORATORY: \"Laboratorio\"\n  STR_WORKSHOP: \"Taller\"\n  STR_SMALL_RADAR_SYSTEM: \"Radar de corto alcance\"\n  STR_LARGE_RADAR_SYSTEM: \"Radar de largo alcance\"\n  STR_MISSILE_DEFENSES: \"Defensas de Misiles\"\n  STR_GENERAL_STORES: \"Almacenes Generales\"\n  STR_ALIEN_CONTAINMENT: \"Confinamiento Alienígena\"\n  STR_LASER_DEFENSES: \"Defensas Láser\"\n  STR_PLASMA_DEFENSES: \"Defensas de Plasma\"\n  STR_FUSION_BALL_DEFENSES: \"Defensas de Bolas Fusión\"\n  STR_PSIONIC_LABORATORY: \"Laboratorio Psíquico\"\n  STR_HYPER_WAVE_DECODER: \"Decodificador de Hiperondas\"\n  STR_HANGAR: \"Hangar\"\n  STR_USA: \"EE.UU.\"\n  STR_RUSSIA: \"RUSIA\"\n  STR_UK: \"REINO UNIDO\"\n  STR_FRANCE: \"FRANCIA\"\n  STR_GERMANY: \"ALEMANIA\"\n  STR_ITALY: \"ITALIA\"\n  STR_SPAIN: \"ESPAÑA\"\n  STR_CHINA: \"CHINA\"\n  STR_JAPAN: \"JAPÓN\"\n  STR_INDIA: \"INDIA\"\n  STR_BRAZIL: \"BRASIL\"\n  STR_AUSTRALIA: \"AUSTRALIA\"\n  STR_NIGERIA: \"NIGERIA\"\n  STR_SOUTH_AFRICA: \"SUDÁFRICA\"\n  STR_EGYPT: \"EGIPTO\"\n  STR_CANADA: \"CANADÁ\"\n  STR_TANK: \"Tanque\"\n  STR_CIVILIAN: \"Civil\"\n  STR_JAN: \"Ene\"\n  STR_FEB: \"Feb\"\n  STR_MAR: \"Mar\"\n  STR_APR: \"Abr\"\n  STR_MAY: \"May\"\n  STR_JUN: \"Jun\"\n  STR_JUL: \"Jul\"\n  STR_AUG: \"Ago\"\n  STR_SEP: \"Sep\"\n  STR_OCT: \"Oct\"\n  STR_NOV: \"Nov\"\n  STR_DEC: \"Dic\"\n  STR_INTERNATIONAL_RELATIONS: \"Relaciones Internacionales\"\n  STR_COUNTRY: \"País\"\n  STR_FUNDING: \"Financiación\"\n  STR_CHANGE: \"Cambio\"\n  STR_WEAPON_SYSTEMS: \"SISTEMAS DE ARMAS\"\n  STR_HWPS: \"PAPs\"\n  STR_DAMAGE_UC_: \"DAÑO>{ALT}{0}\"\n  STR_ACCESS_LIFT_UFOPEDIA: \"El ascensor de acceso permite transportar equipo y personal dentro o fuera de una base subterránea. Es lo primero que se construya en un emplazamiento nuevo. El ascensor es vulnerable y puede ser invadido por cualquier fuerza hostil.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Cada zona de alojamiento puede albergar a 50 miembros del personal. Estos alojamientos constan de instalaciones básicas de descanso, alimentación y recreación.\"\n  STR_LABORATORY_UFOPEDIA: \"En un laboratorio pueden trabajar 50 científicos. Los laboratorios están equipados con las tecnologías más modernas para la investigación de materiales, bioquímica y cosmología. X-COM tiene acceso a los mejores laboratorios de investigación del mundo, tanto civiles como militares.\"\n  STR_WORKSHOP_UFOPEDIA: \"En un taller se puede encontrar todo lo necesario para fabricar productos a partir de diseños realizados en los laboratorios científicos. En un taller caben 50 técnicos, los objetos que se están fabricando también ocupan sitio.\"\n  STR_SMALL_RADAR_SYSTEM_UFOPEDIA: \"Un sistema de radar pequeño tiene un alcance efectivo de 300 millas náuticas y está conectado a sistemas de satélites para el análisis de la superficie. Cada radar tiene una probabilidad del 10% de detectar un objeto de tamaño medio cada 30 minutos.\"\n  STR_LARGE_RADAR_SYSTEM_UFOPEDIA: \"Un sistema de radar grande cubre una zona de más de 450 millas náuticas y está conectado a sistemas de satélites para el análisis de la superficie. Cada radar tiene una probabilidad del 20% de detectar un objeto de tamaño medio cada 30 minutos.\"\n  STR_MISSILE_DEFENSES_UFOPEDIA: \"Los sistemas de defensa basados en misiles proporcionan protección contra las incursiones de naves hostiles que intenten aterrizar en la base.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"Todo el equipo, armas, municiones, materiales recuperados y armas pesadas están situadas en almacenes, incluyendo equipo asignado a naves en el hangar.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"Es probable que los alienígenas capturados con vida necesiten un  hábitat especial para mantener sus sistemas vitales. En cada unidad de contención caben 10 alienígenas metidos en otras tantas unidades independientes.\"\n  STR_LASER_DEFENSES_UFOPEDIA: \"Las defensas basadas en rayos láser proporcionan protección contra incursiones de naves hostiles.\"\n  STR_PLASMA_DEFENSES_UFOPEDIA: \"Las defensas basadas en rayos de plasma constituyen una protección eficaz y poderosa contra las incursiones de naves hostiles.\"\n  STR_FUSION_BALL_DEFENSES_UFOPEDIA: \"Los misiles de fusión ofrecen la mejor protección contra ataques alienígenas. Estos misiles originan una implosión de antimateria que destruye todo lo que se encuentra en su radio de acción.\"\n  STR_GRAV_SHIELD_UFOPEDIA: \"El escudo de gravedad repele a las naves alienígenas que estén intentando aterrizar cerca de la base de manera que los sistemas de defensa tengan tiempo de recargarse y puedan volver a abrir fuego. En la práctica dobla la eficacia de cualquier sistema de defensa de tu base.\"\n  STR_MIND_SHIELD_UFOPEDIA: \"Puesto que las naves alienígenas se sirven de las ondas mentales para detectar la presencia humana, la forma más eficaz de resolver este problema es escudar las ondas cerebrales que salen de la base. Esto reducirá enormemente las posibilidades de ser detectados por una nave alienígena.\"\n  STR_PSIONIC_LABORATORY_UFOPEDIA: \"En el laboratorio psíquico se calcula la capacidad psíquica de todos los soldados de la base y se les da el entrenamiento necesario para usar estas habilidades. Cada laboratorio puede entrenar un máximo de 10 soldados. Las plazas del laboratorio se asignan a los soldados al final de cada mes. Estas habilidades se utilizan en combinación con un amp-psi, que puede servir para realizar ataques psíquicos durante un combate.\"\n  STR_HYPER_WAVE_DECODER_UFOPEDIA: \"Las comunicaciones alienígenas emplean una onda supradimensional que se desplaza casi de forma instantánea. El descodificador intercepta las transmisiones de los OVNIs y descodifica la información. Así se puede saber de qué clase de ovni se trata, las raza alienígena y el tipo de actividad.\"\n  STR_HANGAR_UFOPEDIA: \"Cada hangar puede cobijar una nave, y cuenta con instalaciones para el mantenimiento, reabastecimiento y reparación de la flota X-Com. Cada nave estacionada en una base debe tener un hangar reservado exclusivamente para ella, incluso cuando ha salido en una misión.\"\n  STR_PISTOL_UFOPEDIA: \"La pistola estándar X-Com es una semiautomática con capacidad para 12 disparos.\"\n  STR_RIFLE_UFOPEDIA: \"Este fusil de gran precisión para francotiradores tiene una mira láser y usa munición de 6,7mm en cargadores de 20 disparos.\"\n  STR_HEAVY_CANNON_UFOPEDIA: \"El cañón de combate es un arma devastadora, aunque también abulta mucho. Su versatilidad le permite disparar tres tipos de munición: perforante, incendiaria y altamente explosiva.\"\n  STR_AUTO_CANNON_UFOPEDIA: \"El cañón automático combina la versatilidad y la potencia del cañón de combate con una cadencia de tiro más rápida.\"\n  STR_ROCKET_LAUNCHER_UFOPEDIA: \"El lanzacohetes es un sistema guiado por láser que puede disparar misiles de tres tamaños.\"\n  STR_LASER_PISTOL_UFOPEDIA: \"La pistola láser es una implementacion eficaz de nueva tecnología. Tiene la facilidad de manejo de una pistola pero el tiro es más veloz y preciso\"\n  STR_LASER_RIFLE_UFOPEDIA: \"El fusil láser es un modelo más potente y preciso basado en el diseño anterior de pistola.\"\n  STR_HEAVY_LASER_UFOPEDIA: \"El láser pesado abulta mucho pero es muy eficaz.\"\n  STR_GRENADE_UFOPEDIA: \"Esta granada tiene un temporizador sofisticado y preciso para un control más exacto.\"\n  STR_SMOKE_GRENADE_UFOPEDIA: \"Las granadas de humo sirven para proveer cobertura en situaciones de combate expuestas. Utilícelas con cuidado porque también pueden beneficiar al enemigo \"\n  STR_PROXIMITY_GRENADE_UFOPEDIA: \"La granada de proximidad se lanza como las normales, pero lo que la activa es el movimiento que se produzca cerca de ella una vez que ha caído. Para utilizarla debidamente se necesitan habilidad y práctica.\"\n  STR_HIGH_EXPLOSIVE_UFOPEDIA: \"Este explosivo debe emplearse únicamente para demolición. Mantenga a su personal lejos de los puntos de demolición.\"\n  STR_MOTION_SCANNER_UFOPEDIA: \"Este sofisticado dispositivo usa una gran variedad de detectores y avanzados algoritmos informáticos para identificar unidades enemigas en movimiento. No obstante lleva algun tiempo aprender a usarlo correctamente. Presione el icono del escáner de movimiento que hay en la pantalla táctica. Elija 'Usar escáner' en el menú. La pantalla del escáner mostrará una flecha en el centro que indica la dirección en la que mira el soldado (el norte está arriba). Los puntos parpadeantes indican unidades que se han movido hace poco. Las unidades grandes o las que se desplazan rápidamente aparecen como marcas más grandes. Las unidades que no se mueven o estan estaticas no aparecerán en la pantalla.\"\n  STR_MEDI_KIT_UFOPEDIA: \"Un pequeño botiquín que contiene utiles para curar heridas, ademas de calmantes y estimulantes. Para utilizarlo debes ponerte delante del operativo X-COM que requiera tratamiento. Si el operativo esta aturdido debes colocarte sobre su cuerpo. Presione el icono del botiquín y elija \\\"usar botiquín\\\" del menu. {NEWLINE}CURAR > Las partes rojas en el cuerpo indican heridas mortales. Presione en la parte del cuerpo que esta herida y presione en el boton \\\"CURAR\\\". Se curara una herida mortal y el operativo recuperara parte de la salud.{NEWLINE}ESTIMULANTE > Repone la energía y reaviva a los operativos aturdidos. Para reavivar a un operativo inconsciente, colócate justo encima de su cuerpo.{NEWLINE}CALMANTE > Le sube la moral a los operativos heridos hasta un maximo equivalente a la salud perdida del soldado.\"\n  STR_PSI_AMP_UFOPEDIA: \"El Amp-Psi solo puede ser usado por soldados con habilidades psiquicas. Durante combate presione en Amp-Psi, elija el tipo de ataque y un objetivo con el cursor. Hay 2 tipos de ataques psiquicos:{NEWLINE}ATERRORIZAR UNIDAD> Si el ataque tiene éxito reducirá la moral del objetivo con la probabilidad de inducir panico.{NEWLINE}CONTROL MENTAL>Si este ataque es exitoso ganara control inmediatamente de la unidad enemiga como si fuera suya. Es mas difícil ser exitoso con este tipo de ataque.\"\n  STR_STUN_ROD_UFOPEDIA: \"Este artefacto sólo se puede usar en el combate cuerpo a cuerpo y aturde a un organismo vivo con descargas eléctricas, sin llegar a matarlo.\"\n  STR_MIND_PROBE_UFOPEDIA: \"La sonda mental es un dispositivo alienígena de comunicación que sirve para obtener información directamente de las ondas cerebrales. Los operativos X-Com pueden utilizarlo durante el combate para averiguar las características de un alienígena. Presione sobre la sonda mental y la opción 'Usar'. Luego presione sobre el alienígena que quiera examinar.\"\n  STR_PLASMA_PISTOL_UFOPEDIA: \"La pistola de plasma es un arma alienígena mortífera basada en la aceleración de partículas desde un diminuto campo antigravitatorio.\"\n  STR_PLASMA_RIFLE_UFOPEDIA: \"Esta potente y devastadora arma está basada en la aceleración de partículas desde un diminuto campo antigravitatorio.\"\n  STR_HEAVY_PLASMA_UFOPEDIA: \"Esta es una arma devastadora basada en la aceleración de partículas desde un diminuto campo antigravitatorio.\"\n  STR_BLASTER_LAUNCHER_UFOPEDIA: \"Este lanzamisiles alienígena dispara potentes bombas teledirigidas. Cuando dispare con esta arma observará que en la pantalla aparecen puntos indicando la ruta que seguirá la bomba. Cuando tengas suficientes puntos de ruta establecidos presione el icono de lanzamiento para disparar.\"\n  STR_SMALL_LAUNCHER_UFOPEDIA: \"Un pequeño lanzador que dispara bombas aturdidoras. Muy útil para capturar alienígenas vivos.\"\n  STR_ALIEN_GRENADE_UFOPEDIA: \"Este artefacto funciona igual que una granada terrestre, pero es mucho más potente.\"\n  STR_SMALL_SCOUT: \"Explorador Pequeño\"\n  STR_MEDIUM_SCOUT: \"Explorador Mediano\"\n  STR_LARGE_SCOUT: \"Explorador Grande\"\n  STR_HARVESTER: \"Segador\"\n  STR_ABDUCTOR: \"Secuestrador\"\n  STR_TERROR_SHIP: \"Nave Terrorista\"\n  STR_BATTLESHIP: \"Acorazado\"\n  STR_SUPPLY_SHIP: \"Crucero de Suministro\"\n  STR_RATING: \"RENDIMIENTO> {0}\"\n  STR_RATING_TERRIBLE: \"¡TERRIBLE!\"\n  STR_RATING_POOR: \"¡MALA!\"\n  STR_RATING_OK: \"OK\"\n  STR_RATING_GOOD: \"¡BUENA!\"\n  STR_RATING_EXCELLENT: \"¡EXCELENTE!\"\n  STR_SCORE: \"PUNTAJE\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"INFORME MENSUAL DEL PROYECTO X-COM\"\n  STR_MONTH: \"Mes> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"El comité de naciones patrocinadoras está satisfecho con los progresos que has hecho hasta el momento.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"El comité de naciones patrocinadoras está muy satisfecho con el progreso que ha hecho hasta el momento. Continue con su buen labor.\"\n  STR_COUNCIL_IS_DISSATISFIED: \"El comité de naciones patrocinadoras no está satisfecho con su desarollo. Debe ser más eficaz a la hora de enfrentarte a la amenaza alienígena o arriesga a que se suspenda el proyecto.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"Ha fracasado en su lucha contra la invasión alienígena y el comité de naciones patrocinadoras se ha visto obligado a cancelar el proyecto. Cada nación se enfrentará al problema como pueda. Esperamos que sea posible llegar a un acuerdo con estas fuerzas aparentemente hostiles y que la población se adapte a la presencia de los visitantes alienígenas.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} está especialmente satisfecho con su capacidad para enfrentar la amenaza local  y ha acordado aumentar su financiación.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} están particularmente satisfechos con sus logros frente al avanze local alienígena y han accedido a aumentar sus fondos.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} y {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0}  está insatisfecho con su capacidad para lidiar con la actividad alienígena en su territorio y ha decidido reducir su compromiso financiero\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} está insatisfecho con su capacidad para lidiar con la actividad alienígena en su territorio y ha decidido reducir su compromiso financiero.\"\n  STR_KNOTS: \"{0} nudos\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} ha firmado un pacto secreto con fuerzas alienígenas desconocidas y se ha retirado del proyecto.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} han firmado un pacto secreto con fuerzas alienígenas desconocidas y se han retirado del proyecto.\"\n  STR_MONTHLY_RATING: \"Tasación mensual> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Cambios en finanzas {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"El consejo financiero no esta contento con su situación financiera. Debe reducir sus deudas por debajo de $1 millón de dólares o el proyecto será cancelado.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"TRANSMISIONES DE HIPERONDAS DESCODIFICADAS\"\n  STR_CRAFT_TYPE: \"TIPO DE NAVE\"\n  STR_RACE: \"RAZA\"\n  STR_MISSION: \"MISIÓN\"\n  STR_ZONE: \"ZONA\"\n  STR_ALLOCATE_RESEARCH: \"Asignar Investigación\"\n  STR_ALLOCATE_MANUFACTURE: \"Asignar Fabricación\"\n  STR_NEW_YORK: \"Nueva York\"\n  STR_WASHINGTON: \"Washington\"\n  STR_LOS_ANGELES: \"Los Ángeles\"\n  STR_MONTREAL: \"Montreal\"\n  STR_HAVANA: \"Habana\"\n  STR_MEXICO_CITY: \"Ciudad de México\"\n  STR_CHICAGO: \"Chicago\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_DALLAS: \"Dallas\"\n  STR_BRASILIA: \"Brasilia\"\n  STR_BOGOTA: \"Bogotá\"\n  STR_BUENOS_AIRES: \"Buenos Aires\"\n  STR_SANTIAGO: \"Santiago de Chile\"\n  STR_RIO_DE_JANEIRO: \"Río de Janeiro\"\n  STR_LIMA: \"Lima\"\n  STR_CARACAS: \"Caracas\"\n  STR_LONDON: \"Londres\"\n  STR_PARIS: \"París\"\n  STR_BERLIN: \"Berlín\"\n  STR_MOSCOW: \"Moscú\"\n  STR_ROME: \"Roma\"\n  STR_MADRID: \"Madrid\"\n  STR_BUDAPEST: \"Budapest\"\n  STR_LAGOS: \"Lagos\"\n  STR_CAIRO: \"Cairo\"\n  STR_CASABLANCA: \"Casablanca\"\n  STR_PRETORIA: \"Pretoria\"\n  STR_NAIROBI: \"Nairobi\"\n  STR_CAPE_TOWN: \"Ciudad del Cabo\"\n  STR_KINSHASA: \"Kinshasa\"\n  STR_ANKARA: \"Ankara\"\n  STR_DELHI: \"Delhi\"\n  STR_KARACHI: \"Karachi\"\n  STR_BAGHDAD: \"Bagdad\"\n  STR_TEHRAN: \"Teherán\"\n  STR_BOMBAY: \"Bombay\"\n  STR_CALCUTTA: \"Calcuta\"\n  STR_TOKYO: \"Tokio\"\n  STR_BEIJING: \"Beijing\"\n  STR_BANGKOK: \"Bangkok\"\n  STR_MANILA: \"Manila\"\n  STR_SEOUL: \"Seúl\"\n  STR_SINGAPORE: \"Singapur\"\n  STR_JAKARTA: \"Yakarta\"\n  STR_SHANGHAI: \"Shangai\"\n  STR_HONG_KONG: \"Hong Kong\"\n  STR_NOVOSIBIRSK: \"Novosibirsk\"\n  STR_CANBERRA: \"Canberra\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_MELBOURNE: \"Melbourne\"\n  STR_PERTH: \"Perth\"\n  STR_PSI_TRAINING: \"Entrenam. Psi.\"\n  STR_PSIONIC_TRAINING: \"ENTRENAM. PSÍQUICO\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Capacidad restante del lab. psi.> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"Fuerza{NEWLINE}Psíquica\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"Habilidad{NEWLINE}/Mejora\"\n  STR_PSI_AMP: \"Amp-Psi\"\n  STR_IN_TRAINING: \"¿Entrenando?\"\n  STR_TARGETTED_BY: \"OBJETIVO DE:\"\n  STR_WEAPONS_CREW_HWPS: \"ARMAS/{NEWLINE}TRIPULACIÓN/PAP\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"tiene poco combustible, {NEWLINE} regresando a la base\"\n  STR_SOLDIER_LIST: \"Lista de Soldados\"\n  STR_RANK_: \"RANGO> {ALT}{0}\"\n  STR_MISSIONS: \"MISIONES> {ALT}{0}\"\n  STR_KILLS: \"BAJAS> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"RECUPERACIÓN DE HERIDA> {ALT}{0}\"\n  STR_TIME_UNITS: \"UNIDADES DE TIEMPO\"\n  STR_STAMINA: \"VIGOR\"\n  STR_HEALTH: \"SALUD\"\n  STR_BRAVERY: \"VALENTÍA\"\n  STR_REACTIONS: \"REFLEJOS\"\n  STR_FIRING_ACCURACY: \"PUNTERÍA\"\n  STR_THROWING_ACCURACY: \"PRECISIÓN DE LANZAMIENTO\"\n  STR_STRENGTH: \"FUERZA\"\n  STR_PSIONIC_STRENGTH: \"FUERZA PSÍQUICA\"\n  STR_PSIONIC_SKILL: \"HABILIDAD PSÍQUICA\"\n  STR_NEW_RANK: \"NUEVO RANGO\"\n  STR_PROMOTIONS: \"Promociones\"\n  STR_SOLDIERS_UC: \"SOLDADOS\"\n  STR_TANK_CANNON_UFOPEDIA: \"Las Plataformas Automáticas de armas Pesadas (PAP) están diseñadas para servir de complemento a los escuadrones X-Com. La combinación de una gran potencia de fuego y un blindaje pesado hace que estas unidades sean muy valiosas en los combates en campo abierto. Asegúrate de que tienes suficientes proyectiles de cañón en tus almacenes para rearmar los tanques. Se rearman automáticamente cuando son asignados a un escuadrón.\"\n  STR_TANK_ROCKET_LAUNCHER_UFOPEDIA: \"Esta plataforma automática de armas pesadas (PAP) está armada con cohetes potentes. Serán devastadores para cualquier enemigo alienígena. Asegúrate de que tienes suficientes cohetes PAP en tus almacenes.\"\n  STR_TANK_LASER_CANNON_UFOPEDIA: \"Las armas láser constituyen un complemento útil para las PAP. Combinan una gran potencia de fuego con una munición ilimitada.\"\n  STR_HOVERTANK_PLASMA_UFOPEDIA: \"La tecnología alienígena ha redefinido las PAP. La maniobrabilidad aportada por el desplazamiento aéreo y la potencia de los rayos de plasma son una combinación mortífera.\"\n  STR_HOVERTANK_LAUNCHER_UFOPEDIA: \"Este tanque volador tiene un lanzador de bolas de fusión, capaz de causar una devastación inmensa. Utilízalo con precaución. Tendrás que fabricar las bolas de fusión con las que mantener armadas estas PAP. Una bola de fusión es un arma dirigida e inteligente. Para disparar una tendrá que usar el cursor para establecer una serie de puntos de ruta en el mapa que le sirvan de guía, y luego presione el icono de lanzamiento.\"\n  STR_HEAVY_PLASMA_CLIP_UFOPEDIA: \"Este artefacto compacto se usa como munición para el Plasma Pesado. Contiene una pequeña cantidad de elerio.\"\n  STR_PLASMA_RIFLE_CLIP_UFOPEDIA: \"Este pequeño objeto es la fuente de energía de un fusil plasma: un arma alienígena de potencia media. Contiene una pequeña cantidad de Elerio.\"\n  STR_PLASMA_PISTOL_CLIP_UFOPEDIA: \"Fuente de energía de la pistola alienígena de plasma. Lleva elerio, la fuente de toda la energía alienígena.\"\n  STR_STUN_BOMB_UFOPEDIA: \"La bomba aturdidora se usa para capturar vivos a los humanos, pero también se puede usar contra las razas alienígenas. Se dispara con un pequeño lanzador.\"\n  STR_ALIEN_RESEARCH_UFOPEDIA: \"La misión de investigación alienígena sirve para recoger información básica sobre la Tierra y sus habitantes. Utilizan sobre todo vehículos pequeños y aterrizan de vez en cuando en zonas desérticas. Este tipo de actividad alienígena supone la menor de las amenaza para X-Com. A los gobiernos y al público les preocupa poco.\"\n  STR_ALIEN_HARVEST_UFOPEDIA: \"Los alienígenas utilizan la fauna terrestre para muchas cosas. Secuestran a los animales y los devuelven después de haberles estirpado varios órganos. Lo que más se denuncia son las mutilaciones de ganado junto con avistamientos de OVNIs. Este tipo de actividad alienígena preocupa mucho a los gobiernos y causa bastante inquietud a la población; tiene lugar sobre todo en areas rurales. La posible explicación de esta cosecha alienígena es que en un principio las razas alienígenas 'sembraron' el planeta con su flora y su fauna, y ahora han vuelto a recoger la cosecha.\"\n  STR_ALIEN_ABDUCTION_UFOPEDIA: \"Éste es el tipo de actividad alienígena más perniciosa. La abduccion de civiles por parte de alienigenas ha sido ampliamente denunciada pese a que los alienígenas intentan borrarles la memoria a sus víctimas. Los abducidos declaran haber sido sometidos a humillantes exámenes físicos, incluyendo la implantación de fetos alienígenas y extraños experimentos genéticos. Según parece el propósito detras de esta actividad parece estar unido a la mutación genética y la manipulación de material genético de los propios alienígenas. Esta actividad causa un gran pánico y tiene lugar en ciudades y zonas pobladas.\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"Agentes alienígenas con aspecto humano pueden infiltrarse en los gobiernos de la Tierra. Esto puede dar lugar a contactos oficiales del más alto nivel entre los alienígenas y dichos gobiernos. El clímax de esta actividad se caracteriza por una intensa actividad de OVNIs en los alrededores de las grandes ciudades. Los alienígenas intentarán firmar un pacto con un gobierno ofreciéndole acceso a su tecnología superior. A cambio, el gobierno permitirá a los alienígenas realizar sus actividades sin ningún estorbo. Este tipo de misión alienígena representa el peor escenario para X-Com. si un govierno acceda al pacto sus fondos cecaran. \"\n  STR_ALIEN_BASE_UFOPEDIA: \"Los alienígenas construirán bases subterráneas secretas en zonas remotas. Tras ciertos vuelos iniciales de reconocimiento, comenzará una intensa actividad OVNI que durará mientras construyan la base. En ellas hay laboratorios para hacer experimentos con humanos abducidos y suministros para continuar sus actividades en la región. Estas bases generarán una gran cantidad de denuncias de actividad alienígena sin la presencia de OVNIs. Para localizar una de estas bases una nave de X-Com debe patrullar por la zona durante unas cuantas horas.\"\n  STR_ALIEN_TERROR_UFOPEDIA: \"Cuando los alienígenas realizan una incursión en una ciudad, despliegan fuerzas especiales con poderes horribles. Los civiles son amenazados directamente y los gobiernos tienen que evacuar zonas enormes. El propósito de esta actividad es causar la suficiente histeria en la población como para que los gobiernos abandonen el proyecto X-Com.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"Si los interceptores de X-Com derriban muchos OVNIs, los alienígenas podrían tomar represalias. Ello podría acabar en un ataque directo contra una base X-Com. Sin embargo, si quieren atacarnos, primero deben encontrar la base, y si mantenemos alejados a los OVNIs, el peligro de ataque es menor.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"Una vez que una base alienígena está construida, comienza a recibir abastecimientos, traídos en una nave especial. Si se detecta a una de estas naves cuando va a aterrizar, es que hay una base cerca.\"\n  STR_SMALL_SCOUT_UFOPEDIA: \"Esta mininave se emplea principalmente para misiones de investigación y reconocimiento. Suele preceder a naves más grandes al principio de una misión alienígena.\"\n  STR_MEDIUM_SCOUT_UFOPEDIA: \"Un ovni explorador mediano no supone una gran amenaza para las fuerzas terrestres. Suele preceder a naves más grandes durante las misiones.\"\n  STR_LARGE_SCOUT_UFOPEDIA: \"El ovni explorador más grande se usa en todo tipo de misiones alienígenas.\"\n  STR_HARVESTER_UFOPEDIA: \"El ovni cosechador tiene una escotilla en la parte de abajo y está equipado con aparatos para subir a bordo ganado u otras bestias. Extirpan el material deseado con láser y luego tiran el cadáver al suelo. También tienen contenedores para almacenar las partes del cuerpo extirpadas.\"\n  STR_ABDUCTOR_UFOPEDIA: \"Este ovni va equipado con una sala de exámenes para realizar horribles experimentos con humanos. Normalmente las víctimas son paralizadas por medios telepáticos, pero permanecen conscientes mientras están en la mesa de operaciones.\"\n  STR_TERROR_SHIP_UFOPEDIA: \"La nave Terrorista  tiene una instalación de confinamiento para criaturas alienígenas de gran tamaño y/o armas, cuyo propósito es aterrorizar a la población. Sirven para transportar dichas criaturas/armas a zonas pobladas.\"\n  STR_BATTLESHIP_UFOPEDIA: \"El acorazado es la nave alienígena más poderosa. Normalmente es la nave más importante de las misiones alienígenas. Está equipada con armas potentes y su tripulación es muy numerosa.\"\n  STR_SUPPLY_SHIP_UFOPEDIA: \"El buque de suministros se emplea durante la construcción de bases alienígenas y para llevar suministros a las ya existentes. Transporta contenedores de alimentos para alienígenas y cámaras de reproducción.\"\n  STR_DISMANTLE: \"Desmantelar\"\n  STR_FACILITY_IN_USE: \"INSTALACIÓN EN USO\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"¡NO SE PUEDE DESMANTELAR LA INSTALACIÓN!{SMALLLINE}Todas las instalaciones de la base deben estar unidas al ascensor de acceso.\"\n  STR_TRANSFER_ITEMS_TO: \"Transferir articulos a {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"NO HAY CONFINAMIENTO ALIENÍGENA PARA TRASLADO!{SMALLLINE}Los alienígenas necesitan una unidad de contencion para sobrevivir.\"\n  STR_AMOUNT_AT_DESTINATION: \"EN DESTINO\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"Alienígena muere porque no hay confinamiento alienígena.\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"NO HAY ALOJAMIENTO{SMALLLINE}La base de destino no tiene suficiente espacio para la tripulación de la nave.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"INSUFICIENTE ESPACIO DE ALMACENAJE{SMALLLINE}La base de destino no tiene espacio suficiente para almacenar el equipo asignado a la nave.\"\n  STR_ITEMS_ARRIVING: \"Artículos Trasladados\"\n  STR_DESTINATION_UC: \"DESTINO\"\n  STR_PISTOL: \"Pistola\"\n  STR_PISTOL_CLIP: \"Cargador de Pistola\"\n  STR_RIFLE: \"Fusil\"\n  STR_RIFLE_CLIP: \"Cargador de Fusil\"\n  STR_HEAVY_CANNON: \"Cañón de Combate\"\n  STR_HC_AP_AMMO: \"Munición P para CC\"\n  STR_HC_HE_AMMO: \"Munición AE para CC\"\n  STR_HC_I_AMMO: \"Munición I para CC\"\n  STR_AUTO_CANNON: \"Cañón Automático\"\n  STR_AC_AP_AMMO: \"Munición P para CA \"\n  STR_AC_HE_AMMO: \"Munición AE para CA \"\n  STR_AC_I_AMMO: \"Munición I para CA\"\n  STR_ROCKET_LAUNCHER: \"Lanzacohetes\"\n  STR_SMALL_ROCKET: \"Cohete Pequeño\"\n  STR_LARGE_ROCKET: \"Cohete Grande\"\n  STR_INCENDIARY_ROCKET: \"Cohete Incendiario\"\n  STR_GRENADE: \"Granada\"\n  STR_SMOKE_GRENADE: \"Granada de Humo\"\n  STR_PROXIMITY_GRENADE: \"Granada de Proximidad\"\n  STR_HIGH_EXPLOSIVE: \"Explosivo de Demolición\"\n  STR_STUN_ROD: \"Vara Aturdidora\"\n  STR_HEAVY_PLASMA: \"Plasma Pesado\"\n  STR_HEAVY_PLASMA_CLIP: \"Cargador de Plasma Pesado\"\n  STR_PLASMA_RIFLE: \"Fusil de Plasma\"\n  STR_PLASMA_RIFLE_CLIP: \"Cargador de Fusil de Plasma\"\n  STR_PLASMA_PISTOL: \"Pistola de Plasma\"\n  STR_PLASMA_PISTOL_CLIP: \"Cargador de Pistola de Plasma\"\n  STR_BLASTER_LAUNCHER: \"Lanzabombas Guiadas\"\n  STR_BLASTER_BOMB: \"Bomba Guiada\"\n  STR_SMALL_LAUNCHER: \"Lanzador Pequeño\"\n  STR_STUN_BOMB: \"Bomba Aturdidora\"\n  STR_ALIEN_GRENADE: \"Granada Alienígena\"\n  STR_ELERIUM_115: \"Elerio 115\"\n  STR_MIND_PROBE: \"Sonda Mental\"\n  STR_SECTOID_CORPSE: \"Cadáver de Sectoide\"\n  STR_SNAKEMAN_CORPSE: \"Cadáver de Hombre-Serpiente\"\n  STR_ETHEREAL_CORPSE: \"Cadáver de Etéreo\"\n  STR_MUTON_CORPSE: \"Cadáver de Muton\"\n  STR_FLOATER_CORPSE: \"Cadáver de Flotador\"\n  STR_CELATID_CORPSE: \"Cadáver de Celátido\"\n  STR_SILACOID_CORPSE: \"Cadáver de Silacoide\"\n  STR_CHRYSSALID_CORPSE: \"Cadáver de Crisálida\"\n  STR_REAPER_CORPSE: \"Cadáver de Devorador\"\n  STR_SECTOPOD_CORPSE: \"Restos de Sectópodo\"\n  STR_CYBERDISC_CORPSE: \"Restos de Ciberdisco\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"Insuficiente munición para armar PAP{SMALLLINE}Cada PAP requiere {0} {1}.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Insuficiente armamento para re-equipar pelotón \"\n  STR_MARS_CYDONIA_LANDING: \"Marte: Aterrizaje en Cydonia.\"\n  STR_MARS_CYDONIA_LANDING_BRIEFING: \"Su nave Avenger ha aterrizado en la región de Cydonia sobre la superficie de Marte. Nuestra información indica que una de las pirámides contiene un ascensor de acceso a un complejo subterráneo. Una vez que hayas reunido a todos los soldados en el área del ascensor, presione el icono de 'Abortar misión' para pasar al siguiente nivel.\"\n  STR_MARS_THE_FINAL_ASSAULT: \"Marte: El Asalto Final\"\n  STR_MARS_THE_FINAL_ASSAULT_BRIEFING: \"El ascensor de la pirámide lleva a tus soldados, cansados por la batalla, hacia el interior del planeta. Llegan al corazón de un gran complejo de túneles y cámaras. El cerebro alienígena está oculto en alguna parte del laberinto. Para que la Tierra se salve de la esclavitud a manos de los alienígenas el cerebro tiene que ser destruido.{NEWLINE}¡Buena suerte!\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Tiene que investigar {NEWLINE}{0}{NEWLINE}para producir{NEWLINE}{1}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"Los Alienígenas han destruido la base indefensa {0}\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"Agentes X-Com han localizado una base Alienígena en {0}\"\n  STR_STANDOFF: \"RETIRARSE\"\n  STR_CAUTIOUS_ATTACK: \"ATAQUE CAUTELOSO\"\n  STR_STANDARD_ATTACK: \"ATAQUE NORMAL\"\n  STR_AGGRESSIVE_ATTACK: \"ATAQUE AGRESIVO\"\n  STR_DISENGAGING: \"ABANDONAR COMBATE\"\n  STR_UFO_HIT: \"¡OVNI IMPACTADO!\"\n  STR_UFO_CRASH_LANDS: \"¡OVNI DERRIBADO!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Minimizar sólo cuando esta retirado.\"\n  STR_UFO_RETURN_FIRE: \"OVNI RESPONDE AL FUEGO\"\n  STR_INTERCEPTOR_DAMAGED: \">>> INTERCEPTOR DAÑADO <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> INTERCEPTOR DESTRUIDO <<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"¡OVNI ESTA ESCAPANDO!\"\n  STR_ALIENS_TERRORISE: \"INCURSIÓN ALIENíGENA\"\n  STR_LONG_RANGE_DETECTION: \"Radar de Largo Alcanze\"\n  STR_STORES_UC: \"ALMACENES\"\n  STR_DIFFICULTY_LEVEL: \"DIFICULTAD\"\n  STR_INTERCEPT: \"INTERCEPTAR\"\n  STR_BASES: \"BASES\"\n  STR_GRAPHS: \"ESTADÍSTICAS\"\n  STR_UFOPAEDIA_UC: \"OVNIPEDIA\"\n  STR_OPTIONS_UC: \"OPCIONES\"\n  STR_FUNDING_UC: \"FINANZAS\"\n  STR_5_SECONDS: \"5 seg \"\n  STR_1_MINUTE: \"1 min \"\n  STR_5_MINUTES: \"5 min \"\n  STR_30_MINUTES: \"30 min \"\n  STR_1_HOUR: \"1 hora\"\n  STR_1_DAY: \"1 día\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"Lista de Rendimiento de X-Com\"\n  STR_ENTER_NAME: \"Escriba el Nombre\"\n  STR_PERFORMANCE_RATING: \"Evaluación de Rendimiento\"\n  STR_VICTORY_DATE: \"Fecha de Victoria\"\n  STR_ELECTRO_FLARE: \"Bengala Eléctrica\"\n  STR_ELECTRO_FLARE_UFOPEDIA: \"Este artefacto produce una señal luminosa brillante. Ilumina a las unidades tanto amigas como enemigas que esten cerca durante misiones nocturnas.\"\n  STR_MONTHLY_COSTS: \"Gastos Mensuales\"\n  STR_CRAFT_RENTAL: \"Alquiler de Naves\"\n  STR_SALARIES: \"Salarios\"\n  STR_BASE_MAINTENANCE: \"Mantenimiento de Bases\"\n  STR_COST_PER_UNIT: \"Costo\"\n  STR_QUANTITY: \"Cantidad\"\n  STR_TOTAL: \"Total\"\n  STR_IN_PSIONIC_TRAINING: \"En Entrenamiento Psíquico\"\n  STR_BLASTER_BOMB_UFOPEDIA: \"Este aparato es un misil altamente explosivo que lleva instalado un sistema de guía inteligente. Lo dispara un Lanzador de Bombas Guiadas.\"\n  STR_FRONT_ARMOR: \"Protección Frontal\"\n  STR_LEFT_ARMOR: \"Protección Izquierdo\"\n  STR_RIGHT_ARMOR: \"Protección Derecho\"\n  STR_REAR_ARMOR: \"Protección Trasero\"\n  STR_UNDER_ARMOR: \"Protección Inferior\"\n  STR_ROUNDS: \"Disparos\"\n  STR_UNIT: \"UNIDAD> {0}\"\n  STR_ENERGY: \"ENERGÍA\"\n  STR_MORALE: \"MORAL\"\n  STR_ARMOR_: \"ARMADURA> {0}\"\n  STR_FRONT_ARMOR_UC: \"PROTECCIÓN FRONTAL\"\n  STR_LEFT_ARMOR_UC: \"PROTECCIÓN IZQUIERDO\"\n  STR_RIGHT_ARMOR_UC: \"PROTECCIÓN DERECHO\"\n  STR_REAR_ARMOR_UC: \"PROTECCIÓN TRASERA\"\n  STR_SKILLS: \"HABILIDADES> {0}\"\n  STR_LEVEL: \"NIVEL> {0}\"\n  STR_HEAD: \"CABEZA\"\n  STR_TORSO: \"TORSO\"\n  STR_RIGHT_ARM: \"BRAZO DCHO.\"\n  STR_LEFT_ARM: \"BRAZO IZQ.\"\n  STR_RIGHT_LEG: \"PIERNA DCHA.\"\n  STR_LEFT_LEG: \"PIERNA IZQ.\"\n  STR_PAIN_KILLER: \"ANALGÉSICO\"\n  STR_STIMULANT: \"ESTIMULANTE\"\n  STR_HEAL: \"CURAR\"\n  STR_TIME_UNITS_SHORT: \"UT>{ALT}{0}\"\n  STR_WEIGHT: \"Peso>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"Reacción>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"Abilidad Psíquica>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"Fuerza Psíquica>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Artefacto Alienígena\"\n  STR_AMMO_ROUNDS_LEFT: \"MUNICIÓN:{NEWLINE}RESTANTE={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Analgésico>{ALT}{0}{ALT}{NEWLINE}Estimulante>{ALT}{1}{ALT}{NEWLINE}Curar>{ALT}{2}\"\n  STR_THROW: \"Lanzar\"\n  STR_AUTO_SHOT: \"Ráfaga\"\n  STR_SNAP_SHOT: \"Simple\"\n  STR_AIMED_SHOT: \"Precisión\"\n  STR_STUN: \"Aturdir\"\n  STR_PRIME_GRENADE: \"Activar Granada\"\n  STR_USE_SCANNER: \"Utilizar Escáner\"\n  STR_USE_MEDI_KIT: \"Utilizar Botiquín\"\n  STR_LAUNCH_MISSILE: \"Lanzar Misil\"\n  STR_ACCURACY_SHORT: \"Punteria>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"¡Unidades de Tiempo Insuficientes!\"\n  STR_NOT_ENOUGH_ENERGY: \"¡Energía Insuficiente!\"\n  STR_NO_ROUNDS_LEFT: \"¡No queda Munición!\"\n  STR_NO_AMMUNITION_LOADED: \"¡El Arma no está Cargada!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"¡Munición Incorrecta para esta Arma!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"¡El Arma ya está Cargada!\"\n  STR_NO_LINE_OF_FIRE: \"¡No hay Línea de Tiro!\"\n  STR_GRENADE_IS_ACTIVATED: \"¡La Granada está Activada!\"\n  STR_GRENADE_IS_DEACTIVATED: \"¡La Granada está Desactivada!\"\n  STR_THERE_IS_NO_ONE_THERE: \"¡Allí no hay nadie!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"¡Incapaz de ulilizar artefacto hasta después de ser estudiado!\"\n  STR_OUT_OF_RANGE: \"¡Fuera de Alcance!\"\n  STR_UNABLE_TO_THROW_HERE: \"¡Imposible lanzar aquí!\"\n  STR_SET_TIMER: \"Ajustar Temporizador\"\n  STR_HIDDEN_MOVEMENT: \"MOVIMIENTO OCULTO\"\n  STR_TURN: \"TURNO> {0}\"\n  STR_SIDE: \"BANDO> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Presione un botón para continuar\"\n  STR_MIND_CONTROL: \"Control Mental\"\n  STR_PANIC_UNIT: \"Causar Pánico\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Ataque Moral Exitoso\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Control Mental Exitoso\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}ha entrado en cólera\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}ha entrado en cólera\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}ha entrado en pánico\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}es presa del pánico\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Alienígenas\"\n  STR_RIGHT_HAND: \"MANO DCHA.\"\n  STR_LEFT_HAND: \"MANO IZQ.\"\n  STR_RIGHT_SHOULDER: \"HOMBRO DCHO.\"\n  STR_LEFT_SHOULDER: \"HOMBRO IZQ.\"\n  STR_BACK_PACK: \"MOCHILA\"\n  STR_BELT: \"CINTURÓN\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}esta bajo control alienígena\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}esta bajo control alienígena\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}ha caído inconsciente\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}se ha desmayado\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}ha muerto de una herida mortal\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}ha muerto de una herida fatal\"\n  STR_USE_MIND_PROBE: \"Usar Sonda Mental\"\n  STR_FATAL_WOUNDS: \"HERIDAS MORTALES\"\n  STR_UNDER_ARMOR_UC: \"PROTECCIÓN INFERIOR\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"UT reservadas para Disparo Simple\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"UT reservadas para Ráfagas\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"UT reservadas para Disparo de Precisión\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"UTs reservadas para Arrodillarse\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"UTs reservadas para Arrodillarse y Disparar\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} Unidad en Nave X-Com\"\n    many: \"{N} Unidades en Nave X-Com\"\n    other: \"{N} Unidades en Nave X-Com\"\n  STR_UNITS_OUTSIDE:\n    one: \"{N} Unidad dejada fuera\"\n    many: \"{N} Unidades dejadas fuera\"\n    other: \"{N} Unidades dejadas fuera\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} Unidad en la Entrada\"\n    many: \"{N} Unidades en la Entrada\"\n    other: \"{N} Unidades en la Entrada\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} Unidad en la Meta de Salida\"\n    many: \"{N} Unidades en la Meta de Salida\"\n    other: \"{N} Unidades en la Meta de Salida\"\n  STR_ABORT_MISSION_QUESTION: \"¿Cancelar la Misión?\"\n  STR_CORPSE: \"Cadáver\"\n  STR_UNLOAD_CRAFT: \"Descargar\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}ha muerto\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}ha muerto\"\n  STR_HIT_MELEE: \"Impacto\"\n  STR_GROUND: \"SUELO\"\n  STR_LIVING_QUARTERS_PLURAL: \"Viviendas\"\n  STR_LIST_ITEM: \"ARTÍCULOS\"\n  STR_PERSONAL_ARMOR_UFOPEDIA: \"Usando la recien descubierta aleación alienígena, esta nueva armadura da a nuestros soldados una oportunidad en la lucha contra la amenaza alienígena.\"\n  STR_POWER_SUIT_UFOPEDIA: \"Una nueva y poderosa protección para nuestros soldados, esta alimentada por una fuente de energia alienígena que amplifica la velocidad y fuerza del usuario y ofrece la mejor protección para tropas.\"\n  STR_FLYING_SUIT_UFOPEDIA: \"Una version mejorada de la armadura  mecánica, incorporando tecnologia antigravitacional alienigena que permite amplia libertad de movimiento en el campo de batalla.\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"Todos los alianigenas han muerto{NEWLINE} Recuperación automática iniciada\"\n  STR_RESET: \"Reiniciar\"\n  STR_MEMORIAL: \"Conmemoración\"\n  STR_DATE_UC: \"FECHA\"\n  STR_SOLDIERS_RECRUITED_UC: \"SOLDADOS RECLUTADOS>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"BAJAS>{ALT}{0}\"\n  MAP_CULTA: \"Granja\"\n  MAP_FOREST: \"Bosque\"\n  MAP_JUNGLE: \"Jungla\"\n  MAP_MOUNT: \"Montaña\"\n  MAP_DESERT: \"Desierto\"\n  MAP_POLAR: \"Polar\"\n  MAP_URBAN: \"Ciudad\"\n  MAP_UBASE: \"Base Alienígena\"\n  MAP_XBASE: \"Base X-Com\"\n  MAP_MARS: \"Marte\"\n  STR_MIXED: \"Mezclado\"\n  STR_REMOVE_SELECTED: \"Eliminar Elejidos\"\n  STR_LIVE_ALIENS: \"Especímenes{NEWLINE}Vivos\"\n  STR_DEAD_ALIENS: \"Especímenes{NEWLINE}Rechazados\"\n  STR_UNDER_INTERROGATION: \"Siendo{NEWLINE}Estudiados\"\n  STR_CONTAINMENT_EXCEEDED: \"¡LÍMITE DE CONFINAMIENTO ALIENÍGENAS EXCEDIDO!{SMALLLINE} El espacio en la sala de confinamiento es insuficiente en {0}. Debe eliminar el exceso de alienígenas (quien luego morirá).\"\n  STR_MANAGE_CONTAINMENT: \"Administrar Confinamiento Alienígena\"\n  STR_STORAGE_EXCEEDED: \"ESPACIO DE ALMACENAMIENTO SUPERADO{SMALLLINE}Espacio de almacenamiento insuficiente en {0}. Bebe vender artículos excedentes.\"\n  STR_GO_TO_BASE: \"Ir a la Base\"\n  STR_MELEE_ACCURACY: \"PRECISIÓN CUERPO A CUERPO\"\n  STR_SELL_PRODUCTION: \"VENDER\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Ambas manos deben estar vacías!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Elementos insuficientes para copiar la plantilla!\"\n  STR_UNLOAD_WEAPON: \"Descargar arma\"\n  STR_ALL_ITEMS: \"Todos los items\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"NO MÁS EQUIPO PERMITIDO A BORDO!{SMALLLINE}solamente se le permite tomar un máximo de {N} elemento del equipo en esta nave.\"\n    many: \"NO MÁS EQUIPO PERMITIDO A BORDO!{SMALLLINE}solamente se le permite tomar un máximo de {N} elemento del equipo en esta nave.\"\n    other: \"NO MÁS EQUIPO PERMITIDO A BORDO!{SMALLLINE}solamente se le permite tomar un máximo de {N} elemento del equipo en esta nave.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}CENTRO DE CONTROL DESTRUIDO{NEWLINE}Diríjase a la entrada y aborte.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"Instalaciones X-Com no se pueden construir bajo el agua\"\n  STR_LEVEL_SHORT: \"{0}\"\n  STR_PERSONNEL: \"Personal\"\n  STR_CRAFT_ARMAMENT: \"Nave y Armamento\"\n  STR_COMPONENTS: \"Componentes\"\n  STR_SOLDIERS_RECRUITED: \"Soldados reclutados\"\n  STR_SOLDIERS_LOST: \"Bajas\"\n  STR_TOTAL_UFOS: \"OVNIs detectados\"\n  STR_TOTAL_ALIEN_BASES: \"Bases Alienígena descubiertas\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"FPS\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"MPS\"\n  FEMALE_CIVILIAN: \"Civil, Femenino\"\n  MALE_CIVILIAN: \"Civil, Masculino\"\n  CYBERDISC_WEAPON: \"Arma Ciberdisco\"\n  REAPER_WEAPON: \"Arma Devorador\"\n  CHRYSSALID_WEAPON: \"Arma Crisálida\"\n  CELATID_WEAPON: \"Arma Celátido\"\n  SILACOID_WEAPON: \"Arma Silacoide\"\n  SECTOPOD_WEAPON: \"Arma Sectópodo\"\n  ZOMBIE_WEAPON: \"Arma Zombi \"\n  ALIEN_PSI_WEAPON: \"Arma Psi Alien\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/es-ES.yml",
    "content": "es-ES:\n  STR_AVENGER_UFOPEDIA: \"NAVE ESPACIAL DE TRANSPORTE Y COMBATE. LO ÚLTIMO COPIANDO  TECNOLOGÍA ALIENÍGENA\"\n  STR_INTERCEPTOR_UFOPEDIA: \"NAVE DE COMBATE CON MOTORES DUALES DE DETONACIÓN DE IMPULSOS Y SISTEMAS ELECTRÓNICOS ESPECIALMENTE PROTEGIDOS. LA MEJOR TECNOLOGÍA TERRESTRE.\"\n  STR_LIGHTNING_UFOPEDIA: \"NAVE DE TRANSPORTE Y COMBATE. UNA COPIA TOSCA PERO EFICAZ DE LOS SISTEMAS DE PROPULSIÓN ALIENÍGENAS.\"\n  STR_SKYRANGER_UFOPEDIA: \"TRANSPORTE DE TROPAS. EL MÁS RÁPIDO DE SU CLASE, CON DESPEGUE Y ATERRIZAJE VERTICAL (V.T.O.L.)\"\n  STR_FIRESTORM_UFOPEDIA: \"NAVE DE COMBATE. ESTE CAZA MONOPLAZA ES UNA COPIA DEL CLÁSICO PLATILLO VOLANTE DE LOS ALIENÍGENAS CON UNIDAD DE PROPULSIÓN CENTRAL.\"\n  STR_STINGRAY_UFOPEDIA: \" MISIL AVANZADO AIRE-AIRE CON COMPONENTES ELÉCTRONICOS ESPECIALMENTE PROTEGIDOS.\"\n  STR_AVALANCHE_UFOPEDIA: \"MISIL AIRE-AIRE CON CABEZA NUCLEAR, EXTREMADAMENTE POTENTE.\"\n  STR_CANNON_UFOPEDIA: \"CAÑÓN DE GRAN POTENCIA QUE DISPARA MUNICIÓN PERFORANTE CAPAZ DE ATRAVESAR 16 PULGADAS DE ACERO.\"\n  STR_FUSION_BALL_UFOPEDIA: \"ESTE LANZADOR DISPARA UN MISIL EN FORMA DE BOLA PROPULSADA POR UNA REACCIÓN DE ANTIMATERIA. ESTA BOLA DESTRUYE EL BLANCO CON UNA ONDA GRAVITATORIA QUE PROVOCA UNA IMPLOSIÓN.\"\n  STR_LASER_CANNON_UFOPEDIA: \"ESTE RAYO LÁSER CONVENCIONAL SE ACCIONA POR UNA CÁMARA DE REACCIÓN DE ANTIMATERIA.\"\n  STR_PLASMA_BEAM_UFOPEDIA: \"EL RAYO GRAVITATORIO DIRIGE UN CAMPO DE GRAVEDAD CANALIZADO CON GRAN PRECISIÓN QUE PROVOCA UNA IMPLOSIÓN.\"\n  STR_SECTOID_UFOPEDIA: \"La jerarquía sectoide va desde soldados hasta lideres con poderosas habilidades psiónicas. Estos poderes psionicos pueden ser usados para desmoralizar soldados en combate e incluso para controlar sus mentes. Tienden a realizar abducciones de humanos y mutilaciones de ganado. Gracias a las abducciones obtienen material genético para realizar cruces y crear clones para infiltrarse en la sociedad humana. El ganado proporciona alimentos y material genético. Parece que esta raza quiere desarrollar híbridos genéticamente superiores para aumentar la eficacia de su sociedad tipo colmena.\"\n  STR_SECTOID_AUTOPSY: \"Autopsia de Sectoide\"\n  STR_SECTOID_AUTOPSY_UFOPEDIA: \"La autopsia revela vestigios de órganos digestivos y una estructura sencilla. El cerebro y los ojos están muy desarrollados. La estructura sugiere una alteración genética o mutación. La boca y la nariz pequeñas parecen tener poca utilidad. Las membranas entre los dedos y los pies planos sugieren un origen acuático. No hay órganos reproductores ni ningun indicio que indique cómo se reproduce esta especie. Lo más probable es que sea una especie creada por ingeniería genética.\"\n  STR_SNAKEMAN_UFOPEDIA: \"Esta raza se ha desarrollado en un medio extremadamente hostil. Son muy resistentes y pueden aguantar cambios extremos de temperatura. Su movilidad depende de una enorme parte inferior que es como la de una serpiente y que protege todos los órganos vitales. Sus objetivos parecen ser meramente predatorios y parecen estar bajo el control de alguna otra inteligencia que dirige sus incursiones de estilo militar en la Tierra.\"\n  STR_SNAKEMAN_AUTOPSY: \"Autopsia de Hombre-serpiente\"\n  STR_SNAKEMAN_AUTOPSY_UFOPEDIA: \"La piel es extremadamente dura y resistente al calor. El sistema cardio-vascular es parte del sistema muscular, el cual usa principios hidráulicos para crear movimiento. El único músculo verdadero es el \\\"corazón\\\". El sistema reproductor parece ser muy eficiente. La reproducción es asexual; cada hombre-serpiente lleva cincuenta huevos dentro de su cuerpo en todo momento. Si se les dejara actuar esta especie supondría una amenaza muy seria para la vida en la Tierra.\"\n  STR_ETHEREAL_UFOPEDIA: \"Este ser tiene poderes mentales asombrosos que le permiten comunicarse telepáticamente y usar habilidades telequineticas. Las aparentemente débiles capacidades fisicas de esta criatura se compensan gracias a estos poderes mentales. No comprendemos cómo funcionan estos poderes telequinéticos, ya que parecen desafiar las leyes de la física como la conocemos. Son muy peligrosos en combate ya que cuentan con sus poderes mentales. Es muy raro verlos en la Tierra, pues parecen confiar en otras razas para conseguir sus objetivos.\"\n  STR_ETHEREAL_AUTOPSY: \"Autopsia de Etéreo\"\n  STR_ETHEREAL_AUTOPSY_UFOPEDIA: \"Este ser esta físicamente subdesarrollado y parece ser incapaz de realizar ninguna función vital. Los músculos están severamente atrofiados y parece que los órganos internos están poco desarrollados. Los órganos sensoriales, incluyendo los ojos, parecen no funcionar. El cerebro, sin embargo, está bien desarrollado y utiliza una gran parte del suministro sanguíneo del cuerpo. Es un misterio cómo esta criatura puede sobrevivir sin soporte externo.\"\n  STR_MUTON_UFOPEDIA: \"Esta criatura humanoide es inteligente y tiene una constitución física muy fuerte. Tiene un apetito particular por la carne cruda de cualquier tipo, la cual necesita para sobrevivir como los carnívoros de la Tierra. Parece que confian en las órdenes telepáticas enviadas por una raza conocida como \\\"Etéreos\\\". Una vez se rompe esta unión telepática, su sistema nervioso parece colapsarse y mueren. Los implantes cibernéticos sirven para mejorar su eficacia en combate. Son claramente los soldados de a pie de una inteligencia superior.\"\n  STR_MUTON_AUTOPSY: \"Autopsia de Mutante\"\n  STR_MUTON_AUTOPSY_UFOPEDIA: \"La \\\"piel\\\" de esta criatura parece ser una armadura protectora creada orgánicamente e injertada en el cuerpo. Hay numerosos implantes cibernéticos que sirven para mejorar el sistema cardio-vascular y los sentidos. Los órganos reproductores han sido extirpados quirurgicamente. Evidentemente la vida de estas desafortunadas criaturas se limita a la guerra y la conquista. La munición perforadora de blindaje no es muy eficaz contra su piel reforzada.\"\n  STR_CELATID_UFOPEDIA: \"Esta forma de vida tiene la misteriosa habilidad natural de flotar en el aire. Parece detectar las ondas mentales humanas, gracias a lo cual puede encontrar a su blanco aunque éste esté bien escondido. Una vez que ha detectado el blanco, el celátido aterriza y dispara pequeños glóbulos de veneno altamente corrosivo. Esta criatura es capaz de crear clones de sí misma a un ritmo alarmante. Suele acompañar a la raza \\\"Mutante\\\" en sus incursiones.\"\n  STR_CELATID_AUTOPSY: \"Autopsia de Celátido\"\n  STR_CELATID_AUTOPSY_UFOPEDIA: \"En el núcleo hay un pequeño dispositivo biomecánico que parece ser un sistema de propulsión antigravedad, resultado de la evolución natural de la criatura. La bolsa de veneno es el órgano más grande y no parece haber ninguna estructura cerebral independiente. No se distingue ningún sistema digestivo ni reproductor. Un pequeño órgano contiene embriones capaces de crecer y convertirse rápidamente en criaturas adultas.\"\n  STR_SILACOID_UFOPEDIA: \"Esta forma de vida basada en el silicio genera una cantidad enorme de calor. Es capaz de romper rocas y digerirlas en su núcleo interior a alta temperatura. Se trata de una inteligencia primitiva que puede ser controlada con implantes o por seres con poderes telepáticos. Trabaja con la raza alienígena de los \\\"Mutantes\\\".\"\n  STR_SILACOID_AUTOPSY: \"Autopsia de Silacoide\"\n  STR_SILACOID_AUTOPSY_UFOPEDIA: \"El interior de esta criatura está muy caliente, lo que parece ser la base de su sistema digestivo. Su sistema muscular sin igual le permite ser tremendamente fuerte y rápido. Su piel, dura como la piedra, no se ve afectada por la munición incendiaria ni por el fuego.\"\n  STR_CHRYSSALID_UFOPEDIA: \"Las garras tipo cangrejo de esta criatura son un arma poderosa en el combate cuerpo a cuerpo. Su evolucionado metabolismo y su gran fuerza le proporcionan gran velocidad y destreza. En vez de matar a su víctima le inserta un huevo y le inyecta un veneno que la convierte en un zombi. Poco después de que la víctima haya sido infestada una nueva crisálida surgirá de ella. Las crisálidas están asociadas con la raza de los hombres-serpiente.\"\n  STR_CHRYSSALID_AUTOPSY: \"Autopsia de Crisálida\"\n  STR_CHRYSSALID_AUTOPSY_UFOPEDIA: \"El exoesqueleto de esta criatura es muy duro pero sorprendentemente vulnerable a la munición explosiva. El cerebro está muy desarrollado y el ritmo de crecimiento de sus células muy alto. Lleva veinte huevos, que deposita en otros organismos. Constituye un elemento muy eficaz para aterrorizar a la población.\"\n  STR_FLOATER_UFOPEDIA: \"Los flotadores son soldados usados para sembrar el pánico entre los civiles. Son bestias depredadoras por naturaleza, mejorados cibernética y genéticamente para convertirlos en guerreros formidables. Se les ha extirpado la parte inferior del cuerpo y la mayoría de los órganos internos, y se les ha instalado un sistema de soporte vital. Este implante contiene una unidad antigravitatoria que permite a la criatura flotar de forma inestable en el aire.\"\n  STR_FLOATER_AUTOPSY: \"Autopsia de Flotador\"\n  STR_FLOATER_AUTOPSY_UFOPEDIA: \"Esta criatura ha sido alterada drásticamente por medio de la cirugía. El aparato que parece formar el núcleo de su cuerpo es un sistema de soporte vital que hace las veces de corazón, pulmones y aparato digestivo. Dicho aparato permite a la criatura sobrevivir en entornos extremadamente hostiles. El cerebro es más pequeño que el nuestro, pero sus órganos sensoriales están muy desarrollados.\"\n  STR_REAPER_UFOPEDIA: \"Este carnívoro bípedo tiene unas mandíbulas poderosas y un apetito voraz. Tiene varios implantes cerebrales que sirven para controlar sus actividades. Los instintos depredadores de esta criatura son de poca utilidad, excepto para aterrorizar y destruir. Los segadores suelen asociarse con los Flotadores.\"\n  STR_REAPER_AUTOPSY: \"Autopsia de Segador\"\n  STR_REAPER_AUTOPSY_UFOPEDIA: \"El segador tiene dos cerebros y dos corazones, los cuales le permiten seguir moviéndose incluso cuando está gravemente herido. Sin embargo, su piel peluda es altamente inflamable, por lo que esta criatura es vulnerable a las armas incendiarias.\"\n  STR_SECTOPOD_UFOPEDIA: \"Los Sectopodos son criaturas roboticas equipadas con una poderosa arma de rayos laser. El control de estas bestias mecánicas se realiza mediante un vinculo telepático con sus controladores: los Etereos. Los sectopodos son el arma de incursión mas poderosa disponible para las fuerzas alienígenas.\"\n  STR_SECTOPOD_AUTOPSY: \"Examen de Sectópodo\"\n  STR_SECTOPOD_AUTOPSY_UFOPEDIA: \"El robot esta sólidamente construido con un blindaje reforzado capaz de resistir la mayoría de formas de ataque, sobretodo las armas de plasma. No obstante sus circuitos sensores parecen ser particularmente vulnerables a las armas láser.\"\n  STR_CYBERDISC_UFOPEDIA: \"Este platillo volante en miniatura está equipado con un potente rayo de plasma y se usa para aterrorizar a la población . Su propulsión antigravedad le da una gran ventaja en terrenos difíciles. Su principal función es sembrar la destrucción y el terror al servicio de los sectoides.\"\n  STR_CYBERDISC_AUTOPSY: \"Examen de Ciberdisco\"\n  STR_CYBERDISC_AUTOPSY_UFOPEDIA: \"Los ciberdiscos tienen un blindaje muy bueno, especialmente resistente a los ataques con munición explosiva. El sistema de antigravedad de este ejemplar está demasiado dañado como para averiguar su funcionamiento.\"\n  STR_UFO_POWER_SOURCE_UFOPEDIA: \"La fuente de energía de las naves alienígenas consiste en un reactor antimateria que utiliza elerio (elemento 115) para crear poderosas ondas gravitatorias así como otras formas de energía. La conversión de materia en energía tiene una eficacia del 99%, gracias a lo cual pequeñas cantidades de elerio producen cantidades enormes de energía. Esta unidad se puede reproducir fácilmente usando aleaciones alienígenas.\"\n  STR_UFO_NAVIGATION_UFOPEDIA: \"Las naves alienígenas utilizan sofisticados ordenadores para viajar por la Tierra y por el espacio. El sistema está basado en procesadores ópticos que se distribuyen formando una red. El interfaz de control es relativamente sencillo: el navegante controla la dirección de las ondas de gravedad generadas por la fuente de energía para mover la nave en cualquier dirección. Los humanos pueden utilizar fácilmente este sistema, y se puede reproducir utilizando aleaciones alienígenas y otros elementos.\"\n  STR_UFO_CONSTRUCTION_UFOPEDIA: \"Las naves alienígenas constan de tres elementos principales: una fuente de energía, un sistema de navegación y un casco hecho de aleaciones alienígenas. El casco está especialmente diseñado para permitir que las ondas de gravedad sean dirigidas y controladas. También necesita una pequeña cantidad de elerio para alimentar la fuente de energía. Cuando comprendamos los principios de su construcción y las funciones de cada componente de este tipo de nave, podremos construirlas.\"\n  STR_ALIEN_FOOD_UFOPEDIA: \"Estas cámaras contienen varias enzimas que sirven para digerir las partes del cuerpo del ganado, otros animales e incluso humanos. El líquido resultante es consumido como alimento ya digerido, probablemente de forma directa al torrente sanguíneo. Esto sugiere una cierta dependencia de la Tierra para su alimentación: una simbiosis entre Tierra y sociedad alienígena.\"\n  STR_ALIEN_REPRODUCTION_UFOPEDIA: \"Estas cámaras contienen fetos alienígenas. El diseño de estos contenedores sugiere que los alienígenas que utilizan este proceso dependen totalmente de la reproducción en laboratorio. Los ricos nutrientes aseguran el rápido desarrollo de los fetos. Este sistema de producción en cadena podría generar miles de clones alienigenas en poco tiempo. El proceso podría ser adoptado fácilmente para la reproducción de humanos o de híbridos humano-alienígena.\"\n  STR_ALIEN_ENTERTAINMENT_UFOPEDIA: \"Lo más probable es que estas esferas tengan una función recreativa. El circuito psiónico estimula varios centros nerviosos del cerebro. El efecto es parecido al de los alucinógenos. Es la única prueba de que los alienígenas tienen pasatiempos culturales o recreativos.\"\n  STR_ALIEN_SURGERY_UFOPEDIA: \"Este equipo quirúrgico utiliza rayos láser para cortar y extraer ciertas partes del cuerpo del ganado y otros animales. La famosa mutilación de ganado se debe a esta extraña actividad alienígena. Es probable que estas partes se utilicen para fines alimenticios o genéticos.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"En el pasado miles de personas declararon haber sido abducidas por alienígenas; algunas repetidamente. La verdad es mucho más horrible. Los humanos son abducidos para ser objeto de investigaciones y observaciones. A los mejores especímenes se les extrae material genético. A las mujeres se les implantan fetos de híbridos humano-alienígena y se los extraen varios meses después. Quién sabe cuál es su siniestro propósito.\"\n  STR_ALIEN_ALLOYS_UFOPEDIA: \"Las naves alienígenas están hechas de aleaciones especiales con propiedades únicas. Son muy ligeras y resistentes, y se pueden moldear con métodos electromagnéticos. Este material se puede reproducir y utilizar en muchos tipos de procesos de fabricación.\"\n  STR_ELERIUM_115_UFOPEDIA: \"Este elemento tiene la propiedad poco común de generar energía antimateria cuando es bombardeado con ciertas partículas. Esto genera ondas gravitatorias y otras formas de energía. No existe de forma natural en nuestro sistema solar y no se puede reproducir.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"Está claro que estamos luchando una batalla perdida en la Tierra. Las hordas alienígenas nos superan en número. Lo mejor que podemos hacer es retrasar su avance. La única esperanza para la humanidad es atacar a los alienígenas en su origen. Nuestra investigación indica la existencia de una base de operaciones dentro de nuestro sistema solar. Los alienígenas afirman que este lugar es el centro de una civilización anterior a la existencia de la humanidad. Tenemos que localizar ese sitio lo antes posible. Pero antes hemos de capturar e interrogar a un lider alienígena para conseguir información detallada. Seguramente los ovnis más grandes contienen, al menos, un lider alienigena.\"\n  STR_THE_MARTIAN_SOLUTION_UFOPEDIA: \"Nuestra investigación se dirige ahora a Marte como base de operaciones alienígenas. La base está bien escondida y contiene todas las instalaciones de fabricación y de clonación necesarias para la infiltración en la Tierra. También parece haber un ordenador de control que dirige toda la operación. Parece ser que en la sociedad tipo colmena de los alienígenas hay una especia de abeja reina. Esa es su mayor debilidad: si eliminamos el \\\"cerebro\\\", el cuerpo morirá. Hay que acelerar nuestra investigación antes de que sea demasiado tarde. Para progresar tenemos que capturar a los altos mandos alienígenas - los comandantes - que sólo residen en bases alienígenas y cruceros de batalla.\"\n  STR_CYDONIA_OR_BUST_UFOPEDIA: \"Ahora está claro que las hordas alienígenas son controladas desde una base subterránea en Cydonia - una zona curiosa de Marte en la que hay pirámides de cinco lados y una estructura enorme similar a una cara humana. La civilización de Cydonia floreció en Marte hace muchos millones de años, pero no sabemos por qué desapareció o qué conexión tiene con la reciente actividad alienígena. Cualquiera que sea la explicación, tenemos que mandar una expedición a Cydonia. Es la única forma de derrotar a los alienígenas. Tenemos que destruir su cerebro dirigente. Necesitaremos una nave Avenger equipada con las mejores armas destructivas de que dispongamos. No hay nada más que podamos averiguar aquí, sólo queda esperar el resultado del asalto en Cydonia.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"CENTRAR EN SITIO-TIEMPO=5 Seg\"\n  STR_CANCEL_UC: \"CANCELAR\"\n  STR_NONE: \"Ninguno\"\n  STR_UNKNOWN: \"Desconocido\"\n  STR_POOR: \"Pobre\"\n  STR_AVERAGE: \"Normal\"\n  STR_GOOD: \"Bueno\"\n  STR_EXCELLENT: \"Excelente\"\n  STR_BUILD_NEW_BASE_UC: \"CONSTRUIR NUEVA BASE\"\n  STR_BASE_INFORMATION: \"INFORMACIÓN DE BASES\"\n  STR_EQUIP_CRAFT: \"EQUIPAR NAVE\"\n  STR_BUILD_FACILITIES: \"CONSTRUIR INSTALACIONES\"\n  STR_RESEARCH: \"INVESTIGAR\"\n  STR_MANUFACTURE: \"FABRICAR\"\n  STR_TRANSFER_UC: \"TRANSFERIR\"\n  STR_PURCHASE_RECRUIT: \"COMPRAR/RECLUTAR\"\n  STR_SACK: \"DESPEDIR\"\n  STR_SELL_SACK_UC: \"VENDER/DESPEDIR\"\n  STR_GEOSCAPE_UC: \"GEOESCAPE\"\n  STR_NAME: \"Nombre\"\n  STR_AREA: \"Zona\"\n  STR_BUILD_NEW_BASE: \"Construir base nueva\"\n  STR_CANCEL: \"Cancelar\"\n  STR_COST_UC: \"COSTE>\"\n  STR_CONSTRUCTION_TIME_UC: \"TIEMPO DE CONSTRUCCIÓN>\"\n  STR_DAY:\n    one: \"{N} día\"\n    many: \"{N} días\"\n    other: \"{N} días\"\n  STR_HOUR:\n    one: \"{N} hora\"\n    many: \"{N} horas\"\n    other: \"{N} horas\"\n  STR_MAINTENANCE_UC: \"MANTENIMIENTO>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Instalación\"\n  STR_CURRENT_RESEARCH: \"INVESTIGACIÓN EN CURSO\"\n  STR_SCIENTISTS_AVAILABLE: \"Científicos disponibles>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Científicos asignados>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Espacio de Laboratorio Disponible>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"PROYECTO DE INVESTIGACIÓN\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"CIENTÍFICOS ASIGNADOS\"\n  STR_PROGRESS: \"PROGRESO\"\n  STR_NEW_PROJECT: \"Nuevo proyecto\"\n  STR_CANCEL_PROJECT: \"CANCELAR PROYECTO\"\n  STR_NEW_RESEARCH_PROJECTS: \"Nuevos proyectos de investigación\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"CIENTIFICOS DISPONIBLES>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"ESPACIO DE LABORATORIO DISPONIBLE>{ALT}{0}\"\n  STR_INCREASE: \"Aumentar\"\n  STR_DECREASE: \"Disminuir\"\n  STR_START_PROJECT: \"INICIAR PROYECTO\"\n  STR_CURRENT_PRODUCTION: \"PRODUCCIÓN ACTUAL\"\n  STR_ENGINEERS_AVAILABLE: \"Ingenieros Disponibles>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Ingenieros destinados>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Espacio de Taller Disponible>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Fondos actuales>{ALT}{0}\"\n  STR_ITEM: \"ELEMENTO\"\n  STR_ENGINEERS__ALLOCATED: \"Ingenieros\"\n  STR_UNITS_PRODUCED: \"Unidades producidas\"\n  STR_TOTAL_TO_PRODUCE: \"Total a Producir\"\n  STR_COST__PER__UNIT: \"Coste{NEWLINE}por{NEWLINE}unidad\"\n  STR_DAYS_HOURS_LEFT: \"Dias/Horas restantes\"\n  STR_NEW_PRODUCTION: \"Nueva producción\"\n  STR_PRODUCTION_ITEMS: \"Artículos en producción\"\n  STR_CATEGORY: \"CATEGORÍA\"\n  STR_START_PRODUCTION: \"INICIAR FABRICACIÓN\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} Horas/ingeniero para producir una unidad\"\n  STR_COST_PER_UNIT_: \"Coste por unidad>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Espacio de trabajo necesario>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"MATERIALES ESPECIALES NECESARIOS\"\n  STR_ITEM_REQUIRED: \"ELEMENTO REQUERIDO\"\n  STR_UNITS_REQUIRED: \"UNIDADES NECESARIAS\"\n  STR_UNITS_AVAILABLE: \"UNIDADES DISPONIBLES\"\n  STR_STOP_PRODUCTION: \"DETENER PRODUCCIÓN\"\n  STR_ENGINEERS_AVAILABLE_UC: \"INGENIEROS DISPONIBLES>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"ESPACIO DE TALLER DISPONIBLE>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"BENEFICIOS MENSUALES>{ALT}{0}\"\n  STR_INCREASE_UC: \"AUMENTAR\"\n  STR_DECREASE_UC: \"DISMINUIR\"\n  STR_UNITS_TO_PRODUCE: \"Unidades a producir\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Comprar/Contratar personal\"\n  STR_COST_OF_PURCHASES: \"Coste de Compras>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"COSTE POR UNIDAD\"\n  STR_QUANTITY_UC: \"CANTIDAD\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"PERSONAL DISPONIBLE:PERSONAL TOTAL>\"\n  STR_SOLDIERS: \"Soldados\"\n  STR_SCIENTISTS: \"Científicos\"\n  STR_ENGINEERS: \"ingenieros\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"ESPACIO USADO:ESPACIO DISPONIBLE>\"\n  STR_LIVING_QUARTERS: \"Alojamientos\"\n  STR_STORES: \"Almacenes\"\n  STR_LABORATORIES: \"Laboratorios\"\n  STR_WORK_SHOPS: \"Talleres\"\n  STR_HANGARS: \"Hangares\"\n  STR_SHORT_RANGE_DETECTION: \"Detección de corto alcance\"\n  STR_DEFENSE_STRENGTH: \"Fuerza defensiva\"\n  STR_TRANSFERS_UC: \"TRANSFERENCIAS\"\n  STR_TRANSFERS: \"Transferencias\"\n  STR_ARRIVAL_TIME_HOURS: \"Hora de llegada (horas)\"\n  STR_COST_: \"Coste>{ALT}{0}\"\n  STR_AREA_: \"Area>{ALT}{0}\"\n  STR_BASE_NAME: \"¿Nombre de la base?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"SELECCIONAR POSICIÓN DEL ASCENSOR DE ACCESO\"\n  STR_TRANSFER: \"Transferir\"\n  STR_AMOUNT_TO_TRANSFER: \"CANTIDAD A TRANSFERIR\"\n  STR_SELECT_DESTINATION_BASE: \"Seleccionar base de destino\"\n  STR_COST: \"Coste\"\n  STR_VICTORY_1: \"Al entrar en la cámara se puede ver al cerebro alienígena: el objeto de tu búsqueda. Antes de dispararle, se comunica contigo mediante una pantalla que hay en su base. Te implora que antes de apretar el gatillo escuches las razones por las que deberías dejarle vivir.\"\n  STR_VICTORY_2: \"El cerebro dice: \\\"Hace muchos millones de años el planeta al que llamáis Marte estaba vivo. Nuestra civilización llevó vida a ese planeta estéril igual que la llevó al tuyo. Durante millones de años hemos visitado tu planeta y desarrollado genéticamente tu especie. No podéis matarnos, sois parte de nosotros...\"\n  STR_VICTORY_3: \"Este es el centro de la civilización marciana. Estas pirámides fueron levantadas millones de años antes que las vuestras por una especie de la que vosotros descendéis. Ningún planeta está fuera de nuestro alcance. Este poder podría ser vuestro dentro de poco. Todo lo que os pedimos es vuestra cooperación.\"\n  STR_GAME_OVER_1: \"Los alienígenas intentan exterminar a la humanidad destruyendo las ciudades y envenenando el aire y el mar. La resistencia de los ejércitos de la Tierra es inútil frente a su enorme superioridad tecnológica. Las generaciones que sobreviven sufren terribles mutaciones mientras intentan escapar de la destrucción alienígena. Son encerradas en campos de esclavos para que ayuden a transformar la Tierra en una colonia alienígena que forma parte de algun imperio desconocido.\"\n  STR_GAME_OVER_2: \"Los conocimientos adquiridos durante el proyecto X-Com se han perdido para siempre. Ha fracasado en su intento por salvar la Tierra.\"\n  STR_VICTORY_4: \"El cerebro alienígena es interrumpido por una ráfaga de plasma caliente y la totalidad de las fuerzas alienígenas es derrotada.\"\n  STR_VICTORY_5: \"Una vez que los alienígenas pierden Marte, pierden también la Tierra. El proyecto de investigación X-Com no tarda mucho en hacer posible una vez más el florecimiento de la humanidad, y ésta asume el control de Marte. La amenaza alienígena ha desaparecido, pero ¿por cuánto tiempo? Nadie lo sabe...\"\n  STR_YOU_HAVE_FAILED: \"Has fracasado en tu misión de detener la matanza alienígena. Las naciones patrocinadoras, una tras otra, firman pactos con los alienígenas en los que éstos les prometen tecnología, prosperidad y paz. Sin embargo pronto se dan cuenta de que los invasores tienen planes muy diferentes...\"\n  STR_TOTAL_UC: \"TOTAL\"\n  STR_INCOME: \"Ingresos\"\n  STR_EXPENDITURE: \"Gastos\"\n  STR_MAINTENANCE: \"Mantenimiento\"\n  STR_BALANCE: \"Balance\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"Actividad OVNI en zonas\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"Actividad OVNI en países\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"Actividad X-Com en Zonas\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"Actividad X-Com en Países\"\n  STR_FINANCE: \"Finanzas\"\n  STR_DATE_FIRST: \"{0}º\"\n  STR_DATE_SECOND: \"{0}º\"\n  STR_DATE_THIRD: \"  {0}º\"\n  STR_DATE_FOURTH: \"{0}º\"\n  STR_FINANCE_THOUSANDS: \"$1000's\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"No hay suficientes materiales para producir{NEWLINE}{0}{NEWLINE}en{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"No hay dinero suficiente para producir {NEWLINE}{0}{NEWLINE}en{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"Producción de{NEWLINE}{0}{NEWLINE}en{NEWLINE}{1}{NEWLINE}completada\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"Construcción de{NEWLINE}{0}{NEWLINE}en{NEWLINE}{1}{NEWLINE}completada\"\n  STR_OK_5_SECONDS: \"OK - 5 seg\"\n  STR_RESEARCH_COMPLETED: \"Investigación finalizada\"\n  STR_VIEW_REPORTS: \"VER INFORMES\"\n  STR_WE_CAN_NOW_RESEARCH: \"Preparados para investigar\"\n  STR_WE_CAN_NOW_PRODUCE: \"Preparados para fabricar\"\n  STR_SUNDAY: \"DOMINGO\"\n  STR_MONDAY: \"LUNES\"\n  STR_TUESDAY: \"MARTES\"\n  STR_WEDNESDAY: \"MIÉRCOLES\"\n  STR_THURSDAY: \"JUEVES\"\n  STR_FRIDAY: \"VIERNES\"\n  STR_SATURDAY: \"SÁBADO\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"No hay suficiente {0} para repostar {1} en {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"No hay suficiente {0} para rearmar{1} en {2}\"\n  STR_UFO_IS_NOT_RECOVERED: \"OVNI no recuperado\"\n  STR_UFO_IS_RECOVERED: \"OVNI recuperado\"\n  STR_CRAFT_IS_LOST: \"Nave destruida\"\n  STR_TERROR_CONTINUES: \"La incursión alienígena continúa\"\n  STR_ALIENS_DEFEATED: \"Alienígenas derrotados\"\n  STR_BASE_IS_LOST: \"La base se ha perdido\"\n  STR_BASE_IS_SAVED: \"La base se ha salvado\"\n  STR_ALIEN_BASE_STILL_INTACT: \"Base alienígena intacta\"\n  STR_ALIEN_BASE_DESTROYED: \"Base alienígena destruida\"\n  STR_ALIENS_KILLED: \"BAJAS ALIENÍGENAS\"\n  STR_ALIEN_CORPSES_RECOVERED: \"CADÁVERES ALIENÍGENAS RECUPERADOS\"\n  STR_LIVE_ALIENS_RECOVERED: \"ALIENÍGENAS VIVOS CAPTURADOS\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"ARTEFACTOS ALIENÍGENAS RECUPERADOS\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"CONTROL DE LA BASE ALIENÍGENA DESTRUIDO\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"BAJAS CIVILES CAUSADAS POR LOS ALIENÍGENAS\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"BAJAS CIVILES CAUSADAS POR X-COM\"\n  STR_CIVILIANS_SAVED: \"CIVILES A SALVO\"\n  STR_XCOM_OPERATIVES_KILLED: \"BAJAS X-COM\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"OPERATIVOS X-COM DESAPARECIDOS EN ACCIÓN\"\n  STR_TANKS_DESTROYED: \"TANQUES DESTRUIDOS\"\n  STR_XCOM_CRAFT_LOST: \"NAVE X-COM DESTRUIDA\"\n  STR_UFO_RECOVERY: \"RECUPERACIÓN DE OVNI\"\n  STR_ALIEN_BASE_RECOVERY: \"RECUPERACIÓN DE BASE ALIENÍGENA\"\n  STR_BASE_UNDER_ATTACK: \"{0} bajo ataque!\"\n  STR_BASE_DEFENSES_INITIATED: \"INICIADA DEFENSA DE LA BASE\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"¡ESCUDO DE GRAVEDAD REPELE OVNI!\"\n  STR_FIRING: \"DISPARANDO\"\n  STR_HIT: \"¡TOCADO!\"\n  STR_UFO_DESTROYED: \"¡OVNI DESTRUIDO!\"\n  STR_MISSED: \"¡DISPARO FALLIDO!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Vender artículos/Despedir personal\"\n  STR_VALUE_OF_SALES: \"VALOR DE LAS VENTAS> {ALT}{0}\"\n  STR_FUNDS: \"FONDOS> {ALT}{0}\"\n  STR_SELL_SACK: \"Vender/Despedir\"\n  STR_VALUE: \"Valor\"\n  STR_CRAFT_: \"NAVE> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"RECUPERACIÓN DE OVNI ESTRELLADO\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"Extreme la precaución - Es posible que haya operativos en el OVNI o alrededor del lugar del accidente. La Misión tendrá éxito cuando todas las unidades enemigas hayan sido eliminadas o neutralizadas. La recuperación de restos del OVNI, artefactos y cadáveres alienígenas puede entonces ser iniciada. Para abortar la misión regrese los operativos X-Com al vehículo de transporte y haga clic en el icono 'Abortar Misión'.\"\n  STR_UFO_GROUND_ASSAULT: \"ASALTO A OVNI ATERRIZADO\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"Explore el punto de amerizaje y, si es posible, gane acceso al OVNI. Esta misión se completará cuando todas las unidades enemigas hayan sido eliminadas o neutralizadas. La recuperación de restos OVNI, tecnología y cadáveres alienígenas podrá entonces ser iniciada. Para abortar la misión regrese los operativos X-Com al vehículo de transporte y haga clic en el icono 'Abortar Misión'.\"\n  STR_BASE_DEFENSE: \"DEFENSA DE LA BASE\"\n  STR_BASE_UC_: \"BASE> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"Una nave alienígena ha aterrizado muy cerca. Nuestra base está en peligro. Según el procedimiento habitual, se ha evacuado todo el personal no combatiente y las naves de X-Com. Los alienígenas accederán a la base por las puertas del hangar o por el ascensor de acceso. Defienda la base y sus instalaciones vitales a toda costa, es una lucha a vida o muerte. Si presiona en el icono de 'Abortar misión' aceptará la derrota y perderá la base.\"\n  STR_ALIEN_BASE_ASSAULT: \"ASALTO A BASE ALIENíGENA\"\n  STR_ALIEN_BASE_ASSAULT_BRIEFING: \"Los operativos X-COM han entrado en una base alienígena. Hay que destruir el centro de control para que la base quede inservible. El objetivo de la misión estara completo cuando elimine a todos los enemigos o cuando regrese sus hombres al área verde de salida (presione el icono de 'Abortar misión' para escapar).\"\n  STR_CYDONIA_BRIEFING: \"Has llegado a Cydonia. Entras en un gran complejo subterráneo cercano a la Esfinge Marciana. Tienes que destruir al cerebro alienígena que controla todas sus actividades. El destino de la humanidad está en tus manos.\"\n  STR_TERROR_MISSION: \"MISIÓN DE INCURSIÓN\"\n  STR_TERROR_MISSION_BRIEFING: \"El objetivo de la misión es eliminar o neutralizar todas las unidades enemigas. Debe intentar salvar a cualquier civil que haya en el área. Para abortar la misión, regrese los operativos X-Com al vehículo de transporte y presione el icono de 'Abortar misión'.\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"¡NO HAY HANGARES LIBRES PARA CONSTRUIR NAVES!{SMALLLINE}Cada nave asignada o transferida a una base, comprada o construida ocupa un hangar. Construye un nuevo hangar o traslada una nave a otra base.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"¡NO HAY HANGARES LIBRES PARA COMPRAR NAVES!{SMALLLINE}Cada nave asignada o transferida a una base, comprada o construida ocupa un hangar. Construye un nuevo hangar o traslada una nave a otra base.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"¡NO HAY HANGARES LIBRES PARA TRASLADAR NAVES{SMALLLINE}Cada nave asignada o transferida a una base, comprada o construida ocupa un hangar. Construye un nuevo hangar o traslada una nave a otra base.\"\n  STR_CANNOT_BUILD_HERE: \"¡NO PUEDES CONSTRUIR AQUÍ!{SMALLLINE}Sólo junto a una instalación finalizada.\"\n  STR_NO_FREE_ACCOMODATION: \"¡NO HAY ALOJAMIENTO DISPONIBLE!{SMALLLINE}La base de destino no tiene espacio suficiente en la zona de alojamiento.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"¡NO HAY SUFICIENTE ESPACIO PARA TRABAJAR!{SMALLLINE}Construye un taller nuevo o reduce los trabajos relacionados con otros proyectos.\"\n  STR_NOT_ENOUGH_MONEY: \"¡NO HAY DINERO SUFICIENTE!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"¡NO HAY SUFICIENTE ESPACIO DE ALMACENAJE!{SMALLLINE}Construye un almacén nuevo o traslada las existencias a otras bases.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"¡NO HAY SUFICIENTE ESPACIO HABITABLE!{SMALLLINE}Construye nuevos alojamientos o traslada personal a otras bases.\"\n  STR_LAUNCH_INTERCEPTION: \"INICIAR INTERCEPCIÓN\"\n  STR_CRAFT: \"NAVE\"\n  STR_STATUS: \"SITUACIÓN\"\n  STR_BASE: \"BASE\"\n  STR_READY: \"LISTO\"\n  STR_OUT: \"FUERA\"\n  STR_REPAIRS: \"REPARACIONES\"\n  STR_REFUELLING: \"REPOSTANDO\"\n  STR_REARMING: \"REARMANDO\"\n  STR_TARGET: \"OBJETIVO: {0}\"\n  STR_WAY_POINT: \"PUNTO DE DESTINO\"\n  STR_ARE_YOU_SURE_CYDONIA: \"¿Estás seguro de que quieres mandar esta nave a Cydonia en una misión?\"\n  STR_YES: \"SÍ\"\n  STR_NO: \"NO\"\n  STR_SELECT_DESTINATION: \"SELECCIONAR DESTINO\"\n  STR_CYDONIA: \"CYDONIA\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"SELECCIONAR EMPLAZAMIENTO DE LA{NEWLINE}NUEVA BASE\"\n  STR_RETURN_TO_BASE: \"REGRESAR A LA BASE\"\n  STR_SELECT_NEW_TARGET: \"SELECCIONAR OTRO BLANCO\"\n  STR_PATROL: \"PATRULLAR\"\n  STR_STATUS_: \"SITUACIÓN>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"AVERIADO - REGRESA A LA BASE\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"POCO COMBUSTIBLE - REGRESA A LA BASE\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"MISIÓN COMPLETADA - REGRESANDO A LA BASE\"\n  STR_PATROLLING: \"PATRULLANDO\"\n  STR_TAILING_UFO: \"SIGUIENDO A UN OVNI\"\n  STR_INTERCEPTING_UFO: \"INTERCEPTANDO OVNI-{0}\"\n  STR_RETURNING_TO_BASE: \"REGRESANDO A LA BASE\"\n  STR_DESTINATION_UC_: \"DESTINO: {0}\"\n  STR_BASE_UC: \"BASE>{ALT}{0}\"\n  STR_SPEED_: \"VELOCIDAD>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"VELOCIDAD MAXIMA>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"ALTITUD>{ALT}{0}\"\n  STR_VERY_LOW: \"MUY POCA\"\n  STR_LOW_UC: \"POCA\"\n  STR_HIGH_UC: \"BASTANTE\"\n  STR_VERY_HIGH: \"MUY ALTA\"\n  STR_FUEL: \"COMBUSTIBLE>{ALT}{0}\"\n  STR_WEAPON_ONE: \"ARMA-1>{ALT}{0}\"\n  STR_NONE_UC: \"NINGUNA\"\n  STR_ROUNDS_: \"DISPAROS>{ALT}{0}\"\n  STR_WEAPON_TWO: \"ARMA-2>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"NAVE DE INTERCEPCIÓN\"\n  STR_BASE_: \"Base>{0}\"\n  STR_NAME_UC: \"NOMBRE\"\n  STR_AMMO_: \"MUNICION>{ALT}{0}\"\n  STR_CREW: \"TRIPULACIÓN\"\n  STR_EQUIPMENT_UC: \"EQUIPO\"\n  STR_ARMOR: \"BLINDAJE\"\n  STR_MAX: \"MAX>{ALT}{0}\"\n  STR_ROOKIE: \"Recluta\"\n  STR_SQUADDIE: \"Soldado raso\"\n  STR_SERGEANT: \"Sargento\"\n  STR_CAPTAIN: \"Capitán\"\n  STR_COLONEL: \"Coronel\"\n  STR_COMMANDER: \"Comandante\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Selecciona equipo para {0}\"\n  STR_SORT_BY: \"ORDENAR POR...\"\n  STR_ORIGINAL_ORDER: \"ORDEN ORIGINAL\"\n  STR_MISSIONS2: \"MISIONES\"\n  STR_KILLS2: \"MUERTES\"\n  STR_WOUND_RECOVERY2: \"RECUPERACIÓN DE HERIDAS\"\n  STR_SPACE_AVAILABLE: \"ESPACIO DISPONIBLE>{ALT}{0}\"\n  STR_SPACE_USED: \"ESPACIO USADO>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"ESPACIO USADO\"\n  STR_RANK: \"RANGO\"\n  STR_WOUNDED: \"HERIDO\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Equipo para {0}\"\n  STR_DEFENSE_VALUE: \"Valor defensivo\"\n  STR_HIT_RATIO: \"Media de impactos\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}preparado para{NEWLINE}aterrizar cerca de{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"¿Iniciar la misión?\"\n  STR_SELECT_ARMAMENT: \"Seleccionar armamento\"\n  STR_AMMUNITION_AVAILABLE: \"MUNICIÓN DISPONIBLE\"\n  STR_ARMAMENT: \"ARMAMENTO\"\n  STR_NOT_AVAILABLE: \"N.D.\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"SELECCIONA BLINDAJE PARA{NEWLINE}{0}\"\n  STR_TYPE: \"TIPO\"\n  STR_PERSONAL_ARMOR_UC: \"BLINDAJE PERSONAL\"\n  STR_POWER_SUIT_UC: \"TRAJE MECANICO\"\n  STR_FLYING_SUIT_UC: \"TRAJE VOLADOR\"\n  STR_SELECT_ARMOR: \"Selección de Blindaje\"\n  STR_NORTH: \"NORTE\"\n  STR_NORTH_EAST: \"NORESTE\"\n  STR_EAST: \"ESTE\"\n  STR_SOUTH_EAST: \"SURESTE\"\n  STR_SOUTH: \"SUR\"\n  STR_SOUTH_WEST: \"SUROESTE\"\n  STR_WEST: \"OESTE\"\n  STR_NORTH_WEST: \"NOROESTE\"\n  STR_SELECT_ACTION: \"SELECCIONAR ACCIÓN\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"CONTINUAR PERSECUCIÓN DE INTERCEPCIÓN\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"PERSECUCIÓN SIN INTERCEPCIÓN\"\n  STR_VERY_LARGE: \"MUY GRANDE\"\n  STR_LARGE: \"GRANDE\"\n  STR_MEDIUM_UC: \"NORMAL\"\n  STR_SMALL: \"PEQUEÑO\"\n  STR_VERY_SMALL: \"MUY PEQUEÑO\"\n  STR_GROUNDED: \"EN TIERRA\"\n  STR_DETECTED: \"Detectado\"\n  STR_SIZE_UC: \"TAMAÑO\"\n  STR_ALTITUDE: \"ALTITUD\"\n  STR_HEADING: \"RUMBO\"\n  STR_SPEED: \"VELOCIDAD\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"CENTRAR EN OVNI-TIEMPO=5 Seg\"\n  STR_TRACKING_LOST: \"RASTRO PERDIDO\"\n  STR_REDIRECT_CRAFT: \"CAMBIAR RUMBO\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"IR A ÚLTIMA POSICIÓN CONOCIDA DEL OVNI \"\n  STR_UFO_: \"OVNI-{0}\"\n  STR_ALIEN_BASE_: \"BASE ALIENIGENA-{0}\"\n  STR_CRASH_SITE_: \"LUGAR DE IMPACTO-{0}\"\n  STR_LANDING_SITE_: \"LUGAR DE ATERRIZAJE-{0}\"\n  STR_WAY_POINT_: \"PUNTO DE DESTINO-{0}\"\n  STR_TERROR_SITE: \"LUGAR DE INCURSION-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}ha alcanzado{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"Está patrullando\"\n  STR_ALIEN_ORIGINS: \"Origen de los alienígenas\"\n  STR_THE_MARTIAN_SOLUTION: \"La solución marciana\"\n  STR_CYDONIA_OR_BUST: \"Cydonia o reventar!\"\n  STR_UFOPAEDIA: \"Ovnipedia\"\n  STR_XCOM_CRAFT_ARMAMENT: \"NAVES Y ARMAS DE X-COM\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"PLATAFORMAS DE ARMAS PESADAS\"\n  STR_WEAPONS_AND_EQUIPMENT: \"EQUIPO Y ARMAS\"\n  STR_ALIEN_ARTIFACTS: \"ARTEFACTOS ALIENÍGENAS\"\n  STR_BASE_FACILITIES: \"INSTALACIONES DE LA BASE\"\n  STR_ALIEN_LIFE_FORMS: \"CRIATURAS ALIENÍGENAS\"\n  STR_ALIEN_RESEARCH_UC: \"INVESTIGACIÓN ALIENÍGENA\"\n  STR_UFO_COMPONENTS: \"COMPONENTES OVNI\"\n  STR_UFOS: \"OVNIS\"\n  STR_SELECT_ITEM: \"SELECCIONAR ARTÍCULO\"\n  STR_ACCELERATION: \"ACELERACION>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"CAPACIDAD DE COMBUSTIBLE>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"RANURAS DE ARMAS>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"RESISTENCIA A LOS DAÑOS>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"ESPACIO DE CARGA>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"CAPACIDAD PAP>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Daño\"\n  STR_RANGE: \"Alcance\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Precisión\"\n  STR_RE_LOAD_TIME: \"Tiempo de recarga\"\n  STR_SECONDS: \"{0}s\"\n  STR_DAMAGE_ARMOR_PIERCING: \"PERFORADORA\"\n  STR_DAMAGE_INCENDIARY: \"INCENDIARIA\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"EXPLOSIVO\"\n  STR_DAMAGE_LASER_BEAM: \"RAYO LÁSER\"\n  STR_DAMAGE_PLASMA_BEAM: \"RAYO DE PLASMA\"\n  STR_DAMAGE_STUN: \"ATURDIDORA\"\n  STR_DAMAGE_MELEE: \"DAÑO CUERPO A CUERPO\"\n  STR_DAMAGE_ACID: \"ÁCIDO\"\n  STR_DAMAGE_SMOKE: \"HUMO\"\n  STR_SHOT_TYPE: \"TIPO DE MUNICIÓN\"\n  STR_ACCURACY_UC: \"PRECISIÓN\"\n  STR_TIME_UNIT_COST: \"COSTE UT\"\n  STR_DAMAGE_UC: \"DAÑO\"\n  STR_AMMO: \"MUNICIÓN\"\n  STR_SHOT_TYPE_AUTO: \"Auto\"\n  STR_SHOT_TYPE_SNAP: \"Rápido\"\n  STR_SHOT_TYPE_AIMED: \"Precisión\"\n  STR_CONSTRUCTION_TIME: \"Tiempo de construcción\"\n  STR_CONSTRUCTION_COST: \"Coste de construcción\"\n  STR_MAINTENANCE_COST: \"Coste de mantenimiento\"\n  STR_LOW: \"Insuficiente\"\n  STR_MEDIUM: \"Media\"\n  STR_HIGH: \"Suficiente\"\n  STR_CRAFT_WEAPON: \"Arma de la nave\"\n  STR_CRAFT_AMMUNITION: \"Munición de la nave\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Plataforma de armas pesadas\"\n  STR_WEAPON: \"Arma\"\n  STR_AMMUNITION: \"Munición\"\n  STR_EQUIPMENT: \"Equipo\"\n  STR_ALIEN_CORPSE: \"Cadáver alienígena\"\n  STR_UFO_COMPONENT: \"Componente de OVNI\"\n  STR_PERSONAL_ARMOR: \"Blindaje personal\"\n  STR_RAW_MATERIALS: \"Materias primas\"\n  STR_HWP_CANNON_SHELLS: \"Munición para cañón PAP\"\n  STR_ALIEN: \"Alienígena\"\n  STR_SECTOID: \"Sectoide\"\n  STR_SNAKEMAN: \"Hombre-serpiente\"\n  STR_ETHEREAL: \"Etéreo\"\n  STR_MUTON: \"Mutante\"\n  STR_FLOATER: \"Flotador\"\n  STR_CELATID: \"Celátido\"\n  STR_SILACOID: \"Silacoide\"\n  STR_CHRYSSALID: \"Crisálida\"\n  STR_ZOMBIE: \"Zombi\"\n  STR_REAPER: \"Segador\"\n  STR_SECTOPOD: \"Sectópodo\"\n  STR_CYBERDISC: \"Ciberdisco\"\n  STR_LIVE_COMMANDER: \"Comandante\"\n  STR_LIVE_LEADER: \"Líder\"\n  STR_LIVE_ENGINEER: \"Ingeniero\"\n  STR_LIVE_MEDIC: \"Médico\"\n  STR_LIVE_NAVIGATOR: \"Navegante\"\n  STR_LIVE_SOLDIER: \"Soldado\"\n  STR_LIVE_TERRORIST: \"Terrorista\"\n  STR_FLOATER_SOLDIER: \"Soldado Flotador\"\n  STR_FLOATER_NAVIGATOR: \"Navegante Flotador\"\n  STR_FLOATER_MEDIC: \"Médico Flotador\"\n  STR_FLOATER_ENGINEER: \"Técnico Flotador\"\n  STR_FLOATER_LEADER: \"Lider Flotador\"\n  STR_FLOATER_COMMANDER: \"Comandante Flotador\"\n  STR_SECTOID_SOLDIER: \"Soldado Sectoide\"\n  STR_SECTOID_NAVIGATOR: \"Navegante Sectoide\"\n  STR_SECTOID_MEDIC: \"Médico Sectoide\"\n  STR_SECTOID_ENGINEER: \"Técnico Sectoide\"\n  STR_SECTOID_LEADER: \"Líder Sectoide\"\n  STR_SECTOID_COMMANDER: \"Comandante Sectoide\"\n  STR_SNAKEMAN_SOLDIER: \"Soldado Hombre-serpiente\"\n  STR_SNAKEMAN_NAVIGATOR: \"Navegante Hombre-serpiente\"\n  STR_SNAKEMAN_ENGINEER: \"Técnico Hombre-serpiente\"\n  STR_SNAKEMAN_LEADER: \"Líder Hombre-serpiente\"\n  STR_SNAKEMAN_COMMANDER: \"Comandante Hombre-serpiente\"\n  STR_MUTON_SOLDIER: \"Soldado Mutante\"\n  STR_MUTON_NAVIGATOR: \"Navegante Mutante\"\n  STR_MUTON_ENGINEER: \"Técnico Mutante\"\n  STR_ETHEREAL_SOLDIER: \"Soldado Etéreo\"\n  STR_ETHEREAL_LEADER: \"Lider Etéreo\"\n  STR_ETHEREAL_COMMANDER: \"Comandante Etéreo\"\n  STR_CYBERDISC_TERRORIST: \"Terrorista Ciberdisco\"\n  STR_REAPER_TERRORIST: \"Terrorista Segador\"\n  STR_CHRYSSALID_TERRORIST: \"Terrorista Crisálida\"\n  STR_CELATID_TERRORIST: \"Terrorista Celátido\"\n  STR_SILACOID_TERRORIST: \"Terrorista Silacoide\"\n  STR_SECTOPOD_TERRORIST: \"Terrorista Sectópodo\"\n  STR_UFO_POWER_SOURCE: \"Fuente de energía de OVNI\"\n  STR_UFO_NAVIGATION: \"Navegación de OVNI\"\n  STR_UFO_CONSTRUCTION: \"Construcción de OVNI\"\n  STR_ALIEN_FOOD: \"Comida alienígena\"\n  STR_ALIEN_REPRODUCTION: \"Reproducción alienígena\"\n  STR_ALIEN_ENTERTAINMENT: \"Diversión alienígena\"\n  STR_ALIEN_SURGERY: \"Cirugía alienígena\"\n  STR_EXAMINATION_ROOM: \"Sala de exámenes\"\n  STR_ALIEN_ALLOYS: \"Aleaciones alienígenas\"\n  STR_ALIEN_HABITAT: \"Hábitat alienígena\"\n  STR_POWER_SUIT: \"Traje Automático\"\n  STR_FLYING_SUIT: \"Traje volador\"\n  STR_HWP_ROCKETS: \"Cohetes PAP\"\n  STR_HWP_FUSION_BOMB: \"Bombas de fusión PAP\"\n  STR_LASER_WEAPONS: \"Armas de rayos láser\"\n  STR_NEW_FIGHTER_CRAFT: \"Nueva nave caza\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Nuevo caza-transporte\"\n  STR_ULTIMATE_CRAFT: \"Lo último en naves\"\n  STR_LASER_PISTOL: \"Pistola láser\"\n  STR_LASER_RIFLE: \"Rifle láser\"\n  STR_HEAVY_LASER: \"Láser pesado\"\n  STR_LASER_CANNON: \"Cañón láser\"\n  STR_PLASMA_CANNON: \"Cañón de plasma\"\n  STR_FUSION_MISSILE: \"Misil de fusión\"\n  STR_LASER_DEFENSE: \"Defensas láser\"\n  STR_PLASMA_DEFENSE: \"Defensas de plasma\"\n  STR_FUSION_DEFENSE: \"Defensas de fusión\"\n  STR_GRAV_SHIELD: \"Escudo de gravedad\"\n  STR_MIND_SHIELD: \"Escudo mental\"\n  STR_PSI_LAB: \"Laboratorio psiónico\"\n  STR_MOTION_SCANNER: \"Escáner de movimiento\"\n  STR_MEDI_KIT: \"Botiquín\"\n  STR_TANK_CANNON: \"Tanque/Cañón\"\n  STR_TANK_ROCKET_LAUNCHER: \"Tanque/Lanzacohetes\"\n  STR_TANK_LASER_CANNON: \"Tanque/Cañón láser\"\n  STR_HOVERTANK_PLASMA: \"Tanque volador/Plasma\"\n  STR_HOVERTANK_LAUNCHER: \"Tanque volador/Lanzador\"\n  STR_STINGRAY_LAUNCHER: \"Lanzamisiles Stingray\"\n  STR_AVALANCHE_LAUNCHER: \"Lanzamisiles Avalancha\"\n  STR_CANNON: \"Cañón\"\n  STR_FUSION_BALL_LAUNCHER: \"Lanzador de bolas de fusión\"\n  STR_PLASMA_BEAM: \"Rayo de plasma\"\n  STR_STINGRAY_MISSILES: \"Misiles Stingray\"\n  STR_AVALANCHE_MISSILES: \"Misil Avalancha\"\n  STR_CANNON_ROUNDS_X50: \"Balas del cañón(x50)\"\n  STR_FUSION_BALL: \"Bola de fusión\"\n  STR_SOLDIER: \"Soldado\"\n  STR_SCIENTIST: \"Científico\"\n  STR_ENGINEER: \"Ingeniero\"\n  STR_NORTH_AMERICA: \"Norteamérica\"\n  STR_ARCTIC: \"Ártico\"\n  STR_ANTARCTICA: \"Antártida\"\n  STR_SOUTH_AMERICA: \"Sudamérica\"\n  STR_EUROPE: \"Europa\"\n  STR_NORTH_AFRICA: \"Norte de África\"\n  STR_SOUTHERN_AFRICA: \"Sur de África\"\n  STR_CENTRAL_ASIA: \"Asia Central\"\n  STR_SOUTH_EAST_ASIA: \"Sureste de Asia\"\n  STR_SIBERIA: \"Siberia\"\n  STR_AUSTRALASIA: \"Australia\"\n  STR_PACIFIC: \"Océano Pacífico\"\n  STR_NORTH_ATLANTIC: \"Atlántico Norte\"\n  STR_SOUTH_ATLANTIC: \"Atlántico Sur\"\n  STR_INDIAN_OCEAN: \"Océano Índico\"\n  STR_ALIEN_RESEARCH: \"Investigación alienígena\"\n  STR_ALIEN_HARVEST: \"Cosecha alienígena\"\n  STR_ALIEN_ABDUCTION: \"Abducción alienígena\"\n  STR_ALIEN_INFILTRATION: \"Infiltración alienígena\"\n  STR_ALIEN_BASE: \"Base alienígena\"\n  STR_ALIEN_TERROR: \"Incursión alienígena\"\n  STR_ALIEN_RETALIATION: \"Represalia alienígena\"\n  STR_ALIEN_SUPPLY: \"Suministro alienígena\"\n  STR_MAXIMUM_SPEED: \"Velocidad máxima\"\n  STR_HYPER_WAVE_DECODER_UC: \"DESCODIFICADOR DE HIPERONDAS\"\n  STR_SKYRANGER: \"SKYRANGER\"\n  STR_LIGHTNING: \"LIGHTNING\"\n  STR_AVENGER: \"VENGADOR\"\n  STR_INTERCEPTOR: \"INTERCEPTOR\"\n  STR_FIRESTORM: \"FIRESTORM\"\n  STR_UFO: \"OVNI\"\n  STR_STINGRAY: \"STINGRAY\"\n  STR_AVALANCHE: \"AVALANCHA\"\n  STR_CANNON_UC: \"CAÑÓN\"\n  STR_FUSION_BALL_UC: \"BOLA DE FUSIÓN\"\n  STR_LASER_CANNON_UC: \"CAÑÓN LÁSER\"\n  STR_PLASMA_BEAM_UC: \"RAYO DE PLASMA\"\n  STR_DAMAGE_CAPACITY: \"Resistencia a los daños\"\n  STR_WEAPON_POWER: \"Potencia del arma\"\n  STR_WEAPON_RANGE: \"Alcance del arma\"\n  STR_ACCESS_LIFT: \"Ascensor de acceso\"\n  STR_LABORATORY: \"Laboratorio\"\n  STR_WORKSHOP: \"Taller\"\n  STR_SMALL_RADAR_SYSTEM: \"Radar de corto alcance\"\n  STR_LARGE_RADAR_SYSTEM: \"Radar de largo alcance\"\n  STR_MISSILE_DEFENSES: \"Defensas de misiles\"\n  STR_GENERAL_STORES: \"Almacenes generales\"\n  STR_ALIEN_CONTAINMENT: \"Contención alienígena\"\n  STR_LASER_DEFENSES: \"Defensas láser\"\n  STR_PLASMA_DEFENSES: \"Defensas de plasma\"\n  STR_FUSION_BALL_DEFENSES: \"Defensas bolas fusión\"\n  STR_PSIONIC_LABORATORY: \"Laboratorio psiónico\"\n  STR_HYPER_WAVE_DECODER: \"Descodificador de hiperondas\"\n  STR_HANGAR: \"Hangar\"\n  STR_USA: \"EE.UU.\"\n  STR_RUSSIA: \"RUSIA\"\n  STR_UK: \"REINO UNIDO\"\n  STR_FRANCE: \"FRANCIA\"\n  STR_GERMANY: \"ALEMANIA\"\n  STR_ITALY: \"ITALIA\"\n  STR_SPAIN: \"ESPAÑA\"\n  STR_CHINA: \"CHINA\"\n  STR_JAPAN: \"JAPÓN\"\n  STR_INDIA: \"INDIA\"\n  STR_BRAZIL: \"BRASIL\"\n  STR_AUSTRALIA: \"AUSTRALIA\"\n  STR_NIGERIA: \"NIGERIA\"\n  STR_SOUTH_AFRICA: \"SUDÁFRICA\"\n  STR_EGYPT: \"EGIPTO\"\n  STR_CANADA: \"CANADÁ\"\n  STR_TANK: \"Tanque\"\n  STR_CIVILIAN: \"Civil\"\n  STR_JAN: \"Ene\"\n  STR_FEB: \"Feb\"\n  STR_MAR: \"Mar\"\n  STR_APR: \"Abr\"\n  STR_MAY: \"May\"\n  STR_JUN: \"Jun\"\n  STR_JUL: \"Jul\"\n  STR_AUG: \"Ago\"\n  STR_SEP: \"Sep\"\n  STR_OCT: \"Oct\"\n  STR_NOV: \"Nov\"\n  STR_DEC: \"Dic\"\n  STR_INTERNATIONAL_RELATIONS: \"Relaciones internacionales\"\n  STR_COUNTRY: \"País\"\n  STR_FUNDING: \"Financiación\"\n  STR_CHANGE: \"Cambio\"\n  STR_WEAPON_SYSTEMS: \"SISTEMAS DE ARMAS\"\n  STR_HWPS: \"PAPs\"\n  STR_DAMAGE_UC_: \"DAÑO>{ALT}{0}\"\n  STR_ACCESS_LIFT_UFOPEDIA: \"El ascensor de acceso permite transportar equipo y personal dentro o fuera de una base subterránea. Es lo primero que se construye en un emplazamiento nuevo. El ascensor es vulnerable y puede ser invadido por cualquier fuerza hostil.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Cada zona de alojamiento puede albergar a 50 miembros del personal. Estos alojamientos constan de instalaciones básicas para dormir, comer y divertirse.\"\n  STR_LABORATORY_UFOPEDIA: \"En un laboratorio pueden trabajar 50 científicos. Los laboratorios están equipados con las tecnologías más modernas para la investigación de materiales, bioquímica y cosmología. XCom tiene acceso a los mejores laboratorios de investigación del mundo, tanto civiles como militares.\"\n  STR_WORKSHOP_UFOPEDIA: \"En un taller se puede encontrar todo lo necesario para fabricar productos a partir de diseños realizados en los laboratorios científicos. En un taller caben 50 ingenieros, los objetos que se están fabricando también ocupan sitio.\"\n  STR_SMALL_RADAR_SYSTEM_UFOPEDIA: \"Un sistema de radar pequeño tiene un alcance efectivo de 300 millas náuticas y está conectado a sistemas de satélites para el análisis de la superficie. Cada radar tiene una probabilidad del 10% de detectar un objeto de tamaño medio cada 30 minutos.\"\n  STR_LARGE_RADAR_SYSTEM_UFOPEDIA: \"Un sistema de radar de largo alcance cubre un radio efectivo de 450 millas náuticas y está conectado a sistemas de satélites para el análisis de la superficie. Cada radar tiene una probabilidad del 10% de detectar un objeto de tamaño medio cada 30 minutos.\"\n  STR_MISSILE_DEFENSES_UFOPEDIA: \"Los sistemas de defensa basados en misiles proporcionan protección contra las incursiones de naves hostiles que intenten aterrizar en la base.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"Todo el equipo, armas, munición, materiales recuperados y PAPs están situadas en almacenes, incluyendo el equipo asignado a las naves en los hangares.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"Es probable que los alienígenas capturados con vida necesiten un  hábitat especial para mantener sus sistemas vitales. En cada unidad de contención caben 10 alienígenas metidos en otras tantas unidades independientes.\"\n  STR_LASER_DEFENSES_UFOPEDIA: \"Las defensas basadas en rayos láser proporcionan protección contra incursiones de naves hostiles.\"\n  STR_PLASMA_DEFENSES_UFOPEDIA: \"Las defensas basadas en rayos de plasma constituyen una protección eficaz y poderosa contra las incursiones de naves hostiles.\"\n  STR_FUSION_BALL_DEFENSES_UFOPEDIA: \"Los misiles de fusión ofrecen la mejor protección contra ataques alienígenas. Estos misiles originan una implosión de antimateria que destruye todo lo que se encuentra en su radio de acción.\"\n  STR_GRAV_SHIELD_UFOPEDIA: \"El escudo de gravedad repele a las naves alienígenas que estén intentando aterrizar cerca de la base de manera que los sistemas de defensa tengan tiempo de recargarse y puedan volver a abrir fuego. En la práctica dobla la eficacia de cualquier sistema de defensa de tu base.\"\n  STR_MIND_SHIELD_UFOPEDIA: \"Puesto que las naves alienígenas se sirven de las ondas mentales para detectar la presencia humana, la forma más eficaz de resolver este problema es escudar las ondas cerebrales que salen de la base. Esto reducirá enormemente las posibilidades de ser detectados por una nave alienígena.\"\n  STR_PSIONIC_LABORATORY_UFOPEDIA: \"En el laboratorio psiónico se calcula la capacidad psiónica de todos los soldados de la base y se les da el entrenamiento necesario para usar estas habilidades. Cada laboratorio puede entrenar un máximo de 10 soldados. Las plazas del laboratorio se asignan a los soldados al final de cada mes. Estas habilidades se utilizan en combinación con un amp-psi, que puede servir para realizar ataques psiónicos durante un combate.\"\n  STR_HYPER_WAVE_DECODER_UFOPEDIA: \"Las comunicaciones alienígenas emplean una onda supradimensional que se desplaza casi de forma instantánea. El descodificador intercepta las transmisiones de los OVNIS y descodifica la información. Así se puede saber de qué clase de ovni se trata, las raza alienígena y el tipo de actividad.\"\n  STR_HANGAR_UFOPEDIA: \"Cada hangar puede cobijar una nave, y cuenta con instalaciones para el mantenimiento, reabastecimiento y reparación de la flota X-Com. Cada nave estacionada en una base debe tener un hangar reservado exclusivamente para ella, incluso cuando ha salido en una misión.\"\n  STR_PISTOL_UFOPEDIA: \"La pistola estándar X-Com es una semiautomática con capacidad para 12 disparos.\"\n  STR_RIFLE_UFOPEDIA: \"Este rifle de gran precisión para francotiradores tiene una mira láser y usa munición de 6,7mm en cargadores de 20 disparos.\"\n  STR_HEAVY_CANNON_UFOPEDIA: \"El cañón pesado es un arma devastadora, aunque también abulta mucho. Su versatilidad le permite disparar tres tipos de munición: perforadora de blindaje, incendiaria y altamente explosiva.\"\n  STR_AUTO_CANNON_UFOPEDIA: \"El cañón automático combina la versatilidad y la potencia del cañón pesado con una cadencia de tiro más rápida.\"\n  STR_ROCKET_LAUNCHER_UFOPEDIA: \"El lanzacohetes es un sistema guiado por láser que puede disparar misiles de tres tamaños.\"\n  STR_LASER_PISTOL_UFOPEDIA: \"La pistola láser es una implementacion eficaz de nueva tecnología. Tiene la facilidad de manejo de una pistola pero el tiro es más rápido y preciso\"\n  STR_LASER_RIFLE_UFOPEDIA: \"El rifle láser es un modelo más potente y preciso basado en el diseño anterior de pistola.\"\n  STR_HEAVY_LASER_UFOPEDIA: \"El láser pesado es engorroso pero muy eficaz.\"\n  STR_GRENADE_UFOPEDIA: \"Esta granada estándar tiene un temporizador sofisticado y preciso para un control más exacto.\"\n  STR_SMOKE_GRENADE_UFOPEDIA: \"Las granadas de humo sirven para proveer cobertura en situaciones de combate expuestas. Utilízalas con cuidado porque también pueden beneficiar al enemigo \"\n  STR_PROXIMITY_GRENADE_UFOPEDIA: \"La granada de proximidad se lanza como las normales, pero lo que la activa es el movimiento que se produzca cerca de ella una vez que ha caído. Para utilizarla debidamente se necesitan habilidad y práctica.\"\n  STR_HIGH_EXPLOSIVE_UFOPEDIA: \"Este explosivo debe emplearse únicamente para demolición. Mantén a tu personal lejos de los puntos de demolición.\"\n  STR_MOTION_SCANNER_UFOPEDIA: \"Este sofisticado dispositivo usa una gran variedad de detectores y avanzados algoritmos informáticos para identificar unidades enemigas en movimiento. No obstante lleva algun tiempo aprender a usarlo correctamente. Haz click en el icono del escáner de movimiento que hay en la pantalla táctica. Elige 'Usar escáner' en el menú. La pantalla del escáner mostrará una flecha en el centro que indica la dirección en la que mira el soldado (el norte está arriba). Las manchas parpadeantes indican unidades que se han movido hace poco. Las unidades grandes o las que se desplazan rápidamente aparecen como manchas más grandes. Las unidades que estén paradas no aparecerán en la pantalla.\"\n  STR_MEDI_KIT_UFOPEDIA: \"El Kit medico es un pequeño botiquin que contiene pequeños utiles para curar heridas ademas de calmantes y estimulantes. Para utilizarlo debes ponerte delante del operativo XCom que requiera tratamiento. Si el operativo esta aturdido debes colocarte sobre su cuerpo. Haz click en el icono del kit medico y elige \\\"usar Kit medico\\\" del menu. {NEWLINE}CURAR> Las partes rojas en el cuerpo indican heridas mortales. Haz click en la parte del cuerpo que esta herida y haz click en el boton \\\"CURAR\\\". Se curara una herida mortal y el operativo recuperara parte de la salud.{NEWLINE}ESTIMULANTE> Repone la energía y reaviva a los operativos aturdidos. Para reavivar a un operativo inconsciente, colócate justo encima de su cuerpo.{NEWLINE}CALMANTE> Le sube la moral a los operativos heridos hasta un maximo equivalente a la salud perdida del soldado.\"\n  STR_PSI_AMP_UFOPEDIA: \"El Amp-Psi solo puede ser usado por soldados con habilidades psionicas. Durante el combate haz click en el Amp-Psi, elige el tipo de ataque y una unidad objetivo con el cursor. Hay 2 tipos de ataques psionicos:{NEWLINE}ATERRORIZAR UNIDAD> Si el ataque tiene éxito reducirá la moral del objetivo pudiendo hacer que pierda el control.{NEWLINE}CONTROL MENTAL>Si tiene éxito ganas inmediatamente el control de la unidad enemiga como si fuera una de las tuyas. Es mas difícil tener éxito con este tipo de ataque.\"\n  STR_STUN_ROD_UFOPEDIA: \"Este ingenio sólo se puede usar en el combate cuerpo a cuerpo y aturde a un organismo vivo con descargas eléctricas, sin llegar a matarlo.\"\n  STR_MIND_PROBE_UFOPEDIA: \"La sonda mental es un dispositivo alienígena de comunicación que sirve para obtener información directamente de las ondas cerebrales. Los operativos X-Com pueden utilizarlo durante el combate para averiguar las características de un alienígena. Presione sobre la sonda mental y la opción 'Usar'. Luego presione sobre el alienígena que quiera examinar.\"\n  STR_PLASMA_PISTOL_UFOPEDIA: \"La pistola de plasma es un arma alienígena mortífera basada en la aceleración de partículas desde un diminuto campo antigravitatorio.\"\n  STR_PLASMA_RIFLE_UFOPEDIA: \"Esta potente y devastadora arma está basada en la aceleración de partículas desde un diminuto campo antigravitatorio.\"\n  STR_HEAVY_PLASMA_UFOPEDIA: \"Esta es un arma increíblemente poderosa basada en la aceleración de partículas desde un diminuto campo antigravitatorio.\"\n  STR_BLASTER_LAUNCHER_UFOPEDIA: \"Este lanzamisiles alienígena dispara potentes bombas guiadas. Cuando hagas click para disparar con esta arma observarás que en la pantalla aparecen puntos indicando la ruta que seguirá la bomba. Cuando tengas suficientes puntos de ruta establecidos pulsa el icono de lanzamiento para disparar.\"\n  STR_SMALL_LAUNCHER_UFOPEDIA: \"Un pequeño lanzador que dispara bombas aturdidoras. Muy útil para capturar alienígenas vivos.\"\n  STR_ALIEN_GRENADE_UFOPEDIA: \"Este artefacto funciona igual que una granada terrestre, pero es mucho más potente.\"\n  STR_SMALL_SCOUT: \"Explorador pequeño\"\n  STR_MEDIUM_SCOUT: \"Explorador mediano\"\n  STR_LARGE_SCOUT: \"Explorador grande\"\n  STR_HARVESTER: \"Segador\"\n  STR_ABDUCTOR: \"Abductor\"\n  STR_TERROR_SHIP: \"Nave de incursión\"\n  STR_BATTLESHIP: \"Acorazado\"\n  STR_SUPPLY_SHIP: \"Nave de suministro\"\n  STR_RATING: \"EVALUACION> {0}\"\n  STR_RATING_TERRIBLE: \"¡TERRIBLE!\"\n  STR_RATING_POOR: \"¡MAL!\"\n  STR_RATING_OK: \"OK\"\n  STR_RATING_GOOD: \"¡BIEN!\"\n  STR_RATING_EXCELLENT: \"¡EXCELENTE!\"\n  STR_SCORE: \"PUNTUACIóN\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"INFORME MENSUAL DEL PROYECTO DE XCOM\"\n  STR_MONTH: \"Mes> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"El comité de naciones patrocinadoras está satisfecho con los progresos que has hecho hasta el momento.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"El comité de naciones patrocinadoras está muy satisfecho con los progresos que has hecho hasta el momento. Sigue así.\"\n  STR_COUNCIL_IS_DISSATISFIED: \"El comité de naciones patrocinadoras no está satisfecho con tu actuación. Debes ser más eficaz a la hora de enfrentarte a la amenaza alienígena o te arriesgas a que se suspenda el proyecto.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"Has fracasado en tu lucha contra la invasión alienígena y el comité de naciones patrocinadoras se ha visto obligado a cancelar el proyecto. Cada nación se enfrentará al problema como pueda. Esperamos que sea posible llegar a un acuerdo con estas fuerzas aparentemente hostiles y que la población se adapte a la presencia de los visitantes alienígenas.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} esta particularmente satisfecho con tu forma de hacer frente a la amenaza y accede a aumentar su financiación.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} están particularmente contentos con tus avances haciendo frente a la incursión alienígena local y han accedido a aumentar sus fondos.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} y {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} no esta contento con tu forma de hacer frente a la actividad alienígena en su territorio y ha decidido reducir su aportación económica.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} no estan contentos con tu forma de hacer frente a la actividad alienígena en su territorio y han decidido reducir su aportación económica.\"\n  STR_KNOTS: \"{0} nudos\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} ha firmado un pacto secreto con fuerzas alienígenas desconocidas y ha abandonado el proyecto.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} han firmado un pacto secreto con fuerzas alienígenas desconocidas y han abandonado el proyecto.\"\n  STR_MONTHLY_RATING: \"Valoración mensual> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Cambio de financiación> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"El consejo de naciones no esta contento con tu situación económica. Debes reducir tus deudas por debajo de 1 millón de dólares o el proyecto será cancelado.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"TRANSMISIONES DE HIPERONDAS DESCODIFICADAS.\"\n  STR_CRAFT_TYPE: \"TIPO DE NAVE\"\n  STR_RACE: \"RAZA\"\n  STR_MISSION: \"MISIÓN\"\n  STR_ZONE: \"ZONA\"\n  STR_ALLOCATE_RESEARCH: \"Asignar investigación\"\n  STR_ALLOCATE_MANUFACTURE: \"Asignar fabricación\"\n  STR_NEW_YORK: \"Nueva York\"\n  STR_WASHINGTON: \"Washington\"\n  STR_LOS_ANGELES: \"Los Ángeles\"\n  STR_MONTREAL: \"Montreal\"\n  STR_HAVANA: \"La Habana\"\n  STR_MEXICO_CITY: \"Ciudad de México\"\n  STR_CHICAGO: \"Chicago\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_DALLAS: \"Dallas\"\n  STR_BRASILIA: \"Brasilia\"\n  STR_BOGOTA: \"Bogotá\"\n  STR_BUENOS_AIRES: \"Buenos Aires\"\n  STR_SANTIAGO: \"Santiago de Chile\"\n  STR_RIO_DE_JANEIRO: \"Río de Janeiro\"\n  STR_LIMA: \"Lima\"\n  STR_CARACAS: \"Caracas\"\n  STR_LONDON: \"Londres\"\n  STR_PARIS: \"París\"\n  STR_BERLIN: \"Berlín\"\n  STR_MOSCOW: \"Moscú\"\n  STR_ROME: \"Roma\"\n  STR_MADRID: \"Madrid\"\n  STR_BUDAPEST: \"Budapest\"\n  STR_LAGOS: \"Lagos\"\n  STR_CAIRO: \"El Cairo\"\n  STR_CASABLANCA: \"Casablanca\"\n  STR_PRETORIA: \"Pretoria\"\n  STR_NAIROBI: \"Nairobi\"\n  STR_CAPE_TOWN: \"Ciudad del Cabo\"\n  STR_KINSHASA: \"Kinshasa\"\n  STR_ANKARA: \"Ankara\"\n  STR_DELHI: \"Delhi\"\n  STR_KARACHI: \"Karachi\"\n  STR_BAGHDAD: \"Bagdad\"\n  STR_TEHRAN: \"Teherán\"\n  STR_BOMBAY: \"Bombay\"\n  STR_CALCUTTA: \"Calcuta\"\n  STR_TOKYO: \"Tokio\"\n  STR_BEIJING: \"Beijing\"\n  STR_BANGKOK: \"Bangkok\"\n  STR_MANILA: \"Manila\"\n  STR_SEOUL: \"Seúl\"\n  STR_SINGAPORE: \"Singapur\"\n  STR_JAKARTA: \"Yakarta\"\n  STR_SHANGHAI: \"Shanghai\"\n  STR_HONG_KONG: \"Hong Kong\"\n  STR_NOVOSIBIRSK: \"Novosibirsk\"\n  STR_CANBERRA: \"Canberra\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_MELBOURNE: \"Melbourne\"\n  STR_PERTH: \"Perth\"\n  STR_PSI_TRAINING: \"Entrenam. Psi.\"\n  STR_PSIONIC_TRAINING: \"ENTRENAMIENTO PSIÓNICO\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Capacidad del lab. psi. restante> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"Fuerza{NEWLINE} psiónica\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"Mejora de la{NEWLINE}/habilidad psiónica\"\n  STR_PSI_AMP: \"Amp-psi\"\n  STR_IN_TRAINING: \"¿De{NEWLINE}entrenamiento?\"\n  STR_TARGETTED_BY: \"OBJETIVO DE:\"\n  STR_WEAPONS_CREW_HWPS: \"ARMAS/{NEWLINE}TRIPULACIÓN/PAP\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"tiene poco combustible,{NEWLINE}regresa a la base\"\n  STR_SOLDIER_LIST: \"Lista de soldados\"\n  STR_RANK_: \"RANGO> {ALT}{0}\"\n  STR_MISSIONS: \"MISIONES> {ALT}{0}\"\n  STR_KILLS: \"MUERTES> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"RECUPERACION DE HERIDAS> {ALT}{0}\"\n  STR_TIME_UNITS: \"UNIDADES DE TIEMPO\"\n  STR_STAMINA: \"AGUANTE\"\n  STR_HEALTH: \"SALUD\"\n  STR_BRAVERY: \"CORAJE\"\n  STR_REACTIONS: \"REFLEJOS\"\n  STR_FIRING_ACCURACY: \"PUNTERÍA\"\n  STR_THROWING_ACCURACY: \"PRECISIÓN DE LANZAMIENTO\"\n  STR_STRENGTH: \"FUERZA\"\n  STR_PSIONIC_STRENGTH: \"FUERZA PSIÓNICA\"\n  STR_PSIONIC_SKILL: \"HABILIDAD PSIÓNICA\"\n  STR_NEW_RANK: \"NUEVO RANGO\"\n  STR_PROMOTIONS: \"Ascensos\"\n  STR_SOLDIERS_UC: \"SOLDADOS\"\n  STR_TANK_CANNON_UFOPEDIA: \"Las Plataformas Automáticas de armas Pesadas (PAP) están diseñadas para servir de complemento a los escuadrones X-Com. La combinación de una gran potencia de fuego y un blindaje pesado hace que estas unidades sean muy valiosas en los combates en campo abierto. Asegúrate de que tienes suficientes proyectiles de cañón en tus almacenes para rearmar los tanques. Se rearman automáticamente cuando son asignados a un escuadrón.\"\n  STR_TANK_ROCKET_LAUNCHER_UFOPEDIA: \"Esta plataforma automática de armas pesadas (PAP) está armada con cohetes potentes. Serán devastadores para cualquier enemigo alienígena. Asegúrate de que tienes suficientes cohetes PAP en tus almacenes.\"\n  STR_TANK_LASER_CANNON_UFOPEDIA: \"Las armas láser constituyen un complemento útil para las PAP. Combinan una gran potencia de fuego con una munición ilimitada.\"\n  STR_HOVERTANK_PLASMA_UFOPEDIA: \"La tecnología alienígena ha redefinido las PAP. La maniobrabilidad aportada por el desplazamiento aéreo y la potencia de los rayos de plasma son una combinación mortífera.\"\n  STR_HOVERTANK_LAUNCHER_UFOPEDIA: \"Este tanque volador tiene un lanzador de bolas de fusión, capaz de causar una devastación inmensa. Utilízalo con precaución. Tendrás que fabricar las bolas de fusión con las que mantener armadas estas PAP. Una bola de fusión es un arma dirigida e inteligente. Para disparar una tendrás que usar el cursor para establecer una serie de puntos de ruta en el mapa que le sirvan de itinerario, y luego pulsar sobre el icono de lanzamiento.\"\n  STR_HEAVY_PLASMA_CLIP_UFOPEDIA: \"Este artefacto compacto se usa como munición para un arma de plasma pesada. Contiene una pequeña cantidad de elerio.\"\n  STR_PLASMA_RIFLE_CLIP_UFOPEDIA: \"Este pequeño objeto es la fuente de energía de un rifle de plasma: un arma alienígena de potencia media. Contiene una pequeña cantidad de elerio.\"\n  STR_PLASMA_PISTOL_CLIP_UFOPEDIA: \"Fuente de energía de la pistola alienígena de plasma. Lleva elerio, la fuente de toda la energía alienígena.\"\n  STR_STUN_BOMB_UFOPEDIA: \"La bomba aturdidora se usa para capturar vivos a los humanos, pero también se puede usar contra las razas alienígenas. Se dispara con un pequeño lanzador.\"\n  STR_ALIEN_RESEARCH_UFOPEDIA: \"La misión de investigación alienígena sirve para recoger información básica sobre la Tierra y sus habitantes. Utilizan sobre todo vehículos pequeños y aterrizan de vez en cuando en zonas desérticas. Este tipo de actividad alienígena supone la menor de las amenaza para X-Com. A los gobiernos y al público les preocupa poco.\"\n  STR_ALIEN_HARVEST_UFOPEDIA: \"Los alienígenas utilizan la fauna terrestre para muchas cosas. Secuestran a los animales y los devuelven después de haberles extirpado varios órganos. Lo que más se denuncia son las mutilaciones de ganado junto con avistamientos de ovnis. Este tipo de actividad alienígena preocupa mucho a los gobiernos y causa bastante inquietud a la población; tiene lugar sobre todo en areas rurales. La teoría detras de esta \\\"cosecha alienígena\\\" sugiere que las razas alienígenas 'sembraron' el planeta con su flora y fauna hace tiempo, y ahora han vuelto a recoger la cosecha.\"\n  STR_ALIEN_ABDUCTION_UFOPEDIA: \"Éste es el tipo de actividad alienígena más insidiosa. La abduccion de civiles por parte de alienigenas ha sido ampliamente denunciada pese a que los alienígenas intentan borrarles la memoria a sus víctimas. Los abducidos declaran haber sido sometidos a humillantes exámenes físicos, incluyendo la implantación de fetos alienígenas y extraños experimentos genéticos. Según parece el propósito detras de esta actividad parece estar unido a la mutación genética y la manipulación de material genético de los propios alienígenas. Esta actividad causa un gran pánico y tiene lugar en ciudades y zonas pobladas.\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"Agentes alienígenas con aspecto humano pueden infiltrarse en los gobiernos de la Tierra. Esto puede dar lugar a contactos oficiales del más alto nivel entre los alienígenas y dichos gobiernos. El clímax de esta actividad se caracteriza por una intensa actividad de OVNIs en los alrededores de las grandes ciudades. Los alienígenas intentarán firmar un pacto con un gobierno ofreciéndole acceso a su tecnología superior. A cambio, el gobierno permitirá a los alienígenas realizar sus actividades sin ningún estorbo. Este tipo de misión alienígena representa el peor escenario para X-Com. si un govierno acceda al pacto sus fondos cecaran.\"\n  STR_ALIEN_BASE_UFOPEDIA: \"Los alienígenas construirán bases subterráneas secretas en zonas remotas. Tras ciertos vuelos iniciales de reconocimiento, comenzará una intensa actividad OVNI que durará mientras construyan la base. En ellas hay laboratorios para hacer experimentos con humanos abducidos y suministros para continuar sus actividades en la región. Estas bases generarán una gran cantidad de denuncias de actividad alienígena sin la presencia de OVNIs. Para localizar una de estas bases una nave de X-Com debe patrullar por la zona durante unas cuantas horas.\"\n  STR_ALIEN_TERROR_UFOPEDIA: \"Cuando los alienígenas realizan una incursión en una ciudad, despliegan fuerzas especiales con poderes horribles. Los civiles son amenazados directamente y los gobiernos tienen que evacuar zonas enormes. El propósito de esta actividad es causar la suficiente histeria en la población como para que los gobiernos abandonen el proyecto X-Com.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"Si los interceptores de X-Com derriban muchos OVNIs, los alienígenas podrían tomar represalias. Ello podría acabar en un ataque directo contra una base X-Com. Sin embargo, si quieren atacarnos, primero deben encontrar la base, y si mantenemos alejados a los OVNIs, el peligro de ataque es menor.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"Una vez que una base alienígena está construida, comienza a recibir abastecimientos, traídos en una nave especial. Si se detecta a una de estas naves cuando va a aterrizar, es que hay una base cerca.\"\n  STR_SMALL_SCOUT_UFOPEDIA: \"Esta mininave se emplea principalmente para misiones de investigación y reconocimiento. Suele preceder a naves más grandes al principio de una misión alienígena.\"\n  STR_MEDIUM_SCOUT_UFOPEDIA: \"Un ovni explorador de tamaño medio no supone una gran amenaza para las fuerzas terrestres. Suele preceder a naves más grandes durante las misiones.\"\n  STR_LARGE_SCOUT_UFOPEDIA: \"El ovni explorador más grande se usa en todo tipo de misiones alienígenas.\"\n  STR_HARVESTER_UFOPEDIA: \"El ovni cosechador tiene una escotilla en la parte de abajo y está equipado con aparatos para subir a bordo ganado u otras bestias. Extirpan el material deseado con láser y luego tiran el cadáver al suelo. También tienen contenedores para almacenar las partes del cuerpo extirpadas.\"\n  STR_ABDUCTOR_UFOPEDIA: \"Este ovni va equipado con una sala de exámenes para realizar horribles experimentos con humanos. Normalmente las víctimas son paralizadas por medios telepáticos, pero permanecen conscientes mientras están en la mesa de operaciones.\"\n  STR_TERROR_SHIP_UFOPEDIA: \"La nave de incursión tiene una instalación de confinamiento para criaturas alienígenas de gran tamaño y/o armas, cuyo proposito es aterrorizar a la población. Sirven para transportar dichas criaturas/armas a zonas pobladas.\"\n  STR_BATTLESHIP_UFOPEDIA: \"El acorazado es la nave alienígena más poderosa. Normalmente es la nave más importante de las misiones alienígenas. Está equipada con armas potentes y su tripulación es muy numerosa.\"\n  STR_SUPPLY_SHIP_UFOPEDIA: \"El buque de suministros se emplea durante la construcción de bases alienígenas y para llevar suministros a las ya existentes. Transporta contenedores de alimentos para alienígenas y cámaras de reproducción.\"\n  STR_DISMANTLE: \"Desmantelar\"\n  STR_FACILITY_IN_USE: \"INSTALACIÓN EN USO\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"¡NO SE PUEDE DESMANTELAR LA INSTALACIóN!{SMALLLINE}Todas las instalaciones de la base deben estar unidas al ascensor de acceso.\"\n  STR_TRANSFER_ITEMS_TO: \"Transferir elementos a {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"NO HAY UNIDAD DE CONTENCION PARA TRASLADO!{SMALLLINE}Los alienígenas necesitan una unidad de contencion para sobrevivir.\"\n  STR_AMOUNT_AT_DESTINATION: \"CANTIDAD EN{NEWLINE}DESTINO\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"Alienígena muere porque no hay unidad de contención.\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"NO HAY ALOJAMIENTO{SMALLLINE}La base de destino no tiene suficiente espacio para la tripulación de la nave.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"¡INSUFICIENTE ESPACIO DE ALMACENAMIENTO!{SMALLLINE}La base de destino no tiene espacio suficiente para almacenar el equipo asignado a la nave.\"\n  STR_ITEMS_ARRIVING: \"Artículos trasladados\"\n  STR_DESTINATION_UC: \"DESTINO\"\n  STR_PISTOL: \"Pistola\"\n  STR_PISTOL_CLIP: \"Cargador de pistola\"\n  STR_RIFLE: \"Rifle\"\n  STR_RIFLE_CLIP: \"Cargador de rifle\"\n  STR_HEAVY_CANNON: \"Cañón pesado\"\n  STR_HC_AP_AMMO: \"Munición PB para CP\"\n  STR_HC_HE_AMMO: \"Munición AE para CP\"\n  STR_HC_I_AMMO: \"Munición I para CP\"\n  STR_AUTO_CANNON: \"Cañón automático\"\n  STR_AC_AP_AMMO: \"Munición PB para CA \"\n  STR_AC_HE_AMMO: \"Munición AE para CA \"\n  STR_AC_I_AMMO: \"Munición I para CA\"\n  STR_ROCKET_LAUNCHER: \"Lanzacohetes\"\n  STR_SMALL_ROCKET: \"Cohete pequeño\"\n  STR_LARGE_ROCKET: \"Cohete grande\"\n  STR_INCENDIARY_ROCKET: \"Cohete incendiario\"\n  STR_GRENADE: \"Granada\"\n  STR_SMOKE_GRENADE: \"Granada de humo\"\n  STR_PROXIMITY_GRENADE: \"Granada de proximidad\"\n  STR_HIGH_EXPLOSIVE: \"Explosivo de demolición\"\n  STR_STUN_ROD: \"Vara aturdidora\"\n  STR_HEAVY_PLASMA: \"Plasma pesado\"\n  STR_HEAVY_PLASMA_CLIP: \"Cargador de plasma pesado\"\n  STR_PLASMA_RIFLE: \"Rifle de plasma\"\n  STR_PLASMA_RIFLE_CLIP: \"Cargador de rifle de plasma\"\n  STR_PLASMA_PISTOL: \"Pistola de plasma\"\n  STR_PLASMA_PISTOL_CLIP: \"Cargador de pistola de plasma\"\n  STR_BLASTER_LAUNCHER: \"Lanzabombas guiadas\"\n  STR_BLASTER_BOMB: \"Bomba guiada\"\n  STR_SMALL_LAUNCHER: \"Lanzador pequeño\"\n  STR_STUN_BOMB: \"Bomba aturdidora\"\n  STR_ALIEN_GRENADE: \"Granada alienígena\"\n  STR_ELERIUM_115: \"Elerio 115\"\n  STR_MIND_PROBE: \"Sonda mental\"\n  STR_SECTOID_CORPSE: \"Cadáver de sectoide\"\n  STR_SNAKEMAN_CORPSE: \"Cadáver de hombre-serpiente\"\n  STR_ETHEREAL_CORPSE: \"Cadáver de etéreo\"\n  STR_MUTON_CORPSE: \"Cadáver de mutante\"\n  STR_FLOATER_CORPSE: \"Cadáver de flotador\"\n  STR_CELATID_CORPSE: \"Cadáver de celátido\"\n  STR_SILACOID_CORPSE: \"Cadáver de silacoide\"\n  STR_CHRYSSALID_CORPSE: \"Cadáver de crisálida\"\n  STR_REAPER_CORPSE: \"Cadáver de Segador\"\n  STR_SECTOPOD_CORPSE: \"Restos de sectópodo\"\n  STR_CYBERDISC_CORPSE: \"Restos de ciberdisco\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"No hay suficiente munición HWP para armar{SMALLLINE}Cada HWP requiere {0} {1}.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Equipo insuficiente para reequipar el escuadrón\"\n  STR_MARS_CYDONIA_LANDING: \"Marte: aterrizaje en Cydonia.\"\n  STR_MARS_CYDONIA_LANDING_BRIEFING: \"Tu nave Avenger ha aterrizado en la región de Cydonia sobre la superficie de Marte. Nuestra información indica que una de las pirámides contiene un ascensor de acceso a un complejo subterráneo. Una vez que hayas reunido a todos los soldados en el área del ascensor, pulsa sobre el icono de 'Cancelar misión' para pasar al siguiente nivel.\"\n  STR_MARS_THE_FINAL_ASSAULT: \"Marte: el asalto final.\"\n  STR_MARS_THE_FINAL_ASSAULT_BRIEFING: \"El ascensor de la pirámide lleva a tus soldados, cansados por la batalla, hacia el interior del planeta. Llegan al corazón de un gran complejo de túneles y cámaras. El cerebro alienígena está oculto en alguna parte del laberinto. Para que la Tierra se salve de la esclavitud a manos de los alienígenas el cerebro tiene que ser destruido.{NEWLINE}¡Buena suerte!\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Necesitas investigar {NEWLINE}{0}{NEWLINE}para producir el{NEWLINE}{1}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"Los alienígenas han destruido la base indefensa {0}\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"Agentes XCom han localizado una base alienígena en {0}\"\n  STR_STANDOFF: \"APARTARSE\"\n  STR_CAUTIOUS_ATTACK: \"ATAQUE CAUTO\"\n  STR_STANDARD_ATTACK: \"ATAQUE NORMAL\"\n  STR_AGGRESSIVE_ATTACK: \"ATAQUE AGRESIVO\"\n  STR_DISENGAGING: \"ABANDONAR COMBATE\"\n  STR_UFO_HIT: \"¡OVNI TOCADO!\"\n  STR_UFO_CRASH_LANDS: \"¡OVNI DERRIBADO!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Minimizar sólo a distancia prudente.\"\n  STR_UFO_RETURN_FIRE: \"¡EL OVNI DEVUELVE EL FUEGO!\"\n  STR_INTERCEPTOR_DAMAGED: \">>> INTERCEPTOR DAÑADO <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> INTERCEPTOR DESTRUIDO <<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"OVNI ESCAPA DEL INTERCEPTOR\"\n  STR_ALIENS_TERRORISE: \"INCURSIÓN ALIENíGENA\"\n  STR_LONG_RANGE_DETECTION: \"Detección de largo alcance\"\n  STR_STORES_UC: \"ALMACENES\"\n  STR_DIFFICULTY_LEVEL: \"Nivel de dificultad\"\n  STR_INTERCEPT: \"INTERCEPTAR\"\n  STR_BASES: \"BASES\"\n  STR_GRAPHS: \"GRÁFICOS\"\n  STR_UFOPAEDIA_UC: \"OVNIPEDIA\"\n  STR_OPTIONS_UC: \"OPCIONES\"\n  STR_FUNDING_UC: \"FINANCIACIÓN\"\n  STR_5_SECONDS: \"5 seg \"\n  STR_1_MINUTE: \"1 min \"\n  STR_5_MINUTES: \"5 min \"\n  STR_30_MINUTES: \"30 min \"\n  STR_1_HOUR: \"1 hora\"\n  STR_1_DAY: \"1 día\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"Lista de Rendimiento de X-Com\"\n  STR_ENTER_NAME: \"Introducir nombre\"\n  STR_PERFORMANCE_RATING: \"Evaluación de actuación\"\n  STR_VICTORY_DATE: \"Fecha de victoria\"\n  STR_ELECTRO_FLARE: \"Bengala eléctrica\"\n  STR_ELECTRO_FLARE_UFOPEDIA: \"Este artefacto produce una señal luminosa brillante. Ilumina a las unidades tanto amigas como enemigas que haya cerca durante misiones nocturnas.\"\n  STR_MONTHLY_COSTS: \"Gastos mensuales\"\n  STR_CRAFT_RENTAL: \"Alquiler de naves\"\n  STR_SALARIES: \"Salarios\"\n  STR_BASE_MAINTENANCE: \"Mantenimiento de bases\"\n  STR_COST_PER_UNIT: \"Coste por unidad\"\n  STR_QUANTITY: \"Cantidad\"\n  STR_TOTAL: \"Total\"\n  STR_IN_PSIONIC_TRAINING: \"En entrenamiento psiónico\"\n  STR_BLASTER_BOMB_UFOPEDIA: \"Este aparato es un misil altamente explosivo que lleva instalado un sistema de guía inteligente. Lo dispara un lanzador de bombas guiadas.\"\n  STR_FRONT_ARMOR: \"Blindaje frontal\"\n  STR_LEFT_ARMOR: \"Blindaje izquierdo\"\n  STR_RIGHT_ARMOR: \"Blindaje derecho\"\n  STR_REAR_ARMOR: \"Blindaje trasero\"\n  STR_UNDER_ARMOR: \"Blindaje inferior\"\n  STR_ROUNDS: \"Disparos\"\n  STR_UNIT: \"UNIDAD> {0}\"\n  STR_ENERGY: \"ENERGÍA\"\n  STR_MORALE: \"MORAL\"\n  STR_ARMOR_: \"BLINDAJE> {0}\"\n  STR_FRONT_ARMOR_UC: \"BLINDAJE DELANTERO\"\n  STR_LEFT_ARMOR_UC: \"BLINDAJE IZQUIERDO\"\n  STR_RIGHT_ARMOR_UC: \"BLINDAJE DERECHO\"\n  STR_REAR_ARMOR_UC: \"BLINDAJE TRASERO\"\n  STR_SKILLS: \"HABILIDADES> {0}\"\n  STR_LEVEL: \"NIVEL> {0}\"\n  STR_HEAD: \"CABEZA\"\n  STR_TORSO: \"TORSO\"\n  STR_RIGHT_ARM: \"Brazo Dcho.\"\n  STR_LEFT_ARM: \"Brazo Izdo.\"\n  STR_RIGHT_LEG: \"Pierna Dcha.\"\n  STR_LEFT_LEG: \"Pierna Izda.\"\n  STR_PAIN_KILLER: \"CALMANTE\"\n  STR_STIMULANT: \"ESTIMULANTE\"\n  STR_HEAL: \"CURAR\"\n  STR_TIME_UNITS_SHORT: \"UT>{ALT}{0}\"\n  STR_WEIGHT: \"Peso>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"Reacción>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"Nivel Psi{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"Fuer.Psi>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Artefacto alienígena\"\n  STR_AMMO_ROUNDS_LEFT: \"MUNICIÓN:{NEWLINE}CARGADORES{NEWLINE}RESTANTES={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Calmar>{ALT}{0}{ALT}{NEWLINE}Estim.>{ALT}{1}{ALT}{NEWLINE}Curar>{ALT}{2}\"\n  STR_THROW: \"Lanzar\"\n  STR_AUTO_SHOT: \"Disparo auto.\"\n  STR_SNAP_SHOT: \"Disparo rápido\"\n  STR_AIMED_SHOT: \"Disparo preciso\"\n  STR_STUN: \"Aturdir\"\n  STR_PRIME_GRENADE: \"Activar granada\"\n  STR_USE_SCANNER: \"Utilizar escáner\"\n  STR_USE_MEDI_KIT: \"Utilizar botiquín\"\n  STR_LAUNCH_MISSILE: \"Lanzar misil\"\n  STR_ACCURACY_SHORT: \"Punt>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"¡Unidades de tiempo insuficientes!\"\n  STR_NOT_ENOUGH_ENERGY: \"¡Energía insuficiente!\"\n  STR_NO_ROUNDS_LEFT: \"¡No queda munición!\"\n  STR_NO_AMMUNITION_LOADED: \"¡El arma no está cargada!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"¡Esta munición no sirve para esta arma!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"¡El arma ya está cargada!\"\n  STR_NO_LINE_OF_FIRE: \"¡No hay línea de tiro!\"\n  STR_GRENADE_IS_ACTIVATED: \"¡La granada está activada!\"\n  STR_GRENADE_IS_DEACTIVATED: \"¡Granada desactivada!\"\n  STR_THERE_IS_NO_ONE_THERE: \"¡Allí no hay nadie!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"¡Artefacto alienígena inutilizable hasta después inspección!\"\n  STR_OUT_OF_RANGE: \"¡Fuera de alcance!\"\n  STR_UNABLE_TO_THROW_HERE: \"¡Imposible lanzar aquí!\"\n  STR_SET_TIMER: \"Ajustar temporizador\"\n  STR_HIDDEN_MOVEMENT: \"MOVIMIENTO OCULTO\"\n  STR_TURN: \"TURNO> {0}\"\n  STR_SIDE: \"LADO> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Pulsar un botón para continuar\"\n  STR_MIND_CONTROL: \"Control mental\"\n  STR_PANIC_UNIT: \"Causar pánico\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Ataque con Exito a la Moral\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Control Mental con éxito\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}ha enloquecido\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}ha Enloquecido\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}ha entrado en pánico\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}ha perdido el control\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Alienígenas\"\n  STR_RIGHT_HAND: \"Mano Dcha.\"\n  STR_LEFT_HAND: \"Mano Izda.\"\n  STR_RIGHT_SHOULDER: \"Hombro Dcho.\"\n  STR_LEFT_SHOULDER: \"Hombro Izdo.\"\n  STR_BACK_PACK: \"Mochila\"\n  STR_BELT: \"CINTURÓN\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}esta bajo control alienigena\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}está bajo control alienígena\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}ha quedado inconsciente\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}ha quedado inconsciente\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}ha muerto de una herida mortal\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}ha muerto de una herida fatal\"\n  STR_USE_MIND_PROBE: \"Usar sonda mental\"\n  STR_FATAL_WOUNDS: \"HERIDAS MORTALES\"\n  STR_UNDER_ARMOR_UC: \"BAJO BLINDAJE\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Uni. de tiempo reservadas para disparo rápido\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Uni. de tiempo reservadas para disparo automático\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Uni. de tiempo reservadas para disparo de precisión\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Unidades de Tiempo reservadas para arrodillarse\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"UT's reservadas para arrodillarse y disparar\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} Unidad en Nave X-Com\"\n    many: \"{N} Unidades en Nave X-Com\"\n    other: \"{N} Unidades en Nave X-Com\"\n  STR_UNITS_OUTSIDE:\n    one: \"{N} Unidad dejada fuera\"\n    many: \"{N} Unidades abandonadas\"\n    other: \"{N} Unidades abandonadas\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} Unidad en la Entrada\"\n    many: \"{N} Unidades en la Entrada\"\n    other: \"{N} Unidades en la Entrada\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} Unidad en la Meta de Salida\"\n    many: \"{N} Unidades en la Meta de Salida\"\n    other: \"{N} Unidades en la Meta de Salida\"\n  STR_ABORT_MISSION_QUESTION: \"¿Cancelar la misión?\"\n  STR_CORPSE: \"Cadáver\"\n  STR_UNLOAD_CRAFT: \"Descargar\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}ha muerto\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}ha muerto\"\n  STR_HIT_MELEE: \"Impacto\"\n  STR_GROUND: \"EN TIERRA\"\n  STR_LIVING_QUARTERS_PLURAL: \"Alojamientos\"\n  STR_LIST_ITEM: \"ELEMENTO\"\n  STR_PERSONAL_ARMOR_UFOPEDIA: \"Creada usando las recientemente descubiertas Aleaciones alienígenas esta nueva armadura da a nuestros hombres una oportunidad en la lucha contra la amenaza alienígena.\"\n  STR_POWER_SUIT_UFOPEDIA: \"Una nueva y poderosa protección para nuestros soldados. Esta armadura esta alimentada por una fuente de energía de Elerium y aumenta en gran medida la velocidad y fuerza del que la lleva, ofreciendo la mejor protección para tropas de combate.\"\n  STR_FLYING_SUIT_UFOPEDIA: \"Una versión mejorada del Traje de Poder que incorpora tecnología alienígena de navegación anti-gravedad para permitir libertad total de movimientos en el campo de batalla.\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"Todos los alienígenas han muerto en el accidente,{NEWLINE}Recuperación automática iniciada.\"\n  STR_RESET: \"Inicializar\"\n  STR_MEMORIAL: \"Memorial\"\n  STR_DATE_UC: \"FECHA\"\n  STR_SOLDIERS_RECRUITED_UC: \"SOLDADOS RECLUTADOS>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"SOLDADOS PERDIDOS>{ALT}{0}\"\n  MAP_CULTA: \"Granja\"\n  MAP_FOREST: \"Bosque\"\n  MAP_JUNGLE: \"Jungla\"\n  MAP_MOUNT: \"Montaña\"\n  MAP_DESERT: \"Desierto\"\n  MAP_POLAR: \"Polar\"\n  MAP_URBAN: \"Ciudad\"\n  MAP_UBASE: \"Base alienígena\"\n  MAP_XBASE: \"Base X-Com\"\n  MAP_MARS: \"Marte\"\n  STR_MIXED: \"Mezclado\"\n  STR_REMOVE_SELECTED: \"Eliminar seleccionado\"\n  STR_LIVE_ALIENS: \"Especímenes{NEWLINE}Vivos\"\n  STR_DEAD_ALIENS: \"Especímenes{NEWLINE}Rechazados\"\n  STR_UNDER_INTERROGATION: \"Siendo{NEWLINE}Estudiados\"\n  STR_CONTAINMENT_EXCEEDED: \"¡EXCEDIDO LÍMITE DE CONTENCIÓN ALIENÍGENA!{SMALLLINE}Insuficiente espacio de contención en {0}. Debes reducir el exceso de alienígenas del compartimento (los seleccionados morirán).\"\n  STR_MANAGE_CONTAINMENT: \"Administrar Contención Alienígena\"\n  STR_STORAGE_EXCEEDED: \"¡ESPACIO DE ALMACENAJE SOBREPASADO!{SMALLLINE}Espacio de almacenamiento insuficiente en {0}. Debes vender elementos para hacer sitio.\"\n  STR_GO_TO_BASE: \"Ir a la Base\"\n  STR_MELEE_ACCURACY: \"Precisión cuerpo a cuerpo\"\n  STR_SELL_PRODUCTION: \"VENDER\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"¡Las dos manos tienen que estar libres!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"¡Objetos insuficientes para copiar la plantilla!\"\n  STR_UNLOAD_WEAPON: \"Descargar arma\"\n  STR_ALL_ITEMS: \"Todos los objetos\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"¡NO SE LE PERMITE MAS EQUIPO A BORDO!{SMALLLINE}Sólo se le permite llevar un máximo de {N} objeto en esta nave.\"\n    many: \"¡NO SE LE PERMITE MAS EQUIPO A BORDO!{SMALLLINE}Sólo se le permite llevar un máximo de {N} objetos en esta nave.\"\n    other: \"¡NO SE LE PERMITE MAS EQUIPO A BORDO!{SMALLLINE}Sólo se le permite llevar un máximo de {N} objetos en esta nave.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}CENTRO DE CONTROL DESTRUIDO{NEWLINE}Diríjase a la entrada y aborte.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"Instalaciones X-Com no se pueden construir bajo el agua\"\n  STR_LEVEL_SHORT: \"{0}\"\n  STR_PERSONNEL: \"Personal\"\n  STR_CRAFT_ARMAMENT: \"Naves y Armamento\"\n  STR_COMPONENTS: \"Componentes\"\n  STR_SOLDIERS_RECRUITED: \"Soldados reclutados\"\n  STR_SOLDIERS_LOST: \"Soldados perdidos\"\n  STR_TOTAL_UFOS: \"OVNIS detectados\"\n  STR_TOTAL_ALIEN_BASES: \"Bases alienígenas descubiertas\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"FPSI\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"HPSI\"\n  FEMALE_CIVILIAN: \"Civil, Mujer\"\n  MALE_CIVILIAN: \"Civil, Hombre\"\n  CYBERDISC_WEAPON: \"Arma de Ciberdisco\"\n  REAPER_WEAPON: \"Arma Reaper\"\n  CHRYSSALID_WEAPON: \"Arma Chryssalid\"\n  CELATID_WEAPON: \"Arma Celatid\"\n  SILACOID_WEAPON: \"Arma Silacoid\"\n  SECTOPOD_WEAPON: \"Arma Sectopod\"\n  ZOMBIE_WEAPON: \"Arma Zombie\"\n  ALIEN_PSI_WEAPON: \"Arma Psiónica Alienígena\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/et.yml",
    "content": "et:\n  STR_AVENGER_UFOPEDIA: \"TRANSPORTER JA LAHINGLAEV. VIIMANE SÕNA TULNUKATE TEHNOLOOGIA REPLITSEERIMISES.\"\n  STR_INTERCEPTOR_UFOPEDIA: \"KAHE PULSSDETONATISIOONIMOOTORI JA KAITSTUD ELEKTROONIKAGA HÄVITAJA. PARIM MIDA MAA TEHNOLOOGIA VÕIMALDAB.\"\n  STR_LIGHTNING_UFOPEDIA: \"TRANSPORTER JA LAHINGLAEV. TAHUMATA KUID EFEKTIIVNE KOOPIA TULNUKATE LENNUVAHENDIST.\"\n  STR_SKYRANGER_UFOPEDIA: \"TRANSPORTER. OMA KLASSI KIIREIM, VERTIKAALSE MAANDUMISE JA ÕHKUTÕUSMIS (VMÕL) VÕIMEKUSEGA.\"\n  STR_FIRESTORM_UFOPEDIA: \"HÄVITUSTALDRIK. SEE ÜHEMEHELINE HÄVITAJA KOPEERIB OMA KESKSE JÕUALLIKAGA TÜÜPILIST TULNUKATE LENDAVAT TALDRIKUT.\"\n  STR_STINGRAY_UFOPEDIA: \"VARJESTATUD ELEKTROONIKAGA EDASIARENENUD ÕHK-ÕHK RAKETT.\"\n  STR_AVALANCHE_UFOPEDIA: \"ERITI RASKE TUUMALÕHKEPEAGA ÕHK-ÕHK RAKETT.\"\n  STR_CANNON_UFOPEDIA: \"KUNI 16 TOLLISEID SOOMUSTADU TERASPLAATE LÄBISTAVAID MÜRSKE TULISTAV KÕRGTEHNOLOOGILINE KAHUR.\"\n  STR_FUSION_BALL_UFOPEDIA: \"SEE HEITJA TULISTAB VÄLJA ANTI-MATEERIA REAKTSIOONI ESILE KUTSUVAID KUULE. KUUL PURUSTAB SIHTMÄRGI GRAVITATSIOONIPLAHVATUSE TAGAJÄRJEL.\"\n  STR_LASER_CANNON_UFOPEDIA: \"SEDA TAVALIST LASERIT TOIDAB ANTI-MATEERIA JÕUALLIKAS.\"\n  STR_PLASMA_BEAM_UFOPEDIA: \"KATKEMATU RASKUSJÕU KIIR\"\n  STR_SECTOID_UFOPEDIA: \"Sektoidide hierarhiline süsteem ulatub sõduritest kuni suurte psiooniliste võimetega juhtideni. Need psioonilised võimed võimaldavad lahingus sõdureid demoraliseerida ning isegi kontrollida. Sektoidid tegelevad peamiselt inimröövide ja karja moonutamisega. Röövimiste eesmärgiks on geneetilise materjali korjamine ning kloonide arendamine inimühiskonda sisse imbumiseks. Karja moonutatakse nii toitainete kui ka geneetilise materjali saamiseks. Paistab, et sektoidid soovivad aretada paremaid hübriide, et suurendada oma pesalaadse ühiskonna efektiivsust.\"\n  STR_SECTOID_AUTOPSY: \"Sektoidi lahkamine\"\n  STR_SECTOID_AUTOPSY_UFOPEDIA: \"Lahkamine näitas taandarenenud seedeelundeid ja lihtsakoelist struktuuri. Aju ja silmad on väga hästi arenenud. Struktuur viitab geneetilistele muutmistele või mutatsioonile. Väikesel suul ja väikesel ninal ilmselt puudub igasugune funktsioon. Käed ja lampjalad viitavad päritolule veekeskonnast. Suguelundid puuduvad ning puuduvad ka vihjed kuidas nad paljunevad. Tegemist on ilmselt geneetiliselt arendatud rassiga.\"\n  STR_SNAKEMAN_UFOPEDIA: \"See rass on arenenud väga vaenulikes tingimustes. Nad on väga vastupidavad ning suudavad üle elada ekstreemseid temperatuuri kõikumisi. Nende mobiilsus sõltub ussilaadsest suurest \\\"jalast\\\", mis kaitseb ühtlasi kõiki vitaalseid organeid. Nende eesmärgid paistavad olevat puhtalt predaatorlikud ning nad paistavad olevat mingi teistsuguse intelligentsi kontrolli all, kes juhendab nende sõjaväelikke sissetunge maale.\"\n  STR_SNAKEMAN_AUTOPSY: \"Ussimehe Lahkamine\"\n  STR_SNAKEMAN_AUTOPSY_UFOPEDIA: \"Nahk on väga tugev ja kuumusekindel. Kardio-vaskulaarne süsteem on muskulaarsüsteemi osa ning kasutab hüdraulikaprintsiipe et liikumine tekitada. Ainuke \\\"õige\\\" muskel on süda. Paljunemissüsteem paistab olevat väga efektiivne. Paljunemine on aseksuaalne, iga ussmees kannab igal aja hetkel oma kehas kuni viitekümmet muna. Kui ussmehed rahule jätta siis see rass oleks maa elule väga ohtlik.\"\n  STR_ETHEREAL_UFOPEDIA: \"See olend omab aukartust äratavaid mentaalseid võimeid, mille abil suudavad nad üksteisega kommunikeerida, ja telekineetilisi omadusi. Ilmsetele nõrkadele füüsilistele omadustele annad jõudu juurde mentaalsed võimed. Siiamaani pole me veel aru saanud kuidas nende telekineetilsed võimed töötavad, sest need paistavad ignoreerivat meile teada olevaid füüsikaseaduseid. Nad on väga ohtlikud lahingusituatsioonides kus on neil võimalus kasutada oma mentaaseid võimeid. Maa peal kohtab neid harva kuna paistab, et nad kasutavad teisi rasse oma eesmärkide saavutamiseks.\"\n  STR_ETHEREAL_AUTOPSY: \"Taevase Lahkamine\"\n  STR_ETHEREAL_AUTOPSY_UFOPEDIA: \"See olend on füüsiliselt väärakas ning paistab olevat suutmatu pikalt töös hoidma eluks vajalikke organisme. Musklid on taandarenenud ja siseelundid paistavad olevat vähearenenud. Tundmisorganid, kaasaarvatud silmad, ei paista üldse töötavat. Selleeest aju on väga kaugele arenenud ning kasutab enamus keha vereringlusest. On mõistatuseks kuidas suudab olend liikuda ilma väliste toetusteta.\"\n  STR_MUTON_UFOPEDIA: \"See humanoidi laadne olend on füüsiliselt tugev ja intelligente. Neil paistab olevat eriline huvi konsumeerida tooret liha, mida nad vajavad eluspüsimiseks nagu maapealsed kiskjadki. Nad paistavad sõltuvat telepaatilisest käskudest rassilt nimega \\\"taevased\\\". Kui telepaatiline ühendus katkestada siis nende mentaalne süsteem paistab kokku jooksvat ning nad surevad. Nende küberneetilised implantaadid suurendavad nende lahinguvõimekust. Ilmselgelt on nad kahurilihaks kõrgemale intelligentsile.\"\n  STR_MUTON_AUTOPSY: \"Mutooni Lahkamine\"\n  STR_MUTON_AUTOPSY_UFOPEDIA: \"Olendi \\\"nahk\\\" paistab olevad orgaaniliselt valmistatud kaitserüü mis on kehale siirdatud. Olendis on hulk küberneetilisi implantaate mis võimendavad kardio-vaskulaarset süsteemi ning muid meeli. Paljunemisorganid on kirurgiliselt eemaldatud. Paistab et nende õnnetute olendite elu koosneb ainult sõjapidamisest ja vallutustes. Soomustläbistavad kuulid ei ole eriti efektiivsed nende vastu.\"\n  STR_CELATID_UFOPEDIA: \"See eluvorm oma müstilist omadust õhus hõljuda. Paistab, et ta suudab tuvastada inimeste ajulaineid ning liigub nende poole isegi siis kui inimesed on peidus. Kui sihtmärk on avastatud siis Celatiid maandub ning tulistab välja väga söövitavat mürki. Olend suudab ise ennast väga kiiresti kloonida. Tavaliselt kohtab teda koos mutoonidega. \"\n  STR_CELATID_AUTOPSY: \"Celatiidi lahkamine\"\n  STR_CELATID_AUTOPSY_UFOPEDIA: \"Tuumik koosneb väikesest biomehaanilisest vidinast mis paistab olevat loomulikul viisil arenenud antigravitaalne liikumissüsteem. Mürgikotike on suurim organ ning olendil puudub aju. Ka puuduvad märgatavad seede ja paljunemisorganud. Väike organ sisaldab looteid, mis suudavad kiirelt uueks olendiks kasvada.\"\n  STR_SILACOID_UFOPEDIA: \"See silikoonil baseeruv eluvorm genereerib tohutult soojust. Tal on jõudu purustada kive, mida siis kuum tuum alla neelab. Omab primitiivset intelligentsi ja teda saab kontrollida implantaatide või telepaatiliste võimetega. Liigub tavaliselt koos mutoonide rassiga.\"\n  STR_SILACOID_AUTOPSY: \"Silacoidi lahkamine\"\n  STR_SILACOID_AUTOPSY_UFOPEDIA: \"Subjekti tuum on väga kuum ning paistab olevat baasiks seedesüsteemile. Unikaalne muskulatuurne süsteem annab kehale meeletu kiiruse ja tugevuse. Kivilaadne nahk on immuune tulele ja leekkuulidele.\"\n  STR_CHRYSSALID_UFOPEDIA: \"Olendi krabilaadsed sõrad on lähivõitluses hirmuäratavad relvad. Kõrge metabolism ja tugevus annavad olendile kiiruse ja osavuse. Ohvrite tapmise asemel süstib olend nendesse muna ning muudab mürgi abil liikuvaks zombiks. Peale muna sisendamist tekib lühikese aja jooksul ohvrist uus krüssaliid. Krüssaliidid liiguvad ringi koos ussmeestega.\"\n  STR_CHRYSSALID_AUTOPSY: \"Krüssaliidi Lahkamine\"\n  STR_CHRYSSALID_AUTOPSY_UFOPEDIA: \"Olendi välisskelett on väga vastupidav kuid üllatavalt tundlik lõhkeainetele. Aju on hästi arenenud ning rakud kasvavad väga kiiresti. Olend kannab kahtekümmend muna mis hiljem munetakse teistesse organismidesse. Olend on väga efektiivne terrorirelv.\"\n  STR_FLOATER_UFOPEDIA: \"Hõljutised on peamiselt sõdurid ja terroristid. Nad on loomult kiskjad, geneetiliselt arendatud ja küberneetiliselt täiustatud, et teha neist hirmuäratavaid sõjamehi. Alamkeha ja enamus siseorganeid on kirurgiliselt eemaldatud ning asendatud elutoetava süsteemiga. See implantaat sisaldab antigravitaalset elementi mis võimaldab olendil mõnevõrra ebastabiilselt õhus hõljuda.\"\n  STR_FLOATER_AUTOPSY: \"Hõljutise lahkamine\"\n  STR_FLOATER_AUTOPSY_UFOPEDIA: \"Hõljutis on kirurgiliselt drastiliselt muudetud. Ese mis moodustab keha tuuma paistab olevat elushoidmise süsteem, mis on üle võtnud südame, kopsude ja seedesüsteemide toimingud. Tänu sellele suudab olend eksisteerida väga vaenulikes keskkondades. Aju on väiksem kui inimestel, kuid tundmismeeled on hästi arenenud.\"\n  STR_REAPER_UFOPEDIA: \"See bipedaalne lihasööja omab tugevaid lõugu ja meeletut isu. Omab hulka implantaate mille abil kontrollitakse tema aktiivsust. Primitiivseist kiskjalikeist instinktidest on vähe kasu peale terroriseerimise ja hävitamise. Pussitajad on tavaliselt seotud hõljutistega.\"\n  STR_REAPER_AUTOPSY: \"Pussitaja Lahkamine\"\n  STR_REAPER_AUTOPSY_UFOPEDIA: \"Pussitajal on kaks \\\"aju\\\" ja kaks \\\"süda\\\", tänu millele suudab ta edukalt võidelda ka raskelt haavatuna. Kuid tema karvane nahk on väga tuleohtlik, tehes olendi tundlikuks süütemoonale.\"\n  STR_SECTOPOD_UFOPEDIA: \"Sektokõdrad on robotilaadsed olendid vägevate laserkiirtega relvadega. Neid mehaanilisi monstrumeid kontrollivad taevased telepaatilise ühenduse kaudu. Sektokõdrad on kõige tugevamad terrorrelvad mis tulnukvägedele saadaval.\"\n  STR_SECTOPOD_AUTOPSY: \"Sektokõdra lahkamine\"\n  STR_SECTOPOD_AUTOPSY_UFOPEDIA: \"Robot on vastupidav konstruktsioon tugevatud soomusega, mis on suuteline vastu pidama enamus rünnakuvormidele, eriti on kaitstud plasmarelvade vastu. Kuid siiski paistab sensorite süsteem olema eriti tundlik laserrelvade suhtes.\"\n  STR_CYBERDISC_UFOPEDIA: \"See miniatuurne lendav taldrik on automatiseeritud terrorirelv varustatud võimsa plasmakiirega. Anti-gravitatsiooniline veojõud annab taldrikule suure eelise raskel maastikul. Selle peamine eesmärk on hävituse ja terrori külvamine sektoidi rassi nimel.\"\n  STR_CYBERDISC_AUTOPSY: \"Küberketta Lahkamine\"\n  STR_CYBERDISC_AUTOPSY_UFOPEDIA: \"Küberketas on hästi soomustatud ning eriti resistante plahvatuslikule laskemoonale. Primaarne hõljuksüsteem on liiga vigastatud, et selle funktsiooni lähemalt tunda õppida.\"\n  STR_UFO_POWER_SOURCE_UFOPEDIA: \"Tulnukate sõidukite jõuallikaks on antiaine reaktor, mis kasutab eleriumi (element 115) et tekitada võimsaid antigravitatsioonilisi laineid ja teisi energiavorme. Aine konvertimine energiaks toimub 99% efektiivsusega, tänu millele imetillukesest kogusest eleriumist toodetakse meeletu hulk energiat. Jõuallikat on tulnuksulamist lihtne toota.\"\n  STR_UFO_NAVIGATION_UFOPEDIA: \"Tulnukate sõidukid kasutavad keerukaid arvuteid maal ja kosmoses navigeerimiseks. Süsteem baseerub optilistel protsessoritel mis on omavahel võrguühenduses. Juhtimisliides on suhteliselt lihtne, navigaator kontrollib jõuallika poolt genereeritavate gravitatsioonilainete suundi liigutamaks sõidukit soovitud suunas. Inimesed saavad süsteemi kergesti kasutada ning selle järgi tegemine kasutades tulnukainet ja muid komponente ei ole keeruline.\"\n  STR_UFO_CONSTRUCTION_UFOPEDIA: \"Tulnukate sõidukid koosnevad kolmest peamisest komponendist: jõuallikas, navigeerimissüsteem ja tulnukainest ehitatud kerest. Kere on spetsiaalselt disainitud gravitatsioonilainete juhtimiseks. Peale selle on vaja väikest kogust eleriumi jõuallika kütuseks. Peale seda kui konstrueerimise printsiibid on selged ning komponentide funktsioonid teada, on võimalik seda tüüpi sõidukeid ise toota.\"\n  STR_ALIEN_FOOD_UFOPEDIA: \"Need kambrid sisaldavad erinevaid ensüüme mida kasutatakse karja, metsloomade ning isegi inimeste tükkide seedimiseks. Saadav vedelik on siis valmis seedimiseks ning ilmselt suunatakse otse vereringlusse.  See kõik näitab teatavat sõltuvust Maast - sümbioos maa ja tulnukate kultuuride vahel.\"\n  STR_ALIEN_REPRODUCTION_UFOPEDIA: \"Need kambrid sisaldavad tulnukate looteid. Kambrite disain viitab sellele, et tulnukad sõltuvad täielikult laboratoorsest paljunemisest. Rikkalikud toitained tagavad loote kiire arengu. Selline liinisüsteem suudab lühikese ajaga toota tuhandeid tulnukate kloone. Protsessi võib lihtsalt adapteeruda inimeste või inim-tulnuka hübriidide tootmiseks.\"\n  STR_ALIEN_ENTERTAINMENT_UFOPEDIA: \"Nende sfääride kõige tõenäolisem ülesanne on meelelahutus. Psüühilised vooluringid stimuleerivad erinevaid ajuosakesi ja nende effekt on sarnane hallutsinogeenilistele narkootikumidele. Need sfäärid on ainukesed tõendid tulnukate kultuuriliste ja meelelahutuslike tegevuste kohta vabal ajal.\"\n  STR_ALIEN_SURGERY_UFOPEDIA: \"Kirurgilised seadmed kasutavad laserlõikureid et eemaldada teatud eluneid karja või muudest loomadest. Laialdane karjaloomade mutileerimine viitab sellele veidrale tegevusele. On tõenäiline, et loomade elundeid kasutatakse toitaineteks või geneetiliseks uurimiseks.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"Minevikus on tuhanded inimesed väitnud, et tulnukad on neid röövinud, mõnikord mitu korda järjest. Tõde on hoopis õudsam. Inimesi on röövitud, uuritud ja monitooritud. Parimailt on siirdatud geneetilist materjali. Naistesse on siirdatud tulnukhübriidide looteid ja siis mitme kuu pärast eemaldatud. Kes teab milliseid pahaendelisi motiive tulnukad tegelikult omavad?\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"On selge et võitleme sõjas mida pole võimalik võita. Tulnukhordide suurused on lugematud. Parim mida me suudame on nende progressi aeglustada. Inimkonna ainus lootus on viia võitlus nende juurde. Meie luure andmeil on nende operatsioonibaas kuskil päikesesüsteemis. Tulnukad on vihjanud, et asub see iidse tsivilisatsiooni varemeis. Me peame selle asukoha teada saama niipea kui võimalik, kuid detailsema info jaoks on vaja kinni püüda ja üle kuulata tulnukate kõrgema taseme juht. Suurematel UFOdel on tavaliselt vähemalt üks selline ringi lendamas.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"UFO KESKELE-AEG=5 S\"\n  STR_CANCEL_UC: \"TÜHISTA\"\n  STR_NONE: \"Mitte midagi\"\n  STR_UNKNOWN: \"Teadmata\"\n  STR_POOR: \"Kehv\"\n  STR_AVERAGE: \"Keskmine\"\n  STR_GOOD: \"Hea\"\n  STR_EXCELLENT: \"Suurepärane\"\n  STR_BUILD_NEW_BASE_UC: \"EHITA UUS BAAS\"\n  STR_BASE_INFORMATION: \"BAASI INFO\"\n  STR_EQUIP_CRAFT: \"VARUSTA LAEV\"\n  STR_BUILD_FACILITIES: \"EHITA HOONEID\"\n  STR_RESEARCH: \"UURIMUSTÖÖD\"\n  STR_MANUFACTURE: \"TOOTMINE\"\n  STR_TRANSFER_UC: \"ÜLEKANNE\"\n  STR_PURCHASE_RECRUIT: \"OSTA/PALKA\"\n  STR_SACK: \"VALLANDA\"\n  STR_SELL_SACK_UC: \"Müü/Vallanda\"\n  STR_GEOSCAPE_UC: \"MAAILM\"\n  STR_NAME: \"Nimi\"\n  STR_AREA: \"Ala\"\n  STR_BUILD_NEW_BASE: \"Ehita Uus Baas\"\n  STR_CANCEL: \"Tühista\"\n  STR_COST_UC: \"HIND>\"\n  STR_CONSTRUCTION_TIME_UC: \"EHITUSAEG>\"\n  STR_DAY:\n    one: \"{N} päev\"\n    other: \"{N} päeva\"\n  STR_HOUR:\n    one: \"{N} tundi\"\n    other: \"{N} tundi\"\n  STR_MAINTENANCE_UC: \"ÜLALHOID>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Installeerimine\"\n  STR_CURRENT_RESEARCH: \"HETKE UURIMUSTÖÖ\"\n  STR_SCIENTISTS_AVAILABLE: \"Vabu  Teadlasi>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Teadlaseid Töötamas>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Labori pinda saadaval>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"UURIMIS PROJEKT\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"TEADLASED TÖÖLE PANDUD\"\n  STR_PROGRESS: \"PROGRESS\"\n  STR_NEW_PROJECT: \"Uus Projekt\"\n  STR_CANCEL_PROJECT: \"TÜHISTA PROJEKT\"\n  STR_NEW_RESEARCH_PROJECTS: \"UUS UURIMUSTÖÖ PROJEKT\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"TEADLASEID VABA>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"LABORIS RUUMI>{ALT}{0}\"\n  STR_INCREASE: \"Suurenda\"\n  STR_DECREASE: \"Vähenda\"\n  STR_START_PROJECT: \"ALUSTA PROJEKTI\"\n  STR_CURRENT_PRODUCTION: \"HETKEL TOOTMISES\"\n  STR_ENGINEERS_AVAILABLE: \"Vabu insenere>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Insenere Töödamas>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Töökoja pinda saadaval>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Hetkel Raha>{ALT}{0}\"\n  STR_ITEM: \"ASI\"\n  STR_ENGINEERS__ALLOCATED: \"Insenerid Tööl\"\n  STR_UNITS_PRODUCED: \"Toodetud Kogus\"\n  STR_TOTAL_TO_PRODUCE: \"Kokku Toota\"\n  STR_COST__PER__UNIT: \"Hind{NEWLINE}ühiku{NEWLINE}kohta\"\n  STR_DAYS_HOURS_LEFT: \"Päevi/Tunde Jäänud\"\n  STR_NEW_PRODUCTION: \"Uus Tootmine\"\n  STR_PRODUCTION_ITEMS: \"Tootmine\"\n  STR_CATEGORY: \"KATEGOORIA\"\n  STR_START_PRODUCTION: \"ALUSTA TOOTMIST\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"Kulub {0} töötundi et toota 1 ese.\"\n  STR_COST_PER_UNIT_: \"Tüki hind>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Töökoja ruumi vaja>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"ERIMATERJALID VAJALIKUD\"\n  STR_ITEM_REQUIRED: \"VAJALIK ESE\"\n  STR_UNITS_REQUIRED: \"VAJALIK{NEWLINE}KOGUS\"\n  STR_UNITS_AVAILABLE: \"KOGUS{NEWLINE}SAADAVAL\"\n  STR_STOP_PRODUCTION: \"PEATA TOOTMINE\"\n  STR_ENGINEERS_AVAILABLE_UC: \"VABU INSENERE>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"TOOTMISES RUUMI>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"KASU KUU KOHTA>{ALT}{0}\"\n  STR_INCREASE_UC: \"SUURENDA\"\n  STR_DECREASE_UC: \"VÄHENDA\"\n  STR_UNITS_TO_PRODUCE: \"Ühikuid Toota\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Osta/Palka Personali\"\n  STR_COST_OF_PURCHASES: \"Ostmiste Koguhind>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"TÜKI HIND\"\n  STR_QUANTITY_UC: \"KOGUS\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"PERSONALI SAADAVAL:PERSONALI KOKKU>\"\n  STR_SOLDIERS: \"Sõdurid\"\n  STR_SCIENTISTS: \"Teadlased\"\n  STR_ENGINEERS: \"Insenerid\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"RUUMI KASUTATUD:RUUMI VABA>\"\n  STR_LIVING_QUARTERS: \"Majutus\"\n  STR_STORES: \"Ladu\"\n  STR_LABORATORIES: \"Laborid\"\n  STR_WORK_SHOPS: \"Töökoda\"\n  STR_HANGARS: \"Hangaar\"\n  STR_SHORT_RANGE_DETECTION: \"Lühikese maa tuvastus\"\n  STR_DEFENSE_STRENGTH: \"Kaitsetugevus\"\n  STR_TRANSFERS_UC: \"ÜLEKANDED\"\n  STR_TRANSFERS: \"Ülekanded\"\n  STR_ARRIVAL_TIME_HOURS: \"Jõuavad Kohale (tunnid)\"\n  STR_COST_: \"Hind>{ALT}{0}\"\n  STR_AREA_: \"Ala>{ALT}{0}\"\n  STR_BASE_NAME: \"Baasi Nimi?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"VALI ASUKOHT PEALIFTILE\"\n  STR_TRANSFER: \"Ülekanne\"\n  STR_AMOUNT_TO_TRANSFER: \"ÜLEKANDE KOGUS\"\n  STR_SELECT_DESTINATION_BASE: \"Vali Baasi Asukoht\"\n  STR_COST: \"Hind\"\n  STR_VICTORY_1: \"Kambrisse sisenedes näete tulnukaju - missiooni eesmärki. Enne kui suudate tuld avada , võtab see ühendust teiega baasis asuva ekraani kaudu. Aju palub, et kuulaksite ära tema argumendid tema ellujätmiseks, enne kui päästikule vajutate...\"\n  STR_VICTORY_2: \"Aju räägib: 'Palju miljoneid aastaid tagasi planeet mida te Marsiks kutsute oli elus. Elu tõime siia tühjale planeedile meie nagu seda tegime teie planeediga. Miljonite aastate jooksul külastasime teie planeeti ja geneetiliselt arendasime teie rassi. Te ei saa meid tappa, te olete osa meist...\"\n  STR_VICTORY_3: \"Siin Marsi tsivilisatsiooni keskus, püramiidides mis ehitati miljoneid aastaid varem teie omadest, rassi poolt keda võib pidada teie esiisadeks. Mitte ükski planeet pole meie jaoks kauge. See kõik võib mõne aja pärast kõik teile kuuluda. Ainuke mida me palume on koostöö...\"\n  STR_GAME_OVER_1: \"Tulnukad proovivad hävitada kogu inimkonda, purustades linnasid ning õhku ja merd mürgitades. Maa armeede vastupanu on mõttetu sellise tehnoloogilise üleoleku juures. Ellujäänud generatsioonid kannatavad hirmsate mutatsioonide käes kui nad püüavad tulnukate eest põgeneda. Nad korjatakse kokku orjalaagreisse, et aidata tulnukail muuta maa tulnukakolooniaks mingi tundmatu impeeriumi koosseisus.\"\n  STR_GAME_OVER_2: \"X-Comi projektiga saavutatud teadmised kadusid igavikku. Maa päästmine ebaõnnestus.\"\n  STR_VICTORY_4: \"Kuum plasmavalang lõpetab Tulnukaju eksistentsi ja kogu tulnukate vägi saab alistatud.\"\n  STR_VICTORY_5: \"Peale seda kui tulnukad kaotasid Marsil, kaotasid nad ka Maa. Peagi suuresti tänu X-Comi uurimustöödele suutis inimrass Marsi endale allutada. Ähvardavad tulnukpilved on kadunud kuid kui kauaks...\"\n  STR_YOU_HAVE_FAILED: \"Tulnukate pealetungi peatamine ebaõnnestus. Rahastust pakkunud riigid sõlmivad üksteise järel tulnukatega lepinguid, kes lubavad uusi tehnoloogiaid, jõukust ja rahu. Kuid mõne aja möödudes selgub tulnukate tõeline pale...\"\n  STR_TOTAL_UC: \"KOKKU\"\n  STR_INCOME: \"Sissetulek\"\n  STR_EXPENDITURE: \"Kulutused\"\n  STR_MAINTENANCE: \"Korrashoid\"\n  STR_BALANCE: \"Tasakaal\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"UFO aktiivsus regioonides.\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"UFO aktiivsus riikides\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"X-COMi aktiivsus regioonides\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"X-Comi aktiivsus riikides.\"\n  STR_FINANCE: \"Finants\"\n  STR_DATE_FIRST: \"{0}.\"\n  STR_DATE_SECOND: \"{0}.\"\n  STR_DATE_THIRD: \"{0}.\"\n  STR_DATE_FOURTH: \"{0}.\"\n  STR_FINANCE_THOUSANDS: \"$1000.\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Liiga vähe erikomponente, et toota {NEWLINE}{0}{NEWLINE}{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Liiga vähe raha, e toota {NEWLINE}{0}{NEWLINE}{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"{NEWLINE}{0}{NEWLINE}tootmine{NEWLINE}{1}{NEWLINE} on valmis.\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"{NEWLINE}{0}{NEWLINE}ehitamine{NEWLINE}{1}{NEWLINE} on valmis.\"\n  STR_OK_5_SECONDS: \"OK - 5 s\"\n  STR_RESEARCH_COMPLETED: \"Uurimine valmis\"\n  STR_VIEW_REPORTS: \"VAATA RAPORDIT\"\n  STR_WE_CAN_NOW_RESEARCH: \"Me saame nüüd uurida\"\n  STR_WE_CAN_NOW_PRODUCE: \"Me saame nüüd uurida\"\n  STR_SUNDAY: \"PÜHAPÄEV\"\n  STR_MONDAY: \"ESMASPÄEV\"\n  STR_TUESDAY: \"TEISIPÄEV\"\n  STR_WEDNESDAY: \"KOLMAPÄEV\"\n  STR_THURSDAY: \"NELJAPÄEV\"\n  STR_FRIDAY: \"REEDE\"\n  STR_SATURDAY: \"LAUPÄEV\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Liiga vähe {0} et tankida {1} {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Pole piisavalt {0} ,et taasrelvastada {1} {2}\"\n  STR_UFO_IS_NOT_RECOVERED: \"UFOt ei toodud kaasa.\"\n  STR_UFO_IS_RECOVERED: \"UFO toodi kaasa.\"\n  STR_CRAFT_IS_LOST: \"Kaotasime sõiduki.\"\n  STR_TERROR_CONTINUES: \"Terror jätkub\"\n  STR_ALIENS_DEFEATED: \"Tulnukad hävitatud\"\n  STR_BASE_IS_LOST: \"Baas kaotatud\"\n  STR_BASE_IS_SAVED: \"Baas päästetud\"\n  STR_ALIEN_BASE_STILL_INTACT: \"Tulnukate baas on ikka operatiivne\"\n  STR_ALIEN_BASE_DESTROYED: \"Tulnukate Baas hävitatud\"\n  STR_ALIENS_KILLED: \"TAPETUD TULNUKAID\"\n  STR_ALIEN_CORPSES_RECOVERED: \"Tulnukate kaasa toodud karkassid\"\n  STR_LIVE_ALIENS_RECOVERED: \"Elusalt tabatud tulnukad\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"Tulnukate vidinad leitud\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"TULNUKABAASI KONTROLLMOODUL HÄVITATUD\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"TULNUKATE POOLT TAPETUD TSIVIILID\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"X-COMI POOLT TAPETUD TSIVIILID\"\n  STR_CIVILIANS_SAVED: \"PÄÄSTETUD TSIVIILID\"\n  STR_XCOM_OPERATIVES_KILLED: \"LANGENUD X-COM OPERATIIVTÖÖTAJAD\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"LAHINGUS KADUMA JÄÄNUD X-COMI OPERATIIVTÖÖTAJAD\"\n  STR_TANKS_DESTROYED: \"HÄVITATUD TANKID\"\n  STR_XCOM_CRAFT_LOST: \"KAOTATUD X-COMI SÕIDUKID\"\n  STR_UFO_RECOVERY: \"UFO UTILISEERIMINE\"\n  STR_ALIEN_BASE_RECOVERY: \"TULNUKABAASI UTILISEERIMINE\"\n  STR_BASE_UNDER_ATTACK: \"{0} rünnatakse!\"\n  STR_BASE_DEFENSES_INITIATED: \"BAASI KAITSEMEHHANISMID ALUSTATUD\"\n  STR_FIRING: \"TULISTAMINE\"\n  STR_HIT: \"PIHTAS!\"\n  STR_UFO_DESTROYED: \"UFO HÄVITATUD!\"\n  STR_MISSED: \"MÖÖDA!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Müü Asju/Vallanda Personali\"\n  STR_SELL_SACK: \"Müü/Vallanda\"\n  STR_VALUE: \"Väärtus\"\n  STR_CRAFT_: \"ALUS> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"Kammi läbi maabumiskoht ning kui võimalik murra UFOsse sisse. Missioon loetakse õnnestunuks siis kui kõik tulnukad on hävitatud või neutraliseeritud. UFO, tulnukate laipade ja asjade kokkukorjamine algatatakse peale seda. Et missiooni katkestada, vii kõik X-Comi operatiivtöötajad transporterisse ja kliki 'Katkesta missioon' ikoonil.\"\n  STR_BASE_DEFENSE: \"BAASI KAITSE\"\n  STR_BASE_UC_: \"BAAS> {0}\"\n  STR_CYDONIA_BRIEFING: \"Olete jõudnud Cydoniasse. Sisenete suurde maaalusesse kompleksi Marsi sfinksi läheduses. Peate hävitama tulnukaju mis kontrollib kõiki tulnukate tegevusi. Inimkonna saatus on teie kätes..\"\n  STR_TERROR_MISSION: \"TERRORIRÜNNAK\"\n  STR_TERROR_MISSION_BRIEFING: \"Missioon on edukas siis kui kõik vaenlased on elimineeritud või neutraliseeritud. Peate proovima päästa piirkonnas olevaid tsiviilisikuid tulnukate nuhtluse eest. Missiooni katkestamiseks naase kõikide agentidega X-Comi sõiduki juurde ja vajuta 'Katkesta missioon' ikooni.\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"PUUDUB VABA ANGAAR SÕIDUKI TOOTMISEKS!{SMALLLINE}Iga baasi suunatud, ostetud või ehitatud sõiduk kasutab ühte angaari. Ehita uus angaar või suuna sõiduk teise baasi.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"PUUDUB VABA ANGAAR SÕIDUKI OSTMISEKS!{SMALLLINE}Iga baasi suunatud, ostetud või ehitatud sõiduk kasutab ühte angaari. Ehita uus angaar või suuna sõiduk teise baasi.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"PUUDUB VABA ANGAAR SÕIDUKI SUUNAMISEKS!{SMALLLINE}Iga baasi suunatud, ostetud või ehitatud sõiduk kasutab ühte angaari. Ehita uus angaar või suuna sõiduk teise baasi.\"\n  STR_CANNOT_BUILD_HERE: \"SIIA EI SAA EHITADA!{SMALLLINE}Peate ehitama olemasoleva rajatise kõrvale.\"\n  STR_NO_FREE_ACCOMODATION: \"POLE ROHKEM VOODIKOHTI!{SMALLLINE}Baasis pole rohkem eluruumi.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"POLE PIISAVALT TÖÖKOJA RUUMI SAADAVAL!{SMALLLINE}Ehita uus töökoda või vähenda teiste projektide tööd.\"\n  STR_NOT_ENOUGH_MONEY: \"POLE PIIRAVALT RAHA!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"POLE PIISAVALT LAORUUMI!{SMALLLINE}Ehitage uus laoruum või viige osad kaubad üle teistesse baasidesse.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"POLE PIISAVALT ELURUUME!{SMALLLINE}Ehita juurde eluruume või vii kaadrit üle teistesse baasidesse.\"\n  STR_CRAFT: \"ALUS\"\n  STR_STATUS: \"STAATUS\"\n  STR_BASE: \"BAAS\"\n  STR_READY: \"VALMIS\"\n  STR_OUT: \"VÄLJAS\"\n  STR_REPAIRS: \"PARANDUSED\"\n  STR_REFUELLING: \"KÜTUSE TANKIMINE\"\n  STR_REARMING: \"ÜMBER RELVASTUMINE\"\n  STR_TARGET: \"SIHTMÄRK: {0}\"\n  STR_ARE_YOU_SURE_CYDONIA: \"Olete kindel, et soovite seda alust saata Cydonia missioonile?\"\n  STR_YES: \"JAH\"\n  STR_NO: \"EI\"\n  STR_SELECT_DESTINATION: \"VALI ASUKOHT\"\n  STR_CYDONIA: \"CYDONIA\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"VALI UUE BAASI ASUKOHT\"\n  STR_RETURN_TO_BASE: \"TAGASI BAASI\"\n  STR_SELECT_NEW_TARGET: \"VALI UUS SIHTMÄRK\"\n  STR_PATROL: \"PATRULL\"\n  STR_STATUS_: \"STAATUS>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"VIGASTATUD - NAASEME BAASI\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"KÜTUST VÄHE - NAASEME BAASI\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"ÜLESANNE TÄIDETUD - NAASEME BAASI\"\n  STR_PATROLLING: \"PATRULLIMAS\"\n  STR_TAILING_UFO: \"UFO JÄLITAMINE\"\n  STR_INTERCEPTING_UFO: \"UFO-{0} RÜNDAMINE\"\n  STR_RETURNING_TO_BASE: \"TAGASI BAASI\"\n  STR_DESTINATION_UC_: \"SIHTPUNKT: {0}\"\n  STR_BASE_UC: \"BAAS>{ALT}{0}\"\n  STR_SPEED_: \"KIIRUS>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"TIPPKIIRUS>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"KÕRGUS>{ALT}{0}\"\n  STR_VERY_LOW: \"VÄGA MADAL\"\n  STR_LOW_UC: \"MADAL\"\n  STR_HIGH_UC: \"KÕRGE\"\n  STR_VERY_HIGH: \"VÄGA KÕRGE\"\n  STR_FUEL: \"KÜTUS>{ALT}{0}\"\n  STR_WEAPON_ONE: \"RELV-1>{ALT}{0}\"\n  STR_NONE_UC: \"EI OLE\"\n  STR_ROUNDS_: \"LASKE>{ALT}{0}\"\n  STR_WEAPON_TWO: \"RELV-2>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"RÜNDEALUSED\"\n  STR_BASE_: \"Baas>{0}\"\n  STR_NAME_UC: \"NIMI\"\n  STR_AMMO_: \"LASKEMOON>{ALT}{0}\"\n  STR_CREW: \"MEESKOND\"\n  STR_EQUIPMENT_UC: \"VARUSTUS\"\n  STR_ARMOR: \"TURVIS\"\n  STR_MAX: \"MAKS.>{ALT}{0}\"\n  STR_ROOKIE: \"Reamees\"\n  STR_SQUADDIE: \"Kapral\"\n  STR_SERGEANT: \"Seersant\"\n  STR_CAPTAIN: \"Kapten\"\n  STR_COLONEL: \"Kolonel\"\n  STR_COMMANDER: \"Komandör\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Vali meeskond {0} jaoks\"\n  STR_SORT_BY: \"SORTEERI\"\n  STR_ORIGINAL_ORDER: \"ORIGINAALNE JÄRJESTUS\"\n  STR_MISSIONS2: \"MISSIOONID\"\n  STR_KILLS2: \"VÕIDUD\"\n  STR_WOUND_RECOVERY2: \"HAAVADES PARANEMINE\"\n  STR_SPACE_AVAILABLE: \"VABARUUMI>{ALT}{0}\"\n  STR_RANK: \"AUASTE\"\n  STR_WOUNDED: \"HAAVATUD\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Varustus {0}\"\n  STR_DEFENSE_VALUE: \"Kaitse väärtus\"\n  STR_HIT_RATIO: \"Tabamisprotsent\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}valmis{NEWLINE}maanduma{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"Alusta Missiooni?\"\n  STR_SELECT_ARMAMENT: \"Vali relvastus\"\n  STR_AMMUNITION_AVAILABLE: \"OLEMASOLEV LASKEMOON\"\n  STR_ARMAMENT: \"RELVASTUS\"\n  STR_NOT_AVAILABLE: \"PUUDUB\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"VALI TURVIS{NEWLINE}{0}\"\n  STR_TYPE: \"TÜÜP\"\n  STR_PERSONAL_ARMOR_UC: \"ISIKLIK TURVIS\"\n  STR_POWER_SUIT_UC: \"JÕUTURVIS\"\n  STR_FLYING_SUIT_UC: \"LENNUTURVIS\"\n  STR_SELECT_ARMOR: \"Vali Turvise\"\n  STR_NORTH: \"PÕHI\"\n  STR_NORTH_EAST: \"KIRRE\"\n  STR_EAST: \"IDA\"\n  STR_SOUTH_EAST: \"KAGU\"\n  STR_SOUTH: \"LÕUNA\"\n  STR_SOUTH_WEST: \"EDEL\"\n  STR_WEST: \"LÄÄS\"\n  STR_NORTH_WEST: \"Loe\"\n  STR_SELECT_ACTION: \"VALI TEGEVUS\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"JÄTKA RÜNNAKUT\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"JÄLITA ILMA RÜNDAMATA\"\n  STR_VERY_LARGE: \"VÄGA SUUR\"\n  STR_LARGE: \"SUUR\"\n  STR_MEDIUM_UC: \"KESKMINE\"\n  STR_SMALL: \"VÄIKE\"\n  STR_VERY_SMALL: \"VÄGA VÄIKE\"\n  STR_GROUNDED: \"MAAPIND\"\n  STR_DETECTED: \"Avastatud\"\n  STR_SIZE_UC: \"SUURUS\"\n  STR_ALTITUDE: \"KÕRGUS\"\n  STR_HEADING: \"KURSS\"\n  STR_SPEED: \"KIIRUS\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"UFO KESKEÖE-AEG=5 S\"\n  STR_TRACKING_LOST: \"KADUS RADARILT\"\n  STR_REDIRECT_CRAFT: \"SUUNA ALUS ÜMBER\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"MINE VIIMASESSE TEATATUD ASUKOHTA\"\n  STR_UFO_: \"UFO-{0}\"\n  STR_ALIEN_BASE_: \"TULNUKATE BAAS-{0}\"\n  STR_LANDING_SITE_: \"MAANDUMIS PLATS-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}jõudis{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"Patrullimas\"\n  STR_ALIEN_ORIGINS: \"Tulnukate päritolu\"\n  STR_THE_MARTIAN_SOLUTION: \"Marsi Lahendus\"\n  STR_CYDONIA_OR_BUST: \"Cydonia või surm\"\n  STR_UFOPAEDIA: \"UFOpedia\"\n  STR_XCOM_CRAFT_ARMAMENT: \"X-COMi alused ja relvastus\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"RELVAPLATFORMID\"\n  STR_WEAPONS_AND_EQUIPMENT: \"RELVAD JA VARUSTUS\"\n  STR_ALIEN_ARTIFACTS: \"TULNUKATE VIDINAD\"\n  STR_BASE_FACILITIES: \"BAASI RAJATISED\"\n  STR_ALIEN_LIFE_FORMS: \"TULNUKATE RASSID\"\n  STR_ALIEN_RESEARCH_UC: \"TULNUKATE TEADUSTÖÖ\"\n  STR_UFO_COMPONENTS: \"UFO KOMPONENDID\"\n  STR_UFOS: \"UFOd\"\n  STR_SELECT_ITEM: \"Vali\"\n  STR_ACCELERATION: \"KIIRENDUS>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"KÜTUSE MAHUTUVUS>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Kahjustused\"\n  STR_RANGE: \"Raadius\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Täpsus\"\n  STR_RE_LOAD_TIME: \"Laadimis aeg\"\n  STR_SECONDS: \"{0} sek\"\n  STR_DAMAGE_ARMOR_PIERCING: \"SOOMUSLÄBISTATAVUS\"\n  STR_DAMAGE_LASER_BEAM: \"LASERKIIR\"\n  STR_DAMAGE_PLASMA_BEAM: \"PLASMAKIIR\"\n  STR_DAMAGE_STUN: \"UIMASTAMA\"\n  STR_DAMAGE_MELEE: \"KÄSIVÕITLUS\"\n  STR_DAMAGE_ACID: \"HAPE\"\n  STR_DAMAGE_SMOKE: \"SUITS\"\n  STR_SHOT_TYPE: \"LASU TÜÜP\"\n  STR_ACCURACY_UC: \"TÄPSUS\"\n  STR_TIME_UNIT_COST: \"AÜ MAKSUMUS\"\n  STR_DAMAGE_UC: \"KAHJUSTUSED\"\n  STR_AMMO: \"LASKEMOON\"\n  STR_SHOT_TYPE_AUTO: \"Automaatne\"\n  STR_SHOT_TYPE_SNAP: \"Puusalt\"\n  STR_SHOT_TYPE_AIMED: \"Sihitud\"\n  STR_CONSTRUCTION_TIME: \"Ehituse aeg\"\n  STR_CONSTRUCTION_COST: \"Ehituse Hind\"\n  STR_MAINTENANCE_COST: \"Korrashoiu hind\"\n  STR_LOW: \"Madal\"\n  STR_MEDIUM: \"Keskmine\"\n  STR_HIGH: \"Kõrge\"\n  STR_CRAFT_WEAPON: \"Aluse relvad\"\n  STR_CRAFT_AMMUNITION: \"Aluse laskemoon\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Relvaplatformid\"\n  STR_WEAPON: \"Relv\"\n  STR_AMMUNITION: \"Laskemoon\"\n  STR_EQUIPMENT: \"Varustus\"\n  STR_ALIEN_CORPSE: \"Tulnuka laip\"\n  STR_UFO_COMPONENT: \"UFO komponent\"\n  STR_PERSONAL_ARMOR: \"Isiklik Turvis\"\n  STR_RAW_MATERIALS: \"Toorained\"\n  STR_HWP_CANNON_SHELLS: \"RRP kahurimürsud\"\n  STR_ALIEN: \"Tulnukas\"\n  STR_SECTOID: \"Sektoid\"\n  STR_SNAKEMAN: \"Ussimees\"\n  STR_ETHEREAL: \"Taevane\"\n  STR_MUTON: \"Mutoon\"\n  STR_FLOATER: \"Lendaja\"\n  STR_CELATID: \"Celatiid\"\n  STR_SILACOID: \"Silacoid\"\n  STR_CHRYSSALID: \"Krüssaliid\"\n  STR_ZOMBIE: \"Zombie\"\n  STR_REAPER: \"Pussitaja\"\n  STR_SECTOPOD: \"Sektopod\"\n  STR_CYBERDISC: \"Küberketas\"\n  STR_LIVE_COMMANDER: \"Komandör\"\n  STR_LIVE_LEADER: \"Juht\"\n  STR_LIVE_ENGINEER: \"Insener\"\n  STR_LIVE_MEDIC: \"Meedik\"\n  STR_LIVE_NAVIGATOR: \"Navigaator\"\n  STR_LIVE_SOLDIER: \"Sõdur\"\n  STR_LIVE_TERRORIST: \"Terrorist\"\n  STR_FLOATER_SOLDIER: \"Lendaja Sõdur\"\n  STR_FLOATER_NAVIGATOR: \"Lendaja Navigaator\"\n  STR_FLOATER_MEDIC: \"Lendaja Meedik\"\n  STR_FLOATER_ENGINEER: \"Lendaja Insener\"\n  STR_FLOATER_LEADER: \"Lendaja Juht\"\n  STR_FLOATER_COMMANDER: \"Lendaja Komandör\"\n  STR_SECTOID_SOLDIER: \"Sektoid Sõdur\"\n  STR_SECTOID_NAVIGATOR: \"Sektoid Navigaator\"\n  STR_SECTOID_MEDIC: \"Sektoid Meedik\"\n  STR_SECTOID_ENGINEER: \"Sektoid Insener\"\n  STR_SECTOID_LEADER: \"Sektoid Juht\"\n  STR_SECTOID_COMMANDER: \"Sektoid Komandör\"\n  STR_SNAKEMAN_SOLDIER: \"Ussimees Sõdur\"\n  STR_SNAKEMAN_NAVIGATOR: \"Ussimees Navigaator\"\n  STR_SNAKEMAN_ENGINEER: \"Ussimees Insener\"\n  STR_SNAKEMAN_LEADER: \"Ussimees Juht\"\n  STR_SNAKEMAN_COMMANDER: \"Ussimees Komandör\"\n  STR_MUTON_SOLDIER: \"Mutoon Sõdur\"\n  STR_MUTON_NAVIGATOR: \"Mutoon Navigaator\"\n  STR_MUTON_ENGINEER: \"Mutoon Insener\"\n  STR_ETHEREAL_SOLDIER: \"Taevane Sõdur\"\n  STR_ETHEREAL_LEADER: \"Taevane Juht\"\n  STR_ETHEREAL_COMMANDER: \"Taevane Komandör\"\n  STR_CYBERDISC_TERRORIST: \"Küberketas Terrorist\"\n  STR_REAPER_TERRORIST: \"Pussitaja Terrorist\"\n  STR_CHRYSSALID_TERRORIST: \"Krüssaliid Terrorist\"\n  STR_CELATID_TERRORIST: \"Celatiidi terrorist\"\n  STR_SILACOID_TERRORIST: \"Silacoidi terrorist\"\n  STR_SECTOPOD_TERRORIST: \"Sectopod terrorist\"\n  STR_UFO_POWER_SOURCE: \"UFO jõuallikas\"\n  STR_UFO_NAVIGATION: \"UFO navigatsiooniseade\"\n  STR_UFO_CONSTRUCTION: \"UFO ehitus\"\n  STR_ALIEN_FOOD: \"Tulnukate Toit\"\n  STR_ALIEN_REPRODUCTION: \"Tulnukate paljunemine\"\n  STR_ALIEN_ENTERTAINMENT: \"Tulnukate meelelahutus\"\n  STR_ALIEN_SURGERY: \"Tulnukate operatsioonisaal\"\n  STR_EXAMINATION_ROOM: \"Uurimisruum\"\n  STR_ALIEN_ALLOYS: \"Tulnukate sulam\"\n  STR_ALIEN_HABITAT: \"Tulnukate elukoht\"\n  STR_POWER_SUIT: \"Jõuturvis\"\n  STR_FLYING_SUIT: \"Lennuturvis\"\n  STR_HWP_ROCKETS: \"RRP raketid\"\n  STR_LASER_WEAPONS: \"Laser relvad\"\n  STR_NEW_FIGHTER_CRAFT: \"Uus hävituslennuk\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Uus hävitus-transporter\"\n  STR_ULTIMATE_CRAFT: \"Ülim õhusõiduk\"\n  STR_LASER_PISTOL: \"Laserpüstol\"\n  STR_LASER_RIFLE: \"Laser Püss\"\n  STR_HEAVY_LASER: \"Raskelaser\"\n  STR_LASER_CANNON: \"Laserkahur\"\n  STR_PLASMA_CANNON: \"Plasmakahur\"\n  STR_LASER_DEFENSE: \"Laserpatarei\"\n  STR_PLASMA_DEFENSE: \"Plasmapatarei\"\n  STR_MIND_SHIELD: \"Meelekilp\"\n  STR_PSI_LAB: \"Psi-Labor\"\n  STR_MOTION_SCANNER: \"Liikumisskanner\"\n  STR_MEDI_KIT: \"Ravimikott\"\n  STR_TANK_CANNON: \"Tank/Kahur\"\n  STR_TANK_ROCKET_LAUNCHER: \"Tank/Raketiheitja\"\n  STR_TANK_LASER_CANNON: \"Tank/Laser\"\n  STR_HOVERTANK_PLASMA: \"Hõljuktank/plasma\"\n  STR_HOVERTANK_LAUNCHER: \"Hõljuktank/Pommiheitja\"\n  STR_STINGRAY_LAUNCHER: \"Stingray heitur\"\n  STR_AVALANCHE_LAUNCHER: \"Avalanche heitur\"\n  STR_CANNON: \"Kahur\"\n  STR_STINGRAY_MISSILES: \"Stingray raketid\"\n  STR_AVALANCHE_MISSILES: \"Avalanche raketid\"\n  STR_CANNON_ROUNDS_X50: \"kahurimürsud(x50)\"\n  STR_SOLDIER: \"Sõdur\"\n  STR_SCIENTIST: \"Teadlane\"\n  STR_ENGINEER: \"Insener\"\n  STR_NORTH_AMERICA: \"Põhja-Ameerika\"\n  STR_ARCTIC: \"Arktika\"\n  STR_ANTARCTICA: \"Antartika\"\n  STR_SOUTH_AMERICA: \"Lõuna Ameerika\"\n  STR_EUROPE: \"Euroopa\"\n  STR_NORTH_AFRICA: \"Põhja-Aafrika\"\n  STR_SOUTHERN_AFRICA: \"Lõuna-Aafrika\"\n  STR_CENTRAL_ASIA: \"Kesk-Aasia\"\n  STR_SOUTH_EAST_ASIA: \"Kagu-Aasia\"\n  STR_SIBERIA: \"Siber\"\n  STR_AUSTRALASIA: \"Australaasia\"\n  STR_PACIFIC: \"Vaikne Ookean\"\n  STR_NORTH_ATLANTIC: \"Põhja-Atlant\"\n  STR_SOUTH_ATLANTIC: \"Lõuna-Atlant\"\n  STR_INDIAN_OCEAN: \"India Ookean\"\n  STR_ALIEN_RESEARCH: \"Tulnukate uurimusretk\"\n  STR_ALIEN_HARVEST: \"Tulnukate koristusretk\"\n  STR_ALIEN_ABDUCTION: \"Tulnukröövid\"\n  STR_ALIEN_BASE: \"Tulnukate Baas\"\n  STR_ALIEN_TERROR: \"Tulnukterror\"\n  STR_ALIEN_RETALIATION: \"Tulnukate vastulöök\"\n  STR_ALIEN_SUPPLY: \"Tulnukate varustusretk\"\n  STR_MAXIMUM_SPEED: \"Tippkiirus\"\n  STR_SKYRANGER: \"SKYRANGER\"\n  STR_LIGHTNING: \"VÄLK\"\n  STR_AVENGER: \"TASUJA\"\n  STR_INTERCEPTOR: \"HÄVITAJA\"\n  STR_FIRESTORM: \"TULETORM\"\n  STR_UFO: \"UFO\"\n  STR_STINGRAY: \"STINGRAY\"\n  STR_AVALANCHE: \"AVALANCHE\"\n  STR_CANNON_UC: \"KAHUR\"\n  STR_LASER_CANNON_UC: \"LASER KAHUR\"\n  STR_PLASMA_BEAM_UC: \"PLASMAKIIR\"\n  STR_WEAPON_RANGE: \"Relva Ulatuvus\"\n  STR_ACCESS_LIFT: \"Juurdepääsulift\"\n  STR_LABORATORY: \"Labor\"\n  STR_WORKSHOP: \"Töökoda\"\n  STR_SMALL_RADAR_SYSTEM: \"Väike Radari Süsteem\"\n  STR_LARGE_RADAR_SYSTEM: \"Suur Radari Süsteem\"\n  STR_MISSILE_DEFENSES: \"Raketipatareid\"\n  STR_GENERAL_STORES: \"Laoruumid\"\n  STR_ALIEN_CONTAINMENT: \"Tulnukate vangla\"\n  STR_LASER_DEFENSES: \"Laserpatareid\"\n  STR_PLASMA_DEFENSES: \"Plasmapatareid\"\n  STR_PSIONIC_LABORATORY: \"Psüühiline Labor\"\n  STR_HANGAR: \"Angaar\"\n  STR_USA: \"USA\"\n  STR_RUSSIA: \"VENEMAA\"\n  STR_UK: \"ÜHENDKUNINGRIIK\"\n  STR_FRANCE: \"PRANTSUSMAA\"\n  STR_GERMANY: \"SAKSAMAA\"\n  STR_ITALY: \"ITAALIA\"\n  STR_SPAIN: \"HISPAANIA\"\n  STR_CHINA: \"HIINA\"\n  STR_JAPAN: \"JAAPAN\"\n  STR_INDIA: \"INDIA\"\n  STR_BRAZIL: \"BRASIILIA\"\n  STR_AUSTRALIA: \"AUSTRAALIA\"\n  STR_NIGERIA: \"NIGEERIA\"\n  STR_SOUTH_AFRICA: \"LÕUNA-AAFRIKA\"\n  STR_EGYPT: \"EGIPTUS\"\n  STR_CANADA: \"KANADA\"\n  STR_TANK: \"Tank\"\n  STR_CIVILIAN: \"Tsivilist\"\n  STR_JAN: \"Jan\"\n  STR_FEB: \"Veeb\"\n  STR_MAR: \"Mär\"\n  STR_APR: \"Apr\"\n  STR_MAY: \"Mai\"\n  STR_JUN: \"Jun\"\n  STR_JUL: \"Jul\"\n  STR_AUG: \"Aug\"\n  STR_SEP: \"Sept\"\n  STR_OCT: \"Okt\"\n  STR_NOV: \"Nov\"\n  STR_DEC: \"Dets\"\n  STR_INTERNATIONAL_RELATIONS: \"Rahvusvahelised suhted\"\n  STR_COUNTRY: \"Riik\"\n  STR_FUNDING: \"Rahastus\"\n  STR_CHANGE: \"Muuda\"\n  STR_WEAPON_SYSTEMS: \"RELVASÜSTEEMID\"\n  STR_HWPS: \"RRPd\"\n  STR_DAMAGE_UC_: \"KAHJUSTUSED>{ALT}{0}\"\n  STR_ACCESS_LIFT_UFOPEDIA: \"Juurdepääsulift võimaldab varustust ja töötajaid maaalusese baasi sisse ja välja liigutada. See on alati esimene rajatis mis uue baasi puhul valmis ehitatakse. Potensiaalsed vaenulikud jõud võivad lifti kaudu baasi sisse tungida. \"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Igas majutusblokis on ruumi kuni 50 inimesele. Rajatis pakub elementaarset meelelahutust, söömis ja magamisruume.\"\n  STR_LABORATORY_UFOPEDIA: \"Laboratooriumis on töökohti kuni 50 teadlasele. Labor on varustatud tehnoloogia viimase sõnaga materjalide, biokeemia ja kosmoloogiaga tegelemiseks. Laboril on priviligeeritud juurdepääs parimatele teaduslaboritele üle maailma, kaasaarvatud sõjavägede kontrolli all olevatele.\"\n  STR_WORKSHOP_UFOPEDIA: \"Töökoda sisaldab kõik vajaliku, et toota varustust teaduslaborist tulevate projektide alusel. Töökohti on kuni 50 insenerile kuigi ruumi vajavad ka tootmises olevad tooted.\"\n  STR_SMALL_RADAR_SYSTEM_UFOPEDIA: \"Väikesel avastussüsteemil on efektiivne radari kaugus 300 meremiili ning on ühendatud sateliitsüsteemiga, maapealseks seireks. Igal süsteemil on 10% suurus avastamaks keskmise suurusega objekte iga 30 minuti tagant.\"\n  STR_LARGE_RADAR_SYSTEM_UFOPEDIA: \"Suurel avastussüsteemil on efektiivne radari kaugus 450 meremiili ning on ühendatud sateliitsüsteemiga maapealseks seireks. Igal süsteemil on 20% suurus avastamaks keskmise suurusega objekte iga 30 minuti tagant.\"\n  STR_MISSILE_DEFENSES_UFOPEDIA: \"Raketipatareid pakuvad mõnigat kaitset vaenulike lennuvahendite sissetungi vastu, mis püüavad baasi läheduses maanduda.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"Kõik varustus, relvasüsteemid, lasemoon, sõjasaak ja raskerelva platformid pannakse lattu, kaasaarvatud varustus mida kasutatakse angaaris asuvate sõidukite juures.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"Elusad tulnukad vajavad eluspüsimiseks omale sobivat elukeskkonda. Kinnipidamisasutuses on ruumi kuni kümnele tulnukate eluvormile.\"\n  STR_LASER_DEFENSES_UFOPEDIA: \"Laserkaitse pakub kaitset tulnukate rünnakute eest.\"\n  STR_PLASMA_DEFENSES_UFOPEDIA: \"Plasmakaitse pakub head ja efektiivset kaitset tulnukate rünnakute vastu.\"\n  STR_HANGAR_UFOPEDIA: \"Iga angaar suudab majutada ühte lennuvahendit. Angaar sisaldab rajatisi hoolduseks, tankimiseks ja parandamiseks. Igale baasis asuvale lennuvahendile on määratud kindel angaar, mida ei saa kasutada teised lennuvahendid isegi siis kui sõiduk on parajasti missioonil.\"\n  STR_PISTOL_UFOPEDIA: \"Standartne X-Comi püstol on poolautomaate ning 12 kuuliga.\"\n  STR_RIFLE_UFOPEDIA: \"See väga täpne snaiperrelv on lasersihikuga ning magasini mahub 20 6.7mm kuuli.\"\n  STR_HEAVY_CANNON_UFOPEDIA: \"Raskekahur on suure hävitusjõuga kuid väga tülikas relv. Relva mitmekülgsus tuleneb kolmest erinevast laskemoonast: soomusläbistav, süütav ja plahvatav.\"\n  STR_AUTO_CANNON_UFOPEDIA: \"Automaatkahur kombineerib raskekahuri mitmekülgsuse kiirema tulejõuga.\"\n  STR_ROCKET_LAUNCHER_UFOPEDIA: \"Raketiheitja on laserjuhitav relvasüsteem, millega saab välja lasta kolme erinevat raketti.\"\n  STR_LASER_PISTOL_UFOPEDIA: \"Laserpüstol on uue tehnoloogia efektiivne teostus. Ta on tavalise püstoli mugavustega kuid kiirem ja täpsem.\"\n  STR_LASER_RIFLE_UFOPEDIA: \"Laserpüss on võimsam ja täpsem versioon eelnevast laserpüstoli konstruktsioonist.\"\n  STR_HEAVY_LASER_UFOPEDIA: \"Raskelaser on kobakas kuid väga efektiivne relv.\"\n  STR_GRENADE_UFOPEDIA: \"Standartne granaat oma keerulist kuid täpset ajamõõtjat.\"\n  STR_SMOKE_GRENADE_UFOPEDIA: \"Suitsugranaadid on kasulikud loomaks varjumisvõimalusi muidu avatud lahingusituatsioonides. Kasuta ettevaatlikult, sest ka vaenlased võivad neist kasu lõigata.\"\n  STR_HIGH_EXPLOSIVE_UFOPEDIA: \"Seda lõhkeseadeldist peaks kasutama ainult purustuse eesmärkidel. Hoia meeskond plahvatusraadiusest väljas.\"\n  STR_STUN_ROD_UFOPEDIA: \"Seda riistapuud saab kasutada ainult lähivõitluses, kuid see uimastab elektrishokiga elusorganisme neid tapmata.\"\n  STR_MIND_PROBE_UFOPEDIA: \"Meeleurkel on tulnukate kommunikatsiooniseadeldis, mida kasutatakse info hankimiseks otse ajust. X-Comi võitlejad saavad seda seadet lahingus kasutada tulnukate karakteristika näitamiseks. Kliki meeleurkelile ja \\\"kasuta\\\" valikut ning siis kliki kursoriga tulnukale.\"\n  STR_ALIEN_GRENADE_UFOPEDIA: \"See riistapuu töötab sarnaselt maa granaadiga, kuid on tunduvalt võimsam.\"\n  STR_SMALL_SCOUT: \"Väike Eelluurelaev\"\n  STR_MEDIUM_SCOUT: \"Keskmine Eelluurelaev\"\n  STR_LARGE_SCOUT: \"Suur Eelluurelaev\"\n  STR_HARVESTER: \"Kombain\"\n  STR_ABDUCTOR: \"Röövija\"\n  STR_TERROR_SHIP: \"Terrori laev\"\n  STR_BATTLESHIP: \"Lahinglaev\"\n  STR_SUPPLY_SHIP: \"Varustuslaev\"\n  STR_RATING: \"HINNANG> {0}\"\n  STR_RATING_TERRIBLE: \"KOHUTAV!\"\n  STR_RATING_POOR: \"KEHVA!\"\n  STR_RATING_OK: \"OK\"\n  STR_RATING_GOOD: \"HEA!\"\n  STR_RATING_EXCELLENT: \"SUUREPÄRANE!\"\n  STR_SCORE: \"TULEMUS\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"X-COM PROJEKTI KUUKOKKUVÕTE\"\n  STR_MONTH: \"Kuu> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"Finantseerimist pakkuvad riigid on siiamaani üldiselt rahul teie tegevusega.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"Finantseerimist pakkuvad riigid on väga rahul teie suurepäraste tulemustega. Jätkake samas vaimus!\"\n  STR_COUNCIL_IS_DISSATISFIED: \"Finantseerimiskonsiilium ei ole rahul teie tegevusega. Te peate oma efektiivsust suurendama tulnukate hädaohuga tegelemisel, et mitte riskeerida projekti lõpetamisega.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"Olete ebaõnnestunud tulnukate invasiooni tõrjumisel ning finantskonsiilium on kahjuks otsustanud projekt peatada. Iga riik tegeleb probleemiga omaette nii nagu heaks arvab. Me saame ainult loota, et suudame kuidagi kohaneda ilmselgelt vaenulike jõududa ning inimkond suudab kuidagi tulnukatega kokkuleppele jõuda.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} on eriti rahul teie tegevusega kohaliku ohu neutraliseerimisega ning on nõustunud rahastust suurendama.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} on eriti rõõmus teie tegevusega kohaliku tulnukate sissetungi neutraliseerimisega ning on nõustunud rahastust suurendama.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} ja {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} ei ole rahul sinu võimega tulla toime tulnukatega oma territooriumil ja otsustas vähendada oma finantsosalust.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} ei ole rahul sinu võimega tulla toime tulnukatega oma territooriumitel ja otsustasid vähendada oma finantsosalust.\"\n  STR_KNOTS: \"{0} sõlme\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} kirjutas alla paktile tundmatute tulnukate jõududega ning taandas ennast projektist.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} on alla kirjutanud paktile tundmatute tulnukate jõududega ning on projektist taandunud.\"\n  STR_COUNCIL_REDUCE_DEBTS: \"Rahastuskonsiilium ei ole rahul teie finantspositsiooniga. Te peate oma võlgu vähendama alla $1 miljoni või projekt lõpetatakse.\"\n  STR_CRAFT_TYPE: \"ALUSE TÜÜP\"\n  STR_RACE: \"RASS\"\n  STR_MISSION: \"MISSIOON\"\n  STR_ZONE: \"TSOON\"\n  STR_ALLOCATE_RESEARCH: \"Määra teaduslik töö\"\n  STR_ALLOCATE_MANUFACTURE: \"Määra tootmine\"\n  STR_NEW_YORK: \"New York\"\n  STR_WASHINGTON: \"Washington\"\n  STR_LOS_ANGELES: \"Los Angeles\"\n  STR_MONTREAL: \"Montreal\"\n  STR_HAVANA: \"Havana\"\n  STR_MEXICO_CITY: \"Mexico City\"\n  STR_CHICAGO: \"Chicago\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_DALLAS: \"Dallas\"\n  STR_BRASILIA: \"Brasiilia\"\n  STR_BOGOTA: \"Bogota\"\n  STR_BUENOS_AIRES: \"Buenos Aires\"\n  STR_SANTIAGO: \"Santiago\"\n  STR_RIO_DE_JANEIRO: \"Rio De Janeiro\"\n  STR_LIMA: \"Lima\"\n  STR_CARACAS: \"Caracas\"\n  STR_LONDON: \"London\"\n  STR_PARIS: \"Pariis\"\n  STR_BERLIN: \"Berliin\"\n  STR_MOSCOW: \"Moskva\"\n  STR_ROME: \"Rooma\"\n  STR_MADRID: \"Mardiid\"\n  STR_BUDAPEST: \"Budapest\"\n  STR_LAGOS: \"Lagos\"\n  STR_CAIRO: \"Kairo\"\n  STR_CASABLANCA: \"Casablanca\"\n  STR_PRETORIA: \"Pretoria\"\n  STR_NAIROBI: \"Nairobi\"\n  STR_CAPE_TOWN: \"Cape Town\"\n  STR_KINSHASA: \"Kinshasa\"\n  STR_ANKARA: \"Ankara\"\n  STR_DELHI: \"Delhi\"\n  STR_KARACHI: \"Karachi\"\n  STR_BAGHDAD: \"Bagdad\"\n  STR_TEHRAN: \"Teheran\"\n  STR_BOMBAY: \"Bombay\"\n  STR_CALCUTTA: \"Kalkutta\"\n  STR_TOKYO: \"Tokio\"\n  STR_BEIJING: \"Peking\"\n  STR_BANGKOK: \"Bangkok\"\n  STR_MANILA: \"Manila\"\n  STR_SEOUL: \"Seoul\"\n  STR_SINGAPORE: \"Singapur\"\n  STR_JAKARTA: \"Jakarta\"\n  STR_SHANGHAI: \"Shanghai\"\n  STR_HONG_KONG: \"Hong Kong\"\n  STR_NOVOSIBIRSK: \"Novosibirsk\"\n  STR_CANBERRA: \"Canberra\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_MELBOURNE: \"Melbourne\"\n  STR_PERTH: \"Perth\"\n  STR_PSI_TRAINING: \"Psitreening\"\n  STR_PSIONIC_TRAINING: \"PSÜÜHILINE TREENING\"\n  STR_IN_TRAINING: \"Treenimisel?\"\n  STR_TARGETTED_BY: \"SIHIKUL:\"\n  STR_WEAPONS_CREW_HWPS: \"RELVASTUS/{NEWLINE}MEESKOND/RRPid\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"kütus hakkab otsa saama,{NEWLINE}naaseme baasi.\"\n  STR_SOLDIER_LIST: \"Sõdurite Nimekiri\"\n  STR_RANK_: \"AUASTE> {ALT}{0}\"\n  STR_MISSIONS: \"MISSIOONID> {ALT}{0}\"\n  STR_KILLS: \"TAPMISED>{ALT}{0}\"\n  STR_WOUND_RECOVERY: \"HAAVADEST PARANEMINE> {ALT}{0}\"\n  STR_TIME_UNITS: \"AJA ÜHIKUD\"\n  STR_STAMINA: \"VASTUPIDAVUS\"\n  STR_HEALTH: \"TERVIS\"\n  STR_BRAVERY: \"JULGUS\"\n  STR_REACTIONS: \"REAKTSIOONID\"\n  STR_FIRING_ACCURACY: \"LASKE TÄPSUS\"\n  STR_THROWING_ACCURACY: \"VISKE TÄPSUS\"\n  STR_STRENGTH: \"TUGEVUS\"\n  STR_PSIONIC_STRENGTH: \"PSÜÜHILINE TUGEVUS\"\n  STR_PSIONIC_SKILL: \"PSÜÜHILINE OSKUS\"\n  STR_NEW_RANK: \"UUS AUASTE\"\n  STR_PROMOTIONS: \"Edutamised\"\n  STR_SOLDIERS_UC: \"SÕDURID\"\n  STR_TANK_CANNON_UFOPEDIA: \"Automatiseeritud raskerelvaplatfromid on välja töötatud täiendamaks X-Comi rühmasid. Tugevast soomusest ja tulejõust kombinatsioon teeb need üksused väga väärtuslikuks lahingutes avatud maastikul. Veendu et ladudes oleks piisavalt mürske, sest RRP laetakse automaatselt kui nad lisatakse X-Comi rühmale.\"\n  STR_TANK_ROCKET_LAUNCHER_UFOPEDIA: \"See automatiseeritud raskerelvade platform omab relvastuses võimsaid rakette, millede hävitusjõust piisab igasuguste vaenlaste vastu. Veendu, et laod oleksid kogu aeg varustatud RRP rakettidega.\"\n  STR_TANK_LASER_CANNON_UFOPEDIA: \"RRPle lisatud laserrelvad on kasulik lisand, tugevam tulejõud ilma laskemoona piiranguteta.\"\n  STR_HOVERTANK_PLASMA_UFOPEDIA: \"Tulnukate tehnoloogia on andnud RRPle uue hingamise. Lisatud õhus manööverdamine ja plasmarelvad on letaalne kombinatsioon.\"\n  STR_HEAVY_PLASMA_CLIP_UFOPEDIA: \"Seda kompaktset seadeldist kasutatakse Raske plasmarelva laskemoonana. Sisaldab vähesel määral eleriumi.\"\n  STR_PLASMA_RIFLE_CLIP_UFOPEDIA: \"See väike objekt on salveks plasmapüssile - keskmise tugevusega tulnukate relvale. Sisaldab väikest kogust Eleriumi.\"\n  STR_PLASMA_PISTOL_CLIP_UFOPEDIA: \"Plasmapüstoli jõuallikas. Sisaldab eleriumi.\"\n  STR_STUN_BOMB_UFOPEDIA: \"Uimapommi kasutatakse elusate inimsubjektide püüdmiseks, kuid sobib ka enamuste tulnukrasside vastu. Pomm lastakse välja väikesest heitjast.\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"Inimeste välimusega tulnukate agendid võivad infliteeruda erinevate riikide valitsustesse. See võimaldab kõrgetasemelisi kontakte tulnukate ja valitsuste vahel. Kontaktide märgiks on tihe UFOde aktiivsus suurlinnade ümbruses. Tulnukad püüavad sõlmida pakti valitsustega pakkudes teadmisi ja uuemat tehnoloogiat. Vastutasuks lubab valitsus jätkata tulnukatel oma tegevusi segamatult. See tulnukate missioon on X-Comi jaoks kõige ohtlikum, sest kui valitsus sõlmib pakti siis rahastus kaob.\"\n  STR_ALIEN_BASE_UFOPEDIA: \"Tulnukad ehitavad salajasi maaaluseid baase kõrvalistesse kohtadesse. Peale algseid luurelende suureneb UFOde aktiivsus tunduvalt, sest käib baasiehitus. Baasides asuvad laborid, et sooritada eksperimente röövitud inimeste peal ning varustus toetamaks edasist tegevust regioonis. Tulnukabaasi olemasolu genereerib suurt arvu raporteeritud tulnukate aktiivsust piirkonnas ilma UFOde kohaloluta. Et baasi leida peab X-Comi lennuvahend piirkonnas patrulllende sooritama.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"Peale seda kui tulnukate baas on valmis varustatakse seda regulaarselt eriliste varustuslaevadega. Kui avastakse ühe sellise laeva maabumine siis võib kindel olla, et läheduses asub tulnukate baas.\"\n  STR_SMALL_SCOUT_UFOPEDIA: \"Seda tillukest sõidukit kasutatakse peamiselt luureks või otsinguiks. Eelneb tavaliselt suurtematele tulnukate laevadele missioonide alguses.\"\n  STR_MEDIUM_SCOUT_UFOPEDIA: \"Keskmise suurusega luuresõiduk, mis kujutab väikest ohtu maajõududele, eelneb tavaliselt suurtematele tulnukate laevadele.\"\n  STR_LARGE_SCOUT_UFOPEDIA: \"Suur tulnukate luuresõiduk on multifunktsionaalne lennuk, mida saab kõikide tulnukate missioonideks.\"\n  STR_BATTLESHIP_UFOPEDIA: \"Lahingulaev on suurim ja tugevaim tulnukate lennumasin. Tavaliselt on see primaarne tulnukate missioonisõiduk tugeva relvastuse ja rohke meeskonnaga.\"\n  STR_DISMANTLE: \"Lammuta\"\n  STR_FACILITY_IN_USE: \"RAJATIS ON KASUTUSES\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"EI SAA RAJATIST LAMMUTADA!{SMALLLINE}Kõik baasi rajatised peavad olema ühendatud sissepääsuga.\"\n  STR_TRANSFER_ITEMS_TO: \"Suuna asjad {0}sse\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"Tulnukas suri kuna puudus koht tema hoidmiseks\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"VABU TUBE EI OLE!{SMALLLINE}Baasis ei ole piisavalt palju vabu eluruume sõidukile määratud meeskonna jaoks.\"\n  STR_ITEMS_ARRIVING: \"Saabuvad asjad\"\n  STR_DESTINATION_UC: \"SIHTPUNKT\"\n  STR_PISTOL: \"Püstol\"\n  STR_PISTOL_CLIP: \"Püstoli salv\"\n  STR_RIFLE: \"Püss\"\n  STR_RIFLE_CLIP: \"Vintpüssi salv\"\n  STR_HEAVY_CANNON: \"Raske kahur\"\n  STR_HC_AP_AMMO: \"Kahuri soomusläbistav mürsk\"\n  STR_HC_HE_AMMO: \"Kahuri lõhkemürsk\"\n  STR_HC_I_AMMO: \"Kahuri napalmmürsk\"\n  STR_AUTO_CANNON: \"Automaatkahur\"\n  STR_AC_AP_AMMO: \"AK soomustläbistav salv\"\n  STR_AC_HE_AMMO: \"AK lõhkesalv\"\n  STR_AC_I_AMMO: \"AK napalmsalv\"\n  STR_ROCKET_LAUNCHER: \"Raketiheitja\"\n  STR_SMALL_ROCKET: \"Väike Rakett\"\n  STR_LARGE_ROCKET: \"Suur rakett\"\n  STR_INCENDIARY_ROCKET: \"Napalmrakett\"\n  STR_GRENADE: \"Granaat\"\n  STR_SMOKE_GRENADE: \"Suitsupomm\"\n  STR_PROXIMITY_GRENADE: \"Lähedusgranaat\"\n  STR_HIGH_EXPLOSIVE: \"Lõhkekeha\"\n  STR_STUN_ROD: \"Uimapulk\"\n  STR_HEAVY_PLASMA: \"Raske plasma\"\n  STR_HEAVY_PLASMA_CLIP: \"Raske plasma salv\"\n  STR_PLASMA_RIFLE: \"Plasma Püss\"\n  STR_PLASMA_RIFLE_CLIP: \"Plasma püssi salv\"\n  STR_PLASMA_PISTOL: \"Plasma püstol\"\n  STR_PLASMA_PISTOL_CLIP: \"Plasma püstoli salv\"\n  STR_BLASTER_LAUNCHER: \"Lõhkeheitja\"\n  STR_BLASTER_BOMB: \"Lõhkepomm\"\n  STR_SMALL_LAUNCHER: \"Väike heitur\"\n  STR_STUN_BOMB: \"Uimapomm\"\n  STR_ALIEN_GRENADE: \"Tulnuka Granaat\"\n  STR_ELERIUM_115: \"Eleerium-115\"\n  STR_MIND_PROBE: \"Meeleurkel\"\n  STR_SECTOID_CORPSE: \"Sektoidi Laip\"\n  STR_SNAKEMAN_CORPSE: \"Ussimehe Laip\"\n  STR_ETHEREAL_CORPSE: \"Taevase Laip\"\n  STR_MUTON_CORPSE: \"Mutooni Laip\"\n  STR_FLOATER_CORPSE: \"Lendaja Laip\"\n  STR_CELATID_CORPSE: \"Celatiidi laip\"\n  STR_SILACOID_CORPSE: \"Silacoidi laip\"\n  STR_CHRYSSALID_CORPSE: \"Krüssaliidi Laip\"\n  STR_REAPER_CORPSE: \"Pussitaja Laip\"\n  STR_SECTOPOD_CORPSE: \"Sectopodi laip\"\n  STR_CYBERDISC_CORPSE: \"Küberketta Laip\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"Pole piisavalt laskemoona, et varustada RRP{SMALLLINE}Iga RRP vajab {0} {1}.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Pole piisavalt varustust, et rühma täielikult uuesti relvastuda.\"\n  STR_MARS_CYDONIA_LANDING: \"Marss: Cydonia Maabumine\"\n  STR_MARS_CYDONIA_LANDING_BRIEFING: \"Avenger on maandunud Marsil asuvas Cydonia regioonis. Luureandmete järgi on ühes püramiidis rohelist värvi sissepääs maaalusesse kompleksi. Peale seda kui kõik sõdurid on kogunenud lifti piirkonda, kliki 'Katkesta missioon' ikooni, et edasi liikuda järgmisele tasemele.\"\n  STR_MARS_THE_FINAL_ASSAULT: \"Marss: Viimane Rünnak\"\n  STR_MARS_THE_FINAL_ASSAULT_BRIEFING: \"Püramiidi lift viib sinu lahinguväsinud sõdurid sügavale planeedi sisemusse. Nad jõuavad suurde kambrite ja tunnelite kompleksi. Kuskil selles labürindis on peidus Tulnukaju. Maa tulnukate orjusest päästmiseks on vaja see hävitada!{NEWLINE}{NEWLINE}Kivi koti!\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Peate avastama kõigepealt {NEWLINE}{0}{NEWLINE}et toota {NEWLINE}{1}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"Tulnukad lõhkusid ära kaitsetu baasi {0}\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"X-Comi agendid on leidnud tulnukate baasi: {0}\"\n  STR_STANDOFF: \"HOIA KAUGUST\"\n  STR_CAUTIOUS_ATTACK: \"ETTEVAATLIK RÜNNAK\"\n  STR_STANDARD_ATTACK: \"STANDARD RÜNNAK\"\n  STR_AGGRESSIVE_ATTACK: \"AGRESIIVNE RÜNNAK\"\n  STR_DISENGAGING: \"EEMALDU\"\n  STR_UFO_HIT: \"UFO SAI PIHTA!\"\n  STR_UFO_CRASH_LANDS: \"UFO KUKKUS ALLA!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Minimiseeri ainult mittelähenemise korral.\"\n  STR_UFO_RETURN_FIRE: \"UFO TULISTAB VASTU!\"\n  STR_INTERCEPTOR_DAMAGED: \">>> SÕIDUK VIGASTATUD <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> HÄVITAJA PURUSTATUD<<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"UFO SÕIDAB EEST ÄRA!\"\n  STR_ALIENS_TERRORISE: \"TULNUKAD TERRORISEERIVAD\"\n  STR_LONG_RANGE_DETECTION: \"Pikamaa tuvastus\"\n  STR_STORES_UC: \"LADU\"\n  STR_DIFFICULTY_LEVEL: \"Raskus Aste\"\n  STR_INTERCEPT: \"RÜNDA\"\n  STR_BASES: \"BAASID\"\n  STR_GRAPHS: \"DIAGRAMMID\"\n  STR_UFOPAEDIA_UC: \"UFOPEEDIA\"\n  STR_OPTIONS_UC: \"VALIKUD\"\n  STR_FUNDING_UC: \"RAHASTUS\"\n  STR_5_SECONDS: \"5 s\"\n  STR_1_MINUTE: \"1 Min\"\n  STR_5_MINUTES: \"5 Min\"\n  STR_30_MINUTES: \"30 Min\"\n  STR_1_HOUR: \"1 Tund\"\n  STR_1_DAY: \"1 Päev\"\n  STR_ENTER_NAME: \"Sisesta Nimi\"\n  STR_VICTORY_DATE: \"Võidu Kuupäev\"\n  STR_ELECTRO_FLARE: \"Elektriloidik\"\n  STR_ELECTRO_FLARE_UFOPEDIA: \"See kompaktne vidin tekitab heleda valguse kui visata. Valgustab lähedalolevaid vaenlase üksusi öömissioonidel.\"\n  STR_MONTHLY_COSTS: \"Kuu maksumus\"\n  STR_CRAFT_RENTAL: \"Sõidukite rent\"\n  STR_SALARIES: \"Palgad\"\n  STR_BASE_MAINTENANCE: \"Baasi kulud\"\n  STR_COST_PER_UNIT: \"Tüki hind\"\n  STR_QUANTITY: \"Kogus\"\n  STR_TOTAL: \"Kokku\"\n  STR_IN_PSIONIC_TRAINING: \"Psitreeningus\"\n  STR_BLASTER_BOMB_UFOPEDIA: \"See riistapuu on väga plahvatusohtlik rakett inteligentse juhtimisseadega. See tulistatakse välja lõhkeheitjast.\"\n  STR_FRONT_ARMOR: \"Eesmine Turvis\"\n  STR_LEFT_ARMOR: \"Vasak Turvis\"\n  STR_RIGHT_ARMOR: \"Parem Turvis\"\n  STR_REAR_ARMOR: \"Tagumine Turvis\"\n  STR_UNDER_ARMOR: \"Alumine Turvis\"\n  STR_ROUNDS: \"Kuule\"\n  STR_UNIT: \"ÜKSUS> {0}\"\n  STR_ENERGY: \"ENERGIA\"\n  STR_MORALE: \"MORAAL\"\n  STR_ARMOR_: \"TURVIS> {0}\"\n  STR_FRONT_ARMOR_UC: \"EESMINE TURVIS\"\n  STR_LEFT_ARMOR_UC: \"VASAK TURVIS\"\n  STR_RIGHT_ARMOR_UC: \"PAREM TURVIS\"\n  STR_REAR_ARMOR_UC: \"TAGUMINE TURVIS\"\n  STR_SKILLS: \"OSKUSED> {0}\"\n  STR_LEVEL: \"TASE> {0}\"\n  STR_HEAD: \"PEA\"\n  STR_TORSO: \"KEHA\"\n  STR_RIGHT_ARM: \"PAREM KÄSI\"\n  STR_LEFT_ARM: \"VASAK KÄSI\"\n  STR_RIGHT_LEG: \"PAREM JALG\"\n  STR_LEFT_LEG: \"VASAK JALG\"\n  STR_PAIN_KILLER: \"VALUVAIGISTI\"\n  STR_STIMULANT: \"STIMULANT\"\n  STR_HEAL: \"RAVIDA\"\n  STR_TIME_UNITS_SHORT: \"TU>{ALT}{0}\"\n  STR_WEIGHT: \"Kaal>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"Reakts>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"P.osav>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"P.tug>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Tulnukate imevidin\"\n  STR_AMMO_ROUNDS_LEFT: \"LASKEMOON:{NEWLINE}KUULE{NEWLINE}ALLES={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Valuv>{ALT}{0}{ALT}{NEWLINE}Stim>{ALT}{1}{ALT}{NEWLINE}Ravi>{ALT}{2}\"\n  STR_THROW: \"Viska\"\n  STR_AUTO_SHOT: \"Valang\"\n  STR_SNAP_SHOT: \"Lask puusalt\"\n  STR_AIMED_SHOT: \"Sihitud Lask\"\n  STR_STUN: \"Uimastama\"\n  STR_PRIME_GRENADE: \"Aktiveeri Granaat\"\n  STR_USE_SCANNER: \"Kasuta skannerit\"\n  STR_USE_MEDI_KIT: \"Ravima\"\n  STR_LAUNCH_MISSILE: \"Tulista rakett\"\n  STR_ACCURACY_SHORT: \"Acc>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Pole piisavalt ajaühikuid\"\n  STR_NOT_ENOUGH_ENERGY: \"Pole piisavalt energiat\"\n  STR_NO_ROUNDS_LEFT: \"Kuulid otsas!\"\n  STR_NO_AMMUNITION_LOADED: \"Laskemoon laadimata!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Laskemoon ei sobi sellele relvale!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"Relv juba laetud!\"\n  STR_NO_LINE_OF_FIRE: \"Puudub tulejoon!\"\n  STR_GRENADE_IS_ACTIVATED: \"Granaat aktiveeritud!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Granaat deaktiveeritud\"\n  STR_THERE_IS_NO_ONE_THERE: \"Seal pole kedagi!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Ilma uuringuta tulnukate asju kasutada ei saa!\"\n  STR_OUT_OF_RANGE: \"Ei ulata!\"\n  STR_UNABLE_TO_THROW_HERE: \"Sinna pole võimalik visata!\"\n  STR_SET_TIMER: \"Määra aeg\"\n  STR_HIDDEN_MOVEMENT: \"PEIDETUD LIIKUMINE\"\n  STR_TURN: \"KÄIK> {0}\"\n  STR_SIDE: \"POOL> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Väjuta nuppu, et jätkata\"\n  STR_MIND_CONTROL: \"Mõistuse kontroll\"\n  STR_PANIC_UNIT: \"Paanikas Üksus\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Rünnak moraalile õnnestus\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Mõistuse kontroll õnnestus\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}läks Segaseks\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}läks Segaseks\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}on paanikas\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}on Paanikas\"\n  STR_XCOM: \"X-COM\"\n  STR_ALIENS: \"Tulnukad\"\n  STR_RIGHT_HAND: \"Paremkäsi\"\n  STR_LEFT_HAND: \"VASAK KÄSI\"\n  STR_RIGHT_SHOULDER: \"PAREM ÕLG\"\n  STR_LEFT_SHOULDER: \"VASAK ÕLG\"\n  STR_BACK_PACK: \"SELJAKOTT\"\n  STR_BELT: \"VÖÖ\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}on tulnukate kontrolli all\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}on tulnukate kontrolli all\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}kaotas teadvuse\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}kaotas teadvuse\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}suri haavadesse\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}suri haavadesse\"\n  STR_USE_MIND_PROBE: \"Kasuta meeleurkelit.\"\n  STR_FATAL_WOUNDS: \"SURMAVAD HAAVAD\"\n  STR_UNDER_ARMOR_UC: \"ALUMINE TURVIS\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Ajaühikud reserveeritud puusalt lasuks\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Ajaühikud reserveeritud valanguks\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Ajaühikud reserveeritud täpsuslasuks\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Ajaühikud reserveeritud põlvitamiseks\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"Ajaühikud reserveeritud põlvili tulistamiseks\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} sõdurit X-COMi masinas\"\n    other: \"{N} sõdurit X-COMi sõidukis\"\n  STR_UNITS_OUTSIDE:\n    one: \"{N} sõdurit väljapääsul\"\n    other: \"{N} sõdurit väljas\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} sõdurit sissepääsul\"\n    other: \"{N} sõdurit sissepääsul\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} sõdurit sihtmärgil\"\n    other: \"{N} sõdurit sihtmärgil\"\n  STR_ABORT_MISSION_QUESTION: \"Katkesta missioon?\"\n  STR_CORPSE: \"Laip\"\n  STR_UNLOAD_CRAFT: \"Lae tühjaks\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}tapetud\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}tapetud\"\n  STR_HIT_MELEE: \"Pihtas\"\n  STR_GROUND: \"MAAPIND\"\n  STR_LIVING_QUARTERS_PLURAL: \"Majutus\"\n  STR_LIST_ITEM: \"ASI\"\n  STR_PERSONAL_ARMOR_UFOPEDIA: \"Tänu uuele tulnukate sulamile annab see uus turvis meie sõduritele võimaluse võidelda edukalt tulnukate ohuga.\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"Kõik tulnukad hukkusid,{NEWLINE}automaatne utiliseerimine alustatud\"\n  STR_RESET: \"Taasta\"\n  STR_MEMORIAL: \"Memoriaal\"\n  STR_DATE_UC: \"KUUPÄEV\"\n  STR_SOLDIERS_RECRUITED_UC: \"SÕDUREID VÄRVATUD>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"SÕDUREID KAOTATUD>{ALT}{0}\"\n  MAP_CULTA: \"Farm\"\n  MAP_FOREST: \"Mets\"\n  MAP_JUNGLE: \"Džungel\"\n  MAP_MOUNT: \"Mägi\"\n  MAP_DESERT: \"Kõrb\"\n  MAP_POLAR: \"Polaar\"\n  MAP_URBAN: \"Linn\"\n  MAP_UBASE: \"Tulnukate Baas\"\n  MAP_XBASE: \"X-Comi Baas\"\n  MAP_MARS: \"Marss\"\n  STR_MIXED: \"Segamaastik\"\n  STR_REMOVE_SELECTED: \"Eemalda Valitud\"\n  STR_MANAGE_CONTAINMENT: \"Manageeri tulnukhoidlat\"\n  STR_STORAGE_EXCEEDED: \"LAORUUMID ON TÄIS!{SMALLLINE}{0} pole rohkem ruumi asjade jaoks, olete sunnitud üleliigse maha müüma.\"\n  STR_GO_TO_BASE: \"Mine baasi\"\n  STR_MELEE_ACCURACY: \"LÄHIVÕITLUSE TÄPSUS\"\n  STR_SELL_PRODUCTION: \"MÜÜ\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Mõlemad käed peavad olema tühjad\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Pole piisavalt varustust malli kopeerimiseks!\"\n  STR_UNLOAD_WEAPON: \"Eemalda laskemoonasalv.\"\n  STR_ALL_ITEMS: \"Kogu inventar\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"ROHKEM VARUSTUST PARDALE POLE LUBATUD!{SMALLLINE}Sellele alusele on lubatud võtta maksimum {N} asja kaasa.\"\n    other: \"ROHKEM VARUSTUST PARDALE POLE LUBATUD!{SMALLLINE}Sellele alusele on lubatud võtta maksimum {N} asja kaasa.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}JUHTIMISKESKUS HÄVITATUD!{NEWLINE}Siirdu algusesse ja katkesta.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"X-comi hooneid ei saa ehitada vee alla\"\n  STR_LEVEL_SHORT: \"{0}\"\n  STR_PERSONNEL: \"Personal\"\n  STR_CRAFT_ARMAMENT: \"Lennukid & Kahurid\"\n  STR_COMPONENTS: \"Komponendid\"\n  STR_SOLDIERS_RECRUITED: \"Sõdurite Nimekiri\"\n  STR_SOLDIERS_LOST: \"Sõdureid kaotatud\"\n  STR_TOTAL_UFOS: \"UFOsid avastatud\"\n  STR_TOTAL_ALIEN_BASES: \"Leitud tulnukate baase\"\n  FEMALE_CIVILIAN: \"Tsiviilisik, naine\"\n  MALE_CIVILIAN: \"Tsiviilisik, mees\"\n  CYBERDISC_WEAPON: \"Küberketta relv\"\n  REAPER_WEAPON: \"Pussitaja relv\"\n  CHRYSSALID_WEAPON: \"Krüssaliidi relv\"\n  CELATID_WEAPON: \"Celatiidi relv\"\n  SILACOID_WEAPON: \"Silacoidi relv\"\n  SECTOPOD_WEAPON: \"Sectopodi relv\"\n  ZOMBIE_WEAPON: \"Zombie relv\"\n  ALIEN_PSI_WEAPON: \"Tulnukate Psirelv\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/fi.yml",
    "content": "fi:\n  STR_AVENGER_UFOPEDIA: \"AVENGER ON KULJETUS- JA HÄVITTÄJÄAVARUUSALUS, JOKA ON MUUKALAISILTA KOPIOIDUN TEKNOLOGIAN HUIPPUSOVELLUS.\"\n  STR_INTERCEPTOR_UFOPEDIA: \"HÄVITTÄJÄ, JOSSA ON KAKSI PULSSIRÄJÄYTYSMOOTTORIA JA ERIKOISSUOJATUT ELEKTRONISET JÄRJESTELMÄT; PARASTA TEKNOLOGIAA, MITÄ MAA VOI TARJOTA.\"\n  STR_LIGHTNING_UFOPEDIA: \"LIGHTNING ON KULJETUS- JA HÄVITTÄJÄALUS, JOSSA ON HIOMATON MUTTA TEHOKAS KOPIO MUUKALAISTEN TYÖNTÖVOIMAJÄRJESTELMÄSTÄ.\"\n  STR_SKYRANGER_UFOPEDIA: \"SKYRANGER ON KULJETUSALUS, JOKA ON LUOKKANSA NOPEIN, SEKÄ PYSTYY LASKEUTUMAAN JA NOUSEMAAN PYSTYSUORASSA (V.T.O.L.).\"\n  STR_FIRESTORM_UFOPEDIA: \"FIRESTORM ON YHDEN MIEHEN HÄVITTÄJÄALUS, JOKA KOPIOI KLASSISTA LENTÄVÄN LAUTASEN MALLIA, JOSSA TYÖNTÖVOIMAN LÄHDE ON KESKELLÄ ALUSTA.\"\n  STR_STINGRAY_UFOPEDIA: \"STINGRAY ON KEHITTYNYT ILMATAISTELUOHJUS, JONKA ELEKTRONIIKKA ON ERITYISSUOJATTU.\"\n  STR_AVALANCHE_UFOPEDIA: \"AVALANCHE ON ILMATAISTELUOHJUS, JONKA PAINOLASTI ON ERITTÄIN RASKAS, SISÄLTÄEN YDINKÄRJEN.\"\n  STR_CANNON_UFOPEDIA: \"TÄMÄ ON VOIMAKAS TYKKI, JOKA AMPUU TAVANOMAISIA PANSSARIAMMUKSIA, JOTKA PYSTYVÄT LÄVISTÄMÄÄN JOPA 16 TUUMAN TERÄSLEVYN.\"\n  STR_FUSION_BALL_UFOPEDIA: \"TÄMÄ LAUKAISIN LAUKAISEE PALLONMUOTOISEN OHJUKSEN, JOKA SAA VOIMANSA ANTIMATERIAREAKTIOSTA. PALLO AIHEUTTAA OSUESSAAN GRAVITAATIOAALTOIMPLOOSION JOKA TUHOAA KOHTEEN.\"\n  STR_LASER_CANNON_UFOPEDIA: \"TÄMÄ MUUTOIN TAVANOMAINEN LASERASE SAA VOIMANSA ANTIMATERIAREAKTORISTA.\"\n  STR_PLASMA_BEAM_UFOPEDIA: \"PLASMATYKKI TUOTTAA GRAVITAATIOSÄTEEN, JOKA KOOSTUU HIENOSTUNEESTI KOOSTETUSTA IMPLODOIVASTA GRAVITAATIOKENTÄSTÄ.\"\n  STR_SECTOID_UFOPEDIA: \"Harmaiden hierarkia käsittää arvoasteikon sotilaista johtajiin, joilla on voimakkaita psionisia kykyjä. Näitä kykyjä voidaan käyttää vastustajien taistelutahdon nujertamiseen, tai jopa heidän mielensä hallitsemiseen. Harmailla on tapana kaapata ihmisiä ja silpoa karjaa geneettisiä kokeita varten. Kokeiden päämääränä on ristijalostus sekä hybridien tuottaminen ihmisyhteisöön soluttautumista varten. Lisäksi harmaat saavat näin ravintoa. Harmaiden päämääränä näyttäisi olevan ylivertaisen olennon kehittäminen mehiläisyhteiskuntaa muistuttavaa yhteisöään varten.\"\n  STR_SECTOID_AUTOPSY: \"Harmaan ruumiinavaus\"\n  STR_SECTOID_AUTOPSY_UFOPEDIA: \"Ruumiinavauksessa paljastuu olennon vajaasti kehittynyt ruuansulatuselimistö ja yksinkertainen tukirangan rakenne. Aivot ja silmät ovat hyvin kehittyneet. Kokonaiskuvan perusteella herää epäilys geneettisestä manipulaatiosta. Pienellä suulla ja nenällä ei näytä olevan mitään käyttöä. Sormien väliset ihopoimut, sekä litteät jalat viittaavat olennon vedenalaiseen alkuperään. Olennolla ei ole lainkaan lisääntymiselimiä. Nämä olennot on todennäköisesti rakennettu täysin geenitekniikan avulla.\"\n  STR_SNAKEMAN_UFOPEDIA: \"Tämä laji on kehittynyt äärimmäisen hankalassa elinympäristössä. Käärmemiehet ovat äärimmäisen kestäviä ja sietävät äärimmäsiä lämpötilavaihteluita. Niiden liikkuminen tapahtuu pääasiassa käärmemäisen vartalon avulla, joka samalla suojaa elintärkeitä elimiä. Niiden motiivina näyttäisi olevan pelkästään saalistushalu, ja näyttää siltä että jokin suurempi äly komentaa tämän rodun sotilaallistyyppisen yhteisön tunkeutumista Maahan.\"\n  STR_SNAKEMAN_AUTOPSY: \"Käärmemiehen ruumiinavaus\"\n  STR_SNAKEMAN_AUTOPSY_UFOPEDIA: \"Tämän olennon iho on erittäin vahva ja kestää hyvin lämpöä. Verenkiertojärjestelmä on kiinteä osa lihaksistoa, joka käyttää hydrauliikkaa hyväksi liikkeen aikaansaamiseksi. Ainoa todellinen lihas on järjestelmän \\\"sydän\\\". Lisääntymisjärjestelmä vaikuttaa erittäin kehittyneeltä. Lisääntyminen on aseksuaalista, ja jokaisessa käärmemiehessä voi olla jopa viisikymmentä munaa. Jos tämä laji saisi lisääntyä rauhassa, olisi se erittäin vaarallista Maan eliöstölle.\"\n  STR_ETHEREAL_UFOPEDIA: \"Tällä olennolla on mahtavia mentaalisia voimia, joiden avulla se voi kommunikoida telepaattisesti. Sillä on myös telekineettisiä kykyjä. Olennon mentaaliset voimat ylläpitävät sen heikkoa ruumista. Emme pysty toistaiseksi selittämään, kuinka olennon telekineettiset kyvyt toimivat, sillä ne näyttävät rikkovan tuntemiamme fysiikan lakeja. Nämä olennot ovat äärimmäisen vaarallisia taistelutilanteessa, jossa ne luottavat mentaalisiin kykyihinsä. Eteerejä tavataan vain harvoin Maassa, sillä ne näyttävät luottavan muihin lajeihin päämääriensä tavoittelussa.\"\n  STR_ETHEREAL_AUTOPSY: \"Eteerin ruumiinavaus\"\n  STR_ETHEREAL_AUTOPSY_UFOPEDIA: \"Tämä olento on fyysisesti rajoittunut ja kyvytön ylläpitämään minkäänlaisia elintoimintoja. Lihaksisto on vakavasti surkastunut ja sisäelimet alikehittyneitä. Aistinelimet, silmät mukaanluettuna, eivät näytä toimivan lainkaan. Sen sijaan aivot ovat erittäin hyvin kehittyneet ja vievät suuren osan olennon verenkierrosta. Arvoitukseksi jää, kuinka tämä olento pystyy ylläpitämään elintoimintojaan ilman ulkoista, keinotekoista tukea.\"\n  STR_MUTON_UFOPEDIA: \"Tämä humanoidi on fyysisesti vahva ja älykäs. Mutoneilla on erityinen ruokahalu minkälaisen tahansa raa'an lihan syöntiin, jota ne tarvitsevat selvitäkseen samaan tapaan kuin maanpäälliset lihansyöjät. Ne näyttävät olevan riippuvaisia telepaattisista komennoista muukalaislajilta, jota kutsutaan nimellä \\\"eteerit\\\". Jos tämä telepaattinen yhteys katkeaa, olennon psyykkinen järjestelmä näyttää hajoavan, mikä johtaa lopulta olennon kuolemaan. Olennon taistelukykyä on kohennettu kyberneettisillä implanteilla. Mutonit ovat ilmiselvästi jonkin suuremman älykkään tahon sotilaita.\"\n  STR_MUTON_AUTOPSY: \"Mutonin ruumiinavaus\"\n  STR_MUTON_AUTOPSY_UFOPEDIA: \"Tämän olennon \\\"iho\\\" vaikuttaisi koostuvan orgaanisesti tuotetulta suoja-panssarilta, joka on kiinteästi liitetty vartaloon. Olennosta löytyy lukuisia kyberneettisiä implantteja, joiden avulla sen verenkiertojärjestelmää ja aisteja on paranneltu. Lisääntymiselimet on kirurgisesti poistettu. Ilmeisesti näiden epäonnisten olentojen tehtävä on rajattu vain sotaan ja valloitukseen. Panssariammukset eivät ole erityisen tehokkaita niiden kovan ihon lävistämisessä.\"\n  STR_CELATID_UFOPEDIA: \"Tällä eliöllä on salaperäinen luontainen kyky leijua ilmassa. Se näyttäisi havaitsevan ihmisten aivoaaltoja ja hakeutuvan ihmisiä kohti, vaikka kohde olisikin hyvin piiloutunut. Kun se havaitsee sopivan ihmiskohteen, se syöksee pieniä pallomaisia möykkyjä, jotka sisältävät erittäin syövyttävää myrkkyä. Tämä olio pystyy lisääntymään jakautumalla erittäin nopealla tahdilla. Sitä tavataan yleensä mutonilajin läheisyydessä.\"\n  STR_CELATID_AUTOPSY: \"Kelatoidin ruumiinavaus\"\n  STR_CELATID_AUTOPSY_UFOPEDIA: \"Olennon sisältä löytyy pieni bio-mekaaninen antipainovoimatyöntölaite, joka näyttäisi syntyneen normaalin evoluution avulla. Myrkkyrakkula on suurin sisäelin, eikä olennolla vaikuta olevan lainkaan erillistä aivokudosta. Myöskään ruuansulatus- tai lisääntymiselimiä ei löydy. Pieni elin sisältää kuitenkin sikiöitä, joista voi kasvaa nopeasti uusia kelatoideja.\"\n  STR_SILACOID_UFOPEDIA: \"Tämä piin kemiaan pohjautuva eliö tuottaa uskomattomia määriä lämpöä. Se pystyy murskaamaan kiviä, joita se sitten käyttää polttoaineena kuumassa ytimessään. Sen älylliset toiminnot ovat erittäin alkukantaisia, ja sitä voidaan ohjailla erilaisilla implanteilla sekä telepaattisesti. Yleensä silikoideja tavataan mutoneiden läheisyydessä.\"\n  STR_SILACOID_AUTOPSY: \"Silikoidin ruumiinavaus\"\n  STR_SILACOID_AUTOPSY_UFOPEDIA: \"Tämän olennon sisin on äärimmäisen kuuma, mikä on välttämätöntä olennon louhiessa energiaa ympäristöstä löytämästään materiaalista. Sen ainutlaatuinen lihaksisto on uskomattoman vahva ja nopea. Sen kivimäinen ulkopinta ei vahingoitu lainkaan tulessa, joten polttonesteeeseen perustuvat aseet ovat hyödyttömiä sitä vastaan.\"\n  STR_CHRYSSALID_UFOPEDIA: \"Tämän olion rapumaiset sakset toimivat tehokkaina aseina lähitaistelussa. Olento on erittäin nopea ja ketterä nopean aineenvaihduntansa ansiosta. Sen sijaan, että se tappaisi uhrinsa, se ruiskuttaa uhriinsa munan sekä myrkkyä, joka muuttaa uhrin käveleväksi zombiksi. Lyhyen ajan kuluttua munimisesta uusi samanlainen olento räjähtää ulos uhrin ruumiista. Yleensä munamiehet liikkuvat käärmemiesten läheisyydessä.\"\n  STR_CHRYSSALID_AUTOPSY: \"Munamiehen ruumiinavaus\"\n  STR_CHRYSSALID_AUTOPSY_UFOPEDIA: \"Tämän olennon ulkoinen tukiranka on erittäin vahva, joskin yllättävän herkkä räjähdystyyppisille aseille. Aivot ovat hyvin kehittyneet, ja sen solujen kasvuvauhti on erittäin nopea. Tämä olento kantaa sisällään kahtakymmentä munaa, jotka se asettaa muiden eläinten sisälle. Tämä olento on erittäin tehokas terroriaseena.\"\n  STR_FLOATER_UFOPEDIA: \"Leijujat ovat luonnostaan sotilaallisia ja toimivat usein terroriagentteina. Niillä on luonnostaan petomainen saalistusvietti, jonka pohjalta niistä on geneettisen ja kyberneettisen muokkauksen avulla tehty erinomaisia sotilaita. Vartalon alaosa ja suurin osa sisäelimistä on kirurgisesti poistettu, ja tilalle on asennettu elämää ylläpitävä järjestelmä. Tähän järjestelmään on liitetty kiinteästi antipainovoimayksikkö, jonka ansiosta olento pystyy leijumaan ilmassa, joskin kömpelön oloisesti.\"\n  STR_FLOATER_AUTOPSY: \"Leijujan ruumiinavaus\"\n  STR_FLOATER_AUTOPSY_UFOPEDIA: \"Tätä olentoa on muunneltu dramaattisesti kirurgisilla keinoilla. Sen vartalon keskellä oleva laite näyttäisi olevan elintoimintoja ylläpitävä laite, joka toimittaa sydämen, keuhkojen ja ruuansulatuselimistön tehtävää. Sen ansiosta eliö pystyy selviämään äärimmäisen hankalissa olosuhteissa. Sen aivot ovat pienemmät kuin meidän, mutta aistinelimet ovat erittäin hyvin kehittyneet.\"\n  STR_REAPER_UFOPEDIA: \"Tällä kaksijalkaisella lihansyöjällä on voimakkaat leuat ja valtava ruokahalu. Sillä on useita implantteja aivoissa, joiden avulla sen toimintaa kontrolloidaan. Tämän pedon alkukantaisilla saalistajan vaistoilla on tuskin muuta käyttöä kuin terrorisointi ja tuhoaminen. Raatelijoita tavataan useimmiten leijujien läheisyydessä.\"\n  STR_REAPER_AUTOPSY: \"Raatelijan ruumiinavaus\"\n  STR_REAPER_AUTOPSY_UFOPEDIA: \"Raatelijalla on kaksi sydäntä ja kaksi aivoa, minkä vuoksi se pystyy toimimaan hyvin vakavasti haavoittuneenakin. Sen karvainen iho on kuitenkin erittäin tulenarkaa, joten polttonesteammukset ovat erityisen tehokkaita sitä vastaan.\"\n  STR_SECTOPOD_UFOPEDIA: \"Sektopodit ovat robotteja, joilla on voimakas laserase. Eteerit, näiden mekaanisten hirviöiden omistajat, ohjaavat niitä telepaattisten kykyjensä avulla. Sektopodit ovat kaikista voimakkain terroriase, mitä muukalaisilla on käytettävissään.\"\n  STR_SECTOPOD_AUTOPSY: \"Sektopodin purku\"\n  STR_SECTOPOD_AUTOPSY_UFOPEDIA: \"Tämä robotti on jykevästi rakennettu ja sen panssari, joka on vahvistettu energiakentällä, pystyy torjumaan useimpia vahingoittamiskeinoja, erityisesti plasma-aseiden ammuksia. Sen havainnointijärjestelmä vaikuttaisi erityisen herkältä laseraseiden tulitukselle.\"\n  STR_CYBERDISC_UFOPEDIA: \"Tämä pienoiskokoinen lentävä lautanen on automatisoitu terroriase, joka käyttää vomakasta plasmaa aseenaan. Antipainovoimapropulsion ansiosta sillä on suuri etu hankalassa maastossa. Sen pääasiallinen käyttötehtävä on terrori ja tuhoaminen. Kyberlautanen on useimmiten Harmaiden käyttämä terroriase.\"\n  STR_CYBERDISC_AUTOPSY: \"Kyberlautasen purku\"\n  STR_CYBERDISC_AUTOPSY_UFOPEDIA: \"Kyberlautanen on hyvin suojattu erityisesti räjähtäviä aseita kohtaan. Antipainovoimayksikkö on kärsinyt liikaa vaurioita jotta voisimme tutkia paremmin sen toimintaa.\"\n  STR_UFO_POWER_SOURCE_UFOPEDIA: \"Muukalaisten alusten voimanlähde on eräänlainen antimateriareaktori, joka käyttää eleriumia (järjestysluku 115) polttoaineenaan. Lopputuloksena syntyy gravitaatioaaltoja ja muunlaisia energianmuotoja. Materian muuntaminen energiaksi on uskomattoman tehokasta, ja reaktorilla on 99 %:n hyötysuhde. Niinpä hyvin pienillä määrillä eleriumia voidaan tuottaa uskomattoman suuria määriä energiaa. Voimme tehdä näitä reaktoreita lisää helposti käyttäen muukalaisten metalliseoksia.\"\n  STR_UFO_NAVIGATION_UFOPEDIA: \"Muukalaisten alukset käyttävät maassa ja avaruudessa navigoimiseen navigointijärjestelmää, joka koostuu klusterina toimivista optiseen tekniikkaan pohjautuvista prosessoreista. Käyttöliittymä on kohtalaisen yksinkertainen - navigoija suuntaa aluksen voimanlähteen luomia gravitaatioaaltoja siten, että alus liikkuu haluttuun suuntaan. Ihmiset pystyvät käyttämään tätä järjestelmää helposti, ja voimme myös rakentaa niitä lisää käyttäen muukalaisten metalliseoksia sekä muita komponentteja.\"\n  STR_UFO_CONSTRUCTION_UFOPEDIA: \"Muukalaisten aluksissa on yleensä kolme pääkomponenttia - voimanlähde, navigointijärjestelmä ja runko, joka on rakennettu muukalaisten metalliseoksista. Runko on aina suunniteltu siten, että sen avulla voidaan ohjata ja suunnata gravitaatioaaltoja. Lisäksi pieni määrä eleriumia tarvitaan polttoaineeksi voimanlähteeseen. Kun kaikkien näiden osien toiminnan periaatteet ja rakennustapa on tunnettu, voimme rakentaa samaan tapaan toimivia aluksia.\"\n  STR_ALIEN_FOOD_UFOPEDIA: \"Nämä säiliöt sisältävät erilaisia entsyymejä, jotka sulattavat karjan, muiden eläinten ja jopa ihmisten ruumiinosia. Näin syntyvä neste voidaan käyttää suoraan ravinnoksi - todennäköisesti suoraan injisoimalla verenkiertoon. Tämä löydös viittaa jonkinasteiseen muukalaisten riippuvuuteen Maan eläimistöstä ruuantuotantoa varten - eli tietynlaiseen symbioosiin maan biosfäärin ja muukalaisyhteiskunnan välillä.\"\n  STR_ALIEN_REPRODUCTION_UFOPEDIA: \"Nämä säiliöt sisältävät muukalaisten sikiöitä. Säiliöiden rakennustapa viittaa siihen, että ne muukalaislajit, jotka käyttävät tätä prosessia, lisääntyvät täysin keinotekoisesti laboratoriossa. Runsas ravintoliuos mahdollistaa nopean sikiön kehityksen ja kasvun. Kokonaisuutena löydetty lisääntymisjärjestelmä pystyisi tuottamaan tuhansia muukalaisten klooneja lyhyessä ajassa. Tätä teknologiaa voitaisiin helposti käyttää myös ihmisten kloonaamiseen tai ihmis-muukalaishybridien tuottamiseen.\"\n  STR_ALIEN_ENTERTAINMENT_UFOPEDIA: \"Näiden pallomaisten laitteiden käyttö on todennäköisesti viihteellistä. Laitteen psioninen elektroniikka stimuloi useita eri alueita aivoissa. Lopputulos muistuttaa monien psykotrooppisten huumeiden vaikutusta. Tämä laite on ainoa viite muukalaisten vapaa-ajan käytöstä virkistymiseen tai kulttuuriin.\"\n  STR_ALIEN_SURGERY_UFOPEDIA: \"Tällä laserkirurgisella laitteistolla poistetaan tiettyjä ruumiinosia karjasta ja muista eläimistä. Laajalti tavatut karjan silpomistapaukset liittynevät tähän outoon muukalaisten toimintaan. Poistettuja ruumiinosia käytetään joko ravinnoksi tai geneettisiin tutkimuksiin.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"On tiedossa tuhansia ihmisiä, jotka väittävät tulleensa muukalaisten kaappaamiksi, joskus toistuvasti. Totuus on paljon kamalampi. Ihmisiä on kaapattu, tutkittu ja vakoiltu. Parhailta yksilöiltä on kopioitu geneettistä materiaalia. Naisiin on istutettu ihmis-muukalaishybridisikiöitä, jotka on sitten useiden kuukausien päästä istutuksesta poistettu. Voimme vain arvailla näiden tekojen taustalla olevia muukalaisten vihamielisiä motiiveja.\"\n  STR_ALIEN_ALLOYS_UFOPEDIA: \"Muukalaisten alukset on rakennettu erityisistä metalliseoksista, joilla on ainutlaatuisia ominaisuuksia. Nämä seokset ovat äärimmäisen kevyitä ja kestäviä, ja niitä voidaan muovata sähkömagneettisilla keinoilla. Voimme tehdä näitä seoksia lisää keinotekoisesti ja käyttää niitä monenlaisissa valmistusprojekteissa.\"\n  STR_ELERIUM_115_UFOPEDIA: \"Tällä alkuaineella on erittäin epätavallinen ominaisuus - se tuottaa antimateriaa, kun sitä pommitetaan tietyillä alkeishiukkasilla. Lopputuloksena syntyy gravitaatioaaltoja sekä muun tyyppistä energiaa. Alkuainetta ei löydy luonnostaan aurinkokunnastamme eikä sitä voi tuottaa keinotekoisesti.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"Näyttää siltä, että olemme väistämättä häviämässä maanpäällisen taistelun. Muukalaisten määrät ovat ylivoimaisia. Voimme ainoastaan hidastaa heidän etenemistään. Ainoa toivo ihmiskunnalle on iskeä sinne, mistä muukalaiset ovat peräisin. Tutkimustemme mukaan muukalaisilla on keskeinen toimintojensa tukikohta jossakin aurinkokunnassamme. Muukalaisilta saatujen tietojen mukaan tämä paikka on muinaisen sivilisaation keskus, joka on huomattavasti vanhempi kuin ihmisen tunnettu historia. Meidän täytyy löytää tämä paikka mahdollisimman pian. Tätä varten meidän on kaapattava elävänä ja kuulusteltava muukalaisten johtajia. Useimmissa suuremmissa ufoissa on vähintään yksi muukalaisten johtaja.\"\n  STR_THE_MARTIAN_SOLUTION_UFOPEDIA: \"Tutkimuksemme viittaa siihen, että muukalaisilla on päätukikohta Marsissa. Tukikohta on piilotettu hyvin, ja se sisältää kaiken tarvittavan laitteiston tuotantoa ja kloonausta varten, joita tarvitaan Maahan soluttautumiseen. Vaikuttaa siltä, että siellä sijaitsee myös jonkinlainen muukalaisten keskustietokone, joka ohjaa koko muukalaisten toimintaa. Näyttäisi siis siltä, että mehiläisyhdyskuntaa muistuttavilla muukalaisilla on jonkinlainen \\\"kuningatarmehiläinen\\\". Tämä on heidän keskeinen heikkoutensa - jos pystymme tuhoamaan nämä \\\"aivot\\\", koko ruumis kuolee. Meidän on kiihdytettävä tutkimustamme, ennen kuin on liian myöhäistä. Edetäksemme kuulusteluissa meidän on kaapattava muukalaisten hierarkiassa kaikista korkeimman tason muukalaisia. Näitä ovat muukalaisten komentajat, joita löytyy vain muukalaisten tukikohdista sekä taistelualuksista.\"\n  STR_CYDONIA_OR_BUST_UFOPEDIA: \"Nyt on selvinnyt että muukalaisten joukkoja johdetaan maanalaisesta tukikohdasta Kydoniassa - joka on epätavallinen alue Marsissa, joka sisältää viisisivuisia pyramideja sekä suuren muodostelman joka muistuttaa ihmisen kasvoja. Kydoniassa oli kukoistava sivilisaatio monia miljoonia vuosia sitten, mutta me emme tiedä miksi se kuihtui pois, ja mikä on sen yhteys viimeaikaiseen muukalaisten aktiivisuuteen siellä. Oli syy mikä tahansa, meidän täytyy lähettää retkikunta Kydoniaan. Tämä on ainoa tapa jolla voimme voittaa muukalaiset. Meidän täytyy tuhota muukalaisten johtava keskus, \\\"aivot\\\". Tarvitsemme yhden Avenger-tyyppisen kuljetus- ja hävittäjäkoneen, joka on varustettu kaikista parhaimmalla tuhovoimalla, jota meillä on käytettävissä. Maan päällä emme voi saavuttaa enempää - hyökkäys Kydoniaan on ainoa vaihtoehto.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"KOHDISTA PAIKKAAN - AIKA=5 s\"\n  STR_CANCEL_UC: \"PERUUTA\"\n  STR_NONE: \"Ei mitään\"\n  STR_UNKNOWN: \"Tuntematon\"\n  STR_POOR: \"Huono\"\n  STR_AVERAGE: \"Keskiverto\"\n  STR_GOOD: \"Hyvä\"\n  STR_EXCELLENT: \"Erinomainen\"\n  STR_BUILD_NEW_BASE_UC: \"RAKENNA UUSI TUKIKOHTA\"\n  STR_BASE_INFORMATION: \"TUKIKOHDAN TIEDOT\"\n  STR_EQUIP_CRAFT: \"ALUKSET\"\n  STR_BUILD_FACILITIES: \"RAKENNA LAITOKSIA\"\n  STR_RESEARCH: \"TUTKIMUS\"\n  STR_MANUFACTURE: \"TUOTANTOPROJEKTIT\"\n  STR_TRANSFER_UC: \"SIIRRÄ\"\n  STR_PURCHASE_RECRUIT: \"OSTA/VÄRVÄÄ\"\n  STR_SACK: \"EROTA\"\n  STR_SELL_SACK_UC: \"MYY/EROTA\"\n  STR_GEOSCAPE_UC: \"GEOMAISEMA\"\n  STR_NAME: \"Nimi\"\n  STR_AREA: \"Alue\"\n  STR_BUILD_NEW_BASE: \"Rakenna uusi tukikohta\"\n  STR_CANCEL: \"Peruuta\"\n  STR_COST_UC: \"HINTA>\"\n  STR_CONSTRUCTION_TIME_UC: \"RAKENNUSAIKA>\"\n  STR_DAY:\n    one: \"{N} päivä\"\n    other: \"{N} päivää\"\n  STR_HOUR:\n    one: \"{N} tunti\"\n    other: \"{N} tuntia\"\n  STR_MAINTENANCE_UC: \"YLLÄPITO>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Rakenna\"\n  STR_CURRENT_RESEARCH: \"TUTKIMUSPROJEKTIT\"\n  STR_SCIENTISTS_AVAILABLE: \"Tiedemiehiä vapaana>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Tiedemiehiä projekteissa>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Laboratoriotilaa vapaana>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"TUTKIMUSPROJEKTI\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"TIEDEMIEHIÄ\"\n  STR_PROGRESS: \"EDISTYMINEN\"\n  STR_NEW_PROJECT: \"Uusi projekti\"\n  STR_CANCEL_PROJECT: \"PERUUTA PROJEKTI\"\n  STR_NEW_RESEARCH_PROJECTS: \"UUDET TUTKIMUSPROJEKTIT\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"TIEDEMIEHIÄ VAPAANA>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"LABORATORIOTILAA VAPAANA>{ALT}{0}\"\n  STR_INCREASE: \"Lisää\"\n  STR_DECREASE: \"Vähennä\"\n  STR_START_PROJECT: \"ALOITA PROJEKTI\"\n  STR_CURRENT_PRODUCTION: \"TUOTANTOPROJEKTIT\"\n  STR_ENGINEERS_AVAILABLE: \"Teknikkoja vapaana>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Teknikkoja projekteissa>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Työpajatilaa vapaana>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Nykyiset varat>{ALT}{0}\"\n  STR_ITEM: \"TAVARA\"\n  STR_ENGINEERS__ALLOCATED: \"Teknikkoja projektissa\"\n  STR_UNITS_PRODUCED: \"Tuotetut yksiköt\"\n  STR_TOTAL_TO_PRODUCE: \"Tuotetaan yht.\"\n  STR_COST__PER__UNIT: \"Hinta{NEWLINE}per{NEWLINE}yksikkö\"\n  STR_DAYS_HOURS_LEFT: \"Aikaa (d/h) jäljellä\"\n  STR_NEW_PRODUCTION: \"Uusi tuotantoprojekti\"\n  STR_PRODUCTION_ITEMS: \"Mahdolliset projektit\"\n  STR_CATEGORY: \"LUOKITUS\"\n  STR_START_PRODUCTION: \"ALOITA TUOTANTO\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} teknikkotyötuntia yhden yksikön tuottamiseksi\"\n  STR_COST_PER_UNIT_: \"Hinta / yks.>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Tarvittava työpajatila>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"TARVITTAVAT ERITYISTARVIKKEET\"\n  STR_ITEM_REQUIRED: \"TARVITTAVA TAVARA\"\n  STR_UNITS_REQUIRED: \"TARVITTAVAT YKSIKÖT\"\n  STR_UNITS_AVAILABLE: \"YKSIKKÖÄ SAATAVANA\"\n  STR_STOP_PRODUCTION: \"LOPETA TUOTANTO\"\n  STR_ENGINEERS_AVAILABLE_UC: \"TEKNIKKOJA VAPAANA>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"TYÖPAJATILAA VAPAANA>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"TUOTOT / KK>{ALT}{0}\"\n  STR_INCREASE_UC: \"LISÄÄ\"\n  STR_DECREASE_UC: \"VÄHENNÄ\"\n  STR_UNITS_TO_PRODUCE: \"Tuotettavat yksiköt\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Osta/Palkkaa henkilökuntaa\"\n  STR_COST_OF_PURCHASES: \"Tilauksen hinta>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"HINTA / YKS.\"\n  STR_QUANTITY_UC: \"MÄÄRÄ\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"HENKILÖKUNTAA VAPAANA:HENKILÖKUNTAA YHTEENSÄ>\"\n  STR_SOLDIERS: \"Sotilaat\"\n  STR_SCIENTISTS: \"Tutkijat\"\n  STR_ENGINEERS: \"Teknikot\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"TILAA KÄYTETTY:TILAA JÄLJELLÄ>\"\n  STR_LIVING_QUARTERS: \"Asuintila\"\n  STR_STORES: \"Varastot\"\n  STR_LABORATORIES: \"Laboratoriot\"\n  STR_WORK_SHOPS: \"Työpajat\"\n  STR_HANGARS: \"Lentokonehallit\"\n  STR_SHORT_RANGE_DETECTION: \"Lyhyen matkan tutkat\"\n  STR_DEFENSE_STRENGTH: \"Puolustusvoima\"\n  STR_TRANSFERS_UC: \"SIIRROT\"\n  STR_TRANSFERS: \"Siirrot\"\n  STR_ARRIVAL_TIME_HOURS: \"Saapumisaika (tuntia)\"\n  STR_COST_: \"Hinta>{ALT}{0}\"\n  STR_AREA_: \"Alue>{ALT}{0}\"\n  STR_BASE_NAME: \"Tukikohdan nimi?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"VALITSE LAITOSHISSIN SIJAINTI\"\n  STR_TRANSFER: \"Siirrä\"\n  STR_AMOUNT_TO_TRANSFER: \"SIIRRETTÄVÄ MÄÄRÄ\"\n  STR_SELECT_DESTINATION_BASE: \"Valitse kohdetukikohta\"\n  STR_COST: \"Hinta\"\n  STR_VICTORY_1: \"Kun astut sisään halliin, näet muukalaisten aivot - tehtäväsi päämäärän. Ennen kuin kerkeät tuhota sen aseillasi, se kerkeää kommunikoida kanssasi sen juuressa olevan näytön välityksellä. Se rukoilee sinua kuuntelemaan omaa tarinaansa ja perustelujaan hänen säästämisekseen, ennen kuin teet päätöksen painaa liipaisinta...\"\n  STR_VICTORY_2: \"Muukalaisten aivo puhuu: 'Miljoonia vuosia sitten, tämä planeetta, jota te kutsutte Marsiksi, oli elävä. Elämä täällä oli tuotu tänne meidän sivilisaatiomme toimesta, kuten se on tuotu myös teidän planeetallenne. Miljoonien vuosien ajan olemme vierailleet planeetallanne ja geneettisesti kehittäneet teidän lajianne. Te ette voi tappaa meitä, sillä te olette osa meitä...\"\n  STR_VICTORY_3: \"Tässä on marsilaisen sivilisaation keskus - nämä pyramidit, jotka rakennettiin miljoonia vuosia ennen teidän vastaavianne - erään lajin toimesta, joka on teidän esi-isiänne. Mikään planeetta ei ole meidän ulottumattomissamme. Nämä kyvyt ja voimat voisivat olla teidän. Pyydämme ainoastaan teidän yhteistyötänne...\"\n  STR_GAME_OVER_1: \"Muukalaiset yrittävät tuhota kaiken ihmiskunnasta, tuhoten kaupunkeja ja myrkyttäen ilmaa ja merta. Maan armeijoiden vastustus on turhaa, kun vastassa on ylivoimaista teknologiaa. Jäljelle jääneet sukupolvet kärsivät karmeista mutaatioista samalla kun ne pakenevat muukalaisten aiheuttamaa tuhoa. Lopulta heidät kerätään orjaleireille, jossa he auttavat muuttamaan Maapalloa muukalaisten kolonisaatioksi, joka on osa jotain tuntematonta valtakuntaa.\"\n  STR_GAME_OVER_2: \"X-Com-projektin kautta saavutettu tieto on menetetty lopullisesti. Olet epäonnistunut yrityksessäsi pelastaa Maan.\"\n  STR_VICTORY_4: \"Muukalaisten aivojen selittely keskeytetään kuumalla plasmaryöpyllä, ja muukalaisten joukot on näin voitettu.\"\n  STR_VICTORY_5: \"Nyt, kun muukalaiset ovat menettäneet Marsin, he ovat myös menettäneet Maan. Ennen pitkää X-Com-projektista saatu tieto ja teknologia auttaa ihmiskuntaa kukoistamaan jälleen ja myöskin valloittamaan Marsin itselleen. Muukalaisuhka on torjuttu, mutta kuinka pitkäksi aikaa, sitä ei tiedä kukaan...\"\n  STR_YOU_HAVE_FAILED: \"Olet epäonnistunut pysäyttämään muukalaisten hyökkäyksen. Yksi kerrallaan rahoittavat kansakunnat solmivat sopimuksia muukalaisten kanssa, jotka lupaavat teknologiaa, yltäkylläisyyttä ja rauhaa. Pian kuitenkin selviää, että muukalaisilla on muita suunnitelmia...\"\n  STR_TOTAL_UC: \"YHTEENSÄ\"\n  STR_INCOME: \"Tulot\"\n  STR_EXPENDITURE: \"Menot\"\n  STR_MAINTENANCE: \"Ylläpito\"\n  STR_BALANCE: \"Saldo\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"Ufoaktiivisuus alueittain\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"Ufoaktiivisuus maittain\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"X-Com-aktiivisuus alueittain\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"X-Com-aktiivisuus maittain\"\n  STR_FINANCE: \"Talous\"\n  STR_DATE_FIRST: \"{0}.\"\n  STR_DATE_SECOND: \"{0}.\"\n  STR_DATE_THIRD: \"{0}.\"\n  STR_DATE_FOURTH: \"{0}.\"\n  STR_FINANCE_THOUSANDS: \"1000 $\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Ei riittävästi erityistarvikkeita tuotteen {NEWLINE}{0}{NEWLINE}tuottamiseen tukikohdassa{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Rahat eivät riitä {NEWLINE}{0}{NEWLINE}tuottamiseen tukikohdassa{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"Tuotantoprojektin{NEWLINE}{0}{NEWLINE}tuotanto tukikohdassa{NEWLINE}{1}{NEWLINE}on valmis\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"{NEWLINE}{0}{NEWLINE}on valmistunut{NEWLINE}tukikohdassa{NEWLINE}{1}\"\n  STR_OK_5_SECONDS: \"OK - 5 s\"\n  STR_RESEARCH_COMPLETED: \"Tutkimusprojekti valmis\"\n  STR_VIEW_REPORTS: \"NÄYTÄ RAPORTTI\"\n  STR_WE_CAN_NOW_RESEARCH: \"Uudet tutkimusprojektit:\"\n  STR_WE_CAN_NOW_PRODUCE: \"Uudet tuotantoprojektit:\"\n  STR_SUNDAY: \"SUNNUNTAI\"\n  STR_MONDAY: \"MAANANTAI\"\n  STR_TUESDAY: \"TIISTAI\"\n  STR_WEDNESDAY: \"KESKIVIIKKO\"\n  STR_THURSDAY: \"TORSTAI\"\n  STR_FRIDAY: \"PERJANTAI\"\n  STR_SATURDAY: \"LAUANTAI\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Ei riittävästi {0}-polttoainetta aluksen {1} tankkaamiseksi tukikohdassa {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Ei riittävästi ammustyyppiä {0} {1}:n uudelleen aseistamiseksi tukikohdassa {2}\"\n  STR_UFO_IS_NOT_RECOVERED: \"Ufoa ei saatu korjattua talteen\"\n  STR_UFO_IS_RECOVERED: \"Ufo korjattu talteen\"\n  STR_CRAFT_IS_LOST: \"Alus menetettiin\"\n  STR_TERROR_CONTINUES: \"Terrori jatkuu\"\n  STR_ALIENS_DEFEATED: \"Muukalaiset hävisivät\"\n  STR_BASE_IS_LOST: \"Tukikohta menetettiin\"\n  STR_BASE_IS_SAVED: \"Tukikohta pelastettu\"\n  STR_ALIEN_BASE_STILL_INTACT: \"Muukalaisten tukikohta edelleen toiminnassa\"\n  STR_ALIEN_BASE_DESTROYED: \"Muukalaisten tukikohta tuhottu\"\n  STR_ALIENS_KILLED: \"TAPETUT MUUKALAISET\"\n  STR_ALIEN_CORPSES_RECOVERED: \"MUUKALAISTEN RUUMIITA LÖYDETTY\"\n  STR_LIVE_ALIENS_RECOVERED: \"ELÄVIÄ MUUKALAISIA KAAPATTU\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"MUUKALAISTEN ESINEITÄ LÖYDETTY\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"MUUKALAISTUKIKOHDAN KOMENTOKESKUS TUHOTTU\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"SIVIILEJÄ TAPETTU MUUKALAISTEN TOIMESTA\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"X-COMIN TAPPAMAT SIVIILIT\"\n  STR_CIVILIANS_SAVED: \"SIVIILEJÄ PELASTETTU\"\n  STR_XCOM_OPERATIVES_KILLED: \"KAATUNEET X-COM-SOTILAAT\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"KADONNEET X-COM-SOTILAAT\"\n  STR_TANKS_DESTROYED: \"MTK:ITA TUHOTTU\"\n  STR_XCOM_CRAFT_LOST: \"X-COM-ALUS MENETETTY\"\n  STR_UFO_RECOVERY: \"UFON LAITTEISTO\"\n  STR_ALIEN_BASE_RECOVERY: \"MUUKALAISTEN TUKIKOHDAN SAALIS\"\n  STR_BASE_UNDER_ATTACK: \"{0} hyökkäyksen kohteena!\"\n  STR_BASE_DEFENSES_INITIATED: \"TUKIKOHDAN PUOLUSTUKSET AKTIVOITU\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"PAINOVOIMASUOJA HYLKII UFOA!\"\n  STR_FIRING: \"TULITTAA\"\n  STR_HIT: \"OSUMA!\"\n  STR_UFO_DESTROYED: \"UFO TUHOUTUI!\"\n  STR_MISSED: \"OHI!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Myy tavaraa/Erota henkilökuntaa\"\n  STR_VALUE_OF_SALES: \"MYYNTIEN ARVO> {ALT}{0}\"\n  STR_FUNDS: \"VARAT> {ALT}{0}\"\n  STR_SELL_SACK: \"Myy/erota\"\n  STR_VALUE: \"Arvo\"\n  STR_CRAFT_: \"ALUS> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"UFOHYLYN HALTUUNOTTO\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"Ole varovainen - maahan syöksyneen muukalaisaluksen sisällä tai sen ympäristössä saattaa olla eläviä muukalaisia. Tehtävä on onnistunut, kun kaikki vihollisen yksiköt on tapettu tai tehty muutoin taistelukyvyttömiksi. Vasta sitten voidaan aloittaa muukalaisaluksen purku sekä esineiden ja ruumiiden talteenotto. Keskeyttääksesi tehtävän palauta kaikki X-Com-joukot kuljetusalukseen ja napsauta \\\"Keskeytä tehtävä\\\"-kuvaketta.\"\n  STR_UFO_GROUND_ASSAULT: \"HYÖKKÄYS UFOON\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"Tutki laskeutumisalue ja sen ympäristö ja, mikäli mahdollista, pyri pääsemään muukalaisaluksen sisään. Tehtävä on onnistunut, kun kaikki vihollisen yksiköt on tapettu tai tehty muutoin taistelukyvyttömiksi. Vasta sitten voidaan aloittaa muukalaisaluksen purku sekä esineiden ja ruumiiden talteenotto. Keskeyttääksesi tehtävän palauta kaikki X-Com-joukot kuljetusalukseen ja napsauta \\\"Keskeytä tehtävä\\\"-kuvaketta.\"\n  STR_BASE_DEFENSE: \"TUKIKOHDAN PUOLUSTUS\"\n  STR_BASE_UC_: \"TUKIKOHTA> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"Muukalaisten alus on laskeutunut lähettyville. Tukikohtamme on vakavassa vaarassa. Normaalikäytännön mukaisesti kaikki ei-sotilaallinen henkilökunta sekä X-Com-alukset on evakuoitu. Muukalaiset pyrkivät tukikohtaan joko lentohallien tai laitoshissin kautta. Puolusta tukikohtaa ja sen elintärkeitä laitoksia kaikin mahdollisin keinoin - tämän taistelun hintana on tämä tukikohta. Mikäli napsautat \\\"Keskeytä tehtävä\\\"-kuvaketta, myönnät häviön ja menetät tukikohdan.\"\n  STR_ALIEN_BASE_ASSAULT: \"RYNNÄKKÖ MUUKALAISTEN TUKIKOHTAAN\"\n  STR_ALIEN_BASE_ASSAULT_BRIEFING: \"X-Com-joukot ovat päässeet sisään muukalaisten tukikohtaan. Tukikohdan komentokeskus on tuhottava, jotta tukikohdan toiminta lakkaa. Tehtävä loppuu, kun kaikki muukalaiset on tuhottu tai kun kaikki sotilaat ovat palanneet vihreille poistumisalueille (napsauta \\\"Keskeytä tehtävä\\\"-kuvaketta poistuaksesi tukikohdasta).\"\n  STR_CYDONIA_BRIEFING: \"Olet saapunut Kydoniaan. Sait vallattua sisäänkäynnin suureen maanalaiseen kompleksiin lähellä marsilaista sfinksiä. Sinun täytyy tuhota muukalaisten \\\"aivot\\\", jotka ohjaavat kaikkea muukalaisten toimintaa. Ihmiskunnan kohtalo on sinun käsissäsi...\"\n  STR_TERROR_MISSION: \"TERRORI\"\n  STR_TERROR_MISSION_BRIEFING: \"Tehtävä on onnistunut, kun kaikki vihollisen joukot on tapettu tai muutoin tehty taistelukyvyttömiksi. Sinun täytyy yrittää pelastaa mahdollisiman monta alueella olevaa siviiliä tuhoamalla muukalaisten joukot. Jos haluat perääntyä taistelusta, vie jäljellä olevat X-Com-joukot takaisin kuljetusalukseen ja napsauta \\\"Keskeytä tehtävä\\\"-kuvaketta.\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"EI VAPAATA LENTOKONEHALLIA RAKENNUSPROJEKTIA VARTEN!{SMALLLINE}Jokainen tukikohtaan sijoitettu, siirretty, hankittu tai rakennettu alus vie yhden lentokonehallin verran tilaa. Rakenna uusi lentokonehalli tai siirrä jokin toinen alus toiseen tukikohtaan.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"EI VAPAATA LENTOKONEHALLIA TILAUSTA VARTEN!{SMALLLINE}Jokainen tukikohtaan sijoitettu, siirretty, hankittu tai rakennettu alus vie yhden lentokonehallin verran tilaa. Rakenna uusi lentokonehalli tai siirrä jokin toinen alus toiseen tukikohtaan.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"EI VAPAATA LENTOKONEHALLIA SIIRTOA VARTEN!{SMALLLINE}Jokainen tukikohtaan sijoitettu, siirretty, hankittu tai rakennettu alus vie yhden lentokonehallin verran tilaa. Rakenna uusi lentokonehalli tai siirrä jokin toinen alus toiseen tukikohtaan.\"\n  STR_CANNOT_BUILD_HERE: \"TÄHÄN EI VOI RAKENTAA!{SMALLLINE}Sinun täytyy rakentaa jonkin toisen valmiin laitoksen viereen.\"\n  STR_NO_FREE_ACCOMODATION: \"EI RIITTÄVIÄ ASUINTILOJA!{SMALLLINE}Kohdetukikohdassa ei ole riittävästi asuintiloja.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"TYÖSKENTELYTILAA EI OLE TARPEEKSI!{SMALLLINE}Rakenna lisää työpajoja tai vähennä työskenteleviä insinöörejä muissa projekteissa.\"\n  STR_NOT_ENOUGH_MONEY: \"RAHAA EI OLE RIITTÄVÄSTI!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"VARASTOTILA LOPPU!{SMALLLINE}Rakenna uusi varasto tai siirrä esineitä toisiin tukikohtiin.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"ASUINTILOJA EI OLE RIITTÄVÄSTI!{SMALLLINE}Rakenna lisää asuintiloja tai siirrä henkilökuntaa toisiin tukikohtiin.\"\n  STR_LAUNCH_INTERCEPTION: \"LÄHETÄ HÄVITTÄJÄ/KULJETUSLENTOKONE\"\n  STR_CRAFT: \"ALUS\"\n  STR_STATUS: \"TILA\"\n  STR_BASE: \"TUKIKOHTA\"\n  STR_READY: \"VALMIS\"\n  STR_OUT: \"ULKONA\"\n  STR_REPAIRS: \"KORJATAAN\"\n  STR_REFUELLING: \"TANKATAAN\"\n  STR_REARMING: \"ASEISTETAAN\"\n  STR_TARGET: \"KOHDE: {0}\"\n  STR_WAY_POINT: \"VÄLIETAPPI\"\n  STR_ARE_YOU_SURE_CYDONIA: \"Oletko varma että haluat lähettää tämän aluksen tehtävälle Kydoniaan?\"\n  STR_YES: \"KYLLÄ\"\n  STR_NO: \"EI\"\n  STR_SELECT_DESTINATION: \"VALITSE MÄÄRÄNPÄÄ\"\n  STR_CYDONIA: \"KYDONIA\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"VALITSE SIJAINTI UUDELLE TUKIKOHDALLE\"\n  STR_RETURN_TO_BASE: \"PALAA TUKIKOHTAAN\"\n  STR_SELECT_NEW_TARGET: \"VALITSE UUSI KOHDE\"\n  STR_PATROL: \"PARTIOI\"\n  STR_STATUS_: \"TILA>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"VAURIOITUNUT - PALAA TUKIKOHTAAN\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"POLTTOAINE VÄHISSÄ - PALAA TUKIKOHTAAN\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"TEHTÄVÄ PÄÄTTYNYT - PALAA TUKIKOHTAAN\"\n  STR_PATROLLING: \"PARTIOI\"\n  STR_TAILING_UFO: \"SEURATAAN UFOA\"\n  STR_INTERCEPTING_UFO: \"KOHTEENA UFO-{0}\"\n  STR_RETURNING_TO_BASE: \"PALAA TUKIKOHTAAN\"\n  STR_DESTINATION_UC_: \"MÄÄRÄNPÄÄ: {0}\"\n  STR_BASE_UC: \"TUKIKOHTA>{ALT}{0}\"\n  STR_SPEED_: \"NOPEUS>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"MAKSIMINOPEUS>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"KORKEUS>{ALT}{0}\"\n  STR_VERY_LOW: \"ERITTÄIN MATALA\"\n  STR_LOW_UC: \"MATALA\"\n  STR_HIGH_UC: \"KORKEA\"\n  STR_VERY_HIGH: \"ERITTÄIN KORKEA\"\n  STR_FUEL: \"POLTTOAINE>{ALT}{0}\"\n  STR_WEAPON_ONE: \"ASE 1>{ALT}{0}\"\n  STR_NONE_UC: \"EI MITÄÄN\"\n  STR_ROUNDS_: \"AMMUKSIA>{ALT}{0}\"\n  STR_WEAPON_TWO: \"ASE 2>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"TUKIKOHDAN ALUKSET\"\n  STR_BASE_: \"Tukikohta>{0}\"\n  STR_NAME_UC: \"NIMI\"\n  STR_AMMO_: \"AMMUKSET>{ALT}{0}\"\n  STR_CREW: \"MIEHISTÖ\"\n  STR_EQUIPMENT_UC: \"VARUSTEET\"\n  STR_ARMOR: \"PANSSARIT\"\n  STR_MAX: \"MAKSIMI>{ALT}{0}\"\n  STR_ROOKIE: \"Alokas\"\n  STR_SQUADDIE: \"Sotamies\"\n  STR_SERGEANT: \"Kersantti\"\n  STR_CAPTAIN: \"Kapteeni\"\n  STR_COLONEL: \"Eversti\"\n  STR_COMMANDER: \"Komentaja\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Sotilaat aluksessa {0}\"\n  STR_SORT_BY: \"LAJITTELUPERUSTE...\"\n  STR_ORIGINAL_ORDER: \"ALKUPERÄISJÄRJESTYS\"\n  STR_MISSIONS2: \"TEHTÄVÄT\"\n  STR_KILLS2: \"TAPOT\"\n  STR_WOUND_RECOVERY2: \"TOIPILASAIKA\"\n  STR_SPACE_AVAILABLE: \"TILAA VAPAANA>{ALT}{0}\"\n  STR_SPACE_USED: \"TILANKÄYTTÖ>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"KÄYTETTY TILA\"\n  STR_RANK: \"SOTILASARVO\"\n  STR_WOUNDED: \"HAAVOITTUNUT\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Varusteet aluksessa {0}\"\n  STR_DEFENSE_VALUE: \"Puolustusarvo\"\n  STR_HIT_RATIO: \"Osumatarkkuus\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}on valmis laskeutumaan:{NEWLINE}{ALT}{1}{NEWLINE}\"\n  STR_BEGIN_MISSION: \"Aloitetaanko tehtävä?\"\n  STR_SELECT_ARMAMENT: \"Valitse aseistus\"\n  STR_AMMUNITION_AVAILABLE: \"AMMUKSIA SAATAVANA\"\n  STR_ARMAMENT: \"ASEISTUS\"\n  STR_NOT_AVAILABLE: \"EI TARV\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"VALITSE PANSSARI SOTILAALLE{NEWLINE}{0}\"\n  STR_TYPE: \"TYYPPI\"\n  STR_PERSONAL_ARMOR_UC: \"HENKILÖPANSSARI\"\n  STR_POWER_SUIT_UC: \"VOIMAPANSSARI\"\n  STR_FLYING_SUIT_UC: \"LENTOPANSSARI\"\n  STR_SELECT_ARMOR: \"Valitse panssari\"\n  STR_NORTH: \"POHJOINEN\"\n  STR_NORTH_EAST: \"KOILLINEN\"\n  STR_EAST: \"ITÄ\"\n  STR_SOUTH_EAST: \"KAAKKO\"\n  STR_SOUTH: \"ETELÄ\"\n  STR_SOUTH_WEST: \"LOUNAS\"\n  STR_WEST: \"LÄNSI\"\n  STR_NORTH_WEST: \"LUODE\"\n  STR_SELECT_ACTION: \"VALITSE TOIMINTO\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"JATKA TORJUNTATEHTÄVÄÄ\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"JATKA ILMAN HYÖKKÄYSTÄ\"\n  STR_VERY_LARGE: \"ERITTÄIN SUURI\"\n  STR_LARGE: \"SUURI\"\n  STR_MEDIUM_UC: \"KESKIKOKOINEN\"\n  STR_SMALL: \"PIENI\"\n  STR_VERY_SMALL: \"HYVIN PIENI\"\n  STR_GROUNDED: \"MAA\"\n  STR_DETECTED: \"Havaittu\"\n  STR_SIZE_UC: \"KÄYTÖSSÄ\"\n  STR_ALTITUDE: \"KORKEUS\"\n  STR_HEADING: \"SUUNTA\"\n  STR_SPEED: \"NOPEUS\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"KOHDISTA UFOON - AIKA=5 s\"\n  STR_TRACKING_LOST: \"SEURANTAJÄLKI KATOSI\"\n  STR_REDIRECT_CRAFT: \"UUDELLEENOHJAA ALUS\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"MENE VIIMEISEEN TUNNETTUUN SIJAINTIIN\"\n  STR_UFO_: \"UFO-{0}\"\n  STR_ALIEN_BASE_: \"MUUKALAISTUKIKOHTA-{0}\"\n  STR_CRASH_SITE_: \"PAKKOLASKUKOHDE-{0}\"\n  STR_LANDING_SITE_: \"LASKEUTUNUT UFO-{0}\"\n  STR_WAY_POINT_: \"VÄLIETAPPI {0}\"\n  STR_TERROR_SITE: \"TERRORIKOHDE-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}on saapunut{NEWLINE}{1}:een\"\n  STR_NOW_PATROLLING: \"Partiointi aloitettu\"\n  STR_ALIEN_ORIGINS: \"Muukalaisten alkuperä\"\n  STR_THE_MARTIAN_SOLUTION: \"Ratkaisu Marsista\"\n  STR_CYDONIA_OR_BUST: \"Kydonia tai tuho\"\n  STR_UFOPAEDIA: \"Ufopedia\"\n  STR_XCOM_CRAFT_ARMAMENT: \"X-COM-ALUKSET JA ASEISTUS\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"MIEHITTÄMÄTÖMÄT TAISTELUKONEET\"\n  STR_WEAPONS_AND_EQUIPMENT: \"ASEET JA VARUSTEET\"\n  STR_ALIEN_ARTIFACTS: \"MUUKALAISTEN VARUSTEET\"\n  STR_BASE_FACILITIES: \"TUKIKOHTIEN LAITOKSET\"\n  STR_ALIEN_LIFE_FORMS: \"MUUKALAISELIÖT\"\n  STR_ALIEN_RESEARCH_UC: \"MUUKALAISTUTKIMUS\"\n  STR_UFO_COMPONENTS: \"UFOJEN KOMPONENTIT\"\n  STR_UFOS: \"UFOT\"\n  STR_SELECT_ITEM: \"VALITSE AIHE\"\n  STR_ACCELERATION: \"KIIHTYVYYS>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"POLTTOAINETANKKI>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"ASEPAIKAT>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"KESTÄVYYS>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"RAHTITILA>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"MTK-TILA>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Tuhovoima\"\n  STR_RANGE: \"Kantama\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Tarkkuus\"\n  STR_RE_LOAD_TIME: \"Uudelleenlatausaika\"\n  STR_SECONDS: \"{0}s\"\n  STR_DAMAGE_ARMOR_PIERCING: \"TAVALLINEN(AP)\"\n  STR_DAMAGE_INCENDIARY: \"PALO\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"RÄJÄHDE\"\n  STR_DAMAGE_LASER_BEAM: \"LASER\"\n  STR_DAMAGE_PLASMA_BEAM: \"PLASMA\"\n  STR_DAMAGE_STUN: \"TAINNUTUS\"\n  STR_DAMAGE_MELEE: \"LÄHITAISTELU\"\n  STR_DAMAGE_ACID: \"HAPPO\"\n  STR_DAMAGE_SMOKE: \"SAVU\"\n  STR_SHOT_TYPE: \"TULITUSTAPA\"\n  STR_ACCURACY_UC: \"TARKKUUS\"\n  STR_TIME_UNIT_COST: \"AY HINTA\"\n  STR_DAMAGE_UC: \"TYYPPI\"\n  STR_AMMO: \"AMMUS\"\n  STR_SHOT_TYPE_AUTO: \"Sarjatuli\"\n  STR_SHOT_TYPE_SNAP: \"Kertatuli\"\n  STR_SHOT_TYPE_AIMED: \"Tähdätty\"\n  STR_CONSTRUCTION_TIME: \"Rakennusaika\"\n  STR_CONSTRUCTION_COST: \"Rakennuskustannukset\"\n  STR_MAINTENANCE_COST: \"Ylläpitokustannukset\"\n  STR_LOW: \"Matala\"\n  STR_MEDIUM: \"Keskikokoinen\"\n  STR_HIGH: \"Korkea\"\n  STR_CRAFT_WEAPON: \"Aluksen ase\"\n  STR_CRAFT_AMMUNITION: \"Aluksen ammukset\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Miehittämätön taistelukone\"\n  STR_WEAPON: \"Ase\"\n  STR_AMMUNITION: \"Ammukset\"\n  STR_EQUIPMENT: \"Varusteet\"\n  STR_ALIEN_CORPSE: \"Muukalaisen ruumis\"\n  STR_UFO_COMPONENT: \"Ufokomponentti\"\n  STR_PERSONAL_ARMOR: \"Henkilöpanssari\"\n  STR_RAW_MATERIALS: \"Raaka-aineet\"\n  STR_HWP_CANNON_SHELLS: \"MTK-ammus\"\n  STR_ALIEN: \"Muukalainen\"\n  STR_SECTOID: \"Harmaa\"\n  STR_SNAKEMAN: \"Käärmemies\"\n  STR_ETHEREAL: \"Eteeri\"\n  STR_MUTON: \"Mutoni\"\n  STR_FLOATER: \"Leijuja\"\n  STR_CELATID: \"Kelatoidi\"\n  STR_SILACOID: \"Silikoidi\"\n  STR_CHRYSSALID: \"Munamies\"\n  STR_ZOMBIE: \"Zombi\"\n  STR_REAPER: \"Raatelija\"\n  STR_SECTOPOD: \"Sektopodi\"\n  STR_CYBERDISC: \"Kyberlautanen\"\n  STR_LIVE_COMMANDER: \"Komentaja\"\n  STR_LIVE_LEADER: \"Johtaja\"\n  STR_LIVE_ENGINEER: \"Teknikko\"\n  STR_LIVE_MEDIC: \"Lääkintämies\"\n  STR_LIVE_NAVIGATOR: \"Navigoija\"\n  STR_LIVE_SOLDIER: \"Sotilas\"\n  STR_LIVE_TERRORIST: \"Terroristi\"\n  STR_FLOATER_SOLDIER: \"Leijujien sotilas\"\n  STR_FLOATER_NAVIGATOR: \"Leijujien navigoija\"\n  STR_FLOATER_MEDIC: \"Leijujien lääkintämies\"\n  STR_FLOATER_ENGINEER: \"Leijujien teknikko\"\n  STR_FLOATER_LEADER: \"Leijujien johtaja\"\n  STR_FLOATER_COMMANDER: \"Leijujien komentaja\"\n  STR_SECTOID_SOLDIER: \"Harmaiden sotilas\"\n  STR_SECTOID_NAVIGATOR: \"Harmaiden navigoija\"\n  STR_SECTOID_MEDIC: \"Harmaiden lääkintämies\"\n  STR_SECTOID_ENGINEER: \"Harmaiden teknikko\"\n  STR_SECTOID_LEADER: \"Harmaiden johtaja\"\n  STR_SECTOID_COMMANDER: \"Harmaiden komentaja\"\n  STR_SNAKEMAN_SOLDIER: \"Käärmemiessotilas\"\n  STR_SNAKEMAN_NAVIGATOR: \"Käärmemiesten navigoija\"\n  STR_SNAKEMAN_ENGINEER: \"Käärmemiesten teknikko\"\n  STR_SNAKEMAN_LEADER: \"Käärmemiesten johtaja\"\n  STR_SNAKEMAN_COMMANDER: \"Käärmemiesten komentaja\"\n  STR_MUTON_SOLDIER: \"Mutonisotilas\"\n  STR_MUTON_NAVIGATOR: \"Mutoneiden navigoija\"\n  STR_MUTON_ENGINEER: \"Mutoneiden teknikko\"\n  STR_ETHEREAL_SOLDIER: \"Eteerisotilas\"\n  STR_ETHEREAL_LEADER: \"Eteerien johtaja\"\n  STR_ETHEREAL_COMMANDER: \"Eteerien komentaja\"\n  STR_CYBERDISC_TERRORIST: \"Kyberlautasterroristi\"\n  STR_REAPER_TERRORIST: \"Raatelijaterroristi\"\n  STR_CHRYSSALID_TERRORIST: \"Munamiesterroristi\"\n  STR_CELATID_TERRORIST: \"Kelatoiditerroristi\"\n  STR_SILACOID_TERRORIST: \"Silikoiditerroristi\"\n  STR_SECTOPOD_TERRORIST: \"Sektopoditerroristi\"\n  STR_UFO_POWER_SOURCE: \"Ufon voimanlähde\"\n  STR_UFO_NAVIGATION: \"Ufon navigointilaite\"\n  STR_UFO_CONSTRUCTION: \"Ufon rakennus\"\n  STR_ALIEN_FOOD: \"Muukalaisten ruoka\"\n  STR_ALIEN_REPRODUCTION: \"Muukalaisten lisääntyminen\"\n  STR_ALIEN_ENTERTAINMENT: \"Muukalaisten viihdytys\"\n  STR_ALIEN_SURGERY: \"Muukalaisten kirurgia\"\n  STR_EXAMINATION_ROOM: \"Tutkimushuone\"\n  STR_ALIEN_ALLOYS: \"Muukalaisten metalliseokset\"\n  STR_ALIEN_HABITAT: \"Muukalaisten elintilat\"\n  STR_POWER_SUIT: \"Voimapanssari\"\n  STR_FLYING_SUIT: \"Lentopanssari\"\n  STR_HWP_ROCKETS: \"MTK raketti\"\n  STR_HWP_FUSION_BOMB: \"MTK fuusiopommi\"\n  STR_LASER_WEAPONS: \"Laseraseet\"\n  STR_NEW_FIGHTER_CRAFT: \"Uusi taisteluhävittäjä\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Uusi hävittäjä-kuljetusalus\"\n  STR_ULTIMATE_CRAFT: \"Huippualus\"\n  STR_LASER_PISTOL: \"Laser-pistooli\"\n  STR_LASER_RIFLE: \"Laserkivääri\"\n  STR_HEAVY_LASER: \"Laserkäsitykki\"\n  STR_LASER_CANNON: \"Lasertykki\"\n  STR_PLASMA_CANNON: \"Plasmatykki\"\n  STR_FUSION_MISSILE: \"Fuusio-ohjus\"\n  STR_LASER_DEFENSE: \"Laserpuolustus\"\n  STR_PLASMA_DEFENSE: \"Plasmapuolustus\"\n  STR_FUSION_DEFENSE: \"Fuusiopuolustus\"\n  STR_GRAV_SHIELD: \"Painovoimasuoja\"\n  STR_MIND_SHIELD: \"EEG-suoja\"\n  STR_PSI_LAB: \"Psi-laboratorio\"\n  STR_MOTION_SCANNER: \"Liiketunnistin\"\n  STR_MEDI_KIT: \"Ensiapulaite\"\n  STR_TANK_CANNON: \"MTK/Tykki\"\n  STR_TANK_ROCKET_LAUNCHER: \"MTK/Raketinheitin\"\n  STR_TANK_LASER_CANNON: \"MTK/Lasertykki\"\n  STR_HOVERTANK_PLASMA: \"LMTK/Plasma\"\n  STR_HOVERTANK_LAUNCHER: \"LMTK/Laukaisija\"\n  STR_STINGRAY_LAUNCHER: \"Stingray -ohjuslaukaisin\"\n  STR_AVALANCHE_LAUNCHER: \"Avalanche -ohjuslaukaisin\"\n  STR_CANNON: \"Tykki\"\n  STR_FUSION_BALL_LAUNCHER: \"Fuusiopallolaukaisin\"\n  STR_PLASMA_BEAM: \"Plasmasäde\"\n  STR_STINGRAY_MISSILES: \"Stingray -ohjus\"\n  STR_AVALANCHE_MISSILES: \"Avalanche -ohjus\"\n  STR_CANNON_ROUNDS_X50: \"Tykin ammus(x50)\"\n  STR_FUSION_BALL: \"Fuusiopallo\"\n  STR_SOLDIER: \"Sotilas\"\n  STR_SCIENTIST: \"Tiedemies\"\n  STR_ENGINEER: \"Teknikko\"\n  STR_NORTH_AMERICA: \"Pohjois-Amerikka\"\n  STR_ARCTIC: \"Arktinen\"\n  STR_ANTARCTICA: \"Antarktinen\"\n  STR_SOUTH_AMERICA: \"Etelä-Amerikka\"\n  STR_EUROPE: \"Eurooppa\"\n  STR_NORTH_AFRICA: \"Pohjois-Afrikka\"\n  STR_SOUTHERN_AFRICA: \"Etelä-Afrikka\"\n  STR_CENTRAL_ASIA: \"Keski-Aasia\"\n  STR_SOUTH_EAST_ASIA: \"Kaakkois-Aasia\"\n  STR_SIBERIA: \"Siperia\"\n  STR_AUSTRALASIA: \"Australaasia\"\n  STR_PACIFIC: \"Tyyni valtameri\"\n  STR_NORTH_ATLANTIC: \"Pohjois-Atlantti\"\n  STR_SOUTH_ATLANTIC: \"Etelä-Atlantti\"\n  STR_INDIAN_OCEAN: \"Intian valtameri\"\n  STR_ALIEN_RESEARCH: \"Muukalaistutkimus\"\n  STR_ALIEN_HARVEST: \"Muukalaissadonkorjuu\"\n  STR_ALIEN_ABDUCTION: \"Muukalaiskaappaus\"\n  STR_ALIEN_INFILTRATION: \"Muukalaissoluttautuminen\"\n  STR_ALIEN_BASE: \"Muukalaisten tukikohta\"\n  STR_ALIEN_TERROR: \"Muukalaisterrori\"\n  STR_ALIEN_RETALIATION: \"Muukalaisten hyökkäys\"\n  STR_ALIEN_SUPPLY: \"Muukalaishuolto\"\n  STR_MAXIMUM_SPEED: \"Maksiminopeus\"\n  STR_HYPER_WAVE_DECODER_UC: \"HYPERAALTOTULKITSIN\"\n  STR_SKYRANGER: \"SKYRANGER\"\n  STR_LIGHTNING: \"LIGHTNING\"\n  STR_AVENGER: \"AVENGER\"\n  STR_INTERCEPTOR: \"HÄVITTÄJÄ\"\n  STR_FIRESTORM: \"FIRESTORM\"\n  STR_UFO: \"UFO\"\n  STR_STINGRAY: \"STINGRAY\"\n  STR_AVALANCHE: \"AVALANCHE\"\n  STR_CANNON_UC: \"TYKKI\"\n  STR_FUSION_BALL_UC: \"FUUSIOPALLO\"\n  STR_LASER_CANNON_UC: \"LASERTYKKI\"\n  STR_PLASMA_BEAM_UC: \"PLASMATYKKI\"\n  STR_DAMAGE_CAPACITY: \"Kestävyys\"\n  STR_WEAPON_POWER: \"Tulivoima\"\n  STR_WEAPON_RANGE: \"Aseen kantama\"\n  STR_ACCESS_LIFT: \"Laitoshissi\"\n  STR_LABORATORY: \"Laboratorio\"\n  STR_WORKSHOP: \"Työpaja\"\n  STR_SMALL_RADAR_SYSTEM: \"Lyhyen matkan tutka\"\n  STR_LARGE_RADAR_SYSTEM: \"Pitkän matkan tutka\"\n  STR_MISSILE_DEFENSES: \"Ohjuspuolustus\"\n  STR_GENERAL_STORES: \"Varasto\"\n  STR_ALIEN_CONTAINMENT: \"Muukalaisten vankilaitos\"\n  STR_LASER_DEFENSES: \"Laserpuolustus\"\n  STR_PLASMA_DEFENSES: \"Plasmapuolustus\"\n  STR_FUSION_BALL_DEFENSES: \"Fuusiopallopuolustus\"\n  STR_PSIONIC_LABORATORY: \"Psioninen laboratorio\"\n  STR_HYPER_WAVE_DECODER: \"Hyperaaltotulkitsin\"\n  STR_HANGAR: \"Lentokonehalli\"\n  STR_USA: \"YHDYSVALLAT\"\n  STR_RUSSIA: \"VENÄJÄ\"\n  STR_UK: \"ISO-BRITANNIA\"\n  STR_FRANCE: \"RANSKA\"\n  STR_GERMANY: \"SAKSA\"\n  STR_ITALY: \"ITALIA\"\n  STR_SPAIN: \"ESPANJA\"\n  STR_CHINA: \"KIINA\"\n  STR_JAPAN: \"JAPANI\"\n  STR_INDIA: \"INTIA\"\n  STR_BRAZIL: \"BRASILIA\"\n  STR_AUSTRALIA: \"AUSTRALIA\"\n  STR_NIGERIA: \"NIGERIA\"\n  STR_SOUTH_AFRICA: \"ETELÄ-AFRIKKA\"\n  STR_EGYPT: \"EGYPTI\"\n  STR_CANADA: \"KANADA\"\n  STR_TANK: \"MTK\"\n  STR_CIVILIAN: \"Siviili\"\n  STR_JAN: \"1.\"\n  STR_FEB: \"2.\"\n  STR_MAR: \"3.\"\n  STR_APR: \"4.\"\n  STR_MAY: \"5.\"\n  STR_JUN: \"6.\"\n  STR_JUL: \"7.\"\n  STR_AUG: \"8.\"\n  STR_SEP: \"9.\"\n  STR_OCT: \"10.\"\n  STR_NOV: \"11.\"\n  STR_DEC: \"12.\"\n  STR_INTERNATIONAL_RELATIONS: \"Kansainväliset suhteet\"\n  STR_COUNTRY: \"Maa\"\n  STR_FUNDING: \"Rahoitus\"\n  STR_CHANGE: \"Muutos\"\n  STR_WEAPON_SYSTEMS: \"ASE-{NEWLINE}PAIKAT\"\n  STR_HWPS: \"MTKt\"\n  STR_DAMAGE_UC_: \"VAURIOASTE>{ALT}{0}\"\n  STR_ACCESS_LIFT_UFOPEDIA: \"Laitoshissi on ainoa reitti, jota kautta henkilökuntaa ja tarvikkeita voidaan siirtää maanalaiseen tukikohtaan ja sieltä pois. Se on aina ensimmäinen osa tukikohtaa, joka rakennetaan. Laitoshissi ja sen ympäristö on haavoittuvainen mahdollisen ulkopuolisen hyökkäyksen tapauksessa.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Jokainen asuintilakompleksi sisältää riittävästi asuintilaa 50:lle henkilölle. Asuintilakompleksissa on välttämättömät virkistäytymis- ruokailu- hygienia- ja nukkumistilat.\"\n  STR_LABORATORY_UFOPEDIA: \"Jopa 50 tiedemiestä pystyy työskentelemään yhdessä laboratoriossa. Laboratorioissa on viimeisin teknologia materiaalien, biokemian ja kosmologian tutkimukseen. Laboratoriosta on etuoikeutettu etäyhteys maailman johtaviin laboratorioihin, sekä myös sotilaallisiin tutkimuslaitoksiin.\"\n  STR_WORKSHOP_UFOPEDIA: \"Työpaja sisältää kaiken tarvittavan laitteiston erilaisten tarvikkeiden ja osien tuottamiseen tiedemiesten suunnitelmien pohjalta. Enintään 50 teknikkoa voi työskennellä yhdessä työpajassa, joskin itse osien tuottaminen vie jonkin verran myös tästä tilasta.\"\n  STR_SMALL_RADAR_SYSTEM_UFOPEDIA: \"Lyhyen matkan tutkalla on 300 merimailin toimintasäde, ja se on linkitetty satelliittijärjestelmiin maanpäällisten kohteiden havaitsemista varten. Jokaisella tutkalla on 10 % todennäköisyys havaita keskikokoinen kappale joka 30. minuutti. \"\n  STR_LARGE_RADAR_SYSTEM_UFOPEDIA: \"Pitkän matkan tutkalla on 450 merimailin toimintasäde, ja se on linkitetty satelliittijärjestelmiin maanpäällisten kohteiden havaitsemista varten. Jokaisella tutkalla on 20 % todennäköisyys havaita keskikokoinen kappale joka 30. minuutti.\"\n  STR_MISSILE_DEFENSES_UFOPEDIA: \"Ohjuspuolustusjärjestelmä tarjoaa jonkin verran suojaa vihamielisten alusten yrittäessä laskeutua lähelle tukikohtaa.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"Kaikki varusteet, asejärjestelmät, ammukset, saaliiksi saadut materiaalit ja miehittämättömät taistelukoneet (MTK:t) varastoidaan, myös silloin kun ne on määrätty johonkin alukseen.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"Elävät muukalaiset vaativat vankilaansa todennäköisesti erityisen elinympäristön jotta niiden elintoimintonsa pysyvät yllä. Tällaiseen vankilaitokseen mahtuu enintään 10 muukalaista itsenäisiin vankiyksiköihin.\"\n  STR_LASER_DEFENSES_UFOPEDIA: \"Laserpuolustusjärjestelmä tarjoaa suojaa vihamielisien alusten lähestyessä tukikohtaa. \"\n  STR_PLASMA_DEFENSES_UFOPEDIA: \"Plasmapuolustusjärjestelmä tarjoaa voimakasta ja tehokasta puolustustulitusta vihamielisen aluksen pyrkiessä lähestymään tukikohtaa.\"\n  STR_FUSION_BALL_DEFENSES_UFOPEDIA: \"Fuusio-ohjuksien avulla on mahdollista toteuttaa tehokkain tunnettu puolustus muukalaisten hyökkäystä vastaan. Nämä ohjukset aiheuttavat osuessaan antimateriaimploosion, joka tuhoaa kaiken tietyn etäisyyden sisäpuolella.\"\n  STR_GRAV_SHIELD_UFOPEDIA: \"Painovoimasuoja hylkii laskeutumaan pyrkiviä aluksia, hidastaen niiden laskeutumista jotta puolustusjärjestelmillä on enemmän aikaa toimia. Käytännössä tämä tarkoittaa että tukikohdan puolustusjärjestelmien tehokkuus tuplaantuu.\"\n  STR_MIND_SHIELD_UFOPEDIA: \"Koska muukalaisten alukset etsivät ihmisiä ihmisten aivoaaltojen perusteella, on kaikista tehokkain vastatoimenpide estää aivoaaltojen havaitseminen tukikohdan ulkopuolelta. Tämä laitos vähentää radikaalisti muukalaisalusten mahdollisuutta havaita tukikohtaa.\"\n  STR_PSIONIC_LABORATORY_UFOPEDIA: \"Psionisen laboratorion avulla pääsemme arvioimaan kaikkien sotilaiden psionisen potentiaalin sekä kouluttamaan heitä käyttämään psionisia kykyjään. Jokainen laboratorio pystyy kouluttamaan enintään kymmenen sotilasta. Koulutuspaikat jaetaan aina kuun lopussa käytännön sanelemista syistä. Psioniset kyvyt yhdistettynä Psi-vahvistimeen mahdollistavat psionisten hyökkäysten käytön taistelujen aikana.\"\n  STR_HYPER_WAVE_DECODER_UFOPEDIA: \"Muukalaisten viestintä perustuu yliulottuvuuksisiin aaltoihin, jotka ylittävät valonnopeuden normaalista avaruudesta tarkasteltuna. Tulkitsinlaitos kaappaa ufojen lähetyksiä sekä tulkitsee niiden sisältämät viestit. Näin saamme tietoomme ufon tyypin, kyseessä olevan muukalaislajin sekä minkälaisella tehtävällä alus on.\"\n  STR_HANGAR_UFOPEDIA: \"Jokaiseen lentokonehalliin mahtuu yksi ilma-alus. Näissä halleissa on kaikki tarvittava X-Com-alusten huoltoa, tankkausta ja korjausta varten. Jokainen alus, joka on määrätty tukikohtaan, vaatii oman lentokonehallinsa, eikä hallia voi käyttää samanaikaisesti mikään muu alus, ei vaikka laitokseen määrätty alus olisi ilmassa.\"\n  STR_PISTOL_UFOPEDIA: \"X-Comin vakiopistooli on suuritehoinen, itselataava, ja sen lipaskapasiteetti on 12 patruunaa.\"\n  STR_RIFLE_UFOPEDIA: \"Tässä erittäin tarkassa tarkkuuskiväärissä on lasertähtäin. Siihen käy 6,7mm hylsyt 20kpl lippaissa.\"\n  STR_HEAVY_CANNON_UFOPEDIA: \"Käsikanuuna on tuhovoimaltaan erinomainen, mutta kömpelö käsiase. Se on kuitenkin erittäin monikäyttöinen sillä siinä voidaan käyttää kolmea erityyppistä ammusta - tavallisten lisäksi palopommi- ja räjähdeammuksia (HC-AP, HC-I ja HC-HE).\"\n  STR_AUTO_CANNON_UFOPEDIA: \"Autokanuuna yhdistää käsikanuunan monipuolisuuden ja voiman nopeaan tulitusnopeuteen ja sarjatulikykyyn.\"\n  STR_ROCKET_LAUNCHER_UFOPEDIA: \"Raketinheittimellä voidaan laukaista kolmen kokoisia, laserohjattuja raketteja.\"\n  STR_LASER_PISTOL_UFOPEDIA: \"Laserpistooli on esimerkki laserteknologian tehokkaasta käytöstä. Se on yhtä kätevä kuin perinteinen pistooli, mutta nopeampi ja tarkempi.\"\n  STR_LASER_RIFLE_UFOPEDIA: \"Laserkivääri on tehokkaampi ja tarkempi versio aiemmasta laserpistoolimallista.\"\n  STR_HEAVY_LASER_UFOPEDIA: \"Laserkäsitykki on kömpelö käsiase, joskin erittäin tehokas.\"\n  STR_GRENADE_UFOPEDIA: \"Tämä käsikranaatti on varustettu hienostuneella ajastinmekanismilla, joka mahdollistaa räjähtämisajan tarkan kontrolloinnin.\"\n  STR_SMOKE_GRENADE_UFOPEDIA: \"Savuheitteet ovat hyödyllisiä taistelutilanteissa vähentämään näkyvyyttä avonaisilla alueilla. Käytön tulee olla harkittua, sillä savusta voi olla hyötyä myös viholliselle.\"\n  STR_PROXIMITY_GRENADE_UFOPEDIA: \"Sensorikranaattia voidaan käyttää kuten tavallista kranaattia, mutta se räjähtää vasta, kun sen liiketunnistin havaitsee liikettä riittävän lähellä asetetun aktivoitumisajan jälkeen. Sen tehokas käyttö taistelutilanteessa vaatii paljon taitoa sekä huolellisuutta.\"\n  STR_HIGH_EXPLOSIVE_UFOPEDIA: \"Tätä räjähdettä tulisi käyttää vain räjäytystyömailla esim. rakennusten purkamiseen. Varmista että kaikki henkilöt ovat poistuneet työmaa-alueelta ennen räjäytystä.\"\n  STR_MOTION_SCANNER_UFOPEDIA: \"Tämä hienostunut laite käyttää useita erilaisia ilmaisimia ja kehittyneitä tietokonealgoritmeja tunnistaakseen liikkuvia kohteita. Sen tehokas käyttö vaatii kuitenkin harjoitusta. Napsauta liikkeentunnistinkuvaketta taktisessa taistelunäkymässä. Valitse \\\"Käytä liikkeentunnistinta\\\" valikosta. Liikkeentunnistimen näytössä näkyy nuoli, joka kuvaa käyttäjän katselusuuntaa (pohjoinen on aina ylhäällä). Näytöllä vilkkuvat täplät ilmaisevat kohteet, jotka ovat hiljattain liikkuneet. Suuret ja/tai nopeasti liikkuvat kohteet synnyttävät suurempia täpliä. Laite ei rekisteröi liikkumatomia kohteita.\"\n  STR_MEDI_KIT_UFOPEDIA: \"Ensiapulaite pitää sisällään parannuslaitteiston, kipulääkkeitä sekä taistelupiristeitä. Käyttääksesi ensiapulaitetta sotilaan täytyy seistä katsoen päin sotilasta, joka on hoidon tarpeessa. Jos sotilas on tajuton, täytyy käyttäjän seistä aivan sotilaan yläpuolella. Napsauta ensiapulaitteen kuvaketta ja napsauta \\\"Käytä ensiapulaitetta\\\" valikosta.{NEWLINE}PARANNA> Punaiset ruumiinosat näyttävät vakavien haavojen sijainnin. Napsauta kohtaa, jossa on havaittu vakava haava. Napsauta \\\"Paranna\\\"-nappia. Yksi vakava haava parannetaan ja osa hoidetun sotilaan terveydestä palautuu.{NEWLINE}PIRISTE> Tämä palauttaa osan potilaan energiasta sekä herättää tajuttoman (tai tainnutetun) sotilaan. Herättääksesi tajuttoman sotilaan sinun tulee seistä aivan sotilaan yläpuolella. {NEWLINE}KIPULÄÄKE> Kipulääkkeen antaminen palauttaa haavoittuneen sotilaan taistelutahtoa sotilaan menettämän terveyden verran.\"\n  STR_PSI_AMP_UFOPEDIA: \"Vain sotilaat, joilla on Psi-kykyjä, pystyvät käyttämään Psi-vahvistinta. Taistelun aikana napsauta Psi-vahvistinta valitaksesi hyökkäyksen tyypin ja sen jälkeen hyökkäyksen kohteen. Hyökkäyksiä on kahta eri tyyppiä:{NEWLINE}PANIIKKIKOHTAUS> Jos hyökkäys onnistuu, se vähentää kohteen taistelutahtoa, mikä saattaa johtaa kohteen panikointiin.{NEWLINE}MIELENHALLINTA> Jos tämä hyökkäystyyppi onnistuu, saat väliaikaisesti vihollisen hallintaasi, aivan kuten se taistelisi sinun puolellasi. Tämä hyökkäys on huomattavasti vaikeampi toteuttaa kuin ensimmäinen.\"\n  STR_STUN_ROD_UFOPEDIA: \"Tätä laitetta voidaan käyttää vain lähietäisyydeltä. Se tainnuttaa kohteen tappamatta sitä sähköiskun avulla.\"\n  STR_MIND_PROBE_UFOPEDIA: \"Mielenluotain on muukalaisten viestintälaite, jolla voi lukea tietoa suoraan aivoaalloista. X-Com-sotilaat pystyvät käyttämään tätä laitetta taistelutilanteessa saadakseen tietoa kohteena olevan muukalaisen ominaisuuksista. Napsauta mielenluotainta ja valitse sitten \\\"Käytä mielenluotainta\\\"-vaihtoehto. Sen jälkeen valitse muukalainen osoittimella.\"\n  STR_PLASMA_PISTOL_UFOPEDIA: \"Plasmapistoolit ovat tappavia muukalaisperäisiä aseita, joiden toiminta perustuu hiukkasten kiihdyttämiseen pienessä antigravitaatiokentässä.\"\n  STR_PLASMA_RIFLE_UFOPEDIA: \"Tämä on tuhovoimaltaan erinomainen ase, jonka toiminta perustuu hiukkasten kiihdyttämiseen pienen antipainovoimakentän avulla.\"\n  STR_HEAVY_PLASMA_UFOPEDIA: \"Tämä on tuhovoimaltaan erinomainen ase, jonka toiminta perustuu hiukkasten kiihdyttämiseen pienen antipainovoimakentän avulla.\"\n  STR_BLASTER_LAUNCHER_UFOPEDIA: \"Tämä on muukalaisten älykäs ohjuslaukaisin, joka laukaisee tehokkaita \\\"suurtuhopommeja\\\". Kun napsautat laukaisutoimintoa, voit kohdistaa etappipisteitä, joiden kautta ohjus kulkee viimeiseen ohjelmoituun etappipisteeseen asti. Kun olet ohjelmoinut riittävästi etappipisteitä, napsauta laukaisukuvaketta.\"\n  STR_SMALL_LAUNCHER_UFOPEDIA: \"Ase, jolla voi laukaista pieniä tainnutuspommeja. Se on erittäin käyttökelpoinen elävien muukalaisten kaappaamisessa.\"\n  STR_ALIEN_GRENADE_UFOPEDIA: \"Tämä laite toimii käytännössä aivan samaan tapaan kuin tavallinen käsikranaatti - paitsi, että se on voimakkaampi.\"\n  STR_SMALL_SCOUT: \"Pieni tiedustelija\"\n  STR_MEDIUM_SCOUT: \"Keskikokoinen tiedustelija\"\n  STR_LARGE_SCOUT: \"Iso tiedustelija\"\n  STR_HARVESTER: \"Sadonkorjaaja\"\n  STR_ABDUCTOR: \"Kaappaaja\"\n  STR_TERROR_SHIP: \"Terrorialus\"\n  STR_BATTLESHIP: \"Taistelualus\"\n  STR_SUPPLY_SHIP: \"Huoltoalus\"\n  STR_RATING: \"ARVIO> {0}\"\n  STR_RATING_TERRIBLE: \"KAMALA!\"\n  STR_RATING_POOR: \"HUONO!\"\n  STR_RATING_OK: \"OK\"\n  STR_RATING_GOOD: \"HYVÄ!\"\n  STR_RATING_EXCELLENT: \"ERINOMAINEN!\"\n  STR_SCORE: \"PISTEET\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"X-COM-PROJEKTIN KUUKAUSIRAPORTTI\"\n  STR_MONTH: \"Kuukausi> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"Rahoittavien kansakuntien neuvosto on toistaiseksi tyytyväinen toimintaansi.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"Rahoittavien kansakuntien neuvosto on erittäin tyytyväinen loistavaan edistymiseesi. Pidä yllä hyvää työn tasoa!\"\n  STR_COUNCIL_IS_DISSATISFIED: \"Rahoittavien kansakuntien neuvosto on tyytymätön suoritukseesi. Sinun täytyy parantaa tulostasi muukalaisuhan torjumisessa tai projektia uhkaa lakkautus.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"Olet epäonnistunut käsittelemään muukalaisten invaasiota joten rahoittavien kansakuntien neuvosto on valitettavasti päättänyt lopettaa projektin. Jokainen valtio käsittelee ongelman kuten parhaaksensa näkee. Voimme vain toivoa, että voimme päästä jonkinlaiseen yhteisymmärykseen näiden ilmeisen vihamielisten olentojen kanssa, ja että väestö hyväksyy muukalaisten vierailun.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} on erittäin kiitollinen kykyysi torjua paikallista muukalaisten uhkaa ja päättänyt nostaa rahoitustaan.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} ovat erityisen tyytyväisiä kykyysi torjua paikallista muukalaisten tunkeutumista alueillensa ja ovat päättäneet nostaa rahoitustaan.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} ja {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} on tyytymätön kykyysi torjua muukalaisten toimintaa alueellansa ja on päättänyt vähentää rahoitustaan.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} ovat tyytymättömiä kykyysi torjua muukalaisten toimintaa alueillansa ja ovat päättäneet vähentää rahoitustaan.\"\n  STR_KNOTS: \"{0} solmua\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} on tehnyt salaisen sopimuksen tuntemattomien muukalaistahojen kanssa ja vetäytynyt projektista.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} ovat tehneet salaisen sopimuksen tuntemattomien muukalaistahojen kanssa ja vetäytyneet projektista.\"\n  STR_MONTHLY_RATING: \"Kuukausiarvio> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Rahoituksen muutos> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"Rahoituslautakunta ei ole tyytyväinen taloustilanteeseesi. Sinun täytyy vähentää velkoja alle $1miljoonan tai projekti lakkautetaan.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"HYPERAALTOLÄHETYKSET TULKITTU\"\n  STR_CRAFT_TYPE: \"ALUKSEN TYYPPI\"\n  STR_RACE: \"LAJI\"\n  STR_MISSION: \"TEHTÄVÄ\"\n  STR_ZONE: \"ALUE\"\n  STR_ALLOCATE_RESEARCH: \"Kohdenna tutkimusta\"\n  STR_ALLOCATE_MANUFACTURE: \"Kohdenna tuotantoa\"\n  STR_NEW_YORK: \"New York\"\n  STR_WASHINGTON: \"Washington\"\n  STR_LOS_ANGELES: \"Los Angeles\"\n  STR_MONTREAL: \"Montreal\"\n  STR_HAVANA: \"Havana\"\n  STR_MEXICO_CITY: \"Mexico City\"\n  STR_CHICAGO: \"Chicago\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_DALLAS: \"Dallas\"\n  STR_BRASILIA: \"Brasilia\"\n  STR_BOGOTA: \"Bogotá\"\n  STR_BUENOS_AIRES: \"Buenos Aires\"\n  STR_SANTIAGO: \"Santiago\"\n  STR_RIO_DE_JANEIRO: \"Rio De Janeiro\"\n  STR_LIMA: \"Lima\"\n  STR_CARACAS: \"Caracas\"\n  STR_LONDON: \"Lontoo\"\n  STR_PARIS: \"Pariisi\"\n  STR_BERLIN: \"Berliini\"\n  STR_MOSCOW: \"Moskova\"\n  STR_ROME: \"Rooma\"\n  STR_MADRID: \"Madrid\"\n  STR_BUDAPEST: \"Budapest\"\n  STR_LAGOS: \"Lagos\"\n  STR_CAIRO: \"Kairo\"\n  STR_CASABLANCA: \"Casablanca\"\n  STR_PRETORIA: \"Pretoria\"\n  STR_NAIROBI: \"Nairobi\"\n  STR_CAPE_TOWN: \"Kapkaupunki\"\n  STR_KINSHASA: \"Kinshasa\"\n  STR_ANKARA: \"Ankara\"\n  STR_DELHI: \"Delhi\"\n  STR_KARACHI: \"Karachi\"\n  STR_BAGHDAD: \"Bagdad\"\n  STR_TEHRAN: \"Tehran\"\n  STR_BOMBAY: \"Bombay\"\n  STR_CALCUTTA: \"Kalkutta\"\n  STR_TOKYO: \"Tokio\"\n  STR_BEIJING: \"Beking\"\n  STR_BANGKOK: \"Bangkok\"\n  STR_MANILA: \"Manila\"\n  STR_SEOUL: \"Seoul\"\n  STR_SINGAPORE: \"Singapore\"\n  STR_JAKARTA: \"Jakarta\"\n  STR_SHANGHAI: \"Shanghai\"\n  STR_HONG_KONG: \"Hong Kong\"\n  STR_NOVOSIBIRSK: \"Novosibirsk\"\n  STR_CANBERRA: \"Canberra\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_MELBOURNE: \"Melbourne\"\n  STR_PERTH: \"Perth\"\n  STR_PSI_TRAINING: \"Psi-koulutus\"\n  STR_PSIONIC_TRAINING: \"PSIONINEN KOULUTUS\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Vapaa psi-laboratoriotila> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"Psi-{NEWLINE}voima\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"Psi-taito{NEWLINE}/Kehitys\"\n  STR_PSI_AMP: \"Psi-vahvistin\"\n  STR_IN_TRAINING: \"Koulutuk-{NEWLINE}sessa?\"\n  STR_TARGETTED_BY: \"KOHTEENA ALUKSELLA:\"\n  STR_WEAPONS_CREW_HWPS: \"ASEET/{NEWLINE}MIEH./MTKt\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"-aluksella on polttoaine vähissä,{NEWLINE}joten se palaa tukikohtaan\"\n  STR_SOLDIER_LIST: \"Sotilaat\"\n  STR_RANK_: \"SOTILASARVO> {ALT}{0}\"\n  STR_MISSIONS: \"TEHTÄVÄT> {ALT}{0}\"\n  STR_KILLS: \"TAPOT> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"TOIPILASAIKA> {ALT}{0}\"\n  STR_TIME_UNITS: \"AIKAYKSIKÖT\"\n  STR_STAMINA: \"KESTÄVYYS\"\n  STR_HEALTH: \"TERVEYS\"\n  STR_BRAVERY: \"ROHKEUS\"\n  STR_REACTIONS: \"REAKTIOKYKY\"\n  STR_FIRING_ACCURACY: \"AMPUMATARKKUUS\"\n  STR_THROWING_ACCURACY: \"HEITTOTARKKUUS\"\n  STR_STRENGTH: \"VOIMA\"\n  STR_PSIONIC_STRENGTH: \"PSIONINEN VOIMA\"\n  STR_PSIONIC_SKILL: \"PSIONINEN TAITO\"\n  STR_NEW_RANK: \"UUSI SOTILASARVO\"\n  STR_PROMOTIONS: \"Ylennykset\"\n  STR_SOLDIERS_UC: \"SOTILAAT\"\n  STR_TANK_CANNON_UFOPEDIA: \"Miehittämättömillä taistelukoneilla voidaan täydentää X-Com-ryhmiä. Suuren tulivoiman ja vahvan panssarin yhdistelmä tekee näistä koneista arvokkaita avoimessa maastossa taisteltaessa. Varmista, että sinulla on riittävästi ammuksia tämän MTK:n tykkiä varten. MTK:iden aseet ladataan automaattisesti, kun määräät ne osaksi ryhmää.\"\n  STR_TANK_ROCKET_LAUNCHER_UFOPEDIA: \"Tämä miehitttämätön taistelukone (MTK) on aseistettu voimakkailla ohjuksilla. Taistelutilanteessa sen käyttö on turmiollista vihollisen kannalta. Varmista, että varastoissasi on riittävästi MTK ohjuksia.\"\n  STR_TANK_LASER_CANNON_UFOPEDIA: \"Laseraseet ovat hyödyllinen lisä MTK:iden arsenaaliin. Näin mahdollistetaan suuri tulivoima ilman ammusten määrän rajallisuutta.\"\n  STR_HOVERTANK_PLASMA_UFOPEDIA: \"Muukalaisten teknologiaa soveltamalla MTK-teknologian käyttöikää on lisätty. Lentämisen tuoma lisäliikuntakyky ja plasma-aseen suuri tulivoima on tappava yhdistelmä.\"\n  STR_HOVERTANK_LAUNCHER_UFOPEDIA: \"Tässä lentävässä MTK:ssa on fuusiopallolaukaisin, joka kykenee suunnattoman suureen hävitykseen. Ole erityisen varovainen käyttäessäsi sitä. Fuusiopallot, joita teknikkojemme täytyy valmistaa tätä MTK:ta varten, ovat älykkäästi ohjattavia ohjuksia. Kun laukaiset fuusiopallon, voit valita osoittimella ensin useita etappipisteitä, minkä jälkeen voit laukaista ohjuksen napsauttamalla laukaisukuvaketta.\"\n  STR_HEAVY_PLASMA_CLIP_UFOPEDIA: \"Tämä kompakti laite toimii plasmatykin ammuslippaana. Se sisältää pienen määrän eleriumia.\"\n  STR_PLASMA_RIFLE_CLIP_UFOPEDIA: \"Tämä pieni laite toimii plasmakiväärin - keskivoimakkaan muukalaisten aseen - voimanlähteenä. Se sisältää pienen määrän eleriumia.\"\n  STR_PLASMA_PISTOL_CLIP_UFOPEDIA: \"Tämä on pienen muukalaisten plasmapistoolin voimanlähde. Se sisältää eleriumia, joka on kaiken muukalaisten energiantuotannon lähde.\"\n  STR_STUN_BOMB_UFOPEDIA: \"Tainnutuspommia käytetään elävien ihmisten kaappaamiseen, mutta se on käyttökelpoinen myös useimpien muukalaisten tainnuttamisessa. Sen ampumiseen käytetään pientä laukaisijaa.\"\n  STR_ALIEN_RESEARCH_UFOPEDIA: \"Muukalaiset keräävät tutkimusretkillään perustietoa Maasta ja sen asukkaista. Useimmiten tehtävään käytetään pieniä aluksia, jotka joskus laskeutuvat harvaanasutuille alueille. Tämäntyyppinen muukalaistoiminta uhkaa vähiten X-Comin toimintaa, koska se ei juuri aiheuta huolta hallituksien tai suuren yleisön keskuudessa.\"\n  STR_ALIEN_HARVEST_UFOPEDIA: \"Muukalaisilla on paljon erilaisia käyttötarkoituksia Maan eliöstölle. Eläimiä kaapataan salaa ja palautetaan sen jälkeen, kun niistä on poistettu elimiä. Karjansilpomistapauksia raportoidaan usein ufohavaintojen yhteydessä. Tämäntyyppinen muukalaisten toiminta aiheuttaa suurta huolta maiden hallituksissa sekä ahdistusta siviiliväestön keskuudessa. Yleensä muukalaiset suorittavat sadonkorjuutehtäviään viljellyillä alueilla maaseudulla. \\\"Muukalaisten sadonkorjuu\\\"-teorian mukaan muukalaiset olisivat aikoinaan \\\"kylväneet\\\" tämän planeetan omalla eläin- ja kasvikunnallaan ja olisivat nyt palanneet niittämään satoaan.\"\n  STR_ALIEN_ABDUCTION_UFOPEDIA: \"Muukalaisten kaappaukset ovat salakavalinta muukalaisten toiminnoista. Kaappauksista on useita kertomuksia, huolimatta muukalaisten yrityksistä tyhjentää uhriensa muistikuvat tapahtuneesta. Kaapatut kertovat joutuneensa erilaisiin nöyryyttäviin fyysisiin tutkimuksiin ja kokeisiin. Heitä on käytetty mm. muukalaisten sikiöiden kasvualustana sekä erilaisiin outoihin geneettisiin kokeisiin. Näiden kokeiden motiivina vaikuttaisi olevan muukalaisten tarve manipuloida omaa geneettistä perimäänsä. Muukalaisten kaappaukset aiheuttavat paljon levottomuutta, ja niitä tehdään kaupunkialueilla sekä muilla asutetuilla alueilla.\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"Maan hallituksiin saattaa soluttautua muukalaisten agentteja, jotka näyttävät ulkoisesti ihmisiltä. Tämä saattaa johtaa kohtaamisiin korkean tason virkamiesten ja muukalaisten välillä. Tällaisen muukalaistoiminnan huipentumana tyypillisesti nähdään valtavaa ufojen aktiivisuutta suurimpien kaupunkien lähistöllä. Muukalaiset yrittävät solmia sopimuksen Maan hallituksen kanssa tarjoamalla heidän ylivertaista teknologiaansa. Vastapalveluksena ko. hallitus sallii muukalaisten jatkaa toimintaansa alueellaan rajoituksetta. Tämäntyyppinen muukalaistoiminta on kaikista vaarallisinta X-Com-projektin kannalta. Jos jokin hallitus solmii kuvatunlaisen sopimuksen muukalaisten kanssa, sen rahoitus lakkaa.\"\n  STR_ALIEN_BASE_UFOPEDIA: \"Muukalaiset rakentavat salaisia maanalaisia tukikohtia syrjäisiin paikkoihin. Aluksi muukalaiset yleensä suorittavat tiedustelulentoja mielestään sopivalla alueella, minkä jälkeen tukikohdan rakentamisen yhteydessä havaitaan intensiivistä ufojen aktiivisuutta alueella. Näissä tukikohdissa on kokeellisia laboratorioita ihmiskokeita varten sekä varusteita tulevaa alueellista toimintaa varten. Tukikohtien läsnäolo saa aikaan runsaasti ilmoituksia muukalaisten aktiivisuudesta alueella ilman ufojen läsnäoloa. Jotta voimme löytää muukalaisten tukikohdan, tulee meidän lähettää alus partioimaan epäillylle alueelle. Aluetta on partioitava muutaman tunnin ajan, jotta aluksella olisi minkäänlaista käytännön mahdollisuutta havaita mahdollista tukikohtaa.\"\n  STR_ALIEN_TERROR_UFOPEDIA: \"Kun muukalaiset terrorisoivat kaupunkia, ne käyttävät tehtävään erityisiä terrorijoukkoja, joilla on tuhoisia voimia. Siviilit joutuvat suoran fyysisen uhan kohteeksi, ja paikallishallinnot joutuvat evakuoimaan kokonaisia asuinalueita. Tämän toiminnan pääasiallinen tarkoitus on aiheuttaa massahysteriaa ja paniikkia, jotta hallitukset painostaisivat X-Com-projektia.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"Jos X-Com-hävittäjät onnistuvat erityisen hyvin ampumaan alas ufoja, saattavat muukalaiset ryhtyä vastatoimiin. Tämä saattaa johtaa suoraan hyökkäykseen X-Com-tukikohtaan. Muukalaisten pitää kuitenkin ensin löytää tukikohta hyökätäkseen siihen, ja jos ufot onnistutaan pitämään loitolla, pitäisi suoran hyökkäyksen riskin olla pieni.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"Kun muukalaiset ovat rakentaneet tukikohdan, sitä täytyy ylläpitää säännöllisesti erityisillä huoltoaluksilla. Jos tällainen huoltoalus havaitaan laskeutuneena, on varmaa, että lähistöllä on muukalaisten tukikohta.\"\n  STR_SMALL_SCOUT_UFOPEDIA: \"Tätä pikkuriikkistä alusta käytetään yleensä tiedusteluun ja tutkimukseen. Yleensä se edeltää suurempia muukalaisten aluksia muukalaisten tehtävien alussa.\"\n  STR_MEDIUM_SCOUT_UFOPEDIA: \"Tämä on keskikokoinen tiedustelualus joka ei juuri uhkaa maapallon sotilaallisia voimia. Yleensä alus edeltää suurempia aluksia tehtävien aikana.\"\n  STR_LARGE_SCOUT_UFOPEDIA: \"Suurin muukalaisten tiedustelualus on yleiskäyttöinen alus, jota käytetään kaikentyyppisiin tehtäviin.\"\n  STR_HARVESTER_UFOPEDIA: \"Sadonkorjaajassa on luukku sen pohjassa ja se on varustettu nosturilaitteilla, joiden avulla alukseen nostetaan karjaa ja muita eläimiä. Laserveitsien avulla halutut ruumiinosat ja elimet poistetaan ja loppu raadosta heitetään maahan. Aluksesta löytyy lisäksi varastointisäiliöitä poistettuja ruumiinosia varten.\"\n  STR_ABDUCTOR_UFOPEDIA: \"Tämä alus on varustettu tutkimushuoneella, jossa tehdään karmeita kokeita ihmisillä. Uhri on yleensä halvaannutettu telepaattisilla voimilla, mutta pysyy tajuissaan ollessaan tutkimuspöydällä.\"\n  STR_TERROR_SHIP_UFOPEDIA: \"Terrorialuksessa on tilat suurten terroriaseiden ja -olentojen kuljetusta varten. Sitä käytetäänkin näiden terrorivälineiden kuljettamiseen asuttujen alueiden keskelle.\"\n  STR_BATTLESHIP_UFOPEDIA: \"Taistelualus on muukalaisten suurin ja tulivoimaltaan voimakkain alus. Se on yleensä pääasiallinen muukalaisten alus useissa tehtävissä, sillä siihen mahtuu paljon aseistusta sekä miehistön jäseniä.\"\n  STR_SUPPLY_SHIP_UFOPEDIA: \"Huoltoalusta käytetään rakennettaessa uusia tukikohtia sekä ylläpidettäessä vanhoja. Se tuo muukalaisille ruokaa sekä lisääntymisvälineitä.\"\n  STR_DISMANTLE: \"Pura\"\n  STR_FACILITY_IN_USE: \"LAITOS KÄYTÖSSÄ\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"LAITOSTA EI VOI PURKAA!{SMALLLINE}Jokaisesta tukikohdan laitoksesta täytyy olla yhteys laitoshissiin.\"\n  STR_TRANSFER_ITEMS_TO: \"Siirrä tavarat tukikohtaan {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"MUUKALAISTEN VANKILAITOSTA EI OLE KOHTEESSA{SMALLLINE}Elävät muukalaiset tarvitsevat erityisen vankilaitoksen johon voidaan luoda niiden tarvitsemat elinolosuhteet.\"\n  STR_AMOUNT_AT_DESTINATION: \"MÄÄRÄ{NEWLINE}KOHTEESSA\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"Muukalainen kuolee, koska muukalaisten vankilaitosta ei ole\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"EI RIITTÄVIÄ ASUINTILOJA!{SMALLLINE}Kohdetukikohdassa ei ole riittävästi asuintiloja aluksen miehistöä varten.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"EI TARPEEKSI VARASTOTILAA!{SMALLLINE}Määränpäässä ei ole tarpeeksi varastotilaa alukselle määrätylle varustukselle.\"\n  STR_ITEMS_ARRIVING: \"Kuljetus saapui\"\n  STR_DESTINATION_UC: \"MÄÄRÄNPÄÄ\"\n  STR_PISTOL: \"Pistooli\"\n  STR_PISTOL_CLIP: \"Pistoolin lipas\"\n  STR_RIFLE: \"Kivääri\"\n  STR_RIFLE_CLIP: \"Kiväärin lipas\"\n  STR_HEAVY_CANNON: \"Käsikanuuna\"\n  STR_HC_AP_AMMO: \"HC-AP-ammukset\"\n  STR_HC_HE_AMMO: \"HC-HE-ammukset\"\n  STR_HC_I_AMMO: \"HC-I-ammukset\"\n  STR_AUTO_CANNON: \"Autokanuuna\"\n  STR_AC_AP_AMMO: \"AC-AP-ammukset\"\n  STR_AC_HE_AMMO: \"AC-HE-ammukset\"\n  STR_AC_I_AMMO: \"AC-I-ammukset\"\n  STR_ROCKET_LAUNCHER: \"Raketinheitin\"\n  STR_SMALL_ROCKET: \"Pieni raketti\"\n  STR_LARGE_ROCKET: \"Suuri raketti\"\n  STR_INCENDIARY_ROCKET: \"Paloraketti\"\n  STR_GRENADE: \"Kranaatti\"\n  STR_SMOKE_GRENADE: \"Savuheite\"\n  STR_PROXIMITY_GRENADE: \"Sensorikranaatti\"\n  STR_HIGH_EXPLOSIVE: \"Räjähde\"\n  STR_STUN_ROD: \"Lähilamautin\"\n  STR_HEAVY_PLASMA: \"Plasmakäsitykki\"\n  STR_HEAVY_PLASMA_CLIP: \"Plasmakäsitykin lipas\"\n  STR_PLASMA_RIFLE: \"Plasmakivääri\"\n  STR_PLASMA_RIFLE_CLIP: \"Plasmakiväärin lipas\"\n  STR_PLASMA_PISTOL: \"Plasmapistooli\"\n  STR_PLASMA_PISTOL_CLIP: \"Plasmapistoolin lipas\"\n  STR_BLASTER_LAUNCHER: \"Tuholaukaisin\"\n  STR_BLASTER_BOMB: \"Suurtuhopommi\"\n  STR_SMALL_LAUNCHER: \"Pieni laukaisin\"\n  STR_STUN_BOMB: \"Tainnutuspommi\"\n  STR_ALIEN_GRENADE: \"Muukalaisten kranaatti\"\n  STR_ELERIUM_115: \"Elerium-115\"\n  STR_MIND_PROBE: \"Mielenluotain\"\n  STR_SECTOID_CORPSE: \"Harmaan ruumis\"\n  STR_SNAKEMAN_CORPSE: \"Käärmemiehen ruumis\"\n  STR_ETHEREAL_CORPSE: \"Eteerin ruumis\"\n  STR_MUTON_CORPSE: \"Mutonin ruumis\"\n  STR_FLOATER_CORPSE: \"Leijujan ruumis\"\n  STR_CELATID_CORPSE: \"Kelatoidin ruumis\"\n  STR_SILACOID_CORPSE: \"Silikoidin ruumis\"\n  STR_CHRYSSALID_CORPSE: \"Munamiehen ruumis\"\n  STR_REAPER_CORPSE: \"Raatelijan ruumis\"\n  STR_SECTOPOD_CORPSE: \"Sektopodin jäännökset\"\n  STR_CYBERDISC_CORPSE: \"Kyberlautasen jäännökset\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"Ei riittävästi ammuksia MTK:n lataamiseksi{SMALLLINE}Kukin MTK vaatii {0} kpl ammustyyppiä {1}.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Varusteita ei ole tarpeeksi täydentämiseen\"\n  STR_MARS_CYDONIA_LANDING: \"Mars: Kydonialle laskeutuminen\"\n  STR_MARS_CYDONIA_LANDING_BRIEFING: \"Sinun Avenger -aluksesi on laskeutunut Kydonian alueelle Marsin pinnalla. Tietojemme mukaan yhdessä alueen pyramideissa on vihreä sisäänkäynti muukalaisten maanalaiseen tukikohtaan. Kun olet koonnut kaikki sotilaasi vihreälle sisäänkäyntialueelle, napsauta \\\"Keskeytä tehtävä\\\" -painiketta jatkaaksesi eteenpäin tehtävässä.\"\n  STR_MARS_THE_FINAL_ASSAULT: \"Mars: Viimeinen rynnäkkö\"\n  STR_MARS_THE_FINAL_ASSAULT_BRIEFING: \"Pyramidin hissi vie taistelusta väsyneet sotilaasi syvälle planeetan pinnan alle. Lopulta joukko saapuu suuren käytävä- ja huoneistokompleksin sydämeen. Muukalaisten aivot sijaitsevat piilossa jossakin labyrintin uumenissa. Se on tuhottava, jotta Maa voisi pelastua muukalaisten orjuudelta.{NEWLINE}{NEWLINE}Onnea taisteluun!\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Sinun täytyy tutkia ensin:{NEWLINE}{0}{NEWLINE}ennen kuin voit rakentaa{NEWLINE}{1}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"Muukalaiset ovat tuhonneet puolustamattoman tukikohdan: {0}\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"X-Comin agentit ovat paikallistaneet muukalaisten tukikohdan alueella {0}.\"\n  STR_STANDOFF: \"SEURAA\"\n  STR_CAUTIOUS_ATTACK: \"VAROVAINEN HYÖKKÄYS\"\n  STR_STANDARD_ATTACK: \"TAVALLINEN HYÖKKÄYS\"\n  STR_AGGRESSIVE_ATTACK: \"AGGRESSIIVINEN HYÖKKÄYS\"\n  STR_DISENGAGING: \"PERÄÄNNYTÄÄN\"\n  STR_UFO_HIT: \"UFOON OSUI!\"\n  STR_UFO_CRASH_LANDS: \"UFO SYÖKSYY MAAHAN!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Pienennys vain seuratessa\"\n  STR_UFO_RETURN_FIRE: \"UFO VASTAA TULEEN!\"\n  STR_INTERCEPTOR_DAMAGED: \">>> HÄVITTÄJÄ VAURIOITUI <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> HÄVITTÄJÄ TUHOUTUI <<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"UFO KARKAA HÄVITTÄJÄLTÄ!\"\n  STR_ALIENS_TERRORISE: \"MUUKALAISTERRORI-ISKU! KOHDE:\"\n  STR_LONG_RANGE_DETECTION: \"Pitkän matkan tutkat\"\n  STR_STORES_UC: \"VARASTOT\"\n  STR_DIFFICULTY_LEVEL: \"Vaikeusaste\"\n  STR_INTERCEPT: \"ILMAVOIMAT\"\n  STR_BASES: \"TUKIKOHDAT\"\n  STR_GRAPHS: \"KUVAAJAT\"\n  STR_UFOPAEDIA_UC: \"UFOPEDIA\"\n  STR_OPTIONS_UC: \"ASETUKSET\"\n  STR_FUNDING_UC: \"RAHOITUS\"\n  STR_5_SECONDS: \"5 s\"\n  STR_1_MINUTE: \"1 min\"\n  STR_5_MINUTES: \"5 min\"\n  STR_30_MINUTES: \"30 min\"\n  STR_1_HOUR: \"1 tunti\"\n  STR_1_DAY: \"1 päivä\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"X-Comin suoritustaulukko\"\n  STR_ENTER_NAME: \"Nimi\"\n  STR_PERFORMANCE_RATING: \"Suorituksen arvosana\"\n  STR_VICTORY_DATE: \"Voiton päivänmäärä\"\n  STR_ELECTRO_FLARE: \"Heittovalo\"\n  STR_ELECTRO_FLARE_UFOPEDIA: \"Tämä kompakti kirkas valonlähde on suunniteltu siten, että se syttyy automattisesti heitettäessä. Se on erittäin hyödyllinen vihollisten paljastamiseksi pimeissä olosuhteissa.\"\n  STR_MONTHLY_COSTS: \"Menot/kk\"\n  STR_CRAFT_RENTAL: \"Alusten vuokra\"\n  STR_SALARIES: \"Palkat\"\n  STR_BASE_MAINTENANCE: \"Tukikohdan ylläpito\"\n  STR_COST_PER_UNIT: \"Hinta / yks.\"\n  STR_QUANTITY: \"Määrä\"\n  STR_TOTAL: \"Yhteensä\"\n  STR_IN_PSIONIC_TRAINING: \"Psionisessa koulutuksessa\"\n  STR_BLASTER_BOMB_UFOPEDIA: \"Tämä laite on eräänlainen ohjus, jossa on älykäs ohjausjärjestelmä ja erittäin voimakas räjähdepanos. Se laukaistaan tuholaukaisimen avulla.\"\n  STR_FRONT_ARMOR: \"Etupanssari\"\n  STR_LEFT_ARMOR: \"Vasen panssari\"\n  STR_RIGHT_ARMOR: \"Oikea panssari\"\n  STR_REAR_ARMOR: \"Takapanssari\"\n  STR_UNDER_ARMOR: \"Alapanssari\"\n  STR_ROUNDS: \"Ammuksia\"\n  STR_UNIT: \"YKSIKKÖ> {0}\"\n  STR_ENERGY: \"ENERGIA\"\n  STR_MORALE: \"TAISTELUTAHTO\"\n  STR_ARMOR_: \"PANSSARI> {0}\"\n  STR_FRONT_ARMOR_UC: \"ETUPANSSARI\"\n  STR_LEFT_ARMOR_UC: \"VASEN PANSSARI\"\n  STR_RIGHT_ARMOR_UC: \"OIKEA PANSSARI\"\n  STR_REAR_ARMOR_UC: \"TAKAPANSSARI\"\n  STR_SKILLS: \"TAIDOT> {0}\"\n  STR_LEVEL: \"TASO> {0}\"\n  STR_HEAD: \"PÄÄ\"\n  STR_TORSO: \"VARTALO\"\n  STR_RIGHT_ARM: \"O KÄSI\"\n  STR_LEFT_ARM: \"V KÄSI\"\n  STR_RIGHT_LEG: \"O JALKA\"\n  STR_LEFT_LEG: \"V JALKA\"\n  STR_PAIN_KILLER: \"KIPULÄÄKE\"\n  STR_STIMULANT: \"PIRISTE\"\n  STR_HEAL: \"PARANNA\"\n  STR_TIME_UNITS_SHORT: \"AY>{ALT}{0}\"\n  STR_WEIGHT: \"Paino>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"Reakt>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"P.Taito>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"P.Voima>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Muukalaisten laite\"\n  STR_AMMO_ROUNDS_LEFT: \"AMMUS:{NEWLINE}{NEWLINE}JÄLJELLÄ={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Kipulääke>{ALT}{0}{ALT}{NEWLINE}Piriste>{ALT}{1}{ALT}{NEWLINE}Paranna>{ALT}{2}\"\n  STR_THROW: \"Heitä\"\n  STR_AUTO_SHOT: \"Sarjatuli\"\n  STR_SNAP_SHOT: \"Kertatuli\"\n  STR_AIMED_SHOT: \"Tähdätty\"\n  STR_STUN: \"Tainnuta\"\n  STR_PRIME_GRENADE: \"Ajasta kranaatti\"\n  STR_USE_SCANNER: \"Käytä liikkeentunnistinta\"\n  STR_USE_MEDI_KIT: \"Käytä ensiapulaitetta\"\n  STR_LAUNCH_MISSILE: \"Laukaise ohjus\"\n  STR_ACCURACY_SHORT: \"Tark>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Ei riittävästi aikayksiköitä!\"\n  STR_NOT_ENOUGH_ENERGY: \"Ei tarpeeksi energiaa!\"\n  STR_NO_ROUNDS_LEFT: \"Ei ammuksia jäljellä!\"\n  STR_NO_AMMUNITION_LOADED: \"Ase ei ole ladattu!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Väärä ammus tätä asetta varten!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"Ase on jo ladattu!\"\n  STR_NO_LINE_OF_FIRE: \"Ei tulilinjaa!\"\n  STR_GRENADE_IS_ACTIVATED: \"Kranaatti on aktivoitu!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Kranaatti on deaktivoitu!\"\n  STR_THERE_IS_NO_ONE_THERE: \"Siinä kohtaa ei ole ketään!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Muukalaisten laitteita ei voi käyttää ennen tutkimusprojektin valmistumista!\"\n  STR_OUT_OF_RANGE: \"Kantaman ulkopuolella!\"\n  STR_UNABLE_TO_THROW_HERE: \"Tähän ei voi heittää!\"\n  STR_SET_TIMER: \"Aseta ajastin\"\n  STR_HIDDEN_MOVEMENT: \"VIHOLLISEN VUORO\"\n  STR_TURN: \"VUORO> {0}\"\n  STR_SIDE: \"PUOLI> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Paina näppäintä jatkaaksesi\"\n  STR_MIND_CONTROL: \"Mielenhallinta\"\n  STR_PANIC_UNIT: \"Paniikkikohtaus\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Kohteen taistelutahtoa vähennetty\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Mielenhallinta onnistui\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}on mennyt sekaisin\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}on mennyt sekaisin\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}on joutunut paniikkiin\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}on joutunut paniikkiin\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Muukalaiset\"\n  STR_RIGHT_HAND: \"OIKEA KÄSI\"\n  STR_LEFT_HAND: \"VASEN KÄSI\"\n  STR_RIGHT_SHOULDER: \"OIKEA OLKAPÄÄ\"\n  STR_LEFT_SHOULDER: \"VASEN OLKAPÄÄ\"\n  STR_BACK_PACK: \"REPPU\"\n  STR_BELT: \"VYÖ\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}on muukalaisten hallinnassa\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}on muukalaisten hallinnassa\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}on menettänyt tajuntansa\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}on menettänyt tajuntansa\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}kuoli vakavan haavan vuoksi\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}kuoli vakavan haavan vuoksi\"\n  STR_USE_MIND_PROBE: \"Käytä mielenluotainta\"\n  STR_FATAL_WOUNDS: \"VAKAVAT HAAVAT\"\n  STR_UNDER_ARMOR_UC: \"ALAPANSSARI\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Aikayksiköitä varattu kertatulta varten\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Aikayksiköitä varattu sarjatulta varten\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Aikayksiköitä varattu tähdättyä laukausta varten\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Aikayksiköitä varattu polvistumista varten\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"AY:t varattu polvistumista ja ampumista varten\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} yksikkö X-Com-aluksessa\"\n    other: \"{N} yksikköä X-Com-aluksessa\"\n  STR_UNITS_OUTSIDE:\n    one: \"{N} yksikkö jätetty ulkopuolelle\"\n    other: \"{N} yksikköä jätetty ulkopuolelle\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} yksikkö sisäänkäynnillä\"\n    other: \"{N} yksikköä sisäänkäynnillä\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} yksikkö kohdepoistumisalueella\"\n    other: \"{N} yksikköä kohdepoistumisalueella\"\n  STR_ABORT_MISSION_QUESTION: \"Keskeytetäänkö tehtävä?\"\n  STR_CORPSE: \"Ruumis\"\n  STR_UNLOAD_CRAFT: \"Pura varustelasti\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}on kuollut\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}on kuollut\"\n  STR_HIT_MELEE: \"Osuma\"\n  STR_GROUND: \"MAA\"\n  STR_LIVING_QUARTERS_PLURAL: \"Asuintilat\"\n  STR_LIST_ITEM: \"ASIA\"\n  STR_PERSONAL_ARMOR_UFOPEDIA: \"Käyttämällä hiljattain löydettyjä muukalaisten metalliseoksia, voimme rakentaa henkilökohtaisen panssarin joka antaa sotilaillemme edes pienen mahdollisuuden selvitä joutuessaan muukalaisten tulituksen kohteeksi.\"\n  STR_POWER_SUIT_UFOPEDIA: \"Tämä uusi, voimakas henkilökohtainen panssari on varustettu eleriumia käyttävällä voimanlähteellä. Se parantaa sotilaan nopeutta ja voimaa, sekä antaa tähän mennessä parhaan suojan sotilaillemme.\"\n  STR_FLYING_SUIT_UFOPEDIA: \"Tämä on voimapanssarin paranneltu versio, johon on liitetty antipainovoimanavigointiteknologiaa. Pukua käyttävä sotilas pystyy liikkumaan vapaasti taistelukentällä.\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"Kaikki muukalaiset kuolivat pakkolaskussa,{NEWLINE}Pakkolaskun saalista kerätään\"\n  STR_RESET: \"Nollaa\"\n  STR_MEMORIAL: \"Muistomerkki\"\n  STR_DATE_UC: \"PVM\"\n  STR_SOLDIERS_RECRUITED_UC: \"SOTILAITA VÄRVÄTTY>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"SOTILAITA MENETETTY>{ALT}{0}\"\n  MAP_CULTA: \"Maatila\"\n  MAP_FOREST: \"Metsä\"\n  MAP_JUNGLE: \"Viidakko\"\n  MAP_MOUNT: \"Vuori\"\n  MAP_DESERT: \"Aavikko\"\n  MAP_POLAR: \"Napa\"\n  MAP_URBAN: \"Kaupunki\"\n  MAP_UBASE: \"Muukalaisten tukikohta\"\n  MAP_XBASE: \"X-Com-tukikohta\"\n  MAP_MARS: \"Mars\"\n  STR_MIXED: \"Sekalainen\"\n  STR_REMOVE_SELECTED: \"Poista valitut\"\n  STR_LIVE_ALIENS: \"Eläviä{NEWLINE}yksilöjä\"\n  STR_DEAD_ALIENS: \"Hylättäviä{NEWLINE}yksilöjä\"\n  STR_UNDER_INTERROGATION: \"Tutkit-{NEWLINE}tavana\"\n  STR_CONTAINMENT_EXCEEDED: \"MUUKALAISTEN VANKILAPAIKAT TÄYNNÄ{SMALLLINE}Ei riittävästi vankilatilaa tukikohdassa {0}. Sinun täytyy poistaa turhia muukalaisia vankilasta (toisin sanoen tappaa ne).\"\n  STR_MANAGE_CONTAINMENT: \"Hallitse muukalaisten vankilaitosta\"\n  STR_STORAGE_EXCEEDED: \"VARASTOTILA YLITETTY!{SMALLLINE}Riittämättömästi varastotilaa tukikohdassa {0}. Liika tavara on myytävä pois.\"\n  STR_GO_TO_BASE: \"Mene tukikohtaan\"\n  STR_MELEE_ACCURACY: \"LÄHITAISTELUTARKKUUS\"\n  STR_SELL_PRODUCTION: \"MYY\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Molempien käsien täytyy olla vapaina!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Ei tarpeeksi varusteita mallin kopioimiseksi!\"\n  STR_UNLOAD_WEAPON: \"Poista ammukset\"\n  STR_ALL_ITEMS: \"Kaikki esineet\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"EI ENEMPÄÄ VARUSTEITA SALLITTU ALUKSEEN!{SMALLLINE}Alukseen sallitaan korkeintaan {N} varuste.\"\n    other: \"EI ENEMPÄÄ VARUSTEITA SALLITTU ALUKSEEN!{SMALLLINE}Alukseen sallitaan korkeintaan {N} varustetta.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}KOMENTOKESKUS TUHOTTU{NEWLINE}Palaa sisäänkäynnille ja keskeytä tehtävä.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"X-Com-laitoksia ei voi rakentaa veden alle\"\n  STR_LEVEL_SHORT: \"{0}\"\n  STR_PERSONNEL: \"Henkilökunta\"\n  STR_CRAFT_ARMAMENT: \"Alukset & aseistus\"\n  STR_COMPONENTS: \"Komponentit\"\n  STR_SOLDIERS_RECRUITED: \"Sotilaita värvätty\"\n  STR_SOLDIERS_LOST: \"Sotilaita menetetty\"\n  STR_TOTAL_UFOS: \"Ufoja havaittu\"\n  STR_TOTAL_ALIEN_BASES: \"Muukalaistukikohtia löydetty\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"PSV\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"PST\"\n  FEMALE_CIVILIAN: \"Siviili, nainen\"\n  MALE_CIVILIAN: \"Siviili, mies\"\n  CYBERDISC_WEAPON: \"Kyberlautasen ase\"\n  REAPER_WEAPON: \"Raatelijan ase\"\n  CHRYSSALID_WEAPON: \"Munamiehen ase\"\n  CELATID_WEAPON: \"Kelatoidin ase\"\n  SILACOID_WEAPON: \"Silikoidin ase\"\n  SECTOPOD_WEAPON: \"Sektopodin ase\"\n  ZOMBIE_WEAPON: \"Zombin ase\"\n  ALIEN_PSI_WEAPON: \"Muukalaisten psioninen ase\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/fr-CA.yml",
    "content": "fr-CA:\n  STR_AVENGER_UFOPEDIA: \"VAISSEAU DE TRANSPORT ET DE COMBAT. L'ULTIME RÉPLIQUE DE LA TECHNOLOGIE ALIEN.\"\n  STR_INTERCEPTOR_UFOPEDIA: \"VAISSEAU DE COMBAT AÉRIEN AVEC MOTEURS À DÉTONATION À IMPULSION DOUBLE ET SYSTÈMES ÉLECTRONIQUES SPÉCIALEMENT BLINDÉS. LA PLUS SOPHISTIQUÉE DES TECHNOLOGIES TERRESTRES.\"\n  STR_LIGHTNING_UFOPEDIA: \"VAISSEAU DE TRANSPORT ET DE COMBAT. UNE RÉPLIQUE GROSSIÈRE MAIS EFFICACE DES SYSTÈMES DE PROPULSION ALIEN.\"\n  STR_SKYRANGER_UFOPEDIA: \"VAISSEAU TRANSPORTEUR DE TROUPES. LE PLUS RAPIDE DE SA CATÉGORIE, AVEC CAPACITÉ DE DÉCOLLAGE ET D'ATTERRISSAGE À LA VERTICALE (C.D.A.V).\"\n  STR_FIRESTORM_UFOPEDIA: \"VAISSEAU DE COMBAT. CE CHASSEUR MONOPLACE EST LA RÉPLIQUE DE LA SOUCOUPE VOLANTE ALIEN CLASSIQUE, AVEC UNITÉ CENTRALE DE PROPULSION.\"\n  STR_STINGRAY_UFOPEDIA: \"MISSILE AIR-AIR AVANCÉ AVEC DES SYSTÈMES ÉLECTRONIQUES SPÉCIALEMENT BLINDÉS.\"\n  STR_AVALANCHE_UFOPEDIA: \"MISSILE AIR-AIR À OGIVE NUCLÉAIRE, MAIS D'UN POIDS EXTRÊMEMENT ÉLEVÉ.\"\n  STR_CANNON_UFOPEDIA: \"CANON TRÈS PUISSANT QUI TIRE DES BALLES PERCE-ARMURE CAPABLES DE PÉNÉTRER 40 CM D'ACIER.\"\n  STR_FUSION_BALL_UFOPEDIA: \"CETTE ARME TIRE UN MISSILE EN FORME DE BOULE, PROPULSÉ PAR RÉACTION ANTIMATIÈRE. LA BOULE DÉTRUIT LA CIBLE AVEC UNE IMPLOSION D'ONDES GRAVITATIONNELLES.\"\n  STR_LASER_CANNON_UFOPEDIA: \"CE RAYON LASER CONVENTIONNEL EST ALIMENTÉ PAR UNE CHAMBRE À RÉACTION ANTIMATIÈRE.\"\n  STR_PLASMA_BEAM_UFOPEDIA: \"LE RAYON GRAVITATIONNEL PRODUIT UNE IMPLOSION DE CHAMP GRAVITATIONNEL CANALISÉE.\"\n  STR_SECTOID_UFOPEDIA: \"La hiérarchie Sectoïde va des soldats aux leaders ayant d'importantes compétences psioniques. Ces pouvoirs psioniques peuvent être utilisés pour démoraliser les soldats durant le combat, ou même pour prendre possession de leur esprit. Ils ont tendance à s'adonner aux enlèvements d'humains et à la mutilation du bétail. L'enlèvement permet l'extraction de codes génétiques pour le croisement de races et le développement de clones afin d'infiltrer la société humaine. Cette race semble vouloir développer des hybrides génétiques supérieurs pour augmenter l'efficacité de leur société-ruche.\"\n  STR_SECTOID_AUTOPSY: \"Autopsie de Sectoïde\"\n  STR_SECTOID_AUTOPSY_UFOPEDIA: \"L'autopsie montre des organes digestifs atrophiés et une structure simple. Le cerveau et les yeux sont très bien développés. La structure suggère une modification génétique ou une mutation. La petite bouche et le nez semblent n'avoir que peu de fonctions. Les doigts palmés, et les pieds plats suggèrent des origines aquatiques. Il n'y a pas d'organes reproducteurs, et aucun indice sur la façon dont cette espèce se reproduit. C'est certainement une espèce créée génétiquement.\"\n  STR_SNAKEMAN_UFOPEDIA: \"Cette race s'est développée dans un environnement extrêmement hostile. Ils sont très forts et peuvent résister à d'extrêmes variations de température. Leur mobilité est basée sur un 'pied' géant de la forme d'un serpent qui protège tous les organes vitaux. Leurs objectifs semblent être purement et simplement ceux de prédateurs et ils semblent obéir à une autre intelligence qui dicte leurs incursions de style militaire sur la Terre.\"\n  STR_SNAKEMAN_AUTOPSY: \"Autopsie d'Homme-Serpent\"\n  STR_SNAKEMAN_AUTOPSY_UFOPEDIA: \"La peau est extrêmement dure et résistante à la chaleur. Le système cardio-vasculaire fait partie du système musculaire qui utilise le principe hydraulique pour créer un mouvement. Le seul vrai muscle est le 'cœur'. Le système de reproduction semble très efficace. La reproduction est asexuée, et chaque Homme-Serpent porte jusqu'à cinquante œufs à la fois dans son corps. Si cette espèce n'était pas combattue, elle représenterait une grave menace pour la vie sur la Terre.\"\n  STR_ETHEREAL_UFOPEDIA: \"Cet être a un terrifiant pouvoir mental permettant la communication télépathique et la capacité télékinétique. Les capacités physiques apparemment faibles de cette créature sont compensées par son pouvoir mental. Nous ne savons pas comment fonctionne ce pouvoir télékinétique, car il semble défier les lois de la physique telles que nous les connaissons. Ces êtres sont extrêmement dangereux dans toute situation de combat où ils s'en remettent à leur pouvoir mental. Ils apparaissent rarement sur Terre car ils semblent compter sur d'autres races pour poursuivre leurs objectifs.\"\n  STR_ETHEREAL_AUTOPSY: \"Autopsie d'Ethereal\"\n  STR_ETHEREAL_AUTOPSY_UFOPEDIA: \"Cet être est physiquement déficient et semble incapable de se maintenir en vie. Ses muscles sont sévèrement atrophiés et les organes internes semblent sous-développés. Les organes sensoriels, y compris les yeux, semblent ne pas fonctionner du tout. Le cerveau, cependant, est bien développé et utilise une grande quantité du sang du corps. Comment cette créature peut continuer à vivre sans aide extérieure, cela reste un mystère.\"\n  STR_MUTON_UFOPEDIA: \"Cette créature humanoïde est physiquement puissante et intelligente. Elle apprécie tout particulièrement la viande crue, dont elle a besoin pour vivre, comme les carnivores terriens. Elle semble obéir aux ordres télépathiques d'une race appelée les 'Ethereals'. Si ce lien télépathique vient à se rompre, son système mental est détruit et elle meurt. Les implants cybernétiques sont utilisés pour renforcer sa performance au combat. Elle est de toute évidence au service d'une intelligence supérieure.\"\n  STR_MUTON_AUTOPSY: \"Autopsie de Muton\"\n  STR_MUTON_AUTOPSY_UFOPEDIA: \"La 'peau' de cette créature semble être une armure de protection organique greffée sur le corps. Il y a de nombreux implants cybernétiques utilisés pour renforcer le système cardio-vasculaire et les sens. Les organes de reproduction semblent avoir été enlevés par opération chirurgicale. De toute évidence, ces pauvres créatures sont limitées à une vie de guerre et de conquête. Les munitions permettant de percer les armures ne sont pas très efficaces contre leur peau renforcée.\"\n  STR_CELATID_UFOPEDIA: \"Cette forme de vie a la mystérieuse capacité naturelle de flotter dans les airs. Elle semble détecter les ondes du cerveau humain et se dirige vers une cible humaine même bien cachée. Une fois la cible détectée, le Celatid atterrit et crache des petites gouttes de venin extrêmement corrosif. La créature a la capacité de se multiplier à un rythme affolant. Cette race accompagne la race Muton dans ses déplacements.\"\n  STR_CELATID_AUTOPSY: \"Autopsie de Celatid\"\n  STR_CELATID_AUTOPSY_UFOPEDIA: \"Le cœur contient un petit système biomécanique qui semble être un système de propulsion anti-gravité s'étant développé naturellement. La poche de venin est l'organe le plus grand et il ne semble pas y avoir de structure cérébrale séparée. Il n'y a pas de système digestif ou de reproduction visible. Un petit organe contient des embryons qui peuvent se développer rapidement en un nouvel être.\"\n  STR_SILACOID_UFOPEDIA: \"Cette forme de vie à base de silicone génère une énorme quantité de chaleur. Elle a la force d'écraser des rochers qui peuvent ensuite être ingérés par le cœur chaud. Elle a une intelligence primitive et peut être contrôlée par des implants ou par des êtres télépathiques. Elle travaille avec la race Muton.\"\n  STR_SILACOID_AUTOPSY: \"Autopsie de Silacoïde\"\n  STR_SILACOID_AUTOPSY_UFOPEDIA: \"Le cœur de cette créature est extrêmement chaud et semble être la base d'un système digestif. Son système musculaire unique lui donne une énorme puissance et une très grande vitesse. Sa peau, semblable à du roc, est invulnérable au feu ou aux munitions incendiaires.\"\n  STR_CHRYSSALID_UFOPEDIA: \"Les pinces de cette créature sont une arme puissante en combat rapproché. Le puissant métabolisme et la force de cette créature lui procurent vitesse et dextérité. Au lieu de tuer sa victime, elle l'imprègne d'un œuf et injecte un venin qui la transforme en zombie. Une nouvelle Chrysalide sortira de la victime peu après. Les Chrysalides sont associées à la race des hommes-serpents.\"\n  STR_CHRYSSALID_AUTOPSY: \"Autopsie de Chrysalide\"\n  STR_CHRYSSALID_AUTOPSY_UFOPEDIA: \"L'exosquelette de cette créature est très dur, mais étonnamment vulnérable aux munitions explosives. Le cerveau est bien développé, et le taux de croissance de ses cellules est très rapide. La créature porte une vingtaine d'œufs qu'elle pond dans d'autres organismes. Cette créature est une arme de terreur très efficace.\"\n  STR_FLOATER_UFOPEDIA: \"Les Floaters sont avant tout des soldats et des agents de terreur. Ce sont des prédateurs naturels, génétiquement modifiés et cybernétiquement renforcés pour faire d'exceptionnels guerriers. La partie inférieure de leur corps et la plupart des organes internes sont enlevés par une opération chirurgicale, et un système de support de vie est installé. Cet implant contient une unité antigravitationnelle qui permet à la créature de flotter dans les airs, quoiqu'en vacillant.\"\n  STR_FLOATER_AUTOPSY: \"Autopsie de Floater\"\n  STR_FLOATER_AUTOPSY_UFOPEDIA: \"La créature a été très fortement modifiée par la chirurgie. L'appareil qui semble former le noyau du corps est un système de survie, ayant à la fois les fonctions de cœur, de poumons et de système digestif. Cela permet à la créature de survivre dans des environnements extrêmement hostiles. Le cerveau est plus petit que le nôtre, mais les organes sensoriels sont bien développés.\"\n  STR_REAPER_UFOPEDIA: \"Ce carnivore bipède a des mâchoires puissantes et un appétit vorace. Il a plusieurs implants cérébraux qui sont utilisés pour contrôler son activité. Les instincts primitifs de prédateur de cette créature sont de peu d'utilité si ce n'est pour terroriser et détruire. Les Reapers sont généralement associés aux Floaters.\"\n  STR_REAPER_AUTOPSY: \"Autopsie de Reaper\"\n  STR_REAPER_AUTOPSY_UFOPEDIA: \"Le Reaper possède deux 'cerveaux' et deux 'cœurs' qui lui permettent de fonctionner même lorsqu'il est gravement blessé. Cependant, sa fourrure est hautement inflammable, ce qui le rend vulnérable aux armes incendiaires.\"\n  STR_SECTOPOD_UFOPEDIA: \"Les Sectopodes sont des robots possédant une arme à rayon laser très puissante. Ces bêtes mécaniques sont contrôlées par les Ethereals par lien télépathique. Les Sectopodes représentent l'arme de terreur la plus puissante des forces aliens.\"\n  STR_SECTOPOD_AUTOPSY: \"Autopsie de Sectopode\"\n  STR_SECTOPOD_AUTOPSY_UFOPEDIA: \"Le robot est solidement construit avec une armure puissante capable de résister à la plupart des formes d'attaque, en particulier aux armes à plasma. Cependant, le système de détection semble particulièrement vulnérable aux armes laser.\"\n  STR_CYBERDISC_UFOPEDIA: \"Cette soucoupe volante miniature est une arme de terreur automatique munie d'un puissant rayon à plasma. La propulsion antigravitationnelle lui donne un avantage certain en terrain difficile. Sa principale fonction est de semer la destruction et la terreur au service de la race Sectoïde.\"\n  STR_CYBERDISC_AUTOPSY: \"Autopsie de Cyberdisque\"\n  STR_CYBERDISC_AUTOPSY_UFOPEDIA: \"Le Cyberdisque est bien protégé et résiste particulièrement bien aux munitions explosives. Le système antigravitationnel principal est trop endommagé pour que l'on puisse comprendre son fonctionnement.\"\n  STR_UFO_POWER_SOURCE_UFOPEDIA: \"La source d'énergie du vaisseau alien est un réacteur antimatière qui utilise de l'élérium (élément 115) pour générer des ondes puissantes de gravité ainsi que d'autres formes d'énergie. La conversion de la matière en énergie est, chose incroyable, efficace à 99 %, et de petites quantités d'élérium peuvent donc produire une quantité énorme d'énergie. Cette unité peut être facilement reproduite avec les alliages aliens.\"\n  STR_UFO_NAVIGATION_UFOPEDIA: \"Le vaisseau alien utilise des ordinateurs sophistiqués pour naviguer sur la Terre et dans l'espace. Le système est basé sur des processeurs optiques installés en réseaux. L'interface de contrôle est relativement simple : le navigateur contrôle la direction des ondes de gravité générées par la source d'énergie pour déplacer le vaisseau dans n'importe quelle direction. Ce système peut facilement être utilisé par les humains, et peut être reproduit en utilisant les alliages aliens et d'autres composants.\"\n  STR_UFO_CONSTRUCTION_UFOPEDIA: \"Le vaisseau alien est constitué de trois composants principaux : une source d'énergie, un système de navigation et une coque faite d'alliages aliens. La coque est spécialement conçue pour que les ondes de gravité puissent être contrôlées. De plus, une petite quantité d'élérium est nécessaire pour alimenter la source d'énergie. Une fois que les principes de construction ont été compris, et que l'on connaît les fonctions de chaque composant, il est alors possible de construire ce type de vaisseau.\"\n  STR_ALIEN_FOOD_UFOPEDIA: \"Ces chambres contiennent plusieurs enzymes utilisées pour digérer les parties du corps du bétail, d'autres animaux et même des humains. Le liquide est ensuite consommé comme aliment digéré, et est probablement directement injecté dans le système sanguin. Cela suggère une certaine dépendance sur la Terre vis-à-vis de la nourriture, une symbiose entre la Terre et la société alien.\"\n  STR_ALIEN_REPRODUCTION_UFOPEDIA: \"Ces chambres contiennent des fœtus aliens. Leur design semble suggérer que les aliens qui utilisent ce procédé dépendent totalement de la reproduction en laboratoire. Les riches nutriments assurent le développement rapide du fœtus. Cette reproduction à la chaîne peut générer des milliers de clones aliens en très peu de temps. Le procédé pourrait facilement être appliqué pour la reproduction humaine, ou pour des hybrides aliens-humains.\"\n  STR_ALIEN_ENTERTAINMENT_UFOPEDIA: \"La fonction la plus probable de ces sphères est récréative. Le circuit psionique stimule plusieurs centres du cerveau. L'effet est similaire aux drogues hallucinogènes. C'est la seule preuve qui montre que les aliens ont des passe-temps et une vie culturelle.\"\n  STR_ALIEN_SURGERY_UFOPEDIA: \"Cet équipement chirurgical utilise des scalpels laser pour extraire des parties du corps du bétail et d'autres animaux. Les mutilations répandues du bétail sont dues à cette activité étrange des aliens. Il est vraisemblable que ces morceaux sont utilisés à des fins nutritionnelles ou génétiques.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"Dans le passé, des milliers de gens ont prétendu avoir été enlevés par des aliens, et quelque fois à plusieurs reprises. La vérité est beaucoup plus horrible encore. Les humains sont enlevés, étudiés et contrôlés. On extrait les codes génétiques des meilleurs spécimens. On implante des fœtus humains-aliens à des femmes, et on les enlève plusieurs mois après. Qui sait quels motifs sinistres les aliens poursuivent?\"\n  STR_ALIEN_ALLOYS_UFOPEDIA: \"Le vaisseau alien est composé d'alliages spéciaux aux propriétés uniques. Ils sont extrêmement légers et solides, et peuvent être modelés grâce à des méthodes électromagnétiques. Ces métaux peuvent être reproduits et utilisés dans de nombreux procédés de fabrication.\"\n  STR_ELERIUM_115_UFOPEDIA: \"Cet élément a une propriété inhabituelle : il génère de l'énergie antimatière lorsqu'on le bombarde de certaines particules. Cela crée des ondes de gravité et d'autres formes d'énergie. Cet élément ne se trouve pas naturellement dans notre système solaire et ne peut être reproduit.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"Il est clair que nous nous engageons dans une bataille perdue d'avance sur la Terre. Les hordes aliens sont beaucoup plus nombreuses. La meilleure chose à faire est de ralentir leur progression. Le seul espoir pour l'humanité est de combattre les aliens à la source. Nos recherches semblent nous indiquer une base d'opérations toute proche dans notre système solaire. Les aliens considèrent cet endroit comme le centre d'une ancienne civilisation, antérieure à l'histoire humaine. Nous devons localiser cette base le plus tôt possible. Cependant, il nous faut capturer et interroger un leader alien pour obtenir plus d'informations. Les ovnis les plus grands contiennent probablement au moins un leader alien.\"\n  STR_THE_MARTIAN_SOLUTION_UFOPEDIA: \"Nos recherches nous indiquent maintenant que Mars est la base des opérations aliens. La base est bien cachée, et contient tous les procédés de fabrication et de clonage nécessaires à l'infiltration de la Terre. Elle semble également posséder un ordinateur de contrôle responsable de toute l'opération. Il semble que la société alien, organisée comme une ruche, ait une sorte de 'reine'. C'est leur point faible : si nous pouvons éliminer le 'cerveau', alors le corps mourra. Nous devons intensifier nos efforts de recherche avant qu'il ne soit trop tard. Pour progresser, nous devons capturer les aliens les plus hauts placés - les commandants - qui résident dans les bases et les vaisseaux de combat aliens.\"\n  STR_CYDONIA_OR_BUST_UFOPEDIA: \"Il est maintenant clair que les hordes aliens sont contrôlées d'une base souterraine à Cydonia, qui est une zone étrange de Mars comprenant des pyramides à cinq côtés et une large formation ressemblant à un visage humain. Il y a des millions d'années de cela, la civilisation cydonienne était florissante sur Mars, mais nous ne savons pas pourquoi elle s'est éteinte, ou quel est le lien avec l'activité alien qui y règne aujourd'hui. Quelle que soit l'explication, nous devons envoyer une expédition à Cydonia. C'est le seul moyen de vaincre les aliens. Nous devons détruire le 'cerveau' contrôlant toute l'opération. Il nous faut équiper un vaisseau Avenger avec les armes de destruction les plus puissantes que nous ayons. Nous ne pouvons rien apprendre de plus ici. Il nous faut attendre le résultat de l'attaque cydonienne.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"CENTRER SUR LE SITE - TEMPS = 5 s\"\n  STR_CANCEL_UC: \"ANNULER\"\n  STR_NONE: \"Rien\"\n  STR_UNKNOWN: \"Inconnu\"\n  STR_POOR: \"Médiocre\"\n  STR_AVERAGE: \"Moyen\"\n  STR_GOOD: \"Bon\"\n  STR_EXCELLENT: \"Excellent\"\n  STR_BUILD_NEW_BASE_UC: \"CONSTRUIRE NOUVELLE BASE\"\n  STR_BASE_INFORMATION: \"INFORMATIONS SUR LA BASE\"\n  STR_EQUIP_CRAFT: \"ÉQUIPER VAISSEAU\"\n  STR_BUILD_FACILITIES: \"CONSTRUIRE INSTALLATIONS\"\n  STR_RESEARCH: \"RECHERCHE\"\n  STR_MANUFACTURE: \"FABRICATION\"\n  STR_TRANSFER_UC: \"TRANSFERT\"\n  STR_PURCHASE_RECRUIT: \"ACHETER/RECRUTER\"\n  STR_SACK: \"RENVOYER\"\n  STR_SELL_SACK_UC: \"VENDRE/RENVOYER\"\n  STR_GEOSCAPE_UC: \"GÉOSCAPE\"\n  STR_NAME: \"Nom\"\n  STR_AREA: \"Zone\"\n  STR_BUILD_NEW_BASE: \"Construire une nouvelle base\"\n  STR_CANCEL: \"Annuler\"\n  STR_COST_UC: \"PRIX>\"\n  STR_CONSTRUCTION_TIME_UC: \"DURÉE DE CONSTRUCTION>\"\n  STR_DAY:\n    one: \"{N} jour\"\n    many: \"{N} jours\"\n    other: \"{N} jours\"\n  STR_HOUR:\n    one: \"{N} heure\"\n    many: \"{N} heures\"\n    other: \"{N} heures\"\n  STR_MAINTENANCE_UC: \"ENTRETIEN>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Installations\"\n  STR_CURRENT_RESEARCH: \"RECHERCHE ACTUELLE\"\n  STR_SCIENTISTS_AVAILABLE: \"Savants disponibles> {ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Savants affectés> {ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Espace de laboratoire disponible> {ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"PROJET DE RECHERCHE\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"SAVANTS AFFECTÉS\"\n  STR_PROGRESS: \"PROGRESSION\"\n  STR_NEW_PROJECT: \"Nouveau projet\"\n  STR_CANCEL_PROJECT: \"ANNULER LE PROJET\"\n  STR_NEW_RESEARCH_PROJECTS: \"NOUVEAUX PROJETS DE RECHERCHE\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"SAVANTS DISPONIBLES> {ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"ESPACE DE LABORATOIRE DISPONIBLE> {ALT}{0}\"\n  STR_INCREASE: \"Augmenter\"\n  STR_DECREASE: \"Diminuer\"\n  STR_START_PROJECT: \"LANCER LE PROJET\"\n  STR_CURRENT_PRODUCTION: \"PRODUCTION ACTUELLE\"\n  STR_ENGINEERS_AVAILABLE: \"Ingénieurs disponibles> {ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Ingénieurs affectés> {ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Espace d'atelier disponible> {ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Budget actuel> {ALT}{0}\"\n  STR_ITEM: \"OBJET\"\n  STR_ENGINEERS__ALLOCATED: \"Ingénieurs affectés\"\n  STR_UNITS_PRODUCED: \"Unités produites\"\n  STR_TOTAL_TO_PRODUCE: \"Total à produire\"\n  STR_COST__PER__UNIT: \"Coût{NEWLINE}par{NEWLINE}unité\"\n  STR_DAYS_HOURS_LEFT: \"Jours/heures restants\"\n  STR_NEW_PRODUCTION: \"Nouvelle production\"\n  STR_PRODUCTION_ITEMS: \"Objets à produire\"\n  STR_CATEGORY: \"CATÉGORIE\"\n  STR_START_PRODUCTION: \"COMMENCER LA PRODUCTION\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} heures d'ingénieur pour produire une unité\"\n  STR_COST_PER_UNIT_: \"Coût par unité> {ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Espace de travail requis> {ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"MATÉRIAUX SPÉCIAUX REQUIS\"\n  STR_ITEM_REQUIRED: \"OBJET REQUIS\"\n  STR_UNITS_REQUIRED: \"UNITÉS REQUISES\"\n  STR_UNITS_AVAILABLE: \"UNITÉS DISPONIBLES\"\n  STR_STOP_PRODUCTION: \"ARRÊTER LA PRODUCTION\"\n  STR_ENGINEERS_AVAILABLE_UC: \"INGÉNIEURS DISPONIBLES> {ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"ESPACE D'ATELIER DISPONIBLE> {ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"PROFIT MENSUEL> {ALT}{0}\"\n  STR_INCREASE_UC: \"AUGMENTER\"\n  STR_DECREASE_UC: \"DIMINUER\"\n  STR_UNITS_TO_PRODUCE: \"Unités à produire\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Acheter/recruter\"\n  STR_COST_OF_PURCHASES: \"Prix d'achat> {ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"COÛT PAR UNITÉ\"\n  STR_QUANTITY_UC: \"QUANTITÉ\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"PERSONNEL DISPONIBLE:PERSONNEL TOTAL>\"\n  STR_SOLDIERS: \"Soldats\"\n  STR_SCIENTISTS: \"Savants\"\n  STR_ENGINEERS: \"Ingénieurs\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"ESPACE UTILISÉ:ESPACE DISPONIBLE>\"\n  STR_LIVING_QUARTERS: \"Quartier d'habitation\"\n  STR_STORES: \"Entrepôts\"\n  STR_LABORATORIES: \"Laboratoires\"\n  STR_WORK_SHOPS: \"Ateliers\"\n  STR_HANGARS: \"Hangars\"\n  STR_SHORT_RANGE_DETECTION: \"Radar à courte portée\"\n  STR_DEFENSE_STRENGTH: \"Force de défense\"\n  STR_TRANSFERS_UC: \"TRANSFERTS\"\n  STR_TRANSFERS: \"Transferts\"\n  STR_ARRIVAL_TIME_HOURS: \"ARRIVÉE PRÉVUE (H)\"\n  STR_COST_: \"Prix> {ALT}{0}\"\n  STR_AREA_: \"Zone> {ALT}{0}\"\n  STR_BASE_NAME: \"Nom de la base?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"SÉLECTIONNEZ LA POSITION DE L'ASCENSEUR D'ACCÈS\"\n  STR_TRANSFER: \"Transfert\"\n  STR_AMOUNT_TO_TRANSFER: \"QUANTITÉ À TRANSFÉRER\"\n  STR_SELECT_DESTINATION_BASE: \"Sélectionnez la destination\"\n  STR_COST: \"Prix\"\n  STR_VICTORY_1: \"Alors que vous entrez dans la pièce, vous voyez le cerveau alien, objet de votre quête. Avant que vous puissiez tirer, il vous communique via un écran placé à sa base. Il vous implore de l'épargner et d'écouter ses arguments avant que vous décidiez d'appuyer sur la détente...\"\n  STR_VICTORY_2: \"Le cerveau dit : 'Il y a des millions d'années de cela, la planète que vous appelez Mars était vivante. Cette vie fut apportée à une planète stérile par notre civilisation comme ce fut le cas pour vous. Pendant des millions d'années, nous avons visité votre planète et développé génétiquement votre espèce. Vous ne pouvez pas nous tuer, vous faites partie de nous...\"\n  STR_VICTORY_3: \"Voici le centre de la civilisation martienne - les pyramides construites il y a des millions d'années avant les vôtres - par une espèce qui est votre ancêtre. Aucune planète n'est hors de notre portée. Ce pouvoir pourrait bientôt devenir le vôtre. Tout ce que nous demandons, c'est votre coopération...'\"\n  STR_GAME_OVER_1: \"Les aliens tentent d'exterminer l'humanité tout entière, détruisant les villes et empoisonnant l'air et la mer. La résistance des armées terrestres est futile face à une technologie hautement supérieure. Les générations survivantes souffrent de mutations horribles alors qu'elles fuient la destruction alien. Elles sont rassemblées dans des camps d'esclavage pour aider à transformer la Terre en une colonie alien soumise à un quelconque empire inconnu.\"\n  STR_GAME_OVER_2: \"Les connaissances acquises au cours du projet X-Com sont perdues à jamais. Vous n'avez pas réussi à sauver la Terre.\"\n  STR_VICTORY_4: \"Le cerveau alien est interrompu par une rafale de plasma chaud, et la force alien entière est vaincue.\"\n  STR_VICTORY_5: \"Une fois que les aliens ont perdu Mars, ils ont perdu la Terre. Bientôt, les recherches de X-Com permettront à l'humanité de prospérer à nouveau, et de revendiquer la propriété de Mars. La menace alien a disparu, mais pour combien de temps, nul ne le sait...\"\n  STR_YOU_HAVE_FAILED: \"Vous n'avez pas réussi à stopper l'attaque alien. L'une après l'autre, les nations qui vous finançaient signent des pactes avec les aliens, qui leur promettent la technologie, la prospérité et la paix. Toutefois, il devient rapidement évident que les aliens ont d'autres plans...\"\n  STR_TOTAL_UC: \"TOTAL\"\n  STR_INCOME: \"Revenu\"\n  STR_EXPENDITURE: \"Dépenses\"\n  STR_MAINTENANCE: \"Entretien\"\n  STR_BALANCE: \"Solde\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"Activité des ovnis par zone\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"Activité des ovnis par pays\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"Activité X-Com par zone\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"Activité X-Com par pays\"\n  STR_FINANCE: \"Finances\"\n  STR_DATE_FIRST: \"{0}er\"\n  STR_DATE_SECOND: \"{0}\"\n  STR_DATE_THIRD: \"{0}\"\n  STR_DATE_FOURTH: \"{0}\"\n  STR_FINANCE_THOUSANDS: \"x $1000\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Pas assez de matériaux spéciaux pour produire{NEWLINE}{0}{NEWLINE}à{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Pas assez d'argent pour produire{NEWLINE}{0}{NEWLINE}à{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"Production de{NEWLINE}{0}{NEWLINE}à{NEWLINE}{1}{NEWLINE}terminée\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"Construction de{NEWLINE}{0}{NEWLINE}à{NEWLINE}{1}{NEWLINE}terminée\"\n  STR_OK_5_SECONDS: \"OK - 5 s\"\n  STR_RESEARCH_COMPLETED: \"Recherche terminée\"\n  STR_VIEW_REPORTS: \"VOIR RAPPORTS\"\n  STR_WE_CAN_NOW_RESEARCH: \"Nous pouvons maintenant étudier\"\n  STR_WE_CAN_NOW_PRODUCE: \"Nous pouvons maintenant produire\"\n  STR_SUNDAY: \"DIMANCHE\"\n  STR_MONDAY: \"LUNDI\"\n  STR_TUESDAY: \"MARDI\"\n  STR_WEDNESDAY: \"MERCREDI\"\n  STR_THURSDAY: \"JEUDI\"\n  STR_FRIDAY: \"VENDREDI\"\n  STR_SATURDAY: \"SAMEDI\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Pas assez de {0} pour ravitailler le vaisseau {1} à {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Pas assez de {0} pour réarmer le vaisseau {1} à {2}\"\n  STR_UFO_IS_NOT_RECOVERED: \"L'ovni n'est pas récupéré\"\n  STR_UFO_IS_RECOVERED: \"L'ovni est récupéré\"\n  STR_CRAFT_IS_LOST: \"Le vaisseau est perdu\"\n  STR_TERROR_CONTINUES: \"La terreur continue\"\n  STR_ALIENS_DEFEATED: \"Les aliens sont vaincus\"\n  STR_BASE_IS_LOST: \"La base est perdue\"\n  STR_BASE_IS_SAVED: \"La base est sauvée\"\n  STR_ALIEN_BASE_STILL_INTACT: \"La base alien est intacte\"\n  STR_ALIEN_BASE_DESTROYED: \"La base alien est détruite\"\n  STR_ALIENS_KILLED: \"ALIENS TUÉS\"\n  STR_ALIEN_CORPSES_RECOVERED: \"CORPS ALIENS RÉCUPÉRÉS\"\n  STR_LIVE_ALIENS_RECOVERED: \"ALIENS VIVANTS RÉCUPÉRÉS\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"OBJETS ALIENS RÉCUPÉRÉS\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"CONTRÔLE DE BASE ALIEN DÉTRUIT\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"CIVILS TUÉS PAR DES ALIENS\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"CIVILS TUÉS PAR DES AGENTS X-COM\"\n  STR_CIVILIANS_SAVED: \"CIVILS SAUVÉS\"\n  STR_XCOM_OPERATIVES_KILLED: \"AGENTS X-COM TUÉS\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"AGENTS X-COM PORTÉS DISPARU\"\n  STR_TANKS_DESTROYED: \"TANKS DÉTRUITS\"\n  STR_XCOM_CRAFT_LOST: \"VAISSEAU X-COM PERDU\"\n  STR_UFO_RECOVERY: \"RÉCUPÉRATION D'OVNI\"\n  STR_ALIEN_BASE_RECOVERY: \"RÉCUPÉRATION DE BASE ALIEN\"\n  STR_BASE_UNDER_ATTACK: \"{0} est attaqué!\"\n  STR_BASE_DEFENSES_INITIATED: \"DÉFENSES DE LA BASE ACTIVÉES\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"LE BOUCLIER REPOUSSE L'OVNI!\"\n  STR_FIRING: \"MISE À FEU\"\n  STR_HIT: \"TOUCHÉ!\"\n  STR_UFO_DESTROYED: \"OVNI DÉTRUIT!\"\n  STR_MISSED: \"RATÉ!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Vendre/renvoyer\"\n  STR_VALUE_OF_SALES: \"VALEUR DES VENTES> {ALT}{0}\"\n  STR_FUNDS: \"BUDGET> {ALT}{0}\"\n  STR_SELL_SACK: \"Vendre/virer\"\n  STR_VALUE: \"Valeur\"\n  STR_CRAFT_: \"VAISSEAU> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"RÉCUPÉRATION D'OVNI ÉCRASÉ\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"AVERTISSEMENT - Il peut y avoir des aliens ouvriers dans l'ovni ou autour du lieu du crash. La mission sera réussie quand toutes les unités ennemies auront été éliminées ou neutralisées. La récupération des restes de l'ovni, des objets et des corps aliens pourra alors commencer. Pour annuler la mission, ramenez les agents X-Com au véhicule de transport et cliquez sur l'icône 'Abandonner la mission'.\"\n  STR_UFO_GROUND_ASSAULT: \"ATTAQUE AU SOL DE L'OVNI\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"Explorez le lieu de l'atterrissage et, si possible, entrez dans l'ovni. La mission sera réussie quand toutes les unités ennemies auront été éliminées ou neutralisées. La récupération de l'ovni, des objets et des corps aliens pourra alors commencer. Pour annuler la mission, ramenez les agents X-Com au véhicule de transport et cliquez sur l'icône 'Abandonner la mission'.\"\n  STR_BASE_DEFENSE: \"DÉFENSE DE LA BASE\"\n  STR_BASE_UC_: \"BASE> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"Un vaisseau alien a atterri tout près. Notre base court un grand danger. Selon la procédure habituelle, tout le personnel non-combattant et les vaisseaux X-Com ont été évacués. Les unités aliens vont entrer dans la base par les portes du hangar ou par l'ascenseur d'accès. Défendez la base et ses installations vitales à tout prix - c'est un combat à mort. Si vous cliquez sur l'icône 'Abandonner la mission', vous serez vaincu et perdrez la base.\"\n  STR_ALIEN_BASE_ASSAULT: \"ATTAQUE DE LA BASE ALIEN\"\n  STR_ALIEN_BASE_ASSAULT_BRIEFING: \"Les agents X-Com ont pénétré dans une base alien. Le centre de contrôle doit être détruit pour rendre la base inopérante. La mission sera terminée quand tous les ennemis auront été éliminés, ou quand votre escouade sera revenue à la zone verte de sortie (cliquez sur l'icône 'Abandonner la mission' pour s'échapper).\"\n  STR_CYDONIA_BRIEFING: \"Vous êtes arrivé à Cydonia. Vous pénétrez dans un grand complexe souterrain près du Sphinx martien. Vous devez détruire le cerveau alien qui contrôle toute l'activité alien. Le sort de l'humanité est entre vos mains....\"\n  STR_TERROR_MISSION: \"MISSION DE TERREUR\"\n  STR_TERROR_MISSION_BRIEFING: \"La mission sera réussie lorsque toutes les unités ennemies auront été éliminées ou neutralisées. Vous devez essayer de sauver les vies de tous les civils de la région en neutralisant la menace alien. Pour annuler la mission, ramenez les agents X-Com au véhicule de transport et cliquez sur l'icône 'Abandonner la mission'.\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"AUCUN HANGAR DE LIBRE POUR LA PRODUCTION D'UN VAISSEAU!{SMALLLINE}Tout vaisseau affecté à une base, transféré à une base, acheté ou construit a besoin d'un hangar. Construisez un nouveau hangar ou transférez un vaisseau à une autre base.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"AUCUN HANGAR DE LIBRE POUR L'ACHAT!{SMALLLINE}Tout vaisseau affecté à une base, transféré à une base, acheté ou construit a besoin d'un hangar. Construisez un nouveau hangar ou transférez un vaisseau à une autre base.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"AUCUN HANGAR DE LIBRE POUR LE TRANSFERT!{SMALLLINE}Tout vaisseau affecté à une base, transféré à une base, acheté ou construit a besoin d'un hangar. Construisez un nouveau hangar ou transférez un vaisseau à une autre base.\"\n  STR_CANNOT_BUILD_HERE: \"IMPOSSIBLE DE CONSTRUIRE ICI!{SMALLLINE}Vous devez construire à côté d'une installation existante.\"\n  STR_NO_FREE_ACCOMODATION: \"AUCUN LOGEMENT DE LIBRE!{SMALLLINE}La base de destination n'a pas assez de place dans les quartiers d'habitation.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"PAS ASSEZ D'ESPACE DE TRAVAIL!{SMALLLINE}Construisez un nouvel atelier ou réduisez le travail sur d'autres projets.\"\n  STR_NOT_ENOUGH_MONEY: \"PAS ASSEZ D'ARGENT!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"PAS ASSEZ D'ESPACE DE STOCKAGE!{SMALLLINE}Construisez un nouvel entrepôt ou transférez les stocks existants aux autres bases.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"PAS ASSEZ D'ESPACE VITAL!{SMALLLINE}Construisez de nouveaux quartiers d'habitation ou transférez le personnel aux autres bases.\"\n  STR_LAUNCH_INTERCEPTION: \"LANCER UNE INTERCEPTION\"\n  STR_CRAFT: \"VAISSEAU\"\n  STR_STATUS: \"STATUT\"\n  STR_BASE: \"BASE\"\n  STR_READY: \"PRÊT\"\n  STR_OUT: \"ABSENT\"\n  STR_REPAIRS: \"RÉPARATION\"\n  STR_REFUELLING: \"RAVITAILLE\"\n  STR_REARMING: \"RÉARMEMENT\"\n  STR_TARGET: \"CIBLE : {0}\"\n  STR_WAY_POINT: \"POINT DE REPÈRE\"\n  STR_ARE_YOU_SURE_CYDONIA: \"Voulez-vous vraiment envoyer ce vaisseau en mission à Cydonia?\"\n  STR_YES: \"OUI\"\n  STR_NO: \"NON\"\n  STR_SELECT_DESTINATION: \"SÉLECTIONNEZ LA DESTINATION\"\n  STR_CYDONIA: \"CYDONIA\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"SÉLECTIONNEZ LE SITE POUR LA NOUVELLE BASE À CONSTRUIRE\"\n  STR_RETURN_TO_BASE: \"RETOURNER À LA BASE\"\n  STR_SELECT_NEW_TARGET: \"SÉLECTIONNER UNE NOUVELLE CIBLE\"\n  STR_PATROL: \"PATROUILLER\"\n  STR_STATUS_: \"STATUT> {ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"ENDOMMAGÉ - RETOURNE À LA BASE\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"CARBURANT BAS - RETOURNE À LA BASE\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"MISSION TERMINÉE - RETOURNE À LA BASE\"\n  STR_PATROLLING: \"EN PATROUILLE\"\n  STR_TAILING_UFO: \"POURSUIT UN OVNI\"\n  STR_INTERCEPTING_UFO: \"INTERCEPTE L'OVNI-{0}\"\n  STR_RETURNING_TO_BASE: \"RETOURNE À LA BASE\"\n  STR_DESTINATION_UC_: \"DESTINATION : {0}\"\n  STR_BASE_UC: \"BASE> {ALT}{0}\"\n  STR_SPEED_: \"VITESSE> {ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"VITESSE MAXIMUM> {ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"ALTITUDE> {ALT}{0}\"\n  STR_VERY_LOW: \"TRÈS BASSE\"\n  STR_LOW_UC: \"BASSE\"\n  STR_HIGH_UC: \"HAUTE\"\n  STR_VERY_HIGH: \"TRÈS HAUTE\"\n  STR_FUEL: \"CARBURANT> {ALT}{0}\"\n  STR_WEAPON_ONE: \"ARME-1> {ALT}{0}\"\n  STR_NONE_UC: \"RIEN\"\n  STR_ROUNDS_: \"MUNITIONS> {ALT}{0}\"\n  STR_WEAPON_TWO: \"ARME-2> {ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"VAISSEAUX D'INTERCEPTION\"\n  STR_BASE_: \"Base> {0}\"\n  STR_NAME_UC: \"NOM\"\n  STR_AMMO_: \"MUNITIONS> {ALT}{0}\"\n  STR_CREW: \"ÉQUIPAGE\"\n  STR_EQUIPMENT_UC: \"ÉQUIPEMENT\"\n  STR_ARMOR: \"ARMURE\"\n  STR_MAX: \"MAX> {ALT}{0}\"\n  STR_ROOKIE: \"Recrue\"\n  STR_SQUADDIE: \"Simple soldat\"\n  STR_SERGEANT: \"Sergent\"\n  STR_CAPTAIN: \"Capitaine\"\n  STR_COLONEL: \"Colonel\"\n  STR_COMMANDER: \"Commandant\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Formez l'équipe pour {0}\"\n  STR_SORT_BY: \"TRIER PAR...\"\n  STR_ORIGINAL_ORDER: \"ORDRE ORIGINAL\"\n  STR_MISSIONS2: \"MISSIONS\"\n  STR_KILLS2: \"VICTIMES\"\n  STR_WOUND_RECOVERY2: \"GUÉRISON DE BLESSURE\"\n  STR_SPACE_AVAILABLE: \"ESPACE DISPONIBLE> {ALT}{0}\"\n  STR_SPACE_USED: \"ESPACE UTILISÉ> {ALT}{0}\"\n  STR_SPACE_USED_UC: \"ESPACE UTILISÉ\"\n  STR_RANK: \"GRADE\"\n  STR_WOUNDED: \"BLESSÉ\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Équipement pour {0}\"\n  STR_DEFENSE_VALUE: \"Valeur défensive\"\n  STR_HIT_RATIO: \"Ratio de tirs réussis\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}prêt à{NEWLINE}atterrir près de{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"Commencer la mission?\"\n  STR_SELECT_ARMAMENT: \"Sélectionnez l'armement\"\n  STR_AMMUNITION_AVAILABLE: \"MUNITIONS DISPONIBLES\"\n  STR_ARMAMENT: \"ARMEMENT\"\n  STR_NOT_AVAILABLE: \"N.D.\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"SÉLECTIONNEZ L'ARMURE POUR{NEWLINE}{0}\"\n  STR_TYPE: \"TYPE\"\n  STR_PERSONAL_ARMOR_UC: \"ARMURE PERSONNELLE\"\n  STR_POWER_SUIT_UC: \"ARMURE ÉNERGÉTIQUE\"\n  STR_FLYING_SUIT_UC: \"ARMURE ANTIGRAVITÉ\"\n  STR_SELECT_ARMOR: \"Sélectionnez une armure\"\n  STR_NORTH: \"NORD\"\n  STR_NORTH_EAST: \"NORD-EST\"\n  STR_EAST: \"EST\"\n  STR_SOUTH_EAST: \"SUD-EST\"\n  STR_SOUTH: \"SUD\"\n  STR_SOUTH_WEST: \"SUD-OUEST\"\n  STR_WEST: \"OUEST\"\n  STR_NORTH_WEST: \"NORD-OUEST\"\n  STR_SELECT_ACTION: \"SÉLECTIONNEZ UNE ACTION\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"CONTINUER L'INTERCEPTION\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"POURSUIVRE SANS INTERCEPTION\"\n  STR_VERY_LARGE: \"TRÈS GROS\"\n  STR_LARGE: \"GROS\"\n  STR_MEDIUM_UC: \"MOYEN\"\n  STR_SMALL: \"PETIT\"\n  STR_VERY_SMALL: \"TRÈS PETIT\"\n  STR_GROUNDED: \"AU SOL\"\n  STR_DETECTED: \"Détecté\"\n  STR_SIZE_UC: \"TAILLE\"\n  STR_ALTITUDE: \"ALTITUDE\"\n  STR_HEADING: \"CAP\"\n  STR_SPEED: \"VITESSE\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"CENTRER SUR L'OVNI - TEMPS = 5 s\"\n  STR_TRACKING_LOST: \"L'OVNI A DISPARU\"\n  STR_REDIRECT_CRAFT: \"REDIRIGER LE VAISSEAU\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"ALLER À SA DERNIÈRE POSITION CONNUE\"\n  STR_UFO_: \"OVNI-{0}\"\n  STR_ALIEN_BASE_: \"BASE ALIEN-{0}\"\n  STR_CRASH_SITE_: \"LIEU DU CRASH-{0}\"\n  STR_LANDING_SITE_: \"SITE D'ATTERRISSAGE-{0}\"\n  STR_WAY_POINT_: \"POINT DE REPÈRE-{0}\"\n  STR_TERROR_SITE: \"SITE DE TERREUR-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}a atteint{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"En patrouille\"\n  STR_ALIEN_ORIGINS: \"Origines des aliens\"\n  STR_THE_MARTIAN_SOLUTION: \"La solution martienne\"\n  STR_CYDONIA_OR_BUST: \"Cydonia ou rien\"\n  STR_UFOPAEDIA: \"Ovnipédie\"\n  STR_XCOM_CRAFT_ARMAMENT: \"VAISSEAUX ET ARMEMENT X-COM\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"PLATES-FORMES D'ARMES LOURDES\"\n  STR_WEAPONS_AND_EQUIPMENT: \"ARMES ET ÉQUIPEMENTS\"\n  STR_ALIEN_ARTIFACTS: \"OBJETS ALIENS\"\n  STR_BASE_FACILITIES: \"INSTALLATIONS D'UNE BASE\"\n  STR_ALIEN_LIFE_FORMS: \"FORMES DE VIE ALIENS\"\n  STR_ALIEN_RESEARCH_UC: \"RECHERCHE SUR LES ALIENS\"\n  STR_UFO_COMPONENTS: \"COMPOSANTS DES OVNIS\"\n  STR_UFOS: \"OBJETS VOLANTS NON IDENTIFIÉS (OVNIs)\"\n  STR_SELECT_ITEM: \"SÉLECTIONNEZ UN ARTICLE\"\n  STR_ACCELERATION: \"ACCÉLÉRATION> {ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"CAPACITÉ DE CARBURANT> {ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"NACELLES D'ARMES> {ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"CAPACITÉ DE DÉGÂTS> {ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"ESPACE DE LA SOUTE> {ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"CAPACITÉ DES PAL> {ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Dégâts\"\n  STR_RANGE: \"Portée\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Précision\"\n  STR_RE_LOAD_TIME: \"Rechargement\"\n  STR_SECONDS: \"{0} s\"\n  STR_DAMAGE_ARMOR_PIERCING: \"PERCE-ARMURE\"\n  STR_DAMAGE_INCENDIARY: \"INCENDIAIRE\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"EXPLOSIF\"\n  STR_DAMAGE_LASER_BEAM: \"RAYON LASER\"\n  STR_DAMAGE_PLASMA_BEAM: \"RAYON À PLASMA\"\n  STR_DAMAGE_STUN: \"ASSOMMER\"\n  STR_DAMAGE_MELEE: \"MÊLÉE\"\n  STR_DAMAGE_ACID: \"ACIDE\"\n  STR_DAMAGE_SMOKE: \"FUMÉE\"\n  STR_SHOT_TYPE: \"TYPE DE TIR\"\n  STR_ACCURACY_UC: \"PRÉCISION\"\n  STR_TIME_UNIT_COST: \"COÛT EN UT\"\n  STR_DAMAGE_UC: \"DÉGÂTS\"\n  STR_AMMO: \"MUNITIONS\"\n  STR_SHOT_TYPE_AUTO: \"Auto.\"\n  STR_SHOT_TYPE_SNAP: \"Rapide\"\n  STR_SHOT_TYPE_AIMED: \"Précis\"\n  STR_CONSTRUCTION_TIME: \"Durée de construction\"\n  STR_CONSTRUCTION_COST: \"Coût de construction\"\n  STR_MAINTENANCE_COST: \"Coût d'entretien\"\n  STR_LOW: \"Basse\"\n  STR_MEDIUM: \"Moyenne\"\n  STR_HIGH: \"Haute\"\n  STR_CRAFT_WEAPON: \"Arme de vaisseau\"\n  STR_CRAFT_AMMUNITION: \"Munitions de vaisseau\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Plate-forme d'armes lourdes\"\n  STR_WEAPON: \"Arme\"\n  STR_AMMUNITION: \"Munitions\"\n  STR_EQUIPMENT: \"Équipement\"\n  STR_ALIEN_CORPSE: \"Corps alien\"\n  STR_UFO_COMPONENT: \"Composant d'ovni\"\n  STR_PERSONAL_ARMOR: \"Armure personnelle\"\n  STR_RAW_MATERIALS: \"Matières premières\"\n  STR_HWP_CANNON_SHELLS: \"Obus de PAL\"\n  STR_ALIEN: \"Alien\"\n  STR_SECTOID: \"Sectoïde\"\n  STR_SNAKEMAN: \"Homme-Serpent\"\n  STR_ETHEREAL: \"Ethereal\"\n  STR_MUTON: \"Muton\"\n  STR_FLOATER: \"Floater\"\n  STR_CELATID: \"Celatid\"\n  STR_SILACOID: \"Silacoïde\"\n  STR_CHRYSSALID: \"Chrysalide\"\n  STR_ZOMBIE: \"Zombie\"\n  STR_REAPER: \"Reaper\"\n  STR_SECTOPOD: \"Sectopode\"\n  STR_CYBERDISC: \"Cyberdisque\"\n  STR_LIVE_COMMANDER: \"Commandant\"\n  STR_LIVE_LEADER: \"Leader\"\n  STR_LIVE_ENGINEER: \"Ingénieur\"\n  STR_LIVE_MEDIC: \"Infirmier\"\n  STR_LIVE_NAVIGATOR: \"Navigateur\"\n  STR_LIVE_SOLDIER: \"Soldat\"\n  STR_LIVE_TERRORIST: \"Terroriste\"\n  STR_FLOATER_SOLDIER: \"Soldat Floater\"\n  STR_FLOATER_NAVIGATOR: \"Navigateur Floater\"\n  STR_FLOATER_MEDIC: \"Infirmier Floater\"\n  STR_FLOATER_ENGINEER: \"Ingénieur Floater\"\n  STR_FLOATER_LEADER: \"Leader Floater\"\n  STR_FLOATER_COMMANDER: \"Commandant Floater\"\n  STR_SECTOID_SOLDIER: \"Soldat Sectoïde\"\n  STR_SECTOID_NAVIGATOR: \"Navigateur Sectoïde\"\n  STR_SECTOID_MEDIC: \"Infirmier Sectoïde\"\n  STR_SECTOID_ENGINEER: \"Ingénieur Sectoïde\"\n  STR_SECTOID_LEADER: \"Leader Sectoïde\"\n  STR_SECTOID_COMMANDER: \"Commandant Sectoïde\"\n  STR_SNAKEMAN_SOLDIER: \"Soldat Homme-Serpent\"\n  STR_SNAKEMAN_NAVIGATOR: \"Navigateur Homme-Serpent\"\n  STR_SNAKEMAN_ENGINEER: \"Ingénieur Homme-Serpent\"\n  STR_SNAKEMAN_LEADER: \"Leader Homme-Serpent\"\n  STR_SNAKEMAN_COMMANDER: \"Commandant Homme-Serpent\"\n  STR_MUTON_SOLDIER: \"Soldat Muton\"\n  STR_MUTON_NAVIGATOR: \"Navigateur Muton\"\n  STR_MUTON_ENGINEER: \"Ingénieur Muton\"\n  STR_ETHEREAL_SOLDIER: \"Soldat Ethereal\"\n  STR_ETHEREAL_LEADER: \"Leader Ethereal\"\n  STR_ETHEREAL_COMMANDER: \"Commandant Ethereal\"\n  STR_CYBERDISC_TERRORIST: \"Terroriste Cyberdisque\"\n  STR_REAPER_TERRORIST: \"Terroriste Reaper\"\n  STR_CHRYSSALID_TERRORIST: \"Terroriste Chrysalide\"\n  STR_CELATID_TERRORIST: \"Terroriste Celatid\"\n  STR_SILACOID_TERRORIST: \"Terroriste Silacoïde\"\n  STR_SECTOPOD_TERRORIST: \"Terroriste Sectopode\"\n  STR_UFO_POWER_SOURCE: \"Source d'énergie d'ovni\"\n  STR_UFO_NAVIGATION: \"Navigation d'ovni\"\n  STR_UFO_CONSTRUCTION: \"Construction d'ovni\"\n  STR_ALIEN_FOOD: \"Nourriture alien\"\n  STR_ALIEN_REPRODUCTION: \"Reproduction alien\"\n  STR_ALIEN_ENTERTAINMENT: \"Divertissement alien\"\n  STR_ALIEN_SURGERY: \"Chirurgie alien\"\n  STR_EXAMINATION_ROOM: \"Salle d'examen\"\n  STR_ALIEN_ALLOYS: \"Alliages aliens\"\n  STR_ALIEN_HABITAT: \"Habitat alien\"\n  STR_POWER_SUIT: \"Armure énergétique\"\n  STR_FLYING_SUIT: \"Armure antigravité\"\n  STR_HWP_ROCKETS: \"Roquettes de PAL\"\n  STR_HWP_FUSION_BOMB: \"Boule de fusion de PAL\"\n  STR_LASER_WEAPONS: \"Armes laser\"\n  STR_NEW_FIGHTER_CRAFT: \"Nouveau vaisseau chasseur\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Nouveau chasseur-transporteur\"\n  STR_ULTIMATE_CRAFT: \"Vaisseau suprême\"\n  STR_LASER_PISTOL: \"Pistolet laser\"\n  STR_LASER_RIFLE: \"Fusil laser\"\n  STR_HEAVY_LASER: \"Laser lourd\"\n  STR_LASER_CANNON: \"Canon laser\"\n  STR_PLASMA_CANNON: \"Rayon à plasma\"\n  STR_FUSION_MISSILE: \"Missile à fusion\"\n  STR_LASER_DEFENSE: \"Défense laser\"\n  STR_PLASMA_DEFENSE: \"Défense à plasma\"\n  STR_FUSION_DEFENSE: \"Défense à fusion\"\n  STR_GRAV_SHIELD: \"Bouclier gravitationnel\"\n  STR_MIND_SHIELD: \"Bouclier psychique\"\n  STR_PSI_LAB: \"Psi-Labo\"\n  STR_MOTION_SCANNER: \"Scanner de mouvement\"\n  STR_MEDI_KIT: \"Trousse de soins\"\n  STR_TANK_CANNON: \"Canon de tank\"\n  STR_TANK_ROCKET_LAUNCHER: \"Lance-roquettes de tank\"\n  STR_TANK_LASER_CANNON: \"Canon laser de tank\"\n  STR_HOVERTANK_PLASMA: \"Rayon à plasma d'aérotank\"\n  STR_HOVERTANK_LAUNCHER: \"Lance-boules de fusion d'aérotank\"\n  STR_STINGRAY_LAUNCHER: \"Lance-missiles Stingray\"\n  STR_AVALANCHE_LAUNCHER: \"Lance-missiles Avalanche\"\n  STR_CANNON: \"Canon\"\n  STR_FUSION_BALL_LAUNCHER: \"Lance-boules de fusion\"\n  STR_PLASMA_BEAM: \"Rayon à plasma\"\n  STR_STINGRAY_MISSILES: \"Missiles Stingray\"\n  STR_AVALANCHE_MISSILES: \"Missiles Avalanche\"\n  STR_CANNON_ROUNDS_X50: \"Obus de canon (x50)\"\n  STR_FUSION_BALL: \"Boule de fusion\"\n  STR_SOLDIER: \"Soldat\"\n  STR_SCIENTIST: \"Savant\"\n  STR_ENGINEER: \"Ingénieur\"\n  STR_NORTH_AMERICA: \"Amérique du Nord\"\n  STR_ARCTIC: \"Arctique\"\n  STR_ANTARCTICA: \"Antarctique\"\n  STR_SOUTH_AMERICA: \"Amérique du Sud\"\n  STR_EUROPE: \"Europe\"\n  STR_NORTH_AFRICA: \"Afrique du Nord\"\n  STR_SOUTHERN_AFRICA: \"Afrique du Sud\"\n  STR_CENTRAL_ASIA: \"Asie centrale\"\n  STR_SOUTH_EAST_ASIA: \"Asie du Sud-Est\"\n  STR_SIBERIA: \"Sibérie\"\n  STR_AUSTRALASIA: \"Australasie\"\n  STR_PACIFIC: \"Pacifique\"\n  STR_NORTH_ATLANTIC: \"Atlantique Nord\"\n  STR_SOUTH_ATLANTIC: \"Atlantique Sud\"\n  STR_INDIAN_OCEAN: \"Océan Indien\"\n  STR_ALIEN_RESEARCH: \"Recherche sur les aliens\"\n  STR_ALIEN_HARVEST: \"Moisson alien\"\n  STR_ALIEN_ABDUCTION: \"Enlèvement alien\"\n  STR_ALIEN_INFILTRATION: \"Infiltration alien\"\n  STR_ALIEN_BASE: \"Base alien\"\n  STR_ALIEN_TERROR: \"Terreur alien\"\n  STR_ALIEN_RETALIATION: \"Représailles aliens\"\n  STR_ALIEN_SUPPLY: \"Réserves aliens\"\n  STR_MAXIMUM_SPEED: \"Vitesse maximum\"\n  STR_HYPER_WAVE_DECODER_UC: \"DÉCODEUR D'HYPERONDES\"\n  STR_SKYRANGER: \"SKYRANGER\"\n  STR_LIGHTNING: \"LIGHTNING\"\n  STR_AVENGER: \"AVENGER\"\n  STR_INTERCEPTOR: \"INTERCEPTOR\"\n  STR_FIRESTORM: \"FIRESTORM\"\n  STR_UFO: \"OVNI\"\n  STR_STINGRAY: \"STINGRAY\"\n  STR_AVALANCHE: \"AVALANCHE\"\n  STR_CANNON_UC: \"CANON\"\n  STR_FUSION_BALL_UC: \"BOULES DE FUSION\"\n  STR_LASER_CANNON_UC: \"CANON LASER\"\n  STR_PLASMA_BEAM_UC: \"RAYON À PLASMA\"\n  STR_DAMAGE_CAPACITY: \"Capacité de dégâts\"\n  STR_WEAPON_POWER: \"Puissance de l'arme\"\n  STR_WEAPON_RANGE: \"Portée de l'arme\"\n  STR_ACCESS_LIFT: \"Ascenseur d'accès\"\n  STR_LABORATORY: \"Laboratoire\"\n  STR_WORKSHOP: \"Atelier\"\n  STR_SMALL_RADAR_SYSTEM: \"Petit système radar\"\n  STR_LARGE_RADAR_SYSTEM: \"Grand système radar\"\n  STR_MISSILE_DEFENSES: \"Défenses à missiles\"\n  STR_GENERAL_STORES: \"Entrepôt\"\n  STR_ALIEN_CONTAINMENT: \"Centre de détention\"\n  STR_LASER_DEFENSES: \"Défenses au laser\"\n  STR_PLASMA_DEFENSES: \"Défenses à plasma\"\n  STR_FUSION_BALL_DEFENSES: \"Déf. à boules de fusion\"\n  STR_PSIONIC_LABORATORY: \"Laboratoire psionique\"\n  STR_HYPER_WAVE_DECODER: \"Décodeur d'hyperondes\"\n  STR_HANGAR: \"Hangar\"\n  STR_USA: \"ÉTATS-UNIS\"\n  STR_RUSSIA: \"RUSSIE\"\n  STR_UK: \"ROYAUME-UNI\"\n  STR_FRANCE: \"FRANCE\"\n  STR_GERMANY: \"ALLEMAGNE\"\n  STR_ITALY: \"ITALIE\"\n  STR_SPAIN: \"ESPAGNE\"\n  STR_CHINA: \"CHINE\"\n  STR_JAPAN: \"JAPON\"\n  STR_INDIA: \"INDE\"\n  STR_BRAZIL: \"BRÉSIL\"\n  STR_AUSTRALIA: \"AUSTRALIE\"\n  STR_NIGERIA: \"NIGÉRIA\"\n  STR_SOUTH_AFRICA: \"AFRIQUE DU SUD\"\n  STR_EGYPT: \"ÉGYPTE\"\n  STR_CANADA: \"CANADA\"\n  STR_TANK: \"Tank\"\n  STR_CIVILIAN: \"Civil\"\n  STR_JAN: \"Jan\"\n  STR_FEB: \"Fév\"\n  STR_MAR: \"Mar\"\n  STR_APR: \"Avr\"\n  STR_MAY: \"Mai\"\n  STR_JUN: \"Jun\"\n  STR_JUL: \"Jul\"\n  STR_AUG: \"Aoû\"\n  STR_SEP: \"Sep\"\n  STR_OCT: \"Oct\"\n  STR_NOV: \"Nov\"\n  STR_DEC: \"Déc\"\n  STR_INTERNATIONAL_RELATIONS: \"Relations internationales\"\n  STR_COUNTRY: \"Pays\"\n  STR_FUNDING: \"Budget\"\n  STR_CHANGE: \"Écart\"\n  STR_WEAPON_SYSTEMS: \"SYSTÈMES D'ARMES\"\n  STR_HWPS: \"PAL\"\n  STR_DAMAGE_UC_: \"DÉGÂTS> {ALT}{0}\"\n  STR_ACCESS_LIFT_UFOPEDIA: \"L'ascenseur d'accès permet d'entrer ou de sortir l'équipement et le personnel d'une base souterraine. C'est toujours la première installation à être construite sur un nouveau site. La cage d'ascenseur est vulnérable aux intrusions de toute force hostile potentielle.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Chaque quartier d'habitation peut abriter jusqu'à 50 personnes. Cette installation comporte une zone de loisirs, un secteur d'alimentation et des dortoirs.\"\n  STR_LABORATORY_UFOPEDIA: \"Un maximum de 50 savants peuvent travailler dans un laboratoire. Les laboratoires sont équipés de la toute dernière technologie en matière de recherche de matériaux, de biochimie et de cosmologie. L'accès aux meilleurs laboratoires de recherche est privilégié dans le monde entier, y compris les établissements militaires.\"\n  STR_WORKSHOP_UFOPEDIA: \"Un atelier contient tout l'équipement nécessaire à la fabrication de produits basés sur les conceptions des laboratoires scientifiques. Un atelier peut contenir jusqu'à 50 ingénieurs, mais les objets en construction prennent également de la place.\"\n  STR_SMALL_RADAR_SYSTEM_UFOPEDIA: \"Un petit système radar a une portée radar de 300 milles marin et est relié à des systèmes satellites pour les recherches au sol. Chaque système a 10 % de chance de détecter un objet de taille moyenne toutes les 30 minutes.\"\n  STR_LARGE_RADAR_SYSTEM_UFOPEDIA: \"Un grand système radar a une portée de 450 milles marin et est relié à des systèmes satellites pour les recherches au sol. Chaque système a 20 % de chance de détecter un objet de taille moyenne toutes les 30 minutes.\"\n  STR_MISSILE_DEFENSES_UFOPEDIA: \"Les défenses à missiles protègent contre les incursions des vaisseaux ennemis qui essaieraient d'atterrir près de la base.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"Tout l'équipement, les systèmes d'armes, les munitions, le matériel récupéré et les plates-formes d'armes lourdes sont placés dans les entrepôts, y compris l'équipement destiné aux vaisseaux qui sont dans les hangars.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"Les aliens vivants risquent de nécessiter un habitat spécial pour maintenir leurs fonctions vitales. L'installation de centre de détention des aliens peut contenir jusqu'à 10 formes de vie aliens dans des unités indépendantes.\"\n  STR_LASER_DEFENSES_UFOPEDIA: \"Les défenses au laser protègent contre les incursions des vaisseaux ennemis.\"\n  STR_PLASMA_DEFENSES_UFOPEDIA: \"Les défenses à plasma fournissent une protection puissante et efficace contre les intrusions des vaisseaux ennemis.\"\n  STR_FUSION_BALL_DEFENSES_UFOPEDIA: \"Les missiles de boule de fusion sont la défense la plus efficace contre les attaques aliens. Ces missiles créent une implosion antimatière qui détruit tout dans un rayon spécifique.\"\n  STR_GRAV_SHIELD_UFOPEDIA: \"Le bouclier gravitationnel repousse les vaisseaux aliens qui essaieraient d'atterrir près de la base assez longtemps pour que tous les systèmes de défense puissent tirer à nouveau. En pratique, cela double l'efficacité de tous les systèmes de défense de votre base.\"\n  STR_MIND_SHIELD_UFOPEDIA: \"Comme les vaisseaux aliens détectent les humains grâce aux ondes cérébrales, la contre-mesure la plus efficace consiste à isoler ces ondes dans la base. Le bouclier psychique réduira de façon importante les chances de détection par les vaisseaux aliens.\"\n  STR_PSIONIC_LABORATORY_UFOPEDIA: \"Le laboratoire psionique peut évaluer le potentiel psionique de tous les soldats de la base et leur donner l'entraînement nécessaire pour utiliser leurs compétences psioniques. Chaque laboratoire peut entraîner jusqu'à 10 soldats. L'entraînement est attribué à la fin de chaque mois. Les compétences psioniques utilisées en association avec un Psi-Amp peuvent être utilisées pour les attaques psioniques pendant le combat.\"\n  STR_HYPER_WAVE_DECODER_UFOPEDIA: \"Les communications aliens se font par ondes supra-dimensionnelles qui voyagent presque instantanément. Le décodeur intercepte les transmissions d'ovnis, décode l'information et indique le type de l'ovni, la race d'alien et le type d'activité.\"\n  STR_HANGAR_UFOPEDIA: \"Chaque hangar peut contenir un vaisseau. Il y a des installations pour l'entretien, le ravitaillement et la réparation des vaisseaux X-Com. Chaque vaisseau posté dans une base doit avoir un hangar libre qui lui est affecté et qui ne peut être utilisé par aucun autre vaisseau, même si le vaisseau affecté est parti en mission.\"\n  STR_PISTOL_UFOPEDIA: \"Le pistolet X-Com standard est un semi-automatique à forte puissance pouvant contenir 12 cartouches.\"\n  STR_RIFLE_UFOPEDIA: \"Ce fusil de sniper haute précision a un viseur guidé au laser et peut contenir 20 cartouches de 6,7mm.\"\n  STR_HEAVY_CANNON_UFOPEDIA: \"Le canon lourd est une arme dévastatrice mais encombrante. Sa versatilité vient du fait qu'il peut contenir trois types de munitions : perce-armure, explosive et incendiaire.\"\n  STR_AUTO_CANNON_UFOPEDIA: \"Le canon automatique combine la versatilité et la puissance d'un canon lourd avec une cadence de tir plus rapide.\"\n  STR_ROCKET_LAUNCHER_UFOPEDIA: \"Le lance-roquettes est un système guidé au laser qui peut tirer trois différentes tailles de roquettes.\"\n  STR_LASER_PISTOL_UFOPEDIA: \"Le pistolet laser est une réalisation efficace de la technologie moderne. Il conjugue la commodité d'un pistolet avec un tir plus rapide et plus précis.\"\n  STR_LASER_RIFLE_UFOPEDIA: \"Le fusil laser est une version plus puissante et plus précise du pistolet laser.\"\n  STR_HEAVY_LASER_UFOPEDIA: \"Le laser lourd est encombrant, mais extrêmement efficace.\"\n  STR_GRENADE_UFOPEDIA: \"Cette grenade standard a un détonateur précis et sophistiqué, permettant un contrôle de précision.\"\n  STR_SMOKE_GRENADE_UFOPEDIA: \"Les grenades fumigènes sont utiles pour le camouflage durant des combats exposés. À utiliser avec précaution car elles peuvent également avantager l'ennemi.\"\n  STR_PROXIMITY_GRENADE_UFOPEDIA: \"Une grenade de proximité peut être lancée comme une grenade ordinaire, mais elle est déclenchée par tout mouvement à proximité après être tombée. Il faut beaucoup d'habileté et de précaution pour utiliser correctement ces armes.\"\n  STR_HIGH_EXPLOSIVE_UFOPEDIA: \"Cet explosif ne devrait être utilisé que pour démolir. Gardez vos soldats hors des lieux de démolition.\"\n  STR_MOTION_SCANNER_UFOPEDIA: \"Cet appareil sophistiqué utilise toutes sortes de détecteurs et d'algorithmes informatiques avancés pour identifier les unités ennemies mouvantes. Cependant, il faut de la pratique pour l'utiliser correctement. Cliquez sur l'icône 'Scanner de mouvement' sur l'affichage tactique. Sélectionnez 'Utiliser le scanner' dans le menu. L'affichage du scanner montre une flèche au centre qui représente la direction vers laquelle le soldat est orienté (le Nord est en haut). Les points clignotants montrent les unités qui ont récemment changé de position. Les grosses unités ou les unités rapides auront des points plus grands. Les unités statiques ne seront pas détectées.\"\n  STR_MEDI_KIT_UFOPEDIA: \"La trousse de soins contient des médicaments, des stimulants et des calmants. Pour utiliser la trousse de soins, votre soldat doit se tourner vers un autre soldat ayant besoin d'un traitement. Si ce dernier est assommé, il doit se tenir sur le corps. Cliquez sur l'icône 'Trousse de soins' et sélectionnez 'Utiliser la trousse de soins' dans le menu.{NEWLINE}SOIGNER> Les parties du corps en rouge représentent les blessures graves. Cliquez sur une partie du corps qui est blessée. Cliquez sur le bouton 'Soigner'. La blessure grave sera soignée et un peu de santé sera restaurée.{NEWLINE}STIMULANT> Cela va restaurer de l'énergie et ranimer les soldats inconscients (assommés). Pour ranimer un soldat inconscient, le soldat doit se tenir directement sur le corps.{NEWLINE}CALMANT> Cela va restaurer le moral des soldats blessés à un niveau équivalent à la santé perdue du soldat.\"\n  STR_PSI_AMP_UFOPEDIA: \"Le Psi-Amp ne peut être utilisé que par des soldats ayant des compétences psioniques. Durant le combat, cliquez sur le Psi-Amp, sélectionnez le type d'attaque et une unité cible avec le curseur. Il y a deux types d'attaques psioniques :{NEWLINE}PANIQUE DE L'UNITÉ> Si l'attaque réussit, cela réduira le moral de la cible et pourra la faire paniquer.{NEWLINE}CONTRÔLE DE L'ESPRIT> Si cela marche, vous prendrez alors le contrôle immédiat de l'unité ennemie comme si c'était l'une des vôtres. Ce type d'attaque est plus difficile à réussir.\"\n  STR_STUN_ROD_UFOPEDIA: \"Cet appareil ne peut être utilisé qu'en combat rapproché. Il permet d'assommer un organisme vivant sans le tuer grâce à des chocs électriques.\"\n  STR_MIND_PROBE_UFOPEDIA: \"La sonde d'esprit est une technique de communication alien qui est utilisée pour prendre l'information directement des ondes cérébrales. Les unités X-Com peuvent utiliser cette technique durant le combat pour connaître les caractéristiques des aliens. Cliquez sur la sonde d'esprit et l'option 'Utiliser la sonde d'esprit'. Puis, cliquez sur un alien avec le curseur.\"\n  STR_PLASMA_PISTOL_UFOPEDIA: \"Les pistolets à plasma sont une arme alien fatale basée sur l'accélération des particules à l'intérieur d'un minuscule champ antigravitationnel.\"\n  STR_PLASMA_RIFLE_UFOPEDIA: \"C'est une arme puissante et dévastatrice basée sur l'accélération des particules à l'intérieur d'un minuscule champ antigravitationnel.\"\n  STR_HEAVY_PLASMA_UFOPEDIA: \"C'est une arme très puissante et très dévastatrice basée sur l'accélération des particules à l'intérieur d'un minuscule champ antigravitationnel.\"\n  STR_BLASTER_LAUNCHER_UFOPEDIA: \"C'est un lance-missiles guidé alien qui tire de puissantes 'bombes blaster'. Lorsque vous cliquez pour tirer, vous verrez apparaître des 'points de repère' que la bombe blaster suivra. Lorsque vous avez positionné assez de points de repère, cliquez sur l'icône 'Tir spécial'.\"\n  STR_SMALL_LAUNCHER_UFOPEDIA: \"Un petit lanceur qui tire des bombes assommantes. Très utile pour capturer des aliens vivants.\"\n  STR_ALIEN_GRENADE_UFOPEDIA: \"Cette arme fonctionne de la même façon qu'une grenade terrestre - à l'exception qu'elle est plus puissante.\"\n  STR_SMALL_SCOUT: \"Petit éclaireur\"\n  STR_MEDIUM_SCOUT: \"Moyen éclaireur\"\n  STR_LARGE_SCOUT: \"Grand éclaireur\"\n  STR_HARVESTER: \"Moissonneur\"\n  STR_ABDUCTOR: \"Ravisseur\"\n  STR_TERROR_SHIP: \"Vaisseau de terreur\"\n  STR_BATTLESHIP: \"Vaisseau de combat\"\n  STR_SUPPLY_SHIP: \"Vaisseau de ravitaillement\"\n  STR_RATING: \"ÉVALUATION> {0}\"\n  STR_RATING_TERRIBLE: \"TERRIBLE!\"\n  STR_RATING_POOR: \"MÉDIOCRE!\"\n  STR_RATING_OK: \"PASSABLE\"\n  STR_RATING_GOOD: \"BIEN!\"\n  STR_RATING_EXCELLENT: \"EXCELLENT!\"\n  STR_SCORE: \"SCORE\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"RAPPORT MENSUEL DU PROJET X-COM\"\n  STR_MONTH: \"Mois> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"Le Conseil des Nations participant au financement est dans l'ensemble satisfait de vos progrès jusqu'ici.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"Le Conseil des Nations participant au financement est très satisfait de vos excellents progrès. Continuez comme ça.\"\n  STR_COUNCIL_IS_DISSATISFIED: \"Le Conseil des Nations participant au financement n'est pas satisfait de votre travail. Vous devez améliorer votre efficacité à combattre la menace alien, sinon, il risque de mettre fin au projet.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"Vous n'avez pas réussi à combattre l'invasion alien et le Conseil des Nations participant au financement a malheureusement décidé de mettre fin au projet. Chaque nation va s'occuper elle-même du problème comme elle l'entend. Nous ne pouvons qu'espérer arriver à un accord avec ces forces apparemment hostiles, et souhaiter que la population s'entendra avec les visiteurs aliens.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} est particulièrement satisfait de votre aptitude à combattre la menace localisée et est d'accord pour augmenter votre budget.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} sont particulièrement satisfaits de vos progrès dans le combat contre les incursions aliens localisées et sont d'accord pour augmenter votre budget.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} et {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} n'est pas satisfait de votre aptitude à combattre l'activité alien sur son territoire et a décidé de réduire sa participation financière.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} ne sont pas satisfaits de votre aptitude à combattre l'activité alien sur leur territoire et ont décidé de réduire leur participation financière.\"\n  STR_KNOTS: \"{0} nœuds\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} a signé un pacte secret avec des forces aliens inconnues et s'est retiré du projet.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} ont signé un pacte secret avec des forces aliens inconnues et se sont retirés du projet.\"\n  STR_MONTHLY_RATING: \"Évaluation mensuelle> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Changement de financement> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"Le Conseil n'est pas satisfait de votre situation financière. Vous devez réduire vos dettes en-dessous de 1 million $ ou le projet cessera.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"TRANSMISSIONS D'HYPERONDES DÉCODÉES\"\n  STR_CRAFT_TYPE: \"TYPE DE VAISSEAU\"\n  STR_RACE: \"RACE\"\n  STR_MISSION: \"MISSION\"\n  STR_ZONE: \"ZONE\"\n  STR_ALLOCATE_RESEARCH: \"Allouer la recherche\"\n  STR_ALLOCATE_MANUFACTURE: \"Allouer la fabrication\"\n  STR_NEW_YORK: \"New York\"\n  STR_WASHINGTON: \"Washington\"\n  STR_LOS_ANGELES: \"Los Angeles\"\n  STR_MONTREAL: \"Montréal\"\n  STR_HAVANA: \"La Havane\"\n  STR_MEXICO_CITY: \"Mexico\"\n  STR_CHICAGO: \"Chicago\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_DALLAS: \"Dallas\"\n  STR_BRASILIA: \"Brasilia\"\n  STR_BOGOTA: \"Bogota\"\n  STR_BUENOS_AIRES: \"Buenos Aires\"\n  STR_SANTIAGO: \"Santiago\"\n  STR_RIO_DE_JANEIRO: \"Rio de Janeiro\"\n  STR_LIMA: \"Lima\"\n  STR_CARACAS: \"Caracas\"\n  STR_LONDON: \"Londres\"\n  STR_PARIS: \"Paris\"\n  STR_BERLIN: \"Berlin\"\n  STR_MOSCOW: \"Moscou\"\n  STR_ROME: \"Rome\"\n  STR_MADRID: \"Madrid\"\n  STR_BUDAPEST: \"Budapest\"\n  STR_LAGOS: \"Lagos\"\n  STR_CAIRO: \"Le Caire\"\n  STR_CASABLANCA: \"Casablanca\"\n  STR_PRETORIA: \"Pretoria\"\n  STR_NAIROBI: \"Nairobi\"\n  STR_CAPE_TOWN: \"Le Cap\"\n  STR_KINSHASA: \"Kinshasa\"\n  STR_ANKARA: \"Ankara\"\n  STR_DELHI: \"Delhi\"\n  STR_KARACHI: \"Karachi\"\n  STR_BAGHDAD: \"Bagdad\"\n  STR_TEHRAN: \"Téhéran\"\n  STR_BOMBAY: \"Bombay\"\n  STR_CALCUTTA: \"Calcutta\"\n  STR_TOKYO: \"Tokyo\"\n  STR_BEIJING: \"Pékin\"\n  STR_BANGKOK: \"Bangkok\"\n  STR_MANILA: \"Manille\"\n  STR_SEOUL: \"Séoul\"\n  STR_SINGAPORE: \"Singapour\"\n  STR_JAKARTA: \"Djakarta\"\n  STR_SHANGHAI: \"Shanghai\"\n  STR_HONG_KONG: \"Hong Kong\"\n  STR_NOVOSIBIRSK: \"Novossibirsk\"\n  STR_CANBERRA: \"Canberra\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_MELBOURNE: \"Melbourne\"\n  STR_PERTH: \"Perth\"\n  STR_PSI_TRAINING: \"Entraînement psionique\"\n  STR_PSIONIC_TRAINING: \"ENTRAÎNEMENT PSIONIQUE\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Capacité restante du Psi-Labo> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"Force{NEWLINE}psionique\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"Compétence{NEWLINE}/progression psionique\"\n  STR_PSI_AMP: \"Psi-Amp\"\n  STR_IN_TRAINING: \"En{NEWLINE}entraînement?\"\n  STR_TARGETTED_BY: \"VISÉ PAR :\"\n  STR_WEAPONS_CREW_HWPS: \"ARMES/{NEWLINE}ÉQUIPAGE/PAL\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"est à court de carburant,{NEWLINE}retourne à la base\"\n  STR_SOLDIER_LIST: \"Liste des soldats\"\n  STR_RANK_: \"GRADE> {ALT}{0}\"\n  STR_MISSIONS: \"MISSIONS> {ALT}{0}\"\n  STR_KILLS: \"VICTIMES> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"GUÉRISON DE BLESSURE> {ALT}{0}\"\n  STR_TIME_UNITS: \"UNITÉS DE TEMPS\"\n  STR_STAMINA: \"ENDURANCE\"\n  STR_HEALTH: \"SANTÉ\"\n  STR_BRAVERY: \"COURAGE\"\n  STR_REACTIONS: \"RÉACTIONS\"\n  STR_FIRING_ACCURACY: \"PRÉCISION AU TIR\"\n  STR_THROWING_ACCURACY: \"PRÉCISION AU LANCER\"\n  STR_STRENGTH: \"FORCE\"\n  STR_PSIONIC_STRENGTH: \"FORCE PSIONIQUE\"\n  STR_PSIONIC_SKILL: \"COMPÉTENCE PSIONIQUE\"\n  STR_NEW_RANK: \"NOUVEAU GRADE\"\n  STR_PROMOTIONS: \"Promotions\"\n  STR_SOLDIERS_UC: \"SOLDATS\"\n  STR_TANK_CANNON_UFOPEDIA: \"Les plates-formes d'armes lourdes automatiques sont conçues pour compléter l'escouade X-Com. Ces unités, ayant à la fois une grande puissance de feu et un blindage résistant, sont idéales pour les combats à terrain ouvert. Assurez-vous que vous avez suffisamment d'obus dans vos stocks pour réarmer les tanks. Ils s'arment automatiquement lorsque vous les affectez à une escouade.\"\n  STR_TANK_ROCKET_LAUNCHER_UFOPEDIA: \"Cette plate-forme d'armes lourdes automatique est armée de puissantes roquettes. C'est une arme dévastatrice pour tout ennemi alien. Assurez-vous que vos stocks sont approvisionnés en roquettes de PAL.\"\n  STR_TANK_LASER_CANNON_UFOPEDIA: \"Les armes laser sont un complément utile aux PAL. Elles ont une grande puissance de feu et n'ont pas de limite de munitions.\"\n  STR_HOVERTANK_PLASMA_UFOPEDIA: \"La technologie alien offre une nouvelle vie aux PAL. La maniabilité du voyage aérien et la puissance des rayons à plasma est une combinaison mortelle.\"\n  STR_HOVERTANK_LAUNCHER_UFOPEDIA: \"Cet aérotank possède un lance-boules de fusion capable de faire d'immenses dégâts. Utilisez-le avec beaucoup de précaution. Il vous faudra fabriquer les boules de fusion pour charger ces PAL. Une boule de fusion est une arme guidée intelligente. Pour tirer, vous devez sélectionner un certain nombre de 'points de repère' avec le curseur puis cliquer sur l'icône 'Lancer un missile' pour tirer la boule de fusion.\"\n  STR_HEAVY_PLASMA_CLIP_UFOPEDIA: \"Cet appareil compact est utilisé comme munition pour le canon à plasma. Il contient une petite quantité d'élérium.\"\n  STR_PLASMA_RIFLE_CLIP_UFOPEDIA: \"Ce petit objet est utilisé comme source d'énergie pour le fusil à plasma - une arme alien de puissance moyenne. Contient une petite quantité d'élérium.\"\n  STR_PLASMA_PISTOL_CLIP_UFOPEDIA: \"Source d'énergie pour le petit pistolet à plasma alien. Contient de l'élérium - source de toute puissance alien.\"\n  STR_STUN_BOMB_UFOPEDIA: \"La bombe assommante est utilisée pour capturer des spécimens humains vivants, mais elle peut aussi être utilisée contre la plupart des races aliens. On la tire d'un petit lanceur.\"\n  STR_ALIEN_RESEARCH_UFOPEDIA: \"La mission de recherche alien est faite pour recueillir des données de base sur la Terre et ses habitants. Ils utilisent généralement des petits véhicules, et atterrissent parfois dans les zones désertes. Ce type d'activité alien est une moindre menace pour X-Com, et ne touche pas beaucoup les gouvernements ou les populations.\"\n  STR_ALIEN_HARVEST_UFOPEDIA: \"Les aliens utilisent la faune terrienne de différentes façons. Les animaux sont secrètement enlevés, puis ramenés après qu'on leur ait enlevé plusieurs organes. Les témoignages de mutilations du bétail coïncident généralement avec des apparitions d'ovnis. Ce type d'activité alien préoccupe beaucoup les gouvernements et provoque une grande inquiétude parmi la population. Ce type d'activité se produit généralement en campagne. La théorie derrière cette 'moisson alien' serait que les races aliens ont à l'origine 'ensemencé' la planète de sa flore et de sa faune, et qu'ils reviennent aujourd'hui pour récolter les fruits qu'ils ont semés.\"\n  STR_ALIEN_ABDUCTION_UFOPEDIA: \"C'est le type d'activité alien le plus insidieux. De nombreux témoignages font état d'enlèvements par les aliens, et ceci malgré les efforts faits par les aliens pour effacer cette expérience de la mémoire de leurs victimes. Les personnes enlevées disent avoir été soumises à des examens physiques humiliants, et parlent même d'implantations de fœtus aliens et d'expériences génétiques étranges. Le but de cette activité semble être lié à la mutation génétique et à la manipulation du propre code génétique des aliens. Cette activité provoque une vive inquiétude, et se produit dans les zones peuplées ou les villes.\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"Les gouvernements de la Terre peuvent être infiltrés par des agents aliens ayant une apparence humaine. Cela peut aboutir à des contacts entre aliens et gouvernements au plus haut niveau. Cette activité se caractérise à son plus haut point par une intense activité des ovnis dans les environs des grandes villes. Les aliens vont essayer de signer un pacte avec un gouvernement terrien en lui offrant la connaissance de leur technologie supérieure. En échange, le gouvernement permettra aux aliens de continuer leurs activités en toute tranquillité. Cette mission alien représente la pire menace pour X-Com. Si un gouvernement accepte de signer un pacte, alors il cessera son financement.\"\n  STR_ALIEN_BASE_UFOPEDIA: \"Les aliens vont construire des bases souterraines secrètes dans des endroits isolés. Après quelques vols de reconnaissance, une intense activité des ovnis se produira pendant la construction de la base. On sait que ces bases ont des laboratoires d'expérimentations pour les humains qui ont été enlevés, et du ravitaillement pour une activité plus poussée dans la région. La présence de bases aliens va créer une intense activité alien sans la présence d'ovnis. Afin de localiser une base, un vaisseau X-Com doit patrouiller dans une région pendant quelques heures pour avoir une chance de la détecter.\"\n  STR_ALIEN_TERROR_UFOPEDIA: \"Pour terroriser une ville, les aliens vont déployer des forces spéciales avec des pouvoirs terrifiants. Les civils seront directement menacés, et les gouvernements seront forcés d'évacuer des zones entières. Le but essentiel de cette activité est de créer suffisamment d'hystérie collective pour que les gouvernements menacent le projet X-Com.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"Si les intercepteurs X-Com réussissent particulièrement bien à abattre des ovnis, alors les aliens pourraient commettre des actions de représailles. Cela pourrait aboutir à une attaque directe contre une base X-Com. Cependant, les aliens doivent trouver cette base avant de l'attaquer, et tant que les ovnis sont tenus à l'écart, il y a peu de risque d'une attaque.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"Une fois qu'une base alien est construite, elle est régulièrement approvisionnée par un vaisseau de ravitaillement spécial. Si l'un de ces vaisseaux est détecté lors de son atterrissage, vous pouvez alors être certain qu'il y a une base alien à proximité.\"\n  STR_SMALL_SCOUT_UFOPEDIA: \"Ce minuscule vaisseau est utilisé essentiellement pour la reconnaissance ou la recherche. Il précède normalement des vaisseaux plus grands au début d'une mission alien.\"\n  STR_MEDIUM_SCOUT_UFOPEDIA: \"Un vaisseau éclaireur de taille moyenne qui ne représente pas une grande menace pour les forces terrestres. Il apparaît normalement avant des vaisseaux plus grands durant les missions.\"\n  STR_LARGE_SCOUT_UFOPEDIA: \"Le vaisseau éclaireur alien le plus grand est un vaisseau utilisé dans tous les types de missions aliens.\"\n  STR_HARVESTER_UFOPEDIA: \"Le moissonneur a une trappe à sa base et est équipé d'un treuil pour hisser le bétail ou d'autres animaux. Les scalpels laser sont utilisés pour extraire les morceaux désirés et la carcasse est jetée au sol. Il y a également des conteneurs de stockage pour les parties du corps.\"\n  STR_ABDUCTOR_UFOPEDIA: \"Ce vaisseau est équipé d'une salle d'examen utilisée pour d'horribles expériences sur des sujets humains. La victime est paralysée par des pouvoirs télépathiques, mais reste consciente sur la table d'opération.\"\n  STR_TERROR_SHIP_UFOPEDIA: \"Le vaisseau de terreur est équipé d'installations lui permettant de transporter de lourdes armes de terreur aliens ou des créatures. Il est utilisé pour transporter ces terroristes aliens jusque dans les zones peuplées.\"\n  STR_BATTLESHIP_UFOPEDIA: \"Le vaisseau de combat est le vaisseau alien le plus grand et le plus puissant. C'est normalement le vaisseau principal des missions aliens, il est équipé d'armes puissantes et de nombreux membres d'équipage.\"\n  STR_SUPPLY_SHIP_UFOPEDIA: \"Le vaisseau de ravitaillement est utilisé durant la construction de bases aliens ou pour l'approvisionnement de bases existantes. Il transporte des conteneurs de nourriture alien et des chambres de reproduction.\"\n  STR_DISMANTLE: \"Démonter\"\n  STR_FACILITY_IN_USE: \"INSTALLATION EN UTILISATION\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"IMPOSSIBLE DE DÉMONTER L'INSTALLATION!{NEWLINE}Toutes les installations de la base doivent être reliées à l'ascenseur d'accès.\"\n  STR_TRANSFER_ITEMS_TO: \"Transférer les objets vers {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"PAS DE CENTRE DE DÉTENTION DES ALIENS POUR LE TRANSFERT!{SMALLLINE}Les aliens vivants ont besoin d'une installation de centre de détention des aliens pour survivre.\"\n  STR_AMOUNT_AT_DESTINATION: \"QUANTITÉ À{NEWLINE}DESTINATION\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"L'alien meurt car il n'y a pas d'installation de centre de détention des aliens.\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"AUCUN LOGEMENT DE LIBRE!{SMALLLINE}La base de destination n'a pas assez de place dans les quartiers d'habitation pour l'équipage affecté au vaisseau.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"PAS ASSEZ D'ESPACE DE STOCKAGE!{SMALLLINE}La base de destination n'a pas assez de place dans les entrepôts pour l'équipement attribué au vaisseau.\"\n  STR_ITEMS_ARRIVING: \"Le matériel arrive\"\n  STR_DESTINATION_UC: \"DESTINATION\"\n  STR_PISTOL: \"Pistolet\"\n  STR_PISTOL_CLIP: \"Chargeur de pistolet\"\n  STR_RIFLE: \"Fusil\"\n  STR_RIFLE_CLIP: \"Chargeur de fusil\"\n  STR_HEAVY_CANNON: \"Canon lourd\"\n  STR_HC_AP_AMMO: \"Munitions CL-PA\"\n  STR_HC_HE_AMMO: \"Munitions CL-E\"\n  STR_HC_I_AMMO: \"Munitions CL-I\"\n  STR_AUTO_CANNON: \"Canon automatique\"\n  STR_AC_AP_AMMO: \"Munitions CA-PA\"\n  STR_AC_HE_AMMO: \"Munitions CA-E\"\n  STR_AC_I_AMMO: \"Munitions CA-I\"\n  STR_ROCKET_LAUNCHER: \"Lance-roquettes\"\n  STR_SMALL_ROCKET: \"Petite roquette\"\n  STR_LARGE_ROCKET: \"Grande roquette\"\n  STR_INCENDIARY_ROCKET: \"Roquette incendiaire\"\n  STR_GRENADE: \"Grenade\"\n  STR_SMOKE_GRENADE: \"Grenade fumigène\"\n  STR_PROXIMITY_GRENADE: \"Grenade de proximité\"\n  STR_HIGH_EXPLOSIVE: \"Explosif\"\n  STR_STUN_ROD: \"Matraque électrique\"\n  STR_HEAVY_PLASMA: \"Canon à plasma\"\n  STR_HEAVY_PLASMA_CLIP: \"Chargeur de canon à plasma\"\n  STR_PLASMA_RIFLE: \"Fusil à plasma\"\n  STR_PLASMA_RIFLE_CLIP: \"Chargeur de fusil à plasma\"\n  STR_PLASMA_PISTOL: \"Pistolet à plasma\"\n  STR_PLASMA_PISTOL_CLIP: \"Chargeur de pistolet à plasma\"\n  STR_BLASTER_LAUNCHER: \"Lance-blaster\"\n  STR_BLASTER_BOMB: \"Bombe blaster\"\n  STR_SMALL_LAUNCHER: \"Petit lanceur\"\n  STR_STUN_BOMB: \"Bombe assommante\"\n  STR_ALIEN_GRENADE: \"Grenade alien\"\n  STR_ELERIUM_115: \"Élérium-115\"\n  STR_MIND_PROBE: \"Sonde d'esprit\"\n  STR_SECTOID_CORPSE: \"Corps de Sectoïde\"\n  STR_SNAKEMAN_CORPSE: \"Corps d'Homme-Serpent\"\n  STR_ETHEREAL_CORPSE: \"Corps d'Ethereal\"\n  STR_MUTON_CORPSE: \"Corps de Muton\"\n  STR_FLOATER_CORPSE: \"Corps de Floater\"\n  STR_CELATID_CORPSE: \"Corps de Celatid\"\n  STR_SILACOID_CORPSE: \"Corps de Silacoïde\"\n  STR_CHRYSSALID_CORPSE: \"Corps de Chrysalide\"\n  STR_REAPER_CORPSE: \"Corps de Reaper\"\n  STR_SECTOPOD_CORPSE: \"Corps de Sectopode\"\n  STR_CYBERDISC_CORPSE: \"Corps de Cyberdisque\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"Pas assez de munitions pour armer la PAL{SMALLLINE}Chaque PAL requiert {0} {1}.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Pas assez d'équipement pour rééquiper entièrement l'escouade\"\n  STR_MARS_CYDONIA_LANDING: \"Mars : Atterrissage sur Cydonia\"\n  STR_MARS_CYDONIA_LANDING_BRIEFING: \"Votre vaisseau Avenger a atterri dans la région de Cydonia, sur la surface de Mars. Nos informations indiquent que l'une des pyramides contient un ascenseur vert menant à un complexe souterrain. Lorsque vous aurez rassemblé tous vos soldats près de l'ascenseur, cliquez sur l'icône 'Abandonner la mission' pour passer à l'étape suivante.\"\n  STR_MARS_THE_FINAL_ASSAULT: \"Mars : L'assaut final\"\n  STR_MARS_THE_FINAL_ASSAULT_BRIEFING: \"L'ascenseur de la pyramide emmène vos soldats fatigués sous la surface de la planète. Ils arrivent au cœur d'un grand complexe de tunnels et de salles. Le cerveau alien est caché quelque part dans le labyrinthe. Il doit être détruit si vous voulez sauver la Terre de l'esclavage alien.{NEWLINE}{NEWLINE}Bonne chance!\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Vous aurez besoin d'étudier{NEWLINE}{0}{NEWLINE}afin de pouvoir produire{NEWLINE}{1}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"Les aliens ont détruit la base {0} non défendue\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"Les agents X-Com ont localisé une base alien en {0}\"\n  STR_STANDOFF: \"RESTER À DISTANCE\"\n  STR_CAUTIOUS_ATTACK: \"ATTAQUE PRUDENTE\"\n  STR_STANDARD_ATTACK: \"ATTAQUE STANDARD\"\n  STR_AGGRESSIVE_ATTACK: \"ATTAQUE AGRESSIVE\"\n  STR_DISENGAGING: \"DÉSENGAGEMENT\"\n  STR_UFO_HIT: \"L'OVNI EST TOUCHÉ!\"\n  STR_UFO_CRASH_LANDS: \"L'OVNI S'EST ÉCRASÉ!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Réduire à une distance sûre seulement\"\n  STR_UFO_RETURN_FIRE: \"L'OVNI RIPOSTE!\"\n  STR_INTERCEPTOR_DAMAGED: \">>> INTERCEPTEUR ENDOMMAGÉ <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> INTERCEPTEUR DÉTRUIT <<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"L'OVNI SÈME L'INTERCEPTEUR!\"\n  STR_ALIENS_TERRORISE: \"TERREUR ALIEN\"\n  STR_LONG_RANGE_DETECTION: \"Radar à longue portée\"\n  STR_STORES_UC: \"STOCKS\"\n  STR_DIFFICULTY_LEVEL: \"Niveau de difficulté\"\n  STR_INTERCEPT: \"INTERCEPTER\"\n  STR_BASES: \"BASES\"\n  STR_GRAPHS: \"GRAPHIQUES\"\n  STR_UFOPAEDIA_UC: \"OVNIPÉDIE\"\n  STR_OPTIONS_UC: \"OPTIONS\"\n  STR_FUNDING_UC: \"BUDGET\"\n  STR_5_SECONDS: \"5 s\"\n  STR_1_MINUTE: \"1 min\"\n  STR_5_MINUTES: \"5 min\"\n  STR_30_MINUTES: \"30 min\"\n  STR_1_HOUR: \"1 heure\"\n  STR_1_DAY: \"1 jour\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"Tableau de performance X-Com\"\n  STR_ENTER_NAME: \"Entrez un nom\"\n  STR_PERFORMANCE_RATING: \"Évaluation de performance\"\n  STR_VICTORY_DATE: \"Date de victoire\"\n  STR_ELECTRO_FLARE: \"Torche électronique\"\n  STR_ELECTRO_FLARE_UFOPEDIA: \"Cet appareil compact produit une lumière vive lorsqu'il est lancé, permettant d'éclairer les unités ennemies à proximité durant les missions nocturnes.\"\n  STR_MONTHLY_COSTS: \"Coûts mensuels\"\n  STR_CRAFT_RENTAL: \"Location de vaisseaux\"\n  STR_SALARIES: \"Salaires\"\n  STR_BASE_MAINTENANCE: \"Entretien de la base\"\n  STR_COST_PER_UNIT: \"Coût par unité\"\n  STR_QUANTITY: \"Quantité\"\n  STR_TOTAL: \"Total\"\n  STR_IN_PSIONIC_TRAINING: \"En entraînement psionique\"\n  STR_BLASTER_BOMB_UFOPEDIA: \"Ce dispositif est un missile explosif équipé d'un système de guidage intelligent. Il est tiré d'un lance-blaster.\"\n  STR_FRONT_ARMOR: \"Armure avant\"\n  STR_LEFT_ARMOR: \"Armure gauche\"\n  STR_RIGHT_ARMOR: \"Armure droite\"\n  STR_REAR_ARMOR: \"Armure arrière\"\n  STR_UNDER_ARMOR: \"Armure de dessous\"\n  STR_ROUNDS: \"Munitions\"\n  STR_UNIT: \"UNITÉ> {0}\"\n  STR_ENERGY: \"ÉNERGIE\"\n  STR_MORALE: \"MORAL\"\n  STR_ARMOR_: \"ARMURE> {0}\"\n  STR_FRONT_ARMOR_UC: \"ARMURE AVANT\"\n  STR_LEFT_ARMOR_UC: \"ARMURE GAUCHE\"\n  STR_RIGHT_ARMOR_UC: \"ARMURE DROITE\"\n  STR_REAR_ARMOR_UC: \"ARMURE ARRIÈRE\"\n  STR_SKILLS: \"COMPÉTENCES> {0}\"\n  STR_LEVEL: \"NIVEAU> {0}\"\n  STR_HEAD: \"TÊTE\"\n  STR_TORSO: \"TORSE\"\n  STR_RIGHT_ARM: \"BRAS DROIT\"\n  STR_LEFT_ARM: \"BRAS GAUCHE\"\n  STR_RIGHT_LEG: \"JAMBE DROITE\"\n  STR_LEFT_LEG: \"JAMBE GAUCHE\"\n  STR_PAIN_KILLER: \"CALMANT\"\n  STR_STIMULANT: \"STIMULANT\"\n  STR_HEAL: \"SOIGNER\"\n  STR_TIME_UNITS_SHORT: \"UT>{ALT}{0}\"\n  STR_WEIGHT: \"Poids> {ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"Réact> {ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"Cmp.P> {ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"For.P> {ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Objet alien\"\n  STR_AMMO_ROUNDS_LEFT: \"MUNITIONS{NEWLINE}RESTANTES{NEWLINE}{ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Calm> {ALT}{0}{ALT}{NEWLINE}Stim> {ALT}{1}{ALT}{NEWLINE}Soin> {ALT}{2}\"\n  STR_THROW: \"Lancer\"\n  STR_AUTO_SHOT: \"Tir auto.\"\n  STR_SNAP_SHOT: \"Tir rapide\"\n  STR_AIMED_SHOT: \"Tir précis\"\n  STR_STUN: \"Assommer\"\n  STR_PRIME_GRENADE: \"Amorcer la grenade\"\n  STR_USE_SCANNER: \"Utiliser le scanner\"\n  STR_USE_MEDI_KIT: \"Utiliser la trousse\"\n  STR_LAUNCH_MISSILE: \"Tirer la bombe\"\n  STR_ACCURACY_SHORT: \"Pr>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Pas assez d'unités de temps!\"\n  STR_NOT_ENOUGH_ENERGY: \"Pas assez d'énergie!\"\n  STR_NO_ROUNDS_LEFT: \"Plus de munitions!\"\n  STR_NO_AMMUNITION_LOADED: \"Pas de munitions de chargées!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Mauvais type de munition pour cette arme!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"L'arme est déjà chargée!\"\n  STR_NO_LINE_OF_FIRE: \"Pas de ligne de tir!\"\n  STR_GRENADE_IS_ACTIVATED: \"La grenade est activée!\"\n  STR_GRENADE_IS_DEACTIVATED: \"La grenade est désactivée!\"\n  STR_THERE_IS_NO_ONE_THERE: \"Il n'y a personne ici!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Impossible d'utiliser l'objet alien avant son étude!\"\n  STR_OUT_OF_RANGE: \"Hors de portée!\"\n  STR_UNABLE_TO_THROW_HERE: \"Impossible de lancer à cet endroit!\"\n  STR_SET_TIMER: \"Détonateur\"\n  STR_HIDDEN_MOVEMENT: \"MOUVEMENTS CACHÉS\"\n  STR_TURN: \"TOUR> {0}\"\n  STR_SIDE: \"CAMP> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Cliquez pour continuer\"\n  STR_MIND_CONTROL: \"Contrôle de l'esprit\"\n  STR_PANIC_UNIT: \"Faire paniquer l'unité\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Attaque psionique réussie\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Contrôle de l'esprit réussi\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}est devenu fou furieux\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}est devenue folle furieuse\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}panique et s'affole\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}panique et s'affole\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Aliens\"\n  STR_RIGHT_HAND: \"MAIN DROITE\"\n  STR_LEFT_HAND: \"MAIN GAUCHE\"\n  STR_RIGHT_SHOULDER: \"ÉPAULE DROITE\"\n  STR_LEFT_SHOULDER: \"ÉPAULE GAUCHE\"\n  STR_BACK_PACK: \"SAC À DOS\"\n  STR_BELT: \"CEINTURE\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}est sous contrôle alien\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}est sous contrôle alien\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}a perdu connaissance\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}a perdu connaissance\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}est mort d'une blessure mortelle\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}est morte d'une blessure mortelle\"\n  STR_USE_MIND_PROBE: \"Utiliser la sonde\"\n  STR_FATAL_WOUNDS: \"BLESSURES MORTELLES\"\n  STR_UNDER_ARMOR_UC: \"ARMURE DE DESSOUS\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Unités de temps réservées au tir rapide\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Unités de temps réservées au tir automatique\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Unités de temps réservées au tir précis\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Unités de temps réservées pour s'agenouiller\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"Unités de temps réservées pour tirer à genoux\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} unité dans le vaisseau X-Com\"\n    many: \"{N} unités dans le vaisseau X-Com\"\n    other: \"{N} unités dans le vaisseau X-Com\"\n  STR_UNITS_OUTSIDE:\n    one: \"{N} unité laissée dehors\"\n    many: \"{N} unités laissées dehors\"\n    other: \"{N} unités laissées dehors\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} unité à l'entrée\"\n    many: \"{N} unités à l'entrée\"\n    other: \"{N} unités à l'entrée\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} unité à la sortie cible\"\n    many: \"{N} unités à la sortie cible\"\n    other: \"{N} unités à la sortie cible\"\n  STR_ABORT_MISSION_QUESTION: \"Abandonner la mission?\"\n  STR_CORPSE: \"Corps\"\n  STR_UNLOAD_CRAFT: \"Décharger\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}a été tué\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}a été tuée\"\n  STR_HIT_MELEE: \"Frapper\"\n  STR_GROUND: \"SOL\"\n  STR_LIVING_QUARTERS_PLURAL: \"Quartiers d'habitation\"\n  STR_LIST_ITEM: \"OBJET\"\n  STR_PERSONAL_ARMOR_UFOPEDIA: \"Fabriquée avec les alliages aliens récemment découverts, cette nouvelle armure donne à nos hommes une meilleure chance au combat contre la menace alien.\"\n  STR_POWER_SUIT_UFOPEDIA: \"D'une puissante nouvelle protection pour les soldats, cette armure est alimentée par une source d'énergie à l'élérium et amplifie grandement la vitesse et la force de celui ou celle qui la porte. Elle offre la meilleure protection pour les troupes de combat.\"\n  STR_FLYING_SUIT_UFOPEDIA: \"Une version améliorée de l'armure énergétique, incorporant la technologie de navigation antigravitationnelle alien pour permettre une totale liberté de mouvements sur le champ de bataille.\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"Tous les aliens sont morts lors du crash.{NEWLINE}Procédure de récupération automatique activée\"\n  STR_RESET: \"Réinitialiser\"\n  STR_MEMORIAL: \"Mémorial\"\n  STR_DATE_UC: \"DATE\"\n  STR_SOLDIERS_RECRUITED_UC: \"SOLDATS RECRUTÉS> {ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"SOLDATS PERDUS> {ALT}{0}\"\n  MAP_CULTA: \"Ferme\"\n  MAP_FOREST: \"Forêt\"\n  MAP_JUNGLE: \"Jungle\"\n  MAP_MOUNT: \"Montagne\"\n  MAP_DESERT: \"Désert\"\n  MAP_POLAR: \"Polaire\"\n  MAP_URBAN: \"Ville\"\n  MAP_UBASE: \"Base alien\"\n  MAP_XBASE: \"Base X-Com\"\n  MAP_MARS: \"Mars\"\n  STR_MIXED: \"Mixte\"\n  STR_REMOVE_SELECTED: \"Enlever ceux sélectionnés\"\n  STR_LIVE_ALIENS: \"Spécimens{NEWLINE}vivants\"\n  STR_DEAD_ALIENS: \"Spécimens{NEWLINE}rejetés\"\n  STR_UNDER_INTERROGATION: \"En cours{NEWLINE}d'interrogation\"\n  STR_CONTAINMENT_EXCEEDED: \"LIMITES DE DÉTENTION D'ALIENS EXCÉDÉES!{SMALLLINE}Pas assez d'espace de détention à {0}. Vous devez enlever l'excès d'aliens de la détention (qui mourront ensuite).\"\n  STR_MANAGE_CONTAINMENT: \"Gestion de la détention des aliens\"\n  STR_STORAGE_EXCEEDED: \"ESPACE DE STOCKAGE EXCÉDÉE!{SMALLLINE}Pas assez d'espace de stockage à {0}. Vous devez vendre l'excès de matériel.\"\n  STR_GO_TO_BASE: \"Aller à la base\"\n  STR_MELEE_ACCURACY: \"PRÉCISION EN MÊLÉE\"\n  STR_SELL_PRODUCTION: \"VENDRE\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Les deux mains doivent être vides!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Pas assez d'objets pour copier le modèle!\"\n  STR_UNLOAD_WEAPON: \"Décharger l'arme\"\n  STR_ALL_ITEMS: \"Tous les objets\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"AUCUN ÉQUIPEMENT DE PLUS N'EST AUTORISÉ À BORD !{SMALLLINE}Vous êtes uniquement autorisé de transporter un maximum d'{N} objet sur ce vaisseau.\"\n    many: \"AUCUN ÉQUIPEMENT DE PLUS N'EST AUTORISÉ À BORD!{SMALLLINE}Vous êtes uniquement autorisé de transporter un maximum de {N} objets sur ce vaisseau.\"\n    other: \"AUCUN ÉQUIPEMENT DE PLUS N'EST AUTORISÉ À BORD!{SMALLLINE}Vous êtes uniquement autorisé de transporter un maximum de {N} objets sur ce vaisseau.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}CENTRE DE CONTRÔLE DÉTRUIT{NEWLINE}Retournez à l'entrée et abandonnez la mission.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"Les installations X-Com ne peuvent pas être construites sous l'eau\"\n  STR_LEVEL_SHORT: \"{0}\"\n  STR_PERSONNEL: \"Personnel\"\n  STR_CRAFT_ARMAMENT: \"Vaisseaux et armement\"\n  STR_COMPONENTS: \"Composants\"\n  STR_SOLDIERS_RECRUITED: \"Soldats recrutés\"\n  STR_SOLDIERS_LOST: \"Soldats perdus\"\n  STR_TOTAL_UFOS: \"Ovnis détectés\"\n  STR_TOTAL_ALIEN_BASES: \"Bases aliens découvertes\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"FPS\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"CPS\"\n  FEMALE_CIVILIAN: \"Civile\"\n  MALE_CIVILIAN: \"Civil\"\n  CYBERDISC_WEAPON: \"Arme de Cyberdisque\"\n  REAPER_WEAPON: \"Arme de Reaper\"\n  CHRYSSALID_WEAPON: \"Arme de Chrysalide\"\n  CELATID_WEAPON: \"Arme de Celatid\"\n  SILACOID_WEAPON: \"Arme de Silacoïde\"\n  SECTOPOD_WEAPON: \"Arme de Sectopode\"\n  ZOMBIE_WEAPON: \"Arme de Zombie\"\n  ALIEN_PSI_WEAPON: \"Arme psionique alien\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/fr.yml",
    "content": "fr:\n  STR_AVENGER_UFOPEDIA: \"VAISSEAU SPATIAL  DE  TRANSPORT ET DE COMBAT.  RÉPLICATION ULTIME DE LA TECHNOLOGIE EXTRATERRESTRE.\"\n  STR_INTERCEPTOR_UFOPEDIA: \"CHASSEUR AVEC MOTEURS À DÉTONATION PULSÉE ET SYSTÈMES ÉLECTRONIQUES BLINDÉS.  LA PLUS SOPHISTIQUÉE DES TECHNOLOGIES TERRESTRES.\"\n  STR_LIGHTNING_UFOPEDIA: \"VAISSEAU SPATIAL DÉDIÉ AU TRANSPORT ET AU COMBAT.  UNE COPIE RUDIMENTAIRE, MAIS AVEC DES SYSTÈMES EFFICACES DE PROPULSION EXTRATERRESTRE.\"\n  STR_SKYRANGER_UFOPEDIA: \"TRANSPORTEUR DE TROUPES.  UN AVION-CARGO TRÈS RAPIDE, A DÉCOLLAGE ET ATTERRISSAGE VERTICAUX (A.D.A.V.).\"\n  STR_FIRESTORM_UFOPEDIA: \"VAISSEAU SPATIAL DE COMBAT.  UNE COPIE DE LA SOUCOUPE VOLANTE EXTRATERRESTRE CLASSIQUE, AVEC UNITÉ CENTRALE DE PROPULSION.\"\n  STR_STINGRAY_UFOPEDIA: \"MISSILE AIR-AIR SOPHISTIQUÉ AVEC DES SYSTÈMES ÉLECTRONIQUES BLINDÉS.\"\n  STR_AVALANCHE_UFOPEDIA: \"MISSILE AIR-AIR À OGIVE NUCLÉAIRE, MAIS TRÈS LOURD.\"\n  STR_CANNON_UFOPEDIA: \"CANON TRÈS PUISSANT À MUNITIONS PERFORANTES, POUVANT PÉNÉTRER 40 CM D'ACIER.\"\n  STR_FUSION_BALL_UFOPEDIA: \"CE LANCE-MISSILE TIRE UNE MUNITION DE LA FORME D'UNE BOULE, PROPULSÉE PAR UNE RÉACTION ANTIMATIÈRE.  LA BOULE PROVOQUE UNE IMPLOSION D'ONDES GRAVITATIONNELLES.\"\n  STR_LASER_CANNON_UFOPEDIA: \"RAYON LASER CONVENTIONNEL ACTIVÉ PAR UNE CHAMBRE À RÉACTION ANTIMATIÈRE.\"\n  STR_PLASMA_BEAM_UFOPEDIA: \"LE RAYON GRAVITATIONNEL PRODUIT, VIA L'IMPLOSION D'UN CHAMP GRAVITATIONNEL, UN TIR PRÉCIS.\"\n  STR_SECTOID_UFOPEDIA: \"La hiérarchie sectoïde va des soldats aux chefs d'escouades ayant d'importantes compétences psioniques.  Ces pouvoirs psioniques peuvent être utilisés pour démoraliser les soldats durant le combat, ou même pour prendre possession de leur esprit.  Ils ont tendance à s'adonner aux enlèvements d'humains et à la mutilation du bétail.  L'enlèvement permet l'extraction de codes génétiques pour le croisement de races et le développement de clones afin d'infiltrer la société humaine.  Cette race semble vouloir développer des hybrides génétiques supérieurs pour augmenter l'efficacité de leur société-ruche.\"\n  STR_SECTOID_AUTOPSY: \"Autopsie du Sectoïde\"\n  STR_SECTOID_AUTOPSY_UFOPEDIA: \"L'autopsie montre des organes digestifs atrophiés et une structure simple.  Le cerveau et les yeux sont très bien développés.  La structure suggère une modification génétique ou une mutation.  La petite bouche et le nez semblent n'avoir que peu de fonctions.  Les doigts palmés, et les pieds plats suggèrent des origines aquatiques.  Il n'y a pas d'organes reproducteurs, et aucun indice sur la façon dont cette espèce se reproduit.  C'est certainement une espèce créée par génie génétique.\"\n  STR_SNAKEMAN_UFOPEDIA: \"Cette race s'est développée dans un environnement extrêmement hostile.  Ils sont très forts et peuvent résister à d'extrêmes variations de température.  Leur mobilité est basée sur un 'pied' géant de la forme d'un serpent qui protège tous les organes vitaux.  Leurs objectifs semblent être purement et simplement ceux de prédateurs et ils semblent obéir à une autre intelligence qui dicte leurs incursions de style militaire sur la Terre.\"\n  STR_SNAKEMAN_AUTOPSY: \"Autopsie de l'Homme-Serpent\"\n  STR_SNAKEMAN_AUTOPSY_UFOPEDIA: \"La peau est extrêmement dure et résistante à la chaleur.  Le système cardio-vasculaire fait partie du système musculaire qui utilise le principe hydraulique pour créer un mouvement.  Le seul vrai muscle est le 'cœur'.  Le système de reproduction semble très efficace.  La reproduction est asexuée, et chaque homme-serpent porte jusqu'à cinquante œufs à la fois dans son corps.  Si cette espèce n'était pas combattue, elle représenterait une grave menace pour la vie sur la Terre.\"\n  STR_ETHEREAL_UFOPEDIA: \"Cet être a un terrifiant pouvoir mental permettant la télépathie et la télékinésie.  Les capacités physiques apparemment faibles de cette créature sont compensées par son pouvoir mental.  Nous ne savons pas comment fonctionne ce pouvoir mental, car il semble défier les lois de la physique telles que nous les connaissons.  Ces êtres sont extrêmement dangereux dans toute situation de combat où ils s'en remettent à leur pouvoir mental.  Ils apparaissent rarement sur Terre car ils semblent compter sur d'autres races pour poursuivre leurs objectifs.\"\n  STR_ETHEREAL_AUTOPSY: \"Autopsie d'Ethereal\"\n  STR_ETHEREAL_AUTOPSY_UFOPEDIA: \"Cet être est physiquement déficient et semble incapable de se maintenir en vie.  Ses muscles sont sévèrement atrophiés et les organes internes semblent sous-développés.  Les organes sensoriels, y compris les yeux, semblent ne pas fonctionner du tout.  Le cerveau, cependant, est bien développé et utilise une grande quantité du sang du corps.  Comment cette créature peut continuer à vivre sans aide extérieure, cela reste un mystère.\"\n  STR_MUTON_UFOPEDIA: \"Cette créature humanoïde est physiquement puissante et intelligente.  Elle apprécie tout particulièrement la viande crue, dont elle a besoin pour vivre, comme les carnivores terriens.  Elle semble obéir aux ordres télépathiques d'une race appelée les 'Éthérés'.  Si ce lien télépathique vient à se rompre, son système mental est détruit et elle meurt.  Les implants cybernétiques sont utilisés pour renforcer sa performance au combat.  Elle est de toute évidence au service d'une intelligence supérieure.\"\n  STR_MUTON_AUTOPSY: \"Autopsie du Muton\"\n  STR_MUTON_AUTOPSY_UFOPEDIA: \"La « peau » de cette créature semble être une armure de protection organique greffée sur le corps.  Il y a de nombreux implants cybernétiques utilisés pour renforcer le système cardio-vasculaire et les sens.  Les organes de reproduction semblent avoir été enlevés par opération chirurgicale.  A l'évidence, ces pauvres créatures sont limitées à une vie de guerre et de conquête.  Les munitions permettant de percer les armures ne sont pas très efficaces contre leur peau renforcée.\"\n  STR_CELATID_UFOPEDIA: \"Cette forme de vie a la mystérieuse capacité naturelle de flotter dans l'air.  Elle semble détecter les ondes du cerveau humain et peut se diriger vers une cible humaine même bien cachée.  Une fois la cible détectée, le Célatide atterrit et tire des petites bulles de venin extrêmement corrosif.  La créature peut se multiplier à un rythme affolant.  Cette race accompagne la race des Muton dans ses déplacements.\"\n  STR_CELATID_AUTOPSY: \"Autopsie du Célatide\"\n  STR_CELATID_AUTOPSY_UFOPEDIA: \"Le cœur contient un petit système biomécanique qui semble être un système de propulsion anti-gravité s'étant développé naturellement. La poche à venin est l'organe le plus grand et il ne semble pas y avoir de structure cérébrale séparée. Il n'y a pas de système digestif ou de reproduction visible. Un petit organe contient des embryons qui peuvent se développer rapidement en un nouvel être.\"\n  STR_SILACOID_UFOPEDIA: \"Cette forme de vie à base de silicone génère une énorme quantité de chaleur.  Elle a la force d'écraser des rochers qui peuvent ensuite être ingérés par le cœur chaud.  Elle a une intelligence limitée et peut être contrôlée par des implants ou par des êtres télépathiques.  Elle travaille avec la race des Muton.\"\n  STR_SILACOID_AUTOPSY: \"Autopsie du Silacoïde\"\n  STR_SILACOID_AUTOPSY_UFOPEDIA: \"Le cœur de cette créature est extrêmement chaud et semble être la base d'un système digestif.  Son système musculaire unique lui donne une énorme puissance et une très grande vitesse.  Sa peau, semblable à du roc, est invulnérable au feu ou aux munitions incendiaires.\"\n  STR_CHRYSSALID_UFOPEDIA: \"Les pinces de cette créature sont une arme puissante en combat rapproché.  Le puissant métabolisme et la force de cette créature lui procurent vitesse et dextérité.  Au lieu de tuer sa victime, elle l'imprègne d'un œuf et injecte un venin qui la transforme en mort-vivant.  Un nouveau Chryssalid sortira de la victime peu après.  Les Chryssalid sont associées à la race des Hommes-Serpents.\"\n  STR_CHRYSSALID_AUTOPSY: \"Autopsie du Chryssalid\"\n  STR_CHRYSSALID_AUTOPSY_UFOPEDIA: \"L'exosquelette de cette créature est très dur, mais étonnamment vulnérable aux munitions explosives.  Le cerveau est bien développé, et le taux de croissance de ses cellules est très rapide.  La créature porte vingt œufs qu'elle pond dans d'autres organismes.  Cette créature est une arme de terreur très efficace.\"\n  STR_FLOATER_UFOPEDIA: \"Les Flottants sont avant tout des soldats et des agents de terreur.  Ce sont des prédateurs naturels, produits par génie génétique et cybernétiquement renforcés pour faire d'exceptionnels guerriers.  La partie inférieure de leur corps et la plupart des organes internes sont enlevés par opération chirurgicale, et un système de survie est installé.  Cet implant contient une unité antigravitationnelle qui permet à la créature de flotter, avec quelques difficultés, dans l'air.\"\n  STR_FLOATER_AUTOPSY: \"Autopsie de Flottant\"\n  STR_FLOATER_AUTOPSY_UFOPEDIA: \"La créature a été très fortement modifiée par la chirurgie.  L'appareil qui semble former le noyau du corps est un système de survie, ayant à la fois les fonctions de cœur, de poumons et de système digestif.  Cela permet à la créature de survivre dans des environnements extrêmement hostiles.  Le cerveau est plus petit que le nôtre, mais les organes sensoriels sont bien développés.\"\n  STR_REAPER_UFOPEDIA: \"Ce carnivore bipède a des mâchoires puissantes et un appétit vorace.  Il a plusieurs implants cérébraux qui sont utilisés pour contrôler son activité.  Les instincts primitifs de prédateur de cette créature sont de peu d'utilité si ce n'est pour terroriser et détruire.  Les Reapers sont généralement associés aux Flottants.\"\n  STR_REAPER_AUTOPSY: \"Autopsie de Reaper \"\n  STR_REAPER_AUTOPSY_UFOPEDIA: \"Le Reaper possède deux 'cerveaux' et deux 'cœurs' lui permettant de survivre même lorsqu'il est gravement blessé. Cependant, sa fourrure est hautement inflammable, ce qui le rend vulnérable aux armes incendiaires.\"\n  STR_SECTOPOD_UFOPEDIA: \"Les Sectopodes sont des robots puissamment armés avec un rayon à plasma.  Ces créatures mécaniques sont contrôlées par les Ethereals par lien télépathique.  Les Sectopodes représentent l'arme de terreur la plus puissante des forces extraterrestres.\"\n  STR_SECTOPOD_AUTOPSY: \"Autopsie de Sectopode\"\n  STR_SECTOPOD_AUTOPSY_UFOPEDIA: \"Le robot est solidement construit avec une armure puissante capable de résister à la plupart des armes, en particulier celles à plasma.  Cependant, le système de détection semble particulièrement vulnérable aux armes laser.\"\n  STR_CYBERDISC_UFOPEDIA: \"Cette soucoupe volante miniature est une arme de terreur automatique munie d'un puissant rayon à plasma. La propulsion antigravitationnelle lui donne un avantage certain en terrain difficile. Sa fonction essentielle est de semer la destruction et la terreur au service de la race Sectoïde.\"\n  STR_CYBERDISC_AUTOPSY: \"Autopsie du Cyberdisque\"\n  STR_CYBERDISC_AUTOPSY_UFOPEDIA: \"Le Cyberdisque est bien protégé et résiste particulièrement bien aux munitions explosives.  Le système antigravitationnel principal est trop endommagé pour que l'on puisse comprendre son fonctionnement.\"\n  STR_UFO_POWER_SOURCE_UFOPEDIA: \"La source d'énergie du vaisseau extraterrestre est un réacteur antimatière qui utilise de l'Elerium (élément 115) pour générer des ondes puissantes de gravité ainsi que d'autres formes d'énergie.  La conversion de la matière en énergie est, chose incroyable, efficace à 99%, et de petites quantités d'Elerium peuvent donc produire une quantité énorme d'énergie.  Cette unité peut être facilement reproduite avec les alliages extraterrestres.\"\n  STR_UFO_NAVIGATION_UFOPEDIA: \"Le vaisseau extraterrestre utilise des ordinateurs sophistiqués pour naviguer sur la Terre et dans l'espace.  Le système est basé sur des processeurs optiques installés en réseaux.  L'interface de contrôle est relativement simple : le navigateur contrôle la direction des ondes de gravité générées par la source d'énergie pour déplacer le vaisseau dans n'importe quelle direction.  Ce système peut facilement être utilisé par les humains, et peut être reproduit en utilisant les alliages extraterrestres et d'autres composants.\"\n  STR_UFO_CONSTRUCTION_UFOPEDIA: \"Le vaisseau extraterrestre est constitué de trois composants principaux : une source d'énergie, un système de navigation et une coque faite d'alliages extraterrestres.  La coque est spécialement conçue pour que les ondes de gravité puissent être contrôlées.  De plus, une petite quantité d'Elerium est nécessaire pour alimenter la source d'énergie.  Une fois que les principes de construction ont été compris, et que l'on connaît les fonctions de chaque composant, il est alors possible de construire ce type de vaisseau.\"\n  STR_ALIEN_FOOD_UFOPEDIA: \"Ces chambres contiennent plusieurs enzymes utilisées pour digérer les parties corporelles du bétail, d'autres animaux et même des humains.  Le liquide est ensuite consommé comme aliment prédigéré, et est probablement directement injecté dans le système sanguin.  Cela suggère une certaine dépendance vis-à-vis de la nourriture sur Terre, une symbiose entre la Terre et la société extraterrestre.\"\n  STR_ALIEN_REPRODUCTION_UFOPEDIA: \"Ces chambres contiennent des fœtus extraterrestres.  La forme de ces containers semble suggérer que les extraterrestres qui utilisent ce procédé dépendent totalement de la reproduction en laboratoire.  Les riches nutriments assurent le développement rapide du fœtus.  Cette reproduction à la chaîne peut générer des milliers de clones extraterrestres en très peu de temps.  Le procédé pourrait facilement être appliqué pour la reproduction humaine, ou pour des hybrides extraterrestres-humains.\"\n  STR_ALIEN_ENTERTAINMENT_UFOPEDIA: \"La fonction la plus probable de ces sphères est une fonction récréative.  Le circuit psionique stimule plusieurs centres du cerveau.  L'effet est similaire aux drogues hallucinogènes.  C'est la seule preuve qui montre que les extraterrestres ont des passe-temps et une vie culturelle.\"\n  STR_ALIEN_SURGERY_UFOPEDIA: \"Cet équipement chirurgical utilise des scalpels laser pour extraire des parties du corps du bétail et d'autres animaux.  Les mutilations répandues du bétail sont dues à cette activité étrange des extraterrestres.  Il est vraisemblable que ces morceaux sont utilisés à des fins nutritionnelles ou d'études génétiques.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"Dans le passé, des milliers de gens ont prétendu avoir été enlevés par des extraterrestres, et quelques fois à plusieurs reprises.  La vérité est beaucoup plus horrible encore.  Les humains sont enlevés, étudiés et contrôlés.  On prélève les codes génétiques des  meilleurs spécimens.  On implante des fœtus humains-extraterrestres à des femmes, et on les enlève plusieurs mois après.  Qui connaît le but sinistre poursuivi par les extraterrestres ?\"\n  STR_ALIEN_ALLOYS_UFOPEDIA: \"Le vaisseau extraterrestre est composé d'alliages spéciaux aux propriétés uniques.  Ils sont extrêmement légers et solides, et peuvent être modelés grâce à des méthodes électromagnétiques.  Ces métaux peuvent être reproduits et utilisés dans de nombreux procédés de fabrication.\"\n  STR_ELERIUM_115_UFOPEDIA: \"Cet élément à une propriété inhabituelle : il génère de l'énergie antimatière lorsqu'on le bombarde de certaines particules.  Cela crée des ondes de gravité et d'autres formes d'énergie.  Cet élément ne se trouve pas naturellement dans notre système solaire et ne peut être reproduit.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"Il est clair que nous nous engageons dans une bataille perdue d'avance sur la Terre.  Les hordes extraterrestres sont beaucoup plus nombreuses.  La meilleure chose à faire est de ralentir leur progression.  Le seul espoir pour l'humanité est de combattre les extraterrestres à la source.  Nos recherches semblent nous indiquer une base d'opérations toute proche dans notre système solaire.  Les extraterrestres considèrent cet endroit comme le centre d'une ancienne civilisation, antérieure à l'histoire humaine.  Nous devons localiser cette base le plus tôt possible.  Cependant, il nous faut capturer et interroger un leader extraterrestre pour obtenir plus d'informations.  Les OVNIS les plus grands contiennent probablement au moins un leader extraterrestre.\"\n  STR_THE_MARTIAN_SOLUTION_UFOPEDIA: \"A présent, tout nous indique que Mars est le centre d'opérations des extraterrestres. La base est bien cachée et concentre toute la capacité de production et de clonage qui alimente le processus d'invasion de la terre. Elle semble également contenir un ordinateur de contrôle qui assume seul l'ensemble des opérations. La société extraterrestre semble donc organisé comme une ruche avec une sorte de «reine des abeilles». C'est là leur faiblesse fondamentale, si nous pouvons éliminer le «cerveau», le corps mourra. Nous devons intensifier nos efforts pour localiser cette base avant qu'il ne soit trop tard. L'étape suivante est d'exfiltrer une créature de haut rang tel qu'un commandant, situé uniquement dans des bases et des cuirassés extraterrestres.\"\n  STR_CYDONIA_OR_BUST_UFOPEDIA: \"Il est maintenant clair que les hordes extraterrestres sont contrôlées d'une base souterraine à Cydonia, qui est une zone étrange de Mars comprenant des pyramides à cinq côtés et une large formation ressemblant à un visage humain.  Il y a des millions d'années de cela, la civilisation cydonienne était florissante sur Mars, mais nous ne savons pas pourquoi elle s'est éteinte, ou quel est le lien avec l'activité extraterrestre qui y règne aujourd'hui.  Quelle que soit l'explication, nous devons envoyer une expédition à Cydonia.  C'est le seul moyen de vaincre les extraterrestres.  Nous devons détruire le 'cerveau' contrôlant toute l'opération.  Il nous faut équiper un vaisseau Avenger avec les armes de destruction les plus puissantes que nous ayons.  Nous ne pouvons rien apprendre de plus ici.  Il nous faut attendre le résultat de l'attaque sur Cydonia.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"CENTRER SUR SITE-TEMPS=5 Sec\"\n  STR_CANCEL_UC: \"ANNULER\"\n  STR_NONE: \"Rien\"\n  STR_UNKNOWN: \"Inconnu\"\n  STR_POOR: \"Médiocre\"\n  STR_AVERAGE: \"Moyen\"\n  STR_GOOD: \"Bon\"\n  STR_EXCELLENT: \"Excellent\"\n  STR_BUILD_NEW_BASE_UC: \"CONSTRUIRE NOUVELLE BASE\"\n  STR_BASE_INFORMATION: \"INFORMATIONS SUR LA BASE\"\n  STR_EQUIP_CRAFT: \"ÉQUIPER VAISSEAU\"\n  STR_BUILD_FACILITIES: \"CONSTRUIRE INSTALLATIONS\"\n  STR_RESEARCH: \"RECHERCHE\"\n  STR_MANUFACTURE: \"FABRICATION\"\n  STR_TRANSFER_UC: \"TRANSFERT\"\n  STR_PURCHASE_RECRUIT: \"ACHETER/RECRUTER\"\n  STR_SACK: \"LICENCIER\"\n  STR_SELL_SACK_UC: \"VENDRE/LICENCIER\"\n  STR_GEOSCAPE_UC: \"GÉOSCAPE\"\n  STR_NAME: \"Nom\"\n  STR_AREA: \"Zone\"\n  STR_BUILD_NEW_BASE: \"Construire Nouvelle Base\"\n  STR_CANCEL: \"Annuler\"\n  STR_COST_UC: \"PRIX>\"\n  STR_CONSTRUCTION_TIME_UC: \"TEMPS DE CONSTRUCTION>\"\n  STR_DAY:\n    one: \"{N} jour\"\n    many: \"{N} jours\"\n    other: \"{N} jours\"\n  STR_HOUR:\n    one: \"{N} heure\"\n    many: \"{N} heures\"\n    other: \"{N} heures\"\n  STR_MAINTENANCE_UC: \"ENTRETIEN>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Installation\"\n  STR_CURRENT_RESEARCH: \"RECHERCHE ACTUELLE\"\n  STR_SCIENTISTS_AVAILABLE: \"Scientifiques Disponibles> {ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Scientifiques Assignés> {ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Espace Laboratoire Disponible> {ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"PROJET DE RECHERCHE\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"SCIENTIFIQUES ASSIGNÉS\"\n  STR_PROGRESS: \"PROGRÈS\"\n  STR_NEW_PROJECT: \"Nouveau Projet\"\n  STR_CANCEL_PROJECT: \"ANNULER PROJET\"\n  STR_NEW_RESEARCH_PROJECTS: \"NOUVEAUX PROJETS DE RECHERCHE\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"SCIENTIFIQUES DISPONIBLES> {ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"ESPACE LABORATOIRE DISPONIBLE> {ALT}{0}\"\n  STR_INCREASE: \"Augmenter\"\n  STR_DECREASE: \"Réduire\"\n  STR_START_PROJECT: \"COMMENCER PROJET\"\n  STR_CURRENT_PRODUCTION: \"PRODUCTION ACTUELLE\"\n  STR_ENGINEERS_AVAILABLE: \"Ingénieurs Disponibles> {ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Ingénieurs Attribués> {ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Espace Atelier Disponible> {ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Fonds Actuels> {ALT}{0}\"\n  STR_ITEM: \"OBJET\"\n  STR_ENGINEERS__ALLOCATED: \"Ingénieurs Attribués\"\n  STR_UNITS_PRODUCED: \"Unités Produites\"\n  STR_TOTAL_TO_PRODUCE: \"Total à Produire\"\n  STR_COST__PER__UNIT: \"Coût{NEWLINE}par{NEWLINE}Unité\"\n  STR_DAYS_HOURS_LEFT: \"Jours/Heures restants\"\n  STR_NEW_PRODUCTION: \"Nouvelle Production\"\n  STR_PRODUCTION_ITEMS: \"Objets à Produire\"\n  STR_CATEGORY: \"CATÉGORIE\"\n  STR_START_PRODUCTION: \"COMMENCER PRODUCTION\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} heures d'Ingénieur pour produire une unité\"\n  STR_COST_PER_UNIT_: \"Coût par Unité> {ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Espace de Travail Requis> {ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"MATÉRIAUX SPÉCIAUX NÉCESSAIRES\"\n  STR_ITEM_REQUIRED: \"OBJET REQUIS\"\n  STR_UNITS_REQUIRED: \"UNITÉS REQUISES\"\n  STR_UNITS_AVAILABLE: \"UNITÉS DISPONIBLES\"\n  STR_STOP_PRODUCTION: \"ARRÊTER PRODUCTION\"\n  STR_ENGINEERS_AVAILABLE_UC: \"INGÉNIEURS DISPONIBLES> {ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"ESPACE ATELIER DISPONIBLE> {ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"BÉNÉFICE MENSUEL> {ALT}{0}\"\n  STR_INCREASE_UC: \"AUGMENTER\"\n  STR_DECREASE_UC: \"RÉDUIRE\"\n  STR_UNITS_TO_PRODUCE: \"Unités à Produire\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Acheter/Recruter Personnel\"\n  STR_COST_OF_PURCHASES: \"Prix d'Achat> {ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"COÛT PAR UNITÉ\"\n  STR_QUANTITY_UC: \"QUANTITÉ\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"PERSONNEL DISPONIBLE:PERSONNEL TOTAL>\"\n  STR_SOLDIERS: \"Soldats\"\n  STR_SCIENTISTS: \"Savants\"\n  STR_ENGINEERS: \"Ingénieurs\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"ESPACE UTILISÉ:ESPACE DISPONIBLE>\"\n  STR_LIVING_QUARTERS: \"Baraquements\"\n  STR_STORES: \"Entrepôts\"\n  STR_LABORATORIES: \"Laboratoires\"\n  STR_WORK_SHOPS: \"Ateliers\"\n  STR_HANGARS: \"Hangars\"\n  STR_SHORT_RANGE_DETECTION: \"Détection Courte Portée\"\n  STR_DEFENSE_STRENGTH: \"Force de Défense\"\n  STR_TRANSFERS_UC: \"TRANSFERTS\"\n  STR_TRANSFERS: \"Transferts\"\n  STR_ARRIVAL_TIME_HOURS: \"ARRIVÉE PRÉVUE (H)\"\n  STR_COST_: \"Prix> {ALT}{0}\"\n  STR_AREA_: \"Zone> {ALT}{0}\"\n  STR_BASE_NAME: \"Nom de la Base ?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"SÉLECTIONNER POSITION DE L'ASCENSEUR D'ACCÈS\"\n  STR_TRANSFER: \"Transfert\"\n  STR_AMOUNT_TO_TRANSFER: \"MONTANT A TRANSFÉRER\"\n  STR_SELECT_DESTINATION_BASE: \"Sélectionner Base de Destination\"\n  STR_COST: \"Prix\"\n  STR_VICTORY_1: \"En entrant dans la pièce, vous voyez le cerveau extraterrestre, objet de votre quête.  Avant que vous ayez eu le temps de tirer, il vous parle à travers un écran placé à sa base.  Il vous implore de l'épargner et d'écouter ses arguments avant que vous décidiez d'appuyer sur la détente...\"\n  STR_VICTORY_2: \"Le cerveau parle : 'Il y a des millions d'années de cela, la planète que vous appelez Mars était vivante.  Cette vie fut apportée à une planète stérile par notre civilisation, ainsi qu'à la votre.  Pendant des millions d'années, nous avons visité votre planète et développé génétiquement votre espèce.  Vous ne pouvez pas nous tuer, vous faites partie de nous...\\\"\"\n  STR_VICTORY_3: \"Vous êtes ici au centre de la civilisation martienne - les pyramides construites il y a des millions d'années avant vous - par une espèce qui est en fait votre ancêtre.  Aucune planète n'est hors de portée de notre pouvoir.  Ce pouvoir pourrait devenir le vôtre bientôt.  Tout ce que nous demandons, c'est votre coopération...\"\n  STR_GAME_OVER_1: \"Les extraterrestres essaient d'exterminer l'humanité tout entière, détruisant les villes et empoisonnant l'air et la mer.  La résistance des armées terrestres est futile face à une technologie hautement supérieure.  Les générations survivantes souffrent de mutations horribles alors qu'elles fuient la destruction extraterrestre.  Elles sont parquées dans des camps d'esclavage destinés à faire de la Terre une colonie extraterrestre soumise à quelque empire inconnu.\"\n  STR_GAME_OVER_2: \"Les connaissances acquises au cours du projet X-Com sont perdues à jamais. Vous avez échoué à sauver la Terre. \"\n  STR_VICTORY_4: \"Le cerveau extraterrestre est interrompu par une explosion de plasma brûlant, et toutes les forces extraterrestres sont vaincues.\"\n  STR_VICTORY_5: \"Maintenant que Mars est débarrassé des extraterrestres, la Terre est enfin libéré de leurs griffes. La recherche X-Com permettra durablement à l'humanité de s'épanouir et de s'étendre en revendiquant Mars pour elle-même. La menace extraterrestre s'est évanouie, mais pour combien de temps personne ne le sait ...\"\n  STR_YOU_HAVE_FAILED: \"Vous n'avez pas réussi à stopper l'attaque extraterrestre.  L'une après l'autre, les nations qui vous finançaient signent des pactes avec les extraterrestres, qui leur offrent la technologie, la prospérité et la paix.  Cependant, il devient rapidement évident que les extraterrestres ont d'autres plans...\"\n  STR_TOTAL_UC: \"TOTAL\"\n  STR_INCOME: \"Revenu\"\n  STR_EXPENDITURE: \"Dépenses\"\n  STR_MAINTENANCE: \"Entretien\"\n  STR_BALANCE: \"Solde\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"Activité des E.T. (Régions)\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"Activité des OVNIs par Pays\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"Activité X-Com dans les Zones\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"Activité X-Com dans les Pays\"\n  STR_FINANCE: \"Finances\"\n  STR_DATE_FIRST: \"{0}\"\n  STR_DATE_SECOND: \"{0}\"\n  STR_DATE_THIRD: \"{0}\"\n  STR_DATE_FOURTH: \"{0}\"\n  STR_FINANCE_THOUSANDS: \"$1000\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Pas assez de matériaux spéciaux pour produire{NEWLINE}{0}{NEWLINE}à{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Pas Assez d'Argent pour Produire{NEWLINE}{0}{NEWLINE}à{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"Production de{NEWLINE}{0}{NEWLINE}à{NEWLINE}{1}{NEWLINE}terminée.\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"Construction de{NEWLINE}{0}{NEWLINE}à{NEWLINE}{1}{NEWLINE}terminée\"\n  STR_OK_5_SECONDS: \"OK - 5 sec\"\n  STR_RESEARCH_COMPLETED: \"Recherche terminée\"\n  STR_VIEW_REPORTS: \"VOIR RAPPORTS\"\n  STR_WE_CAN_NOW_RESEARCH: \"Nous pouvons maintenant étudier\"\n  STR_WE_CAN_NOW_PRODUCE: \"Nous pouvons maintenant produire\"\n  STR_SUNDAY: \"DIMANCHE\"\n  STR_MONDAY: \"LUNDI\"\n  STR_TUESDAY: \"MARDI\"\n  STR_WEDNESDAY: \"MERCREDI\"\n  STR_THURSDAY: \"JEUDI\"\n  STR_FRIDAY: \"VENDREDI\"\n  STR_SATURDAY: \"SAMEDI\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Pas assez de {0} pour faire le plein de {1} à {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Pas assez de {0} pour réarmer {1} à {2}\"\n  STR_UFO_IS_NOT_RECOVERED: \"L'OVNI n'a pas été récupéré\"\n  STR_UFO_IS_RECOVERED: \"L'OVNI est récupéré\"\n  STR_CRAFT_IS_LOST: \"Le Vaisseau est Perdu\"\n  STR_TERROR_CONTINUES: \"La Terreur Continue\"\n  STR_ALIENS_DEFEATED: \"Extraterrestres Vaincus\"\n  STR_BASE_IS_LOST: \"La base est perdue\"\n  STR_BASE_IS_SAVED: \"La Base est Sauvée\"\n  STR_ALIEN_BASE_STILL_INTACT: \"Base extraterrestre toujours intacte\"\n  STR_ALIEN_BASE_DESTROYED: \"Base Extraterrestre Détruite\"\n  STR_ALIENS_KILLED: \"EXTRATERRESTRES TUÉS\"\n  STR_ALIEN_CORPSES_RECOVERED: \"CORPS EXTRATERRESTRES RÉCUPÉRÉS\"\n  STR_LIVE_ALIENS_RECOVERED: \"EXTRATERRESTRES VIVANTS RÉCUPÉRÉS\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"OBJETS EXTRATERRESTRES RÉCUPÉRÉS\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"CONTRÔLE DE BASE EXTRATERRESTRE DÉTRUIT\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"CIVILS TUÉS PAR DES EXTRATERRESTRES\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"CIVILS TUÉS PAR DES AGENTS X-COM\"\n  STR_CIVILIANS_SAVED: \"CIVILS SAUVÉS\"\n  STR_XCOM_OPERATIVES_KILLED: \"AGENTS X-COM TUÉS\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"AGENTS X-COM PORTÉS DISPARUS\"\n  STR_TANKS_DESTROYED: \"BLINDÉS DÉTRUITS\"\n  STR_XCOM_CRAFT_LOST: \"VAISSEAU X-COM PERDU\"\n  STR_UFO_RECOVERY: \"RÉCUPÉRATION DE L'OVNI\"\n  STR_ALIEN_BASE_RECOVERY: \"RÉCUPÉRATION BASE EXTRATERRESTRE\"\n  STR_BASE_UNDER_ATTACK: \"{0} est attaqué !\"\n  STR_BASE_DEFENSES_INITIATED: \"DÉFENSES DE LA BASE ACTIVÉES\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"LE BOUCLIER DE GRAVITÉ REPOUSSE L'OVNI !\"\n  STR_FIRING: \"TIR\"\n  STR_HIT: \"TOUCHÉ !\"\n  STR_UFO_DESTROYED: \"OVNI DÉTRUIT !\"\n  STR_MISSED: \"MANQUÉ !\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Vendre/Licencier Personnel\"\n  STR_VALUE_OF_SALES: \"VALEUR DE VENTE> {ALT}{0}\"\n  STR_FUNDS: \"FONDS> {ALT}{0}\"\n  STR_SELL_SACK: \"Vendre/Licencier\"\n  STR_VALUE: \"Valeur\"\n  STR_CRAFT_: \"VAISSEAU> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"RÉCUPÉRATION OVNI\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"Avertissement - Il peut y avoir des agents extraterrestres dans l'OVNI ou à proximité du lieu du crash.  La mission sera réussie quand toutes les unités ennemies auront été éliminées ou neutralisées.  La récupération des fragments de l'OVNI, des objets et des corps extraterrestres pourra alors commencer.  Pour abandonner la mission, évacuez les agents XCom au véhicule de transport et cliquez sur l'icône 'Abandonner Mission'.\"\n  STR_UFO_GROUND_ASSAULT: \"ATTAQUE AU SOL DE L'OVNI\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"Explorez le site de l'atterrissage et si possible entrez dans l'OVNI.  La mission sera réussie quand toutes les unités ennemies auront été éliminées ou neutralisées.  La récupération de l'OVNI, des objets et des corps extraterrestres pourra alors commencer.  Pour abandonner la mission, évacuez les agents XCom au véhicule de transport et cliquez sur l'icône 'Abandonner Mission'.\"\n  STR_BASE_DEFENSE: \"DÉFENSE DE LA BASE\"\n  STR_BASE_UC_: \"BASE> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"Notre base court un danger alarmant, un vaisseau extraterrestre c'est posé à proximité de nos installations. Selon la procédure habituelle, tout le personnel non-combattant et les vaisseaux X-Com ont été évacués. Les unités extraterrestres vont assaillir la base par les portes du hangar ou par l'ascenseur d'accès. Défendez la base et ses installations vitales à tout prix. C'est un combat à mort, si vous cliquez sur l'icône 'Abandonner Mission', vous serez vaincu et perdrez la base.\"\n  STR_ALIEN_BASE_ASSAULT: \"ASSAUT DE BASE E.T.\"\n  STR_ALIEN_BASE_ASSAULT_BRIEFING: \"Les agents X-Com ont forcé l’accès d'une base extraterrestre.  Le centre de contrôle doit être détruit pour rendre la base inopérante.  La mission sera terminée quand tous les ennemis auront été éliminés, ou quand votre escouade sera revenue à la zone verte d'extraction (cliquez sur l'icône 'Abandonner Mission' pour sortir).\"\n  STR_CYDONIA_BRIEFING: \"Vous êtes arrivé à Cydonia.  Vous pénétrez dans un grand complexe souterrain près du Sphinx martien.  Vous devez détruire le Cerveau Extraterrestre qui contrôle toute l'activité extraterrestre.  Le sort de l'humanité est entre vos mains....\"\n  STR_TERROR_MISSION: \"MISSION DE TERREUR\"\n  STR_TERROR_MISSION_BRIEFING: \"La mission sera réussie lorsque toutes les unités ennemies auront été éliminées ou neutralisées.  Vous devez essayer de sauver tous les civils de la région en neutralisant la menace extraterrestre.  Pour abandonner la mission, ramenez les agents XCom au véhicule de transport et cliquez sur l'icône 'Abandonner Mission'.\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"PAS DE HANGAR DE LIBRE POUR LA PRODUCTION DE VAISSEAU !{SMALLLINE}Tout vaisseau affecté à une base, transféré à une base, acheté ou construit, a besoin d'un hangar.  Construisez un nouveau hangar ou transférez un vaisseau à une autre base.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"PAS DE HANGAR DE LIBRE POUR L'ACHAT !{SMALLLINE}Tout vaisseau affecté à une base, transféré à une base, acheté ou construit, nécessite un hangar.  Construisez un nouveau hangar ou transférez un vaisseau à une autre base.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"PAS DE HANGAR DE LIBRE POUR LE TRANSFERT !{SMALLLINE}Tout vaisseau affecté à une base, transféré à une base, acheté ou construit, nécessite un hangar.  Construisez un nouveau hangar ou transférez un vaisseau à une autre base.\"\n  STR_CANNOT_BUILD_HERE: \"IMPOSSIBLE DE CONSTRUIRE ICI !{SMALLLINE}Vous devez construire à côté d'une installation déjà existante.\"\n  STR_NO_FREE_ACCOMODATION: \"PAS DE LOGEMENT DE LIBRE !{SMALLLINE}La base de destination n'a pas assez de place dans les baraquements.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"ESPACE DE TRAVAIL INSUFFISANT ! {SMALLLINE}Construisez un nouvel atelier ou réduisez le travail sur d'autres projets.\"\n  STR_NOT_ENOUGH_MONEY: \"ARGENT INSUFFISANT !\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"PAS ASSEZ DE PLACE POUR STOCKER !{SMALLLINE}Construisez un nouvel entrepôt ou transférez les stocks existants aux autres bases.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"PAS ASSEZ D'ESPACE VITAL !{SMALLLINE}Construisez de nouveaux baraquements ou transférez le personnel aux autres bases.\"\n  STR_LAUNCH_INTERCEPTION: \"LANCER INTERCEPTION\"\n  STR_CRAFT: \"VAISSEAU\"\n  STR_STATUS: \"STATUT\"\n  STR_BASE: \"BASE\"\n  STR_READY: \"Prêt\"\n  STR_OUT: \"Absent\"\n  STR_REPAIRS: \"Réparations\"\n  STR_REFUELLING: \"Ravitaillement\"\n  STR_REARMING: \"Réarmement\"\n  STR_TARGET: \"CIBLE : {0}\"\n  STR_WAY_POINT: \"POINT DE REPÈRE\"\n  STR_ARE_YOU_SURE_CYDONIA: \"Êtes-vous sûr de vouloir envoyer ce vaisseau en mission à Cydonia ?\"\n  STR_YES: \"OUI\"\n  STR_NO: \"NON\"\n  STR_SELECT_DESTINATION: \"SÉLECTIONNER{NEWLINE}DESTINATION\"\n  STR_CYDONIA: \"CYDONIA\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"SÉLECTIONNER SITE POUR NOUVELLE BASE\"\n  STR_RETURN_TO_BASE: \"RETOUR À LA BASE\"\n  STR_SELECT_NEW_TARGET: \"SÉLECTIONNER NOUVELLE CIBLE\"\n  STR_PATROL: \"PATROUILLE\"\n  STR_STATUS_: \"STATUT> {ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"ENDOMMAGÉ - RETOUR À LA BASE\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"CARBURANT BAS - RETOUR À LA BASE\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"MISSION TERMINÉE - RETOUR À LA BASE\"\n  STR_PATROLLING: \"PATROUILLE\"\n  STR_TAILING_UFO: \"POURSUITE DE L'OVNI\"\n  STR_INTERCEPTING_UFO: \"INTERCEPTION DE OVNI-{0}\"\n  STR_RETURNING_TO_BASE: \"RETOUR À LA BASE\"\n  STR_DESTINATION_UC_: \"DESTINATION : {0}\"\n  STR_BASE_UC: \"BASE> {ALT}{0}\"\n  STR_SPEED_: \"VITESSE> {ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"VITESSE DE POINTE> {ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"ALTITUDE> {ALT}{0}\"\n  STR_VERY_LOW: \"TRÈS BASSE\"\n  STR_LOW_UC: \"BASSE\"\n  STR_HIGH_UC: \"HAUTE\"\n  STR_VERY_HIGH: \"TRÈS HAUTE\"\n  STR_FUEL: \"CARBURANT> {ALT}{0}\"\n  STR_WEAPON_ONE: \"ARME-1> {ALT}{0}\"\n  STR_NONE_UC: \"RIEN\"\n  STR_ROUNDS_: \"CARTOUCHES> {ALT}{0}\"\n  STR_WEAPON_TWO: \"ARME-2> {ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"VAISSEAU D'INTERCEPTION\"\n  STR_BASE_: \"Base> {0}\"\n  STR_NAME_UC: \"NOM\"\n  STR_AMMO_: \"MUNITIONS> {ALT}{0}\"\n  STR_CREW: \"ÉQUIPAGE\"\n  STR_EQUIPMENT_UC: \"ÉQUIPEMENT\"\n  STR_ARMOR: \"ARMURE\"\n  STR_MAX: \"MAX> {ALT}{0}\"\n  STR_ROOKIE: \"Recrue\"\n  STR_SQUADDIE: \"Deuxième Classe\"\n  STR_SERGEANT: \"Sergent\"\n  STR_CAPTAIN: \"Capitaine\"\n  STR_COLONEL: \"Colonel\"\n  STR_COMMANDER: \"Commandant\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Sélectionner l'Escouade pour {0}\"\n  STR_SORT_BY: \"TRIER PAR...\"\n  STR_ORIGINAL_ORDER: \"ORDRE D'ORIGINE\"\n  STR_MISSIONS2: \"MISSIONS\"\n  STR_KILLS2: \"TUÉS\"\n  STR_WOUND_RECOVERY2: \"CONVALESCENCE\"\n  STR_SPACE_AVAILABLE: \"ESPACE DISPONIBLE> {ALT}{0}\"\n  STR_SPACE_USED: \"ESPACE UTILISÉ> {ALT}{0}\"\n  STR_SPACE_USED_UC: \"ESPACE UT.\"\n  STR_RANK: \"GRADE\"\n  STR_WOUNDED: \"BLESSÉ\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Équipement pour {0}\"\n  STR_DEFENSE_VALUE: \"Valeur Défensive\"\n  STR_HIT_RATIO: \"Ratio de Tirs Réussis \"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}prêt à{NEWLINE}atterrir près de{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"Commencer la Mission ?\"\n  STR_SELECT_ARMAMENT: \"Sélectionner Armement\"\n  STR_AMMUNITION_AVAILABLE: \"MUNITIONS DISPONIBLES\"\n  STR_ARMAMENT: \"ARMEMENT\"\n  STR_NOT_AVAILABLE: \"N.D.\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"SÉLECTIONNEZ ARMURE POUR{NEWLINE}{0}\"\n  STR_TYPE: \"TYPE\"\n  STR_PERSONAL_ARMOR_UC: \"ARMURE PERSONNELLE\"\n  STR_POWER_SUIT_UC: \"ARMURE ÉNERGÉTIQUE\"\n  STR_FLYING_SUIT_UC: \"ARMURE ANTI-G\"\n  STR_SELECT_ARMOR: \"Sélectionner Armure\"\n  STR_NORTH: \"NORD\"\n  STR_NORTH_EAST: \"NORD EST\"\n  STR_EAST: \"EST\"\n  STR_SOUTH_EAST: \"SUD EST\"\n  STR_SOUTH: \"SUD\"\n  STR_SOUTH_WEST: \"SUD OUEST\"\n  STR_WEST: \"OUEST\"\n  STR_NORTH_WEST: \"NORD OUEST\"\n  STR_SELECT_ACTION: \"SÉLECTIONNER ACTION\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"CONTINUER L'INTERCEPTION\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"POURSUIVRE SANS INTERCEPTION\"\n  STR_VERY_LARGE: \"TRÈS GRAND\"\n  STR_LARGE: \"GRAND\"\n  STR_MEDIUM_UC: \"MOYEN\"\n  STR_SMALL: \"PETIT\"\n  STR_VERY_SMALL: \"TRÈS PETIT\"\n  STR_GROUNDED: \"SOL\"\n  STR_DETECTED: \"Détecté\"\n  STR_SIZE_UC: \"TAILLE\"\n  STR_ALTITUDE: \"ALTITUDE\"\n  STR_HEADING: \"CAP\"\n  STR_SPEED: \"VITESSE\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"CENTRER SUR OVNI-TEMPS=5 Sec\"\n  STR_TRACKING_LOST: \"OVNI DISPARU\"\n  STR_REDIRECT_CRAFT: \"REDIRIGER VAISSEAU\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"ALLER À LA DERNIÈRE POSITION CONNUE\"\n  STR_UFO_: \"OVNI-{0}\"\n  STR_ALIEN_BASE_: \"BASE E.T.-{0}\"\n  STR_CRASH_SITE_: \"SITE DE CRASH-{0}\"\n  STR_LANDING_SITE_: \"SITE D'ATTERRISSAGE-{0}\"\n  STR_WAY_POINT_: \"POINT DE REPÈRE-{0}\"\n  STR_TERROR_SITE: \"SITE DE TERREUR-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}a atteint{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"En Patrouille\"\n  STR_ALIEN_ORIGINS: \"Origines Extraterrestres\"\n  STR_THE_MARTIAN_SOLUTION: \"La Solution Martienne\"\n  STR_CYDONIA_OR_BUST: \"Cydonia ou Rien\"\n  STR_UFOPAEDIA: \"OVNIpédie\"\n  STR_XCOM_CRAFT_ARMAMENT: \"VAISSEAU ET ARMEMENT X-COM\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"PLATES-FORMES D'ARMES LOURDES\"\n  STR_WEAPONS_AND_EQUIPMENT: \"ARMES ET ÉQUIPEMENTS\"\n  STR_ALIEN_ARTIFACTS: \"OBJETS EXTRATERRESTRES\"\n  STR_BASE_FACILITIES: \"INSTALLATIONS DE BASE\"\n  STR_ALIEN_LIFE_FORMS: \"FORMES DE VIE EXTRATERRESTRES\"\n  STR_ALIEN_RESEARCH_UC: \"RECHERCHE SUR LES EXTRATERRESTRES\"\n  STR_UFO_COMPONENTS: \"COMPOSANTS D'OVNIS\"\n  STR_UFOS: \"OVNIS\"\n  STR_SELECT_ITEM: \"SÉLECTIONNER ARTICLE\"\n  STR_ACCELERATION: \"ACCÉLÉRATION> {ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"CAPACITÉ CARBURANT> {ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"NACELLES D'ARMES> {ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"BLINDAGE> {ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"ÉQUIPAGE> {ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"CAPACITÉ PAL> {ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Dégâts\"\n  STR_RANGE: \"Portée\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Précision\"\n  STR_RE_LOAD_TIME: \"Temps de Recharge\"\n  STR_SECONDS: \"{0}s\"\n  STR_DAMAGE_ARMOR_PIERCING: \"PERFORANT\"\n  STR_DAMAGE_INCENDIARY: \"INCENDIAIRE\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"EXPLOSIF\"\n  STR_DAMAGE_LASER_BEAM: \"RAYON LASER\"\n  STR_DAMAGE_PLASMA_BEAM: \"RAYON PLASMA\"\n  STR_DAMAGE_STUN: \"ASSOMMER\"\n  STR_DAMAGE_MELEE: \"MÊLÉE\"\n  STR_DAMAGE_ACID: \"ACIDE\"\n  STR_DAMAGE_SMOKE: \"FUMÉE\"\n  STR_SHOT_TYPE: \"TYPE DE TIR\"\n  STR_ACCURACY_UC: \"PRÉCISION\"\n  STR_TIME_UNIT_COST: \"COÛT UT\"\n  STR_DAMAGE_UC: \"DÉGÂTS\"\n  STR_AMMO: \"MUNITIONS\"\n  STR_SHOT_TYPE_AUTO: \"Auto\"\n  STR_SHOT_TYPE_SNAP: \"Rapide\"\n  STR_SHOT_TYPE_AIMED: \"Précis\"\n  STR_CONSTRUCTION_TIME: \"Temps de Construction\"\n  STR_CONSTRUCTION_COST: \"Coût de Construction\"\n  STR_MAINTENANCE_COST: \"Coût d'Entretien\"\n  STR_LOW: \"Basse\"\n  STR_MEDIUM: \"Moyenne\"\n  STR_HIGH: \"Haute\"\n  STR_CRAFT_WEAPON: \"Arme du Vaisseau\"\n  STR_CRAFT_AMMUNITION: \"Munitions du Vaisseau\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Plate-Forme d'Arme Lourde\"\n  STR_WEAPON: \"Arme\"\n  STR_AMMUNITION: \"Munitions\"\n  STR_EQUIPMENT: \"Équipement\"\n  STR_ALIEN_CORPSE: \"Corps Extraterrestre\"\n  STR_UFO_COMPONENT: \"Composant d'OVNI\"\n  STR_PERSONAL_ARMOR: \"Armure Personnelle\"\n  STR_RAW_MATERIALS: \"Matières Premières\"\n  STR_HWP_CANNON_SHELLS: \"Obus PAL\"\n  STR_ALIEN: \"Extraterrestre\"\n  STR_SECTOID: \"Sectoïde\"\n  STR_SNAKEMAN: \"Homme-Serpent\"\n  STR_ETHEREAL: \"Ethereal\"\n  STR_MUTON: \"Muton\"\n  STR_FLOATER: \"Flottant\"\n  STR_CELATID: \"Célatide\"\n  STR_SILACOID: \"Silacoïde\"\n  STR_CHRYSSALID: \"Chryssalid\"\n  STR_ZOMBIE: \"Zombi\"\n  STR_REAPER: \"Reaper\"\n  STR_SECTOPOD: \"Sectopode\"\n  STR_CYBERDISC: \"Cyberdisque\"\n  STR_LIVE_COMMANDER: \"Commandant\"\n  STR_LIVE_LEADER: \"Chef d'Escouade\"\n  STR_LIVE_ENGINEER: \"Ingénieur\"\n  STR_LIVE_MEDIC: \"Médecin\"\n  STR_LIVE_NAVIGATOR: \"Navigateur\"\n  STR_LIVE_SOLDIER: \"Soldat\"\n  STR_LIVE_TERRORIST: \"Terroriste\"\n  STR_FLOATER_SOLDIER: \"Soldat Flottant\"\n  STR_FLOATER_NAVIGATOR: \"Navigateur Flottant\"\n  STR_FLOATER_MEDIC: \"Docteur Flottant\"\n  STR_FLOATER_ENGINEER: \"Ingénieur Flottant\"\n  STR_FLOATER_LEADER: \"Chef d'Escouade Flottant\"\n  STR_FLOATER_COMMANDER: \"Commandant Flottant\"\n  STR_SECTOID_SOLDIER: \"Soldat Sectoïde\"\n  STR_SECTOID_NAVIGATOR: \"Navigateur Sectoïde\"\n  STR_SECTOID_MEDIC: \"Docteur Sectoïde\"\n  STR_SECTOID_ENGINEER: \"Ingénieur Sectoïde\"\n  STR_SECTOID_LEADER: \"Chef d'Escouade Sectoïde\"\n  STR_SECTOID_COMMANDER: \"Commandant Sectoïde\"\n  STR_SNAKEMAN_SOLDIER: \"Soldat Homme-Serpent\"\n  STR_SNAKEMAN_NAVIGATOR: \"Navigateur Homme-Serpent\"\n  STR_SNAKEMAN_ENGINEER: \"Ingénieur Homme-Serpent\"\n  STR_SNAKEMAN_LEADER: \"Chef d'Escouade Homme-Serpent\"\n  STR_SNAKEMAN_COMMANDER: \"Commandant Homme-Serpent\"\n  STR_MUTON_SOLDIER: \"Soldat Muton\"\n  STR_MUTON_NAVIGATOR: \"Navigateur Muton\"\n  STR_MUTON_ENGINEER: \"Ingénieur Muton\"\n  STR_ETHEREAL_SOLDIER: \"Soldat Ethereal\"\n  STR_ETHEREAL_LEADER: \"Chef d'Escouade Ethereal\"\n  STR_ETHEREAL_COMMANDER: \"Commandant Ethereal\"\n  STR_CYBERDISC_TERRORIST: \"Terroriste Cyberdisque\"\n  STR_REAPER_TERRORIST: \"Terroriste Reaper\"\n  STR_CHRYSSALID_TERRORIST: \"Terroriste Chryssalid\"\n  STR_CELATID_TERRORIST: \"Terroriste Célatide\"\n  STR_SILACOID_TERRORIST: \"Terroriste Silacoïde \"\n  STR_SECTOPOD_TERRORIST: \"Terroriste Sectopode\"\n  STR_UFO_POWER_SOURCE: \"Source d'énergie OVNI\"\n  STR_UFO_NAVIGATION: \"Navigation OVNI\"\n  STR_UFO_CONSTRUCTION: \"Construction OVNI\"\n  STR_ALIEN_FOOD: \"Nourriture Extraterrestre\"\n  STR_ALIEN_REPRODUCTION: \"Reproduction Extraterrestre\"\n  STR_ALIEN_ENTERTAINMENT: \"Divertissement Extraterrestre\"\n  STR_ALIEN_SURGERY: \"Chirurgie Extraterrestre\"\n  STR_EXAMINATION_ROOM: \"Salle d'Examen\"\n  STR_ALIEN_ALLOYS: \"Alliages Extraterrestres\"\n  STR_ALIEN_HABITAT: \"Habitat Extraterrestre\"\n  STR_POWER_SUIT: \"Armure Énergétique\"\n  STR_FLYING_SUIT: \"Armure Anti-G\"\n  STR_HWP_ROCKETS: \"Roquettes PAL\"\n  STR_HWP_FUSION_BOMB: \"Bombe à Fusion PAL\"\n  STR_LASER_WEAPONS: \"Armes Laser\"\n  STR_NEW_FIGHTER_CRAFT: \"Nouveau Chasseur\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Nouveau Chasseur-Transporteur\"\n  STR_ULTIMATE_CRAFT: \"Vaisseau Suprême\"\n  STR_LASER_PISTOL: \"Pistolet Laser\"\n  STR_LASER_RIFLE: \"Fusil Laser\"\n  STR_HEAVY_LASER: \"Laser Lourd\"\n  STR_LASER_CANNON: \"Canon Laser\"\n  STR_PLASMA_CANNON: \"Canon Plasma\"\n  STR_FUSION_MISSILE: \"Missile à Fusion\"\n  STR_LASER_DEFENSE: \"Défense Laser\"\n  STR_PLASMA_DEFENSE: \"Défense à Plasma\"\n  STR_FUSION_DEFENSE: \"Défense à Fusion\"\n  STR_GRAV_SHIELD: \"Bouclier Gravitationnel\"\n  STR_MIND_SHIELD: \"Bouclier Psychique\"\n  STR_PSI_LAB: \"Psi-Labo\"\n  STR_MOTION_SCANNER: \"Scanner de Mouvement\"\n  STR_MEDI_KIT: \"Trousse de Soins\"\n  STR_TANK_CANNON: \"Blindé Canon Lourd\"\n  STR_TANK_ROCKET_LAUNCHER: \"Blindé Lance-Roquettes\"\n  STR_TANK_LASER_CANNON: \"Blindé Laser\"\n  STR_HOVERTANK_PLASMA: \"Blindé Anti-G Plasma\"\n  STR_HOVERTANK_LAUNCHER: \"Blindé Anti-G Lanceur Nucléaire\"\n  STR_STINGRAY_LAUNCHER: \"Lance-Missile Stingray\"\n  STR_AVALANCHE_LAUNCHER: \"Lance-Missile Avalanche\"\n  STR_CANNON: \"Canon\"\n  STR_FUSION_BALL_LAUNCHER: \"Lance-Missile à Fusion\"\n  STR_PLASMA_BEAM: \"Rayon Plasma\"\n  STR_STINGRAY_MISSILES: \"Missile Stingray\"\n  STR_AVALANCHE_MISSILES: \"Missile Avalanche\"\n  STR_CANNON_ROUNDS_X50: \"Munitions de Canon (x50)\"\n  STR_FUSION_BALL: \"Boule de Fusion\"\n  STR_SOLDIER: \"Soldat\"\n  STR_SCIENTIST: \"Scientifique\"\n  STR_ENGINEER: \"Ingénieur\"\n  STR_NORTH_AMERICA: \"Amérique du Nord\"\n  STR_ARCTIC: \"Arctique\"\n  STR_ANTARCTICA: \"Antarctique\"\n  STR_SOUTH_AMERICA: \"Amérique du Sud\"\n  STR_EUROPE: \"Europe\"\n  STR_NORTH_AFRICA: \"Afrique du Nord\"\n  STR_SOUTHERN_AFRICA: \"Afrique australe\"\n  STR_CENTRAL_ASIA: \"Asie Centrale\"\n  STR_SOUTH_EAST_ASIA: \"Asie du Sud-Est\"\n  STR_SIBERIA: \"Sibérie\"\n  STR_AUSTRALASIA: \"Océanie\"\n  STR_PACIFIC: \"Pacifique\"\n  STR_NORTH_ATLANTIC: \"Atlantique Nord\"\n  STR_SOUTH_ATLANTIC: \"Atlantique Sud\"\n  STR_INDIAN_OCEAN: \"Océan Indien\"\n  STR_ALIEN_RESEARCH: \"Recherche E.T.\"\n  STR_ALIEN_HARVEST: \"Moisson E.T.\"\n  STR_ALIEN_ABDUCTION: \"Enlèvement E.T.\"\n  STR_ALIEN_INFILTRATION: \"Infiltration E.T.\"\n  STR_ALIEN_BASE: \"Base Extraterrestre\"\n  STR_ALIEN_TERROR: \"Terreur E.T.\"\n  STR_ALIEN_RETALIATION: \"Représailles E.T.\"\n  STR_ALIEN_SUPPLY: \"Ravitaillement E.T.\"\n  STR_MAXIMUM_SPEED: \"Vitesse Maximum\"\n  STR_HYPER_WAVE_DECODER_UC: \"DÉCODEUR D'HYPER-ONDES\"\n  STR_SKYRANGER: \"MERCURE\"\n  STR_LIGHTNING: \"JUPITER\"\n  STR_AVENGER: \"TALION\"\n  STR_INTERCEPTOR: \"INTERCEPTEUR\"\n  STR_FIRESTORM: \"DÉMON\"\n  STR_UFO: \"OVNI\"\n  STR_STINGRAY: \"STINGRAY\"\n  STR_AVALANCHE: \"AVALANCHE\"\n  STR_CANNON_UC: \"CANON\"\n  STR_FUSION_BALL_UC: \"BOULE DE FUSION\"\n  STR_LASER_CANNON_UC: \"CANON LASER\"\n  STR_PLASMA_BEAM_UC: \"RAYON PLASMA\"\n  STR_DAMAGE_CAPACITY: \"Capacité de Dégâts\"\n  STR_WEAPON_POWER: \"Puissance d'Arme\"\n  STR_WEAPON_RANGE: \"Portée de l'Arme\"\n  STR_ACCESS_LIFT: \"Ascenseur d'Accès\"\n  STR_LABORATORY: \"Laboratoire\"\n  STR_WORKSHOP: \"Atelier\"\n  STR_SMALL_RADAR_SYSTEM: \"Petit Système Radar\"\n  STR_LARGE_RADAR_SYSTEM: \"Grand Système Radar\"\n  STR_MISSILE_DEFENSES: \"Défenses Missiles\"\n  STR_GENERAL_STORES: \"Entrepôts\"\n  STR_ALIEN_CONTAINMENT: \"Détention des E.T.\"\n  STR_LASER_DEFENSES: \"Défenses Laser\"\n  STR_PLASMA_DEFENSES: \"Défenses à Plasma\"\n  STR_FUSION_BALL_DEFENSES: \"Défenses à Fusion\"\n  STR_PSIONIC_LABORATORY: \"Laboratoire Psionique\"\n  STR_HYPER_WAVE_DECODER: \"Décodeur d'Hyper-Ondes\"\n  STR_HANGAR: \"Hangar\"\n  STR_USA: \"ÉTATS-UNIS\"\n  STR_RUSSIA: \"RUSSIE\"\n  STR_UK: \"ROYAUME-UNI\"\n  STR_FRANCE: \"FRANCE\"\n  STR_GERMANY: \"ALLEMAGNE\"\n  STR_ITALY: \"ITALIE\"\n  STR_SPAIN: \"ESPAGNE\"\n  STR_CHINA: \"CHINE\"\n  STR_JAPAN: \"JAPON\"\n  STR_INDIA: \"INDE\"\n  STR_BRAZIL: \"BRÉSIL\"\n  STR_AUSTRALIA: \"AUSTRALIE\"\n  STR_NIGERIA: \"NIGER\"\n  STR_SOUTH_AFRICA: \"AFRIQUE DU SUD\"\n  STR_EGYPT: \"ÉGYPTE\"\n  STR_CANADA: \"CANADA\"\n  STR_TANK: \"Blindé\"\n  STR_CIVILIAN: \"Civil\"\n  STR_JAN: \"Jan\"\n  STR_FEB: \"Fév\"\n  STR_MAR: \"Mar\"\n  STR_APR: \"Avr\"\n  STR_MAY: \"Mai\"\n  STR_JUN: \"Jui\"\n  STR_JUL: \"Juil\"\n  STR_AUG: \"Aoû\"\n  STR_SEP: \"Sep\"\n  STR_OCT: \"Oct\"\n  STR_NOV: \"Nov\"\n  STR_DEC: \"Déc\"\n  STR_INTERNATIONAL_RELATIONS: \"Relations Internationales\"\n  STR_COUNTRY: \"Pays\"\n  STR_FUNDING: \"Budget\"\n  STR_CHANGE: \"Écart\"\n  STR_WEAPON_SYSTEMS: \"SYSTÈMES D'ARME\"\n  STR_HWPS: \"PAL\"\n  STR_DAMAGE_UC_: \"DÉGÂTS> {ALT}{0}\"\n  STR_ACCESS_LIFT_UFOPEDIA: \"L'ascenseur d'accès permet de transférer l'équipement et le personnel aux bases souterraines.  C'est toujours la première installation à être construite sur un nouveau site.  La cage d'ascenseur est vulnérable aux intrusions de toute force hostile.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Chaque bloc d'habitation peut abriter jusqu'à 50 personnes.  Cette installation comporte une zone de loisirs, un secteur d'alimentation et des dortoirs.\"\n  STR_LABORATORY_UFOPEDIA: \"Un maximum de 50 savants peut travailler dans un laboratoire.  Les laboratoires sont équipés de la toute dernière technologie en matière de recherche de matériaux, de biochimie et de cosmologie.  XCom a un accès privilégié aux meilleurs laboratoires de recherche du monde entier, y compris les établissements militaires.\"\n  STR_WORKSHOP_UFOPEDIA: \"Un atelier contenant tout l'équipement nécessaire à la fabrication de produits basés sur les conceptions des laboratoires scientifiques.  Un atelier peut contenir jusqu'à 50 ingénieurs, mais les objets en construction prennent également de la place.\"\n  STR_SMALL_RADAR_SYSTEM_UFOPEDIA: \"Petit système de détection ayant une portée radar de 300 nautiques avec liaison aux systèmes satellites pour les recherches au sol.  Chaque système a 5% de chances de détecter un objet de taille moyenne toutes les 10 minutes.\"\n  STR_LARGE_RADAR_SYSTEM_UFOPEDIA: \"Grand système de détection ayant une portée de 450 nautiques avec liaison aux systèmes satellites pour les recherches au sol.  Chaque système a 5% de chances de détecter un objet de taille moyenne toutes les 10 minutes.\"\n  STR_MISSILE_DEFENSES_UFOPEDIA: \"Les défenses missiles protègent des incursions des vaisseaux ennemis qui essaient d'atterrir près de la base.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"Tous les équipements, systèmes d'armements, munitions, matériel récupéré et Plateformes d'Armes Lourdes sont stockés dans les entrepôts. Cela inclus également la dotation en équipement des vaisseaux stationnés dans les hangars.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"Les extraterrestres vivants risquent de nécessiter un habitat spécial pour maintenir leurs fonctions vitales.  L'installation de détention peut contenir jusqu'à 10 formes de vie extraterrestres dans des unités indépendantes.\"\n  STR_LASER_DEFENSES_UFOPEDIA: \"Les défenses laser protègent de l'incursion des vaisseaux ennemis.\"\n  STR_PLASMA_DEFENSES_UFOPEDIA: \"Les défenses à plasma fournissent une protection puissante et efficace contre l'intrusion des vaisseaux ennemis.\"\n  STR_FUSION_BALL_DEFENSES_UFOPEDIA: \"Les missiles à ogives de fusion sont la défense la plus efficace contre les attaques extraterrestres.  Ces missiles créent une implosion antimatière qui détruit tout dans un rayon spécifique.\"\n  STR_GRAV_SHIELD_UFOPEDIA: \"Le bouclier de gravité repousse les extraterrestres qui essaient d'atterrir près de la base assez longtemps pour que tous les systèmes de défense puissent tirer à nouveau.  Dans la pratique, ceci double l'efficacité de tous les systèmes de défense de votre base.\"\n  STR_MIND_SHIELD_UFOPEDIA: \"Comme les vaisseaux extraterrestres détectent les humains grâce aux ondes cérébrales, la contre-mesure la plus efficace consiste à protéger la base de ces ondes.  Ceci réduira de façon importante les chances de détection par les vaisseaux extraterrestres.\"\n  STR_PSIONIC_LABORATORY_UFOPEDIA: \"Le labo psionique peut évaluer le potentiel psionique de tous les soldats de la base et leur donner l'entraînement nécessaire pour utiliser leurs compétences psioniques.  Chaque labo peut entraîner jusqu'à 10 soldats.  L'entraînement est attribué à la fin de chaque mois.  Les compétences psioniques utilisées en association avec un Psi-Amp peuvent être utilisées pour les attaques psioniques pendant le combat.\"\n  STR_HYPER_WAVE_DECODER_UFOPEDIA: \"Les communications extraterrestres se font par ondes supra-dimensionnelles qui voyagent presque instantanément.  Le décodeur intercepte les transmissions d'OVNIS et décode l'information.  Celle-ci indique le type de l'OVNI, la race extraterrestre et le type d'activité.\"\n  STR_HANGAR_UFOPEDIA: \"Chaque hangar peut abriter un appareil.  Il est équipé avec des installations pour l'entretien, le ravitaillement et la réparation des chasseurs et transporteurs X-Com.  Chaque appareil posté dans une base doit avoir un hangar libre qui lui est affecté et qui ne peut être utilisé par aucun autre, même si l’occupant principal est parti en mission.\"\n  STR_PISTOL_UFOPEDIA: \"Le pistolet X-Com standard est un semi-automatique de gros calibre pouvant contenir 12 cartouches.\"\n  STR_RIFLE_UFOPEDIA: \"Un fusil de haute précision calibre 6,7mm avec chargeur 20 coups et guidage laser.\"\n  STR_HEAVY_CANNON_UFOPEDIA: \"Le canon lourd est une arme dévastatrice mais encombrante.  Sa versatilité vient du fait qu'il peut contenir trois types de munitions : perforantes, incendiaires et explosives.\"\n  STR_AUTO_CANNON_UFOPEDIA: \"Le canon automatique combine la versatilité et la puissance d'un canon lourd avec une cadence de tir plus rapide.\"\n  STR_ROCKET_LAUNCHER_UFOPEDIA: \"Le lance-roquettes est un système guidé au laser qui peut tirer trois types différents de roquettes.\"\n  STR_LASER_PISTOL_UFOPEDIA: \"Le pistolet laser est une réalisation efficace de la technologie moderne.  Il conjugue la commodité d'un pistolet avec un tir rapide et précis.\"\n  STR_LASER_RIFLE_UFOPEDIA: \"Le fusil laser est une version plus puissante et plus précise du pistolet décrit précédemment.\"\n  STR_HEAVY_LASER_UFOPEDIA: \"Le laser lourd est encombrant, mais extrêmement efficace.\"\n  STR_GRENADE_UFOPEDIA: \"Cette grenade standard a un détonateur fiable et sophistiqué, permettant un contrôle de précision.\"\n  STR_SMOKE_GRENADE_UFOPEDIA: \"Les grenades fumigènes sont utiles pour se mettre à l'abri durant des combats à découvert.  À utiliser avec précaution car elles peuvent également avantager l'ennemi.\"\n  STR_PROXIMITY_GRENADE_UFOPEDIA: \"Une grenade de proximité est lancée comme une grenade ordinaire mais une fois au sol elle est déclenchée par tout mouvement proche.  Il faut beaucoup d'habileté et de précaution pour utiliser correctement ces armes.\"\n  STR_HIGH_EXPLOSIVE_UFOPEDIA: \"Cet explosif ne doit être utilisé que pour la démolition.  Évacuez les lieux de l'explosion.\"\n  STR_MOTION_SCANNER_UFOPEDIA: \"Cet appareil sophistiqué utilise toutes sortes de détecteurs et d'algorithmes informatiques évolués pour identifier les mouvements des unités ennemies.  Cependant, il faut de l'expérience pour l'utiliser correctement.  Cliquez sur l'icône scanneur de mouvement sur l'affichage tactique.  Sélectionnez 'Utiliser Scanneur' dans le menu.  L'affichage du scanneur montre une flèche au centre qui représente la direction vers laquelle le soldat est tourné (Le Nord est en haut).  Les points clignotants montrent les unités qui ont récemment changé de position.  Des unités importantes, ou des unités se déplaçant rapidement, seront représentées par des points plus grands.  Les unités statiques ne seront pas détectées.\"\n  STR_MEDI_KIT_UFOPEDIA: \"La trousse de soins contient des médicaments, des calmants et des stimulants.  Pour utiliser la trousse de soins, vous devez vous tourner vers le soldat ayant besoin d'un traitement.  Si le soldat est assommé, vous devez vous pencher sur le corps.  Cliquez sur l'icône trousse de soins et sélectionnez 'utiliser trousse de soins' dans le menu.{NEWLINE}SOIGNER> Les parties du corps en rouge représentent des blessures.  Cliquez sur une partie du corps qui est blessée.  Cliquez sur le bouton 'Soigner'.  La blessure sera soignée et cela redonnera un peu de santé à la personne blessée.{NEWLINE}STIMULANT> Redonne de l'énergie et fait reprendre conscience aux soldats ayant été assommés.  Pour faire reprendre conscience à un soldat inanimé, penchez-vous directement sur le corps.{NEWLINE}CALMANT> Ramène le moral des soldats blessés à un niveau équivalent à la santé perdue du soldat.\"\n  STR_PSI_AMP_UFOPEDIA: \"Le Psi-amp ne peut être utilisé que par les soldats avec une compétence psionique. Pendant le combat, cliquez sur le Psi-amp, sélectionnez le type d'attaque, et sélectionnez une cible avec le curseur. Il y a deux types d'attaque psionique :{NEWLINE}PANIQUER L'UNITÉ> Si l'attaque est réussie, elle réduit le morale de la cible et peut la faire paniquer.{NEWLINE}CONTRÔLE MENTAL> Si l'attaque est réussie, vous gagnez le contrôle immédiat de l'unité ennemie comme si c'était votre unité. Il est plus difficile de réussir ce type d'attaque. \"\n  STR_STUN_ROD_UFOPEDIA: \"Cet objet ne peut être utilisé que dans le combat rapproché.  Il permet d'assommer un organisme vivant sans le tuer grâce à des chocs électriques.\"\n  STR_MIND_PROBE_UFOPEDIA: \"La sonde d'esprit est un périphérique de communication extraterrestre qui est utilisée pour prendre l'information directement des ondes cérébrales.  Les unités X-Com peuvent utiliser cette technique durant le combat pour connaître les caractéristiques des extraterrestres.  Cliquez sur la sonde d'esprit et l'option 'utiliser'.  Puis, cliquez sur un extraterrestre avec le curseur.\"\n  STR_PLASMA_PISTOL_UFOPEDIA: \"Les pistolets à plasma sont une arme extraterrestre fatale basée sur l'accélération des particules à l'intérieur d'un minuscule champ antigravitationnel.\"\n  STR_PLASMA_RIFLE_UFOPEDIA: \"C'est une arme puissante et dévastatrice basée sur l'accélération des particules à l'intérieur d'un minuscule champ antigravitationnnel.\"\n  STR_HEAVY_PLASMA_UFOPEDIA: \"Cet arme dotée d'une puissance dévastatrice est basée sur l'accélération des particules à l'intérieur d'un minuscule champ antigravitationnel.\"\n  STR_BLASTER_LAUNCHER_UFOPEDIA: \"Un lance-missiles guidé extraterrestre qui tire de puissantes 'bombes blaster'.  Lorsque vous cliquez pour tirer, vous voyez apparaître les points de repère que la bombe blaster suivra.  Lorsque vous avez positionné assez de points de repère, cliquez sur l'icône lancement spécial.\"\n  STR_SMALL_LAUNCHER_UFOPEDIA: \"Un petit lance-grenade qui tire des bombes assommantes.  Très utile pour capturer des extraterrestres vivants.\"\n  STR_ALIEN_GRENADE_UFOPEDIA: \"Cette arme fonctionne de la même façon qu'une grenade terrestre - mais elle est plus puissante.\"\n  STR_SMALL_SCOUT: \"Petit Éclaireur\"\n  STR_MEDIUM_SCOUT: \"Éclaireur Moyen\"\n  STR_LARGE_SCOUT: \"Grand Éclaireur\"\n  STR_HARVESTER: \"Moissonneur\"\n  STR_ABDUCTOR: \"Ravisseur\"\n  STR_TERROR_SHIP: \"Vaisseau de Terreur\"\n  STR_BATTLESHIP: \"Vaisseau de Combat\"\n  STR_SUPPLY_SHIP: \"Vaisseau Cargo\"\n  STR_RATING: \"ÉVALUATION> {0}\"\n  STR_RATING_TERRIBLE: \"TERRIBLE !\"\n  STR_RATING_POOR: \"MÉDIOCRE !\"\n  STR_RATING_OK: \"PASSABLE\"\n  STR_RATING_GOOD: \"BIEN !\"\n  STR_RATING_EXCELLENT: \"EXCELLENT !\"\n  STR_SCORE: \"SCORE\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"RAPPORT MENSUEL PROJET X-COM\"\n  STR_MONTH: \"Mois> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"Le Conseil des Nations participant au financement est jusqu'ici satisfait de vos progrès.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"Le Conseil des Nations participant au financement est très satisfait de vos excellents progrès.  Continuez comme ça.\"\n  STR_COUNCIL_IS_DISSATISFIED: \"Le Conseil des Nations participant au financement n'est pas satisfait de votre travail.  Vous devez améliorer votre efficacité à combattre la menace extraterrestre, sinon, il risque de mettre fin au projet.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"Vous n'avez pas réussi à combattre l'invasion extraterrestre et le conseil des nations participant au financement a malheureusement décidé de mettre fin au projet.  Chaque nation va s'occuper elle-même du problème comme elle l'entend.  Nous ne pouvons qu'espérer arriver à un accord avec ces forces apparemment hostiles, et souhaiter que la population s'entende avec les visiteurs extraterrestres.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} est particulièrement satisfait de votre aptitude à gérer la menace sur son territoire et a accepté d'augmenter son financement.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} sont particulièrement satisfaits de vos progrès dans le combat contre les incursions extraterrestres sur leur territoire, et ont accepté d'augmenter votre budget.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} et {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} n'est pas satisfait de votre aptitude à combattre l'activité extraterrestre sur son territoire et a décidé de réduire sa participation financière.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} sont mécontents de votre aptitude à contenir l'activité extraterrestre sur leur territoire, et ont décidé de réduire leur contribution financière.\"\n  STR_KNOTS: \"{0} nœuds\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} a signé un pacte secret avec des forces extraterrestres inconnues et s'est retiré du projet.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} ont signé un pacte secret avec des forces extraterrestres inconnues et se sont retirés du projet.\"\n  STR_MONTHLY_RATING: \"Évaluation Mensuelle> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Changement du Financement> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"Le conseil n'est pas satisfait de votre situation financière. Vous devez réduire vos dettes en dessous d'1 million de $ ou le projet sera terminé.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"LES TRANSMISSIONS D'HYPER-ONDES SONT DÉCODÉES\"\n  STR_CRAFT_TYPE: \"TYPE DE VAISSEAU\"\n  STR_RACE: \"RACE\"\n  STR_MISSION: \"MISSION\"\n  STR_ZONE: \"ZONE\"\n  STR_ALLOCATE_RESEARCH: \"Allouer Recherche\"\n  STR_ALLOCATE_MANUFACTURE: \"Allouer Fabrication\"\n  STR_NEW_YORK: \"New York\"\n  STR_WASHINGTON: \"Washington\"\n  STR_LOS_ANGELES: \"Los Angeles\"\n  STR_MONTREAL: \"Montréal\"\n  STR_HAVANA: \"La Havane\"\n  STR_MEXICO_CITY: \"Mexico\"\n  STR_CHICAGO: \"Chicago\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_DALLAS: \"Dallas\"\n  STR_BRASILIA: \"Brésil\"\n  STR_BOGOTA: \"Bogota\"\n  STR_BUENOS_AIRES: \"Buenos Aires\"\n  STR_SANTIAGO: \"Santiago\"\n  STR_RIO_DE_JANEIRO: \"Rio de Janeiro\"\n  STR_LIMA: \"Lima\"\n  STR_CARACAS: \"Caracas\"\n  STR_LONDON: \"Londres\"\n  STR_PARIS: \"Paris\"\n  STR_BERLIN: \"Berlin\"\n  STR_MOSCOW: \"Moscou\"\n  STR_ROME: \"Rome\"\n  STR_MADRID: \"Madrid\"\n  STR_BUDAPEST: \"Budapest\"\n  STR_LAGOS: \"Lagos\"\n  STR_CAIRO: \"Le Caire\"\n  STR_CASABLANCA: \"Casablanca\"\n  STR_PRETORIA: \"Pretoria\"\n  STR_NAIROBI: \"Nairobi\"\n  STR_CAPE_TOWN: \"Le Cap\"\n  STR_KINSHASA: \"Kinshasa\"\n  STR_ANKARA: \"Ankara\"\n  STR_DELHI: \"Delhi\"\n  STR_KARACHI: \"Karachi\"\n  STR_BAGHDAD: \"Bagdad\"\n  STR_TEHRAN: \"Téhéran\"\n  STR_BOMBAY: \"Bombay\"\n  STR_CALCUTTA: \"Calcutta\"\n  STR_TOKYO: \"Tokyo\"\n  STR_BEIJING: \"Pékin\"\n  STR_BANGKOK: \"Bangkok\"\n  STR_MANILA: \"Manille\"\n  STR_SEOUL: \"Séoul\"\n  STR_SINGAPORE: \"Singapour\"\n  STR_JAKARTA: \"Djakarta\"\n  STR_SHANGHAI: \"Shanghai\"\n  STR_HONG_KONG: \"Hong Kong\"\n  STR_NOVOSIBIRSK: \"Novossibirsk\"\n  STR_CANBERRA: \"Canberra\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_MELBOURNE: \"Melbourne\"\n  STR_PERTH: \"Perth\"\n  STR_PSI_TRAINING: \"Entraînement Psi\"\n  STR_PSIONIC_TRAINING: \"ENTRAINEMENT PSIONIQUE\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Capacité Psi-lab restante> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"Force{NEWLINE}Psionique\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"Progression{NEWLINE}/Compétence Psionique\"\n  STR_PSI_AMP: \"Psi-Amp\"\n  STR_IN_TRAINING: \"{NEWLINE}Inscrit ?\"\n  STR_TARGETTED_BY: \"VISÉ PAR :\"\n  STR_WEAPONS_CREW_HWPS: \"ARMES/{NEWLINE}ÉQUIPAGE/PAL\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"à court de carburant,{NEWLINE}retourne à la base\"\n  STR_SOLDIER_LIST: \"Liste des Soldats\"\n  STR_RANK_: \"GRADE> {ALT}{0}\"\n  STR_MISSIONS: \"MISSIONS> {ALT}{0}\"\n  STR_KILLS: \"VICTIMES> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"GUÉRISON DE BLESSURE> {ALT}{0}\"\n  STR_TIME_UNITS: \"UNITÉS DE TEMPS\"\n  STR_STAMINA: \"ENDURANCE\"\n  STR_HEALTH: \"SANTÉ\"\n  STR_BRAVERY: \"COURAGE\"\n  STR_REACTIONS: \"RÉACTIONS\"\n  STR_FIRING_ACCURACY: \"PRÉCISION AU TIR\"\n  STR_THROWING_ACCURACY: \"PRÉCISION AU LANCER\"\n  STR_STRENGTH: \"FORCE\"\n  STR_PSIONIC_STRENGTH: \"FORCE PSIONIQUE\"\n  STR_PSIONIC_SKILL: \"COMPÉTENCE PSIONIQUE\"\n  STR_NEW_RANK: \"NOUVEAU GRADE\"\n  STR_PROMOTIONS: \"Promotions\"\n  STR_SOLDIERS_UC: \"SOLDATS\"\n  STR_TANK_CANNON_UFOPEDIA: \"Les Plates-formes d'Armes Lourdes sont conçus pour appuyer les escouades X-Com. Ces unités, ayant à la fois une grande puissance de feu et un blindage résistant, sont idéales pour les combats à découvert.  Assurez-vous que vous avez suffisamment de munitions dans vos stocks pour réarmer les chars d'assauts.  Ils s'arment automatiquement lorsque vous les affectez à une escouade.\"\n  STR_TANK_ROCKET_LAUNCHER_UFOPEDIA: \"Cette plate-forme d'arme lourde automatique est armée de puissantes roquettes.  C'est une arme dévastatrice pour tout ennemi extraterrestre.  Assurez-vous que vos stocks sont approvisionnés en roquettes PAL.\"\n  STR_TANK_LASER_CANNON_UFOPEDIA: \"Les armes laser sont un complément utile aux PAL.  Elles ont une grande puissance de feu et n'ont pas de limite de munitions.\"\n  STR_HOVERTANK_PLASMA_UFOPEDIA: \"La technologie extraterrestre a réssuscité les PAL.  La maniabilité du voyage aérien et la puissance des rayons à plasma est une combinaison mortelle.\"\n  STR_HOVERTANK_LAUNCHER_UFOPEDIA: \"Cet \\\"aérochar\\\" possède un lance-missile, à boules de fusion, capable de faire d'immenses dégâts.  Utilisez-le avec beaucoup de précaution.  Il vous faudra fabriquer les boules de fusion pour charger ces PAL.  Une boule de fusion est une arme guidée intelligente.  Pour tirer, vous devez sélectionner un certain nombre de 'points de repère' avec le curseur puis cliquer sur l'icône lancer pour tirer la boule de fusion.\"\n  STR_HEAVY_PLASMA_CLIP_UFOPEDIA: \"Cet objet compact est utilisé comme munition pour un canon lourd à plasma.  Il contient une petite quantité d'Elerium.\"\n  STR_PLASMA_RIFLE_CLIP_UFOPEDIA: \"Ce petit objet est utilisé comme source d'énergie pour un fusil à plasma - une arme extraterrestre de puissance moyenne.  Contient une petite quantité d'Elerium.\"\n  STR_PLASMA_PISTOL_CLIP_UFOPEDIA: \"Source d'énergie pour le petit pistolet à plasma extraterrestre.  Contient de l'Elerium - source de toute puissance extraterrestre.\"\n  STR_STUN_BOMB_UFOPEDIA: \"La bombe assommante est utilisée pour capturer des spécimens humains vivants, mais elle peut aussi être utilisée contre la plupart des races extraterrestres.  On la tire d'un petit lance-grenade.\"\n  STR_ALIEN_RESEARCH_UFOPEDIA: \"Les missions de recherches extraterrestres sont lancés dans le but de rassembler des informations élémentaires sur la Terre et ses habitants.  Ils utilisent généralement des petits véhicules, et atterrissent parfois dans les zones désertes.  Ce type d'activité extraterrestre est une moindre menace pour X-Com et ont peu d'impacts sur  les gouvernements ou les populations.\"\n  STR_ALIEN_HARVEST_UFOPEDIA: \"Les extraterrestres utilisent la faune terrienne de différentes façons.  Les animaux sont secrètement enlevés, puis ramenés après qu'on leur ait enlevé plusieurs organes.  Les témoignages de mutilations du bétail coïncident généralement avec des apparitions d'OVNIS.  Ce type d'activité extraterrestre préoccupe beaucoup les gouvernements et provoque une grande inquiétude parmi la population.  Ce type d'activité se produit généralement en campagne.  La théorie derrière cette 'moisson extraterrestre' serait que les races extraterrestres ont à l'origine 'ensemencé' la planète de sa flore et de sa faune, et qu'ils reviennent aujourd'hui pour récolter les fruits qu'ils ont semés.\"\n  STR_ALIEN_ABDUCTION_UFOPEDIA: \"C'est le type d'activité alien le plus insidieux.  De nombreux témoignages font état d'enlèvements par les aliens, et ceci malgré les efforts faits par les extraterrestres pour effacer cette expérience de la mémoire de leurs victimes.  Les personnes enlevées disent avoir été soumises à des examens physiques humiliants, et parlent même d'implantations de fœtus aliens et d'expériences génétiques étranges.  Le but de cette activité semble être lié à l'étude des mutations génétiques et à la manipulation du propre code génétique des extraterrestres.  Cette activité provoque une vive inquiétude, et se produit dans les zones peuplées ou les villes.\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"Si les extraterrestres peuvent revêtir une apparence humaine, alors il est fort probable que les gouvernements de la Terre soient infiltrés. Un regain anormal d'activité OVNIS à proximité des grandes villes pourraient signifier que des agents extraterrestres tentent de faire pression sur des officiels au plus haut niveau dans le but de ratifier un pacte. En échange des connaissances et technologies supérieures aux nôtres , les extraterrestres pourraient mener leurs activités sans entraves. Cette mission extraterrestre représente la pire menace pour X-Com, car si un gouvernement accepte de signer ce pacte il cessera alors de financer X-Com.\"\n  STR_ALIEN_BASE_UFOPEDIA: \"Les extraterrestres vont construire des bases souterraines secrètes dans des endroits isolés.  Après quelques vols de reconnaissance, une intense activité OVNIS se produira pendant la phase de construction de la base. Ces bases sont sans doute équipés de laboratoires pour réaliser des expériences sur les humains qui ont été enlevés. De plus d'importants stocks sont probablement entreposés pour développer leurs activités dans la région. Une intense activité extraterrestre sans la présence d'OVNIS devrait donc nous alerter sur la présence d'une base extraterrestre dans le secteur.  Afin de localiser une base, un vaisseau X-Com doit patrouiller dans une région pendant quelques heures pour avoir une chance de la détecter.\"\n  STR_ALIEN_TERROR_UFOPEDIA: \"Pour terroriser une ville, les extraterrestres vont déployer des forces spéciales avec des pouvoirs terrifiants.  Les civils seront directement menacés et les gouvernements seront forcés d'évacuer des zones étendus.  Le but essentiel de cette activité est de créer suffisamment d'hystérie collective pour que les gouvernements remettent en cause le projet X-Com.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"fssdg\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"Une fois qu'une base extraterrestre est construite, elle est régulièrement approvisionnée par un vaisseau cargo spécial.  Si l'un de ses vaisseaux est détecté lors de son atterrissage, vous pouvez alors être certain qu'il y a une base extraterrestre à proximité.\"\n  STR_SMALL_SCOUT_UFOPEDIA: \"Ce minuscule vaisseau est utilisé essentiellement pour la reconnaissance ou la recherche.  Il précède normalement des vaisseaux plus grands au début d'une mission extraterrestre.\"\n  STR_MEDIUM_SCOUT_UFOPEDIA: \"Un vaisseau éclaireur de taille moyenne qui ne représente pas une grande menace pour les forces terrestres.  Il apparaît normalement avant des vaisseaux plus grands durant les missions.\"\n  STR_LARGE_SCOUT_UFOPEDIA: \"Le vaisseau éclaireur extraterrestre le plus grand est un vaisseau utilisé dans tous les types de missions extraterrestres.\"\n  STR_HARVESTER_UFOPEDIA: \"Le moissonneur a une trappe à sa base et est équipé d'un treuil pour hisser le bétail ou d'autres animaux.  Les scalpels laser sont utilisés pour extraire les morceaux désirés et la carcasse est jetée au sol.  Il y a également des conteneurs de stockage pour les parties du corps.\"\n  STR_ABDUCTOR_UFOPEDIA: \"Ce vaisseau est équipé d'une salle d'examen utilisée pour d'horribles expériences sur des sujets humains.  La victime est paralysée par des pouvoirs télépathiques, mais reste consciente sur la table d'opération.\"\n  STR_TERROR_SHIP_UFOPEDIA: \"Le vaisseau de terreur est équipé d'installations lui permettant de transporter de lourdes armes de terreur ou des créatures.  Il est utilisé pour transporter des terroristes extraterrestres jusque dans les zones peuplées.\"\n  STR_BATTLESHIP_UFOPEDIA: \"Le vaisseau de combat est le vaisseau extraterrestre le plus grand et le plus puissant.  C'est normalement le vaisseau principal des missions extraterrestres, il est équipé d'armes puissantes et de nombreux membres d'équipage.\"\n  STR_SUPPLY_SHIP_UFOPEDIA: \"Le vaisseau cargo est utilisé durant la construction de bases extraterrestres ou pour l'approvisionnement de bases existantes.  Il transporte des conteneurs de nourriture extraterrestre et des chambres de reproduction.\"\n  STR_DISMANTLE: \"Démonter\"\n  STR_FACILITY_IN_USE: \"INSTALLATION UTILISÉE\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"IMPOSSIBLE DE DÉMONTER L'INSTALLATION !{SMALLLINE}Toutes les installations de la base doivent être reliées à l'ascenseur d'accès.\"\n  STR_TRANSFER_ITEMS_TO: \"Transférer Matériel Vers {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"PAS D'INSTALLATION DE DÉTENTION DES EXTRATERRESTRES POUR LE TRANSFERT !{SMALLLINE}Les extraterrestres vivants ont besoin d'une installation de détention des extraterrestres pour survivre \"\n  STR_AMOUNT_AT_DESTINATION: \"QUANTITE A{NEWLINE}DESTINATION\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"L'extraterrestre meurt car il n'y a pas d'installation de détention des extraterrestres\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"PAS DE LOGEMENT DE LIBRE !{SMALLLINE}La base de destination n'a pas assez de place dans les baraquements pour l'équipage affecté au vaisseau.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"PAS SUFFISAMENT D'ESPACE DE STOCKAGE !{SMALLLINE}La base de destination n'a pas suffisament de place pour l'équippement attribué au vaisseau.\"\n  STR_ITEMS_ARRIVING: \"Le Matériel Arrive\"\n  STR_DESTINATION_UC: \"DESTINATION\"\n  STR_PISTOL: \"Pistolet\"\n  STR_PISTOL_CLIP: \"Chargeur de Pistolet\"\n  STR_RIFLE: \"Fusil\"\n  STR_RIFLE_CLIP: \"Chargeur de Fusil\"\n  STR_HEAVY_CANNON: \"Canon Lourd\"\n  STR_HC_AP_AMMO: \"Munitions CL-PA\"\n  STR_HC_HE_AMMO: \"Munitions CL-E\"\n  STR_HC_I_AMMO: \"Munitions CL-I\"\n  STR_AUTO_CANNON: \"Canon Auto\"\n  STR_AC_AP_AMMO: \"Munitions CA-PA\"\n  STR_AC_HE_AMMO: \"Munitions CA-E\"\n  STR_AC_I_AMMO: \"Munitions CA-I\"\n  STR_ROCKET_LAUNCHER: \"Lance-Roquettes\"\n  STR_SMALL_ROCKET: \"Petite Roquette\"\n  STR_LARGE_ROCKET: \"Grande Roquette\"\n  STR_INCENDIARY_ROCKET: \"Roquette Incendiaire\"\n  STR_GRENADE: \"Grenade\"\n  STR_SMOKE_GRENADE: \"Grenade Fumigène\"\n  STR_PROXIMITY_GRENADE: \"Grenade de Proximité\"\n  STR_HIGH_EXPLOSIVE: \"Explosif\"\n  STR_STUN_ROD: \"Matraque électrique\"\n  STR_HEAVY_PLASMA: \"Canon Plasma Lourd\"\n  STR_HEAVY_PLASMA_CLIP: \"Chargeur de Canon Plasma Lourd\"\n  STR_PLASMA_RIFLE: \"Fusil Plasma\"\n  STR_PLASMA_RIFLE_CLIP: \"Chargeur de Fusil Plasma\"\n  STR_PLASMA_PISTOL: \"Pistolet Plasma\"\n  STR_PLASMA_PISTOL_CLIP: \"Chargeur de Pistolet Plasma\"\n  STR_BLASTER_LAUNCHER: \"Lanceur Blaster\"\n  STR_BLASTER_BOMB: \"Bombe Nucléaire\"\n  STR_SMALL_LAUNCHER: \"Petit Lanceur\"\n  STR_STUN_BOMB: \"Bombe Assommante\"\n  STR_ALIEN_GRENADE: \"Grenade Extraterrestre\"\n  STR_ELERIUM_115: \"Elerium-115\"\n  STR_MIND_PROBE: \"Sonde d'Esprit\"\n  STR_SECTOID_CORPSE: \"Corps Sectoïde\"\n  STR_SNAKEMAN_CORPSE: \"Corps Homme-Serpent\"\n  STR_ETHEREAL_CORPSE: \"Corps Ethereal\"\n  STR_MUTON_CORPSE: \"Corps Muton\"\n  STR_FLOATER_CORPSE: \"Corps Flottant\"\n  STR_CELATID_CORPSE: \"Corps Célatide\"\n  STR_SILACOID_CORPSE: \"Corps Silacoïde\"\n  STR_CHRYSSALID_CORPSE: \"Corps Chryssalid\"\n  STR_REAPER_CORPSE: \"Corps Reaper\"\n  STR_SECTOPOD_CORPSE: \"Corps de Sectopode\"\n  STR_CYBERDISC_CORPSE: \"Corps Cyberdisque\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"Munitions insuffisantes pour équiper ces PAL {SMALLLINE}{0} {1} requis.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Matériel Insuffisant pour rééquiper entièrement l'escouade\"\n  STR_MARS_CYDONIA_LANDING: \"Mars : Atterrissage sur Cydonia\"\n  STR_MARS_CYDONIA_LANDING_BRIEFING: \"Votre vaisseau Talion a atterri dans la région de Cydonia, sur la surface de Mars.  Nos informations indiquent que l'une des pyramides contient un ascenseur vert menant à un complexe souterrain.  Lorsque vous aurez rassemblé tous vos soldats près de l'ascenseur, cliquez sur l'icône 'Abandonner mission' pour passer à l'étape suivante.\"\n  STR_MARS_THE_FINAL_ASSAULT: \"Mars : L'assaut final\"\n  STR_MARS_THE_FINAL_ASSAULT_BRIEFING: \"L'ascenseur de la pyramide emmène vos soldats fatigués sous la surface de la planète.  Ils arrivent au cœur d'un grand complexe de tunnels et de salles.  Le cerveau extraterrestre est caché quelque part dans le labyrinthe.  Il doit être détruit si vous voulez sauver la Terre de l'esclavage extraterrestre.{NEWLINE}{NEWLINE}Bonne chance !\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Vous devez étudier{NEWLINE}{0}{NEWLINE}avant de fabriquer{NEWLINE}{1}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"Les extraterrestres ont détruit la base non défendue {0}\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"Les agents X-Com ont localisé une base extra-terrestre en {0}\"\n  STR_STANDOFF: \"ATTENTE\"\n  STR_CAUTIOUS_ATTACK: \"ATTAQUE PRUDENTE\"\n  STR_STANDARD_ATTACK: \"ATTAQUE STANDARD\"\n  STR_AGGRESSIVE_ATTACK: \"ATTAQUE AGRESSIVE\"\n  STR_DISENGAGING: \"DÉSENGAGEMENT\"\n  STR_UFO_HIT: \"L'OVNI EST TOUCHÉ !\"\n  STR_UFO_CRASH_LANDS: \"L'OVNI S'ÉCRASE !\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Réduction en mode attente seulement\"\n  STR_UFO_RETURN_FIRE: \"L'OVNI RIPOSTE !\"\n  STR_INTERCEPTOR_DAMAGED: \">>>INTERCEPTEUR ENDOMMAGÉ<<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>>INTERCEPTEUR DÉTRUIT<<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"L'OVNI DÉPASSE L'INTERCEPTEUR !\"\n  STR_ALIENS_TERRORISE: \"TERREUR EXTRATERRESTRE\"\n  STR_LONG_RANGE_DETECTION: \"Détection Longue Portée\"\n  STR_STORES_UC: \"STOCK\"\n  STR_DIFFICULTY_LEVEL: \"Niveau de difficulté\"\n  STR_INTERCEPT: \"INTERCEPTER\"\n  STR_BASES: \"BASES\"\n  STR_GRAPHS: \"GRAPHIQUES\"\n  STR_UFOPAEDIA_UC: \"OVNIPÉDIE\"\n  STR_OPTIONS_UC: \"OPTIONS\"\n  STR_FUNDING_UC: \"BUDGET\"\n  STR_5_SECONDS: \"5 s\"\n  STR_1_MINUTE: \"1 min\"\n  STR_5_MINUTES: \"5 min\"\n  STR_30_MINUTES: \"30 min\"\n  STR_1_HOUR: \"1 heure\"\n  STR_1_DAY: \"1 jour\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"Rapport de Performances Xcom\"\n  STR_ENTER_NAME: \"Entrer nom\"\n  STR_PERFORMANCE_RATING: \"Évaluation de Performance\"\n  STR_VICTORY_DATE: \"Date de victoire\"\n  STR_ELECTRO_FLARE: \"Balise Lumineuse\"\n  STR_ELECTRO_FLARE_UFOPEDIA: \"Cette balise éclairante produit une lumière vive lorsqu'elle est lancée.  Ceci éclaire les unités ennemies proches lors des missions de nuit.\"\n  STR_MONTHLY_COSTS: \"Coûts Mensuels\"\n  STR_CRAFT_RENTAL: \"Location de Vaisseaux\"\n  STR_SALARIES: \"Salaires\"\n  STR_BASE_MAINTENANCE: \"Entretien de la Base\"\n  STR_COST_PER_UNIT: \"Coût par Unité\"\n  STR_QUANTITY: \"Quantité\"\n  STR_TOTAL: \"Total\"\n  STR_IN_PSIONIC_TRAINING: \"En Entraînement Psionique\"\n  STR_BLASTER_BOMB_UFOPEDIA: \"Ce dispositif est un missile explosif, équipé, d'un système de guidage intelligent.  Il est tiré d'un lanceur blaster.\"\n  STR_FRONT_ARMOR: \"ARMURE AVANT\"\n  STR_LEFT_ARMOR: \"ARMURE GAUCHE\"\n  STR_RIGHT_ARMOR: \"ARMURE DROITE\"\n  STR_REAR_ARMOR: \"ARMURE ARRIÈRE\"\n  STR_UNDER_ARMOR: \"ARMURE DE DESSOUS\"\n  STR_ROUNDS: \"Cartouches\"\n  STR_UNIT: \"UNITÉ> {0}\"\n  STR_ENERGY: \"ÉNERGIE\"\n  STR_MORALE: \"MORAL\"\n  STR_ARMOR_: \"ARMURE> {0}\"\n  STR_FRONT_ARMOR_UC: \"ARMURE AVANT\"\n  STR_LEFT_ARMOR_UC: \"ARMURE GAUCHE\"\n  STR_RIGHT_ARMOR_UC: \"ARMURE DROITE\"\n  STR_REAR_ARMOR_UC: \"ARMURE ARRIÈRE\"\n  STR_SKILLS: \"COMPÉTENCES> {0}\"\n  STR_LEVEL: \"NIVEAU> {0}\"\n  STR_HEAD: \"TÊTE\"\n  STR_TORSO: \"TORSE\"\n  STR_RIGHT_ARM: \"BRAS DROIT\"\n  STR_LEFT_ARM: \"BRAS GAUCHE\"\n  STR_RIGHT_LEG: \"JAMBE DROITE\"\n  STR_LEFT_LEG: \"JAMBE GAUCHE\"\n  STR_PAIN_KILLER: \"CALMANT\"\n  STR_STIMULANT: \"STIMULANT\"\n  STR_HEAL: \"SOIGNER\"\n  STR_TIME_UNITS_SHORT: \"UT> {ALT}{0}\"\n  STR_WEIGHT: \"Poids> {ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"Réact> {ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"Cmp.P> {ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"For.P> {ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Objet Extraterrestre\"\n  STR_AMMO_ROUNDS_LEFT: \"MUNITIONS :{NEWLINE}CARTOUCHES{NEWLINE}RESTANTES={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Calm> {ALT}{0}{ALT}{NEWLINE}Stim> {ALT}{1}{ALT}{NEWLINE}Soin> {ALT}{2}\"\n  STR_THROW: \"Lancer\"\n  STR_AUTO_SHOT: \"Tir Automatique\"\n  STR_SNAP_SHOT: \"Tir Rapide\"\n  STR_AIMED_SHOT: \"Tir Précis\"\n  STR_STUN: \"Assommer\"\n  STR_PRIME_GRENADE: \"Armer Grenade\"\n  STR_USE_SCANNER: \"Utiliser Scanner\"\n  STR_USE_MEDI_KIT: \"Utiliser Trousse de Soins\"\n  STR_LAUNCH_MISSILE: \"Lancer Missile\"\n  STR_ACCURACY_SHORT: \"Pr> {ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Unités de Temps Insuffisantes !\"\n  STR_NOT_ENOUGH_ENERGY: \"Énergie Épuisée !\"\n  STR_NO_ROUNDS_LEFT: \"Plus de Munitions !\"\n  STR_NO_AMMUNITION_LOADED: \"Pas de Munitions Chargées !\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Mauvaise Munition pour cette Arme !\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"L'Arme est Déjà Chargée !\"\n  STR_NO_LINE_OF_FIRE: \"Pas de Ligne de Tir !\"\n  STR_GRENADE_IS_ACTIVATED: \"La Grenade est Activée !\"\n  STR_GRENADE_IS_DEACTIVATED: \"La Grenade est Désactivée !\"\n  STR_THERE_IS_NO_ONE_THERE: \"Il n'y a Personne ici !\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Impossible d'utiliser Objet Extraterrestre sans recherche !\"\n  STR_OUT_OF_RANGE: \"Hors de Portée !\"\n  STR_UNABLE_TO_THROW_HERE: \"Impossible de Lancer à cet Endroit !\"\n  STR_SET_TIMER: \"Détonateur\"\n  STR_HIDDEN_MOVEMENT: \"MOUVEMENT CACHÉ\"\n  STR_TURN: \"TOUR> {0}\"\n  STR_SIDE: \"CAMP> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Cliquez pour continuer\"\n  STR_MIND_CONTROL: \"Contrôle de l'Esprit\"\n  STR_PANIC_UNIT: \"Panique de l'Unité\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Attaque Psionique Réussie\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Contrôle de l'Esprit Réussi\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}a perdu son sang-froid\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}a perdu son sang-froid\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}a paniqué\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}a paniqué\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Extraterrestres\"\n  STR_RIGHT_HAND: \"MAIN DROITE\"\n  STR_LEFT_HAND: \"MAIN GAUCHE\"\n  STR_RIGHT_SHOULDER: \"ÉPAULE DROITE\"\n  STR_LEFT_SHOULDER: \"ÉPAULE GAUCHE\"\n  STR_BACK_PACK: \"SAC À DOS\"\n  STR_BELT: \"CEINTURE\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}est sous contrôle extraterrestre\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}est sous contrôle extraterrestre\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}a perdu connaissance\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}a perdu connaissance\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}a succombé à une blessure mortelle\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}a succombé à une blessure mortelle.\"\n  STR_USE_MIND_PROBE: \"Utiliser Sonde d'Esprit\"\n  STR_FATAL_WOUNDS: \"BLESSURES CRITIQUES\"\n  STR_UNDER_ARMOR_UC: \"ARMURE DE DESSOUS\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Unités de temps réservées pour le tir rapide\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Unités de temps réservées pour le tir automatique\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Unités de temps réservées pour le tir précis\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Unités de temps réservées pour s'agenouiller\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"UTs réservées pour s'agenouiller et tirer\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} Unité dans Vaisseau X-Com\"\n    many: \"{N} Unités dans Vaisseau X-Com\"\n    other: \"{N} Unités dans Vaisseau X-Com\"\n  STR_UNITS_OUTSIDE:\n    one: \"{N} Unité laissée à l'extérieur\"\n    many: \"{N} Unités laissées à l'extérieur\"\n    other: \"{N} Unités laissées à l'extérieur\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} Unité en Zone d’Insertion\"\n    many: \"{N} Unités en Zone d’Insertion\"\n    other: \"{N} Unités en Zone d’Insertion\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} Unité en Zone d'Extraction\"\n    many: \"{N} Unités en Zone d'Extraction\"\n    other: \"{N} Unités en Zone d'Extraction\"\n  STR_ABORT_MISSION_QUESTION: \"Abandonner la Mission ?\"\n  STR_CORPSE: \"Corps\"\n  STR_UNLOAD_CRAFT: \"Décharger\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}a été tué\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}a été tué\"\n  STR_HIT_MELEE: \"Mêlée\"\n  STR_GROUND: \"SOL\"\n  STR_LIVING_QUARTERS_PLURAL: \"Baraquements\"\n  STR_LIST_ITEM: \"OBJET\"\n  STR_PERSONAL_ARMOR_UFOPEDIA: \"Réalisée à l'aide des alliages E.T. récemment découverts, cette nouvelle armure donne une meilleure chance à nos hommes dans le combat face à la menace extraterrestre.\"\n  STR_POWER_SUIT_UFOPEDIA: \"Une excellente nouvelle protection pour les soldats, cette armure est alimentée par un micro-réacteur à Elerium et améliore grandement la vitesse et la force du porteur, elle offre actuellement la meilleure protection pour les troupes de combat.\"\n  STR_FLYING_SUIT_UFOPEDIA: \"Une version améliorée de l'armure énergétique, équipée d'une technologie anti-gravité extraterrestre pour permettre une pleine liberté de mouvement sur le champ de bataille.\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"Tous les extraterrestres sont morts lors du crash {NEWLINE}Procédure de récupération automatique activée\"\n  STR_RESET: \"Réinitialiser\"\n  STR_MEMORIAL: \"Mémorial\"\n  STR_DATE_UC: \"DATE\"\n  STR_SOLDIERS_RECRUITED_UC: \"SOLDATS RECRUTES> {ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"SOLDATS PERDUS> {ALT}{0}\"\n  MAP_CULTA: \"Ferme\"\n  MAP_FOREST: \"Forêt\"\n  MAP_JUNGLE: \"Jungle\"\n  MAP_MOUNT: \"Montagne\"\n  MAP_DESERT: \"Désert\"\n  MAP_POLAR: \"Pôle\"\n  MAP_URBAN: \"Ville\"\n  MAP_UBASE: \"Base Extra-Terrestre\"\n  MAP_XBASE: \"Base X-Com\"\n  MAP_MARS: \"Mars\"\n  STR_MIXED: \"Divers\"\n  STR_REMOVE_SELECTED: \"Supprimer les Spécimens Choisis\"\n  STR_LIVE_ALIENS: \"Spécimens{NEWLINE}Vivants\"\n  STR_DEAD_ALIENS: \"Spécimens{NEWLINE}Rejetés\"\n  STR_UNDER_INTERROGATION: \"Interrogatoire{NEWLINE}En cours\"\n  STR_CONTAINMENT_EXCEEDED: \"LA DÉTENTION DES E.T. EST SATURÉE !{SMALLLINE}Toutes les cellules à {0} sont occupées. Vous devez choisir les spécimens à conserver, et ceux à éliminer.\"\n  STR_MANAGE_CONTAINMENT: \"Gestion de la Détention des E.T.\"\n  STR_STORAGE_EXCEEDED: \"ESPACE DE STOCKAGE SATURÉ !{SMALLLINE}Espace de stockage insuffisant à {0}. Les objets en surplus doivent êtres vendus.\"\n  STR_GO_TO_BASE: \"Aller à la Base\"\n  STR_MELEE_ACCURACY: \"PRÉCISION EN MÊLÉE\"\n  STR_SELL_PRODUCTION: \"VENDRE\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Nécessite les deux mains libres !\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Matériel insuffisant pour appliquer le template\"\n  STR_UNLOAD_WEAPON: \"Décharger l'arme\"\n  STR_ALL_ITEMS: \"Tous les objets\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"LIMITE DE MATÉRIEL À BORD ATTEINTE !{SMALLLINE}Vous n'êtes pas autorisé à embarquer plus de {N} objets à bord de ce vaisseau.\"\n    many: \"LIMITE DE MATÉRIEL À BORD ATTEINTE !{SMALLLINE}Vous n'êtes pas autorisé à embarquer plus de {N} objets à bord de ce vaisseau.\"\n    other: \"LIMITE DE MATÉRIEL À BORD ATTEINTE !{SMALLLINE}Vous n'êtes pas autorisé à embarquer plus de {N} objets à bord de ce vaisseau.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}CENTRE DE CONTRÔLE DÉTRUIT{NEWLINE}Trouvez votre chemin jusqu'à l'entrée et abandonnez.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"Les installations X-Com ne peuvent être construites sous l'eau\"\n  STR_LEVEL_SHORT: \"{0}\"\n  STR_PERSONNEL: \"Personnel\"\n  STR_CRAFT_ARMAMENT: \"Vaisseau & Armement\"\n  STR_COMPONENTS: \"Composants\"\n  STR_SOLDIERS_RECRUITED: \"Soldats recrutés\"\n  STR_SOLDIERS_LOST: \"Soldats perdus\"\n  STR_TOTAL_UFOS: \"OVNIS détectés\"\n  STR_TOTAL_ALIEN_BASES: \"Bases alien découverte\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"FORCE PSI\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"TALENT PSI\"\n  FEMALE_CIVILIAN: \"Civile, Femme\"\n  MALE_CIVILIAN: \"Civil, Homme\"\n  CYBERDISC_WEAPON: \"Arme de Cyberdisque\"\n  REAPER_WEAPON: \"Arme de Reaper\"\n  CHRYSSALID_WEAPON: \"Arme de Chryssalid\"\n  CELATID_WEAPON: \"Arme de Célatide\"\n  SILACOID_WEAPON: \"Arme de Silacoïde\"\n  SECTOPOD_WEAPON: \"Arme de Sectopode\"\n  ZOMBIE_WEAPON: \"Arme de Zombi\"\n  ALIEN_PSI_WEAPON: \"Arme Psi Alien\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/hr.yml",
    "content": "hr:\n  STR_INTERCEPTOR_UFOPEDIA: \"RATNI ZRAKOPLOV S DVOSTRUKIM PULSNIM MOTOROM I POSEBNO ZAŠTIĆENIM ELEKTRONSKIM SUSTAVIMA. PREDSTAVLJA NAJBOLJU TEHNOLOGIJU NA ZEMLJI.\"\n  STR_FIRESTORM_UFOPEDIA: \"BORBENA LETJELICA. OVAJ JEDNOPILOTNI LOVAC PREDSTAVLJA KOPIJU KLASIČNOG IZVANZEMALJSKOG LETEĆEG TANJURA, S CENTRALNOM POGONSKOM JEDINICOM.\"\n  STR_AVALANCHE_UFOPEDIA: \"RAKETA ZRAK-ZRAK S NUKLEARNOM BOJEVOM GLAVOM, ALI I VELIKOM MASOM\"\n  STR_CANNON_UFOPEDIA: \"TOP VELIKE UDARNE SNAGE MOŽE ISPALITI PROTUOKLOPNE PROJEKTILE KOJI SU SPOSOBNI PROBITI DO 40 CENTIMATARA ČELIKA.\"\n  STR_LASER_CANNON_UFOPEDIA: \"KONVENCIONALNA LASERSKA ZRAKA KOJA CRPI ENERGIJU IZ KOMORE ZA ANTIMATERIJSKE REAKCIJE.\"\n  STR_SECTOID_UFOPEDIA: \"Sektoidska hijerarhija kreće se od vojnika do vođa sa snažnim psioničkim sposobnostima. Te psioničke sposobnosti im omogućuju da demoraliziraju protivnike, ili čak preuzmu kontrolu nad njihovim umovima. Sektoidi se često bave otimanjem ljudi i mrcvarenjem govedi. Otmice im služe za prikupljanje genetskog materijala za stvaranje križanaca i klonova koji mogu infiltrirati ljudsko društvo. Goveda im služe kao hrana i genetski materijal. Izgleda da je cilj ove rase stvoriti rasu nadmoćnih genetskih križanaca pomoću kojih bi povećali učinkovitost svog košnici-nalik društva.\"\n  STR_SECTOID_AUTOPSY: \"Autopsija Sektoida\"\n  STR_SNAKEMAN_UFOPEDIA: \"Ova se izvanzemaljska rasa razvila u ekstremnim uvjetima. Vrlo su žilavi i otporni na velike izmjene temperature. Pokretljivost im ovisi o zmijolikoj \\\"nozi\\\" koja ujedno štiti sve vitalne organe. Izgleda da su im ciljevi čisto grabežljivački te da se nalaze pod vrhovnim zapovjedništvom neke druge inteligencije koja nadzire i upravlja njihovim vojnim nadiranjima na Zemlju.\"\n  STR_SNAKEMAN_AUTOPSY: \"Autopsija Zmijolikog\"\n  STR_SNAKEMAN_AUTOPSY_UFOPEDIA: \"Koža je vrlo žilava i otporna na toplinu. Kardiovaskularni sustav dio je mišićnog sustava koji koristi princip hidraulike kako bi stvorio kretanje. Jedini pravi mišić je \\\"srce\\\". Sustav za razmnožavanje je vrlo efikasan. Razmnožavanje je aseksualno, te svaki Zmijoliki u svom tijelu nosi do pedeset jaja. Prepuštena sebi, ova bi vrsta mogla ozbiljno ugroziti život na zemlji.\"\n  STR_ETHEREAL_AUTOPSY: \"Autopsija Nebeskog\"\n  STR_MUTON_UFOPEDIA: \"Ovo čovjekoliko biće je fizički moćno i inteligentno. Poput zemaljskih mesojeda, ima tek za sirovo meso bilo koje vrste, koje mu je potrebno za preživljavanje. Izgleda da su ovisni o telepatskim zapovjedima rase poznate kao \\\"Nebeski\\\". Jednom kada su odvojeni od spomenute telepatske veze, njihov mentalni sustav se počinje raspadati te uskoro nastupa smrt. U tijelu su im prisutne kibernetske modifikacije koje ih čine nadmoćnim vojnicima. Jasno je da se radi o prvolinijskim trupama neke više inteligencije.\"\n  STR_MUTON_AUTOPSY: \"Autopsija Mutona\"\n  STR_MUTON_AUTOPSY_UFOPEDIA: \"\\\"Koža\\\" ovoga bića izgleda kao organski izrađen zaštitni oklop koji je transplantiran na tijelo. Prisutni su mnogi kibernetički implantati koji služe kako bi se ojačao kardiovaskularni sustav i osjetila. Izgleda da su organi za razmnožavanje bili odstranjeni kirurškim zahvatom. Jasno je da je život ovih nesretnih stvorenja ograničen na ratovanje i osvanjanje. Streljivo za probijanje oklopa nije vrlo učinkovito protiv njihove čvrste kože.\"\n  STR_CELATID_AUTOPSY: \"Autopsija Celatida\"\n  STR_SILACOID_UFOPEDIA: \"Ovo je biće bazirano na siliciju i proizvodi golemu količinu topline. Dovoljno je snažno da smrvi i pojede kamenje, koje završi u vrućoj jezgri bića. Posjeduje primitivnu inteligenciju te ga je moguće kontrolirati pomoću implantata ili telepatije. Surađuje s izvanzemaljskom rasom Mutona.\"\n  STR_SILACOID_AUTOPSY: \"Autopsija Silakoida\"\n  STR_CHRYSSALID_UFOPEDIA: \"Ovo se biće za blisku borbu služi kliještima poput rakovih. Brz metabolizam i velika snaga ovoga bića daju mu izvanrednu pokretljivost i brzinu. Umjesto da ubije svoj plijen, ono u njega usađuje jajašce i ubrizga otrov koji nesretnika pretvori u hodajućeg zombija. Ubrzo nakon toga iz žrtve će izaći novi Krisalid. Krisalidi prate radu Zmijolikih izvanzemaljaca. \"\n  STR_CHRYSSALID_AUTOPSY: \"Autopsija Krisalida\"\n  STR_CHRYSSALID_AUTOPSY_UFOPEDIA: \"Egzoskelet ovog bića je vrlo čvrst, ali začuđujuće ranjiv na eksplozije. Mozak je dobro razvijen, a brzina rasta stanica nevjerojatno visoka. Ovo biće u sebi nosi dvadeset jaja koje polaže u druge organizme. Vrlo je učinkovito kao oruđe terora.\"\n  STR_FLOATER_UFOPEDIA: \"Lebdeći su ponajprije vojnici i provoditelji terora. Po prirodi su grabežljive zvijeri, no genetski inženjering i kibernetska pojačanja pretvorili su ih u zastrašujuće ratnike. Donji dio tijela i većina unutarnih organa su im kirurški odstranjeni, te je na njihovo mjesto ugrađen sustav koji ih održava na životu. Taj implantat sadrži i antigravitacijski pogon koji biću dozvoljava da lebdi kroz zrak, iako uz poteškoće.\"\n  STR_FLOATER_AUTOPSY: \"Autopsija Lebdećeg\"\n  STR_REAPER_UFOPEDIA: \"Ovaj dvonožni mesojed posjeduje snažnu čeljust i golemi apetit. U mozgu ima određen broj moždanih implantata koje služe kako bi se nadziralo njegove aktivnosti. Primitivni grabežljivački instinkti ovoga bića ograničuju ga na zadatke povezane s teroriziranjem i uništavanjem. Kosci se obično nalaze u pratnji Lebdećih.\"\n  STR_REAPER_AUTOPSY: \"Autopsija Kosca\"\n  STR_REAPER_AUTOPSY_UFOPEDIA: \"Kosac posjeduje dva \\\"mozga\\\" i dva \\\"srca\\\" koja mu dozvoljavaju da se bori čak i ako je teško ranjen. Međutim, njegova je dlakava koža lako zapaljiva i time ranjiva na zapaljivo streljivo.\"\n  STR_SECTOPOD_UFOPEDIA: \"Sektopodi su roboti naoružani moćnim laserskim topom. Ove mehaničke zvijeri nalaze se pod telepatskom kontrolom bića poznatih kao \\\"Nebeski\\\". Sektopodi predstavljaju najsnažnije oružje terora dostupno izvanzemaljskim snagama.\"\n  STR_SECTOPOD_AUTOPSY: \"Autopsija Sektopoda\"\n  STR_SECTOPOD_AUTOPSY_UFOPEDIA: \"Ovaj je robot čvrsto građen te posjeduje oklopni egzoskelet koji može zaustaviti većinu projektila, posebno onih od plazma oružja. Međutim, osjetilni su mu sklopovi vrlo ranjivi na laserska oružja.\"\n  STR_CYBERDISC_AUTOPSY: \"Autopsija Kiberdiska\"\n  STR_CYBERDISC_AUTOPSY_UFOPEDIA: \"Kiberdisk je dobro zaštićen i vrlo otporan na eksplozije. Antigravitacijski sustav je previše oštećen da bismo mogli shvatiti način njegovog funkcioniranja.\"\n  STR_UFO_POWER_SOURCE_UFOPEDIA: \"Izvanzemaljski brodovi kao izvor energije koriste antimaterijski reaktor na Elerijski (kemijski element 115) pogon, pomoću stvaranja snažnih gravitacijskih valova kao i drugih oblika energije. Pretvorba materije u energiju je nevjerojatnih 99% učinkovita, pa stoga je iz malih količina Elerija moguće proizvesti nevjerojatnu količinu energije. Ovaj je pogon moguće reproducirati pomoću izvanzemaljskih legura.\"\n  STR_UFO_NAVIGATION_UFOPEDIA: \"Izvanzemaljske letjelice koriste sofisticirana računala za navigaciju na Zemlji i u svemiru. Sustav je utemeljen na umreženim optičkim procesorima. Korisničko sučelje je relativno jednostavno - navigator nadzire smjer gravitacijskih valova koji nastaju u energetskom izvoru letjelice, što mu omogućuje da ju pomakne u bilo kojem smjeru. Sustavom se mogu služiti i ljudi, te ga je moguće replicirati pomoću izvanzemaljskih legura i drugih materijala.\"\n  STR_ALIEN_REPRODUCTION_UFOPEDIA: \"Ove prostorije sadrže izvanzemaljske fetuse. Kontejneri su oblikovani na način koji sugerira da se izvanzemaljci oslanjaju isključivo na laboratorijsko razmnožavanje. Bogate prehrambene tvari omogućuju fetusu da se brzo razvije. Ovakav gotovo tvornički sustav omogućio bi stvaranje tisuća izvanzemaljskih klonova u vrlo kratkom vremenu. Bilo bi moguće prilagoditi ovaj proces za ljudska bića, ili za stvaranja križanaca čovjeka i izvanzemaljaca.\"\n  STR_ALIEN_ALLOYS_UFOPEDIA: \"Izvanzemaljske letjelice izgrađene su od posebih legura s jedinstvenim svojstvima. One su vrlo lagane i izdržljive, te ih je moguće oblikovati putem elektromagnetskih metoda. Ovaj materijal možemo reproducirati i iskoristiti u mnogim procesima proizvodnje.\"\n  STR_ELERIUM_115_UFOPEDIA: \"Ovaj element ima neobično svojstvo da proizvodi antimaterijsku energiju kada je izložen određenim česticama. Tako nastaju gravitacijski valovi i drugi oblici energije. Nije prirodno dosupan u Sunčevom sustavu te ga ne možemo reproducirati.\"\n  STR_CYDONIA_OR_BUST_UFOPEDIA: \"Postalo je jasno da se izvanzemaljskim hordama upravlja iz podzemne baze u Cydoniji - neobičnom području Marsa koje se sastoji od peterostranih piramida i velike formacije kamena koja nalikuje ljudskom licu. Nekad davno, prije više milijuna godina, na Marsu je prosperirala Cydonska civilizacija, ali nije nam poznato zašto je propala, ili koja je njena povezanost s trenutačnom izvanzemaljskom aktivnošću na tom području. Bez obzira na tu nepoznanicu, moramo poslati ekspediciju u Cydoniju. To je jedini način na koji možemo poraziti izvanzemaljce. Moramo uništiti \\\"mozak\\\" koji ih kontrolira. Zato nam je potrebno izgraditi letjelicu tipa \\\"Osvetnik\\\" i nakrcati ga najjačim snagama koje imamo na raspolaganju. Više ne možemo otkriti na ovaj način - potrebno je pričekati rezultate napada na Cydoniju.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"CENTRIRAJ NA MJESTO-VRIJEME=5 sek\"\n  STR_CANCEL_UC: \"PONIŠTI\"\n  STR_NONE: \"Ništa\"\n  STR_AVERAGE: \"Osrednje\"\n  STR_EXCELLENT: \"Izvrsno\"\n  STR_EQUIP_CRAFT: \"OPREMI LETJELICU\"\n  STR_RESEARCH: \"ISTRAŽIVANJE\"\n  STR_MANUFACTURE: \"PROIZVEDI\"\n  STR_PURCHASE_RECRUIT: \"KUPI/UNOVAČI\"\n  STR_SACK: \"OTPUSTI\"\n  STR_SELL_SACK_UC: \"PRODAJ/OTPUSTI\"\n  STR_BUILD_NEW_BASE: \"Izgradi Novu Bazu\"\n  STR_CANCEL: \"Poništi\"\n  STR_COST_UC: \"CIJENA>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Instalacija\"\n  STR_SCIENTISTS_AVAILABLE: \"Raspoloživo Znanstvenika>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Znanstvenika na Projektu>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Dostupno Laboratorijskog Prostora>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"ISTRAŽIVAČKI PROJEKT\"\n  STR_PROGRESS: \"NAPREDAK\"\n  STR_NEW_PROJECT: \"Novi Projekt\"\n  STR_CANCEL_PROJECT: \"PREKINI PROJEKT\"\n  STR_NEW_RESEARCH_PROJECTS: \"Nove istraživačke projekte\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"RASPOLOŽIVO ZNANSTVENIKA>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"DOSTUPNO LABORATORIJSKOG PROSTORA>{ALT}{0}\"\n  STR_INCREASE: \"Povećaj\"\n  STR_DECREASE: \"Smanji\"\n  STR_START_PROJECT: \"POKRENI PROJEKT\"\n  STR_CURRENT_PRODUCTION: \"TRENUTAČNA PROIZVODNJA\"\n  STR_ENGINEERS_AVAILABLE: \"Dostupno Inženjera>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Inženjeri na Projektu>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Dostupan Radionički Prostor>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Raspoloživa Sredstva>{ALT}{0}\"\n  STR_ITEM: \"PREDMET\"\n  STR_ENGINEERS__ALLOCATED: \"Inženjeri na Projektu\"\n  STR_UNITS_PRODUCED: \"Proizvedeno Jedinica\"\n  STR_TOTAL_TO_PRODUCE: \"Ukupno za Proizvesti\"\n  STR_COST__PER__UNIT: \"Trošak{NEWLINE}po{NEWLINE}Jedinici\"\n  STR_DAYS_HOURS_LEFT: \"Dana/sati ostalo\"\n  STR_NEW_PRODUCTION: \"Nova Proizvodnja\"\n  STR_PRODUCTION_ITEMS: \"Predmeti za Proizvodnju\"\n  STR_CATEGORY: \"KATEGORIJA\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} inženjerskih sati za proizvodnju jedne jedinice\"\n  STR_COST_PER_UNIT_: \"Trošak po jedinici>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Potrebno Prostora za Rad>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"POTREBNI SU POSEBNI MATERIJALI\"\n  STR_ITEM_REQUIRED: \"POTREBAN PREDMET\"\n  STR_UNITS_REQUIRED: \"POTREBNO JEDINICA\"\n  STR_UNITS_AVAILABLE: \"JEDINICA NA RASPOLAGANJU\"\n  STR_ENGINEERS_AVAILABLE_UC: \"DOSTUPNO INŽENJERA>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"DOSTUPAN RADIONIČKI PROSTOR>{ALT}{0}\"\n  STR_INCREASE_UC: \"POVEĆAJ\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Kupi/Unajmi Osoblje\"\n  STR_COST_OF_PURCHASES: \"Cijena Kupljenog>{ALT}{0}\"\n  STR_QUANTITY_UC: \"KOLIČINA\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"RASPOLOŽIVO LJUDSTVO:UKUPNO LJUDSTVO>\"\n  STR_SOLDIERS: \"Vojnici\"\n  STR_SCIENTISTS: \"Znanstvenici\"\n  STR_ENGINEERS: \"Inženjeri\"\n  STR_LIVING_QUARTERS: \"Prostorija za Življenje\"\n  STR_STORES: \"Skladišta\"\n  STR_LABORATORIES: \"Laboratoriji\"\n  STR_HANGARS: \"Hangari\"\n  STR_SHORT_RANGE_DETECTION: \"Kratkodometna Detekcija\"\n  STR_TRANSFERS_UC: \"TRANSFERI\"\n  STR_TRANSFERS: \"Transferi\"\n  STR_ARRIVAL_TIME_HOURS: \"Vrijeme do Dolaska (sati)\"\n  STR_COST_: \"Cijena>{ALT}{0}\"\n  STR_AREA_: \"Područje>{ALT}{0}\"\n  STR_BASE_NAME: \"Ime baze?\"\n  STR_AMOUNT_TO_TRANSFER: \"KOLIČINA ZA TRANSFERIRANJE\"\n  STR_SELECT_DESTINATION_BASE: \"Izaberi Bazu Odredište\"\n  STR_COST: \"Cijena\"\n  STR_VICTORY_1: \"Ulazeći u prostoriju suočeni ste s izvanzemaljskim mozgom - ciljem vašeg zadatka. Prije no što počnete pucati, mozak otvara kanal komunikacije putem zaslona kod svojeg podnožja. Preklinje vas da poslušate njegove argumente za preživljavanje prije no što donesete konačnu odluku da povučete okidač... \"\n  STR_VICTORY_2: \"Mozak započinje priču: \\\"Prije mnogo milijuna godina planet kojeg zovete Mars bio je živ. Taj je život na pusti planet donijela naša civilizacija, kao što smo ga donijeli i na vašu Zemlju. Milijunima godina smo posjećivali vaš planet i genetski razvili vašu vrstu. Ne možete nas ubiti - vi ste dio nas...\"\n  STR_VICTORY_3: \"Ovdje je središte Marsovske civilizacije - piramide izgrađene milijunima godina prije vaših. Sagradila ih je vrsta vaših predaka. Niti jedan planet nam nije van dosega. Ovu moć možemo podijeliti s vama. Sve što tražimo je vaša suradnja...\"\n  STR_GAME_OVER_1: \"Izvanzemaljci pokušavaju istrijebiti čovječanstvo, uništavajući gradove i trujući zrak i mora. Otpor zemaljskih vojski je uzaludan uoči daleko nadmoćne tehnologije. Preživjele generacije trpe strašne mutacije dok bježe od izvanzemaljaca. Izvanzemaljci ih okupljaju u koncentracijske logore kako bi pomogli preobraziti Zemlju u izvanzemaljsku koloniju, dio nekog nepoznatog carstva.\"\n  STR_VICTORY_4: \"Izvanzemljski mozak je iznanada prekinuo rafal vruće plazme, čime je čitava izvanzemaljska sila poražena.\"\n  STR_YOU_HAVE_FAILED: \"Pokušaj zaustavnjanja izvanzemaljskog nadiranja pokazao se bezuspješnim. Jedna za drugom sponzorirajuće države potpisale su ugovore s izvanzemaljcima, koji su im obećali tehnologiju, prosperitet i mir. Međutim, uskoro se pokazalo da izvanzemaljci imaju drugačije namjere...\"\n  STR_TOTAL_UC: \"UKUPNO\"\n  STR_INCOME: \"Prihod\"\n  STR_EXPENDITURE: \"Trošak\"\n  STR_MAINTENANCE: \"Održavanje\"\n  STR_BALANCE: \"Bilansa\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"Aktivnost NLO-a prema Regiji\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"Aktivnost NLO-a prema državi\"\n  STR_DATE_FIRST: \"{0}\"\n  STR_DATE_SECOND: \"{0}\"\n  STR_DATE_THIRD: \"{0}\"\n  STR_DATE_FOURTH: \"{0}\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Nema dovoljno posebnih materijala za proizvodnju{NEWLINE}{0}{NEWLINE}u{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Nemamo dovoljno sredstava za proizvodnju{NEWLINE}{0}{NEWLINE}u{NEWLINE}{1}\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"Izgradnja {NEWLINE}{0}{NEWLINE} u {NEWLINE}{1}{NEWLINE} je završena.\"\n  STR_OK_5_SECONDS: \"OK - 5 sec\"\n  STR_RESEARCH_COMPLETED: \"Istraživanje završeno\"\n  STR_VIEW_REPORTS: \"VIDI IZVJEŠTAJE\"\n  STR_WE_CAN_NOW_RESEARCH: \"Sada možemo istražiti\"\n  STR_WE_CAN_NOW_PRODUCE: \"Sada možemo proizvesti\"\n  STR_SUNDAY: \"NEDJELJA\"\n  STR_MONDAY: \"PONEDJELJAK\"\n  STR_TUESDAY: \"UTORAK\"\n  STR_WEDNESDAY: \"SRIJEDA\"\n  STR_THURSDAY: \"ČETVRTAK\"\n  STR_FRIDAY: \"PETAK\"\n  STR_SATURDAY: \"SUBOTA\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"U {2} nema dovoljno {0} za opskrbljivanje {1} s gorivom.\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Nema dovoljno {0} za naoružavanje {1} pri {2}\"\n  STR_UFO_IS_NOT_RECOVERED: \"NLO nije zaplijenjen\"\n  STR_UFO_IS_RECOVERED: \"NLO je zaplijenjen\"\n  STR_CRAFT_IS_LOST: \"Letjelica je Izgubljena\"\n  STR_TERROR_CONTINUES: \"Teror se nastavlja\"\n  STR_BASE_IS_LOST: \"Baza je izgubljena\"\n  STR_BASE_IS_SAVED: \"Baza je obranjena\"\n  STR_ALIEN_BASE_STILL_INTACT: \"Izvanzemaljska Baza i dalje aktivna\"\n  STR_ALIEN_BASE_DESTROYED: \"Izvanzemaljska Baza je uništena\"\n  STR_ALIENS_KILLED: \"UBIJENI IZVANZEMALJCI\"\n  STR_ALIEN_CORPSES_RECOVERED: \"PRONAĐENO IZVANZEMALJSKIH LEŠINA\"\n  STR_LIVE_ALIENS_RECOVERED: \"PRONAĐENO ŽIVIH IZVANZEMALJACA\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"ZAPLIJENJENI IZVANZEMALJSKI ARTEFAKTI\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"KONTROLNA PROSTORIJA IZVANZEMALJSKE BAZE UNIŠTENA\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"CIVILA UBIJENO OD STRANE IZVANZEMALJACA\"\n  STR_CIVILIANS_SAVED: \"SPAŠENO CIVILA\"\n  STR_TANKS_DESTROYED: \"IZGUBLJENI TENKOVI\"\n  STR_UFO_RECOVERY: \"RATNI PLIJEN S NLO-a\"\n  STR_BASE_UNDER_ATTACK: \"{0} je napadnuta!\"\n  STR_BASE_DEFENSES_INITIATED: \"OBRANA BAZE PRIPRAVNA\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"GRAVITACIJSKI ŠTIT JE ODBACIO NLO!\"\n  STR_FIRING: \"GAĐANJE\"\n  STR_HIT: \"POGODAK!\"\n  STR_UFO_DESTROYED: \"NLO UNIŠTEN!\"\n  STR_MISSED: \"PROMAŠAJ!\"\n  STR_FUNDS: \"SREDSTVA> {ALT}{0}\"\n  STR_VALUE: \"Vrijednost\"\n  STR_CRAFT_: \"LETJELICA> {ALT}{0}\"\n  STR_UFO_GROUND_ASSAULT: \"NAPAD NA PRIZEMLJENI NLO\"\n  STR_BASE_UC_: \"BAZA> {0}\"\n  STR_ALIEN_BASE_ASSAULT: \"NAPAD NA IZVANZEMALJSKU BAZU\"\n  STR_CYDONIA_BRIEFING: \"Došli smo u Cydoniju i ušli u veliki podzemni kompleks kraj marsovske Sfinge. Moramo uništiti Izvanzemaljski Mozak koji nadzire sve izvanzemaljske aktivnosti. Sudbina čovječanstva je u tvojim rukama...\"\n  STR_TERROR_MISSION: \"TEROR MISIJA\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"NEMA SLOBODNIH HANGARA ZA TRANSFER!{SMALLLINE}Svaka letjelica u bazi, koja je u transferu k bazi, upravo kupljena ili proizvedena zauzima jedan hangar. Izgradi novi hangar ili transferiraj letjelicu u drugu bazu.\"\n  STR_CANNOT_BUILD_HERE: \"NEMOGUĆE GRADITI OVDJE!{SMALLLINE}Moraš graditi pokraj postojeće prostorije.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"NEMA DOVOLJNO PROSTORA ZA RAD!{SMALLLINE}Izgradi novu radionicu ili smanji broj inženjera koji rade na drugim projektima.\"\n  STR_NOT_ENOUGH_MONEY: \"NEMAMO DOVOLJNO SREDSTAVA!\"\n  STR_LAUNCH_INTERCEPTION: \"NAREDI PRESRETANJE\"\n  STR_BASE: \"BAZA\"\n  STR_READY: \"SPREMNO\"\n  STR_REARMING: \"NAORUŽAVANJE\"\n  STR_TARGET: \"CILJ: {0}\"\n  STR_WAY_POINT: \"MEĐUTOČKA\"\n  STR_YES: \"DA\"\n  STR_NO: \"NE\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"IZABERI MJESTO ZA NOVU BAZU\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"MISIJA ZAVRŠENA - VRAĆA SE U BAZU\"\n  STR_PATROLLING: \"PATROLIRANJE\"\n  STR_TAILING_UFO: \"SLIJEDI NLO\"\n  STR_RETURNING_TO_BASE: \"VRAĆA SE U BAZU\"\n  STR_DESTINATION_UC_: \"ODREDIŠTE: {0}\"\n  STR_SPEED_: \"BRZINA>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"MAKSIMALNA BRZINA>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"VISINA>{ALT}{0}\"\n  STR_LOW_UC: \"NISKO\"\n  STR_FUEL: \"GORIVO>{ALT}{0}\"\n  STR_WEAPON_ONE: \"ORUŽJE-1>{ALT}{0}\"\n  STR_NONE_UC: \"NIŠTA\"\n  STR_ROUNDS_: \"Metaka>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"PRESRETAČKA LETJELICA\"\n  STR_BASE_: \"Baza>{0}\"\n  STR_NAME_UC: \"IME\"\n  STR_AMMO_: \"STRELJIVO>{ALT}{0}\"\n  STR_EQUIPMENT_UC: \"OPREMA\"\n  STR_ARMOR: \"OKLOP\"\n  STR_ROOKIE: \"Novak\"\n  STR_SQUADDIE: \"Pozornik\"\n  STR_SERGEANT: \"Narednik\"\n  STR_CAPTAIN: \"Satnik\"\n  STR_COLONEL: \"Pukovnik\"\n  STR_COMMANDER: \"Zapovjednik\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Izaberi Desetinu za {0}\"\n  STR_SPACE_AVAILABLE: \"DOSTUPNO PROSTORA>{ALT}{0}\"\n  STR_SPACE_USED: \"ZAUZETI PROSTOR>{ALT}{0}\"\n  STR_WOUNDED: \"RANJEN(A)\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Oprema za {0}\"\n  STR_DEFENSE_VALUE: \"Obrambena Vrijednost\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}spreman za{NEWLINE}slijetanje blizu{NEWLINE}{ALT}{1}\"\n  STR_SELECT_ARMAMENT: \"Izaberi Naoružanje\"\n  STR_AMMUNITION_AVAILABLE: \"RASPOLOŽIVO STRELJIVO\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"IZABERI OKLOP ZA{NEWLINE}{0}\"\n  STR_TYPE: \"VRSTA\"\n  STR_PERSONAL_ARMOR_UC: \"OSOBNI OKLOP\"\n  STR_POWER_SUIT_UC: \"OKLOPLJENI EGZOSKELET\"\n  STR_FLYING_SUIT_UC: \"LETEĆI EGZOSKELET\"\n  STR_SELECT_ARMOR: \"Izaberi Oklop\"\n  STR_NORTH: \"SJEVER\"\n  STR_NORTH_EAST: \"SJEVEROISTOK\"\n  STR_EAST: \"ISTOK\"\n  STR_SOUTH_EAST: \"JUGOISTOK\"\n  STR_SOUTH: \"JUG\"\n  STR_SOUTH_WEST: \"JUGOZAPAD\"\n  STR_WEST: \"ZAPAD\"\n  STR_NORTH_WEST: \"SJEVEROZAPAD\"\n  STR_SELECT_ACTION: \"IZABERI AKCIJU\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"NASTAVI POTJERU\"\n  STR_VERY_LARGE: \"VRLO VELIK\"\n  STR_LARGE: \"VELIK\"\n  STR_MEDIUM_UC: \"SREDNJI\"\n  STR_SMALL: \"MALI\"\n  STR_VERY_SMALL: \"VRLO MALI\"\n  STR_GROUNDED: \"TLO\"\n  STR_DETECTED: \"Otkriven\"\n  STR_SIZE_UC: \"VELIČINA\"\n  STR_ALTITUDE: \"VISINA\"\n  STR_HEADING: \"SMJER KRETANJA\"\n  STR_SPEED: \"BRZINA\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"CENTRIRAJ NA NLO-VRIJEME=5 sek\"\n  STR_REDIRECT_CRAFT: \"PREUSMJERI LETJELICU\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"IDI DO MJESTA GDJE JE NLO POSLJEDNJE VIĐEN\"\n  STR_UFO_: \"NLO-{0}\"\n  STR_ALIEN_BASE_: \"IZVANZEMALJSKA BAZA-{0}\"\n  STR_CRASH_SITE_: \"OBORENI NLO-{0}\"\n  STR_LANDING_SITE_: \"MJESTO SLIJETANJA-{0}\"\n  STR_WAY_POINT_: \"MEĐUTOČKA-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}je došao do{NEWLINE}{1}\"\n  STR_ALIEN_ORIGINS: \"Porijeklo Izvanzemaljaca\"\n  STR_THE_MARTIAN_SOLUTION: \"Marsovsko Rješenje\"\n  STR_UFOPAEDIA: \"NLOpedija\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"TENKOVI\"\n  STR_WEAPONS_AND_EQUIPMENT: \"ORUŽJE I OPREMA\"\n  STR_ALIEN_ARTIFACTS: \"IZVANZEMALJSKI ARTEFAKTI\"\n  STR_BASE_FACILITIES: \"PROSTORIJE U BAZI\"\n  STR_ALIEN_RESEARCH_UC: \"IZVANZEMALJSKO ISTRAŽIVANJE\"\n  STR_UFOS: \"NLO-i\"\n  STR_ACCELERATION: \"UBRZANJE>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"KAPACITET GORIVA>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"MJESTA ZA ORUŽJE>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"OTPORNOST>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"TERETNI PROSTOR>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"MJESTA ZA TENKOVE>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Oštećenje\"\n  STR_RANGE: \"Domet\"\n  STR_ACCURACY: \"Točnost\"\n  STR_RE_LOAD_TIME: \"Vrijeme do idućeg hitca\"\n  STR_DAMAGE_ARMOR_PIERCING: \"PROTUOKLOPNO\"\n  STR_DAMAGE_INCENDIARY: \"ZAPALJIVO\"\n  STR_DAMAGE_LASER_BEAM: \"LASERSKA ZRAKA\"\n  STR_DAMAGE_PLASMA_BEAM: \"PLAZMA ZRAKA\"\n  STR_DAMAGE_STUN: \"ONESVIJESTI\"\n  STR_DAMAGE_MELEE: \"PRSA O PRSA\"\n  STR_DAMAGE_ACID: \"KISELINA\"\n  STR_DAMAGE_SMOKE: \"DIM\"\n  STR_ACCURACY_UC: \"TOČNOST\"\n  STR_TIME_UNIT_COST: \"POTREBNO VJ\"\n  STR_DAMAGE_UC: \"OŠTEĆENJE\"\n  STR_AMMO: \"STRELJIVO\"\n  STR_SHOT_TYPE_AUTO: \"Rafal\"\n  STR_SHOT_TYPE_SNAP: \"Brzi\"\n  STR_SHOT_TYPE_AIMED: \"Ciljano\"\n  STR_CONSTRUCTION_COST: \"Cijena Izgradnje\"\n  STR_MAINTENANCE_COST: \"Cijena Održavanja\"\n  STR_MEDIUM: \"Srednje\"\n  STR_HIGH: \"Visoko\"\n  STR_CRAFT_WEAPON: \"Oružje za Letjelice\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Nosač Teškog Naoružanja\"\n  STR_WEAPON: \"Oružje\"\n  STR_EQUIPMENT: \"Oprema\"\n  STR_ALIEN_CORPSE: \"Izvanzemaljski Leš\"\n  STR_UFO_COMPONENT: \"Sastavni dio NLO-a\"\n  STR_PERSONAL_ARMOR: \"Osobni Oklop\"\n  STR_HWP_CANNON_SHELLS: \"Topovske Granate za Tenk\"\n  STR_ALIEN: \"Izvanzemaljac\"\n  STR_SECTOID: \"Sektoid\"\n  STR_SNAKEMAN: \"Zmijoliki\"\n  STR_ETHEREAL: \"Nebeski\"\n  STR_FLOATER: \"Lebdeći\"\n  STR_SILACOID: \"Silakoid\"\n  STR_CHRYSSALID: \"Krisalid\"\n  STR_ZOMBIE: \"Zombi\"\n  STR_REAPER: \"Kosac\"\n  STR_CYBERDISC: \"Kiberdisk\"\n  STR_LIVE_COMMANDER: \"Vrhovni Zapovjednik\"\n  STR_LIVE_LEADER: \"Vođa\"\n  STR_LIVE_ENGINEER: \"Inženjer\"\n  STR_LIVE_MEDIC: \"Liječnik\"\n  STR_LIVE_SOLDIER: \"Vojnik\"\n  STR_LIVE_TERRORIST: \"Terorist\"\n  STR_FLOATER_SOLDIER: \"Vojnik Lebdećih\"\n  STR_FLOATER_NAVIGATOR: \"Navigator Lebdećih\"\n  STR_FLOATER_MEDIC: \"Liječnik Lebdećih\"\n  STR_FLOATER_ENGINEER: \"Inženjer Lebdećih\"\n  STR_FLOATER_LEADER: \"Vođa Lebdećih\"\n  STR_FLOATER_COMMANDER: \"Zapovjednik Lebdećih\"\n  STR_SECTOID_SOLDIER: \"Vojnik Sektoida\"\n  STR_SECTOID_NAVIGATOR: \"Navigator Sektoida\"\n  STR_SECTOID_MEDIC: \"Liječnik Sektoida\"\n  STR_SECTOID_ENGINEER: \"Inženjer Sektoida\"\n  STR_SECTOID_LEADER: \"Vođa Sektoida\"\n  STR_SECTOID_COMMANDER: \"Zapovjednik Sektoida\"\n  STR_SNAKEMAN_SOLDIER: \"Vojnik Zmijolikih\"\n  STR_SNAKEMAN_NAVIGATOR: \"Navigator Zmijolikih\"\n  STR_SNAKEMAN_ENGINEER: \"Inženjer Zmijolikih\"\n  STR_SNAKEMAN_LEADER: \"Vođa Zmijolikih\"\n  STR_SNAKEMAN_COMMANDER: \"Zapovjednik Zmijolikih\"\n  STR_MUTON_SOLDIER: \"Vojnik Mutona\"\n  STR_MUTON_NAVIGATOR: \"Navigator Mutona\"\n  STR_MUTON_ENGINEER: \"Inženjer Mutona\"\n  STR_ETHEREAL_SOLDIER: \"Vojnik Nebeskih\"\n  STR_ETHEREAL_LEADER: \"Vođa Nebeskih\"\n  STR_ETHEREAL_COMMANDER: \"Zapovjednik Nebeskih\"\n  STR_CYBERDISC_TERRORIST: \"Kiberdisk Terorist\"\n  STR_REAPER_TERRORIST: \"Kosac Terorist\"\n  STR_CHRYSSALID_TERRORIST: \"Krisalid Terorist\"\n  STR_CELATID_TERRORIST: \"Celatid Terorist\"\n  STR_SILACOID_TERRORIST: \"Silakoid Terorist\"\n  STR_UFO_POWER_SOURCE: \"Izvor Energije NLO-a\"\n  STR_UFO_CONSTRUCTION: \"Konstrukcija NLO-a\"\n  STR_ALIEN_ENTERTAINMENT: \"Izvanzemaljska Razonoda\"\n  STR_ALIEN_SURGERY: \"Izvanzemaljska Kirurgija\"\n  STR_EXAMINATION_ROOM: \"Prostorija za Proučavanje\"\n  STR_ALIEN_ALLOYS: \"Izvanzemaljske Legure\"\n  STR_ALIEN_HABITAT: \"Izvanzemaljsko Stanište\"\n  STR_POWER_SUIT: \"Oklopljeni Egzoskelet\"\n  STR_FLYING_SUIT: \"Leteći Egzoskelet\"\n  STR_HWP_ROCKETS: \"Rakete za Tenk\"\n  STR_HWP_FUSION_BOMB: \"Fuzijska Kugla za Tenk\"\n  STR_LASER_WEAPONS: \"Laserska oružja\"\n  STR_NEW_FIGHTER_CRAFT: \"Nova Lovačka Letjelica\"\n  STR_LASER_PISTOL: \"Laserski pištolj\"\n  STR_LASER_RIFLE: \"Laserska puška\"\n  STR_HEAVY_LASER: \"Teški Laser\"\n  STR_LASER_CANNON: \"Laserski Top\"\n  STR_PLASMA_CANNON: \"Plazma Top\"\n  STR_FUSION_MISSILE: \"Fuzijski Projektil\"\n  STR_PLASMA_DEFENSE: \"Bitnica Plazma Zraka\"\n  STR_FUSION_DEFENSE: \"Fuzijska Bitnica\"\n  STR_MOTION_SCANNER: \"Detektor Pokreta\"\n  STR_TANK_CANNON: \"Tenk/Top\"\n  STR_TANK_ROCKET_LAUNCHER: \"Tenk/Raketni Bacač\"\n  STR_TANK_LASER_CANNON: \"Tenk/Laserski Top\"\n  STR_HOVERTANK_PLASMA: \"Lebdeći Tenk/Plazma\"\n  STR_HOVERTANK_LAUNCHER: \"Lebdeći Tenk/Fuzijski Bacač\"\n  STR_AVALANCHE_LAUNCHER: \"Bacač Lavina\"\n  STR_CANNON: \"Top\"\n  STR_FUSION_BALL_LAUNCHER: \"Bacač Fuzijski Kugli\"\n  STR_PLASMA_BEAM: \"Plazma-Zraka\"\n  STR_AVALANCHE_MISSILES: \"Rakete \\\"Lavina\\\"\"\n  STR_CANNON_ROUNDS_X50: \"Metci za Top(x50)\"\n  STR_FUSION_BALL: \"Fuzijska Kugla\"\n  STR_SOLDIER: \"Vojnik\"\n  STR_SCIENTIST: \"Znanstvenik\"\n  STR_ENGINEER: \"Inženjer\"\n  STR_NORTH_AMERICA: \"Sjeverna Amerika\"\n  STR_ARCTIC: \"Arktik\"\n  STR_ANTARCTICA: \"Antarktika\"\n  STR_SOUTH_AMERICA: \"Južna Amerika\"\n  STR_EUROPE: \"Europa\"\n  STR_NORTH_AFRICA: \"Sjeverna Afrika\"\n  STR_SOUTHERN_AFRICA: \"Južna Afrika\"\n  STR_CENTRAL_ASIA: \"Središnja Azija\"\n  STR_SOUTH_EAST_ASIA: \"Jugoistočna Azija\"\n  STR_SIBERIA: \"Sibir\"\n  STR_AUSTRALASIA: \"Australazija\"\n  STR_PACIFIC: \"Pacifik\"\n  STR_NORTH_ATLANTIC: \"Sjeverni Atlantik\"\n  STR_SOUTH_ATLANTIC: \"Južni Atlantik\"\n  STR_INDIAN_OCEAN: \"Indijski ocean\"\n  STR_ALIEN_RESEARCH: \"Izvanzemaljsko Istraživanje\"\n  STR_ALIEN_ABDUCTION: \"Izvanzemaljska Otmica\"\n  STR_ALIEN_INFILTRATION: \"Vanzemaljska Infiltracija\"\n  STR_ALIEN_BASE: \"Izvanzemaljska Baza\"\n  STR_ALIEN_TERROR: \"Izvanzemaljski Teror\"\n  STR_ALIEN_RETALIATION: \"Izvanzemaljska Odmazda\"\n  STR_ALIEN_SUPPLY: \"Izvanzemaljsko Opskrbljivanje\"\n  STR_MAXIMUM_SPEED: \"Maksimalna brzina\"\n  STR_HYPER_WAVE_DECODER_UC: \"HIPERVALNI DEKODER\"\n  STR_LIGHTNING: \"MUNJA\"\n  STR_AVENGER: \"OSVETNIK\"\n  STR_FIRESTORM: \"VATRENA OLUJA\"\n  STR_UFO: \"NLO\"\n  STR_AVALANCHE: \"LAVINA\"\n  STR_CANNON_UC: \"TOP\"\n  STR_FUSION_BALL_UC: \"FUZIJSKA KUGLA\"\n  STR_LASER_CANNON_UC: \"LASERSKI TOP\"\n  STR_PLASMA_BEAM_UC: \"PLAZMA ZRAKA\"\n  STR_DAMAGE_CAPACITY: \"Otpornost\"\n  STR_WEAPON_POWER: \"Snaga Oružja\"\n  STR_WEAPON_RANGE: \"Domet Oružja\"\n  STR_ACCESS_LIFT: \"Pristupni Lift\"\n  STR_LABORATORY: \"Laboratorij\"\n  STR_WORKSHOP: \"Radiona\"\n  STR_SMALL_RADAR_SYSTEM: \"Mali radarski sistem\"\n  STR_LARGE_RADAR_SYSTEM: \"Veliki Radarski Sustav\"\n  STR_MISSILE_DEFENSES: \"Raketna Bitnica\"\n  STR_GENERAL_STORES: \"Skladište\"\n  STR_ALIEN_CONTAINMENT: \"Prostorija za Internaciju Izvanzemaljaca\"\n  STR_PLASMA_DEFENSES: \"Plazma Bitnica\"\n  STR_PSIONIC_LABORATORY: \"Psionički Laboratorij\"\n  STR_HYPER_WAVE_DECODER: \"Hipervalni Dekoder\"\n  STR_HANGAR: \"Hangar\"\n  STR_USA: \"SAD\"\n  STR_RUSSIA: \"RUSIJA\"\n  STR_UK: \"UJEDINJENO KRALJEVSTVO\"\n  STR_FRANCE: \"FRANCUSKA\"\n  STR_GERMANY: \"NJEMAČKA\"\n  STR_ITALY: \"ITALIJA\"\n  STR_SPAIN: \"ŠPANJOLSKA\"\n  STR_CHINA: \"KINA\"\n  STR_JAPAN: \"JAPAN\"\n  STR_INDIA: \"INDIJA\"\n  STR_BRAZIL: \"BRAZIL\"\n  STR_AUSTRALIA: \"AUSTRALIJA\"\n  STR_NIGERIA: \"NIGERIJA\"\n  STR_SOUTH_AFRICA: \"JUŽNA AFRIKA\"\n  STR_EGYPT: \"EGIPAT\"\n  STR_CANADA: \"KANADA\"\n  STR_TANK: \"Tenk\"\n  STR_CIVILIAN: \"Civil\"\n  STR_JAN: \"sij\"\n  STR_FEB: \"velj\"\n  STR_MAR: \"ožu\"\n  STR_APR: \"tra\"\n  STR_MAY: \"svi\"\n  STR_JUN: \"lip\"\n  STR_JUL: \"srp\"\n  STR_AUG: \"kol\"\n  STR_SEP: \"ruj\"\n  STR_OCT: \"lis\"\n  STR_NOV: \"stu\"\n  STR_DEC: \"pro\"\n  STR_INTERNATIONAL_RELATIONS: \"Međunarodni Odnosi\"\n  STR_COUNTRY: \"Država\"\n  STR_FUNDING: \"Financiranje\"\n  STR_CHANGE: \"Promjena\"\n  STR_WEAPON_SYSTEMS: \"ORUŽJA\"\n  STR_HWPS: \"Tenkovi\"\n  STR_DAMAGE_UC_: \"OŠTEĆENJE>{ALT}{0}\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Svaki blok za smještaj može prihvatiti do 50 osoblja. Prostorija pruža osnovna postrojenja za rekreaciju, hranu i spavanje.\"\n  STR_LABORATORY_UFOPEDIA: \"U jednom laboratoriju može istovremeno raditi do 50 znanstvenika. Laboratoriji su opremljeni najnovihom tehnologijom za istraživanje materijala, biokemije i kozmologije. Imaju privilegirani pristup najboljim istraživačkim laboratorijima diljem svijeta, uključujući one vojne naravi.\"\n  STR_WORKSHOP_UFOPEDIA: \"Radiona sadrži svu opremu potrebnu za prozivodnju predmeta zasnovanih na nacrtima iz naših znanstvenih zaboratorija. U jednoj radioni može raditi do 50 inženjera, no valja imati na umu da će i predmeti koje proizvode zauzeti dio mjesta.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"U skladišta se pohranjuje sva oprema, streljivo, zaplijenjeni materijal te Tenkovi, uključujući opremu dodijeljenu letjelicama u hangarima.\"\n  STR_LASER_DEFENSES_UFOPEDIA: \"Laserska Bitnica nudi zaštitu od nadiranja neprijateljskih letjelica.\"\n  STR_PLASMA_DEFENSES_UFOPEDIA: \"Bitnica plazma zraka pruža snažnu i učinkovitu zaštitu od napada neprijateljskih letjelica.\"\n  STR_FUSION_BALL_DEFENSES_UFOPEDIA: \"Fuzijski projkektili pružaju najučinkovitiju obranu od izvanzemaljskih napada. Ovi projektili stvaraju antimaterijsku imploziju koja uništava sve unutar specifičnog radijusa.\"\n  STR_HYPER_WAVE_DECODER_UFOPEDIA: \"Izvanzemaljske komunikacije se oslanjaju na supradimenzionalne valove koji na cilj stižu gotovo trenutno. Dekoder presreće poruke iz NLO-a i dešifrira informacije koje one sadrže. Time daje podatke o vrsti NLO-a, rasi izvanzemaljaca članova posade i vrsti aktivnosti koju planiraju.\"\n  STR_RIFLE_UFOPEDIA: \"Vrlo precizna snajperska puška s laserski navođenim ciljanjem. Koristi 6.7mm streljivo u šaržerima od 20 metaka.\"\n  STR_HEAVY_CANNON_UFOPEDIA: \"Teški top je razorno ali nezgrapno oružje. Vrlo je prilagodljiv i može primiti tri vrste streljiva - protuoklopno, zapaljivo i eksplozivno.\"\n  STR_AUTO_CANNON_UFOPEDIA: \"Automatski top spaja prilagodljivost i moć teškog topa s većom brzinom gađanja.\"\n  STR_ROCKET_LAUNCHER_UFOPEDIA: \"Raketni bacač opremljen je s laserskim navođenjem, te može ispaliti rakete triju različitih veličina.\"\n  STR_LASER_PISTOL_UFOPEDIA: \"Laserski pištoj primjer je učinkovite implementacije nove tehnologije. Posjeduje pogodnost pištolja uz veću brzinu i preciznost gađanja.\"\n  STR_LASER_RIFLE_UFOPEDIA: \"Laserska puška je snažnija i preciznija verzija laserskog pištolja.\"\n  STR_HEAVY_LASER_UFOPEDIA: \"Teški laser je nezgrapno, ali vrlo učinkovito oružje.\"\n  STR_HIGH_EXPLOSIVE_UFOPEDIA: \"Ova vrsta eksploziva podobna je samo za demoliranje. Osoblje valja držati na sigurnoj udaljenosti od mjesta postavljanja.\"\n  STR_MEDI_KIT_UFOPEDIA: \"Medicinski komplet predstavlja spoj pribora za liječenje s analgeticima i stimulansima. Kako bi upotrijebio medicinski komplet, korisnik mora biti okrenut prema vojniku kojemu je potrebna pomoć. Ako je vojnik u nesvijesti, potrebno je stajati nad njegovim tijelom. Klikni na ikonu medicinskog kompleta i izaberi \\\"koristi medicinski komplet\\\" s izbornika.{NEWLINE}LIJEČENJE> Crveni dijelovi tijela označavaju mjesta sa smrtonosnim ranama. Klikni na dio tijela koji je ranjen, a zatim klikni na gumb \\\"Izliječi\\\". Jedna smrtonosna rana bit će izliječena te će vojniku biti vraćena mala količina izgubljenog zdravlja.{NEWLINE}STIMULANS> Ovo će vojniku povratiti dio izgubljene energije i pomoći onesviještenim vojnicima da se probude. Za potonje je potrebno stajati iznad njihovih tijela.{NEWLINE}ANALGETIK> Ovo će ranjenom vojniku povratiti dio morala kojeg je izgubio zbog ranjavanja.\"\n  STR_STUN_ROD_UFOPEDIA: \"Ova je naprava namijenjena isključivo za borbu prsa o prsa, no sposobna je putem električnog šoka nokautirati živi organizam bez da ga ubije.\"\n  STR_PLASMA_PISTOL_UFOPEDIA: \"Plazma Pištolji su smrtonosna izvanzemaljska oružja koja djeluju na principu ubrzavanja čestica unutar minijaturnog antigravitacijskog polja.\"\n  STR_PLASMA_RIFLE_UFOPEDIA: \"Ovo oružje posjeduje golemu razornu moć temeljenu na ubrzavanju čestica unutar minijaturnog antigravitacijskog polja.\"\n  STR_HEAVY_PLASMA_UFOPEDIA: \"Ovo oružje posjeduje golemu razornu moć temeljenu na ubrzavanju čestica unutar minijaturnog antigravitacijskog polja.\"\n  STR_BLASTER_LAUNCHER_UFOPEDIA: \"Ovo je oružje bacač navođenih izvanzemaljskih fuzijskih bombi. Klikom na oružjebit će stvorene \\\"međutočke\\\" koje će fuzijska bomba pokušati slijediti. Kada smatraš da si postavio dovoljno međutočki, klikni na posebnu ikonu za lansiranje bombe.\"\n  STR_SMALL_LAUNCHER_UFOPEDIA: \"Mali bacač granata koji ispaljuje bombe za onesvješćivanje protivnika. Vrlo koristan pri zarobljavanju živih izvanzemaljaca.\"\n  STR_ALIEN_GRENADE_UFOPEDIA: \"Ovo sredstvo radi na isti način kao zemaljska granata, no posjeduje veću razornu moć.\"\n  STR_SMALL_SCOUT: \"Mali Izviđački Brod\"\n  STR_MEDIUM_SCOUT: \"Srednji Izviđački Brod\"\n  STR_LARGE_SCOUT: \"Veliki Izviđač\"\n  STR_HARVESTER: \"Sakupljač\"\n  STR_ABDUCTOR: \"Otimač\"\n  STR_TERROR_SHIP: \"Teroristički brod\"\n  STR_SUPPLY_SHIP: \"Brod za opskrbu\"\n  STR_RATING: \"OCJENA> {0}\"\n  STR_RATING_TERRIBLE: \"GROZNO!\"\n  STR_RATING_POOR: \"SLABO!\"\n  STR_RATING_OK: \"OK\"\n  STR_RATING_EXCELLENT: \"IZVRSNO!\"\n  STR_SCORE: \"BODOVI\"\n  STR_MONTH: \"Mjesec> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"Vijeće država koje financiraju XCom projekt uglavnom je zadovoljno tvojim postignućima.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"Niste uspjeli osujetiti izvanzemaljsku invaziju te je stoga vijeće sponzora odlučilo ukinuti XCom projekt. Svaka će se zemlja prema vlastitom izboru nositi s problemom izvanzemaljaca. Možemo se samo nadati da ćemo se uspjeti nagoditi s ovim naoko neprijateljskim snagama, te da će širi slojevi stanovništva prihvatiti izvanzemaljske posjetitelje.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} su posebno zadovoljni s tvojim uspjehom u suzbijanju lokalnih izvanzemaljskih nadiranja te su se složili povećati svoje financiranje XComa.\"\n  STR_COUNTRIES_AND: \"{0} i {1}\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} nisu zadovoljne Vašom sposobnošću da zaustavite izvanzemaljske aktivnosti na njihovom teritoriju te su odlučile smanjiti svoj doprinos financijanju X-coma.\"\n  STR_KNOTS: \"{0} čvorova\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} je potpisala tajni pakt s nepoznatim izvanzemaljskim snagama te je prestala financirati naš projekt.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} su potpisali tajni pakt s nepoznatim izvanzemaljskim snagama te su prestali financirati naš projekt.\"\n  STR_MONTHLY_RATING: \"Mjesečna Ocjena> {ALT}{0}{ALT}{1}\"\n  STR_FUNDING_CHANGE: \"Promjena u razini sponzoriranja> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"Vijeće sponzora nije zadovoljno našim financijskim stanjem. Moramo smanjiti dugove na manje od $1 milijun ili će nam projekt biti ukinut.\"\n  STR_CRAFT_TYPE: \"VRSTA LETJELICE\"\n  STR_RACE: \"RASA\"\n  STR_MISSION: \"MISIJA\"\n  STR_ZONE: \"ZONA\"\n  STR_NEW_YORK: \"New York\"\n  STR_WASHINGTON: \"Washington\"\n  STR_LOS_ANGELES: \"Los Angeles\"\n  STR_MONTREAL: \"Montreal\"\n  STR_HAVANA: \"Havana\"\n  STR_MEXICO_CITY: \"Ciudad de México\"\n  STR_CHICAGO: \"Chicago\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_DALLAS: \"Dallas\"\n  STR_BRASILIA: \"Brazilija\"\n  STR_BOGOTA: \"Bogota\"\n  STR_BUENOS_AIRES: \"Buenos Aires\"\n  STR_SANTIAGO: \"Santiago\"\n  STR_RIO_DE_JANEIRO: \"Rio De Janeiro\"\n  STR_LIMA: \"Lima\"\n  STR_CARACAS: \"Caracas\"\n  STR_LONDON: \"London\"\n  STR_PARIS: \"Pariz\"\n  STR_BERLIN: \"Berlin\"\n  STR_MOSCOW: \"Moskva\"\n  STR_ROME: \"Rim\"\n  STR_MADRID: \"Madrid\"\n  STR_BUDAPEST: \"Budimpešta\"\n  STR_LAGOS: \"Lagos\"\n  STR_CAIRO: \"Kairo\"\n  STR_CASABLANCA: \"Casablanca\"\n  STR_PRETORIA: \"Pretoria\"\n  STR_NAIROBI: \"Nairobi\"\n  STR_CAPE_TOWN: \"Kaapstad\"\n  STR_KINSHASA: \"Kinshasa\"\n  STR_ANKARA: \"Ankara\"\n  STR_DELHI: \"Delhi\"\n  STR_KARACHI: \"Karachi\"\n  STR_BAGHDAD: \"Bagdad\"\n  STR_TEHRAN: \"Teheran\"\n  STR_BOMBAY: \"Mumbai\"\n  STR_CALCUTTA: \"Kolkata\"\n  STR_TOKYO: \"Tokio\"\n  STR_BEIJING: \"Peking\"\n  STR_BANGKOK: \"Bangkok\"\n  STR_MANILA: \"Manila\"\n  STR_SEOUL: \"Seul\"\n  STR_SINGAPORE: \"Singapur\"\n  STR_JAKARTA: \"Jakarta\"\n  STR_SHANGHAI: \"Šangaj\"\n  STR_HONG_KONG: \"Hong Kong\"\n  STR_NOVOSIBIRSK: \"Novosibirsk\"\n  STR_CANBERRA: \"Canberra\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_MELBOURNE: \"Melbourne\"\n  STR_PERTH: \"Perth\"\n  STR_WEAPONS_CREW_HWPS: \"ORUŽJE/{NEWLINE}POSADA/TENKOVI\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"ponestaje gotiva,{NEWLINE}se vraća u bazu\"\n  STR_SOLDIER_LIST: \"Popis vojnika\"\n  STR_RANK_: \"RANG> {ALT}{0}\"\n  STR_MISSIONS: \"MISIJE> {ALT}{0}\"\n  STR_KILLS: \"UBIJENO NEPRIJATELJA> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"VRIJEME ZA OPORAVAK> {ALT}{0}\"\n  STR_TIME_UNITS: \"VREMENSKE JEDINICE\"\n  STR_STAMINA: \"IZDRŽLJIVOST\"\n  STR_HEALTH: \"ZDRAVLJE\"\n  STR_BRAVERY: \"HRABROST\"\n  STR_REACTIONS: \"REFLEKSI\"\n  STR_FIRING_ACCURACY: \"PRECIZNOST GAĐANJA\"\n  STR_THROWING_ACCURACY: \"PRECIZNOST PRILIKOM BACANJA\"\n  STR_STRENGTH: \"SNAGA\"\n  STR_PSIONIC_STRENGTH: \"PSIONIČKA SNAGA\"\n  STR_PSIONIC_SKILL: \"PSIONIČKA VJEŠTINA\"\n  STR_NEW_RANK: \"NOVI RANK\"\n  STR_PROMOTIONS: \"Promaknuća\"\n  STR_SOLDIERS_UC: \"VOJNICI\"\n  STR_HOVERTANK_LAUNCHER_UFOPEDIA: \"Ovaj lebdeći tenk naoružan je bacačem fuzijskih kugli koji je sposoban prouzročiti golemu štetu. Koristi ga vrlo pažljivo. Morat će proizvesti fuzijske kugle kako bi Tenkovi imali dostatno streljivo. Fuzijska kugla je pametno, navođeno oružje. Prilikom paljbe potrebno je izabrati određen broj \\\"međutočaka\\\" pomoću pokazivača na zaslonu, a zatim kliknuti na ikonu \\\"ispali\\\".\"\n  STR_HEAVY_PLASMA_CLIP_UFOPEDIA: \"Ova kompaktna naprava služi kao streljivo za Tešku Plazmu. Sadrži malu količinu Elerija.\"\n  STR_PLASMA_RIFLE_CLIP_UFOPEDIA: \"Ovaj mali predmet služi kao izvor energije za Plazma Pušku, izvanzemaljsko oružje srednje jačine. Sadrži malu količinu Elerija.\"\n  STR_PLASMA_PISTOL_CLIP_UFOPEDIA: \"Izvor energije za kompaktni izvanzemaljski Plazma Pištolj. Sadrži Elerij, izvor sve izvanzemaljske moći.\"\n  STR_SMALL_SCOUT_UFOPEDIA: \"Ova sitna letjelica prvenstveno služi za izviđanje ili istraživanja. Obično prethodi večim letjelicama na početku izvanzemaljske misije.\"\n  STR_MEDIUM_SCOUT_UFOPEDIA: \"Izviđačka letjelica srednje veličine koja ne predstavlja veliku opasnost za zemaljske snage. Njena pojava tijekom izvanzemaljskih misija obično prethodi većim letjelicama.\"\n  STR_TERROR_SHIP_UFOPEDIA: \"Letjelica za Teror posjeduje spremište za velika izvanzemaljska teroristička oružja ili bića. Služi za prebacivanje takvih terorista u napučena područja.\"\n  STR_BATTLESHIP_UFOPEDIA: \"Bojni brod je najveća i najsnažnija izvanzemaljska letjelica. Obično služi kao glavna letjelica za izvršavanje neke misije, te nosi snažno naoružanje i veliku posadu.\"\n  STR_SUPPLY_SHIP_UFOPEDIA: \"Opskrbna letjelica koristi se za izgradnju izvanzemaljskih baza ili za opskrbljivanje već postojećih baza. Nosi kontejnere s izvanzemaljskom hranom te prostorije za razmnožavanje.\"\n  STR_FACILITY_IN_USE: \"PROSTORIJA U UPORABI\"\n  STR_TRANSFER_ITEMS_TO: \"Transferiraj Predmete do {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"NEMA PROSTORIJE ZA IZVANZEMALJCE!{SMALLLINE}Živim izvanzemaljcima je za opstanak potrebna prostorija za izvanzemaljce.\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"Izvanzemaljac je umro pošto nemamo prostoriju za internaciju izvanzemaljaca\"\n  STR_DESTINATION_UC: \"ODREDIŠTE\"\n  STR_PISTOL: \"Pištolj\"\n  STR_PISTOL_CLIP: \"Klip pištolja\"\n  STR_RIFLE: \"Puška\"\n  STR_RIFLE_CLIP: \"Šaržer za pušku\"\n  STR_HEAVY_CANNON: \"Teški Top\"\n  STR_HC_AP_AMMO: \"TT-PO Streljivo\"\n  STR_HC_HE_AMMO: \"TT-E Streljivo\"\n  STR_HC_I_AMMO: \"TT-Z Streljivo\"\n  STR_AUTO_CANNON: \"Automatski top\"\n  STR_AC_AP_AMMO: \"AT-PO Streljivo\"\n  STR_AC_HE_AMMO: \"AT-E Streljivo\"\n  STR_AC_I_AMMO: \"AT-Z Streljivo\"\n  STR_ROCKET_LAUNCHER: \"Raketni Bacač\"\n  STR_SMALL_ROCKET: \"Mala Raketa\"\n  STR_LARGE_ROCKET: \"Velika Raketa\"\n  STR_INCENDIARY_ROCKET: \"Zapaljiva raketa\"\n  STR_GRENADE: \"Granata\"\n  STR_SMOKE_GRENADE: \"Dimna Bomba\"\n  STR_HIGH_EXPLOSIVE: \"Eksploziv\"\n  STR_HEAVY_PLASMA: \"Teška Plazma\"\n  STR_HEAVY_PLASMA_CLIP: \"Klip za Tešku Plazmu\"\n  STR_PLASMA_RIFLE: \"Plazma Puška\"\n  STR_PLASMA_RIFLE_CLIP: \"Saržer za Plazma Pušku\"\n  STR_PLASMA_PISTOL: \"Plazma Pištolj\"\n  STR_PLASMA_PISTOL_CLIP: \"Šaržer za Plazma Pištolj\"\n  STR_BLASTER_LAUNCHER: \"Fuzijski Bacač\"\n  STR_BLASTER_BOMB: \"Fuzijska Bomba\"\n  STR_SMALL_LAUNCHER: \"Mali Bacač\"\n  STR_STUN_BOMB: \"Mala Bomba\"\n  STR_ALIEN_GRENADE: \"Izvanzemaljska Granata\"\n  STR_ELERIUM_115: \"Elerij-115\"\n  STR_SECTOID_CORPSE: \"Leš Sektoida\"\n  STR_SNAKEMAN_CORPSE: \"Leš Zmijolikog\"\n  STR_ETHEREAL_CORPSE: \"Leš Nebeskog\"\n  STR_MUTON_CORPSE: \"Leš Mutona\"\n  STR_FLOATER_CORPSE: \"Leš Lebdećeg\"\n  STR_CELATID_CORPSE: \"Leš Celatida\"\n  STR_SILACOID_CORPSE: \"Leš Silakoida\"\n  STR_CHRYSSALID_CORPSE: \"Leš Krisalida\"\n  STR_REAPER_CORPSE: \"Leš Kosca\"\n  STR_SECTOPOD_CORPSE: \"Leš sektopoda\"\n  STR_CYBERDISC_CORPSE: \"Leš Kiberdiska\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Nema dovoljno opreme za ponovno opskrbljavanje desetine\"\n  STR_MARS_CYDONIA_LANDING: \"Mars: slijetanje u Cydoniji\"\n  STR_MARS_CYDONIA_LANDING_BRIEFING: \"Osvetnik je sletio na područje Cydonije na Marsovoj površini. Prema našim informacijama, jedna od piramida sadrži zeleni lift koji vodi do podzemnog kompleksa. Kada se okupe svi vojnici na području lifta, klikni ikonu \\\"prekini misiju\\\" za početak idućeg stadija misije.\"\n  STR_MARS_THE_FINAL_ASSAULT: \"Mars: konačna bitka\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Potrebno je istražiti{NEWLINE}{0}{NEWLINE}prije no što možemo proizvesti{NEWLINE}{1}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"Izvanzemaljci su uništili nebranjenu bazu {0}\"\n  STR_STANDOFF: \"SIGURNA UDALJENOST\"\n  STR_CAUTIOUS_ATTACK: \"OPREZAN NAPAD\"\n  STR_STANDARD_ATTACK: \"STANDARDNI NAPAD\"\n  STR_AGGRESSIVE_ATTACK: \"AGRESIVNI NAPAD\"\n  STR_DISENGAGING: \"PREKIDANJE KONTAKTA\"\n  STR_UFO_HIT: \"NLO POGOĐEN!\"\n  STR_UFO_CRASH_LANDS: \"NLO OBOREN!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Minimiziraj isključivo na Sigurnoj Udaljenosti\"\n  STR_UFO_RETURN_FIRE: \"NLO UZVRAĆA PALJBU!\"\n  STR_INTERCEPTOR_DAMAGED: \">>> PRESRETAČ OŠTEĆEN <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>>  PRESRETAČ UNIŠTEN <<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"NLO BJEŽI PRESRETAČU!\"\n  STR_ALIENS_TERRORISE: \"IZVANZEMALJCI TERORIZIRAJU\"\n  STR_LONG_RANGE_DETECTION: \"Dalekodometna Detekcija\"\n  STR_STORES_UC: \"SKLADIŠTA\"\n  STR_DIFFICULTY_LEVEL: \"Razina Težine\"\n  STR_INTERCEPT: \"PRESRETANJE\"\n  STR_BASES: \"BAZE\"\n  STR_GRAPHS: \"GRAFIKONI\"\n  STR_OPTIONS_UC: \"OPCIJE\"\n  STR_FUNDING_UC: \"FINANCIRANJE\"\n  STR_5_SECONDS: \"5 sec\"\n  STR_1_MINUTE: \"1 min\"\n  STR_5_MINUTES: \"5 min\"\n  STR_30_MINUTES: \"30 min\"\n  STR_1_HOUR: \"1 sat\"\n  STR_1_DAY: \"1 dan\"\n  STR_ENTER_NAME: \"Upiši ime\"\n  STR_PERFORMANCE_RATING: \"Ocjena Učinkovitosti\"\n  STR_VICTORY_DATE: \"Datum Pobjede\"\n  STR_ELECTRO_FLARE: \"Elektro-baklja\"\n  STR_ELECTRO_FLARE_UFOPEDIA: \"Ova kompaktna naprava proizvodi jarko svijetlo nakon što je bačena. Ono će neprijateljske jedinice u blizini elektro-baklje tijekom noćnih misija učiniti vidljivima.\"\n  STR_MONTHLY_COSTS: \"Mjesečni Izdaci\"\n  STR_CRAFT_RENTAL: \"Najam Letjelica\"\n  STR_SALARIES: \"Plaće\"\n  STR_BASE_MAINTENANCE: \"Održavanje baza\"\n  STR_COST_PER_UNIT: \"Trošak po jedinici\"\n  STR_QUANTITY: \"Količina\"\n  STR_TOTAL: \"Ukupno\"\n  STR_BLASTER_BOMB_UFOPEDIA: \"Ova naprava je visoko eksplozivni projektil s ugrađenim sustavom za pametno navođenje. Ispaljuje ju se iz Fuzijskog Bacača.\"\n  STR_FRONT_ARMOR: \"Prednji Oklop\"\n  STR_LEFT_ARMOR: \"Lijevi Oklop\"\n  STR_RIGHT_ARMOR: \"Desni oklop\"\n  STR_REAR_ARMOR: \"Stražnji Oklop\"\n  STR_UNDER_ARMOR: \"Donji Oklop\"\n  STR_ROUNDS: \"Metaka\"\n  STR_UNIT: \"JEDINICA>{0}\"\n  STR_ENERGY: \"ENERGIJA\"\n  STR_MORALE: \"MORAL\"\n  STR_ARMOR_: \"OKLOP> {0}\"\n  STR_FRONT_ARMOR_UC: \"PREDNJI OKLOP\"\n  STR_LEFT_ARMOR_UC: \"LIJEVI OKLOP\"\n  STR_RIGHT_ARMOR_UC: \"DESNI OKLOP\"\n  STR_REAR_ARMOR_UC: \"STRAŽNJI OKLOP\"\n  STR_SKILLS: \"VJEŠTINE> {0}\"\n  STR_LEVEL: \"RAZINA> {0}\"\n  STR_HEAD: \"GLAVA\"\n  STR_TORSO: \"TORZO\"\n  STR_RIGHT_ARM: \"DESNA RUKA\"\n  STR_LEFT_ARM: \"LIJEVA RUKA\"\n  STR_RIGHT_LEG: \"DESNA NOGA\"\n  STR_LEFT_LEG: \"LIJEVA NOGA\"\n  STR_PAIN_KILLER: \"ANALGETIK\"\n  STR_STIMULANT: \"STIMULANS\"\n  STR_HEAL: \"IZLIJEČI\"\n  STR_TIME_UNITS_SHORT: \"VJ>{ALT}{0}\"\n  STR_WEIGHT: \"Težina>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"Reakc>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Izvanzemaljski Artefakt\"\n  STR_AMMO_ROUNDS_LEFT: \"STRELJIVO:{NEWLINE}METAKA ZA{NEWLINE}PREOSTALO={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Anal>{ALT}{0}{ALT}{NEWLINE}Stim>{ALT}{1}{ALT}{NEWLINE}Lije>{ALT}{2}\"\n  STR_THROW: \"Baci\"\n  STR_AUTO_SHOT: \"Rafalna Paljba\"\n  STR_SNAP_SHOT: \"Brzi Hitac\"\n  STR_AIMED_SHOT: \"Ciljana Paljba\"\n  STR_STUN: \"Onesvijesti\"\n  STR_USE_SCANNER: \"Upotrijebi detektor\"\n  STR_USE_MEDI_KIT: \"Upotrijebi Medicinski Komplet\"\n  STR_ACCURACY_SHORT: \"Ubrzanje>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Nema Dovoljno Vremenskih Jedinica!\"\n  STR_NOT_ENOUGH_ENERGY: \"Nema dovoljno energije!\"\n  STR_NO_ROUNDS_LEFT: \"Nema više Metaka!\"\n  STR_NO_AMMUNITION_LOADED: \"Oružje nema streljiva!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Pogrešno Streljivo za ovo Oružje!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"Oružje je već napunjeno!\"\n  STR_NO_LINE_OF_FIRE: \"Nema čiste vatrene linije!\"\n  STR_GRENADE_IS_ACTIVATED: \"Granata je aktivirana!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Granata je deaktivirana!\"\n  STR_THERE_IS_NO_ONE_THERE: \"Nema nikoga na tom mjestu!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Ne možemo koristiti izvanzemaljski artefakt dok ga ne istražimo u laboratoriju!\"\n  STR_OUT_OF_RANGE: \"Izvan Dometa!\"\n  STR_UNABLE_TO_THROW_HERE: \"Nemoguće baciti ovdje!\"\n  STR_SET_TIMER: \"Namjesti Vremenski Detonator\"\n  STR_HIDDEN_MOVEMENT: \"SKRIVENO KRETANJE\"\n  STR_TURN: \"POTEZ> {0}\"\n  STR_SIDE: \"STRANA> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Pritisni gumb za nastavak\"\n  STR_MIND_CONTROL: \"Kontrola Uma\"\n  STR_PANIC_UNIT: \"Izazovi Paniku\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Protivniku je Smanjen Moral\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Kontrola uma uspješna\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}je zahvatio bijes\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}je zahvatio bijes\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}Paničari\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}Paničari\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Izvanzemaljci\"\n  STR_RIGHT_HAND: \"DESNA RUKA\"\n  STR_LEFT_HAND: \"LIJEVA RUKA\"\n  STR_RIGHT_SHOULDER: \"DESNO RAME\"\n  STR_LEFT_SHOULDER: \"LIJEVO RAME\"\n  STR_BACK_PACK: \"NAPRTNJAČA\"\n  STR_BELT: \"REMEN\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}je pod kontrolom izvanzemaljaca\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}je pod kontrolom izvanzemaljaca\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}se onesvijestio\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}je pala u nesvijest\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE} je poginuo(la) od posljedica smrtonosne rane.\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}je poginula od smrtonosne rane\"\n  STR_FATAL_WOUNDS: \"SMRTONOSNE RANE\"\n  STR_UNDER_ARMOR_UC: \"DONJI OKLOP\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Vremenske jedinice rezervirane za brzi hitac\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Vremenske jedinice rezervitane za automatsku paljbu\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Vremenske jedinice rezervitane za ciljanu paljbu\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Vremenske jedinice rezervitane za klečanje\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"Vremenske jedinice rezervitane za klečanje i pucanje\"\n  STR_ABORT_MISSION_QUESTION: \"Prekini misiju?\"\n  STR_CORPSE: \"Leš\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}je poginuo\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}je ubijen\"\n  STR_HIT_MELEE: \"Pogodak\"\n  STR_GROUND: \"TLO\"\n  STR_LIVING_QUARTERS_PLURAL: \"Prostor za življenje\"\n  STR_LIST_ITEM: \"PREDMET\"\n  STR_PERSONAL_ARMOR_UFOPEDIA: \"Ovaj je oklop načinjen od novootkrivenih izvanzemaljskih legura te našim vojnicima omogućuje učinkovito suprotstavljanje izvanzemaljskoj prijetnji.\"\n  STR_POWER_SUIT_UFOPEDIA: \"Ovaj oklop vojnicima pruža snažnu zaštitu. Oklop crpi energiju iz Elerija, te uz zaštitu snažno uvećava brzinu i snagu vojnika.\"\n  STR_FLYING_SUIT_UFOPEDIA: \"Poboljšana inačica Oklopnog Egzoskeleta, uključuje izvanzemaljsku antigravitacijsku navigacionu tehnologiju kako bi omogućila punu slobodu kretanja na bojištu.\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"Svi izvanzemaljci su poginuli u padu letjelice,{NEWLINE}Započeto automatsko prikupljanje plijena\"\n  STR_RESET: \"Vrati na početak\"\n  STR_MEMORIAL: \"Pali Borci\"\n  STR_DATE_UC: \"DATUM\"\n  MAP_CULTA: \"Farma\"\n  MAP_FOREST: \"Šuma\"\n  MAP_JUNGLE: \"Džungla\"\n  MAP_MOUNT: \"Planina\"\n  MAP_DESERT: \"Pustinja\"\n  MAP_POLAR: \"Polarno\"\n  MAP_URBAN: \"Grad\"\n  MAP_UBASE: \"Izvanzemaljska baza\"\n  MAP_MARS: \"Mars\"\n  STR_MIXED: \"Miješana\"\n  STR_REMOVE_SELECTED: \"Izbaci Izabrano\"\n  STR_GO_TO_BASE: \"Idi u Bazu\"\n  STR_SELL_PRODUCTION: \"PRODAJ\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Obje ruke moraju biti prazne!\"\n  STR_ALL_ITEMS: \"Svi Predmeti\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"Gradnja X-Com baze pod vodom nije moguća\"\n  STR_LEVEL_SHORT: \"{0}\"\n  STR_PERSONNEL: \"Osoblje\"\n  FEMALE_CIVILIAN: \"Civil, žena\"\n  MALE_CIVILIAN: \"Civil, muškarac\"\n  CYBERDISC_WEAPON: \"Kiberdiskovo oružje\"\n  REAPER_WEAPON: \"Koščevo oružje\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/hu.yml",
    "content": "hu:\n  STR_AVENGER_UFOPEDIA: \"SZÁLLÍTÓ ÉS HARCI ŰRREPÜLŐ.  AZ IDEGEN TECHNOLÓGIA LEGMESSZEBBMENŐ MÁSOLATA.\"\n  STR_INTERCEPTOR_UFOPEDIA: \"IKERTURBINÁS HARCI REPÜLŐGÉP, ELEKTRONIKUS RENDSZERE SPECIÁLISAN ÁRNYÉKOLT.  A LÉTEZŐ LEGJOBB FÖLDI TECHNOLÓGIA.\"\n  STR_LIGHTNING_UFOPEDIA: \"SZÁLLÍTÓ ÉS HARCI GÉP.  DURVA, DE HATÁSOS MÁSOLATA AZ IDEGEN MEGHAJTÁSI RENDSZEREKNEK.\"\n  STR_SKYRANGER_UFOPEDIA: \"CSAPATSZÁLLÍTÓ. FAJTÁJA LEGGYORSABBJA, FÜGGŐLEGES FEL- ÉS LESZÁLLÁSI (F.F.É.L.) LEHETŐSÉGGEL.\"\n  STR_FIRESTORM_UFOPEDIA: \"HARCI GÉP.  EZ AZ EGYSZEMÉLYES VADÁSZ A KLASSZIKUS REPÜLŐ CSÉSZEALJ MINTÁJÁRA KÉSZÜLT KÖZÉPEN ELHELYEZKEDŐ MEGHAJTÁSSAL.\"\n  STR_STINGRAY_UFOPEDIA: \"FEJLETT LEVEGŐ-LEVEGŐ RAKÉTA SPECIÁLISAN ÁRNYÉKOLT ELEKTRONIKÁVAL.\"\n  STR_AVALANCHE_UFOPEDIA: \"LEVEGŐ-LEVEGŐ RAKÉTA NUKLEÁRIS ROBBANÓFEJJEL, RENDKÍVÜL NAGY TÖMEGŰ.\"\n  STR_CANNON_UFOPEDIA: \"NAGYEREJŰ ÁGYÚ, AMELY PÁNCÉLTÖRŐ LÖVEDÉKEKET LŐ KI, MELYEK 40 CM VASTAG ACÉLON IS KÉPESEK ÁTHATOLNI.\"\n  STR_FUSION_BALL_UFOPEDIA: \"EZ AZ ESZKÖZ GÖMB ALAKÚ RAKÉTÁKAT LŐ KI, MELYEK HATÁSA AZ ANTI-ANYAG REAKCIÓN ALAPSZIK.  A GÖMB A CÉLPONTOT GRAVITÁCIÓS HULLÁMOKKAL SEMMISÍTI MEG.\"\n  STR_LASER_CANNON_UFOPEDIA: \"HAGYOMÁNYOS LÉZERSUGÁR, ANTI-ANYAG REAKCIÓ GENERÁLJA.\"\n  STR_PLASMA_BEAM_UFOPEDIA: \"A GRAVITÁCIÓS SUGÁR FINOMAN VÁLTOZÓ BEROBBANÓ GRAVITÁCIÓS MEZŐT IRÁNYÍT.\"\n  STR_SECTOID_UFOPEDIA: \"A Szektoid hierachia a katonáktól a vezetőkig erőteljes pszionikus képességekkel rendelkezik.  Ezek segítségével demoralizálhatják katonáinkat, sőt képesek átvenni az irányítást felettük.  Hajlamosak szerepet játszani  emberek és állatok eltűnésében.  A rablás genetikai anyagok beszerzésére irányul keresztezés és klónok előállítása céljából, melyek beszivárognak az emberi társadalomba.  Az állatok egyaránt jelentenek genetikai anyagokat és táplálékforrást.  Ez a faj felsőbbrendű genetikus hibrideket akar kifejleszteni, hogy növelje kaptárszerű közösségük hatékonyságát.\"\n  STR_SECTOID_AUTOPSY: \"Szektoid boncolás\"\n  STR_SECTOID_AUTOPSY_UFOPEDIA: \"A boncolás felfedi a lény egyszerű felépítését és az emésztőszervek maradékát.  Az agy és a szemek igen fejlettek.  A felépítés genetikai beavatkozást vagy mutációt sugall.  A kis száj és orr nem sok szerepet tölt be.  Az ujjak közti hártya és a lapos láb vízi eredetre utal.  Nincsenek szaporítószervek, és fogalmunk sincs, hogyan szaporodhat ez a faj.  A legvalószínűbb, hogy genetikailag gyártott egyedek.\"\n  STR_SNAKEMAN_UFOPEDIA: \"Ez a faj rendkívül barátságtalan környezetben fejlődött ki.  Szívósak és ellenállnak nagymértékű hőmérséklet-változásnak is.  A mozgásuk egy kígyószerű óriási 'lábbal' történik, amely megvédi minden létfontosságú szervüket.  A céljuk szimplán vadászat táplálkozás céljából, és úgy látszik, hogy valamilyen magasabbrendű intelligencia rendelkezik velük, amely katonai jellegű portyázásaikat irányítja a Földön.\"\n  STR_SNAKEMAN_AUTOPSY: \"Kígyóember boncolás\"\n  STR_SNAKEMAN_AUTOPSY_UFOPEDIA: \"A bőr rendkívül szívós és hőálló.  A szív- és érrendszer az izomrendszer része, melyet hidraulikus elv alapján mozgat.  Az egyetlen igazi izom a 'szív'.  A szaporítószervek nagyon hatékonynak tűnnek.  A szaporodás aszexuális, minden kígyóember legföljebb 50 tojást hordoz egyszerre a testében.  Ezek az egyedek a sorsukra hagyva komoly veszélyt jelentenek a földi életre.\"\n  STR_ETHEREAL_UFOPEDIA: \"Ennek az életformának rendkívüli mentális ereje van, melly telepatikus kommunikációt és telekinézist is lehetővé tesz.  Szembetűnően gyenge fizikumát a mentális ereje segítségével támogatja.  Nem értjük ezeknek a telekinetikus erőknek a működését, mivel láthatólag ellentmondanak a jelenleg ismert fizikai törvényeknek.  Rendkívül veszélyesek bármilyen harci helyzetben, ahol mentális erejükre támaszkodva harcolnak.  Ritkán jelennek meg a Földön, mivel úgy néz ki, hogy más fajokat használnak fel céljaik elérése érdekében.\"\n  STR_ETHEREAL_AUTOPSY: \"Éterlény boncolás\"\n  STR_ETHEREAL_AUTOPSY_UFOPEDIA: \"Fizikailag visszamaradt életforma mely látszólag képtelen fenntartani az életfunkcióit.  Az izmok csökevényesek és a belső szervek fejletlennek látszanak.  Az érzékelő szervek - a szemeket is beleértve - úgy tűnik, hogy egyáltalán nem funkcionálnak.  Az agy mindezek ellenére igen fejlett és a test vérellátásának nagy része az agyé.  Rejtély, hogyan képes ez a teremtmény életben maradni külső ellátás nélkül.\"\n  STR_MUTON_UFOPEDIA: \"Ez a humanoid erőteljes fizikumú és intelligens.  Különös étvágyuk van bármilyen nyers húsra, ami a fennmaradásukhoz szükséges, hasonlóan a földi húsevőkhöz.  Az Éterlényekkel vannak telepatikus kapcsolatban, parancsaikat teljesitik.  Amint ez a kapcsolat megszűnik, az elméjük leáll és meghalnak.  A kibernetikus protézisek növelik a harci teljesítményüket.  Tisztán látszik, hogy egy magasabb intelligenciának a bábjai.\"\n  STR_MUTON_AUTOPSY: \"Muton boncolás\"\n  STR_MUTON_AUTOPSY_UFOPEDIA: \"Ennek a teremtménynek a 'bőre' egy szerves alapú páncélzat, mely a testre van ránövesztve.  Számos kibernetikus egység van belé ültetve, mely az érzékelő és keringési rendszer hatékonyságát növeli.  Úgy tűnik a szaporítószervek sebészeti úton el lettek távolítva.  Ezeknek a szerencsétlen teremtményeknek az élete egyértelműen egy hódítás vagy egy háború idejére van korlátozva.  A páncéltörő lőszerek nem igazán hatásosak az edzett bőrükkel szemben.\"\n  STR_CELATID_UFOPEDIA: \"Ez a életforma titokzatos természetes képessége a lebegés.  Az emberi agyhullámokat képes érzékelni, ezért akkor is megtalálja célpontját, ha az jól elrejtőzött.  Ha a Kelatid felfedezte a célpontját, leszáll, és egy kis rendkívül maró méreggömböcskét lő ki.  A teremtmény képes önmagát veszélyes mértékben klónozni.  A Muton fajt kíséri felfedezésein.\"\n  STR_CELATID_AUTOPSY: \"Kelatid boncolás\"\n  STR_CELATID_AUTOPSY_UFOPEDIA: \"A belseje egy kis biomechanikus eszközt tartalmaz, mely ránézésre egy természetes úton kifejlődött anti-gravitációs meghajtórendszer.  A méregtasak a legnagyobb szerv és úgy tűnik nincs elkülönült agyszerkezete.  Nincs felismerhető emésztő- és szaporítószerve. Egy kis szerv embriókat tartalmaz, melyek képesek nagyon gyorsan új egyeddé felnőni.\"\n  STR_SILACOID_UFOPEDIA: \"Ez a szilikon alapú életforma nagy mennyiségű hőt generál.  Megvan az ereje hozzá, hogy sziklákat zúzzon össze, amit a forró belsejében emészt meg.  Az intelligenciája kezdetleges, kibernetikus pótlékok vagy telepatikus egyedek által irányítható. A Mutonokkal együtt dolgozik.\"\n  STR_SILACOID_AUTOPSY: \"Szilakoid boncolás\"\n  STR_SILACOID_AUTOPSY_UFOPEDIA: \"A teremtmény belseje rendkívül forró és úgy látszik ez egyben az emésztőrendszere is.  Egyedi izomrendszere borzasztó erővel és sebességgel bír.  Kőszerű bőre ellenáll a tűznek és a gyújtólőszereknek.\"\n  STR_CHRYSSALID_UFOPEDIA: \"A rákszerű ollók hatékony fegyverek közelharcban.  Ennek a teremtménynek a fejlett anyagcseréje és az ereje gyorssá és ügyessé teszi.  Áldozata megölése helyett egy tojást helyez el benne és mérget fecskendez belé, mely zombit csinál belőle.  Egy új Krisszalid fog hamarosan kitörni a beültetés után.  A Krisszalidok a Kígyóemberekkel állnak kapcsolatban.\"\n  STR_CHRYSSALID_AUTOPSY: \"Krisszalid boncolás\"\n  STR_CHRYSSALID_AUTOPSY_UFOPEDIA: \"Ennek a teremtménynek a csontváza rendkívül szívós, de meglepően sérülékeny robbanó lőszerrel szemben.  Az agy igen fejlett, és sejtjei nagyon gyorsan szaporodnak.  A teremtmény húsz tojást hordoz a belsejében, melyeket más élőlényekbe helyez.  Ez a teremtmény egy nagyon hatékony terrorizáló fegyver.\"\n  STR_FLOATER_UFOPEDIA: \"A Lebegők elsődlegesen katonák és terroristák. Természetileg ragadozó bestiák, genetikai és kibernetikai beavatkozással lettek feljesztve rettentő harcosokká. A test alsó fele és több belső szerv sebészetileg lett eltávolítva, és egy életfunkció-ellátó rendszer helyettesíti azokat.  Ez a rendszer tartalmazza az anti-gravitációs egységet, mely bizonytalanul bár, de lehetővé teszi a teremtmény számára a lebegést.\"\n  STR_FLOATER_AUTOPSY: \"Lebegő boncolás\"\n  STR_FLOATER_AUTOPSY_UFOPEDIA: \"Ez a teremtmény sebészetileg drasztikusan meg lett változtatva.  A lény belsejét formáló eszköz a létfenntartó rendszer, átveszi a szív, a tüdők és az emésztőrendszer szerepét.  Ez teszi lehetővé, hogy teljesen ellenséges körülmények között is túléljen.  Az agya kisebb, mint a miénk, de az érzékelőszervei igen fejlettek.\"\n  STR_REAPER_UFOPEDIA: \"Ennek a kétlábú húsevőnek erőteljes állkapcsai és hatalmas étvágya van.  Számos beültetés van az agyában, melyek aktivitását irányítják.  Ennek a teremtménynek a primitív ragadozóösztönei csak a terrorban és a pusztításban kerülnek kiélésre. Az Aratókat általában a Lebegőkkel együtt szokták emlegetni.\"\n  STR_REAPER_AUTOPSY: \"Arató boncolás\"\n  STR_REAPER_AUTOPSY_UFOPEDIA: \"Az Arató két 'aggyal' és 'szívvel' rendelkezik, így még komolyan megsebesülve is képes ellátni feladatát.  Szőrös bőre azonban erősen gyúlékony, sérülékennyé téve a gyújtólőszerekkel szemben.\"\n  STR_SECTOPOD_UFOPEDIA: \"A Szektopod harci robot, amit nagyerejű lézerfegyverrel láttak el. E hatalmas gépezeteket az Éterlények irányítják telepatikus kapcsolaton keresztül. A Szektopod a legerősebb terrorfegyver, amely az idegen erők rendelkezésére áll.\"\n  STR_SECTOPOD_AUTOPSY: \"Szektopod boncolás\"\n  STR_SECTOPOD_AUTOPSY_UFOPEDIA: \"A robot strapabíró, erőpáncélja a támadás legtöbb formájának ellenáll, különösen a plazmafegyvereknek.  Azonban az érzékelő áramkör sérülékenynek tűnik lézerfegyverekkel szemben.\"\n  STR_CYBERDISC_UFOPEDIA: \"Ez a miniatűr repülő csészealj egy automatizált terror-fegyver nagyteljesítményű plazmasugárral.  Az anti-gravitációs meghajtás nagy előnnyel látja el nehéz terepen.  Elsődleges funkciója a rombolás és a terror a Szektoid faj szolgálatában.\"\n  STR_CYBERDISC_AUTOPSY: \"Kiberkorong boncolás\"\n  STR_CYBERDISC_AUTOPSY_UFOPEDIA: \"A kiberkorong erősen felvértezett és különösen ellenálló robbanó lőszerrel szemben.  Az elsődleges anti-gravitációs rendszer túlságosan megsérült, hogy bármit is megértsünk működéséből.\"\n  STR_UFO_POWER_SOURCE_UFOPEDIA: \"Az idegen gép erőforrása egy anti-anyag reaktor, amely Elerium (115-ös elem) segítségével erőteljes gravitációs hullámokat és az energia más formáit képes generálni.  Az anyag energiává alakítása a hihetetlen 99%-os hatásfokkal történik, ezért kis mennyiségű Elerium nagy mennyiségű erőt képes létrehozni.  Ez az egység könnyedén elkészíthető idegen fémekből.\"\n  STR_UFO_NAVIGATION_UFOPEDIA: \"Az idegen gép kifinomult számítógépek segítségével tájékozódik a Földön és az űrben.  A rendszer optikai processzorok hálózatára épül.  A kezelőfelület viszonylag egyszerű - a navigátor az erőforrás által generált gravitációs hullámokat beállítva irányítja a gép mozgását.  A rendszer kezelését az emberek könnyen elsajátíthatják, és idegen fémekből és más összetevőkből le is gyártható.\"\n  STR_UFO_CONSTRUCTION_UFOPEDIA: \"Egy idegen gép három fő komponensből áll - egy erőforrás, egy navigációs rendszer és egy géptörzs, amely idegen fémekből épül.  A törzs speciális kiképzésű, hogy lehetővé tegye a gravitációs hullámok irányítását.  Ezeken kívül még egy kis mennyiségű Elerium is szükséges az erőforrás működéséhez.  Ha egyszer a szerkesztés irányvonalait megértjük és minden egység funkciója ismert, akkor lehetségessé válik ilyen gép építése.\"\n  STR_ALIEN_FOOD_UFOPEDIA: \"Ezek a kamrák sokféle enzimet tartalmaznak, melyek segítségével emészthetővé válnak az állati vagy akár emberi testrészek.  A folyadék ezután mint előemésztett étel fogyasztható, valószínűleg közvetlenül véráramba adagolva.  Ez bizonyos függőséget sugall a Földön az élelem felé - egy szimbiózis a Föld és az idegen társadalom között.\"\n  STR_ALIEN_REPRODUCTION_UFOPEDIA: \"Ezek a kamrák idegen magzatokat tartalmaznak.  A konténerek felépítéséből úgy tűnik, hogy az idegenek szaporodása teljesen a laboratóriumokon alapul.  A gazdag tápanyag biztosítja a magzat gyors növekedését.  Ez a gyárszerű rendszer rövid idő alatt idegen klónok ezreit képes előállítani.  A folyamat könnyen adaptálható emberekre, vagy ember-idegen hibridekre.\"\n  STR_ALIEN_ENTERTAINMENT_UFOPEDIA: \"Ezek a gömbök a felüdülést szolgálják.  A pszionikus áramkörök az agy különböző központjait stimulálják.  A hatása a hallucinogén drogokéhoz hasonló.  Ez az egyetlen bizonyíték, hogy az idegeneknek létezik kultúrális vagy pihenő időtöltésük.\"\n  STR_ALIEN_SURGERY_UFOPEDIA: \"Ez a sebészeti felszerelés állati testrészek eltávolítására használatos.  A széles körben elterjedt állatcsonkítások főleg ennek a bizarr idegen tevékenységnek tulajdoníthatóak.  Valószínűleg az eltávolított testrészek genetikai vagy táplálkozási célokat szolgálnak.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"Régóta emberek ezrei állítják, hogy idegenek rabolták el, néha többször is ismétlődően.  Az igazság messze rettenetesebb.  Az embereket elrabolják, kivizsgálják, majd megfigyelés alatt tartják.  A legjobb egyedekből genetikai anyagokat vonnak ki.  Asszonyokba idegen-ember hibrid magzatokat ültetnek be, majd néhány hónap múlva eltávolítják.  Ki tudja, milyen szörnyűség motiválja az idegeneket?\"\n  STR_ALIEN_ALLOYS_UFOPEDIA: \"Az idegen gépek különleges tulajdonságokkal bíró fémekből épülnek fel.  Rendkívül könnyűek és tartósak, elektromágneses úton önthetők.  Ez az anyag gyártható és sokféle gyártási folyamatban felhasználható.\"\n  STR_ELERIUM_115_UFOPEDIA: \"Ezen elem különleges tulajdonsága, hogy bizonyos részecskékkel bombázva anti-anyag erőt generál.  Ez gravitációs hullámokat és más formájú energiát képes létrehozni.  Természetes állapotában nem található meg a naprendszerünkben, és nem lehet gyártani sem.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"Tisztán látszik, hogy vesztésre állunk a Földért vívott csatában.  Az idegen hordák számbeli fölényével szemben csak a terjeszkedésüket tudjuk lassítani.  Az emberiség egyetlen reménye: a forrásukra döntő csapást mérni.  A kutatásaink a naprendszerünkön belüli közeli bázisra engednek következtetni.  Az idegenek ezt a helyet egy ősi civilizáció központjaként jelölik, amely megelőzi az emberi történelmet.  Meg kell találnunk ezt a helyet amilyen hamar csak lehet.  El kell fognunk és kihallgatnunk egy idegen vezetőt, hogy részletesebb információkat szerezzünk.  A nagyobb UFO-kban valószínű, hogy legalább egy vezető tartózkodik.\"\n  STR_THE_MARTIAN_SOLUTION_UFOPEDIA: \"A kutatásaink már a Marsra mutatnak az idegen szervezkedések bázisaként. A bázis erősen el van rejtve és tartalmazza mindazokat a klónozó és egyéb gyárakat, amelyből megoldható a földi beszivárgás utánpótlása. Úgy néz ki, hogy van ott egy irányító számítógép-féle, amely az egész műveletet irányítja. Valószínű továbbá, hogy a kaptárszerű idegen társadalom rendelkezik valamiféle 'méhkirálynő'-vel. Ez az alapvetően sebezhető pontjuk - ha megsemmisítjük az 'agyat', a test meghal. Fokoznunk kell kutatási erőfeszítéseinket, mielőtt túl késő lenne. A haladás érdekében el kell fognunk a legmagasabb rangú idegeneket - a parancsnokokat - melyek csak idegen bázisokban és csatahajókon fordulnak elő.\"\n  STR_CYDONIA_OR_BUST_UFOPEDIA: \"Most már világos, hogy az idegen hordák Cydonia földalatti bázisából kapják utasításaikat - mely egy különös területen helyezkedik el a Marson: egy öt oldalú piramis és egy hatalmas arcra emlékeztető formáció közelében.  Cydonia civilizációja évmilliókkal ezelőtt virágzott a Marson, de nem tudjuk miért halt ki, vagy mi a kapcsolata a jelenlegi idegen tevékenységgel.  Bármi is legyen a magyarázat, Cydoniába kell küldenünk egy expedíciót.  Ez az idegenek legyőzésének egyetlen módja.  Le kell rombolnunk a fő irányító 'agyat'.  Szükségünk lesz egy Bosszúállóra, amely a rendelkezésünkre álló legpusztítóbb fegyverekkel van felszerelve.  Itt nincs több tanulmányozni valónk - meg kell várnunk a Cydoniai támadás kimenetelét.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"KÖZÉPRE ÁLL-IDŐ=5 Mp\"\n  STR_CANCEL_UC: \"MÉGSEM\"\n  STR_NONE: \"Semmi\"\n  STR_UNKNOWN: \"Ismeretlen\"\n  STR_POOR: \"Gyenge\"\n  STR_AVERAGE: \"Átlagos\"\n  STR_GOOD: \"Jó\"\n  STR_EXCELLENT: \"Kiváló\"\n  STR_BUILD_NEW_BASE_UC: \"ÚJ BÁZIS ÉPÍTÉSE\"\n  STR_BASE_INFORMATION: \"BÁZIS INFORMÁCIÓ\"\n  STR_EQUIP_CRAFT: \"GÉPFELSZERELÉS\"\n  STR_BUILD_FACILITIES: \"ÉPÜLET EMELÉSE\"\n  STR_RESEARCH: \"KUTATÁS\"\n  STR_MANUFACTURE: \"GYÁRTÁS\"\n  STR_TRANSFER_UC: \"ÁTSZÁLLÍTÁS\"\n  STR_PURCHASE_RECRUIT: \"VÁSÁRLÁS/SOROZÁS\"\n  STR_SACK: \"KIRÚG\"\n  STR_SELL_SACK_UC: \"ELADÁS/KIRÚGÁS\"\n  STR_GEOSCAPE_UC: \"FÖLDGÖMB\"\n  STR_NAME: \"Név\"\n  STR_AREA: \"Terület\"\n  STR_BUILD_NEW_BASE: \"Új bázis építése\"\n  STR_CANCEL: \"Mégsem\"\n  STR_COST_UC: \"ÁR>\"\n  STR_CONSTRUCTION_TIME_UC: \"ÉPÍTÉS IDEJE>\"\n  STR_DAY:\n    one: \"{N} nap\"\n    other: \"{N} nap\"\n  STR_HOUR:\n    one: \"{N} óra\"\n    other: \"{N} óra\"\n  STR_MAINTENANCE_UC: \"FENNTARTÁS>\"\n  STR_OK: \"OKÉ\"\n  STR_INSTALLATION: \"Építkezés\"\n  STR_CURRENT_RESEARCH: \"JELENLEGI KUTATÁS\"\n  STR_SCIENTISTS_AVAILABLE: \"Elérhető Tudósok>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Tudósok beosztva>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Szabad laborkapacitás>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"KUTATÁSI PROGRAM\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"TUDÓSOK BEOSZTVA\"\n  STR_PROGRESS: \"HALADÁS\"\n  STR_NEW_PROJECT: \"Új Program\"\n  STR_CANCEL_PROJECT: \"KUTATÁS LEÁLLÍTÁSA\"\n  STR_NEW_RESEARCH_PROJECTS: \"ÚJ KUTATÁSI PROGRAMOK\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"ELÉRHETŐ TUDÓSOK>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"SZABAD LABORKAPACITÁS>{ALT}{0}\"\n  STR_INCREASE: \"Növelés\"\n  STR_DECREASE: \"Csökkentés\"\n  STR_START_PROJECT: \"PROGRAM INDÍTÁSA\"\n  STR_CURRENT_PRODUCTION: \"JELENLEGI GYÁRTÁS\"\n  STR_ENGINEERS_AVAILABLE: \"Elérhető Mérnökök>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Mérnökök beosztva>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Szabad műhelykapacitás>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Jelenlegi Tőke>{ALT}{0}\"\n  STR_ITEM: \"TÉTEL\"\n  STR_ENGINEERS__ALLOCATED: \"Mérnökök beosztva\"\n  STR_UNITS_PRODUCED: \"Legyártott darabszám\"\n  STR_TOTAL_TO_PRODUCE: \"Összes gyártandó\"\n  STR_COST__PER__UNIT: \"Ár{NEWLINE}per{NEWLINE}egység\"\n  STR_DAYS_HOURS_LEFT: \"Hátralévő napok/órák\"\n  STR_NEW_PRODUCTION: \"Új gyártás\"\n  STR_PRODUCTION_ITEMS: \"Gyártható tételek\"\n  STR_CATEGORY: \"KATEGÓRIA\"\n  STR_START_PRODUCTION: \"GYÁRTÁS INDÍTÁSA\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} mérnöki munkaóra szükséges egy darab legyártásához\"\n  STR_COST_PER_UNIT_: \"Egységár>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Szükséges műhelykapacitás>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"SPECIÁLIS ANYAGSZÜKSÉGLET\"\n  STR_ITEM_REQUIRED: \"SZÜKSÉGES TÁRGY\"\n  STR_UNITS_REQUIRED: \"SZÜKSÉGES DARABSZÁM\"\n  STR_UNITS_AVAILABLE: \"ELÉRHETŐ DARABSZÁM\"\n  STR_STOP_PRODUCTION: \"GYÁRTÁS LEÁLLÍTÁSA\"\n  STR_ENGINEERS_AVAILABLE_UC: \"ELÉRHETŐ MÉRNÖKÖK>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"SZABAD MŰHELYKAPACITÁS>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"HAVI NYERESÉG>{ALT}{0}\"\n  STR_INCREASE_UC: \"NÖVELÉS\"\n  STR_DECREASE_UC: \"CSÖKKENTÉS\"\n  STR_UNITS_TO_PRODUCE: \"Gyártandó darabszám\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Vásárlás/Bérlés/Sorozás\"\n  STR_COST_OF_PURCHASES: \"Beszerzési költség>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"EGYSÉGÁR\"\n  STR_QUANTITY_UC: \"MENNYISÉG\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"FELHASZNÁLHATÓ SZEMÉLYZET:TELJES SZEMÉLYZET>\"\n  STR_SOLDIERS: \"Katonák\"\n  STR_SCIENTISTS: \"Tudósok\"\n  STR_ENGINEERS: \"Mérnökök\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"KIHASZNÁLT HELY:SZABAD HELY>\"\n  STR_LIVING_QUARTERS: \"Lakónegyed\"\n  STR_STORES: \"Raktár\"\n  STR_LABORATORIES: \"Laboratórium\"\n  STR_WORK_SHOPS: \"Műhely\"\n  STR_HANGARS: \"Hangár\"\n  STR_SHORT_RANGE_DETECTION: \"Rövid távú észlelés\"\n  STR_DEFENSE_STRENGTH: \"Védelmi erősség\"\n  STR_TRANSFERS_UC: \"ÁTSZÁLLÍTÁSOK\"\n  STR_TRANSFERS: \"Átszállítások\"\n  STR_ARRIVAL_TIME_HOURS: \"Érkezés: (óra)\"\n  STR_COST_: \"Ár>{ALT}{0}\"\n  STR_AREA_: \"Terület>{ALT}{0}\"\n  STR_BASE_NAME: \"Bázis neve?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"VÁLASSZ HELYET A KÖZPONTI LIFTNEK\"\n  STR_TRANSFER: \"Átszállítás\"\n  STR_AMOUNT_TO_TRANSFER: \"SZÁLLÍTANDÓ MENNYISÉG\"\n  STR_SELECT_DESTINATION_BASE: \"Válaszd ki a célbázist\"\n  STR_COST: \"Ár\"\n  STR_VICTORY_1: \"Amint belépsz a kamrába, megpillantod az idegen agyat - a küldetésed célpontja.  Mielőtt tüzet nyitnál, kommunikálni kezd feléd az alapjainál elhelyezkedő képernyőn keresztül.  Azért könyörög, hogy meghallgasd érveit a túlélésével kapcsolatban, mielőtt meghúznád a ravaszt...\"\n  STR_VICTORY_2: \"Az agy: 'Évmilliókkal ezelőtt az általatok Marsnak nevezett bolygó élő volt.  Az életet a mi civilizációnk hozta az akkor terméketlen bolygótokra.  Évmilliók leforgása alatt látogatgattuk a bolygótokat és genetikai úton fejlesztettük a fajtátokat.  Nem ölhetsz meg minket, ti a részeink vagytok...\"\n  STR_VICTORY_3: \"Ez a marsi civilizáció központja - a piramisok évmilliókkal a tieitek előtt épültek - és egy olyan faj építette, amely a ti ősötök.  Nincs oly bolygó, mely elérhetetlen lenne számunkra.  Ez az erő nemsokára a tiétek lehet.  Mi csak az együttműködéseteket kérjük...\"\n  STR_GAME_OVER_1: \"Az idegenek megkísérelték az emberiséget kivégezni a városok lerombolásával, a tengerek és a levegő megmérgezésével.  Az ellenálló földi hadseregek tehetetlenek voltak a sokkal felsőbbrendű technológiával szemben.  A túlélő generációk szörnyű mutációkon mentek keresztül, ahogy az idegen rombolás elől menekültek.  Rabszolgatáborokba szervezték őket, hogy segítsék a Földet egy valamilyen ismeretlen birodalom idegen kolóniájává alakítani.\"\n  STR_GAME_OVER_2: \"A tudás, amelyet az X-Com program alatt halmoztunk fel, immáron örökre elveszett. Elbuktál. Nem sikerült megmentened a Földet.\"\n  STR_VICTORY_4: \"Az idegen agyat egy kitörő forró plazma szakítja félbe, és az egész idegen erő legyőzetett.\"\n  STR_VICTORY_5: \"Mivel az idegenek elvesztették a Marsot, így a Földet is. Nem tolt sok időbe, az X-Com kutatásoknak köszönhetően, az emberiség újra felvirágzott, és a Marsot megkaparintotta magának. Az idegen fenyegetés véget ért, de hogy meddig, azt senki sem tudhatja ...\"\n  STR_YOU_HAVE_FAILED: \"Nem voltál képes megállítani az idegen támadást.  A támogató nemzetek egytől-egyig egyezményeket kötöttek a technológiát, békét, jólétet ígérő idegenekkel.  Azonban hamarosan kiderült: az idegeneknek más terveik vannak...\"\n  STR_TOTAL_UC: \"ÖSSZESEN\"\n  STR_INCOME: \"Bevétel\"\n  STR_EXPENDITURE: \"Kiadás\"\n  STR_MAINTENANCE: \"Fenntartás\"\n  STR_BALANCE: \"Egyenleg\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"UFO Aktivitás (Régiók)\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"UFO Aktivitás (Országok)\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"X-Com Aktivitás az egyes Régiókban\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"X-Com Aktivitás az egyes Országokban\"\n  STR_FINANCE: \"Pénzügy\"\n  STR_DATE_FIRST: \"{0}.\"\n  STR_DATE_SECOND: \"{0}.\"\n  STR_DATE_THIRD: \"{0}.\"\n  STR_DATE_FOURTH: \"{0}.\"\n  STR_FINANCE_THOUSANDS: \"($1000)\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Nincs elég speciális alapanyag{NEWLINE}{0}{NEWLINE}gyártásához itt:{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Nincs elég pénz{NEWLINE}{0}{NEWLINE}gyártásához itt:{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"Elkészült a(z){NEWLINE}{0}{NEWLINE}a(z){NEWLINE}{1}{NEWLINE}bázison\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"Elkészült a(z){NEWLINE}{0}{NEWLINE}építése a(z){NEWLINE}{1}{NEWLINE}bázison\"\n  STR_OK_5_SECONDS: \"OKÉ - 5 mp\"\n  STR_RESEARCH_COMPLETED: \"Kutatás befejezve\"\n  STR_VIEW_REPORTS: \"JELENTÉS\"\n  STR_WE_CAN_NOW_RESEARCH: \"Most már tudunk kutatni:\"\n  STR_WE_CAN_NOW_PRODUCE: \"Most már tudunk gyártani:\"\n  STR_SUNDAY: \"Vasárnap\"\n  STR_MONDAY: \"Hétfő\"\n  STR_TUESDAY: \"Kedd\"\n  STR_WEDNESDAY: \"Szerda\"\n  STR_THURSDAY: \"Csütörtök\"\n  STR_FRIDAY: \"Péntek\"\n  STR_SATURDAY: \"Szombat\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"{1} feltöltéséhez nincs elég {0} a(z) {2} bázison\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"{1} felfegyverzéséhez nincs elég {0} a(z) {2} bázison\"\n  STR_UFO_IS_NOT_RECOVERED: \"UFO nem lett begyűjtve\"\n  STR_UFO_IS_RECOVERED: \"UFO begyűjtve\"\n  STR_CRAFT_IS_LOST: \"A gép elveszett\"\n  STR_TERROR_CONTINUES: \"A terror folytatódik\"\n  STR_ALIENS_DEFEATED: \"Idegenek legyőzve\"\n  STR_BASE_IS_LOST: \"A bázis elveszett\"\n  STR_BASE_IS_SAVED: \"A bázis megmenekült\"\n  STR_ALIEN_BASE_STILL_INTACT: \"Az idegen bázis még sértetlen\"\n  STR_ALIEN_BASE_DESTROYED: \"Az idegen bázis lerombolva\"\n  STR_ALIENS_KILLED: \"MEGÖLT IDEGENEK\"\n  STR_ALIEN_CORPSES_RECOVERED: \"IDEGEN TETEMEK BEGYŰJTVE\"\n  STR_LIVE_ALIENS_RECOVERED: \"ÉLŐ IDEGENEK BEGYŰJTVE\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"IDEGEN SZERKEZETEK BEGYŰJTVE\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"IDEGEN BÁZIS KÖZPONTJA LEROMBOLVA\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"CIVIL ÁLDOZATOK (IDEGENEK ÁLTAL)\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"CIVIL ÁLDOZATOK X-COM ÜGYNÖKÖK ÁLTAL \"\n  STR_CIVILIANS_SAVED: \"MEGMENTETT CIVILEK\"\n  STR_XCOM_OPERATIVES_KILLED: \"MEGÖLT X-COM ÜGYNÖKÖK \"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"BEVETÉS KÖZBEN ELTŰNT X-COM ÜGYNÖKÖK: \"\n  STR_TANKS_DESTROYED: \"MEGSEMMISÍTETT TANKOK\"\n  STR_XCOM_CRAFT_LOST: \"ELVESZTETT X-COM GÉP\"\n  STR_UFO_RECOVERY: \"UFO BEGYŰJTÉSE\"\n  STR_ALIEN_BASE_RECOVERY: \"IDEGEN BÁZIS BEGYŰJTÉSE\"\n  STR_BASE_UNDER_ATTACK: \"A(z) {0} bázist megtámadták!\"\n  STR_BASE_DEFENSES_INITIATED: \"BÁZIS VÉDELME MŰKÖDÉSBE LÉP\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"GRAVIPAJZS ELTASZÍTJA AZ UFOT!\"\n  STR_FIRING: \"TÜZEL\"\n  STR_HIT: \"TALÁLT!\"\n  STR_UFO_DESTROYED: \"UFO MEGSEMMISÜLT!\"\n  STR_MISSED: \"MELLÉ!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Eladás/Kirúgás\"\n  STR_VALUE_OF_SALES: \"ELADÁSOK ÉRTÉKE> {ALT}{0}\"\n  STR_FUNDS: \"TŐKE> {ALT}{0}\"\n  STR_SELL_SACK: \"Elad/Kirúg\"\n  STR_VALUE: \"Értéke\"\n  STR_CRAFT_: \"GÉP> {ALT}{0}\"\n  STR_CRAFTNAME: \"{1}. {0}\"\n  STR_UFO_CRASH_RECOVERY: \"LEZUHANT UFO BEGYŰJTÉSE\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"Figyelem - Lehetnek túlélők az UFO-ban vagy a környékén. A küldetés sikeres teljesítésének feltétele: az összes ellenséges egység megsemmisítése vagy semlegesítése. Az UFO maradványai, az idegen tetemek és szerkezetek begyűjtése csak ez után kezdődhet meg. A küldetés megszakításához az X-Com ügynökeinek vissza kell térnie a szállítóeszközbe, majd kattints a 'Küldetés megszakítása' ikonra.\"\n  STR_UFO_GROUND_ASSAULT: \"UFO FÖLDI TÁMADÁSA\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"Derítsd fel a leszállóhelyet, majd - ha lehetséges - nyerj belépést az UFO-ba. A küldetés sikeres teljesítésének feltétele: az összes ellenséges egység megsemmisítése vagy semlegesítése. Az UFO, az idegen tetemek és szerkezetek begyűjtése csak ez után kezdődhet meg. A küldetés megszakításához az X-Com ügynökeinek vissza kell térni a szállítóeszközhöz, majd kattints a 'Küldetés megszakítása' ikonra.\"\n  STR_BASE_DEFENSE: \"BÁZIS VÉDELEM\"\n  STR_BASE_UC_: \"BÁZIS> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"Egy idegen hajó landolt a közelben. A bázisunk komoly veszélyben van. Az ilyenkor szokásos eljárás szerint minden nem-fegyveres személyzetet és X-Com gépet evakuáltuk. Az idegen egységek a hangárak ajtajain vagy a központi liften keresztül hatolnak be. Védd meg a bázist és a létfontosságú épületeket minden áron - ez egy küzdelem mindhalálig. Ha a 'Küldetés megszakítása' ikonra kattintasz, elfogadod a vereséget és elveszted a bázist.\"\n  STR_ALIEN_BASE_ASSAULT: \"IDEGEN BÁZIS TÁMADÁSA\"\n  STR_ALIEN_BASE_ASSAULT_BRIEFING: \"X-Com ügynökök belépést nyertek egy idegen bázisra. Az irányítóközpontnak meg kell semmisülnie, hogy a bázis működésképtelenné váljon. A küldetés akkor fejeződik be, amikor az összes ellenség megsemmisült, vagy az osztagod visszatért a zöld kijárati területre (majd kattints a 'Küldetés megszakítása' ikonra).\"\n  STR_CYDONIA_BRIEFING: \"Megérkeztél Cydoniába.  Belépést nyersz egy hatalmas földalatti komplexumba a marsi szfinx közelében.  Meg kell semmisítened az idegen agyat, amely minden idegen tevékenységet irányít.  Az emberiség sorsa a Te kezedben van....\"\n  STR_TERROR_MISSION: \"TERROR KÜLDETÉS\"\n  STR_TERROR_MISSION_BRIEFING: \"A küldetés sikeres teljesítésének feltétele: az összes ellenséges egység megsemmisítése vagy semlegesítése. Meg kell próbálnod megmenteni bármilyen civil életét, semlegesítve a területen az idegen fenyegetést. A küldetés megszakításához az X-Com ügynökeinek vissza kell térni a szállítóeszközbe, majd kattints a 'Küldetés megszakítása' ikonra.\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"NINCS SZABAD HANGÁR A GÉPGYÁRTÁSHOZ!{SMALLLINE}Minden gép egy bázishoz van rendelve; átszállítva, vásárolva, vagy építve, egy hangárt foglal el.  Építs egy új hangárt vagy szállíts át egy gépet egy másik bázisra.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"NINCS SZABAD HANGÁR A VÁSÁRLÁSHOZ!{SMALLLINE}Minden gép egy bázishoz van rendelve; átszállítva, vásárolva, vagy építve, egy hangárt foglal el.  Építs egy új hangárt vagy szállíts át egy gépet egy másik bázisra.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"NINCS SZABAD HANGÁR AZ ÁTSZÁLLÍTÁSHOZ!{SMALLLINE}Minden gép egy bázishoz van rendelve; átszállítva, vásárolva, vagy építve, egy hangárt foglal el.  Építs egy új hangárt vagy szállíts át egy gépet egy másik bázisra.\"\n  STR_CANNOT_BUILD_HERE: \"NEM ÉPÍTHETSZ IDE!{SMALLLINE}Építkezni csak egy már létező épület mellé lehet.\"\n  STR_NO_FREE_ACCOMODATION: \"NINCS SZABAD LAKÓHELY!{SMALLLINE}A célbázis nem rendelkezik a lakónegyedeiben elegendő hellyel.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"NINCS ELÉG MŰHELY!{SMALLLINE}Építs új műhelyt, vagy csökkentsd a munkát más programokon.\"\n  STR_NOT_ENOUGH_MONEY: \"NINCS ELÉG PÉNZ!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"NINCS ELÉG RAKTÁR-HELY!{SMALLLINE}Építs új raktárat vagy küldj át néhány dolgot más bázisokra.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"NINCS ELÉG LAKÓHELY!{SMALLLINE}Építs új lakónegyedeket vagy küldj át valamennyi személyzetet más bázisokra.\"\n  STR_LAUNCH_INTERCEPTION: \"ELFOGÁS INDÍTÁSA\"\n  STR_CRAFT: \"GÉP\"\n  STR_STATUS: \"ÁLLAPOT\"\n  STR_BASE: \"BÁZIS\"\n  STR_READY: \"KÉSZ\"\n  STR_OUT: \"KINT\"\n  STR_REPAIRS: \"JAVÍTJÁK\"\n  STR_REFUELLING: \"TANKOL\"\n  STR_REARMING: \"FEGYVERZIK\"\n  STR_TARGET: \"CÉLPONT: {0}\"\n  STR_WAY_POINT: \"TEREPPONT\"\n  STR_ARE_YOU_SURE_CYDONIA: \"Biztos vagy benne, hogy ezt a gépet el akarod küldeni Cydoniába?\"\n  STR_YES: \"IGEN\"\n  STR_NO: \"NEM\"\n  STR_SELECT_DESTINATION: \"VÁLASSZ CÉLPONTOT\"\n  STR_CYDONIA: \"CYDONIA\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"VÁLASSZ HELYET AZ ÚJ BÁZISNAK\"\n  STR_RETURN_TO_BASE: \"VISSZATÉRÉS A BÁZISRA\"\n  STR_SELECT_NEW_TARGET: \"ÚJ CÉLPONT VÁLASZTÁSA\"\n  STR_PATROL: \"ŐRJÁRAT\"\n  STR_STATUS_: \"ÁLLAPOT>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"MEGSÉRÜLT - VISSZATÉR A BÁZISRA\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"KEVÉS AZ ÜZEMANYAG - VISSZATÉR A BÁZISRA\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"KÜLDETÉS VÉGREHAJTVA - VISSZATÉR A BÁZISRA\"\n  STR_PATROLLING: \"ŐRJÁRATBAN\"\n  STR_TAILING_UFO: \"KÖVETI AZ UFOT\"\n  STR_INTERCEPTING_UFO: \"ELFOGÁS: {0}. UFO\"\n  STR_RETURNING_TO_BASE: \"VISSZATÉR A BÁZISRA\"\n  STR_DESTINATION_UC_: \"CÉL: {0}\"\n  STR_BASE_UC: \"BÁZIS>{ALT}{0}\"\n  STR_SPEED_: \"SEBESSÉG>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"MAXIMÁLIS SEBESSÉG>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"MAGASSÁG>{ALT}{0}\"\n  STR_VERY_LOW: \"NAGYON ALACSONY\"\n  STR_LOW_UC: \"ALACSONY\"\n  STR_HIGH_UC: \"MAGAS\"\n  STR_VERY_HIGH: \"NAGYON MAGAS\"\n  STR_FUEL: \"ÜZEMANYAG>{ALT}{0}\"\n  STR_WEAPON_ONE: \"1. FEGYVER>{ALT}{0}\"\n  STR_NONE_UC: \"SEMMI\"\n  STR_ROUNDS_: \"LŐSZER>{ALT}{0}\"\n  STR_WEAPON_TWO: \"2. FEGYVER>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"ELFOGÓ GÉPEK\"\n  STR_BASE_: \"Bázis>{0}\"\n  STR_NAME_UC: \"NÉV\"\n  STR_AMMO_: \"LŐSZER>{ALT}{0}\"\n  STR_CREW: \"LEGÉNYSÉG\"\n  STR_EQUIPMENT_UC: \"FELSZERELÉS\"\n  STR_ARMOR: \"PÁNCÉL\"\n  STR_MAX: \"MAX>{ALT}{0}\"\n  STR_ROOKIE: \"Újonc\"\n  STR_SQUADDIE: \"Szakaszvezető\"\n  STR_SERGEANT: \"Őrmester\"\n  STR_CAPTAIN: \"Százados\"\n  STR_COLONEL: \"Ezredes\"\n  STR_COMMANDER: \"Parancsnok\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Válassz osztagot a(z) {0} szállítóra\"\n  STR_SORT_BY: \"RENDEZÉS...\"\n  STR_ORIGINAL_ORDER: \"EREDETI SORREND\"\n  STR_MISSIONS2: \"KÜLDETÉSEK\"\n  STR_KILLS2: \"ÖLÉSEK\"\n  STR_WOUND_RECOVERY2: \"SEBGYÓGYULÁS\"\n  STR_SPACE_AVAILABLE: \"SZABAD HELY>{ALT}{0}\"\n  STR_SPACE_USED: \"FOGLALT HELY>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"FOGLALT HELY\"\n  STR_RANK: \"RENDFOKOZAT\"\n  STR_WOUNDED: \"SEBESÜLT\"\n  STR_EQUIPMENT_FOR_CRAFT: \"{0}-n lévő felszerelések\"\n  STR_DEFENSE_VALUE: \"Védelmi érték\"\n  STR_HIT_RATIO: \"Találati arány\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}készen áll{NEWLINE}a leszállásra:{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"Kezdődhet a küldetés?\"\n  STR_SELECT_ARMAMENT: \"Válassz fegyverzetet\"\n  STR_AMMUNITION_AVAILABLE: \"ELÉRHETŐ LŐSZER\"\n  STR_ARMAMENT: \"FEGYVERZET\"\n  STR_NOT_AVAILABLE: \"N.A.\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"PÁNCÉLVÁLASZTÁS:{NEWLINE}{0}\"\n  STR_TYPE: \"TÍPUS\"\n  STR_PERSONAL_ARMOR_UC: \"SZEMÉLYI PÁNCÉL\"\n  STR_POWER_SUIT_UC: \"ERŐ PÁNCÉL\"\n  STR_FLYING_SUIT_UC: \"REPÜLŐ PÁNCÉL\"\n  STR_SELECT_ARMOR: \"Válassz páncélt\"\n  STR_NORTH: \"ÉSZAK\"\n  STR_NORTH_EAST: \"ÉSZAK-KELET\"\n  STR_EAST: \"KELET\"\n  STR_SOUTH_EAST: \"DÉL-KELET\"\n  STR_SOUTH: \"DÉL\"\n  STR_SOUTH_WEST: \"DÉL-NYUGAT\"\n  STR_WEST: \"NYUGAT\"\n  STR_NORTH_WEST: \"ÉSZAK-NYUGAT\"\n  STR_SELECT_ACTION: \"VÁLASSZ MŰVELETET\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"FOLYTASD AZ ELFOGÓ ÜLDÖZÉST\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"ELFOGÁS NÉLKÜLI ÜLDÖZÉS\"\n  STR_VERY_LARGE: \"NAGYON NAGY\"\n  STR_LARGE: \"NAGY\"\n  STR_MEDIUM_UC: \"KÖZEPES\"\n  STR_SMALL: \"KICSI\"\n  STR_VERY_SMALL: \"NAGYON KICSI\"\n  STR_GROUNDED: \"LESZÁLLT\"\n  STR_DETECTED: \"Észlelve\"\n  STR_SIZE_UC: \"MÉRET\"\n  STR_ALTITUDE: \"MAGASSÁG\"\n  STR_HEADING: \"IRÁNY\"\n  STR_SPEED: \"SEBESSÉG\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"UFORA ÁLL-IDŐ=5 Mp\"\n  STR_TRACKING_LOST: \"NYOMA VESZETT\"\n  STR_REDIRECT_CRAFT: \"GÉP ÁTIRÁNYÍTÁSA\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"MENJ AZ UFO UTOLSÓ ISMERT POZÍCIÓJÁRA\"\n  STR_UFO_: \"{0}. UFO\"\n  STR_ALIEN_BASE_: \"{0}. IDEGEN BÁZIS\"\n  STR_CRASH_SITE_: \"{0}. LEZUHANÁSI HELY\"\n  STR_LANDING_SITE_: \"{0}. LESZÁLLÁSI HELY\"\n  STR_WAY_POINT_: \"{0}. TEREPPONT\"\n  STR_TERROR_SITE: \"{0}. TERROR HELY\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}célba ért:{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"Most őrjáratban van\"\n  STR_ALIEN_ORIGINS: \"Idegen eredet\"\n  STR_THE_MARTIAN_SOLUTION: \"A marsi megoldás\"\n  STR_CYDONIA_OR_BUST: \"Cydonia vagy Bukás\"\n  STR_UFOPAEDIA: \"UFOpédia\"\n  STR_XCOM_CRAFT_ARMAMENT: \"X-COM GÉP ÉS FEGYVERZET\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"NEHÉZFEGYVERZET PLATFORM -NFP-\"\n  STR_WEAPONS_AND_EQUIPMENT: \"FEGYVEREK ÉS FELSZERELÉS\"\n  STR_ALIEN_ARTIFACTS: \"IDEGEN SZERKEZETEK\"\n  STR_BASE_FACILITIES: \"BÁZIS ÉPÜLETEI\"\n  STR_ALIEN_LIFE_FORMS: \"IDEGEN ÉLETFORMÁK\"\n  STR_ALIEN_RESEARCH_UC: \"IDEGEN KUTATÁS\"\n  STR_UFO_COMPONENTS: \"UFO KOMPONENSEK\"\n  STR_UFOS: \"UFOk\"\n  STR_SELECT_ITEM: \"VÁLASSZ TÉTELT\"\n  STR_ACCELERATION: \"GYORSULÁS>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"ÜZEMANYAG-KAPACITÁS>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"FEGYVERFOGLALATOK>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"SÉRÜLÉSTŰRÉS>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"RAKODÓKAPACITÁS>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"NFP KAPACITÁS>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Roncsolás\"\n  STR_RANGE: \"Hatótáv\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Pontosság\"\n  STR_RE_LOAD_TIME: \"Újratöltési idő\"\n  STR_SECONDS: \"{0} mp.\"\n  STR_DAMAGE_ARMOR_PIERCING: \"PÁNCÉLTÖRŐ\"\n  STR_DAMAGE_INCENDIARY: \"GYÚJTÓ\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"DETONÁCIÓS\"\n  STR_DAMAGE_LASER_BEAM: \"LÉZERSUGÁR\"\n  STR_DAMAGE_PLASMA_BEAM: \"PLAZMASUGÁR\"\n  STR_DAMAGE_STUN: \"BÉNÍTÓ\"\n  STR_DAMAGE_MELEE: \"KÖZELHARC\"\n  STR_DAMAGE_ACID: \"SAV\"\n  STR_DAMAGE_SMOKE: \"FÜST\"\n  STR_SHOT_TYPE: \"LÖVÉS TÍPUSA\"\n  STR_ACCURACY_UC: \"PONTOSSÁG\"\n  STR_TIME_UNIT_COST: \"IE KÖLTSÉG\"\n  STR_DAMAGE_UC: \"RONCSOLÁS\"\n  STR_AMMO: \"LŐSZER\"\n  STR_SHOT_TYPE_AUTO: \"Automata\"\n  STR_SHOT_TYPE_SNAP: \"Kapás\"\n  STR_SHOT_TYPE_AIMED: \"Célzott\"\n  STR_CONSTRUCTION_TIME: \"Építkezési idő\"\n  STR_CONSTRUCTION_COST: \"Építkezés költsége\"\n  STR_MAINTENANCE_COST: \"Fenntartás költsége\"\n  STR_LOW: \"Alacsony\"\n  STR_MEDIUM: \"Közepes\"\n  STR_HIGH: \"Magas\"\n  STR_CRAFT_WEAPON: \"Gép fegyver\"\n  STR_CRAFT_AMMUNITION: \"Gép lőszer\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Nehézfegyverzet Platform\"\n  STR_WEAPON: \"Fegyver\"\n  STR_AMMUNITION: \"Lőszer\"\n  STR_EQUIPMENT: \"Felszerelés\"\n  STR_ALIEN_CORPSE: \"Idegen Tetem\"\n  STR_UFO_COMPONENT: \"UFO komponens\"\n  STR_PERSONAL_ARMOR: \"Személyi páncél\"\n  STR_RAW_MATERIALS: \"Nyersanyagok\"\n  STR_HWP_CANNON_SHELLS: \"NFP Ágyú lövedék\"\n  STR_ALIEN: \"Idegen\"\n  STR_SECTOID: \"Szektoid\"\n  STR_SNAKEMAN: \"Kígyóember\"\n  STR_ETHEREAL: \"Éterlény\"\n  STR_MUTON: \"Muton\"\n  STR_FLOATER: \"Lebegő\"\n  STR_CELATID: \"Kelatid\"\n  STR_SILACOID: \"Szilakoid\"\n  STR_CHRYSSALID: \"Krisszalid\"\n  STR_ZOMBIE: \"Zombi\"\n  STR_REAPER: \"Arató\"\n  STR_SECTOPOD: \"Szektopod\"\n  STR_CYBERDISC: \"Kiberkorong\"\n  STR_LIVE_COMMANDER: \"Parancsnok\"\n  STR_LIVE_LEADER: \"Vezető\"\n  STR_LIVE_ENGINEER: \"Mérnök\"\n  STR_LIVE_MEDIC: \"Orvos\"\n  STR_LIVE_NAVIGATOR: \"Navigátor\"\n  STR_LIVE_SOLDIER: \"Katona\"\n  STR_LIVE_TERRORIST: \"Terrorista\"\n  STR_FLOATER_SOLDIER: \"Lebegő Katona\"\n  STR_FLOATER_NAVIGATOR: \"Lebegő Navigátor\"\n  STR_FLOATER_MEDIC: \"Lebegő Orvos\"\n  STR_FLOATER_ENGINEER: \"Lebegő Mérnök\"\n  STR_FLOATER_LEADER: \"Lebegő Vezető\"\n  STR_FLOATER_COMMANDER: \"Lebegő Parancsnok\"\n  STR_SECTOID_SOLDIER: \"Szektoid Katona\"\n  STR_SECTOID_NAVIGATOR: \"Szektoid Navigátor\"\n  STR_SECTOID_MEDIC: \"Szektoid Orvos\"\n  STR_SECTOID_ENGINEER: \"Szektoid Mérnök\"\n  STR_SECTOID_LEADER: \"Szektoid Vezető\"\n  STR_SECTOID_COMMANDER: \"Szektoid Parancsnok\"\n  STR_SNAKEMAN_SOLDIER: \"Kígyóember Katona\"\n  STR_SNAKEMAN_NAVIGATOR: \"Kígyóember Navigátor\"\n  STR_SNAKEMAN_ENGINEER: \"Kígyóember Mérnök\"\n  STR_SNAKEMAN_LEADER: \"Kígyóember Vezető\"\n  STR_SNAKEMAN_COMMANDER: \"Kígyóember Parancsnok\"\n  STR_MUTON_SOLDIER: \"Muton Katona\"\n  STR_MUTON_NAVIGATOR: \"Muton Navigátor\"\n  STR_MUTON_ENGINEER: \"Muton Mérnök\"\n  STR_ETHEREAL_SOLDIER: \"Éterlény Katona\"\n  STR_ETHEREAL_LEADER: \"Éterlény Vezető\"\n  STR_ETHEREAL_COMMANDER: \"Éterlény Parancsnok\"\n  STR_CYBERDISC_TERRORIST: \"Kiberkorong Terrorista\"\n  STR_REAPER_TERRORIST: \"Arató Terrorista\"\n  STR_CHRYSSALID_TERRORIST: \"Krisszalid Terrorista\"\n  STR_CELATID_TERRORIST: \"Kelatid Terrorista\"\n  STR_SILACOID_TERRORIST: \"Szilakoid Terrorista\"\n  STR_SECTOPOD_TERRORIST: \"Szektopod Terrorista\"\n  STR_UFO_POWER_SOURCE: \"UFO Erőforrás\"\n  STR_UFO_NAVIGATION: \"UFO Navigáció\"\n  STR_UFO_CONSTRUCTION: \"UFO Építés\"\n  STR_ALIEN_FOOD: \"Idegen Élelem\"\n  STR_ALIEN_REPRODUCTION: \"Idegen Szaporítókamra\"\n  STR_ALIEN_ENTERTAINMENT: \"Idegen Szórakoztatás\"\n  STR_ALIEN_SURGERY: \"Idegen Sebészet\"\n  STR_EXAMINATION_ROOM: \"Kivizsgáló Szoba\"\n  STR_ALIEN_ALLOYS: \"Idegen Fémek\"\n  STR_ALIEN_HABITAT: \"Idegen Lakás\"\n  STR_POWER_SUIT: \"Erő páncél\"\n  STR_FLYING_SUIT: \"Repülő páncél\"\n  STR_HWP_ROCKETS: \"NFP Rakéta\"\n  STR_HWP_FUSION_BOMB: \"NFP Fúziós Bomba\"\n  STR_LASER_WEAPONS: \"Lézerfegyverek\"\n  STR_NEW_FIGHTER_CRAFT: \"Új harci gép\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Új harci/szállító gép\"\n  STR_ULTIMATE_CRAFT: \"Végső Gép\"\n  STR_LASER_PISTOL: \"Lézerpisztoly\"\n  STR_LASER_RIFLE: \"Lézerpuska\"\n  STR_HEAVY_LASER: \"Nehézlézer\"\n  STR_LASER_CANNON: \"Lézerágyú\"\n  STR_PLASMA_CANNON: \"Plazmaágyú\"\n  STR_FUSION_MISSILE: \"Fúziós Rakéta\"\n  STR_LASER_DEFENSE: \"Lézer Védelem\"\n  STR_PLASMA_DEFENSE: \"Plazma Védelem\"\n  STR_FUSION_DEFENSE: \"Fúziós Védelem\"\n  STR_GRAV_SHIELD: \"Gravipajzs\"\n  STR_MIND_SHIELD: \"Elmepajzs\"\n  STR_PSI_LAB: \"Pszi-Labor\"\n  STR_MOTION_SCANNER: \"Mozgásérzékelő\"\n  STR_MEDI_KIT: \"Elsősegély-Csomag\"\n  STR_TANK_CANNON: \"Tank/Ágyú\"\n  STR_TANK_ROCKET_LAUNCHER: \"Tank/Rakétakilövő\"\n  STR_TANK_LASER_CANNON: \"Tank/Lézerágyú\"\n  STR_HOVERTANK_PLASMA: \"Lebegőtank/Plazma\"\n  STR_HOVERTANK_LAUNCHER: \"Lebegőtank/Kilövő\"\n  STR_STINGRAY_LAUNCHER: \"Stingray kilövő\"\n  STR_AVALANCHE_LAUNCHER: \"Avalanche kilövő\"\n  STR_CANNON: \"Gépágyú\"\n  STR_FUSION_BALL_LAUNCHER: \"Fúziós Gömb Kilövő\"\n  STR_PLASMA_BEAM: \"Plazmaágyú\"\n  STR_STINGRAY_MISSILES: \"Stingray Rakéta\"\n  STR_AVALANCHE_MISSILES: \"Avalanche Rakéta\"\n  STR_CANNON_ROUNDS_X50: \"Gépágyú-lövedék(x50)\"\n  STR_FUSION_BALL: \"Fúziós Gömb\"\n  STR_SOLDIER: \"Katona\"\n  STR_SCIENTIST: \"Tudós\"\n  STR_ENGINEER: \"Mérnök\"\n  STR_NORTH_AMERICA: \"Észak-Amerika\"\n  STR_ARCTIC: \"Arktisz\"\n  STR_ANTARCTICA: \"Antarktisz\"\n  STR_SOUTH_AMERICA: \"Dél-Amerika\"\n  STR_EUROPE: \"Európa\"\n  STR_NORTH_AFRICA: \"Észak-Afrika\"\n  STR_SOUTHERN_AFRICA: \"Dél-Afrika\"\n  STR_CENTRAL_ASIA: \"Közép-Ázsia\"\n  STR_SOUTH_EAST_ASIA: \"Dél-Kelet-Ázsia\"\n  STR_SIBERIA: \"Szibéria\"\n  STR_AUSTRALASIA: \"Ausztrálázsia\"\n  STR_PACIFIC: \"Csendes óceán\"\n  STR_NORTH_ATLANTIC: \"Észak-Atlanti\"\n  STR_SOUTH_ATLANTIC: \"Dél-Atlanti\"\n  STR_INDIAN_OCEAN: \"Indiai óceán\"\n  STR_ALIEN_RESEARCH: \"Idegen Kutatás\"\n  STR_ALIEN_HARVEST: \"Idegen Szüret\"\n  STR_ALIEN_ABDUCTION: \"Idegen Emberrablás\"\n  STR_ALIEN_INFILTRATION: \"Idegen Beszivárgás\"\n  STR_ALIEN_BASE: \"Idegen Bázis\"\n  STR_ALIEN_TERROR: \"Idegen Terror\"\n  STR_ALIEN_RETALIATION: \"Idegen Megtorlás\"\n  STR_ALIEN_SUPPLY: \"Idegen Ellátás\"\n  STR_MAXIMUM_SPEED: \"Maximális sebesség\"\n  STR_HYPER_WAVE_DECODER_UC: \"HIPERHULLÁM DEKÓDER\"\n  STR_SKYRANGER: \"FELHŐJÁRÓ\"\n  STR_LIGHTNING: \"VILLÁM\"\n  STR_AVENGER: \"BOSSZÚÁLLÓ\"\n  STR_INTERCEPTOR: \"ELFOGÓ\"\n  STR_FIRESTORM: \"TŰZVIHAR\"\n  STR_UFO: \"UFO\"\n  STR_STINGRAY: \"STINGRAY\"\n  STR_AVALANCHE: \"AVALANCHE\"\n  STR_CANNON_UC: \"GÉPÁGYÚ\"\n  STR_FUSION_BALL_UC: \"FÚZIÓS GÖMB\"\n  STR_LASER_CANNON_UC: \"LÉZERÁGYÚ\"\n  STR_PLASMA_BEAM_UC: \"PLAZMASUGÁR\"\n  STR_DAMAGE_CAPACITY: \"Sérüléstűrés\"\n  STR_WEAPON_POWER: \"Tűzerő\"\n  STR_WEAPON_RANGE: \"Hatótávolság\"\n  STR_ACCESS_LIFT: \"Központi Lift\"\n  STR_LABORATORY: \"Laboratórium\"\n  STR_WORKSHOP: \"Műhely\"\n  STR_SMALL_RADAR_SYSTEM: \"Kis Radarrendszer\"\n  STR_LARGE_RADAR_SYSTEM: \"Nagy Radarrendszer\"\n  STR_MISSILE_DEFENSES: \"Rakétás Védelem\"\n  STR_GENERAL_STORES: \"Raktár\"\n  STR_ALIEN_CONTAINMENT: \"Idegen Tároló\"\n  STR_LASER_DEFENSES: \"Lézer Védelem\"\n  STR_PLASMA_DEFENSES: \"Plazma Védelem\"\n  STR_FUSION_BALL_DEFENSES: \"Fúziós Gömb Védelem\"\n  STR_PSIONIC_LABORATORY: \"Pszionikus Laboratórium\"\n  STR_HYPER_WAVE_DECODER: \"Hiperhullám-Dekóder\"\n  STR_HANGAR: \"Hangár\"\n  STR_USA: \"EGYESÜLT ÁLL.\"\n  STR_RUSSIA: \"OROSZORSZÁG\"\n  STR_UK: \"EGYESÜLT KIR.\"\n  STR_FRANCE: \"FRANCIAORSZÁG\"\n  STR_GERMANY: \"NÉMETORSZÁG\"\n  STR_ITALY: \"OLASZORSZÁG\"\n  STR_SPAIN: \"SPANYOLORSZÁG\"\n  STR_CHINA: \"KÍNA\"\n  STR_JAPAN: \"JAPÁN\"\n  STR_INDIA: \"INDIA\"\n  STR_BRAZIL: \"BRAZÍLIA\"\n  STR_AUSTRALIA: \"AUSZTRÁLIA\"\n  STR_NIGERIA: \"NIGÉRIA\"\n  STR_SOUTH_AFRICA: \"DÉL-AFRIKAI KÖZ.\"\n  STR_EGYPT: \"EGYIPTOM\"\n  STR_CANADA: \"KANADA\"\n  STR_TANK: \"Tank\"\n  STR_CIVILIAN: \"Civil\"\n  STR_JAN: \"Jan\"\n  STR_FEB: \"Feb\"\n  STR_MAR: \"Már\"\n  STR_APR: \"Ápr\"\n  STR_MAY: \"Máj\"\n  STR_JUN: \"Jún\"\n  STR_JUL: \"Júl\"\n  STR_AUG: \"Aug\"\n  STR_SEP: \"Sze\"\n  STR_OCT: \"Okt\"\n  STR_NOV: \"Nov\"\n  STR_DEC: \"Dec\"\n  STR_INTERNATIONAL_RELATIONS: \"Nemzetközi kapcsolatok\"\n  STR_COUNTRY: \"Ország\"\n  STR_FUNDING: \"Támogatás\"\n  STR_CHANGE: \"Változás\"\n  STR_WEAPON_SYSTEMS: \"FEGYVER-{NEWLINE}RENDSZER\"\n  STR_HWPS: \"NFPk\"\n  STR_DAMAGE_UC_: \"RONGÁLÓDÁS>{ALT}{0}\"\n  STR_ACCESS_LIFT_UFOPEDIA: \"A központi liften keresztül történik a személy- és az anyagforgalom a földalatti bázisba/ból.  Mindig ez az első épület amely az új helyen épül.  A lift területe egy sebezhető pont bármilyen lehetséges ellenséges erő betolakodása esetén.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Minden lakóblokk maximum 50 személy ellátásáról gondoskodik.  A blokk tartalmaz pihenő-, alvó-, étkező- és szórakozóterületeket.\"\n  STR_LABORATORY_UFOPEDIA: \"Legföljebb 50 tudós képes egyszerre dolgozni egy laboratóriumban.  A laborok a legmodernebb felszereléssel vannak ellátva akár anyagvizsgálatról, biokémiáról vagy kozmológiáról van szó.  Különleges hozzáféréssel rendelkezik a világ kutatólaboratóriumainak legjobbjaihoz, sőt katonai laborokhoz is.\"\n  STR_WORKSHOP_UFOPEDIA: \"Egy ilyen műhely minden felszerelést tartalmaz, amely szükséges a kutatólaboratóriumok eredményeinek gyártásához.  Legföljebb 50 mérnök képes egyszerre dolgozni egy műhelyben, bár a készülő tárgy szintén elfoglal némi plusz helyet.\"\n  STR_SMALL_RADAR_SYSTEM_UFOPEDIA: \"A kis észlelőrendszer effektív radartávolsága 555 km, amely egy műholdrendszerhez csatlakozik, lehetővé téve a felszíni keresést. Minden rendszer 10%-os eséllyel észlel egy átlagos méretű objektumot 30 perces időintervallumonként.\"\n  STR_LARGE_RADAR_SYSTEM_UFOPEDIA: \"A nagy észlelőrendszer effektív radartávolsága 820 km, amely egy műholdrendszerhez csatlakozik, lehetővé téve a felszíni keresést. Minden rendszer 20%-os eséllyel észlel egy átlagos méretű objektumot 30 perces időintervallumonként.\"\n  STR_MISSILE_DEFENSES_UFOPEDIA: \"A rakétás védelem gondoskodik némi védelemről, ha egy ellenséges gép próbálna leszállni a bázis közelében.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"Minden felszerelést, fegyverzetet, lőszert, zsákmányolt anyagot, és Nehézfegyverzeti Platformot a raktárakban tárolnak; azokat is, amiket a hangárokban álló gépekhez rendeltél.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"Az élő idegeneknek szükséges egy speciális lakóhelyet biztosítani életbenmaradásuk érdekében. A tárolórendszer egyszerre 10 idegent képes tárolni öntároló egységekben.\"\n  STR_LASER_DEFENSES_UFOPEDIA: \"A lézer védelem védelemről gondoskodik ellenséges gép behatolásával szemben.\"\n  STR_PLASMA_DEFENSES_UFOPEDIA: \"A plazmasugár-védelem erőteljes és hatékony védelemről gondoskodik ellenséges gépekkel szemben.\"\n  STR_FUSION_BALL_DEFENSES_UFOPEDIA: \"A fúziós rakéták biztosítják a leghatékonyabb védelmet idegen támadás esetén.  Ezek a rakéták anti-anyag összeomlást produkálnak, amely egy bizonyos sugáron belül mindent elpusztít.\"\n  STR_GRAV_SHIELD_UFOPEDIA: \"A gravitációs pajzs eltaszítja a leszálláshoz készülő idegen gépet, elég időt nyerve a védelmi rendszereknek az újbóli tüzeléshez. Gyakorlatilag megduplázza bármely védelmi rendszer hatékonyságát a bázison.\"\n  STR_MIND_SHIELD_UFOPEDIA: \"Mivel az idegen gépek az agyhullámok segítségével érzékelik az emberi jelenlétet, a leghatékonyabb ellenintézkedés leárnyékolni a bázisról kilépő agyhullámokat.  Ez az épület drasztikusan csökkenti az idegenek esélyét a bázis észlelését illetően.\"\n  STR_PSIONIC_LABORATORY_UFOPEDIA: \"A pszionikus labor képes felbecsülni a bázison tartózkodó katonák pszionikus erejét és megadja nekik a szükséges gyakorlatot a képességeik hasznosításához.  Minden labor 10 katonát képezhet, mely képzés mindig a hónap elején kezdődik.  A pszionikus képesség a pszi-erősítővel együtt pszionikus támadásra használható harc közben.\"\n  STR_HYPER_WAVE_DECODER_UFOPEDIA: \"Az idegenek közti kommunikáció szupra-dimenzionális hullámokon nyugszik melyek jelátvitele szinte azonnali.  Az épület segítségével lehetőség nyílik az UFO-k üzeneteinek elfogására és dekódolására.  Kideríthető az UFO típusa, az fedélzeten tartózkodó idegen faj és tevékenységük típusa is.\"\n  STR_HANGAR_UFOPEDIA: \"Minden hangár egy gép befogadására alkalmas, egyben tartalmazza a szükséges fenntartó, javító, feltöltő egységeket. Minden bázison állomásozó géphez egy szabad hangárnak kell tartoznia, melyet más gép még akkor sem használhat, ha a szóban forgó hangárhoz tartozó / elsődleges gép éppen küldetést teljesít.\"\n  STR_PISTOL_UFOPEDIA: \"A szabványos X-Com pisztoly egy nagy erejű félautomata pisztoly, amelyhez 12 töltényes tár tartozik.\"\n  STR_RIFLE_UFOPEDIA: \"Nagypontosságú mesterlövész-puska lézer irányzékkal.  6.7mm-es lőszeréből 20 db-ot tartalmaz egy tár.\"\n  STR_HEAVY_CANNON_UFOPEDIA: \"A nehézlöveg pusztító, de nehézkes fegyver.  Sokoldalú, hiszen háromféle lőszerrel használható: páncéltörő, gyújtóbomba és detonációs.\"\n  STR_AUTO_CANNON_UFOPEDIA: \"Az automata löveg kombinálja a nehézlöveg tűzerejét és sokoldalúságát a gyorsabb tüzeléssel.\"\n  STR_ROCKET_LAUNCHER_UFOPEDIA: \"A lézerirányzékú rakétakilövő háromféle rakétát képes kilőni.\"\n  STR_LASER_PISTOL_UFOPEDIA: \"A lézerpisztoly hatásos kivitelezése az új technologiának.  A gyorsabb és sokkal pontosabb pisztoly kényelmével rendelkezik.\"\n  STR_LASER_RIFLE_UFOPEDIA: \"A lézerpuska erőteljesebb és pontosabb verziója a korábbi pisztoly-terveknek.\"\n  STR_HEAVY_LASER_UFOPEDIA: \"A nehézlézer nehézkes, de rendkívül hatásos.\"\n  STR_GRENADE_UFOPEDIA: \"Ez a szabványgránát pontos, kifinomult időzítővel rendelkezik.\"\n  STR_SMOKE_GRENADE_UFOPEDIA: \"A füstgránát takarásról gondoskodik nyílt harci helyzetekben.  Odafigyeléssel használd, mert az ellenség is hasznot húzhat ebből.\"\n  STR_PROXIMITY_GRENADE_UFOPEDIA: \"A szomszédgránát ugyanúgy használatos, mint egy normális gránát, de ez landolása után közeli mozgásra aktiválódik.  Nagy ügyesség és odafigyelés szükséges használatához.\"\n  STR_HIGH_EXPLOSIVE_UFOPEDIA: \"Ez a robbanószer kizárólag rombolási célokat szolgál.  Az embereid tartsd távol a felrobbanó területtől.\"\n  STR_MOTION_SCANNER_UFOPEDIA: \"Ez a kifinomult eszköz érzékelők tucatját tartalmazza, melyek jelzései alapján egy algoritmus képes kiszűrni és azonosítani a mozgó ellenséges egységeket. Mindazonáltal igényel némi gyakorlatot a hatékony használata. Kattints a mozgásérzékelő ikonra a taktikai kijelzőn. Válaszd ki a 'Mozgásérzékelő'-t a menüből.  A kijelző középre egy nyilat tesz, mely arra mutat, amerre a katona néz (Észak van fent). A villogó foltok az előzőleg mozgó egységeket jelzik. Nagyobb vagy gyorsabb egységek nagyobb foltokat eredményeznek. A mozdulatlan egységek nem kerülnek kijelzésre.\"\n  STR_MEDI_KIT_UFOPEDIA: \"Az elsősegély-csomag tartalmaz kötszereket, fájdalom-csillapítókat és stimulánsokat. Használatához a páciens mellett, felé fordulva kell állni. Ha a katona bénult, fölé kell állni. Kattints az elsősegély-csomag ikonra és válaszd ki az 'Elsősegély-csomag'-ot a menüből.{NEWLINE}GYÓGYÍTÁS> A vörös testrészek végzetes sebeket jeleznek. Kattints a sebesült tesztrészre. Kattints a 'Gyógyít' gombra. Egy végzetes seb meg lesz gyógyítva, és az egészség valamennyire helyreáll.{NEWLINE}STIMULÁNS> Visszaállítja az energiáját és újraéleszti az öntudatlan (lebénított) katonákat. Az újraélesztéshez a bénult katona fölé kell állni.{NEWLINE}FÁJDALOMCSILLAPÍTÓ> Visszaállítja a sebesült katona morálját annyival, amennyivel a sebesüléssel csökkent neki.\"\n  STR_PSI_AMP_UFOPEDIA: \"A Pszi-Erősítőt csak pszionikus ügyességgel rendelkező katonák használhatják. Csata közben kattints a Pszi-Erősítőre, válaszd ki a támadás típusát, és jelöld ki a kurzorral a célpontot. Kétféle pszionikus támadás lehetséges: {NEWLINE}PÁNIKKELTÉS> Ha a támadás sikeres, akkor csökkenti a célpont morálját, amitől az pánikba eshet. {NEWLINE}ELMEKONTROLL> Ha sikerrel jár, azonnal megszerzed az ellenséges egység irányítását, mintha a sajátod lenne. Ezt a fajta támadást nehezebb véghezvinni.\"\n  STR_STUN_ROD_UFOPEDIA: \"Ez az eszköz közelharcban használatos. Elektromos sokkal képes ölés nélkül megbénítani egy élő szervezetet.\"\n  STR_MIND_PROBE_UFOPEDIA: \"Az elmeszonda egy idegen kommunikációs eszköz, amellyel az információ közvetlenül az agyhullámokból szerezhető meg. Az X-Com ügynökök ezt az eszközt egy idegen jellemzőinek megjelenítésére használhatják harc közben. Kattints az elmeszondára, majd válaszd az 'Elmeteszt' lehetőséget. Ezután válaszd ki az idegent a kurzorral.\"\n  STR_PLASMA_PISTOL_UFOPEDIA: \"A plazmapisztolyok halálos idegen fegyverek, melyek az anti-gravitációs mező azonnali részecskegyorsítására épülnek.\"\n  STR_PLASMA_RIFLE_UFOPEDIA: \"Ez az erőteljes pusztító eszköz az anti-gravitációs mező azonnali részecskegyorsítására épül.\"\n  STR_HEAVY_PLASMA_UFOPEDIA: \"Ez az erőteljes pusztító eszköz az anti-gravitációs mező azonnali részecskegyorsítására épül.\"\n  STR_BLASTER_LAUNCHER_UFOPEDIA: \"Ez egy írányítható idegen rakétakilövő, mely hatékony 'pusztító bombá'-t lő ki. Amikor lőni akarsz a fegyverrel, összeállíthatsz egy útvonalat, amelyet a bomba követ.  Amikor már elég pontot kijelöltél, kattints a speciális kilövés ikonra.\"\n  STR_SMALL_LAUNCHER_UFOPEDIA: \"Ez egy kis kilövő, mely bénító bombákat lő ki. Nagyon hasznos élő idegenek elfogására.\"\n  STR_ALIEN_GRENADE_UFOPEDIA: \"Ez az eszköz ugyanúgy működik, mint földi megfelelője - kivéve, hogy sokkal erősebb.\"\n  STR_SMALL_SCOUT: \"Kis Felderítő\"\n  STR_MEDIUM_SCOUT: \"Közepes Felderítő\"\n  STR_LARGE_SCOUT: \"Nagy Felderítő\"\n  STR_HARVESTER: \"Szüretelő\"\n  STR_ABDUCTOR: \"Elrabló\"\n  STR_TERROR_SHIP: \"Terror hajó\"\n  STR_BATTLESHIP: \"Csatahajó\"\n  STR_SUPPLY_SHIP: \"Ellátó hajó\"\n  STR_RATING: \"ÉRTÉKELÉS> {0}\"\n  STR_RATING_TERRIBLE: \"BORZALMAS!\"\n  STR_RATING_POOR: \"GYENGE!\"\n  STR_RATING_OK: \"OKÉ\"\n  STR_RATING_GOOD: \"JÓ!\"\n  STR_RATING_EXCELLENT: \"KIVÁLÓ!\"\n  STR_SCORE: \"PONTSZÁM\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"X-COM PROGRAM - HAVI JELENTÉS\"\n  STR_MONTH: \"Hónap> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"A támogató nemzetek tanácsa általánosan elégedett az eredményeddel.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"A támogató nemzetek tanácsa rendkívül elégedett a kitűnő eredményeddel.  Csak így tovább.\"\n  STR_COUNCIL_IS_DISSATISFIED: \"A támogató nemzetek tanácsa elégedetlen a teljesítményeddel.  Hatékonyabban kell az idegen veszély ellen fellépned, vagy a program leállítását kockáztatod.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"Nem sikerült az invázió ellen hatékonyan fellépned, ezért a támogató nemzetek tanácsa sajnos a program leállítása mellett döntött.  Minden nemzet megpróbálja a maga eszközeivel megoldani a problémát.  Csak remélni tudjuk, hogy alkalmazkodni tudunk valahogy ezekhez a nyilvánvalóan ellenséges erőkhöz és a lakosság valahogy kiegyezik az idegen látogatókkal.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} különösen elégedett az idegenek elleni helyi eredményeiddel, ezért növeli a támogatását.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} különösen elégedett a területét érő idegen portyázások elleni fellépéseddel, ezért a támogatásuk emeléséről döntöttek.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} és {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} elégedetlen a területét érő idegen portyázások elleni fellépéseddel, ezért a támogatása csökkentéséről döntött.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} elégedetlen a területét érő idegen portyázások elleni fellépéseddel, ezért a támogatásuk csökkentéséről döntöttek.\"\n  STR_KNOTS: \"{0} csomó\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} titkos paktumot írt alá ismeretlen idegen erőkkel, és kivonult a programból.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} titkos paktumot írt alá ismeretlen idegen erőkkel, és kivonult a programból.\"\n  STR_MONTHLY_RATING: \"Havi értékelés> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Támogatás változása> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"A támogató nemzetek tanácsa elégedetlen a pénzügyi helyzeteddel. Az adósságodat 1 millió dollár alá kell csökkentened, különben a program véget ér.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"HIPERHULLÁM ADÁSOK DEKÓDOLVA\"\n  STR_CRAFT_TYPE: \"GÉP TÍPUSA\"\n  STR_RACE: \"FAJ\"\n  STR_MISSION: \"KÜLDETÉS\"\n  STR_ZONE: \"ZÓNA\"\n  STR_ALLOCATE_RESEARCH: \"Kutatás kijelölése\"\n  STR_ALLOCATE_MANUFACTURE: \"Gyártás kijelölése\"\n  STR_NEW_YORK: \"New York\"\n  STR_WASHINGTON: \"Washington\"\n  STR_LOS_ANGELES: \"Los Angeles\"\n  STR_MONTREAL: \"Montreal\"\n  STR_HAVANA: \"Havanna\"\n  STR_MEXICO_CITY: \"Mexikóváros\"\n  STR_CHICAGO: \"Chicago\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_DALLAS: \"Dallas\"\n  STR_BRASILIA: \"Brazíliaváros\"\n  STR_BOGOTA: \"Bogota\"\n  STR_BUENOS_AIRES: \"Buenos Aires\"\n  STR_SANTIAGO: \"Santiago\"\n  STR_RIO_DE_JANEIRO: \"Rio De Janeiro\"\n  STR_LIMA: \"Lima\"\n  STR_CARACAS: \"Caracas\"\n  STR_LONDON: \"London\"\n  STR_PARIS: \"Párizs\"\n  STR_BERLIN: \"Berlin\"\n  STR_MOSCOW: \"Moszkva\"\n  STR_ROME: \"Róma\"\n  STR_MADRID: \"Madrid\"\n  STR_BUDAPEST: \"Budapest\"\n  STR_LAGOS: \"Lagos\"\n  STR_CAIRO: \"Kairó\"\n  STR_CASABLANCA: \"Casablanca\"\n  STR_PRETORIA: \"Pretoria\"\n  STR_NAIROBI: \"Nairobi\"\n  STR_CAPE_TOWN: \"Fokváros\"\n  STR_KINSHASA: \"Kinshasa\"\n  STR_ANKARA: \"Ankara\"\n  STR_DELHI: \"Delhi\"\n  STR_KARACHI: \"Karacsi\"\n  STR_BAGHDAD: \"Bagdad\"\n  STR_TEHRAN: \"Teherán\"\n  STR_BOMBAY: \"Bombay\"\n  STR_CALCUTTA: \"Kalkutta\"\n  STR_TOKYO: \"Tokió\"\n  STR_BEIJING: \"Peking\"\n  STR_BANGKOK: \"Bangkok\"\n  STR_MANILA: \"Manila\"\n  STR_SEOUL: \"Szöul\"\n  STR_SINGAPORE: \"Szingapúr\"\n  STR_JAKARTA: \"Dzsakarta\"\n  STR_SHANGHAI: \"Sanghaj\"\n  STR_HONG_KONG: \"Hong Kong\"\n  STR_NOVOSIBIRSK: \"Novoszibirszk\"\n  STR_CANBERRA: \"Canberra\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_MELBOURNE: \"Melbourne\"\n  STR_PERTH: \"Perth\"\n  STR_PSI_TRAINING: \"Pszi Tréning\"\n  STR_PSIONIC_TRAINING: \"PSZIONIKUS KÉPZÉS\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Szabad Pszi-labor kapacitás> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"Pszionikus{NEWLINE}Erősség\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"Pszionikus{NEWLINE}Ügyesség/javulás\"\n  STR_PSI_AMP: \"Pszi-Erősítő\"\n  STR_IN_TRAINING: \"{NEWLINE}Képzésben\"\n  STR_TARGETTED_BY: \"BECÉLOZTA:\"\n  STR_WEAPONS_CREW_HWPS: \"FEGYVEREK/{NEWLINE}LEGÉNYSÉG/NFPk\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"kevés az üzemanyag,{NEWLINE}visszatér a bázisra\"\n  STR_SOLDIER_LIST: \"Katonák Listája\"\n  STR_RANK_: \"RENDFOKOZAT> {ALT}{0}\"\n  STR_MISSIONS: \"KÜLDETÉSEK> {ALT}{0}\"\n  STR_KILLS: \"ÁLDOZATOK> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"SEBGYÓGYULÁS> {ALT}{0}\"\n  STR_TIME_UNITS: \"IDŐ EGYSÉG\"\n  STR_STAMINA: \"ÁLLÓKÉPESSÉG\"\n  STR_HEALTH: \"EGÉSZSÉG\"\n  STR_BRAVERY: \"BÁTORSÁG\"\n  STR_REACTIONS: \"REAKCIÓK\"\n  STR_FIRING_ACCURACY: \"TÜZELÉSI PONTOSSÁG\"\n  STR_THROWING_ACCURACY: \"DOBÁSI PONTOSSÁG\"\n  STR_STRENGTH: \"ERŐ\"\n  STR_PSIONIC_STRENGTH: \"PSZIONIKUS ERŐ\"\n  STR_PSIONIC_SKILL: \"PSZIONIKUS ÜGYESSÉG\"\n  STR_NEW_RANK: \"ÚJ RENDFOKOZAT\"\n  STR_PROMOTIONS: \"Előléptetések\"\n  STR_SOLDIERS_UC: \"KATONÁK\"\n  STR_TANK_CANNON_UFOPEDIA: \"Az Automatizált Nehézfegyverzet Platformok - avagy Lövegtalpazatok - egy-egy X-Com csapat kiegészítésére szolgálnak. A nagy tűzerő és a strapabíró páncélzat teszi értékessé ezeket az egységeket a nyílt tűzharcban. Mindig ellenőrizd, hogy a raktárban legyen elég ágyúlövedéked a tankok újratöltéséhez. Felfegyverzésük automatikusan megtörténik, amikor egy csapat mellé beosztod őket.\"\n  STR_TANK_ROCKET_LAUNCHER_UFOPEDIA: \"Ez az automata NFP hatékony rakétákkal van felszerelve.  Ez pusztító bármilyen idegen ellenségre nézve.  Légy biztos benne, hogy a raktáraid jól el vannak látva NFP rakétákkal.\"\n  STR_TANK_LASER_CANNON_UFOPEDIA: \"A lézerfegyverek hatékonyan kiegészítik az NFP-t.  Előnye a nagy tűzerő és az a tény, hogy nem igényel lőszert.\"\n  STR_HOVERTANK_PLASMA_UFOPEDIA: \"Az idegen technológia adott egy lökést az NFP-nek.  A levegőben való manőverezhetőség és a plazmasugarak ereje egy halálos kombináció.\"\n  STR_HOVERTANK_LAUNCHER_UFOPEDIA: \"Ez a lebegőtank fúziós bomba kilövővel rendelkezik, mely tömérdek pusztításra képes.  Nagy odafigyeléssel használd.  Gyártanod kell fúziós bombát, hogy ez az NFP mindig teljesen el legyen látva.  A fúziós bomba egy intelligens irányítható fegyver.  A kilövéshez ki kell választanod az 'útpontokat' a kurzorral majd kattints a kilövés ikonra, hogy kilődd a fúziós bombát.\"\n  STR_HEAVY_PLASMA_CLIP_UFOPEDIA: \"Ez a kis eszköz a nehézplazma lőszere.  Kis mennyiségű Eleriumot tartalmaz.\"\n  STR_PLASMA_RIFLE_CLIP_UFOPEDIA: \"Ez a kis eszköz a plazmapuska lőszere - egy középszintű idegen fegyver.  Kis mennyiségű Eleriumot tartalmaz.\"\n  STR_PLASMA_PISTOL_CLIP_UFOPEDIA: \"A kis plazmapisztoly lőszere.  Eleriumot tartalmaz - ez minden idegen erő forrása.\"\n  STR_STUN_BOMB_UFOPEDIA: \"A bénító bomba élő emberi egyedek elfogására használatos, de használható a legtöbb idegen faj egyede ellen is.  A kis kilövő juttatja célba.\"\n  STR_ALIEN_RESEARCH_UFOPEDIA: \"Az idegen kutató küldetések alapszintű adatok gyűjtésére irányulnak a Földről és annak lakóiról. Javarészt kis gépezetek használnak, amelyekkel alkalmanként elhagyatott területeken landolnak. Ez a típusú idegen tevékenység a legjelentéktelenebb fenyegetés az X-Com-ra nézve, és amelyek a legkevesebb aggodalmat váltják ki a közvélemény és a kormányzatok részéről.\"\n  STR_ALIEN_HARVEST_UFOPEDIA: \"Az idegenek sokrétűen hasznosítják a Föld faunáját.  Állatokat rabolnak el titokban, majd különböző szerveik eltávolítása után kerülnek elő ismét.  Marhacsonkításokat ismétlődően jelentenek az UFO észlelések kíséretében.  Ez a típusú idegen tevékenység a kormányzatok és a közvélemény nagy érdeklődését és aggodalmát váltja ki.  Ez a típusú tevékenység főleg farmvidékeken fordul elő.  Az 'idegen szüret' mögötti elmélet szerint az idegenek ültették el az életet a Földön eredetileg, és most visszatérnek learatni munkájuk gyümölcsét.\"\n  STR_ALIEN_ABDUCTION_UFOPEDIA: \"Ez a legalattomosabb formája az idegenek tevékenységének.  Az elrablásokat széles körben jelentik, annak ellenére, hogy az idegenek megpróbálják kitörölni az emlékeket az áldozatok emlékezetéből.  Az elraboltak megalázó fizikai kísérletekről, köztük pl. idegen magzatok beültetéséről és egyéb bizarr genetikai kísérletekről szólnak.  A cél ezek mögött kapcsolatban lehet az idegenek saját génállományának genetikai mutációjával és manipulációjával.  Ez a tevékenység nagy port kavar, és általában népes területeken, városokban fordul elő.\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"Földi kormányzatokba beszivároghatnak idegen ügynökök emberi megjelenéssel. Ez hivatalos kapcsolatot eredményezhet az idegenek és a kormányzatok között a legmagasabb szinten. A tevékenységük tetőpontján ez intenzív UFO aktivitással jár a nagyobb városok vonzáskörzetében. Az idegenek egyezményt próbálnak aláíratni egy kormányzattal, felajánlva a tudásukat és a felsőbbrendű technológiájukat. Viszonzásképp a kormányzat engedélyezi az idegeneknek tevékenységük akadálytalan folytatását. Az idegen küldetések jelentik a lehető legnagyobb fenyegetést az X-Com számára. Ha egy kormányzat elfogadja az egyezményt, minden támogatást megvon a tervezettől.\"\n  STR_ALIEN_BASE_UFOPEDIA: \"Az idegenek titkos földalatti bázisokat építenek távol eső helyeken. Némi kezdeti felderítés után intenzív UFO tevékenység kezdődik, ahogy a bázis épül. Ezek a bázisok szolgálnak az elraboltakon végzett kísérletek színhelyéül, és ellátást biztosítanak a tevékenység további folytatásához a régióban. Az idegen bázisok jelenléte nagy mennyiségű jelentett idegen tevékenységet okoz UFO jelenlét nélkül. Egy bázis megtalálásához egy X-Com gépnek néhány órát kell járőröznie a terület fölött, hogy legyen némi esélye megtalálnia azt.\"\n  STR_ALIEN_TERROR_UFOPEDIA: \"Amikor az idegenek terrorizálnak egy várost, hatalmas erővel rendelkező speciális egységeket küldenek oda. A civileket közvetlen fenyegetés éri, és a kormányzat egész területek kiürítésére kényszerül. A tevékenység fő célja, hogy elegendő nyilvános hisztériát keltsenek ahhoz, hogy a kormányzat csökkentse vagy megvonja támogatását az X-Com programtól.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"Ha az X-Com Elfogók különösen sikeresek az UFO-k lelövésében, akkor az idegenek beindíthatnak néhány megtorló akciót. Ez egy közvetlen támadást eredményezhet egy X-Com bázis ellen. Azonban, az idegeneknek először meg kell találniuk a kérdéses bázist ahhoz, hogy megtámadják. Feltéve, hogy az UFO-kat kellően távol tartják, a bázis elleni támadás veszélye igen elenyésző kell hogy legyen.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"Ha egy idegen bázis megépült, akkor azt rendszeresen ellátja egy speciális ellátó hajó.  Ha egy ilyen hajót észlelünk leszálláskor, akkor biztos, hogy a közelben egy idegen bázis van.\"\n  STR_SMALL_SCOUT_UFOPEDIA: \"Ez a kis gép elsődlegesen felderítésre és kutatásra szolgál.  Általában nagyobb hajókat előz meg egy idegen küldetés kezdetén.\"\n  STR_MEDIUM_SCOUT_UFOPEDIA: \"Egy közepes méretű felderítő, mely alig jelent veszélyt a földi erőkre.  Általában nagyobb hajók előtt jelenik meg küldetések idején.\"\n  STR_LARGE_SCOUT_UFOPEDIA: \"A legnagyobb idegen felderítő gép általános célú hajó, melyet mindenféle típusú idegen küldetésben használnak.\"\n  STR_HARVESTER_UFOPEDIA: \"A szüretelő csapóajtóval rendelkezik az alján, és fel van szerelve lifttel marhák és egyéb állatok beemeléséhez.  Lézervágók szolgálnak a kívánt anyagok kinyerésére, majd a tetemet a földre szórják.  Tartalmaz olyan tárolókat is, amelyekben testrészek tárolhatók.\"\n  STR_ABDUCTOR_UFOPEDIA: \"Ez a gép egy kivizsgáló szobával van felszerelve, melynek segítségével borzalmas kísérleteket hajthatnak végre embereken.  Az áldozatot telepatikus erővel bénítják meg, de öntudatánál marad, míg a műtőasztalon fekszik.\"\n  STR_TERROR_SHIP_UFOPEDIA: \"A terror hajó egy részlege nagyobb idegen teremtmények illetve fegyverek tárolására szolgál.  Ezt a hajót használják, hogy ezeket a terroristákat lakott területekre szállítsák.\"\n  STR_BATTLESHIP_UFOPEDIA: \"A csatahajó a legnagyobb és legerőteljesebb idegen gép.  Normál esetben ez az elsődleges idegen küldetési gép, erőteljes fegyverekkel és nagyszámú legénységgel felszerelve.\"\n  STR_SUPPLY_SHIP_UFOPEDIA: \"Az ellátó hajó az épülő vagy a kész idegen bázis ellátására szolgál.  Idegen élelem-tárolókat és szaporítókamrákat tartalmaz.\"\n  STR_DISMANTLE: \"Szétszedés\"\n  STR_FACILITY_IN_USE: \"ÉPÜLET HASZNÁLATBAN\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"AZ ÉPÜLET NEM SZEDHETŐ SZÉT!{SMALLLINE}Minden épületnek összeköttetésben kell lenni a központi lifttel.\"\n  STR_TRANSFER_ITEMS_TO: \"Tárgyak átszállítása ide: {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"NINCS IDEGEN TÁROLÓ A CÉLBÁZISON!{SMALLLINE}Az élő idegeneknek szüksége van egy idegen tárolóra a túléléshez.\"\n  STR_AMOUNT_AT_DESTINATION: \"CÉLBELI{NEWLINE}MENNYISÉG\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"Az idegen meghal, mivel nincs idegen tároló épület\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"NINCS SZABAD LAKÓHELY!{SMALLLINE}A célbázis nem rendelkezik elég lakóhellyel a lakónegyedeiben, hogy képes legyen befogadni a géphez rendelt legénységet.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"NINCS ELÉG RAKTÁR-HELY!{SMALLLINE}A célbázis nem rendelkezik elegendő raktár-hellyel a gép fedélzetén lévő felszerelések számára.\"\n  STR_ITEMS_ARRIVING: \"Érkező tételek\"\n  STR_DESTINATION_UC: \"CÉLBÁZIS\"\n  STR_PISTOL: \"Pisztoly\"\n  STR_PISTOL_CLIP: \"Pisztoly Tár\"\n  STR_RIFLE: \"Puska\"\n  STR_RIFLE_CLIP: \"Puska Tár\"\n  STR_HEAVY_CANNON: \"Nehéz Löveg\"\n  STR_HC_AP_AMMO: \"NL-PT lőszer\"\n  STR_HC_HE_AMMO: \"NL-D lőszer\"\n  STR_HC_I_AMMO: \"NL-GYB lőszer\"\n  STR_AUTO_CANNON: \"Automata Löveg\"\n  STR_AC_AP_AMMO: \"AL-PT lőszer\"\n  STR_AC_HE_AMMO: \"AL-D lőszer\"\n  STR_AC_I_AMMO: \"AL-GYB lőszer\"\n  STR_ROCKET_LAUNCHER: \"Rakétakilövő\"\n  STR_SMALL_ROCKET: \"Kis Rakéta\"\n  STR_LARGE_ROCKET: \"Nagy Rakéta\"\n  STR_INCENDIARY_ROCKET: \"Gyújtóbomba Rakéta\"\n  STR_GRENADE: \"Gránát\"\n  STR_SMOKE_GRENADE: \"Füstgránát\"\n  STR_PROXIMITY_GRENADE: \"Szomszédgránát\"\n  STR_HIGH_EXPLOSIVE: \"Extraerős Robbanószer\"\n  STR_STUN_ROD: \"Bénítópálca\"\n  STR_HEAVY_PLASMA: \"Nehézplazma\"\n  STR_HEAVY_PLASMA_CLIP: \"Nehézplazma Tár\"\n  STR_PLASMA_RIFLE: \"Plazmapuska\"\n  STR_PLASMA_RIFLE_CLIP: \"Plazmapuska Tár\"\n  STR_PLASMA_PISTOL: \"Plazmapisztoly\"\n  STR_PLASMA_PISTOL_CLIP: \"Plazmapisztoly Tár\"\n  STR_BLASTER_LAUNCHER: \"Pusztító Bomba Kilövő\"\n  STR_BLASTER_BOMB: \"Pusztító Bomba\"\n  STR_SMALL_LAUNCHER: \"Kis Kilövő\"\n  STR_STUN_BOMB: \"Bénító Bomba\"\n  STR_ALIEN_GRENADE: \"Idegen Gránát\"\n  STR_ELERIUM_115: \"Elerium-115\"\n  STR_MIND_PROBE: \"Elmeszonda\"\n  STR_SECTOID_CORPSE: \"Szektoid Tetem\"\n  STR_SNAKEMAN_CORPSE: \"Kígyóember Tetem\"\n  STR_ETHEREAL_CORPSE: \"Éterlény Tetem\"\n  STR_MUTON_CORPSE: \"Muton Tetem\"\n  STR_FLOATER_CORPSE: \"Lebegő Tetem\"\n  STR_CELATID_CORPSE: \"Kelatid Tetem\"\n  STR_SILACOID_CORPSE: \"Szilakoid Tetem\"\n  STR_CHRYSSALID_CORPSE: \"Krisszalid Tetem\"\n  STR_REAPER_CORPSE: \"Arató Tetem\"\n  STR_SECTOPOD_CORPSE: \"Szektopod Tetem\"\n  STR_CYBERDISC_CORPSE: \"Kiberkorong Tetem\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"Nincs elég lőszer az NFP felfegyverzéséhez{SMALLLINE}Minden NFP számára {0} {1} szükséges.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Nincs elég felszerelés az osztag újrafelfegyverzéséhez\"\n  STR_MARS_CYDONIA_LANDING: \"Mars: Cydonia leszálló\"\n  STR_MARS_CYDONIA_LANDING_BRIEFING: \"A Bosszúállód leszállt Cydonia területén a Marson.  Információink szerint az egyik piramis rejti a zöld központi liftet, amely egy földalatti komplexumba vezet.  Miután minden egységedet a lift területére vezényelted, kattints a 'küldetés megszakítása' ikonra, így átjuthatsz a következő fázisba.\"\n  STR_MARS_THE_FINAL_ASSAULT: \"Mars: A végső támadás\"\n  STR_MARS_THE_FINAL_ASSAULT_BRIEFING: \"A piramislift a hadviselt katonáidat mélyen a bolygó felszíne alá szállítja.  Egy alagutakkal és kamrákkal teli hatalmas komplexum szívébe érkeznek meg.  Az idegen agy valahol a labirintus mélyén rejtőzik.  Meg kell semmisítened, ha meg akarod menteni a Földet a rabszolgasorstól.{NEWLINE}{NEWLINE}Sok szerencsét!\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Ki kell kutatnod:{NEWLINE}{0}{NEWLINE}hogy ilyet gyárthass:{NEWLINE}{1}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"Az idegenek lerombolták a védtelen {0} bázist\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"X-Com ügynökök bemértek egy idegen bázist {0} területén.\"\n  STR_STANDOFF: \"KÖVETÉS\"\n  STR_CAUTIOUS_ATTACK: \"ÓVATOS TÁMADÁS\"\n  STR_STANDARD_ATTACK: \"NORMÁL TÁMADÁS\"\n  STR_AGGRESSIVE_ATTACK: \"AGRESSZÍV TÁMADÁS\"\n  STR_DISENGAGING: \"ELSZAKADÁS\"\n  STR_UFO_HIT: \"UFO ELTALÁLVA!\"\n  STR_UFO_CRASH_LANDS: \"AZ UFO LEZUHAN!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Minimizálás követési távolsággal\"\n  STR_UFO_RETURN_FIRE: \"UFO VISSZALŐ!\"\n  STR_INTERCEPTOR_DAMAGED: \">>> ELFOGÓ MEGSÉRÜLT <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> ELFOGÓ MEGSEMMISÜLT <<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"UFO LEHAGYJA AZ ELFOGÓT!\"\n  STR_ALIENS_TERRORISE: \"IDEGENEK TERRORIZÁLJÁK:\"\n  STR_LONG_RANGE_DETECTION: \"Hosszú távú észlelés\"\n  STR_STORES_UC: \"RAKTÁRAK\"\n  STR_DIFFICULTY_LEVEL: \"Nehézségi szint\"\n  STR_INTERCEPT: \"ELFOGÁS\"\n  STR_BASES: \"BÁZISOK\"\n  STR_GRAPHS: \"GRAFIKONOK\"\n  STR_UFOPAEDIA_UC: \"UFOPÉDIA\"\n  STR_OPTIONS_UC: \"OPCIÓK\"\n  STR_FUNDING_UC: \"FINANSZÍROZÁS\"\n  STR_5_SECONDS: \"5 Mp\"\n  STR_1_MINUTE: \"1 Perc\"\n  STR_5_MINUTES: \"5 Perc\"\n  STR_30_MINUTES: \"30 Perc\"\n  STR_1_HOUR: \"1 Óra\"\n  STR_1_DAY: \"1 Nap\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"X-Com Teljesítményjegyzék\"\n  STR_ENTER_NAME: \"Írd be a neved\"\n  STR_PERFORMANCE_RATING: \"Teljesítmény értékelés\"\n  STR_VICTORY_DATE: \"Győzelem dátuma\"\n  STR_ELECTRO_FLARE: \"Elektro-Fáklya\"\n  STR_ELECTRO_FLARE_UFOPEDIA: \"Ez a kis eszköz éles fényt produkál eldobása után.  Az éjszakai bevetéseken megvilágítja az ellenséges egységeket maga körül.\"\n  STR_MONTHLY_COSTS: \"Havi költségek\"\n  STR_CRAFT_RENTAL: \"Gépbérlet\"\n  STR_SALARIES: \"Fizetések\"\n  STR_BASE_MAINTENANCE: \"Bázis fenntartása\"\n  STR_COST_PER_UNIT: \"Egységár\"\n  STR_QUANTITY: \"Mennyiség\"\n  STR_TOTAL: \"Összesen\"\n  STR_IN_PSIONIC_TRAINING: \"Pszionikus képzésben\"\n  STR_BLASTER_BOMB_UFOPEDIA: \"Ez az eszköz nagyerejű robbanást produkál, és egy intelligens írányítórendszere van.  A pusztító bomba kilövővel lehet kilőni.\"\n  STR_FRONT_ARMOR: \"Páncél Elől\"\n  STR_LEFT_ARMOR: \"Páncél Baloldalt\"\n  STR_RIGHT_ARMOR: \"Páncél Jobboldalt\"\n  STR_REAR_ARMOR: \"Páncél Hátul\"\n  STR_UNDER_ARMOR: \"Páncél Alul\"\n  STR_ROUNDS: \"Lövedékek\"\n  STR_UNIT: \"EGYSÉG> {0}\"\n  STR_ENERGY: \"ENERGIA\"\n  STR_MORALE: \"MORÁL\"\n  STR_ARMOR_: \"PÁNCÉL> {0}\"\n  STR_FRONT_ARMOR_UC: \"PÁNCÉL ELŐL\"\n  STR_LEFT_ARMOR_UC: \"PÁNCÉL BALOLDALT\"\n  STR_RIGHT_ARMOR_UC: \"PÁNCÉL JOBBOLDALT\"\n  STR_REAR_ARMOR_UC: \"PÁNCÉL HÁTUL\"\n  STR_SKILLS: \"ÜGYESSÉG> {0}\"\n  STR_LEVEL: \"SZINT> {0}\"\n  STR_HEAD: \"FEJ\"\n  STR_TORSO: \"TÖRZS\"\n  STR_RIGHT_ARM: \"JOBB KAR\"\n  STR_LEFT_ARM: \"BAL KAR\"\n  STR_RIGHT_LEG: \"JOBB LÁB\"\n  STR_LEFT_LEG: \"BAL LÁB\"\n  STR_PAIN_KILLER: \"FÁJ.CS.PÍTÓ\"\n  STR_STIMULANT: \"STIMULÁNS\"\n  STR_HEAL: \"GYÓGYÍTÁS\"\n  STR_TIME_UNITS_SHORT: \"IE>{ALT}{0}\"\n  STR_WEIGHT: \"Súly>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"Reakc>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"P.Ügy>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"P.Erő>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Idegen Szerkezet\"\n  STR_AMMO_ROUNDS_LEFT: \"LŐSZER:{NEWLINE}MARADÉK{NEWLINE}LÖVEDÉK={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"F.cs.>{ALT}{0}{ALT}{NEWLINE}Stim.>{ALT}{1}{ALT}{NEWLINE}Gyógy.>{ALT}{2}\"\n  STR_THROW: \"Dobás\"\n  STR_AUTO_SHOT: \"Automata Lövés\"\n  STR_SNAP_SHOT: \"Kapás Lövés\"\n  STR_AIMED_SHOT: \"Célzott Lövés\"\n  STR_STUN: \"Bénít\"\n  STR_PRIME_GRENADE: \"Gránát időzítése\"\n  STR_USE_SCANNER: \"Mozgásérzékelő\"\n  STR_USE_MEDI_KIT: \"Elsősegély-csomag\"\n  STR_LAUNCH_MISSILE: \"Rakéta Kilövése\"\n  STR_ACCURACY_SHORT: \"Pts>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Nincs elég Idő Egység!\"\n  STR_NOT_ENOUGH_ENERGY: \"Nincs elég Energia!\"\n  STR_NO_ROUNDS_LEFT: \"Nincs több lőszer!\"\n  STR_NO_AMMUNITION_LOADED: \"Nincs lőszer betöltve!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Ebbe a fegyverbe nem ilyen lőszer való!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"A fegyver már meg van töltve!\"\n  STR_NO_LINE_OF_FIRE: \"Nincs tűzvonalban!\"\n  STR_GRENADE_IS_ACTIVATED: \"Gránát élesítve!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Gránát hatástalanítva!\"\n  STR_THERE_IS_NO_ONE_THERE: \"Nincs ott senki!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Kutatás nélkül még használhatatlan!\"\n  STR_OUT_OF_RANGE: \"Túl messze van!\"\n  STR_UNABLE_TO_THROW_HERE: \"Képtelenség oda dobni!\"\n  STR_SET_TIMER: \"Időzítés\"\n  STR_HIDDEN_MOVEMENT: \"REJTETT MOZGÁS\"\n  STR_TURN: \"KÖR> {0}\"\n  STR_SIDE: \"OLDAL> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Gombnyomásra tovább\"\n  STR_MIND_CONTROL: \"Elmekontroll\"\n  STR_PANIC_UNIT: \"Pánikkeltés\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Morál elleni támadás sikeres\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Sikeres Elmekontroll\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}megvadult\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}megvadult\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}pánikba esett\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}pánikba esett\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Idegenek\"\n  STR_RIGHT_HAND: \"JOBB KÉZ\"\n  STR_LEFT_HAND: \"BAL KÉZ\"\n  STR_RIGHT_SHOULDER: \"JOBB VÁLL\"\n  STR_LEFT_SHOULDER: \"BAL VÁLL\"\n  STR_BACK_PACK: \"HÁTIZSÁK\"\n  STR_BELT: \"ÖV\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}idegen irányítás alá került\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}idegen irányítás alá került\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}eszméletét vesztette\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}eszméletét vesztette\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}meghalt egy végzetes seb miatt\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}meghalt egy végzetes seb miatt\"\n  STR_USE_MIND_PROBE: \"Elmeteszt\"\n  STR_FATAL_WOUNDS: \"VÉGZETES SEBEK\"\n  STR_UNDER_ARMOR_UC: \"PÁNCÉL ALUL\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Az időegységek Kapáslövésre fenntartva\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Az időegységek Automata Lövésre fenntartva\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Az időegységek Célzott Lövésre fenntartva\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Idő Egységek Térdelésre fenntartva\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"IE-ek Térdelésre és Lövésre fenntartva\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} Egység X-Com Repülőben\"\n    other: \"{N} Egység X-Com Repülőben\"\n  STR_UNITS_OUTSIDE:\n    one: \"{N} Egység maradt kint\"\n    other: \"{N} Egység maradt kint\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} Egység a Bejáratnál\"\n    other: \"{N} Egység a Bejáratnál\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} Egység a Célkijáratnál\"\n    other: \"{N} Egység a Célkijáratnál\"\n  STR_ABORT_MISSION_QUESTION: \"Abbahagyod a küldetést?\"\n  STR_CORPSE: \"Tetem\"\n  STR_UNLOAD_CRAFT: \"Kiürít\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}meghalt\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}meghalt\"\n  STR_HIT_MELEE: \"Megüt\"\n  STR_GROUND: \"TALAJ\"\n  STR_LIVING_QUARTERS_PLURAL: \"Lakónegyed\"\n  STR_LIST_ITEM: \"TÉTEL\"\n  STR_PERSONAL_ARMOR_UFOPEDIA: \"Az újonnan felfedezett Idegen Fémek felhasználásával, ez az új páncél lehetővé teszi a katonáink számára, hogy reális esélyekkel szállhassanak szembe az idegenekkel.\"\n  STR_POWER_SUIT_UFOPEDIA: \"Ezt az új, erőteljes védőfelszerelést Elerium energiaforrás hajtja, így nagy mértékben megnöveli a viselője sebességét és erejét. Jelenleg ez biztosítja csapataink legjobb védelmét.\"\n  STR_FLYING_SUIT_UFOPEDIA: \"Az Erőpáncél továbbfejlesztett változata. Az idegenektől átvett antigravitációs meghajtással rendelkezik, ami teljes mozgási szabadságot biztosít a csatatéren.\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"Nincs túlélő,{NEWLINE}begyűjtés automatikusan elindult.\"\n  STR_RESET: \"Visszaállítás\"\n  STR_MEMORIAL: \"Emlékmű\"\n  STR_DATE_UC: \"DÁTUM\"\n  STR_SOLDIERS_RECRUITED_UC: \"TOBORZOTT KATONÁK>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"ELESETT KATONÁK>{ALT}{0}\"\n  MAP_CULTA: \"Farm\"\n  MAP_FOREST: \"Erdő\"\n  MAP_JUNGLE: \"Dzsungel\"\n  MAP_MOUNT: \"Hegység\"\n  MAP_DESERT: \"Sivatag\"\n  MAP_POLAR: \"Sarkvidék\"\n  MAP_URBAN: \"Város\"\n  MAP_UBASE: \"Idegen Bázis\"\n  MAP_XBASE: \"X-Com Bázis\"\n  MAP_MARS: \"Mars\"\n  STR_MIXED: \"Vegyes\"\n  STR_REMOVE_SELECTED: \"Kijelöltek eltávolítása\"\n  STR_LIVE_ALIENS: \"Élő{NEWLINE}Példányok\"\n  STR_DEAD_ALIENS: \"Visszautasított{NEWLINE}Példányok\"\n  STR_UNDER_INTERROGATION: \"Tanulmányozás{NEWLINE}Alatt\"\n  STR_CONTAINMENT_EXCEEDED: \"AZ IDEGENTÁROLÓ MEGTELT!{SMALLLINE}Nincs elegendő hely: {0}. El kell távolítanod a felesleges idegeneket (amelyek így aztán meghalnak).\"\n  STR_MANAGE_CONTAINMENT: \"Idegen Tároló kezelése\"\n  STR_STORAGE_EXCEEDED: \"A TÁRHELY MEGTELT!{SMALLLINE}Nincs elegendő tárhely: {0}. A felesleget el kell adnod.\"\n  STR_GO_TO_BASE: \"Bázis mutatása\"\n  STR_MELEE_ACCURACY: \"ÜGYESSÉG KÖZELHARCBAN\"\n  STR_SELL_PRODUCTION: \"ELADÁSRA\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Mindkét kéznek üresnek kell lennie!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Nincs elég tárgy a felszereléshez!\"\n  STR_UNLOAD_WEAPON: \"Fegyver kiürítése\"\n  STR_ALL_ITEMS: \"Minden tétel\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"NEM LEHET TÖBB FELSZERELÉS A FEDÉLZETEN!{SMALLLINE}Csak a megengedett maximum {N} tárgyat vihetsz ebből az eszközből ezen a repülőn.\"\n    other: \"NEM LEHET TÖBB FELSZERELÉS A FEDÉLZETEN!{SMALLLINE}Csak a megengedett maximum {N} tárgyat vihetsz ebből az eszközből ezen a repülőn.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}IRÁNYÍTÓKÖZPONT MEGSEMMISÜLT{NEWLINE}Juss el a bejáratig és szakítsd meg a küldetést.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"X-Com létesítményeket nem lehet víz alá építeni.\"\n  STR_LEVEL_SHORT: \"{0}\"\n  STR_PERSONNEL: \"Személyzet\"\n  STR_CRAFT_ARMAMENT: \"Repülő és Fegyverzet\"\n  STR_COMPONENTS: \"Összetevők\"\n  STR_SOLDIERS_RECRUITED: \"Toborzott katonák\"\n  STR_SOLDIERS_LOST: \"Elesett katonák\"\n  STR_TOTAL_UFOS: \"UFOk észlelve\"\n  STR_TOTAL_ALIEN_BASES: \"Idegen bázisok felfedezve\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"PSE\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"PSÜ\"\n  FEMALE_CIVILIAN: \"Civil, Nő\"\n  MALE_CIVILIAN: \"Civil, Férfi\"\n  CYBERDISC_WEAPON: \"Kiberkorong fegyver\"\n  REAPER_WEAPON: \"Arató fegyver\"\n  CHRYSSALID_WEAPON: \"Krisszalid fegyver\"\n  CELATID_WEAPON: \"Kelatid fegyver\"\n  SILACOID_WEAPON: \"Szilakoid fegyver\"\n  SECTOPOD_WEAPON: \"Szektopod fegyver\"\n  ZOMBIE_WEAPON: \"Zombi fegyver\"\n  ALIEN_PSI_WEAPON: \"Idegen pszi fegyver\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/it.yml",
    "content": "it:\n  STR_AVENGER_UFOPEDIA: \"VEICOLO SPAZIALE DA TRASPORTO E COMBATTIMENTO. L'ULTIMA FRONTIERA NELLA REPLICA DELLA TECNOLOGIA ALIENA.\"\n  STR_INTERCEPTOR_UFOPEDIA: \"VELIVOLO DA COMBATTIMENTO CON DOPPIO MOTORE A REAZIONE E SISTEMI ELETTRONICI SCHERMATI. LA MIGLIORE TECNOLOGIA DISPONIBILE SULLA TERRA.\"\n  STR_LIGHTNING_UFOPEDIA: \"VEICOLO DA TRASPORTO E COMBATTIMENTO. UNA RIPRODUZIONE RUDIMENTALE MA EFFICACE DEI SISTEMI DI PROPULSIONE ALIENI.\"\n  STR_SKYRANGER_UFOPEDIA: \"MEZZO PER TRASPORTO TRUPPE. IL PIU' VELOCE DELLA CATEGORIA, CAPACE DI DECOLLO ED ATTERRAGGIO VERTICALE (V.T.O.L.).\"\n  STR_FIRESTORM_UFOPEDIA: \"VEICOLO DA COMBATTIMENTO. CACCIA MONOPOSTO, RIPRODUCE LO SCHEMA CLASSICO DI UFO ALIENO, CON UN UNITÀ DI PROPULSIONE CENTRALE.\"\n  STR_STINGRAY_UFOPEDIA: \"AVANZATO MISSILE ARIA/ARIA CON ELETTRONICA SCHERMATA.\"\n  STR_AVALANCHE_UFOPEDIA: \"MISSILE ARIA/ARIA CON TESTATA NUCLEARE ED UN PESO ENORME.\"\n  STR_CANNON_UFOPEDIA: \"CANNONE AD ALTA POTENZA CHE SPARA PROIETTILI PERFORANTI IN GRADO DI PENETRARE 35 CENTIMETRI DI ACCIAIO.\"\n  STR_FUSION_BALL_UFOPEDIA: \"QUESTO LANCIAMISSILI SPARA PROIETTILI SFERICI ALIMENTATI DA UNA REAZIONE ANTIMATERICA. LA PALLA DISTRUGGE IL BERSAGLIO CON UN IMPLOSIONE AD ONDE GRAVITAZIONALI.\"\n  STR_LASER_CANNON_UFOPEDIA: \"QUESTO RAGGIO LASER CONVENZIONALE E' AZIONATO DA UNA REAZIONE IN CAMERA ANTIMATERICA.\"\n  STR_PLASMA_BEAM_UFOPEDIA: \"IL RAGGIO GRAVITAZIONALE DIRIGE CON PRECISIONE UN CAMPO DI IMPLOSIONE GRAVITAZIONALE.\"\n  STR_SECTOID_UFOPEDIA: \"La gerarchia dei Sectoidi si estende dai soldati semplici ai capi, i quali si avvalgono di potenti facoltà psioniche. Queste capacità possono essere usate per demoralizzare i soldati in combattimento o per prendere il controllo delle loro menti. Il rapimento viene usato per estrarre materiale genetico, utilizzato per ottenere incroci e cloni da far infiltrare nella società umana. Il bestiame fornisce cibo e materiale genetico. Sembra che questa razza voglia sviluppare degli ibridi genetici superiori, capaci di aumentare l'efficienza della loro società, simile ad un alveare.\"\n  STR_SECTOID_AUTOPSY: \"Autopsia: Sectoide\"\n  STR_SECTOID_AUTOPSY_UFOPEDIA: \"L'autopsia rivela organi digestivi vestigiali e una struttura semplice. Il cervello e gli occhi sono ben sviluppati. La struttura fa pensare ad alterazioni o mutazioni genetiche. La bocca e il naso sembrano non avere alcuna funzione. Il tessuto tra le dita e i piedi piatti fanno ipotizzare origini acquatiche. Non possiedono di apparato riproduttivo, quindi non è chiaro come si riproducano. Si tratta molto probabilmente di una specie geneticamente modificata.\"\n  STR_SNAKEMAN_UFOPEDIA: \"Questa razza si è sviluppata in un ambiente estremamente ostile. Sono esseri molto robusti e riescono a resistere a forti variazioni di temperatura. La loro mobilità dipende da una specie di \\\"piede\\\" simile a un serpente che protegge gli organi vitali. I loro obiettivi sembrano essere unicamente predatori, inoltre sembra agiscono dietro comando di qualche entità intelligente che guida le loro incursioni a carattere militare sulla Terra.\"\n  STR_SNAKEMAN_AUTOPSY: \"Autopsia: Rettiliano\"\n  STR_SNAKEMAN_AUTOPSY_UFOPEDIA: \"La pelle è estremamente dura e resistente al calore. Il sistema cardiovascolare fa parte del sistema muscolare che usa principi idraulici per creare moto. L'unico muscolo vero e proprio è il \\\"cuore\\\". L'apparato riproduttivo sembra essere molto efficiente. La riproduzione è asessuata, con ogni Uomo-Serpente che porta sempre fino a cinquanta uova all'interno del corpo. Lasciata indisturbata, questa specie costituirebbe una seria minaccia per la vita sulla Terra.\"\n  STR_ETHEREAL_UFOPEDIA: \"Questo essere ha incredibili doti mentali che gli forniscono facoltà telepatiche e telecinetiche. Le debolezze fisiche di questa creatura sono bilanciate dalle sue capacità mentali. Non riusciamo a comprendere come funzionino queste doti telecinetiche, perché sembrano sfidare le leggi fisiche finora note. Sono estremamente pericolosi in qualsiasi azione di combattimento, dove utilizzano i loro poteri mentali per combattere. Compaiono raramente sulla Terra, in quanto sembra si affidino ad altre razze per raggiungere i propri obiettivi.\"\n  STR_ETHEREAL_AUTOPSY: \"Autopsia: Etereo\"\n  STR_ETHEREAL_AUTOPSY_UFOPEDIA: \"Questo essere è fisicamente malmesso e sembra incapace di sostenere qualsiasi funzione vitale. I suoi muscoli sono pesantemente atrofizzati e gli organi interni appaiono sottosviluppati. Gli organi sensoriali, tra cui gli occhi, non sembrano funzionare per nulla. Il cervello, tuttavia, è ben sviluppato e assorbe la maggior parte del sangue. Rimane un mistero il modo con il quale questa creatura riesca a mantenersi senza un aiuto esterno.\"\n  STR_MUTON_UFOPEDIA: \"Questo umanoide è intelligente e potente sul piano fisico. È particolarmente affamato di carne cruda di qualsiasi tipo, di cui ha necessità, come i carnivori della Terra. Sembra far affidamento su comandi telepatici provenienti da esseri chiamati \\\"Eterei\\\". Una volta isolato dalla comunicazione telepatica, il suo sistema mentale si deteriora, causandone la morte. Per potenziare le sue prestazioni in combattimento, ricorre a impianti cibernetici. È chiaramente un soldato semplice al comando di intelligenze superiori.\"\n  STR_MUTON_AUTOPSY: \"Autopsia: Muton\"\n  STR_MUTON_AUTOPSY_UFOPEDIA: \"La \\\"pelle\\\" di questa creatura costituisce una sorta di armatura organica innestata direttamente sul corpo. Ci sono diversi impianti cibernetici mirati al potenziamento del sistema cardiovascolare e dei sensi. L'apparato riproduttivo sembra essere stato rimosso chirurgicamente. Evidentemente queste sventurate creature sono destinate unicamente alla vita bellica e alla conquista. I proiettili penetranti non sono molto efficaci sulla loro solidissima epidermide.\"\n  STR_CELATID_UFOPEDIA: \"Questa forma di vita possiede la misteriosa naturale abilità di librarsi nell'aria. Rileva le onde cerebrali umane e si dirige verso i bersagli umani, anche se ben nascosti. Una volta rilevato un bersaglio, la Celatide atterra e lancia piccoli globuli carichi di un veleno estremamente corrosivo. Questa creatura ha la capacità di clonarsi con una rapidità allarmante. Accompagna i Mutoni nei loro vagabondaggi.\"\n  STR_CELATID_AUTOPSY: \"Autopsia: Celatide\"\n  STR_CELATID_AUTOPSY_UFOPEDIA: \"Il nucleo contiene un piccolo congegno bio-meccanico che sembra costituire la naturale evoluzione di una sorta di sistema antigravitazionale a propulsione. La sacca di veleno è l'organo più grande; non si evidenzia una struttura cerebrale a sé stante. Non si osserva nemmeno la presenza di un sistema digerente né di un sistema riproduttivo. Un piccolo organo contiene embrioni che possono trasformarsi rapidamente in nuovi esseri.\"\n  STR_SILACOID_UFOPEDIA: \"Questa forma di vita a base di silicio genera una quantità enorme di calore. Ha la forza di sbriciolare le rocce, che vengono poi ingerite dal nucleo rovente. Ha un'intelligenza primitiva e può essere controllata da impianti o da esseri telepatici. Agisce con la razza aliena dei Mutoni.\"\n  STR_SILACOID_AUTOPSY: \"Autopsia: Silacoide\"\n  STR_SILACOID_AUTOPSY_UFOPEDIA: \"Il nucleo di questa creatura è estremamente caldo, e sembra costituire la base del sistema digestivo. Il suo particolare sistema muscolare ha energia e velocità stupefacenti. La sua epidermide \\\"rocciosa\\\" non viene scalfita dal fuoco o da proiettili incendiari.\"\n  STR_CHRYSSALID_UFOPEDIA: \"Le pinze da granchio di questa creatura sono un'arma temibile nel combattimento ravvicinato. La rapidità del metabolismo e la forza conferiscono a questa creatura velocità e destrezza. Invece di uccidere la vittima, questo essere preferisce fecondarla con un uovo, iniettando poi del veleno che la trasforma in un vero zombie. Poco dopo la vittima genererà una nuova Crisalide. Le Crisalidi sono associate alla razza dei Rettiliani.\"\n  STR_CHRYSSALID_AUTOPSY: \"Autopsia: Crisalide\"\n  STR_CHRYSSALID_AUTOPSY_UFOPEDIA: \"L'esoscheletro di questa creatura è estremamente solido, ma stranamente vulnerabile nei confronti degli esplosivi. Il cervello è ben sviluppato, e la crescita cellulare avviene ad un ritmo molto alto. Questa creatura, che costituisce una vera e propria arma del terrore, porta dentro di se venti uova che vengono deposte all'interno di altri organismi.\"\n  STR_FLOATER_UFOPEDIA: \"I Fluttuanti sono sostanzialmente soldati e agenti del terrore. Sono bestie naturalmente predatorie, strutturate per mezzo dell'ingegneria genetica e potenziate ciberneticamente per diventare guerrieri formidabili. La parte inferiore del corpo e la maggior parte degli organi interni sono stati asportati chirurgicamente e sostituiti con un sistema di sostegno vitale. Questo impianto contiene un'unità antigravitazionale che permette a questa creatura di fluttuare nell'aria, anche se in modo irregolare.\"\n  STR_FLOATER_AUTOPSY: \"Autopsia: Fluttuante\"\n  STR_FLOATER_AUTOPSY_UFOPEDIA: \"Questa creatura è stata drasticamente trasformata dalla chirurgia. Il suo nucleo è costituito da un sistema di supporto vitale che sopperisce alle funzioni di cuore, polmoni e apparato digerente. Così questo essere può sopravvivere in ambienti estremamente ostili. Il cervello è più piccolo del nostro, ma gli organi sensoriali sono ben sviluppati.\"\n  STR_REAPER_UFOPEDIA: \"Questo bipede carnivoro ha potenti mandibole e un appetito vorace. Ha un certo numero di impianti cerebrali che vengono usati per controllare la sua attività. Gli istinti predatori primitivi di questa creatura non risultano utili se non per terrorizzare e distruggere. I Mietitori sono associati ai Fluttuanti.\"\n  STR_REAPER_AUTOPSY: \"Autopsia: Mietitore\"\n  STR_REAPER_AUTOPSY_UFOPEDIA: \"Il Mietitore contiene due \\\"cervelli\\\" e due \\\"cuori\\\" che gli permettono di agire anche quando è gravemente ferito. La sua epidermide pelosa però è altamente infiammabile e rende questa creatura vulnerabile alle armi incendiarie.\"\n  STR_SECTOPOD_UFOPEDIA: \"I Sectopodi sono creature robot con una potente arma a raggi laser. Queste bestie sono controllate per via telepatica dai loro controllori, gli Eterei. I Sectopodi sono la più potente arma di terrore in possesso alle forze aliene.\"\n  STR_SECTOPOD_AUTOPSY: \"Autopsia: Sectopode\"\n  STR_SECTOPOD_AUTOPSY_UFOPEDIA: \"Il robot è costruito molto solidamente e dispone di un'armatura capace di resistere a molte forme di attacchi, in particolare alle armi al plasma. I suoi circuiti sensoriali risultano però piuttosto vulnerabili alle armi laser.\"\n  STR_CYBERDISC_UFOPEDIA: \"Questo disco volante in miniatura è una terrificante arma automatica dotata di un potente raggio al plasma. La propulsione antigravitazionale costituisce un grande vantaggio sui terreni difficili. La sua funzione primaria consiste nel distruggere e spargere terrore al servizio della razza Sectoide.\"\n  STR_CYBERDISC_AUTOPSY: \"Autopsia: Cyberdisco\"\n  STR_CYBERDISC_AUTOPSY_UFOPEDIA: \"Il Cyberdisco è ben schermato e particolarmente adatto a sostenere l'attacco con esplosivi. Il sistema primario antigravitazionale è danneggiato in modo troppo grave per poter capire qualcosa di più del suo funzionamento.\"\n  STR_UFO_POWER_SOURCE_UFOPEDIA: \"La fonte energetica dei veicoli alieni deriva dal reattore ad antimateria, che usa l'Elerium (elemento 115) per generare potenti onde gravitazionali e altre forme di energia. La conversione di materia in energia è efficiente al 99%, per cui minuscole quantità di Elerium possono produrre una quantità di energia enorme. Questa unità può essere riprodotta facilmente usando le leghe aliene.\"\n  STR_UFO_NAVIGATION_UFOPEDIA: \"I veicoli alieni utilizzano sofisticati computer per navigare sulla terra e nello spazio. Il sistema si basa su processori ottici disposti in rete. L'interfaccia di controllo è relativamente semplice - il navigatore controlla la direzione delle onde gravitazionali generate dalla sorgente di alimentazione per spostare il veicolo in qualsiasi direzione. Questo sistema può essere utilizzato facilmente dagli esseri umani, e può essere riprodotto utilizzando leghe aliene e altri componenti.\"\n  STR_UFO_CONSTRUCTION_UFOPEDIA: \"I veicoli degli alieni consistono di tre componenti - una fonte di energia, un sistema di navigazione e uno scafo costruito con leghe aliene. Lo scafo in particolare è studiato in modo da permettere alle onde gravitazionali di essere guidate e controllate. È necessaria anche una piccola quantità di Elerium per attivare la fonte di energia. Una volta compresi i principi costruttivi e individuate le funzioni di ogni componente, risulta possibile costruire questo tipo di veicolo.\"\n  STR_ALIEN_FOOD_UFOPEDIA: \"Queste celle contengono diversi enzimi che vengono usati per digerire le varie parti di bovini, di altri tipi di animali e persino degli umani. Il liquido viene poi consumato come riserva di cibo predigerito, che viene assorbito direttamente dal sangue. Questo fa pensare a una certa dipendenza dal cibo terrestre - una forma di simbiosi tra la Terra e la società aliena.\"\n  STR_ALIEN_REPRODUCTION_UFOPEDIA: \"Queste celle contengono feti di alieni. La forma di questi contenitori fa pensare che gli alieni che usano questo processo contino esclusivamente sulla riproduzione in laboratorio. Le ricche sostanze nutritive assicurano uno sviluppo rapido del feto. Il sistema a catena di montaggio può generare migliaia di cloni alieni in un breve spazio di tempo. Il processo potrebbe essere facilmente adattato alla riproduzione umana, oppure a qualche forma di ibrido alieno-uomo.\"\n  STR_ALIEN_ENTERTAINMENT_UFOPEDIA: \"La funzione più probabile di queste sfere è quella ricreativa. Il circuito psionico stimola vari centri cerebrali. L'effetto è simile a quello degli allucinogeni. Questo è l'unico elemento che ci può far pensare che gli alieni abbiano dei momenti culturali o di svago.\"\n  STR_ALIEN_SURGERY_UFOPEDIA: \"Le apparecchiature chirurgiche sono dotate di bisturi a raggio laser per estrarre gli organi dal bestiame e dagli uomini. L'aumento delle mutilazioni nei bovini si spiega con questa bizzarra attività aliena. È probabile che queste parti vengano usate a scopo alimentare o genetico.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"Nel passato moltissime persone hanno denunciato di essere state rapite dagli alieni, spesso più di una volta. La verità è ancora più drammatica; si è trattato di rapimenti seguiti da ricerche e monitoraggi. Agli esemplari migliori viene tolto del materiale genetico. Alle donne vengono impiantati feti ibridi uomo-alieno che sono tolti diversi mesi dopo. Non è facile capire quali finalità muovano gli alieni a svolgere questo tipo di attività.\"\n  STR_ALIEN_ALLOYS_UFOPEDIA: \"I veicoli alieni sono costruiti con speciali leghe dalle proprietà uniche. Sono estremamente leggeri e resistenti, e possono essere costruiti con metodi elettro-magnetici. Questo materiale può essere riprodotto e usato in vari processi costruttivi.\"\n  STR_ELERIUM_115_UFOPEDIA: \"Questo elemento ha l'insolita proprietà di generare energia ad antimateria quando viene bombardato da certe particelle. Questo crea onde gravitazionali e altre forme di energia. Non si trova naturalmente nel nostro sistema solare e non può essere riprodotto.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"È chiaro che stiamo combattendo una battaglia perduta qui sulla Terra. Gli alieni sono numericamente molto superiori. L'unica cosa che possiamo fare è rallentare la loro avanzata. L'unica speranza per l'umanità è cercare di affrontarli nelle loro basi. Le nostre ricerche sembrano indicare una base operativa all'interno del nostro sistema solare. Gli alieni ritengono che questo luogo sia il centro di un'antica civiltà che ha preceduto la storia umana. Dobbiamo localizzare questo luogo nel più breve tempo possibile. Dobbiamo però catturare e interrogare un leader alieno per ricavare informazioni più dettagliate. Probabilmente gli UFO più grandi contengono almeno un leader alieno.\"\n  STR_THE_MARTIAN_SOLUTION_UFOPEDIA: \"Le nostre ricerche puntano a Marte come quartier generale delle operazioni aliene. La base è ben nascosta, e contiene tutte le strutture manifatturiere e di clonaggio necessarie per l'infiltrazione sulla Terra. Sembra anche contenere una sorta di computer di controllo che gestisce l'intera operazione. Sembra che la società aliena simile alla struttura della società delle api ha una sorta di 'ape regina'. Questa è la loro più grande debolezza: se riusciamo a distruggere il loro 'cervello' allora l'intero corpo morirà. Dobbiamo concentrarci sulle ricerche prima che sia troppo tardi. Per poter progredire dobbiamo catturare una specie capo aliena presenti soltanto nelle basi aliene e sulle navi da battaglia, ed interrogarlo.\"\n  STR_CYDONIA_OR_BUST_UFOPEDIA: \"È chiaro ormai che le orde di alieni vengono controllate da una base sotterranea situata a Cydonia - un'area isolata di Marte in cui si trovano piramidi a cinque lati e una enorme struttura con il volto umano. Un tempo, milioni di anni fa, su Marte fiorì la civiltà Cydonia, ma si ignora il motivo per cui questa civiltà in seguito sia scomparsa, e anche quali connessioni possa avere con l'attuale attività degli alieni in questa zona. In ogni caso è bene inviare una spedizione a Cydonia per cercare di distruggere la \\\"mente\\\", il controllore supremo, e sconfiggere gli alieni. Dovremo fornirci di un veicolo Avenger, attrezzato con le più temibili e potenti armi a nostra disposizione. Non abbiamo più niente da imparare qui. Dobbiamo soltanto attendere l'esito dell'assalto a Cydonia.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"CENTRA SU LUOGO-TEMPO=5 Sec.\"\n  STR_CANCEL_UC: \"ANNULLA\"\n  STR_NONE: \"Nessuno\"\n  STR_UNKNOWN: \"Sconosciuto\"\n  STR_POOR: \"Scarso\"\n  STR_AVERAGE: \"Medio\"\n  STR_GOOD: \"Buono\"\n  STR_EXCELLENT: \"Eccellente\"\n  STR_BUILD_NEW_BASE_UC: \"COSTRUISCI NUOVA BASE\"\n  STR_BASE_INFORMATION: \"INFORMAZIONI BASE\"\n  STR_EQUIP_CRAFT: \"EQUIPAGGIA VEICOLO\"\n  STR_BUILD_FACILITIES: \"COSTRUISCI STRUTTURE\"\n  STR_RESEARCH: \"RICERCA\"\n  STR_MANUFACTURE: \"PRODUCI\"\n  STR_TRANSFER_UC: \"TRASFERISCI\"\n  STR_PURCHASE_RECRUIT: \"ACQUISTA/ASSUMI\"\n  STR_SACK: \"LICENZIA\"\n  STR_SELL_SACK_UC: \"VENDI/LICENZIA\"\n  STR_GEOSCAPE_UC: \"GEOSCAPE\"\n  STR_NAME: \"Nome\"\n  STR_AREA: \"Area\"\n  STR_BUILD_NEW_BASE: \"Costruisci Nuova Base\"\n  STR_CANCEL: \"Annulla\"\n  STR_COST_UC: \"COSTO>\"\n  STR_CONSTRUCTION_TIME_UC: \"TEMPO COSTRUZIONE>\"\n  STR_DAY:\n    one: \"{N} g.\"\n    many: \"{N} giorni.\"\n    other: \"{N} giorni.\"\n  STR_HOUR:\n    one: \"{N} ora\"\n    many: \"{N} ore\"\n    other: \"{N} ore\"\n  STR_MAINTENANCE_UC: \"MANUTENZIONE>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Installazione\"\n  STR_CURRENT_RESEARCH: \"RICERCA IN CORSO\"\n  STR_SCIENTISTS_AVAILABLE: \"Scienziati Disponibili>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Scienziati Allocati>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Spazio Laboratorio Disponibile>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"PROGETTO DI RICERCA\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"SCIENZIATI IMPEGNATI\"\n  STR_PROGRESS: \"PROGRESSI\"\n  STR_NEW_PROJECT: \"Nuovo progetto\"\n  STR_CANCEL_PROJECT: \"ANNULLA PROGETTO\"\n  STR_NEW_RESEARCH_PROJECTS: \"NUOVI PROGETTI DI RICERCA\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"SCIENZIATI DISPONIBILI>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"LABORATORIO SPAZIO DISPONIBILE>{ALT}{0}\"\n  STR_INCREASE: \"Aumenta\"\n  STR_DECREASE: \"Diminuisci\"\n  STR_START_PROJECT: \"AVVIA PROGETTO\"\n  STR_CURRENT_PRODUCTION: \"PRODUZIONE IN ATTO\"\n  STR_ENGINEERS_AVAILABLE: \"Ingegneri Disponibili>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Ingegneri Allocati>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Spazio Officina Disponibile>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Fondi Attuali>{ALT}{0}\"\n  STR_ITEM: \"OGGETTO\"\n  STR_ENGINEERS__ALLOCATED: \"Ingegneri Allocati\"\n  STR_UNITS_PRODUCED: \"Unità Prodotte\"\n  STR_TOTAL_TO_PRODUCE: \"Totale da Produrre\"\n  STR_COST__PER__UNIT: \"Costo{NEWLINE}per{NEWLINE}Unità\"\n  STR_DAYS_HOURS_LEFT: \"Giorni/Ore Rimaste\"\n  STR_NEW_PRODUCTION: \"Nuova Produzione\"\n  STR_PRODUCTION_ITEMS: \"Articoli per Produzione\"\n  STR_CATEGORY: \"CATEGORIA\"\n  STR_START_PRODUCTION: \"AVVIA PRODUZIONE\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} Ore di lavoro per produrre una unità\"\n  STR_COST_PER_UNIT_: \"Costo per unità>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Spazio Officina Richiesto>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"MATERIALI SPECIALI RICHIESTI\"\n  STR_ITEM_REQUIRED: \"OGGETTO RICHIESTO\"\n  STR_UNITS_REQUIRED: \"UNITA' RICHIESTE\"\n  STR_UNITS_AVAILABLE: \"UNITA' DISPONIBILI\"\n  STR_STOP_PRODUCTION: \"INTERROMPI PRODUZIONE\"\n  STR_ENGINEERS_AVAILABLE_UC: \"INGEGNERI DISPONIBILI>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"SPAZIO OFFICINA DISPONIBILE>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"PROFITTO MENSILE>{ALT}{0}\"\n  STR_INCREASE_UC: \"AUMENTA\"\n  STR_DECREASE_UC: \"DIMINUISCI\"\n  STR_UNITS_TO_PRODUCE: \"Unità da Produrre\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Acquista/Assumi Personale\"\n  STR_COST_OF_PURCHASES: \"Costo di Acquisto>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"COSTO PER UNITA'\"\n  STR_QUANTITY_UC: \"QUANTITÀ\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"PERSONALE DISPONIBILE:PERSONALE TOTALE>\"\n  STR_SOLDIERS: \"Soldati\"\n  STR_SCIENTISTS: \"Scienziati\"\n  STR_ENGINEERS: \"Ingegneri\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"SPAZIO USATO:SPAZIO DISPONIBILE>\"\n  STR_LIVING_QUARTERS: \"Alloggi\"\n  STR_STORES: \"Magazzini\"\n  STR_LABORATORIES: \"Laboratori\"\n  STR_WORK_SHOPS: \"Officine\"\n  STR_HANGARS: \"Hangar\"\n  STR_SHORT_RANGE_DETECTION: \"Rilevazione Corto Raggio\"\n  STR_DEFENSE_STRENGTH: \"Potere Difensivo\"\n  STR_TRANSFERS_UC: \"TRASFERIMENTI\"\n  STR_TRANSFERS: \"Trasferimenti\"\n  STR_ARRIVAL_TIME_HOURS: \"Tempo di Arrivo (ore)\"\n  STR_COST_: \"Costo>{ALT}{0}\"\n  STR_AREA_: \"Area>{ALT}{0}\"\n  STR_BASE_NAME: \"Nome Base?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"SELEZIONA LUOGO ASCENSORE D'ACCESSO\"\n  STR_TRANSFER: \"Trasferisci\"\n  STR_AMOUNT_TO_TRANSFER: \"TOT. DA TRASFERIRE\"\n  STR_SELECT_DESTINATION_BASE: \"Seleziona Base di Destinazione\"\n  STR_COST: \"Costo\"\n  STR_VICTORY_1: \"Quando entri nella sala vedi il cervello alieno - l'obiettivo della tua ricerca. Prima di poter sparare, il cervello comunica con te per mezzo di uno schermo che sta alla sua base. Ti supplica di ascoltare le sue ragioni, per convincerti a risparmiargli la vita prima che tu decida di premere il grilletto...\"\n  STR_VICTORY_2: \"Il cervello parla: Molti milioni di anni fa, sul pianeta che voi chiamate Marte, c'era la vita. Noi stessi avevamo portato la vita in quelle lande desolate, come avevamo fatto con la vostra Terra. Per milioni di anni noi abbiamo fatto visita al vostro pianeta e abbiamo sviluppato nuove specie. Non potete ucciderci, siete parte di noi...\"\n  STR_VICTORY_3: \"Ecco il cuore della civiltà marziana - le piramidi costruite milioni di anni prima delle vostre - da creature che possono essere considerate i vostri progenitori. Non c'è pianeta che sia fuori dalla nostra portata. Presto questo nostro potere potrebbe diventare vostro. Vi chiediamo soltanto un po' di collaborazione.\"\n  STR_GAME_OVER_1: \"Gli alieni tentano di sterminare tutta l'umanità, distruggendo città e avvelenando l'aria e il mare. La resistenza degli eserciti terrestri è del tutto inutile di fronte all'innegabile superiorità tecnica degli alieni. Le generazioni sopravvissute subiscono terribili mutazioni mentre cercano di sfuggire alla distruzione. Gli uomini finiscono poi in campi di concentramento, trattati come schiavi e costretti a collaborare alla trasformazione della Terra in una colonia aliena, che costituirà parte di un più vasto impero ignoto.\"\n  STR_GAME_OVER_2: \"La conoscienza ottenuta attraverso il progetto X-Com è perduta per sempre. Non sei riuscito a salvare la terra.\"\n  STR_VICTORY_4: \"Il cervello alieno è stato colpito da una carica di plasma rovente, e tutte le forze aliene sono state sconfitte.\"\n  STR_VICTORY_5: \"Dopo aver perso Marte, gli alieni hanno perso la Terra. Le ricerche XCom permetteranno all'umanità di rifiorire e di aspirare al dominio di Marte. La minaccia aliena è scomparsa ma, attenzione, fino a quando?\"\n  STR_YOU_HAVE_FAILED: \"Non sei riuscito a fermare il massacro da parte degli alieni. Una per una, le nazioni associate al patto, tratteranno con gli alieni che promettono tecnologia, prosperità e pace. Si capirà in breve che gli alieni avevano ben altri progetti...\"\n  STR_TOTAL_UC: \"TOTALE\"\n  STR_INCOME: \"Entrate\"\n  STR_EXPENDITURE: \"Uscite\"\n  STR_MAINTENANCE: \"Manutenzione\"\n  STR_BALANCE: \"Fondi disponibili\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"Attività UFO nelle Aree\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"Attività UFO nei Paesi\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"Attività X-Com nelle Aree\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"Attività X-Com nei Paesi\"\n  STR_FINANCE: \"Situaz. finanziaria\"\n  STR_DATE_FIRST: \"{0}mo\"\n  STR_DATE_SECOND: \"{0}do\"\n  STR_DATE_THIRD: \"{0}zo\"\n  STR_DATE_FOURTH: \"{0}°\"\n  STR_FINANCE_THOUSANDS: \"1000$\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Non ci sono abbastanza materiali speciali per produrre{NEWLINE}{0}{NEWLINE}a{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Soldi insufficienti per produrre{NEWLINE}{0}{NEWLINE}a{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"Produzione di{NEWLINE}{0}{NEWLINE}in{NEWLINE}{1}{NEWLINE}completata\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"Costruzione di{NEWLINE}{0}{NEWLINE}in{NEWLINE}{1}{NEWLINE}completata\"\n  STR_OK_5_SECONDS: \"OK - 5 sec.\"\n  STR_RESEARCH_COMPLETED: \"Ricerca Completata\"\n  STR_VIEW_REPORTS: \"RISULTATI RICERCA\"\n  STR_WE_CAN_NOW_RESEARCH: \"Ora possiamo ricercare\"\n  STR_WE_CAN_NOW_PRODUCE: \"Ora possiamo produrre\"\n  STR_SUNDAY: \"DOMENICA\"\n  STR_MONDAY: \"LUNEDÌ\"\n  STR_TUESDAY: \"MARTEDÌ\"\n  STR_WEDNESDAY: \"MERCOLEDÌ\"\n  STR_THURSDAY: \"GIOVEDÌ\"\n  STR_FRIDAY: \"VENERDÌ\"\n  STR_SATURDAY: \"SABATO\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"{2} non ha abbastanza {0} per rifornire {1}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"{2} non ha abbastanza {0} per riarmare {1}\"\n  STR_UFO_IS_NOT_RECOVERED: \"UFO non recuperato\"\n  STR_UFO_IS_RECOVERED: \"UFO recuperato\"\n  STR_CRAFT_IS_LOST: \"Veicolo perduto\"\n  STR_TERROR_CONTINUES: \"Il terrore continua\"\n  STR_ALIENS_DEFEATED: \"Alieni sconfitti\"\n  STR_BASE_IS_LOST: \"Base perduta\"\n  STR_BASE_IS_SAVED: \"Base salvata\"\n  STR_ALIEN_BASE_STILL_INTACT: \"Base Aliena ancora intatta\"\n  STR_ALIEN_BASE_DESTROYED: \"Base aliena distrutta\"\n  STR_ALIENS_KILLED: \"ALIENI UCCISI\"\n  STR_ALIEN_CORPSES_RECOVERED: \"CORPI ALIENI RECUPERATI\"\n  STR_LIVE_ALIENS_RECOVERED: \"ALIENI VIVI RECUPERATI\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"OGGETTI ALIENI RECUPERATI\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"CONTROLLO BASE ALIENA DISTRUTTO\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"CIVILI UCCISI DAGLI ALIENI\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"CIVILI UCCISI DA OPERATORI X-COM\"\n  STR_CIVILIANS_SAVED: \"CIVILI SALVATI\"\n  STR_XCOM_OPERATIVES_KILLED: \"OPERATORI X-COM UCCISI\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"X-COM DISPERSI IN AZIONE\"\n  STR_TANKS_DESTROYED: \"TANK DISTRUTTI\"\n  STR_XCOM_CRAFT_LOST: \"VEICOLO X-COM PERDUTO \"\n  STR_UFO_RECOVERY: \"UFO RECUPERATI\"\n  STR_ALIEN_BASE_RECOVERY: \"RECUPERO BASE ALIENA\"\n  STR_BASE_UNDER_ATTACK: \"{0} sotto attacco!\"\n  STR_BASE_DEFENSES_INITIATED: \"SISTEMI DI DIFESA ATTIVATI\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"SCUDO GRAVITAZ. RESPINGE UFO!\"\n  STR_FIRING: \"MIRA\"\n  STR_HIT: \"COLPITO!\"\n  STR_UFO_DESTROYED: \"UFO DISTRUTTO!\"\n  STR_MISSED: \"MANCATO!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Vendi Oggetti/Licenzia Personale\"\n  STR_VALUE_OF_SALES: \"VALORE VENDITE> {ALT}{0}\"\n  STR_FUNDS: \"ENTRATE>{ALT}{0}\"\n  STR_SELL_SACK: \"Vendi/Licenzia\"\n  STR_VALUE: \"Valore\"\n  STR_CRAFT_: \"VEICOLO> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"RECUPERO UFO PRECIPITATO\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"Fai attenzione - Potrebbero esserci alieni ancora operativi dentro l'UFO o intorno al luogo dello schianto. La missione sarà compiuta con successo solo se tutte le unità nemiche verranno eliminate o neutralizzate. Solo allora si potrà iniziare il recupero dei resti dell'UFO, dei manufatti e dei cadaveri degli alieni. Per interrompere la missione, riporta i soldati XCom al veicolo da trasporto e fai clic sull'icona \\\"Interruzione missione\\\".\"\n  STR_UFO_GROUND_ASSAULT: \"ASSALTO DI TERRA DEGLI UFO\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"Esplora la zona di atterraggio e, se possibile, fatti strada nell'UFO. La missione sarà compiuta con successo solo se tutte le unità nemiche verranno eliminate o neutralizzate. Solo allora si potrà iniziare il recupero dei resti dell'UFO, dei manufatti e dei cadaveri degli alieni. Per interrompere la missione riporta i soldati XCom al veicolo da trasporto e fai clic sull'icona \\\"Interruzione missione.\\\"\"\n  STR_BASE_DEFENSE: \"DIFESA BASE\"\n  STR_BASE_UC_: \"BASE> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"Un veicolo alieno è atterrato nelle vicinanze. La nostra base è in grave pericolo. Seguendo la procedura standard tutto il personale non combattente è stato evacuato. Le unità aliene irromperanno nella base attraverso le porte dell'hangar oppure dall'ascensore d'accesso. Difendi la base e le sue installazioni vitali a tutti i costi - è una questione di vita o di morte. Se fai clic sull'icona \\\"Interrompi la missione\\\", dovrai considerarti sconfitto e perderai la base.\"\n  STR_ALIEN_BASE_ASSAULT: \"ASSALTO DI BASE ALIENA\"\n  STR_ALIEN_BASE_ASSAULT_BRIEFING: \"Operatori XCom sono penetrati in una base aliena. Il centro di controllo deve essere distrutto perché la base non sia più operativa. La missione sarà compiuta quando tutti i nemici saranno stati eliminati oppure quando la tua squadra sarà ritornata all'area verde di uscita (per uscire, premi sull'icona \\\"Interrompi la missione\\\").\"\n  STR_CYDONIA_BRIEFING: \"Sei arrivato a Cydonia. Entri in un grande complesso sotterraneo vicino alla Sfinge di Marte. Devi distruggere il Cervello che controlla tutte le attività degli alieni. Le sorti dell'umanità sono nelle tue mani....\"\n  STR_TERROR_MISSION: \"MISSIONE TERRORE\"\n  STR_TERROR_MISSION_BRIEFING: \"La Missione potrà dirsi riuscita soltanto se tutte le unità nemiche saranno state eliminate o neutralizzate. Devi cercare di salvare la vita di tutti i civili che si trovano nella zona, neutralizzando la minaccia aliena. Per interrompere la missione riporta gli operatori XCom al veicolo da trasporto e premi sull'icona \\\"Interrompi la missione\\\".\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"NESSUN HANGAR LIBERO PER LA PRODUZIONE DI VEICOLI!{SMALLLINE}Ogni veicolo assegnato alla base, trasferito a una base, acquistato o costruito, usa un hangar. Costruisci un nuovo hangar o trasferisci un veicolo in un'altra base.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"NESSUN HANGAR LIBERO PER I NUOVI ACQUISTI!{SMALLLINE}Ogni veicolo assegnato alla base, trasferito a una base, acquistato o costruito, usa un hangar. Costruisci un nuovo hangar o trasferisci un veicolo in un'altra base.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"NESSUN HANGAR LIBERO PER IL TRASFERIMENTO!{SMALLLINE}Ogni veicolo assegnato alla base, trasferito a una base, acquistato o costruito, usa un hangar. Costruisci un nuovo hangar o trasferisci un veicolo in un'altra base.\"\n  STR_CANNOT_BUILD_HERE: \"NON PUOI COSTRUIRE QUI!{SMALLLINE}Devi costruire a fianco di una struttura pre-esistente.\"\n  STR_NO_FREE_ACCOMODATION: \"ALLOGGI NON DISPONIBILI!{SMALLLINE}La base di destinazione non ha spazio sufficiente negli alloggi.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"SPAZIO OFFICINA NON DISPONIBILE!{SMALLLINE}Crea un'altra officina oppure riduci il lavoro su altri progetti.\"\n  STR_NOT_ENOUGH_MONEY: \"CREDITI INSUFFICIENTI!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"SPAZIO INSUFFICIENTE IN MAGAZZINO!{SMALLLINE}Costruisci un altro magazzino o trasferisci i magazzini esistenti in altre basi.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"ALLOGGI INSUFFICIENTI!{SMALLLINE}Costruisci nuovi alloggi oppure trasferisci il personale in altre basi.\"\n  STR_LAUNCH_INTERCEPTION: \"INTERCETTA\"\n  STR_CRAFT: \"VEICOLO\"\n  STR_STATUS: \"STATO\"\n  STR_BASE: \"BASE\"\n  STR_READY: \"PRONTO\"\n  STR_OUT: \"FUORI\"\n  STR_REPAIRS: \"RIPARAZIONE\"\n  STR_REFUELLING: \"RIFORNIMENTO\"\n  STR_REARMING: \"RIARMO\"\n  STR_TARGET: \"BERSAGLIO: {0}\"\n  STR_WAY_POINT: \"NODO PERCORSO\"\n  STR_ARE_YOU_SURE_CYDONIA: \"Vuoi davvero mandare questo veicolo in missione a Cydonia?\"\n  STR_YES: \"SÌ\"\n  STR_NO: \"NO\"\n  STR_SELECT_DESTINATION: \"SCEGLI DESTINAZIONE\"\n  STR_CYDONIA: \"CYDONIA\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"SCEGLI LUOGO PER NUOVA BASE\"\n  STR_RETURN_TO_BASE: \"RITORNA ALLA BASE\"\n  STR_SELECT_NEW_TARGET: \"SCEGLI NUOVO OBIETTIVO\"\n  STR_PATROL: \"RICOGNIZIONE\"\n  STR_STATUS_: \"STATO>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"DANNEGGIATO - RITORNO ALLA BASE\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"CARBURANTE SCARSO - RITORNO ALLA BASE\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"MISSIONE COMPLETA - RITORNO ALLA BASE\"\n  STR_PATROLLING: \"IN RICOGNIZIONE\"\n  STR_TAILING_UFO: \"INSEGUENDO UFO\"\n  STR_INTERCEPTING_UFO: \"INTERCETTANDO UFO-{0}\"\n  STR_RETURNING_TO_BASE: \"RITORNO ALLA BASE\"\n  STR_DESTINATION_UC_: \"DESTINAZIONE: {0}\"\n  STR_BASE_UC: \"BASE>{ALT}{0}\"\n  STR_SPEED_: \"VELOCITA'>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"VELOCITA' MASSIMA>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"ALTITUDINE>{ALT}{0}\"\n  STR_VERY_LOW: \"MOLTO BASSA\"\n  STR_LOW_UC: \"BASSA\"\n  STR_HIGH_UC: \"ALTA\"\n  STR_VERY_HIGH: \"MOLTO ALTA\"\n  STR_FUEL: \"CARBURANTE>{ALT}{0}\"\n  STR_WEAPON_ONE: \"ARMA-1>{ALT}{0}\"\n  STR_NONE_UC: \"NESSUNO\"\n  STR_ROUNDS_: \"COLPI>{ALT}{0}\"\n  STR_WEAPON_TWO: \"ARMA-2>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"INTERCETTA VELIVOLO\"\n  STR_BASE_: \"Base>{0}\"\n  STR_NAME_UC: \"NOME\"\n  STR_AMMO_: \"MUNIZ.>{ALT}{0}\"\n  STR_CREW: \"EQUIPAGGIO\"\n  STR_EQUIPMENT_UC: \"ARMAMENTI\"\n  STR_ARMOR: \"ARMATURA\"\n  STR_MAX: \"MAX>{ALT}{0}\"\n  STR_ROOKIE: \"Recluta\"\n  STR_SQUADDIE: \"Soldato Scelto\"\n  STR_SERGEANT: \"Sergente\"\n  STR_CAPTAIN: \"Capitano\"\n  STR_COLONEL: \"Colonnello\"\n  STR_COMMANDER: \"Comandante\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Seleziona Squadra per {0}\"\n  STR_SORT_BY: \"ORDINA PER...\"\n  STR_ORIGINAL_ORDER: \"ORDINE ORIGINALE\"\n  STR_MISSIONS2: \"MISSIONI\"\n  STR_KILLS2: \"UCCISIONI\"\n  STR_WOUND_RECOVERY2: \"GUARIGIONE FERITA\"\n  STR_SPACE_AVAILABLE: \"SPAZIO DISPONIBILE>{ALT}{0}\"\n  STR_SPACE_USED: \"SPAZIO USATO>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"SPAZIO USATO\"\n  STR_RANK: \"GRADO\"\n  STR_WOUNDED: \"FERITO\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Armamenti per {0}\"\n  STR_DEFENSE_VALUE: \"Potere Difensivo\"\n  STR_HIT_RATIO: \"Colpi a Segno\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}è pronto ad{NEWLINE}atterrare nei pressi di{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"Inizio Missione?\"\n  STR_SELECT_ARMAMENT: \"Seleziona Armamenti\"\n  STR_AMMUNITION_AVAILABLE: \"MUNIZIONI DISPONIBILI\"\n  STR_ARMAMENT: \"ARMAMENTI\"\n  STR_NOT_AVAILABLE: \"NON DISP.\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"SELEZIONA ARMATURA PER {NEWLINE}{0}\"\n  STR_TYPE: \"TIPO\"\n  STR_PERSONAL_ARMOR_UC: \"ARM. PERSONALE\"\n  STR_POWER_SUIT_UC: \"TUTA POTENZIATA\"\n  STR_FLYING_SUIT_UC: \"TUTA VOLANTE\"\n  STR_SELECT_ARMOR: \"Selezione Armatura\"\n  STR_NORTH: \"NORD\"\n  STR_NORTH_EAST: \"NORD-EST\"\n  STR_EAST: \"EST\"\n  STR_SOUTH_EAST: \"SUD-EST\"\n  STR_SOUTH: \"SUD\"\n  STR_SOUTH_WEST: \"SUD-OVEST\"\n  STR_WEST: \"OVEST\"\n  STR_NORTH_WEST: \"NORD-OVEST\"\n  STR_SELECT_ACTION: \"SELEZIONA AZIONE\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"CONTINUA INTERCETTAZ.\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"INSEGUI SENZA INTERCETTAZ.\"\n  STR_VERY_LARGE: \"MOLTO GRANDE\"\n  STR_LARGE: \"GRANDE\"\n  STR_MEDIUM_UC: \"MEDIO\"\n  STR_SMALL: \"PICCOLO\"\n  STR_VERY_SMALL: \"MOLTO PICCOLO\"\n  STR_GROUNDED: \"A TERRA\"\n  STR_DETECTED: \"Individuato\"\n  STR_SIZE_UC: \"DIMENSIONI\"\n  STR_ALTITUDE: \"ALTITUDINE\"\n  STR_HEADING: \"DIRETTO A\"\n  STR_SPEED: \"VELOCITÀ\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"CENTRA SU UFO-TEMPO=5 Sec.\"\n  STR_TRACKING_LOST: \"TRACCIA PERSA\"\n  STR_REDIRECT_CRAFT: \"MODIFICA DIREZIONE VEICOLO\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"VAI ALL'ULTIMA POSIZIONE NOTA DELL'UFO\"\n  STR_UFO_: \"UFO-{0}\"\n  STR_ALIEN_BASE_: \"BASE ALIENA-{0}\"\n  STR_CRASH_SITE_: \"SITO D'IMPATTO-{0}\"\n  STR_LANDING_SITE_: \"SITO DI ATTERRAGGIO-{0}\"\n  STR_WAY_POINT_: \"NODO PERCORSO-{0}\"\n  STR_TERROR_SITE: \"SITO DI TERRORE-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}ha raggiunto{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"In ricognizione\"\n  STR_ALIEN_ORIGINS: \"Origini Aliene\"\n  STR_THE_MARTIAN_SOLUTION: \"La Soluzione Marziana\"\n  STR_CYDONIA_OR_BUST: \"Marte o Morte\"\n  STR_UFOPAEDIA: \"UFOpedia\"\n  STR_XCOM_CRAFT_ARMAMENT: \"VEICOLI E ARMAMENTI X-COM\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"TANK\"\n  STR_WEAPONS_AND_EQUIPMENT: \"ARMI E ARMAMENTI\"\n  STR_ALIEN_ARTIFACTS: \"OGGETTI ALIENI\"\n  STR_BASE_FACILITIES: \"STRUTTURE BASI\"\n  STR_ALIEN_LIFE_FORMS: \"FORME DI VITA ALIENE\"\n  STR_ALIEN_RESEARCH_UC: \"RICERCA ALIENA\"\n  STR_UFO_COMPONENTS: \"COMPONENTI UFO\"\n  STR_UFOS: \"UFO\"\n  STR_SELECT_ITEM: \"SCEGLI OGGETTO\"\n  STR_ACCELERATION: \"ACCELERAZIONE>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"CAPACITÀ CARBURANTE>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"ALLOGGI ARMAMENTI>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"CAPACITÅ DI DANNO<{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"SPAZIO IN STIVA>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"CAPACITÀ TANK<{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Danno\"\n  STR_RANGE: \"Portata\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Precisione\"\n  STR_RE_LOAD_TIME: \"Tempo ricarica\"\n  STR_SECONDS: \"{0}s\"\n  STR_DAMAGE_ARMOR_PIERCING: \"PENETRAZIONE ARMATURA\"\n  STR_DAMAGE_INCENDIARY: \"INCENDIARIO\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"SUPER-ESPLOSIVO\"\n  STR_DAMAGE_LASER_BEAM: \"RAGGIO LASER\"\n  STR_DAMAGE_PLASMA_BEAM: \"RAGGIO PLASMA\"\n  STR_DAMAGE_STUN: \"STORDIMENTO\"\n  STR_DAMAGE_MELEE: \"MISCHIA\"\n  STR_DAMAGE_ACID: \"ACIDO\"\n  STR_DAMAGE_SMOKE: \"FUMO\"\n  STR_SHOT_TYPE: \"TIPO DI COLPO\"\n  STR_ACCURACY_UC: \"PRECISIONE\"\n  STR_TIME_UNIT_COST: \"COSTO UdT\"\n  STR_DAMAGE_UC: \"DANNO\"\n  STR_AMMO: \"MUNIZ.\"\n  STR_SHOT_TYPE_AUTO: \"Automatico\"\n  STR_SHOT_TYPE_SNAP: \"Rapido\"\n  STR_SHOT_TYPE_AIMED: \"Mirato\"\n  STR_CONSTRUCTION_TIME: \"Tempo Costruzione\"\n  STR_CONSTRUCTION_COST: \"Costo Costruzione\"\n  STR_MAINTENANCE_COST: \"Costo Manutenzione\"\n  STR_LOW: \"Basso\"\n  STR_MEDIUM: \"Medio\"\n  STR_HIGH: \"Alto\"\n  STR_CRAFT_WEAPON: \"Armi Veicolo\"\n  STR_CRAFT_AMMUNITION: \"Munizioni Veicolo\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Tank\"\n  STR_WEAPON: \"Arma\"\n  STR_AMMUNITION: \"Muniz.\"\n  STR_EQUIPMENT: \"Armamenti\"\n  STR_ALIEN_CORPSE: \"Cadavere Alieno\"\n  STR_UFO_COMPONENT: \"Componente UFO \"\n  STR_PERSONAL_ARMOR: \"Arm. Personale\"\n  STR_RAW_MATERIALS: \"Materiale Grezzo\"\n  STR_HWP_CANNON_SHELLS: \"Proiettile Cannone Tank\"\n  STR_ALIEN: \"Alieno\"\n  STR_SECTOID: \"Sectoide\"\n  STR_SNAKEMAN: \"Uomo-Serpente\"\n  STR_ETHEREAL: \"Etereo\"\n  STR_MUTON: \"Muton\"\n  STR_FLOATER: \"Fluttuante\"\n  STR_CELATID: \"Celatide\"\n  STR_SILACOID: \"Silacoide\"\n  STR_CHRYSSALID: \"Crisalide\"\n  STR_ZOMBIE: \"Zombi\"\n  STR_REAPER: \"Mietitore\"\n  STR_SECTOPOD: \"Sectopode\"\n  STR_CYBERDISC: \"Cyberdisco\"\n  STR_LIVE_COMMANDER: \"Comandante\"\n  STR_LIVE_LEADER: \"Leader\"\n  STR_LIVE_ENGINEER: \"Ingegnere\"\n  STR_LIVE_MEDIC: \"Medico\"\n  STR_LIVE_NAVIGATOR: \"Navigatore\"\n  STR_LIVE_SOLDIER: \"Soldato\"\n  STR_LIVE_TERRORIST: \"Terrorista\"\n  STR_FLOATER_SOLDIER: \"Fluttuante Soldato\"\n  STR_FLOATER_NAVIGATOR: \"Fluttuante Navigatore\"\n  STR_FLOATER_MEDIC: \"Fluttuante Medico\"\n  STR_FLOATER_ENGINEER: \"Fluttuante Ingegnere\"\n  STR_FLOATER_LEADER: \"Fluttuante Leader\"\n  STR_FLOATER_COMMANDER: \"Fluttuante Comandante\"\n  STR_SECTOID_SOLDIER: \"Sectoide Soldato\"\n  STR_SECTOID_NAVIGATOR: \"Sectoide Navigatore\"\n  STR_SECTOID_MEDIC: \"Sectoide Medico\"\n  STR_SECTOID_ENGINEER: \"Sectoide Ingegnere\"\n  STR_SECTOID_LEADER: \"Sectoide Leader\"\n  STR_SECTOID_COMMANDER: \"Sectoide Comandante\"\n  STR_SNAKEMAN_SOLDIER: \"Uomo-Serpente Soldato\"\n  STR_SNAKEMAN_NAVIGATOR: \"Uomo-Serpente Navigatore\"\n  STR_SNAKEMAN_ENGINEER: \"Uomo-Serpente Ingegnere\"\n  STR_SNAKEMAN_LEADER: \"Uomo-Serpente Leader\"\n  STR_SNAKEMAN_COMMANDER: \"Uomo-Serpente Comandante\"\n  STR_MUTON_SOLDIER: \"Muton Soldato\"\n  STR_MUTON_NAVIGATOR: \"Muton Navigatore\"\n  STR_MUTON_ENGINEER: \"Muton Ingegnere\"\n  STR_ETHEREAL_SOLDIER: \"Etereo Soldato\"\n  STR_ETHEREAL_LEADER: \"Etereo Leader\"\n  STR_ETHEREAL_COMMANDER: \"Etereo Comandante\"\n  STR_CYBERDISC_TERRORIST: \"Cyberdisco Terrorista\"\n  STR_REAPER_TERRORIST: \"Mietitore Terrorista\"\n  STR_CHRYSSALID_TERRORIST: \"Crisalide Terrorista\"\n  STR_CELATID_TERRORIST: \"Celatide Terrorista\"\n  STR_SILACOID_TERRORIST: \"Silacoide Terrorista\"\n  STR_SECTOPOD_TERRORIST: \"Sectopode Terrorista\"\n  STR_UFO_POWER_SOURCE: \"Fonte Energia UFO\"\n  STR_UFO_NAVIGATION: \"Navigazione UFO\"\n  STR_UFO_CONSTRUCTION: \"Costruzione UFO\"\n  STR_ALIEN_FOOD: \"Cibo Alieno\"\n  STR_ALIEN_REPRODUCTION: \"Riproduzione Aliena\"\n  STR_ALIEN_ENTERTAINMENT: \"Svaghi Alieni\"\n  STR_ALIEN_SURGERY: \"Chirurgia Aliena\"\n  STR_EXAMINATION_ROOM: \"Sala Ricerche Aliena\"\n  STR_ALIEN_ALLOYS: \"Leghe Aliene\"\n  STR_ALIEN_HABITAT: \"Habitat Alieno\"\n  STR_POWER_SUIT: \"Tuta Potenziata\"\n  STR_FLYING_SUIT: \"Tuta Volante\"\n  STR_HWP_ROCKETS: \"Razzi Tank\"\n  STR_HWP_FUSION_BOMB: \"Bomba a Fusione Tank\"\n  STR_LASER_WEAPONS: \"Armi Laser\"\n  STR_NEW_FIGHTER_CRAFT: \"Nuovo Veicolo Caccia\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Nuovo Veicolo di Trasporto\"\n  STR_ULTIMATE_CRAFT: \"Veicolo Definitivo\"\n  STR_LASER_PISTOL: \"Pistola Laser\"\n  STR_LASER_RIFLE: \"Fucile Laser\"\n  STR_HEAVY_LASER: \"Laser Pesante\"\n  STR_LASER_CANNON: \"Cannone Laser\"\n  STR_PLASMA_CANNON: \"Cannone Plasma\"\n  STR_FUSION_MISSILE: \"Missile a Fusione\"\n  STR_LASER_DEFENSE: \"Contraerea Laser\"\n  STR_PLASMA_DEFENSE: \"Contraerea Plasma\"\n  STR_FUSION_DEFENSE: \"Difesa a Fusione\"\n  STR_GRAV_SHIELD: \"Scudo Grav\"\n  STR_MIND_SHIELD: \"Scudo Mentale\"\n  STR_PSI_LAB: \"Psi-Lab\"\n  STR_MOTION_SCANNER: \"Scanner di Movimento\"\n  STR_MEDI_KIT: \"Medi-Kit\"\n  STR_TANK_CANNON: \"Tank/Cannone\"\n  STR_TANK_ROCKET_LAUNCHER: \"Tank/Lanciarazzi\"\n  STR_TANK_LASER_CANNON: \"Tank/Cannone Laser\"\n  STR_HOVERTANK_PLASMA: \"Hovertank/Plasma\"\n  STR_HOVERTANK_LAUNCHER: \"Hovertank/Lanciarazzi\"\n  STR_STINGRAY_LAUNCHER: \"Lanciarazzi Stingray\"\n  STR_AVALANCHE_LAUNCHER: \"Lanciarazzi Avalanche\"\n  STR_CANNON: \"Cannone\"\n  STR_FUSION_BALL_LAUNCHER: \"Lanciarazzi a Fusione\"\n  STR_PLASMA_BEAM: \"Raggio Plasma\"\n  STR_STINGRAY_MISSILES: \"Missile Stingray\"\n  STR_AVALANCHE_MISSILES: \"Missile Avalanche\"\n  STR_CANNON_ROUNDS_X50: \"Proiettili Cannone(x50)\"\n  STR_FUSION_BALL: \"Palla a Fusione\"\n  STR_SOLDIER: \"Soldato\"\n  STR_SCIENTIST: \"Scienziato\"\n  STR_ENGINEER: \"Ingegnere\"\n  STR_NORTH_AMERICA: \"Nord America\"\n  STR_ARCTIC: \"Artico\"\n  STR_ANTARCTICA: \"Antartico\"\n  STR_SOUTH_AMERICA: \"Sud America\"\n  STR_EUROPE: \"Europa\"\n  STR_NORTH_AFRICA: \"Nord Africa\"\n  STR_SOUTHERN_AFRICA: \"Sudafrica\"\n  STR_CENTRAL_ASIA: \"Asia Centrale\"\n  STR_SOUTH_EAST_ASIA: \"Sudest Asiatico\"\n  STR_SIBERIA: \"Siberia\"\n  STR_AUSTRALASIA: \"Australasia\"\n  STR_PACIFIC: \"Pacifico\"\n  STR_NORTH_ATLANTIC: \"Nord Atlantico\"\n  STR_SOUTH_ATLANTIC: \"Sud Atlantico\"\n  STR_INDIAN_OCEAN: \"Oceano Indiano\"\n  STR_ALIEN_RESEARCH: \"Ricerche Aliene\"\n  STR_ALIEN_HARVEST: \"Raccolto Alieno\"\n  STR_ALIEN_ABDUCTION: \"Rapimento Alieno\"\n  STR_ALIEN_INFILTRATION: \"Infiltrazione Aliena\"\n  STR_ALIEN_BASE: \"Base Aliena\"\n  STR_ALIEN_TERROR: \"Terrore Alieno\"\n  STR_ALIEN_RETALIATION: \"Rappresaglia Aliena\"\n  STR_ALIEN_SUPPLY: \"Rifornimento Alieno\"\n  STR_MAXIMUM_SPEED: \"Velocità Massima\"\n  STR_HYPER_WAVE_DECODER_UC: \"DECODIFICATORE IPER-ONDE\"\n  STR_SKYRANGER: \"SKYRANGER\"\n  STR_LIGHTNING: \"LIGHTNING\"\n  STR_AVENGER: \"AVENGER\"\n  STR_INTERCEPTOR: \"INTERCEPTOR\"\n  STR_FIRESTORM: \"FIRESTORM\"\n  STR_UFO: \"UFO\"\n  STR_STINGRAY: \"Stingray\"\n  STR_AVALANCHE: \"Avalanche\"\n  STR_CANNON_UC: \"CANNONE\"\n  STR_FUSION_BALL_UC: \"PALLA A FUSIONE\"\n  STR_LASER_CANNON_UC: \"CANNONE LASER\"\n  STR_PLASMA_BEAM_UC: \"RAGGIO PLASMA\"\n  STR_DAMAGE_CAPACITY: \"Capacità di Danno\"\n  STR_WEAPON_POWER: \"Potenza Arma\"\n  STR_WEAPON_RANGE: \"Gittata Arma\"\n  STR_ACCESS_LIFT: \"Ascensore Accesso\"\n  STR_LABORATORY: \"Laboratorio\"\n  STR_WORKSHOP: \"Officina\"\n  STR_SMALL_RADAR_SYSTEM: \"Radar Piccolo\"\n  STR_LARGE_RADAR_SYSTEM: \"Radar Grande\"\n  STR_MISSILE_DEFENSES: \"Contraerea Missili\"\n  STR_GENERAL_STORES: \"Magazzini\"\n  STR_ALIEN_CONTAINMENT: \"Contenimento Alieni\"\n  STR_LASER_DEFENSES: \"Contraerea Laser\"\n  STR_PLASMA_DEFENSES: \"Contraerea Plasma\"\n  STR_FUSION_BALL_DEFENSES: \"Contraerea a fusione\"\n  STR_PSIONIC_LABORATORY: \"Lab. Psionico\"\n  STR_HYPER_WAVE_DECODER: \"Decodificatore Iper-onde\"\n  STR_HANGAR: \"Hangar\"\n  STR_USA: \"USA\"\n  STR_RUSSIA: \"RUSSIA\"\n  STR_UK: \"GRAN BRETAGNA\"\n  STR_FRANCE: \"FRANCIA\"\n  STR_GERMANY: \"GERMANIA\"\n  STR_ITALY: \"ITALIA\"\n  STR_SPAIN: \"SPAGNA\"\n  STR_CHINA: \"CINA\"\n  STR_JAPAN: \"GIAPPONE\"\n  STR_INDIA: \"INDIA\"\n  STR_BRAZIL: \"BRASILE\"\n  STR_AUSTRALIA: \"AUSTRALIA\"\n  STR_NIGERIA: \"NIGERIA\"\n  STR_SOUTH_AFRICA: \"SUDAFRICA\"\n  STR_EGYPT: \"EGITTO\"\n  STR_CANADA: \"CANADA\"\n  STR_TANK: \"Tank\"\n  STR_CIVILIAN: \"Civile\"\n  STR_JAN: \"Gen\"\n  STR_FEB: \"Feb\"\n  STR_MAR: \"Mar\"\n  STR_APR: \"Apr\"\n  STR_MAY: \"Mag\"\n  STR_JUN: \"Giu\"\n  STR_JUL: \"Lug\"\n  STR_AUG: \"Ago\"\n  STR_SEP: \"Set\"\n  STR_OCT: \"Ott\"\n  STR_NOV: \"Nov\"\n  STR_DEC: \"Dic\"\n  STR_INTERNATIONAL_RELATIONS: \"Relazioni Internazionali\"\n  STR_COUNTRY: \"Paese\"\n  STR_FUNDING: \"Finanziamenti\"\n  STR_CHANGE: \"Modifiche\"\n  STR_WEAPON_SYSTEMS: \"SISTEMI DI ARMAMENTO\"\n  STR_HWPS: \"TANK\"\n  STR_DAMAGE_UC_: \"DANNO>{ALT}{0}\"\n  STR_ACCESS_LIFT_UFOPEDIA: \"L'ascensore di accesso permette all'equipaggiamento e al personale di essere trasferito fuori e dentro ad una base sotterranea. È la struttura che viene costruita per prima quando si decide di costruire una base. L'area dell'ascensore è vulnerabile all'intrusione di forze potenzialmente ostili.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Ogni blocco abitativo contiene fino a 50 persone. La struttura fornisce aree per alimentarsi, per il sonno e lo svago.\"\n  STR_LABORATORY_UFOPEDIA: \"In un laboratorio possono lavorare fino a 50 scienziati. I laboratori possono contare sulle più recenti tecnologie per la ricerca sulla biochimica e l'astrofisica. Può contare su un accesso privilegiato ai migliori laboratori di ricerca in tutto il mondo, compresi quelli militari.\"\n  STR_WORKSHOP_UFOPEDIA: \"Un'officina contiene tutte le attrezzature necessarie per costruire l'equipaggiamento disegnato nei laboratori. Possono occupare un'officina fino a 50 ingegnerii, anche se un certo spazio è ovviamente occupato dal materiale stesso.\"\n  STR_SMALL_RADAR_SYSTEM_UFOPEDIA: \"Un sistema di rilevamento piccolo ha un raggio di rilevamento di 300 miglia nautiche ed è collegato ai satelliti per la ricerca a terra. Ogni sistema ha il 5% di possibilità di individuare un oggetto di grandezza media ogni 10 minuti.\"\n  STR_LARGE_RADAR_SYSTEM_UFOPEDIA: \"Un sistema di rilevamento grande ha un raggio di rilevamento di 450 miglia nautiche ed è collegato ai satelliti per la ricerca a terra. Ogni sistema ha il 5% di possibilità di individuare un oggetto di grandezza media ogni 10 minuti.\"\n  STR_MISSILE_DEFENSES_UFOPEDIA: \"Le difese missilistiche forniscono una certa protezione contro le incursioni da parte di veicoli spaziali nemici quando questi tentano di atterrare vicino alla base.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"Tutto l'equipaggiamento, i sistemi di armamenti, le munizioni, i materiali raccolti e i Tank sono sistemati nei magazzini, incluso l'equipaggiamento assegnato ai veicoli presenti negli hangar.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"Si pensa che gli alieni vivi richiedano uno speciale habitat per conservare il loro sistema vitale. La struttura di contenimento può racchiudere fino a 10 forme di vita aliene in speciali alloggiamenti chiusi\"\n  STR_LASER_DEFENSES_UFOPEDIA: \"Le difese laser forniscono protezione contro le incursioni di veicoli nemici.\"\n  STR_PLASMA_DEFENSES_UFOPEDIA: \"Le difese con raggio al plasma forniscono una potente protezione contro le incursioni di veicoli nemici\"\n  STR_FUSION_BALL_DEFENSES_UFOPEDIA: \"I missili a fusione forniscono un'efficace difesa contro gli alieni. Questi missili creano un'implosione ad antimateria che distrugge tutto ciò che si trova all'interno di un certo raggio\"\n  STR_GRAV_SHIELD_UFOPEDIA: \"Lo scudo gravitazionale respinge i veicoli spaziali alieni, che cercano di atterrare vicino alla base, per tutto il tempo in cui si stanno allestendo tutti i sistemi di difesa. In pratica questo raddoppia l'efficacia dei vari sistemi difensivi della base\"\n  STR_MIND_SHIELD_UFOPEDIA: \"Dato che i veicoli alieni si affidano alle onde cerebrali per rilevare la presenza di umani, la più efficace contromisura è schermare le onde cerebrali fuoriuscenti dalla base. Questa struttura ridurrà drasticamente le probabilità di rilevamento da parte di veicoli alieni.\"\n  STR_PSIONIC_LABORATORY_UFOPEDIA: \"Il laboratorio psionico valuta il potenziale psichico di tutti i soldati della base e dà loro l'addestramento necessario all'uso ottimale delle facoltà psioniche. Questo addestramento viene messo a punto alla fine di ogni mese. Le abilità psioniche, congiunte all'amplificatore psionico, possono essere usate per attacchi fondati su tali facoltà nel corso delle varie azioni militari.\"\n  STR_HYPER_WAVE_DECODER_UFOPEDIA: \"Le comunicazioni aliene si basano su un'onda sovradimensionale che viaggia quasi istantanemanete. La struttura di decodifica intercetta le trasmissioni UFO e decodifica i messaggi. In questo modo si ricavano il tipo di UFO, la razza aliena e il tipo di attività.\"\n  STR_HANGAR_UFOPEDIA: \"Ogni hangar può ospitare un solo veicolo. Dispone di tutti gli strumenti per la manutenzione ordinaria dei veicoli XCom, il rifornimento di carburante e le riparazioni. Ogni veicolo spaziale fermo alla base deve avere la disponibilità di un hangar che non può essere usato da altri veicoli, anche se il veicolo a cui è riservata la struttura si trova fuori in missione.\"\n  STR_PISTOL_UFOPEDIA: \"La pistola standard X-Com è un'arma semiautomatica ad alto potenziale, a 12 colpi.\"\n  STR_RIFLE_UFOPEDIA: \"Questo fucile con mirino laser offre una visibilità eccezionale, per cui il tiro risulta estremamente preciso.Usa munizioni da 6,7mm in caricatori da 20 colpi.\"\n  STR_HEAVY_CANNON_UFOPEDIA: \"Il cannone pesante è un'arma devastante ma voluminosa. È molto versatile perché può utilizzare tre tipi di munizioni: perforanti, incendiarie ed esplosive.\"\n  STR_AUTO_CANNON_UFOPEDIA: \"Il cannone automatico combina la versatilità e la potenza del cannone pesante con una maggiore velocità di fuoco.\"\n  STR_ROCKET_LAUNCHER_UFOPEDIA: \"Il lanciarazzi è un congegno guidato dal laser, che può lanciare missili di tre diverse dimensioni.\"\n  STR_LASER_PISTOL_UFOPEDIA: \"La pistola a laser si avvale delle ultimissime scoperte tecnologiche. Ha la maneggevolezza di una pistola, ma con un tiro più veloce e accurato.\"\n  STR_LASER_RIFLE_UFOPEDIA: \"Il fucile laser è una versione più accurata e più potente della precedente pistola.\"\n  STR_HEAVY_LASER_UFOPEDIA: \"Questo laser pesante è voluminoso ma estremamente efficace.\"\n  STR_GRENADE_UFOPEDIA: \"Questa granata standard ha un timer accurato e sofisticato per il controllo di precisione.\"\n  STR_SMOKE_GRENADE_UFOPEDIA: \"Le granate fumogene sono utili perché forniscono protezione in situazioni di esposizione all'attacco nemico. È necessario usarle con cura perché anche il nemico può beneficiare delle loro prestazioni.\"\n  STR_PROXIMITY_GRENADE_UFOPEDIA: \"Una granata di prossimità può essere lanciata come una normale granata ma esplode quando rileva movimento nelle sue vicinanze. Questa granata va usata con molta attenzione.\"\n  STR_HIGH_EXPLOSIVE_UFOPEDIA: \"Questo esplosivo dovrebbe essere usato soltanto per demolizioni. È importante che il personale venga tenuto lontano dai luoghi di demolizione.\"\n  STR_MOTION_SCANNER_UFOPEDIA: \"Questo sofisticato dispositivo usa diversi rivelatori e avanzati algoritmi per identificare unità nemiche in movimento. Tuttavia, richiede un po' di pratica per essere usato efficacemente. Clicca sull'icona dello scanner di movimento sul display tattico. Seleziona 'Usa Scanner' dal menù. Il display dello Scanner mostra una freccia  nel centro diretta nella direzione in cui è rivolto il soldato (il Nord è in alto). I puntini lampeggianti mostrano le unità che si sono mosse di recente. Unità grandi, o unità che si muovono velocemente, produrranno punti più grossi. Unità immobili non vengono rivelate.\"\n  STR_MEDI_KIT_UFOPEDIA: \"Il Kit Medico combina un'attrezzatura curativa con antidolorifici e stimolanti. Per utilizzare il Kit medico devi rivolgerti in direzione del soldato da trattare. Se il soldato è stordito devi posizionarti sul suo corpo. Clicca sull'icona del Kit Medico e seleziona 'usa kit medico' dal menù. {NEWLINE}CURATIVO> Le parti rosse del corpo indicano feriti mortali. Clicca su una parte del corpo ferita. Clicca sul pulsante 'Cura'. Verrà curata una ferita mortale e ripristinata parte della salute.{NEWLINE}STIMOLANTE> Ripristina l'energia e rianima soldati svenuti (storditi). Per rianimare un soldato svenuto devi posizionarti direttamente sul suo corpo.{NEWLINE}ANTIDOLORIFICO> Ripristina il morale dei soldati feriti fino ad un massimo dell'equivalente della salute del soldato persa.\"\n  STR_PSI_AMP_UFOPEDIA: \"L'Amplificatore Psionico può essere usato solo dai soldati con poteri psionici. Durante il combattimento, clicca sull'Amplificatore Psionico, scegli il tipo di attacco e poi scegli un bersaglio con il cursore. Ci sono due tipi di attacco Psionico:{NEWLINE}PANICO> Se l'attacco ha successo, diminuirà il morale del bersaglio e in alcuni casi lo farà andare in panico.{NEWLINE}CONTROLLO MENTALE> Se l'attacco ha successo, prenderai immediatamente il controllo dell'unità nemica,come se fosse tua. Con questi tipi di attacco è più difficile avere successo.\"\n  STR_STUN_ROD_UFOPEDIA: \"Questo strumento può essere usato soltanto nel combattimento ravvicinato per tramortire un organismo vivente senza ucciderlo .\"\n  STR_MIND_PROBE_UFOPEDIA: \"La sonda mentale è un congegno di comunicazione alieno usato per ricavare informazioni direttamente dalle onde cerebrali. Le unità XCom possono usarla in combattimento per visualizzare le caratteristiche di un alieno. Fai clic sulla sonda mentale e sull'opzione \\\"Usa\\\". Poi fai clic sopra un alieno con il cursore.\"\n  STR_PLASMA_PISTOL_UFOPEDIA: \"Le pistole al plasma sono un'arma aliena letale, basata sull'accelerazione di particelle all'interno di un piccolo campo antigravitazionale.\"\n  STR_PLASMA_RIFLE_UFOPEDIA: \"Questa è un'arma potentemente devastante che si basa sull'accelerazione di particelle all'interno di un piccolo campo antigravitazionale.\"\n  STR_HEAVY_PLASMA_UFOPEDIA: \"Questa è una potente arma devastante basata sull'accelerazione di particelle all'interno di un piccolo campo antigravitazionale.\"\n  STR_BLASTER_LAUNCHER_UFOPEDIA: \"Quest'arma può sparare \\\"bombe devastanti\\\" molto potenti. Quando clicchi per far fuoco appariranno dei punti di rotta da seguire con l'arma. Quando sei posizionato sui punti di rotta premi START per evidenziare l'icona. Premi CROCE per lanciare.\"\n  STR_SMALL_LAUNCHER_UFOPEDIA: \"Un piccolo lanciagranate che spara bombe stordenti. Utilissimo per catturare vivi gli alieni.\"\n  STR_ALIEN_GRENADE_UFOPEDIA: \"Questo congegno funziona in modo abbastanza simile ad una granata di terrestre, ma è decisamente più potente.\"\n  STR_SMALL_SCOUT: \"Esploratore Piccolo\"\n  STR_MEDIUM_SCOUT: \"Esploratore Medio\"\n  STR_LARGE_SCOUT: \"Esploratore Grande\"\n  STR_HARVESTER: \"Mietitore\"\n  STR_ABDUCTOR: \"Rapitore\"\n  STR_TERROR_SHIP: \"Nave Terrore\"\n  STR_BATTLESHIP: \"Nave da Guerra\"\n  STR_SUPPLY_SHIP: \"Nave Rifornimento\"\n  STR_RATING: \"VALUTAZIONE> {0}\"\n  STR_RATING_TERRIBLE: \"TERRIBILE!\"\n  STR_RATING_POOR: \"SCARSO!\"\n  STR_RATING_OK: \"OK\"\n  STR_RATING_GOOD: \"BUONO!\"\n  STR_RATING_EXCELLENT: \"ECCELLENTE!\"\n  STR_SCORE: \"PUNTEGGIO\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"RAPPORTO MENSILE SUL PROGETTO X-COM\"\n  STR_MONTH: \"Mese> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"Il consiglio delle nazioni esprime una generale soddisfazione per i tuoi progressi.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"Il consiglio delle nazioni esprime grande soddisfazione per i tuoi eccellenti progressi. Continua a lavorare così.\"\n  STR_COUNCIL_IS_DISSATISFIED: \"Il consiglio delle nazioni esprime la propria insoddisfazione nei confronti dei tuoi risultati. Devi mostrarti più efficace nel contrastare la minaccia aliena o il progetto rischierà di essere terminato.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"Non sei riuscito ad opporti alla minaccia aliena e il consiglio delle nazioni ha deciso di porre termine al progetto. Ogni paese tratterà il problema nel modo più opportuno. Si può solo sperare che si giunga a qualche tipo di accordo con queste forze apparentemente ostili, e che la popolazione riesca a trattare con i visitatori alieni.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} è particolarmente soddisfatta del lavoro svolto per affrontare la minaccia sul proprio territorio ed ha accettato di aumentare il suo finanziamento.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} sono particolarmente contenti dei tuoi progressi nell'affrontare l'incursione aliena locale ed hanno acconsentito ad aumentare i fondi.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} e {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} non è soddisfatto dei tuoi progressi nell'affrontare l'attività aliena nel loro territorio ed ha deciso di ridurre i fondi.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} non sono soddisfatti delle tue abilità nell'affrontare l'attività aliena nel loro territorio e hanno deciso di erogare meno fondi.\"\n  STR_KNOTS: \"{0} nodi\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} ha stipulato un patto segreto con le forze aliene e si sono ritirati dal progetto.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} ha firmato un accordo segreto con forze aliene sconosciute e si è ritirato dal progetto.\"\n  STR_MONTHLY_RATING: \"Valutazione Mensile> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Variazione Fondi> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"Il concilio dei fondi non è contento della tua posizione finanziaria. E' necessario ridurre il debito al di sotto di $1 milione/i affinchè il progetto non venga terminato.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"TRASMISSIONI IPER-ONDE DECODIFICATE\"\n  STR_CRAFT_TYPE: \"TIPO DI VEICOLO\"\n  STR_RACE: \"RAZZA\"\n  STR_MISSION: \"MISSIONE\"\n  STR_ZONE: \"ZONA\"\n  STR_ALLOCATE_RESEARCH: \"Imposta Ricerca\"\n  STR_ALLOCATE_MANUFACTURE: \"Imposta Produzione\"\n  STR_NEW_YORK: \"New York\"\n  STR_WASHINGTON: \"Washington\"\n  STR_LOS_ANGELES: \"Los Angeles\"\n  STR_MONTREAL: \"Montreal\"\n  STR_HAVANA: \"L'Avana\"\n  STR_MEXICO_CITY: \"Città del Messico\"\n  STR_CHICAGO: \"Chicago\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_DALLAS: \"Dallas\"\n  STR_BRASILIA: \"Brasilia\"\n  STR_BOGOTA: \"Bogotà\"\n  STR_BUENOS_AIRES: \"Buenos Aires\"\n  STR_SANTIAGO: \"Santiago\"\n  STR_RIO_DE_JANEIRO: \"Rio de Janeiro\"\n  STR_LIMA: \"Lima\"\n  STR_CARACAS: \"Caracas\"\n  STR_LONDON: \"Londra\"\n  STR_PARIS: \"Parigi\"\n  STR_BERLIN: \"Berlino\"\n  STR_MOSCOW: \"Mosca\"\n  STR_ROME: \"Roma\"\n  STR_MADRID: \"Madrid\"\n  STR_BUDAPEST: \"Budapest\"\n  STR_LAGOS: \"Lagos\"\n  STR_CAIRO: \"Il Cairo\"\n  STR_CASABLANCA: \"Casablanca\"\n  STR_PRETORIA: \"Pretoria\"\n  STR_NAIROBI: \"Nairobi\"\n  STR_CAPE_TOWN: \"Città del Capo\"\n  STR_KINSHASA: \"Kinshasa\"\n  STR_ANKARA: \"Ankara\"\n  STR_DELHI: \"Delhi\"\n  STR_KARACHI: \"Caraci\"\n  STR_BAGHDAD: \"Bagdad\"\n  STR_TEHRAN: \"Teheran\"\n  STR_BOMBAY: \"Bombay\"\n  STR_CALCUTTA: \"Calcutta\"\n  STR_TOKYO: \"Tokyo\"\n  STR_BEIJING: \"Beijing\"\n  STR_BANGKOK: \"Bangkok\"\n  STR_MANILA: \"Manila\"\n  STR_SEOUL: \"Seoul\"\n  STR_SINGAPORE: \"Singapore\"\n  STR_JAKARTA: \"Giakarta\"\n  STR_SHANGHAI: \"Shangai\"\n  STR_HONG_KONG: \"Hong Kong\"\n  STR_NOVOSIBIRSK: \"Novosibirsk\"\n  STR_CANBERRA: \"Canberra\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_MELBOURNE: \"Melbourne\"\n  STR_PERTH: \"Perth\"\n  STR_PSI_TRAINING: \"Addestramento Psionico\"\n  STR_PSIONIC_TRAINING: \"TRAINING PSIONICO\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Capacità disponibile Psi-Lab> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"Forza{NEWLINE}Psionica\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"Abilità Psionica{NEWLINE}/Progresso\"\n  STR_PSI_AMP: \"Psi-Amp\"\n  STR_IN_TRAINING: \"In{NEWLINE}Allenamento?\"\n  STR_TARGETTED_BY: \"PRESO DI MIRA DA:\"\n  STR_WEAPONS_CREW_HWPS: \"ARMI/{NEWLINE}EQUIPAGGI/TANK\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"è a corto di carburante,{NEWLINE}sta tornando alla base\"\n  STR_SOLDIER_LIST: \"Lista Soldati\"\n  STR_RANK_: \"GRADO> {ALT}{0}\"\n  STR_MISSIONS: \"MISSIONI> {ALT}{0}\"\n  STR_KILLS: \"ELIMINATI> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"GUARIGIONE FERITA> {ALT}{0}\"\n  STR_TIME_UNITS: \"UNITA' DI TEMPO\"\n  STR_STAMINA: \"STAMINA\"\n  STR_HEALTH: \"SALUTE\"\n  STR_BRAVERY: \"CORAGGIO\"\n  STR_REACTIONS: \"REAZIONI\"\n  STR_FIRING_ACCURACY: \"MIRA\"\n  STR_THROWING_ACCURACY: \"TIRO\"\n  STR_STRENGTH: \"FORZA\"\n  STR_PSIONIC_STRENGTH: \"FORZA PSIONICA\"\n  STR_PSIONIC_SKILL: \"ABILITÀ PSIONICA\"\n  STR_NEW_RANK: \"PROMOZIONE\"\n  STR_PROMOTIONS: \"Promozioni\"\n  STR_SOLDIERS_UC: \"SOLDATI\"\n  STR_TANK_CANNON_UFOPEDIA: \"I Tank sono studiati per supportare le squadre XCom. La combinazione di grande fpotenza di fuoco e di resistenza della struttura ne fanno degli strumenti preziosi per gli scontri a fuoco in campo aperto. Assicurati che in magazzino ci siano munizioni sufficienti per riarmare i tank. Quando li assegni ad una squadra, i tank si armano automaticamente.\"\n  STR_TANK_ROCKET_LAUNCHER_UFOPEDIA: \"Questo Tank è armato con potenti razzi, devastanti per qualsiasi nemico alieno. Controlla che il magazzino contenga un numero adeguato di razzi per Tank.\"\n  STR_TANK_LASER_CANNON_UFOPEDIA: \"Le armi laser sono un utile complemento per i Tank. Costituiscono un mezzo di fuoco potente e allo stesso tempo non richiedono riserve di munizioni.\"\n  STR_HOVERTANK_PLASMA_UFOPEDIA: \"La tecnologia aliena ha dato nuove possibilità ai Tank. La facilità di manovra in aria e la potenza dei raggi al plasma costituiscono una combinazione letale.\"\n  STR_HOVERTANK_LAUNCHER_UFOPEDIA: \"Questo hovertank ha un lanciabombe a fusione capace di provocare grandi devastazioni. Usalo con molta attenzione. Dovrai costruire i proiettili a fusione per tenere ben armati Tank. Una palla a fusione è un'arma intelligente. Quando vuoi sparare, devi selezionare con il cursore una serie di \\\"destinazioni programmate\\\" e poi fare clic sull'icona di lancio per far partire la palla.\"\n  STR_HEAVY_PLASMA_CLIP_UFOPEDIA: \"Questo caricatore viene usato dal fucile pesante al plasma. Contiene una piccola quantità di Elerium.\"\n  STR_PLASMA_RIFLE_CLIP_UFOPEDIA: \"Questo caricatore viene usato come fonte di energia per un fucile al plasma - un'arma aliena di media potenza. Contiene una piccola quantità di Elerium.\"\n  STR_PLASMA_PISTOL_CLIP_UFOPEDIA: \"Caricatore per la piccola pistola aliena al plasma. Contiene Elerium - la fonte di energia aliena.\"\n  STR_STUN_BOMB_UFOPEDIA: \"La bomba stordente è usata per catturare vivi gli esemplari umani, ma può essere usata anche contro la maggior parte delle specie aliene. Viene sparata da un piccolo lanciabombe.\"\n  STR_ALIEN_RESEARCH_UFOPEDIA: \"La missione di ricerca degli alieni ha come scopo la raccolta di informazioni sulla Terra e sui suoi abitanti. Vengono utilizzati principalmente veicoli piccoli, che atterrano occasionalmente in aree poco popolate senza attirare l'attenzione. Non pare che l'organizzazione XCom, i governi e la popolazione, si preoccupino molto di questa minaccia.\"\n  STR_ALIEN_HARVEST_UFOPEDIA: \"Gli alieni considerano interessante la fauna terrestre per svariate ragioni. Gli animali sono rapiti in segreto e restituiti poi privi di alcuni organi che sono stati espiantati. Questi fatti vengono denunciati particolarmente dopo avvistamenti di UFO. Questa attività aliena suscita preoccupazione presso i governi e grande ansia nella popolazione. Si verifica soprattutto nelle aree agricole. Il concetto di \\\"mietitura aliena\\\" fa pensare ad una possibile \\\"semina\\\" di flora e fauna sulla Terra, da parte degli alieni, i quali adesso verrebbero a falciare il raccolto a loro dovuto.\"\n  STR_ALIEN_ABDUCTION_UFOPEDIA: \"Questa è l'attività aliena più insidiosa. Spesso vengono denunciati rapimenti da parte degli alieni, nonostante il tentativo di questi di rimuovere il ricordo dei fatti dalla memoria delle vittime. I rapiti dichiarano di essere stati sottoposti a umilianti esami fisici, e di aver perfino dovuto subire la fecondazione e altri bizzarri esperimenti genetici. Lo scopo di tutto questo sembra correlato ad esperimenti di mutazione genetica e di manipolazione del materiale genetico degli alieni stessi. Questa attività suscita grande allarme, e si verifica particolarmente nelle aree popolose e nelle grandi città.\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"I governi della Terra possono essere infiltrati da agenti alieni, umani solo nell'aspetto. Questo può avere come conseguenza incontri ai massimi livelli tra gli alieni e i vari governi. I momenti culminanti di queste attività si accompagnano ad un'intensa presenza di UFO nelle aree prossime alle città. Gli alieni di solito propongono un accordo ad un governo della Terra, offrendo alta tecnologia. In cambio, il governo deve lasciare svolgere l'attività agli UFO senza ostacolarli. Questa missione aliena rappresenta la minaccia più grave per il progetto XCom. Se un governo accetta questo tipo di patto, il finanziamento da parte del rispettivo stato cesserà.\"\n  STR_ALIEN_BASE_UFOPEDIA: \"Gli alieni costruiscono basi sotterranee segrete in località remote. Dopo alcuni voli di ricognizione, si avrà un'intensa attività di UFO durante tutto il periodo della costruzione. Si sa che queste basi contengono laboratori per la sperimentazione su umani rapiti, oltre che rifornimenti per le attività nella zona. La presenza di basi aliene fa sì che si rilevi un'intensa attività aliena nel territorio, ma senza la presenza di UFO. Per poter localizzare una base, i mezzi XCom dovranno perlustrare la zona per alcune ore nella speranza di individuarla.\"\n  STR_ALIEN_TERROR_UFOPEDIA: \"Quando gli alieni vogliono seminare il terrore in una città mettono in campo forze speciali di potenza formidabile. I civili vengono minacciati direttamente e i governi sono costretti ad evacuare intere zone. Il loro obiettivo è diffondere il panico tra tutta la popolazione, in modo che i governi abbandonino il progetto XCom.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"Se gli intercettatori XCom stanno avendo particolarmente successo nell'abbattere gli UFO, gli alieni potrebbero intraprendere delle azioni di rappresaglia. Ciò potrebbe portare ad un attacco diretto contro la base XCom. Tuttavia gli alieni per poter attaccare una base devono prima trovarla, e se gli UFO vengono mantenuti a distanza dovrebbe esserci solo un rischio minimo di assalto.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"Una volta che è stata costruita la base aliena, questa è rifornita con regolarità da uno speciale veicolo. Se, al momento dell'atterraggio, viene individuato uno di questi veicoli da rifornimento, si può star certi che nelle vicinanze si troverà una base aliena.\"\n  STR_SMALL_SCOUT_UFOPEDIA: \"Questo piccolo veicolo è usato principalmente per ricognizioni o ricerche. Di solito precede veicoli più grandi all'inizio di una missione aliena.\"\n  STR_MEDIUM_SCOUT_UFOPEDIA: \"Un veicolo da esplorazione di dimensioni medie che non appare troppo minaccioso alle forze terrestri. Di solito anticipa i veicoli di dimensioni più grandi durante le missioni.\"\n  STR_LARGE_SCOUT_UFOPEDIA: \"Il più grande veicolo da esplorazione alieno è un mezzo multiuso utilizzato in tutti i tipi di missioni aliene.\"\n  STR_HARVESTER_UFOPEDIA: \"Il mietitore ha una botola alla base ed è fornito di un congegno di sollevamento per issare a bordo vari tipi di animali. Vengono usati coltelli laser per estrarre il materiale che interessa. Poi le carcasse sono lasciate cadere a terra. Ci sono anche speciali contenitori dove si conservano i vari organi.\"\n  STR_ABDUCTOR_UFOPEDIA: \"Questo veicolo è dotato di una sala per sperimentazioni dove si eseguono interventi orripilanti su soggetti umani. Generalmente le vittime vengono paralizzate per mezzo di forze telepatiche, ma restano coscienti per tutto il tempo in cui giacciono sul lettino operatorio.\"\n  STR_TERROR_SHIP_UFOPEDIA: \"La nave del terrore ha strutture apposite per contenere armi e creature aliene destinate a suscitare terrore. Viene usata per trasportare i terroristi alieni nelle aree fortemente abitate.\"\n  STR_BATTLESHIP_UFOPEDIA: \"La nave da guerra è il veicolo alieno più potente. Il suo uso è fondamentale per le missioni degli alieni. Porta armi potentissime e un equipaggio composto da numerosi alieni.\"\n  STR_SUPPLY_SHIP_UFOPEDIA: \"Il veicolo da rifornimento viene usato nel corso della costruzione delle basi aliene oppure per rifornire basi già in funzione. Porta dei container pieni di cibo alieno e celle di riproduzione.\"\n  STR_DISMANTLE: \"Smantella\"\n  STR_FACILITY_IN_USE: \"STRUTTURA IN USO\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"IMPOSSIBILE SMANTELLARE STRUTTURA!{SMALLLINE}Tutte le strutture della base devono essere collegate all'ascensore di accesso.\"\n  STR_TRANSFER_ITEMS_TO: \"Trasferire Oggetti a {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"CELLA DI CONTENIMENTO ALIENA NON PRESENTE!{SMALLLINE}Gli alieni vivi hanno bisogno di una cella di contenimento per sopravvivere.\"\n  STR_AMOUNT_AT_DESTINATION: \"NUMERO A{NEWLINE}DESTINAZIONE\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"L'alieno muore per mancanza di strutture di contenimento.\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"ALLOGGIAMENTI NON DISPONIBILI!{SMALLLINE}La base di destinazione non ha spazio sufficiente nei quartieri abitativi per l'equipaggio assegnato al veicolo.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"SPAZIO NEL MAGAZZINO INSUFFICIENTE!{SMALLLINE}La base di destinazione non ha abbastanza spazio per l'equipaggiamento assegnato al veicolo.\"\n  STR_ITEMS_ARRIVING: \"Oggetti in Arrivo\"\n  STR_DESTINATION_UC: \"DESTINAZIONE\"\n  STR_PISTOL: \"Pistola\"\n  STR_PISTOL_CLIP: \"Car. Pistola\"\n  STR_RIFLE: \"Fucile\"\n  STR_RIFLE_CLIP: \"Car. Fucile\"\n  STR_HEAVY_CANNON: \"Cannone Pesante\"\n  STR_HC_AP_AMMO: \"Colpi HC-AP\"\n  STR_HC_HE_AMMO: \"Colpi HC-HE\"\n  STR_HC_I_AMMO: \"Colpi HC-I\"\n  STR_AUTO_CANNON: \"Auto-Cannone\"\n  STR_AC_AP_AMMO: \"Colpi AC-AP\"\n  STR_AC_HE_AMMO: \"Colpi AC-HE\"\n  STR_AC_I_AMMO: \"Colpi AC-I\"\n  STR_ROCKET_LAUNCHER: \"Lanciarazzi\"\n  STR_SMALL_ROCKET: \"Razzo Piccolo\"\n  STR_LARGE_ROCKET: \"Razzo Grande\"\n  STR_INCENDIARY_ROCKET: \"Razzo Incendiario\"\n  STR_GRENADE: \"Granata\"\n  STR_SMOKE_GRENADE: \"Granata Fumogena\"\n  STR_PROXIMITY_GRENADE: \"Granata di Prossimità\"\n  STR_HIGH_EXPLOSIVE: \"Super-Esplosivo\"\n  STR_STUN_ROD: \"Storditore\"\n  STR_HEAVY_PLASMA: \"Plasma Pesante\"\n  STR_HEAVY_PLASMA_CLIP: \"Car. Plasma Pesante\"\n  STR_PLASMA_RIFLE: \"Fucile Plasma\"\n  STR_PLASMA_RIFLE_CLIP: \"Car. Fucile Plasma\"\n  STR_PLASMA_PISTOL: \"Pistola Plasma\"\n  STR_PLASMA_PISTOL_CLIP: \"Car. Pistola Plasma\"\n  STR_BLASTER_LAUNCHER: \"Lanciatore Blaster\"\n  STR_BLASTER_BOMB: \"Bomba Blaster\"\n  STR_SMALL_LAUNCHER: \"Lanciatore Stordente\"\n  STR_STUN_BOMB: \"Bomba Stordente\"\n  STR_ALIEN_GRENADE: \"Granata Aliena\"\n  STR_ELERIUM_115: \"Elerium-115\"\n  STR_MIND_PROBE: \"Sonda Mentale\"\n  STR_SECTOID_CORPSE: \"Cadavere Sectoide\"\n  STR_SNAKEMAN_CORPSE: \"Cadavere Uomo-Serpente\"\n  STR_ETHEREAL_CORPSE: \"Cadavere Etereo\"\n  STR_MUTON_CORPSE: \"Cadavere Muton\"\n  STR_FLOATER_CORPSE: \"Cadavere Fluttuante\"\n  STR_CELATID_CORPSE: \"Cadavere Celatide\"\n  STR_SILACOID_CORPSE: \"Cadavere Silacoide\"\n  STR_CHRYSSALID_CORPSE: \"Cadavere Crisalide\"\n  STR_REAPER_CORPSE: \"Cadavere Mietitore\"\n  STR_SECTOPOD_CORPSE: \"Cadavere Sectopode\"\n  STR_CYBERDISC_CORPSE: \"Cadavere Cyberdisco\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"Munizioni insufficenti per armare TANK{SMALLLINE}Ogni TANK richiede {0} {1}.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Insufficienti armamenti per equipaggiare la squadra intera\"\n  STR_MARS_CYDONIA_LANDING: \"Marte: Approdo a Cydonia\"\n  STR_MARS_CYDONIA_LANDING_BRIEFING: \"Il tuo veicolo Avenger è atterrato a Cydonia, sulla superficie di Marte. Le nostre informazioni dicono che una delle piramidi contiene un ascensore che accede ad un complesso sotterraneo. Dopo aver raccolto tutti i tuoi soldati nell'area dell'ascensore, fai clic sull'icona indicata con \\\"Interrompi la missione\\\" per continuare con la fase seguente.\"\n  STR_MARS_THE_FINAL_ASSAULT: \"Marte: l'Assalto Finale\"\n  STR_MARS_THE_FINAL_ASSAULT_BRIEFING: \"L'ascensore della piramide porta i tuoi stanchi soldati nelle viscere del pianeta, dove trovano un labirinto di tunnel e celle. Il cervello alieno si trova nascosto in qualche punto del labirinto. Se si vuole che la Terra non venga ridotta in stato di schiavitù, bisogna che questo cervello venga distrutto.{NEWLINE}{NEWLINE}Buona fortuna!\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Occorre ricercare prima {NEWLINE}{0}{NEWLINE}per poter produrre{NEWLINE}{1}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"Gli alieni hanno distrutto la base indifesa {0}\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"Alcuni agenti X-Com hanno localizzato una base aliena a {0}\"\n  STR_STANDOFF: \"STATO DI ATTESA\"\n  STR_CAUTIOUS_ATTACK: \"ATTACCO CAUTO\"\n  STR_STANDARD_ATTACK: \"ATTACCO STANDARD\"\n  STR_AGGRESSIVE_ATTACK: \"ATTACCO AGGRESSIVO\"\n  STR_DISENGAGING: \"SGANCIAMENTO\"\n  STR_UFO_HIT: \"UFO COLPITO!\"\n  STR_UFO_CRASH_LANDS: \"UFO PRECIPITATO A TERRA!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Riduci a Stato di Attesa\"\n  STR_UFO_RETURN_FIRE: \"UFO RISPONDE AL FUOCO!\"\n  STR_INTERCEPTOR_DAMAGED: \">>> INTERCEPTOR DANNEGGIATO <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> INTERCEPTOR DISTRUTTO <<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"UFO SUPERA INTERCEPTOR!\"\n  STR_ALIENS_TERRORISE: \"GLI ALIENI SPARGONO TERRORE!\"\n  STR_LONG_RANGE_DETECTION: \"Rilevazione a Lungo Raggio\"\n  STR_STORES_UC: \"SCORTE\"\n  STR_DIFFICULTY_LEVEL: \"Livello Difficoltà\"\n  STR_INTERCEPT: \"INTERCETTA\"\n  STR_BASES: \"BASI\"\n  STR_GRAPHS: \"GRAFICI\"\n  STR_UFOPAEDIA_UC: \"UFOPEDIA\"\n  STR_OPTIONS_UC: \"OPZIONI\"\n  STR_FUNDING_UC: \"FINANZIAMENTI\"\n  STR_5_SECONDS: \"5 sec\"\n  STR_1_MINUTE: \"1 min\"\n  STR_5_MINUTES: \"5 min\"\n  STR_30_MINUTES: \"30 min\"\n  STR_1_HOUR: \"1 ora\"\n  STR_1_DAY: \"1 g.\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"Valutazione Roster X-Com\"\n  STR_ENTER_NAME: \"Inserisci Nome\"\n  STR_PERFORMANCE_RATING: \"Valutazione Prestazione\"\n  STR_VICTORY_DATE: \"Data Vittoria\"\n  STR_ELECTRO_FLARE: \"Elettro-bagliore\"\n  STR_ELECTRO_FLARE_UFOPEDIA: \"Questo congegno compatto, al momento del lancio, produce un bagliore accecante, che illumina le unità nemiche tutt'attorno durante le missioni notturne.\"\n  STR_MONTHLY_COSTS: \"Costi Mensili\"\n  STR_CRAFT_RENTAL: \"Costo Noleggio\"\n  STR_SALARIES: \"Stipendi\"\n  STR_BASE_MAINTENANCE: \"Manutenzione Base\"\n  STR_COST_PER_UNIT: \"Costo per unità\"\n  STR_QUANTITY: \"Quantità\"\n  STR_TOTAL: \"Totale\"\n  STR_IN_PSIONIC_TRAINING: \"In Addestramento Psionico\"\n  STR_BLASTER_BOMB_UFOPEDIA: \"Questo congegno è una bomba ad alto potenziale esplosivo che viene comandata da un sistema intelligente. È lanciato da un lancia-bombe apposito.\"\n  STR_FRONT_ARMOR: \"Armatura Frontale\"\n  STR_LEFT_ARMOR: \"Armatura Sinistra\"\n  STR_RIGHT_ARMOR: \"Armatura Destra\"\n  STR_REAR_ARMOR: \"Armatura Posteriore\"\n  STR_UNDER_ARMOR: \"Armatura Inferiore\"\n  STR_ROUNDS: \"Colpi\"\n  STR_UNIT: \"UNITA'> {0}\"\n  STR_ENERGY: \"ENERGIA\"\n  STR_MORALE: \"VOLONTA'\"\n  STR_ARMOR_: \"ARMATURA> {0}\"\n  STR_FRONT_ARMOR_UC: \"ARMATURA FRONTALE\"\n  STR_LEFT_ARMOR_UC: \"ARMATURA SINISTRA\"\n  STR_RIGHT_ARMOR_UC: \"ARMATURA DESTRA\"\n  STR_REAR_ARMOR_UC: \"ARMATURA POSTERIORE\"\n  STR_SKILLS: \"ABILITA'> {0}\"\n  STR_LEVEL: \"LIVELLO> {0}\"\n  STR_HEAD: \"TESTA\"\n  STR_TORSO: \"TORSO\"\n  STR_RIGHT_ARM: \"BRACCIO DX\"\n  STR_LEFT_ARM: \"BRACCIO SX\"\n  STR_RIGHT_LEG: \"GAMBA DX\"\n  STR_LEFT_LEG: \"GAMBA SX\"\n  STR_PAIN_KILLER: \"ANTIDOLORIFICO\"\n  STR_STIMULANT: \"STIMOLANTE\"\n  STR_HEAL: \"CURA\"\n  STR_TIME_UNITS_SHORT: \"UdT>{ALT}{0}\"\n  STR_WEIGHT: \"Peso>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"Reazione>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"A.PSI>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"F.PSI>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Artefatto Alieno\"\n  STR_AMMO_ROUNDS_LEFT: \"MUNIZ.:{NEWLINE}COLPI{NEWLINE}DISP.={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Antidolorifico>{ALT}{0}{ALT}{NEWLINE}Stim>{ALT}{1}{ALT}{NEWLINE}Cura>{ALT}{2}\"\n  STR_THROW: \"Lancia\"\n  STR_AUTO_SHOT: \"Colpo Automatico\"\n  STR_SNAP_SHOT: \"Colpo Rapido\"\n  STR_AIMED_SHOT: \"Colpo Mirato\"\n  STR_STUN: \"Stordisci\"\n  STR_PRIME_GRENADE: \"Innesca Granata\"\n  STR_USE_SCANNER: \"Usa Scanner\"\n  STR_USE_MEDI_KIT: \"Usa Medi-Kit\"\n  STR_LAUNCH_MISSILE: \"Lancia Missile\"\n  STR_ACCURACY_SHORT: \"Mira>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Unità di Tempo Insufficienti!\"\n  STR_NOT_ENOUGH_ENERGY: \"Energia Insufficiente!\"\n  STR_NO_ROUNDS_LEFT: \"Non ci sono più colpi!\"\n  STR_NO_AMMUNITION_LOADED: \"Munizioni non caricate!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Munizioni non adatte all'arma!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"Arma già carica!\"\n  STR_NO_LINE_OF_FIRE: \"Non c'è linea di fuoco!\"\n  STR_GRENADE_IS_ACTIVATED: \"Granata attivata!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Granata Disattivata!\"\n  STR_THERE_IS_NO_ONE_THERE: \"Qui non c'è nessuno!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Impossibile usare oggetti alieni senza ricerca!\"\n  STR_OUT_OF_RANGE: \"Fuori tiro!\"\n  STR_UNABLE_TO_THROW_HERE: \"Non è possibile lanciare qui!\"\n  STR_SET_TIMER: \"Regola Timer\"\n  STR_HIDDEN_MOVEMENT: \"MOVIMENTO NASCOSTO\"\n  STR_TURN: \"TURNO> {0}\"\n  STR_SIDE: \"LATO> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Premi un tasto per continuare\"\n  STR_MIND_CONTROL: \"Controllo Mentale\"\n  STR_PANIC_UNIT: \"Unità di Panico\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Attacco Mentale Riuscito\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Controllo Mentale riuscito\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}è andato in Berserk\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}è andata in Berserk\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}è andato in Panico\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}è andato in Panico\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Alieni\"\n  STR_RIGHT_HAND: \"MANO DX\"\n  STR_LEFT_HAND: \"MANO SX\"\n  STR_RIGHT_SHOULDER: \"SPALLA DX\"\n  STR_LEFT_SHOULDER: \"SPALLA SX\"\n  STR_BACK_PACK: \"ZAINO\"\n  STR_BELT: \"CINTA\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}è sotto Controllo Alieno\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}è sotto Controllo Alieno\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}ha perso i sensi\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}ha perso i sensi\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}è deceduto per una ferita fatale\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}è deceduto per una ferita fatale\"\n  STR_USE_MIND_PROBE: \"Usa Sonda Mentale\"\n  STR_FATAL_WOUNDS: \"FERITE MORTALI\"\n  STR_UNDER_ARMOR_UC: \"ARMATURA INFERIORE\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"UdT riservate per Colpo Rapido\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"UdT riservate per Colpo Automatico\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"UdT riservate per Colpo Mirato\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Unità di Tempo riservate per l'inginocchiamento\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"UdT riservati per Inginocchiarsi e Sparare\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} unità nel velivolo X-Com\"\n    many: \"{N} unità nel velivolo X-Com\"\n    other: \"{N} Unità nel velivolo X-Com\"\n  STR_UNITS_OUTSIDE:\n    one: \"{N} unità rimasta fuori\"\n    many: \"{N} unità rimaste fuori\"\n    other: \"{N} Unità rimaste fuori\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} unità nell'entrata\"\n    many: \"{N} unità nell'entrata\"\n    other: \"{N} Unità nell'entrata\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} unità nell'uscita obiettivo\"\n    many: \"{N} unità nell'uscita obiettivo\"\n    other: \"{N} Unità nell'uscita obiettivo\"\n  STR_ABORT_MISSION_QUESTION: \"Interrompi Missione?\"\n  STR_CORPSE: \"Cadavere\"\n  STR_UNLOAD_CRAFT: \"Scarica\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}è stato ucciso\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}è stato ucciso\"\n  STR_HIT_MELEE: \"Colpito\"\n  STR_GROUND: \"A TERRA\"\n  STR_LIVING_QUARTERS_PLURAL: \"Alloggi\"\n  STR_LIST_ITEM: \"OGGETTO\"\n  STR_PERSONAL_ARMOR_UFOPEDIA: \"Costruita con i metalli alieni recentemente scoperti, questa nuova armatura da ai tuoi uomini chance di sopravvivenza maggiori contro la minaccia aliena.\"\n  STR_POWER_SUIT_UFOPEDIA: \"Una nuova e potente protezione per i soldati, questa armatura è alimentata da una sorgente energetica di Elerium che amplifica significativamente la velocità e la forza di chi la indossa. Offre la migliore protezione per le truppe in combattimento.\"\n  STR_FLYING_SUIT_UFOPEDIA: \"Una versione migliorata della tuta potenziata, che incorpora tecnologia aliena di navigazione anti-gravitazionale, permettendo piena libertà di movimento sul campo di battaglia.\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"Non ci sono alieni sopravvissuti all'impatto,{NEWLINE}Recupero automatico avviato\"\n  STR_RESET: \"Reset\"\n  STR_MEMORIAL: \"Memoriale\"\n  STR_DATE_UC: \"DATA\"\n  STR_SOLDIERS_RECRUITED_UC: \"SOLDATI ARRUOLATI>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"SOLDATI CADUTI>{ALT}{0}\"\n  MAP_CULTA: \"Fattoria\"\n  MAP_FOREST: \"Foresta\"\n  MAP_JUNGLE: \"Giungla\"\n  MAP_MOUNT: \"Montagna\"\n  MAP_DESERT: \"Deserto\"\n  MAP_POLAR: \"Polare\"\n  MAP_URBAN: \"Città\"\n  MAP_UBASE: \"Base Aliena\"\n  MAP_XBASE: \"Base X-COM\"\n  MAP_MARS: \"Marte\"\n  STR_MIXED: \"Misto\"\n  STR_REMOVE_SELECTED: \"Rimuovi Selezionati\"\n  STR_LIVE_ALIENS: \"Alieni Vivi\"\n  STR_DEAD_ALIENS: \"Elementi{NEWLINE}Rifiutati\"\n  STR_UNDER_INTERROGATION: \"Già{NEWLINE}Studiati\"\n  STR_CONTAINMENT_EXCEEDED: \"LIMITE DI CONTENIMENTO ALIENI SUPERATO!{SMALLLINE}Spazio di contenimento insufficiente a {0}. Necessaria rimozione degli alieni in eccesso (questi ultimi moriranno).\"\n  STR_MANAGE_CONTAINMENT: \"Gestisci Contenimento Alieni\"\n  STR_STORAGE_EXCEEDED: \"CAPACITA' DI MAGAZZINO SUPERATA!{SMALLLINE}Capacità di magazzino insufficiente a {0}. Devi vendere gli oggetti in eccesso.\"\n  STR_GO_TO_BASE: \"Vai alla Base\"\n  STR_MELEE_ACCURACY: \"MELEE\"\n  STR_SELL_PRODUCTION: \"VENDI\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Entrambe le mani devono essere vuote!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Oggetti insufficienti per copiare il modello!\"\n  STR_UNLOAD_WEAPON: \"Scarica arma\"\n  STR_ALL_ITEMS: \"Tutti gli Oggetti\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"NON È CONSENTITO ULTERIORE EQUIPAGGIAMENTO A BORDO!{SMALLLINE}Ti è consentito portare al massimo {N} oggetto di equipaggiamento su questo veicolo.\"\n    many: \"NON È CONSENTITO ULTERIORE EQUIPAGGIAMENTO A BORDO!{SMALLLINE}Ti è consentito portare al massimo {N} oggetti di equipaggiamento su questo veicolo.\"\n    other: \"NON È CONSENTITO ULTERIORE EQUIPAGGIAMENTO A BORDO!{SMALLLINE}Ti è consentito portare al massimo {N} oggetti di equipaggiamento su questo veicolo.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}CENTRO DI CONTROLLO DISTRUTTO{SMALLLINE}Trova la strada per l'entrata e abbbandona.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"Le strutture X-Com non possono essere costruite sott'acqua \"\n  STR_LEVEL_SHORT: \"{0}\"\n  STR_PERSONNEL: \"Personale\"\n  STR_CRAFT_ARMAMENT: \"Velivoli e Armamenti\"\n  STR_COMPONENTS: \"Componenti\"\n  STR_SOLDIERS_RECRUITED: \"Soldati arruolati\"\n  STR_SOLDIERS_LOST: \"Soldati caduti\"\n  STR_TOTAL_UFOS: \"UFO rilevati\"\n  STR_TOTAL_ALIEN_BASES: \"Basi aliene scovate\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"FPS\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"APS\"\n  FEMALE_CIVILIAN: \"Civile, Femmina\"\n  MALE_CIVILIAN: \"Civile, Maschio\"\n  CYBERDISC_WEAPON: \"Arma Cyberdisco\"\n  REAPER_WEAPON: \"Arma Mietitore\"\n  CHRYSSALID_WEAPON: \"Arma Crisalide\"\n  CELATID_WEAPON: \"Arma Celatide\"\n  SILACOID_WEAPON: \"Arma Silacoide\"\n  SECTOPOD_WEAPON: \"Arma Sectopode\"\n  ZOMBIE_WEAPON: \"Arma Zombie\"\n  ALIEN_PSI_WEAPON: \"Arma Psionica Aliena\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/ja.yml",
    "content": "ja:\n  STR_AVENGER_UFOPEDIA: \"戦闘輸送艇。エイリアンのテクノロジーをフルに応用しており、いかなるUFOよりも高速に飛行することができる。さらに、宇宙飛行も可能。\"\n  STR_INTERCEPTOR_UFOPEDIA: \"地球の最高技術を集めて製造された迎撃用戦闘機。パルス・デトネーション・エンジンを2基搭載しており、特殊シールドを施された人工頭脳は迎撃を自動で行う。\"\n  STR_LIGHTNING_UFOPEDIA: \"円盤型の戦闘輸送艇。UFOに搭載されていた推進装置の複製品を主エンジンとして使用している。\"\n  STR_SKYRANGER_UFOPEDIA: \"兵員輸送機。ジェット輸送機としては最も高速で飛行することが可能。またVTOL(垂直離着陸)性能も有する。\"\n  STR_FIRESTORM_UFOPEDIA: \"戦闘艇。この一人乗りの戦闘艇はクラシックなエイリアンの円盤のデザインを模倣しており、推進装置もUFOに搭載されていた物の複製である。\"\n  STR_STINGRAY_UFOPEDIA: \"空対空ミサイル。特殊シールドによって電子装置を保護している。\"\n  STR_AVALANCHE_UFOPEDIA: \"核弾頭を装備する空対空ミサイル。破壊力は大きいが、非常に重い。\"\n  STR_CANNON_UFOPEDIA: \"高性能カノン砲。この砲から発射される徹甲弾は16インチの鋼鉄を貫通する。\"\n  STR_FUSION_BALL_UFOPEDIA: \"このランチャーは、球形のミサイルを反物質反応の力により発射する。ミサイルは重力波を発生して目標を破壊する。\"\n  STR_LASER_CANNON_UFOPEDIA: \"この通常型レーザー砲は、反物質反応を利用している。\"\n  STR_PLASMA_BEAM_UFOPEDIA: \"重力ビームは重力場の内方破壊を引き起こす。\"\n  STR_SECTOID_UFOPEDIA: \"セクトイドのヒエラルキーは、下は兵士から上は強力なサイオニック能力を持つ指導者で構成されている。サイオニックパワーは、敵の士気をくじくことができるばかりか、精神をもコントロールすることができる。彼らはたわむれに人間の誘拐や、キャトル・ミューティレーションを行う。誘拐した人間は、人間社会に潜入させるクローン開発用や、遺伝材料を抽出することに用いられ、家畜は栄養素と遺伝素材の摂取のために用いられる。この種族は、彼らのハチの様な社会の能率を高めるために、優れたハイブリッド種を開発したいという欲望をもっているようだ。\"\n  STR_SECTOID_AUTOPSY: \"セクトイドの解剖\"\n  STR_SECTOID_AUTOPSY_UFOPEDIA: \"解剖により、この種の消化器官は退化しており、その構造も単純であることが判明した。脳と目は非常に発達している。その構造から推測すると、遺伝的な改造か突然変異かと思われる。小さな口と鼻はほとんど機能していないようだが指の間の水かきや偏平足から、この種の起源は水生であると考えられる。この種には生殖器官がないので、どの様に生殖するかについては不明だが、この事からも、この種が遺伝子操作により作られた種であると推測される。\"\n  STR_SNAKEMAN_UFOPEDIA: \"この種族は非常に厳しい環境で進化した。彼らは非常にタフで、極端な気温の変化にも耐えることができる。彼らの動作は、生体器官の全てを守るヘビの様な巨大な足にたよっている。彼らの目的は、ただ単に略奪することであり、軍事的な命令は他の種族により行われている様である。\"\n  STR_SNAKEMAN_AUTOPSY: \"スネークマンの解剖\"\n  STR_SNAKEMAN_AUTOPSY_UFOPEDIA: \"その皮膚は大変固く耐熱性がある。心臓血管系は、水圧原理を使用する筋肉系の一部である。つまり機械にたとえれば、心臓が油圧ポンプで筋肉が油圧シリンダの働きをしている。この生物の唯一の真の筋肉は心臓である。生殖系は非常に能率的で無性生殖であり、各個体が体中に常に50個の卵を宿している。放置しておくと、この種は地球の生物にとってひどい脅威となるであろう。 \"\n  STR_ETHEREAL_UFOPEDIA: \"この生き物には恐ろしい精神力があって、テレパシーによる意志伝達やテレキネシス能力をもつ。弱々しく見えるこの生き物の肉体は、強力な精神力で支えられている。我々が認識している物理の法則に反しているので、テレキネシスがどの様に作用しているのか見当もつかない。どんな戦闘状況でも彼らは非常に危険な存在である。なぜなら見えない場所から強力な精神攻撃を行ってくるからである。彼らは目標達成の為の実務を他の種族に任せているようで、地球上にはほとんど現れない。\"\n  STR_ETHEREAL_AUTOPSY: \"エセリアルの解剖\"\n  STR_ETHEREAL_AUTOPSY_UFOPEDIA: \"この生き物は肉体的な退化が進んでおり、生体機能を維持することは困難に見える。筋肉はほとんどなく内器官は発育不全のようで、感覚器官も目を含めて、全く機能していないと思われる。しかし、脳はよく発達しており、体の大部分の血液はここで消費される。外部からのサポートなしでこの生き物がどのように生命を維持しているのかは謎である。\"\n  STR_MUTON_UFOPEDIA: \"人間に類似したこの生物は、強じんな肉体を持ち知能も高い。彼らは生の肉ならばどんなものでも食べ尽くす異様な食欲があるが、地球に住む食肉動物のように、これは彼らにとっても生命を維持する為に必要な事である。この種は‘エセリアル’として知られる種族から送られるテレパシー命令に依存している様で、テレパシーのつながりが切れると彼らの精神システムは破壊され、やがて死んでしまう。彼ら全員に戦闘能力を高めるためのサイバーインプラントが埋め込まれており、指導者の下で動く下級兵士であることは明白である。\"\n  STR_MUTON_AUTOPSY: \"ミュートンの解剖\"\n  STR_MUTON_AUTOPSY_UFOPEDIA: \"この生き物の皮膚は有機的に合成された後に、体に移植された防護装甲である。心臓血管系や感覚器官の能力を強化するために、様々な人工臓器が移植されているが、生殖器官は手術で取り除かれているようだ。これらの不運な生き物は、明らかに闘争と征服のみの一生を送ることを運命づけられている。装甲を貫くだけの弾丸は、彼らの強化された皮膚には何の効力もない。\"\n  STR_CELATID_UFOPEDIA: \"この生物は空中を浮遊するという不思議な能力を持つ。人間の脳波を探知することができるようで、うまく隠れていても人間に向かって動く。一度目標を発見すると、セラチドは地面に降りて腐食性の毒液の滴を射出する。この生き物は非常な速度で増殖する能力がある。また、なぜかミュートン族と行動を共にすることが多い。\"\n  STR_CELATID_AUTOPSY: \"セラチドの解剖\"\n  STR_CELATID_AUTOPSY_UFOPEDIA: \"体の中心部には小さなバイオ・メカ装置があるが、この装置は自然に進化した反重力推進システムのようである。毒の袋は一番大きな器官で、独立した脳はない。また、消化系や生殖系も識別できない。別の小さな器官には新しい個体を急速に成長させる芽がある。\"\n  STR_SILACOID_UFOPEDIA: \"このシリコンを主体とする生物は、大量の熱を発生する。その熱には岩を砕くほどの力があり、その熱い芯で砕いた岩を栄養として摂取する。知能はあまり発達しておらず、体内に移植されたコントロール装置またはテレパシーによってコントロールされる。この種はミュートンと一緒に行動する。\"\n  STR_SILACOID_AUTOPSY: \"シラコイドの解剖\"\n  STR_SILACOID_AUTOPSY_UFOPEDIA: \"この生き物の芯は非常に熱く、消化系の基盤になっている。また、そのユニークな筋肉系はすごい力とスピードをもっている。その岩のような皮膚は、火炎や焼夷弾などの弾薬では損なわれない。 \"\n  STR_CHRYSSALID_UFOPEDIA: \"カニに似たこの生き物の爪は、白兵戦では強力な武器となる。この生物の高い代謝能力と筋力の強さは、戦闘時のスピードと器用さにつながる。また、人間を殺さずに卵をを植え付け、さらにゾンビに変えてしまう毒を注入する。植え付けられた卵は、ゾンビ化した犠牲者の体内でふ化すると体を破裂させて別の個体として出現する。クリサリドは、スネークマンと行動を共にする。 \"\n  STR_CHRYSSALID_AUTOPSY: \"クリサリドの解剖\"\n  STR_CHRYSSALID_AUTOPSY_UFOPEDIA: \"この生物の外骨格は非常に固いが、意外にも爆発性の弾薬にはもろい。脳は大変発達しており、脳細胞の成長速度も速い。この生物は他の生体内に産み付ける卵を20個もっている。この生物は宇宙人の非常に効果的なテロ兵器である。\"\n  STR_FLOATER_UFOPEDIA: \"フローターは主として兵士やテロリストの役割を持つ。彼らは生まれつきの野獣であり、さらに恐るべき戦士に仕立てるために遺伝工学的に工夫され、人工頭脳などの移植で強化されている。下半身と内蔵の大部分は手術で取り除かれ、代わりに生命維持装置が取り付けられている。この装置には反重力機関も搭載されていて、そのお陰で体を空中に浮かせられる。\"\n  STR_FLOATER_AUTOPSY: \"フローターの解剖\"\n  STR_FLOATER_AUTOPSY_UFOPEDIA: \"この生き物は手術で徹底的に変えられている。体の中心にある機械は生命維持装置で、心臓や肺や消化器などのすべての機能を代替している。この装置のおかげで、非常に厳しい環境下でも生存できる。脳は我々の脳より小さいが感覚器官はよく発達している。 \"\n  STR_REAPER_UFOPEDIA: \"この２足食肉動物のあごは強力で、食欲も旺盛である。この生物には、その活動をコントロールしている装置が数種類移植されている。この生物の原始的な食肉本能は、恐怖を与える事と破壊活動以外にはほとんど役に立たない。リーパーは一般にフローターと行動を共にする。\"\n  STR_REAPER_AUTOPSY: \"リーパーの解剖\"\n  STR_REAPER_AUTOPSY_UFOPEDIA: \"リーパーは‘脳’と‘心臓’を２つずつ持ち、重傷を受けても活動することができる。しかし、毛皮でおおわれた皮膚は非常に燃えやすいので、焼夷弾などの武器には弱い。 \"\n  STR_SECTOPOD_UFOPEDIA: \"セクトポッドは強力なプラズマ光線兵器を内蔵するロボットである。この機械獣を‘エセリアル’がテレパシーでコントロールしている。セクトポッドは宇宙人が所有する最も強力な脅威の武器である。\"\n  STR_SECTOPOD_AUTOPSY: \"セクトポッドの解剖\"\n  STR_SECTOPOD_AUTOPSY_UFOPEDIA: \"このロボットは対弾性の高い、とりわけプラズマ兵器に対する防御力にすぐれた強化装甲により保護されている。しかし、センサー回路部だけは、レーザー兵器などの攻撃に弱いようである。\"\n  STR_CYBERDISC_UFOPEDIA: \"この小型の円盤はプラズマ兵器を搭載した恐るべき自動兵器である。反重力推進装置を備え、起伏の大きい地形での移動にも非常に適している。テロと破壊を目的としており、セクトイドの指示で行動する。\"\n  STR_CYBERDISC_AUTOPSY: \"サイバーディスクの解剖\"\n  STR_CYBERDISC_AUTOPSY_UFOPEDIA: \"このサイバーディスクは強固な装甲を持ち、特に爆発性の弾薬による攻撃に対する防御力は優秀である。ただし、この標本は損傷が酷いため、反重力装置の機能を理解するのは困難である。\"\n  STR_UFO_POWER_SOURCE_UFOPEDIA: \"エイリアンの宇宙船のパワー源は反物質リアクターで、これはエレリウム(元素115)を用いて強力な重力波および他の形態のエネルギーを生成する。物質からエネルギーへの転換率は99%という驚くべき効率で行われるために、少量のエレリウムで莫大な量のパワーを生み出すことができる。このユニットは宇宙人の合金を用いれば簡単に複製できる。\"\n  STR_UFO_NAVIGATION_UFOPEDIA: \"エイリアンの宇宙船は精巧なコンピュータを用いて、大気圏内および宇宙空間を航行する。そのシステムは光処理装置を基とし、複雑怪奇なネットワークを構築している。制御インターフェースは比較的単純である。ナビゲータはパワー源で生成された重力波を制御して、宇宙船をあらゆる方向へ移動させることができる。このシステムは人間にも簡単に使用でき、さらにエイリアンの合金や他の構成要素を用いれば、複製することも可能だ。\"\n  STR_UFO_CONSTRUCTION_UFOPEDIA: \"エイリアンの宇宙船は、パワー源、航法システム、特殊合金製の艇体の、3つの主な構成部品でできている。特に艇体は重力波を制御できるように設計されている。さらにパワー源への燃料供給には、少量のエレリウムが必要である。構造上の原則が理解でき、各構成部分の機能が明らかになれば、この種の宇宙船を建造することも可能となるであろう。\"\n  STR_ALIEN_FOOD_UFOPEDIA: \"これらの部屋にはさまざまな酵素が含まれており、その酵素で牛やその他の動物、さらに人間さえも消化してしまう。そしてそれらを液状化して消化促進食品のように、おそらく直接血液へと注入される。このことから、食物は地球上で調達しているということが分かる。\"\n  STR_ALIEN_REPRODUCTION_UFOPEDIA: \"この部屋にはエイリアンの胎児が置かれている。コンテナのデザインから考えて、この過程を用いるエイリアンは実験室での繁殖活動に完全に依存していると思われる。豊富な栄養素を与えられて、胎児は確実に急成長を遂げている。この生産ラインシステムにより短期間に何千体ものクローンを生成することもできる。この過程は人間や、エイリアンと人間との混血種の繁殖にも簡単に流用できる。\"\n  STR_ALIEN_ENTERTAINMENT_UFOPEDIA: \"これらの球形の物体はエイリアンに娯楽を提供する機能を持っていると思われる。サイオニック回路が脳の中枢を刺激して、幻覚剤に似た効果をもたらす。エイリアンが文化的、娯楽的活動を行う存在であるということを証明する証拠は、おそらくこれだけである。\"\n  STR_ALIEN_SURGERY_UFOPEDIA: \"この手術設備に備えられているレーザーカッターで、牛やその他の動物の体から、さまざまな臓器類を切り取る。キャトルミューティレーションがあちこちで行われているが、これらエイリアンの奇妙な活動も、このような設備の存在によって説明できるだろう。おそらく、切断された体は、栄養補給や遺伝操作の実験などの目的に利用されていると思われる。\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"これまでに何千人もの人々がエイリアンに誘拐されたことがあると証言しており、その中には、何度も誘拐されたと主張する者もいる。しかし、事実はそれ以上に恐ろしい。人間を誘拐し、調査し、監視するのである。最高の標本と判断されればその遺伝材料を抽出する。女性であれば、人間とエイリアンのハイブリッド胎児を移植し、数カ月後に成長した胎児を回収する。エイリアンがどんな邪悪な目的を持っているかを誰が知ろうか?\"\n  STR_ALIEN_ALLOYS_UFOPEDIA: \"エイリアンの宇宙船は、特殊な性質を備えた合金で作られている。この合金は極めて軽く耐久性があり、電磁気学的方法により鋳造することができる。この金属は複製可能で、様々な製造過程で用いることができる。\"\n  STR_ELERIUM_115_UFOPEDIA: \"この元素はある特定の粒子の状態で衝撃を与えると、莫大な反物質パワーを発生するという変わった特性を備えている。これにより、重力波および他の形態のエネルギーが創り出される。我々の太陽系には存在しない物質であり、複製することは不可能である。\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"我々が地上で負け戦を戦っているということは明らかである。エイリアンの部隊は数の上でも我々を圧倒している。我々にできることはせいぜいその侵攻のスピードを遅らせることだけかもしれない。しかし、エイリアンの存在の源を攻撃すれば人類にも希望が持てるであろう。{NEWLINE}{NEWLINE}我々の研究機関は太陽系内のどこかに作戦基地が存在すると考えている。我々はできる限り早くこの場所を突き止めなければならない。その為にはまずエイリアンのリーダーを捕らえて取り調べを行い、より詳しい情報を得る必要がある。{NEWLINE}{NEWLINE}大型のUFOにはリーダーが最低一人は乗り込んでいるはずである。\"\n  STR_THE_MARTIAN_SOLUTION_UFOPEDIA: \"現時点の我々の調査の結果、エイリアンの基地が火星に存在する事を確認した。基地は巧妙に隠され、あらゆる兵器の製造およびクローン用の設備を備えており、次々と地上に潜入者を送り込んでいる。そこにはまた、全作戦をコントロールするコンピュータが存在しているようだ。蜂の様な階層社会を形成するエイリアンには、一種の女王蜂が存在するらしい。この社会構造こそエイリアンの根本的な弱点である。この‘脳’が除去されてしまえば、'肉体'は直ちに滅びてしまうであろう。{NEWLINE}{NEWLINE}手遅れになる前に、我々は研究のペースアップを計らねばならない。そのためにも最高ランクのエイリアンの司令官を捕らえなければならない。{NEWLINE}{NEWLINE}司令官は戦艦及び宇宙人基地にのみ存在する。\"\n  STR_CYDONIA_OR_BUST_UFOPEDIA: \"エイリアンの部隊はサイドニアの地下基地からコントロールされていることが、様々な研究の結果から判明した。サイドニアは火星でも珍しい地域で、5角錐のピラミッドと、人間の顔のような巨大な建造物が特徴である。{NEWLINE}{NEWLINE}火星には何百万年もの昔にサイドニアに文明が発展していたのだが、なぜ、それが滅びてしまったのか、またそこで行われていたエイリアンの活動とどのような関係があるのかは、現在でも明らかではない。しかし、どのような説明がなされるにしても、サイドニアに襲撃隊を送る必要がある。{NEWLINE}{NEWLINE}エイリアンを倒すためには、全てを支配している‘脳’を破壊しなければならない。最大の攻撃力を備えているアベンジャーを、我々の戦力に加える必要がある。もはや学べることは、全て学んだ。我々の待つべき物は、サイドニア襲撃の結果のみである。\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"現場を中央に表示 - 時間=5秒\"\n  STR_CANCEL_UC: \"取消\"\n  STR_NONE: \"なし\"\n  STR_UNKNOWN: \"0%\"\n  STR_POOR: \"25%\"\n  STR_AVERAGE: \"50%\"\n  STR_GOOD: \"75%\"\n  STR_EXCELLENT: \"95%\"\n  STR_BUILD_NEW_BASE_UC: \"新基地を建設する\"\n  STR_BASE_INFORMATION: \"基地情報\"\n  STR_EQUIP_CRAFT: \"格納庫へ行く\"\n  STR_BUILD_FACILITIES: \"施設を建設する\"\n  STR_RESEARCH: \"研究する\"\n  STR_MANUFACTURE: \"製造する\"\n  STR_TRANSFER_UC: \"移動する\"\n  STR_PURCHASE_RECRUIT: \"購入する/雇う\"\n  STR_SACK: \"解雇する\"\n  STR_SELL_SACK_UC: \"売る/解雇する\"\n  STR_GEOSCAPE_UC: \"ジオスケープ\"\n  STR_NAME: \"名前\"\n  STR_AREA: \"エリア\"\n  STR_BUILD_NEW_BASE: \"新基地を建設する\"\n  STR_CANCEL: \"取消\"\n  STR_COST_UC: \"建設費用>\"\n  STR_CONSTRUCTION_TIME_UC: \"建設期間>\"\n  STR_DAY:\n    other: \"{N} 日\"\n  STR_HOUR:\n    other: \"{N} 時間\"\n  STR_MAINTENANCE_UC: \"維持費>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"軍事施設\"\n  STR_CURRENT_RESEARCH: \"研究プロジェクト\"\n  STR_SCIENTISTS_AVAILABLE: \"配属可能な科学者>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"配属済み科学者>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"研究室内の空きスペース>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"研究課題\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"科学者\"\n  STR_PROGRESS: \"経過\"\n  STR_NEW_PROJECT: \"研究課題の選択\"\n  STR_CANCEL_PROJECT: \"プロジェクトを取り消す\"\n  STR_NEW_RESEARCH_PROJECTS: \"研究課題\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"配属可能な科学者>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"実験室内の有効スペース>{ALT}{0}\"\n  STR_INCREASE: \"増加\"\n  STR_DECREASE: \"減少\"\n  STR_START_PROJECT: \"この課題の研究開始\"\n  STR_CURRENT_PRODUCTION: \"現在の生産\"\n  STR_ENGINEERS_AVAILABLE: \"配属可能な技術者>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"配属済み技術者>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"工作室内の有効スペース>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"現在の資金>{ALT}{0}\"\n  STR_ITEM: \"アイテム\"\n  STR_ENGINEERS__ALLOCATED: \"技術者数\"\n  STR_UNITS_PRODUCED: \"生産\"\n  STR_TOTAL_TO_PRODUCE: \"生産数済/総\"\n  STR_COST__PER__UNIT: \"生産単価\"\n  STR_DAYS_HOURS_LEFT: \"残りの日/時\"\n  STR_NEW_PRODUCTION: \"生産物の選択\"\n  STR_PRODUCTION_ITEMS: \"生産アイテム\"\n  STR_CATEGORY: \"カテゴリー\"\n  STR_START_PRODUCTION: \"生産をスタートする\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} 1ユニットの作成に要するエンジニアの工数\"\n  STR_COST_PER_UNIT_: \"ユニットごとの費用>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"必要な作業スペース>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"必要な特殊材料\"\n  STR_ITEM_REQUIRED: \"必要なアイテム\"\n  STR_UNITS_REQUIRED: \"必要なユニット\"\n  STR_UNITS_AVAILABLE: \"使用可能なユニット\"\n  STR_STOP_PRODUCTION: \"生産を中止する\"\n  STR_ENGINEERS_AVAILABLE_UC: \"配属可能な技術者>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"作業場内の有効スペース>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"月間収入 >{ALT}{0}\"\n  STR_INCREASE_UC: \"増加\"\n  STR_DECREASE_UC: \"減少\"\n  STR_UNITS_TO_PRODUCE: \"生産するユニット\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"購入する/雇う\"\n  STR_COST_OF_PURCHASES: \"購入価格>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"ユニットごとの費用\"\n  STR_QUANTITY_UC: \"数量\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"待機:総数\"\n  STR_SOLDIERS: \"戦闘員\"\n  STR_SCIENTISTS: \"科学者\"\n  STR_ENGINEERS: \"技術者\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"使用済みスペース:有効スペース\"\n  STR_LIVING_QUARTERS: \"居住区\"\n  STR_STORES: \"倉　庫\"\n  STR_LABORATORIES: \"研究室\"\n  STR_WORK_SHOPS: \"工作室\"\n  STR_HANGARS: \"格納庫\"\n  STR_SHORT_RANGE_DETECTION: \"短距離探知\"\n  STR_DEFENSE_STRENGTH: \"防衛力\"\n  STR_TRANSFERS_UC: \"受領\"\n  STR_TRANSFERS: \"移動\"\n  STR_ARRIVAL_TIME_HOURS: \"到着時間(時間)\"\n  STR_COST_: \"費用>{ALT}{0}\"\n  STR_AREA_: \"エリア>{ALT}{0}\"\n  STR_BASE_NAME: \"基地の名前は?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"アクセス・リフトの位置を選択する\"\n  STR_TRANSFER: \"移動\"\n  STR_AMOUNT_TO_TRANSFER: \"移動 総数\"\n  STR_SELECT_DESTINATION_BASE: \"移動先を選択する\"\n  STR_COST: \"費用\"\n  STR_VICTORY_1: \"部屋に入ると、探し求めていた宇宙人の脳があった。 発砲しようとすると、ベースの画面を通して脳が語りかけてくる。脳は、自分が生き延びなければならない理由をまず聞いてから引き金を引くかどうかを決意してくれと懇願する...\"\n  STR_VICTORY_2: \"脳が語り始める。'今人類が火星と呼んでいる惑星は何百万年も前には活発な星だった。地球と同様、我々の文明が不毛の惑星にそのような生命をもたらしたのだ。数百万年もの間、我々は地球を訪れては人類を遺伝子的に進化させてきた。人類に我々を倒すことはできない。人類は我々の一部なのだ...\"\n  STR_VICTORY_3: \"ここが火星文明の中心である。このピラミッドは地上のピラミッドが建つ数百万年前に、人類の祖先である種族が築いた。どの惑星であろうと我々の手中にあるのだ。。。すぐに人類もこのパワーを手に入れることができる。我々はただ人類に協力を求めているだけである...'\"\n  STR_GAME_OVER_1: \"宇宙人は全人類を全滅させ、都市を破壊し、空や海を汚染しようと試みる。地球軍の抵抗は、遥かに優れたテクノロジーの前では無益である。生き残った世代も宇宙人の大虐殺から逃れる際、恐ろしい目にあう。奴隷キャンプへ集められ、正体不明の帝国の一部となっている宇宙人の植民地へと地球を改造する為に使役される。\"\n  STR_GAME_OVER_2: \"XComプロジェクトにより得た知識は永遠に失われてしまう。あなたは地球を救うことができなかった。\"\n  STR_VICTORY_4: \"エイリアンの脳は高温のプラズマ・ビームにより遮断され、エイリアンの全戦力は打破される。\"\n  STR_VICTORY_5: \"火星を失ったエイリアンは、じきに地球も失う事になる。XComの研究によって間もなく人類は繁栄を取り戻し、火星の所有権も主張するだろう。エイリアンの脅威は去った。しかし、いつまでこの状態が続くのかを知る者は誰もいない...\"\n  STR_YOU_HAVE_FAILED: \"あなたは宇宙人の猛攻撃をくい止めるのに失敗した。資金を提供している国々は、テクノロジーや繁栄、平和を約束するという宇宙人との条約に一国、また一国と調印していく。しかし、宇宙人の真の計画はじきに明らかになる...\"\n  STR_TOTAL_UC: \"合計\"\n  STR_INCOME: \"収入\"\n  STR_EXPENDITURE: \"支出\"\n  STR_MAINTENANCE: \"維持\"\n  STR_BALANCE: \"残高\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"エリア別のUFOの活動\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"国別のUFOの活動\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"エリア別のXComの活動\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"国別のXComの活動\"\n  STR_FINANCE: \"財政\"\n  STR_DATE_FIRST: \"{0}日\"\n  STR_DATE_SECOND: \"{0}日\"\n  STR_DATE_THIRD: \"{0}日\"\n  STR_DATE_FOURTH: \"{0}日\"\n  STR_FINANCE_THOUSANDS: \"1000ドル\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"{0}{NEWLINE}の製造に必要な材料が{NEWLINE}{1}{NEWLINE}で不足しています。\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"{1}{NEWLINE}で{NEWLINE}{0}{NEWLINE}の製造に必要な資金が足りません\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"{1}{NEWLINE}で{NEWLINE}{0}{NEWLINE}の製造が完了しました\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"{1}{NEWLINE}で{NEWLINE}{0}{NEWLINE}の工事が完了しました\"\n  STR_OK_5_SECONDS: \"OK - 5秒\"\n  STR_RESEARCH_COMPLETED: \"研究終了\"\n  STR_VIEW_REPORTS: \"レポートを見る\"\n  STR_WE_CAN_NOW_RESEARCH: \"現在研究可能です\"\n  STR_WE_CAN_NOW_PRODUCE: \"現在生産可能です\"\n  STR_SUNDAY: \"日曜日\"\n  STR_MONDAY: \"月曜日\"\n  STR_TUESDAY: \"火曜日\"\n  STR_WEDNESDAY: \"水曜日\"\n  STR_THURSDAY: \"木曜日\"\n  STR_FRIDAY: \"金曜日\"\n  STR_SATURDAY: \"土曜日\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"{0}が {2}で{1}を補給するのは十分ではありません\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"{2}で{1}を備えるには{0}が足りません\"\n  STR_UFO_IS_NOT_RECOVERED: \"UFOは未回収です\"\n  STR_UFO_IS_RECOVERED: \"UFOを回収しました\"\n  STR_CRAFT_IS_LOST: \"輸送機を失いました\"\n  STR_TERROR_CONTINUES: \"テロ活動継続中\"\n  STR_ALIENS_DEFEATED: \"エイリアンは打倒されました\"\n  STR_BASE_IS_LOST: \"基地を失いました\"\n  STR_BASE_IS_SAVED: \"基地は助かりました\"\n  STR_ALIEN_BASE_STILL_INTACT: \"エイリアンの基地は依然無傷\"\n  STR_ALIEN_BASE_DESTROYED: \"エイリアンの基地は破壊された\"\n  STR_ALIENS_KILLED: \"XComに射殺された宇宙人\"\n  STR_ALIEN_CORPSES_RECOVERED: \"回収された宇宙人の死体\"\n  STR_LIVE_ALIENS_RECOVERED: \"XComが捕虜にした宇宙人\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"回収された宇宙人の製造品\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"破壊した敵基地の制御装置\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"宇宙人に殺された民間人\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"XComに誤殺された民間人\"\n  STR_CIVILIANS_SAVED: \"無事に救助された民間人\"\n  STR_XCOM_OPERATIVES_KILLED: \"戦闘で死亡したXCom隊員\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"行方不明になったXCom隊員\"\n  STR_TANKS_DESTROYED: \"破壊されたHWP(戦車)\"\n  STR_XCOM_CRAFT_LOST: \"失われたXComの戦闘艇\"\n  STR_UFO_RECOVERY: \"UFO回収\"\n  STR_ALIEN_BASE_RECOVERY: \"エイリアン基地の回収\"\n  STR_BASE_UNDER_ATTACK: \"{0}は攻撃を受けています!\"\n  STR_BASE_DEFENSES_INITIATED: \"基地防衛戦開始\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"重力シールドでUFO撃退!\"\n  STR_FIRING: \"攻撃中\"\n  STR_HIT: \"迎撃成功!\"\n  STR_UFO_DESTROYED: \"UFOを破壊しました!\"\n  STR_MISSED: \"迎撃失敗!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"アイテムを売る/人員を解雇する\"\n  STR_VALUE_OF_SALES: \"販売価格> {ALT}{0}\"\n  STR_FUNDS: \"資金> {ALT}{0}\"\n  STR_SELL_SACK: \"売る/解雇する\"\n  STR_VALUE: \"価格\"\n  STR_CRAFT_: \"搭乗機> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"不時着UFO回収\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"UFOの内部またはその周囲にエイリアンの生存者が存在する可能性があるので、充分注意せよ。敵の全ユニットを倒すかまたは無力化した後、UFOの残骸や兵器死体の回収を行うことができる。任務を中断する場合は全ての隊員を輸送機に戻した後'任務中断'を実行せよ。\"\n  STR_UFO_GROUND_ASSAULT: \"UFO地上襲撃戦\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"着陸地点を捜索し、可能ならばUFO内部に侵入せよ。敵の全ユニットを倒すか、または無力化すると任務は達成される。その後、UFOや兵器、エイリアンの死体の回収を行うことができる。任務を中断する場合は全ての隊員を輸送機に戻した後'任務中断'を実行せよ。\"\n  STR_BASE_DEFENSE: \"基地防衛\"\n  STR_BASE_UC_: \"基地> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"エイリアンの強襲艇が付近に着陸し、我々の基地は深刻な危険に晒されている。規定によって非戦闘員と航空機は退避済である。エイリアンはハンガーの扉やアクセスリフトから侵入を試みるはずだ。基地の防衛は最重要任務であり、基地の存続を賭けた戦いである。'任務中断'を実行した場合は敗北を認めることになり、基地を失う。\"\n  STR_ALIEN_BASE_ASSAULT: \"エイリアン基地襲撃戦\"\n  STR_ALIEN_BASE_ASSAULT_BRIEFING: \"XComはエイリアンの基地へ侵入した。コントロール・センターを破壊して基地の機能を完全に停止させるのが、任務の目標である。任務は全ての敵を倒すか、または'任務中断'を選択すると終了する。やむを得ず撤退する場合には、全隊員が脱出エリアにいることを確認せよ。\"\n  STR_CYDONIA_BRIEFING: \"襲撃部隊はついにサイドニアに到着した。火星スフィンクスの近くにある巨大地下基地に侵入して、エイリアンの全活動をコントロールするブレインを破壊せよ。人類の運命はこの作戦に委ねられている。諸君の健闘を祈る。\"\n  STR_TERROR_MISSION: \"テロ鎮圧戦\"\n  STR_TERROR_MISSION_BRIEFING: \"全ての敵のユニットを倒すか無力化すると任務が達成される。エイリアンの脅威を一掃して、エリア内の民間人の救助に全力を挙げて努めなければならない。やむを得ず撤退する場合には、全ての隊員を輸送機に戻してから'任務中断'を実行すること。\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"生産する航空機のための空き格納庫がありません!{SMALLLINE}格納庫で待機中の航空機を別の基地に移動するか、新しい格納庫を建設して、保管場所を確保してから生産してください。\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"購入する航空機のための空き格納庫がありません!{SMALLLINE}格納庫で待機中の航空機を別の基地に移動するか、新しい格納庫を建設して、保管場所を確保してから購入してください。\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"移動する航空機のための空き格納庫がありません!{SMALLLINE}移動先で待機中の航空機をその他の基地に移動するか、移動先に新しい格納庫を建設してから航空機を移動してください。\"\n  STR_CANNOT_BUILD_HERE: \"そこに施設を建設することはできません!{SMALLLINE}新しい施設は、すでに建設されている施設のとなりに建設してください。\"\n  STR_NO_FREE_ACCOMODATION: \"移動することができません!{SMALLLINE}移動先の基地に、人員を収容するスペースがありません。\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"作業スペースが足りません!{SMALLLINE}新しい工作室を建設するか、他の製造プロジェクトの作業スペースを削減して下さい。\"\n  STR_NOT_ENOUGH_MONEY: \"資金不足です!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"貯蔵スペースがありません!{SMALLLINE}新しい倉庫を建設するか、別の基地へ貯蔵品を移動して、スペースを確保して下さい。\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"居住スペースがありません!{SMALLLINE}新しい居住区を建設するか、別の基地へ人員を移動して、スペースを確保して下さい。\"\n  STR_LAUNCH_INTERCEPTION: \"出撃命令\"\n  STR_CRAFT: \"航空機\"\n  STR_STATUS: \"ステイタス\"\n  STR_BASE: \"所属基地\"\n  STR_READY: \"発進待機中\"\n  STR_OUT: \"出撃中\"\n  STR_REPAIRS: \"修理中\"\n  STR_REFUELLING: \"燃料補給中\"\n  STR_REARMING: \"兵器搭載中\"\n  STR_TARGET: \"ターゲット: {0}\"\n  STR_WAY_POINT: \"ガイド・ポイント\"\n  STR_ARE_YOU_SURE_CYDONIA: \"本当に、この戦闘艇をサイドニア襲撃任務に出撃させるのですか?\"\n  STR_YES: \"はい\"\n  STR_NO: \"いいえ\"\n  STR_SELECT_DESTINATION: \"目的地を選択する\"\n  STR_CYDONIA: \"サイドニア\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"新基地の建設場所を指定する\"\n  STR_RETURN_TO_BASE: \"基地へ戻る\"\n  STR_SELECT_NEW_TARGET: \"新しいターゲットを選択する\"\n  STR_PATROL: \"パトロール\"\n  STR_STATUS_: \"ステイタス>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"被弾破損 - 基地へ帰投中\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"燃料不足 - 基地へ帰投中\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"ミッション完了-帰投せよ\"\n  STR_PATROLLING: \"パトロール中\"\n  STR_TAILING_UFO: \"UFO追跡中\"\n  STR_INTERCEPTING_UFO: \"UFO攻撃中-{0}\"\n  STR_RETURNING_TO_BASE: \"基地へ帰投中\"\n  STR_DESTINATION_UC_: \"目標: {0}\"\n  STR_BASE_UC: \"基地>{ALT}{0}\"\n  STR_SPEED_: \"速度>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"最高速度>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"高度>{ALT}{0}\"\n  STR_VERY_LOW: \"超低空\"\n  STR_LOW_UC: \"低空\"\n  STR_HIGH_UC: \"高空\"\n  STR_VERY_HIGH: \"超高空\"\n  STR_FUEL: \"燃料>{ALT}{0}\"\n  STR_WEAPON_ONE: \"武器プライマリー>{ALT}{0}\"\n  STR_NONE_UC: \"なし\"\n  STR_ROUNDS_: \"弾薬>{ALT}{0}\"\n  STR_WEAPON_TWO: \"武器セカンダリ>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"武装/装備/搭乗員の変更\"\n  STR_BASE_: \"基地>{0}\"\n  STR_NAME_UC: \"名前\"\n  STR_AMMO_: \"弾薬>{ALT}{0}\"\n  STR_CREW: \"搭乗員\"\n  STR_EQUIPMENT_UC: \"装備\"\n  STR_ARMOR: \"アーマー\"\n  STR_MAX: \"最大>{ALT}{0}\"\n  STR_ROOKIE: \"新兵\"\n  STR_SQUADDIE: \"伍長\"\n  STR_SERGEANT: \"軍曹\"\n  STR_CAPTAIN: \"大尉\"\n  STR_COLONEL: \"大佐\"\n  STR_COMMANDER: \"司令官\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"{0}の部隊を選択\"\n  STR_SORT_BY: \"ソートの条件...\"\n  STR_ORIGINAL_ORDER: \"元の順列\"\n  STR_MISSIONS2: \"ミッション\"\n  STR_KILLS2: \"倒した数\"\n  STR_WOUND_RECOVERY2: \"治療中\"\n  STR_SPACE_AVAILABLE: \"有効スペース>{ALT}{0}\"\n  STR_SPACE_USED: \"使用済みスペース>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"使用済みスペース\"\n  STR_RANK: \"階級\"\n  STR_WOUNDED: \"負傷\"\n  STR_EQUIPMENT_FOR_CRAFT: \"{0}の装備\"\n  STR_DEFENSE_VALUE: \"防衛力\"\n  STR_HIT_RATIO: \"迎撃成功率\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}は{ALT}{1}の近くで着陸準備完了\"\n  STR_BEGIN_MISSION: \"任務を開始しますか?\"\n  STR_SELECT_ARMAMENT: \"武装を選択する\"\n  STR_AMMUNITION_AVAILABLE: \"弾薬使用可能\"\n  STR_ARMAMENT: \"武装\"\n  STR_NOT_AVAILABLE: \"N.A.\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"{0}のアーマーを選択\"\n  STR_TYPE: \"タイプ\"\n  STR_PERSONAL_ARMOR_UC: \"バトルスーツ\"\n  STR_POWER_SUIT_UC: \"パワースーツ\"\n  STR_FLYING_SUIT_UC: \"フライスーツ\"\n  STR_SELECT_ARMOR: \"アーマーの選択\"\n  STR_NORTH: \"北　\"\n  STR_NORTH_EAST: \"北東\"\n  STR_EAST: \"東　\"\n  STR_SOUTH_EAST: \"南東\"\n  STR_SOUTH: \"南　\"\n  STR_SOUTH_WEST: \"南西\"\n  STR_WEST: \"西　\"\n  STR_NORTH_WEST: \"北西\"\n  STR_SELECT_ACTION: \"行動を選択する\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"迎撃を続ける\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"攻撃せずに追跡する\"\n  STR_VERY_LARGE: \"非常に大きい\"\n  STR_LARGE: \"大きい\"\n  STR_MEDIUM_UC: \"中型\"\n  STR_SMALL: \"小さい\"\n  STR_VERY_SMALL: \"非常に小さい\"\n  STR_GROUNDED: \"地面\"\n  STR_DETECTED: \"発見しました\"\n  STR_SIZE_UC: \"サイズ\"\n  STR_ALTITUDE: \"高度\"\n  STR_HEADING: \"進路\"\n  STR_SPEED: \"速度\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"UFOを中央に表示する - 時間=5秒\"\n  STR_TRACKING_LOST: \"追跡失敗\"\n  STR_REDIRECT_CRAFT: \"行動の選択\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"最後にUFOが確認された地点へ行く\"\n  STR_UFO_: \"UFO-{0}\"\n  STR_ALIEN_BASE_: \"宇宙人基地-{0}\"\n  STR_CRASH_SITE_: \"不時着地点-{0}\"\n  STR_LANDING_SITE_: \"着陸地点-{0}\"\n  STR_WAY_POINT_: \"ガイド・ポイント-{0}\"\n  STR_TERROR_SITE: \"テロ活動地点-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{1}は{0}に到達した\"\n  STR_NOW_PATROLLING: \"現在パトロール中\"\n  STR_ALIEN_ORIGINS: \"エイリアンの起源\"\n  STR_THE_MARTIAN_SOLUTION: \"火星の解明\"\n  STR_CYDONIA_OR_BUST: \"サイドニア\"\n  STR_UFOPAEDIA: \"UFOペディア\"\n  STR_XCOM_CRAFT_ARMAMENT: \"Xcomの機体と兵器\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"HWP\"\n  STR_WEAPONS_AND_EQUIPMENT: \"武器と装具\"\n  STR_ALIEN_ARTIFACTS: \"エイリアンの製造品\"\n  STR_BASE_FACILITIES: \"基地の設備\"\n  STR_ALIEN_LIFE_FORMS: \"エイリアンの生態\"\n  STR_ALIEN_RESEARCH_UC: \"エイリアンの研究\"\n  STR_UFO_COMPONENTS: \"UFO構成部品\"\n  STR_UFOS: \"UFO\"\n  STR_SELECT_ITEM: \"アイテムを選択せよ\"\n  STR_ACCELERATION: \"加速力>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"燃料搭載量>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"武装搭載数>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"ダメージ容量>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"搭載スペース>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"HWP搭載数>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"破壊力\"\n  STR_RANGE: \"射程距離\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"命中精度\"\n  STR_RE_LOAD_TIME: \"再装填に要する時間\"\n  STR_SECONDS: \"{0}秒\"\n  STR_DAMAGE_ARMOR_PIERCING: \"徹甲弾\"\n  STR_DAMAGE_INCENDIARY: \"焼夷弾\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"りゅう弾\"\n  STR_DAMAGE_LASER_BEAM: \"レーザー\"\n  STR_DAMAGE_PLASMA_BEAM: \"プラズマ\"\n  STR_DAMAGE_STUN: \"スタン\"\n  STR_DAMAGE_MELEE: \"格闘\"\n  STR_DAMAGE_ACID: \"酸\"\n  STR_DAMAGE_SMOKE: \"煙幕\"\n  STR_SHOT_TYPE: \"射撃タイプ\"\n  STR_ACCURACY_UC: \"命中精度\"\n  STR_TIME_UNIT_COST: \"TUコスト\"\n  STR_DAMAGE_UC: \"弾頭/破壊力\"\n  STR_AMMO: \"弾薬\"\n  STR_SHOT_TYPE_AUTO: \"3連\"\n  STR_SHOT_TYPE_SNAP: \"急速\"\n  STR_SHOT_TYPE_AIMED: \"精密\"\n  STR_CONSTRUCTION_TIME: \"建造期間\"\n  STR_CONSTRUCTION_COST: \"建造費\"\n  STR_MAINTENANCE_COST: \"維持費\"\n  STR_LOW: \"低い\"\n  STR_MEDIUM: \"中位\"\n  STR_HIGH: \"高い\"\n  STR_CRAFT_WEAPON: \"航空機の武装\"\n  STR_CRAFT_AMMUNITION: \"武装用の弾薬\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"HWP\"\n  STR_WEAPON: \"兵器\"\n  STR_AMMUNITION: \"弾薬\"\n  STR_EQUIPMENT: \"装備\"\n  STR_ALIEN_CORPSE: \"宇宙人の死体\"\n  STR_UFO_COMPONENT: \"UFO構成部品\"\n  STR_PERSONAL_ARMOR: \"個人用装甲\"\n  STR_RAW_MATERIALS: \"原材料\"\n  STR_HWP_CANNON_SHELLS: \"HWP用砲弾\"\n  STR_ALIEN: \"エイリアン\"\n  STR_SECTOID: \"セクトイド\"\n  STR_SNAKEMAN: \"スネークマン\"\n  STR_ETHEREAL: \"エセリアル\"\n  STR_MUTON: \"ミュートン\"\n  STR_FLOATER: \"フローター\"\n  STR_CELATID: \"セラチド\"\n  STR_SILACOID: \"シラコイド\"\n  STR_CHRYSSALID: \"クリサリド\"\n  STR_ZOMBIE: \"ゾンビ\"\n  STR_REAPER: \"リーパー\"\n  STR_SECTOPOD: \"セクトポッド\"\n  STR_CYBERDISC: \"サイバーディスク\"\n  STR_LIVE_COMMANDER: \"司令官\"\n  STR_LIVE_LEADER: \"リーダー\"\n  STR_LIVE_ENGINEER: \"技術者\"\n  STR_LIVE_MEDIC: \"衛生兵\"\n  STR_LIVE_NAVIGATOR: \"ナビゲーター\"\n  STR_LIVE_SOLDIER: \"兵士\"\n  STR_LIVE_TERRORIST: \"テロリスト\"\n  STR_FLOATER_SOLDIER: \"フローター兵士\"\n  STR_FLOATER_NAVIGATOR: \"フローターのナビゲーター\"\n  STR_FLOATER_MEDIC: \"フローター衛生兵\"\n  STR_FLOATER_ENGINEER: \"フローター技術者\"\n  STR_FLOATER_LEADER: \"フローターのリーダー\"\n  STR_FLOATER_COMMANDER: \"フローター司令官\"\n  STR_SECTOID_SOLDIER: \"セクトイド兵士\"\n  STR_SECTOID_NAVIGATOR: \"セクトイドのナビゲーター\"\n  STR_SECTOID_MEDIC: \"セクトイド衛生兵\"\n  STR_SECTOID_ENGINEER: \"セクトイド技術者\"\n  STR_SECTOID_LEADER: \"セクトイドのリーダー\"\n  STR_SECTOID_COMMANDER: \"セクトイド司令官\"\n  STR_SNAKEMAN_SOLDIER: \"スネークマン兵士\"\n  STR_SNAKEMAN_NAVIGATOR: \"スネークマンのナビゲーター\"\n  STR_SNAKEMAN_ENGINEER: \"スネークマンの技術者\"\n  STR_SNAKEMAN_LEADER: \"スネークマンのリーダー\"\n  STR_SNAKEMAN_COMMANDER: \"スネークマン司令官\"\n  STR_MUTON_SOLDIER: \"ミュートン兵士\"\n  STR_MUTON_NAVIGATOR: \"ミュートンのナビゲーター\"\n  STR_MUTON_ENGINEER: \"ミュートンの技術者\"\n  STR_ETHEREAL_SOLDIER: \"エセリアル兵士\"\n  STR_ETHEREAL_LEADER: \"エセリアルリーダー\"\n  STR_ETHEREAL_COMMANDER: \"エセリアル司令官\"\n  STR_CYBERDISC_TERRORIST: \"サイバーディスクのテロリスト\"\n  STR_REAPER_TERRORIST: \"リーパーテロリスト\"\n  STR_CHRYSSALID_TERRORIST: \"クリサリドテロリスト\"\n  STR_CELATID_TERRORIST: \"セラチドのテロリスト\"\n  STR_SILACOID_TERRORIST: \"シラコイドテロリスト\"\n  STR_SECTOPOD_TERRORIST: \"セクトポッドテロリスト\"\n  STR_UFO_POWER_SOURCE: \"UFO動力源\"\n  STR_UFO_NAVIGATION: \"UFO航法装置\"\n  STR_UFO_CONSTRUCTION: \"UFOの船体\"\n  STR_ALIEN_FOOD: \"エイリアンの食物\"\n  STR_ALIEN_REPRODUCTION: \"エイリアンの繁殖器\"\n  STR_ALIEN_ENTERTAINMENT: \"エイリアンの娯楽\"\n  STR_ALIEN_SURGERY: \"エイリアンの手術台\"\n  STR_EXAMINATION_ROOM: \"エイリアンの検査室\"\n  STR_ALIEN_ALLOYS: \"エイリアンの合金\"\n  STR_ALIEN_HABITAT: \"エイリアンの生活房\"\n  STR_POWER_SUIT: \"パワースーツ\"\n  STR_FLYING_SUIT: \"フライスーツ\"\n  STR_HWP_ROCKETS: \"HWPロケット\"\n  STR_HWP_FUSION_BOMB: \"HWP核融合弾\"\n  STR_LASER_WEAPONS: \"レーザー兵器\"\n  STR_NEW_FIGHTER_CRAFT: \"新戦闘艇\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"新戦闘輸送艇\"\n  STR_ULTIMATE_CRAFT: \"究極の襲撃艇\"\n  STR_LASER_PISTOL: \"レーザー・ピストル\"\n  STR_LASER_RIFLE: \"レーザー・ライフル\"\n  STR_HEAVY_LASER: \"重レーザー・ライフル\"\n  STR_LASER_CANNON: \"レーザー砲\"\n  STR_PLASMA_CANNON: \"プラズマ砲\"\n  STR_FUSION_MISSILE: \"核融合ミサイル\"\n  STR_LASER_DEFENSE: \"レーザー防衛\"\n  STR_PLASMA_DEFENSE: \"プラズマ防衛\"\n  STR_FUSION_DEFENSE: \"核融合防衛\"\n  STR_GRAV_SHIELD: \"重力シールド\"\n  STR_MIND_SHIELD: \"マインド・シールド\"\n  STR_PSI_LAB: \"サイオニック訓練室\"\n  STR_MOTION_SCANNER: \"モーション・スキャナ\"\n  STR_MEDI_KIT: \"医療キット\"\n  STR_TANK_CANNON: \"戦車/カノン砲\"\n  STR_TANK_ROCKET_LAUNCHER: \"戦車/ロケット\"\n  STR_TANK_LASER_CANNON: \"戦車/レーザー\"\n  STR_HOVERTANK_PLASMA: \"ホバータンク/プラズマ\"\n  STR_HOVERTANK_LAUNCHER: \"ホバータンク/ランチャ\"\n  STR_STINGRAY_LAUNCHER: \"スティングレイ発射機\"\n  STR_AVALANCHE_LAUNCHER: \"アバランチ発射機\"\n  STR_CANNON: \"キャノン\"\n  STR_FUSION_BALL_LAUNCHER: \"核融合弾発射機\"\n  STR_PLASMA_BEAM: \"プラズマ砲\"\n  STR_STINGRAY_MISSILES: \"スティングレイ\"\n  STR_AVALANCHE_MISSILES: \"アバランチ\"\n  STR_CANNON_ROUNDS_X50: \"砲弾(x50)\"\n  STR_FUSION_BALL: \"核融合弾\"\n  STR_SOLDIER: \"戦闘員\"\n  STR_SCIENTIST: \"科学者\"\n  STR_ENGINEER: \"技術者\"\n  STR_NORTH_AMERICA: \"北アメリカ\"\n  STR_ARCTIC: \"北極圏\"\n  STR_ANTARCTICA: \"南極大陸\"\n  STR_SOUTH_AMERICA: \"南アメリカ\"\n  STR_EUROPE: \"ヨーロッパ\"\n  STR_NORTH_AFRICA: \"北アフリカ\"\n  STR_SOUTHERN_AFRICA: \"南アフリカ\"\n  STR_CENTRAL_ASIA: \"中央アジア\"\n  STR_SOUTH_EAST_ASIA: \"東南アジア\"\n  STR_SIBERIA: \"シベリア\"\n  STR_AUSTRALASIA: \"オセアニア\"\n  STR_PACIFIC: \"太平洋\"\n  STR_NORTH_ATLANTIC: \"北大西洋\"\n  STR_SOUTH_ATLANTIC: \"南大西洋\"\n  STR_INDIAN_OCEAN: \"インド洋\"\n  STR_ALIEN_RESEARCH: \"研究任務\"\n  STR_ALIEN_HARVEST: \"動物の捕獲\"\n  STR_ALIEN_ABDUCTION: \"誘拐\"\n  STR_ALIEN_INFILTRATION: \"政府への侵入\"\n  STR_ALIEN_BASE: \"エイリアンの基地\"\n  STR_ALIEN_TERROR: \"テロ活動\"\n  STR_ALIEN_RETALIATION: \"報復活動\"\n  STR_ALIEN_SUPPLY: \"物資補給\"\n  STR_MAXIMUM_SPEED: \"最高速度\"\n  STR_HYPER_WAVE_DECODER_UC: \"ハイパー通信解読室\"\n  STR_SKYRANGER: \"スカイレンジャー\"\n  STR_LIGHTNING: \"ライトニング\"\n  STR_AVENGER: \"アベンジャー\"\n  STR_INTERCEPTOR: \"インターセプター\"\n  STR_FIRESTORM: \"ファイヤーストーム\"\n  STR_UFO: \"UFO\"\n  STR_STINGRAY: \"スティングレイ\"\n  STR_AVALANCHE: \"アバランチ\"\n  STR_CANNON_UC: \"キャノン\"\n  STR_FUSION_BALL_UC: \"核融合弾\"\n  STR_LASER_CANNON_UC: \"レーザー砲\"\n  STR_PLASMA_BEAM_UC: \"プラズマ砲\"\n  STR_DAMAGE_CAPACITY: \"ダメージ容量\"\n  STR_WEAPON_POWER: \"兵器の破壊力\"\n  STR_WEAPON_RANGE: \"射程距離\"\n  STR_ACCESS_LIFT: \"アクセス・リフト\"\n  STR_LABORATORY: \"研究室\"\n  STR_WORKSHOP: \"工作室\"\n  STR_SMALL_RADAR_SYSTEM: \"小型レーダー\"\n  STR_LARGE_RADAR_SYSTEM: \"大型レーダー\"\n  STR_MISSILE_DEFENSES: \"ミサイル防衛\"\n  STR_GENERAL_STORES: \"倉庫\"\n  STR_ALIEN_CONTAINMENT: \"隔離拘束施設\"\n  STR_LASER_DEFENSES: \"レーザー防衛\"\n  STR_PLASMA_DEFENSES: \"プラズマ防衛\"\n  STR_FUSION_BALL_DEFENSES: \"核融合防衛\"\n  STR_PSIONIC_LABORATORY: \"サイオニック訓練室\"\n  STR_HYPER_WAVE_DECODER: \"ハイパー通信解読室\"\n  STR_HANGAR: \"格納庫\"\n  STR_USA: \"アメリカ\"\n  STR_RUSSIA: \"ロシア\"\n  STR_UK: \"イギリス\"\n  STR_FRANCE: \"フランス\"\n  STR_GERMANY: \"ドイツ\"\n  STR_ITALY: \"イタリア\"\n  STR_SPAIN: \"スペイン\"\n  STR_CHINA: \"中国\"\n  STR_JAPAN: \"日本\"\n  STR_INDIA: \"インド\"\n  STR_BRAZIL: \"ブラジル\"\n  STR_AUSTRALIA: \"オーストラリア\"\n  STR_NIGERIA: \"ナイジェリア\"\n  STR_SOUTH_AFRICA: \"南アフリカ\"\n  STR_EGYPT: \"エジプト\"\n  STR_CANADA: \"カナダ\"\n  STR_TANK: \"戦車\"\n  STR_CIVILIAN: \"民間人\"\n  STR_JAN: \"1月\"\n  STR_FEB: \"2月\"\n  STR_MAR: \"3月\"\n  STR_APR: \"4月\"\n  STR_MAY: \"5月\"\n  STR_JUN: \"6月\"\n  STR_JUL: \"7月\"\n  STR_AUG: \"8月\"\n  STR_SEP: \"9月\"\n  STR_OCT: \"10月\"\n  STR_NOV: \"11月\"\n  STR_DEC: \"12月\"\n  STR_INTERNATIONAL_RELATIONS: \"国際関係\"\n  STR_COUNTRY: \"国名\"\n  STR_FUNDING: \"提供資金額\"\n  STR_CHANGE: \"変更\"\n  STR_WEAPON_SYSTEMS: \"武器システム\"\n  STR_HWPS: \"HWP\"\n  STR_DAMAGE_UC_: \"ダメージ>{ALT}{0}\"\n  STR_ACCESS_LIFT_UFOPEDIA: \"アクセス・リフトにより、装備や人員を地下基地の内部へ、または基地から外部へと移動することができる。新しく基地を建設する場合には、この施設を最初に建設する必要がある。リフト付近は、敵の侵入に絶えずさらされているので要注意。\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"各居住区の収容人員は最大50名である。基本的な食事および睡眠のための生活エリアと簡易娯楽設備が備わっている。\"\n  STR_LABORATORY_UFOPEDIA: \"研究室には最大50名迄の科学者用の研究スペースがある。研究室には素材、生化学、宇宙物理学などを研究するための最新の設備が備えられており、さらに軍事施設を含む世界中のあらゆる研究施設のコンピュータにアクセスできるという特権がある。\"\n  STR_WORKSHOP_UFOPEDIA: \"工作室には、研究室で行われた研究成果に基づいてデザインされた装備を製造する為の生産用設備が全てそろっている。製造中のアイテムもいくらかスペースを必要とするが、基本的には技術者は最大50名まで工作室に入ることができる。\"\n  STR_SMALL_RADAR_SYSTEM_UFOPEDIA: \"小型レーダー・システムの有効捜索範囲は約300海里であり、地上探査用の衛星システムとリンクしている。各システムは10%の公算で、30分ごとに平均サイズの目標を探知することが可能である。\"\n  STR_LARGE_RADAR_SYSTEM_UFOPEDIA: \"大型レーダー・システムの有効捜索範囲は約450海里であり、地上探査用の衛星システムとリンクしている。各システムは20%の公算で、30分ごとに平均サイズの目標を探知することが可能である。\"\n  STR_MISSILE_DEFENSES_UFOPEDIA: \"ミサイル防衛は、基地の付近に敵の強襲艇が着陸を試みた際に、ある程度の防衛力を提供する。\"\n  STR_GENERAL_STORES_UFOPEDIA: \"全ての装備、武器、弾薬、回収した物品およびHWP(重兵器プラットホーム)は、この倉庫内に保管されている。ただし、輸送機や襲撃艇に搭載されるべき装備や兵器類は、格納庫内に保管されている。\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"生け捕りにしたエイリアンの生命を維持する為には特別な生息環境を必要とする。隔離拘束施設には特殊な生命維持装置を備えた10個の独居房が用意されている。\"\n  STR_LASER_DEFENSES_UFOPEDIA: \"レーザー防衛は、基地付近に敵の強襲艇が着陸を試みた際に、ある程度の防衛力を提供する。\"\n  STR_PLASMA_DEFENSES_UFOPEDIA: \"プラズマビーム防衛は、敵の侵入に対して強力な防御効果を発揮する。\"\n  STR_FUSION_BALL_DEFENSES_UFOPEDIA: \"フュージョンミサイルは、エイリアンの攻撃に対し最も効果的な防衛手段を提供する。このミサイルは反物質の対消滅によって、任意の地点の周囲に存在する何もかもを破壊する。\"\n  STR_GRAV_SHIELD_UFOPEDIA: \"この重力シールドは、基地の周辺に着陸を試みるエイリアンの宇宙船の着陸速度を低下させる。そのために、防衛システムが攻撃を行う時間は倍増するので、事実上、基地の防衛効果も２倍になる。\"\n  STR_MIND_SHIELD_UFOPEDIA: \"エイリアンは、人間の発する脳波によりその存在を探知するので、基地から脳波が一切漏れないように覆ってしまうのが最も効果的な対策法である。この設備により、我々の基地がエイリアンに探知される可能性はほとんどなくなるだろう。\"\n  STR_PSIONIC_LABORATORY_UFOPEDIA: \"サイオニック訓練室は、基地内の全戦闘員を対象に、潜在的なサイオニック(超能力保持者)であるかどうかを判定し、サイオニック能力を利用するのに必要なトレーニングを行う。各訓練室では最大10名まで訓練できる。この訓練は毎月末に行われる。この施設でサイオニック能力を身につけたならば、テレパシー・アンプを用いて、戦闘中にサイオニック攻撃を行うことができる。\"\n  STR_HYPER_WAVE_DECODER_UFOPEDIA: \"エイリアンの通信は超次元的伝達能力を持つハイパー波を用いて、ほぼ瞬間的に行われている。この通信解読施設がUFOの通信を傍受して、暗号情報を解読する。これにより、UFOのタイプやエイリアンの種類、活動の目的などが判明する。\"\n  STR_HANGAR_UFOPEDIA: \"それぞれの格納庫には航空機１機を収納することができる。そして、機材の修理やメンテナンス、さらに燃料や武器弾薬の補給を行うための設備も備えている。基地に所属する航空機は、必ず一つの格納庫を占有し、他の航空機がその格納庫を重複して使用することはできない。\"\n  STR_PISTOL_UFOPEDIA: \"XComの装備する標準的な拳銃。装弾数12発のセミ・オートで、通常より火薬の多い弾丸を使用する。\"\n  STR_RIFLE_UFOPEDIA: \"この高性能狙撃ライフルはレーザー照準器を備え、マガジンには6.7mm弾を20発装填可能である。\"\n  STR_HEAVY_CANNON_UFOPEDIA: \"重キャノンは破壊力は大きいが取扱いの難しい兵器である。徹甲弾、焼夷弾及び高性能さく薬りゅう弾を使用できるので、あらゆる目標を攻撃することができる。\"\n  STR_AUTO_CANNON_UFOPEDIA: \"オート・キャノンは、速射性と多用途性と破壊力をバランス良く兼ね備えた兵器である。\"\n  STR_ROCKET_LAUNCHER_UFOPEDIA: \"ロケット・ランチャは、レーザー照準システムを備えており、3種類のロケット弾を発射できる。\"\n  STR_LASER_PISTOL_UFOPEDIA: \"レーザー・ピストルは新しい技術を効果的に利用したものである。拳銃の取り回しの良さと、通常型の拳銃よりも向上した速射性と命中精度を兼ね備えている。\"\n  STR_LASER_RIFLE_UFOPEDIA: \"レーザー・ライフルはレーザー・ピストルのパワーと命中精度をさらに強化したものである。\"\n  STR_HEAVY_LASER_UFOPEDIA: \"重レーザー・ライフルは取り回しが悪く扱いにくい兵器だが、非常に強力である。\"\n  STR_GRENADE_UFOPEDIA: \"この手りゅう弾は、正確なコントロールを行うために、精密かつ精巧なタイマーを備えている。\"\n  STR_SMOKE_GRENADE_UFOPEDIA: \"発煙手りゅう弾は、敵の目から姿を隠す場合に有効である。ただし、敵の姿を見失う場合もあるので慎重に使用せよ。\"\n  STR_PROXIMITY_GRENADE_UFOPEDIA: \"近接手りゅう弾は、普通の手りゅう弾と同様に投げることができるが、その爆発はタイマー信管ではなく近接信管による。この種の兵器を使用するには、熟練した技術と最大の注意力が必要である。\"\n  STR_HIGH_EXPLOSIVE_UFOPEDIA: \"この高性能時限爆弾は、建造物の破壊等の目的にのみ使用しなければならない。破壊力が大きいので、タイマー・セット後直ちに現場から人員を退避させること。\"\n  STR_MOTION_SCANNER_UFOPEDIA: \"この精巧な装置は、種々の探知器とコンピュータ・アルゴリズムを駆使しており、移動中の敵ユニットを探知することができる。しかし、これを使いこなすには、ある程度の訓練を要する。{NEWLINE}{NEWLINE}この装置を使用するには、まずタクティカル・ディスプレイにてスキャナを選択し、メニューから‘スキャナを使う’を選択する。{NEWLINE}{NEWLINE}スキャナの中央に表示された矢印が、兵士の向きを表している(上は常に北)。点滅しているドットは、移動中のユニットを示す。ドットは高速で移動するほど、またはユニットのサイズが大きくなるほど大きく表示される。ただし、この装置は静止しているユニットを探知できない。\"\n  STR_MEDI_KIT_UFOPEDIA: \"この装置は負傷した兵士の方を向いて、または気絶した兵士の体の上で使用する。{NEWLINE}{NEWLINE}治療> 赤い部分が負傷した部位を示す。治療する部位を選択して‘治療’ボタンを押す。傷が治療され健康を回復する。{NEWLINE}{NEWLINE}興奮剤> エネルギーを回復し、気絶した兵士の意識を回復する。気絶した兵士の意識を回復させるには、身体の上に直接立って操作を行う。{NEWLINE}{NEWLINE}鎮痛剤> 負傷した兵の士気を取り戻す。\"\n  STR_PSI_AMP_UFOPEDIA: \"テレパシー増幅器はサイオニック能力を持つ兵士のみが使用できる。この装置で可能なサイオニック攻撃には以下の２タイプがある。{NEWLINE}{NEWLINE}パニック・ユニット>攻撃が成功すれば、ターゲットは士気をくじかれ、パニックにおちいる。{NEWLINE}{NEWLINE}マインド・コントロール>この攻撃が成功すれば、敵ユニットを自分のユニットの様に直接コントロールできる(ただし、オブジェクト画面にはアクセスできない)。この攻撃を成功させるのはかなりの能力を必要とする。\"\n  STR_STUN_ROD_UFOPEDIA: \"この装置は接近戦でしか使用できないが、電気ショックを用いて相手を殺さずに気絶させることができる。{NEWLINE}{NEWLINE}使用法>スタンさせたい相手に隣接し、その方向を向いて用いる。\"\n  STR_MIND_PROBE_UFOPEDIA: \"マインド・プローブはエイリアンの通信装置であり、相手の脳波から直接情報を収集する事ができる。XComもこの装置を用いて、特定のエイリアンの情報を得ることができる。\"\n  STR_PLASMA_PISTOL_UFOPEDIA: \"プラズマ・ピストルはエイリアンの使用する強力な兵器のひとつである。カートリッジの中で反重力フィールドが形成され、そこで光速に近い速度まで加速された粒子が目標を破壊する。\"\n  STR_PLASMA_RIFLE_UFOPEDIA: \"プラズマ・ライフルはプラズマ・ピストルと同じ原理の兵器であるが、ピストルよりも大きなカートリッジを使用するため、破壊力はより強力である。\"\n  STR_HEAVY_PLASMA_UFOPEDIA: \"これは反重力フィールドから加速された粒子を撃ち出す圧倒的で強力な武器である。\"\n  STR_BLASTER_LAUNCHER_UFOPEDIA: \"これは強力なブラスター弾を発射することができる、エイリアンの誘導ミサイル発射器である。この武器を使用する場合、ミサイルの通過するガイド・ポイントを設定し、それが終了したら特別な'発射'のアイコンをクリックする。\"\n  STR_SMALL_LAUNCHER_UFOPEDIA: \"スタン弾を発射するための小型ランチャ。この兵器を使用すると、エイリアンを生きたまま捕獲することができる。\"\n  STR_ALIEN_GRENADE_UFOPEDIA: \"この手りゅう弾は、我々の手りゅう弾と全く同じ機能を持つが、より強力である。\"\n  STR_SMALL_SCOUT: \"小型偵察機\"\n  STR_MEDIUM_SCOUT: \"中型偵察艇\"\n  STR_LARGE_SCOUT: \"大型偵察艇\"\n  STR_HARVESTER: \"収穫船\"\n  STR_ABDUCTOR: \"誘拐船\"\n  STR_TERROR_SHIP: \"テロ活動船\"\n  STR_BATTLESHIP: \"戦艦\"\n  STR_SUPPLY_SHIP: \"補給船\"\n  STR_RATING: \"評価> {0}\"\n  STR_RATING_TERRIBLE: \"劣悪!\"\n  STR_RATING_POOR: \"不十分!\"\n  STR_RATING_OK: \"OK\"\n  STR_RATING_GOOD: \"良い!\"\n  STR_RATING_EXCELLENT: \"優秀!\"\n  STR_SCORE: \"スコア\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"XCOMプロジェクト月間レポート\"\n  STR_MONTH: \"月> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"資金提供国の評議会は、これまでのあなたの働きにおおむね満足しています。\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"資金提供国の評議会は、あなたの素晴らしい働きに大変満足しています。その調子で続けて下さい。\"\n  STR_COUNCIL_IS_DISSATISFIED: \"資金提供国の評議会はあなたの働きに不満です。エイリアン対策の効率を高めなければ、プロジェクトは停止される恐れがあります。\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"あなたは宇宙人の侵略に対し、処置を講じ損ないました。資金提供国の評議会は、残念ながらプロジェクトの停止を決定しました。各国は、それぞれに問題を処理することになります。今、我々にできることは、これらの明らかに敵と思われる軍隊と和解することと、民間人がエイリアンの視察員との協定に納得するように願うことだけです。\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0}は脅威を局部的に食い止めたあなたの処置能力に 特に満足して、資金提供額を増やすことに同意しました。\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0}は、特定地域におけるエイリアンの侵略に対するあなたの働きに特に満足して、資金提供額を増やすことに同意しました。\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} と {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0}は、領土内でのエイリアンの活動に対するあなたの処置能力に不満足で、経済的な援助を削減させることを決定しました。\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0}は、領土内でのエイリアンの活動に対するあなたの処置能力に不満足で、経済的な援助を削減させることを決定しました。\"\n  STR_KNOTS: \"{0} ノット\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0}は、エイリアン軍との秘密条約にサインし、プロジェクトから離脱しました。\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0}は、エイリアン軍との秘密条約にサインし、プロジェクトから離脱しました。\"\n  STR_MONTHLY_RATING: \"月間評価> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"資金変更> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"資金提供評議会は、あなたの経済状況を好ましく思っていません。負債を百万ドル以下に抑えなければ、プロジェクトは停止されます。\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"ハイパー波通信を解読しました\"\n  STR_CRAFT_TYPE: \"宇宙船のタイプ\"\n  STR_RACE: \"種族\"\n  STR_MISSION: \"任務\"\n  STR_ZONE: \"ゾーン\"\n  STR_ALLOCATE_RESEARCH: \"研究を割り当てる\"\n  STR_ALLOCATE_MANUFACTURE: \"製造を割り当てる\"\n  STR_NEW_YORK: \"ニューヨーク\"\n  STR_WASHINGTON: \"ワシントン\"\n  STR_LOS_ANGELES: \"ロサンゼルス\"\n  STR_MONTREAL: \"モントリオール\"\n  STR_HAVANA: \"ハバナ\"\n  STR_MEXICO_CITY: \"メキシコシティー\"\n  STR_CHICAGO: \"シカゴ\"\n  STR_VANCOUVER: \"バンクーバー\"\n  STR_DALLAS: \"ダラス\"\n  STR_BRASILIA: \"ブラジリア\"\n  STR_BOGOTA: \"ボゴタ\"\n  STR_BUENOS_AIRES: \"ブエノスアイレス\"\n  STR_SANTIAGO: \"サンチアゴ\"\n  STR_RIO_DE_JANEIRO: \"リオデジャネイロ\"\n  STR_LIMA: \"リマ\"\n  STR_CARACAS: \"カラカス\"\n  STR_LONDON: \"ロンドン\"\n  STR_PARIS: \"パリ\"\n  STR_BERLIN: \"ベルリン\"\n  STR_MOSCOW: \"モスクワ\"\n  STR_ROME: \"ローマ\"\n  STR_MADRID: \"マドリッド\"\n  STR_BUDAPEST: \"ブダペスト\"\n  STR_LAGOS: \"ラゴス\"\n  STR_CAIRO: \"カイロ\"\n  STR_CASABLANCA: \"カサブランカ\"\n  STR_PRETORIA: \"プレトリア\"\n  STR_NAIROBI: \"ナイロビ\"\n  STR_CAPE_TOWN: \"ケープタウン\"\n  STR_KINSHASA: \"キンシャサ\"\n  STR_ANKARA: \"アンカラ\"\n  STR_DELHI: \"デリー\"\n  STR_KARACHI: \"カラチ\"\n  STR_BAGHDAD: \"バグダッド\"\n  STR_TEHRAN: \"テヘラン\"\n  STR_BOMBAY: \"ボンベイ\"\n  STR_CALCUTTA: \"カルカッタ\"\n  STR_TOKYO: \"東京\"\n  STR_BEIJING: \"北京\"\n  STR_BANGKOK: \"バンコク\"\n  STR_MANILA: \"マニラ\"\n  STR_SEOUL: \"ソウル\"\n  STR_SINGAPORE: \"シンガポール\"\n  STR_JAKARTA: \"ジャカルタ\"\n  STR_SHANGHAI: \"上海\"\n  STR_HONG_KONG: \"香港\"\n  STR_NOVOSIBIRSK: \"ノボシビルスク\"\n  STR_CANBERRA: \"キャンベラ\"\n  STR_WELLINGTON: \"ウェリントン\"\n  STR_MELBOURNE: \"メルボルン\"\n  STR_PERTH: \"パース\"\n  STR_PSI_TRAINING: \"Psi訓練\"\n  STR_PSIONIC_TRAINING: \"サイオニック訓練\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Psi訓練室 残り容量> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"サイオニック強度\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"サイオニック技術/向上\"\n  STR_PSI_AMP: \"テレパシー・アンプ\"\n  STR_IN_TRAINING: \"訓練中?\"\n  STR_TARGETTED_BY: \"の目的地です\"\n  STR_WEAPONS_CREW_HWPS: \"武装:戦闘員:HWP\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"は燃料不足により、基地へ帰投します。\"\n  STR_SOLDIER_LIST: \"戦闘員リスト\"\n  STR_RANK_: \"階級> {ALT}{0}\"\n  STR_MISSIONS: \"任務> {ALT}{0}\"\n  STR_KILLS: \"倒した敵> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"傷回復> {ALT}{0}\"\n  STR_TIME_UNITS: \"時間ユニット\"\n  STR_STAMINA: \"スタミナ\"\n  STR_HEALTH: \"H.P.\"\n  STR_BRAVERY: \"勇敢さ\"\n  STR_REACTIONS: \"反応度\"\n  STR_FIRING_ACCURACY: \"射撃能力\"\n  STR_THROWING_ACCURACY: \"投てき能力\"\n  STR_STRENGTH: \"筋力\"\n  STR_PSIONIC_STRENGTH: \"サイオニック強度\"\n  STR_PSIONIC_SKILL: \"サイオニック技術\"\n  STR_NEW_RANK: \"新しい階級\"\n  STR_PROMOTIONS: \"昇進\"\n  STR_SOLDIERS_UC: \"兵士\"\n  STR_TANK_CANNON_UFOPEDIA: \"自走化された重兵器プラットホームは、XCom分隊を支援するためのものである。優れた火力と頑強な装甲の組合せにより、これらのユニットは見通しのよい地形での戦闘に有効である。倉庫に再装備に十分な砲弾があることを確認すること。砲弾は戦車を分隊に割り当てると、自動的に搭載される。\"\n  STR_TANK_ROCKET_LAUNCHER_UFOPEDIA: \"この自動化された重兵器プラットホームは、強力なロケット砲を装備している。この兵器はいかなるエイリアンをも撃退することができる。肝心なときに弾切れにならないように、ロケット弾の補充は確実に行うこと。\"\n  STR_TANK_LASER_CANNON_UFOPEDIA: \"レーザー砲は重兵器プラットホームにとって、非常に有益な兵器である。それは強大な破壊力と弾数無制限という2つの長所を兼ね備えているからである。\"\n  STR_HOVERTANK_PLASMA_UFOPEDIA: \"エイリアンのテクノロジーはHWPをさらに有効な兵器へと進化させた。空中機動能力とプラズマ砲の破壊力の組み合わせにより、正に殺りく兵器と呼ぶにふさわしいものとなった。\"\n  STR_HOVERTANK_LAUNCHER_UFOPEDIA: \"このホバータンクは計り知れない破壊力を持つ核融合弾発射装置を備えている。慎重に使用すること。このHWPを完全装備状態にしておくには、核融合弾を製造して倉庫に保管しておかなければならない。核融合弾は知的誘導装置付き兵器である。発射するためには、ガイド・ポイントを設定した後、'発射'のアイコンをクリックする。\"\n  STR_HEAVY_PLASMA_CLIP_UFOPEDIA: \"この小さな装置は、重プラズマ・ライフル用の弾倉である。少量のエレリウムを含有しており、35回発射分のエネルギーカートリッジが装填されている。\"\n  STR_PLASMA_RIFLE_CLIP_UFOPEDIA: \"この小さな装置は、プラズマ・ライフル用の弾倉である。極少量のエレリウムを含有しており、28回発射分のエネルギーカートリッジが装填されている。\"\n  STR_PLASMA_PISTOL_CLIP_UFOPEDIA: \"プラズマ・ピストル用弾倉。エイリアンのパワーの源であるエレリウムを含有するエネルギー・カートリッジが、28発分装填されている。\"\n  STR_STUN_BOMB_UFOPEDIA: \"スタンボムは生きたまま人間の標本を捕獲するために使用される。が、それはまた殆どのエイリアン種族に対しても有効である。これは小型ランチャーから発射される。\"\n  STR_ALIEN_RESEARCH_UFOPEDIA: \"エイリアンの研究任務とは、地球およびそこに生息する動物に関する基礎データの収集である。この任務には、主に小型偵察機が使用され、発見されるのを防ぐ為か、人口の密集していないところで行われる場合が多い。この種のエイリアンの活動がXComに与える脅威は最小限のもので、政府や民間人もほとんど関心を持たない。\"\n  STR_ALIEN_HARVEST_UFOPEDIA: \"エイリアンは地球の動物を様々な目的の為に利用する。これらの動物はひそかに連れ去られ、内蔵などを抜き取られたうえで廃棄される。この様なキャトル・ミューティレーションについての報告は、UFOの目撃情報とともにもたらされる傾向がある。この種の活動は政府にとって大きな問題であり、民間人を大いなる不安に陥れる。この種の活動は主に農業地域で行われる。エイリアンの‘収穫’という言葉の背後にある理論によれば、エイリアンがこの惑星に植物や動物の‘種’をまき、その種から実ったものを収穫しに戻って来たということに他ならない。\"\n  STR_ALIEN_ABDUCTION_UFOPEDIA: \"これはエイリアンの活動の中でも、最も卑劣なものである。エイリアンによる誘拐は彼らが犠牲者の記憶から、その体験したことを消去しようと試みているにもかかわらず、多数が報告されている。誘拐された者は、屈辱的な検査をされたと報告しており、その中にはエイリアン胎児の受胎や奇妙な遺伝子実験も含まれる。{NEWLINE}{NEWLINE}これらの活動の真の目的は、遺伝子上の突然変異やエイリアン自身の遺伝子を操作することと関連があるらしい。この活動は、大都市などの人口密集地で行われ、民間人に計り知れない恐怖を与える。\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"各国政府は、人間と同じ姿をしたエイリアンの諜報員に侵入されているおそれがある。そうなれば、宇宙人と政府の間で正式な高官レベルでの折衝が行われる。この交渉が最高潮に達すると、主要都市付近のUFOの活動が非常に活発化する。宇宙人は政府に対し、協定にサインすれば自分たちの優れた技術を提供しても良いとアプローチする。その代わり、政府に領土内で自由に活動を行える事を要求する。{NEWLINE}{NEWLINE}この活動は、XComにとって最大の脅威である。もし政府が協定を結べば、その国からの資金の提供は停止される。\"\n  STR_ALIEN_BASE_UFOPEDIA: \"エイリアンは人里離れた場所に、秘密の地下基地を建設する。基地建設の前には、まず調査飛行が数回行われる。それから基地建設中には頻繁に輸送船が飛来し、大量の物資を運んでくる。これらの基地は誘拐された人間のための実験室を備え、その地域での全ての活動をサポートしていることが判明している。宇宙人の基地があれば、UFOが現れなくても、非常に多くの宇宙人の活動が報告されることになるだろう。{NEWLINE}{NEWLINE}基地の所在地を発見するには、偵察機を目的の地域へ派遣し、数時間かけて同エリアをパトロールしなければならない。\"\n  STR_ALIEN_TERROR_UFOPEDIA: \"エイリアンは都市をテロ攻撃する際に、すざまじいパワーを持つ特殊部隊を投入する。民間人は、その脅威に直接さらされることになり、政府はそのエリアの放棄を強いられる。{NEWLINE}{NEWLINE}この活動の真の目的は市民を恐慌状態に陥れることと、その結果から政府がXComプロジェクトを脅かすことである。\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"もし、XComの迎撃機がUFOを撃墜した場合、エイリアンが何らかの報復活動を起こすかも知れない。XComの基地を直接攻撃してくる可能性もある。{NEWLINE}しかし基地を攻撃するためにはその位置を知らなければならないので、常にUFOを遠ざけておけば、襲撃される危険はほとんどないはずである。\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"エイリアンの基地が建設されると、大型の輸送船が定期的に物資の補給を行うために飛来する。{NEWLINE}もし着陸している輸送船を発見したら、その近くに宇宙人の基地が存在するはずだ。\"\n  STR_SMALL_SCOUT_UFOPEDIA: \"この小さな宇宙船は主として偵察や観測に用いられる。{NEWLINE}エイリアンが任務を開始する場合、この小型偵察機を用いて初期の情報収集を行う。\"\n  STR_MEDIUM_SCOUT_UFOPEDIA: \"この中型の偵察艇はXComにとって全く脅威とはなり得ない。防御力は弱く、武装も貧弱だからである。{NEWLINE}通常は、襲撃任務の前に姿を現す。任務のための詳細な情報収集を行っている。\"\n  STR_LARGE_SCOUT_UFOPEDIA: \"この大型の偵察艇はある程度強力な装甲と兵器を備えており、威力偵察などの任務に用いられる。\"\n  STR_HARVESTER_UFOPEDIA: \"収穫船の底には大きなドアがあり、牛や他の動物を引き上げるための装置を備えている。レーザー・カッターはそれらの家畜から必要な材料を切除抽出するために用いられ、残骸は地上に捨てられる。また切除した体部を保管するためのコンテナも備えている。\"\n  STR_ABDUCTOR_UFOPEDIA: \"この宇宙船には誘拐した人間に対して、恐ろしい人体実験を行うための検査室や各種の実験用器具が備わっている。犠牲者は通常テレパシーの力でマヒ状態にさるのだが、手術の間意識はそのまま残っているという。\"\n  STR_TERROR_SHIP_UFOPEDIA: \"テロ活動船にはエイリアンがテロ活動を行うための特殊な兵器や生物が搭載されている。この船はそれらのテロリストを、人口密集地域へ輸送するために用いられる。\"\n  STR_BATTLESHIP_UFOPEDIA: \"戦艦はエイリアンの保有する、最大かつ最強の宇宙船である。並はずれた防御力と武装を持ち、また、多数の戦闘員も搭乗している。制圧任務や基地強襲任務などに用いられる。\"\n  STR_SUPPLY_SHIP_UFOPEDIA: \"補給船はエイリアン基地への各種物資の輸送に使用される。この船には食料用のコンテナや繁殖作業用の部屋が設置されている。この宇宙船が頻繁に現れるような場合は、どこかに新しい基地を建設していると思われる。\"\n  STR_DISMANTLE: \"施設を撤去する\"\n  STR_FACILITY_IN_USE: \"設備使用中\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"この施設は撤去できません!{SMALLLINE}基地の全施設は、アクセス・リフトと直接または間接的に接続される必要があります。\"\n  STR_TRANSFER_ITEMS_TO: \"{0}にアイテムを移動する\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"隔離拘束施設がありません!{SMALLLINE}移動するエイリアンの生命を維持するためには、移動先の基地に隔離施設が必要です。\"\n  STR_AMOUNT_AT_DESTINATION: \"移動先の保有数\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"捕獲したエイリアンは基地に隔離拘束施設がない為、死亡しました\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"居住区に空きがありません!{SMALLLINE}移動先の基地に、移動する輸送機の搭乗員のための居住スペースを確保できません。\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"格納スペースがありません！{SMALLLINE}輸送機に割り当てられた機材の格納スペースが輸送先の基地にありません\"\n  STR_ITEMS_ARRIVING: \"アイテム到着\"\n  STR_DESTINATION_UC: \"目的地\"\n  STR_PISTOL: \"ピストル\"\n  STR_PISTOL_CLIP: \"ピストル用弾倉\"\n  STR_RIFLE: \"ライフル\"\n  STR_RIFLE_CLIP: \"ライフル用弾倉\"\n  STR_HEAVY_CANNON: \"重キャノン(HC)\"\n  STR_HC_AP_AMMO: \"HC用 AP(徹甲)弾\"\n  STR_HC_HE_AMMO: \"HC用 HE(りゅう)弾\"\n  STR_HC_I_AMMO: \"HC用 I (焼夷)弾\"\n  STR_AUTO_CANNON: \"オート・キャノン(AC)\"\n  STR_AC_AP_AMMO: \"AC用 AP(徹甲)弾\"\n  STR_AC_HE_AMMO: \"AC用 HE(りゅう)弾\"\n  STR_AC_I_AMMO: \"AC用 I(焼夷)弾\"\n  STR_ROCKET_LAUNCHER: \"ロケット・ランチャ\"\n  STR_SMALL_ROCKET: \"小型ロケット弾\"\n  STR_LARGE_ROCKET: \"大型ロケット弾\"\n  STR_INCENDIARY_ROCKET: \"焼夷ロケット弾\"\n  STR_GRENADE: \"手りゅう弾\"\n  STR_SMOKE_GRENADE: \"発煙弾\"\n  STR_PROXIMITY_GRENADE: \"近接手りゅう弾\"\n  STR_HIGH_EXPLOSIVE: \"高性能時限爆弾\"\n  STR_STUN_ROD: \"スタン・ロッド\"\n  STR_HEAVY_PLASMA: \"重プラズマ・ライフル\"\n  STR_HEAVY_PLASMA_CLIP: \"重プラズマ用弾倉\"\n  STR_PLASMA_RIFLE: \"プラズマ・ライフル\"\n  STR_PLASMA_RIFLE_CLIP: \"プラズマＲ用弾倉\"\n  STR_PLASMA_PISTOL: \"プラズマ・ピストル\"\n  STR_PLASMA_PISTOL_CLIP: \"プラズマＰ用弾倉\"\n  STR_BLASTER_LAUNCHER: \"ブラスター・ランチャ\"\n  STR_BLASTER_BOMB: \"ブラスター・ミサイル\"\n  STR_SMALL_LAUNCHER: \"スタン・ランチャ\"\n  STR_STUN_BOMB: \"スタンボム\"\n  STR_ALIEN_GRENADE: \"エイリアンの手りゅう弾\"\n  STR_ELERIUM_115: \"エレリウム-115\"\n  STR_MIND_PROBE: \"マインド・プローブ\"\n  STR_SECTOID_CORPSE: \"セクトイドの死体\"\n  STR_SNAKEMAN_CORPSE: \"スネークマンの死体\"\n  STR_ETHEREAL_CORPSE: \"エセリアルの死体\"\n  STR_MUTON_CORPSE: \"ミュートンの死体\"\n  STR_FLOATER_CORPSE: \"フローターの死体\"\n  STR_CELATID_CORPSE: \"セラチドの死体\"\n  STR_SILACOID_CORPSE: \"シラコイドの死体\"\n  STR_CHRYSSALID_CORPSE: \"クリサリドの死体\"\n  STR_REAPER_CORPSE: \"リーパーの死体\"\n  STR_SECTOPOD_CORPSE: \"セクトポッドの残骸\"\n  STR_CYBERDISC_CORPSE: \"サイバーディスクの残骸\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"HWPを充填するのに十分な弾薬がありません。{SMALLLINE}それぞれのHWPには {0} {1}が必要です。\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"戦闘部隊の戦力を維持するための兵員または装備が不足しています\"\n  STR_MARS_CYDONIA_LANDING: \"火星: サイドニア襲撃\"\n  STR_MARS_CYDONIA_LANDING_BRIEFING: \"アベンジャーは火星表面のサイドニアに着陸した。情報によると、ピラミッドの１つには地下コンビナートに通じる緑色のアクセス・リフトがある。敵の衛兵を倒して、敵の本拠地へ突入せよ。リフトに全戦闘員を集めてから'任務中断'を実行し次のステージへ向かえ。\"\n  STR_MARS_THE_FINAL_ASSAULT: \"火星: 最終襲撃戦\"\n  STR_MARS_THE_FINAL_ASSAULT_BRIEFING: \"ピラミッドのリフトは戦闘で疲労した戦闘員達を火星の地下深くへと運んだ。そして、彼らは巨大な地下コンビナートの中心に到着した。最終目標の‘脳’はこの地下迷宮のどこかに存在する。地球をエイリアンの脅威から救うためには、その脳を破壊しなければならない。{NEWLINE}{NEWLINE}諸君らの健闘を祈る!\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"{1} を開発するには {0} を研究する必要がある。\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"エイリアンはXComの無防備な基地{0}を破壊した\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"XCom のエージェントは {0} にエイリアンの基地を発見した。\"\n  STR_STANDOFF: \"射程外\"\n  STR_CAUTIOUS_ATTACK: \" 慎重な攻撃\"\n  STR_STANDARD_ATTACK: \" 通常攻撃\"\n  STR_AGGRESSIVE_ATTACK: \" 猛攻撃\"\n  STR_DISENGAGING: \" 離脱\"\n  STR_UFO_HIT: \" UFO被弾!\"\n  STR_UFO_CRASH_LANDS: \" UFO不時着!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \" 攻撃中は無効\"\n  STR_UFO_RETURN_FIRE: \" UFO反撃!\"\n  STR_INTERCEPTOR_DAMAGED: \" 迎撃機破損\"\n  STR_INTERCEPTOR_DESTROYED: \" 迎撃機破壊\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"UFOはインターセプターから逃走中!\"\n  STR_ALIENS_TERRORISE: \"エイリアンがテロ活動中:\"\n  STR_LONG_RANGE_DETECTION: \"長距離探知\"\n  STR_STORES_UC: \"在庫\"\n  STR_DIFFICULTY_LEVEL: \"難易度\"\n  STR_INTERCEPT: \"迎撃\"\n  STR_BASES: \"基地\"\n  STR_GRAPHS: \"グラフ\"\n  STR_UFOPAEDIA_UC: \"UFOペディア\"\n  STR_OPTIONS_UC: \"オプション\"\n  STR_FUNDING_UC: \"資金提供国\"\n  STR_5_SECONDS: \"5秒\"\n  STR_1_MINUTE: \"1分\"\n  STR_5_MINUTES: \"5分\"\n  STR_30_MINUTES: \"30分\"\n  STR_1_HOUR: \"1時間\"\n  STR_1_DAY: \"1日\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"XCom勤務名簿\"\n  STR_ENTER_NAME: \"名前を入力する\"\n  STR_PERFORMANCE_RATING: \"勤務評価\"\n  STR_VICTORY_DATE: \"勝利の日\"\n  STR_ELECTRO_FLARE: \"エレクトロ・フレア\"\n  STR_ELECTRO_FLARE_UFOPEDIA: \"この照明ライトは、地面に落ちた瞬間に点灯する。夜間戦闘中に敵のユニットを発見するのに役立つ。\"\n  STR_MONTHLY_COSTS: \"毎月の費用\"\n  STR_CRAFT_RENTAL: \"整備コスト\"\n  STR_SALARIES: \"人件費\"\n  STR_BASE_MAINTENANCE: \"基地の維持費\"\n  STR_COST_PER_UNIT: \"ユニットごとの費用\"\n  STR_QUANTITY: \"数量\"\n  STR_TOTAL: \"合計\"\n  STR_IN_PSIONIC_TRAINING: \"サイオニック訓練中\"\n  STR_BLASTER_BOMB_UFOPEDIA: \"ラグビー・ボールのような形をした弾丸はブラスター・ランチャ用のミサイルで高度な知的誘導システムを備えている。\"\n  STR_FRONT_ARMOR: \"前面装甲\"\n  STR_LEFT_ARMOR: \"左側装甲\"\n  STR_RIGHT_ARMOR: \"右側装甲\"\n  STR_REAR_ARMOR: \"背面装甲\"\n  STR_UNDER_ARMOR: \"下面装甲\"\n  STR_ROUNDS: \"装弾数\"\n  STR_UNIT: \"ユニット> {0}\"\n  STR_ENERGY: \"体力\"\n  STR_MORALE: \"士気\"\n  STR_ARMOR_: \"アーマー> {0}\"\n  STR_FRONT_ARMOR_UC: \"正面装甲\"\n  STR_LEFT_ARMOR_UC: \"左側装甲\"\n  STR_RIGHT_ARMOR_UC: \"右側装甲\"\n  STR_REAR_ARMOR_UC: \"背面装甲\"\n  STR_SKILLS: \"スキル> {0}\"\n  STR_LEVEL: \"レベル> {0}\"\n  STR_HEAD: \"頭部\"\n  STR_TORSO: \"胴体\"\n  STR_RIGHT_ARM: \"右腕\"\n  STR_LEFT_ARM: \"左腕\"\n  STR_RIGHT_LEG: \"右足\"\n  STR_LEFT_LEG: \"左足\"\n  STR_PAIN_KILLER: \"鎮痛剤\"\n  STR_STIMULANT: \"興奮剤\"\n  STR_HEAL: \"治療\"\n  STR_TIME_UNITS_SHORT: \"TU>{ALT}{0}\"\n  STR_WEIGHT: \"重量>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"反応>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"Pスキル>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"P強度>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"エイリアンの製造品\"\n  STR_AMMO_ROUNDS_LEFT: \"弾薬:弾丸残り={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"痛み>{ALT}{0}{ALT}興奮>{ALT}{1}{ALT}治療>{ALT}{2}\"\n  STR_THROW: \"投げる\"\n  STR_AUTO_SHOT: \"3連射撃\"\n  STR_SNAP_SHOT: \"急速射撃\"\n  STR_AIMED_SHOT: \"精密射撃\"\n  STR_STUN: \"気絶させる\"\n  STR_PRIME_GRENADE: \"時限設定\"\n  STR_USE_SCANNER: \"スキャナを使う\"\n  STR_USE_MEDI_KIT: \"医療キットを使う\"\n  STR_LAUNCH_MISSILE: \"ミサイルを発射する\"\n  STR_ACCURACY_SHORT: \"精度>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"時間ユニットが足りません!\"\n  STR_NOT_ENOUGH_ENERGY: \"体力が足りません!\"\n  STR_NO_ROUNDS_LEFT: \"弾薬がありません!\"\n  STR_NO_AMMUNITION_LOADED: \"弾が装填されていません!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"別の兵器用の弾薬です!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"弾は既に装填されています!\"\n  STR_NO_LINE_OF_FIRE: \"射線上に障害あり!\"\n  STR_GRENADE_IS_ACTIVATED: \"手りゅう弾作動中！\"\n  STR_GRENADE_IS_DEACTIVATED: \"手りゅう弾解除！\"\n  STR_THERE_IS_NO_ONE_THERE: \"そこには誰もいません!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"研究終了まで使用できません!\"\n  STR_OUT_OF_RANGE: \"射程距離外です!\"\n  STR_UNABLE_TO_THROW_HERE: \"そこには投げられません!\"\n  STR_SET_TIMER: \"タイマーをセットする\"\n  STR_HIDDEN_MOVEMENT: \"エイリアン行動中\"\n  STR_TURN: \"ターン> {0}\"\n  STR_SIDE: \"サイド> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"ボタンを押して下さい\"\n  STR_MIND_CONTROL: \"マインド・コントロール\"\n  STR_PANIC_UNIT: \"パニック・ユニット\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"精神攻撃に成功\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"マインド・コントロール成功\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}が狂暴化した\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}が狂暴化した\"\n  STR_HAS_PANICKED_MALE: \"{0}はパニックに陥った\"\n  STR_HAS_PANICKED_FEMALE: \"{0}はパニックに陥った\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"エイリアン\"\n  STR_RIGHT_HAND: \"右手\"\n  STR_LEFT_HAND: \"左手\"\n  STR_RIGHT_SHOULDER: \"右肩\"\n  STR_LEFT_SHOULDER: \"左肩\"\n  STR_BACK_PACK: \"バックパック\"\n  STR_BELT: \"ベルト\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}はエイリアンに支配されている\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}はエイリアンに支配されている\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}は昏倒した\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}は昏倒した\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}は致命傷が原因で死亡した\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}は致命傷が原因で死亡した\"\n  STR_USE_MIND_PROBE: \"プローブを使用する\"\n  STR_FATAL_WOUNDS: \"致命傷\"\n  STR_UNDER_ARMOR_UC: \"下面装甲\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"残りT.U.は急速射撃用リザーブ\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"残りT.U.は3連射撃用リザーブ\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"残りT.U.は精密射撃用リザーブ\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"屈みこむためのTUをリザーブ\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"屈みこみ射撃するためのTUをリザーブ\"\n  STR_UNITS_IN_CRAFT:\n    other: \"{N}Xcomの機体に居るユニット\"\n  STR_UNITS_OUTSIDE:\n    other: \"{N}外に居るユニット\"\n  STR_UNITS_IN_ENTRANCE:\n    other: \"{N}入り口に居るユニット\"\n  STR_UNITS_IN_EXIT:\n    other: \"{N}目標の出口に居るユニット\"\n  STR_ABORT_MISSION_QUESTION: \"任務を中断しますか?\"\n  STR_CORPSE: \"死体\"\n  STR_UNLOAD_CRAFT: \"弾薬を抜き取る\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}は死亡した\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}は死亡した\"\n  STR_HIT_MELEE: \"近接攻撃\"\n  STR_GROUND: \"着陸中\"\n  STR_LIVING_QUARTERS_PLURAL: \"居住区\"\n  STR_LIST_ITEM: \"アイテム\"\n  STR_PERSONAL_ARMOR_UFOPEDIA: \"この新しいアーマーには宇宙人の合金を用いており、我々が宇宙人の脅威に打ち勝つチャンスをもたらす。\"\n  STR_POWER_SUIT_UFOPEDIA: \"兵士のための強力な防護手段であるこのアーマーは、エレリウムを動力源とし、着用者の素早さと強さを大幅に増幅させるため、戦闘部隊にとって最高の保護を提供する。\"\n  STR_FLYING_SUIT_UFOPEDIA: \"パワースーツの強化バージョンにはエイリアンの反重力制御技術が組み込まれており、戦場を自由自在に移動する事を可能とする。\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"UFOの墜落でエイリアンが死亡し、自動回収された\"\n  STR_RESET: \"リセット\"\n  STR_MEMORIAL: \"墓碑\"\n  STR_DATE_UC: \"日付\"\n  STR_SOLDIERS_RECRUITED_UC: \"雇用した兵士 >{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"失った兵士 >{ALT}{0}\"\n  MAP_CULTA: \"農地\"\n  MAP_FOREST: \"森林\"\n  MAP_JUNGLE: \"ジャングル\"\n  MAP_MOUNT: \"山地\"\n  MAP_DESERT: \"砂漠\"\n  MAP_POLAR: \"極地\"\n  MAP_URBAN: \"都市\"\n  MAP_UBASE: \"エイリアンの基地\"\n  MAP_XBASE: \"X-COM基地\"\n  MAP_MARS: \"火星\"\n  STR_MIXED: \"混合\"\n  STR_REMOVE_SELECTED: \"選択範囲を消去\"\n  STR_LIVE_ALIENS: \"捕虜宇宙人\"\n  STR_DEAD_ALIENS: \"殺害した宇宙人\"\n  STR_UNDER_INTERROGATION: \"現在尋問中\"\n  STR_CONTAINMENT_EXCEEDED: \"隔離拘束施設の許容範囲を超えました！{SMALLLINE}収容スペースが{0} 人分不足しています。彼らが死んでしまう前に超過分のエイリアンを拘束施設から除去する必要があります\"\n  STR_MANAGE_CONTAINMENT: \"隔離拘束施設の管理\"\n  STR_STORAGE_EXCEEDED: \"格納スペースを超過しています！{SMALLLINE}{0}分スペースが足りません。アイテムを売ってください\"\n  STR_GO_TO_BASE: \"基地に戻る\"\n  STR_MELEE_ACCURACY: \"格闘精度\"\n  STR_SELL_PRODUCTION: \"売る\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"両手が空いてなければなりません！\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"装備品のストックが足りません\"\n  STR_UNLOAD_WEAPON: \"弾倉を外す\"\n  STR_ALL_ITEMS: \"選択可能なアイテム\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    other: \"これ以上、兵器および装備を搭載することはできません!{SMALLLINE}輸送機に搭載できるアイテムは{N}個に制限されています。\"\n  STR_CONTROL_CENTER_DESTROYED: \"コントロールセンターが破壊されました。入り口へ戻り、'任務中断'を実行してください。\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"X-COMの海洋施設は水中には建てられません\"\n  STR_LEVEL_SHORT: \"{0}\"\n  STR_PERSONNEL: \"構成員\"\n  STR_CRAFT_ARMAMENT: \"軍備\"\n  STR_COMPONENTS: \"パーツ\"\n  STR_SOLDIERS_RECRUITED: \"雇用した兵士\"\n  STR_SOLDIERS_LOST: \"失った兵士\"\n  STR_TOTAL_UFOS: \"探知したUFO\"\n  STR_TOTAL_ALIEN_BASES: \"発見した宇宙人基地\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"Psi訓練\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"Psi能力\"\n  FEMALE_CIVILIAN: \"民間人-女\"\n  MALE_CIVILIAN: \"民間人-男\"\n  CYBERDISC_WEAPON: \"サイバーディスクの武器\"\n  REAPER_WEAPON: \"リーパーの武器\"\n  CHRYSSALID_WEAPON: \"クリサリドの武器\"\n  CELATID_WEAPON: \"セラチドの武器\"\n  SILACOID_WEAPON: \"シラコイドの武器\"\n  SECTOPOD_WEAPON: \"セクトポッドの武器\"\n  ZOMBIE_WEAPON: \"ゾンビの武器\"\n  ALIEN_PSI_WEAPON: \"エイリアンのPSI兵器\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/ko.yml",
    "content": "ko:\n  STR_AVENGER_UFOPEDIA: \"수송기이자 전투 우주선이다. 외계인 기술을 궁극적으로 재현한 것이다.\"\n  STR_INTERCEPTOR_UFOPEDIA: \"쌍발 펄스 데토네이션 엔진과 특별히 차폐한 전자 장치가 있는 전투 비행기다. 지구 기반 기술로 쓸 수 있는 최고의 물건이다.\"\n  STR_LIGHTNING_UFOPEDIA: \"수송기이자 전투용 기체다. 외계인 추진 장치를 조악하나 효과적으로 재현한 것이다.\"\n  STR_SKYRANGER_UFOPEDIA: \"병력 수송기다. 수직 이륙 및 착륙(V.T.O.L.) 능력이 있는, 이러한 종류 중 가장 빠른 것이다.\"\n  STR_FIRESTORM_UFOPEDIA: \"전투용 기체다. 이 1인승 전투기는 고전적 외계인 비행 접시를 재현하며, 중앙 추진기가 있다.\"\n  STR_STINGRAY_UFOPEDIA: \"특별히 차폐한 전자 장치가 있는 발전된 공대공 미사일이다.\"\n  STR_AVALANCHE_UFOPEDIA: \"핵탄두를 달았으나, 엄청나게 무거운 중량을 지닌 공대공 미사일이다.\"\n  STR_CANNON_UFOPEDIA: \"40cm의 강철을 관통할 능력이 있는 철갑탄을 쏘는 높은 위력의 기총이다.\"\n  STR_FUSION_BALL_UFOPEDIA: \"이 발사기는 반물질 반응으로 위력을 내는 공 모양의 미사일을 쏜다. 이 공은 중력파의 내파로 표적을 파괴한다.\"\n  STR_LASER_CANNON_UFOPEDIA: \"이 재래식 레이저 빔은 반물질 반응로로 작동된다.\"\n  STR_PLASMA_BEAM_UFOPEDIA: \"이 중력 빔은 정교하게 조절된 중력장 내파를 유도한다.\"\n  STR_SECTOID_UFOPEDIA: \"섹토이드 사회 계층은 병사에서 강력한 사이오닉 능력을 지닌 지도자까지 아우른다. 이 사이오닉 권능은 전투에서 병사의 사기를 깎거나, 심지어 그들의 정신을 장악하는 데까지 이용될 수 있다. 그들은 인간의 유괴와 가축의 해체에 탐닉하는 경향이 있다. 유괴는 이종 교배와 인간 사회에 잠입할 복제 인간을 개발하기 위한 유전 물질을 추출하는 데 이용된다. 가축은 양분과 유전 재료 양쪽을 제공한다. 이 종족은 그들의 벌집 비슷한 사회의 효율을 올리기 위해 우월한 유전적 혼종을 개발하길 원하는 것으로 보인다.\"\n  STR_SECTOID_AUTOPSY: \"섹토이드 검시\"\n  STR_SECTOID_AUTOPSY_UFOPEDIA: \"검시는 흔적만 남은 소화 기관과 단순한 신체 구조를 드러낸다. 두뇌와 눈은 아주 잘 발달되었다. 이 구조는 유전자 변형 또는 변이를 암시한다. 작은 눈과 코는 별 기능이 없는 것으로 보인다. 손가락 사이의 물갈퀴, 그리고 평평한 발은 수중 생물이 기원임을 암시한다. 아무런 생식 기관도 없으며, 어떻게 이 종족이 번식할 수 있는 지에 대해 아무런 단서도 없다. 그들은 유전적으로 조작된 종임이 거의 확실하다.\"\n  STR_SNAKEMAN_UFOPEDIA: \"이 종족은 엄청나게 혹독한 환경에서 발달했다. 그들은 엄청나게 억세며 엄청난 온도 변화에 저항할 수 있다. 그들의 이동은 모든 핵심 장기를 보호하는 뱀 비슷한 거대한 '발'에 의존한다. 그들의 목적은 순수하게 사냥을 하는 것으로 보이며, 그들은 지구에 대한 그들의 군대식 침략을 지시하는 어떤 다른 지성체의 지휘 하에 있는 것으로 보인다.\"\n  STR_SNAKEMAN_AUTOPSY: \"스네이크맨 검시\"\n  STR_SNAKEMAN_AUTOPSY_UFOPEDIA: \"피부는 엄청나게 억세며 열에 잘 저항한다. 심혈관계는 이동을 만들어내기 위한 유압의 원리를 이용하는 근육계의 일부다. 유일한 진짜 근육은 '심장'이다. 그들의 생식 기관은 아주 효율적인 것으로 보인다. 번식 방법은 무성생식이며, 각각의 스네이크맨은 언제라도 그 몸 안에 50개에 이르는 알을 품고 있다.마음대로 하게 두면 이 종족은 지구 상의 생물에게 심각한 위협이 될 것이다.\"\n  STR_ETHEREAL_UFOPEDIA: \"이 존재는 텔레파시 통신과 염동 능력을 쓰도록 하는 끝내주는 정신력을 지닌다. 이 생물의 명백히 약한 육체적 능력은 그 정신적 힘으로 보조를 받는다. 그들이 우리가 아는 물리 법칙을 거부하는 듯하기에, 우리는 이 염동력이 어떻게 일어나는지 이해하지 못한다. 그들은 어떠한 전투 상황에서도 엄청나게 위험한데, 그들이 전투를 정신적 힘에 의존한다. 그들은 자기 목적 달성을 위해 다른 종족에 의존하는 듯하기에 지구에 드물게 나타난다.\"\n  STR_ETHEREAL_AUTOPSY: \"이더리얼 검시\"\n  STR_ETHEREAL_AUTOPSY_UFOPEDIA: \"이 존재는 육체적으로 쇠퇴했고 어떠한 생명 기능을 유지할 역량이 없는 듯하다. 근육은 심각하게 위축되었고 내부 장기는 덜 발달된 것으로 보인다. 감각 기관은, 눈을 포함해, 전혀 기능하지 못하는 것으로 보인다. 두뇌는, 그렇지만, 잘 발달되었고 몸의 혈액 공급 중 높은 부분을 끌어다 쓴다. 어떻게 이 생물이 외부 지원 없이 스스로를 지탱할 수 있는지는 수수께끼다.\"\n  STR_MUTON_UFOPEDIA: \"이 인간형 생물은 육체적인 힘이 세고 지능적이다. 그들은 어떠한 종류건 생 살점을 섭취하는 특별한 식성을 지니는데, 이는 그들이 지구 출신의 육식동물 같이 생존을 위해 필요하다. 그들은 '이더리얼'로 알려진 종족으로부터 받는 텔레파시 명령에 의존하는 것으로 보인다. 일단 이 텔레파시 연결로부터 분리되면 그들의 정신 체계는 무너지는 것으로 보이고 그들은 죽는다. 사이버네틱 삽입물이 그들의 전투 능력을 강화하기 위해 이용된다. 그들은 분명히 더 높은 지성체를 위한 보병이다.\"\n  STR_MUTON_AUTOPSY: \"뮤톤 검시\"\n  STR_MUTON_AUTOPSY_UFOPEDIA: \"이 생물의 '피부'는 몸에 접목된 유기적으로 만들어진 보호 장갑인 것으로 보인다. 심혈관계 및 감각을 강화하는 데 이용되는 다수의 사이버네틱 삽입물이 있다. 생식 기관은 수술로 제거된 것으로 보인다. 명백히 이 불행한 생물은 전쟁과 정복의 나날을 지낼 뿐이다. 철갑 탄약은 그들의 억세진 피부에 대해 그리 효과적이지 않다.\"\n  STR_CELATID_UFOPEDIA: \"이 생명체는 공기 중에 떠다니는 신비한 기본 능력을 지닌다. 그건 인간의 뇌파를 탐지하는 것으로 보이고 잘 숨어있다 하여도 인간 표적을 향해 움직일 것이다. 일단 표적이 탐지되면 셀라티드는 착륙해 엄청나게 부식성이 강한 독으로 이루어진 작은 방울을 쏜다. 이 생물은 걱정스러울 정도로 스스로를 복제하는 능력을 지닌다. 그건 돌아다닐 때 뮤톤 종족과 함께한다.\"\n  STR_CELATID_AUTOPSY: \"셀라티드 검시\"\n  STR_CELATID_AUTOPSY_UFOPEDIA: \"심장부에는 자연적으로 발달된 반중력 추진 장치인 것으로 보이는 작은 생체기계 장치가 들어 있다. 독 샘은 가장 커다란 장기이고 구분되는 두뇌 구조가 있는 것으로 보이지 않는다. 분별할 수 있는 아무런 소화 또는 생식 기관도 없다. 작은 장기는 새로운 존재로 급속히 성장할 수 있는 태아가 들어 있다.\"\n  STR_SILACOID_UFOPEDIA: \"이 실리콘 기반 생명체는 막대한 양의 열을 생성한다. 그건 이후 그 뜨거운 속살로 흡수할 수 있는 바위를 부술 힘을 지닌다. 그건 원시적인 지능을 지니고 삽입물 또는 텔레파시를 다루는 존재에 의해 통제될 수 있다. 그건 뮤톤이라는 외계 종족과 함께 일한다.\"\n  STR_SILACOID_AUTOPSY: \"실라코이드 검시\"\n  STR_SILACOID_AUTOPSY_UFOPEDIA: \"이 생물의 속살은 엄청나게 뜨겁고, 소화 기관의 기초가 되는 듯하다. 그 독특한 근육계는 굉장한 힘과 속도를 지닌다. 그 바위 비슷한 피부는 불 또는 소이 탄약에 의해 상하지 않는다.\"\n  STR_CHRYSSALID_UFOPEDIA: \"이 생물의 게와 비슷한 발톱은 근접 전투에서 강력한 무기다. 이 생물의 높은 신진대사와 근력은 속도 및 날렵함을 준다. 그건 피해자를 죽이는 대신 몸에 알을 까고 피해자를 걸어 다니는 좀비로 바꾸는 맹독을 주입한다. 새로운 크리살리드는 알까기 직후 피해자로부터 튀어 나온다. 크리살리드는 스네이크맨 종족과 함께한다.\"\n  STR_CHRYSSALID_AUTOPSY: \"크리살리드 검시\"\n  STR_CHRYSSALID_AUTOPSY_UFOPEDIA: \"이 생물의 외골격은 엄청나게 억세나, 폭발 탄약에 놀랍도록 취약하다. 두뇌는 잘 발달되었고, 세포 성장률은 대단히 빠르다. 이 생물은 다른 생체 내부에 낳을 20개의 알을 지닌다. 이 생물은 아주 효과적인 테러 무기다.\"\n  STR_FLOATER_UFOPEDIA: \"플로터는 주로 병사 및 테러 요원이다. 그들은 당연히 사냥하는 야수로, 만만찮은 전사를 만들기 위해 유전적으로 처리되었고 사이버네틱으로 강화되었다. 몸의 아래 절반과 대부분의 내부 장기는 수술로 제거되었고, 생명 유지 장치가 설치되었다. 이 삽입물은 이 생물을, 비록 불안정하지만, 공기 중을 떠다니도록 하는 반중력 장치가 들어 있다.\"\n  STR_FLOATER_AUTOPSY: \"플로터 검시\"\n  STR_FLOATER_AUTOPSY_UFOPEDIA: \"이 생물은 수술에 의해 극적으로 변화되어 버렸다. 몸의 핵심을 형성하는 듯한 장치는 생명 유지 장치로, 심장, 폐 그리고 소화 기관의 기능을 대신한다. 이는 이 생물이 엄청나게 혹독한 환경에서 생존하는 걸 가능하게 하는 것 같다. 두뇌는 우리 것보다 작으나, 감각 기관은 잘 발달되었다.\"\n  STR_REAPER_UFOPEDIA: \"이 이족보행하는 육식동물은 강력한 아가리와 게걸스러운 식성을 지닌다. 그건 활동을 통제하는 데 이용되는 다수의 두뇌 삽입물을 지닌다. 이 생물의 원초적인 사냥 본능은 테러와 파괴를 일으키는 걸 제외하는 거의 사용되지 않는다. 리퍼는 플로터와 보통 함께한다.\"\n  STR_REAPER_AUTOPSY: \"리퍼 검시\"\n  STR_REAPER_AUTOPSY_UFOPEDIA: \"리퍼는 심하게 다쳤을 때조차 기능을 하게 하는 두 개의 '두뇌'와 두 개의 '심장'을 지닌다. 그렇지만, 그 털이 무성한 피부는 대단히 불이 잘 붙어, 이 생물을 소이 무기에 취약하게 만든다.\"\n  STR_SECTOPOD_UFOPEDIA: \"섹토포드는 강력한 레이저 빔 무기가 있는 로봇 생물이다. 이 기계 야수의 제어는 조종사, 이더리얼의 텔레파시 연결을 통해 이루어진다. 섹토포드는 외계인 군대가 쓸 수 있는 가장 강력한 테러 무기다.\"\n  STR_SECTOPOD_AUTOPSY: \"섹토포드 검시\"\n  STR_SECTOPOD_AUTOPSY_UFOPEDIA: \"이 로봇은 대다수 형태의 공격, 특히 플라스마 무기에 저항할 능력 있는 동력 장갑으로 견고하게 건조되었다. 그렇지만, 그 감각 회로는 레이저 무기에 특히 취약한 듯하다.\"\n  STR_CYBERDISC_UFOPEDIA: \"이 축소 비행 접시는 강력한 플라스마 빔으로 무장한 자율적 테러 무기다. 반중력 추진기는 험난한 환경에서 큰 이점을 준다. 그 주요 기능은 섹토이드 종족의 필요에 따른 파괴와 테러다.\"\n  STR_CYBERDISC_AUTOPSY: \"사이버디스크 검시\"\n  STR_CYBERDISC_AUTOPSY_UFOPEDIA: \"사이버디스크는 잘 차폐되었고 폭발 탄약을 버티는 데 특히 능하다. 주 반중력 장치는 그 기능에 대해 어떠한 이해를 얻기에는 너무 심하게 망가졌다.\"\n  STR_UFO_POWER_SOURCE_UFOPEDIA: \"외계인 기체의 동력원은 강력한 중력파 뿐만 아니라 다른 형태의 에너지를 생성하기 위해 엘레리움(115번 원소)을 이용하는 반물질 반응로다. 물질의 에너지 변환률은 믿을 수 없는 99%의 효율을 보이며, 따라서 자그마한 양의 엘레리움이 거대한 양의 동력을 만들어낼 수 있다. 이 장치는 외계 합금을 이용해 쉽게 재현할 수 있다.\"\n  STR_UFO_NAVIGATION_UFOPEDIA: \"외계인의 기체는 지구 위와 우주 공간을 항해하기 위해 정교한 컴퓨터를 이용한다. 이 장치는 네트워크 형태로 배열된 광학 처리 장치에 기반한다. 제어 인터페이스는 상대적으로 단순하다 - 항법사는 기체를 어떤 방향으로 움직이기 위해 동력원에서 생성된 중력파의 방향을 제어한다. 이 장치는 인간이 쉽게 이용할 수 있고, 외계 합금과 다른 부품을 이용해 재현할 수 있다.\"\n  STR_UFO_CONSTRUCTION_UFOPEDIA: \"외계인의 기체는 세 주요 부품으로 이루어진다 - 동력원, 항법 장치 및 외계 합금으로 만들어진 선체다. 선체는 중력파가 유도 및 제어될 수 있도록 특별히 설계된다. 추가로 동력원을 움직이는 데 적은 양의 엘레리움이 요구된다. 일단 건조 원리가 이해되었고, 부품 각각의 기능이 알려졌기에, 이러한 유형의 기체를 만드는 게 가능하다.\"\n  STR_ALIEN_FOOD_UFOPEDIA: \"이 용기는 가축, 다른 동물과 심지어 인간의 신체 일부를 소화하는 데 이용되는 다양한 효소가 들어 있다. 이 액체는 이후 즉석 소화 식품으로서 섭취된다 - 아마도 혈류에 직접. 이는 식량을 지구에 일정 부분 의존함을 암시한다 - 지구와 외계인 사회 간의 공생이라는 형태로.\"\n  STR_ALIEN_REPRODUCTION_UFOPEDIA: \"이 용기는 외계인의 태아가 들어 있다. 이 용기의 설계는 이 장치를 이용하는 외계인이 인공 번식에 완전히 의존한다는 것을 암시하는 듯하다. 풍부한 영양분은 태아의 급속한 발달을 보장한다. 이 공장 생산 체계는 짧은 시간 간격 안에 수천의 외계인 복제 생물을 만들어낼 수 있었다. 이 공정은 인간의 번식, 또는 외계인-인간 혼종에 쉽게 적용될 수 있었다.\"\n  STR_ALIEN_ENTERTAINMENT_UFOPEDIA: \"이 구체의 가장 비슷한 기능은 여가다. 사이오닉 회로는 두뇌의 다양한 중추를 자극한다. 그 효과는 환각 약물과 비슷하다. 이는 외계인이 어떤 문화 또는 여가 활동을 즐긴다는 유일한 증거다.\"\n  STR_ALIEN_SURGERY_UFOPEDIA: \"이 수술 장비는 가축 및 다른 동물의 특정 신체 부위를 추출하기 위한 레이저 절단기를 이용한다. 널리 퍼진 가축 해체는 이 괴기한 외계인 활동으로 설명될 수 있다. 이 부위들은 영양분 또는 유전자 확보 목적으로 이용되는 것 같다.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"과거에 수천 명의 사람들은 외계인에 의해, 때때로 반복해서 유괴되었다고 주장했다. 진실은 훨씬 더 끔찍하다. 인간은 유괴되어, 연구 및 감시를 당했다. 최고의 표본은 유전 재료를 추출 당했다. 여성은 인간-외계인 혼종 태아가 삽입되었고, 수 개월 후 제거되었다. 외계인이 어떤 사악한 동기를 가졌는지 누가 알겠는가?\"\n  STR_ALIEN_ALLOYS_UFOPEDIA: \"외계인의 기체는 독특한 특성이 있는 특별한 합금으로 건조된다. 그건 엄청나게 가볍고 튼튼하며, 전자기 방식으로 찍어낼 수 있다. 이 재료는 재현할 수 있고 많은 종류의 제조 공정에 이용될 수 있다.\"\n  STR_ELERIUM_115_UFOPEDIA: \"이 원소는 특정 입자로 때렸을 대 반물질 동력을 생성하는 비상한 속성을 지닌다. 이는 중력파 및 다른 형태의 에너지를 생성한다. 그건 우리 태양계에서 자연적으로 발견되지 않고 재현될 수 없다.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"우리가 지구에서 지는 싸움을 벌이고 있음은 명확하다. 외계인의 무리는 압도적인 숫자를 보인다. 우리가 할 수 있는 최선은 그들의 진도를 늦추는 것이다. 인류를 위한 유일한 희망은 외계인을 원점에서 쓰러트리는 것이다. 우리 연구는 우리 태양계 내부에 가까운 작전 기지가 있음을 가리키는 듯하다. 외계인은 이곳이 인류 역사 이전의 고대 문명의 중심부였음을 내비친다. 우리는 가능한 빨리 이곳의 자리를 잡아 내야 한다. 그렇지만, 우리는 더 자세한 정보를 얻기 위해 외계인의 지도자를 포획해 심문할 필요가 있다. 더 커다란 UFO는 아마도 적어도 한 마리의 외계인 지도자가 있을 것이다.\"\n  STR_THE_MARTIAN_SOLUTION_UFOPEDIA: \"우리 연구는 이제 외계인 작전 기지가 화성임을 지목한다. 그 기지는 잘 숨겨졌고, 지구의 잠입에 불을 지필 모든 제조 및 복제 시설이 들어 있다. 그건 또한 전체 작전을 지휘하는 어떤 종류의 제어 컴퓨터가 들어 있는 듯하다. 벌집 비슷한 외계인의 사회는 어떤 종류의 '여왕벌이 있는 듯하다. 이는 그들의 근원적 약점이다 - 만약 우리가 이 '두뇌'를 제거할 수 있다면 육체는 죽을 것이다. 우리는 너무 늦기 전에 연구에 더욱 매진해야 한다. 진도를 나가기 위해 우리는 오직 외계인 기지와 전함에만 거주하는 최고위 외계인을 - 사령관을 - 반드시 포획해야 한다.\"\n  STR_CYDONIA_OR_BUST_UFOPEDIA: \"이제 외계인의 무리가 사이도니아 안의 지하 기지에서 지휘를 받는다는 게 명확하다 - 다섯 면을 가진 피라미드와 인간 얼굴을 닮은 커다란 형상이 특징인 화성의 비상한 영역이다. 사이도니아의 문명은 수백 만년 전 화성에서 한때 번성했으나,우리는 왜 그게 자취를 감추었는지, 아니면 그곳의 최근 외계인 활동과 어떤 관계가 있는지 알지 못한다. 설명이 무엇이건 우리는 반드시 사이도니아로 원정대를 보내야 한다. 이는 우리가 외계인을 물리칠 수 있는 유일한 방법이다. 우리는 지휘를 하는 중추 '두뇌'를 반드시 부수어야 한다. 우리는 우리 뜻대로 쓸 가장 끝내주는 파괴력을 장착한 어벤저 기체가 필요할 것이다. 우리가 여기서 배울 수 있는 건 더 이상 없다 - 우리는 사이도니아의 강습 결과를 기다려야 한다.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"현장을 화면 가운데로-시간=5초\"\n  STR_CANCEL_UC: \"취소\"\n  STR_NONE: \"없음\"\n  STR_UNKNOWN: \"불명\"\n  STR_POOR: \"나쁨\"\n  STR_AVERAGE: \"보통\"\n  STR_GOOD: \"좋음\"\n  STR_EXCELLENT: \"훌륭함\"\n  STR_BUILD_NEW_BASE_UC: \"새 기지 짓기\"\n  STR_BASE_INFORMATION: \"기지 정보\"\n  STR_EQUIP_CRAFT: \"기체 장비\"\n  STR_BUILD_FACILITIES: \"시설 건설\"\n  STR_RESEARCH: \"연구\"\n  STR_MANUFACTURE: \"제조\"\n  STR_TRANSFER_UC: \"이송\"\n  STR_PURCHASE_RECRUIT: \"구매/고용\"\n  STR_SACK: \"해고\"\n  STR_SELL_SACK_UC: \"매각/해고\"\n  STR_GEOSCAPE_UC: \"지구 화면\"\n  STR_NAME: \"이름\"\n  STR_AREA: \"영역\"\n  STR_BUILD_NEW_BASE: \"새 기지 짓기\"\n  STR_CANCEL: \"취소\"\n  STR_COST_UC: \"비용>\"\n  STR_CONSTRUCTION_TIME_UC: \"건설 시간>\"\n  STR_DAY:\n    other: \"{N} 일\"\n  STR_HOUR:\n    other: \"{N} 시간\"\n  STR_MAINTENANCE_UC: \"유지비>\"\n  STR_OK: \"확인\"\n  STR_INSTALLATION: \"설비\"\n  STR_CURRENT_RESEARCH: \"현재 연구\"\n  STR_SCIENTISTS_AVAILABLE: \"쓸 수 있는 과학자>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"할당된 과학자>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"쓸 수 있는 연구 공간>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"연구 과제\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"할당된 과학자\"\n  STR_PROGRESS: \"진도\"\n  STR_NEW_PROJECT: \"새로운 과제\"\n  STR_CANCEL_PROJECT: \"과제 취소\"\n  STR_NEW_RESEARCH_PROJECTS: \"새로운 연구 과제\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"쓸 수 있는 과학자>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"쓸 수 있는 연구 공간>{ALT}{0}\"\n  STR_INCREASE: \"증가\"\n  STR_DECREASE: \"감소\"\n  STR_START_PROJECT: \"과제 시작\"\n  STR_CURRENT_PRODUCTION: \"현재 생산\"\n  STR_ENGINEERS_AVAILABLE: \"쓸 수 있는 공학자>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"할당된 공학자>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"쓸 수 있는 작업 공간>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"현재 자금>{ALT}{0}\"\n  STR_ITEM: \"물품\"\n  STR_ENGINEERS__ALLOCATED: \"할당된{NEWLINE}공학자\"\n  STR_UNITS_PRODUCED: \"생산된{NEWLINE}유닛\"\n  STR_TOTAL_TO_PRODUCE: \"생산하려는 총수\"\n  STR_COST__PER__UNIT: \"유닛{NEWLINE}당{NEWLINE}비용\"\n  STR_DAYS_HOURS_LEFT: \"남은 기간\"\n  STR_NEW_PRODUCTION: \"새로운 생산\"\n  STR_PRODUCTION_ITEMS: \"생산 물품\"\n  STR_CATEGORY: \"분류\"\n  STR_START_PRODUCTION: \"생산 시작\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"유닛 하나 생산하는 데 {0} 인시\"\n  STR_COST_PER_UNIT_: \"유닛 당 비용>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"요구되는 작업 공간>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"요구되는 특별 재료\"\n  STR_ITEM_REQUIRED: \"요구되는 물품\"\n  STR_UNITS_REQUIRED: \"요구되는 개수\"\n  STR_UNITS_AVAILABLE: \"쓸 수 있는 개수\"\n  STR_STOP_PRODUCTION: \"생산 정지\"\n  STR_ENGINEERS_AVAILABLE_UC: \"쓸 수 있는 공학자>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"쓸 수 있는 작업 공간>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"월 수익>{ALT}{0}\"\n  STR_INCREASE_UC: \"증가\"\n  STR_DECREASE_UC: \"감소\"\n  STR_UNITS_TO_PRODUCE: \"생산할{NEWLINE}개수\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"구매/직원 고용\"\n  STR_COST_OF_PURCHASES: \"구매 비용>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"단가\"\n  STR_QUANTITY_UC: \"수량\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"쓸 수 있는 직원:총 직원>\"\n  STR_SOLDIERS: \"병사\"\n  STR_SCIENTISTS: \"과학자\"\n  STR_ENGINEERS: \"공학자\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"사용된 공간:쓸 수 있는 공간>\"\n  STR_LIVING_QUARTERS: \"생활관\"\n  STR_STORES: \"창고\"\n  STR_LABORATORIES: \"연구실\"\n  STR_WORK_SHOPS: \"작업실\"\n  STR_HANGARS: \"격납고\"\n  STR_SHORT_RANGE_DETECTION: \"단거리 탐지기\"\n  STR_DEFENSE_STRENGTH: \"방위력\"\n  STR_TRANSFERS_UC: \"이송\"\n  STR_TRANSFERS: \"이송\"\n  STR_ARRIVAL_TIME_HOURS: \"도착 소요시간(시간)\"\n  STR_COST_: \"비용>{ALT}{0}\"\n  STR_AREA_: \"영역>{ALT}{0}\"\n  STR_BASE_NAME: \"기지 이름?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"출입 승강기 위치 지정\"\n  STR_TRANSFER: \"이송\"\n  STR_AMOUNT_TO_TRANSFER: \"이송하려는 양\"\n  STR_SELECT_DESTINATION_BASE: \"행선지 기지 선택\"\n  STR_COST: \"비용\"\n  STR_VICTORY_1: \"방으로 들어가자 당신은 외계인 두뇌를 본다 - 당신이 찾던 목표를. 당신이 쏘려 하기 전에 그건 기지에 있는 화면을 통해 당신과 교신한다. 그건 당신이 방아쇠를 당기려는 결정을 하기 전에 자신의 생존에 대한 항변을 들어 줄 것을 간청한다...\"\n  STR_VICTORY_2: \"그 두뇌는 말한다: '수백 만년 전 너희가 화성이라 부르는 행성은 살아 있었다. 이 생명은 너희에게 했던 것처럼 우리 문명이 황량한 행성으로 가져왔었지. 수백 만년 동안 우리는 너희 행성을 들렀고 너희 종족을 유전적으로 개발했다. 너희는 우릴 죽일 수 없다, 너희는 우리의 일부다...\"\n  STR_VICTORY_3: \"여기는 너희 선대 종이 세운 - 너희 것보다 수백 만년 전에 지어진 피라미드로 - 화성 문명의 중심이다. 어느 행성도 너희의 성과에 미치지 못했다. 이 힘은 오래지 않아 너희 것이 될 수 있었어. 우리가 요청하는 건 협력이 전...\"\n  STR_GAME_OVER_1: \"외계인은 모든 인류를 말살하려 하며, 도시를 부수고 대기와 바다에 독을 풀어 놓는다. 지구 군대의 저항은 엄청나게 우월한 기술 앞에서 효과가 없다. 살아남은 세대는 외계인의 파괴에서 도망치는 동안 끔찍한 변이에 시달린다. 그들은 지구를 어떤 알려지지 않은 제국의 일부인 외계인 식민지로 바꾸는 걸 돕기 위해 노예 수용소에 모아졌다.\"\n  STR_GAME_OVER_2: \"X-Com 프로젝트를 통해 얻었던 지식은 영원히 잃어버렸다. 당신은 지구를 구하는 데 실패했다.\"\n  STR_VICTORY_4: \"그 외계인의 두뇌는 뜨거운 플라스마의 폭발에 의해 작동 중단되었고, 모든 외계인 세력은 패배했다.\"\n  STR_VICTORY_5: \"일단 외계인이 화성을 잃으면서 지구도 잃었다. 오래지 않아 X-Com의 연구는 다시 한번 인류를 번영하게 하였고, 화성을 영토로 선포한다. 외계인의 위협은 사라졌으나, 얼마나 오래 갈지, 그건 아무도 모른다...\"\n  STR_YOU_HAVE_FAILED: \"당신은 외계인의 맹공을 저지하는 데 실패했다. 후원 국가들은 하나하나 기술, 번영 및 평화를 약속하는 외계인과 조약을 체결한다. 그렇지만, 외계인이 다른 계획을 지니고 있음이 곧 분명해졌다...\"\n  STR_TOTAL_UC: \"합계\"\n  STR_INCOME: \"수입\"\n  STR_EXPENDITURE: \"지출\"\n  STR_MAINTENANCE: \"유지비\"\n  STR_BALANCE: \"수지\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"영역별 UFO 활동\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"국가별 UFO 활동\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"영역별 X-COM 활동\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"국가별 X-COM 활동\"\n  STR_FINANCE: \"재정\"\n  STR_DATE_FIRST: \"{0}일\"\n  STR_DATE_SECOND: \"{0}일\"\n  STR_DATE_THIRD: \"{0}일\"\n  STR_DATE_FOURTH: \"{0}일\"\n  STR_FINANCE_THOUSANDS: \"$1000's\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"{1}{NEWLINE}에서{NEWLINE}{0}{NEWLINE}의 생산을 위한 특별 재료가 부족하다\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"{1}{NEWLINE}에서{NEWLINE}{0}{NEWLINE}의 생산을 위한 돈이 부족하다\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"{1}{NEWLINE}에서{NEWLINE}{0}{NEWLINE}의 생산을{NEWLINE}마쳤다\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"{1}{NEWLINE}에서{NEWLINE}{0}{NEWLINE}의 건설을{NEWLINE}마쳤다\"\n  STR_OK_5_SECONDS: \"확인 - 5초\"\n  STR_RESEARCH_COMPLETED: \"연구 완료\"\n  STR_VIEW_REPORTS: \"보고서 열람\"\n  STR_WE_CAN_NOW_RESEARCH: \"이제 아래를 연구할 수 있다\"\n  STR_WE_CAN_NOW_PRODUCE: \"이제 아래를 생산할 수 있다\"\n  STR_SUNDAY: \"일요일\"\n  STR_MONDAY: \"월요일\"\n  STR_TUESDAY: \"화요일\"\n  STR_WEDNESDAY: \"수요일\"\n  STR_THURSDAY: \"목요일\"\n  STR_FRIDAY: \"금요일\"\n  STR_SATURDAY: \"토요일\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"{2}에서 {1}에 주유하기 위한 {0}이 충분하지 않다\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"{2}에서 {1}를 재무장하기 위한 {0}이 충분하지 않다\"\n  STR_UFO_IS_NOT_RECOVERED: \"UFO가 회수되지 않았다\"\n  STR_UFO_IS_RECOVERED: \"UFO가 회수되었다\"\n  STR_CRAFT_IS_LOST: \"기체를 잃었다\"\n  STR_TERROR_CONTINUES: \"테러는 계속된다\"\n  STR_ALIENS_DEFEATED: \"외계인은 물러났다\"\n  STR_BASE_IS_LOST: \"기지를 잃었다\"\n  STR_BASE_IS_SAVED: \"기지는 무사하다\"\n  STR_ALIEN_BASE_STILL_INTACT: \"외계인 기지는 여전히 활동한다\"\n  STR_ALIEN_BASE_DESTROYED: \"외계인 기지를 부수었다\"\n  STR_ALIENS_KILLED: \"죽인 외계인\"\n  STR_ALIEN_CORPSES_RECOVERED: \"회수한 외계인 시체\"\n  STR_LIVE_ALIENS_RECOVERED: \"회수한 살아있는 외계인\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"회수한 외계인 유물\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"부순 외계인 식민지 제어부\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"외계인이 죽인 민간인\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"X-COM 요원이 죽인 민간인\"\n  STR_CIVILIANS_SAVED: \"민간인 구조\"\n  STR_XCOM_OPERATIVES_KILLED: \"죽은 X-COM 요원\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"작전 중 실종된 X-COM 요원\"\n  STR_TANKS_DESTROYED: \"부서진 탱크\"\n  STR_XCOM_CRAFT_LOST: \"잃어버린 X-COM 기체\"\n  STR_UFO_RECOVERY: \"UFO 회수\"\n  STR_ALIEN_BASE_RECOVERY: \"외계인 기지 회수\"\n  STR_BASE_UNDER_ATTACK: \"{0} 기지가 공격을 받는다!\"\n  STR_BASE_DEFENSES_INITIATED: \"기지 방어 개시\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"중력 방어막이 UFO를 밀어냄!\"\n  STR_FIRING: \"발포\"\n  STR_HIT: \"명중!\"\n  STR_UFO_DESTROYED: \"UFO 파괴!\"\n  STR_MISSED: \"빗나감!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"물품 매각/직원 해고\"\n  STR_VALUE_OF_SALES: \"판매가> {ALT}{0}\"\n  STR_FUNDS: \"자금> {ALT}{0}\"\n  STR_SELL_SACK: \"매각/해고\"\n  STR_VALUE: \"가격\"\n  STR_CRAFT_: \"기체> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}호\"\n  STR_UFO_CRASH_RECOVERY: \"UFO 잔해 회수\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"주의 요망 - UFO 안이나 추락 현장 주변에 요원이 있을 지 모른다. 임무는 모든 적 유닛이 제거되거나 무력화될 때 완료될 것이다. UFO 잔해, 유물 및 외계인 시체에 대한 회수는 이후에 개시될 수 있다. 임무를 중단하려면 X-Com 요원을 수송 차량으로 보내고 '임무 중단' 아이콘을 눌러라.\"\n  STR_UFO_GROUND_ASSAULT: \"UFO 지상 강습\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"착륙 현장을 탐험하고, 만약 가능하다면, UFO에 진입하라. 임무는 모든 적 유닛이 제거되거나 무력화될 때 완료될 것이다. UFO, 유물 및 외계인 시체에 대한 회수는 이후에 개시될 수 있다. 임무를 중단하려면 X-Com 요원을 수송 차량으로 보내고 '임무 중단' 아이콘을 눌러라.\"\n  STR_BASE_DEFENSE: \"기지 방어\"\n  STR_BASE_UC_: \"기지> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"외계인 함선 하나가 근처에 착륙했다. 우리 기지는 심각한 위험에 처해 있다. 표준 절차에 따라 모든 비전투 직원과 X-Com 기체는 대피했다. 외계인은 격납고 문 또는 출입 승강기를 통해 기지로 들어올 것이다. 무슨 수를 쓰더라도 기지와 중요 설비를 방어하라 - 이것은 목숨을 건 싸움이다. 만약 '임무 중단' 아이콘을 누르면 당신은 패배를 인정하고 기지를 잃을 것이다.\"\n  STR_ALIEN_BASE_ASSAULT: \"외계인 기지 강습\"\n  STR_ALIEN_BASE_ASSAULT_BRIEFING: \"X-Com 요원은 외계인의 기지로 가는 입구를 확보했다. 기지를 무력화하려면 제어부가 반드시 부서져야 한다. 이 임무는 모든 적이 제거될 때, 또는 당신의 분대가 녹색 출구 영역으로 돌아왔을 때(탈출하려면 '임무 중단' 아이콘을 눌러라) 종료할 것이다.\"\n  STR_CYDONIA_BRIEFING: \"당신은 사이도니아에 도착했다. 당신은 화성의 스핑크스 근처의 커다란 지하 단지로 가는 입구를 확보했다. 당신은 모든 외계인 활동을 제어하는 외계인 두뇌를 반드시 부수어야 한다. 인류의 운명은 당신의 손에 달렸다...\"\n  STR_TERROR_MISSION: \"테러 임무\"\n  STR_TERROR_MISSION_BRIEFING: \"임무는 모든 적 유닛이 제거되거나 무력화될 때 성공으로 끝날 것이다. 당신은 외계인의 위협을 제거해 이 영역에 있는 어떠한 시민의 생명도 반드시 살리려고 노력해야 한다. 임무를 중단하려면 X-Com 요원을 수송 차량으로 보내고 '임무 중단' 아이콘을 눌러라.\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"기체 생산에 필요한 빈 격납고가 없다!{SMALLLINE}기지에 할당, 기지로 이송, 구매 또는 건조한 각각의 기체는 하나의 격납고를 이용한다. 새로운 격납고를 짓거나 또 다른 기지로 기체를 이송하라.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"구매에 필요한 빈 격납고가 없다!{SMALLLINE}기지에 할당, 기지로 이송, 구매 또는 건조한 각각의 기체는 하나의 격납고를 이용한다. 새로운 격납고를 짓거나 또 다른 기지로 기체를 이송하라.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"이송에 필요한 빈 격납고가 없다!{SMALLLINE}기지에 할당, 기지로 이송, 구매 또는 건조한 각각의 기체는 하나의 격납고를 이용한다. 새로운 격납고를 짓거나 또 다른 기지로 기체를 이송하라.\"\n  STR_CANNOT_BUILD_HERE: \"여기에 지을 수 없다!{SMALLLINE}당신은 반드시 기존 기지 시설 옆에 지어야 한다.\"\n  STR_NO_FREE_ACCOMODATION: \"빈 생활 공간이 없다!{SMALLLINE}행선지 기지는 생활관 안에 충분한 공간을 지니지 않는다.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"쓸 수 있는 작업 공간이 충분하지 않다!{SMALLLINE}새 작업실을 짓거나 다른 과제의 일을 줄여라\"\n  STR_NOT_ENOUGH_MONEY: \"돈이 충분하지 않다!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"저장 공간이 충분하지 않다!{SMALLLINE}새로운 저장 시설을 짓거나 기존 창고 내 물건을 다른 기지로 이송하라.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"생활 공간이 충분하지 않다!{SMALLLINE}새로운 생활관을 짓거나 직원을 다른 기지로 이송하라.\"\n  STR_LAUNCH_INTERCEPTION: \"요격기 발진\"\n  STR_CRAFT: \"기체\"\n  STR_STATUS: \"상태\"\n  STR_BASE: \"기지\"\n  STR_READY: \"대기\"\n  STR_OUT: \"출동했음\"\n  STR_REPAIRS: \"수리 중\"\n  STR_REFUELLING: \"급유 중\"\n  STR_REARMING: \"재무장 중\"\n  STR_TARGET: \"표적: {0}\"\n  STR_WAY_POINT: \"경유지\"\n  STR_ARE_YOU_SURE_CYDONIA: \"당신은 이 기체를 사이도니아로 가는 임무에 보내길 원하는 게 확실한가?\"\n  STR_YES: \"예\"\n  STR_NO: \"아니요\"\n  STR_SELECT_DESTINATION: \"행선지 선택\"\n  STR_CYDONIA: \"사이도니아\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"새로운 기지를 위한 현장 선택\"\n  STR_RETURN_TO_BASE: \"기지로 복귀\"\n  STR_SELECT_NEW_TARGET: \"새로운 표적 선택\"\n  STR_PATROL: \"순찰\"\n  STR_STATUS_: \"상태>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"손상됨 - 기지로 복귀함\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"연료 부족 - 기지로 복귀함\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"임무 완료 - 기지로 복귀함\"\n  STR_PATROLLING: \"순찰 중\"\n  STR_TAILING_UFO: \"UFO 추격 중\"\n  STR_INTERCEPTING_UFO: \"UFO-{0}호 요격 중\"\n  STR_RETURNING_TO_BASE: \"기지로 복귀함\"\n  STR_DESTINATION_UC_: \"행선지: {0\"\n  STR_BASE_UC: \"기지>{ALT}{0}\"\n  STR_SPEED_: \"속도>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"최대 속도>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"고도>{ALT}{0}\"\n  STR_VERY_LOW: \"매우 낮음\"\n  STR_LOW_UC: \"낮음\"\n  STR_HIGH_UC: \"높음\"\n  STR_VERY_HIGH: \"매우 높음\"\n  STR_FUEL: \"연료>{ALT}{0}\"\n  STR_WEAPON_ONE: \"무기-1>{ALT}{0}\"\n  STR_NONE_UC: \"없음\"\n  STR_ROUNDS_: \"잔탄>{ALT}{0}\"\n  STR_WEAPON_TWO: \"무기-2>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"요격 기체\"\n  STR_BASE_: \"기지>{0}\"\n  STR_NAME_UC: \"이름\"\n  STR_AMMO_: \"탄약>{ALT}{0}\"\n  STR_CREW: \"승무원\"\n  STR_EQUIPMENT_UC: \"장비\"\n  STR_ARMOR: \"갑옷\"\n  STR_MAX: \"최대>{ALT}{0}\"\n  STR_ROOKIE: \"이병\"\n  STR_SQUADDIE: \"일병\"\n  STR_SERGEANT: \"하사\"\n  STR_CAPTAIN: \"대위\"\n  STR_COLONEL: \"대령\"\n  STR_COMMANDER: \"준장\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"{0}에 탑승할 분대를 선택\"\n  STR_SORT_BY: \"정렬 기준\"\n  STR_ORIGINAL_ORDER: \"원래 순서\"\n  STR_MISSIONS2: \"참여 임무 수\"\n  STR_KILLS2: \"사살 수\"\n  STR_WOUND_RECOVERY2: \"부상 회복일\"\n  STR_SPACE_AVAILABLE: \"쓸 수 있는 공간>{ALT}{0}\"\n  STR_SPACE_USED: \"쓰이는 공간>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"쓰이는 공간\"\n  STR_RANK: \"계급\"\n  STR_WOUNDED: \"부상\"\n  STR_EQUIPMENT_FOR_CRAFT: \"{0}에 실을 장비\"\n  STR_DEFENSE_VALUE: \"방위력\"\n  STR_HIT_RATIO: \"명중률\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}가{NEWLINE}{ALT}{1}{NEWLINE}근처에{NEWLINE}착륙 대기\"\n  STR_BEGIN_MISSION: \"임무 개시?\"\n  STR_SELECT_ARMAMENT: \"무장 선택\"\n  STR_AMMUNITION_AVAILABLE: \"쓸 수 있는 탄약\"\n  STR_ARMAMENT: \"무장\"\n  STR_NOT_AVAILABLE: \"불필요\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"{0}{NEWLINE}에 입힐 갑옷 선택\"\n  STR_TYPE: \"유형\"\n  STR_PERSONAL_ARMOR_UC: \"개인 갑옷\"\n  STR_POWER_SUIT_UC: \"동력 갑옷\"\n  STR_FLYING_SUIT_UC: \"비행 갑옷\"\n  STR_SELECT_ARMOR: \"갑옷 선택\"\n  STR_NORTH: \"북쪽\"\n  STR_NORTH_EAST: \"북동쪽\"\n  STR_EAST: \"동쪽\"\n  STR_SOUTH_EAST: \"남동쪽\"\n  STR_SOUTH: \"남쪽\"\n  STR_SOUTH_WEST: \"남서쪽\"\n  STR_WEST: \"서쪽\"\n  STR_NORTH_WEST: \"북서쪽\"\n  STR_SELECT_ACTION: \"행동 선택\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"요격 추적 계속\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"요격 없이 추적\"\n  STR_VERY_LARGE: \"초대형\"\n  STR_LARGE: \"대형\"\n  STR_MEDIUM_UC: \"중형\"\n  STR_SMALL: \"소형\"\n  STR_VERY_SMALL: \"초소형\"\n  STR_GROUNDED: \"지면\"\n  STR_DETECTED: \"탐지됨\"\n  STR_SIZE_UC: \"크기\"\n  STR_ALTITUDE: \"고도\"\n  STR_HEADING: \"이동 방향\"\n  STR_SPEED: \"속도\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"UFO를 화면 가운데로-시간=5초\"\n  STR_TRACKING_LOST: \"추적 소실\"\n  STR_REDIRECT_CRAFT: \"기체 행선지 재지정\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"마지막으로 알려진 UFO 위치로 이동\"\n  STR_UFO_: \"UFO-{0}호\"\n  STR_ALIEN_BASE_: \"외계인 기지-{0}호\"\n  STR_CRASH_SITE_: \"추락 현장-{0}호\"\n  STR_LANDING_SITE_: \"착륙 현장-{0}호\"\n  STR_WAY_POINT_: \"경유지-{0}호\"\n  STR_TERROR_SITE: \"테러 현장-{0}호\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{1}에{NEWLINE}{0}{NEWLINE}도착했음\"\n  STR_NOW_PATROLLING: \"지금 순찰 시작\"\n  STR_ALIEN_ORIGINS: \"외계인의 기원\"\n  STR_THE_MARTIAN_SOLUTION: \"화성의 해결책\"\n  STR_CYDONIA_OR_BUST: \"사이도니아 아니면 죽음을\"\n  STR_UFOPAEDIA: \"UFO 사전\"\n  STR_XCOM_CRAFT_ARMAMENT: \"X-COM 기체 & 무장\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"중화기 차량\"\n  STR_WEAPONS_AND_EQUIPMENT: \"무기 및 장비\"\n  STR_ALIEN_ARTIFACTS: \"외계인 유물\"\n  STR_BASE_FACILITIES: \"기지 시설\"\n  STR_ALIEN_LIFE_FORMS: \"외계 생명체\"\n  STR_ALIEN_RESEARCH_UC: \"외계인 연구\"\n  STR_UFO_COMPONENTS: \"UFO 부품\"\n  STR_UFOS: \"UFO들\"\n  STR_SELECT_ITEM: \"물품 선택\"\n  STR_ACCELERATION: \"가속력>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"연료 용량>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"무장 공간>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"내구도>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"병력 수용량>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"중화기 차량 수용량>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"피해량\"\n  STR_RANGE: \"사거리\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"명중률\"\n  STR_RE_LOAD_TIME: \"발사 간격\"\n  STR_SECONDS: \"{0}초\"\n  STR_DAMAGE_ARMOR_PIERCING: \"철갑\"\n  STR_DAMAGE_INCENDIARY: \"소이\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"폭발\"\n  STR_DAMAGE_LASER_BEAM: \"레이저 빔\"\n  STR_DAMAGE_PLASMA_BEAM: \"플라스마 빔\"\n  STR_DAMAGE_STUN: \"기절\"\n  STR_DAMAGE_MELEE: \"격투\"\n  STR_DAMAGE_ACID: \"강산\"\n  STR_DAMAGE_SMOKE: \"연막\"\n  STR_SHOT_TYPE: \"사격 유형\"\n  STR_ACCURACY_UC: \"정확도\"\n  STR_TIME_UNIT_COST: \"TU 소비\"\n  STR_DAMAGE_UC: \"피해량\"\n  STR_AMMO: \"탄종\"\n  STR_SHOT_TYPE_AUTO: \"자동사격\"\n  STR_SHOT_TYPE_SNAP: \"지향사격\"\n  STR_SHOT_TYPE_AIMED: \"조준사격\"\n  STR_CONSTRUCTION_TIME: \"건설 기간\"\n  STR_CONSTRUCTION_COST: \"건설 비용\"\n  STR_MAINTENANCE_COST: \"유지 비용\"\n  STR_LOW: \"낮음\"\n  STR_MEDIUM: \"중간\"\n  STR_HIGH: \"높음\"\n  STR_CRAFT_WEAPON: \"기체 무장\"\n  STR_CRAFT_AMMUNITION: \"기체 탄약\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"중화기 차량\"\n  STR_WEAPON: \"무기\"\n  STR_AMMUNITION: \"탄약\"\n  STR_EQUIPMENT: \"장비\"\n  STR_ALIEN_CORPSE: \"외계인 시체\"\n  STR_UFO_COMPONENT: \"UFO 부품\"\n  STR_PERSONAL_ARMOR: \"개인 갑옷\"\n  STR_RAW_MATERIALS: \"원재료\"\n  STR_HWP_CANNON_SHELLS: \"HWP 기관포 포탄\"\n  STR_ALIEN: \"외계인\"\n  STR_SECTOID: \"섹토이드\"\n  STR_SNAKEMAN: \"스네이크맨\"\n  STR_ETHEREAL: \"이더리얼\"\n  STR_MUTON: \"뮤톤\"\n  STR_FLOATER: \"플로터\"\n  STR_CELATID: \"셀라티드\"\n  STR_SILACOID: \"실라코이드\"\n  STR_CHRYSSALID: \"크리살리드\"\n  STR_ZOMBIE: \"좀비\"\n  STR_REAPER: \"리퍼\"\n  STR_SECTOPOD: \"섹토포드\"\n  STR_CYBERDISC: \"사이버디스크\"\n  STR_LIVE_COMMANDER: \"사령관\"\n  STR_LIVE_LEADER: \"지도자\"\n  STR_LIVE_ENGINEER: \"공학자\"\n  STR_LIVE_MEDIC: \"의무병\"\n  STR_LIVE_NAVIGATOR: \"항법사\"\n  STR_LIVE_SOLDIER: \"병사\"\n  STR_LIVE_TERRORIST: \"테러분자\"\n  STR_FLOATER_SOLDIER: \"플로터 병사\"\n  STR_FLOATER_NAVIGATOR: \"플로터 항법사\"\n  STR_FLOATER_MEDIC: \"플로터 의무병\"\n  STR_FLOATER_ENGINEER: \"플로터 공학자\"\n  STR_FLOATER_LEADER: \"플로터 지도자\"\n  STR_FLOATER_COMMANDER: \"플로터 사령관\"\n  STR_SECTOID_SOLDIER: \"섹토이드 병사\"\n  STR_SECTOID_NAVIGATOR: \"섹토이드 항법사\"\n  STR_SECTOID_MEDIC: \"섹토이드 의무병\"\n  STR_SECTOID_ENGINEER: \"섹토이드 공학자\"\n  STR_SECTOID_LEADER: \"섹토이드 지도자\"\n  STR_SECTOID_COMMANDER: \"섹토이드 사령관\"\n  STR_SNAKEMAN_SOLDIER: \"스네이크맨 병사\"\n  STR_SNAKEMAN_NAVIGATOR: \"스네이크맨 항법사\"\n  STR_SNAKEMAN_ENGINEER: \"스네이크맨 공학자\"\n  STR_SNAKEMAN_LEADER: \"스네이크맨 지도자\"\n  STR_SNAKEMAN_COMMANDER: \"스네이크맨 사령관\"\n  STR_MUTON_SOLDIER: \"뮤톤 병사\"\n  STR_MUTON_NAVIGATOR: \"뮤톤 항법사\"\n  STR_MUTON_ENGINEER: \"뮤톤 공학자\"\n  STR_ETHEREAL_SOLDIER: \"이더리얼 병사\"\n  STR_ETHEREAL_LEADER: \"이더리얼 지도자\"\n  STR_ETHEREAL_COMMANDER: \"이더리얼 사령관\"\n  STR_CYBERDISC_TERRORIST: \"사이버디스크 테러분자\"\n  STR_REAPER_TERRORIST: \"리퍼 테러분자\"\n  STR_CHRYSSALID_TERRORIST: \"크리살리드 테러분자\"\n  STR_CELATID_TERRORIST: \"셀라티드 테러분자\"\n  STR_SILACOID_TERRORIST: \"실라코이드 테러분자\"\n  STR_SECTOPOD_TERRORIST: \"섹토포드 테러분자\"\n  STR_UFO_POWER_SOURCE: \"UFO 동력원\"\n  STR_UFO_NAVIGATION: \"UFO 항법장치\"\n  STR_UFO_CONSTRUCTION: \"UFO 구조\"\n  STR_ALIEN_FOOD: \"외계인 식량\"\n  STR_ALIEN_REPRODUCTION: \"외계인 번식기\"\n  STR_ALIEN_ENTERTAINMENT: \"외계인 오락기\"\n  STR_ALIEN_SURGERY: \"외계인 수술기\"\n  STR_EXAMINATION_ROOM: \"시험 장치\"\n  STR_ALIEN_ALLOYS: \"외계 합금\"\n  STR_ALIEN_HABITAT: \"외계인 거주지\"\n  STR_POWER_SUIT: \"동력 갑옷\"\n  STR_FLYING_SUIT: \"비행 갑옷\"\n  STR_HWP_ROCKETS: \"HWP 로켓\"\n  STR_HWP_FUSION_BOMB: \"HWP 핵융합 폭탄\"\n  STR_LASER_WEAPONS: \"레이저 무기\"\n  STR_NEW_FIGHTER_CRAFT: \"새로운 전투 기체\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"새로운 전투 수송기\"\n  STR_ULTIMATE_CRAFT: \"궁극의 기체\"\n  STR_LASER_PISTOL: \"레이저 권총\"\n  STR_LASER_RIFLE: \"레이저 소총\"\n  STR_HEAVY_LASER: \"중형 레이저 총\"\n  STR_LASER_CANNON: \"레이저 포\"\n  STR_PLASMA_CANNON: \"플라스마 포\"\n  STR_FUSION_MISSILE: \"핵융합 미사일\"\n  STR_LASER_DEFENSE: \"레이저 방어시설\"\n  STR_PLASMA_DEFENSE: \"플라스마 방어시설\"\n  STR_FUSION_DEFENSE: \"핵융합 방어시설\"\n  STR_GRAV_SHIELD: \"중력 방어막\"\n  STR_MIND_SHIELD: \"정신 방어막\"\n  STR_PSI_LAB: \"사이오닉 연구실\"\n  STR_MOTION_SCANNER: \"동작 스캐너\"\n  STR_MEDI_KIT: \"메디킷\"\n  STR_TANK_CANNON: \"탱크/기관포\"\n  STR_TANK_ROCKET_LAUNCHER: \"탱크/로켓 발사기\"\n  STR_TANK_LASER_CANNON: \"탱크/레이저 포\"\n  STR_HOVERTANK_PLASMA: \"호버탱크/플라스마\"\n  STR_HOVERTANK_LAUNCHER: \"호버탱크/핵융합 폭탄\"\n  STR_STINGRAY_LAUNCHER: \"스팅레이 발사기\"\n  STR_AVALANCHE_LAUNCHER: \"아발란치 발사기\"\n  STR_CANNON: \"기총\"\n  STR_FUSION_BALL_LAUNCHER: \"핵융합 폭탄 발사기\"\n  STR_PLASMA_BEAM: \"플라스마 포\"\n  STR_STINGRAY_MISSILES: \"스팅레이 미사일\"\n  STR_AVALANCHE_MISSILES: \"아발란치 미사일\"\n  STR_CANNON_ROUNDS_X50: \"기총 탄환(x50)\"\n  STR_FUSION_BALL: \"핵융합 폭탄\"\n  STR_SOLDIER: \"병사\"\n  STR_SCIENTIST: \"과학자\"\n  STR_ENGINEER: \"기술자\"\n  STR_NORTH_AMERICA: \"북아메리카\"\n  STR_ARCTIC: \"북극\"\n  STR_ANTARCTICA: \"남극\"\n  STR_SOUTH_AMERICA: \"남아메리카\"\n  STR_EUROPE: \"유럽\"\n  STR_NORTH_AFRICA: \"북아프리카\"\n  STR_SOUTHERN_AFRICA: \"남아프리카\"\n  STR_CENTRAL_ASIA: \"중앙아시아\"\n  STR_SOUTH_EAST_ASIA: \"동남아시아\"\n  STR_SIBERIA: \"시베리아\"\n  STR_AUSTRALASIA: \"오스트랄라시아\"\n  STR_PACIFIC: \"태평양\"\n  STR_NORTH_ATLANTIC: \"북대서양\"\n  STR_SOUTH_ATLANTIC: \"남대서양\"\n  STR_INDIAN_OCEAN: \"인도양\"\n  STR_ALIEN_RESEARCH: \"외계인 연구\"\n  STR_ALIEN_HARVEST: \"외계인 수확\"\n  STR_ALIEN_ABDUCTION: \"외계인 유괴\"\n  STR_ALIEN_INFILTRATION: \"외계인 잠입\"\n  STR_ALIEN_BASE: \"외계인 기지\"\n  STR_ALIEN_TERROR: \"외계인 테러\"\n  STR_ALIEN_RETALIATION: \"외계인 보복\"\n  STR_ALIEN_SUPPLY: \"외계인 보급\"\n  STR_MAXIMUM_SPEED: \"최대 속도\"\n  STR_HYPER_WAVE_DECODER_UC: \"하이퍼웨이브 해석기\"\n  STR_SKYRANGER: \"스카이레인저\"\n  STR_LIGHTNING: \"라이트닝\"\n  STR_AVENGER: \"어벤저\"\n  STR_INTERCEPTOR: \"요격기\"\n  STR_FIRESTORM: \"파이어스톰\"\n  STR_UFO: \"UFO\"\n  STR_STINGRAY: \"스팅레이\"\n  STR_AVALANCHE: \"아발란치\"\n  STR_CANNON_UC: \"기총\"\n  STR_FUSION_BALL_UC: \"핵융합 폭탄\"\n  STR_LASER_CANNON_UC: \"레이저 포\"\n  STR_PLASMA_BEAM_UC: \"플라스마 포\"\n  STR_DAMAGE_CAPACITY: \"내구도\"\n  STR_WEAPON_POWER: \"무기 위력\"\n  STR_WEAPON_RANGE: \"무기 사거리\"\n  STR_ACCESS_LIFT: \"출입 승강기\"\n  STR_LABORATORY: \"연구실\"\n  STR_WORKSHOP: \"작업실\"\n  STR_SMALL_RADAR_SYSTEM: \"소형 레이더 장치\"\n  STR_LARGE_RADAR_SYSTEM: \"대형 레이더 장치\"\n  STR_MISSILE_DEFENSES: \"미사일 방어시설\"\n  STR_GENERAL_STORES: \"범용 창고\"\n  STR_ALIEN_CONTAINMENT: \"외계인 격리실\"\n  STR_LASER_DEFENSES: \"레이저 방어시설\"\n  STR_PLASMA_DEFENSES: \"플라스마 방어시설\"\n  STR_FUSION_BALL_DEFENSES: \"핵융합 방어시설\"\n  STR_PSIONIC_LABORATORY: \"사이오닉 연구실\"\n  STR_HYPER_WAVE_DECODER: \"하이퍼웨이브 해석기\"\n  STR_HANGAR: \"격납고\"\n  STR_USA: \"미국\"\n  STR_RUSSIA: \"러시아\"\n  STR_UK: \"영국\"\n  STR_FRANCE: \"프랑스\"\n  STR_GERMANY: \"독일\"\n  STR_ITALY: \"이탈리아\"\n  STR_SPAIN: \"스페인\"\n  STR_CHINA: \"중국\"\n  STR_JAPAN: \"일본\"\n  STR_INDIA: \"인도\"\n  STR_BRAZIL: \"브라질\"\n  STR_AUSTRALIA: \"호주\"\n  STR_NIGERIA: \"나이지리아\"\n  STR_SOUTH_AFRICA: \"남아프리카공화국\"\n  STR_EGYPT: \"이집트\"\n  STR_CANADA: \"캐나다\"\n  STR_TANK: \"탱크\"\n  STR_CIVILIAN: \"민간인\"\n  STR_JAN: \"1월\"\n  STR_FEB: \"2월\"\n  STR_MAR: \"3월\"\n  STR_APR: \"4월\"\n  STR_MAY: \"5월\"\n  STR_JUN: \"6월\"\n  STR_JUL: \"7월\"\n  STR_AUG: \"8월\"\n  STR_SEP: \"9월\"\n  STR_OCT: \"10월\"\n  STR_NOV: \"11월\"\n  STR_DEC: \"12월\"\n  STR_INTERNATIONAL_RELATIONS: \"국제 관계\"\n  STR_COUNTRY: \"국가\"\n  STR_FUNDING: \"후원금\"\n  STR_CHANGE: \"변동\"\n  STR_WEAPON_SYSTEMS: \"무기 체계\"\n  STR_HWPS: \"HWPs\"\n  STR_DAMAGE_UC_: \"피해량>{ALT}{0}\"\n  STR_ACCESS_LIFT_UFOPEDIA: \"출입 승강기는 지하 기지 안과 밖으로 장비와 직원을 옮기도록 한다. 그건 언제나 새로운 현장에서 건설되는 첫 시설이다. 승강기 영역은 어떠한 잠재적 적대 세력의 침입에도 취약하다.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"각 거주 구역은 50명에 이르는 직원을 위한 공간을 제공한다. 이 시설은 기본적 여가, 식량 및 수면 영역을 제공한다.\"\n  STR_LABORATORY_UFOPEDIA: \"한 연구 시설 안에서 50명에 이르는 과학자가 일할 수 있다. 연구실은 재료공학, 생화학 및 우주론의 연구를 위한 최신 기술이 집약되어 있다. 군사 시설을 포함해, 세계 전역에 걸친 모든 최고의 연구 시설에 대한 특별 접근 권한이 있다.\"\n  STR_WORKSHOP_UFOPEDIA: \"작업실은 과학 연구실에서 나온 설계에 기반한 장비를 제조하기에 필요한 모든 장비가 들어 있다. 비록 건조 중인 물품 또한 공간을 좀 잡아먹을 것이나, 50명에 이르는 공학자가 한 작업실을 차지할 수 있다.\"\n  STR_SMALL_RADAR_SYSTEM_UFOPEDIA: \"소형 탐지 장치는 300해리의 유효 레이더 범위를 지니며 지표 분석을 위한 정지 위성 네트워크와 연결되어 있다. 각각의 장치는 30분의 스캔 주기 당 10%의 평균 크기를 지닌 물체를 탐지할 기회를 지닌다.\"\n  STR_LARGE_RADAR_SYSTEM_UFOPEDIA: \"대형 탐지 장치는 450해리의 유효 범위를 지니며 지표 분석을 위한 정지 위성 네트워크와 연결되어 있다. 각각의 장치는 30분의 스캔 주기 당 20%의 평균 크기를 지닌 물체를 탐지할 기회를 지닌다.\"\n  STR_MISSILE_DEFENSES_UFOPEDIA: \"미사일 방어시설은 기지 주변에 착륙하려 하는 적대적 기체의 침략에 대한 약간의 보호를 제공한다.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"격납고 안의 기체에 할당된 장비를 포함해, 모든 장비, 무기 체계, 탄약, 회수된 재료 및 중화기 차량은 창고에 저장된다.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"살아있는 외계인은 생명을 유지하기 위해 특별한 거주지를 요구할 것이다. 이 격리 시설은 자체 격리 장치 안에 10마리에 이르는 외계 생명체를 보관할 수 있다.\"\n  STR_LASER_DEFENSES_UFOPEDIA: \"레이저 방어시설은 적대적 기체의 침략에 대한 보호를 제공한다.\"\n  STR_PLASMA_DEFENSES_UFOPEDIA: \"플라스마 방어시설은 적대적 기체의 침략에 대한 강력하고 효율적인 보호를 제공한다.\"\n  STR_FUSION_BALL_DEFENSES_UFOPEDIA: \"핵융합 미사일은 외계인의 공격에 대해 가장 효과적인 보호를 제공한다. 이 미사일은 특정 범위 내 모든 것을 부수는 반물질 내파를 일으킨다.\"\n  STR_GRAV_SHIELD_UFOPEDIA: \"중력 방어막은 기지 가까이 착륙하려 하는 외계인의 기체를 모든 방어장치가 다시 쏘기에 충분할 만큼 멀리 밀어낸다. 실제로 이는 당신의 기지에 있는 어떠한 방어 체계의 효력도 두 배로 한다.\"\n  STR_MIND_SHIELD_UFOPEDIA: \"외계인의 기체가 인간 존재의 탐지를 뇌파에 의존하기에 가장 효율적인 대응책은 기지에서 뇌파를 차폐하는 것이다. 이 시설은 외계인의 기체에 의해 탐지될 기회를 극적으로 낮출 것이다.\"\n  STR_PSIONIC_LABORATORY_UFOPEDIA: \"사이오닉 연구실은 기지에 있는 모든 병사의 사이오닉 잠재력을 평가하고 그들의 사이오닉 기술을 활용하는 데 필요한 훈련을 제공할 수 있다. 각각의 연구실은 10명에 이르는 병사를 훈련할 수 있다. 훈련은 매월 말에 할당된다. 사이오닉 증폭기와 결합해 이용한 사이오닉 기술은 전투 중에 사이오닉 공격에 이용될 수 있다.\"\n  STR_HYPER_WAVE_DECODER_UFOPEDIA: \"외계인의 통신은 거의 순간적으로 날아가는 초차원 파동에 의존한다. 이 해석기 시설은 UFO의 지령을 가로채 정보를 해석한다. 이는 UFO 유형, 외계인 종족, 일어날 활동의 유형을 보여줄 것이다.\"\n  STR_HANGAR_UFOPEDIA: \"각 격납고는 기체 하나를 할당할 수 있다. 이건 X-Com 기체의 유지, 급유 및 수리를 위한 시설이다. 기지에 머무르는 각 기체는 설령 그 기체가 임무로 나갔다 해도, 다른 기체가 이용할 수 없는 자기만의 빈 격납고가 반드시 있어야 한다.\"\n  STR_PISTOL_UFOPEDIA: \"이 제식 X-Com 권총은 12발 용량의 강력한 반자동 권총이다.\"\n  STR_RIFLE_UFOPEDIA: \"이 대단히 정확한 저격소총은 레이저 유도 조준기를 지니고 20발 탄창에 든 6.7mm 탄약이 들어간다.\"\n  STR_HEAVY_CANNON_UFOPEDIA: \"중형포는 파괴적이나, 거추장스러운, 그런 무기다. 그 다재다능함은 그게 세 가지 유형의 탄약 - 철갑, 소이 및 고폭탄이 들어간다는 사실에서 나온다.\"\n  STR_AUTO_CANNON_UFOPEDIA: \"기관포는 중형포의 다재다능함과 위력에 더 빠른 발사 속도를 결합한 것이다.\"\n  STR_ROCKET_LAUNCHER_UFOPEDIA: \"로켓 발사기는 서로 다른 세 가지 크기의 미사일을 쏠 수 있는 레이저 유도 장치가 달린 물건이다.\"\n  STR_LASER_PISTOL_UFOPEDIA: \"레이저 권총은 새로운 기술을 효과적으로 적용한 것이다. 그건 권총의 편리함에 더 빠르고 정확한 사격을 지닌다.\"\n  STR_LASER_RIFLE_UFOPEDIA: \"레이저 소총은 이전 권총의 더 강력하고 정확한 형태이다.\"\n  STR_HEAVY_LASER_UFOPEDIA: \"중형 레이저 총은 거추장스러우나, 엄청나게 효과적이다.\"\n  STR_GRENADE_UFOPEDIA: \"이 제식 수류탄은 정교한 기폭 시점 제어를 위한 정확하고 복잡한 타이머를 지닌다.\"\n  STR_SMOKE_GRENADE_UFOPEDIA: \"연막 수류탄은 노출된 전투 상황에서 엄폐를 제공하는 데 유용하다. 그건 적 또한 이득을 볼 수 있으므로 사용에 주의하라.\"\n  STR_PROXIMITY_GRENADE_UFOPEDIA: \"근접 수류탄은 평범한 수류탄 같이 던질 수 있으나 착지한 후 근처의 움직임에 의해 격발된다. 이 장치를 적절하게 이용하려면 대단한 기술과 조심성이 요구된다.\"\n  STR_HIGH_EXPLOSIVE_UFOPEDIA: \"이 폭발물은 오직 철거 목적으로으로만 이용되어야 한다. 철거 현장에서 직원을 비우도록 하라.\"\n  STR_MOTION_SCANNER_UFOPEDIA: \"이 정교한 장치는 이동하는 적 유닛을 식별하기 위해 다양한 탐지기와 발전된 컴퓨터 알고리즘을 이용한다. 그렇지만, 그건 효과적으로 이용하는 데 약간의 연습을 요구한다. 전술 화면에서 동작 스캐너 아이콘을 눌러라. 메뉴에서 '스캐너 이용'을 눌러라. 스캐너 디스플레이는 중앙의 화살표로 병사가 바라보는 방향을 보여 준다(북쪽은 위에 있다). 반짝이는 방울은 최근에 움직였던 유닛을 보여 준다. 커다란 유닛, 또는 빠르게 움직이는 유닛은, 더 커다란 방울을 만들 것이다. 정지한 유닛은 탐지되지 않을 것이다.\"\n  STR_MEDI_KIT_UFOPEDIA: \"메디킷은 진통제 및 각성제와 치료 도구를 결합한 것이다. 메디킷을 이용하기 위해서 당신은 반드시 처치를 요구하는 병사 쪽을 바라보아야 한다. 만약 병사가 기절했으면 당신은 반드시 그 몸 위에 서야 한다. 메디킷 아이콘을 누르고 메뉴에서 '메디킷 이용'을 골라라.{NEWLINE}치료> 적색 신체 부위는 치명상을 보여준다. 다친 신체 부위를 선택하라. '치료' 버튼을 눌러라. 하나의 치명상이 치료되고 약간의 체력이 회복될 것이다.{NEWLINE}각성제> 이것은 기력을 회복하고 의식불명인(기절한) 병사를 되살릴 것이다. 의식불명인 병사를 되살리기 위해 당신은 반드시 그 몸 바로 위에 서야 한다.{NEWLINE}진통제> 이것은 다친 병사에게 잃어버린 체력과 동등한 양에 이르는 사기를 회복할 것이다.\"\n  STR_PSI_AMP_UFOPEDIA: \"사이오닉 증폭기는 오직 사이오닉 기술이 있는 병사만 이용할 수 있다. 전투 중, 사이오닉 증폭기를 누르고, 공격의 유형을 선택하고, 커서로 표적을 골라라. 두 가지 유형의 사이오닉 공격이 있다:{NEWLINE}공황 유발> 만약 공격이 성공하면 그건 표적의 사기를 낮추고 공황을 일으킬 지 모른다..{NEWLINE}정신 지배> 만약 이게 성공하면 당신은 그게 당신 소유였던 것처럼 적 유닛을 즉각적으로 조종할 것이다. 이 유형의 공격을 성공시키는 건 더 어렵다.\"\n  STR_STUN_ROD_UFOPEDIA: \"이 장치는 오직 근접 전투에서만 이용될 수 있으나, 살아있는 생물을 전기 충격을 이용해 죽이지 않고 기절시킬 것이다.\"\n  STR_MIND_PROBE_UFOPEDIA: \"마인드 프로브는 뇌파에서 직접 정보를 취하는 데 이용되는 외계인의 통신 장치다. X-Com 유닛은 외계인의 특징을 표시하기 위해 전투 중에 이 장치를 이용할 수 있다. 마인드 프로브를 누르고 '사용' 선택지를 눌러라. 그리고 커서로 외계인을 눌러라.\"\n  STR_PLASMA_PISTOL_UFOPEDIA: \"플라스마 권총은 국소 반중력장 내부로부터 가속되는 입자에 기반한 치명적인 외계인의 무기다.\"\n  STR_PLASMA_RIFLE_UFOPEDIA: \"이건 국소 반중력장 내부로부터 가속되는 입자에 기반한 파괴적으로 강력한 무기다.\"\n  STR_HEAVY_PLASMA_UFOPEDIA: \"이건 국소 반중력장 내부로부터 가속되는 입자에 기반한 파괴적으로 강력한 무기다.\"\n  STR_BLASTER_LAUNCHER_UFOPEDIA: \"이건 강력한 '블래스터 폭탄'을 쏘는 외계인의 유도 미사일 발사기다. 당신이 무기를 쏘려고 누를 때 그건 블래스터 폭탄이 따라갈 '경유지'를 생성할 것이다. 당신이 충분한 경유지를 지정했을 때 발사 아이콘을 눌러라.\"\n  STR_SMALL_LAUNCHER_UFOPEDIA: \"기절 폭탄을 쏘는 소형 발사기다. 살아있는 외계인을 포획하는 데 아주 유용하다.\"\n  STR_ALIEN_GRENADE_UFOPEDIA: \"이 장치는 지구의 수류탄과 같은 방식으로 작동한다 - 그게 더 강력하다는 걸 제외하면.\"\n  STR_SMALL_SCOUT: \"소형 정찰선\"\n  STR_MEDIUM_SCOUT: \"중형 정찰선\"\n  STR_LARGE_SCOUT: \"대형 정찰선\"\n  STR_HARVESTER: \"수확선\"\n  STR_ABDUCTOR: \"유괴선\"\n  STR_TERROR_SHIP: \"테러함\"\n  STR_BATTLESHIP: \"전함\"\n  STR_SUPPLY_SHIP: \"보급함\"\n  STR_RATING: \"평가> {0}\"\n  STR_RATING_TERRIBLE: \"끔찍함!\"\n  STR_RATING_POOR: \"나쁨!\"\n  STR_RATING_OK: \"적당\"\n  STR_RATING_GOOD: \"좋음!\"\n  STR_RATING_EXCELLENT: \"훌륭함!\"\n  STR_SCORE: \"평점\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"X-COM 프로젝트 월간 보고서\"\n  STR_MONTH: \"시기> {ALT}{1}년 {0}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"후원 국가 위원회는 지금까지 당신의 성과에 전반적으로 만족했다.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"후원 국가 위원회는 당신의 탁월한 성과에 아주 기뻐했다. 좋은 활동을 지속하라.\"\n  STR_COUNCIL_IS_DISSATISFIED: \"후원 국가 위원회는 당신의 성과에 만족하지 못했다. 당신은 외계인의 위협을 다루는 효율성을 반드시 개선하거나 과제 종료를 감수해야 한다.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"당신은 외계인의 침략을 처리하는 데 성공하지 못했고, 후원 국가 위원회는 유감스럽게도 이 프로젝트를 끝낸다고 결정했다. 각 국가는 자기들이 적절하다 보이는 방식으로 이 문제를 다룰 것이다. 우리는 오직 이 명백하게 적대적인 세력과 어떤 화해를 할 수 있고, 일반 대중이 외계의 방문자를 받아들일 것인지 기대할 수밖에 없다.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0}에서는 국지적인 위협을 다루는 당신의 능력에 특히 기뻐했고 후원을 올리는 데 동의했다.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0}에서는 국지적인 위협을 다루는 당신의 능력에 특히 기뻐했고 후원을 올리는 데 동의했다.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} 및 {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0}에서는 영토 내 외계인 활동을 다루는 당신의 능력에 불평했고 재정적 지원을 줄이기로 결정했다.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0}에서는 영토 내 외계인 활동을 다루는 당신의 능력에 불평했고 후원을 줄이기로 결정했다.\"\n  STR_KNOTS: \"{0} 노트\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} 당국은 미지의 외계인 세력과 비밀 조약을 체결했고 프로젝트 참여를 철회했다.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} 당국은 미지의 외계인 세력과 비밀 조약을 체결했고 프로젝트 참여를 철회했다.\"\n  STR_MONTHLY_RATING: \"월간 평가> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"후원금 변동> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"후원 국가 위원회는 당신의 재정 상황에 기뻐하지 않는다. 당신은 빚을 $1,000,000 이하로 반드시 낮추어야 하고 아니면 과제가 종료될 것이다.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"하이퍼웨이브 지령 해석됨\"\n  STR_CRAFT_TYPE: \"기체 유형\"\n  STR_RACE: \"종족\"\n  STR_MISSION: \"임무\"\n  STR_ZONE: \"구역\"\n  STR_ALLOCATE_RESEARCH: \"연구 할당\"\n  STR_ALLOCATE_MANUFACTURE: \"제조 할당\"\n  STR_NEW_YORK: \"뉴욕\"\n  STR_WASHINGTON: \"워싱턴\"\n  STR_LOS_ANGELES: \"로스엔젤레스\"\n  STR_MONTREAL: \"몬트리올\"\n  STR_HAVANA: \"아바나\"\n  STR_MEXICO_CITY: \"멕시코시티\"\n  STR_CHICAGO: \"시카고\"\n  STR_VANCOUVER: \"밴쿠버\"\n  STR_DALLAS: \"댈러스\"\n  STR_BRASILIA: \"브라질리아\"\n  STR_BOGOTA: \"보고타\"\n  STR_BUENOS_AIRES: \"부에노스아이레스\"\n  STR_SANTIAGO: \"산티아고\"\n  STR_RIO_DE_JANEIRO: \"리우데자네이루\"\n  STR_LIMA: \"리마\"\n  STR_CARACAS: \"카라카스\"\n  STR_LONDON: \"런던\"\n  STR_PARIS: \"파리\"\n  STR_BERLIN: \"베를린\"\n  STR_MOSCOW: \"모스크바\"\n  STR_ROME: \"로마\"\n  STR_MADRID: \"마드리드\"\n  STR_BUDAPEST: \"부다페스트\"\n  STR_LAGOS: \"라고스\"\n  STR_CAIRO: \"카이로\"\n  STR_CASABLANCA: \"카사블랑카\"\n  STR_PRETORIA: \"프레토리아\"\n  STR_NAIROBI: \"나이로비\"\n  STR_CAPE_TOWN: \"케이프타운\"\n  STR_KINSHASA: \"킨샤사\"\n  STR_ANKARA: \"앙카라\"\n  STR_DELHI: \"델리\"\n  STR_KARACHI: \"카라치\"\n  STR_BAGHDAD: \"바그다드\"\n  STR_TEHRAN: \"테헤란\"\n  STR_BOMBAY: \"봄베이\"\n  STR_CALCUTTA: \"캘커타\"\n  STR_TOKYO: \"도쿄\"\n  STR_BEIJING: \"베이징\"\n  STR_BANGKOK: \"방콕\"\n  STR_MANILA: \"마닐라\"\n  STR_SEOUL: \"서울\"\n  STR_SINGAPORE: \"싱가포르\"\n  STR_JAKARTA: \"자카르타\"\n  STR_SHANGHAI: \"상하이\"\n  STR_HONG_KONG: \"홍콩\"\n  STR_NOVOSIBIRSK: \"노보시비르스크\"\n  STR_CANBERRA: \"캔버라\"\n  STR_WELLINGTON: \"웰링턴\"\n  STR_MELBOURNE: \"멜버른\"\n  STR_PERTH: \"퍼스\"\n  STR_PSI_TRAINING: \"사이오닉 훈련\"\n  STR_PSIONIC_TRAINING: \"사이오닉 훈련\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"잔여 사이오닉 연구실 공간> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"사이오닉{NEWLINE}강도\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"사이오닉 기술{NEWLINE}/개선\"\n  STR_PSI_AMP: \"사이오닉 증폭기\"\n  STR_IN_TRAINING: \"훈련{NEWLINE}중인가?\"\n  STR_TARGETTED_BY: \"다음이 노림:\"\n  STR_WEAPONS_CREW_HWPS: \"무기/{NEWLINE}승무원/HWP\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"는 연료가 부족해,{NEWLINE}기지로 복귀함\"\n  STR_SOLDIER_LIST: \"병사 목록\"\n  STR_RANK_: \"계급> {ALT}{0}\"\n  STR_MISSIONS: \"임무> {ALT}{0}\"\n  STR_KILLS: \"사살> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"부상 회복> {ALT}{0}\"\n  STR_TIME_UNITS: \"행동력\"\n  STR_STAMINA: \"기력\"\n  STR_HEALTH: \"체력\"\n  STR_BRAVERY: \"용기\"\n  STR_REACTIONS: \"반응\"\n  STR_FIRING_ACCURACY: \"사격술\"\n  STR_THROWING_ACCURACY: \"투척술\"\n  STR_STRENGTH: \"근력\"\n  STR_PSIONIC_STRENGTH: \"사이오닉 강도\"\n  STR_PSIONIC_SKILL: \"사이오닉 기술\"\n  STR_NEW_RANK: \"새 계급\"\n  STR_PROMOTIONS: \"진급\"\n  STR_SOLDIERS_UC: \"병사\"\n  STR_TANK_CANNON_UFOPEDIA: \"자율적인 중화기 차량은 X-Com 분대를 보완하기 위해 설계되었다. 높은 화력과 강한 장갑의 결합은 이 유닛을 개활지의 사격전에서 가치 있게 만든다. 탱크를 재무장하기 위해 당신의 창고에 충분한 기관포 포탄이 있는지 확인하라. 그들은 분대에 할당할 때 자동으로 무장할 것이다.\"\n  STR_TANK_ROCKET_LAUNCHER_UFOPEDIA: \"이 자율적인 중화기 차량은 강력한 로켓으로 무장했다. 이건 어떠한 외계의 적에게도 파멸적일 것이다. 당신의 창고에 중화기 차량용 로켓 보급이 지속되는 지 확인하라.\"\n  STR_TANK_LASER_CANNON_UFOPEDIA: \"레이저 무기는 중화기 차량에 있어 유용한 추가 무기다. 그건 강한 화력에 탄약으로 인한 제약이 없다는 걸 결합한다.\"\n  STR_HOVERTANK_PLASMA_UFOPEDIA: \"외계인의 기술은 중화기 차량에 새로운 활력을 주었다. 공중 이동이라는 추가된 기동성과 플라스마 빔의 위력은 치명적인 결합이다.\"\n  STR_HOVERTANK_LAUNCHER_UFOPEDIA: \"이 호버탱크는 막대한 파괴 능력이 있는 핵융합 폭탄 발사기를 지닌다. 대단한 주의를 기울여 이용하라. 당신은 이 중화기 차량이 완전히 무장한 상태를 지속하도록 핵융합 폭탄을 제조해야 할 것이다. 핵융합 폭탄은 지능적인 유도 무기다. 그걸 쏘려면 당신은 다수의 '경유지'를 커서로 선택한 후 발사 아이콘을 눌러라.\"\n  STR_HEAVY_PLASMA_CLIP_UFOPEDIA: \"이 자그마한 장치는 중형 플라스마 총을 위한 탄약으로 이용된다. 그건 적은 양의 엘레리움이 들어 있다.\"\n  STR_PLASMA_RIFLE_CLIP_UFOPEDIA: \"이 작은 물체는 플라스마 소총 - 중간 위력의 외계인 무기를 위한 동력원으로 이용된다. 적은 양의 엘레리움이 들어 있다.\"\n  STR_PLASMA_PISTOL_CLIP_UFOPEDIA: \"작은 외계인의 플라스마 권총을 위한 동력원이다.  모든 외계인 동력의 원천 - 엘레리움이 들어 있다.\"\n  STR_STUN_BOMB_UFOPEDIA: \"기절 폭탄은 살아있는 인간 표본을 포획하는 데 이용되나, 또한 대다수 외계인 종족에 대해 이용될 수 있다. 그건 소형 발사기에서 쏘아진다.\"\n  STR_ALIEN_RESEARCH_UFOPEDIA: \"외계인 연구 임무는 지구와 그 거주자들에 대한 기본적인 자료를 수집하기 위해 이용된다. 작은 차량이 대개 이용되며, 사람이 살지 않는 영역에 주로 착륙한다. 이 유형의 외계인 활동은 X-Com에 최소한의 위협만 나타내고, 정부 또는 대중에게 우려를 별로 끼치지 않는다.\"\n  STR_ALIEN_HARVEST_UFOPEDIA: \"외계인은 지구의 동물을 많은 용도로 사용한다. 동물은 비밀리에 유괴되며, 다양한 장기가 제거되어 돌아온다. 가축 해체는 대개 UFO 목격과 더불어 보고된다. 이 유형의 외계인 활동은 정부에게 대단한 우려와 함께 주민들 사이에 상당한 불안을 일으킨다. 이 유형의 활동은 주로 농장에서 일어난다. '외계인 수확'에 숨어 있는 이론은 외계 종족이 자신들의 동식물을 이 행성에 원래 '심었었고', 이제 그들은 심었던 걸 거두기 위해 돌아왔다는 걸 암시한다.\"\n  STR_ALIEN_ABDUCTION_UFOPEDIA: \"이건 가장 음흉한 형태의 외계인 활동이다. 피해자의 기억에서 유괴 경험을 지우려는 외계인의 시도에도 불구하고, 외계인에 의한 유괴는 폭넓게 보고되었다. 유괴된 자는 외계인의 태아 임신과 괴기한 유전자 실험을 포함하는, 굴욕적인 신체 실험의 대상이 되었다고 보고한다. 이 활동에 숨어 있는 목적은 유전자 변이와 외계인 소유의 유전 재료 조작에 연결된 것으로 보인다. 이 활동은 대단한 위기감을 일으키고, 거주 영역 또는 도시에서 일어난다.\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"지구의 정부는 외관이 인간인 외계인 요원이 잠입할 수 있다. 이는 최고위 수준에서 외계인과 정부 간 공식적 접촉을 초래할 수 있다. 이 활동의 정점은 주요 도시의 근처에서 나타나는 집중적인 UFO의 활동으로 구분된다. 외계인은 자신들의 우월한 기술에 대한 지식을 제공하는 것으로 정부와 협정을 체결하려 시도할 것이다. 보상으로 정부는 외계인이 자신들의 활동을 방해 받지 않고 수행하도록 허용할 것이다. 이 외계인 활동은 X-Com에 대한 최악의 위협을 나타낸다. 만약 정부가 협정을 체결하면 그의 후원은 중지될 것이다.\"\n  STR_ALIEN_BASE_UFOPEDIA: \"외계인은 외딴 자리에 비밀 지하 기지를 건설할 것이다. 약간의 초기 정찰 비행 후 기지가 지어지는 동안 집중적인 UFO 활동이 일어날 것이다.이 기지는 유괴된 인간을 처리하는 실험 연구실과, 이 지역에 대한 후속 연구를 위한 보급품이 들어 있다고 알려졌다. 외계인 기지의 존재는 UFO의 존재 없이도 더 많은 외계인 활동을 생성할 것이다. 기지의 자리를 잡아 내려면 X-Com 기체는 성공적인 탐지 확률을 얻기 위해 어떤 영역을 수 시간 동안 반드시 순찰해야 한다.\"\n  STR_ALIEN_TERROR_UFOPEDIA: \"외계인들이 도시에 테러를 일으킬 때 그들은 무시무시한 힘을 지닌 어떤 특수부대를 배치할 것이다. 민간인은 직접적으로 위협을 받을 것이고, 정부는 영역 전체를 강제로 소개할 것이다. 이 활동에 숨어 있는 목적은 저 정부가 X-Com 프로젝트를 위협하도록 충분한 대중의 히스테리를 생성하는 것이다.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"만약 X-Com 요격기가 UFO를 격추하는 데 특히 성공적이라면 외계인은 어떤 보복 행동을 취할 지도 모른다. 이는 X-Com 기지에 대한 직접 공격을 초래할 수 있다. 그렇지만, 외계인은 X-Com 기지를 공격하려면 그 기지를 찾아야 하고, UFO와 거리를 두면 강습의 위험은 거의 없을 것이다.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"일단 외계인 기지가 건설된 후에 그건 특별한 보급 함선에 의해 정기적으로 재 보급을 받는다. 만약 이러한 함선 중 하나가 착륙한 동안 탐지되었다면 이는 외계인 기지가 주변에 있는 게 확실하다.\"\n  STR_SMALL_SCOUT_UFOPEDIA: \"이 조그마한 기체는 수색 또는 연구에 주로 이용된다. 그건 외계인 임무의 시작 시 보통 더 커다란 함선에 앞서 나온다.\"\n  STR_MEDIUM_SCOUT_UFOPEDIA: \"지구 군대에 별 위협을 나타내지 않는 중간 크기의 정찰 함선이다. 보통은 임무 중 더 커다란 함선 이전에 나타난다.\"\n  STR_LARGE_SCOUT_UFOPEDIA: \"가장 커다란 외계인 정찰 기체는 모든 유형의 외계인 임무에 이용되는 범용 함선이다.\"\n  STR_HARVESTER_UFOPEDIA: \"수확선은 하부에 함정 문을 지니고 가축 또는 다른 야수를 끌어올리기 위한 견인 장치가 장착되었다. 레이저 절단기는 원하는 재료를 추출하기 위해 이용되며 사체는 지상에 버려진다. 신체 부위를 담는 저장 용기 또한 있다.\"\n  STR_ABDUCTOR_UFOPEDIA: \"이 함선은 인간 표본에 대해 끔찍한 실험을 수행하기 위한 시험 장치가 장착되었다. 피해자는 텔레파시의 힘으로 보통 마비되나, 수술대 위에 있는 동안 의식을 유지한다.\"\n  STR_TERROR_SHIP_UFOPEDIA: \"테러함은 커다란 외계인 테러 무기 또는 생물을 위한 격리 시설을 지닌다. 그건 이 외계인 테러분자들을 거주 영역으로 수송하는 데 이용된다.\"\n  STR_BATTLESHIP_UFOPEDIA: \"전함은 가장 커다랗고 강력한 외계인의 기체다. 그건 보통 주력 외계인 임무 기체로, 강력한 무기와 다수의 승무원이 적재되었다.\"\n  STR_SUPPLY_SHIP_UFOPEDIA: \"보급 함선은 외계인 기지의 건설이나 기존 기지의 보급에 이용된다. 그건 외계인 식량 용기 및 번식기를 나른다.\"\n  STR_DISMANTLE: \"철거\"\n  STR_FACILITY_IN_USE: \"시설을 이용 중이다\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"시설을 철거할 수 없다!{SMALLLINE}모든 기지 시설은 반드시 출입 승강기에 연결되어야 한다.\"\n  STR_TRANSFER_ITEMS_TO: \"물품을 {0} 기지로 이송\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"이송에 필요한 외계인 격리실이 없다!{SMALLLINE}산 외계인은 살려 두려면 외계인 격리 시설이 필요하다.\"\n  STR_AMOUNT_AT_DESTINATION: \"행선지에{NEWLINE}있는 양\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"외계인 격리 시설이 없기에 외계인이 죽었다.\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"빈 생활 공간이 없다!{SMALLLINE}행선지 기지는 생활관 안에 기체에 배속된 승무원을 위한 충분한 공간이 없다.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"저장 공간이 없다!{SMALLLINE}행선지 기지는 기체에 배속된 장비를 위한 충분한 저장 공간이 없다.\"\n  STR_ITEMS_ARRIVING: \"도착한 물품\"\n  STR_DESTINATION_UC: \"행선지\"\n  STR_PISTOL: \"권총\"\n  STR_PISTOL_CLIP: \"권총 탄창\"\n  STR_RIFLE: \"소총\"\n  STR_RIFLE_CLIP: \"소총 탄창\"\n  STR_HEAVY_CANNON: \"중형포\"\n  STR_HC_AP_AMMO: \"중형포 탄약/철갑\"\n  STR_HC_HE_AMMO: \"중형포 탄약/고폭\"\n  STR_HC_I_AMMO: \"중형포 탄약/소이\"\n  STR_AUTO_CANNON: \"기관포\"\n  STR_AC_AP_AMMO: \"기관포 탄약/철갑\"\n  STR_AC_HE_AMMO: \"기관포 탄약/고폭\"\n  STR_AC_I_AMMO: \"기관포 탄약/소이\"\n  STR_ROCKET_LAUNCHER: \"로켓 발사기\"\n  STR_SMALL_ROCKET: \"로켓/소형\"\n  STR_LARGE_ROCKET: \"로켓/대형\"\n  STR_INCENDIARY_ROCKET: \"로켓/소이\"\n  STR_GRENADE: \"수류탄\"\n  STR_SMOKE_GRENADE: \"연막탄\"\n  STR_PROXIMITY_GRENADE: \"근접 수류탄\"\n  STR_HIGH_EXPLOSIVE: \"고폭탄\"\n  STR_STUN_ROD: \"기절 막대\"\n  STR_HEAVY_PLASMA: \"중형 플라스마 총\"\n  STR_HEAVY_PLASMA_CLIP: \"중형 플라스마 총 탄창\"\n  STR_PLASMA_RIFLE: \"플라스마 소총\"\n  STR_PLASMA_RIFLE_CLIP: \"플라스마 소총 탄창\"\n  STR_PLASMA_PISTOL: \"플라스마 권총\"\n  STR_PLASMA_PISTOL_CLIP: \"플라스마 권총 탄창\"\n  STR_BLASTER_LAUNCHER: \"블래스터 발사기\"\n  STR_BLASTER_BOMB: \"블래스터 폭탄\"\n  STR_SMALL_LAUNCHER: \"소형 발사기\"\n  STR_STUN_BOMB: \"기절 폭탄\"\n  STR_ALIEN_GRENADE: \"외계 수류탄\"\n  STR_ELERIUM_115: \"엘레리움-115\"\n  STR_MIND_PROBE: \"마인드 프로브\"\n  STR_SECTOID_CORPSE: \"섹토이드 시체\"\n  STR_SNAKEMAN_CORPSE: \"스네이크맨 시체\"\n  STR_ETHEREAL_CORPSE: \"이더리얼 시체\"\n  STR_MUTON_CORPSE: \"뮤톤 시체\"\n  STR_FLOATER_CORPSE: \"플로터 시체\"\n  STR_CELATID_CORPSE: \"셀라티드 시체\"\n  STR_SILACOID_CORPSE: \"실라코이드 시체\"\n  STR_CHRYSSALID_CORPSE: \"크리살리드 시체\"\n  STR_REAPER_CORPSE: \"리퍼 시체\"\n  STR_SECTOPOD_CORPSE: \"섹토포드 시체\"\n  STR_CYBERDISC_CORPSE: \"사이버디스크 시체\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"중화기 차량을 무장하기 위한 탄약이 부족하다{SMALLLINE}각 중화기 차량은 {1} {0}개를 요구한다.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"분대를 완전히 재정비할 장비가 충분하지 않다\"\n  STR_MARS_CYDONIA_LANDING: \"화성: 사이도니아 착륙\"\n  STR_MARS_CYDONIA_LANDING_BRIEFING: \"당신의 어벤저 기체는 화성의 표면 위에 있는 사이도니아라는 영역에 착륙했다. 우리 정보는 피라미드 구조물 중 하나에 지하 단지로 가는 녹색의 출입 승강기가 들어 있다는 걸 가리킨다. 일단 당신이 모든 병사를 승강기 영역에 모았으면 다음 무대로 나아가기 위해 '임무 중단' 아이콘을 눌러라.\"\n  STR_MARS_THE_FINAL_ASSAULT: \"화성: 최후의 강습\"\n  STR_MARS_THE_FINAL_ASSAULT_BRIEFING: \"피라미드 승강기는 당신의 전투에 지친 병사들을 화성의 표면 아래 깊숙이로 데려간다. 그들은 터널과 밀실이 있는 커다란 단지의 핵심에 도착한다. 외계인의 두뇌는 이 미궁의 어떤 곳에 숨겨져 있다. 지구가 외계인의 예속으로부터 해방되려면 그 두뇌를 반드시 부수어야 한다.{NEWLINE}{NEWLINE}행운을 빈다!\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"{1}{NEWLINE}물품을 생산하려면{NEWLINE}{0}{NEWLINE}의 연구가 필요할 것이다.\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"외계인들은 무방비한 {0} 기지를 부수었다.\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"X-Com 요원이 {0}에서 외계인 기지를 찾았다\"\n  STR_STANDOFF: \"대치\"\n  STR_CAUTIOUS_ATTACK: \"소극적 공격\"\n  STR_STANDARD_ATTACK: \"표준적 공격\"\n  STR_AGGRESSIVE_ATTACK: \"적극적 공격\"\n  STR_DISENGAGING: \"교전 이탈\"\n  STR_UFO_HIT: \"UFO에 명중!\"\n  STR_UFO_CRASH_LANDS: \"UFO가 지면에 추락!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"최소화는 대치 거리에서만 가능\"\n  STR_UFO_RETURN_FIRE: \"UFO가 응사!\"\n  STR_INTERCEPTOR_DAMAGED: \">>> 요격기 손상  <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> 요격기 파괴 <<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"UFO가 요격기를 따돌린다!\"\n  STR_ALIENS_TERRORISE: \"외계인이 아래에서 테러를 벌인다\"\n  STR_LONG_RANGE_DETECTION: \"장거리 탐지기\"\n  STR_STORES_UC: \"창고\"\n  STR_DIFFICULTY_LEVEL: \"난이도\"\n  STR_INTERCEPT: \"요격\"\n  STR_BASES: \"기지\"\n  STR_GRAPHS: \"그래프\"\n  STR_UFOPAEDIA_UC: \"UFO 사전\"\n  STR_OPTIONS_UC: \"옵션\"\n  STR_FUNDING_UC: \"후원금\"\n  STR_5_SECONDS: \"5초\"\n  STR_1_MINUTE: \"1분\"\n  STR_5_MINUTES: \"5분\"\n  STR_30_MINUTES: \"30분\"\n  STR_1_HOUR: \"1시간\"\n  STR_1_DAY: \"하루\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"X-Com 성과 내역\"\n  STR_ENTER_NAME: \"이름 입력\"\n  STR_PERFORMANCE_RATING: \"성과 평점\"\n  STR_VICTORY_DATE: \"승리한 날\"\n  STR_ELECTRO_FLARE: \"전자 조명기\"\n  STR_ELECTRO_FLARE_UFOPEDIA: \"이 조그마한 장치는 던졌을 때 밝은 섬광을 만들어낸다. 이는 야간 임무 중 전자 조명기 주변에 있는 적 유닛을 비출 것이다.\"\n  STR_MONTHLY_COSTS: \"월간 비용\"\n  STR_CRAFT_RENTAL: \"기체 대여비\"\n  STR_SALARIES: \"급여\"\n  STR_BASE_MAINTENANCE: \"기지 유지비\"\n  STR_COST_PER_UNIT: \"유닛 당 비용\"\n  STR_QUANTITY: \"수량\"\n  STR_TOTAL: \"합계\"\n  STR_IN_PSIONIC_TRAINING: \"사이오닉 훈련 중\"\n  STR_BLASTER_BOMB_UFOPEDIA: \"이 장치는 지능적인 유도 장치를 지닌 고폭탄 미사일이다. 그건 블래스터 발사기에서 쏘아진다.\"\n  STR_FRONT_ARMOR: \"전면 장갑\"\n  STR_LEFT_ARMOR: \"좌측 장갑\"\n  STR_RIGHT_ARMOR: \"우측 장갑\"\n  STR_REAR_ARMOR: \"후면 장갑\"\n  STR_UNDER_ARMOR: \"하부 장갑\"\n  STR_ROUNDS: \"잔탄\"\n  STR_UNIT: \"유닛> {0}\"\n  STR_ENERGY: \"기력\"\n  STR_MORALE: \"사기\"\n  STR_ARMOR_: \"갑옷> {0}\"\n  STR_FRONT_ARMOR_UC: \"전면 장갑\"\n  STR_LEFT_ARMOR_UC: \"좌측 장갑\"\n  STR_RIGHT_ARMOR_UC: \"우측 장갑\"\n  STR_REAR_ARMOR_UC: \"후면 장갑\"\n  STR_SKILLS: \"기술> {0}\"\n  STR_LEVEL: \"층수> {0}\"\n  STR_HEAD: \"머리\"\n  STR_TORSO: \"몸통\"\n  STR_RIGHT_ARM: \"오른팔\"\n  STR_LEFT_ARM: \"왼팔\"\n  STR_RIGHT_LEG: \"오른다리\"\n  STR_LEFT_LEG: \"왼다리\"\n  STR_PAIN_KILLER: \"진통제\"\n  STR_STIMULANT: \"각성제\"\n  STR_HEAL: \"치료\"\n  STR_TIME_UNITS_SHORT: \"행동>{ALT}{0}\"\n  STR_WEIGHT: \"무게>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"반응>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"P.기술>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"P.강도>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"외계인 유물\"\n  STR_AMMO_ROUNDS_LEFT: \"탄종:{NEWLINE}남은{NEWLINE}탄환={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"진통제>{ALT}{0}{ALT}{NEWLINE}각성제>{ALT}{1}{ALT}{NEWLINE}치료>{ALT}{2}\"\n  STR_THROW: \"투척\"\n  STR_AUTO_SHOT: \"자동사격\"\n  STR_SNAP_SHOT: \"지향사격\"\n  STR_AIMED_SHOT: \"조준사격\"\n  STR_STUN: \"기절시키기\"\n  STR_PRIME_GRENADE: \"신관 설정\"\n  STR_USE_SCANNER: \"스캐너 이용\"\n  STR_USE_MEDI_KIT: \"메디킷 이용\"\n  STR_LAUNCH_MISSILE: \"미사일 발사\"\n  STR_ACCURACY_SHORT: \"정확>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"행동력이 부족하다!\"\n  STR_NOT_ENOUGH_ENERGY: \"기력이 부족하다!\"\n  STR_NO_ROUNDS_LEFT: \"남은 탄환이 없다!\"\n  STR_NO_AMMUNITION_LOADED: \"장전된 탄약이 없다!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"이 무기의 탄약이 아니다!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"무기가 이미 장전되었다!\"\n  STR_NO_LINE_OF_FIRE: \"사선이 안 나온다!\"\n  STR_GRENADE_IS_ACTIVATED: \"수류탄이 켜졌다!\"\n  STR_GRENADE_IS_DEACTIVATED: \"수류탄이 꺼졌다!\"\n  STR_THERE_IS_NO_ONE_THERE: \"그곳에는 아무도 없다!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"연구할 때까지 외계인 유물은 이용할 수 없다!\"\n  STR_OUT_OF_RANGE: \"사거리 밖이다!\"\n  STR_UNABLE_TO_THROW_HERE: \"여기 던질 수 없다!\"\n  STR_SET_TIMER: \"타이머 설정\"\n  STR_HIDDEN_MOVEMENT: \"보이지 않는 이동\"\n  STR_TURN: \"턴> {0}\"\n  STR_SIDE: \"진영> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"계속하려면 버튼을 눌러라\"\n  STR_MIND_CONTROL: \"정신 지배\"\n  STR_PANIC_UNIT: \"공황 유발\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"사기 공격 성공\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"정신 지배 성공\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}대원은 난폭해졌다\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}대원은 난폭해졌다\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}대원은 공황에 빠졌다\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}대원은 공황에 빠졌다\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"외계인\"\n  STR_RIGHT_HAND: \"오른손\"\n  STR_LEFT_HAND: \"왼손\"\n  STR_RIGHT_SHOULDER: \"오른어깨\"\n  STR_LEFT_SHOULDER: \"왼어깨\"\n  STR_BACK_PACK: \"배낭\"\n  STR_BELT: \"벨트\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}대원은 외계인이 조종한다\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}대원은 외계인이 조종한다\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}대원은 의식불명에 빠졌다\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}대원은 의식불명에 빠졌다\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}대원은 치명상으로 사망했다\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}대원은 치명상으로 사망했다\"\n  STR_USE_MIND_PROBE: \"마인드 프로브 이용\"\n  STR_FATAL_WOUNDS: \"치명상\"\n  STR_UNDER_ARMOR_UC: \"하부 장갑\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"지향사격에 필요한 행동력을 남김\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"자동사격에 필요한 행동력을 남김\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"조준사격에 필요한 행동력을 남김\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"무릎 꿇기에 필요한 행동력을 남김\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"무릎 꿇고 쏘기에 필요한 행동력을 남김\"\n  STR_UNITS_IN_CRAFT:\n    other: \"{N} 명의 대원이 X-Com 기체 안에 있다\"\n  STR_UNITS_OUTSIDE:\n    other: \"{N} 명의 대원이 밖에 남겨졌다\"\n  STR_UNITS_IN_ENTRANCE:\n    other: \"{N} 명의 대원이 입구에 있다\"\n  STR_UNITS_IN_EXIT:\n    other: \"{N} 명의 대원이 표적 출구에 있다\"\n  STR_ABORT_MISSION_QUESTION: \"임무 중단?\"\n  STR_CORPSE: \"시신\"\n  STR_UNLOAD_CRAFT: \"탄창 제거\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}대원은 살해되었다\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}대원은 살해되었다\"\n  STR_HIT_MELEE: \"명중\"\n  STR_GROUND: \"지면\"\n  STR_LIVING_QUARTERS_PLURAL: \"생활관\"\n  STR_LIST_ITEM: \"물품\"\n  STR_PERSONAL_ARMOR_UFOPEDIA: \"새로 발견된 외계 합금을 이용해, 이 새로운 갑옷은 우리 병사에게 외계인의 위협에 대항해 싸울 기회를 준다.\"\n  STR_POWER_SUIT_UFOPEDIA: \"병사를 위한 강력한 새 보호 수단인, 이 갑옷은 엘레리움 에너지원으로 작동되며 착용자의 속도와 근력을 엄청나게 증폭해, 전투 부대를 위해 지금까지 없었던 최고의 보호를 제공한다.\"\n  STR_FLYING_SUIT_UFOPEDIA: \"강화된 형태의 동력 갑옷으로, 전장에서 완전한 이동의 자유를 얻기 위해 외계인의 반중력 항법 장치를 통합했다.\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"모든 외계인이 추락으로 죽었고,{NEWLINE}자동 회수를 개시했다\"\n  STR_RESET: \"초기화\"\n  STR_MEMORIAL: \"추모비\"\n  STR_DATE_UC: \"날짜\"\n  STR_SOLDIERS_RECRUITED_UC: \"고용된 병사>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"잃은 병사>{ALT}{0}\"\n  MAP_CULTA: \"농장\"\n  MAP_FOREST: \"숲\"\n  MAP_JUNGLE: \"정글\"\n  MAP_MOUNT: \"산악\"\n  MAP_DESERT: \"사막\"\n  MAP_POLAR: \"극지\"\n  MAP_URBAN: \"도시\"\n  MAP_UBASE: \"외계인 기지\"\n  MAP_XBASE: \"X-Com 기지\"\n  MAP_MARS: \"화성\"\n  STR_MIXED: \"혼합\"\n  STR_REMOVE_SELECTED: \"선택된 목록 삭제\"\n  STR_LIVE_ALIENS: \"산{NEWLINE}표본\"\n  STR_DEAD_ALIENS: \"버릴{NEWLINE}표본\"\n  STR_UNDER_INTERROGATION: \"연구{NEWLINE}중\"\n  STR_CONTAINMENT_EXCEEDED: \"외계인 격리실 한도를 초과했다!{SMALLLINE}{0}에 있는 격리 공간이 불충분하다. 당신은 격리실에서 여분의 외계인을 반드시 제거해야 한다(그건 이후 죽을 것이다).\"\n  STR_MANAGE_CONTAINMENT: \"외계인 격리실 관리\"\n  STR_STORAGE_EXCEEDED: \"저장 공간을 초과했다!{SMALLLINE}{0}에 있는 저장 공간이 불충분하다. 당신은 여분의 물품을 반드시 팔아 치워야 한다.\"\n  STR_GO_TO_BASE: \"기지로 이동\"\n  STR_MELEE_ACCURACY: \"격투술\"\n  STR_SELL_PRODUCTION: \"매각\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"양손 모두가 반드시 비어 있어야 한다!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"템플릿을 복사하기 위한 물품이 충분하지 않다!\"\n  STR_UNLOAD_WEAPON: \"탄창 제거\"\n  STR_ALL_ITEMS: \"모든 물품\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    other: \"장비를 더 이상 적재할 수 없다!{SMALLLINE}당신은 이 기체에 오직 최대 {N}개의 물품만 가져갈 수 있다.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}제어부를 부수었다{NEWLINE}입구로 나아간 후 임무를 중단하라.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"X-Com 시설은 수중에 지어질 수 없다\"\n  STR_LEVEL_SHORT: \"{0}\"\n  STR_PERSONNEL: \"직원\"\n  STR_CRAFT_ARMAMENT: \"기체 & 무장\"\n  STR_COMPONENTS: \"부품\"\n  STR_SOLDIERS_RECRUITED: \"고용한 병사\"\n  STR_SOLDIERS_LOST: \"잃은 병사\"\n  STR_TOTAL_UFOS: \"탐지된 UFO\"\n  STR_TOTAL_ALIEN_BASES: \"발견된 외계인 기지\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"PST\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"PSK\"\n  FEMALE_CIVILIAN: \"여성 민간인\"\n  MALE_CIVILIAN: \"남성 민간인\"\n  CYBERDISC_WEAPON: \"사이버디스크 무기\"\n  REAPER_WEAPON: \"리퍼 무기\"\n  CHRYSSALID_WEAPON: \"크리살리드 무기\"\n  CELATID_WEAPON: \"셀라티드 무기\"\n  SILACOID_WEAPON: \"실라코이드 무기\"\n  SECTOPOD_WEAPON: \"섹토포드 무기\"\n  ZOMBIE_WEAPON: \"좀비 무기\"\n  ALIEN_PSI_WEAPON: \"외계인 사이오닉 무기\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/lb.yml",
    "content": "lb:\n  STR_AVENGER_UFOPEDIA: \"TRANSPORTER A KAMPFFLIGER. ENG ULTIMATIV REPLIKA VUN ALIEN TECHNOLOGIE.\"\n  STR_INTERCEPTOR_UFOPEDIA: \"KAMPFFLIGER MAT DUAL PULSE DETONATION MOTOREN A SPEZIAL GEPANZERT ELEKTRONESCH SYSTEMER. DEI BESCHT ERDBASEIERT TECHNOLOGIE.\"\n  STR_LIGHTNING_UFOPEDIA: \"TRANSPORTER A KAMPFFLIGER. ENG GESCHMACKLOS REPLIKA VU ALIEN UNDRIWWER.\"\n  STR_SKYRANGER_UFOPEDIA: \"TRUPPENTRANSPORTER. DE SCHNELLSTE VUN SÉNGER ART, KAPABEL SENKRECHT ZE STARTEN A LANDEN.\"\n  STR_FIRESTORM_UFOPEDIA: \"KAMPFFLIGER. DËSEN EESËTZER ASS ENG REPLICA VUM KLASSESCHEN UFO DESIGN. DEN UNDRIWW ASS ZENTRAL POSITIONEIERT.\"\n  STR_STINGRAY_UFOPEDIA: \"FORTGESCHRATT LOFT-LOFT RAKEIT MAT SPEZIELL OFGESCHIERMTER ELEKTRONIK.\"\n  STR_AVALANCHE_UFOPEDIA: \"LOFT-LOFT RAKÉIT MAT NUKLEAREM SPRENGKAPP, MEE GROUSST GEWIICHT.\"\n  STR_CANNON_UFOPEDIA: \"STARKT GEWIER DAT PANZERBRIECHEND KUGELEN VERSCHEISST DEI DURCH 16 ZOLL STARKE STOL KENNEN GOEN.\"\n  STR_FUSION_BALL_UFOPEDIA: \"DËSEN OFSCHOSSMECHANISMUS SCHÉISST E GESCHOSS A FORM VUN ENGEM BALL DEN UGEDRIWWEN ASS VUN ENGER ANTI-MATERIELLER REAKTIOUN. DE BALL ZERSTEIERT SAIN ZIL MAT ENGER IMPLOSIOUN VUN SCHWEIERKRAAFTWELLEN.\"\n  STR_LASER_CANNON_UFOPEDIA: \"DE KONVENTIONELLEN LASERSTRAHL GET UGEDRIWWEN VUN ENGER ANTI-MATERIELLER REAKTIOUNSKUMMER.\"\n  STR_PLASMA_BEAM_UFOPEDIA: \"DE GRAVITATIOUNSSTRAHL DIRIGEIERT E FAIN KANALISEIERT IMPLODEIREND GRAVITATIOUNSFELD.\"\n  STR_SECTOID_UFOPEDIA: \"D'Sectoiden Hierarchie geet vun Zaldot bis Leader mat staarken psionëschen Fähegkeeten. Des psionësch Kraaft kann benotzt ginn fir Zaldoten am Kampf ze demoraliséiren, oder souguer d'Kontroll iwwert se ze erlaangen. Se entféiren Mënschen an verstümmeln Béischten. D'Entféirungen déngen dozou genetescht Material ze kréien a mutéiert Hybridmënschen ze kreéiren. D'Béischten ginn hinnen Iessen an genetëscht Material. Dës Rass schéngt iwwerleeën genetësch Hybriden entwéckelen ze wellen fir hier Efficacitéit vun hierer beienstackarteger Gesellschaft ze erhéigen.\"\n  STR_SECTOID_AUTOPSY: \"Sectoid Autopsie\"\n  STR_SECTOID_AUTOPSY_UFOPEDIA: \"D'Autopsie ermëttelt verkümmert Verdauungsorganer an eng banal Struktur. D'Gehier an Aan sinn wäit entwéckelt. D'Struktur ass genetesch oder mutéierent verännert ginn. De klénge Mond an Nues schéngen quasi keng Funktioun ze hunn. D'Gewebe tëschent de Fangeren an déi flaach Féiss schéngen vun aquatëschem Ursprong ze sinn. Et gëtt keng Fortplanzungsorganer, an et wees en net wéi dat sollt geschéien. Et schéngt eng fabrizéiert Spezies ze sinn.\"\n  STR_SNAKEMAN_UFOPEDIA: \"Dës Rass huet sech an enger extrem feindlecher Ëmwelt entwéckelt. Se sinn extrem staark an kënnen extremen Temperaturdifferenzen widderstoen. Hier Beweglechkeet hängt vun engem schlaangenartegen groussen 'Fouss' of den all Liewensorganer schützt. Hier Absichten schéngen just räiberescher Natur ze sinn an schéngen ennert der Kontroll vun enger anerer Intelligenz ze stoen déi d'Militäraktiounen op der Äerd steieren.\"\n  STR_SNAKEMAN_AUTOPSY: \"Schlaangemënsch Autopsie\"\n  STR_SNAKEMAN_AUTOPSY_UFOPEDIA: \"D'Haut ass extrem fest and hëtzbestänneg. Den cardio-vasculären System ass en Deel vum muskulären System den en hydraulëschen Prinzip benotzt fir eng Bewegung ze kreéiren. Den eenzegen echten Muskel ass d''Häerz'. De reproduktiven System schéngt effizient ze sinn. Reproduktioun ass asexual, all Schlaangemënschen huet bis zu fofzeg Eeër bei sech. Géif een se gewäerden loossen, wieren se eng schwéier Bedrohung fir d'Äerd.\"\n  STR_ETHEREAL_UFOPEDIA: \"Dëst Wiesen huet eng genial mental Stäerkt déi him erlaabt telepathesch ze kommunizéire an Telekinesis unzewennen. Déi schwaach physesch Fähegkeeten ginn duerch déi mental kompenséiert. Mir verstinn net, wéi déi telekinetesch Fähegkeeten funktionéieren, wëll déi géint all physesch Gesetzer verstoussen. Se sinn extrem geféierlech a Kampfsituatiounen wou se ob hier mental Stäerkte setzen. e erschéngen nëmmen seelen op der Äerd an schéngen sech op aner Rassen ze verloossen fir hier Objektiver ze areechen.\"\n  STR_ETHEREAL_AUTOPSY: \"Ethereal Autopsie\"\n  STR_ETHEREAL_AUTOPSY_UFOPEDIA: \"Dës Kreatur ass physësch zréckbliwwen and schéngt net kapabel Liewensfunktiounen ze erhalen. D'Muskelen sinn stark verkümmert an d'intern Organer schéngen ënnerentwéckelt ze sinn. D'Sënnesorganer, souwéi d'Aan, schéngen guer net ze fonktionéiren. D'Gehier allerdéngs, as gutt entwéckelt and zidd en groussen Undeel vum Kierper séngem Blutt. Et ass e Rätsel wéi d'Kreatur sech kann selwer versuergen ouni extern Hëllef.\"\n  STR_MUTON_UFOPEDIA: \"Dës humanoid Kreatur ass physesch staark an intelligent. Se hunn speziell Honger op réit Fleesch vun all Zort, wat se fir ze iwwerliewen brauchen genau wéi d'Fleeschfriesser vun der Aerd. Se sinn op telepathesch Kommandoen vun enger Rass déi als 'Etherals' bezeechent gëtt ugewisen. Wann d'Verbindung gekappt gëtt, schéngt den mentalen System auszefalen an se stierwen. D'Cyberimplantater gi benotzt fir d'Kampfperformance ze verbessern.\"\n  STR_MUTON_AUTOPSY: \"Muton Autopsie\"\n  STR_MUTON_AUTOPSY_UFOPEDIA: \"D'Haut vun dëser Kreatur schéngt eng organesch Schutzschicht ze sinn déi um Kierper pescht. Et gëtt vill cybernetesch Implantater déi benotzt ginn fir den cardio-vaskulären System an Sënner ze verbessern. Reproduktivorganer schéngen operativ ewechgeholl ginn ze sinn. Onglécklecherweis sinn dës Kreaturen limitéiert op en Liewen am Krich. Panzerbriechend Munitioun ass wéineg effektiv géint des gehäerten Haut.\"\n  STR_CELATID_UFOPEDIA: \"Dës Liewensform huet déi mysteriéis Eegenschaft durch d'Loft ze schwiewen. Se schéngt mënschlech Gehierwellen ze fannen an an d'Richtung vun hinnen ze lafen, souguer wann se verstoppt sinn. Soubal en Zil entdeckt gëtt, land den Celatid an schéisst en korrosivt Gëft of. D'Kreatur huet d'Eegenschaft sech schnell ze klonen. Et begleed d'Vollék vun den Mutonen bei séngen Wanderungen.\"\n  STR_CELATID_AUTOPSY: \"Celatid Autopsie\"\n  STR_CELATID_AUTOPSY_UFOPEDIA: \"De Käer huet e klengt bio-mechanescht Gerät, wellecht e Motor mat Antigravitatiounstechnologie ze si schéngt. De Gëftsak ass dat gréissten Organ an et schéngt keng separat Gehierstruktur ze ginn. Et erkennt een keen Verdauungs- a Reproduktiounssystem. E klengt Organ beinhalt Embryonen déi séier kënnen wuessen an eng nei Gestalt bilden.\"\n  STR_SILACOID_UFOPEDIA: \"Dës op Silikon baséiert Liewensform generéiert eng enorm Hëtzt. Se ass stark genuch Fielsen ze briechen déi dann vun dem warmen Käer verdaut ginn. D'Intelligenz ass primitiv an kann durch Implantater oder Telepathie kontrolléiert ginn. Se schaffen mat den Muton Alien.\"\n  STR_SILACOID_AUTOPSY: \"Silacoid Autopsie\"\n  STR_SILACOID_AUTOPSY_UFOPEDIA: \"De Käer vun dëser Kreatur ass extrem warm, an et schéngt d'Basis fir de Verdaungssystem ze sinn. Den eegenaartegen Muskelsystem huet enorm Kraaft an Geschwindegkeet. D'Haut ass wéi e Fiels an immun géint Feier oder Brandmunitioun.\"\n  STR_CHRYSSALID_UFOPEDIA: \"D'schéierarteg Krallen vun dëser Kreatur sinn eng staark Waff am Nokampf. De héige Metabolismus a Stäerkt vun dëser Kreatur ginn hinnen Geschwindegkeet a Genauegkeet. Amplaz säin Opfer emzebréngen, gëtt him en Ee ageplanzt an Gëft injectéiert, wat et zu engem wandelnden Zombie mescht. En neien Chryssalid entspréngt dem Kierper no kuerzer Zäit. Chryssalide sinn verwandt met der Rass vun de Schlaangemënsche.\"\n  STR_CHRYSSALID_AUTOPSY: \"Chryssalid Autopsie\"\n  STR_CHRYSSALID_AUTOPSY_UFOPEDIA: \"D'Aussenskelett vun dëser Kreatur ass extrem stark, mee ufälleg géint explosiv Munitioun. D'Gehier ass gutt entwéckelt an d'Zellen vermehren sech séier. D'Kreatur dréid zwanzeg Eeër déi an aner Organismen gelued ginn. Des Kreatur ass eng ganz effektiv Terrorwaff.\"\n  STR_FLOATER_UFOPEDIA: \"Floater sinn primär Zaldoten an Terroragenten. Se sinn natierlecherweis Raubdéieren, genetësch geschaf and kybernetesch verbessert fir formidabel Zaldoten ze ginn. Den ënneschte Kierper an déi meescht Organer goufen operativ ewechgeholl an en Liewenserhalungssystem gouf installéiert. Dëst Implantat huet eng Antigravitatiounseenheet mat dem d'Kreatur schwiëwe kann, wann och net ganz stabil.\"\n  STR_FLOATER_AUTOPSY: \"Floater Autopsie\"\n  STR_FLOATER_AUTOPSY_UFOPEDIA: \"Dës Kreatur gouf durch Operatiounen drastesch verännert. D'Gerät wat den Haptdeel vum Kierper ausmécht, schéngt e Liewenserhalungssystem ze sinn, den d'Funktioun vum Häerz, Long an Verdauungssystem iwwerhuele kann. Dëst erlabt der Kreatur an engem extrem feindleche Liewensraum ze iwwerliewen. D'Gehier ass méi kleng wéi eist, mee d'Sensorik ass gutt entwéckelt.\"\n  STR_REAPER_UFOPEDIA: \"Dësen zweeféissegen Fleeschfriesser huet e starkt Gebëss an e groussen Appetit. En huet eng Rei Gehierimplantater fir seng Aktivitéit ze kontrolléiren. D'primitiv Raubinstinkter vun dëser Kreatur sinn just ze gebrauchen fir ze terroriséiren an ze zerstéiren. Reaper sinn verwand mat Floater.\"\n  STR_REAPER_AUTOPSY: \"Reaper Autopsie\"\n  STR_REAPER_AUTOPSY_UFOPEDIA: \"De Reaper huet zwee 'Gehierer' and zwee 'Häerzer' déi em erlaben ze iwwerliewen, och wann e schwéier verwond ass. Allerdéngs ass séng pelzesch Haut zimlech entflambar déi et enorm verwondbar géigeniwwer Feierwaffen mescht.\"\n  STR_SECTOPOD_UFOPEDIA: \"Sectopods sinn Roboterkreaturen mat enger staarker Laserwaff. D'Kontroll vun dësen Roboter geht iwwert eng telepatësch Verbindung mat hieren Kontrolleren, d'Ethereals. Sectopods sinn déi stäerksten Terrorwaff vun den Alien.\"\n  STR_SECTOPOD_AUTOPSY: \"Sectopod Autopsie\"\n  STR_SECTOPOD_AUTOPSY_UFOPEDIA: \"De Roboter ass kräfteg gebaut mat enger starker Panzerung déi denen meeschten Attacken kann widderstoen, zemols Plasma Waffen. Allerdéngs schéngen d'Sensoren sensibel géint Laserwaffen ze sinn.\"\n  STR_CYBERDISC_UFOPEDIA: \"Dëse Miniatur-UFO as eng automatiésiert Terrorwaff mat engem starken Plasmastral. Den Antigravitatiounsuntrieb huet en groussen Virdeel a schwéierem Terrain. D'Haptfunktioun ass Zerstéirung an Terror am Numm vun der Sektoidenrass.\"\n  STR_CYBERDISC_AUTOPSY: \"Cyberdisc Autopsie\"\n  STR_CYBERDISC_AUTOPSY_UFOPEDIA: \"De Cyberdisc ass gutt gepanzert an speziell resistent géint explosiv Munitioun. De primären Antigravitatiounssystem ass ze schwéier beschiedegt fir seng Fonktiounsweis ze analyséiren.\"\n  STR_UFO_POWER_SOURCE_UFOPEDIA: \"De Motor vun engem Alien Fliger as en anti-materiellen Reaktor den Elerium (Element 115) benotzt fir staark Gravitatiounswellen an aner Formen vun Energie ze generéiren. D'Emwandlung vun Materie zu Energie ass zu 99% effizient, dowéinst kann eng kléng Quantitéit Elerium eng grouss Quantitéit Energie produzéiren. Dës Unitéit kann einfach mat Alien Metaller nogebaut gin.\"\n  STR_UFO_NAVIGATION_UFOPEDIA: \"Alien Fliger hunn sophistikéiert Computer fir op d'Äerd duerch den Weltall ze navigéiren. De System baséiert op optëschen Prozessoren déi an engem Netzierk zesummenhenken. D'Steierung ass relativ einfach - den Navigator kontrolléiert d'Richtung vun den Gravitatiounswellen déi vun Kraftquell generéiert ginn fir de Fliger ze bewegen. De System kann einfach vun Mënschen benotzt ginn, an et kann reproduzéiert ginn mat Alien Metaller an aner Komponenten.\"\n  STR_UFO_CONSTRUCTION_UFOPEDIA: \"Alien Fliger bestinn aus 3 Haptkomponenten - e Motor, en Navigatiounssystem an e Rumpf aus Alienmetaller. De Rumpf ass designt fir Gravitatiounswellen kënne geleed a kontrolléiert ginn. Zousätzlech gëtt eng kleng Unzuel und Elerium gebraucht fir kënnen ze fléien. Wann d'Prinzipien vun der Konstruktioun an d'Fonktioun vun all Komponent verstan sinn, ass et méiglech dëse Fliger ze bauen.\"\n  STR_ALIEN_FOOD_UFOPEDIA: \"Des Räim hu verschidden Enzymer déi benotzt ginn fir Kierperdeeler vu Véi, aneren Déieren an sougur Mënschen ze verdauen. D'Flëssegkeet gëtt konsuméiert als fäerdeg verdaut Iessen - wahrscheinlech direkt an der Bluttzirkulatioun.\"\n  STR_ALIEN_REPRODUCTION_UFOPEDIA: \"An dësen Kummeren gëtt et Alien Fötusen. Den Design vun den Containeren schléisst dorop hin, dass d'Alien komplett op kënstlëch Befruchtung wäert leeën. Räichhaltegt Fudder garantéiert eng séier Entwécklung vum Fötus. Dësen fabrikartëgen System kann Dausenden vun Alienclonen an enger kuerzer Zäit produzéiren. De Prozess kann einfach un Mënschen oder Alien-Mënschen ugepasst ginn.\"\n  STR_ALIEN_ENTERTAINMENT_UFOPEDIA: \"Déi wahrscheinlechsten Funktioun vun dësen Kugelen ass Ënnerhalung. D'psionësch Schaltkreser stimuléiren verschidden Gehierzentren. Den Effekt ass den selweschten wéi bei halluzinéisen Drogen. Dëst ass den eenzegen Beweis, dass d'Alien an hierer Fräizäit Kultur an Ënnerhalung hunn.\"\n  STR_ALIEN_SURGERY_UFOPEDIA: \"D'chirurgescht Equipement benotzt Laserschneider fir verschidden Kierperdeeler aus Béischten an aneren Déiren rauszeschneiden. D'verbreeden Béischtenmutatiounen schléissen op dës komesch Alien Aktivitéit zréck. Et ass wahrscheinlech, dass des Deeler fir d'Ernährung oder genetesch Zwecker benotzt ginn.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"An der Vergangenheet hun dausenden Leit behapt se wieren vun Alien ënnersicht ginn, heiansdo et puer mol. D'Wourëcht ass vill méi schlëmm. Mënschen ginn entfouert, ennersicht an iwwerwaacht. Vun denen beschten Spezimen gëtt genetëscht Material entzunn. Fraën kréien Alien-Mënschen Fötusen implantéiert, an dann e puer Méint spéider erem erausgeholl. Wen weess wat fir düster Motiver d'Alien nach hunn ?\"\n  STR_ALIEN_ALLOYS_UFOPEDIA: \"Alien Fliger sin aus engem speziellen Aluminium gebaut. Se sinn extrem liicht an stabil an kënnen durch elektro-mangéitesch Methoden geformt ginn. Dëst Material kann reproduzéiert ginn an an villen handwierklëchen Prozesser benotzt ginn.\"\n  STR_ELERIUM_115_UFOPEDIA: \"Dest Element huet déi ongewéinleg Eegeschaft fir anti-materiell Kraft ze entwéckelen wann se mat gewësse Partikel beschoss gëtt. Dest féiert zu Gravitatiounswellen an anere Formen vun Energie. Et ass net natierlecherweis an eisem Solarsystem ze fannen an kann och net reproduzéiert ginn.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"Et ass sëcher, dass mer en aussiichtslosen Kampf op der Äerd ausdroen. D'Alien Horden sinn an der Zuel iwwerleeën. Dat Bescht wat mer kënnen maachen, ass hieren Fortschrëtt ze bremsen. Déi eenzeg Hoffnung fir d'Menschheet ze retten, ass d'Alien un hierer Quell ze attackéiren. Eis Forschung huet Indicen fonnt, dass et eng operativ Basis an eisem Solarsystem gëtt. D'Alien behapten, dass dës Plaz den Zentrum vun enger antiker Zvilisatioun ass, déi et schons firun den Mënschen gouf. Mir mussen dës Plaz esou séier wéi méiglech fannen. Allerdéngs mussen mer en Alien Leader fannen an lieweg fänken, fir méi detailléiert Informatiounen ze kréien. Déi méi grouss UFOs hunn wahrscheinlech op manst een Alien Leader u Bord.\"\n  STR_THE_MARTIAN_SOLUTION_UFOPEDIA: \"Eis Forschung leed eis elo op de Mars als Basis vun den Alien Operatiounen. D'Basis ass gutt verstoppt, an huet all d'Fabriken an Klonräim fir d'Infiltratioun vun der Äerd ze garantéiren. Se schéngt och e Kontrollcomputer ze hunn den alles steiert. Et schéngt wéi wann déi schwarm-ähnlech Aliengesellschaft eppes wéi eng 'Beiekinnigin' hätt. Dest ass hir Schwächt - wa mer kënnen hiert 'Gehier' ausschalten, wäert de Kierpr stierwen. Mir mussen eis Forschung beschleunegen befier et ze spéit ass. Fir weiderzekommen musse mer hir héchsten Leader a Gefaangeschaft huelene - d'Kommandeuren - déi et just an den Alienbasen an Schlachtschëffer ze fanne gett.\"\n  STR_CYDONIA_OR_BUST_UFOPEDIA: \"Et ass elo kloër, dass d'Alien vun enger ënnerierdëscher Basis aus Cydonia kontrolléiert ginn - wat eng ongewéinlech Zone um Mars ass, déi aus fënnefsäitegen Pyramiden an enger grousser Formatioun besteet déi engem mënschlechen Gesiicht ähnelt. D'cydonësch Zivilisatioun huet firun Milliounen Joren um Mars geliewt, mee mir wëssen net, wisou se ausgestuerw ass oder wellech Verbindung se zu den neisten Aktivitéiten vun den Alien hunn. Op alle Fall muss eng Expeditioun op Cydonia gemet ginn. Nëmmen sou kënnen d'Alien bezwongen ginn. Mir mussen d''Gehier' zerstéiren dat se steiert. Mir brauchen en Avenger mat denen beschten Waffen déi mer hunn. Hei kommen mer net weider, mir mussen de Kampf op Cydonia ofwarden.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"OP DE SITE ZENTRÉIREN-ZÄIT=5 Sek.\"\n  STR_CANCEL_UC: \"OFBRIECHEN\"\n  STR_NONE: \"Ouni\"\n  STR_UNKNOWN: \"Onbekannt\"\n  STR_POOR: \"Schlecht\"\n  STR_AVERAGE: \"Mëttel\"\n  STR_GOOD: \"Gutt\"\n  STR_EXCELLENT: \"Exzellent\"\n  STR_BUILD_NEW_BASE_UC: \"NEI BASIS BAUEN\"\n  STR_BASE_INFORMATION: \"BASIS INFO\"\n  STR_EQUIP_CRAFT: \"FLIGER EQUIPÉIREN\"\n  STR_BUILD_FACILITIES: \"RAIMLECHKEETEN BAUEN\"\n  STR_RESEARCH: \"FORSCHUNG\"\n  STR_MANUFACTURE: \"HIERSTELLUNG\"\n  STR_TRANSFER_UC: \"TRANSFEREIREN\"\n  STR_PURCHASE_RECRUIT: \"KAFEN/ASTELLEN\"\n  STR_SACK: \"ENTLOOSSEN\"\n  STR_SELL_SACK_UC: \"VERKAFEN/ENTLOOSSEN\"\n  STR_GEOSCAPE_UC: \"GEOSCAPE\"\n  STR_NAME: \"Numm\"\n  STR_AREA: \"Areal\"\n  STR_BUILD_NEW_BASE: \"Nei Basis bauen\"\n  STR_CANCEL: \"Ofbriechen\"\n  STR_COST_UC: \"KÄSCHTEN>\"\n  STR_CONSTRUCTION_TIME_UC: \"KONSTRUKTIOUNSZÄIT>\"\n  STR_DAY:\n    one: \"{N} Dag\"\n    other: \"{N} Deeg\"\n  STR_HOUR:\n    one: \"{N} Stonn\"\n    other: \"{N} Stonnen\"\n  STR_MAINTENANCE_UC: \"ËNNERHALT>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Installatioun\"\n  STR_CURRENT_RESEARCH: \"AKTUELL FORSCHUNG\"\n  STR_SCIENTISTS_AVAILABLE: \"Wëssenschaftler verfügbar>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Wëssenschaftler zougedeelt>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Laboen verfügbar>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"FORSCHUNGSPROJET\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"WËSSENSCHAFTLER ZOUGEDEELT\"\n  STR_PROGRESS: \"FORTSCHRËTT\"\n  STR_NEW_PROJECT: \"Neie Projet\"\n  STR_CANCEL_PROJECT: \"PROJET OFBRIECHEN\"\n  STR_NEW_RESEARCH_PROJECTS: \"NEI FORSCHUNGSPROJEKTER\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"WESSENTSCHAFTLER VERFÜGBAR>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"LABO PLAZ VERFÜGBAR>{ALT}{0}\"\n  STR_INCREASE: \"Méi\"\n  STR_DECREASE: \"Manner\"\n  STR_START_PROJECT: \"PROJET STARTEN\"\n  STR_CURRENT_PRODUCTION: \"AKTUELL PRODUKTIOUN\"\n  STR_ENGINEERS_AVAILABLE: \"Ingenieuren verfügbar>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Ingenieuren zougedeelt>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Atelieren verfügbar>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Momentan Gelder>{ALT}{0}\"\n  STR_ITEM: \"DEEL\"\n  STR_ENGINEERS__ALLOCATED: \"Ingenieuren zougedeelt\"\n  STR_UNITS_PRODUCED: \"Eenheeten produzéiert\"\n  STR_TOTAL_TO_PRODUCE: \"Unzuel déi produzéiert gëtt\"\n  STR_COST__PER__UNIT: \"Käschten{NEWLINE}pro{NEWLINE}Eenheet\"\n  STR_DAYS_HOURS_LEFT: \"Deeg/Stonnen iwwreg\"\n  STR_NEW_PRODUCTION: \"Nei Produktioun\"\n  STR_PRODUCTION_ITEMS: \"Produktioun\"\n  STR_CATEGORY: \"KATEGORIE\"\n  STR_START_PRODUCTION: \"PRODUKTIOUN STARTEN\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} Ingenieur-Stonnen fir eng Eenheet ze bauen\"\n  STR_COST_PER_UNIT_: \"Käschten pro Eenheet>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Atelieren gebraucht>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"BRAUCH SPEZIALMATERIAL\"\n  STR_ITEM_REQUIRED: \"DEEL GEBRAUCHT\"\n  STR_UNITS_REQUIRED: \"EENHEETEN GEBRAUCHT\"\n  STR_UNITS_AVAILABLE: \"EENHEETEN VERFUGBAR\"\n  STR_STOP_PRODUCTION: \"PRODUKTIOUN STOPPEN\"\n  STR_ENGINEERS_AVAILABLE_UC: \"INGENIEUREN VERFÜGBAR>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"ATELIERS PLAZ VERFÜGBAR>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"PROFIT PRO MOUNT>{ALT}{0}\"\n  STR_INCREASE_UC: \"MÉI\"\n  STR_DECREASE_UC: \"MANNER\"\n  STR_UNITS_TO_PRODUCE: \"Eenheeten déi produzéiert ginn\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Personal kafen/astellen\"\n  STR_COST_OF_PURCHASES: \"Kafkàschten>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"KÄSCHTEN PRO EENHEET\"\n  STR_QUANTITY_UC: \"UNZUEL\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"PERSONAL VERFÜGBAR:PERSONAL TOTAL>\"\n  STR_SOLDIERS: \"Zaldoten\"\n  STR_SCIENTISTS: \"Wëssenschaftler\"\n  STR_ENGINEERS: \"Ingenieuren\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"PLAZ BENOTZT:PLAZ VERFÜGBAR>\"\n  STR_LIVING_QUARTERS: \"Wunnräim\"\n  STR_STORES: \"Lager\"\n  STR_LABORATORIES: \"Laboen\"\n  STR_WORK_SHOPS: \"Atelieren\"\n  STR_HANGARS: \"Hangaren\"\n  STR_SHORT_RANGE_DETECTION: \"Kuerzstreckenerkennung\"\n  STR_DEFENSE_STRENGTH: \"Verteidegungsstäerkt\"\n  STR_TRANSFERS_UC: \"TRANSFEREN\"\n  STR_TRANSFERS: \"Transferen\"\n  STR_ARRIVAL_TIME_HOURS: \"Ukonftszäit (Stonnen)\"\n  STR_COST_: \"Käschten>{ALT}{0}\"\n  STR_AREA_: \"Areal>{ALT}{0}\"\n  STR_BASE_NAME: \"Numm fir d'Basis?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"WIEL D'POSITIOUN FIR DEN AGANGSLIFT\"\n  STR_TRANSFER: \"Transfer\"\n  STR_AMOUNT_TO_TRANSFER: \"UNZUEL FIR ZE TRANSFERÉIREN\"\n  STR_SELECT_DESTINATION_BASE: \"Zilbasis auswielen\"\n  STR_COST: \"Käschten\"\n  STR_VICTORY_1: \"Wéis'de an de Raum rakoums, huesde d'Alien Gehir gesinn - den Objet vun dénger Missioun. Befiersde konns lassschéissen, kommunizéiert et mat der iwwert e Bildschierm an senger Basis. Et bied dech séngen iwwerliewenswichtegen Argumenter nozelauschteren, befiers d'Entscheedung trëffs fir lasszeschéissen...\"\n  STR_VICTORY_2: \"D'Gehir seet: 'Viru Milliounen Joren war de Planéit den's de Mars nenns lieweg. Dëst Liewen gouf zu engem Ödland duerch eis Zivilisatioun. Während Milliounen Joren sinn mir op ären Planéit komm an hunn är genetesch Spezies entwéckelt. Dir kënnt eis net ëmbréngen, dir sidd en Deel vun eis...'\"\n  STR_VICTORY_3: \"Hei ass den Zentrum vun der marsianescher Zivilisatioun - mat Pyramiden déi millioune Joren firun äere gebaut goufen - vun enger Spezie déi är Virfahre sinn. Keen Planéit ass an eiser Reechwäit. Dës Kraft hätt är kënnte sinn, firu laangem schon. Alles wat mir wëllen, ass är Kooperatioun...\"\n  STR_GAME_OVER_1: \"D'Alien probéiren d'Mënschheet auszeläschen, zerstéiren Stied an vergëften d'Loft an Mierer. De Widderstand vun den Mënschenarméi ass sënnlos géigeniwwer der enorm besserer Technologie. Iwwerliewend Generatiounen leider ënner terriblen Mutatiounen an lafen vun der Alienzerstéirung fort. Se ginn an Sklavencamps gefangen an mussen hëllefen d'Aerd an eng Alienkolonie ze verwandeln, déi dann Deel vun engem onbekannten Räich gëtt.\"\n  STR_GAME_OVER_2: \"D'Wëssen wat durch den X-Com Projet erlaangt gouf, ass fir ëmmer verluer. Du hues et net geschafft d'Äerd ze retten.\"\n  STR_VICTORY_4: \"D'Aliengehier ass durch en warmen Plasmastrahl ënnerbrach ginn, an d'gesamt Alienarméi ass ënnergaang.\"\n  STR_VICTORY_5: \"Wann d'Alien den Mars verluer hunn, hunn se d'Äerd verluer. Gläich wäert d'XCom-Forschung  erem opbléien an den Mars fir sech behapten. D'Alienbedrohung ass fort, mee ween weess fir wéi laang...\"\n  STR_YOU_HAVE_FAILED: \"Du konns d'Alienattacken net ofwieren. Een nom aneren schléissen déi bezuelend Natiounen Pakter mat den Alien déi hinnen Technologien, Wuelstand an Fridden verspriechen. Allerdéngs ass schnell kloer ginn, dass d'Alien aner Pläng hunn...\"\n  STR_TOTAL_UC: \"TOTAL\"\n  STR_INCOME: \"Akommes\"\n  STR_EXPENDITURE: \"Ausgaben\"\n  STR_MAINTENANCE: \"Ënnerhalt\"\n  STR_BALANCE: \"Bilanz\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"UFO Aktivitéit an den Arealer\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"UFO Aktivitéit an de Länner\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"X-Com Aktivitéit an den Arealer\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"X-Com Aktivitéit an de Länner\"\n  STR_FINANCE: \"Finanzen\"\n  STR_DATE_FIRST: \"{0}t(en)\"\n  STR_DATE_SECOND: \"{0}t(en)\"\n  STR_DATE_THIRD: \"{0}t(en)\"\n  STR_DATE_FOURTH: \"{0}t(en)\"\n  STR_FINANCE_THOUSANDS: \"$1000\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Net genuch Spezialmaterial fir d'Konstruktioun vun{NEWLINE}{0}{NEWLINE}Basis:{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Net genuch Finanzen fir{NEWLINE}{0}{NEWLINE}ze produzéiren zu{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"Produktioun vun{NEWLINE}{0}{NEWLINE}ass faerdeg{NEWLINE}Basis:{1}{NEWLINE}\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"Konstruktioun vun{NEWLINE}{0}{NEWLINE}ass faerdeg{NEWLINE}Basis:{1}{NEWLINE}\"\n  STR_OK_5_SECONDS: \"OK - 5 Sek\"\n  STR_RESEARCH_COMPLETED: \"Fuerschung fäerdeg\"\n  STR_VIEW_REPORTS: \"RAPPORT LIESEN\"\n  STR_WE_CAN_NOW_RESEARCH: \"Nei Forschungsméiglechkeet\"\n  STR_WE_CAN_NOW_PRODUCE: \"Nei Produktiounsméiglechkeet \"\n  STR_SUNDAY: \"SONNDEN\"\n  STR_MONDAY: \"MÉINDEN\"\n  STR_TUESDAY: \"DËNSCHDEN\"\n  STR_WEDNESDAY: \"MËTTWOCH\"\n  STR_THURSDAY: \"DONNESCHDEG\"\n  STR_FRIDAY: \"FREIDEG\"\n  STR_SATURDAY: \"SAMSDEN\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Net genuch {0} fir den {1} zu {2} opzefëllen\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Net genuch {0} fir {1} an {2} nei ze lueden\"\n  STR_UFO_IS_NOT_RECOVERED: \"UFO gouf net gebuergen\"\n  STR_UFO_IS_RECOVERED: \"UFO gouf gebuergen\"\n  STR_CRAFT_IS_LOST: \"Fliger ass verluer\"\n  STR_TERROR_CONTINUES: \"Den Terror geet weider\"\n  STR_ALIENS_DEFEATED: \"Aliens vernicht\"\n  STR_BASE_IS_LOST: \"Basis ass verluer\"\n  STR_BASE_IS_SAVED: \"Basis gouf gerett\"\n  STR_ALIEN_BASE_STILL_INTACT: \"Alien Basis nach intakt\"\n  STR_ALIEN_BASE_DESTROYED: \"Alien Basis zerstéiert\"\n  STR_ALIENS_KILLED: \"ALIEN EMBRUED\"\n  STR_ALIEN_CORPSES_RECOVERED: \"ALIEN KIERPER GEBUERGEN\"\n  STR_LIVE_ALIENS_RECOVERED: \"LIEWEG ALIEN GEBUERGEN\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"ALIEN ARTEFAKTER GEBUERGEN\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"ALIEN BASIS KONTROLL ZERSTEIERT\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"ZIVILISTEN VUN ALIEN GEKILLT\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"ZIVILISTEN EMBRUED VUN X-COM LEIT\"\n  STR_CIVILIANS_SAVED: \"ZIVILISTE GERETT\"\n  STR_XCOM_OPERATIVES_KILLED: \"X-COM LEIT EMBRUED GINN\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"X-COM LEIT VERMËSST\"\n  STR_TANKS_DESTROYED: \"TANK ZERSTÉIERT\"\n  STR_XCOM_CRAFT_LOST: \"X-COM FLIGER VERLUER\"\n  STR_UFO_RECOVERY: \"UFO BIERGUNG\"\n  STR_ALIEN_BASE_RECOVERY: \"BIERGUNG VUN ENGER ALIEN BASE\"\n  STR_BASE_UNDER_ATTACK: \"{0} gëtt ugegraff!\"\n  STR_BASE_DEFENSES_INITIATED: \"BASISVERTEIDEGUNG AGELEED\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"GRAV SCHËLD HUET UFO OFGEWIERT!\"\n  STR_FIRING: \"SCHÉISST\"\n  STR_HIT: \"TREFFER!\"\n  STR_UFO_DESTROYED: \"UFO ZERSTEIERT!\"\n  STR_MISSED: \"LAANSCHT!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Deeler verkafen/Personal entloossen\"\n  STR_VALUE_OF_SALES: \"WÄERT VUN DEN VERKEEF>{ALT}{0}\"\n  STR_FUNDS: \"GELDER> {ALT}{0}\"\n  STR_SELL_SACK: \"Verkafen/Entloossen\"\n  STR_VALUE: \"Wäert\"\n  STR_CRAFT_: \"FLIGER> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"UFO CRASH BIERGUNG\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"Opgepasst - et kinnten XCom-Matarbëschter am UFO oder ronderem d'Crash-Plaz sinn. D'Missioun ass en Erfollëg wann all Géigner eliminéiert oder neutraliséiert gouf. Dono ginn UFO-Deeler, Artefakter an doudeg Alien gebuergen. Fir d'Missioun ofzebriechen, mussen d'XCom-Leit zeréck an de Fliger goen an dann op 'Missioun ofbriechen' klicken.\"\n  STR_UFO_GROUND_ASSAULT: \"UFO BUEDEMATTACK\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"Erkund d'Géigend vun der Landeplaz an, wa méiglech, kuck fir an den UFO eranzekommen. D'Missioun ass en Erfollëg wann all Géigner eliminéiert oder neutraliséiert gouf. Dono ginn UFO-Deeler, Artefakter an doudeg Alien gebuergen. Fir d'Missioun ofzebriechen, mussen d'XCom-Leit zeréck an de Fliger goen an dann op 'Missioun ofbriechen' klicken.\"\n  STR_BASE_DEFENSE: \"BASISVERTEIDEGUNG\"\n  STR_BASE_UC_: \"BASIS> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"En Alienschëff ass an der Géigend geland. Eis Basis ass a grousser Gefor. All net-bewaffnet Personal an X-Com Fligeren goufen laut Standardprozedur evakuéiert. D'Alien kommen via den Hangar oder den Zougangslift an d'Basis eran. Verteideg d'Basis an seng wichteg Installation em all Präis - dest ass e Kampf em Liewen an Doud. Wann op 'Missioun ofbriechen' geklickt gëtt, gëssde op an d'Basis ass verluer.\"\n  STR_ALIEN_BASE_ASSAULT: \"UGREFF OP ENG ALIEN BASIS\"\n  STR_ALIEN_BASE_ASSAULT_BRIEFING: \"X-Com Leit sinn an d'Alienbasis erakomm. De Kontrollzentrum muss zerstéiert ginn fir d'Basis inoperabel ze man. D'Missioun ass fäerdeg wann all Géigner eliminéiert gouf, oder wann d'Ekipp rem an déi gréng Ausgangszone zeréckkënnt (klick op 'Missioun ofbriechen' fir zeréckzefléien)\"\n  STR_CYDONIA_BRIEFING: \"Du bass zu Cydonia ukomm. Du hues Zoutrëtt zu engem ënnerierdeschen Komplex nierft der Martianescher Sphinx kritt. Du muss d'Alien Gehier wat all Alienaktivitéiten kontrolléiert zerstéieren. D'Schicksal vun der Mënschheet läit an dengen Hänn....\"\n  STR_TERROR_MISSION: \"TERROR MISSIOUN\"\n  STR_TERROR_MISSION_BRIEFING: \"D'Missioun ass en Erfolleg wann all géigneresch Eenheeten eliminéiert oder neutraliséiert goufen. Du muss versichen all Zivilisiten am Areal ze beschützen andems d'Gefor vun den Alien neutraliséiert gëtt. Fir d'Missioun ofzebriechen, bréng deng X-Com Leit zeréck zum Transporter an klick op den Icon 'Missioun ofbriechen'.\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"KENG FRÄI HANGAREN FIR E FLIGER ZE BAUEN!{SMALLLINE}All Fliger den enger Base gehéiert, op eng transferéiert gëtt, kaft oder gebaut gëtt, brauch e fräien Hangar. Bau en neien Hangar oder transferéiert ee Fliger op eng aner Base.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"KENG FRÄI HANGAREN FIR E FLIGER ZE KAFEN!{SMALLLINE}All Fliger den enger Base gehéiert, op eng transferéiert gëtt, kaft oder gebaut gëtt, brauch e fräien Hangar. Bau en neien Hangar oder transferéiert ee Fliger op eng aner Base.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"KENG FRÄI HANGAREN FIR E FLIGER ZE TRANSFEREIREN!{SMALLLINE}All Fliger den enger Base gehéiert, op eng transferéiert gëtt, kaft oder gebaut gëtt, brauch e fräien Hangar. Bau en neien Hangar oder transferéiert ee Fliger op eng aner Base.\"\n  STR_CANNOT_BUILD_HERE: \"KANN HEI NET BAUEN!{SMALLLINE}Muss un en anert Basismodul ugrenzen.\"\n  STR_NO_FREE_ACCOMODATION: \"KENG FRAI RAIM!{SMALLLINE}D'Zilbasis huet net genuch fräi Plaz an de Wunnräim.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"NET GENUCH ARBESCHTSRAIM VERFÜGBAR!{SMALLLINE}Bau en neien Atelier oder reduzéier d'Arbeschter vun aneren Projeten.\"\n  STR_NOT_ENOUGH_MONEY: \"NET GENUCH GELD!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"NET GENUCH PLAZ AM STOCK!{SMALLLINE}Bau en neien Stock oder transferéier Wueren aus dem Stock op eng aner Basis.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"NET GENUCH WUNNRAUM!{SMALLLINE}Bau nei Wunnräim oder transferéier Personal op eng aner Basis.\"\n  STR_LAUNCH_INTERCEPTION: \"OFFANGMANÖVER STARTEN\"\n  STR_CRAFT: \"FLIGER\"\n  STR_STATUS: \"STATUS\"\n  STR_BASE: \"BASIS\"\n  STR_READY: \"BEREED\"\n  STR_OUT: \"DOBAUSSEN\"\n  STR_REPAIRS: \"REPARATIOUN\"\n  STR_REFUELLING: \"NOTANKEN\"\n  STR_REARMING: \"BEWAFFNEN\"\n  STR_TARGET: \"ZIL: {0}\"\n  STR_WAY_POINT: \"WEEPUNKT\"\n  STR_ARE_YOU_SURE_CYDONIA: \"Bass du sëcher dëse Fliger op eng Missioun a Cydonia ze schécken?\"\n  STR_YES: \"JO\"\n  STR_NO: \"NEE\"\n  STR_SELECT_DESTINATION: \"ZIL WIELEN\"\n  STR_CYDONIA: \"CYDONIA\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"NEIE SITE FIR BASIS WIELEN\"\n  STR_RETURN_TO_BASE: \"ZERÉCK OP D'BASIS\"\n  STR_SELECT_NEW_TARGET: \"WIEL NEIT ZIL\"\n  STR_PATROL: \"PATRULLÉIREN\"\n  STR_STATUS_: \"STATUS>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"BESCHIEDEGT - FLITT ZERÉCK OP D'BASIS\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"WÉINEG BENSIN - FLITT ZERÉCK OP D'BASIS\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"MISSIOUN FÄERDEG - FLITT ZERÉCK OP D'BASIS\"\n  STR_PATROLLING: \"PATRULLÉIERT\"\n  STR_TAILING_UFO: \"VERFOLLEGEN UFO\"\n  STR_INTERCEPTING_UFO: \"FENKT UFO-{0} OF\"\n  STR_RETURNING_TO_BASE: \"FLITT ZERÉCK OP D'BASIS\"\n  STR_DESTINATION_UC_: \"ZIL: {0}\"\n  STR_BASE_UC: \"BASIS>{ALT}{0}\"\n  STR_SPEED_: \"GESCHW.>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"MAXIMAL GESCHW.>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"HÉIGT>{ALT}{0}\"\n  STR_VERY_LOW: \"GANZ NIDDRËG\"\n  STR_LOW_UC: \"NIDDRËG\"\n  STR_HIGH_UC: \"HÉIG\"\n  STR_VERY_HIGH: \"GANZ HÉIG\"\n  STR_FUEL: \"BENSIN>{ALT}{0}\"\n  STR_WEAPON_ONE: \"WAFF-1>{ALT}{0}\"\n  STR_NONE_UC: \"OUNI\"\n  STR_ROUNDS_: \"RONNEN>{ALT}{0}\"\n  STR_WEAPON_TWO: \"WAFF-2>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"OFFANGFLIGER\"\n  STR_BASE_: \"Basis>{0}\"\n  STR_NAME_UC: \"NUMM\"\n  STR_AMMO_: \"MUNITIOUN>{ALT}{0}\"\n  STR_CREW: \"CREW\"\n  STR_EQUIPMENT_UC: \"EQUIPEMENT\"\n  STR_ARMOR: \"RÜSTUNG\"\n  STR_MAX: \"MAX>{ALT}{0}\"\n  STR_ROOKIE: \"Ufänger\"\n  STR_SQUADDIE: \"Zaldot\"\n  STR_SERGEANT: \"Sergant\"\n  STR_CAPTAIN: \"Kapitän\"\n  STR_COLONEL: \"Kolonel\"\n  STR_COMMANDER: \"Kommandant\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Wiel d'Ekipp fir {0}\"\n  STR_SORT_BY: \"SORTÉIREN NO...\"\n  STR_ORIGINAL_ORDER: \"UFANKSUEDER\"\n  STR_MISSIONS2: \"MISSIOUNEN\"\n  STR_KILLS2: \"EMBRUED\"\n  STR_WOUND_RECOVERY2: \"WONNENHEELUNG\"\n  STR_SPACE_AVAILABLE: \"PLAZ VERFÜGBAR>{ALT}{0}\"\n  STR_SPACE_USED: \"GEBRAUCHTE PLAZ>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"GEBRAUCHTE PLAZ\"\n  STR_RANK: \"RANG\"\n  STR_WOUNDED: \"VERLETZT\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Equipement fir {0}\"\n  STR_DEFENSE_VALUE: \"Verteidegungswert\"\n  STR_HIT_RATIO: \"Trefferquote\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}bereed an der Géigend vun{NEWLINE}{ALT}{1}{NEWLINE}ze landen\"\n  STR_BEGIN_MISSION: \"Missioun starten?\"\n  STR_SELECT_ARMAMENT: \"Rüstung wielen\"\n  STR_AMMUNITION_AVAILABLE: \"MUNITIOUN VERFÜGBAR\"\n  STR_ARMAMENT: \"BEWAFFNUNG\"\n  STR_NOT_AVAILABLE: \"-\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"WIEL RÜSTUNG FIR{NEWLINE}{0}\"\n  STR_TYPE: \"TYP\"\n  STR_PERSONAL_ARMOR_UC: \"PERSOUNENPANZER\"\n  STR_POWER_SUIT_UC: \"POWERKOSTÜM\"\n  STR_FLYING_SUIT_UC: \"FLUGKOSTÜM\"\n  STR_SELECT_ARMOR: \"Rüstung auswielen\"\n  STR_NORTH: \"NORDEN\"\n  STR_NORTH_EAST: \"NORDOSTEN\"\n  STR_EAST: \"OSTEN\"\n  STR_SOUTH_EAST: \"SÜD OST\"\n  STR_SOUTH: \"SÜD\"\n  STR_SOUTH_WEST: \"SÜDWEST\"\n  STR_WEST: \"WEST\"\n  STR_NORTH_WEST: \"NORDWEST\"\n  STR_SELECT_ACTION: \"AKTIOUN WIELEN\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"OFFÄNKMANÖVER WIEDERMAN\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"VERFOLGEN OUNI UGRËFF\"\n  STR_VERY_LARGE: \"GANZ GROUSS\"\n  STR_LARGE: \"GROUSS\"\n  STR_MEDIUM_UC: \"METTEL\"\n  STR_SMALL: \"KLENG\"\n  STR_VERY_SMALL: \"GANZ KLENG\"\n  STR_GROUNDED: \"BUEDEM\"\n  STR_DETECTED: \"Entdeckt\"\n  STR_SIZE_UC: \"GREISST\"\n  STR_ALTITUDE: \"HÉIGT\"\n  STR_HEADING: \"RICHTUNG\"\n  STR_SPEED: \"GESCHWINDEGKEET\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"OP UFO ZENTRÉIREN-ZÂIT=5 Sek.\"\n  STR_TRACKING_LOST: \"ZIL VERLUER\"\n  STR_REDIRECT_CRAFT: \"FLIGER EMLEEDEN\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"OP DEI LESCHT BEKANNTEN UFO POSITIOUN GOEN\"\n  STR_UFO_: \"UFO-{0}\"\n  STR_ALIEN_BASE_: \"ALIEN BASIS-{0}\"\n  STR_CRASH_SITE_: \"CRASH-PLAZ-{0}\"\n  STR_LANDING_SITE_: \"LANDUNGSSITE-{0}\"\n  STR_WAY_POINT_: \"WEEPUNKT-{0}\"\n  STR_TERROR_SITE: \"TERRORSITE-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}huet{NEWLINE}{1}erreecht\"\n  STR_NOW_PATROLLING: \"Patroulléiert\"\n  STR_ALIEN_ORIGINS: \"Alien Originen\"\n  STR_THE_MARTIAN_SOLUTION: \"D'marsianesch Léisung\"\n  STR_CYDONIA_OR_BUST: \"Cydonia oder gelénkt\"\n  STR_UFOPAEDIA: \"UFOpedia\"\n  STR_XCOM_CRAFT_ARMAMENT: \"X-COM FLIGER A WAFFEN\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"SCHWEIER WAFFE PLATTFORM\"\n  STR_WEAPONS_AND_EQUIPMENT: \"WAFFEN AN EQUIPEMENT\"\n  STR_ALIEN_ARTIFACTS: \"ALIEN ARTEFAKTER\"\n  STR_BASE_FACILITIES: \"BASISRAIMLECHKEETEN\"\n  STR_ALIEN_LIFE_FORMS: \"ALIEN LIEWENSFORMEN\"\n  STR_ALIEN_RESEARCH_UC: \"ALIEN FORSCHUNG\"\n  STR_UFO_COMPONENTS: \"UFO STÉCKER\"\n  STR_UFOS: \"UFOen\"\n  STR_SELECT_ITEM: \"DEEL WIELEN\"\n  STR_ACCELERATION: \"BESCHLEUNIG.>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"BENSINSTANK>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"WAFFEBEHÄLTER>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"SCHUEDENSKAPAZITEIT>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"CARGORAUM>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"SWP KAPAZITEIT>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Schued\"\n  STR_RANGE: \"Reechwäit\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Genauegkeet\"\n  STR_RE_LOAD_TIME: \"Nei-lued-Zäit\"\n  STR_SECONDS: \"{0}s\"\n  STR_DAMAGE_ARMOR_PIERCING: \"PANZERBRIECHEND\"\n  STR_DAMAGE_INCENDIARY: \"BRANDSTOFF\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"HÉIGEXPLOSIV\"\n  STR_DAMAGE_LASER_BEAM: \"LASERSTRAHL\"\n  STR_DAMAGE_PLASMA_BEAM: \"PLASMASTRAHL\"\n  STR_DAMAGE_STUN: \"BETÄUBEN\"\n  STR_DAMAGE_MELEE: \"NOKAMPF\"\n  STR_DAMAGE_ACID: \"SAIER\"\n  STR_DAMAGE_SMOKE: \"DAMP\"\n  STR_SHOT_TYPE: \"SCHOSSTYP\"\n  STR_ACCURACY_UC: \"GENAUEGKEET\"\n  STR_TIME_UNIT_COST: \"ZE KÄSCHTEN\"\n  STR_DAMAGE_UC: \"SCHUED\"\n  STR_AMMO: \"MUNITIOUN\"\n  STR_SHOT_TYPE_AUTO: \"Auto\"\n  STR_SHOT_TYPE_SNAP: \"Schnell\"\n  STR_SHOT_TYPE_AIMED: \"Gezilt\"\n  STR_CONSTRUCTION_TIME: \"Konstruktiounsdauer\"\n  STR_CONSTRUCTION_COST: \"Konstruktiounskäschten\"\n  STR_MAINTENANCE_COST: \"Ënnerhalungskäschten\"\n  STR_LOW: \"Niddreg\"\n  STR_MEDIUM: \"Mëttel\"\n  STR_HIGH: \"Héig\"\n  STR_CRAFT_WEAPON: \"Waffe bauen\"\n  STR_CRAFT_AMMUNITION: \"Munitioun bauen\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Schwéier Waffe Plattform\"\n  STR_WEAPON: \"Waff\"\n  STR_AMMUNITION: \"Munitioun\"\n  STR_EQUIPMENT: \"Equipement\"\n  STR_ALIEN_CORPSE: \"Alien Kierper\"\n  STR_UFO_COMPONENT: \"UFO Komponent\"\n  STR_PERSONAL_ARMOR: \"PERSOUNENPANZER\"\n  STR_RAW_MATERIALS: \"Réimaterial\"\n  STR_HWP_CANNON_SHELLS: \"SWP Kanounenschoss\"\n  STR_ALIEN: \"Alien\"\n  STR_SECTOID: \"Sektoid\"\n  STR_SNAKEMAN: \"Schlaangemënsch\"\n  STR_ETHEREAL: \"Ethereal\"\n  STR_MUTON: \"Muton\"\n  STR_FLOATER: \"Floater\"\n  STR_CELATID: \"Celatid\"\n  STR_SILACOID: \"Silacoid\"\n  STR_CHRYSSALID: \"Chryssalid\"\n  STR_ZOMBIE: \"Zombie\"\n  STR_REAPER: \"Reaper\"\n  STR_SECTOPOD: \"Sectopod\"\n  STR_CYBERDISC: \"Cyberdisc\"\n  STR_LIVE_COMMANDER: \"Kommandant\"\n  STR_LIVE_LEADER: \"Leader\"\n  STR_LIVE_ENGINEER: \"Ingenieur\"\n  STR_LIVE_MEDIC: \"Dokter\"\n  STR_LIVE_NAVIGATOR: \"Navigator\"\n  STR_LIVE_SOLDIER: \"Zaldot\"\n  STR_LIVE_TERRORIST: \"Terrorist\"\n  STR_FLOATER_SOLDIER: \"Floater Zaldot\"\n  STR_FLOATER_NAVIGATOR: \"Floater Navigator\"\n  STR_FLOATER_MEDIC: \"Floater Dokter\"\n  STR_FLOATER_ENGINEER: \"Floater Ingenieur\"\n  STR_FLOATER_LEADER: \"Floater Anführer\"\n  STR_FLOATER_COMMANDER: \"Floater Kommandant\"\n  STR_SECTOID_SOLDIER: \"Sectoid Zaldot\"\n  STR_SECTOID_NAVIGATOR: \"Sectoid Navigator\"\n  STR_SECTOID_MEDIC: \"Sektoiden Dokter\"\n  STR_SECTOID_ENGINEER: \"Sectoid Ingenieur\"\n  STR_SECTOID_LEADER: \"Sectoid Leader\"\n  STR_SECTOID_COMMANDER: \"Sectoid Kommandant\"\n  STR_SNAKEMAN_SOLDIER: \"Schlaangemënsch Zaldot\"\n  STR_SNAKEMAN_NAVIGATOR: \"Schlaangemënsch Navigator\"\n  STR_SNAKEMAN_ENGINEER: \"Schlaangemënsch Ingenieur\"\n  STR_SNAKEMAN_LEADER: \"Schlaangemënsch Anführer\"\n  STR_SNAKEMAN_COMMANDER: \"Schlaangemënsch Kommandant\"\n  STR_MUTON_SOLDIER: \"Muton Zaldot\"\n  STR_MUTON_NAVIGATOR: \"Muton Navigator\"\n  STR_MUTON_ENGINEER: \"Muton Ingenieur\"\n  STR_ETHEREAL_SOLDIER: \"Ethereal Zaldot\"\n  STR_ETHEREAL_LEADER: \"Ethereal Leader\"\n  STR_ETHEREAL_COMMANDER: \"Ethereal Kommandant\"\n  STR_CYBERDISC_TERRORIST: \"Cyberdisc Terrorist\"\n  STR_REAPER_TERRORIST: \"Reaper Terrorist\"\n  STR_CHRYSSALID_TERRORIST: \"Chryssalid Terrorist\"\n  STR_CELATID_TERRORIST: \"Celatid Terrorist\"\n  STR_SILACOID_TERRORIST: \"Silacoid Terrorist\"\n  STR_SECTOPOD_TERRORIST: \"Sectopod Terrorist\"\n  STR_UFO_POWER_SOURCE: \"UFO Kraftquel\"\n  STR_UFO_NAVIGATION: \"UFO Navigatioun\"\n  STR_UFO_CONSTRUCTION: \"UFO Konstruktioun\"\n  STR_ALIEN_FOOD: \"Alien Iessen\"\n  STR_ALIEN_REPRODUCTION: \"Alien Vervielfältegung\"\n  STR_ALIEN_ENTERTAINMENT: \"Alien Entertainment\"\n  STR_ALIEN_SURGERY: \"Alien Operatioun\"\n  STR_EXAMINATION_ROOM: \"Analyseraum\"\n  STR_ALIEN_ALLOYS: \"Alien Legierungen\"\n  STR_ALIEN_HABITAT: \"Alien Wunnraum\"\n  STR_POWER_SUIT: \"Powerkostüm\"\n  STR_FLYING_SUIT: \"Fluchkostüm\"\n  STR_HWP_ROCKETS: \"SWP Rakéiten\"\n  STR_HWP_FUSION_BOMB: \"SWP Fusiounsbomm\"\n  STR_LASER_WEAPONS: \"Laserwaffen\"\n  STR_NEW_FIGHTER_CRAFT: \"Neie Kampffliger\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Neien Fighter-Transporter\"\n  STR_ULTIMATE_CRAFT: \"Ultimative Fliger\"\n  STR_LASER_PISTOL: \"Laser Pistoul\"\n  STR_LASER_RIFLE: \"Laser Gewier\"\n  STR_HEAVY_LASER: \"Schwéiren Laser\"\n  STR_LASER_CANNON: \"Laserkanoun\"\n  STR_PLASMA_CANNON: \"Plasmakanoun\"\n  STR_FUSION_MISSILE: \"Fusiounsrakéit\"\n  STR_LASER_DEFENSE: \"Laserverteidegung\"\n  STR_PLASMA_DEFENSE: \"Plasma Ofwier\"\n  STR_FUSION_DEFENSE: \"Fusiounsverteidegung\"\n  STR_GRAV_SHIELD: \"Grav Schëld\"\n  STR_MIND_SHIELD: \"Gedankeschëld\"\n  STR_PSI_LAB: \"Psi-Labor\"\n  STR_MOTION_SCANNER: \"Bewegungsscanner\"\n  STR_MEDI_KIT: \"1t-Hëllef-Kit\"\n  STR_TANK_CANNON: \"Tank/Kanoun\"\n  STR_TANK_ROCKET_LAUNCHER: \"Panzer/Rakéitewerfer\"\n  STR_TANK_LASER_CANNON: \"Tank/Lasekanoun\"\n  STR_HOVERTANK_PLASMA: \"Hovertank/Plasma\"\n  STR_HOVERTANK_LAUNCHER: \"Hovertank/Rakéitenwerfer\"\n  STR_STINGRAY_LAUNCHER: \"Stingray Rakéitenwerfer\"\n  STR_AVALANCHE_LAUNCHER: \"Avalanche Rakéitenwerfer\"\n  STR_CANNON: \"Kanoun\"\n  STR_FUSION_BALL_LAUNCHER: \"Fusiounsball-Rakéitenwerfer\"\n  STR_PLASMA_BEAM: \"Plasmastrahl\"\n  STR_STINGRAY_MISSILES: \"Stingray Rakéiten\"\n  STR_AVALANCHE_MISSILES: \"Avalanche Rakéiten\"\n  STR_CANNON_ROUNDS_X50: \"Cannon Munitioun(x50)\"\n  STR_FUSION_BALL: \"Fusiouns Ball\"\n  STR_SOLDIER: \"Zaldot\"\n  STR_SCIENTIST: \"Wëssenschaftler\"\n  STR_ENGINEER: \"Ingenieur\"\n  STR_NORTH_AMERICA: \"Nordamerika\"\n  STR_ARCTIC: \"Arktis\"\n  STR_ANTARCTICA: \"Antarktis\"\n  STR_SOUTH_AMERICA: \"Südamerika\"\n  STR_EUROPE: \"Europa\"\n  STR_NORTH_AFRICA: \"Nordafrika\"\n  STR_SOUTHERN_AFRICA: \"Südafrika\"\n  STR_CENTRAL_ASIA: \"Zentral Asien\"\n  STR_SOUTH_EAST_ASIA: \"Süd-Ost Asien\"\n  STR_SIBERIA: \"Siberien\"\n  STR_AUSTRALASIA: \"Australasien\"\n  STR_PACIFIC: \"Pazifik\"\n  STR_NORTH_ATLANTIC: \"Nord Atlantik\"\n  STR_SOUTH_ATLANTIC: \"Süd Atlantik\"\n  STR_INDIAN_OCEAN: \"Indeschen Ozean\"\n  STR_ALIEN_RESEARCH: \"Alien Forschung\"\n  STR_ALIEN_HARVEST: \"Alien Ernt\"\n  STR_ALIEN_ABDUCTION: \"Alien Kidnapping\"\n  STR_ALIEN_INFILTRATION: \"Alien Infiltratioun\"\n  STR_ALIEN_BASE: \"Alien Basis\"\n  STR_ALIEN_TERROR: \"Alien Terror\"\n  STR_ALIEN_RETALIATION: \"Alien Vergeltung\"\n  STR_ALIEN_SUPPLY: \"Alien Wueren\"\n  STR_MAXIMUM_SPEED: \"Maximal Geschwindegkeet\"\n  STR_HYPER_WAVE_DECODER_UC: \"HYPER-WAVE DEKODER\"\n  STR_SKYRANGER: \"SKYRANGER\"\n  STR_LIGHTNING: \"LIGHTNING\"\n  STR_AVENGER: \"AVENGER\"\n  STR_INTERCEPTOR: \"INTERCEPTOR\"\n  STR_FIRESTORM: \"FIRESTORM\"\n  STR_UFO: \"UFO\"\n  STR_STINGRAY: \"STINGRAY\"\n  STR_AVALANCHE: \"AVALANCHE\"\n  STR_CANNON_UC: \"KANOUN\"\n  STR_FUSION_BALL_UC: \"FUSIOUNS BALL\"\n  STR_LASER_CANNON_UC: \"LASER KANOUN\"\n  STR_PLASMA_BEAM_UC: \"PLASMA STRAHL\"\n  STR_DAMAGE_CAPACITY: \"Schuedenskapazitéit\"\n  STR_WEAPON_POWER: \"Waffestäerkt\"\n  STR_WEAPON_RANGE: \"Waffereechwäit\"\n  STR_ACCESS_LIFT: \"Zougangslift\"\n  STR_LABORATORY: \"Labo\"\n  STR_WORKSHOP: \"ATELIER\"\n  STR_SMALL_RADAR_SYSTEM: \"Klénge Radarsystem\"\n  STR_LARGE_RADAR_SYSTEM: \"Grousse Radar\"\n  STR_MISSILE_DEFENSES: \"Rakéitenofwier\"\n  STR_GENERAL_STORES: \"Haptlager\"\n  STR_ALIEN_CONTAINMENT: \"Alien-Klimazell\"\n  STR_LASER_DEFENSES: \"Laserverteidegung\"\n  STR_PLASMA_DEFENSES: \"Plasma Verteidegung\"\n  STR_FUSION_BALL_DEFENSES: \"Fusiounsballverteidegung\"\n  STR_PSIONIC_LABORATORY: \"Psioneschen Labo\"\n  STR_HYPER_WAVE_DECODER: \"Hyper-wave Dekoder\"\n  STR_HANGAR: \"Hangar\"\n  STR_USA: \"USA\"\n  STR_RUSSIA: \"RUSSLAND\"\n  STR_UK: \"ENGLAND\"\n  STR_FRANCE: \"FRANKRÄICH\"\n  STR_GERMANY: \"DÄITSCHLAND\"\n  STR_ITALY: \"ITALIEN\"\n  STR_SPAIN: \"SPUENIEN\"\n  STR_CHINA: \"CHINA\"\n  STR_JAPAN: \"JAPAN\"\n  STR_INDIA: \"INDIEN\"\n  STR_BRAZIL: \"BRASILIEN\"\n  STR_AUSTRALIA: \"AUSTRALIEN\"\n  STR_NIGERIA: \"NIGERIA\"\n  STR_SOUTH_AFRICA: \"SÜDAFRIKA\"\n  STR_EGYPT: \"ÄGYPTEN\"\n  STR_CANADA: \"KANADA\"\n  STR_TANK: \"Panzer\"\n  STR_CIVILIAN: \"Zivilist\"\n  STR_JAN: \"Jan\"\n  STR_FEB: \"Feb\"\n  STR_MAR: \"Mär\"\n  STR_APR: \"Abr\"\n  STR_MAY: \"Mee\"\n  STR_JUN: \"Jun\"\n  STR_JUL: \"Jul\"\n  STR_AUG: \"Aug\"\n  STR_SEP: \"Sep\"\n  STR_OCT: \"Okt\"\n  STR_NOV: \"Nov\"\n  STR_DEC: \"Dez\"\n  STR_INTERNATIONAL_RELATIONS: \"International Relatiounen\"\n  STR_COUNTRY: \"Land\"\n  STR_FUNDING: \"Finanzéirung\"\n  STR_CHANGE: \"Wiesselen\"\n  STR_WEAPON_SYSTEMS: \"WAFFENSYSTEMER\"\n  STR_HWPS: \"SWPen\"\n  STR_DAMAGE_UC_: \"SCHUED>{ALT}{0}\"\n  STR_ACCESS_LIFT_UFOPEDIA: \"Den Zougangslift erlabt et Ekipementer an Personal an d'ënnerierdesch Basis eran an eraus ze transferéiren. Et ass emmer den éischten Deel den an enger neier Basis muss gebaut gin. Den Lift ass eng Schwaachstell fir géigneresch Ugrëff.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"All Wunnraumblock kann bis zu 50 Leit ophuelen. Hei gëtt et e bessen Ennerhalung, Iessen an Schlofméiglechkeeten.\"\n  STR_LABORATORY_UFOPEDIA: \"Bis zu 50 Wëssenschaftler kënnen an engem Labo schaffen. D'Laboën sinn mat der neister Technologie zur Forschung vun Materialien, Biochimie an Kosmologie ausgerüst. Et gëtt e priviligiéirten Zougang zu de beschten Laboën iwwert d'ganz Welt, och déi vum Militär.\"\n  STR_WORKSHOP_UFOPEDIA: \"En Atelier huet all dat néidegt Geschier fir Equipment ze bauen dat op Designer aus den wëssentschaftlechen Labos baséiert. Bis zu 50 Ingenieuren kënnen an engem Atelier schaffen, mee Deeler déi a Produktioun sinn, verbrauchen och Plaz.\"\n  STR_SMALL_RADAR_SYSTEM_UFOPEDIA: \"E klenge Radar huet eng Reechwäit vun 300 nautesche Meilen an ass un e Satellitesystem gekoppelt fir uewerierdesch ze sichen. All System huet eng 10% Chance en mëttelgrousst Objekt all 30 Minuten ze fannen.\"\n  STR_LARGE_RADAR_SYSTEM_UFOPEDIA: \"E grousse Radar huet eng Reechwäit vun 450 nautesche Meilen an ass un e Satellitesystem gekoppelt fir uewerierdesch ze sichen. All System huet eng 20% Chance en mëttelgrousst Objekt all 30 Minuten ze fannen.\"\n  STR_MISSILE_DEFENSES_UFOPEDIA: \"D'Rakéitenofwier schützt d'Basis géint feindlech Ugrräifer déi probéiren bei der Basis ze landen.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"All Equipementer, Waffesystemer, Munitioun, gebuerge Material an Schwéier Waffe Plattform ginn an Lager gesat, Equipementer fir Fligeren am Hangar inclus.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"Liewëg Alien brauchen en speziellt Emfeld fir ze iwwerliewen. D'Klimazell kann bis zu 10 Alien an zouenen Zellen ophuelen.\"\n  STR_LASER_DEFENSES_UFOPEDIA: \"D'Laserofwier beschützt d'Basis géint feindlech Ugräifer.\"\n  STR_PLASMA_DEFENSES_UFOPEDIA: \"Plasmastrahl Verteidegung bidd en starken an effizienten Schutz géint Ugrëff vun feindlechen Fliger.\"\n  STR_FUSION_BALL_DEFENSES_UFOPEDIA: \"Fusiouns-Rakéiten sinn déi beschten Verteidegung géint Alien Attacken. Dës Rakéiten kreéiren eng anti-materiell Implosioun déi alles an engem spezifeschen Radius zerstéiert.\"\n  STR_GRAV_SHIELD_UFOPEDIA: \"De Gravitatiounsschëld h!lt géigneresch Fliger laang genuch dovun of nierft der Basis ze landen bis d'Verteidegungssystem erem schéisse kënnen. Praktesch gesinn, verduebelt dat d'Effektivitéit vun all Verteidegungssystem an der Basis.\"\n  STR_MIND_SHIELD_UFOPEDIA: \"Well d'Alien Fliger Gehierstréim vun den Menschen entdecken kann, ass déi bescht Verteidegung d'Ofschiermen vun den Gehierstréim vun der Basis. Dës Ariichtung reduzéiert drastesch d'Gefor vun enger Entdeckung durch Alien Fliger.\"\n  STR_PSIONIC_LABORATORY_UFOPEDIA: \"De psychesche Labo kann den Zaldoten hier psionesch Basis manipuléiren an hinnen den néidegen Training ginn fir hier psionesch Fähegkeeten ze verbessern.\"\n  STR_HYPER_WAVE_DECODER_UFOPEDIA: \"Alien Kommunikatioun beroud op supra-dimensionalen Wellen déi quasi direkt ukommen. D'Decodereenheet fänkt UFO Iwwerdroungen op an decodéiert d'Informatioun. Dëst weist den Typ vun UFO, d'Alien Rass an den Typ vun Aktivitéit.\"\n  STR_HANGAR_UFOPEDIA: \"An all Hangar ass Plaz fir ee Fliger. Hei kréien d'Fligeren hier Maintenance, Kraftstoff a ginn och reparéiert. All Fliger den zu enger Basis gehéiert brauch e fräien Hangar den net vun engem anere Fliger ka genotzt ginn, och wann de Fliger grad ennerwee ass.\"\n  STR_PISTOL_UFOPEDIA: \"D'Standard X-Com-Pistoul ass eng staark semiautomatesch Waff mat 12 Schoss Kapazitéit.\"\n  STR_RIFLE_UFOPEDIA: \"Dest héigakkurat Snipergewier huet e lasergestützt Viséier and notzt 6.7mm Munitioun an engem 20-Schoss Magasinn.\"\n  STR_HEAVY_CANNON_UFOPEDIA: \"D'schwéiert Gefier ass eng zerstéieresch mee schwéierfälleg Waff. Seng Vilfalt kennt doduerch dass se dräi Aarte vu Munitioun kann notzen: panzerbriechend, entzündlech an héich explosiv.\"\n  STR_AUTO_CANNON_UFOPEDIA: \"D'Auto-Kanoun kombinéiert d'Villsäitegkeet an Stäerkt vun enger schwéirer Kanoun mat enger séierer Schossrat.\"\n  STR_ROCKET_LAUNCHER_UFOPEDIA: \"De Rakéitewerfer ass e lasergesteierte System den dräi verschidden gréissten Rakéiten kann verschéissen.\"\n  STR_LASER_PISTOL_UFOPEDIA: \"D'Laserpistoul ass eng effektiv Implementatioun vun neier Technologie. Se huet d'Bequemlechkeet vun enger Pistoul an kann méi séier an präzis schéissen.\"\n  STR_LASER_RIFLE_UFOPEDIA: \"D'Lasergewier ass eng méi staark a präzis Versioun vun dem Pistoulendesign.\"\n  STR_HEAVY_LASER_UFOPEDIA: \"Den schwéiren Laser as schwéierfälleg, mee extrem effektiv.\"\n  STR_GRENADE_UFOPEDIA: \"D'Standardausféierung vun der Granat huet e präzisen an sophistiquéierten Timer fir eng genau Kontroll.\"\n  STR_SMOKE_GRENADE_UFOPEDIA: \"Dampgranaten sinn gutt fir Deckung an enger Kampfsituatioun ze ginn. Mat Bedenken benotzen, well den Géigner kann dovun och profitéiren.\"\n  STR_PROXIMITY_GRENADE_UFOPEDIA: \"Eng Proximitéitsgranat ka wéi eng normal Granat geworf gi mee gëtt duerch Beweegungen an hirer Géigend ausgeléist. Kënnen a Suergfalt gëtt gebraucht fir se uerdentlech ze benotzen.\"\n  STR_HIGH_EXPLOSIVE_UFOPEDIA: \"Dësen Sprengstoff soll nëmmen fir Zerstéirung benotzt ginn. All Personal soll sech wait ewech halen.\"\n  STR_MOTION_SCANNER_UFOPEDIA: \"Dësen sofistikéierten Apparat benotzt eng Rei Detektoren an komplex Computer Algorithmen fir Bewegungen vun géignereschen Eenheeten ze identifizéiren. Allerdéngs brauch een e bëssen Training fir en effektiv ze benotzen. Klick op den Bewegungsscanner um takteschen Schierm. Wiel 'Scanner benotzen' aus dem Menu. De Scanner weist en Feil an der Mëtt wou den Zaldot hikuckt (uewen ass Norden). D'Punkten déi blénken weisen Eenheeten un déi séch kierzlech bewegt hunn. Grouss Eenheeten, oder séier Eenheeten, sinn méi déck Punkten. Statësch Eenheeten ginn net erkannt.\"\n  STR_MEDI_KIT_UFOPEDIA: \"Den 1t-Hëllef-Kit huet Verbänn, Medikamenter a Stimulanten. Fir en ze benotzen, muss en a Richtung verwondten Zaldot gedréint sinn. Wann den Zaldot betäubt ass, muss een op him stoen. Klick d'1t-Hëllef-Kit-Icon an wiel '1t-Hëllef-Kit benotzen' am Menü.{NEWLINE}HEELEN> Roud Kierperdeeler weisen fatal Wonnen op. Klick op e Kierperdeel de verwond ass. Klick dann den 'Heelen'-Kneppchen. Eng fatal Wonn an e bëssen Liewenspunkten ginn geheelt.{NEWLINE}STIMULANT>Fir Energie ze restoréiren an e um Buedem leienden (bewosstlosen) Zaldot rem op d'Been ze bréngen. Fir dëst ze man, muss een direkt iwwert dem Kierper stoen.{NEWLINE}MEDIKAMENT>Dëst erhéigt d'Moral vun engem verwondten Zaldot bis op e Wert vun verluerenen Liewenspunkten.\"\n  STR_PSI_AMP_UFOPEDIA: \"D'Psi-amp ka just vun Zaldote mat psionësche Fähegkeete genotzt ginn. Klick während dem Kampf op den Psi-amp, wiel d'Typ vun der Attaque a wiel eng Zileenheet mam Kurseur aus. Et gëtt zwou Aarte vun psionëschen Attaquen:{NEWLINE}EENHEET PANIKEIEREN>Wann des Attaque geklappt huet huet. geet dem Zil seng Moral erof an et ka panikéieren.{NEWLINE}GEDANKEKONTROLL> Wann dëst geklappt huet, kriss du direkt d'Kontroll iwwert d'géigneresch Eenheet wéi wann et deng eege wier. Dësen Typ vun Attaque ass méi schwéier durchzeféireren.\"\n  STR_STUN_ROD_UFOPEDIA: \"Dëst Gerät kann just am Nahkampf benotzt ginn, mee betäubt en liewegt Wiesen mat Elektroschocken ouni et emzebréngen.\"\n  STR_MIND_PROBE_UFOPEDIA: \"D'Gehiersond ass en Alienkommunikatiounsgerät dat benotzt gëtt fir Informatiounen direkt aus Gehierstralen ze liesen. X-Com Eenheeten kënnen et am Kampf benotzen fir den Alien hier Characteristiken unzeweisen. Klick op d'Gehiersond an d'benotzen' Optioun. Klick dann op en Alien mat dem Cursor.\"\n  STR_PLASMA_PISTOL_UFOPEDIA: \"Plasmapistoulen sinn déiglech Alienwaffen baséirend op beschleunegte Partikelen aus engem präzisen Antigravitatiounsfeld.\"\n  STR_PLASMA_RIFLE_UFOPEDIA: \"Dëst ass eng zerstéierësch staark Waff baséiernt op beschleunegte Partikel aus engem präzisen Antigravitatiounsfeld.\"\n  STR_HEAVY_PLASMA_UFOPEDIA: \"Dëst ass eng zerstéierësch staark Waff baséiernt op beschleunegte Partikel aus engem präzisen Antigravitatiounsfeld.\"\n  STR_BLASTER_LAUNCHER_UFOPEDIA: \"Dëst ass en vun Alien gebauten Rakéitenwerfer den staark 'Blasterbommen' verschéisse kann. Wann een d'Waff benotzt fir ze schéissen, gi 'Weepunkter' gesat dem d'Bomm wäert nogoen. Wann genuch Weepunkter gesat goufen, klick op den Spezialicon fir d'Bomm ofzeschéissen.\"\n  STR_SMALL_LAUNCHER_UFOPEDIA: \"E klénge Granatwerfer fir Betäubungsgranaten. Gutt fir lieweg Alien ze fänken.\"\n  STR_ALIEN_GRENADE_UFOPEDIA: \"Dëst Gerät funktionéiert wéi eng normal Granat mat der Ausnam, dass se méi staark ass.\"\n  STR_SMALL_SCOUT: \"KLENGE SCOUT\"\n  STR_MEDIUM_SCOUT: \"Mëttleren Scout\"\n  STR_LARGE_SCOUT: \"Groussen Scout\"\n  STR_HARVESTER: \"Ernter\"\n  STR_ABDUCTOR: \"Entféierer\"\n  STR_TERROR_SHIP: \"Terrorschëff\"\n  STR_BATTLESHIP: \"Kampfschëff\"\n  STR_SUPPLY_SHIP: \"Liwwerschëff\"\n  STR_RATING: \"RATING> {0}\"\n  STR_RATING_TERRIBLE: \"TERRIBEL!\"\n  STR_RATING_POOR: \"SCHWAACH!\"\n  STR_RATING_OK: \"OK\"\n  STR_RATING_GOOD: \"GUTT!\"\n  STR_RATING_EXCELLENT: \"EXZELLENT!\"\n  STR_SCORE: \"SCORE\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"X-COM PROJET RAPPORT VUM MOUNT\"\n  STR_MONTH: \"Mount> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"De Rot vun den finanzéirenden Natiounen ass am groussen Ganzen zefridden mat déngem Fortschrétt.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"De Rot vun den finanzéirenden Natiounen ass zefridden mat denger Leeschtung. Maach weider esou.\"\n  STR_COUNCIL_IS_DISSATISFIED: \"De Rot vun den finanzéirenden Natiounen ass net zefridden mat denger Leeschtung. Du muss d'Effektivitéit géint d'Alienbedrohung verbesseren oder de Projet riskéiert op en Enn ze goen.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"Du hues et net geschafft d'Alieninvasioun ze bekämpfen an de Rot vun den finanzéirenden Natiounen huet leider entscheed de Projet ofzeschléissen. All Natioun soll mam Problem emgoen wéi se wëllen. Mir kënnen just hoffen, dass mier iergendwéi mat dësen Feinden eenz ginn an d'Bevölkerung d'Alien bewältegt.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} sinn deels zefridde mat denger Aarbecht a bereet méi Gelder ze finanzéieren.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} ass besonneg frou mat dem Fortschrëtt géint d'Andréngen vun den Alien an hunn décidéiert d'Gelder ze erhéigen.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} an {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} ass net zefridden wéi mat den Alienaktivitéiten an hierer Emgéigend gehandhabt gëtt an huet décidéiert de finanziellen Engagement ze reduzéiren.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} ass onzefridden mat denger Fähegkeet sech géint d'Alien an hierem Territoire durchzesetzen an hunn decidéiert d'Finanzéirung ze reduzéiren.\"\n  STR_KNOTS: \"{0} Kniet\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} huet en geheimen Pakt mat enger onbekannten Alienmuecht gemet an ass vum Projet zeréckgetrueden.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} huet en geheimen Pakt mat enger onbekannter Alienmuecht gemet an ass vum Projet zeréckgetrueden.\"\n  STR_MONTHLY_RATING: \"Rating vum Mount> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Finanziell Ännerung> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"De finanziellen Rot ass net zefridden mat dénger Finanzlag. Du muss d'Scholden ennert $1 Mio. bréngen oder den Projet gëtt ofgeblosen.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"HYPER-WELLEN TRANSMISSIOUNEN SINN ENTSCHLËSSELT\"\n  STR_CRAFT_TYPE: \"FLIGER TYP\"\n  STR_RACE: \"RASS\"\n  STR_MISSION: \"MISSIOUN\"\n  STR_ZONE: \"ZON\"\n  STR_ALLOCATE_RESEARCH: \"Forschung ufänken\"\n  STR_ALLOCATE_MANUFACTURE: \"Produktioun zoudeelen\"\n  STR_NEW_YORK: \"New York\"\n  STR_WASHINGTON: \"Washington\"\n  STR_LOS_ANGELES: \"Los Angeles\"\n  STR_MONTREAL: \"Montreal\"\n  STR_HAVANA: \"Havana\"\n  STR_MEXICO_CITY: \"Mexico City\"\n  STR_CHICAGO: \"Chicago\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_DALLAS: \"Dallas\"\n  STR_BRASILIA: \"Brasilia\"\n  STR_BOGOTA: \"Bogota\"\n  STR_BUENOS_AIRES: \"Buenos Aires\"\n  STR_SANTIAGO: \"Santiago\"\n  STR_RIO_DE_JANEIRO: \"Rio De Janeiro\"\n  STR_LIMA: \"Lima\"\n  STR_CARACAS: \"Caracas\"\n  STR_LONDON: \"London\"\n  STR_PARIS: \"Paris\"\n  STR_BERLIN: \"Berlin\"\n  STR_MOSCOW: \"Moskau\"\n  STR_ROME: \"Roum\"\n  STR_MADRID: \"Madrid\"\n  STR_BUDAPEST: \"Budapest\"\n  STR_LAGOS: \"Lagos\"\n  STR_CAIRO: \"Kairo\"\n  STR_CASABLANCA: \"Casablanca\"\n  STR_PRETORIA: \"Pretoria\"\n  STR_NAIROBI: \"Nairobi\"\n  STR_CAPE_TOWN: \"Kapstadt\"\n  STR_KINSHASA: \"Kinschasa\"\n  STR_ANKARA: \"Ankara\"\n  STR_DELHI: \"Delhi\"\n  STR_KARACHI: \"Karachi\"\n  STR_BAGHDAD: \"Baghdad\"\n  STR_TEHRAN: \"Teheran\"\n  STR_BOMBAY: \"Bombay\"\n  STR_CALCUTTA: \"Kalkutta\"\n  STR_TOKYO: \"Tokyo\"\n  STR_BEIJING: \"Peking\"\n  STR_BANGKOK: \"Bangkok\"\n  STR_MANILA: \"Manila\"\n  STR_SEOUL: \"Seoul\"\n  STR_SINGAPORE: \"Singapor\"\n  STR_JAKARTA: \"Jakarta\"\n  STR_SHANGHAI: \"Shanghai\"\n  STR_HONG_KONG: \"Hong Kong\"\n  STR_NOVOSIBIRSK: \"Novosibirsk\"\n  STR_CANBERRA: \"Canberra\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_MELBOURNE: \"Melbourne\"\n  STR_PERTH: \"Perth\"\n  STR_PSI_TRAINING: \"Psi Training\"\n  STR_PSIONIC_TRAINING: \"PSIONESCHEN TRAINING\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Reschtkapazitéit am Psi-Labo> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"Psionesch{NEWLINE}Stärkt\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"Psionesch Fähegkeet{NEWLINE}/Verbesserung\"\n  STR_PSI_AMP: \"Psi-Verstärkung\"\n  STR_IN_TRAINING: \"Am{NEWLINE}Training?\"\n  STR_TARGETTED_BY: \"AM ZIL VUN:\"\n  STR_WEAPONS_CREW_HWPS: \"WAFFEN/{NEWLINE}CREW/SWPs\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"huet kaum nach Bensin,{NEWLINE}flitt zeréck op d'Basis\"\n  STR_SOLDIER_LIST: \"Zaldotelëscht\"\n  STR_RANK_: \"RANG> {ALT}{0}\"\n  STR_MISSIONS: \"MISSIOUNEN> {ALT}{0}\"\n  STR_KILLS: \"KILLS> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"WONNENHEELUNG> {ALT}{0}\"\n  STR_TIME_UNITS: \"ZÄITEENHEETEN\"\n  STR_STAMINA: \"AUSDAUER\"\n  STR_HEALTH: \"LIEWEN\"\n  STR_BRAVERY: \"MUDD\"\n  STR_REACTIONS: \"REAKTIOUNEN\"\n  STR_FIRING_ACCURACY: \"SCHOSSGENAUEGKEET\"\n  STR_THROWING_ACCURACY: \"WORFGENAUEGKEET\"\n  STR_STRENGTH: \"STÄERKT\"\n  STR_PSIONIC_STRENGTH: \"PSIONESCH STÄERKT\"\n  STR_PSIONIC_SKILL: \"PSIONESCH FÄHEGKEET\"\n  STR_NEW_RANK: \"NEIEN RANG\"\n  STR_PROMOTIONS: \"Promotiounen\"\n  STR_SOLDIERS_UC: \"ZALDOTEN\"\n  STR_TANK_CANNON_UFOPEDIA: \"Automatesch Schwéier Waffe Plattforme goufen designt fir der X-COM Ekipp ze hëllefen. D'Kombinatioun aus héiger Schosskraft an staark Panzerung sinn ideal fir am openen Terrain ze kämpfen. Kontrolléier, dass emmer genuch Munitioun am Lager ass fir d'SWP nei ze lueden. Se ginn automatesch gelueden wann se enger Ekipp zougewise ginn.\"\n  STR_TANK_ROCKET_LAUNCHER_UFOPEDIA: \"Dës automesch Schwéier Waffe Plattform as mat starken Rakéiten equipéiert. Dëst ass verheerend fir all ausserierdësch Liewensform. Stell sëcher, dass am Lager genuch SWP Rakéiten sinn.\"\n  STR_TANK_LASER_CANNON_UFOPEDIA: \"Laserwaffen sinn sënnvoll Equipementer fir SWPen. Se kombinéiren staark Power ouni mussen mat Munitioun gelueden ze ginn.\"\n  STR_HOVERTANK_PLASMA_UFOPEDIA: \"Wéint der Alien Technologie huet den SWP nei Funktiounen kritt. D'verbessert Beweglechkeet durch d'Schwiewen an der Loft an Plasma Strahlen sinn eng déidlech Kombinatioun.\"\n  STR_HOVERTANK_LAUNCHER_UFOPEDIA: \"Dësen Hovertank huet e Fusiounsball-Rakéitenwerfer den fir eng immens Zerstéirung suergt. Mat Virsiicht ze benotzen. D'Fusiounsbäll musse gebaut ginn fir den SWP voll ze lueden. E Fusiounsball ass eng intelligent guidéiert Waff. Fir de Fusiounsball ofzeschéissen muss Weepunkter erstallt ginn an dann d'Icon gedréckt fir de Fusiounsball ofzeschéissen.\"\n  STR_HEAVY_PLASMA_CLIP_UFOPEDIA: \"Dëst klengt Gerät gëtt als Munitioun fir eng Schwéier Plasma Waff benotzt. Et enthält eng kleng Quantitéit Elerium.\"\n  STR_PLASMA_RIFLE_CLIP_UFOPEDIA: \"Dëst kléngt Stéck gëtt als Energiequell fir en Plasmagewier benotzt - eng mëttelstaark Alienwaff. Beinhalt eng kléng Quantitéit Elerium.\"\n  STR_PLASMA_PISTOL_CLIP_UFOPEDIA: \"Kraaftquell fir eng kleng Alien Plasma Pistoul. Geet mat Elerium - d'Energiequell vun den Alien.\"\n  STR_STUN_BOMB_UFOPEDIA: \"D'Betäubungsgranat gëtt benotzt fir lieweg Human Spezien ze fénken, mee och fir déi meescht aner Alien-Rassen. Se gëtt vun engem kléngen Rakéitenwerfer ofgeschoss.\"\n  STR_ALIEN_RESEARCH_UFOPEDIA: \"D'Alien Recherchemissioun huet als Zweck Datë vun der Äerd a sengen Awunner ze kréien. Kleng Fligere gi meeschtens benotzt an landen ab und zu a wüüstenaartege Gebidder. Des Alienaktivitéit ass déi klengste Gefor fir d'X-Com, Regierungen an d'Mënschen.\"\n  STR_ALIEN_HARVEST_UFOPEDIA: \"D'Alien hu vill Interêt un der Fauna vun der Äerd. Déiere gi geheim entfouert, a mat feelenden Organer zeréck bruet. Verstümmelungen u Béischte sinn do ze fanne wou och UFOe gesicht goufen. Des Alienaktivitéiert mécht de Regierunge vill Kappzerbrieches an den Awunner vill Angscht. Des Aktivitéit gëtt haaptsächlech a ländleche Géigende beobacht. D'Theorie hannert dem 'Alien farmen' seet dass d'Alien deemools de Planéit mat Flora a Fauna 'besomt' hunn an sech elo hier Ernt zeréckhuelen.\"\n  STR_ALIEN_ABDUCTION_UFOPEDIA: \"Dëst ass déi hannerlëschtegsten Form vun Alien Aktivitéit. Et gëtt iwwerall vun den Entféirungen durch Alien geschwat, trotz dem Läschen vun dem Verhalt vun den Opfer. Entféierter schwetzen dovun, wéi mat hinnen erniddregent physikalesch Experimenter durchgefouert goufen, inklusiv d'Schwängeren vun Alien Fetusen an bizarren geneteschen Experimenter. Dën Sënn hannert dem Ganzen schéngt a Verbindung mat geneteschen Mutatiounen an Manipulatiounen vun den Alien hierem egenen geneteschen Material ze stoen. Dës Aktivitéit léist héchsten Alarm aus, an kënnt an bevölkerten Géigenden an Stied fir.\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"Regierunge kënne vun Alienagente déi mënschlech ausgesinn infiltréiert ginn. Des ka Kontakter op héchstem politeschen Niveau tëschent Alien an Regierungen erméiglechen. Den Héichpunkt vun där Aktivitéit ass charakteriséiert vun erhéichter UFO-Aktivitéit an den Haptstied. D'Alien probéieren a Pakt mat de Regierungen ze schléissen am Echange mat hirer iwwerleeëner Technologie. Am Géigesaz hënneren d'Regierungen se net un hirer Aktivitéit. Des Alienmissiounen sinn déi héchste Gefor fir d'X-Com. Wann eng Regierung e Pakt gemet huet, finanzéiert se net weider.\"\n  STR_ALIEN_BASE_UFOPEDIA: \"Alien baue geheim ënnerierdesch Basen an ofgeleeëne Géigenden. No e puer Erkundungsflich, erhéicht sech d'UFO-Aktivitéit an der Regioun wou d'Basis gebaut gëtt. Des Basen si bekannt dofir fir speziell Laboen ze hunn wou entfouert Mënschen ënnersicht ginn, an aner Lager fir d'Aktivitéit an der Regioun ze ënnerstëtzen. D'Präsenz vun Alienbasen generéiert eng Rei vun Alienaktivitéiten ouni UFOpräsenz. Fir esou eng Basis ze fannen, muss een X-Com-Fliger an der Regioun fir e puer Stonne patrulléieren fir eng Chance ze hunn se ze fannen.\"\n  STR_ALIEN_TERROR_UFOPEDIA: \"Wann d'Alien eng Stad terroriséieren, setzen se eng Spezialeenhet mat staarker Kraft an. Zivilisten sinn direkt bedrot an d'Regierung evakuéiert déi ganz Regioun. D'Haptzil hannert dëser Aktivitéit ass fir souvill wéi méiglech Hysterie ze generéiren sou dass d'Regierungen den X-Com-Projet menacéieren.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"Wann XCom Intercepter halbwegs en UFO ofgeschoss hunn, kënnen d'Alien zréckugraifen. Dës kann an engem direkten Ugreff op eng XCom Basis enden. Allerdéngs mussen d'Alien dofir eng XCom Basis fannen, fir se kënnen unzegräifen, wann den Alienfliger allerdéngs ofgewiert gëtt, gëtt et kaum Gefor fir en Ugrëff.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"Wa bis eng Alienbasis gebaut gouf, gëtt se regelméisseg vun engem Liwwerschëff beliwwert. Wann esou ee Fliger beim Landen entdeckt gëtt, ass zimlech sécher eng Alienbasis an der Géigend.\"\n  STR_SMALL_SCOUT_UFOPEDIA: \"Dëse Minifliger gëtt primär fir Opklärung a Forschung agesat. Normalerweis flitt et firun gréissere Fligere beim Start vun enger Alienmissioun\"\n  STR_MEDIUM_SCOUT_UFOPEDIA: \"E mëttelgroussen Opklärer den keng grouss Bedrohung fir d'Äerd. Normalerweis kënnt dono nach en méi grousst Schëff ugeflunn.\"\n  STR_LARGE_SCOUT_UFOPEDIA: \"De gréissten Alienopklärer a Standardschëff wat an all Typ vun Alienmissiounen an den Asaz kënnt.\"\n  STR_HARVESTER_UFOPEDIA: \"Den Ernter huet eng Klappdier a senger Basis an ass ekipéiert mat engem Kran fir Béischten an aner Déieren an d'Luet ze hiewen. Lasercutter gi benotzt fir dat gewënschte Material erauszehuelen an de Kadaver gëtt zeréck op de Buedem fale gelooss. En huet och Lagerplaz fir Kierperdeeler.\"\n  STR_ABDUCTOR_UFOPEDIA: \"Dëst Schëff ass mat engem Ënnersichungsraum ekipéiert fir schrecklech Experimenter mat Mënschen ze maachen. D'Opfer gëtt mat telepathescher Kraaft geläämt mee bleift bei Bewosstsi wärend et um Operatiounsdësch läit.\"\n  STR_TERROR_SHIP_UFOPEDIA: \"D'Terrorschëff huet eng Klimazell fir grouss Alien Terrorwaffen an Kreaturen. Et get benotzt fir dës Alien Terroristen an bevölkert Deeler ze transportéiren.\"\n  STR_BATTLESHIP_UFOPEDIA: \"D'Schlachtschëff ass de gréissten an stäerksten UFO. Et ass normalerweis de primären Alien Missiouns Fliger, equipéiert mat starken Waffen a villen Crew Memberen.\"\n  STR_SUPPLY_SHIP_UFOPEDIA: \"D'Liwwerschëff gëtt agesat fir Alienbasen ze bauen oder déi ze beliwweren. Et huet Alieniessenscontaineren an Reproduktiounskummeren u Bord.\"\n  STR_DISMANTLE: \"Demontéiren\"\n  STR_FACILITY_IN_USE: \"ARIICHTUNG A GEBRAUCH\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"KANN ARIICHTUNG NET OFRAPPEN!{SMALLLINE}All Basisariichtung muss eng Verbindung mam Zougangslift hunn.\"\n  STR_TRANSFER_ITEMS_TO: \"Géigestänn op {0} transferéiren\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"KENG PLAZ FIR ALIENTRANSFER!{SMALLLINE}Lieweg Alien brauchen eng Klimazell fir kënnen ze iwwerliewen.\"\n  STR_AMOUNT_AT_DESTINATION: \"UNZUEL OP DER{NEWLINE}DESTINATIOUN\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"Alien stierwt well keng Alienklimazell do ass\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"KENG FRAI RAIM!{SMALLLINE}D'Zilbasis huet net genuch fräi Plaz an de Wunnräim fir d'Crew vun dem Fliger.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"NET GENUCH LAGERPLAZ!{SMALLLINE}D'Zilbasis huet genuch fräi Lagerplaz fir d'Equipment am Fliger.\"\n  STR_ITEMS_ARRIVING: \"Deeler kommen un\"\n  STR_DESTINATION_UC: \"ZIL\"\n  STR_PISTOL: \"Pistoul\"\n  STR_PISTOL_CLIP: \"Pistoule Munitioun\"\n  STR_RIFLE: \"Maschinnegewier\"\n  STR_RIFLE_CLIP: \"Maschinnegewiermunitioun\"\n  STR_HEAVY_CANNON: \"Schwéiert Gewier\"\n  STR_HC_AP_AMMO: \"HC-AP Munitioun\"\n  STR_HC_HE_AMMO: \"HC-HE Munitioun\"\n  STR_HC_I_AMMO: \"HC-I Munitioun\"\n  STR_AUTO_CANNON: \"Automatëscht Gewier\"\n  STR_AC_AP_AMMO: \"AC-AP Munitioun\"\n  STR_AC_HE_AMMO: \"AC-HE Munitioun\"\n  STR_AC_I_AMMO: \"AC-I Munitioun\"\n  STR_ROCKET_LAUNCHER: \"Rakéitewerfer\"\n  STR_SMALL_ROCKET: \"Kléng Rakéit\"\n  STR_LARGE_ROCKET: \"Grouss Rakéit\"\n  STR_INCENDIARY_ROCKET: \"Entzündlech Rakéit\"\n  STR_GRENADE: \"Granat\"\n  STR_SMOKE_GRENADE: \"Damp Granat\"\n  STR_PROXIMITY_GRENADE: \"Proximitéitsgranat\"\n  STR_HIGH_EXPLOSIVE: \"Héigexplosiv\"\n  STR_STUN_ROD: \"Betäubungslanz\"\n  STR_HEAVY_PLASMA: \"Schwéier Plasma\"\n  STR_HEAVY_PLASMA_CLIP: \"Schwéieren Plasma Clip\"\n  STR_PLASMA_RIFLE: \"Plasma Gewier\"\n  STR_PLASMA_RIFLE_CLIP: \"Plasma Gewiermuni\"\n  STR_PLASMA_PISTOL: \"Plasmapistoul\"\n  STR_PLASMA_PISTOL_CLIP: \"Plasmapistoul Munitioun\"\n  STR_BLASTER_LAUNCHER: \"Blaster Rakéitenwerfer\"\n  STR_BLASTER_BOMB: \"Blasterbomm\"\n  STR_SMALL_LAUNCHER: \"Klénge Rakéitenwerfer\"\n  STR_STUN_BOMB: \"Beäubungsgranat\"\n  STR_ALIEN_GRENADE: \"Aliengranat\"\n  STR_ELERIUM_115: \"Elerium-115\"\n  STR_MIND_PROBE: \"Gehiersond\"\n  STR_SECTOID_CORPSE: \"Sectoidekierper\"\n  STR_SNAKEMAN_CORPSE: \"Schlaangemënsch Kierper\"\n  STR_ETHEREAL_CORPSE: \"Ethereal Kierper\"\n  STR_MUTON_CORPSE: \"Muton Kierper\"\n  STR_FLOATER_CORPSE: \"Floater Kierper\"\n  STR_CELATID_CORPSE: \"Celatid Kierper\"\n  STR_SILACOID_CORPSE: \"Silacoidekierper\"\n  STR_CHRYSSALID_CORPSE: \"Chryssalidekierper\"\n  STR_REAPER_CORPSE: \"Reaper Kierper\"\n  STR_SECTOPOD_CORPSE: \"Sectopodkierper\"\n  STR_CYBERDISC_CORPSE: \"Cyberdisc Kierper\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"Net genuch Munitioun fir SWP ze lueden.{SMALLLINE}All SWP brauch {0} {1}.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Net genuch Equipement fir d'Ekipp voll ze equipéiren\"\n  STR_MARS_CYDONIA_LANDING: \"Mars: Cydonia Landung\"\n  STR_MARS_CYDONIA_LANDING_BRIEFING: \"Dain Avenger ass an der Regioun vun Cydonia um Mars geland. Eisen Informatiounen no, huet eng vun den Pyramidenkontruktiounen en gréngen Zougangslift den zu engem ënenrierdeschen Komplex leed. Soubal all d'Zaldoten an dem Liftareal stinn, klick op den 'Missioun Ofbriechen' Icon fir an den nächsten Level ze gelaangen.\"\n  STR_MARS_THE_FINAL_ASSAULT: \"Mars: Déi lescht Schlacht\"\n  STR_MARS_THE_FINAL_ASSAULT_BRIEFING: \"De Pyramidelift féiert déi beschten Zaldoten déi ënnert d'Aerd erof. Se kommen an engem grousse Komplex vun Tunnelen a Räim un. Iergendwou an dem Labyrinth ass d'Aliengehier verstoppt. Et muss zerstéiert ginn wann d'Aerd soll aus enger Aliensklaverei gerett ginn.{NEWLINE}{NEWLINE}Vill Gléck!\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Du muss en{NEWLINE}{0}{NEWLINE} erforschen befier en {NEWLINE}{1}{NEWLINE}erforscht ka ginn\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"D'Alien hunn déi onverteidegt Basis {0} zerstéiert.\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"X-Com Agenten hunn eng Alienbasis zu {0} fonnt\"\n  STR_STANDOFF: \"PATTSITUATIOUN\"\n  STR_CAUTIOUS_ATTACK: \"VIRSIICHTEG ATTACK\"\n  STR_STANDARD_ATTACK: \"STANDARDATTACK\"\n  STR_AGGRESSIVE_ATTACK: \"AGGRESSIV ATTACK\"\n  STR_DISENGAGING: \"ZERÉCKZÉIEN\"\n  STR_UFO_HIT: \"UFO GETRAFF!\"\n  STR_UFO_CRASH_LANDS: \"UFO STIERZT OF!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Nëmmen a Pattsituatioun minimiséieren\"\n  STR_UFO_RETURN_FIRE: \"UFO SCHEISST ZERÉCK!\"\n  STR_INTERCEPTOR_DAMAGED: \">>> INTERCEPTOR BESCHIEDEGT <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> INTERCEPTOR ZERSTÉIERT <<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"UFO FLITT DEM INTERCEPTOR FORT!\"\n  STR_ALIENS_TERRORISE: \"ALIEN TERRORISEIEREN\"\n  STR_LONG_RANGE_DETECTION: \"Laangstreckeradar\"\n  STR_STORES_UC: \"LAGER\"\n  STR_DIFFICULTY_LEVEL: \"Schwierëgkeetsgrad\"\n  STR_INTERCEPT: \"OFFENKEN\"\n  STR_BASES: \"BASEN\"\n  STR_GRAPHS: \"GRAFIKEN\"\n  STR_UFOPAEDIA_UC: \"UFOPEDIA\"\n  STR_OPTIONS_UC: \"OPTIOUNEN\"\n  STR_FUNDING_UC: \"FINANZÉIRUNG\"\n  STR_5_SECONDS: \"5 Sek\"\n  STR_1_MINUTE: \"1 Min\"\n  STR_5_MINUTES: \"5 Mins\"\n  STR_30_MINUTES: \"30 Mins\"\n  STR_1_HOUR: \"1 Stonn\"\n  STR_1_DAY: \"1 Dag\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"X-Com Performance Tabell\"\n  STR_ENTER_NAME: \"Numm aginn\"\n  STR_PERFORMANCE_RATING: \"Performance Rating\"\n  STR_VICTORY_DATE: \"Triumphdatum\"\n  STR_ELECTRO_FLARE: \"Elektro-Liichtsignal\"\n  STR_ELECTRO_FLARE_UFOPEDIA: \"Dës kompakt Gerät produzéiert en hellt Liicht wann et geworf gëtt. Dës weist géigneresch Eenheeten am Emkrees vun der Luut während den Nuetsmissiounen.\"\n  STR_MONTHLY_COSTS: \"Käschte pro Mount\"\n  STR_CRAFT_RENTAL: \"Fliger Leasing\"\n  STR_SALARIES: \"Paien\"\n  STR_BASE_MAINTENANCE: \"Basisennerhalt\"\n  STR_COST_PER_UNIT: \"Käschten pro Eenheet\"\n  STR_QUANTITY: \"Unzuel\"\n  STR_TOTAL: \"Total\"\n  STR_IN_PSIONIC_TRAINING: \"Psionescht Fähegkeet{NEWLINE}/Verbesserung\"\n  STR_BLASTER_BOMB_UFOPEDIA: \"Dëst Gerät ass eng héigexplosiv Rakéit déi en intelligenten Guidéiersystem huet. Se gëtt vun engem Blaster Rakéitenwerfer ofgeschoss.\"\n  STR_FRONT_ARMOR: \"Broschtpanzer\"\n  STR_LEFT_ARMOR: \"Panzerung lénks\"\n  STR_RIGHT_ARMOR: \"Panzerung riets\"\n  STR_REAR_ARMOR: \"Réckerüstung\"\n  STR_UNDER_ARMOR: \"Enner Rüstung\"\n  STR_ROUNDS: \"Ronnen\"\n  STR_UNIT: \"EENHEET> {0}\"\n  STR_ENERGY: \"ENERGIE\"\n  STR_MORALE: \"MORAL\"\n  STR_ARMOR_: \"PANZERUNG> {0}\"\n  STR_FRONT_ARMOR_UC: \"Viischt Panzerung\"\n  STR_LEFT_ARMOR_UC: \"LÉNKS RÜSTUNG\"\n  STR_RIGHT_ARMOR_UC: \"PANZERUNG RIETS\"\n  STR_REAR_ARMOR_UC: \"RÉCKERÜSTUNG\"\n  STR_SKILLS: \"FÄHEGKEETEN> {0}\"\n  STR_LEVEL: \"LEVEL> {0}\"\n  STR_HEAD: \"KAPP\"\n  STR_TORSO: \"TORSO\"\n  STR_RIGHT_ARM: \"RIETSEN ARM\"\n  STR_LEFT_ARM: \"LÉNKEN ARM\"\n  STR_RIGHT_LEG: \"RIETST BEEN\"\n  STR_LEFT_LEG: \"LENKST BEEN\"\n  STR_PAIN_KILLER: \"MËTTEL GÉINT PÉNG\"\n  STR_STIMULANT: \"STIMULANT\"\n  STR_HEAL: \"HEELUNG\"\n  STR_TIME_UNITS_SHORT: \"ZE>{ALT}{0}\"\n  STR_WEIGHT: \"Gewiicht>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"React>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"P.Fähegkeet>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"P.Stä>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Alien Artefakt\"\n  STR_AMMO_ROUNDS_LEFT: \"MUNITIOUN:{NEWLINE}KUGELEN{NEWLINE}IWWREG={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Péng>{ALT}{0}{ALT}{NEWLINE}Opputsch>{ALT}{1}{ALT}{NEWLINE}Heelen>{ALT}{2}\"\n  STR_THROW: \"Werfen\"\n  STR_AUTO_SHOT: \"Autoschoss\"\n  STR_SNAP_SHOT: \"Schnellschoss\"\n  STR_AIMED_SHOT: \"Gezilte Schoss\"\n  STR_STUN: \"Betäuben\"\n  STR_PRIME_GRENADE: \"Granat scharf man\"\n  STR_USE_SCANNER: \"Scanner benotzen\"\n  STR_USE_MEDI_KIT: \"1t-Hëllef benotzen\"\n  STR_LAUNCH_MISSILE: \"Rakéit ofschéissen\"\n  STR_ACCURACY_SHORT: \"Gen>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Net genuch Zäit-Eenheeten!\"\n  STR_NOT_ENOUGH_ENERGY: \"Net genuch Energie!\"\n  STR_NO_ROUNDS_LEFT: \"Keng Kugelen iwwreg!\"\n  STR_NO_AMMUNITION_LOADED: \"Keng Munitioun gelueden!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Falsch Munitioun fir des Waff!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"Waff ass schons gelueden!\"\n  STR_NO_LINE_OF_FIRE: \"Keng Schosslinn!\"\n  STR_GRENADE_IS_ACTIVATED: \"Granat ass aktivéiert!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Granat deaktivéiert!\"\n  STR_THERE_IS_NO_ONE_THERE: \"Do ass keen!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Kann d'Alien Artefakt net benotzen bis et erforscht gouf!\"\n  STR_OUT_OF_RANGE: \"Ausser Reechwäit!\"\n  STR_UNABLE_TO_THROW_HERE: \"Kann net dohin werfen!\"\n  STR_SET_TIMER: \"Timer setzen\"\n  STR_HIDDEN_MOVEMENT: \"VERSTOPPTE BEWEGUNG\"\n  STR_TURN: \"TUER> {0}\"\n  STR_SIDE: \"SÄIT> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Tast drécken fir weider ze maachen\"\n  STR_MIND_CONTROL: \"Gedankenkontroll\"\n  STR_PANIC_UNIT: \"Aschüchtern\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Moralesch Attack gelongen!\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Gedankekontroll huet geklappt\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}leeft Amok\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}leeft Amok\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}panikéiert\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}panikéiert\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Alien\"\n  STR_RIGHT_HAND: \"RIETS HAND\"\n  STR_LEFT_HAND: \"LENKS HAND\"\n  STR_RIGHT_SHOULDER: \"RIETS SCHELLER\"\n  STR_LEFT_SHOULDER: \"LÉNKS SCHËLLER\"\n  STR_BACK_PACK: \"RUCKSAK\"\n  STR_BELT: \"RIMM\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}ass ënnert Kontroll vun den Alien\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}ass ënnert Kontroll vun den Alien\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}ass bewosstlos ginn\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}ass bewosstlos ginn\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}as un enger fataler Wonn gestuerwen\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}as un enger fataler Wonn gestuerwen\"\n  STR_USE_MIND_PROBE: \"Gehiersond benotzen\"\n  STR_FATAL_WOUNDS: \"FATAL WONN\"\n  STR_UNDER_ARMOR_UC: \"PANZERUNG ËNNEN\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Zäiteenheeten fir Schnellschoss reservéiert\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Zäiteenheeten fir en Autoschoss reservéiert\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Zäiteenheete reservéiert fir gezilte Schoss\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Zäiteenheten fir ze knéien reservéiert\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"ZE reservéiert fir ze knéien a schéissen\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} Eenheet am X-Com Fliger\"\n    other: \"{N} Eenheeten am X-Com Fliger\"\n  STR_UNITS_OUTSIDE:\n    one: \"{N} Eenheet bausse bliwwen\"\n    other: \"{N} Eenheete bausse bliwwen\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} Eenheet am Agang\"\n    other: \"{N} Eenheeten am Agang\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} Eenheet am Zil-Ausgang\"\n    other: \"{N} Eenheeten am Zil-Ausgang\"\n  STR_ABORT_MISSION_QUESTION: \"Missioun ofbriechen?\"\n  STR_CORPSE: \"Kierper\"\n  STR_UNLOAD_CRAFT: \"Entlueden\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}ass embrued ginn\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}ass embrued ginn\"\n  STR_HIT_MELEE: \"Treffer\"\n  STR_GROUND: \"BUEDEM\"\n  STR_LIVING_QUARTERS_PLURAL: \"Wunnräim\"\n  STR_LIST_ITEM: \"DEEL\"\n  STR_PERSONAL_ARMOR_UFOPEDIA: \"Mat den neientdeckten Alienmetaller kann dës Panzerung eise Leit eng Chance am Kampf mat den Alien ginn.\"\n  STR_POWER_SUIT_UFOPEDIA: \"En starken neien Schutz fir d'Zaldoten, dës Panzerung as verstärkt mat enger Elerium Energiequell an verstärkt d'Geschwindegkeet an Stäerkt vun dem den se unhuet an garantéiert beschten Schutz fir Kampftruppen.\"\n  STR_FLYING_SUIT_UFOPEDIA: \"Eng verbessert Versioun vum Powerkostüm, den och nach Alienantigravitatiounstechnik huet, fir sech fräi bewegen ze kënnen.\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"All d'Alien sinn am Crash gestuerwen,{NEWLINE}Automatesch Biergung amgaang\"\n  STR_RESET: \"Reset\"\n  STR_MEMORIAL: \"Memorial\"\n  STR_DATE_UC: \"DATUM\"\n  STR_SOLDIERS_RECRUITED_UC: \"ZALDOTE REKRUTÉIERT>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"ZALDOTE VERLUER>{ALT}{0}\"\n  MAP_CULTA: \"Baurenhaff\"\n  MAP_FOREST: \"Bësch\"\n  MAP_JUNGLE: \"Dschungel\"\n  MAP_MOUNT: \"Bierg\"\n  MAP_DESERT: \"Wüst\"\n  MAP_POLAR: \"Polar\"\n  MAP_URBAN: \"Stad\"\n  MAP_UBASE: \"Alien Basis\"\n  MAP_XBASE: \"X-Com Basis\"\n  MAP_MARS: \"Mars\"\n  STR_MIXED: \"Gemëscht\"\n  STR_REMOVE_SELECTED: \"Ugewielten wechhuelen\"\n  STR_LIVE_ALIENS: \"Liëwegt{NEWLINE}Exemplar\"\n  STR_DEAD_ALIENS: \"Ofgeleent{NEWLINE}Exemplar\"\n  STR_UNDER_INTERROGATION: \"Gëtt{NEWLINE}studéiert\"\n  STR_CONTAINMENT_EXCEEDED: \"Alien-Klimazell Kapazitéit errecht.{SMALLLINE}Keng Plaz an der Alien-Klimazell zu {0}. Du muss e puer Alien aus der Klimazell eraushuelen (déi dann stierwen wäerten).\"\n  STR_MANAGE_CONTAINMENT: \"Alien-Klimazell verwalten\"\n  STR_STORAGE_EXCEEDED: \"LAGER IWWERFËLLT!{SMALLLINE}Net genuch Lagerplaz an der Basis {0}. Exzessiv Deeler musse verkaf ginn.\"\n  STR_GO_TO_BASE: \"Zur Basis goen\"\n  STR_MELEE_ACCURACY: \"NOKAMPFGENAUEGKEET\"\n  STR_SELL_PRODUCTION: \"VERKAFEN\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Béid Hänn mussen eidel sinn!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Net genuch Deeler fir den Template ze kopéieren\"\n  STR_UNLOAD_WEAPON: \"Waff entlueden\"\n  STR_ALL_ITEMS: \"All Deeler\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"NET MEI EQUIPEMENT U BORD ERLABT!{SMALLINE}Du kanns just e maximum vun {N} Eenheet vun dësem Equipement mat u Bord huelen.\"\n    other: \"NET MEI EQUIPEMENT U BORD ERLABT!{SMALLINE}Du kanns just e maximum vun {N} Eenheeten vun dësem Equipement mat u Bord huelen.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}KONTROLLZENTER ZERSTÉIERT{NEWLINE}Maach dech zeréck bei den Agang a briech of.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"X-Com Gebäier kënnen net ënnerwaasser gebaut ginn\"\n  STR_LEVEL_SHORT: \"{0}\"\n  STR_PERSONNEL: \"Personal\"\n  STR_CRAFT_ARMAMENT: \"Fliger & Bewaffnung\"\n  STR_COMPONENTS: \"Komponenten\"\n  STR_SOLDIERS_RECRUITED: \"Zaldote rekrutéiert\"\n  STR_SOLDIERS_LOST: \"Zaldote verluer\"\n  STR_TOTAL_UFOS: \"UFOen entdeckt\"\n  STR_TOTAL_ALIEN_BASES: \"Alienbasis fonnt\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"PST\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"PSK\"\n  FEMALE_CIVILIAN: \"Zivilist, weiblech\"\n  MALE_CIVILIAN: \"Zivilist, männlech\"\n  CYBERDISC_WEAPON: \"Cyberdiscwaff\"\n  REAPER_WEAPON: \"Reaperwaff\"\n  CHRYSSALID_WEAPON: \"Chryssalidwaff\"\n  CELATID_WEAPON: \"Celatidwaff\"\n  SILACOID_WEAPON: \"Silacoidwaff\"\n  SECTOPOD_WEAPON: \"Sectopodwaff\"\n  ZOMBIE_WEAPON: \"Zombiewaff\"\n  ALIEN_PSI_WEAPON: \"Alien Psiwaff\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/lv.yml",
    "content": "lv:\n  STR_AVENGER_UFOPEDIA: \"TRANSPORTA IN CĪŅAS LIDAPARĀTS. GALĪGĀ CITPLANĒTIEŠU TEHNOLOGIJAS REPLIKĀCIJA.\"\n  STR_INTERCEPTOR_UFOPEDIA: \"KAUJAS LIDMAŠĪNA AR DUBULTPULSA DETONĀCIJAS DZINĒJU UN ĪPAŠI AIZSARGĀU ELEKTRONIKAS SISTĒMU. VISLABĀKĀ PIEEJAMĀ TEHNOLOGIJA UZ ZEMES.\"\n  STR_LIGHTNING_UFOPEDIA: \"TRANSPORTA UN CĪŅAS KUĢIS. RUPJA, BET EFEKTĪVA SVEŠZEMJU VILCES SISTĒMAS REPLIKA.\"\n  STR_SKYRANGER_UFOPEDIA: \"KARAVĪRU TRANSPORTIERIS. ĀTRĀKAIS NO SAVA VEIDA, AR VERTIKĀLO PACELŠANOS UN NOSĒŠANOS (????) IESPĒJU.  \"\n  STR_FIRESTORM_UFOPEDIA: \"CĪŅAS KUĢIS. ŠIS VIEN-VIETĪGAIS CĪNĪTĀJS ATSPOGUĻO KLASISKO LIDOJOŠĀ ŠĶĪVĪŠA DIZAINU,  AR CENTRĀLO PROPULSIJAS VIENĪBU.\"\n  STR_STINGRAY_UFOPEDIA: \"MODERNIZĒTA GAISA RAĶETE AR ĪPAŠI AIZSARGĀTU ELEKTRONIKU.\"\n  STR_AVALANCHE_UFOPEDIA: \"GAISĀ VADĪTĀ RAĶETE AR REAKTĪVO KODOLGALVIŅU, BET AR ĻOTI SMAGU KRAVU.\"\n  STR_CANNON_UFOPEDIA: \"AUGSTAS JAUDAS LIELGABALS KAS ŠAUJ BRUŅU CAURSITOŠU MUNĪCIJU UN KAS VAR CAURSIST 16 COLLAS TĒRAUDA.\"\n  STR_SECTOID_UFOPEDIA: \"Sektoīdu hierarhija sastāv no karavīriem un līderiem kuri pārvalda spēcīgas prāta spējas. Šīs Sioniskās spējas var izmantot, lai demoralizēt karavīrus cīņas laukā, vai pat veikt kontroli viņu prātiem. Nolaupīšanu tiek pielietota lai iegūtu ģenētisko materiālu priekš krustošanas un lai izveidotu jaunus klonus kuri infiltrētu cilvēku sabiedrību. Liellopi sniedz gan uzturu un ģenētisko materiālu. Šīs rase, šķiet, vēlas attīstīt ģenētisko hibrīdus, lai palielinātu savu stropu efektivitāti.\"\n  STR_SECTOID_AUTOPSY: \"Sektoīda līķā sekcija\"\n  STR_SNAKEMAN_AUTOPSY: \"Čūskvīra līķa sekcija\"\n  STR_ETHEREAL_AUTOPSY: \"Ēteriskā līķa sekcija\"\n  STR_ETHEREAL_AUTOPSY_UFOPEDIA: \"Radība ir fiziski atpalikusi un liekas, ka ir nespējīga uzturēt savas dzīvības funkcijas. Tās muskuļi ir daļēji atrofējušies un iekšējie orgāni izskatās neattīstījušies. Sensorie orgāni, kā acis, neizskatās, ka vispār funkcionētu. Savukārt smadzenes ir labi attīstītas un saņem lielāko daļu no ķermeņa asinsrites. Tā ir mistērija, kā šis radījums vispār var sevi uzturēt, bez atbalsta no ārpuses.\"\n  STR_MUTON_AUTOPSY: \"Mjutona līķa sekcija\"\n  STR_MUTON_AUTOPSY_UFOPEDIA: \"Šīs būtnes \\\"āda\\\" šķiet, ir organiski radīta kā aizsardzības bruņas, kuras ir ieaudzētas organismā. Tajā ir daudz kibernētisko implantu, kas tiek izmantoti, lai uzlabotu sirds-asinsvadu sistēmu un sajūtas. Reproduktīvie orgāni, šķiet, ir ķirurģiski izņemti. Acīmredzot šie nelaimīgie radījumi tika radīti tikai karadarbībai. Bruņu griezīgā munīcija nav ļoti efektīva pret viņu rūdīto ādu.\"\n  STR_CELATID_UFOPEDIA: \"Šaj dzīvības formai ir noslēpumaina dabas dota spēja lidināties pa gaisu. Šķiet, ka tā var uzņemt cilvēku smadzeņu viļņus un virzīsies pretim cilvēka mērķim, pat ja tas ir labi paslēpts. Pēc tam, kad mērķis ir konstatēts, Celatīds nolaižas uz zemes izšauj nelielas uguns lodītes kuras satur ļoti kodīgu indi. Būtne spēj klonēt sevi satraucošā ātrumā. Tā pavada Mjutonu rasi savos klejojumos.\"\n  STR_CELATID_AUTOPSY: \"Celatīda līķa sekcija\"\n  STR_SILACOID_AUTOPSY: \"Silokoīda līķa sekcija\"\n  STR_CHRYSSALID_AUTOPSY: \"Krisalīda līķa sekcija\"\n  STR_FLOATER_AUTOPSY: \"Klīstoša līķa sekcija\"\n  STR_REAPER_UFOPEDIA: \"Šim divkājainajam gaļēdājam ir spēcīgi žokļi un rijīga apetīte. Tam ir vairāki smadzeņu implanti, kas tiek lietoti, lai kontrolētu tā darbību. Primitīvajiem plēsoņas instinktiem nav īpašs pielietojums, atskaitot, lai terorizētu un iznīcinātu. Pļāvēji bieži vien ir saistīti ar Lidoņiem.\"\n  STR_REAPER_AUTOPSY: \"Pļāvēja līķa sekcija\"\n  STR_SECTOPOD_AUTOPSY: \"Sektopoda līķa sekcija\"\n  STR_CYBERDISC_UFOPEDIA: \"Šis miniatūrais lidojošais šķīvītis ir automatizēts terora ierocis, bruņojies ar spēcīgu plazmas šaujamo. Anti-gravitācijas dzinējspēks piešķir tai lielu priekšrocību sarežģītajā reljefā. Tās galvenais uzdevums ir iznīcināšana un terora radīšana, Setoīdu rases rīcībā. \"\n  STR_CYBERDISC_AUTOPSY: \"Kiberdisku sekcija\"\n  STR_UFO_POWER_SOURCE_UFOPEDIA: \"Barošanas avots citplanētiešu lidaparāiem ir anti-matērijas reaktors, kas izmanto Elērijumu (elementu 115), lai radītu spēcīgu gravitācijas viļņi, kā arī citus enerģijas veidus. Pārveidot matēriju enerģijai ir neticami 99% efektīvi, tāpēc nelieli daudzumi Elērijuma var radīt milzīgu spēku. Šo vienību var reproducēt viegli, izmantojot citplanētiešu sakausējumus.\"\n  STR_ALIEN_ALLOYS_UFOPEDIA: \"Citplanētiešu lidaparāti ir būvēti no speciāliem sakausējumiem ar unikālām īpašībām. Tie ir ļoti viegli un izturīgi, un var tikt veidoti ar elektromagnētiskajām metodēm. Šo materiālu var atveidot un izmantot daudzu veidu ražošanas procesos.\"\n  STR_CYDONIA_OR_BUST_UFOPEDIA: \"Tagad ir skaidrs, ka citplanētieši tiek kontrolēti no pazemes bāzes Cidonijā - kas ir neparasta Marsa zona kurā atrodas piecas vienpusīgas piramīdas un lielu veidošanos, kas atgādina cilvēka seju. Cidonijas civilizācija reiz plauka uz Marsa, daudziem miljoniem gadu atpakaļ, bet mēs nezinām, kāpēc tā izmira, vai kā tā ir saistīta ar tur tagad darbojošamies citplanētiešiem. Kāds paskaidrojums jel būtu, mums jāsūta ekspedīciju uz Cidoniju. Tas ir vienīgais veids, kā mēs varam uzvarēt svešzemniekus. Mums ir jāiznīcina kontrolējošās meistar \\\"smadzenes\\\". Mums būs nepieciešams Atriebēja lidaparāts, aprīkots ar vislabāko ekipējumu mūsu rīcībā. Šeit mēs vairāk neko jaunu neiemācīsimies - mums ir jāsagaida  Cidonijas uzbrukuma iznākumu.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"Centrēt uz atrašanās vietu, laiks = 5 Sekundes\"\n  STR_CANCEL_UC: \"ATCELT\"\n  STR_NONE: \"Nekāds\"\n  STR_UNKNOWN: \"Nezināms\"\n  STR_POOR: \"Slikti\"\n  STR_AVERAGE: \"Vidēji\"\n  STR_GOOD: \"Labi\"\n  STR_EXCELLENT: \"Lieliski\"\n  STR_BUILD_NEW_BASE_UC: \"CELT JAUNU BĀZI\"\n  STR_BASE_INFORMATION: \"BĀZES INFORMĀCIJA\"\n  STR_EQUIP_CRAFT: \"APRĪKOT KUĢI\"\n  STR_BUILD_FACILITIES: \"CELT STRUKTŪRAS\"\n  STR_RESEARCH: \"IZPĒTE\"\n  STR_MANUFACTURE: \"RAŽOT\"\n  STR_TRANSFER_UC: \"PĀRVEST\"\n  STR_PURCHASE_RECRUIT: \"PIRKT/REKRUTĒT\"\n  STR_SACK: \"ATLAIST\"\n  STR_SELL_SACK_UC: \"PĀRDOT/ATLAIST\"\n  STR_GEOSCAPE_UC: \"Zemes ainava\"\n  STR_NAME: \"Vārds\"\n  STR_AREA: \"Zona\"\n  STR_BUILD_NEW_BASE: \"Uzcelt Jaunu Bāzi\"\n  STR_CANCEL: \"Atcelt\"\n  STR_COST_UC: \"CENA>\"\n  STR_CONSTRUCTION_TIME_UC: \"BŪVNIECĪBAS LAIKS>\"\n  STR_MAINTENANCE_UC: \"UZTURĒŠANA>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Instalācija\"\n  STR_CURRENT_RESEARCH: \"PAŠREIZĒJĀ IZPĒTE\"\n  STR_SCIENTISTS_AVAILABLE: \"Zinātnieki Pieejami>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Piešķirtie Zinātnieki>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Pieejamā Vieta Labaratorijā>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"IZPĒTES PROJEKTS\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"ZINĀTNIEKI PĒTNIECĪBĀ\"\n  STR_PROGRESS: \"PROGRESS\"\n  STR_NEW_PROJECT: \"Jauns projekts\"\n  STR_CANCEL_PROJECT: \"ATCELT PROJEKTU\"\n  STR_NEW_RESEARCH_PROJECTS: \"JAUNI IZPĒTES PROJEKTI\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"ZINĀTNIEKI PIEEJAMI>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"PIEEJAMĀ VIETA LABARATORIJĀ>{ALT}{0}\"\n  STR_INCREASE: \"Palielināt\"\n  STR_DECREASE: \"Samazināt\"\n  STR_START_PROJECT: \"SĀKT PROJEKTU\"\n  STR_CURRENT_PRODUCTION: \"PAŠREIZĒJĀ PRODUKCIJA\"\n  STR_ENGINEERS_AVAILABLE: \"Inžinieri Pieejami>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Piešķirtie inženieri>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Pieejamā Vieta Darbnīcā>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Pašreizējie Fondi>{ALT}{0}\"\n  STR_ENGINEERS__ALLOCATED: \"Piešķirtie Inžinieri\"\n  STR_UNITS_PRODUCED: \"Vienības Saražotas\"\n  STR_COST__PER__UNIT: \"Izmaksas{NEWLINE}par{NEWLINE}Vienību\"\n  STR_DAYS_HOURS_LEFT: \"Dienas/stundas palikušas\"\n  STR_NEW_PRODUCTION: \"Jauna produkcija\"\n  STR_CATEGORY: \"KATEGORIJA\"\n  STR_START_PRODUCTION: \"SĀKT PRODUKCIJU\"\n  STR_COST_PER_UNIT_: \"Vienas vienības izmaksas>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"NEPIECIEŠAMI SPECIALIZĒTI MATERIĀLI\"\n  STR_UNITS_REQUIRED: \"VIENĪBAS VAJADZĪGAS\"\n  STR_UNITS_AVAILABLE: \"VIENĪBAS PIEEJAMAS\"\n  STR_STOP_PRODUCTION: \"PĀRTRAUKT IZGATAVOŠANU\"\n  STR_ENGINEERS_AVAILABLE_UC: \"INŽENIERI PIEEJAMI>{ALT}{0}\"\n  STR_INCREASE_UC: \"Palielināt\"\n  STR_DECREASE_UC: \"SAMAZINĀT\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Pirkt/Algot Personālu\"\n  STR_COST_PER_UNIT_UC: \"IZMAKSA PAR VIENU VIENĪBU\"\n  STR_QUANTITY_UC: \"SKAITS\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"PIEEJAMAIS PERSONĀLS:PERSONĀLS KOPĀ>\"\n  STR_SOLDIERS: \"Karavīri\"\n  STR_SCIENTISTS: \"Zinātnieki\"\n  STR_ENGINEERS: \"Inženieri\"\n  STR_LIVING_QUARTERS: \"Dzīvojamās Telpas\"\n  STR_STORES: \"Noliktavas\"\n  STR_LABORATORIES: \"Laboratorijas\"\n  STR_WORK_SHOPS: \"Darbnīcas\"\n  STR_HANGARS: \"Angāri\"\n  STR_SHORT_RANGE_DETECTION: \"Īsā darbības rādiusa atklāšana\"\n  STR_DEFENSE_STRENGTH: \"Aizsardzības spēks\"\n  STR_TRANSFERS_UC: \"PĀRSKAITĪJUMI\"\n  STR_ARRIVAL_TIME_HOURS: \"Ierašanās laiks (stundās)\"\n  STR_COST_: \"Izmaksa>{ALT}{0}\"\n  STR_AREA_: \"Zona>{ALT}{0}\"\n  STR_BASE_NAME: \"Bāzes Nosaukums?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"IZVĒLATIES KU NOVIETOT PIEEJAS LIFTU\"\n  STR_TRANSFER: \"Pārvest\"\n  STR_SELECT_DESTINATION_BASE: \"Norādiet bāzi galamērķim\"\n  STR_COST: \"Izmaksa\"\n  STR_VICTORY_1: \"Ieejot kambarī tu redzi citplanētiešu smadzenes - jūsu meklēšanas objektu. Pirms jūs varat izšaut, tās sazinās ar jums caur ekrānu tām blakus. Tās lūdz tevi, lai uzklausies tā argumentus par izdzīvošanu, pirms veicat lēmumu izšaut\"\n  STR_VICTORY_2: \"Smadzenes runā: ''Pirms daudziem miljoniem gadu, planēta kuru jūs saucat par Marsu, bija dzīva. Šī dzīve tika izveidota no neauglīgas planētas - mūsu civilizācijā, tā pat kā ar jūsu Zemi. Miljoniem gadu laikā mēs esam apmeklējuši jūsu planētu un ģenētiski uzlabojuši jūs. Jūs nevarat mūs nogalināt, mēs esam daļa no jums...\"\n  STR_VICTORY_3: \"Šis ir  Marsa civilizācijas centrs - piramīdas būvētas miljoniem gadu pirms jūsējām - rasei, kas ir jūsu sencis. Neviena planēta ir ārpus mūsu ietekmes. Šīs pilnvaras arī varētu būt jūsu. Viss, ko mēs lūdzam, ir jūsu sadarbība ...\"\n  STR_GAME_OVER_1: \"Citplanētieši mēģina iznīcināt visu cilvēci, iznīcinot pilsētas un saindējot gaisu un jūras. Zemes pretestība ir veltīga, saskaroties ar ievērojami augstākām tehnoloģijām. Izdzīvojušās paaudzes cieš no briesmīgas mutācijas, bēgot no citplanētiešu iznīcināšanas. Tie tiek aizvesti uz vergu nometnēm palīdzēt pārveidot zemi par citplanētiešu koloniju, kas ir daļa no kaut kādas nezināmas impērijas.\"\n  STR_VICTORY_4: \"Citplanētiešu smadzenes ir pārtrauktas ar karstā plazmaz eksploziju, un viss svešzemju spēks ir uzvarēts...\"\n  STR_YOU_HAVE_FAILED: \"Jums nav izdevies apturēt svešzemju iebrucējus. Viena pēc otras, finansējušās nācijas paraksta līgumus ar citplanētiešiem sološus daudzsološu tehnoloģiju, labklājību un mieru. Tomēr drīz vien kļūst skaidrs, ka citplanētiešiem ir citi plāni ...\"\n  STR_TOTAL_UC: \"KOPSUMMA\"\n  STR_INCOME: \"Ienākums\"\n  STR_EXPENDITURE: \"Izdevumi\"\n  STR_MAINTENANCE: \"Uzturēšana\"\n  STR_BALANCE: \"Balanss\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"NLO Aktivitāte Apgabalos\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"NLO Darbība Valstīs\"\n  STR_FINANCE: \"Finanses\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Nepietiekami speciālo materiālu lai producētu{NEWLINE}{0}{NEWLINE}uz{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Nepietiekami naudas līdzekļu lai producētu{NEWLINE}{0}{NEWLINE}uz{NEWLINE}{1}\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"Būvniecība{NEWLINE}{0}{NEWLINE}uz{NEWLINE}{1}{NEWLINE}ir pabeigta\"\n  STR_OK_5_SECONDS: \"OK - 5 sekundes\"\n  STR_RESEARCH_COMPLETED: \"Pētījums pabeigts\"\n  STR_VIEW_REPORTS: \"APSKATĪT ZIŅOJUMUS\"\n  STR_WE_CAN_NOW_RESEARCH: \"Mēs tagad varam izpētīt\"\n  STR_WE_CAN_NOW_PRODUCE: \"Mēs tagad varam producēt\"\n  STR_SUNDAY: \"SVĒTDIENA\"\n  STR_MONDAY: \"PIRMDIENA\"\n  STR_TUESDAY: \"OTRDIENA\"\n  STR_WEDNESDAY: \"TREŠDIENA\"\n  STR_THURSDAY: \"CETURTDIENA\"\n  STR_FRIDAY: \"PIEKTDIENA\"\n  STR_SATURDAY: \"SESTDIENA\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Nepietiek {0}, lai uzpildītu degvielu {1} pie {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Nav pietiekami{0} lai apbruņot {1} uz {2}\"\n  STR_UFO_IS_NOT_RECOVERED: \"NLO netika atgūts\"\n  STR_UFO_IS_RECOVERED: \"NLO tika atgūts\"\n  STR_CRAFT_IS_LOST: \"Lidaparāts tika zaudēts\"\n  STR_TERROR_CONTINUES: \"Terors turpinās\"\n  STR_ALIENS_DEFEATED: \"Citplanētieši tika pieveikti\"\n  STR_BASE_IS_LOST: \"Bāze tika zaudēta\"\n  STR_BASE_IS_SAVED: \"Bāze ir pasargāta\"\n  STR_ALIEN_BASE_STILL_INTACT: \"Citplanētiešu bāze joprojām neskarta\"\n  STR_ALIEN_BASE_DESTROYED: \"Citplanētiešu Bāze iznīcināta\"\n  STR_ALIENS_KILLED: \"CITPLANĒTIEŠI NOGALINĀTI\"\n  STR_ALIEN_CORPSES_RECOVERED: \"ATGŪTIE CITPLANĒTIEŠU LĪĶI\"\n  STR_LIVE_ALIENS_RECOVERED: \"DZĪVI CITPLANĒTIEŠI ATGŪTI\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"CITPLANĒTIEŠU ARTIFAKTI ATGŪTI\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"Citplanētiešu bāze iznīcināta\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"CITPLANĒTIEŠIEM NOGALINĀTIE CIVILIEDZĪVOTĀJI\"\n  STR_CIVILIANS_SAVED: \"CIVILIEDZĪVOTĀJI IZGLĀBTI \"\n  STR_TANKS_DESTROYED: \"TANKI INĪCINĀTI\"\n  STR_UFO_RECOVERY: \"NLO Atgūšana\"\n  STR_ALIEN_BASE_RECOVERY: \"ATKOPŠANĀS NO CITPLANĒTIEŠU BĀZES\"\n  STR_BASE_UNDER_ATTACK: \"{0} under attack!\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"GRAVITĀTES VAIROGS ATVAIRA NLO!\"\n  STR_FIRING: \"ŠAUJ\"\n  STR_HIT: \"TRĀPĪJUMS!\"\n  STR_UFO_DESTROYED: \"NLO IZNĪCINĀTS!\"\n  STR_FUNDS: \"NAUDAS LĪDZEKĻĪ> {ALT}{0}\"\n  STR_SELL_SACK: \"Pārdot/Atlaist\"\n  STR_UFO_GROUND_ASSAULT: \"NLO ZEMES UZBRUKUMS\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"NEPIETIEKAMI DARBA VIETAS PIEEJAMS! {SMALLLINE} Uzbūvējiet jaunu darbnīcu vai samazināt darbu pie citiem projektiem.\"\n  STR_NOT_ENOUGH_MONEY: \"NEPIETIEKAMI NAUDAS!\"\n  STR_LAUNCH_INTERCEPTION: \"UZSĀKT IZSEKOŠANU\"\n  STR_BASE: \"BĀZE\"\n  STR_READY: \"GATAVS\"\n  STR_TARGET: \"MĒRĶIS: {0}\"\n  STR_YES: \"JĀ\"\n  STR_NO: \"NĒ\"\n  STR_SELECT_DESTINATION: \"IZVĒLATIES GALAPUNKTU\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"Izvēlēties vietu priekš jaunas bāzes\"\n  STR_RETURN_TO_BASE: \"ATGRIEZTIES UZ BĀZI\"\n  STR_SELECT_NEW_TARGET: \"IZVĒLIES JAUNU MĒRĶI\"\n  STR_TAILING_UFO: \"IZSEKO NLO\"\n  STR_MAXIMUM_SPEED_UC: \"MAKSIMĀLAIS ĀTRUMS>{ALT}{0}{ALT}\"\n  STR_LOW_UC: \"ZEMS\"\n  STR_VERY_HIGH: \"ĻOTI AUGSTS\"\n  STR_WEAPON_ONE: \"IEROCIS-1>{ALT}{0}\"\n  STR_NONE_UC: \"NAV\"\n  STR_INTERCEPTION_CRAFT: \"PĀRTVĒRŠANAS LIDAPARĀTS\"\n  STR_BASE_: \"Bāze>{0}\"\n  STR_NAME_UC: \"VĀRDS\"\n  STR_AMMO_: \"MUNĪCIJA>{ALT}{0}\"\n  STR_ARMOR: \"BRUŅAS\"\n  STR_ROOKIE: \"Iesācējs\"\n  STR_SERGEANT: \"Seržants\"\n  STR_SPACE_AVAILABLE: \"VIETA PIEEJAMA>{ALT}{0}\"\n  STR_WOUNDED: \"Ievainots\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Aprīkojums priekš {0}\"\n  STR_DEFENSE_VALUE: \"Aizsardzība\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}gatavs{NEWLINE}nolaisties pie{NEWLINE}{ALT}{1}\"\n  STR_SELECT_ARMAMENT: \"Izvēlaties Ekipējumu\"\n  STR_AMMUNITION_AVAILABLE: \"MUNĪCIJA PIEEJAMA\"\n  STR_ARMAMENT: \"BRUŅOJUMS\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"IZVĒLĒTIES BRUŅAS PRIEKŠ{NEWLINE}{0}\"\n  STR_PERSONAL_ARMOR_UC: \"PERSONISKĀS BRUŅAS\"\n  STR_POWER_SUIT_UC: \"JAUDAS KOSTĪMS\"\n  STR_FLYING_SUIT_UC: \"LIDKOSTĪMS\"\n  STR_SELECT_ARMOR: \"Izvēlaties Bruņas\"\n  STR_NORTH_EAST: \"ZIEMEĻAUSTRUMI\"\n  STR_EAST: \"AUSTRUMI\"\n  STR_SOUTH_EAST: \"DIENVIDAUSTRUMI\"\n  STR_SOUTH_WEST: \"Dienvidrietumi\"\n  STR_NORTH_WEST: \"ZIEMEĻRIETUMI\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"TURPINĀT TVARSTĪŠANU\"\n  STR_VERY_LARGE: \"ĻOTI LIELS\"\n  STR_MEDIUM_UC: \"VIDĒJI\"\n  STR_SMALL: \"MAZS\"\n  STR_DETECTED: \"Atklāts\"\n  STR_SIZE_UC: \"LIELUMS\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"CENTRĒT NLO - LAIKS = 5 sek.\"\n  STR_CRASH_SITE_: \"AVĀRIJAS NOTIKUMA VIETA-{0}\"\n  STR_LANDING_SITE_: \"NOLAIŠANĀS VIETA-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}ir sasniedzis{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"Patrulē\"\n  STR_ALIEN_ORIGINS: \"Citplanētiešu izcelšanās\"\n  STR_THE_MARTIAN_SOLUTION: \"Marsa Risinājums\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"Smago Ieroču Platforma\"\n  STR_ALIEN_ARTIFACTS: \"CITPLANĒTIEŠU ARTIFAKTI\"\n  STR_ALIEN_LIFE_FORMS: \"CITPLANĒTIEŠU DZĪVĪBAS FORMAS\"\n  STR_ALIEN_RESEARCH_UC: \"CITPLANĒTIEŠU IZPĒTE\"\n  STR_UFO_COMPONENTS: \"NLO SASTĀVDAĻAS\"\n  STR_SELECT_ITEM: \"IZVĒLĒTIES IERĪCI\"\n  STR_FUEL_CAPACITY: \"Degvielas tvertne>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"BOJĀJUMU JAUDA>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Bojājumi\"\n  STR_RANGE: \"Attālums\"\n  STR_KILOMETERS: \"{0} kilometri\"\n  STR_DAMAGE_SMOKE: \"DŪMI\"\n  STR_ACCURACY_UC: \"PRECIZITĀTE\"\n  STR_DAMAGE_UC: \"BOJĀJUMI\"\n  STR_AMMO: \"MUNĪCIJA\"\n  STR_CONSTRUCTION_COST: \"Celtniecības Izmaksas\"\n  STR_MAINTENANCE_COST: \"Uzturēšanas izmaksas\"\n  STR_LOW: \"Zema\"\n  STR_MEDIUM: \"Vidējs\"\n  STR_CRAFT_AMMUNITION: \"Kuģa munīcija\"\n  STR_WEAPON: \"Ierocis\"\n  STR_AMMUNITION: \"Munīcija\"\n  STR_PERSONAL_ARMOR: \"Personālās Bruņas\"\n  STR_ALIEN: \"Svešzemis\"\n  STR_ETHEREAL: \"Ēteriskais\"\n  STR_MUTON: \"Mjutons\"\n  STR_CELATID: \"Celatīds\"\n  STR_SILACOID: \"Silikoīds\"\n  STR_ZOMBIE: \"Zombijs\"\n  STR_CYBERDISC: \"Kiberdisks\"\n  STR_LIVE_LEADER: \"Līderis\"\n  STR_LIVE_ENGINEER: \"Inžinieris\"\n  STR_LIVE_MEDIC: \"Ārsts\"\n  STR_LIVE_TERRORIST: \"Terorists\"\n  STR_FLOATER_NAVIGATOR: \"Klīstojošo Navigātors\"\n  STR_SECTOID_SOLDIER: \"Sektoīdu kareivis\"\n  STR_SECTOID_NAVIGATOR: \"Sektoīdu Navigātors\"\n  STR_SECTOID_MEDIC: \"Sektoīdu mediķis\"\n  STR_SECTOID_ENGINEER: \"Sektoīdu Inžinieris\"\n  STR_SECTOID_COMMANDER: \"Sektoīdu Komandieris\"\n  STR_SNAKEMAN_SOLDIER: \"Čūskvīru Karavīrs\"\n  STR_SNAKEMAN_NAVIGATOR: \"Čūksvīru navigators\"\n  STR_SNAKEMAN_COMMANDER: \"Čūskvīru komandieris\"\n  STR_ETHEREAL_SOLDIER: \"Ēterisko kareivis\"\n  STR_ETHEREAL_LEADER: \"Etērisko Līderis\"\n  STR_ETHEREAL_COMMANDER: \"Ēterisko komandieris\"\n  STR_CYBERDISC_TERRORIST: \"Kiberdisku terorists\"\n  STR_REAPER_TERRORIST: \"Pļāvēju terorists\"\n  STR_CHRYSSALID_TERRORIST: \"Krissalīdu terorists\"\n  STR_CELATID_TERRORIST: \"Selatīdu terorists\"\n  STR_SILACOID_TERRORIST: \"Silikoīdu terorists\"\n  STR_SECTOPOD_TERRORIST: \"Sektopodu Terorists\"\n  STR_UFO_POWER_SOURCE: \"NLO Enerģijas Avots\"\n  STR_UFO_NAVIGATION: \"NLO Navigācija\"\n  STR_UFO_CONSTRUCTION: \"NLO Konstrukcija\"\n  STR_ALIEN_FOOD: \"Citplanētiešu ēdiens\"\n  STR_ALIEN_REPRODUCTION: \"Citplanētiešu vairošanās\"\n  STR_ALIEN_ENTERTAINMENT: \"Citplanētiešu Izklaide\"\n  STR_POWER_SUIT: \"Spēka Kostīms\"\n  STR_NEW_FIGHTER_CRAFT: \"Jauns Kaujas Pārtvērējs\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Jauns Cīnītājs-Transportieris\"\n  STR_LASER_PISTOL: \"Lāzera pistole\"\n  STR_LASER_RIFLE: \"Lāzera Šautene\"\n  STR_HEAVY_LASER: \"Smagais Lāzers\"\n  STR_PLASMA_DEFENSE: \"Plazmas Aizsardzība\"\n  STR_GRAV_SHIELD: \"Gravitātes vairogs\"\n  STR_MOTION_SCANNER: \"Kustības Skeneris\"\n  STR_TANK_CANNON: \"Tanks/Lielgabals\"\n  STR_TANK_ROCKET_LAUNCHER: \"Tanks/Granāt Metējs\"\n  STR_HOVERTANK_LAUNCHER: \"Lidtanks/Lielgabals\"\n  STR_STINGRAY_LAUNCHER: \"Dzeloņraju lielgabals\"\n  STR_STINGRAY_MISSILES: \"Dzeloņraju Raķetes\"\n  STR_AVALANCHE_MISSILES: \"Lavīnas Raķetes\"\n  STR_CANNON_ROUNDS_X50: \"Lielgabala lādiņi (x50)\"\n  STR_FUSION_BALL: \"Sintēzes Bumba\"\n  STR_ENGINEER: \"Inžinieris\"\n  STR_NORTH_AMERICA: \"Ziemeļamerika\"\n  STR_ARCTIC: \"Arktika\"\n  STR_ANTARCTICA: \"Antarktika\"\n  STR_SOUTH_AMERICA: \"Dienvidamerika\"\n  STR_NORTH_AFRICA: \"Ziemeļāfrika\"\n  STR_CENTRAL_ASIA: \"Centrālā āzija\"\n  STR_PACIFIC: \"Klusais Okeāns\"\n  STR_NORTH_ATLANTIC: \"Ziemeļatlantija\"\n  STR_SOUTH_ATLANTIC: \"Dienvidatlantija\"\n  STR_ALIEN_RESEARCH: \"Citplanētiešu izpēte\"\n  STR_ALIEN_INFILTRATION: \"Citplanētiešu infiltrācija\"\n  STR_ALIEN_BASE: \"Citplanētiešu bāze\"\n  STR_ALIEN_TERROR: \"Citplanētiešu teror-akts\"\n  STR_HYPER_WAVE_DECODER_UC: \"HIPERVIĻŅU DEKODĒTĀJS\"\n  STR_LIGHTNING: \"APGAISMOJUMS\"\n  STR_AVENGER: \"ATRIEBĒJS\"\n  STR_FUSION_BALL_UC: \"SINTĒZES BUMBA\"\n  STR_LASER_CANNON_UC: \"LĀZERA LIELGABALS\"\n  STR_DAMAGE_CAPACITY: \"Bojājumu kapacitāte\"\n  STR_WEAPON_POWER: \"Ieroča spēks\"\n  STR_ACCESS_LIFT: \"Piekļuves lifts\"\n  STR_LABORATORY: \"Labaratorija\"\n  STR_SMALL_RADAR_SYSTEM: \"Nelielā radaru sistēma\"\n  STR_LARGE_RADAR_SYSTEM: \"Lielā Radaru Sistēma\"\n  STR_MISSILE_DEFENSES: \"Raķešu Aizsardzība\"\n  STR_PLASMA_DEFENSES: \"Plazmas Aizsardzības\"\n  STR_HANGAR: \"Angārs\"\n  STR_RUSSIA: \"KRIEVIJA\"\n  STR_UK: \"APVIENOTĀ KARALISTE\"\n  STR_FRANCE: \"FRANCIJA\"\n  STR_GERMANY: \"VĀCIJA\"\n  STR_SPAIN: \"SPĀNIJA\"\n  STR_CHINA: \"ĶĪNA\"\n  STR_JAPAN: \"Japāna\"\n  STR_INDIA: \"INDIJA\"\n  STR_AUSTRALIA: \"AUSTRĀLIA\"\n  STR_NIGERIA: \"NIGĒRIJA\"\n  STR_SOUTH_AFRICA: \"DIENVIDĀFRIKA\"\n  STR_EGYPT: \"ĒĢIPTE\"\n  STR_FEB: \"Feb.\"\n  STR_MAR: \"Mar.\"\n  STR_APR: \"Aprīlis\"\n  STR_MAY: \"Mai.\"\n  STR_JUN: \"Jūnijs\"\n  STR_JUL: \"Jūlijs\"\n  STR_OCT: \"Okt.\"\n  STR_COUNTRY: \"Valsts\"\n  STR_FUNDING: \"Finansējums\"\n  STR_CHANGE: \"Mainīt\"\n  STR_WEAPON_SYSTEMS: \"IEROČU SISTĒMAS\"\n  STR_HWPS: \"SIPs\"\n  STR_DAMAGE_UC_: \"BOJĀJUMS>{ALT}{0}\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Katrs izmitināšanas bloks nodrošina līdz 50 darbiniekiem. Tas nodrošina  pamata rekreācijas, pārtikas un guļamistabas zonu.\"\n  STR_PLASMA_DEFENSES_UFOPEDIA: \"Plazmas starotāja aizsargspēja nodrošina spēcīgu un efektīvu aizsardzību pret NLO lidaparāu iebrukumu.\"\n  STR_MIND_SHIELD_UFOPEDIA: \"Tā kā svešzemju lidaparāti paļaujas uz smadzeņu viļņiem lai atklātu cilvēku klātbūtni, visefektīvākais pretpasākums ir aizsargāt smadzeņu viļņus no bāzes. Šis mehānisms krasi samazinās izredzes citplanētiešiem atrast mūsu bāzi.\"\n  STR_HYPER_WAVE_DECODER_UFOPEDIA: \"Citplanētiešu sakari paļaujas uz supra-dimensiju viļņiem, kas pārvietojas gandrīz momentāni. Dekodera iekārta pārtver NLO pārraides un dekodē informāciju. Tās liecina par NLO veidu, to rasi un darbības vietu.\"\n  STR_LASER_PISTOL_UFOPEDIA: \"Lāzera pistole ir efektīva īstenošana jaunajā tehnoloģijā. Tāi ir parastās pistoles ērtības ar ātrāku un precīzāku šaušanu.\"\n  STR_HEAVY_LASER_UFOPEDIA: \"Smagais lāzers ir apgrūtinošs, bet ļoti efektīvs.\"\n  STR_SMOKE_GRENADE_UFOPEDIA: \"Dūmu granātas ir noderīgas lai nodrošinātu aizsardzību atklātajās kaujas situācijās. Izmantojiet viņas uzmanīgi, jo tās var dot labumu arī ienaidniekam.\"\n  STR_HIGH_EXPLOSIVE_UFOPEDIA: \"Šī sprāgstviela būtu jāizmanto vienīgi nojaukšanas nolūkos. Turiet personālu tālāk no nojaukšanas vietām.\"\n  STR_MEDI_KIT_UFOPEDIA: \"Aptieciņa apvieno dzīšanas iekārtas ar pretsāpju līdzekļiem un stimulantiem. Lai izmantotu aptieciņu jums ir jāpieiet pie karavīra kuram nepieciešama ārstēšana. Ja karavīrs ir apdullinātas, jums ir jāstāv virs viņa ķermeņa. Noklikšķiniet uz aptieciņas ikonas un izvēlieties \\\"lietot aptieciņu\\\" no izvēlnes. {NEWLINE} ĀRSTĒŠANA> Sarkanās virsbūves daļas parādīs fatālās brūces. Noklikšķiniet uz ķermeņa daļas, kas tika ievainota. Noklikšķiniet uz \\\"Ārstēt\\\" ikonas. Viena letāla brūce tiks izārstēta un mazliet veselības tiks atjaunots. {NEWLINE} STIMULANTS> Tas atjaunos enerģiju un atdzīvinās karavīrus kuri ir bezsamaņā (apdullināti). Lai atdzīvinātu karavīrus bezsamaņā jums ir jāstāv tieši virs to ķermeņa. {NEWLINE} PRETSĀPJU LĪDZEKĻI> Tas atjaunos ievainoto karavīru morāli līdz summai, kas vienāda ar karavīra zaudēto veselību.\"\n  STR_STUN_ROD_UFOPEDIA: \"Šo ierīci var izmantot tikai tuvcīņā, tomēr tā apdullinās dzīvu organismu nenogalinot to, izmantojot elektrošoku.\"\n  STR_SMALL_LAUNCHER_UFOPEDIA: \"Neliels granātmetējs, kas šauj apdullinošas bumbas. Ārkārtīgi noderīgs dzīvu citplanētiešu notveršanā.\"\n  STR_SMALL_SCOUT: \"Mazais izlūks\"\n  STR_MEDIUM_SCOUT: \"Vidējs Skauts\"\n  STR_LARGE_SCOUT: \"Lielais Skautu Kuģis\"\n  STR_TERROR_SHIP: \"Teroristu kuģis\"\n  STR_SUPPLY_SHIP: \"Apgādes kuģis\"\n  STR_RATING: \"REITINGS> {0}\"\n  STR_RATING_POOR: \"SLIKTI!\"\n  STR_RATING_OK: \"OK\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"Finansējošo nāciju padome ir visā visumā apmierināta ar līdzšinējo progresu.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"Finansējošo nāciju padome ir ļoti apmierināta ar jūsu lieliskajiem panākumiem. Turpiniet sekmīgo darbu.\"\n  STR_COUNCIL_IS_DISSATISFIED: \"Finansējošo nāciju padome nav apmierināta ar jūsu sniegumu. Jums ir jāuzlabo sava efektivitāte sakarā ar citplanētiešu draudu novēršanu, citāti jūs riskējat ar projekta darbības pārtraukšanu.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"Jums neizdevās tikt galā ar citplanētiešu invāziju un finansējošo nāciju padome ar nožēlu ir nolēmusi pārtraukt projekta darbību. Katra nācija tiks galā ar problēmu pēc saviem ieskatiem. Mēs varam tikai cerēt, ka mums izdosies tikt skaidrībā ar šiem, acīmredzami naidīgajiem, spēkiem, un to, ka lielākā iedzīvotāju daļa samierināsies ar citplanētu ciemiņiem.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} ir īpaši apmierināti ar jūsu progresu cīņā ar svešzemju iebrucējiem un ir vienojušās palielināt finansējumu.\"\n  STR_COUNTRIES_AND: \"{0} un {1}\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} ir neapmierināti ar tavu spēju tikt galā ar citplanētiešu darbību viņu teritorijā, un ir nolēmuši samazināt finansējumu\"\n  STR_KNOTS: \"{0} mezgli\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} ir parakstījuši slepenu paktu ar nezināmiem svešzemju spēkiem un ir izstājušies no projekta.\"\n  STR_COUNCIL_REDUCE_DEBTS: \"Finansēšanas padome nav apmierināta ar jūsu finansiālo stāvokli. Jums ir jāsamazina savi parādi zem $1 miljona vai projekts tiks atcelts.\"\n  STR_ZONE: \"ZONA\"\n  STR_ALLOCATE_RESEARCH: \"Pētniecība\"\n  STR_NEW_YORK: \"Ņujorka\"\n  STR_MONTREAL: \"Montreāls\"\n  STR_VANCOUVER: \"Vankūvera\"\n  STR_BRASILIA: \"Brazīlija\"\n  STR_BUENOS_AIRES: \"Buenosairesa\"\n  STR_SANTIAGO: \"Santjago\"\n  STR_LONDON: \"Londona\"\n  STR_BERLIN: \"Berlīne\"\n  STR_MOSCOW: \"Maskava\"\n  STR_CAIRO: \"Kaira\"\n  STR_CASABLANCA: \"Kasablanka\"\n  STR_PRETORIA: \"Pretorija\"\n  STR_KINSHASA: \"Kinšasa\"\n  STR_BAGHDAD: \"Bagdāde\"\n  STR_TOKYO: \"Tokija\"\n  STR_BEIJING: \"Pekina\"\n  STR_BANGKOK: \"Bangkoka\"\n  STR_SEOUL: \"Seula\"\n  STR_SINGAPORE: \"Singapūra\"\n  STR_SHANGHAI: \"Šanhaja\"\n  STR_HONG_KONG: \"Honkonga\"\n  STR_CANBERRA: \"Kanbera\"\n  STR_WELLINGTON: \"Velingtona\"\n  STR_PSIONIC_TRAINING: \"PSIONISKAIS TRENIŅŠ\"\n  STR_PSI_AMP: \"Psi-pastiprinātājs\"\n  STR_WEAPONS_CREW_HWPS: \"IEROČI/{NEWLINE}KOMANDA/HWPs\"\n  STR_RANK_: \"RANGS> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"ATVESEĻOŠANĀS> {ALT}{0}\"\n  STR_STAMINA: \"IZTURĪBA\"\n  STR_REACTIONS: \"REAKCIJA\"\n  STR_FIRING_ACCURACY: \"ŠAUŠANAS PRECIZITĀTE\"\n  STR_THROWING_ACCURACY: \"MEŠANAS PRECIZITĀTE\"\n  STR_STRENGTH: \"SPĒKS\"\n  STR_NEW_RANK: \"JAUNS RANGS\"\n  STR_PROMOTIONS: \"Paaugstinājumi\"\n  STR_SOLDIERS_UC: \"KARAVĪRI\"\n  STR_TANK_ROCKET_LAUNCHER_UFOPEDIA: \"Šī automatizētā Smagā Ieroču Platforma ir bruņota ar spēcīgām raķetēm. Tā būs postoša jebkuram svešzemju ienaidniekam. Pārliecinieties, ka jūms ir pietiekami SIP rakešu.\"\n  STR_HOVERTANK_PLASMA_UFOPEDIA: \"Citplanētiešu tehnoloģija ir devusi HWP jaunu dzīves slāni. Pievienotā manevrētspēja gaisa ceļojumiem un plazmas staru spēks ir letāla kombinācija.\"\n  STR_HOVERTANK_LAUNCHER_UFOPEDIA: \"Šis lidtanks ir aprīkots ar kodolsintēzes bumbu nesējraķeti, kas spēj izraisīt milzīgu postījumu. Izmantojiet to ar lielu rūpību. Jums būs jāražo šīs kodolsintēzes bumbas, lai SIP tanki būtu bruņoti. Lai izšautu to, jūms ir  jāizvēlās \\\"punkti,\\\" kuroslidos bumba ar kursoru un tad noklikšķiniet uz palaišanas ikonas, lai izšautu kodolsintēzes bumbu.\"\n  STR_HEAVY_PLASMA_CLIP_UFOPEDIA: \"Šī kompaktā ierīce tiek lietota kā munīcija smagajai plazmas šautenei. Tā satur nelielu Elērija daudzumu.\"\n  STR_BATTLESHIP_UFOPEDIA: \"Kaujas kuģis ir lielākais un jaudīgākais citplanētiešu lidaparāts. Parasti tas ir galvenais citplanētiešu misiju kuģis, kas aprīkots ar spēcīgiem ieročiem un daudziem apkalpes locekļiem.\"\n  STR_DISMANTLE: \"Demontēt\"\n  STR_TRANSFER_ITEMS_TO: \"Pārvest ekipējumu uz {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"NAV CITPLANĒTIEŠU IEROBEŽOŠANAS MEHĀNISMA PĀRVEŠANAI! {SMALLLINE} Dzīviem citplanētiešiem nepieciešama citplanētiešu ierobežošanas mehānisms, lai izdzīvotu.\"\n  STR_PISTOL: \"Pistole\"\n  STR_PISTOL_CLIP: \"Pistoles aptvere\"\n  STR_HC_AP_AMMO: \"SL-AP munīcija\"\n  STR_AUTO_CANNON: \"Automātiskais lielgabals\"\n  STR_AC_AP_AMMO: \"AL-AP munīcija\"\n  STR_AC_HE_AMMO: \"AL-HE munīcija\"\n  STR_AC_I_AMMO: \"AC-I Munīcija\"\n  STR_SMALL_ROCKET: \"Mazā Raķete\"\n  STR_GRENADE: \"Granāta\"\n  STR_SMOKE_GRENADE: \"Dūmu Granāta\"\n  STR_PROXIMITY_GRENADE: \"Tuvuma granāta\"\n  STR_STUN_ROD: \"Apdullināšanas nūja\"\n  STR_HEAVY_PLASMA_CLIP: \"Smagās Plazmas Aptvere\"\n  STR_PLASMA_RIFLE: \"Plazmas Šautene\"\n  STR_PLASMA_PISTOL: \"Plazmas pistole\"\n  STR_STUN_BOMB: \"Apdullināšanas Granāta\"\n  STR_ALIEN_GRENADE: \"Citplanētiešu Granāta\"\n  STR_ELERIUM_115: \"Elērijums-115\"\n  STR_SECTOID_CORPSE: \"Sektoīdu Līķis\"\n  STR_SNAKEMAN_CORPSE: \"Čūskvīra līķis\"\n  STR_ETHEREAL_CORPSE: \"Etēriskā līķīs\"\n  STR_MUTON_CORPSE: \"Mjutona Līķīs\"\n  STR_CELATID_CORPSE: \"Celatīda Līķis\"\n  STR_REAPER_CORPSE: \"Pļāvēja līķis\"\n  STR_CYBERDISC_CORPSE: \"Saiberdiska Līķis\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Nepietiek ekipējuma, lai atkārtoti pilnībā aprīkotu komandu\"\n  STR_MARS_CYDONIA_LANDING: \"Marss: piezemēšanās Sidonijā\"\n  STR_MARS_CYDONIA_LANDING_BRIEFING: \"Jūsu kuģis Atriebējs piezemējās Sidonijas reģionā uz Marsa virsmas. Mūsu informācija norāda, ka viena no piramidālajām konstrukcijām satur pazemes kompleksa piekļuves liftu. Tikko jūsu kareivji ir sapulcējušies lifta zonā, klikšķini uz \\\"atcelt misiju\\\" piktogrammas, lai turpinātu uz nākamo posmu.\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"Citplanētieši ir iznīcinājuši neaizsargāto bāzi  {0}\"\n  STR_CAUTIOUS_ATTACK: \"PIESARDZĪGS UZBRUKUMS\"\n  STR_STANDARD_ATTACK: \"STANDARTA UZBRUKUMS\"\n  STR_AGGRESSIVE_ATTACK: \"AGRESĪVS UZBRUKUMS\"\n  STR_UFO_CRASH_LANDS: \"NLO CIETA AVĀRIJU NOLAIŽOTIES!\"\n  STR_UFO_RETURN_FIRE: \"NLO ATKLĀJ UGUNI!\"\n  STR_INTERCEPTOR_DAMAGED: \">>> BOJĀTS PĀRTVĒRĒJS<<<\"\n  STR_INTERCEPT: \"PĀRTVERT\"\n  STR_BASES: \"BĀZES\"\n  STR_OPTIONS_UC: \"IZVĒLES\"\n  STR_FUNDING_UC: \"FINANSĒJUMS\"\n  STR_1_MINUTE: \"1 min.\"\n  STR_30_MINUTES: \"30 min.\"\n  STR_1_HOUR: \"1 Stunda\"\n  STR_1_DAY: \"1 Diena\"\n  STR_ENTER_NAME: \"Ievadiet vārdu\"\n  STR_PERFORMANCE_RATING: \"Snieguma Reitings\"\n  STR_VICTORY_DATE: \"Uzvaras Datums\"\n  STR_ELECTRO_FLARE_UFOPEDIA: \"Šī kompaktā ierīce rada spožu gaismas uzliesmojumu, kad tās ir aizmesta. Tā izcels ienaidnieku vienības kuras atrodas elektro-raķetes tuvumā, nakts laika misijās.\"\n  STR_CRAFT_RENTAL: \"Lidaparātu Noma\"\n  STR_SALARIES: \"Algas\"\n  STR_COST_PER_UNIT: \"Vienas vienības izmaksa\"\n  STR_QUANTITY: \"Skaits\"\n  STR_REAR_ARMOR: \"Aizmugures bruņas\"\n  STR_UNDER_ARMOR: \"Apakš Bruņas\"\n  STR_ROUNDS: \"Lādiņi\"\n  STR_UNIT: \"VIENĪBA> {0}\"\n  STR_ENERGY: \"ENERGIJA\"\n  STR_MORALE: \"MORĀLE\"\n  STR_FRONT_ARMOR_UC: \"PRIEKŠAS BRUŅAS\"\n  STR_REAR_ARMOR_UC: \"MUGURAS BRUŅAS\"\n  STR_SKILLS: \"IEMAŅAS> {0}\"\n  STR_HEAD: \"GALVA\"\n  STR_TORSO: \"TORSS\"\n  STR_LEFT_ARM: \"KREISĀ ROKA\"\n  STR_LEFT_LEG: \"KREISĀ KĀJA\"\n  STR_PAIN_KILLER: \"PRETSĀPJU LĪDZEKLIS\"\n  STR_HEAL: \"VESEĻOT\"\n  STR_ALIEN_ARTIFACT: \"Citplanētiešu Artifakts\"\n  STR_THROW: \"Mest\"\n  STR_AUTO_SHOT: \"Auto-šaušana\"\n  STR_STUN: \"Apdullināt\"\n  STR_USE_SCANNER: \"Izmantot skeneri\"\n  STR_USE_MEDI_KIT: \"Izmantot aptieciņu\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Nepietiek laika vienības!\"\n  STR_NO_AMMUNITION_LOADED: \"Munīcija nav ielādēta!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"Ierocis jau ir uzlādēts!\"\n  STR_GRENADE_IS_ACTIVATED: \"Granāta aktivizēta!\"\n  STR_THERE_IS_NO_ONE_THERE: \"Tur nav neviens!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Nevar izmantot citplanētiešu artefaktu kamēr tas nav izpētīts!\"\n  STR_OUT_OF_RANGE: \"Ārpus diapazonas!\"\n  STR_UNABLE_TO_THROW_HERE: \"Tur nevar mest!\"\n  STR_SET_TIMER: \"Uzlikt Taimeri\"\n  STR_HIDDEN_MOVEMENT: \"PASLĒPTĀ KUSTĪBA\"\n  STR_TURN: \"KĀRTA> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Nospiediet pogu lai turpinātu\"\n  STR_MIND_CONTROL: \"Prāta kontrole\"\n  STR_PANIC_UNIT: \"Izsaukt paniku\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Prāta kontrole sekmīga\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}kļuvis ļoti dusmīgs\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}kļuvis ļoti dusmīgs\"\n  STR_HAS_PANICKED_MALE: \"{0} {NEWLINE} ir panikā\"\n  STR_HAS_PANICKED_FEMALE: \"{0} {NEWLINE} ir panikā\"\n  STR_ALIENS: \"Citplanētieši\"\n  STR_RIGHT_HAND: \"LABĀ ROKA\"\n  STR_LEFT_HAND: \"KREISĀ ROKA\"\n  STR_RIGHT_SHOULDER: \"LABAIS PLECS\"\n  STR_BACK_PACK: \"MUGURSOMA\"\n  STR_BELT: \"JOSTA\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}ir zem citplanētiešu kontroles\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}ir zem citplanētiešu kontroles\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0} {NEWLINE} nomira no letālajām brūcēm\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0} {NEWLINE} nomira no letālajām brūcēm\"\n  STR_FATAL_WOUNDS: \"LETĀLIE IEVAINOJUMI\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Laika Vienības rezervētas priekš (snap shot)\"\n  STR_UNLOAD_CRAFT: \"Izkraut\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}tika nogalināts(a)\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}tika nogalināts(a)\"\n  STR_LIVING_QUARTERS_PLURAL: \"Dzīvesvietas\"\n  STR_POWER_SUIT_UFOPEDIA: \"Jauna, spēcīga aizsardzība karavīriem, šīs bruņas darbina Eleriuma enerģijas avots un ievērojami pastiprina valkātāja ātrumu un izturību, tas piedāvā vislabāko aizsardzību kaujas vienībām.\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"Visi citplanētieši tika nogalināti avārijā, {NEWLINE} Auto atgūšanas uzsākta\"\n  MAP_CULTA: \"Ferma\"\n  MAP_FOREST: \"Mežs\"\n  MAP_MOUNT: \"Kalns\"\n  MAP_POLAR: \"Polārs\"\n  MAP_UBASE: \"Citplanētiešu bāze\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Abām rokām jābūt tukšām!\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/nl.yml",
    "content": "nl:\n  STR_AVENGER_UFOPEDIA: \"TRANSPORT- EN GEVECHTSRUIMTEVAARTUIG. DE ULTIEME REPLICATIE VAN BUITENAARDSE TECHNOLOGIE.\"\n  STR_INTERCEPTOR_UFOPEDIA: \"GEVECHTSVLIEGTUIG MET DUBBELE-PULSONTSTEKINGSMOTOREN EN SPECIAAL AFGESCHERMDE ELEKTRONICA. DE BEST BESCHIKBARE TECHNOLOGIE OP AARDE.\"\n  STR_LIGHTNING_UFOPEDIA: \"TRANSPORT- EN GEVECHTSVLIEGTUIG. EEN SIMPELE MAAR EFFECTIEVE REPLICATIE VAN BUITENAARDSE AANDRIJFSYSTEMEN.\"\n  STR_SKYRANGER_UFOPEDIA: \"TRANSPORTVLIEGTUIG. DE SNELSTE IN Z'N SOORT, MET MOGELIJKHEID TOT VERTICAAL OPSTIJGEN EN LANDEN.\"\n  STR_FIRESTORM_UFOPEDIA: \"GEVECHTSVLIEGTUIG. DIT EENPERSOONSVLIEGTUIG IS GEBOUWD NAAR DE KLASSIEKE VLIEGENDE SCHOTEL, MET EEN CENTRALE STUWMOTOR.\"\n  STR_STINGRAY_UFOPEDIA: \"GEAVANCEERDE LUCHT-LUCHTRAKET MET SPECIAAL AFGESCHERMDE ELEKTRONICA.\"\n  STR_AVALANCHE_UFOPEDIA: \"LUCHT-LUCHT RAKET MET KERNKOP, VRIJ ZWAAR EN LOG.\"\n  STR_CANNON_UFOPEDIA: \"KRACHTIG KANON DAT KOGELS AFVUURT DIE PANTSERS TOT 30CM STAAL KUNNEN DOORBOREN.\"\n  STR_FUSION_BALL_UFOPEDIA: \"DIT WAPEN VUURT EEN BOLVORMIG PROJECTIEL AF, VOORTGESTUWD DOOR EEN ANTIMATERIE-REACTIE. DE BOL VERNIETIGT HET DOEL MIDDELS EEN ZWAARTEKRACHTIMPLOSIE.\"\n  STR_LASER_CANNON_UFOPEDIA: \"DEZE CONVENTIONELE LASERSTRAAL WORDT GEVOED DOOR EEN ANTIMATERIE-REACTIE.\"\n  STR_PLASMA_BEAM_UFOPEDIA: \"DE PLASMASTRAAL LEIDT EEN FIJN GEKANALISEERDE ZWAARTEKRACHT-IMPLOSIE.\"\n  STR_SECTOID_UFOPEDIA: \"De hiërarchie der Sectoïden loopt van soldaten tot leiders met sterke psionische krachten. Met deze krachten kunnen ze soldaten demoraliseren tijdens een gevecht, of zelfs controle nemen over hun geest. Ze leven zich graag uit met het ontvoeren van mensen en het verminken van vee. Bij de ontvoeringen wordt genetisch materiaal onttrokken voor het maken van een bastaardras en het ontwikkelen van klonen om zo de menselijke samenleving te infiltreren. Het vee biedt voedsel en genetisch materiaal. Dit ras lijkt superieure genetische hybriden te willen ontwikkelen om de efficiëntie van hun zwermachtige samenleving te vergroten.\"\n  STR_SECTOID_AUTOPSY: \"Autopsie van Sectoïde\"\n  STR_SECTOID_AUTOPSY_UFOPEDIA: \"De autopsie toont rudimentaire spijsverteringsorganen en een eenvoudige structuur. De hersenen en ogen zijn zeer goed ontwikkeld. De structuur suggereert genetische manipulatie of mutatie. De kleine mond en neus lijken weinig functie hebben. De vliezen tussen de vingers, en de platte voeten suggereren een oorsprong onder water. Er zijn geen voortplantingsorganen, en geen aanwijzingen over hoe deze soort zich kan voortplanten. Ze zijn zeer waarschijnlijk een genetisch gemanipuleerde soort.\"\n  STR_SNAKEMAN_UFOPEDIA: \"Dit ras ontwikkelde zich in een zeer vijandige omgeving. Ze zijn extreem gehard en bestand tegen extreme temperatuurschommelingen. Ze bewegen zich voort op de grote slang-achtige 'voet', die tevens alle vitale organen beschermt. Hun instinct lijkt puur roofzuchtig, mogelijk onder het bevel van één of andere Intelligentie die hun strategische invallen op aarde coordineert.\"\n  STR_SNAKEMAN_AUTOPSY: \"Autopsie van Slangeman\"\n  STR_SNAKEMAN_AUTOPSY_UFOPEDIA: \"De huid is zeer taai en hittebestendig. Hun hart- en vaatstelsel maakt deel uit van het spierstelsel dat een hydraulisch principe gebruikt om beweging te creëren. De enige echte spier is het 'hart'. Het voortplantingssysteem lijkt zeer efficiënt. Voortplanting is aseksueel, met tot vijftig eitjes die door elk exemplaar worden meegedragen. Overgelaten aan haar lot zou deze soort een ernstige bedreiging vormen voor het leven op aarde.\"\n  STR_ETHEREAL_UFOPEDIA: \"Deze wezens hebben ontzagwekkende mentale krachten, welke hun in staat stellen tot telepathie en telekinese. De schijnbaar zwakke fysieke vaardigheden van dit schepsel worden ondersteund door haar mentale krachten. We begrijpen niet hoe deze telekinetische krachten werken, omdat ze tegen alle bekende natuurkundige wetten lijken in te gaan. Ze zijn extreem gevaarlijk in gevechtssituaties, waarbij ze hun mentale krachten in de strijd gooien. Ze verschijnen zelden op aarde, omdat ze lijken te vertrouwen op andere rassen om hun doelstellingen te verwezenlijken.\"\n  STR_ETHEREAL_AUTOPSY: \"Autopsie van Etheriër\"\n  STR_ETHEREAL_AUTOPSY_UFOPEDIA: \"Dit wezen is lichamelijk achtergebleven en lijkt amper levensvatbaar. De spieren zijn ernstig verschrompeld en de inwendige organen lijken onderontwikkeld. De zintuigen, waaronder ook de ogen, lijken helemaal niet te werken. De hersenen zijn echter goed ontwikkeld en hebben een hoge bloedtoevoer ten opzichte van de rest van het lichaam. Het is een raadsel hoe dit schepsel stand kan houden zonder enige vorm van externe ondersteuning.\"\n  STR_MUTON_UFOPEDIA: \"Dit mensachtige wezen is fysiek sterk en intelligent. Ze hebben een voorkeur voor consumptie van rauw vlees van welke aard ook, wat ze nodig hebben als voedsel net als bij carnivoren zoals wij die kennen. Ze vertrouwen op telepathische opdrachten van een ras bekend als de 'Etheriërs'.  Eenmaal gescheiden van deze telepathische band lijkt hun mentale systeem af te breken en sterven ze.  De implantaten worden gebruikt om hun vechtprestaties te verbeteren. Zij zijn duidelijk het voetvolk voor een hogere intelligentie.\"\n  STR_MUTON_AUTOPSY: \"Autopsie van Muton\"\n  STR_MUTON_AUTOPSY_UFOPEDIA: \"De 'huid' van dit schepsel lijkt een organisch beschermend harnas, dat geënt is op het lichaam. Er zijn tal van cybernetische implantaten die gebruikt worden om het hart- en vaatstelsel en de zintuigen te verbeteren. De voortplantingsorganen lijken operatief te zijn verwijderd. Deze ongelukkige wezens zijn beperkt tot een leven van oorlog en verovering. Pantserdoorborende munitie is niet erg doeltreffend tegen hun geharde huid.\"\n  STR_CELATID_UFOPEDIA: \"Deze levensvorm heeft het mysterieuze natuurlijke vermogen om te zweven door de lucht. Het lijkt menselijke hersengolven op te sporen en te volgen. Zodra een doelwit wordt gedetecteerd, landt de Celatide en vuurt kleine bolletjes extreem bijtend gif af. Het wezen heeft het vermogen om zichzelf te klonen in een alarmerend tempo. Het begeleidt het Muton ras in zijn zoektocht.\"\n  STR_CELATID_AUTOPSY: \"Autopsie van Celatide\"\n  STR_CELATID_AUTOPSY_UFOPEDIA: \"De kern bevat een klein bio-mechanisch apparaat welk een natuurlijk geëvolueerde anti-zwaartekrachtaandrijving lijkt te zijn. De gifzak is het grootste orgaan en er lijkt geen aparte hersenstructuur te zijn. Er zijn geen waarneembare spijsverterings- of voortplantingsorganen. Een klein orgaan bevat embryo's die snel kunnen uitgroeien tot een nieuw wezen.\"\n  STR_SILACOID_UFOPEDIA: \"Deze silicium-gebaseerde levensvorm genereert een enorme hoeveelheid warmte. Het heeft de kracht om rotsen te verpletteren die vervolgens kunnen worden opgenomen in de hete kern. Het heeft een primitieve vorm van intelligentie en wordt geleid door implantaten of telepathische wezens. Het werkt samen met de Mutons.\"\n  STR_SILACOID_AUTOPSY: \"Autopsie van Silacoïde\"\n  STR_SILACOID_AUTOPSY_UFOPEDIA: \"De kern van het schepsel is extreem heet en lijkt de basis voor een spijsverteringssysteem. Zijn unieke spierenstelsel heeft een enorme kracht en snelheid. Zijn rotsachtige huid is niet aantastbaar door vuur of ontvlambare munitie.\"\n  STR_CHRYSSALID_UFOPEDIA: \"De krab-achtige scharen van dit schepsel zijn een krachtig wapen in lijf-aan-lijfgevechten.  De snelle stofwisseling en de kracht van dit schepsel zorgen voor snelheid en behendigheid.  In plaats van zijn slachtoffers te doden, bevrucht het ze met een eitje en injecteert een gif waarmee ze in wandelende zombies veranderen. Een nieuwe Chrysalide zal kort na bevruchting uit het slachtoffer barsten. Chrysaliden zijn geassocieerd met het Slangeman-ras.\"\n  STR_CHRYSSALID_AUTOPSY: \"Autopsie van Chrysalide\"\n  STR_CHRYSSALID_AUTOPSY_UFOPEDIA: \"Het uitwendig skelet van dit schepsel is extreem gehard, maar verrassend kwetsbaar voor explosieve munitie. De hersenen zijn goed ontwikkeld, en het heeft een hoge mate van celgroei. Het weezn draagt twintig eitjes welke in andere organismen worden gelegd. Dit wezen is een zeer effectief terreurwapen.\"\n  STR_FLOATER_UFOPEDIA: \"De Zwevers zijn voornamelijk soldaten en terreuragenten. Ze zijn natuurlijke roofdieren, genetisch gemanipuleerd en cybernetisch verbeterd tot formidabele strijders. Het onderste gedeelte van het lichaam en de meeste interne organen zijn chirurgisch verwijderd, en een levensinstandhoudingssysteem is ingebouwd. Dit implantaat bevat een anti-zwaartekrachteenheid wat dit wezen in staat stelt om, hoewel instabiel, te zweven door de lucht.\"\n  STR_FLOATER_AUTOPSY: \"Autopsie van Zwever\"\n  STR_FLOATER_AUTOPSY_UFOPEDIA: \"Dit schepsel is drastisch veranderd door middel van chirurgie. Het apparaat welk de kern van het lichaam lijkt te zijn is een levensinstandhoudingssysteem, welk de functies van hart, longen en spijsverteringssysteem overneemt. Dit zou het in staat stellen om te kunnen overleven in vijandige omgevingen. Het brein is kleiner dan het onze, maar de zintuigen zijn goed ontwikkeld.\"\n  STR_REAPER_UFOPEDIA: \"Deze tweevoetige carnivoor heeft krachtige kaken en een vraatzuchtige eetlust. Het heeft een aantal hersenimplantaten waarmee zijn activiteiten worden gecontroleerd. De primitieve roofinstincten van dit wezen hebben weinig nut behalve om te terroriseren en te vernietigen. Vreters worden vaak geassocieerd met Zwevers.\"\n  STR_REAPER_AUTOPSY: \"Autopsie van Vreter\"\n  STR_REAPER_AUTOPSY_UFOPEDIA: \"De Vreter bevat twee stel 'hersens' en twee 'harten' welke ervoor zorgen dat deze zelfs kan functioneren als hij zwaargewond is.  Echter, zijn bonte vacht is hoogst ontvlambaar, waardoor dit schepsel kwetsbaar is voor brandwapens.\"\n  STR_SECTOPOD_UFOPEDIA: \"Sectopods zijn robotwezens met een krachtig laserstraalwapen. Deze mechanische beesten worden bestuurd met behulp van een telepathische link met hun bestuurders, de Ethereals. Sectopods zijn de krachtigste terreurwapens die de alientroepen hebben.\"\n  STR_SECTOPOD_AUTOPSY: \"Autopsie van Sectopod\"\n  STR_SECTOPOD_AUTOPSY_UFOPEDIA: \"De robot is stevig gebouwd met een krachtig pantser wat de meeste soorten aanvallen kan weerstaan, plasmawapens in het bijzonder. Echter, de bedrading van het zintuiglijk systeem lijkt bijzonder kwetsbaar voor laserwapens.\"\n  STR_CYBERDISC_UFOPEDIA: \"Deze miniatuur-vliegende schotel is een geautomatiseerd terreurwapen uitgerust met een krachtige plasmastraal. De anti-zwaartekrachtaandrijving is een groot voordeel op zwaar terrein. De primaire functie is vernietiging en terreur tot dienst van het ras der Sectoïden.\"\n  STR_CYBERDISC_AUTOPSY: \"Autopsie van Cyberschijf\"\n  STR_CYBERDISC_AUTOPSY_UFOPEDIA: \"De Cyberschijf is goed afgeschermd en is zeer goed bestand tegen explosieve munitie.  Het primaire anti-zwaartekrachtsysteem is te zwaar beschadigd om een goed beeld te krijgen van hoe het functioneert.\"\n  STR_UFO_POWER_SOURCE_UFOPEDIA: \"De energiebron van buitenaardse vaartuigen is een antimaterie-reactor welke gebruik maakt van Elerium (element 115) om krachtige zwaartekrachtgolven alsook andere vormen van energie te genereren. De conversie van materie naar energie behaalt een indrukwekkend rendement van 99%, dus uiterst kleine hoeveelheden Elerium kunnen een gigantische hoeveelheid energie produceren. Deze eenheid kan eenvoudig worden geproduceerd met behulp van buitenaardse legeringen.\"\n  STR_UFO_NAVIGATION_UFOPEDIA: \"Buitenaardse voertuigen gebruiken geavanceerde computers om over de aarde en door het heelal te navigeren.  Het systeem is gebaseerd op optische processoren die als netwerk zijn opgesteld. De besturingsinterface is relatief eenvoudig - de navigator bestuurt de richting van de zwaartekrachtsgolven die door de energiebron worden gegenereerd om het schip een bepaalde richting op te sturen. Dit systeem kan eenvoudig door mensen bestuurd worden en kan worden nagebouwd door gebruik te maken van buitenaardse legeringen en andere componenten.\"\n  STR_UFO_CONSTRUCTION_UFOPEDIA: \"Buitenaardse voertuigen bestaan uit drie hoofdonderdelen - een energiebron, een navigatiesysteem en een romp gemaakt van buitenaardse legeringen.  De romp is speciaal ontworpen om zwaartekrachtsgolven te buigen en beheersen. Verder is een kleine hoeveelheid Elerium nodig als brandstof voor de energiebron.  Wanneer we de constructieprincipes begrijpen en weten wat de functie van ieder component is, kunnen we dit type voertuig bouwen.\"\n  STR_ALIEN_FOOD_UFOPEDIA: \"Deze ruimtes bevatten verscheidene enzymen welke gebruikt worden om de lichaamsdelen van vee, andere dieren en zelfs van mensen te verteren.  De vloeistof wordt vervolgens als voorverteerd voedsel geconsumeerd - waarschijnlijk rechtstreeks de bloedbaan in.  Dit suggereert een bepaalde afhankelijkheid op de aarde voor voedsel - een symbiose tussen de aarde en de buitenaardse maatschappij.\"\n  STR_ALIEN_REPRODUCTION_UFOPEDIA: \"Deze ruimtes bevatten buitenaardse foetussen.  Het ontwerp van deze vaten lijkt te suggereren dat de buitenaardsen die dit proces gebruiken volledig afhankelijk zijn van laboratoria voor hun voortplanting.  De rijke voedingsstoffen zorgen voor snelle ontwikkeling van de foetussen.  Dit systeem van lopende bandwerk zou in korte tijd duizenden buitenaardse klonen kunnen produceren.  Het proces zou eenvoudig aangepast kunnen worden voor de voortplanting van mensen of mens-buitenaardse hybriden.\"\n  STR_ALIEN_ENTERTAINMENT_UFOPEDIA: \"De meest waarschijnlijke functie van deze bollen is recreatief.  De psionische bedrading stimuleert verscheidene punten in het brein.  Het effect is vergelijkbaar met hallucinogene drugs.  Dit is het enige bewijs dat buitenaardsen enig cultureel of recreatief tijdsverdrijf hebben.\"\n  STR_ALIEN_SURGERY_UFOPEDIA: \"Dit chirurgische gereedschap gebruikt lasersnijders om bepaalde lichaamsdelen te verwijderen uit vee en andere dieren.  De wijdverbreide verminkingen van van vee kunnen worden verklaard aan de hand van deze bizarre praktijken.  Waarschijnlijk worden deze lichaamsdelen gebruikt als voedsel of voor genetische doeleinden.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"In het verleden beweerden duizenden mensen dat ze zijn ontvoerd door buitenaardse wezens, soms zelfs herhaaldelijk.  De waarheid is veel afschuwelijker.  Mensen worden ontvoerd, onderzocht en in de gaten gehouden.  Van de beste exemplaren wordt genetisch materiaal genomen.  Bij vrouwen wordt mens-buitenaardse hybride foetussen geïmplanteerd, en enkele maanden later weer verwijderd.  Wie weet wat voor duistere motieven de buitenaardsen hebben?\"\n  STR_ALIEN_ALLOYS_UFOPEDIA: \"Buitenaardse voertuigen worden gebouwd uit speciale legeringen met unieke eigenschappen.  Ze zijn extreem licht en bestendig, en kunnen worden gevormd middels electro-magnetische methoden.  Dit materiaal kan worden gereproduceerd en gebruikt in verscheidene productieprocessen.\"\n  STR_ELERIUM_115_UFOPEDIA: \"Dit element heeft de ongebruikelijke eigenschap dat het antimaterie-energie genereert wanneer het wordt gebombardeerd met bepaalde deeltjes.  Dit creëert zwaartekrachtsgolven en andere soorten energie.  Dit komt niet natuurlijk voor in ons zonnestelsel en kan niet worden gereproduceerd.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"Het is duidelijk dat we de oorlog op aarde aan het verliezen zijn.  De buitenaardse hordes zijn overweldigend in aantal.  Het beste wat we kunnen doen is hun voortgang vertragen.  De enige hoop voor de mensheid is om de buitenaardsen aan te pakken bij de bron.  Ons onderzoek lijkt te wijzen op een uitvalsbasis in de buurt, in ons zonnestelsel.  Buitenaardsen geven aan dat dit het centrum is van een oeroude beschaving die bestond vóór de mensheid.  We moeten deze plek zo spoedig mogelijk zien te vinden.  Echter, we moeten een buitenaardse leider gevangen weten te nemen en te ondervragen om meer gedetailleerde informatie te achterhalen.  De grotere UFO's bevatten waarschijnlijk minstens één buitenaardse leider.\"\n  STR_THE_MARTIAN_SOLUTION_UFOPEDIA: \"Ons onderzoek is nu gericht naar Mars op basis van alien operaties. De basis is goed verstopt, en heeft alle fabricage en kloonfaciliteiten om de infiltratie van aarde te tanken. Het blijkt ook het een controlerende computer te hebben die de hele operatie controleerd. Het lijkt dat de net-kolonie alien groep een soort 'bijen koningin' heeft. Dit is hun findamentele zwakte - als we de 'hersens' kunnen uitschakelen, dan zal het lichaam sterven. We moeten ons onderzoek snel afmaken voor het te laat is. Om dat de kunnen doen moeten we de sterkste aliens ontvoeren - de commandanten - die komen alleen voor in alien basis en gevechtsschepen.\"\n  STR_CYDONIA_OR_BUST_UFOPEDIA: \"Het is nu duidelijk dat de buitenaardse hordes worden aangestuurd vanuit een ondergrondse basis in Cydonia - dit is een ongewoon gebied op Mars met vijfzijdige piramides en een grote rotsformatie gelijkend op een menselijk gezicht.  Ooit floreerde een Cydonische beschaving op Mars, vele miljoenen jaren geleden, maar we weten niet waarom deze uitstierf of wat het verband is met de laatste buitenaardse activiteit in dat gebied.  Ongeacht de verklaring, we moeten een expeditie naar Cydonia sturen.  Dit is de enige manier waarop we de buitenaardsen kunnen verslaan.  We moeten het aansturende 'meesterbrein' vernietigen.  We zullen een Wreker-voertuig nodig hebben, uitgerust met de meest ontzagwekkende vernietigingskracht die we tot onze beschikking hebben.  We kunnen niets meer leren - we moeten afwachten wat de uitslag is van de bestorming op Cydonia.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"CENTREREN OP LOCATIE-TIJD=5 Sec\"\n  STR_CANCEL_UC: \"ANNULEREN\"\n  STR_NONE: \"Geen\"\n  STR_UNKNOWN: \"Onbekend\"\n  STR_POOR: \"Zwak\"\n  STR_AVERAGE: \"Gemiddeld\"\n  STR_GOOD: \"Goed\"\n  STR_EXCELLENT: \"Uitstekend\"\n  STR_BUILD_NEW_BASE_UC: \"NIEUWE BASIS BOUWEN\"\n  STR_BASE_INFORMATION: \"BASIS-INFORMATIE\"\n  STR_EQUIP_CRAFT: \"VAARTUIG UITRUSTEN\"\n  STR_BUILD_FACILITIES: \"FACILITEITEN BOUWEN\"\n  STR_RESEARCH: \"ONDERZOEK\"\n  STR_MANUFACTURE: \"PRODUCTIE\"\n  STR_TRANSFER_UC: \"OVERPLAATSINGEN\"\n  STR_PURCHASE_RECRUIT: \"AANKOPEN/WERVEN\"\n  STR_SACK: \"ONSLAAN\"\n  STR_SELL_SACK_UC: \"VERKOPEN/ONTSLAAN\"\n  STR_GEOSCAPE_UC: \"GLOBE\"\n  STR_NAME: \"Naam\"\n  STR_AREA: \"Gebied\"\n  STR_BUILD_NEW_BASE: \"Nieuwe Basis Bouwen\"\n  STR_CANCEL: \"Annuleer\"\n  STR_COST_UC: \"PRIJS>\"\n  STR_CONSTRUCTION_TIME_UC: \"BOUWTIJD>\"\n  STR_DAY:\n    one: \"{N} dag\"\n    other: \"{N} dagen\"\n  STR_HOUR:\n    one: \"{N} uur\"\n    other: \"{N} uren\"\n  STR_MAINTENANCE_UC: \"ONDERHOUD>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Installatie\"\n  STR_CURRENT_RESEARCH: \"HUIDIG ONDERZOEK\"\n  STR_SCIENTISTS_AVAILABLE: \"Onderzoekers Beschikbaar>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Onderzoekers Toegewezen>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Laboratorium Ruimte Beschikbaar>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"ONDERZOEKSPROJECT\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"TOEGEWEZEN WETENSCHAPPERS\"\n  STR_PROGRESS: \"VOORTGANG\"\n  STR_NEW_PROJECT: \"Nieuw Project\"\n  STR_CANCEL_PROJECT: \"PROJECT ANNULEREN\"\n  STR_NEW_RESEARCH_PROJECTS: \"NIEUWE ONDERZOEKSPROJECTEN\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"ONDERZOEKERS BESCHIKBAAR>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"LABORATORIUMRUIMTE BESCHIKBAAR>{ALT}{0}\"\n  STR_INCREASE: \"Verhogen\"\n  STR_DECREASE: \"Verlagen\"\n  STR_START_PROJECT: \"PROJECT STARTEN\"\n  STR_CURRENT_PRODUCTION: \"HUIDIGE PRODUCTIE\"\n  STR_ENGINEERS_AVAILABLE: \"Ingenieurs Beschikbaar>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Ingenieurs Toegewezen>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Werkplaats Ruimte Beschikbaar>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Beschikbare Middelen>{ALT}{0}\"\n  STR_ITEM: \"ARTIKEL\"\n  STR_ENGINEERS__ALLOCATED: \"Ingenieurs Toegewezen\"\n  STR_UNITS_PRODUCED: \"Eenheden Geproduceerd\"\n  STR_TOTAL_TO_PRODUCE: \"Totaal nog te produceren\"\n  STR_COST__PER__UNIT: \"Prijs{NEWLINE}per{NEWLINE}Eenheid\"\n  STR_DAYS_HOURS_LEFT: \"Resterende dagen/uren\"\n  STR_NEW_PRODUCTION: \"Nieuwe Productie\"\n  STR_PRODUCTION_ITEMS: \"Productie-artikelen\"\n  STR_CATEGORY: \"CATEGORIE\"\n  STR_START_PRODUCTION: \"START PRODUCTIE\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} Ingenieur uren om een object the maken\"\n  STR_COST_PER_UNIT_: \"Kosten per eenheid>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Werkplaats nodig>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"SPECIALE MATERIALEN VEREIST\"\n  STR_ITEM_REQUIRED: \"ARTIKEL NODIG\"\n  STR_UNITS_REQUIRED: \"EENHEDEN NODIG\"\n  STR_UNITS_AVAILABLE: \"EENHEDEN BESCHIKBAAR\"\n  STR_STOP_PRODUCTION: \"STOP PRODUCTIE\"\n  STR_ENGINEERS_AVAILABLE_UC: \"INGENIEURS BESCHIKBAAR>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"WERKPLAATSRUIMTE BESCHIKBAAR>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"MAANDELIJKSE WINST>{ALT}{0}\"\n  STR_INCREASE_UC: \"VERHOOG\"\n  STR_DECREASE_UC: \"VERLAAG\"\n  STR_UNITS_TO_PRODUCE: \"Eenheden nog te produceren\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Aankoop/Werving van Personeel\"\n  STR_COST_OF_PURCHASES: \"Kosten van aankopen>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"PRIJS PER STUK\"\n  STR_QUANTITY_UC: \"AANTAL\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"BESCHIKBAAR PERSONEEL:TOTAAL PERSONEEL>\"\n  STR_SOLDIERS: \"Soldaten\"\n  STR_SCIENTISTS: \"Wetenschappers\"\n  STR_ENGINEERS: \"Ingenieurs\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"GEBRUIKTE RUIMTE:BESCHIKBARE RUIMTE>\"\n  STR_LIVING_QUARTERS: \"Leefruimtes\"\n  STR_STORES: \"Opslag\"\n  STR_LABORATORIES: \"Laboratoria\"\n  STR_WORK_SHOPS: \"Werkplaatsen\"\n  STR_HANGARS: \"Loodsen\"\n  STR_SHORT_RANGE_DETECTION: \"Detectie Korte Afstand\"\n  STR_DEFENSE_STRENGTH: \"Sterkte Defensie\"\n  STR_TRANSFERS_UC: \"OVERPLAATSINGEN\"\n  STR_TRANSFERS: \"Overplaatsingen\"\n  STR_ARRIVAL_TIME_HOURS: \"Aankomsttijd (uren)\"\n  STR_COST_: \"Kosten>{ALT}{0}\"\n  STR_AREA_: \"Gebied>{ALT}{0}\"\n  STR_BASE_NAME: \"Basisnaam?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"KIES POSITIE TOEGANGSLIFT\"\n  STR_TRANSFER: \"Overplaatsen\"\n  STR_AMOUNT_TO_TRANSFER: \"HOEVEELHEID OVER TE PLAATSEN\"\n  STR_SELECT_DESTINATION_BASE: \"Selecteer Doelbasis\"\n  STR_COST: \"Kostprijs\"\n  STR_VICTORY_1: \"De kamer binnenkomend zie je het buitenaardse brein - het doel van je zoektocht.  Voordat je kunt vuren communiceert het met je via een scherm aan het voetstuk.  Het smeekt je te luisteren naar zijn overlevingspleidooi voordat je de beslissing neemt om de trekker over te halen...\"\n  STR_VICTORY_2: \"Het brein spreekt: 'Vele miljoenen jaren geleden leefde de planeet die jullie Mars noemen.  Dit leven was door onze beschaving naar deze dorre planeet gebracht, net zoals naar die van jullie.  Gedurende miljoenen jaren bezochten we jullie planeet en ontwikkelden jullie soort op genetische wijze.  Jullie kunnen ons niet vernietigen, jullie zijn onderdeel van ons...'\"\n  STR_VICTORY_3: \"Hier is het centrum van Martiaanse beschaving - de piramiden die miljoenen jaren zijn gebouwd voor die van jullie - door een soort die jullie voorouder is.  Geen planeet valt buiten onze greep.  Deze macht kan binnenkort van jullie zijn.  We vragen enkel jullie medewerking...'\"\n  STR_GAME_OVER_1: \"De buitenaardsen trachten de volledige mensheid uit te roeien, vernietigen steden en vergiftigen de lucht en de zee.  Het verzet van de aardse legers is zinloos ten opzichte van de enorm superieure technologie.  De overlevende generaties lijden onder vreselijke mutaties terwijl ze vluchten voor vernietiging door buitenaardsen.  Ze worden bijeen gedreven in slavenkampen om te helpen de aarde om te vormen naar een buitenaardse kolonie welke onderdeel is van een of ander onbekend rijk.\"\n  STR_GAME_OVER_2: \"De kennis verworven met het X-Com project is voor altijd verloren. Je hebt gefaald om de aarde te redden.\"\n  STR_VICTORY_4: \"Het buitenaardse brein wordt onderbroken door een salvo heet plasma, en de volledige buitenaardse krijgsmacht is verslagen.\"\n  STR_VICTORY_5: \"Eenmaal Mars verloren hebben de buitenaardsen de Aarde verloren. Uiteindelijk zou het X-Com onderzoek er voor zorgen dat mensheid weer opnieuw kon opbloeien om Mars voor zichzelf te kunnen opeisen. De buitenaardse bedreiging is verdwenen, maar voor hoe lang, dat weet niemand... \"\n  STR_YOU_HAVE_FAILED: \"Je de buitenaardse aanval niet kunnen tegenhouden.  De geldschietende naties tekenen één voor één verdragen met de buitenaardsen waarin technologie, voorspoed en vrede wordt beloofd.  Maar al snel wordt duidelijk dat ze andere plannen hebben...\"\n  STR_TOTAL_UC: \"TOTAAL\"\n  STR_INCOME: \"Inkomsten\"\n  STR_EXPENDITURE: \"Uitgaven\"\n  STR_MAINTENANCE: \"Onderhoud\"\n  STR_BALANCE: \"Balans\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"UFO-Activiteit in Gebieden\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"UFO-Activiteit in Landen\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"X-Com Activiteit in Gebieden\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"X-Com Activiteit in Landen\"\n  STR_FINANCE: \"Financiën\"\n  STR_DATE_FIRST: \"{0}ste\"\n  STR_DATE_SECOND: \"{0}de\"\n  STR_DATE_THIRD: \"{0}de\"\n  STR_DATE_FOURTH: \"{0}de\"\n  STR_FINANCE_THOUSANDS: \"$1000's\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Niet genoeg speciale materialen om{NEWLINE}{0}{NEWLINE}bij{NEWLINE}{1}te produceren\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Niet genoeg geld om{NEWLINE}{0}{NEWLINE}bij{NEWLINE}{1}te produceren\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"De productie van{NEWLINE}{0}{NEWLINE}bij{NEWLINE}{1}{NEWLINE}is compleet\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"De bouw van{NEWLINE}{0}{NEWLINE}op{NEWLINE}{1}{NEWLINE}is compleet\"\n  STR_OK_5_SECONDS: \"OK - 5 sec\"\n  STR_RESEARCH_COMPLETED: \"Onderzoek Voltooid\"\n  STR_VIEW_REPORTS: \"RAPPORT INZIEN\"\n  STR_WE_CAN_NOW_RESEARCH: \"Onderzoek mogelijk van\"\n  STR_WE_CAN_NOW_PRODUCE: \"Productie mogelijk van\"\n  STR_SUNDAY: \"ZONDAG\"\n  STR_MONDAY: \"MAANDAG\"\n  STR_TUESDAY: \"DINSDAG\"\n  STR_WEDNESDAY: \"WOENSDAG\"\n  STR_THURSDAY: \"DONDERDAG\"\n  STR_FRIDAY: \"VRIJDAG\"\n  STR_SATURDAY: \"ZATERDAG\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Niet genoeg {0} om {1} bijtetanken bij {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Niet genoeg {0} om {1} te herladen in {2}\"\n  STR_UFO_IS_NOT_RECOVERED: \"UFO werd niet teruggevonden\"\n  STR_UFO_IS_RECOVERED: \"UFO is teruggevonden\"\n  STR_CRAFT_IS_LOST: \"Vaartuig is verloren\"\n  STR_TERROR_CONTINUES: \"Terreur gaat verder\"\n  STR_ALIENS_DEFEATED: \"Buitenaardsen verslagen\"\n  STR_BASE_IS_LOST: \"Basis is verloren\"\n  STR_BASE_IS_SAVED: \"Basis is gered\"\n  STR_ALIEN_BASE_STILL_INTACT: \"Buitenaardse basis nog steeds intact\"\n  STR_ALIEN_BASE_DESTROYED: \"Buitenaardse basis vernietigd\"\n  STR_ALIENS_KILLED: \"BUITENAARDSEN GEDOOD\"\n  STR_ALIEN_CORPSES_RECOVERED: \"TERRUGGEVONDEN BUITENAARDSE LICHAMEN\"\n  STR_LIVE_ALIENS_RECOVERED: \"LEVENDE BUITENAARDSEN TERUGGEVONDEN\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"BUITENAARDSE VOORWERPEN GEVONDEN\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"CONTROLE BUITENAARDSE BASIS VERNIETIGD\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"BURGERS GEDOOD DOOR BUITENAARDSEN\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"BURGERS GEDOOD DOOR X-COM AGENTEN\"\n  STR_CIVILIANS_SAVED: \"BURGERS GERED\"\n  STR_XCOM_OPERATIVES_KILLED: \"X-COM AGENTEN GEDOOD\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"X-COM AGENTEN VERMIST IN ACTIE\"\n  STR_TANKS_DESTROYED: \"TANKS VERNIETIGD\"\n  STR_XCOM_CRAFT_LOST: \"X-COM VOERTUIG VERLOREN\"\n  STR_UFO_RECOVERY: \"BERGING UFO\"\n  STR_ALIEN_BASE_RECOVERY: \"ONTMANTELING BUITENAARDSE BASIS\"\n  STR_BASE_UNDER_ATTACK: \"{0} wordt aangevallen!\"\n  STR_BASE_DEFENSES_INITIATED: \"BASISDEFENSIE GEACTIVEERD\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"ZWAARTEKRACHTSCHILD STOOT UFO AF!\"\n  STR_FIRING: \"VUURT\"\n  STR_HIT: \"RAAK!\"\n  STR_UFO_DESTROYED: \"UFO VERNIETIGD!\"\n  STR_MISSED: \"MIS!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Verkoop/Ontslag van Personeel\"\n  STR_VALUE_OF_SALES: \"WAARDE VAN VERKOOP> {ALT}{0}\"\n  STR_FUNDS: \"GELDMIDDELEN> {ALT}{0}\"\n  STR_SELL_SACK: \"Verkopen/Ontslaan\"\n  STR_VALUE: \"Waarde\"\n  STR_CRAFT_: \"VERVAARDIG> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"BERGING VAN NEERGESTORTE UFO\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"Wees voorzichig - Er zijn mischien nog bemmaningsleden in de UFO of rondom de lokatie van de crash. De Missie is succesvol wanneer alle vijandige eenheden zijn uitgeschakeld. Dan kan het bergen van UFO overblijfselen, buitenaardse artifacten  en lijken worden begonnen. Om de missie af te breken, breng alle X-Com soldaten terug naar het transportvoertuig en klik op de 'Missie afbreken'' icoon.\"\n  STR_UFO_GROUND_ASSAULT: \"AANVAL OP GELANDE UFO\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"Verken de landingsplaats en probeer, wanneer mogelijk, toegang tot de UFO te krijgen. De missie zal succesvol zijn wanneer alle vijandelijke eenheden zijn geëlimineerd of geneutraliseerd. Het herstel van UFO's, artefacten en buitenaardse lijken kan dan worden gestart. Om de missie af te breken, moeten de X-Com-agenten terug worden gebracht naar het transportvoertuig en klikken op de icoon 'Missie afbreken'.\"\n  STR_BASE_DEFENSE: \"VERDEDIGING BASIS\"\n  STR_BASE_UC_: \"BASIS> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"Een buitenaards schip is in de buurt geland. Onze basis is in groot gevaar. Volgens de standaardprocedure zijn al het niet-gevechtspersoneel en X-Com-vaartuigen geëvacueerd. Buitenaardse eenheden komen de basis binnen via hangardeuren of de toegangslift. Verdedig de basis en zijn vitale installaties tegen elke prijs - dit is een gevecht op leven en dood. Wanneer je  op het iccon 'Missie afbreken' klikt, accepteer je de nederlaag toe en je verliest de basis.\"\n  STR_ALIEN_BASE_ASSAULT: \"AANVAL OP BUITENAARDSE BASIS\"\n  STR_ALIEN_BASE_ASSAULT_BRIEFING: \"X-Com-agenten hebben toegang gekregen tot een buitenaardse basis. Het controlecentrum moet worden vernietigd om de basis uit te schakelen. De missie eindigt wanneer alle vijanden zijn uitgeschakeld, of wanneer je squadron is teruggekeerd naar het groene terugkeer zone  (klik op het icoon 'Missie afbreken' om te ontsnappen).\"\n  STR_CYDONIA_BRIEFING: \"Je bent aangekomen in Cydonia.  Je verschaft toegang tot een groot ondergronds complex in de buurt van de Martiaanse Sphinx.  Je moet het Buitenaardse Brein vernietigen dat alle buitenaardse activiteit bestuurt.  Het lot van de mensheid ligt in jouw handen ....\"\n  STR_TERROR_MISSION: \"TERREURMISSIE\"\n  STR_TERROR_MISSION_BRIEFING: \"Missie zal succesvol zijn wanneer alle vijandelijke eenheden zijn gedood of geneutraliseerd. Je moet proberen de levens van alle burgers in het gebied te redden door de buitenaardse dreiging te uit te schakelen. Om de missie af te breken, moet je X-Com-agenten terugbrengen naar het transportvoertuig en dan te klikken op het icoon 'Missie afbreken'.\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"GEEN LOODSEN VRIJ VOOR CONSTRUCTIE VAN VAARTUIG!{SMALLLINE}Elk vaartuig toegewezen of onderweg naar een basis, in aankoop of constructie bezet een loods.  Bouw een nieuwe loods of maak er één vrij.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"GEEN LOODSEN VRIJ VOOR AANKOOP VAN VAARTUIG!{SMALLLINE}Elk vaartuig toegewezen of onderweg naar een basis, in aankoop of constructie bezet een loods.  Bouw een nieuwe loods of maak er één vrij.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"GEEN LOODSEN VRIJ VOOR OVERPLAATSING VAN VAARTUIG!{SMALLLINE}Elk vaartuig toegewezen of onderweg naar een basis, in aankoop of constructie bezet een loods.  Bouw een nieuwe loods of maak er één vrij.\"\n  STR_CANNOT_BUILD_HERE: \"KAN HIER NIET BOUWEN!{SMALLLINE}Je moet naast een bestaande ruimte bouwen.\"\n  STR_NO_FREE_ACCOMODATION: \"GEEN ACCOMODATIE BESCHIKBAAR!{SMALLLINE}De doelbasis heeft niet genoeg leefruimte.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"ONVOLDOENDE WERKPLAATS BESCHIKBAAR!{SMALLLINE}Bouw meer werkplaatsen of verminder werk op andere projecten.\"\n  STR_NOT_ENOUGH_MONEY: \"TE WEINIG GELD!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"NIET GENOEG OPSLAGRUIMTE!{SMALLLINE}Bouw nieuwe opslagruimte of maak ruimte vrij.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"NIET GENOEG LEEFRUIMTE!{SMALLLINE}Bouw nieuwe leefruimte of verplaats personeel naar andere basissen.\"\n  STR_LAUNCH_INTERCEPTION: \"ONDERSCHEPPING LANCEREN\"\n  STR_CRAFT: \"VAARTUIG\"\n  STR_STATUS: \"STATUS\"\n  STR_BASE: \"BASIS\"\n  STR_READY: \"GEREED\"\n  STR_OUT: \"ONDERWEG\"\n  STR_REPAIRS: \"REPARATIE\"\n  STR_REFUELLING: \"BIJTANKEN\"\n  STR_REARMING: \"BEWAPENEN\"\n  STR_TARGET: \"DOELWIT: {0}\"\n  STR_WAY_POINT: \"Veld Punt\"\n  STR_ARE_YOU_SURE_CYDONIA: \"Weet je zeker dat je dit vaartuig op missie naar Cydonia wil sturen?\"\n  STR_YES: \"JA\"\n  STR_NO: \"NEE\"\n  STR_SELECT_DESTINATION: \"SELECTEER BESTEMMING\"\n  STR_CYDONIA: \"CYDONIA\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"KIES PLAATS VOOR NIEUWE BASIS\"\n  STR_RETURN_TO_BASE: \"TERUGKEREN NAAR BASIS\"\n  STR_SELECT_NEW_TARGET: \"NIEUW DOELWIT SELECTEREN\"\n  STR_PATROL: \"PATROUILLEREN\"\n  STR_STATUS_: \"STATUS>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"BESCHADIGD - KEERT TERUG NAAR BASIS\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"WEINIG BRANDSTOF - KEERT TERUG NAAR BASIS\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"MISSIE AFGEROND - ONDERWEG TERUG NAAR BASIS\"\n  STR_PATROLLING: \"PATROUILLEERT\"\n  STR_TAILING_UFO: \"ACHTERVOLGT UFO\"\n  STR_INTERCEPTING_UFO: \"ONDERSCHEPPEN UFO-{0}\"\n  STR_RETURNING_TO_BASE: \"KEERT TERUG NAAR BASIS\"\n  STR_DESTINATION_UC_: \"BESTEMMING: {0}\"\n  STR_BASE_UC: \"BASIS>{ALT}{0}\"\n  STR_SPEED_: \"SNELHEID>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"MAXIMUM SNELHEID>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"HOOGTE>{ALT}{0}\"\n  STR_VERY_LOW: \"ZEER LAAG\"\n  STR_LOW_UC: \"LAAG\"\n  STR_HIGH_UC: \"HOOG\"\n  STR_VERY_HIGH: \"ZEER HOOG\"\n  STR_FUEL: \"BRANDSTOF>{ALT}{0}\"\n  STR_WEAPON_ONE: \"WAPEN-1>{ALT}{0}\"\n  STR_NONE_UC: \"GEEN\"\n  STR_ROUNDS_: \"PATRONEN>{ALT}{0}\"\n  STR_WEAPON_TWO: \"WAPEN-2>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"ONDERSCHEPPINGSVAARTUIGEN\"\n  STR_BASE_: \"Basis>{0}\"\n  STR_NAME_UC: \"NAAM\"\n  STR_AMMO_: \"MUNITIE>{ALT}{0}\"\n  STR_CREW: \"BEZETTING\"\n  STR_EQUIPMENT_UC: \"UITRUSTING\"\n  STR_ARMOR: \"PANTSERS\"\n  STR_MAX: \"MAX>{ALT}{0}\"\n  STR_ROOKIE: \"Nieuweling\"\n  STR_SQUADDIE: \"Soldaat\"\n  STR_SERGEANT: \"Sergeant\"\n  STR_CAPTAIN: \"Kapitein\"\n  STR_COLONEL: \"Kolonel\"\n  STR_COMMANDER: \"Commandeur\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Selecteer Squad voor {0}\"\n  STR_SORT_BY: \"SORTEER OP...\"\n  STR_ORIGINAL_ORDER: \"ORGINELE VOLGORDE\"\n  STR_MISSIONS2: \"MISSIES\"\n  STR_KILLS2: \"GEDOOD\"\n  STR_WOUND_RECOVERY2: \"WONDHERSTEL\"\n  STR_SPACE_AVAILABLE: \"RUIMTE BESCHIKBAAR>{ALT}{0}\"\n  STR_SPACE_USED: \"RUIMTE GEBRUIKT>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"RUIMTE IN GEBRUIK\"\n  STR_RANK: \"RANG\"\n  STR_WOUNDED: \"GEWOND\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Uitrusting voor {0}\"\n  STR_DEFENSE_VALUE: \"Defensieve Waarde\"\n  STR_HIT_RATIO: \"Verhouding Treffers\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}klaar om te{NEWLINE}landen bij{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"Missie Starten?\"\n  STR_SELECT_ARMAMENT: \"Bewapening Kiezen\"\n  STR_AMMUNITION_AVAILABLE: \"MUNITIE BESCHIKBAAR\"\n  STR_ARMAMENT: \"BEWAPENING\"\n  STR_NOT_AVAILABLE: \"NB\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"KIES PANTSER VOOR{NEWLINE}{0}\"\n  STR_TYPE: \"TYPE\"\n  STR_PERSONAL_ARMOR_UC: \"PERSOONLIJK PANTSER\"\n  STR_POWER_SUIT_UC: \"ENERGIEPAK\"\n  STR_FLYING_SUIT_UC: \"VLIEGEND PAK\"\n  STR_SELECT_ARMOR: \"Kies Pantser\"\n  STR_NORTH: \"NOORDEN\"\n  STR_NORTH_EAST: \"NOORD-OOSTEN\"\n  STR_EAST: \"OOSTEN\"\n  STR_SOUTH_EAST: \"ZUID-OOSTEN\"\n  STR_SOUTH: \"ZUIDEN\"\n  STR_SOUTH_WEST: \"ZUID-WESTEN\"\n  STR_WEST: \"WESTEN\"\n  STR_NORTH_WEST: \"NOORD-WESTEN\"\n  STR_SELECT_ACTION: \"KIES ACTIE\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"DOORGAAN MET ONDERSCHEPPINGSACHTERVOLGING\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"DOORGAAN ZONDER ONDERSCHEPPING\"\n  STR_VERY_LARGE: \"ZEER GROOT\"\n  STR_LARGE: \"GROOT\"\n  STR_MEDIUM_UC: \"MIDDELGROOT\"\n  STR_SMALL: \"KLEIN\"\n  STR_VERY_SMALL: \"ZEER KLEIN\"\n  STR_GROUNDED: \"GROND\"\n  STR_DETECTED: \"Gedetecteerd\"\n  STR_SIZE_UC: \"GROOTTE\"\n  STR_ALTITUDE: \"HOOGTE\"\n  STR_HEADING: \"RICHTING\"\n  STR_SPEED: \"SNELHEID\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"CENTREREN OP UFO-TIJD=5 Sec.\"\n  STR_TRACKING_LOST: \"SPOOR BIJSTER\"\n  STR_REDIRECT_CRAFT: \"VAARTUIG OMLEIDEN\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"GA NAAR LAATST BEKENDE UFO-POSITIE\"\n  STR_UFO_: \"UFO-{0}\"\n  STR_ALIEN_BASE_: \"BUITENAARDSE BASIS-{0}\"\n  STR_CRASH_SITE_: \"CRASH LOKATIE-{0}\"\n  STR_LANDING_SITE_: \"LANDINGSPLAATS-{0}\"\n  STR_WAY_POINT_: \"RICHTINGSPUNT-{0}\"\n  STR_TERROR_SITE: \"TERREUR LOKATIE-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}heeft bereikt{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"Patrioulleert nu\"\n  STR_ALIEN_ORIGINS: \"Buitenaardse Oorsprong\"\n  STR_THE_MARTIAN_SOLUTION: \"De Martiaanse Oplossing\"\n  STR_CYDONIA_OR_BUST: \"Cydonia of Niets\"\n  STR_UFOPAEDIA: \"UFOpedie\"\n  STR_XCOM_CRAFT_ARMAMENT: \"X-COM VOERTUIG & BEWAPENING\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"ZWARE WAPENPLATFORMS\"\n  STR_WEAPONS_AND_EQUIPMENT: \"WAPENS EN UITRUSTING\"\n  STR_ALIEN_ARTIFACTS: \"BUITENAARDSE VOORWERPEN\"\n  STR_BASE_FACILITIES: \"BASISFACILITEITEN\"\n  STR_ALIEN_LIFE_FORMS: \"BUITENAARDSE LEVENSVORMEN\"\n  STR_ALIEN_RESEARCH_UC: \"ONDERZOEK NAAR HET BUITENAARDSE\"\n  STR_UFO_COMPONENTS: \"UFO-ONDERDELEN\"\n  STR_UFOS: \"UFO's\"\n  STR_SELECT_ITEM: \"SELECTEER ONDERDEEL\"\n  STR_ACCELERATION: \"ACCELERATIE>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"BRANDSTOF CAPACITEIT>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"WAPEN PODS>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"SCHADE  CAPACITEIT>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"BERGRUIMTE>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"HWP CAPACITEIT>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Schade\"\n  STR_RANGE: \"Bereik\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Nauwkeurigheid\"\n  STR_RE_LOAD_TIME: \"Herlaadtijd\"\n  STR_SECONDS: \"{0}s\"\n  STR_DAMAGE_ARMOR_PIERCING: \"PANTSER PENETRATIE\"\n  STR_DAMAGE_INCENDIARY: \"Brandbaar\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"ZWAAR EXPLOSIEF\"\n  STR_DAMAGE_LASER_BEAM: \"LAZER STRAAL\"\n  STR_DAMAGE_PLASMA_BEAM: \"PLASMASTRAAL\"\n  STR_DAMAGE_STUN: \"BEVRIES\"\n  STR_DAMAGE_MELEE: \"HANDGEVECHT\"\n  STR_DAMAGE_ACID: \"ZUUR\"\n  STR_DAMAGE_SMOKE: \"ROOK\"\n  STR_SHOT_TYPE: \"SOORT SCHOT\"\n  STR_ACCURACY_UC: \"NAUWK.HEID\"\n  STR_TIME_UNIT_COST: \"AP KOSTEN\"\n  STR_DAMAGE_UC: \"SCHADE\"\n  STR_AMMO: \"MUNITIE\"\n  STR_SHOT_TYPE_AUTO: \"Automatisch\"\n  STR_SHOT_TYPE_SNAP: \"Snel\"\n  STR_SHOT_TYPE_AIMED: \"Gericht\"\n  STR_CONSTRUCTION_TIME: \"Constructietijd\"\n  STR_CONSTRUCTION_COST: \"Constructieprijs\"\n  STR_MAINTENANCE_COST: \"Onderhoudsprijs\"\n  STR_LOW: \"Laag\"\n  STR_MEDIUM: \"Gemiddels\"\n  STR_HIGH: \"Hoog\"\n  STR_CRAFT_WEAPON: \"Wapen voor Vaartuig\"\n  STR_CRAFT_AMMUNITION: \"Munitie voor Vaartuig\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Zwaar Wapenplatform\"\n  STR_WEAPON: \"Wapen\"\n  STR_AMMUNITION: \"Munitie\"\n  STR_EQUIPMENT: \"Uitrusting\"\n  STR_ALIEN_CORPSE: \"Dode Buitenaardsen\"\n  STR_UFO_COMPONENT: \"UFO-onderdeel\"\n  STR_PERSONAL_ARMOR: \"Persoonlijke Pantsers\"\n  STR_RAW_MATERIALS: \"Grondstoffen\"\n  STR_HWP_CANNON_SHELLS: \"Geschutsmunitie ZWP\"\n  STR_ALIEN: \"Buitenaardse\"\n  STR_SECTOID: \"Sectoïde\"\n  STR_SNAKEMAN: \"Slangeman\"\n  STR_ETHEREAL: \"Etheriër\"\n  STR_MUTON: \"Muton\"\n  STR_FLOATER: \"Zwever\"\n  STR_CELATID: \"Celatide\"\n  STR_SILACOID: \"Silacoïde\"\n  STR_CHRYSSALID: \"Chrysalide\"\n  STR_ZOMBIE: \"Zombie\"\n  STR_REAPER: \"Vreter\"\n  STR_SECTOPOD: \"Sectopod\"\n  STR_CYBERDISC: \"Cyberschijf\"\n  STR_LIVE_COMMANDER: \"Commandeur\"\n  STR_LIVE_LEADER: \"Leider\"\n  STR_LIVE_ENGINEER: \"Ingenieur\"\n  STR_LIVE_MEDIC: \"Hospik\"\n  STR_LIVE_NAVIGATOR: \"Navigator\"\n  STR_LIVE_SOLDIER: \"Soldaat\"\n  STR_LIVE_TERRORIST: \"Terrorist\"\n  STR_FLOATER_SOLDIER: \"Zwever-Soldaat\"\n  STR_FLOATER_NAVIGATOR: \"Zwever-Navigator\"\n  STR_FLOATER_MEDIC: \"Zwever-Hospik\"\n  STR_FLOATER_ENGINEER: \"Zwever-Ingenieur\"\n  STR_FLOATER_LEADER: \"Zwever-Leider\"\n  STR_FLOATER_COMMANDER: \"Zwever-Commandant\"\n  STR_SECTOID_SOLDIER: \"Sectoïde Soldaat\"\n  STR_SECTOID_NAVIGATOR: \"Sectoïde Navigator\"\n  STR_SECTOID_MEDIC: \"Sectoïde Hospik\"\n  STR_SECTOID_ENGINEER: \"Sectoïde Ingenieur\"\n  STR_SECTOID_LEADER: \"Sectoïde Leider\"\n  STR_SECTOID_COMMANDER: \"Sectoïde Commandant\"\n  STR_SNAKEMAN_SOLDIER: \"Slangeman-Soldaat\"\n  STR_SNAKEMAN_NAVIGATOR: \"Slangeman-Navigator\"\n  STR_SNAKEMAN_ENGINEER: \"Slangeman-Ingenieur\"\n  STR_SNAKEMAN_LEADER: \"Slangeman-Leider\"\n  STR_SNAKEMAN_COMMANDER: \"Slangeman-Commandant\"\n  STR_MUTON_SOLDIER: \"Muton-Soldaat\"\n  STR_MUTON_NAVIGATOR: \"Muton-Navigator\"\n  STR_MUTON_ENGINEER: \"Muton-Ingenieur\"\n  STR_ETHEREAL_SOLDIER: \"Etherische Soldaat\"\n  STR_ETHEREAL_LEADER: \"Etherische Leider\"\n  STR_ETHEREAL_COMMANDER: \"Etherische Commandant\"\n  STR_CYBERDISC_TERRORIST: \"Cyberschijf-Terrorist\"\n  STR_REAPER_TERRORIST: \"Vreter-Terrorist\"\n  STR_CHRYSSALID_TERRORIST: \"Chrysalide Terrorist\"\n  STR_CELATID_TERRORIST: \"Celatide Terrorist\"\n  STR_SILACOID_TERRORIST: \"Silacoïde Terrorist\"\n  STR_SECTOPOD_TERRORIST: \"Sectopod-Terrorist\"\n  STR_UFO_POWER_SOURCE: \"UFO-Energiebron\"\n  STR_UFO_NAVIGATION: \"UFO-Navigatie\"\n  STR_UFO_CONSTRUCTION: \"UFO-Constructie\"\n  STR_ALIEN_FOOD: \"Buitenaards Voedsel\"\n  STR_ALIEN_REPRODUCTION: \"Buitenaardse Voortplanting\"\n  STR_ALIEN_ENTERTAINMENT: \"Buitenaardse Recreatie\"\n  STR_ALIEN_SURGERY: \"Buitenaardse Chirurgie\"\n  STR_EXAMINATION_ROOM: \"Onderzoekskamer\"\n  STR_ALIEN_ALLOYS: \"Buitenaardse Legeringen\"\n  STR_ALIEN_HABITAT: \"Buitenaardse Leefomgeving\"\n  STR_POWER_SUIT: \"Energiepak\"\n  STR_FLYING_SUIT: \"Vliegend Pak\"\n  STR_HWP_ROCKETS: \"ZWP-Raketten\"\n  STR_HWP_FUSION_BOMB: \"ZWP-Fusiebom\"\n  STR_LASER_WEAPONS: \"Laserwapens\"\n  STR_NEW_FIGHTER_CRAFT: \"Nieuw gevechtsvliegtuig\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Nieuw transport- en gevechtsvliegtuig\"\n  STR_ULTIMATE_CRAFT: \"Ultiem Vaartuig\"\n  STR_LASER_PISTOL: \"Laserpistool\"\n  STR_LASER_RIFLE: \"Lasergeweer\"\n  STR_HEAVY_LASER: \"Zware laser\"\n  STR_LASER_CANNON: \"Laserkanon\"\n  STR_PLASMA_CANNON: \"Plasmakanon\"\n  STR_FUSION_MISSILE: \"Fusie-raket\"\n  STR_LASER_DEFENSE: \"Laserverdediging\"\n  STR_PLASMA_DEFENSE: \"Plasmaverdediging\"\n  STR_FUSION_DEFENSE: \"Fusie-verdediging\"\n  STR_GRAV_SHIELD: \"Zwaartekrachtschild\"\n  STR_MIND_SHIELD: \"Gedachtenschild\"\n  STR_PSI_LAB: \"Psi-lab\"\n  STR_MOTION_SCANNER: \"Bewegingsscanner\"\n  STR_MEDI_KIT: \"Medicijnkit\"\n  STR_TANK_CANNON: \"Tank/Kanon\"\n  STR_TANK_ROCKET_LAUNCHER: \"Tank/Raketwerper\"\n  STR_TANK_LASER_CANNON: \"Tank/Laserkanon\"\n  STR_HOVERTANK_PLASMA: \"Zweeftank/Plasma\"\n  STR_HOVERTANK_LAUNCHER: \"Zweeftank/Werper\"\n  STR_STINGRAY_LAUNCHER: \"Pijlstaart-werper\"\n  STR_AVALANCHE_LAUNCHER: \"Lawine-werper\"\n  STR_CANNON: \"Kanon\"\n  STR_FUSION_BALL_LAUNCHER: \"Fusiebal-werper\"\n  STR_PLASMA_BEAM: \"Plasmastraal\"\n  STR_STINGRAY_MISSILES: \"Pijlstaart-Raketten\"\n  STR_AVALANCHE_MISSILES: \"Lawine-Raketten\"\n  STR_CANNON_ROUNDS_X50: \"Kanonrondes(x50)\"\n  STR_FUSION_BALL: \"Fusie-bal\"\n  STR_SOLDIER: \"Soldaat\"\n  STR_SCIENTIST: \"Wetenschapper\"\n  STR_ENGINEER: \"Ingenieur\"\n  STR_NORTH_AMERICA: \"Noord-Amerika\"\n  STR_ARCTIC: \"Noordpool\"\n  STR_ANTARCTICA: \"Antarctica\"\n  STR_SOUTH_AMERICA: \"Zuid-Amerika\"\n  STR_EUROPE: \"Europa\"\n  STR_NORTH_AFRICA: \"Noord-Afrika\"\n  STR_SOUTHERN_AFRICA: \"Zuid-Afrika\"\n  STR_CENTRAL_ASIA: \"Centraal-Azië\"\n  STR_SOUTH_EAST_ASIA: \"Zuid-Oost-Azië\"\n  STR_SIBERIA: \"Siberië\"\n  STR_AUSTRALASIA: \"Australazië\"\n  STR_PACIFIC: \"Pacifische Oceaan\"\n  STR_NORTH_ATLANTIC: \"Noord-Atlantische\"\n  STR_SOUTH_ATLANTIC: \"Zuid-Atlantische\"\n  STR_INDIAN_OCEAN: \"Indische Oceaan\"\n  STR_ALIEN_RESEARCH: \"Buitenaards Onderzoek\"\n  STR_ALIEN_HARVEST: \"Buitenaards Oogstwerk\"\n  STR_ALIEN_ABDUCTION: \"Buitenaardse Ontvoeringen\"\n  STR_ALIEN_INFILTRATION: \"Buitenaardse Infiltratie\"\n  STR_ALIEN_BASE: \"Buitenaardse Basis\"\n  STR_ALIEN_TERROR: \"Buitenaardse Terreur\"\n  STR_ALIEN_RETALIATION: \"Buitenaardse Wraakacties\"\n  STR_ALIEN_SUPPLY: \"Buitenaardse Bevoorrading\"\n  STR_MAXIMUM_SPEED: \"Maximumsnelheid\"\n  STR_HYPER_WAVE_DECODER_UC: \"HYPERGOLF-DECODER\"\n  STR_SKYRANGER: \"LUCHTWAKER\"\n  STR_LIGHTNING: \"BLIKSEMSCHICHT\"\n  STR_AVENGER: \"WREKER\"\n  STR_INTERCEPTOR: \"ONDERSCHEPPER\"\n  STR_FIRESTORM: \"VUURSTORM\"\n  STR_UFO: \"UFO\"\n  STR_STINGRAY: \"PIJLSTAART\"\n  STR_AVALANCHE: \"LAWINE\"\n  STR_CANNON_UC: \"KANON\"\n  STR_FUSION_BALL_UC: \"FUSIE-BAL\"\n  STR_LASER_CANNON_UC: \"LASERKANON\"\n  STR_PLASMA_BEAM_UC: \"PLASMASTRAAL\"\n  STR_DAMAGE_CAPACITY: \"Capaciteit voor Schade\"\n  STR_WEAPON_POWER: \"Wapenkracht\"\n  STR_WEAPON_RANGE: \"Wapenbereik\"\n  STR_ACCESS_LIFT: \"Toegangslift\"\n  STR_LABORATORY: \"Laboratorium\"\n  STR_WORKSHOP: \"Werkplaats\"\n  STR_SMALL_RADAR_SYSTEM: \"Klein Radarsysteem\"\n  STR_LARGE_RADAR_SYSTEM: \"Groot Radarsysteem\"\n  STR_MISSILE_DEFENSES: \"Raketverdediging\"\n  STR_GENERAL_STORES: \"Opslagruimte\"\n  STR_ALIEN_CONTAINMENT: \"Buitenaardse Klimaatcel\"\n  STR_LASER_DEFENSES: \"Laserverdediging\"\n  STR_PLASMA_DEFENSES: \"Plasmaverdediging\"\n  STR_FUSION_BALL_DEFENSES: \"Fusiebal-verdediging\"\n  STR_PSIONIC_LABORATORY: \"Psionisch Laboratorium\"\n  STR_HYPER_WAVE_DECODER: \"Hypergolf-decoder\"\n  STR_HANGAR: \"Loods\"\n  STR_USA: \"VS\"\n  STR_RUSSIA: \"RUSLAND\"\n  STR_UK: \"VK\"\n  STR_FRANCE: \"FRANKRIJK\"\n  STR_GERMANY: \"DUITSLAND\"\n  STR_ITALY: \"ITALIË\"\n  STR_SPAIN: \"SPANJE\"\n  STR_CHINA: \"CHINA\"\n  STR_JAPAN: \"JAPAN\"\n  STR_INDIA: \"INDIA\"\n  STR_BRAZIL: \"BRAZILIË\"\n  STR_AUSTRALIA: \"AUSTRALIË\"\n  STR_NIGERIA: \"NIGERIA\"\n  STR_SOUTH_AFRICA: \"ZUID-AFRIKA\"\n  STR_EGYPT: \"EGYPTE\"\n  STR_CANADA: \"CANADA\"\n  STR_TANK: \"Tank\"\n  STR_CIVILIAN: \"Burger\"\n  STR_JAN: \"Jan\"\n  STR_FEB: \"Feb\"\n  STR_MAR: \"Maa\"\n  STR_APR: \"Apr\"\n  STR_MAY: \"Mei\"\n  STR_JUN: \"Jun\"\n  STR_JUL: \"Jul\"\n  STR_AUG: \"Aug\"\n  STR_SEP: \"Sep\"\n  STR_OCT: \"Okt\"\n  STR_NOV: \"Nov\"\n  STR_DEC: \"Dec\"\n  STR_INTERNATIONAL_RELATIONS: \"Internationale Betrekkingen\"\n  STR_COUNTRY: \"Land\"\n  STR_FUNDING: \"Steun\"\n  STR_CHANGE: \"Verandering\"\n  STR_WEAPON_SYSTEMS: \"WAPENSYSTEMEN\"\n  STR_HWPS: \"ZWP's\"\n  STR_DAMAGE_UC_: \"SCHADE>{ALT}{0}\"\n  STR_ACCESS_LIFT_UFOPEDIA: \"Via de toegangslift kan materieel en personeel de ondergrondse basis in- en uitgaan.  Het is altijd de eerste faciliteit die wordt gebouwd op een nieuwe locatie.  Het gebied rond de lift is kwetsbaar voor vijandige indringers.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Ieder accommodatieblok kan tot 50 man personeel huisvesten.  De faciliteit biedt basale recreatie-, voedsel- en slaapvoorzieningen.\"\n  STR_LABORATORY_UFOPEDIA: \"In een laboratoriumfaciliteit kunnen tot 50 wetenschappers werken.  Laboratoria zijn ingericht met de laatste technologie voor onderzoek naar materialen, biochemie en kosmologie.  Er is toegang vrijgesteld tot de beste onderzoekslabs ter wereld, waaronder ook militaire instellingen.\"\n  STR_WORKSHOP_UFOPEDIA: \"Een werkplaats  alle uitrusting die nodig is om uitrusting te maken gebaseerd op ontwerpen uit de wetenschappenlijke labs.  Tot 50 ingenieurs kunnen een werkplaats bezetten, maar eenheden onder constructie zullen ook wat ruimte in beslag nemen.\"\n  STR_SMALL_RADAR_SYSTEM_UFOPEDIA: \"Een klein detectiesysteem heeft een effectief radarbereik van 300 zeemijl en is gekoppeld aan satellietsystemen voor grondonderzoek. Elk systeem heeft een kans van 10% om elke 30 minuten een object van gemiddelde grootte te detecteren.\"\n  STR_LARGE_RADAR_SYSTEM_UFOPEDIA: \"Een groot detectiesysteem heeft een effectief bereik van 450 zeemijl en is gekoppeld aan satellietsystemen voor grondonderzoek. Elk systeem heeft een kans van 20% om elke 30 minuten een object van gemiddelde grootte te detecteren.\"\n  STR_MISSILE_DEFENSES_UFOPEDIA: \"Raketverdediging biedt enige bescherming tegen een inval door vijandige vaartuigen welke proberen te landen in de buurt van de basis.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"Alle uitrusting, wapensystemen, munitie,  geborgen `materiaal en platforms voor zware wapens worden in de opslag geplaatst, inclusief uitrusting die is toegewezen aan vaartuigen in hangars.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"Levende buitenaardse wezens hebben waarschijnlijk een speciale habitat nodig om hun vitale functies te ondersteunen.  De klimaatcel kan tot 10 buitenaardse wezens huisvesten in onafhankelijke eenheden.\"\n  STR_LASER_DEFENSES_UFOPEDIA: \"Laserverdediging biedt bescherming tegen invallen door vijandige vaartuigen.\"\n  STR_PLASMA_DEFENSES_UFOPEDIA: \"Plasmastraal-verdediging biedt krachtige en efficiënte bescherming tegen invallen door vijandige vaartuigen.\"\n  STR_FUSION_BALL_DEFENSES_UFOPEDIA: \"Fusie-raketten bieden de meeste effectieve verdediging tegen buitenaardse aanvallen.  Deze raketten creëren een antimaterie-implosie die alles binnen een bepaalde straal vernietigt.\"\n  STR_GRAV_SHIELD_UFOPEDIA: \"Het zwaartekrachtschild kan buitenaardse vaartuigen lang genoeg afslaan om verdedigingssystemen te herhalen.  In de praktijk verdubbelt op die manier de defensieve kracht van de basis.\"\n  STR_MIND_SHIELD_UFOPEDIA: \"Omdat buitenaardse vaartuigen de aanwezigheid van mensen kunnen bepalen op basis van hersengolven is de meest effectieve tegenmaatregel het afschermen van hersengolven in de basis.  Deze faciliteit zal de detectiekans voor buitenaardse vaartuigen drastisch verminderen.\"\n  STR_PSIONIC_LABORATORY_UFOPEDIA: \"Het psionische lab kan de psionische potentie van iedere soldaat in de basis bepalen, en de nodige training bieden om gebruik te kunnen gaan maken van hun psionische vaardigheden.  Ieder lab kan tot tien soldaten trainen.  Training wordt aan het eind van iedere maand toegewezen.  Psionische vaardigheden kunnen met behulp van een Psi-versterker worden ingezet voor psionische aanvallen tijdens een gevecht.\"\n  STR_HYPER_WAVE_DECODER_UFOPEDIA: \"De communicatie van buitenaardsen onderling gaat via een supra-dimensionale golf die vrijwel instantaan is.  De decoder-faciliteit onderschept berichten van UFO's en decodeert de informatie.  Dit zal het type UFO, het buitenaardse ras en de aard van de activiteiten onthullen.\"\n  STR_HANGAR_UFOPEDIA: \"Elke hangar biedt plaats aan een enkel voertuig. Er zijn voorzieningen voor onderhoud, tanken en reparatie van X-Com voertuigen. Aan elk voertuig dat op een basis is gestationeerd, moet een vrije hangar zijn toegewezen die niet door andere voertuigen kan worden gebruikt, zelfs wanneer het toegewezen voertuig op een missie is.\"\n  STR_PISTOL_UFOPEDIA: \"Het standaard X-Com-pistool is een krachtige semi-automatische machine pistool met een capaciteit van 12 kogels\"\n  STR_RIFLE_UFOPEDIA: \"Dit zeer nauwkeurige scherpschuttersgeweer heeft een lasergeleide richtkijker en gebruikt 6.7mm munitie in een 20-patroonsmagazijn.\"\n  STR_HEAVY_CANNON_UFOPEDIA: \"Het zware kanon is een allesvernietigend, maar onhandig wapen.  Zijn veelzijdigheid ontleent hij aan het feit dat er drie soorten munitie in passen - pantserdoorborende, brandende en hoog-explosieve munitie.\"\n  STR_AUTO_CANNON_UFOPEDIA: \"Het automatisch kanon combineert de veelzijdigheid en kracht van een zwaar kannon met een hogere snelheid van vuren.\"\n  STR_ROCKET_LAUNCHER_UFOPEDIA: \"De raketwerper is een lasergestuurd systeem waarmee raketten van drie verschillende afmetingen mee kunnen worden afgevuurd.\"\n  STR_LASER_PISTOL_UFOPEDIA: \"Het laserpistool is een effectieve toepassing van nieuwe technologie.  Het heeft het gemak van een pistool met een snellere en nauwkeurigere afvuring.\"\n  STR_LASER_RIFLE_UFOPEDIA: \"Het lasergeweer is een krachtigere en nauwkeurigere versie van het oudere ontwerp van het pistool.\"\n  STR_HEAVY_LASER_UFOPEDIA: \"De zware laser is onhandig maar extreem effectief.\"\n  STR_GRENADE_UFOPEDIA: \"Deze granaat uit de standaarduitrusting heeft een nauwkeurige en complexe timer voor precieze controle.\"\n  STR_SMOKE_GRENADE_UFOPEDIA: \"Rookgranaten zijn handig voor het bieden van dekking in een open gevecht.  Gebruik ze met beleid want de vijand kan er ook voordeel bij hebben.\"\n  STR_PROXIMITY_GRENADE_UFOPEDIA: \"Een afstandsgranaat wordt gegooid zoals een gewone granaat, maar gaat pas af wanneer er beweging wordt waargenomen.  Correct gebruik van dit apparaat vergt bekwaamheid en zorg.\"\n  STR_HIGH_EXPLOSIVE_UFOPEDIA: \"Dit explosief moet alleen gebruikt worden voor de sloop.  Houd personeel op afstand bij sloopwerkzaamheden.\"\n  STR_MOTION_SCANNER_UFOPEDIA: \"Dit complexe apparaat gebruikt een veelheid aan sensoren en geavanceerde computeralgoritmes om bewegende vijanden te identificeren.  Echter, het vergt wat oefening voordat het effectief kan worden gebruikt.  Klik op het bewegingssensor-icoon in het tactische scherm.  Selecteer 'Gebruik Scanner' in het menu.  Het Scannerscherm toont in het midden een pijl dit wijst in de kijkrichting van de soldaat (het noorden staat bovenaan).  De knipperende stippen tonen eenheden die recentelijk hebben bewogen.  Grote of snel bewegende eenheden zullen grotere stippen produceren.  Onbeweeglijke eenheden worden niet gedecteerd.\"\n  STR_MEDI_KIT_UFOPEDIA: \"De medicijnkit combineert een genezingsvoorziening met pijnstillers en opwekkende middelen.  Om de medicijnkit te gebruiken moet je naar de soldaat toe staan die de behandeling nodig heeft.  Als de soldaat is verdoofd moet je boven het lichaam gaan staan.  Klik op het icoon van de medicijnkit en klik op 'Gebruik Medicijnkit' in het menu.{NEWLINE}GENEZEN> Rode lichaamsdelen tonen fatale verwondingen.  Klik op een lichaamsdeel met verwondingen.  Klik op de 'Genees'-knop.  Een fatale wond zal worden genezen en een deel van de gezondheid zal worden hersteld.{NEWLINE}OPWEKKEND MIDDEL> Dit zal energie herstellen en bewusteloze (verdoofde) soldaten weer bij kennis brengen.{NEWLINE}PIJNSTILLER> Dit zal het moreel van de soldaat herstellen in gelijke mate met de verminderde gezondheidstoestand.\"\n  STR_PSI_AMP_UFOPEDIA: \"De Psi-versterker kan alleen worden gebruikt door soldaten met psionische vaardigheden. Klik tijdens gevechten op de Psi-versterker, selecteer het type aanval en selecteer een doel met de cursor. Er zijn twee soorten psionische aanvallen:{NEWLINE}PANIC UNIT> Als de aanval slaagt, zal dit het moreel van het doelwit verminderen en kan het in paniek raken.{NEWLINE}MIND CONTROL> Als dit lukt, krijg je onmiddellijk controle over de vijandelijke eenheid alsof het een van uw eigen eenheden is. Het is moeilijker om succesvol te zijn met dit type aanval.\"\n  STR_STUN_ROD_UFOPEDIA: \"Dit apparaat kan alleen in een lijf-aan-lijfgevecht worden gebruikt, maar het zal een levend organisme niet doden, maar verdoven via elektrische schokken.\"\n  STR_MIND_PROBE_UFOPEDIA: \"De mind probe is een buitenaards communicatieapparaat dat wordt gebruikt om informatie rechtstreeks uit hersengolven te lezen. X-Com-eenheden kunnen dit apparaat in gevechten gebruiken om de kenmerken van een buitenaards wezen weer te geven. Klik op de mind probe en de optie 'gebruiken'. Klik dan op een alien met de cursor.\"\n  STR_PLASMA_PISTOL_UFOPEDIA: \"Plasmapistolen zijn dodelijke buitenaards wapens gebaseerd op het versnellen van deeltjes vanuit een miniem antizwaartekrachtsveld.\"\n  STR_PLASMA_RIFLE_UFOPEDIA: \"Dit is een verwoestend buitenaards wapen gebaseerd op het versnellen van deeltjes vanuit een miniem antizwaartekrachtsveld.\"\n  STR_HEAVY_PLASMA_UFOPEDIA: \"Dit is een ongelofelijk verwoestende wapen gebaseerd op het versnellen van deeltjes vanuit een miniem antizwaartekrachtsveld.\"\n  STR_BLASTER_LAUNCHER_UFOPEDIA: \"Dit is een buitenaardse geleide raketwerper waarmee krachtige 'springbommen' kunnen worden afgevuurd.  Als je klikt om te vuren kun je 'markeerpunten' zetten die door de springbom worden gevolgd.  Wanneer je voldoende markeerpunten hebt neergezet, klik op het speciale icoon om te vuren.\"\n  STR_SMALL_LAUNCHER_UFOPEDIA: \"Een kleine werper voor verdovingsbommen.  Zeer bruikbaar bij het vangen van levende buitenaardsen.\"\n  STR_ALIEN_GRENADE_UFOPEDIA: \"Dit apparaat werkt op dezelfde wijze als een aardse granaat - behalve dat deze krachtiger is.\"\n  STR_SMALL_SCOUT: \"Kleine Verkenner\"\n  STR_MEDIUM_SCOUT: \"Middelgrote Verkenner\"\n  STR_LARGE_SCOUT: \"Grote Verkenner\"\n  STR_HARVESTER: \"Oogster\"\n  STR_ABDUCTOR: \"Ontvoerder\"\n  STR_TERROR_SHIP: \"Terreurschip\"\n  STR_BATTLESHIP: \"Slagschip\"\n  STR_SUPPLY_SHIP: \"Bevoorradingsschip\"\n  STR_RATING: \"PRESTATIE> {0}\"\n  STR_RATING_TERRIBLE: \"TRIEST!\"\n  STR_RATING_POOR: \"ZWAK!\"\n  STR_RATING_OK: \"OK\"\n  STR_RATING_GOOD: \"GOED!\"\n  STR_RATING_EXCELLENT: \"UITSTEKEND!\"\n  STR_SCORE: \"SCORE\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"X-COM PROJECT MAANDELIJKS RAPPORT\"\n  STR_MONTH: \"Maand> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"De raad van steunende naties is over het algemeen tevreden met je voortgang tot nu toe.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"De raad van steunende naties is zeer tevreden met je uitstekende voortgang.  Hou dit goede werk vol.\"\n  STR_COUNCIL_IS_DISSATISFIED: \"De raad van steunende naties is ontevreden met je prestaties.  Je moet effectiever omgaan met de buitenaardse dreiging, anders loop je het risico dat het project wordt beëindigd.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"Je hebt niet op een succesvolle manier om kunnen gaan met de buitenaardse invasie en de raad van steunende naties heeft helaas besloten het project te beëindigen.  Iedere natie zal met het probleem omgaan als hun goeddunkt.  We kunnen alleen maar hopen dat we op de één of andere manier een regeling kunnen treffen met deze ogenschijnlijk vijandelijke macht, en dat de bevolking zich zal kunnen neerleggen bij de aanwezigheid van deze buitenaardse bezoekers.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} is bijzonder tevreden over je vermogen om de lokale dreiging het hoofd te bieden en heeft ermee ingestemd de financiering te verhogen.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} zijn vooral blij met uw vooruitgang met het omgaan van de lokale alien inval en zijn overeengekomen om hun financiering te verhogen.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} en {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} is niet tevreden met je vermogen om buitenaardse activiteiten op zijn grondgebied aan te pakken en heeft besloten zijn financiele bijdrage te verlagen.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} zijn ontevreden met je bestrijding van alien activiteiten in hun regio en hebben besloten om hun financiering te verlagen.\"\n  STR_KNOTS: \"{0} knopen\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} heeft een geheimen bond gesloten met een onbekende alien strijdmacht en heeft zich terug getroken van het project.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} heeft een geheim verband gesloten met onbekende alien krachten en heeft zich teruggetrokken uit het project.\"\n  STR_MONTHLY_RATING: \"Maandelijkse Beoordeling> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Financieringsaanpassing> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"De financiële raad is niet blij met je financiële positie. Je moet zorgen dat je schulden minder dan 1 miljoen dollar zijn of het project wordt beëindigd.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"HYPERGOLF-UITZENDINGEN ZIJN GEDECODEERD\"\n  STR_CRAFT_TYPE: \"TYPE VAARTUIG\"\n  STR_RACE: \"RAS\"\n  STR_MISSION: \"MISSIE\"\n  STR_ZONE: \"GEBIED\"\n  STR_ALLOCATE_RESEARCH: \"Onderzoek Toewijzen\"\n  STR_ALLOCATE_MANUFACTURE: \"Productie Toewijzen\"\n  STR_NEW_YORK: \"New York\"\n  STR_WASHINGTON: \"Washington\"\n  STR_LOS_ANGELES: \"Los Angeles\"\n  STR_MONTREAL: \"Montreal\"\n  STR_HAVANA: \"Havana\"\n  STR_MEXICO_CITY: \"Mexico Stad\"\n  STR_CHICAGO: \"Chicago\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_DALLAS: \"Dallas\"\n  STR_BRASILIA: \"Brazilië\"\n  STR_BOGOTA: \"Bogota\"\n  STR_BUENOS_AIRES: \"Buenos Aires\"\n  STR_SANTIAGO: \"Santiago\"\n  STR_RIO_DE_JANEIRO: \"Rio de Janeiro\"\n  STR_LIMA: \"Lima\"\n  STR_CARACAS: \"Caracas\"\n  STR_LONDON: \"Londen\"\n  STR_PARIS: \"Parijs\"\n  STR_BERLIN: \"Berlijn\"\n  STR_MOSCOW: \"Moskou\"\n  STR_ROME: \"Rome\"\n  STR_MADRID: \"Madrid\"\n  STR_BUDAPEST: \"Budapest\"\n  STR_LAGOS: \"Lagos\"\n  STR_CAIRO: \"Caïro\"\n  STR_CASABLANCA: \"Casablanca\"\n  STR_PRETORIA: \"Pretoria\"\n  STR_NAIROBI: \"Nairobi\"\n  STR_CAPE_TOWN: \"Kaapstad\"\n  STR_KINSHASA: \"Kinshasa\"\n  STR_ANKARA: \"Ankara\"\n  STR_DELHI: \"Delhi\"\n  STR_KARACHI: \"Karachi\"\n  STR_BAGHDAD: \"Bagdad\"\n  STR_TEHRAN: \"Teheran\"\n  STR_BOMBAY: \"Mumbai\"\n  STR_CALCUTTA: \"Kolkata\"\n  STR_TOKYO: \"Tokio\"\n  STR_BEIJING: \"Peking\"\n  STR_BANGKOK: \"Bangkok\"\n  STR_MANILA: \"Manilla\"\n  STR_SEOUL: \"Seoel\"\n  STR_SINGAPORE: \"Singapore\"\n  STR_JAKARTA: \"Jakarta\"\n  STR_SHANGHAI: \"Sjanghai\"\n  STR_HONG_KONG: \"Hongkong\"\n  STR_NOVOSIBIRSK: \"Novosibirsk\"\n  STR_CANBERRA: \"Canberra\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_MELBOURNE: \"Melbourne\"\n  STR_PERTH: \"Perth\"\n  STR_PSI_TRAINING: \"Psi Training\"\n  STR_PSIONIC_TRAINING: \"PSIONISCHE TRAINING\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Overgebleven Psi-lab capaciteit> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"Psionische{NEWLINE}Kracht\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"Psionische Vaardigheid{NEWLINE}/Verbetering\"\n  STR_PSI_AMP: \"Psi-Versterker\"\n  STR_IN_TRAINING: \"Wordt{NEWLINE}Getraind?\"\n  STR_TARGETTED_BY: \"DOELWIT VAN:\"\n  STR_WEAPONS_CREW_HWPS: \"WAPENS/{NEWLINE}BEZETTING/ZWP's\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"heeft weinig brandstof,{NEWLINE}keert terug naar basis\"\n  STR_SOLDIER_LIST: \"Lijst van Soldaten\"\n  STR_RANK_: \"RANG> {ALT}{0}\"\n  STR_MISSIONS: \"MISSIES> {ALT}{0}\"\n  STR_KILLS: \"GEDOOD> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"WOND HERSTEL> {ALT}{0}\"\n  STR_TIME_UNITS: \"ACTIEPUNTEN\"\n  STR_STAMINA: \"UITHOUDINGSVERMOGEN\"\n  STR_HEALTH: \"GEZONDHEIDSTOESTAND\"\n  STR_BRAVERY: \"MOED\"\n  STR_REACTIONS: \"REACTIES\"\n  STR_FIRING_ACCURACY: \"SCHIETNAUWKEURIGHEID\"\n  STR_THROWING_ACCURACY: \"GOOINAUWKEURIGHEID\"\n  STR_STRENGTH: \"KRACHT\"\n  STR_PSIONIC_STRENGTH: \"PSIONISCHE KRAHT\"\n  STR_PSIONIC_SKILL: \"PSIONISCHE VAARDIGHEID\"\n  STR_NEW_RANK: \"NIEUWE RANG\"\n  STR_PROMOTIONS: \"Promoties\"\n  STR_SOLDIERS_UC: \"SOLDATEN\"\n  STR_TANK_CANNON_UFOPEDIA: \"De geautomatiseerde zware wapens platforms zijn ontworpen om een X-com squadron te ondersteunen. De combinatie van hoge vuurkracht en sterke bepantsering maakt deze eenheden waardevol voor vuurgevechten in open terrein. Zorg ervoor dat er voldoende kanonhulzen in je opslag zijn om de tanks te herbewapenen. Ze worden automatisch geladen wanneer je ze aan een squadron toewijst.\"\n  STR_TANK_ROCKET_LAUNCHER_UFOPEDIA: \"Dit geautomatiseerde Zware WapenPlatform is bewapend met krachtige raketten.  Dit is vernietigend voor iedere buitenaardse tegenstander.  Zorg dat je opslagruimte blijft bevoorraad met ZWP-raketten.\"\n  STR_TANK_LASER_CANNON_UFOPEDIA: \"Laserwapens zijn een bruikbare toevoeging voor ZWP's.  Het combineert zware vuurkracht met een gebrek aan beperkingen op munitie.\"\n  STR_HOVERTANK_PLASMA_UFOPEDIA: \"Buitenaardse technologie heeft ZWP's nieuw leven ingeblazen.  De toegevoegde manoeuvreerbaarheid dankzij het reizen door de lucht en de kracht van plasmastralen is een dodelijke combinatie.\"\n  STR_HOVERTANK_LAUNCHER_UFOPEDIA: \"Deze zweeftank heeft een fusiebal-werper die ongekende vernietiging teweeg kan brengen. Pas goed op wanneer je hier gebruik van maakt. Je zult de fusieballen moeten produceren om deze ZWP's volledig bewapend te houden. Een fusiebal is een intelligent geleid wapen. Bij het afvuren kun je een aantal markeerpunten neerzetten met je cursor en vervolgens op het icoon klikken om de fusiebal te lanceren.\"\n  STR_HEAVY_PLASMA_CLIP_UFOPEDIA: \"Dit compacte apparaat wordt gebruikt als munitie voor het Zwaar Plasma-wapen.  Er zit een kleine hoeveelheid Elerium in.\"\n  STR_PLASMA_RIFLE_CLIP_UFOPEDIA: \"Dit kleine object wordt gebruikt als energiebron voor een plasmageweer - een buitenaards wapen van gemiddelde kracht.  Er zit een kleine hoeveelheid Elerium in.\"\n  STR_PLASMA_PISTOL_CLIP_UFOPEDIA: \"Energiebron voor het kleine buitenaardse plasmapistool.  Bevat Elerium - de bron van alle buitenaardse energie.\"\n  STR_STUN_BOMB_UFOPEDIA: \"De verdovingsbom wordt gebruikt om levende mensen te vangen, maar het kan ook gebruikt worden op de meeste buitenaardse rassen.  Deze worden afgevuurd met behulp van een kleine werper.\"\n  STR_ALIEN_RESEARCH_UFOPEDIA: \"De buitenaardse onderzoeksmissie wordt gebruikt voor het verzamelen van basisgegevens over de aarde en haar bewoners. Er worden overwegend kleine voertuigen gebruikt, met af en toe landingen in verlaten gebieden. Dit soort buitenaardse activiteiten vormt de minste bedreiging voor X-Com en wordt niet als heel belangrijk beschouwd voor regeringen of het publiek.\"\n  STR_ALIEN_HARVEST_UFOPEDIA: \"De buitenaardsen kunnen veel met de aardse fauna.  Dieren worden in het geheim ontvoerd en zonder een aantal organen weer teruggezet.  Verminkingen van vee worden over het algemeen tegelijk gerapporteerd met UFO-waarnemingen.  Dit soort buitenaardse activiteit baart overheden zorgen en levert behoorlijk wat onrust op onder de bevolking.  Dit soort activiteit vindt vooral plaats in landbouwgebieden.  De theorie achter de 'buitenaardse oogst' suggereert dat buitenaardse rassen oorspronkelijk de planeet hebben 'bezaaid' met flora en fauna en dat ze nu zijn teruggekeerd om hun oogst binnen te halen.\"\n  STR_ALIEN_ABDUCTION_UFOPEDIA: \"Dit is de meest verraderlijke vorm van buitenaardse activiteit.  Ontvoeringen door buitenaardsen worden breed gerapporteerd, ondanks pogingen om de ervaring uit het geheugen van de slachtoffers te wissen.  Ontvoerden melden dat ze werden onderworpen aan vernederende lichamelijke onderzoeken, waaronder bevruchting met buitenaardse foetussen en bizarre genetische experimenten.  Het doel achter deze activiteit lijkt te maken te hebben met genetische mutatie en manipulatie van het eigen genetisch materiaal van de buitenaardsen.  Deze activiteit veroorzaakt grote ophef, en vindt plaats in bevolkte gebieden of steden.\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"Regeringen op aarde kunnen worden binnengedrongen door buitenaardse agenten die er menselijk uitzien. Dit kan leiden tot officieel contact tussen buitenaardsen en overheden op het hoogste niveau. Het hoogtepunt van deze activiteit wordt gekenmerkt door intense UFO-activiteit in de buurt van grote steden. De aliens zullen proberen een pact te sluiten met een aardse regering door kennis aan te bieden van hun superieure technologie. In ruil daarvoor zal de overheid de vreemdelingen toestaan hun activiteiten ongehinderd uit te voeren. Deze buitenaardse missie vormt de grootste bedreiging voor X-Com. Als een regering instemt met een pact, stopt de financiering ervan.\"\n  STR_ALIEN_BASE_UFOPEDIA: \"Aliens zullen geheime ondergrondse bases bouwen op afgelegen locaties. Na enkele eerste verkenningsvluchten zal er tijdens de bouw van de basis intense UFO-activiteit plaatsvinden. Van deze bases is bekend dat ze experimentele laboratoria bevatten voor ontvoerden van mensen en voorraden voor verdere activiteiten in de regio. De aanwezigheid van buitenaardse bases zal een grote hoeveelheid gerapporteerde buitenaardse activiteit genereren zonder de aanwezigheid van UFO's. Om een basis te vinden, moet een X-Com-vaartuig een paar uur in een gebied patrouilleren om enige kans te hebben ontdekt te worden.\"\n  STR_ALIEN_TERROR_UFOPEDIA: \"Wanneer de buitenaardsen een stad terroriseren, zullen ze een aantal speciale eenheden met vreselijke krachten inzetten. Burgers zullen direct worden bedreigd en regeringen zullen worden gedwongen hele gebieden te evacueren. Het belangrijkste doel achter deze activiteit is om voldoende publieke hysterie te genereren zodat regeringen het X-Com-project zullen bedreigen.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"Wanneer X-Com-onderscheppers bijzonder succesvol zijn in het neerhalen van UFO's, kunnen de buitenaardsen wraakacties ondernemen. Dit kan resulteren in een directe aanval op een X-Com-basis. De buitenaardsen moeten echter een X-Com-basis vinden om deze aan te vallen, en op voorwaarde dat UFO's op afstand worden gehouden, zou er weinig gevaar voor een aanval moeten zijn.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"Wanneer een buitenaardse basis eenmaal gebouwd is, dan wordt deze geregeld bevoorraad door een speciaal bevoorradingsschip.  Als een van deze vaartuigen wordt gedetecteerd tijdens het landen, dan weten we zeker dat er een buitenaardse basis in de buurt is.\"\n  STR_SMALL_SCOUT_UFOPEDIA: \"Dit piepkleine vaartuig wordt voornamelijk gebruikt voor verkenning of onderzoek.  Gebruikelijk lopen deze schepen voor op grotere vaartuigen aan het begin van een buitenaardse missie.\"\n  STR_MEDIUM_SCOUT_UFOPEDIA: \"Een verkenningsvaartuig van gemiddelde grootte, welk weinig dreiging vormt voor de aardse krijgsmacht.  Normaal gesproken verschijnt dit voordat de grotere schepen komen tijdens een missie.\"\n  STR_LARGE_SCOUT_UFOPEDIA: \"Het grootste verkenningsvaartuig is een schip voor algemeen gebruik wat ingezet wordt voor verscheidene soorten buitenaardse missies.\"\n  STR_HARVESTER_UFOPEDIA: \"De oogster heeft een klapdeur aan de onderkant en is uitgerust met hef-apparatuur die vee of andere dieren kan optillen.  Lasersnijders worden gebruikt om het gewenste materiaal te onttrekken en het kadaver wordt op de grond gedumpt.  Er zijn ook opslagruimtes voor lichaamsdelen.\"\n  STR_ABDUCTOR_UFOPEDIA: \"Dit vaartuig is uitgerust met een onderzoekskamer waar verschrikkelijke experimenten worden uitgevoerd op menselijke patiënten.  Het slachtoffer wordt meestal op telepatische wijze verlamd, maar blijft op de operatietafel bij bewustzijn.\"\n  STR_TERROR_SHIP_UFOPEDIA: \"Het terreurschip bevat een opslagfaciliteit voor grote buitenaardse terreurwapens of wezens.  Het wordt gebruikt om deze buitenaardse terroristen te verplaatsen naar bevolkte gebieden.\"\n  STR_BATTLESHIP_UFOPEDIA: \"Het slagschip is het grootste en machtigste buitenaardse vaartuig.  Het is gewoonlijk het primaire vaartuig in een missie, en uitgerust met krachtige wapens en een brede bezetting.\"\n  STR_SUPPLY_SHIP_UFOPEDIA: \"Het bevoorradingsschip wordt gebruikt tijdens de aanbouw van buitenaardsen-basissen of om bestaande basissen te bevoorraaden.  Het vervoert voedsel en voortplantingsruimtes.\"\n  STR_DISMANTLE: \"Ontmantel\"\n  STR_FACILITY_IN_USE: \"FACILITEIT IN GEBRUIK\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"KAN FACILITEIT NIET ONTMANTELEN!{SMALLLINE}Alle basisfaciliteiten moeten aangesloten zijn op de toegangslift.\"\n  STR_TRANSFER_ITEMS_TO: \"Verplaats spullen naar {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"GEEN KLIMAATCEL OM NAAR OVER TE BRENGEN!{SMALLLINE}Levende buitenaardse wezens hebben een klimaatcel nodig om te kunnen overleven.\"\n  STR_AMOUNT_AT_DESTINATION: \"AANTAL OP{NEWLINE}BESTEMMING\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"Buitenaardse wezen sterft vanwege het ontbreken van een klimaatcel.\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"GEEN BESCHIKBARE LEEFRUIMTE!{SMALLLINE}De bestemmingsbasis heeft niet genoeg ruimte in de accommodatieblokken voor de aan het vaartuig toegewezen bezetting.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"NIET GENOEG OPSLAGRUIMTE!{SMALLLINE}De bestemmingsbasis heeft niet genoeg opslagruimte voor de uitrusting die is toegewezen aan het voertuig.\"\n  STR_ITEMS_ARRIVING: \"Aankomende Artikelen\"\n  STR_DESTINATION_UC: \"BESTEMMING\"\n  STR_PISTOL: \"Pistool\"\n  STR_PISTOL_CLIP: \"Magazijn Voor Pistool\"\n  STR_RIFLE: \"Geweer\"\n  STR_RIFLE_CLIP: \"Magazijn Voor Geweer\"\n  STR_HEAVY_CANNON: \"Zwaar Kanon\"\n  STR_HC_AP_AMMO: \"ZK-PD-Munitie\"\n  STR_HC_HE_AMMO: \"ZK-HE-Munitie\"\n  STR_HC_I_AMMO: \"ZK-B-Munitie\"\n  STR_AUTO_CANNON: \"Automatisch Kanon\"\n  STR_AC_AP_AMMO: \"AK-PD-Munitie\"\n  STR_AC_HE_AMMO: \"AK-HE-Munitie\"\n  STR_AC_I_AMMO: \"AK-B-Munitie\"\n  STR_ROCKET_LAUNCHER: \"Raketwerper\"\n  STR_SMALL_ROCKET: \"Kleine Raket\"\n  STR_LARGE_ROCKET: \"Grote Raket\"\n  STR_INCENDIARY_ROCKET: \"Brandraket\"\n  STR_GRENADE: \"Granaat\"\n  STR_SMOKE_GRENADE: \"Rookgranaat\"\n  STR_PROXIMITY_GRENADE: \"Afstandsgranaat\"\n  STR_HIGH_EXPLOSIVE: \"Hoog Explosief\"\n  STR_STUN_ROD: \"Verdovingsstok\"\n  STR_HEAVY_PLASMA: \"Zware Plasma\"\n  STR_HEAVY_PLASMA_CLIP: \"Magazijn Voor Zware Plasma\"\n  STR_PLASMA_RIFLE: \"Plasmageweer\"\n  STR_PLASMA_RIFLE_CLIP: \"Magazijn Voor Plasmageweer\"\n  STR_PLASMA_PISTOL: \"Plasmapistool\"\n  STR_PLASMA_PISTOL_CLIP: \"Magazijn Voor Plasmapistool\"\n  STR_BLASTER_LAUNCHER: \"Werper voor Springbommen\"\n  STR_BLASTER_BOMB: \"Springbom\"\n  STR_SMALL_LAUNCHER: \"Kleine werper\"\n  STR_STUN_BOMB: \"Verdovingsbom\"\n  STR_ALIEN_GRENADE: \"Buitenaardse Granaat\"\n  STR_ELERIUM_115: \"Elerium-115\"\n  STR_MIND_PROBE: \"Gedachtenlezer\"\n  STR_SECTOID_CORPSE: \"Lichaam van Sectoïde\"\n  STR_SNAKEMAN_CORPSE: \"Lichaam van Slangeman\"\n  STR_ETHEREAL_CORPSE: \"Lichaam van Etheriër\"\n  STR_MUTON_CORPSE: \"Lichaam van Muton\"\n  STR_FLOATER_CORPSE: \"Lichaam van Zwever\"\n  STR_CELATID_CORPSE: \"Lichaam van Celatide\"\n  STR_SILACOID_CORPSE: \"Lichaam van Silacoïde\"\n  STR_CHRYSSALID_CORPSE: \"Lichaam van Chrysalide\"\n  STR_REAPER_CORPSE: \"Lichaam van Vreter\"\n  STR_SECTOPOD_CORPSE: \"Lichaam van Sectopod\"\n  STR_CYBERDISC_CORPSE: \"Lichaam van Cyberdisc\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"Niet genoeg munitie voor bewapening van HWP{SMALLLINE}Elke HWP vereist {0} {1}.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Onvoldoende materieel om geweergroep volledig opnieuw uit te rusten.\"\n  STR_MARS_CYDONIA_LANDING: \"Mars: Landing in Cydonia\"\n  STR_MARS_CYDONIA_LANDING_BRIEFING: \"Je Wreker-vaartuig is geland op de Cydonia-vlakte van Mars.  Volgens onze informatie bevat een van de piramidevormige gebouwen een groene toegangslift naar een ondergronds complex.  Wanneer je al je soldaten hebt verzameld in het liftgebied, klik op het icoon  'missie afbreken' om door te gaan naar de volgende fase.\"\n  STR_MARS_THE_FINAL_ASSAULT: \"Mars: De Laatste Aanval\"\n  STR_MARS_THE_FINAL_ASSAULT_BRIEFING: \"De lift in de piramide vervoert je - door de strijd vermoeide - soldaten diep onder het oppervlak van de planeet.  Ze komen aan in het hart van een groot complex van tunnels en kamers.  Het buitenaardse brein zit ergens in het doolhof verscholen.  Het moet vernietigd worden om de aarde te redden van buitenaardse onderdrukking.{NEWLINE}{NEWLINE}Veel Succes!\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Doe onderzoek naar{NEWLINE}{0}{NEWLINE} voor de productie van{NEWLINE}{1}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"De aliens hebben de onverdedigde basis {0} vernietigt.\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"X-Com agenten hebben een buitenaardse basis gelokaliseerd in {0}\"\n  STR_STANDOFF: \"HOU AFSTAND\"\n  STR_CAUTIOUS_ATTACK: \"VOORZICHTIGE AANVAL\"\n  STR_STANDARD_ATTACK: \"STANDAARDAANVAL\"\n  STR_AGGRESSIVE_ATTACK: \"AGGRESSIEVE AANVAL\"\n  STR_DISENGAGING: \"TREKT TERUG\"\n  STR_UFO_HIT: \"UFO GERAAKT!\"\n  STR_UFO_CRASH_LANDS: \"UFO STORT NEER!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Minimaliseren Enkel op Veilige Afstand\"\n  STR_UFO_RETURN_FIRE: \"UFO VUURT TERUG!\"\n  STR_INTERCEPTOR_DAMAGED: \">>> ONDERSCHEPPER BESCHADIGD <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> ONDERSCHEPPER VERNIETIGD <<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"UFO ONTSNAPT AAN ONDERSCHEPPER!\"\n  STR_ALIENS_TERRORISE: \"BUITENAARDSEN TERRORISEREN\"\n  STR_LONG_RANGE_DETECTION: \"Lange-afstandsdetectie\"\n  STR_STORES_UC: \"OPSLAGRUIMTE\"\n  STR_DIFFICULTY_LEVEL: \"Moeilijkheidsgraad\"\n  STR_INTERCEPT: \"ONDERSCHEPPING\"\n  STR_BASES: \"BASISSEN\"\n  STR_GRAPHS: \"GRAFIEKEN\"\n  STR_UFOPAEDIA_UC: \"UFOPEDIE\"\n  STR_OPTIONS_UC: \"OPTIES\"\n  STR_FUNDING_UC: \"FINANCIERING\"\n  STR_5_SECONDS: \"5 Sec\"\n  STR_1_MINUTE: \"1 Min\"\n  STR_5_MINUTES: \"5 Min\"\n  STR_30_MINUTES: \"30 Min\"\n  STR_1_HOUR: \"1 Uur\"\n  STR_1_DAY: \"1 Dag\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"X-Com prestatie Rooster\"\n  STR_ENTER_NAME: \"Naam Invoeren\"\n  STR_PERFORMANCE_RATING: \"Beoordeling van Prestatie\"\n  STR_VICTORY_DATE: \"Datum Overwinning\"\n  STR_ELECTRO_FLARE: \"Elektrische Fakkel\"\n  STR_ELECTRO_FLARE_UFOPEDIA: \"Dit compacte apparaatje produceert een fel licht wanneer het gegooid wordt.  Het kan de positie van vijandelijke eenheden in de buurt van de fakkel verlichten tijdens nachtelijke missies.\"\n  STR_MONTHLY_COSTS: \"Maandelijkse Kosten\"\n  STR_CRAFT_RENTAL: \"Huur Vaartuigen\"\n  STR_SALARIES: \"Salarissen\"\n  STR_BASE_MAINTENANCE: \"Onderhoud Basis\"\n  STR_COST_PER_UNIT: \"Kosten per eenheid\"\n  STR_QUANTITY: \"Aantal\"\n  STR_TOTAL: \"Totaal\"\n  STR_IN_PSIONIC_TRAINING: \"In Psionische Training\"\n  STR_BLASTER_BOMB_UFOPEDIA: \"Dit is een zeer explosief projectiel met een intelligente telegeleiding.  Het wordt afgevuurd met behulp van een speciale werper voor deze 'springbommen'.\"\n  STR_FRONT_ARMOR: \"Pantser Voor\"\n  STR_LEFT_ARMOR: \"Pantser Links\"\n  STR_RIGHT_ARMOR: \"Pantser Rechts\"\n  STR_REAR_ARMOR: \"Pantser Achter\"\n  STR_UNDER_ARMOR: \"Pantser Onder\"\n  STR_ROUNDS: \"Patronen\"\n  STR_UNIT: \"EENHEID> {0}\"\n  STR_ENERGY: \"ENERGIE\"\n  STR_MORALE: \"MOREEL\"\n  STR_ARMOR_: \"PANTSER> {0}\"\n  STR_FRONT_ARMOR_UC: \"PANTSER VOOR\"\n  STR_LEFT_ARMOR_UC: \"PANTSER LINKS\"\n  STR_RIGHT_ARMOR_UC: \"PANTSER RECHTS\"\n  STR_REAR_ARMOR_UC: \"PANTSER ACHTER\"\n  STR_SKILLS: \"VAARDIGHEDEN> {0}\"\n  STR_LEVEL: \"NIVEAU> {0}\"\n  STR_HEAD: \"HOOFD\"\n  STR_TORSO: \"ROMP\"\n  STR_RIGHT_ARM: \"RECHTERARM\"\n  STR_LEFT_ARM: \"LINKERARM\"\n  STR_RIGHT_LEG: \"RECHTERBEEN\"\n  STR_LEFT_LEG: \"LINKERBEEN\"\n  STR_PAIN_KILLER: \"PIJNSTILLER\"\n  STR_STIMULANT: \"OPWEKKEND MIDDEL\"\n  STR_HEAL: \"GENEZEN\"\n  STR_TIME_UNITS_SHORT: \"AP>{ALT}{0}\"\n  STR_WEIGHT: \"Gewicht>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"React>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"P.Skill>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"P.Str>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Buitenaards Voorwerp\"\n  STR_AMMO_ROUNDS_LEFT: \"MUNITIE:{NEWLINE}KOGELS{NEWLINE}OVER={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Pijn>{ALT}{0}{ALT}{NEWLINE}Stim>{ALT}{1}{ALT}{NEWLINE}Helen>{ALT}{2}\"\n  STR_THROW: \"Werpen\"\n  STR_AUTO_SHOT: \"Autom. Schot\"\n  STR_SNAP_SHOT: \"Vlug Schot\"\n  STR_AIMED_SHOT: \"Gericht Schot\"\n  STR_STUN: \"Verdoven\"\n  STR_PRIME_GRENADE: \"Granaat Afstellen\"\n  STR_USE_SCANNER: \"Gebruik Scanner\"\n  STR_USE_MEDI_KIT: \"Gebruik Medicijnkit\"\n  STR_LAUNCH_MISSILE: \"Afvuren Projectiel\"\n  STR_ACCURACY_SHORT: \"Acc>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Onvoldoende Actiepunten!\"\n  STR_NOT_ENOUGH_ENERGY: \"Onvoldoende Energie!\"\n  STR_NO_ROUNDS_LEFT: \"Geen Resterende Patronen!\"\n  STR_NO_AMMUNITION_LOADED: \"Wapen Niet geladen!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Vekeerde Munitie voor dit wapen!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"Wapen is reeds Geladen!\"\n  STR_NO_LINE_OF_FIRE: \"Obstructie in de Vuurlinie!\"\n  STR_GRENADE_IS_ACTIVATED: \"Granaat is Geactiveerd!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Granaat is  Gedeactiveert\"\n  STR_THERE_IS_NO_ONE_THERE: \"Daar staat niemand!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Kan buitenaards voorwerp niet gebruiken totdat het onderzocht is!\"\n  STR_OUT_OF_RANGE: \"Buiten Bereik!\"\n  STR_UNABLE_TO_THROW_HERE: \"Kan hier niet heen gooien!\"\n  STR_SET_TIMER: \"Tijd Instellen\"\n  STR_HIDDEN_MOVEMENT: \"VERBORGEN ACTIE\"\n  STR_TURN: \"BEURT>{0}\"\n  STR_SIDE: \"ZIJDE> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Druk een toets om verder te gaan\"\n  STR_MIND_CONTROL: \"Hersenspoelen\"\n  STR_PANIC_UNIT: \"EENHEID BEANGSTIGEN\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Moreel Aanval Succesvol\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Hersenspoelen Gelukt\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}is Dol geworden\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}is Dol geworden\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}is in paniek\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}is in paniek\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Buitenaardsen\"\n  STR_RIGHT_HAND: \"RECHTERHAND\"\n  STR_LEFT_HAND: \"LINKERHAND\"\n  STR_RIGHT_SHOULDER: \"RECHTERSCHOUDER\"\n  STR_LEFT_SHOULDER: \"LINKERSCHOUDER\"\n  STR_BACK_PACK: \"RUGZAK\"\n  STR_BELT: \"RIEM\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}is onder buitenaardse invloed\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}is onder buitenaardse invloed\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}is bewusteloos geraakt\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}is bewusteloos geraakt\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}is dood gegaan door een fatale wond\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}is dood gegaan door een fatale wond\"\n  STR_USE_MIND_PROBE: \"Gebruik Gedachtenlezer\"\n  STR_FATAL_WOUNDS: \"FATALE WONDEN\"\n  STR_UNDER_ARMOR_UC: \"PANTSER ONDER\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Actiepunten gereserveerd voor Vlug Schot\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Actiepunten gereserveerd voor Automatisch Schot\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Actiepunten gereserveerd voor Gericht Schot\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Actiepunten gereserveerd voor knielen\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"Actiepunten gereserveerd voor Knielen en Vuren\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} Eenheid in X-Com Voertuig\"\n    other: \"{N} Eenheden in X-Com Voertuig\"\n  STR_UNITS_OUTSIDE:\n    one: \"{N} Eenheid buiten gelaten\"\n    other: \"{N} Eenheden buiten gelaten\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} Eenheid voor Ingang\"\n    other: \"{N} Eenheden voor Ingang\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} Eenheid bij Doel Uitgang\"\n    other: \"{N} Eenheden bij Doel Uitgang\"\n  STR_ABORT_MISSION_QUESTION: \"Missie Afbreken ?\"\n  STR_CORPSE: \"Lichaam\"\n  STR_UNLOAD_CRAFT: \"Uitladen\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}is gedood\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}is gedood\"\n  STR_HIT_MELEE: \"Slag\"\n  STR_GROUND: \"GROND\"\n  STR_LIVING_QUARTERS_PLURAL: \"Leefruimtes\"\n  STR_LIST_ITEM: \"ARTIKEL\"\n  STR_PERSONAL_ARMOR_UFOPEDIA: \"Met behulp van de nieuw ontdekte Alien Alloys, geeft dit nieuwe pantser onze mannen een kans de buitenaardse dreiging te bestrijden.\"\n  STR_POWER_SUIT_UFOPEDIA: \"Een krachtige nieuwe bescherming voor soldaten, dit pantser word aangedreven door een Elerium energie bron en versterkt aanzienlijk de snelheid en sterkte van de drager, het bied de beste bescherming voor gevechtstroepen tot nu toe.\"\n  STR_FLYING_SUIT_UFOPEDIA: \"Een verbeterde versie van de Power Suit, met buitenaardse anti-zwaartekrachtnavigatietechnologie voor volledige bewegingsvrijheid over het slagveld.\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"Alle aliens zijn overleden bij het neerstorten,{NEWLINE}Automatische berging gestart\"\n  STR_RESET: \"Reset\"\n  STR_MEMORIAL: \"Herdenking\"\n  STR_DATE_UC: \"DATUM\"\n  STR_SOLDIERS_RECRUITED_UC: \"SOLDATEN GERECRUTEERD>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"SOLDATEN VERLOREN>{ALT}{0}\"\n  MAP_CULTA: \"Platteland\"\n  MAP_FOREST: \"Bosrijk Gebied\"\n  MAP_JUNGLE: \"Oerwoud\"\n  MAP_MOUNT: \"Gebergte\"\n  MAP_DESERT: \"Woestijn\"\n  MAP_POLAR: \"Poolgebied\"\n  MAP_URBAN: \"Stad\"\n  MAP_UBASE: \"Buitenaardse Basis\"\n  MAP_XBASE: \"X-Com Basis\"\n  MAP_MARS: \"Mars\"\n  STR_MIXED: \"Gemengd\"\n  STR_REMOVE_SELECTED: \"Verwijder Geselecteerd\"\n  STR_LIVE_ALIENS: \"Levend{NEWLINE}Exemplaar\"\n  STR_DEAD_ALIENS: \"Afgewezen{NEWLINE}Exemplaar\"\n  STR_UNDER_INTERROGATION: \"Wezen{NEWLINE}Bestudeerd\"\n  STR_CONTAINMENT_EXCEEDED: \"LIMIET BUITENAARDSE KLIMAATCEL OVERSCHREDEN!{SMALLLINE}Onvoldoende opslagruimte in {0}. Verwijder overtollige buitenaardse wezens van de klimaatcellen (zij zullen sterven).\"\n  STR_MANAGE_CONTAINMENT: \"Beheer Buitenaardse Klimaatcellen\"\n  STR_STORAGE_EXCEEDED: \"OPSLAGRUIMTE OVERSCHREDEN!{SMALLLINE}Onvoldoende opslagruimte voor {0}. U moet overtollige zaken verkopen.\"\n  STR_GO_TO_BASE: \"Ga naar Basis\"\n  STR_MELEE_ACCURACY: \"HANDGEVECHT NAUWKEURIGHEID\"\n  STR_SELL_PRODUCTION: \"VERKOOP\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Beide handen moeten leeg zijn!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Niet genoeg spullen om sjabloon te kopieren\"\n  STR_UNLOAD_WEAPON: \"Ongeladen wapen\"\n  STR_ALL_ITEMS: \"Alle spullen\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"GEEN UITRUSTING MEER TOEGESTAAN AAN BOORD!{SMALLLINE}Je mag maximaal {N} artikel meenemen op dit vaartuig.\"\n    other: \"GEEN UITRUSTING MEER TOEGESTAAN AAN BOORD!{SMALLLINE}Je mag maximaal {N} artikelen meenemen op dit vaartuig.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}CONTROLE CENTRUM VERNIETIGD{NEWLINE}Ga naar de ingang en breek de missie af.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"X-Com faciliteiten kunnen niet onderwater gebouwd worden\"\n  STR_LEVEL_SHORT: \"{0}\"\n  STR_PERSONNEL: \"Personeel\"\n  STR_CRAFT_ARMAMENT: \"Voertuigen & Bewapening\"\n  STR_COMPONENTS: \"Componenten\"\n  STR_SOLDIERS_RECRUITED: \"Soldaten gerecruteerd\"\n  STR_SOLDIERS_LOST: \"Soldaten verloren\"\n  STR_TOTAL_UFOS: \"UFOs gedetecteerd\"\n  STR_TOTAL_ALIEN_BASES: \"Buitenaardse basissen ontdekt\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"PST\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"PSK\"\n  FEMALE_CIVILIAN: \"Burger, Vrouw\"\n  MALE_CIVILIAN: \"Burger, Man\"\n  CYBERDISC_WEAPON: \"Cyberdisc Wapen\"\n  REAPER_WEAPON: \"Reaper Wapen\"\n  CHRYSSALID_WEAPON: \"Chryssalid Wapen\"\n  CELATID_WEAPON: \"Celatid Wapen\"\n  SILACOID_WEAPON: \"Silacoid Wapen\"\n  SECTOPOD_WEAPON: \"Sectopod Wapen\"\n  ZOMBIE_WEAPON: \"Zombie Wapen\"\n  ALIEN_PSI_WEAPON: \"Buitenaards Psi Wapen\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/no.yml",
    "content": "\"no\":\n  STR_AVENGER_UFOPEDIA: \"KOMBINERT TROPPETRANSPORT OG STRIDSFARTØY.  DEN ULTIMATE REPRODUKSJONEN AV UTENOMJORDISK TEKNOLOGI.\"\n  STR_INTERCEPTOR_UFOPEDIA: \"JAGERFLY MED DOBLE PULSDETONASJONSMOTORER OG SPESIELT BESKYTTEDE ELEKTRONISKE SYSTEMER.  DEN BESTE TEKNOLOGIEN JORDEN HAR TILGJENGELIG.\"\n  STR_LIGHTNING_UFOPEDIA: \"KOMBINERT TROPPETRANSPORT OG KAMPFLY.  EN GROVBYGD MEN EFFEKTIV REPRODUKSJON AV UTENOMJORDISKE DRIVSYSTEMER.\"\n  STR_SKYRANGER_UFOPEDIA: \"TROPPETRANSPORT.  DET HURTIGSTE I SITT SLAG SOM KAN FORETA VERTIKAL TAKE-OFF OG LANDING (V.T.O.L.).\"\n  STR_FIRESTORM_UFOPEDIA: \"KAMPFLY.  DENNE ENMANNS-JAGEREN KOPIERER DET KLASSISKE UTENOMJORDISKE FLYVENDE TALLERKEN-DESIGNET, MED ET SENTRALT DRIVSYSTEM.\"\n  STR_STINGRAY_UFOPEDIA: \"AVANSERT LUFT-TIL-LUFT MISSIL MED SPESIELT SKJERMET ELEKTRONIKK.\"\n  STR_AVALANCHE_UFOPEDIA: \"EKSTREMT TUNGVEKTIG LUFT-TIL-LUFT MISSIL MED ATOM-STRIDSHODE.\"\n  STR_CANNON_UFOPEDIA: \"KRAFTIG KANON SOM AVFYRER PANSERBRYTENDE PROSJEKTILER SOM KAN PENETRERE 16 TOMMER TYKT STÅL.\"\n  STR_FUSION_BALL_UFOPEDIA: \"DENNE AVFYRER EN KULEFORMET MISSIL DREVET FREM AV EN ANTI-MATERIE REAKSJON. KULEN ØDELEGGER MÅLET MED EN GRAVITASJONSBØLGE IMPLOSJON.\"\n  STR_LASER_CANNON_UFOPEDIA: \"DENNE KONVENSJONELLE LASERSTRÅLEN ER DREVET AV ETT ANTI-MATERIE REAKSJONSKAMMER.\"\n  STR_PLASMA_BEAM_UFOPEDIA: \"DENNE GRAVITASJONS-STRÅLEN DIRIGERER ETT NØYE KANALISERT IMPLODERENDE GRAVITASJONSFELT.\"\n  STR_SECTOID_UFOPEDIA: \"Sektoidenes hierarki strekker seg fra soldater til ledere med kraftfulle psioniske evner.  Disse psioniske kreftene kan brukes til å demoralisere soldater i kamp, eller til og med ta kontroll over deres sinn.  De hengir seg gjerne til å bortføre mennesker og lemleste kveg.  Bortføringene har som mål å utvinne genetisk materiale til kryssavl og utvikle kloner for å infiltrere menneskenes samfunn.  Kveget gir både næring og genetisk materiale.  Denne rasen ser ut til å ønske å utvikle overlegne genetiske hybrider for å øke effektiviteten i deres bikube-lignende samfunn.\"\n  STR_SECTOID_AUTOPSY: \"Obduksjon av Sectoide\"\n  STR_SECTOID_AUTOPSY_UFOPEDIA: \"Obduksjonen avdekker et tilbakedannet fordøyelsessystem og en enkel struktur.  Hjernen og øynene er svært godt utviklet.  Strukturen tyder på genetisk forandring eller mutasjon.  Den lille munnen og nesen synes å ha liten funksjon.  Svømmehuden mellom fingrene og de flate føttene tyder på en akvatisk opprinnelse.  Det er ingen kjønnsorganer, og ingen ledetråder til hvordan denne arten kan reprodusere.  De er mest sannsynlig en genmanipulert art.\"\n  STR_SNAKEMAN_UFOPEDIA: \"Denne arten utviklet seg i et svært fiendtlig miljø.  De er ekstremt robuste og kan motstå ekstreme temperaturvariasjoner.  Deres mobilitet er basert på en stor, slangelignende 'fot' som beskytter alle vitale organer.  Deres mål synes å være rent rov, og de ser ut til å være under kommando av en annen intelligens som styrer deres militær-lignende angrep på Jorden.\"\n  STR_SNAKEMAN_AUTOPSY: \"Obduksjon av Slangemann\"\n  STR_SNAKEMAN_AUTOPSY_UFOPEDIA: \"Huden er meget robust og motstandsdyktig mot varme.  Det kardiovaskulære systemet er del av muskel-systemet som benytter hydrauliske prinsipper for å skape bevegelse.  Den eneste egentlige muskelen er 'hjertet'.  Det reproduktive systemet ser ut til å være svært effektivt.  Reproduksjonen er ukjønnet, med hver slangemann bærende på opptil 50 egg i kroppen til enhver tid.  Overlatt til seg selv vil denne arten være en alvorlig trussel mot livet på Jorden.\"\n  STR_ETHEREAL_UFOPEDIA: \"Dette vesenet har fantastiske mentale krefter som gir mulighet for telepatisk kommunikasjon og telekinetiske evner.  De tilsynelatende svake fysiske evnene blir holdt oppe av skapningens mentale krefter.  Vi forstår ikke hvordan disse telekinetiske kreftene fungerer, siden de ser ut til å trosse fysikkens lover slik vi kjenner dem.  De er ekstremt farlige i enhver kampsituasjon, der de bruker sine mentale krefter til kamp.  De dukker sjelden opp på Jorden, siden de ser ut til å være avhengige av andre raser for å forfølge sine mål.\"\n  STR_ETHEREAL_AUTOPSY: \"Obduksjon av Eterisk\"\n  STR_ETHEREAL_AUTOPSY_UFOPEDIA: \"Dette vesenet er fysisk tilbakestående og virker ute av stand til å opprettholde grunnleggende livsfunksjoner.  Musklene er sterkt forkrøplet og de indre organer virker underutviklet.  Sanseorganene, inkudert øynene, ser ikke ut til å fungere i det hele tatt.  Hjernen derimot er godt utviklet og krever en stor andel av kroppens blodtilførsel.  Det er et mysterium hvordan denne skapningen kan klare seg selv uten ekstern støtte.\"\n  STR_MUTON_UFOPEDIA: \"Denne menneskelignende skapningen er fysisk sterk og intelligent.  De har en spesiell appetitt for rått kjøtt av alle slag, som de trenger for å overleve som jordbaserte kjøttetere.  De ser ut til å være avhengige av telepatiske kommandoer fra en rase som kalles 'Eteriske'.  Når de blir skilt fra denne telepatisk koblingen ser deres mentale system ut til å kollapse og de dør.  De kybernetiske implantatene brukes til å forbedre sin kampytelse.  De er helt klart fotsoldater for en høyere intelligens.\"\n  STR_MUTON_AUTOPSY: \"Obduksjon av Muton\"\n  STR_MUTON_AUTOPSY_UFOPEDIA: \"'Huden' til denne skapningen synes å være en organisk laget beskyttelsesarmering som er podet på kroppen.  Det er mange kybernetiske implantater som anvendes for å forbedre hjerte-kar-systemet og sansene.  Reproduktive organer synes å ha blitt kirurgisk fjernet.  Tydeligvis er disse uheldige skapninger begrenset til et liv i krig og erobring.  Panserbrytende ammunisjon er ikke veldig effektiv mot deres herdede hud.\"\n  STR_CELATID_UFOPEDIA: \"Denne livsformen har en mystisk naturlig evne til å sveve gjennom luften.  Den ser ut til å sanse menneskelige hjernebølger og vil bevege seg mot menneskelige mål selv om de er godt skjult.  Når et mål er lokalisert lander Celatiden på bakken og skyter små klyser av ekstremt etsende syre.  Skapningen har evnen til å klone seg selv i et urovekkende tempo.  De følger med Muton-rasen i sine vandringer.\"\n  STR_CELATID_AUTOPSY: \"Obduksjon av Celatide\"\n  STR_CELATID_AUTOPSY_UFOPEDIA: \"Vesenets kjerne inneholder en liten bio-mekanisk innretning som synes å være et naturlig utviklet antigravitasjons-fremdriftssystem.  Giftsekken er det største organet, og det ser ikke ut til å være noen separat hjernestruktur.  Det er ingen opplagte fordøyelse eller reproduktive systemer.  Et lite organ inneholder embryoer som raskt kan vokse til et nytt vesen.\"\n  STR_SILACOID_UFOPEDIA: \"Denne silisium-baserte livsformen genererer en enorm mengde varme.  Den har styrke nok til å knuse stein som deretter kan inntas av den varme kjernen.  Den har en primitiv intelligens og kan kontrolleres av implantater eller telepatiske vesener.  Den arbeider sammen med Mutonene.\"\n  STR_SILACOID_AUTOPSY: \"Obduksjon av Kiseldyr\"\n  STR_SILACOID_AUTOPSY_UFOPEDIA: \"Kjernen i dyret er svært varmt, og synes å være basis for et fordøyelsessystem.  Dens unike muskel-systeme har enorm kraft og fart.  Dens stein-aktig hud blir ikke skadet av brann eller brannstifter ammunisjon.\"\n  STR_CHRYSSALID_UFOPEDIA: \"De krabbe-lignende klørne til denne skapningen er kraftfulle nærkampvåpen.  Det høye stoffskiftet og styrken gir denne skapningen fart og smidighet.  I stedet for å drepe sitt offer befruktes det med et egg samtidig som en gift injiseres, noe som gjør offeret til en vandrende zombie.  En ny Draug vil sprenge seg ut av offeret kort tid etter befruktningen.  Draugene er forbundet med Slangemann-rasen.\"\n  STR_CHRYSSALID_AUTOPSY: \"Obduksjon av Draug\"\n  STR_CHRYSSALID_AUTOPSY_UFOPEDIA: \"Det utvendige skjelettet til denne skapningen er ekstremt robust, men overraskende sårbart for eksplosiv ammunisjon.  Hjernen er godt utviklet, og dens cellevekstrate er veldig rask.  Skapningen bærer 20 egg som legges inne i andre organismer.  Denne skapningen er et svært effektiv terrorvåpen.\"\n  STR_FLOATER_UFOPEDIA: \"Sveverne er først og fremst soldater og terrorister.  De er naturlig rovdyraktige beist, genmanipulerte og kybernetisk forbedret for å bli formidable krigere.  Den nedre halvdelen av kroppen og de fleste indre organer er kirugisk fjernet og erstattet med et kunstig livsopprettholdende system.  Dette implantatet inneholder en antigravitasjonsenhet som gjør det mulig for skapning å sveve, om enn noe ustødig, gjennom luften.\"\n  STR_FLOATER_AUTOPSY: \"Obduksjon av Svever\"\n  STR_FLOATER_AUTOPSY_UFOPEDIA: \"Skapningen har blitt drastisk forandret gjennom kirurgi.  Enheten som ser ut til å utgjøre kjernen av kroppen er et livsopprettholdende system, som overtar funksjonene til hjertet, lungene og fordøyelsessystemet.  Dette vil gi skapningen mulighet for å overleve i ekstremt fiendtlige miljøer.  Hjernen er mindre enn vår, men sanseorganene er godt utviklede.\"\n  STR_REAPER_UFOPEDIA: \"Denne tobente kjøtteteren har kraftige kjever og en glupsk appetitt.  Den har et antall hjerneimplantater som brukes til å styre dens adferd.  De primitive rovdyrinstinktene til denne skapningen er til liten nytte bortsett fra til å terrorisere og ødelegge.  Treskere er ofte forbundet med Svevere.\"\n  STR_REAPER_AUTOPSY: \"Obduksjon av Tresker\"\n  STR_REAPER_AUTOPSY_UFOPEDIA: \"Treskeren har to 'hjerner' og to 'hjerter' som gjør at den kan fungere selv når den er sterkt såret.  Men pelsen dens er meget lettantennelig, noe som gjør skapningen sårbar for brannvåpen.\"\n  STR_SECTOPOD_UFOPEDIA: \"Sektopoder er robot-skapninger utrustet med et kraftfullt laserstråle-våpen.  Kontrollen av disse mekaniske beistene skjer via en telepatisk link til sine kontrollere, de Eteriske.  Sektopoder er de kraftigste terrorvåpen tilgjengelig til de utenomjordiske.\"\n  STR_SECTOPOD_AUTOPSY: \"Obduksjon av Sectopode\"\n  STR_SECTOPOD_AUTOPSY_UFOPEDIA: \"Roboten er robust konstruert med drevet rustning stand til å motstå de fleste former for angrep, særlig plasmavåpen.  Imidlertid synes sensorkretsene særlig utsatt for laservåpen.\"\n  STR_CYBERDISC_UFOPEDIA: \"Denne lille flyvende tallerkenen er et automatisert terrorvåpen bevæpnet med en kraftfull plasmastråle.  Antigravitasjons-fremdriften gir den en stor fordel i ulendt terreng.  Dens fremste funksjon er ødeleggelse og terror i Sektoidenes tjeneste.\"\n  STR_CYBERDISC_AUTOPSY: \"Demontering av Cyberdisk\"\n  STR_CYBERDISC_AUTOPSY_UFOPEDIA: \"Svevetallerkenen er godt skjermet og er spesielt motstandsdyktig mot eksplosiver.  Det primære antigravitasjonssystemet er for sterkt skadet til å få noen forståelse av hvordan det fungerer.\"\n  STR_UFO_POWER_SOURCE_UFOPEDIA: \"Kraftkilden for utenomjordiske fartøyer er en antimaterie-reaktor som bruker Elerium (grunnstoff 115) for å generere kraftige gravitasjonsbølger, så vel som andre former for energi. Konverteringen av materie til energi er utrolige 99% effektivt, derfor kan ørsmå mengder Elerium produsere en stor mengde kraft. Denne enheten kan enkelt reproduseres ved hjelp av utenomjordiske legeringer.\"\n  STR_UFO_NAVIGATION_UFOPEDIA: \"Utenomjordiske fartøy bruker avanserte datamaskiner for å navigere på jorden og i verdensrommet. Systemet er basert på optiske prosessorer arrangert i et nettverk. Kontrollgrensesnittet er relativt enkelt - navigatøren styrer retningen av gravitasjonsbølger som genereres av kraftkilden for å bevege fartøyet i enhver retning. Dette systemet kan enkelt brukes av mennesker, og det kan bli reprodusert med utenomjordiske legeringer og andre komponenter.\"\n  STR_UFO_CONSTRUCTION_UFOPEDIA: \"Utenomjordiske fartøy bestående av tre hovedkomponenter -  en energikilde, ett navigasjonssystem samt ett skrog laget av utenomjordiske legeringer. Skroget er spesialdesignet for å tillate dirigering og kontrollering av gravitasjons-bølger. I tillegg er en liten mengde Elerium påkrevet for å drive energikilden. Når disse konstruksjonprinsippene er forstått, samt funksjonene til hver av komponentene er kjent, da er det mulig å bygge denne typen fartøy.\"\n  STR_ALIEN_FOOD_UFOPEDIA: \"Disse kamrene inneholder diverse enzymer som blir brukt til å fordøye kroppsdeøer fra kyr, andre dyr og også mennesker. Væsken blir deretter konsumert som allerede-fordøyd næring. - mest sannsynlig ved intravenøs tilførsel. Dette antyder ett visst nivå av avhengighet av jorden for kontinuerlig næringstilførsel.\"\n  STR_ALIEN_REPRODUCTION_UFOPEDIA: \"Disse kamrene inneholder alien-foster. Designet på disse beholderne antyder at de aliens som benytter denne prosessen er helt avhengig av laboratorium-basert reproduksjon. Den rikholdige næringstilførselen sikrer rask utvikling av fosteret. Denne samlebånd-metoden kan produsere tusenvis av alien-kloner innenfor kort tid. Prosessen vil enkelt kunne benyttes ved menneskelig reproduksjon., eller for alien-menneske hybrider.\"\n  STR_ALIEN_ENTERTAINMENT_UFOPEDIA: \"Den mest sannsynlige funksjon av disse sfærene er rekreasjon. De psioniske kretsene stimulerer ulike sentre i hjernen. Effekten er lik hallusinogene stoffer. Dette er det eneste bevis for at utenomjordiske har noen form for kultur eller fritidssysler.\"\n  STR_ALIEN_SURGERY_UFOPEDIA: \"Dette kirurgisk utstyret bruker laser kuttere for å ekstrahere visse kroppsdeler fra storfe og andre dyr. Den utbredte lemlestelsen av storfe kan forklares ved denne bisarre utenomjordiske aktiviteten. Det er sannsynlig at disse delene blir brukt til ernæringsmessige eller genetiske formål.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"I gjennom historien har mange tusen mennesker hevdet å ha blitt bortført av romvesener, noen flere ganger. Sannheten er langt mer forferdelig. Mennesker blir bortført, undersøkt og overvåket. De beste eksemplarene for sitt genetiske materiale ekstrahert. Kvinner får menneske-romvesen hybrid fostre implantert og deretter fjernet flere måneder senere. Hvem vet hva skumle motiver romvesenene har?\"\n  STR_ALIEN_ALLOYS_UFOPEDIA: \"Utenomjordisk fartøy er konstruert i spesiallegeringer som innehar unike egenskaper. De er ekstremt lett-vektig og holdbare, og kan bli formet med elektromagnetiske metoder. Dette materialet kan reproduseres og kan benyttes i ett mangfold av produksjonsprosesser.\"\n  STR_ELERIUM_115_UFOPEDIA: \"Dette grunnstoffet har den uvanlige egenskapen at det genererer antimaterie-energi når det bombarderes med visse partikler.  Dette skaper gravitasjonsbølger og andre former for energi.  Det finnes ikke naturlig i vårt solsystem, og kan ikke reproduseres.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"SENTRER PÅ STED - TID=5 Sek\"\n  STR_CANCEL_UC: \"AVBRYT\"\n  STR_NONE: \"Ingen\"\n  STR_UNKNOWN: \"Ukjent\"\n  STR_POOR: \"Dårlig\"\n  STR_AVERAGE: \"Middels\"\n  STR_GOOD: \"God\"\n  STR_EXCELLENT: \"Fantastisk\"\n  STR_BUILD_NEW_BASE_UC: \"BYGG NY BASE\"\n  STR_BASE_INFORMATION: \"BASE-INFORMASJON\"\n  STR_EQUIP_CRAFT: \"UTRUST FARTØY\"\n  STR_BUILD_FACILITIES: \"BYGG FASILITETER\"\n  STR_RESEARCH: \"FORSKNING\"\n  STR_MANUFACTURE: \"PRODUKSJON\"\n  STR_TRANSFER_UC: \"OVERFØR\"\n  STR_PURCHASE_RECRUIT: \"KJØP/ANSETT\"\n  STR_SACK: \"SPARK\"\n  STR_SELL_SACK_UC: \"SELG/SPARK\"\n  STR_GEOSCAPE_UC: \"JORDKLODE\"\n  STR_NAME: \"Navn\"\n  STR_AREA: \"Område\"\n  STR_BUILD_NEW_BASE: \"Bygg Ny Base\"\n  STR_CANCEL: \"Avbryt\"\n  STR_COST_UC: \"KOSTNAD>\"\n  STR_CONSTRUCTION_TIME_UC: \"BYGGE-PERIODE>\"\n  STR_DAY:\n    one: \"{N} dag\"\n    other: \"{N} dager\"\n  STR_HOUR:\n    one: \"{N} time\"\n    other: \"{N} timer\"\n  STR_MAINTENANCE_UC: \"VEDLIKEHOLD>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Installasjon\"\n  STR_CURRENT_RESEARCH: \"NÅVÆRENDE FORSKNING\"\n  STR_SCIENTISTS_AVAILABLE: \"Ledige Forskere>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Forskere i Arbeid>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Ledig Laboratorie-Plass>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"FORSKNINGS-PROSJEKT\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"FORSKERE I ARBEID\"\n  STR_PROGRESS: \"FREMGANG\"\n  STR_NEW_PROJECT: \"Nytt Prosjekt\"\n  STR_CANCEL_PROJECT: \"AVBRYT PROSJEKT\"\n  STR_NEW_RESEARCH_PROJECTS: \"NYE FORSKNINGS-PROSJEKTER\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"LEDIGE FORSKERE>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"LEDIG LABORATORIE-PLASS>{ALT}{0}\"\n  STR_INCREASE: \"Flere\"\n  STR_DECREASE: \"Færre\"\n  STR_START_PROJECT: \"START PROSJEKT\"\n  STR_CURRENT_PRODUCTION: \"NÅVÆRENDE PRODUKSJON\"\n  STR_ENGINEERS_AVAILABLE: \"Ledige Ingeniører>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Ingeniører i Arbeid>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Ledig Verksted-Plass>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Tilgjengelige Midler>{ALT}{0}\"\n  STR_ITEM: \"GJENSTAND\"\n  STR_ENGINEERS__ALLOCATED: \"Ingeniører{NEWLINE}i Arbeid\"\n  STR_UNITS_PRODUCED: \"Produserte Enheter\"\n  STR_TOTAL_TO_PRODUCE: \"Totalt å Produsere\"\n  STR_COST__PER__UNIT: \"Kostnad{NEWLINE}per{NEWLINE}Enhet\"\n  STR_DAYS_HOURS_LEFT: \"Dager/Timer Igjen\"\n  STR_NEW_PRODUCTION: \"Ny Produksjon\"\n  STR_CATEGORY: \"KATEGORI\"\n  STR_START_PRODUCTION: \"START PRODUKSJON\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} Ingeniørtimer for å produsere en enhet\"\n  STR_COST_PER_UNIT_: \"Kostnad per enhet>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"SPESIELLE MATERIALER NØDVENDIG\"\n  STR_ITEM_REQUIRED: \"GJENSTAND PÅKREVD\"\n  STR_UNITS_REQUIRED: \"ENHETER PÅKREVD\"\n  STR_UNITS_AVAILABLE: \"ENHETER TILGJENGELIG\"\n  STR_STOP_PRODUCTION: \"STOPP PRODUKSJON\"\n  STR_ENGINEERS_AVAILABLE_UC: \"LEDIGE INGENIØRER>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"LEDIG VERKSTED-PLASS>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"MÅNEDLIG PROFITT>{ALT}{0}\"\n  STR_INCREASE_UC: \"FLERE\"\n  STR_DECREASE_UC: \"FÆRRE\"\n  STR_UNITS_TO_PRODUCE: \"Enheter å Produsere\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Kjøp/Ansett Personell\"\n  STR_COST_OF_PURCHASES: \"Kjøpesum>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"PRIS PR. ENHET\"\n  STR_QUANTITY_UC: \"ANTALL\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"LEDIG PERSONELL:TOTALT PERSONELL>\"\n  STR_SOLDIERS: \"Soldater\"\n  STR_SCIENTISTS: \"Forskere\"\n  STR_ENGINEERS: \"Ingeniører\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"BRUKT PLASS:TOTAL PLASS>\"\n  STR_LIVING_QUARTERS: \"Bolig\"\n  STR_STORES: \"Lager\"\n  STR_LABORATORIES: \"Laboratorier\"\n  STR_WORK_SHOPS: \"Verksted\"\n  STR_HANGARS: \"Hangarer\"\n  STR_SHORT_RANGE_DETECTION: \"Kortdistanse-Radar\"\n  STR_DEFENSE_STRENGTH: \"Forsvars Styrke\"\n  STR_TRANSFERS_UC: \"OVERFØRINGER\"\n  STR_TRANSFERS: \"Overføringer\"\n  STR_ARRIVAL_TIME_HOURS: \"Ankomsttid (timer)\"\n  STR_COST_: \"Kostnad>{ALT}{0}\"\n  STR_AREA_: \"Område>{ALT}{0}\"\n  STR_BASE_NAME: \"Basens Navn?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"VELG PLASSERING FOR ADGANGS-HEIS\"\n  STR_TRANSFER: \"Overføre\"\n  STR_AMOUNT_TO_TRANSFER: \"ANTALL FOR OVERFØRING\"\n  STR_SELECT_DESTINATION_BASE: \"Velg Destinasjons Base\"\n  STR_COST: \"Kostnad\"\n  STR_VICTORY_1: \"Når du kommer inn i kammeret ser du den utenomjordiske hjernen - målet du har lett etter.  Før du kan skyte kommuniserer den til deg via en skjerm ved dens fot.  Den ber deg lytte til argumentene for å la den leve før du tar beslutningen om å trykke på avtrekkeren...\"\n  STR_VICTORY_2: \"Hjernen taler :  'Mange millioner år siden var planeten dere kaller Mars i live.  Dette livet ble brakt til en øde planet av vår sivilisasjon på samme måte som det ble til deres.  I millioner av år har vi besøkt deres planet og genetisk utviklet deres rase.  Du kan ikke drepe oss, du er en del av oss...'\"\n  STR_VICTORY_3: \"'Dette er sentrum av Mars' sivilisasjon - pyramidene ble bygget millioner av år før deres - av en art som er din stamfar.  Ingen planet er utenfor vår rekkevidde.  Denne makten kan bli din før lenge.  Alt vi ber om er ditt samarbeid...'\"\n  STR_GAME_OVER_2: \"Kunnskapen frembrakt gjennom X-Com prosjektet er tapt for alltid. Du klarte ikke å redde jorden.\"\n  STR_VICTORY_4: \"Den utenomjordiske hjernen blir avbrutt av en salve brennhet plasma, og hele den utenomjordiske styrken er beseiret.\"\n  STR_TOTAL_UC: \"TOTALT\"\n  STR_INCOME: \"Inntekter\"\n  STR_EXPENDITURE: \"Utgifter\"\n  STR_MAINTENANCE: \"Vedlikehold\"\n  STR_BALANCE: \"Balanse\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"UFO-Aktivitet pr. Område\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"UFO-Aktivitet pr. Land\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"X-Com Aktivitet i Områder\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"X-Com Aktivitet i Land\"\n  STR_FINANCE: \"Finanser\"\n  STR_DATE_FIRST: \"{0}.\"\n  STR_DATE_SECOND: \"{0}.\"\n  STR_DATE_THIRD: \"{0}.\"\n  STR_DATE_FOURTH: \"{0}.\"\n  STR_FINANCE_THOUSANDS: \"$1000's\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"Bygging av{NEWLINE}{0}{NEWLINE}i{NEWLINE}{1}{NEWLINE}er ferdig\"\n  STR_OK_5_SECONDS: \"OK - 5 sek\"\n  STR_RESEARCH_COMPLETED: \"Forskning Fullført\"\n  STR_VIEW_REPORTS: \"LES RAPPORTER\"\n  STR_WE_CAN_NOW_RESEARCH: \"Vi kan nå forske på\"\n  STR_WE_CAN_NOW_PRODUCE: \"Vi kan nå produsere\"\n  STR_SUNDAY: \"SØNDAG\"\n  STR_MONDAY: \"MANDAG\"\n  STR_TUESDAY: \"TIRSDAG\"\n  STR_WEDNESDAY: \"ONSDAG\"\n  STR_THURSDAY: \"TORSDAG\"\n  STR_FRIDAY: \"FREDAG\"\n  STR_SATURDAY: \"LØRDAG\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Ikke nok {0} til å tanke opp {1} ved {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Ikke nok {0} for å armere {1} ved {2}\"\n  STR_UFO_IS_NOT_RECOVERED: \"UFO ble ikke berget\"\n  STR_UFO_IS_RECOVERED: \"UFO ble berget\"\n  STR_CRAFT_IS_LOST: \"Fartøyet er tapt\"\n  STR_TERROR_CONTINUES: \"Terroren fortsetter\"\n  STR_ALIENS_DEFEATED: \"Aliens overvunnet\"\n  STR_BASE_IS_LOST: \"Basen er tapt\"\n  STR_BASE_IS_SAVED: \"Basen er reddet\"\n  STR_ALIEN_BASE_STILL_INTACT: \"Romvesen-Basen er fremdeles intakt\"\n  STR_ALIEN_BASE_DESTROYED: \"Romvesen-Basen er ødelagt\"\n  STR_ALIENS_KILLED: \"UTENOMJORDISKE DREPT\"\n  STR_ALIEN_CORPSES_RECOVERED: \"DØDE UTENOMJORDISKE FUNNET\"\n  STR_LIVE_ALIENS_RECOVERED: \"LEVENDE UTENOMJORDISKE FUNNET\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"UTENOMJORDISKE GJENSTANDER FUNNET\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"ROMVESEN-BASENS KONTROLLENHET ER ØDELAGT\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"SIVILE DREPT AV ALIENS\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"SIVILE DREPT AV X-COM STYRKER\"\n  STR_CIVILIANS_SAVED: \"SIVILE REDDET\"\n  STR_XCOM_OPERATIVES_KILLED: \"X-COM STYRKER DREPT\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"X-COM STYRKER SAVNET I AKSJON\"\n  STR_TANKS_DESTROYED: \"STRIDSVOGN ØDELAGT\"\n  STR_XCOM_CRAFT_LOST: \"X-COM FARTØY TAPT\"\n  STR_UFO_RECOVERY: \"UFO BERGING\"\n  STR_BASE_UNDER_ATTACK: \"{0} under angrep!\"\n  STR_BASE_DEFENSES_INITIATED: \"BASEFORSVAR IGANGSATT\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"GRAVITASJONS-SKJOLD MOTSTOD UFO!\"\n  STR_FIRING: \"AVFYRER\"\n  STR_HIT: \"TREFF!\"\n  STR_UFO_DESTROYED: \"UFO ØDELAGT!\"\n  STR_MISSED: \"BOMMET!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Selg Gjenstander/Spark Personell\"\n  STR_VALUE_OF_SALES: \"SALGSVERDI> {ALT}{0}\"\n  STR_FUNDS: \"MIDLER> {ALT}{0}\"\n  STR_SELL_SACK: \"Selg/Spark\"\n  STR_VALUE: \"Verdi\"\n  STR_CRAFT_: \"FARTØY> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"BERGING AV KRASJET UFO\"\n  STR_UFO_GROUND_ASSAULT: \"BAKKEANGREP PÅ UFO\"\n  STR_BASE_DEFENSE: \"BASEFORSVAR\"\n  STR_BASE_UC_: \"BASE> {0}\"\n  STR_ALIEN_BASE_ASSAULT: \"ANGREP PÅ ROMVESEN-BASE\"\n  STR_TERROR_MISSION: \"TERROR-TOKT\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"INGEN LEDIG HANGAR TIL FARTØYPRODUKSJON!SMALLLINE} Ethvert fartøy tildelt en base, kjøpt eller bygget, bruker en hangar. Bygg en ny hangar eller overfør ett fartøy til en annen base.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"INGEN LEDIG HANGAR FOR Å KJØPE!{SMALLLINE}Ethvert fartøy tildelt en base, kjøpt eller bygget, bruker en hangar. Bygg en ny hangar eller overfør ett fartøy til en annen base.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"INGEN LEDIG HANGAR FOR OVERFØRING!{SMALLLINE}Ethvert fartøy tildelt en base, kjøpt eller bygget, bruker en hangar. Bygg en ny hangar eller overfør ett fartøy til en annen base.\"\n  STR_CANNOT_BUILD_HERE: \"KAN IKKE BYGGE HER!{SMALLLINE}Du må bygge ved siden av en allerede eksisterende basefasilitet.\"\n  STR_NOT_ENOUGH_MONEY: \"IKKE NOK MIDLER!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"IKKE NOK LAGERPLASS!{SMALLLINE}Bygg en ny lager fasilitet eller overfør eksisterende lagerbeholdninger til andre baser.\"\n  STR_LAUNCH_INTERCEPTION: \"START AVSKJÆRING\"\n  STR_CRAFT: \"FARTØY\"\n  STR_STATUS: \"STATUS\"\n  STR_BASE: \"BASE\"\n  STR_READY: \"KLAR\"\n  STR_OUT: \"UTE\"\n  STR_REPAIRS: \"REPARASJONER\"\n  STR_REFUELLING: \"TANKER OPP\"\n  STR_REARMING: \"OPPRUSTER\"\n  STR_TARGET: \"MÅL: {0}\"\n  STR_WAY_POINT: \"VEIPUNKT\"\n  STR_YES: \"JA\"\n  STR_NO: \"NEI\"\n  STR_SELECT_DESTINATION: \"VELG DESTINASJON\"\n  STR_CYDONIA: \"CYDONIA\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"VELG STED FOR NY BASE\"\n  STR_RETURN_TO_BASE: \"RETURNER TIL BASEN\"\n  STR_SELECT_NEW_TARGET: \"VELG NYTT MÅL\"\n  STR_PATROL: \"PATRULJERE\"\n  STR_STATUS_: \"STATUS>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"SKADET - RETURNERER TIL BASEN\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"LITE DRIVSTOFF - RETURNERER TIL BASE\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"OPPDRAG UTFØRT - RETURNERER TIL BASE\"\n  STR_PATROLLING: \"PATRULJERER\"\n  STR_TAILING_UFO: \"FØLGER UFO\"\n  STR_INTERCEPTING_UFO: \"AVSKJÆRER UFO-{0}\"\n  STR_RETURNING_TO_BASE: \"RETURNERER TIL BASEN\"\n  STR_DESTINATION_UC_: \"DESTINASJON: {0}\"\n  STR_BASE_UC: \"BASE>{ALT}{0}\"\n  STR_SPEED_: \"HASTIGHET>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"TOPPFART>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"HØYDE>{ALT}{0}\"\n  STR_VERY_LOW: \"VELDIG LAVT\"\n  STR_LOW_UC: \"LAVT\"\n  STR_HIGH_UC: \"HØYT\"\n  STR_VERY_HIGH: \"VELDIG HØYT\"\n  STR_FUEL: \"DRIVSTOFF>{ALT}{0}\"\n  STR_WEAPON_ONE: \"VÅPEN-1>{ALT}{0}\"\n  STR_NONE_UC: \"INGEN\"\n  STR_ROUNDS_: \"SKUDD>{ALT}{0}\"\n  STR_WEAPON_TWO: \"VÅPEN-2>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"AVSKJÆRINGS-FARTØY\"\n  STR_BASE_: \"Base>{0}\"\n  STR_NAME_UC: \"NAVN\"\n  STR_AMMO_: \"AMMUNISJON>{ALT}{0}\"\n  STR_CREW: \"BESETNING\"\n  STR_EQUIPMENT_UC: \"UTRUSTNING\"\n  STR_ARMOR: \"RUSTNING\"\n  STR_MAX: \"MAX>{ALT}{0}\"\n  STR_ROOKIE: \"Rekrutt\"\n  STR_SQUADDIE: \"Menig\"\n  STR_SERGEANT: \"Sersjant\"\n  STR_CAPTAIN: \"Kaptein\"\n  STR_COLONEL: \"Oberst\"\n  STR_COMMANDER: \"Kommandør\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Velg Tropp for {0}\"\n  STR_SORT_BY: \"SORTER ETTER...\"\n  STR_ORIGINAL_ORDER: \"OPPRINNELIG ORDRE\"\n  STR_MISSIONS2: \"OPPDRAG\"\n  STR_SPACE_AVAILABLE: \"LEDIG PLASS>{ALT}{0}\"\n  STR_SPACE_USED: \"BRUKT PLASS>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"BRUKT PLASS\"\n  STR_RANK: \"GRAD\"\n  STR_WOUNDED: \"SKADET\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Utrustning for {0}\"\n  STR_DEFENSE_VALUE: \"Forsvars Verdi\"\n  STR_HIT_RATIO: \"Treffrate\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}klar til å{NEWLINE}lande nær{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"Starte Oppdrag?\"\n  STR_SELECT_ARMAMENT: \"Velg Bevæpning\"\n  STR_AMMUNITION_AVAILABLE: \"TILGJENGELIG AMMUNISJON\"\n  STR_ARMAMENT: \"BEVÆPNING\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"VELG RUSTNING FOR{NEWLINE}{0}\"\n  STR_TYPE: \"TYPE\"\n  STR_PERSONAL_ARMOR_UC: \"PERSONLIG RUSTNING\"\n  STR_POWER_SUIT_UC: \"STYRKEDRAKT\"\n  STR_FLYING_SUIT_UC: \"FLYVEDRAKT\"\n  STR_SELECT_ARMOR: \"Velg Rustning\"\n  STR_NORTH: \"NORD\"\n  STR_NORTH_EAST: \"NORDØST\"\n  STR_EAST: \"ØST\"\n  STR_SOUTH_EAST: \"SØRØST\"\n  STR_SOUTH: \"SØR\"\n  STR_SOUTH_WEST: \"SØRVEST\"\n  STR_WEST: \"VEST\"\n  STR_NORTH_WEST: \"NORDVEST\"\n  STR_SELECT_ACTION: \"VELG HANDLING\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"FORTSETT JAGER-FORFØLGELSEN\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"FORFØLGE MED AVSTAND\"\n  STR_VERY_LARGE: \"VELDIG STOR\"\n  STR_LARGE: \"STOR\"\n  STR_MEDIUM_UC: \"MELLOMSTOR\"\n  STR_SMALL: \"LITEN\"\n  STR_VERY_SMALL: \"VELDIG LITEN\"\n  STR_GROUNDED: \"LANDET\"\n  STR_DETECTED: \"Oppdaget\"\n  STR_SIZE_UC: \"STØRRELSE\"\n  STR_ALTITUDE: \"HØYDE\"\n  STR_HEADING: \"KURS\"\n  STR_SPEED: \"HASTIGHET\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"SENTRER PÅ UFO - TID=5 Sek\"\n  STR_TRACKING_LOST: \"SPORING FEILET\"\n  STR_REDIRECT_CRAFT: \"OMDIRIGER FARTØY\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"GÅ TIL SIST KJENTE UFO POSISJON\"\n  STR_UFO_: \"UFO-{0}\"\n  STR_ALIEN_BASE_: \"Romvesen-Base-{0}\"\n  STR_CRASH_SITE_: \"HAVARI-STED-{0}\"\n  STR_LANDING_SITE_: \"LANDINGS-STED-{0}\"\n  STR_WAY_POINT_: \"VEIPUNKT-{0}\"\n  STR_TERROR_SITE: \"TERROR OMRÅDE-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}har ankommet{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"Patruljerer\"\n  STR_ALIEN_ORIGINS: \"Utenomjordisk opphav\"\n  STR_UFOPAEDIA: \"UFOpedia\"\n  STR_XCOM_CRAFT_ARMAMENT: \"X.COM FARTØY & BEVÆPNING\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"TUNGSKYTS PLATFORMER\"\n  STR_WEAPONS_AND_EQUIPMENT: \"VÅPEN OG UTRUSTNING\"\n  STR_BASE_FACILITIES: \"BASE-FASILITETER\"\n  STR_ALIEN_LIFE_FORMS: \"Utenomjordiske livsformer\"\n  STR_ALIEN_RESEARCH_UC: \"UTENOMJORDISK FORSKNING\"\n  STR_UFO_COMPONENTS: \"UFO-KOMPONENTER\"\n  STR_UFOS: \"UFOer\"\n  STR_SELECT_ITEM: \"VELG GJENSTAND\"\n  STR_ACCELERATION: \"AKSELERASJON>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"DRIVSTOFF-KAPASITET>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"VÅPEN-FESTER>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"PANSRING>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"LASTE-KAPASITET>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"HWP KAPASITET>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Skade\"\n  STR_RANGE: \"Rekkevidde\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Treffsikkerhet\"\n  STR_RE_LOAD_TIME: \"Omladningstid\"\n  STR_SECONDS: \"{0}s\"\n  STR_DAMAGE_ARMOR_PIERCING: \"PANSERBRYTENDE\"\n  STR_DAMAGE_INCENDIARY: \"BRANNSKADE\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"HØY-EKSPLOSIV\"\n  STR_DAMAGE_LASER_BEAM: \"LASER-STRÅLE\"\n  STR_DAMAGE_PLASMA_BEAM: \"PLASMA STRÅLE\"\n  STR_DAMAGE_STUN: \"BEDØVELSE\"\n  STR_DAMAGE_MELEE: \"NÆRKAMP\"\n  STR_DAMAGE_ACID: \"SYREANGREP\"\n  STR_DAMAGE_SMOKE: \"RØYK\"\n  STR_SHOT_TYPE: \"SKUDD-TYPE\"\n  STR_ACCURACY_UC: \"TREFFSIKKERHET\"\n  STR_TIME_UNIT_COST: \"TIDSENHETER\"\n  STR_DAMAGE_UC: \"SKADE\"\n  STR_AMMO: \"AMMUNISJON\"\n  STR_SHOT_TYPE_AUTO: \"Serie (3)\"\n  STR_SHOT_TYPE_SNAP: \"Slengskudd\"\n  STR_SHOT_TYPE_AIMED: \"Siktet\"\n  STR_CONSTRUCTION_TIME: \"Bygge-Periode\"\n  STR_CONSTRUCTION_COST: \"Bygge-Kostnader\"\n  STR_MAINTENANCE_COST: \"Vedlikeholds-Kostnader\"\n  STR_LOW: \"Lav\"\n  STR_MEDIUM: \"Mellomstor\"\n  STR_HIGH: \"Høy\"\n  STR_CRAFT_WEAPON: \"Fartøy-Våpen\"\n  STR_CRAFT_AMMUNITION: \"Fartøy-Ammunisjon\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Tungskyts Platform\"\n  STR_WEAPON: \"Våpen\"\n  STR_AMMUNITION: \"Ammunisjon\"\n  STR_EQUIPMENT: \"Utrustning\"\n  STR_ALIEN_CORPSE: \"Utenomjordisk Kropp\"\n  STR_UFO_COMPONENT: \"UFO komponent\"\n  STR_PERSONAL_ARMOR: \"Personlig Rustning\"\n  STR_RAW_MATERIALS: \"Råmaterialer\"\n  STR_HWP_CANNON_SHELLS: \"HWP Kanon Prosjektiler\"\n  STR_ALIEN: \"Romvesen\"\n  STR_SECTOID: \"Sektoide\"\n  STR_SNAKEMAN: \"Slangemann\"\n  STR_ETHEREAL: \"Eterisk\"\n  STR_MUTON: \"Muton\"\n  STR_FLOATER: \"Svever\"\n  STR_CELATID: \"Celatide\"\n  STR_SILACOID: \"Kiseldyr\"\n  STR_CHRYSSALID: \"Draug\"\n  STR_ZOMBIE: \"Zombi\"\n  STR_REAPER: \"Tresker\"\n  STR_SECTOPOD: \"Sektopode\"\n  STR_CYBERDISC: \"Svevetallerken\"\n  STR_LIVE_COMMANDER: \"Kommandør\"\n  STR_LIVE_LEADER: \"Leder\"\n  STR_LIVE_ENGINEER: \"Ingeniør\"\n  STR_LIVE_MEDIC: \"Pleier\"\n  STR_LIVE_NAVIGATOR: \"Navigatør\"\n  STR_LIVE_SOLDIER: \"Soldat\"\n  STR_LIVE_TERRORIST: \"Terrorist\"\n  STR_FLOATER_SOLDIER: \"Svever-Soldat\"\n  STR_FLOATER_NAVIGATOR: \"Svever-Navigatør\"\n  STR_FLOATER_MEDIC: \"Svever-Pleier\"\n  STR_FLOATER_ENGINEER: \"Svever-Ingeniør\"\n  STR_FLOATER_LEADER: \"Svever-Leder\"\n  STR_FLOATER_COMMANDER: \"Svever-Kommandør\"\n  STR_SECTOID_SOLDIER: \"Sektoide-Soldat\"\n  STR_SECTOID_NAVIGATOR: \"Sektoide-Navigatør\"\n  STR_SECTOID_MEDIC: \"Sektoide-Pleier\"\n  STR_SECTOID_ENGINEER: \"Sektoide-Ingeniør\"\n  STR_SECTOID_LEADER: \"Sektoide-Leder\"\n  STR_SECTOID_COMMANDER: \"Sektoide-Kommandør\"\n  STR_SNAKEMAN_SOLDIER: \"Slangemann-Soldat\"\n  STR_SNAKEMAN_NAVIGATOR: \"Slangemann-Navigatør\"\n  STR_SNAKEMAN_ENGINEER: \"Slangemann-Ingeniør\"\n  STR_SNAKEMAN_LEADER: \"Slangemann-Leder\"\n  STR_SNAKEMAN_COMMANDER: \"Slangemann-Kommandør\"\n  STR_MUTON_SOLDIER: \"Muton-Soldat\"\n  STR_MUTON_NAVIGATOR: \"Muton-Navigatør\"\n  STR_MUTON_ENGINEER: \"Muton-Ingeniør\"\n  STR_ETHEREAL_SOLDIER: \"Eterisk Soldat\"\n  STR_ETHEREAL_LEADER: \"Eterisk Leder\"\n  STR_ETHEREAL_COMMANDER: \"Eterisk Kommandør\"\n  STR_CYBERDISC_TERRORIST: \"Svevetallerken-Terrorist\"\n  STR_REAPER_TERRORIST: \"Tresker-Terrorist\"\n  STR_CHRYSSALID_TERRORIST: \"Draug-Terrorist\"\n  STR_CELATID_TERRORIST: \"Celatide-Terrorist\"\n  STR_SILACOID_TERRORIST: \"Kiseldyr-Terrorist\"\n  STR_SECTOPOD_TERRORIST: \"Sektopode-Terrorist\"\n  STR_UFO_POWER_SOURCE: \"UFO-Kraftkilde\"\n  STR_UFO_NAVIGATION: \"UFO-Navigasjon\"\n  STR_UFO_CONSTRUCTION: \"UFO-Konstruksjon\"\n  STR_ALIEN_FOOD: \"Utenomjordisk Mat\"\n  STR_ALIEN_REPRODUCTION: \"Utenomjordisk reproduksjon\"\n  STR_ALIEN_ENTERTAINMENT: \"Utenomjordisk Underholdning\"\n  STR_ALIEN_SURGERY: \"Utenomjordisk Kirurgi\"\n  STR_EXAMINATION_ROOM: \"Undersøkelsesrom\"\n  STR_ALIEN_ALLOYS: \"Utenomjordiske Legeringer\"\n  STR_POWER_SUIT: \"Styrkedrakt\"\n  STR_FLYING_SUIT: \"Flyvedrakt\"\n  STR_LASER_WEAPONS: \"Laservåpen\"\n  STR_NEW_FIGHTER_CRAFT: \"Nytt Kamp-Fartøy\"\n  STR_LASER_PISTOL: \"Laser-Pistol\"\n  STR_LASER_RIFLE: \"Laser-Gevær\"\n  STR_HEAVY_LASER: \"Tung Laser\"\n  STR_LASER_CANNON: \"Laser-Kanon\"\n  STR_PLASMA_CANNON: \"Plasma-Kanon\"\n  STR_FUSION_MISSILE: \"FUSJON MISSIL\"\n  STR_LASER_DEFENSE: \"Laser Forsvar\"\n  STR_PLASMA_DEFENSE: \"Plasma Forsvar\"\n  STR_FUSION_DEFENSE: \"Fusjon Forsvar\"\n  STR_GRAV_SHIELD: \"Gravitasjons Skjold\"\n  STR_MIND_SHIELD: \"Tankeskjold\"\n  STR_MOTION_SCANNER: \"Bevegelseskanner\"\n  STR_MEDI_KIT: \"Førstehjelpssett\"\n  STR_TANK_CANNON: \"Stridsvogn/Kanon\"\n  STR_TANK_ROCKET_LAUNCHER: \"Stridsvogn/Rakettkaster\"\n  STR_TANK_LASER_CANNON: \"Stridsvogn/Laser-Kanon\"\n  STR_HOVERTANK_PLASMA: \"Svevetanks/Plasma\"\n  STR_STINGRAY_LAUNCHER: \"Rokke-Rakettkaster\"\n  STR_AVALANCHE_LAUNCHER: \"Lavine-Rakettkaster\"\n  STR_CANNON: \"Kanon\"\n  STR_FUSION_BALL_LAUNCHER: \"FUSJONSKULE-KASTER\"\n  STR_PLASMA_BEAM: \"Plasma Stråle\"\n  STR_STINGRAY_MISSILES: \"Rokke-Raketter\"\n  STR_AVALANCHE_MISSILES: \"Lavine-Raketter\"\n  STR_CANNON_ROUNDS_X50: \"Kanon-Skudd(x50)\"\n  STR_FUSION_BALL: \"Fusjonskule\"\n  STR_SOLDIER: \"Soldat\"\n  STR_SCIENTIST: \"Forsker\"\n  STR_ENGINEER: \"Ingeniør\"\n  STR_NORTH_AMERICA: \"Nord-Amerika\"\n  STR_ARCTIC: \"Arktis\"\n  STR_ANTARCTICA: \"Antarktis\"\n  STR_SOUTH_AMERICA: \"Sør-Amerika\"\n  STR_EUROPE: \"Europa\"\n  STR_NORTH_AFRICA: \"Nordlige Afrika\"\n  STR_SOUTHERN_AFRICA: \"Sørlige Afrika\"\n  STR_CENTRAL_ASIA: \"Sentral-Asia\"\n  STR_SOUTH_EAST_ASIA: \"Sørøst-Asia\"\n  STR_SIBERIA: \"Sibir\"\n  STR_AUSTRALASIA: \"Australasia\"\n  STR_PACIFIC: \"Stillehavet\"\n  STR_NORTH_ATLANTIC: \"Nord-Atlanteren\"\n  STR_SOUTH_ATLANTIC: \"Sør-Atlanteren\"\n  STR_INDIAN_OCEAN: \"Indiahavet\"\n  STR_ALIEN_RESEARCH: \"Alien Forskning\"\n  STR_ALIEN_HARVEST: \"Utenomjordisk Høsting\"\n  STR_ALIEN_ABDUCTION: \"Utenomjordisk Bortføring\"\n  STR_ALIEN_INFILTRATION: \"Romvesen-Infiltrasjon\"\n  STR_ALIEN_BASE: \"Romvesen-Base\"\n  STR_ALIEN_TERROR: \"Alien Terror\"\n  STR_ALIEN_RETALIATION: \"Utenomjordisk Gjengjeldelse\"\n  STR_ALIEN_SUPPLY: \"Utenomjordisk Forsyning\"\n  STR_MAXIMUM_SPEED: \"Toppfart\"\n  STR_HYPER_WAVE_DECODER_UC: \"HYPER-BØLGE DEKODER\"\n  STR_SKYRANGER: \"HIMMELBUSS\"\n  STR_LIGHTNING: \"LYNNEDSLAG\"\n  STR_AVENGER: \"HEVNER\"\n  STR_INTERCEPTOR: \"AVSKJÆRER\"\n  STR_FIRESTORM: \"ILDSTORM\"\n  STR_UFO: \"UFO\"\n  STR_STINGRAY: \"ROKKE\"\n  STR_AVALANCHE: \"LAVINE\"\n  STR_CANNON_UC: \"KANON\"\n  STR_FUSION_BALL_UC: \"FUSJONS-BALL\"\n  STR_LASER_CANNON_UC: \"LASER-KANON\"\n  STR_PLASMA_BEAM_UC: \"PLASMA STRÅLE\"\n  STR_DAMAGE_CAPACITY: \"Pansring\"\n  STR_WEAPON_POWER: \"Våpen-Kraft\"\n  STR_WEAPON_RANGE: \"Våpen-Rekkevidde\"\n  STR_ACCESS_LIFT: \"Adgangs-Heis\"\n  STR_LABORATORY: \"Laboratorium\"\n  STR_WORKSHOP: \"Verksted\"\n  STR_SMALL_RADAR_SYSTEM: \"Liten Radar\"\n  STR_LARGE_RADAR_SYSTEM: \"Stor Radar\"\n  STR_MISSILE_DEFENSES: \"Missil Forsvar\"\n  STR_GENERAL_STORES: \"Lager\"\n  STR_LASER_DEFENSES: \"Laserforsvar\"\n  STR_PLASMA_DEFENSES: \"Plasma Forsvar\"\n  STR_FUSION_BALL_DEFENSES: \"Fusjons-ball Forsvar\"\n  STR_PSIONIC_LABORATORY: \"Psionisk Laboratorium\"\n  STR_HYPER_WAVE_DECODER: \"Hyper-bølge Dekoder\"\n  STR_HANGAR: \"Hangar\"\n  STR_USA: \"USA\"\n  STR_RUSSIA: \"RUSSLAND\"\n  STR_UK: \"STORBRITANNIA\"\n  STR_FRANCE: \"FRANKRIKE\"\n  STR_GERMANY: \"TYSKLAND\"\n  STR_ITALY: \"ITALIA\"\n  STR_SPAIN: \"SPANIA\"\n  STR_CHINA: \"KINA\"\n  STR_JAPAN: \"JAPAN\"\n  STR_INDIA: \"INDIA\"\n  STR_BRAZIL: \"BRASIL\"\n  STR_AUSTRALIA: \"AUSTRALIA\"\n  STR_NIGERIA: \"NIGERIA\"\n  STR_SOUTH_AFRICA: \"SØR-AFRIKA\"\n  STR_EGYPT: \"EGYPT\"\n  STR_CANADA: \"CANADA\"\n  STR_TANK: \"Stridsvogn\"\n  STR_CIVILIAN: \"Sivilperson\"\n  STR_JAN: \"Jan\"\n  STR_FEB: \"Feb\"\n  STR_MAR: \"Mar\"\n  STR_APR: \"Apr\"\n  STR_MAY: \"Mai\"\n  STR_JUN: \"Jun\"\n  STR_JUL: \"Jul\"\n  STR_AUG: \"Aug\"\n  STR_SEP: \"Sep\"\n  STR_OCT: \"Okt\"\n  STR_NOV: \"Nov\"\n  STR_DEC: \"Des\"\n  STR_INTERNATIONAL_RELATIONS: \"Internasjonale Forbindelser\"\n  STR_COUNTRY: \"Land\"\n  STR_FUNDING: \"Finansiering\"\n  STR_CHANGE: \"Endring\"\n  STR_WEAPON_SYSTEMS: \"VÅPEN- SYSTEMER\"\n  STR_DAMAGE_UC_: \"SKADE>{ALT}{0}\"\n  STR_ACCESS_LIFT_UFOPEDIA: \"Adgangsheisen lar utrustning og personell forflytte seg inn og ut av den underjordiske basen.  Det er alltid heisen som bygges først i en ny base.  Heisområdet er utsatt for inntrenging fra enhver potensiell fiendtlig makt.\"\n  STR_SMALL_SCOUT: \"Liten Speider\"\n  STR_MEDIUM_SCOUT: \"Mellomstor Speider\"\n  STR_LARGE_SCOUT: \"Stor Speider\"\n  STR_HARVESTER: \"Høster\"\n  STR_ABDUCTOR: \"Bortfører\"\n  STR_TERROR_SHIP: \"Terrorskip\"\n  STR_BATTLESHIP: \"Slagskip\"\n  STR_SUPPLY_SHIP: \"Forsyningsskip\"\n  STR_RATING: \"VURDERING> {0}\"\n  STR_RATING_TERRIBLE: \"FORFERDELIG!\"\n  STR_RATING_POOR: \"DÅRLIG!\"\n  STR_RATING_OK: \"OK\"\n  STR_RATING_GOOD: \"BRA!\"\n  STR_RATING_EXCELLENT: \"FANTASTISK!\"\n  STR_SCORE: \"POENG\"\n  STR_MONTH: \"Måned> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"Rådet av finansierende nasjoner er generelt fornøyd med fremgangen så langt.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"Rådet av finansierende nasjoner er svært tilfreds med din utmerkede fremgang.  Fortsett med det gode arbeidet.\"\n  STR_COUNCIL_IS_DISSATISFIED: \"Rådet av finansierende nasjoner er misfornøyd med resultatene.  Du må forbedre din effektivitet i håndteringen av den utenomjordiske trusselen eller risikere at prosjektet blir avsluttet.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"Du har ikke lykkes i å håndtere den utenomjordiske invasjonen, og rådet av finansierende nasjoner har dessverre besluttet å avslutte prosjektet.  Hver nasjon vil nå håndtere problemet på sin egen måte.  Vi kan bare håpe at vi kan forhandle med disse tilsynelatende fiendlige styrkene, og at den generelle befolkningen vil komme til enighet med de utenomjordiske besøkende.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} er spesielt fornøyd med din evne til å håndtere den lokaliserte trusselen og har sagt seg villig til å øke sin finansiering.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} er spesielt fornøyde med fremgangen i håndteringen av de lokale utenomjordiske angrepene og har blitt enige om å øke deres finansiering.\"\n  STR_COUNTRIES_AND: \"{0} og {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} er misfornøyd med din evne til å håndtere utenomjordisk aktivitet i deres territorium og har besluttet å redusere sin finansielle forpliktelse.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} er misfornøyde med din evne til å håndtere utenomjordisk aktivitet i deres territorier og har besluttet å redusere deres finansiering.\"\n  STR_KNOTS: \"{0} knop\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} har inngått en hemmelig avtale med ukjente utenomjordiske styrker og har trukket seg fra prosjektet.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} har inngått en hemmelig avtale med ukjente utenomjordiske styrker og har trukket seg fra prosjektet.\"\n  STR_COUNCIL_REDUCE_DEBTS: \"Rådet av finansierende nasjoner er misfornøyd med din økonomiske situasjon.  Du må redusere din gjeld til under $1 million ellers vil prosjektet bli avsluttet.\"\n  STR_RACE: \"RASE\"\n  STR_MISSION: \"OPPDRAG\"\n  STR_ALLOCATE_RESEARCH: \"Tildel Forskning\"\n  STR_MONTREAL: \"Montréal\"\n  STR_HAVANA: \"Havanna\"\n  STR_MEXICO_CITY: \"Mexico By\"\n  STR_BRASILIA: \"Brasília\"\n  STR_BOGOTA: \"Bogotá\"\n  STR_RIO_DE_JANEIRO: \"Rio de Janeiro\"\n  STR_MOSCOW: \"Moskva\"\n  STR_ROME: \"Roma\"\n  STR_CAIRO: \"Kairo\"\n  STR_BAGHDAD: \"Bagdad\"\n  STR_TEHRAN: \"Teheran\"\n  STR_BOMBAY: \"Mumbai\"\n  STR_CALCUTTA: \"Kolkata\"\n  STR_HONG_KONG: \"Hongkong\"\n  STR_WEAPONS_CREW_HWPS: \"VÅPEN/{NEWLINE}TROPPER/HWPs\"\n  STR_SOLDIER_LIST: \"Liste over Soldater\"\n  STR_RANK_: \"GRAD> {ALT}{0}\"\n  STR_MISSIONS: \"OPPDRAG> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"SYKEDAGER> {ALT}{0}\"\n  STR_TIME_UNITS: \"TIDS-ENHETER\"\n  STR_STAMINA: \"UTHOLDENHET\"\n  STR_HEALTH: \"HELSE\"\n  STR_BRAVERY: \"TAPPERHET\"\n  STR_REACTIONS: \"REAKSJONSEVNE\"\n  STR_FIRING_ACCURACY: \"SKYTE-FERDIGHETER\"\n  STR_THROWING_ACCURACY: \"KASTE-FERDIGHETER\"\n  STR_STRENGTH: \"STYRKE\"\n  STR_NEW_RANK: \"NY GRAD\"\n  STR_SOLDIERS_UC: \"SOLDATER\"\n  STR_HOVERTANK_PLASMA_UFOPEDIA: \"Utenomjordisk teknologi har gitt TVP et nytt liv. Den ekstra manøvreringsfriheten av å være luftbåren og kraften i plasma stråler er en dødelig kombinasjon.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"Når romvesen-basen er konstruert så blir den regelmessig forsynt av et spesielt forsyningsfartøy.  Hvis et av disse fartøyene blir oppdaget under landing så er det et sikkert tegn på at en romvesen-base er i nærheten.\"\n  STR_SMALL_SCOUT_UFOPEDIA: \"Dette lille fartøyet blir mest brukt til rekognosering eller forskning.  Det opptrer oftest før større fartøy i innledningen av et romvesen-tokt.\"\n  STR_MEDIUM_SCOUT_UFOPEDIA: \"Et mellomstort speider-fartøy som utgjør liten trussel mot jordens styrker.  Opptrer vanligvis før større fartøy når de er ute på tokt.\"\n  STR_LARGE_SCOUT_UFOPEDIA: \"Det største speider-fartøyet er et allsidig fartøy som blir brukt i alle typer romvesen-tokt.\"\n  STR_SUPPLY_SHIP_UFOPEDIA: \"Forsyningsfartøyet benyttes under byggingen av romvesen-baser eller for å forsyne eksisterende baser.  Det har med seg beholdere med utenomjordisk mat og reproduksjonkamre.\"\n  STR_DISMANTLE: \"Demontere\"\n  STR_DESTINATION_UC: \"DESTINASJON\"\n  STR_PISTOL: \"Pistol\"\n  STR_PISTOL_CLIP: \"Pistol-Magasin\"\n  STR_RIFLE: \"Gevær\"\n  STR_RIFLE_CLIP: \"Gevær-Magasin\"\n  STR_HEAVY_CANNON: \"Tung Kanon\"\n  STR_HC_AP_AMMO: \"TK-PB-Ammunisjon\"\n  STR_HC_HE_AMMO: \"TK-HE-Ammunisjon\"\n  STR_HC_I_AMMO: \"TK-BR-Ammunisjon\"\n  STR_AUTO_CANNON: \"Maskin-Kanon\"\n  STR_AC_AP_AMMO: \"MK-PB-Ammunisjon\"\n  STR_AC_HE_AMMO: \"MK-HE-Ammunisjon\"\n  STR_AC_I_AMMO: \"MK-BR-Ammunisjon\"\n  STR_ROCKET_LAUNCHER: \"Rakettkaster\"\n  STR_SMALL_ROCKET: \"Liten Rakett\"\n  STR_LARGE_ROCKET: \"Stor Rakett\"\n  STR_INCENDIARY_ROCKET: \"Brann-Rakett\"\n  STR_GRENADE: \"Granat\"\n  STR_SMOKE_GRENADE: \"Røyk-Granat\"\n  STR_HIGH_EXPLOSIVE: \"Høy-Eksplosiv\"\n  STR_STUN_ROD: \"Bedøvelses-Stav\"\n  STR_HEAVY_PLASMA: \"Tung Plasma\"\n  STR_HEAVY_PLASMA_CLIP: \"Tungt Plasma- Magasin\"\n  STR_PLASMA_RIFLE: \"Plasma-Gevær\"\n  STR_PLASMA_RIFLE_CLIP: \"Plasma-Gevær- Magasin\"\n  STR_PLASMA_PISTOL: \"Plasma-Pistol\"\n  STR_PLASMA_PISTOL_CLIP: \"Plasma-Pistol- Magasin\"\n  STR_SMALL_LAUNCHER: \"Liten Granatkaster\"\n  STR_STUN_BOMB: \"Bedøvelses-Granat\"\n  STR_ALIEN_GRENADE: \"Utenomjordisk Granat\"\n  STR_ELERIUM_115: \"Elerium-115\"\n  STR_SECTOID_CORPSE: \"Død Sektoide\"\n  STR_SNAKEMAN_CORPSE: \"Død Slangemann\"\n  STR_ETHEREAL_CORPSE: \"Død Eterisk\"\n  STR_MUTON_CORPSE: \"Død Muton\"\n  STR_FLOATER_CORPSE: \"Død Svever\"\n  STR_CELATID_CORPSE: \"Celatide Lik\"\n  STR_SILACOID_CORPSE: \"Dødt Kiseldyr\"\n  STR_CHRYSSALID_CORPSE: \"Død Draug\"\n  STR_REAPER_CORPSE: \"Død Tresker\"\n  STR_SECTOPOD_CORPSE: \"Ødelagt Sektopode\"\n  STR_CYBERDISC_CORPSE: \"Ødelagt Svevetallerken\"\n  STR_MARS_CYDONIA_LANDING: \"Mars: Landgang i Cydonia\"\n  STR_MARS_THE_FINAL_ASSAULT: \"Mars: Det Avgjørende Angrepet\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"X-Com agenter har lokalisert en alien-base ved {0}\"\n  STR_STANDOFF: \"HOLD AVSTAND\"\n  STR_CAUTIOUS_ATTACK: \"FORSIKTIG ANGREP\"\n  STR_STANDARD_ATTACK: \"STANDARD ANGREP\"\n  STR_AGGRESSIVE_ATTACK: \"AGGRESSIVT ANGREP\"\n  STR_DISENGAGING: \"FALL IFRA\"\n  STR_UFO_HIT: \"UFO TRUFFET!\"\n  STR_UFO_CRASH_LANDS: \"UFO KRASJLANDER!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Minimer Kun Under Avstandholdelese\"\n  STR_UFO_RETURN_FIRE: \"UFO GJENGJELDER!\"\n  STR_INTERCEPTOR_DAMAGED: \">>> AVSKJÆRER SKADET <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> AVSKJÆRER ØDELAGT <<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"UFO FLYR IFRA JAGER!\"\n  STR_ALIENS_TERRORISE: \"ALIENS TERRORISERER\"\n  STR_LONG_RANGE_DETECTION: \"Langdistanse-Radar\"\n  STR_STORES_UC: \"LAGER\"\n  STR_DIFFICULTY_LEVEL: \"Vanskelighetsgrad\"\n  STR_INTERCEPT: \"AVSKJÆRING\"\n  STR_BASES: \"BASER\"\n  STR_GRAPHS: \"GRAFER\"\n  STR_UFOPAEDIA_UC: \"UFOPEDIA\"\n  STR_OPTIONS_UC: \"ALTERNATIVER\"\n  STR_FUNDING_UC: \"FINANSIERING\"\n  STR_5_SECONDS: \"5 Sek\"\n  STR_1_MINUTE: \"1 Min\"\n  STR_5_MINUTES: \"5 Min\"\n  STR_30_MINUTES: \"30 Min\"\n  STR_1_HOUR: \"1 Time\"\n  STR_1_DAY: \"1 Dag\"\n  STR_ENTER_NAME: \"Skriv Navn\"\n  STR_PERFORMANCE_RATING: \"Prestasjons Vurdering\"\n  STR_VICTORY_DATE: \"Seiers-dato\"\n  STR_ELECTRO_FLARE: \"Elektro-bluss\"\n  STR_MONTHLY_COSTS: \"Månedskostnader\"\n  STR_CRAFT_RENTAL: \"Fartøy-leie\"\n  STR_SALARIES: \"Lønninger\"\n  STR_BASE_MAINTENANCE: \"Base-Vedlikehold\"\n  STR_COST_PER_UNIT: \"Kostnad/stk.\"\n  STR_QUANTITY: \"Antall\"\n  STR_TOTAL: \"Totalt\"\n  STR_IN_PSIONIC_TRAINING: \"I Psionisk Trening\"\n  STR_FRONT_ARMOR: \"Beskyttelse Front\"\n  STR_LEFT_ARMOR: \"Beskyttelse Venstre\"\n  STR_RIGHT_ARMOR: \"Beskyttelse Høyre\"\n  STR_REAR_ARMOR: \"Beskyttelse Bak\"\n  STR_UNDER_ARMOR: \"Beskyttelse Under\"\n  STR_ROUNDS: \"Skudd\"\n  STR_UNIT: \"ENHET> {0}\"\n  STR_ENERGY: \"UTHOLDENHET\"\n  STR_MORALE: \"DISIPLIN\"\n  STR_ARMOR_: \"PANSER> {0}\"\n  STR_FRONT_ARMOR_UC: \"FREMRE PANSER\"\n  STR_LEFT_ARMOR_UC: \"VENSTRE PANSER\"\n  STR_RIGHT_ARMOR_UC: \"HØYRE PANSER\"\n  STR_REAR_ARMOR_UC: \"BAKRE PANSER\"\n  STR_SKILLS: \"FERDIGHETER> {0}\"\n  STR_LEVEL: \"NIVÅ> {0}\"\n  STR_HEAD: \"HODE\"\n  STR_TORSO: \"TORSO\"\n  STR_RIGHT_ARM: \"HØYRE ARM\"\n  STR_LEFT_ARM: \"VENSTRE ARM\"\n  STR_RIGHT_LEG: \"HØYRE BEN\"\n  STR_LEFT_LEG: \"VENSTRE BEN\"\n  STR_PAIN_KILLER: \"SMERTESTILLENDE\"\n  STR_STIMULANT: \"STIMULERENDE\"\n  STR_HEAL: \"HELBREDE\"\n  STR_TIME_UNITS_SHORT: \"TID>{ALT}{0}\"\n  STR_WEIGHT: \"Vekt>{ALT}{0}/{1}\"\n  STR_ALIEN_ARTIFACT: \"Utenomjordisk Gjenstand\"\n  STR_AMMO_ROUNDS_LEFT: \"AMMUNISJON:{NEWLINE}{ALT}{0} SKUDD{NEWLINE}IGJEN\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Bedøve>{ALT}{0}{ALT}{NEWLINE}Opplive>{ALT}{1}{ALT}{NEWLINE}Helbrede>{ALT}{2}\"\n  STR_THROW: \"Kast\"\n  STR_AUTO_SHOT: \"Skuddserie (3)\"\n  STR_SNAP_SHOT: \"Slengskudd\"\n  STR_AIMED_SHOT: \"Siktet Skudd\"\n  STR_STUN: \"Bedøve\"\n  STR_USE_SCANNER: \"Bruk Skanner\"\n  STR_USE_MEDI_KIT: \"Bruk Førstehjelpssett\"\n  STR_LAUNCH_MISSILE: \"Avfyr Missil\"\n  STR_ACCURACY_SHORT: \"Trf>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Ikke Nok Tid!\"\n  STR_NOT_ENOUGH_ENERGY: \"For Dårlig Kondisjon!\"\n  STR_NO_ROUNDS_LEFT: \"Tom for kuler!\"\n  STR_NO_AMMUNITION_LOADED: \"Ingen Ammunisjon Ladd!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Feil Ammunisjon for dette Våpenet!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"Våpenet er allerede ladd!\"\n  STR_NO_LINE_OF_FIRE: \"Ingen Skuddlinje!\"\n  STR_GRENADE_IS_ACTIVATED: \"Granat er Avsikret!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Granat er Sikret!\"\n  STR_THERE_IS_NO_ONE_THERE: \"Det er ingen der!\"\n  STR_OUT_OF_RANGE: \"Utenfor Rekkevidde!\"\n  STR_UNABLE_TO_THROW_HERE: \"Kan ikke kaste der!\"\n  STR_HIDDEN_MOVEMENT: \"SKJULT AKTIVITET\"\n  STR_TURN: \"RUNDE> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Trykk knapp for å fortsette\"\n  STR_MIND_CONTROL: \"Tankekontroll\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Moralangrep Vellykket\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Tankekontroll Vellykket\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}har gått Berserk\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}har gått Berserk\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}har fått Panikk\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}har fått Panikk\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Romvesen\"\n  STR_RIGHT_HAND: \"HØYRE HÅND\"\n  STR_LEFT_HAND: \"VENSTRE HÅND\"\n  STR_RIGHT_SHOULDER: \"HØYRE SKULDER\"\n  STR_LEFT_SHOULDER: \"VENSTRE SKULDER\"\n  STR_BACK_PACK: \"RYGGSEKK\"\n  STR_BELT: \"BELTE\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}blir kontrollert av utenomjordiske\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}blir kontrollert av utenomjordiske\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}er blitt bevisstløs\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}er blitt bevisstløs\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}omkom av ett dødelig sår\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}omkom av ett dødelig sår\"\n  STR_FATAL_WOUNDS: \"DØDELIGE SÅR\"\n  STR_UNDER_ARMOR_UC: \"NEDRE PANSER\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Tid Reservert for Slengskudd\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Tid Reservert for Skuddserie (3)\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Tid Reservert for Siktet Skudd\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Tid Reservert for Kneling\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"Tid Reservert for Kneling og Skyting\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} Enhet i X-Com Fartøy\"\n    other: \"{N} Enheter i X-Com Fartøy\"\n  STR_UNITS_OUTSIDE:\n    one: \"{N} Enhet igjen der ute\"\n    other: \"{N} Enheter igjen der ute\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} Enhet i Inngangen\"\n    other: \"{N} Enheter i Inngangen\"\n  STR_ABORT_MISSION_QUESTION: \"Avbryte Oppdrag?\"\n  STR_CORPSE: \"Kropp\"\n  STR_UNLOAD_CRAFT: \"Last Av\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}ble drept\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}ble drept\"\n  STR_HIT_MELEE: \"Treff\"\n  STR_GROUND: \"BAKKE\"\n  STR_LIVING_QUARTERS_PLURAL: \"Boliger\"\n  STR_LIST_ITEM: \"GJENSTAND\"\n  STR_FLYING_SUIT_UFOPEDIA: \"En forbedret versjon av Styrkedrakten, som benytter utenomjordisk anti-gravitasjon navigeringteknologi som tillater full bevegelsesfrihet på slagmarken.\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"Alle Romvesen drept i krasjet,{NEWLINE}Automatisk berging startet\"\n  STR_RESET: \"Reset\"\n  STR_MEMORIAL: \"Minnetavle\"\n  STR_DATE_UC: \"DATO\"\n  STR_SOLDIERS_RECRUITED_UC: \"SOLDATER REKRUTTERT>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"SOLDATER TAPT>{ALT}{0}\"\n  MAP_CULTA: \"Bondegård\"\n  MAP_FOREST: \"Skog\"\n  MAP_JUNGLE: \"Jungel\"\n  MAP_MOUNT: \"Fjell\"\n  MAP_DESERT: \"Ørken\"\n  MAP_POLAR: \"Arktis\"\n  MAP_URBAN: \"By\"\n  MAP_UBASE: \"Alien-Base\"\n  MAP_XBASE: \"X-Com Base\"\n  MAP_MARS: \"Mars\"\n  STR_MIXED: \"Blanding\"\n  STR_REMOVE_SELECTED: \"Fjern Valgte\"\n  STR_LIVE_ALIENS: \"Levende{NEWLINE}Eksemplarer\"\n  STR_DEAD_ALIENS: \"Forkastede{NEWLINE}Eksemplarer\"\n  STR_UNDER_INTERROGATION: \"Blir{NEWLINE}Studert\"\n  STR_GO_TO_BASE: \"Gå til Base\"\n  STR_MELEE_ACCURACY: \"NÆRKAMP-FERDIGHET\"\n  STR_SELL_PRODUCTION: \"SELG\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Begge hender må være tomhendt!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Ikke nok utstyr til å kopiere mal!\"\n  STR_UNLOAD_WEAPON: \"Ta av våpen\"\n  STR_ALL_ITEMS: \"Alle Gjenstander\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"X-Com bygninger kan ikke plasseres under vann\"\n  STR_LEVEL_SHORT: \"{0}\"\n  STR_PERSONNEL: \"Personell\"\n  STR_CRAFT_ARMAMENT: \"Fartøy & Bevæpning\"\n  STR_COMPONENTS: \"Komponenter\"\n  STR_SOLDIERS_RECRUITED: \"Soldater rekruttert\"\n  STR_SOLDIERS_LOST: \"Soldater tapt\"\n  STR_TOTAL_UFOS: \"UFOer oppdaget\"\n  STR_TOTAL_ALIEN_BASES: \"Alien-baser funnet\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"PST\"\n  FEMALE_CIVILIAN: \"Sivil, Kvinne\"\n  MALE_CIVILIAN: \"Sivil, Mann\"\n  CYBERDISC_WEAPON: \"Cyberdisc Våpen\"\n  REAPER_WEAPON: \"Reaper Våpen\"\n  CHRYSSALID_WEAPON: \"Chryssalide Våpen\"\n  CELATID_WEAPON: \"Celatide Våpen\"\n  SILACOID_WEAPON: \"Silacoide Våpen\"\n  SECTOPOD_WEAPON: \"Sectopode Våpen\"\n  ZOMBIE_WEAPON: \"Zombi Våpen\"\n  ALIEN_PSI_WEAPON: \"Alien Psi Våpen\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/pl.yml",
    "content": "pl:\n  STR_AVENGER_UFOPEDIA: \"TRANSPORTOWY MYŚLIWIEC KOSMICZNY, WIERNIE ODWZOROWUJĄCY TECHNOLOGIĘ OBCYCH.\"\n  STR_INTERCEPTOR_UFOPEDIA: \"MYŚLIWIEC Z PODWÓJNYMI SILNIKAMI PULSACYJNYMI, WYPOSAŻONY W SPECJALISTYCZNE ZABEZPIECZENIA SYSTEMÓW ELEKTRONICZNYCH. NAJWYŻSZE OSIĄGNIĘCIE LOTNICZE ZIEMSKIEJ MYŚLI TECHNICZNEJ.\"\n  STR_LIGHTNING_UFOPEDIA: \"SKUTECZNY MYŚLIWIEC TRANSPORTOWY, PROWIZORYCZNA LECZ EFEKTYWNA REPLIKA OBCYCH SYSTEMÓW NAPĘDU.\"\n  STR_SKYRANGER_UFOPEDIA: \"NAJSZYBSZY TRANSPORTOWIEC WOJSKA TEGO TYPU, POSIADAJĄCY ZDOLNOŚĆ PIONOWEGO STARTU I LĄDOWANIA (PSiL).\"\n  STR_FIRESTORM_UFOPEDIA: \"JEDNOMIEJSCOWY MYŚLIWIEC, BĘDĄCY REPLIKĄ KLASYCZNEGO LATAJĄCEGO SPODKA OBCYCH Z CENTRALNIE UMIESZCZONĄ JEDNOSTKĄ NAPĘDOWĄ.\"\n  STR_STINGRAY_UFOPEDIA: \"ZAAWANSOWANA RAKIETA KLASY POWIETRZE-POWIETRZE Z DODATKOWĄ OSŁONĄ ZABEZPIECZAJĄCĄ ELEKTRONIKĘ.\"\n  STR_AVALANCHE_UFOPEDIA: \"RAKIETA KLASY POWIETRZE-POWIETRZE UZBROJONA W GŁOWICĘ NUKLEARNĄ O NIESAMOWICIE DUŻEJ MOCY.\"\n  STR_CANNON_UFOPEDIA: \"DZIAŁO WYSOKIEJ MOCY STRZELAJĄCE POCISKAMI PRZECIWPANCERNYMI ZDOLNYMI PRZEBIĆ 400 MM STALI.\"\n  STR_FUSION_BALL_UFOPEDIA: \"TA WYRZUTNIA STRZELA KULISTYMI POCISKAMI KIEROWANYMI, KTÓRE SĄ ZASILANE PRZEZ REAKCJĘ ANTYMATERII. KULA NISZCZY CEL FALĄ GRAWITACYJNEJ IMPLOZJI.\"\n  STR_LASER_CANNON_UFOPEDIA: \"TEN KONWENCJONALNY TRANSMITER LASEROWY JEST ZASILANY PRZEZ KOMORĘ REAKCYJNĄ ANTYMATERII.\"\n  STR_PLASMA_BEAM_UFOPEDIA: \"TRANSMITER GRAWITACYJNY FORMUJE WĄSKIE POLE KANAŁOWE GRAWITACYJNEJ IMPLOZJI.\"\n  STR_SECTOID_UFOPEDIA: \"Hierarchia sektoidów rozciąga się od żołnierzy po przywódców o potężnych zdolnościach psi. Te moce mogą być użyte podczas walki do obniżania morale żołnierzy wroga, a nawet do kontrolowania ich umysłów. Sektoidy chętnie okaleczają bydło i porywają ludzi. Porwani są wykorzystywani jako źródło materiału genetycznego dla sztucznie hodowanych i rozwijanych klonów, infiltrujących ludzkie społeczeństwo. Bydło natomiast służy jako źródło materiału genetycznego i pożywienie. Rasa ta wydaje się tworzyć wysokiej jakości genetyczne hybrydy, by zwiększyć wydajność ich przypominającego rój społeczeństwa.\"\n  STR_SECTOID_AUTOPSY: \"Sekcja sektoida\"\n  STR_SECTOID_AUTOPSY_UFOPEDIA: \"Sekcja wyjawiła prostą budowę ciała ze śladowymi organami trawiennymi. Mózg i oczy są bardzo dobrze rozwinięte. Budowa ciała sugeruje zmiany genetyczne lub mutacje. Małe usta i nos wydają się pełnić mało znaczące funkcje. Błona między palcami u rąk i płaskie stopy sugerują wodne pochodzenie. Brak jest organów rozrodczych i ich śladów, które wyjaśniłyby, jak ten gatunek się rozmnaża. Prawdopodobnie został genetycznie zaprojektowany.\"\n  STR_SNAKEMAN_UFOPEDIA: \"Ta rasa rozwinęła się w nadzwyczaj nieprzyjaznym środowisku. Jest niezwykle wytrzymała i może przetrwać w skrajnych wahaniach temperatur. Osobniki przemieszczają się za pomocą olbrzymiej 'stopy', która chroni wszystkie istotne organy wewnętrzne. Ich cele zdają się wynikać wyłącznie z drapieżnictwa i według nas są pod kontrolą innych inteligentnych istot, które kierują ich militarnymi działaniami na Ziemi.\"\n  STR_SNAKEMAN_AUTOPSY: \"Sekcja wężownika\"\n  STR_SNAKEMAN_AUTOPSY_UFOPEDIA: \"Skóra jest bardzo twarda i wytrzymała na ciepło. Układ sercowo-naczyniowy jest częścią układu mięśniowego i tworzą razem układ hydrauliczny, który porusza częściami ciała. Jedynym prawdziwym mięśniem jest serce. Układ rozrodczy wydaje się bardzo wydajny. Wężowniki są obojnakami. Każdy z nich może jednocześnie przenosić do 50 jaj wewnątrz własnego ciała. Pozostawiona sama sobie, rasa ta stałaby się poważnym zagrożeniem dla życia na Ziemi.\"\n  STR_ETHEREAL_UFOPEDIA: \"Ta istota ma niesamowitą moc umysłową, która umożliwia jej komunikację telepatyczną oraz telekinezę. Prawdopodobnie małe możliwości fizyczne tej istoty są wspomagane przez moc umysłu. Nie możemy zrozumieć, jak działają te telekinetyczne zdolności, ponieważ zdają się przeczyć prawom fizyki, które znamy. W walce w każdej sytuacji etereale są bardzo niebezpieczne, ale tylko dopóki mogą liczyć na siłę swojego umysłu. Rzadko zjawiają się na Ziemi, ponieważ według nas liczą na inne rasy, które wykonują ich rozkazy.\"\n  STR_ETHEREAL_AUTOPSY: \"Sekcja eterianina\"\n  STR_ETHEREAL_AUTOPSY_UFOPEDIA: \"Ta istota jest niedorozwinięta fizycznie i wygląda na niezdolną do podtrzymywania jakichkolwiek własnych funkcji życiowych. Mięśnie są w stanie poważnego zaniku, a wewnętrzne organy wyglądają na atroficzne. Narządy zmysłów, włącznie z oczami, zdają się w ogóle nie działać. Mózg za to jest dobrze rozwinięty, ale potrzebuje dużych dostaw krwi. Jest dla nas zagadką, jak te stworzenia mogą funkcjonować bez zewnętrznej pomocy.\"\n  STR_MUTON_UFOPEDIA: \"Te ludzko-podobne istoty są silne fizycznie i inteligentne. Mają szczególny apetyt na surowe mięso każdego rodzaju, którego potrzebują do przeżycia - podobnie jak nasze ziemskie drapieżniki. Prawdopodobnie otrzymują rozkazy telepatycznie od rasy zwanej eterianami. Jeśli tylko to telepatyczne połączenie zostanie przerwane, ich system nerwowy zdaje się załamywać i wtedy umierają. Cybernetyczne implanty zwiększają ich bitewne możliwości. Najwyraźniej są żołnierzami piechoty wyższej inteligencji.\"\n  STR_MUTON_AUTOPSY: \"Sekcja mutona\"\n  STR_MUTON_AUTOPSY_UFOPEDIA: \"Skóra tych istot wydaje się stworzonym z materiału organicznego pancerzem zabezpieczającym, który jest wszczepiony na ciało. Zastosowano liczne implanty cybernetyczne do wspomagania zmysłów i układu sercowo-naczyniowego. Narządy rozrodcze zostały prawdopodobnie chirurgicznie usunięte. Życie tych nieszczęsnych stworzeń ewidentnie ogranicza się do walki i zabijania. Amunicja przeciwpancerna jest mało efektywna przeciwko ich twardej skórze.\"\n  STR_CELATID_UFOPEDIA: \"Ta forma życia ma tajemniczą naturalną zdolność do unoszenia się w powietrzu. Potrafi ona wyczuwać ludzkie fale mózgowe i podążać za człowiekiem, nawet jeśli ten dobrze się ukryje. Gdy tylko cel zostanie wykryty, celatyd ląduje i zaczyna strzelać w jego kierunku małymi granulkami bardzo żrącego jadu. Istota ta ma zdolności do klonowania się w zastraszającym tempie. Towarzyszy rasie mutonów w jej wyprawach.\"\n  STR_CELATID_AUTOPSY: \"Sekcja celatyda\"\n  STR_CELATID_AUTOPSY_UFOPEDIA: \"Rdzeń zawiera małe biomechaniczne urządzenie, które wydaje się naturalnie wyewoluowanym układem napędu anty grawitacyjnego. Gruczoł jadowy jest największym organem, a wydzielona struktura mózgowa prawdopodobnie nie istnieje. Nie stwierdziliśmy obecności układów trawiennego i rozrodczego. Pewien mały organ natomiast zawiera embriony, które mogą szybko rozwijać się w nowym ciele.\"\n  STR_SILACOID_UFOPEDIA: \"Ta forma życia opartego na krzemie wytwarza olbrzymią ilość ciepła. Potrafi ona kruszyć kamienie dzięki rozgrzewaniu ich w swoim gorącym ciele. Dysponuje prymitywnym rozumem, przez co może być kontrolowana przez inne istoty telepatycznie lub za pomocą implantów. Współdziała z rasą mutonów.\"\n  STR_SILACOID_AUTOPSY: \"Sekcja silakoida\"\n  STR_SILACOID_AUTOPSY_UFOPEDIA: \"Wnętrze tych istot jest bardzo gorące, a ciepło wydaje się podstawowym czynnikiem trawiennym. Ich unikalny system mięśniowy jest niesamowicie silny i szybki, a skało-podobna skóra jest niewrażliwa na ogień czy amunicję zapalającą.\"\n  STR_CHRYSSALID_UFOPEDIA: \"Szczypce tych istot podobne do kraba są potężną bronią w bezpośrednim kontakcie. Szybka przemiana materii oraz siła tego stworzenia sprawiają, że jest ono szybkie i sprawne. Zamiast zabijać swoją ofiarę, składa ono wewnątrz jej ciała jajo oraz wprowadza jad, który zamienia ją w żywego trupa. Wkrótce po złożeniu jaja nowy kryzalid rozrywa od wewnątrz swoją ofiarę. Kryzalidy współpracują z rasą wężowników.\"\n  STR_CHRYSSALID_AUTOPSY: \"Sekcja kryzalida\"\n  STR_CHRYSSALID_AUTOPSY_UFOPEDIA: \"Egzoszkielet tych istot jest bardzo twardy, ale kruchy, przez co zadziwiająco podatny na uszkodzenia z amunicji eksplodującej. Mózg jest dobrze rozwinięty, a rozwój komórek jest bardzo szybki. Stworzenia te przenoszą około 20 jaj, które znoszą do wnętrza innych organizmów, przez cio są bardzo efektywną bronią terrorystyczną.\"\n  STR_FLOATER_UFOPEDIA: \"Lewitony są przede wszystkim żołnierzami i terrorystami. Z natury są zabójczymi bestiami wspomaganymi cybernetyką i genetycznie poprawionymi, by lepiej walczyć. Dolna część ciała i większość organów wewnętrznych zostały chirurgicznie usunięte, a na ich miejsce został wstawiony system podtrzymywania życia. System ten zawiera jednostkę anty-grawitacyjną, która pozwala tym stworzeniom, choć niestabilnie, lewitować w powietrzu (stąd nazwa tychże stworzeń).\"\n  STR_FLOATER_AUTOPSY: \"Sekcja lewitona\"\n  STR_FLOATER_AUTOPSY_UFOPEDIA: \"Ta istota została drastycznie zmodyfikowana chirurgicznie. Urządzenie, które zdaje się tworzyć tułów, jest systemem podtrzymywania życia. System ten pełni funkcje usuniętego serca, płuc i układu trawiennego, co umożliwia tym istotom przetrwanie nawet w ekstremalnie nieprzyjaznym środowisku. Mózg jest mniejszy niż nasz, ale narządy zmysłów są dobrze rozwinięte.\"\n  STR_REAPER_UFOPEDIA: \"Ten stwór ma potężne szczęki i ogromny apetyt. Posiada też liczne implanty w mózgu, które są używane do kontrolowania jego aktywności. Prymitywne instynkty tych zabójczych stworzeń są mało użyteczne, chyba że chodzi o terroryzowanie i niszczenie. Żeńce zwykle towarzyszą lewitonom.\"\n  STR_REAPER_AUTOPSY: \"Sekcja żeńca\"\n  STR_REAPER_AUTOPSY_UFOPEDIA: \"Żeńce posiadają dwa mózgi i dwa serca, które pozwalają im funkcjonować, nawet gdy są ciężko ranne. Jednak ich futrzana skóra jest łatwopalna, przez co są podatne na broń zapalającą.\"\n  STR_SECTOPOD_UFOPEDIA: \"Sektopody to wielkie mechaniczne bestie z potężną bronią strzelającą wiązkami lasera, które są kontrolowane poprzez połączenie telepatyczne dzięki eterianom. Są jednocześnie jedną z najsilniejszych broni terrorystycznych dostępnych w siłach zbrojnych u obcych.\"\n  STR_SECTOPOD_AUTOPSY: \"Analiza części sektopoda\"\n  STR_SECTOPOD_AUTOPSY_UFOPEDIA: \"Robot ma mocną konstrukcję z twardym pancerzem, który jest zdolny stawić opór większości rodzajom broni, w szczególności broni plazmowej. Jednakże delikatne obwody wydają się szczególnie podatne na uszkodzenia z broni laserowej.\"\n  STR_CYBERDISC_UFOPEDIA: \"Ten miniaturowy latający spodek jest zautomatyzowaną bronią terrorystyczną uzbrojoną w silne działko plazmowe. Napęd anty-grawitacyjny daje im dużą przewagę na trudnym terenie. Podstawowymi zadaniami tego spodka są terror i niszczenie w służbie rasy sektoidów.\"\n  STR_CYBERDISC_AUTOPSY: \"Analiza części cyberdysku\"\n  STR_CYBERDISC_AUTOPSY_UFOPEDIA: \"Cyber-dysk jest dobrze opancerzony, a w szczególności odporny na amunicję eksplodującą. Niestety, główny system anty-grawitacyjny jest zbyt uszkodzony, by zrozumieć jego działanie.\"\n  STR_UFO_POWER_SOURCE_UFOPEDIA: \"Źródłem energii statków obcych są reaktory antymaterii, które wykorzystują eler - pierwiastek o liczbie atomowej Z=115 do generowania silnych fal grawitacyjnych, a także różnych form energii. Przekształcanie materii w energię jest niesamowicie wydajne i wynosi 99%, dlatego mała ilość eleru może wytworzyć ogromną ilość energii. To urządzenie może być łatwo reprodukowane przy użyciu stopów metali obcych.\"\n  STR_UFO_NAVIGATION_UFOPEDIA: \"Statki obcych używają wyspecjalizowanych komputerów do nawigacji na Ziemi i w przestrzeni kosmicznej. System bazuje na procesorach optycznych połączonych na wzór sieci. Sterowanie statkiem jest stosunkowo proste: nawigator kontroluje generowane przez źródło zasilania fale grawitacyjne przemieszczające statek w dowolnym kierunku. System ten może być przez ludzi łatwo używany oraz reprodukowany przy użyciu stopów metali obcych.\"\n  STR_UFO_CONSTRUCTION_UFOPEDIA: \"Statki obcych składają się z trzech głównych komponentów: reaktorów antymaterii będących źródłem energii, systemu nawigacyjnego i kadłuba zbudowanego ze stopów metali obcych. Kadłub jest tak skonstruowany, by można było kierować i kontrolować fale grawitacyjne. Dodatkowo potrzebne są małe ilości eleru jako paliwa dla źródła energii. Jeśli tylko poznamy i zrozumiemy zasady budowy oraz funkcje każdego z komponentów, wtedy możliwe będzie zbudowanie statku tego typu.\"\n  STR_ALIEN_FOOD_UFOPEDIA: \"Te komory zawierają rozmaite enzymy, które są używane do trawienia części ciała bydła, innych zwierząt, a nawet ludzi. Powstały płyn jest następnie wchłaniany jako gotowy przetrawiony pokarm, prawdopodobnie prosto do obiegu krwi. To sugeruje pewną zależność między zwierzętami na Ziemi a obcymi: swego rodzaju symbiozę między Ziemią a społeczeństwem obcych.\"\n  STR_ALIEN_REPRODUCTION_UFOPEDIA: \"Te komory zawierają płody obcych. Konstrukcja tych pojemników sugeruje, że obcy, którzy używają metod klonujących, całkowicie polegają na reprodukcji laboratoryjnej. Pożywne odżywki zapewniają szybki rozwój płodów. Taki taśmowy system fabrykujący może wytworzyć tysiące klonów obcych w krótkim okresie czasu. Proces ten może być łatwo przystosowany do reprodukcji ludzi lub tworzenia krzyżówek obcych z ludźmi.\"\n  STR_ALIEN_ENTERTAINMENT_UFOPEDIA: \"Najbardziej prawdopodobne jest, że sfery te służą jako źródło rozrywki. Wyładowania psioniczne pobudzają rozmaite ośrodki mózgu. Efekt jest podobny jak po zażyciu narkotyków halucynogennych. To jest jedyny dowód na to, że obcy mają jakąkolwiek kulturę lub chwile rozrywki.\"\n  STR_ALIEN_SURGERY_UFOPEDIA: \"Ten sprzęt obcych używa laserowych noży, by wyciąć pewne części ciała z bydła i innych zwierząt. Szeroko rozprzestrzenione przypadki okaleczania bydła mogą być wyjaśnione tą dziwną działalnością ze strony obcych. Organy są zapewne wykorzystywane do odżywiania innych obcych lub celów genetycznych.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"W przeszłości wiele tysięcy osób twierdziło, że zostali porwani przez obcych, niekiedy wielokrotnie. Prawda tymczasem jest dużo bardziej przerażająca: ludzie są porywani, badani i obserwowani. Z najlepszych okazów wydobywa się materiał genetyczny. Kobietom implantuje się płody krzyżówek ludzi i obcych, a potem usuwa kilka miesięcy później. Kto wie, jakimi złowrogimi motywami kierują się obcy?\"\n  STR_ALIEN_ALLOYS_UFOPEDIA: \"Statki obcych są skonstruowane ze specjalnych stopów metali o unikalnych właściwościach. Stopy te są bardzo lekkie i jednocześnie niesamowicie wytrzymałe. Mogą być modelowane metodami elektromagnetycznymi oraz być reprodukowane i używane do różnych celów w procesach produkcyjnych.\"\n  STR_ELERIUM_115_UFOPEDIA: \"Ten pierwiastek chemiczny o liczbie atomowej Z=115 posiada niezwykłą własność generowania antymaterii podczas bombardowania go pewnymi cząstkami. Proces ten wytwarza fale grawitacyjne i różne formy energii. W naszym Układzie Słonecznym nie występuje naturalnie i nie może być reprodukowany.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"Jest jasne, że na Ziemi walczymy w przegranej bitwie. Hordy obcych są przytłaczająco liczne. Najlepsze co możemy zrobić to spowolnić ich inwazję. Jedyną nadzieją ludzkości jest zniszczenie obcych poprzez zaatakowanie ich źródła. Nasze badania wskazują na istnienie pobliskiej bazy operacyjnej w obrębie Układu Słonecznego. Z licznych badań nad obcymi wynika, że jest to centrum starożytnej cywilizacji, starszej nawet od ludzkiej historii. Musimy zlokalizować to miejsce jak najszybciej. W związku z tym musimy pojmać i przesłuchać lidera obcych, by zyskać bardziej szczegółowe informacje. Większe UFO prawdopodobnie mają na pokładzie co najmniej jednego lidera obcych.\"\n  STR_THE_MARTIAN_SOLUTION_UFOPEDIA: \"Według naszych najnowszych badań baza operacyjna obcych znajduje się na Marsie. Jest ona dobrze ukryta i wyposażona we wszelakie systemy produkcji i klonowania potrzebne do infiltracji Ziemi. Wydaje się, że mieści również jakiegoś rodzaju komputer kontrolujący całą operację. Prawdopodobnie społeczeństwo obcych, która przypomina rój pszczół, podobnie jak one ma też swego rodzaju 'królową'. Jest to istotna słabość obcych - jeśli potrafimy unicestwić 'mózg', wtedy całe ciało umrze. Musimy zwiększyć tempo i wysiłek naszych badań, zanim będzie za późno. W pierwszej kolejności musimy pojmać najwyższych rangą obcych - przywódców - którzy przebywają tylko w bazach obcych i na pokładzie pancerników.\"\n  STR_CYDONIA_OR_BUST_UFOPEDIA: \"Teraz jest jasne, że hordy obcych są kontrolowane z podziemnej bazy w Cydonii. Jest to niezwykłe miejsce na Marsie, które cechuje się pięciobocznymi piramidami i dużą formacją przypominającą ludzką twarz. Miliony lat temu na Marsie kwitła cydońska cywilizacja. Niestety, nie wiemy jednak, dlaczego wymarła ani jakie jest jej powiązanie z ostatnią aktywnością obcych na tamtym obszarze. Jakby tego było mało, musimy wysłać ekspedycję do Cydonii. Jest to jedyny sposób, by pokonać obcych. Musimy zniszczyć główny kontrolujący 'Mózg'! Potrzebujemy do tego 'Mściciela' wyposażonego w najbardziej niszczycielską broń, jaką mamy do dyspozycji. Nic więcej nie ma tu do odkrycia - pozostaje jedynie nadzieja w ataku na Cydonię.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"WSKAŻ MIEJSCE - CZAS: 5 sekund\"\n  STR_CANCEL_UC: \"ANULUJ\"\n  STR_NONE: \"Żaden\"\n  STR_UNKNOWN: \"Nieznany\"\n  STR_POOR: \"Słaby\"\n  STR_AVERAGE: \"Średni\"\n  STR_GOOD: \"Dobry\"\n  STR_EXCELLENT: \"Znakomity\"\n  STR_BUILD_NEW_BASE_UC: \"BUDUJ NOWĄ BAZĘ\"\n  STR_BASE_INFORMATION: \"INFORMACJE O BAZIE\"\n  STR_EQUIP_CRAFT: \"WYPOSAŻENIE POJAZDÓW\"\n  STR_BUILD_FACILITIES: \"BUDUJ INSTALACJĘ\"\n  STR_RESEARCH: \"BADANIA\"\n  STR_MANUFACTURE: \"PRODUKCJA\"\n  STR_TRANSFER_UC: \"TRANSFER\"\n  STR_PURCHASE_RECRUIT: \"KUP/ZATRUDNIJ\"\n  STR_SACK: \"ZWOLNIJ\"\n  STR_SELL_SACK_UC: \"SPRZEDAJ/ZWOLNIJ\"\n  STR_GEOSCAPE_UC: \"EKRAN ZIEMI\"\n  STR_NAME: \"Nazwa\"\n  STR_AREA: \"Teren\"\n  STR_BUILD_NEW_BASE: \"Buduj nową bazę\"\n  STR_CANCEL: \"Anuluj\"\n  STR_COST_UC: \"KOSZT:\"\n  STR_CONSTRUCTION_TIME_UC: \"DŁUGOŚĆ BUDOWY:\"\n  STR_DAY:\n    one: \"{N} dzień\"\n    few: \"{N} dni\"\n    many: \"{N} dni\"\n    other: \"{N} dni\"\n  STR_HOUR:\n    one: \"{N} godzina\"\n    few: \"{N} godziny\"\n    many: \"{N} godziny\"\n    other: \"{N} godziny\"\n  STR_MAINTENANCE_UC: \"UTRZYMANIE:\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Instalacja\"\n  STR_CURRENT_RESEARCH: \"AKTUALNE BADANIA\"\n  STR_SCIENTISTS_AVAILABLE: \"Dostępnych naukowców: {ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Wysłanych do badań: {ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Wolnych stanowisk badań: {ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"BADANY PROJEKT\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"WYSŁANYCH DO BADAŃ\"\n  STR_PROGRESS: \"POSTĘP\"\n  STR_NEW_PROJECT: \"Nowy projekt\"\n  STR_CANCEL_PROJECT: \"ANULUJ BADANIA\"\n  STR_NEW_RESEARCH_PROJECTS: \"NOWE PROJEKTY NAUKOWE\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"DOSTĘPNYCH NAUKOWCÓW: {ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"WOLNYCH STANOWISK BADAŃ: {ALT}{0}\"\n  STR_INCREASE: \"Zwiększ\"\n  STR_DECREASE: \"Zmniejsz\"\n  STR_START_PROJECT: \"ROZPOCZNIJ BADANIA\"\n  STR_CURRENT_PRODUCTION: \"AKTUALNA PRODUKCJA\"\n  STR_ENGINEERS_AVAILABLE: \"Dostępnych inżynierów: {ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Wysłanych do pracy: {ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Wolnych stanowisk pracy: {ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Obecne środki: {ALT}{0}\"\n  STR_ITEM: \"PRZEDMIOT\"\n  STR_ENGINEERS__ALLOCATED: \"Wysłanych do pracy\"\n  STR_UNITS_PRODUCED: \"Wykonanych sztuk\"\n  STR_TOTAL_TO_PRODUCE: \"Zlecona ilość\"\n  STR_COST__PER__UNIT: \"Koszt{NEWLINE}za{NEWLINE}sztukę\"\n  STR_DAYS_HOURS_LEFT: \"Pozostało dni/godzin\"\n  STR_NEW_PRODUCTION: \"Nowa produkcja\"\n  STR_PRODUCTION_ITEMS: \"Przedmioty do produkcji\"\n  STR_CATEGORY: \"KATEGORIA\"\n  STR_START_PRODUCTION: \"ROZPOCZNIJ PRODUKCJĘ\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} roboczogodzin na jedną sztukę\"\n  STR_COST_PER_UNIT_: \"Koszt za sztukę: {ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Wymagana przestrzeń, by rozpocząć produkcję: {ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"WYMAGANE SPECJALNE MATERIAŁY\"\n  STR_ITEM_REQUIRED: \"WYMAGANY PRZEDMIOT\"\n  STR_UNITS_REQUIRED: \"WYMAGANYCH SZTUK\"\n  STR_UNITS_AVAILABLE: \"DOSTĘPNYCH SZTUK\"\n  STR_STOP_PRODUCTION: \"PRZERWIJ PRODUKCJĘ\"\n  STR_ENGINEERS_AVAILABLE_UC: \"DOSTĘPNYCH INŻYNIERÓW: {ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"WOLNYCH STANOWISK PRACY: {ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"ZYSK MIESIĘCZNY>{ALT}{0}\"\n  STR_INCREASE_UC: \"ZWIĘKSZ\"\n  STR_DECREASE_UC: \"ZMNIEJSZ\"\n  STR_UNITS_TO_PRODUCE: \"Sztuk do produkcji\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Kup produkty/Zatrudnij ludzi\"\n  STR_COST_OF_PURCHASES: \"Koszt transakcji: {ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"KOSZT ZA SZTUKĘ\"\n  STR_QUANTITY_UC: \"SZTUK\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"DOSTĘPNY PERSONEL/CAŁY PERSONEL:\"\n  STR_SOLDIERS: \"Żołnierze\"\n  STR_SCIENTISTS: \"Naukowcy\"\n  STR_ENGINEERS: \"Inżynierowie\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"UŻYWANA PRZESTRZEŃ/DOSTĘPNA PRZESTRZEŃ:\"\n  STR_LIVING_QUARTERS: \"Kwatery mieszkalne\"\n  STR_STORES: \"Magazyny\"\n  STR_LABORATORIES: \"Laboratoria\"\n  STR_WORK_SHOPS: \"Warsztaty\"\n  STR_HANGARS: \"Hangary\"\n  STR_SHORT_RANGE_DETECTION: \"Krótki zasięg wykrycia\"\n  STR_DEFENSE_STRENGTH: \"Siła obrony\"\n  STR_TRANSFERS_UC: \"TRANSFERY\"\n  STR_TRANSFERS: \"Transfery\"\n  STR_ARRIVAL_TIME_HOURS: \"Godzin do przybycia\"\n  STR_COST_: \"Koszt: {ALT}{0}\"\n  STR_AREA_: \"Teren: {ALT}{0}\"\n  STR_BASE_NAME: \"Wpisz nazwę bazy\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"WYBIERZ POŁOŻENIE WINDY WEJŚCIOWEJ\"\n  STR_TRANSFER: \"Transfer\"\n  STR_AMOUNT_TO_TRANSFER: \"SZTUK DO TRANSFERU\"\n  STR_SELECT_DESTINATION_BASE: \"Wybierz bazę docelową\"\n  STR_COST: \"Koszt\"\n  STR_VICTORY_1: \"Po wejściu do sali zobaczyłeś 'Mózg' obcych - obiekt Twoich poszukiwań. Zanim postanowiłeś strzelić, skomunikował się z Tobą poprzez ekran w swojej bazie. To 'coś' błagało Cię o wysłuchanie argumentów obrony, nim podejmiesz decyzję, by pociągnąć za spust...\"\n  STR_VICTORY_2: \"'Mózg' mówi: 'Wiele milionów lat temu planeta zwana przez was Marsem była żywa. Nasza cywilizacja sprowadziła życie na tę jałową planetę, tak jak i sprowadziła na waszą. Przez miliony lat odwiedzaliśmy waszą planetę i genetycznie rozwijaliśmy wasz gatunek. Nie możecie nas zabić, jesteście częścią nas...\"\n  STR_VICTORY_3: \"To jest centrum marsjańskiej cywilizacji - piramidy, który wybudował miliony lat przed wami gatunek będący waszym przodkiem. Nie ma planety poza naszym zasięgiem. Ta potęga może być wkrótce wasza. Pytanie brzmi: Czy chcesz współpracować...'\"\n  STR_GAME_OVER_1: \"Obcym udało się wytępić całą ludzkość, niszcząc miasta oraz zatruwając powietrze i wodę. Opór ziemskich armii był daremny w starciu z o wiele wyższą technologią. Pokolenia, które przetrwały, cierpią teraz z powodu okropnych mutacji, jak i{NEWLINE}ucieczek przed obcymi, którzy tępią ludzi. Wielu ludzi przebywa w obozach pracy, pomagając przekształcać Ziemię w kolonię obcych, która jest częścią pewnego nieznanego imperium.\"\n  STR_GAME_OVER_2: \"Wiedza zdobyta podczas projektu X-Com została utracona na zawsze. Nie udało Ci się ochronić Ziemi.\"\n  STR_VICTORY_4: \"'Mózg' obcych został rozerwany przez wybuch gorącej plazmy, przez co cała armia obcych została pokonana.\"\n  STR_VICTORY_5: \"Obcy utracili Marsa, a teraz stracili też Ziemię. Wkrótce odkrycia organizacji X-Com pozwolą ludzkości raz jeszcze rozkwitnąć i posiąść Marsa już dla siebie. Zagrożenie ze strony obcych zażegnane, ale na jak długo, kto wie...\"\n  STR_YOU_HAVE_FAILED: \"Nie udało Ci się powstrzymać najazdu obcych. Państwa sponsorujące Twoją organizację, jedno po drugim, podpisały pakt obiecujący dostęp do technologii obcych - w myśl dobrobytu i pokoju. Jednak niebawem stało się jasne, że obcy mają inne plany...\"\n  STR_TOTAL_UC: \"SUMA\"\n  STR_INCOME: \"Dochód\"\n  STR_EXPENDITURE: \"Wydatki\"\n  STR_MAINTENANCE: \"Utrzymanie\"\n  STR_BALANCE: \"Bilans\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"Aktywność obcych na terenach\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"Aktywność obcych w państwach\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"Aktywność X-Comu na terenach\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"Aktywność X-Comu w państwach\"\n  STR_FINANCE: \"Finanse\"\n  STR_DATE_FIRST: \"{0}.\"\n  STR_DATE_SECOND: \"{0}.\"\n  STR_DATE_THIRD: \"{0}.\"\n  STR_DATE_FOURTH: \"{0}.\"\n  STR_FINANCE_THOUSANDS: \"tys. $\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Brakuje specjalnych materiałów, żeby produkować{NEWLINE}{0}{NEWLINE}w bazie{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Brakuje pieniędzy, żeby produkować{NEWLINE}{0}{NEWLINE}w bazie{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"Produkcja{NEWLINE}{0}{NEWLINE}w bazie{NEWLINE}{1}{NEWLINE}została zakończona\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"Budowa {0}{NEWLINE}w bazie {1}{NEWLINE}została zakończona\"\n  STR_OK_5_SECONDS: \"OK - CZAS: 5 sekund\"\n  STR_RESEARCH_COMPLETED: \"Badania zakończone\"\n  STR_VIEW_REPORTS: \"ZOBACZ RAPORT\"\n  STR_WE_CAN_NOW_RESEARCH: \"Możemy teraz badać\"\n  STR_WE_CAN_NOW_PRODUCE: \"Możemy teraz produkować\"\n  STR_SUNDAY: \"NIEDZIELA\"\n  STR_MONDAY: \"PONIEDZIAŁEK\"\n  STR_TUESDAY: \"WTOREK\"\n  STR_WEDNESDAY: \"ŚRODA\"\n  STR_THURSDAY: \"CZWARTEK\"\n  STR_FRIDAY: \"PIĄTEK\"\n  STR_SATURDAY: \"SOBOTA\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Brakuje {0}, by zatankować {1} w bazie {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Brakuje {0}, by dozbroić {1} w bazie {2}\"\n  STR_UFO_IS_NOT_RECOVERED: \"UFO nieprzejęte\"\n  STR_UFO_IS_RECOVERED: \"UFO przejęte\"\n  STR_CRAFT_IS_LOST: \"Pojazd stracony\"\n  STR_TERROR_CONTINUES: \"Terror trwa\"\n  STR_ALIENS_DEFEATED: \"Obcy pokonani\"\n  STR_BASE_IS_LOST: \"Baza stracona\"\n  STR_BASE_IS_SAVED: \"Baza uratowana\"\n  STR_ALIEN_BASE_STILL_INTACT: \"Baza obcych nadal istnieje\"\n  STR_ALIEN_BASE_DESTROYED: \"Baza obcych zniszczona\"\n  STR_ALIENS_KILLED: \"ZABITYCH OBCYCH\"\n  STR_ALIEN_CORPSES_RECOVERED: \"ZNALEZIONYCH ZWŁOK OBCYCH\"\n  STR_LIVE_ALIENS_RECOVERED: \"POJMANYCH ŻYWYCH OBCYCH\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"ZNALEZIONYCH PRZEDMIOTÓW OBCYCH\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"ZNISZCZONO STEROWNIĘ BAZY OBCYCH\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"CYWILI ZABITYCH PRZEZ OBCYCH\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"CYWILI ZABITYCH PRZEZ ŻOŁNIERZY X-COMU\"\n  STR_CIVILIANS_SAVED: \"URATOWANYCH CYWILI\"\n  STR_XCOM_OPERATIVES_KILLED: \"ZABITYCH ŻOŁNIERZY X-COMU\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"ZAGINIONYCH W AKCJI ŻOŁNIERZY X-COMU\"\n  STR_TANKS_DESTROYED: \"ZNISZCZONYCH CZOŁGÓW\"\n  STR_XCOM_CRAFT_LOST: \"STRACONYCH POJAZDÓW X-COMU\"\n  STR_UFO_RECOVERY: \"PRZEJĘTE POZOSTAŁOŚCI UFO\"\n  STR_ALIEN_BASE_RECOVERY: \"PRZEJĘTE POZOSTAŁOŚCI BAZY OBCYCH\"\n  STR_BASE_UNDER_ATTACK: \"Baza '{0}' jest atakowana!\"\n  STR_BASE_DEFENSES_INITIATED: \"ZAINICJOWANO SYSTEMY OBRONNE BAZY\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"TARCZA GRAWITACYJNA ODPYCHA UFO!\"\n  STR_FIRING: \"STRZELA\"\n  STR_HIT: \"TRAFIENIE!\"\n  STR_UFO_DESTROYED: \"UFO ZNISZCZONE!\"\n  STR_MISSED: \"PUDŁO!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Sprzedaj produkty/Zwolnij ludzi\"\n  STR_VALUE_OF_SALES: \"WARTOŚĆ SPRZEDAŻY: {ALT}{0}\"\n  STR_FUNDS: \"PIENIĄDZE: {ALT}{0}\"\n  STR_SELL_SACK: \"Sprzedaj/Zwolnij\"\n  STR_VALUE: \"Wartość\"\n  STR_CRAFT_: \"POJAZD: {ALT}{0}\"\n  STR_CRAFTNAME: \"{0} {1}\"\n  STR_UFO_CRASH_RECOVERY: \"PRZEJĘCIE ROZBITEGO UFO\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"Zachowaj ostrożność! Obcy mogą być aktywni w UFO lub pobliżu miejsca katastrofy. Misja będzie zakończona powodzeniem, gdy wszystkie jednostki wroga zostaną wyeliminowane lub zneutralizowane. Nastąpi wtedy przejęcie pozostałości UFO, przedmiotów i martwych obcych. By przerwać misję, wycofaj żołnierzy X-Comu do transportowca i kliknij na ikonę 'Przerwij misję', po czym potwierdź wybór.\"\n  STR_UFO_GROUND_ASSAULT: \"PRZEJĘCIE UFO NA LĄDOWISKU\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"Zbadaj miejsce lądowania i, jeśli to możliwe, wejdź do UFO. Misja zakończy się powodzeniem, gdy wszystkie jednostki wroga zostaną wyeliminowane lub zneutralizowane. Nastąpi wtedy przejęcie pozostałości UFO, przedmiotów i martwych obcych. By przerwać misję, wycofaj agentów X-Comu do transportowca i kliknij na ikonę 'Przerwij misję', po czym potwierdź wybór.\"\n  STR_BASE_DEFENSE: \"OBRONA BAZY X-COMU\"\n  STR_BASE_UC_: \"BAZA: {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"W pobliżu wylądował statek obcych. Nasza baza jest w wielkim niebezpieczeństwie. Standardową procedurą w takiej sytuacji jest ewakuacja całego niewalczącego personelu wszystkimi dostępnymi pojazdami X-Comu. Jednostki obcych mogły wejść do bazy przez wrota hangarów lub windę wejściową. Obroń bazę i jej istotne instalacje za wszelką cenę. To jest walka na śmierć i życie. Jeśli klikniesz ikonę 'Przerwij misję' i potwierdzisz wybór, poniesiesz klęskę i stracisz tę bazę.\"\n  STR_ALIEN_BASE_ASSAULT: \"SZTURM NA BAZĘ OBCYCH\"\n  STR_ALIEN_BASE_ASSAULT_BRIEFING: \"Żołnierze X-Comu znaleźli wejście do bazy obcych. Aby baza została zneutralizowana, należy zniszczyć jej sterownię. Misja zakończy się, kiedy wszyscy wrogowie zostaną wyeliminowani lub gdy po zniszczeniu sterowni bazy Twój oddział powróci do zielonego obszaru będącego wyjściem i klikniesz na ikonę 'Przerwij misję', po czym potwierdzisz wybór. Po wykonaniu tej drugiej czynności wrócisz do swojego transportowca.\"\n  STR_CYDONIA_BRIEFING: \"Przybyłeś do Cydonii i znalazłeś wejście do wielkiego podziemnego kompleksu niedaleko marsjańskiego Sfinksa. Musisz zniszczyć 'Mózg' obcych, który kontroluje działalność wszystkich obcych. Los ludzkości jest w twoich rękach...\"\n  STR_TERROR_MISSION: \"TERROR OBCYCH W MIEŚCIE\"\n  STR_TERROR_MISSION_BRIEFING: \"Misja będzie zakończona powodzeniem, gdy wszystkie jednostki wroga zostaną zneutralizowane lub wyeliminowane. Uratuj życie tylu cywilom, ilu tylko zdołasz na terenie bitwy poprzez zneutralizowanie zagrożenia ze strony obcych. By przerwać misję, wycofaj żołnierzy X-Comu do transportowca i kliknij na ikonę 'Przerwij misję', po czym potwierdź wybór.\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"BRAKUJE WOLNEGO HANGARU DLA PRODUKOWANEGO POJAZDU!{SMALLLINE}Każdy pojazd przydzielony w danej bazie, przenoszony do innej bazy, kupowany lub produkowany wymaga co najmniej jednego hangaru. Wybuduj nowy hangar lub przenieś przynajmniej jeden pojazd do innej bazy.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"BRAKUJE WOLNEGO HANGARU DLA KUPOWANEGO POJAZDU!{SMALLLINE}Każdy pojazd przydzielony w danej bazie, przenoszony do innej bazy, kupowany lub produkowany wymaga co najmniej jednego hangaru. Wybuduj nowy hangar lub przenieś przynajmniej jeden pojazd do innej bazy.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"BRAKUJE WOLNEGO HANGARU DLA PRZENOSZONEGO POJAZDU!{SMALLLINE}Każdy pojazd przydzielony w danej bazie, przenoszony do innej bazy, kupowany lub produkowany wymaga co najmniej jednego hangaru. Wybuduj nowy hangar lub przenieś przynajmniej jeden pojazd do innej bazy.\"\n  STR_CANNOT_BUILD_HERE: \"NIE MOŻNA TU BUDOWAĆ!{SMALLLINE}Budowana instalacja musi sąsiadować z istniejącą.\"\n  STR_NO_FREE_ACCOMODATION: \"BRAKUJE WOLNYCH KWATER!{SMALLLINE}Brak wolnych kwater w bazie docelowej.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"BRAKUJE WOLNEGO MIEJSCA W WARSZTACIE!{SMALLLINE}Wybuduj nowy warsztat lub ogranicz pracę nad co najmniej jednym projektem.\"\n  STR_NOT_ENOUGH_MONEY: \"BRAKUJE PIENIĘDZY!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"BRAKUJE MIEJSCA W MAGAZYNACH!{SMALLLINE}Wybuduj nowe magazyny lub przenieś część zapasów do innej bazy.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"BRAKUJE WOLNYCH KWATER!{SMALLLINE}Wybuduj nowe kwatery lub przenieś część personelu do innej bazy.\"\n  STR_LAUNCH_INTERCEPTION: \"WYSYŁANIE POJAZDÓW\"\n  STR_CRAFT: \"POJAZD\"\n  STR_STATUS: \"STATUS\"\n  STR_BASE: \"BAZA\"\n  STR_READY: \"GOTOWY\"\n  STR_OUT: \"WYSŁANY\"\n  STR_REPAIRS: \"NAPRAWIANY\"\n  STR_REFUELLING: \"TANKOWANY\"\n  STR_REARMING: \"DOZBRAJANY\"\n  STR_TARGET: \"CEL: {0}\"\n  STR_WAY_POINT: \"PUNKT DOCELOWY\"\n  STR_ARE_YOU_SURE_CYDONIA: \"Czy na pewno chcesz wysłać ten pojazd na misję do Cydonii?\"\n  STR_YES: \"TAK\"\n  STR_NO: \"NIE\"\n  STR_SELECT_DESTINATION: \"WYBIERZ CEL\"\n  STR_CYDONIA: \"CYDONIA\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"WYBIERZ MIEJSCE NA NOWĄ BAZĘ\"\n  STR_RETURN_TO_BASE: \"POWRÓT DO BAZY\"\n  STR_SELECT_NEW_TARGET: \"WYBIERZ NOWY CEL\"\n  STR_PATROL: \"PATROL\"\n  STR_STATUS_: \"STATUS: {ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"USZKODZONY - WRACA DO BAZY\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"MAŁO PALIWA - WRACA DO BAZY\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"MISJA ZAKOŃCZONA - WRACA DO BAZY\"\n  STR_PATROLLING: \"PATROLUJE\"\n  STR_TAILING_UFO: \"ŚLEDZI UFO\"\n  STR_INTERCEPTING_UFO: \"PRZECHWYTUJE UFO-{0}\"\n  STR_RETURNING_TO_BASE: \"WRACA DO BAZY\"\n  STR_DESTINATION_UC_: \"CEL: {0}\"\n  STR_BASE_UC: \"BAZA: {ALT}{0}\"\n  STR_SPEED_: \"PRĘDKOŚĆ: {ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"PRĘDKOŚĆ MAKS.: {ALT}{0} w.{ALT}\"\n  STR_ALTITUDE_: \"PUŁAP: {ALT}{0}\"\n  STR_VERY_LOW: \"BARDZO NISKO\"\n  STR_LOW_UC: \"NISKO\"\n  STR_HIGH_UC: \"WYSOKO\"\n  STR_VERY_HIGH: \"BARDZO WYSOKO\"\n  STR_FUEL: \"PALIWO: {ALT}{0}\"\n  STR_WEAPON_ONE: \"BROŃ L.: {ALT}{0}\"\n  STR_NONE_UC: \"BRAK\"\n  STR_ROUNDS_: \"NABOI: {ALT}{0}\"\n  STR_WEAPON_TWO: \"BROŃ P.: {ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"POJAZDY PRZECHWYTUJĄCE\"\n  STR_BASE_: \"Baza: {0}\"\n  STR_NAME_UC: \"NAZWA\"\n  STR_AMMO_: \"AMUNICJA: {ALT}{0}\"\n  STR_CREW: \"ZAŁOGA\"\n  STR_EQUIPMENT_UC: \"EKWIPUNEK\"\n  STR_ARMOR: \"PANCERZ\"\n  STR_MAX: \"MAKS.: {ALT}{0}\"\n  STR_ROOKIE: \"Rekrut\"\n  STR_SQUADDIE: \"Kapral\"\n  STR_SERGEANT: \"Sierżant\"\n  STR_CAPTAIN: \"Kapitan\"\n  STR_COLONEL: \"Pułkownik\"\n  STR_COMMANDER: \"Komendant\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Wybierz skład dla: {0}\"\n  STR_SORT_BY: \"SORTUJ WG...\"\n  STR_ORIGINAL_ORDER: \"PIERWOTNA KOLEJNOŚĆ\"\n  STR_MISSIONS2: \"MISJE\"\n  STR_KILLS2: \"ZABITYCH\"\n  STR_WOUND_RECOVERY2: \"CZAS KURACJI\"\n  STR_SPACE_AVAILABLE: \"WOLNE MIEJSCA: {ALT}{0}\"\n  STR_SPACE_USED: \"ZAJĘTE MIEJSCA: {ALT}{0}\"\n  STR_SPACE_USED_UC: \"ZAJĘTO\"\n  STR_RANK: \"RANGA\"\n  STR_WOUNDED: \"RANNY\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Wybierz broń dla: {0}\"\n  STR_DEFENSE_VALUE: \"Wartość obrony\"\n  STR_HIT_RATIO: \"Celność\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}w gotowości do{NEWLINE}lądowania przy:{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"Rozpocząć misję?\"\n  STR_SELECT_ARMAMENT: \"Wybierz uzbrojenie\"\n  STR_AMMUNITION_AVAILABLE: \"DOSTĘPNA AMUNICJA\"\n  STR_ARMAMENT: \"UZBROJENIE\"\n  STR_NOT_AVAILABLE: \"BRAK\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"WYBIERZ PANCERZ DLA{NEWLINE}{0}\"\n  STR_TYPE: \"TYP\"\n  STR_PERSONAL_ARMOR_UC: \"PANCERZ OSOBISTY\"\n  STR_POWER_SUIT_UC: \"PANCERZ WSPOMAGANY\"\n  STR_FLYING_SUIT_UC: \"PANCERZ LATAJĄCY\"\n  STR_SELECT_ARMOR: \"Wybierz pancerz\"\n  STR_NORTH: \"PÓŁNOC\"\n  STR_NORTH_EAST: \"PÓŁNOCNY WSCHÓD\"\n  STR_EAST: \"WSCHÓD\"\n  STR_SOUTH_EAST: \"POŁUDNIOWY WSCHÓD\"\n  STR_SOUTH: \"POŁUDNIE\"\n  STR_SOUTH_WEST: \"POŁUDNIOWY ZACHÓD\"\n  STR_WEST: \"ZACHÓD\"\n  STR_NORTH_WEST: \"PÓŁNOCNY ZACHÓD\"\n  STR_SELECT_ACTION: \"WYBIERZ ZADANIE\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"KONTYNUUJ POŚCIG PRZECHWYTUJĄCY\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"ŚCIGAJ BEZ PRZECHWYTYWANIA\"\n  STR_VERY_LARGE: \"BARDZO DUŻE\"\n  STR_LARGE: \"DUŻE\"\n  STR_MEDIUM_UC: \"ŚREDNIE\"\n  STR_SMALL: \"MAŁE\"\n  STR_VERY_SMALL: \"BARDZO MAŁE\"\n  STR_GROUNDED: \"NA ZIEMI\"\n  STR_DETECTED: \"ZOSTAŁO WYKRYTE\"\n  STR_SIZE_UC: \"ROZMIAR\"\n  STR_ALTITUDE: \"PUŁAP\"\n  STR_HEADING: \"KIERUNEK\"\n  STR_SPEED: \"PRĘDKOŚĆ\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"POKAŻ UFO - CZAS: 5 sekund\"\n  STR_TRACKING_LOST: \"ZNIKNĘŁO Z RADARU\"\n  STR_REDIRECT_CRAFT: \"WYBIERZ NOWE ZADANIE\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"LEĆ DO OSTATNIEJ ZNANEJ POZYCJI UFO\"\n  STR_UFO_: \"UFO-{0}\"\n  STR_ALIEN_BASE_: \"BAZA OBCYCH-{0}\"\n  STR_CRASH_SITE_: \"ROZBITE UFO-{0}\"\n  STR_LANDING_SITE_: \"UFO NA ZIEMI-{0}\"\n  STR_WAY_POINT_: \"PUNKT DOCELOWY-{0}\"\n  STR_TERROR_SITE: \"MIEJSCE TERRORU-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}doleciał do{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"Teraz patroluje\"\n  STR_ALIEN_ORIGINS: \"Pochodzenie obcych\"\n  STR_THE_MARTIAN_SOLUTION: \"Rozwiązanie Marsjańskie\"\n  STR_CYDONIA_OR_BUST: \"Cydonia lub Śmierć\"\n  STR_UFOPAEDIA: \"UFOpedia\"\n  STR_XCOM_CRAFT_ARMAMENT: \"POJAZDY X-COMU I ICH UZBROJENIE\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"CIĘŻKIE DZIAŁA SAMOBIEŻNE\"\n  STR_WEAPONS_AND_EQUIPMENT: \"BROŃ I SPRZĘT\"\n  STR_ALIEN_ARTIFACTS: \"ARTEFAKTY OBCYCH\"\n  STR_BASE_FACILITIES: \"INSTALACJE BAZY\"\n  STR_ALIEN_LIFE_FORMS: \"OBCE FORMY ŻYCIA\"\n  STR_ALIEN_RESEARCH_UC: \"BADANIA NAD OBCYMI\"\n  STR_UFO_COMPONENTS: \"KOMPONENTY UFO\"\n  STR_UFOS: \"RODZAJE UFO\"\n  STR_SELECT_ITEM: \"WYBIERZ POZYCJĘ\"\n  STR_ACCELERATION: \"PRZYŚPIESZENIE: {ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"MAKS. ILOŚĆ PALIWA: {ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"MOCOWAŃ NA BROŃ: {ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"WYTRZYMAŁOŚĆ: {ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"ŁADOWNOŚĆ: {ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"MAKS. LICZBA CDS-ów: {ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Siła rażenia\"\n  STR_RANGE: \"Zasięg\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Celność\"\n  STR_RE_LOAD_TIME: \"Czas przeładowania\"\n  STR_SECONDS: \"{0} s\"\n  STR_DAMAGE_ARMOR_PIERCING: \"PRZEBIJAJĄCE\"\n  STR_DAMAGE_INCENDIARY: \"ZAPALAJĄCE\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"WYBUCHOWE\"\n  STR_DAMAGE_LASER_BEAM: \"LASEROWE\"\n  STR_DAMAGE_PLASMA_BEAM: \"PLAZMOWE\"\n  STR_DAMAGE_STUN: \"OGŁUSZAJĄCE\"\n  STR_DAMAGE_MELEE: \"KONTAKTOWE\"\n  STR_DAMAGE_ACID: \"KWAS\"\n  STR_DAMAGE_SMOKE: \"DYMNE\"\n  STR_SHOT_TYPE: \"TYP STRZAŁU\"\n  STR_ACCURACY_UC: \"CELNOŚĆ\"\n  STR_TIME_UNIT_COST: \"KOSZT JC\"\n  STR_DAMAGE_UC: \"OBRAŻENIA\"\n  STR_AMMO: \"AMUNICJA\"\n  STR_SHOT_TYPE_AUTO: \"Seria\"\n  STR_SHOT_TYPE_SNAP: \"Szybki\"\n  STR_SHOT_TYPE_AIMED: \"Celowany\"\n  STR_CONSTRUCTION_TIME: \"Długość budowy\"\n  STR_CONSTRUCTION_COST: \"Koszt budowy\"\n  STR_MAINTENANCE_COST: \"Koszt utrzymania\"\n  STR_LOW: \"Słabe\"\n  STR_MEDIUM: \"Średnie\"\n  STR_HIGH: \"Mocne\"\n  STR_CRAFT_WEAPON: \"Broń pojazdów\"\n  STR_CRAFT_AMMUNITION: \"Amunicja pojazdów\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Ciężkie działo samobieżne\"\n  STR_WEAPON: \"Broń\"\n  STR_AMMUNITION: \"Amunicja\"\n  STR_EQUIPMENT: \"Sprzęt\"\n  STR_ALIEN_CORPSE: \"Zwłoki obcego\"\n  STR_UFO_COMPONENT: \"Komponent UFO\"\n  STR_PERSONAL_ARMOR: \"Pancerz osobisty\"\n  STR_RAW_MATERIALS: \"Surowiec\"\n  STR_HWP_CANNON_SHELLS: \"Naboje działka do cds-a\"\n  STR_ALIEN: \"Obcy\"\n  STR_SECTOID: \"Sektoid\"\n  STR_SNAKEMAN: \"Wężownik\"\n  STR_ETHEREAL: \"Eterianin\"\n  STR_MUTON: \"Muton\"\n  STR_FLOATER: \"Lewiton\"\n  STR_CELATID: \"Celatyd\"\n  STR_SILACOID: \"Silakoid\"\n  STR_CHRYSSALID: \"Kryzalid\"\n  STR_ZOMBIE: \"Zombi\"\n  STR_REAPER: \"Żeniec\"\n  STR_SECTOPOD: \"Sektopod\"\n  STR_CYBERDISC: \"Cyberdysk\"\n  STR_LIVE_COMMANDER: \"Przywódca\"\n  STR_LIVE_LEADER: \"Lider\"\n  STR_LIVE_ENGINEER: \"Inżynier\"\n  STR_LIVE_MEDIC: \"Medyk\"\n  STR_LIVE_NAVIGATOR: \"Nawigator\"\n  STR_LIVE_SOLDIER: \"Żołnierz\"\n  STR_LIVE_TERRORIST: \"Terrorysta\"\n  STR_FLOATER_SOLDIER: \"Lewiton żołnierz\"\n  STR_FLOATER_NAVIGATOR: \"Lewiton nawigator\"\n  STR_FLOATER_MEDIC: \"Lewiton medyk\"\n  STR_FLOATER_ENGINEER: \"Lewiton inżynier\"\n  STR_FLOATER_LEADER: \"Lewiton lider\"\n  STR_FLOATER_COMMANDER: \"Lewiton przywódca\"\n  STR_SECTOID_SOLDIER: \"Sektoid żołnierz\"\n  STR_SECTOID_NAVIGATOR: \"Sektoid nawigator\"\n  STR_SECTOID_MEDIC: \"Sektoid medyk\"\n  STR_SECTOID_ENGINEER: \"Sektoid inżynier\"\n  STR_SECTOID_LEADER: \"Sektoid lider\"\n  STR_SECTOID_COMMANDER: \"Sektoid przywódca\"\n  STR_SNAKEMAN_SOLDIER: \"Wężownik żołnierz\"\n  STR_SNAKEMAN_NAVIGATOR: \"Wężownik nawigator\"\n  STR_SNAKEMAN_ENGINEER: \"Wężownik inżynier\"\n  STR_SNAKEMAN_LEADER: \"Wężownik lider\"\n  STR_SNAKEMAN_COMMANDER: \"Wężownik przywódca\"\n  STR_MUTON_SOLDIER: \"Muton żołnierz\"\n  STR_MUTON_NAVIGATOR: \"Muton nawigator\"\n  STR_MUTON_ENGINEER: \"Muton inżynier\"\n  STR_ETHEREAL_SOLDIER: \"Eterianin żołnierz\"\n  STR_ETHEREAL_LEADER: \"Eterianin lider\"\n  STR_ETHEREAL_COMMANDER: \"Eterianin przywódca\"\n  STR_CYBERDISC_TERRORIST: \"Cyberdysk terrorysta\"\n  STR_REAPER_TERRORIST: \"Żeniec terrorysta\"\n  STR_CHRYSSALID_TERRORIST: \"Kryzalid terrorysta\"\n  STR_CELATID_TERRORIST: \"Celatyd terrorysta\"\n  STR_SILACOID_TERRORIST: \"Silakoid terrorysta\"\n  STR_SECTOPOD_TERRORIST: \"Sektopod terrorysta\"\n  STR_UFO_POWER_SOURCE: \"Źródło zasilania UFO\"\n  STR_UFO_NAVIGATION: \"System nawigacyjny UFO\"\n  STR_UFO_CONSTRUCTION: \"Budowa UFO\"\n  STR_ALIEN_FOOD: \"Pokarm obcych\"\n  STR_ALIEN_REPRODUCTION: \"Reproduktor obcych\"\n  STR_ALIEN_ENTERTAINMENT: \"Sprzęt rekreacyjny obcych\"\n  STR_ALIEN_SURGERY: \"Jednostka chirurgiczna obcych\"\n  STR_EXAMINATION_ROOM: \"Laboratoria obcych\"\n  STR_ALIEN_ALLOYS: \"Obce stopy\"\n  STR_ALIEN_HABITAT: \"Środowisko obcych\"\n  STR_POWER_SUIT: \"Pancerz wspomagany\"\n  STR_FLYING_SUIT: \"Pancerz latający\"\n  STR_HWP_ROCKETS: \"Rakiety do CDS-a\"\n  STR_HWP_FUSION_BOMB: \"Bomba fuzyjna do CDS-a\"\n  STR_LASER_WEAPONS: \"Broń laserowa\"\n  STR_NEW_FIGHTER_CRAFT: \"Nowy myśliwiec\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Nowy transportowiec\"\n  STR_ULTIMATE_CRAFT: \"Statek kosmiczny\"\n  STR_LASER_PISTOL: \"Pistolet laserowy\"\n  STR_LASER_RIFLE: \"Karabin laserowy\"\n  STR_HEAVY_LASER: \"Ręczne działko laserowe\"\n  STR_LASER_CANNON: \"Działko laserowe\"\n  STR_PLASMA_CANNON: \"Działko plazmowe\"\n  STR_FUSION_MISSILE: \"Wyrzutnia fuzyjna\"\n  STR_LASER_DEFENSE: \"Obrona laserowa\"\n  STR_PLASMA_DEFENSE: \"Obrona plazmowa\"\n  STR_FUSION_DEFENSE: \"Obrona fuzyjna\"\n  STR_GRAV_SHIELD: \"Tarcza grawitacyjna\"\n  STR_MIND_SHIELD: \"Tarcza umysłowa\"\n  STR_PSI_LAB: \"Laboratorium psioniczne\"\n  STR_MOTION_SCANNER: \"Wykrywacz ruchu\"\n  STR_MEDI_KIT: \"Apteczka\"\n  STR_TANK_CANNON: \"Czołg/Działko\"\n  STR_TANK_ROCKET_LAUNCHER: \"Czołg/Wyrzutnia rakiet\"\n  STR_TANK_LASER_CANNON: \"Czołg/Działko laserowe\"\n  STR_HOVERTANK_PLASMA: \"Czołgolot/Działko plazmowe\"\n  STR_HOVERTANK_LAUNCHER: \"Czołgolot/Wyrzutnia fuzyjna\"\n  STR_STINGRAY_LAUNCHER: \"Wyrzutnia 'Trygon'\"\n  STR_AVALANCHE_LAUNCHER: \"Wyrzutnia 'Lawina'\"\n  STR_CANNON: \"Działko\"\n  STR_FUSION_BALL_LAUNCHER: \"Wyrzutnia kul fuzyjnych\"\n  STR_PLASMA_BEAM: \"Działko plazmowe\"\n  STR_STINGRAY_MISSILES: \"Rakieta 'Trygon'\"\n  STR_AVALANCHE_MISSILES: \"Rakieta 'Lawina'\"\n  STR_CANNON_ROUNDS_X50: \"Naboje działka (50 sztuk)\"\n  STR_FUSION_BALL: \"Kula fuzyjna\"\n  STR_SOLDIER: \"Żołnierz\"\n  STR_SCIENTIST: \"Naukowiec\"\n  STR_ENGINEER: \"Inżynier\"\n  STR_NORTH_AMERICA: \"Ameryka Płn.\"\n  STR_ARCTIC: \"Arktyka\"\n  STR_ANTARCTICA: \"Antarktyda\"\n  STR_SOUTH_AMERICA: \"Ameryka Płd.\"\n  STR_EUROPE: \"Europa\"\n  STR_NORTH_AFRICA: \"Afryka Północna\"\n  STR_SOUTHERN_AFRICA: \"Afryka Płd.\"\n  STR_CENTRAL_ASIA: \"Azja Środkowa\"\n  STR_SOUTH_EAST_ASIA: \"Azja Płd.-Wsch.\"\n  STR_SIBERIA: \"Syberia\"\n  STR_AUSTRALASIA: \"Australazja\"\n  STR_PACIFIC: \"Pacyfik\"\n  STR_NORTH_ATLANTIC: \"Atlantyk Płn.\"\n  STR_SOUTH_ATLANTIC: \"Atlantyk Płd.\"\n  STR_INDIAN_OCEAN: \"Ocean Indyjski\"\n  STR_ALIEN_RESEARCH: \"Badania obcych\"\n  STR_ALIEN_HARVEST: \"Żniwa obcych\"\n  STR_ALIEN_ABDUCTION: \"Porwania obcych\"\n  STR_ALIEN_INFILTRATION: \"Infiltracja obcych\"\n  STR_ALIEN_BASE: \"Baza obcych\"\n  STR_ALIEN_TERROR: \"Terror obcych\"\n  STR_ALIEN_RETALIATION: \"Odwet obcych\"\n  STR_ALIEN_SUPPLY: \"Zaopatrzenie obcych\"\n  STR_MAXIMUM_SPEED: \"Prędkość maksymalna\"\n  STR_HYPER_WAVE_DECODER_UC: \"DEKODER HIPERFAL\"\n  STR_SKYRANGER: \"DESANTOWIEC\"\n  STR_LIGHTNING: \"BŁYSKAWICA\"\n  STR_AVENGER: \"MŚCICIEL\"\n  STR_INTERCEPTOR: \"MYŚLIWIEC\"\n  STR_FIRESTORM: \"POŻOGA\"\n  STR_UFO: \"UFO\"\n  STR_STINGRAY: \"RAKIETA TRYGON\"\n  STR_AVALANCHE: \"RAKIETA LAWINA\"\n  STR_CANNON_UC: \"DZIAŁO\"\n  STR_FUSION_BALL_UC: \"WYRZUTNIA FUZYJNA\"\n  STR_LASER_CANNON_UC: \"DZIAŁO LASEROWE\"\n  STR_PLASMA_BEAM_UC: \"DZIAŁO PLAZMOWE\"\n  STR_DAMAGE_CAPACITY: \"Wytrzymałość\"\n  STR_WEAPON_POWER: \"Siła rażenia broni\"\n  STR_WEAPON_RANGE: \"Zasięg broni\"\n  STR_ACCESS_LIFT: \"Winda wejściowa\"\n  STR_LABORATORY: \"Laboratorium\"\n  STR_WORKSHOP: \"Warsztat\"\n  STR_SMALL_RADAR_SYSTEM: \"Mały system radarowy\"\n  STR_LARGE_RADAR_SYSTEM: \"Duży system radarowy\"\n  STR_MISSILE_DEFENSES: \"Obrona rakietowa\"\n  STR_GENERAL_STORES: \"Magazyny\"\n  STR_ALIEN_CONTAINMENT: \"Cele dla obcych\"\n  STR_LASER_DEFENSES: \"Obrona laserowa\"\n  STR_PLASMA_DEFENSES: \"Obrona plazmowa\"\n  STR_FUSION_BALL_DEFENSES: \"Obrona fuzyjna\"\n  STR_PSIONIC_LABORATORY: \"Laboratorium psioniczne\"\n  STR_HYPER_WAVE_DECODER: \"Dekoder hiperfal\"\n  STR_HANGAR: \"Hangar\"\n  STR_USA: \"USA\"\n  STR_RUSSIA: \"ROSJA\"\n  STR_UK: \"WIELKA BRYTANIA\"\n  STR_FRANCE: \"FRANCJA\"\n  STR_GERMANY: \"NIEMCY\"\n  STR_ITALY: \"WŁOCHY\"\n  STR_SPAIN: \"HISZPANIA\"\n  STR_CHINA: \"CHINY\"\n  STR_JAPAN: \"JAPONIA\"\n  STR_INDIA: \"INDIE\"\n  STR_BRAZIL: \"BRAZYLIA\"\n  STR_AUSTRALIA: \"AUSTRALIA\"\n  STR_NIGERIA: \"NIGERIA\"\n  STR_SOUTH_AFRICA: \"AFRYKA PŁD.\"\n  STR_EGYPT: \"EGIPT\"\n  STR_CANADA: \"KANADA\"\n  STR_TANK: \"Czołg\"\n  STR_CIVILIAN: \"Cywil\"\n  STR_JAN: \"Sty\"\n  STR_FEB: \"Lut\"\n  STR_MAR: \"Mar\"\n  STR_APR: \"Kwi\"\n  STR_MAY: \"Maj\"\n  STR_JUN: \"Cze\"\n  STR_JUL: \"Lip\"\n  STR_AUG: \"Sie\"\n  STR_SEP: \"Wrz\"\n  STR_OCT: \"Paź\"\n  STR_NOV: \"Lis\"\n  STR_DEC: \"Gru\"\n  STR_INTERNATIONAL_RELATIONS: \"Stosunki międzynarodowe\"\n  STR_COUNTRY: \"Kraj\"\n  STR_FUNDING: \"Dotacje\"\n  STR_CHANGE: \"Zmiana\"\n  STR_WEAPON_SYSTEMS: \"SYSTEMY BRONI\"\n  STR_HWPS: \"CDS-ów\"\n  STR_DAMAGE_UC_: \"USZKODZENIA: {ALT}{0}\"\n  STR_ACCESS_LIFT_UFOPEDIA: \"Winda wejściowa umożliwia dostarczanie sprzętu i personelu do lub z podziemnej bazy. Jest to zawsze pierwsza instalacja konstruowana w miejscu nowej bazy. W okolice windy mogą wtargnąć potencjalne siły wroga.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Każdy blok kwater mieści do 50 osób personelu. Instalacja zapewnia miejsce na odpoczynek, sen i spożywanie posiłków.\"\n  STR_LABORATORY_UFOPEDIA: \"W bloku laboratorium może pracować do 50 naukowców. Każde laboratorium jest wyposażone w najnowszą aparaturę do badań materiałowych, biochemicznych i kosmologicznych. Zapewniony jest też ułatwiony dostęp do najlepszych laboratoriów naukowych na całym świecie, włącznie z instytutami wojskowymi.\"\n  STR_WORKSHOP_UFOPEDIA: \"Warsztaty posiadają całe potrzebne wyposażenie służące do produkcji sprzętu zaprojektowanego lub przebadanego{NEWLINE}w laboratoriach naukowych. W warsztatach może pracować do 50 inżynierów, ale konstruowane przedmioty również wymagają trochę miejsca.\"\n  STR_SMALL_RADAR_SYSTEM_UFOPEDIA: \"Mały system radarowy ma efektywny zasięg około 550 km. Podłączony jest do systemów satelitarnych, służących wyszukiwaniu obiektów naziemnych. Każdy taki system radarowy ma 10% szans, aby wykryć obiekt średniej wielkości w ciągu 30 minut.\"\n  STR_LARGE_RADAR_SYSTEM_UFOPEDIA: \"Duży system radarowy jest efektywny w promieniu około 830 km oraz jest połączony z systemami satelitarnymi, aby wyszukiwać obiekty naziemne. Każdy taki system radarowy ma 20% szans, aby wykryć obiekt średniej wielkości w ciągu 30 minut.\"\n  STR_MISSILE_DEFENSES_UFOPEDIA: \"Obrona rakietowa stanowi jakąś ochronę przed wrogim statkiem, który próbuje lądować w pobliżu bazy.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"Cały sprzęt, broń, amunicja, zdobyte materiały i ciężkie działa samobieżne, są przechowywane w magazynach. Dotyczy to także sprzętu przydzielonego do pojazdów w hangarach.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"Cele dla obcych posiadają specjalne środowisko utrzymujące ich procesy życiowe. Instalacja ta może utrzymywać przy życiu do 10 obcych form życia przebywających w oddzielnych celach.\"\n  STR_LASER_DEFENSES_UFOPEDIA: \"Obrona laserowa zapewnia ochronę przed atakiem wrogich statków.\"\n  STR_PLASMA_DEFENSES_UFOPEDIA: \"Energia kinetyczna wiązek zjonizowanej plazmy zapewnia doskonałą ochronę przed atakiem wrogiego statku.\"\n  STR_FUSION_BALL_DEFENSES_UFOPEDIA: \"Obrona fuzyjna zapewnia najbardziej skuteczną ochronę przed atakiem obcych. Dzięki antymaterii pociski wytwarzają implozję, która niszczy wszystko w określonym promieniu.\"\n  STR_GRAV_SHIELD_UFOPEDIA: \"Tarcza grawitacyjna odpycha statek obcych próbujący lądować w pobliżu bazy wystarczająco długo, by wszystkie systemy obronne mogły wystrzelić ponownie. W praktyce podwaja to skuteczność każdego systemu obronnego bazy.\"\n  STR_MIND_SHIELD_UFOPEDIA: \"Dopóki statki obcych polegają na odbiorze fal mózgowych do wykrywania obecności ludzi (a więc i baz), najefektywniejszym środkiem zaradczym przeciw wykryciu bazy jest tłumienie fal mózgowych emitowanych przez jej personel. Ta instalacja drastycznie redukuje szansę wykrycia bazy przez statek obcych.\"\n  STR_PSIONIC_LABORATORY_UFOPEDIA: \"Laboratorium psioniczne może oszacować potencjał psioniczny żołnierzy w bazie i zapewniać im niezbędne szkolenia zwiększające ich zdolności psioniczne. Każdy blok takiego laboratorium może szkolić do 10 żołnierzy na raz. Szkoleni żołnierze są wyznaczani na początku każdego miesiąca. Zdolności psioniczne używane w połączeniu z wzmacniaczem psionicznym mogą być stosowane do ataków psionicznych podczas walki przeciwko obcym.\"\n  STR_HYPER_WAVE_DECODER_UFOPEDIA: \"Komunikacja obcych wykorzystuje fale wielowymiarowe (tzw. hiperfale), które rozchodzą się prawie natychmiastowo. To urządzenie wychwytuje transmisje UFO i je dekoduje, dzięki czemu dostarcza nam więcej informacji o wykrytym spodku - m.in. o typie UFO, rasie załogi i rodzaju ich misji.\"\n  STR_HANGAR_UFOPEDIA: \"Każdy hangar mieści jeden pojazd. Znajduje się w nim także sprzęt służący do obsługi, tankowania i naprawy pojazdów organizacji X-Com. Pojazd stacjonujący w bazie musi mieć przydzielony wolny hangar, który nie może być używany przez żaden inny pojazd, nawet jeśli pojazd, któremu przydzielono dany hangar, został wysłany na misję.\"\n  STR_PISTOL_UFOPEDIA: \"Standardowy półautomatyczny pistolet organizacji X-Com o dużej sile rażenia z 12. nabojowym magazynkiem.\"\n  STR_RIFLE_UFOPEDIA: \"Ten bardzo celny karabin szturmowy z celownikiem laserowym używa magazynka na 20 naboi o rozmiarze 6,7 mm.\"\n  STR_HEAVY_CANNON_UFOPEDIA: \"Ręczne działko (w skrócie rd) jest niszczycielską, ale nieporęczną bronią. Jego wszechstronność wynika z faktu, że może przyjmować aż trzy typy amunicji - amunicję przeciwpancerną dużego kalibru, amunicję wybuchową i zapalającą.\"\n  STR_AUTO_CANNON_UFOPEDIA: \"Ręczne działko rotacyjne (w skrócie rdr) łączy w sobie szybkostrzelność z siłą ognia i wszechstronnością ręcznego działka.\"\n  STR_ROCKET_LAUNCHER_UFOPEDIA: \"Ta wyrzutnia rakiet z laserowym naprowadzaniem potrafi strzelać trzema różnymi rodzajami rakiet.\"\n  STR_LASER_PISTOL_UFOPEDIA: \"Pistolet laserowy to efektywne zastosowanie nowej technologii. Łączy on wygodę klasycznego pistoletu ze zwiększoną szybkością i celnością oddawanych strzałów.\"\n  STR_LASER_RIFLE_UFOPEDIA: \"Karabin laserowy jest potężniejszą i celniejszą wersją wcześniejszego projektu pistoletu laserowego.\"\n  STR_HEAVY_LASER_UFOPEDIA: \"Ciężki działko laserowe jest nieporęczne, ale za to niezwykle efektywne.\"\n  STR_GRENADE_UFOPEDIA: \"Ten standardowy granat posiada dokładny i zaawansowany układ czasowy do precyzyjnej kontroli momentu zapłonu.\"\n  STR_SMOKE_GRENADE_UFOPEDIA: \"Granat dymny jest przydatny do tworzenia zasłony w przypadku walki na otwartej przestrzeni. Używaj go ostrożnie, ponieważ obcy mogą również wykorzystać tę zasłonę.\"\n  STR_PROXIMITY_GRENADE_UFOPEDIA: \"Mina może być rzucona jak zwykły granat. Jednak po upadku uaktywnia ją dopiero pobliski ruch. Używanie jej wymaga dużej wprawy i ostrożności.\"\n  STR_HIGH_EXPLOSIVE_UFOPEDIA: \"Ten materiał wybuchowy powinien być używany tylko do wyburzania. Trzymaj żołnierzy z daleka od wyburzanych obiektów.\"\n  STR_MOTION_SCANNER_UFOPEDIA: \"To nowoczesne urządzenie wykorzystuje różnorodne detektory i zaawansowane algorytmy komputerowe do wykrywania ruchu jednostek (wroga, własnych itp.). Efektywne używanie tego urządzenia wymaga jednak pewnej praktyki. Podczas misji kliknij na ikonę skanera ruchu trzymanego w ręku. Z menu wybierz 'Skanuj'. Wyświetlacz skanera pokaże w centrum strzałkę wskazującą kierunek, w którym jest zwrócona twarz żołnierza (północ będzie na górze). Pulsujące plamy będą odpowiadać jednostkom, które ostatnio się ruszały. Większe lub szybciej poruszające się jednostki wygenerują większe plamy. Nieruchome jednostki w ogóle nie zostaną wykryte.\"\n  STR_MEDI_KIT_UFOPEDIA: \"Apteczką można leczyć, znieczulać oraz stymulować. Aby jej użyć, trzeba stanąć twarzą przodem do żołnierza wymagającego leczenia. Jeśli żołnierz jest ogłuszony, trzeba stanąć dokładnie nad jego ciałem. Następnie trzeba kliknąć na ikonę apteczki i wybrać z menu 'Użyj apteczki'.{NEWLINE}{NEWLINE}LECZENIE: Części ciała z ranami śmiertelnymi będą czerwone. Kliknij na zranioną część ciała, a następnie na przycisk 'Leczenie'. Zostanie wyleczona jedna rana śmiertelna oraz przywrócone trochę punktów życia.{NEWLINE}STYMULACJA: Zwiększa wytrzymałość i ocuca nieprzytomnego (ogłuszonego) żołnierza.{NEWLINE}ZNIECZULANIE: Przywraca morale zranionego żołnierza, nie więcej jednak niż stracone przez niego punkty życia.\"\n  STR_PSI_AMP_UFOPEDIA: \"Wzmacniacz psioniczny może być używany wyłącznie przez żołnierzy z mocami psionicznymi. Podczas walki kliknij na wzmacniaczu, kursorem wybierz rodzaj, a potem obiekt ataku. Dostępne są dwa rodzaje ataku psionicznego:{NEWLINE}{NEWLINE}WYWOŁAJ PANIKĘ: Jeśli atak się powiedzie, morale celu się obniży, co może spowodować jego panikę.{NEWLINE}KONTROLA UMYSŁU: Jeśli się powiedzie, zyskasz natychmiastową kontrolę nad jednostką przeciwnika, tak jakby była Twoją własną. Ten rodzaj ataku jest trudniejszy do przeprowadzenia.\"\n  STR_STUN_ROD_UFOPEDIA: \"To urządzenie może być użyte tylko w bezpośrednim kontakcie. Wstrząsem elektrycznym ogłuszy żywy organizm bez zabijania go.\"\n  STR_MIND_PROBE_UFOPEDIA: \"Próbnik umysłu jest urządzeniem komunikacyjnym obcych, który pobiera informacje bezpośrednio z fal mózgowych, jednak jednostki organizacji X-Com mogą używać tego urządzenia w walce do wyświetlania charakterystyk obcych. Kliknij na próbniku umysłu, a potem wybierz opcję 'Użyj próbnika umysłu'. Następnie kliknij kursorem na obcego.\"\n  STR_PLASMA_PISTOL_UFOPEDIA: \"Pistolet plazmowy jest śmiercionośną bronią obcych, bazującą na przyśpieszaniu cząstek we wnętrzu słabego pola antygrawitacyjnego.\"\n  STR_PLASMA_RIFLE_UFOPEDIA: \"Jest to porażająco potężna broń bazująca na przyśpieszaniu cząstek we wnętrzu nikłego pola anty-grawitacyjnego.\"\n  STR_HEAVY_PLASMA_UFOPEDIA: \"Ta śmiercionośna broń o wielkiej sile rażenia działa na zasadzie przyspieszania cząstek w słabym polu antygrawitacyjnym.\"\n  STR_BLASTER_LAUNCHER_UFOPEDIA: \"To jest wyrzutnia rakiet kierowanych, która strzela rakietami fuzyjnymi o potężnej sile rażenia. Gdy klikniesz na wyrzutni, będziesz mógł ustalić punkty kontrolne, przez które będzie miała przelatywać rakieta fuzyjna. Jeśli jesteś pewny, że ustawiłeś wystarczającą liczbę punktów kontrolnych, kliknij na specjalną ikonę odpalenia.\"\n  STR_SMALL_LAUNCHER_UFOPEDIA: \"Mała wyrzutnia bomb ogłuszających. Idealna, by pojmać żywych obcych.\"\n  STR_ALIEN_GRENADE_UFOPEDIA: \"To urządzenie działa tak samo jak ziemski granat z wyjątkiem tego, że ma większą siłę rażenia.\"\n  STR_SMALL_SCOUT: \"Mały zwiadowca\"\n  STR_MEDIUM_SCOUT: \"Średni zwiadowca\"\n  STR_LARGE_SCOUT: \"Duży zwiadowca\"\n  STR_HARVESTER: \"Żniwiarz\"\n  STR_ABDUCTOR: \"Porywacz\"\n  STR_TERROR_SHIP: \"Terroryzer\"\n  STR_BATTLESHIP: \"Pancernik\"\n  STR_SUPPLY_SHIP: \"Zaopatrzeniowiec\"\n  STR_RATING: \"OCENA: {0}\"\n  STR_RATING_TERRIBLE: \"FATALNIE!\"\n  STR_RATING_POOR: \"NĘDZNIE!\"\n  STR_RATING_OK: \"OK\"\n  STR_RATING_GOOD: \"DOBRZE!\"\n  STR_RATING_EXCELLENT: \"ZNAKOMICIE!\"\n  STR_SCORE: \"PUNKTY\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"MIESIĘCZNY RAPORT X-COMU\"\n  STR_MONTH: \"Miesiąc: {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"Rada krajów sponsorujących projekt jest ogólnie zadowolona{NEWLINE}z Twojego dotychczasowego postępu.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"Rada krajów sponsorujących projekt jest bardzo zadowolona{NEWLINE}z Twojego znakomitego postępu. Oby tak dalej!\"\n  STR_COUNCIL_IS_DISSATISFIED: \"Rada krajów sponsorujących projekt jest niezadowolona{NEWLINE}z Twojej działalności. Musisz poprawić swoją skuteczność działań wobec zagrożenia ze strony obcych albo będzie Ci grozić zakończenie projektu.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"Nie udała Ci się obrona Ziemi przed inwazją obcych. Rada krajów sponsorujących projekt zdecydowała się niestety go zakończyć. Każdy naród będzie rozwiązywał problem na własną rękę. Możemy mieć jedynie nadzieję, że potrafimy przyzwyczaić się do oczywistych sił zbrojnych wroga oraz że powszechna ludność zżyje się z przybyszami.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} - kraj ten jest szczególnie zadowolony z Twojej zdolności do radzenia sobie z lokalnym zagrożeniem i zgodził się zwiększyć poziom finansowania.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} - kraje te są szczególnie zadowolone z Twojej zdolności do radzenia sobie z inwazją obcych na swoich terytoriach i zgodziły się zwiększyć poziom finansowania.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} i {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} - kraj ten jest niezadowolony z Twojej zdolności do radzenia sobie z działalnością obcych na jego terytorium i zdecydował się zmniejszyć poziom finansowania.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} - kraje te są szczególnie niezadowolone z efektów Twoich działań przeciw obcym na ich terytorium i postanowiły zmniejszyć poziom finansowania.\"\n  STR_KNOTS: \"{0} w.\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} - kraj ten podpisał tajny pakt z nieznanymi siłami obcych i wycofał się z projektu X-Com.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} - kraje te podpisały tajny pakt z nieznanymi siłami obcych i wycofały się z projektu X-Com.\"\n  STR_MONTHLY_RATING: \"Ocena miesięczna: {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Zmiana funduszy: {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"Rada krajów sponsorujących projekt nie jest zadowolona z Twoich wyników finansowych. Musisz zmniejszyć swoje długi poniżej jednego miliona dolarów albo projekt zostanie zakończony.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"ZDEKODOWANO TRANSMISJĘ HIPERFALOWĄ\"\n  STR_CRAFT_TYPE: \"STATEK\"\n  STR_RACE: \"RASA\"\n  STR_MISSION: \"MISJA\"\n  STR_ZONE: \"REGION\"\n  STR_ALLOCATE_RESEARCH: \"Wyznacz badania\"\n  STR_ALLOCATE_MANUFACTURE: \"Wyznacz produkcję\"\n  STR_NEW_YORK: \"Nowy Jork\"\n  STR_WASHINGTON: \"Waszyngton\"\n  STR_LOS_ANGELES: \"Los Angeles\"\n  STR_MONTREAL: \"Montreal\"\n  STR_HAVANA: \"Hawana\"\n  STR_MEXICO_CITY: \"Meksyk\"\n  STR_CHICAGO: \"Chicago\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_DALLAS: \"Dallas\"\n  STR_BRASILIA: \"Brasilia\"\n  STR_BOGOTA: \"Bogota\"\n  STR_BUENOS_AIRES: \"Buenos Aires\"\n  STR_SANTIAGO: \"Santiago\"\n  STR_RIO_DE_JANEIRO: \"Rio de Janeiro\"\n  STR_LIMA: \"Lima\"\n  STR_CARACAS: \"Caracas\"\n  STR_LONDON: \"Londyn\"\n  STR_PARIS: \"Paryż\"\n  STR_BERLIN: \"Berlin\"\n  STR_MOSCOW: \"Moskwa\"\n  STR_ROME: \"Rzym\"\n  STR_MADRID: \"Madryt\"\n  STR_BUDAPEST: \"Budapeszt\"\n  STR_LAGOS: \"Lagos\"\n  STR_CAIRO: \"Kair\"\n  STR_CASABLANCA: \"Casablanca\"\n  STR_PRETORIA: \"Pretoria\"\n  STR_NAIROBI: \"Nairobi\"\n  STR_CAPE_TOWN: \"Kapsztad\"\n  STR_KINSHASA: \"Kinszasa\"\n  STR_ANKARA: \"Ankara\"\n  STR_DELHI: \"Delhi\"\n  STR_KARACHI: \"Karaczi\"\n  STR_BAGHDAD: \"Bagdad\"\n  STR_TEHRAN: \"Teheran\"\n  STR_BOMBAY: \"Bombaj\"\n  STR_CALCUTTA: \"Kalkuta\"\n  STR_TOKYO: \"Tokio\"\n  STR_BEIJING: \"Pekin\"\n  STR_BANGKOK: \"Bangkok\"\n  STR_MANILA: \"Manila\"\n  STR_SEOUL: \"Seul\"\n  STR_SINGAPORE: \"Singapur\"\n  STR_JAKARTA: \"Dżakarta\"\n  STR_SHANGHAI: \"Szanghaj\"\n  STR_HONG_KONG: \"Hong Kong\"\n  STR_NOVOSIBIRSK: \"Nowosybirsk\"\n  STR_CANBERRA: \"Canberra\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_MELBOURNE: \"Melbourne\"\n  STR_PERTH: \"Perth\"\n  STR_PSI_TRAINING: \"Trening psioniczny\"\n  STR_PSIONIC_TRAINING: \"TRENING PSIONICZNY\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Wolnych miejsc w l.p.: {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"Siła{NEWLINE}psioniczna\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"Zdolność psioniczna{NEWLINE}/Zmiana\"\n  STR_PSI_AMP: \"Wzmacniacz psioniczny\"\n  STR_IN_TRAINING: \"W{NEWLINE}treningu?\"\n  STR_TARGETTED_BY: \"CEL NAMIERZONY PRZEZ:\"\n  STR_WEAPONS_CREW_HWPS: \"SYSTEMY BRONI/{NEWLINE}I. ZAŁOGI/CDS-ów\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"ma mało paliwa,{NEWLINE}wraca do bazy.\"\n  STR_SOLDIER_LIST: \"Lista żołnierzy\"\n  STR_RANK_: \"RANGA: {ALT}{0}\"\n  STR_MISSIONS: \"MISJI: {ALT}{0}\"\n  STR_KILLS: \"ZABITYCH: {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"CZAS KURACJI: {ALT}{0}\"\n  STR_TIME_UNITS: \"JEDNOSTKI CZASU\"\n  STR_STAMINA: \"KONDYCJA\"\n  STR_HEALTH: \"ZDROWIE\"\n  STR_BRAVERY: \"ODWAGA\"\n  STR_REACTIONS: \"REFLEKS\"\n  STR_FIRING_ACCURACY: \"CELNOŚĆ STRZAŁU\"\n  STR_THROWING_ACCURACY: \"CELNOŚĆ RZUTU\"\n  STR_STRENGTH: \"SIŁA\"\n  STR_PSIONIC_STRENGTH: \"SIŁA PSIONICZNA\"\n  STR_PSIONIC_SKILL: \"ZDOLNOŚĆ PSIONICZNA\"\n  STR_NEW_RANK: \"NOWA RANGA\"\n  STR_PROMOTIONS: \"Awanse\"\n  STR_SOLDIERS_UC: \"ŻOŁNIERZE\"\n  STR_TANK_CANNON_UFOPEDIA: \"Ciężkie działa samobieżne są przeznaczone do wsparcia oddziału organizacji X-Com. Połączenie dużej siły ognia i twardego pancerza sprawia, że jednostki te są bardzo przydatne podczas wymiany ognia na otwartym terenie. Upewnij się, że w magazynach masz wystarczającą ilość amunicji, aby uzbroić czołg. CDS-y są zawsze uzbrajane automatycznie, gdy włączasz je do załogi.\"\n  STR_TANK_ROCKET_LAUNCHER_UFOPEDIA: \"Ten czołg jest uzbrojony w potężne rakiety. Jest to groźna broń przeciwko każdemu obcemu. Jeśli chcesz ten czołg włączyć do załogi, upewnij się, że w magazynach masz wystarczającą ilość rakiet dla tego cds-a.\"\n  STR_TANK_LASER_CANNON_UFOPEDIA: \"Broń laserowa jest przydatną bronią dla cds-ów. Daje to dużą siłę ognia bez ograniczeń amunicyjnych.\"\n  STR_HOVERTANK_PLASMA_UFOPEDIA: \"Technologia obcych tchnęła w cds-y nowe życie. Dodana możliwość latania oraz siła dział plazmowych stworzyła razem niezwykle mordercze połączenie.\"\n  STR_HOVERTANK_LAUNCHER_UFOPEDIA: \"Ten czołgolot jest wyrzutnią rakiet fuzyjnych cds-a, które są niesamowicie niszczycielskie. Używaj tej broni z wielką ostrożnością. Aby w pełni uzbroić ten czołgolot, musisz mieć wyprodukowaną odpowiednią liczbę rakiet fuzyjnych dla CDS-a. By strzelić, musisz ustalić kursorem kolejne punkty kontrolne, przez które będzie przelatywać rakieta, a następnie kliknąć na specjalnej ikonie, która odpali rakietę fuzyjną CDS-a.\"\n  STR_HEAVY_PLASMA_CLIP_UFOPEDIA: \"Ten przedmiot jest używany jako amunicja dla ręcznego działka plazmowego. Zawiera niewielkie ilości eleru.\"\n  STR_PLASMA_RIFLE_CLIP_UFOPEDIA: \"Ten mały obiekt jest używany jako źródło energii dla karabinu plazmowego - broni obcych średniej mocy. Zawiera niewielkie ilości eleru.\"\n  STR_PLASMA_PISTOL_CLIP_UFOPEDIA: \"Źródło energii dla małego pistoletu plazmowego obcych. Zawiera eler - źródło wszelakiej energii dla urządzeń, które wykorzystują technologię obcych w mniejszym bądź większym stopniu.\"\n  STR_STUN_BOMB_UFOPEDIA: \"Bomba ogłuszająca jest wykorzystywana do chwytania żywych okazów ludzi, ale jak najbardziej może być używana przeciwko różnym rasom obcych. Jest wystrzeliwana z wyrzutni bomb ogłuszających.\"\n  STR_ALIEN_RESEARCH_UFOPEDIA: \"Misje naukowe obcych mają na celu zbieranie podstawowych danych o Ziemi i jej mieszkańcach. Do tego celu są używane przeważnie małe statki, które sporadycznie lądują na opustoszałych terenach. Ten typ aktywności obcych stwarza najmniejsze niebezpieczeństwo dla organizacji X-Com, ale trochę niepokoi rządy i ludność.\"\n  STR_ALIEN_HARVEST_UFOPEDIA: \"Obcy wykorzystują ziemską faunę na wiele sposobów. Zwierzęta są dyskretnie porywane, a następnie zwracane z usuniętymi różnymi narządami. Okaleczenia bydła są przeważnie zgłaszane łącznie z obserwacją UFO. Ten typ aktywności budzi duży niepokój rządów i grozę wśród ludności. Lądowania UFO zdarzają się głównie w pobliżu gospodarstw rolnych. Tak zwana teoria 'żniw obcych' mówi, że rasy obcych pierwotnie pojawiły się na planecie pozbawionej flory i fauny, a teraz powróciły, by zbierać żniwo z tego, co niegdyś zasiały.\"\n  STR_ALIEN_ABDUCTION_UFOPEDIA: \"Jest to najbardziej złowroga forma aktywności obcych. Porwania prowadzone przez obcych są często zgłaszane, mimo że obcy usiłują wymazywać z pamięci ofiar przeżycia związane z porwaniami. Porywanie istot ludzkich ma na celu zbadanie fizjologii człowieka, impregnowanie płodów obcych oraz przeprowadzanie dziwacznych eksperymentów genetycznych. Celem tej aktywności wydają się genetyczne mutacje i hodowanie nowych krzyżówek obcych. Takie zachowanie obcych jest powodem podnoszonego alarmu zdarzającego się na terenach zaludnionych, np, w miastach.\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"Rządy Ziemi mogą być infiltrowane przez szpiegów obcych, z wyglądu nieodróżnialnych od ludzi. Może to doprowadzić do oficjalnego spotkania na najwyższym szczeblu pomiędzy rządami, a obcymi. Charakterystyczne dla szczytu tej aktywności jest częste pojawianie się UFO w okolicy ważniejszych miast. Obcy będą próbowali podpisać z ziemskim rządem pakt, oferując wiedzę o ich wyższej technologii. W zamian rząd nie będzie przeszkadzał obcym w ich poczynaniach. Tego typu misje obcych to największa groźba dla organizacji X-Com. Jeśli rząd zgodzi się podpisać pakt, wówczas wycofa się z finansowania projektu X-Com.\"\n  STR_ALIEN_BASE_UFOPEDIA: \"Obcy budują tajne podziemne bazy w odległych, niezaludnionych miejscach. Po wstępnym rozpoznaniu lotniczym następuje intensyfikacja lotów UFO w miejscu budowanej bazy. O ile nam wiadomo, bazy te zawierają laboratoria do przeprowadzania eksperymentów na porwanych ludziach oraz sprzęt potrzebny do przyszłych misji przeprowadzanych w rejonie. Obecność bazy obcych wywołuje dużą liczbę doniesień o aktywności obcych, ale bez zauważonych UFO. W takiej sytuacji, aby zlokalizować bazę, pojazd organizacji X-Com musi patrolować teren przez kilka godzin, by zwiększyć szansę wykrycia.\"\n  STR_ALIEN_TERROR_UFOPEDIA: \"Gdy obcy terroryzują miasto, rozmieszczają specjalne siły zbrojne z bronią wzbudzającą zarówno podziw, jak i lęk. Cywile są zastraszani bezpośrednio, a rządy z całego rejonu zostają zmuszane do ewakuacji. Głównym celem tej aktywności jest wywołanie dostatecznej publicznej histerii, by rządy zaprzestały finansowania projektu X-Com.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"Jeśli pojazdy X-Comu będą szczególnie często zestrzeliwać UFO, wtedy obcy mogą podjąć akcję odwetową. Wynikiem tego może być bezpośredni atak na bazę X-Comu. Jednak obcy muszą ją najpierw znaleźć, by móc zaatakować, więc jeśli patrolujące UFO będą trzymane z dala od bazy, wówczas prawdopodobieństwo ataku będzie minimalne.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"Gdy tylko baza obcych zostanie skonstruowana, będzie regularnie zaopatrywana przez specjalny statek zaopatrzeniowy. Gdy jeden z takich statków zostanie wykryty podczas przebywania na ziemi, wtedy jest pewne, że baza obcych znajduje się w pobliżu tego miejsca.\"\n  STR_SMALL_SCOUT_UFOPEDIA: \"To maleńkie UFO jest wykorzystywane przede wszystkim do rozpoznawania i poszukiwań. Zazwyczaj poprzedza ono większe UFO wykonujące misje obcych.\"\n  STR_MEDIUM_SCOUT_UFOPEDIA: \"Średni statek zwiadowczy niegroźny dla sił naziemnych. Zwykle pojawia się przed większymi statkami wykonującymi misję.\"\n  STR_LARGE_SCOUT_UFOPEDIA: \"Największy statek zwiadowczy obcych jest statkiem ogólnego przeznaczenia, używanym we wszystkich typach misji obcych.\"\n  STR_HARVESTER_UFOPEDIA: \"Żniwiarka ma w podstawie otwieraną podłogę oraz jest wyposażona w podnośnik do wciągania bydła lub innych zwierząt. Noże laserowe są używane do wycinania żądanych narządów. Padlina jest zrzucana na ziemię. UFO zawiera również pojemniki do przechowywania części ciał.\"\n  STR_ABDUCTOR_UFOPEDIA: \"Statek ten jest wyposażony w laboratorium do dokonywania przerażających eksperymentów na schwytanych ludziach. Normalnie ofiara jest paraliżowana siłą telepatyczną, lecz pozostaje świadoma na stole operacyjnym.\"\n  STR_TERROR_SHIP_UFOPEDIA: \"Terroryzer ma ładownię dla dużej ilości terrorystycznych stworów i broni obcych. Służy do transportowania terrorystów na zaludnione tereny.\"\n  STR_BATTLESHIP_UFOPEDIA: \"Pancernik jest największym i najlepiej uzbrojonym statkiem obcych. Jest podstawowym rodzajem UFO wchodzącym w skład każdej misji. Posiada liczną załogę i jest wyposażony w broń o dalekim zasięgu i dużej sile rażenia.\"\n  STR_SUPPLY_SHIP_UFOPEDIA: \"Statek zaopatrzeniowy jest używany podczas konstruowania baz obcych lub zaopatrywania już istniejących. Przenosi pojemniki z żywnością obcych oraz komory reprodukcyjne.\"\n  STR_DISMANTLE: \"Rozbierz\"\n  STR_FACILITY_IN_USE: \"INSTALACJA W UŻYCIU\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"NIE MOŻNA ROZEBRAĆ INSTALACJI!{SMALLLINE}Wszystkie instalacje bazy muszą mieć połączenie z windą wejściową.\"\n  STR_TRANSFER_ITEMS_TO: \"Cel transferu: {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"BRAK MIEJSCA DLA PRZENOSZONYCH OBCYCH!{SMALLLINE}Żywi obcy potrzebują pomieszczeń, w których mogą przeżyć.\"\n  STR_AMOUNT_AT_DESTINATION: \"SZTUK NA{NEWLINE}MIEJSCU\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"Obcy zmarli, ponieważ nie zbudowałeś celi dla obcych\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"BRAK WOLNYCH KWATER!{SMALLLINE}W bazie docelowej brak wolnych kwater dla załogi pojazdu.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"NIEWYSTARCZAJĄCA ILOŚĆ MIEJSCA!{SMALLLINE}W bazie docelowej nie ma dość przestrzeni magazynowej na wyposażenie przypisane pojazdowi.\"\n  STR_ITEMS_ARRIVING: \"Dostarczone przedmioty\"\n  STR_DESTINATION_UC: \"DOSTARCZONO DO:\"\n  STR_PISTOL: \"Pistolet\"\n  STR_PISTOL_CLIP: \"Magazynek pistoletu\"\n  STR_RIFLE: \"Karabin szturmowy\"\n  STR_RIFLE_CLIP: \"Magazynek karabinu\"\n  STR_HEAVY_CANNON: \"Ręczne działko\"\n  STR_HC_AP_AMMO: \"Amunicja przeciwpancerna RD\"\n  STR_HC_HE_AMMO: \"Amunicja wybuchowa RD\"\n  STR_HC_I_AMMO: \"Amunicja zapalająca RD\"\n  STR_AUTO_CANNON: \"Ręczne działko rotacyjne\"\n  STR_AC_AP_AMMO: \"Amunicja przeciwpancerna RDR\"\n  STR_AC_HE_AMMO: \"Amunicja wybuchowa RDR\"\n  STR_AC_I_AMMO: \"Amunicja zapalająca RDR\"\n  STR_ROCKET_LAUNCHER: \"Wyrzutnia rakiet\"\n  STR_SMALL_ROCKET: \"Rakieta mała\"\n  STR_LARGE_ROCKET: \"Rakieta duża\"\n  STR_INCENDIARY_ROCKET: \"Rakieta zapalająca\"\n  STR_GRENADE: \"Granat\"\n  STR_SMOKE_GRENADE: \"Granat dymny\"\n  STR_PROXIMITY_GRENADE: \"Granat zbliżeniowy\"\n  STR_HIGH_EXPLOSIVE: \"Ładunek wybuchowy\"\n  STR_STUN_ROD: \"Paralizator\"\n  STR_HEAVY_PLASMA: \"Ręczne działko plazmowe\"\n  STR_HEAVY_PLASMA_CLIP: \"Magazynek ręcznego działka plazmowego\"\n  STR_PLASMA_RIFLE: \"Karabin plazmowy\"\n  STR_PLASMA_RIFLE_CLIP: \"Magazynek karabinu plazmowego\"\n  STR_PLASMA_PISTOL: \"Pistolet plazmowy\"\n  STR_PLASMA_PISTOL_CLIP: \"Magazynek pistoletu plazmowego\"\n  STR_BLASTER_LAUNCHER: \"Wyrzutnia rakiet fuzyjnych\"\n  STR_BLASTER_BOMB: \"Rakieta fuzyjna\"\n  STR_SMALL_LAUNCHER: \"Wyrzutnia bomb ogłuszających\"\n  STR_STUN_BOMB: \"Bomba ogłuszająca\"\n  STR_ALIEN_GRENADE: \"Granat obcych\"\n  STR_ELERIUM_115: \"Eler-115\"\n  STR_MIND_PROBE: \"Próbnik umysłu\"\n  STR_SECTOID_CORPSE: \"Zwłoki sektoida\"\n  STR_SNAKEMAN_CORPSE: \"Zwłoki wężownika\"\n  STR_ETHEREAL_CORPSE: \"Zwłoki eterianina\"\n  STR_MUTON_CORPSE: \"Zwłoki mutona\"\n  STR_FLOATER_CORPSE: \"Zwłoki lewitona\"\n  STR_CELATID_CORPSE: \"Zwłoki celatyda\"\n  STR_SILACOID_CORPSE: \"Zwłoki silakoida\"\n  STR_CHRYSSALID_CORPSE: \"Zwłoki kryzalida\"\n  STR_REAPER_CORPSE: \"Zwłoki żeńca\"\n  STR_SECTOPOD_CORPSE: \"Wrak sektopoda\"\n  STR_CYBERDISC_CORPSE: \"Wrak cyber-dysku\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"Za mało amunicji do uzbrojenia CDS-a{SMALLLINE}Każdy CDS wymaga {0} {1}.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Za mało sprzętu, by w pełni uzbroić oddział.\"\n  STR_MARS_CYDONIA_LANDING: \"Mars: Lądowanie w Cydonii\"\n  STR_MARS_CYDONIA_LANDING_BRIEFING: \"Twój Mściciel wylądował na powierzchni Marsa w terenie Cydonii. Nasze informacje wskazują na to, że jedna z piramidalnych konstrukcji zawiera zieloną windę stanowiącą wejście do podziemnego kompleksu. Gdy zgromadzisz wszystkich swoich żołnierzy na zielonych obszarach, kliknij na ikonę 'Przerwij misję', aby uruchomić windy i dostać się do podziemi.\"\n  STR_MARS_THE_FINAL_ASSAULT: \"Mars: Szturm ostateczny\"\n  STR_MARS_THE_FINAL_ASSAULT_BRIEFING: \"Windy piramid zabrały twoich znużonych walką żołnierzy głęboko pod powierzchnię planety. Żołnierze dotarli do serca wielkiego kompleksu tuneli i sal. 'Mózg' obcych jest ukryty gdzieś w labiryncie. Musi zostać zniszczony, jeśli Ziemia ma być uratowana przed zniewoleniem ze strony obcych.{NEWLINE}{NEWLINE}Życzymy powodzenia!\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Musisz zbadać{NEWLINE}{0}{NEWLINE}by móc produkować:{NEWLINE}{1}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"Obcy zniszczyli niebronioną bazę '{0}'\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"Twoi agenci zlokalizowali bazę obcych w regionie: {0}\"\n  STR_STANDOFF: \"ŚLEDZENIE\"\n  STR_CAUTIOUS_ATTACK: \"ATAK OSTROŻNY\"\n  STR_STANDARD_ATTACK: \"ATAK STANDARDOWY\"\n  STR_AGGRESSIVE_ATTACK: \"ATAK AGRESYWNY\"\n  STR_DISENGAGING: \"ZAWRACANIE\"\n  STR_UFO_HIT: \"UFO TRAFIONE!\"\n  STR_UFO_CRASH_LANDS: \"UFO ZESTRZELONE!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Minimalizuj tylko podczas śledzenia\"\n  STR_UFO_RETURN_FIRE: \"UFO ODPOWIADA OGNIEM!\"\n  STR_INTERCEPTOR_DAMAGED: \">>> POJAZD USZKODZONY <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> POJAZD ZNISZCZONY <<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"UFO UCIEKA Z WALKI!\"\n  STR_ALIENS_TERRORISE: \"TERROR OBCYCH\"\n  STR_LONG_RANGE_DETECTION: \"Daleki zasięg wykrycia\"\n  STR_STORES_UC: \"MAGAZYNY\"\n  STR_DIFFICULTY_LEVEL: \"Poziom trudności\"\n  STR_INTERCEPT: \"PRZECHWYTYWANIE\"\n  STR_BASES: \"BAZY\"\n  STR_GRAPHS: \"WYKRESY\"\n  STR_UFOPAEDIA_UC: \"UFOPEDIA\"\n  STR_OPTIONS_UC: \"OPCJE\"\n  STR_FUNDING_UC: \"BUDŻET\"\n  STR_5_SECONDS: \"5 s\"\n  STR_1_MINUTE: \"1 min.\"\n  STR_5_MINUTES: \"5 min.\"\n  STR_30_MINUTES: \"30 min.\"\n  STR_1_HOUR: \"1 godz.\"\n  STR_1_DAY: \"1 dzień\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"Lista działaczy organizacji X-Com\"\n  STR_ENTER_NAME: \"Wprowadź nazwę\"\n  STR_PERFORMANCE_RATING: \"Ocena działalności\"\n  STR_VICTORY_DATE: \"Dzień zwycięstwa\"\n  STR_ELECTRO_FLARE: \"Elektroflara\"\n  STR_ELECTRO_FLARE_UFOPEDIA: \"To małe urządzenie po rzuceniu na ziemię zaczyna emitować bardzo jaskrawe światło. Podczas misji nocnych może to spowodować oświetlenie jednostek wroga będących w pobliżu elektroflary, przez co staną się widoczne.\"\n  STR_MONTHLY_COSTS: \"KOSZTY MIESIĘCZNE\"\n  STR_CRAFT_RENTAL: \"Dzierżawa pojazdów\"\n  STR_SALARIES: \"Wypłaty\"\n  STR_BASE_MAINTENANCE: \"Utrzymanie bazy\"\n  STR_COST_PER_UNIT: \"Koszt za sztukę\"\n  STR_QUANTITY: \"Sztuk\"\n  STR_TOTAL: \"Razem\"\n  STR_IN_PSIONIC_TRAINING: \"Na treningu psionicznym\"\n  STR_BLASTER_BOMB_UFOPEDIA: \"To urządzenie jest silnie wybuchową rakietą z inteligentnym systemem naprowadzania. Jest wystrzeliwana z wyrzutni rakiet fuzyjnych.\"\n  STR_FRONT_ARMOR: \"Pancerz przedni\"\n  STR_LEFT_ARMOR: \"Pancerz lewy\"\n  STR_RIGHT_ARMOR: \"Pancerz prawy\"\n  STR_REAR_ARMOR: \"Pancerz tylny\"\n  STR_UNDER_ARMOR: \"Pancerz dolny\"\n  STR_ROUNDS: \"Naboi\"\n  STR_UNIT: \"JEDNOSTKA: {0}\"\n  STR_ENERGY: \"ENERGIA\"\n  STR_MORALE: \"MORALE\"\n  STR_ARMOR_: \"PANCERZ: {0}\"\n  STR_FRONT_ARMOR_UC: \"PANCERZ PRZEDNI\"\n  STR_LEFT_ARMOR_UC: \"PANCERZ LEWY\"\n  STR_RIGHT_ARMOR_UC: \"PANCERZ PRAWY\"\n  STR_REAR_ARMOR_UC: \"PANCERZ TYLNY\"\n  STR_SKILLS: \"ZDOLNOŚCI: {0}\"\n  STR_LEVEL: \"POZIOM: {0}\"\n  STR_HEAD: \"GŁOWA\"\n  STR_TORSO: \"TUŁÓW\"\n  STR_RIGHT_ARM: \"PRAWA RĘKA\"\n  STR_LEFT_ARM: \"LEWA RĘKA\"\n  STR_RIGHT_LEG: \"PRAWA NOGA\"\n  STR_LEFT_LEG: \"LEWA NOGA\"\n  STR_PAIN_KILLER: \"ZNIECZULENIE\"\n  STR_STIMULANT: \"STYMULACJA\"\n  STR_HEAL: \"LECZENIE\"\n  STR_TIME_UNITS_SHORT: \"JC: {ALT}{0}\"\n  STR_WEIGHT: \"Waga: {ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"Refl.: {ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"Zd. Psi: {ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"Siła Psi: {ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Artefakt obcych\"\n  STR_AMMO_ROUNDS_LEFT: \"AMUNICJA:{NEWLINE}ZOSTAŁO{NEWLINE}NABOI: {ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Znie.: {ALT}{0}{ALT}{NEWLINE}Stym.: {ALT}{1}{ALT}{NEWLINE}Lecz.: {ALT}{2}\"\n  STR_THROW: \"Rzuć\"\n  STR_AUTO_SHOT: \"Strzał serią\"\n  STR_SNAP_SHOT: \"Strzał szybki\"\n  STR_AIMED_SHOT: \"Strzał mierzony\"\n  STR_STUN: \"Ogłusz\"\n  STR_PRIME_GRENADE: \"Odbezpiecz granat\"\n  STR_USE_SCANNER: \"Użyj skanera ruchu\"\n  STR_USE_MEDI_KIT: \"Użyj apteczki\"\n  STR_LAUNCH_MISSILE: \"Odpal rakietę\"\n  STR_ACCURACY_SHORT: \"Cel.: {ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Za mało Jednostek Czasu!\"\n  STR_NOT_ENOUGH_ENERGY: \"Za mało energii!\"\n  STR_NO_ROUNDS_LEFT: \"Brak naboi!\"\n  STR_NO_AMMUNITION_LOADED: \"Nie załadowano amunicji!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Niewłaściwa amunicja do tej broni!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"Broń jest już załadowana!\"\n  STR_NO_LINE_OF_FIRE: \"Brak linii strzału!\"\n  STR_GRENADE_IS_ACTIVATED: \"Granat odbezpieczony!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Granat zabezpieczony!\"\n  STR_THERE_IS_NO_ONE_THERE: \"Nie ma tam nikogo!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Musisz przebadać ten artefakt obcych, by móc go używać!\"\n  STR_OUT_OF_RANGE: \"Poza zasięgiem!\"\n  STR_UNABLE_TO_THROW_HERE: \"Nie można tutaj rzucić!\"\n  STR_SET_TIMER: \"Ustaw stoper na\"\n  STR_HIDDEN_MOVEMENT: \"RUCH UKRYTY\"\n  STR_TURN: \"TURA: {0}\"\n  STR_SIDE: \"STRONA: {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Naciśnij dowolny klawisz, by kontynuować\"\n  STR_MIND_CONTROL: \"Kontrola umysłu\"\n  STR_PANIC_UNIT: \"Wywołaj panikę\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Morale obcego zostały osłabione\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Kontrola umysłu pomyślna\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}wpadł w szał\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}wpadła w szał\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}spanikował\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}spanikowała\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Obcy\"\n  STR_RIGHT_HAND: \"PRAWA DŁOŃ\"\n  STR_LEFT_HAND: \"LEWA DŁOŃ\"\n  STR_RIGHT_SHOULDER: \"PRAWE RAMIĘ\"\n  STR_LEFT_SHOULDER: \"LEWE RAMIĘ\"\n  STR_BACK_PACK: \"PLECAK\"\n  STR_BELT: \"PAS\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}jest pod kontrolą obcych\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}jest pod kontrolą obcych\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}jest nieprzytomny\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}jest nieprzytomna\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}zmarł od ran śmiertelnych\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}zmarła od ran śmiertelnych\"\n  STR_USE_MIND_PROBE: \"Użyj próbnika umysłu\"\n  STR_FATAL_WOUNDS: \"RANY ŚMIERTELNE\"\n  STR_UNDER_ARMOR_UC: \"PANCERZ DOLNY\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"JC zarezerwowano dla strzału pojedynczego\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"JC zarezerwowano dla strzału serią\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"JC zarezerwowano dla strzału celowanego\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"JC zarezerwowano na klęknięcie\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"JC zarezerwowano na klęknięcie i ostrzał\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} jednostka w pojeździe X-Com\"\n    few: \"{N} jednostki w pojeździe X-Com\"\n    many: \"{N} jednostek w pojeździe X-Com\"\n    other: \"{N} jednostek w pojeździe X-Com\"\n  STR_UNITS_OUTSIDE:\n    one: \"{N} jednostka pozostawiona na zewnątrz\"\n    few: \"{N} jednostki pozostawione na zewnątrz\"\n    many: \"{N} jednostek pozostawionych na zewnątrz\"\n    other: \"{N} jednostki pozostawione na zewnątrz\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} jednostka stojąca w wejściu\"\n    few: \"{N} jednostek stojących w wejściu\"\n    many: \"{N} jednostki stojące w wejściu\"\n    other: \"{N} jednostki stojące w wejściu\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} jednostka w docelowym wyjściu\"\n    few: \"{N} jednostek w docelowym wyjściu\"\n    many: \"{N} jednostki w docelowym wyjściu\"\n    other: \"{N} jednostki w docelowym wyjściu\"\n  STR_ABORT_MISSION_QUESTION: \"Przerwać misję?\"\n  STR_CORPSE: \"Zwłoki\"\n  STR_UNLOAD_CRAFT: \"Rozładuj\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}został zabity\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}została zabita\"\n  STR_HIT_MELEE: \"Cios\"\n  STR_GROUND: \"NA ZIEMI\"\n  STR_LIVING_QUARTERS_PLURAL: \"Kwatery mieszkalne\"\n  STR_LIST_ITEM: \"PRZEDMIOT\"\n  STR_PERSONAL_ARMOR_UFOPEDIA: \"Ten nowy pancerz, wykorzystujący nowo odkryte stopy metali obcych, daje naszym ludziom większe szanse w walce przeciwko zagrożeniu ze strony obcych.\"\n  STR_POWER_SUIT_UFOPEDIA: \"Nowa potężna ochrona dla żołnierzy. Ten pancerz jest zasilany elerowym źródłem energii, co znacznie podnosi szybkość i siłę osoby, która go nosi. Oferuje najlepszą obecnie dostępną ochronę oddziałom bojowym.\"\n  STR_FLYING_SUIT_UFOPEDIA: \"Ulepszona wersja pancerza wspomaganego, wykorzystująca technologię nawigacji anty-grawitacyjnej. Pozwala ona na pełną swobodę poruszania się na polu bitwy.\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"Wszyscy obcy zginęli, więc{NEWLINE}pozostałości przejęto automatycznie\"\n  STR_RESET: \"Resetowanie\"\n  STR_MEMORIAL: \"Tablica poległych\"\n  STR_DATE_UC: \"DATA\"\n  STR_SOLDIERS_RECRUITED_UC: \"ZATRUDNIENI ŻOŁNIERZE>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"UTRACENI ŻOŁNIERZE>{ALT}{0}\"\n  MAP_CULTA: \"Farma\"\n  MAP_FOREST: \"Zalesiony\"\n  MAP_JUNGLE: \"Dżungla\"\n  MAP_MOUNT: \"Górzysty\"\n  MAP_DESERT: \"Pustynny\"\n  MAP_POLAR: \"Polarny\"\n  MAP_URBAN: \"Miejski\"\n  MAP_UBASE: \"Baza obcych\"\n  MAP_XBASE: \"Baza X-Comu\"\n  MAP_MARS: \"Mars\"\n  STR_MIXED: \"Mieszany\"\n  STR_REMOVE_SELECTED: \"Usuń zaznaczone\"\n  STR_LIVE_ALIENS: \"Żywe{NEWLINE}gatunki\"\n  STR_DEAD_ALIENS: \"Odrzucone{NEWLINE}gatunki\"\n  STR_UNDER_INTERROGATION: \"W{NEWLINE}badaniach\"\n  STR_CONTAINMENT_EXCEEDED: \"LIMIT CEL DLA OBCYCH PRZEKROCZONY!{SMALLLINE}Brak miejsca w celi w bazie {0}. Musisz usunąć z cel nadmiar obcych, gdyż następni będą umierać.\"\n  STR_MANAGE_CONTAINMENT: \"Zarządzanie celami dla obcych\"\n  STR_STORAGE_EXCEEDED: \"PRZESTRZEŃ MAGAZYNOWA PRZEPEŁNIONA!{SMALLLINE}Niewystarczająca ilość miejsca w magazynach bazy {0}. Musisz sprzedać nadwyżkę stanu magazynowego.\"\n  STR_GO_TO_BASE: \"Wejdź do bazy\"\n  STR_MELEE_ACCURACY: \"WALKA WRĘCZ\"\n  STR_SELL_PRODUCTION: \"SPRZEDAJ\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Obie dłonie muszą być puste!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Za mało przedmiotów, aby stworzyć szablon!\"\n  STR_UNLOAD_WEAPON: \"Rozładuj broń\"\n  STR_ALL_ITEMS: \"Wszystkie przedmioty\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"BRAK MIEJSCA NA POKŁADZIE!{SMALLLINE}Możesz załadować najwyżej {N} przedmiot na ten pojazd.\"\n    few: \"BRAK MIEJSCA NA POKŁADZIE!{SMALLLINE}Możesz załadować najwyżej {N} przedmioty na ten pojazd.\"\n    many: \"BRAK MIEJSCA NA POKŁADZIE!{SMALLLINE}Możesz załadować najwyżej {N} przedmiotów na ten pojazd.\"\n    other: \"BRAK MIEJSCA NA POKŁADZIE!{SMALLLINE}Możesz załadować najwyżej {N} przedmiotów na ten pojazd.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}CENTRUM KONTROLI ZNISZCZONE{NEWLINE}Skieruj wszystkich żołnierzy do wyjścia i kliknij przycisk 'Przerwij misję'.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"Bazy X-Comu nie mogą być budowane pod wodą.\"\n  STR_LEVEL_SHORT: \"{0}\"\n  STR_PERSONNEL: \"Personel\"\n  STR_CRAFT_ARMAMENT: \"Pojazdy i uzbrojenie\"\n  STR_COMPONENTS: \"Komponenty\"\n  STR_SOLDIERS_RECRUITED: \"Zatrudnieni żołnierze\"\n  STR_SOLDIERS_LOST: \"Utraceni żołnierze\"\n  STR_TOTAL_UFOS: \"Wykrytych UFO\"\n  STR_TOTAL_ALIEN_BASES: \"Odkrytych baz obcych\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"SPS\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"UPS\"\n  FEMALE_CIVILIAN: \"Cywil, kobieta\"\n  MALE_CIVILIAN: \"Cywil, mężczyzna\"\n  CYBERDISC_WEAPON: \"Broń cyberdysku\"\n  REAPER_WEAPON: \"Atak żeńca\"\n  CHRYSSALID_WEAPON: \"Atak krysalida\"\n  CELATID_WEAPON: \"Atak celatyda\"\n  SILACOID_WEAPON: \"Atak silakoida\"\n  SECTOPOD_WEAPON: \"Broń sektopoda\"\n  ZOMBIE_WEAPON: \"Atak zombiego\"\n  ALIEN_PSI_WEAPON: \"Atak psi obcych\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/pt-BR.yml",
    "content": "pt-BR:\n  STR_AVENGER_UFOPEDIA: \"AERONAVE DE TRANSPORTE E COMBATE. A RÉPLICA SUPREMA DA TECNOLOGIA ALIENÍGENA.\"\n  STR_INTERCEPTOR_UFOPEDIA: \"AERONAVE DE COMBATE COM MOTORES DE DETONAÇÃO DE PULSO DUPLOS E SISTEMAS ELETRÔNICOS ESPECIALMENTE BLINDADOS. A MELHOR TECNOLOGIA DISPONÍVEL NA TERRA.\"\n  STR_LIGHTNING_UFOPEDIA: \"NAVE DE TRANSPORTE E COMBATE. UMA RÉPLICA CRUA MAS EFICAZ DOS SISTEMAS DE PROPULSÃO ALIENÍGENA.\"\n  STR_SKYRANGER_UFOPEDIA: \"TRANSPORTADOR DE TROPAS. O MAIS RÁPIDO DO SEU TIPO, COM CAPACIDADE DE DECOLAGEM E ATERRISSAGEM VERTICAL (D.A.V.).\"\n  STR_FIRESTORM_UFOPEDIA: \"NAVE DE COMBATE. ESTE COMBATENTE DE UM HOMEM SÓ REPRODUZ O FORMATO CLÁSSICO DO DISCO VOADOR ALIENÍGENA, COM UMA UNIDADE DE PROPULSÃO CENTRAL.\"\n  STR_STINGRAY_UFOPEDIA: \"AVANÇADO MÍSSIL AR-AR COM ELETRÔNICA ESPECIALMENTE BLINDADA.\"\n  STR_AVALANCHE_UFOPEDIA: \"MÍSSIL AR-AR COM OGIVA NUCLEAR, MAS EXTREMAMENTE PESADO.\"\n  STR_CANNON_UFOPEDIA: \"CANHÃO DE ALTA POTÊNCIA QUE DISPARA MUNIÇÃO PERFURANTE CAPAZ DE PENETRAR 40CM DE AÇO.\"\n  STR_FUSION_BALL_UFOPEDIA: \"ESTE LANÇADOR DISPARA UM MÍSSIL EM FORMATO DE BOLA ENERGIZADO POR UMA REAÇÃO ANTIMATÉRIA. A BOLA DESTRÓI O ALVO COM UMA IMPLOSÃO DE ONDAS GRAVITACIONAIS.\"\n  STR_LASER_CANNON_UFOPEDIA: \"ESTE RAIO LASER CONVENCIONAL É ALIMENTADO POR UMA CÂMARA DE REAÇÃO DE ANTIMATÉRIA.\"\n  STR_PLASMA_BEAM_UFOPEDIA: \"O FEIXE GRAVITACIONAL É DIRECIONADO DE FORMA CONCENTRADA, IMPLODINDO O CAMPO GRAVITACIONAL.\"\n  STR_SECTOID_UFOPEDIA: \"A hierarquia Sectoide varia de soldados a líderes com poderosas habilidades psiônicas. Esses poderes psiônicos podem ser utilizados para desmoralizar os soldados em combate, ou até mesmo assumir o controle de suas mentes. Eles tendem a se satisfazer com abduções humanas e mutilação de gado. A abdução é usada para extrair o material genético para reprodução cruzada e para desenvolver clones para infiltração na sociedade humana. O gado fornece tanto nutrição quanto material genético. Esta raça parece querer desenvolver híbridos genéticos superiores para aumentar a eficiência de sua sociedade tipo colmeia.\"\n  STR_SECTOID_AUTOPSY: \"Autópsia de Sectoide\"\n  STR_SECTOID_AUTOPSY_UFOPEDIA: \"A autópsia revela vestígios de órgãos digestivos e uma estrutura simples. O cérebro e os olhos são muito bem desenvolvidos. A estrutura sugere alteração genética ou mutação. A pequena boca e nariz parecem ter pouca função. A membrana entre os dedos das mãos e os pés chatos sugerem origens aquáticas. Não há órgãos reprodutivos, e nenhuma pista de como essa espécie pode se reproduzir. Eles são provavelmente uma espécie geneticamente modificada.\"\n  STR_SNAKEMAN_UFOPEDIA: \"Esta raça desenvolveu-se em um ambiente extremamente hostil. Eles são extremamente resistentes e podem resistir a variações extremas de temperatura. Sua mobilidade depende de um 'pé' gigante que lembra uma cobra o qual protege todos os órgãos vitais. Seus objetivos parecem ser puramente predatórios e eles aparentam estar sob o comando de alguma outra inteligência que dirige suas incursões de estilo militar na Terra.\"\n  STR_SNAKEMAN_AUTOPSY: \"Autópsia de Homem-Cobra\"\n  STR_SNAKEMAN_AUTOPSY_UFOPEDIA: \"A pele é extremamente rígida e resistente ao calor. O sistema cardiovascular é parte do sistema muscular, que utiliza o princípio hidráulico para criar movimento. O único músculo verdadeiro é o 'coração'. O sistema reprodutivo parece ser muito eficiente. A reprodução é assexuada, com cada homem-cobra transportando até cinquenta ovos dentro de seu corpo a qualquer momento. A propagação desta espécie no nosso planeta poderia ser uma séria ameaça para toda a vida na Terra.\"\n  STR_ETHEREAL_UFOPEDIA: \"Este ser tem poderes mentais impressionantes que permitem a comunicação telepática e telecinese. As capacidades físicas aparentemente fracas desta criatura são compensadas por seus poderes mentais. Nós não entendemos como esses poderes telecinéticos trabalham, uma vez que parecem desafiar as leis da física como as conhecemos. Eles são extremamente perigosos em qualquer situação de combate, onde eles dependem de seus poderes mentais. Eles raramente aparecem na Terra já que aparentam contar com outras raças para alcançar seus objetivos.\"\n  STR_ETHEREAL_AUTOPSY: \"Autópsia de Etéreo\"\n  STR_ETHEREAL_AUTOPSY_UFOPEDIA: \"O ser é fisicamente fraco e parece ser incapaz de manter qualquer função vital.  Os músculos são extremamente atrofiados e os órgãos internos subdesenvolvidos. Os órgãos sensoriais, incluindo os olhos, aparentam não funcionar de modo algum. No entanto, o cérebro é bem desenvolvido e utiliza uma boa parte do suprimento de sangue do corpo. É um mistério como essa criatura pode sobreviver sem suporte externo.\"\n  STR_MUTON_UFOPEDIA: \"Esta criatura humanoide é fisicamente poderosa e inteligente. Eles têm um apetite peculiar por consumir carne fresca de qualquer tipo, que eles precisam para o seu sustento como os carnívoros terrestres. Eles aparentam depender de comandos telepáticos de uma raça conhecida como 'Etéreos'. Uma vez separados deste link telepático, seu sistema mental parece pifar e eles morrem. Os implantes cibernéticos são utilizados para otimizar sua performance em combate. Eles são claramente a infantaria de uma inteligência superior.\"\n  STR_MUTON_AUTOPSY: \"Autópsia de Muton\"\n  STR_MUTON_AUTOPSY_UFOPEDIA: \"A 'pele' desta criatura aparenta ser uma armadura de proteção criada organicamente que foi incrustada em seu corpo. Há numerosos implantes cibernéticos que são utilizados para melhorar o sistema cardiovascular e os sentidos. Os órgãos reprodutivos aparentam ter sido cirurgicamente removidos. Evidentemente essas desafortunadas criaturas são limitadas a uma vida de guerras e conquistas. Munição perfurante não é muito eficiente contra sua pele endurecida.\"\n  STR_CELATID_UFOPEDIA: \"Esta forma de vida tem uma misteriosa capacidade natural de flutuar no ar. Parece detectar ondas cerebrais humanas e avançará para um alvo humano, mesmo que bem escondido. Uma vez que um alvo é detectado, o Celátido pousa e dispara pequenos glóbulos de veneno extremamente corrosivo. A criatura tem a capacidade de clonar-se em um ritmo alarmante. Acompanha a raça Muton em suas expedições.\"\n  STR_CELATID_AUTOPSY: \"Autópsia de Celátido\"\n  STR_CELATID_AUTOPSY_UFOPEDIA: \"O núcleo contém um dispositivo biomecânico pequeno, o que parece ser um sistema de propulsão antigravidade que evoluiu naturalmente. O saco de veneno é o maior órgão e não parece ser uma estrutura separada do cérebro. Não há digestivo discernível ou sistema reprodutivo. Um pequeno órgão contém embriões que podem crescer rapidamente em um novo ser.\"\n  STR_SILACOID_UFOPEDIA: \"Esta forma de vida baseada em silício gera uma quantidade enorme de calor. Ela tem a capacidade de quebrar rochas que podem ser digeridas pelo núcleo quente. Ela tem uma inteligência primitiva e pode ser controlada por implantes ou seres telepáticos. Ela trabalha com a raça alienígena Muton.\"\n  STR_SILACOID_AUTOPSY: \"Autópsia de Silacoide\"\n  STR_SILACOID_AUTOPSY_UFOPEDIA: \"O miolo da criatura é extremamente quente, e parece ser a base de um sistema digestivo. Sua musculatura possui força e velocidade tremendas e sem precedentes. Sua pele é como rocha e não é danificado por fogo ou munição incendiaria.\"\n  STR_CHRYSSALID_UFOPEDIA: \"As garras de tipo caranguejo desta criatura são uma arma poderosa no combate corpo a corpo. O metabolismo acelerado e força desta criatura dão-lhe velocidade e destreza. Em vez de matar sua vítima ele impregna-o com um ovo e injeta um veneno que o transforma em um zumbi ambulante. Uma nova Crisálida vai estourar da vítima logo após a impregnação. Crisálidas estão associados com a raça dos Homens-Cobra.\"\n  STR_CHRYSSALID_AUTOPSY: \"Autópsia de Crisálida\"\n  STR_CHRYSSALID_AUTOPSY_UFOPEDIA: \"O exoesqueleto desta criatura é extremamente rígido, mas surpreendentemente vulnerável a munição explosiva. O cérebro é bem desenvolvido, e sua taxa de crescimento celular muito rápido. A criatura leva vinte e cinco ovos que são colocados dentro de outros organismos. Esta criatura é uma arma de terror muito eficaz.\"\n  STR_FLOATER_UFOPEDIA: \"Os Flutuadores são principalmente soldados e agentes terroristas. Eles são naturalmente bestas predatórias, geneticamente modificados e aprimorados ciberneticamente para serem formidáveis guerreiros. A metade inferior do corpo e a maioria dos órgãos internos foram removidos cirurgicamente, e um sistema de suporte de vida foi instalado. Este implante contém uma unidade antigravitacional que permite que a criatura flutue, ainda que de forma instável, através do ar.\"\n  STR_FLOATER_AUTOPSY: \"Autópsia de Flutuador\"\n  STR_FLOATER_AUTOPSY_UFOPEDIA: \"A criatura foi drasticamente alterada cirurgicamente. O dispositivo que parece formar o núcleo do corpo é um sistema de suporte de vida, assumindo a função de coração, pulmões e sistema digestivo. Isso permite que a criatura sobreviva em ambientes extremamente hostis. O cérebro é menor do que o nosso, mas os órgãos sensoriais são bem desenvolvidos.\"\n  STR_REAPER_UFOPEDIA: \"Este bípede carnívoro possuí mandíbulas poderosas e um apetite voraz. Ele tem implantes cerebrais que são usados para controlar suas atividades. Os instintos predatórios primitivos desta criatura são pouco úteis exceto para aterrorizar e destruir. Ceifadores costumam estar juntos com Flutuadores.\"\n  STR_REAPER_AUTOPSY: \"Autópsia de Ceifador\"\n  STR_REAPER_AUTOPSY_UFOPEDIA: \"O Ceifador contém dois 'cérebros' e dois 'corações', que permitem que ele funcione mesmo quando gravemente ferido. No entanto, sua pele peluda é altamente inflamável, fazendo com que a criatura seja vulnerável a armas incendiárias.\"\n  STR_SECTOPOD_UFOPEDIA: \"Sectópodes são criaturas robô com uma poderosa arma de feixe de laser. O controle dessas bestas mecânicas é através de uma ligação telepática com seus controladores, os Etéreos. Sectópodes são a arma mais poderosa de terror disponível para as forças alienígenas.\"\n  STR_SECTOPOD_AUTOPSY: \"Análise do Sectópode\"\n  STR_SECTOPOD_AUTOPSY_UFOPEDIA: \"O robô é resistentemente construído com uma poderosa armadura capaz de resistir a maioria das formas de ataque, em particular armas de plasma. No entanto, o circuito de detecção parece particularmente vulnerável às armas de laser.\"\n  STR_CYBERDISC_UFOPEDIA: \"Este mini disco voador é uma arma terrorista automatizada equipada com poderosos raios de plasma. Sua propulsão antigravitacional lhe fornece uma grande vantagem em terreno acidentado. Sua função primária é o terror e a destruição em nome da raça Sectoide.\"\n  STR_CYBERDISC_AUTOPSY: \"Análise do Ciberdisco\"\n  STR_CYBERDISC_AUTOPSY_UFOPEDIA: \"Os Ciberdiscos têm uma blindagem muito boa, especialmente resistente a explosões. O sistema antigravitacional foi muito danificado para ser estudado.\"\n  STR_UFO_POWER_SOURCE_UFOPEDIA: \"A fonte de energia da nave alienígena é um reator de antimatéria que utiliza Elério (elemento 115) para gerar poderosas ondas de gravidade, bem como outras formas de energia. A conversão da matéria em energia tem uma incrível eficiência de 99%, pois pequenas quantidades de Elério podem produzir uma enorme quantidade de energia. Esta unidade pode ser reproduzida facilmente usando ligas metálicas alienígenas.\"\n  STR_UFO_NAVIGATION_UFOPEDIA: \"Naves alienígenas utilizam computadores sofisticados para navegar na Terra e no espaço. O sistema é baseado em processadores ópticos organizados em um tipo de rede. A interface de controle é relativamente simples - o navegador controla a direção das ondas de gravidade geradas pela fonte de energia para mover a nave em qualquer direção. Este sistema pode ser utilizado facilmente por humanos, e pode ser reproduzido utilizando ligas alienígenas e outros componentes. \"\n  STR_UFO_CONSTRUCTION_UFOPEDIA: \"A nave alienígena é composta por três componentes principais - uma fonte de energia, um sistema de navegação e um casco construído a partir de ligas metálicas alienígenas. O casco é projetado especialmente para permitir que as ondas de gravidade sejam direcionadas e controladas. Além disso, uma pequena quantidade de Elério é necessária para alimentar a fonte de energia. Uma vez que os princípios da construção sejam entendidos, e as funções de cada um dos componentes sejam conhecidos, então será possível construir estes tipos de naves.\"\n  STR_ALIEN_FOOD_UFOPEDIA: \"Estas câmaras contêm várias enzimas que são usadas para digerir as partes do corpo do gado, outros animais e até mesmo seres humanos. O líquido é então consumido como alimento digerido pronto - provavelmente direto para a corrente sanguínea. Isto sugere uma certa dependência da Terra para o alimento - uma simbiose entre a Terra e a sociedade alienígena.\"\n  STR_ALIEN_REPRODUCTION_UFOPEDIA: \"Estas câmaras contem fetos alienígenas. O design destes recipientes parece sugerir que os alienígenas que utilizam este processo confiam inteiramente em reprodução em laboratório. Os ricos nutrientes asseguram o rápido desenvolvimento dos fetos. Este sistema de linha de produção poderia gerar milhares de clones alienígenas em um curto espaço de tempo. O processo pode ser facilmente adaptado para a reprodução humana, ou híbridos alien-humanos.\"\n  STR_ALIEN_ENTERTAINMENT_UFOPEDIA: \"Recreação é a função mais provável dessas esferas. O circuito psiônico estimula várias partes do cérebro. Os efeitos são similares aos de drogas alucinógenas. Esta é a única evidência de que os alienígenas possuem alguma forma de passatempo recreativo ou cultural.\"\n  STR_ALIEN_SURGERY_UFOPEDIA: \"Este equipamento cirúrgico utiliza cortadores laser para extrair certas partes de gado e outros animais. As frequentes mutilações de gado podem ser explicadas por essa atividade alienígena. É provável que essas partes sejam utilizadas para nutrição ou experimentos genéticos.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"No passado, milhares de pessoas afirmaram ter sido abduzido por alienígenas, às vezes repetidamente. A verdade é muito mais horrível. Os seres humanos são raptados, pesquisados e monitorados. As melhores amostras têm material genético extraído. As mulheres têm fetos humano-alienígenas híbridos implantados, e, em seguida, removidos vários meses depois. Quem sabe que motivos sinistros os alienígenas têm?\"\n  STR_ALIEN_ALLOYS_UFOPEDIA: \"Naves alienígenas são construídas a partir de ligas metálicas especiais com propriedades únicas. Elas são extremamente leves e resistentes, e podem ser moldadas por meio de métodos eletromagnéticos. Este material pode ser reproduzido e utilizado em diversos tipos de processos de fabricação.\"\n  STR_ELERIUM_115_UFOPEDIA: \"Este elemento tem a propriedade incomum de geração de energia antimatéria quando bombardeado com certas partículas. Isso cria ondas de gravidade e outras formas de energia. Não é encontrada naturalmente em nosso sistema solar e não pode ser reproduzida.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"É claro que estamos lutando uma batalha perdida na terra. As hordas alienígenas são esmagadoras em número. O melhor que podemos fazer é retardar o seu progresso. A única esperança para a humanidade é combater os alienígenas na sua origem. Nossa pesquisa parece indicar uma base de operações nas proximidades, dentro do nosso sistema solar. Alienígenas indicam que este lugar é o centro de uma civilização antiga que precede a história humana. Temos que localizar este lugar o mais rápido possível. No entanto, é preciso capturar e interrogar um líder alienígena para obter informação mais detalhada. Os OVNIs maiores provavelmente contêm pelo menos um líder alienígena.\"\n  STR_THE_MARTIAN_SOLUTION_UFOPEDIA: \"Nossa pesquisa agora aponta para Marte, como a base de operações alienígenas. A base é bem escondida, e contém todas as instalações de produção e de clonagem para abastecer a infiltração de terra. Também parece conter um tipo de computador de controle que dirige toda a operação. Parece que a sociedade alienígena é do tipo colmeia e possui uma espécie de 'abelha rainha'. Esta é a sua fraqueza fundamental, se pudermos eliminar o 'cérebro', em seguida, o corpo vai morrer. Temos de intensificar os nossos esforços de pesquisa antes que seja tarde demais. Para progredir é preciso capturar os alienígenas de mais alta patente - os comandantes, que residem exclusivamente em bases alienígenas.\"\n  STR_CYDONIA_OR_BUST_UFOPEDIA: \"Agora está claro que as hordas alienígenas estão sendo controladas a partir de uma base subterrânea em Cidônia, uma região muito peculiar de Marte que apresenta construções piramidais com cinco lados e uma grande formação rochosa semelhante a um rosto humano. A civilização Cidoniana floresceu uma vez em Marte muitos milhões de anos atrás, mas não sabemos por que ela desapareceu, ou que conexão há com a mais recente atividade alienígena lá. Seja qual for a explicação, devemos enviar uma expedição para Cidônia. Esta é a única maneira de derrotar os alienígenas. Devemos destruir o 'cérebro' controlador. Vamos precisar de uma nave Avenger equipada com as melhores armas destrutivas que dispomos. Não há nada mais que possamos averiguar aqui, é preciso aguardar o resultado do assalto a Cidônia.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"CENTRALIZAR NO LOCAL = 5 Segs\"\n  STR_CANCEL_UC: \"CANCELAR\"\n  STR_NONE: \"Nenhum\"\n  STR_UNKNOWN: \"Desconhecido\"\n  STR_POOR: \"Fraco\"\n  STR_AVERAGE: \"Médio\"\n  STR_GOOD: \"Bom\"\n  STR_EXCELLENT: \"Excelente\"\n  STR_BUILD_NEW_BASE_UC: \"CONSTRUIR NOVA BASE\"\n  STR_BASE_INFORMATION: \"INFORMAÇÕES DA BASE\"\n  STR_EQUIP_CRAFT: \"EQUIPAR NAVE\"\n  STR_BUILD_FACILITIES: \"CONSTRUIR INSTALAÇÕES\"\n  STR_RESEARCH: \"PESQUISAR\"\n  STR_MANUFACTURE: \"PRODUZIR\"\n  STR_TRANSFER_UC: \"TRANSFERIR\"\n  STR_PURCHASE_RECRUIT: \"COMPRAR/RECRUTAR\"\n  STR_SACK: \"DISPENSAR\"\n  STR_SELL_SACK_UC: \"VENDER/DISPENSAR\"\n  STR_GEOSCAPE_UC: \"TELA GLOBAL\"\n  STR_NAME: \"Nome\"\n  STR_AREA: \"Área\"\n  STR_BUILD_NEW_BASE: \"Construir Nova Base\"\n  STR_CANCEL: \"Cancelar\"\n  STR_COST_UC: \"CUSTO>\"\n  STR_CONSTRUCTION_TIME_UC: \"TEMPO DE CONSTRUÇÃO>\"\n  STR_DAY:\n    one: \"{N} dia\"\n    many: \"{N} dias\"\n    other: \"{N} dias\"\n  STR_HOUR:\n    one: \"{N} hora\"\n    many: \"{N} horas\"\n    other: \"{N} horas\"\n  STR_MAINTENANCE_UC: \"MANUTENÇÃO>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Instalação\"\n  STR_CURRENT_RESEARCH: \"PESQUISAS ATUAIS\"\n  STR_SCIENTISTS_AVAILABLE: \"Cientistas Disponíveis>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Cientistas Alocados>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Espaço de Laboratório Disponível>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"PROJETO DE PESQUISA\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"CIENTISTAS ALOCADOS\"\n  STR_PROGRESS: \"PROGRESSO\"\n  STR_NEW_PROJECT: \"Novo Projeto\"\n  STR_CANCEL_PROJECT: \"CANCELAR PROJETO\"\n  STR_NEW_RESEARCH_PROJECTS: \"NOVOS PROJETOS DE PESQUISA\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"CIENTISTAS DISPONÍVEIS>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"ESPAÇO DE LABORATÓRIO DISPONÍVEL>{ALT}{0}\"\n  STR_INCREASE: \"Aumentar\"\n  STR_DECREASE: \"Diminuir\"\n  STR_START_PROJECT: \"INICIAR PROJETO\"\n  STR_CURRENT_PRODUCTION: \"PRODUÇÃO ATUAL\"\n  STR_ENGINEERS_AVAILABLE: \"Engenheiros Disponíveis>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Engenheiros Alocados>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Espaço Disponível na Oficina>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Fundos Atuais>{ALT}{0}\"\n  STR_ITEM: \"ITEM\"\n  STR_ENGINEERS__ALLOCATED: \"Engenheiros Alocados\"\n  STR_UNITS_PRODUCED: \"Unidades Produzidas\"\n  STR_TOTAL_TO_PRODUCE: \"Total a Produzir\"\n  STR_COST__PER__UNIT: \"Custo{NEWLINE}por{NEWLINE}Unidade\"\n  STR_DAYS_HOURS_LEFT: \"Dias/Horas Restantes\"\n  STR_NEW_PRODUCTION: \"Nova Produção\"\n  STR_PRODUCTION_ITEMS: \"Itens para Produção\"\n  STR_CATEGORY: \"CATEGORIA\"\n  STR_START_PRODUCTION: \"INICIAR PRODUÇÃO\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} horas de Engenheiros para produzir uma unidade.\"\n  STR_COST_PER_UNIT_: \"Custo por unid.>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Espaço de Trabalho Necessário>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"MATERIAIS ESPECIAIS NECESSÁRIOS\"\n  STR_ITEM_REQUIRED: \"ITEM NECESSÁRIO\"\n  STR_UNITS_REQUIRED: \"UNIDADES NECESSÁRIAS\"\n  STR_UNITS_AVAILABLE: \"UNIDADES DISPONÍVEIS\"\n  STR_STOP_PRODUCTION: \"PARAR PRODUÇÃO\"\n  STR_ENGINEERS_AVAILABLE_UC: \"ENGENHEIROS DISPONÍVEIS>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"ESPAÇO DISPONÍVEL NA OFICINA>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"LUCRO MENSAL>{ALT}{0}\"\n  STR_INCREASE_UC: \"AUMENTAR\"\n  STR_DECREASE_UC: \"DIMINUIR\"\n  STR_UNITS_TO_PRODUCE: \"Unidades a Produzir\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Comprar/Recrutar Pessoal\"\n  STR_COST_OF_PURCHASES: \"Custo das Compras>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"CUSTO POR UNID.\"\n  STR_QUANTITY_UC: \"QUANTID.\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"PESSOAL DISPONÍVEL : PESSOAL TOTAL>\"\n  STR_SOLDIERS: \"Soldados\"\n  STR_SCIENTISTS: \"Cientistas\"\n  STR_ENGINEERS: \"Engenheiros\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"ESPAÇO USADO : ESPAÇO DISPONÍVEL>\"\n  STR_LIVING_QUARTERS: \"Habitação\"\n  STR_STORES: \"Depósitos\"\n  STR_LABORATORIES: \"Laboratórios\"\n  STR_WORK_SHOPS: \"Oficinas\"\n  STR_HANGARS: \"Hangares\"\n  STR_SHORT_RANGE_DETECTION: \"Detecção Curto Alcance\"\n  STR_DEFENSE_STRENGTH: \"Força Defensiva\"\n  STR_TRANSFERS_UC: \"Transferências\"\n  STR_TRANSFERS: \"Transferências\"\n  STR_ARRIVAL_TIME_HOURS: \"CHEGADA (EM HORAS)\"\n  STR_COST_: \"Custo>{ALT}{0}\"\n  STR_AREA_: \"Área>{ALT}{0}\"\n  STR_BASE_NAME: \"Nome da Base?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"SELECIONE A LOCALIZAÇÃO DO ELEVADOR DE ACESSO\"\n  STR_TRANSFER: \"Transferir\"\n  STR_AMOUNT_TO_TRANSFER: \"QUANT. A TRANSF.\"\n  STR_SELECT_DESTINATION_BASE: \"Selecionar Base de Destino\"\n  STR_COST: \"Custo\"\n  STR_VICTORY_1: \"Quando você entra na câmara, você pode ver o cérebro alienígena - o objeto de sua busca. Antes que você possa disparar, ele se comunica com você através de uma tela em sua base. Ele implora para que você ouça os seus argumentos para a sobrevivência antes de tomar a decisão de puxar o gatilho...\"\n  STR_VICTORY_2: \"O cérebro fala: Muitos milhões de anos atrás, o planeta que você chama de Marte estava vivo. Esta vida foi trazida para um planeta estéril por nossa civilização, assim como foi a sua. Durante milhões de anos visitamos o seu planeta e geneticamente desenvolvemos sua espécie. Você não pode nos matar, você é parte de nós...\"\n  STR_VICTORY_3: \"Aqui é o centro da civilização Marciana. Estas pirâmides foram construídas milhões de anos antes das que vocês têm na Terra, por uma espécie que é sua antepassada. Nenhum planeta está fora do nosso alcance. Este poder poderia ser de vocês em breve. Tudo o que pedimos é a sua cooperação...\"\n  STR_GAME_OVER_1: \"Os alienígenas tentam exterminar toda a humanidade, destruindo cidades e envenenando o ar e a água. A resistência dos exércitos terrestres é inútil face à superioridade tecnológica dos alienígenas. As gerações sobreviventes à guerra sofrem terríveis mutações enquanto tentam escapar da destruição alienígena. Após capturados, os humanos restantes são levados para campos de trabalho para ajudarem a transformar a Terra em uma colônia alienígena, parte de um império desconhecido.\"\n  STR_GAME_OVER_2: \"O conhecimento obtido pelo Projeto X-Com está perdido para sempre. Você falhou em salvar a Terra.\"\n  STR_VICTORY_4: \"O discurso do cérebro alienígena é subitamente interrompido por uma rajada de plasma, e toda a força alienígena é derrotada.\"\n  STR_VICTORY_5: \"Uma vez que os alienígenas perderam Marte, também perderam a Terra. Em pouco tempo a pesquisa X-Com permitirá à humanidade florescer mais uma vez, e reivindicar Marte para si. A ameaça alienígena se foi, mas por quanto tempo, ninguém sabe...\"\n  STR_YOU_HAVE_FAILED: \"Você não conseguiu parar o ataque alienígena. Uma a uma as nações patrocinadoras assinaram pactos com os alienígenas em troca de tecnologia, prosperidade e paz. No entanto, logo ficou claro que os alienígenas tinham outros planos...\"\n  STR_TOTAL_UC: \"TOTAL\"\n  STR_INCOME: \"Renda\"\n  STR_EXPENDITURE: \"Gastos\"\n  STR_MAINTENANCE: \"Manutenção\"\n  STR_BALANCE: \"Saldo\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"Atividade OVNI por Áreas\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"Atividade de OVNIs nos Países\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"Atividade X-Com por Áreas\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"Atividade X-Com por Países\"\n  STR_FINANCE: \"Finanças\"\n  STR_DATE_FIRST: \"{0}  de\"\n  STR_DATE_SECOND: \"{0}  de\"\n  STR_DATE_THIRD: \"{0}  de\"\n  STR_DATE_FOURTH: \"{0}  de\"\n  STR_FINANCE_THOUSANDS: \"$1000\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Não há materiais especiais suficientes para produzir{NEWLINE}{0}{NEWLINE}em{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Dinheiro insuficiente para produzir{NEWLINE}{0}{NEWLINE}em{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"Produção de{NEWLINE}{0}{NEWLINE}em{NEWLINE}{1}{NEWLINE}está completa\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"Construção de {NEWLINE}{0}{NEWLINE}em{NEWLINE}{1}{NEWLINE}completa\"\n  STR_OK_5_SECONDS: \"OK - 5 segs\"\n  STR_RESEARCH_COMPLETED: \"Pesquisa Completa\"\n  STR_VIEW_REPORTS: \"VER RELATÓRIOS\"\n  STR_WE_CAN_NOW_RESEARCH: \"Agora podemos pesquisar\"\n  STR_WE_CAN_NOW_PRODUCE: \"Agora podemos produzir\"\n  STR_SUNDAY: \"DOMINGO\"\n  STR_MONDAY: \"SEGUNDA\"\n  STR_TUESDAY: \"TERÇA\"\n  STR_WEDNESDAY: \"QUARTA\"\n  STR_THURSDAY: \"QUINTA\"\n  STR_FRIDAY: \"SEXTA\"\n  STR_SATURDAY: \"SÁBADO\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Não há {0} suficiente para reabastecer {1} em {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Não há {0} suficiente para rearmar {1} em {2}\"\n  STR_UFO_IS_NOT_RECOVERED: \"O OVNI não foi recuperado\"\n  STR_UFO_IS_RECOVERED: \"O OVNI foi recuperado\"\n  STR_CRAFT_IS_LOST: \"A nave foi perdida\"\n  STR_TERROR_CONTINUES: \"Terror continua\"\n  STR_ALIENS_DEFEATED: \"Alienígenas derrotados\"\n  STR_BASE_IS_LOST: \"Base perdida\"\n  STR_BASE_IS_SAVED: \"Base está salva\"\n  STR_ALIEN_BASE_STILL_INTACT: \"A Base Alienígena permanece intacta\"\n  STR_ALIEN_BASE_DESTROYED: \"Base Alienígena destruída\"\n  STR_ALIENS_KILLED: \"ALIENÍGENAS MORTOS\"\n  STR_ALIEN_CORPSES_RECOVERED: \"CADÁVERES DE ALIENÍGENAS RECUPERADOS \"\n  STR_LIVE_ALIENS_RECOVERED: \"ALIENÍGENAS RECUPERADOS VIVOS\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"ARTEFATOS ALIENÍGENAS RECUPERADOS\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"CONTROLE DA BASE ALIENÍGENA DESTRUÍDO\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"CIVIS MORTOS POR ALIENÍGENAS\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"CIVIS MORTOS POR SOLDADOS X-COM\"\n  STR_CIVILIANS_SAVED: \"CIVIS SALVOS\"\n  STR_XCOM_OPERATIVES_KILLED: \"AGENTES X-COM MORTOS\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"AGENTES X-COM DESAPARECIDOS EM COMBATE\"\n  STR_TANKS_DESTROYED: \"TANQUES DESTRUÍDOS\"\n  STR_XCOM_CRAFT_LOST: \"NAVE X-COM PERDIDA\"\n  STR_UFO_RECOVERY: \"RECUPERAÇÃO DE OVNI\"\n  STR_ALIEN_BASE_RECOVERY: \"CAPTURADOS NA BASE ALIENÍGENA\"\n  STR_BASE_UNDER_ATTACK: \"{0} está sob ataque!\"\n  STR_BASE_DEFENSES_INITIATED: \"DEFESAS DA BASE INICIADAS\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"OVNI REPELIDO POR ESCUDO GRAVITACIONAL!\"\n  STR_FIRING: \"ATIRANDO\"\n  STR_HIT: \"ACERTOU!\"\n  STR_UFO_DESTROYED: \"OVNI DESTRUÍDO!\"\n  STR_MISSED: \"ERROU!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Vender Itens/Dispensar Pessoal\"\n  STR_VALUE_OF_SALES: \"VALOR DA VENDA> {ALT}{0}\"\n  STR_FUNDS: \"FUNDOS> {ALT}{0}\"\n  STR_SELL_SACK: \"Vender/Dispensar\"\n  STR_VALUE: \"Valor\"\n  STR_CRAFT_: \"NAVE> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"RECUPERAÇÃO DE OVNI ABATIDO\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"Tenha cuidado - Podem haver agentes no OVNI ou ao redor do local do acidente. A missão será bem sucedida quando todas as unidades inimigas forem eliminadas ou neutralizadas. A recuperação de destroços do OVNI, artefatos e cadáveres alienígenas podem então ser iniciados. Para abortar a missão, retorne os agentes X-Com para o veículo de transporte e clique no ícone 'Abortar Missão'.\"\n  STR_UFO_GROUND_ASSAULT: \"ATAQUE POR TERRA AO OVNI\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"Explore o local de pouso e, se possível, entre no OVNI. A missão será bem sucedida quando todas as unidades inimigas forem eliminadas ou neutralizadas. A recuperação do OVNI, artefatos e cadáveres alienígenas podem então ser iniciados. Para abortar a missão, retorne os agentes X-Com para o veículo de transporte e clique no ícone 'Abortar Missão'.\"\n  STR_BASE_DEFENSE: \"DEFESA DE BASE\"\n  STR_BASE_UC_: \"BASE> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"Uma nave alienígena aterrissou nas proximidades. Nossa base está em grave perigo. De acordo com o procedimento padrão de todo o pessoal não combatente e as naves X-Com foram evacuadas. Unidades alienígenas entrarão na base através de portas do hangar ou do elevador. Defenda a base e suas instalações vitais a todo custo - esta é uma luta até a morte. Se você clicar no ícone 'Abortar Missão', você vai admitir a derrota e perder a base.\"\n  STR_ALIEN_BASE_ASSAULT: \"ATAQUE À BASE ALIENÍGENA\"\n  STR_ALIEN_BASE_ASSAULT_BRIEFING: \"Agentes X-Com conseguiram entrar em uma base alienígena. O centro de controle deve ser destruído para tornar a base inoperante. A missão terminará quando todos os inimigos forem eliminados, ou quando o seu time retornar para a área verde de saída (clique no ícone 'Abortar Missão' para escapar).\"\n  STR_CYDONIA_BRIEFING: \"Você chegou em Cidônia. Você conseguiu entrar em um grande complexo subterrâneo perto da Esfinge Marciana. Você deve destruir o Cérebro Alienígena que controla toda a atividade alienígena. O destino da humanidade está em suas mãos...\"\n  STR_TERROR_MISSION: \"MISSÃO DE TERROR\"\n  STR_TERROR_MISSION_BRIEFING: \"A missão será bem sucedida quando todas as unidades inimigas forem eliminadas ou neutralizadas. Você deve tentar salvar a vida de todos os civis na área, neutralizando a ameaça alienígena. Para abortar a missão, retorne os agentes X-Com para o veículo de transporte e clique no ícone 'Abortar Missão'.\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"NÃO HÁ HANGARES LIVRES PARA A PRODUÇÃO!{SMALLLINE}Cada nave atribuída a uma base, transferida, comprada ou construída ocupa um hangar. Construa um novo hangar ou transfira uma nave para outra base.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"NÃO HÁ HANGARES LIVRES PARA AQUISIÇÃO!{SMALLLINE}Cada nave atribuída a uma base, transferida para uma base, comprada ou construída utiliza um hangar. Construa um novo hangar ou transfira uma nave para outra base.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"NÃO HÁ HANGARES LIVRES PARA TRANSFERÊNCIA!{SMALLLINE}Cada nave atribuída a uma base, transferida para uma base, comprada ou construída utiliza um hangar. Construa um novo hangar ou transfira uma nave para outra base.\"\n  STR_CANNOT_BUILD_HERE: \"IMPOSSÍVEL CONSTRUIR AQUI!{SMALLLINE}Você deve construir próximo a uma instalação existente na base.\"\n  STR_NO_FREE_ACCOMODATION: \"SEM ACOMODAÇÕES DISPONÍVEIS!{SMALLLINE}A base de destino não tem espaço suficiente nas habitações.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"NÃO HÁ ESPAÇO DE TRABALHO DISPONÍVEL!{SMALLLINE}Construa mais oficinas ou reduza outros projetos.\"\n  STR_NOT_ENOUGH_MONEY: \"DINHEIRO INSUFICIENTE!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"ESPAÇO DE ARMAZENAMENTO INSUFICIENTE!{SMALLLINE}Construa um novo depósito ou transfira equipamentos existentes para outras bases.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"NÃO HÁ HABITAÇÕES SUFICIENTES!{SMALLLINE}Construa novas habitações ou transfira pessoal para outras bases.\"\n  STR_LAUNCH_INTERCEPTION: \"LANÇAR INTERCEPTAÇÃO\"\n  STR_CRAFT: \"NAVE\"\n  STR_STATUS: \"ESTADO\"\n  STR_BASE: \"BASE\"\n  STR_READY: \"PRONTO\"\n  STR_OUT: \"FORA\"\n  STR_REPAIRS: \"REPAROS\"\n  STR_REFUELLING: \"ABASTECENDO\"\n  STR_REARMING: \"REARMANDO\"\n  STR_TARGET: \"ALVO: {0}\"\n  STR_WAY_POINT: \"PONTO DE DESTINO\"\n  STR_ARE_YOU_SURE_CYDONIA: \"Tem certeza de que deseja enviar esta nave em uma missão para Cidônia?\"\n  STR_YES: \"SIM\"\n  STR_NO: \"NÃO\"\n  STR_SELECT_DESTINATION: \"SELECIONE O DESTINO\"\n  STR_CYDONIA: \"CIDÔNIA\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"SELECIONE O LOCAL PARA A NOVA BASE\"\n  STR_RETURN_TO_BASE: \"VOLTAR PARA A BASE\"\n  STR_SELECT_NEW_TARGET: \"SELECIONAR O NOVO ALVO\"\n  STR_PATROL: \"PATRULHAR\"\n  STR_STATUS_: \"ESTADO>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"DANIFICADA - RETORNANDO À BASE\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"POUCO COMBUSTÍVEL - RETORNANDO À BASE\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"MISSÃO COMPLETA - RETORNANDO À BASE\"\n  STR_PATROLLING: \"PATRULHANDO\"\n  STR_TAILING_UFO: \"PERSEGUINDO OVNI\"\n  STR_INTERCEPTING_UFO: \"INTERCEPTANDO OVNI - {0}\"\n  STR_RETURNING_TO_BASE: \"RETORNANDO À BASE\"\n  STR_DESTINATION_UC_: \"DESTINO: {0}\"\n  STR_BASE_UC: \"BASE>{ALT}{0}\"\n  STR_SPEED_: \"VELOCIDADE>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"VELOCIDADE MÁXIMA>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"ALTITUDE>{ALT}{0}\"\n  STR_VERY_LOW: \"MUITO BAIXA\"\n  STR_LOW_UC: \"BAIXA\"\n  STR_HIGH_UC: \"ALTA\"\n  STR_VERY_HIGH: \"MUITO ALTA\"\n  STR_FUEL: \"COMBUSTÍVEL>{ALT}{0}\"\n  STR_WEAPON_ONE: \"ARMA-1>{ALT}{0}\"\n  STR_NONE_UC: \"NENHUMA\"\n  STR_ROUNDS_: \"MUNIÇÃO>{ALT}{0}\"\n  STR_WEAPON_TWO: \"ARMA-2>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"NAVE DE INTERCEPTAÇÃO\"\n  STR_BASE_: \"Base>{0}\"\n  STR_NAME_UC: \"NOME\"\n  STR_AMMO_: \"MUNIÇÃO>{ALT}{0}\"\n  STR_CREW: \"TRIPULAÇÃO\"\n  STR_EQUIPMENT_UC: \"EQUIPAMENTO\"\n  STR_ARMOR: \"ARMADURA\"\n  STR_MAX: \"MÁX>{ALT}{0}\"\n  STR_ROOKIE: \"Recruta\"\n  STR_SQUADDIE: \"Soldado\"\n  STR_SERGEANT: \"Sargento\"\n  STR_CAPTAIN: \"Capitão\"\n  STR_COLONEL: \"Coronel\"\n  STR_COMMANDER: \"Comandante\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Selecionar Esquadrão para {0}\"\n  STR_SORT_BY: \"CLASSIFICAR POR...\"\n  STR_ORIGINAL_ORDER: \"ORDEM ORIGINAL\"\n  STR_MISSIONS2: \"MISSÕES\"\n  STR_KILLS2: \"MORTES\"\n  STR_WOUND_RECOVERY2: \"RECUPER. DE FERIMENTO\"\n  STR_SPACE_AVAILABLE: \"ESPAÇO DISPONÍVEL>{ALT}{0}\"\n  STR_SPACE_USED: \"ESPAÇO USADO>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"ESPAÇO USADO\"\n  STR_RANK: \"PATENTE\"\n  STR_WOUNDED: \"FERIDO\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Equipamento para {0}\"\n  STR_DEFENSE_VALUE: \"Pontos de Defesa\"\n  STR_HIT_RATIO: \"Taxa de Acerto\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}pronto para{NEWLINE}pousar próximo a{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"Começar Missão?\"\n  STR_SELECT_ARMAMENT: \"Selecionar Armamento\"\n  STR_AMMUNITION_AVAILABLE: \"MUNIÇÃO DISPONÍVEL\"\n  STR_ARMAMENT: \"ARMAMENTO\"\n  STR_NOT_AVAILABLE: \"N.D.\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"SELECIONAR ARMADURA PARA{NEWLINE}{0}\"\n  STR_TYPE: \"TIPO\"\n  STR_PERSONAL_ARMOR_UC: \"ARMADURA PESSOAL\"\n  STR_POWER_SUIT_UC: \"ARMADURA ENERGIZADA\"\n  STR_FLYING_SUIT_UC: \"ARMADURA VOADORA\"\n  STR_SELECT_ARMOR: \"Selecionar Armadura\"\n  STR_NORTH: \"NORTE\"\n  STR_NORTH_EAST: \"NORDESTE\"\n  STR_EAST: \"LESTE\"\n  STR_SOUTH_EAST: \"SUDESTE\"\n  STR_SOUTH: \"SUL\"\n  STR_SOUTH_WEST: \"SUDOESTE\"\n  STR_WEST: \"OESTE\"\n  STR_NORTH_WEST: \"NOROESTE\"\n  STR_SELECT_ACTION: \"SELECIONAR AÇÃO\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"CONTINUAR PERSEGUIÇÃO DE INTERCEPTAÇÃO\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"PERSEGUIR SEM INTERCEPTAR\"\n  STR_VERY_LARGE: \"MUITO GRANDE\"\n  STR_LARGE: \"GRANDE\"\n  STR_MEDIUM_UC: \"MÉDIO\"\n  STR_SMALL: \"PEQUENO\"\n  STR_VERY_SMALL: \"MUITO PEQUENO\"\n  STR_GROUNDED: \"EM TERRA\"\n  STR_DETECTED: \"Detectado\"\n  STR_SIZE_UC: \"TAMANHO\"\n  STR_ALTITUDE: \"ALTITUDE\"\n  STR_HEADING: \"SENTIDO\"\n  STR_SPEED: \"VELOCIDADE\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"CENTRALIZAR NO OVNI - TEMPO = 5 Segs\"\n  STR_TRACKING_LOST: \"RASTRO PERDIDO\"\n  STR_REDIRECT_CRAFT: \"REDIRECIONAR NAVE\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"IR PARA A ÚLTIMA LOCALIZAÇÃO DO ALVO\"\n  STR_UFO_: \"OVNI-{0}\"\n  STR_ALIEN_BASE_: \"BASE ALIENÍGENA - {0}\"\n  STR_CRASH_SITE_: \"LOCAL DE IMPACTO - {0}\"\n  STR_LANDING_SITE_: \"LOCAL DE POUSO - {0}\"\n  STR_WAY_POINT_: \"PONTO DE DESTINO - {0}\"\n  STR_TERROR_SITE: \"LOCAL DE TERROR - {0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}chegou em{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"Patrulhando\"\n  STR_ALIEN_ORIGINS: \"Origens Alienígenas\"\n  STR_THE_MARTIAN_SOLUTION: \"A Solução Marciana\"\n  STR_CYDONIA_OR_BUST: \"Cidônia ou Fracasso\"\n  STR_UFOPAEDIA: \"UFOpédia\"\n  STR_XCOM_CRAFT_ARMAMENT: \"ARMAMENTO E NAVES X-COM\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"PLATAFORMA DE ARMAS PESADAS (PAP)\"\n  STR_WEAPONS_AND_EQUIPMENT: \"ARMAS E EQUIPAMENTOS\"\n  STR_ALIEN_ARTIFACTS: \"ARTEFATOS ALIENÍGENAS\"\n  STR_BASE_FACILITIES: \"INSTALAÇÕES DA BASE\"\n  STR_ALIEN_LIFE_FORMS: \"FORMAS DE VIDA ALIENÍGENAS\"\n  STR_ALIEN_RESEARCH_UC: \"PESQUISA ALIENÍGENA\"\n  STR_UFO_COMPONENTS: \"COMPONENTES DE OVNI\"\n  STR_UFOS: \"OVNIs\"\n  STR_SELECT_ITEM: \"SELECIONE O ITEM\"\n  STR_ACCELERATION: \"ACELERAÇÃO>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"CAPACIDADE DE COMBUSTÍVEL>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"SISTEMAS DE ARMAS>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"CAPACIDADE DE DANO>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"ESPAÇO DE CARGA>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"CAPACIDADE DE PAPs>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Dano\"\n  STR_RANGE: \"Alcance\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Precisão\"\n  STR_RE_LOAD_TIME: \"Tempo de Recarga\"\n  STR_SECONDS: \"{0}s\"\n  STR_DAMAGE_ARMOR_PIERCING: \"PERFURANTE\"\n  STR_DAMAGE_INCENDIARY: \"INCENDIÁRIO\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"EXPLOSIVO\"\n  STR_DAMAGE_LASER_BEAM: \"RAIO LASER\"\n  STR_DAMAGE_PLASMA_BEAM: \"FEIXE DE PLASMA\"\n  STR_DAMAGE_STUN: \"ATORDOAR\"\n  STR_DAMAGE_MELEE: \"CORPO-A-CORPO\"\n  STR_DAMAGE_ACID: \"ÁCIDO\"\n  STR_DAMAGE_SMOKE: \"FUMAÇA\"\n  STR_SHOT_TYPE: \"TIPO DO TIRO\"\n  STR_ACCURACY_UC: \"PRECISÃO\"\n  STR_TIME_UNIT_COST: \"CUSTO UT\"\n  STR_DAMAGE_UC: \"DANO\"\n  STR_AMMO: \"MUNIÇÃO\"\n  STR_SHOT_TYPE_AUTO: \"Rajada\"\n  STR_SHOT_TYPE_SNAP: \"Simples\"\n  STR_SHOT_TYPE_AIMED: \"Preciso\"\n  STR_CONSTRUCTION_TIME: \"Tempo de Construção\"\n  STR_CONSTRUCTION_COST: \"Custo de Construção\"\n  STR_MAINTENANCE_COST: \"Custo de Manutenção\"\n  STR_LOW: \"Baixo\"\n  STR_MEDIUM: \"Médio\"\n  STR_HIGH: \"Alto\"\n  STR_CRAFT_WEAPON: \"Armamento de Nave\"\n  STR_CRAFT_AMMUNITION: \"Munição de Nave\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Plataforma de Armas Pesadas\"\n  STR_WEAPON: \"Armamento\"\n  STR_AMMUNITION: \"Munição\"\n  STR_EQUIPMENT: \"Equipamento\"\n  STR_ALIEN_CORPSE: \"Cadáver Alienígena\"\n  STR_UFO_COMPONENT: \"Componente OVNI\"\n  STR_PERSONAL_ARMOR: \"Armadura Pessoal\"\n  STR_RAW_MATERIALS: \"Matérias Primas\"\n  STR_HWP_CANNON_SHELLS: \"Munição de Canhão PAP\"\n  STR_ALIEN: \"Alienígena\"\n  STR_SECTOID: \"Sectoide\"\n  STR_SNAKEMAN: \"Homem-Cobra\"\n  STR_ETHEREAL: \"Etéreo\"\n  STR_MUTON: \"Muton\"\n  STR_FLOATER: \"Flutuador\"\n  STR_CELATID: \"Celátido\"\n  STR_SILACOID: \"Silacoide\"\n  STR_CHRYSSALID: \"Crisálida\"\n  STR_ZOMBIE: \"Zumbi\"\n  STR_REAPER: \"Ceifador\"\n  STR_SECTOPOD: \"Sectópode\"\n  STR_CYBERDISC: \"Ciberdisco\"\n  STR_LIVE_COMMANDER: \"Comandante\"\n  STR_LIVE_LEADER: \"Líder\"\n  STR_LIVE_ENGINEER: \"Engenheiro\"\n  STR_LIVE_MEDIC: \"Médico\"\n  STR_LIVE_NAVIGATOR: \"Navegador\"\n  STR_LIVE_SOLDIER: \"Soldado\"\n  STR_LIVE_TERRORIST: \"Agente Terrorista\"\n  STR_FLOATER_SOLDIER: \"Soldado Flutuador\"\n  STR_FLOATER_NAVIGATOR: \"Navegador Flutuador\"\n  STR_FLOATER_MEDIC: \"Médico Flutuador\"\n  STR_FLOATER_ENGINEER: \"Engenheiro Flutuador\"\n  STR_FLOATER_LEADER: \"Líder Flutuador\"\n  STR_FLOATER_COMMANDER: \"Comandante Flutuador\"\n  STR_SECTOID_SOLDIER: \"Soldado Sectoide\"\n  STR_SECTOID_NAVIGATOR: \"Navegador Sectoide\"\n  STR_SECTOID_MEDIC: \"Médico Sectoide\"\n  STR_SECTOID_ENGINEER: \"Engenheiro Sectoide\"\n  STR_SECTOID_LEADER: \"Líder Sectoide\"\n  STR_SECTOID_COMMANDER: \"Comandante Sectoide\"\n  STR_SNAKEMAN_SOLDIER: \"Soldado Homem-Cobra\"\n  STR_SNAKEMAN_NAVIGATOR: \"Navegador Homem-Cobra\"\n  STR_SNAKEMAN_ENGINEER: \"Engenheiro Homem-Cobra\"\n  STR_SNAKEMAN_LEADER: \"Líder Homem-Cobra\"\n  STR_SNAKEMAN_COMMANDER: \"Comandante Homem-Cobra\"\n  STR_MUTON_SOLDIER: \"Soldado Muton\"\n  STR_MUTON_NAVIGATOR: \"Navegador Muton\"\n  STR_MUTON_ENGINEER: \"Engenheiro Muton\"\n  STR_ETHEREAL_SOLDIER: \"Soldado Etéreo\"\n  STR_ETHEREAL_LEADER: \"Líder Etéreo \"\n  STR_ETHEREAL_COMMANDER: \"Comandante Etéreo\"\n  STR_CYBERDISC_TERRORIST: \"Terrorista Ciberdisco\"\n  STR_REAPER_TERRORIST: \"Terrorista Ceifador\"\n  STR_CHRYSSALID_TERRORIST: \"Crisálida Terrorista\"\n  STR_CELATID_TERRORIST: \"Terrorista Celátido\"\n  STR_SILACOID_TERRORIST: \"Terrorista Silacoide\"\n  STR_SECTOPOD_TERRORIST: \"Terrorista Sectópode\"\n  STR_UFO_POWER_SOURCE: \"Fonte de Energia OVNI\"\n  STR_UFO_NAVIGATION: \"Sistema de Navegação OVNI\"\n  STR_UFO_CONSTRUCTION: \"Métodos de Construção OVNI\"\n  STR_ALIEN_FOOD: \"Alimentação Alienígena\"\n  STR_ALIEN_REPRODUCTION: \"Reprodução Alienígena\"\n  STR_ALIEN_ENTERTAINMENT: \"Entretenimento Alienígena\"\n  STR_ALIEN_SURGERY: \"Cirurgia Alienígena\"\n  STR_EXAMINATION_ROOM: \"Sala de Exames\"\n  STR_ALIEN_ALLOYS: \"Ligas Metálicas Alienígenas\"\n  STR_ALIEN_HABITAT: \"Habitat Alienígena\"\n  STR_POWER_SUIT: \"Armadura Energizada\"\n  STR_FLYING_SUIT: \"Armadura Voadora\"\n  STR_HWP_ROCKETS: \"Foguetes PAP\"\n  STR_HWP_FUSION_BOMB: \"Bombas de Fusão PAP\"\n  STR_LASER_WEAPONS: \"Armas Laser\"\n  STR_NEW_FIGHTER_CRAFT: \"Novo Caça de Combate\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Novo Caça-Transportador\"\n  STR_ULTIMATE_CRAFT: \"Nave Definitiva\"\n  STR_LASER_PISTOL: \"Pistola Laser\"\n  STR_LASER_RIFLE: \"Rifle Laser\"\n  STR_HEAVY_LASER: \"Laser Pesado\"\n  STR_LASER_CANNON: \"Canhão Laser\"\n  STR_PLASMA_CANNON: \"Canhão de Plasma\"\n  STR_FUSION_MISSILE: \"Mísseis de Fusão\"\n  STR_LASER_DEFENSE: \"Defesas Laser\"\n  STR_PLASMA_DEFENSE: \"Defesa Plasma\"\n  STR_FUSION_DEFENSE: \"Defesa por Fusão\"\n  STR_GRAV_SHIELD: \"Escudo Gravitacional\"\n  STR_MIND_SHIELD: \"Escudo Mental\"\n  STR_PSI_LAB: \"Laboratório Psiônico\"\n  STR_MOTION_SCANNER: \"Detector de Movimento\"\n  STR_MEDI_KIT: \"Kit Médico\"\n  STR_TANK_CANNON: \"Tanque/Canhão\"\n  STR_TANK_ROCKET_LAUNCHER: \"Tanque/Lança-foguetes\"\n  STR_TANK_LASER_CANNON: \"Tanque/Canhão Laser\"\n  STR_HOVERTANK_PLASMA: \"Levitanque/Plasma\"\n  STR_HOVERTANK_LAUNCHER: \"Levitanque/Lançador\"\n  STR_STINGRAY_LAUNCHER: \"Lançador de Mísseis Stingray\"\n  STR_AVALANCHE_LAUNCHER: \"Lançador de Mísseis Avalanche\"\n  STR_CANNON: \"Canhão\"\n  STR_FUSION_BALL_LAUNCHER: \"Lançador de Esferas de Fusão\"\n  STR_PLASMA_BEAM: \"Feixe de Plasma\"\n  STR_STINGRAY_MISSILES: \"Mísseis Stingray\"\n  STR_AVALANCHE_MISSILES: \"Mísseis Avalanche\"\n  STR_CANNON_ROUNDS_X50: \"Munição de Canhão (x50)\"\n  STR_FUSION_BALL: \"Esfera de Fusão\"\n  STR_SOLDIER: \"Soldado\"\n  STR_SCIENTIST: \"Cientistas\"\n  STR_ENGINEER: \"Engenheiro\"\n  STR_NORTH_AMERICA: \"América do Norte\"\n  STR_ARCTIC: \"Ártico\"\n  STR_ANTARCTICA: \"Antártida\"\n  STR_SOUTH_AMERICA: \"América do Sul\"\n  STR_EUROPE: \"Europa\"\n  STR_NORTH_AFRICA: \"África do Norte\"\n  STR_SOUTHERN_AFRICA: \"África do Sul\"\n  STR_CENTRAL_ASIA: \"Ásia Central\"\n  STR_SOUTH_EAST_ASIA: \"Sudeste da Ásia\"\n  STR_SIBERIA: \"Sibéria\"\n  STR_AUSTRALASIA: \"Australásia\"\n  STR_PACIFIC: \"Pacífico\"\n  STR_NORTH_ATLANTIC: \"Atlântico Norte\"\n  STR_SOUTH_ATLANTIC: \"Atlântico Sul\"\n  STR_INDIAN_OCEAN: \"Oceano Índico\"\n  STR_ALIEN_RESEARCH: \"Pesquisa Alienígena\"\n  STR_ALIEN_HARVEST: \"Colheita Alienígena\"\n  STR_ALIEN_ABDUCTION: \"Abdução Alienígena\"\n  STR_ALIEN_INFILTRATION: \"Infiltração Alienígena\"\n  STR_ALIEN_BASE: \"Base Alienígena\"\n  STR_ALIEN_TERROR: \"Terror Alienígena\"\n  STR_ALIEN_RETALIATION: \"Retaliação Alienígena\"\n  STR_ALIEN_SUPPLY: \"Suprimento Alienígena\"\n  STR_MAXIMUM_SPEED: \"Velocidade Máxima\"\n  STR_HYPER_WAVE_DECODER_UC: \"DECODIFICADOR DE HIPER ONDA\"\n  STR_SKYRANGER: \"SKYRANGER\"\n  STR_LIGHTNING: \"LIGHTNING\"\n  STR_AVENGER: \"AVENGER\"\n  STR_INTERCEPTOR: \"INTERCEPTOR\"\n  STR_FIRESTORM: \"FIRESTORM\"\n  STR_UFO: \"OVNI\"\n  STR_STINGRAY: \"STINGRAY\"\n  STR_AVALANCHE: \"AVALANCHE\"\n  STR_CANNON_UC: \"CANHÃO\"\n  STR_FUSION_BALL_UC: \"ESFERA DE FUSÃO\"\n  STR_LASER_CANNON_UC: \"CANHÃO LASER\"\n  STR_PLASMA_BEAM_UC: \"FEIXE DE PLASMA\"\n  STR_DAMAGE_CAPACITY: \"Capacidade de Dano\"\n  STR_WEAPON_POWER: \"Poder do Armamento\"\n  STR_WEAPON_RANGE: \"Alcance do Armamento\"\n  STR_ACCESS_LIFT: \"Elevador de Acesso\"\n  STR_LABORATORY: \"Laboratório\"\n  STR_WORKSHOP: \"Oficina\"\n  STR_SMALL_RADAR_SYSTEM: \"Radar Pequeno\"\n  STR_LARGE_RADAR_SYSTEM: \"Radar Grande\"\n  STR_MISSILE_DEFENSES: \"Defesa por Mísseis\"\n  STR_GENERAL_STORES: \"Depósito\"\n  STR_ALIEN_CONTAINMENT: \"Contentor de Alienígena\"\n  STR_LASER_DEFENSES: \"Defesas Laser\"\n  STR_PLASMA_DEFENSES: \"Defesas de Plasma\"\n  STR_FUSION_BALL_DEFENSES: \"Defesas com Esferas de Fusão\"\n  STR_PSIONIC_LABORATORY: \"Laboratório Psiônico\"\n  STR_HYPER_WAVE_DECODER: \"Decodificador de Hiper Onda\"\n  STR_HANGAR: \"Hangar\"\n  STR_USA: \"ESTADOS UNIDOS\"\n  STR_RUSSIA: \"RÚSSIA\"\n  STR_UK: \"REINO UNIDO\"\n  STR_FRANCE: \"FRANÇA\"\n  STR_GERMANY: \"ALEMANHA\"\n  STR_ITALY: \"ITÁLIA\"\n  STR_SPAIN: \"ESPANHA\"\n  STR_CHINA: \"CHINA\"\n  STR_JAPAN: \"JAPÃO\"\n  STR_INDIA: \"ÍNDIA\"\n  STR_BRAZIL: \"BRASIL\"\n  STR_AUSTRALIA: \"AUSTRÁLIA\"\n  STR_NIGERIA: \"NIGÉRIA\"\n  STR_SOUTH_AFRICA: \"ÁFRICA DO SUL\"\n  STR_EGYPT: \"EGITO\"\n  STR_CANADA: \"CANADÁ\"\n  STR_TANK: \"Tanque\"\n  STR_CIVILIAN: \"Civis\"\n  STR_JAN: \"Jan\"\n  STR_FEB: \"Fev\"\n  STR_MAR: \"Mar\"\n  STR_APR: \"Abr\"\n  STR_MAY: \"Mai\"\n  STR_JUN: \"Jun\"\n  STR_JUL: \"Jul\"\n  STR_AUG: \"Ago\"\n  STR_SEP: \"Set\"\n  STR_OCT: \"Out\"\n  STR_NOV: \"Nov\"\n  STR_DEC: \"Dez\"\n  STR_INTERNATIONAL_RELATIONS: \"Relações Internacionais\"\n  STR_COUNTRY: \"País\"\n  STR_FUNDING: \"Finanças\"\n  STR_CHANGE: \"Alteração\"\n  STR_WEAPON_SYSTEMS: \"SISTEMAS DE ARMAS\"\n  STR_HWPS: \"PAPs\"\n  STR_DAMAGE_UC_: \"DANO>{ALT}{0}\"\n  STR_ACCESS_LIFT_UFOPEDIA: \"O elevador de acesso permite que os equipamentos e pessoal sejam transferidos para dentro ou fora de uma base subterrânea. É sempre a primeira instalação a ser construída em um novo site. A área de elevador é vulnerável a invasão de qualquer força hostil potencial.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Cada bloco acomoda até 50 pessoas. As instalações proveem áreas de recreação, alimentação e sono.\"\n  STR_LABORATORY_UFOPEDIA: \"Até 50 cientistas podem trabalhar em uma instalação de laboratório. Laboratórios são equipados com a mais recente tecnologia para a pesquisa em materiais, bioquímica e cosmologia. Há acesso privilegiado aos melhores laboratórios de pesquisa em todo o mundo, incluindo os estabelecimentos militares.\"\n  STR_WORKSHOP_UFOPEDIA: \"Uma oficina contém todos os equipamentos necessários para a fabricação de equipamentos com base em projetos dos laboratórios de ciências. Até 50 engenheiros podem ocupar uma oficina, embora itens em construção também consumam espaço.\"\n  STR_SMALL_RADAR_SYSTEM_UFOPEDIA: \"Um sistema de detecção pequeno possui um alcance de radar efetivo de 300 milhas náuticas e está conectado a sistemas de satélite para buscas em solo. Cada sistema tem uma probabilidade de 10% de detectar um objeto de tamanho médio a cada 30 minutos.\"\n  STR_LARGE_RADAR_SYSTEM_UFOPEDIA: \"Um sistema de detecção grande possui um alcance de radar efetivo de 450 milhas náuticas e está conectado a sistemas de satélite para buscas em solo. Cada sistema tem uma probabilidade de 20% de detectar um objeto de tamanho médio a cada 30 minutos.\"\n  STR_MISSILE_DEFENSES_UFOPEDIA: \"Defesas por mísseis fornecem alguma proteção contra a incursão de naves hostis que estão tentando pousar perto da base.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"Todos os equipamentos, sistemas de armas, munições, material recuperado e Plataformas de Armas Pesadas são colocados nos depósitos, incluindo equipamento atribuído às naves nos hangares.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"Alienígenas vivos dependem de um habitat especial para manter seus sistemas de vida. O confinamento pode manter até 10 formas de vida alienígenas em unidades autossuficientes.\"\n  STR_LASER_DEFENSES_UFOPEDIA: \"Defesas por Laser fornecem proteção contra a incursão de naves hostis.\"\n  STR_PLASMA_DEFENSES_UFOPEDIA: \"Defesas de raios de plasma proveem uma proteção poderosa e eficiente contra incursões de naves hostis.\"\n  STR_FUSION_BALL_DEFENSES_UFOPEDIA: \"Mísseis de fusão fornecem a defesa mais eficaz contra ataques alienígenas. Estes mísseis criam uma implosão antimatéria que destrói tudo dentro de um raio específico.\"\n  STR_GRAV_SHIELD_UFOPEDIA: \"O Escudo Gravitacional repele naves alienígenas tentando pousar perto da base o suficiente para que todos os sistemas de defesa atirem novamente. Na prática, isso vai dobrar a eficácia de quaisquer sistemas de defesa em sua base.\"\n  STR_MIND_SHIELD_UFOPEDIA: \"Já que as naves alienígenas dependem de ondas cerebrais para detectar a presença de seres humanos, a contramedida mais eficaz é bloquear as ondas cerebrais da base. Esta instalação reduzirá drasticamente as chances de detecção por naves alienígenas.\"\n  STR_PSIONIC_LABORATORY_UFOPEDIA: \"O laboratório psiônico pode avaliar o potencial psiônico de todos os soldados na base e dar-lhes a formação necessária para utilizar suas habilidades psiônicas. Cada laboratório pode treinar até dez soldados. Treinamento é alocado no final de cada mês. Habilidades psiônicas usadas em conjunto com um Amplificador Psi pode ser usado para ataques psiônicos durante o combate.\"\n  STR_HYPER_WAVE_DECODER_UFOPEDIA: \"As comunicações dos alienígenas dependem de uma onda supradimensional que viaja quase instantaneamente. A sala de decodificação intercepta transmissões dos OVNIs e as decodifica. Isso revela o tipo de OVNI, a raça da tripulação e a sua missão.\"\n  STR_HANGAR_UFOPEDIA: \"Cada hangar pode acomodar uma aeronave e possui instalações de manutenção, reabastecimento e reparos. Cada aeronave estacionado em uma base deve possuir um hangar designado a ela e que não pode ser utilizado por outra, mesmo que a primeira esteja fora em uma missão.\"\n  STR_PISTOL_UFOPEDIA: \"A pistola X-Com padrão é uma semiautomática de alta potência, com capacidade para 12 cartuchos.\"\n  STR_RIFLE_UFOPEDIA: \"Este rifle sniper de alta precisão tem mira guiada a laser e carrega munição de 6,7 milímetros em carregadores de 20 cartuchos.\"\n  STR_HEAVY_CANNON_UFOPEDIA: \"O canhão pesado é um armamento devastador, mas pesado. Sua versatilidade vem do fato de que ele pode usar três tipos de munição - perfurante, incendiária e explosiva.\"\n  STR_AUTO_CANNON_UFOPEDIA: \"O canhão automático combina a versatilidade e o poder de um canhão pesado com uma taxa de fogo rápido.\"\n  STR_ROCKET_LAUNCHER_UFOPEDIA: \"O lança-foguetes é um sistema guiado a laser que pode atirar mísseis de três tamanhos.\"\n  STR_LASER_PISTOL_UFOPEDIA: \"A pistola laser é uma implementação efetiva de uma nova tecnologia. Ela possui a conveniência da pistola com disparos mais rápidos e precisos.\"\n  STR_LASER_RIFLE_UFOPEDIA: \"O rifle laser é uma versão mais poderosa e precisa do projeto de pistola anterior.\"\n  STR_HEAVY_LASER_UFOPEDIA: \"O laser pesado é difícil de manejar, mas extremamente eficaz.\"\n  STR_GRENADE_UFOPEDIA: \"Esta granada padrão tem um temporizador preciso e sofisticado para controle de precisão.\"\n  STR_SMOKE_GRENADE_UFOPEDIA: \"Granadas de fumaça são uteis para gerar cobertura em situações de exposição em combate. Use com cuidado pois elas também podem beneficiar o inimigo.\"\n  STR_PROXIMITY_GRENADE_UFOPEDIA: \"Uma granada de proximidade pode ser jogada como uma granada normal, mas é disparada pelo movimento nas proximidades depois dela cair. É necessária muita habilidade e cuidado para usar esses dispositivos corretamente.\"\n  STR_HIGH_EXPLOSIVE_UFOPEDIA: \"Este explosivo deve ser utilizado apenas para demolição. Mantenha as equipes longe das áreas de demolição.\"\n  STR_MOTION_SCANNER_UFOPEDIA: \"Esse sofisticado aparelho utiliza uma variedade de detectores e avançados algoritmos de computador para identificar unidades inimigas em movimento. Ainda assim é necessário alguma prática para operá-lo de maneira eficiente. Clique no ícone do scanner na tela tática. Selecione 'Usar Scanner' no menu. A tela do scanner mostra uma seta no centro que diz a direção para a qual o soldado está virado (O Norte é para cima). Os círculos que piscam mostram quais unidades se moveram recentemente. Unidades grandes ou velozes produzirão círculos grandes. Unidades paradas não serão detectadas.\"\n  STR_MEDI_KIT_UFOPEDIA: \"O Kit Médico combina utilidades como primeiros socorros além de analgésicos e estimulantes. Para utilizar o kit médico você deve estar virado de frente para a vítima que necessita do tratamento. Se a vítima estiver inconsciente você deve ficar em cima do corpo da mesma. Clique no ícone do kit médico e selecione 'Usar Kit Médico' a partir do menu.{NEWLINE}  CURA> As partes do corpo em vermelho mostram ferimentos fatais. Clique em uma parte do corpo que estiver ferida e clique no botão de 'Cura'. Uma ferida fatal será curada e um pouco da saúde restaurada.{NEWLINE}  ESTIMULANTE> O Estimulante restaurará a energia e despertará vítimas inconscientes. Para despertar uma vítima inconsciente, você deve ficar em cima do corpo da mesma.{NEWLINE}  ANALGÉSICO> O Analgésico restaurará a moral das vítimas feridas até uma quantidade equivalente à sua saúde perdida.\"\n  STR_PSI_AMP_UFOPEDIA: \"O Amplificador Psi só pode ser usado por soldados com habilidade psiônica. Durante o combate, clique sobre o Amplificador Psi, selecione o tipo de ataque, e selecione um alvo com o cursor. Existem dois tipos de ataque psíquico:{NEWLINE}PÂNICO> Se o ataque for bem sucedido, irá reduzir a moral do alvo e pode fazer com que ele entre em pânico.{NEWLINE}CONTROLE DA MENTE> Se este for bem sucedido, então você vai ganhar o controle imediato da unidade inimiga, como se fosse um dos seus próprios. É mais difícil de ser bem sucedido com este tipo de ataque.\"\n  STR_STUN_ROD_UFOPEDIA: \"Este dispositivo só pode ser usado em combates corpo a corpo, mas irá atordoar um organismo vivo sem matá-lo usando choques elétricos.\"\n  STR_MIND_PROBE_UFOPEDIA: \"A sonda mental é um dispositivo de comunicação alienígena que é usado para obter informações diretamente de ondas cerebrais. Unidades X-Com podem usar este dispositivo em combate para exibir características de um alienígena. Clique na sonda mental e na opção 'usar'. Em seguida, clique em um alienígena com o cursor.\"\n  STR_PLASMA_PISTOL_UFOPEDIA: \"Pistolas de Plasma são armas alienígenas letais baseadas em aceleração de partículas a partir de um campo antigravidade minúsculo.\"\n  STR_PLASMA_RIFLE_UFOPEDIA: \"Esta é uma devastadora e poderosa arma baseada em aceleração de partículas a partir de um campo antigravitacional minúsculo.\"\n  STR_HEAVY_PLASMA_UFOPEDIA: \"Esta é uma arma poderosamente devastadora baseada em aceleração de partículas a partir de um campo antigravidade minúsculo.\"\n  STR_BLASTER_LAUNCHER_UFOPEDIA: \"Este é um lançador de mísseis teleguiados alienígena que dispara poderosas Bombas Teleguiadas. Quando você clicar para disparar a arma, ela irá gerar 'pontos guia' para a bomba seguir. Quando você tiver estabelecido pontos suficientes, clique no ícone especial \\\"Lançar Míssil\\\".\"\n  STR_SMALL_LAUNCHER_UFOPEDIA: \"Um pequeno lançador que atira bombas atordoantes. Muito útil para capturar alienígenas vivos.\"\n  STR_ALIEN_GRENADE_UFOPEDIA: \"Este dispositivo funciona da mesma maneira que uma granada terrestre - exceto que é mais poderoso.\"\n  STR_SMALL_SCOUT: \"Batedor Pequeno\"\n  STR_MEDIUM_SCOUT: \"Batedor Médio\"\n  STR_LARGE_SCOUT: \"Batedor Grande\"\n  STR_HARVESTER: \"Colheitadeira\"\n  STR_ABDUCTOR: \"Abdutor\"\n  STR_TERROR_SHIP: \"Nave de Terror\"\n  STR_BATTLESHIP: \"Nave de Batalha\"\n  STR_SUPPLY_SHIP: \"Nave de Suprimento\"\n  STR_RATING: \"AVALIAÇÃO> {0}\"\n  STR_RATING_TERRIBLE: \"TERRÍVEL!\"\n  STR_RATING_POOR: \"RUIM!\"\n  STR_RATING_OK: \"OK\"\n  STR_RATING_GOOD: \"BOM!\"\n  STR_RATING_EXCELLENT: \"EXCELENTE!\"\n  STR_SCORE: \"PONTOS\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"RELATÓRIO MENSAL DO PROJETO X-COM\"\n  STR_MONTH: \"Mês> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"O conselho das nações financiadoras está satisfeito com seu progresso até agora.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"O conselho das nações financiadoras está muito contente com o seu excelente progresso. Continue com o bom trabalho.\"\n  STR_COUNCIL_IS_DISSATISFIED: \"O conselho das nações financiadoras está insatisfeito com seu desempenho. Você deve melhorar sua eficácia em lidar com a ameaça alienígena ou o projeto será encerrado.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"Você não conseguiu lidar com a invasão alienígena e o conselho das nações financiadoras decidiu terminar o projeto. Cada nação lidará com o problema como achar melhor. Só torcemos para que sejamos capazes de nos entender com essas forças aparentemente hostis e que a população chegue a um acordo com estes visitantes alienígenas.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} está particularmente satisfeito com a sua capacidade de lidar com a ameaça localizada e concordou em aumentar o seu financiamento.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} estão particularmente felizes com o seu progresso em lidar com a incursão alienígena local e concordaram em aumentar o seu financiamento.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} e {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} está insatisfeito com a sua habilidade de lidar com as atividades alienígenas em seu território e decidiu reduzir seu patrocínio.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} estão insatisfeitos com a sua habilidade de lidar com as atividades alienígenas em seu território e decidiram reduzir seu patrocínio.\"\n  STR_KNOTS: \"{0} nós\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} assinou um pacto secreto com as forças alienígenas desconhecidas e retirou-se do projeto.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} assinaram um pacto secreto com as forças alienígenas desconhecidas e retiraram-se do projeto.\"\n  STR_MONTHLY_RATING: \"Avaliação Mensal> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Mudanças no financiamento> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"O conselho das nações financiadoras não está feliz com a sua situação financeira. Você deve reduzir seus débitos para menos de $1 milhão ou o projeto será cancelado.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"TRANSMISSÕES DE HIPER-ONDA DECODIFICADAS\"\n  STR_CRAFT_TYPE: \"TIPO DE NAVE\"\n  STR_RACE: \"RAÇA\"\n  STR_MISSION: \"MISSÃO\"\n  STR_ZONE: \"ZONA\"\n  STR_ALLOCATE_RESEARCH: \"Alocar Pesquisa\"\n  STR_ALLOCATE_MANUFACTURE: \"Alocar Produção\"\n  STR_NEW_YORK: \"Nova Iorque\"\n  STR_WASHINGTON: \"Washington\"\n  STR_LOS_ANGELES: \"Los Angeles\"\n  STR_MONTREAL: \"Montreal\"\n  STR_HAVANA: \"Havana\"\n  STR_MEXICO_CITY: \"Cidade do México\"\n  STR_CHICAGO: \"Chicago\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_DALLAS: \"Dallas\"\n  STR_BRASILIA: \"Brasília\"\n  STR_BOGOTA: \"Bogotá\"\n  STR_BUENOS_AIRES: \"Buenos Aires\"\n  STR_SANTIAGO: \"Santiago\"\n  STR_RIO_DE_JANEIRO: \"Rio de Janeiro\"\n  STR_LIMA: \"Lima\"\n  STR_CARACAS: \"Caracas\"\n  STR_LONDON: \"Londres\"\n  STR_PARIS: \"Paris\"\n  STR_BERLIN: \"Berlim\"\n  STR_MOSCOW: \"Moscou\"\n  STR_ROME: \"Roma\"\n  STR_MADRID: \"Madri\"\n  STR_BUDAPEST: \"Budapeste\"\n  STR_LAGOS: \"Lagos\"\n  STR_CAIRO: \"Cairo\"\n  STR_CASABLANCA: \"Casablanca\"\n  STR_PRETORIA: \"Pretória\"\n  STR_NAIROBI: \"Nairóbi\"\n  STR_CAPE_TOWN: \"Cidade do cabo\"\n  STR_KINSHASA: \"Quinxassa\"\n  STR_ANKARA: \"Ancara\"\n  STR_DELHI: \"Déli\"\n  STR_KARACHI: \"Carachi\"\n  STR_BAGHDAD: \"Bagdá\"\n  STR_TEHRAN: \"Teerã\"\n  STR_BOMBAY: \"Bombaim\"\n  STR_CALCUTTA: \"Calcutá\"\n  STR_TOKYO: \"Tóquio\"\n  STR_BEIJING: \"Pequim\"\n  STR_BANGKOK: \"Bancoque\"\n  STR_MANILA: \"Manila\"\n  STR_SEOUL: \"Seul\"\n  STR_SINGAPORE: \"Singapura\"\n  STR_JAKARTA: \"Jacarta\"\n  STR_SHANGHAI: \"Xangai\"\n  STR_HONG_KONG: \"Hong Kong\"\n  STR_NOVOSIBIRSK: \"Novosibirsk\"\n  STR_CANBERRA: \"Camberra\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_MELBOURNE: \"Melbourne\"\n  STR_PERTH: \"Perth\"\n  STR_PSI_TRAINING: \"Treinam. Psi.\"\n  STR_PSIONIC_TRAINING: \"TREINAMENTO PSIÔNICO\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Capacidade do Lab-Psi Restante> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"Força{NEWLINE}Psiônica\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"Habilidade Psiônica{NEWLINE}/Melhora\"\n  STR_PSI_AMP: \"Amp-Psi\"\n  STR_IN_TRAINING: \"Treinando?\"\n  STR_TARGETTED_BY: \"FOCADO EM:\"\n  STR_WEAPONS_CREW_HWPS: \"ARMAS/{NEWLINE}TRIPULAÇÃO/PAPs\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"tem pouco combustível.{NEWLINE}retornando a base\"\n  STR_SOLDIER_LIST: \"Lista de Soldados\"\n  STR_RANK_: \"PATENTE> {ALT}{0}\"\n  STR_MISSIONS: \"MISSÕES> {ALT}{0}\"\n  STR_KILLS: \"MORTES> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"RECUPERAÇÃO EM> {ALT}{0}\"\n  STR_TIME_UNITS: \"UNIDADES DE TEMPO\"\n  STR_STAMINA: \"VIGOR\"\n  STR_HEALTH: \"SAÚDE\"\n  STR_BRAVERY: \"BRAVURA\"\n  STR_REACTIONS: \"REAÇÕES\"\n  STR_FIRING_ACCURACY: \"PRECISÃO DE TIRO\"\n  STR_THROWING_ACCURACY: \"PRECISÃO DE ARREMESSO\"\n  STR_STRENGTH: \"FORÇA\"\n  STR_PSIONIC_STRENGTH: \"FORÇA PSIÔNICA\"\n  STR_PSIONIC_SKILL: \"HABILIDADE PSIÔNICA\"\n  STR_NEW_RANK: \"NOVA PATENTE\"\n  STR_PROMOTIONS: \"Promoções\"\n  STR_SOLDIERS_UC: \"SOLDADOS\"\n  STR_TANK_CANNON_UFOPEDIA: \"As Plataformas de Armas Pesadas (PAP) automatizadas são projetadas para complementar um esquadrão X-Com. A combinação de alto poder de fogo e uma forte armadura faz com que essas unidades sejam valiosas nos combates em campo aberto. Certifique-se que dispõe de Munições de Canhão PAP suficientes para rearmar os tanques. As PAPs são armadas automaticamente quando são atribuídas a um pelotão.\"\n  STR_TANK_ROCKET_LAUNCHER_UFOPEDIA: \"Esta Plataforma de Armas Pesadas (PAP) automatizada possui foguetes poderosos. Ela será devastadora para qualquer inimigo alienígena. Certifique-se de que dispõe de foguetes PAP suficientes nos depósitos.\"\n  STR_TANK_LASER_CANNON_UFOPEDIA: \"Armas laser são muito uteis nas PAPs. Eles combinam um grande poder de fogo e a ausência dos limites de munição que outros tipos de armas possuem.\"\n  STR_HOVERTANK_PLASMA_UFOPEDIA: \"A tecnologia alienígena deus vida nova à PAP. A manobrabilidade do voo e o poder de fogo dos feixes de plasma são uma combinação letal.\"\n  STR_HOVERTANK_LAUNCHER_UFOPEDIA: \"Este levitanque possui um lançador de esferas de fusão que é capaz de imensa destruição. Utilize-o com muito cuidado. Você terá que manufaturar as esferas de fusão para manter essas PAPs municiadas. Uma esfera de fusão é uma arma guiada inteligente. Para dispará-la você seleciona alguns 'pontos guia' com o cursor e por fim clica no ícone de lançar.\"\n  STR_HEAVY_PLASMA_CLIP_UFOPEDIA: \"Esse dispositivo compacto é usado como munição para Arma Pesada de Plasma. Ele contém uma pequena quantidade de Elério.\"\n  STR_PLASMA_RIFLE_CLIP_UFOPEDIA: \"Este pequeno objeto é utilizado como fonte de energia para os rifles de plasma, que são armas médias dos alienígenas. Contém uma pequena quantidade de Elério.\"\n  STR_PLASMA_PISTOL_CLIP_UFOPEDIA: \"Fonte de energia para as pequenas Pistolas de Plasma alienígenas. Contém Elério - a fonte de toda a energia alienígena.\"\n  STR_STUN_BOMB_UFOPEDIA: \"A Bomba de Atordoamento é usada para capturar espécimes humanos vivos, mas também pode ser usada contra a maioria das raças alienígenas. Ela é disparada a partir de um Lançador Pequeno.\"\n  STR_ALIEN_RESEARCH_UFOPEDIA: \"A missão de pesquisa alienígena é usada para coletar dados básicos sobre a Terra e seus habitantes. Pequenos veículos são predominantemente utilizados, com desembarques ocasionais em áreas desertas. Este tipo de atividade alienígena expõe a menor ameaça para o X-Com, com pouca preocupação dos governos ou do público.\"\n  STR_ALIEN_HARVEST_UFOPEDIA: \"Os alienígenas têm muitos usos para a fauna da Terra. Os animais são abduzidos secretamente, e retornam com vários órgãos removidos. Mutilações de gado são predominantemente relatadas juntamente com avistamentos de OVNIs. Este tipo de atividade alienígena causa grande preocupação para os governos e considerável ansiedade entre a população. Esse tipo de atividade ocorre principalmente em terras agrícolas. A teoria por trás da 'colheita alien' sugere que raças alienígenas originalmente 'semearam' o planeta com sua flora e fauna, e agora eles voltaram a fazer a colheita do que semearam.\"\n  STR_ALIEN_ABDUCTION_UFOPEDIA: \"A mais traiçoeira das atividades alienígenas. As abduções alienígenas são amplamente reportadas apesar das tentativas de apagar a experiência da memória de suas vítimas. Os abduzidos relatam terem sido sujeitos a exames físicos humilhantes, inseminações com fetos alienígenas e experimentos genéticos bizarros. O propósito dessas atividades parece ligada as mutações e manipulações do material genético dos próprios alienígenas. Essa atividade causa grande alarde e ocorre em áreas povoadas ou cidades.\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"Os governos da Terra podem ser infiltrados por agentes alienígenas de aparência humana. Isso pode resultar em um contato oficial entre os alienígenas e os escalões mais altos do governo. O clímax dessa atividade é caracterizado por uma intensa movimentação de OVNIs nas imediações de grandes cidades. Os alienígenas tentarão assinar um acordo com um governo da Terra oferecendo conhecimentos de sua tecnologia superior. Em retorno o governo deixaria que os alienígenas conduzam suas atividades sem impedimentos. Essa missão dos alienígenas representa a pior das ameaças ao X-Com. Se um governo aceitar um acordo como esses, seu patrocínio será retirado.\"\n  STR_ALIEN_BASE_UFOPEDIA: \"Alienígenas vão construir bases subterrâneas secretas em locais remotos. Depois de alguns voos iniciais de reconhecimento, em alguma atividade OVNI intensa ocorrerá a construção da base. Estas bases são conhecidas por conter laboratórios experimentais para humanos abduzidos, e materiais para uma maior atividade na região. A presença de bases alienígenas gerará uma grande quantidade de atividade alienígena percebida com a presença de OVNIs. Para localizar uma base, uma nave X-Com deve patrulhar uma área por algumas horas para ter alguma chance de detecção.\"\n  STR_ALIEN_TERROR_UFOPEDIA: \"Quando os alienígenas aterrorizam uma cidade, eles utilizam forças especiais com poderes terríveis. Os civis serão diretamente ameaçados, e os governos serão forçados a evacuar áreas inteiras. O objetivo principal desta atividade é gerar histeria pública suficiente para que os governos ameacem o projeto X-Com.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"Caso os interceptadores do X-Com estejam sendo muito efetivos em abater OVNIs, os alienígenas podem revidar com ataques diretos às bases do X-Com. Mas para isso os alienígenas precisam encontrar uma base do X-Com para poder atacá-la, o que apresenta um risco muito pequeno se os OVNIs forem mantidos longe delas.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"Uma vez que uma base alienígena for construída, ela começa a receber suprimentos, trazidos por uma nave especial. Se uma dessas naves for detectada enquanto aterrissar, então é certo que há uma base alienígena próxima.\"\n  STR_SMALL_SCOUT_UFOPEDIA: \"Esta pequena nave é usada principalmente para o reconhecimento e pesquisa. Ela normalmente precede a chegada de naves de maior porte no início de uma missão alienígena.\"\n  STR_MEDIUM_SCOUT_UFOPEDIA: \"Uma nave batedora de médio porte que não oferece grande perigo as forças da Terrestres. Normalmente precede a vinda de naves maiores durante as missões.\"\n  STR_LARGE_SCOUT_UFOPEDIA: \"Está é a maior nave de reconhecimento alienígena, uma nave de propósito geral que é usada em todo tipo de missão alienígena.\"\n  STR_HARVESTER_UFOPEDIA: \"A Nave Ceifadora tem um alçapão em sua base e está equipada com dispositivos de elevação para transportar o gado ou outros animais. Cortadores a laser são utilizadas para extrair o material desejado e a carcaça é despejada no chão. Há também recipientes de armazenamento para partes do corpo.\"\n  STR_ABDUCTOR_UFOPEDIA: \"Esta nave está equipada com uma sala de exames para a realização de horríveis experimentos em seres humanos. A vítima normalmente é paralisada por poderes telepáticos, mas permanece consciente enquanto está na mesa de operação.\"\n  STR_TERROR_SHIP_UFOPEDIA: \"A Nave de Terror tem uma instalação de confinamento para as grandes armas e criaturas de terror alienígenas. Ela é usada para transportar esses terríveis alienígenas em áreas povoadas.\"\n  STR_BATTLESHIP_UFOPEDIA: \"A Nave de Batalha é a maior e mais poderosa nave alienígena. Ela normalmente é a principal nave de uma missão alienígena, equipada com armas poderosas e numerosos membros de tripulação.\"\n  STR_SUPPLY_SHIP_UFOPEDIA: \"A Nave de Suprimento é usada durante a construção de bases alienígenas ou para o suprimento de bases já existentes. Ela carrega contentores de alimentos e câmaras de reprodução.\"\n  STR_DISMANTLE: \"Demolir\"\n  STR_FACILITY_IN_USE: \"INSTALAÇÃO EM USO\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"NÃO É POSSÍVEL DEMOLIR ESTA INSTALAÇÃO!{SMALLLINE}Todas as instalações da base devem estar ligadas ao elevador de acesso.\"\n  STR_TRANSFER_ITEMS_TO: \"Transferir Itens para {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"NÃO HÁ CONTENTOR DE ALIENÍGENA PARA TRANSFERÊNCIA!{SMALLLINE}Alienígenas vivos precisam de uma instalação contentora para sobreviverem.\"\n  STR_AMOUNT_AT_DESTINATION: \"QUANT. NO{NEWLINE}DESTINO\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"Os alienígenas capturados morreram devido à falta de uma instalação de contenção de alienígenas\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"SEM ACOMODAÇÕES DISPONÍVEIS!{SMALLLINE}A base de destino não tem espaço suficiente nas habitações para a tripulação designada à nave.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"ESPAÇO INSUFICIENTE!{SMALLLINE}A base de destino não tem espaço suficiente para armazenar o equipamento designado para a nave.\"\n  STR_ITEMS_ARRIVING: \"Chegada de Transporte\"\n  STR_DESTINATION_UC: \"DESTINO\"\n  STR_PISTOL: \"Pistola\"\n  STR_PISTOL_CLIP: \"Carregador de Pistola\"\n  STR_RIFLE: \"Rifle\"\n  STR_RIFLE_CLIP: \"Carregador de Rifle\"\n  STR_HEAVY_CANNON: \"Canhão Pesado\"\n  STR_HC_AP_AMMO: \"Munição P para CP\"\n  STR_HC_HE_AMMO: \"Munição E para CP\"\n  STR_HC_I_AMMO: \"Munição I para CP\"\n  STR_AUTO_CANNON: \"Canhão Automático\"\n  STR_AC_AP_AMMO: \"Munição P para CA\"\n  STR_AC_HE_AMMO: \"Munição E para CA\"\n  STR_AC_I_AMMO: \"Munição I para CA\"\n  STR_ROCKET_LAUNCHER: \"Lança-foguetes\"\n  STR_SMALL_ROCKET: \"Foguete Pequeno\"\n  STR_LARGE_ROCKET: \"Foguete Grande\"\n  STR_INCENDIARY_ROCKET: \"Foguete Incendiário\"\n  STR_GRENADE: \"Granada\"\n  STR_SMOKE_GRENADE: \"Granada de Fumaça\"\n  STR_PROXIMITY_GRENADE: \"Granada de Proximidade\"\n  STR_HIGH_EXPLOSIVE: \"Explosivos\"\n  STR_STUN_ROD: \"Bastão de Choque\"\n  STR_HEAVY_PLASMA: \"Plasma Pesado\"\n  STR_HEAVY_PLASMA_CLIP: \"Carregador de Plasma Pesado\"\n  STR_PLASMA_RIFLE: \"Rifle de Plasma\"\n  STR_PLASMA_RIFLE_CLIP: \"Carregador de Rifle de Plasma\"\n  STR_PLASMA_PISTOL: \"Pistola de Plasma\"\n  STR_PLASMA_PISTOL_CLIP: \"Carregador de Pistola de Plasma\"\n  STR_BLASTER_LAUNCHER: \"Lançador Teleguiado\"\n  STR_BLASTER_BOMB: \"Bomba Teleguiada\"\n  STR_SMALL_LAUNCHER: \"Lançador Pequeno\"\n  STR_STUN_BOMB: \"Bomba Atordoante\"\n  STR_ALIEN_GRENADE: \"Granada Alienígena\"\n  STR_ELERIUM_115: \"Elério-115\"\n  STR_MIND_PROBE: \"Sonda Mental\"\n  STR_SECTOID_CORPSE: \"Cadáver de Sectoide\"\n  STR_SNAKEMAN_CORPSE: \"Cadáver de Homem-Cobra\"\n  STR_ETHEREAL_CORPSE: \"Cadáver de Etéreo\"\n  STR_MUTON_CORPSE: \"Cadáver de Muton\"\n  STR_FLOATER_CORPSE: \"Cadáver de Flutuador\"\n  STR_CELATID_CORPSE: \"Cadáver de Celátido\"\n  STR_SILACOID_CORPSE: \"Cadáver de Silacoide\"\n  STR_CHRYSSALID_CORPSE: \"Cadáver de Crisálida\"\n  STR_REAPER_CORPSE: \"Cadáver de Ceifador\"\n  STR_SECTOPOD_CORPSE: \"Destroços de Sectópode\"\n  STR_CYBERDISC_CORPSE: \"Destroços de Ciberdisco\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"Munição insuficiente para equipar a PAP{SMALLLINE}Cada PAP necessita de {0} {1}.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Não há equipamento suficiente para reequipar o esquadrão.\"\n  STR_MARS_CYDONIA_LANDING: \"Marte: Pouso em Cidônia\"\n  STR_MARS_CYDONIA_LANDING_BRIEFING: \"Sua nave Avenger pousou na região de Cidônia na superfície de Marte. Nossas informações indicam que uma das construções piramidais possuem um elevador verde que dá acesso ao complexo subterrâneo. Assim que todos os seus soldados estiverem dentro do elevador aperte o botão de 'abortar missão' e seguir para o próximo estágio.\"\n  STR_MARS_THE_FINAL_ASSAULT: \"Marte: O Ataque Final\"\n  STR_MARS_THE_FINAL_ASSAULT_BRIEFING: \"O elevador pirâmide leva seus soldados cansados da batalha às profundezas abaixo da superfície do planeta. Eles chegam no coração de um grande complexo de túneis e câmaras. O cérebro alienígena está escondido em algum lugar no labirinto. Ele deve ser destruído para que a Terra seja salva da escravidão alienígena.{NEWLINE}{NEWLINE}Boa Sorte!\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Você necessitará pesquisar {NEWLINE}{0}{NEWLINE}para poder produzir {NEWLINE}{1}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"Os alienígenas destruíram uma base desguarnecida: {0}\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"Agentes da X-Com localizaram uma base alienígena em {0}\"\n  STR_STANDOFF: \"DEFENSIVO\"\n  STR_CAUTIOUS_ATTACK: \"ATAQUE CAUTELOSO\"\n  STR_STANDARD_ATTACK: \"ATAQUE PADRÃO\"\n  STR_AGGRESSIVE_ATTACK: \"ATAQUE AGRESSIVO\"\n  STR_DISENGAGING: \"DESISTIR\"\n  STR_UFO_HIT: \"ACERTOU O OVNI!\"\n  STR_UFO_CRASH_LANDS: \"OVNI DERRUBADO!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Só Minimiza em Distância Segura\"\n  STR_UFO_RETURN_FIRE: \"O OVNI ABRIU FOGO!\"\n  STR_INTERCEPTOR_DAMAGED: \">>> INTERCEPTOR DANIFICADO <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> INTERCEPTOR DESTRUÍDO <<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"O OVNI ESCAPOU!\"\n  STR_ALIENS_TERRORISE: \"ALIENÍGENAS ATERRORIZAM\"\n  STR_LONG_RANGE_DETECTION: \"Detecção Longo Alcance\"\n  STR_STORES_UC: \"Depósitos\"\n  STR_DIFFICULTY_LEVEL: \"Nível de Dificuldade\"\n  STR_INTERCEPT: \"INTERCEPTAR\"\n  STR_BASES: \"BASES\"\n  STR_GRAPHS: \"GRÁFICOS\"\n  STR_UFOPAEDIA_UC: \"UFOPÉDIA\"\n  STR_OPTIONS_UC: \"OPÇÕES\"\n  STR_FUNDING_UC: \"FINANÇAS\"\n  STR_5_SECONDS: \"5 Segs\"\n  STR_1_MINUTE: \"1 Min\"\n  STR_5_MINUTES: \"5 Mins\"\n  STR_30_MINUTES: \"30 Mins\"\n  STR_1_HOUR: \"1 Hora\"\n  STR_1_DAY: \"1 Dia\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"Quadro de Desempenho do X-Com\"\n  STR_ENTER_NAME: \"Introduza o Nome\"\n  STR_PERFORMANCE_RATING: \"Classificação de Desempenho\"\n  STR_VICTORY_DATE: \"Data da Vitória\"\n  STR_ELECTRO_FLARE: \"Sinalizador Elétrico\"\n  STR_ELECTRO_FLARE_UFOPEDIA: \"Este dispositivo produz um sinal luminoso brilhante. Ilumina tanto as unidades amigas como​ as inimigas que estão próximas durante as missões noturnas.\"\n  STR_MONTHLY_COSTS: \"Custos Mensais\"\n  STR_CRAFT_RENTAL: \"Aluguel de Aeronave\"\n  STR_SALARIES: \"Salários\"\n  STR_BASE_MAINTENANCE: \"Manutenção da Base\"\n  STR_COST_PER_UNIT: \"Custo por unid.\"\n  STR_QUANTITY: \"Quantidade\"\n  STR_TOTAL: \"Total\"\n  STR_IN_PSIONIC_TRAINING: \"No Treinamento Psiônico\"\n  STR_BLASTER_BOMB_UFOPEDIA: \"Esse dispositivo é um míssil que possui um sistema teleguiado inteligente e é altamente explosivo. É disparado por um Lançador Teleguiado.\"\n  STR_FRONT_ARMOR: \"Blindagem Frontal\"\n  STR_LEFT_ARMOR: \"Blindagem Esquerda\"\n  STR_RIGHT_ARMOR: \"Blindagem Direita\"\n  STR_REAR_ARMOR: \"Blindagem Traseira\"\n  STR_UNDER_ARMOR: \"Blindagem Inferior\"\n  STR_ROUNDS: \"Cartuchos\"\n  STR_UNIT: \"UNIDADE> {0}\"\n  STR_ENERGY: \"ENERGIA\"\n  STR_MORALE: \"MORAL\"\n  STR_ARMOR_: \"ARMADURA> {0}\"\n  STR_FRONT_ARMOR_UC: \"ARMADURA FRONTAL\"\n  STR_LEFT_ARMOR_UC: \"ARMADURA ESQUERDA\"\n  STR_RIGHT_ARMOR_UC: \"ARMADURA DIREITA\"\n  STR_REAR_ARMOR_UC: \"ARMADURA TRASEIRA\"\n  STR_SKILLS: \"HABILIDADES> {0}\"\n  STR_LEVEL: \"NÍVEL> {0}\"\n  STR_HEAD: \"CABEÇA\"\n  STR_TORSO: \"TRONCO\"\n  STR_RIGHT_ARM: \"BRAÇO DIR.\"\n  STR_LEFT_ARM: \"BRAÇO ESQ.\"\n  STR_RIGHT_LEG: \"PERNA DIR.\"\n  STR_LEFT_LEG: \"PERNA ESQ.\"\n  STR_PAIN_KILLER: \"ANALGÉSICO\"\n  STR_STIMULANT: \"ESTIMULANTE\"\n  STR_HEAL: \"CURA\"\n  STR_TIME_UNITS_SHORT: \"UT>{ALT}{0}\"\n  STR_WEIGHT: \"Peso>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"Reaç>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"Hb.Psi>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"Fç.Psi>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Artefato Alienígena\"\n  STR_AMMO_ROUNDS_LEFT: \"MUNIÇÃO:{NEWLINE}TIROS{NEWLINE}RESTANTES={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Analgésico>{ALT}{0}{ALT}{NEWLINE}Estimulante>{ALT}{1}{ALT}{NEWLINE}Cura>{ALT}{2}\"\n  STR_THROW: \"Arremessar\"\n  STR_AUTO_SHOT: \"Tiro Rajada\"\n  STR_SNAP_SHOT: \"Tiro Simples\"\n  STR_AIMED_SHOT: \"Tiro Preciso\"\n  STR_STUN: \"Atordoar\"\n  STR_PRIME_GRENADE: \"Ativar Granada\"\n  STR_USE_SCANNER: \"Usar Scanner\"\n  STR_USE_MEDI_KIT: \"Usar Kit Médico\"\n  STR_LAUNCH_MISSILE: \"Lançar Míssil\"\n  STR_ACCURACY_SHORT: \"Prec>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Unidades de Tempo Insuficientes!\"\n  STR_NOT_ENOUGH_ENERGY: \"Energia Insuficiente!\"\n  STR_NO_ROUNDS_LEFT: \"Cartuchos esgotados!\"\n  STR_NO_AMMUNITION_LOADED: \"Sem Munição Carregada!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Munição Errada para esta Arma!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"A arma já está carregada!\"\n  STR_NO_LINE_OF_FIRE: \"Obstáculo na Linha de Fogo!\"\n  STR_GRENADE_IS_ACTIVATED: \"Granada Ativada!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Granada Desativada!\"\n  STR_THERE_IS_NO_ONE_THERE: \"Não há ninguém aqui!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Não pode usar artefato alienígena sem antes pesquisá-lo!\"\n  STR_OUT_OF_RANGE: \"Fora de Alcance!\"\n  STR_UNABLE_TO_THROW_HERE: \"Não é possível arremessar ali!\"\n  STR_SET_TIMER: \"Ajustar Temporizador\"\n  STR_HIDDEN_MOVEMENT: \"MOVIMENTO OCULTO\"\n  STR_TURN: \"TURNO> {0}\"\n  STR_SIDE: \"LADO> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Pressione o botão para continuar\"\n  STR_MIND_CONTROL: \"Controle da Mente\"\n  STR_PANIC_UNIT: \"Aterrorizar Unidade\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Ataque Moral Bem Sucedido\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Controle da Mente Bem Sucedido\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}teve um frenesi de fúria\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}teve um frenesi de fúria\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}entrou em pânico\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}entrou em pânico\"\n  STR_XCOM: \"UFO\"\n  STR_ALIENS: \"Alienígenas\"\n  STR_RIGHT_HAND: \"MÃO DIR.\"\n  STR_LEFT_HAND: \"MÃO ESQ.\"\n  STR_RIGHT_SHOULDER: \"OMBRO DIR.\"\n  STR_LEFT_SHOULDER: \"OMBRO ESQ.\"\n  STR_BACK_PACK: \"MOCHILA\"\n  STR_BELT: \"CINTO\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}está sob controle alienígena\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}está sob controle alienígena\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}está inconsciente\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}está inconsciente\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}morreu vítima de ferimentos fatais.\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}morreu vítima de ferimentos fatais\"\n  STR_USE_MIND_PROBE: \"Usar Sonda Mental\"\n  STR_FATAL_WOUNDS: \"FERIMENTOS FATAIS\"\n  STR_UNDER_ARMOR_UC: \"ARMADURA INFERIOR\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Unidades de Tempo reservadas para Tiro Simples\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Unidades de Tempo reservadas para Tiro Rajada\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Unidades de Tempo reservadas para Tiro Preciso\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Unidades de Tempo reservados para Ajoelhar\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"Unidades de Tempo reservadas para Ajoelhar e Disparar\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} unidade na nave X-Com.\"\n    many: \"{N} unidades na nave X-Com.\"\n    other: \"{N} unidades na nave X-Com.\"\n  STR_UNITS_OUTSIDE:\n    one: \"Resta {N} unidade do lado de fora.\"\n    many: \"Restam {N} unidades do lado de fora.\"\n    other: \"Restam {N} unidades do lado de fora.\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} unidade na entrada.\"\n    many: \"{N} unidades na entrada.\"\n    other: \"{N} unidades na entrada.\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} unidade na área de saída.\"\n    many: \"{N} unidades na área de saída.\"\n    other: \"{N} unidades na área de saída.\"\n  STR_ABORT_MISSION_QUESTION: \"Abortar Missão?\"\n  STR_CORPSE: \"Cadáver\"\n  STR_UNLOAD_CRAFT: \"Descarregar\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}foi morto\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}foi morta\"\n  STR_HIT_MELEE: \"Acerto\"\n  STR_GROUND: \"CHÃO\"\n  STR_LIVING_QUARTERS_PLURAL: \"Habitações\"\n  STR_LIST_ITEM: \"ITEM\"\n  STR_PERSONAL_ARMOR_UFOPEDIA: \"Usando as ligas metálicas alienígenas recém-descobertas, esta nova armadura dá aos nossos homens uma chance de lutar contra a ameaça alienígena.\"\n  STR_POWER_SUIT_UFOPEDIA: \"Uma poderosa armadura movida por uma fonte de energia de Elério capaz de amplificar muito a velocidade e a força de quem a utiliza. Oferece uma melhor blindagem para suas tropas.\"\n  STR_FLYING_SUIT_UFOPEDIA: \"Uma versão melhorada da Armadura Energizada, incorporando a tecnologia alienígena de navegação antigravitacional que permite total liberdade de movimentos no campo de batalha.\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"Alienígenas mortos no impacto,{NEWLINE}Recuperação automática iniciada\"\n  STR_RESET: \"Inicializar\"\n  STR_MEMORIAL: \"Memorial\"\n  STR_DATE_UC: \"DATA\"\n  STR_SOLDIERS_RECRUITED_UC: \"SOLDADOS RECRUTADOS>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"SOLDADOS PERDIDOS>{ALT}{0}\"\n  MAP_CULTA: \"Fazenda\"\n  MAP_FOREST: \"Floresta\"\n  MAP_JUNGLE: \"Selva\"\n  MAP_MOUNT: \"Montanha\"\n  MAP_DESERT: \"Deserto\"\n  MAP_POLAR: \"Polar\"\n  MAP_URBAN: \"Cidade\"\n  MAP_UBASE: \"Base Alienígena\"\n  MAP_XBASE: \"Base X-COM\"\n  MAP_MARS: \"Marte\"\n  STR_MIXED: \"Misturado\"\n  STR_REMOVE_SELECTED: \"Remover o Selecionado\"\n  STR_LIVE_ALIENS: \"Espécimes{NEWLINE}vivas\"\n  STR_DEAD_ALIENS: \"Espécimes{NEWLINE}mortas\"\n  STR_UNDER_INTERROGATION: \"Sendo{NEWLINE}examinada\"\n  STR_CONTAINMENT_EXCEEDED: \"LIMITES DO CONFINAMENTO ALIENÍGENA EXCEDIDO!{SMALLLINE}Espaço de contenção insuficiente em {0}. Você deve remover o excesso de alienígenas do confinamento (que morrerão, por consequência).\"\n  STR_MANAGE_CONTAINMENT: \"Gerenciar Contentor de Alienígena\"\n  STR_STORAGE_EXCEEDED: \"ESPAÇO DE ARMAZENAMENTO EXCEDIDO!{SMALLLINE}Espaço de armazenamento insuficiente em {0}. Você deve vender itens excedentes.\"\n  STR_GO_TO_BASE: \"Ir para Base\"\n  STR_MELEE_ACCURACY: \"PRECISÃO CORPO-A-CORPO\"\n  STR_SELL_PRODUCTION: \"VENDER\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Ambas as mãos necessitam estar vazias!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Itens insuficientes para copiar modelo!\"\n  STR_UNLOAD_WEAPON: \"Descarregar arma\"\n  STR_ALL_ITEMS: \"Todos os Itens\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"NÃO SÃO PERMITIDOS MAIS EQUIPAMENTOS A BORDO!{SMALLLINE}Só é permitido levar um máximo de {N} item deste equipamento nesta aeronave.\"\n    many: \"NÃO SÃO PERMITIDOS MAIS EQUIPAMENTOS A BORDO!{SMALLLINE}Só é permitido levar um máximo de {N} itens deste equipamento nesta aeronave.\"\n    other: \"NÃO SÃO PERMITIDOS MAIS EQUIPAMENTOS A BORDO!{SMALLLINE}Só é permitido levar um máximo de {N} itens deste equipamento nesta aeronave.\"\n  STR_CONTROL_CENTER_DESTROYED: \"CENTRO DE CONTROLE DESTRUÍDO{NEWLINE}Encaminha-se para a entrada e aborta.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"As bases X-Com não podem ser construídas debaixo da água.\"\n  STR_LEVEL_SHORT: \"{0}\"\n  STR_PERSONNEL: \"Pessoal\"\n  STR_CRAFT_ARMAMENT: \"Veículos e armamento\"\n  STR_COMPONENTS: \"Componentes\"\n  STR_SOLDIERS_RECRUITED: \"Soldados recrutados\"\n  STR_SOLDIERS_LOST: \"Soldados perdidos\"\n  STR_TOTAL_UFOS: \"OVNIs detectados\"\n  STR_TOTAL_ALIEN_BASES: \"Bases alienígenas descobertas\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"FPSI\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"PSI\"\n  FEMALE_CIVILIAN: \"Civil, Feminino\"\n  MALE_CIVILIAN: \"Civil, Masculino\"\n  CYBERDISC_WEAPON: \"Arma do Ciberdisco\"\n  REAPER_WEAPON: \"Arma do Ceifador\"\n  CHRYSSALID_WEAPON: \"Arma do Crisálida\"\n  CELATID_WEAPON: \"Arma do Celátido\"\n  SILACOID_WEAPON: \"Arma do Silacoide\"\n  SECTOPOD_WEAPON: \"Arma do Sectópode\"\n  ZOMBIE_WEAPON: \"Arma do Zumbi\"\n  ALIEN_PSI_WEAPON: \"Arma Psiônica Alienígena\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/pt-PT.yml",
    "content": "pt-PT:\n  STR_AVENGER_UFOPEDIA: \"ESTA NAVE DE COMBATE E TRANSPORTE É UMA APLICAÇÃO PERFEITA DA TECNOLOGIA ALIENÍGENA.\"\n  STR_INTERCEPTOR_UFOPEDIA: \"ESTA AERONAVE DE COMBATE UTILIZA A MELHOR TECNOLOGIA TERRESTRE DISPONÍVEL. É MOVIDA POR DOIS MOTORES DE PULSO-DETONAÇÃO E POSSUÍ SISTEMAS ELETRÓNICOS ESPECIALMENTE PROTEGIDOS.\"\n  STR_LIGHTNING_UFOPEDIA: \"ESTA AERONAVE DE TRANSPORTE E COMBATE É UMA REPRODUÇÃO RUDIMENTAR, MAS EFICAZ DOS SISTEMAS DE PROPULSÃO ALIENÍGENAS.\"\n  STR_SKYRANGER_UFOPEDIA: \"O SKYRANGER É O TRANSPORTE DE TROPAS MAIS RÁPIDO DA SUA CATEGORIA, E POSSUÍ CAPACIDADE DE DESCOLAGEM E ATERRAGEM VERTICAL (V.T.O.L.).\"\n  STR_FIRESTORM_UFOPEDIA: \"ESTA AERONAVE DE COMBATE É UM CAÇA MONOLUGAR QUE REPRODUZ O FORMATO CLÁSSICO DO DISCO VOADOR ALIENÍGENA, COM UMA UNIDADE DE PROPULSÃO CENTRAL.\"\n  STR_STINGRAY_UFOPEDIA: \"ESTE MÍSSIL AR-AR POSSUÍ SISTEMAS ELETRÓNICOS ESPECIALMENTE PROTEGIDOS.\"\n  STR_AVALANCHE_UFOPEDIA: \"ESTE MÍSSIL AR-AR PESADO ESTÁ CARREGADO COM UMA OGIVA NUCLEAR.\"\n  STR_CANNON_UFOPEDIA: \"ESTE PODEROSO CANHÃO DISPARA PROJÉTEIS PERFURANTES, CAPAZES DE PENETRAR ATÉ 40 CM DE AÇO.\"\n  STR_FUSION_BALL_UFOPEDIA: \"ESTE LANÇADOR DISPARA UM PROJÉTIL ESFÉRICO ALIMENTADO POR UMA REAÇÃO DE ANTIMATÉRIA. A BOLA DESTROI O ALVO ATRAVÉS DE UMA IMPLOSÃO GRAVITACIONAL.\"\n  STR_LASER_CANNON_UFOPEDIA: \"ESTE RAIO LASER CONVENCIONAL É ALIMENTADO POR UMA CÂMARA DE REAÇÃO ANTIMATÉRIA.\"\n  STR_PLASMA_BEAM_UFOPEDIA: \"O CANHÃO DE PLASMA DISPARA UM RAIO DE GRAVIDADE QUE PROJETA UMA IMPLOSÃO GRAVITACIONAL ALTAMENTE CONCENTRADA. \"\n  STR_SECTOID_UFOPEDIA: \"A rede de comando sectóide assenta nos soldados e é comandada por líderes detentores de poderosas habilidades psíquicas. Os líderes utilizam estes poderes mentais para desmoralizar ou até para controlar as mentes dos seus inimigos. Esta espécie pratica frequentemente sequestros humanos e mutilação de gado. Os sequestros humanos destinam-se à recolha de material genético para realizar cruzamentos e criar clones para fins de infiltração na sociedade humana. O gado serve tanto para alimentação como para material genético. Crê-se que esta espécie procura desenvolver híbridos genéticos para melhorar a eficiência da sua estrutura social.\"\n  STR_SECTOID_AUTOPSY: \"Autópsia: Sectóide\"\n  STR_SECTOID_AUTOPSY_UFOPEDIA: \"A autópsia revela órgãos digestivos residuais e uma estrutura física muito simples, que sugere mutação ou alteração genética. O cérebro e os olhos são bastante desenvolvidos, mas a boca pequena e o nariz parecem desprovidos de função. As membranas interdigitais das mãos e os pés chatos sugerem origens aquáticas. Como não há traços de órgãos que indiquem como se reproduzem é muito provável que esta seja uma espécie criada geneticamente.\"\n  STR_SNAKEMAN_UFOPEDIA: \"Esta espécie evoluiu num ambiente extremamente hostil. Os Homens-cobra são incrivelmente fortes e capazes de resistir a mudanças extremas de temperatura. Movimentam-se através de um único \\\"membro\\\" gigante, semelhante ao corpo de uma serpente, que contém os seus órgãos vitais. As suas intenções parecem ser exclusivamente predatórias e crê-se que estejam sob o controlo de uma inteligência superior que organiza as suas incursões militares à Terra.\"\n  STR_SNAKEMAN_AUTOPSY: \"Autópsia: Homem-cobra\"\n  STR_SNAKEMAN_AUTOPSY_UFOPEDIA: \"A pele é extremamente rígida e resistente ao calor. O sistema cardiovascular faz parte do sistema muscular, que utiliza o princípio hidráulico para gerar movimento, sendo o único músculo verdadeiro o \\\"coração\\\". O sistema reprodutivo é assexual e aparenta ser bastante eficiente: cada Homem-cobra pode transportar até cinquenta ovos dentro do seu corpo. A propagação desta espécie no nosso planeta poderia ser uma séria ameaça para toda a vida na Terra.\"\n  STR_ETHEREAL_UFOPEDIA: \"Estes seres possuem poderes mentais impressionantes que permitem comunicação telepática e habilidades telecinéticas. Aparentemente, o seu próprio físico débil é sustentado por estas capacidades mentais. Não compreendemos ao certo como funcionam os seus poderes telecinéticos, pois parecem desafiar as próprias leis da física. Como tal, estes seres são extremamente perigosos em qualquer situação de combate, pois os seus poderes mentais podem ser usados de forma ofensiva. Os Etéreos raramente aparecem na Terra, preferindo fazer uso de outras espécies subordinadas para alcançar os seus objetivos.\"\n  STR_ETHEREAL_AUTOPSY: \"Autópsia: Etéreo\"\n  STR_ETHEREAL_AUTOPSY_UFOPEDIA: \"Esta entidade possuí um físico débil que parece ser incapaz de manter quaisquer funções vitais. Os músculos estão muito atrofiados e os órgãos internos parecem subdesenvolvidos. Os órgãos sensoriais, incluindo os olhos, parecem não funcionar de todo. No entanto, o cérebro é muito desenvolvido e utiliza grande parte do fluxo sanguíneo corporal. É um mistério como esta criatura é capaz de se manter viva sem suporte externo.\"\n  STR_MUTON_UFOPEDIA: \"Estas criaturas humanóides são muito fortes e inteligentes, e possuem um gosto especial por carne crua de qualquer espécie, da qual necessitam para sobreviver, tal como os carnívoros terrestres. Os Mutons parecem depender das ordens telepáticas de uma outra espécie alienígena chamada de \\\"Etéreos\\\". Uma vez cortada a ligação telepática, o seu sistema nervoso deixa de funcionar e morrem. Têm vários implantes cibernéticos espalhados por todo o corpo, que servem para melhorar o seu desempenho em situações de combate. Estes seres são obviamente meros peões ao serviço de uma inteligência superior.\"\n  STR_MUTON_AUTOPSY: \"Autópsia: Muton\"\n  STR_MUTON_AUTOPSY_UFOPEDIA: \"A \\\"pele\\\" desta criatura é uma espécie de armadura orgânica que foi postumamente enxertada sobre o seu corpo e aparenta ser particularmente resistente a munições perfurantes. Encontrámos vários implantes cibernéticos espalhados por todo o corpo que servem para melhorar o desempenho do sistema cardiovascular e das capacidades sensoriais da criatura. Os órgãos reprodutores parecem ter sido removidos cirurgicamente. É evidente que estas pobres criaturas são escravos, forçados a uma vida de guerra e de conquista.\"\n  STR_CELATID_UFOPEDIA: \"Esta forma de vida possuí a capacidade misteriosa de flutuar naturalmente. É sensível a ondas cerebrais, sendo capaz de detetar facilmente um ser humano em qualquer sítio. Uma vez identificada a sua vítima, o Celátido pousa no solo e cospe pequenos globos de um veneno extremamente corrosivo. Esta criatura possuí a habilidade de se clonar a um ritmo alarmante. Acompanha regularmente a espécie Muton nas suas incursões.\"\n  STR_CELATID_AUTOPSY: \"Autópsia: Celátido\"\n  STR_CELATID_AUTOPSY_UFOPEDIA: \"O núcleo desta criatura contém um pequeno órgão biomecânico que aparenta ser um sistema de propulsão antigravidade natural. A bolsa de veneno é o maior órgão do corpo e não parece haver nenhuma estrutura cerebral independente. Não encontrámos indícios de um sistema digestivo ou reprodutor. Um outro pequeno órgão contém vários embriões que podem rapidamente dar origem a uma nova criatura.\"\n  STR_SILACOID_UFOPEDIA: \"Esta forma de vida à base de silício é capaz de gerar enormes quantidades de calor. A sua força permite-lhe esmagar rochas para digerir no seu núcleo escaldante. Possui uma inteligência primitiva e é facilmente controlável através de implantes ou por entidades telepáticas. Opera em conjunto com a espécie Muton.\"\n  STR_SILACOID_AUTOPSY: \"Autópsia: Silacóide\"\n  STR_SILACOID_AUTOPSY_UFOPEDIA: \"O núcleo desta criatura é extremamente quente e parece ser a base do seu sistema digestivo. O seu sistema muscular possui uma força e rapidez tremendas. A sua pele rochosa é impregnável ao fogo ou a munições incendiárias.\"\n  STR_CHRYSSALID_UFOPEDIA: \"As suas tenazes são uma arma terrível em combate corpo a corpo. O seu metabolismo elevado e força física concedem-lhe uma velocidade e destreza incríveis. Em vez de matar as suas vítimas, o Crisalídeo injeta um veneno que as transforma em mortos-vivos e deposita um ovo dentro dos seus corpos. Pouco tempo depois de a vítima ter sido injetada, um novo Crisalídeo eclodirá do seu corpo. Estes seres estão associados à espécie dos Homens-cobra.\"\n  STR_CHRYSSALID_AUTOPSY: \"Autópsia: Crisalídeo\"\n  STR_CHRYSSALID_AUTOPSY_UFOPEDIA: \"O exoesqueleto desta criatura é muito resistente, mas parece ser vulnerável a munição explosiva. O seu cérebro é muito desenvolvido e o seu crescimento celular é bastante rápido. Esta criatura transporta cerca de vinte ovos para serem depositados dentro de outros organismos vivos, o que faz dela uma arma biológica de terror extremamente eficaz.\"\n  STR_FLOATER_UFOPEDIA: \"Os Flutuadores desempenham as funções de soldado e de agente terrorista. São predadores natos, desenvolvidos geneticamente e implantados com várias modificações cibernéticas para os tornar em guerreiros formidáveis. A parte inferior do seu corpo, tal como a maioria dos seus órgãos internos, foi removida cirurgicamente e substituída por um sistema de suporte de vida artificial. Este implante contém um sistema antigravidade que lhes permite flutuar de forma mais ou menos estável.\"\n  STR_FLOATER_AUTOPSY: \"Autópsia: Flutuador\"\n  STR_FLOATER_AUTOPSY_UFOPEDIA: \"Esta criatura foi radicalmente alterada através de meios cirúrgicos. O aparelho cibernético que ocupa a maior parte do seu corpo é um sistema de suporte de vida, que substituí o coração, pulmões e sistema digestivo. Isto faz com que estas criaturas sejam capazes de sobreviver em ambientes extremamente hostis. O seu cérebro é mais pequeno que o nosso, mas os seus órgãos sensoriais são altamente desenvolvidos.\"\n  STR_REAPER_UFOPEDIA: \"Este carnívoro bípede possuí maxilares fortes e um apetite voraz. O seu cérebro tem vários implantes que são utilizados para controlar a sua atividade. Os instintos selvagens desta criatura apenas servem para causar destruição e terror. Acompanha frequentemente a espécie dos Flutuadores.\"\n  STR_REAPER_AUTOPSY: \"Autópsia: Devorador\"\n  STR_REAPER_AUTOPSY_UFOPEDIA: \"Esta criatura possuí dois \\\"cérebros\\\" e dois \\\"corações\\\" que lhe permitem manter-se ativa mesmo quando gravemente ferida. No entanto, a sua pelagem exterior é altamente inflamável, o que a torna vulnerável a armas incendiárias. \"\n  STR_SECTOPOD_UFOPEDIA: \"Os Sectópodes são robôs equipados com poderosas armas laser e controlados através de uma ligação telepática pelos seus mestres, os Etéreos. Estes monstros mecânicos são as mais devastadoras armas de terror ao serviço das forças alienígenas.\"\n  STR_SECTOPOD_AUTOPSY: \"Autópsia: Sectópode\"\n  STR_SECTOPOD_AUTOPSY_UFOPEDIA: \"Este robô está construído de forma robusta, com uma blindagem capaz de resistir a todos os tipos de ataque. É especialmente a resistente a armas de plasma. No entanto, os seus sensores parecem ser particularmente vulneráveis a armas laser.\"\n  STR_CYBERDISC_UFOPEDIA: \"Este disco voador em miniatura é uma arma de terror automatizada que está equipado com um raio de plasma. O seu sistema de propulsão antigravidade proporciona-lhe uma grande vantagem no combate em terreno acidentado. As suas diretivas principais são provocar a destruição e o terror ao serviço da espécie Sectóide.\"\n  STR_CYBERDISC_AUTOPSY: \"Autópsia: Ciberdisco\"\n  STR_CYBERDISC_AUTOPSY_UFOPEDIA: \"O Ciberdisco possuí uma blindagem forte e é especialmente resistente a munição explosiva. Infelizmente, o sistema antigravidade está demasiado danificado para compreendermos o seu funcionamento.\"\n  STR_UFO_POWER_SOURCE_UFOPEDIA: \"As naves alienígenas são alimentadas por um reator de antimatéria, que utiliza Elério (elemento 115) para gerar ondas de gravidade e outras formas de energia. A conversão de matéria para energia possui um nível de eficiência de tal forma incrível (99%) que mesmo fragmentos minúsculos de Elério são capazes de gerar enormes quantidades de energia. Este dispositivo de conversão é facilmente fabricável através de ligas alienígenas. \"\n  STR_UFO_NAVIGATION_UFOPEDIA: \"As naves alienígenas utilizam computadores sofisticados para navegar em terra e no espaço. O seu funcionamento é baseado num conjunto de processadores óticos ligados em rede. Os controles são relativamente simples: o navegador controla a direção das ondas de gravidade geradas pela fonte de energia para mover a nave na direção que desejar. Este sistema pode ser facilmente utilizado por humanos e é reproduzível através de ligas alienígenas e outros componentes.\"\n  STR_UFO_CONSTRUCTION_UFOPEDIA: \"As naves alienígenas possuem três componentes principais: uma fonte de energia, um sistema de navegação e uma fuselagem feita a partir de ligas alienígenas. A fuselagem é projetada de forma a facilitar o controle das ondas de gravidade. É também necessária uma pequena quantidade de Elério para alimentar a fonte de energia. Uma vez estudados os princípios de construção e as funções de cada componente, a fabricação destes meios de transporte está ao nosso alcance.\"\n  STR_ALIEN_FOOD_UFOPEDIA: \"Estas câmaras contêm várias enzimas utilizadas para digerir cadáveres de gado e outros animais ou até mesmo de seres humanos. O líquido resultante é consumido como alimento instantâneo, provavelmente injetado diretamente na corrente sanguínea. Este comportamento sugere uma certa dependência do planeta Terra como fonte de alimentos, ou seja, uma relação simbiótica entre a vida terrestre e a sociedade alienígena.    \"\n  STR_ALIEN_REPRODUCTION_UFOPEDIA: \"Estas câmaras contêm fetos alienígenas. O seu aspeto sugere uma dependência exclusiva na reprodução in-vitro. Os nutrientes ricos asseguram o desenvolvimento rápido do feto. Se aplicado em massa este sistema seria capaz de gerar milhares de clones num curto espaço de tempo. O mesmo processo poderia ser facilmente adaptado para seres humanos ou para cruzamentos entre humanos e alienígenas.\"\n  STR_ALIEN_ENTERTAINMENT_UFOPEDIA: \"É muito provável que a função destas esferas seja puramente recreativa. Os circuitos destes aparelhos geram emanações psíquicas que estimulam vários centros nervosos, produzindo um efeito semelhante a drogas alucinogénicas. Este é o único indício que comprova a existência de passatempos culturais ou recreativos na sociedade alienígena.\"\n  STR_ALIEN_SURGERY_UFOPEDIA: \"Este equipamento cirúrgico utiliza bisturis laser para extrair partes do corpo específicas de gado e outros animais. A ocorrência frequente de casos de mutilação de gado deve-se provavelmente a esta prática bizarra. Crê-se que os alienígenas utilizam as partes extraídas para alimentação ou investigação genética.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"Há milhares de casos registados de pessoas que afirmam terem sido raptadas por alienígenas, por vezes consecutivamente. A realidade é bem mais sinistra: as vítimas são raptadas, estudadas e monitorizadas. Os alienígenas extraem o material genético dos melhores espécimes e implantam fetos híbridos entre humanos e alienígenas nas mulheres, que são removidos meses mais tarde. Por enquanto, os motivos sinistros desta prática permanecem desconhecidos.\"\n  STR_ALIEN_ALLOYS_UFOPEDIA: \"Os artefactos alienígenas são construídos a partir de ligas especiais com propriedades únicas. São incrivelmente leves e resistentes, e muito fáceis de moldar através de eletromagnetismo. Estes materiais podem ser reproduzidos e utilizados em vários processos de fabricação.\"\n  STR_ELERIUM_115_UFOPEDIA: \"O Elério-115 possuí a característica invulgar de produzir antimatéria quando bombardeado com certos tipos de partículas, gerando ondas de gravidade e outras formas de energia. Infelizmente este elemento não ocorre naturalmente no nosso sistema solar e não pode ser reproduzido por meios artificiais.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"Travamos uma batalha inútil no nosso planeta. As forças alienígenas são esmagadoras em número e o melhor que conseguimos fazer é retardar o seu progresso. A única esperança para a humanidade é atacar os alienígenas na sua origem. As nossas pesquisas indicam a existência de uma base de operações no nosso sistema solar que os alienígenas descrevem como o centro de uma civilização anterior à humanidade. Temos de localizar esta base o mais depressa possível. No entanto, precisamos de capturar e interrogar um Líder alienígena para obtermos informações mais detalhadas. É provável que encontremos pelo menos um líder numa das naves de maior dimensão.\"\n  STR_THE_MARTIAN_SOLUTION_UFOPEDIA: \"As nossas investigações indicam que a base de operações alienígena está situada em Marte. Esta base está muito bem escondida e contém todas as instalações de manufatura e clonagem essenciais para a continuar a sua infiltração no nosso planeta. Todas estas operações são controladas por uma espécie de computador localizado nesta mesma base. Acreditamos que este é o ponto fraco da sociedade alienígena, ou seja, se conseguirmos eliminar este \\\"cérebro\\\", o resto corpo morrerá com ele. Logo, é essencial continuarmos as nossas pesquisas antes que seja demasiado tarde. Para tal precisamos de capturar um alienígena da mais alta patente, os Comandantes, que residem exclusivamente em bases alienígenas e naves de batalha.\"\n  STR_CYDONIA_OR_BUST_UFOPEDIA: \"Foi-nos esclarecido que as forças alienígenas são controladas através de uma base subterrânea localizada em Cidónia, no planeta Marte. Esta é uma região muito peculiar que apresenta construções piramidais com cinco lados e uma grande formação rochosa semelhante a um rosto humano. Sabemos que a civilização Cidoniana prosperou em Marte há muitos milhões de anos atrás, mas desconhecemos os motivos que levaram ao seu declínio ou qual a sua ligação com a recente atividade alienígena. Seja qual for a razão, é imperativo enviarmos uma força expedicionária a Cidónia, pois a única maneira de derrotar-mos os alienígenas é destruindo o \\\"cérebro-mãe\\\" que os controla. Para tal será necessário equiparmos um Avenger com as armas mais poderosas ao nosso dispor. Não há mais informação que possamos recolher aqui na Terra; só nos resta aguardar o desfecho do assalto final a Cidónia.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"CENTRAR NO LOCAL-TEMPO=5 Segs\"\n  STR_CANCEL_UC: \"CANCELAR\"\n  STR_NONE: \"Nenhum\"\n  STR_UNKNOWN: \"Desconhecido\"\n  STR_POOR: \"Fraco\"\n  STR_AVERAGE: \"Médio\"\n  STR_GOOD: \"Bom\"\n  STR_EXCELLENT: \"Excelente\"\n  STR_BUILD_NEW_BASE_UC: \"CONSTRUIR NOVA BASE\"\n  STR_BASE_INFORMATION: \"INFORMAÇÕES DA BASE\"\n  STR_EQUIP_CRAFT: \"EQUIPAR AERONAVE\"\n  STR_BUILD_FACILITIES: \"CONSTRUIR INSTALAÇÕES\"\n  STR_RESEARCH: \"PESQUISAS\"\n  STR_MANUFACTURE: \"MANUFATURAS\"\n  STR_TRANSFER_UC: \"TRANSFERÊNCIAS\"\n  STR_PURCHASE_RECRUIT: \"COMPRAR/CONTRATAR\"\n  STR_SACK: \"DEMITIR\"\n  STR_SELL_SACK_UC: \"VENDER/DEMITIR\"\n  STR_GEOSCAPE_UC: \"GLOBO\"\n  STR_NAME: \"Nome\"\n  STR_AREA: \"Área\"\n  STR_BUILD_NEW_BASE: \"Construir nova base\"\n  STR_CANCEL: \"Cancelar\"\n  STR_COST_UC: \"VALOR>\"\n  STR_CONSTRUCTION_TIME_UC: \"TEMPO DE CONSTRUÇÃO>\"\n  STR_DAY:\n    one: \"{N} dia\"\n    many: \"{N} dias\"\n    other: \"{N} dias\"\n  STR_HOUR:\n    one: \"{N} hora\"\n    many: \"{N} horas\"\n    other: \"{N} horas\"\n  STR_MAINTENANCE_UC: \"MANUTENÇÃO>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Instalação\"\n  STR_CURRENT_RESEARCH: \"PESQUISAS ATUAIS\"\n  STR_SCIENTISTS_AVAILABLE: \"Cientistas disponíveis>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Cientistas atribuídos>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Espaço de laboratório disponível>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"PROJETO DE INVESTIGAÇÃO\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"CIENTISTAS ATRIBUÍDOS\"\n  STR_PROGRESS: \"PROGRESSO\"\n  STR_NEW_PROJECT: \"Novo projeto\"\n  STR_CANCEL_PROJECT: \"CANCELAR PROJETO\"\n  STR_NEW_RESEARCH_PROJECTS: \"NOVOS PROJETOS DE INVESTIGAÇÃO\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"CIENTISTAS DISPONÍVEIS>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"ESPAÇO DE LABORATÓRIO DISPONÍVEL>{ALT}{0}\"\n  STR_INCREASE: \"Aumentar\"\n  STR_DECREASE: \"Diminuir\"\n  STR_START_PROJECT: \"INICIAR PROJETO\"\n  STR_CURRENT_PRODUCTION: \"PRODUÇÃO ATUAL\"\n  STR_ENGINEERS_AVAILABLE: \"Engenheiros disponíveis>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Engenheiros atribuídos>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Espaço de oficina disponível>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Fundos atuais>{ALT}{0}\"\n  STR_ITEM: \"ITEM\"\n  STR_ENGINEERS__ALLOCATED: \"Engenheiros atribuídos\"\n  STR_UNITS_PRODUCED: \"Unidades produzidas\"\n  STR_TOTAL_TO_PRODUCE: \"Total a produzir\"\n  STR_COST__PER__UNIT: \"Custo{NEWLINE}por{NEWLINE}unidade\"\n  STR_DAYS_HOURS_LEFT: \"Dias/Horas restantes\"\n  STR_NEW_PRODUCTION: \"Nova produção\"\n  STR_PRODUCTION_ITEMS: \"Itens para produção\"\n  STR_CATEGORY: \"CATEGORIA\"\n  STR_START_PRODUCTION: \"INICIAR PRODUÇÃO\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} Horas de trabalho para produzir uma unidade\"\n  STR_COST_PER_UNIT_: \"Valor da unidade>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Espaço de oficina necessário>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"MATERIAIS ESPECIAIS NECESSÁRIOS\"\n  STR_ITEM_REQUIRED: \"ITEM NECESSÁRIO\"\n  STR_UNITS_REQUIRED: \"UNIDADES NECESSÁRIAS\"\n  STR_UNITS_AVAILABLE: \"UNIDADES DISPONÍVEIS\"\n  STR_STOP_PRODUCTION: \"CANCELAR PRODUÇÃO\"\n  STR_ENGINEERS_AVAILABLE_UC: \"ENGENHEIROS DISPONÍVEIS>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"ESPAÇO DE OFICINA DISPONÍVEL>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"LUCRO MENSAL>{ALT}[0}\"\n  STR_INCREASE_UC: \"AUMENTAR\"\n  STR_DECREASE_UC: \"DIMINUIR\"\n  STR_UNITS_TO_PRODUCE: \"Unidades a produzir\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Comprar/Contratar\"\n  STR_COST_OF_PURCHASES: \"Valor total>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"VALOR P/ UNIDADE\"\n  STR_QUANTITY_UC: \"QUANTIDADE\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"PESSOAL DISPONÍVEL:PESSOAL TOTAL>\"\n  STR_SOLDIERS: \"Soldados\"\n  STR_SCIENTISTS: \"Cientistas\"\n  STR_ENGINEERS: \"Engenheiros\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"ESPAÇO USADO:ESPAÇO DISPONÍVEL>\"\n  STR_LIVING_QUARTERS: \"Bloco habitacional\"\n  STR_STORES: \"Armazéns\"\n  STR_LABORATORIES: \"Laboratórios\"\n  STR_WORK_SHOPS: \"Oficinas\"\n  STR_HANGARS: \"Hangares\"\n  STR_SHORT_RANGE_DETECTION: \"Deteção de curto alcance\"\n  STR_DEFENSE_STRENGTH: \"Defesas\"\n  STR_TRANSFERS_UC: \"TRANSFERÊNCIAS\"\n  STR_TRANSFERS: \"Transferências\"\n  STR_ARRIVAL_TIME_HOURS: \"Hora de chegada\"\n  STR_COST_: \"Valor>{ALT}{0}\"\n  STR_AREA_: \"Área>{ALT}{0}\"\n  STR_BASE_NAME: \"Nome da base?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"SELECIONAR POSIÇÃO PARA O ELEVADOR DE ACESSO\"\n  STR_TRANSFER: \"Transferir\"\n  STR_AMOUNT_TO_TRANSFER: \"QUANTIDADE A TRANSFERIR\"\n  STR_SELECT_DESTINATION_BASE: \"Selecionar base de destino\"\n  STR_COST: \"Valor\"\n  STR_VICTORY_1: \"Ao entrarem na câmara, as nossas tropas avistam imediatamente o cérebro alienígena - o alvo da nossa missão. Mas antes de abrirem fogo o cérebro comunica através de um ecrã na sua base, implorando que escutemos os seus argumentos para que o deixemos vivo.\"\n  STR_VICTORY_2: \"Então o cérebro diz: \\\"Há muitos milhões de anos, este planeta a que chamais de Marte foi outrora repleto de vida. Vida essa que foi trazida de outro planeta pela nossa civilização e que foi postumamente levada para o vosso. Fomos nós que, ao longo de milhões de anos, visitámos o vosso planeta e desenvolvemos geneticamente a vossa espécie. Não podeis matar-nos porque sois parte de nós.\"\n  STR_VICTORY_3: \"Estas pirâmides são o núcleo da civilização marciana, construídas milhões de anos antes das que tendes na Terra, por uma espécie nossa antepassada. Nenhum planeta está fora do nosso alcance. Este poder poderá vir a ser vosso. Em troca só pedimos a vossa cooperação...\"\n  STR_GAME_OVER_1: \"Os alienígenas tentam exterminar toda a humanidade, destruindo cidades e envenenando o ar e a água. A resistência dos exércitos terrestres é inútil face à superioridade tecnológica dos alienígenas. As gerações sobreviventes à guerra sofrem terríveis mutações enquanto tentam escapar à destruição. Após capturados, os humanos restantes são levados para campos de trabalho para ajudarem a transformar a Terra numa colónia alienígena, parte de um império desconhecido.\"\n  STR_GAME_OVER_2: \"O conhecimento adquirido pelo projeto X-Com foi perdido para sempre. Não conseguimos salvar a Terra. Falhámos a nossa missão.\"\n  STR_VICTORY_4: \"O discurso do cérebro alienígena é subitamente interrompido por uma rajada de plasma. As forças alienígenas foram derrotadas.\"\n  STR_VICTORY_5: \"Após a queda de Marte, os alienígenas perderam a batalha pela Terra. Alguns anos mais tarde a tecnologia capturada pelo projeto X-Com conduz a humanidade a uma nova idade de ouro e à colonização do planeta vermelho. A ameaça alienígena foi repelida, mas por quanto tempo ninguém sabe... \"\n  STR_YOU_HAVE_FAILED: \"Não conseguiu travar a ameaça alienígena. Uma a uma, as nações financiadoras assinam pactos com os alienígenas em troca de tecnologia, paz e prosperidade. No entanto, cedo se apercebem de que os alienígenas têm outros planos...\"\n  STR_TOTAL_UC: \"TOTAL\"\n  STR_INCOME: \"Rendimento\"\n  STR_EXPENDITURE: \"Despesa\"\n  STR_MAINTENANCE: \"Manutenção\"\n  STR_BALANCE: \"Balanço\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"Atividade OVNI por área\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"Atividade OVNI por país\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"Atividade X-Com por área\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"Atividade X-Com por país\"\n  STR_FINANCE: \"Finanças\"\n  STR_DATE_FIRST: \"{0}\"\n  STR_DATE_SECOND: \"{0}\"\n  STR_DATE_THIRD: \"{0}\"\n  STR_DATE_FOURTH: \"{0}\"\n  STR_FINANCE_THOUSANDS: \"$1000\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Não há materiais especiais suficientes para produzir:{NEWLINE}{0}{NEWLINE}em{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Não há dinheiro suficiente para produzir:{NEWLINE}{0}{NEWLINE}em{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"A produção de:{NEWLINE}{0}{NEWLINE}em{NEWLINE}{1}{NEWLINE}está completa\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"A construção de:{NEWLINE}{0}{NEWLINE}em{NEWLINE}{1}{NEWLINE}está completa\"\n  STR_OK_5_SECONDS: \"OK - 5 segs\"\n  STR_RESEARCH_COMPLETED: \"Investigação completa\"\n  STR_VIEW_REPORTS: \"VER RELATÓRIOS\"\n  STR_WE_CAN_NOW_RESEARCH: \"Nova investigação disponível\"\n  STR_WE_CAN_NOW_PRODUCE: \"Nova produção disponível\"\n  STR_SUNDAY: \"DOMINGO\"\n  STR_MONDAY: \"SEGUNDA\"\n  STR_TUESDAY: \"TERÇA\"\n  STR_WEDNESDAY: \"QUARTA\"\n  STR_THURSDAY: \"QUINTA\"\n  STR_FRIDAY: \"SEXTA\"\n  STR_SATURDAY: \"SÁBADO\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Não há {0} suficiente para reabastecer {1} em {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Não há {0} para rearmar {1} em {2}\"\n  STR_UFO_IS_NOT_RECOVERED: \"O OVNI não foi recuperado\"\n  STR_UFO_IS_RECOVERED: \"OVNI recuperado\"\n  STR_CRAFT_IS_LOST: \"Nave perdida\"\n  STR_TERROR_CONTINUES: \"O terror continua\"\n  STR_ALIENS_DEFEATED: \"Os alienígenas foram derrotados\"\n  STR_BASE_IS_LOST: \"A nossa base foi destruída\"\n  STR_BASE_IS_SAVED: \"Base defendida com sucesso\"\n  STR_ALIEN_BASE_STILL_INTACT: \"A base continua operacional\"\n  STR_ALIEN_BASE_DESTROYED: \"A base alienígena foi destruída\"\n  STR_ALIENS_KILLED: \"ALIENÍGENAS MORTOS\"\n  STR_ALIEN_CORPSES_RECOVERED: \"CADÁVERES ALIENÍGENAS RECUPERADOS\"\n  STR_LIVE_ALIENS_RECOVERED: \"ALIENÍGENAS VIVOS CAPTURADOS\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"ARTEFACTOS ALIENÍGENAS RECUPERADOS\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"COMANDO DA BASE ALIENÍGENA DESTRUÍDO\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"CIVIS MORTOS POR ALIENÍGENAS\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"CIVIS MORTOS POR AGENTES X-COM\"\n  STR_CIVILIANS_SAVED: \"CIVIS RESGATADOS\"\n  STR_XCOM_OPERATIVES_KILLED: \"AGENTES X-COM MORTOS EM COMBATE\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"AGENTES X-COM DESAPARECIDOS EM COMBATE\"\n  STR_TANKS_DESTROYED: \"TANQUES DESTRUÍDOS\"\n  STR_XCOM_CRAFT_LOST: \"AERONAVE X-COM PERDIDA\"\n  STR_UFO_RECOVERY: \"RECUPERAÇÃO DE OVNI\"\n  STR_ALIEN_BASE_RECOVERY: \"RECUPERAÇÃO DE BASE ALIENÍGENA\"\n  STR_BASE_UNDER_ATTACK: \"{0} está sob ataque!\"\n  STR_BASE_DEFENSES_INITIATED: \"SISTEMAS DE DEFESA ATIVADOS\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"O ESCUDO DE GRAVIDADE REPELIU O OVNI!\"\n  STR_FIRING: \"A DISPARAR\"\n  STR_HIT: \"ALVO ATINGIDO!\"\n  STR_UFO_DESTROYED: \"OVNI DESTRUÍDO!\"\n  STR_MISSED: \"FALHOU!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Vender itens/Demitir pessoal\"\n  STR_VALUE_OF_SALES: \"VALOR DAS VENDAS> {ALT}{0}\"\n  STR_FUNDS: \"FUNDOS>{ALT}{0}\"\n  STR_SELL_SACK: \"Vender/Demitir\"\n  STR_VALUE: \"Valor\"\n  STR_CRAFT_: \"AERONAVE> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"RECUPERAÇÃO DE OVNI ABATIDO\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"Temos de proceder com cautela. É provável que hajam agentes alienígenas no interior do OVNI ou nas proximidades do local de queda. A missão será bem-sucedida quando todas as unidades inimigas forem eliminadas ou neutralizadas. Só depois poderemos iniciar a recuperação dos restos do OVNI, artefactos e cadáveres de alienígenas. Para abortar a missão, retorne os agentes X-Com ao veículo de transporte e clique no ícone \\\"Abortar missão\\\".\"\n  STR_UFO_GROUND_ASSAULT: \"ASSALTO A LOCAL DE ATERRAGEM\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"O objetivo desta missão é explorar o local de aterragem e, se possível, conseguir aceder ao OVNI. A missão será bem-sucedida quando todas as unidades inimigas forem eliminadas ou neutralizadas. Só depois poderemos iniciar a recuperação dos destroços do OVNI, artefactos e cadáveres de alienígenas. Para abortar a missão, retorne os agentes X-Com ao veículo de transporte e clique no ícone \\\"Abortar missão\\\".\"\n  STR_BASE_DEFENSE: \"DEFESA DE BASE\"\n  STR_BASE_UC_: \"BASE> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"Uma nave alienígena aterrou nas proximidades. A nossa base está em sério perigo. Todas as aeronaves X-Com e o pessoal não-militar foram evacuados conforme o protocolo. As tropas alienígenas entrarão na base através dos hangares ou do elevador de acesso. Temos de defender a base e as suas instalações vitais a todo o custo num combate até à morte. Se clicar no ícone \\\"Abortar missão\\\" as nossas tropas render-se-ão e a base será destruída.\"\n  STR_ALIEN_BASE_ASSAULT: \"ASSALTO A BASE ALIENÍGENA\"\n  STR_ALIEN_BASE_ASSAULT_BRIEFING: \"Os agentes X-Com conseguiram aceder à base alienígena. Para a desativar temos de destruir o  centro de comando. A missão terminará quando todos os inimigos forem eliminados ou quando as nossas tropas regressarem à zona verde de saída (clique no ícone \\\"Abortar missão\\\" para retirar).\"\n  STR_CYDONIA_BRIEFING: \"Chegámos a Cidónia. As nossas tropas entram num enorme complexo subterrâneo perto do Rosto de Marte. Temos de destruir o cérebro que controla toda a atividade alienígena. O destino da humanidade está nas nossas mãos...\"\n  STR_TERROR_MISSION: \"MISSÃO DE TERROR\"\n  STR_TERROR_MISSION_BRIEFING: \"A missão será bem-sucedida quando todas as unidades inimigas forem eliminadas ou neutralizadas. Temos de neutralizar todas as forças alienígenas para salvar os civis que se encontrem na zona. Para abortar a missão, retorne os agentes X-Com ao veículo de transporte e clique no ícone \\\"Abortar missão\\\".\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"NÃO HÁ HANGARES LIVRES PARA A PRODUÇÃO!{SMALLLINE}Cada nave atribuída a uma base, transferida, comprada ou construída ocupa um hangar.  Construa um novo hangar ou transfira uma nave para outra base.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"NÃO HÁ HANGARES LIVRES PARA EFETUAR A COMPRA!{SMALLLINE}Cada nave atribuída a uma base, transferida, comprada ou construída ocupa um hangar.  Construa um novo hangar ou transfira uma nave para outra base.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"NÃO HÁ HANGARES LIVRES PARA A TRANSFERÊNCIA!{SMALLLINE}Cada nave atribuída a uma base, transferida, comprada ou construída ocupa um hangar.  Construa um novo hangar ou transfira uma nave para outra base.\"\n  STR_CANNOT_BUILD_HERE: \"IMPOSSÍVEL CONSTRUIR AQUI!{SMALLLINE}Todas as construções devem ser feitas ao lado de uma instalação existente.\"\n  STR_NO_FREE_ACCOMODATION: \"NÃO HÁ HABITAÇÕES LIVRES!{SMALLLINE}A base de destino não tem espaço suficiente nos blocos habitacionais.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"NÃO HÁ ESPAÇO DE TRABALHO SUFICIENTE!{SMALLLINE}Construa uma nova oficina ou reduza o trabalho noutros projetos.\"\n  STR_NOT_ENOUGH_MONEY: \"NÃO TEM DINHEIRO SUFICIENTE!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"NÃO HÁ ESPAÇO EM ARMAZÉM SUFICIENTE!{SMALLLINE}Construa um novo armazém ou transfira equipamento para outras bases.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"NÃO HÁ HABITAÇÕES SUFICIENTES{SMALLLINE}Construa um novo bloco habitacional ou transfira pessoal para outras bases.\"\n  STR_LAUNCH_INTERCEPTION: \"LANÇAR INTERCEÇÃO\"\n  STR_CRAFT: \"AERONAVE\"\n  STR_STATUS: \"ESTADO\"\n  STR_BASE: \"BASE\"\n  STR_READY: \"PRONTO\"\n  STR_OUT: \"FORA\"\n  STR_REPAIRS: \"A REPARAR\"\n  STR_REFUELLING: \"A REABASTECER\"\n  STR_REARMING: \"A REARMAR\"\n  STR_TARGET: \"ALVO: {0}\"\n  STR_WAY_POINT: \"PONTO DE REFERÊNCIA\"\n  STR_ARE_YOU_SURE_CYDONIA: \"Tem a certeza de que deseja enviar esta nave numa missão a Cidónia?\"\n  STR_YES: \"SIM\"\n  STR_NO: \"NÃO\"\n  STR_SELECT_DESTINATION: \"SELECIONAR DESTINO\"\n  STR_CYDONIA: \"CIDÓNIA\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"SELECIONAR LOCAL PARA A NOVA BASE\"\n  STR_RETURN_TO_BASE: \"REGRESSAR À BASE\"\n  STR_SELECT_NEW_TARGET: \"SELECIONAR NOVO ALVO\"\n  STR_PATROL: \"PATRULHAR\"\n  STR_STATUS_: \"ESTADO>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"DANIFICADA - A REGRESSAR À BASE\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"POUCO COMBUSTÍVEL - A REGRESSAR À BASE\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"MISSÃO COMPLETA - A REGRESSAR À BASE\"\n  STR_PATROLLING: \"EM PATRULHA\"\n  STR_TAILING_UFO: \"A PERSEGUIR OVNI\"\n  STR_INTERCEPTING_UFO: \"A INTERCEPTAR OVNI-{0}\"\n  STR_RETURNING_TO_BASE: \"A REGRESSAR À BASE\"\n  STR_DESTINATION_UC_: \"DESTINO: {0}\"\n  STR_BASE_UC: \"BASE>{ALT}{0}\"\n  STR_SPEED_: \"VELOCIDADE>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"VELOCIDADE MÁXIMA>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"ALTITUDE>{ALT}{0}\"\n  STR_VERY_LOW: \"MUITO BAIXA\"\n  STR_LOW_UC: \"BAIXA\"\n  STR_HIGH_UC: \"ALTA\"\n  STR_VERY_HIGH: \"MUITO ALTA\"\n  STR_FUEL: \"COMBUSTÍVEL>{ALT}{0}\"\n  STR_WEAPON_ONE: \"ARMA-1>{ALT}{0}\"\n  STR_NONE_UC: \"NENHUMA\"\n  STR_ROUNDS_: \"MUNIÇÃO>{ALT}{0}\"\n  STR_WEAPON_TWO: \"ARMA-2>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"AERONAVES DE INTERCEÇÃO\"\n  STR_BASE_: \"Base>{0}\"\n  STR_NAME_UC: \"NOME\"\n  STR_AMMO_: \"MUNIÇÃO>{ALT}{0}\"\n  STR_CREW: \"TRIPULAÇÃO\"\n  STR_EQUIPMENT_UC: \"EQUIPAMENTO\"\n  STR_ARMOR: \"ARMADURA\"\n  STR_MAX: \"MÁX>{ALT}{0}\"\n  STR_ROOKIE: \"Recruta\"\n  STR_SQUADDIE: \"Cabo\"\n  STR_SERGEANT: \"Sargento\"\n  STR_CAPTAIN: \"Capitão\"\n  STR_COLONEL: \"Coronel\"\n  STR_COMMANDER: \"Comandante\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"{0}: selecionar tropas\"\n  STR_SORT_BY: \"ORGANIZAR POR...\"\n  STR_ORIGINAL_ORDER: \"ORDEM ORIGINAL\"\n  STR_MISSIONS2: \"MISSÕES\"\n  STR_KILLS2: \"MORTOS\"\n  STR_WOUND_RECOVERY2: \"EM RECUPERAÇÃO\"\n  STR_SPACE_AVAILABLE: \"ESPAÇO DISPONÍVEL>{ALT}{0}\"\n  STR_SPACE_USED: \"ESPAÇO UTILIZADO>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"ESPAÇO USADO\"\n  STR_RANK: \"POSTO\"\n  STR_WOUNDED: \"FERIDO\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Equipar {0}\"\n  STR_DEFENSE_VALUE: \"Pontos de defesa\"\n  STR_HIT_RATIO: \"Precisão de fogo\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}pronto a aterrar{NEWLINE}perto de{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"Iniciar missão?\"\n  STR_SELECT_ARMAMENT: \"Selecionar armamento\"\n  STR_AMMUNITION_AVAILABLE: \"MUNIÇÃO DISPONÍVEL\"\n  STR_ARMAMENT: \"ARMAMENTO\"\n  STR_NOT_AVAILABLE: \"N.D.\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"SELECIONAR ARMADURA PARA{NEWLINE}{0}\"\n  STR_TYPE: \"TIPO\"\n  STR_PERSONAL_ARMOR_UC: \"ARMADURA PESSOAL\"\n  STR_POWER_SUIT_UC: \"ARMADURA MECÂNICA\"\n  STR_FLYING_SUIT_UC: \"ARMADURA VOADORA\"\n  STR_SELECT_ARMOR: \"Selecionar armadura\"\n  STR_NORTH: \"NORTE\"\n  STR_NORTH_EAST: \"NORDESTE\"\n  STR_EAST: \"ESTE\"\n  STR_SOUTH_EAST: \"SUDESTE\"\n  STR_SOUTH: \"SUL\"\n  STR_SOUTH_WEST: \"SUDOESTE\"\n  STR_WEST: \"OESTE\"\n  STR_NORTH_WEST: \"NOROESTE\"\n  STR_SELECT_ACTION: \"SELECIONAR AÇÃO\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"CONTINUAR PERSEGUIÇÃO E INTERCETAR\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"PERSEGUIR SEM INTERCEÇÃO\"\n  STR_VERY_LARGE: \"MUITO GRANDE\"\n  STR_LARGE: \"GRANDE\"\n  STR_MEDIUM_UC: \"MÉDIO\"\n  STR_SMALL: \"PEQUENO\"\n  STR_VERY_SMALL: \"MUITO PEQUENO\"\n  STR_GROUNDED: \"EM TERRA\"\n  STR_DETECTED: \"Detetado\"\n  STR_SIZE_UC: \"TAMANHO\"\n  STR_ALTITUDE: \"ALTITUDE\"\n  STR_HEADING: \"DIREÇÃO\"\n  STR_SPEED: \"VELOCIDADE\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"CENTRAR EM OVNI-TEMPO=5 Segs\"\n  STR_TRACKING_LOST: \"ALVO PERDIDO\"\n  STR_REDIRECT_CRAFT: \"REDIRECIONAR AERONAVE\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"IR PARA A ÚLTIMA LOCALIZAÇÃO DO ALVO\"\n  STR_UFO_: \"OVNI-{0}\"\n  STR_ALIEN_BASE_: \"BASE ALIENÍGENA-{0}\"\n  STR_CRASH_SITE_: \"LOCAL DE QUEDA-{0}\"\n  STR_LANDING_SITE_: \"LOCAL DE ATERRAGEM-{0}\"\n  STR_WAY_POINT_: \"PONTO DE REFERÊNCIA-{0}\"\n  STR_TERROR_SITE: \"LOCAL DE TERROR-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}chegou a{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"A patrulhar\"\n  STR_ALIEN_ORIGINS: \"Origens alienígenas\"\n  STR_THE_MARTIAN_SOLUTION: \"A solução marciana\"\n  STR_CYDONIA_OR_BUST: \"Cidónia: destino final\"\n  STR_UFOPAEDIA: \"OVNIpédia\"\n  STR_XCOM_CRAFT_ARMAMENT: \"AERONAVES E ARMAMENTO X-COM\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"PLATAFORMAS DE ARMAS PESADAS\"\n  STR_WEAPONS_AND_EQUIPMENT: \"ARMAS E EQUIPAMENTO\"\n  STR_ALIEN_ARTIFACTS: \"ARTEFACTOS ALIENÍGENAS\"\n  STR_BASE_FACILITIES: \"INSTALAÇÕES X-COM\"\n  STR_ALIEN_LIFE_FORMS: \"FORMAS DE VIDA ALIENÍGENA\"\n  STR_ALIEN_RESEARCH_UC: \"INVESTIGAÇÃO ALIENÍGENA\"\n  STR_UFO_COMPONENTS: \"COMPONENTES DE OVNI\"\n  STR_UFOS: \"TIPOS DE OVNI\"\n  STR_SELECT_ITEM: \"SELECIONAR ITEM\"\n  STR_ACCELERATION: \"ACELERAÇÃO>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"CAPACIDADE DE COMBUSTÍVEL>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"SISTEMAS DE ARMAS>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"BLINDAGEM>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"ESPAÇO PARA CARGA>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"SUPORTE PARA PAPs>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Dano\"\n  STR_RANGE: \"Alcance\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Precisão\"\n  STR_RE_LOAD_TIME: \"Intervalo de fogo\"\n  STR_SECONDS: \"{0}s\"\n  STR_DAMAGE_ARMOR_PIERCING: \"PERFURANTE\"\n  STR_DAMAGE_INCENDIARY: \"INCENDIÁRIO\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"EXPLOSIVO\"\n  STR_DAMAGE_LASER_BEAM: \"RAIO LASER\"\n  STR_DAMAGE_PLASMA_BEAM: \"RAIO DE PLASMA\"\n  STR_DAMAGE_STUN: \"ATORDOAMENTO\"\n  STR_DAMAGE_MELEE: \"CORPO A CORPO\"\n  STR_DAMAGE_ACID: \"ÁCIDO\"\n  STR_DAMAGE_SMOKE: \"FUMO\"\n  STR_SHOT_TYPE: \"MODOS DE TIRO\"\n  STR_ACCURACY_UC: \"PRECISÃO\"\n  STR_TIME_UNIT_COST: \"UTs\"\n  STR_DAMAGE_UC: \"TIPO DE DANO\"\n  STR_AMMO: \"MUNIÇÃO\"\n  STR_SHOT_TYPE_AUTO: \"Rajada\"\n  STR_SHOT_TYPE_SNAP: \"Simples\"\n  STR_SHOT_TYPE_AIMED: \"Preciso\"\n  STR_CONSTRUCTION_TIME: \"Tempo de construção\"\n  STR_CONSTRUCTION_COST: \"Valor de construção\"\n  STR_MAINTENANCE_COST: \"Custo de manutenção\"\n  STR_LOW: \"Baixo\"\n  STR_MEDIUM: \"Médio\"\n  STR_HIGH: \"Alto\"\n  STR_CRAFT_WEAPON: \"Armamento para aeronaves\"\n  STR_CRAFT_AMMUNITION: \"Munição para aeronaves\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Plataforma de armas pesadas\"\n  STR_WEAPON: \"Arma\"\n  STR_AMMUNITION: \"Munição\"\n  STR_EQUIPMENT: \"Equipamento\"\n  STR_ALIEN_CORPSE: \"Cadáver Alienígena\"\n  STR_UFO_COMPONENT: \"Componente OVNI\"\n  STR_PERSONAL_ARMOR: \"Armadura pessoal\"\n  STR_RAW_MATERIALS: \"Matéria-prima\"\n  STR_HWP_CANNON_SHELLS: \"Munição de canhão PAP\"\n  STR_ALIEN: \"Alienígena\"\n  STR_SECTOID: \"Sectóide\"\n  STR_SNAKEMAN: \"Homem-cobra\"\n  STR_ETHEREAL: \"Etéreo\"\n  STR_MUTON: \"Muton\"\n  STR_FLOATER: \"Flutuador\"\n  STR_CELATID: \"Celátido\"\n  STR_SILACOID: \"Silacóide\"\n  STR_CHRYSSALID: \"Crisalídeo\"\n  STR_ZOMBIE: \"Zombie\"\n  STR_REAPER: \"Devorador\"\n  STR_SECTOPOD: \"Sectópode\"\n  STR_CYBERDISC: \"Ciberdisco\"\n  STR_LIVE_COMMANDER: \"Comandante\"\n  STR_LIVE_LEADER: \"Líder\"\n  STR_LIVE_ENGINEER: \"Engenheiro\"\n  STR_LIVE_MEDIC: \"Médico\"\n  STR_LIVE_NAVIGATOR: \"Navegador\"\n  STR_LIVE_SOLDIER: \"Soldado\"\n  STR_LIVE_TERRORIST: \"Agente terrorista\"\n  STR_FLOATER_SOLDIER: \"Soldado Flutuador\"\n  STR_FLOATER_NAVIGATOR: \"Navegador Flutuador\"\n  STR_FLOATER_MEDIC: \"Médico Flutuador\"\n  STR_FLOATER_ENGINEER: \"Engenheiro Flutuador\"\n  STR_FLOATER_LEADER: \"Líder Flutuador\"\n  STR_FLOATER_COMMANDER: \"Comandante Flutuador\"\n  STR_SECTOID_SOLDIER: \"Soldado Sectóide\"\n  STR_SECTOID_NAVIGATOR: \"Navegador Sectóide\"\n  STR_SECTOID_MEDIC: \"Médico Sectóide\"\n  STR_SECTOID_ENGINEER: \"Engenheiro Sectóide\"\n  STR_SECTOID_LEADER: \"Líder Sectóide\"\n  STR_SECTOID_COMMANDER: \"Comandante Sectóide\"\n  STR_SNAKEMAN_SOLDIER: \"Soldado Homem-cobra\"\n  STR_SNAKEMAN_NAVIGATOR: \"Navegador Homem-cobra\"\n  STR_SNAKEMAN_ENGINEER: \"Engenheiro Homem-cobra\"\n  STR_SNAKEMAN_LEADER: \"Líder Homem-cobra\"\n  STR_SNAKEMAN_COMMANDER: \"Comandante Homem-cobra\"\n  STR_MUTON_SOLDIER: \"Soldado Muton\"\n  STR_MUTON_NAVIGATOR: \"Navegador Muton\"\n  STR_MUTON_ENGINEER: \"Engenheiro Muton\"\n  STR_ETHEREAL_SOLDIER: \"Soldado Etéreo\"\n  STR_ETHEREAL_LEADER: \"Líder Etéreo\"\n  STR_ETHEREAL_COMMANDER: \"Comandante Etéreo\"\n  STR_CYBERDISC_TERRORIST: \"Ciberdisco - Terrorista\"\n  STR_REAPER_TERRORIST: \"Devorador - Terrorista\"\n  STR_CHRYSSALID_TERRORIST: \"Crisalídeo - Terrorista\"\n  STR_CELATID_TERRORIST: \"Celátido - Terrorista\"\n  STR_SILACOID_TERRORIST: \"Silacóide - Terrorista\"\n  STR_SECTOPOD_TERRORIST: \"Sectópode - Terrorista\"\n  STR_UFO_POWER_SOURCE: \"Fonte de energia OVNI\"\n  STR_UFO_NAVIGATION: \"Sistema de navegação OVNI\"\n  STR_UFO_CONSTRUCTION: \"Métodos de construção OVNI\"\n  STR_ALIEN_FOOD: \"Alimentação alienígena\"\n  STR_ALIEN_REPRODUCTION: \"Reprodução alienígena\"\n  STR_ALIEN_ENTERTAINMENT: \"Entretenimento alienígena\"\n  STR_ALIEN_SURGERY: \"Cirurgia alienígena\"\n  STR_EXAMINATION_ROOM: \"Sala de exames\"\n  STR_ALIEN_ALLOYS: \"Ligas alienígenas\"\n  STR_ALIEN_HABITAT: \"Habitat alienígena\"\n  STR_POWER_SUIT: \"Armadura mecânica\"\n  STR_FLYING_SUIT: \"Armadura voadora\"\n  STR_HWP_ROCKETS: \"Mísseis PAP\"\n  STR_HWP_FUSION_BOMB: \"Bombas de fusão PAP\"\n  STR_LASER_WEAPONS: \"Armas laser\"\n  STR_NEW_FIGHTER_CRAFT: \"Novo caça\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Novo caça-transportador\"\n  STR_ULTIMATE_CRAFT: \"Nave suprema\"\n  STR_LASER_PISTOL: \"Pistola laser\"\n  STR_LASER_RIFLE: \"Espingarda laser\"\n  STR_HEAVY_LASER: \"Laser pesado\"\n  STR_LASER_CANNON: \"Canhão laser\"\n  STR_PLASMA_CANNON: \"Canhão de plasma\"\n  STR_FUSION_MISSILE: \"Míssil de fusão\"\n  STR_LASER_DEFENSE: \"Defesas laser\"\n  STR_PLASMA_DEFENSE: \"Defesas de plasma\"\n  STR_FUSION_DEFENSE: \"Defesas de fusão\"\n  STR_GRAV_SHIELD: \"Escudo de gravidade\"\n  STR_MIND_SHIELD: \"Escudo mental\"\n  STR_PSI_LAB: \"Laboratório psíquico\"\n  STR_MOTION_SCANNER: \"Sensor de movimento\"\n  STR_MEDI_KIT: \"Medi-kit\"\n  STR_TANK_CANNON: \"Tanque/Canhão\"\n  STR_TANK_ROCKET_LAUNCHER: \"Tanque/Lança-mísseis\"\n  STR_TANK_LASER_CANNON: \"Tanque/Canhão laser\"\n  STR_HOVERTANK_PLASMA: \"Tanque voador/Plasma\"\n  STR_HOVERTANK_LAUNCHER: \"Tanque voador/Lançador\"\n  STR_STINGRAY_LAUNCHER: \"Lançador Stingray\"\n  STR_AVALANCHE_LAUNCHER: \"Lançador Avalanche\"\n  STR_CANNON: \"Canhão\"\n  STR_FUSION_BALL_LAUNCHER: \"Lançador de bolas de fusão\"\n  STR_PLASMA_BEAM: \"Canhão de plasma\"\n  STR_STINGRAY_MISSILES: \"Mísseis Stingray\"\n  STR_AVALANCHE_MISSILES: \"Mísseis Avalanche\"\n  STR_CANNON_ROUNDS_X50: \"Munição de Canhão(x50)\"\n  STR_FUSION_BALL: \"Bola de fusão\"\n  STR_SOLDIER: \"Soldado\"\n  STR_SCIENTIST: \"Cientista\"\n  STR_ENGINEER: \"Engenheiro\"\n  STR_NORTH_AMERICA: \"América do Norte\"\n  STR_ARCTIC: \"Ártico\"\n  STR_ANTARCTICA: \"Antártida\"\n  STR_SOUTH_AMERICA: \"América do Sul\"\n  STR_EUROPE: \"Europa\"\n  STR_NORTH_AFRICA: \"África do Norte\"\n  STR_SOUTHERN_AFRICA: \"África do Sul\"\n  STR_CENTRAL_ASIA: \"Ásia Central\"\n  STR_SOUTH_EAST_ASIA: \"Ásia Sudeste\"\n  STR_SIBERIA: \"Sibéria\"\n  STR_AUSTRALASIA: \"Australásia\"\n  STR_PACIFIC: \"Pacífico\"\n  STR_NORTH_ATLANTIC: \"Atlântico Norte\"\n  STR_SOUTH_ATLANTIC: \"Atlântico Sul\"\n  STR_INDIAN_OCEAN: \"Oceano Índico\"\n  STR_ALIEN_RESEARCH: \"Investigação alienígena\"\n  STR_ALIEN_HARVEST: \"Recoleção alienígena\"\n  STR_ALIEN_ABDUCTION: \"Sequestro alienígena\"\n  STR_ALIEN_INFILTRATION: \"Infiltração alienígena\"\n  STR_ALIEN_BASE: \"Base alienígena\"\n  STR_ALIEN_TERROR: \"Terrorismo alienígena\"\n  STR_ALIEN_RETALIATION: \"Retaliação alienígena\"\n  STR_ALIEN_SUPPLY: \"Abastecimento alienígena\"\n  STR_MAXIMUM_SPEED: \"Velocidade máxima\"\n  STR_HYPER_WAVE_DECODER_UC: \"RECETOR HIPERONDA\"\n  STR_SKYRANGER: \"SKYRANGER\"\n  STR_LIGHTNING: \"LIGHTNING\"\n  STR_AVENGER: \"AVENGER\"\n  STR_INTERCEPTOR: \"INTERCETOR\"\n  STR_FIRESTORM: \"FIRESTORM\"\n  STR_UFO: \"OpenXcom\"\n  STR_STINGRAY: \"STINGRAY\"\n  STR_AVALANCHE: \"AVALANCHE\"\n  STR_CANNON_UC: \"CANHÃO\"\n  STR_FUSION_BALL_UC: \"BOLA DE FUSÃO\"\n  STR_LASER_CANNON_UC: \"CANHÃO LASER\"\n  STR_PLASMA_BEAM_UC: \"CANHÃO DE PLASMA\"\n  STR_DAMAGE_CAPACITY: \"Blindagem\"\n  STR_WEAPON_POWER: \"Poder de fogo\"\n  STR_WEAPON_RANGE: \"Alcance de fogo\"\n  STR_ACCESS_LIFT: \"Elevador de acesso\"\n  STR_LABORATORY: \"Laboratório\"\n  STR_WORKSHOP: \"Oficina\"\n  STR_SMALL_RADAR_SYSTEM: \"Radar pequeno\"\n  STR_LARGE_RADAR_SYSTEM: \"Radar grande\"\n  STR_MISSILE_DEFENSES: \"Defesas míssil\"\n  STR_GENERAL_STORES: \"Armazéns\"\n  STR_ALIEN_CONTAINMENT: \"Contenção alienígena\"\n  STR_LASER_DEFENSES: \"Defesas laser\"\n  STR_PLASMA_DEFENSES: \"Defesas de plasma\"\n  STR_FUSION_BALL_DEFENSES: \"Defesas de fusão\"\n  STR_PSIONIC_LABORATORY: \"Laboratório psíquico\"\n  STR_HYPER_WAVE_DECODER: \"Recetor hiperonda\"\n  STR_HANGAR: \"Hangar\"\n  STR_USA: \"EUA\"\n  STR_RUSSIA: \"RÚSSIA\"\n  STR_UK: \"REINO UNIDO\"\n  STR_FRANCE: \"FRANÇA\"\n  STR_GERMANY: \"ALEMANHA\"\n  STR_ITALY: \"ITÁLIA\"\n  STR_SPAIN: \"ESPANHA\"\n  STR_CHINA: \"CHINA\"\n  STR_JAPAN: \"JAPÃO\"\n  STR_INDIA: \"ÍNDIA\"\n  STR_BRAZIL: \"BRASIL\"\n  STR_AUSTRALIA: \"AUSTRÁLIA\"\n  STR_NIGERIA: \"NIGÉRIA\"\n  STR_SOUTH_AFRICA: \"ÁFRICA DO SUL\"\n  STR_EGYPT: \"EGITO\"\n  STR_CANADA: \"CANADÁ\"\n  STR_TANK: \"Tanque\"\n  STR_CIVILIAN: \"Civil\"\n  STR_JAN: \"jan\"\n  STR_FEB: \"fev\"\n  STR_MAR: \"mar\"\n  STR_APR: \"abr\"\n  STR_MAY: \"mai\"\n  STR_JUN: \"jun\"\n  STR_JUL: \"jul\"\n  STR_AUG: \"ago\"\n  STR_SEP: \"set\"\n  STR_OCT: \"out\"\n  STR_NOV: \"nov\"\n  STR_DEC: \"dez\"\n  STR_INTERNATIONAL_RELATIONS: \"Relações internacionais\"\n  STR_COUNTRY: \"País\"\n  STR_FUNDING: \"Fundos\"\n  STR_CHANGE: \"Alteração\"\n  STR_WEAPON_SYSTEMS: \"SISTEMAS DE ARMAS\"\n  STR_HWPS: \"PAPs\"\n  STR_DAMAGE_UC_: \"DANO>{ALT}{0}\"\n  STR_ACCESS_LIFT_UFOPEDIA: \"O elevador de acesso permite a transferência de pessoal e equipamento para dentro ou fora da base subterrânea. É sempre a primeira instalação a ser construída numa nova base. A zona do elevador é vulnerável à intrusão por forças hostis.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Cada bloco habitacional pode alojar o máximo de 50 pessoas. Estes blocos dispõem de instalações básicas para alimentação, descanso e recreio.\"\n  STR_LABORATORY_UFOPEDIA: \"Estas instalações estão equipadas com a mais recente tecnologia para investigação de materiais, bioquímica e cosmologia, dispondo de acesso privilegiado às bases de dados dos melhores centros de investigação do planeta, incluindo estabelecimentos militares. Cada laboratório possuí espaço de trabalho suficiente para 50 cientistas. \"\n  STR_WORKSHOP_UFOPEDIA: \"As oficinas dispõem de todo o equipamento necessário para fabricar produtos baseados nos projetos elaborados pelos laboratórios. Cada oficina possuí espaço de trabalho suficiente para 50 engenheiros, mas os processos de fabricação de produtos podem também ocupar algum espaço adicional.\"\n  STR_SMALL_RADAR_SYSTEM_UFOPEDIA: \"Este sistema de deteção por radar tem um alcance de 300 milhas náuticas e está ligado a uma rede de satélites para deteção ao nível do solo. Cada sistema tem a probabilidade de 10% de detetar um objeto de tamanho médio em cada 30 minutos.\"\n  STR_LARGE_RADAR_SYSTEM_UFOPEDIA: \"Este sistema de deteção por radar tem um alcance de 450 milhas náuticas e está ligado a uma rede de satélites para deteção ao nível do solo. Cada sistema tem a probabilidade de 20% de detetar um objeto de tamanho médio em cada 30 minutos.\"\n  STR_MISSILE_DEFENSES_UFOPEDIA: \"Estes mísseis defensivos proporcionam alguma proteção contra incursões de naves hostis que tentem aterrar perto da base.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"Todos os equipamentos, sistemas de armas, munições, material recuperado e plataformas de armas pesadas são guardados nos armazéns, incluindo o equipamento atribuído a veículos em hangar.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"É provável que alienígenas capturados com vida necessitem de ser mantidos em habitats especiais, a fim de preservar os seus sistemas vitais. Estas instalações podem manter até dez formas de vida alienígena em unidades de contenção individuais.\"\n  STR_LASER_DEFENSES_UFOPEDIA: \"Estes sistemas de defesa laser proporcionam proteção contra incursões de naves inimigas.\"\n  STR_PLASMA_DEFENSES_UFOPEDIA: \"Estes sistemas de defesa de raios plasma proporcionam uma proteção poderosa e eficiente contra incursões de naves inimigas. \"\n  STR_FUSION_BALL_DEFENSES_UFOPEDIA: \"Os mísseis de fusão proporcionam o sistema de defesa mais eficaz contra ataques alienígenas. Estes mísseis geram uma implosão de antimatéria que aniquila tudo o que se encontra no seu raio de ação.\"\n  STR_GRAV_SHIELD_UFOPEDIA: \"O escudo de gravidade repele naves alienígenas que tentem aterrar perto de uma base X-Com, permitindo tempo suficiente para que os sistemas de defesa voltem a abrir fogo, duplicando a sua eficácia.\"\n  STR_MIND_SHIELD_UFOPEDIA: \"Como os alienígenas detetam a presença de seres humanos através de ondas cerebrais, esta instalação isola todas as emissões cerebrais dos ocupantes de uma base X-Com, de maneira a reduzir drasticamente as probabilidades de deteção por naves alienígenas.\"\n  STR_PSIONIC_LABORATORY_UFOPEDIA: \"Estas instalações avaliam o potencial psíquico de todos os soldados da base. Cada laboratório pode treinar até dez soldados de cada vez. Os programas de treino são atribuídos no fim de cada mês. Quando usadas em conjunto com um amplificador psíquico as habilidades psíquicas podem ser utilizadas para realizar ataques mentais durante situações de combate.\"\n  STR_HYPER_WAVE_DECODER_UFOPEDIA: \"Os sistemas de comunicação alienígenas usam ondas supradimensionais que viajam quase instantaneamente. Esta instalação interceta transmissões feitas por OVNIs e descodifica a informação, o que permite identificar o tipo de OVNI, a espécie da tripulação e o tipo de missão a que se destina.\"\n  STR_HANGAR_UFOPEDIA: \"Cada hangar pode albergar uma aeronave X-Com, dispondo de instalações próprias para manutenção, abastecimento e reparação. Uma aeronave atribuída a uma base deverá dispor de um hangar exclusivo. Mesmo que uma aeronave esteja fora em missão, o seu hangar não pode ser utilizado por outras sem que esta seja transferida em primeiro lugar.\"\n  STR_PISTOL_UFOPEDIA: \"A pistola padrão utilizada pelas forças X-Com é uma arma semiautomática de alto calibre, com capacidade para 12 tiros.\"\n  STR_RIFLE_UFOPEDIA: \"Esta espingarda altamente precisa está equipada com mira laser e usa munição de 6,7 mm, em carregadores de vinte balas.\"\n  STR_HEAVY_CANNON_UFOPEDIA: \"O canhão de assalto é uma arma devastadora, mas de difícil uso. Este dispositivo versátil funciona com três tipos de munição: perfurante, incendiária e explosiva.\"\n  STR_AUTO_CANNON_UFOPEDIA: \"O canhão automático combina a versatilidade e poder do canhão de assalto com uma maior cadência de tiro.\"\n  STR_ROCKET_LAUNCHER_UFOPEDIA: \"Este lança-mísseis guiado a laser é capaz de disparar três tipos diferentes de projétil.\"\n  STR_LASER_PISTOL_UFOPEDIA: \"A pistola laser é uma aplicação eficaz da nova tecnologia de armas laser, aliando maior precisão e poder de fogo ao formato portátil de arma curta.\"\n  STR_LASER_RIFLE_UFOPEDIA: \"A espingarda laser é uma versão mais precisa e destrutiva do modelo da pistola laser.\"\n  STR_HEAVY_LASER_UFOPEDIA: \"O laser pesado é uma arma de difícil de manejo, mas altamente eficaz.\"\n  STR_GRENADE_UFOPEDIA: \"Esta granada padrão possuí um temporizador sofisticado que permite um controlo preciso.\"\n  STR_SMOKE_GRENADE_UFOPEDIA: \"As granadas de fumo são úteis para criar cobertura para agentes expostos em situações de combate. Recomenda-se cuidado, pois o seu uso pode também beneficiar o inimigo.\"\n  STR_PROXIMITY_GRENADE_UFOPEDIA: \"A  granada de proximidade funciona como um explosivo normal, mas é apenas detonada caso detete movimento na zona onde é lançada. Utilizar com extremo cuidado.\"\n  STR_HIGH_EXPLOSIVE_UFOPEDIA: \"Este explosivo deve apenas ser utilizado em demolições. Evacuar todo o pessoal da zona de explosão antes de usar.\"\n  STR_MOTION_SCANNER_UFOPEDIA: \"Este aparelho sofisticado utiliza uma série de sensores e algoritmos para identificar unidades inimigas em movimento, mas necessita de prática para ser utilizado eficazmente. Clique no ícone do sensor de movimento no menu tático e selecione \\\"Usar sensor\\\". O mostrador do sensor aparecerá no ecrã, indicando com uma seta ao centro a direção para a qual o agente X-Com está voltado (o norte corresponde à aresta superior). As manchas amarelas indicam unidades que se moveram recentemente. Criaturas mais rápidas ou de maior porte produzem manchas maiores. Unidades estáticas não serão detetadas.\"\n  STR_MEDI_KIT_UFOPEDIA: \"O medi-kit é um aparelho portátil que combina as funções de estojo de primeiros-socorros e distribuidor de analgésicos e estimulantes. Para usar o medi-kit, o agente deve estar de frente para a vítima a ser tratada. Caso a vítima esteja inconsciente, posicione o agente sobre o corpo da mesma. Clique no ícone do medi-kit e selecione a opção \\\"Usar medi-kit\\\".{NEWLINE}CURAR> As partes do corpo assinaladas a vermelho representam ferimentos graves. Selecione a parte do corpo a tratar e clique no botão \\\"Curar\\\". Um ferimento grave será curado por cada uso, e a vítima recuperará alguns pontos de vida.{NEWLINE}ESTIMULANTE> O uso de estimulantes recupera pontos de energia e reanima tropas inconscientes. Posicione o agente sobre o corpo da vítima caso esta esteja inconsciente.{NEWLINE}ANALGÉSICOS> Os analgésicos recuperam a moral de agentes feridos até a um valor equivalente ao número de pontos de vida perdidos.\"\n  STR_PSI_AMP_UFOPEDIA: \"O amplificador psíquico só pode ser usado por agentes com habilidades psíquicas. Durante o combate clique no ícone do amplificador, escolha o tipo de ataque a executar e selecione o alvo com o cursor. Existem duas formas de ataque psíquico:{NEWLINE}PÂNICO> Se executado com sucesso este ataque reduz a moral da unidade-alvo para que esta entre em pânico. {NEWLINE}CONTROLO MENTAL> Este ataque é mais difícil de executar, mas, se bem-sucedido, garante controlo total e imediato sobre uma unidade inimiga.\"\n  STR_STUN_ROD_UFOPEDIA: \"Esta arma de eletrochoque é capaz de neutralizar um inimigo de forma não letal, mas só pode ser utilizada em combate corpo a corpo.\"\n  STR_MIND_PROBE_UFOPEDIA: \"A sonda mental é um aparelho de comunicação alienígena utilizado para extrair informação diretamente das ondas cerebrais. Os agentes X-Com podem utilizar este dispositivo em combate, de maneira a saberem mais sobre as características de um determinado alienígena. Após equipar, clique no ícone da sonda mental e selecione a opção \\\"usar\\\". Em seguida, selecione o inimigo-alvo com o cursor.\"\n  STR_PLASMA_PISTOL_UFOPEDIA: \"As pistolas de plasma são armas mortíferas que funcionam com base na aceleração de partículas dentro de um campo de antigravidade instantâneo.\"\n  STR_PLASMA_RIFLE_UFOPEDIA: \"Esta arma devastadora funciona com base na aceleração de partículas dentro de um campo antigravidade instantâneo.\"\n  STR_HEAVY_PLASMA_UFOPEDIA: \"Esta arma devastadora funciona com base num sistema de aceleração de partículas dentro de um campo de antigravidade instantâneo.\"\n  STR_BLASTER_LAUNCHER_UFOPEDIA: \"Esta arma é uma espécie de lança-mísseis alienígena que dispara \\\"bombas desintegradoras\\\" altamente destrutivas. Ao ativar a arma pode colocar pontos de referência no terreno de maneira guiar mais eficazmente a bomba. Após definir pontos suficientes, clique no ícone especial \\\"Lançar míssil\\\". \"\n  STR_SMALL_LAUNCHER_UFOPEDIA: \"Um lança-granadas miniatura que dispara bombas de atordoamento. Esta arma é bastante útil para capturar alienígenas vivos.\"\n  STR_ALIEN_GRENADE_UFOPEDIA: \"Este dispositivo funciona de maneira similar a uma granada terrestre, mas possui uma maior capacidade destrutiva.\"\n  STR_SMALL_SCOUT: \"Explorador ligeiro\"\n  STR_MEDIUM_SCOUT: \"Explorador médio\"\n  STR_LARGE_SCOUT: \"Explorador pesado\"\n  STR_HARVESTER: \"Recoletor\"\n  STR_ABDUCTOR: \"Nave de sequestro\"\n  STR_TERROR_SHIP: \"Nave de terror\"\n  STR_BATTLESHIP: \"Nave de batalha\"\n  STR_SUPPLY_SHIP: \"Nave de abastecimento\"\n  STR_RATING: \"AVALIAÇÃO> {0}\"\n  STR_RATING_TERRIBLE: \"PÉSSIMO!\"\n  STR_RATING_POOR: \"FRACO!\"\n  STR_RATING_OK: \"OK\"\n  STR_RATING_GOOD: \"BOM!\"\n  STR_RATING_EXCELLENT: \"EXCELENTE!\"\n  STR_SCORE: \"PONTUAÇÃO\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"RELATÓRIO MENSAL X-COM\"\n  STR_MONTH: \"Mês> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"O concelho de nações financiadoras está satisfeito com o seu progresso atual.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"O conselho de nações financiadoras está muito satisfeito com os seus excelentes progressos. Continue o bom trabalho.\"\n  STR_COUNCIL_IS_DISSATISFIED: \"O conselho de nações financiadoras está insatisfeito com os seus resultados. Melhore o seu desempenho em lidar com a ameaça alienígena ou arrisca-se a que o projeto X-Com seja cancelado.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"Como não conseguiu lidar adequadamente com a invasão alienígena o concelho de nações financiadoras decidiu, a muito custo, terminar o projeto X-Com. Cada nação irá lidar com o problema à sua maneira. Só nos resta esperar que cheguemos a um acordo com estas forças aparentemente hostis e que a população consiga aceitar os visitantes alienígenas.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} está especialmente contente pela maneira como lidou com a ameaça local e concordou em aumentar a sua contribuição financeira.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} estão particularmente contentes com os seus progressos em lidar com incursões alienígenas locais e concordaram em aumentar a sua contribuição financeira.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} e {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} está descontente com maneira como lidou com a atividade alienígena no seu território e decidiu diminuir a sua contribuição financeira.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} estão descontentes com a sua incapacidade em lidar com a atividade alienígena nos respetivos territórios e decidiram reduzir a sua contribuição financeira.\"\n  STR_KNOTS: \"{0} nós\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} assinou um pacto secreto com forças alienígenas desconhecidas e decidiu retirar-se do projeto.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} assinaram um pacto secreto com forças alienígenas desconhecidas e decidiram retirar-se do projeto.\"\n  STR_MONTHLY_RATING: \"Avaliação mensal> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Alteração de fundos> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"O conselho de nações financiadoras não está satisfeito com a sua posição financeira. Reduza a sua dívida abaixo de 1 milhão ou o projeto X-Com será cancelado.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"DESCODIFICAÇÃO DE TRANSMISSÃO HIPERONDA\"\n  STR_CRAFT_TYPE: \"TIPO DE NAVE\"\n  STR_RACE: \"ESPÉCIE\"\n  STR_MISSION: \"MISSÃO\"\n  STR_ZONE: \"ZONA\"\n  STR_ALLOCATE_RESEARCH: \"Novo projeto\"\n  STR_ALLOCATE_MANUFACTURE: \"Nova produção\"\n  STR_NEW_YORK: \"Nova Iorque\"\n  STR_WASHINGTON: \"Washington\"\n  STR_LOS_ANGELES: \"Los Angeles\"\n  STR_MONTREAL: \"Montreal\"\n  STR_HAVANA: \"Havana\"\n  STR_MEXICO_CITY: \"Cidade do México\"\n  STR_CHICAGO: \"Chicago\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_DALLAS: \"Dallas\"\n  STR_BRASILIA: \"Brasília\"\n  STR_BOGOTA: \"Bogotá\"\n  STR_BUENOS_AIRES: \"Buenos Aires\"\n  STR_SANTIAGO: \"Santiago\"\n  STR_RIO_DE_JANEIRO: \"Rio de Janeiro\"\n  STR_LIMA: \"Lima\"\n  STR_CARACAS: \"Caracas\"\n  STR_LONDON: \"Londres\"\n  STR_PARIS: \"Paris\"\n  STR_BERLIN: \"Berlim\"\n  STR_MOSCOW: \"Moscovo\"\n  STR_ROME: \"Roma\"\n  STR_MADRID: \"Madrid\"\n  STR_BUDAPEST: \"Budapeste\"\n  STR_LAGOS: \"Lagos\"\n  STR_CAIRO: \"Cairo\"\n  STR_CASABLANCA: \"Casablanca\"\n  STR_PRETORIA: \"Pretória\"\n  STR_NAIROBI: \"Nairóbi\"\n  STR_CAPE_TOWN: \"Cidade do Cabo\"\n  STR_KINSHASA: \"Quinxassa\"\n  STR_ANKARA: \"Ancara\"\n  STR_DELHI: \"Deli\"\n  STR_KARACHI: \"Carachi\"\n  STR_BAGHDAD: \"Bagdade\"\n  STR_TEHRAN: \"Teerão\"\n  STR_BOMBAY: \"Bombaim\"\n  STR_CALCUTTA: \"Calcutá\"\n  STR_TOKYO: \"Tóquio\"\n  STR_BEIJING: \"Pequim\"\n  STR_BANGKOK: \"Banguecoque\"\n  STR_MANILA: \"Manila\"\n  STR_SEOUL: \"Seul\"\n  STR_SINGAPORE: \"Singapura\"\n  STR_JAKARTA: \"Jacarta\"\n  STR_SHANGHAI: \"Xangai\"\n  STR_HONG_KONG: \"Hong Kong\"\n  STR_NOVOSIBIRSK: \"Novosibirsk\"\n  STR_CANBERRA: \"Camberra\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_MELBOURNE: \"Melbourne\"\n  STR_PERTH: \"Perth\"\n  STR_PSI_TRAINING: \"Treino psíquico\"\n  STR_PSIONIC_TRAINING: \"TREINO PSÍQUICO\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Capacidade restante> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"Poder{NEWLINE}psíquico\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"Hab. psíquica{NEWLINE}/Melhoramento\"\n  STR_PSI_AMP: \"Amplificador psíquico\"\n  STR_IN_TRAINING: \"Em{NEWLINE}treino?\"\n  STR_TARGETTED_BY: \"ALVO DE:\"\n  STR_WEAPONS_CREW_HWPS: \"ARMAS/{NEWLINE}TRIPULAÇÃO/PAPs\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"tem pouco combustível.{NEWLINE}A regressar à base\"\n  STR_SOLDIER_LIST: \"Lista de soldados\"\n  STR_RANK_: \"POSTO> {ALT}{0}\"\n  STR_MISSIONS: \"MISSÕES> {ALT}{0}\"\n  STR_KILLS: \"MORTOS> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"EM RECUPERAÇÃO> {ALT}{0}\"\n  STR_TIME_UNITS: \"UNIDADES DE TEMPO\"\n  STR_STAMINA: \"RESISTÊNCIA\"\n  STR_HEALTH: \"PONTOS DE VIDA\"\n  STR_BRAVERY: \"CORAGEM\"\n  STR_REACTIONS: \"REAÇÕES\"\n  STR_FIRING_ACCURACY: \"PRECISÃO DE FOGO\"\n  STR_THROWING_ACCURACY: \"PRECISÃO DE ARREMESSO\"\n  STR_STRENGTH: \"FORÇA\"\n  STR_PSIONIC_STRENGTH: \"PODER PSÍQUICO\"\n  STR_PSIONIC_SKILL: \"HABILIDADE PSÍQUICA\"\n  STR_NEW_RANK: \"Promoção\"\n  STR_PROMOTIONS: \"Promoções\"\n  STR_SOLDIERS_UC: \"SOLDADOS\"\n  STR_TANK_CANNON_UFOPEDIA: \"As plataformas de armas pesadas de controlo à distância são projetadas de maneira a complementar a eficácia do esquadrão de assalto X-Com em situações de combate. A sua blindagem e poder de fogo são bastante úteis no combate em campo aberto. Certifique-se que dispõe de munições suficientes para rearmamento após o combate. Todas as PAP são recarregadas automaticamente quando atribuídas a um esquadrão.\"\n  STR_TANK_ROCKET_LAUNCHER_UFOPEDIA: \"Esta plataforma de armas pesadas controlada à distância está armada com mísseis altamente destrutivos, eficazes contra qualquer tipo de alienígena. Certifique-se de que dispõe de mísseis PAP suficientes nos armazéns para rearmar a plataforma após o combate.\"\n  STR_TANK_LASER_CANNON_UFOPEDIA: \"A tecnologia laser é uma adição excelente ao arsenal das PAP, permitindo um poder de fogo superior sem quaisquer restrições de munição. \"\n  STR_HOVERTANK_PLASMA_UFOPEDIA: \"A tecnologia alienígena deu origem a uma nova geração de PAPs, aliando propulsão antigravítica e o poder de fogo da tecnologia plasma numa combinação mortífera.\"\n  STR_HOVERTANK_LAUNCHER_UFOPEDIA: \"Este tanque voador está equipado com um lançador de bolas de fusão de enorme poder destrutivo. Usar com extrema cautela. Para armar esta PAP será necessário fabricar bolas de fusão, um tipo de projétil inteligente. Para disparar esta arma pode colocar vários pontos de referência no terreno com o cursor. De seguida clique no ícone \\\"Lançar Míssil\\\".\"\n  STR_HEAVY_PLASMA_CLIP_UFOPEDIA: \"Este pequeno dispositivo é utilizado como fonte de energia para as armas de plasma pesado. Contém uma pequena quantidade de Elério no seu interior. \"\n  STR_PLASMA_RIFLE_CLIP_UFOPEDIA: \"Este pequeno objeto é utilizado como fonte de energia para a espingarda de plasma - uma arma alienígena de potência média. Contém uma pequena quantidade de Elério no seu interior. \"\n  STR_PLASMA_PISTOL_CLIP_UFOPEDIA: \"Dispositivo de alimentação para a pistola de plasma alienígena. Contém Elério, a fonte de energia alienígena.\"\n  STR_STUN_BOMB_UFOPEDIA: \"A bomba atordoadora serve, originalmente, para capturar humanos vivos, mas também pode ser utilizada contra a maioria das espécies alienígenas. É disparada através de um minilançador.\"\n  STR_ALIEN_RESEARCH_UFOPEDIA: \"As missões alienígenas de investigação destinam-se a recolher informação básica sobre a Terra e os seus habitantes. Para tal, os alienígenas utilizam sobretudo veículos pequenos que aterram ocasionalmente em áreas desertas. Este tipo de atividade alienígena é considerada a menos perigosa para o projeto X-Com, devido a atrair pouca atenção dos governos e do público geral. \"\n  STR_ALIEN_HARVEST_UFOPEDIA: \"Os alienígenas utilizam a fauna terrestre para vários fins. Os animais são capturados em segredo e devolvidos com vários órgãos removidos. Estes casos de mutilação de gado são predominantemente relatados em ocasiões de avistamento de OVNIs. Este tipo de atividade alienígena aumenta a ansiedade geral das populações e o ocorre principalmente em zonas rurais. A teoria da \\\"recoleção alienígena\\\" sugere que foram estas espécies extraterrestres que originalmente \\\"cultivaram\\\" o nosso planeta com a sua flora e fauna e que regressam agora para colher aquilo que semearam.\"\n  STR_ALIEN_ABDUCTION_UFOPEDIA: \"Esta é a forma mais perversa de atividade alienígena. Existe uma grande variedade de relatos sobre sequestros executados por alienígenas, apesar de estes tentarem apagar o episódio da memória das suas vítimas. As vítimas de sequestro dizem ser sujeitas a testes físicos humilhantes, incluindo a implantação de fetos alienígenas em mulheres e outras experiências genéticas bizarras. O interesse dos alienígenas pela manipulação e mutação do seu próprio material genético parece ser o propósito por detrás destes atos. Estas atividades provocam pânico geral nas populações e ocorrem em zonas povoadas ou cidades.\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"Os governos terrestres podem ser alvo de infiltração por parte de agentes alienígenas disfarçados de humanos. Isto pode resultar em contacto oficial entre alienígenas e entidades governamentais ao mais alto nível. Os picos deste género de atividade são caracterizados por atividade OVNI intensa nas proximidades de cidades importantes. Os alienígenas tentarão assinar um pacto com uma nação terrestre, oferecendo o seu conhecimento e tecnologia superiores. Em troca, o governo assinante permitirá aos alienígenas levarem a cabo as suas atividades sem impedimentos. Este género de missão representa a maior ameaça para o projeto X-Com, pois se um governo concordar em assinar um pacto irá cancelar o nosso financiamento. \"\n  STR_ALIEN_BASE_UFOPEDIA: \"Descobrimos que os alienígenas constroem bases subterrâneas secretas em localizações remotas do nosso planeta. Após alguns voos de reconhecimento iniciais, a atividade OVNI intensifica-se enquanto a base está a ser construída. Sabemos que estas instalações contém laboratórios experimentais para realizar experiências em seres humanos sequestrados e que dispoem de equipamento para desenvolver outros tipos de atividade. A presença de uma base irá causar um aumento de atividade alienígena na zona sem que se registe a presença de OVNIs. Para localizar uma base é necessário patrulhar a área-alvo com uma aeronave X-Com durante algumas horas. \"\n  STR_ALIEN_TERROR_UFOPEDIA: \"Ao aterrorizar uma cidade, os alienígenas utilizam forças especiais com enorme poder destrutivo. Com vidas civis em risco, os governos são forçados a evacuar áreas inteiras. O objetivo desta atividade é provocar medo suficiente nas populações para forçar os governos a abandonarem o projeto X-Com.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"Se as missões de interceção X-Com forem especialmente bem-sucedidas em abater naves alienígenas, é possível que as forças extraterrestres tomem medidas de retaliação, o que pode culminar num assalto direto às bases X-Com. No entanto, como é necessário aos alienígenas encontrar uma base para lançar uma incursão, é pouco provável que tal suceda, desde que as naves alienígenas sejam mantidas à distância. \"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"Após a sua construção, as bases alienígenas necessitam de abastecimento frequente executado por veículos próprios. Se uma destas naves for detetada no solo é porque uma base alienígena se encontra nas proximidades.\"\n  STR_SMALL_SCOUT_UFOPEDIA: \"Esta nave minúscula é utilizada para fins de reconhecimento e pesquisa. Precede a chegada de naves maiores durante o início de uma incursão alienígena.\"\n  STR_MEDIUM_SCOUT_UFOPEDIA: \"Uma nave de reconhecimento ligeira que não é grande ameaça para as forças terrestres. Precede a vinda de naves maiores no início de incursões alienígenas.\"\n  STR_LARGE_SCOUT_UFOPEDIA: \"Esta é a maior nave de reconhecimento alienígena, adaptada para desempenhar todo o tipo de missões.\"\n  STR_HARVESTER_UFOPEDIA: \"Os recoletores estão equipados com um feixe de tração para recolher gado e outros animais. Bisturis laser extraem rapidamente o material orgânico desejado que é guardado em contentores próprios. Após a extração, o cadáver é despejado para o solo.  \"\n  STR_ABDUCTOR_UFOPEDIA: \"Esta nave está equipada com uma sala de exames para executar experiências horríveis em cobaias humanas. A vítima é normalmente paralisada através de poderes telepáticos, mas é mantida consciente enquanto está na mesa de operações.\"\n  STR_TERROR_SHIP_UFOPEDIA: \"A nave de terror é um veículo equipado com uma unidade de contenção para armas e entidades terroristas. A sua principal função é o transporte forças terroristas com o propósito de lançar incursões a povoações terrestres.\"\n  STR_BATTLESHIP_UFOPEDIA: \"A nave de batalha é a maior e mais poderosa das naves alienígenas. Equipada com armas devastadoras e uma tripulação numerosa, é utilizada apenas nas missões mais importantes.\"\n  STR_SUPPLY_SHIP_UFOPEDIA: \"A nave de abastecimento é utilizada durante a construção de bases alienígenas ou para o abastecimento das mesmas. Transporta contentores de alimentos e câmaras de reprodução. \"\n  STR_DISMANTLE: \"Demolir\"\n  STR_FACILITY_IN_USE: \"INSTALAÇÃO EM USO\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"NÃO É POSSÍVEL DEMOLIR ESTA INSTALAÇÃO!{SMALLLINE}Todas as instalações têm de estar ligadas ao elevador de acesso.\"\n  STR_TRANSFER_ITEMS_TO: \"Transferir itens para {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"NÃO HÁ ESPAÇO DE CONTENÇÃO ALIENÍGENA PARA EFETUAR A TRANSFERÊNCIA!{SMALLLINE}Os alienígenas vivos necessitam de uma área de contenção alienígena para sobreviverem.\"\n  STR_AMOUNT_AT_DESTINATION: \"QUANTIDADE{NEWLINE}NA BASE DESTINO\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"Os alienígenas capturados morreram devido à falta de uma instalação de contenção alienígena\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"NÃO HÁ HABITAÇÕES LIVRES!{SMALLLINE}A base de destino não tem espaço de habitação suficiente para a tripulação desta aeronave.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"NÃO HÁ ESPAÇO EM ARMAZÉM SUFICIENTE!{SMALLLINE}A base de destino não dispõe de espaço suficiente para armazenar o equipamento atribuído a esta aeronave.\"\n  STR_ITEMS_ARRIVING: \"Chegada de transporte\"\n  STR_DESTINATION_UC: \"DESTINO\"\n  STR_PISTOL: \"Pistola\"\n  STR_PISTOL_CLIP: \"Carregador de pistola\"\n  STR_RIFLE: \"Espingarda de assalto\"\n  STR_RIFLE_CLIP: \"Carregador de espingarda\"\n  STR_HEAVY_CANNON: \"Canhão de assalto\"\n  STR_HC_AP_AMMO: \"Munição CC-P\"\n  STR_HC_HE_AMMO: \"Munição CC-E\"\n  STR_HC_I_AMMO: \"Munição CC-I\"\n  STR_AUTO_CANNON: \"Canhão automático\"\n  STR_AC_AP_AMMO: \"Munição CA-P\"\n  STR_AC_HE_AMMO: \"Munição CA-E\"\n  STR_AC_I_AMMO: \"Munição CA-I\"\n  STR_ROCKET_LAUNCHER: \"Lança-mísseis\"\n  STR_SMALL_ROCKET: \"Míssil pequeno\"\n  STR_LARGE_ROCKET: \"Míssil grande\"\n  STR_INCENDIARY_ROCKET: \"Míssil incendiário\"\n  STR_GRENADE: \"Granada\"\n  STR_SMOKE_GRENADE: \"Granada de fumo\"\n  STR_PROXIMITY_GRENADE: \"Granada de proximidade\"\n  STR_HIGH_EXPLOSIVE: \"Explosivo de demolição\"\n  STR_STUN_ROD: \"Bastão elétrico\"\n  STR_HEAVY_PLASMA: \"Plasma pesado\"\n  STR_HEAVY_PLASMA_CLIP: \"Carregador de plasma pesado\"\n  STR_PLASMA_RIFLE: \"Espingarda de plasma\"\n  STR_PLASMA_RIFLE_CLIP: \"Carregador de espingarda plasma\"\n  STR_PLASMA_PISTOL: \"Pistola de plasma\"\n  STR_PLASMA_PISTOL_CLIP: \"Carregador de pistola de plasma\"\n  STR_BLASTER_LAUNCHER: \"Desintegrador\"\n  STR_BLASTER_BOMB: \"Bomba desintegradora\"\n  STR_SMALL_LAUNCHER: \"Minilançador\"\n  STR_STUN_BOMB: \"Bomba atordoadora\"\n  STR_ALIEN_GRENADE: \"Granada alienígena\"\n  STR_ELERIUM_115: \"Elério-115\"\n  STR_MIND_PROBE: \"Sonda mental\"\n  STR_SECTOID_CORPSE: \"Cadáver de Sectóide\"\n  STR_SNAKEMAN_CORPSE: \"Cadáver de Homem-cobra\"\n  STR_ETHEREAL_CORPSE: \"Cadáver de Etéreo\"\n  STR_MUTON_CORPSE: \"Cadáver de Muton\"\n  STR_FLOATER_CORPSE: \"Cadáver de Flutuador\"\n  STR_CELATID_CORPSE: \"Cadáver de Celátido\"\n  STR_SILACOID_CORPSE: \"Cadáver de Silacóide\"\n  STR_CHRYSSALID_CORPSE: \"Cadáver de Crisalídeo\"\n  STR_REAPER_CORPSE: \"Cadáver de Devorador\"\n  STR_SECTOPOD_CORPSE: \"Destroços de Sectópode\"\n  STR_CYBERDISC_CORPSE: \"Destroços de Ciberdisco\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"Sem munições suficientes para equipar a PAP{SMALLLINE}Cada PAP necessita de {0} {1}.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Não há equipamento suficiente para reequipar o esquadrão\"\n  STR_MARS_CYDONIA_LANDING: \"Marte: aterragem em Cidónia\"\n  STR_MARS_CYDONIA_LANDING_BRIEFING: \"A nossa nave aterrou na região de Cidónia, localizada na superfície marciana. A informação disponível indica que uma das pirâmides contém um elevador de cor verde que dá acesso a um complexo subterrâneo. Assim que reunir todas as suas tropas na zona do elevador, clique no ícone \\\"Abortar missão\\\" para proceder à fase seguinte.\"\n  STR_MARS_THE_FINAL_ASSAULT: \"Marte: o assalto final\"\n  STR_MARS_THE_FINAL_ASSAULT_BRIEFING: \"O elevador da pirâmide transporta as nossas tropas até ao fundo da superfície do planeta, chegando ao coração de uma rede de túneis e câmaras. O cérebro-mãe alienígena está escondido algures neste labirinto. Temos de o destruir para salvar a Terra do jugo alienígena.{NEWLINE}{NEWLINE}Boa sorte! \"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Para produzir:{NEWLINE}{1}{NEWLINE}é necessário investigar:{NEWLINE}{0}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"Os alienígenas destruíram a base indefesa {0}\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"Detetámos uma base alienígena na seguinte localização: {0}\"\n  STR_STANDOFF: \"MODO DE PERSEGUIÇÃO\"\n  STR_CAUTIOUS_ATTACK: \"ATAQUE DE LONGO ALCANCE\"\n  STR_STANDARD_ATTACK: \"ATAQUE NORMAL\"\n  STR_AGGRESSIVE_ATTACK: \"ATAQUE AGRESSIVO\"\n  STR_DISENGAGING: \"A RETIRAR\"\n  STR_UFO_HIT: \"ALVO ATINGIDO!\"\n  STR_UFO_CRASH_LANDS: \"O OVNI DESPENHOU-SE!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Minimizar apenas em perseguição\"\n  STR_UFO_RETURN_FIRE: \"O OVNI ABRIU FOGO!\"\n  STR_INTERCEPTOR_DAMAGED: \">>> CAÇA DANIFICADO <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> CAÇA DESTRUÍDO <<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"O OVNI ESCAPOU!\"\n  STR_ALIENS_TERRORISE: \"FORÇAS ALIENÍGENAS ATERRORIZAM\"\n  STR_LONG_RANGE_DETECTION: \"Deteção de longo alcance\"\n  STR_STORES_UC: \"ARMAZÉNS\"\n  STR_DIFFICULTY_LEVEL: \"Nível de dificuldade\"\n  STR_INTERCEPT: \"INTERCETAR\"\n  STR_BASES: \"BASES\"\n  STR_GRAPHS: \"ESTATÍSTICAS\"\n  STR_UFOPAEDIA_UC: \"OVNIPÉDIA\"\n  STR_OPTIONS_UC: \"OPÇÕES\"\n  STR_FUNDING_UC: \"ORÇAMENTO\"\n  STR_5_SECONDS: \"5 segs\"\n  STR_1_MINUTE: \"1 min\"\n  STR_5_MINUTES: \"5 mins\"\n  STR_30_MINUTES: \"30 mins\"\n  STR_1_HOUR: \"1 hora\"\n  STR_1_DAY: \"1 dia\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"Registo de avaliação X-Com\"\n  STR_ENTER_NAME: \"Introduza o seu nome\"\n  STR_PERFORMANCE_RATING: \"Classificação final\"\n  STR_VICTORY_DATE: \"Data de vitória\"\n  STR_ELECTRO_FLARE: \"Sinalizador elétrico\"\n  STR_ELECTRO_FLARE_UFOPEDIA: \"Este pequeno aparelho produz uma luz brilhante que ilumina a área para onde é lançado, revelando unidades inimigas durante missões noturnas.\"\n  STR_MONTHLY_COSTS: \"Despesas mensais\"\n  STR_CRAFT_RENTAL: \"Aluguer de aeronaves\"\n  STR_SALARIES: \"Salários\"\n  STR_BASE_MAINTENANCE: \"Manutenção da base\"\n  STR_COST_PER_UNIT: \"Valor individual\"\n  STR_QUANTITY: \"Quantidade\"\n  STR_TOTAL: \"Total\"\n  STR_IN_PSIONIC_TRAINING: \"Em treino psíquico\"\n  STR_BLASTER_BOMB_UFOPEDIA: \"Este projétil altamente destrutivo é guiado por um sistema de orientação inteligente e disparado através de um desintegrador.\"\n  STR_FRONT_ARMOR: \"Armadura frontal\"\n  STR_LEFT_ARMOR: \"Armadura esquerda\"\n  STR_RIGHT_ARMOR: \"Armadura direita\"\n  STR_REAR_ARMOR: \"Armadura traseira\"\n  STR_UNDER_ARMOR: \"Armadura inferior\"\n  STR_ROUNDS: \"Tiros\"\n  STR_UNIT: \"UNIDADE> {0}\"\n  STR_ENERGY: \"ENERGIA\"\n  STR_MORALE: \"MORAL\"\n  STR_ARMOR_: \"ARMADURA> {0}\"\n  STR_FRONT_ARMOR_UC: \"ARMADURA FRONTAL\"\n  STR_LEFT_ARMOR_UC: \"ARMADURA ESQUERDA\"\n  STR_RIGHT_ARMOR_UC: \"ARMADURA DIREITA\"\n  STR_REAR_ARMOR_UC: \"ARMADURA TRASEIRA\"\n  STR_SKILLS: \"HABILIDADES> {0}\"\n  STR_LEVEL: \"NÍVEL> {0}\"\n  STR_HEAD: \"CABEÇA\"\n  STR_TORSO: \"TRONCO\"\n  STR_RIGHT_ARM: \"BRAÇO DIR.\"\n  STR_LEFT_ARM: \"BRAÇO ESQ.\"\n  STR_RIGHT_LEG: \"PERNA DIR.\"\n  STR_LEFT_LEG: \"PERNA ESQ.\"\n  STR_PAIN_KILLER: \"ANALGÉSICO\"\n  STR_STIMULANT: \"ESTIMULANTE\"\n  STR_HEAL: \"CURAR\"\n  STR_TIME_UNITS_SHORT: \"UT>{ALT}{0}\"\n  STR_WEIGHT: \"Peso>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"Reaç>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"H.Psi>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"P.Psi>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Artefacto Alienígena\"\n  STR_AMMO_ROUNDS_LEFT: \"MUNIÇÃO:{NEWLINE}TIROS{NEWLINE}RESTANTES={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Analgésico>{ALT}{0}{ALT}{NEWLINE}Estimulante>{ALT}{1}{ALT}{NEWLINE}Curar>{ALT}{2}\"\n  STR_THROW: \"Atirar\"\n  STR_AUTO_SHOT: \"Rajada\"\n  STR_SNAP_SHOT: \"Tiro simples\"\n  STR_AIMED_SHOT: \"Tiro preciso\"\n  STR_STUN: \"Atordoar\"\n  STR_PRIME_GRENADE: \"Programar explosivo\"\n  STR_USE_SCANNER: \"Usar sensor\"\n  STR_USE_MEDI_KIT: \"Usar medi-kit\"\n  STR_LAUNCH_MISSILE: \"Lançar míssil\"\n  STR_ACCURACY_SHORT: \"Pr>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Sem unidades de tempo suficientes!\"\n  STR_NOT_ENOUGH_ENERGY: \"Sem energia suficiente!\"\n  STR_NO_ROUNDS_LEFT: \"Sem munição!\"\n  STR_NO_AMMUNITION_LOADED: \"Sem munição!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Munição errada para esta arma!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"A arma já está carregada!\"\n  STR_NO_LINE_OF_FIRE: \"Nenhuma linha de fogo!\"\n  STR_GRENADE_IS_ACTIVATED: \"Explosivo ativado!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Explosivo desativado!\"\n  STR_THERE_IS_NO_ONE_THERE: \"Não há ninguém aqui!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Impossível utilizar um artefacto alienígena sem ser investigado!\"\n  STR_OUT_OF_RANGE: \"Fora de alcance!\"\n  STR_UNABLE_TO_THROW_HERE: \"Não é possível atirar para aqui!\"\n  STR_SET_TIMER: \"Temporizador\"\n  STR_HIDDEN_MOVEMENT: \"MOVIMENTO OCULTO\"\n  STR_TURN: \"TURNO> {0}\"\n  STR_SIDE: \"LADO> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Pressione um botão para continuar\"\n  STR_MIND_CONTROL: \"Controlo mental\"\n  STR_PANIC_UNIT: \"Pânico\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Ataque psíquico bem-sucedido\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Controlo Mental bem-sucedido\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}enlouqueceu\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}enlouqueceu\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}entrou em pânico\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}entrou em pânico\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Alienígenas\"\n  STR_RIGHT_HAND: \"MÃO DIR.\"\n  STR_LEFT_HAND: \"MÃO ESQ.\"\n  STR_RIGHT_SHOULDER: \"OMBRO DIR.\"\n  STR_LEFT_SHOULDER: \"OMBRO ESQ.\"\n  STR_BACK_PACK: \"MOCHILA\"\n  STR_BELT: \"CINTO\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}está sob controlo alienígena\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}está sob controlo alienígena\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}está inconsciente\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}está inconsciente\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}morreu vítima de ferimentos graves\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}morreu vítima de ferimentos graves\"\n  STR_USE_MIND_PROBE: \"Usar sonda mental\"\n  STR_FATAL_WOUNDS: \"FERIMENTOS GRAVES\"\n  STR_UNDER_ARMOR_UC: \"ARMADURA INFERIOR\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"UTs reservadas para Tiro rápido\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"UTs reservadas para Rajada\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"UTs reservadas para Tiro preciso\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"UTs reservadas para Ajoelhar\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"UTs reservadas para Ajoelhar e disparar\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} Unidade na nave X-Com\"\n    many: \"{N} unidades na nave X-Com\"\n    other: \"{N} unidades na nave X-Com\"\n  STR_UNITS_OUTSIDE:\n    one: \"Resta {N} unidade no exterior\"\n    many: \"Restam {N} unidades no exterior\"\n    other: \"Restam {N} unidades no exterior\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} Unidade na entrada\"\n    many: \"{N} unidades na entrada\"\n    other: \"{N} unidades na entrada\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} Unidade na saída-alvo\"\n    many: \"{N} unidades na saída-alvo\"\n    other: \"{N} unidades na saída-alvo\"\n  STR_ABORT_MISSION_QUESTION: \"Abortar missão?\"\n  STR_CORPSE: \"Cadáver\"\n  STR_UNLOAD_CRAFT: \"Remover todos\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}morreu em combate\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}morreu em combate\"\n  STR_HIT_MELEE: \"Atacar\"\n  STR_GROUND: \"SOLO\"\n  STR_LIVING_QUARTERS_PLURAL: \"Habitações\"\n  STR_LIST_ITEM: \"ITEM\"\n  STR_PERSONAL_ARMOR_UFOPEDIA: \"Fabricada através das novas ligas alienígenas, esta armadura aumenta as hipóteses de sobrevivência das nossas tropas contra as forças extraterrestres.\"\n  STR_POWER_SUIT_UFOPEDIA: \"A melhor proteção atualmente disponível para tropas em campo, esta poderosa armadura é movida por uma fonte de energia à base de Elério e aumenta de forma extraordinária a força e destreza do utilizador.\"\n  STR_FLYING_SUIT_UFOPEDIA: \"Esta versão melhorada da armadura mecânica está equipada com um sistema de navegação antigravidade alienígena, que permite a liberdade total de movimento em situações de combate.\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"Todos os alienígenas morreram na queda.{NEWLINE}Recuperação de OVNI iniciada.\"\n  STR_RESET: \"Repor\"\n  STR_MEMORIAL: \"Memorial\"\n  STR_DATE_UC: \"DATA\"\n  STR_SOLDIERS_RECRUITED_UC: \"SOLDADOS RECRUTADOS>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"SOLDADOS PERDIDOS>{ALT}{0}\"\n  MAP_CULTA: \"Zona agrícola\"\n  MAP_FOREST: \"Floresta\"\n  MAP_JUNGLE: \"Selva\"\n  MAP_MOUNT: \"Montanha\"\n  MAP_DESERT: \"Deserto\"\n  MAP_POLAR: \"Polar\"\n  MAP_URBAN: \"Cidade\"\n  MAP_UBASE: \"Base Alienígena\"\n  MAP_XBASE: \"Base X-Com\"\n  MAP_MARS: \"Marte\"\n  STR_MIXED: \"Várias\"\n  STR_REMOVE_SELECTED: \"Remover seleção\"\n  STR_LIVE_ALIENS: \"Espécimes{NEWLINE}vivos\"\n  STR_DEAD_ALIENS: \"Espécimes{NEWLINE}reijeitados\"\n  STR_UNDER_INTERROGATION: \"Em{NEWLINE}estudo\"\n  STR_CONTAINMENT_EXCEEDED: \"CONTENÇÃO ALIENÍGENA CHEIA!{SMALLLINE}Não há espaço de contenção suficiente em {0}. Remova os alienígenas em excesso. Todos os alienígenas excluidos morrerão imediatamente.\"\n  STR_MANAGE_CONTAINMENT: \"Gerir contenção Alienígena\"\n  STR_STORAGE_EXCEEDED: \"LIMITES DE ARMAZENAMENTO EXCEDIDOS!{SMALLLINE}Não há espaço em armazém suficiente em {0}. É necessário vender itens em excesso.\"\n  STR_GO_TO_BASE: \"Ver base\"\n  STR_MELEE_ACCURACY: \"PRECISÃO CORPO A CORPO\"\n  STR_SELL_PRODUCTION: \"VENDER\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Ambas as mãos devem estar vazias!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Não há itens necessários para copiar o modelo!\"\n  STR_UNLOAD_WEAPON: \"Descarregar arma\"\n  STR_ALL_ITEMS: \"Todos\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"NÃO É PERMITIDO MAIS EQUIPAMENTO A BORDO!{SMALLLINE}Este veículo só pode transportar o limite máximo de {N} item.\"\n    many: \"NÃO É PERMITIDO MAIS EQUIPAMENTO A BORDO!{SMALLLINE}Este veículo só pode transportar o limite máximo de {N} itens.\"\n    other: \"NÃO É PERMITIDO MAIS EQUIPAMENTO A BORDO!{SMALLLINE}Este veículo só pode transportar o limite máximo de {N} itens.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}CENTRO DE COMANDO DESTRUÍDO{NEWLINE}Regresse à entrada e aborte a missão.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"As bases X-Com não podem ser construídas debaixo de água.\"\n  STR_LEVEL_SHORT: \"{0}\"\n  STR_PERSONNEL: \"Pessoal\"\n  STR_CRAFT_ARMAMENT: \"Veículos e armamento\"\n  STR_COMPONENTS: \"Componentes\"\n  STR_SOLDIERS_RECRUITED: \"Soldados recrutados\"\n  STR_SOLDIERS_LOST: \"Soldados perdidos\"\n  STR_TOTAL_UFOS: \"OVNIs detetados\"\n  STR_TOTAL_ALIEN_BASES: \"Bases alienígenas descobertas\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"PP\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"HP\"\n  FEMALE_CIVILIAN: \"Civil, Mulher\"\n  MALE_CIVILIAN: \"Civil, Homem\"\n  CYBERDISC_WEAPON: \"Arma de Ciberdisco\"\n  REAPER_WEAPON: \"Arma de Devorador\"\n  CHRYSSALID_WEAPON: \"Arma de Crisalídeo\"\n  CELATID_WEAPON: \"Arma de Celátido\"\n  SILACOID_WEAPON: \"Arma de Silacóide\"\n  SECTOPOD_WEAPON: \"Arma de Sectópode\"\n  ZOMBIE_WEAPON: \"Arma de Zombie\"\n  ALIEN_PSI_WEAPON: \"Arma Psíquica Alienígena\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/ro.yml",
    "content": "ro:\n  STR_AVENGER_UFOPEDIA: \"TRANSPORTOR ȘI NAVĂ DE LUPTĂ. CEA MAI BUNĂ IMPLEMENTARE A TEHNOLOGIILOR EXTRATERESTRE.\"\n  STR_INTERCEPTOR_UFOPEDIA: \"NAVĂ DE LUPTĂ AVÂND DOUĂ MOTOARE CU DETONARE PULSATORIE ȘI SISTEME ELECTRONICE SPECIAL ECRANATE. CEA MAI BUNĂ TEHNOLOGIE PAMANTEANĂ DISPONIBILĂ.\"\n  STR_LIGHTNING_UFOPEDIA: \"TRANSPORTOR ȘI NAVĂ DE LUPTĂ. O IMPLEMENTARE NEFINISATĂ DAR EFICIENTĂ A SISTEMELOR DE PROPULSIE EXTRATERESTRE.\"\n  STR_SKYRANGER_UFOPEDIA: \"TRANSPORTOR DE TRUPE. CEL MAI RAPID DE ACEST TIP, PUTÂND ATERIZA ȘI DECOLA PE VERTICALĂ (V.T.O.L.).\"\n  STR_FIRESTORM_UFOPEDIA: \"NAVĂ DE LUPTĂ. ACEASTĂ NAVĂ MONO-PILOT COPIAZĂ MODELUL FARFURIEI ZBURĂTOARE EXTRATERESTRE CU UNITATE PROPULSOARE CENTRALĂ.\"\n  STR_STINGRAY_UFOPEDIA: \"RACHETĂ AER-AER AVANSATĂ AVÂND SISTEME ELECTRONICE SPECIAL ECRANATE.\"\n  STR_AVALANCHE_UFOPEDIA: \"RACHETĂ AER-AER CU FOCOS NUCLEAR, DAR AVÂND O GREUTATE FOARTE MARE.\"\n  STR_CANNON_UFOPEDIA: \"TUN DE ARTILERIE DE MARE PUTERE CARE PROPULSEAZĂ GLOANȚE CE STRĂPUNG BLINDAJUL, PUTÂND PERFORA PÂNĂ LA 40 CM DE OȚEL.\"\n  STR_FUSION_BALL_UFOPEDIA: \"ACEST LANSATOR PROIECTEAZĂ O RACHETĂ SFERICĂ PROPULSATĂ DE O REACȚIE ANTIMATERIE. PROIECTILUL DISTRUGE ȚINTA PRINTR-O IMPLOZIE GRAVITAȚIONALĂ.\"\n  STR_LASER_CANNON_UFOPEDIA: \"ACEST FASCICUL LASER CONVENȚIONAL PRIMEȘTE ENERGIE DE LA O CAMERĂ DE REACȚIE ANTIMATERIE.\"\n  STR_PLASMA_BEAM_UFOPEDIA: \"UNDĂ GRAVITICĂ DIRECȚIONEAZĂ UN CÂMP SUBȚIRE DE IMPLOZIE GRAVITAȚIONALĂ.\"\n  STR_SECTOID_UFOPEDIA: \"Sistemul lor ierarhic variază de la soldați la conducători cu puternice abilități psionice. Aceste îndemânări pot fi folosite pentru a demoraliza sau chiar pentru a dobândi controlul asupra minților soldaților. Tind să se dedice răpirii oamenilor și mutilării bovinelor. Răpirile servesc la extragerea materialului genetic pentru încrucișări și clonări ce slujesc infiltrării în societatea umană. Bovinele furnizează nutrienți și material genetic. Această rasă pare sa dorească dezvoltarea de hibrizi genetici pentru a crește eficiența societății lor, de tip stup.\"\n  STR_SECTOID_AUTOPSY: \"Autopsie Sectoid\"\n  STR_SECTOID_AUTOPSY_UFOPEDIA: \"Autopsia relevă organe digestive vestigiale și o structură simplă. Creierul și ochii sunt foarte bine dezvoltați. Structura sugerează alterări sau mutații genetice. Gura și nasul mici par să aibă funcționalități minore. Membrana palmară dintre degete și laba plată a piciorului sugerează origini acvatice. Nu există organe reproductive, indiciile despre cum se reproduce această specie lipsind. După toate probabilitățile este o specie proiectată genetic.\"\n  STR_SNAKEMAN_UFOPEDIA: \"Această rasă s-a dezvoltat într-un mediu extrem de ostil. Sunt foarte puternici și pot rezista la variații mari ale temperaturii. Mobilitatea lor se datorează unui 'membru' urias semănând trunchiului de șarpe care protejează toate organele vitale. Obiectivele lor par a fi pur prădătoare și par să se afle sub comanda unei alte 'Inteligențe' ce le dirijează incursiunile armate de pe planetă.\"\n  STR_SNAKEMAN_AUTOPSY: \"Autopsie Snakeman\"\n  STR_SNAKEMAN_AUTOPSY_UFOPEDIA: \"Pielea este foarte dură și rezistentă la caldură. Aparatul cardiovascular face parte din sistemul muscular, care folosește principiul hidraulic pentru a produce mișcarea. Singurul mușchi adevărat este 'inima'. Sistemul reproductiv pare a fi extrem de eficient. Reproducerea este asexuată, fiecare creatură cărând la un moment dat până la 50 de ouă în corpul său. Lăsată pe cont propriu, această specie poate fi o amenințare puternică la adresa vieții de pe Pământ.\"\n  STR_ETHEREAL_UFOPEDIA: \"Această creatură posedă stranii puteri mentale care permit comunicarea telepatică și abilitățile telechinezice. Capabilitățile fizice ale creaturei, aparent slabe, sunt susținute de puterile ei mentale. Nu înțelegem cum funcționează telechinezia, de vreme ce pare să sfideze legile fizicii așa cum le cunoaștem noi. Sunt extrem de periculoși în orice luptă, în această situație bazându-se pe abilitățile lor mentale. Apar foarte rar pe Pământ, de vreme ce se folosesc de alte rase pentru a-și realiza obiectivele.\"\n  STR_ETHEREAL_AUTOPSY: \"Autopsie Ethereal\"\n  STR_ETHEREAL_AUTOPSY_UFOPEDIA: \"Această ființă este subdezvoltată fizic și pare incapabilă de a susține orice funcții vitale. Mușchii sunt foarte atrofiați iar organele interne par a fi subdezvoltate. Organele senzoriale, inclusiv ochii, par să nu funcționeze deloc. Totuși creierul este bine dezvoltat și primește o mare parte din rezervele de sânge ale corpului. Rămâne un mister faptul că această creatură se poate întreține fără sprijin extern.\"\n  STR_MUTON_UFOPEDIA: \"Această creatură umanoidă este puternică din punct de vedere fizic și inteligentă. Au un apetit aparte pentru consumul de carne crudă de orice tip, de care au nevoie pentru subzistență asemenea carnivorelor pământene. Par să depindă de comenzi telepatice venite de la o rasa numită 'Ethereal'. Odată tăiată această legătură telepatică sistemul lor mental pare să se rupă iar aceștia mor. Pentru a-și îmbunătăți abilitățile sunt folosite implanturi cibernetice. Este clar că aceștia sunt infanteriștii unei 'Inteligențe' mai puternice.\"\n  STR_MUTON_AUTOPSY: \"Autopsie Muton\"\n  STR_MUTON_AUTOPSY_UFOPEDIA: \"'Pielea' acestei creaturi pare a fi o armură protectoare creată organic, grefată pe corp. Se găsesc numeroase implanturi cibernetice care sunt folosite pentru a dezvolta sistemul cardiovascular și simțurile. Organele reproductive par să fi fost îndepărtate cirurgical. În mod evident, aceste creaturi ghinioniste sunt limitate la o viață plină de războaie și cuceriri. Muniția capabilă de a străpunge armura nu este foarte eficientă împotriva pielii întărite.\"\n  STR_CELATID_UFOPEDIA: \"Această misterioasă formă de viață are abilitatea de a pluti prin aer. Pare să detecteze undele cerebrale ale oamenilor, după care se deplasează către țintă chiar dacă aceasta este bine ascunsă. Odată ce ținta este detectată, aterizează și lansează mici globule de acid extrem de coroziv. Creatura are abilitatea de a se clona într-un ritm alarmant. Însoțește rasa 'Muton'.\"\n  STR_CELATID_AUTOPSY: \"Autopsie Celatid\"\n  STR_CELATID_AUTOPSY_UFOPEDIA: \"Miezul conține un mic dispozitiv biomecanic care pare a fi un sistem natural evoluat de propulsie antigravitațională. Cel mai mare organ este punga de venin și nu pare a exista o structură cerebrală separată. Nu este vizibil niciun sistem digestiv sau reproductiv. Un mic organ conține embrioni care se pot dezvolta rapid într-o nouă ființă.\"\n  STR_SILACOID_UFOPEDIA: \"Această formă de viață bazată pe siliciu generează cantități enorme de caldură. Poate sparge pietre care apoi sunt ingerate de miezul incandescent. Posedă o inteligență primitivă și poate fi controlată de implanturi sau de către telepați. Acționează alături de rasa 'Muton'.\"\n  STR_SILACOID_AUTOPSY: \"Autopsie Silacoid\"\n  STR_SILACOID_AUTOPSY_UFOPEDIA: \"Miezul creaturii este extrem de fierbinte și pare a fi baza unui sistem digestiv. Sistemul muscular aparte are o putere și viteză incredibile. Învelișul precum piatra nu este vătămat de foc sau muniție incendiară.\"\n  STR_CHRYSSALID_UFOPEDIA: \"Cleștii acestei creaturi sunt o armă puternică în lupta corp la corp. Metabolismul rapid al creaturii și puterea mare îi dau viteză și dexteritate. În loc să își omoare victima o impregnează cu un ou și injectează venin care o transformă într-un zombie. O nouă creatură va izbucni din victimă la scurt timp după impregnare. Sunt asociate cu rasa 'Snakeman'.\"\n  STR_CHRYSSALID_AUTOPSY: \"Autopsie Chryssalid\"\n  STR_CHRYSSALID_AUTOPSY_UFOPEDIA: \"Exoscheletul acestei creaturi este extrem de rezistent, dar în mod surprinzător este vulnerabil la explozibili. Creierul este bine dezvoltat, cu o rată de creștere a celulelor foarte mare. Creatura poartă 20 de ouă care vor fi depuse în alte organisme. Este o armă de terorizare foarte eficientă.\"\n  STR_FLOATER_UFOPEDIA: \"În principal sunt soldați și agenți de terorizare. Sunt prădători din fire, proiectați genetic și îmbunătățiți cibernetic pentru a fi luptători formidabili. Jumătatea inferioară a corpului și majoritatea organelor interne sunt îndepărtate chirurgical, în locul lor fiind instalat un sistem de susținere a vieții. Acest implant conține o unitate antigravitațională ce permite creaturii să plutească prin aer, cu toate că o face inconsecvent.\"\n  STR_FLOATER_AUTOPSY: \"Autopsie Floater\"\n  STR_FLOATER_AUTOPSY_UFOPEDIA: \"Creatura a fost puternic modificată chirurgical. Mecanismul care pare a forma nucleul corpului este un sistem de menținere a vieții care preia funcțiile inimii, plămânilor și sistemului digestiv. Acesta permite creaturii să supraviețuiască în medii extrem de ostile. Creierul este mai mic decât al nostru, dar organele senzoriale sunt bine dezvoltate.\"\n  STR_REAPER_UFOPEDIA: \"Acest carnivor biped are fălci puternice și un apetit vorace. Posedă implanturi cerebrale care sunt folosite pentru a îi controla mișcările. Instinctele prădătoare primitive ale acestei creaturi nu folosesc decât la a cauza teroare și distrugere. Sunt asociați cu rasa 'Floater'.\"\n  STR_REAPER_AUTOPSY: \"Autopsie Reaper\"\n  STR_REAPER_AUTOPSY_UFOPEDIA: \"Posedă două 'creiere' și două 'inimi' care îi permit să funcționeze chiar și atunci când are leziuni grave. Totuși blana este puternic inflamabilă, făcând creatura vulnerabilă la munițiile incendiare.\"\n  STR_SECTOPOD_UFOPEDIA: \"Aceștia sunt roboți dotați cu o puternică armă cu fascicul laser. Controlul acestor bestii de metal se face prin conexiune telepatică cu indivizi din rasa 'Ethereal'. Sunt cea mai puternică armă de terorizare aflată la dispoziția forțelor extraterestre.\"\n  STR_SECTOPOD_AUTOPSY: \"Autopsie Sectopod\"\n  STR_SECTOPOD_AUTOPSY_UFOPEDIA: \"Robotul are o construcție solidă, cu armură alimentată capabilă să reziste la majoritatea atacurilor, în special cele cu plasmă. Totuși, circuitele senzoriale par în special vulnerabile la armele laser.\"\n  STR_CYBERDISC_UFOPEDIA: \"Această farfurie zburătoare miniaturală este o armă de terorizare automatizată, înarmată cu un puternic fascicul de plasmă. Propulsia antigravitațională îi oferă un avantaj major pe teren accidentat. Principala activitate este de distrugere și terorizare în slujba rasei 'Sectoid'.\"\n  STR_CYBERDISC_AUTOPSY: \"Autopsie Cyberdisc\"\n  STR_CYBERDISC_AUTOPSY_UFOPEDIA: \"Acest dispozitiv este bine ecranat și rezistent în special la munițiile explozibile. Principalul sistem antigravitațional este prea avariat pentru a îi intelege funcționalitatea.\"\n  STR_UFO_POWER_SOURCE_UFOPEDIA: \"Sursa de energie a navei extraterestre este un reactor antimaterie care folosește Elerium (elementul 115) pentru a genera unde gravitaționale puternice precum și alte forme de energie. Conversia materiei în energie are o eficiență incredibilă de 99%, cantități minuscule de Elerium producând multă energie. Această unitate poate fi reprodusă ușor folosind aliaje extraterestre.\"\n  STR_UFO_NAVIGATION_UFOPEDIA: \"Navele extraterestre folosesc computere sofisticate pentru a naviga pe Pământ și în spațiu. Sistemul se bazează pe procesoare optice aranjate în rețea. Interfața de control este relativ simplă - pentru a mișca nava în orice direcție pilotul controlează orientarea undelor gravitaționale generate de sursa de energie. Acest sistem poate fi folosit ușor de către oameni putând fi reprodus folosind aliaje extraterestre împreună cu alte componente.\"\n  STR_UFO_CONSTRUCTION_UFOPEDIA: \"Nava extraterestră este alcătuită din trei componente principale - o sursă de energie, un sistem de navigație și un fuzelaj construit din aliaje extraterestre. Fuzelajul este special conceput pentru a permite controlul undelor gravitaționale. O cantitate mică de Elerium este necesară pentru alimentare. Odată ce principiile de construcție sunt înțelese iar funcțiile fiecărei componente cunoscute, atunci este posibilă construcția acestor tipuri de nave.\"\n  STR_ALIEN_FOOD_UFOPEDIA: \"Aceste camere conțin diverse enzime ce sunt folosite pentru digerarea bovinelor, altor animale, precum și a oamenilor. Lichidul este apoi consumat drept hrană deja digerată - probabil direct în sange. Acest lucru sugerează o anumită dependență de Pământ pentru hrană - o simbioză între societatea umană și cea extraterestră.\"\n  STR_ALIEN_REPRODUCTION_UFOPEDIA: \"Aceste camere conțin fetuși de extratereștrii. Construcția recipientelor sugerează că extratereștrii ce folosesc acest procedeu depind total de reproducerea în laborator. Nutrienții îmbelșugați asigură dezvoltarea rapidă a fetușilor. Linia de producție poate genera într-un timp scurt mii de clone extraterestre. Procedeul poate fi adaptat ușor pentru reproducerea oamenilor sau pentru hibrizi om-extraterestru.\"\n  STR_ALIEN_ENTERTAINMENT_UFOPEDIA: \"Cel mai probabil aceste sfere au funcții recreaționale. Circuitul psionic stimulează diverși centri nervoși ai creierului. Efectul este similar substanțelor halucinogene. Aceasta este singura marturie că extratereștrii au și alte activități, culturale sau recreaționale.\"\n  STR_ALIEN_SURGERY_UFOPEDIA: \"Acest echipament chirurgical folosește lasere pentru a preleva diferite organe de la bovine sau alte animale. Mutilările de bovine întâlnite pe scară largă pot fi explicate de această îndeletnicire bizară a extratereștrilor. Probabil că aceste organe sunt folosite în scopuri nutriționale sau genetice.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"Mii de oameni au declarat în trecut că au fost răpiți de extratereștrii, câteodată în mod repetat. Adevărul este mult mai îngrozitor. Oamenii au fost răpiți, cercetați și monitorizați. Celor mai bune specimene li se extrăgea materialul genetic. Femeile erau implantate cu fetuși hibrizi om-extraterestru, aceștia fiind extrași după câteva luni. Cine știe ce motive sinistre au extratereștrii!?\"\n  STR_ALIEN_ALLOYS_UFOPEDIA: \"Navele extraterestre sunt construite din aliaje speciale cu proprietăți unice. Sunt extrem de ușoare, durabile și pot fi modelate prin metode electromagnetice. Acest material poate fi reprodus și folosit în multe procese de producție.\"\n  STR_ELERIUM_115_UFOPEDIA: \"Acest element are proprietatea neobișnuită de a genera antimaterie atunci când este bombardat de anumite particule. Astfel se creează unde gravitaționale și alte forme de energie. Nu se regăsește în stare naturală în sistemul nostru solar și nici nu poate fi reprodus.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"Este clar că pe Pământ ducem o luptă fără izbândă. Hoarda de extratereștrii ne copleșește numeric. Tot ce putem să facem este să le încetinim înaintarea. Singura speranță pentru umanitate este să atacăm direct la sursă. Cercetările noastre par să indice existența unei baze de operațiuni în sistemul nostru solar. Extratereștrii indică acest loc ca fiind centrul unei civilizații antice ce precede umanitatea. Trebuie să localizăm acest loc cât mai urgent. Totuși este nevoie să capturăm și să interogăm un lider extraterestru. Cel mai probabil OZNurile mari conțin cel puțin un lider extraterestru.\"\n  STR_THE_MARTIAN_SOLUTION_UFOPEDIA: \"Cercetările noastre indică Marte ca fiind baza de operațiuni a extratereștrilor. Baza este bine ascunsă și conține toate structurile de producție și clonare ce alimentează infiltrarea Pământului. De asemenea pare să conțină un fel de computer ce controlează întreaga operațiune. Se pare că societatea extraterestră de tip stup are un fel de 'regină'. Aceasta este slăbiciunea lor - dacă putem să eliminăm 'creierul' atunci corpul va muri. Trebuie să accelerăm eforturile de cercetare înainte de a fi prea târziu. Ca să progresăm trebuie să capturăm extratereștrii cu rangul cel mai mare - comandanții - care rezidă numai în bazele și navele de război extraterestre.\"\n  STR_CYDONIA_OR_BUST_UFOPEDIA: \"Acum este evident că hoardele extraterestre sunt controlate dintr-o bază subterană din Cydonia - o suprafață neobișnuită de pe planeta Marte înfățișând piramide și o formațiune mare semănând cu o față umană. Civilizația din Cydonia a înflorit pe Marte acum milioane de ani, dar nu știm de ce a murit sau care este legătură cu activitățile desfășurate de extraterștrii acolo. Oricare ar fi explicația trebuie să trimitem o expediție către Cydonia. Acesta este singurul mod în care putem să înfrângem extratereștrii. Trebuie să distrugem 'creierul'. Avem nevoie de o navă Avenger echipată cu cele mai puternice arme aflate la dispoziția noastră. Nu mai putem afla nimic de aici - trebuie să așteptăm rezultatul atacului din Cydonia.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"CENTRARE ZONĂ-TIMP=5 Sec\"\n  STR_CANCEL_UC: \"ANULARE\"\n  STR_NONE: \"Nimic\"\n  STR_UNKNOWN: \"Necunoscut\"\n  STR_POOR: \"Slab\"\n  STR_AVERAGE: \"Mediu\"\n  STR_GOOD: \"Bun\"\n  STR_EXCELLENT: \"Excelent\"\n  STR_BUILD_NEW_BASE_UC: \"CONSTRUIRE BAZĂ NOUĂ\"\n  STR_BASE_INFORMATION: \"INFORMAȚII BAZĂ\"\n  STR_EQUIP_CRAFT: \"DOTĂRI NAVĂ\"\n  STR_BUILD_FACILITIES: \"CONSTRUIRE STRUCTURI\"\n  STR_RESEARCH: \"CERCETARE\"\n  STR_MANUFACTURE: \"PRODUCȚIE\"\n  STR_TRANSFER_UC: \"TRANSFER\"\n  STR_PURCHASE_RECRUIT: \"ACHIZIȚII/RECRUTĂRI\"\n  STR_SACK: \"CONCEDIERE\"\n  STR_SELL_SACK_UC: \"VÂNZĂRI/CONCEDIERI\"\n  STR_GEOSCAPE_UC: \"GEOSFERĂ\"\n  STR_NAME: \"Nume\"\n  STR_AREA: \"Zonă\"\n  STR_BUILD_NEW_BASE: \"Construire Bază Nouă\"\n  STR_CANCEL: \"Anulare\"\n  STR_COST_UC: \"COST>\"\n  STR_CONSTRUCTION_TIME_UC: \"TIMP CONSTRUCȚIE>\"\n  STR_DAY:\n    one: \"{N} zi\"\n    few: \"{N} zile\"\n    other: \"{N} zile\"\n  STR_HOUR:\n    one: \"{N} oră\"\n    few: \"{N} ore\"\n    other: \"{N} ore\"\n  STR_MAINTENANCE_UC: \"ÎNTREȚINERE>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Structuri\"\n  STR_CURRENT_RESEARCH: \"CERCETARE CURENTĂ\"\n  STR_SCIENTISTS_AVAILABLE: \"Cercetători Disponibili>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Cercetători Alocați>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Spațiu Disponibil Laboratoare>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"PROIECT CERCETARE\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"CERCETĂTORI ALOCAȚI\"\n  STR_PROGRESS: \"EVOLUȚIE\"\n  STR_NEW_PROJECT: \"Proiect Nou\"\n  STR_CANCEL_PROJECT: \"ANULARE PROIECT\"\n  STR_NEW_RESEARCH_PROJECTS: \"NOI PROIECTE DE CERCETARE\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"CERCETĂTORI DISPONIBILI>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"SPAȚIU DISPONIBIL LABORATOARE>{ALT}{0}\"\n  STR_INCREASE: \"Creștere\"\n  STR_DECREASE: \"Scădere\"\n  STR_START_PROJECT: \"DEMARARE PROIECT\"\n  STR_CURRENT_PRODUCTION: \"PRODUCȚIE CURENTĂ\"\n  STR_ENGINEERS_AVAILABLE: \"Ingineri Disponibili>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Ingineri Alocați>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Spațiu Disponibil Ateliere>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Fonduri Curente>{ALT}{0}\"\n  STR_ITEM: \"ARTICOL\"\n  STR_ENGINEERS__ALLOCATED: \"Ingineri Alocați\"\n  STR_UNITS_PRODUCED: \"Unități Produse\"\n  STR_TOTAL_TO_PRODUCE: \"Total de Produs\"\n  STR_COST__PER__UNIT: \"Cost{NEWLINE}Unitar{NEWLINE}\"\n  STR_DAYS_HOURS_LEFT: \"Zile/Ore Rămase\"\n  STR_NEW_PRODUCTION: \"Producție Nouă\"\n  STR_PRODUCTION_ITEMS: \"Articole Producție\"\n  STR_CATEGORY: \"CATEGORIE\"\n  STR_START_PRODUCTION: \"PORNIRE PRODUCȚIE\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} ore pentru a produce un articol\"\n  STR_COST_PER_UNIT_: \"Cost unitar>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Spațiu de Lucru Necesar>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"MATERIALE SPECIALE NECESARE\"\n  STR_ITEM_REQUIRED: \"ARTICOL NECESAR\"\n  STR_UNITS_REQUIRED: \"UNITĂȚI NECESARE\"\n  STR_UNITS_AVAILABLE: \"UNITĂȚI DISPONIBILE\"\n  STR_STOP_PRODUCTION: \"OPRIRE PRODUCȚIE\"\n  STR_ENGINEERS_AVAILABLE_UC: \"INGINERI DISPONIBILI>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"SPAȚIU DISPONIBIL ATELIERE>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"PROFIT LUNAR>{ALT}{0}\"\n  STR_INCREASE_UC: \"CREȘTERE\"\n  STR_DECREASE_UC: \"SCĂDERE\"\n  STR_UNITS_TO_PRODUCE: \"Unități de Produs\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Achiziții Articole/Recrutări Personal\"\n  STR_COST_OF_PURCHASES: \"Costul Achizițiilor>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"COST UNITAR\"\n  STR_QUANTITY_UC: \"CANTITATE\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"PERSONAL DISPONIBIL:TOTAL PERSONAL>\"\n  STR_SOLDIERS: \"Soldați\"\n  STR_SCIENTISTS: \"Cercetători\"\n  STR_ENGINEERS: \"Ingineri\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"SPAȚIU UTILIZAT:SPAȚIU DISPONIBIL>\"\n  STR_LIVING_QUARTERS: \"Ansamblu Locuințe\"\n  STR_STORES: \"Depozite\"\n  STR_LABORATORIES: \"Laboratoare\"\n  STR_WORK_SHOPS: \"Ateliere\"\n  STR_HANGARS: \"Hangare\"\n  STR_SHORT_RANGE_DETECTION: \"Detecție Rază Scurtă\"\n  STR_DEFENSE_STRENGTH: \"Putere Sistem Defensiv\"\n  STR_TRANSFERS_UC: \"TRANSFERURI\"\n  STR_TRANSFERS: \"Transferuri\"\n  STR_ARRIVAL_TIME_HOURS: \"Timp Sosire (ore)\"\n  STR_COST_: \"Cost>{ALT}{0}\"\n  STR_AREA_: \"Zonă>{ALT}{0}\"\n  STR_BASE_NAME: \"Denumirea Bazei?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"ALEGERE POZIȚIE LIFT ACCES\"\n  STR_TRANSFER: \"Transfer\"\n  STR_AMOUNT_TO_TRANSFER: \"CANTITATE DE TRANSFERAT\"\n  STR_SELECT_DESTINATION_BASE: \"Alegere Bază Destinație\"\n  STR_COST: \"Cost\"\n  STR_VICTORY_1: \"După intrarea în cameră se remarcă creierul extraterestru - ținta căutărilor. Înainte de a deschide focul, acesta comunică printr-un ecran aflat în apropiere implorând ascultarea argumentelor pentru supraviețuire înainte de a lua decizia de a apăsa pe trăgaci...\"\n  STR_VICTORY_2: \"Creierul spune: 'Acum multe milioane de ani planeta numită de voi Marte era vie. Viața aceasta a fost adusă pe o planetă aridă de către civilizația noastră, același lucru fiind valabil și pentru voi. De milioane de ani v-am vizitat planeta și v-am dezvoltat genetic specia. Nu puteți să ne omorâți, faceți parte din noi...\"\n  STR_VICTORY_3: \"Acesta este centrul civilizației Marțiene - piramidele construite cu milioane de ani înaintea alor voastre - de către o specie care vă este stramoș. Nicio planetă nu ne este inaccesibilă. Această putere poate fi în scurt timp a voastră. Tot ceea ce vă cerem este cooperarea...\"\n  STR_GAME_OVER_1: \"Extratereștrii încearcă să extermine umanitatea distrugând orașe și otrăvind aerul și marea. Rezistența forțelor armate pământene este zadarnică în fața tehnologiei vast superioare. Generațiile supraviețuitoare suferă mutații teribile pe masură ce fug din calea distrugerii. Sunt adunați în tabere de sclavi pentru a transforma Pământul într-o colonie extraterestră, parte a unui imperiu necunoscut.\"\n  STR_GAME_OVER_2: \"Cunoștințele dobândite în cadrul proiectului X-Com sunt pierdute pentru totdeauna. Ai eșuat în încercarea de a salva Pământul.\"\n  STR_VICTORY_4: \"Creierul extraterestru este întrerupt de o explozie de plasmă fierbinte şi drept urmare forțele armate extraterestre sunt înfrânte.\"\n  STR_VICTORY_5: \"Odată ce extratereștrii au pierdut lupta pe Marte au pierdut și Pământul. În scurt timp cercetările X-Com permit umanității să înflorească și să revendice planeta Marte. Amenințarea extraterestră a dispărut, dar pentru cât timp, nimeni nu poate ști...\"\n  STR_YOU_HAVE_FAILED: \"Ai eșuat în încercarea de a opri atacul extraterestru. Una după una, țările finanțatoare semnează pacte cu extratereștrii, aceștia promițând tehnologie, prosperitate și pace. Totuși, în scurt timp devine clar că extratereștrii au alte planuri...\"\n  STR_TOTAL_UC: \"TOTAL\"\n  STR_INCOME: \"Venit\"\n  STR_EXPENDITURE: \"Cheltuieli\"\n  STR_MAINTENANCE: \"Întreținere\"\n  STR_BALANCE: \"Balanță\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"Activități OZN în Zone\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"Activități OZN în Țări\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"Activități X-Com în Zone\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"Activități X-Com în Țări\"\n  STR_FINANCE: \"Finanțe\"\n  STR_DATE_FIRST: \"{0}\"\n  STR_DATE_SECOND: \"{0}\"\n  STR_DATE_THIRD: \"{0}\"\n  STR_DATE_FOURTH: \"{0}\"\n  STR_FINANCE_THOUSANDS: \"mii $\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Materiale speciale insuficiente pentru a produce{NEWLINE}{0}{NEWLINE}în{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Fonduri insuficiente pentru a produce{NEWLINE}{0}{NEWLINE}în{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"Producția de{NEWLINE}{0}{NEWLINE}de la{NEWLINE}{1}{NEWLINE}este completă\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"Lucrările pentru{NEWLINE}{0}{NEWLINE}din{NEWLINE}{1}{NEWLINE}s-au finalizat\"\n  STR_OK_5_SECONDS: \"OK - 5 sec\"\n  STR_RESEARCH_COMPLETED: \"Cercetare Completă\"\n  STR_VIEW_REPORTS: \"RAPORTARE\"\n  STR_WE_CAN_NOW_RESEARCH: \"Putem cerceta\"\n  STR_WE_CAN_NOW_PRODUCE: \"Putem produce\"\n  STR_SUNDAY: \"DUMINICĂ\"\n  STR_MONDAY: \"LUNI\"\n  STR_TUESDAY: \"MARȚI\"\n  STR_WEDNESDAY: \"MIERCURI\"\n  STR_THURSDAY: \"JOI\"\n  STR_FRIDAY: \"VINERI\"\n  STR_SATURDAY: \"SÂMBĂTĂ\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Insuficient {0} pentru realimentare {1} din {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Insuficient(e) {0} pentru re-înarmarea {1} din {2}\"\n  STR_UFO_IS_NOT_RECOVERED: \"OZN pierdut\"\n  STR_UFO_IS_RECOVERED: \"OZN recuperat\"\n  STR_CRAFT_IS_LOST: \"Navă pierdută\"\n  STR_TERROR_CONTINUES: \"Teroarea continuă\"\n  STR_ALIENS_DEFEATED: \"Extratereștrii sunt înfrânți\"\n  STR_BASE_IS_LOST: \"Bază pierdută\"\n  STR_BASE_IS_SAVED: \"Bază salvată\"\n  STR_ALIEN_BASE_STILL_INTACT: \"Bază Extraterestră încă intactă\"\n  STR_ALIEN_BASE_DESTROYED: \"Baza Extraterestră distrusă\"\n  STR_ALIENS_KILLED: \"EXTRATEREȘTRI UCIȘI\"\n  STR_ALIEN_CORPSES_RECOVERED: \"CADAVRE EXTRATERESTRE RECUPERATE\"\n  STR_LIVE_ALIENS_RECOVERED: \"EXTRATEREȘTRI CAPTURAȚi VII\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"ARTEFACTE EXTRATERESTRE RECUPERATE\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"CONTROLUL BAZEI EXTRATERESTRE DISTRUS\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"CIVILI UCIȘI DE EXTRATEREȘTRII\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"CIVILI UCIȘI DE SOLDAȚI X-COM\"\n  STR_CIVILIANS_SAVED: \"CIVILI SALVAȚI\"\n  STR_XCOM_OPERATIVES_KILLED: \"SOLDAȚI X-COM UCIȘI\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"SOLDAȚI X-COM DISPĂRUȚI ÎN MISIUNE\"\n  STR_TANKS_DESTROYED: \"TANCURI DISTRUSE\"\n  STR_XCOM_CRAFT_LOST: \"NAVĂ X-COM PIERDUTĂ\"\n  STR_UFO_RECOVERY: \"RECUPERATE DIN OZN\"\n  STR_ALIEN_BASE_RECOVERY: \"RECUPERATE DIN BAZA EXTRATERESTRĂ\"\n  STR_BASE_UNDER_ATTACK: \"{0} se află sub asediu!\"\n  STR_BASE_DEFENSES_INITIATED: \"APĂRAREA BAZEI INIȚIATĂ\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"SCUTUL GRAVITAȚIONAL RESPINGE OZNul!\"\n  STR_FIRING: \"EXECUTĂ FOC\"\n  STR_HIT: \"LOVIT!\"\n  STR_UFO_DESTROYED: \"OZN DISTRUS!\"\n  STR_MISSED: \"RATAT!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Vânzări Articole/Concedieri Personal\"\n  STR_VALUE_OF_SALES: \"VALOARE VÂNZĂRI> {ALT}{0}\"\n  STR_FUNDS: \"FONDURI> {ALT}{0}\"\n  STR_SELL_SACK: \"Vânzări/Concedieri\"\n  STR_VALUE: \"Valoare\"\n  STR_CRAFT_: \"NAVĂ> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"RECUPERARE OZN DOBORÂT\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"Exercitați prudență - Este posibil să existe inamici în OZN sau în zona unde s-a prăbușit acesta. Misiunea va avea succes numai atunci când toți inamicii au fost eliminați sau neutralizați. După aceea poate fi inițiată recuperarea resturilor de OZN, a artefactelor și cadavrelor extratereștrilor. Pentru a anula misiunea soldații X-Com trebuie să se întoarcă în nava de transport după care se apasă pe butonul 'Abandonare Misiune'.\"\n  STR_UFO_GROUND_ASSAULT: \"ATAC TERESTRU ASUPRA OZN\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"Echipa va explora zona și, dacă e posibil, va pătrunde în OZN. Misiunea va avea succes numai atunci când toți inamicii au fost eliminați sau neutralizați. După aceea poate fi inițiată recuperarea resturilor de OZN, a artefactelor și cadavrelor extratereștrilor. Pentru a anula misiunea soldații X-Com trebuie să se întoarcă în nava de transport după care se apasă pe butonul 'Abandonare Misiune'.\"\n  STR_BASE_DEFENSE: \"APĂRAREA BAZEI\"\n  STR_BASE_UC_: \"BAZĂ> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"O navă extraterestră a aterizat în apropiere. Baza noastră este în pericol. Tot personalul necombatant a fost evacuat cu navele X-Com. Extratereștrii vor pătrunde în bază prin porțile hangarelor sau liftul de acces. Apară baza și structurile vitale cu orice preț - aceasta este o luptă pe viață și pe moarte. Butonul 'Abandonare Misiune' declanșează capitularea și pierderea bazei.\"\n  STR_ALIEN_BASE_ASSAULT: \"ATACAREA BAZEI EXTRATERESTRE\"\n  STR_ALIEN_BASE_ASSAULT_BRIEFING: \"Soldații X-Com au pătruns în baza extraterestră. Centrul de control trebuie distrus pentru a face baza inoperantă. Misiunea va avea succes când toți inamicii au fost eliminați sau când echipa s-a întors în zona de ieșire marcată cu verde (butonul 'Abandonare Misiune' declanșează fuga).\"\n  STR_CYDONIA_BRIEFING: \"Ai ajuns în Cydonia. Pătrunzi într-un mare complex subteran de lângă Sfinxul marțian. Trebuie să distrugi creierul care controlează toate acțiunile extratereștrilor. Soarta umanității se află în mâinile tale...\"\n  STR_TERROR_MISSION: \"MISIUNE DE TERORIZARE\"\n  STR_TERROR_MISSION_BRIEFING: \"Misiunea va avea succes numai atunci când toți inamicii au fost eliminați sau neutralizați. Încearcă să salvezi viețile civililor din zonă prin neutralizarea amenințării extraterestre. Pentru a anula misiunea soldații X-Com trebuie să se întoarcă în nava de transport după care se apasă butonul de 'Abandonare Misiune'.\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"NU EXISTĂ HANGARE LIBERE PENTRU A PRODUCE NAVA!{SMALLLINE}Fiecare navă desemnată unei baze, transferată, cumpărată sau construită foloseste un hangar. Construiește un hangar nou sau transferă o navă în altă bază.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"NU EXISTĂ HANGARE LIBERE PENTRU ACHIZIȚIE!{SMALLLINE}Fiecare navă desemnată unei baze, transferată, cumpărată sau construită foloseste un hangar. Construiește un hangar nou sau transferă o navă în altă bază.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"NU EXISTĂ HANGARE LIBERE PENTRU TRANSFER!{SMALLLINE}Fiecare navă desemnată unei baze, transferată, cumpărată sau construită foloseste un hangar. Construiește un hangar nou sau transferă o navă în altă bază.\"\n  STR_CANNOT_BUILD_HERE: \"NU SE POATE CONSTRUI AICI!{SMALLLINE}Trebuie amplasat lângă o structură existentă.\"\n  STR_NO_FREE_ACCOMODATION: \"NU EXISTĂ LOCURI LIBERE!{SMALLLINE}Baza destinată nu are locuri libere în locuințe.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"SPAȚIU INSUFICIENT ÎN ATELIER!{SMALLLINE}Construiește un atelier nou sau redu activitatea la alte proiecte.\"\n  STR_NOT_ENOUGH_MONEY: \"FONDURI INSUFICIENTE!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"SPAȚIU DE DEPOZITARE INSUFICIENT!{SMALLLINE}Construiește un depozit nou sau transferă articole existente către alte baze.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"LOCUINȚE INSUFICIENTE!{SMALLLINE}Construiește locuințe sau transferă personal către alte baze.\"\n  STR_LAUNCH_INTERCEPTION: \"LANSARE INTERCEPȚIE\"\n  STR_CRAFT: \"NAVĂ\"\n  STR_STATUS: \"STARE\"\n  STR_BASE: \"BAZĂ\"\n  STR_READY: \"PREGĂTIT\"\n  STR_OUT: \"ÎN MISIUNE\"\n  STR_REPAIRS: \"REPARAȚII\"\n  STR_REFUELLING: \"REALIMENTARE\"\n  STR_REARMING: \"REÎNARMARE\"\n  STR_TARGET: \"ȚINTĂ: {0}\"\n  STR_WAY_POINT: \"PUNCT RUTĂ\"\n  STR_ARE_YOU_SURE_CYDONIA: \"Sigur trimitem această navă în misiune către Cydonia?\"\n  STR_YES: \"DA\"\n  STR_NO: \"NU\"\n  STR_SELECT_DESTINATION: \"ALEGERE DESTINAȚIE\"\n  STR_CYDONIA: \"CYDONIA\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"ALEGERE LOCAȚIE BAZĂ NOUĂ\"\n  STR_RETURN_TO_BASE: \"REVENIRE LA BAZĂ\"\n  STR_SELECT_NEW_TARGET: \"ALEGERE ȚINTĂ NOUĂ\"\n  STR_PATROL: \"PATRULARE\"\n  STR_STATUS_: \"STARE>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"AVARIAT - REVENIRE LA BAZĂ\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"REZERVOR GOL - REVENIRE LA BAZĂ\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"MISIUNE COMPLETĂ - REVENIRE LA BAZĂ\"\n  STR_PATROLLING: \"PATRULEAZĂ\"\n  STR_TAILING_UFO: \"URMĂREȘTE OZN\"\n  STR_INTERCEPTING_UFO: \"INTERCEPTARE OZN-{0}\"\n  STR_RETURNING_TO_BASE: \"REVENIRE LA BAZĂ\"\n  STR_DESTINATION_UC_: \"DESTINAȚIE: {0}\"\n  STR_BASE_UC: \"BAZĂ>{ALT}{0}\"\n  STR_SPEED_: \"VITEZĂ>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"VITEZĂ MAXIMĂ>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"ALTITUDINE>{ALT}{0}\"\n  STR_VERY_LOW: \"FOARTE JOASĂ\"\n  STR_LOW_UC: \"JOASĂ\"\n  STR_HIGH_UC: \"MARE\"\n  STR_VERY_HIGH: \"FOARTE MARE\"\n  STR_FUEL: \"COMBUSTIBIL>{ALT}{0}\"\n  STR_WEAPON_ONE: \"ARMA-1>{ALT}{0}\"\n  STR_NONE_UC: \"NIMIC\"\n  STR_ROUNDS_: \"SALVE>{ALT}{0}\"\n  STR_WEAPON_TWO: \"ARMA-2>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"NAVĂ INTERCEPȚIE\"\n  STR_BASE_: \"Bază>{0}\"\n  STR_NAME_UC: \"NUME\"\n  STR_AMMO_: \"MUNIȚIE>{ALT}{0}\"\n  STR_CREW: \"ECHIPAJ\"\n  STR_EQUIPMENT_UC: \"ECHIPAMENT\"\n  STR_ARMOR: \"ARMURĂ\"\n  STR_MAX: \"MAXIM>{ALT}{0}\"\n  STR_ROOKIE: \"Recrut\"\n  STR_SQUADDIE: \"Fruntaș\"\n  STR_SERGEANT: \"Sergent\"\n  STR_CAPTAIN: \"Căpitan\"\n  STR_COLONEL: \"Colonel\"\n  STR_COMMANDER: \"General\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Alegere Echipă pentru {0}\"\n  STR_SORT_BY: \"SORTARE DUPĂ...\"\n  STR_ORIGINAL_ORDER: \"ORDINE IMPLICITĂ\"\n  STR_MISSIONS2: \"MISIUNI\"\n  STR_KILLS2: \"VICTIME\"\n  STR_WOUND_RECOVERY2: \"VINDECARE RĂNI\"\n  STR_SPACE_AVAILABLE: \"SPAȚIU DISPONIBIL>{ALT}{0}\"\n  STR_SPACE_USED: \"SPAȚIU UTILIZAT>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"SPAȚIU UTILIZAT\"\n  STR_RANK: \"RANG\"\n  STR_WOUNDED: \"RĂNIT\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Echipament pentru {0}\"\n  STR_DEFENSE_VALUE: \"Valoare Defensivă\"\n  STR_HIT_RATIO: \"Raport Lovire\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}pregătit de{NEWLINE}aterizare lângă{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"Începere Misiune?\"\n  STR_SELECT_ARMAMENT: \"Alegere Armament\"\n  STR_AMMUNITION_AVAILABLE: \"MUNIȚIE DISPONIBILĂ\"\n  STR_ARMAMENT: \"ARMAMENT\"\n  STR_NOT_AVAILABLE: \"N.A.\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"ALEGERE ARMURĂ PENTRU{NEWLINE}{0}\"\n  STR_TYPE: \"TIP\"\n  STR_PERSONAL_ARMOR_UC: \"ARMURĂ PERSONALĂ\"\n  STR_POWER_SUIT_UC: \"COSTUM FORȚĂ\"\n  STR_FLYING_SUIT_UC: \"COSTUM ZBOR\"\n  STR_SELECT_ARMOR: \"Alegere Armură\"\n  STR_NORTH: \"NORD\"\n  STR_NORTH_EAST: \"NORD-EST\"\n  STR_EAST: \"EST\"\n  STR_SOUTH_EAST: \"SUD-EST\"\n  STR_SOUTH: \"SUD\"\n  STR_SOUTH_WEST: \"SUD-VEST\"\n  STR_WEST: \"VEST\"\n  STR_NORTH_WEST: \"NORD-VEST\"\n  STR_SELECT_ACTION: \"ALEGERE ACȚIUNE\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"CONTINUARE URMĂRIRE ȘI INTERCEPTARE\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"URMĂRIRE FĂRĂ INTERCEPTARE\"\n  STR_VERY_LARGE: \"FOARTE MARE\"\n  STR_LARGE: \"MARE\"\n  STR_MEDIUM_UC: \"MEDIU\"\n  STR_SMALL: \"MIC\"\n  STR_VERY_SMALL: \"FOARTE MIC\"\n  STR_GROUNDED: \"LA SOL\"\n  STR_DETECTED: \"Detectat\"\n  STR_SIZE_UC: \"DIMENSIUNE\"\n  STR_ALTITUDE: \"ALTITUDINE\"\n  STR_HEADING: \"DIRECȚIE\"\n  STR_SPEED: \"VITEZĂ\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"CENTRARE OZN-TIMP=5 Sec\"\n  STR_TRACKING_LOST: \"SEMNAL PIERDUT\"\n  STR_REDIRECT_CRAFT: \"REDIRECȚIONARE NAVĂ\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"ULTIMA LOCAȚIE CUNOSCUTĂ\"\n  STR_UFO_: \"OZN-{0}\"\n  STR_ALIEN_BASE_: \"BAZĂ EXTRATERESTRĂ-{0}\"\n  STR_CRASH_SITE_: \"OZN DOBORÂT-{0}\"\n  STR_LANDING_SITE_: \"OZN ATERIZAT-{0}\"\n  STR_WAY_POINT_: \"PUNCT RUTĂ-{0}\"\n  STR_TERROR_SITE: \"ZONĂ TERORIZATĂ-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}a ajuns la{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"Patrulează\"\n  STR_ALIEN_ORIGINS: \"Originile Extratereștrilor\"\n  STR_THE_MARTIAN_SOLUTION: \"Soluția Marțiană\"\n  STR_CYDONIA_OR_BUST: \"Cydonia sau Eșec\"\n  STR_UFOPAEDIA: \"UFOpedia\"\n  STR_XCOM_CRAFT_ARMAMENT: \"NAVE ȘI ARMAMENT X-COM\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"TANCURI AUTOMATIZATE\"\n  STR_WEAPONS_AND_EQUIPMENT: \"ARME ȘI ECHIPAMENTE\"\n  STR_ALIEN_ARTIFACTS: \"ARTEFACTE EXTRATERESTRE\"\n  STR_BASE_FACILITIES: \"CONSTRUCȚII BAZĂ\"\n  STR_ALIEN_LIFE_FORMS: \"FIINȚE EXTRATERESTRE\"\n  STR_ALIEN_RESEARCH_UC: \"CERCETĂRI EXTRATERESTRE\"\n  STR_UFO_COMPONENTS: \"COMPONENTE OZN\"\n  STR_UFOS: \"OZNuri EXTRATERESTRE\"\n  STR_SELECT_ITEM: \"SELECTARE ARTICOL\"\n  STR_ACCELERATION: \"ACCELERAȚIE>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"VOLUM REZERVOR>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"SOCLURI ARMAMENT>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"REZISTENȚĂ AVARII>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"SPAȚIU ÎNCĂRCĂTURĂ>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"SPAȚIU TANCURI>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Putere Foc\"\n  STR_RANGE: \"Rază Acțiune\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Precizie Foc\"\n  STR_RE_LOAD_TIME: \"Timp Reîncărcare\"\n  STR_SECONDS: \"{0}s\"\n  STR_DAMAGE_ARMOR_PIERCING: \"PERCUTANT\"\n  STR_DAMAGE_INCENDIARY: \"INCENDIAR\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"EXPLOZIV\"\n  STR_DAMAGE_LASER_BEAM: \"FASCICUL LASER\"\n  STR_DAMAGE_PLASMA_BEAM: \"FASCICUL PLASMĂ\"\n  STR_DAMAGE_STUN: \"PARALIZANT\"\n  STR_DAMAGE_MELEE: \"MELEU\"\n  STR_DAMAGE_ACID: \"ACID\"\n  STR_DAMAGE_SMOKE: \"FUMIGEN\"\n  STR_SHOT_TYPE: \"MODALITATE FOC\"\n  STR_ACCURACY_UC: \"PRECIZIE\"\n  STR_TIME_UNIT_COST: \"RĂSTIMP\"\n  STR_DAMAGE_UC: \"PUTERE\"\n  STR_AMMO: \"MUNIȚIE\"\n  STR_SHOT_TYPE_AUTO: \"Automat\"\n  STR_SHOT_TYPE_SNAP: \"Rapid\"\n  STR_SHOT_TYPE_AIMED: \"Ochit\"\n  STR_CONSTRUCTION_TIME: \"Timp Construcție\"\n  STR_CONSTRUCTION_COST: \"Cost Construcție\"\n  STR_MAINTENANCE_COST: \"Cost Întreținere\"\n  STR_LOW: \"Scăzut\"\n  STR_MEDIUM: \"Mediu\"\n  STR_HIGH: \"Mare\"\n  STR_CRAFT_WEAPON: \"Armă Nave\"\n  STR_CRAFT_AMMUNITION: \"Muniție Nave\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Tanc\"\n  STR_WEAPON: \"Armă\"\n  STR_AMMUNITION: \"Muniție\"\n  STR_EQUIPMENT: \"Echipament\"\n  STR_ALIEN_CORPSE: \"Cadavru Extraterestru\"\n  STR_UFO_COMPONENT: \"Componentă OZN\"\n  STR_PERSONAL_ARMOR: \"Armură Personală\"\n  STR_RAW_MATERIALS: \"Materii Prime\"\n  STR_HWP_CANNON_SHELLS: \"Proiectile Tanc\"\n  STR_ALIEN: \"Extraterestru\"\n  STR_SECTOID: \"Sectoid\"\n  STR_SNAKEMAN: \"Snakeman\"\n  STR_ETHEREAL: \"Ethereal\"\n  STR_MUTON: \"Muton\"\n  STR_FLOATER: \"Floater\"\n  STR_CELATID: \"Celatid\"\n  STR_SILACOID: \"Silacoid\"\n  STR_CHRYSSALID: \"Chryssalid\"\n  STR_ZOMBIE: \"Zombie\"\n  STR_REAPER: \"Reaper\"\n  STR_SECTOPOD: \"Sectopod\"\n  STR_CYBERDISC: \"Cyberdisc\"\n  STR_LIVE_COMMANDER: \"Comandant\"\n  STR_LIVE_LEADER: \"Lider\"\n  STR_LIVE_ENGINEER: \"Inginer\"\n  STR_LIVE_MEDIC: \"Medic\"\n  STR_LIVE_NAVIGATOR: \"Pilot\"\n  STR_LIVE_SOLDIER: \"Soldat\"\n  STR_LIVE_TERRORIST: \"Terorist\"\n  STR_FLOATER_SOLDIER: \"Soldat Floater\"\n  STR_FLOATER_NAVIGATOR: \"Pilot Floater\"\n  STR_FLOATER_MEDIC: \"Medic Floater\"\n  STR_FLOATER_ENGINEER: \"Inginer Floater\"\n  STR_FLOATER_LEADER: \"Lider Floater\"\n  STR_FLOATER_COMMANDER: \"Comandant Floater\"\n  STR_SECTOID_SOLDIER: \"Soldat Sectoid\"\n  STR_SECTOID_NAVIGATOR: \"Pilot Sectoid\"\n  STR_SECTOID_MEDIC: \"Medic Sectoid\"\n  STR_SECTOID_ENGINEER: \"Inginer Sectoid\"\n  STR_SECTOID_LEADER: \"Lider Sectoid\"\n  STR_SECTOID_COMMANDER: \"Comandant Sectoid\"\n  STR_SNAKEMAN_SOLDIER: \"Soldat Snakeman\"\n  STR_SNAKEMAN_NAVIGATOR: \"Pilot Snakeman\"\n  STR_SNAKEMAN_ENGINEER: \"Inginer Snakeman\"\n  STR_SNAKEMAN_LEADER: \"Lider Snakeman\"\n  STR_SNAKEMAN_COMMANDER: \"Comandant Snakeman\"\n  STR_MUTON_SOLDIER: \"Soldat Muton\"\n  STR_MUTON_NAVIGATOR: \"Pilot Muton\"\n  STR_MUTON_ENGINEER: \"Inginer Muton\"\n  STR_ETHEREAL_SOLDIER: \"Soldat Ethereal\"\n  STR_ETHEREAL_LEADER: \"Lider Ethereal\"\n  STR_ETHEREAL_COMMANDER: \"Comandant Ethereal\"\n  STR_CYBERDISC_TERRORIST: \"Terorist Cyberdisc\"\n  STR_REAPER_TERRORIST: \"Terorist Reaper\"\n  STR_CHRYSSALID_TERRORIST: \"Terorist Chryssalid\"\n  STR_CELATID_TERRORIST: \"Terorist Celatid\"\n  STR_SILACOID_TERRORIST: \"Terorist Silacoid\"\n  STR_SECTOPOD_TERRORIST: \"Terorist Sectopod\"\n  STR_UFO_POWER_SOURCE: \"Sursă Energie OZN\"\n  STR_UFO_NAVIGATION: \"Sistem Navigație OZN\"\n  STR_UFO_CONSTRUCTION: \"Construcție OZN\"\n  STR_ALIEN_FOOD: \"Hrană Extraterestră\"\n  STR_ALIEN_REPRODUCTION: \"Reproducție Extraterestră\"\n  STR_ALIEN_ENTERTAINMENT: \"Recreere Extraterestră\"\n  STR_ALIEN_SURGERY: \"Chirurgie Extraterestră\"\n  STR_EXAMINATION_ROOM: \"Cameră Examinări\"\n  STR_ALIEN_ALLOYS: \"Aliaje Extraterestre\"\n  STR_ALIEN_HABITAT: \"Habitat Extraterestru\"\n  STR_POWER_SUIT: \"Costum Forță\"\n  STR_FLYING_SUIT: \"Costum Zbor\"\n  STR_HWP_ROCKETS: \"Rachete (Tanc)\"\n  STR_HWP_FUSION_BOMB: \"Bombă Fuziune (Tanc)\"\n  STR_LASER_WEAPONS: \"Arme Laser\"\n  STR_NEW_FIGHTER_CRAFT: \"Navă de Luptă Nouă\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Transportor de Luptă Nou\"\n  STR_ULTIMATE_CRAFT: \"Nava Supremă\"\n  STR_LASER_PISTOL: \"Pistol Laser\"\n  STR_LASER_RIFLE: \"Pușcă Laser\"\n  STR_HEAVY_LASER: \"Laser Greu\"\n  STR_LASER_CANNON: \"Artilerie Laser\"\n  STR_PLASMA_CANNON: \"Artilerie Plasmă\"\n  STR_FUSION_MISSILE: \"Rachetă Fuziune\"\n  STR_LASER_DEFENSE: \"Defensivă Laser\"\n  STR_PLASMA_DEFENSE: \"Defensivă Plasmă\"\n  STR_FUSION_DEFENSE: \"Defensivă Fuziune\"\n  STR_GRAV_SHIELD: \"Scut Gravitațional\"\n  STR_MIND_SHIELD: \"Scut Mental\"\n  STR_PSI_LAB: \"Laborator-Psi\"\n  STR_MOTION_SCANNER: \"Detector Mișcare\"\n  STR_MEDI_KIT: \"Trusă Medicală\"\n  STR_TANK_CANNON: \"Tanc/Artilerie\"\n  STR_TANK_ROCKET_LAUNCHER: \"Tanc/Lansator Rachete\"\n  STR_TANK_LASER_CANNON: \"Tanc/Artilerie Laser\"\n  STR_HOVERTANK_PLASMA: \"Hovertanc/Plasmă\"\n  STR_HOVERTANK_LAUNCHER: \"Hovertanc/Lansator\"\n  STR_STINGRAY_LAUNCHER: \"Lansator Stingray\"\n  STR_AVALANCHE_LAUNCHER: \"Lansator Avalanche\"\n  STR_CANNON: \"Artilerie\"\n  STR_FUSION_BALL_LAUNCHER: \"Lansator Sfere Fuziune\"\n  STR_PLASMA_BEAM: \"Artilerie Plasmă\"\n  STR_STINGRAY_MISSILES: \"Rachete Stingray\"\n  STR_AVALANCHE_MISSILES: \"Rachete Avalanche\"\n  STR_CANNON_ROUNDS_X50: \"Salve Artilerie (x50)\"\n  STR_FUSION_BALL: \"Sferă Fuziune\"\n  STR_SOLDIER: \"Soldat\"\n  STR_SCIENTIST: \"Cercetător\"\n  STR_ENGINEER: \"Inginer\"\n  STR_NORTH_AMERICA: \"America de Nord\"\n  STR_ARCTIC: \"Oceanul Arctic\"\n  STR_ANTARCTICA: \"Antarctica\"\n  STR_SOUTH_AMERICA: \"America de Sud\"\n  STR_EUROPE: \"Europa\"\n  STR_NORTH_AFRICA: \"Africa de Nord\"\n  STR_SOUTHERN_AFRICA: \"Africa de Sud\"\n  STR_CENTRAL_ASIA: \"Asia Centrală\"\n  STR_SOUTH_EAST_ASIA: \"Asia de Sud-Est\"\n  STR_SIBERIA: \"Siberia\"\n  STR_AUSTRALASIA: \"Australasia\"\n  STR_PACIFIC: \"Pacific\"\n  STR_NORTH_ATLANTIC: \"Atlanticul de Nord\"\n  STR_SOUTH_ATLANTIC: \"Atlanticul de Sud\"\n  STR_INDIAN_OCEAN: \"Oceanul Indian\"\n  STR_ALIEN_RESEARCH: \"Cercetări Extraterestre\"\n  STR_ALIEN_HARVEST: \"Recoltări Extraterestre\"\n  STR_ALIEN_ABDUCTION: \"Răpiri Extraterestre\"\n  STR_ALIEN_INFILTRATION: \"Infiltrări Extraterestre\"\n  STR_ALIEN_BASE: \"Bază Extraterestră\"\n  STR_ALIEN_TERROR: \"Teroare Extraterestră\"\n  STR_ALIEN_RETALIATION: \"Represalii Extraterestre\"\n  STR_ALIEN_SUPPLY: \"Provizii Extraterestre\"\n  STR_MAXIMUM_SPEED: \"Viteză Maximă\"\n  STR_HYPER_WAVE_DECODER_UC: \"DECODOR HIPER-UNDĂ\"\n  STR_SKYRANGER: \"SKYRANGER\"\n  STR_LIGHTNING: \"LIGHTNING\"\n  STR_AVENGER: \"AVENGER\"\n  STR_INTERCEPTOR: \"INTERCEPTOR\"\n  STR_FIRESTORM: \"FIRESTORM\"\n  STR_UFO: \"OZN\"\n  STR_STINGRAY: \"STINGRAY\"\n  STR_AVALANCHE: \"AVALANCHE\"\n  STR_CANNON_UC: \"ARTILERIE\"\n  STR_FUSION_BALL_UC: \"SFERĂ FUZIUNE\"\n  STR_LASER_CANNON_UC: \"ARTILERIE LASER\"\n  STR_PLASMA_BEAM_UC: \"FASCICUL PLASMĂ\"\n  STR_DAMAGE_CAPACITY: \"Rezistență Avarii\"\n  STR_WEAPON_POWER: \"Putere Armament\"\n  STR_WEAPON_RANGE: \"Rază Acțiune\"\n  STR_ACCESS_LIFT: \"Lift Acces\"\n  STR_LABORATORY: \"Laborator\"\n  STR_WORKSHOP: \"Atelier\"\n  STR_SMALL_RADAR_SYSTEM: \"Sistem Radar Mic\"\n  STR_LARGE_RADAR_SYSTEM: \"Sistem Radar Mare\"\n  STR_MISSILE_DEFENSES: \"Defensivă Rachete\"\n  STR_GENERAL_STORES: \"Depozite Generale\"\n  STR_ALIEN_CONTAINMENT: \"Carantină Extratereștrii\"\n  STR_LASER_DEFENSES: \"Defensivă Laser\"\n  STR_PLASMA_DEFENSES: \"Defensivă Plasmă\"\n  STR_FUSION_BALL_DEFENSES: \"Defensivă Sfere Fuziune\"\n  STR_PSIONIC_LABORATORY: \"Laborator Psionic\"\n  STR_HYPER_WAVE_DECODER: \"Decodor Hiper-Undă\"\n  STR_HANGAR: \"Hangar\"\n  STR_USA: \"SUA\"\n  STR_RUSSIA: \"RUSIA\"\n  STR_UK: \"MAREA BRITANIE\"\n  STR_FRANCE: \"FRANȚA\"\n  STR_GERMANY: \"GERMANIA\"\n  STR_ITALY: \"ITALIA\"\n  STR_SPAIN: \"SPANIA\"\n  STR_CHINA: \"CHINA\"\n  STR_JAPAN: \"JAPONIA\"\n  STR_INDIA: \"INDIA\"\n  STR_BRAZIL: \"BRAZILIA\"\n  STR_AUSTRALIA: \"AUSTRALIA\"\n  STR_NIGERIA: \"NIGERIA\"\n  STR_SOUTH_AFRICA: \"AFRICA DE SUD\"\n  STR_EGYPT: \"EGIPT\"\n  STR_CANADA: \"CANADA\"\n  STR_TANK: \"Tanc\"\n  STR_CIVILIAN: \"Civil\"\n  STR_JAN: \"Ian\"\n  STR_FEB: \"Feb\"\n  STR_MAR: \"Mar\"\n  STR_APR: \"Apr\"\n  STR_MAY: \"Mai\"\n  STR_JUN: \"Iun\"\n  STR_JUL: \"Iul\"\n  STR_AUG: \"Aug\"\n  STR_SEP: \"Sep\"\n  STR_OCT: \"Oct\"\n  STR_NOV: \"Noi\"\n  STR_DEC: \"Dec\"\n  STR_INTERNATIONAL_RELATIONS: \"Relații Internaționale\"\n  STR_COUNTRY: \"Țară\"\n  STR_FUNDING: \"Finanțare\"\n  STR_CHANGE: \"Variație\"\n  STR_WEAPON_SYSTEMS: \"ARMAMENT\"\n  STR_HWPS: \"TANCURI\"\n  STR_DAMAGE_UC_: \"AVARII>{ALT}{0}\"\n  STR_ACCESS_LIFT_UFOPEDIA: \"Liftul de acces permite transferul echipamentului și personalului în și din baza subterană. Este întotdeauna prima structură construită în noua locație. Zona liftului este vulnerabilă intruziunii posibilelor forțe ostile.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Fiecare ansamblu de locuințe furnizează spațiu pentru maxim 50 de oameni. Este prevăzut cu zone de recreere, alimentație și odihnă.\"\n  STR_LABORATORY_UFOPEDIA: \"Într-un laborator pot lucra până la 50 de cercetători. Laboratoarele sunt echipate cu cea mai nouă tehnologie pentru cercetarea materialelor, biochimiei și armelor. Cercetătorii X-Com au acces privilegiat la cele mai bune laboratoare din lume, atât civile cât și militare.\"\n  STR_WORKSHOP_UFOPEDIA: \"Atelierul conține toate echipamentele necesare producerii obiectelor bazate pe schițele venite de la laboratoare. Până la 50 de ingineri pot să lucreze în atelier, deși obiectele produse o să ocupe de asemenea spațiu.\"\n  STR_SMALL_RADAR_SYSTEM_UFOPEDIA: \"Un mic sistem de detecție cu o rază de acțiune efectivă de 300 de mile marine, legat la rețeaua de sateliți geostaționari pentru căutarea la sol. Fiecare sistem are o șansă de 10% la fiecare 30 de minute de a detecta un obiect de dimensiune medie.\"\n  STR_LARGE_RADAR_SYSTEM_UFOPEDIA: \"Un sistem mare de detecție cu o rază de acțiune efectivă de 450 de mile marine, legat la rețeaua de sateliți geostaționari pentru căutarea la sol. Fiecare sistem are o șansă de 20% la fiecare 30 de minute de a detecta un obiect de dimensiune medie.\"\n  STR_MISSILE_DEFENSES_UFOPEDIA: \"Furnizează o oarecare protecție împotriva incursiunilor navelor forțelor ostile care încearcă să aterizeze lângă bază.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"Toate echipamentele, armele, munițiile, materialele recuperate și tancurile sunt păstrate în depozite, inclusiv echipamentele atribuite navelor din hangare.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"Extratereștrii vii necesită un habitat special pentru a fi menținuți în viață. Structura poate păstra până la 10 forme de viață extraterestre în unități autonome.\"\n  STR_LASER_DEFENSES_UFOPEDIA: \"Furnizează protecție împotriva incursiunilor navelor inamice.\"\n  STR_PLASMA_DEFENSES_UFOPEDIA: \"Furnizează o protecție puternică și eficientă împotriva incursiunilor navelor inamice.\"\n  STR_FUSION_BALL_DEFENSES_UFOPEDIA: \"Furnizează cea mai eficientă defensivă împotriva atacurilor extraterestre. Aceste bombe pot crea implozii antimaterie care distrug totul pe o anumită rază.\"\n  STR_GRAV_SHIELD_UFOPEDIA: \"Scutul respinge navele extraterestre care încearcă să aterizeze lângă bază suficient de mult timp pentru ca sistemele defensive să mai tragă o dată. Practic, acest sistem dublează efectul oricărui sistem defensiv din bază.\"\n  STR_MIND_SHIELD_UFOPEDIA: \"Ținând cont că navele extraterestre se folosesc de undele cerebrale pentru a detecta prezența oamenilor, atunci cea mai eficientă contramăsură este să ecranăm undele cerebrale din bază. Această construcție va reduce drastic șansele de a fi detectați de navele extraterestre.\"\n  STR_PSIONIC_LABORATORY_UFOPEDIA: \"Poate evalua potențialul psionic al tuturor soldaților din bază și furnizează antrenamentul necesar pentru a-și folosi abilitățile. Fiecare laborator poate antrena până la 10 soldați. Antrenamentul este alocat la sfarșitul fiecărei luni. Abilitățile psionice pot fi folosite împreună cu un Amplificator-Psi în luptă pentru atacuri psionice.\"\n  STR_HYPER_WAVE_DECODER_UFOPEDIA: \"Comunicațiile extraterestre se bazează pe o undă supra-dimensională ce se transmite aproape instantaneu. Această structură interceptează trasmisiunile OZN, decodează informația și arată tipul OZNului, specia extraterestră și natura activității desfășurate.\"\n  STR_HANGAR_UFOPEDIA: \"Fiecare hangar poate găzdui o singură navă. Conține echipamente pentru întreținerea, alimentarea și repararea navelor X-Com. Fiecare navă alocată unei baze trebuie să aibă un hangar liber atribuit ce nu poate fi folosit de altă navă, chiar dacă nava atribuită se află într-o misiune.\"\n  STR_PISTOL_UFOPEDIA: \"Pistolul standard emis de către X-Com este un semiautomat puternic având un încarcător cu 12 gloanțe.\"\n  STR_RIFLE_UFOPEDIA: \"Această pușcă cu lunetă foarte precisă are cătare laser și încărcătoare cu 20 de gloanțe de calibrul 6.7mm.\"\n  STR_HEAVY_CANNON_UFOPEDIA: \"Tunul de artilerie grea este o armă devastatoare dar anevoioasă. Versatilitatea ei vine din faptul că poate folosi trei tipuri de muniție - percutantă, incendiară și explozivă.\"\n  STR_AUTO_CANNON_UFOPEDIA: \"Tunul de artilerie automată combină versatilitatea și puterea tunului de artilerie grea cu o rată de foc mai mare.\"\n  STR_ROCKET_LAUNCHER_UFOPEDIA: \"Lansatorul de rachete este un sistem ghidat prin laser ce poate trage cu trei tipuri de rachete de diverse dimensiuni.\"\n  STR_LASER_PISTOL_UFOPEDIA: \"Pistolul laser este o implementare eficientă a noii tehnologii. Prezintă confortul unui pistol dar este mai precis și are o rată de foc mai mare.\"\n  STR_LASER_RIFLE_UFOPEDIA: \"Pușca laser este o versiune mai puternică și mai precisă a modelului de pistol laser.\"\n  STR_HEAVY_LASER_UFOPEDIA: \"Laserul greu este anevoios, dar extrem de eficient.\"\n  STR_GRENADE_UFOPEDIA: \"Această grenadă standard prezintă un cronometru sofisticat, pentru un control de precizie.\"\n  STR_SMOKE_GRENADE_UFOPEDIA: \"Grenadele fumigene sunt utile, oferind adăpost într-un câmp de luptă deschis. A se folosi cu grijă, inamicul putând beneficia de asemenea de ele.\"\n  STR_PROXIMITY_GRENADE_UFOPEDIA: \"O grenadă de proximitate poate fi aruncată precum o grenadă normală dar odată activată este declanșată de mișcările din apropiere. Pentru a folosi corect acest echipament sunt necesare abilități bune și multă prudență.\"\n  STR_HIGH_EXPLOSIVE_UFOPEDIA: \"Acest explozibil ar trebui folosit numai pentru demolări. Personalul trebuie să păstreze distanța de zonele în curs de demolare.\"\n  STR_MOTION_SCANNER_UFOPEDIA: \"Acest dispozitiv sofisticat folosește o varietate de detectori și algoritmi avansați pentru a identifica unitățile aflate în mișcare. Totuși necesită practică pentru a fi folosit eficient. Apasă pe reprezentarea detectorului de mișcare de pe afișajul tactic. Alege 'Folosire Detector' din meniu. Afișajul scanerului arată o săgeată în mijloc - direcția în care se uită soldatul (nordul este în sus). Cercurile pulsatorii arată unitățile care s-au mișcat recent. Unitățile mari sau care se mișcă repede vor produce cercuri mai mari. Unitățile statice nu vor fi detectate.\"\n  STR_MEDI_KIT_UFOPEDIA: \"Această trusă combină facilitatea de vindecare cu analgezice și stimulenți. Pentru a folosi trusa trebuie să stai cu fața la soldatul care are nevoie de tratament. Dacă soldatul este paralizat trebuie să stai deasupra corpului acestuia. Apasă pe reprezentarea trusei și alege 'Folosire Trusă' din meniu.{NEWLINE}TRATAMENT> Zonele cu roșu sunt rănile grave. Apasă pe o zonă rănită, apoi pe butonul 'Vindecare'. O rană gravă va fi vindecată și o parte din sănătate refăcută.{NEWLINE}STIMULENT> Va restaura energia și resuscita soldații inconștienți (paralizați). Pentru a resuscita un soldat incoștient trebuie să stai deasupra corpului acestuia.{NEWLINE}CALMANT> Va restaura moralul soldaților răniți până la un nivel echivalent cu sănătatea pierdută.\"\n  STR_PSI_AMP_UFOPEDIA: \"Poate fi folosit numai de către soldații cu abilități psionice. În luptă, apasă pe Amplificator-Psi, alege tipul atacului și selectează o țintă. Sunt două tipuri de atac psionic:{NEWLINE}PANICARE> Dacă atacul are succes va reduce moralul țintei, putând induce panica.{NEWLINE}CONTROL MENTAL> Dacă are succes vei avea imediat control asupra unității inamice ca și cum ți-ar fi aparținut. Este mai dificil să ai succes cu acest tip de atac.\"\n  STR_STUN_ROD_UFOPEDIA: \"Acest dispozitiv poate fi folosit numai în lupta corp la corp și va paraliza un organism viu folosind șocuri electrice însă fără a îl omorî.\"\n  STR_MIND_PROBE_UFOPEDIA: \"Acesta este un dispozitiv extraterestru de comunicare care este folosit pentru a extrage informații direct din undele cerebrale. Soldații X-Com pot folosi acest dispozitiv în luptă pentru a afișa caracteristicile extraterestrului. Apasă pe reprezentarea sondei și alege opțiunea 'Folosire Sondă Mentală' apoi selectează un extraterestru.\"\n  STR_PLASMA_PISTOL_UFOPEDIA: \"Pistolul cu plasmă este o armă letală bazată pe accelerarea particulelor din cadrul unui minuscul câmp antigravitațional.\"\n  STR_PLASMA_RIFLE_UFOPEDIA: \"Aceasta este o armă devastatoare de mare putere, bazată pe accelerarea particulelor din cadrul unui minuscul câmp antigravitațional.\"\n  STR_HEAVY_PLASMA_UFOPEDIA: \"Aceasta este o armă devastator de puternică bazată pe accelerarea particulelor din cadrul unui minuscul câmp antigravitațional.\"\n  STR_BLASTER_LAUNCHER_UFOPEDIA: \"Acesta este un lansator de rachete teleghidate care proiectează puternice 'bombe explozive'. Când se trage cu arma, aceasta va genera 'puncte rută' pe care bomba le va traversa. După ce s-au trasat suficiente puncte se apasă pe butonul de lansare.\"\n  STR_SMALL_LAUNCHER_UFOPEDIA: \"Un mic lansator care proiectează bombe paralizante. Foarte folositor pentru capturarea extratereștrilor vii.\"\n  STR_ALIEN_GRENADE_UFOPEDIA: \"Acest dispozitiv funcționează asemenea unei grenade pământene - numai că este mult mai puternică.\"\n  STR_SMALL_SCOUT: \"Navă Observare mică\"\n  STR_MEDIUM_SCOUT: \"Navă Observare medie\"\n  STR_LARGE_SCOUT: \"Navă Observare mare\"\n  STR_HARVESTER: \"Navă Recoltare\"\n  STR_ABDUCTOR: \"Navă Răpire\"\n  STR_TERROR_SHIP: \"Navă Terorizare\"\n  STR_BATTLESHIP: \"Navă Război\"\n  STR_SUPPLY_SHIP: \"Navă Aprovizionare\"\n  STR_RATING: \"EVALUARE> {0}\"\n  STR_RATING_TERRIBLE: \"GROAZNIC!\"\n  STR_RATING_POOR: \"SLAB!\"\n  STR_RATING_OK: \"OK\"\n  STR_RATING_GOOD: \"BUN!\"\n  STR_RATING_EXCELLENT: \"EXCELENT!\"\n  STR_SCORE: \"PUNCTAJ\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"RAPORT LUNAR PROIECT X-COM\"\n  STR_MONTH: \"Lună> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"Consiliul națiunilor finanțatoare este în general mulțumit de progresul realizat.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"Consiliul națiunilor finanțatoare este foarte mulțumit de progresul realizat. Continuă tot așa!\"\n  STR_COUNCIL_IS_DISSATISFIED: \"Consiliul națiunilor finanțatoare este nemulțumit de performanța ta. Trebuie să îți mărești eficacitatea în lupta cu amenințarea extraterestră sau riști încheierea proiectului.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"Nu ai reușit să faci față amenințării extraterestre iar consiliul națiunilor finanțatoare a decis cu regret închiderea proiectului. Fiecare națiune va trata problema așa cum crede de cuviință. Nu putem decât să sperăm că vom ajunge la un oarecare nivel de împăcare cu aceste forțe aparent ostile și că populația va ajunge la o întelegere cu vizitatorii extratereștri.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} este în mod special satisfăcută de competențele de care ai dat dovadă în lupta cu amenințarea locală și a decis să își mărească contribuția financiară.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} sunt în mod special fericite de progresul făcut în lupta împotriva incursiunilor locale ale extratereștrilor și au decis să își mărească contribuția financiară.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} și {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} este nemulțumită de abilitățile de care ai dat dovadă în lupta cu extratereștrii din teritoriul ei și a decis să își reducă contribuția financiară.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} sunt nemulțumite de capacitatea ta de a face față activităților extratereștrilor din teritoriile lor și au decis să își reducă contribuțiile financiare.\"\n  STR_KNOTS: \"{0} noduri\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} a semnat un tratat secret cu forțe extraterestre necunoscute și s-a retras din proiect.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} au semnat un tratat secret cu forțe extraterestre necunoscute și s-au retras din proiect.\"\n  STR_MONTHLY_RATING: \"Evaluare Lunară> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Variație Finanțe> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"Consiliul nu este mulțumit de situația ta financiară. Trebuie să îți micșorezi datoriile la o valoare de până în 1 milion $ sau proiectul va fi închis.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"TRANSMISIUNI HIPER-UNDĂ DECODATE\"\n  STR_CRAFT_TYPE: \"TIP NAVĂ\"\n  STR_RACE: \"RASĂ\"\n  STR_MISSION: \"MISIUNE\"\n  STR_ZONE: \"ZONĂ\"\n  STR_ALLOCATE_RESEARCH: \"Alocare Cercetare\"\n  STR_ALLOCATE_MANUFACTURE: \"Alocare Producție\"\n  STR_NEW_YORK: \"New York\"\n  STR_WASHINGTON: \"Washington\"\n  STR_LOS_ANGELES: \"Los Angeles\"\n  STR_MONTREAL: \"Montreal\"\n  STR_HAVANA: \"Havana\"\n  STR_MEXICO_CITY: \"Mexico City\"\n  STR_CHICAGO: \"Chicago\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_DALLAS: \"Dallas\"\n  STR_BRASILIA: \"Brazilia\"\n  STR_BOGOTA: \"Bogota\"\n  STR_BUENOS_AIRES: \"Buenos Aires\"\n  STR_SANTIAGO: \"Santiago\"\n  STR_RIO_DE_JANEIRO: \"Rio De Janeiro\"\n  STR_LIMA: \"Lima\"\n  STR_CARACAS: \"Caracas\"\n  STR_LONDON: \"Londra\"\n  STR_PARIS: \"Paris\"\n  STR_BERLIN: \"Berlin\"\n  STR_MOSCOW: \"Moscova\"\n  STR_ROME: \"Roma\"\n  STR_MADRID: \"Madrid\"\n  STR_BUDAPEST: \"Budapesta\"\n  STR_LAGOS: \"Lagos\"\n  STR_CAIRO: \"Cairo\"\n  STR_CASABLANCA: \"Casablanca\"\n  STR_PRETORIA: \"Pretoria\"\n  STR_NAIROBI: \"Nairobi\"\n  STR_CAPE_TOWN: \"Cape Town\"\n  STR_KINSHASA: \"Kinshasa\"\n  STR_ANKARA: \"Ankara\"\n  STR_DELHI: \"Delhi\"\n  STR_KARACHI: \"Karachi\"\n  STR_BAGHDAD: \"Bagdad\"\n  STR_TEHRAN: \"Teheran\"\n  STR_BOMBAY: \"Bombay\"\n  STR_CALCUTTA: \"Calcutta\"\n  STR_TOKYO: \"Tokio\"\n  STR_BEIJING: \"Beijing\"\n  STR_BANGKOK: \"Bangkok\"\n  STR_MANILA: \"Manila\"\n  STR_SEOUL: \"Seul\"\n  STR_SINGAPORE: \"Singapore\"\n  STR_JAKARTA: \"Jakarta\"\n  STR_SHANGHAI: \"Shanghai\"\n  STR_HONG_KONG: \"Hong Kong\"\n  STR_NOVOSIBIRSK: \"Novosibirsk\"\n  STR_CANBERRA: \"Canberra\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_MELBOURNE: \"Melbourne\"\n  STR_PERTH: \"Perth\"\n  STR_PSI_TRAINING: \"Antrenament Psi\"\n  STR_PSIONIC_TRAINING: \"ANTRENAMENT PSIONIC\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Spațiu liber Laborator-Psi> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"Rezistență{NEWLINE}Psionică\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"Abilități Psionice{NEWLINE}/Îmbunătățire\"\n  STR_PSI_AMP: \"Amplificator-Psi\"\n  STR_IN_TRAINING: \"Sub{NEWLINE}Antrenament?\"\n  STR_TARGETTED_BY: \"ȚINTIT DE CĂTRE:\"\n  STR_WEAPONS_CREW_HWPS: \"ARME/ECHIPAJ/{NEWLINE}TANCURI\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"a terminat combustibilul{NEWLINE}și revine la bază\"\n  STR_SOLDIER_LIST: \"Listă Soldați\"\n  STR_RANK_: \"RANG> {ALT}{0}\"\n  STR_MISSIONS: \"MISIUNI> {ALT}{0}\"\n  STR_KILLS: \"VICTIME> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"VINDECARE> {ALT}{0}\"\n  STR_TIME_UNITS: \"UNITĂȚI TIMP\"\n  STR_STAMINA: \"ENERGIE\"\n  STR_HEALTH: \"SĂNĂTATE\"\n  STR_BRAVERY: \"VITEJIE\"\n  STR_REACTIONS: \"REACȚII\"\n  STR_FIRING_ACCURACY: \"PRECIZIE FOC\"\n  STR_THROWING_ACCURACY: \"PRECIZIE ARUNCARE\"\n  STR_STRENGTH: \"FORȚĂ\"\n  STR_PSIONIC_STRENGTH: \"REZISTENȚĂ PSIONICĂ\"\n  STR_PSIONIC_SKILL: \"ABILITĂȚI PSIONICE\"\n  STR_NEW_RANK: \"RANG NOU\"\n  STR_PROMOTIONS: \"Promovări\"\n  STR_SOLDIERS_UC: \"SOLDAȚI\"\n  STR_TANK_CANNON_UFOPEDIA: \"Tancurile automatizate sunt proiectate pentru a fi complementare unei echipe X-Com. Combinația dintre puterea mare de foc și armura solidă pun în valoare aceste unități în luptele din teren deschis. Atenție să existe în depozite proiectile de tanc suficiente pentru reîncărcarea tancurilor. Se înarmează automat când sunt alocate unei echipe.\"\n  STR_TANK_ROCKET_LAUNCHER_UFOPEDIA: \"Acest tanc automatizat este înarmat cu lansatoare de rachete devastatoare pentru orice inamic extraterestru. Atenție să existe în depozite suficiente rachete de tanc.\"\n  STR_TANK_LASER_CANNON_UFOPEDIA: \"Armele laser sunt o adăugire folositoare în arsenalul tancurilor. Combină puterea mare de foc cu muniția practic nelimitată.\"\n  STR_HOVERTANK_PLASMA_UFOPEDIA: \"Tehnologia extraterestră a dat o nouă utilitate tancurilor. Manevrabilitatea sporită dată de plutirea prin aer împreună cu fasciculele de plasmă formează o combinație letală.\"\n  STR_HOVERTANK_LAUNCHER_UFOPEDIA: \"Acest hovertanc are un lansator de sfere de fuziune care poate fi devastator. A se folosi cu grijă. Va fi necesară producerea sferelor pentru a păstra hovertancurile înarmate. Sfera de fuziune este o armă inteligentă teleghidată. Pentru a o lansa, se alege un număr de puncte pe traseu după care se apașă pe butonul de lansare.\"\n  STR_HEAVY_PLASMA_CLIP_UFOPEDIA: \"Acest dispozitiv compact este folosit drept muniție pentru tunul de artilerie cu plasmă. Conține o cantitate mică de Elerium.\"\n  STR_PLASMA_RIFLE_CLIP_UFOPEDIA: \"Acest mic dispozitiv este folosit drept sursă de energie pentru pușca cu plasmă - o armă extraterestră de putere medie. Conține o cantitate mică de Elerium.\"\n  STR_PLASMA_PISTOL_CLIP_UFOPEDIA: \"Sursa de energie pentru pistolul cu plasmă extraterestru. Conține Elerium - sursa de energie folosită de către extratereștri.\"\n  STR_STUN_BOMB_UFOPEDIA: \"Bomba paralizantă este folosită pentru capturarea în viață a specimenelor umane, dar poate fi de asemenea utilizată împotriva majorității speciilor extraterestre. Este proiectată la țintă cu ajutorul unui mic lansator.\"\n  STR_ALIEN_RESEARCH_UFOPEDIA: \"Misiunea de cercetare a extratereștrilor este folosită pentru a colecta date despre Pământ și locuitorii acestuia. Predominant sunt folosite nave mici, dar au loc și aterizări ocazionale în zone pustii. Acest tip de activitate constituie cea mai mică amenințare pentru X-Com, preocupând în mică masură guvernele sau publicul.\"\n  STR_ALIEN_HARVEST_UFOPEDIA: \"Extratereștrii au multe întrebuințări pentru fauna Pământului. Animalele sunt luate în secret și apoi înapoiate cu diverse organe lipsă. Bovine mutilate sunt semnalate preponderent în zone unde au fost observate OZNuri. Această activitate a extratereștrilor are loc în principal în zonele rurale, provocând mare îngrijorare pentru guverne și teamă printre locuitori. Teoria din spatele acestei 'recoltări' sugerează că rasele extraterestre au 'însămânțat' inițial planeta cu floră și faună iar acum s-au întors să își culeagă recolta.\"\n  STR_ALIEN_ABDUCTION_UFOPEDIA: \"Aceasta este cea mai perfidă dintre activitățile extraterestre. Răpirile sunt raportate la scară largă în ciuda încercărilor extratereștrilor de a șterge întâmplările din memoria victimelor. Răpiții au declarat că au fost supuși la examinări fizice umilitoare, inclusiv impregnarea cu fetuși extratereștrii, precum și experimente genetice. Motivul din spatele acestora pare să fie legat de mutația și manipularea materialului genetic extraterestru. Aceste activități provoacă o teamă puternică și au loc în zone populate sau orașe.\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"Guvernele Pământene pot fi infiltrate de către agenți extratereștrii cu aspect uman. Acest lucru poate duce la întâlniri oficiale la cel mai înalt nivel între extratereștrii și guverne. Apogeul este caracterizat de activități OZN intense în apropierea marilor orașe. Extratereștrii vor încerca să semneze un pact cu unul din guverne prin oferirea cunoștințelor lor tehnologice avansate. Guvernul va permite în schimb extratereștrilor să își continue activitățile. Această misiune a extratereștrilor reprezintă cea mai mare amenințare pentru X-Com. Dacă un guvern acceptă pactul atunci contribuția financiară va înceta.\"\n  STR_ALIEN_BASE_UFOPEDIA: \"Extratereștrii vor construi baze subterane secrete în zone izolate. După zborurile de observare inițiale va urma o activitate OZN intensă pe masură ce baza este construită. Aceasta conține laboratoare pentru experimentele asupra victimelor umane precum și diverse provizii pentru viitoarele activități din regiune. Existența unei baze extraterestre va genera o activitate intensă chiar și fără apariția OZNurilor. Pentru a localiza o bază o navă X-Com trebuie să patruleze zona câteva ore pentru a avea o șansă de detecție.\"\n  STR_ALIEN_TERROR_UFOPEDIA: \"Când extratereștrii terorizează un oraș vor desfășura forțe speciale cu puteri incredibile. Civilii vor fi în pericol, iar guvernele vor fi nevoite să evacueze zone întinse. Scopul principal este de a genera o isterie publică suficient de mare pentru ca guvernele să amenințe buna desfășurare a proiectului X-Com.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"Dacă interceptoarele X-Com reușesc să doboare multe OZNuri atunci extratereștrii pot recurge la represalii. Acestea pot lua forma unui atac direct împotriva bazelor X-Com. Totuși, extratereștrii trebuie să găsească o bază X-Com pentru a o putea ataca, însă dacă OZNurile sunt îndepărtate atunci acest pericol a trebui să fie redus.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"Odată ce baza extraterestră este construită, aceasta va fi aprovizionată în mod regulat de către o navă specială. Dacă una din aceste nave este detectată în timp ce aterizează atunci este sigur faptul că în apropiere se află o bază extraterestră.\"\n  STR_SMALL_SCOUT_UFOPEDIA: \"Această navă minusculă este folosită pentru observare sau cercetare. În mod normal precede navele mai mari de la începutul unei misiuni extraterestre.\"\n  STR_MEDIUM_SCOUT_UFOPEDIA: \"O navă de observare de dimensiune medie ce nu prezintă o amenințare puternică pentru forțele Pământene. Apare în mod normal înaintea navelor mari din timpul misiunilor extraterestre.\"\n  STR_LARGE_SCOUT_UFOPEDIA: \"Cea mai mare navă de observare extraterestră are un scop general și este folosită în toate tipurile de misiuni ale extratereștrilor.\"\n  STR_HARVESTER_UFOPEDIA: \"Această navă prezintă o poartă de acces la baza ei și este echipată cu mecanisme de manipulare a vitelor sau altor ființe. Unelte laser de tăiat sunt folosite pentru a extrage materialele dorite după care corpul este aruncat la pământ. Prezintă de asemenea recipiente pentru organe.\"\n  STR_ABDUCTOR_UFOPEDIA: \"Această navă prezintă o cameră de examinare în care au loc experimente groaznice pe subiecți umani. În mod obișnuit victima este paralizată cu ajutorul puterilor telepatice dar rămâne conștientă pe masa de operație.\"\n  STR_TERROR_SHIP_UFOPEDIA: \"Această navă prezintă o cameră mare pentru arme sau creaturi de groază. Este folosită pentru a transporta acești extratereștrii în zone populate.\"\n  STR_BATTLESHIP_UFOPEDIA: \"Cea mai mare și puternică navă extraterestră. În mod normal este nava principală pentru misiunile extraterestre, dotată cu arme puternice și având un echipaj numeros.\"\n  STR_SUPPLY_SHIP_UFOPEDIA: \"Această navă este folosită în timpul construcției bazelor extraterestre sau pentru aprovizionarea bazelor existente. Transportă recipiente cu mâncare extraterestră și camere de reproducție.\"\n  STR_DISMANTLE: \"Dezafectare\"\n  STR_FACILITY_IN_USE: \"STRUCTURĂ îNTREBUINȚATĂ\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"NU SE POATE DEZAFECTA!{SMALLLINE}Toate structurile trebuie să aibă legături către liftul de acces.\"\n  STR_TRANSFER_ITEMS_TO: \"Transferă Articole la {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"NU EXISTĂ CARANTINĂ PENTRU TRANSFER!{SMALLLINE}Extratereștrii vii au nevoie de carantină pentru a supraviețui.\"\n  STR_AMOUNT_AT_DESTINATION: \"CANTITATE LA{NEWLINE}DESTINAȚIE\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"Extraterestrul moare pentru că nu există carantină\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"NU EXISTĂ LOCURI LIBERE!{SMALLLINE}Baza destinată nu are locuri libere în locuințe pentru echipajul alocat navei.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"SPAȚIU DEPOZITARE INSUFICIENT!{SMALLLINE}Baza destinație nu are spațiu suficient în depozite pentru echipamentul alocat navei.\"\n  STR_ITEMS_ARRIVING: \"Sosire Articole\"\n  STR_DESTINATION_UC: \"DESTINAȚIE\"\n  STR_PISTOL: \"Pistol\"\n  STR_PISTOL_CLIP: \"Muniție Pistol\"\n  STR_RIFLE: \"Pușcă\"\n  STR_RIFLE_CLIP: \"Muniție Pușcă\"\n  STR_HEAVY_CANNON: \"Artilerie Grea\"\n  STR_HC_AP_AMMO: \"Muniție AG-P\"\n  STR_HC_HE_AMMO: \"Muniție AG-E\"\n  STR_HC_I_AMMO: \"Muniție AG-I\"\n  STR_AUTO_CANNON: \"Artilerie Automată\"\n  STR_AC_AP_AMMO: \"Muniție AA-P\"\n  STR_AC_HE_AMMO: \"Muniție AA-E\"\n  STR_AC_I_AMMO: \"Muniție AA-I\"\n  STR_ROCKET_LAUNCHER: \"Lansator Rachete\"\n  STR_SMALL_ROCKET: \"Rachetă Mică\"\n  STR_LARGE_ROCKET: \"Rachetă Mare\"\n  STR_INCENDIARY_ROCKET: \"Rachetă Incendiară\"\n  STR_GRENADE: \"Grenadă\"\n  STR_SMOKE_GRENADE: \"Grenadă Fumigenă\"\n  STR_PROXIMITY_GRENADE: \"Grenadă Proximitate\"\n  STR_HIGH_EXPLOSIVE: \"Super-Explozibil\"\n  STR_STUN_ROD: \"Baston Paralizant\"\n  STR_HEAVY_PLASMA: \"Artilerie Plasmă\"\n  STR_HEAVY_PLASMA_CLIP: \"Muniție Artilerie Plasmă\"\n  STR_PLASMA_RIFLE: \"Pușcă Plasmă\"\n  STR_PLASMA_RIFLE_CLIP: \"Muniție Pușcă Plasmă\"\n  STR_PLASMA_PISTOL: \"Pistol Plasmă\"\n  STR_PLASMA_PISTOL_CLIP: \"Muniție Pistol Plasmă\"\n  STR_BLASTER_LAUNCHER: \"Lansator Bombe\"\n  STR_BLASTER_BOMB: \"Bombă Teleghidată\"\n  STR_SMALL_LAUNCHER: \"Lansator Mic\"\n  STR_STUN_BOMB: \"Bombă Paralizantă\"\n  STR_ALIEN_GRENADE: \"Grenadă Extraterestră\"\n  STR_ELERIUM_115: \"Elerium-115\"\n  STR_MIND_PROBE: \"Sondă Mentală\"\n  STR_SECTOID_CORPSE: \"Cadavru Sectoid\"\n  STR_SNAKEMAN_CORPSE: \"Cadavru Snakeman\"\n  STR_ETHEREAL_CORPSE: \"Cadavru Ethereal\"\n  STR_MUTON_CORPSE: \"Cadavru Muton\"\n  STR_FLOATER_CORPSE: \"Cadavru Floater\"\n  STR_CELATID_CORPSE: \"Cadavru Celatid\"\n  STR_SILACOID_CORPSE: \"Cadavru Silacoid\"\n  STR_CHRYSSALID_CORPSE: \"Cadavru Chryssalid\"\n  STR_REAPER_CORPSE: \"Cadavru Reaper\"\n  STR_SECTOPOD_CORPSE: \"Cadavru Sectopod\"\n  STR_CYBERDISC_CORPSE: \"Cadavru Cyberdisc\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"Muniție insuficientă pentru înarmare Tanc{SMALLLINE}Fiecare tanc necesită {0} {1}.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Echipamente insuficiente pentru utilarea trupelor\"\n  STR_MARS_CYDONIA_LANDING: \"Marte: Aterizarea în Cydonia\"\n  STR_MARS_CYDONIA_LANDING_BRIEFING: \"Nava Avenger a aterizat pe suprafața planetei Marte, în regiunea Cydonia. Informațiile noastre sugerează că una dintre construcțiile piramidale conține un lift de acces verde care conduce într-un complex subteran. Odată ce soldații sunt plasați în lift se apasă pe butonul 'Abandonare Misiune' pentru a trece la următoarea fază.\"\n  STR_MARS_THE_FINAL_ASSAULT: \"Marte: Asaltul Final\"\n  STR_MARS_THE_FINAL_ASSAULT_BRIEFING: \"Liftul piramidei conduce soldații osteniți de luptă mult sub suprafața planetei. Aceștia ajung în inima unui complex mare de tuneluri și camere. Creierul extraterestru este ascuns undeva în labirint. Dacă vrem ca Pământul să fie salvat de extratereștrii atunci acesta trebuie distrus.{NEWLINE}{NEWLINE}Succes!\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Finalizare cercetare{NEWLINE}{0}{NEWLINE}pentru a produce{NEWLINE}{1}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"Extratereștrii au distrus baza lipsită de apărare {0}\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"Agenții X-Com au localizat o bază extraterestră în {0}\"\n  STR_STANDOFF: \"PĂSTREAZĂ DISTANȚA\"\n  STR_CAUTIOUS_ATTACK: \"ATAC PRECAUT\"\n  STR_STANDARD_ATTACK: \"ATAC STANDARD\"\n  STR_AGGRESSIVE_ATTACK: \"ATAC AGRESIV\"\n  STR_DISENGAGING: \"DEGAJARE\"\n  STR_UFO_HIT: \"OZN LOVIT!\"\n  STR_UFO_CRASH_LANDS: \"OZN DOBORÂT!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Minimizare Numai la Distanță\"\n  STR_UFO_RETURN_FIRE: \"OZN RIPOSTEAZĂ!\"\n  STR_INTERCEPTOR_DAMAGED: \">>> INTERCEPTOR AVARIAT <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> INTERCEPTOR DISTRUS <<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"OZN DEVANSEAZĂ INTERCEPTORUL!\"\n  STR_ALIENS_TERRORISE: \"EXTRATEREȘTRII TERORIZEAZĂ\"\n  STR_LONG_RANGE_DETECTION: \"Detecție Rază Lungă\"\n  STR_STORES_UC: \"DEPOZITE\"\n  STR_DIFFICULTY_LEVEL: \"Nivel Dificultate\"\n  STR_INTERCEPT: \"INTERCEPTARE\"\n  STR_BASES: \"BAZE\"\n  STR_GRAPHS: \"GRAFICE\"\n  STR_UFOPAEDIA_UC: \"UFOPEDIA\"\n  STR_OPTIONS_UC: \"OPȚIUNI\"\n  STR_FUNDING_UC: \"FINANȚARE\"\n  STR_5_SECONDS: \"5 Sec\"\n  STR_1_MINUTE: \"1 Min\"\n  STR_5_MINUTES: \"5 Min\"\n  STR_30_MINUTES: \"30 Min\"\n  STR_1_HOUR: \"1 Oră\"\n  STR_1_DAY: \"1 Zi\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"Listă Performanțe X-Com\"\n  STR_ENTER_NAME: \"Introducere Nume\"\n  STR_PERFORMANCE_RATING: \"Evaluare Performanță\"\n  STR_VICTORY_DATE: \"Data Victoriei\"\n  STR_ELECTRO_FLARE: \"Semnal Luminos\"\n  STR_ELECTRO_FLARE_UFOPEDIA: \"Când este aruncat, acest dispozitiv compact produce o lumină puternică. În timpul misiunilor de noapte va evidenția inamicii din proximitatea semnalului luminos.\"\n  STR_MONTHLY_COSTS: \"Costuri Lunare\"\n  STR_CRAFT_RENTAL: \"Chiria Navelor\"\n  STR_SALARIES: \"Salarii\"\n  STR_BASE_MAINTENANCE: \"Întreținerea Bazei\"\n  STR_COST_PER_UNIT: \"Cost unitar\"\n  STR_QUANTITY: \"Cantitate\"\n  STR_TOTAL: \"Total\"\n  STR_IN_PSIONIC_TRAINING: \"Sub Antrenament Psionic\"\n  STR_BLASTER_BOMB_UFOPEDIA: \"Acest dispozitiv este o rachetă explozivă dotată cu un sistem inteligent de ghidare. Este proiectată de un lansator de bombe.\"\n  STR_FRONT_ARMOR: \"Armură Frontală\"\n  STR_LEFT_ARMOR: \"Armură Stânga\"\n  STR_RIGHT_ARMOR: \"Armură Dreapta\"\n  STR_REAR_ARMOR: \"Armură Spate\"\n  STR_UNDER_ARMOR: \"Armură Inferioară\"\n  STR_ROUNDS: \"Muniţie\"\n  STR_UNIT: \"UNITATE> {0}\"\n  STR_ENERGY: \"ENERGIE\"\n  STR_MORALE: \"MORAL\"\n  STR_ARMOR_: \"ARMURĂ> {0}\"\n  STR_FRONT_ARMOR_UC: \"ARMURĂ FRONTALĂ\"\n  STR_LEFT_ARMOR_UC: \"ARMURĂ STÂNGA\"\n  STR_RIGHT_ARMOR_UC: \"ARMURĂ DREAPTA\"\n  STR_REAR_ARMOR_UC: \"ARMURĂ SPATE\"\n  STR_SKILLS: \"ABILITĂȚI> {0}\"\n  STR_LEVEL: \"NIVEL> {0}\"\n  STR_HEAD: \"CAP\"\n  STR_TORSO: \"TRUNCHI\"\n  STR_RIGHT_ARM: \"BRAȚ DREPT\"\n  STR_LEFT_ARM: \"BRAȚ STÂNG\"\n  STR_RIGHT_LEG: \"PICIOR DREPT\"\n  STR_LEFT_LEG: \"PICIOR STÂNG\"\n  STR_PAIN_KILLER: \"ANALGEZIC\"\n  STR_STIMULANT: \"STIMULENT\"\n  STR_HEAL: \"VINDECARE\"\n  STR_TIME_UNITS_SHORT: \"UT>{ALT}{0}\"\n  STR_WEIGHT: \"Greut>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"Reac>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"Abil.Psi>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"Rez.Psi>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Artefact Extraterestru\"\n  STR_AMMO_ROUNDS_LEFT: \"MUNIȚIE:{NEWLINE}SALVE{NEWLINE}RĂMASE={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Calm>{ALT}{0}{ALT}{NEWLINE}Stim>{ALT}{1}{ALT}{NEWLINE}Trat>{ALT}{2}\"\n  STR_THROW: \"Aruncare\"\n  STR_AUTO_SHOT: \"Foc Automat\"\n  STR_SNAP_SHOT: \"Foc Rapid\"\n  STR_AIMED_SHOT: \"Foc Ochit\"\n  STR_STUN: \"Paralizare\"\n  STR_PRIME_GRENADE: \"Amorsare\"\n  STR_USE_SCANNER: \"Folosire Detector\"\n  STR_USE_MEDI_KIT: \"Folosire Trusă\"\n  STR_LAUNCH_MISSILE: \"Lansare Rachetă\"\n  STR_ACCURACY_SHORT: \"Pre>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Unități Timp Insuficiente!\"\n  STR_NOT_ENOUGH_ENERGY: \"Energie Insuficientă!\"\n  STR_NO_ROUNDS_LEFT: \"Salve Terminate!\"\n  STR_NO_AMMUNITION_LOADED: \"Arma este Descărcată!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Muniție improprie pentru această Armă!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"Arma este deja încărcată!\"\n  STR_NO_LINE_OF_FIRE: \"Linie de Tragere Blocată!\"\n  STR_GRENADE_IS_ACTIVATED: \"Grenada este Amorsată!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Grenada este Dezamorsată!\"\n  STR_THERE_IS_NO_ONE_THERE: \"Nu este nimeni acolo!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Artefact inutilizabil până ce nu este cercetat!\"\n  STR_OUT_OF_RANGE: \"În Afara Razei De Acțiune!\"\n  STR_UNABLE_TO_THROW_HERE: \"Nu se poate arunca acolo!\"\n  STR_SET_TIMER: \"Setare Cronometru\"\n  STR_HIDDEN_MOVEMENT: \"MIȘCĂRI ASCUNSE\"\n  STR_TURN: \"RUNDA> {0}\"\n  STR_SIDE: \"FACȚIUNEA> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Apasă orice pentru a continua\"\n  STR_MIND_CONTROL: \"Control Mental\"\n  STR_PANIC_UNIT: \"Panicare Unitate\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Atac Moral Reușit\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Control Mental Reușit\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}a Înnebunit\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}a Înnebunit\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}s-a Panicat\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}s-a Panicat\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Extratereștrii\"\n  STR_RIGHT_HAND: \"MÂNA DREAPTĂ\"\n  STR_LEFT_HAND: \"MÂNA STÂNGĂ\"\n  STR_RIGHT_SHOULDER: \"UMĂR DREPT\"\n  STR_LEFT_SHOULDER: \"UMĂR STÂNG\"\n  STR_BACK_PACK: \"RUCSAC\"\n  STR_BELT: \"CENTURĂ\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}se află sub control străin\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}se află sub control străin\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}și-a pierdut cunoștința\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}și-a pierdut cunoștința\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}a murit din cauza rănilor grave\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}a murit din cauza rănilor grave\"\n  STR_USE_MIND_PROBE: \"Folosire Sondă Mentală\"\n  STR_FATAL_WOUNDS: \"RĂNI GRAVE\"\n  STR_UNDER_ARMOR_UC: \"ARMURĂ INFERIOARĂ\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Unități Timp rezervate pentru Foc Rapid\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Unități Timp rezervate pentru Foc Automat\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Unități Timp rezervate pentru Foc Țintit\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Unități Timp rezervate pentru Îngenunchere\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"UT rezervate pentru Îngenunchere și Foc\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} Soldat în Nava X-Com\"\n    few: \"{N} Soldați în Nava X-Com\"\n    other: \"{N} Soldați în Nava X-Com\"\n  STR_UNITS_OUTSIDE:\n    one: \"{N} Soldat lăsat afară\"\n    few: \"{N} Soldați lăsați afară\"\n    other: \"{N} Soldați lăsați afară\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} Soldat în Zona de Intrare\"\n    few: \"{N} Soldați în Zona de Intrare\"\n    other: \"{N} Soldați în Zona de Intrare\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} Soldat în Zona de Evacuare\"\n    few: \"{N} Soldați în Zona de Evacuare\"\n    other: \"{N} Soldați în Zona de Evacuare\"\n  STR_ABORT_MISSION_QUESTION: \"Abandonare Misiune?\"\n  STR_CORPSE: \"Cadavru\"\n  STR_UNLOAD_CRAFT: \"Descărcare\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}a fost ucis\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}a fost ucisă\"\n  STR_HIT_MELEE: \"Lovire\"\n  STR_GROUND: \"LA SOL\"\n  STR_LIVING_QUARTERS_PLURAL: \"Ansamblu Locuințe\"\n  STR_LIST_ITEM: \"ARTICOL\"\n  STR_PERSONAL_ARMOR_UFOPEDIA: \"Această armură folosește nou descoperitele Aliaje Extraterestre, oferind soldaților o șansă în lupta împotriva amenințării extraterestre.\"\n  STR_POWER_SUIT_UFOPEDIA: \"O nouă și puternică protecție pentru soldați, această armură este alimentată de o sursă de energie pe bază de Elerium ce amplifică mult viteza și forța utilizatorului, oferind cea mai bună protecție de până acum pentru trupele luptătoare.\"\n  STR_FLYING_SUIT_UFOPEDIA: \"O versiune îmbunătățită a Costumului de Forță, având incorporată tehnologie de navigație antigravitațională ce permite libertate totală de mișcare pe câmpul de luptă.\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"Toți extratereștrii morți în prăbușire,{NEWLINE}se inițiază recuperarea automată\"\n  STR_RESET: \"Resetare\"\n  STR_MEMORIAL: \"Memorial\"\n  STR_DATE_UC: \"DATĂ\"\n  STR_SOLDIERS_RECRUITED_UC: \"SOLDAȚI RECRUTAȚI>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"SOLDAȚI PIERDUȚI>{ALT}{0}\"\n  MAP_CULTA: \"Fermă\"\n  MAP_FOREST: \"Pădure\"\n  MAP_JUNGLE: \"Junglă\"\n  MAP_MOUNT: \"Munte\"\n  MAP_DESERT: \"Deșert\"\n  MAP_POLAR: \"Arctic\"\n  MAP_URBAN: \"Oraș\"\n  MAP_UBASE: \"Bază Extraterestră\"\n  MAP_XBASE: \"Bază X-Com\"\n  MAP_MARS: \"Marte\"\n  STR_MIXED: \"Amestecate\"\n  STR_REMOVE_SELECTED: \"Eliminare Selecționați\"\n  STR_LIVE_ALIENS: \"Exemplare{NEWLINE}În Viață\"\n  STR_DEAD_ALIENS: \"Exemplare{NEWLINE}Respinse\"\n  STR_UNDER_INTERROGATION: \"Supuse{NEWLINE}Studiului\"\n  STR_CONTAINMENT_EXCEEDED: \"LIMITE DEPĂȘITE CARANTINĂ EXTRATEREȘTRII!{SMALLLINE}Spațiu insuficient în carantina din {0}. Trebuie eliminat excesul de extratereștrii din carantină (aceștia vor muri).\"\n  STR_MANAGE_CONTAINMENT: \"Gestionare Carantină Extratereștrii\"\n  STR_STORAGE_EXCEEDED: \"SPAȚIU DEPOZITARE DEPĂȘIT!{SMALLLINE}Spațiu insuficient pentru stocare în {0}. Trebuie vândut surplusul de articole.\"\n  STR_GO_TO_BASE: \"Afișare Bază\"\n  STR_MELEE_ACCURACY: \"PRECIZIE MELEU\"\n  STR_SELL_PRODUCTION: \"VÂNZARE\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Ambele mâini trebuie să fie goale!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Articole insuficiente pentru a copia șablonul!\"\n  STR_UNLOAD_WEAPON: \"Descărcare armă\"\n  STR_ALL_ITEMS: \"Toate Articolele\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"FĂRĂ ECHIPAMENT ÎN PLUS LA BORD!{SMALLLINE}Se poate lua la bord un număr maxim de {N} articol pentru această navă.\"\n    few: \"FĂRĂ ECHIPAMENT ÎN PLUS LA BORD!{SMALLLINE}Se pot lua la bord un număr maxim de {N} de articole pentru această navă.\"\n    other: \"FĂRĂ ECHIPAMENT ÎN PLUS LA BORD!{SMALLLINE}Se pot lua la bord un număr maxim de {N} de articole pentru această navă.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}CENTRU DE CONTROL DISTRUS{NEWLINE}Continuați până la intrare și evacuați.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"Structurile X-Com nu pot fi construite sub apă\"\n  STR_LEVEL_SHORT: \"{0}\"\n  STR_PERSONNEL: \"Personal\"\n  STR_CRAFT_ARMAMENT: \"Nave & Armament\"\n  STR_COMPONENTS: \"Componente\"\n  STR_SOLDIERS_RECRUITED: \"Soldați recrutați\"\n  STR_SOLDIERS_LOST: \"Soldați pierduți\"\n  STR_TOTAL_UFOS: \"OZNuri detectate\"\n  STR_TOTAL_ALIEN_BASES: \"Baze Extraterestre descoperite\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"RZP\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"ABP\"\n  FEMALE_CIVILIAN: \"Civil, Femeie\"\n  MALE_CIVILIAN: \"Civil, Bărbat\"\n  CYBERDISC_WEAPON: \"Armă Cyberdisc\"\n  REAPER_WEAPON: \"Armă Reaper\"\n  CHRYSSALID_WEAPON: \"Armă Chryssalid\"\n  CELATID_WEAPON: \"Armă Celatid\"\n  SILACOID_WEAPON: \"Armă Silacoid\"\n  SECTOPOD_WEAPON: \"Armă Sectopod\"\n  ZOMBIE_WEAPON: \"Armă Zombie\"\n  ALIEN_PSI_WEAPON: \"Armă Psi Extraterestră\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/ru.yml",
    "content": "ru:\n  STR_AVENGER_UFOPEDIA: \"ТРАНСПОРТНО-БОЕВОЙ КОСМИЧЕСКИЙ КОРАБЛЬ. НАИВЫСШЕЕ ВОПЛОЩЕНИЕ ТЕХНОЛОГИЙ ПРИШЕЛЬЦЕВ.\"\n  STR_INTERCEPTOR_UFOPEDIA: \"БОЕВОЙ ЛА, ОСНАЩЕННЫЙ ДВУМЯ ИМПУЛЬСНЫМИ ДЕТОНАЦИОННЫМИ ДВИГАТЕЛЯМИ И СПЕЦИАЛЬНО ЭКРАНИРОВАННЫМИ ЭЛЕКТРОННЫМИ СИСТЕМАМИ. ЛУЧШЕЕ, ЧТО МОГУТ ПРЕДЛОЖИТЬ ЗЕМНЫЕ ТЕХНОЛОГИИ.\"\n  STR_LIGHTNING_UFOPEDIA: \"ТРАНСПОРТНО-БОЕВОЙ ЛЕТАТЕЛЬНЫЙ АППАРАТ, ИСПОЛЬЗУЮЩИЙ ГРУБУЮ, НО ЭФФЕКТИВНУЮ КОПИЮ СИЛОВЫХ УСТАНОВОК ПРИШЕЛЬЦЕВ.\"\n  STR_SKYRANGER_UFOPEDIA: \"ТРАНСПОРТНЫЙ САМОЛЕТ. САМЫЙ БЫСТРЫЙ В СВОЕМ КЛАССЕ, СПОСОБНЫЙ НА ВЕРТИКАЛЬНЫЙ ВЗЛЕТ И ПОСАДКУ (СВВП).\"\n  STR_FIRESTORM_UFOPEDIA: \"БОЕВОЙ ЛЕТАТЕЛЬНЫЙ АППАРАТ. В ЭТОМ ОДНОМЕСТНОМ ИСТРЕБИТЕЛЕ ПОВТОРЕНА СХЕМА КЛАССИЧЕСКИХ ЛЕТАЮЩИХ ТАРЕЛОК ПРИШЕЛЬЦЕВ С ЦЕНТРАЛЬНЫМ РАСПОЛОЖЕНИЕМ СИЛОВОЙ УСТАНОВКИ.\"\n  STR_STINGRAY_UFOPEDIA: \"ПЕРЕДОВАЯ РАКЕТА КЛАССА «ВОЗДУХ-ВОЗДУХ» СО СПЕЦИАЛЬНО ЭКРАНИРОВАННЫМИ ЭЛЕКТРОННЫМИ СИСТЕМАМИ.\"\n  STR_AVALANCHE_UFOPEDIA: \"РАКЕТА КЛАССА «ВОЗДУХ-ВОЗДУХ» С ЯДЕРНОЙ БОЕВОЙ ЧАСТЬЮ. ОТЛИЧАЕТСЯ КРАЙНЕ БОЛЬШОЙ МАССОЙ.\"\n  STR_CANNON_UFOPEDIA: \"АВТОМАТИЧЕСКАЯ ПУШКА БОЛЬШОЙ МОЩНОСТИ, СТРЕЛЯЮЩАЯ БРОНЕБОЙНЫМИ СНАРЯДАМИ, СПОСОБНЫМИ ПРОБИТЬ 400-МИЛЛИМЕТРОВУЮ СТАЛЬНУЮ БРОНЮ.\"\n  STR_FUSION_BALL_UFOPEDIA: \"ЭТА ПУСКОВАЯ УСТАНОВКА ВЫСТРЕЛИВАЕТ ШАРООБРАЗНЫЕ РАКЕТЫ, ИНИЦИАТОРОМ В КОТОРЫХ СЛУЖИТ РЕАКЦИЯ АНТИВЕЩЕСТВА. ШАР УНИЧТОЖАЕТ ЦЕЛЬ ПОСРЕДСТВОМ ГРАВИТАЦИОННОЙ ИМПЛОЗИИ.\"\n  STR_LASER_CANNON_UFOPEDIA: \"ЭТОТ СТАНДАРТНЫЙ ЛАЗЕРНЫЙ ИЗЛУЧАТЕЛЬ ПИТАЕТСЯ ЭНЕРГИЕЙ РЕАКТОРА, РАБОТАЮЩЕГО НА АНТИМАТЕРИИ.\"\n  STR_PLASMA_BEAM_UFOPEDIA: \"ГРАВИТАЦИОННЫЙ ЛУЧ НАПРАВЛЯЕТ ТОЧНО СФОКУСИРОВАННОЕ СЖИМАЮЩЕЕ ГРАВИТАЦИОННОЕ ПОЛЕ.\"\n  STR_SECTOID_UFOPEDIA: \"В иерархию cектоидов входят особи от солдат до лидеров с мощными пси-способностями. Они используют пси-силы для деморализации противника в бою и даже захвата контроля над его сознанием. Как правило, сектоиды занимаются похищением людей и изувечиванием рогатого скота. Похищенные используются для сбора генного материала для последующего скрещивания и создания клонов для внедрения в человеческое общество. Скот используется в качестве пищи и генетического материала. Эта раса, похоже, хочет вывести более совершенных гибридов для повышения эффективности своего ульеподобного общества.\"\n  STR_SECTOID_AUTOPSY: \"Вскрытие сектоида\"\n  STR_SECTOID_AUTOPSY_UFOPEDIA: \"Вскрытие выявило рудиментарные органы пищеварения и простое строение организма. Мозг и глаза очень хорошо развиты. Строение организма свидетельствует о применении генной инженерии или  последствиях мутации. Малых размеров рот и нос, похоже, выполняют рудиментарные функции. Перепонки между пальцами и плоские стопы указывают на происхождение из водной среды. Репродуктивные органы отсутствуют; способ размножения этого вида неясен. Вероятнее всего, этот вид возник как продукт генной инженерии.\"\n  STR_SNAKEMAN_UFOPEDIA: \"Эта раса сформировалась в чрезвычайно враждебной среде. Ее представители обладают чрезвычайно крепким телом и могут выдерживать экстремальные колебания температуры. Их мобильность обеспечивается змееподобной «ногой», которая защищает все жизненно важные органы. Похоже на то, что для них характерны паттерны поведения хищников и что они находятся под контролем другого разума, который руководит их вторжениями на Землю, более напоминающими военные операции.\"\n  STR_SNAKEMAN_AUTOPSY: \"Вскрытие человекозмея\"\n  STR_SNAKEMAN_AUTOPSY_UFOPEDIA: \"Кожа чрезвычайно жесткая и термостойкая. Сердечно-сосудистая система является частью мышечной системы, использующей гидравлический принцип для приведения тела в движение. Единственной настоящей мышцей является «сердце». Репродуктивная система, похоже, крайне эффективна. Размножение бесполое; каждый человекозмей несет до 50 яиц единовременно. Без внешнего контроля популяции они могли бы стать серьезнейшей угрозой земной жизни.\"\n  STR_ETHEREAL_UFOPEDIA: \"Это существо обладает устрашающими ментальными силами, включающими коммуникацию посредством телепатии и способность к телекинезу. Очень слабое физическое развитие этого существа компенсируется силой разума. Мы не понимаем принцип работы телекинеза, так как это явление противоречит известным нам законам физики. Они всегда чрезвычайно опасны на поле боя, где они полагаются на свои ментальные силы. Они редко появляются на Земле, так как используют другие расы для достижения своих целей.\"\n  STR_ETHEREAL_AUTOPSY: \"Вскрытие эфириала\"\n  STR_ETHEREAL_AUTOPSY_UFOPEDIA: \"Это существо физически деградировало и кажется неспособным поддерживать какие-либо жизненные функции. Мышцы сильно атрофированы, внутренние органы слабо развиты. Органы чувств, включая глаза, похоже, вообще неактивны. Мозг, однако, хорошо развит и обильно снабжается кровью. Непонятно, как это существо могло поддерживать свою жизнь без посторонней помощи.\"\n  STR_MUTON_UFOPEDIA: \"Эти человекоподобные существа физически и умственно очень развиты. У них особое пристрастие к употреблению в пищу сырого мяса, которое им необходимо для существования, как земным хищникам. Похоже, что они полагаются на телепатическое управление со стороны представителей расы, известной как эфириалы. Как только телепатическая связь прерывается, их нервная система разрушается и они умирают. Кибернетические импланты усиливают их боевые характеристики. Очевидно, что они выполняют роль пехоты для некого высшего разума.\"\n  STR_MUTON_AUTOPSY: \"Вскрытие мутона\"\n  STR_MUTON_AUTOPSY_UFOPEDIA: \"«Кожа» этого существа представляет собой органически выращенную броню, вживленную в тело. Обнаружены многочисленные кибернетические импланты, предназначенные для повышения эффективности сердечно-сосудистой системы и усиления органов чувств. Репродуктивные органы, похоже, были удалены хирургическим путем. Очевидно, жизнь этих несчастных существ сводится к участию в войнах и завоеваниях. Бронебойные боеприпасы малоэффективны против их укрепленной кожи.\"\n  STR_CELATID_UFOPEDIA: \"Эта форма жизни обладает загадочной способностью естественным образом парить в воздухе. Она способна обнаруживать активность человеческого мозга и двигаться в сторону человека, даже находящегося в надежном укрытии. Обнаружив цель, целатид приземляется и выплевывает капельки чрезвычайно едкого ядовитого вещества. Эти существа могут клонировать себя с поразительной скоростью. Они сопровождают расу мутонов в их странствиях.\"\n  STR_CELATID_AUTOPSY: \"Вскрытие целатида\"\n  STR_CELATID_AUTOPSY_UFOPEDIA: \"Ядро содержит маленькое биомеханическое устройство, которое, похоже, представляет собой естественным образом развившуюся антигравитационную двигательную систему. Самым крупным внутренним органом является железа, выделяющая яд. Похоже, отдельный мозговой центр отсутствует; также не обнаружено признаков пищеварительной и репродуктивной систем. Маленький орган содержит эмбрионы, которые могут быстро развиться в новое существо.\"\n  STR_SILACOID_UFOPEDIA: \"Этот организм на основе кремния выделяет огромное количество тепла. Сила, которой он обладает, достаточна для разрушения камней, которые затем поглощает горячее ядро. Эти существа имеют примитивный разум, и ими можно управлять при помощи имплантов или телепатии. Они действуют совместно с инопланетной расой мутонов.\"\n  STR_SILACOID_AUTOPSY: \"Вскрытие силакоида\"\n  STR_SILACOID_AUTOPSY_UFOPEDIA: \"Ядро этого существа выделяет чрезвычайно много тепла и, похоже, является основой его пищеварительной системы. Его уникальная мышечная система обеспечивает этому пришельцу огромную силу и скорость. Прочная как камень шкура этого существа неуязвима для огня и зажигательных снарядов.\"\n  STR_CHRYSSALID_UFOPEDIA: \"Крабовидные клешни этого существа представляют собой мощное оружие ближнего боя. Высокий метаболизм и большая сила этого существа придают ему значительную скорость и ловкость. Оно не убивает своих жертв, а откладывает в них яйца и впрыскивает яд, превращающий жертву в ходячего зомби. Молодой криссалид вылупляется из жертвы вскоре после введения яйца. Криссалиды действуют совместно с расой человекозмеев.\"\n  STR_CHRYSSALID_AUTOPSY: \"Вскрытие криссалида\"\n  STR_CHRYSSALID_AUTOPSY_UFOPEDIA: \"Экзоскелет этого существа чрезвычайно прочный, однако неожиданно уязвимый для фугасных боеприпасов. Мозг хорошо развит, и скорость роста его клеток очень высока. Существо несет двадцать яиц, которые оно откладывает в тела других живых существ. Это существо представляет собой крайне эффективное орудие террора.\"\n  STR_FLOATER_UFOPEDIA: \"Летуны - это в первую очередь солдаты и террористы. По своей природе это хищные звери, которые были превращены в грозных воинов сочетанием генной инженерии и кибернетики. Нижняя часть тела и большинство внутренних органов хирургически удалены и заменены системой жизнеобеспечения. Этот имплант включает антигравитационное устройство, которое позволяет этому существу, хоть и неуверенно, парить в воздухе.\"\n  STR_FLOATER_AUTOPSY: \"Вскрытие летуна\"\n  STR_FLOATER_AUTOPSY_UFOPEDIA: \"Это существо было кардинально изменено хирургически. Устройством, которое составляет ядро организма, является система жизнеобеспечения, выполняющая функции сердца, легких и системы пищеварения. Это позволит существу выжить в чрезвычайно враждебных условиях. Мозг меньше, чем наш, но органы чувств хорошо развиты.\"\n  STR_REAPER_UFOPEDIA: \"Это двуногое плотоядное животное имеет мощные челюсти и крайне прожорливо. Оно наделено рядом мозговых имплантов, которые используются для управления им. Примитивные инстинкты хищника едва ли годятся для чего-либо, кроме террора и разрушения. Жнецы обычно действуют совместно летунами.\"\n  STR_REAPER_AUTOPSY: \"Вскрытие жнеца\"\n  STR_REAPER_AUTOPSY_UFOPEDIA: \"Жнец имеет два «мозга» и два «сердца», что позволяет ему сохранять боеспособность, даже если он тяжело ранен. Однако его покрытая шерстью шкура легко воспламеняется, что делает это существо уязвимым для зажигательного оружия.\"\n  STR_SECTOPOD_UFOPEDIA: \"Сектоподы - это роботы, оснащенные мощным лазерным оружием. Управление этими механическими монстрами осуществляется их операторами, эфириалами, по телепатическому каналу. Сектоподы представляют собой наиболее мощное орудие террора пришельцев.\"\n  STR_SECTOPOD_AUTOPSY: \"Вскрытие сектопода\"\n  STR_SECTOPOD_AUTOPSY_UFOPEDIA: \"Этот прочный робот обладает усиленной броней, способной выдержать большинство видов воздействия, особенно плазмы. Однако его сенсоры, похоже, серьезно уязвимы для лазерного оружия.\"\n  STR_CYBERDISC_UFOPEDIA: \"Эта миниатюрная версия летающей тарелки представляет собой автоматизированное орудие террора, оснащенное мощным плазменным излучателем. Благодаря антигравитационному приводу кибердиск обладает большим преимуществом в мобильности на пересеченной местности. В его задачи входит причинение разрушений и проведение террора под контролем сектоидов.\"\n  STR_CYBERDISC_AUTOPSY: \"Вскрытие кибердиска\"\n  STR_CYBERDISC_AUTOPSY_UFOPEDIA: \"Кибердиск обладает эффективным бронированием и особенно устойчив к действию фугасных боеприпасов. Антигравитационный модуль слишком сильно поврежден, что не позволяет понять принцип его действия.\"\n  STR_UFO_POWER_SOURCE_UFOPEDIA: \"Источник энергии кораблей пришельцев - это реактор на антиматерии, который использует элерий (115-й элемент химической таблицы) для создания мощных гравитационных волн, а также других форм энергии. КПД преобразования материи в энергию невероятно высок и достигает 99 %, поэтому даже крошечная крупица элерия позволяет произвести огромное количество энергии. Это устройство можно легко воспроизвести, используя сплавы пришельцев.\"\n  STR_UFO_NAVIGATION_UFOPEDIA: \"Полетом инопланетных кораблей в гравитационном поле планеты и открытом космосе управляют сложные компьютеры. В системе используются оптические процессоры, объединенные в сеть. Интерфейс управления относительно прост: навигатор изменяет направление гравитационных волн, исходящих от источника энергии, чтобы переместить корабль в нужном направлении. Человек может с легкостью использовать эту систему, а также воспроизвести ее, используя сплавы пришельцев и ряд других компонентов.\"\n  STR_UFO_CONSTRUCTION_UFOPEDIA: \"Корабль пришельцев состоит из трех основных подсистем - источника энергии, навигационной системы и корпуса. Особая форма корпуса позволяет направлять гравитационные волны в произвольном направлении. Для источника энергии требуется небольшое количество элерий. Зная устройство всех компонентов корабля, мы сможем строить аппараты подобного типа.\"\n  STR_ALIEN_FOOD_UFOPEDIA: \"Камеры содержат раствор энзимов, предназначенный для расщепления тканей животного происхождения (или даже человеческих органов). Производимый в камерах раствор использовался в качестве пищи. Предполагаемый способ употребления - прямая инъекция в кровоток. Это предполагает некоторую зависимость пришельцев от Земли для производства пищи.\"\n  STR_ALIEN_REPRODUCTION_UFOPEDIA: \"В капсулах находятся зародыши инопланетных организмов. Устройство этих инкубаторов свидетельствует о том, что пришельцы полностью перешли на искусственный метод воспроизводства. В случае промышленного применения подобная система способна произвести тысячи клонов в короткое время. Процесс может быть легко адаптирован к человеческому или гибридному организму.\"\n  STR_ALIEN_ENTERTAINMENT_UFOPEDIA: \"Наиболее вероятная функция этих сфер - отдых и восстановление. Псионический контур стимулирует различные центры мозга. Производимый эффект сходен с действием галлюциногенных наркотиков. Это - единственное свидетельство, что пришельцы имеют культурное или развлекательное времяпрепровождение.\"\n  STR_ALIEN_SURGERY_UFOPEDIA: \"Это хирургическое оборудование использует лазерный скальпель для извлечения частей тела у крупного рогатого скота и других животных. Повсеместные случаи калечения скота, вероятно, происходят с применением этих странных устройств. Скорее всего, органы используются для пищи и генетических опытов.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"В прошлом многие тысячи людей утверждали, что был похищены инопланетянами, иногда неоднократно. Истина гораздо более ужасна. Людей похищают, изучают и наблюдают. Лучшие экземпляры служат источником генетического материала. Женщинам имплантируются инопланетные гибридные зародыши, извлекаемые по прошествии нескольких месяцев развития. Неизвестно, какими зловещими мотивами руководствуются пришельцы в своей деятельности.\"\n  STR_ALIEN_ALLOYS_UFOPEDIA: \"Корабли пришельцев построены из особых сплавов, обладающих уникальными свойствами. Они чрезвычайно легки и прочны, и могут изменять форму под воздействием электромагнитных полей. Этот материал можно воспроизвести, используя методы электрометаллургии, и использовать в ряде производственных процессов.\"\n  STR_ELERIUM_115_UFOPEDIA: \"Этот элемент обладает необычным свойством производить антивещество при бомбардировке определенными частицами. Это приводит к возникновению гравитационных волн и других форм энергии. Этот элемент не обнаружен в естественном виде в Солнечной системе, и мы не можем его синтезировать искусственным путем.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"Очевидно, что дальнейшая борьба за Землю бесперспективна. Противник превосходит нас числом. Самое большее, что мы можем сделать - это замедлить его продвижение. Единственный наш шанс победить - это уничтожить источник вторжения. Исследования показывают, что он находится в пределах нашей Солнечной системы. Пришельцы описывают это место как центр древней цивилизации, возникшей намного раньше человечества. Мы должны обнаружить его как можно скорее. Для получения подробной информации необходимо захватить пришельца-лидера. Предположительно, на крупных кораблях противника должен присутствовать по меньшей мере один лидер.\"\n  STR_THE_MARTIAN_SOLUTION_UFOPEDIA: \"По результатам исследований, основная база сил вторжения располагается на Марсе. База хорошо замаскирована и располагает всеми средствами производства техники и живой силы для проникновения на Землю. Также там находится некий управляющий компьютерный центр, командующий всеми операциями противника. Роеподобное по своей структуре общество пришельцев имеет \\\"королеву роя\\\", и в этом их фундаментальная слабость - если мы сможем уничтожить этот \\\"мозг\\\", вся армия погибнет, как одно существо. Мы должны ускорить исследования в этом направлении, пока не поздно. Чтобы достигнуть успеха, необходимо допросить пришельцев наиболее высокого ранга - командующих, постоянно находящихся на базах.\"\n  STR_CYDONIA_OR_BUST_UFOPEDIA: \"Установлено, что армия пришельцев управляется из подземной базы в Кидонии - странной области Марса, известной расположенными там пирамидами и образованием, напоминающим изображение человеческого лица. Кидонийская цивилизация процветала много миллионов лет назад, причины ее гибели неизвестны, равно как и связь этой цивилизации с активностью инопланетян в наше время. Независимо от объяснений мы должны лететь на Кидонию. Есть лишь один способ победить пришельцев - уничтожить центральный управляющий \\\"мозг\\\". Нам понадобится \\\"Мститель\\\" - транспорт, оборудованный наилучшим доступным нам оружием, способный доставить десант на Марс. Мы не можем узнать больше, оставаясь здесь, и вынуждены ждать результатов штурма Кидонии.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"ФОКУС НА ТОЧКЕ, ВРЕМЯ=5 сек.\"\n  STR_CANCEL_UC: \"ОТМЕНА\"\n  STR_NONE: \"Отсутствует\"\n  STR_UNKNOWN: \"Неизвестно\"\n  STR_POOR: \"Плохо\"\n  STR_AVERAGE: \"Посредственно\"\n  STR_GOOD: \"Хорошо\"\n  STR_EXCELLENT: \"Превосходно\"\n  STR_BUILD_NEW_BASE_UC: \"СТРОИТЬ НОВУЮ БАЗУ\"\n  STR_BASE_INFORMATION: \"ИНФОРМАЦИЯ ПО БАЗЕ\"\n  STR_EQUIP_CRAFT: \"СНАРЯДИТЬ ТС\"\n  STR_BUILD_FACILITIES: \"СТРОИТЬ МОДУЛИ\"\n  STR_RESEARCH: \"ИССЛЕДОВАНИЕ\"\n  STR_MANUFACTURE: \"ПРОИЗВОДСТВО\"\n  STR_TRANSFER_UC: \"ТРАНСПОРТИРОВКА\"\n  STR_PURCHASE_RECRUIT: \"ЗАКУПКА/ВЕРБОВКА\"\n  STR_SACK: \"УВОЛИТЬ\"\n  STR_SELL_SACK_UC: \"ПРОДАТЬ/УВОЛИТЬ\"\n  STR_GEOSCAPE_UC: \"ГЛОБУС\"\n  STR_NAME: \"Имя\"\n  STR_AREA: \"Регион\"\n  STR_BUILD_NEW_BASE: \"Строить новую базу\"\n  STR_CANCEL: \"Отмена\"\n  STR_COST_UC: \"СТОИМОСТЬ>\"\n  STR_CONSTRUCTION_TIME_UC: \"ВРЕМЯ СТРОИТЕЛЬСТВА>\"\n  STR_DAY:\n    one: \"{N} день\"\n    few: \"{N} дня\"\n    many: \"{N} дней\"\n    other: \"{N} дней\"\n  STR_HOUR:\n    one: \"{N} час\"\n    few: \"{N} часа\"\n    many: \"{N} часов\"\n    other: \"{N} часов\"\n  STR_MAINTENANCE_UC: \"ОБСЛУЖИВАНИЕ>\"\n  STR_OK: \"ОК\"\n  STR_INSTALLATION: \"Строить:\"\n  STR_CURRENT_RESEARCH: \"ТЕКУЩИЕ ИССЛЕДОВАНИЯ\"\n  STR_SCIENTISTS_AVAILABLE: \"Ученых доступно>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Ученых занято>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Места в лаборатории доступно>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"ИССЛЕДОВАТЬ ПРОЕКТ\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"УЧЕНЫХ ЗАНЯТО\"\n  STR_PROGRESS: \"ПРОГРЕСС\"\n  STR_NEW_PROJECT: \"Новый проект\"\n  STR_CANCEL_PROJECT: \"ОТМЕНА ПРОЕКТА\"\n  STR_NEW_RESEARCH_PROJECTS: \"НАЧАТЬ НОВЫЙ ПРОЕКТ\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"УЧЕНЫХ ДОСТУПНО>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"МЕСТА В ЛАБОРАТОРИЯХ ДОСТУПНО>{ALT}{0}\"\n  STR_INCREASE: \"Увеличить\"\n  STR_DECREASE: \"Уменьшить\"\n  STR_START_PROJECT: \"НАЧАТЬ ПРОЕКТ\"\n  STR_CURRENT_PRODUCTION: \"ТЕКУЩЕЕ ПРОИЗВОДСТВО\"\n  STR_ENGINEERS_AVAILABLE: \"Инженеров доступно>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Инженеров занято>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Рабочих мест доступно>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Текущий баланс>{ALT}{0}\"\n  STR_ITEM: \"ИЗДЕЛИЕ\"\n  STR_ENGINEERS__ALLOCATED: \"Инженеров занято\"\n  STR_UNITS_PRODUCED: \"Единиц произвед.\"\n  STR_TOTAL_TO_PRODUCE: \"Всего к произв.\"\n  STR_COST__PER__UNIT: \"Цена{NEWLINE}за ед.\"\n  STR_DAYS_HOURS_LEFT: \"Дней/часов осталось\"\n  STR_NEW_PRODUCTION: \"Новое производство\"\n  STR_PRODUCTION_ITEMS: \"Произвести изделие\"\n  STR_CATEGORY: \"КАТЕГОРИЯ\"\n  STR_START_PRODUCTION: \"НАЧАТЬ ПРОИЗВОДСТВО\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} человеко-часов на производство единицы\"\n  STR_COST_PER_UNIT_: \"Стоимость за ед.>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Требуется рабочих мест>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"ТРЕБУЮТСЯ СПЕЦИАЛЬНЫЕ МАТЕРИАЛЫ\"\n  STR_ITEM_REQUIRED: \"НЕОБХОДИМЫЕ МАТЕРИАЛЫ\"\n  STR_UNITS_REQUIRED: \"ТРЕБУЕТСЯ ЕДИНИЦ\"\n  STR_UNITS_AVAILABLE: \"ДОСТУПНО ЕДИНИЦ\"\n  STR_STOP_PRODUCTION: \"ОСТАНОВИТЬ ПРОИЗВОДСТВО\"\n  STR_ENGINEERS_AVAILABLE_UC: \"ИНЖЕНЕРОВ ДОСТУПНО>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"МЕСТА В МАСТЕРСКИХ ДОСТУПНО>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"ДОХОД В МЕСЯЦ>{ALT}{0}\"\n  STR_INCREASE_UC: \"УВЕЛИЧИТЬ\"\n  STR_DECREASE_UC: \"УМЕНЬШИТЬ\"\n  STR_UNITS_TO_PRODUCE: \"Произвести\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Купить/Нанять\"\n  STR_COST_OF_PURCHASES: \"Стоимость покупки>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"ЦЕНА ЗА ЕД.\"\n  STR_QUANTITY_UC: \"КОЛ-ВО\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"ДОСТУПНО ЧЕЛОВЕК:ВСЕГО ЧЕЛОВЕК>\"\n  STR_SOLDIERS: \"Бойцы\"\n  STR_SCIENTISTS: \"Ученые\"\n  STR_ENGINEERS: \"Инженеры\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"МЕСТА ЗАНЯТО:МЕСТА ДОСТУПНО>\"\n  STR_LIVING_QUARTERS: \"Жилые модули\"\n  STR_STORES: \"Склады\"\n  STR_LABORATORIES: \"Лаборатории\"\n  STR_WORK_SHOPS: \"Мастерские\"\n  STR_HANGARS: \"Ангар\"\n  STR_SHORT_RANGE_DETECTION: \"Ближнее обнаружение\"\n  STR_DEFENSE_STRENGTH: \"Мощность ПВО\"\n  STR_TRANSFERS_UC: \"ТРАНСПОРТИРОВКИ\"\n  STR_TRANSFERS: \"Транспортировки\"\n  STR_ARRIVAL_TIME_HOURS: \"Время прибытия (часов)\"\n  STR_COST_: \"Стоимость>{ALT}{0}\"\n  STR_AREA_: \"Регион>{ALT}{0}\"\n  STR_BASE_NAME: \"Название базы?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"ВЫБЕРИТЕ МЕСТО ДЛЯ ВХОДНОГО ЛИФТА\"\n  STR_TRANSFER: \"Транспортировка\"\n  STR_AMOUNT_TO_TRANSFER: \"КОЛ-ВО ДЛЯ ОТПРАВКИ\"\n  STR_SELECT_DESTINATION_BASE: \"Выберите место назначения\"\n  STR_COST: \"Стоимость\"\n  STR_VICTORY_1: \"Войдя в зал, вы видите инопланетный Мозг - цель ваших поисков. Прежде чем вы успеваете выстрелить, Мозг обращается к вам через находящийся в помещении экран. Он просит выслушать аргументы в свою защиту прежде, чем вы нажмете на спусковой крючок...\"\n  STR_VICTORY_2: \"Мозг говорит: «Много миллионов лет назад на планете, которую вы именуете Марсом, цвела жизнь. Эта жизнь была принесена на бесплодную планету нашей цивилизацией, как это затем произошло и с вашей. Миллионы лет мы посещали вашу планету и генетически развивали ваш вид. Вы не можете уничтожить нас, вы - часть нас...\"\n  STR_VICTORY_3: \"...Здесь находится центр Марсианской цивилизации - эти пирамиды построены за миллионы лет до ваших пирамид существами, которые были вашими предками. Не существует планет, которые мы не могли бы достигнуть. Эта мощь и технологии вскоре могут стать вашими. Все, что мы просим - это сотрудничество...\"\n  STR_GAME_OVER_1: \"Пришельцы пытаются истребить все человечество, разрушая города, отравляя воздух и воду. Сопротивление земных армий тщетно перед превосходящими инопланетными технологиями. Выжившие поколения, спасаясь от уничтожения, страдают от ужасных мутаций. Они помещены в специальные лагеря, где их используют как рабов для превращения Земли в колонию огромной неизвестной империи пришельцев.\"\n  STR_GAME_OVER_2: \"Знания, добытые проектом Х-Сom, потеряны навсегда. Вы не сумели защитить Землю.\"\n  STR_VICTORY_4: \"Излияния мозга прервал сгусток раскаленной плазмы, и силы пришельцев были повержены.\"\n  STR_VICTORY_5: \"Пришельцы потеряли Марс, а значит - и Землю. Скоро исследования Х-Сom позволят человечеству достичь истинного процветания и начать колонизацию Марса. Инопланетная угроза устранена, но надолго ли, никто не знает...\"\n  STR_YOU_HAVE_FAILED: \"Вы не сумели остановить вторжение. Одна за другой ведущие мировые державы подписывают пакт с пришельцами, обещающими новые технологии, процветание и мир. Однако вскоре становится очевидно, что у пришельцев совсем другие планы...\"\n  STR_TOTAL_UC: \"ВСЕГО\"\n  STR_INCOME: \"Доход\"\n  STR_EXPENDITURE: \"Расход\"\n  STR_MAINTENANCE: \"Обслуживание\"\n  STR_BALANCE: \"Баланс\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"Активн. НЛО в регионах\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"Активн. НЛО в странах\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"Активн. X-Com в регионах\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"Активн. X-Com в странах\"\n  STR_FINANCE: \"Финансы\"\n  STR_DATE_FIRST: \"{0}\"\n  STR_DATE_SECOND: \"{0}\"\n  STR_DATE_THIRD: \"{0}\"\n  STR_DATE_FOURTH: \"{0}\"\n  STR_FINANCE_THOUSANDS: \"тыс. $\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"{0}{NEWLINE}требует материалов для производства на базе{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"{0}{NEWLINE}требует денег для производства на базе{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"{0}{NEWLINE}{NEWLINE}Завершено{NEWLINE}производство{NEWLINE}на базе{NEWLINE}{1}\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"{0}{NEWLINE}{NEWLINE}Завершено{NEWLINE}строительство{NEWLINE}на базе{NEWLINE}{1}\"\n  STR_OK_5_SECONDS: \"ОК - 5 сек.\"\n  STR_RESEARCH_COMPLETED: \"Исследование завершено\"\n  STR_VIEW_REPORTS: \"ОТЧЕТ\"\n  STR_WE_CAN_NOW_RESEARCH: \"Теперь мы можем исследовать\"\n  STR_WE_CAN_NOW_PRODUCE: \"Теперь мы можем произвести\"\n  STR_SUNDAY: \"ВОСКРЕСЕНЬЕ\"\n  STR_MONDAY: \"ПОНЕДЕЛЬНИК\"\n  STR_TUESDAY: \"ВТОРНИК\"\n  STR_WEDNESDAY: \"СРЕДА\"\n  STR_THURSDAY: \"ЧЕТВЕРГ\"\n  STR_FRIDAY: \"ПЯТНИЦА\"\n  STR_SATURDAY: \"СУББОТА\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Требуется {0}, чтобы заправить {1} на базе {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Требуется {0}, чтобы доукомплектовать {1} на базе {2}\"\n  STR_UFO_IS_NOT_RECOVERED: \"НЛО не захвачен\"\n  STR_UFO_IS_RECOVERED: \"НЛО захвачен\"\n  STR_CRAFT_IS_LOST: \"Транспорт потерян\"\n  STR_TERROR_CONTINUES: \"Террор продолжается\"\n  STR_ALIENS_DEFEATED: \"Пришельцы побеждены\"\n  STR_BASE_IS_LOST: \"База потеряна\"\n  STR_BASE_IS_SAVED: \"Нападение отражено\"\n  STR_ALIEN_BASE_STILL_INTACT: \"База пришельцев все еще действует\"\n  STR_ALIEN_BASE_DESTROYED: \"База пришельцев уничтожена\"\n  STR_ALIENS_KILLED: \"ПРИШЕЛЬЦЕВ УБИТО\"\n  STR_ALIEN_CORPSES_RECOVERED: \"ТРУПОВ ПРИШЕЛЬЦЕВ НАЙДЕНО\"\n  STR_LIVE_ALIENS_RECOVERED: \"ЖИВЫХ ПРИШЕЛЬЦЕВ НАЙДЕНО\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"ИНОПЛАНЕТНЫХ АРТЕФАКТОВ НАЙДЕНО\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"БАЗА ПРИШЕЛЬЦЕВ УНИЧТОЖЕНА\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"ГРАЖДАНСКИХ УБИТО ПРИШЕЛЬЦАМИ\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"ГРАЖДАНСКИХ УБИТО БОЙЦАМИ X-COM\"\n  STR_CIVILIANS_SAVED: \"ГРАЖДАНСКИХ СПАСЕНО\"\n  STR_XCOM_OPERATIVES_KILLED: \"БОЙЦОВ X-COM УБИТО\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"БОЙЦОВ X-COM ПРОПАЛО БЕЗ ВЕСТИ\"\n  STR_TANKS_DESTROYED: \"ТАНКОВ УНИЧТОЖЕНО\"\n  STR_XCOM_CRAFT_LOST: \"ТС X-COM ПОТЕРЯНО\"\n  STR_UFO_RECOVERY: \"ДОБЫТО В НЛО\"\n  STR_ALIEN_BASE_RECOVERY: \"ДОБЫТО НА БАЗЕ ПРИШЕЛЬЦЕВ\"\n  STR_BASE_UNDER_ATTACK: \"База {0} атакована!\"\n  STR_BASE_DEFENSES_INITIATED: \"ЗАДЕЙСТВОВАНА ПВО БАЗЫ\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"ГРАВИТАЦИОННЫЙ ЩИТ ОТТАЛКИВАЕТ НЛО!\"\n  STR_FIRING: \"ВЫСТРЕЛ\"\n  STR_HIT: \"ПОПАДАНИЕ!\"\n  STR_UFO_DESTROYED: \"НЛО УНИЧТОЖЕН!\"\n  STR_MISSED: \"ПРОМАХ!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Продать/Уволить\"\n  STR_VALUE_OF_SALES: \"СТОИМОСТЬ ПРОДАЖИ> {ALT}{0}\"\n  STR_FUNDS: \"БАЛАНС> {ALT}{0}\"\n  STR_SELL_SACK: \"Продать/Уволить\"\n  STR_VALUE: \"Цена\"\n  STR_CRAFT_: \"ТС> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"ЗАХВАТ СБИТОГО НЛО\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"Будьте осторожны - вокруг и внутри НЛО могут быть пришельцы. Миссия будет успешно завершена, когда все вражеские силы будут уничтожены или нейтрализованы. Остатки НЛО, артефакты и трупы пришельцев будут автоматически эвакуированы. В случае необходимости прервать миссию, верните оперативников в транспорт и нажмите \\\"Покинуть поле боя\\\".\"\n  STR_UFO_GROUND_ASSAULT: \"НАЗЕМНЫЙ ШТУРМ НЛО\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"Обследуйте место посадки и по возможности проникните внутрь НЛО. Задание будет успешно завершено после ликвидации или нейтрализации всех сил противника. По завершении задания НЛО, артефакты и тела пришельцев будут автоматически эвакуированы. Чтобы прервать задание, верните всех бойцов X-Com на транспорт и нажмите кнопку «Покинуть поле боя».\"\n  STR_BASE_DEFENSE: \"ЗАЩИТА БАЗЫ\"\n  STR_BASE_UC_: \"БАЗА> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"Где-то неподалеку приземлился корабль пришельцев. Нашей базе грозит уничтожение. В соответствии с установленными процедурами, невоенный персонал и ТС X-Com были эвакуированы. Пришельцы могут проникнуть в помещения базы через ангары или входной лифт. Защищайте базу и все важные модули любой ценой: отступать некуда. Нажатие на кнопку «Покинуть поле боя» равносильно сдаче и приведет к потере базы.\"\n  STR_ALIEN_BASE_ASSAULT: \"ШТУРМ БАЗЫ ПРИШЕЛЬЦЕВ\"\n  STR_ALIEN_BASE_ASSAULT_BRIEFING: \"Бойцы X-Com проникли на базу пришельцев. Необходимо разрушить командный центр, чтобы вывести базу из строя. Миссия автоматически завершится, если все силы противника будут нейтрализованы или когда ваше подразделение вернется в зону выхода, подсвеченную зеленым (нажмите кнопку «Покинуть поле боя» для эвакуации).\"\n  STR_CYDONIA_BRIEFING: \"Вы прибыли в Кидонию. Необходимо проникнуть в подземный комплекс сооружений рядом с Марсианским Сфинксом. Вы должны найти и уничтожить центральный мозг инопланетной колонии, управляющий вторжением. Судьба человечества находится в ваших руках..\"\n  STR_TERROR_MISSION: \"ПОДАВЛЕНИЕ ТЕРРОРА\"\n  STR_TERROR_MISSION_BRIEFING: \"Задание считается выполненным, когда все противники будут уничтожены или нейтрализованы. Ваша задача - защитить любых гражданских лиц в зоне операции путем нейтрализации пришельцев. Чтобы прервать задание, верните всех бойцов X-Com на транспорт и нажмите кнопку «Покинуть поле боя».\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"НЕТ СВОБОДНОГО АНГАРА ДЛЯ СТРОИТЕЛЬСТВА КОРАБЛЯ!{SMALLLINE}Каждый корабль, приписанный к базе, транспортируемый на базу, приобретенный или строящийся использует один ангар. Постройте новый ангар или переправьте корабль на другую базу.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"НЕТ СВОБОДНОГО АНГАРА ДЛЯ ПОКУПКИ КОРАБЛЯ!{SMALLLINE}Каждый корабль, приписанный к базе, транспортируемый на базу, приобретенный или строящийся использует один ангар. Постройте новый ангар или переправьте корабль на другую базу.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"НЕТ СВОБОДНОГО АНГАРА ДЛЯ ТРАНСПОРТИРОВКИ!{SMALLLINE}Каждое ТС, приписанное к базе, транспортируемое на базу, приобретенное или строящееся, использует один ангар. Постройте новый ангар или переправьте ТС на другую базу.\"\n  STR_CANNOT_BUILD_HERE: \"НЕЛЬЗЯ СТРОИТЬ ЗДЕСЬ!{SMALLLINE}Строительство возможно только рядом с уже существующим модулем.\"\n  STR_NO_FREE_ACCOMODATION: \"НЕТ СВОБОДНОГО ПОМЕЩЕНИЯ!{SMALLLINE}На базе назначения не хватает мест в жилых модулях.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"НЕДОСТАТОЧНО РАБОЧЕГО МЕСТА!{SMALLLINE}Постройте новую мастерскую или сократите работы над другими проектами.\"\n  STR_NOT_ENOUGH_MONEY: \"НЕ ХВАТАЕТ ДЕНЕГ!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"НЕДОСТАТОЧНО МЕСТА НА СКЛАДЕ!{SMALLLINE}Постройте новые склады или перевезите складируемое на другие базы.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"НЕ ХВАТАЕТ МЕСТ В ЖИЛЫХ МОДУЛЯХ!{SMALLLINE}Постройте жилые модули или переправьте персонал на другие базы.\"\n  STR_LAUNCH_INTERCEPTION: \"ЗАПУСТИТЬ ПЕРЕХВАТЧИК\"\n  STR_CRAFT: \"ТС\"\n  STR_STATUS: \"СТАТУС\"\n  STR_BASE: \"БАЗА\"\n  STR_READY: \"ГОТОВ\"\n  STR_OUT: \"НА ВЫЛЕТЕ\"\n  STR_REPAIRS: \"РЕМОНТ\"\n  STR_REFUELLING: \"ЗАПРАВКА\"\n  STR_REARMING: \"ПЕРЕЗАРЯДКА\"\n  STR_TARGET: \"ЦЕЛЬ: {0}\"\n  STR_WAY_POINT: \"ПУТЕВАЯ ТОЧКА\"\n  STR_ARE_YOU_SURE_CYDONIA: \"Вы уверены, что хотите послать экспедицию в Кидонию?\"\n  STR_YES: \"ДА\"\n  STR_NO: \"НЕТ\"\n  STR_SELECT_DESTINATION: \"ВЫБЕРИТЕ ЦЕЛЬ\"\n  STR_CYDONIA: \"КИДОНИЯ\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"ВЫБЕРИТЕ МЕСТО ДЛЯ НОВОЙ БАЗЫ\"\n  STR_RETURN_TO_BASE: \"ВЕРНУТЬСЯ НА БАЗУ\"\n  STR_SELECT_NEW_TARGET: \"ВЫБРАТЬ НОВУЮ ЦЕЛЬ\"\n  STR_PATROL: \"ПАТРУЛИРОВАТЬ\"\n  STR_STATUS_: \"СТАТУС>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"ПОВРЕЖДЕН - ВОЗВРАЩАЮСЬ НА БАЗУ\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"МАЛО ТОПЛИВА - ВОЗВРАЩАЮСЬ НА БАЗУ\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"ЗАДАНИЕ ВЫПОЛНЕНО - ВОЗВРАЩАЮСЬ НА БАЗУ\"\n  STR_PATROLLING: \"ПАТРУЛИРОВАНИЕ\"\n  STR_TAILING_UFO: \"ПРЕСЛЕДОВАНИЕ НЛО\"\n  STR_INTERCEPTING_UFO: \"ПЕРЕХВАТ НЛО-{0}\"\n  STR_RETURNING_TO_BASE: \"ВОЗВРАЩАЮСЬ НА БАЗУ\"\n  STR_DESTINATION_UC_: \"ПУНКТ НАЗНАЧЕНИЯ: {0}\"\n  STR_BASE_UC: \"БАЗА>{ALT}{0}\"\n  STR_SPEED_: \"СКОРОСТЬ>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"МАКС. СКОРОСТЬ>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"ВЫСОТА>{ALT}{0}\"\n  STR_VERY_LOW: \"ОЧ. МАЛАЯ\"\n  STR_LOW_UC: \"МАЛАЯ\"\n  STR_HIGH_UC: \"БОЛЬШАЯ\"\n  STR_VERY_HIGH: \"ОЧ. БОЛЬШ.\"\n  STR_FUEL: \"ТОПЛИВО>{ALT}{0}\"\n  STR_WEAPON_ONE: \"ОРУЖИЕ-1>{ALT}{0}\"\n  STR_NONE_UC: \"НЕТ\"\n  STR_ROUNDS_: \"БОЕЗАПАС>{ALT}{0}\"\n  STR_WEAPON_TWO: \"ОРУЖИЕ-2>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"ПЕРЕХВАТЧИК\"\n  STR_BASE_: \"База>{0}\"\n  STR_NAME_UC: \"ИМЯ\"\n  STR_AMMO_: \"БОЕЗАПАС>{ALT}{0}\"\n  STR_CREW: \"ЭКИПАЖ\"\n  STR_EQUIPMENT_UC: \"СНАРЯЖЕНИЕ\"\n  STR_ARMOR: \"БРОНЯ\"\n  STR_MAX: \"МАКС>{ALT}{0}\"\n  STR_ROOKIE: \"Новобранец\"\n  STR_SQUADDIE: \"Рядовой\"\n  STR_SERGEANT: \"Сержант\"\n  STR_CAPTAIN: \"Капитан\"\n  STR_COLONEL: \"Полковник\"\n  STR_COMMANDER: \"Командующий\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"{0}: Экипаж и пассажиры\"\n  STR_SORT_BY: \"СОРТИРОВКА\"\n  STR_ORIGINAL_ORDER: \"ОБЫЧНЫЙ ПОРЯДОК\"\n  STR_MISSIONS2: \"МИССИЙ\"\n  STR_KILLS2: \"УБИЙСТВ\"\n  STR_WOUND_RECOVERY2: \"ЛЕЧЕНИЕ\"\n  STR_SPACE_AVAILABLE: \"МЕСТА ДОСТУПНО>{ALT}{0}\"\n  STR_SPACE_USED: \"МЕСТА ЗАНЯТО>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"  МЕСТА\"\n  STR_RANK: \"ЗВАНИЕ\"\n  STR_WOUNDED: \"РАНЕНИЕ\"\n  STR_EQUIPMENT_FOR_CRAFT: \"{0}: Техника и снаряжение\"\n  STR_DEFENSE_VALUE: \"Степень защиты\"\n  STR_HIT_RATIO: \"Точность\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"ТС {0}{ALT}{NEWLINE}готово{NEWLINE}к высадке возле{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"Начать операцию?\"\n  STR_SELECT_ARMAMENT: \"Выберите оружие\"\n  STR_AMMUNITION_AVAILABLE: \"{NEWLINE}БОЕЗАПАС\"\n  STR_ARMAMENT: \"ОРУЖИЕ\"\n  STR_NOT_AVAILABLE: \"НЕТ\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"{0}{NEWLINE}ВЫБЕРИТЕ БРОНЮ\"\n  STR_TYPE: \"ТИП\"\n  STR_PERSONAL_ARMOR_UC: \"БРОНЕКОСТЮМ\"\n  STR_POWER_SUIT_UC: \"ЭНЕРГОСКАФАНДР\"\n  STR_FLYING_SUIT_UC: \"ЛЕТАЮЩИЙ СКАФАНДР\"\n  STR_SELECT_ARMOR: \"Экипировка бронезащитой\"\n  STR_NORTH: \"СЕВЕР\"\n  STR_NORTH_EAST: \"СЕВ.-ВОСТ.\"\n  STR_EAST: \"ВОСТОК\"\n  STR_SOUTH_EAST: \"ЮГО-ВОСТ.\"\n  STR_SOUTH: \"ЮГ\"\n  STR_SOUTH_WEST: \"ЮГО-ЗАП.\"\n  STR_WEST: \"ЗАПАД\"\n  STR_NORTH_WEST: \"СЕВ.-ЗАП.\"\n  STR_SELECT_ACTION: \"ВЫБЕРИТЕ ДЕЙСТВИЕ\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"ПРОДОЛЖИТЬ ПРЕСЛЕДОВАНИЕ\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"ПРЕСЛЕДОВАТЬ БЕЗ ПЕРЕХВАТА\"\n  STR_VERY_LARGE: \"ОЧ. БОЛЬШ.\"\n  STR_LARGE: \"БОЛЬШОЙ\"\n  STR_MEDIUM_UC: \"СРЕДНИЙ\"\n  STR_SMALL: \"МАЛЕНЬКИЙ\"\n  STR_VERY_SMALL: \"ОЧ. МАЛ.\"\n  STR_GROUNDED: \"НА ЗЕМЛЕ\"\n  STR_DETECTED: \"Обнаружен\"\n  STR_SIZE_UC: \"РАЗМЕР\"\n  STR_ALTITUDE: \"ВЫСОТА\"\n  STR_HEADING: \"НАПРАВЛ.\"\n  STR_SPEED: \"СКОРОСТЬ\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"ФОКУС НА НЛО, ВРЕМЯ=5 сек.\"\n  STR_TRACKING_LOST: \"ВНЕ ЗОНЫ РАДАРА\"\n  STR_REDIRECT_CRAFT: \"ПЕРЕНАПРАВИТЬ ТС\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"К ПОСЛЕДНЕЙ ИЗВЕСТНОЙ ПОЗИЦИИ НЛО\"\n  STR_UFO_: \"НЛО-{0}\"\n  STR_ALIEN_BASE_: \"БАЗА ПРИШЕЛЬЦЕВ-{0}\"\n  STR_CRASH_SITE_: \"МЕСТО КРУШЕНИЯ-{0}\"\n  STR_LANDING_SITE_: \"МЕСТО ПОСАДКИ-{0}\"\n  STR_WAY_POINT_: \"ПУТЕВАЯ ТОЧКА-{0}\"\n  STR_TERROR_SITE: \"МЕСТО ТЕРРОРА-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"ТС {0}{NEWLINE}достигло места{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"Патрулирует\"\n  STR_ALIEN_ORIGINS: \"Происхождение пришельцев\"\n  STR_THE_MARTIAN_SOLUTION: \"Решение Марсианского вопроса\"\n  STR_CYDONIA_OR_BUST: \"Кидония или смерть\"\n  STR_UFOPAEDIA: \"УФОпедия\"\n  STR_XCOM_CRAFT_ARMAMENT: \"ТЕХНИКА И ВООРУЖЕНИЕ X-COM\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"ТЯЖЕЛЫЕ БОЕВЫЕ ПЛАТФОРМЫ\"\n  STR_WEAPONS_AND_EQUIPMENT: \"ОРУЖИЕ И СНАРЯЖЕНИЕ\"\n  STR_ALIEN_ARTIFACTS: \"ИНОПЛАНЕТНЫЕ АРТЕФАКТЫ\"\n  STR_BASE_FACILITIES: \"МОДУЛИ БАЗЫ\"\n  STR_ALIEN_LIFE_FORMS: \"ИНОПЛАНЕТНЫЕ ФОРМЫ ЖИЗНИ\"\n  STR_ALIEN_RESEARCH_UC: \"ДЕЯТЕЛЬНОСТЬ ПРИШЕЛЬЦЕВ\"\n  STR_UFO_COMPONENTS: \"КОМПОНЕНТЫ НЛО\"\n  STR_UFOS: \"НЛО\"\n  STR_SELECT_ITEM: \"ВЫБЕРИТЕ СТАТЬЮ\"\n  STR_ACCELERATION: \"УСКОРЕНИЕ>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"ЗАПАС ТОПЛИВА>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"ТОЧЕК ПОДВЕСКИ ОРУЖИЯ>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"ЗАПАС ПРОЧНОСТИ>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"ОБЪЕМ ГРУЗОВОГО ОТСЕКА>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"КОЛИЧЕСТВО ТБП>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Урон\"\n  STR_RANGE: \"Дальность\"\n  STR_KILOMETERS: \"{0} км\"\n  STR_ACCURACY: \"Точность\"\n  STR_RE_LOAD_TIME: \"Время перезарядки\"\n  STR_SECONDS: \"{0}с\"\n  STR_DAMAGE_ARMOR_PIERCING: \"БРОНЕБОЙНЫЙ\"\n  STR_DAMAGE_INCENDIARY: \"ЗАЖИГАТЕЛЬНЫЙ\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"ФУГАСНЫЙ\"\n  STR_DAMAGE_LASER_BEAM: \"ЛАЗЕРНЫЙ ЛУЧ\"\n  STR_DAMAGE_PLASMA_BEAM: \"ПЛАЗМЕННЫЙ ЛУЧ\"\n  STR_DAMAGE_STUN: \"ОГЛУШЕНИЕ\"\n  STR_DAMAGE_MELEE: \"БЛИЖНИЙ БОЙ\"\n  STR_DAMAGE_ACID: \"КИСЛОТА\"\n  STR_DAMAGE_SMOKE: \"ДЫМ\"\n  STR_SHOT_TYPE: \"ТИП ВЫСТРЕЛА\"\n  STR_ACCURACY_UC: \"ТОЧНОСТЬ\"\n  STR_TIME_UNIT_COST: \"ЦЕНА ОД\"\n  STR_DAMAGE_UC: \"УРОН\"\n  STR_AMMO: \"БОЕЗАПАС\"\n  STR_SHOT_TYPE_AUTO: \"Очередь\"\n  STR_SHOT_TYPE_SNAP: \"Навскидку\"\n  STR_SHOT_TYPE_AIMED: \"Прицельный\"\n  STR_CONSTRUCTION_TIME: \"Время постройки\"\n  STR_CONSTRUCTION_COST: \"Стоимость постройки\"\n  STR_MAINTENANCE_COST: \"Стоимость содержания\"\n  STR_LOW: \"Низкий\"\n  STR_MEDIUM: \"Средний\"\n  STR_HIGH: \"Высокий\"\n  STR_CRAFT_WEAPON: \"Вооружение ТС\"\n  STR_CRAFT_AMMUNITION: \"Боеприпасы ТС\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Тяжелая боевая платформа\"\n  STR_WEAPON: \"Оружие\"\n  STR_AMMUNITION: \"Боеприпасы\"\n  STR_EQUIPMENT: \"Снаряжение\"\n  STR_ALIEN_CORPSE: \"Труп пришельца\"\n  STR_UFO_COMPONENT: \"Компонент НЛО\"\n  STR_PERSONAL_ARMOR: \"Бронекостюм\"\n  STR_RAW_MATERIALS: \"Исходные материалы\"\n  STR_HWP_CANNON_SHELLS: \"Пушечные снаряды ТБП\"\n  STR_ALIEN: \"Пришелец\"\n  STR_SECTOID: \"Сектоид\"\n  STR_SNAKEMAN: \"Человекозмей\"\n  STR_ETHEREAL: \"Эфириал\"\n  STR_MUTON: \"Мутон\"\n  STR_FLOATER: \"Летун\"\n  STR_CELATID: \"Целатид\"\n  STR_SILACOID: \"Силакоид\"\n  STR_CHRYSSALID: \"Криссалид\"\n  STR_ZOMBIE: \"Зомби\"\n  STR_REAPER: \"Жнец\"\n  STR_SECTOPOD: \"Сектопод\"\n  STR_CYBERDISC: \"Кибердиск\"\n  STR_LIVE_COMMANDER: \"Командующий\"\n  STR_LIVE_LEADER: \"Лидер\"\n  STR_LIVE_ENGINEER: \"Инженер\"\n  STR_LIVE_MEDIC: \"Медик\"\n  STR_LIVE_NAVIGATOR: \"Навигатор\"\n  STR_LIVE_SOLDIER: \"Солдат\"\n  STR_LIVE_TERRORIST: \"Террорист\"\n  STR_FLOATER_SOLDIER: \"Летун-солдат\"\n  STR_FLOATER_NAVIGATOR: \"Летун-навигатор\"\n  STR_FLOATER_MEDIC: \"Летун-медик\"\n  STR_FLOATER_ENGINEER: \"Летун-инженер\"\n  STR_FLOATER_LEADER: \"Летун-лидер\"\n  STR_FLOATER_COMMANDER: \"Летун-командующий\"\n  STR_SECTOID_SOLDIER: \"Сектоид-солдат\"\n  STR_SECTOID_NAVIGATOR: \"Сектоид-навигатор\"\n  STR_SECTOID_MEDIC: \"Сектоид-медик\"\n  STR_SECTOID_ENGINEER: \"Сектоид-инженер\"\n  STR_SECTOID_LEADER: \"Сектоид-лидер\"\n  STR_SECTOID_COMMANDER: \"Сектоид-командующий\"\n  STR_SNAKEMAN_SOLDIER: \"Человекозмей-солдат\"\n  STR_SNAKEMAN_NAVIGATOR: \"Человекозмей-навигатор\"\n  STR_SNAKEMAN_ENGINEER: \"Человекозмей-инженер\"\n  STR_SNAKEMAN_LEADER: \"Человекозмей-лидер\"\n  STR_SNAKEMAN_COMMANDER: \"Человекозмей-командующий\"\n  STR_MUTON_SOLDIER: \"Мутон-солдат\"\n  STR_MUTON_NAVIGATOR: \"Мутон-навигатор\"\n  STR_MUTON_ENGINEER: \"Мутон-инженер\"\n  STR_ETHEREAL_SOLDIER: \"Эфириал-солдат\"\n  STR_ETHEREAL_LEADER: \"Эфириал-лидер\"\n  STR_ETHEREAL_COMMANDER: \"Эфириал-командующий\"\n  STR_CYBERDISC_TERRORIST: \"Кибердиск-террорист\"\n  STR_REAPER_TERRORIST: \"Жнец-террорист\"\n  STR_CHRYSSALID_TERRORIST: \"Криссалид-террорист\"\n  STR_CELATID_TERRORIST: \"Целатид-террорист\"\n  STR_SILACOID_TERRORIST: \"Силакоид-террорист\"\n  STR_SECTOPOD_TERRORIST: \"Сектопод-террорист\"\n  STR_UFO_POWER_SOURCE: \"Источник энергии НЛО\"\n  STR_UFO_NAVIGATION: \"Навигационный блок НЛО\"\n  STR_UFO_CONSTRUCTION: \"Конструкция НЛО\"\n  STR_ALIEN_FOOD: \"Пища пришельцев\"\n  STR_ALIEN_REPRODUCTION: \"Инкубатор пришельцев\"\n  STR_ALIEN_ENTERTAINMENT: \"Развлечения пришельцев\"\n  STR_ALIEN_SURGERY: \"Хирургия пришельцев\"\n  STR_EXAMINATION_ROOM: \"Комната допроса\"\n  STR_ALIEN_ALLOYS: \"Сплавы пришельцев\"\n  STR_ALIEN_HABITAT: \"Среда обитания пришельцев\"\n  STR_POWER_SUIT: \"Энергоскафандр\"\n  STR_FLYING_SUIT: \"Летающий скафандр\"\n  STR_HWP_ROCKETS: \"Ракета ТБП\"\n  STR_HWP_FUSION_BOMB: \"Бластер-ракета ТБП\"\n  STR_LASER_WEAPONS: \"Лазерное оружие\"\n  STR_NEW_FIGHTER_CRAFT: \"Новый тактический боевой ЛА\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Новый транспортно-боевой ЛА\"\n  STR_ULTIMATE_CRAFT: \"Передовой корабль\"\n  STR_LASER_PISTOL: \"Лазерный пистолет\"\n  STR_LASER_RIFLE: \"Лазерная винтовка\"\n  STR_HEAVY_LASER: \"Тяжелый лазер\"\n  STR_LASER_CANNON: \"Лазерная авиапушка\"\n  STR_PLASMA_CANNON: \"Плазменная авиапушка\"\n  STR_FUSION_MISSILE: \"Бластерная ракета\"\n  STR_LASER_DEFENSE: \"Лазерная ПВО\"\n  STR_PLASMA_DEFENSE: \"Плазменная ПВО\"\n  STR_FUSION_DEFENSE: \"Бластерная ПВО\"\n  STR_GRAV_SHIELD: \"Гравитационный щит\"\n  STR_MIND_SHIELD: \"Ментальный щит\"\n  STR_PSI_LAB: \"Пси-лаборатория\"\n  STR_MOTION_SCANNER: \"Сканер движения\"\n  STR_MEDI_KIT: \"Медкомплект\"\n  STR_TANK_CANNON: \"Танк/Пушка\"\n  STR_TANK_ROCKET_LAUNCHER: \"Танк/Ракетная установка\"\n  STR_TANK_LASER_CANNON: \"Танк/Лазерная пушка\"\n  STR_HOVERTANK_PLASMA: \"Плазменный ховертанк\"\n  STR_HOVERTANK_LAUNCHER: \"Бластерный ховертанк\"\n  STR_STINGRAY_LAUNCHER: \"Пусковая установка \\\"Скат\\\"\"\n  STR_AVALANCHE_LAUNCHER: \"Пусковая установка \\\"Лавина\\\"\"\n  STR_CANNON: \"Авиапушка\"\n  STR_FUSION_BALL_LAUNCHER: \"Бластерная авиапушка\"\n  STR_PLASMA_BEAM: \"Плазменный луч\"\n  STR_STINGRAY_MISSILES: \"Ракета \\\"Скат\\\"\"\n  STR_AVALANCHE_MISSILES: \"Ракета \\\"Лавина\\\"\"\n  STR_CANNON_ROUNDS_X50: \"Снаряды к авиапушке (х50)\"\n  STR_FUSION_BALL: \"Бластерный снаряд\"\n  STR_SOLDIER: \"Боец\"\n  STR_SCIENTIST: \"Ученый\"\n  STR_ENGINEER: \"Инженер\"\n  STR_NORTH_AMERICA: \"Северная Америка\"\n  STR_ARCTIC: \"Арктика\"\n  STR_ANTARCTICA: \"Антарктика\"\n  STR_SOUTH_AMERICA: \"Южная Америка\"\n  STR_EUROPE: \"Европа\"\n  STR_NORTH_AFRICA: \"Северная Африка\"\n  STR_SOUTHERN_AFRICA: \"Южная Африка\"\n  STR_CENTRAL_ASIA: \"Центральная Азия\"\n  STR_SOUTH_EAST_ASIA: \"Юго-Вост. Азия\"\n  STR_SIBERIA: \"Сибирь\"\n  STR_AUSTRALASIA: \"Австралазия\"\n  STR_PACIFIC: \"Тихий океан\"\n  STR_NORTH_ATLANTIC: \"Сев. Атлантика\"\n  STR_SOUTH_ATLANTIC: \"Южная Атлантика\"\n  STR_INDIAN_OCEAN: \"Индийский океан\"\n  STR_ALIEN_RESEARCH: \"Исследование\"\n  STR_ALIEN_HARVEST: \"Жатва\"\n  STR_ALIEN_ABDUCTION: \"Похищения\"\n  STR_ALIEN_INFILTRATION: \"Инфильтрация\"\n  STR_ALIEN_BASE: \"База пришельцев\"\n  STR_ALIEN_TERROR: \"Террор\"\n  STR_ALIEN_RETALIATION: \"Ответный удар\"\n  STR_ALIEN_SUPPLY: \"Снабжение\"\n  STR_MAXIMUM_SPEED: \"Макс. скорость\"\n  STR_HYPER_WAVE_DECODER_UC: \"ГИПЕРВОЛНОВОЙ ДЕКОДЕР\"\n  STR_SKYRANGER: \"РЕЙНДЖЕР\"\n  STR_LIGHTNING: \"МОЛНИЯ\"\n  STR_AVENGER: \"МСТИТЕЛЬ\"\n  STR_INTERCEPTOR: \"ПЕРЕХВАТЧИК\"\n  STR_FIRESTORM: \"ОГНЕННЫЙ ШТОРМ\"\n  STR_UFO: \"НЛО\"\n  STR_STINGRAY: \"СКАТ\"\n  STR_AVALANCHE: \"ЛАВИНА\"\n  STR_CANNON_UC: \"АВИАПУШКА\"\n  STR_FUSION_BALL_UC: \"БЛАСТЕРНАЯ АВИАПУШКА\"\n  STR_LASER_CANNON_UC: \"ЛАЗЕРНАЯ АВИАПУШКА\"\n  STR_PLASMA_BEAM_UC: \"ПЛАЗМЕННЫЙ ЛУЧ\"\n  STR_DAMAGE_CAPACITY: \"Запас прочности\"\n  STR_WEAPON_POWER: \"Мощность оружия\"\n  STR_WEAPON_RANGE: \"Дальность оружия\"\n  STR_ACCESS_LIFT: \"Входной лифт\"\n  STR_LABORATORY: \"Лаборатория\"\n  STR_WORKSHOP: \"Мастерская\"\n  STR_SMALL_RADAR_SYSTEM: \"Ближний радар\"\n  STR_LARGE_RADAR_SYSTEM: \"Дальний радар\"\n  STR_MISSILE_DEFENSES: \"Ракетная ПВО\"\n  STR_GENERAL_STORES: \"Склад\"\n  STR_ALIEN_CONTAINMENT: \"Изолятор пришельцев\"\n  STR_LASER_DEFENSES: \"Лазерная ПВО\"\n  STR_PLASMA_DEFENSES: \"Плазменная ПВО\"\n  STR_FUSION_BALL_DEFENSES: \"Бластерная ПВО\"\n  STR_PSIONIC_LABORATORY: \"Пси-лаборатория\"\n  STR_HYPER_WAVE_DECODER: \"Гиперволновой декодер\"\n  STR_HANGAR: \"Ангар\"\n  STR_USA: \"США\"\n  STR_RUSSIA: \"РОССИЯ\"\n  STR_UK: \"ВЕЛИКОБРИТАНИЯ\"\n  STR_FRANCE: \"ФРАНЦИЯ\"\n  STR_GERMANY: \"ГЕРМАНИЯ\"\n  STR_ITALY: \"ИТАЛИЯ\"\n  STR_SPAIN: \"ИСПАНИЯ\"\n  STR_CHINA: \"КИТАЙ\"\n  STR_JAPAN: \"ЯПОНИЯ\"\n  STR_INDIA: \"ИНДИЯ\"\n  STR_BRAZIL: \"БРАЗИЛИЯ\"\n  STR_AUSTRALIA: \"АВСТРАЛИЯ\"\n  STR_NIGERIA: \"НИГЕРИЯ\"\n  STR_SOUTH_AFRICA: \"ЮЖНАЯ АФРИКА\"\n  STR_EGYPT: \"ЕГИПЕТ\"\n  STR_CANADA: \"КАНАДА\"\n  STR_TANK: \"Танк\"\n  STR_CIVILIAN: \"Гражданский\"\n  STR_JAN: \"янв\"\n  STR_FEB: \"фев\"\n  STR_MAR: \"мар\"\n  STR_APR: \"апр\"\n  STR_MAY: \"мая\"\n  STR_JUN: \"июн\"\n  STR_JUL: \"июл\"\n  STR_AUG: \"авг\"\n  STR_SEP: \"сен\"\n  STR_OCT: \"окт\"\n  STR_NOV: \"ноя\"\n  STR_DEC: \"дек\"\n  STR_INTERNATIONAL_RELATIONS: \"Международные отношения\"\n  STR_COUNTRY: \"Страна\"\n  STR_FUNDING: \"Инвестиции\"\n  STR_CHANGE: \"Изменение\"\n  STR_WEAPON_SYSTEMS: \"ОРУЖЕЙНЫЕ СИСТЕМЫ\"\n  STR_HWPS: \"ТБП\"\n  STR_DAMAGE_UC_: \"ПОВРЕЖДЕНИЯ>{ALT}{0}\"\n  STR_ACCESS_LIFT_UFOPEDIA: \"Входной лифт используется для доставки персонала и оборудования в подземную базу. Закладка новой базы начинается с постройки этого модуля. Лифт уязвим для проникновения потенциального противника.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Каждый жилой блок обеспечивает размещение до 50 человек. Содержит комнату отдыха, столовую и спальные помещения.\"\n  STR_LABORATORY_UFOPEDIA: \"В лабораторном модуле могут работать до 50 ученых. Лаборатории оснащены по последнему слову техники для проведения исследований в области материаловедения, биохимии и космологии. Сотрудникам обеспечен привилегированный доступ к лучшим исследовательским центрам мира, включая военные лаборатории.\"\n  STR_WORKSHOP_UFOPEDIA: \"Мастерская оборудована всем необходимым для производства снаряжения и техники. В каждой мастерской может одновременно работать до 50 инженеров. Производимое оборудование, как правило, занимает часть доступного места мастерской.\"\n  STR_SMALL_RADAR_SYSTEM_UFOPEDIA: \"Радарная система ближнего обнаружения имеет эффективный радиус действия 3140 километров и связана со спутниковыми системами для поиска наземных объектов. Каждые 30 минут система с вероятностью 10% в может обнаружить объект средних размеров.\"\n  STR_LARGE_RADAR_SYSTEM_UFOPEDIA: \"Радарная система ближнего обнаружения имеет эффективный радиус действия 4770 километров и связана со спутниковыми системами для поиска наземных объектов. Каждые 30 минут система с вероятностью 20% в может обнаружить объект средних размеров.\"\n  STR_MISSILE_DEFENSES_UFOPEDIA: \"Ракетная система ПВО обеспечивает защиту против летательных аппаратов, совершающих посадку вблизи базы.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"Все снаряжение, вооружения, боеприпасы, добытые в ходе заданий материалы и тяжелые боевые платформы размещаются на складах (включая снаряжение в грузовых отсеках транспортов, приписанных к ангарам базы).\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"Содержание пришельцев требует специальных условий для поддержания их жизнедеятельности. Изолятор позволяет безопасно содержать до 10 инопланетных организмов в отдельных боксах.\"\n  STR_LASER_DEFENSES_UFOPEDIA: \"Лазерная система противовоздушной обороны обеспечивает защиту от нападения враждебных летательных аппаратов.\"\n  STR_PLASMA_DEFENSES_UFOPEDIA: \"Плазменно-лучевая система противовоздушной обороны обеспечивает эффективную защиту от нападения враждебных летательных аппаратов.\"\n  STR_FUSION_BALL_DEFENSES_UFOPEDIA: \"Бластер-ракеты обеспечивают наиболее эффективную защиту против атак пришельцев. Выброс антиматерии при взрыве ракеты уничтожает все, что оказалось в радиусе поражения.\"\n  STR_GRAV_SHIELD_UFOPEDIA: \"Гравитационный щит отталкивает летательные аппараты противника при попытке сесть неподалеку от базы, позволяя средствам ПВО совершить повторный залп. На практике это означает удваивание эффективности систем ПВО.\"\n  STR_MIND_SHIELD_UFOPEDIA: \"Для обнаружения присутствия человека пришельцы полагаются на характерные волны, излучаемые его мозгом. Блокирующий эти волны экран может сильно понизить вероятность обнаружения базы противником.\"\n  STR_PSIONIC_LABORATORY_UFOPEDIA: \"Пси-лаборатория позволяет произвести оценку псионического потенциала бойцов, а также необходимое для развития пси-навыков обучение. Каждая лаборатория может тренировать до 10 человек одновременно, распределение обучающихся происходит в конце месяца. Для боевого применения псионических навыков необходимо снабдить бойцов пси-усилителями.\"\n  STR_HYPER_WAVE_DECODER_UFOPEDIA: \"Средства связи инопланетян основаны на использовании гиперпространственных волн, распространяющихся почти мгновенно. Декодер позволяет осуществить перехват и расшифровку переговоров НЛО. Возможно определение типа НЛО, его принадлежности определенной расе инопланетян и тип выполняемого им задания.\"\n  STR_HANGAR_UFOPEDIA: \"Ангар оснащен оборудованием для обслуживания, дозаправки и ремонта транспортных средств. Каждому аппарату, приписанному к базе, должен быть назначен свой ангар, который не может быть использован для размещения других ТС, даже если приписанное транспортное средство находится на задании.\"\n  STR_PISTOL_UFOPEDIA: \"Штатный полуавтоматический двенадцатизарядный пистолет X-Com.\"\n  STR_RIFLE_UFOPEDIA: \"Высокоточная штурмовая винтовка калибра 6,7 мм, снабженная лазерным прицелом. Стандартный магазин содержит 20 патронов.\"\n  STR_HEAVY_CANNON_UFOPEDIA: \"Тяжелая пушка - мощное, но громоздкое оружие. Возможно использование бронебойных, зажигательных и разрывных боеприпасов.\"\n  STR_AUTO_CANNON_UFOPEDIA: \"Автопушка - это результат удачного сочетания универсальности и мощности тяжелой пушки с функцией автоматического огня.\"\n  STR_ROCKET_LAUNCHER_UFOPEDIA: \"Пусковая ракетная установка с лазерной системой наведения. Заряжается тремя видами ракет.\"\n  STR_LASER_PISTOL_UFOPEDIA: \"Лазерный пистолет - эффективная реализация новой технологии. Он совмещает удобство стандартного пистолета с повышенной скорострельностью и точностью.\"\n  STR_LASER_RIFLE_UFOPEDIA: \"Лазерная винтовка - более мощное и точное оружие, основанное на разработках проекта лазерного пистолета.\"\n  STR_HEAVY_LASER_UFOPEDIA: \"Тяжелый лазер - громоздкое, но крайне эффективное оружие.\"\n  STR_GRENADE_UFOPEDIA: \"Эта стандартная наступательная граната имеет сложный и точный таймер, который позволяет устанавливать задержку перед взрывом.\"\n  STR_SMOKE_GRENADE_UFOPEDIA: \"Дымовые гранаты применяются для обеспечения прикрытия в сложных боевых ситуациях. Проявляйте осмотрительность, поскольку враг также может воспользоваться низкой видимостью в дыму.\"\n  STR_PROXIMITY_GRENADE_UFOPEDIA: \"Сенсорную гранату бросают так же, как и обычную, но взрыв происходит, если в ближайшем радиусе было движение. Правильное применение требует особой осторожности.\"\n  STR_HIGH_EXPLOSIVE_UFOPEDIA: \"Заряд взрывчатки, используемый для разрушения объектов. Эвакуируйте персонал от места взрыва.\"\n  STR_MOTION_SCANNER_UFOPEDIA: \"Это сложное устройство использует мощные алгоритмы обработки данных, поступающих с различных анализаторов, для обнаружения движущихся объектов. Однако требуется некоторая практика для его эффективного использования. Нажмите на иконку сканера движения на тактическом экране. Выберите пункт 'Сканировать'. Стрелка на экране устройства отображает направление взгляда использующего сканер бойца (север расположен наверху). Движущиеся объекты отображаются мигающими пятнами, большие пятна соответствуют быстро движущимся или крупным объектам. Неподвижные объекты сканером не детектируются.\"\n  STR_MEDI_KIT_UFOPEDIA: \"Медкомплект содержит как лечебные средства, так и обезб. и стимуляторы. Чтобы применить медкомплект, встаньте лицом к бойцу, которому необходимо лечение. Если он без сознания, необходимо встать над его телом. Нажмите на иконку и выберите пункт меню «Использовать медкомплект».{NEWLINE}ЛЕЧЕНИЕ> Красным отображаются части тела со смертельными ранениями. Нажмите на кнопку «Лечение». Будет излечено одно смертельное ранение, и немного восстановится здоровье.{NEWLINE}СТИМУЛЯТОР> Восстанавливает энергию и приводит в сознание оглушенных бойцов. Чтобы привести в сознание оглушенного, необходимо встать непосредственно над его телом.{NEWLINE}ОБЕЗБОЛИВАЮЩЕЕ> Восстанавливает мораль раненых бойцов. Количество восстанавливаемых очков морали равно количеству потерянных бойцом ОЗ.\"\n  STR_PSI_AMP_UFOPEDIA: \"Пси-усилитель могут использовать только бойцы с псионическим способностями. Во время боя нажмите на пси-усилитель, выберите тип атаки и укажите цель курсором мыши. Вы можете выбрать одну из двух пси-атак:{NEWLINE}ВЫЗВАТЬ ПАНИКУ> В случае если атака окажется успешной, мораль цели снизится, что может вызвать у нее панику.{NEWLINE}КОНТРОЛЬ НАД РАЗУМОМ> Если эта атака успешна, вы немедленно получите полный непосредственный контроль над боевой единицей противника. Вероятность успешного осуществления этой атаки ниже.\"\n  STR_STUN_ROD_UFOPEDIA: \"Это устройство может использоваться только в ближнем бою, но воздействие создаваемого им электрического разряда оглушит живой организм, не убив его.\"\n  STR_MIND_PROBE_UFOPEDIA: \"Ментальный зонд - используемое пришельцами средство связи, позволяющее извлекать информацию из волн, излучаемых мозгом. Может быть применено для определения характеристик противника. Для использования наведите зонд на противника.\"\n  STR_PLASMA_PISTOL_UFOPEDIA: \"Плазменные пистолеты - смертоносное оружие пришельцев, в котором частицы ускоряются сверхмалым гравитационным полем.\"\n  STR_PLASMA_RIFLE_UFOPEDIA: \"Смертоносное оружие пришельцев чудовищной силы, в котором частицы ускоряются сверхмалым гравитационным полем.\"\n  STR_HEAVY_PLASMA_UFOPEDIA: \"Смертоносное оружие пришельцев чудовищной силы, в котором частицы ускоряются сверхмалым гравитационным полем.\"\n  STR_BLASTER_LAUNCHER_UFOPEDIA: \"Эта пусковая установка пришельцев стреляет мощными управляемыми \\\"бластерными ракетами\\\". Траектория, по которой будет следовать ракета, задается непосредственно перед выстрелом. После задания траектории нажмите специальную кнопку пуска ракеты.\"\n  STR_SMALL_LAUNCHER_UFOPEDIA: \"Небольшая пусковая установка, стреляющая парализующими снарядами. Весьма полезна для захвата живых инопланетян.\"\n  STR_ALIEN_GRENADE_UFOPEDIA: \"Принцип действия этого устройства тот же, что у земных гранат, однако его мощность выше.\"\n  STR_SMALL_SCOUT: \"Легкий разведчик\"\n  STR_MEDIUM_SCOUT: \"Средний разведчик\"\n  STR_LARGE_SCOUT: \"Большой разведчик\"\n  STR_HARVESTER: \"Жнец\"\n  STR_ABDUCTOR: \"Похититель\"\n  STR_TERROR_SHIP: \"Корабль террора\"\n  STR_BATTLESHIP: \"Линкор\"\n  STR_SUPPLY_SHIP: \"Корабль снабжения\"\n  STR_RATING: \"РЕЙТИНГ> {0}\"\n  STR_RATING_TERRIBLE: \"УЖАСНО!\"\n  STR_RATING_POOR: \"ПЛОХО!\"\n  STR_RATING_OK: \"ОК\"\n  STR_RATING_GOOD: \"ХОРОШО!\"\n  STR_RATING_EXCELLENT: \"ПРЕВОСХОДНО!\"\n  STR_SCORE: \"СЧЕТ\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"ОТЧЕТ ПРОЕКТА X-COM ЗА МЕСЯЦ\"\n  STR_MONTH: \"Месяц> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"Совет финансирующих государств в целом доволен вашим текущим прогрессом.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"Совет финансирующих государств очень доволен вашими действиями. Продолжайте в том же духе.\"\n  STR_COUNCIL_IS_DISSATISFIED: \"Совет финансирующих государств не удовлетворен вашими результатами. Вы должны улучшить эффективность противодействия инопланетной угрозе, иначе проект будет прекращен.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"Вы не преуспели в борьбе с вторжением пришельцев и совет финансирующих государств с сожалением принял решение о закрытии проекта. Каждое государство будет отныне решать эту проблему по своему усмотрению. Мы можем только надеяться, что придем к некоторому соглашению с явно враждебными силами, и что общество примет условия, предложенные пришельцами.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} выражает глубокое удовлетворение проведенной вами работой и соглашается увеличить финансирование.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} особенно довольны вашими успехами при отражении нападений пришельцев и договорились увеличить финансирование.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} и {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} выражает неудовлетворенность мерами, предпринятыми вами для пресечения активности пришельцев на своей территории, и сокращает финансирование.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} не удовлетворены мерами, предпринятыми вами для пресечения активности пришельцев на их территории, и решили сократить финансирование.\"\n  STR_KNOTS: \"{0} узлов\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} сообщает о подписании секретного пакта с силами пришельцев и выходит из проекта.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} подписали секретный пакт с силами пришельцев и вышли из проекта.\"\n  STR_MONTHLY_RATING: \"Рейтинг за месяц> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Изменение в финансировании> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"Финансирующий совет недоволен вашим финансовым состоянием. Вы должны сократить долги до 1 миллиона долларов, или проект будет закрыт.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"ГИПЕРВОЛНОВАЯ ПЕРЕДАЧА ДЕКОДИРОВАНА\"\n  STR_CRAFT_TYPE: \"ТИП ТС\"\n  STR_RACE: \"РАСА\"\n  STR_MISSION: \"МИССИЯ\"\n  STR_ZONE: \"РЕГИОН\"\n  STR_ALLOCATE_RESEARCH: \"Новое исследование\"\n  STR_ALLOCATE_MANUFACTURE: \"Произвести\"\n  STR_NEW_YORK: \"Нью-Йорк\"\n  STR_WASHINGTON: \"Вашингтон\"\n  STR_LOS_ANGELES: \"Лос-Анджелес\"\n  STR_MONTREAL: \"Монреаль\"\n  STR_HAVANA: \"Гавана\"\n  STR_MEXICO_CITY: \"Мехико\"\n  STR_CHICAGO: \"Чикаго\"\n  STR_VANCOUVER: \"Ванкувер\"\n  STR_DALLAS: \"Даллас\"\n  STR_BRASILIA: \"Бразилиа\"\n  STR_BOGOTA: \"Богота\"\n  STR_BUENOS_AIRES: \"Буэнос-Айрес\"\n  STR_SANTIAGO: \"Сантьяго\"\n  STR_RIO_DE_JANEIRO: \"Рио-де-Жанейро\"\n  STR_LIMA: \"Лима\"\n  STR_CARACAS: \"Каракас\"\n  STR_LONDON: \"Лондон\"\n  STR_PARIS: \"Париж\"\n  STR_BERLIN: \"Берлин\"\n  STR_MOSCOW: \"Москва\"\n  STR_ROME: \"Рим\"\n  STR_MADRID: \"Мадрид\"\n  STR_BUDAPEST: \"Будапешт\"\n  STR_LAGOS: \"Лагос\"\n  STR_CAIRO: \"Каир\"\n  STR_CASABLANCA: \"Касабланка\"\n  STR_PRETORIA: \"Претория\"\n  STR_NAIROBI: \"Найроби\"\n  STR_CAPE_TOWN: \"Кейптаун\"\n  STR_KINSHASA: \"Киншаса\"\n  STR_ANKARA: \"Анкара\"\n  STR_DELHI: \"Дели\"\n  STR_KARACHI: \"Карачи\"\n  STR_BAGHDAD: \"Багдад\"\n  STR_TEHRAN: \"Тегеран\"\n  STR_BOMBAY: \"Бомбей\"\n  STR_CALCUTTA: \"Калькутта\"\n  STR_TOKYO: \"Токио\"\n  STR_BEIJING: \"Пекин\"\n  STR_BANGKOK: \"Бангкок\"\n  STR_MANILA: \"Манила\"\n  STR_SEOUL: \"Сеул\"\n  STR_SINGAPORE: \"Сингапур\"\n  STR_JAKARTA: \"Джакарта\"\n  STR_SHANGHAI: \"Шанхай\"\n  STR_HONG_KONG: \"Гонконг\"\n  STR_NOVOSIBIRSK: \"Новосибирск\"\n  STR_CANBERRA: \"Канберра\"\n  STR_WELLINGTON: \"Веллингтон\"\n  STR_MELBOURNE: \"Мельбурн\"\n  STR_PERTH: \"Перт\"\n  STR_PSI_TRAINING: \"Пси-тренировка\"\n  STR_PSIONIC_TRAINING: \"ПСИ-ТРЕНИРОВКА\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Мест в пси-лаборатории>{ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"Псионическая{NEWLINE}сила\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"Пси-навыки{NEWLINE}/Улучшение\"\n  STR_PSI_AMP: \"Пси-усилитель\"\n  STR_IN_TRAINING: \"Тренир.?\"\n  STR_TARGETTED_BY: \"ЦЕЛЬ ДЛЯ:\"\n  STR_WEAPONS_CREW_HWPS: \"ОРУЖИЕ/{NEWLINE}ЭКИПАЖ/БП\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \" Топливо на исходе,{NEWLINE}возвращаюсь на базу\"\n  STR_SOLDIER_LIST: \"Список бойцов\"\n  STR_RANK_: \"ЗВАНИЕ> {ALT}{0}\"\n  STR_MISSIONS: \"МИССИЙ> {ALT}{0}\"\n  STR_KILLS: \"УБИЙСТВ> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"ЛЕЧЕНИЕ> {ALT}{0}\"\n  STR_TIME_UNITS: \"ОЧКИ ДЕЙСТВИЯ\"\n  STR_STAMINA: \"ВЫНОСЛИВОСТЬ\"\n  STR_HEALTH: \"ЗДОРОВЬЕ\"\n  STR_BRAVERY: \"ХРАБРОСТЬ\"\n  STR_REACTIONS: \"РЕАКЦИЯ\"\n  STR_FIRING_ACCURACY: \"ТОЧНОСТЬ ВЫСТРЕЛА\"\n  STR_THROWING_ACCURACY: \"ТОЧНОСТЬ БРОСКА\"\n  STR_STRENGTH: \"СИЛА\"\n  STR_PSIONIC_STRENGTH: \"ПСИОНИЧЕСКАЯ СИЛА\"\n  STR_PSIONIC_SKILL: \"ПСИОНИЧЕСКИЙ НАВЫК\"\n  STR_NEW_RANK: \"НОВОЕ ЗВАНИЕ\"\n  STR_PROMOTIONS: \"Повышение\"\n  STR_SOLDIERS_UC: \"БОЙЦЫ\"\n  STR_TANK_CANNON_UFOPEDIA: \"Автоматизированные тяжелые боевые платформы (ТБП) были разработаны для усиления подразделений X-Com. Сочетание высокой огневой мощи и мощной брони делает их незаменимыми в бою на открытой местности. Следите за наличием на складах достаточного количества боеприпасов для ТБП. Пополнение боекомплекта ТБП происходит автоматически при их назначении в подразделение.\"\n  STR_TANK_ROCKET_LAUNCHER_UFOPEDIA: \"Эта автоматическая тяжелая боевая платформа вооружена мощными ракетами. Они разрушительны для любого инопланетного врага. Следите за поддержанием на складах достаточного запаса ракет для ТБП.\"\n  STR_TANK_LASER_CANNON_UFOPEDIA: \"Боевой лазер - полезное усовершенствование для ТБП. Он наносит сильные повреждения, не требуя при этом боеприпасов.\"\n  STR_HOVERTANK_PLASMA_UFOPEDIA: \"Технологии пришельцев обеспечили ТБП принципиально новыми возможностями. Лучшая маневренность за счет парения в воздухе и мощь плазменного оружия делают эти летающие танки по-настоящему смертоносными в бою.\"\n  STR_HOVERTANK_LAUNCHER_UFOPEDIA: \"Этот парящий танк оснащен бластерной пусковой установкой огромной мощности. Используйте его с большой осторожностью. Для полного снаряжения этого ТБП необходимо производить бластерные ракеты. Бластерные ракеты - высокоточное управляемое оружие, позволяющее задать перед выстрелом траекторию движения снаряда.\"\n  STR_HEAVY_PLASMA_CLIP_UFOPEDIA: \"Источник энергии для тяжелой плазменной пушки. Содержит небольшое количество элерия.\"\n  STR_PLASMA_RIFLE_CLIP_UFOPEDIA: \"Источник энергии для плазменной винтовки - оружия пришельцев средней мощности. Содержит небольшое количество элерия.\"\n  STR_PLASMA_PISTOL_CLIP_UFOPEDIA: \"Источник энергии для небольшого плазменного пистолета. Содержит небольшое количество элерия - основы всей технологической мощи пришельцев.\"\n  STR_STUN_BOMB_UFOPEDIA: \"Парализующая бомба применяется пришельцами для захвата живых людей, но может использоваться и против большинства видов пришельцев. Используется как боеприпас для парализатора.\"\n  STR_ALIEN_RESEARCH_UFOPEDIA: \"Целью исследовательских миссий пришельцев является сбор данных о Земле и ее жителях. Используются преимущественно легкие корабли для высадки в заброшенных областях. Этот тип активности пришельцев представляет наименьшую опасность для Х-Сom, и меньше всего беспокоит правительства и общественность.\"\n  STR_ALIEN_HARVEST_UFOPEDIA: \"Пришельцы широко используют земную фауну в своих целях. Животные тайно похищаются и возвращаются после извлечения различных органов. О случаях увечья животных часто сообщается из мест наблюдения НЛО. Этот тип деятельности пришельцев вызывает большую обеспокоенность у правительств и тревогу среди населения. Чаще всего данная активность проявляется в сельской местности. Существует теория \\\"сбора урожая\\\", согласно которой инопланетяне в прошлом заселили планету образцами своей флоры и фауны и теперь вернулись, чтобы собрать \\\"урожай\\\".\"\n  STR_ALIEN_ABDUCTION_UFOPEDIA: \"Наиболее коварный вид инопланетной активности. Случаи похищения людей инопланетянами широко известны, несмотря на попытки пришельцев стирать воспоминания о происшедшем из памяти жертв. Похищенные сообщают о проводившихся над ними физиологических опытах, включая имплантацию зародышей инопланетных организмов и генетические эксперименты. Преследуемая пришельцами цель, вероятно, имеет отношение к мутациям и манипулированию их собственным генетическим материалом. Эти вызывающие большую тревогу инциденты происходят обычно в городах или густонаселенных районах.\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"В правительства могут быть внедрены агенты пришельцев, внешне неотличимые от людей. В результате между пришельцами и правительствами могут установиться официальные контакты на самом высоком уровне. Чем ближе этот момент, тем выше активность НЛО вблизи крупных городов. Пришельцы попытаются подписать пакт с земным правительством, предлагая передачу своих технологий в обмен на возможность беспрепятственно действовать на территории страны. Эта деятельность пришельцев представляет самую большую угрозу для X-Com. Если правительство подпишет пакт, финансирование со стороны возглавляемой им страны будет прекращено.\"\n  STR_ALIEN_BASE_UFOPEDIA: \"Пришельцы будут создавать скрытые подземные базы в удаленных районах. После периода разведывательных полетов будет отмечаться высокая активность НЛО в месте строительства базы. На базах размещаются экспериментальные лаборатории для изучения людей, а также средства обеспечения дальнейшей деятельности инопланетян в регионе. Присутствие базы будет сопровождаться большим количеством сообщений о действиях пришельцев при относительно малом числе случаев наблюдения НЛО. Чтобы обнаружить базу, корабль X-Com должен патрулировать область в течение нескольких часов.\"\n  STR_ALIEN_TERROR_UFOPEDIA: \"Для террора городов пришельцы используют специализированные тяжелые отряды. Ввиду наличия непосредственной угрозы гражданскому населению, правительство вынуждено эвакуировать целые районы. Основная цель этих действий - вызвать панику среди населения, и оказать давление на проект X-Com со стороны правительства страны.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"В случае особо успешных действий перехватчиков X-Com, пришельцы будут предпринимать ответные меры, вплоть до прямой атаки баз X-Com. Однако перед атакой пришельцы сперва должны обнаружить базу, поэтому риск можно существенно снизить, если не подпускать НЛО к базе.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"Построенную базу пришельцев регулярно снабжают специальные транспортные суда. Недалеко от того места, где приземлилось подобное судно, можно с большой вероятностью обнаружить базу пришельцев.\"\n  STR_SMALL_SCOUT_UFOPEDIA: \"Этот крошечный корабль используется для разведки или исследований. Его полеты обычно предшествуют более крупным кораблям в начале акций.\"\n  STR_MEDIUM_SCOUT_UFOPEDIA: \"Средний по размеру разведывательный корабль, не представляющий большой опасности. Обычно появляется перед более крупными кораблями в ходе акции.\"\n  STR_LARGE_SCOUT_UFOPEDIA: \"Самый большой разведывательный корабль пришельцев представляет собой корабль общего назначения, использующийся для выполнения любых задач.\"\n  STR_HARVESTER_UFOPEDIA: \"Сборщик имеет люк в нижней части корпуса и оборудован подъемным механизмом для рогатого скота и других животных. Необходимый биоматериал извлекается с использованием \\\"лазерных скальпелей\\\", после чего туша сбрасывается на землю. Имеются также контейнеры для хранения добытых органов.\"\n  STR_ABDUCTOR_UFOPEDIA: \"Этот корабль оборудован комнатой для проведения допросов и ужасных экспериментов над людьми. Обычно жертва телепатически парализуется, но остается в сознании на операционном столе.\"\n  STR_TERROR_SHIP_UFOPEDIA: \"Корабль террора имеет отсеки-контейнеры для перевозки крупных существ или техники отрядов устрашения. Он используется для доставки инопланетных террористов в населенные районы.\"\n  STR_BATTLESHIP_UFOPEDIA: \"Линкор - самый большой и наиболее мощный корабль пришельцев. Является основным боевым кораблем в любой миссии, несет на борту мощное оружие и многочисленный экипаж.\"\n  STR_SUPPLY_SHIP_UFOPEDIA: \"Корабль поддержки используется при строительстве баз пришельцев или для снабжения уже существующих. Перевозит контейнеры с пищей и репродукционные камеры.\"\n  STR_DISMANTLE: \"Демонтировать\"\n  STR_FACILITY_IN_USE: \"МОДУЛЬ ИСПОЛЬЗУЕТСЯ\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"НЕВОЗМОЖНО ДЕМОНТИРОВАТЬ МОДУЛЬ!{SMALLLINE}Все модули должны быть соединены с входным лифтом.\"\n  STR_TRANSFER_ITEMS_TO: \"Перевозка на базу {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"НЕТ ИЗОЛЯТОРА ПРИШЕЛЬЦЕВ ДЛЯ ПЕРЕДАЧИ!{SMALLLINE}Для содержания живых пришельцев необходим специальный модуль.\"\n  STR_AMOUNT_AT_DESTINATION: \"НА МЕСТЕ {NEWLINE}НАЗНАЧЕНИЯ\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"Пришелец погиб, так как нет модуля для его содержания.\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"НЕ ХВАТАЕТ МЕСТ!{SMALLLINE}На базе назначения не хватает мест в жилых модулях для экипажа, назначенного на корабль.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"НЕДОСТАТОЧНО МЕСТА НА СКЛАДЕ!{SMALLLINE}На складе базы назначения не хватает места для снаряжения, назначенного ТС.\"\n  STR_ITEMS_ARRIVING: \"Прибытие\"\n  STR_DESTINATION_UC: \"ПУНКТ НАЗНАЧЕНИЯ\"\n  STR_PISTOL: \"Пистолет\"\n  STR_PISTOL_CLIP: \"Магазин к пистолету\"\n  STR_RIFLE: \"Винтовка\"\n  STR_RIFLE_CLIP: \"Магазин к винтовке\"\n  STR_HEAVY_CANNON: \"Тяжелая пушка\"\n  STR_HC_AP_AMMO: \"ТП-ББ магазин\"\n  STR_HC_HE_AMMO: \"ТП-Р магазин\"\n  STR_HC_I_AMMO: \"ТП-З магазин\"\n  STR_AUTO_CANNON: \"Автопушка\"\n  STR_AC_AP_AMMO: \"АП-ББ магазин\"\n  STR_AC_HE_AMMO: \"АП-Р магазин\"\n  STR_AC_I_AMMO: \"АП-З магазин\"\n  STR_ROCKET_LAUNCHER: \"Ракетная установка\"\n  STR_SMALL_ROCKET: \"Легкая ракета\"\n  STR_LARGE_ROCKET: \"Тяжелая ракета\"\n  STR_INCENDIARY_ROCKET: \"Зажигательная ракета\"\n  STR_GRENADE: \"Граната\"\n  STR_SMOKE_GRENADE: \"Дымовая граната\"\n  STR_PROXIMITY_GRENADE: \"Сенсорная граната\"\n  STR_HIGH_EXPLOSIVE: \"Взрывчатка\"\n  STR_STUN_ROD: \"Электрошоковая дубинка\"\n  STR_HEAVY_PLASMA: \"Тяжелая плазма\"\n  STR_HEAVY_PLASMA_CLIP: \"Батарея тяж. плазмы\"\n  STR_PLASMA_RIFLE: \"Плазменная винтовка\"\n  STR_PLASMA_RIFLE_CLIP: \"Батарея плазм. винтовки\"\n  STR_PLASMA_PISTOL: \"Плазменный пистолет\"\n  STR_PLASMA_PISTOL_CLIP: \"Батарея плазм. пистолета\"\n  STR_BLASTER_LAUNCHER: \"Бластерная установка\"\n  STR_BLASTER_BOMB: \"Бластерная ракета\"\n  STR_SMALL_LAUNCHER: \"Парализующая установка\"\n  STR_STUN_BOMB: \"Парализующая бомба\"\n  STR_ALIEN_GRENADE: \"Граната пришельцев\"\n  STR_ELERIUM_115: \"Элерий-115\"\n  STR_MIND_PROBE: \"Ментальный зонд\"\n  STR_SECTOID_CORPSE: \"Труп сектоида\"\n  STR_SNAKEMAN_CORPSE: \"Труп человекозмея\"\n  STR_ETHEREAL_CORPSE: \"Труп эфириала\"\n  STR_MUTON_CORPSE: \"Труп мутона\"\n  STR_FLOATER_CORPSE: \"Труп летуна\"\n  STR_CELATID_CORPSE: \"Труп целатида\"\n  STR_SILACOID_CORPSE: \"Труп силакоида\"\n  STR_CHRYSSALID_CORPSE: \"Труп криссалида\"\n  STR_REAPER_CORPSE: \"Труп жнеца\"\n  STR_SECTOPOD_CORPSE: \"Останки сектопода\"\n  STR_CYBERDISC_CORPSE: \"Останки кибердиска\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"Недостаточно боеприпасов для вооружения ТБП{SMALLLINE}Погрузите {1} ({0} шт.) для доукомплектования ТБП.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Недостаточно снаряжения для экипировки подразделения\"\n  STR_MARS_CYDONIA_LANDING: \"Марс: Высадка в Кидонии\"\n  STR_MARS_CYDONIA_LANDING_BRIEFING: \"«Мститель» сел на поверхность Марса в районе Кидонии. По нашей информации, в одной из пирамидальных структур находится спуск в подземный комплекс. Соберите подразделение в лифте (зеленая зона) и нажмите кнопку «Покинуть поле боя» для перехода к следующему этапу штурма.\"\n  STR_MARS_THE_FINAL_ASSAULT: \"Марс: Последняя битва\"\n  STR_MARS_THE_FINAL_ASSAULT_BRIEFING: \"Лифт пирамиды доставил отряд глубоко под поверхность планеты, в сердце лабиринта туннелей. Где-то там скрыт инопланетный Мозг. Он должен быть уничтожен, чтобы спасти Землю от нашествия инопланетян.{NEWLINE}{NEWLINE}Удачи!\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Необходимо исследовать{NEWLINE}{0},{NEWLINE}чтобы производить{NEWLINE}{1}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"Незащищенная база {0} разрушена пришельцами\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"Агенты X-Com обнаружили базу пришельцев. Место: {0}\"\n  STR_STANDOFF: \"ОЖИДАНИЕ\"\n  STR_CAUTIOUS_ATTACK: \"ОСТОРОЖНАЯ АТАКА\"\n  STR_STANDARD_ATTACK: \"СТАНДАРТНАЯ АТАКА\"\n  STR_AGGRESSIVE_ATTACK: \"АГРЕССИВНАЯ АТАКА\"\n  STR_DISENGAGING: \"ВЫХОД ИЗ БОЯ\"\n  STR_UFO_HIT: \"ПОПАДАНИЕ!\"\n  STR_UFO_CRASH_LANDS: \"НЛО СБИТ!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Минимизировать только на безопасной дистанции\"\n  STR_UFO_RETURN_FIRE: \"НЛО СТРЕЛЯЕТ!\"\n  STR_INTERCEPTOR_DAMAGED: \">>> ПЕРЕХВАТЧИК ПОВРЕЖДЕН <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> ПЕРЕХВАТЧИК УНИЧТОЖЕН <<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"НЛО УШЕЛ ОТ ПЕРЕХВАТЧИКА!\"\n  STR_ALIENS_TERRORISE: \"ПРИШЕЛЬЦЫ ТЕРРОРИЗИРУЮТ\"\n  STR_LONG_RANGE_DETECTION: \"Дальнее обнаружение\"\n  STR_STORES_UC: \"СКЛАД\"\n  STR_DIFFICULTY_LEVEL: \"Уровень сложности\"\n  STR_INTERCEPT: \"ПЕРЕХВАТ\"\n  STR_BASES: \"БАЗЫ\"\n  STR_GRAPHS: \"ГРАФИКИ\"\n  STR_UFOPAEDIA_UC: \"УФОПЕДИЯ\"\n  STR_OPTIONS_UC: \"НАСТРОЙКИ\"\n  STR_FUNDING_UC: \"ФИНАНСЫ\"\n  STR_5_SECONDS: \"5 сек\"\n  STR_1_MINUTE: \"1 мин\"\n  STR_5_MINUTES: \"5 мин\"\n  STR_30_MINUTES: \"30 мин\"\n  STR_1_HOUR: \"1 час\"\n  STR_1_DAY: \"1 день\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"Выполнение заданий X-Com\"\n  STR_ENTER_NAME: \"Введите имя\"\n  STR_PERFORMANCE_RATING: \"Оценка выполнения\"\n  STR_VICTORY_DATE: \"День Победы\"\n  STR_ELECTRO_FLARE: \"Осветитель\"\n  STR_ELECTRO_FLARE_UFOPEDIA: \"Оказавшись на земле, это компактное устройство начинает излучать мощный световой поток, что позволяет осветить противника, находящегося вблизи от осветителя, во время ночных заданий.\"\n  STR_MONTHLY_COSTS: \"МЕСЯЧНЫЕ ЗАТРАТЫ\"\n  STR_CRAFT_RENTAL: \"Аренда ТС\"\n  STR_SALARIES: \"Жалованье\"\n  STR_BASE_MAINTENANCE: \"Обслуживание базы\"\n  STR_COST_PER_UNIT: \"Стоимость за ед.\"\n  STR_QUANTITY: \"Кол-во\"\n  STR_TOTAL: \"Всего\"\n  STR_IN_PSIONIC_TRAINING: \"Тренируется в пси-лаборатории\"\n  STR_BLASTER_BOMB_UFOPEDIA: \"Это устройство представляет собой ракету, снабженную фугасным зарядом и оснащенную умной системой наведения. Предназначено для стрельбы из бластерной пусковой установки.\"\n  STR_FRONT_ARMOR: \"Броня спереди\"\n  STR_LEFT_ARMOR: \"Броня слева\"\n  STR_RIGHT_ARMOR: \"Броня справа\"\n  STR_REAR_ARMOR: \"Броня сзади\"\n  STR_UNDER_ARMOR: \"Броня снизу\"\n  STR_ROUNDS: \"Боезапас\"\n  STR_UNIT: \"БОЕЦ> {0}\"\n  STR_ENERGY: \"ЭНЕРГИЯ\"\n  STR_MORALE: \"МОРАЛЬ\"\n  STR_ARMOR_: \"БРОНЯ> {0}\"\n  STR_FRONT_ARMOR_UC: \"БРОНЯ СПЕРЕДИ\"\n  STR_LEFT_ARMOR_UC: \"БРОНЯ СЛЕВА\"\n  STR_RIGHT_ARMOR_UC: \"БРОНЯ СПРАВА\"\n  STR_REAR_ARMOR_UC: \"БРОНЯ СЗАДИ\"\n  STR_SKILLS: \"НАВЫКИ> {0}\"\n  STR_LEVEL: \"УРОВЕНЬ> {0}\"\n  STR_HEAD: \"ГОЛОВА\"\n  STR_TORSO: \"ТОРС\"\n  STR_RIGHT_ARM: \"ПРАВАЯ РУКА\"\n  STR_LEFT_ARM: \"ЛЕВАЯ РУКА\"\n  STR_RIGHT_LEG: \"ПРАВАЯ НОГА\"\n  STR_LEFT_LEG: \"ЛЕВАЯ НОГА\"\n  STR_PAIN_KILLER: \"АНАЛЬГЕТИК\"\n  STR_STIMULANT: \"СТИМУЛЯТОР\"\n  STR_HEAL: \"ЛЕЧИТЬ\"\n  STR_TIME_UNITS_SHORT: \"ОД>{ALT}{0}\"\n  STR_WEIGHT: \"Вес>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"Реакц>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"П.Нав>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"П.Cила>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Артефакт пришельцев\"\n  STR_AMMO_ROUNDS_LEFT: \"ОРУЖИЕ:{NEWLINE}ИМЕЮЩИЙСЯ{NEWLINE}БОЕЗАПАС={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Болеут>{ALT}{0}{ALT}{NEWLINE}Стим>{ALT}{1}{ALT}{NEWLINE}Леч>{ALT}{2}\"\n  STR_THROW: \"Бросить\"\n  STR_AUTO_SHOT: \"Очередь\"\n  STR_SNAP_SHOT: \"Навскидку\"\n  STR_AIMED_SHOT: \"Прицельный\"\n  STR_STUN: \"Парализовать\"\n  STR_PRIME_GRENADE: \"Взвести гранату\"\n  STR_USE_SCANNER: \"Сканировать\"\n  STR_USE_MEDI_KIT: \"Использовать\"\n  STR_LAUNCH_MISSILE: \"Пуск ракеты\"\n  STR_ACCURACY_SHORT: \"Точ>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Не хватает очков действия!\"\n  STR_NOT_ENOUGH_ENERGY: \"Не хватает энергии!\"\n  STR_NO_ROUNDS_LEFT: \"Кончились боеприпасы!\"\n  STR_NO_AMMUNITION_LOADED: \"Оружие не заряжено!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Боеприпасы не от этого оружия!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"Оружие уже заряжено!\"\n  STR_NO_LINE_OF_FIRE: \"Нет линии огня!\"\n  STR_GRENADE_IS_ACTIVATED: \"Граната активирована!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Граната деактивирована!\"\n  STR_THERE_IS_NO_ONE_THERE: \"Там никого нет!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Невозможно использовать неисследованный артефакт!\"\n  STR_OUT_OF_RANGE: \"Вне зоны поражения!\"\n  STR_UNABLE_TO_THROW_HERE: \"Не могу бросить сюда!\"\n  STR_SET_TIMER: \"Установить таймер\"\n  STR_HIDDEN_MOVEMENT: \"СКРЫТЫЕ ПЕРЕМЕЩЕНИЯ\"\n  STR_TURN: \"ХОД> {0}\"\n  STR_SIDE: \"СТОРОНА> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Нажмите кнопку для продолжения\"\n  STR_MIND_CONTROL: \"Контроль сознания\"\n  STR_PANIC_UNIT: \"Паника\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Психическая атака удалась\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Контроль установлен\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}потерял рассудок\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}потеряла рассудок\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}запаниковал\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}запаниковала\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Пришельцы\"\n  STR_RIGHT_HAND: \"ПРАВАЯ РУКА\"\n  STR_LEFT_HAND: \"ЛЕВАЯ РУКА\"\n  STR_RIGHT_SHOULDER: \"ПРАВОЕ ПЛЕЧО\"\n  STR_LEFT_SHOULDER: \"ЛЕВОЕ ПЛЕЧО\"\n  STR_BACK_PACK: \"РЮКЗАК\"\n  STR_BELT: \"ПОЯС\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}под контролем пришельцев \"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}под контролем пришельцев\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}потерял сознание\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}потеряла сознание\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}умер от смертельных ран\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}умерла от смертельных ран\"\n  STR_USE_MIND_PROBE: \"Использовать зонд\"\n  STR_FATAL_WOUNDS: \"СМЕРТЕЛЬНЫЕ РАНЫ\"\n  STR_UNDER_ARMOR_UC: \"БРОНЯ СНИЗУ\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Очки действия зарезервированы для выстрела навскидку\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Очки действия зарезервированы для стрельбы очередью\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Очки действия зарезервированы для прицельного выстрела\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"ОД зарезервированы, чтобы присесть\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"ОД зарезервированы, чтобы присесть и выстрелить\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} боец в транспорте X-Com\"\n    few: \"{N} бойца в транспорте X-Com\"\n    many: \"{N} бойцрв в транспорте X-Com\"\n    other: \"{N} бойцов в транспорте X-Com\"\n  STR_UNITS_OUTSIDE:\n    one: \"{N} боец остался снаружи\"\n    few: \"{N} бойца осталось снаружи\"\n    many: \"{N} бойцов осталось снаружи\"\n    other: \"{N} бойцов осталось снаружи\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} боец на входе\"\n    few: \"{N} бойца на входе\"\n    many: \"{N} бойцов на входе\"\n    other: \"{N} бойцов на входе\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} боец в зоне выхода\"\n    few: \"{N} бойца в зоне выхода\"\n    many: \"{N} бойцов в зоне выхода\"\n    other: \"{N} бойцов в зоне выхода\"\n  STR_ABORT_MISSION_QUESTION: \"Покинуть поле боя?\"\n  STR_CORPSE: \"Труп\"\n  STR_UNLOAD_CRAFT: \"Выгрузить\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}убит\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}убита\"\n  STR_HIT_MELEE: \"Ударить\"\n  STR_GROUND: \"НА ЗЕМЛЕ\"\n  STR_LIVING_QUARTERS_PLURAL: \"Жилые модули\"\n  STR_LIST_ITEM: \"ПРЕДМЕТ\"\n  STR_PERSONAL_ARMOR_UFOPEDIA: \"Новая бронезащита, содержащая сплавы пришельцев, дает нашим бойцам хоть какой-то шанс выжить в боях с инопланетной угрозой.\"\n  STR_POWER_SUIT_UFOPEDIA: \"Новое действенное средство защиты. Этот бронекостюм, питающийся от элериевого источника энергии, значительно увеличивает скорость и силу носителя, что делает его наиболее эффективным средством защиты пехоты в настоящее время.\"\n  STR_FLYING_SUIT_UFOPEDIA: \"Улучшенная версия энергоскафандра, в которую интегрирован гравитационный модуль пришельцев. Обеспечивает полную свободу передвижения на поле боя.\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"Все пришельцы погибли при крушении.{NEWLINE}Автоматическая эвакуация НЛО\"\n  STR_RESET: \"Сброс\"\n  STR_MEMORIAL: \"Мемориал\"\n  STR_DATE_UC: \"ДАТА\"\n  STR_SOLDIERS_RECRUITED_UC: \"БОЙЦОВ НАНЯТО>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"ПОТЕРИ>{ALT}{0}\"\n  MAP_CULTA: \"Ферма\"\n  MAP_FOREST: \"Лес\"\n  MAP_JUNGLE: \"Джунгли\"\n  MAP_MOUNT: \"Горы\"\n  MAP_DESERT: \"Пустыня\"\n  MAP_POLAR: \"Заполярье\"\n  MAP_URBAN: \"Город\"\n  MAP_UBASE: \"База пришельцев\"\n  MAP_XBASE: \"База X-Com\"\n  MAP_MARS: \"Марс\"\n  STR_MIXED: \"Смешанная\"\n  STR_REMOVE_SELECTED: \"Убрать отобранных\"\n  STR_LIVE_ALIENS: \"Живые{NEWLINE}образцы\"\n  STR_DEAD_ALIENS: \"Негодные{NEWLINE}образцы\"\n  STR_UNDER_INTERROGATION: \"Изучаемые{NEWLINE}\"\n  STR_CONTAINMENT_EXCEEDED: \"ИЗОЛЯТОР ПРИШЕЛЬЦЕВ ЗАПОЛНЕН!{SMALLLINE}На базе {0} не хватает мест в изоляторе. Вы должны избавиться от лишних пленных (которые не выживут).\"\n  STR_MANAGE_CONTAINMENT: \"Управление изолятором пришельцев\"\n  STR_STORAGE_EXCEEDED: \"СКЛАДЫ ПЕРЕПОЛНЕНЫ!{SMALLLINE}На базе {0} недостаточно свободного места. Необходимо продать часть хранимого.\"\n  STR_GO_TO_BASE: \"Перейти к базе\"\n  STR_MELEE_ACCURACY: \"ТОЧНОСТЬ БЛИЖНЕГО БОЯ\"\n  STR_SELL_PRODUCTION: \"ПРОДАТЬ\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Обе руки должны быть свободны!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Не хватает экипировки для применения шаблона!\"\n  STR_UNLOAD_WEAPON: \"Разрядить оружие\"\n  STR_ALL_ITEMS: \"Все предметы\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"НЕТ МЕСТА НА БОРТУ!{SMALLLINE}Вы можете взять не больше {N} предмета на этот корабль.\"\n    few: \"НЕТ МЕСТА НА БОРТУ!{SMALLLINE}Вы можете взять не больше {N} предметов на этот корабль.\"\n    many: \"НЕТ МЕСТА НА БОРТУ!{SMALLLINE}Вы можете взять не больше {N} предметов на этот корабль.\"\n    other: \"НЕТ МЕСТА НА БОРТУ!{SMALLLINE}Вы можете взять не больше {N} единиц груза на это ТС.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}КОМАНДНЫЙ ЦЕНТР УНИЧТОЖЕН{NEWLINE}Доберитесь до входа и покиньте поле боя.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"Постройки X-Com невозможно размещать под водой\"\n  STR_LEVEL_SHORT: \"{0}\"\n  STR_PERSONNEL: \"Персонал\"\n  STR_CRAFT_ARMAMENT: \"Корабли и вооружение\"\n  STR_COMPONENTS: \"Компоненты\"\n  STR_SOLDIERS_RECRUITED: \"Бойцов нанято\"\n  STR_SOLDIERS_LOST: \"Бойцов потеряно\"\n  STR_TOTAL_UFOS: \"Обнаружено НЛО\"\n  STR_TOTAL_ALIEN_BASES: \"Обнаружено баз пришельцев\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"ПСИ\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"ПСН\"\n  FEMALE_CIVILIAN: \"Гражданский, женщина\"\n  MALE_CIVILIAN: \"Гражданский, мужчина\"\n  CYBERDISC_WEAPON: \"Оружие кибердиска\"\n  REAPER_WEAPON: \"Оружие жнеца\"\n  CHRYSSALID_WEAPON: \"Оружие криссалида\"\n  CELATID_WEAPON: \"Оружие целатида\"\n  SILACOID_WEAPON: \"Оружие силакоида\"\n  SECTOPOD_WEAPON: \"Оружие сектопода\"\n  ZOMBIE_WEAPON: \"Оружие зомби\"\n  ALIEN_PSI_WEAPON: \"Пси-оружие пришельцев\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/sk.yml",
    "content": "sk:\n  STR_AVENGER_UFOPEDIA: \"TRANSPORTNÉ A BOJOVÉ VESMÍRNE PLAVIDLO. DEFINITÍVNA REPLIKÁCIA MIMOZEMSKEJ TECHNOLÓGIE.\"\n  STR_INTERCEPTOR_UFOPEDIA: \"BOJOVÉ PLAVIDLO S DUÁLNYMI PULZNO-DETONAČNÝMI MOTORMI A ŠPECIÁLNYM TIENENÝM ELEKTRONICKÝM SYSTÉMOM. NAJLEPŠIA TECHNOLÓGIA DOSTUPNÁ NA ZEMI.\"\n  STR_LIGHTNING_UFOPEDIA: \"TRIEDA LIGHTNING PLNÍ FUNKCIU TRANSPORTÉRU A BOJOVÉHO STÍHAČA. HRUBÁ, ALE EFEKTÍVNA REPLIKÁCIA MIMOZEMSKÝCH POHONNÝCH SYSTÉMOV.\"\n  STR_SKYRANGER_UFOPEDIA: \"TRANSPORT PECHOTY. NAJRÝCHLEJŠÍ SVOJHO DRUHU SO SCHOPNOSŤOU VERTIKÁLNEHO ŠTARTU A PRISTÁTIA.\"\n  STR_FIRESTORM_UFOPEDIA: \"PLAVIDLO TRIEDY FIRESTORM JE BOJOVÝ STÍHAČ. TENTO JEDNOMIESTNY STROJ REPLIKUJE KLASICKÝ VZHĽAD MIMOZEMSKÉHO LIETAJÚCEHO TANIERA S CENTRÁLNOU POHONNOU JEDNOTKOU. \"\n  STR_STINGRAY_UFOPEDIA: \"POKROČILÁ RAKETA VZDUCH - VZDUCH SO ŠPECIÁLNE TIENENOU ELEKTRONIKOU.\"\n  STR_AVALANCHE_UFOPEDIA: \"RAKETA VZDUCH - VZDUCH S NUKLEÁRNOU HLAVICOU, AVŠAK EXTRÉMNE ŤAŽKÁ.\"\n  STR_CANNON_UFOPEDIA: \"VYSOKO VÝKONNÝ KANÓN STRIEĽAJÚCI PRIERAZNÉ STRELY SCHOPNÉ PRERAZIŤ 400 MM OCEĽOVÝ PANCIER.\"\n  STR_FUSION_BALL_UFOPEDIA: \"TENTO ODPAĽOVAČ VYSTREĽUJE RAKETU V TVARE GULE, KTORÁ JE NAPÁJANÁ REAKCIOU ANTIHMOTY. RAKETA ZNIČÍ CIEĽ POMOCOU IMPLÓZIE GRAVITAČNÝCH VĹN.\"\n  STR_LASER_CANNON_UFOPEDIA: \"TENTO KONVENČNÝ LASEROVÝ LÚČ JE NAPÁJANÝ KOMOROU S PREBIEHAJÚCOU REAKCIOU ANTIHMOTY. \"\n  STR_PLASMA_BEAM_UFOPEDIA: \"GRAVITAČNÝ LÚČ, KTORÝ ZAMIERI NA CIEĽ PRECÍZNE SMEROVANÉ IMPLODUJÚCE GRAVITAČNÉ POLE.\"\n  STR_SECTOID_UFOPEDIA: \"Hierarchia Sectoidov zahŕňa množstvo jedincov od vojakov až po ich veliteľov so silnými psionickými schopnosťami. Tieto schopnosti môžu byť použité na demoralizovanie jednotiek v boji alebo dokonca na kontrolu ich mysle. Často sa zapájajú do únosov ľudí a mrzačenia dobytku. Únosy využívajú na extrakciu genetického materiálu pre účely kríženia a vývoja klonov určených k infiltrácií ľudskej spoločnosti. Dobytok poskytuje rovnako ako výživu, tak aj vhodný genetický materiál. Tento druh zdá sa chce vyvinúť čo najdokonalejšie genetické hybridy, aby tak zvýšili efektivitu svojej úľu podobnej spoločnosti.\"\n  STR_SECTOID_AUTOPSY: \"Pitva sectoida\"\n  STR_SECTOID_AUTOPSY_UFOPEDIA: \"Pitva odhalila zakrpatené zažívacie orgány a jednoduché štruktúry. Mozog a oči sú veľmi dobre vyvinuté. Štruktúra orgánov ukazuje na genetickú manipuláciu alebo mutáciu. Malé ústa a nos majú pravdepodobne bezvýznamnú funkciu. Blana medzi prstami a ploché chodidlá naznačujú vodný pôvod druhu. Nenašli sme nič čo by pripomínalo reprodukčné orgány, ani stopy po inom spôsobe rozmnožovania tohto živočíšneho druhu. Pravdepodobne sa jedná o geneticky vytvorený druh.\"\n  STR_SNAKEMAN_UFOPEDIA: \"Tento hada pripomínajúci druh (odtiaľ angl. pomenovanie Snakeman - hadí muž) sa vyvinul v extrémne nepriaznivom prostredí. Tento druh je výnimočne húževnatý a dokáže odolať i extrémnym výkyvom teplôt. Pohyblivosť tohto druhu je závislá na veľkej hadovi podobnej \\\"nohe\\\", ktorá chráni všetky životne dôležité orgány. Zdá sa, že ich záujmy sú čisto predátorské a podliehajú veleniu inej inteligencie, ktorá riadi ich vojenské nájazdy na Zem.\"\n  STR_SNAKEMAN_AUTOPSY: \"Pitva Snakemana\"\n  STR_SNAKEMAN_AUTOPSY_UFOPEDIA: \"Koža tohto tvora je extrémne tvrdá a odolná voči žiaru. Kardiovaskulárny systém je súčasťou svalového systému, ktorý funguje na princípe hydrauliky a je využívaný k pohybu tvora. Jediným pravým svalom je tak srdce. Systém rozmnožovania sa zdá byť veľmi efektívny. Rozmnožovanie je asexuálne. Každý snakeman dokáže niesť vo vnútri svojho tela až do štyridsať vajec. Ponechaný svojmu osudu by tento druh znamenal nebezpečné ohrozenie života na Zemi.\"\n  STR_ETHEREAL_UFOPEDIA: \"Táto bytosť má neuveriteľné mentálne schopnosti, ktoré jej umožňujú telepaticky komunikovať a využívať telekinetické schopnosti. Tento evidentne fyzicky slabý tvor je závislý na svojej mentálnej sile, ktorá ho drží pri živote. Nevieme presne ako tieto schopnosti fungujú, keďže sa vymykajú naším fyzikálnym zákonom. Avšak s istotou môžeme povedať, že sú extrémne nebezpeční v bojových situáciách, kde sa spoliehajú na svoje mentálne sily. Len veľmi zriedka sa vyskytujú na Zemi, keďže sa spoliehajú na to, že ostatné druhy budú plniť ich príkazy. \"\n  STR_ETHEREAL_AUTOPSY: \"Pitva Ethereala\"\n  STR_ETHEREAL_AUTOPSY_UFOPEDIA: \"Táto bytosť je fyzicky nevyvinutá a vyzerá to tak, že nie je schopná udržať základné životné funkcie. Svaly sú ťažko atrofované a vnútorné orgány sú veľmi málo vyvinuté. Zdá sa, že zmyslové orgány, vrátane očí, vôbec nefungujú. Naopak mozog je veľmi dobre vyvinutý a spotrebúva veľkú časť z krvného obehu. Nedokážeme však určiť ako môže táto bytosť existovať bez vonkajšej podpory života.\"\n  STR_MUTON_UFOPEDIA: \"Táto humanoidná bytosť je fyzický silná a inteligentná. Majú veľký apetít konkrétne, čo sa týka konzumácie surového mäsa hocijakého druhu, ktoré potrebujú podobne ako pozemské šelmy. Zdá sa, že sa spoliehajú na telepatické príkazy rasy známej ako Ethereál. Akonáhle sa telepatické spojenie preruší, ich mentálny systém začína odumierať a umierajú. Kybernetické implantáty sú používané na zlepšenie výkonnosti v boji. Sú to pešiaci slúžiaci vyššej moci.\"\n  STR_MUTON_AUTOPSY: \"Pitva mutona\"\n  STR_MUTON_AUTOPSY_UFOPEDIA: \"\\\"Pokožka\\\" tohto tvora sa zdá byť organicky vytvorené ochranné brnenie, ktoré je transplantovaná na telo. Nachádzajú sa tu početné kybernetické implantáty, ktoré sú používané na zlepšenie kardiovaskulárneho systému a zmyslov. Reprodukčné orgány sa zdajú byť chirurgicky odstránené. Tieto nešťastné organizmy sú evidentne vytvorené iba za účelom vojny a dobývania. AP munícia sa nezdá byť veľmi efektívna proti tejto spevnenej koži.\"\n  STR_CELATID_UFOPEDIA: \"Táto životná forma má záhadnú prirodzenú schopnosť levitácie vzduchom. Pravdepodobne dokáže detekovať vlny ľudského mozgu a sledovať ich i k dobre ukrytému ľudskému cieľu. Akonáhle objaví cieľ, Celatid pristane a vystrelí malé globule extrémne korozívneho jedu. Tento tvor má schopnosť veľmi rýchleho klonovania samého seba. Na misiách sprevádza druh označovaný ako Mutóni.\"\n  STR_CELATID_AUTOPSY: \"Pitva celatida\"\n  STR_CELATID_AUTOPSY_UFOPEDIA: \"Jadro obsahuje malé biomechanické zariadenie, ktoré vyzerá ako prirodzene vyvinutý antigravitačný pohonný systém. Vak s jednom je najväčší orgán a nezdá sa, že by tu existovala samostatne vyvinutá mozgová štruktúra. Pri pitve sme nenašli žiadny rozpoznateľný tráviaci alebo reprodukčný systém. Jeden malý orgán obsahoval embryá, ktoré dokážu rýchlo dorásť do novej bytosti. \"\n  STR_SILACOID_UFOPEDIA: \"Táto forma života tvorená prevažne kremíkom vyžaruje obrovské množstvo tepla. Má dostatok energie aj na rozdrvenie skál, ktoré potom strávi za pomoci horúceho jadra. Má len primitívnu inteligenciu a môže byť kontrolovaná implantátmi alebo jedincami s psionickými schopnosťami. Je využívaná druhom označovaným ako Mutoni.\"\n  STR_SILACOID_AUTOPSY: \"Pitva silacoida\"\n  STR_SILACOID_AUTOPSY_UFOPEDIA: \"Vnútro tohto organizmu je extrémne horúce a zdá sa, že tvorí akýsi základ tráviaceho traktu. Jeho jedinečný svalový vykazuje ohromnú silu a pružnosť. Jeho skalopevnú pokožku nezraňuje zápalná alebo horľavá munícia.\"\n  STR_CHRYSSALID_UFOPEDIA: \"Tento tvor má klepetá podobné krabovi, ktoré sú veľmi silnou zbraňou v boji na blízko. Rýchly metabolizmus a veľká sila tohto tvora mu dovoľuje vyvinúť vysokú rýchlosť a mrštnosť. Namiesto toho aby svoje obete zabíjal, nakladie do nich vajíčka a vstrekne jed, ktorý z nich vytvorí kráčajúce mŕtvoly - zombie. Nový chryssalid sa liahne vo veľmi krátkej dobe - roztrhaním tela hostiteľa. Chryssalidi sú asociovaný s mimozemských druhom označovaným ako Snakeman.\"\n  STR_CHRYSSALID_AUTOPSY: \"Pitva chryssalida\"\n  STR_CHRYSSALID_AUTOPSY_UFOPEDIA: \"Exo-skelet tohto tvora je extrémne tvrdý a odolný, avšak prekvapivo citlivý na explozívnu muníciu. Mozog je dobre vyvinutý a bunky organizmu sa obnovujú veľmi rýchlo. Tvor nesie dvadsať vajíčok, ktoré môže klásť do iných organizmov. Tento tvor je veľmi efektívnou zbraňou mimozemského teroru.\"\n  STR_FLOATER_UFOPEDIA: \"Floateri primárne plnia funkciu rádových vojakov a agentov teroru. Sú prirodzenými predátormi, geneticky navrhnutý a kyberneticky upravený tak, aby z nich boli čo najlepší bojovníci. Spodná časť ich tela a väčšina interných orgánov je chirurgicky odstránená. Navyše im je nainštalovaný systém na podporu života. Tento implantát obsahuje anti-gravitačnú jednotku, ktorá umožňuje tomuto tvorovi vznášať sa vo vzduchu. \"\n  STR_FLOATER_AUTOPSY: \"Pitva floatera\"\n  STR_FLOATER_AUTOPSY_UFOPEDIA: \"Tento tvor bol drasticky pozmenený pomocou chirurgických zákrokov. Zariadenie, ktoré tvorí jadro jeho tela, je vlastne systémom podpory života. Tento systém preberá funkciu srdca, pľúc a tráviaceho systému. Táto úprava umožňuje tvorovi prežiť i v extrémnych podmienkach. Mozog je menší ako ľudský, avšak zmyslové orgány sú veľmi dobre vyvinuté. \"\n  STR_REAPER_UFOPEDIA: \"Tento dvojnohý mäsožravec má silné čeľuste a nesmierny apetít. Má niekoľko mozgových implantátov, ktoré sú uspôsobené na kontrolu jeho správania sa. Základné inštinkty predátora tohto tvora nemajú iné použitie ako spôsobovať strach a ničenie. Reaperi sú bežne asociovaný s druhom označovaným ako Floateri.\"\n  STR_REAPER_AUTOPSY: \"Pitva reapera\"\n  STR_REAPER_AUTOPSY_UFOPEDIA: \"Žnec alebo Reaper - ako je nazývaný v angl. jazyku - má dva mozgy a dve srdcia, ktoré tomuto tvorovi dovoľujú fungovať aj keď je veľmi ťažko zranený. Avšak jeho chlpatá koža je veľmi horľavá, čo robí tohto tvora zraniteľného na zápalnú muníciu.\"\n  STR_SECTOPOD_UFOPEDIA: \"Sectopodi sú roboty vyzbrojené silným laserovým lúčom. Tieto mechanické zvieratá sú ovládané cez telepatické spojenie z ich operátormi - Etherealmi. Sectopodi sú najsilnejšou zbraňou teroru, ktorú majú mimozemské sily k dispozícií. \"\n  STR_SECTOPOD_AUTOPSY: \"Pitva Sectopoda\"\n  STR_SECTOPOD_AUTOPSY_UFOPEDIA: \"Robustná konštrukcia robota je pokrytá energetickým pancierovaním schopným odolať väčšine typov útokov. Obzvlášť odolný je proti plazmovým zbraniam. Zmyslové obvody sú však veľmi dobre zraniteľné laserovými zbraňami. \"\n  STR_CYBERDISC_UFOPEDIA: \"Tento miniatúrny lietajúci tanier je automatickou zbraňou teroru vyzbrojený silným plazmovým lúčom. Antigravitačný pohon poskytuje výhody pri pohybe v ťažkom teréne. Hlavná funkcia tohto zariadenia je deštrukcia a teror v službách druhu označovaného ako Sectoid.\"\n  STR_CYBERDISC_AUTOPSY: \"Pitva kyberdisku\"\n  STR_CYBERDISC_AUTOPSY_UFOPEDIA: \"Kyberdisk je veľmi dobre chránený špeciálne proti explozívnej munícii. Primárny anti-gravitačný systém je však príliš poškodený, aby sme z neho dokázali získať poznatky o jeho fungovaní.\"\n  STR_UFO_POWER_SOURCE_UFOPEDIA: \"Zdrojom energie mimozemského plavidla je reaktor antihmoty využívajúci Elerium (prvok 115) ku generovaniu silných gravitačných vĺn ako aj ďalších foriem energie. Konverzia hmoty na energiu vykazuje 99% efektivitu, preto i malé množstvá Eléria dokážu vyprodukovať neuveriteľné množstvo sily. Tento energetický zdroj dokážeme vyrobiť jednoducho za pomoci mimozemských zliatin.\"\n  STR_UFO_NAVIGATION_UFOPEDIA: \"Mimozemské plavidlá používajú sofistikované počítače na navigáciu na Zemi a naprieč vesmírom. Systém je založený na optických procesoroch usporiadaných ako typ špeciálnej siete. Kontrolné rozhranie je relatívne jednoduché - navigátor ovláda smer gravitačných vĺn generovaných zdrojom energie na pohyb plavidla ľubovoľným smerom. Tento systém môže byť ľahko používaný ľuďmi a vieme ho reprodukovať použitím mimozemských zliatin a iných komponentov.\"\n  STR_UFO_CONSTRUCTION_UFOPEDIA: \"Mimozemská loď sa skladá z troch základných komponentov - zdroja energie, navigačného systému a z trupu skonštruovaného z mimozemských zliatin. Trup je špeciálne navrhnutý tak, aby dokázal presmerovať a kontrolovať gravitačné vlny. K napájaniu pohonu zdroja energie sa využívajú malé množstvá Eleria. Keď poznáme princípy konštrukcie a funkcie každého z komponentov, bude možné replikovať tento druh plavidiel.\"\n  STR_ALIEN_FOOD_UFOPEDIA: \"Tieto komory obsahujú rôzne druhy enzýmov, ktoré sú využívané na trávenie častie tieľ dobytka, iných zvierat a dokonca i ľudí. Výsledná tekutina je následne konzumovaná ako predstrávené jednlo - pravdepodobne priamo do krvného obehu. Tento fakt by nám mohol naznačovať istú závislosť na pozemskom jedle - symbiózu medzi pozemskou a mimozemskou spoločnosťou.\"\n  STR_ALIEN_REPRODUCTION_UFOPEDIA: \"Tieto nádrže obsahujú mimozemské zárodky. Konštrukčné riešenie týchto zásobníkov napovedá, že mimozemšťania využívajúci tento proces sú plne závislí na laboratórnom rozmnožovaní. Výživné látky tu obsiahnuté zaisťujú rýchly vývoj zárodku. Tento, továrenskej linke podobný, systém je schopný vytvárať tisícky mimozemských klonov v krátkom časovom úseku. Postup môže byť jednoducho prispôsobený pre rozmnožovanie ľudí alebo mimozemsko-ľudských hybridov.\"\n  STR_ALIEN_ENTERTAINMENT_UFOPEDIA: \"Najpravdepodobnejšia funkcia týchto guľovitých objektov je rekreačná. Psionické obvody, ktoré sa tu nachádzajú, stimulujú rôzne mozgové centrá. Efekt je podobný ako pri užívaní halucinogénnych drog. Toto je jediný dôkaz toho, že mimozemšťania majú aj nejaké kultúrne či rekreačné záľuby.\"\n  STR_ALIEN_SURGERY_UFOPEDIA: \"Mimozemské chirurgické zariadenie využíva laserové skalpely na vybranie špecifických časti tela z dobytka alebo iných zvierat. Veľmi rozšírené mrzačenie dobytka môžeme priradiť k tejto bizarnej aktivite mimozemšťanov. Je veľmi pravdepodobné, že sú tieto časti využívané za účelom stravovania alebo genetickým experimentom. \"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"Z minulosti máme tisíce svedectiev ľudí, ktorí tvrdili, že ich uniesli mimozemšťania, niekedy dokonca opakovane. Pravda je však omnoho strašnejšia. Ľudia sú unášaní, skúmaní a pozorovaní. Z najlepších exemplárov je extrahovaný genetický materiál. Ženám sú implantované ľudsko-mimozemské zárodky a následne - po niekoľkých mesiacoch - opäť odobraté. Kto vie aké zlovestné úmysly mimozemšťania majú?\"\n  STR_ALIEN_ALLOYS_UFOPEDIA: \"Mimozemské plavidlá sú skonštruované zo špeciálnych zliatin s unikátnymi vlastnosťami. Sú extrémne ľahké a odolné a sú ľahko tvarovateľné pomocou elektro-magnetických metód. Tento materiál dokážeme reprodukovať a využiť vo výrobnom procese.\"\n  STR_ELERIUM_115_UFOPEDIA: \"Tento element má nezvyklé vlastnosti, kedy dokáže pri bombardovaní špecifickými časticami vytvárať energiu na princípe anti-hmoty. To vytvára gravitačné vlny a ďalšie formy energie. V našom solárnom systéme sa tento prvok nenachádza v žiadnej prirodzenej forme a nedá sa reprodukovať. \"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"Je zrejmé, že Zem tu bojuje vopred prehranú bitku. Mimozemské hordy majú početnú prevahu. Najlepšie čo môžeme urobiť je spomaliť ich postup. Jediná nádej ľudstva je zasiahnuť mimozemských agresorov priamo pri zdroji. Náš výskum naznačuje, že majú operačnú základňu niekde vo vnútri nášho solárneho systému. Podľa mimozemšťanov to bolo centrum pradávnej civilizácie, ktorá presahuje známu ľudskú históriu. Je nutné lokalizovať toto miesto čo najskôr. Avšak, takto vitálne informácie bude mať len niektorí z vyššie postavených jedincov. Preto musíme zajať a vypočuť mimozemského veliteľa. Dá sa predpokladať, že každé väčšie UFO bude riadiť aspoň jeden mimozemšťan - veliteľ.\"\n  STR_THE_MARTIAN_SOLUTION_UFOPEDIA: \"Výsledky nášho posledného výskumu hovoria, že operačná základňa mimozemšťanov sa nachádza na Marse. Základňa je dobre skrytá a obsahuje výrobné a klonovacie zariadenia, ktoré slúžia na podporu infiltrácie Zeme. Rovnako sa zdá, že toto zariadenie obsahuje i nejaký druh počítača, ktorý riadi celú operáciu. Zdá sa, že organizačnou štruktúrou úľu podobná mimozemská spoločnosť je závislá od akejsi 'včelej kráľovny'. Táto podstatná slabina v organizácii mimozemskej spoločnosti nám dáva nádej na úspech. Ak dokážeme eliminovať 'mozog', potom telo odumrie. Musíme zvýšiť tempo nášho vedeckého bádania v tejto oblasti, skôr než bude neskoro. Aby sme mohli pokračovať, musíme zajať vysoko postaveného mimozemšťana - komandéra - ktorí sídlia len v základniach mimozemšťanov a v bojových lodiach.\"\n  STR_CYDONIA_OR_BUST_UFOPEDIA: \"Je zrejmé, že mimozemská invázia je kontrolovaná z podzemnej bázy v Cydonii - čo je neobvyklá oblasť Marsu, v ktorej sa nachádzajú päťstranné pyramídy a veľká kamenná formácia pripomínajúca ľudskú tvár. Cydoniánska civilizácia prekvitala pred miliónmi rokov na Marse, avšak nemáme poznatky o tom prečo zanikla alebo aké je jej spojenie s poslednou mimozemskou aktivitou na tomto mieste. Akékoľvek existuje vysvetlenie, je jasné, že na toto miesto musíme vyslať expedíciu. Je to jediný spôsob ako zastaviť útoky mimozemšťanov na našu planétu. Bude potrebné eliminovať kontrolný 'mozog'. Budeme potrebovať plavidlo triedy Avenger vyzbrojené tou najmodernejšou, najdeštruktívnejšou technológiou. Už nie je nič viac čo by sme sa mohli dozvedieť - môžeme len čakať na výsledok operácie Cydonia.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"VYCENTROVAŤ-ČAS=5 sek.\"\n  STR_CANCEL_UC: \"ZRUŠIŤ\"\n  STR_NONE: \"Žiadny\"\n  STR_UNKNOWN: \"Neznámy\"\n  STR_POOR: \"Slabé\"\n  STR_AVERAGE: \"Priemerný\"\n  STR_GOOD: \"Dobrý\"\n  STR_EXCELLENT: \"Výborne\"\n  STR_BUILD_NEW_BASE_UC: \"POSTAVIŤ NOVÚ ZÁKLADŇU\"\n  STR_BASE_INFORMATION: \"INFORMÁCIA O ZÁKLADNI\"\n  STR_EQUIP_CRAFT: \"VYZBROJIŤ LIETADLO\"\n  STR_BUILD_FACILITIES: \"POSTAVIŤ ZARIADENIE\"\n  STR_RESEARCH: \"VÝSKUM\"\n  STR_MANUFACTURE: \"VÝROBA\"\n  STR_TRANSFER_UC: \"PRESUN\"\n  STR_PURCHASE_RECRUIT: \"NÁKUP/NÁBOR\"\n  STR_SACK: \"PREPUSTIŤ\"\n  STR_SELL_SACK_UC: \"PREDAŤ/PREPUSTIŤ\"\n  STR_GEOSCAPE_UC: \"GLÓBUS\"\n  STR_NAME: \"Meno\"\n  STR_AREA: \"Oblasť\"\n  STR_BUILD_NEW_BASE: \"PostavIť novú základňu\"\n  STR_CANCEL: \"Zrušiť\"\n  STR_COST_UC: \"CENA>\"\n  STR_CONSTRUCTION_TIME_UC: \"ČAS VÝSTAVBY>\"\n  STR_DAY:\n    one: \"{N} deň\"\n    few: \"{N} dni\"\n    many: \"{N} dní\"\n    other: \"{N} dní\"\n  STR_HOUR:\n    one: \"{N} hodina\"\n    few: \"{N} hodiny\"\n    many: \"{N} hodín\"\n    other: \"{N} hodín\"\n  STR_MAINTENANCE_UC: \"ÚDRŽBA>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Inštalácia\"\n  STR_CURRENT_RESEARCH: \"AKTUÁLNY VÝSKUM\"\n  STR_SCIENTISTS_AVAILABLE: \"Dostupní vedci>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Pridelených vedcov>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Voľné laboratórne miesto>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"VÝSKUMNÝ PROJEKT\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"PRIDELENÍ VEDCI\"\n  STR_PROGRESS: \"POSTUP\"\n  STR_NEW_PROJECT: \"Nový projekt\"\n  STR_CANCEL_PROJECT: \"ZRUŠIŤ PROJEKT\"\n  STR_NEW_RESEARCH_PROJECTS: \"NOVÉ VÝSKUMNÉ PROJEKTY\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"DOSTUPNÍ VEDCI>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"VOĽNÉ LABORATÓRNE MIESTO>{ALT}{0}\"\n  STR_INCREASE: \"Zvýšenie\"\n  STR_DECREASE: \"Znížiť\"\n  STR_START_PROJECT: \"ZAČAŤ PROJEKT\"\n  STR_CURRENT_PRODUCTION: \"Aktuálna produkcia\"\n  STR_ENGINEERS_AVAILABLE: \"Dostupní inžinieri>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Pridelených inžinierov>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Dostupné miesto v dielni>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Dostupné financie>{ALT}{0}\"\n  STR_ITEM: \"POLOŽKA\"\n  STR_ENGINEERS__ALLOCATED: \"Pridelených inžinierov\"\n  STR_UNITS_PRODUCED: \"Vyrobených kusov\"\n  STR_TOTAL_TO_PRODUCE: \"Celkovo vyrobiť\"\n  STR_COST__PER__UNIT: \"Cena{NEWLINE}za{NEWLINE}kus\"\n  STR_DAYS_HOURS_LEFT: \"Ostávajúce dni/hodiny\"\n  STR_NEW_PRODUCTION: \"Nová výroba\"\n  STR_PRODUCTION_ITEMS: \"Predmety k výrobe\"\n  STR_CATEGORY: \"KATEGÓRIA\"\n  STR_START_PRODUCTION: \"ZAČNI S VÝROBOU\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} Osobohodín potrebných na výrobu jedného kusu\"\n  STR_COST_PER_UNIT_: \"Jedn. cena>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Požadovaný pracovný priestor>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"VYŽADUJE ŠPECIÁLNE MATERIÁLY\"\n  STR_ITEM_REQUIRED: \"POTREBNÝ MATERIÁL\"\n  STR_UNITS_REQUIRED: \"POTREBNÝCH JEDNOTIEK\"\n  STR_UNITS_AVAILABLE: \"DOSTUPNÉ JEDNOTKY\"\n  STR_STOP_PRODUCTION: \"ZASTAVIŤ VÝROBU\"\n  STR_ENGINEERS_AVAILABLE_UC: \"DOSTUPNÍ INŽINIERI>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"DOSTUPNÉ PRACOVNÉ MIESTO>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"MESAČNÝ ZISK>{ALT}{0}\"\n  STR_INCREASE_UC: \"ZVÝŠIŤ\"\n  STR_DECREASE_UC: \"ZNÍŽIŤ\"\n  STR_UNITS_TO_PRODUCE: \"Vyrobiť kusov\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Nákup/Nábor personálu\"\n  STR_COST_OF_PURCHASES: \"Cena za nákup>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"JEDN. CENA\"\n  STR_QUANTITY_UC: \"MNOŽSTVO\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"VOĽNÝCH MIEST:ZAMESTNANCOV CELKOM>\"\n  STR_SOLDIERS: \"Vojakov\"\n  STR_SCIENTISTS: \"Vedci\"\n  STR_ENGINEERS: \"Inžinieri\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"POUŽITÉ MIESTO:DOSTUPNÉ MIESTO>\"\n  STR_LIVING_QUARTERS: \"Ubytovne\"\n  STR_STORES: \"Sklady\"\n  STR_LABORATORIES: \"Laboratóriá\"\n  STR_WORK_SHOPS: \"Dielne\"\n  STR_HANGARS: \"Hangáre\"\n  STR_SHORT_RANGE_DETECTION: \"Detekcia krátkeho dosahu\"\n  STR_DEFENSE_STRENGTH: \"Účinnosť obrany\"\n  STR_TRANSFERS_UC: \"PRESUNY\"\n  STR_TRANSFERS: \"Presuny\"\n  STR_ARRIVAL_TIME_HOURS: \"Doba dodávky (hodiny)\"\n  STR_COST_: \"Cena>{ALT}{0}\"\n  STR_AREA_: \"Oblasť>{ALT}{0}\"\n  STR_BASE_NAME: \"Meno základne?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"URČI POZÍCIU PRE PRÍSTUPOVÝ VÝŤAH\"\n  STR_TRANSFER: \"Presun\"\n  STR_AMOUNT_TO_TRANSFER: \"MNOŽSTVO NA PRESUN\"\n  STR_SELECT_DESTINATION_BASE: \"Označ cieľovú základňu\"\n  STR_COST: \"Cena\"\n  STR_VICTORY_1: \"Po vstupe do miestnosti vidíš mimozemský mozog - cieľ tvojej misie. Predtým ako na neho stihnete vystreliť začne komunikovať cez obrazovky v základni. Prosí, aby ste počúvali jeho argumenty pre prežitie, než sa rozhodnete vystreliť...\"\n  STR_VICTORY_2: \"Mozog prehovoril: 'Pred mnohými miliónmi rokov planéta, ktorú voláte Mars, prekvitala životom. Tento život bol našou civilizáciou prinesený na túto pustú planétu, tak ako na vašu. Po milióny rokov sme navštevovali vašu planétu a geneticky rozvíjali váš živočíšny druh. Nemôžete nás zabiť, vy ste našou súčasťou... '\"\n  STR_VICTORY_3: \"Tu je centrum marťanskej civilizácie - pyramídy postavené milióny rokov pred vašimi - druhom, ktorý patril k vaším predkom. Žiadna planéta nie je mimo nášho dosahu. Táto moc môže byť onedlho i vaša. Jediné čo po vás žiadame je vaša spolupráca... \"\n  STR_GAME_OVER_1: \"Mimozemšťania sa pokúsili zlikvidovať celé ľudstvo; zničili mestá a otrávili vzduch i moria. Odpor pozemských armád je márny. Pozemské technológie nedokážu konkurovať oveľa vyspelejšej technológii agresorov. Preživšie generácie, ktoré sa snažili ujsť pred mimozemským ničením trpia strašnými mutáciami. Tí čo prežili sú pochytaní a zatvorení do pracovných táborov, aby pomohli premeniť Zem v mimozemskú kolóniu, ktorá je časťou neznámeho impéria.\"\n  STR_GAME_OVER_2: \"Poznatky získané projektom X-Com sú navždy stratené. Zlyhal si pri záchrane Zeme.\"\n  STR_VICTORY_4: \"Mimozemský mozog si prerušil výbojom horúcej plazmy, a v tom okamihu boli všetky jednotky mimozemšťanov porazené.\"\n  STR_VICTORY_5: \"Akonáhle invázne sily mimozemšťanov stratili Mars, stratili Zem. Netrvalo dlho a výskum X-Com priniesol ľudskej civilizácii obdobie rozkvetu, a vďaka tomu dokázala zabrať Mars pre seba. Mimozemská hrozba je preč, avšak otázkou ostáva na ako dlho...\"\n  STR_YOU_HAVE_FAILED: \"Zlyhal si a nezastavil mimozemský útok. Jeden po druhom financujúce národy podpisujú dohody o miery a prosperite s mimozemšťanmi, výmenou za  ich technológie. Hoci čoskoro je jasné, že mimozemšťania mali iné plány ...\"\n  STR_TOTAL_UC: \"CELKOM\"\n  STR_INCOME: \"Príjmy\"\n  STR_EXPENDITURE: \"Výdavky\"\n  STR_MAINTENANCE: \"Údržba\"\n  STR_BALANCE: \"Zostatok\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"Aktivita UFO v oblasti\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"Aktivita UFO v krajinách\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"Aktivita X-Com v oblastiach\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"Aktivita X-Com v krajinách\"\n  STR_FINANCE: \"Financie\"\n  STR_DATE_FIRST: \"{0}.\"\n  STR_DATE_SECOND: \"{0}.\"\n  STR_DATE_THIRD: \"{0}.\"\n  STR_DATE_FOURTH: \"{0}.\"\n  STR_FINANCE_THOUSANDS: \"$1000's\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Nemáme dostatok špeciálnych materiálov na výrobu{NEWLINE}{0}{NEWLINE}v{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Nemáme dosatok financií na výrobu{NEWLINE}{0}{NEWLINE}v{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"Dokončená výroba predmetu{NEWLINE}{0}{NEWLINE}na základni{NEWLINE}{1}{NEWLINE}\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"Výstavba{NEWLINE}{0}{NEWLINE}v{NEWLINE}{1}{NEWLINE}je ukončená\"\n  STR_OK_5_SECONDS: \"OK - 5 sek\"\n  STR_RESEARCH_COMPLETED: \"Výskum dokončený\"\n  STR_VIEW_REPORTS: \"PREZRIEŤ HLÁSENIA\"\n  STR_WE_CAN_NOW_RESEARCH: \"Teraz môžete skúmať\"\n  STR_WE_CAN_NOW_PRODUCE: \"Môžeme vyrábať\"\n  STR_SUNDAY: \"NEDEĽA\"\n  STR_MONDAY: \"PONDELOK\"\n  STR_TUESDAY: \"UTOROK\"\n  STR_WEDNESDAY: \"STREDA\"\n  STR_THURSDAY: \"ŠTVRTOK\"\n  STR_FRIDAY: \"PIATOK\"\n  STR_SATURDAY: \"SOBOTA\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Nedostatok {0} na dotankovanie {1} v {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Nedostatok {0} na vzybrojenie {1} v {2}\"\n  STR_UFO_IS_NOT_RECOVERED: \"UFO nebolo zaistené\"\n  STR_UFO_IS_RECOVERED: \"UFO bolo vyzdvihnuté\"\n  STR_CRAFT_IS_LOST: \"Plavidlo bolo zničené\"\n  STR_TERROR_CONTINUES: \"Teror pokračuje\"\n  STR_ALIENS_DEFEATED: \"Mimozemšťania boli porazení\"\n  STR_BASE_IS_LOST: \"Prišli sme o základňu\"\n  STR_BASE_IS_SAVED: \"Základňu sme ubránili\"\n  STR_ALIEN_BASE_STILL_INTACT: \"Základňa mimozemšťanov je stále nepoškodená\"\n  STR_ALIEN_BASE_DESTROYED: \"Základňa mimozemšťanov bola zničená\"\n  STR_ALIENS_KILLED: \"MIMOZEMŠŤANIA ZABITÍ\"\n  STR_ALIEN_CORPSES_RECOVERED: \"ZÍSKANÉ TELÁ MIMOZEMŠŤANOV\"\n  STR_LIVE_ALIENS_RECOVERED: \"ZAJATÝCH ŽIVÝCH MIMOZEMŠŤANOV\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"ZÍSKANÉ MIMOZEMSKÉ ARTEFAKTY\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"RIADENIE MIMOZEMSKEJ BÁZE ZNIČENÉ\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"CIVILISTI ZABITÍ MIMOZEMŠŤANMI\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"CIVILISTI ZABITÍ JEDNOTKAMI X-COM\"\n  STR_CIVILIANS_SAVED: \"ZACHRANENÍ CIVILISTI\"\n  STR_XCOM_OPERATIVES_KILLED: \"ZABITÍ AGENTI X-COM\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"AGENTI X-COM STRATENÍ V AKCII\"\n  STR_TANKS_DESTROYED: \"ZNIČENÉ TANKY\"\n  STR_XCOM_CRAFT_LOST: \"PLAVIDLO X-COM ZNIČENÉ\"\n  STR_UFO_RECOVERY: \"ZAISTENIE UFO\"\n  STR_ALIEN_BASE_RECOVERY: \"DOBÝVANIE ZÁKLADNE MIMOZEMŠŤANOV\"\n  STR_BASE_UNDER_ATTACK: \"{0} pod paľbou!\"\n  STR_BASE_DEFENSES_INITIATED: \"OBRANA ZÁKLADNE INICIALIZOVANÁ\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"GRAVITAČNÝ ŠTÍT ODPUDZUJE UFO!\"\n  STR_FIRING: \"STREĽBA\"\n  STR_HIT: \"ZÁSAH!\"\n  STR_UFO_DESTROYED: \"UFO ZNIČENÉ!\"\n  STR_MISSED: \"VEDĽA!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Predaj predmety/Prepusti personál\"\n  STR_VALUE_OF_SALES: \"HODNOTA PREDAJA> {ALT}{0}\"\n  STR_FUNDS: \"FINANCIE> {ALT}{0}\"\n  STR_SELL_SACK: \"Predať/Prepustiť\"\n  STR_VALUE: \"Cena\"\n  STR_CRAFT_: \"PLAVIDLO> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"ZAISTENIE HAVAROVANÉHO UFO\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"Upozornenie - v UFO alebo okolí miesta havárie sa stále môžu pohybovať živí mimozemšťania. Misia bude úspešná pokiaľ budú všetky opozičné jednotky eliminované či zneškodnené. Následne bude zahájený presun zvyškov UFO, artefaktov a mŕtvol mimozemšťanov späť na základňu. Ak chcete predčasne ukončiť misiu, musia sa všetci príslušníci výsadku X-Com vrátiť do transportéru, inak budú zanechaní na mieste. Misiu zrušíte kliknutím na ikonu 'Zrušiť misiu'.\"\n  STR_UFO_GROUND_ASSAULT: \"POZEMNÝ ÚTOK NA UFO\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"Preskúmajte miesto pristátia, a pokiaľ možno, získajte vstup do UFO. Misia bude úspešná pokiaľ budú všetky opozičné jednotky eliminované či zneškodnené. Následne bude zahájený presun zvyškov UFO, artefaktov a mŕtvol mimozemšťanov späť na základňu. Ak chcete predčasne ukončiť misiu, musia sa všetci príslušníci výsadku X-Com vrátiť do transportéru, inak budú zanechaní na mieste. Misiu zrušíte kliknutím na ikonu 'Zrušiť misiu'.\"\n  STR_BASE_DEFENSE: \"OBRANA ZÁKLADNE\"\n  STR_BASE_UC_: \"ZÁKLADŇA> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"Bolo detekované mimozemské plavidlo. Naša základňa je v nebezpečenstve. Podľa štandardných bezpečnostných protokolov všetok nebojový personál a plavidlá X-Com boli evakuované. Mimozemské jednotky sa pokúsia do základne preniknúť cez hangár alebo prístupový výťah. Ochráňte základňu a jej kľúčové zariadenia za každú cenu - toto je boj na smrť. Kliknutie na 'opustiť misiu' bude znamenať okamžitú porážku a stratu základne.\"\n  STR_ALIEN_BASE_ASSAULT: \"ÚTOK NA ZÁKLADŇU MIMOZEMŠŤANOV\"\n  STR_ALIEN_BASE_ASSAULT_BRIEFING: \"Jednotky X-Com sa dostali do vstupu základne mimozemšťanov. Aby bola základňa zničená je potrebné zlikvidovať jej kontrolné centrum. Misia bude automaticky ukončená pokiaľ budú eliminovaní všetci nepriatelia alebo keď sa jednotky vrátia k východu označenému zelenou farbou (kliknutím na ikonu 'zrušiť misiu' opustíte priestor).\"\n  STR_CYDONIA_BRIEFING: \"Vaše jednotky dorazili na Cydoniu. Získali vstup do veľkého podzemného komplexu neďaleko Marťanskej sfingy. Vašou úlohou je zničiť tzv. mozog mimozemšťanov, ktorý riadi všetku mimozemskú aktivitu. Osud ľudstva je vo vašich rukách, veliteľ...\"\n  STR_TERROR_MISSION: \"PROTITERORISTICKÁ MISIA\"\n  STR_TERROR_MISSION_BRIEFING: \"Misia bude úspešná v prípade, že budú eliminované alebo neutralizované všetky nepriateľské jednotky v oblasti. V oblasti sa nachádzajú civilisti, ktorých životy je treba chrániť pred mimozemskou hrozbou. Čím skôr neutralizujete hrozbu, tým viac ľudí sa vám podarí zachrániť. Ak chcete ukončiť misiu, uistite sa, že sú všetci agenti X-Com v transporte a kliknite na ikonu 'Zrušiť misiu'.\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"NIE JE VOĽNÝ HANGÁR PRE ZAČATIE VÝROBY PLAVIDLA!{SMALLLINE}Každé plavidlo pridelené na základňu, presunuté na základňu, kúpené alebo skonštruované využíva jeden hangár. Postavte nový hangár alebo presuňte plavidlo do inej základne. \"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"NIE JE VOĽNÝ HANGÁR PRE KUPOVANÝ STROJ!{SMALLLINE}Každé plavidlo pridelené na základňu, presunuté na základňu, kúpené alebo skonštruované využíva jeden hangár. Postavte nový hangár alebo presuňte plavidlo do inej základne.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"NIE JE VOĽNÝ HANGÁR TRANSFER PLAVIDLA!{SMALLLINE}Každé plavidlo pridelené na základňu, presunuté na základňu, kúpené alebo skonštruované využíva jeden hangár. Postavte nový hangár alebo presuňte plavidlo do inej základne. \"\n  STR_CANNOT_BUILD_HERE: \"NA TOMTO MIESTE NIE JE MOŽNÉ STAVAŤ!{SMALLLINE}Nové zariadenie môžete postaviť len vedľa existujúceho zariadenia.\"\n  STR_NO_FREE_ACCOMODATION: \"K DISPOZÍCII NIE SÚ DOSTATOČNÉ UBYTOVACIE KAPACITY!{SMALLLINE}Cieľová základňa nemá dostatok miesta v ubytovniach.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"NEDOSTATOK VOĽNÉHO PRACOVNÉHO MIESTA!{SMALLLINE}Postavte novú dielňu, alebo znížte výrobu na iných projektoch.\"\n  STR_NOT_ENOUGH_MONEY: \"NEDOSTATOK FINANCIÍ!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"NEDOSTATOK MIESTA V SKLADOCH!{SMALLLINE}Postavte nové skladové priestory alebo presuňte existujúce zásoby do inej základne.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"NEDOSTATOČNÁ UBYTOVACIA KAPACITA!{SMALLLINE}Postav nové ubytovacie priestory alebo presuň personál na inú základňu.\"\n  STR_LAUNCH_INTERCEPTION: \"ZAHÁJIŤ STÍHANIE\"\n  STR_CRAFT: \"LIETADLO\"\n  STR_STATUS: \"STAV\"\n  STR_BASE: \"ZÁKLADŇA\"\n  STR_READY: \"PRIPRAVENÝ\"\n  STR_OUT: \"MIMO\"\n  STR_REPAIRS: \"OPRAVY\"\n  STR_REFUELLING: \"TANKUJE\"\n  STR_REARMING: \"ZBROJENIE\"\n  STR_TARGET: \"CIEĽ: {0}\"\n  STR_WAY_POINT: \"SÚRADNICE\"\n  STR_ARE_YOU_SURE_CYDONIA: \"Skutočne chceš vyslať toto plavidlo na Cydoniu?\"\n  STR_YES: \"ÁNO\"\n  STR_NO: \"NIE\"\n  STR_SELECT_DESTINATION: \"OZNAČ CIEĽOVÉ MIESTO\"\n  STR_CYDONIA: \"CYDONIA\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"ZVOĽ MIESTO PRE NOVÚ ZÁKLADŇU\"\n  STR_RETURN_TO_BASE: \"NÁVRAT NA ZÁKLADŇU\"\n  STR_SELECT_NEW_TARGET: \"OZNAČ NOVÝ CIEĽ\"\n  STR_PATROL: \"HLIADKOVAŤ\"\n  STR_STATUS_: \"STAV>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"POŠKODENÉ - VRACIA SA NA ZÁKLADŇU\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"MÁLO PALIVA - VRACIA SA NA ZÁKLADŇU\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"MISIA ÚSPEŠNÁ - VRACIAME SA NA ZÁKLADŇU\"\n  STR_PATROLLING: \"HLIADKUJE\"\n  STR_TAILING_UFO: \"SLEDUJE UFO\"\n  STR_INTERCEPTING_UFO: \"PRENASLEDUJE UFO-{0}\"\n  STR_RETURNING_TO_BASE: \"VRACIA SA NA ZÁKLADŇU\"\n  STR_DESTINATION_UC_: \"MIESTO URČENIA: {0}\"\n  STR_BASE_UC: \"ZÁKLADŇA>{ALT}{0}\"\n  STR_SPEED_: \"RÝCHLOSŤ>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"MAXIMÁLNA RÝCHLOSŤ>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"Výška>{ALT}{0}\"\n  STR_VERY_LOW: \"VELMI NÍZKO\"\n  STR_LOW_UC: \"NÍZKO\"\n  STR_HIGH_UC: \"VYSOKO\"\n  STR_VERY_HIGH: \"VEĽMI VYSOKO\"\n  STR_FUEL: \"PALIVO>{ALT}{0}\"\n  STR_WEAPON_ONE: \"ZBRAŇ-1>{ALT}{0}\"\n  STR_NONE_UC: \"PRÁZDNY\"\n  STR_ROUNDS_: \"NÁBOJE>{ALT}{0}\"\n  STR_WEAPON_TWO: \"ZBRAŇ-2>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"STÍHACIE LIETADLO\"\n  STR_BASE_: \"Základňa>{0}\"\n  STR_NAME_UC: \"MENO\"\n  STR_AMMO_: \"MUNÍCIA>{ALT}{0}\"\n  STR_CREW: \"POSÁDKA\"\n  STR_EQUIPMENT_UC: \"VYBAVENIE\"\n  STR_ARMOR: \"ZBROJ\"\n  STR_MAX: \"MAX>{ALT}{0}\"\n  STR_ROOKIE: \"Vojak\"\n  STR_SQUADDIE: \"Čatár\"\n  STR_SERGEANT: \"Seržant\"\n  STR_CAPTAIN: \"Kapitán\"\n  STR_COLONEL: \"Plukovník\"\n  STR_COMMANDER: \"Komandér\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Vyberte bojový tím pre {0}\"\n  STR_SORT_BY: \"ZORADIŤ PODĽA...\"\n  STR_ORIGINAL_ORDER: \"PÔVODNÉ PORADIE\"\n  STR_MISSIONS2: \"POČET MISIÍ\"\n  STR_KILLS2: \"POČET ZABITÍ\"\n  STR_WOUND_RECOVERY2: \"DOBA ZOTAVENIA\"\n  STR_SPACE_AVAILABLE: \"DOSTUPNÉ MIESTO>{ALT}{0}\"\n  STR_SPACE_USED: \"POUŽITÉ MIESTO>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"POUŽITÉ MIESTO\"\n  STR_RANK: \"HODNOSŤ\"\n  STR_WOUNDED: \"ZRANENÝ\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Vybavenie pre {0}\"\n  STR_DEFENSE_VALUE: \"Hodnota obrany\"\n  STR_HIT_RATIO: \"Pravdepodobnosť zásahu\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}pripravený na{NEWLINE}pristáctie v blízkosti{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"Začať misiu?\"\n  STR_SELECT_ARMAMENT: \"Vybrať výzbroj\"\n  STR_AMMUNITION_AVAILABLE: \"DOSTUPNÁ MUNÍCIA\"\n  STR_ARMAMENT: \"VÝZBROJ\"\n  STR_NOT_AVAILABLE: \"NIE JE\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"VYBRAŤ ZBROJ PRE {NEWLINE}{0}\"\n  STR_TYPE: \"TYP\"\n  STR_PERSONAL_ARMOR_UC: \"OSOBNÁ ZBROJ\"\n  STR_POWER_SUIT_UC: \"ENERGETICKÁ ZBROJ\"\n  STR_FLYING_SUIT_UC: \"LIETAJÚCI SKAFANDER\"\n  STR_SELECT_ARMOR: \"Vybrať zbroj\"\n  STR_NORTH: \"SEVER\"\n  STR_NORTH_EAST: \"SEVEROVÝCHOD\"\n  STR_EAST: \"VÝCHOD\"\n  STR_SOUTH_EAST: \"JUHOVÝCHOD\"\n  STR_SOUTH: \"JUH\"\n  STR_SOUTH_WEST: \"JUHOZÁPAD\"\n  STR_WEST: \"ZÁPAD\"\n  STR_NORTH_WEST: \"SEVEROZÁPAD\"\n  STR_SELECT_ACTION: \"VYBER AKCIU\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"POKRAČUJ V ÚTOKU\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"SLEDUJ BEZ STÍHANIA\"\n  STR_VERY_LARGE: \"VEĽMI VEĽKÉ\"\n  STR_LARGE: \"VELKÉ\"\n  STR_MEDIUM_UC: \"STREDNÉ\"\n  STR_SMALL: \"MALÉ\"\n  STR_VERY_SMALL: \"VEĽMI MALÉ\"\n  STR_GROUNDED: \"ZEM\"\n  STR_DETECTED: \"Zistené\"\n  STR_SIZE_UC: \"VEĽKOSŤ\"\n  STR_ALTITUDE: \"VÝŠKA\"\n  STR_HEADING: \"SMER\"\n  STR_SPEED: \"RÝCHLOSŤ\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"VYCENTROVAŤ NA UFO-ČAS=5 sek\"\n  STR_TRACKING_LOST: \"STRATILI SME KONTAKT\"\n  STR_REDIRECT_CRAFT: \"PRESMEROVAŤ PLAVIDLO\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"ÍSŤ NA POSLEDNÚ ZNÁMU POZÍCIU UFO\"\n  STR_UFO_: \"UFO-{0}\"\n  STR_ALIEN_BASE_: \"ZÁKLADŇA MIMOZEMŠŤANOV-{0}\"\n  STR_CRASH_SITE_: \"MIESTO HAVÁRIE-{0}\"\n  STR_LANDING_SITE_: \"MIESTO PRISTÁTIA-{0}\"\n  STR_WAY_POINT_: \"SÚRADNICA-{0}\"\n  STR_TERROR_SITE: \"MIESTO TERORU-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}dorazil{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"Hliadkuje\"\n  STR_ALIEN_ORIGINS: \"Pôvod mimozemšťanov\"\n  STR_THE_MARTIAN_SOLUTION: \"Marťanské riešenie\"\n  STR_CYDONIA_OR_BUST: \"Cydonia alebo smrť\"\n  STR_UFOPAEDIA: \"UFOpédia\"\n  STR_XCOM_CRAFT_ARMAMENT: \"VÝZBROJ A STROJE X-COMu\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"ŤAŽKÉ ZBRAŇOVÉ SYSTÉMY\"\n  STR_WEAPONS_AND_EQUIPMENT: \"ZBRANE A VYBAVENIE\"\n  STR_ALIEN_ARTIFACTS: \"MIMOZEMSKÉ ARTEFAKTY\"\n  STR_BASE_FACILITIES: \"ZARIADENIA ZÁKLADNE\"\n  STR_ALIEN_LIFE_FORMS: \"MIMOZEMSKÉ ŽIVOTNÉ FORMY\"\n  STR_ALIEN_RESEARCH_UC: \"MIMOZEMSKÝ VÝSKUM\"\n  STR_UFO_COMPONENTS: \"KOMPONENTY UFO\"\n  STR_UFOS: \"UFO\"\n  STR_SELECT_ITEM: \"OZNAČ POLOŽKU\"\n  STR_ACCELERATION: \"AKCELERÁCIA>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"KAPACITA PALIVA>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"MIESTO PRE ZBRANE>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"PANCIEROVANIE>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"NÁKLADNÝ PRIESTOR>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"KAPACITA ŤZS>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Poškodenie\"\n  STR_RANGE: \"Dostrel\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Presnosť\"\n  STR_RE_LOAD_TIME: \"Dĺžka prebitia\"\n  STR_SECONDS: \"{0}s\"\n  STR_DAMAGE_ARMOR_PIERCING: \"PRIERAZNÉ\"\n  STR_DAMAGE_INCENDIARY: \"ZÁPALNÉ\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"SILNÁ VÝBUŠNINA\"\n  STR_DAMAGE_LASER_BEAM: \"LASEROVÝ LÚČ\"\n  STR_DAMAGE_PLASMA_BEAM: \"PLAZMOVÝ LÚČ\"\n  STR_DAMAGE_STUN: \"OMRAČUJÚCE\"\n  STR_DAMAGE_MELEE: \"BOJ Z BLÍZKA\"\n  STR_DAMAGE_ACID: \"KYSELINA\"\n  STR_DAMAGE_SMOKE: \"DYM\"\n  STR_SHOT_TYPE: \"TYP STREĽBY\"\n  STR_ACCURACY_UC: \"PRESNOSŤ\"\n  STR_TIME_UNIT_COST: \"CENA AB\"\n  STR_DAMAGE_UC: \"POŠKODENIE\"\n  STR_AMMO: \"MUNÍCIA\"\n  STR_SHOT_TYPE_AUTO: \"Automat\"\n  STR_SHOT_TYPE_SNAP: \"Rýchla\"\n  STR_SHOT_TYPE_AIMED: \"Mierená\"\n  STR_CONSTRUCTION_TIME: \"Čas výstavby\"\n  STR_CONSTRUCTION_COST: \"Cena výstavby\"\n  STR_MAINTENANCE_COST: \"Cena údržby\"\n  STR_LOW: \"Nízke\"\n  STR_MEDIUM: \"Stredné\"\n  STR_HIGH: \"Vysoko\"\n  STR_CRAFT_WEAPON: \"Palubná zbraň\"\n  STR_CRAFT_AMMUNITION: \"Munícia pre stíhačky\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Ťažký zbraňový systém\"\n  STR_WEAPON: \"Zbraň\"\n  STR_AMMUNITION: \"Munícia\"\n  STR_EQUIPMENT: \"Výbava\"\n  STR_ALIEN_CORPSE: \"Mŕtvola mimozemšťana\"\n  STR_UFO_COMPONENT: \"Komponent UFO\"\n  STR_PERSONAL_ARMOR: \"Osobná zbroj\"\n  STR_RAW_MATERIALS: \"Nespracované materiály\"\n  STR_HWP_CANNON_SHELLS: \"ŤZS Náboje do kanónu\"\n  STR_ALIEN: \"Mimozemšťan\"\n  STR_SECTOID: \"Sectoid\"\n  STR_SNAKEMAN: \"Snakeman\"\n  STR_ETHEREAL: \"Ethereal\"\n  STR_MUTON: \"Muton\"\n  STR_FLOATER: \"Floater\"\n  STR_CELATID: \"Celatid\"\n  STR_SILACOID: \"Silacoid\"\n  STR_CHRYSSALID: \"Chryssalid\"\n  STR_ZOMBIE: \"Zombie\"\n  STR_REAPER: \"Reaper\"\n  STR_SECTOPOD: \"Sectopod\"\n  STR_CYBERDISC: \"Kyberdisk\"\n  STR_LIVE_COMMANDER: \"Komandér\"\n  STR_LIVE_LEADER: \"Veliteľ\"\n  STR_LIVE_ENGINEER: \"Inžinier\"\n  STR_LIVE_MEDIC: \"Medik\"\n  STR_LIVE_NAVIGATOR: \"Navigátor\"\n  STR_LIVE_SOLDIER: \"Vojak\"\n  STR_LIVE_TERRORIST: \"Terorista\"\n  STR_FLOATER_SOLDIER: \"Floater vojak\"\n  STR_FLOATER_NAVIGATOR: \"Floater navigátor\"\n  STR_FLOATER_MEDIC: \"Floater medik\"\n  STR_FLOATER_ENGINEER: \"Floater inžinier\"\n  STR_FLOATER_LEADER: \"Floater veliteľ\"\n  STR_FLOATER_COMMANDER: \"Floater komandér\"\n  STR_SECTOID_SOLDIER: \"Sectoid vojak\"\n  STR_SECTOID_NAVIGATOR: \"Sectoid navigátor\"\n  STR_SECTOID_MEDIC: \"Sectoid medik\"\n  STR_SECTOID_ENGINEER: \"Sectoid inžinier\"\n  STR_SECTOID_LEADER: \"Sectoid veliteľ\"\n  STR_SECTOID_COMMANDER: \"Sectoid komandér\"\n  STR_SNAKEMAN_SOLDIER: \"Snakeman vojak\"\n  STR_SNAKEMAN_NAVIGATOR: \"Snakeman navigátor\"\n  STR_SNAKEMAN_ENGINEER: \"Snakeman inžinier\"\n  STR_SNAKEMAN_LEADER: \"Snakeman veliteľ\"\n  STR_SNAKEMAN_COMMANDER: \"Snakeman komandér\"\n  STR_MUTON_SOLDIER: \"Muton vojak\"\n  STR_MUTON_NAVIGATOR: \"Muton navigátor\"\n  STR_MUTON_ENGINEER: \"Muton inžinier\"\n  STR_ETHEREAL_SOLDIER: \"Ethereal vojak\"\n  STR_ETHEREAL_LEADER: \"Ethereal veliteľ\"\n  STR_ETHEREAL_COMMANDER: \"Ethereal komandér\"\n  STR_CYBERDISC_TERRORIST: \"Kyberdisk terorista\"\n  STR_REAPER_TERRORIST: \"Reaper terorista\"\n  STR_CHRYSSALID_TERRORIST: \"Chryssalid terorista\"\n  STR_CELATID_TERRORIST: \"Celatid terorista\"\n  STR_SILACOID_TERRORIST: \"Silacoid terorista\"\n  STR_SECTOPOD_TERRORIST: \"Sectopod terorista\"\n  STR_UFO_POWER_SOURCE: \"Zdroj energie UFO\"\n  STR_UFO_NAVIGATION: \"UFO Navigácia\"\n  STR_UFO_CONSTRUCTION: \"Konštrukcia UFO\"\n  STR_ALIEN_FOOD: \"Mimozemská strava\"\n  STR_ALIEN_REPRODUCTION: \"Rozmnožovanie mimozemšťanov\"\n  STR_ALIEN_ENTERTAINMENT: \"Mimozemská zábava\"\n  STR_ALIEN_SURGERY: \"Mimozemská chirurgia\"\n  STR_EXAMINATION_ROOM: \"Vyšetrovacia miestnosť\"\n  STR_ALIEN_ALLOYS: \"Mimozemské zliatiny\"\n  STR_ALIEN_HABITAT: \"Mimozemské prostredie\"\n  STR_POWER_SUIT: \"Energetická zbroj\"\n  STR_FLYING_SUIT: \"Lietajúci skafander\"\n  STR_HWP_ROCKETS: \"ŤZS Rakety\"\n  STR_HWP_FUSION_BOMB: \"ŤZS Fúzna raketa\"\n  STR_LASER_WEAPONS: \"Laserové zbrane\"\n  STR_NEW_FIGHTER_CRAFT: \"Nové stíhacie plavidlo\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Nový stíhač-transportér\"\n  STR_ULTIMATE_CRAFT: \"Dokonalý stroj\"\n  STR_LASER_PISTOL: \"Laserová pištoľ\"\n  STR_LASER_RIFLE: \"Laserová puška\"\n  STR_HEAVY_LASER: \"Ťažký laser\"\n  STR_LASER_CANNON: \"Laserové delo\"\n  STR_PLASMA_CANNON: \"Plazmové delo\"\n  STR_FUSION_MISSILE: \"Fúzna raketa\"\n  STR_LASER_DEFENSE: \"Laserová obrana\"\n  STR_PLASMA_DEFENSE: \"Plazmová obrana\"\n  STR_FUSION_DEFENSE: \"Fúzna obrana\"\n  STR_GRAV_SHIELD: \"Grav-štít\"\n  STR_MIND_SHIELD: \"Štít mysle\"\n  STR_PSI_LAB: \"Psionické laboratórium\"\n  STR_MOTION_SCANNER: \"Detektor pohybu\"\n  STR_MEDI_KIT: \"Lekárnička\"\n  STR_TANK_CANNON: \"Tank/Delo\"\n  STR_TANK_ROCKET_LAUNCHER: \"Tank/Raketomet\"\n  STR_TANK_LASER_CANNON: \"Tank/Laserový kanón\"\n  STR_HOVERTANK_PLASMA: \"Antigrav-Tank/Plazma\"\n  STR_HOVERTANK_LAUNCHER: \"Antigrav-Tank/Fúzny\"\n  STR_STINGRAY_LAUNCHER: \"Odpaľovač rakiet Stingray\"\n  STR_AVALANCHE_LAUNCHER: \"Odpaľovač rakiet Avalanche\"\n  STR_CANNON: \"Kanón\"\n  STR_FUSION_BALL_LAUNCHER: \"Odpaľovač fúznych rakiet\"\n  STR_PLASMA_BEAM: \"Plazmový lúč\"\n  STR_STINGRAY_MISSILES: \"Rakety Stingray\"\n  STR_AVALANCHE_MISSILES: \"Rakety Avalanche\"\n  STR_CANNON_ROUNDS_X50: \"Strelivo do kanóna(x50)\"\n  STR_FUSION_BALL: \"Fúzna munícia\"\n  STR_SOLDIER: \"Vojak\"\n  STR_SCIENTIST: \"Vedec\"\n  STR_ENGINEER: \"Inžinier\"\n  STR_NORTH_AMERICA: \"Severná Amerika\"\n  STR_ARCTIC: \"Arktída\"\n  STR_ANTARCTICA: \"Antarktída\"\n  STR_SOUTH_AMERICA: \"Južná Amerika\"\n  STR_EUROPE: \"Európa\"\n  STR_NORTH_AFRICA: \"Severná Afrika\"\n  STR_SOUTHERN_AFRICA: \"Južná Afrika\"\n  STR_CENTRAL_ASIA: \"Stredná Ázia\"\n  STR_SOUTH_EAST_ASIA: \"Juhových. Ázia\"\n  STR_SIBERIA: \"Sibír\"\n  STR_AUSTRALASIA: \"Australoázia\"\n  STR_PACIFIC: \"Pacifický oceán\"\n  STR_NORTH_ATLANTIC: \"Severný Atlantik\"\n  STR_SOUTH_ATLANTIC: \"Južný Atlantik\"\n  STR_INDIAN_OCEAN: \"Indický oceán\"\n  STR_ALIEN_RESEARCH: \"Mimozemský výskum\"\n  STR_ALIEN_HARVEST: \"Mimozemská žatva\"\n  STR_ALIEN_ABDUCTION: \"Mimozemské únosy\"\n  STR_ALIEN_INFILTRATION: \"Mimozemská infiltrácia\"\n  STR_ALIEN_BASE: \"Základňa mimozemšťanov\"\n  STR_ALIEN_TERROR: \"Mimozemský teror\"\n  STR_ALIEN_RETALIATION: \"Mimozemská odplata\"\n  STR_ALIEN_SUPPLY: \"Mimozemské zásobovanie\"\n  STR_MAXIMUM_SPEED: \"Maximálna rýchlosť\"\n  STR_HYPER_WAVE_DECODER_UC: \"DEKÓDER HYPER-VĹN\"\n  STR_SKYRANGER: \"SKYRANGER\"\n  STR_LIGHTNING: \"LIGHTNING\"\n  STR_AVENGER: \"AVENGER\"\n  STR_INTERCEPTOR: \"INTERCEPTOR\"\n  STR_FIRESTORM: \"FIRESTORM\"\n  STR_UFO: \"UFO\"\n  STR_STINGRAY: \"STINGRAY\"\n  STR_AVALANCHE: \"AVALANCHE\"\n  STR_CANNON_UC: \"KANÓN\"\n  STR_FUSION_BALL_UC: \"FÚZNY ODPAĽOVAČ\"\n  STR_LASER_CANNON_UC: \"LASEROVÝ KANÓN\"\n  STR_PLASMA_BEAM_UC: \"PLAZMOVÝ LÚČ\"\n  STR_DAMAGE_CAPACITY: \"Pancierovanie\"\n  STR_WEAPON_POWER: \"Sila zbrane\"\n  STR_WEAPON_RANGE: \"Dosah zbrane\"\n  STR_ACCESS_LIFT: \"Prístupový výťah\"\n  STR_LABORATORY: \"Laboratórium\"\n  STR_WORKSHOP: \"Dielňa\"\n  STR_SMALL_RADAR_SYSTEM: \"Radar krátkeho dosahu\"\n  STR_LARGE_RADAR_SYSTEM: \"Radar dlhého dosahu\"\n  STR_MISSILE_DEFENSES: \"Raketová obrana\"\n  STR_GENERAL_STORES: \"Sklady\"\n  STR_ALIEN_CONTAINMENT: \"Zadržiavacia cela\"\n  STR_LASER_DEFENSES: \"Laserová obrana\"\n  STR_PLASMA_DEFENSES: \"Plazmová obrana\"\n  STR_FUSION_BALL_DEFENSES: \"Fúzna obrana\"\n  STR_PSIONIC_LABORATORY: \"Psionické laboratórium\"\n  STR_HYPER_WAVE_DECODER: \"Dekóder hyper-vĺn\"\n  STR_HANGAR: \"Hangár\"\n  STR_USA: \"USA\"\n  STR_RUSSIA: \"RUSKO\"\n  STR_UK: \"VEĽKÁ BRITÁNIA\"\n  STR_FRANCE: \"FRANCÚZSKO\"\n  STR_GERMANY: \"NEMECKO\"\n  STR_ITALY: \"TALIANSKO\"\n  STR_SPAIN: \"ŠPANIELSKO\"\n  STR_CHINA: \"ČÍNA\"\n  STR_JAPAN: \"JAPONSKO\"\n  STR_INDIA: \"INDIA\"\n  STR_BRAZIL: \"BRAZÍLIA\"\n  STR_AUSTRALIA: \"AUSTRÁLIA\"\n  STR_NIGERIA: \"NIGER\"\n  STR_SOUTH_AFRICA: \"JAR\"\n  STR_EGYPT: \"EGYPT\"\n  STR_CANADA: \"KANADA\"\n  STR_TANK: \"Tank\"\n  STR_CIVILIAN: \"Civilista\"\n  STR_JAN: \"Jan\"\n  STR_FEB: \"Feb\"\n  STR_MAR: \"Mar\"\n  STR_APR: \"Apr\"\n  STR_MAY: \"Máj\"\n  STR_JUN: \"Jún\"\n  STR_JUL: \"Júl\"\n  STR_AUG: \"Aug\"\n  STR_SEP: \"Sep\"\n  STR_OCT: \"Okt\"\n  STR_NOV: \"Nov\"\n  STR_DEC: \"Dec\"\n  STR_INTERNATIONAL_RELATIONS: \"Medzinárodné vzťahy\"\n  STR_COUNTRY: \"Krajina\"\n  STR_FUNDING: \"Financovanie\"\n  STR_CHANGE: \"Zmena\"\n  STR_WEAPON_SYSTEMS: \"ZBRAŇOVÉ SYSTÉMY\"\n  STR_HWPS: \"ŤZS-y\"\n  STR_DAMAGE_UC_: \"POŠKODENIE>{ALT}{0}\"\n  STR_ACCESS_LIFT_UFOPEDIA: \"Prístupový výťah slúži na prepravu vybavenia a personálu do a z podzemnej základne. Je to vždy prvé zariadenie, ktoré musí byť postavené na novom mieste. Priestor výťahu je zraniteľný na útok potencionálnych nepriateľských síl.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Každý ubytovací blok poskytuje miesto pre 50 osôb. Zariadenie poskytuje základné rekreačné, stravovacie a ubytovacie zariadenie.\"\n  STR_LABORATORY_UFOPEDIA: \"Kapacita laborátória je maximálne 50 vedcov. Laboratóriá sú vybavené najmodernejšími technológiami pre výskum materiálov, biochémie a kozmológie. Je vám poskytnutý privilegovaný prístup k najlepším výskumným laboratóriám po celom svete, vrátane vojenských zariadení.\"\n  STR_WORKSHOP_UFOPEDIA: \"Dielne obsahujú všetko potrebné vybavenie na realizáciu projektov, ktoré vyvinuli vedci vo vedeckých laboratóriách. Až 50 inžinierov dokáže pracovať v jednom bloku dielní, avšak treba počítať s tým, že i konštruované predmety zaberajú nejaké miesto.\"\n  STR_SMALL_RADAR_SYSTEM_UFOPEDIA: \"Systém krátkovlnnej detekcie má radar s efektivitou 300 námorných míľ a je prepojený na satelitný systém pre pozemné vyhľadávanie. Každý takýto systém ma 10%-tnú šancu objaviť objekt priemernej veľkosti každých 30 minút.\"\n  STR_LARGE_RADAR_SYSTEM_UFOPEDIA: \"Systém ďalekej detekcie má radar s efektivitou 450 námorných míľ a je prepojený na satelitný systém pre pozemné vyhľadávanie. Každý takýto systém ma 20%-tnú šancu objaviť objekt priemernej veľkosti každých 30 minút.\"\n  STR_MISSILE_DEFENSES_UFOPEDIA: \"Raketová obrana predstavuje základnú ochranu proti útoku nepriateľských útočných strojov, ktoré sa snažia o pristátie neďaleko základne. \"\n  STR_GENERAL_STORES_UFOPEDIA: \"Všetko vybavenie, zbraňové systémy, získaný materiál a ťažké zbraňové systémy sú uložené v skladových priestoroch, vrátane vybavenia prideleného lietadlám v hangároch.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"Aby sme udržali pri živote živých mimozemšťanov je potrebné ich uzavrieť do špeciálneho prostredia. Toto zadržiavacie zariadenie dokáže udržať pri živote až 10 mimozemských životných foriem v sebestačných jednotkách.\"\n  STR_LASER_DEFENSES_UFOPEDIA: \"Laserová obrana poskytuje obranu proti útoku nepriateľských útočných lodí.\"\n  STR_PLASMA_DEFENSES_UFOPEDIA: \"Plazmová obrana zabezpečuje výkonnú a efektívnu ochranu pred vniknutím nepriateľského plavidla.\"\n  STR_FUSION_BALL_DEFENSES_UFOPEDIA: \"Fúzne rakety predstavujú najefektívnejšiu obranu proti útoku mimozemšťanov. Tieto rakety vytvárajú implóziu antihmoty, ktorá zničí všetko v špecifickom rádiuse.\"\n  STR_GRAV_SHIELD_UFOPEDIA: \"Gravitačný štít odpudzuje mimozemské plavidlá, ktoré sa pokúšajú pristáť pri základni, natoľko aby obranné systémy základne dokázali vystreliť ešte raz. V praxi tento systém zdvojnásobí efektivitu obranných systémov základne.\"\n  STR_MIND_SHIELD_UFOPEDIA: \"Keďže mimozemské plavidlá využívajú na detekciu ľudí ich mozgové vlny, potom najlepším opatrením bude mozgové vlny ukryť. Toto zariadenie drasticky zníži schopnosť mimozemšťanov na odhalenie základní X-Com.\"\n  STR_PSIONIC_LABORATORY_UFOPEDIA: \"V psionickom laboratóriu dokážeme odhaliť psionický potenciál vojakov na základni. Rovnako im v tomto zariadení dokážeme dať potrebný výcvik, ktorý zlepší tieto ich schopnosti. Každé laboratórium môže trénovať najviac desať vojakov. Na výcvik sa vojaci hlásia na konci každého mesiaca. Psionické schopnosti spolu s využitím zosilňovača psionických síl (Psi-Amp) sa dajú využiť na psionické útoky behom boja.\"\n  STR_HYPER_WAVE_DECODER_UFOPEDIA: \"Mimozemská komunikácia je založená na super-dimenzionálnych vlnách, ktoré prekonávajú vzdialenosť takmer okamžite. Dekódovacie oddelenie zachytáva prenos UFO a dekóduje informácie. Takto odhalí typ UFA, mimozemskú rasu a typ aktivity.\"\n  STR_HANGAR_UFOPEDIA: \"V každom hangári môže byť umiestnené jedno plavidlo. Obsahuje zariadenia pre údržbu, tankovanie a opravu plavidiel X-Com. Každé plavidlo na základni musí mať priradený vlastný hangár, ktorý nemôže byť využívaný iným plavidlom, ani keď je priradené plavidlo na misii.\"\n  STR_PISTOL_UFOPEDIA: \"Štandardná poloautomatická X-Com pištoľ s kapacitou na 12 nábojov.\"\n  STR_RIFLE_UFOPEDIA: \"Presná puška s laserovým zameriavaním využíva muníciu ráže 6.7mm v zásobníkoch po 20 nábojov. \"\n  STR_HEAVY_CANNON_UFOPEDIA: \"Ťažký kanón je zničujúca aj keď veľmi ťažkopádna zbraň. Jeho všestrannosť vychádza z toho, že dokáže využiť tri druhy munície - prieraznú, zápalnú a výbušnú.\"\n  STR_AUTO_CANNON_UFOPEDIA: \"Rotačný kanón kombinuje všestranosť a silu ťažkého kanónu s rýchlou automatickou streľbou.\"\n  STR_ROCKET_LAUNCHER_UFOPEDIA: \"Raketomet využíva systém laserového navádzania, pre ktorý je možné využiť tri druhy rakiet rôznej veľkosti.\"\n  STR_LASER_PISTOL_UFOPEDIA: \"Laserová pištoľ je výsledkom efektívneho využitia novej technológie. Má vlastnosti štandardnej pištole, ale s väčšou kadenciou a presnejšou streľbou.\"\n  STR_LASER_RIFLE_UFOPEDIA: \"Laserová puška je silnejšia a presnejšia verzia vychádzajúca z predchádzajúceho dizajnu laserovej pištole.\"\n  STR_HEAVY_LASER_UFOPEDIA: \"Ťažký laser je ťažkopádny, ale veľmi efektívny.\"\n  STR_GRENADE_UFOPEDIA: \"Štandardný granát s presným a sofistikovaným systémom odistenia a časovania, ktorý umožňuje precíznu kontrolu odpalu.\"\n  STR_SMOKE_GRENADE_UFOPEDIA: \"Dymovnice môžu poskytnúť krytie v otvorených priestoroch a vypätých bojových situáciách. Používajte opatrne, pretože ich výhod môže využiť aj protivník.\"\n  STR_PROXIMITY_GRENADE_UFOPEDIA: \"Mína môže byť odhodená ako bežný granát avšak spustí sa až pri zaregistrovaní neďalekého pohybu po tom čo pristane. Pre manipuláciu s týmto zariadením je potrebná veľká zručnosť a opatrnosť.\"\n  STR_HIGH_EXPLOSIVE_UFOPEDIA: \"Táto výbušnina by mala byť použitá len na demolačné účely. Zamedzte prístup osobám na miesto demolácie.\"\n  STR_MOTION_SCANNER_UFOPEDIA: \"Toto sofistikované zariadenie využíva množstvo čidiel a pokročilých algoritmov, ktoré dokážu identifikovať pohyb nepriateľských jednotiek v oblasti. Avšak jeho efektívne používanie vyžaduje prax. Obrazovka detektora zobrazuje šípku v strednej časti predstavujúcu smer, ktorým je vojak otočený (sever je na vrchu). Blikajúce body ukazujú na jednotku, ktorá sa nedávno pohla. Veľké jednotky alebo rýchlo sa pohybujúce jednotky budú tvoriť väčšie blikajúce body. Statické jednotky prístroj nedetekuje. \"\n  STR_MEDI_KIT_UFOPEDIA: \"Lekárnička kombinuje vlastnosti liečiaceho zariadenia so sedatívami a stimulantmi. Ak chcete lekárničku použiť musíte byť otočený tvárou k vojakovi, ktorý potrebuje ošetrenie. Ak je vojak v bezvedomí, musíte stáť nad jeho telom. Kliknutím na ikonu lekárničky a vybratím možnosti 'použiť lekárničku' z menu získate prístup k funkciám zariadenia.{NEWLINE}LIEČENIE> Červenou farbou vyznačené časti tela znamenajú vážne zranenia. Kliknutím na 'Liečenie' bude vyliečené jedno smrteľné zranenie a trocha zdravia pacienta.{NEWLINE}STIMULANT>Táto funkcia obnoví energiu vojaka a preberie vojaka v bezvedomí. Aby ste mohli oživiť vojaka v bezvedomí je potrebné stáť priamo nad jeho telom.{NEWLINE}SEDATÍVA>Táto funkcia obnoví morálku vašich ranených vojakov až do ekvivalentu strateného zdravia vojaka.\"\n  STR_PSI_AMP_UFOPEDIA: \"Psi-amp (zosilovač psionických schopností) môže byť použitý len vojakmi, ktorý majú psionické schopnosti. Počas boja, kliknite na Psi-amp, vyberte typ útoku a vyberte cieľovú jednotku. Poznáme dva druhy psionických útokov:{NEWLINE}PANIKA> Úspešný útok zníži morálku cieľa, čo môže spôsobiť, že jednotka spanikári.{NEWLINE}OVLÁDANIE MYSLE> Ak je ovládnutie úspešné, získate okamžitú kontrolu nad nepriateľskou jednotkou, akoby to bola vaša vlastná. Tento druh útoku je však náročnejší na úspešné použitie.\"\n  STR_STUN_ROD_UFOPEDIA: \"Toto zariadenie môže byť použité len v boji na blízko, pomocou elektrických šokov omráči živý organizmus bez toho aby ho zabilo.\"\n  STR_MIND_PROBE_UFOPEDIA: \"Sonda mysle je mimozemským komunikačným zariadením, ktoré sa používa na extrahovanie informácií priamo z mozgových vĺn. Jednotky X-Com môžu použiť toto zariadenie v boji pre zobrazenie charakteristík mimozemšťanov. Používa sa kliknutím na sondu mysle, vybraním možnosti 'použiť' a následným kliknutím kurzoru na mimozemšťana.\"\n  STR_PLASMA_PISTOL_UFOPEDIA: \"Plazmové pištole sú smrtiace zbrane založené na časticiach urýchlených v dočasnom antigravitačnom poli.\"\n  STR_PLASMA_RIFLE_UFOPEDIA: \"Táto nesmierne účinná zbraň zničujúcej sily je založená na časticiach urýchlených v dočasnom antigravitačnom poli.\"\n  STR_HEAVY_PLASMA_UFOPEDIA: \"Táto nesmierne účinná zbraň zničujúcej sily je založená na časticiach urýchlených v dočasnom antigravitačnom poli.\"\n  STR_BLASTER_LAUNCHER_UFOPEDIA: \"Toto je mimozemský odpaľovač rakiet, ktorý vystreľuje rakety nazývané 'fúzna bomba'. Fúzna bomba je inteligentne navádzaná zbraň. Pred jej vystrelením je potrebné zadať cieľové body, ktoré určia jej trajektóriu a následne potvrdiť ikonou výstrelu.\"\n  STR_SMALL_LAUNCHER_UFOPEDIA: \"Malý odpaľovač, ktorý slúži na vystreľovanie malých omračujúcich bômb. Veľmi užitočný pri chytaní živých mimozemšťanov.\"\n  STR_ALIEN_GRENADE_UFOPEDIA: \"Toto zariadenie funguje rovnako ako pozemský granát - s tým rozdielom, že mimozemský granát je niekoľkonásobne ničivejší.\"\n  STR_SMALL_SCOUT: \"Malý prieskumník\"\n  STR_MEDIUM_SCOUT: \"Stredne veľký prieskumník\"\n  STR_LARGE_SCOUT: \"Veľký prieskumník\"\n  STR_HARVESTER: \"Kombajn\"\n  STR_ABDUCTOR: \"Abduktor\"\n  STR_TERROR_SHIP: \"Teroristická loď\"\n  STR_BATTLESHIP: \"Bojová loď\"\n  STR_SUPPLY_SHIP: \"Zásobovacia loď\"\n  STR_RATING: \"HODNOTENIE> {0}\"\n  STR_RATING_TERRIBLE: \"PRÍŠERNÉ!\"\n  STR_RATING_POOR: \"SLABÉ!\"\n  STR_RATING_OK: \"OK\"\n  STR_RATING_GOOD: \"DOBRÉ!\"\n  STR_RATING_EXCELLENT: \"VÝBORNÉ!\"\n  STR_SCORE: \"BODY\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"MESAČNÁ SPRÁVA PROJEKTU X-COM\"\n  STR_MONTH: \"Mesiac> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"Rada národov financiujúca projekt je zatiaľ spokojná s vašim napredovaním.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"Rada národov financujúca projekt X-Com je spokojná s vašimi výbornými výsledkami. Pokračujte v dobre odvádzanej práci.\"\n  STR_COUNCIL_IS_DISSATISFIED: \"Rada zaisťujúca financovanie projektu je nespokojná s vaším napredovaním. Musíte zvýšiť efektivitu akcií podnikaných proti mimozemskej hrozbe, inak riskujete okamžité ukončenie celého projektu.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"V boji s mimozemšťanmi si zlyhal. Rada členských štátov sa bohužiaľ rozhodla ukončiť projekt X-Com. Každý štát sa teraz bude musieť vysporiadať so situáciou vlastnými prostriedkami. Môžeme len dúfať, že s týmito zjavne nepriateľskými silami nájdeme spôsob akým spor urovnať, a že obyvateľstvo pristúpi na podmienky mimozemských návštevníkov.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} je obzvlášť spokojné so schopnosťou vašej organizácie vysporiadať sa s mimozemskou hrozbou a súhlasili s navýšením financovania.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} sú čiastočne spokojné s vašim pokrokom s vysporiadaním sa s miestnymi vpádmi UFO a rozhodli sa navýšiť svoje finančné príspevky.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} a {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} nie je spokojná s Vašou schopnosťou vysporiadať sa s mimozemskou aktivitou na ich území a preto sa rozhodli, že znížia svoje financovanie.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} nie sú spokojní s Vašou schopnosťou vysporiadať sa s mimozemskou aktivitou na ich území a preto sa rozhodli, že znížia svoje financovanie.\"\n  STR_KNOTS: \"{0} uzlov\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} podpísal tajnú dohodu s neznámymi mimozemskými silami a odstúpil od projektu.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} podpísali tajnú dohodu s neznámymi mimozemskými silami a odstúpili od projektu.\"\n  STR_MONTHLY_RATING: \"Mesačné hodnotenie> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Zmena financovania> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"Rada zaisťujúca financovanie projektu nie je spokojná s vašou finančnou situáciou. Musíte redukovať dlhy pod $1 milión inak bude projekt ukončený.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"DEKÓDOVANÉ VYSIELANIE HYPER-VĹN\"\n  STR_CRAFT_TYPE: \"TYP PLAVIDLA\"\n  STR_RACE: \"DRUH\"\n  STR_MISSION: \"MISIA\"\n  STR_ZONE: \"ZÓNA\"\n  STR_ALLOCATE_RESEARCH: \"Rozvrhnúť výskum\"\n  STR_ALLOCATE_MANUFACTURE: \"Naplánovať výrobu\"\n  STR_NEW_YORK: \"New York\"\n  STR_WASHINGTON: \"Washington\"\n  STR_LOS_ANGELES: \"Los Angeles\"\n  STR_MONTREAL: \"Montreal\"\n  STR_HAVANA: \"Havana\"\n  STR_MEXICO_CITY: \"Mexico City\"\n  STR_CHICAGO: \"Chicago\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_DALLAS: \"Dallas\"\n  STR_BRASILIA: \"Brazília\"\n  STR_BOGOTA: \"Bogota\"\n  STR_BUENOS_AIRES: \"Buenos Aires\"\n  STR_SANTIAGO: \"Santiago\"\n  STR_RIO_DE_JANEIRO: \"Rio De Janeiro\"\n  STR_LIMA: \"Lima\"\n  STR_CARACAS: \"Caracas\"\n  STR_LONDON: \"Londýn\"\n  STR_PARIS: \"Paríž\"\n  STR_BERLIN: \"Berlín\"\n  STR_MOSCOW: \"Moskva\"\n  STR_ROME: \"Rím\"\n  STR_MADRID: \"Madrid\"\n  STR_BUDAPEST: \"Budapešť\"\n  STR_LAGOS: \"Lagos\"\n  STR_CAIRO: \"Káhira\"\n  STR_CASABLANCA: \"Casablanca\"\n  STR_PRETORIA: \"Pretória\"\n  STR_NAIROBI: \"Nairobi\"\n  STR_CAPE_TOWN: \"Kapské Mesto\"\n  STR_KINSHASA: \"Kinshasa\"\n  STR_ANKARA: \"Ankara\"\n  STR_DELHI: \"Dillí\"\n  STR_KARACHI: \"Karáči\"\n  STR_BAGHDAD: \"Bagdad\"\n  STR_TEHRAN: \"Teherán\"\n  STR_BOMBAY: \"Bombaj\"\n  STR_CALCUTTA: \"Kalkata\"\n  STR_TOKYO: \"Tokyo\"\n  STR_BEIJING: \"Peking\"\n  STR_BANGKOK: \"Bangkok\"\n  STR_MANILA: \"Manilla\"\n  STR_SEOUL: \"Soul\"\n  STR_SINGAPORE: \"Singapur\"\n  STR_JAKARTA: \"Jakarta\"\n  STR_SHANGHAI: \"Šanghaj\"\n  STR_HONG_KONG: \"Hong Kong\"\n  STR_NOVOSIBIRSK: \"Novosibirsk\"\n  STR_CANBERRA: \"Canberra\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_MELBOURNE: \"Melbourne\"\n  STR_PERTH: \"Perth\"\n  STR_PSI_TRAINING: \"Psionický tréning\"\n  STR_PSIONIC_TRAINING: \"PSIONICKÝ TRÉNING\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Zvyšná kapacita Psi-labu> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"Psionická{NEWLINE}odolnosť\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"PSI schopnosť{NEWLINE}/zlepšenie\"\n  STR_PSI_AMP: \"Psi-Amp\"\n  STR_IN_TRAINING: \"V{NEWLINE}výcviku?\"\n  STR_TARGETTED_BY: \"ZACIEĽENÝ:\"\n  STR_WEAPONS_CREW_HWPS: \"ZBRANE/{NEWLINE}POSÁDKA/ŤZS\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"má málo paliva,{NEWLINE}sa vracia na základňu\"\n  STR_SOLDIER_LIST: \"Zoznam vojakov\"\n  STR_RANK_: \"HODNOSŤ> {ALT}{0}\"\n  STR_MISSIONS: \"MISIE> {ALT}{0}\"\n  STR_KILLS: \"ZABITIA> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"ZOTAVENIE> {ALT}{0}\"\n  STR_TIME_UNITS: \"AKČNÉ BODY\"\n  STR_STAMINA: \"VÝDRŽ\"\n  STR_HEALTH: \"ZDRAVIE\"\n  STR_BRAVERY: \"UDATNOSŤ\"\n  STR_REACTIONS: \"REAKCIE\"\n  STR_FIRING_ACCURACY: \"PRESNOSŤ STREĽBY\"\n  STR_THROWING_ACCURACY: \"PRESNOSŤ VRHU\"\n  STR_STRENGTH: \"SILA\"\n  STR_PSIONIC_STRENGTH: \"PSIONICKÁ ODOLNOSŤ\"\n  STR_PSIONIC_SKILL: \"PSIONICKÁ SCHOPNOSŤ\"\n  STR_NEW_RANK: \"NOVÁ HODNOSŤ\"\n  STR_PROMOTIONS: \"Povýšenia\"\n  STR_SOLDIERS_UC: \"VOJSKO\"\n  STR_TANK_CANNON_UFOPEDIA: \"Automatické ťažké zbraňové systémy sú navrhnuté ako doplnok jednotky X-Com. Kombinácia veľkej palebnej sily a silného brnenia je vhodná pre boj v otvorených priestranstvách. Vždy sa presvedčite, že máte dostatok tankových striel vo vašich skladoch. Tanky sa nabíjajú automaticky po priradení k jednotke.\"\n  STR_TANK_ROCKET_LAUNCHER_UFOPEDIA: \"Tento automatický ťažký zbraňový systém je vyzbrojený odpaľovačom silných rakiet. Sila rakiet bude devastačná pre akéhokoľvek mimozemského nepriateľa. Uistite sa, že v skladoch máte dostatok raketovej munície pre ŤZS.\"\n  STR_TANK_LASER_CANNON_UFOPEDIA: \"Laserové zbrane sú užitočným prídavkom pre naše ŤZSy. Kombinuje vysokú kadenciu a silu a nie je obmedzená muníciou.\"\n  STR_HOVERTANK_PLASMA_UFOPEDIA: \"Poznatky mimozemských technológii vdýchli našim Ťažkým zbraňovým systémom (ŤZP) nový život. Manévrovateľnosť vo vzduchu a sila plazmových zbraní je smrteľnou kombináciou.\"\n  STR_HOVERTANK_LAUNCHER_UFOPEDIA: \"Anti-grav tank vyzbrojený odpaľovačom fúznych rakiet. Táto technológia je schopná vytvoriť neuveriteľnú deštrukčnú silu. Používajte z najvyššou opatrnosťou. Budete musieť vyrobiť fúzne rakety aby ste udržali tento ŤZS v plnej pohotovosti. Fúzna raketa je inteligentne navádzaná zbraň. Pred jej vystrelením je potrebné zadať cieľové body, ktoré určia jej trajektóriu a následne potvrdiť ikonou výstrelu.\"\n  STR_HEAVY_PLASMA_CLIP_UFOPEDIA: \"Toto kompaktné zariadenie slúži ako munícia pre Ťažký plazmový kanón. Obsahuje malé množstvo eléria.\"\n  STR_PLASMA_RIFLE_CLIP_UFOPEDIA: \"Tento malý objekt je používaný ako zdroj energie pre plazmovú pušku - stredne silnú mimozemskú zbraň. Obsahuje malé množstvo Eléria.\"\n  STR_PLASMA_PISTOL_CLIP_UFOPEDIA: \"Zdroj energie pre malú mimozemskú plazmovú pištoľ. Obsahuje malé množstvo Eléria - zdroj mimozemskej energie.\"\n  STR_STUN_BOMB_UFOPEDIA: \"Omračujúca bomba sa používa pri chytaní živých ľudských vzoriek, avšak rovnako môže byť použitá proti väčšine mimozemských druhov. Vystreľuje sa pomocou tzv. malého odpaľovača.\"\n  STR_ALIEN_RESEARCH_UFOPEDIA: \"Výskumné misie mimozemšťanov sú zamerané na zbieranie základných dát o Zemi a jej obyvateľoch. Na tento účel slúžia prevážne malé stroje, ktoré občas pristávajú na opustených miestach. Tento druh aktivít mimozemšťanov nepriťahuje pozornosť vlád a verejnosti, preto predstavuje najmenšiu hrozbu pre X-Com.\"\n  STR_ALIEN_HARVEST_UFOPEDIA: \"Zdá sa, že mimozemšťania dokážu využívať pozemskú faunu. Uneseným zvieratám, ktoré neskôr vrátili chýbali rôzne vnútorné orgány. Mrzačenie dobytka je často hlásené v súvislosti s pozorovaním UFO. Tento druh aktivít mimozemšťanov spôsobuje obavy v radoch vlády a vyvoláva strach v radoch obyvateľstva. Tento druh aktivít je najčastejšie sledovaný v poľnohospodárskych oblastiach. Teória, ktorá by naznačovala zmysel tejto 'mimozemskej žatvy' - zberu darov planéty Zem - naznačuje, že mimozemšťania pôvodne 'vysadili' flóru a faunu na planéte a teraz sa vrátili aby zožali jej plody.\"\n  STR_ALIEN_ABDUCTION_UFOPEDIA: \"Toto je najzákernejšia forma mimozemskej aktivity na Zemi. Únosy mimozemšťanmi sú hlásené z mnohých miest, bez ohľadu na pokusy mimozemšťanov vymazať zážitky z pamäti ľudí. Unášaní hlásia, že boli obeťami ponižujúcich fyzických výskumov, vrátane oplodnenia mimozemskými zárodkami a objektmi strašných genetických experimentov. Účel týchto aktivít sa zdá byť spojený s genetickými mutáciami a manipuláciou s vlastným gnetickým materiálom mimozemšťanov. Táto aktivita spôsobuje významný rozruch a odohráva sa v obývaných oblastiach alebo mestách.\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"Pozemská vláda môže byť infiltrovaná mimozemskými agentami, ktorí vyzerajú ako ľudia. Toto môže mať za dôsledok oficiálny kontakt medzi mimozemšťanmi a vládou na najvyššej úrovni. Vyvrcholenie tejto aktivity má za následok zvýšenie mimozemskej aktivity v blízkom okolí hlavných miest. Mimozemšťania sa budú pokúšať podpísať dohodu s pozemskou vládou ponúknutím poznatkov ich vysoko vyvinutej technológie. Výmenou za to budú požadovať, aby im vláda umožnila vykonávať ich aktivity na tomto území bez zásahu vlády. Tento typ mimozemskej aktivity je najhoršou hrozbou pre X-Com. Ak vláda pristúpi na dohodu, potom jej financovanie projektu X-Com prestane.\"\n  STR_ALIEN_BASE_UFOPEDIA: \"Mimozemšťania budujú tajné podzemné základne v odľahlých lokalitách Zeme. Výstavba základne začína prieskumnými letmi UFO, ktoré sú nasledované častejšou UFO aktivitou v momente keď mimozemšťania začnú s výstavbou základne. Tieto základne obsahujú experimentálne laboratória pre ľudských zajatcov a zásoby pre rozvoj ďalších aktivít v regióne. Prítomnosť základne generuje veľké množstvo hlásení aktivít mimozemšťanov bez prítomnosti UFO. Aby bol X-Com schopný detekovať základňu musí hliadkovacie lietadlo skúmať oblasť niekoľko hodín.\"\n  STR_ALIEN_TERROR_UFOPEDIA: \"Keď mimozemšťania terorizujú mesto vypustia do oblasti niekoľko špeciálnych jednotiek so smrtiacimi schopnosťami. Civilisti sú priamo ohrození a vlády donútené evakuovať celé oblasti. Hlavným cieľom týchto aktivít je vytvoriť čo najväčšiu verejnú hystériu, aby vlády tlačili na X-Com prípadným zrušením celého projektu.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"Ak sa stíhacím lietadlám X-Com darí úspešne zostreľovať UFO, potom môžu mimozemšťania pristúpiť k odvetným akciám. To môže mať za následok priamy útok na základňu X-Com. Odhaleniu základne sa dá predísť promptnou reakciou na výskyt UFO v okolí základne. V takom prípade je riziko útoku minimálne.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"Po tom ako mimozemšťania postavia na Zemi svoju základňu je táto zásobovaná v pravidelných intervaloch pomocou špeciálnych zásobovacích lodí. Ak je jedna z takýchto lodí detekovaná pri pristávaní, je viac než isté, že sa v okolí nachádza základňa mimozemšťanov.\"\n  STR_SMALL_SCOUT_UFOPEDIA: \"Táto malá loď je primárne určená na prieskum a výskum. Táto loď je predvojom väčších lodí a pripravuje pôdu pre začiatok mimozemských misií.\"\n  STR_MEDIUM_SCOUT_UFOPEDIA: \"Stredne veľké prieskumné plavidlo, ktoré nepredstavuje veľkú hrozbu pre pozemské sily. Obvykle predstavuje predvoj väčších mimozemských plavidiel.\"\n  STR_LARGE_SCOUT_UFOPEDIA: \"Najväčšia prieskumná loď mimozemšťanov je univerzálnym plavidlom využívaným na všetky druhy mimozemských misií. \"\n  STR_HARVESTER_UFOPEDIA: \"Kombajn má na spodnej strane vstup a je vyzbrojený zariadením na zbieranie dobytka alebo iných zvierat. Laserové skalpely sú využívané na extrahovanie potrebného materiálu, pričom zvyšky sú odhadzované späť na zem. Rovnako obsahuje skladové kontajnery pre časti tiel.\"\n  STR_ABDUCTOR_UFOPEDIA: \"Táto loď je vybavená vyšetrovacou miestnosťou, v ktorej sa vykonávajú strašné experimenty na ľudských subjektoch. Obeť je často paralyzovaná pomocou telepatických schopností, avšak po celý čas je na operačnom stole pri plnom vedomí. \"\n  STR_TERROR_SHIP_UFOPEDIA: \"Teroristická loď je vybavená zariadením, ktoré dokáže prenášať mimozemské teroristické zbrane a bytosti šľachtené pre tento účel. Je využívaná na prepravu týchto mimozemských teroristov do husto obývaných oblastí Zeme.\"\n  STR_BATTLESHIP_UFOPEDIA: \"Bojová loď je najväčším a najsilnejším mimozemským plavidlom. Je hlavnou loďou mimozemských misií, vybavená ničivými zbraňami a početnou posádkou.\"\n  STR_SUPPLY_SHIP_UFOPEDIA: \"Zásobovacia loď je používaná počas budovania základne mimozemšťanov alebo ako prostriedok zásobovania existujúcej základne. Prepravuje potravu mimozemšťanov rovnako ako reprodukčné komory.\"\n  STR_DISMANTLE: \"Rozobrať\"\n  STR_FACILITY_IN_USE: \"ZARIADENIE SA POUŽÍVA\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"ZARIADENIE NIE JE MOŽNÉ ROZOBRAŤ! {SMALLLINE}Všetky zariadenia v základni musia byť spojené s prístupovým výťahom.\"\n  STR_TRANSFER_ITEMS_TO: \"Presuň predmety do {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"CHÝBA ZADRŽIAVACIA CELA PRE MIMOZEMŠŤANOV!{SMALLLINE}Aby živí mimozemšťania prežili musia byť umiestnení v špeciálnej cele.\"\n  STR_AMOUNT_AT_DESTINATION: \"MNOŽSTVO{NEWLINE}V CIELI\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"Mimozemšťan zahynul, pretože nemáme zadržiavaciu celu pre mimozemšťanov\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"K DISPOZÍCII NIE SÚ DOSTATOČNÉ UBYTOVACIE KAPACITY!{SMALLLINE}Cieľová základňa nemá dostatok miesta v ubytovniach pre tím priradený k transportnému plavidlu.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"NEDOSTATOK MIESTA V SKLADOCH!{SMALLLINE}Cieľová základňa nemá dostatok skladových priestorov pre vybavenie, ktoré bolo pridelené tomuto plavidlu.\"\n  STR_ITEMS_ARRIVING: \"Dodané položky\"\n  STR_DESTINATION_UC: \"MIESTO URČENIA\"\n  STR_PISTOL: \"Pištoľ\"\n  STR_PISTOL_CLIP: \"Zásobník pištole\"\n  STR_RIFLE: \"Puška\"\n  STR_RIFLE_CLIP: \"Zásobník pušky\"\n  STR_HEAVY_CANNON: \"Ťažký kanón\"\n  STR_HC_AP_AMMO: \"ŤK-PR munícia\"\n  STR_HC_HE_AMMO: \"ŤK-EX munícia\"\n  STR_HC_I_AMMO: \"ŤK-ZAP munícia\"\n  STR_AUTO_CANNON: \"Rotačný kanón\"\n  STR_AC_AP_AMMO: \"RK-PR munícia\"\n  STR_AC_HE_AMMO: \"RK-EX munícia\"\n  STR_AC_I_AMMO: \"RK-ZAP munícia\"\n  STR_ROCKET_LAUNCHER: \"Raketomet\"\n  STR_SMALL_ROCKET: \"Malá raketa\"\n  STR_LARGE_ROCKET: \"Veľká raketa\"\n  STR_INCENDIARY_ROCKET: \"Zápalná raketa\"\n  STR_GRENADE: \"Granát\"\n  STR_SMOKE_GRENADE: \"Dymovnica\"\n  STR_PROXIMITY_GRENADE: \"Mína\"\n  STR_HIGH_EXPLOSIVE: \"Demolačná výbušnina\"\n  STR_STUN_ROD: \"Elektrický obušok\"\n  STR_HEAVY_PLASMA: \"Ťažký plazmový kanón\"\n  STR_HEAVY_PLASMA_CLIP: \"Zásobník ťažkej plazmy\"\n  STR_PLASMA_RIFLE: \"Plazmová puška\"\n  STR_PLASMA_RIFLE_CLIP: \"Zásobník plazmovej pušky\"\n  STR_PLASMA_PISTOL: \"Plazmová pištoľ\"\n  STR_PLASMA_PISTOL_CLIP: \"Zásobník plazmovej pištole\"\n  STR_BLASTER_LAUNCHER: \"Prenosný fúzny odpaľovač\"\n  STR_BLASTER_BOMB: \"Fúzna bomba\"\n  STR_SMALL_LAUNCHER: \"Malý odpaľovač\"\n  STR_STUN_BOMB: \"Omračujúca bomba\"\n  STR_ALIEN_GRENADE: \"Mimozemský granát\"\n  STR_ELERIUM_115: \"Elerium-115\"\n  STR_MIND_PROBE: \"Sonda mysle\"\n  STR_SECTOID_CORPSE: \"Mŕtvola sectoida\"\n  STR_SNAKEMAN_CORPSE: \"Mŕtvola snakemana\"\n  STR_ETHEREAL_CORPSE: \"Mŕtvola ethereala\"\n  STR_MUTON_CORPSE: \"Mŕtvola mutona\"\n  STR_FLOATER_CORPSE: \"Mŕtvola floatera\"\n  STR_CELATID_CORPSE: \"Mŕtvola celatida\"\n  STR_SILACOID_CORPSE: \"Mŕtvola silacoida\"\n  STR_CHRYSSALID_CORPSE: \"Mŕtvola chryssalida\"\n  STR_REAPER_CORPSE: \"Mŕtvola reapera\"\n  STR_SECTOPOD_CORPSE: \"Pozostatky sectopoda\"\n  STR_CYBERDISC_CORPSE: \"Pozostatky kyberdisku\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"Nedostatok munície pre ŤZS{SMALLLINE}Každý ŤZS vyžaduje {0} {1}.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Nedostatok vybavenia pre plné prezbrojenie jednotky\"\n  STR_MARS_CYDONIA_LANDING: \"Mars: Pristátie v Cydonii\"\n  STR_MARS_CYDONIA_LANDING_BRIEFING: \"Vaša loď triedy Avenger pristála v regióne Cydonia na povrchu Marsu. Naše informácie naznačujú, že v jednej z pyramídových konštrukcií sa nachádza zelený prístupový výťah do podzemného komlexu. Keď zoradíte svoje jednotky v oblasti výťahu, kliknite na ikonu 'zrušiť misiu' pre pokračovanie do ďalšej časti mimozemského komplexu. \"\n  STR_MARS_THE_FINAL_ASSAULT: \"Mars: Finálny útok\"\n  STR_MARS_THE_FINAL_ASSAULT_BRIEFING: \"Výťah v pyramíde vezie tvojich bojom unavených vojakov hlboko pod povrch planéty. Dostali sa priamo do srdca veľkého komplexu tunelov a miestností. Mimozemský mozog sa skrýva niekde v tomto labyrinte. Ak chceme zachrániť Zem od zotročenia mimozemšťanmi, musí byť hlavný mozog zničený.{NEWLINE}{NEWLINE}Veľa šťastia!\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Najprv musíte vynájsť{NEWLINE}{0}{NEWLINE}aby ste moholi vyrobiť{NEWLINE}{1}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"Mimozemšťania zničili nechránenú základňu {0}\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"Agenti X-Com objavili umiestnenie základne mimozemšťanov v {0}\"\n  STR_STANDOFF: \"ODSTUP\"\n  STR_CAUTIOUS_ATTACK: \"OPATRNÝ ÚTOK\"\n  STR_STANDARD_ATTACK: \"ŠTANDARDNÝ ÚTOK\"\n  STR_AGGRESSIVE_ATTACK: \"AGRESÍVNY ÚTOK\"\n  STR_DISENGAGING: \"RUŠÍM PRENASLEDOVANIE\"\n  STR_UFO_HIT: \"ZÁSAH UFO!\"\n  STR_UFO_CRASH_LANDS: \"UFO HAVAROVALO!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Minimalizovať len pri odstupe\"\n  STR_UFO_RETURN_FIRE: \"UFO OPÄTUJE PAĽBU!\"\n  STR_INTERCEPTOR_DAMAGED: \">>> STÍHACIE LIETADLO POŠKODENÉ <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> STÍHAČKA BOLA ZNIČENÁ <<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"UFO UNIKÁ STÍHACIEMU LIETADLU!\"\n  STR_ALIENS_TERRORISE: \"MIMOZEMŠŤANIA TERORIZUJÚ\"\n  STR_LONG_RANGE_DETECTION: \"Detekcia dlhého dosahu\"\n  STR_STORES_UC: \"SKLADY\"\n  STR_DIFFICULTY_LEVEL: \"Stupeň obtiažnosti\"\n  STR_INTERCEPT: \"STÍHANIE\"\n  STR_BASES: \"ZÁKLADNE\"\n  STR_GRAPHS: \"GRAFY\"\n  STR_UFOPAEDIA_UC: \"UFOPÉDIA\"\n  STR_OPTIONS_UC: \"NASTAVENIA\"\n  STR_FUNDING_UC: \"FINANCOVANIE\"\n  STR_5_SECONDS: \"5 sek\"\n  STR_1_MINUTE: \"1 min\"\n  STR_5_MINUTES: \"5 min\"\n  STR_30_MINUTES: \"30 min\"\n  STR_1_HOUR: \"1 hod\"\n  STR_1_DAY: \"1 deň\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"Rozpis výkonu X-Com\"\n  STR_ENTER_NAME: \"Zadaj meno\"\n  STR_PERFORMANCE_RATING: \"Hodnotenie výkonu\"\n  STR_VICTORY_DATE: \"Dátum víťazstva\"\n  STR_ELECTRO_FLARE: \"Svetlica\"\n  STR_ELECTRO_FLARE_UFOPEDIA: \"Po odhodení, toto kompaktné zariadenie produkuje silné, jasné svetlo, ktoré dokáže počas nočných misií odhaliť nepriateľské jednotky v okolí svetlice. \"\n  STR_MONTHLY_COSTS: \"Mesačné náklady\"\n  STR_CRAFT_RENTAL: \"Prenájom lietadiel\"\n  STR_SALARIES: \"Výplaty\"\n  STR_BASE_MAINTENANCE: \"Údržba základne\"\n  STR_COST_PER_UNIT: \"Jedn. cena\"\n  STR_QUANTITY: \"Množstvo\"\n  STR_TOTAL: \"Celkovo\"\n  STR_IN_PSIONIC_TRAINING: \"V psionickom tréningu\"\n  STR_BLASTER_BOMB_UFOPEDIA: \"Toto zariadenie je vysoko explozívnou raketou, ktorá ma inteligentný navádzací systém. Je odpaľovaná pomocou prenosného fúzneho odpaľovača.\"\n  STR_FRONT_ARMOR: \"Predná zbroj\"\n  STR_LEFT_ARMOR: \"Ľavá zbroj\"\n  STR_RIGHT_ARMOR: \"Pravá zbroj\"\n  STR_REAR_ARMOR: \"Zadná zbroj\"\n  STR_UNDER_ARMOR: \"Spodná zbroj\"\n  STR_ROUNDS: \"Náboje\"\n  STR_UNIT: \"JEDNOTKA> {0}\"\n  STR_ENERGY: \"ENERGIA\"\n  STR_MORALE: \"MORÁLKA\"\n  STR_ARMOR_: \"Zbroj > {0}\"\n  STR_FRONT_ARMOR_UC: \"PREDNÁ ZBROJ\"\n  STR_LEFT_ARMOR_UC: \"ĽAVÁ ZBROJ\"\n  STR_RIGHT_ARMOR_UC: \"PRAVÁ ZBROJ\"\n  STR_REAR_ARMOR_UC: \"ZADNÁ ZBROJ\"\n  STR_SKILLS: \"SCHOPNOSTI> {0}\"\n  STR_LEVEL: \"ÚROVEŇ> {0}\"\n  STR_HEAD: \"HLAVA\"\n  STR_TORSO: \"TELO\"\n  STR_RIGHT_ARM: \"PRAVÁ PAŽA\"\n  STR_LEFT_ARM: \"ĽAVÉ RAMENO\"\n  STR_RIGHT_LEG: \"PRAVÁ NOHA\"\n  STR_LEFT_LEG: \"ĽAVÁ NOHA\"\n  STR_PAIN_KILLER: \"SEDATÍVA\"\n  STR_STIMULANT: \"STIMULANT\"\n  STR_HEAL: \"LIEČENIE\"\n  STR_TIME_UNITS_SHORT: \"AB>{ALT}{0}\"\n  STR_WEIGHT: \"Váha>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"REA>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"PSIS>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"PSIO>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Mimozemský artefakt\"\n  STR_AMMO_ROUNDS_LEFT: \"NÁBOJE:{NEWLINE}OSTÁVA{NEWLINE}VÝSTRELOV={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Sedatíva>{ALT}{0}{ALT}{NEWLINE}Stimulant>{ALT}{1}{ALT}{NEWLINE}Liečenie>{ALT}{2}\"\n  STR_THROW: \"Hodiť\"\n  STR_AUTO_SHOT: \"Auto-streľba\"\n  STR_SNAP_SHOT: \"Bez mierenia\"\n  STR_AIMED_SHOT: \"Mierená strela\"\n  STR_STUN: \"Omráčiť\"\n  STR_PRIME_GRENADE: \"Odistiť granát\"\n  STR_USE_SCANNER: \"Použi detektor\"\n  STR_USE_MEDI_KIT: \"Použi lekárničku\"\n  STR_LAUNCH_MISSILE: \"Vystreliť raketu\"\n  STR_ACCURACY_SHORT: \"PRE>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Nedostatok akčných bodov!\"\n  STR_NOT_ENOUGH_ENERGY: \"Nedostatok energie!\"\n  STR_NO_ROUNDS_LEFT: \"Chýba munícia!\"\n  STR_NO_AMMUNITION_LOADED: \"Nie je nabitá!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Munícia nevhodná pre túto zbraň!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"Zbraň je už nabitá!\"\n  STR_NO_LINE_OF_FIRE: \"Prekážka v dráhe strely!\"\n  STR_GRENADE_IS_ACTIVATED: \"Granát je odistený!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Granát zaistený!\"\n  STR_THERE_IS_NO_ONE_THERE: \"Nikto tam nie je!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Nie je možné používať mimozemský artefakt keď nie je preskúmaný našimi vedcami!\"\n  STR_OUT_OF_RANGE: \"Mimo dosah!\"\n  STR_UNABLE_TO_THROW_HERE: \"Nedá sa odhodiť!\"\n  STR_SET_TIMER: \"Nastav časovač\"\n  STR_HIDDEN_MOVEMENT: \"SKRYTÝ POHYB\"\n  STR_TURN: \"ŤAH> {0}\"\n  STR_SIDE: \"STRANA> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Stlač tlačidlo pre pokračovanie\"\n  STR_MIND_CONTROL: \"Ovládnutie mysle\"\n  STR_PANIC_UNIT: \"Panika\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Úspešný útok na morálku\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Ovládnutie mysle bolo úspešné\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}podľahol amoku\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}podlahla amoku\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE} spanikáril\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}spanikárila\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Mimozemšťania\"\n  STR_RIGHT_HAND: \"PRAVÁ RUKA\"\n  STR_LEFT_HAND: \"ĽAVÁ RUKA\"\n  STR_RIGHT_SHOULDER: \"PRAVÉ RAMENO\"\n  STR_LEFT_SHOULDER: \"ĽAVÉ RAMENO\"\n  STR_BACK_PACK: \"RUKSAK\"\n  STR_BELT: \"OPASOK\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}je ovládaný mimozemšťanmi\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}je pod kontrolou mimozemšťanov\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}stratil vedomie\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}je v bezvedomí\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}zomrel na smrteľné zranenia\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}zomrela na smrtelné zranenie\"\n  STR_USE_MIND_PROBE: \"Použi sondu mysle\"\n  STR_FATAL_WOUNDS: \"SMRTEĽNÉ ZRANENIA\"\n  STR_UNDER_ARMOR_UC: \"SPODNÁ ZBROJ\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Akčné body rezervované pre rýchly výstrel\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Akčné body rezervované pre auto-streľbu\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Akčné body rezervované pre mierenú strelu\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Akčné body rezervované pre pokľaknutie\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"AB rezervované pre pokľaknutie a streľbu\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} jednotka v X-Com transportéri\"\n    few: \"{N} jednotky v X-Com transportéri\"\n    many: \"{N} jednotiek v X-Com transportéri\"\n    other: \"{N} jednotiek v X-Com transportéri\"\n  STR_UNITS_OUTSIDE:\n    one: \"{N} jednotka ostala vonku\"\n    few: \"{N} jednotky ostalo vonku\"\n    many: \"{N} jednotiek ostalo vonku\"\n    other: \"{N} jednotiek ostalo vonku\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} jednotka pri vstupe\"\n    few: \"{N} jednotky pri vstupe\"\n    many: \"{N} jednotiek pri vstupe\"\n    other: \"{N} jednotiek pri vstupe\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} jednotka v cieľovej oblasti\"\n    few: \"{N} jednotky v cieľovej oblasti\"\n    many: \"{N} jednotiek v cieľovej oblasti\"\n    other: \"{N} jednotiek v cieľovej oblasti\"\n  STR_ABORT_MISSION_QUESTION: \"Ukončiť misiu?\"\n  STR_CORPSE: \"Mŕtvola\"\n  STR_UNLOAD_CRAFT: \"Vybrať náboje\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}bol zabitý\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}bola zabitá.\"\n  STR_HIT_MELEE: \"Zásah\"\n  STR_GROUND: \"ZEM\"\n  STR_LIVING_QUARTERS_PLURAL: \"Ubytovacie priestory\"\n  STR_LIST_ITEM: \"POLOŽKA\"\n  STR_PERSONAL_ARMOR_UFOPEDIA: \"S využitím novo objavených mimozemských zliatin sme vytvorili novú zbroj, ktorá dokáže lepšie ochrániť našich vojakov v boji s mimozemskou hrozbou.\"\n  STR_POWER_SUIT_UFOPEDIA: \"Nová výkonná zbroj pre vojakov je napájaná z elériového generátora. Značne zosiľňuje rýchlosť a silu nositeľa a poskytuje zatiaľ najlepšiu ochranu pre naše jednotky.\"\n  STR_FLYING_SUIT_UFOPEDIA: \"Vylepšená verzia energetickej zbroje obsahujúca mimozemskú technológiu antigravitačnej navigácie, umožňujúca úplnu slobodu pohybu po bojisku.\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"Všetci mimozemšťania zahynuli pri havárii,{NEWLINE}Zahajujem automatické prehliadnutie miesta havárie.\"\n  STR_RESET: \"Reset\"\n  STR_MEMORIAL: \"Pamätník\"\n  STR_DATE_UC: \"DÁTUM\"\n  STR_SOLDIERS_RECRUITED_UC: \"NAVERBOVANÝCH VOJAKOV>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"VOJENSKÉ STRATY>{ALT}{0}\"\n  MAP_CULTA: \"Farma\"\n  MAP_FOREST: \"Les\"\n  MAP_JUNGLE: \"Džungľa\"\n  MAP_MOUNT: \"Hora\"\n  MAP_DESERT: \"Púšť\"\n  MAP_POLAR: \"Polárna\"\n  MAP_URBAN: \"Mesto\"\n  MAP_UBASE: \"Základňa mimozemšťanov\"\n  MAP_XBASE: \"Základňa X-Com\"\n  MAP_MARS: \"Mars\"\n  STR_MIXED: \"Zmiešaný\"\n  STR_REMOVE_SELECTED: \"Odstráň označené\"\n  STR_LIVE_ALIENS: \"Živí{NEWLINE}jedinci\"\n  STR_DEAD_ALIENS: \"Nepotrební{NEWLINE}jedinci\"\n  STR_UNDER_INTERROGATION: \"Vo{NEWLINE}výskume\"\n  STR_CONTAINMENT_EXCEEDED: \"LIMIT ZADRŽIAVACEJ CELY PRE MIMOZEMŠŤANOV BOL PREKROČENÝ!{SMALLLINE}Nedostatok miesta v {0}. Je potrebné odstrániť prevyšujúcich mimozemšťanov z cely (tí potom zahynú).\"\n  STR_MANAGE_CONTAINMENT: \"Správa zadržiavacej cely\"\n  STR_STORAGE_EXCEEDED: \"KAPACITA SKLADOV BOLA PREKROČENÁ!{SMALLLINE}Máme nedostatok miesta v {0}. Musíte predať nadbytočné predmety.\"\n  STR_GO_TO_BASE: \"Do základne\"\n  STR_MELEE_ACCURACY: \"BOJ Z BLÍZKA\"\n  STR_SELL_PRODUCTION: \"PREDAŤ\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Obe ruky musia byť voľné!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Nedostatok predmetov pre kopírovanie šablóny!\"\n  STR_UNLOAD_WEAPON: \"Vybiť zbraň\"\n  STR_ALL_ITEMS: \"Všetky predmety\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"NA PALUBU SA NEZMESTÍ VIAC VYBAVENIA!{SMALLLINE}Máte povolenú maximálne {N} položku vybavenia na palube tohto stroja.\"\n    few: \"NA PALUBU SA NEZMESTÍ VIAC VYBAVENIA!{SMALLLINE}Máte povolených maximálne {N} položiek vybavenia na palube tohto stroja.\"\n    many: \"NA PALUBU SA NEZMESTÍ VIAC VYBAVENIA!{SMALLLINE}Máte povolených maximálne {N} položiek vybavenia na palube tohto stroja.\"\n    other: \"NA PALUBU SA NEZMESTÍ VIAC VYBAVENIA!{SMALLLINE}Máte povolených maximálne {N} položiek vybavenia na palube tohto stroja.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}RIADIACE CENTRUM BOLO ZNIČENÉ{NEWLINE}Dostaňte sa do vstupnej oblasti a ukončite misiu.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"X-Com nemôže budovať svoje zariadenia pod vodou\"\n  STR_LEVEL_SHORT: \"{0}\"\n  STR_PERSONNEL: \"Personál\"\n  STR_CRAFT_ARMAMENT: \"Lietadlá a výzbroj\"\n  STR_COMPONENTS: \"Komponenty\"\n  STR_SOLDIERS_RECRUITED: \"Naverbovaní vojaci\"\n  STR_SOLDIERS_LOST: \"Vojenské straty\"\n  STR_TOTAL_UFOS: \"Zistených UFO\"\n  STR_TOTAL_ALIEN_BASES: \"Objavených základní mimozemšťanov\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"PSO\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"PSS\"\n  FEMALE_CIVILIAN: \"Civilista, Žena\"\n  MALE_CIVILIAN: \"Civilista, Muž\"\n  CYBERDISC_WEAPON: \"Zbraň kyberdisku\"\n  REAPER_WEAPON: \"Zbraň reapera\"\n  CHRYSSALID_WEAPON: \"Zbraň chryssalida\"\n  CELATID_WEAPON: \"Zbraň celatida\"\n  SILACOID_WEAPON: \"Zbraň silacoida\"\n  SECTOPOD_WEAPON: \"Zbraň sectopoda\"\n  ZOMBIE_WEAPON: \"Zbraň zombieho\"\n  ALIEN_PSI_WEAPON: \"Mimozemská psi zbraň\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/sv.yml",
    "content": "sv:\n  STR_AVENGER_UFOPEDIA: \"TRANSPORTER OCH RYMDSTRIDSSKEPP. DEN ULTIMATA REPLIKERINGEN AV UTOMJORDISK TEKNIK.\"\n  STR_INTERCEPTOR_UFOPEDIA: \"LUFTSTRIDSPLAN MED DUBBLA PULSDETONATIONSMOTORER OCH SPECIALSKYDDADE ELEKTRONIKSYSTEM. DEN BÄSTA TEKNOLOGIN JORDEN KAN ERBJUDA.\"\n  STR_LIGHTNING_UFOPEDIA: \"TRANSPORTER OCH STRIDSFARKOST. EN GRUBBIG MEN EFFEKTIV REPLIKATION AV UTOMJORDISKA DRIVSYSTEM.\"\n  STR_SKYRANGER_UFOPEDIA: \"TRUPPTRANSPORT. DEN SNABBASTE I SITT SLAG MED VERTIKAL LYFT- OCH LANDNINGSFÖRMÅGA (V.T.O.L.)\"\n  STR_FIRESTORM_UFOPEDIA: \"LUFTSTRIDSFARKOST. DETTA ENMANSJAKTPLAN REPLIKERAR DEN KLASSISKA FLYGANDE-TEFATS-DESIGNEN MED ETT CENTRALT DRIVSYSTEM.\"\n  STR_STINGRAY_UFOPEDIA: \"AVANCERAD LUFTSTRIDSMISSIL MED SPECIALSKYDDAD ELEKTRONIK.\"\n  STR_AVALANCHE_UFOPEDIA: \"LUFTSTRIDSMISSIL MED KÄRNVAPENSTRIDSSPETS, MEN EN EXTREM BÄRTYNGD.\"\n  STR_CANNON_UFOPEDIA: \"KRAFTFULL KANON SOM AVFYRAR PANSARBRYTANDE PROJEKTILER MED PENETRATIONSFÖRMÅGA PÅ UPP TILL 16 TUM STÅL.\"\n  STR_FUSION_BALL_UFOPEDIA: \"DETTA VAPEN SKJUTER EN BOLLFORMAD MISSIL DRIVEN AV EN ANTIMATERIA-REAKTOR. BOLLEN FÖRSTÖR MÅLET MED EN IMPLODERANDE GRAVITATIONSVÅGS.\"\n  STR_LASER_CANNON_UFOPEDIA: \"DENNA KONVENTIONELLA LASERKANON DRIVS AV EN REAKTIONSKAMMARE BASERAD PÅ ANTIMATERIA.\"\n  STR_PLASMA_BEAM_UFOPEDIA: \"GRAVITATIONSSTRÅLEN RIKTAR ETT IMPLODERANDE GRAVITATIONSFÄLT.\"\n  STR_SECTOID_UFOPEDIA: \"Sectoidernas hierarki sträcker sig från soldat till ledare med kraftfulla psioniska egenskaper. Dessa psioniska krafter kan användas för att demoralisera soldater i strid och till och med ta kontroll över deras hjärnor. Sectoiderna verkar främst utföra människorov och djurstympning. Kidnappningarna har som mål att utvinna genetiska material för korsbefruktning och utveckling av kloner för infiltration av människornas samhälle. Boskapen ger både näring och genetiskt material. Denna art verkar inriktad på att utveckla genetiska superhybrider för att stärka deras bikupeliknande samhälle.\"\n  STR_SECTOID_AUTOPSY: \"Obduktion av Sectoid\"\n  STR_SECTOID_AUTOPSY_UFOPEDIA: \"Obduktionen visar ett enklare matsmältningssystem och enkel kroppsstruktur. Hjärnan samt ögonen är välutvecklade och deras struktur tyder på genetisk manipulation eller mutation. Den lilla munnen och näsan verkar ha liten funktion. Simhuden mellan fingrarna tyder på ett vattenbaserat ursprung. Det finns inga reproduktionsorgan och inga tecken på hur de kan reproducera. De är antagligen en genetiskt tillverkad art.\"\n  STR_SNAKEMAN_UFOPEDIA: \"Denna art utvecklades i en extremt fientlig miljö. De är extremt tuffa och kan motstå extrema temperaturskillnader. Deras rörlighet beror på en ormlikande, stor \\\"fot\\\" som skyddar alla vitala organ. Deras mål verkar vara rent rövarinriktade och de verkar lyda under en högre vilja som styr deras militärliknande-räder på Jorden.\"\n  STR_SNAKEMAN_AUTOPSY: \"Obduktion av Ormman\"\n  STR_SNAKEMAN_AUTOPSY_UFOPEDIA: \"Skinnet är väldigt hårt och värmeresistant. Hjärt-kärl-systemet är del av muskelsystemet och använder den hydraliska principen för att röra sig. Den enda riktiga muskeln är \\\"hjärtat\\\". Det reproduktiva systemet verkar väldigt effektivt. Förökningen sker asexuellt eftersom varje ormman bär på upp till 50 ägg i sin kropp. Om de lämnas till att föröka sig kan denna art bli ett allvarligt hot mot livet på Jorden.\"\n  STR_ETHEREAL_UFOPEDIA: \"Denna varelse har skräckinjagande mentala krafter som tillåter telepatisk kommunikation och telekinetisk förmåga. Den ömtåliga kroppen hålls ihop av dess mentala krafter. Vi förstår inte hur dessa telekinetiska krafter fungerar eftersom de helt trotsar fysikens lagar. De dyker sällan upp på Jorden eftersom de föredrar att låta andra arter göra jobbet åt dem.\"\n  STR_ETHEREAL_AUTOPSY: \"Eterisk obduktion\"\n  STR_ETHEREAL_AUTOPSY_UFOPEDIA: \"Varelsen är fysiskt underutvecklad och verkar inkapabel att upprätthålla grundläggande livsfunktioner. Musklerna är allvarligt förtvinade och de inre organen är underutvecklade. Sinnesorganen inklusive ögonen verkar vara helt oanvändbara. Hjärnan är däremot välutvecklad och kräver en stor mängd av kroppens blod. Det är ett mysterium hur denna varelse kan överleva utan extern hjälp.\"\n  STR_MUTON_UFOPEDIA: \"Denna humanoida varelse är fysiskt stark och intelligent. Den har en särskild aptit för rått kött av alla slag som den behöver för att överleva likt andra jordbaserade köttätare. De verkar förlita sig på en telepatisk kommandolänk från en ras kallad \\\"De Eteriska\\\". När de separeras från denna länk verkar deras mentala system kollapsa och de dör. De har cybernetiska implantat för att förbättra sin stridsförmåga. De har är helt klart fotsoldaterna för ett högre intellekt.\"\n  STR_MUTON_AUTOPSY: \"Muton obduktion\"\n  STR_MUTON_AUTOPSY_UFOPEDIA: \"Denna varelses \\\"skinn\\\" verkar vara en organiskt odlad kroppsrustning som transplanterats på kroppen. Ett flertal cybernetiska implantat används för att förstärka hjärt-kärlsystemet och sinnesorganen. De reproduktiva delarna verkar ha tagits bort kirurgiskt. Tydligen är dessa stackars varelser dömda till ett liv av krigföring och erövring. Pansarbrytande ammunition är speciellt ineffektivt mot dess härdade skinn.\"\n  STR_CELATID_UFOPEDIA: \"Denna livsform har en mystisk förmåga att sväva genom luften. Den verkar upptäcka mänskliga hjärnvågor och kan söka sig mot mål även om de är väl gömda. När ett mål lokaliserats landar Celatiden på marken och sprutar små strålar av extremt frätande gift. Denna varelse har en förmåga att klona sig själv i en alarmerande takt. Den ackompanjerar Mutonerna i sina vandringar.\"\n  STR_CELATID_AUTOPSY: \"Celatid obduktion\"\n  STR_CELATID_AUTOPSY_UFOPEDIA: \"Varelsens kärna innehåller en lite biomekanisk apparat som verkar fungera som verkar vara ett naturligt utvecklat antigravitationsdrivande system. En giftsäck är det största organet och det verkar inte finnas någon separat hjärnstruktur. Det finns inget matsmältande eller reproduktivt organ. En litet organ innehåller embryon som snabbt kan växa till nya Celatider.\"\n  STR_SILACOID_UFOPEDIA: \"Denna kiselbaserade lifsform genererar enorma mängder hetta. Den har kraft nog att krossa stena som den sen absorberar i sin heta kärna. Den har primitiv intelligens och kan kontrolleras genom implantat eller telepatiska kommandon. Den samverkar med Mutonerna.\"\n  STR_SILACOID_AUTOPSY: \"Silacoid obduktion\"\n  STR_SILACOID_AUTOPSY_UFOPEDIA: \"Centrum av denna varelses kropp innehar en extremt hög temperatur, vilket verkar vara grunden för dess matsmältningssystem. Dess unika muskelsystem har enorm kraft och fart. Dess stenhårda skinn är helresistent mot eld och flammbar ammunition.\"\n  STR_CHRYSSALID_UFOPEDIA: \"De krabbliknande klorna på denna varelse är kraftfulla närstridsvapen. Den höga ämnesomsättningen och styrkan ger denna varelse fart och fingerfärdighet. Istället för att döda sina offer befruktas de med ett ägg samtidigt som ett gift injiceras och förvandlar offret till en levande död, en zombie. En ny Chryssalid spränger sig ur offret en kort tid efter befruktningen. Chryssalider är förknippade med Ormmännen.\"\n  STR_CHRYSSALID_AUTOPSY: \"Chryssalid obduktion\"\n  STR_CHRYSSALID_AUTOPSY_UFOPEDIA: \"Exoskelettet på denna varelse är extremt hårt, men förvånansvärt sårbar för explosiv ammunition. Hjärnan är välutvecklad och dess celldelningstakt är snabb. Varelsen bär tjugo ägg som läggs inuti andra organismer. Denna varelse är ett väldigt effektivt terrorvapen.\"\n  STR_FLOATER_UFOPEDIA: \"Svävarna är framförallt soldater och terrorister. De är naturligt rovdjurliknande bestar, genetiskt framtagna och cybernetiskt förbättrade för att vara skräckinjagande krigare. Den lägre halvan av kroppen samt de flesta inre organ har kirugiskt avlägsnats och istället har ett livsuppehållande system installerats. Detta implantat innehåller ett antigravitationsfält som tillåter varelsen att sväva något ostadigt i luften.\"\n  STR_FLOATER_AUTOPSY: \"Svävare obduktion\"\n  STR_FLOATER_AUTOPSY_UFOPEDIA: \"Denna varelse har ändrats drastiskt genom kirurgi. Enheten som formar kärnan av kroppen är ett livsuppehållande system som uppfyller hjärtat, lungornas och matsmältningssystemets funktion. Detta get varelsen möjlighet att överleva i extremt ogästvänliga miljöer. Hjärnan är mindre än vår men sinnesorganen är välutvecklade.\"\n  STR_REAPER_UFOPEDIA: \"Denna tvåbenta köttätare har kraftfulla käkar och en glupsk aptit. Ett antal hjärnimplantat används för att kontrollera dess handlingar. Denna varelses primitiva rovdjursinstinkter har få användningsområden mer än att terrorisera och förstöra. Liemän används oftast av Svävarna.\"\n  STR_REAPER_AUTOPSY: \"Obduktion av Lieman\"\n  STR_REAPER_AUTOPSY_UFOPEDIA: \"Liemannen har dubbla \\\"hjärnor\\\" och hjärtan vilket tillåter överlevnad efter extremt trauma. Dess päls är dock högst eldbar, varför varelsen är svag mot flammbar ammunition.\"\n  STR_SECTOPOD_UFOPEDIA: \"Sectopoder är robotar beväpnade med kraftfulla laservapen. Dessa mekaniska bestar kontrolleras via en telepatisk länk till deras mästare, de Eteriska. Sectopoder är de mest kraftfulla terrorvapnen hos de utomjordiska styrkorna.\"\n  STR_SECTOPOD_AUTOPSY: \"Obduktion av Sectopod\"\n  STR_SECTOPOD_AUTOPSY_UFOPEDIA: \"Roboten är robust konstruerad med kraftigt pansar för att stå emot de flesta former av attacker, speciellt plasmavapen. De sensoriska kretsarna verkar vara känsliga för laserskada.\"\n  STR_CYBERDISC_UFOPEDIA: \"Detta mini-flygande tefat är ett automatiserat terrorvapen beväpnat med en kraftfull plasmastråle. Antigravitationsmotorn ger den ett stort övertag i svår terräng. Dess främsta funktion är förstörelse och terror i Sectoid-rasens tjänst.\"\n  STR_CYBERDISC_AUTOPSY: \"Cyberdisk obduktion\"\n  STR_CYBERDISC_AUTOPSY_UFOPEDIA: \"Cyberdisken är välskyddad och speciellt motståndskraftig mot explosioner. Dess primära antigravitationssystem är för skadat för att kunna ge oss ett hum om dess konstruktion.\"\n  STR_UFO_POWER_SOURCE_UFOPEDIA: \"Kraftkällan i en utomjordisk farkost är en antimateriareaktor som använder Elerium-115 för att generera kraftfulla gravitationsvågor såväl som andra former av energi. Omvandlingen av materia till energi är makalösa 99% varför små mängder Elerium kan producera stora mängder kraft. Dessa enheter kan byggas med utomjordisk legering.\"\n  STR_UFO_NAVIGATION_UFOPEDIA: \"Utomjordiska skepp använder avancerade datorer för att navigera genom rymd och atmosfär. Systemet baseras på optiska processorer som arrangerats i en nätverkad form. Kontrollgränssnittet är relativt enkelt: Navigatören kontrollerar gravitationsvågorna från kraftkällan i den riktning som farkosten behöver komma. Detta system kan enkelt användas av människor och kan reproduceras av utomjordisk legering och andra komponenter.\"\n  STR_UFO_CONSTRUCTION_UFOPEDIA: \"Utomjordiska farkoster består av tre huvudkomponenter: Kraftkälla, navigationssystem och ett skrov byggt av utomjordisk legering. Skrovet är specialdesignat för låta gravitationsvågorna riktas och kontrolleras. Det krävs dessutom Elerium för att driva farkostens kraftkälla. När konstruktionsprincipen och varje komponents funktion är utredd kan vi börja bygga egna farkoster.\"\n  STR_ALIEN_FOOD_UFOPEDIA: \"Dessa kammare innehåller olika enzymer som används för att lösa upp kroppsdelarna av boskap, djur och även människor. Vätskan intas sedan som redan nedsmält mat, antagligen rakt in i blodomloppet. Detta visar på ett visst beroende av Jorden för mat, en symbios mellan Jordens och utomjordingarnas samhälle.\"\n  STR_ALIEN_REPRODUCTION_UFOPEDIA: \"Dessa kammare innehåller utomjordiska foster. Utformningen på kontainrarna tyder på att dessa utomjordingar förlitar sig helt på reproduktion i laboratorier. Den näringsrika vätskan hjälper till att snabba på utvecklingen av fostren. Detta rullbandssystem kan producera flera tusen kloner på kort tid. Processen kan säkerligen användas för kloning av människor eller mänskliga hybrider.\"\n  STR_ALIEN_ENTERTAINMENT_UFOPEDIA: \"Den mest sannolika funktionen av dessa klot är avslappning. De psioniska kretsarna stimulerar olika centrum i hjärnan vilket ger en hallucinatorisk effekt. Detta är enda beviset på att utomjordingarna har någon form av fritidsnöje.\"\n  STR_ALIEN_SURGERY_UFOPEDIA: \"Denna kirurgiska utrustning använder laser för att extrahera vissa kroppsdelar från boskap och andra djur. Utbredda djurstympningarna kan länkas till denna bisarra utomjordingsaktivitet. Det är sannolikt att kroppsdelarna används för näring eller genetiska skäl.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"Folk har sedan länge påstått sig ha blivit bortförda av utomjordingar, ibland gång på gång. Sanningen är betydligt mer ryslig. Människor är bortförda, forskade på och undersökta. De bästa exemplaren får sitt genetiska material extraherad. Kvinnor får människo-utomjordingshybrider till foster inplanterade, som sedan extraheras några månader senare. Vem vet vilka olyckbådande motiv utomjordingarna har?\"\n  STR_ALIEN_ALLOYS_UFOPEDIA: \"Utomjordiska farkoster är konstruerade från speciallegeringar med unika egenskaper. De är extremt lätta och hållfasta samt kan omformas med elektro-magnetisk teknik. Detta material kan reproduceras och användas i tillverkningsprocessen.\"\n  STR_ELERIUM_115_UFOPEDIA: \"Detta element har den ovanliga egenskapen att skapa antimateria när den bombarderas med vissa partiklar. Detta skapar gravitationsvågor och andra former av energi. Det kan inte återfinnas i vårt solsystem och kan inte reproduceras.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"Det är tydligt att vi utkämpar en hopplös kamp på Jorden. De utomjordiska horderna är överväldigande i sina antal. Det bästa vi kan göra är att sakta ner deras framfart. Det enda hoppet för mänskligheten är att attackera utomjordingarna vid deras källa. Vår forskning verkar indikera en närliggande bas inom vårt solsystem. Utomjordingarna anser detta vara ett centrum för en forntida civilisation som föregått människans historia. Vi måste hitta denna plats så snart som möjligt, men vi måste fånga och förhöra en utomjordisk ledare för att få mer detaljerad information. De större UFO:na har antagligen minst en utomjordisk ledare.\"\n  STR_THE_MARTIAN_SOLUTION_UFOPEDIA: \"Vår forskning pekar på att utomjordingarnas centrala hembas finns på planeten Mars. Basen är väl gömd och besitter både tillverknings- och kloningsfaciliteter till utomjordingarnas infiltrationsförsök. Den verkar också husera en centraldator som kontrollerar hela verksamheten. Det verkar som att det bikupe-liknande samhället har en sorts bidrottning. Detta är deras största svaghet- om vi kan eliminera hjärnan kommer kroppen att dö. Vi måste öka våra ansträngningar innan det är för sent. För att komma vidare måste vi fånga en utomjordisk officer av högsta rang, en befälhavare. De ska enbart finnas i utomjordiska baser samt Slagskepp. \"\n  STR_CYDONIA_OR_BUST_UFOPEDIA: \"Det är nu klarlagt att de främmande horderna kontrolleras från en underjordisk bas i Cydonia, vilket är ett ovanligt område på Mars yta med femsidiga pyramider och en stor formation som påminner om ett mänskligt ansikte. Cydonias civilisation blomstade för miljoner år sen på Mars. Vi vet inte varför den dog ut, eller vad dess koppling till den senaste tidens utomjordiska aktiviteter är. I vilket fall som helst måste vi skicka en expedition till Cydonia. Detta är det enda sättet att besegra utomjordingarna. Vi måste förstöra hjärnan bakom som kontrollerar. Vi kommer att behöva en Hämnarfarkost bestyckad med den mäktigaste eldkraften vi har tillgång till. Det finns inget mer vi kan lära oss, vi måste invänta utgången av Cydonia-attacken.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"CENTRERA PÅ PLATS-TID=5 s\"\n  STR_CANCEL_UC: \"AVBRYT\"\n  STR_NONE: \"Ingen\"\n  STR_UNKNOWN: \"Okänt\"\n  STR_POOR: \"Dålig\"\n  STR_AVERAGE: \"Genomsnitt\"\n  STR_GOOD: \"Bra\"\n  STR_EXCELLENT: \"Utmärkt\"\n  STR_BUILD_NEW_BASE_UC: \"BYGG NY BAS\"\n  STR_BASE_INFORMATION: \"BASINFORMATION\"\n  STR_EQUIP_CRAFT: \"UTRUSTA FARKOST\"\n  STR_BUILD_FACILITIES: \"BYGG ANLÄGGNINGAR\"\n  STR_RESEARCH: \"FORSKNING\"\n  STR_MANUFACTURE: \"TILLVERKA\"\n  STR_TRANSFER_UC: \"ÖVERFÖR\"\n  STR_PURCHASE_RECRUIT: \"KÖP/ANSTÄLL\"\n  STR_SACK: \"AVSKEDA\"\n  STR_SELL_SACK_UC: \"SÄLJ/AVSKEDA\"\n  STR_GEOSCAPE_UC: \"GEOVY\"\n  STR_NAME: \"Namn\"\n  STR_AREA: \"Område\"\n  STR_BUILD_NEW_BASE: \"Bygg Ny Bas\"\n  STR_CANCEL: \"Avbryt\"\n  STR_COST_UC: \"KOSTNAD>\"\n  STR_CONSTRUCTION_TIME_UC: \"BYGGTID>\"\n  STR_DAY:\n    one: \"{N} dag\"\n    other: \"{N} dagar\"\n  STR_HOUR:\n    one: \"{N} timme\"\n    other: \"{N} timmar\"\n  STR_MAINTENANCE_UC: \"UNDERHÅLL>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Installation\"\n  STR_CURRENT_RESEARCH: \"NUVARANDE FORSKNING\"\n  STR_SCIENTISTS_AVAILABLE: \"Forskare Tillgängliga>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Forskare Tilldelade>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Laboratoriumutrymme Tillgängligt>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"FORSKNINGSPROJEKT\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"FORSKARE TILLDELADE\"\n  STR_PROGRESS: \"UTVECKLING\"\n  STR_NEW_PROJECT: \"Nytt projekt\"\n  STR_CANCEL_PROJECT: \"AVBRYT PROJEKT\"\n  STR_NEW_RESEARCH_PROJECTS: \"NYA FORSKNINGSPROJEKT\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"FORSKARE TILLGÄNGLIGA>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"LABORATORIEPLATSER TILLGÄNGLIGA>{ALT}{0}\"\n  STR_INCREASE: \"Öka\"\n  STR_DECREASE: \"Minska\"\n  STR_START_PROJECT: \"STARTA PROJEKT\"\n  STR_CURRENT_PRODUCTION: \"NUVARANDE PRODUKTION\"\n  STR_ENGINEERS_AVAILABLE: \"Ingenjörer Tillgängliga>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Ingenjörer Tilldelade>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Verkstadsutrymme Tillgängligt>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Nuvarande Tillgångar>{ALT}{0}\"\n  STR_ITEM: \"FÖREMÅL\"\n  STR_ENGINEERS__ALLOCATED: \"Ingenjörer Tilldelade\"\n  STR_UNITS_PRODUCED: \"Enheter Producerade\"\n  STR_TOTAL_TO_PRODUCE: \"Totalt att Producera\"\n  STR_COST__PER__UNIT: \"Kostnad{NEWLINE}per{NEWLINE}Enhet\"\n  STR_DAYS_HOURS_LEFT: \"Dagar/Timmar Kvar\"\n  STR_NEW_PRODUCTION: \"Ny Produktion\"\n  STR_PRODUCTION_ITEMS: \"Produktionsföremål\"\n  STR_CATEGORY: \"KATEGORI\"\n  STR_START_PRODUCTION: \"STARTA PRODUKTION\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} Ingenjörstimmar för att producera en enhet\"\n  STR_COST_PER_UNIT_: \"Kostnad per enhet>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"VERKSTADSUTRYMME SOM KRÄVS>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"SPECIALMATERIEL KRÄVS\"\n  STR_ITEM_REQUIRED: \"FÖREMÅL KRÄVS\"\n  STR_UNITS_REQUIRED: \"ENHETSKRAV\"\n  STR_UNITS_AVAILABLE: \"ENHETER TILLGÄNGLIGA\"\n  STR_STOP_PRODUCTION: \"STOPPA PRODUKTION\"\n  STR_ENGINEERS_AVAILABLE_UC: \"INGENJÖRER TILLGÄNGLIGA>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"VERKSTADSUTRYMME TILLGÄNGLIGT>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"MÅNATLIG VINST>{ALT}{0}\"\n  STR_INCREASE_UC: \"ÖKA\"\n  STR_DECREASE_UC: \"MINSKA\"\n  STR_UNITS_TO_PRODUCE: \"Enheter att Producera\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Köp/Anställ Personal\"\n  STR_COST_OF_PURCHASES: \"Kostnad per Köp>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"KOSTNAD PER ENHET\"\n  STR_QUANTITY_UC: \"KVANTITET\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"PERSONAL TILLGÄNGLIG:PERSONAL TOTAL>\"\n  STR_SOLDIERS: \"Soldater\"\n  STR_SCIENTISTS: \"Forskare\"\n  STR_ENGINEERS: \"Ingenjörer\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"UTRYMME ANVÄNT:UTRYMME TILLGÄNGLIGT>\"\n  STR_LIVING_QUARTERS: \"Logement\"\n  STR_STORES: \"Förråd\"\n  STR_LABORATORIES: \"Laboratorier\"\n  STR_WORK_SHOPS: \"Verkstäder\"\n  STR_HANGARS: \"Hangarer\"\n  STR_SHORT_RANGE_DETECTION: \"Korträckviddsdetektering\"\n  STR_DEFENSE_STRENGTH: \"Försvarsstyrka\"\n  STR_TRANSFERS_UC: \"ÖVERFÖRINGAR\"\n  STR_TRANSFERS: \"Överföringar\"\n  STR_ARRIVAL_TIME_HOURS: \"Ankomsttid (timmar)\"\n  STR_COST_: \"Kostnad>{ALT}{0}\"\n  STR_AREA_: \"Area>{ALT}{0}\"\n  STR_BASE_NAME: \"Basens Namn?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"VÄLJ POSITION FÖR ENTRÉHISSEN.\"\n  STR_TRANSFER: \"Överför\"\n  STR_AMOUNT_TO_TRANSFER: \"ANTAL ATT ÖVERFÖRA\"\n  STR_SELECT_DESTINATION_BASE: \"Välj målbas\"\n  STR_COST: \"Kostnad\"\n  STR_VICTORY_1: \"När du äntrar kammaren ser du den utomjordiska hjärnan, ditt huvudmål. Innan du kan skjuta börjar den kommunicera med dig via en skärm vid dess fot. Den ber dig att lyssna på dess skäl att fortsätta leva innan du tar beslutet att trycka på avtryckaren...\"\n  STR_VICTORY_2: \"Hjärnan talar: \\\"Många miljoner år sedan levde planeten ni kallar Mars. Detta liv fördes hit av vår civilisation på samma sätt som det fördes till er. I miljoner år har vi besökt er planet och utvecklat er art genetiskt. Ni kan inte döda oss, ni är en del av oss...\\\"\"\n  STR_VICTORY_3: \"\\\"Detta är centrum i Mars civilisation. Pyramiderna är byggda miljoner år innan era av en art som var era förfädrar. Ingen planet är bortom vår räckhåll. Denna kraft kan bli eran och allt vi ber om är ert samarbete...\\\"\"\n  STR_GAME_OVER_1: \"Utomjordingarna försöker utrota alla människor genom att förstöra städer och förgifta luften och haven. Jordens armeer är chanslösa mot utomjordingarnas övermäktiga teknologi. De överlevande generationerna utvecklar fruktansvärda mutationer under flykten från utplåning. De samlas ihop i arbetsläger för att transformera Jorden till en koloni som är del av ett okänt imperium.\"\n  STR_GAME_OVER_2: \"Kunskapen från X-COM projektet är förlorad för evigt. Du har misslyckats med att rädda Jorden.\"\n  STR_VICTORY_4: \"Den utomjordiska hjärnan är avbruten av en salva het plasma, och hela den utomjordiska styrkan är besegrad.\"\n  STR_VICTORY_5: \"Efter utomjordingarnas nederlag tar det inte lång tid förrän mänskligheten med hjälp av X-Coms forskningsupptäckter koloniserar Mars. Det utomjordiska hotet är borta, men hur länge det kommer vara vet ingen...\"\n  STR_YOU_HAVE_FAILED: \"Du har misslyckats med att stoppa de utomjordiska angreppen. En efter en ger de grundande nationerna efter och signerar avtal med löften om avancerad teknologi, fred och välstånd. Det blir dock snart tydligt att utomjordingarna har andra planer...\"\n  STR_TOTAL_UC: \"TOTALT\"\n  STR_INCOME: \"Inkomst\"\n  STR_EXPENDITURE: \"Utgifter\"\n  STR_MAINTENANCE: \"Underhåll\"\n  STR_BALANCE: \"Balans\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"UFO-Aktivitet per Område\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"UFO-Aktivitet per Land\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"X-Com-Aktivitet per Område\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"X-Com-Aktivitet per Land\"\n  STR_FINANCE: \"Finans\"\n  STR_DATE_FIRST: \"{0}.\"\n  STR_DATE_SECOND: \"{0}.\"\n  STR_DATE_THIRD: \"{0}.\"\n  STR_DATE_FOURTH: \"{0}.\"\n  STR_FINANCE_THOUSANDS: \"$1000's\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Otillräckligt med specialmaterial för att producera{NEWLINE}{0}{NEWLINE}i{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Otillräckligt med pengar för att producera{NEWLINE}{0}{NEWLINE}i{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"Produktion av {NEWLINE}{0}{NEWLINE}på{NEWLINE}{1}{NEWLINE}är avklarad\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"Konstruktion av{NEWLINE}{0}{NEWLINE}på{NEWLINE}{1}{NEWLINE}är slutförd\"\n  STR_OK_5_SECONDS: \"OK - 5 s\"\n  STR_RESEARCH_COMPLETED: \"Forskning avslutad\"\n  STR_VIEW_REPORTS: \"GRANSKA RAPPORTER\"\n  STR_WE_CAN_NOW_RESEARCH: \"Vi kan nu undersöka\"\n  STR_WE_CAN_NOW_PRODUCE: \"Vi kan nu producera\"\n  STR_SUNDAY: \"SÖNDAG\"\n  STR_MONDAY: \"MÅNDAG\"\n  STR_TUESDAY: \"TISDAG\"\n  STR_WEDNESDAY: \"ONSDAG\"\n  STR_THURSDAY: \"TORSDAG\"\n  STR_FRIDAY: \"FREDAG\"\n  STR_SATURDAY: \"LÖRDAG\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Inte tillräckligt med {0} för att fylla på {1} i {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Inte tillräckligt med {0} för att rusta om {1} i {2}\"\n  STR_UFO_IS_NOT_RECOVERED: \"UFO inte inhämtat\"\n  STR_UFO_IS_RECOVERED: \"UFO:t inhämtat\"\n  STR_CRAFT_IS_LOST: \"Farkost förlorad\"\n  STR_TERROR_CONTINUES: \"Terrorattentat fortsätter\"\n  STR_ALIENS_DEFEATED: \"Utomjordingar besegrade\"\n  STR_BASE_IS_LOST: \"Basen är förlorad\"\n  STR_BASE_IS_SAVED: \"Basen är räddad\"\n  STR_ALIEN_BASE_STILL_INTACT: \"Utomjordisk bas fortfarande intakt\"\n  STR_ALIEN_BASE_DESTROYED: \"Utomjordisk bas förstörd\"\n  STR_ALIENS_KILLED: \"UTOMJORDINGAR DÖDADE\"\n  STR_ALIEN_CORPSES_RECOVERED: \"UTOMJORDISKA KROPPAR INHÄMTADE\"\n  STR_LIVE_ALIENS_RECOVERED: \"LEVANDE UTOMJORDING INFÅNGAD\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"UTOMJORDISKA FÖREMÅL BESLAGTAGNA\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"UTOMJORDINGSBASENS KONTROLLENHET FÖRSTÖRD\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"CIVILA DÖDADE AV UTOMJORDINGAR\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"CIVILA DÖDADE AV X-COM-AGENTER\"\n  STR_CIVILIANS_SAVED: \"CIVILA RÄDDADE\"\n  STR_XCOM_OPERATIVES_KILLED: \"X-COM-AGENTER DÖDADE\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"X-COM AGENTER SAKNADE I STRID\"\n  STR_TANKS_DESTROYED: \"TANKS FÖRSTÖRDA\"\n  STR_XCOM_CRAFT_LOST: \"X-COM-FARKOST FÖRLORAD\"\n  STR_UFO_RECOVERY: \"UFO BÄRGADE\"\n  STR_ALIEN_BASE_RECOVERY: \"UTOMJORDISK BAS BESLAG\"\n  STR_BASE_UNDER_ATTACK: \"{0} är under attack!\"\n  STR_BASE_DEFENSES_INITIATED: \"BASFÖRSVAR INLETT\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"GRAVITATIONSSKÖLD STÖTER TILLBAKA UFO!\"\n  STR_FIRING: \"AVFYRAR\"\n  STR_HIT: \"TRÄFF!\"\n  STR_UFO_DESTROYED: \"UFO FÖRSTÖRT!\"\n  STR_MISSED: \"MISS!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Sälj Föremål/Avskeda Personal\"\n  STR_VALUE_OF_SALES: \"SÄLJVÄRDE>{ALT}{0}\"\n  STR_FUNDS: \"TILLGÅNGAR>{ALT}{0}\"\n  STR_SELL_SACK: \"Sälj/Avskeda\"\n  STR_VALUE: \"Värde\"\n  STR_CRAFT_: \"FARKOST> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"UFOKRASCHS BÄRGNING\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"Iakta stor försiktighet. Det kan finnas fiender i UFO:t eller runt nedslagsplatsen. Uppdraget är slutfört när alla fiendeenheter är eliminerade eller neutraliserade. Beslag av UFO-rester, artefakter och utomjordiska kroppar kan då genomföras. För att avbryta uppdraget återför X-Com agenterna till transportfordonet och klicka på Avbryt Uppdrag-ikonen.\"\n  STR_UFO_GROUND_ASSAULT: \"UFO MARKBASERAT ÖVERFALL\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"Utforska landningsplatsen och om möjligt äntra UFO:t. Uppdraget är slutfört när alla fiendeenheter är eliminerade eller neutraliserade. Beslag av UFO, artefakter och utomjordiska kroppar kan då genomföras. För att avbryta uppdraget återför X-Com agenterna till transportfordonet och klicka på Avbryt Uppdrag-ikonen.\"\n  STR_BASE_DEFENSE: \"BASFÖRSVAR\"\n  STR_BASE_UC_: \"BAS> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"Ett UFO har landat i närheten. Vår bas är i allvarlig fara. Enligt säkerhetsförfarandet har all icke stridbar personal och alla farkoster evakuerats. Utomjordiska enheter kommer anfalla basen via hangarerna och entréhissen.\\nFörsvara basen och dess faciliteter till varje pris, det finns ingen väg ut. Om du klickar på Avbryt Uppdrag-ikonen kommer du ge upp och förlora basen.\"\n  STR_ALIEN_BASE_ASSAULT: \"UTOMJORDISK BAS ANFALL\"\n  STR_ALIEN_BASE_ASSAULT_BRIEFING: \"X-Coms agenter har äntrat en utomjordisk bas. Kontrollcentret måste förstöras för att göra basen obrukbar. Uppdraget är avslutat när alla fiender eliminerats eller neutraliserats, alternativt om du evakuerar agenterna från de gröna utgångarna genom att klicka på Avbryt Uppdrag-ikonen.\"\n  STR_CYDONIA_BRIEFING: \"Du har ankommit till Cydonia. Du äntrar ett stort underjordiskt komplex nära Marssphinxen. Du måste förstöra hjärnan bakom utomjordingarnas planer. Mänsklighetens öde ligger i dina händer...\"\n  STR_TERROR_MISSION: \"TERRORUPPDRAG\"\n  STR_TERROR_MISSION_BRIEFING: \"Uppdraget är slutfört när alla fiendeenheter är eliminerade eller neutraliserade. Du måste försöka rädda civilisterna i området från det utomjordiska hotet. För att avbryta uppdraget återför X-Com agenterna till transportfordonet och klicka på Avbryt Uppdrag-ikonen.\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"INGA LEDIA HANGARER FÖR ÖVERFÖRING!{SMALLLINE}Varje farkost tilldelad, överför, köpt eller konstruerad använder en hangar i denna bas. Bygg en ny hangar eller överför en farkost till en annan bas.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"INGA FRIA HANGARER FÖR INKÖP!{SMALLLINE}Varje farkost tilldelad, överförd, inköpt eller överförd upptar en hangar. Bygg en ny hangar eller överför en farkost till en annan bas.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"INGA FRIA HANGARER FÖR ÖVERFÖRING!{SMALLLINE}Varje farkost tilldelad, överförd, köpt eller konstruerad i basen använder en hangar. Bygg en ny hangar eller överför en farkost till en annan bas.\"\n  STR_CANNOT_BUILD_HERE: \"KAN INTE BYGGA HÄR!{SMALLLINE}Du måste bygga bredvid en redan byggd anläggning.\"\n  STR_NO_FREE_ACCOMODATION: \"INGA FRIA LOGIUTRYMMEN!{SMALLLINE}Destinationsbasen har inte tillräckligt med utrymme i sina logement.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"OTILLRÄCKLIGT MED ARBETSUTRYMME!{SMALLLINE}Bygg nya verkstäder eller minska arbetsstorleken på andra projekt.\"\n  STR_NOT_ENOUGH_MONEY: \"OTILLRÄCKLIGT MED PENGAR!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"OTILLRÄCKLIGT FÖRRÅDSUTRYMME!{SMALLLINE}Bygg nya förråd eller överför material till andra baser.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"OTILLRÄCKLIGT MED LOGIUTRYMMEN!{SMALLLINE}Bygg nya logement eller överför personal till andra baser.\"\n  STR_LAUNCH_INTERCEPTION: \"STARTA GENSKJUTNING\"\n  STR_CRAFT: \"FARKOST\"\n  STR_STATUS: \"STATUS\"\n  STR_BASE: \"BAS\"\n  STR_READY: \"REDO\"\n  STR_OUT: \"UT\"\n  STR_REPAIRS: \"REPARATIONER\"\n  STR_REFUELLING: \"TANKAR\"\n  STR_REARMING: \"OMRUSTAS\"\n  STR_TARGET: \"MÅL: {0}\"\n  STR_WAY_POINT: \"VÄGPUNKT\"\n  STR_ARE_YOU_SURE_CYDONIA: \"Är du säker på att du vill sända denna farkost på uppdrag till Cydonia?\"\n  STR_YES: \"JA\"\n  STR_NO: \"NEJ\"\n  STR_SELECT_DESTINATION: \"VÄLJ DESTINATION\"\n  STR_CYDONIA: \"CYDONIA\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"VÄLJ PLATS FÖR NY BAS\"\n  STR_RETURN_TO_BASE: \"ÅTERVÄND TILL BASEN\"\n  STR_SELECT_NEW_TARGET: \"VÄLJ NYTT MÅL\"\n  STR_PATROL: \"PATRULLERA\"\n  STR_STATUS_: \"STATUS>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"SKADAD - ÅTERVÄNDER TILL BAS\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"LÅG BRÄNSLENIVÅ - ÅTERVÄNDER TILL BAS\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"UPPDRAG SLUTFÖRT - ÅTERVÄNDER TILL BAS\"\n  STR_PATROLLING: \"PATRULLERAR\"\n  STR_TAILING_UFO: \"FÖLJER UFO\"\n  STR_INTERCEPTING_UFO: \"GENSKJUTER UFO-{0}\"\n  STR_RETURNING_TO_BASE: \"ÅTERVÄNDER TILL BAS\"\n  STR_DESTINATION_UC_: \"DESTINATION: {0}\"\n  STR_BASE_UC: \"BAS>{ALT}{0}\"\n  STR_SPEED_: \"HASTIGHET>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"MAXHASTIGHET>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"ALTITUD>{ALT}{0}\"\n  STR_VERY_LOW: \"VÄLDIGT LÅG\"\n  STR_LOW_UC: \"LÅG\"\n  STR_HIGH_UC: \"HÖG\"\n  STR_VERY_HIGH: \"VÄLDIGT HÖG\"\n  STR_FUEL: \"BRÄNSLE>{ALT}{0}\"\n  STR_WEAPON_ONE: \"VAPEN-1>{ALT}{0}\"\n  STR_NONE_UC: \"INGEN\"\n  STR_ROUNDS_: \"SKOTT>{ALT}{0}\"\n  STR_WEAPON_TWO: \"VAPEN-2>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"JAKTPLANSFARKOST\"\n  STR_BASE_: \"Bas>{0}\"\n  STR_NAME_UC: \"NAMN\"\n  STR_AMMO_: \"AMMO>{ALT}{0}\"\n  STR_CREW: \"BESÄTTNING\"\n  STR_EQUIPMENT_UC: \"UTRUSTNING\"\n  STR_ARMOR: \"PANSAR\"\n  STR_MAX: \"MAX>{ALT}{0}\"\n  STR_ROOKIE: \"Rekryt\"\n  STR_SQUADDIE: \"Menig\"\n  STR_SERGEANT: \"Sergeant\"\n  STR_CAPTAIN: \"Kapten\"\n  STR_COLONEL: \"Överste\"\n  STR_COMMANDER: \"Kommendör\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Välj Trupp för {0}\"\n  STR_SORT_BY: \"SORTERA EFTER...\"\n  STR_ORIGINAL_ORDER: \"ORIGINAL ORDNING\"\n  STR_MISSIONS2: \"UPPDRAG\"\n  STR_KILLS2: \"DÖDADE\"\n  STR_WOUND_RECOVERY2: \"SJUKDAGAR\"\n  STR_SPACE_AVAILABLE: \"UTRYMME TILLGÄNGLIGT>{ALT}{0}\"\n  STR_SPACE_USED: \"UTRYMME ANVÄNT>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"UTRYMME ANVÄNT\"\n  STR_RANK: \"GRAD\"\n  STR_WOUNDED: \"SKADAD\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Utrustning för {0}\"\n  STR_DEFENSE_VALUE: \"Försvarsvärde\"\n  STR_HIT_RATIO: \"Träffratio\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}redo att{NEWLINE}landa nära{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"Påbörja uppdrag?\"\n  STR_SELECT_ARMAMENT: \"Välj Bestyckning\"\n  STR_AMMUNITION_AVAILABLE: \"AMMUNITION TILLGÄNGLIG\"\n  STR_ARMAMENT: \"BESTYCKNING\"\n  STR_NOT_AVAILABLE: \"N.A.\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"VÄLJ RUSTNING FÖR{NEWLINE}{0}\"\n  STR_TYPE: \"TYP\"\n  STR_PERSONAL_ARMOR_UC: \"PERSONPANSAR\"\n  STR_POWER_SUIT_UC: \"KRAFTRUSTNING\"\n  STR_FLYING_SUIT_UC: \"FLYGARRUSTNING\"\n  STR_SELECT_ARMOR: \"Välj Rustning\"\n  STR_NORTH: \"NORR\"\n  STR_NORTH_EAST: \"NORDÖST\"\n  STR_EAST: \"ÖST\"\n  STR_SOUTH_EAST: \"SYDÖST\"\n  STR_SOUTH: \"SYD\"\n  STR_SOUTH_WEST: \"SYDVÄST\"\n  STR_WEST: \"VÄST\"\n  STR_NORTH_WEST: \"NORDVÄST\"\n  STR_SELECT_ACTION: \"VÄLJ HANDLING\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"FORTSÄTT GENSKJUTNINGSJAKT\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"FÖLJ EFTER UTAN GENSKJUTNING\"\n  STR_VERY_LARGE: \"VÄLDIGT STOR\"\n  STR_LARGE: \"STOR\"\n  STR_MEDIUM_UC: \"MELLAN\"\n  STR_SMALL: \"LITEN\"\n  STR_VERY_SMALL: \"VÄLDIGT LITEN\"\n  STR_GROUNDED: \"MARK\"\n  STR_DETECTED: \"Upptäckt\"\n  STR_SIZE_UC: \"STORLEK\"\n  STR_ALTITUDE: \"HÖJD\"\n  STR_HEADING: \"KURS\"\n  STR_SPEED: \"HASTIGHET\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"CENTRERA UFO-TID=5 s\"\n  STR_TRACKING_LOST: \"SPÅR FÖRLORAT\"\n  STR_REDIRECT_CRAFT: \"OMDIRIGERA FARKOST\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"GÅ TILL SIST KÄNDA UFO-POSITION\"\n  STR_UFO_: \"UFO-{0}\"\n  STR_ALIEN_BASE_: \"UTOMJORDISK BAS-{0}\"\n  STR_CRASH_SITE_: \"Olycksplats-{0}\"\n  STR_LANDING_SITE_: \"LANDNINGSPLATS-{0}\"\n  STR_WAY_POINT_: \"VÄGPUNKT-{0}\"\n  STR_TERROR_SITE: \"TERRORISERAD ORT-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}har anlänt till{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"Patrullerar\"\n  STR_ALIEN_ORIGINS: \"Utomjordingarnas Ursprung\"\n  STR_THE_MARTIAN_SOLUTION: \"Marslösningen\"\n  STR_CYDONIA_OR_BUST: \"Cydonia eller Brista\"\n  STR_UFOPAEDIA: \"UFOpedia\"\n  STR_XCOM_CRAFT_ARMAMENT: \"X-COM FARKOSTER & BESTYCKNINGAR\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"VAPENPLATTFORM\"\n  STR_WEAPONS_AND_EQUIPMENT: \"VAPEN OCH UTRUSTNING\"\n  STR_ALIEN_ARTIFACTS: \"UTOMJORDISK ARTEFAKT\"\n  STR_BASE_FACILITIES: \"BASANLÄGGNINGAR\"\n  STR_ALIEN_LIFE_FORMS: \"UTOMJORDISKA LIVSFORMER\"\n  STR_ALIEN_RESEARCH_UC: \"UTOMJORDISK FORSKNING\"\n  STR_UFO_COMPONENTS: \"UFO KOMPONENTER\"\n  STR_UFOS: \"UFO:n\"\n  STR_SELECT_ITEM: \"VÄLJ FÖREMÅL\"\n  STR_ACCELERATION: \"ACCELERATION>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"BRÄNSLEKAPACITET>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"VAPENSYSTEM>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"SKADEKAPACITET>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"LASTUTRYMME>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"VP KAPACITET>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Skada\"\n  STR_RANGE: \"Räckvidd\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Träffsäkerhet\"\n  STR_RE_LOAD_TIME: \"Omladdningstid\"\n  STR_SECONDS: \"{0}s\"\n  STR_DAMAGE_ARMOR_PIERCING: \"PANSARBRYTANDE\"\n  STR_DAMAGE_INCENDIARY: \"FLAMMBAR\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"HÖGEXPLOSIVT\"\n  STR_DAMAGE_LASER_BEAM: \"LASERSTRÅLE\"\n  STR_DAMAGE_PLASMA_BEAM: \"PLASMASTRÅLE\"\n  STR_DAMAGE_STUN: \"BEDÖVA\"\n  STR_DAMAGE_MELEE: \"NÄRSTRID\"\n  STR_DAMAGE_ACID: \"SYRA\"\n  STR_DAMAGE_SMOKE: \"RÖK\"\n  STR_SHOT_TYPE: \"ELDTYP\"\n  STR_ACCURACY_UC: \"TRÄFFSÄKERHET\"\n  STR_TIME_UNIT_COST: \"TE KOST\"\n  STR_DAMAGE_UC: \"SKADA\"\n  STR_AMMO: \"AMMO\"\n  STR_SHOT_TYPE_AUTO: \"Auto\"\n  STR_SHOT_TYPE_SNAP: \"Snabb\"\n  STR_SHOT_TYPE_AIMED: \"Välriktat\"\n  STR_CONSTRUCTION_TIME: \"Byggtid\"\n  STR_CONSTRUCTION_COST: \"Byggkostnad\"\n  STR_MAINTENANCE_COST: \"Underhållskostnad\"\n  STR_LOW: \"Låg\"\n  STR_MEDIUM: \"Mellan\"\n  STR_HIGH: \"Hög\"\n  STR_CRAFT_WEAPON: \"Tillverka Vapen\"\n  STR_CRAFT_AMMUNITION: \"Tillverka Ammunition\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Vapenplattform\"\n  STR_WEAPON: \"Vapen\"\n  STR_AMMUNITION: \"Ammunition\"\n  STR_EQUIPMENT: \"Utrustning\"\n  STR_ALIEN_CORPSE: \"Utomjordiskt lik\"\n  STR_UFO_COMPONENT: \"UFO komponent\"\n  STR_PERSONAL_ARMOR: \"Personpansar\"\n  STR_RAW_MATERIALS: \"Råmaterial\"\n  STR_HWP_CANNON_SHELLS: \"VP Kanonpatroner\"\n  STR_ALIEN: \"Utomjording\"\n  STR_SECTOID: \"Sectoid\"\n  STR_SNAKEMAN: \"Ormman\"\n  STR_ETHEREAL: \"Eterisk\"\n  STR_MUTON: \"Muton\"\n  STR_FLOATER: \"Svävare\"\n  STR_CELATID: \"Celatid\"\n  STR_SILACOID: \"Silacoid\"\n  STR_CHRYSSALID: \"Chryssalid\"\n  STR_ZOMBIE: \"Zombie\"\n  STR_REAPER: \"Lieman\"\n  STR_SECTOPOD: \"Sectopod\"\n  STR_CYBERDISC: \"Cyberdisk\"\n  STR_LIVE_COMMANDER: \"Kommendör\"\n  STR_LIVE_LEADER: \"Chef\"\n  STR_LIVE_ENGINEER: \"Ingenjör\"\n  STR_LIVE_MEDIC: \"Sjukvårdare\"\n  STR_LIVE_NAVIGATOR: \"Navigatör\"\n  STR_LIVE_SOLDIER: \"Soldat\"\n  STR_LIVE_TERRORIST: \"Terrorist\"\n  STR_FLOATER_SOLDIER: \"Svävare Soldat\"\n  STR_FLOATER_NAVIGATOR: \"Svärare Navigatör\"\n  STR_FLOATER_MEDIC: \"Svävare Sjukvårdare\"\n  STR_FLOATER_ENGINEER: \"Svävare Ingenjör\"\n  STR_FLOATER_LEADER: \"Svävare chef\"\n  STR_FLOATER_COMMANDER: \"Svävare Kommendör\"\n  STR_SECTOID_SOLDIER: \"Sectoid Soldat\"\n  STR_SECTOID_NAVIGATOR: \"Sectoid Navigatör\"\n  STR_SECTOID_MEDIC: \"Sectoid Sjukvårdare\"\n  STR_SECTOID_ENGINEER: \"Sectoid Ingenjör\"\n  STR_SECTOID_LEADER: \"Sectoid chef\"\n  STR_SECTOID_COMMANDER: \"Sectoid Kommendör\"\n  STR_SNAKEMAN_SOLDIER: \"Ormman Soldat\"\n  STR_SNAKEMAN_NAVIGATOR: \"Ormman Navigatör\"\n  STR_SNAKEMAN_ENGINEER: \"Ormman Ingenjör\"\n  STR_SNAKEMAN_LEADER: \"Ormman chef\"\n  STR_SNAKEMAN_COMMANDER: \"Ormman Kommendör\"\n  STR_MUTON_SOLDIER: \"Muton Soldat\"\n  STR_MUTON_NAVIGATOR: \"Muton Navigatör\"\n  STR_MUTON_ENGINEER: \"Muton Ingenjör\"\n  STR_ETHEREAL_SOLDIER: \"Eterisk Soldat\"\n  STR_ETHEREAL_LEADER: \"Eterisk chef\"\n  STR_ETHEREAL_COMMANDER: \"Eterisk Kommendör\"\n  STR_CYBERDISC_TERRORIST: \"Cyberdisk Terrorist\"\n  STR_REAPER_TERRORIST: \"Lieman Terrorist\"\n  STR_CHRYSSALID_TERRORIST: \"Chryssalid Terrorist\"\n  STR_CELATID_TERRORIST: \"Celatid Terrorist\"\n  STR_SILACOID_TERRORIST: \"Silacoid Terrorist\"\n  STR_SECTOPOD_TERRORIST: \"Sectopod Terrorist\"\n  STR_UFO_POWER_SOURCE: \"UFO Kraftkälla\"\n  STR_UFO_NAVIGATION: \"UFO Navigation\"\n  STR_UFO_CONSTRUCTION: \"UFO Kontstruktion\"\n  STR_ALIEN_FOOD: \"Utomjordisk Mat\"\n  STR_ALIEN_REPRODUCTION: \"Utomjordisk Reproduktion\"\n  STR_ALIEN_ENTERTAINMENT: \"Utomjordisk Underhållning\"\n  STR_ALIEN_SURGERY: \"Utomjordisk Kirurgi\"\n  STR_EXAMINATION_ROOM: \"Undersökningsrum\"\n  STR_ALIEN_ALLOYS: \"Utomjordiska legeringar\"\n  STR_ALIEN_HABITAT: \"Utomjordisk Livsmiljö\"\n  STR_POWER_SUIT: \"Kraftrustning\"\n  STR_FLYING_SUIT: \"Flygarrustning\"\n  STR_HWP_ROCKETS: \"VP Raketer\"\n  STR_HWP_FUSION_BOMB: \"VP Fusionsbomb\"\n  STR_LASER_WEAPONS: \"Laservapen\"\n  STR_NEW_FIGHTER_CRAFT: \"Ny Jaktplansfarkost\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Nytt Jaktplan-Trupptransportör\"\n  STR_ULTIMATE_CRAFT: \"Ultimata Farkosten\"\n  STR_LASER_PISTOL: \"Laserpistol\"\n  STR_LASER_RIFLE: \"Lasergevär\"\n  STR_HEAVY_LASER: \"Tung Laserkarbin\"\n  STR_LASER_CANNON: \"Laserkanon\"\n  STR_PLASMA_CANNON: \"Plasmakanon\"\n  STR_FUSION_MISSILE: \"Fusionsmissil\"\n  STR_LASER_DEFENSE: \"Laserförsvar\"\n  STR_PLASMA_DEFENSE: \"Plasmaförsvar\"\n  STR_FUSION_DEFENSE: \"Fusionsförsvar\"\n  STR_GRAV_SHIELD: \"Grav. Sköld\"\n  STR_MIND_SHIELD: \"Sinnesköld\"\n  STR_PSI_LAB: \"Psi-Lab\"\n  STR_MOTION_SCANNER: \"Rörelseskanner\"\n  STR_MEDI_KIT: \"Första-Hjälpen-verktyg\"\n  STR_TANK_CANNON: \"Tank/Kanon\"\n  STR_TANK_ROCKET_LAUNCHER: \"Tank/Raket\"\n  STR_TANK_LASER_CANNON: \"Tank/Laserkanon\"\n  STR_HOVERTANK_PLASMA: \"Svävartank/Plasma\"\n  STR_HOVERTANK_LAUNCHER: \"Svävartank/Fusionskanon\"\n  STR_STINGRAY_LAUNCHER: \"Stingrocksavfyrare\"\n  STR_AVALANCHE_LAUNCHER: \"Lavinavfyrare\"\n  STR_CANNON: \"Kanon\"\n  STR_FUSION_BALL_LAUNCHER: \"Fusionsbollavfyrare\"\n  STR_PLASMA_BEAM: \"Plasmastråle\"\n  STR_STINGRAY_MISSILES: \"Stingrockemissil\"\n  STR_AVALANCHE_MISSILES: \"Lavinmissil\"\n  STR_CANNON_ROUNDS_X50: \"Kanonskott (x50)\"\n  STR_FUSION_BALL: \"Fusionsboll\"\n  STR_SOLDIER: \"Soldat\"\n  STR_SCIENTIST: \"Forskare\"\n  STR_ENGINEER: \"Ingenjör\"\n  STR_NORTH_AMERICA: \"Nordamerika\"\n  STR_ARCTIC: \"Arktisk\"\n  STR_ANTARCTICA: \"Antarktis\"\n  STR_SOUTH_AMERICA: \"Sydamerika\"\n  STR_EUROPE: \"Europa\"\n  STR_NORTH_AFRICA: \"Nordafrika\"\n  STR_SOUTHERN_AFRICA: \"Sydafrika\"\n  STR_CENTRAL_ASIA: \"Centralasien\"\n  STR_SOUTH_EAST_ASIA: \"Sydöstra Asien\"\n  STR_SIBERIA: \"Sibirien\"\n  STR_AUSTRALASIA: \"Australasien\"\n  STR_PACIFIC: \"Stilla Havet\"\n  STR_NORTH_ATLANTIC: \"Norra Atlanten\"\n  STR_SOUTH_ATLANTIC: \"Sydatlanten\"\n  STR_INDIAN_OCEAN: \"Indiska Oceanen\"\n  STR_ALIEN_RESEARCH: \"Utomjordisk Forskning\"\n  STR_ALIEN_HARVEST: \"Utomjordisk Skördning\"\n  STR_ALIEN_ABDUCTION: \"Utomjordisk Bortföring\"\n  STR_ALIEN_INFILTRATION: \"Utomjordisk Infiltrering\"\n  STR_ALIEN_BASE: \"Utomjordisk Bas\"\n  STR_ALIEN_TERROR: \"Utomjordisk terror\"\n  STR_ALIEN_RETALIATION: \"Utomjordisk Vedergällning\"\n  STR_ALIEN_SUPPLY: \"Utomjordisk Materialtransport\"\n  STR_MAXIMUM_SPEED: \"Maxfart\"\n  STR_HYPER_WAVE_DECODER_UC: \"HYPERVÅGSAVKODARE\"\n  STR_SKYRANGER: \"SKYVANDRARE\"\n  STR_LIGHTNING: \"BLIXTEN\"\n  STR_AVENGER: \"HÄMNARE\"\n  STR_INTERCEPTOR: \"JAKTPLAN\"\n  STR_FIRESTORM: \"ELDSTORM\"\n  STR_UFO: \"UFO\"\n  STR_STINGRAY: \"STINGROCKA\"\n  STR_AVALANCHE: \"LAVINEN\"\n  STR_CANNON_UC: \"KANON\"\n  STR_FUSION_BALL_UC: \"FUSIONSBOLL\"\n  STR_LASER_CANNON_UC: \"LASERKANON\"\n  STR_PLASMA_BEAM_UC: \"PLASMASTRÅLE\"\n  STR_DAMAGE_CAPACITY: \"Skadekapacitet\"\n  STR_WEAPON_POWER: \"Vapenkraft\"\n  STR_WEAPON_RANGE: \"Vapenräckvidd\"\n  STR_ACCESS_LIFT: \"Entréhiss\"\n  STR_LABORATORY: \"Laboratorie\"\n  STR_WORKSHOP: \"Verkstad\"\n  STR_SMALL_RADAR_SYSTEM: \"Litet Radarsystem\"\n  STR_LARGE_RADAR_SYSTEM: \"Stort Radarsystem\"\n  STR_MISSILE_DEFENSES: \"Missilförsvar\"\n  STR_GENERAL_STORES: \"Lagerutrymme\"\n  STR_ALIEN_CONTAINMENT: \"Utomjordingsförvaring\"\n  STR_LASER_DEFENSES: \"Laserförsvar\"\n  STR_PLASMA_DEFENSES: \"Plasmaförsvar\"\n  STR_FUSION_BALL_DEFENSES: \"Fusionbollsförsvar\"\n  STR_PSIONIC_LABORATORY: \"Psioniskt Laboratorium\"\n  STR_HYPER_WAVE_DECODER: \"Hypervågsavkodare\"\n  STR_HANGAR: \"Hangar\"\n  STR_USA: \"USA\"\n  STR_RUSSIA: \"RYSSLAND\"\n  STR_UK: \"STORBRITANNIEN\"\n  STR_FRANCE: \"FRANKRIKE\"\n  STR_GERMANY: \"TYSKLAND\"\n  STR_ITALY: \"ITALIEN\"\n  STR_SPAIN: \"SPANIEN\"\n  STR_CHINA: \"KINA\"\n  STR_JAPAN: \"JAPAN\"\n  STR_INDIA: \"INDIEN\"\n  STR_BRAZIL: \"BRASILIEN\"\n  STR_AUSTRALIA: \"AUSTRALIEN\"\n  STR_NIGERIA: \"NIGERIA\"\n  STR_SOUTH_AFRICA: \"SYDAFRIKA\"\n  STR_EGYPT: \"EGYPTEN\"\n  STR_CANADA: \"KANADA\"\n  STR_TANK: \"Tank\"\n  STR_CIVILIAN: \"Civilist\"\n  STR_JAN: \"Jan\"\n  STR_FEB: \"Feb\"\n  STR_MAR: \"Mar\"\n  STR_APR: \"Apr\"\n  STR_MAY: \"Maj\"\n  STR_JUN: \"Jun\"\n  STR_JUL: \"Jul\"\n  STR_AUG: \"Aug\"\n  STR_SEP: \"Sep\"\n  STR_OCT: \"Okt\"\n  STR_NOV: \"Nov\"\n  STR_DEC: \"Dec\"\n  STR_INTERNATIONAL_RELATIONS: \"Internationella Relationer\"\n  STR_COUNTRY: \"Land\"\n  STR_FUNDING: \"Finansiering\"\n  STR_CHANGE: \"Ändra\"\n  STR_WEAPON_SYSTEMS: \"VAPENSYSTEM\"\n  STR_HWPS: \"VP:s\"\n  STR_DAMAGE_UC_: \"SKADA>{ALT}{0}\"\n  STR_ACCESS_LIFT_UFOPEDIA: \"Entréliften tillåter utrustning och personal att komma in eller ut från den underjordiska basen. Det är alltid liften som byggs först i en ny bas. Liften är sårbar för intrång från potentiellt fientliga styrkor.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Varje logement får plats med 50 anställda. Varje anläggning har fritidsrum för avkoppling samt mat- och sovfaciliteter.\"\n  STR_LABORATORY_UFOPEDIA: \"Upp till 50 forskare kan jobba i laboratorieanläggningen. Laboratorierna är utrustade med den senaste sortens teknologi för forskning inom material, biokemi och kosmologi. De har privilegierad åtkomst till världens bästa forskningslabb inklusive militära inrättningar.\"\n  STR_WORKSHOP_UFOPEDIA: \"En verkstad innehåller alla verktyg för att tillverka utrustning baserad på designritningar från forskningslabbet. Upp till 50 ingenjörer kan arbeta i verkstaden, men objekt under konstruktion kommer också att ta upp plats.\"\n  STR_SMALL_RADAR_SYSTEM_UFOPEDIA: \"Ett litet radarsystem med en effektiv räckvidd på 300 nautiska mil som är sammankopplat med ett satellitsystem för markavsökning. Varje system har 10% chans att detektera ett normalstort föremål var 30:e minut.\"\n  STR_LARGE_RADAR_SYSTEM_UFOPEDIA: \"Ett stort radarsystem med en effektiv räckvidd på 450 nautiska mil som är sammankopplat med ett satellitsystem för markavsökning. Varje system har 20% chans att detektera ett normalstort föremål var 30:e minut.\"\n  STR_MISSILE_DEFENSES_UFOPEDIA: \"Missilförsvar ger ett viss skydd mot intrång från fientliga farkoster som försöker landa nära basen.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"All utrustning såsom vapen, ammo, beslagtaget material och Vapenplattformar förvaras i förrådet. Detta inkluderar utrustning som tilldelats farkoster i hangarer.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"Levande utomjordingar behöver antagligen en speciell sorts livsmiljö för att kunna överleva. Anläggningen kan hålla upp till tio utomjordiska livsformer i fristående enheter.\"\n  STR_LASER_DEFENSES_UFOPEDIA: \"Laserförsvar ger skydd mot intrång från fientliga farkoster.\"\n  STR_PLASMA_DEFENSES_UFOPEDIA: \"Plasmastråleförsvar ger ett kraftfullt och effektivt skydd mot inträngande fiendefarkoster.\"\n  STR_FUSION_BALL_DEFENSES_UFOPEDIA: \"Fusionmissilsförsvar ger det effektivaste skyddet mot utomjordiska attacker. Dessa missiler skapar en antimaterisk implosion som förstör allting inom en specifik radie.\"\n  STR_GRAV_SHIELD_UFOPEDIA: \"Gravitationsskölden stöter tillbaka utomjordiska farkoster som försöker landa nära basen tillräckligt länge för att försvarssystemen får skjuta en gång till. I praktiken dubblerar detta alla försvarssystems effektivitet i basen.\"\n  STR_MIND_SHIELD_UFOPEDIA: \"Eftersom de utomjordiska farkosterna använder hjärnvågor för att hitta människor borde den effektivaste motmetoden vara att gömma hjärnvågorna som kommer från basen. Denna anläggning minskar risken för upptäckt drastiskt.\"\n  STR_PSIONIC_LABORATORY_UFOPEDIA: \"Det psioniska labbet kan låsa upp den psioniska potentialen i alla basens soldater och ge dem träning i att använda sina förmågor. Varje labb kan träna upp till tio soldater. Träningen fördelas i slutet av varje månad. Psioniska färdigheter i kombination med en Psi-förstärkare kan användas för att genomföra psioniska attacker i strid.\"\n  STR_HYPER_WAVE_DECODER_UFOPEDIA: \"Utomjordingarnas kommunikation förlitar sig på supradimensionella vågor som transporteras nästan ögonblickligen. Avkodaranläggningen genskjuter UFO-signalerna och avkodar informationen. Denna visar UFO-typ, besättningens art  samt vad för sorts uppdrag det är ute på.\"\n  STR_HANGAR_UFOPEDIA: \"Varje hangar kan rymma en farkost. Det finns utrustning för underhållning, tankning och reparation av X-Com farkoster. Varje farkost stationerad vid en bas måste ha en tillgänglig hangar tilldelad till den som inte kan bli använd av någon annan farkost, även om den tilldelade farkosten är ute på ett uppdrag.\"\n  STR_PISTOL_UFOPEDIA: \"Semiautomatisk pistol med 12 skotts kapacitet.\"\n  STR_RIFLE_UFOPEDIA: \"Detta högst träffsäkra prickskyttegevär har ett lasersikte och tar 6.7 mm ammunition i 20-skottsmagasin.\"\n  STR_HEAVY_CANNON_UFOPEDIA: \"Den tunga kanonen är ett förödande men otympligt vapen. Dess mångsidighet kommer från det faktum att det kan ta tre olika sorters ammunition: pansarbrytande (PB), flambar (F) samt högexplosivt (HE).\"\n  STR_AUTO_CANNON_UFOPEDIA: \"Automatkanonen kombinerar mångsidigheten i en tung kanon med en snabbare eldhastighet.\"\n  STR_ROCKET_LAUNCHER_UFOPEDIA: \"Raketgeväret är ett laserassisterat vapensystem som kan avfyra tre olika sorters missiler.\"\n  STR_LASER_PISTOL_UFOPEDIA: \"Laserpistolen är en effektiv implementering av ny teknologi. Den har samma fördelar som en pistol med snabbare och mer träffsäker eldgivning.\"\n  STR_LASER_RIFLE_UFOPEDIA: \"Lasergeväret är en kraftfullare och mer träffsäker version av den tidigare pistoldesignen.\"\n  STR_HEAVY_LASER_UFOPEDIA: \"Den tunga laserkarbinen är otymplig men väldigt effektiv.\"\n  STR_GRENADE_UFOPEDIA: \"Denna standardgranat har en exakt och sofistikerad timer för precis kontroll.\"\n  STR_SMOKE_GRENADE_UFOPEDIA: \"Rökgranater används för att ge skydd i öppna stridsscenarier. Bör användas försiktigt då röken även kan dölja fienden.\"\n  STR_PROXIMITY_GRENADE_UFOPEDIA: \"En rörelsekänslig granat kan kastas som en vanlig granat men exploderar om något kommer i närheten efter att den landat. Skicklighet och försiktighet krävs för att använda den effektivt.\"\n  STR_HIGH_EXPLOSIVE_UFOPEDIA: \"Denna bomb bör endast användas för demoleringsjobb. Håll personal borta från sprängområdet.\"\n  STR_MOTION_SCANNER_UFOPEDIA: \"Denna sofistikerade apparat använder olika detektorer och avancerade datoralgoritmer för att hitta rörliga fientliga enheter, men den kräver övning för att användas effektivt. Klicka på rörelsescanner ikonen på den taktiska displayen. Välj \\\"Använd Skanner\\\" från menyn. Skannern visar en pil i mitten vilken är vänd i den skannande soldatens riktning (Norr är uppåt på displayen). De blinkande prickarna är enheter som rört sig nyligen. Större samt snabbare enheter ger ifrån sig större prickar. Stillastående enheter kan inte upptäckas.\"\n  STR_MEDI_KIT_UFOPEDIA: \"Första-hjälpen-verktyget kombinerar en läkestation med smärtstillande och stimulantia. För att använda verktyget måste du vända dig mot den skadade soldaten. Om soldaten är medvetslös måste du ställa dig på den liggande kroppen. Klicka på Första-hjälpen-verktygets ikon och välj \\\"Använd Första-hjälpen-verktyg\\\" från menyn.{NEWLINE}HELNING> Röda kroppsdelar visar allvarliga skador. Klicka på en kroppsdel som är skadad och klicka på \\\"HELA\\\"-knappen. En allvarlig skada åtgärdas och lite hälsa återställs.{NEWLINE}STIMULANTIA> Detta återställer energi och väcker medvetslösa soldater. För att väcka medvetslösa måste du stå i samma ruta som den drabbades kropp ligger i.{NEWLINE}SMÄRTSTILLANDE> Detta återställer lika mycket moral som soldaten förlorat i hälsa.\"\n  STR_PSI_AMP_UFOPEDIA: \"Psi-förstärkaren kan bara användas av soldater med psioniska förmåga. Under strid klickar du på Psi-förstärkaren i soldatens hand. Klicka vilken sorts attack du vill ha och välj målet med muspilen. Det finns två sorters psioniska attacker:{NEWLINE}DEMORALISERA ENHET> Om attacken lyckas sänks målets moral vilket kan orsaka panikattacker hos enheten.{NEWLINE}TANKEKONTROLL> Om attacken lyckas får du direkt kontroll över fiendeenheter som om de var dina egna. Det är svårare att lyckas med denna sortens attack.\"\n  STR_STUN_ROD_UFOPEDIA: \"Denna apparat kan enbart användas i närstrid men kan neutralisera en levande organism utan att döda den.\"\n  STR_MIND_PROBE_UFOPEDIA: \"Tankeläsaren är en utomjordisk kommunikationsapparat som används för att få information direkt från hjärnvågor. X-Com soldater kan använda apparaten i strid för att se en utomjordings egenskaper. Klicka på tankeläsaren och sedan 'använd'. Klicka sedan på en utomjording med pekaren.\"\n  STR_PLASMA_PISTOL_UFOPEDIA: \"Plasmapistoler är dödliga, utomjordiskt vapen baserade på att partiklar accelereras inuti ett minimalt antigravitationsfält.\"\n  STR_PLASMA_RIFLE_UFOPEDIA: \"Detta är ett förödande kraftfullt vapen baserat på att accelerera partiklar inifrån ett minimalt anti-gravitationsfält.\"\n  STR_HEAVY_PLASMA_UFOPEDIA: \"Detta är ett förödande kraftfullt vapen som accelererar partiklar inifrån ett minimalt anti-gravitationsfält.\"\n  STR_BLASTER_LAUNCHER_UFOPEDIA: \"Detta är en utomjordisk, målsökande missilramp som avfyrar kraftfulla tryckvågsbomber. Varje gång du klickar för att avfyra vapnet skapar du en vägpunkt för bomben att följa. När du skapat tillräckligt med vägpunkter klickar du på specialavfyrnings-ikonen.\"\n  STR_SMALL_LAUNCHER_UFOPEDIA: \"En liten granatkastare som avfyrar bedövningsbomber. Väldigt användbar för att fånga levande utomjordingar.\"\n  STR_ALIEN_GRENADE_UFOPEDIA: \"Denna anordning fungerar precis som en vanlig granat, förutom att den är mer kraftfull.\"\n  STR_SMALL_SCOUT: \"Liten Spanare\"\n  STR_MEDIUM_SCOUT: \"Mellanstor Spanare\"\n  STR_LARGE_SCOUT: \"Stor Spanare\"\n  STR_HARVESTER: \"Skördeskepp\"\n  STR_ABDUCTOR: \"Bortförare\"\n  STR_TERROR_SHIP: \"Terrorskepp\"\n  STR_BATTLESHIP: \"Slagskepp\"\n  STR_SUPPLY_SHIP: \"Utrustnings-skepp\"\n  STR_RATING: \"GRADERING> {0}\"\n  STR_RATING_TERRIBLE: \"FRUKTANSVÄRT!\"\n  STR_RATING_POOR: \"DÅLIG!\"\n  STR_RATING_OK: \"OK\"\n  STR_RATING_GOOD: \"BRA!\"\n  STR_RATING_EXCELLENT: \"UTMÄRKT!\"\n  STR_SCORE: \"POÄNG\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"X-COM-PROJEKTETS MÅNADSRAPPORT\"\n  STR_MONTH: \"Månad> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"Rådet av finansierande nationer är generellt nöjt med dina framsteg så här långt.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"Rådet av finansierande nationer är väldigt nöjt med dina utmärkta framsteg. Fortsätt med det bra jobbet!\"\n  STR_COUNCIL_IS_DISSATISFIED: \"Rådet av finansierande nationer är missnöjt med din insats. Du måste förbättra din effektivitet att hantera det utomjordiska hotet annars kan projektet stängas ned.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"Du har inte lyckats hantera den utomjordiska invasionen och rådet av finansierande nationer har tyvärr beslutat att stänga ned projektet. Varje nation kommer hantera problemet var för sig som de anser bäst. Vi kan bara hoppas att vi kan förhandla med dessa fientliga styrkor och att jordens befolkning vänjer sig vid utomjordiska besökare.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} är väldigt nöjd med din förmåga att hantera hot inom nationens gränser och har beslutat att öka sitt anslag.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} är väldigt nöjda med din förmåga att hantera lokala intrång från utomjordingarna och har beslutat att öka sina anslag.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} och {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} är missnöjd med din förmåga att hantera den utomjordiska verksamheten i dess område och har beslutat att minska sitt finansiella anslag.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} är missnöjda med din förmåga att hantera utomjordisk verksamhet inom deras gränser och har beslutat att minska sina anslag.\"\n  STR_KNOTS: \"{0} knop\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} har skrivit under ett hemligt avtal med okända, utomjordiska styrkor och dragit sig ur projektet.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} har skrivit under hemliga avtal med okända, utomjordiska styrkor och dragit sig ur projektet.\"\n  STR_MONTHLY_RATING: \"Månadsutvärdering> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Inkomständring> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"Rådet av finansierande länder är missnöjt med din ekonomiska situation. Du måste sänka din skuld under $1 miljon annars kommer projektet avslutas.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"HYPERVÅGS-ÖVERFÖRING AVKODAD\"\n  STR_CRAFT_TYPE: \"FARKOSTTYP\"\n  STR_RACE: \"ART\"\n  STR_MISSION: \"UPPDRAG\"\n  STR_ZONE: \"ZON\"\n  STR_ALLOCATE_RESEARCH: \"Fördela Forskning\"\n  STR_ALLOCATE_MANUFACTURE: \"Fördela Tillverkning\"\n  STR_NEW_YORK: \"New York\"\n  STR_WASHINGTON: \"Washington\"\n  STR_LOS_ANGELES: \"Los Angeles\"\n  STR_MONTREAL: \"Montréal\"\n  STR_HAVANA: \"Havanna\"\n  STR_MEXICO_CITY: \"Mexico City\"\n  STR_CHICAGO: \"Chicago\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_DALLAS: \"Dallas\"\n  STR_BRASILIA: \"Brasilia\"\n  STR_BOGOTA: \"Bogotá\"\n  STR_BUENOS_AIRES: \"Buenos Aires\"\n  STR_SANTIAGO: \"Santiago\"\n  STR_RIO_DE_JANEIRO: \"Rio de Janeiro\"\n  STR_LIMA: \"Lima\"\n  STR_CARACAS: \"Caracas\"\n  STR_LONDON: \"London\"\n  STR_PARIS: \"Paris\"\n  STR_BERLIN: \"Berlin\"\n  STR_MOSCOW: \"Moskva\"\n  STR_ROME: \"Rom\"\n  STR_MADRID: \"Madrid\"\n  STR_BUDAPEST: \"Budapest\"\n  STR_LAGOS: \"Lagos\"\n  STR_CAIRO: \"Kairo\"\n  STR_CASABLANCA: \"Casablanca\"\n  STR_PRETORIA: \"Pretoria\"\n  STR_NAIROBI: \"Nairobi\"\n  STR_CAPE_TOWN: \"Kapstaden\"\n  STR_KINSHASA: \"Kinshasa\"\n  STR_ANKARA: \"Ankara\"\n  STR_DELHI: \"Delhi\"\n  STR_KARACHI: \"Karachi\"\n  STR_BAGHDAD: \"Bagdad\"\n  STR_TEHRAN: \"Teheran\"\n  STR_BOMBAY: \"Mumbai\"\n  STR_CALCUTTA: \"Calcutta\"\n  STR_TOKYO: \"Tokyo\"\n  STR_BEIJING: \"Peking\"\n  STR_BANGKOK: \"Bangkok\"\n  STR_MANILA: \"Manila\"\n  STR_SEOUL: \"Seoul\"\n  STR_SINGAPORE: \"Singapore\"\n  STR_JAKARTA: \"Djakarta\"\n  STR_SHANGHAI: \"Shanghai\"\n  STR_HONG_KONG: \"Hong Kong\"\n  STR_NOVOSIBIRSK: \"Novosibirsk\"\n  STR_CANBERRA: \"Canberra\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_MELBOURNE: \"Melbourne\"\n  STR_PERTH: \"Perth\"\n  STR_PSI_TRAINING: \"Psionisk Träning\"\n  STR_PSIONIC_TRAINING: \"PSIONISK TRÄNING\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Återstående Psi-labskapacitet> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"Psionisk{NEWLINE}Styrka\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"Psionisk Färdighet{NEWLINE}/Förbättring\"\n  STR_PSI_AMP: \"Psi-Förstärkare\"\n  STR_IN_TRAINING: \"Genomgår{NEWLINE}Träning?\"\n  STR_TARGETTED_BY: \"MÅLINRIKTAD AV:\"\n  STR_WEAPONS_CREW_HWPS: \"VAPEN/{NEWLINE}BESÄTTNING/VP\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"har låg bränslenivå,{NEWLINE}återvänder till bas\"\n  STR_SOLDIER_LIST: \"Soldatlista\"\n  STR_RANK_: \"GRAD> {ALT}{0}\"\n  STR_MISSIONS: \"UPPDRAG> {ALT}{0}\"\n  STR_KILLS: \"DÖDADE> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"SJUKDAGAR> {ALT}{0}\"\n  STR_TIME_UNITS: \"TIDSENHETER\"\n  STR_STAMINA: \"UTHÅLLIGHET\"\n  STR_HEALTH: \"HÄLSA\"\n  STR_BRAVERY: \"MOD\"\n  STR_REACTIONS: \"REAKTIONSFÖRMÅGA\"\n  STR_FIRING_ACCURACY: \"SKYTTEFÖRMÅGA\"\n  STR_THROWING_ACCURACY: \"KASTFÖRMÅGA\"\n  STR_STRENGTH: \"STYRKA\"\n  STR_PSIONIC_STRENGTH: \"PSIONISK STYRKA\"\n  STR_PSIONIC_SKILL: \"PSIONISK FÖRMÅGA\"\n  STR_NEW_RANK: \"NY GRAD\"\n  STR_PROMOTIONS: \"Befordran\"\n  STR_SOLDIERS_UC: \"SOLDATER\"\n  STR_TANK_CANNON_UFOPEDIA: \"Automatiserade vapenplattformar är designade för att komplettera X-Com trupper. Kombination av hög eldkraft och kraftigt pansar gör dessa enheter praktiska för strider över öppen terräng. Var noggrann med att ha tillräckligt med ammunition i dina lager för att kunna ladda upp plattformen för nästa uppdrag. De laddas automatiskt när de tilldelas till en trupp.\"\n  STR_TANK_ROCKET_LAUNCHER_UFOPEDIA: \"Denna automatiserade Vapenplatform är beväpnad med kraftfulla raketer. De kommer ha en förödande verkan på alla utomjordiska fiender. Se till att förrådet är välförsett med VP-raketer.\"\n  STR_TANK_LASER_CANNON_UFOPEDIA: \"Laservapen är ett användbart tillägg för vapenplattformar. De kombinerar hög eldkraft med oändlig ammunition.\"\n  STR_HOVERTANK_PLASMA_UFOPEDIA: \"Utomjordisk teknologi har gett Vapenplattformen ett nytt perspektiv på livet. Den luftburna rörelsefriheten och kraften i en plasmastråle är en dödlig kombination.\"\n  STR_HOVERTANK_LAUNCHER_UFOPEDIA: \"Denna svävartank har en fusionsbollavfyrare med storslagen sprängkraft. Använd den försiktigt. Du måste tillverka fusionsbollarna för att kunna fullt ladda vapenplattformen mellan uppdragen. En fusionsboll är ett intelligent målsökande vapen. För att avfyra det måste du välja minst en vägpunkt med muspilen och sedan klicka på avfyringsknappen.\"\n  STR_HEAVY_PLASMA_CLIP_UFOPEDIA: \"Denna kompakta enhet används som ammunition i den Tunga Plasmakarbinen. Den innehåller en liten mängd Elerium.\"\n  STR_PLASMA_RIFLE_CLIP_UFOPEDIA: \"Detta lilla objekt används som kraftkälla för ett plasmagevär - ett mellan-kraftfullt, utomjordiskt vapen. Innehåller en liten mängd Elerium.\"\n  STR_PLASMA_PISTOL_CLIP_UFOPEDIA: \"Kraftkälla för plasmapistolen. Innehåller Elerium - källan till all utomjordisk eldkraft.\"\n  STR_STUN_BOMB_UFOPEDIA: \"Knockoutbomber används för att fånga levande människoexemplar, men de kan också användas mot de flesta utomjordiska arter. De avfyras från lilla granatkastaren.\"\n  STR_ALIEN_RESEARCH_UFOPEDIA: \"Utomjordingarnas forskningsuppdrag används för att samla grundläggande data om Jorden och dess invånare. Små farkoster används mest med oregelbundna landningar i öde områden. Den här typen av aktivitet utgör det minsta hotet för X-Coms verksamhet då det skapar förhållandevis lite oro bland regering och allmänhet.\"\n  STR_ALIEN_HARVEST_UFOPEDIA: \"Utomjordingarna har många användningsområden för Jordens djurfauna. Djur förs bort i hemlighet och återbördas med organ borttagna. Boskapsstympningar är vanligast förekommande i relation till UFO-iakttagelser. Dessa händelser oroar regeringar och deras medborgare märkbart. Detta sker mest i jordbruksområden. Teorin är att \\\"djurskördarna\\\" visar att utomjordingarna från början \\\"sådde\\\" Jorden med dess flora och fauna och att de nu återkommit för att skörda.\"\n  STR_ALIEN_ABDUCTION_UFOPEDIA: \"Detta är den lömskaste formen av utomjordisk aktivitet. Historier från människor som blir bortförda rapporteras i media, trots utomjordingarnas försök att sudda ut offrens minnen av händelsen. De bortförda berättar om förödmjukande fysiska undersökningar som inkluderar inplantering av utomjordiska foster och bisarra genetiska experiment. Syftet med dessa aktiviteter verkar kopplat till genetiska mutationer samt genmanipulation av utomjordingarnas egna arvsmassa. Dessa aktiviteter orsakar stor oro och sker i bebodda orter och städer.\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"Jordens regeringar kan bli infiltrerade av utomjordiska agenter med mänskligt utseende. Detta kan resultera i officiell kontakt mellan utomjordingarna och en regering på högsta nivå. Följden av detta är intensiv UFO-aktivitet i närheten av större städer. Utomjordingarna kommer försöka sluta överenskommelser med jordens regeringar genom att erbjuda kunskap om deras överlägsna teknologi. I utbyte tillåter regeringen dem operera i landet ostört. Denna aktivitet utgör det största hotet mot X-Com. Om en regering sluter ett avtal kommer dess finansiering av X-Com-projektet upphöra.\"\n  STR_ALIEN_BASE_UFOPEDIA: \"Utomjordingarna kommer bygga hemliga, underjordiska baser på avlägsna platser. Efter viss rekognoscering kommer ökande UFO-aktivitet när basen byggs. Dessa baser har faciliteter för experiment på bortförda människor och kan understödja mer aktivitet i området. Närvaron av en bas kommer att leda till fler incidentrapporter utan närvaron av UFO:n. För att hitta en bas måste en X-Com farkost patrullera ett område i några timma för att ha någon chans att lokalisera den exakta positionen.\"\n  STR_ALIEN_TERROR_UFOPEDIA: \"När utomjordingarna terroriserar en stad använder de specialstyrkor med hög eldkraft. Civilister blir direkt hotade och landets regering måste utrymma hela områden. Syftet med dessa angrepp är att generera tillräcklig masshysteri för att regeringen ska hota att lämna X-Com-projektet.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"Om X-Com:s flygflottilj är för framgångsrika i att skjuta ner UFO:n kan utomjordingarna sätta in motangrepp. Detta kan resultera i direkta anfall mot X-Com:s baser. Så länge UFO:n hålls borta från X-Com:s baser är risken liten, då dessa kan rapportera basens position om de kommer för nära.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"När en utomjordisk bas konstruerats är den försedd på regelbunden basis av ett speciellt fraktfartyg. Om en av dessa fartyg är siktade när de landar är det ett säkert tecken på att en utomjordisk bas är i närheten.\"\n  STR_SMALL_SCOUT_UFOPEDIA: \"Denna minimala farkost är främst till för rekognosering och forskning. De föregår oftast större skepp i början av utomjordingarnas uppdrag.\"\n  STR_MEDIUM_SCOUT_UFOPEDIA: \"Det mellanstora spaningsskeppet utgör ett minimalt hot mot jordens styrkor. Används normalt som förtrupp för större farkoster.\"\n  STR_LARGE_SCOUT_UFOPEDIA: \"Den största spanarfarkosten är ett mångsidigt skepp som används av utomjordingarna i alla uppdrag.\"\n  STR_HARVESTER_UFOPEDIA: \"Skördaren har en lucka på sin undersida och är utrustad med lyftanordningar för att lyfta boskap och andra djur. Laserskärare används för att avlägsna material och kroppen dumpas ut på marken. Det finns även förvaringsbehållare för kroppsdelar.\"\n  STR_ABDUCTOR_UFOPEDIA: \"Denna farkost är utrustad med ett undersökningsrum för att utföra rysliga experiment på levande människor. Offret är oftast paralyserat genom telepatiska krafter men är fortfarande vid medvetande under operationstillfället.\"\n  STR_TERROR_SHIP_UFOPEDIA: \"Terrorskeppet har förvaringsutrymmen för större terrorvapen och varelser. De används för att transportera dessa terrorenheter till befolkade områden.\"\n  STR_BATTLESHIP_UFOPEDIA: \"Slagskeppet är den största och mest kraftfulla utomjordiska farkosten. Den är normalt den primära uppdragsfarkosten och är beväpnad med kraftfulla vapen och ett stort antal besättningsmedlemmar.\"\n  STR_SUPPLY_SHIP_UFOPEDIA: \"Transportskeppet används under konstruktionen av utomjordiska baser och för att förse existerande baser. De levererar matkontainrar och reproduktionskammare.\"\n  STR_DISMANTLE: \"Demontera\"\n  STR_FACILITY_IN_USE: \"ANLÄGGNING ANVÄNDS\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"KAN INTE DEMONTERA ANLÄGGNING!{SMALLLINE}Alla basanläggningar måste vara länkade till entréhissen.\"\n  STR_TRANSFER_ITEMS_TO: \"Överför Föremål till {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"INGEN UTOMJORDINGSFÖRVARING FÖR ÖVERFÖRING!{SMALLLINE}Levande utomjordingar behöver Utomjordingssförvaring för att kunna överleva.\"\n  STR_AMOUNT_AT_DESTINATION: \"ANTAL VID{NEWLINE}DESTINATION\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"Utomjording dör pga brist på Utomjordingsförvaring i bas\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"INGA LEDIGA LOGIPLATSER!{SMALLLINE}Den destinerade basen har inte tillräckligt med plats i logement för farkostens besättning.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"OTILLRÄCKLIGT MED UTRYMME!{SMALLLINE}Destinationsbasen har inte tillräckligt med förvaringsutrymme för farkostens utrustning.\"\n  STR_ITEMS_ARRIVING: \"Föremål Ankommer\"\n  STR_DESTINATION_UC: \"DESTINATION\"\n  STR_PISTOL: \"Pistol\"\n  STR_PISTOL_CLIP: \"Pistolmagasin\"\n  STR_RIFLE: \"Gevär\"\n  STR_RIFLE_CLIP: \"Gevärsmagasin\"\n  STR_HEAVY_CANNON: \"Tung Kanon\"\n  STR_HC_AP_AMMO: \"TK-PB Ammo\"\n  STR_HC_HE_AMMO: \"TK-HE Ammo\"\n  STR_HC_I_AMMO: \"TK-F Ammo\"\n  STR_AUTO_CANNON: \"Auto-Kanon\"\n  STR_AC_AP_AMMO: \"AK-PB Ammo\"\n  STR_AC_HE_AMMO: \"AK-HE Ammo\"\n  STR_AC_I_AMMO: \"AK-I Ammo\"\n  STR_ROCKET_LAUNCHER: \"Raketgevär\"\n  STR_SMALL_ROCKET: \"Liten Raket\"\n  STR_LARGE_ROCKET: \"Stor Raket\"\n  STR_INCENDIARY_ROCKET: \"Flammracket\"\n  STR_GRENADE: \"Granat\"\n  STR_SMOKE_GRENADE: \"Rökgranat\"\n  STR_PROXIMITY_GRENADE: \"Rörelsekänslig granat\"\n  STR_HIGH_EXPLOSIVE: \"Högexplosivt\"\n  STR_STUN_ROD: \"Bedövningsstav\"\n  STR_HEAVY_PLASMA: \"Tung Plasmakarbin\"\n  STR_HEAVY_PLASMA_CLIP: \"Tungt Plasmamagasin\"\n  STR_PLASMA_RIFLE: \"Plasmagevär\"\n  STR_PLASMA_RIFLE_CLIP: \"Plasmagevärsmagasin\"\n  STR_PLASMA_PISTOL: \"Plasmapistol\"\n  STR_PLASMA_PISTOL_CLIP: \"Plasmapistolmagasin\"\n  STR_BLASTER_LAUNCHER: \"Tryckvågsbombsavfyrare\"\n  STR_BLASTER_BOMB: \"Tryckvågsbomb\"\n  STR_SMALL_LAUNCHER: \"Liten Granatkastare\"\n  STR_STUN_BOMB: \"Bedövningsbomb\"\n  STR_ALIEN_GRENADE: \"Utomjordisk Granat\"\n  STR_ELERIUM_115: \"Elerium-115\"\n  STR_MIND_PROBE: \"Tankeläsare\"\n  STR_SECTOID_CORPSE: \"Sectoid Kropp\"\n  STR_SNAKEMAN_CORPSE: \"Ormman Kropp\"\n  STR_ETHEREAL_CORPSE: \"Eterisk Kropp\"\n  STR_MUTON_CORPSE: \"Muton Kropp\"\n  STR_FLOATER_CORPSE: \"Svävare Kropp\"\n  STR_CELATID_CORPSE: \"Celatid Kropp\"\n  STR_SILACOID_CORPSE: \"Silacoid Kropp\"\n  STR_CHRYSSALID_CORPSE: \"Chryssalid Kropp\"\n  STR_REAPER_CORPSE: \"Lieman Kropp\"\n  STR_SECTOPOD_CORPSE: \"Sectopod Kropp\"\n  STR_CYBERDISC_CORPSE: \"Cyberdisk Kropp\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"Inte tillräckligt med ammunition för att rusta VP{SMALLLINE}Varje VP behöver {0} {1}.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Otillräckligt med materiel för att fullt återbeväpna truppen\"\n  STR_MARS_CYDONIA_LANDING: \"Mars: Landning på Cydonia\"\n  STR_MARS_CYDONIA_LANDING_BRIEFING: \"Ditt Hämnarskepp har landat i regionen Cydonia på Mars yta. Vår information indikerar att en av pyramiderna innehåller en grön hiss till ett underjordiskt komplex. När du samlat dina soldater i hiss-området klickar du på \\\"överge uppdrag\\\"-ikonen för att fortsätta till nästa nivå.\"\n  STR_MARS_THE_FINAL_ASSAULT: \"Mars: Det slutgiltiga anfallet\"\n  STR_MARS_THE_FINAL_ASSAULT_BRIEFING: \"Pyramidens hiss tar dina stridströtta soldater djupt ner under planetens yta. De når till sist hjärtat på ett stort komplex av tunnlar och kammare. Den utomjordiska hjärnan är gömd någonstans i labyrinten. Den måste förstöras om Jorden ska räddas från förslavning.{NEWLINE}{NEWLINE}Lycka till!\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Du måste undersöka {NEWLINE}{0}{NEWLINE}för att kunna tillverka{NEWLINE}{1}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"Utomjordingarna har förstört den oskyddade basen {0}\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"X-Com agenter har hittat en utomjordisk bas i {0}\"\n  STR_STANDOFF: \"DÖDLÄGE\"\n  STR_CAUTIOUS_ATTACK: \"FÖRSIKTIG ATTACK\"\n  STR_STANDARD_ATTACK: \"STANDARDATTACK\"\n  STR_AGGRESSIVE_ATTACK: \"AGGRESSIV ATTACK\"\n  STR_DISENGAGING: \"AVSTÅNDSTAGANDE\"\n  STR_UFO_HIT: \"UFO TRÄFFAT!\"\n  STR_UFO_CRASH_LANDS: \"UFO KRASCHLANDAR!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"MINIMERA VID DÖDLÄGESRÄCKVIDD ENDAST\"\n  STR_UFO_RETURN_FIRE: \"UFO BESVARAR ELD!\"\n  STR_INTERCEPTOR_DAMAGED: \">>> JAKTPLAN SKADAT <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> JAKTPLAN NERSKJUTET <<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"UFO UNDGÅR JAKTPLAN!\"\n  STR_ALIENS_TERRORISE: \"UTOMJORDINGAR TERRORISERAR\"\n  STR_LONG_RANGE_DETECTION: \"Långräckviddsdetektorer\"\n  STR_STORES_UC: \"LAGER\"\n  STR_DIFFICULTY_LEVEL: \"Svårighetsgrad\"\n  STR_INTERCEPT: \"GENSKJUT\"\n  STR_BASES: \"BASER\"\n  STR_GRAPHS: \"GRAFER\"\n  STR_UFOPAEDIA_UC: \"UFOPEDIA\"\n  STR_OPTIONS_UC: \"ALTERNATIV\"\n  STR_FUNDING_UC: \"FINANSIERING\"\n  STR_5_SECONDS: \"5 s\"\n  STR_1_MINUTE: \"1 min\"\n  STR_5_MINUTES: \"5 min\"\n  STR_30_MINUTES: \"30 min\"\n  STR_1_HOUR: \"1 tim\"\n  STR_1_DAY: \"1 dag\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"X-Com Prestationstabell\"\n  STR_ENTER_NAME: \"Ange namn\"\n  STR_PERFORMANCE_RATING: \"Prestationsbetyg\"\n  STR_VICTORY_DATE: \"Segerdatum\"\n  STR_ELECTRO_FLARE: \"Elektriskt Stavljus\"\n  STR_ELECTRO_FLARE_UFOPEDIA: \"Denna anordning lyser upp med ljus när den kastas. Detta är speciellt användbart för att avslöja fiender dolda i mörker under nattuppdrag.\"\n  STR_MONTHLY_COSTS: \"Månadskostnader\"\n  STR_CRAFT_RENTAL: \"Farkosthyra\"\n  STR_SALARIES: \"Löner\"\n  STR_BASE_MAINTENANCE: \"Basunderhåll\"\n  STR_COST_PER_UNIT: \"Kostnad per enhet\"\n  STR_QUANTITY: \"Kvantitet\"\n  STR_TOTAL: \"Total\"\n  STR_IN_PSIONIC_TRAINING: \"Genomgår psionisk-träning\"\n  STR_BLASTER_BOMB_UFOPEDIA: \"Denna enhet är en högexplosiv missil med ett intelligent målangivelsesystem. Det avfyras från en tryckvågsavfyrare.\"\n  STR_FRONT_ARMOR: \"Främre pansar\"\n  STR_LEFT_ARMOR: \"Vänster Pansar\"\n  STR_RIGHT_ARMOR: \"Höger Pansar\"\n  STR_REAR_ARMOR: \"Bakre Pansar\"\n  STR_UNDER_ARMOR: \"Undre Pansar\"\n  STR_ROUNDS: \"Skott\"\n  STR_UNIT: \"ENHET>{0}\"\n  STR_ENERGY: \"ENERGI\"\n  STR_MORALE: \"MORAL\"\n  STR_ARMOR_: \"PANSAR>{0}\"\n  STR_FRONT_ARMOR_UC: \"FRÄMRE PANSAR\"\n  STR_LEFT_ARMOR_UC: \"VÄNSTER PANSAR\"\n  STR_RIGHT_ARMOR_UC: \"HÖGER PANSAR\"\n  STR_REAR_ARMOR_UC: \"BAKRE PANSAR\"\n  STR_SKILLS: \"FÄRDIGHET> {0}\"\n  STR_LEVEL: \"NIVÅ> {0}\"\n  STR_HEAD: \"HUVUD\"\n  STR_TORSO: \"TORSO\"\n  STR_RIGHT_ARM: \"HÖGER ARM\"\n  STR_LEFT_ARM: \"VÄNSTER ARM\"\n  STR_RIGHT_LEG: \"HÖGER BEN\"\n  STR_LEFT_LEG: \"VÄNSTER BEN\"\n  STR_PAIN_KILLER: \"SMÄRTSTILLANDE\"\n  STR_STIMULANT: \"PSYKOSTIMULANTIA\"\n  STR_HEAL: \"LÄK\"\n  STR_TIME_UNITS_SHORT: \"TE>{ALT}{0}\"\n  STR_WEIGHT: \"Bärvikt>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"Reakt>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"P.Färdi>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"P.Sty>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Utomjordisk artefakt\"\n  STR_AMMO_ROUNDS_LEFT: \"AMMO:{NEWLINE}SKOTT{NEWLINE}KVAR={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Smärt>{ALT}{0}{ALT}{NEWLINE}Stim>{ALT}{1}{ALT}{NEWLINE}Hela>{ALT}{2}\"\n  STR_THROW: \"Kasta\"\n  STR_AUTO_SHOT: \"Automateld\"\n  STR_SNAP_SHOT: \"Snabbskott\"\n  STR_AIMED_SHOT: \"Välriktat skott\"\n  STR_STUN: \"Bedöva\"\n  STR_PRIME_GRENADE: \"Förbered granat\"\n  STR_USE_SCANNER: \"Använd skanner\"\n  STR_USE_MEDI_KIT: \"Använd förstahjälpen\"\n  STR_LAUNCH_MISSILE: \"Avfyra missil\"\n  STR_ACCURACY_SHORT: \"Trf>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Otillräckligt med TE!\"\n  STR_NOT_ENOUGH_ENERGY: \"Slut på energi!\"\n  STR_NO_ROUNDS_LEFT: \"Inga skott kvar!\"\n  STR_NO_AMMUNITION_LOADED: \"Ingen ammunition laddad!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Fel ammunition för detta vapen!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"Vapnet redan laddat!\"\n  STR_NO_LINE_OF_FIRE: \"Ingen skottlinje!\"\n  STR_GRENADE_IS_ACTIVATED: \"Granat aktiverad!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Granat inaktiverad!\"\n  STR_THERE_IS_NO_ONE_THERE: \"Det finns ingen där!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Omöjligt att använda utomjordiska artefakter innan de undersökts.\"\n  STR_OUT_OF_RANGE: \"Utom räckvidd!\"\n  STR_UNABLE_TO_THROW_HERE: \"Oförmögen att kasta där!\"\n  STR_SET_TIMER: \"Ställ in timer\"\n  STR_HIDDEN_MOVEMENT: \"DOLD FÖRFLYTTNING\"\n  STR_TURN: \"RUNDA> {0}\"\n  STR_SIDE: \"SIDA> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Tryck på knapp för att fortsätta\"\n  STR_MIND_CONTROL: \"Tankekontroll\"\n  STR_PANIC_UNIT: \"Panikslå enhet\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Moral Attack Framgångsrik\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Tankekontroll Lyckades\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}går bärsärkargång\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}går Bärsärkargång\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}grips av Panik\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}grips av Panik\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Utomjordingar\"\n  STR_RIGHT_HAND: \"HÖGER HAND\"\n  STR_LEFT_HAND: \"VÄNSTER HAND\"\n  STR_RIGHT_SHOULDER: \"HÖGER AXEL\"\n  STR_LEFT_SHOULDER: \"VÄNSTER AXEL\"\n  STR_BACK_PACK: \"RYGGSÄCK\"\n  STR_BELT: \"BÄLTE\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE} kontrolleras av utomjordingarna\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}kontrolleras av utomjordingarna\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}är medvetslös\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}är medvetslös\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}har förblött\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}har avlidit från en dödlig skada\"\n  STR_USE_MIND_PROBE: \"Använd tankeläsare\"\n  STR_FATAL_WOUNDS: \"DÖDLIGA SÅR\"\n  STR_UNDER_ARMOR_UC: \"UNDRE PANSAR\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"TidsEnheter reserverade för Snabbskott\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"TidsEnheter reserverade för Automateld\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"TidsEnheter reserverade för Välriktat Skott\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Tidsenheter reserverade för knäställning\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"TE reserverade för knäställning och eld\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} Soldat i X-Com farkost\"\n    other: \"{N} Soldater i X-Com farkost\"\n  STR_UNITS_OUTSIDE:\n    one: \"{N} Soldat lämnad utanför\"\n    other: \"{N} Soldater lämnade utanför\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} Soldat i Entrén\"\n    other: \"{N} Soldater i entrén\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} Enheter i Målutgången\"\n    other: \"{N} Enheter i målutgången\"\n  STR_ABORT_MISSION_QUESTION: \"Överge uppdrag?\"\n  STR_CORPSE: \"Kropp\"\n  STR_UNLOAD_CRAFT: \"Ladda ur\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}har avlidit\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}har avlidit\"\n  STR_HIT_MELEE: \"Träffa\"\n  STR_GROUND: \"MARK\"\n  STR_LIVING_QUARTERS_PLURAL: \"Logement\"\n  STR_LIST_ITEM: \"FÖREMÅL\"\n  STR_PERSONAL_ARMOR_UFOPEDIA: \"Med de nyligen upptäckta utomjordiska legeringarna kan denna rustning ge våra soldater en chans mot det utomjordiska hotet.\"\n  STR_POWER_SUIT_UFOPEDIA: \"En ny, kraftfull skyddsrustning för soldater driven av en Elerium-baserad kraftkälla. Rustningen ökar soldatens styrka och snabbhet samtidigt som den ger det hittills bästa skadeskyddet för våra soldater.\"\n  STR_FLYING_SUIT_UFOPEDIA: \"En förbättrad version av Kraftrustningen som innehåller utomjordisk antigravitations-teknologi för full rörelsefrihet över slagfältet.\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"Alla utomjordingar dog i kraschen,{NEWLINE}Automatisk bärgning inledd\"\n  STR_RESET: \"Återställ\"\n  STR_MEMORIAL: \"Minnesmärke\"\n  STR_DATE_UC: \"DATUM\"\n  STR_SOLDIERS_RECRUITED_UC: \"SOLDATER REKRYTERADE>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"SOLDATER FÖRLORADE>{ALT}{0}\"\n  MAP_CULTA: \"Bondgård\"\n  MAP_FOREST: \"Skog\"\n  MAP_JUNGLE: \"Djungel\"\n  MAP_MOUNT: \"Berg\"\n  MAP_DESERT: \"Öken\"\n  MAP_POLAR: \"Polarisk\"\n  MAP_URBAN: \"Stad\"\n  MAP_UBASE: \"Utomjordisk bas\"\n  MAP_XBASE: \"X-COM-bas\"\n  MAP_MARS: \"Mars\"\n  STR_MIXED: \"Blandat\"\n  STR_REMOVE_SELECTED: \"Ta markerade\"\n  STR_LIVE_ALIENS: \"Levande{NEWLINE}varelser\"\n  STR_DEAD_ALIENS: \"Avvisade{NEWLINE}varelser\"\n  STR_UNDER_INTERROGATION: \"Blir{NEWLINE}undersökta\"\n  STR_CONTAINMENT_EXCEEDED: \"UTOMJORDINGFÖRVARINGS GRÄNSVÄRDE ÖVERSKRIDEN!{SMALLLINE}Otillräcklig förvaringskapacitet i {0}. Du måste välja ut överskridande utomjordingar från förvaringen (Som sedermera avlider).\"\n  STR_MANAGE_CONTAINMENT: \"Hantera utomjordingsförvaring\"\n  STR_STORAGE_EXCEEDED: \"LAGERUTRYMME SLUT!{SMALLLINE}Otillräckligt lagerutrymme i {0}. Du måste sälja överskridande föremål.\"\n  STR_GO_TO_BASE: \"Gå till bas\"\n  STR_MELEE_ACCURACY: \"TRÄFFSÄKERHET FÖR NÄRKAMP\"\n  STR_SELL_PRODUCTION: \"SÄLJ\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Båda händerna måste vara tomma!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Otillräckligt med föremål för att kopiera mall!\"\n  STR_UNLOAD_WEAPON: \"Ladda ur vapen\"\n  STR_ALL_ITEMS: \"Alla föremål\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"INGEN MER UTRUSTNING FÅR PLATS OMBORD!{SMALLLINE}Du får bara ta med max {N} utrustningsföremål på denna farkost.\"\n    other: \"INGEN MER UTRUSTNING FÅR PLATS OMBORD!{SMALLLINE}Du får bara ta med max {N} utrustningsföremål på denna farkost.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}KONTROLLCENTER FÖRSTÖRT{NEWLINE}Ta dig till entrén och avbryt.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"X-Com-anläggningar kan inte byggas under vatten\"\n  STR_LEVEL_SHORT: \"{0}\"\n  STR_PERSONNEL: \"Personal\"\n  STR_CRAFT_ARMAMENT: \"Farkost & bestyckning\"\n  STR_COMPONENTS: \"Komponenter\"\n  STR_SOLDIERS_RECRUITED: \"Soldater rekryterade\"\n  STR_SOLDIERS_LOST: \"Soldater förlorade\"\n  STR_TOTAL_UFOS: \"UFO:n upptäckta\"\n  STR_TOTAL_ALIEN_BASES: \"Utomjordiska baser upptäckta\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"PST\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"PSK\"\n  FEMALE_CIVILIAN: \"Civilist, kvinna\"\n  MALE_CIVILIAN: \"Civilist, man\"\n  CYBERDISC_WEAPON: \"Cyberdisk-vapen\"\n  REAPER_WEAPON: \"Lieman-vapen\"\n  CHRYSSALID_WEAPON: \"Chryssalid-vapen\"\n  CELATID_WEAPON: \"Celatid-vapen\"\n  SILACOID_WEAPON: \"Silacoid-vapen\"\n  SECTOPOD_WEAPON: \"Sectopod-vapen\"\n  ZOMBIE_WEAPON: \"Zombie-vapen\"\n  ALIEN_PSI_WEAPON: \"Utomjordiskt Psi-vapen\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/tr.yml",
    "content": "tr:\n  STR_AVENGER_UFOPEDIA: \"NAKLİYE VE MUHAREBE AMAÇLI UZAY ARACI. YABANCI TEKNOLOJİSİNİN KOPYALANMASIYLA VARILAN SON NOKTA.\"\n  STR_INTERCEPTOR_UFOPEDIA: \"ÇİFT PULSE DETONASYONLU JET MOTORUYLA DONATILMIŞ, ELEKTRONİK SİSTEMLERİ ÖZEL KALKAN SİSTEMLERİYLE KORUNAN SAVAŞ UÇAĞI. DÜNYA KAYNAKLI MEVCUT EN İLERİ TEKNOLOJİ.\"\n  STR_LIGHTNING_UFOPEDIA: \"NAKLİYE VE MUHAREBE ARACI. YABANCI İTİŞ SİSTEMLERİNİN KABA AMA ETKİN BİR KOPYASINI KULLANIYOR.\"\n  STR_SKYRANGER_UFOPEDIA: \"DİKEY KALKIŞ VE İNİŞ (V.T.O.L.) YETENEĞİNE SAHİP BİRLİK İNTİKAL ARACI. SINIFININ EN HIZLISI.\"\n  STR_FIRESTORM_UFOPEDIA: \"MUHAREBE ARACI. MERKEZİ İTİŞ SİSTEMİYLE DONATILMIŞ BU TEK KİŞİLİK SAVAŞ ARACI İÇİN KLASİK UÇAN DAİRE TASARIMINDAN ESİNLENİLMİŞ.\"\n  STR_STINGRAY_UFOPEDIA: \"GELİŞMİŞ BİR HAVADAN HAVAYA FÜZE. ELEKTRONİK DEVRELERİ ÖZEL KALKANLARLA KORUNUYOR.\"\n  STR_AVALANCHE_UFOPEDIA: \"NÜKLEER BAŞLIKLI HAVADAN HAVAYA FÜZE. SON DERECE AĞIR.\"\n  STR_CANNON_UFOPEDIA: \"40 SANTİMETRE ÇELİĞİ DELEBİLECEK GÜÇTE ZIRH DELİCİ TOP MERMİLERİ ATAN YÜKSEK GÜÇLÜ SİLAH.\"\n  STR_FUSION_BALL_UFOPEDIA: \"BU SİLAH, GÜCÜNÜ ANTİ-MADDE REAKSİYONDAN ALAN KÜRE ŞEKLİNDE BİR FÜZE FIRLATIR. FÜZE, HEDEFİNİ BİR KÜTLEÇEKİM DALGASIYLA İÇE ÇÖKERTEREK YOK EDER.\"\n  STR_LASER_CANNON_UFOPEDIA: \"ANTİ-MADDE REAKSİYON HAZNESİYLE ENERJİ ÜRETEN KONVANSİYONEL LAZER SİLAHI.\"\n  STR_PLASMA_BEAM_UFOPEDIA: \"KÜTLEÇEKİM IŞINI, NESNELERİ ÇÖKERTEBİLECEK GÜÇTE BİR KÜTLEÇEKİM ALANI OLUŞTURUR VE HEDEFE YÖNLENDİRİR.\"\n  STR_SECTOID_UFOPEDIA: \"Sektoid hiyerarşisi, alt kademedeki askerlerden, güçlü psionik kabiliyetlere sahip liderlere kadar uzanır. Bu psionik güçler, savaşta askerleri demoralize etmekte ve hatta zihinlerini kontrol altına almakta kullanılabilir. Sektoidler, çoğunlukla insan kaçırma ve hayvan parçalama faaliyetlerinde görev alıyor. Kaçırma faaliyetleriyle, çapraz dölleme ve insan toplumuna sızacak klonlar üretme amaçlanıyor. Hayvan etleri ise hem besin, hem de genetik materyal olarak kullanılıyor. Bu ırk, arı kovanı benzeri toplumlarının etkinliğini arttırabilmek için daha üstün genetik melezler üretmeyi amaçlıyor.\"\n  STR_SECTOID_AUTOPSY: \"Sektoid otopsisi\"\n  STR_SECTOID_AUTOPSY_UFOPEDIA: \"Otopside, işlevini kaybetmiş sindirim organları ve basit bir vücut yapısı görülüyor. Beyin ve gözler oldukça gelişmiş. Organik yapı, genetik mühendisliğe ya da mutasyona işaret eder görünümde. Küçük ağız ve burun, herhangi bir işleve sahip değil gibi görünüyor. Parmakların arasındaki dokular ve düz ayak tabanları, suda yaşam izleri teşkil ediyor. Bu türün üreme organları yok ve nasıl çoğaldıklarına dair hiç bir ipucu mevcut değil. Bunlar çok büyük ihtimalle, genetik mühendislik ürünü yaratıklar.\"\n  STR_SNAKEMAN_UFOPEDIA: \"Bu ırk, oldukça ağır koşullar altında evrimleşmiş. Son derece dayanıklılar ve büyük sıcaklık değişimlerine karşı koyabiliyorlar. Tüm hayati organlarını koruyan, yılana benzer tek bir dev 'ayak' sayesinde hareket ediyorlar. Tamamen avlanmaya yönelik hareket ediyorlar ve Dünya yüzeyindeki askeri saldırıları başka bir zeki ırk tarafından yönetiliyor gibi görünüyor.\"\n  STR_SNAKEMAN_AUTOPSY: \"Yılanadam otopsisi\"\n  STR_SNAKEMAN_AUTOPSY_UFOPEDIA: \"Yaratığın derisi son derece sert ve sıcağa karşı dayanıklı. Kardiyo vasküler sistem, hidrolik prensibiyle hareket sağlayan kas sisteminin bir parçası. Tek gerçek kas dokusu, 'kalp'. Üreme sisteminin çok etkin olduğu görülüyor. Her bir Yılanadam, vücudunda elli kadar yumurta taşıyabiliyor ve üreme tamamen aseksüel. Bu tür, kendi haline bırakılacak olursa, Dünya üzerindeki yaşam için ciddi bir tehdit oluşturabilir.\"\n  STR_ETHEREAL_UFOPEDIA: \"Bu varlığın inanılmaz zihin güçleri ona telepati ve telekinezi yetenekleri sağlıyor. Görünürde zayıf olan fiziksel kabiliyetler, zihinsel güçlerle desteklenerek yaratığın hayatta kalması sağlanıyor. Bu telekinetik güçlerin nasıl çalıştığına dair bir fikrimiz yok zira bildiğimiz fizik kurallarını hiçe sayar nitelikteler. Bu yaratıklar, çatışma anlarında, zihinsel güçlerine başvuruyorlar ve son derece tehlikeliler. Dünya yüzeyinde nadiren görülüyorlar çünkü amaçlarına ulaşmak için diğer ırkların hizmetinden faydalanıyorlar.\"\n  STR_ETHEREAL_AUTOPSY: \"Semavi otopsisi\"\n  STR_ETHEREAL_AUTOPSY_UFOPEDIA: \"Fiziksel anlamda bu canlı, herhangi bir yaşamsal faaliyeti yerine getiremeyecek kadar geri kalmış görünüyor. Kaslar, ileri derecede atrofiye uğramış ve iç organlar tam olarak gelişmemiş. Gözler de dahil olmak üzere duyu organlarının hiç biri faal değil. Bununla birlikte vücuttaki kan akışının büyük kısmını çeken beyin oldukça gelişmiş. Bu yaratığın, harici destek olmaksızın hayatını nasıl sürdürebildiği tam bir muamma.\"\n  STR_MUTON_UFOPEDIA: \"Bu insansı yaratık, hem fiziksel olarak güçlü hem de zeki. Dünya üzerindeki etoburlara benzer biçimde, hayatlarını sürdürmek için çiğ et tüketmeye ihtiyaç duyuyorlar. 'Semavi' olarak bilinen telepatik bir ırktan emir alıyor görünümündeler. Bu telepatik bağ koptuğunda, zihinsel sistemleri çöküyor ve bu da ölümleriyle sonuçlanıyor. Vücutlarındaki sibernetik implantlar, savaş alanındaki etkinliklerini arttırmaya yönelik. Daha yüksek bir zekaya hizmet eden piyadeler oldukları çok açık.\"\n  STR_MUTON_AUTOPSY: \"Muton otopsisi\"\n  STR_MUTON_AUTOPSY_UFOPEDIA: \"Bu yaratığın 'derisi', aslında organik bir materyalden üretilip vücuda sonradan kaplanmış bir zırh. Kardiyo-vasküler sistemi ve duyuları güçlendirmek için sayısız sibernetik implant nakli yapılmış. Üreme organları, cerrahi müdahaleyle alınmış. Görünen o ki bu talihsiz yaratıklar, savaş ve fetihle dolu bir ömre mahkum edilmişler. Sertleştirilmiş derileri karşısında zırh delici mühimmat çok etkili değil.\"\n  STR_CELATID_UFOPEDIA: \"Esrarengiz bir havada süzülerek uçma yeteneğine doğal olarak sahip olan bir yaşam formu. Görünüşe göre insan beyin dalgalarını algılayabiliyor ve iyi gizlenmiş de olsa hedefini bulabiliyor. Selatid, hedefini tespit ettiğinde yere konuyor ve son derece aşındırıcı bir madde olan zehrini püskürtmeye başlıyor. Yaratık, korkutucu bir hızla kendi kendini klonlama kabiliyetine de sahip. Genellikle Muton ırkının civarında dolaştığı görülüyor.\"\n  STR_CELATID_AUTOPSY: \"Selatid otopsisi\"\n  STR_CELATID_AUTOPSY_UFOPEDIA: \"Bu organizmanın çekirdeğinde, doğal süreçlerle evrimleşmiş görünen biomekanik bir anti-yerçekim cihazı var. Zehir kesesi, organlar arasında en büyüğü ve müstakil bir beyin yapısı mevcut değil gibi görünüyor. Belirgin sindirim ya da üreme sistemleri yok. Küçük bir organ, hızla büyüyebilen ve yeni yaratıklara dönüşen embriyolar içeriyor.\"\n  STR_SILACOID_UFOPEDIA: \"Silikon bazlı bu yaşam formu, inanılmaz yükseklikte ısı üretebiliyor. Korkunç kuvvetiyle kayaları parçalayıp yutuyor ve sıcak çekirdeği içinde sindiriyor. İlkel bir zekaya sahip ve implantlar ya da telepati yoluyla yönetilebiliyor. Çoğunlukla Muton ırkıyla birlikte görülüyorlar.\"\n  STR_SILACOID_AUTOPSY: \"Silakoid otopsisi\"\n  STR_SILACOID_AUTOPSY_UFOPEDIA: \"Bu canlının son derece sıcak bir çekirdeği var ve bu sindirim sisteminin temelini teşkil eder görünümünde. Eşsiz kas sistemi, inanılmaz bir güce ve hıza sahip. Kaya gibi sert derisi, ateşten ya da yangın çıkaran mühimmattan etkilenmiyor.\"\n  STR_CHRYSSALID_UFOPEDIA: \"Bu yaratığın yengeç kıskaçları, yakın dövüşte çok etkili birer silah. Yüksek metabolizması sayesinde son derece hızlı ve çevik hareket edebiliyor. Kurbanını öldürmek yerine, vücuduna bir yumurta yerleştiriyor ve kurbanını zombiye çeviren bir zehir enjekte ediyor. Aşılama sonrasında kısa bir süre içinde yeni bir Krizalid, kurbanın vücudunu parçalayarak dışarı çıkıyor. Krizalidler, genellikle Yılanadam ırkıyla birlikte görülüyorlar.\"\n  STR_CHRYSSALID_AUTOPSY: \"Krizalid otopsisi\"\n  STR_CHRYSSALID_AUTOPSY_UFOPEDIA: \"Bu yaratığın dış kabuğu son derece dayanıklı olmakla beraber, patlayıcı mühimmat karşısında şaşırtıcı derece savunmasız görünüyor. Hücre büyüme hızı çok yüksek olan beyin, oldukça gelişmiş durumda. Yaratık, diğer canlıların vücuduna yerleştirebildiği yirmi kadar yumurta taşıyor. Yaratığın, oldukça etkin bir terör silahı olduğu söylenebilir.\"\n  STR_FLOATER_UFOPEDIA: \"Fantomlar, asli olarak asker ve terör unsuru olarak görevlendiriliyor. Yırtıcı bir doğaya sahip bu canavarlar, genetik mühendislik ve sibernetik destek yoluyla güçlü askerlere dönüştürülmüş. Bedenin alt yarısı ve iç organların çoğunluğu ameliyatla alınmış ve yerlerine bir yaşam destek sistemi konulmuş. Bu sistem, yaratığın dengesizce de olsa havada süzülmesine imkan sağlayan bir karşı-yerçekimi modülüne sahip.\"\n  STR_FLOATER_AUTOPSY: \"Fantom otopsisi\"\n  STR_FLOATER_AUTOPSY_UFOPEDIA: \"Bu yaratığın bedeni, cerrahi müdahalelerle çok büyük ölçüde değiştirilmiş. Vücudun çekirdeğini teşkil eden bir cihaz, kalbin, ciğerlerin ve sindirim sisteminin yerini alan tam bir yaşam destek sistemi görevi görüyor. Bu cihaz sayesinde yaratık, son derece elverişsiz koşullar altında bile hayatta kalabiliyor. Beyin, bir insan beyninden daha küçük, ama duyu organları çok gelişmiş.\"\n  STR_REAPER_UFOPEDIA: \"Bu iki ayaklı etoburun çok güçlü bir çenesi ve bitmek bilmez bir iştahı var. Faaliyetlerini kontrol etmek için beynine bazı implantlar yerleştirilmiş. Yaratığın ilkel yırtıcı iç güdüleri, ancak terör ve yıkım amaçlarına hizmet edebiliyor. Orakçılar genellikle Fantom'larla beraber bulunuyorlar.\"\n  STR_REAPER_AUTOPSY: \"Orakçı otopsisi\"\n  STR_REAPER_AUTOPSY_UFOPEDIA: \"Orakçının vücudunda iki tane 'beyin' ve iki tane 'kalp' mevcut. Bu sayede ağır yaralıyken bile faaliyetlerini sürdürebiliyor. Ancak tüylü derisi son derece yanıcı. Bu da, yaratığı yangın çıkaran mühimmata karşı savunmasız kılıyor.\"\n  STR_SECTOPOD_UFOPEDIA: \"Sektopodlar, güçlü bir lazer silahıyla donatılmış robot yaratıklardır. Bu mekanik canavarlar, telepatik bir bağlantı üzerinden, sahipleri olan Semavi'ler tarafından yönetilirler. Sektopodlar, Yabancı kuvvetlerinin elindeki en güçlü terör silahlarıdır.\"\n  STR_SECTOPOD_AUTOPSY: \"Sektopod otopsisi\"\n  STR_SECTOPOD_AUTOPSY_UFOPEDIA: \"Bu robot, başta plazma silahları olmak üzere her tür saldırıya dayanabilen güçlendirilmiş bir zırhla donatılmış. Ancak algılama devreleri, lazer silahlarına karşı özellikle savunmasız görünüyor.\"\n  STR_CYBERDISC_UFOPEDIA: \"Bu minyatür uçan daire, kuvvetli bir plazma ışınıyla donatılmış tam otomatik bir terör silahı. Karşı-yerçekimi temelli hareket kabiliyeti, bu araca zorlu arazi koşullarında büyük bir avantaj sağlıyor. Sektoid ırkı, bu aracı yıkım ve terör faaliyetlerinde kullanıyor.\"\n  STR_CYBERDISC_AUTOPSY: \"Siberdisk otopsisi\"\n  STR_CYBERDISC_AUTOPSY_UFOPEDIA: \"Siberdisk'in zırhı oldukça güçlü ve özellikle patlayıcı mühimmata direnmekte oldukça başarılı. Merkezi Karşı-Yerçekimi sistemi, çalışma prensipleri hakkında bir fikir edinilmesine imkan kalmayacak ölçüde hasar görmüş.\"\n  STR_UFO_POWER_SOURCE_UFOPEDIA: \"Yabancı araçlarının güç kaynağı, Eleryum (115 numaralı element) kullanan bir anti-madde reaktöründen ibarettir. Bu reaktör, diğer enerji türlerinin yanı sıra, güçlü kütleçekim dalgaları da üretebilir. Reaktörün maddeyi enerjiye çevirme kabiliyeti, %99 gibi inanılmaz bir etkinliğe sahiptir. Bu sayede az miktarda Eleryum kullanarak olağanüstü miktarda enerji üretilebilir. Bu güç kaynağı, Yabancı alaşımları kullanılarak kolaylıkla yeniden üretilebilecek bir ünitedir.\"\n  STR_UFO_NAVIGATION_UFOPEDIA: \"Yabancı araçları, Dünya atmosferinde ve dış uzayda yollarını bulabilmek için gelişmiş bilgisayar sistemlerinden faydalanıyor. Bu, optik işlemciler ağı şeklinde tasarlanmış bir sistem. Kumanda arabirimi göreceli olarak basit: seyrüsefer personeli, aracın güç kaynağı tarafından üretilen kütleçekim dalgalarını farklı istikametlere yönlendirerek aracı istediği yönde hareket ettirebiliyor. Sistem, insanlar tarafından da kolaylıkla kullanılabilir. Ayrıca, Yabancı alaşımları ve diğer bileşenler kullanılarak rahatlıkla yeniden üretilebilir.\"\n  STR_UFO_CONSTRUCTION_UFOPEDIA: \"Yabancı araçları, üç ana öğeden oluşuyor: bir güç kaynağı, bir seyrüsefer modülü ve Yabancı alaşımlarından üretilmiş bir dış gövde. Gövde, özellikle kütle çekim dalgalarının yönlendirilmesine ve kontrol edilmesine uygun biçimde tasarlanmış. Güç kaynağını besleyebilmek için az miktarda Eleryum kullanılıyor. Yapısal prensipler tam olarak anlaşıldığında ve her bir öğenin fonksiyonları öğrenildiğinde, bu tip araçlar üretmek mümkün hale gelecektir.\"\n  STR_ALIEN_FOOD_UFOPEDIA: \"Bu odalarda, sığırlardan, diğer hayvanlardan ve hatta insanlardan alınmış vücut parçaları bazı enzimler kullanılarak eritiliyor. Bu sıvı daha sonra hazır sindirilmiş besin olarak - muhtemelen doğrudan kan dolaşımına enjekte edilerek tüketiliyor. Bu, Yabancıların Dünya kaynaklı besinlere bağımlı oldukları ve iki toplum arasında bir ortakyaşarlık olduğu düşüncesini doğuruyor.\"\n  STR_ALIEN_REPRODUCTION_UFOPEDIA: \"Bu konteynerlerde Yabancı fetüsleri muhafaza ediliyor. Konteynerlerin tasarımı incelendiğinde, bu süreçten faydalanan Yabancıların üremek için tamamen laboratuvar ortamına bağımlı oldukları anlaşılıyor. Zenginleştirilmiş besin maddeleri, fetüslerin hızla gelişmesini sağlıyor. Üretim hattı benzeri bir sistemle, çok kısa sürede binlerce Yabancı klon üretilebiliyor. Bu sürecin, insan ya da Yabancı-insan melezlerinin üretilmesine de kolaylıkla uyarlanması mümkün görünüyor.\"\n  STR_ALIEN_ENTERTAINMENT_UFOPEDIA: \"Bu küreler, büyük ihtimalle eğlence amaçlı. İçlerindeki psionik devreler, beyindeki bazı merkezleri uyarıyor ve sanrı gösteren ilaçlara benzer bir etki oluşturuyor. Bu cihazlar, Yabancıların eğlenceye veya kültürel etkinliklere de zaman ayırıyor olduklarının tek delili.\"\n  STR_ALIEN_SURGERY_UFOPEDIA: \"Lazer kesiciler kullanarak sığır ve diğer hayvanların vücudundan belli parçaları ayırmaya yarayan cerrahi bir araç. Kesilip sakat bırakılmış hayvanlarla yaygın olarak karşılaşılıyor olması, Yabancıların bu tuhaf faaliyetiyle açıklanabilir. Toplanan bu parçaların besin olarak ya da genetik amaçlarla değerlendirildiği düşünülüyor.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"Geçmişte, binlerce insan, Yabancılar tarafından -bazen defalarca- kaçırıldıklarını iddia etmişlerdir. Gerçeklik, sanıldığından çok daha korku vericidir. İnsanlar kaçırılmakta, araştırılmakta ve gözlem altında tutulmaktadırlar. En iyi numunelerden genetik materyal alınmaktadır. Kadınların bedenine insan-yabancı hibrit fetüsler yerleştirilmekte ve bir kaç ay sonra çıkartılmaktadır. Yabancıların bu faaliyetlerinin arkasında yatan sinsi amaçları kim bilebilir?\"\n  STR_ALIEN_ALLOYS_UFOPEDIA: \"Yabancı araçları, eşsiz özelliklere sahip özel bir alaşımdan üretilmiş. Bu alaşım son derece hafif ve dayanıklı olup, elektromanyetik yöntemlerle şekillendirilebiliyor. Aynı alaşımın, mevcut Dünya teknolojileriyle üretilmesi ve çeşitli imalat süreçlerinde kullanılması mümkün.\"\n  STR_ELERIUM_115_UFOPEDIA: \"Bu element, belli bazı parçacıklarla bombardımana tutulduğunda anti-madde enerjisi üretebilmek gibi sıradışı bir özelliğe sahip. Bu şekilde kütleçekim dalgaları ve diğer enerji türleri üretilebiliyor. Güneş sistemimizde doğal olarak bulunabilen bir madde değil ve laboratuvarlarda sentezlenemiyor.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"Dünyadaki çatışmadan galip çıkma ümidimiz olmadığı açıkça görülüyor. Yabancı orduları sayıca ezici bir üstünlüğe sahip. Burada yapabileceğimiz tek şey, ilerleyişlerini yavaşlatmak. İnsanlığın tek ümidi, yabancıları kaynağında mağlup etmek. Araştırmalarımız, harekatlaırnı, güneş sistemimizdeki bir merkezden yönettiklerini gösteriyor. Bu merkezin, insan tarihinden bile eski bir uygarlığın yuvası olduğu bilgisini edindik. Mümkün olduğunca hızlı bir şekilde bu merkezin yerini tespit etmeliyiz. Daha detaylı bilgi edinebilmek için, bir Yabancı lider ele geçirmeli ve sorgulamalıyız. Büyük UFO'ların mürettebatında en az bir lider bulunması muhtemel.\"\n  STR_THE_MARTIAN_SOLUTION_UFOPEDIA: \"Araştırmalarımız, Yabancı harekatlarının Mars'taki bir merkez üssünden yürütüldüğünü gösteriyor. Bu gizli üs, Dünya istilasını beslemek için her tür üretim ve klonlama tesisine ev sahipliği yapıyor. Ayrıca tüm operasyonu yöneten bir tür ana bilgisayarla donatılmış görünüyor. Yabancıların kovan benzeri toplumlarının bir tür 'kraliçe arı' tarafından yönetildiğine dair bulgular var. Yabancıların temel zaafları da işte bu - eğer yönetimdeki bu 'beyin' ortadan kaldırılabilirse, vücut yenik düşecektir. İş işten geçmeden araştırma faaliyetlerimizi hızlandırmalıyız. Daha fazla bilgi edinebilmek için, en üst rütbeli Yabancılar olan komutanları canlı ele geçirip sorgulamalıyız. Komutanlar, sadece Yabancı üslerinde ve Savaş Gemilerinde görev alır.\"\n  STR_CYDONIA_OR_BUST_UFOPEDIA: \"Yabancı istilacıların, Cydonia'daki bir yer altı üssünden kontrol edilmekte olduğu açıkça görülüyor. Cydonia, Mars yüzeyinde, beş kenarlı piramitlerle ve insan yüzüne benzeyen büyük bir yapıyla dikkat çeken sıradışı bir bölge. Cydonia uygarlığı, milyonlarca yıl önce Mars'ta hüküm sürmüş ve bu uygarlığın neden ortadan kaybolduğu ya da mevcut Yabancı faaliyetleriyle herhangi bir bağlantısı olup olmadığı hakkında bilgimiz yok. Bu soruların cevabı ne olursa olsun, Cydonia'ya bir keşif ekibi göndermemiz gerekli. İstilacıları yöneten bir ana 'beyin' mevcut ve Yabancılara galip gelmemizin tek yolu onu yok etmek. Keşif uçuşu için, en güçlü silahlarla donatılmış bir İntikamcı aracına ihtiyacımız var. Burada öğrenebileceğimiz başka bir şey kalmadı - Cydonia taarruzunun sonucunu beklemeliyiz.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"MEVKİYE ODAKLAN-SÜRE=5 Sn.\"\n  STR_CANCEL_UC: \"İPTAL\"\n  STR_NONE: \"Yok\"\n  STR_UNKNOWN: \"Bilinmiyor\"\n  STR_POOR: \"Zayıf\"\n  STR_AVERAGE: \"Ortalama\"\n  STR_GOOD: \"İyi\"\n  STR_EXCELLENT: \"Mükemmel\"\n  STR_BUILD_NEW_BASE_UC: \"YENİ ÜS KUR\"\n  STR_BASE_INFORMATION: \"ÜS BİLGİLERİ\"\n  STR_EQUIP_CRAFT: \"ARAÇ DONATIM\"\n  STR_BUILD_FACILITIES: \"TESİS İNŞA ET\"\n  STR_RESEARCH: \"ARAŞTIRMA\"\n  STR_MANUFACTURE: \"ÜRETİM\"\n  STR_TRANSFER_UC: \"TRANSFER\"\n  STR_PURCHASE_RECRUIT: \"SATIN AL/İŞE AL\"\n  STR_SACK: \"KOV\"\n  STR_SELL_SACK_UC: \"SAT/KOV\"\n  STR_GEOSCAPE_UC: \"YERKÜRE\"\n  STR_NAME: \"İsim\"\n  STR_AREA: \"Bölge\"\n  STR_BUILD_NEW_BASE: \"Yeni Üs İnşa Et\"\n  STR_CANCEL: \"İptal\"\n  STR_COST_UC: \"MALİYET>\"\n  STR_CONSTRUCTION_TIME_UC: \"İNŞAAT SÜRESİ>\"\n  STR_DAY:\n    one: \"{N} gün\"\n    other: \"{N} gün\"\n  STR_HOUR:\n    one: \"{N} saat\"\n    other: \"{N} saat\"\n  STR_MAINTENANCE_UC: \"BAKIM>\"\n  STR_OK: \"TAMAM\"\n  STR_INSTALLATION: \"Tesisler\"\n  STR_CURRENT_RESEARCH: \"MEVCUT ARAŞTIRMA\"\n  STR_SCIENTISTS_AVAILABLE: \"Toplam Araştırma Personeli>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Görevli Araştırma Personeli>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Mevcut Laboratuvar Alanı>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"ARAŞTIRMA PROJESİ\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"GÖREVLİ PERSONEL\"\n  STR_PROGRESS: \"GİDİŞAT\"\n  STR_NEW_PROJECT: \"Yeni Proje\"\n  STR_CANCEL_PROJECT: \"PROJEYİ İPTAL ET\"\n  STR_NEW_RESEARCH_PROJECTS: \"YENİ ARAŞTIRMA PROJELERİ\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"TOPLAM ARAŞTIRMA PERSONELİ>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"MEVCUT LABORATUVAR KAPASİTESİ>{ALT}{0}\"\n  STR_INCREASE: \"Arttır\"\n  STR_DECREASE: \"Azalt\"\n  STR_START_PROJECT: \"PROJE BAŞLAT\"\n  STR_CURRENT_PRODUCTION: \"MEVCUT ÜRETİM\"\n  STR_ENGINEERS_AVAILABLE: \"Mevcut Mühendisler>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Görevlendirilen Mühendisler>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Mevcut Atölye Alanı>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Mevcut Ödenek>{ALT}{0}\"\n  STR_ITEM: \"MADDE\"\n  STR_ENGINEERS__ALLOCATED: \"Görevli Mühendisler\"\n  STR_UNITS_PRODUCED: \"Üretilen Miktar\"\n  STR_TOTAL_TO_PRODUCE: \"Toplam Üretilecek\"\n  STR_COST__PER__UNIT: \"Birim{NEWLINE}başına{NEWLINE}Maliyet\"\n  STR_DAYS_HOURS_LEFT: \"Kalan Gün/Saat\"\n  STR_NEW_PRODUCTION: \"Yeni Üretim\"\n  STR_PRODUCTION_ITEMS: \"Üretim Kalemleri\"\n  STR_CATEGORY: \"KATEGORİ\"\n  STR_START_PRODUCTION: \"ÜRETİME BAŞLA\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"Bir birim üretmek için gerekli Mühendis saati: {0}\"\n  STR_COST_PER_UNIT_: \"Birim başına maliyet>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Gerekli Atölye Alanı>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"ÜRETİM İÇİN GEREKLİ MATERYAL\"\n  STR_ITEM_REQUIRED: \"GEREKLİ MATERYAL\"\n  STR_UNITS_REQUIRED: \"GEREKLİ MİKTAR\"\n  STR_UNITS_AVAILABLE: \"MEVCUT MİKTAR\"\n  STR_STOP_PRODUCTION: \"ÜRETİMİ DURDUR\"\n  STR_ENGINEERS_AVAILABLE_UC: \"MEVCUT MÜHENDİSLER>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"MEVCUT ÇALIŞMA ALANI>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"AYLIK GELİR>{ALT}{0}\"\n  STR_INCREASE_UC: \"ARTTIR\"\n  STR_DECREASE_UC: \"AZALT\"\n  STR_UNITS_TO_PRODUCE: \"Üretilecek Miktar\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Satın Al / İşe Al\"\n  STR_COST_OF_PURCHASES: \"Toplam Fiyat>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"BİRİM BAŞINA MALİYET\"\n  STR_QUANTITY_UC: \"MİKTAR\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"MEVCUT PERSONEL:TOPLAM PERSONEL>\"\n  STR_SOLDIERS: \"Askerler\"\n  STR_SCIENTISTS: \"Bilim İnsanları\"\n  STR_ENGINEERS: \"Mühendisler\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"KULLANILAN ALAN:MEVCUT ALAN>\"\n  STR_LIVING_QUARTERS: \"Koğuş\"\n  STR_STORES: \"Depo\"\n  STR_LABORATORIES: \"Laboratuvar\"\n  STR_WORK_SHOPS: \"Atölyeler\"\n  STR_HANGARS: \"Hangarlar\"\n  STR_SHORT_RANGE_DETECTION: \"Kısa Menzilli Keşif\"\n  STR_DEFENSE_STRENGTH: \"Savunma Kuvveti\"\n  STR_TRANSFERS_UC: \"TRANSFERLER\"\n  STR_TRANSFERS: \"Transferler\"\n  STR_ARRIVAL_TIME_HOURS: \"Varış Süresi (saat)\"\n  STR_COST_: \"Maliyet>{ALT}{0}\"\n  STR_AREA_: \"Bölge>{ALT}{0}\"\n  STR_BASE_NAME: \"Üs Adı?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"GİRİŞ ASANSÖRÜNÜN KONUMUNU SEÇ\"\n  STR_TRANSFER: \"Transfer\"\n  STR_AMOUNT_TO_TRANSFER: \"TRANSFER EDİLECEK MİKTAR\"\n  STR_SELECT_DESTINATION_BASE: \"Varış Üssünü Seç\"\n  STR_COST: \"Maliyet\"\n  STR_VICTORY_1: \"Salona girdiğinizde, bunca zaman izini takip ettiğiniz Yabancı Beyin'le karşılaştınız. Tam ateş etmeye hazırlanırken, yakındaki bir ekran aydınlandı ve Beyin sizinle iletişim kurmaya başladı. Tetiğe davranmadan önce söyleyeceklerini dinlemeniz için yalvardı.\"\n  STR_VICTORY_2: \"Beyin konuşmaya başladı: 'Milyonlarca yıl önce, adına Mars dediğiniz gezegen yaşam doluydu. Bu yaşam, kurak bir gezegene bizim uygarlığımız tarafından getirilmişti - aynı sizin dünyanıza da getirildiği gibi. Milyonlarca yıldır gezegeninizi ziyaret ediyor ve türünüzü genetik olarak yetiştiriyoruz. Bizi öldüremezsiniz - çünkü siz, bizim bir parçamızsınız...\"\n  STR_VICTORY_3: \"Burası Mars uygarlığının merkezi - bu piramitler, dünyanızdakilerden milyonlarca yıl önce, sizin atalarınız olan bir tür tarafından inşa edildi. Bizim erişemeyeceğimiz hiç bir gezegen yok. Çok geçmeden siz de aynı güce sahip olabilirsiniz. Sizden tek beklediğimiz, iş birliği yapmanız...\"\n  STR_GAME_OVER_1: \"Yabancılar, şehirleri yakıp yıkarak, havayı ve denizleri zehirleyerek tüm insanlığı ortadan kaldırmaya çalıştılar. Böylesine ileri bir teknoloji karşısında Dünya ordularının direniş çabaları boşunaydı. Hayatta kalabilen nesiller, Yabancı yıkımından kaçmaya çalışırken korkunç mutasyonlara maruz kaldılar, esir kamplarında toplandılar ve Dünya'nın, bilinmeyen bir Yabancı imparatorluğunun kolonisi haline getirilmesine alet edildiler.\"\n  STR_GAME_OVER_2: \"X-Com projesi sayesinde elde edilen kıymetli bilgiler sonsuza dek ortadan kayboldu. Dünya'yı kurtarmayı başaramadınız.\"\n  STR_VICTORY_4: \"Yabancı Beyin'in sözleri, kavurucu bir plazma patlamasıyla yarıda kesildi. Yaratığın ölümüyle, komutası altındaki tüm Yabancı kuvvetleri mağlup edilmiş oldu.\"\n  STR_VICTORY_5: \"Yabancılar Mars'ın kontrolünü yitirdiklerinde, Dünya üzerindeki planları da boşa çıkmış oldu. Çok geçmeden insanlık, X-Com araştırmalarının da yardımıyla yeniden gelişip serpildi ve Mars'ın hakimiyetini ele geçirdi. Yabancı tehdidi şimdilik ortadan kalkmış görünüyor. Ancak bu refah ortamının ne kadar süreceğini hiç kimse bilmiyor...\"\n  STR_YOU_HAVE_FAILED: \"Yabancı akınını durdurmakta başarısız oldunuz. Finansör uluslar, teknoloji, bolluk ve barış vaadlerine inanarak birer birer Yabancılarla anlaşma imzaladılar. Ancak çok geçmeden, Yabancıların başka planları olduğu ortaya çıktı...\"\n  STR_TOTAL_UC: \"TOPLAM\"\n  STR_INCOME: \"Gelir\"\n  STR_EXPENDITURE: \"Harcama\"\n  STR_MAINTENANCE: \"Bakım\"\n  STR_BALANCE: \"Bakiye\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"Bölgelere göre UFO Aktivitesi\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"Ülkelere göre UFO Aktivitesi\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"Bölgelere göre X-Com aktivitesi\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"Ülkelere göre X-Com Aktivitesi\"\n  STR_FINANCE: \"Finans\"\n  STR_DATE_FIRST: \"{0}\"\n  STR_DATE_SECOND: \"{0}\"\n  STR_DATE_THIRD: \"{0}\"\n  STR_DATE_FOURTH: \"{0}\"\n  STR_FINANCE_THOUSANDS: \"$1000\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"{1} üssünde{NEWLINE}{0} üretmek için yeterli özel malzeme yok\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"{1} üssündeki{NEWLINE}{0} üretimi için yeterli para yok\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"{1}{NEWLINE}üssünde{NEWLINE}{0}{NEWLINE}üretimi tamamlandı.\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"{1}{NEWLINE}üssünde{NEWLINE}{0}{NEWLINE}inşaatı tamamlandı.\"\n  STR_OK_5_SECONDS: \"TAMAM - 5 sn.\"\n  STR_RESEARCH_COMPLETED: \"Araştırma Sonuçlandı\"\n  STR_VIEW_REPORTS: \"SONUÇ RAPORU\"\n  STR_WE_CAN_NOW_RESEARCH: \"Yeni araştırma konusu:\"\n  STR_WE_CAN_NOW_PRODUCE: \"Yeni Üretim Kalemi:\"\n  STR_SUNDAY: \"PAZAR\"\n  STR_MONDAY: \"PAZARTESİ\"\n  STR_TUESDAY: \"SALI\"\n  STR_WEDNESDAY: \"ÇARŞAMBA\"\n  STR_THURSDAY: \"PERŞEMBE\"\n  STR_FRIDAY: \"CUMA\"\n  STR_SATURDAY: \"CUMARTESİ\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"{2} üssünde {1} için yakıt ikmaline yetecek kadar {0} yok\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"{2} üssünde {1} için yeterli {0} yok\"\n  STR_UFO_IS_NOT_RECOVERED: \"UFO ele geçirilemedi\"\n  STR_UFO_IS_RECOVERED: \"UFO ele geçirildi\"\n  STR_CRAFT_IS_LOST: \"Araç kaybedildi\"\n  STR_TERROR_CONTINUES: \"Terör devam ediyor\"\n  STR_ALIENS_DEFEATED: \"Yabancılar yenilgiye uğratıldı\"\n  STR_BASE_IS_LOST: \"Üs hakimiyeti kaybedildi\"\n  STR_BASE_IS_SAVED: \"Üs kurtarıldı\"\n  STR_ALIEN_BASE_STILL_INTACT: \"Yabancı Üssü hala aktif\"\n  STR_ALIEN_BASE_DESTROYED: \"Yabancı Üssü imha edildi\"\n  STR_ALIENS_KILLED: \"ÖLDÜRÜLEN YABANCILAR\"\n  STR_ALIEN_CORPSES_RECOVERED: \"ÖLÜ ELE GEÇİRİLEN YABANCILAR\"\n  STR_LIVE_ALIENS_RECOVERED: \"CANLI ELE GEÇİRİLEN YABANCILAR\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"ELE GEÇİRİLEN YABANCI YAPITLARI\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"KOMUTA MERKEZİNİN İMHASI\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"YABANCILARIN ÖLDÜRDÜĞÜ SİVİLLER\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"X-COM TARAFINDAN ÖLDÜRÜLEN SİVİLLER\"\n  STR_CIVILIANS_SAVED: \"KURTARILAN SİVİLLER\"\n  STR_XCOM_OPERATIVES_KILLED: \"ÖLDÜRÜLEN X-COM PERSONELİ\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"MUHAREBEDE KAYBOLAN X-COM PERSONELİ\"\n  STR_TANKS_DESTROYED: \"İMHA EDİLEN TANKLAR\"\n  STR_XCOM_CRAFT_LOST: \"KAYBEDİLEN X-COM ARACI\"\n  STR_UFO_RECOVERY: \"UFO'DAN ELE GEÇİRİLENLER\"\n  STR_ALIEN_BASE_RECOVERY: \"YABANCI ÜSSÜNE TAARRUZ\"\n  STR_BASE_UNDER_ATTACK: \"{0} taarruz altında!\"\n  STR_BASE_DEFENSES_INITIATED: \"ÜS SAVUNMA SİLAHLARI AKTİF\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"YERÇEKİM KALKANI UFO'YU PÜSKÜRTTÜ!\"\n  STR_FIRING: \"ATEŞ EDİYOR\"\n  STR_HIT: \"İSABET!\"\n  STR_UFO_DESTROYED: \"UFO İMHA EDİLDİ!\"\n  STR_MISSED: \"ISKA!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Mal Sat / Personel Kov\"\n  STR_VALUE_OF_SALES: \"SATIŞ DEĞERİ> {ALT}{0}\"\n  STR_FUNDS: \"ÖDENEK> {ALT}{0}\"\n  STR_SELL_SACK: \"Sat/Kov\"\n  STR_VALUE: \"Değer\"\n  STR_CRAFT_: \"ARAÇ> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"ÇAKILAN UFOYU ELE GEÇİRME\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"Dikkatli hareket edin - zorunlu iniş yapan UFO'nun içinde ya da civarında hala düşman personeli mevcut olabilir. Harekat, tüm düşman unsurları etkisiz hale getirildiğinde başarıya ulaşacaktır. UFO'nun, taşıdığı malzemelerin ve Yabancı cesetlerinin ele geçirilmesine bundan sonra başlanabilir. Harekatı iptal etmek için, X-Com personelini intikal aracına geri döndürün ve 'Harekatı Bırak' butonuna basın.\"\n  STR_UFO_GROUND_ASSAULT: \"UFO KARA HAREKATI\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"İniş bölgesini araştırın ve mümkünse UFO'ya giriş yapmaya çalışın. Harekat, tüm düşman unsurları etkisiz hale getirildiğinde başarıya ulaşacaktır. UFO'nun, taşıdığı malzemelerin ve Yabancı cesetlerinin ele geçirilmesine bundan sonra başlanabilir. Harekatı iptal etmek için, tüm X-Com personelini intikal aracına geri döndürün ve 'Harekatı Bırak' butonuna basın.\"\n  STR_BASE_DEFENSE: \"ÜS SAVUNMASI\"\n  STR_BASE_UC_: \"ÜS> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"Bir Yabancı araç, yakınlarda iniş yaptı. Üssümüz büyük tehlike altında. Standart prosedür gereği tüm sivil personel tahliye edildi ve X-Com araçları dışarı çıkartıldı. Düşman unsurlar, hangar kapılarından ya da merkez asansörden giriş yapacaklar. Üssü ve içindeki hayati tesisleri her ne pahasına olursa olsun savunmalısınız - bu bir ölüm kalım savaşı. Eğer 'harekatı bırak' butonuna basarsanız yenilgiyi kabul etmiş olacaksınız ve üssü kaybedeceğiz.\"\n  STR_ALIEN_BASE_ASSAULT: \"YABANCI ÜSSÜNE TAARRUZ\"\n  STR_ALIEN_BASE_ASSAULT_BRIEFING: \"X-Com personeli, bir Yabancı üssüne sızmayı başardı. Üssü çalışmaz hale getirmek için kontrol merkezi yok edilmeli. Harekatın sona ermesi için ya tüm düşman ünitelerin etkisiz hale getirilmesi ya da takımınızın yeşil tahliye bölgesine geri dönmesi gerekli (geri çekilmek için, 'harekatı bırak' butonuna basın).\"\n  STR_CYDONIA_BRIEFING: \"Cydonia'ya ulaştınız. Marslı Sfenks'in yakınında büyük bir yer altı kompleksine giriş yaptınız. Tüm Yabancı faaliyetlerini yöneten Yabancı Beyin'i yok etmelisiniz. İnsanlığın kaderi sizin ellerinizde.\"\n  STR_TERROR_MISSION: \"TERÖR HAREKATI\"\n  STR_TERROR_MISSION_BRIEFING: \"Harekat, tüm düşman unsurları etkisiz hale getirildiğinde başarıya ulaşacaktır. Yabancı tehdidini yok ederek, bölgedeki sivillerin hayatını kurtarmaya çalışmalısınız. Harekatı iptal etmek için, X-Com personelini intikal aracına geri döndürün ve 'Harekatı Bırak' butonuna basın.\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"ÜRETİM İÇİN BOŞ HANGAR YOK!{SMALLLINE}Bir üsse tahsis edilen, transfer edilen, satın alınan ya da üretimine başlanan her bir araç için bir hangar ayrılmalıdır. Yeni bir hangar inşa edin ya da diğer araçlardan birini başka bir üsse transfer edin.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"SATINALIM İÇİN BOŞ HANGAR YOK!{SMALLLINE}Bir üsse tahsis edilen, transfer edilen, satın alınan ya da üretimine başlanan her bir araç için bir hangar ayrılmalıdır. Yeni bir hangar inşa edin ya da diğer araçlardan birini başka bir üsse transfer edin.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"TRANSFER İÇİN BOŞ HANGAR YOK!{SMALLLINE}Bir üsse tahsis edilen, transfer edilen, satın alınan ya da üretimine başlanan her bir araç için bir hangar ayrılmalıdır. Yeni bir hangar inşa edin ya da diğer araçlardan birini başka bir üsse transfer edin.\"\n  STR_CANNOT_BUILD_HERE: \"BURADA İNŞA EDİLEMEZ!{SMALLLINE}Yeni tesis, mevcut bir tesise komşu olmak zorunda.\"\n  STR_NO_FREE_ACCOMODATION: \"YETERLİ YAŞAM ALANI YOK!{SMALLLINE}Varış üssü, personel için yeterli koğuş kapasitesine sahip değil.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"YETERLİ ÇALIŞMA ALANI YOK!{SMALLLINE}Ya yeni bir atölye inşa edin ya da diğer projelere ayrılan iş gücünü azaltın.\"\n  STR_NOT_ENOUGH_MONEY: \"YETERLİ PARA YOK!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"YETERLİ DEPO ALANI YOK!{SMALLLINE}Yeni bir depo inşa edin ya da mevcut stokları diğer üslere transfer edin.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"YETERLİ YAŞAM ALANI YOK!{SMALLLINE}Yeni koğuşlar inşa edin ya da mevcut personeli diğer üslere transfer edin.\"\n  STR_LAUNCH_INTERCEPTION: \"TAKİP BAŞLAT\"\n  STR_CRAFT: \"ARAÇ\"\n  STR_STATUS: \"DURUM\"\n  STR_BASE: \"ÜS\"\n  STR_READY: \"HAZIR\"\n  STR_OUT: \"DIŞARIDA\"\n  STR_REPAIRS: \"TAMİRAT\"\n  STR_REFUELLING: \"YAKIT İKMALİ\"\n  STR_REARMING: \"SİLAHLANMA\"\n  STR_TARGET: \"HEDEF: {0}\"\n  STR_WAY_POINT: \"ARA NOKTA\"\n  STR_ARE_YOU_SURE_CYDONIA: \"Bu aracı Cydonia harekatına göndermek istediğinize emin misiniz?\"\n  STR_YES: \"EVET\"\n  STR_NO: \"HAYIR\"\n  STR_SELECT_DESTINATION: \"HEDEFİ SEÇ\"\n  STR_CYDONIA: \"CYDONIA\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"YENİ ÜS İÇİN KONUM BELİRLEYİN\"\n  STR_RETURN_TO_BASE: \"ÜSSE GERİ DÖN\"\n  STR_SELECT_NEW_TARGET: \"YENİ HEDEF SEÇ\"\n  STR_PATROL: \"DEVRİYE\"\n  STR_STATUS_: \"DURUM>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"HASARLI - ÜSSE DÖNÜYOR\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"YAKIT AZALDI - ÜSSE DÖNÜYOR\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"GÖREV TAMAMLANDI - ÜSSE DÖNÜYOR\"\n  STR_PATROLLING: \"DEVRİYE GEZİYOR\"\n  STR_TAILING_UFO: \"UFO TAKİBİ\"\n  STR_INTERCEPTING_UFO: \"UFO-{0} TAKİP EDİLİYOR\"\n  STR_RETURNING_TO_BASE: \"ÜSSE DÖNÜYOR\"\n  STR_DESTINATION_UC_: \"HEDEF: {0}\"\n  STR_BASE_UC: \"ÜS>{ALT}{0}\"\n  STR_SPEED_: \"SÜRAT>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"AZAMİ SÜRAT>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"İRTİFA>{ALT}{0}\"\n  STR_VERY_LOW: \"ÇOK DÜŞÜK\"\n  STR_LOW_UC: \"DÜŞÜK\"\n  STR_HIGH_UC: \"YÜKSEK\"\n  STR_VERY_HIGH: \"ÇOK YÜKSEK\"\n  STR_FUEL: \"YAKIT>{ALT}{0}\"\n  STR_WEAPON_ONE: \"SİLAH-1>{ALT}{0}\"\n  STR_NONE_UC: \"YOK\"\n  STR_ROUNDS_: \"MERMİ>{ALT}{0}\"\n  STR_WEAPON_TWO: \"SİLAH-2>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"TAKİP ARACI\"\n  STR_BASE_: \"Üs>{0}\"\n  STR_NAME_UC: \"İSİM\"\n  STR_AMMO_: \"CEPHANE>{ALT}{0}\"\n  STR_CREW: \"MÜRETTEBAT\"\n  STR_EQUIPMENT_UC: \"TEÇHİZAT\"\n  STR_ARMOR: \"ZIRH\"\n  STR_MAX: \"AZAMİ>{ALT}{0}\"\n  STR_ROOKIE: \"Çaylak\"\n  STR_SQUADDIE: \"Er\"\n  STR_SERGEANT: \"Çavuş\"\n  STR_CAPTAIN: \"Yüzbaşı\"\n  STR_COLONEL: \"Albay\"\n  STR_COMMANDER: \"Komutan\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"{0} için Takım Seç\"\n  STR_SORT_BY: \"SIRALAMA...\"\n  STR_ORIGINAL_ORDER: \"ÖZGÜN SIRALAMA\"\n  STR_MISSIONS2: \"GÖREV SAYISI\"\n  STR_KILLS2: \"İMHA\"\n  STR_WOUND_RECOVERY2: \"MALÜLİYET SÜRESİ\"\n  STR_SPACE_AVAILABLE: \"BOŞ ALAN>{ALT}{0}\"\n  STR_SPACE_USED: \"KULLANILAN ALAN>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"KULLANILAN ALAN\"\n  STR_RANK: \"RÜTBE\"\n  STR_WOUNDED: \"YARALI\"\n  STR_EQUIPMENT_FOR_CRAFT: \"{0} için Teçhizat\"\n  STR_DEFENSE_VALUE: \"Savunma Değeri\"\n  STR_HIT_RATIO: \"İsabet Oranı\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}iniş yapmaya hazır.{NEWLINE}Hedef:{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"Göreve Başla?\"\n  STR_SELECT_ARMAMENT: \"Donatım Seç\"\n  STR_AMMUNITION_AVAILABLE: \"MEVCUT CEPHANE\"\n  STR_ARMAMENT: \"DONATIM\"\n  STR_NOT_AVAILABLE: \"-\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"{0}{NEWLINE}için zırh tahsis et\"\n  STR_TYPE: \"TİP\"\n  STR_PERSONAL_ARMOR_UC: \"VÜCUT ZIRHI\"\n  STR_POWER_SUIT_UC: \"GÜÇLENDİRİLMİŞ ZIRH\"\n  STR_FLYING_SUIT_UC: \"UÇUŞ ZIRHI\"\n  STR_SELECT_ARMOR: \"Zırh Seç\"\n  STR_NORTH: \"KUZEY\"\n  STR_NORTH_EAST: \"KUZEY DOĞU\"\n  STR_EAST: \"DOĞU\"\n  STR_SOUTH_EAST: \"GÜNEY DOĞU\"\n  STR_SOUTH: \"GÜNEY\"\n  STR_SOUTH_WEST: \"GÜNEY BATI\"\n  STR_WEST: \"BATI\"\n  STR_NORTH_WEST: \"KUZEY BATI\"\n  STR_SELECT_ACTION: \"AKSİYON SEÇ\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"TAKİBE DEVAM ET\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"TEMAS SAĞLAMADAN TAKİP\"\n  STR_VERY_LARGE: \"ÇOK BÜYÜK\"\n  STR_LARGE: \"BÜYÜK\"\n  STR_MEDIUM_UC: \"ORTA\"\n  STR_SMALL: \"KÜÇÜK\"\n  STR_VERY_SMALL: \"ÇOK KÜÇÜK\"\n  STR_GROUNDED: \"ZEMİN\"\n  STR_DETECTED: \"Tespit edildi\"\n  STR_SIZE_UC: \"BOYUT\"\n  STR_ALTITUDE: \"İRTİFA\"\n  STR_HEADING: \"İSTİKAMET\"\n  STR_SPEED: \"SÜRAT\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"UFO'YA ODAKLAN-SÜRE=5 Sn.\"\n  STR_TRACKING_LOST: \"UFO İZİNİ KAYBETTİRDİ\"\n  STR_REDIRECT_CRAFT: \"ARACI YENİDEN YÖNLENDİR\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"BİLİNEN SON UFO KONUMUNA GİT\"\n  STR_UFO_: \"UFO-{0}\"\n  STR_ALIEN_BASE_: \"YABANCI ÜSSÜ-{0}\"\n  STR_CRASH_SITE_: \"DÜŞÜŞ BÖLGESİ-{0}\"\n  STR_LANDING_SITE_: \"İNİŞ BÖLGESİ-{0}\"\n  STR_WAY_POINT_: \"ARA NOKTA-{0}\"\n  STR_TERROR_SITE: \"TERÖR MEVKİİ-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}{1}{NEWLINE}hedefine ulaştı\"\n  STR_NOW_PATROLLING: \"Devriye geziyor\"\n  STR_ALIEN_ORIGINS: \"Yabancı Kökenleri\"\n  STR_THE_MARTIAN_SOLUTION: \"Mars Sorununa Çözüm\"\n  STR_CYDONIA_OR_BUST: \"Ya Cydonia ya Ölüm\"\n  STR_UFOPAEDIA: \"UFOpedi\"\n  STR_XCOM_CRAFT_ARMAMENT: \"X-COM ARAÇ VE TEÇHİZATI\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"AĞIR SİLAH PLATFORMU\"\n  STR_WEAPONS_AND_EQUIPMENT: \"SİLAH VE TEÇHİZAT\"\n  STR_ALIEN_ARTIFACTS: \"YABANCI YAPITLARI\"\n  STR_BASE_FACILITIES: \"TESİSLER\"\n  STR_ALIEN_LIFE_FORMS: \"YABANCI YAŞAM FORMLARI\"\n  STR_ALIEN_RESEARCH_UC: \"YABANCI ARAŞTIRMASI\"\n  STR_UFO_COMPONENTS: \"UFO BİLEŞENLERİ\"\n  STR_UFOS: \"UFO'lar\"\n  STR_SELECT_ITEM: \"KONU BAŞLIKLARI\"\n  STR_ACCELERATION: \"SÜRATLENME>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"YAKIT KAPASİTESİ>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"SİLAH YUVALARI>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"HASAR KAPASİTESİ>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"KARGO ALANI>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"ASP KAPASİTESİ>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Hasar\"\n  STR_RANGE: \"Menzil\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"İsabet\"\n  STR_RE_LOAD_TIME: \"Doldurma süresi\"\n  STR_SECONDS: \"{0}s\"\n  STR_DAMAGE_ARMOR_PIERCING: \"ZIRH DELİCİ\"\n  STR_DAMAGE_INCENDIARY: \"YANGIN ÇIKARICI\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"PATLAYICI\"\n  STR_DAMAGE_LASER_BEAM: \"LAZER IŞINI\"\n  STR_DAMAGE_PLASMA_BEAM: \"PLAZMA IŞINI\"\n  STR_DAMAGE_STUN: \"ŞOK\"\n  STR_DAMAGE_MELEE: \"YAKIN DÖVÜŞ\"\n  STR_DAMAGE_ACID: \"ASİT\"\n  STR_DAMAGE_SMOKE: \"DUMAN\"\n  STR_SHOT_TYPE: \"ATIŞ TİPİ\"\n  STR_ACCURACY_UC: \"İSABET\"\n  STR_TIME_UNIT_COST: \"ZÜ\"\n  STR_DAMAGE_UC: \"HASAR\"\n  STR_AMMO: \"MÜHİMMAT\"\n  STR_SHOT_TYPE_AUTO: \"Otomatik\"\n  STR_SHOT_TYPE_SNAP: \"Ani\"\n  STR_SHOT_TYPE_AIMED: \"Keskin\"\n  STR_CONSTRUCTION_TIME: \"İnşaat Süresi\"\n  STR_CONSTRUCTION_COST: \"İnşaat Maliyeti\"\n  STR_MAINTENANCE_COST: \"Bakım Maliyeti\"\n  STR_LOW: \"Düşük\"\n  STR_MEDIUM: \"Orta\"\n  STR_HIGH: \"Yüksek\"\n  STR_CRAFT_WEAPON: \"Araç Silahı\"\n  STR_CRAFT_AMMUNITION: \"Araç Mühimmatı\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Ağır Silah Platformu\"\n  STR_WEAPON: \"Silah\"\n  STR_AMMUNITION: \"Mühimmat\"\n  STR_EQUIPMENT: \"Teçhizat\"\n  STR_ALIEN_CORPSE: \"Yabancı Cesedi\"\n  STR_UFO_COMPONENT: \"UFO bileşeni\"\n  STR_PERSONAL_ARMOR: \"Vücut Zırhı\"\n  STR_RAW_MATERIALS: \"Ham Madde\"\n  STR_HWP_CANNON_SHELLS: \"ASP Top Mermileri\"\n  STR_ALIEN: \"Yabancı\"\n  STR_SECTOID: \"Sektoid\"\n  STR_SNAKEMAN: \"Yılanadam\"\n  STR_ETHEREAL: \"Semavi\"\n  STR_MUTON: \"Muton\"\n  STR_FLOATER: \"Fantom\"\n  STR_CELATID: \"Selatid\"\n  STR_SILACOID: \"Silakoid\"\n  STR_CHRYSSALID: \"Krizalid\"\n  STR_ZOMBIE: \"Zombi\"\n  STR_REAPER: \"Orakçı\"\n  STR_SECTOPOD: \"Sektopod\"\n  STR_CYBERDISC: \"Siberdisk\"\n  STR_LIVE_COMMANDER: \"Komutan\"\n  STR_LIVE_LEADER: \"Lider\"\n  STR_LIVE_ENGINEER: \"Mühendis\"\n  STR_LIVE_MEDIC: \"Sıhhiyeci\"\n  STR_LIVE_NAVIGATOR: \"Seyrüseferci\"\n  STR_LIVE_SOLDIER: \"Asker\"\n  STR_LIVE_TERRORIST: \"Terörist\"\n  STR_FLOATER_SOLDIER: \"Asker Fantom\"\n  STR_FLOATER_NAVIGATOR: \"Seyrüseferci Fantom\"\n  STR_FLOATER_MEDIC: \"Sıhhiyeci Fantom\"\n  STR_FLOATER_ENGINEER: \"Mühendis Fantom\"\n  STR_FLOATER_LEADER: \"Lider Fantom\"\n  STR_FLOATER_COMMANDER: \"Komutan Fantom\"\n  STR_SECTOID_SOLDIER: \"Asker Sektoid\"\n  STR_SECTOID_NAVIGATOR: \"Seyrüseferci Sektoid\"\n  STR_SECTOID_MEDIC: \"Sıhhiyeci Sektoid\"\n  STR_SECTOID_ENGINEER: \"Mühendis Sektoid\"\n  STR_SECTOID_LEADER: \"Lider Sektoid\"\n  STR_SECTOID_COMMANDER: \"Komutan Sektoid\"\n  STR_SNAKEMAN_SOLDIER: \"Asker Yılanadam\"\n  STR_SNAKEMAN_NAVIGATOR: \"Seyrüseferci Yılanadam\"\n  STR_SNAKEMAN_ENGINEER: \"Mühendis Yılanadam\"\n  STR_SNAKEMAN_LEADER: \"Lider Yılanadam\"\n  STR_SNAKEMAN_COMMANDER: \"Komutan Yılanadam\"\n  STR_MUTON_SOLDIER: \"Asker Muton\"\n  STR_MUTON_NAVIGATOR: \"Seyrüseferci Muton\"\n  STR_MUTON_ENGINEER: \"Mühendis Muton\"\n  STR_ETHEREAL_SOLDIER: \"Asker Semavi\"\n  STR_ETHEREAL_LEADER: \"Lider Semavi\"\n  STR_ETHEREAL_COMMANDER: \"Komutan Semavi\"\n  STR_CYBERDISC_TERRORIST: \"Terörist Siberdisk\"\n  STR_REAPER_TERRORIST: \"Terörist Orakçı\"\n  STR_CHRYSSALID_TERRORIST: \"Terörist Krizalid\"\n  STR_CELATID_TERRORIST: \"Terörist Selatid\"\n  STR_SILACOID_TERRORIST: \"Terörist Silakoid\"\n  STR_SECTOPOD_TERRORIST: \"Terörist Sektopod\"\n  STR_UFO_POWER_SOURCE: \"UFO Güç Kaynağı\"\n  STR_UFO_NAVIGATION: \"UFO Seyrüsefer Modülü\"\n  STR_UFO_CONSTRUCTION: \"UFO Konstrüksiyonu\"\n  STR_ALIEN_FOOD: \"Yabancı Gıdası\"\n  STR_ALIEN_REPRODUCTION: \"Yabancılarda Üreme\"\n  STR_ALIEN_ENTERTAINMENT: \"Yabancı Eğlence Tesisi\"\n  STR_ALIEN_SURGERY: \"Yabancı Ameliyathanesi\"\n  STR_EXAMINATION_ROOM: \"Tetkik Odası\"\n  STR_ALIEN_ALLOYS: \"Yabancı Alaşımları\"\n  STR_ALIEN_HABITAT: \"Yabancı Yaşam Alanı\"\n  STR_POWER_SUIT: \"Güçlendirilmiş Zırh\"\n  STR_FLYING_SUIT: \"Uçuş Zırhı\"\n  STR_HWP_ROCKETS: \"ASP Roketleri\"\n  STR_HWP_FUSION_BOMB: \"ASP Füzyon Bombası\"\n  STR_LASER_WEAPONS: \"Lazer Silahları\"\n  STR_NEW_FIGHTER_CRAFT: \"Yeni Avcı Uçağı\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Yeni Avcı-Taşıyıcı\"\n  STR_ULTIMATE_CRAFT: \"Nihai Araç Tasarımı\"\n  STR_LASER_PISTOL: \"Lazer Tabancası\"\n  STR_LASER_RIFLE: \"Lazer Tüfeği\"\n  STR_HEAVY_LASER: \"Ağır Lazer\"\n  STR_LASER_CANNON: \"Lazer Topu\"\n  STR_PLASMA_CANNON: \"Plazma Topu\"\n  STR_FUSION_MISSILE: \"Füzyon Füzesi\"\n  STR_LASER_DEFENSE: \"Lazer Savunma\"\n  STR_PLASMA_DEFENSE: \"Plazma Savunma\"\n  STR_FUSION_DEFENSE: \"Füzyon Savunma\"\n  STR_GRAV_SHIELD: \"Yerçekim Kalkanı\"\n  STR_MIND_SHIELD: \"Zihin Kalkanı\"\n  STR_PSI_LAB: \"Psi-Lab\"\n  STR_MOTION_SCANNER: \"Hareket Dedektörü\"\n  STR_MEDI_KIT: \"İlk Yardım Çantası\"\n  STR_TANK_CANNON: \"Tank: Top\"\n  STR_TANK_ROCKET_LAUNCHER: \"Tank: Roketatar\"\n  STR_TANK_LASER_CANNON: \"Tank: Lazer Topu\"\n  STR_HOVERTANK_PLASMA: \"Uçartank: Plazma\"\n  STR_HOVERTANK_LAUNCHER: \"Uçartank: Roketatar\"\n  STR_STINGRAY_LAUNCHER: \"Vatoz Roketatar\"\n  STR_AVALANCHE_LAUNCHER: \"Heyelan Roketatar\"\n  STR_CANNON: \"Volkan Topu\"\n  STR_FUSION_BALL_LAUNCHER: \"Füzyon Topu Atıcısı\"\n  STR_PLASMA_BEAM: \"Plazma Işını\"\n  STR_STINGRAY_MISSILES: \"Vatoz Füzesi\"\n  STR_AVALANCHE_MISSILES: \"Heyelan Füzesi\"\n  STR_CANNON_ROUNDS_X50: \"Volkan Top Mermisi (x50)\"\n  STR_FUSION_BALL: \"Füzyon Topu\"\n  STR_SOLDIER: \"Asker\"\n  STR_SCIENTIST: \"Bilim İnsanı\"\n  STR_ENGINEER: \"Mühendis\"\n  STR_NORTH_AMERICA: \"Kuzey Amerika\"\n  STR_ARCTIC: \"Arktika\"\n  STR_ANTARCTICA: \"Antarktika\"\n  STR_SOUTH_AMERICA: \"Güney Amerika\"\n  STR_EUROPE: \"Avrupa\"\n  STR_NORTH_AFRICA: \"Kuzey Afrika\"\n  STR_SOUTHERN_AFRICA: \"Güney Afrika\"\n  STR_CENTRAL_ASIA: \"Orta Asya\"\n  STR_SOUTH_EAST_ASIA: \"Güney Doğu Asya\"\n  STR_SIBERIA: \"Sibirya\"\n  STR_AUSTRALASIA: \"Avustralasya\"\n  STR_PACIFIC: \"Pasifik\"\n  STR_NORTH_ATLANTIC: \"Kuzey Atlantik\"\n  STR_SOUTH_ATLANTIC: \"Güney Atlantik\"\n  STR_INDIAN_OCEAN: \"Hint Okyanusu\"\n  STR_ALIEN_RESEARCH: \"Yabancı Araştırması\"\n  STR_ALIEN_HARVEST: \"Yabancı Hasadı\"\n  STR_ALIEN_ABDUCTION: \"İnsan Kaçırma\"\n  STR_ALIEN_INFILTRATION: \"Yabancı Sızma Harekatı\"\n  STR_ALIEN_BASE: \"Yabancı Üssü\"\n  STR_ALIEN_TERROR: \"Terör Saldırısı\"\n  STR_ALIEN_RETALIATION: \"Karşı Taarruz\"\n  STR_ALIEN_SUPPLY: \"Yabancı İkmal Görevi\"\n  STR_MAXIMUM_SPEED: \"Azami Sürat\"\n  STR_HYPER_WAVE_DECODER_UC: \"HİPER-DALGA ÇÖZÜCÜ\"\n  STR_SKYRANGER: \"GÖKMUHAFIZI\"\n  STR_LIGHTNING: \"YILDIRIM\"\n  STR_AVENGER: \"İNTİKAMCI\"\n  STR_INTERCEPTOR: \"YOLKESEN\"\n  STR_FIRESTORM: \"ATEŞFIRTINASI\"\n  STR_UFO: \"UFO\"\n  STR_STINGRAY: \"VATOZ\"\n  STR_AVALANCHE: \"HEYELAN\"\n  STR_CANNON_UC: \"VOLKAN\"\n  STR_FUSION_BALL_UC: \"FÜZYON TOPU\"\n  STR_LASER_CANNON_UC: \"LAZER TOPU\"\n  STR_PLASMA_BEAM_UC: \"PLAZMA IŞINI\"\n  STR_DAMAGE_CAPACITY: \"Hasar Kapasitesi\"\n  STR_WEAPON_POWER: \"Silah Gücü\"\n  STR_WEAPON_RANGE: \"Silah Menzili\"\n  STR_ACCESS_LIFT: \"Giriş Asansörü\"\n  STR_LABORATORY: \"Laboratuvar\"\n  STR_WORKSHOP: \"Atölye\"\n  STR_SMALL_RADAR_SYSTEM: \"Küçük Radar Sistemi\"\n  STR_LARGE_RADAR_SYSTEM: \"Büyük Radar Sistemi\"\n  STR_MISSILE_DEFENSES: \"Roket Savunma\"\n  STR_GENERAL_STORES: \"Depo\"\n  STR_ALIEN_CONTAINMENT: \"Yabancı Karantinası\"\n  STR_LASER_DEFENSES: \"Lazer Savunma\"\n  STR_PLASMA_DEFENSES: \"Plazma Savunma\"\n  STR_FUSION_BALL_DEFENSES: \"Füzyon Topu Savunma\"\n  STR_PSIONIC_LABORATORY: \"Psionik Laboratuvar\"\n  STR_HYPER_WAVE_DECODER: \"Hiper-dalga Çözücü\"\n  STR_HANGAR: \"Hangar\"\n  STR_USA: \"ABD\"\n  STR_RUSSIA: \"RUSYA\"\n  STR_UK: \"BK\"\n  STR_FRANCE: \"FRANSA\"\n  STR_GERMANY: \"ALMANYA\"\n  STR_ITALY: \"İTALYA\"\n  STR_SPAIN: \"İSPANYA\"\n  STR_CHINA: \"ÇİN\"\n  STR_JAPAN: \"JAPONYA\"\n  STR_INDIA: \"HİNDİSTAN\"\n  STR_BRAZIL: \"BREZİLYA\"\n  STR_AUSTRALIA: \"AVUSTRALYA\"\n  STR_NIGERIA: \"NİJERYA\"\n  STR_SOUTH_AFRICA: \"GÜNEY AFRİKA\"\n  STR_EGYPT: \"MISIR\"\n  STR_CANADA: \"KANADA\"\n  STR_TANK: \"Tank\"\n  STR_CIVILIAN: \"Sivil\"\n  STR_JAN: \"Oca\"\n  STR_FEB: \"Şub\"\n  STR_MAR: \"Mar\"\n  STR_APR: \"Nis\"\n  STR_MAY: \"May\"\n  STR_JUN: \"Haz\"\n  STR_JUL: \"Tem\"\n  STR_AUG: \"Ağu\"\n  STR_SEP: \"Eyl\"\n  STR_OCT: \"Eki\"\n  STR_NOV: \"Kas\"\n  STR_DEC: \"Ara\"\n  STR_INTERNATIONAL_RELATIONS: \"Uluslararası İlişkiler\"\n  STR_COUNTRY: \"Ülke\"\n  STR_FUNDING: \"Finansman\"\n  STR_CHANGE: \"Değişiklik\"\n  STR_WEAPON_SYSTEMS: \"SİLAH SİSTEMLERİ\"\n  STR_HWPS: \"ASP'ler\"\n  STR_DAMAGE_UC_: \"HASAR>{ALT}{0}\"\n  STR_ACCESS_LIFT_UFOPEDIA: \"Giriş asansörü, yer altındaki üsse personel ve teçhizatın giriş çıkışını sağlar. Yeni inşa edilen bir üste ilk kurulan tesistir. Asansör bölgesi, olası bir düşman saldırısında hücuma maruz kalmaya meyillidir.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Her bir koğuş, azami 50 personel için yaşam alanı sağlar. Tesis, temel eğlence, yeme içme ve uyuma alanlarından oluşur.\"\n  STR_LABORATORY_UFOPEDIA: \"Bir laboratuvarda, azami 50 bilim insanı çalışabilir. Laboratuvarlar, madde, biyokimya ve kozmoloji araştırmaları için en son teknolojiyle donatılmıştır. Askeri kurumlar da dahil olmak üzere dünyanın en gelişmiş araştırma laboratuvarlarına ayrıcalıklı erişim yetkisi mevcuttur.\"\n  STR_WORKSHOP_UFOPEDIA: \"Atölyeler, laboratuvarlarda tasarlanan tüm teçhizatı üretebilecek ekipman ve teknolojiyle donatılmışlardır. Her bir atölye, azami 50 mühendis için çalışma ortamı sağlar, ancak üretimi devam eden teçhizatın da bir miktar yer kaplayacağını unutmayın.\"\n  STR_SMALL_RADAR_SYSTEM_UFOPEDIA: \"Büyük radar tespit sistemleri, 300 deniz mili menzile sahiptir ve yer taraması için de uydularla bağlantılıdır. Her bir sistemin, her 30 dakikada bir, orta büyüklükte bir cismi tespit etmek için %10 şansı vardır.\"\n  STR_LARGE_RADAR_SYSTEM_UFOPEDIA: \"Küçük radar tespit sistemleri, 450 deniz mili menzile sahiptir ve yer taraması için de uydularla bağlantılıdır. Her bir sistemin, her 30 dakikada bir, orta büyüklükte bir cismi tespit etmek için %20 şansı vardır.\"\n  STR_MISSILE_DEFENSES_UFOPEDIA: \"Füze savunma sistemleri, üssün yakınına inmeye çalışan düşman araçlarıyla yürütülecek bir Yabancı istilasına karşı koruma sağlar.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"Hangarlarda bekleyen araçlara tahsis edilmiş olanlar da dahil olmak üzere tüm silah sistemleri, teçhizat, cephane, ele geçirilen materyal ve Ağır Silah Platformları, bu depolarda saklanır.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"Canlı ele geçirilen Yabancıların yaşamsal faaliyetlerini sürdürebilmek için özel bir ortama ihtiyaçları vardır. Karantina tesisi, izole üniteler içerisinde azami 10 adet Yabancıyı muhafaza edebilir.\"\n  STR_LASER_DEFENSES_UFOPEDIA: \"Lazer savunma silahları, düşman araçlarının istilasına karşı koruma sağlar.\"\n  STR_PLASMA_DEFENSES_UFOPEDIA: \"Plazma savunma sistemleri, düşman araçlarının istilasına karşı güçlü ve etkin bir koruma sağlar.\"\n  STR_FUSION_BALL_DEFENSES_UFOPEDIA: \"Füzyon roketleri, Yabancı saldırılarına karşı en etkin koruma sağlayan savunma sistemleridir. Bu roketler, patlama anında, belli bir yarıçap içindeki her şeyi yok edebilen bir anti-madde çöküşü oluştururlar.\"\n  STR_GRAV_SHIELD_UFOPEDIA: \"Yerçekim kalkanı, üssün yakınında iniş yapmaya çalışan araçları bir defaya mahsus geri püskürterek tüm savunma sistemlerinin bir kez daha ateş edebilmesi için yeterli zaman sağlar. Pratikte bu kalkan, üssünüzde mevcut olan tüm savunma sistemlerinin toplam etkisini ikiye katlayacaktır.\"\n  STR_MIND_SHIELD_UFOPEDIA: \"Yabancılar, insan varlığını tespit etmek için beyin dalgalarını takip etme yeteneklerine güveniyorlar. Bu nedenle dalga yayılımını bir kalkan sistemiyle engellemek, üsleri saklamak için en etkin yol. Bu savunma sistemi sayesinde, Yabancı araçları tarafından üslerimizin tespit edilme riski önemli ölçüde azaltılabiliyor.\"\n  STR_PSIONIC_LABORATORY_UFOPEDIA: \"Psionik laboratuvarlarda, üsteki tüm askerlerin zihinsel potansiyelleri değerlendirilir ve psionik yeteneklerini kullanabilmeleri için eğitim olanağı sağlanır. Her bir laboratuvarda, azami on asker eğitim görebilir. Sınıf mevcutları her ayın sonunda belirlenir. Askerler, psionik yeteneklerini bir psi-amp kullanarak odaklayabilir ve savaşta zihinsel saldırılarda bulunabilirler.\"\n  STR_HYPER_WAVE_DECODER_UFOPEDIA: \"Yabancılar, neredeyse anlık iletilebilen boyut üstü dalgalar kullanarak iletişim kuruyorlar. Hiper-dalga çözücü, UFO'lardan yayınlanan bu dalgaları yakalayıp şifreli mesajları çözebiliyor. Bu sayede UFO'nun tipi, mürettebatındaki Yabancı ırkının hangisi olduğu ve aracın görevli olduğu harekat tipi tespit edilebiliyor.\"\n  STR_HANGAR_UFOPEDIA: \"Her bir hangar, bir adet araca ev sahipliği yapabilir. Hangarlar, X-Com araçlarının bakımı, tamiratı ve yakıt ikmali için kullanılacak teçhizatla donatılmışlardır. Bir üste konuşlanmış her bir araca ayrı bir hangar tahsis edilmiş olmalıdır. Araç, üs dışında göreve çıkmış da olsa, tahsis edilen hangar, bir başka araç tarafından kullanılamaz.\"\n  STR_PISTOL_UFOPEDIA: \"Standart X-Com tabancası, 12 mermi kapasiteli ve yüksek güçlü bir yarı otomatik silah.\"\n  STR_RIFLE_UFOPEDIA: \"Lazerli nişan sistemiyle donatılmış çok isabetli bir keskin nişancı tüfeği. 6.7mm mermi kullanıyor ve 20 mermilik şarjör kapasitesi var.\"\n  STR_HEAVY_CANNON_UFOPEDIA: \"Ağır top, çok hantal ama bir o kadar da yıkıcı bir silah. Kullanışlılığı, üç farklı tipte cephane kullanabiliyor olmasından ileri geliyor: Zırh delici, yangın çıkarıcı ve kuvvetli patlayıcı.\"\n  STR_AUTO_CANNON_UFOPEDIA: \"Otomatik ağır silah, ağır top gibi çok yönlü ve güçlü bir silah olmakla beraber, daha seri atış yeteneğine sahiptir.\"\n  STR_ROCKET_LAUNCHER_UFOPEDIA: \"Roketatar, üç ayrı büyüklükte füze fırlatabilen lazer güdümlü bir sistemdir.\"\n  STR_LASER_PISTOL_UFOPEDIA: \"Lazer tabancası, yeni savaş teknolojilerinin etkin bir uygulamasıdır. Standart bir tabancanın elverişliliğiyle, daha hızlı ve isabetli atış avantajını bir arada sunar.\"\n  STR_LASER_RIFLE_UFOPEDIA: \"Lazer tüfeği, daha önceki tabanca tasarımından daha isabetli ve güçlü bir silahtır.\"\n  STR_HEAVY_LASER_UFOPEDIA: \"Ağır lazer hantal olmakla birlikte, son derece etkili bir silah.\"\n  STR_GRENADE_UFOPEDIA: \"Bu standart el bombası, gelişmiş ve hassas bir zamanlayıcı içerir.\"\n  STR_SMOKE_GRENADE_UFOPEDIA: \"Duman bombaları, askerlerin açıkta kaldığı çatışma durumlarında perdeleme sağlamak için kullanılır. Düşmana da avantaj sağlayabileceği için dikkatli kullanılması gerekir.\"\n  STR_PROXIMITY_GRENADE_UFOPEDIA: \"Harekete duyarlı mayın, sıradan bir el bombası gibi fırlatılarak kullanılır, ancak tetikleme mekanizması, düştüğü yerin civarında hareket eden nesnelere duyarlıdır. Bu silahları doğru biçimde kullanabilmek için büyük tecrübe ve dikkat gerekir.\"\n  STR_HIGH_EXPLOSIVE_UFOPEDIA: \"Bu patlayıcı, sadece yıkım amacıyla kullanılmalıdır. Tüm personel, yıkım bölgesinden uzak tutulmalıdır.\"\n  STR_MOTION_SCANNER_UFOPEDIA: \"Bu gelişmiş araç, çeşitli dedektörler ve ileri bilgisayar algoritmaları kullanarak hareketli düşman birimlerini tespit edebilir, ancak etkin biçimde kullanabilmek için bir miktar tecrübe gerektirir. Taktik ekranında hareket dedektörü ikonuna tıklayın. Menüden 'Dedektör Kullan' komutunu seçin. Tarayıcı ekranının ortasında, askerin yüzünün dönük olduğu istikameti gösteren bir ok göreceksiniz (yukarısı Kuzeyi gösterir). Yanıp sönen noktalar, yakın zamanda hareket etmiş olan birimleri temsil eder. Büyük boyutlu veya hızlı hareket eden birimlere ait noktalar daha büyük görüntülenir. Hareketsiz birimler tespit edilemeyecektir.\"\n  STR_MEDI_KIT_UFOPEDIA: \"İlk yardım çantası, sağlık müdahale araçlarının yanı sıra ağrı kesiciler ve uyarıcılar içerir. İlk yardım çantasını kullanmak için, yüzünüzü tedaviye ihtiyaç duyan askere dönmeniz, eğer asker bilincini kaybetmişse, vücudunun üzerinde durmanız gerekir. İlk yardım çantası ikonuna tıklayın ve menüden 'ilk yardım çantası kullan' komutunu seçin.{NEWLINE}TEDAVİ> Ağır yaralı organlar kırmızı renkte gösterilir. Yaralı bölgeye tıklayın ve 'Tedavi' butonuna basın. Hayati yaralardan bir tanesi iyileştirilecek ve askerin sağlığı bir miktar yerine gelecektir.{NEWLINE}UYARICI> Bu seçenek, kaybedilen enerjinin yeniden kazandırılması ve bilincini yitirmiş (sersemletilmiş) askerlerin uyandırılması için kullanılır. Bilinçsiz bir askere tedavi uygulamak için doğrudan vücudun üzerinde durmanız gerekir.{NEWLINE}AĞRI KESİCİ> Bu seçenek, yaralı askerlerin moralini, kaybettikleri sağlık oranında yükseltmeye yarar.\"\n  STR_PSI_AMP_UFOPEDIA: \"Psionik amplifikatör, sadece psionik eğitim almış askerler tarafından kullanılabilir. Çatışma anında psi-amp ikonuna tıklayın, saldırı tipini belirleyin ve imleci kullanarak hedefi seçin. İki farklı psionik saldırı tipi mevcut:{NEWLINE}PANİĞE SEVKET> Eğer bu saldırı başarılı olursa, hedefin moralini düşürür ve paniğe kapılmasına neden olabilir.{NEWLINE}ZİHİN KONTROLÜ> Bu saldırı başarılı olduğunda, düşman ünitesinin kontrolü tamamiyle elinize geçmiş olur. Bu tip bir saldırıda başarılı olma ihtimali daha düşüktür.\"\n  STR_STUN_ROD_UFOPEDIA: \"Canlı bir organizmayı öldürmeden elektrik şokuyla etkisiz hale getirme amaçlı bu cihaz, sadece yakın dövüşte kullanılabilir.\"\n  STR_MIND_PROBE_UFOPEDIA: \"Zihin sondası, beyin dalgalarını yakalayarak doğrudan bilgiye dönüştüren bir Yabancı cihazıdır. X-Com personeli, bu cihazı kullanarak hedefledikleri bir Yabancı unsur hakkında detaylı bilgiye erişebilirler. Zihin sondası üzerinde 'kullan' komutunu tıklayın. Ardından, imleci kullanarak hedef alınacak Yabancıyı seçin.\"\n  STR_PLASMA_PISTOL_UFOPEDIA: \"Plazma tabancası, küçük bir karşı-çekim haznesi içinde parçacık hızlandırılması prensibiyle çalışan, ölümcül bir Yabancı silahıdır.\"\n  STR_PLASMA_RIFLE_UFOPEDIA: \"Küçük bir karşı-çekim haznesi içinde parçacık hızlandırılması prensibiyle çalışan, yüksek tahrip gücüne sahip bir silah.\"\n  STR_HEAVY_PLASMA_UFOPEDIA: \"Ağır plazma, küçük bir karşı-çekim haznesi içinde parçacık hızlandırılması prensibiyle çalışan, korkunç tahrip gücüne sahip bir silahtır.\"\n  STR_BLASTER_LAUNCHER_UFOPEDIA: \"Yabancıların çok güçlü 'tahrip bombası' fırlatan güdümlü roketatarı. Silahı ateşlemek için tahrip bombasının izleyeceği güzergahı belirleyen birden fazla ara nokta seçebilirsiniz. Yeterince ara nokta tanımladıktan sonra \\\"ateşle\\\" butonuna basın.\"\n  STR_SMALL_LAUNCHER_UFOPEDIA: \"Sersemletici bomba atan hafif silah. Yabancıları canlı ele geçirmek için çok kullanışlı.\"\n  STR_ALIEN_GRENADE_UFOPEDIA: \"Bu silah, dünya üretimi bir el bombasıyla aynı şekilde kullanılır - ancak çok daha kuvvetli bir patlama etkisi vardır.\"\n  STR_SMALL_SCOUT: \"Küçük Kaşif\"\n  STR_MEDIUM_SCOUT: \"Orta Boy Kaşif\"\n  STR_LARGE_SCOUT: \"Büyük Kaşif\"\n  STR_HARVESTER: \"Hasat Gemisi\"\n  STR_ABDUCTOR: \"Kaçıran\"\n  STR_TERROR_SHIP: \"Terör Gemisi\"\n  STR_BATTLESHIP: \"Savaş Gemisi\"\n  STR_SUPPLY_SHIP: \"İkmal gemisi\"\n  STR_RATING: \"DEĞERLENDİRME> {0}\"\n  STR_RATING_TERRIBLE: \"REZALET!\"\n  STR_RATING_POOR: \"ZAYIF!\"\n  STR_RATING_OK: \"GEÇER\"\n  STR_RATING_GOOD: \"İYİ!\"\n  STR_RATING_EXCELLENT: \"MÜKEMMEL!\"\n  STR_SCORE: \"SKOR\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"X-COM PROJESİ AYLIK RAPOR\"\n  STR_MONTH: \"Ay> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"Finansör uluslar konseyi, genel olarak şu ana kadarki gidişatınızdan memnun.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"Finansör uluslar konseyi, mükemmel gidişatınızdan son derece memnun. Aynen devam.\"\n  STR_COUNCIL_IS_DISSATISFIED: \"Finansör uluslar konseyi, performansınızdan hoşnut değil. Yabancı tehdidiyle daha etkin bir mücadele yürütmeye başlamadığınız taktirde, projenin iptal edilmesi söz konusu olabilir.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"Ne yazık ki Yabancı istilasıyla mücadelede başarılı olamadınız ve finansör uluslar projeyi sonlandırma kararı aldılar. Her bir ulus, sorunu kendi uygun gördüğü biçimde çözmeye çalışacak. Şimdi geride kalan tek umut, görünüşte düşmancıl olan bu güçlerle bir anlaşma sağlanması ve genel halkın yabancı ziyaretçilerle mutabakata varması.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} yerel tehditle mücadelede gösterdiğiniz başarıdan çok memnun ve finansal desteğini arttırma kararı aldı.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} yerel Yabancı istilasıyla mücadelede katettiğiniz yoldan çok memnun ve finansal desteklerini arttırma kararı aldılar.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} ve {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} bölgesindeki Yabancı faaliyetleriyle mücadelede yetersiz kaldığınız kanaatinde ve finansal desteğini azaltma kararı aldı.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} bölgedeki Yabancı faaliyetleriyle mücadeleden hoşnut değil ve finansal desteğini azaltma kararı aldı.\"\n  STR_KNOTS: \"{0} deniz mili\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} bilinmeyen Yabancı güçleriyle gizli bir anlaşma imzaladı ve projeden çekildi.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} bilinmeyen Yabancı güçleriyle gizli bir anlaşma imzaladı ve projeden çekildiler.\"\n  STR_MONTHLY_RATING: \"Aylık Değerlendirme> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Finansman değişikliği> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"Finansör uluslar konseyi, mali durumunuzdan hoşnut değil. Borçlarınızı $1 milyon seviyesinin altına çekemezseniz projenin sonlandırılması ihtimali gündemde.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"HİPER-DALGA GÖNDERİLERİ DEŞİFRE EDİLDİ\"\n  STR_CRAFT_TYPE: \"ARAÇ TİPİ\"\n  STR_RACE: \"IRK\"\n  STR_MISSION: \"GÖREV\"\n  STR_ZONE: \"BÖLGE\"\n  STR_ALLOCATE_RESEARCH: \"Araştırma Başlat\"\n  STR_ALLOCATE_MANUFACTURE: \"Üretim Başlat\"\n  STR_NEW_YORK: \"New York\"\n  STR_WASHINGTON: \"Washington\"\n  STR_LOS_ANGELES: \"Los Angeles\"\n  STR_MONTREAL: \"Montreal\"\n  STR_HAVANA: \"Havana\"\n  STR_MEXICO_CITY: \"Meksika\"\n  STR_CHICAGO: \"Şikago\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_DALLAS: \"Dallas\"\n  STR_BRASILIA: \"Brezilya\"\n  STR_BOGOTA: \"Bogota\"\n  STR_BUENOS_AIRES: \"Buenos Aires\"\n  STR_SANTIAGO: \"Santiago\"\n  STR_RIO_DE_JANEIRO: \"Rio de Janeiro\"\n  STR_LIMA: \"Lima\"\n  STR_CARACAS: \"Karakas\"\n  STR_LONDON: \"Londra\"\n  STR_PARIS: \"Paris\"\n  STR_BERLIN: \"Berlin\"\n  STR_MOSCOW: \"Moskova\"\n  STR_ROME: \"Roma\"\n  STR_MADRID: \"Madrid\"\n  STR_BUDAPEST: \"Budapeşte\"\n  STR_LAGOS: \"Lagos\"\n  STR_CAIRO: \"Kahire\"\n  STR_CASABLANCA: \"Kazablanka\"\n  STR_PRETORIA: \"Pretoria\"\n  STR_NAIROBI: \"Nairobi\"\n  STR_CAPE_TOWN: \"Cape Town\"\n  STR_KINSHASA: \"Kinşasa\"\n  STR_ANKARA: \"Ankara\"\n  STR_DELHI: \"Delhi\"\n  STR_KARACHI: \"Karaçi\"\n  STR_BAGHDAD: \"Bağdat\"\n  STR_TEHRAN: \"Tahran\"\n  STR_BOMBAY: \"Mumbai\"\n  STR_CALCUTTA: \"Kalküta\"\n  STR_TOKYO: \"Tokyo\"\n  STR_BEIJING: \"Pekin\"\n  STR_BANGKOK: \"Bangkok\"\n  STR_MANILA: \"Manila\"\n  STR_SEOUL: \"Seul\"\n  STR_SINGAPORE: \"Singapur\"\n  STR_JAKARTA: \"Cakarta\"\n  STR_SHANGHAI: \"Şanghay\"\n  STR_HONG_KONG: \"Hong Kong\"\n  STR_NOVOSIBIRSK: \"Novosibirsk\"\n  STR_CANBERRA: \"Canberra\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_MELBOURNE: \"Melbourne\"\n  STR_PERTH: \"Perth\"\n  STR_PSI_TRAINING: \"Psionik Eğitim\"\n  STR_PSIONIC_TRAINING: \"PSİONİK EĞİTİM\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Kalan Psi-Lab kapasitesi> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"Psionik{NEWLINE}Direnç\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"Psionik Beceri{NEWLINE}/Gelişim\"\n  STR_PSI_AMP: \"Psi-Amp\"\n  STR_IN_TRAINING: \"Eğitimde?{NEWLINE}\"\n  STR_TARGETTED_BY: \"HEDEFLEYEN:\"\n  STR_WEAPONS_CREW_HWPS: \"ARAÇ SİLAHLARI/{NEWLINE}PERSONEL/ASP\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"Yakıt azaldı,{NEWLINE}araç üsse dönüyor.\"\n  STR_SOLDIER_LIST: \"Asker Listesi\"\n  STR_RANK_: \"RÜTBE> {ALT}{0}\"\n  STR_MISSIONS: \"GÖREVLER> {ALT}{0}\"\n  STR_KILLS: \"İMHA> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"MALÜLİYET> {ALT}{0}\"\n  STR_TIME_UNITS: \"ZAMAN ÜNİTESİ\"\n  STR_STAMINA: \"DAYANIKLILIK\"\n  STR_HEALTH: \"SAĞLIK\"\n  STR_BRAVERY: \"CESARET\"\n  STR_REACTIONS: \"TEPKİ\"\n  STR_FIRING_ACCURACY: \"ATIŞ İSABETLİLİĞİ\"\n  STR_THROWING_ACCURACY: \"FIRLATMA İSABETLİLİĞİ\"\n  STR_STRENGTH: \"KUVVET\"\n  STR_PSIONIC_STRENGTH: \"PSİONİK DİRENÇ\"\n  STR_PSIONIC_SKILL: \"PSİONİK BECERİ\"\n  STR_NEW_RANK: \"YENİ RÜTBE\"\n  STR_PROMOTIONS: \"Terfiler\"\n  STR_SOLDIERS_UC: \"ASKERLER\"\n  STR_TANK_CANNON_UFOPEDIA: \"Otomatik ağır silah platformları, X-Com ekiplerine destek olmak için tasarlanmıştır. Yüksek ateş gücü ve dayanıklı zırhları, bu araçları açık arazi çatışmalarında çok değerli kılar. Tankları yeniden silahlandırabilmek için depolarınızda yeterli top mermisi bulundurduğunuzdan emin olun. Araçları bir ekibin hizmetine tahsis ettiğinizde otomatik olarak silahlandırılacaklardır.\"\n  STR_TANK_ROCKET_LAUNCHER_UFOPEDIA: \"Bu otomatik ağır silah platformu, herhangi bir Yabancı düşmanı harap edebilecek güçte roketlerle donatılmıştır. Stoklarınızda yeterli miktarda ASP roketi bulundurmaya dikkat edin.\"\n  STR_TANK_LASER_CANNON_UFOPEDIA: \"Lazer silahları, ASP'ler için faydalı bir eklenti. Mühimmat ihtiyacı olmaksızın yüksek atış gücü sağlıyorlar.\"\n  STR_HOVERTANK_PLASMA_UFOPEDIA: \"Yabancı teknolojisi sayesinde, ASP alanında bir çığır açılmıştır. Havada manevra kabiliyeti ve plazma ışınlarının gücü, ölümcül bir kombinasyon teşkil etmektedir.\"\n  STR_HOVERTANK_LAUNCHER_UFOPEDIA: \"Bu uçartank, korkunç yıkım gücüne sahip füzyon topları fırlatan bir roketatarla donatılmıştır. Çok dikkatli kullanın. Bu ASP'ler için sürekli füzyon topları üreterek yeterli mühimmat stoklarınız olduğundan emin olmalısınız. Füzyon topu, akıllı bir güdüm sistemine sahip . Ateşlemek için öncelikle imleci kullanarak bir ya da daha fazla ara nokta tanımlamalı, daha sonra da ateşleme simgesine tıklamalısınız.\"\n  STR_HEAVY_PLASMA_CLIP_UFOPEDIA: \"Bu küçük cihaz, Ağır Plazma Topu için mühimmat olarak kullanılır. Az miktarda Eleryum içerir.\"\n  STR_PLASMA_RIFLE_CLIP_UFOPEDIA: \"Bu küçük cihaz, orta kuvvette bir Yabancı silahı olan plazma tüfeği için güç kaynağı olarak kullanılır. Az miktarda Eleryum içerir.\"\n  STR_PLASMA_PISTOL_CLIP_UFOPEDIA: \"Yabancıların küçük plazma tabancası için güç kaynağı. Yabancıların tüm diğer güç kaynakları gibi Eleryum içeriyor.\"\n  STR_STUN_BOMB_UFOPEDIA: \"Sersemletici bomba, canlı insan örnekleri elde etmek için kullanılmaktadır, ancak pek çok Yabancı ırka karşı da etkilidir. Ateşlemek için küçük bir fırlatıcı silah kullanılır.\"\n  STR_ALIEN_RESEARCH_UFOPEDIA: \"Yabancı araştırma harekatları, dünya ve üzerinde yaşayanlar hakkında temel bilgi edinmeyi amaçlıyor. Çoğunlukla, terkedilmiş bölgelere iniş yapan küçük araçlarla yürütülüyorlar. X-Com için en az tehdit teşkil eden bu tip faaliyetler, hükümetleri ve halkları da çok tedirgin etmiyor.\"\n  STR_ALIEN_HARVEST_UFOPEDIA: \"Yabancılar, Dünya faunasından çok çeşitli şekillerde faydalanıyor. Hayvanlar, gizlice kaçırılıyor ve bazı organları çıkartılmış olarak geri bırakılıyorlar. Parçalanmış hayvan olayları, çoğunlukla UFO faaliyetlerine paralel biçimde rapor ediliyor. Genellikle çiftlik bölgelerinde gerçekleşen bu tip faaliyetler, halk arasında ciddi huzursuzluğa yol açıyor ve hükümetler için de tedirginlik kaynağı teşkil ediyor. 'Hasat' faaliyetlerini açıklayan teori, Yabancı ırkların uzun zaman önce gezegeni 'tohumlayarak' bitki ve hayvan örtüsünün oluşmasını sağladıkları ve şimdi de zamanında ektiklerini biçmek için geri dönmüş oldukları yönünde.\"\n  STR_ALIEN_ABDUCTION_UFOPEDIA: \"Yabancı faaliyetleri arasında en sinsi olanıdır. Kaçırma olayları, kurbanların hafızalarını silme girişimlerine rağmen çok yaygın olarak rapor edilmektedir. Kaçırılanlar, garip genetik deneyler ve Yabancı fetüsleriyle hamile bırakılmak da dahil olmak üzere çok çeşitli fiziksel incelemelerle aşağılandıklarını anlatmaktadırlar. Yabancıların, bu faaliyetler yoluyla kendi genetik materyallerini mutasyona uğratarak yönlendirmeyi amaçladıkları düşünülüyor. Bu tür faaliyetler, şehirler gibi nüfusun yoğun olduğu bölgelerde ve gerçekleşir ve büyük ölçüde dehşete yol açar.\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"İnsan görünümlü Yabancılar, Dünya hükümetlerine sızabilirler. Böylece Yabancılar, hükümetlerle en üst düzeyde temas sağlamış olurlar. Sızma çalışmalarının doruk noktası, büyük şehirlerin yakınında yoğun UFO faaliyetleriyle kendini gösterir. Yabancılar, hükümetlere anlaşma teklifi getirecek ve faaliyetlerini engellenmeden yürütebilme karşılığında üstün teknoloji desteği vaadedeceklerdir. Bu tür Yabancı faaliyetleri, X-Com için söz konusu en büyük tehdittir. Yabancılarla anlaşma imzalayan bir hükümet, projeden tüm desteğini çekecektir.\"\n  STR_ALIEN_BASE_UFOPEDIA: \"Yabancılar, gizli yer altı üslerini, ıssız bölgelerde inşa ederler. Bazı ön keşif uçuşlarını müteakip, üssün inşasına geçildiğinde yoğun bir UFO trafiği gerçekleşir. Bu üslerde, kaçırılan insanlar üzerinde deneyler yapıldığı ve bölgedeki diğer harekatlar için ikmal sağlandığı bilinmektedir. Yabancı üssü kurulan bölgelerde, UFO'lar görülmese de rapor edilen Yabancı faaliyetlerinde bir artış gözlenir. Bir üssü tespit edebilmek için X-Com araçları şüphelenilen bölgede devriye uçuşu yapmalıdır.\"\n  STR_ALIEN_TERROR_UFOPEDIA: \"Yabancılar bir şehirde terör estirmek istediklerinde çok güçlü özel kuvvetlerle çıkarma yaparlar. Bu harekatlar, sivil halkı doğrudan tehdit eder ve hükümetleri, geniş yerleşim bölgelerinin tahliyesine zorlar. Bu faaliyetlerin ardındaki asıl amaç, halk arasında panik oluşturmak ve hükümetleri X-Com projesine sırtlarını dönmeye zorlamaktır.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"X-Com avcıları, UFO'ları vurmakta üstün başarı gösterdiklerinde Yabancılar missilleme olarak X-Com üslerine doğrudan saldırı düzenlemeye karar verebilirler. Ancak Yabancıların bir X-Com üssüne saldırabilmek için önce üssün yerini tespit etmeleri gereklidir ve UFO'lar üslerden uzak tutulduğu sürece saldırı tehlikesi düşük kalacaktır.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"Yer yüzünde bir Yabancı üssü inşa edildiğinde, özel ikmal gemileri düzenli olarak ikmal uçuşları yapacaklardır. Bu gemilerden birinin yere iniş yaptığını tespit ettiğinizde, civarlarda bir Yabancı üssü olduğuna kesin gözüyle bakabilirsiniz.\"\n  STR_SMALL_SCOUT_UFOPEDIA: \"Bu küçük araç, öncelikle keşif ve araştırma amacıyla kullanılıyor. Normal şartlar altında, bir Yabancı harekatının başlangıcında, daha büyük araçlara öncülük ediyor.\"\n  STR_MEDIUM_SCOUT_UFOPEDIA: \"Dünya kuvvetleri için fazla tehdit oluşturmayan, orta büyüklükte bir keşif aracı. Normalde, göreve giden daha büyük araçlara öncülük eder.\"\n  STR_LARGE_SCOUT_UFOPEDIA: \"Büyük keşif aracı, her tür Yabancı harekatında kullanılabilen genel amaçlı bir gemi.\"\n  STR_HARVESTER_UFOPEDIA: \"Hasat gemisinin alt tarafındaki kargo kapısından, bir vinç teçhizatıyla sığırlar ve diğer hayvanlar yükleniyor. Lazer kesiciler yardımıyla istenen materyalin kesilip alınmasından sonra hayvan leşi dışarı atılıyor. Gemide ayrıca, vücut parçaları için konteynerler mevcut.\"\n  STR_ABDUCTOR_UFOPEDIA: \"Bu araç, insanlar üzerinde korkunç deneyler yapmakta kullanılan bir ameliyat odası içeriyor. Kurbanlar normalde, telepatik yöntemlerle felç ediliyor, ancak ameliyat masası üzerindeyken bilinçleri açık kalıyor.\"\n  STR_TERROR_SHIP_UFOPEDIA: \"Terör gemisi, Yabancı saldırganları ve onların büyük terör silahlarını taşımak için tasarlanmış tesislere sahiptir. Bu gemiler, Yabancı teröristleri yerleşim alanlarına nakletmek için kullanılır.\"\n  STR_BATTLESHIP_UFOPEDIA: \"Yabancı araçları içinde en büyük ve en güçlü olanı, Savaş Gemisi. Normal şartlar altında Yabancıların harekatlarında kullandıkları asıl araç. Güçlü silahlarla donatılmış ve çok sayıda mürettebat taşıyor.\"\n  STR_SUPPLY_SHIP_UFOPEDIA: \"İkmal gemileri, yeni Yabancı üslerinin inşasında ve mevcut üslerin tedarik faaliyetlerinde kullanılır. Bu gemilerde, Yabancı besin konteynerleri ve üreme salonları mevcuttur.\"\n  STR_DISMANTLE: \"İstimlak\"\n  STR_FACILITY_IN_USE: \"TESİS KULLANIMDA\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"BU TESİS YIKILAMAZ!{SMALLLINE}Tüm tesislerin giriş asansörüne bağlantısı olmalı.\"\n  STR_TRANSFER_ITEMS_TO: \"{0} üssüne transferi onaylayın\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"TRANSFER İÇİN KARANTİNA ALANI YOK!{SMALLLINE}Canlı ele geçirilmiş Yabancıların hayatta tutulabilmesi için bir karantina tesisi zorunludur.\"\n  STR_AMOUNT_AT_DESTINATION: \"VARIŞ MERKEZİNDEKİ{NEWLINE}MİKTAR\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"Ele geçirilen Yabancı, karantina tesisi olmadığı için öldü\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"YETERLİ YAŞAM ALANI YOK!{SMALLLINE}Varış üssü, araca tahsis edilmiş personeli ağırlayabilecek kapasitede yaşam alanı mevcut değil.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"DEPOLAMA ALANI YETERSİZ!{SMALLLINE}Hedef üste, araca tahsis edilmiş levazımatı depolamaya yetecek kadar boş alan yok.\"\n  STR_ITEMS_ARRIVING: \"Teslimat\"\n  STR_DESTINATION_UC: \"HEDEF\"\n  STR_PISTOL: \"Tabanca\"\n  STR_PISTOL_CLIP: \"Tabanca Şarjörü\"\n  STR_RIFLE: \"Tüfek\"\n  STR_RIFLE_CLIP: \"Tüfek Şarjörü\"\n  STR_HEAVY_CANNON: \"Ağır Top\"\n  STR_HC_AP_AMMO: \"AT-ZD Mühimmat\"\n  STR_HC_HE_AMMO: \"AT-KP Mühimmat\"\n  STR_HC_I_AMMO: \"AT-Y Mühimmat\"\n  STR_AUTO_CANNON: \"Otomatik Ağır Silah\"\n  STR_AC_AP_AMMO: \"OAS-ZD Mühimmat\"\n  STR_AC_HE_AMMO: \"OAS-KP Mühimmat\"\n  STR_AC_I_AMMO: \"OAS-Y Mühimmat\"\n  STR_ROCKET_LAUNCHER: \"Roketatar\"\n  STR_SMALL_ROCKET: \"Küçük Roket\"\n  STR_LARGE_ROCKET: \"Büyük Roket\"\n  STR_INCENDIARY_ROCKET: \"Yangın Roketi\"\n  STR_GRENADE: \"El Bombası\"\n  STR_SMOKE_GRENADE: \"Duman Bombası\"\n  STR_PROXIMITY_GRENADE: \"Harekete Duyarlı Mayın\"\n  STR_HIGH_EXPLOSIVE: \"Kuvvetli Patlayıcı\"\n  STR_STUN_ROD: \"Elektroşok Batonu\"\n  STR_HEAVY_PLASMA: \"Ağır Plazma\"\n  STR_HEAVY_PLASMA_CLIP: \"Ağır Plazma Şarjörü\"\n  STR_PLASMA_RIFLE: \"Plazma Tüfeği\"\n  STR_PLASMA_RIFLE_CLIP: \"Plazma Tüfek Şarjörü\"\n  STR_PLASMA_PISTOL: \"Plazma Tabancası\"\n  STR_PLASMA_PISTOL_CLIP: \"Plazma Tabanca Şarjörü\"\n  STR_BLASTER_LAUNCHER: \"Tahrip Bombası Fırlatıcı\"\n  STR_BLASTER_BOMB: \"Tahrip Bombası\"\n  STR_SMALL_LAUNCHER: \"Küçük Roketatar\"\n  STR_STUN_BOMB: \"Sersemletici Bomba\"\n  STR_ALIEN_GRENADE: \"Yabancı El Bombası\"\n  STR_ELERIUM_115: \"Eleryum-115\"\n  STR_MIND_PROBE: \"Zihin Sondası\"\n  STR_SECTOID_CORPSE: \"Sektoid Cesedi\"\n  STR_SNAKEMAN_CORPSE: \"Yılanadam Cesedi\"\n  STR_ETHEREAL_CORPSE: \"Semavi Cesedi\"\n  STR_MUTON_CORPSE: \"Muton Cesedi\"\n  STR_FLOATER_CORPSE: \"Fantom Cesedi\"\n  STR_CELATID_CORPSE: \"Selatid Cesedi\"\n  STR_SILACOID_CORPSE: \"Silakoid Cesedi\"\n  STR_CHRYSSALID_CORPSE: \"Krizalid Cesedi\"\n  STR_REAPER_CORPSE: \"Orakçı Cesedi\"\n  STR_SECTOPOD_CORPSE: \"Sektopod Cesedi\"\n  STR_CYBERDISC_CORPSE: \"Siberdisk Cesedi\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"ASP'yi donatmak için yeterli cephane yok{SMALLLINE}Her ASP, {0} {1} gerektirir.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Takımı tamamen donatmak için yeterli teçhizat yok\"\n  STR_MARS_CYDONIA_LANDING: \"Mars: Cydonia Çıkartması\"\n  STR_MARS_CYDONIA_LANDING_BRIEFING: \"İntikamcı aracınız, Mars yüzeyindeki Cydonia bölgesine iniş yaptı. İstihbaratımıza göre piramitlerden birinde, yer altındaki bir yapılar kompleksine erişim sağlayan yeşil bir asansör mevcut. Tüm askerlerinizi asansör bölgesine intikal ettirdikten sonra 'harekatı sonlandır' simgesine tıklayarak bir sonraki aşamaya geçebilirsiniz.\"\n  STR_MARS_THE_FINAL_ASSAULT: \"Mars: Nihai Taarruz\"\n  STR_MARS_THE_FINAL_ASSAULT_BRIEFING: \"Çatışmada yorgun düşmüş askerleriniz, piramit asansörünü kullanarak gezegen yüzeyinin derinliklerine indiler ve kendilerini büyük bir tünel kompleksinin kalbinde buldular. Yabancı beyin, bu labirentin bir yerlerinde saklanmış durumda. Dünya'nın Yabancılara esir düşmekten kurtulması için onu bulmalı ve yok etmelisiniz.{NEWLINE}{NEWLINE}Bol şans!\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"{1}{NEWLINE}üretebilmek için öncelikle{NEWLINE}{0}{NEWLINE}araştırmasını tamamlamalısınız.\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"Yabancılar, savunmasız {0} üssünü imha etti\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"X-Com ajanları, {0} sınırları içinde bir Yabancı üssü tespit etti\"\n  STR_STANDOFF: \"TAKİP\"\n  STR_CAUTIOUS_ATTACK: \"TEMKİNLİ SALDIRI\"\n  STR_STANDARD_ATTACK: \"STANDART SALDIRI\"\n  STR_AGGRESSIVE_ATTACK: \"AGRESİF SALDIRI\"\n  STR_DISENGAGING: \"GERİ ÇEKİLME\"\n  STR_UFO_HIT: \"UFO İSABET ALDI!\"\n  STR_UFO_CRASH_LANDS: \"UFO ÇAKILDI!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Sadece Takip Mesafesinde Küçült\"\n  STR_UFO_RETURN_FIRE: \"UFO KARŞI ATEŞ AÇTI!\"\n  STR_INTERCEPTOR_DAMAGED: \">>>AVCI HASAR GÖRDÜ<<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>>AVCI İMHA EDİLDİ<<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"UFO AVCIDAN KAÇIYOR!\"\n  STR_ALIENS_TERRORISE: \"YABANCI TERÖRÜ:\"\n  STR_LONG_RANGE_DETECTION: \"Uzun Menzilli Keşif\"\n  STR_STORES_UC: \"DEPO\"\n  STR_DIFFICULTY_LEVEL: \"Zorluk Seviyesi\"\n  STR_INTERCEPT: \"TAKİP\"\n  STR_BASES: \"ÜSLER\"\n  STR_GRAPHS: \"GRAFİKLER\"\n  STR_UFOPAEDIA_UC: \"UFOPEDİ\"\n  STR_OPTIONS_UC: \"AYARLAR\"\n  STR_FUNDING_UC: \"FİNANSMAN\"\n  STR_5_SECONDS: \"5 Sn.\"\n  STR_1_MINUTE: \"1 Dk.\"\n  STR_5_MINUTES: \"5 Dk.\"\n  STR_30_MINUTES: \"30 Dk.\"\n  STR_1_HOUR: \"1 Saat\"\n  STR_1_DAY: \"1 Gün\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"X-Com Performans Cetveli\"\n  STR_ENTER_NAME: \"İsim Girin\"\n  STR_PERFORMANCE_RATING: \"Performans Değerlendirmesi\"\n  STR_VICTORY_DATE: \"Zafer Tarihi\"\n  STR_ELECTRO_FLARE: \"Elektro-fişek\"\n  STR_ELECTRO_FLARE_UFOPEDIA: \"Bu küçük cihaz, fırlatıldığı yerde parlak bir ışık saçar. Gece görevlerinde, elektro fişek kullanarak civardaki düşman üniteleri kolaylıkla tespit edebilirsiniz.\"\n  STR_MONTHLY_COSTS: \"Aylık Maliyet\"\n  STR_CRAFT_RENTAL: \"Araç Kirası\"\n  STR_SALARIES: \"Maaşlar\"\n  STR_BASE_MAINTENANCE: \"Üs bakımı\"\n  STR_COST_PER_UNIT: \"Maliyet/Birim\"\n  STR_QUANTITY: \"Miktar\"\n  STR_TOTAL: \"Toplam\"\n  STR_IN_PSIONIC_TRAINING: \"Psionik Eğitimde\"\n  STR_BLASTER_BOMB_UFOPEDIA: \"Akıllı bir güdüm sistemiyle donatılmış, çok yüksek patlayıcı güce sahip füze. Tahrip Bombası Fırlatıcı kullanarak ateşleniyor.\"\n  STR_FRONT_ARMOR: \"Ön Zırh\"\n  STR_LEFT_ARMOR: \"Sol Zırh\"\n  STR_RIGHT_ARMOR: \"Sağ Zırh\"\n  STR_REAR_ARMOR: \"Arka Zırh\"\n  STR_UNDER_ARMOR: \"Alt Zırh\"\n  STR_ROUNDS: \"Mermi\"\n  STR_UNIT: \"ÜNİTE> {0}\"\n  STR_ENERGY: \"ENERJİ\"\n  STR_MORALE: \"MORAL\"\n  STR_ARMOR_: \"ZIRH> {0}\"\n  STR_FRONT_ARMOR_UC: \"ÖN ZIRH\"\n  STR_LEFT_ARMOR_UC: \"SOL ZIRH\"\n  STR_RIGHT_ARMOR_UC: \"SAĞ ZIRH\"\n  STR_REAR_ARMOR_UC: \"ARKA ZIRH\"\n  STR_SKILLS: \"YETENEK> {0}\"\n  STR_LEVEL: \"SEVİYE>{0}\"\n  STR_HEAD: \"BAŞ\"\n  STR_TORSO: \"GÖVDE\"\n  STR_RIGHT_ARM: \"SAĞ KOL\"\n  STR_LEFT_ARM: \"SOL KOL\"\n  STR_RIGHT_LEG: \"SAĞ BACAK\"\n  STR_LEFT_LEG: \"SOL BACAK\"\n  STR_PAIN_KILLER: \"AĞRI KESİCİ\"\n  STR_STIMULANT: \"UYARICI\"\n  STR_HEAL: \"TEDAVİ\"\n  STR_TIME_UNITS_SHORT: \"ZÜ>{ALT}{0}\"\n  STR_WEIGHT: \"Yük>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"Tep.>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"Ps.Y.>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"Ps.K.>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Yabancı Yapıtı\"\n  STR_AMMO_ROUNDS_LEFT: \"KALAN{NEWLINE}CEPHANE:{NEWLINE}{ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Ağrı Kesici>{ALT}{0}{ALT}{NEWLINE}Uyarıcı    >{ALT}{1}{ALT}{NEWLINE}Tedavi    >{ALT}{2}\"\n  STR_THROW: \"Fırlat\"\n  STR_AUTO_SHOT: \"Otomatik Atış\"\n  STR_SNAP_SHOT: \"Ani Atış\"\n  STR_AIMED_SHOT: \"Keskin Atış\"\n  STR_STUN: \"Elektroşok\"\n  STR_PRIME_GRENADE: \"El Bombasını Kur\"\n  STR_USE_SCANNER: \"Dedektör Kullan\"\n  STR_USE_MEDI_KIT: \"İlk Yardım Çantası Kullan\"\n  STR_LAUNCH_MISSILE: \"Füzeyi Ateşle\"\n  STR_ACCURACY_SHORT: \"İsb>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Zaman Ünitesi Yetersiz!\"\n  STR_NOT_ENOUGH_ENERGY: \"Yeterli Enerji Yok!\"\n  STR_NO_ROUNDS_LEFT: \"Cephane kalmadı!\"\n  STR_NO_AMMUNITION_LOADED: \"Silah Boş!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Bu cephane bu silah için değil!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"Silah zaten dolu!\"\n  STR_NO_LINE_OF_FIRE: \"Görüş Açısı Yok!\"\n  STR_GRENADE_IS_ACTIVATED: \"El Bombası Aktif!\"\n  STR_GRENADE_IS_DEACTIVATED: \"El bombası etkisiz hale getirildi!\"\n  STR_THERE_IS_NO_ONE_THERE: \"Orada hiç kimse yok!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Yabancı teçhizatı, araştırılmadan kullanılamaz!\"\n  STR_OUT_OF_RANGE: \"Menzil Dışı!\"\n  STR_UNABLE_TO_THROW_HERE: \"Buraya fırlatılamıyor!\"\n  STR_SET_TIMER: \"Zamanlayıcıyı Kur\"\n  STR_HIDDEN_MOVEMENT: \"GİZLİ MANEVRA\"\n  STR_TURN: \"TUR> {0}\"\n  STR_SIDE: \"TARAF> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Devam etmek için butona basın\"\n  STR_MIND_CONTROL: \"Zihin Kontrolü\"\n  STR_PANIC_UNIT: \"Paniğe Sevket\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Moral Saldırısı Başarılı\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Zihin Kontrolü Başarılı\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}çıldırdı\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}çıldırdı\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}paniğe kapıldı\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}paniğe kapıldı\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Yabancılar\"\n  STR_RIGHT_HAND: \"SAĞ EL\"\n  STR_LEFT_HAND: \"SOL EL\"\n  STR_RIGHT_SHOULDER: \"SAĞ OMUZ\"\n  STR_LEFT_SHOULDER: \"SOL OMUZ\"\n  STR_BACK_PACK: \"ÇANTA\"\n  STR_BELT: \"KEMER\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}Yabancı kontrolüne geçti\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}Yabancı kontrolü altında\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}bilincini kaybetti\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}bilincini yitirdi\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}ölümcül bir yara nedeniyle hayatını kaybetti\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}ölümcül bir yara nedeniyle hayatını kaybetti\"\n  STR_USE_MIND_PROBE: \"Zihin Sondası Kullan\"\n  STR_FATAL_WOUNDS: \"ÖLÜMCÜL YARALAR\"\n  STR_UNDER_ARMOR_UC: \"ALT ZIRH\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Zaman Üniteleri ani atış için ayrıldı\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Zaman Üniteleri otomatik atış için ayrıldı\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Zaman Üniteleri keskin atış için ayrıldı\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Zaman Üniteleri diz çökmek için ayrıldı\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"ZÜ'leri diz çöküp ateş etmek için ayrıldı\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} Ünite X-Com aracında\"\n    other: \"{N} Ünite X-Com aracında\"\n  STR_UNITS_OUTSIDE:\n    one: \"{N} Ünite X-Com aracı dışında\"\n    other: \"{N} Ünite X-Com aracı dışında\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} Ünite giriş bölgesinde\"\n    other: \"{N} Ünite giriş bölgesinde\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} Ünite tahliye bölgesinde.\"\n    other: \"{N} Ünite tahliye bölgesinde.\"\n  STR_ABORT_MISSION_QUESTION: \"Harekat Yarıda Bırakılsın mı?\"\n  STR_CORPSE: \"Ceset\"\n  STR_UNLOAD_CRAFT: \"Aracı boşalt\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}öldürüldü\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}öldürüldü\"\n  STR_HIT_MELEE: \"Vur\"\n  STR_GROUND: \"ZEMİN\"\n  STR_LIVING_QUARTERS_PLURAL: \"Koğuşlar\"\n  STR_LIST_ITEM: \"MADDE\"\n  STR_PERSONAL_ARMOR_UFOPEDIA: \"Yeni keşfedilen Yabancı Alaşımları kullanılarak üretilmiş bu zırhlar, askerlerimize, Yabancı tehdidine karşı direnme şansı verecektir.\"\n  STR_POWER_SUIT_UFOPEDIA: \"Askerlerimiz için güçlü koruma sağlayan bu yeni zırh, Eleryum kullanan bir güç kaynağıyla besleniyor ve kullanıcısının hareket hızını ve gücünü önemli ölçüde arttırıyor. Bu zırh, harekat güçlerimiz için şu ana kadar geliştirilmiş en iyi korunma aracı.\"\n  STR_FLYING_SUIT_UFOPEDIA: \"Güçlendirilmiş Zırh tasarımının daha gelişmiş bir versiyonu. Yabancıların anti-çekim teknolojisi sayesinde, savaş alanında sınırsız hareket kabiliyeti sağlıyor.\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"Düşüşte tüm yabancılar öldü,{NEWLINE}Ele geçirme çalışması başlatıldı\"\n  STR_RESET: \"Baştan Başla\"\n  STR_MEMORIAL: \"Anıt\"\n  STR_DATE_UC: \"TARİH\"\n  STR_SOLDIERS_RECRUITED_UC: \"ASKERE ALINANLAR>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"ŞEHİTLER>{ALT}{0}\"\n  MAP_CULTA: \"Çiftlik\"\n  MAP_FOREST: \"Orman\"\n  MAP_JUNGLE: \"Vahşi Orman\"\n  MAP_MOUNT: \"Dağ\"\n  MAP_DESERT: \"Çöl\"\n  MAP_POLAR: \"Kutup\"\n  MAP_URBAN: \"Şehir\"\n  MAP_UBASE: \"Yabancı Üssü\"\n  MAP_XBASE: \"X-Com Üssü\"\n  MAP_MARS: \"Mars\"\n  STR_MIXED: \"Karışık\"\n  STR_REMOVE_SELECTED: \"Seçilenleri Öldür\"\n  STR_LIVE_ALIENS: \"Canlı{NEWLINE}Numuneler\"\n  STR_DEAD_ALIENS: \"Iskarta{NEWLINE}Numuneler\"\n  STR_UNDER_INTERROGATION: \"İnceleme{NEWLINE}Altında\"\n  STR_CONTAINMENT_EXCEEDED: \"KARANTİNA LİMİTLERİ AŞILDI!{SMALLLINE}{0} üssünde karantina tesisi tamamen dolu. Muhafaza etmek istemediğiniz Yabancıları imha etmelisiniz.\"\n  STR_MANAGE_CONTAINMENT: \"Karantina Yönetimi\"\n  STR_STORAGE_EXCEEDED: \"DEPOLAMA KAPASİTESİ AŞILDI!{SMALLLINE}{0} üssünde yeterli depolama alanı kalmadı. İhtiyaç fazlası levazımatı satmalısınız.\"\n  STR_GO_TO_BASE: \"Üssü Görüntüle\"\n  STR_MELEE_ACCURACY: \"YAKIN DÖVÜŞ\"\n  STR_SELL_PRODUCTION: \"SAT\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Her iki el boş olmalıdır!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Mevcut teçhizat, envanter şablonu için yetersiz!\"\n  STR_UNLOAD_WEAPON: \"Silahı boşalt\"\n  STR_ALL_ITEMS: \"Tüm Kalemler\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"ARAÇTA TEÇHİZAT İÇİN YER YOK!{SMALLLINE}Bu araca, azami {N} parça teçhizat yükleyebilirsiniz.\"\n    other: \"ARAÇTA TEÇHİZAT İÇİN YER YOK!{SMALLLINE}Bu araca, azami {N} parça teçhizat yükleyebilirsiniz.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}KOMUTA MERKEZİ YOK EDİLDİ{NEWLINE}Girişe geri dönüp görevi iptal edin.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"X-Com tesisleri su altında inşa edilemez\"\n  STR_LEVEL_SHORT: \"{0}\"\n  STR_PERSONNEL: \"Personel\"\n  STR_CRAFT_ARMAMENT: \"Araç ve Donatım\"\n  STR_COMPONENTS: \"Bileşenler\"\n  STR_SOLDIERS_RECRUITED: \"Askerler\"\n  STR_SOLDIERS_LOST: \"Şehitler\"\n  STR_TOTAL_UFOS: \"Tespit edilen UFO'lar\"\n  STR_TOTAL_ALIEN_BASES: \"Tespit edilen Yabancı üsleri\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"PSD\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"PSB\"\n  FEMALE_CIVILIAN: \"Sivil, Kadın\"\n  MALE_CIVILIAN: \"Sivil, Erkek\"\n  CYBERDISC_WEAPON: \"Siberdisk Silahı\"\n  REAPER_WEAPON: \"Orakçı Silahı\"\n  CHRYSSALID_WEAPON: \"Krizalid Silahı\"\n  CELATID_WEAPON: \"Selatid Silahı\"\n  SILACOID_WEAPON: \"Silakoid Silahı\"\n  SECTOPOD_WEAPON: \"Sektopod Silahı\"\n  ZOMBIE_WEAPON: \"Zombi Silahı\"\n  ALIEN_PSI_WEAPON: \"Yabancı Psionik Silahı\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/uk.yml",
    "content": "uk:\n  STR_AVENGER_UFOPEDIA: \"ТРАНСПОРТНО-БОЙОВИЙ КОСМІЧНИЙ КОРАБЕЛЬ. ПОБУДОВАНИЙ НА ОСНОВІ ПЕРЕДОВИХ ІНОПЛАНЕТНИХ ТЕХНОЛОГІЙ.\"\n  STR_INTERCEPTOR_UFOPEDIA: \"БОЙОВИЙ ЛІТАК ОСНАЩЕНИЙ ЗДВОЄНИМ ІМПУЛЬСНИМ ДВИГУНОМ ТА СПЕЦІАЛЬНО ЕКРАНОВАНИМИ ЕЛЕКТРОННИМИ СИСТЕМАМИ. НАЙКРАЩА З ДОСТУПНИХ ЗЕМНИХ ТЕХНОЛОГІЙ.\"\n  STR_LIGHTNING_UFOPEDIA: \"ТРАНСПОРТНО-БОЙОВИЙ ЛІТАЛЬНИЙ АПАРАТ. ВИКОРИСТОВУЄ ГРУБУ, АЛЕ ЕФЕКТИВНУ КОПІЮ РУХОВИХ СИСТЕМ ПРИБУЛЬЦІВ.\"\n  STR_SKYRANGER_UFOPEDIA: \"ТРАНСПОРТНИЙ ЛІТАК. НАЙШВИДШИЙ В СВОЄМУ КЛАСІ, З ВЕРТИКАЛЬНИМ ЗЛЬОТОМ ТА ПОСАДКОЮ.\"\n  STR_FIRESTORM_UFOPEDIA: \"БОЙОВИЙ ЛІТАЛЬНИЙ АПАРАТ. В ЦЬОМУ ОДНОМІСНОМУ ВИНИЩУВАЧІ ВІДТВОРЕНА КОНСТРУКЦІЯ КЛАСИЧНИХ \\\"ЛІТАЮЧИХ ТАРІЛОК\\\" ПРИБУЛЬЦІВ, З ЦЕНТРАЛЬНИМ РОЗТАШУВАННЯМ ДВИГУНА.\"\n  STR_STINGRAY_UFOPEDIA: \"ПОКРАЩЕНА РАКЕТА ПОВІТРЯ-ПОВІТРЯ ЗІ СПЕЦІАЛЬНО ЕКРАНОВАНИМИ ЕЛЕКТРОННИМИ СИСТЕМАМИ.\"\n  STR_AVALANCHE_UFOPEDIA: \"РАКЕТА КЛАСУ ПОВІТРЯ-ПОВІТРЯ З ЯДЕРНОЮ БОЄГОЛОВКОЮ. ВІДЗНАЧАЄТЬСЯ ВКРАЙ ПОВІЛЬНОЮ ПЕРЕЗАРЯДКОЮ.\"\n  STR_CANNON_UFOPEDIA: \"АВТОМАТИЧНА ГАРМАТА ВЕЛИКОЇ ПОТУЖНОСТІ. СТРІЛЯЄ БРОНЕБІЙНИМИ СНАРЯДАМИ, ЗДАТНИМИ ПРОБИТИ 400-МІЛІМЕТРОВУ СТАЛЬ.\"\n  STR_FUSION_BALL_UFOPEDIA: \"ЦЯ ПУСКОВА УСТАНОВКА СТРІЛЯЄ КУЛЕПОДІБНИМИ РАКЕТАМИ, ЯКІ ПРАЦЮЮТЬ НА ОСНОВІ РЕАКЦІЇ АНТИМАТЕРІЇ. СНАРЯД ВРАЖАЄ ЦІЛЬ ГРАВІТАЦІЙНИМ ІМПУЛЬСОМ.\"\n  STR_LASER_CANNON_UFOPEDIA: \"ЦЕ СТАНДАРТНИЙ ЛАЗЕРНИЙ ВИПРОМІНЮВАЧ. ЖИВИТЬСЯ ЕНЕРГІЄЮ РЕАКТОРА, ЯКИЙ ПРАЦЮЄ НА АНТИМАТЕРІЇ.\"\n  STR_PLASMA_BEAM_UFOPEDIA: \"ПЛАЗМОВИЙ ВИПРОМІНЮВАЧ. СТВОРЮЄ ВУЗЬКИЙ КАНАЛ РУЙНІВНОГО ГРАВІТАЦІЙНОГО ПОЛЯ.\"\n  STR_SECTOID_UFOPEDIA: \"Ієрархія сектоїдів простягається від солдатів до лідерів із потужними псіонічними здібностями, які можуть деморалізувати наших солдат чи, навіть, встановити контроль над їх розумом. Зазвичай сектоїди займаються викраденням людей і дослідами над худобою. Людей використовують для отримання генетичного матеріалу, який потрібен для міжвидового схрещування, та для розробки клонів, щоб проникати в людське суспільство. Худоба використовується в якості їжі та генетичного матеріалу. Схоже ця раса хоче розробити досконалі генетичні гібриди для збільшення ефективності їх вуликоподібного суспільства.\"\n  STR_SECTOID_AUTOPSY: \"Розтин сектоїда\"\n  STR_SECTOID_AUTOPSY_UFOPEDIA: \"Розтин виявив рудиментарні органи травлення та просту будову. Мозок та очі дуже добре розвинені. Будова організму свідчить про генетичні зміни або мутації. Ніс та рот малих розмірів, схоже, виконують незначні функції. Перетинки між пальцями і плоскі стопи вказують на водне походження. Репродуктивні органи відсутні, спосіб розмноження даного виду незрозумілий. Найімовірніше, це генетично спроектований вид.\"\n  STR_SNAKEMAN_UFOPEDIA: \"Ця раса сформувалась в надзвичайно ворожому середовищі. Вони надзвичайно міцні та можуть витримувати екстремальні коливання температур. Їх мобільність забезпечується змієподібною \\\"ногою\\\", яка захищає всі життєво важливі органи. Схоже на те, що їх завданням є виключно полювання, і що їх контролює інший розум, який керує їх воєнними нальотами на Землю.\"\n  STR_SNAKEMAN_AUTOPSY: \"Розтин людинозмії\"\n  STR_SNAKEMAN_AUTOPSY_UFOPEDIA: \"Шкіра надзвичайно жорстка та термостійка. Серцево-судинна система є частиною м'язової системи, яка використовує гідравлічний принцип для здійснення рухів. Єдиним справжнім м'язом є \\\"серце\\\". Репродуктивна система здається вкрай ефективною. Розмноження не залежить від статі, в будь-який момент всередині кожної людинозмії є до п'ятдесяти яєць. Залишений без нагляду, цей вид міг би бути серйозною загрозою життю на Землі.\"\n  STR_ETHEREAL_UFOPEDIA: \"Ця істота володіє страхітливими ментальними здібностями, які включають телепатичне спілкування та здатність до телекінезу. Дуже слабкий фізичний розвиток цієї істоти компенсується силою розуму. Ми не розуміємо принцип роботи телекінезу, оскільки це явище суперечить відомим нам законам фізики. Вони надзвичайно небезпечні в будь-якій бойовій ситуації, де вони покладаються на свої ментальні сили. Вони рідко з'являються на Землі, оскільки використовують інші раси для досягнення своїх цілей.\"\n  STR_ETHEREAL_AUTOPSY: \"Розтин ефіріала\"\n  STR_ETHEREAL_AUTOPSY_UFOPEDIA: \"Ця істота фізично деградувала та здається не здатною підтримувати якісь життєві функції. М'язи сильно атрофовані, внутрішні органи слабо розвинені. Органи чуттів, включаючи очі, схоже зовсім не функціонують. Мозок, однак, добре розвинений та щедро забезпечується кров'ю. Незрозуміло, як ця істота могла підтримувати свою життєдіяльність без сторонньої допомоги.\"\n  STR_MUTON_UFOPEDIA: \"Ці людиноподібні істоти розвинені фізично і розумово. Вони з особливим апетитом поїдають сире м'ясо будь-якого виду, яке потрібне їм для підтримки життя, як земним хижакам. Схоже, що ці істоти покладаються на телепатичні команди від раси, відомої як \\\"Ефіріали\\\". Переривання телепатичного зв'язку призводить до порушення функціонування їх нервової системи і вони гинуть. Знайдені кібернетичні імпланти, які використовуються для покращення їх бойових якостей. Очевидно, що ці істоти не більше ніж рядові солдати для вищого розуму.\"\n  STR_MUTON_AUTOPSY: \"Розтин мутона\"\n  STR_MUTON_AUTOPSY_UFOPEDIA: \"\\\"Шкіра\\\" цієї істоти є органічно створеною бронею, вживленою в тіло. Наявні численні кібернетичні імпланти, призначені для підсилення серцево-судинної системи і органів чуттів. Репродуктивні органи, схоже, були видалені хірургічним шляхом. Очевидно, життя цих нещасних істот обмежена боями і завоюваннями. Бронебійні снаряди малоефективні проти їхньої міцної шкіри.\"\n  STR_CELATID_UFOPEDIA: \"Ця життєва форма володіє загадковою природною здатністю літати в повітрі. Вона здатна виявляти активність людського мозку і таким чином знаходить ціль, навіть якщо вона добре захована. Після виявлення цілі целатид приземляється і стріляє маленькими капсулами, які містять надзвичайно їдку отруту. Ці істоти можуть клонувати себе з надзвичайною швидкістю. Вони супроводжують расу мутонів в їхніх подорожах.\"\n  STR_CELATID_AUTOPSY: \"Розтин целатида\"\n  STR_CELATID_AUTOPSY_UFOPEDIA: \"Ядро містить маленький біо-механічний пристрій, який схоже є природньо-вирощеною антигравітаційною руховою системою. Найбільшим внутрішнім органом є залоза, яка виробляє отруту. Мозок відсутній. Також не знайдено ознак травної та репродуктивної систем. Маленький орган містить ембріони, які можуть швидко розвиватись в нову істоту.\"\n  STR_SILACOID_UFOPEDIA: \"Ця форма життя на кремнієвій основі виділяє величезну кількість тепла. Вона має силу для руйнування каменів, які потім будуть поглинуті гарячим ядром. Ці істоти мають примітивний інтелект та можуть контролюватись імплантами або істотами, які мають телепатичні здібності. Вони діють спільно з інопланетною расою мутонів.\"\n  STR_SILACOID_AUTOPSY: \"Розтин силакоїда\"\n  STR_SILACOID_AUTOPSY_UFOPEDIA: \"Ядро цієї істоти надзвичайно гаряче і, схоже, є основою його травної системи. Його унікальна м'язова система має величезну силу і швидкість. Каменеподібна шкіра цієї істоти не вразлива для вогню чи запалювальних снарядів.\"\n  STR_CHRYSSALID_UFOPEDIA: \"Крабоподібні клешні цієї істоти є могутньою зброєю в ближньому бою. Високий метаболізм і сила цієї істоти надають йому високу швидкість та спритність. Замість того щоб вбивати своїх жертв, вона запліднює її яйцем та вприскує отруту, яка перетворює жертву в ходячого зомбі. Молодий крисалід вилупиться з жертви невдовзі після запліднення. Крисаліди асоціюються з расою людинозмій.\"\n  STR_CHRYSSALID_AUTOPSY: \"Розтин крисаліда\"\n  STR_CHRYSSALID_AUTOPSY_UFOPEDIA: \"Екзоскелет цієї істоти надзвичайно міцний, однак на диво вразливий для вибухових снарядів. Мозок добре розвинений, темп поділу його клітин дуже високий. Істота несе двадцять яєць, котрі відкладаються всередину інших організмів. Крисалід є дуже ефективною зброєю для терору.\"\n  STR_FLOATER_UFOPEDIA: \"Летуни є перш за все солдатами і терористами. Вони хижаки по своїй природі, які були перетворені в грізних воїнів генетичними модифікаціями та кібернетичними підсиленнями. Нижня частина тіла та більшість внутрішніх органів хірургічно видалені, натомість встановлена система життєзабезпечення. Цей імплант включає в себе антигравітаційний пристрій, який дозволяє цій істоті, хоч і невпевнено, літати в повітрі.\"\n  STR_FLOATER_AUTOPSY: \"Розтин летуна\"\n  STR_FLOATER_AUTOPSY_UFOPEDIA: \"Ця істота була кардинально змінена хірургічно. Пристроєм, який є ядром організму, є система життєзабезпечення, яка виконує функції серця, легенів і системи травлення. Це дозволяє істоті виживати в надзвичайно несприятливих умовах. Мозок менший, ніж наш, але органи чуттів розвинені добре.\"\n  STR_REAPER_UFOPEDIA: \"Ця двонога м'ясоїдна тварина має міцні щелепи та надзвичайно ненажерлива. Вона має низку мозкових імплантів, які використовуються для контролю за її діяльністю. Примітивні хижацькі інстинкти цієї істоти навряд чи підходять для чогось, крім як терору та руйнування. Рипери зазвичай асоціюються з летунами.\"\n  STR_REAPER_AUTOPSY: \"Розтин рипера\"\n  STR_REAPER_AUTOPSY_UFOPEDIA: \"Рипер має два \\\"мозки\\\" і два \\\"серця\\\", що дозволяє йому діяти навіть з сильними ранами. Однак, його покрита шерстю шкіра легко спалахує, що робить цю істоту вразливою для запалювальної зброї.\"\n  STR_SECTOPOD_UFOPEDIA: \"Сектоподи - це роботи, оснащені потужною лазерною зброєю. Ці механічні монстри управляються телепатично їх контролерами, ефіріалами. Сектоподи є найпотужнішою зброєю терору, яка доступна збройним силам прибульців.\"\n  STR_SECTOPOD_AUTOPSY: \"Розбір сектопода\"\n  STR_SECTOPOD_AUTOPSY_UFOPEDIA: \"Робот був створений з використанням міцної броні, здатної протидіяти більшості видів атак, особливо плазмовій зброї. Однак, система виявлення цілі виглядає частково вразливою для лазерної зброї.\"\n  STR_CYBERDISC_UFOPEDIA: \"Ця \\\"літаюча тарілка\\\" в мініатюрі є автоматичним пристроєм для терору, озброєним потужним плазмовим випромінювачем. Антигравітаційний двигун дає йому велику перевагу на важкопрохідній місцевості. Основним призначенням є руйнування і терор на службі в раси сектоїдів.\"\n  STR_CYBERDISC_AUTOPSY: \"Розбір кібердиска\"\n  STR_CYBERDISC_AUTOPSY_UFOPEDIA: \"Кібердиск добре захищений і практично невразливий для вибухівки. Антигравітаційна система надто пошкоджена, щоб зрозуміти принцип її функціонування.\"\n  STR_UFO_POWER_SOURCE_UFOPEDIA: \"Джерело енергії, яке використовується на кораблях прибульців, базується на реакторі антиматерії, який використовує Елеріум (елемент 115) і генерує потужні гравітаційні хвилі та інші форми енергії. ККД перетворення матерії в енергію досягає 99%, тому навіть незначна кількість Елеріуму може виробити величезну кількість енергії. Цей пристрій можна легко відтворити, використовуючи сплави прибульців.\"\n  STR_UFO_NAVIGATION_UFOPEDIA: \"Польотами інопланетних кораблів керують потужні комп'ютери. Система базується на оптичних процесорах, об'єднаних в мережу. Інтерфейс управління відносно простий - навігатор міняє напрям гравітаційних хвиль, генерованих реактором, щоб рухати корабель в потрібному напрямку. Ця система може бути освоєна людиною. Для її виробництва необхідні сплави прибульців та ряд інших компонентів.\"\n  STR_UFO_CONSTRUCTION_UFOPEDIA: \"Корабель прибульців складається з трьох основних частин - джерела енергії, навігаційної системи та корпуса. Особлива форма корпуса дозволяє спрямовувати гравітаційні хвилі в довільному напрямку. Для джерела енергії потрібна невелика кількість Елеріуму. Знаючи будову всіх компонентів корабля, чи зможемо будувати апарати схожого типу.\"\n  STR_ALIEN_FOOD_UFOPEDIA: \"Камери містять розчин ензимів, призначений для розщеплення тканин тваринного походження (чи навіть людських органів). Вироблений в камерах розчин використовувався в якості їжі. Ймовірний спосіб вживання - пряма внутрішньовенна ін'єкція. Це передбачає деяку залежність прибульців від Землі для виробництва їжі.\"\n  STR_ALIEN_REPRODUCTION_UFOPEDIA: \"В капсулах знаходяться зародки інопланетних організмів. Будова цих інкубаторів свідчить про те, що прибульці повністю перейшли на штучний метод відтворення. Велика кількість поживних речовин забезпечує швидкий розвиток зародків. Така \\\"виробнича лінія\\\" може робити тисячі клонів за короткий час. Процес може бути легко адаптований для людського чи гібридного організму.\"\n  STR_ALIEN_ENTERTAINMENT_UFOPEDIA: \"Найбільш ймовірна функція цих сфер - розважальна. Псіонічний контур стимулює різні центри мозку. Кінцевий ефект схожий на дію галюциногенних наркотиків. Це єдиний доказ того, що прибульці мають культурне чи розважальне дозвілля.\"\n  STR_ALIEN_SURGERY_UFOPEDIA: \"Це хірургічне обладнання використовує лазерний скальпель для вилучення органів. Поширені випадки калічення худоби, ймовірно, відбуваються з використанням цих дивних пристроїв. Скоріш за все, органи використовуються для їжі та генетичних дослідів.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"В минулому тисячі людей стверджували, що були викрадені прибульцями, інколи неодноразово. Правда значно жахливіша. Людей викрадають, досліджують і контролюють. Найкращі екземпляри слугують джерелом генетичного матеріалу. Жінкам імплантуються інопланетні гібридні ембріони, які виймають після кількох місяців розвитку. Невідомо, якими зловісними мотивами керуються прибульці.\"\n  STR_ALIEN_ALLOYS_UFOPEDIA: \"Кораблі прибульців побудовані з особливих сплавів, які мають унікальні властивості. Вони надзвичайно легкі та міцні. Цей матеріал можна відтворити, використовуючи методи електрометалургії, та використати в низці виробничих процесів.\"\n  STR_ELERIUM_115_UFOPEDIA: \"Цей елемент має незвичайну здатність генерувати антиматерію при бомбардуванні певними частинками. Це викликає появу гравітаційних хвиль та інших форм енергії. Елеріум-115 не знайдено в нашій Сонячній системі, і ми також не можемо синтезувати його штучно.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"Очевидно, що подальша боротьба за Землю безперспективна. Ворог переважає нас кількістю. Найбільше, що ми можемо зробити - це сповільнити його просування. Єдиний шанс перемогти - це знищити джерело вторгнення. Дослідження показують, що воно знаходиться в межах нашої Сонячної системи. Прибульці описують це місце як центр древньої цивілізації, яка виникла набагато раніше людства. Ми мусимо якнайшвидше знайти це місце. Для отримання детальної інформації необхідно захопити прибульця-лідера. Ймовірно, на великих кораблях ворога має бути принаймні один лідер.\"\n  STR_THE_MARTIAN_SOLUTION_UFOPEDIA: \"Наші дослідження тепер спрямовані на Марс як на плацдарм операцій прибульців. База надійно прихована, вона містить всі виробничі та клонуючі потужності щоб підживлювати вторгнення на Землю. Також містить контролюючий комп'ютер, який, здається, контролює всю операцію. Схоже що вуликоподібне суспільство прибульців має щось на зразок \\\"королеви бджоли\\\". Це їх фундаментальна слабкість - якщо ми зможемо знищити \\\"мозок\\\", то тіло загине. Ми маємо подвоїти зусилля нашого дослідження, поки не стало запізно. Щоб просунутися далі ми повинні схопити прибульців вищого рангу - командирів, які розтошовуються тільки на лінкорах та базах прибульців.\"\n  STR_CYDONIA_OR_BUST_UFOPEDIA: \"Встановлено, що армія прибульців управляється з підземної бази в Кідонії - дивної області Марса, відомої розташованими там пірамідами та утворенням, яке нагадує людське лице. Кідонійська цивілізація процвітала мільйони років тому, причини її загибелі невідомі, як і зв'язок цієї цивілізації з активністю прибульців в наш час. Якими б не були пояснення, нам необхідно летіти в Кідонію. Є лише один спосіб перемогти прибульців - знищити центральний \\\"мозок\\\". Нам буде потрібен \\\"Месник\\\" - транспорт, обладнаний найкращим доступним озброєнням, здатний доставити десант на Марс. Ми не можемо дізнатись більше, залишаючись тут, і змушені чекати результатів штурму Кідонії.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"ЦЕНТР НА ДІЛЯНЦІ-ЧАС=5 Сек\"\n  STR_CANCEL_UC: \"СКАСУВАТИ\"\n  STR_NONE: \"Нічого\"\n  STR_UNKNOWN: \"Невідомо\"\n  STR_POOR: \"Погано\"\n  STR_AVERAGE: \"Посередньо\"\n  STR_GOOD: \"Добре\"\n  STR_EXCELLENT: \"Відмінно\"\n  STR_BUILD_NEW_BASE_UC: \"БУДУВАТИ НОВУ БАЗУ\"\n  STR_BASE_INFORMATION: \"ІНФОРМАЦІЯ ПРО БАЗИ\"\n  STR_EQUIP_CRAFT: \"СПОРЯДИТИ КОРАБЕЛЬ\"\n  STR_BUILD_FACILITIES: \"БУДУВАТИ МОДУЛІ\"\n  STR_RESEARCH: \"ДОСЛІДЖЕННЯ\"\n  STR_MANUFACTURE: \"ВИРОБНИЦТВО\"\n  STR_TRANSFER_UC: \"ПЕРЕДАЧА\"\n  STR_PURCHASE_RECRUIT: \"ЗАКУПІВЛЯ/НАЙМ\"\n  STR_SACK: \"ЗВІЛЬНИТИ\"\n  STR_SELL_SACK_UC: \"ПРОДАЖ/ЗВІЛЬНЕННЯ\"\n  STR_GEOSCAPE_UC: \"ГЛОБУС\"\n  STR_NAME: \"Назва\"\n  STR_AREA: \"Регіон\"\n  STR_BUILD_NEW_BASE: \"Будувати нову базу\"\n  STR_CANCEL: \"Скасувати\"\n  STR_COST_UC: \"ЦІНА>\"\n  STR_CONSTRUCTION_TIME_UC: \"ЧАС БУДІВНИЦТВА>\"\n  STR_DAY:\n    one: \"{N} день\"\n    few: \"{N} дні\"\n    many: \"{N} днів\"\n    other: \"{N} днів\"\n  STR_HOUR:\n    one: \"{N} година\"\n    few: \"{N} години\"\n    many: \"{N} годин\"\n    other: \"{N} годин\"\n  STR_MAINTENANCE_UC: \"ОБСЛУГОВУВАННЯ>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Встановлення\"\n  STR_CURRENT_RESEARCH: \"ПОТОЧНІ ДОСЛІДЖЕННЯ\"\n  STR_SCIENTISTS_AVAILABLE: \"Вчених вільно>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Вчених зайнято>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Вільних місць в лабораторіях>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"ПРОЕКТ ДОСЛІДЖЕНЬ\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"ВЧЕНИХ ЗАЙНЯТО\"\n  STR_PROGRESS: \"ПРОГРЕС\"\n  STR_NEW_PROJECT: \"Новий проект\"\n  STR_CANCEL_PROJECT: \"СКАСУВАТИ ПРОЕКТ\"\n  STR_NEW_RESEARCH_PROJECTS: \"НОВІ ПРОЕКТИ ДОСЛІДЖЕНЬ\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"ВЧЕНИХ ВІЛЬНО>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"ВІЛЬНИХ МІСЦЬ В ЛАБОРАТОРІЯХ>{ALT}{0}\"\n  STR_INCREASE: \"Збільшити\"\n  STR_DECREASE: \"Зменшити\"\n  STR_START_PROJECT: \"ПОЧАТИ ПРОЕКТ\"\n  STR_CURRENT_PRODUCTION: \"ПОТОЧНЕ ВИРОБНИЦТВО\"\n  STR_ENGINEERS_AVAILABLE: \"Інженерів вільно>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Інженерів зайнято>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Вільних місць в майстернях>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Поточні фонди>{ALT}{0}\"\n  STR_ITEM: \"ПРЕДМЕТ\"\n  STR_ENGINEERS__ALLOCATED: \"Інженерів зайнято\"\n  STR_UNITS_PRODUCED: \"Одиниць виготовлено\"\n  STR_TOTAL_TO_PRODUCE: \"Всього до виготовл.\"\n  STR_COST__PER__UNIT: \" Ціна{NEWLINE}за{NEWLINE}одиницю\"\n  STR_DAYS_HOURS_LEFT: \"Днів/Годин залишилось\"\n  STR_NEW_PRODUCTION: \"Нове виробництво\"\n  STR_PRODUCTION_ITEMS: \"Виготовити виріб\"\n  STR_CATEGORY: \"КАТЕГОРІЯ\"\n  STR_START_PRODUCTION: \"ПОЧАТИ ВИРОБНИЦТВО\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} Інженеро-годин на виготовлення одиниці\"\n  STR_COST_PER_UNIT_: \"Ціна за одиницю>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Робочого місця необхідно>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"НЕОБХІДНІ СПЕЦІАЛЬНІ МАТЕРІАЛИ\"\n  STR_ITEM_REQUIRED: \"НЕОБХІДНИЙ ПРЕДМЕТ\"\n  STR_UNITS_REQUIRED: \"НЕОБХІДНО ОДИНИЦЬ\"\n  STR_UNITS_AVAILABLE: \"ДОСТУПНО ОДИНИЦЬ\"\n  STR_STOP_PRODUCTION: \"ЗУПИНИТИ ВИРОБНИЦТВО\"\n  STR_ENGINEERS_AVAILABLE_UC: \"ІНЖЕНЕРІВ ВІЛЬНО>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"ВІЛЬНИХ МІСЦЬ В МАЙСТЕРНЯХ>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"МІСЯЧНИЙ ПРИБУТОК>{ALT}{0}\"\n  STR_INCREASE_UC: \"ЗБІЛЬШИТИ\"\n  STR_DECREASE_UC: \"ЗМЕНШИТИ\"\n  STR_UNITS_TO_PRODUCE: \"Одиниць для виготовлення\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Закупівля/Найм персоналу\"\n  STR_COST_OF_PURCHASES: \"Ціна придбань>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"ЦІНА ЗА ОДИНИЦЮ\"\n  STR_QUANTITY_UC: \" КІЛЬКІСТЬ\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"ЧОЛОВІК ВІЛЬНО:ЧОЛОВІК ВСЬОГО>\"\n  STR_SOLDIERS: \"Солдати\"\n  STR_SCIENTISTS: \"Вчені\"\n  STR_ENGINEERS: \"Інженери\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"МІСЦЯ ЗАЙНЯТО:МІСЦЯ ВІЛЬНО>\"\n  STR_LIVING_QUARTERS: \"Житловий модуль\"\n  STR_STORES: \"Склади\"\n  STR_LABORATORIES: \"Лабораторії\"\n  STR_WORK_SHOPS: \"Майстерні\"\n  STR_HANGARS: \"Ангари\"\n  STR_SHORT_RANGE_DETECTION: \"Ближнє виявлення\"\n  STR_DEFENSE_STRENGTH: \"Сила ППО\"\n  STR_TRANSFERS_UC: \"ПЕРЕДАЧІ\"\n  STR_TRANSFERS: \"Передачі\"\n  STR_ARRIVAL_TIME_HOURS: \"Час прибуття (годин)\"\n  STR_COST_: \"Вартість>{ALT}{0}\"\n  STR_AREA_: \"Регіон>{ALT}{0}\"\n  STR_BASE_NAME: \"Назва бази?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"ВИБЕРІТЬ МІСЦЕ ДЛЯ ВХІДНОГО ЛІФТА\"\n  STR_TRANSFER: \"Передача\"\n  STR_AMOUNT_TO_TRANSFER: \"КІЛЬКІСТЬ ДЛЯ ПЕРЕДАЧІ\"\n  STR_SELECT_DESTINATION_BASE: \"Виберіть базу призначення\"\n  STR_COST: \"Ціна\"\n  STR_VICTORY_1: \"Зайшовши в зал, ви бачите інопланетний Мозок - ціль ваших пошуків. Перш ніж ви встигаєте вистелити, Мозок звертається до вас через екран, що знаходиться в приміщенні. Він просить вислухати аргументи на свій захист перш, ніж Ви натиснете на спусковий гачок...\"\n  STR_VICTORY_2: \"\\\"...Багато мільйонів років тому планета, яку ви називаєте Марс, була живою. Це життя було принесене на безплідну планету нашою цивілізацією. Протягом мільйонів років ми відвідували вашу планету і генетично розробили ваш вид. Ви не можете знищити нас, ви - частина нас...\"\n  STR_VICTORY_3: \"...Тут центр Марсіанської цивілізації - піраміди, побудовані за мільйони років до вас видом, який є вашим предком. Немає такої планети якої ми не могли б досягнути. Ця сила скоро може стати вашою. Все що ми просимо - ваша співпраця...\"\n  STR_GAME_OVER_1: \"Прибульці взялися за винищення людства, зруйнували міста, отруїли повітря та океани. Опір земних армій марний проти передових інопланетних технологій. Покоління, які виживуть, перенесуть жахливі мутації, уникнувши знищення прибульцями. Вони стануть рабами і будуть використані для перетворення Землі в колонію прибульців - частину якоїсь невідомої імперії.\"\n  STR_GAME_OVER_2: \"Знання здобуті через проект X-COM загублені назавжди. Вам не вдалося врятувати землю.\"\n  STR_VICTORY_4: \"Мозок знищено зарядом гарячої плазми, сили прибульців переможені.\"\n  STR_VICTORY_5: \"Тільки но прибульці втратили Марс, вони втратили і землю. Незабаром X-Com дослідження дозволило людству процвітати знову, та наголосити Марс своїм. Загроза прибульців зникла, але як на довго - ніхто не знає.\"\n  STR_YOU_HAVE_FAILED: \"Ви не змогли зупинити вторгнення. Одна за одною передові держави підпишуть пакт з прибульцями, які обіцяють дати нові технології, мир і процвітання. Однак швидко стане зрозуміло, що в прибульців інші плани...\"\n  STR_TOTAL_UC: \"ВСЬОГО\"\n  STR_INCOME: \"Дохід\"\n  STR_EXPENDITURE: \"Витрати\"\n  STR_MAINTENANCE: \"Обслуговування\"\n  STR_BALANCE: \"Баланс\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"Активн. НЛО в Регіонах\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"Активн. НЛО в Країнах\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"Активн. X-COM в Регіонах\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"Активн. Х-СОМ в Країнах\"\n  STR_FINANCE: \"Фінанси\"\n  STR_DATE_FIRST: \"{0}e\"\n  STR_DATE_SECOND: \"{0}е\"\n  STR_DATE_THIRD: \"{0}є\"\n  STR_DATE_FOURTH: \"{0}е\"\n  STR_FINANCE_THOUSANDS: \"$1000'рів\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Бракує спеціальних матеріалів для виготовлення{NEWLINE}{0}{NEWLINE}на базі{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Бракує грошей для виготовлення{NEWLINE}{0}{NEWLINE}на базі{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"Виготовлення{NEWLINE}{0}{NEWLINE}на базі{NEWLINE}{1}{NEWLINE}завершено\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"Виготовлення{NEWLINE}{0}{NEWLINE}на базі{NEWLINE}{1}{NEWLINE}завершено\"\n  STR_OK_5_SECONDS: \"OK - 5 сек\"\n  STR_RESEARCH_COMPLETED: \"Дослідження завершено\"\n  STR_VIEW_REPORTS: \"ЗВІТИ\"\n  STR_WE_CAN_NOW_RESEARCH: \"Ми тепер можемо досліджувати\"\n  STR_WE_CAN_NOW_PRODUCE: \"Ми тепер можемо виготовляти\"\n  STR_SUNDAY: \"НЕДІЛЯ\"\n  STR_MONDAY: \"ПОНЕДІЛОК\"\n  STR_TUESDAY: \"ВІВТОРОК\"\n  STR_WEDNESDAY: \"СЕРЕДА\"\n  STR_THURSDAY: \"ЧЕТВЕР\"\n  STR_FRIDAY: \"П'ЯТНИЦЯ\"\n  STR_SATURDAY: \"СУБОТА\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Бракує {0} для заправки {1} в {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Бракує {0} для перезарядки {1} на базі {2}\"\n  STR_UFO_IS_NOT_RECOVERED: \"НЛО не захоплено\"\n  STR_UFO_IS_RECOVERED: \"НЛО захоплено\"\n  STR_CRAFT_IS_LOST: \"Корабель втрачено\"\n  STR_TERROR_CONTINUES: \"Терор продовжується\"\n  STR_ALIENS_DEFEATED: \"Прибульці переможені\"\n  STR_BASE_IS_LOST: \"Базу втрачено\"\n  STR_BASE_IS_SAVED: \"Базу збережено\"\n  STR_ALIEN_BASE_STILL_INTACT: \"Базу прибульців не знищено\"\n  STR_ALIEN_BASE_DESTROYED: \"Базу прибульців знищено\"\n  STR_ALIENS_KILLED: \"ПРИБУЛЬЦІВ ВБИТО\"\n  STR_ALIEN_CORPSES_RECOVERED: \"ТРУПІВ ПРИБУЛЬЦІВ ЗНАЙДЕНО\"\n  STR_LIVE_ALIENS_RECOVERED: \"ЖИВИХ ПРИБУЛЬЦІВ ЗНАЙДЕНО\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"АРТЕФАКТІВ ПРИБУЛЬЦІВ ЗНАЙДЕНО\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"БАЗУ ПРИБУЛЬЦІВ ЗНИЩЕНО\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"ЦИВІЛЬНИХ ВБИТО ПРИБУЛЬЦЯМИ\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"ЦИВІЛЬНИХ ВБИТО СОЛДАТАМИ X-COM\"\n  STR_CIVILIANS_SAVED: \"ЦИВІЛЬНИХ ВРЯТОВАНО\"\n  STR_XCOM_OPERATIVES_KILLED: \"СОЛДАТІВ X-COM ВБИТО\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"СОЛДАТІВ X-COM ЗНИКЛО БЕЗ ВІСТІ\"\n  STR_TANKS_DESTROYED: \"ТАНКІВ ЗНИЩЕНО\"\n  STR_XCOM_CRAFT_LOST: \"КОРАБЕЛЬ X-COM ВТРАЧЕНО\"\n  STR_UFO_RECOVERY: \"ЗНАЙДЕНЕ В НЛО\"\n  STR_ALIEN_BASE_RECOVERY: \"БАЗУ ПРИБУЛЬЦІВ ЗНАЙДЕНО\"\n  STR_BASE_UNDER_ATTACK: \"{0} атаковано!\"\n  STR_BASE_DEFENSES_INITIATED: \"ЗАДІЯНО ЗАХИСТ БАЗИ\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"ГРАВ. ЩИТ ВІДШТОВХНУВ НЛО!\"\n  STR_FIRING: \"СТРІЛЯЄ\"\n  STR_HIT: \"ВЛУЧИВ!\"\n  STR_UFO_DESTROYED: \"НЛО ЗНИЩЕНО!\"\n  STR_MISSED: \"ПРОМАХНУВСЯ!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Продаж/Звільнення персоналу\"\n  STR_VALUE_OF_SALES: \"ВАРТІСТЬ ПРОДАНОГО> {ALT}{0}\"\n  STR_FUNDS: \"ФОНДИ> {ALT}{0}\"\n  STR_SELL_SACK: \"Продати/Звільнити\"\n  STR_VALUE: \"Ціна\"\n  STR_CRAFT_: \"КОРАБЕЛЬ> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"ЗАХОПЛЕННЯ ЗБИТОГО НЛО\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"Вивчіть місце посадки і, при можливості, отримайте доступ до НЛО. Місія завершиться коли всі прибульці будуть вбиті або нейтралізовані. Після цього знайдені рештки НЛО, тіла прибульців та їх спорядження будуть евакуйовані. Для припинення місії поверніть бійців в транспорт і натисніть кнопку \\\"Перервати Місію\\\".\"\n  STR_UFO_GROUND_ASSAULT: \"ШТУРМ НЛО\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"Вивчіть місце посадки і, при можливості, отримайте доступ до НЛО. Місія завершиться коли всі прибульці будуть вбиті або нейтралізовані. Після цього знайдені рештки НЛО, тіла прибульців та їх спорядження будуть евакуйовані. Для припинення місії поверніть бійців в транспорт і натисніть кнопку \\\"Перервати Місію\\\".\"\n  STR_BASE_DEFENSE: \"ЗАХИСТ БАЗИ\"\n  STR_BASE_UC_: \"БАЗА> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"Неподалік приземлився корабель прибульців. Наша база в серйозній небезпеці. Згідно зі стандартною процедурою, цивільний персонал та кораблі X-COM були евакуйовані. Прибульці будуть проникати на базу через ангари та вхідний ліфт. Захищайте базу будь-якою ціною - це битва на смерть. В випадку відступу Ви втратите базу.\"\n  STR_ALIEN_BASE_ASSAULT: \"ШТУРМ БАЗИ ПРИБУЛЬЦІВ\"\n  STR_ALIEN_BASE_ASSAULT_BRIEFING: \"Бійці X-COM проникнули на базу прибульців. Для ліквідації бази потрібно знищити центр керування. Всі прибульці, присутні на базі, мають бути знищені або нейтралізовані. Для припинення місії поверніть бійців в зелену зону висадки та натисніть кнопку \\\"Перервати Місію\\\".\"\n  STR_CYDONIA_BRIEFING: \"Ви прибули в Кідонію. Необхідно проникнути в підземний комплекс, який знаходиться біля Марсіанського Сфінкса. Ви мусите знайти і знищити Інопланетний Мозок, який керує вторгненням. Доля людства у Ваших руках...\"\n  STR_TERROR_MISSION: \"ПРИПИНЕННЯ ТЕРОРУ\"\n  STR_TERROR_MISSION_BRIEFING: \"Місія буде успішною, коли всі ворожі частини будуть усунені або нейтралізовані. Ви повинні намагатися врятувати життя будь-якого цивільного населення в цьому районі шляхом нейтралізації небезпеки від прибульців. Щоб скасувати місію, поверніт оперативників X-Com до транспортного засобу та натисніть значок 'Скасувати Завдання'.\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"НЕМАЄ ВІЛЬНОГО АНГАРУ ДЛЯ БУДІВНИЦТВА КОРАБЛЯ!{SMALLLINE}Кожний корабель приписаний до бази, транспортований на базу, придбаний або такий, який тільки будується, використовує один ангар. Будуйте новий ангар або транспортуйте якийсь корабель на іншу базу.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"НЕМАЄ ВІЛЬНОГО АНГАРУ ДЛЯ КУПІВЛІ КОРАБЛЯ!{SMALLLINE}Кожний корабель приписаний до бази, транспортований на базу, придбаний або такий, який тільки будується, використовує один ангар. Будуйте новий ангар або транспортуйте якийсь корабель на іншу базу.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"НЕМАЄ ВІЛЬНОГО АНГАРУ ДЛЯ ТРАНСПОРТУВАННЯ!{SMALLLINE}Кожний корабель приписаний до бази, транспортований на базу, придбаний або такий, який тільки будується, використовує один ангар. Будуйте новий ангар або транспортуйте якийсь корабель на іншу базу.\"\n  STR_CANNOT_BUILD_HERE: \"НЕ МОЖНА БУДУВАТИ ТУТ!{SMALLLINE}Будівництво можливе лише поруч з уже наявним модулем.\"\n  STR_NO_FREE_ACCOMODATION: \"НЕМАЄ ВІЛЬНИХ МІСЦЬ!{SMALLLINE}База-адресат не має достатньо вільних місць в житлових модулях.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"НЕ ДОСТАТНЬО РОБОЧИХ МІСЦЬ!{SMALLLINE}Будуйте нову майстерню або зменшуйте роботу над іншими проектами.\"\n  STR_NOT_ENOUGH_MONEY: \"НЕ ДОСТАТНЬО ГРОШЕЙ!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"НЕ ДОСТАТНЬО МІСЦЯ НА СКЛАДАХ!{SMALLLINE}Будуйте нові склади або транспортуйте наявні предмети на інші бази.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"НЕ ДОСТАТНЬО ЖИТЛОВОЇ ПЛОЩІ!{SMALLLINE}Будуйте житлові модулі або транспортуйте персонал на інші бази.\"\n  STR_LAUNCH_INTERCEPTION: \"ПОЧАТИ ПЕРЕХОПЛЕННЯ\"\n  STR_CRAFT: \"КОРАБЕЛЬ\"\n  STR_STATUS: \"СТАТУС\"\n  STR_BASE: \"БАЗА\"\n  STR_READY: \"ГОТОВИЙ\"\n  STR_OUT: \"НА ВИЛЬОТІ\"\n  STR_REPAIRS: \"НА РЕМОНТІ\"\n  STR_REFUELLING: \"ЗАПРАВЛЯЄТЬСЯ\"\n  STR_REARMING: \"ПЕРЕЗАРЯД.\"\n  STR_TARGET: \"ЦІЛЬ: {0}\"\n  STR_WAY_POINT: \"ТОЧКА ШЛЯХУ\"\n  STR_ARE_YOU_SURE_CYDONIA: \"Ви впевнені, що бажаєте відправити експедицію на Кідонію?\"\n  STR_YES: \"ТАК\"\n  STR_NO: \"НІ\"\n  STR_SELECT_DESTINATION: \"ВИБЕРІТЬ ЦІЛЬ\"\n  STR_CYDONIA: \"КІДОНІЯ\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"ВИБЕРІТЬ МІСЦЕ ДЛЯ НОВОЇ БАЗИ\"\n  STR_RETURN_TO_BASE: \"ПОВЕРНУТИСЬ НА БАЗУ\"\n  STR_SELECT_NEW_TARGET: \"ОБРАТИ НОВУ ЦІЛЬ\"\n  STR_PATROL: \"ПАТРУЛЮВАТИ\"\n  STR_STATUS_: \"СТАТУС>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"ПОШКОДЖЕНИЙ - ПОВЕРТАЄТЬСЯ НА БАЗУ\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"МАЛО ПАЛЬНОГО - ПОВЕРТАЄТЬСЯ НА БАЗУ\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"МІСІЮ ЗАВЕРШЕНО - ПОВЕРТАЄТЬСЯ НА БАЗУ\"\n  STR_PATROLLING: \"ПАТРУЛЮЄ\"\n  STR_TAILING_UFO: \"ПЕРЕСЛІДУЄ НЛО\"\n  STR_INTERCEPTING_UFO: \"ПЕРЕХОПЛЮЄ НЛО-{0}\"\n  STR_RETURNING_TO_BASE: \"ПОВЕРТАЄТЬСЯ НА БАЗУ\"\n  STR_DESTINATION_UC_: \"ПУНКТ ПРИЗНАЧЕННЯ:{0}\"\n  STR_BASE_UC: \"БАЗА>{ALT}{0}\"\n  STR_SPEED_: \"ШВИДКІСТЬ>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"МАКСИМАЛЬНА ШВИДКІСТЬ>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"ВИСОТА>{ALT}{0}\"\n  STR_VERY_LOW: \"ДУЖЕ МАЛА\"\n  STR_LOW_UC: \"МАЛА\"\n  STR_HIGH_UC: \"ВЕЛИКА\"\n  STR_VERY_HIGH: \"ДУЖЕ ВЕЛИКА\"\n  STR_FUEL: \"ПАЛЬНЕ>{ALT}{0}\"\n  STR_WEAPON_ONE: \"ЗБРОЯ-1>{ALT}{0}\"\n  STR_NONE_UC: \"НЕМАЄ\"\n  STR_ROUNDS_: \"БОЄЗАПАС>{ALT}{0}\"\n  STR_WEAPON_TWO: \"ЗБРОЯ-2>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"Виберіть корабель\"\n  STR_BASE_: \"База>{0}\"\n  STR_NAME_UC: \"ІМ'Я\"\n  STR_AMMO_: \"НАБОЇ>{ALT}{0}\"\n  STR_CREW: \"ЕКІПАЖ\"\n  STR_EQUIPMENT_UC: \"СПОРЯДЖЕННЯ\"\n  STR_ARMOR: \"БРОНЯ\"\n  STR_MAX: \"МАКС>{ALT}{0}\"\n  STR_ROOKIE: \"Новобранець\"\n  STR_SQUADDIE: \"Рядовий\"\n  STR_SERGEANT: \"Сержант\"\n  STR_CAPTAIN: \"Капітан\"\n  STR_COLONEL: \"Полковник\"\n  STR_COMMANDER: \"Командир\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Виберіть екіпаж для {0}\"\n  STR_SORT_BY: \"ВІДСОРТУВАТИ ЗА...\"\n  STR_ORIGINAL_ORDER: \"ЗАГАЛЬНИЙ НАКАЗ\"\n  STR_MISSIONS2: \"МІСІЯ\"\n  STR_KILLS2: \"ВБИВСТВ\"\n  STR_WOUND_RECOVERY2: \"ЗАГОЄННЯ РАН\"\n  STR_SPACE_AVAILABLE: \"МІСЦЯ ВІЛЬНО>{ALT}{0}\"\n  STR_SPACE_USED: \"МІСЦЯ ЗАЙНЯТО>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"МІСЦЯ ЗАЙНЯТО\"\n  STR_RANK: \"ЗВАННЯ\"\n  STR_WOUNDED: \"ПОРАНЕНИЙ\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Спорядження для {0}\"\n  STR_DEFENSE_VALUE: \"Ступінь Захисту\"\n  STR_HIT_RATIO: \"Точність\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}готовий до{NEWLINE}приземлення біля{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"Почати операцію?\"\n  STR_SELECT_ARMAMENT: \"Виберіть зброю\"\n  STR_AMMUNITION_AVAILABLE: \"БОЄПРИПАСІВ ДОСТУПНО\"\n  STR_ARMAMENT: \"ЗБРОЯ\"\n  STR_NOT_AVAILABLE: \"Н.Д.\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"ОБЕРІТЬ БРОНЮ ДЛЯ{NEWLINE}{0}\"\n  STR_TYPE: \"ТИП\"\n  STR_PERSONAL_ARMOR_UC: \"БРОНЕКОСТЮМ\"\n  STR_POWER_SUIT_UC: \"СИЛОВИЙ СКАФАНДР\"\n  STR_FLYING_SUIT_UC: \"ЛІТАЛЬНИЙ СКАФАНДР\"\n  STR_SELECT_ARMOR: \"Виберіть броню\"\n  STR_NORTH: \"ПІВНІЧ\"\n  STR_NORTH_EAST: \"ПІВНІЧНИЙ СХІД\"\n  STR_EAST: \"СХІД\"\n  STR_SOUTH_EAST: \"ПІВДЕННИЙ СХІД\"\n  STR_SOUTH: \"ПІВДЕНЬ\"\n  STR_SOUTH_WEST: \"ПІВДЕННИЙ ЗАХІД\"\n  STR_WEST: \"ЗАХІД\"\n  STR_NORTH_WEST: \"ПІВНІЧНИЙ ЗАХІД\"\n  STR_SELECT_ACTION: \"ВИБЕРІТЬ ЗАВДАННЯ\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"ПРОДОВЖИТИ ПЕРЕХОПЛЕННЯ\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"ПЕРЕСЛІДУВАТИ БЕЗ ПЕРЕХОПЛЕННЯ\"\n  STR_VERY_LARGE: \"ДУЖЕ ВЕЛИКИЙ\"\n  STR_LARGE: \"ВЕЛИКИЙ\"\n  STR_MEDIUM_UC: \"СЕРЕДНІЙ\"\n  STR_SMALL: \"МАЛИЙ\"\n  STR_VERY_SMALL: \"ДУЖЕ МАЛИЙ\"\n  STR_GROUNDED: \"НА ЗЕМЛІ\"\n  STR_DETECTED: \"Виявлено\"\n  STR_SIZE_UC: \"РОЗМІР\"\n  STR_ALTITUDE: \"ВИСОТА\"\n  STR_HEADING: \"НАПРЯМ\"\n  STR_SPEED: \"ШВИДКІСТЬ\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"ЦЕНТР НА НЛО-ЧАС=5 Сек\"\n  STR_TRACKING_LOST: \"ВТРАЧЕНО\"\n  STR_REDIRECT_CRAFT: \"ПЕРЕНАПРАВИТИ КОРАБЕЛЬ\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"ЛЕТІТИ ДО ОСТАННЬОЇ ВІДОМОЇ ПОЗИЦІЇ НЛО\"\n  STR_UFO_: \"НЛО-{0}\"\n  STR_ALIEN_BASE_: \"БАЗА ПРИБУЛЬЦІВ-{0}\"\n  STR_CRASH_SITE_: \"МІСЦЕ АВАРІЇ-{0}\"\n  STR_LANDING_SITE_: \"МІСЦЕ ПОСАДКИ-{0}\"\n  STR_WAY_POINT_: \"ТОЧКА ШЛЯХУ-{0}\"\n  STR_TERROR_SITE: \"МІСЦЕ ТЕРОРУ-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}досяг{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"Патрулювання\"\n  STR_ALIEN_ORIGINS: \"Походження прибульців\"\n  STR_THE_MARTIAN_SOLUTION: \"Вирішення Марсіанського Питання\"\n  STR_CYDONIA_OR_BUST: \"Кідонія або кінець\"\n  STR_UFOPAEDIA: \"НЛОПЕДІЯ\"\n  STR_XCOM_CRAFT_ARMAMENT: \"КОРАБЛІ X-COM ТА ЇХНЄ ОЗБРОЄННЯ\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"ВАЖКІ БОЙОВІ ПЛАТФОРМИ (ВБП)\"\n  STR_WEAPONS_AND_EQUIPMENT: \"ЗБРОЯ ТА СПОРЯДЖЕННЯ\"\n  STR_ALIEN_ARTIFACTS: \"АРТЕФАКТИ ПРИБУЛЬЦІВ\"\n  STR_BASE_FACILITIES: \"МОДУЛІ БАЗИ\"\n  STR_ALIEN_LIFE_FORMS: \"ПОЗАЗЕМНІ ФОРМИ ЖИТТЯ\"\n  STR_ALIEN_RESEARCH_UC: \"ДІЯЛЬНІСТЬ ПРИБУЛЬЦІВ\"\n  STR_UFO_COMPONENTS: \"КОМПОНЕНТИ НЛО\"\n  STR_UFOS: \"НЛО\"\n  STR_SELECT_ITEM: \"ВИБЕРІТЬ ПРЕДМЕТ\"\n  STR_ACCELERATION: \"ПРИСКОРЕННЯ>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"ЗАПАС ПАЛЬНОГО>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"ПІДВІСОК ДЛЯ ЗБРОЇ>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"РІВЕНЬ ЗАХИСТУ>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"ОБ'ЄМ ВАНТАЖНОГО ВІДСІКУ>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"МІСЦЬ ДЛЯ ВБП>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Пошкодження\"\n  STR_RANGE: \"Радіус ураження\"\n  STR_KILOMETERS: \"{0} км\"\n  STR_ACCURACY: \"Точність\"\n  STR_RE_LOAD_TIME: \"Час перезарядки\"\n  STR_SECONDS: \"{0}с\"\n  STR_DAMAGE_ARMOR_PIERCING: \"БРОНЕБІЙНИЙ\"\n  STR_DAMAGE_INCENDIARY: \"ЗАПАЛЮВАЛЬНИЙ\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"ВИБУХОВИЙ\"\n  STR_DAMAGE_LASER_BEAM: \"ЛАЗЕРНИЙ{NEWLINE}ПРОМІНЬ\"\n  STR_DAMAGE_PLASMA_BEAM: \"ПЛАЗМОВИЙ{NEWLINE}ПРОМІНЬ\"\n  STR_DAMAGE_STUN: \"ПАРАЛІТИЧНИЙ\"\n  STR_DAMAGE_MELEE: \"БЛИЖНІЙ БІЙ\"\n  STR_DAMAGE_ACID: \"КИСЛОТНИЙ\"\n  STR_DAMAGE_SMOKE: \"ДИМОВИЙ\"\n  STR_SHOT_TYPE: \"ТИП ПОСТРІЛУ\"\n  STR_ACCURACY_UC: \"ТОЧНІСТЬ\"\n  STR_TIME_UNIT_COST: \"ОЧКИ ДІЙ\"\n  STR_DAMAGE_UC: \"ПОШКОДЖЕННЯ\"\n  STR_AMMO: \"ЗАРЯД\"\n  STR_SHOT_TYPE_AUTO: \"Черга\"\n  STR_SHOT_TYPE_SNAP: \"Навмання\"\n  STR_SHOT_TYPE_AIMED: \"Прицільно\"\n  STR_CONSTRUCTION_TIME: \"Час будівництва\"\n  STR_CONSTRUCTION_COST: \"Вартість будівництва\"\n  STR_MAINTENANCE_COST: \"Вартість утримання\"\n  STR_LOW: \"Низький\"\n  STR_MEDIUM: \"Середній\"\n  STR_HIGH: \"Високий\"\n  STR_CRAFT_WEAPON: \"Озброєння кораблів\"\n  STR_CRAFT_AMMUNITION: \"Боєприпаси кораблів\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Важка Бойова Платформа\"\n  STR_WEAPON: \"Зброя\"\n  STR_AMMUNITION: \"Боєприпаси\"\n  STR_EQUIPMENT: \"Спорядження\"\n  STR_ALIEN_CORPSE: \"Труп прибульця\"\n  STR_UFO_COMPONENT: \"Компонент НЛО\"\n  STR_PERSONAL_ARMOR: \"Бронекостюм\"\n  STR_RAW_MATERIALS: \"Вихідні матеріали\"\n  STR_HWP_CANNON_SHELLS: \"Гарматні снаряди ВБП\"\n  STR_ALIEN: \"Прибулець\"\n  STR_SECTOID: \"Сектоїд\"\n  STR_SNAKEMAN: \"Людинозмія\"\n  STR_ETHEREAL: \"Ефіріал\"\n  STR_MUTON: \"Мутон\"\n  STR_FLOATER: \"Летун\"\n  STR_CELATID: \"Целатид\"\n  STR_SILACOID: \"Силакоїд\"\n  STR_CHRYSSALID: \"Крисалід\"\n  STR_ZOMBIE: \"Зомбі\"\n  STR_REAPER: \"Рипер\"\n  STR_SECTOPOD: \"Сектопод\"\n  STR_CYBERDISC: \"Кібердиск\"\n  STR_LIVE_COMMANDER: \"Командир\"\n  STR_LIVE_LEADER: \"Лідер\"\n  STR_LIVE_ENGINEER: \"Інженер\"\n  STR_LIVE_MEDIC: \"Медик\"\n  STR_LIVE_NAVIGATOR: \"Навігатор\"\n  STR_LIVE_SOLDIER: \"Солдат\"\n  STR_LIVE_TERRORIST: \"Терорист\"\n  STR_FLOATER_SOLDIER: \"Летун-солдат\"\n  STR_FLOATER_NAVIGATOR: \"Летун-навігатор\"\n  STR_FLOATER_MEDIC: \"Летун-медик\"\n  STR_FLOATER_ENGINEER: \"Летун-інженер\"\n  STR_FLOATER_LEADER: \"Летун-лідер\"\n  STR_FLOATER_COMMANDER: \"Летун-командир\"\n  STR_SECTOID_SOLDIER: \"Сектоїд-солдат\"\n  STR_SECTOID_NAVIGATOR: \"Сектоїд-навігатор\"\n  STR_SECTOID_MEDIC: \"Сектоїд-медик\"\n  STR_SECTOID_ENGINEER: \"Сектоїд-інженер\"\n  STR_SECTOID_LEADER: \"Сектоїд-лідер\"\n  STR_SECTOID_COMMANDER: \"Сектоїд-командир\"\n  STR_SNAKEMAN_SOLDIER: \"Людинозмія-солдат\"\n  STR_SNAKEMAN_NAVIGATOR: \"Людинозмія-навігатор\"\n  STR_SNAKEMAN_ENGINEER: \"Людинозмія-інженер\"\n  STR_SNAKEMAN_LEADER: \"Людинозмія-лідер\"\n  STR_SNAKEMAN_COMMANDER: \"Людинозмія-командир\"\n  STR_MUTON_SOLDIER: \"Мутон-солдат\"\n  STR_MUTON_NAVIGATOR: \"Мутон-навігатор\"\n  STR_MUTON_ENGINEER: \"Мутон-інженер\"\n  STR_ETHEREAL_SOLDIER: \"Ефіріал-солдат\"\n  STR_ETHEREAL_LEADER: \"Ефіріал-лідер\"\n  STR_ETHEREAL_COMMANDER: \"Ефіріал-командир\"\n  STR_CYBERDISC_TERRORIST: \"Кібердиск Терорист\"\n  STR_REAPER_TERRORIST: \"Рипер Терорист\"\n  STR_CHRYSSALID_TERRORIST: \"Крисалід Терорист\"\n  STR_CELATID_TERRORIST: \"Целатид-терорист\"\n  STR_SILACOID_TERRORIST: \"Силакоїд Терорист\"\n  STR_SECTOPOD_TERRORIST: \"Сектопод Терорист\"\n  STR_UFO_POWER_SOURCE: \"Джерело енергії НЛО\"\n  STR_UFO_NAVIGATION: \"Навігація НЛО\"\n  STR_UFO_CONSTRUCTION: \"Конструкція НЛО\"\n  STR_ALIEN_FOOD: \"Їжа прибульців\"\n  STR_ALIEN_REPRODUCTION: \"Інкубатор прибульців\"\n  STR_ALIEN_ENTERTAINMENT: \"Розваги прибульців\"\n  STR_ALIEN_SURGERY: \"Хірургія прибульців\"\n  STR_EXAMINATION_ROOM: \"Кімната допитів\"\n  STR_ALIEN_ALLOYS: \"Сплави прибульців\"\n  STR_ALIEN_HABITAT: \"Місце проживання прибульців\"\n  STR_POWER_SUIT: \"Силовий скафандр\"\n  STR_FLYING_SUIT: \"Літальний скафандр\"\n  STR_HWP_ROCKETS: \"Ракета ВБП\"\n  STR_HWP_FUSION_BOMB: \"Бластер-ракета ВБП\"\n  STR_LASER_WEAPONS: \"Лазерна зброя\"\n  STR_NEW_FIGHTER_CRAFT: \"Новий винищувач\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Новий винищувач-транспорт\"\n  STR_ULTIMATE_CRAFT: \"Останній корабель\"\n  STR_LASER_PISTOL: \"Лазерний пістолет\"\n  STR_LASER_RIFLE: \"Лазерна гвинтівка\"\n  STR_HEAVY_LASER: \"Важкий лазер\"\n  STR_LASER_CANNON: \"Лазерна гармата\"\n  STR_PLASMA_CANNON: \"Плазмова гармата\"\n  STR_FUSION_MISSILE: \"Бластерна ракета\"\n  STR_LASER_DEFENSE: \"Лазерна система ППО\"\n  STR_PLASMA_DEFENSE: \"Плазмова система ППО\"\n  STR_FUSION_DEFENSE: \"Бластерна система ППО\"\n  STR_GRAV_SHIELD: \"Гравітаційний щит\"\n  STR_MIND_SHIELD: \"Ментальний щит\"\n  STR_PSI_LAB: \"Псі-лабораторія\"\n  STR_MOTION_SCANNER: \"Сканер руху\"\n  STR_MEDI_KIT: \"Мед-комплект\"\n  STR_TANK_CANNON: \"Танк/Гармата\"\n  STR_TANK_ROCKET_LAUNCHER: \"Танк/Ракетна установка\"\n  STR_TANK_LASER_CANNON: \"Танк/Лазерна гармата\"\n  STR_HOVERTANK_PLASMA: \"Ховертанк/Плазма\"\n  STR_HOVERTANK_LAUNCHER: \"Ховертанк/Бластер\"\n  STR_STINGRAY_LAUNCHER: \"Пускова установка \\\"Скат\\\"\"\n  STR_AVALANCHE_LAUNCHER: \"Пускова установка \\\"Лавина\\\"\"\n  STR_CANNON: \"Авіагармата\"\n  STR_FUSION_BALL_LAUNCHER: \"Бластерна гармата\"\n  STR_PLASMA_BEAM: \"Плазмова гармата\"\n  STR_STINGRAY_MISSILES: \"Ракета \\\"Скат\\\"\"\n  STR_AVALANCHE_MISSILES: \"Ракета \\\"Лавина\\\"\"\n  STR_CANNON_ROUNDS_X50: \"Снаряди для Авіагармати(x50)\"\n  STR_FUSION_BALL: \"Бластерна ракета\"\n  STR_SOLDIER: \"Солдат\"\n  STR_SCIENTIST: \"Вчений\"\n  STR_ENGINEER: \"Інженер\"\n  STR_NORTH_AMERICA: \"Північна Америка\"\n  STR_ARCTIC: \"Арктика\"\n  STR_ANTARCTICA: \"Антарктика\"\n  STR_SOUTH_AMERICA: \"Південна Америка\"\n  STR_EUROPE: \"Європа\"\n  STR_NORTH_AFRICA: \"Північна Африка\"\n  STR_SOUTHERN_AFRICA: \"Південна Африка\"\n  STR_CENTRAL_ASIA: \"Центральна Азія\"\n  STR_SOUTH_EAST_ASIA: \"Півд.-східна Азія\"\n  STR_SIBERIA: \"Сибір\"\n  STR_AUSTRALASIA: \"Австралія\"\n  STR_PACIFIC: \"Тихий Океан\"\n  STR_NORTH_ATLANTIC: \"Північна Атлантика\"\n  STR_SOUTH_ATLANTIC: \"Півд. Атлантика\"\n  STR_INDIAN_OCEAN: \"Індійський Океан\"\n  STR_ALIEN_RESEARCH: \"Дослідження\"\n  STR_ALIEN_HARVEST: \"Збір врожаю\"\n  STR_ALIEN_ABDUCTION: \"Викрадення\"\n  STR_ALIEN_INFILTRATION: \"Проникнення\"\n  STR_ALIEN_BASE: \"База прибульців\"\n  STR_ALIEN_TERROR: \"Терор\"\n  STR_ALIEN_RETALIATION: \"Удар у відповідь\"\n  STR_ALIEN_SUPPLY: \"Постачання прибульців\"\n  STR_MAXIMUM_SPEED: \"Макс. швидкість\"\n  STR_HYPER_WAVE_DECODER_UC: \"ГІПЕРХВИЛЬОВИЙ ДЕКОДЕР\"\n  STR_SKYRANGER: \"РЕЙНДЖЕР\"\n  STR_LIGHTNING: \"БЛИСКАВКА\"\n  STR_AVENGER: \"МЕСНИК\"\n  STR_INTERCEPTOR: \"ПЕРЕХОПЛЮВАЧ\"\n  STR_FIRESTORM: \"ВОГНЯНИЙ ШТОРМ\"\n  STR_UFO: \"НЛО\"\n  STR_STINGRAY: \"СКАТ\"\n  STR_AVALANCHE: \"ЛАВИНА\"\n  STR_CANNON_UC: \"АВІАГАРМАТА\"\n  STR_FUSION_BALL_UC: \"БЛАСТЕРНА ГАРМАТА\"\n  STR_LASER_CANNON_UC: \"ЛАЗЕРНА ГАРМАТА\"\n  STR_PLASMA_BEAM_UC: \"ПЛАЗМОВИЙ ПРОМІНЬ\"\n  STR_DAMAGE_CAPACITY: \"Рівень захисту\"\n  STR_WEAPON_POWER: \"Потужність зброї\"\n  STR_WEAPON_RANGE: \"Дальність зброї\"\n  STR_ACCESS_LIFT: \"Вхідний ліфт\"\n  STR_LABORATORY: \"Лабораторія\"\n  STR_WORKSHOP: \"Майстерня\"\n  STR_SMALL_RADAR_SYSTEM: \"Ближній радар\"\n  STR_LARGE_RADAR_SYSTEM: \"Дальній радар\"\n  STR_MISSILE_DEFENSES: \"Ракетний захист\"\n  STR_GENERAL_STORES: \"Склад\"\n  STR_ALIEN_CONTAINMENT: \"Ізолятор прибульців\"\n  STR_LASER_DEFENSES: \"Лазерний захист\"\n  STR_PLASMA_DEFENSES: \"Плазмовий захист\"\n  STR_FUSION_BALL_DEFENSES: \"Бластерний захист\"\n  STR_PSIONIC_LABORATORY: \"Псі-лабораторія\"\n  STR_HYPER_WAVE_DECODER: \"Гіперхвильовий декодер\"\n  STR_HANGAR: \"Ангар\"\n  STR_USA: \"США\"\n  STR_RUSSIA: \"РОСІЯ\"\n  STR_UK: \"ВЕЛИКА БРИТАНІЯ\"\n  STR_FRANCE: \"ФРАНЦІЯ\"\n  STR_GERMANY: \"НІМЕЧЧИНА\"\n  STR_ITALY: \"ІТАЛІЯ\"\n  STR_SPAIN: \"ІСПАНІЯ\"\n  STR_CHINA: \"КИТАЙ\"\n  STR_JAPAN: \"ЯПОНІЯ\"\n  STR_INDIA: \"ІНДІЯ\"\n  STR_BRAZIL: \"БРАЗИЛІЯ\"\n  STR_AUSTRALIA: \"АВСТРАЛІЯ\"\n  STR_NIGERIA: \"НІГЕРІЯ\"\n  STR_SOUTH_AFRICA: \"ПІВДЕННА АФРИКА\"\n  STR_EGYPT: \"ЄГИПЕТ\"\n  STR_CANADA: \"КАНАДА\"\n  STR_TANK: \"Танк\"\n  STR_CIVILIAN: \"Цивільний\"\n  STR_JAN: \"Січ\"\n  STR_FEB: \"Лют\"\n  STR_MAR: \"Бер\"\n  STR_APR: \"Кві\"\n  STR_MAY: \"Тра\"\n  STR_JUN: \"Чер\"\n  STR_JUL: \"Лип\"\n  STR_AUG: \"Сер\"\n  STR_SEP: \"Вер\"\n  STR_OCT: \"Жов\"\n  STR_NOV: \"Лис\"\n  STR_DEC: \"Гру\"\n  STR_INTERNATIONAL_RELATIONS: \"Міжнародні відносини\"\n  STR_COUNTRY: \"Країна\"\n  STR_FUNDING: \"Фінансування\"\n  STR_CHANGE: \"Зміна\"\n  STR_WEAPON_SYSTEMS: \"СИСТЕМИ ОЗБРОЄННЯ\"\n  STR_HWPS: \"ВБП\"\n  STR_DAMAGE_UC_: \"ПОШКОДЖЕННЯ>{ALT}{0}\"\n  STR_ACCESS_LIFT_UFOPEDIA: \"Вхідний ліфт використовується для доставки персоналу та обладнання в підземну базу. Створення нової бази починається з будівництва цього модуля. Ліфт вразливий для проникнення потенційного противника.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Житловий модуль забезпечує розміщення до 50 чоловік. Тут знаходяться кімната відпочинку, їдальня та спальні приміщення.\"\n  STR_LABORATORY_UFOPEDIA: \"В лабораторії можуть працювати до 50 вчених. Лабораторії оснащені найсучаснішими технологіями для проведення фізичних, біохімічних та космологічних досліджень. Передбачений зв'язок з кращими дослідницькими центрами світу, включаючи військові установи.\"\n  STR_WORKSHOP_UFOPEDIA: \"Майстерня обладнана всім необхідним для виробництва спорядження і техніки, розробленої в лабораторіях. В майстерні можуть працювати до 50 інженерів, в залежності від того скільки місця займає обладнання, яке виготовляють.\"\n  STR_SMALL_RADAR_SYSTEM_UFOPEDIA: \"Невелика система виявлення має ефективний радіус дії до 300 морських миль і пов'язана із супутниковими системами для наземного пошуку. Кожна система має 10% шанс виявлення об'єкта середнього розміру кожні 30 хвилин.\"\n  STR_LARGE_RADAR_SYSTEM_UFOPEDIA: \"Велика система виявлення має ефективний радіус дії до 450 морських миль і пов'язана з супутниковими системами для пошуку на суші. Кожна система має 20% шанс виявлення об'єкта середнього розміру кожні 30 хвилин.\"\n  STR_MISSILE_DEFENSES_UFOPEDIA: \"Ракетна система ППО (протиповітряної оборони) забезпечує деякий захист проти літальних апаратів, які намагаються сісти неподалік від бази.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"Все обладнання, зброя, військове спорядження, матеріали та важкі бойові платформи зберігаються на складах, включаючи обладнання приписане до кораблів в ангарах.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"Для підтримання життєдіяльності прибульців необхідні спеціальні умови. Ізолятор прибульців дозволяє безпечно утримувати до 10 інопланетних організмів в ізольованих камерах.\"\n  STR_LASER_DEFENSES_UFOPEDIA: \"Лазерна система ППО забезпечує кращий захист проти ворожих літальних апаратів.\"\n  STR_PLASMA_DEFENSES_UFOPEDIA: \"Плазмова система ППО забезпечує ефективний захист проти ворожих літальних апаратів.\"\n  STR_FUSION_BALL_DEFENSES_UFOPEDIA: \"Бластерні ракети забезпечують найбільш ефективний захист проти атак прибульців. Під час вибуху ці ракети викидають антиматерію, яка, анігілюючи, знищує все в певному радіусі.\"\n  STR_GRAV_SHIELD_UFOPEDIA: \"Гравітаційний щит відштовхує літальні апарати противника при спробі сісти неподалік від бази, даючи можливість захисним системам вистрелити знову. Це фактично подвоює ефективність систем ППО бази. \"\n  STR_MIND_SHIELD_UFOPEDIA: \"Для виявлення присутності людей прибульці покладаються на характерні хвилі, які випромінює людський мозок. Ментальний щит екранує ці мозкові хвилі, сильно зменшуючи ймовірність виявлення бази противником.\"\n  STR_PSIONIC_LABORATORY_UFOPEDIA: \"Псі-лабораторія дозволяє провести оцінку псіонічного потенціалу всіх бійців на базі, а також необхідне для розвитку псі-вмінь навчання. Кожна лабораторія може тренувати до 10 чоловік одночасно, розподіл на тренування відбувається в кінці місяця. Для бойового використання псіонічних вмінь необхідно спорядити бійців псі-підсилювачами.\"\n  STR_HYPER_WAVE_DECODER_UFOPEDIA: \"Засоби зв'язку прибульців базуються на використанні гіперпросторових хвиль, які поширюються майже миттєво. Декодер дозволяє здійснювати перехоплення та розшифрування переговорів НЛО. Можна визначити тип НЛО, расу прибульців і тип виконуваного завдання.\"\n  STR_HANGAR_UFOPEDIA: \"Кожен ангар може вмістити один корабель. Є засоби для технічного обслуговування, заправки та ремонту кораблів X-Com. Кожен корабель, розташований на базі, повинен мати вільний ангар, який за ним закріплений, і який не може бути використаний іншим кораблем, навіть якщо закріплений корабель вилетів на місію.\"\n  STR_PISTOL_UFOPEDIA: \"Стандартний пістолет X-Com - це високоміцний напіввтомат з магазином на 12 патронів.\"\n  STR_RIFLE_UFOPEDIA: \"Високоточна снайперська гвинтівка калібру 6.7мм, оснащена лазерним прицілом. Магазин вміщує 20 патронів.\"\n  STR_HEAVY_CANNON_UFOPEDIA: \"Важка гармата - потужна, але громіздка зброя. Вона відзначається можливістю використання трьох видів боєприпасів - бронебійних, вибухових та запалювальних.\"\n  STR_AUTO_CANNON_UFOPEDIA: \"Авто-гармата поєднує експлуатаційну гнучкість та потужність важкої гармати з можливістю автоматичної стрільби.\"\n  STR_ROCKET_LAUNCHER_UFOPEDIA: \"Пускова ракетна установка з лазерною системою наведення. Може стріляти трьома видами ракет.\"\n  STR_LASER_PISTOL_UFOPEDIA: \"Лазерний пістолет - ефективна реалізація нової технології. Поєднує зручність пістолета з більшою точністю та скорострільністю.\"\n  STR_LASER_RIFLE_UFOPEDIA: \"Лазерна гвинтівка - більш потужна та точна зброя, що базується на розробках лазерного пістолета.\"\n  STR_HEAVY_LASER_UFOPEDIA: \"Важкий лазер - громіздка, але напрочуд ефективна зброя.\"\n  STR_GRENADE_UFOPEDIA: \"Стандартна осколкова граната з точним таймером для запалу.\"\n  STR_SMOKE_GRENADE_UFOPEDIA: \"Димові гранати використовуються для забезпечення прикриття в складних бойових ситуаціях. Використовуйте з обережністю, оскільки ворог теж може використати низьку видимість в диму.\"\n  STR_PROXIMITY_GRENADE_UFOPEDIA: \"Сенсорна граната використовується так само, як і звичайна, але після приземлення її запалом керує сенсор, що реагує на рух. Правильне використання вимагає хорошого вміння та особливої обережності.\"\n  STR_HIGH_EXPLOSIVE_UFOPEDIA: \"Заряд вибухівки, який використовується для знищення об'єктів. Евакуюйте персонал від місця вибуху.\"\n  STR_MOTION_SCANNER_UFOPEDIA: \"Цей складний пристрій використовує потужні алгоритми обробки даних, які надходять з різних сенсорів, для виявлення рухомих об'єктів. Для використання сканера натисніть \\\"Використати Сканер\\\" в меню дій, під час тактичної місії. Стрілка на екрані пристрою показує напрям погляду бійця, який використовує сканер (Північ знаходиться вгорі). Миготливі плями - це об'єкти, які нещодавно рухались. Великі плями відповідають великим об'єктам, чи таким, які швидко рухаються. Нерухомі об'єкти сканером не фіксуються.\"\n  STR_MEDI_KIT_UFOPEDIA: \"Мед-комплект містить засоби для зупинки кровотеч, а також знеболювальні та стимулювальні препарати.{NEWLINE} Для застосування мед-комплекту потрібно стати навпроти солдата який потребує лікування. Якщо солдат лежить, потрібно встати над ним. При використанні виберіть:{NEWLINE}ЛІКУВАННЯ> Частини тіла, які мають смертельні рани, позначені червоним. Виберіть уражену частину та натисніть кнопку, щоб зупинити кровотечу.{NEWLINE}СТИМУЛЯТОР> Ін'єкція стимулятора відновлює енергію бійця, може використовуватись для повернення потерпілих до свідомості (для цього потрібно стояти над тілом).{NEWLINE}ЗНЕБОЛЮЮЧЕ> Введення комплексу знеболювальних препаратів допомагає покращити моральний стан поранених.\"\n  STR_PSI_AMP_UFOPEDIA: \"Псі-підсилювач можуть використовувати лише солдати з псіонічними вміннями. Для використання виберіть тип атаки, а далі - ціль атаки. Можливі два типи атаки:{NEWLINE}ПАНІКА> При успішній атаці противник буде деморалізований і може впасти в стан паніки.{NEWLINE}КОНТРОЛЬ РОЗУМУ> При успішній атаці ви отримуєте безпосередній контроль над діями ворога, так ніби він є одним із ваших солдат. Це найскладніший тип псі-атаки.\"\n  STR_STUN_ROD_UFOPEDIA: \"Цей пристрій призначений для ураження противника електричним розрядом при безпосередньому контакті. При цьому противник залишається живим.\"\n  STR_MIND_PROBE_UFOPEDIA: \"Ментальний зонд - це пристрій зв'язку прибульців, який використовується для отримання інформації безпосередньо від хвиль мозку. Бійці X-Com можуть використовувати цей пристрій у бою, щоб візуалізувати характеристики прибульця. Клацніть на ментальний зонд та опцію \\\"Використати зонд\\\". Потім натисніть курсор на прибульця.\"\n  STR_PLASMA_PISTOL_UFOPEDIA: \"Плазмовий пістолет - це смертоносна зброя прибульців, яка базується на принципі прискорення частинок антигравітаційним полем.\"\n  STR_PLASMA_RIFLE_UFOPEDIA: \"Руйнівна плазмова зброя прибульців, яка базується на принципі прискорення частинок антигравітаційним полем.\"\n  STR_HEAVY_PLASMA_UFOPEDIA: \"Це смертоносна плазмова зброя прибульців неймовірної руйнівної сили. В її основі лежить принцип прискорення частинок антигравітаційним полем.\"\n  STR_BLASTER_LAUNCHER_UFOPEDIA: \"Ця пускова установка прибульців стріляє потужними керованими бластерними ракетами. Траєкторія польоту задається безпосередньо перед пострілом. Після задання траєкторії натисніть спеціальну кнопку пуску ракети.\"\n  STR_SMALL_LAUNCHER_UFOPEDIA: \"Невелика пускова установка, яка стріляє паралізуючими бомбами. Надзвичайно корисна для захоплення живих інопланетян.\"\n  STR_ALIEN_GRENADE_UFOPEDIA: \"Граната прибульців працює таким самим чином, як і земна граната, але має більшу потужність.\"\n  STR_SMALL_SCOUT: \"Малий розвідник\"\n  STR_MEDIUM_SCOUT: \"Середній розвідник\"\n  STR_LARGE_SCOUT: \"Великий розвідник\"\n  STR_HARVESTER: \"Жнець\"\n  STR_ABDUCTOR: \"Викрадач\"\n  STR_TERROR_SHIP: \"Корабель терору\"\n  STR_BATTLESHIP: \"Лінкор\"\n  STR_SUPPLY_SHIP: \"Корабель постачання\"\n  STR_RATING: \"РЕЙТИНГ> {0}\"\n  STR_RATING_TERRIBLE: \"ЖАХЛИВО!\"\n  STR_RATING_POOR: \"ПОГАНО!\"\n  STR_RATING_OK: \"НОРМАЛЬНО\"\n  STR_RATING_GOOD: \"ДОБРЕ!\"\n  STR_RATING_EXCELLENT: \"ПРЕКРАСНО!\"\n  STR_SCORE: \"РАХУНОК\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"ЩОМІСЯЧНИЙ ЗВІТ ПРОЕКТУ X-COM\"\n  STR_MONTH: \"Місяць> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"Рада держав, що фінансують проект, в загальному задоволена Вашими діями.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"Рада держав, що фінансують проект, дуже задоволена Вашими діями. Продовжуйте в тому ж дусі.\"\n  STR_COUNCIL_IS_DISSATISFIED: \"Рада держав, що фінансують проект, незадоволена Вашими діями. Ви мусите збільшити ефективність протидії інопланетній загрозі, або проект буде згорнутий.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"Ви не досягли успіху в боротьбі з вторгненням прибульців і рада держав, що фінансують проект, з прикрістю прийняла рішення про закриття проекту. Відтепер кожна держава буде вирішувати цю проблему по-своєму. Ми можемо тільки надіятись, що прийдемо до якоїсь угоди з явно ворожими силами, і що суспільство прийме умови, запропоновані прибульцями.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} особливо задоволена Вашими успіхами в боротьбі з загрозою на її території та погодилась збільшити фінансування.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} особливо задоволені вашими успіхами в боротьбі з вторгненням на їхніх територіях та погодились збільшити фінансування.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} та {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} незадоволена заходами, вжитими вами для протидії активності прибульців на її території, і вирішила урізати фінансування.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} незадоволені заходами, вжитими вами для протидії активності прибульців на їхніх територіях, і вирішили урізати фінансування.\"\n  STR_KNOTS: \"{0} вузлів\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} підписала секретний пакт з невідомими інопланетними силами та вийшла з проекту.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} підписали секретний пакт з невідомими інопланетними силами та вийшли з проекту.\"\n  STR_MONTHLY_RATING: \"Рейтинг за місяць> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Зміна фінансування> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"Рада з фінансування не задоволена Вашим фінансовим станом. Ви мусите скоротити борги до 1 мільйона доларів, або проект буде закритий.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"ГІПЕРХВИЛЬОВІ ПЕРЕДАЧІ ДЕКОДОВАНО\"\n  STR_CRAFT_TYPE: \"ТИП КОРАБЛЯ\"\n  STR_RACE: \"РАСА\"\n  STR_MISSION: \"ЗАВДАННЯ\"\n  STR_ZONE: \"ЗОНА\"\n  STR_ALLOCATE_RESEARCH: \"Почати дослідження\"\n  STR_ALLOCATE_MANUFACTURE: \"Почати виробництво\"\n  STR_NEW_YORK: \"Нью-Йорк\"\n  STR_WASHINGTON: \"Вашингтон\"\n  STR_LOS_ANGELES: \"Лос-Анджелес\"\n  STR_MONTREAL: \"Монреаль\"\n  STR_HAVANA: \"Гавана\"\n  STR_MEXICO_CITY: \"Мехіко\"\n  STR_CHICAGO: \"Чикаго\"\n  STR_VANCOUVER: \"Ванкувер\"\n  STR_DALLAS: \"Даллас\"\n  STR_BRASILIA: \"Бразіліа\"\n  STR_BOGOTA: \"Богота\"\n  STR_BUENOS_AIRES: \"Буенос-Айрес\"\n  STR_SANTIAGO: \"Сантьяго\"\n  STR_RIO_DE_JANEIRO: \"Ріо-де-Жанейро\"\n  STR_LIMA: \"Ліма\"\n  STR_CARACAS: \"Каракас\"\n  STR_LONDON: \"Лондон\"\n  STR_PARIS: \"Париж\"\n  STR_BERLIN: \"Берлін\"\n  STR_MOSCOW: \"Москва\"\n  STR_ROME: \"Рим\"\n  STR_MADRID: \"Мадрид\"\n  STR_BUDAPEST: \"Будапешт\"\n  STR_LAGOS: \"Лагос\"\n  STR_CAIRO: \"Каїр\"\n  STR_CASABLANCA: \"Касабланка\"\n  STR_PRETORIA: \"Преторія\"\n  STR_NAIROBI: \"Найробі\"\n  STR_CAPE_TOWN: \"Кейптаун\"\n  STR_KINSHASA: \"Кіншаса\"\n  STR_ANKARA: \"Анкара\"\n  STR_DELHI: \"Делі\"\n  STR_KARACHI: \"Карачі\"\n  STR_BAGHDAD: \"Багдад\"\n  STR_TEHRAN: \"Тегеран\"\n  STR_BOMBAY: \"Бомбей\"\n  STR_CALCUTTA: \"Калькутта\"\n  STR_TOKYO: \"Токіо\"\n  STR_BEIJING: \"Пекін\"\n  STR_BANGKOK: \"Бангкок\"\n  STR_MANILA: \"Маніла\"\n  STR_SEOUL: \"Сеул\"\n  STR_SINGAPORE: \"Сінгапур\"\n  STR_JAKARTA: \"Джакарта\"\n  STR_SHANGHAI: \"Шанхай\"\n  STR_HONG_KONG: \"Гонконг\"\n  STR_NOVOSIBIRSK: \"Новосибірськ\"\n  STR_CANBERRA: \"Канберра\"\n  STR_WELLINGTON: \"Веллінгтон\"\n  STR_MELBOURNE: \"Мельбурн\"\n  STR_PERTH: \"Перт\"\n  STR_PSI_TRAINING: \"Псі Тренування\"\n  STR_PSIONIC_TRAINING: \"ПСІОНІЧНЕ ТРЕНУВАННЯ\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Вільних місць в псі-лабораторії> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"Псіонічна{NEWLINE}сила\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"Псі-вміння{NEWLINE}/Поліпшення\"\n  STR_PSI_AMP: \"Псі-підсилювач\"\n  STR_IN_TRAINING: \"На{NEWLINE}Тренув.?\"\n  STR_TARGETTED_BY: \"ЦІЛЬ ДЛЯ:\"\n  STR_WEAPONS_CREW_HWPS: \"ЗБРОЯ/{NEWLINE}ЕКІПАЖ/ВБП\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"закінчується пальне,{NEWLINE}повертаюсь на базу\"\n  STR_SOLDIER_LIST: \"Список солдатів\"\n  STR_RANK_: \"ЗВАННЯ> {ALT}{0}\"\n  STR_MISSIONS: \"МІСІЙ> {ALT}{0}\"\n  STR_KILLS: \"ВБИВСТВ> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"ЛІКУВАННЯ РАН> {ALT}{0}\"\n  STR_TIME_UNITS: \"ОДИНИЦІ ДІЙ\"\n  STR_STAMINA: \"ВИТРИВАЛІСТЬ\"\n  STR_HEALTH: \"ЗДОРОВ'Я\"\n  STR_BRAVERY: \"ХОРОБРІСТЬ\"\n  STR_REACTIONS: \"РЕАКЦІЯ\"\n  STR_FIRING_ACCURACY: \"ТОЧНІСТЬ СТРІЛЬБИ\"\n  STR_THROWING_ACCURACY: \"ТОЧНІСТЬ КИДАННЯ\"\n  STR_STRENGTH: \"СИЛА\"\n  STR_PSIONIC_STRENGTH: \"ПСІОНІЧНА СИЛА\"\n  STR_PSIONIC_SKILL: \"ПСІОНІЧНЕ ВМІННЯ\"\n  STR_NEW_RANK: \"НОВЕ ЗВАННЯ\"\n  STR_PROMOTIONS: \"Присвоєні звання:\"\n  STR_SOLDIERS_UC: \"СОЛДАТИ\"\n  STR_TANK_CANNON_UFOPEDIA: \"Автоматизовані важкі бойові платформи призначені для доповнення команди X-Com. Поєднання високої вогневої потужності та міцної броні робить ці одиниці цінними для вогневих подій на відкритих місцевостях. Переконайтеся, що на ваших складах є достатня кількість гарматних снарядів для переозболєння танків. Вони автоматично озброюються, коли ви призначаєте їх до загону.\"\n  STR_TANK_ROCKET_LAUNCHER_UFOPEDIA: \"Ця автоматизована важка бойова платформа озброєна потужними ракетами. Вона може знищити будь-якого ворога. Слідкуйте за наявністю ракет для ВБП у сховищах.\"\n  STR_TANK_LASER_CANNON_UFOPEDIA: \"Бойовий лазер - корисне вдосконалення для ВБП. Він завдає значних пошкоджень, не вимагаючи боєприпасів.\"\n  STR_HOVERTANK_PLASMA_UFOPEDIA: \"Інопланетна технологія вдихнула в ВБП нове життя. Здатність літати та сила плазмової зброї утворюють смертоносну комбінацію.\"\n  STR_HOVERTANK_LAUNCHER_UFOPEDIA: \"Цей ширяючий танк обладнаний бластерною пусковою установкою величезної потужності. Використовуйте його з великою обережністю. Для озброєння цієї ВБП необхідно виготовляти бластерні ракети. Бластерна ракета - це високоточна керована зброя, яка дозволяє перед пострілом задавати траєкторію руху снаряду.\"\n  STR_HEAVY_PLASMA_CLIP_UFOPEDIA: \"Цей компактний об'єкт - джерело енергії для важкої плазми. Містить невелику кількість елеріуму.\"\n  STR_PLASMA_RIFLE_CLIP_UFOPEDIA: \"Цей маленький об'єкт є джерелом енергії для плазмової гвинтівки - зброї прибульців середньої потужності. Містить невелику кількість елеріуму.\"\n  STR_PLASMA_PISTOL_CLIP_UFOPEDIA: \"Джерело енергії для невеликого плазмового пістолета. Містить елеріум - джерело енергії всіх інопланетних технологій.\"\n  STR_STUN_BOMB_UFOPEDIA: \"Паралізуюча бомба використовується для захоплення живих людей, але може також застосовуватись проти більшості рас прибульців. Вистрілюється з паралізуючої установки.\"\n  STR_ALIEN_RESEARCH_UFOPEDIA: \"Метою дослідницьких місій прибульців є збір даних про Землю та її жителів. Використовуються переважно малі кораблі, які іноді сідають в пустельних районах. Цей тип активності прибульців становить найменшу небезпеку, із невеликим впливом на занепокоєння уряду та суспільства.\"\n  STR_ALIEN_HARVEST_UFOPEDIA: \"Прибульці широко використовують земну фауну в своїх цілях. Тварин таємно викрадають та повертають після видалення різних органів. Здебільшого випадки каліцтва худоби співпадають з випадками спостереження НЛО. Цей тип діяльності прибульців викликає найбільше занепокоєння в урядів і тривогу серед населення. Найчастіше така активність проявляється в сільськогосподарських регіонах. Теорія \\\"збору врожаю\\\" передбачає, що прибульці колись \\\"засіяли\\\" планету зразками своєї флори і фауни, а тепер повернулись, щоб зібрати \\\"врожай\\\".\"\n  STR_ALIEN_ABDUCTION_UFOPEDIA: \"Найбільш підступний вид діяльності прибульців. Випадки викрадення людей прибульцями широко відомі, незважаючи на спроби прибульців стирати спогади з пам'яті жертв. Викрадені розказують про проведені над ними фізіологічні досліди, включаючи запліднення зародками інопланетних організмів і різні генетичні експерименти. Переслідувана прибульцями ціль, ймовірно, має відношення до мутацій і маніпулювання їх власним генетичним матеріалом. Ці інциденти викликають велике занепокоєння і відбуваються в населених місцях або містах.\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"В земні уряди можуть проникнути агенти прибульців, які ззовні виглядають як люди. Це може призвести до встановлення звязків між прибульцями та урядом на найвищому рівні. Ознакою підготовки такої операції може бути висока активність НЛО поблизу великих міст. Прибульці намагатимуться підписати договір з урядом, пропонуючи передачу своїх технологій в обмін на можливість безперешкодно діяти на даній території. Цей тип місій являє собою найбільшу загрозу для X-COM. Якщо уряд погодиться - фінансування з його сторони буде припинене.\"\n  STR_ALIEN_BASE_UFOPEDIA: \"Прибульці будуть споруджувати таємні підземні бази у віддалених районах. Після періоду розвідувальних польотів буде відзначатись висока активність НЛО в місці будівництва бази. На базах розміщуються експерииментальні лабораторії для вивчення людей, а також засоби для подальшої діяльності прибульців в регіоні. Присутність бази буде супроводжуватись великою кількістю повідомлень про дії прибульців при відносно малій кількості випадків спостереження НЛО. Щоб виявити базу, корабель X-COM має патрулювати область протягом кількох годин.\"\n  STR_ALIEN_TERROR_UFOPEDIA: \"Коли прибульці тероризують місто, вони використовують спеціальні загони вражаючої сили. Через наявність беспосередньої небезпеки для цивільних, уряд змушений евакуювати цілі райони. Основна ціль цієї діяльності - викликати величезну паніку серед людей, через що уряди можуть чинити суттєвий тиск на проект X-COM.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"У випадку особливо успішних дій перехоплювачів X-COM, прибульці будуть вживати заходів у відповідь. Результатом може стати напад на базу X-COM. Однак прибульцям потрібно спершу виявити базу. Тому ризик можна суттєво знизити, якщо не підпускати НЛО-розвідники до бази.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"Після того як база прибульців побудована, її постачання здійснюється на регулярній основі спеціальним вантажним кораблем. Виявивши такий корабель на землі, можна бути певним, що неподалік є база прибульців.\"\n  STR_SMALL_SCOUT_UFOPEDIA: \"Цей крихітний корабель використовується для розвідки чи досліджень. Його польоти зазвичай передують більшим кораблям на початку місій прибульців.\"\n  STR_MEDIUM_SCOUT_UFOPEDIA: \"Середній за розміром розвідувальний корабель, який не становить великої небезпеки. Зазвичай з'являється перед більшими кораблями під час місій прибульців.\"\n  STR_LARGE_SCOUT_UFOPEDIA: \"Найбільший розвідувальний корабель прибульців, який є кораблем загального призначення і використовується у всіх типах місій.\"\n  STR_HARVESTER_UFOPEDIA: \"Жнець має люк в нижній частині корпуса і оснащений підйомним механізмом для худоби та інших тварин. Необхідний біо-матеріал виймається з використанням лазерних скальпелів, після чого туша скидається на землю. Також наявні контейнери для зберігання здобутих органів.\"\n  STR_ABDUCTOR_UFOPEDIA: \"Цей корабель обладнано кімнатою для проведення допитів і жахливих експериментів над людьми. Зазвичай жертва телепатично паралізується, але залишається при свідомості на операційному столі.\"\n  STR_TERROR_SHIP_UFOPEDIA: \"Корабель терору має відсіки для перевезення великих істот або техніки, які є частиною загонів залякування. Він використовується для доставки інопланетних терористів у населені райони.\"\n  STR_BATTLESHIP_UFOPEDIA: \"Лінкор - найбільший і найпотужніший корабель прибульців. Він є основним бойовим кораблем в будь-якій місії, несе на борту потужну зброю та численний екіпаж.\"\n  STR_SUPPLY_SHIP_UFOPEDIA: \"Корабель постачання використовується при закладанні нових баз і постачанні існуючих. Перевозить контейнери з їжею та кнонувальні капсули.\"\n  STR_DISMANTLE: \"Демонтувати\"\n  STR_FACILITY_IN_USE: \"МОДУЛЬ ВИКОРИСТОВУЄТЬСЯ\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"НЕ МОЖУ ДЕМОНТУВАТИ МОДУЛЬ!{SMALLLINE}Всі модулі мають бути з'єднані з вхідним ліфтом.\"\n  STR_TRANSFER_ITEMS_TO: \"Переслати на базу {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"НЕМАЄ ТЮРМИ ДЛЯ ПРИБУЛЬЦІВ ДЛЯ ПЕРЕДАЧІ!{SMALLLINE}Для утримання живих прибульців необхідний спеціальний модуль.\"\n  STR_AMOUNT_AT_DESTINATION: \"НА МІСЦІ{NEWLINE}ПРИЗНАЧЕННЯ\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"Прибулець загинув, оскільки немає модуля для його утримання.\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"НЕМАЄ ВІЛЬНОГО МІСЦЯ!{SMALLLINE}База призначення не має достатньої кількості місця в житлових модулях для екіпажу, призначеного на корабель.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"НЕ ДОСТАТНЬО МІСЦЯ НА СКЛАДАХ!{SMALLLINE}Цільова база немає достатньо вільного місця на складах для спорядження приписаного до корабля.\"\n  STR_ITEMS_ARRIVING: \"Прибуття\"\n  STR_DESTINATION_UC: \"ПУНКТ ПРИЗНАЧЕННЯ\"\n  STR_PISTOL: \"Пістолет\"\n  STR_PISTOL_CLIP: \"Магазин для пістолета\"\n  STR_RIFLE: \"Гвинтівка\"\n  STR_RIFLE_CLIP: \"Магазин для гвинтівки\"\n  STR_HEAVY_CANNON: \"Важка гармата \"\n  STR_HC_AP_AMMO: \"ВГ-ББ магазин\"\n  STR_HC_HE_AMMO: \"ВГ-В магазин\"\n  STR_HC_I_AMMO: \"ВГ-З магазин\"\n  STR_AUTO_CANNON: \"Авто-гармата\"\n  STR_AC_AP_AMMO: \"АГ-ББ магазин\"\n  STR_AC_HE_AMMO: \"АГ-В магазин\"\n  STR_AC_I_AMMO: \"АГ-З магазин\"\n  STR_ROCKET_LAUNCHER: \"Ракетна установка\"\n  STR_SMALL_ROCKET: \"Легка ракета\"\n  STR_LARGE_ROCKET: \"Важка ракета\"\n  STR_INCENDIARY_ROCKET: \"Запалювальна ракета\"\n  STR_GRENADE: \"Граната\"\n  STR_SMOKE_GRENADE: \"Димова граната\"\n  STR_PROXIMITY_GRENADE: \"Сенсорна граната\"\n  STR_HIGH_EXPLOSIVE: \"Вибухівка\"\n  STR_STUN_ROD: \"Електрошоковий кийок\"\n  STR_HEAVY_PLASMA: \"Важка плазма\"\n  STR_HEAVY_PLASMA_CLIP: \"Магазин для важ. плазми\"\n  STR_PLASMA_RIFLE: \"Плазмова гвинтівка\"\n  STR_PLASMA_RIFLE_CLIP: \"Магазин для плаз. гвинтівки\"\n  STR_PLASMA_PISTOL: \"Плазмовий пістолет\"\n  STR_PLASMA_PISTOL_CLIP: \"Магазин для плаз. пістолета\"\n  STR_BLASTER_LAUNCHER: \"Бластерна установка\"\n  STR_BLASTER_BOMB: \"Бластерна ракета\"\n  STR_SMALL_LAUNCHER: \"Паралізуюча установка\"\n  STR_STUN_BOMB: \"Паралізуюча бомба\"\n  STR_ALIEN_GRENADE: \"Граната прибульців\"\n  STR_ELERIUM_115: \"Елеріум-115\"\n  STR_MIND_PROBE: \"Ментальний зонд\"\n  STR_SECTOID_CORPSE: \"Труп сектоїда\"\n  STR_SNAKEMAN_CORPSE: \"Труп людинозмії\"\n  STR_ETHEREAL_CORPSE: \"Труп ефіріала\"\n  STR_MUTON_CORPSE: \"Труп мутона\"\n  STR_FLOATER_CORPSE: \"Труп летуна\"\n  STR_CELATID_CORPSE: \"Труп целатида\"\n  STR_SILACOID_CORPSE: \"Труп силакоїда\"\n  STR_CHRYSSALID_CORPSE: \"Труп крисаліда\"\n  STR_REAPER_CORPSE: \"Труп рипера\"\n  STR_SECTOPOD_CORPSE: \"Обломки сектопода\"\n  STR_CYBERDISC_CORPSE: \"Обломки кібердиска\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"Недостатньо набоїв для озброєння ВБП{SMALLLINE}Кожній ВБП необхідно {0} {1}.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Недостатньо спорядження для екіпірування загону\"\n  STR_MARS_CYDONIA_LANDING: \"Марс: Десантування в Кідонії\"\n  STR_MARS_CYDONIA_LANDING_BRIEFING: \"Ваш корабель \\\"Месник\\\" приземлився на поверхню Марсу в районі Кідонії. За нашою інформацією, в одній із пірамідальних споруд знаходиться ліфт, що веде в підземний комплекс. Зберіть загін в ліфті (зелена область) і натисніть кнопку \\\"Перервати завдання\\\" для переходу на наступний рівень.\"\n  STR_MARS_THE_FINAL_ASSAULT: \"Марс: Фінальна Битва\"\n  STR_MARS_THE_FINAL_ASSAULT_BRIEFING: \"Ліфт піраміди доправив ваших змучених битвою солдатів глибоко під поверхню планети. Вони прибули в серце великого комплексу лабіринтів та камер. Десь там схований інопланетний Мозок. Він мусить бути знищений, щоб врятувати Землю від навали інопланетян.{NEWLINE}{NEWLINE}Удачі!\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Вам потрібно вивчити{NEWLINE}{0}{NEWLINE}для виготовлення{NEWLINE}{1}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"Прибульці зруйнували незахищену базу {0}\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"Агенти X-COM виявили базу прибульців в {0}\"\n  STR_STANDOFF: \"НА БЕЗПЕЧНІЙ ВІДСТАНІ\"\n  STR_CAUTIOUS_ATTACK: \"ОБЕРЕЖНА АТАКА\"\n  STR_STANDARD_ATTACK: \"ЗВИЧАЙНА АТАКА\"\n  STR_AGGRESSIVE_ATTACK: \"АГРЕСИВНА АТАКА\"\n  STR_DISENGAGING: \"ВІДДАЛЕННЯ\"\n  STR_UFO_HIT: \"НЛО УРАЖЕНО!\"\n  STR_UFO_CRASH_LANDS: \"НЛО ПІДБИТО!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Переслідувати на безпечній дистанції\"\n  STR_UFO_RETURN_FIRE: \"НЛО СТРІЛЯЄ!\"\n  STR_INTERCEPTOR_DAMAGED: \">>> ПЕРЕХОПЛЮВАЧ ПОШКОДЖЕНО <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> ПЕРЕХОПЛЮВАЧ ЗНИЩЕНО <<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"НЛО ВІДІРВАВСЯ ВІД ПЕРЕХОПЛЮВАЧА!\"\n  STR_ALIENS_TERRORISE: \"ПРИБУЛЬЦІ ТЕРОРИЗУЮТЬ\"\n  STR_LONG_RANGE_DETECTION: \"Дальнє виявлення\"\n  STR_STORES_UC: \"СКЛАДИ\"\n  STR_DIFFICULTY_LEVEL: \"Рівень складності\"\n  STR_INTERCEPT: \"ПЕРЕХОПЛЕННЯ\"\n  STR_BASES: \"БАЗИ\"\n  STR_GRAPHS: \"ГРАФІКИ\"\n  STR_UFOPAEDIA_UC: \"НЛОПЕДІЯ\"\n  STR_OPTIONS_UC: \"НАЛАШТУВАННЯ\"\n  STR_FUNDING_UC: \"ФІНАНСИ\"\n  STR_5_SECONDS: \"5 сек\"\n  STR_1_MINUTE: \"1 хв\"\n  STR_5_MINUTES: \"5 хв\"\n  STR_30_MINUTES: \"30 хв\"\n  STR_1_HOUR: \"1 год\"\n  STR_1_DAY: \"1 день\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"Виконання завдань X-COM\"\n  STR_ENTER_NAME: \"Введіть ім'я\"\n  STR_PERFORMANCE_RATING: \"Оцінка виконання\"\n  STR_VICTORY_DATE: \"День Перемоги\"\n  STR_ELECTRO_FLARE: \"Освітлювач\"\n  STR_ELECTRO_FLARE_UFOPEDIA: \"Цей компактний пристрій випромінює яскраве світло, якщо його кинути куди-небудь. Він корисний під час виконання завдань в темний час доби.\"\n  STR_MONTHLY_COSTS: \"Місячні витрати\"\n  STR_CRAFT_RENTAL: \"Оренда кораблів\"\n  STR_SALARIES: \"Зарплати\"\n  STR_BASE_MAINTENANCE: \"Обслуговування бази\"\n  STR_COST_PER_UNIT: \"Ціна одиниці\"\n  STR_QUANTITY: \"Кільк.\"\n  STR_TOTAL: \"Всього\"\n  STR_IN_PSIONIC_TRAINING: \"Тренуються в Псі-лабораторії\"\n  STR_BLASTER_BOMB_UFOPEDIA: \"Потужна ракета, оснащена програмованою системою управління. Призначена для стрільби з бластерної пускової установки.\"\n  STR_FRONT_ARMOR: \"Передня броня\"\n  STR_LEFT_ARMOR: \"Ліва броня\"\n  STR_RIGHT_ARMOR: \"Права броня\"\n  STR_REAR_ARMOR: \"Задня броня\"\n  STR_UNDER_ARMOR: \"Нижня броня\"\n  STR_ROUNDS: \"Боєзапас\"\n  STR_UNIT: \"ОДИНИЦЯ> {0}\"\n  STR_ENERGY: \"ЕНЕРГІЯ\"\n  STR_MORALE: \"МОРАЛЬ\"\n  STR_ARMOR_: \"БРОНЯ> {0}\"\n  STR_FRONT_ARMOR_UC: \"ПЕРЕДНЯ БРОНЯ\"\n  STR_LEFT_ARMOR_UC: \"ЛІВА БРОНЯ\"\n  STR_RIGHT_ARMOR_UC: \"ПРАВА БРОНЯ\"\n  STR_REAR_ARMOR_UC: \"ЗАДНЯ БРОНЯ\"\n  STR_SKILLS: \"ВМІННЯ> {0}\"\n  STR_LEVEL: \"РІВЕНЬ> {0}\"\n  STR_HEAD: \"ГОЛОВА\"\n  STR_TORSO: \"ТУЛУБ\"\n  STR_RIGHT_ARM: \"ПРАВА РУКА\"\n  STR_LEFT_ARM: \"ЛІВА РУКА\"\n  STR_RIGHT_LEG: \"ПРАВА НОГА\"\n  STR_LEFT_LEG: \"ЛІВА НОГА\"\n  STR_PAIN_KILLER: \"ЗНЕБОЛЮЮЧЕ\"\n  STR_STIMULANT: \"СТИМУЛЯТОР\"\n  STR_HEAL: \"ЛІКУВАННЯ\"\n  STR_TIME_UNITS_SHORT: \"ОД>{ALT}{0}\"\n  STR_WEIGHT: \"Вага>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"Реакц>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"П.Вмінн>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"Ф.Сил>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Артефакт прибульців\"\n  STR_AMMO_ROUNDS_LEFT: \"БОЄПРИПАСИ:{NEWLINE}ЗАРЯДІВ{NEWLINE}ЗАЛИШИЛОСЬ={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Знеб>{ALT}{0}{ALT}{NEWLINE}Стим>{ALT}{1}{ALT}{NEWLINE}Ліку>{ALT}{2}\"\n  STR_THROW: \"Кинути\"\n  STR_AUTO_SHOT: \"Черга\"\n  STR_SNAP_SHOT: \"Навмання\"\n  STR_AIMED_SHOT: \"Прицільно\"\n  STR_STUN: \"Паралізувати\"\n  STR_PRIME_GRENADE: \"Активувати\"\n  STR_USE_SCANNER: \"Використати\"\n  STR_USE_MEDI_KIT: \"Використати\"\n  STR_LAUNCH_MISSILE: \"Пуск ракети\"\n  STR_ACCURACY_SHORT: \"Точ>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Не достатньо дій!\"\n  STR_NOT_ENOUGH_ENERGY: \"Не достатньо енергії!\"\n  STR_NO_ROUNDS_LEFT: \"Немає боєприпасів!\"\n  STR_NO_AMMUNITION_LOADED: \"Зброя не заряджена!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Боєприпаси від іншої зброї!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"Зброя вже заряджена!\"\n  STR_NO_LINE_OF_FIRE: \"Немає лінії вогню!\"\n  STR_GRENADE_IS_ACTIVATED: \"Граната активована!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Граната деактивована!\"\n  STR_THERE_IS_NO_ONE_THERE: \"Там нікого немає!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Не досліджений артефакт прибульців!\"\n  STR_OUT_OF_RANGE: \"Надто далеко!\"\n  STR_UNABLE_TO_THROW_HERE: \"Не можу кинути сюди!\"\n  STR_SET_TIMER: \"Виставити Таймер\"\n  STR_HIDDEN_MOVEMENT: \"ПРИХОВАНІ ПЕРЕМІЩЕННЯ\"\n  STR_TURN: \"ХІД> {0}\"\n  STR_SIDE: \"СТОРОНА> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Натисніть будь-яку кнопку...\"\n  STR_MIND_CONTROL: \"Контроль розуму\"\n  STR_PANIC_UNIT: \"Паніка\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Атака на мораль вдалась\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Успішно взято під контроль\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}оскаженів\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}оскаженіла\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}запанікував\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}запанікувала\"\n  STR_XCOM: \"X-COM\"\n  STR_ALIENS: \"Прибульці\"\n  STR_RIGHT_HAND: \"ПРАВА РУКА\"\n  STR_LEFT_HAND: \"ЛІВА РУКА\"\n  STR_RIGHT_SHOULDER: \"ПРАВЕ ПЛЕЧЕ\"\n  STR_LEFT_SHOULDER: \"ЛІВЕ ПЛЕЧЕ\"\n  STR_BACK_PACK: \"РАНЕЦЬ\"\n  STR_BELT: \"ПОЯС\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}під контролем прибульців\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}під контролем прибульців\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE} втратив свідомість\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}втратила свідомість\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}помер від смертельного поранення\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}померла від смертельної рани\"\n  STR_USE_MIND_PROBE: \"Використати\"\n  STR_FATAL_WOUNDS: \"СМЕРТЕЛЬНІ РАНИ\"\n  STR_UNDER_ARMOR_UC: \"НИЖНЯ БРОНЯ\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Одиниці дій зекономлено для пострілу навмання\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Одиниці дій зекономлено для стрільби чергою\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Одиниці дій зекономлено для прицільного пострілу\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"ОД зарезервовано для вставання на коліна\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"ОД зарезервовано для вставання на коліна і стрільби\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} боєць в кораблі X-Com\"\n    few: \"{N} бійці в кораблі X-Com\"\n    many: \"{N} бійців в кораблі X-Com\"\n    other: \"{N} бійців в кораблі X-Com\"\n  STR_UNITS_OUTSIDE:\n    one: \"{N} боєць поза Зоною Виходу\"\n    few: \"{N} бійці поза Зоною Виходу\"\n    many: \"{N} бійців поза Зоною Виходу\"\n    other: \"{N} бійців поза Зоною Виходу\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} боєць на вході\"\n    few: \"{N} бійці на вході\"\n    many: \"{N} бійців на вході\"\n    other: \"{N} бійців на вході\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} боєць на виході\"\n    few: \"{N} бійці на виході\"\n    many: \"{N} бійців на виході\"\n    other: \"{N} бійців на виході\"\n  STR_ABORT_MISSION_QUESTION: \"Перервати місію?\"\n  STR_CORPSE: \"Труп\"\n  STR_UNLOAD_CRAFT: \"Розрядити\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}був убитий\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}була вбита\"\n  STR_HIT_MELEE: \"Вдарити\"\n  STR_GROUND: \"НА ЗЕМЛІ\"\n  STR_LIVING_QUARTERS_PLURAL: \"Житлові модулі\"\n  STR_LIST_ITEM: \"ПРЕДМЕТ\"\n  STR_PERSONAL_ARMOR_UFOPEDIA: \"З використанням щойно вивчених сплавів прибульців, ця нова броня дає нашим бійцям шанс у боротьбі проти інопланетної загрози.\"\n  STR_POWER_SUIT_UFOPEDIA: \"Новий потужний захист для солдат, ця броня живиться від джерела енергії на основі елеріуму. Значно посилює швидкість і силу солдата. Ця броня надає відмінний захист для бійців.\"\n  STR_FLYING_SUIT_UFOPEDIA: \"Вдосконалена версія силового скафандру, включає анти-гравітаційну технологію прибульців для забезпечення повної свободи руху на полі бою.\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"Всі прибульці загинули при падінні,{NEWLINE}розпочато авто-захоплення НЛО\"\n  STR_RESET: \"Скинути\"\n  STR_MEMORIAL: \"Меморіал\"\n  STR_DATE_UC: \"ДАТА\"\n  STR_SOLDIERS_RECRUITED_UC: \"СОЛДАТІВ НАЙНЯТО>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"СОЛДАТІВ ВТРАЧЕНО>{ALT}{0}\"\n  MAP_CULTA: \"Ферма\"\n  MAP_FOREST: \"Ліс\"\n  MAP_JUNGLE: \"Джунглі\"\n  MAP_MOUNT: \"Гора\"\n  MAP_DESERT: \"Пустеля\"\n  MAP_POLAR: \"Полярний\"\n  MAP_URBAN: \"Місто\"\n  MAP_UBASE: \"База Прибульців \"\n  MAP_XBASE: \"База X-Com\"\n  MAP_MARS: \"Марс\"\n  STR_MIXED: \"Змішаний\"\n  STR_REMOVE_SELECTED: \"Видалити обране\"\n  STR_LIVE_ALIENS: \"Живі{NEWLINE}особини\"\n  STR_DEAD_ALIENS: \"Мертві{NEWLINE}особини\"\n  STR_UNDER_INTERROGATION: \"В процесі{NEWLINE}допиту\"\n  STR_CONTAINMENT_EXCEEDED: \"ПЕРЕВИЩЕНО ЛІМІТ ТЮРМИ ДЛЯ ПРИБУЛЬЦІВ!{SMALLLINE}Недостатньо місця в тюрмі на базі {0}. Ви мусите видалити зайвих прибульців з тюрми (вони від цього загинуть).\"\n  STR_MANAGE_CONTAINMENT: \"Управління Тюрмою для Прибульців\"\n  STR_STORAGE_EXCEEDED: \"МІСЦЕ НА СКЛАДАХ ВИЧЕРПАЛОСЬ!{SMALLLINE}Недостатньо місця на складах бази {0}. Ви мусите продати зайві речі.\"\n  STR_GO_TO_BASE: \"Перейти до бази\"\n  STR_MELEE_ACCURACY: \"ТОЧНІСТЬ БЛИЖНЬОГО БОЮ\"\n  STR_SELL_PRODUCTION: \"ПРОДАЖ\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Обидві руки мають бути вільні!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Не достатньо предметів для копіювання шаблону!\"\n  STR_UNLOAD_WEAPON: \"Розрядити зброю\"\n  STR_ALL_ITEMS: \"Усі предмети\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"НЕДОСТАТНЬО МІСЦЯ НА БОРТУ!{SMALLLINE}Ви можете взяти не більше {N} предметів спорядження на цей транспорт.\"\n    few: \"НЕДОСТАТНЬО МІСЦЯ НА БОРТУ!{SMALLLINE}Ви можете взяти не більше {N} предметів спорядження на цей транспорт.\"\n    many: \"НЕДОСТАТНЬО МІСЦЯ НА БОРТУ!{SMALLLINE}Ви можете взяти не більше {N} предметів спорядження на цей транспорт.\"\n    other: \"НЕДОСТАТНЬО МІСЦЯ НА БОРТУ!{SMALLLINE}Ви можете взяти не більше {N} предметів спорядження на цей транспорт.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}ЦЕНТР КЕРУВАННЯ ЗНИЩЕНО{NEWLINE}Прямуйте до входу та тікайте.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"Спорядження X-Com не можуть бути збудовані під водою\"\n  STR_LEVEL_SHORT: \"{0}\"\n  STR_PERSONNEL: \"Персонал\"\n  STR_CRAFT_ARMAMENT: \"Літаки та Озброєння\"\n  STR_COMPONENTS: \"Складові\"\n  STR_SOLDIERS_RECRUITED: \"Солдатів найнято\"\n  STR_SOLDIERS_LOST: \"Солдатів загинуло\"\n  STR_TOTAL_UFOS: \"НЛО виявлено\"\n  STR_TOTAL_ALIEN_BASES: \"Баз прибульців викрито\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"ПСС\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"ПСН\"\n  FEMALE_CIVILIAN: \"Цивільний, жінка\"\n  MALE_CIVILIAN: \"Цивільний, чоловік\"\n  CYBERDISC_WEAPON: \"Зброя кібердиска\"\n  REAPER_WEAPON: \"Зброя рипера\"\n  CHRYSSALID_WEAPON: \"Зброя крисаліда\"\n  CELATID_WEAPON: \"Зброя целатида\"\n  SILACOID_WEAPON: \"Зброя силакоїда\"\n  SECTOPOD_WEAPON: \"Зброя сектопода\"\n  ZOMBIE_WEAPON: \"Зброя зомбі\"\n  ALIEN_PSI_WEAPON: \"Псі-зброя прибульців\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/zh-CN.yml",
    "content": "zh-CN:\n  STR_AVENGER_UFOPEDIA: \"用于运输与战斗的太空飞船。复制异形科技的终极产物。\"\n  STR_INTERCEPTOR_UFOPEDIA: \"该战机配备两台冲压引擎，其电子设备也有特殊的防护措施。这是目前用地球技术能造出的最好的战机。\"\n  STR_LIGHTNING_UFOPEDIA: \"这种战斗运输机对外星推进系统的运用虽然还很粗糙，但却十分有效。\"\n  STR_SKYRANGER_UFOPEDIA: \"兵员运输机，是同类机型中最快的，并拥有垂直起降功能。\"\n  STR_FIRESTORM_UFOPEDIA: \"空战飞行器。采用中央推进单元的单人驾驶的战斗飞船是异形经典的圆盘形飞船的复制品。\"\n  STR_STINGRAY_UFOPEDIA: \"先进的空对空导弹，其电子设备拥有良好的防护。\"\n  STR_AVALANCHE_UFOPEDIA: \"具备装载核弹头能力的对空导弹，目前只装载了超重型常规弹头。\"\n  STR_CANNON_UFOPEDIA: \"使用穿甲弹的高性能机炮能击穿16英寸的钢板。\"\n  STR_FUSION_BALL_UFOPEDIA: \"此种发射器发射由反物质推进的椭球状导弹，导弹依靠引力波聚能爆震来毁伤目标。\"\n  STR_LASER_CANNON_UFOPEDIA: \"此常规激光武器采用反物质反应槽驱动。\"\n  STR_SECTOID_AUTOPSY: \"灵能者尸检\"\n  STR_SNAKEMAN_UFOPEDIA: \"这种生物发源于环境极端恶劣的地方。他们非常强壮，并且可以忍受极大的温差变化。他们依靠像蛇一样的一支大“脚”来移动，同时他们的关键器官也都由其保护。他们的目标似乎是纯粹的掠夺，而且他们的这种军事入侵一样的行动应该是其他高级智能的命令。\"\n  STR_SNAKEMAN_AUTOPSY: \"蛇人尸体\"\n  STR_ETHEREAL_AUTOPSY: \"虚灵解剖报告\"\n  STR_ETHEREAL_AUTOPSY_UFOPEDIA: \"这种生物的的物理结构发育不全，表面上似乎不能维持自身的生命。他们的肌肉很虚弱，体内的器官也高度退化，举例来说，他们的眼睛根本看不见。但是，他们的大脑却高度发达，占用了身体中大部分的血液供应。我们无法解释这种生物是如何在没有额外维生设备的情况下存活下来的。\"\n  STR_MUTON_UFOPEDIA: \"这种类人生物强壮且聪明。他们似乎有种对于血肉的强烈渴望，就像地球上的肉食动物一样。他们应该受到名为“虚灵”的生物的灵能控制。一旦他们失去了这种灵能链接，他们的神经系统就会停止工作，然后他们也会死去。他们体内有用来增强器战斗能力的植入物。他们显然是其他高级智能的兵卒。\"\n  STR_MUTON_AUTOPSY_UFOPEDIA: \"这种生物的“皮肤”似乎是一种移植而来的有机物护甲。其体内还有很多用来增强循环系统和感官能力的电子植入物。同时，他们没有繁殖能力。显然，这种不幸的生物只能为战斗而活。用穿甲弹对抗他们的坚固装甲效果有限。\"\n  STR_CELATID_UFOPEDIA: \"这种生物有神器的能力，可以悬浮于空中。它似乎能探测到人的脑电波，并据此向目标移动，即使那个人隐蔽得很好。一旦发现目标，腐蚀虫会向目标喷出一些剧毒的腐蚀性液体。而在遇到危险时，它能迅速增殖。他们常与突变者一起行动。\"\n  STR_CELATID_AUTOPSY: \"腐蚀虫尸体\"\n  STR_SILACOID_UFOPEDIA: \"这种硅基生物的身体发热量巨大，甚至足以将岩石融化。他们的智能有限，通常由植入物或者灵能者控制。他们与突变者共生。\"\n  STR_SILACOID_AUTOPSY: \"自爆虫解剖\"\n  STR_SILACOID_AUTOPSY_UFOPEDIA: \"该生物核心温度非常高，这似乎属于它消化系统的一部分。它独特的肌肉系统拥有强大的力量和速度。它岩石一般的皮肤表面让他们免疫来自于火或者燃烧弹的伤害。\"\n  STR_CHRYSSALID_UFOPEDIA: \"这种生物有着螃蟹一样的爪子，那是有效的近战武器。高速的新陈代谢和强大的力量使得它灵巧与速度兼备。它并不会直接杀死它的受害者，而是在目标体内产下一枚卵并使目标中毒，中毒的目标将会成为一个没有意识的僵尸。一个新的捕猎手将会在产卵后不久从受害者的体内挣出。捕猎手常与蛇人共同行动。\"\n  STR_CHRYSSALID_AUTOPSY: \"猎手解剖\"\n  STR_CHRYSSALID_AUTOPSY_UFOPEDIA: \"这种生物的外骨骼相当坚固，但是却容易受到高爆弹药的伤害。他们的细胞繁殖率很高，而且大脑高度发达。一个这样的生物携带着二十枚可产入其它有机体内的卵。他们是一种极其有效的恐怖袭击武器。\"\n  STR_FLOATER_AUTOPSY: \"漂浮者解剖报告\"\n  STR_FLOATER_AUTOPSY_UFOPEDIA: \"该生物通过手术被大幅改造过。身体核心部分的设备似乎是生命维持系统，取代心、肺和消化系统。这使它们能在极度恶劣的环境下生存。它的大脑比我们的小，但感官器官很发达。\"\n  STR_REAPER_AUTOPSY: \"收割兽解剖\"\n  STR_SECTOPOD_AUTOPSY: \"长足机甲拆卸\"\n  STR_SECTOPOD_AUTOPSY_UFOPEDIA: \"这种机器人由坚固的装甲制成，可以有效抵御大部分类型的攻击，特别是等离子武器的攻击。然而，它的探测系统似乎容易被激光武器击伤。\"\n  STR_CYBERDISC_AUTOPSY: \"电盘解剖\"\n  STR_CYBERDISC_AUTOPSY_UFOPEDIA: \"电盘拥有良好的防护，对爆炸的抵御能力特别强。它的反重力系统已经严重损坏，无法从中了解其工作原理。\"\n  STR_UFO_POWER_SOURCE_UFOPEDIA: \"异形飞船的动力源于采用E115的反物质反应堆，它能产生强大的引力波和其它类型的能量。物质转换为能量的转化比达到了99%的惊人效率，以至于极少量的E115就能产生极其强大的动力。该反应堆能用异形合金轻易再造。\"\n  STR_UFO_NAVIGATION_UFOPEDIA: \"不论在太空中或是在地球大气层内，外星飞碟都使用复杂的计算机系统来为飞碟导航。该系统基于先进的光学计算机技术，它的控制面板则相对简单——领航员只需指定由动力源产生的引力波的指向即可控制飞碟向期望的方向运动。人类很容易掌握这种导航系统的用法，并且还可以使用外星合金等组件自行制造。\"\n  STR_ALIEN_REPRODUCTION_UFOPEDIA: \"这些容器内装的是外星人胚胎。这种容器的设计表明它们的主人几乎完全依赖人工方式繁殖。若有充足的营养供应，胚胎将可快速发育。这种生产线可以在短时间内制造大量的外星人克隆体。这一过程也可以很容易地被改为克隆人类或是克隆人类-外星人混合体。\"\n  STR_ALIEN_ENTERTAINMENT_UFOPEDIA: \"这些球体最可能的功能是用于娱乐。其中的灵能回路可以刺激大脑的部分区域，效果类似于致幻药品。这是唯一能证明外星人也需要娱乐消遣的证据。\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"过去，上千人声称自己曾被外星人绑架，有时还有人被多次绑架。真实情况更为恐怖，人类被绑架、研究和观察，最优秀的样本被提取基因材料。女性被植入人类与异形混种的胎儿，并在数月后移除。谁会知道异形这么做的邪恶动机是什么？\"\n  STR_ALIEN_ALLOYS_UFOPEDIA: \"异形的飞行器采用了拥有独特性能的特殊的合金。这种合金极为轻盈和耐用，并能采用电磁法冶炼。这种材料能复制并且用于多种生产流程上。\"\n  STR_CYDONIA_OR_BUST_UFOPEDIA: \"我们现在终于知道，这些外星人由位于Cydonia 的一个地下基地控制。Cydonia是火星上一个特别的地方，那里有四座小金字塔和一座俯视起来像人脸一样的大金字塔。几百万年前，Cydonia的文明曾经遍布火星各处。他们为何灭亡了？他们与现在地球上的外星人又有何联系？这些我们都不知道。不论如何，我们必须派遣部队到那里去，这是我们唯一的取胜机会。我们必须摧毁外人星的控制主脑。我们将会用到一架装备着我们最顶尖武器的复仇者式战机。目前，我们知道的只有这些了——我们只能等待Cydonian 突击行动的结果。\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"以现场为中心 - TIME=5 Secs\"\n  STR_CANCEL_UC: \"取消项目\"\n  STR_NONE: \"无\"\n  STR_UNKNOWN: \"未知\"\n  STR_POOR: \"优秀\"\n  STR_AVERAGE: \"平均\"\n  STR_GOOD: \"好\"\n  STR_EXCELLENT: \"优秀\"\n  STR_BUILD_NEW_BASE_UC: \"建造新基地\"\n  STR_BASE_INFORMATION: \"基地情报\"\n  STR_EQUIP_CRAFT: \"配置战机\"\n  STR_BUILD_FACILITIES: \"修建设施\"\n  STR_RESEARCH: \"研究\"\n  STR_MANUFACTURE: \"制造\"\n  STR_TRANSFER_UC: \"转移\"\n  STR_PURCHASE_RECRUIT: \"购买/雇用\"\n  STR_SACK: \"解雇\"\n  STR_SELL_SACK_UC: \"卖掉\"\n  STR_GEOSCAPE_UC: \"全球视图\"\n  STR_NAME: \"名字\"\n  STR_AREA: \"地区\"\n  STR_BUILD_NEW_BASE: \"建造新基地\"\n  STR_CANCEL: \"取消\"\n  STR_CONSTRUCTION_TIME_UC: \"建造时间>\"\n  STR_MAINTENANCE_UC: \"维护费用\"\n  STR_OK: \"OK\"\n  STR_CURRENT_RESEARCH: \"当前研究\"\n  STR_SCIENTISTS_AVAILABLE: \"可用科学家>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"可用实验室空间>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"研究项目\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"分配科学家\"\n  STR_PROGRESS: \"进展\"\n  STR_NEW_PROJECT: \"新的项目\"\n  STR_CANCEL_PROJECT: \"取消项目\"\n  STR_NEW_RESEARCH_PROJECTS: \"新的研究计划\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"可用科学家>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"实验室空间剩余>{ALT}{0}\"\n  STR_INCREASE: \"增加\"\n  STR_DECREASE: \"降低\"\n  STR_START_PROJECT: \"开始项目\"\n  STR_CURRENT_PRODUCTION: \"当前制造\"\n  STR_ENGINEERS_AVAILABLE: \"可用工程师>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"分配工程师>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"可用工作室空间>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"当前资金>{ALT}{0}\"\n  STR_ITEM: \"物品\"\n  STR_ENGINEERS__ALLOCATED: \"分配工程师\"\n  STR_UNITS_PRODUCED: \"生产数量\"\n  STR_DAYS_HOURS_LEFT: \"日/小时剩下\"\n  STR_NEW_PRODUCTION: \"新制造计划\"\n  STR_PRODUCTION_ITEMS: \"生产项目\"\n  STR_CATEGORY: \"类别\"\n  STR_START_PRODUCTION: \"开始生产\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} 工程师/小时 可以生产一单位\"\n  STR_COST_PER_UNIT_: \"每单位成本>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"需要工作空间>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"需要特殊材料\"\n  STR_ITEM_REQUIRED: \"所需材料\"\n  STR_UNITS_REQUIRED: \"所需数量\"\n  STR_UNITS_AVAILABLE: \"可用单位\"\n  STR_STOP_PRODUCTION: \"停止制造\"\n  STR_ENGINEERS_AVAILABLE_UC: \"可用工程师>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"每月收益>{ALT}{0}\"\n  STR_INCREASE_UC: \"增加\"\n  STR_DECREASE_UC: \"减少\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"雇佣人员\"\n  STR_COST_OF_PURCHASES: \"交易花费>{ALT}{0}\"\n  STR_QUANTITY_UC: \"数量\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"待命人员：PERSONNEL TOTAL>\"\n  STR_SOLDIERS: \"士兵\"\n  STR_SCIENTISTS: \"科学家\"\n  STR_ENGINEERS: \"工程师\"\n  STR_LIVING_QUARTERS: \"生活区\"\n  STR_STORES: \"通用仓库\"\n  STR_LABORATORIES: \"实验室\"\n  STR_WORK_SHOPS: \"工作间\"\n  STR_HANGARS: \"机库\"\n  STR_SHORT_RANGE_DETECTION: \"远程侦查\"\n  STR_DEFENSE_STRENGTH: \"防御力量\"\n  STR_TRANSFERS_UC: \"传输\"\n  STR_TRANSFERS: \"运送物品到{0}\"\n  STR_ARRIVAL_TIME_HOURS: \"到达所需时间（小时）\"\n  STR_AREA_: \"区域>{ALT}{0}\"\n  STR_BASE_NAME: \"基地名称\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"选择入口电梯的位置\"\n  STR_TRANSFER: \"调\"\n  STR_SELECT_DESTINATION_BASE: \"选择目的地基地\"\n  STR_VICTORY_1: \"你缓步走进这个房间，看到了外星主脑——你的任务目标。在你开火之前，它通过基地里的一个屏幕与你通话。它请求在决定是否开枪前先听它把话说完......\"\n  STR_VICTORY_2: \"外星主脑说：“很久很久以前，这个被你们称为火星的星球是有生命的。我们的文明在一个另一个荒芜的星球种下了生命的种子，那就是你们的地球。几百万年来，我们多次造访你们的星球并改造你们的物种，使你们进化。你不能杀死我们，你们是我们的一部分......”\"\n  STR_VICTORY_3: \"这里是火星文明的中心——这些金字塔由你们遥远的祖先于千百万年前建造。宇宙中没有什么地方是我们到不了的。很快，这种力量也将会是你们的，我们只需要你们的合作......\"\n  STR_GAME_OVER_1: \"异形打算灭绝所有人类，毁灭人类城市并且毒害空气与海洋。地球军队面对拥有甚高科技水平异形的抵抗证明是徒劳的。幸存的人类在逃离异形屠戮时遭受了严重的基因突变，他们被聚集在奴隶营帮助异形将地球变成它们一些未知帝国的殖民地。\"\n  STR_GAME_OVER_2: \"由X-COM计划得到的知识永远丢失了，你没能拯救地球。\"\n  STR_VICTORY_4: \"等离子武器的射击摧毁了外星主脑，整个外星部队也随之被打败。\"\n  STR_VICTORY_5: \"一旦外星人失去了火星，它们也失去了地球。用不了多久，X-COM的研究成果就会使人类迅速繁荣并控制火星。外星人就此消失了，但没人知道它们会不会回来......\"\n  STR_YOU_HAVE_FAILED: \"你无法阻止异形的攻势，XCOM的资助国家一个接一个地跟异形签订合约，以换取异形期许的科技、财富与和平。但不久人们便很清晰发现异形其实有别的打算。\"\n  STR_INCOME: \"收入\"\n  STR_EXPENDITURE: \"花费\"\n  STR_MAINTENANCE: \"维护费用\"\n  STR_BALANCE: \"预算平衡\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"UFO活动地区\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"各国UFO活动情况\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"在{NEWLINE}{1}{NEWLINE}建设的{NEWLINE}{0}{NEWLINE}已经完成\"\n  STR_OK_5_SECONDS: \"好-五秒钟\"\n  STR_RESEARCH_COMPLETED: \"研究完成\"\n  STR_VIEW_REPORTS: \"查看报告\"\n  STR_WE_CAN_NOW_RESEARCH: \"我们现在可以研究\"\n  STR_WE_CAN_NOW_PRODUCE: \"现在我们可以制造\"\n  STR_SUNDAY: \"周日\"\n  STR_MONDAY: \"周一\"\n  STR_TUESDAY: \"星期二\"\n  STR_WEDNESDAY: \"周三\"\n  STR_THURSDAY: \"周四\"\n  STR_FRIDAY: \"周五\"\n  STR_SATURDAY: \"周六\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"没有足够的{0}用来补充位于{2}的{1}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"没有足够的{0}来补充位于{2}的{1}\"\n  STR_UFO_IS_NOT_RECOVERED: \"UFO未被回收\"\n  STR_UFO_IS_RECOVERED: \"UFO被起获\"\n  STR_CRAFT_IS_LOST: \"飞行器损失\"\n  STR_TERROR_CONTINUES: \"恐怖继续\"\n  STR_ALIENS_DEFEATED: \"外星人被击败\"\n  STR_BASE_IS_LOST: \"X-COM基地陷落\"\n  STR_ALIEN_BASE_STILL_INTACT: \"外星人基地仍然完好\"\n  STR_ALIEN_BASE_DESTROYED: \"外星人基地被摧毁\"\n  STR_ALIENS_KILLED: \"杀死外星人\"\n  STR_ALIEN_CORPSES_RECOVERED: \"俘获外星人\"\n  STR_LIVE_ALIENS_RECOVERED: \"俘获外星人\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"外星制品\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"外星基地控制中心被摧毁\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"平民被外星人击毙\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"被X-COM人员杀死的平民\"\n  STR_CIVILIANS_SAVED: \"拯救平民数\"\n  STR_FIRING: \"射击\"\n  STR_HIT: \"命中！\"\n  STR_UFO_DESTROYED: \"飞碟被摧毁！\"\n  STR_VALUE_OF_SALES: \"出售物品价值>{ALT}{0}\"\n  STR_FUNDS: \"资金>{ALT}{0}\"\n  STR_SELL_SACK: \"出售\"\n  STR_CRAFT_: \"战机>{ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_GROUND_ASSAULT: \"UFO地面战斗\"\n  STR_BASE_DEFENSE: \"基地防御\"\n  STR_ALIEN_BASE_ASSAULT: \"突击外星基地\"\n  STR_ALIEN_BASE_ASSAULT_BRIEFING: \"X-COM队员成功进入了外星基地。要使该基地瘫痪，我们必须摧毁它的控制中心。如果所有敌人都被消灭，或者所有队员都返回撤离区域，任务都可以结束(点击“放弃任务”按钮来撤离)。\"\n  STR_TERROR_MISSION: \"反恐任务\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"无多余机库可用！{SMALLLINE}任何一架在基地驻扎、转移、购买、建造的飞行器都占用一个机库。建造一个新机库或者转移一架飞行器到其它基地。\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"工作空间不足！{SMALLLINE}新建一个工场或者减少其他项目的工作空间占用。\"\n  STR_NOT_ENOUGH_MONEY: \"资金不足！\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"没有足够居住空间！{SMALLLINE}建造新的员工居住区或者将人员转移到其他基地。\"\n  STR_BASE: \"基地\"\n  STR_READY: \"就绪\"\n  STR_REPAIRS: \"修理中\"\n  STR_REFUELLING: \"补充燃料中\"\n  STR_WAY_POINT: \"导航点\"\n  STR_ARE_YOU_SURE_CYDONIA: \"确定要前往塞多尼亚？\"\n  STR_CYDONIA: \"塞東尼亞區\"\n  STR_RETURN_TO_BASE: \"返回基地\"\n  STR_SELECT_NEW_TARGET: \"选择新目标\"\n  STR_PATROL: \"巡逻\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"受损——返回基地\"\n  STR_TAILING_UFO: \"追踪UFO\"\n  STR_RETURNING_TO_BASE: \"返回基地\"\n  STR_MAXIMUM_SPEED_UC: \"最大速度>{ALT}{0}{ALT}\"\n  STR_VERY_LOW: \"非常低\"\n  STR_LOW_UC: \"低\"\n  STR_HIGH_UC: \"高\"\n  STR_VERY_HIGH: \"很高\"\n  STR_WEAPON_ONE: \"武器-1>{ALT}{0}\"\n  STR_NONE_UC: \"没有任何事物\"\n  STR_INTERCEPTION_CRAFT: \"拦截机\"\n  STR_BASE_: \"基地>{0}\"\n  STR_NAME_UC: \"名字\"\n  STR_AMMO_: \"弹药>{ALT}{0}\"\n  STR_CREW: \"乘员数\"\n  STR_EQUIPMENT_UC: \"装备\"\n  STR_ARMOR: \"装甲\"\n  STR_ROOKIE: \"新兵\"\n  STR_SQUADDIE: \"二等兵\"\n  STR_SERGEANT: \"士官\"\n  STR_CAPTAIN: \"上尉\"\n  STR_COLONEL: \"上校\"\n  STR_COMMANDER: \"指挥官\"\n  STR_MISSIONS2: \"任务\"\n  STR_SPACE_AVAILABLE: \"剩余空间>{ALT}{0}\"\n  STR_WOUNDED: \"受伤\"\n  STR_EQUIPMENT_FOR_CRAFT: \"装备到 {0}\"\n  STR_DEFENSE_VALUE: \"防御力量\"\n  STR_HIT_RATIO: \"命中率\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}准备好{NEWLINE}降落在{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"任务开始？\"\n  STR_SELECT_ARMAMENT: \"选择武器装备\"\n  STR_AMMUNITION_AVAILABLE: \"可用弹药\"\n  STR_ARMAMENT: \"武器配置\"\n  STR_NOT_AVAILABLE: \"不可用\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"为{0}{NEWLINE}选择装甲\"\n  STR_PERSONAL_ARMOR_UC: \"个人装甲\"\n  STR_POWER_SUIT_UC: \"动力装甲\"\n  STR_FLYING_SUIT_UC: \"飞行装甲\"\n  STR_SELECT_ARMOR: \"选择装甲\"\n  STR_NORTH: \"北\"\n  STR_NORTH_EAST: \"东北\"\n  STR_EAST: \"东\"\n  STR_SOUTH_EAST: \"东南\"\n  STR_SOUTH: \"南\"\n  STR_SOUTH_WEST: \"西南方\"\n  STR_WEST: \"西\"\n  STR_NORTH_WEST: \"北 西\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"继续追踪拦截\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"跟踪但不开火\"\n  STR_VERY_LARGE: \"很大\"\n  STR_LARGE: \"大型\"\n  STR_MEDIUM_UC: \"中型\"\n  STR_SMALL: \"小\"\n  STR_VERY_SMALL: \"超小型\"\n  STR_GROUNDED: \"着陆\"\n  STR_SIZE_UC: \"大小\"\n  STR_ALTITUDE: \"高度\"\n  STR_SPEED: \"速度\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"以UFO为中心 - TIME=5 Secs\"\n  STR_TRACKING_LOST: \"丢失目标\"\n  STR_REDIRECT_CRAFT: \"为战机重新制定目标\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"转到 UFO 失踪前的最后位置\"\n  STR_UFO_: \"UFO-{0}\"\n  STR_ALIEN_BASE_: \"外星基地-{0}\"\n  STR_CRASH_SITE_: \"坠毁地点-{0}\"\n  STR_LANDING_SITE_: \"着陆场-{0}\"\n  STR_WAY_POINT_: \"路径点-{0}\"\n  STR_TERROR_SITE: \"袭击地点-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}已经抵达了{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"正在巡逻\"\n  STR_ALIEN_ORIGINS: \"外星人起源\"\n  STR_THE_MARTIAN_SOLUTION: \"火星方案\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"重型武器平台\"\n  STR_ALIEN_ARTIFACTS: \"外星制品\"\n  STR_ALIEN_LIFE_FORMS: \"外星生命\"\n  STR_ALIEN_RESEARCH_UC: \"外星人研究\"\n  STR_UFO_COMPONENTS: \"飞碟部件\"\n  STR_UFOS: \"UFO\"\n  STR_FUEL_CAPACITY: \"燃料剩余>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"武器舱>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"伤害能力>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"HWP容量>{ALT}{0}{ALT}\"\n  STR_RANGE: \"射程\"\n  STR_KILOMETERS: \"{0} 公里\"\n  STR_ACCURACY: \"精度\"\n  STR_SECONDS: \"{0}秒\"\n  STR_DAMAGE_INCENDIARY: \"燃烧弹\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"高爆炸药\"\n  STR_DAMAGE_LASER_BEAM: \"激光束\"\n  STR_DAMAGE_PLASMA_BEAM: \"对空等离子系统\"\n  STR_DAMAGE_SMOKE: \"烟雾\"\n  STR_ACCURACY_UC: \"精度\"\n  STR_DAMAGE_UC: \"伤害\"\n  STR_AMMO: \"弹药\"\n  STR_SHOT_TYPE_AUTO: \"自动\"\n  STR_CONSTRUCTION_TIME: \"建造时间>\"\n  STR_CONSTRUCTION_COST: \"工程费用\"\n  STR_MAINTENANCE_COST: \"维护花费\"\n  STR_LOW: \"低\"\n  STR_MEDIUM: \"中\"\n  STR_HIGH: \"高\"\n  STR_CRAFT_WEAPON: \"战机武器\"\n  STR_CRAFT_AMMUNITION: \"制造弹药\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"重型武器平台\"\n  STR_WEAPON: \"武器\"\n  STR_AMMUNITION: \"弹药\"\n  STR_EQUIPMENT: \"設備\"\n  STR_ALIEN_CORPSE: \"外星人尸体\"\n  STR_UFO_COMPONENT: \"UFO的組成部件\"\n  STR_PERSONAL_ARMOR: \"个人护甲\"\n  STR_HWP_CANNON_SHELLS: \"重型武器平台加农炮弹药\"\n  STR_ALIEN: \"异形\"\n  STR_SECTOID: \"灵能者\"\n  STR_SNAKEMAN: \"蛇人\"\n  STR_ETHEREAL: \"虚灵\"\n  STR_MUTON: \"突变者\"\n  STR_FLOATER: \"漂浮者\"\n  STR_CELATID: \"腐蚀虫\"\n  STR_SILACOID: \"自爆虫\"\n  STR_CHRYSSALID: \"鉗獵者\"\n  STR_ZOMBIE: \"僵尸\"\n  STR_REAPER: \"收割兽\"\n  STR_CYBERDISC: \"电盘\"\n  STR_LIVE_COMMANDER: \"指挥官\"\n  STR_LIVE_LEADER: \"领导\"\n  STR_LIVE_ENGINEER: \"工程师\"\n  STR_LIVE_MEDIC: \"医疗兵\"\n  STR_LIVE_NAVIGATOR: \"领航员\"\n  STR_LIVE_SOLDIER: \"士兵\"\n  STR_LIVE_TERRORIST: \"恐怖单位\"\n  STR_FLOATER_SOLDIER: \"漂浮者士兵\"\n  STR_FLOATER_NAVIGATOR: \"浮动导航\"\n  STR_FLOATER_MEDIC: \"漂浮者医护\"\n  STR_FLOATER_ENGINEER: \"漂浮者工程师\"\n  STR_FLOATER_LEADER: \"漂浮者领导人\"\n  STR_FLOATER_COMMANDER: \"漂浮者指挥官\"\n  STR_SECTOID_SOLDIER: \"灵能者士兵\"\n  STR_SECTOID_NAVIGATOR: \"灵能者领航员\"\n  STR_SECTOID_MEDIC: \"灵能者医疗兵\"\n  STR_SECTOID_ENGINEER: \"灵能者工程师\"\n  STR_SECTOID_LEADER: \"灵能者领导人\"\n  STR_SECTOID_COMMANDER: \"灵能者指挥官\"\n  STR_SNAKEMAN_SOLDIER: \"蛇人士兵\"\n  STR_SNAKEMAN_NAVIGATOR: \"蛇人领航员\"\n  STR_SNAKEMAN_ENGINEER: \"蛇人工程师\"\n  STR_SNAKEMAN_LEADER: \"蛇人领袖\"\n  STR_SNAKEMAN_COMMANDER: \"蛇人指挥官\"\n  STR_MUTON_SOLDIER: \"突变者兵\"\n  STR_MUTON_NAVIGATOR: \"突变者领航员\"\n  STR_MUTON_ENGINEER: \"突变者工程师\"\n  STR_ETHEREAL_SOLDIER: \"虚灵士兵\"\n  STR_ETHEREAL_LEADER: \"虚灵领袖\"\n  STR_ETHEREAL_COMMANDER: \"虚灵指挥官\"\n  STR_CYBERDISC_TERRORIST: \"电盘\"\n  STR_REAPER_TERRORIST: \"收割兽\"\n  STR_CHRYSSALID_TERRORIST: \"猎手\"\n  STR_SILACOID_TERRORIST: \"自爆虫\"\n  STR_UFO_POWER_SOURCE: \"UFO 能源\"\n  STR_UFO_NAVIGATION: \"飞碟导航系统\"\n  STR_UFO_CONSTRUCTION: \"UFO建筑架构\"\n  STR_ALIEN_FOOD: \"外星人食品\"\n  STR_ALIEN_REPRODUCTION: \"外星人无性\"\n  STR_ALIEN_ENTERTAINMENT: \"外星人娱乐设备\"\n  STR_ALIEN_SURGERY: \"外星人外科\"\n  STR_EXAMINATION_ROOM: \"检查室\"\n  STR_ALIEN_ALLOYS: \"异形合金\"\n  STR_ALIEN_HABITAT: \"外星人生境\"\n  STR_POWER_SUIT: \"能源组件\"\n  STR_FLYING_SUIT: \"飞行装甲\"\n  STR_LASER_WEAPONS: \"激光武器\"\n  STR_NEW_FIGHTER_CRAFT: \"新空战飞行器\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"新型战斗运输机\"\n  STR_LASER_PISTOL: \"激光手枪\"\n  STR_LASER_RIFLE: \"激光步枪\"\n  STR_HEAVY_LASER: \"重型激光枪\"\n  STR_LASER_CANNON: \"对空激光系统\"\n  STR_PLASMA_CANNON: \"等离子加农炮\"\n  STR_FUSION_MISSILE: \"聚变导弹\"\n  STR_LASER_DEFENSE: \"激光防御武器\"\n  STR_PLASMA_DEFENSE: \"等离子防御系统\"\n  STR_FUSION_DEFENSE: \"聚变防御系统\"\n  STR_GRAV_SHIELD: \"引力护盾\"\n  STR_MIND_SHIELD: \"心灵防护墙\"\n  STR_PSI_LAB: \"精神训练中心\"\n  STR_MOTION_SCANNER: \"动态扫描器\"\n  STR_MEDI_KIT: \"医疗包\"\n  STR_TANK_CANNON: \"加农炮坦克\"\n  STR_TANK_ROCKET_LAUNCHER: \"坦克/火箭发射车\"\n  STR_TANK_LASER_CANNON: \"坦克，配备激光加农炮\"\n  STR_HOVERTANK_PLASMA: \"悬浮坦克/等离子武器\"\n  STR_HOVERTANK_LAUNCHER: \"导弹悬浮坦克\"\n  STR_STINGRAY_LAUNCHER: \"魔鬼鱼导弹发射器\"\n  STR_AVALANCHE_LAUNCHER: \"雪崩射车\"\n  STR_CANNON: \"加农炮\"\n  STR_STINGRAY_MISSILES: \"魔鬼鱼导弹\"\n  STR_AVALANCHE_MISSILES: \"雪崩导弹\"\n  STR_CANNON_ROUNDS_X50: \"加农炮弹药（x50）\"\n  STR_FUSION_BALL: \"核聚变球\"\n  STR_SOLDIER: \"士兵\"\n  STR_SCIENTIST: \"科学家\"\n  STR_ENGINEER: \"工程师\"\n  STR_NORTH_AMERICA: \"北美\"\n  STR_ARCTIC: \"北极\"\n  STR_ANTARCTICA: \"南极洲\"\n  STR_SOUTH_AMERICA: \"南美\"\n  STR_EUROPE: \"欧洲\"\n  STR_NORTH_AFRICA: \"北非\"\n  STR_SOUTHERN_AFRICA: \"南非\"\n  STR_CENTRAL_ASIA: \"中亚\"\n  STR_SOUTH_EAST_ASIA: \"东南亚\"\n  STR_SIBERIA: \"西伯利亚\"\n  STR_AUSTRALASIA: \"大洋洲\"\n  STR_PACIFIC: \"太平洋\"\n  STR_NORTH_ATLANTIC: \"北大西洋\"\n  STR_SOUTH_ATLANTIC: \"南大西洋\"\n  STR_INDIAN_OCEAN: \"印度洋\"\n  STR_ALIEN_INFILTRATION: \"异形渗透任务\"\n  STR_ALIEN_BASE: \"外星人基地\"\n  STR_ALIEN_TERROR: \"外星人恐怖袭击\"\n  STR_ALIEN_RETALIATION: \"外星人报复\"\n  STR_HYPER_WAVE_DECODER_UC: \"外星解码器\"\n  STR_SKYRANGER: \"空中游侠\"\n  STR_LIGHTNING: \"闪电\"\n  STR_AVENGER: \"复仇者\"\n  STR_INTERCEPTOR: \"拦截机\"\n  STR_FIRESTORM: \"火龙卷\"\n  STR_UFO: \"UFO\"\n  STR_STINGRAY: \"魔鬼鱼导弹\"\n  STR_AVALANCHE: \"雪崩\"\n  STR_CANNON_UC: \"机炮\"\n  STR_FUSION_BALL_UC: \"核聚变球\"\n  STR_LASER_CANNON_UC: \"激光加农炮\"\n  STR_PLASMA_BEAM_UC: \"对空等离子系统\"\n  STR_WEAPON_POWER: \"武器伤害\"\n  STR_WEAPON_RANGE: \"武器射程\"\n  STR_ACCESS_LIFT: \"入口电梯\"\n  STR_LABORATORY: \"实验室\"\n  STR_SMALL_RADAR_SYSTEM: \"小型雷达系统\"\n  STR_LARGE_RADAR_SYSTEM: \"大型雷达系统\"\n  STR_MISSILE_DEFENSES: \"导弹防御设施\"\n  STR_GENERAL_STORES: \"通用仓库\"\n  STR_ALIEN_CONTAINMENT: \"异形收容设施\"\n  STR_LASER_DEFENSES: \"激光防御系统\"\n  STR_PLASMA_DEFENSES: \"等离子防御武器\"\n  STR_FUSION_BALL_DEFENSES: \"聚变防御系统\"\n  STR_PSIONIC_LABORATORY: \"精神训练室\"\n  STR_HYPER_WAVE_DECODER: \"超波解码设施\"\n  STR_HANGAR: \"机库\"\n  STR_USA: \"美国\"\n  STR_RUSSIA: \"俄罗斯\"\n  STR_UK: \"英国\"\n  STR_FRANCE: \"法国\"\n  STR_GERMANY: \"德国\"\n  STR_ITALY: \"意大利\"\n  STR_SPAIN: \"西班牙\"\n  STR_CHINA: \"中国\"\n  STR_JAPAN: \"日本\"\n  STR_INDIA: \"印度\"\n  STR_BRAZIL: \"巴西\"\n  STR_AUSTRALIA: \"澳大利亚\"\n  STR_NIGERIA: \"尼日利亚\"\n  STR_SOUTH_AFRICA: \"南非\"\n  STR_EGYPT: \"埃及\"\n  STR_CANADA: \"加拿大\"\n  STR_TANK: \"坦克\"\n  STR_CIVILIAN: \"平民\"\n  STR_JAN: \"一月\"\n  STR_FEB: \"二月\"\n  STR_MAR: \"三月\"\n  STR_APR: \"四月\"\n  STR_MAY: \"五月\"\n  STR_JUN: \"六月\"\n  STR_JUL: \"七月\"\n  STR_AUG: \"八月\"\n  STR_SEP: \"九月\"\n  STR_OCT: \"十月\"\n  STR_NOV: \"11月\"\n  STR_DEC: \"十二月\"\n  STR_INTERNATIONAL_RELATIONS: \"国际关系\"\n  STR_COUNTRY: \"国家\"\n  STR_FUNDING: \"资金\"\n  STR_CHANGE: \"更改值\"\n  STR_WEAPON_SYSTEMS: \"武器系统\"\n  STR_DAMAGE_UC_: \"伤害>{ALT}{0}\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"每个居住区模块可以容纳50人。这种设施提供基本的娱乐，食品和床铺。\"\n  STR_LABORATORY_UFOPEDIA: \"最多50名研究人员可以在一座实验室设施内工作。实验室配备了研究材料、生物学、宇宙学科技的最新设备。实验室拥有连接全球各地最尖端的研究实验室和军用设施的特权。\"\n  STR_WORKSHOP_UFOPEDIA: \"工场包含所有必要设备，以制造研究实验室设计出来的装备。空间最多可容纳50名工程师，但建造中的装备将占据一定的工场空间。\"\n  STR_MISSILE_DEFENSES_UFOPEDIA: \"导弹防御系统能对试图在基地附近着的陆敌对飞行器提供一定程度的保护。\"\n  STR_GENERAL_STORES_UFOPEDIA: \"所有装备、武器系统、弹药、捕获的材料和重型武器平台都储存在仓库，还包括机库飞行器的装备。\"\n  STR_PLASMA_DEFENSES_UFOPEDIA: \"面对敌对入侵飞船，等离子防御系统能提供强大与有效的防御。\"\n  STR_FUSION_BALL_DEFENSES_UFOPEDIA: \"聚变导弹设置能提供对抗异形攻击最有效的防御。这些导弹能创造出毁灭一切的反物质内爆区域。\"\n  STR_GRAV_SHIELD_UFOPEDIA: \"引力盾系统能延缓异形飞行器着陆一段时间，这段时间足以让基地的防御系统再发射一次。实际上，它能使基地的防御系统发挥双倍的效能。\"\n  STR_MIND_SHIELD_UFOPEDIA: \"异形飞船依赖脑电波来探测人类，所以最有效的反制措施就是屏蔽基地范围的脑电波。该设施能大幅降低基地被异形飞船发现的机会。\"\n  STR_HYPER_WAVE_DECODER_UFOPEDIA: \"外星人使用一种接近于超距作用的四维波动进行通信。这个解码器设施可以拦截并解密飞碟间的此类通信，从而让我们知道飞碟类型和任务，以及外星人的种族。\"\n  STR_RIFLE_UFOPEDIA: \"此高精度狙击步枪采用激光瞄准模式，使用6.7毫米口径弹药，并采用20发装填的弹夹。\"\n  STR_HEAVY_CANNON_UFOPEDIA: \"重型榴弹炮的威力强大，但很笨重。它的多功能性在于能使用三种弹药：穿甲弹、燃烧弹、高爆弹。\"\n  STR_AUTO_CANNON_UFOPEDIA: \"机炮将重型榴弹炮的火力与射速的多功能结合在了一起。\"\n  STR_ROCKET_LAUNCHER_UFOPEDIA: \"火箭发射器采用激光引导系统，并使用三种不同类型的弹药。\"\n  STR_LASER_PISTOL_UFOPEDIA: \"激光手枪是新科技的产物。它不仅拥有更快速和更精准的火力，而且还跟常规手枪一样易用。\"\n  STR_LASER_RIFLE_UFOPEDIA: \"激光步枪比起早期的手枪版本更为精准和大威力。\"\n  STR_HEAVY_LASER_UFOPEDIA: \"重型激光枪虽然笨重，但极为有效。\"\n  STR_SMOKE_GRENADE_UFOPEDIA: \"烟雾弹能在非隐蔽场合的作战提供掩护。因为同时它们也能为敌人提供掩护，所以请审慎使用。\"\n  STR_PROXIMITY_GRENADE_UFOPEDIA: \"感应手榴弹能跟普通手榴弹一样投掷，但它只会被落点附近的活动所触发。使用感应手榴弹需要很高技巧与谨慎才能发挥作用。\"\n  STR_HIGH_EXPLOSIVE_UFOPEDIA: \"该爆炸装置应当仅用于爆破用途。使用时要让人员远离爆破现场。\"\n  STR_STUN_ROD_UFOPEDIA: \"此近战装备采用电击瘫痪而非杀死目标生物。\"\n  STR_SMALL_LAUNCHER_UFOPEDIA: \"震撼弹发射器，可以用来俘虏外星人。\"\n  STR_SMALL_SCOUT: \"小型侦查机\"\n  STR_MEDIUM_SCOUT: \"中型侦查机\"\n  STR_LARGE_SCOUT: \"大型侦查飞碟\"\n  STR_BATTLESHIP: \"战列舰\"\n  STR_SUPPLY_SHIP: \"补给舰\"\n  STR_RATING: \"评分> {0}\"\n  STR_RATING_POOR: \"糟糕！\"\n  STR_RATING_OK: \"OK\"\n  STR_RATING_GOOD: \"好！\"\n  STR_RATING_EXCELLENT: \"优秀\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"基金委员会目前基本满意你的表现。\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"议会对你的工作进展感到十分满意，请再接再厉。\"\n  STR_COUNCIL_IS_DISSATISFIED: \"议会对你的表现感到失望，你必须提高工作效率，否则我们的计划将面临危险。\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"你没能阻止外星人的侵入，议会因此不得不中止X-COM计划，世界各国将会自行处理这些事务。我们只能祈祷我们能与这些敌对势力达成某种协议，以便让我们可以与这些外星来客共存。\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0}非常满意你处理当地异性入侵的表现并决定增加对你的拨款。\"\n  STR_COUNTRIES_AND: \"{0} 和 {1}\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0}对你应对外星人袭击的能力感到失望，并决定减少对你的资金支持。\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0}与不明异形签订了一个秘密协议并退出了XCOM项目。\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0}与不明异形签订了一个秘密协议并退出了XCOM项目。\"\n  STR_COUNCIL_REDUCE_DEBTS: \"基金委员会对你的财政状况不满意。你必须减少你的债务至$1百万以下，否则项目会被终结。\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"超维通信已被破译\"\n  STR_CRAFT_TYPE: \"飞行器类型\"\n  STR_MISSION: \"任务\"\n  STR_NEW_YORK: \"纽约\"\n  STR_WASHINGTON: \"华盛顿\"\n  STR_LOS_ANGELES: \"洛杉矶\"\n  STR_MONTREAL: \"蒙特利尔\"\n  STR_MEXICO_CITY: \"墨西哥城\"\n  STR_CHICAGO: \"芝加哥\"\n  STR_VANCOUVER: \"温哥华\"\n  STR_BRASILIA: \"巴西利亚\"\n  STR_BOGOTA: \"波哥大\"\n  STR_BUENOS_AIRES: \"布宜诺斯艾利斯\"\n  STR_SANTIAGO: \"圣地亚哥\"\n  STR_RIO_DE_JANEIRO: \"里约热内卢\"\n  STR_CARACAS: \"加拉加斯\"\n  STR_LONDON: \"伦敦\"\n  STR_PARIS: \"巴黎\"\n  STR_BERLIN: \"柏林\"\n  STR_MOSCOW: \"莫斯科\"\n  STR_ROME: \"罗马\"\n  STR_MADRID: \"马德里\"\n  STR_BUDAPEST: \"布达佩斯\"\n  STR_LAGOS: \"拉戈斯\"\n  STR_CAIRO: \"开罗\"\n  STR_CASABLANCA: \"卡萨布兰卡\"\n  STR_PRETORIA: \"比勒陀利亚\"\n  STR_NAIROBI: \"内罗毕\"\n  STR_CAPE_TOWN: \"开普敦\"\n  STR_KINSHASA: \"金沙萨\"\n  STR_DELHI: \"德里\"\n  STR_KARACHI: \"卡拉奇\"\n  STR_BAGHDAD: \"巴格达\"\n  STR_TOKYO: \"东京\"\n  STR_BEIJING: \"北京\"\n  STR_BANGKOK: \"曼谷\"\n  STR_SEOUL: \"汉城\"\n  STR_SINGAPORE: \"新加坡\"\n  STR_SHANGHAI: \"上海\"\n  STR_HONG_KONG: \"香港\"\n  STR_CANBERRA: \"堪培拉\"\n  STR_WELLINGTON: \"惠灵顿\"\n  STR_MELBOURNE: \"墨尔本\"\n  STR_PERTH: \"珀斯\"\n  STR_PSIONIC_TRAINING: \"灵能训练\"\n  STR_PSIONIC__STRENGTH: \"灵能{NEWLINE}力量\"\n  STR_PSI_AMP: \"心灵增幅器\"\n  STR_WEAPONS_CREW_HWPS: \"武器/{NEWLINE}乘员/重武器平台\"\n  STR_WOUND_RECOVERY: \"创伤复原> {ALT}{0}\"\n  STR_TIME_UNITS: \"时间\"\n  STR_STAMINA: \"体力\"\n  STR_HEALTH: \"生命值\"\n  STR_BRAVERY: \"勇气\"\n  STR_REACTIONS: \"反应\"\n  STR_FIRING_ACCURACY: \"射击精度\"\n  STR_THROWING_ACCURACY: \"投掷精度\"\n  STR_STRENGTH: \"力量\"\n  STR_PSIONIC_STRENGTH: \"灵能力量\"\n  STR_PSIONIC_SKILL: \"灵能技能\"\n  STR_NEW_RANK: \"晋升军衔\"\n  STR_PROMOTIONS: \"晋级\"\n  STR_SOLDIERS_UC: \"士兵\"\n  STR_TANK_ROCKET_LAUNCHER_UFOPEDIA: \"这种无人的重型武器平台配备了威力强大的火箭发射器，这对任何外星人而言都是灾难性的。注意时刻保证你有充足的火箭弹供应。\"\n  STR_HOVERTANK_PLASMA_UFOPEDIA: \"外星技术大大提高了HWP的战场生存能力。新增的浮空能力和等离子武器是个致命的组合。\"\n  STR_HEAVY_PLASMA_CLIP_UFOPEDIA: \"设个紧凑的设备是重型等离子步枪的弹匣，其中含有少量Elerium元素。\"\n  STR_PLASMA_RIFLE_CLIP_UFOPEDIA: \"这个设备可以供能给等离子步枪—— 一种中型外星武器。其中含有少量的E-115元素。\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"异形基地一旦建立，定期会有特殊的补给飞行器进行补给。如果这类飞行器被发现着陆，那么附近肯定会有异形基地。\"\n  STR_MEDIUM_SCOUT_UFOPEDIA: \"一种威胁不大的中型侦查船只。一般先于大型船只出现。\"\n  STR_ABDUCTOR_UFOPEDIA: \"此飞行器配备了一间用于对人类实施可怕试验的检验室。手术台上的受害者通常被精神力麻醉，但仍然清醒。\"\n  STR_BATTLESHIP_UFOPEDIA: \"战列舰是外星人最强大的舰船。它通常配备威力强大的武器和大量的船员，并被作为主要的任务舰船使用。\"\n  STR_DISMANTLE: \"拆除\"\n  STR_FACILITY_IN_USE: \"设施正在使用中\"\n  STR_TRANSFER_ITEMS_TO: \"运送物品到{0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"无外星人收容设施！{SMALLLINE}活的外星人需要外星人收容设施才能存活。\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"因为没有异形收容设施，所有活体异形已死亡。\"\n  STR_DESTINATION_UC: \"目的地\"\n  STR_PISTOL: \"手枪\"\n  STR_PISTOL_CLIP: \"手枪弹匣\"\n  STR_RIFLE: \"步枪\"\n  STR_RIFLE_CLIP: \"步枪弹匣\"\n  STR_HEAVY_CANNON: \"重型榴弹炮\"\n  STR_HC_AP_AMMO: \"重型加农炮穿甲弹药\"\n  STR_HC_HE_AMMO: \"重型加农炮高爆弹药\"\n  STR_AUTO_CANNON: \"自动加农炮\"\n  STR_AC_AP_AMMO: \"自动加农炮穿甲弹药\"\n  STR_AC_HE_AMMO: \"自动加农炮高爆弹药\"\n  STR_AC_I_AMMO: \"自动加农炮燃烧弹药\"\n  STR_ROCKET_LAUNCHER: \"火箭发射器\"\n  STR_SMALL_ROCKET: \"小型火箭弹\"\n  STR_LARGE_ROCKET: \"大型火箭弹\"\n  STR_INCENDIARY_ROCKET: \"火箭燃烧弹\"\n  STR_GRENADE: \"手榴弹\"\n  STR_SMOKE_GRENADE: \"烟雾弹\"\n  STR_PROXIMITY_GRENADE: \"感应手榴弹\"\n  STR_HIGH_EXPLOSIVE: \"高爆炸药\"\n  STR_STUN_ROD: \"电击棒\"\n  STR_HEAVY_PLASMA: \"重型等离子步枪\"\n  STR_HEAVY_PLASMA_CLIP: \"中型等离子步枪弹匣\"\n  STR_PLASMA_RIFLE: \"等离子步枪\"\n  STR_PLASMA_RIFLE_CLIP: \"等离子步枪弹匣\"\n  STR_PLASMA_PISTOL: \"等离子手枪\"\n  STR_PLASMA_PISTOL_CLIP: \"等离子手枪弹夹\"\n  STR_STUN_BOMB: \"震撼弹\"\n  STR_ALIEN_GRENADE: \"异形手榴弹\"\n  STR_ELERIUM_115: \"Elerium-115元素\"\n  STR_SECTOID_CORPSE: \"灵能者尸体\"\n  STR_SNAKEMAN_CORPSE: \"蛇人尸体\"\n  STR_ETHEREAL_CORPSE: \"虚灵尸体\"\n  STR_MUTON_CORPSE: \"突变者尸体\"\n  STR_FLOATER_CORPSE: \"漂浮者尸体\"\n  STR_CELATID_CORPSE: \"腐蚀虫尸体\"\n  STR_SILACOID_CORPSE: \"自爆虫尸体\"\n  STR_CHRYSSALID_CORPSE: \"猎手尸体\"\n  STR_REAPER_CORPSE: \"收割兽尸体\"\n  STR_CYBERDISC_CORPSE: \"电盘尸体\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"没有足够的物资来完全补充战斗分队\"\n  STR_MARS_CYDONIA_LANDING: \"火星：塞多尼亚着陆\"\n  STR_MARS_CYDONIA_LANDING_BRIEFING: \"你的“复仇者”战斗运输机降落在了火星表面名为“Cydonia ”的地方。我们的情报指出在其中一个金字塔一样的建筑物中，有一个通往地下建筑的升降机。当你把所有士兵都移动到升降机区域后，通过“放弃任务”按钮来前进到下一个场景。\"\n  STR_MARS_THE_FINAL_ASSAULT: \"火星：最终突击\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"外星人摧毁了不设防的基地 {0}\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"X-COM特工已于{0}定位了外星基地。\"\n  STR_CAUTIOUS_ATTACK: \"谨慎的攻击\"\n  STR_STANDARD_ATTACK: \"标准攻击\"\n  STR_AGGRESSIVE_ATTACK: \"主动攻击\"\n  STR_UFO_HIT: \"命中！\"\n  STR_UFO_CRASH_LANDS: \"飞碟坠毁地点\"\n  STR_UFO_RETURN_FIRE: \"UFO 还击\"\n  STR_INTERCEPTOR_DAMAGED: \">>> 拦截机受损 <<<\"\n  STR_LONG_RANGE_DETECTION: \"远程侦查\"\n  STR_DIFFICULTY_LEVEL: \"难度\"\n  STR_INTERCEPT: \"拦截\"\n  STR_BASES: \"基地\"\n  STR_OPTIONS_UC: \"选项\"\n  STR_FUNDING_UC: \"资金\"\n  STR_5_SECONDS: \"五秒\"\n  STR_1_MINUTE: \"一分钟\"\n  STR_5_MINUTES: \"5分钟\"\n  STR_30_MINUTES: \"三十分钟\"\n  STR_1_HOUR: \"1小时\"\n  STR_ENTER_NAME: \"输入名称\"\n  STR_PERFORMANCE_RATING: \"表现评价\"\n  STR_VICTORY_DATE: \"胜利日\"\n  STR_ELECTRO_FLARE_UFOPEDIA: \"这个小巧的装置能在被抛出后发出明亮的光芒，可为夜间任务照亮电子照明弹附近的敌人。\"\n  STR_SALARIES: \"薪水\"\n  STR_BASE_MAINTENANCE: \"基地维护\"\n  STR_COST_PER_UNIT: \"每单位成本\"\n  STR_QUANTITY: \"数量\"\n  STR_IN_PSIONIC_TRAINING: \"正接受灵能训练\"\n  STR_BLASTER_BOMB_UFOPEDIA: \"这是一枚高性能微型导弹，可以使用导弹发射器发射。\"\n  STR_REAR_ARMOR: \"侧向护甲\"\n  STR_UNDER_ARMOR: \"底部装甲\"\n  STR_UNIT: \"数量>{0}\"\n  STR_MORALE: \"士气\"\n  STR_FRONT_ARMOR_UC: \"前装甲\"\n  STR_LEFT_ARMOR_UC: \"左侧装甲\"\n  STR_REAR_ARMOR_UC: \"侧向护甲\"\n  STR_SKILLS: \"技能>{0}\"\n  STR_TORSO: \"躯干\"\n  STR_RIGHT_ARM: \"右臂\"\n  STR_LEFT_ARM: \"左臂\"\n  STR_RIGHT_LEG: \"右腿\"\n  STR_LEFT_LEG: \"左腿\"\n  STR_PAIN_KILLER: \"止痛药\"\n  STR_PSIONIC_SKILL_SHORT: \"灵能技巧>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"灵能力量>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"异形物品\"\n  STR_THROW: \"丢弃\"\n  STR_AUTO_SHOT: \"全自动射击\"\n  STR_SNAP_SHOT: \"速射\"\n  STR_PRIME_GRENADE: \"感应手榴弹\"\n  STR_USE_SCANNER: \"使用扫描器\"\n  STR_USE_MEDI_KIT: \"使用医疗包\"\n  STR_LAUNCH_MISSILE: \"发射导弹\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"单位没有足够的时间！\"\n  STR_NO_AMMUNITION_LOADED: \"未装填弹药！\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"武器已经装填！\"\n  STR_NO_LINE_OF_FIRE: \"没有射界！\"\n  STR_GRENADE_IS_ACTIVATED: \"手榴弹已被激活！\"\n  STR_GRENADE_IS_DEACTIVATED: \"手榴弹已被关闭！\"\n  STR_THERE_IS_NO_ONE_THERE: \"这里空无一人！\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"研究完成前无法使用该异形物品！\"\n  STR_OUT_OF_RANGE: \"超出射程！\"\n  STR_UNABLE_TO_THROW_HERE: \"无能在这里扔！\"\n  STR_SET_TIMER: \"设置定时器\"\n  STR_HIDDEN_MOVEMENT: \"隐蔽移动\"\n  STR_TURN: \"回合> {0}\"\n  STR_SIDE: \"侧面>{0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"按任意键继续\"\n  STR_MIND_CONTROL: \"心灵控制\"\n  STR_PANIC_UNIT: \"恐慌单位\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"士气攻击成功\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}已经进入狂暴\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}已经进入狂暴\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}感到十分惊恐\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}感到十分惊恐\"\n  STR_ALIENS: \"外星人\"\n  STR_RIGHT_HAND: \"右手\"\n  STR_LEFT_HAND: \"左手\"\n  STR_RIGHT_SHOULDER: \"右肩\"\n  STR_LEFT_SHOULDER: \"左肩\"\n  STR_BACK_PACK: \"背包\"\n  STR_BELT: \"腰带\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}已被异形精神控制\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}已被异形精神控制\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}已经伤重死亡\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}已经伤重死亡\"\n  STR_FATAL_WOUNDS: \"致命伤\"\n  STR_UNDER_ARMOR_UC: \"底部装甲\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"预留速射时间\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"预留扫射时间\"\n  STR_ABORT_MISSION_QUESTION: \"放弃任务？\"\n  STR_CORPSE: \"尸体\"\n  STR_UNLOAD_CRAFT: \"卸载\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}已被杀害\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}已被杀害\"\n  STR_HIT_MELEE: \"命中\"\n  STR_GROUND: \"着陆\"\n  STR_LIVING_QUARTERS_PLURAL: \"生活居住区\"\n  STR_LIST_ITEM: \"物品\"\n  STR_POWER_SUIT_UFOPEDIA: \"一种采用E115能源的强大新型动力护甲能大幅提高穿戴者的力量与速度，是目前科技所能提供给战斗人员的最佳护甲。\"\n  STR_FLYING_SUIT_UFOPEDIA: \"这是动力装甲的增强版本。通过使用外星人的反重力技术，它可以让士兵在战场上完全自由地移动，也以让士兵悬浮于半空。\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"所有外星人都在飞碟坠毁时死亡{NEWLINE}开始自动清理战场\"\n  MAP_CULTA: \"农场\"\n  MAP_FOREST: \"森林\"\n  MAP_JUNGLE: \"丛林\"\n  MAP_MOUNT: \"突变者\"\n  MAP_UBASE: \"外星基地\"\n  STR_REMOVE_SELECTED: \"移除所选\"\n  STR_CONTAINMENT_EXCEEDED: \"外星人收容设施容量已满！{SMALLLINE}位于{0}的收容设施容量用尽。你必须把多出来的外星人从收容设施移出，被移出的外星人将会死亡。\"\n  STR_MANAGE_CONTAINMENT: \"管理异形收容设施\"\n  STR_STORAGE_EXCEEDED: \"物品数量达到上限{SMALLLINE} {0}的存储空间不足。你必须将多余的物品售出。\"\n  STR_GO_TO_BASE: \"前往总部\"\n  STR_MELEE_ACCURACY: \"近战精度\"\n  STR_SELL_PRODUCTION: \"卖出\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"两只手都必须是空的！\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"模板中部分物品数量不足，无法复制。\"\n  STR_UNLOAD_WEAPON: \"武器退弹\"\n  STR_ALL_ITEMS: \"全部物品\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    other: \"无法继续加载更多装备！{SMALLLINE}在这个载具上，你仅可以加载 {N}件装备。 \"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}控制中心已被摧毁{NEWLINE}请前往基地入口撤离。\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"X-COM基地无法建设在水域。\"\n  STR_LEVEL_SHORT: \"{0}\"\n  STR_PERSONNEL: \"人员\"\n  STR_CRAFT_ARMAMENT: \"战机和武器\"\n  STR_COMPONENTS: \"附件\"\n  STR_SOLDIERS_RECRUITED: \"士兵已招募\"\n  STR_SOLDIERS_LOST: \"士兵阵亡\"\n  STR_TOTAL_UFOS: \"发现UFO\"\n  STR_TOTAL_ALIEN_BASES: \"已发现外星人基地\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"灵能强度\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"灵能技能\"\n  FEMALE_CIVILIAN: \"平民，女性\"\n  MALE_CIVILIAN: \"平民，男性\"\n  CYBERDISC_WEAPON: \"电盘武器\"\n  REAPER_WEAPON: \"收割者武器\"\n  CHRYSSALID_WEAPON: \"猎手武器\"\n  CELATID_WEAPON: \"腐蚀虫武器\"\n  SILACOID_WEAPON: \"自爆虫武器\"\n  SECTOPOD_WEAPON: \"长足机甲武器\"\n  ZOMBIE_WEAPON: \"僵尸武器\"\n  ALIEN_PSI_WEAPON: \"外星灵能武器\"\n"
  },
  {
    "path": "bin/standard/xcom1/Language/zh-TW.yml",
    "content": "zh-TW:\n  STR_AVENGER_UFOPEDIA: \"運輸及戰鬥兩用太空船。外星生物科技的最終複製。\"\n  STR_INTERCEPTOR_UFOPEDIA: \"使用地球現有最尖端科技製造的戰鬥機。機體裝備兩個脈衝引擎及反干擾電子系統。\"\n  STR_LIGHTNING_UFOPEDIA: \"運輸戰鬥兩用飛行器。粗糙但有效地複製自外星生物推進系統。\"\n  STR_SKYRANGER_UFOPEDIA: \"地球最高速的部隊運輸機，能夠垂直升降(V.T.O.L)。\"\n  STR_FIRESTORM_UFOPEDIA: \"參考典型的飛碟設計，推進系統安裝於中央的單座式戰鬥飛行器。\"\n  STR_STINGRAY_UFOPEDIA: \"利用最先進科技制造的空對空導彈，配有反干擾電子系統。\"\n  STR_AVALANCHE_UFOPEDIA: \"帶有核彈頭的空對空飛彈，負載極重。\"\n  STR_CANNON_UFOPEDIA: \"重火力加農砲，其穿甲彈可射穿厚達十六吋的鋼板。\"\n  STR_FUSION_BALL_UFOPEDIA: \"反物質導彈發射器，球形的導彈擊中目標後會向中心聚爆，所產生的重力波破壞力極高。\"\n  STR_LASER_CANNON_UFOPEDIA: \"這是優秀的常規雷射武器，由反物質反應腔所提供的能源產生。\"\n  STR_PLASMA_BEAM_UFOPEDIA: \"引力光束可以準確控制一種向內收縮的重力場，擊中的目標因而內爆受損。\"\n  STR_SECTOID_UFOPEDIA: \"灰人的階級涵蓋一般士兵到領導階層。{NEWLINE}它們的將領和指揮官甚至擁有強勁的心靈控制能力，這種靈能力可以在戰鬥中令敵人士氣低落，甚至控制對方的意識。它們經常從事綁架人類和屠殺牲畜的任務，綁架的目的是抽取人類遺傳基因製作混種人，以便滲透人類社會。屠殺牲畜的任務的目的是收集養份和遺傳物質。它們透過基因混合發展出更優秀的雜交體，改進它們類蜂群社會的運作效率。\"\n  STR_SECTOID_AUTOPSY: \"灰人解剖報告\"\n  STR_SECTOID_AUTOPSY_UFOPEDIA: \"解剖結果顯示，該生物擁有發育非常良好的大腦和眼睛、功能有限的小嘴和小鼻孔、退化的消化器官以及一個簡單的身體構造，其獨特的結構表明可能發生了基因突變或基因改造。手指間的蹼狀結構和扁平的脚趾顯示它可能起源於水生環境。由於它缺乏生殖器官，因此無法確定其繁殖方式，因此很可能是一項基因工程的產物。\"\n  STR_SNAKEMAN_UFOPEDIA: \"蛇人族生於惡劣環境的星球上，它們強壯得能抵禦極端溫度。它們的腹鱗及肌肉除了透過縮放產生移動力外，也可保護身體的重要器官。它們聽從其他高智慧生物的指揮進攻地球，主要從事掠奪的任務。\"\n  STR_SNAKEMAN_AUTOPSY: \"蛇人解剖報告\"\n  STR_SNAKEMAN_AUTOPSY_UFOPEDIA: \"皮膚非常堅硬和耐熱。心肺血管系統是透過肌肉系統的液壓運動進行，唯一真正的內臟是心臟。無性繁殖的生殖系統有很高的效率，它們體內能攜帶多達五十顆蛋。對它們放任不管對地球的生物來說是一個嚴重的威脅。\"\n  STR_ETHEREAL_UFOPEDIA: \"異靈族擁有強大的精神力量，能夠進行心靈感應和念力傳輸，明顯虛弱的體能是由其精神力量維持的。我們尚不清楚這些念力傳輸是如何運作的，因為它們似乎違反了我們已知的物理定律，在戰鬥中遇到這種善於使用精神力量的對手是極度危險的事情！ 它們依賴其他種族來達成任務，因此很少出現在地球上。\"\n  STR_ETHEREAL_AUTOPSY: \"異靈族解剖報告\"\n  STR_ETHEREAL_AUTOPSY_UFOPEDIA: \"從表面看，這種生物的身體機能虛弱得不足以維持生命。肌肉嚴重萎縮，內臟器官發育不良，包括眼睛在內的感官系統似乎完全喪失功能。然而腦部卻異常發達，因此需要體內大量的血液提供養份。它如何在沒有外界支持的情況下維持自身生命，至今仍是個謎。\"\n  STR_MUTON_UFOPEDIA: \"這種類人生物有強壯的體質和高智慧。它們好像地球的食肉動物一樣嗜吃生肉。異靈族似乎透過心靈感應向它們發施號令，一旦心靈感應連結中斷將會它們的精神系統崩潰並導致死亡。我們發現它們被植入神經機械系統以提高它們的作戰能力。它們顯然被更高智慧生物利用作前線士兵。\"\n  STR_MUTON_AUTOPSY: \"變異者解剖報告\"\n  STR_MUTON_AUTOPSY_UFOPEDIA: \"這種生物被植入一層由有機物製造的保護皮甲，穿甲彈對這種強韌皮膚沒三小路用。它們身體內安裝的眾多控制裝置可以增強心血管以及感官系統，生殖系統似乎經手術後被切除。綜合以上證據，我們相信這種生物不幸地被利用作侵略及戰爭棋子。\"\n  STR_CELATID_UFOPEDIA: \"這種生物擁有神秘自然能力-浮空。他可透過偵測人類的腦波，發現並降下移向匿藏的敵人，然後向目標噴出一團高腐蝕性的毒液。此外，它們能夠以驚人的速度自我複製。它們主要隨同變異者作戰。\"\n  STR_CELATID_AUTOPSY: \"腐食體解剖報告\"\n  STR_CELATID_AUTOPSY_UFOPEDIA: \"從生物力學的角度來看，這生物的核心內有一個自然進化而成的小型反重力推進系統。毒囊是它們體內最大的器官，而它們似乎並沒有獨立的大腦結構、消化器官和生殖系統。此外，我們發現在某個細小的器官內育有胚胎，這可以解釋它們為何可以快速分裂出另一個獨立的個體。\"\n  STR_SILACOID_UFOPEDIA: \"這種矽基生命體可以產生大量的熱能。它們可從容地把岩石碾成粉末，從而利用高熱的核心加以熔化並攝取所需能量。矽原體只有低等的智慧，通過植入裝置或使用心靈感應就能加以控制。它們隨同變異者一同行動。\"\n  STR_SILACOID_AUTOPSY: \"矽原體解剖報告\"\n  STR_SILACOID_AUTOPSY_UFOPEDIA: \"該生物的核心極其炙熱，似乎是其消化系統的基礎。它獨特的肌肉系統擁有巨大的力量和速度。像石頭一樣堅硬的皮膚可抵禦火焰和燃燒彈藥的攻擊。\"\n  STR_CHRYSSALID_UFOPEDIA: \"這種生物擁有猶如蟹鉗的強力近身戰鬥武器。強壯和高新陳代謝率令它們快速而靈活。雖然這鉗獵者不殺死獵物，但是會將蛋注入受害者體內，而附帶的毒液會令他們變成行屍。不需太久的時間，一隻新生的鉗獵者就會破肚而出。它們會和蛇人族一起執行任務。\"\n  STR_CHRYSSALID_AUTOPSY: \"鉗獵者解剖報告\"\n  STR_CHRYSSALID_AUTOPSY_UFOPEDIA: \"儘管這生物的外骨骼極其堅硬，然而卻意料之外地難以承受爆炸性彈藥的攻擊。它們不但大腦發達，而且細胞可快速生長。這鉗獵者可攜帶多達二十顆蛋，用以注入其他生物體內。因此，它們是非常有效的恐怖襲擊兵器。\"\n  STR_FLOATER_UFOPEDIA: \"漂浮者主要充當士兵及恐怖襲擊代理人。他們原本只掠食野獸，經過遺傳工程和神經機械學的強化後成為令敵人聞風喪膽的戰士。他們的下半身和所有內臟已用手術移除，並由生命維持系統和反重力裝置所取代。雖則有時會不大穩定，但這種族可漂浮於空中。\"\n  STR_FLOATER_AUTOPSY: \"漂浮者解剖報告\"\n  STR_FLOATER_AUTOPSY_UFOPEDIA: \"這種生物已經過手術徹底改造。構成它身體核心的裝置是一個生命維持系統，用以取代心臟、肺部及消化系統，因此它們可以在極度惡劣的環境下生存。漂浮者的腦部比人類小，可是感官器官卻非常發達。\"\n  STR_REAPER_UFOPEDIA: \"這種雙足肉食性生物擁有強而有力的顎部和極強的食慾。它的腦部植入了多個控制裝置，用於控制其行為。這種生物的原始掠食本能除了用來製造恐慌和破壞之外，幾乎沒有其他用途。收割獸通常與漂浮者一起出現。\"\n  STR_REAPER_AUTOPSY: \"收割獸解剖報告\"\n  STR_REAPER_AUTOPSY_UFOPEDIA: \"收割獸體內包含兩組「大腦」和兩組「心臟」，這使得牠們即使在遭受重創時，仍能維持運作。然而，牠們身上的毛皮具有高度易燃性，使得這種生物極易受到燃燒武器的攻擊。\"\n  STR_SECTOPOD_UFOPEDIA: \"步行機甲是一種裝有強勁電漿光束武器的機械人。異靈族透過心靈感應聯結並操控它們。毫無疑問，這種機械獸是外星生物最強勁的恐怖攻擊武器。\"\n  STR_SECTOPOD_AUTOPSY: \"步行機甲解剖報告\"\n  STR_SECTOPOD_AUTOPSY_UFOPEDIA: \"這機械人的強化裝甲製造得極為堅固，能有效抵禦包括電漿武器在內的各種攻擊。然而它的傳感電路似乎特別容易被雷射武器破壞。\"\n  STR_CYBERDISC_UFOPEDIA: \"這小型飛碟是一種自動化恐怖襲擊武器，它們不單裝備了一門威力強大的電漿光束砲，內置的反重力推進系統亦可令任何地勢都變為有利。灰人族利用這兵器從事破壞和恐怖攻擊任務。\"\n  STR_CYBERDISC_AUTOPSY: \"電腦飛碟解剖報告\"\n  STR_CYBERDISC_AUTOPSY_UFOPEDIA: \"裝有優良的防護外殼，對爆炸性彈藥的防禦尤其優秀。因為被回收的反重力系統損毀嚴重，所以我們未能研究出它的運作原理。\"\n  STR_UFO_POWER_SOURCE_UFOPEDIA: \"外星飛行器的動力來源是使用奧雷爾(第115元素)的反物質反應爐，它能產生強大的重力波和其他所需能源，而能源效益更達至驚人的99%。因此只需小量的奧雷爾就能產生大量的能源。這個動力單元可以利用外星合金輕鬆地複製。{NEWLINE}奧雷爾正是外星科技的命脈，正確的使用奧雷爾我們就能擁有幾乎無限的動力來源。我們能將這項技術運用於製造更強大的飛行器、新一代動力裝甲以及毀滅性的高能武器。\"\n  STR_UFO_NAVIGATION_UFOPEDIA: \"外星飛船利用先進的電腦系統在地球和太空航行，該系統基於網路化的光子處理器。控制介面相當簡單－操作人員只要控制由動力源產生的重力波的方向，就能讓飛行器朝任何方向移動。這套系統人類能輕鬆掌握這項技術，利用外星合金和其他零組件也能複製類似的系統。{NEWLINE}這是一項重大的突破！這不僅可能讓我們建造出足以對抗外星科技的飛行器，甚至能將這項重力波技術應用到武器或者護具上。\"\n  STR_UFO_CONSTRUCTION_UFOPEDIA: \"外星飛行器由三個主要部份構成，分別是能源供應系統、導航系統和用外星合金建造的船身。這種船身經過特別設計，可以引導並控制重力波。此外，只需少量的奧雷爾就能注滿能源供應設備。當了解它各部份功能和構造原理後，我們也可建造這些飛行器。\"\n  STR_ALIEN_FOOD_UFOPEDIA: \"這些水槽內裝有多種酵素，可消化牛隻、其他動物甚至人類的身體組織，消化後的液體會直接當作已消化的食物被吸收-很可能直接進入血液。這顯示出外星生命對於地球食物的某種依賴性，也暗示著地球與外星社會之間存在一種共生關係。\"\n  STR_ALIEN_REPRODUCTION_UFOPEDIA: \"這些水槽裝有外星生物胚胎，槽內豐富的養份可以令胚胎快速成長。我們從這些容器的設計了解到外星生物是完全倚賴實驗室繁殖的。一條生產線於短時間內就能製造數以千計的複製生物，這生產程序不單適用於繁殖人類，甚至也可製造人類與外星種族的混血兒。\"\n  STR_ALIEN_ENTERTAINMENT_UFOPEDIA: \"這些球體最可能的功能是用於娛樂。原理是透過心靈電路刺激大腦的各個中樞，從而產生類似服用迷幻藥物的效果。這是我們唯一能證明外星生物擁有文化或娛樂消遣的證據。\"\n  STR_ALIEN_SURGERY_UFOPEDIA: \"這套手術設備使用雷射切割器提取牛隻及其他動物身體的特定器官組織，這些部位很可能被用於營養或基因研究目的。世界各地廣泛發生的怪異牛隻肢解事件，就是由這種奇特的外星活動所造成的。\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"過去成千上萬的人聲稱自己遭到外星生物綁架，有些甚至被綁架多次，但這些行動背後的真相遠比綁架可怕。人類不單被劫持，研究和監視，其中最優良的個體甚至會被抽取基因物質。女性會被植入人類與外星生物的混血胚胎，並數個月後被取出。誰知道這些外星生物有什麼其他邪惡的動機呢？\"\n  STR_ALIEN_ALLOYS_UFOPEDIA: \"外星飛行器是用特別的合金建造，這金屬的性質獨一無二。它不單輕巧兼耐用，而且能用電磁方法鑄造成不同形狀。這種材料可以回收再造並使用於其他生產過程之中。\"\n  STR_ELERIUM_115_UFOPEDIA: \"這種元素具有不尋常的特性，當它受到特定粒子的撞擊時，能夠產生反物質能源，這個過程會產生重力波及其他形式的能量。此元素並非自然存在於我們的太陽系，也無法人工合成。\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"我們顯然正在地球上進行一場註定會失敗的戰鬥。外星大軍的數量多到難以招架，我們所能做的，只是盡力拖延它們的腳步。人類唯一的希望就是從源頭解決外星威脅。研究指出它們在太陽系內有一個接近地球的行動基地，外星生物供稱此地為一個比人類歷史更古老的古文明中心。我們必須盡快找到這個地方。然而，我們需要先活捉並審問外星生物領袖，從而得到更多的資訊。大型不明飛行物中很可能至少有一名外星生物首領。\"\n  STR_THE_MARTIAN_SOLUTION_UFOPEDIA: \"我們當前的研究都將外星生物活動的基地指向火星。該基地相當隱密，且涵蓋所有製造和克隆設施，為滲透地球的行動提供資源。該基地似乎配備一台控制整個行動的電腦。這種蜂巢式外星社會似乎存在某個「蜂后」，這是它們的結構性弱點-若我們能殲滅這個「大腦」，那麼整個「身體」就會隨之死亡。我們必須在為時已晚前，加快研究腳步。{NEWLINE}{NEWLINE}為了讓計畫有所進展，我們必須捕捉軍階最高的外星生物-指揮官，它們只會出現在外星基地和戰鬥艦中。\"\n  STR_CYDONIA_OR_BUST_UFOPEDIA: \"我們現在非常清楚，外星大軍是由火星上一個名為「塞東尼亞」的地下基地控制。這個不尋常的區域有多個五面金字塔和一塊類似人臉的巨大構造。塞東尼亞文明在幾百萬年前的火星上曾經盛極一時，但我們不清楚它為何滅亡，也不明白它與最近的外星活動有何關聯。無論原因為何，我們一定要派遣一支遠征隊進攻塞東尼亞，摧毀那個控制一切的「主腦」，這是消滅這些不速之客的唯一方法。{NEWLINE}{NEWLINE}我們需要一架復仇者飛行器，並帶上我們所能掌握的最強大與最具毀滅性的武器，我們在地球上已無法獲得更多資訊-靜待進攻塞東尼亞的結果。\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"置中該地-時間流逝=5秒\"\n  STR_CANCEL_UC: \"取消\"\n  STR_NONE: \"沒有\"\n  STR_UNKNOWN: \"不詳\"\n  STR_POOR: \"差\"\n  STR_AVERAGE: \"普通\"\n  STR_GOOD: \"良好\"\n  STR_EXCELLENT: \"優秀\"\n  STR_BUILD_NEW_BASE_UC: \"建設新基地\"\n  STR_BASE_INFORMATION: \"基地資訊\"\n  STR_EQUIP_CRAFT: \"裝備飛行器\"\n  STR_BUILD_FACILITIES: \"增建設施\"\n  STR_RESEARCH: \"研究\"\n  STR_MANUFACTURE: \"生產\"\n  STR_TRANSFER_UC: \"運輸\"\n  STR_PURCHASE_RECRUIT: \"購買/招募\"\n  STR_SACK: \"解雇\"\n  STR_SELL_SACK_UC: \"出售/解雇\"\n  STR_GEOSCAPE_UC: \"全球介面\"\n  STR_NAME: \"名稱\"\n  STR_AREA: \"地區\"\n  STR_BUILD_NEW_BASE: \"建設新基地\"\n  STR_CANCEL: \"取消\"\n  STR_COST_UC: \"成本>\"\n  STR_CONSTRUCTION_TIME_UC: \"建造需時>\"\n  STR_DAY:\n    other: \"{N} 日\"\n  STR_HOUR:\n    other: \"{N}小時\"\n  STR_MAINTENANCE_UC: \"維修>\"\n  STR_OK: \"確定\"\n  STR_INSTALLATION: \"設施\"\n  STR_CURRENT_RESEARCH: \"目前研究項目\"\n  STR_SCIENTISTS_AVAILABLE: \"可用的科學家>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"已配置的科學家>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"可用的實驗室空間>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"研究專案\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"已配置的科學家\"\n  STR_PROGRESS: \"進展\"\n  STR_NEW_PROJECT: \"新專案\"\n  STR_CANCEL_PROJECT: \"取消專案\"\n  STR_NEW_RESEARCH_PROJECTS: \"新研究專案\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"可用的科學家>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"可用的實驗室空間>{ALT}{0}\"\n  STR_INCREASE: \"增加\"\n  STR_DECREASE: \"減少\"\n  STR_START_PROJECT: \"開始專案\"\n  STR_CURRENT_PRODUCTION: \"目前生產項目\"\n  STR_ENGINEERS_AVAILABLE: \"可用的工程師>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"已分配工作的工程師>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"可用的工作室空間>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"現有資金>{ALT}{0}\"\n  STR_ITEM: \"物品\"\n  STR_ENGINEERS__ALLOCATED: \"已分配工作的工程師\"\n  STR_UNITS_PRODUCED: \"已生產單位\"\n  STR_TOTAL_TO_PRODUCE: \"生產總數\"\n  STR_COST__PER__UNIT: \"每單位{NEWLINE}成本{NEWLINE}\"\n  STR_DAYS_HOURS_LEFT: \"尚餘日/小時\"\n  STR_NEW_PRODUCTION: \"新生產\"\n  STR_PRODUCTION_ITEMS: \"生產物品\"\n  STR_CATEGORY: \"類別\"\n  STR_START_PRODUCTION: \"開始新產\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"工程師毎 {0} 小時生産一個單位\"\n  STR_COST_PER_UNIT_: \"每單位成本>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"所需工作空間>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"所需特別材料\"\n  STR_ITEM_REQUIRED: \"所需物品\"\n  STR_UNITS_REQUIRED: \"所需單位\"\n  STR_UNITS_AVAILABLE: \"可用單位\"\n  STR_STOP_PRODUCTION: \"停止生產\"\n  STR_ENGINEERS_AVAILABLE_UC: \"可用的工程師>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"可用的工作室空間>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"月利潤>{ALT}{0}\"\n  STR_INCREASE_UC: \"增加\"\n  STR_DECREASE_UC: \"減少\"\n  STR_UNITS_TO_PRODUCE: \"要製造的單位\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"購買/招募人員\"\n  STR_COST_OF_PURCHASES: \"購買成本>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"每單位成本\"\n  STR_QUANTITY_UC: \"庫存數量\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"可用人員:人員總數>\"\n  STR_SOLDIERS: \"士兵\"\n  STR_SCIENTISTS: \"科學家\"\n  STR_ENGINEERS: \"工程師\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"已使用空間:總可用空間>\"\n  STR_LIVING_QUARTERS: \"居住區\"\n  STR_STORES: \"倉庫\"\n  STR_LABORATORIES: \"實驗室\"\n  STR_WORK_SHOPS: \"工作室\"\n  STR_HANGARS: \"停機棚\"\n  STR_SHORT_RANGE_DETECTION: \"短程偵測\"\n  STR_DEFENSE_STRENGTH: \"防禦力\"\n  STR_TRANSFERS_UC: \"運輸\"\n  STR_TRANSFERS: \"運輸\"\n  STR_ARRIVAL_TIME_HOURS: \"送達時間 (小時)\"\n  STR_COST_: \"成本>{ALT}{0}\"\n  STR_AREA_: \"地區>{ALT}{0}\"\n  STR_BASE_NAME: \"基地名稱?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"選擇入口電梯的位置\"\n  STR_TRANSFER: \"運輸\"\n  STR_AMOUNT_TO_TRANSFER: \"    轉移量\"\n  STR_SELECT_DESTINATION_BASE: \"選擇目的基地\"\n  STR_COST: \"成本\"\n  STR_VICTORY_1: \"當你進入控制室後便看到今次任務的目標-外星主腦。當你準備開火時它透過基地顯示器和你溝通,並懇求你在扣下扳機前聆聽它的說話......\"\n  STR_VICTORY_2: \"主腦說:'這個被你們稱作火星的行星在好幾百萬年前生機蓬勃 ，我們的文明在這個貧瘠的星球播下生命的種子，在最近的幾百萬年我們多次到達地球並用基因技術栽培出人類。你們不能殺死我們 ，因為你們是我們一份子......'\"\n  STR_VICTORY_3: \"這裏是火星文明的中心，這些金字塔的歷史比你們的還早幾百萬年，是由你們的遠古祖先建造的。而你們也將會獲得他們的力量，因此沒有哪個星球是不能到達的。我們只需要你們的合作......\"\n  STR_GAME_OVER_1: \"外星生物決意滅絶全人類，摧毀都市、汙染空氣和海洋。面對遠超過人類的科技，地球軍隊只能絶望地抵抗。倖存下來的幾代人在躲避外星人的破壞過程中發生了可怕的基因變異。他們被外星生物囚禁起來當做奴隸，並協助將地球改造成某個未知外星帝國的殖民地。\"\n  STR_GAME_OVER_2: \"透過X-Com計畫獲得的知識將永遠消失。{NEWLINE}很遺憾您未能拯救地球。\"\n  STR_VICTORY_4: \"外星主腦被一陣熾熱的電漿光束擊穿，而整個外星軍隊也被擊敗。\"\n  STR_VICTORY_5: \"若外星生物失去了火星也就失去了地球。不久之後X-Com的研究再次讓人類重返榮光，並取得了火星。外星生物的威脅已經消失，但沒人知道能持續多久...\"\n  STR_YOU_HAVE_FAILED: \"你不能制止外星生物對地球各國猛烈的進攻。一個又一個的資金提供國和外星生物簽訂條約，以換取外星的先進技術，以及保證的繁榮與和平。可是人類很快便發覺它們另有所圖......\"\n  STR_TOTAL_UC: \"總數\"\n  STR_INCOME: \"收入\"\n  STR_EXPENDITURE: \"支出\"\n  STR_MAINTENANCE: \"維修\"\n  STR_BALANCE: \"結餘\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"各區域的ＵＦＯ活動\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"各國的ＵＦＯ活動\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"Ｘ-ＣＯＭ各區域的活動\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"Ｘ-ＣＯＭ各國家的活動\"\n  STR_FINANCE: \"財務狀況\"\n  STR_DATE_FIRST: \"{0}日\"\n  STR_DATE_SECOND: \"{0}日\"\n  STR_DATE_THIRD: \"{0}日\"\n  STR_DATE_FOURTH: \"{0}日\"\n  STR_FINANCE_THOUSANDS: \"單位仟元\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"{1}{NEWLINE}生產的項目{NEWLINE}{0}{NEWLINE}特殊材料不足\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"{1}{NEWLINE}生產的項目{NEWLINE}{0}{NEWLINE}金錢不足\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"{1}{NEWLINE}生產的項目{NEWLINE}{0}{NEWLINE}已完成\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"{1}{NEWLINE}增建的設施{NEWLINE}{0}{NEWLINE}已完成\"\n  STR_OK_5_SECONDS: \"確定 - 5 秒\"\n  STR_RESEARCH_COMPLETED: \"研究完成\"\n  STR_VIEW_REPORTS: \"觀看報告\"\n  STR_WE_CAN_NOW_RESEARCH: \"我們可以開始研究\"\n  STR_WE_CAN_NOW_PRODUCE: \"我們可以開始生產\"\n  STR_SUNDAY: \"星期日\"\n  STR_MONDAY: \"星期一\"\n  STR_TUESDAY: \"星期二\"\n  STR_WEDNESDAY: \"星期三\"\n  STR_THURSDAY: \"星期四\"\n  STR_FRIDAY: \"星期五\"\n  STR_SATURDAY: \"星期六\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"{2} 基地{NEWLINE}{1} 飛行器{NEWLINE}{0} 燃料不足\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"{2} 基地{NEWLINE}{1} 飛行器{NEWLINE}{0} 備料不足\"\n  STR_UFO_IS_NOT_RECOVERED: \"回收UFO失敗\"\n  STR_UFO_IS_RECOVERED: \"成功回收UFO\"\n  STR_CRAFT_IS_LOST: \"損失運兵飛行器\"\n  STR_TERROR_CONTINUES: \"未能制止恐怖活動\"\n  STR_ALIENS_DEFEATED: \"外星生物被擊敗\"\n  STR_BASE_IS_LOST: \"失去基地\"\n  STR_BASE_IS_SAVED: \"成功守護基地\"\n  STR_ALIEN_BASE_STILL_INTACT: \"外星基地未被破壞\"\n  STR_ALIEN_BASE_DESTROYED: \"外星基地被消滅\"\n  STR_ALIENS_KILLED: \"殺死的外星生物\"\n  STR_ALIEN_CORPSES_RECOVERED: \"回收的外星生物屍體\"\n  STR_LIVE_ALIENS_RECOVERED: \"活捉的外星生物\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"回收的外星物品\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"外星基地控制系統被破壞\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"被外星生物殺死的平民\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"X-COM作業人員誤殺的平民\"\n  STR_CIVILIANS_SAVED: \"救出的平民\"\n  STR_XCOM_OPERATIVES_KILLED: \"被殺的X-COM作業人員\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"失蹤的X-COM作業人員\"\n  STR_TANKS_DESTROYED: \"被摧毀的戰車\"\n  STR_XCOM_CRAFT_LOST: \"失去的X-COM飛行器\"\n  STR_UFO_RECOVERY: \"UFO回收物\"\n  STR_ALIEN_BASE_RECOVERY: \"回收的外星基地物資\"\n  STR_BASE_UNDER_ATTACK: \"{0} 遭受襲撃！\"\n  STR_BASE_DEFENSES_INITIATED: \"啟動基地防衛設置\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"重力防護罩抵禦了UFO！\"\n  STR_FIRING: \"開火中\"\n  STR_HIT: \"擊中！\"\n  STR_UFO_DESTROYED: \"UFO被消滅！\"\n  STR_MISSED: \"沒有命中！\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"出售物品/解雇人員\"\n  STR_VALUE_OF_SALES: \"出售價值>{ALT}{0}\"\n  STR_FUNDS: \"基金>{ALT}{0}\"\n  STR_SELL_SACK: \"出售/解雇\"\n  STR_VALUE: \"價值\"\n  STR_CRAFT_: \"飛行器> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"回收墜毀的UFO\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"注意-UFO内或墜機地點周圍可能有外星生物。當所有敵方單位被殲滅或失去戰意，任務即成功。之後就會開始回收UFO殘骸、外星生物物品及屍體。{NEWLINE}{NEWLINE}若要中止任務，請先將X-Com作戰人員返回運輸飛行器後再點選「中止任務」圖示。\"\n  STR_UFO_GROUND_ASSAULT: \"UFO地面襲擊戰\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"探索著陸地點並盡可能進入UFO內部。當所有敵方單位被殲滅或失去戰意，任務即成功。之後就會開始回收UFO、外星生物物品及屍體。{NEWLINE}{NEWLINE}若要中止任務，請先將X-Com作戰人員返回飛行器後再點選「中止任務」圖示。\"\n  STR_BASE_DEFENSE: \"基地防禦\"\n  STR_BASE_UC_: \"基地> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"一架外星生物飛行器降落在附近。我們的基地遭遇極大危機。所有非戰鬥人員和飛行器已避難。外星生物單位會透過停機棚和電梯進入基地。竭盡全力防衛基地和其相關設備，非戰即死。若點擊放棄任務，就會失去基地。\"\n  STR_ALIEN_BASE_ASSAULT: \"突襲外星基地\"\n  STR_ALIEN_BASE_ASSAULT_BRIEFING: \"X-COM特工已成功潛入外星基地，摧毀控制中心即可使基地失效。{NEWLINE}{NEWLINE}本次任務將在下列任一條件達成時終止：{NEWLINE} 1.消滅所有敵方單位。{NEWLINE} 2.您的戰術小隊成功撤退至綠色撤離區域再點擊「中止任務」圖示即可逃脱。\"\n  STR_CYDONIA_BRIEFING: \"你已到達火星塞東尼亞區，現在可以進入火星獅身人面像附近的大型地下建築群。{NEWLINE}必需破壞控制所有外星生物活動的主腦。全人類的命運就掌握在X-Com手中.....\"\n  STR_TERROR_MISSION: \"反恐任務\"\n  STR_TERROR_MISSION_BRIEFING: \"當所有敵方單位被殲滅或失去戰意，任務即成功。{NEWLINE}你必須試圖透過消除外來威脅來拯救該地區所有平民的生命。{NEWLINE}{NEWLINE}若要中止任務，請先將X-Com作戰人員返回飛行器後再點選「中止任務」圖示。\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"沒有額外的停機棚可用作生產飛行器！{SMALLLINE}每架分配到基地、轉移到基地、購買或建造的飛行器，都需要佔用一個停機棚，請建造一個新停機棚或者轉移現役飛行器至其他基地。\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"沒有額外的停機棚可用作安置新購飛行器{SMALLLINE}每架分配到基地、轉移到基地、購買或建造的飛行器，都需要佔用一個停機棚，請建造一個新停機棚或者轉移現役飛行器至其他基地。\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"沒有額外的停機棚可用作轉移戰機！{SMALLLINE}每架分配到基地、轉移到基地、購買或建造的飛行器，都需要佔用一個停機棚，請建造一個新停機棚或者移轉現役戰機至其他基地。\"\n  STR_CANNOT_BUILD_HERE: \"不能在這裏蓋設施！{SMALLLINE}你必須蓋在現有基地設施旁。\"\n  STR_NO_FREE_ACCOMODATION: \"沒有額外的居住空間！{SMALLLINE}目的地居住區沒有足夠空間。\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"沒有額外的工作空間 ！{SMALLLINE}蓋一間新工作室或減少其他方案的工作量。\"\n  STR_NOT_ENOUGH_MONEY: \"資金不足！\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"儲物空間不足！{SMALLLINE}蓋新的儲物設施或將這裏的物資轉移至其他基地。\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"居住空間不足！{SMALLLINE}蓋新住宅區或將人員調往其他基地。\"\n  STR_LAUNCH_INTERCEPTION: \"派機攔截\"\n  STR_CRAFT: \"飛行器\"\n  STR_STATUS: \"狀態\"\n  STR_BASE: \"基地\"\n  STR_READY: \"待命\"\n  STR_OUT: \"外出\"\n  STR_REPAIRS: \"維修中\"\n  STR_REFUELLING: \"燃料補給中\"\n  STR_REARMING: \"武器裝填中\"\n  STR_TARGET: \"目標: {0}\"\n  STR_WAY_POINT: \"航點\"\n  STR_ARE_YOU_SURE_CYDONIA: \"確定要派這架飛行器到塞東尼亞去執行任務？\"\n  STR_YES: \"是\"\n  STR_NO: \"否\"\n  STR_SELECT_DESTINATION: \"選擇目的地\"\n  STR_CYDONIA: \"塞東尼亞\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"選擇建造新基地的地點\"\n  STR_RETURN_TO_BASE: \"返回基地\"\n  STR_SELECT_NEW_TARGET: \"選擇新目標\"\n  STR_PATROL: \"巡邏\"\n  STR_STATUS_: \"狀態>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"受損 - 返回基地\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"燃料將用盡 - 返回基地\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"任務完成 - 返回基地\"\n  STR_PATROLLING: \"巡邏中\"\n  STR_TAILING_UFO: \"跟蹤UFO\"\n  STR_INTERCEPTING_UFO: \"攔截UFO-{0}\"\n  STR_RETURNING_TO_BASE: \"返回基地\"\n  STR_DESTINATION_UC_: \"目標: {0}\"\n  STR_BASE_UC: \"基地>{ALT}{0}\"\n  STR_SPEED_: \"速度>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"最高速度>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"高度>{ALT}{0}\"\n  STR_VERY_LOW: \"很低\"\n  STR_LOW_UC: \"低\"\n  STR_HIGH_UC: \"高\"\n  STR_VERY_HIGH: \"很高\"\n  STR_FUEL: \"燃料>{ALT}{0}\"\n  STR_WEAPON_ONE: \"武器-1>{ALT}{0}\"\n  STR_NONE_UC: \"無\"\n  STR_ROUNDS_: \"子彈量>{ALT}{0}\"\n  STR_WEAPON_TWO: \"武器-2>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"攔截機\"\n  STR_BASE_: \"基地>{0}\"\n  STR_NAME_UC: \"名稱\"\n  STR_AMMO_: \"彈藥>{ALT}{0}\"\n  STR_CREW: \"人員\"\n  STR_EQUIPMENT_UC: \"裝備\"\n  STR_ARMOR: \"裝甲\"\n  STR_MAX: \"最大>{ALT}{0}\"\n  STR_ROOKIE: \"菜鳥\"\n  STR_SQUADDIE: \"二兵\"\n  STR_SERGEANT: \"中士\"\n  STR_CAPTAIN: \"上尉\"\n  STR_COLONEL: \"上校\"\n  STR_COMMANDER: \"指揮官\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"選擇 {0} 的小隊\"\n  STR_SORT_BY: \"排序依據的項目\"\n  STR_ORIGINAL_ORDER: \"原始排序\"\n  STR_MISSIONS2: \"任務\"\n  STR_KILLS2: \"撃殺\"\n  STR_WOUND_RECOVERY2: \"康復需時\"\n  STR_SPACE_AVAILABLE: \"尚餘空間>{ALT}{0}\"\n  STR_SPACE_USED: \"佔用空間>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"佔用空間\"\n  STR_RANK: \"軍階\"\n  STR_WOUNDED: \"受傷\"\n  STR_EQUIPMENT_FOR_CRAFT: \"{0} 的裝備\"\n  STR_DEFENSE_VALUE: \"防禦值\"\n  STR_HIT_RATIO: \"命中率\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}準備好{NEWLINE}降落在{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"開始任務？\"\n  STR_SELECT_ARMAMENT: \"選擇艦載武器\"\n  STR_AMMUNITION_AVAILABLE: \"可用彈藥\"\n  STR_ARMAMENT: \"艦載武器\"\n  STR_NOT_AVAILABLE: \"--\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"選擇護甲{NEWLINE}{0}\"\n  STR_TYPE: \"型號\"\n  STR_PERSONAL_ARMOR_UC: \"個人護甲\"\n  STR_POWER_SUIT_UC: \"強力護甲\"\n  STR_FLYING_SUIT_UC: \"飛行護甲\"\n  STR_SELECT_ARMOR: \"選擇護甲\"\n  STR_NORTH: \"北\"\n  STR_NORTH_EAST: \"東北\"\n  STR_EAST: \"東\"\n  STR_SOUTH_EAST: \"東南\"\n  STR_SOUTH: \"南\"\n  STR_SOUTH_WEST: \"西南\"\n  STR_WEST: \"西\"\n  STR_NORTH_WEST: \"西北\"\n  STR_SELECT_ACTION: \"行動選擇\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"繼續追蹤並攔截\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"只追蹤但不攔截\"\n  STR_VERY_LARGE: \"非常巨大\"\n  STR_LARGE: \"大\"\n  STR_MEDIUM_UC: \"中\"\n  STR_SMALL: \"小\"\n  STR_VERY_SMALL: \"很小\"\n  STR_GROUNDED: \"地面\"\n  STR_DETECTED: \"偵測到的訊息：\"\n  STR_SIZE_UC: \"大小\"\n  STR_ALTITUDE: \"高度\"\n  STR_HEADING: \"航向\"\n  STR_SPEED: \"速度\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"UFO置中-時間流逝=5秒\"\n  STR_TRACKING_LOST: \"失去蹤影\"\n  STR_REDIRECT_CRAFT: \"重新指示飛行器航向\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"前往UFO最後已知位置\"\n  STR_UFO_: \"UFO-{0}\"\n  STR_ALIEN_BASE_: \"外星生物基地-{0}\"\n  STR_CRASH_SITE_: \"墜毀地點-{0}\"\n  STR_LANDING_SITE_: \"著陸地點-{0}\"\n  STR_WAY_POINT_: \"航點-{0}\"\n  STR_TERROR_SITE: \"恐怖襲擊地點-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}已抵達{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"開始巡邏\"\n  STR_ALIEN_ORIGINS: \"外星生物起源\"\n  STR_THE_MARTIAN_SOLUTION: \"火星解決方案\"\n  STR_CYDONIA_OR_BUST: \"往塞東尼亞決一死戰\"\n  STR_UFOPAEDIA: \"ＵＦＯ百科全書\"\n  STR_XCOM_CRAFT_ARMAMENT: \"X-COM 飛行器和艦載火力\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"重型武器平台(HWP)\"\n  STR_WEAPONS_AND_EQUIPMENT: \"武器和設備\"\n  STR_ALIEN_ARTIFACTS: \"外星物品\"\n  STR_BASE_FACILITIES: \"基地設施\"\n  STR_ALIEN_LIFE_FORMS: \"外星生物的生命形態\"\n  STR_ALIEN_RESEARCH_UC: \"研究外星生物\"\n  STR_UFO_COMPONENTS: \"UFO的組成部件\"\n  STR_UFOS: \"UFO\"\n  STR_SELECT_ITEM: \"選擇物品\"\n  STR_ACCELERATION: \"加速度>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"燃料容量>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"武器架>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"裝甲防禦力>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"可載人員>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"可載HWP>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"破壞力\"\n  STR_RANGE: \"射程\"\n  STR_KILOMETERS: \"{0} 公里\"\n  STR_ACCURACY: \"命中率\"\n  STR_RE_LOAD_TIME: \"裝填時長\"\n  STR_SECONDS: \"{0}s\"\n  STR_DAMAGE_ARMOR_PIERCING: \"穿甲傷害\"\n  STR_DAMAGE_INCENDIARY: \"燃燒傷害\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"高爆傷害\"\n  STR_DAMAGE_LASER_BEAM: \"雷射光束傷害\"\n  STR_DAMAGE_PLASMA_BEAM: \"電漿光束傷害\"\n  STR_DAMAGE_STUN: \"眩暈傷害\"\n  STR_DAMAGE_MELEE: \"肉搏傷害\"\n  STR_DAMAGE_ACID: \"酸蝕傷害\"\n  STR_DAMAGE_SMOKE: \"煙霧傷害\"\n  STR_SHOT_TYPE: \"射擊種類\"\n  STR_ACCURACY_UC: \"命中率\"\n  STR_TIME_UNIT_COST: \"花費TU\"\n  STR_DAMAGE_UC: \"破壞力\"\n  STR_AMMO: \"彈藥\"\n  STR_SHOT_TYPE_AUTO: \"自動射擊\"\n  STR_SHOT_TYPE_SNAP: \"快速射擊\"\n  STR_SHOT_TYPE_AIMED: \"精準射擊\"\n  STR_CONSTRUCTION_TIME: \"建造需時\"\n  STR_CONSTRUCTION_COST: \"建造成本\"\n  STR_MAINTENANCE_COST: \"維修成本\"\n  STR_LOW: \"低\"\n  STR_MEDIUM: \"中\"\n  STR_HIGH: \"高\"\n  STR_CRAFT_WEAPON: \"戰機武器\"\n  STR_CRAFT_AMMUNITION: \"戰機彈藥\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"重型武器平台(HWP)\"\n  STR_WEAPON: \"武器\"\n  STR_AMMUNITION: \"彈藥\"\n  STR_EQUIPMENT: \"設備\"\n  STR_ALIEN_CORPSE: \"外星生物屍體\"\n  STR_UFO_COMPONENT: \"UFO的組成部件\"\n  STR_PERSONAL_ARMOR: \"個人護甲\"\n  STR_RAW_MATERIALS: \"原料\"\n  STR_HWP_CANNON_SHELLS: \"HWP加農砲彈\"\n  STR_ALIEN: \"外星生物\"\n  STR_SECTOID: \"灰人\"\n  STR_SNAKEMAN: \"蛇人\"\n  STR_ETHEREAL: \"異靈族\"\n  STR_MUTON: \"變異者\"\n  STR_FLOATER: \"漂浮者\"\n  STR_CELATID: \"腐蝕體\"\n  STR_SILACOID: \"矽原體\"\n  STR_CHRYSSALID: \"鉗獵者\"\n  STR_ZOMBIE: \"殭屍\"\n  STR_REAPER: \"收割獸\"\n  STR_SECTOPOD: \"步行機甲\"\n  STR_CYBERDISC: \"電腦飛碟\"\n  STR_LIVE_COMMANDER: \" 指揮官\"\n  STR_LIVE_LEADER: \" 將領\"\n  STR_LIVE_ENGINEER: \" 工程師\"\n  STR_LIVE_MEDIC: \" 軍醫\"\n  STR_LIVE_NAVIGATOR: \" 領航員\"\n  STR_LIVE_SOLDIER: \" 士兵\"\n  STR_LIVE_TERRORIST: \" 執行恐襲單位\"\n  STR_FLOATER_SOLDIER: \"漂浮者士兵\"\n  STR_FLOATER_NAVIGATOR: \"漂浮者領航員\"\n  STR_FLOATER_MEDIC: \"漂浮者軍醫\"\n  STR_FLOATER_ENGINEER: \"漂浮者工程師\"\n  STR_FLOATER_LEADER: \"漂浮者將領\"\n  STR_FLOATER_COMMANDER: \"漂浮者指揮官\"\n  STR_SECTOID_SOLDIER: \"灰人士兵\"\n  STR_SECTOID_NAVIGATOR: \"灰人導航員\"\n  STR_SECTOID_MEDIC: \"灰人醫兵\"\n  STR_SECTOID_ENGINEER: \"灰人工程師\"\n  STR_SECTOID_LEADER: \"灰人將領\"\n  STR_SECTOID_COMMANDER: \"灰人指揮官\"\n  STR_SNAKEMAN_SOLDIER: \"蛇人士兵\"\n  STR_SNAKEMAN_NAVIGATOR: \"蛇人導航者\"\n  STR_SNAKEMAN_ENGINEER: \"蛇人工程師\"\n  STR_SNAKEMAN_LEADER: \"蛇人將領\"\n  STR_SNAKEMAN_COMMANDER: \"蛇人指揮官\"\n  STR_MUTON_SOLDIER: \"變異者士兵\"\n  STR_MUTON_NAVIGATOR: \"變異者導航員\"\n  STR_MUTON_ENGINEER: \"變異者工程師\"\n  STR_ETHEREAL_SOLDIER: \"異靈族士兵\"\n  STR_ETHEREAL_LEADER: \"異靈族將領\"\n  STR_ETHEREAL_COMMANDER: \"異靈族指揮官\"\n  STR_CYBERDISC_TERRORIST: \"電腦飛碟恐怖分子\"\n  STR_REAPER_TERRORIST: \"收割獸恐怖分子\"\n  STR_CHRYSSALID_TERRORIST: \"鉗獵者恐怖分子\"\n  STR_CELATID_TERRORIST: \"腐蝕體恐怖分子\"\n  STR_SILACOID_TERRORIST: \"矽原體恐怖分子\"\n  STR_SECTOPOD_TERRORIST: \"步行機甲恐怖分子\"\n  STR_UFO_POWER_SOURCE: \"UFO的動力來源\"\n  STR_UFO_NAVIGATION: \"UFO的導航系統\"\n  STR_UFO_CONSTRUCTION: \"UFO的結構\"\n  STR_ALIEN_FOOD: \"外星生物的食物\"\n  STR_ALIEN_REPRODUCTION: \"外星生物的繁殖\"\n  STR_ALIEN_ENTERTAINMENT: \"外星生物的娛樂\"\n  STR_ALIEN_SURGERY: \"外星生物的手術室\"\n  STR_EXAMINATION_ROOM: \"外星生物的檢驗室\"\n  STR_ALIEN_ALLOYS: \"外星合金\"\n  STR_ALIEN_HABITAT: \"外星生物的原居地\"\n  STR_POWER_SUIT: \"強力護甲\"\n  STR_FLYING_SUIT: \"飛行護甲\"\n  STR_HWP_ROCKETS: \"HWP用飛彈\"\n  STR_HWP_FUSION_BOMB: \"HWP用熱核彈\"\n  STR_LASER_WEAPONS: \"雷射武器\"\n  STR_NEW_FIGHTER_CRAFT: \"新型戰鬥機\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"新型戰鬥運兵機\"\n  STR_ULTIMATE_CRAFT: \"終極戰鬥機\"\n  STR_LASER_PISTOL: \"雷射手槍\"\n  STR_LASER_RIFLE: \"雷射步槍\"\n  STR_HEAVY_LASER: \"重型雷射步槍\"\n  STR_LASER_CANNON: \"雷射加農砲\"\n  STR_PLASMA_CANNON: \"電漿加農砲\"\n  STR_FUSION_MISSILE: \"熱核導彈\"\n  STR_LASER_DEFENSE: \"雷射防禦工事\"\n  STR_PLASMA_DEFENSE: \"電漿防禦工事\"\n  STR_FUSION_DEFENSE: \"熱核防護\"\n  STR_GRAV_SHIELD: \"重力防護罩\"\n  STR_MIND_SHIELD: \"精神防護罩\"\n  STR_PSI_LAB: \"念力研究室\"\n  STR_MOTION_SCANNER: \"移動物掃描機\"\n  STR_MEDI_KIT: \"醫療工具箱\"\n  STR_TANK_CANNON: \"坦克/加農砲\"\n  STR_TANK_ROCKET_LAUNCHER: \"坦克/飛彈發射器\"\n  STR_TANK_LASER_CANNON: \"坦克/雷射加農砲\"\n  STR_HOVERTANK_PLASMA: \"浮空坦克/電漿\"\n  STR_HOVERTANK_LAUNCHER: \"浮空坦克/飛彈發射器\"\n  STR_STINGRAY_LAUNCHER: \"魔鬼魚導彈發射器\"\n  STR_AVALANCHE_LAUNCHER: \"雪崩導彈發射器\"\n  STR_CANNON: \"加農砲\"\n  STR_FUSION_BALL_LAUNCHER: \"熱核彈發射器\"\n  STR_PLASMA_BEAM: \"電漿加農砲\"\n  STR_STINGRAY_MISSILES: \"魔鬼魚導彈\"\n  STR_AVALANCHE_MISSILES: \"雪崩導彈\"\n  STR_CANNON_ROUNDS_X50: \"加農砲彈藥(x50)\"\n  STR_FUSION_BALL: \"熱核彈\"\n  STR_SOLDIER: \"士兵\"\n  STR_SCIENTIST: \"科學家\"\n  STR_ENGINEER: \"工程師\"\n  STR_NORTH_AMERICA: \"北美\"\n  STR_ARCTIC: \"北極圈\"\n  STR_ANTARCTICA: \"南極洲\"\n  STR_SOUTH_AMERICA: \"南美\"\n  STR_EUROPE: \"歐洲\"\n  STR_NORTH_AFRICA: \"北非\"\n  STR_SOUTHERN_AFRICA: \"南非\"\n  STR_CENTRAL_ASIA: \"中亞\"\n  STR_SOUTH_EAST_ASIA: \"東南亞\"\n  STR_SIBERIA: \"西伯利亞\"\n  STR_AUSTRALASIA: \"澳大利亞\"\n  STR_PACIFIC: \"太平洋\"\n  STR_NORTH_ATLANTIC: \"北大西洋\"\n  STR_SOUTH_ATLANTIC: \"南大西洋\"\n  STR_INDIAN_OCEAN: \"印度洋\"\n  STR_ALIEN_RESEARCH: \"外星研究行動\"\n  STR_ALIEN_HARVEST: \"外星收割行動\"\n  STR_ALIEN_ABDUCTION: \"外星綁架行動\"\n  STR_ALIEN_INFILTRATION: \"外星滲透行動\"\n  STR_ALIEN_BASE: \"外星生物基地\"\n  STR_ALIEN_TERROR: \"外星恐嚇行動\"\n  STR_ALIEN_RETALIATION: \"外星報復行動\"\n  STR_ALIEN_SUPPLY: \"外星物資供應\"\n  STR_MAXIMUM_SPEED: \"最高速度\"\n  STR_HYPER_WAVE_DECODER_UC: \"超電波解碼儀\"\n  STR_SKYRANGER: \"天空漫遊者\"\n  STR_LIGHTNING: \"閃電\"\n  STR_AVENGER: \"復仇者\"\n  STR_INTERCEPTOR: \"攔截者\"\n  STR_FIRESTORM: \"烈焰風暴\"\n  STR_UFO: \"ＵＦＯ\"\n  STR_STINGRAY: \"魔鬼魚導彈\"\n  STR_AVALANCHE: \"雪崩導彈\"\n  STR_CANNON_UC: \"加農砲\"\n  STR_FUSION_BALL_UC: \"熱核彈\"\n  STR_LASER_CANNON_UC: \"雷射光束砲\"\n  STR_PLASMA_BEAM_UC: \"電漿光束砲\"\n  STR_DAMAGE_CAPACITY: \"裝甲防禦力\"\n  STR_WEAPON_POWER: \"武器威力\"\n  STR_WEAPON_RANGE: \"武器射程\"\n  STR_ACCESS_LIFT: \"入口電梯\"\n  STR_LABORATORY: \"實驗室\"\n  STR_WORKSHOP: \"工作室\"\n  STR_SMALL_RADAR_SYSTEM: \"小型雷達系統\"\n  STR_LARGE_RADAR_SYSTEM: \"大型雷達系統\"\n  STR_MISSILE_DEFENSES: \"導彈防禦系統\"\n  STR_GENERAL_STORES: \"通用儲物倉庫\"\n  STR_ALIEN_CONTAINMENT: \"外星生物收容室\"\n  STR_LASER_DEFENSES: \"雷射防禦系統\"\n  STR_PLASMA_DEFENSES: \"電漿防禦系統\"\n  STR_FUSION_BALL_DEFENSES: \"熱核彈防禦系統\"\n  STR_PSIONIC_LABORATORY: \"念力研究室\"\n  STR_HYPER_WAVE_DECODER: \"超電波解碼儀\"\n  STR_HANGAR: \"停機棚\"\n  STR_USA: \"美國\"\n  STR_RUSSIA: \"俄羅斯\"\n  STR_UK: \"英國\"\n  STR_FRANCE: \"法國\"\n  STR_GERMANY: \"德國\"\n  STR_ITALY: \"意大利\"\n  STR_SPAIN: \"西班牙\"\n  STR_CHINA: \"中國\"\n  STR_JAPAN: \"日本\"\n  STR_INDIA: \"印度\"\n  STR_BRAZIL: \"巴西\"\n  STR_AUSTRALIA: \"澳洲\"\n  STR_NIGERIA: \"尼日利亞\"\n  STR_SOUTH_AFRICA: \"南非\"\n  STR_EGYPT: \"埃及\"\n  STR_CANADA: \"加拿大\"\n  STR_TANK: \"坦克\"\n  STR_CIVILIAN: \"平民\"\n  STR_JAN: \"1月\"\n  STR_FEB: \"2月\"\n  STR_MAR: \"3月\"\n  STR_APR: \"4月\"\n  STR_MAY: \"5月\"\n  STR_JUN: \"6月\"\n  STR_JUL: \"7月\"\n  STR_AUG: \"8月\"\n  STR_SEP: \"9月\"\n  STR_OCT: \"10月\"\n  STR_NOV: \"11月\"\n  STR_DEC: \"12月\"\n  STR_INTERNATIONAL_RELATIONS: \"國際關系\"\n  STR_COUNTRY: \"國家\"\n  STR_FUNDING: \"資金\"\n  STR_CHANGE: \"改變\"\n  STR_WEAPON_SYSTEMS: \"武器系統\"\n  STR_HWPS: \"重型武器平台\"\n  STR_DAMAGE_UC_: \"損傷程度>{ALT}{0}\"\n  STR_ACCESS_LIFT_UFOPEDIA: \"入口電梯是物資和人員進出地底基地的主要途徑。它同時也是新基地首先要建造的設施。它非常容易被敵人攻入。\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"每個這樣的居住區可容納五十人，備有基本娛樂、餐飲及休息設施。\"\n  STR_LABORATORY_UFOPEDIA: \"每個實驗室設施可讓五十位科學家同時工作。實驗室配置了研究材料、生物化學及宇宙理論的最新科技。我們有特權存取全球頂尖實驗室的資料包括各國軍事機構的實驗室。\"\n  STR_WORKSHOP_UFOPEDIA: \"每個工作室配置所有必須的儀器去生產實驗室所研發的設備。工作室最多可容納五十位工程師，當然生產中的設備也會佔用一些工作室的空間。\"\n  STR_SMALL_RADAR_SYSTEM_UFOPEDIA: \"一組小型偵測系統具有300海里左右的雷達範圍，並和衛星系統連結進行地面偵蒐。每座系統每30分鐘有10%機率偵測到一個平均大小的物體。\"\n  STR_LARGE_RADAR_SYSTEM_UFOPEDIA: \"一組大型偵測系統具有450海里左右的雷達範圍，並和衛星系統連結進行地面偵蒐。每座系統每30分鐘有20%機率偵測到一個平均大小的物體。\"\n  STR_MISSILE_DEFENSES_UFOPEDIA: \"導彈防禦系統可以在一定程度上阻止試圖在基地附近降落的敵方飛行器的入侵。\"\n  STR_GENERAL_STORES_UFOPEDIA: \"所有設備、武器系統、彈藥、回收材料和重型坦克都存放在通用儲物倉庫內，包括分配給停機棚飛行器上的設備。\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"活體外星生物需要特殊的生存環境去維持它們的生命系統。外星收容設施能獨立存放十個外星生物。\"\n  STR_LASER_DEFENSES_UFOPEDIA: \"雷射防禦系統對敵方飛行器的入侵提供保護。\"\n  STR_PLASMA_DEFENSES_UFOPEDIA: \"電漿防禦系統對敵方飛行器的入侵提供強而有力的保護。\"\n  STR_FUSION_BALL_DEFENSES_UFOPEDIA: \"核融合導彈對外星生物攻擊提供最有效的防禦手段。這些導彈製造反物質爆炸摧毀特定範圍內的所有物體。\"\n  STR_GRAV_SHIELD_UFOPEDIA: \"重力防護罩能夠擊退試圖在基地附近降落的外星飛行器，爭取足夠的時間讓所有防禦系統再次發動攻擊。所以實際上，這等於是把基地防禦系統的效能提升一倍。\"\n  STR_MIND_SHIELD_UFOPEDIA: \"由於外星飛行器通過腦波來偵測人類的活動跡象，因此最有效的反制措施是隔絕基地人員腦波的外泄。這座設施將大幅降低基地被外星飛行器發現的機率。\"\n  STR_PSIONIC_LABORATORY_UFOPEDIA: \"有了念力研究室後我們便能夠評估基地所有士兵的念力潛能，並提供必要的訓練，讓他們學會運用自己的念力技能。每個研究室每次最多可訓練十名士兵，訓練名單在每個月底重新分配。在戰鬥中必須搭配念力增幅器才能發動念力攻擊。\"\n  STR_HYPER_WAVE_DECODER_UFOPEDIA: \"外星生物的通訊是仰賴一種幾乎瞬間傳遞的超維度電波。解碼設備可偵聽UFO間的通訊並解譯訊息，進而得知UFO的類型，外星種族以及它們正在進行的活動類型。\"\n  STR_HANGAR_UFOPEDIA: \"每座停機棚可容納一架飛行器，是具備維護、加油與維修X-Com飛行器的設施。每架停駐在基地的飛行器都必須分配到一個專屬的空停機棚，即使該飛行器出任務，這個停機棚也不能配置給被其他飛行器使用。\"\n  STR_PISTOL_UFOPEDIA: \"X-Com半自動制式手槍配有12枚子彈的彈匣。\"\n  STR_RIFLE_UFOPEDIA: \"這把高精準度的狙擊步槍裝有雷射瞄準器，可裝填二十發6.7mm彈藥。\"\n  STR_HEAVY_CANNON_UFOPEDIA: \"重型加農砲是威力強大但笨重的武器。它的多用途設計特性，可裝填三種不同種類的彈藥-穿甲彈、燃燒彈和高爆彈。\"\n  STR_AUTO_CANNON_UFOPEDIA: \"自動加農砲不但兼具重型加農砲的多用途性及火力，而且射速更快。\"\n  STR_ROCKET_LAUNCHER_UFOPEDIA: \"飛彈發射器使用雷射導向系統，發射三種不同大小的導彈。\"\n  STR_LASER_PISTOL_UFOPEDIA: \"雷射手槍有效善用新研發的技術，它不但和普通手槍一樣方便好用，而且有更高的射速及精準度。\"\n  STR_LASER_RIFLE_UFOPEDIA: \"雷射步槍相較早期的手槍設計有更強的火力及精準度。\"\n  STR_HEAVY_LASER_UFOPEDIA: \"重型雷射槍雖然笨重，但卻是極為有效的武器。\"\n  STR_GRENADE_UFOPEDIA: \"這顆常規用的手榴彈內有準確精密的計時器，可精確控制爆炸時間。\"\n  STR_SMOKE_GRENADE_UFOPEDIA: \"煙霧手榴彈的用途是在無遮蔽的戰鬥環境提供掩護。如不小心使用反而會對敵人有利。\"\n  STR_PROXIMITY_GRENADE_UFOPEDIA: \"感應手榴彈能夠像一般手榴彈般投擲，但是它著地後要探測到附近有物體移動才會觸發爆炸。要有極高技巧和非常小心才能正確地使用這裝備。\"\n  STR_HIGH_EXPLOSIVE_UFOPEDIA: \"高爆地雷只應用於破壞目的。我方人員禁止接近爆炸區域。\"\n  STR_MOTION_SCANNER_UFOPEDIA: \"精密的儀器內裝有多種不同的偵測器和高效能的運算電腦，用以分辨敵方的移動單位。士兵需要多練習才能有效使用這儀器。{NEWLINE}{NEWLINE}● 先按下移動物掃描器圖示，然後再於選單按下\\\"使用掃描器\\\"。{NEWLINE}● 儀器螢光幕中心的箭頭指向代表使用者面朝的方向(北面在螢幕上方)。{NEWLINE}● 閃爍的光點代表剛移動的單位，而體形較大或快速移動的單位，所代表的光點會更大。{NEWLINE}● 它偵測不到靜止不動的物體。\"\n  STR_MEDI_KIT_UFOPEDIA: \"急救包內有治療設備、止痛藥和興奮劑。{NEWLINE}{NEWLINE}● 使用急救包時，你必須面向需要治療的士兵。{NEWLINE}● 治療昏迷不醒的士兵，你必須站立於他上面才能使用。{NEWLINE}● 先按下急救包圖示，然後再於選單按下\\\"使用急救包\\\"。{NEWLINE}{NEWLINE}  治療> 顯示紅色的身體部份代表致命傷，先按受傷的部位再按\\\"治療\\\"鍵，這樣就能治癒一個致命傷並恢復部份生命值。{NEWLINE}{NEWLINE}  興奮劑> 能恢復體力並甦醒昏迷（被擊暈）的士兵。{NEWLINE}{NEWLINE}  止痛藥> 能恢復受傷士兵的士氣。恢復量最高相當於士兵失去的生命值。\"\n  STR_PSI_AMP_UFOPEDIA: \"只有擁有念力技能的士兵才能使用這儀器。{NEWLINE}在戰鬥中按下念力增幅器圖示，然後選擇攻擊類型，再移動游標選擇攻擊目標。共有兩種念力攻擊::{NEWLINE}{NEWLINE}  令敵恐慌> 如果攻擊成功可減低目標單位的士氣，或令其恐慌。{NEWLINE}{NEWLINE}  心靈控制> 如果攻擊成功，你可像控制我方人員一樣即時支配敵方單位(除了不能進入整裝備戰畫面)。但是這種攻擊不易成功\"\n  STR_STUN_ROD_UFOPEDIA: \"這種裝置只能用於近戰。透過電擊來擊暈生物體而不殺死它。\"\n  STR_MIND_PROBE_UFOPEDIA: \"心靈探測器是一種外星通訊設備，用於直接從腦波中獲取生物資訊。{NEWLINE}X-Com作戰單位可在戰鬥中用來顯示外星生物的特徵。{NEWLINE}點擊使用心靈探測儀，然後用游標點取外星生物。\"\n  STR_PLASMA_PISTOL_UFOPEDIA: \"電漿手槍是一種致命的外星武器，其運作原理是利用一個微型的反重力場，從內部加速粒子來發射。\"\n  STR_PLASMA_RIFLE_UFOPEDIA: \"這是一種毀滅性的武器，其運作原理是利用一個微型的反重力場，但有更強大的反重力場和粒子加速，能發射出更致命的火力。\"\n  STR_HEAVY_PLASMA_UFOPEDIA: \"這是一種毀滅性的武器，其運作原理是利用一個微型的反重力場，但有極強大的反重力場和粒子加速，能發射出極度致命的火力。\"\n  STR_BLASTER_LAUNCHER_UFOPEDIA: \"這是一款外星導彈-爆裂彈的發射器，能發射威力強大的「爆裂彈」。當按下發射後，它會提供設定\\\"航點\\\"作為飛行路徑。設定足夠的航點後，便可以按專用的圖示發射爆裂彈。\"\n  STR_SMALL_LAUNCHER_UFOPEDIA: \"這是一個眩暈彈小型發射器，需要活捉外星生物時非常有用。\"\n  STR_ALIEN_GRENADE_UFOPEDIA: \"外星手榴彈-它的使用方法和我軍的手榴彈一樣，但更具威力。\"\n  STR_SMALL_SCOUT: \"小型偵察艇\"\n  STR_MEDIUM_SCOUT: \"中型偵察艇\"\n  STR_LARGE_SCOUT: \"大型偵察艇\"\n  STR_HARVESTER: \"收割船\"\n  STR_ABDUCTOR: \"誘拐者\"\n  STR_TERROR_SHIP: \"恐襲艦\"\n  STR_BATTLESHIP: \"戰鬥艦\"\n  STR_SUPPLY_SHIP: \"補給艦\"\n  STR_RATING: \"評價> {0}\"\n  STR_RATING_TERRIBLE: \"一團糟！\"\n  STR_RATING_POOR: \"差強人意！\"\n  STR_RATING_OK: \"尚可\"\n  STR_RATING_GOOD: \"良好！\"\n  STR_RATING_EXCELLENT: \"非常出色！\"\n  STR_SCORE: \"評分\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"Ｘ-ＣＯＭ 專案月報\"\n  STR_MONTH: \"月> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"到目前為止，資助國議會大致上滿意你的進展。\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"資助國議會很高興見到你有卓越的進展，請繼續保持出色的表現。\"\n  STR_COUNCIL_IS_DISSATISFIED: \"資助國議會不滿意你的表現。你一定要改進應付外星威脅的效率，以減低專案被終止的風險。\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"你沒有成功應對外星生物的侵略，因此很抱歉地，資助國議會決定終止這專案。各國於是決定各自用自認為最合適的對策。我們只希望可以和這些表面上敵對的武力達成和解，而普羅大衆亦會願意和這些外星訪客訂立協議。\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0}特別滿意你處理當地威脅的能力，因此願意投入更多資金。\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0}對你處理當地外星入侵的進展特別欣喜，因此願意投入更多資金。\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0}和{1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0}對你處理在國境內外星生物活動的能力甚感不悅，因此決定減少財政資助。\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0}對你處理在他們國境內外星生物活動的能力甚感不悅，因此都決定減少提供資金。\"\n  STR_KNOTS: \"{0} 海里\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \" {0}已和不明的外星部隊簽訂秘密協議並退出專案。\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} 已和不明的外星部隊簽訂秘密協議並退出專案。\"\n  STR_MONTHLY_RATING: \"每月評價> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"資金增減> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"資助國議會對你的財務狀況深感不悅，你必須設法令債項減低至二佰萬元，否則這專案會被終止。\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"超電波傳訊已解譯\"\n  STR_CRAFT_TYPE: \"機體種類\"\n  STR_RACE: \"種族\"\n  STR_MISSION: \"任務\"\n  STR_ZONE: \"地帶\"\n  STR_ALLOCATE_RESEARCH: \"分配研究資源\"\n  STR_ALLOCATE_MANUFACTURE: \"分配生產資源\"\n  STR_NEW_YORK: \"紐約\"\n  STR_WASHINGTON: \"華盛頓\"\n  STR_LOS_ANGELES: \"洛杉磯\"\n  STR_MONTREAL: \"蒙特婁\"\n  STR_HAVANA: \"哈瓦那\"\n  STR_MEXICO_CITY: \"墨西哥城\"\n  STR_CHICAGO: \"芝加哥\"\n  STR_VANCOUVER: \"溫哥華\"\n  STR_DALLAS: \"達拉斯\"\n  STR_BRASILIA: \"巴西利亞\"\n  STR_BOGOTA: \"波哥大\"\n  STR_BUENOS_AIRES: \"布宜諾斯艾利斯\"\n  STR_SANTIAGO: \"聖地牙哥\"\n  STR_RIO_DE_JANEIRO: \"里約熱內盧\"\n  STR_LIMA: \"利馬\"\n  STR_CARACAS: \"加拉加斯\"\n  STR_LONDON: \"倫敦\"\n  STR_PARIS: \"巴黎\"\n  STR_BERLIN: \"柏林\"\n  STR_MOSCOW: \"莫斯科\"\n  STR_ROME: \"羅馬\"\n  STR_MADRID: \"馬德里\"\n  STR_BUDAPEST: \"布達佩斯\"\n  STR_LAGOS: \"拉哥斯\"\n  STR_CAIRO: \"開羅\"\n  STR_CASABLANCA: \"卡薩布蘭加\"\n  STR_PRETORIA: \"普利托利亞\"\n  STR_NAIROBI: \"奈洛比\"\n  STR_CAPE_TOWN: \"開普敦\"\n  STR_KINSHASA: \"金沙薩\"\n  STR_ANKARA: \"安卡拉\"\n  STR_DELHI: \"德里\"\n  STR_KARACHI: \"卡拉奇\"\n  STR_BAGHDAD: \"巴格達\"\n  STR_TEHRAN: \"德黑蘭\"\n  STR_BOMBAY: \"孟買\"\n  STR_CALCUTTA: \"加爾各答\"\n  STR_TOKYO: \"東京\"\n  STR_BEIJING: \"北京\"\n  STR_BANGKOK: \"曼谷\"\n  STR_MANILA: \"馬尼拉\"\n  STR_SEOUL: \"首爾\"\n  STR_SINGAPORE: \"新加坡\"\n  STR_JAKARTA: \"雅加達\"\n  STR_SHANGHAI: \"上海\"\n  STR_HONG_KONG: \"香港\"\n  STR_NOVOSIBIRSK: \"新西伯利亞\"\n  STR_CANBERRA: \"坎培拉\"\n  STR_WELLINGTON: \"威靈頓\"\n  STR_MELBOURNE: \"墨爾本\"\n  STR_PERTH: \"伯斯\"\n  STR_PSI_TRAINING: \"念力訓練\"\n  STR_PSIONIC_TRAINING: \"念力訓練\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"尚餘念力研究室空間> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"念力{NEWLINE}強度\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"念力技巧{NEWLINE}/強化\"\n  STR_PSI_AMP: \"念力增幅器\"\n  STR_IN_TRAINING: \"正在{NEWLINE}訓練中？\"\n  STR_TARGETTED_BY: \"負責追截:\"\n  STR_WEAPONS_CREW_HWPS: \"{NEWLINE}武器/人/HWPs\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"燃料不足，{NEWLINE}正返回基地\"\n  STR_SOLDIER_LIST: \"士兵列表\"\n  STR_RANK_: \"官階> {ALT}{0}\"\n  STR_MISSIONS: \"任務次數> {ALT}{0}\"\n  STR_KILLS: \"殺敵數> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"康復需時> {ALT}{0}\"\n  STR_TIME_UNITS: \"時間\"\n  STR_STAMINA: \"體力値\"\n  STR_HEALTH: \"健康値\"\n  STR_BRAVERY: \"勇氣値\"\n  STR_REACTIONS: \"反應度\"\n  STR_FIRING_ACCURACY: \"射撃\"\n  STR_THROWING_ACCURACY: \"投擲\"\n  STR_STRENGTH: \"身體強度\"\n  STR_PSIONIC_STRENGTH: \"念力強度\"\n  STR_PSIONIC_SKILL: \"念力技能\"\n  STR_NEW_RANK: \"新官階\"\n  STR_PROMOTIONS: \"晉升\"\n  STR_SOLDIERS_UC: \"士兵\"\n  STR_TANK_CANNON_UFOPEDIA: \"自動重型坦克設計來補充X-Com小隊的戰力。高火力和堅固裝甲的結合使這些部隊對於開闊地形的火戰非常有價値。請確保庫存中有相當數量的砲彈來重新武裝坦克。當他們被分配到小隊時，他們會自動裝備砲彈。\"\n  STR_TANK_ROCKET_LAUNCHER_UFOPEDIA: \"這輛全自動的重型武器平台配備強力飛彈，能對任何外星敵人造成毀滅性打擊。請留意倉庫內是否有充足的HWP飛彈供應。\"\n  STR_TANK_LASER_CANNON_UFOPEDIA: \"雷射武器是HWP一項實用的新增裝備，它結合了強大的火力與沒有彈藥限制的優勢。這意味著它可以長時間部署在戰場上，極大地提高了續航力。\"\n  STR_HOVERTANK_PLASMA_UFOPEDIA: \"外星科技讓重型坦克注入了新的生命力。空中移動所帶來的機動性徹底解決了地形限制，結合電漿光束的強大威力與更強化的防衛能力，形成了一個致命的組合。\"\n  STR_HOVERTANK_LAUNCHER_UFOPEDIA: \"這輛載有熱核彈發射器的浮空坦克可徹底毀滅極大的範圍，請務必小心使用。你必須安排生產熱核彈以補充它的彈藥。要發射這智慧導向的熱核彈，先設定足夠作為引導用的導航點後，便可按專用的發射圖示射出導彈。\"\n  STR_HEAVY_PLASMA_CLIP_UFOPEDIA: \"這小巧的東西是重型電漿步槍的彈匣，內藏小量的奧雷爾元素。\"\n  STR_PLASMA_RIFLE_CLIP_UFOPEDIA: \"這細小的東西可供應能源予電漿步槍-中度火力的外星武器。內藏小量的奧雷爾元素。\"\n  STR_PLASMA_PISTOL_CLIP_UFOPEDIA: \"它可提供能源予小型的外星電漿手槍。內藏奧雷爾-所有外星能量的來源。\"\n  STR_STUN_BOMB_UFOPEDIA: \"暈眩炸彈用於捕獲活體人類標本，但它也可以用於對付大多數外星種族。它是從小型發射器發射的。\"\n  STR_ALIEN_RESEARCH_UFOPEDIA: \"外星生物的研究任務主旨在於收集有關地球及其居民的基本數據。主要使用小型飛行器，偶爾在荒蕪地區著陸。這類外星生物活動對X-Com的威脅最小，政府和民眾對此並不十分擔心。\"\n  STR_ALIEN_HARVEST_UFOPEDIA: \"對外星生物來說，地球動物有很多用途。它們秘密地捕獲動物後摘除各種器官並帶回，所以牛隻支解事件大多伴隨著目擊UFO的報告。這種主要發生在農業區的外星活動引起各國政府極大關注同時也讓民眾感到焦慮。「外星收割」的理論認為，外星種族最初用它們的動植物「播種」了地球，如今只是回來收割它們應得的東西。\"\n  STR_ALIEN_ABDUCTION_UFOPEDIA: \"這是最隱密的外星生物活動形式。儘管外星生物試圖抹去受害者記憶中的經歷，但外星生物綁架事件仍被廣泛報導。受害者聲稱遭受多種羞辱性的人體實驗，包括殖入外星生物胚胎和進行不明的基因實驗。這類活動背後的目的似乎與基因變異和外星生物自身基因物質的改造有關。\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"地球政府可能會受到外表類似人類的外星生物工作人員滲透，這可能導致外星生物與政府高層之間進行官方接觸，特徴是該國主要城市附近頻繁出現不明飛行物的活動。外星生物會試圖透過提供先進的技術來與地球政府簽署協議，而該國把允許外星生物不受阻礙地進行活動作為回報。這對X-Com構成了最嚴重的威脅。如果該政府同意協議，那麼他們將停止提供給X-Com的資金。\"\n  STR_ALIEN_BASE_UFOPEDIA: \"外星生物會在偏遠地區建造秘密地下基地。經過一些初步的偵察飛行後，隨著基地的建設，將伴隨著一些激烈的不明飛行物活動。衆所周知，這些基地設有被劫持者的實驗室，以及該地區進一步活動所需的物資。即使在沒有不明飛行物的情況下，外星生物基地的存在也會產生大量的外星生物活動報告。為了找到基地，X-Com的飛行器必須在該區域巡邏幾個小時，才能有發現的機率。\"\n  STR_ALIEN_TERROR_UFOPEDIA: \"當外星生物即將對一座城市進行恐怖攻撃時，他們會部署一支強大的特種攻撃部隊。居民將受到直接威脅，政府將被迫撤離整個地區。這項活動背後的主要目的是製造足夠的公衆恐慌，促使政府威脅X-Com計畫。\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"如果X-Com在撃落不明飛行物方面特別成功，那麼外星生物可能會採取一些報復行動。這可能會導致對X-Com基地的直接攻撃。然而外星生物必須找到X-Com基地才能對其進行攻擊，如果保持不明飛行物遠離基地，那麼遭受突撃的機率應該很小。\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"外星基地一旦建成，就會有專門的補給艦會定期進行補給。如果探測到這種UFO著陸的話，那麼附近肯定有外星基地。\"\n  STR_SMALL_SCOUT_UFOPEDIA: \"這種小型飛行器主要用於偵察或研究，在外星生物任務開始時，它通常會先於大型飛行器行動。\"\n  STR_MEDIUM_SCOUT_UFOPEDIA: \"一艘對地球部隊威脅性不大的中型偵察艇。它通常在外星生物任務中，會比大型飛船更早出現。\"\n  STR_LARGE_SCOUT_UFOPEDIA: \"這是最大型的多用途外星偵察艇，可執行所有種類的任務。\"\n  STR_HARVESTER_UFOPEDIA: \"這收割艦的底部裝有活動閘門，並配備可吊起牛隻或其他牲畜的起重裝置。它們使用雷射切割器獲取所需材料，並將殘肢傾倒在地面。此外飛行器內設有屍塊的儲存容器。\"\n  STR_ABDUCTOR_UFOPEDIA: \"這種飛船配備了一間檢驗室，用來對受害者進行駭人的實驗。受害者通常會因心靈感應而癱瘓，但在手術台上仍然是清醒著。\"\n  STR_TERROR_SHIP_UFOPEDIA: \"恐襲艦有容納大型恐怖外星武器或生物的設施，並且用於將這些外星恐怖份子運送到人口稠密的地區。\"\n  STR_BATTLESHIP_UFOPEDIA: \"戰鬥艦是體積最大及火力最強的外星飛行器。通常也是外星人主要的任務飛船，配備了強力的武器與眾多的戰鬥人員。\"\n  STR_SUPPLY_SHIP_UFOPEDIA: \"補給艦用於外星基地的建造或對現有基地進行補給。上面搭載外星食物容器和繁殖艙。\"\n  STR_DISMANTLE: \"拆卸\"\n  STR_FACILITY_IN_USE: \"設施正在使用中\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"不能拆卸設施！{SMALLLINE}任何基地設施必須接通入口電梯。\"\n  STR_TRANSFER_ITEMS_TO: \"轉移物品至\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"沒有外星生物收容設施可供轉移！{SMALLLINE}活體外星生物需要外星生物收容設施才能生存。\"\n  STR_AMOUNT_AT_DESTINATION: \"目的地{NEWLINE}存量\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"外星生物{NEWLINE}因為沒有{NEWLINE}外星生物收容設施{NEWLINE}而死亡\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"沒有額外的居住空間！{SMALLLINE}目的地基地沒有足夠的空間給隨機人員居住。\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"儲存空間不足！ {SMALLLINE}目標基地存空間不足以存放分配給飛行器的設備。\"\n  STR_ITEMS_ARRIVING: \"轉移中的物品\"\n  STR_DESTINATION_UC: \"目的地\"\n  STR_PISTOL: \"手槍\"\n  STR_PISTOL_CLIP: \"手槍彈匣\"\n  STR_RIFLE: \"步槍\"\n  STR_RIFLE_CLIP: \"步槍彈匣\"\n  STR_HEAVY_CANNON: \"重型加農砲\"\n  STR_HC_AP_AMMO: \"重型加農砲-穿甲彈藥\"\n  STR_HC_HE_AMMO: \"重型加農砲-高爆彈藥\"\n  STR_HC_I_AMMO: \"重型加農砲-燃燒彈藥\"\n  STR_AUTO_CANNON: \"自動加農砲\"\n  STR_AC_AP_AMMO: \"自動加農砲-穿甲彈藥\"\n  STR_AC_HE_AMMO: \"自動加農砲-高爆彈藥\"\n  STR_AC_I_AMMO: \"自動加農砲-燃燒彈藥\"\n  STR_ROCKET_LAUNCHER: \"飛彈發射器\"\n  STR_SMALL_ROCKET: \"小型飛彈\"\n  STR_LARGE_ROCKET: \"大型飛彈\"\n  STR_INCENDIARY_ROCKET: \"燃燒飛彈\"\n  STR_GRENADE: \"手榴彈\"\n  STR_SMOKE_GRENADE: \"煙霧手榴彈\"\n  STR_PROXIMITY_GRENADE: \"感應手榴彈\"\n  STR_HIGH_EXPLOSIVE: \"高爆地雷\"\n  STR_STUN_ROD: \"眩暈棒\"\n  STR_HEAVY_PLASMA: \"重型電漿步槍\"\n  STR_HEAVY_PLASMA_CLIP: \"重型電漿步槍彈匣\"\n  STR_PLASMA_RIFLE: \"電漿步槍\"\n  STR_PLASMA_RIFLE_CLIP: \"電漿步槍彈匣\"\n  STR_PLASMA_PISTOL: \"電漿手槍\"\n  STR_PLASMA_PISTOL_CLIP: \"電漿手槍彈匣\"\n  STR_BLASTER_LAUNCHER: \"爆裂彈發射器\"\n  STR_BLASTER_BOMB: \"爆裂彈\"\n  STR_SMALL_LAUNCHER: \"小型發射器\"\n  STR_STUN_BOMB: \"眩暈彈\"\n  STR_ALIEN_GRENADE: \"外星手榴彈\"\n  STR_ELERIUM_115: \"奧雷爾-115\"\n  STR_MIND_PROBE: \"心靈探測器\"\n  STR_SECTOID_CORPSE: \"灰人屍體\"\n  STR_SNAKEMAN_CORPSE: \"蛇人屍體\"\n  STR_ETHEREAL_CORPSE: \"異靈族屍體\"\n  STR_MUTON_CORPSE: \"變異者屍體\"\n  STR_FLOATER_CORPSE: \"漂浮者屍體\"\n  STR_CELATID_CORPSE: \"腐蝕體屍體\"\n  STR_SILACOID_CORPSE: \"矽原體屍體\"\n  STR_CHRYSSALID_CORPSE: \"鉗獵者屍體\"\n  STR_REAPER_CORPSE: \"收割獸屍體\"\n  STR_SECTOPOD_CORPSE: \"步行機甲殘骸\"\n  STR_CYBERDISC_CORPSE: \"電腦飛碟殘骸\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"沒有充足的彈藥來裝備 HWP{SMALLLINE}每個 HWP 需要 {0} {1}.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"庫存的裝備不足小隊的編制\"\n  STR_MARS_CYDONIA_LANDING: \"火星: 降落塞東尼亞\"\n  STR_MARS_CYDONIA_LANDING_BRIEFING: \"您的復仇者戰機已降落在火星表面的塞東尼亞地區。我們的情報顯示其中一座金字塔形建築物內有通往地下綜合設施的\\\"綠色\\\"入口電梯。{NEWLINE}{NEWLINE}當所有士兵在\\\"綠色\\\"電梯範圍集結完畢後，請點擊'放棄任務'圖示繼續前往下一個階段。\"\n  STR_MARS_THE_FINAL_ASSAULT: \"火星:最後之攻擊\"\n  STR_MARS_THE_FINAL_ASSAULT_BRIEFING: \"我們疲累的士兵乘坐金字塔電梯到達地底深處，最終他們到達一個由隧道和密室組成的大型建築群的中心。我們深信外星主腦被藏於這個迷宮的某處。如果想要拯救地球免於外星生物奴役，就必須摧毀它。。{NEWLINE}{NEWLINE}祝你武運昌隆！\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"要先研究{NEWLINE}[ {0} ]{NEWLINE}才可以製造{NEWLINE} [ {1} ]\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"外星生物已經摧毀了這座不設防的基地 [ {0} ]\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"X-Com探員在{NEWLINE}[ {0} ]{NEWLINE}定位了一個外星生物基地\"\n  STR_STANDOFF: \"對峙\"\n  STR_CAUTIOUS_ATTACK: \"謹慎攻擊\"\n  STR_STANDARD_ATTACK: \"普通攻擊\"\n  STR_AGGRESSIVE_ATTACK: \"進取攻擊\"\n  STR_DISENGAGING: \"脱離戰線\"\n  STR_UFO_HIT: \"擊中UFO！\"\n  STR_UFO_CRASH_LANDS: \"UFO墜毀！\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"維持對峙距離並最小化視窗\"\n  STR_UFO_RETURN_FIRE: \"UFO還火！\"\n  STR_INTERCEPTOR_DAMAGED: \">>> 攔截機受損 <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> 攔截機被毀 <<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"UFO以更快的速度拋離攔截機！\"\n  STR_ALIENS_TERRORISE: \"外星威嚇\"\n  STR_LONG_RANGE_DETECTION: \"遠距離偵測\"\n  STR_STORES_UC: \"倉庫\"\n  STR_DIFFICULTY_LEVEL: \"難易度\"\n  STR_INTERCEPT: \"攔截\"\n  STR_BASES: \"基地\"\n  STR_GRAPHS: \"圖表\"\n  STR_UFOPAEDIA_UC: \"UFO百科\"\n  STR_OPTIONS_UC: \"選項\"\n  STR_FUNDING_UC: \"資金\"\n  STR_5_SECONDS: \"5 秒鐘\"\n  STR_1_MINUTE: \"1 分鐘\"\n  STR_5_MINUTES: \"5 分鐘\"\n  STR_30_MINUTES: \"30 分鐘\"\n  STR_1_HOUR: \"1 小時\"\n  STR_1_DAY: \"1 整日\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"Ｘ-ＣＯＭ 績效名冊\"\n  STR_ENTER_NAME: \"輸入名稱\"\n  STR_PERFORMANCE_RATING: \"表現評核\"\n  STR_VICTORY_DATE: \"勝利日\"\n  STR_ELECTRO_FLARE: \"照明彈\"\n  STR_ELECTRO_FLARE_UFOPEDIA: \"這小巧的儀器投擲後能產生很強的燈光，在夜間任務能夠顯現出在它附近藏身的敵人。\"\n  STR_MONTHLY_COSTS: \"每月成本\"\n  STR_CRAFT_RENTAL: \"戰機支出\"\n  STR_SALARIES: \"人工\"\n  STR_BASE_MAINTENANCE: \"基地維修\"\n  STR_COST_PER_UNIT: \"每單位成本\"\n  STR_QUANTITY: \"數量\"\n  STR_TOTAL: \"總數\"\n  STR_IN_PSIONIC_TRAINING: \"在進行念力訓練\"\n  STR_BLASTER_BOMB_UFOPEDIA: \"這是一種高爆導彈，配備智慧導引系統，透過爆裂彈發射器發射。\"\n  STR_FRONT_ARMOR: \"前護甲\"\n  STR_LEFT_ARMOR: \"左護甲\"\n  STR_RIGHT_ARMOR: \"右護甲\"\n  STR_REAR_ARMOR: \"背護甲\"\n  STR_UNDER_ARMOR: \"下護甲\"\n  STR_ROUNDS: \"發射次數\"\n  STR_UNIT: \"單位> {0}\"\n  STR_ENERGY: \"體力\"\n  STR_MORALE: \"士氣\"\n  STR_ARMOR_: \"護甲> {0}\"\n  STR_FRONT_ARMOR_UC: \"前護甲\"\n  STR_LEFT_ARMOR_UC: \"左護甲\"\n  STR_RIGHT_ARMOR_UC: \"右護甲\"\n  STR_REAR_ARMOR_UC: \"背護甲\"\n  STR_SKILLS: \"技能> {0}\"\n  STR_LEVEL: \"等級> {0}\"\n  STR_HEAD: \"頭部\"\n  STR_TORSO: \"軀幹\"\n  STR_RIGHT_ARM: \"右臂\"\n  STR_LEFT_ARM: \"左臂\"\n  STR_RIGHT_LEG: \"右腿\"\n  STR_LEFT_LEG: \"左腿\"\n  STR_PAIN_KILLER: \"止痛劑\"\n  STR_STIMULANT: \"興奮劑\"\n  STR_HEAL: \"治療\"\n  STR_TIME_UNITS_SHORT: \"TU>{ALT}{0}\"\n  STR_WEIGHT: \"負重>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"反應>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"PSKL>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"PSTH>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"外星物品\"\n  STR_AMMO_ROUNDS_LEFT: \"彈藥:{NEWLINE}尚餘{NEWLINE}彈量={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"止痛劑>{ALT}{0}{ALT}{NEWLINE}興奮劑>{ALT}{1}{ALT}{NEWLINE}治療>{ALT}{2}\"\n  STR_THROW: \"投擲\"\n  STR_AUTO_SHOT: \"自動射擊\"\n  STR_SNAP_SHOT: \"快速射擊\"\n  STR_AIMED_SHOT: \"精準射擊\"\n  STR_STUN: \"令其暈厥\"\n  STR_PRIME_GRENADE: \"設定引信\"\n  STR_USE_SCANNER: \"使用掃瞄器\"\n  STR_USE_MEDI_KIT: \"使用急救包\"\n  STR_LAUNCH_MISSILE: \"發射導彈\"\n  STR_ACCURACY_SHORT: \"命中>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"時間單位不足！\"\n  STR_NOT_ENOUGH_ENERGY: \"體力不足！\"\n  STR_NO_ROUNDS_LEFT: \"子彈用盡！\"\n  STR_NO_AMMUNITION_LOADED: \"未裝填彈藥！\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"彈藥不適用於這武器！\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"已裝填彈藥！\"\n  STR_NO_LINE_OF_FIRE: \"不在火線上！\"\n  STR_GRENADE_IS_ACTIVATED: \"手榴彈被啟動！\"\n  STR_GRENADE_IS_DEACTIVATED: \"手榴彈已重新插銷！\"\n  STR_THERE_IS_NO_ONE_THERE: \"那邊沒有人！\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"不能使用未研究過的外星物品！\"\n  STR_OUT_OF_RANGE: \"超出射程！\"\n  STR_UNABLE_TO_THROW_HERE: \"不能投擲到這裡！\"\n  STR_SET_TIMER: \"設定計時器\"\n  STR_HIDDEN_MOVEMENT: \"隱伏移動\"\n  STR_TURN: \"第 {0} 回合 \"\n  STR_SIDE: \"{0}的行動\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"按鍵繼續\"\n  STR_MIND_CONTROL: \"心靈控制\"\n  STR_PANIC_UNIT: \"令敵恐慌\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"士氣攻擊成功\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"心靈控制成功\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}暴走中\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}暴走中\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}恐慌了\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}恐慌中\"\n  STR_XCOM: \"Ｘ-ＣＯＭ\"\n  STR_ALIENS: \"外星人\"\n  STR_RIGHT_HAND: \"右手\"\n  STR_LEFT_HAND: \"左手\"\n  STR_RIGHT_SHOULDER: \"右肩\"\n  STR_LEFT_SHOULDER: \"左肩\"\n  STR_BACK_PACK: \"背包\"\n  STR_BELT: \"腰帶\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}被外星生物控制中\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}被外星生物控制中\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}昏厥中\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}昏厥中\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}因重傷而亡\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}因重傷而亡\"\n  STR_USE_MIND_PROBE: \"使用心靈探測器\"\n  STR_FATAL_WOUNDS: \"致命傷\"\n  STR_UNDER_ARMOR_UC: \"下護甲\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"預留時間單位以便快速射擊\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"預留時間單位以便自動射擊\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"預留時間單位以便精準射擊\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"預留時間單位以便進入跪姿\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"預留時間單位以便在跪姿開火\"\n  STR_UNITS_IN_CRAFT:\n    other: \"X-Com飛行器中的有 {N} 個單位\"\n  STR_UNITS_OUTSIDE:\n    other: \"遺留在外的有 {N} 個單位\"\n  STR_UNITS_IN_ENTRANCE:\n    other: \"在入口的有 {N} 個單位\"\n  STR_UNITS_IN_EXIT:\n    other: \"在目標出口的有 {N} 個單位\"\n  STR_ABORT_MISSION_QUESTION: \"放棄任務 ?\"\n  STR_CORPSE: \"屍體\"\n  STR_UNLOAD_CRAFT: \"退出子彈\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}已被擊殺\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}已被擊殺\"\n  STR_HIT_MELEE: \"命中\"\n  STR_GROUND: \"地面\"\n  STR_LIVING_QUARTERS_PLURAL: \"起居室\"\n  STR_LIST_ITEM: \"項目清單\"\n  STR_PERSONAL_ARMOR_UFOPEDIA: \"使用新發現的外星合金{NEWLINE}這種新得護甲使我們的士兵有機會抵抗外星威脅。\"\n  STR_POWER_SUIT_UFOPEDIA: \"這款護甲為士兵提供了強大的新保護{NEWLINE}它由 奧雷爾-115 能源提供動力，大大増強了著裝人員的速度和力量，為戰鬥部隊提供了迄今為止最好的保護。\"\n  STR_FLYING_SUIT_UFOPEDIA: \"強力護甲的増強版{NEWLINE}融合了外星反重力飛行科技，可以在戰場上完全自由地移動。\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"所有外星生物於墜毀中身亡，{NEWLINE}已安排自動回收物資。\"\n  STR_RESET: \"重置\"\n  STR_MEMORIAL: \"緬念\"\n  STR_DATE_UC: \"日期\"\n  STR_SOLDIERS_RECRUITED_UC: \"已招募士兵>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"已失去士兵>{ALT}{0}\"\n  MAP_CULTA: \"農場\"\n  MAP_FOREST: \"森林\"\n  MAP_JUNGLE: \"叢林\"\n  MAP_MOUNT: \"山地\"\n  MAP_DESERT: \"荒漠\"\n  MAP_POLAR: \"極地\"\n  MAP_URBAN: \"城市\"\n  MAP_UBASE: \"外星生物基地\"\n  MAP_XBASE: \"X-Com基地\"\n  MAP_MARS: \"火星\"\n  STR_MIXED: \"混合\"\n  STR_REMOVE_SELECTED: \"移除已選擇\"\n  STR_LIVE_ALIENS: \"活體{NEWLINE}樣品\"\n  STR_DEAD_ALIENS: \"報廢{NEWLINE}樣品\"\n  STR_UNDER_INTERROGATION: \"正在{NEWLINE}研究\"\n  STR_CONTAINMENT_EXCEEDED: \"外星生物收容室超載{SMALLLINE}在{0}的收容室空間不足。您必須從收容室中移除多餘的外星生物(然後它們會死亡)。\"\n  STR_MANAGE_CONTAINMENT: \"管理外星生物收容室\"\n  STR_STORAGE_EXCEEDED: \"儲存空間超載{SMALLLINE}在{0}的儲存空間不足。您必須賣掉多餘的物品。\"\n  STR_GO_TO_BASE: \"移至基地\"\n  STR_MELEE_ACCURACY: \"進戰\"\n  STR_SELL_PRODUCTION: \"販售\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"雙手不能持物！\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"沒有足夠的物品來複製範本！\"\n  STR_UNLOAD_WEAPON: \"卸除武器彈藥\"\n  STR_ALL_ITEMS: \"所有物品\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    other: \"不允許再攜帶任何裝備上船！ {SMALLLINE}最多只能在這艘飛船上攜帶 {N} 件設備。\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}控制中心已被摧毀{NEWLINE}請前往入口並離開。\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"X-Com 設施不得建於水下\"\n  STR_LEVEL_SHORT: \"{0}\"\n  STR_PERSONNEL: \"人員\"\n  STR_CRAFT_ARMAMENT: \"飛行器和武器\"\n  STR_COMPONENTS: \"外星元件\"\n  STR_SOLDIERS_RECRUITED: \"已招募士兵\"\n  STR_SOLDIERS_LOST: \"已失去士兵\"\n  STR_TOTAL_UFOS: \"已偵測UFO\"\n  STR_TOTAL_ALIEN_BASES: \"已發現外星生物基地\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"PST\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"PSK\"\n  FEMALE_CIVILIAN: \"城市居民, 女性\"\n  MALE_CIVILIAN: \"城市居民, 男性\"\n  CYBERDISC_WEAPON: \"電腦飛碟武器\"\n  REAPER_WEAPON: \"收割獸武器\"\n  CHRYSSALID_WEAPON: \"鉗獵者武器\"\n  CELATID_WEAPON: \"腐蝕體武器\"\n  SILACOID_WEAPON: \"矽原體武器\"\n  SECTOPOD_WEAPON: \"步行機甲武器\"\n  ZOMBIE_WEAPON: \"殭屍武器\"\n  ALIEN_PSI_WEAPON: \"外星心靈控制武器\"\n"
  },
  {
    "path": "bin/standard/xcom1/Resources/Extended/Touch/license.txt",
    "content": "Artwork (c) Riccardo Gasperi\n\nThis artwork is licensed under a\nCreative Commons Attribution-ShareAlike 4.0 International License.\n\nYou should have received a copy of the license along with this\nwork.  If not, see <http://creativecommons.org/licenses/by-sa/4.0/>."
  },
  {
    "path": "bin/standard/xcom1/Resources/Weapons/license.txt",
    "content": "Artwork (c) Niklas Jansson (http://androidarts.com/) and Riccardo Gasperi\n\nThis artwork is licensed under a\nCreative Commons Attribution-ShareAlike 4.0 International License.\n\nYou should have received a copy of the license along with this\nwork.  If not, see <http://creativecommons.org/licenses/by-sa/4.0/>."
  },
  {
    "path": "bin/standard/xcom1/TERRAIN/XBASE2.PCK",
    "content": "\u0010\u001a\u0016\u0013\u0011\u000e\r\f\n\t\b\u0007\b\t\u000b\r\u000f\u0012\u0015\u0018\u0013\u0010\u001c\u001a\u0017\u0015\u0012\u000f\u000b\u0006\u0005\u0004\u0004\u0004\u0005\u0006\t\f\u0010\u0013\u0017\u001c\u0007\u000f\u0019\u0015\u0012\u0011\u000f\u000e\u0010\u000f\u000f\u000f\u000f\u000e\u000e\u000e\r\r\r\r\f\r\u0010\u0016\u0013\u001e\u001e\u001c\u001b\u0019\u0018\u0015\u0012\u000f\u000f\u0011\u0014\u0016\u001b\u0013\u000f\u0017\r\r\u0006\u0006\f\f\u0001\f\u000b\u0003\u000b\n\n\t\f\u0011\u0002\f\u001f\u001e\u000e\u001b\u001b\r\u001a\u000e\u0019\u001a\u0019\u0018\u0017\u0016\u0015\u0015\u0014\u0014\u0014\u0016\u0018\u0017\u0010\u0007\u000e\f\t\u0004\u0007\r\u0012\u0006\u001a\u001d\u001a\u0019\u0018\u0015\u0014\u0014\u0013\u0013\u0012\u0012\u0012\u0003\u0012\u0011\u0012\u0011\u0011\u0014\b\u001d\u001b\u0019\u0018\u0016\u0014\u0012\u000f\r\f\t\b\n\r\u0010\u0007\u0007\u0007\u0001\u0002\u0003\u0005\u0006\u0007\t\u000b\r\u0010\u0014\u0019\u001c\u001c\u001c\u001c\u001c\u001c\u001b\u001a\u0019\u0017\u0015\u0014\u0014\u0016\u001a\u0005\u000f\u001b\u000e\u0002\u0002\u0005\b\u0010\u0017\u001b\u001c\u001c\u001c\u001c\u001c\u001c\u001b\u001a\u0019\u0017\u0015\u0014\u0014\u0001\u0001\u0016\u0001\u0010\u001e\u001b\u0019\u0017\u0015\u0013\u0012\u0011\u000f\u000e\f\n\u000b\f\r\u000f\u0010\u0013\u0015\u001a\u001c\u001c\u001c\u001c\u001c\u001c\u001b\u001b\u001a\u0019\u0018\u001a\u001c\u0001\u000e\u001c\u001a\u0018\u0017\u0015\u0014\u0013\u0012\u0012\u0010\u0010\u000f\f\r\u000f\u0010\u0013\u0015\u001a\u001c\u001c\u001c\u001c\u001c\u001c\u001b\u001b\u001a\u0019\u0018\u0018\u0018\u001b\u0005\u0011\u0019\u0016\u0015\u0013\u0001\u0012\u0002\u0013\u0002\u0014\u0002\u0019\u0001\u0001\u0019\u0001\u0001\u0019\u0002\u0012\u0001\u0003\u0011\u0003\u000e\u0003\f\u0004\u000b\u0003\t\u0002\u0001\u0007\u0001\u0001\u0007\u0001\b\u0002\u000b\u0001\u0011\u0019\u0003\u0013\u0004\u0004\u0011\u0002\u0006\r\u0005\u000b\u0006\u0003\f\u0005\u000e\u0002\u0014\u000b\u0010\u001b\u0017\u0015\u0013\u0011\u0010\u0010\u0010\u0011\u0011\u0010\u0010\u0010\u0010\u0011\u0014\u0017\u0018\u0001\u0018\u0006\u0018\u0006\u000b\t\b\u0001\u0001\u0007\u0010\t\u0010\u000e\b\u0014\u0004\u0018\f\u000e\u0002\u0018\u0015\u0012\u000f\f\b\b\b\b\b\n\u000b\u0018\u0004\u001a\u0004\u0019\u0004\u0018\u0006\u0017\u0007\u0016\b\u0016\t\u0015\n\u0013\f\u0011\u001f\u0007\u0016\u001f\u0015\u0017 \u0005\u0011\u0019\u0016\u0015\u0013\u0001\u0012\u0002\u0013\u0002\u0014\u0002\u0019\u0001\u0001\u0019\u0001\u0001\u0019\u0002\u0012\u0001\u0003\u0011\u0003\u000e\u0003\f\u0004\u000b\u0003\t\u0002\u0001\u0007\u0001\u0001\u0007\u0001\b\u0002\u000b\u0001\u0011\u0019\u0003\u0013\u0004\u0004\u0011\u0002\u0006\u000f\u0001\u0005\u0013\u0003\u0013\u0011\u0002\u0015\u000b\u0010\u001b\u0017\u0015\u0013\u0011\u0010\u0010\u0010\u0011\u0011\u0010\u0010\u0010\u0010\u0011\u0014\u0017\u0018\u0001\u0018\u0006\u0018\u0006\u0016\b\u0001\u0001\u000f\u0011\u0001\u000b\u001f !\f\u000e\u0002\u0018\u0015\u0012\u000f\f\b\b\b\b\b\n\u000b\u0018\u0004\u001a\u0004\u0019\u0004\u0018\u0006\u0017\u0007\u0016\b\u0016\t \u0014A\u0001\u000e\u001c\u001a\u0018\u0016\u0014\u0012\u0010\u000e\u000e\u000e\u000e\u000e\u000e\u000e\u000e\u000e\u000e\u000e\u000e\u000e\u000e\u000e\u000e\u000f\u0011\u0013\u0015\u0017\u0019\u001b\u001d\u0001\u000e\u001a\u0018\u0016\u0014\u0012\u0010\u000e\u000e\u000e\u000e\u000e\u000e\u000e\u000e\u000e\u000e\u000e\u000e\u000e\u000e\u000e\u000e\u000e\u000e\u000f\u0011\u0013\u0015\u0017\u0019\u001b\u0019\u000e\u001a\u0016\u0012\u000e\n\u0006\u0002\u0002\u0006\n\u000e\u0012\u0016\u001a\u0013\u000e\u001c\u001c\u001c\u001a\u0019\u0016\u0002\u0007\u000b\u0003\u0001\n\u0002\u0001\u0001\r\u0004\f\u0002\b\u0004\u0002\u0001\u0003\u0003\u0001\u0001\u0003\u0003\u0006\u0002\u0002\u0002\u0001\u0003\u0002\u0004\u0005\u0004\u0001\u0002\u0013\u0001\u0001\u0002\u0004\u0012\u0005\u0017\u0005\u001b\u001c\u0013\u000e\u001c\u001c\u001a\u0019\u0018\u000e\u0007\u0002\f\u0001\u0003\u000b\u0001\u0001\u0002\n\u0004\r\u0002\f\u0001\u0002\u0004\b\u0003\u0003\u0001\u0001\u0003\u0003\u0002\u0003\u0001\u0002\u0002\u0002\u0010\u0002\u0001\u0004\u0005\n\u0004\u0002\u0001\u0001\u0012\u0005\u0015\u0005\u001b\"\u0019\u000euuv\u001arruw\u0016srtv\u0012t\u000er\n\u0006\u0002\u0002\u0006\n\u000e\u0012r\u0016rtu\u001asu\u000e\u000b\\ZVUTSUVZ\\\u0014\\VTVY\\\\\\\\YVTV\\\u0010\\VW\\ZZYYYYYZ[Z\\WV\\\u000eW\\YXXXWWWYZTU[XY\\W\u000eUYXXWWWWWWXZZXWXYU\u000e]VSUVYXXXYZZXVUSV]\u000e\\[\\VTSUXZZXUSTW]\\\\\u000e[YYZ\\YVSSTUW[][Z[\\\u000eZYXY[\\\\\\\\\\\\[YZ[YZ[\u000e[YXXYZYWZYXZXXZYZ[\u000eYZXWXYXVYXXZXXYYZY\u000eXXYWWXWVYXWYXZYYYX\u000e\\VSWVWVVXWVXXYWUX]\u000e\\\\XUSTUVWVWVUUY[]]\u000e[YYZ\\WTSSTUW[]]Z[\\\u000eZYXWZXZ\\\\\\\\[Y[YYZ\\\u000e[YXVYVWWX[ZXYZYYZ[\u000e\\ZXVWVWVVWXXYXYYZ[\u000e[[YWVVXVVVXXYXYYZ[\u000eYZ\\XWVVVVVYWXXY]\\Z\u000fYX[\\[XWVWWY\\]]YZ\u0012ZXY[\\]]]ZYXZ\u0016\\YXWXYZ\\\u0019\u000e\u001a\u0016\u0012\u000e\n\u0006\u0002\u0002\u0006\n\u000e\u0012\u0016\u001a\u0019\u000e\u001a\u0004\u0004\u0004\u0016\u0004\u0004\u0003\u0003\u0003\u0004\u0012\u0004\u0004\u0003\u0003\u0003\u0003\u0004\u0004\u000e\u0004\u0004\u0003\u0003\u0003\u0003\u0004\u0004\n\u0004\u0004\u0003\u0003\u0003\u0003\u0004\u0004\u0006\u0004\u0004\u0003\u0003\u0003\u0003\u0004\u0004\u0002\u0004\u0004\u0003\u0003\u0003\u0003\u0004\u0004\u0002\u0004\u0004\u0004\u0004\u0006\n\u000e\u0012\u0016\u001a\u0019\u000e\u001a\u0004\u0004\u0004\u0016\u0004\u0003\u0003\u0003\u0004\u0004\u0012\u0004\u0004\u0003\u0003\u0003\u0003\u0004\u0004\u000e\u0004\u0004\u0003\u0003\u0003\u0003\u0004\u0004\n\u0004\u0004\u0003\u0003\u0003\u0003\u0004\u0004\u0006\u0004\u0004\u0003\u0003\u0003\u0003\u0004\u0004\u0002\u0004\u0004\u0003\u0003\u0003\u0003\u0004\u0004\u0002\u0004\u0004\u0004\u0004\u0006\n\u000e\u0012\u0016\u001a\u0019\u000e\u0004\u0004\u0004\u0004\u001a\u0004\u0004\u0004\u0003\u0003\u0004\u0004\u0004\u0016\u0004\u0004\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0004\u0004\u0012\u0004\u0004\u0003\u0003\u0003\u0003\u0004\u0004\u0004\u0004\u0003\u0003\u0003\u0003\u0004\u0004\u000e\u0004\u0004\u0003\u0003\u0003\u0003\u0004\u0004\u0004\u0004\u0003\u0003\u0003\u0003\u0004\u0004\n\u0004\u0004\u0003\u0003\u0003\u0003\u0004\u0004\u0004\u0004\u0003\u0003\u0003\u0003\u0004\u0004\u0006\u0004\u0004\u0003\u0003\u0003\u0003\u0004\u0004\u0004\u0004\u0003\u0003\u0003\u0003\u0004\u0004\u0002\u0004\u0004\u0003\u0003\u0003\u0003\u0004\u0004\u0004\u0004\u0003\u0003\u0003\u0003\u0004\u0004\u0002\u0004\u0004\u0004\u0004\u0004\u0004\u0004\u0004\u0006\n\u000e\u0012\u0016\u001a\u0019\u000e\u001a\u0016\u0012\u000e\n\u0006\u0002\u0002\u0006\n\u000e\u0012\u0016\u001a\u0006\r\u0019\u0018\u0018\u0018\u0018\u0018\u0018\u0018\u0018\u0018\u0017\u0016\u0016\u0016\u0016\u0016\u0015\u0014\u0014\u0014\u0013\u0012\u0012\u0012\u0013\u0016\u0019\u0007\u000f\u001d\u001c\u001c\u001b\u001a\u001a\u001a\u001a\u001a\u001a\u0019\u0018\u0018\u0018\u0018\u0018\u0018\u0018\u0018\u0018\u0018\u0018\u0018\u0018\u0018\u0018\u001a\u0006\u000e\u001b\u001a\u001a\u0019\b\b\u0017\u0007\u0007\b\b\u0007\u0007\u0015\b\u0007\u0006\u0006\u0007\u0007\u0007\u0007\u0006\u0006\u0007\b\u0014\t\b\u0007\u0006\u0005\u0004\u0005\u0005\u0006\u0007\b\t\u0015\n\t\b\b\u0007\b\b\b\t\n\u0017\n\t\t\t\b\t\t\n\u0017\n\n\n\t\n\n\u0016cb\u0016\u0001\u0017\u0016\bac\u0017\b\u0007\u0016\u0006\b\u0007\u0006\u0014\u0007\u0006\u0007\b\b\b\b\u0007\u0006\u0007\u0011\t\u0007\u0006\u0006\u0006\u0006\u0006\u0006\u0007\t\u000e\t\b\u0007\u0006\u0005\u0005\u0006\u0007\b\t\u000b\b\u0007\u0006\u0006\u0005\u0006\u0007\b\t\u0007\u0006\u0006\u0007\u0007\u0005\u0003\u0002\u0001\u0003瑐琐\t璐\u0011\u0006\u000e\u001b\u001a\u001a\u0019\b\b\u0017\u0007\u0007\b\b\u0007\u0007\u0015\b\u0007\u0006\u0006\u0007\u0007\u0007\u0007\u0006\u0006\u0007\b\u0014\t\b\u0007\u0006\u0005\u0004\u0005\u0005\u0006\u0007\b\t\u0015\n\t\b\b\u0007\b\b\b\t\n\u0017\n\t\t\t\b\t\t\n\u0017\n\n\n\t\n\n\u0016cb\u0016\u0001\u0017\u0016\bac\u0017\b\u0007\u0016\u0006\b\u0007\u0006\u0014\u0007\u0006\u0007\b\b\b\b\u0007\u0006\u0007\u0010\t\u0007\u0006\u0006\u0006\u0006\u0006\u0006\u0007\t\r\t\b\u0007\u0006\u0005\u0005\u0006\u0007\b\t\u000b\b\u0007\u0006\u0006\u0005\u0006\u0007\b\f\u0007\u0006\u0006\u0007\f\u000b\n\t\t\u000b\r\u000f\u0012\u0015\u0018\u001b\u0006\u000e\u001b\u001a\u001a\u0019\b\b\u0017\u0007\u0007\b\b\u0007\u0007\u0015\b\u0007\u0006\u0006\u0007\u0007\u0007\u0007\u0006\u0006\u0007\b\u0014\t\b\u0007\u0006\u0005\u0004\u0005\u0005\u0006\u0007\b\t\u0015\n\t\b\b\u0007\b\b\b\t\n\u0017\n\t\t\t\b\t\t\n\u0017\n\n\n\t\n\n\u0016cb\u0016\u0001\u0017\u0016\bac\u0017\b\u0007\u0016\u0006\b\u0007\u0006\u0016\u0007\u0006\u0007\b\b\b\b\u0007\u0006\u0007\u0015\t\u0007\u0006\u0006\u0006\u0006\u0006\u0006\u0007\t\u0011\t\b\u0007\u0006\u0005\u0005\u0006\u0007\b\t\u000e\b\u0007\u0006\u0006\u0005\u0006\u0007\b\f\u0007\u0006\u0006\u0007\u000b\n\t\t\t\t\u000b\u000e\u0011\u0014\u0017\u001a\u0006\u000e\u001b\u001a\u001a\u0019\b\b\u0017\u0007\u0007\b\b\u0007\u0007\u0015\b\u0007\u0006\u0006\u0007\u0007\u0007\u0007\u0006\u0006\u0007\b\u0014\t\b\u0007\u0006\u0005\u0004\u0005\u0005\u0006\u0007\b\t\u0015\n\t\b\b\u0007\b\b\b\t\n\u0017\n\t\t\t\b\t\t\n\u0017\n\n\n\t\n\n\u0016cb\u0016\u0001\u0017\u0016\bac\u0017\b\u0007\u0016\u0006\b\u0007\u0006\u0016\u0007\u0006\u0007\b\b\b\b\u0007\u0006\u0007\u0016\t\u0007\u0006\u0006\u0006\u0006\u0006\u0006\u0007\t\u0016\t\b\u0007\u0006\u0005\u0005\u0006\u0007\b\t\u0017\b\u0007\u0006\u0006\u0005\u0006\u0007\b\u0019\u0007\u0006\u0006\u0007\u001a\u0018\u0011\t\u0003\u0002\u0006\n\u000e\u0012\u0016\u001a\u0004\u000f\u001f\u001d\u0001\u0002\u001a\u0019\u0017\u0015\u0014\u0014\u0014\u0014\u001555\u0016225553\u00165204555333\u00165552320455\u001655520355\u0014\b5555\b\u0010\b\b\b\b\r6\t\b\b\t6\u000b665\t\b\b\t556\n5663522267\b56633357\u00075525\u0006\u0006\u0006\u0006\u0006\u0006\b\n\r\u0010\u0013\u0016\u001a\u0004\u000f\u001f\u001d\u0001\u0002\u001a\u0019\u0017\u0015\u0014\u0014\u0014\u0014\u001555\u0016225553\u00165204555333\u00165552320455\u001655520355\u0016\b5555\b\u0016\b\b\b\b\u00166\t\b\b\t6\u0016665\t\b\b\t556\u00155663522267\u001456633357\u00145525\u0010\t\u0003\u0002\u0006\n\u000e\u0012\u0016\u001a\u0004\u000f\u001f\u001d\u0001\u0002\u001a\u0019\u0017\u0015\u0014\u0014\u0014\u0014\u001555\u0016225553\u00165204555333\u00165552320455\u001455520355\u0011\b5555\b\u000e\b\b\b\b\u000b6\t\b\b\t6\t665\t\b\b\t556\u00075663522267\u000556633357\u00035525\u0002\u0001\u0003ꑐꐐ\t꒐\u0011\u0004\u000f\u001f\u001d\u0001\u0002\u001a\u0019\u0017\u0015\u0014\u0014\u0014\u0014\u001555\u0016225553\u00165204555333\u00165552320455\u001655520355\u0016\b5555\b\u0014\b\b\b\b\u00106\t\b\b\t6\f665\t\b\b\t556\b5663522267\u000756633357\u00065525\u0006\u0006\u0006\u0006\u0006\u0006\u0006\t\f\u000f\u0012\u0016\u001a\u0004\u000e\t\t\t\t\u001a\n\tfeef\t\n\u0017\ndca``acd\n\u0014f``f\u0011faaf\u0010f``f\u0010dca``acd\u0010feef\u0010\u0010\u0010\u0010ii\u0010hffh\u0010geeg\u0010fddf\u0010fddf\u0010geeg\u0010hffh\u0010gg\u0010\u0010\u0010\u0010f\u000egd\tfe\u0003g\u0002\u0006\n\u000e\u0012\u0016\u001a\u0004\u000e\t\t\t\t\u001a\n\tfeef\t\n\u0017\ndca``acd\n\u0014f``f\u0011faaf\u0010f``f\u0010dca``acd\u0010feef\u0010\u0010\u0010\u0010ii\u0010hffh\u0010geeg\u0010fddf\u0010fddf\u0010geeg\u0010hffh\rgg\n\b\u0007\u0006f\u0006gd\u0006fe\u0006g\u0006\u0006\u0006\u0006\t\f\u000f\u0012\u0016\u001a\u0004\u000e\t\t\t\t\u001a\n\tfeef\t\n\u0017\ndca``acd\n\u0014f``f\u0011faaf\u0010f``f\u0010dca``acd\u0010feef\u0010\u0010\u0010\u0010ii\u0010hffh\u0010geeg\u0010fddf\u0010fddf\u0010geeg\u000ehffh\u000bgg\t\u0007\u0005\u0003f\u0002gd\u0001feg\u0003ꑐꐐ\t꒐\u0011\u0004\u000e\t\t\t\t\u001a\n\tfeef\t\n\u0017\ndca``acd\n\u0014f``f\u0011faaf\u0010f``f\u0010dca``acd\u0010feef\u0010\u0010\u0010\u0010ii\u0010hffh\u0010geeg\u0010fddf\u0010fddf\u0010geeg\rhffh\ngg\b\b\b\u0007f\u0006gd\u0006fe\u0006g\u0006\u0006\u0006\b\n\r\u0010\u0013\u0016\u001a\u001b\n\u0011\u000b\u0006\u0003⒓\u0001\u0002\u0006\n\u000e\u0012\u0016\u001a\u0015\t\u001a\u0015\u0011ē\u000f\u000e\r\f\u000b\u000b\n\n\f\u000e\u0010\u0013\u0016\u0018\u001b\u0010\u000f\u001b\u0016\u0012\u000f\r\u000b\t\u0007\u0006\u0005\u0004\u0003\u0002\u0001\u0003\b\u000f\u0015\u0014\u001b\u0017\u0012\u000e\r\f\u000b\u000b\n\n\n\n\f\u000f\u0012\u0014\u0017\u001b\u0013\u000e\u001a\u0016\u0012\u000f\r\u000b\t\b\u0007\u0006\u0006\u0005\u0002\u0002\u0006\n\u000e\u0012\u0016\u001a\u0017\u0012\u001a\u000b\u0003\u0006\u0003\u0003\u0003\u0003\u0002\u0002\u0006\n\u000e\u0012\u0016\u001a\u0017\u000f\u001a\u0017\u0016\u0014醆u\u0012t\u000e\n\u0006\u0002\u0002\u0006\n\u000e\u0012\u0016\u001a\u0017\n\u0017\u0012\u0003\u0006\u0004\u0003\u0003\u0003\u0003\u0002\u0002\u0006\n\u000e\u0012\u0016\u001a\u0014\f\u0016\u0012\u000e\u000b\t\u0007\u0005\u0006\u0003\b\u0002\u0001\t\u0003\u0001\u0010\u0001\u000e\u0001\u000b\u0004왘\t뚙\t\b\u0017\u0005\u0014\u000e\f\u000b\t\u0007\u0006\u0006\u0006\b\n\r\u0010\u0013\u0016\u001a\u0017\u0012\u0013\u000e\u000b\t\u0007\u0006\u0006\u0006\u0006\u0006\t\f\u000f\u0012\u0016\u001a\u001d\u0006\u000b\t\t\u0003\u0005\u0002\u0006\n\u000e\u0012\u0016\u001a\u0019\u000e\u001a\u0016\u0012\u000e\n\u0006\u0002\u0002\u0006\n\u000e\u0012\u0016\u001a\u0019\u000e\u001a\u0016\u0012\u000e\n\u0006\u0002\u0002\u0006\n\u000e\u0012\u0016\u001a\u0019\u000e\u001a\u0016\u0012\u000e\n\u0006\u0002\u0002\u0006\n\u000e\u0012\u0016\u001a\u0019\u000e\u001a\u0016\u0012\u000e\n\u0006\u0002\u0002\u0006\n\u000e\u0012\u0016\u001a\u0005\r\u0017\u0013\u0012\u0012\u0012\u0012\u0012\u0012\u0012\u0012\u0012\u0012\u0012\u0012\u0012\u0012\u0012\u0012\u0012\u0012\u0012\u0012\u0012\u0012\u0012\u0012\u0012\u0012\u0013\u0017\u0005\r\u0017\u0013\u0012\u0012\u0012\u0012\u0012\u0012\u0012\u0012\u0012\u0012\u0012\u0012\u0012\u0012\u0012\u0012\u0012\u0012\u0012\u0012\u0012\u0012\u0012\u0012\u0012\u0012\u0013\u0017"
  },
  {
    "path": "bin/standard/xcom1/UNITS/CHRYS.PCK",
    "content": "\f\t\u000b\u001e\u000b\f\u001e\n\f\u001e\u000b\f\u001d\n\f\u001d\u000b\u000b\u000b\u001d\u000b\n\u000b\u001e\t\n\u000b\u001d\u000b\n\f\u001e\u000b\t\u001f\u000b\n\u000b\f\n\u001e\u000b\b\n\u001d\n\u0007\n\u001d\u000b\t\t\u001d\n\b\u000b\u000b\u001c\n\u000b\u001b\u000b\t\u000b\t\u000b\u001b\n\n\t\n\b\u001b\t\u0007\n\b\n\u001b\b\u0006\u000b\u0007\t\u001b\t\u0007\u0001\t\u0007\u001c\b\u0002\b\u001f\u000b\r\u0015\u000b\u001f\u000b\u001f\n\u000b\u001e\n\u000b\u001e\t\f\f\u001c\n\u000b\n\u000b\u001d\f\t\n\u001b\t\u000b\u000b\b\u000b\u001c\u000b\b\t\u001e\t\u000b\u0018\u000b\r\u001e\t\u000b\r\u001d\u000b\n\f\u001d\f\u000b\n\f\u001d\f\u000b\f\u001d\f\u000b\u001c\f\n\b\t\f\u001b\u000b\n\t\n\u000b\u001a\t\u0007\n\u000b\n\u000b\u001a\u0007\b\u000b\u0007\n\f\u0019\b\b\u0001\b\u0007\u000b\u001a\t\r\u0001\u0007\t\u001b\r\r\u0001\b\u001e\b\f\u0015\f\u001e\u000b\u001e\t\n\f\u001d\n\t\u000b\f\u001d\n\n\u000b\u001d\t\n\u001d\u000b\u001b\u000b\n\b\t\n\u001a\b\n\t\t\n\u000b\u0019\u0007\n\u000b\b\n\u000b\f\u0019\b\u000b\u0007\u000b\n\u000b\u001b\u0007\b\n\t\u001b\t\b\r\t\u001c\b\u000e\u0013\n\u001e\n\b\u000b\u001d\n\u0007\n\u001c\t\t\u000b\u001b\u000b\u000b\b\n\u001b\u000b\n\u001b\u000b\t\u000b\t\u000b\u001b\b\n\t\n\n\u001b\n\b\n\u0007\t\u001b\t\u0007\u000b\u0006\b\u001b\u0007\t\u0001\u0007\t\u001b\b\u0002\b\u001c\u000b\f\f\u000b\u001e\f\n\u000b\u001d\u000b\n\n\u001c\f\n\u000b\f\u001c\u000b\n\f\u001d\n\n\u001d\n\u001d\n\b\t\n\u001c\u000b\t\n\n\u000b\u001c\u000b\n\u000b\u000b\u001c\f\u000b\b\u000b\t\n\u001b\f\t\b\u000b\u001d\u000b\t\u0007\b\u000b\u0006\r\u000b\u001d\r\u000b\n\u001d\f\n\u000b\u001c\f\n\u000b\f\u001b\f\u000b\f\u001c\f\u001c\f\b\t\n\f\u001b\u000b\n\n\u000b\f\u001b\f\u000b\u000b\u000b\f\t\u001a\f\u000b\u0007\f\u000b\n\u001b\f\b\u000b\u0001\u000b\n\u001b\n\b\u0001\r\u000b\u001c\f\u0001\r\r\f\u0013\u000b\u001e\u000b\n\f\u001d\n\n\u000b\u001d\f\u000b\n\f\u001d\f\n\u000b\u001d\n\n\u001d\n\u001c\n\t\b\n\u001b\u000b\n\n\t\u000b\u001b\u000b\u000b\n\u000b\u001a\n\t\u000b\b\u000b\f\u001b\u000b\b\t\f\u001b\b\u0007\t\u000b\u000e\f\n\u001e\u000b\b\n\u001d\n\u0007\n\u001d\u000b\t\t\u001d\n\b\u000b\u000b\u001c\n\u000b\u001b\u000b\t\u000b\t\u000b\u001b\n\n\t\n\b\u001b\t\u0007\n\b\n\u001b\b\u0006\u000b\u0007\t\u001b\t\u0007\u0001\t\u0007\u001c\b\u0002\b\u001f\u000b\f\t\f\u001e\u000b\u001d\f\n\t\u001c\f\u000b\t\n\u001c\u000b\n\n\u001d\n\t\u001d\u000b\u001d\n\t\b\n\u000b\u001b\u000b\n\t\t\n\b\u001a\f\u000b\n\b\u000b\n\u0007\u001a\u000b\n\u000b\u0007\u000b\b\u001b\t\n\b\u0007\u001d\t\r\b\t\u001f\b\u000b\u0006\r\u000b\u001d\r\u000b\t\u001d\f\n\u000b\u001c\f\n\u000b\f\u001b\f\u000b\f\u001c\u000b\f\u001c\f\t\b\n\f\u001b\u000b\n\t\n\u000b\u001b\u000b\n\u000b\n\u0007\t\u001a\f\n\u0007\u000b\b\u0007\u001b\u000b\u0007\b\u0001\b\b\u001b\t\u0007\u0001\r\t\u001c\b\u0001\r\r\u001d\b\r\n\u000b\u001f\u000b\u001e\u000b\n\u001e\u000b\n\u001d\f\f\t\u001d\u000b\n\u000b\n\u001c\n\t\f\u001d\u000b\b\u000b\u000b\t\u001c\t\b\u000b\u001e\t\u000b\u0013\n\u001e\n\b\u000b\u001d\n\u0007\n\u001c\t\t\u000b\u001b\u000b\u000b\b\n\u001b\u000b\n\u001b\u000b\t\u000b\t\u000b\u001b\b\n\t\n\n\u001b\n\b\n\u0007\t\u001b\t\u0007\u000b\u0006\b\u001b\u0007\t\u0001\u0007\t\u001b\b\u0002\b\u001c\u000b\f\u0016\u000b\u001f\f\u000b\u001e\f\n\u001d\f\u000b\u001d\f\n\u001d\u000b\u000b\u000b\u001d\u000b\n\u000b\u001c\u000b\n\t\u001d\f\n\u000b\u001d\t\u000b\u001d\n\u000b\u000b\u0018\u000b\r\u001e\n\u000b\r\u001d\u000b\n\f\u001d\f\u000b\n\f\u001d\f\u000b\f\u001d\f\u001c\f\n\t\b\f\u001b\f\u000b\n\n\u000b\u001a\t\f\u000b\u000b\u000b\f\u001a\n\u000b\f\u0007\u000b\f\u0019\n\u000b\u0001\u000b\b\f\u001a\u000b\r\u0001\b\n\u001b\r\r\u0001\f\u0012\u000b\u000b\u000b\t\f\u000b\n\f\n\n\u0017\f\t\b\f\r\u000b\u000b\f\u000b\u0017\f\u000b\n\r\u000b\u000b\n\u000b\f\u0017\f\f\f\f\u000b\n\n\n\n\u000b\u0017\u000b\f\f\u0001\u000b\n\t\b\n\u000b\u0016\n\u000b\f\u0002\f\u000b\n\t\n\f\u0015\u000b\n\f\u0004\f\u000b\u000b\u000b\u0014\u000b\f\f\u0006\f\u000b\f\u0013\u000b\n\u000b\u0007\u000b\r\f\u0012\f\n\u000b\f\u0006\n\t\u000b\u0013\u000b\u000b\f\u0006\u000b\b\u000b\u0014\f\u000b\r\u0005\u000b\t\n\u0015\u000b\n\u000b\f\u0004\f\u000b\f\u0015\u000b\u000b\u000b\f\t\u0003\f\n\u000b\u000b\u001d\u000b\t\u000b\f\f\u001b\n\t\n\u000b\f\b\u0012\r\u000b\u000b\u000b\n\t\t\n\u0018\f\u000b\n\n\t\n\f\t\u0018\f\f\r\f\f\r\f\n\u0018\f\r\f\n\n\u000b\r\u000b\u0019\f\u000b\n\t\u000b\f\u001b\f\n\b\n\u001b\f\f\u000b\t\n\f\u0019\u000b\f\f\f\n\u000b\u000b\u0018\u000b\u000b\u000b\u0002\u000b\n\f\u0017\u000b\n\f\u0001\n\t\r\u000b\f\u0018\f\f\n\t\t\u000b\u001b\n\t\n\u000b\f\u001a\n\t\u000b\f\f\u000b\n\u0018\f\u000b\u000b\u001e\f\u000b\n\u000b\u001d\u000b\u000b\n\n\u000b\u001b\u000b\r\f\u000b\n\u0007\u0012\u000b\u000b\n\t\t\b\f\t\f\t\u0017\f\u000b\f\r\u000b\n\n\u000b\u000b\f\u0016\f\u000b\n\f\r\u000b\u000b\f\f\f\u0017\u000b\t\u000b\f\f\f\r\f\n\f\u0015\f\n\b\n\f\u0002\f\n\n\u000b\u0015\f\u000b\n\u000b\f\u0003\f\u000b\u000b\u000b\u0014\r\r\u000b\f\u0005\f\f\f\u0014\f\u000b\r\f\u0005\n\u000b\f\u0014\u000b\n\u000b\u0005\u000b\u000b\f\u0014\u000b\t\f\u0004\f\u000b\u000b\f\r\u0013\f\n\f\u0005\r\f\f\r\u0013\f\u000b\u000b\u0007\r\f\f\f\u0011\f\n\u000b\f\u0007\f\u000b\n\u000b\f\u0010\f\u000b\t\u000b\f\u0006\u000b\u000b\u0007\r\f\n\u0010\f\u000b\n\u000b\f\u001b\f\u000b\u0007\r\f\n\u0012\u000b\u000b\n\b\f\t\t\f\b\n\u000b\u0015\f\r\r\f\u000b\n\n\u000b\f\r\r\f\u0013\f\u000b\n\u000b\r\f\u000b\u000b\f\r\u000b\n\u000b\f\u0011\f\u000b\n\t\n\u000b\r\f\f\r\u000b\n\t\n\u000b\f\u000f\r\u000b\u000b\u000b\n\u000b\f\r\u0002\r\f\u000b\n\u000b\u000b\u000b\r\u000e\r\r\r\f\u000b\r\u0006\r\u000b\f\r\r\r\u000e\u000b\u000b\f\r\r\b\r\r\f\u000b\u000b\u000e\f\n\u000b\f\n\f\u000b\n\f\u000f\f\n\u000b\f\b\f\u000b\n\f\u0011\f\u000b\f\f\u0006\f\f\u000b\f\u0013\r\r\f\u0006\f\r\r\u0014\f\f\r\u0006\r\f\f\u0012\u000b\f\u000b\r\b\r\u000b\f\u000b\u000f\u000b\n\f\n\u000b\b\u000b\n\f\n\u000b\u000e\u0007\f\r\f\u0007\b\u0007\f\r\f\u0007\u0012\f\t\f\t\f\b\t\t\n\u000b\u0016\f\u000b\u000b\n\n\u000b\r\f\u000b\f\u0016\f\f\f\u000b\u000b\r\f\n\u000b\f\u0015\f\n\f\r\f\f\f\u000b\t\u000b\u0016\u000b\n\n\f\u0002\f\n\b\n\f\u0014\u000b\u000b\u000b\f\u0003\f\u000b\n\u000b\f\u0014\f\f\f\u0005\f\u000b\r\r\u0014\f\u000b\n\u0005\f\r\u000b\f\u0015\f\u000b\u000b\u0005\u000b\n\u000b\u0015\r\f\u000b\u000b\f\u0004\f\t\u000b\u0015\r\f\f\r\u0005\f\n\f\u0013\f\f\f\r\u0007\u000b\u000b\f\u0011\f\u000b\n\u000b\f\u0007\f\u000b\n\f\u000f\n\f\r\u0007\u000b\u000b\u0006\f\u000b\t\u000b\f\u001a\f\u000b\n\u000b\f\u001a\n\f\r\u0007\u000b\f\u0012\f\n\t\t\n\u000b\u000b\u000b\t\u0018\t\f\n\t\n\n\u000b\f\u0018\n\f\r\f\f\r\f\f\u0018\u000b\r\u000b\n\n\f\r\f\u0019\f\u000b\t\n\u000b\f\u001b\n\b\n\f\u001b\f\n\t\u000b\f\f\u001a\u000b\u000b\n\f\f\f\u000b\u0019\f\n\u000b\u0002\u000b\u000b\u000b\u0018\f\u000b\r\t\n\u0001\f\n\u000b\u0019\u000b\t\t\n\f\f\u001a\f\u000b\n\t\n\u001a\n\u000b\f\f\u000b\t\n\u001e\u000b\u000b\f\u001b\u000b\n\u000b\f\u001a\u000b\n\n\u000b\u000b\u001a\u0007\n\u000b\f\r\u000b\u0012\f\t\u000b\f\n\u000b\f\t\u000b\u000b\u0017\u000b\f\u000b\u000b\r\f\b\t\f\u0017\f\u000b\n\u000b\u000b\r\n\u000b\f\u0016\u000b\n\n\n\n\u000b\f\f\f\f\u0015\u000b\n\b\t\n\u000b\u0001\f\f\u000b\u0015\f\n\t\n\u000b\f\u0002\f\u000b\n\u0015\u000b\u000b\u000b\f\u0004\f\n\u000b\u0015\f\u000b\f\u0006\f\f\u000b\u0014\f\r\u000b\u0007\u000b\n\u000b\u0014\u000b\t\n\u0006\f\u000b\n\f\u0014\u000b\b\u000b\u0006\f\u000b\u000b\u0015\n\t\u000b\u0005\r\u000b\f\u0015\f\u000b\f\u0004\f\u000b\n\u000b\u0014\u000b\u000b\n\f\u0003\t\f\u000b\u000b\u000b\u0012\f\f\u000b\t\u000b\u001a\b\f\u000b\n\t\n\u0012\u000b\u000b\f\n\f\n\n\f\n\f\u000b\u0015\f\r\r\f\f\b\b\f\f\r\r\f\u0013\r\u000b\n\u000b\r\f\n\n\f\r\u000b\n\u000b\r\u0011\r\f\u000b\t\n\u000b\r\f\f\r\u000b\n\t\u000b\f\r\u000f\r\f\f\f\u000b\u000b\f\r\u0002\r\f\u000b\u000b\f\f\f\r\u000e\r\r\f\f\f\r\u0006\r\f\f\f\r\r\u000e\f\f\r\r\r\b\r\r\r\f\f\u000e\f\u000b\n\f\n\f\u000b\u000b\f\u000f\f\u000b\n\f\b\f\n\u000b\f\u0011\f\u000b\n\f\u0006\f\n\u000b\f\u0013\r\f\n\u0006\n\f\r\u0014\f\u000b\r\u0006\r\u000b\f\u0012\r\f\f\r\b\r\f\f\r\u000f\f\f\u000b\n\u000b\b\u000b\n\u000b\f\f\u000e\f\u000b\n\t\f\b\f\t\n\u000b\f\u0007\u000e\f\u000b\u000b\u000b\f\u0017\u000b\u0002\u000b\u000b\n\t\n\u000b\f\u0016\n\u0001\u000b\n\t\u0007\b\t\t\u000b\u0016\n\u000b\n\b\u000b\t\u000b\f\u0016\u000b\n\f\n\t\u000b\n\r\f\u0015\f\u000b\u000b\u000b\n\t\u000b\n\u0016\n\f\u000b\n\t\f\t\t\u0016\u000b\n\f\u000b\f\u000b\t\t\u0017\f\f\f\f\f\n\n\u0017\u000b\f\f\u000b\u000b\u000b\n\n\u000b\u0017\n\u000b\n\f\n\u000b\f\f\u000b\u0007\u000e\f\f\u000b\u000b\u000b\f\u0019\f\u000b\u000b\n\t\n\u000b\f\u0013\u000b\u0003\f\u000b\n\t\b\u0006\u0007\b\n\u0012\u000b\t\u0003\u000b\n\t\u0007\b\t\n\u0013\n\u000b\u0001\u000b\n\u000b\f\f\r\f\u000b\u0013\u000b\n\f\n\t\n\u000b\f\f\u000b\f\r\u000b\u0013\f\u000b\t\u000b\n\n\f\n\u000b\f\n\u0014\f\n\t\n\f\u000b\n\n\u0005\u0015\f\n\f\u000b\f\u000b\n\u0006\u0016\n\n\u000b\f\u000b\t\n\f\u000b\u000b\u0016\f\f\f\f\u000b\u000b\f\f\f\u0007\u000e\f\f\u000b\u000b\f\n\u0014\n\u0004\f\u000b\n\t\n\u000b\f\u0014\u000b\n\u0003\u000b\n\t\b\u0006\b\n\u0015\f\u000b\u0002\f\u000b\n\t\b\t\u000b\u0016\f\f\u000b\f\f\r\f\u000b\n\u000b\f\u0014\u000b\f\t\u000b\f\r\u000b\u000b\r\u000b\u0014\n\n\b\u000b\n\f\n\n\u000b\n\u0014\n\u000b\t\f\f\n\u0005\u0005\f\u000b\u0014\u000b\u000b\t\u000b\t\u000b\f\u0006\u0006\f\t\u0015\f\f\u000b\n\n\f\u000b\f\f\f\u000b\u0017\f\f\u000b\t\u000b\u000b\t\n\f\u0007\u0006\f\u000b\f\u0005\f\u000b\u000b\f\u0005\f\u000b\f\u000e\u000b\n\u0003\f\u000b\t\n\u000b\f\u0003\n\u000b\u0011\f\u000b\f\r\u000b\n\u0006\b\n\u000b\r\f\u000b\f\u0013\r\r\f\u000b\n\b\t\n\u000b\f\r\r\u0013\f\r\u000b\f\r\f\n\n\f\r\f\u000b\r\f\u0011\f\f\t\r\f\r\u000b\u000b\r\f\r\t\f\f\u0010\u000b\b\f\n\f\n\n\f\n\f\b\u000b\u0010\f\n\u000b\f\n\u0005\u0005\n\f\u000b\n\f\u0011\f\u000b\u000b\t\u000b\f\u0006\u0006\f\u000b\t\u000b\u000b\f\u0013\r\f\n\f\n\f\f\n\f\n\f\r\u0015\r\u000b\t\n\u000b\u000b\n\t\u000b\r\u0007\f\n\f\u000b\u000b\f\f\u001a\f\u000b\n\t\n\u000b\f\u0004\n\u0014\n\b\u0006\b\t\n\u000b\u0003\n\u000b\u0014\u000b\t\b\t\n\u000b\f\u0002\u000b\f\u0014\f\u000b\n\u000b\f\r\f\f\u000b\f\f\u0015\u000b\r\u000b\u000b\r\f\u000b\t\f\u000b\u0014\n\u000b\n\n\f\n\u000b\b\n\n\u0014\u000b\f\u0005\u0005\n\f\f\t\u000b\n\u0014\t\f\u0006\u0006\f\u000b\t\u000b\t\u000b\u000b\u0014\u000b\f\f\f\u000b\f\n\n\u000b\f\f\u0015\f\n\t\u000b\u000b\t\u000b\f\f\t\u0007\f\f\u000b\u000b\u000b\f\f\u0019\f\u000b\n\t\n\u000b\u000b\f\u0018\n\b\u0007\u0006\b\t\n\u000b\f\u0003\u000b\u0013\n\t\b\u0007\t\n\u000b\u0003\t\u000b\u0012\u000b\f\r\f\f\u000b\n\u000b\u0001\u000b\n\u0013\u000b\r\f\u000b\f\f\u000b\n\t\n\f\n\u000b\u0013\n\f\u000b\n\f\n\n\u000b\t\u000b\f\u0013\u0005\n\n\u000b\f\n\t\n\f\u0014\u0006\n\u000b\f\u000b\f\n\f\u0015\u000b\u000b\f\n\t\u000b\f\u000b\n\n\u0017\f\f\f\u000b\u000b\f\f\f\f\u0007\r\f\u000b\u000b\u000b\f\u001a\f\u000b\n\t\n\u000b\u000b\u0002\u000b\u0016\u000b\t\t\b\u0007\t\n\u000b\u0001\n\u0016\f\u000b\t\u000b\b\n\u000b\n\u0015\f\r\n\u000b\t\n\f\n\u000b\u0016\n\u000b\t\n\u000b\u000b\u000b\f\u0016\t\t\f\t\n\u000b\f\n\u0016\t\t\u000b\f\u000b\f\n\u000b\u0016\n\n\f\f\f\f\f\u0017\u000b\n\n\u000b\u000b\u000b\f\f\u000b\u0017\u000b\f\f\u000b\n\f\n\u000b\n\u0007\u000e\f\u000b\u000b\f\u001b\f\u000b\t\n\u000b\f\u0013\f\n\f\u0003\r\u000b\n\b\t\n\u000b\r\u0003\f\n\f\u000e\u000b\t\u0002\f\u000b\u000b\u000b\u000b\f\u0002\t\u000b\u0011\f\n\f\u000b\f\f\u000b\f\n\f\u0011\f\u000b\n\r\u000b\t\b\b\t\u000b\r\n\u000b\f\u0010\r\b\n\f\u000b\n\n\u000b\f\n\b\r\u0010\f\r\u000b\n\f\u000b\u000b\f\n\u000b\r\f\u0011\f\u000b\f\r\u000b\f\f\f\f\u000b\r\f\u000b\f\u0013\r\f\u000b\f\u000b\f\f\u000b\f\u000b\f\r\u0015\r\n\t\f\u000b\u000b\f\t\n\r\f\t\u000b\u000b\u001d\u000b\f\f\u001d\n\u000b\u000b\f\u000b\u000b\u001b\u000b\f\n\u000b\n\f\u001a\u000b\u000b\t\n\u000b\u000b\u001b\f\u000b\n\f\u000b\u000b\n\u001b\u000b\t\n\u000b\u001d\u000b\n\u0007\b\u000b\t\u000b\u000b\u001d\u000b\f\f\u001d\n\u000b\u000b\u001d\u000b\t\u000b\f\u001d\u000b\n\n\u000b\u000b\u001c\u000b\n\u000b\n\f\u001c\t\n\u000b\u000b\u001c\u000b\n\f\u000b\u000b\n\u001b\u000b\t\n\u000b\u001d\u000b\n\u0007\b\n\t\u000b\u000b\u001d\u000b\f\f\u001d\n\u000b\u000b\u001d\u000b\f\u001d\n\f\u001d\u000b\u000b\u000b\u000b\u001c\u000b\n\u000b\n\f\u001c\t\n\u000b\u000b\u001c\u000b\n\f\u000b\u000b\n\u001b\u000b\t\n\u000b\u001d\u000b\n\u0007\b\u000b\t\u000b\u000b\u001d\u000b\f\f\u001c\u000b\n\u000b\u000b\u001b\u000b\f\u001c\u000b\f\u000b\u000b\u001c\u000b\n\u000b\n\f\u001c\t\n\u000b\u000b\u001c\u000b\n\f\u000b\u000b\n\u001b\u000b\t\n\u000b\u001d\u000b\n\u0007\b\f\b\u000b\u000b\u000b\u001a\n\u000b\f\f\u0019\u000b\u000b\u000b\n\u000b\u000b\u0019\u000b\n\u000b\n\f\u001c\t\n\u000b\u000b\u001c\u000b\n\f\u000b\u000b\n\u001b\u000b\t\n\u000b\u001d\u000b\n\u0007\b\u000b\t\u000b\u000b\u001d\u000b\f\f\u001c\u000b\n\u000b\u000b\u001b\u000b\f\u001c\u000b\f\u000b\u000b\u001c\u000b\n\u000b\n\f\u001c\t\n\u000b\u000b\u001c\u000b\n\f\u000b\u000b\n\u001b\u000b\t\n\u000b\u001d\u000b\n\u0007\b\n\t\u000b\u000b\u001d\u000b\f\f\u001d\n\u000b\u000b\u001d\u000b\f\u001d\n\f\u001d\u000b\u000b\u000b\u000b\u001c\u000b\n\u000b\n\f\u001c\t\n\u000b\u000b\u001c\u000b\n\f\u000b\u000b\n\u001b\u000b\t\n\u000b\u001d\u000b\n\u0007\b\u000b\t\u000b\u000b\u001d\u000b\f\f\u001d\n\u000b\u000b\u001d\u000b\t\u000b\f\u001d\u000b\n\n\u000b\u000b\u001c\u000b\n\u000b\n\f\u001c\t\n\u000b\u000b\u001c\u000b\n\f\u000b\u000b\n\u001b\u000b\t\n\u000b\u001d\u000b\n\u0007\b\r\u0013\u000b\u001e\u000b\n\f\u001c\u000b\n\u000b\u001b\n\t\b\n\u000b\u001a\u000b\b\t\t\u001b\t\t\n\u000b\u001a\n\t\u000b\b\u000b\f\u001b\u000b\b\t\f\u001b\b\u0007\t\u000b\f\u0013\u000b\u001e\u000b\n\f\u001d\n\t\u000b\u001d\u000b\n\f\u001d\f\u000b\u001c\n\n\b\n\u001b\u000b\n\n\t\u000b\u001b\u000b\u000b\n\u000b\u001a\n\t\u000b\b\u000b\f\u001b\u000b\b\t\f\u001b\b\u0007\t\u000b\u000b\u0013\u000b\u001e\u000b\n\f\u001d\n\n\u000b\u001d\f\u000b\n\f\u001d\f\n\u000b\u001d\t\n\u001d\n\u001c\n\t\b\n\u001b\u000b\n\n\t\u000b\u001b\u000b\u000b\n\u000b\u001a\n\t\u000b\b\u000b\f\u001b\u000b\b\t\f\u001b\b\u0007\t\u000b\f\u0013\u000b\u001e\u000b\n\f\u001d\n\n\u000b\u001e\n\t\n\u001e\u000b\n\u000b\u001e\n\u001c\n\t\b\n\u001c\u000b\n\n\t\u001c\u000b\u000b\n\u000b\u001a\n\t\u000b\b\u000b\f\u001b\u000b\b\t\f\u001b\b\u0007\t\u000b\r\u0013\u000b\u001e\u000b\n\f\u001d\n\t\n\u000b\u001d\u000b\n\n\u000b\u001d\u000b\u000b\u001c\u000b\n\n\t\u000b\u001c\u000b\u000b\n\u000b\u001b\t\u000b\b\u000b\f\u001a\n\u000b\b\t\f\u001c\t\u0007\u000b\u001d\b\f\u0013\u000b\u001e\u000b\n\f\u001d\n\n\u000b\u001e\n\t\n\u001e\u000b\n\u000b\u001e\n\u001c\n\t\b\n\u001c\u000b\n\n\t\u001c\u000b\u000b\n\u000b\u001a\n\t\u000b\b\u000b\f\u001b\u000b\b\t\f\u001b\b\u0007\t\u000b\u000b\u0013\u000b\u001e\u000b\n\f\u001d\n\n\u000b\u001d\f\u000b\n\f\u001d\f\n\u000b\u001d\n\n\u001d\n\u001c\n\t\b\n\u001b\u000b\n\n\t\u000b\u001b\u000b\u000b\n\u000b\u001a\n\t\u000b\b\u000b\f\u001b\u000b\b\t\f\u001b\b\u0007\t\u000b\f\u0013\u000b\u001e\u000b\n\f\u001d\n\t\u000b\u001d\u000b\n\f\u001d\f\u000b\u001c\n\n\b\n\u001b\u000b\n\n\t\u000b\u001b\u000b\u000b\n\u000b\u001a\n\t\u000b\b\u000b\f\u001b\u000b\b\t\f\u001b\b\u0007\t\u000b\u0013\u000b\u000b\u000b\t\f\u000b\n\f\n\n\u0017\f\t\b\f\r\u000b\u000b\f\u000b\u0017\f\u000b\n\r\u000b\n\n\t\n\u0017\u000b\f\f\f\u000b\u000b\t\t\b\t\f\u0015\n\f\f\u0002\f\u000b\n\t\n\u000b\u000b\u0014\u000b\n\f\u0005\f\u000b\f\t\u0014\f\u000b\f\u0006\f\n\u000b\u0014\f\f\u0006\u000b\n\u000b\u0014\u000b\n\u000b\u0006\t\u000b\u0014\u000b\u000b\f\u0007\n\u000b\u0012\f\f\r\t\f\n\u000b\u000b\u0010\u000b\n\u000b\n\u000b\t\u000b\f\f\u000e\f\f\u000b\u000b\t\n\t\n\u000b\f\b\u000e\f\f\u000b\t\u0012\u000b\u000b\u000b\t\f\u000b\n\f\n\n\u0017\f\t\b\f\r\u000b\u000b\f\u000b\u0017\f\u000b\n\r\u000b\n\t\n\f\u0018\f\f\f\u000b\n\t\t\n\u0018\u000b\u000b\f\f\u000b\n\t\b\u000b\u0017\u000b\n\f\u0003\u000b\n\n\u000b\u0016\f\u000b\f\u0004\f\u000b\n\u0015\u000b\n\f\u0005\f\n\u000b\u0014\u000b\n\f\u0005\f\n\u000b\u0014\u000b\f\f\u0005\f\u000b\u000b\u0014\f\u000b\u000b\u0006\t\n\u0015\u000b\n\u000b\f\u0005\n\u000b\u0015\f\f\u000b\u000b\f\u0004\f\n\u000b\u000b\u0015\n\u0001\t\u0005\u000b\t\u000b\f\f\u001b\n\t\n\u000b\f\b\u0011\u000b\u000b\u000b\t\f\u000b\n\f\n\n\u0017\f\t\b\f\r\u000b\u000b\f\u000b\u0017\f\u000b\n\r\u000b\n\n\u000b\f\u0017\f\f\f\f\u000b\n\t\n\u0019\f\u000b\f\f\u000b\t\t\f\u0019\f\n\f\u000b\n\b\u000b\u0019\n\u000b\f\u0001\f\n\n\u0018\n\u000b\u0004\u000b\u000b\u0017\u000b\u000b\f\u0004\u000b\n\u0016\f\u000b\u000b\u0004\u000b\n\f\u0016\u000b\n\u000b\f\u0002\u000b\t\f\u0017\f\f\u000b\u000b\f\u000b\n\u000b\u001a\n\u0001\t\b\u000b\u001e\t\n\u001e\f\n\u000b\u000b\u001d\u000b\t\u000b\f\f\u001b\n\t\n\u000b\f\b\u0012\u000b\u000b\u000b\t\f\u000b\n\f\n\n\u0017\f\t\b\f\r\u000b\u000b\f\u000b\u0017\f\u000b\n\r\u000b\n\t\u000b\f\u0018\f\f\f\n\t\t\u000b\u001b\f\u000b\t\t\u000b\u001b\u000b\f\n\t\n\u001a\f\n\f\u000b\b\n\u001a\u000b\u000b\u0001\f\t\u000b\u0019\f\u000b\u000b\f\f\u000b\f\u0019\u000b\n\u000b\f\u000b\n\u000b\u001a\u000b\f\u000b\n\u000b\u001c\u000b\b\u000b\u001d\n\u000b\u001d\u000b\t\u000b\u001d\f\n\u000b\u000b\u001c\u000b\t\n\u000b\f\f\u001a\f\f\u000b\n\u000b\f\b\u0013\u000b\u000b\u000b\t\f\u000b\n\f\n\n\u0017\f\t\b\f\r\u000b\u000b\f\u000b\u0017\f\u000b\n\r\u000b\n\n\u000b\f\u0018\f\f\f\n\n\t\n\u001b\f\n\t\t\u000b\u001c\u000b\t\t\f\u001c\f\b\n\u001d\u000b\t\u000b\u001d\u000b\n\n\f\u001c\u000b\f\n\f\u000b\u001b\u000b\t\u000b\u001c\u000b\t\u000b\u001b\u000b\n\n\u000b\u001b\n\t\u000b\f\u001c\f\u000b\n\u000b\u001c\f\f\u000b\n\f\f\u001b\f\f\f\u000b\f\b\u0012\u000b\u000b\u000b\t\f\u000b\n\f\n\n\u0017\f\t\b\f\r\u000b\u000b\f\u000b\u0017\f\u000b\n\r\u000b\n\t\u000b\f\u0018\f\f\f\u000b\t\t\n\u001b\f\f\n\t\t\u000b\u001a\u000b\u000b\f\n\t\t\u001a\n\u000b\f\u000b\n\b\u000b\u0018\u000b\n\f\u0002\u000b\t\n\u0018\n\u000b\u0004\f\t\u0018\u000b\f\u0003\u000b\u000b\n\u0018\f\f\u000b\f\u000b\n\n\u0019\u000b\n\u000b\u000b\n\u000b\u0019\n\t\n\u000b\u001c\f\f\u000b\u000b\u001d\f\f\u000b\f\u001c\f\f\f\u000b\f\u001c\u000b\u0002\b\u0011\u000b\u000b\u000b\t\f\u000b\n\f\n\n\u0017\f\t\b\f\r\u000b\u000b\f\u000b\u0017\f\u000b\n\r\u000b\n\n\u000b\f\u0018\f\f\f\u000b\n\t\n\u0019\u000b\f\f\f\u000b\t\t\u000b\u0018\u000b\n\f\u0002\u000b\t\b\u0018\f\u000b\f\u0003\u000b\n\n\u0017\u000b\n\f\u0004\u000b\t\u0016\u000b\n\f\u0003\u000b\n\t\u000b\u0016\n\u000b\u0003\u000b\b\u000b\n\u0017\f\u000b\u0002\n\b\t\u0019\u000b\n\f\n\t\n\u000b\u0019\u000b\n\u000b\f\f\u000b\u000b\u0019\u000b\u000b\n\u000b\f\f\u000b\f\u001c\f\f\f\u000b\f\u001c\u000b\u0002\b\u0012\u000b\u000b\u000b\t\f\u000b\n\f\n\n\u0017\f\t\b\f\r\u000b\u000b\f\u000b\u0017\f\u000b\n\r\u000b\n\t\n\f\u0018\f\f\f\u000b\n\t\t\n\u0018\u000b\f\f\f\u000b\n\t\b\n\u0017\u000b\n\u000b\u0003\u000b\n\t\n\u0016\u000b\u000b\u0005\u000b\n\u000b\u0016\f\f\u0004\n\f\u000b\u0016\n\n\u000b\u0003\n\b\u000b\u0016\f\t\u000b\u0003\u000b\b\u000b\u0016\u000b\u000b\f\u0004\u000b\n\u000b\f\f\u0013\f\u000b\u000b\u0006\u000b\t\u000b\u000b\f\b\u0011\u000b\n\u000b\u000b\f\u0004\n\t\n\u000b\f\u0012\f\f\f\u000b\f\t\f\f\u000b\u000b\u001d\u000b\t\n\n\u000b\u000b\u000b\u000b\u000b\u000b\u0017\u000b\u000b\u000b\n\u000b\n\t\t\u001b\n\n\u000b\u000b\u000b\u001a\u000b\u000b\u000b\u000b\b\b\t\u001a\u000b\b\u0007\u0002\t\u000b\u001a\t\b\t\u001f\t\u000b\f\u000b\u001e\u000b\t\n\u001e\u000b\n\u000b\u001e\u000b\n\u000b\u000b\u001c\n\u000b\u000b\u000b\u000b\u001c\u000b\n\t\u001b\u000b\n\n\u000b\u000b\u001b\u000b\n\b\u000b\b\n\u001b\u000b\u0007\u000b\n\b\u001c\n\b\u0002\u000b\u001c\t\n\f\u000b\u001e\u000b\t\u000b\u001d\u000b\b\u000b\u001d\u000b\n\n\u001d\u000b\t\u000b\u000b\u001c\u000b\u000b\u001b\u000b\n\u000b\n\u000b\u001b\u000b\u000b\n\u000b\t\u001b\n\b\u000b\t\u000b\u001b\t\u0007\u000b\b\n\u001b\n\b\u0001\n\b\u001c\t\u0002\t\u001f\u000b\u000b\f\u000b\u001e\u000b\t\u000b\u001d\u000b\n\u000b\u001c\u000b\n\u000b\u001d\n\t\u000b\u000b\u001c\u000b\u000b\u001b\u000b\n\u000b\n\u000b\u001b\u000b\u000b\n\u000b\t\u001b\n\b\u000b\t\u000b\u001b\t\u0007\u000b\b\n\u001b\n\b\u0001\n\b\u001c\t\u0002\t\u001f\u000b\f\f\u000b\u001e\u000b\t\u000b\u001b\u000b\n\n\u000b\u000b\u001a\u000b\n\u000b\u000b\u001c\u000b\u000b\u001b\u000b\n\u000b\n\u000b\u001b\u000b\u000b\n\u000b\t\u001b\n\b\u000b\t\u000b\u001b\t\u0007\u000b\b\n\u001b\n\b\u0001\n\b\u001c\t\u0002\t\u001f\u000b\u000b\f\u000b\u001e\u000b\t\u000b\u001d\u000b\n\u000b\u001c\u000b\n\u000b\u001d\n\t\u000b\u000b\u001c\u000b\u000b\u001b\u000b\n\u000b\n\u000b\u001b\u000b\u000b\n\u000b\t\u001b\n\b\u000b\t\u000b\u001b\t\u0007\u000b\b\n\u001b\n\b\u0001\n\b\u001c\t\u0002\t\u001f\u000b\n\f\u000b\u001e\u000b\t\u000b\u001d\u000b\b\u000b\u001d\u000b\n\n\u001d\u000b\t\u000b\u000b\u001c\u000b\u000b\u001b\u000b\n\u000b\n\u000b\u001b\u000b\u000b\n\u000b\t\u001b\n\b\u000b\t\u000b\u001b\t\u0007\u000b\b\n\u001b\n\b\u0001\n\b\u001c\t\u0002\t\u001f\u000b\u000b\f\u000b\u001e\u000b\t\n\u001e\u000b\n\u000b\u001e\u000b\n\u000b\u000b\u001c\n\u000b\u000b\u000b\u000b\u001c\u000b\n\t\u001b\u000b\n\n\u000b\u000b\u001b\u000b\n\b\u000b\b\n\u001b\u000b\u0007\u000b\n\b\u001c\n\b\u0002\u000b\u001c\t\u000f\f\n\u001e\u000b\b\n\u001b\u000b\t\t\n\u000b\u001a\n\t\n\u000b\u001c\n\u000b\u001b\u000b\t\u000b\t\u000b\u001b\n\n\t\n\b\u001b\t\u0007\n\b\n\u001b\b\u0006\u000b\u0007\t\u001b\t\u0007\u0001\t\u0007\u001c\b\u0002\b\u001f\u000b\u000e\f\n\u001e\u000b\b\n\u001d\n\t\n\u001c\n\t\n\u001d\t\b\u000b\u000b\u001c\n\u000b\u001b\u000b\t\u000b\t\u000b\u001b\n\n\t\n\b\u001b\t\u0007\n\b\n\u001b\b\u0006\u000b\u0007\t\u001b\t\u0007\u0001\t\u0007\u001c\b\u0002\b\u001f\u000b\r\f\n\u001e\u000b\b\n\u001d\n\u0007\n\u001d\u000b\t\t\u001d\n\b\u000b\u000b\u001c\n\u000b\u001b\u000b\t\u000b\t\u000b\u001b\n\n\t\n\b\u001b\t\u0007\n\b\n\u001b\b\u0006\u000b\u0007\t\u001b\t\u0007\u0001\t\u0007\u001c\b\u0002\b\u001f\u000b\u000e\f\n\u001e\u000b\b\t\u001e\u000b\t\n\u001e\n\t\n\u000b\u001c\t\n\u000b\n\u000b\u001c\u000b\t\b\u001b\n\t\t\n\n\u001b\u000b\t\u0007\n\u0007\t\u001b\n\u0006\u000b\t\u0007\u001c\t\u0007\u0002\n\u001c\b\u000f\f\n\u000b\u001d\u000b\b\t\t\n\n\u000b\u000b\n\u000b\u0017\u000b\u000b\n\t\u000b\t\b\b\u001b\t\t\n\u000b\n\u001a\u000b\n\n\u000b\u0007\u0007\b\u001a\n\u0007\u0006\u0002\b\u000b\u001a\b\u0007\b\u001f\b\u000e\f\n\u001e\u000b\b\t\u001e\u000b\t\n\u001e\n\t\n\u000b\u001c\t\n\u000b\n\u000b\u001c\u000b\t\b\u001b\n\t\t\n\n\u001b\u000b\t\u0007\n\u0007\t\u001b\n\u0006\u000b\t\u0007\u001c\t\u0007\u0002\n\u001c\b\r\f\n\u001e\u000b\b\n\u001d\n\u0007\n\u001d\u000b\t\t\u001d\n\b\u000b\u000b\u001c\n\u000b\u001b\u000b\t\u000b\t\u000b\u001b\n\n\t\n\b\u001b\t\u0007\n\b\n\u001b\b\u0006\u000b\u0007\t\u001b\t\u0007\u0001\t\u0007\u001c\b\u0002\b\u001f\u000b\u000e\f\n\u001e\u000b\b\n\u001d\n\t\n\u001c\n\t\n\u001d\t\b\u000b\u000b\u001c\n\u000b\u001b\u000b\t\u000b\t\u000b\u001b\n\n\t\n\b\u001b\t\u0007\n\b\n\u001b\b\u0006\u000b\u0007\t\u001b\t\u0007\u0001\t\u0007\u001c\b\u0002\b\u001f\u000b\u0013\r\u000b\u000b\u000b\n\t\t\n\u0018\f\u000b\n\n\t\n\f\t\u0018\f\f\r\f\f\r\f\n\u0018\f\r\f\n\n\u000b\r\u000b\u0019\f\u000b\n\t\n\f\u001b\f\u000b\n\b\n\f\u0018\f\n\u000b\f\f\u000b\t\n\f\u0016\u000b\u000b\f\u0003\f\u000b\t\u000b\f\u0012\u000b\u000b\f\f\u0006\u000b\u000b\n\u000b\u0013\f\f\u0006\f\t\n\u000b\u0014\f\u000b\u000b\f\u0003\u000b\t\u000b\u0017\f\f\u000b\b\u0001\n\t\f\u001d\u000b\n\u000b\u001e\f\n\u000b\u001d\u000b\u000b\n\n\u000b\u001b\n\f\f\u000b\n\u0007\u0012\r\u000b\u000b\u000b\n\t\t\n\u0018\f\u000b\n\n\t\n\f\t\u0018\f\f\r\f\f\r\f\n\u0018\f\r\f\u000b\n\u000b\r\u000b\u0019\f\u000b\n\t\n\f\u001b\f\n\t\t\u000b\u001a\f\u000b\u000b\n\b\n\u0019\f\u000b\n\f\u000b\t\n\f\u0014\u000b\f\f\f\u000b\f\f\u0001\f\u000b\t\u000b\u0014\f\u000b\u000b\f\u0005\u000b\n\u000b\u0014\f\u000b\f\u0004\u000b\n\n\u000b\u0016\f\u000b\u0003\n\t\u000b\u0019\f\b\u0001\n\t\f\u001d\u000b\n\u000b\u001e\f\n\u000b\u001d\u000b\u000b\n\n\u000b\u001b\n\f\f\u000b\n\u0007\u0011\r\u000b\u000b\u000b\n\t\t\n\u0018\f\u000b\n\n\t\n\f\t\u0018\f\f\r\f\f\r\f\n\u0018\f\r\f\u000b\n\u000b\r\u000b\u0019\f\u000b\n\t\u000b\u001b\u000b\n\n\u000b\f\u001b\f\n\t\n\u001c\f\n\b\n\u0018\u000b\f\f\f\u000b\u000b\t\u000b\u0018\f\u000b\u000b\f\u0001\f\n\u000b\u0018\f\u000b\f\u0002\u000b\n\f\u0019\f\u000b\u0001\u000b\t\u000b\u001b\f\u000b\t\f\u001c\n\t\f\u001d\u000b\n\u001e\f\n\u000b\u001d\u000b\u000b\n\n\u000b\u001b\n\f\f\u000b\n\u0007\u0012\r\u000b\u000b\u000b\n\t\t\n\u0018\f\u000b\n\n\t\n\f\t\u0018\f\f\r\f\f\r\f\n\u0018\f\r\f\u000b\n\u000b\r\u000b\u0019\f\u000b\n\t\u000b\u000b\u001a\u000b\n\n\u000b\f\f\u001a\f\n\b\n\f\u001c\u000b\t\f\u001c\f\u000b\n\u001d\u000b\t\u000b\u001c\u000b\b\u000b\u000b\u000b\f\b\u0018\n\t\f\u0001\f\f\f\u0018\t\u000b\f\u001d\n\u000b\u001d\u000b\u000b\f\u001d\n\u000b\u000b\n\u000b\u001c\f\f\u000b\n\u0007\u0013\r\u000b\u000b\u000b\n\t\t\n\u0018\f\u000b\n\n\t\n\f\t\u0018\f\f\r\f\f\r\f\n\f\u0017\f\r\f\u000b\n\u000b\r\u000b\f\f\u0017\f\u000b\n\t\n\f\u000b\f\u0018\u000b\n\b\n\f\u000b\f\u0019\u000b\n\b\u000b\f\u001b\f\n\t\f\u001d\u000b\n\f\u001c\u000b\n\t\u000b\f\u0019\u000b\t\n\u000b\f\f\u000b\u000b\f\u0016\n\n\u000b\u0002\u000b\f\f\f\u000b\b\u0012\n\n\u000b\u000b\u001d\u000b\u000b\u001e\f\n\n\u000b\u001d\f\u000b\n\u0007\u0012\r\u000b\u000b\u000b\n\t\t\n\u0018\f\u000b\n\n\t\n\f\t\u0018\f\f\r\f\f\r\f\n\u0018\f\r\f\u000b\n\u000b\r\u000b\u0019\f\u000b\n\t\n\f\u001a\u000b\n\b\n\f\f\u001a\u000b\b\t\u000b\f\u001b\u000b\t\n\u001c\u000b\u000b\n\u000b\u001c\f\u000b\n\u001d\u000b\n\t\f\u001b\u000b\n\t\u000b\u000b\u000b\f\u0015\n\u000b\u000b\u000b\n\u000b\u000b\f\f\f\u000b\b\u0014\f\n\n\u000b\u001c\u000b\n\u000b\u001e\u000b\n\u001f\u000b\u0007\u0011\r\u000b\u000b\u000b\n\t\t\n\u0018\f\u000b\n\n\t\n\f\t\u0018\f\f\r\f\f\r\f\n\u0018\f\r\f\n\n\u000b\r\u000b\u0019\f\u000b\n\t\n\u001b\u000b\n\b\n\f\u001c\n\b\n\u001c\f\u000b\t\t\u001b\f\n\f\n\t\u001a\u000b\n\f\u0001\u000b\n\u001a\f\u000b\u0002\u000b\n\u001a\f\u000b\u000b\t\n\t\u0018\n\u000b\u000b\u000b\n\n\u000b\u0019\f\n\n\u000b\f\f\u000b\b\u0018\u000b\n\u000b\u001e\u000b\n\u001f\u000b\u0007\u0012\r\u000b\u000b\u000b\n\t\t\n\u0018\f\u000b\n\n\t\n\f\t\u0018\f\f\r\f\f\r\f\n\u0018\f\r\f\n\n\u000b\r\u000b\u0019\f\u000b\n\t\n\u000b\u001b\f\u000b\n\b\n\u001a\f\t\f\u000b\n\t\u000b\u0018\u000b\n\f\u0002\u000b\n\t\u0017\n\f\f\u0004\n\n\u0017\u000b\f\u0004\u000b\n\u000b\u0016\f\f\f\u0003\u000b\t\u000b\u0017\u000b\f\f\u000b\f\n\t\u000b\u0019\f\f\f\u000b\n\f\u001d\t\n\u000b\u001d\n\u000b\n\n\u000b\u0007\u001c\f\u000b\u000b\r\u0013\u001e\u000b\u000b\f\u001b\f\u000b\n\t\n\f\f\u001c\u000b\u000b\n\u000b\u001d\f\t\n\u001b\t\u000b\u000b\b\u000b\u001c\u000b\b\t\u001e\t\f\u0013\u001e\u000b\u001d\f\u000b\n\u000b\u001e\u000b\u000b\n\u001e\t\f\f\u001c\n\u000b\n\u000b\u001d\f\t\n\u001b\t\u000b\u000b\b\u000b\u001c\u000b\b\t\u001e\t\u000b\u0013\u001e\f\u001d\f\n\u000b\u001e\u000b\n\f\u001d\f\n\u000b\u001e\t\f\f\u001c\n\u000b\n\u000b\u001d\f\t\n\u001b\t\u000b\u000b\b\u000b\u001c\u000b\b\t\u001e\t\f\u0013\u001d\u000b\u001d\u000b\n\u000b\f\u001d\f\n\u000b\u001d\t\f\f\u001c\n\u000b\n\u000b\u001d\f\t\n\u001b\t\u000b\u000b\b\u000b\u001c\u000b\b\t\u001e\t\r\u0013\u001d\n\u000b\u001c\t\n\n\f\u001b\n\u000b\n\u000b\u001d\f\t\n\u001b\t\u000b\u000b\b\u000b\u001c\u000b\b\t\u001e\t\f\u0013\u001d\u000b\u001d\u000b\n\u000b\u001e\f\n\u000b\u001d\t\f\f\u001c\n\u000b\n\u000b\u001d\f\t\n\u001b\t\u000b\u000b\b\u000b\u001c\u000b\b\t\u001e\t\u000b\u0013\u001e\f\u001d\f\n\u000b\u001e\u000b\n\f\u001d\f\n\u000b\u001e\t\f\f\u001c\n\u000b\n\u000b\u001d\f\t\n\u001b\t\u000b\u000b\b\u000b\u001c\u000b\b\t\u001e\t\f\u0013\u001e\u000b\u001d\f\u000b\n\u000b\u001e\u000b\u000b\n\u001e\t\f\f\u001c\n\u000b\n\u000b\u001d\f\t\n\u001b\t\u000b\u000b\b\u000b\u001c\u000b\b\t\u001e\t\r\u0007\f\u000b\f\u001a\f\u000b\n\t\n\u001a\u000b\u000b\u000b\f\u001c\n\t\b\n\u000b\u001b\u000b\n\t\t\n\b\u001a\f\u000b\n\b\u000b\n\u0007\u001a\u000b\n\u000b\u0007\u000b\b\u001b\t\n\b\u0007\u001d\t\r\b\t\u001f\b\f\t\f\u001d\u000b\n\u001c\u000b\t\u000b\f\u001b\u000b\t\n\f\u001c\u000b\n\u001d\n\t\b\n\u000b\u001b\u000b\n\t\t\n\b\u001a\f\u000b\n\b\u000b\n\u0007\u001a\u000b\n\u000b\u0007\u000b\b\u001b\t\n\b\u0007\u001d\t\r\b\t\u001f\b\u000b\t\f\u001e\u000b\u001d\f\n\t\u001c\f\u000b\t\n\u001c\u000b\n\n\u001d\n\t\u001d\u000b\u001d\n\t\b\n\u000b\u001b\u000b\n\t\t\n\b\u001a\f\u000b\n\b\u000b\n\u0007\u001a\u000b\n\u000b\u0007\u000b\b\u001b\t\n\b\u0007\u001d\t\r\b\t\u001f\b\f\t\f\u001e\t\n\u001e\u000b\t\u000b\u001d\f\n\t\u000b\u001d\u000b\u000b\u001d\n\t\b\n\u000b\u001b\u000b\n\t\t\n\b\u001a\f\u000b\n\b\u000b\n\u0007\u001a\u000b\n\u000b\u0007\u000b\b\u001b\t\n\b\u0007\u001d\t\r\b\t\u001f\b\r\t\f\u001e\n\t\n\u000b\u001d\f\u000b\t\n\u000b\f\u001c\f\u000b\n\t\b\n\u000b\u001b\u000b\n\t\t\n\b\u001a\f\u000b\n\b\u000b\n\u0007\u001a\u000b\n\u000b\u0007\u000b\b\u001b\t\n\b\u0007\u001d\t\r\b\t\u001f\b\f\t\f\u001e\t\n\u001e\u000b\t\u000b\u001d\f\n\t\u000b\u001d\u000b\u000b\u001d\n\t\b\n\u000b\u001b\u000b\n\t\t\n\b\u001a\f\u000b\n\b\u000b\n\u0007\u001a\u000b\n\u000b\u0007\u000b\b\u001b\t\n\b\u0007\u001d\t\r\b\t\u001f\b\u000b\t\f\u001e\u000b\u001d\f\n\t\u001c\f\u000b\t\n\u001c\u000b\n\n\u001d\n\t\u001d\u000b\u001d\n\t\b\n\u000b\u001b\u000b\n\t\t\n\b\u001a\f\u000b\n\b\u000b\n\u0007\u001a\u000b\n\u000b\u0007\u000b\b\u001b\t\n\b\u0007\u001d\t\r\b\t\u001f\b\f\t\f\u001d\u000b\n\u001c\u000b\t\u000b\f\u001b\u000b\t\n\f\u001c\u000b\n\u001d\n\t\b\n\u000b\u001b\u000b\n\t\t\n\b\u001a\f\u000b\n\b\u000b\n\u0007\u001a\u000b\n\u000b\u0007\u000b\b\u001b\t\n\b\u0007\u001d\t\r\b\t\u001f\b\u0013\u000b\u000b\n\t\t\b\f\t\f\t\u0017\f\u000b\f\r\u000b\n\n\u000b\u000b\f\u0016\u000b\n\u000b\f\r\u000b\u000b\f\r\n\u0016\f\n\t\n\f\f\f\r\f\u000b\u0017\u000b\n\b\n\u0002\f\t\u0019\u000b\t\t\u0001\f\u000b\n\u0019\f\u000b\b\n\f\u000b\u000b\u0018\r\f\u000b\t\b\u001b\f\u000b\u000b\n\t\u001b\u000b\u000b\t\u000b\f\n\u001a\u000b\n\u000b\u001d\n\u000b\u001e\u000b\n\u001d\u000b\u000b\t\u000b\u001c\f\u000b\t\n\f\u001c\f\u000b\n\u000b\f\u001c\u000b\u0007\r\f\n\u0012\u000b\u000b\n\t\t\b\f\t\f\t\u0017\f\u000b\f\r\u000b\n\n\u000b\u000b\f\u0016\n\u000b\u000b\r\u000b\u000b\f\r\u000b\u0016\n\n\n\f\f\f\f\r\f\n\u0016\u000b\t\n\u000b\u0004\u000b\n\u0017\n\b\n\u0002\f\f\u000b\u000b\u0016\r\u000b\n\t\u000b\f\u000b\u000b\n\f\u0018\u000b\n\n\u000b\f\u001c\u000b\b\u000b\n\u001b\u000b\n\t\u000b\u000b\u0019\u000b\n\n\u000b\u000b\r\n\u0018\u000b\t\n\u001d\n\u000b\u001d\u000b\n\n\u001d\f\u000b\t\u000b\f\u001c\f\u000b\n\u000b\f\u001c\u000b\u0007\r\f\n\u0011\u000b\u000b\n\t\t\b\f\t\f\t\u0017\f\u000b\f\r\u000b\n\n\u000b\u000b\f\u0016\u000b\n\u000b\r\u000b\u000b\f\r\u000b\u000b\u0015\n\t\n\f\f\f\r\f\n\n\u0015\u000b\t\t\u000b\u0005\u000b\t\u000b\u0014\u000b\t\b\n\u0006\n\t\u0015\n\t\n\u0005\f\f\n\u0015\u000b\n\t\u0005\u000b\t\u000b\u0015\u000b\t\n\u0003\f\f\u000b\u000b\u0016\u000b\b\u000b\u0001\f\f\u000b\n\f\u0014\u000b\n\n\n\u000b\u000b\u0001\u000b\f\f\u0015\u000b\t\b\n\u000b\u0003\f\u000b\u000b\u0015\n\u000b\u0007\n\u000b\f\u0013\u000b\n\u000b\u0007\u0007\r\n\u0013\f\u000b\t\u000b\f\u001c\f\u000b\n\u000b\f\u001c\u000b\u0007\r\f\n\u0012\u000b\u000b\n\t\t\b\f\t\f\t\u0017\f\n\u000b\r\u000b\n\n\u000b\u000b\f\u0016\u000b\t\n\r\u000b\u000b\f\r\u000b\u000b\u0015\n\t\n\f\f\f\r\f\n\t\n\u0014\t\t\n\u000b\u0006\u000b\t\n\u0013\t\b\n\b\u000b\t\u0013\n\b\u000b\u0007\u000b\b\u000b\u0013\n\t\u000b\u0006\u000b\n\u000b\u0014\u000b\t\u000b\u0005\u000b\n\u000b\u0013\u000b\n\u000b\b\u0006\n\u000b\u0012\t\u000b\n\t\n\u000b\u0005\r\f\t\f\u0010\n\b\n\u000b\b\f\u000b\u0007\r\f\n\u000e\t\n\u000b\f\b\u000b\f\n\f\u000b\u000f\n\u000b\n\u000b\f\u001c\u000b\u0007\r\f\n\u0013\u000b\u000b\n\t\t\b\f\t\f\t\u0017\f\u000b\f\r\u000b\n\n\u000b\u000b\f\u0016\u000b\n\u000b\r\u000b\u000b\f\r\u000b\u000b\u0015\n\t\n\f\f\f\r\u000b\n\t\n\u000b\u0012\u000b\t\t\n\u000b\u0005\u000b\n\n\t\n\u0011\n\b\t\u000b\b\u000b\b\u000b\u0011\n\b\n\u000b\u0007\u000b\n\u000b\u0012\u000b\t\n\u0007\u000b\u000b\u000b\u0011\n\u000b\u000b\b\u000b\u0006\u000b\n\u000b\u000f\n\t\u000b\t\n\u000b\u000b\u0007\u000b\u000b\u0010\t\n\t\u000b\u000b\u000b\n\u000f\n\n\u000b\f\u000b\r\u000b\t\f\u000e\u0007\r\f\n\n\f\u000b\n\u000b\f\u001d\u0007\r\f\n\u0012\u000b\u000b\n\t\t\b\f\t\f\t\u0017\f\u000b\f\r\u000b\n\n\u000b\u000b\f\u0016\u000b\n\u000b\r\u000b\u000b\f\r\u000b\u000b\u0015\n\t\n\f\f\f\r\u000b\n\n\u000b\u0014\n\t\n\u000b\u0005\u000b\t\n\u0014\n\b\n\u0007\n\t\u000b\u0013\u000b\b\n\u0007\u000b\b\u000b\u0013\u000b\t\u000b\u0006\u000b\n\n\u000b\u0012\u000b\n\b\u0005\u000b\n\u000b\u000b\u0011\u000b\n\u000b\n\u000b\n\u0004\u000b\u000b\u000b\u0013\n\u000b\t\b\n\n\u0013\n\t\u000b\f\u0007\r\n\t\f\u0012\n\n\u000b\f\u0006\f\u000b\n\u000b\f\u0011\b\u000b\r\f\n\u0007\u0007\r\f\n\u0011\u000b\u000b\n\t\t\b\f\t\f\t\u0017\f\u000b\f\r\u000b\n\n\u000b\u000b\f\u0016\u000b\n\u000b\r\u000b\u000b\f\r\u000b\u0016\n\t\t\f\f\f\r\f\n\u000b\u0015\u000b\t\b\u000b\u0004\u000b\t\n\u0016\n\b\n\u0004\u000b\n\t\u000b\u0015\u000b\t\t\u0005\n\b\u000b\u0016\n\t\u0003\u000b\n\n\u000b\u0017\u000b\b\u0001\u000b\u000b\n\u000b\u0019\t\n\u0001\n\u000b\u001a\n\u000b\u0002\u000b\n\u000b\u0018\u000b\u000b\u0003\r\n\t\f\u0015\u000b\t\u000b\u0004\f\u000b\n\u000b\f\u0014\n\n\n\f\u0005\u0007\r\f\n\u0014\n\u000b\u000b\f\u001d\n\r\f\u000b\u001c\b\u0002\n\u0012\u000b\u000b\n\t\t\b\f\t\f\t\u0017\f\u000b\f\r\u000b\n\n\u000b\u000b\f\u0016\n\n\u000b\r\u000b\u000b\f\r\u000b\u0016\u000b\t\b\u000b\f\f\f\r\f\u000b\u0017\n\b\n\u0003\f\u000b\n\u0017\u000b\t\t\u0003\u000b\n\u000b\u0018\n\b\n\u0001\u000b\u000b\u000b\u0019\u000b\t\n\u000b\u000b\n\u001b\t\n\u000b\u001c\n\u000b\n\u000b\f\u001a\n\t\n\u000b\u000b\u000b\f\u0018\u000b\u000b\u000b\u0002\u0007\r\f\n\u0017\n\u000b\u001e\n\t\u001e\u000b\n\u000b\f\u001c\u000b\t\u0007\r\f\n\u001b\u000b\u000b\u000b\u000b\f\f\u0018\u000b\r\u001e\t\u000b\r\u001d\n\t\f\u001d\f\u000b\u001c\f\n\b\t\f\u001b\u000b\n\t\n\u000b\u001a\t\u0007\n\u000b\n\u000b\u001a\u0007\b\u000b\u0007\n\f\u0019\b\b\u0001\b\u0007\u000b\u001a\t\u0002\u0007\t\u001e\b\u001e\b\u000b\u0018\u000b\r\u001e\t\u000b\r\u001d\n\t\f\u001d\f\n\n\f\u001d\u000b\t\u000b\u001c\f\n\b\t\f\u001b\u000b\n\t\n\u000b\u001a\t\u0007\n\u000b\n\u000b\u001a\u0007\b\u000b\u0007\n\f\u0019\b\b\u0001\b\u0007\u000b\u001a\t\u0002\u0007\t\u001e\b\u001e\b\n\u0018\u000b\r\u001e\t\u000b\r\u001d\u000b\n\f\u001d\f\u000b\n\f\u001d\f\u000b\f\u001d\f\u000b\u001c\f\n\b\t\f\u001b\u000b\n\t\n\u000b\u001a\t\u0007\n\u000b\n\u000b\u001a\u0007\b\u000b\u0007\n\f\u0019\b\b\u0001\b\u0007\u000b\u001a\t\u0002\u0007\t\u001e\b\u001e\b\u000b\u0018\u000b\r\u001e\t\u000b\r\u001d\u000b\t\n\u000b\u001d\u000b\t\t\u000b\u001d\f\n\t\u000b\u001c\f\f\b\t\f\u001b\f\u000b\t\n\u000b\u001a\t\u0007\n\u000b\n\u000b\u001a\u0007\b\u000b\u0007\n\f\u0019\b\b\u0001\b\u0007\u000b\u001a\t\u0002\u0007\t\u001e\b\u001e\b\f\u0018\u000b\f\u001e\t\t\u000b\f\u001c\u000b\n\n\t\u000b\u000b\u001b\r\r\f\u000b\t\f\u001a\f\u000b\n\t\n\u000b\u001a\t\u0007\n\u000b\n\u000b\u001a\u0007\b\u000b\u0007\n\f\u0019\b\b\u0001\b\u0007\u000b\u001a\t\u0002\u0007\t\u001e\b\u001e\b\u000b\u0018\u000b\r\u001e\t\u000b\r\u001d\u000b\t\n\u000b\u001d\u000b\t\t\u000b\u001d\f\n\t\u000b\u001c\f\f\b\t\f\u001b\f\u000b\t\n\u000b\u001a\t\u0007\n\u000b\n\u000b\u001a\u0007\b\u000b\u0007\n\f\u0019\b\b\u0001\b\u0007\u000b\u001a\t\u0002\u0007\t\u001e\b\u001e\b\n\u0018\u000b\r\u001e\t\u000b\r\u001d\u000b\n\f\u001d\f\u000b\n\f\u001d\f\u000b\f\u001d\f\u000b\u001c\f\n\b\t\f\u001b\u000b\n\t\n\u000b\u001a\t\u0007\n\u000b\n\u000b\u001a\u0007\b\u000b\u0007\n\f\u0019\b\b\u0001\b\u0007\u000b\u001a\t\u0002\u0007\t\u001e\b\u001e\b\u000b\u0018\u000b\r\u001e\t\u000b\r\u001d\n\t\f\u001d\f\n\n\f\u001d\u000b\t\u000b\u001c\f\n\b\t\f\u001b\u000b\n\t\n\u000b\u001a\t\u0007\n\u000b\n\u000b\u001a\u0007\b\u000b\u0007\n\f\u0019\b\b\u0001\b\u0007\u000b\u001a\t\u0002\u0007\t\u001e\b\u001e\b\f\u0006\f\u000b\u001c\f\u000b\t\t\u001a\u000b\u000b\t\n\n\u000b\u0019\f\t\u000b\f\r\r\u001a\u000b\n\t\n\u000b\f\u001a\u000b\n\u000b\n\u0007\t\u001a\f\n\u0007\u000b\b\u0007\u001b\u000b\u0007\b\u0001\b\b\u001b\t\u0007\u0002\t\u001c\b \b\u000b\u0006\r\u000b\u001d\r\u000b\t\u001c\u000b\n\t\u000b\u001b\u000b\t\t\u000b\u001b\u000b\t\n\f\u001b\f\t\b\f\f\u001b\u000b\n\t\u000b\f\u001b\u000b\n\u000b\n\u0007\t\u001a\f\n\u0007\u000b\b\u0007\u001b\u000b\u0007\b\u0001\b\b\u001b\t\u0007\u0002\t\u001c\b \b\n\u0006\r\u000b\u001d\r\u000b\t\u001d\f\n\u000b\u001c\f\n\u000b\f\u001b\f\u000b\f\u001c\u000b\f\u001c\f\t\b\n\f\u001b\u000b\n\t\n\u000b\u001b\u000b\n\u000b\n\u0007\t\u001a\f\n\u0007\u000b\b\u0007\u001b\u000b\u0007\b\u0001\b\b\u001b\t\u0007\u0002\t\u001c\b \b\u000b\u0006\r\u000b\u001d\r\u000b\t\u001d\f\t\n\u001c\f\n\n\f\u001c\u000b\t\u000b\u001c\f\t\b\n\f\u001b\u000b\n\t\n\u000b\u001b\u000b\n\u000b\n\u0007\t\u001a\f\n\u0007\u000b\b\u0007\u001b\u000b\u0007\b\u0001\b\b\u001b\t\u0007\u0002\t\u001c\b \b\f\u0006\r\u000b\u001d\r\u000b\t\u001d\f\t\n\u001d\u000b\f\u001c\f\t\b\n\f\u001b\u000b\n\t\n\u000b\u001b\u000b\n\u000b\n\u0007\t\u001a\f\n\u0007\u000b\b\u0007\u001b\u000b\u0007\b\u0001\b\b\u001b\t\u0007\u0002\t\u001c\b \b\u000b\u0006\r\u000b\u001d\r\u000b\t\u001d\f\t\n\u001c\f\n\n\f\u001c\u000b\t\u000b\u001c\f\t\b\n\f\u001b\u000b\n\t\n\u000b\u001b\u000b\n\u000b\n\u0007\t\u001a\f\n\u0007\u000b\b\u0007\u001b\u000b\u0007\b\u0001\b\b\u001b\t\u0007\u0002\t\u001c\b \b\n\u0006\r\u000b\u001d\r\u000b\t\u001d\f\n\u000b\u001c\f\n\u000b\f\u001b\f\u000b\f\u001c\u000b\f\u001c\f\t\b\n\f\u001b\u000b\n\t\n\u000b\u001b\u000b\n\u000b\n\u0007\t\u001a\f\n\u0007\u000b\b\u0007\u001b\u000b\u0007\b\u0001\b\b\u001b\t\u0007\u0002\t\u001c\b \b\u000b\u0006\r\u000b\u001d\r\u000b\t\u001c\u000b\n\t\u000b\u001b\u000b\t\t\u000b\u001b\u000b\t\n\f\u001b\f\t\b\f\f\u001b\u000b\n\t\u000b\f\u001b\u000b\n\u000b\n\u0007\t\u001a\f\n\u0007\u000b\b\u0007\u001b\u000b\u0007\b\u0001\b\b\u001b\t\u0007\u0002\t\u001c\b \b\u0013\u000b\u000b\n\b\f\t\t\f\b\n\u000b\u0015\f\r\r\f\u000b\n\n\u000b\f\r\r\f\u0014\u000b\u000b\f\r\f\u000b\u000b\f\r\f\u000b\u000b\f\u0012\f\n\n\u000b\u000b\r\f\f\r\u000b\n\t\t\n\f\u0011\u000b\t\n\u000b\u0001\r\u0002\r\u0001\u000b\n\t\b\u000b\u0011\u000b\b\n\f\b\n\t\b\n\u0010\f\n\u000b\n\u000b\n\t\u000b\u000f\u000b\f\f\n\f\u000b\f\f\u000e\f\u000b\u000b\n\f\f\f\u0010\u000b\f\f\t\f\f\f\u000b\u000b\u000f\u000b\n\u000b\t\u000b\u000b\f\n\u000b\u000f\f\t\n\t\u0007\f\r\f\u0007\u0010\u000b\u000b\u001d\u000b\f\u000b\f\u001b\u000b\n\f\n\u000b\u001b\u0007\f\r\f\u0007\u0012\u000b\u000b\n\b\f\t\t\f\b\n\u000b\u0015\f\r\r\f\u000b\n\n\u000b\f\r\r\f\u0014\u000b\u000b\f\r\f\u000b\u000b\f\r\f\u000b\u000b\u0013\f\u000b\n\n\u000b\r\f\f\r\u000b\n\t\t\u000b\u0012\u000b\t\n\u000b\u0001\r\u0002\r\u0001\u000b\n\b\t\u0011\u000b\b\n\u000b\t\t\b\n\u0010\f\t\u000b\n\u000b\t\n\u000b\u000f\u000b\f\f\n\f\u000b\u000b\f\u000f\u000b\u000b\u000b\t\f\f\u000b\f\u0010\f\f\u000b\t\f\f\f\u000b\f\u000f\u000b\n\f\t\f\u000b\f\n\u000b\u000f\u000b\t\n\t\n\f\r\f\u0007\u0010\u000b\u000b\u001d\u000b\f\u000b\f\u001b\u000b\n\f\n\u000b\u001b\u0007\f\r\f\u0007\u0011\u000b\u000b\n\b\f\t\t\f\b\n\u000b\u0015\f\r\r\f\u000b\n\n\u000b\f\r\r\f\u0014\u000b\u000b\f\r\f\u000b\u000b\f\r\f\u000b\u000b\u0013\u000b\u000b\n\u000b\u000b\r\f\f\r\u000b\n\t\t\u000b\u0011\f\n\t\n\u000b\u0001\r\u0002\r\u0001\u000b\t\b\n\u0011\u000b\b\n\u000b\b\t\b\t\u0010\n\t\n\u000b\n\t\n\f\u000f\f\n\f\u000b\f\u000b\f\u000f\f\u000b\u000b\f\n\f\f\f\u0010\f\n\f\n\u000b\u000b\f\u0010\n\f\r\n\n\t\u0011\u000b\n\f\t\f\f\f\u000b\u0011\u000b\u000b\t\f\u000b\f\n\u000b\u000f\u000b\f\u000b\f\b\u000b\n\f\n\u000b\u000e\u000b\n\f\n\u000b\b\t\f\r\f\u0007\u000e\u0007\f\r\f\u0007\u0012\u000b\u000b\n\b\f\t\t\f\b\n\u000b\u0015\f\r\r\f\u000b\n\n\u000b\f\r\r\f\u0013\u000b\n\u000b\f\r\f\u000b\u000b\f\r\f\u000b\u000b\u0012\u000b\t\n\n\u000b\u000b\r\f\f\r\u000b\n\n\n\f\u0010\u000b\b\b\t\u000b\u0002\r\u0002\r\u0001\u000b\t\t\u000b\u000f\u000b\t\n\u000b\n\n\b\u000b\u000f\f\u000b\u000b\f\n\n\t\u000b\u0010\f\f\f\f\t\f\u000b\f\u0011\f\u000b\f\n\u000b\u000b\f\u0010\f\n\u000b\n\f\f\u000b\u0011\f\f\n\u000b\u000b\u000b\u0010\u000b\f\f\f\t\u000b\n\f\u000f\u000b\u000b\f\u000b\f\t\n\t\u0010\u0007\f\r\f\u0007\b\f\u000b\f\u000b\u001c\u0007\f\r\f\u0007\u001b\n\u000b\f\u000b\n\u0013\u000b\u000b\n\b\f\t\t\f\b\n\u000b\u0015\f\r\r\f\u000b\n\n\u000b\f\r\r\f\u0013\f\u000b\u000b\f\r\f\u000b\u000b\f\r\f\u000b\u000b\u0012\f\n\t\t\n\u000b\r\f\f\r\u000b\u000b\n\n\f\u0011\u000b\b\t\n\u000b\u0001\r\u0002\r\u0001\u000b\n\t\u000b\u0010\n\b\t\n\b\f\n\b\u000b\u000f\u000b\t\n\u000b\n\u000b\n\f\u000f\f\f\u000b\f\n\f\f\u000b\u0011\f\f\f\n\u000b\u000b\f\u000f\u000b\u000b\f\f\f\t\f\f\u000b\u000f\u000b\n\f\u000b\u000b\t\u000b\n\u000b\u000f\u0007\f\r\f\u0007\t\n\t\f\u001d\u000b\u000b\u001d\f\u000b\f\u000b\u001c\u000b\n\f\n\u000b\u001b\u0007\f\r\f\u0007\u0012\u000b\u000b\n\b\f\t\t\f\b\n\u000b\u0015\f\r\r\f\u000b\n\n\u000b\f\r\r\f\u0014\u000b\u000b\f\r\f\u000b\u000b\f\r\f\u000b\u000b\u0013\u000b\t\t\n\u000b\r\f\f\r\u000b\n\n\u000b\f\u0012\t\b\n\u000b\u0001\r\u0002\r\u0001\u000b\n\t\u000b\u0011\n\b\t\t\u000b\n\b\u000b\u000f\u000b\n\t\u000b\n\u000b\t\f\u000f\f\u000b\u000b\f\n\f\f\u000b\u0010\f\u000b\f\f\t\u000b\u000b\u000b\u000f\f\u000b\f\f\f\t\u000b\f\f\u000f\u000b\n\f\u000b\f\t\f\n\u000b\u000f\u0007\f\r\f\n\t\n\t\u000b\u001d\u000b\u000b\u001d\f\u000b\f\u000b\u001c\u000b\n\f\n\u000b\u001b\u0007\f\r\f\u0007\u0011\u000b\u000b\n\b\f\t\t\f\b\n\u000b\u0015\f\r\r\f\u000b\n\n\u000b\f\r\r\f\u0014\u000b\u000b\f\r\f\u000b\u000b\f\r\f\u000b\u000b\u0013\u000b\t\t\n\u000b\r\f\f\r\u000b\u000b\n\u000b\u000b\u0012\n\b\t\u000b\u0001\r\u0002\r\u0001\u000b\n\t\n\f\u0011\t\b\t\b\u000b\n\b\u000b\u0010\f\n\t\n\u000b\n\t\n\u000f\f\u000b\f\u000b\f\n\f\u000f\f\f\f\n\f\u000b\u000b\f\u000f\f\u000b\u000b\n\f\n\f\u0011\t\n\n\r\f\n\u0010\u000b\f\f\f\t\f\n\u000b\u000f\u000b\n\f\u000b\f\t\u000b\u000b\u0010\u000b\n\f\n\u000b\b\f\u000b\f\u000b\u000f\u0007\f\r\f\t\b\u000b\n\f\n\u000b\u001b\u0007\f\r\f\u0007\u0012\u000b\u000b\n\b\f\t\t\f\b\n\u000b\u0015\f\r\r\f\u000b\n\n\u000b\f\r\r\f\u0014\u000b\u000b\f\r\f\u000b\u000b\f\r\f\u000b\n\u000b\u0012\f\n\n\n\u000b\r\f\f\r\u000b\u000b\n\n\t\u000b\u0011\u000b\t\t\u000b\u0001\r\u0002\r\u0002\u000b\t\b\b\u000b\u0010\u000b\b\n\n\u000b\n\t\u000b\u000f\u000b\t\n\n\f\u000b\u000b\f\u000f\f\u000b\f\t\f\f\f\f\u000f\f\u000b\u000b\n\f\u000b\f\u0010\u000b\f\f\n\u000b\n\f\u0010\u000b\u000b\u000b\n\f\f\u0011\f\n\u000b\t\f\f\f\u000b\u0011\t\n\t\f\u000b\f\u000b\u000b\u000f\u000b\f\u000b\f\b\u0007\f\r\f\u0007\u000e\u0007\f\r\f\u0007\u001b\n\u000b\f\u000b\n\r\u0015\f\u000b\f\u001c\n\t\n\u000b\f\u001c\f\u000b\u000b\u000b\u001b\u000b\n\b\t\n\u001a\b\n\t\t\n\u000b\u0019\u0007\n\u000b\b\n\u000b\f\u0019\b\u000b\u0007\u000b\n\u000b\u001b\u0007\b\n\t\u001b\t\b\r\t\u001c\b\f\u0015\f\u001e\n\u000b\u001d\f\u000b\t\u000b\u001d\f\n\t\u000b\u001d\n\u000b\u001b\u000b\n\b\t\n\u001a\b\n\t\t\n\u000b\u0019\u0007\n\u000b\b\n\u000b\f\u0019\b\u000b\u0007\u000b\n\u000b\u001b\u0007\b\n\t\u001b\t\b\r\t\u001c\b\u000b\u0015\f\u001e\u000b\u001e\t\n\f\u001d\n\t\u000b\f\u001d\n\n\u000b\u001d\t\n\u001d\u000b\u001b\u000b\n\b\t\n\u001a\b\n\t\t\n\u000b\u0019\u0007\n\u000b\b\n\u000b\f\u0019\b\u000b\u0007\u000b\n\u000b\u001b\u0007\b\n\t\u001b\t\b\r\t\u001c\b\f\u0015\f\u001e\n\t\u001d\u000b\t\u000b\u001c\u000b\t\n\f\u001b\u000b\u000b\u001a\u000b\n\b\t\n\u001a\b\n\t\t\n\u000b\u0019\u0007\n\u000b\b\n\u000b\f\u0019\b\u000b\u0007\u000b\n\u000b\u001b\u0007\b\n\t\u001b\t\b\r\t\u001c\b\r\u0015\f\u001c\u000b\n\t\n\u0019\f\u000b\n\t\u000b\f\u0017\u000b\n\b\t\n\u000b\f\u0018\b\n\t\t\n\u000b\u0019\u0007\n\u000b\b\n\u000b\f\u0019\b\u000b\u0007\u000b\n\u000b\u001b\u0007\b\n\t\u001b\t\b\r\t\u001c\b\f\u0015\f\u001e\n\t\u001d\u000b\t\u000b\u001c\u000b\t\n\f\u001b\u000b\u000b\u001a\u000b\n\b\t\n\u001a\b\n\t\t\n\u000b\u0019\u0007\n\u000b\b\n\u000b\f\u0019\b\u000b\u0007\u000b\n\u000b\u001b\u0007\b\n\t\u001b\t\b\r\t\u001c\b\u000b\u0015\f\u001e\u000b\u001e\t\n\f\u001d\n\t\u000b\f\u001d\n\n\u000b\u001d\t\n\u001d\u000b\u001b\u000b\n\b\t\n\u001a\b\n\t\t\n\u000b\u0019\u0007\n\u000b\b\n\u000b\f\u0019\b\u000b\u0007\u000b\n\u000b\u001b\u0007\b\n\t\u001b\t\b\r\t\u001c\b\f\u0015\f\u001e\n\u000b\u001d\f\u000b\t\u000b\u001d\f\n\t\u000b\u001d\n\u000b\u001b\u000b\n\b\t\n\u001a\b\n\t\t\n\u000b\u0019\u0007\n\u000b\b\n\u000b\f\u0019\b\u000b\u0007\u000b\n\u000b\u001b\u0007\b\n\t\u001b\t\b\r\t\u001c\b\r\u000b\u001b\f\u000b\u000b\u0019\f\f\n\t\n\u000b\f\u0019\u000b\n\u000b\u000b\u001c\n\t\f\u001d\u000b\b\u000b\u000b\t\u001c\t\b\u000b\u001e\t\f\u000b\u001d\u000b\u001c\u000b\n\u000b\f\u001b\n\u000b\u000b\u001c\f\f\t\u001d\u000b\n\u000b\n\u001c\n\t\f\u001d\u000b\b\u000b\u000b\t\u001c\t\b\u000b\u001e\t\u000b\u000b\u001d\f\u001d\u000b\n\f\u001c\f\n\u000b\u001d\u000b\n\f\u001c\f\f\t\u001d\u000b\n\u000b\n\u001c\n\t\f\u001d\u000b\b\u000b\u000b\t\u001c\t\b\u000b\u001e\t\f\u000b\u001e\u000b\u001c\f\u000b\n\u000b\u001c\u000b\n\f\u001d\f\f\t\u001d\u000b\n\u000b\n\u001c\n\t\f\u001d\u000b\b\u000b\u000b\t\u001c\t\b\u000b\u001e\t\r\u000b\u001d\u000b\n\u001c\f\n\n\t\u001d\u000b\n\u000b\n\u001c\n\t\f\u001d\u000b\b\u000b\u000b\t\u001c\t\b\u000b\u001e\t\f\u000b\u001e\u000b\u001d\u000b\n\u000b\u001c\u000b\n\f\u001d\f\f\t\u001d\u000b\n\u000b\n\u001c\n\t\f\u001d\u000b\b\u000b\u000b\t\u001c\t\b\u000b\u001e\t\u000b\u000b\u001d\f\u001d\u000b\n\f\u001c\f\n\u000b\u001d\u000b\n\f\u001c\f\f\t\u001d\u000b\n\u000b\n\u001c\n\t\f\u001d\u000b\b\u000b\u000b\t\u001c\t\b\u000b\u001e\t\f\u000b\u001d\u000b\u001c\u000b\n\u000b\f\u001b\n\u000b\u000b\u001c\f\f\t\u001d\u000b\n\u000b\n\u001c\n\t\f\u001d\u000b\b\u000b\u000b\t\u001c\t\b\u000b\u001e\t\u0013\f\t\f\t\f\b\t\t\n\u000b\u0016\f\u000b\u000b\n\n\u000b\r\f\u000b\f\u0016\n\r\f\u000b\u000b\r\f\u000b\n\u000b\u0016\u000b\f\r\f\f\f\n\t\n\f\u0017\t\f\u0002\n\b\n\u000b\u0018\n\u000b\f\u0001\t\t\u000b\u0019\u000b\u000b\f\n\b\u000b\f\u001c\b\t\u000b\f\r\u001b\t\n\u000b\u000b\f\u001a\n\f\u000b\t\u000b\u000b\u001d\u000b\n\u000b\u001e\u000b\n\u001e\n\u000b\u001d\u000b\t\u000b\u000b\u001b\f\n\t\u000b\f\u001a\f\u000b\n\u000b\f\u001a\n\f\r\u0007\u000b\u0012\f\t\f\t\f\b\t\t\n\u000b\u0016\f\u000b\u000b\n\n\u000b\r\f\u000b\f\u0016\u000b\r\f\u000b\u000b\r\u000b\u000b\n\u0016\n\f\r\f\f\f\f\n\n\n\u0016\n\u000b\u0004\u000b\n\t\u000b\u0016\u000b\u000b\f\f\u0002\n\b\n\u0017\f\n\u000b\u000b\f\u000b\t\n\u000b\r\u0019\f\u000b\n\n\u000b\u001b\n\u000b\b\u000b\u001c\u000b\u000b\t\n\u000b\u001b\n\r\u000b\u000b\n\n\u000b\u001e\n\t\u000b\u001e\u000b\n\u001e\n\n\u000b\u001b\f\u000b\t\u000b\f\u001a\f\u000b\n\u000b\f\u001a\n\f\r\u0007\u000b\u0011\f\t\f\t\f\b\t\t\n\u000b\u0016\f\u000b\u000b\n\n\u000b\r\f\u000b\f\u0015\u000b\u000b\r\f\u000b\u000b\r\u000b\n\u000b\u0015\n\n\f\r\f\f\f\n\t\n\u0014\u000b\t\u000b\u0005\u000b\t\t\u000b\u0014\t\n\u0006\n\b\t\u000b\u0014\n\f\f\u0005\n\t\n\u0015\u000b\t\u000b\u0005\t\n\u000b\u0016\u000b\u000b\f\f\u0003\n\t\u000b\u0017\f\n\u000b\f\f\u0001\u000b\b\u000b\u0019\f\f\u000b\u0001\u000b\u000b\n\n\n\u000b\u0016\u000b\u000b\f\u0003\u000b\n\b\t\u000b\u0014\f\u000b\n\u0007\u000b\n\u0014\n\r\u0007\u0007\u000b\n\u000b\u001b\f\u000b\t\u000b\f\u001a\f\u000b\n\u000b\f\u001a\n\f\r\u0007\u000b\u0012\f\t\f\t\f\b\t\t\n\u000b\u0016\f\u000b\u000b\n\n\u000b\r\u000b\n\f\u0015\u000b\u000b\r\f\u000b\u000b\r\n\t\u000b\u0014\n\t\n\f\r\f\f\f\n\t\n\u0013\n\t\u000b\u0006\u000b\n\t\t\u0013\t\u000b\b\n\b\t\u0013\u000b\b\u000b\u0007\u000b\b\n\u0014\u000b\n\u000b\u0006\u000b\t\n\u0015\u000b\n\u000b\u0005\u000b\t\u000b\u0016\u000b\n\u0006\b\u000b\n\u000b\u0013\f\t\f\r\u0005\u000b\n\t\n\u000b\t\u000f\n\f\r\u0007\u000b\f\b\u000b\n\b\n\u000f\u000b\f\n\f\u000b\b\f\u000b\n\t\u001b\f\u000b\n\u000b\n\u001a\n\f\r\u0007\u000b\u0013\f\t\f\t\f\b\t\t\n\u000b\u0016\f\u000b\u000b\n\n\u000b\r\f\u000b\f\u0015\u000b\u000b\r\f\u000b\u000b\r\u000b\n\u000b\u0013\u000b\n\t\n\u000b\r\f\f\f\n\t\n\u0012\n\t\n\n\u000b\u0005\u000b\n\t\t\u000b\u0011\u000b\b\u000b\b\u000b\t\b\n\u0012\u000b\n\u000b\u0007\u000b\n\b\n\u0013\u000b\u000b\u000b\u0007\n\t\u000b\u0014\u000b\n\u000b\u0006\u000b\b\u000b\u000b\n\u0013\u000b\u000b\u0007\u000b\u000b\n\t\u000b\t\n\u000f\n\u000b\u000b\u000b\t\n\t\r\f\t\u000b\r\u000b\f\u000b\n\n\f\f\u000b\n\u000b\f\n\n\f\r\u0007\f\n\f\r\u0007\u0012\f\t\f\t\f\b\t\t\n\u000b\u0016\f\u000b\u000b\n\n\u000b\r\f\u000b\f\u0015\u000b\u000b\r\f\u000b\u000b\r\u000b\n\u000b\u0014\u000b\n\n\u000b\r\f\f\f\n\t\n\u0014\n\t\u000b\u0005\u000b\n\t\n\u0013\u000b\t\n\u0007\n\b\n\u0013\u000b\b\u000b\u0007\n\b\u000b\u0013\u000b\n\n\u000b\u0006\u000b\t\u000b\u0015\u000b\u000b\n\u000b\u0005\b\n\u000b\u0016\u000b\u000b\u000b\u0004\n\u000b\n\u000b\n\u000b\u0013\n\n\b\t\u000b\n\u0011\f\t\n\r\u0007\f\u000b\t\n\u0010\f\u000b\n\u000b\f\u0006\f\u000b\n\n\u0010\n\f\r\u0007\u0007\n\f\r\u000b\b\u0011\f\t\f\t\f\b\t\t\n\u000b\u0016\f\u000b\u000b\n\n\u000b\r\f\u000b\f\u0016\u000b\r\f\u000b\u000b\r\u000b\n\u000b\u0015\u000b\n\f\r\f\f\f\t\t\n\u0015\n\t\u000b\u0004\u000b\b\t\u000b\u0014\u000b\t\n\u000b\u0004\n\b\n\u0015\u000b\b\n\u0005\t\t\u000b\u0016\u000b\n\n\u000b\u0003\t\n\u0019\u000b\n\u000b\u000b\u0001\b\u000b\u001b\u000b\n\u0001\n\t\u001a\u000b\n\u000b\u0002\u000b\n\u0018\f\t\n\r\u0003\u000b\u000b\u0016\f\u000b\n\u000b\f\u0004\u000b\t\u000b\u0013\n\f\r\u0007\u0005\f\n\n\n\u001b\f\u000b\u000b\n\u001b\u000b\f\r\n\u001c\n\u0002\b\u0012\f\t\f\t\f\b\t\t\n\u000b\u0016\f\u000b\u000b\n\n\u000b\r\f\u000b\f\u0016\u000b\r\f\u000b\u000b\r\u000b\n\n\u0016\u000b\f\r\f\f\f\u000b\b\t\u000b\u0016\n\u000b\f\u0003\n\b\n\u0017\u000b\n\u000b\u0003\t\t\u000b\u0018\u000b\u000b\u000b\u0001\n\b\n\u001a\n\u000b\u000b\n\t\u000b\u001c\u000b\n\t\u001c\f\u000b\n\u000b\n\u001a\f\u000b\u000b\u000b\n\t\n\u0018\n\f\r\u0007\u0002\u000b\u000b\u000b\u001e\u000b\n\u001e\t\n\u001c\f\u000b\n\u000b\u001a\n\f\r\u0007\t\u000b\u001a\f\u000b\u000b\u000b\u000b\u000f\u0013\n\u001e\n\b\u000b\u001d\u000b\n\t\t\u000b\u001d\u000b\n\t\n\u001b\u000b\n\u001b\u000b\t\u000b\t\u000b\u001b\b\n\t\n\n\u001b\n\b\n\u0007\t\u001b\t\u0007\u000b\u0006\b\u001b\u0007\t\u0001\u0007\t\u001b\b\u0002\b\u001c\u000b\u000e\u0013\n\u001e\n\b\u000b\u001d\n\t\n\u001e\n\t\n\u001c\u000b\u000b\b\t\u001b\u000b\n\u001b\u000b\t\u000b\t\u000b\u001b\b\n\t\n\n\u001b\n\b\n\u0007\t\u001b\t\u0007\u000b\u0006\b\u001b\u0007\t\u0001\u0007\t\u001b\b\u0002\b\u001c\u000b\r\u0013\n\u001e\n\b\u000b\u001d\n\u0007\n\u001c\t\t\u000b\u001b\u000b\u000b\b\n\u001b\u000b\n\u001b\u000b\t\u000b\t\u000b\u001b\b\n\t\n\n\u001b\n\b\n\u0007\t\u001b\t\u0007\u000b\u0006\b\u001b\u0007\t\u0001\u0007\t\u001b\b\u0002\b\u001c\u000b\u000e\u0013\n\u001e\t\b\u000b\u001c\n\t\u000b\u001a\u000b\n\t\n\u001a\u000b\n\u000b\n\t\u001a\b\t\u000b\u001b\n\n\t\t\n\u001a\t\u0007\n\u0007\t\u000b\u001a\u0007\t\u000b\u0006\n\u001a\n\u0002\u0007\t\u001e\b\u000f\u0012\u000b\n\u0017\u000b\n\u000b\u000b\n\n\t\t\b\u000b\u0016\b\b\t\u000b\t\n\u000b\u000b\u0016\n\u000b\n\t\t\u0019\b\u0007\u0007\u000b\n\n\u000b\u0018\u000b\b\u0002\u0006\u0007\n\u001c\b\u0007\b\u001d\b\u000e\u0013\n\u001e\t\b\u000b\u001c\n\t\u000b\u001a\u000b\n\t\n\u001a\u000b\n\u000b\n\t\u001a\b\t\u000b\u001b\n\n\t\t\n\u001a\t\u0007\n\u0007\t\u000b\u001a\u0007\t\u000b\u0006\n\u001a\n\u0002\u0007\t\u001e\b\r\u0013\n\u001e\n\b\u000b\u001d\n\u0007\n\u001c\t\t\u000b\u001b\u000b\u000b\b\n\u001b\u000b\n\u001b\u000b\t\u000b\t\u000b\u001b\b\n\t\n\n\u001b\n\b\n\u0007\t\u001b\t\u0007\u000b\u0006\b\u001b\u0007\t\u0001\u0007\t\u001b\b\u0002\b\u001c\u000b\u000e\u0013\n\u001e\n\b\u000b\u001d\n\t\n\u001e\n\t\n\u001c\u000b\u000b\b\t\u001b\u000b\n\u001b\u000b\t\u000b\t\u000b\u001b\b\n\t\n\n\u001b\n\b\n\u0007\t\u001b\t\u0007\u000b\u0006\b\u001b\u0007\t\u0001\u0007\t\u001b\b\u0002\b\u001c\u000b\f\u0012\u000b\u000b\u0017\u000b\u000b\u000b\u000b\u000b\u000b\n\n\t\u000b\u0016\t\t\n\u000b\n\u000b\u000b\u000b\u0016\u000b\u000b\u000b\n\n\u0019\t\b\b\u000b\u000b\u000b\u000b\u0018\u000b\t\u0002\u0007\b\u000b\u001c\t\b\t\u001d\t\u000b\u0013\u000b\u001e\n\t\u000b\u001c\u000b\n\u000b\u001a\u000b\u000b\n\u000b\u001a\u000b\u000b\u000b\u000b\n\u001a\t\n\u000b\u001b\u000b\u000b\n\n\u000b\u001a\n\b\u000b\b\n\u000b\u001a\b\n\u000b\u0007\u000b\u001a\u000b\u0002\b\n\u001e\t\n\u0013\u000b\u001e\u000b\t\u000b\u001d\u000b\b\u000b\u001c\n\n\u000b\u001b\u000b\u000b\t\u000b\u001b\u000b\u000b\u001b\u000b\n\u000b\n\u000b\u001b\t\u000b\n\u000b\u000b\u001b\u000b\t\u000b\b\n\u001b\n\b\u000b\u0007\t\u001b\b\n\u0001\b\n\u001b\t\u0002\t\u001c\u000b\u000b\u0013\u000b\u001e\u000b\t\u000b\u001d\u000b\n\u000b\u001e\u000b\n\u000b\u001c\u000b\u000b\t\n\u001b\u000b\u000b\u001b\u000b\n\u000b\n\u000b\u001b\t\u000b\n\u000b\u000b\u001b\u000b\t\u000b\b\n\u001b\n\b\u000b\u0007\t\u001b\b\n\u0001\b\n\u001b\t\u0002\t\u001c\u000b\f\u0013\u000b\u001e\u000b\t\u000b\u001d\u000b\u000b\n\n\u000b\u001d\u000b\u000b\n\u000b\u001b\u000b\u000b\u001b\u000b\n\u000b\n\u000b\u001b\t\u000b\n\u000b\u000b\u001b\u000b\t\u000b\b\n\u001b\n\b\u000b\u0007\t\u001b\b\n\u0001\b\n\u001b\t\u0002\t\u001c\u000b\u000b\u0013\u000b\u001e\u000b\t\u000b\u001d\u000b\n\u000b\u001e\u000b\n\u000b\u001c\u000b\u000b\t\n\u001b\u000b\u000b\u001b\u000b\n\u000b\n\u000b\u001b\t\u000b\n\u000b\u000b\u001b\u000b\t\u000b\b\n\u001b\n\b\u000b\u0007\t\u001b\b\n\u0001\b\n\u001b\t\u0002\t\u001c\u000b\n\u0013\u000b\u001e\u000b\t\u000b\u001d\u000b\b\u000b\u001c\n\n\u000b\u001b\u000b\u000b\t\u000b\u001b\u000b\u000b\u001b\u000b\n\u000b\n\u000b\u001b\t\u000b\n\u000b\u000b\u001b\u000b\t\u000b\b\n\u001b\n\b\u000b\u0007\t\u001b\b\n\u0001\b\n\u001b\t\u0002\t\u001c\u000b\u000b\u0013\u000b\u001e\n\t\u000b\u001c\u000b\n\u000b\u001a\u000b\u000b\n\u000b\u001a\u000b\u000b\u000b\u000b\n\u001a\t\n\u000b\u001b\u000b\u000b\n\n\u000b\u001a\n\b\u000b\b\n\u000b\u001a\b\n\u000b\u0007\u000b\u001a\u000b\u0002\b\n\u001e\t\u0013\f\n\t\t\n\u000b\u000b\u000b\u0019\t\f\n\t\n\n\u000b\f\u0018\n\f\r\f\f\r\f\f\u0018\u000b\r\u000b\n\n\f\r\f\u0019\f\n\t\n\u000b\f\u0019\f\n\b\n\u000b\f\u0019\f\n\t\u000b\f\f\u000b\n\f\u0016\f\u000b\t\u000b\f\u0003\f\u000b\u000b\u0015\u000b\n\u000b\u000b\u0006\f\f\u000b\u000b\u0013\u000b\n\t\f\u0006\f\f\u0016\u000b\t\u000b\u0003\f\u000b\u000b\f\u0017\f\t\n\u0001\b\u000b\f\f\u0018\u000b\n\u000b\u001c\u000b\n\f\u001b\u000b\n\n\u000b\u000b\u001a\u0007\n\u000b\f\f\n\u0012\f\n\t\t\n\u000b\u000b\u000b\u0019\t\f\n\t\n\n\u000b\f\u0018\n\f\r\f\f\r\f\f\u0018\u000b\r\u000b\n\u000b\f\r\f\u0019\f\n\t\n\u000b\f\u001a\u000b\t\t\n\f\u001b\n\b\n\u000b\u000b\f\u0019\f\n\t\u000b\f\n\u000b\f\u0018\u000b\t\u000b\f\u0001\f\f\u000b\f\f\f\u000b\u0014\u000b\n\u000b\u0005\f\u000b\u000b\f\u0015\u000b\n\n\u000b\u0004\f\u000b\f\u0017\u000b\t\n\u0003\u000b\f\u0019\f\t\n\u0001\b\f\u001a\u000b\n\u000b\u001c\u000b\n\f\u001b\u000b\n\n\u000b\u000b\u001a\u0007\n\u000b\f\f\n\u0011\f\n\t\t\n\u000b\u000b\u000b\u0019\t\f\n\t\n\n\u000b\f\u0018\n\f\r\f\f\r\f\f\u0018\u000b\r\u000b\n\u000b\f\r\f\u0019\u000b\t\n\u000b\f\u001a\f\u000b\n\n\u000b\u001c\n\t\n\f\u001c\n\b\n\f\u001c\u000b\t\u000b\u000b\f\f\f\u000b\u0018\u000b\n\f\u0001\f\u000b\u000b\f\u0018\f\n\u000b\u0002\f\u000b\f\u0019\u000b\t\u000b\u0001\u000b\f\u001b\f\t\u000b\f\u001d\f\t\n\u001e\n\u000b\u001d\u000b\n\f\u001b\u000b\n\n\u000b\u000b\u001a\u0007\n\u000b\f\f\n\u0012\f\n\t\t\n\u000b\u000b\u000b\u0019\t\f\n\t\n\n\u000b\f\u0018\n\f\r\f\f\r\f\f\u0018\u000b\r\u000b\n\u000b\f\r\f\u0018\u000b\u000b\t\n\u000b\f\u0019\f\f\u000b\n\n\u000b\u001b\f\n\b\n\f\u001c\f\t\u000b\u001e\n\u000b\f\u001d\u000b\t\u000b\u001a\b\f\u000b\u000b\u000b\b\u000b\u001a\f\f\f\u0001\f\t\n\u001e\f\u000b\t\u001e\u000b\n\u001e\f\u000b\u000b\u001b\u000b\n\u000b\u000b\n\u001a\u0007\n\u000b\f\f\u0013\f\n\t\t\n\u000b\u000b\u000b\u0019\t\f\n\t\n\n\u000b\f\u0017\f\n\f\r\f\f\r\f\f\u0016\f\f\u000b\r\u000b\n\u000b\f\r\f\u0016\f\u000b\f\n\t\n\u000b\f\u0018\f\u000b\f\n\b\n\u000b\u001b\f\u000b\b\n\u000b\u001c\f\t\n\f\u001c\f\n\u000b\u001c\f\u000b\t\n\u000b\u0019\f\u000b\u000b\f\f\u000b\n\t\u000b\u0016\b\u000b\f\f\f\u000b\u0002\u000b\n\n\u001f\u000b\u000b\n\n\u001d\u000b\u000b\u001c\u000b\n\n\f\u001b\u0007\n\u000b\f\u0012\f\n\t\t\n\u000b\u000b\u000b\u0019\t\f\n\t\n\n\u000b\f\u0018\n\f\r\f\f\r\f\f\u0018\u000b\r\u000b\n\u000b\f\r\f\u0018\f\n\t\n\u000b\f\u0019\f\f\n\b\n\u000b\u001b\f\u000b\t\b\u000b\u001d\n\t\u000b\u001d\u000b\n\u000b\u000b\u001d\n\u000b\f\u001c\f\t\n\u000b\u001a\f\u000b\u000b\u000b\t\n\u000b\u0018\b\u000b\f\f\f\u000b\u000b\n\u000b\u000b\u000b\n\u001c\u000b\n\n\f\u001d\u000b\n\u000b\u001d\n\u000b\u001d\u0007\u000b\u0011\f\n\t\t\n\u000b\u000b\u000b\u0019\t\f\n\t\n\n\u000b\f\u0018\n\f\r\f\f\r\f\f\u0018\u000b\r\u000b\n\n\f\r\f\u0019\n\t\n\u000b\f\u001a\f\n\b\n\u000b\u001c\n\b\n\u001d\t\t\u000b\f\u001c\t\n\f\n\f\u001b\n\u000b\u0001\f\n\u000b\u001a\n\u000b\u0002\u000b\f\u001a\t\n\t\u000b\u000b\f\u001b\u000b\n\n\u000b\u000b\u000b\n\u0018\b\u000b\f\f\u000b\n\n\f\u001d\u000b\n\u000b\u001d\n\u000b\u001d\u0007\u000b\u0012\f\n\t\t\n\u000b\u000b\u000b\u0019\t\f\n\t\n\n\u000b\f\u0018\n\f\r\f\f\r\f\f\u0018\u000b\r\u000b\n\n\f\r\f\u0019\u000b\n\t\n\u000b\f\u001a\n\b\n\u000b\f\u001a\u000b\t\n\u000b\f\t\f\u0019\t\n\u000b\u0002\f\n\u000b\u0018\n\n\u0004\f\f\n\u0017\u000b\n\u000b\u0004\f\u000b\u0018\u000b\t\u000b\u0003\f\f\f\u0018\u000b\t\n\f\u000b\f\f\u000b\u0019\f\n\u000b\f\f\f\u001a\u000b\n\t\u001a\u0007\u000b\n\n\u000b\n\u001b\u000b\u000b\f\r\f\u000b\u001e\f\n\u000b\u001d\u000b\n\u000b\u001c\u000b\n\b\t\n\u001c\t\t\b\u000b\u001c\u000b\n\t\t\u001c\f\u000b\b\u000b\t\n\u001b\f\t\b\u000b\u001d\u000b\t\u0007\b\f\f\u000b\u001e\f\n\u000b\u001d\u000b\t\n\u001d\f\n\u000b\u001d\u000b\f\u001d\n\b\n\n\u001c\u000b\t\n\n\u000b\u001c\u000b\n\u000b\u000b\u001c\f\u000b\b\u000b\t\n\u001b\f\t\b\u000b\u001d\u000b\t\u0007\b\u000b\f\u000b\u001e\f\n\u000b\u001d\u000b\n\n\u001c\f\n\u000b\f\u001c\u000b\n\f\u001d\n\t\u001d\n\u001d\n\b\t\n\u001c\u000b\t\n\n\u000b\u001c\u000b\n\u000b\u000b\u001c\f\u000b\b\u000b\t\n\u001b\f\t\b\u000b\u001d\u000b\t\u0007\b\f\f\u000b\u001e\f\n\u000b\u001d\u000b\n\n\u001c\n\t\n\u001c\u000b\n\u000b\u001c\n\u001d\n\b\t\n\u001c\t\n\n\u000b\u001c\u000b\n\u000b\u000b\u001c\f\u000b\b\u000b\t\n\u001b\f\t\b\u000b\u001d\u000b\t\u0007\b\r\f\u000b\u001e\f\n\u000b\u001c\u000b\n\t\n\u001b\u000b\n\n\u000b\u001b\u000b\u000b\u001b\u000b\t\n\n\u000b\u001b\u000b\n\u000b\u000b\u001c\f\u000b\b\u000b\t\u001c\f\t\b\u000b\n\u001c\u000b\u0007\t\u001f\b\f\f\u000b\u001e\f\n\u000b\u001d\u000b\n\n\u001c\n\t\n\u001c\u000b\n\u000b\u001c\n\u001d\n\b\t\n\u001c\t\n\n\u000b\u001c\u000b\n\u000b\u000b\u001c\f\u000b\b\u000b\t\n\u001b\f\t\b\u000b\u001d\u000b\t\u0007\b\u000b\f\u000b\u001e\f\n\u000b\u001d\u000b\n\n\u001c\f\n\u000b\f\u001c\u000b\n\f\u001d\n\n\u001d\n\u001d\n\b\t\n\u001c\u000b\t\n\n\u000b\u001c\u000b\n\u000b\u000b\u001c\f\u000b\b\u000b\t\n\u001b\f\t\b\u000b\u001d\u000b\t\u0007\b\f\f\u000b\u001e\f\n\u000b\u001d\u000b\t\n\u001d\f\n\u000b\u001d\u000b\f\u001d\n\b\n\n\u001c\u000b\t\n\n\u000b\u001c\u000b\n\u000b\u000b\u001c\f\u000b\b\u000b\t\n\u001b\f\t\b\u000b\u001d\u000b\t\u0007\b\f\u0015\u000b\u000b\u001e\f\f\u000b\u001a\u000b\u000b\f\u000b\u000b\n\u0019\f\n\u000b\n\f\u000b\u001a\u000b\u000b\n\t\u000b\u000b\u0018\n\u000b\u000b\f\n\u000b\f\u001a\u000b\n\t\u000b\u001b\b\u0007\n\u000b\u000b\u0015\u000b\u000b\u001e\f\f\u000b\u001d\u000b\u000b\n\u001c\f\u000b\t\u000b\u001a\u000b\u000b\n\n\u000b\u001a\f\n\u000b\n\u000b\u001b\u000b\u000b\n\t\u001a\n\u000b\u000b\f\n\u000b\u001b\u000b\n\t\u000b\u001b\b\u0007\n\u000b\n\u0015\u000b\u000b\u001e\f\f\u000b\u001d\u000b\u000b\n\u001d\f\u000b\u001d\f\n\u001c\u000b\u000b\u000b\u000b\u001b\f\n\u000b\n\u000b\u001b\u000b\u000b\n\t\u001a\n\u000b\u000b\f\n\u000b\u001b\u000b\n\t\u000b\u001b\b\u0007\n\u000b\u000b\u0015\u000b\u000b\u001e\f\f\u000b\u001d\u000b\u000b\n\u000b\u001d\f\u000b\u001c\u000b\u000b\f\u000b\u001b\f\n\u000b\n\u000b\u001b\u000b\u000b\n\t\u001a\n\u000b\u000b\f\n\u000b\u001b\u000b\n\t\u000b\u001b\b\u0007\n\u000b\f\u0015\u000b\u000b\u000b\u001d\f\f\u000b\n\u001a\u000b\u000b\n\u000b\u000b\u000b\u001b\f\n\u000b\n\u000b\u001b\u000b\u000b\n\t\u001a\n\u000b\u000b\f\n\u000b\u001b\u000b\n\t\u000b\u001b\b\u0007\n\u000b\u000b\u0015\u000b\u000b\u001e\f\f\u000b\u001d\u000b\u000b\n\u000b\u001d\f\u000b\u001c\u000b\u000b\f\u000b\u001b\f\n\u000b\n\u000b\u001b\u000b\u000b\n\t\u001a\n\u000b\u000b\f\n\u000b\u001b\u000b\n\t\u000b\u001b\b\u0007\n\u000b\n\u0015\u000b\u000b\u001e\f\f\u000b\u001d\u000b\u000b\n\u001d\f\u000b\u001d\f\n\u001c\u000b\u000b\u000b\u000b\u001b\f\n\u000b\n\u000b\u001b\u000b\u000b\n\t\u001a\n\u000b\u000b\f\n\u000b\u001b\u000b\n\t\u000b\u001b\b\u0007\n\u000b\u000b\u0015\u000b\u000b\u001e\f\f\u000b\u001d\u000b\u000b\n\u001c\f\u000b\t\u000b\u001a\u000b\u000b\n\n\u000b\u001a\f\n\u000b\n\u000b\u001b\u000b\u000b\n\t\u001a\n\u000b\u000b\f\n\u000b\u001b\u000b\n\t\u000b\u001b\b\u0007\n\u000b\u0013\f\n\n\f\n\u000b\f\t\u000b\u000b\u0017\u000b\f\u000b\u000b\r\f\b\t\f\u0017\n\t\n\n\u000b\r\n\u000b\f\u0015\f\t\b\t\t\u000b\u000b\f\f\f\u000b\u0014\u000b\u000b\n\t\n\u000b\f\u0002\f\f\n\u0014\t\f\u000b\f\u0005\f\n\u000b\u0014\u000b\n\f\u0006\f\u000b\f\u0015\u000b\n\u000b\u0006\f\f\u0016\u000b\t\u0006\u000b\n\u000b\u0015\u000b\n\u0007\f\u000b\u000b\u0012\u000b\u000b\n\f\t\r\f\f\u000e\f\f\u000b\t\u000b\n\u000b\n\u000b\r\b\f\u000b\n\t\n\t\u000b\u000b\f\f\u001b\t\u000b\f\f\u0012\f\n\n\f\n\u000b\f\t\u000b\u000b\u0017\u000b\f\u000b\u000b\r\f\b\t\f\u0017\f\n\t\n\u000b\r\n\u000b\f\u0017\n\t\t\n\u000b\f\f\f\u0017\u000b\b\t\n\u000b\f\f\u000b\u000b\u0016\u000b\n\n\u000b\u0003\f\n\u000b\u0016\n\u000b\f\u0004\f\u000b\f\u0016\u000b\n\f\u0005\f\n\u000b\u0016\u000b\n\f\u0005\f\n\u000b\u0016\u000b\u000b\f\u0005\f\f\u000b\u0016\n\t\u0006\u000b\u000b\f\u0015\u000b\n\u0005\f\u000b\n\u000b\u0013\u000b\u000b\n\f\u0004\f\u000b\u000b\f\f\u0011\f\f\u000b\t\u000b\u0005\t\u0001\n\u0012\b\f\u000b\n\t\n\u0011\f\n\n\f\n\u000b\f\t\u000b\u000b\u0017\u000b\f\u000b\u000b\r\f\b\t\f\u0017\f\u000b\n\n\u000b\r\n\u000b\f\u0018\n\t\n\u000b\f\f\f\f\u0017\f\t\t\u000b\f\f\u000b\f\u0018\u000b\b\n\u000b\f\n\f\u0019\n\n\f\u0001\f\u000b\n\u0019\u000b\u000b\u0004\u000b\n\u0018\n\u000b\u0004\f\u000b\u000b\u0017\f\n\u000b\u0004\u000b\u000b\f\u0017\f\t\u000b\u0002\f\u000b\n\u000b\u0018\u000b\n\u000b\f\u000b\u000b\f\f\u0019\u000b\b\t\u0001\n\u001b\n\t\u001c\u000b\u000b\n\f\u001a\f\f\u000b\t\u000b\u001a\b\f\u000b\n\t\n\u0012\f\n\n\f\n\u000b\f\t\u000b\u000b\u0017\u000b\f\u000b\u000b\r\f\b\t\f\u0017\f\u000b\t\n\u000b\r\n\u000b\f\u0018\u000b\t\t\n\f\f\f\u0019\u000b\t\t\u000b\f\u001b\n\t\n\f\u000b\u001b\n\b\u000b\f\n\f\u001a\u000b\t\f\u0001\u000b\u000b\u001a\f\u000b\f\f\u000b\u000b\f\u0019\u000b\n\u000b\f\u000b\n\u000b\u001a\u000b\n\u000b\f\u000b\u001c\u000b\b\u000b\u001e\u000b\n\u001e\u000b\t\u000b\u001c\u000b\u000b\n\f\u001a\f\f\u000b\n\t\u000b\u0019\b\f\u000b\n\u000b\f\f\u0013\f\n\n\f\n\u000b\f\t\u000b\u000b\u0017\u000b\f\u000b\u000b\r\f\b\t\f\u0017\f\u000b\n\n\u000b\r\n\u000b\f\u0018\n\t\n\n\f\f\f\u0019\u000b\t\t\n\f\u001b\f\t\t\u000b\u001d\n\b\f\u001d\u000b\t\u000b\u001c\f\n\n\u000b\u001b\u000b\f\n\f\u000b\u001d\u000b\t\u000b\u001e\u000b\t\u000b\u001e\u000b\n\n\u000b\u001d\f\u000b\t\n\u001c\u000b\n\u000b\f\u001a\f\f\n\u000b\f\f\u0019\b\f\u000b\f\f\f\u0012\f\n\n\f\n\u000b\f\t\u000b\u000b\u0017\u000b\f\u000b\u000b\r\f\b\t\f\u0017\f\u000b\t\n\u000b\r\n\u000b\f\u0018\n\t\t\u000b\f\f\f\u0018\u000b\t\t\n\f\f\u001a\t\t\n\f\u000b\u000b\u0019\u000b\b\n\u000b\f\u000b\n\u0019\n\t\u000b\u0002\f\n\u000b\u0018\t\f\u0004\u000b\n\u0018\n\u000b\u000b\u0003\f\u000b\u0019\n\n\u000b\f\u000b\f\f\u001a\u000b\n\u000b\u000b\n\u000b\u001d\u000b\n\t\n\u001c\u000b\u000b\f\f\u001b\f\u000b\f\f\u001b\f\u000b\f\f\f\u001b\b\u0002\u000b\u0011\f\n\n\f\n\u000b\f\t\u000b\u000b\u0017\u000b\f\u000b\u000b\r\f\b\t\f\u0017\f\u000b\n\n\u000b\r\n\u000b\f\u0018\n\t\n\u000b\f\f\f\u0018\u000b\t\t\u000b\f\f\f\u000b\u0018\b\t\u000b\u0002\f\n\u000b\u0017\n\n\u000b\u0003\f\u000b\f\u0017\t\u000b\u0004\f\n\u000b\u0017\u000b\t\n\u000b\u0003\f\n\u000b\u0017\n\u000b\b\u000b\u0003\u000b\n\u0019\t\b\n\u0002\u000b\f\u0019\u000b\n\t\n\f\n\u000b\u0019\u000b\u000b\f\f\u000b\n\u000b\u0018\f\u000b\f\f\u000b\n\u000b\u000b\u0017\f\u000b\f\f\f\u001b\b\u0002\u000b\u0012\f\n\n\f\n\u000b\f\t\u000b\u000b\u0017\u000b\f\u000b\u000b\r\f\b\t\f\u0017\f\n\t\n\u000b\r\n\u000b\f\u0017\n\t\t\n\u000b\f\f\f\u0017\n\b\t\n\u000b\f\f\f\u000b\u0016\n\t\n\u000b\u0003\u000b\n\u000b\u0016\u000b\n\u000b\u0005\u000b\u000b\u0017\u000b\f\n\u0004\f\f\u0018\u000b\b\n\u0003\u000b\n\n\u0018\u000b\b\u000b\u0003\u000b\t\f\u0015\f\f\u000b\n\u000b\u0004\f\u000b\u000b\u0012\b\f\u000b\u000b\t\u000b\u0006\u000b\u000b\f\u0012\f\u000b\n\t\n\u0004\f\u000b\u000b\n\u000b\u001a\t\f\u000b\f\f\f\r\u0006\r\u000b\u001d\r\u000b\t\u001d\f\t\n\u001d\u000b\f\u001c\f\b\t\n\f\u001b\u000b\n\n\u000b\f\u001b\f\u000b\u000b\u000b\f\t\u001a\f\u000b\u0007\f\u000b\n\u001b\f\b\u000b\u0001\u000b\n\u001b\n\b\u0001\r\u000b\u001c\f\u0001\r\r\f\u0006\r\u000b\u001d\r\u000b\t\u001d\f\t\n\u001c\f\n\n\f\u001c\u000b\t\f\u001c\f\b\t\n\f\u001b\u000b\n\n\u000b\f\u001b\f\u000b\u000b\u000b\f\t\u001a\f\u000b\u0007\f\u000b\n\u001b\f\b\u000b\u0001\u000b\n\u001b\n\b\u0001\r\u000b\u001c\f\u0001\r\r\u000b\u0006\r\u000b\u001d\r\u000b\t\u001d\f\n\u000b\u001c\f\n\u000b\f\u001b\f\u000b\f\u001c\u000b\f\u001c\f\b\t\n\f\u001b\u000b\n\n\u000b\f\u001b\f\u000b\u000b\u000b\f\t\u001a\f\u000b\u0007\f\u000b\n\u001b\f\b\u000b\u0001\u000b\n\u001b\n\b\u0001\r\u000b\u001c\f\u0001\r\r\f\u0006\r\u000b\u001d\r\u000b\t\u001c\u000b\n\t\u000b\u001b\u000b\t\t\u000b\u001b\u000b\t\f\f\u001b\f\b\t\n\f\u001b\u000b\n\n\u000b\f\u001b\f\u000b\u000b\u000b\f\t\u001a\f\u000b\u0007\f\u000b\n\u001b\f\b\u000b\u0001\u000b\n\u001b\n\b\u0001\r\u000b\u001c\f\u0001\r\r\r\u0006\f\u000b\u001c\f\u000b\t\t\u001a\u000b\u000b\t\n\n\u000b\u0019\f\b\t\n\f\r\u001a\u000b\n\n\u000b\f\f\u001a\f\u000b\u000b\u000b\f\t\u001a\f\u000b\u0007\f\u000b\n\u001b\f\b\u000b\u0001\u000b\n\u001b\n\b\u0001\r\u000b\u001c\f\u0001\r\r\f\u0006\r\u000b\u001d\r\u000b\t\u001c\u000b\n\t\u000b\u001b\u000b\t\t\u000b\u001b\u000b\t\f\f\u001b\f\b\t\n\f\u001b\u000b\n\n\u000b\f\u001b\f\u000b\u000b\u000b\f\t\u001a\f\u000b\u0007\f\u000b\n\u001b\f\b\u000b\u0001\u000b\n\u001b\n\b\u0001\r\u000b\u001c\f\u0001\r\r\u000b\u0006\r\u000b\u001d\r\u000b\t\u001d\f\n\u000b\u001c\f\n\u000b\f\u001b\f\u000b\f\u001c\f\u001c\f\b\t\n\f\u001b\u000b\n\n\u000b\f\u001b\f\u000b\u000b\u000b\f\t\u001a\f\u000b\u0007\f\u000b\n\u001b\f\b\u000b\u0001\u000b\n\u001b\n\b\u0001\r\u000b\u001c\f\u0001\r\r\f\u0006\r\u000b\u001d\r\u000b\t\u001d\f\t\n\u001c\f\n\n\f\u001c\u000b\t\f\u001c\f\b\t\n\f\u001b\u000b\n\n\u000b\f\u001b\f\u000b\u000b\u000b\f\t\u001a\f\u000b\u0007\f\u000b\n\u001b\f\b\u000b\u0001\u000b\n\u001b\n\b\u0001\r\u000b\u001c\f\u0001\r\r\r\u0018\u000b\f\u001e\t\t\u000b\f\u001c\u000b\n\n\t\u000b\u000b\u001b\r\f\n\t\b\f\u001a\f\f\u000b\n\n\u000b\u001a\t\f\u000b\u000b\u000b\f\u001a\n\u000b\f\u0007\u000b\f\u0019\n\u000b\u0001\u000b\b\f\u001a\u000b\r\u0001\b\n\u001b\r\r\u0001\f\f\u0018\u000b\r\u001e\t\u000b\r\u001d\u000b\t\n\u000b\u001d\u000b\t\t\u000b\u001d\f\f\t\u000b\u001c\f\n\t\b\f\u001b\f\u000b\n\n\u000b\u001a\t\f\u000b\u000b\u000b\f\u001a\n\u000b\f\u0007\u000b\f\u0019\n\u000b\u0001\u000b\b\f\u001a\u000b\r\u0001\b\n\u001b\r\r\u0001\f\u000b\u0018\u000b\r\u001e\t\u000b\r\u001d\u000b\n\f\u001d\f\u000b\n\f\u001d\f\u000b\f\u001d\f\u001c\f\n\t\b\f\u001b\f\u000b\n\n\u000b\u001a\t\f\u000b\u000b\u000b\f\u001a\n\u000b\f\u0007\u000b\f\u0019\n\u000b\u0001\u000b\b\f\u001a\u000b\r\u0001\b\n\u001b\r\r\u0001\f\f\u0018\u000b\r\u001e\t\u000b\r\u001d\n\t\f\u001d\f\n\n\f\u001d\f\t\u000b\u001c\f\n\t\b\f\u001b\f\u000b\n\n\u000b\u001a\t\f\u000b\u000b\u000b\f\u001a\n\u000b\f\u0007\u000b\f\u0019\n\u000b\u0001\u000b\b\f\u001a\u000b\r\u0001\b\n\u001b\r\r\u0001\f\r\u0018\u000b\r\u001e\t\u000b\r\u001d\n\t\f\u001d\f\u000b\u001c\f\n\t\b\f\u001b\f\u000b\n\n\u000b\u001a\t\f\u000b\u000b\u000b\f\u001a\n\u000b\f\u0007\u000b\f\u0019\n\u000b\u0001\u000b\b\f\u001a\u000b\r\u0001\b\n\u001b\r\r\u0001\f\f\u0018\u000b\r\u001e\t\u000b\r\u001d\n\t\f\u001d\f\n\n\f\u001d\f\t\u000b\u001c\f\n\t\b\f\u001b\f\u000b\n\n\u000b\u001a\t\f\u000b\u000b\u000b\f\u001a\n\u000b\f\u0007\u000b\f\u0019\n\u000b\u0001\u000b\b\f\u001a\u000b\r\u0001\b\n\u001b\r\r\u0001\f\u000b\u0018\u000b\r\u001e\t\u000b\r\u001d\u000b\n\f\u001d\f\u000b\n\f\u001d\f\u000b\f\u001d\f\u000b\u001c\f\n\t\b\f\u001b\f\u000b\n\n\u000b\u001a\t\f\u000b\u000b\u000b\f\u001a\n\u000b\f\u0007\u000b\f\u0019\n\u000b\u0001\u000b\b\f\u001a\u000b\r\u0001\b\n\u001b\r\r\u0001\f\f\u0018\u000b\r\u001e\t\u000b\r\u001d\u000b\t\n\u000b\u001d\u000b\t\t\u000b\u001d\f\f\t\u000b\u001c\f\n\t\b\f\u001b\f\u000b\n\n\u000b\u001a\t\f\u000b\u000b\u000b\f\u001a\n\u000b\f\u0007\u000b\f\u0019\n\u000b\u0001\u000b\b\f\u001a\u000b\r\u0001\b\n\u001b\r\r\u0001\f\u0013\u000b\u000b\f\n\f\n\n\f\n\f\u000b\u0015\f\r\r\f\f\b\b\f\f\r\r\f\u0013\r\u000b\n\r\f\n\n\f\r\t\n\f\u0012\r\f\u000b\t\n\r\f\f\r\n\b\n\u000b\u0011\r\f\f\f\u000b\u000b\f\r\u0002\r\u000b\n\u000b\u000b\u0011\f\u000b\r\f\f\r\u0005\f\u000b\u000b\f\u0012\f\u000b\r\b\f\f\f\f\u0012\f\t\u000b\b\f\u000b\f\u0012\f\u000b\f\b\u000b\t\u0012\r\f\f\r\b\u000b\b\u0011\f\f\u000b\n\u000b\b\f\n\u0011\f\u000b\n\t\f\b\f\f\r\u001d\r\n\u000b\r\u001c\f\t\n\f\u001c\f\f\u000b\u000b\f\u001b\n\f\r\f\n\u0012\u000b\u000b\f\n\f\n\n\f\n\f\u000b\u0015\f\r\r\f\f\b\b\f\f\r\r\f\u0013\r\u000b\n\r\f\n\n\f\r\t\n\f\u0013\f\u000b\t\n\r\f\f\r\f\n\n\u000b\u0012\r\f\f\u000b\u000b\f\r\u0002\r\u000b\n\u000b\u000b\r\u0011\f\f\f\f\f\u0005\f\u000b\u000b\u000b\f\u0011\u000b\f\r\b\f\u000b\f\f\u0011\f\f\u000b\n\f\u000b\f\u0011\u000b\t\f\t\u000b\t\u000b\u0011\f\n\u000b\t\f\u000b\u0013\u000b\f\b\u000b\n\u000b\u0011\r\f\f\r\b\f\f\r\u0010\f\f\u000b\n\u000b\b\r\n\u000b\r\u000f\f\u000b\n\t\f\b\f\t\n\f\u001c\f\f\u000b\u000b\f\u001b\u000b\f\r\f\u000b\u001b\t\u0003\t\u0011\u000b\u000b\f\n\f\n\n\f\n\f\u000b\u0015\f\r\r\f\f\b\b\f\f\r\r\f\u0014\u000b\n\r\f\n\n\f\r\n\n\r\u0012\r\n\t\n\r\f\f\r\n\t\n\f\u0012\f\u000b\u000b\n\f\r\u0002\r\u000b\n\n\u000b\f\r\u0011\f\f\u000b\u000b\f\u0004\f\f\u000b\u000b\f\f\u0010\f\f\f\f\f\u0007\f\f\f\f\r\u000f\u000b\u000b\f\f\n\f\f\f\u000f\f\n\f\u000b\u000b\u000b\u0011\f\n\u000b\t\u000b\n\u0012\u000b\b\n\b\u000b\n\u000b\u0013\t\u000b\b\f\f\r\u0013\u000b\f\b\r\n\u000b\r\u0010\r\f\f\r\b\f\t\n\f\u000f\f\f\u000b\n\u000b\b\f\f\u000b\u000b\f\u000e\f\u000b\n\t\f\b\n\f\r\f\n\u0012\u000b\u000b\f\n\f\n\n\f\n\f\u000b\u0015\f\r\r\f\f\b\b\f\f\r\r\f\u0014\f\n\u000b\r\f\n\n\f\r\n\u000b\r\u0013\u000b\t\t\f\r\f\f\r\n\t\u000b\f\r\u0012\u000b\u000b\n\u000b\r\u0002\r\f\u000b\u000b\f\f\f\r\u0011\f\u000b\u000b\f\u0006\f\f\u000b\n\f\u0010\f\f\u000b\f\b\u000b\b\f\u0011\f\u000b\f\b\u000b\n\u000b\u0013\n\u000b\b\f\u000b\f\r\u0011\u000b\u000b\n\b\r\n\u000b\f\u0011\u000b\u0007\u000b\b\f\t\n\u000b\f\u0010\u000b\t\f\b\u000b\u000b\f\f\u000b\u000f\r\f\u000b\f\u001c\f\u000b\n\r\u001b\f\u000b\n\t\f\u001b\f\f\f\u000b\f\u0013\u000b\u000b\f\n\f\n\n\f\n\f\u000b\u0015\f\r\r\f\f\b\b\f\f\r\r\f\u0014\f\n\t\r\f\n\n\f\r\n\u000b\r\u0013\u000b\n\b\n\r\f\f\r\n\t\u000b\f\r\u0012\u000b\u000b\n\u000b\r\u0002\r\f\u000b\u000b\f\f\f\r\u0011\f\u000b\u000b\f\u0005\r\f\f\r\u000b\f\u0010\f\f\f\f\b\r\u000b\f\u0011\f\u000b\f\b\u000b\t\f\u0013\t\u000b\b\f\u000b\f\u0013\b\u000b\b\r\f\f\r\u0012\n\f\b\u000b\n\u000b\f\f\u0010\r\f\f\b\f\t\n\u000b\f\u000f\r\u000b\n\r\u001c\f\n\t\f\u001b\f\u000b\u000b\f\f\u001b\n\f\r\f\n\u0012\u000b\u000b\f\n\f\n\n\f\n\f\u000b\u0015\f\r\r\f\f\b\b\f\f\r\r\f\u0014\f\n\t\r\f\n\n\f\r\n\u000b\r\u0013\u000b\n\n\f\r\f\f\r\n\t\u000b\f\u0012\r\u000b\u000b\n\u000b\r\u0002\r\f\u000b\u000b\f\f\r\u0011\f\u000b\u000b\u000b\f\u0005\f\f\f\f\f\u0011\f\f\u000b\f\b\r\f\u000b\u0010\f\u000b\f\n\u000b\f\f\u0010\u000b\t\u000b\t\f\t\u000b\u0012\u000b\f\t\u000b\n\f\u0012\u000b\n\u000b\b\f\u000b\u0013\r\f\f\b\r\f\f\r\u0010\r\u000b\n\r\b\u000b\n\u000b\f\f\u000f\f\n\t\f\b\f\t\n\u000b\f\u000e\f\u000b\u000b\f\f\u001b\u000b\f\r\f\u000b\u001b\t\u0003\t\u0011\u000b\u000b\f\n\f\n\n\f\n\f\u000b\u0015\f\r\r\f\f\b\b\f\f\r\r\f\u0013\r\n\n\r\f\n\n\f\r\n\u000b\u0013\f\n\t\n\r\f\f\r\n\t\n\r\u0011\r\f\u000b\n\n\u000b\r\u0002\r\f\n\u000b\u000b\f\u0011\f\f\u000b\u000b\f\f\u0004\f\u000b\u000b\f\f\u0010\r\f\f\f\f\u0007\f\f\f\f\f\u000f\f\f\f\n\f\f\u000b\u000b\u0010\u000b\u000b\u000b\f\n\f\u0011\n\u000b\t\u000b\n\f\u0012\u000b\n\u000b\b\n\b\u000b\u0012\r\f\f\b\u000b\t\u0012\r\u000b\n\r\b\f\u000b\u0012\f\n\t\f\b\r\f\f\r\u000f\f\u000b\u000b\f\f\b\u000b\n\u000b\f\f\u000e\n\f\r\f\n\b\f\t\n\u000b\f\u0012\u000b\u000b\f\n\f\n\n\f\n\f\u000b\u0015\f\r\r\f\f\b\b\f\f\r\r\f\u0013\r\u000b\n\r\f\n\n\f\r\u000b\n\f\u0012\r\f\u000b\t\n\r\f\f\r\f\t\t\u000b\u0011\r\f\f\f\u000b\u000b\f\r\u0002\r\u000b\n\u000b\u000b\u0011\f\n\u000b\f\f\u0006\f\u000b\u000b\f\u0012\f\b\u000b\b\f\u000b\f\f\u0012\u000b\n\u000b\b\f\u000b\f\u0011\r\f\u000b\f\b\u000b\n\u0012\f\u000b\n\r\b\n\u000b\u000b\u0010\f\u000b\n\t\f\b\u000b\u0007\u000b\u0010\u000b\f\f\u000b\u000b\b\f\t\u000b\u001d\f\u000b\f\r\u001c\r\n\u000b\f\u001c\f\t\n\u000b\f\u001b\f\u000b\f\f\f\u0007\u000e\f\u000b\u000b\f\u0014\f\u000b\f\u0004\f\u000b\t\n\u000b\f\u0004\f\u000b\f\u000e\u000b\n\u0003\u000b\n\u0006\b\n\u000b\u0003\n\u000b\u0011\f\u000b\f\r\r\r\n\n\r\r\r\f\u000b\f\u0013\r\r\f\u000b\r\u000b\u000b\r\u000b\f\r\r\u0011\f\n\f\r\u000b\f\n\f\u0005\u0005\f\n\f\u000b\r\f\n\f\f\f\u000b\n\f\f\t\r\u000b\n\f\f\n\u000b\r\t\f\f\n\u000b\f\u0007\f\u000b\n\t\u000b\u000b\b\f\f\n\fD\n\f\f\b\u000b\u000b\t\n\u000b\f\u0004\u000b\n\u000b\f\f\f\n\u000b\f\tFG\t\f\u000b\n\f\f\f\u000b\n\u000b\u0003\f\t\f\u0003\f\u000b\u000b\t\u000b\f\u0006\u0006\f\u000b\t\u000b\u000b\f\u0003\f\t\f\u0002\u000b\n\t\n\u000b\u0004D\fFDG\f\f\n\f\n\f\r\u0004\u000b\n\t\n\u000b\u0002\u000b\n\u000b\n\u0007\t\u0004\rIGDFH\n\tD\rD\u0003\t\u0007\n\u000b\n\u000b\u0002\f\n\u0007\u000b\b\u0007\u0004\u000b\n\b\f\t\t\f\b\n\u000b\u0004\u0007\b\u000b\u0007\n\f\u0003\u000b\u0007\b\u0001\b\b\u0002D\r\r\f\u000b\nD\u000b\f\r\r\f\u0002\b\b\u0001\b\u0007\u000b\u0005\t\u0007\u0002\t\u0001\f\u000b\n\u000b\r\f\u000b\u000b\f\r\u000b\n\u000b\f\u0001\t\u0002\u0007\t\u0007\b\n\u0002\f\u000b\n\t\n\u000b\r\f\f\r\u000b\n\t\n\u000b\f\u0002\n\b\t\t\u0001\r\u000b\u000b\u000b\n\u000b\f\r\u0002\r\f\u000b\n\u000b\u000b\u000b\r\u0001\t\f\f\r\r\f\u000b\r\u0006\r\u000b\f\r\r\f\u000f\u000b\f\f\u0003D\u0007\f\u000b\u000b\u000f\f\n\f\u000b\u000b\n\f\u0010\f\u000b\f\t\f\n\f\u0011\r\r\f\t\f\u000b\f\u0010\f\f\f\n\f\r\r\u000f\u000b\f\u000b\r\n\r\f\f\u000e\u000b\n\f\n\u000b\n\r\u000b\f\u000b\r\n\f\r\f\n\bF\u0001\u000b\n\f\n\u000b\u0012F\b\n\f\r\f\n\b\u000e\n\u0019\f\n\u000b\f\u0002\u000b\n\u0003\f\f\n\u0006\u000f\f\u000b\n\n\u000b\u000b\f\u0001\f\u000b\u0002\f\u000b\n\u000b\n\u0007\r\u000b\t\b\t\t\u000b\u000b\f\u0001\u000b\u0002\u000b\n\u000b\t\t\n\f\t\u0007\u0007\u000b\t\b\n\u000b\t\n\u000b\u000b\f\f\u000b\t\n\u000b\u000b\b\u0007\b\u000b\n\n\n\f\u0001\n\n\f\nF\r\u000b\u000b\n\t\n\u0002\b\u0007\u000b\f\u0002\u000b\u000b\b\u000b\n\f\f\u000b\u000b\t\f\b\u0007\t\u0004\f\f\n\n\u000b\n\f\u000b\n\u000b\b\f\n\t\b\u0007\f\u000bFDH\u000b\f\f\n\u000b\n\f\u000b\u000eF\u0004\f\u000bFD\r\n\u000b\f\f\u000b\f\n\u0013\n\t\fGI\rH\u000b\f\f\f\u000b\n\u000b\u0010\f\u000b\r\u000b\u000b\n\n\f\f\u000bG\u0002\u000b\f\n\u000e\r\f\u000b\u000b\f\f\u000b\t\n\u000b\b\f\u0003\f\n\f\u000bD\u000b\n\b\t\u000b\r\n\n\f\f\u000b\f\u0003\u000b\n\t\n\u000b\n\f\u000b\n\t\n\u000b\f\r\u000b\r\u000b\n\u000b\u000b\u0003\u000b\n\u000b\n\u0007\t\t\r\r\n\u000b\u000b\f\r\f\r\f\n\b\n\u000b\u0003\f\n\u0007\u000b\b\u0007\t\f\f\f\f\u0005\f\u000b\t\u000b\f\u0004\u000b\u0007\b\u0001\b\b\b\r\f\u000b\u0006\r\f\n\u000b\f\u0005\t\u0007\u0002\t\t\f\n\f\u0002F\u0003\r\u000b\f\r\u0006\b\n\u000b\r\u000b\u000b\u0007\r\f\f\u0007\t\f\f\f\b\u000b\f\r\u0012\r\f\r\b\r\u000b\f\u0012\f\f\n\f\r\u0011\u000b\f\u000b\r\t\f\u000b\u0010\u000b\n\f\n\u000b\u0002D\u0003GH\r\u000b\f\u000bG\fF\u0001\n\f\r\f\nFF\u0006\u000b\n\f\n\u000b\u0001G\u0019\n\f\r\f\n\f\u0014\u000b\n\u001e\n\u001d\u000b\u0001\u000b\u001a\f\u000b\n\f\u000b\u0005H\u0013\f\u000b\t\f\f\u0001\t\u000b\u000b\u0012\u000b\f\f\u000b\f\f\b\f\u000b\n\n\u0004\u000eH\f\u000b\t\t\u000b\f\u000b\u000b\t\b\fD\u0004\r\u000b\n\n\n\b\u000b\u0001\f\fF\u000b\u000b\u000b\n\u000b\u0005\f\t\u0007\u0007\u000b\t\n\u0002\f\n\tDF\f\r\u000b\u000bH\r\b\u0007\b\u000b\n\n\f\u0003\u000b\f\u000bHD\n\f\n\u000b\f\t\n\u0002\b\u0007\u000b\u0002\f\u000b\t\u000b\fGF\n\u000b\t\n\u000fH\u0007\t\u0002\f\u000b\t\u0006\u000b\f\n\n\u000b\r\u000b\u000b\u000b\r\t\b\u0004\u000b\n\n\u0007\u000b\f\u000b\f\f\r\u000b\n\u000b\u0013\f\u000b\n\t\u000b\f\f\u000b\u000b\f\f\f\u0012\r\f\n\n\f\u0001\u000b\n\b\u000b\f\f\u000b\u000b\u0013\f\u000b\u000b\f\u0001\f\u000b\n\t\u000b\u000b\f\u0007\t\u0011\u000b\u000b\r\u000b\u0003\f\u000b\u000b\u000b\f\f\b\u0007\u0010\f\n\f\u0004\f\f\u000b\f\u000b\f\u000b\u0001\b\b\u000e\f\u000b\f\u0003\f\f\f\f\u0003\u000b\u0007\u0002\t\r\f\f\f\u0003\f\u000b\f\u0006\b\n\u0006H\u0005GI\u000b\f\u000b\r\u0001EG\f\rHDCADFG\t\tIH\u0002\u000b\n\f\n\u000bIH\u0002\u000b\u000b\u0006DCF\f\n\f\r\f\n\u0004\r\u000b\f\u000b\u001c\u000b\n\f\n\u000b\u001b\n\f\r\f\n"
  },
  {
    "path": "bin/standard/xcom1/alienDeployments.rul",
    "content": "alienDeployments:\n  - type: STR_CRAFT_DEPLOYMENT_PREVIEW\n    isHidden: true\n    width: 10\n    length: 10\n    height: 8\n    terrains:\n      - CULTA\n    script: STR_CRAFT_DEPLOYMENT_PREVIEW\n  - type: STR_SMALL_SCOUT\n    data:\n      - alienRank: 5\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n            - STR_PLASMA_PISTOL_CLIP\n            - STR_MIND_PROBE\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_MIND_PROBE\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_MIND_PROBE\n    width: 40\n    length: 40\n    height: 4\n  - type: STR_MEDIUM_SCOUT\n    data:\n      - alienRank: 5\n        lowQty: 2\n        highQty: 4\n        dQty: 2\n        percentageOutsideUfo: 60\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n      - alienRank: 4\n        lowQty: 1\n        highQty: 2\n        dQty: 1\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n            - STR_MIND_PROBE\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n    width: 40\n    length: 40\n    height: 4\n  - type: STR_LARGE_SCOUT\n    data:\n      - alienRank: 5\n        lowQty: 1\n        highQty: 3\n        dQty: 5\n        percentageOutsideUfo: 65\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_HEAVY_PLASMA_CLIP\n      - alienRank: 4\n        lowQty: 1\n        highQty: 1\n        dQty: 1\n        percentageOutsideUfo: 25\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n            - STR_MIND_PROBE\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n      - alienRank: 2\n        lowQty: 1\n        highQty: 2\n        dQty: 1\n        percentageOutsideUfo: 35\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n            - STR_MIND_PROBE\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_MIND_PROBE\n          -\n            - STR_SMALL_LAUNCHER\n            - STR_STUN_BOMB\n            - STR_STUN_BOMB\n            - STR_STUN_BOMB\n    width: 50\n    length: 50\n    height: 4\n  - type: STR_HARVESTER\n    data:\n      - alienRank: 5\n        lowQty: 5\n        highQty: 9\n        dQty: 4\n        percentageOutsideUfo: 70\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n      - alienRank: 4\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_ALIEN_GRENADE\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_HEAVY_PLASMA_CLIP\n      - alienRank: 3\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SMALL_LAUNCHER\n            - STR_STUN_BOMB\n            - STR_STUN_BOMB\n            - STR_STUN_BOMB\n          -\n            - STR_SMALL_LAUNCHER\n            - STR_STUN_BOMB\n            - STR_STUN_BOMB\n            - STR_STUN_BOMB\n          -\n            - STR_SMALL_LAUNCHER\n            - STR_STUN_BOMB\n            - STR_STUN_BOMB\n            - STR_STUN_BOMB\n            - STR_STUN_BOMB\n      - alienRank: 2\n        lowQty: 2\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 30\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n      - alienRank: 1\n        lowQty: 1\n        highQty: 1\n        dQty: 1\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_ALIEN_GRENADE\n            - STR_HEAVY_PLASMA_CLIP\n    width: 50\n    length: 50\n    height: 4\n  - type: STR_ABDUCTOR\n    data:\n      - alienRank: 5\n        lowQty: 3\n        highQty: 5\n        dQty: 4\n        percentageOutsideUfo: 70\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_HEAVY_PLASMA_CLIP\n      - alienRank: 4\n        lowQty: 1\n        highQty: 1\n        dQty: 1\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_HEAVY_PLASMA_CLIP\n      - alienRank: 3\n        lowQty: 2\n        highQty: 4\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_HEAVY_PLASMA_CLIP\n      - alienRank: 2\n        lowQty: 2\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 30\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_HEAVY_PLASMA_CLIP\n      - alienRank: 1\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_HEAVY_PLASMA_CLIP\n    width: 50\n    length: 50\n    height: 4\n  - type: STR_TERROR_SHIP\n    data:\n      - alienRank: 5\n        lowQty: 4\n        highQty: 6\n        dQty: 1\n        percentageOutsideUfo: 70\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_HEAVY_PLASMA_CLIP\n      - alienRank: 4\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_HEAVY_PLASMA_CLIP\n      - alienRank: 3\n        lowQty: 1\n        highQty: 1\n        dQty: 1\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_SMALL_LAUNCHER\n            - STR_STUN_BOMB\n            - STR_STUN_BOMB\n            - STR_STUN_BOMB\n      - alienRank: 2\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_HEAVY_PLASMA_CLIP\n      - alienRank: 1\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_HEAVY_PLASMA_CLIP\n      - alienRank: 6\n        lowQty: 1\n        highQty: 3\n        dQty: 2\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 7\n        lowQty: 1\n        highQty: 3\n        dQty: 2\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n    width: 50\n    length: 50\n    height: 4\n  - type: STR_BATTLESHIP\n    data:\n      - alienRank: 5\n        lowQty: 4\n        highQty: 8\n        dQty: 4\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_HEAVY_PLASMA_CLIP\n      - alienRank: 4\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n      - alienRank: 3\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_SMALL_LAUNCHER\n            - STR_STUN_BOMB\n            - STR_STUN_BOMB\n            - STR_STUN_BOMB\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n      - alienRank: 2\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_BLASTER_LAUNCHER\n            - STR_BLASTER_BOMB\n            - STR_BLASTER_BOMB\n            - STR_BLASTER_BOMB\n            - STR_BLASTER_BOMB\n      - alienRank: 1\n        lowQty: 1\n        highQty: 3\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n          -\n            - STR_BLASTER_LAUNCHER\n            - STR_BLASTER_BOMB\n            - STR_BLASTER_BOMB\n            - STR_BLASTER_BOMB\n            - STR_BLASTER_BOMB\n      - alienRank: 0\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_ALIEN_GRENADE\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_ALIEN_GRENADE\n          -\n            - STR_BLASTER_LAUNCHER\n            - STR_BLASTER_BOMB\n            - STR_BLASTER_BOMB\n            - STR_BLASTER_BOMB\n            - STR_BLASTER_BOMB\n      - alienRank: 6\n        lowQty: 0\n        highQty: 2\n        dQty: 1\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 7\n        lowQty: 0\n        highQty: 2\n        dQty: 1\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n    width: 50\n    length: 50\n    height: 4\n  - type: STR_SUPPLY_SHIP\n    data:\n      - alienRank: 5\n        lowQty: 5\n        highQty: 7\n        dQty: 6\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n      - alienRank: 4\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n      - alienRank: 3\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_SMALL_LAUNCHER\n            - STR_STUN_BOMB\n            - STR_STUN_BOMB\n            - STR_STUN_BOMB\n      - alienRank: 2\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n      - alienRank: 1\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n    width: 50\n    length: 50\n    height: 4\n  - type: STR_TERROR_MISSION\n    data:\n      - alienRank: 5\n        lowQty: 4\n        highQty: 6\n        dQty: 1\n        percentageOutsideUfo: 70\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_HEAVY_PLASMA_CLIP\n      - alienRank: 4\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_HEAVY_PLASMA_CLIP\n      - alienRank: 3\n        lowQty: 1\n        highQty: 1\n        dQty: 1\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_SMALL_LAUNCHER\n            - STR_STUN_BOMB\n            - STR_STUN_BOMB\n            - STR_STUN_BOMB\n      - alienRank: 2\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_HEAVY_PLASMA_CLIP\n      - alienRank: 1\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_HEAVY_PLASMA_CLIP\n      - alienRank: 6\n        lowQty: 1\n        highQty: 3\n        dQty: 2\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 7\n        lowQty: 1\n        highQty: 3\n        dQty: 2\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n    width: 50\n    length: 50\n    height: 4\n    civilians: 16\n    terrains:\n      - URBAN\n    alert: STR_ALIENS_TERRORISE\n    alertBackground: BACK03.SCR\n    briefing:\n      palette: 2\n      music: GMENBASE\n    markerName: STR_TERROR_SITE\n    duration: [4, 10]\n    despawnPenalty: 1000\n  - type: STR_ALIEN_BASE_ASSAULT\n    data:\n      - alienRank: 6\n        lowQty: 1\n        highQty: 3\n        dQty: 1\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 7\n        lowQty: 0\n        highQty: 2\n        dQty: 1\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 5\n        lowQty: 5\n        highQty: 7\n        dQty: 4\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n      - alienRank: 4\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n      - alienRank: 3\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_SMALL_LAUNCHER\n            - STR_STUN_BOMB\n            - STR_STUN_BOMB\n            - STR_STUN_BOMB\n      - alienRank: 2\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_BLASTER_LAUNCHER\n            - STR_BLASTER_BOMB\n            - STR_BLASTER_BOMB\n            - STR_BLASTER_BOMB\n            - STR_BLASTER_BOMB\n      - alienRank: 1\n        lowQty: 2\n        highQty: 4\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n          -\n            - STR_BLASTER_LAUNCHER\n            - STR_BLASTER_BOMB\n            - STR_BLASTER_BOMB\n            - STR_BLASTER_BOMB\n            - STR_BLASTER_BOMB\n      - alienRank: 0\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n    width: 50\n    length: 50\n    height: 2\n    terrains:\n      - UBASE\n    shade: 15\n    script: ALIENBASE\n    briefing:\n      textOffset: -16\n      background: BACK01.SCR\n      showTarget: false\n    objectiveType: 3\n    markerName: STR_ALIEN_BASE\n    markerIcon: 7\n    genMission:\n      STR_ALIEN_SUPPLY: 100\n    genMissionFreq: 6\n    alienBase: true    # this is only to tell new battle mode what to do with this deployment\n    objectiveComplete: [STR_ALIEN_BASE_CONTROL_DESTROYED, 500]\n    objectivePopup: STR_CONTROL_CENTER_DESTROYED\n    points: 5\n  - type: STR_BASE_DEFENSE\n    data:\n      - alienRank: 5\n        lowQty: 4\n        highQty: 8\n        dQty: 4\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_HEAVY_PLASMA_CLIP\n      - alienRank: 4\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n      - alienRank: 3\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_SMALL_LAUNCHER\n            - STR_STUN_BOMB\n            - STR_STUN_BOMB\n            - STR_STUN_BOMB\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n      - alienRank: 2\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_BLASTER_LAUNCHER\n            - STR_BLASTER_BOMB\n            - STR_BLASTER_BOMB\n            - STR_BLASTER_BOMB\n            - STR_BLASTER_BOMB\n      - alienRank: 1\n        lowQty: 1\n        highQty: 3\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n          -\n            - STR_BLASTER_LAUNCHER\n            - STR_BLASTER_BOMB\n            - STR_BLASTER_BOMB\n            - STR_BLASTER_BOMB\n            - STR_BLASTER_BOMB\n      - alienRank: 0\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_ALIEN_GRENADE\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_ALIEN_GRENADE\n          -\n            - STR_BLASTER_LAUNCHER\n            - STR_BLASTER_BOMB\n            - STR_BLASTER_BOMB\n            - STR_BLASTER_BOMB\n            - STR_BLASTER_BOMB\n      - alienRank: 6\n        lowQty: 0\n        highQty: 2\n        dQty: 1\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 7\n        lowQty: 0\n        highQty: 2\n        dQty: 1\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n    width: 60\n    length: 60\n    height: 2\n    terrains:\n      - XBASE\n    shade: 5\n    briefing:\n      palette: 0\n      background: BACK01.SCR\n      music: GMENBASE\n  - type: STR_MARS_CYDONIA_LANDING\n    data:\n      - alienRank: 5\n        lowQty: 4\n        highQty: 6\n        dQty: 0\n        percentageOutsideUfo: 60\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n      - alienRank: 1\n        lowQty: 3\n        highQty: 5\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n      - alienRank: 0\n        lowQty: 3\n        highQty: 5\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_PLASMA_PISTOL\n            - STR_PLASMA_PISTOL_CLIP\n          -\n            - STR_PLASMA_RIFLE\n            - STR_PLASMA_RIFLE_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n      - alienRank: 6\n        lowQty: 2\n        highQty: 4\n        dQty: 0\n        percentageOutsideUfo: 100\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n    width: 50\n    length: 50\n    height: 4\n    terrains:\n      - MARS\n    shade: 15\n    race: STR_SECTOID\n    nextStage: STR_MARS_THE_FINAL_ASSAULT\n    finalDestination: true\n    loseCutscene: loseGame\n    abortCutscene: loseGame\n    briefing:\n      textOffset: -16\n      palette: 6\n      music: GMNEWMAR\n      showTarget: false\n  - type: STR_MARS_THE_FINAL_ASSAULT\n    data:\n      - alienRank: 0\n        lowQty: 2\n        highQty: 4\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_HEAVY_PLASMA_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_HEAVY_PLASMA_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_HEAVY_PLASMA_CLIP\n      - alienRank: 1\n        lowQty: 1\n        highQty: 3\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_HEAVY_PLASMA_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_HEAVY_PLASMA_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_HEAVY_PLASMA_CLIP\n      - alienRank: 2\n        lowQty: 3\n        highQty: 5\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_BLASTER_LAUNCHER\n            - STR_BLASTER_BOMB\n            - STR_BLASTER_BOMB\n            - STR_BLASTER_BOMB\n            - STR_BLASTER_BOMB\n          -\n            - STR_BLASTER_LAUNCHER\n            - STR_BLASTER_BOMB\n            - STR_BLASTER_BOMB\n            - STR_BLASTER_BOMB\n            - STR_BLASTER_BOMB\n          -\n            - STR_BLASTER_LAUNCHER\n            - STR_BLASTER_BOMB\n            - STR_BLASTER_BOMB\n            - STR_BLASTER_BOMB\n            - STR_BLASTER_BOMB\n      - alienRank: 3\n        lowQty: 3\n        highQty: 5\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_HEAVY_PLASMA_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_HEAVY_PLASMA_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_HEAVY_PLASMA_CLIP\n      - alienRank: 4\n        lowQty: 3\n        highQty: 5\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_HEAVY_PLASMA_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_HEAVY_PLASMA_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_HEAVY_PLASMA_CLIP\n      - alienRank: 5\n        lowQty: 3\n        highQty: 5\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_HEAVY_PLASMA_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_HEAVY_PLASMA_CLIP\n          -\n            - STR_HEAVY_PLASMA\n            - STR_HEAVY_PLASMA_CLIP\n            - STR_ALIEN_GRENADE\n            - STR_HEAVY_PLASMA_CLIP\n      - alienRank: 6\n        lowQty: 1\n        highQty: 4\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n    width: 60\n    length: 60\n    height: 2\n    terrains:\n      - UBASE\n    shade: 5\n    race: STR_MIXED\n    winCutscene: winGame\n    loseCutscene: loseGame\n    abortCutscene: loseGame\n    briefing:\n      textOffset: -16\n      palette: 6\n      music: GMNEWMAR\n      showTarget: false\n      showCraft: false\n      background: BACK01.SCR\n    script: BOSSBATTLE\n    objectiveType: 14\n    objectivesRequired: 1\n"
  },
  {
    "path": "bin/standard/xcom1/alienItemLevels.rul",
    "content": "alienItemLevels:\n  - [0, 0, 0, 0, 0, 0, 0, 1, 1, 2]\n  - [0, 0, 0, 0, 0, 1, 1, 1, 2, 2]\n  - [0, 0, 0, 1, 1, 1, 1, 2, 2, 2]\n  - [0, 0, 1, 1, 1, 1, 2, 2, 2, 2]\n  - [0, 0, 1, 1, 1, 2, 2, 2, 2, 2]\n  - [0, 1, 1, 1, 2, 2, 2, 2, 2, 2]\n  - [1, 1, 1, 2, 2, 2, 2, 2, 2, 2]\n  - [1, 1, 1, 2, 2, 2, 2, 2, 2, 2]\n  - [1, 1, 2, 2, 2, 2, 2, 2, 2, 2]\n  - [2, 2, 2, 2, 2, 2, 2, 2, 2, 2]"
  },
  {
    "path": "bin/standard/xcom1/alienMissions.rul",
    "content": "alienMissions:\n  - type: STR_ALIEN_RESEARCH\n    points: 0\n    raceWeights:\n      0:\n        STR_SECTOID: 70\n        STR_SNAKEMAN: 10\n        STR_FLOATER: 20\n      1:\n        STR_SECTOID: 60\n        STR_SNAKEMAN: 10\n        STR_FLOATER: 30\n      3:\n        STR_SECTOID: 30\n        STR_SNAKEMAN: 10\n        STR_MUTON: 30\n        STR_FLOATER: 30\n      6:\n        STR_SECTOID: 20\n        STR_SNAKEMAN: 10\n        STR_MUTON: 40\n        STR_FLOATER: 30\n      9:\n        STR_SECTOID: 30\n        STR_SNAKEMAN: 10\n        STR_MUTON: 30\n        STR_FLOATER: 30\n    waves:\n      - ufo: STR_SMALL_SCOUT\n        count: 1\n        trajectory: P0\n        timer: 9000\n      - ufo: STR_MEDIUM_SCOUT\n        count: 1\n        trajectory: P2\n        timer: 7800\n      - ufo: STR_LARGE_SCOUT\n        count: 2\n        trajectory: P4\n        timer: 9000\n  - type: STR_ALIEN_HARVEST\n    points: 30\n    raceWeights:\n      0:\n        STR_SECTOID: 50\n        STR_SNAKEMAN: 20\n        STR_FLOATER: 30\n      1:\n        STR_SECTOID: 50\n        STR_FLOATER: 50\n      3:\n        STR_SECTOID: 30\n        STR_MUTON: 30\n        STR_FLOATER: 40\n      6:\n        STR_SECTOID: 10\n        STR_MUTON: 40\n        STR_FLOATER: 50\n      9:\n        STR_SECTOID: 30\n        STR_MUTON: 30\n        STR_FLOATER: 40\n    waves:\n      - ufo: STR_SMALL_SCOUT\n        count: 1\n        trajectory: P0\n        timer: 7800\n      - ufo: STR_SMALL_SCOUT\n        count: 1\n        trajectory: P2\n        timer: 7800\n      - ufo: STR_MEDIUM_SCOUT\n        count: 1\n        trajectory: P2\n        timer: 6000\n      - ufo: STR_LARGE_SCOUT\n        count: 1\n        trajectory: P0\n        timer: 7800\n      - ufo: STR_LARGE_SCOUT\n        count: 1\n        trajectory: P3\n        timer: 9000\n      - ufo: STR_HARVESTER\n        count: 1\n        trajectory: P4\n        timer: 3000\n      - ufo: STR_HARVESTER\n        count: 1\n        trajectory: P4\n        timer: 750\n      - ufo: STR_BATTLESHIP\n        count: 1\n        trajectory: P2\n        timer: 1500\n  - type: STR_ALIEN_ABDUCTION\n    points: 50\n    raceWeights:\n      0:\n        STR_SECTOID: 60\n        STR_FLOATER: 40\n      1:\n        STR_SECTOID: 40\n        STR_FLOATER: 60\n      3:\n        STR_SECTOID: 50\n        STR_FLOATER: 50\n      6:\n        STR_SECTOID: 30\n        STR_FLOATER: 70\n      9:\n        STR_SECTOID: 50\n        STR_FLOATER: 50\n    waves:\n      - ufo: STR_SMALL_SCOUT\n        count: 1\n        trajectory: P0\n        timer: 15000\n      - ufo: STR_MEDIUM_SCOUT\n        count: 1\n        trajectory: P1\n        timer: 18000\n      - ufo: STR_LARGE_SCOUT\n        count: 1\n        trajectory: P3\n        timer: 9000\n      - ufo: STR_ABDUCTOR\n        count: 1\n        trajectory: P3\n        timer: 9000\n      - ufo: STR_ABDUCTOR\n        count: 2\n        trajectory: P4\n        timer: 60\n  - type: STR_ALIEN_INFILTRATION\n    points: 150 #Pact score only awarded on month end\n    objective: 1\n    siteType: STR_ALIEN_BASE_ASSAULT\n    spawnZone: 4 #Mission zone for alien bases\n    raceWeights:\n      0:\n        STR_SECTOID: 60\n        STR_SNAKEMAN: 20\n        STR_FLOATER: 20\n      1:\n        STR_SECTOID: 50\n        STR_SNAKEMAN: 20\n        STR_FLOATER: 30\n      3:\n        STR_SECTOID: 20\n        STR_SNAKEMAN: 20\n        STR_MUTON: 50\n        STR_FLOATER: 10\n      6:\n        STR_SECTOID: 10\n        STR_SNAKEMAN: 10\n        STR_ETHEREAL: 40\n        STR_MUTON: 30\n        STR_FLOATER: 10\n      9:\n        STR_SECTOID: 20\n        STR_SNAKEMAN: 20\n        STR_ETHEREAL: 10\n        STR_MUTON: 40\n        STR_FLOATER: 10\n    waves:\n      - ufo: STR_SMALL_SCOUT\n        count: 1\n        trajectory: P0\n        timer: 16500\n      - ufo: STR_MEDIUM_SCOUT\n        count: 1\n        trajectory: P1\n        timer: 15000\n      - ufo: STR_MEDIUM_SCOUT\n        count: 1\n        trajectory: P6\n        timer: 13800\n      - ufo: STR_LARGE_SCOUT\n        count: 1\n        trajectory: P7\n        timer: 9000\n      - ufo: STR_LARGE_SCOUT\n        count: 1\n        trajectory: P7\n        timer: 60\n      - ufo: STR_TERROR_SHIP\n        count: 1\n        trajectory: P7\n        timer: 60\n      - ufo: STR_SUPPLY_SHIP\n        count: 1\n        trajectory: P7\n        timer: 60\n      - ufo: STR_BATTLESHIP\n        count: 2\n        trajectory: P7\n        timer: 60\n  - type: STR_ALIEN_BASE\n    points: 50\n    objective: 2\n    siteType: STR_ALIEN_BASE_ASSAULT\n    spawnZone: 4 #Mission zone for alien bases\n    raceWeights:\n      0:\n        STR_SECTOID: 30\n        STR_SNAKEMAN: 20\n        STR_FLOATER: 50\n      1:\n        STR_SECTOID: 40\n        STR_SNAKEMAN: 20\n        STR_FLOATER: 40\n      3:\n        STR_SECTOID: 10\n        STR_SNAKEMAN: 40\n        STR_MUTON: 30\n        STR_FLOATER: 20\n      6:\n        STR_SECTOID: 10\n        STR_SNAKEMAN: 40\n        STR_ETHEREAL: 10\n        STR_MUTON: 20\n        STR_FLOATER: 20\n      9:\n        STR_SECTOID: 10\n        STR_SNAKEMAN: 20\n        STR_ETHEREAL: 40\n        STR_MUTON: 20\n        STR_FLOATER: 10\n    waves:\n      - ufo: STR_SMALL_SCOUT\n        count: 1\n        trajectory: P1\n        timer: 13500\n      - ufo: STR_MEDIUM_SCOUT\n        count: 1\n        trajectory: P5\n        timer: 15000\n      - ufo: STR_LARGE_SCOUT\n        count: 1\n        trajectory: P5\n        timer: 60\n      - ufo: STR_SUPPLY_SHIP\n        count: 2\n        trajectory: P5\n        timer: 60\n      - ufo: STR_BATTLESHIP\n        count: 1\n        trajectory: P6\n        timer: 60\n  - type: STR_ALIEN_TERROR\n    points: 10\n    objective: 3\n    spawnZone: 3 #Mission zone for terror missions\n    raceWeights:\n      0:\n        STR_SECTOID: 30\n        STR_FLOATER: 70\n      1:\n        STR_SECTOID: 60\n        STR_FLOATER: 40\n      3:\n        STR_SECTOID: 20\n        STR_SNAKEMAN: 60\n        STR_FLOATER: 20\n      6:\n        STR_SECTOID: 10\n        STR_SNAKEMAN: 20\n        STR_ETHEREAL: 40\n        STR_MUTON: 20\n        STR_FLOATER: 10\n      9:\n        STR_SECTOID: 20\n        STR_SNAKEMAN: 30\n        STR_ETHEREAL: 20\n        STR_MUTON: 20\n        STR_FLOATER: 10\n    waves:\n      - ufo: STR_MEDIUM_SCOUT\n        count: 1\n        trajectory: P1\n        timer: 15000\n      - ufo: STR_LARGE_SCOUT\n        count: 1\n        trajectory: P1\n        timer: 9600\n      - ufo: STR_TERROR_SHIP\n        count: 1\n        trajectory: P0\n        timer: 12000\n      - ufo: STR_TERROR_SHIP\n        count: 1\n        trajectory: P7\n        timer: 9000\n        objective: true\n  - type: STR_ALIEN_RETALIATION\n    points: 0\n    objective: 4\n    spawnUfo: STR_BATTLESHIP # Spawned for the final retaliation run\n    raceWeights: # In the case of a shootdown, race comes from the UFO that triggered the mission.\n      0:\n        STR_SECTOID: 20\n        STR_SNAKEMAN: 20\n        STR_ETHEREAL: 20\n        STR_MUTON: 20\n        STR_FLOATER: 20\n    waves:\n      - ufo: STR_SMALL_SCOUT\n        count: 1\n        trajectory: P8\n        timer: 3000\n      - ufo: STR_MEDIUM_SCOUT\n        count: 2\n        trajectory: P8\n        timer: 3000\n      - ufo: STR_LARGE_SCOUT\n        count: 3\n        trajectory: P8\n        timer: 3000\n      - ufo: STR_BATTLESHIP\n        count: 2\n        trajectory: P8\n        timer: 3000\n  - type: STR_ALIEN_SUPPLY\n    points: 0\n    objective: 5\n    raceWeights: {} #Special case, race comes from base.\n    waves:\n      - ufo: STR_SUPPLY_SHIP\n        count: 1\n        trajectory: P9\n        timer: 6000\n        objective: true"
  },
  {
    "path": "bin/standard/xcom1/alienRaces.rul",
    "content": "alienRaces:\n  - id: STR_SECTOID\n    members:\n      - STR_SECTOID_COMMANDER\n      - STR_SECTOID_LEADER\n      - STR_SECTOID_ENGINEER\n      - STR_SECTOID_MEDIC\n      - STR_SECTOID_NAVIGATOR\n      - STR_SECTOID_SOLDIER\n      - STR_CYBERDISC_TERRORIST\n      - STR_CYBERDISC_TERRORIST\n  - id: STR_SNAKEMAN\n    members:\n      - STR_SNAKEMAN_COMMANDER\n      - STR_SNAKEMAN_LEADER\n      - STR_SNAKEMAN_ENGINEER\n      - STR_SNAKEMAN_SOLDIER\n      - STR_SNAKEMAN_NAVIGATOR\n      - STR_SNAKEMAN_SOLDIER\n      - STR_CHRYSSALID_TERRORIST\n      - STR_CHRYSSALID_TERRORIST\n  - id: STR_ETHEREAL\n    members:\n      - STR_ETHEREAL_COMMANDER\n      - STR_ETHEREAL_LEADER\n      - STR_ETHEREAL_LEADER\n      - STR_ETHEREAL_LEADER\n      - STR_ETHEREAL_LEADER\n      - STR_ETHEREAL_SOLDIER\n      - STR_SECTOPOD_TERRORIST\n      - STR_SECTOPOD_TERRORIST\n  - id: STR_MUTON\n    members:\n      - STR_MUTON_SOLDIER\n      - STR_MUTON_SOLDIER\n      - STR_MUTON_ENGINEER\n      - STR_MUTON_SOLDIER\n      - STR_MUTON_NAVIGATOR\n      - STR_MUTON_SOLDIER\n      - STR_SILACOID_TERRORIST\n      - STR_CELATID_TERRORIST\n  - id: STR_FLOATER\n    members:\n      - STR_FLOATER_COMMANDER\n      - STR_FLOATER_LEADER\n      - STR_FLOATER_ENGINEER\n      - STR_FLOATER_MEDIC\n      - STR_FLOATER_NAVIGATOR\n      - STR_FLOATER_SOLDIER\n      - STR_REAPER_TERRORIST\n      - STR_REAPER_TERRORIST\n  - id: STR_MIXED\n    members:\n      - STR_ETHEREAL_SOLDIER\n      - STR_ETHEREAL_LEADER\n      - STR_ETHEREAL_COMMANDER\n      - STR_CHRYSSALID_TERRORIST\n      - STR_SILACOID_TERRORIST\n      - STR_CELATID_TERRORIST\n      - STR_SECTOPOD_TERRORIST\n      - STR_SECTOPOD_TERRORIST"
  },
  {
    "path": "bin/standard/xcom1/armors.rul",
    "content": "armors:\n  - type: STR_NONE_UC\n    spriteSheet: XCOM_0.PCK\n    spriteInv: MAN_0\n    spriteFaceGroup: 6\n    spriteFaceColor: [96, 96, 96, 96, 160, 160, 163, 163] #M0 F0 M1 F1 M2 F2 M3 F3\n    spriteHairGroup: 9\n    spriteHairColor: [144, 144, 164, 164, 245, 245, 166, 166] #M0 F0 M1 F1 M2 F2 M3 F3\n    storeItem: STR_NONE\n    corpseBattle:\n      - STR_CORPSE\n    frontArmor: 12\n    sideArmor: 8\n    rearArmor: 5\n    underArmor: 2\n    damageModifier:\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.2\n      - 1.6\n      - 1.0\n    loftempsSet: [ 3 ]\n  - type: STR_PERSONAL_ARMOR_UC\n    spriteSheet: XCOM_1.PCK\n    spriteInv: MAN_1\n    spriteFaceGroup: 6\n    spriteFaceColor: [96, 96, 96, 96, 160, 160, 163, 163] #M0 F0 M1 F1 M2 F2 M3 F3\n    spriteHairGroup: 9\n    spriteHairColor: [144, 144, 164, 164, 245, 245, 166, 166] #M0 F0 M1 F1 M2 F2 M3 F3\n    corpseBattle:\n      - STR_CORPSE_ARMOR\n    storeItem: STR_PERSONAL_ARMOR\n    frontArmor: 50\n    sideArmor: 40\n    rearArmor: 30\n    underArmor: 30\n    damageModifier:\n      - 1.0\n      - 1.0\n      - 0.8\n      - 1.0\n      - 1.0\n      - 1.0\n      - 0.9\n      - 1.0\n      - 1.1\n      - 1.0\n    loftempsSet: [ 3 ]\n  - type: STR_POWER_SUIT_UC\n    spriteSheet: XCOM_2.PCK\n    spriteInv: MAN_2\n    corpseBattle:\n      - STR_CORPSE_SUIT\n    storeItem: STR_POWER_SUIT\n    frontArmor: 100\n    sideArmor: 80\n    rearArmor: 70\n    underArmor: 60\n    damageModifier:\n      - 1.0\n      - 1.0\n      - 0.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 0.8\n      - 1.0\n      - 1.0\n      - 0.0\n    loftempsSet: [ 3 ]\n    forcedTorso: 1\n  - type: STR_FLYING_SUIT_UC\n    spriteSheet: XCOM_2.PCK\n    spriteInv: MAN_3\n    corpseBattle:\n      - STR_CORPSE_SUIT\n    storeItem: STR_FLYING_SUIT\n    frontArmor: 110\n    sideArmor: 90\n    rearArmor: 80\n    underArmor: 70\n    movementType: 1\n    damageModifier:\n      - 1.0\n      - 1.0\n      - 0.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 0.8\n      - 1.0\n      - 1.0\n      - 0.0\n    loftempsSet: [ 3 ]\n    forcedTorso: 2\n  - type: SECTOID_ARMOR0\n    spriteSheet: SECTOID.PCK\n    corpseBattle:\n      - STR_SECTOID_CORPSE\n    frontArmor: 4\n    sideArmor: 3\n    rearArmor: 2\n    underArmor: 2\n    damageModifier:\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.2\n      - 1.6\n      - 0.0\n    loftempsSet: [ 2 ]\n  - type: FLOATER_ARMOR0\n    spriteSheet: FLOATER.PCK\n    corpseBattle:\n      - STR_FLOATER_CORPSE\n    frontArmor: 8\n    sideArmor: 6\n    rearArmor: 4\n    underArmor: 12\n    drawingRoutine: 1\n    movementType: 1\n    damageModifier:\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.2\n      - 1.6\n      - 0.0\n    loftempsSet: [ 3 ]\n  - type: FLOATER_ARMOR1\n    spriteSheet: FLOATER.PCK\n    corpseBattle:\n      - STR_FLOATER_CORPSE\n    frontArmor: 16\n    sideArmor: 12\n    rearArmor: 8\n    underArmor: 12\n    drawingRoutine: 1\n    movementType: 1\n    damageModifier:\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.2\n      - 1.6\n      - 0.0\n    loftempsSet: [ 3 ]\n  - type: FLOATER_ARMOR2\n    spriteSheet: FLOATER.PCK\n    corpseBattle:\n      - STR_FLOATER_CORPSE\n    frontArmor: 24\n    sideArmor: 18\n    rearArmor: 12\n    underArmor: 16\n    drawingRoutine: 1\n    movementType: 1\n    damageModifier:\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.2\n      - 1.6\n      - 0.0\n    loftempsSet: [ 3 ]\n  - type: CYBERDISC_ARMOR\n    spriteSheet: CYBER.PCK\n    allowInv: false\n    corpseBattle:\n      - CYBERDISC_CORPSE_1\n      - CYBERDISC_CORPSE_2\n      - CYBERDISC_CORPSE_3\n      - CYBERDISC_CORPSE_4\n    corpseGeo: STR_CYBERDISC_CORPSE\n    frontArmor: 34\n    sideArmor: 34\n    rearArmor: 34\n    underArmor: 34\n    drawingRoutine: 3\n    constantAnimation: true\n    movementType: 1\n    size: 2\n    damageModifier:\n      - 1.0\n      - 0.8\n      - 1.0\n      - 0.6\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 0.0\n    loftempsSet: [ 92, 89, 90, 91 ]\n  - type: REAPER_ARMOR\n    spriteSheet: X_REAP.PCK\n    allowInv: false\n    corpseBattle:\n      - REAPER_CORPSE_1\n      - REAPER_CORPSE_2\n      - REAPER_CORPSE_3\n      - REAPER_CORPSE_4\n    corpseGeo: STR_REAPER_CORPSE\n    frontArmor: 28\n    sideArmor: 28\n    rearArmor: 28\n    underArmor: 4\n    drawingRoutine: 5\n    size: 2\n    damageModifier:\n      - 1.0\n      - 1.0\n      - 1.7\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 0.0\n    loftempsSet: [ 92, 89, 90, 91 ]\n  - type: SECTOPOD_ARMOR\n    spriteSheet: X_ROB.PCK\n    allowInv: false\n    corpseBattle:\n      - SECTOPOD_CORPSE_1\n      - SECTOPOD_CORPSE_2\n      - SECTOPOD_CORPSE_3\n      - SECTOPOD_CORPSE_4\n    corpseGeo: STR_SECTOPOD_CORPSE\n    frontArmor: 145\n    sideArmor: 130\n    rearArmor: 100\n    underArmor: 90\n    drawingRoutine: 5\n    size: 2\n    damageModifier:\n      - 1.0\n      - 1.0\n      - 1.0\n      - 0.8\n      - 1.5\n      - 0.8\n      - 1.0\n      - 1.0\n      - 1.0\n      - 0.0\n    loftempsSet: [ 92, 89, 90, 91 ]\n  - type: TANK_ARMOR\n    spriteSheet: TANKS.PCK\n    allowInv: false\n    corpseBattle:\n      - TANK_CORPSE_1\n      - TANK_CORPSE_2\n      - TANK_CORPSE_3\n      - TANK_CORPSE_4\n    frontArmor: 90\n    sideArmor: 75\n    rearArmor: 60\n    underArmor: 60\n    drawingRoutine: 2\n    size: 2\n    damageModifier:\n      - 1.0\n      - 1.0\n      - 0.4\n      - 0.75\n      - 1.0\n      - 1.0\n      - 0.0\n      - 0.9\n      - 0.4\n      - 0.0\n    loftempsSet: [ 92, 89, 90, 91 ]\n  - type: HOVERTANK_ARMOR\n    spriteSheet: TANKS.PCK\n    allowInv: false\n    corpseBattle:\n      - HOVERTANK_CORPSE_1\n      - HOVERTANK_CORPSE_2\n      - HOVERTANK_CORPSE_3\n      - HOVERTANK_CORPSE_4\n    frontArmor: 130\n    sideArmor: 130\n    rearArmor: 130\n    underArmor: 100\n    drawingRoutine: 2\n    constantAnimation: true\n    movementType: 1\n    size: 2\n    damageModifier:\n      - 1.0\n      - 1.0\n      - 0.4\n      - 0.75\n      - 1.0\n      - 1.0\n      - 0.0\n      - 0.9\n      - 0.4\n      - 0.0\n    loftempsSet: [ 92, 89, 90, 91 ]\n  - type: CIVM_ARMOR\n    spriteSheet: CIVM.PCK\n    corpseBattle:\n      - CIVM_CORPSE\n    frontArmor: 0\n    sideArmor: 0\n    rearArmor: 0\n    underArmor: 0\n    drawingRoutine: 4\n    damageModifier:\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.2\n      - 1.6\n      - 1.0\n    loftempsSet: [ 3 ]\n  - type: CIVF_ARMOR\n    spriteSheet: CIVF.PCK\n    corpseBattle:\n      - CIVF_CORPSE\n    frontArmor: 0\n    sideArmor: 0\n    rearArmor: 0\n    underArmor: 0\n    drawingRoutine: 4\n    damageModifier:\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.2\n      - 1.6\n      - 1.0\n    loftempsSet: [ 3 ]\n  - type: SNAKEMAN_ARMOR0\n    spriteSheet: SNAKEMAN.PCK\n    corpseBattle:\n      - STR_SNAKEMAN_CORPSE\n    frontArmor: 20\n    sideArmor: 18\n    rearArmor: 16\n    underArmor: 12\n    drawingRoutine: 6\n    movementType: 2\n    damageModifier:\n      - 1.0\n      - 1.0\n      - 0.7\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 0.0\n    loftempsSet: [ 3 ]\n  - type: SNAKEMAN_ARMOR1\n    spriteSheet: SNAKEMAN.PCK\n    corpseBattle:\n      - STR_SNAKEMAN_CORPSE\n    frontArmor: 20\n    sideArmor: 24\n    rearArmor: 22\n    underArmor: 20\n    drawingRoutine: 6\n    movementType: 2\n    damageModifier:\n      - 1.0\n      - 1.0\n      - 0.7\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 0.0\n    loftempsSet: [ 3 ]\n  - type: SNAKEMAN_ARMOR2\n    spriteSheet: SNAKEMAN.PCK\n    corpseBattle:\n      - STR_SNAKEMAN_CORPSE\n    frontArmor: 26\n    sideArmor: 26\n    rearArmor: 22\n    underArmor: 20\n    drawingRoutine: 6\n    movementType: 2\n    damageModifier:\n      - 1.0\n      - 1.0\n      - 0.7\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 0.0\n    loftempsSet: [ 3 ]\n  - type: MUTON_ARMOR0\n    spriteSheet: MUTON.PCK\n    corpseBattle:\n      - STR_MUTON_CORPSE\n    frontArmor: 20\n    sideArmor: 20\n    rearArmor: 20\n    underArmor: 10\n    drawingRoutine: 10\n    damageModifier:\n      - 1.0\n      - 0.6\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 0.0\n    loftempsSet: [ 3 ]\n  - type: MUTON_ARMOR1\n    spriteSheet: MUTON.PCK\n    corpseBattle:\n      - STR_MUTON_CORPSE\n    frontArmor: 24\n    sideArmor: 24\n    rearArmor: 24\n    underArmor: 15\n    drawingRoutine: 10\n    damageModifier:\n      - 1.0\n      - 0.6\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 0.0\n    loftempsSet: [ 3 ]\n  - type: MUTON_ARMOR2\n    spriteSheet: MUTON.PCK\n    corpseBattle:\n      - STR_MUTON_CORPSE\n    frontArmor: 28\n    sideArmor: 28\n    rearArmor: 28\n    underArmor: 20\n    drawingRoutine: 10\n    damageModifier:\n      - 1.0\n      - 0.6\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 0.0\n    loftempsSet: [ 3 ]\n  - type: ETHEREAL_ARMOR0\n    spriteSheet: ETHEREAL.PCK\n    corpseBattle:\n      - STR_ETHEREAL_CORPSE\n    frontArmor: 35\n    sideArmor: 35\n    rearArmor: 35\n    underArmor: 35\n    movementType: 1\n    drawingRoutine: 4\n    damageModifier:\n      - 1.0\n      - 1.0\n      - 0.7\n      - 1.0\n      - 1.0\n      - 1.0\n      - 0.8\n      - 1.0\n      - 1.0\n      - 0.0\n    loftempsSet: [ 3 ]\n  - type: ETHEREAL_ARMOR1\n    spriteSheet: ETHEREAL.PCK\n    corpseBattle:\n      - STR_ETHEREAL_CORPSE\n    frontArmor: 40\n    sideArmor: 40\n    rearArmor: 40\n    underArmor: 40\n    movementType: 1\n    drawingRoutine: 4\n    damageModifier:\n      - 1.0\n      - 1.0\n      - 0.7\n      - 1.0\n      - 1.0\n      - 1.0\n      - 0.8\n      - 1.0\n      - 1.0\n      - 0.0\n    loftempsSet: [ 3 ]\n  - type: ETHEREAL_ARMOR2\n    spriteSheet: ETHEREAL.PCK\n    corpseBattle:\n      - STR_ETHEREAL_CORPSE\n    frontArmor: 45\n    sideArmor: 45\n    rearArmor: 45\n    underArmor: 45\n    movementType: 1\n    drawingRoutine: 4\n    damageModifier:\n      - 1.0\n      - 1.0\n      - 0.7\n      - 1.0\n      - 1.0\n      - 1.0\n      - 0.8\n      - 1.0\n      - 1.0\n      - 0.0\n    loftempsSet: [ 3 ]\n  - type: CHRYSSALID_ARMOR\n    spriteSheet: CHRYS.PCK\n    allowInv: false\n    corpseBattle:\n      - STR_CHRYSSALID_CORPSE\n    frontArmor: 34\n    sideArmor: 34\n    rearArmor: 34\n    underArmor: 34\n    drawingRoutine: 7\n    damageModifier:\n      - 1.0\n      - 1.0\n      - 0.8\n      - 1.0\n      - 1.0\n      - 1.0\n      - 0.9\n      - 1.0\n      - 1.0\n      - 0.0\n    loftempsSet: [ 3 ]\n  - type: ZOMBIE_ARMOR\n    painImmune: true   # no secondary stun damage\n    spriteSheet: ZOMBIE.PCK\n    allowInv: false\n    corpseBattle:\n      - STR_CHRYSSALID_CORPSE\n    frontArmor: 4\n    sideArmor: 4\n    rearArmor: 4\n    underArmor: 4\n    drawingRoutine: 4\n    damageModifier:\n      - 1.0\n      - 0.6\n      - 1.0\n      - 0.8\n      - 0.7\n      - 0.7\n      - 0.0\n      - 1.0\n      - 1.0\n      - 0.0\n    loftempsSet: [ 3 ]\n    deathFrames: 18\n  - type: SILACOID_ARMOR\n    spriteSheet: SILACOID.PCK\n    allowInv: false\n    corpseBattle:\n      - STR_SILACOID_CORPSE\n    frontArmor: 50\n    sideArmor: 50\n    rearArmor: 50\n    underArmor: 10\n    drawingRoutine: 8\n    constantAnimation: true\n    movementType: 2\n    damageModifier:\n      - 1.0\n      - 1.0\n      - 0.0\n      - 1.3\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 0.0\n    loftempsSet: [ 5 ]\n  - type: CELATID_ARMOR\n    spriteSheet: CELATID.PCK\n    allowInv: false\n    corpseBattle:\n      - STR_CELATID_CORPSE\n    frontArmor: 20\n    sideArmor: 20\n    rearArmor: 20\n    underArmor: 20\n    drawingRoutine: 9\n    constantAnimation: true\n    damageModifier:\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.2\n      - 1.6\n      - 0.0\n    loftempsSet: [ 3 ]"
  },
  {
    "path": "bin/standard/xcom1/converter.rul",
    "content": "# Here be dragons\nconverter:\n  offsets:\n    BASE.DAT_FACILITIES: 0x16\n    BASE.DAT_ENGINEERS: 0x5E\n    BASE.DAT_SCIENTISTS: 0x5F\n    BASE.DAT_ITEMS: 0x60\n    CRAFT.DAT_LEFT_WEAPON: 0x01\n    CRAFT.DAT_LEFT_AMMO: 0x02\n    CRAFT.DAT_FLIGHT: 0x04\n    CRAFT.DAT_RIGHT_WEAPON: 0x05\n    CRAFT.DAT_RIGHT_AMMO: 0x06\n    CRAFT.DAT_DAMAGE: 0x0A\n    CRAFT.DAT_ALTITUDE: 0x0C\n    CRAFT.DAT_SPEED: 0x0E\n    CRAFT.DAT_DESTINATION: 0x10\n    CRAFT.DAT_DEST_LON: 0x14\n    CRAFT.DAT_DEST_LAT: 0x16\n    CRAFT.DAT_FUEL: 0x18\n    CRAFT.DAT_BASE: 0x1A\n    CRAFT.DAT_MISSION: 0x1C\n    CRAFT.DAT_REGION: 0x1E\n    CRAFT.DAT_TRAJECTORY: 0x22\n    CRAFT.DAT_TRAJECTORY_POINT: 0x20\n    CRAFT.DAT_RACE: 0x24\n    CRAFT.DAT_STATUS: 0x2A\n    CRAFT.DAT_ITEMS: 0x2C\n    CRAFT.DAT_STATE: 0x64\n    SOLDIER.DAT_RANK: 0x00\n    SOLDIER.DAT_BASE: 0x02\n    SOLDIER.DAT_CRAFT: 0x04\n    SOLDIER.DAT_MISSIONS: 0x08\n    SOLDIER.DAT_KILLS: 0x0A\n    SOLDIER.DAT_RECOVERY: 0x0C\n    SOLDIER.DAT_NAME: 0x10\n    SOLDIER.DAT_INITIAL_TU: 0x2A\n    SOLDIER.DAT_INITIAL_HE: 0x2B\n    SOLDIER.DAT_INITIAL_STA: 0x2C\n    SOLDIER.DAT_INITIAL_RE: 0x2D\n    SOLDIER.DAT_INITIAL_STR: 0x2E\n    SOLDIER.DAT_INITIAL_FA: 0x2F\n    SOLDIER.DAT_INITIAL_TA: 0x30\n    SOLDIER.DAT_INITIAL_ME: 0x31\n    SOLDIER.DAT_INITIAL_PST: 0x32\n    SOLDIER.DAT_INITIAL_PSK: 0x33\n    SOLDIER.DAT_INITIAL_BR: 0x34\n    SOLDIER.DAT_IMPROVED_TU: 0x35\n    SOLDIER.DAT_IMPROVED_HE: 0x36\n    SOLDIER.DAT_IMPROVED_STA: 0x37\n    SOLDIER.DAT_IMPROVED_RE: 0x38\n    SOLDIER.DAT_IMPROVED_STR: 0x39\n    SOLDIER.DAT_IMPROVED_FA: 0x3A\n    SOLDIER.DAT_IMPROVED_TA: 0x3B\n    SOLDIER.DAT_IMPROVED_ME: 0x3C\n    SOLDIER.DAT_IMPROVED_BR: 0x3D\n    SOLDIER.DAT_ARMOR: 0x3E\n    SOLDIER.DAT_PSI: 0x3F\n    SOLDIER.DAT_PSILAB: 0x40\n    SOLDIER.DAT_GENDER: 0x42\n    SOLDIER.DAT_LOOK: 0x43\n  markers:\n    - STR_UFO\n    - STR_TERROR_SITE\n    - STR_ALIEN_BASE\n    - STR_LANDING_SITE\n    - STR_CRASH_SITE\n    - STR_WAYPOINT\n    - STR_SKYRANGER\n    - STR_LIGHTNING\n    - STR_AVENGER\n    - STR_INTERCEPTOR\n    - STR_FIRESTORM\n  countries:\n    - STR_USA\n    - STR_RUSSIA\n    - STR_UK\n    - STR_FRANCE\n    - STR_GERMANY\n    - STR_ITALY\n    - STR_SPAIN\n    - STR_CHINA\n    - STR_JAPAN\n    - STR_INDIA\n    - STR_BRAZIL\n    - STR_AUSTRALIA\n    - STR_NIGERIA\n    - STR_SOUTH_AFRICA\n    - STR_EGYPT\n    - STR_CANADA\n  regions:\n    - STR_NORTH_AMERICA\n    - STR_ARCTIC\n    - STR_ANTARCTICA\n    - STR_SOUTH_AMERICA\n    - STR_EUROPE\n    - STR_NORTH_AFRICA\n    - STR_SOUTHERN_AFRICA\n    - STR_CENTRAL_ASIA\n    - STR_SOUTH_EAST_ASIA\n    - STR_SIBERIA\n    - STR_AUSTRALASIA\n    - STR_PACIFIC\n    - STR_NORTH_ATLANTIC\n    - STR_SOUTH_ATLANTIC\n    - STR_INDIAN_OCEAN\n  facilities:\n    - STR_ACCESS_LIFT\n    - STR_LIVING_QUARTERS\n    - STR_LABORATORY\n    - STR_WORKSHOP\n    - STR_SMALL_RADAR_SYSTEM\n    - STR_LARGE_RADAR_SYSTEM\n    - STR_MISSILE_DEFENSES\n    - STR_GENERAL_STORES\n    - STR_ALIEN_CONTAINMENT\n    - STR_LASER_DEFENSES\n    - STR_PLASMA_DEFENSES\n    - STR_FUSION_BALL_DEFENSES\n    - STR_GRAV_SHIELD\n    - STR_MIND_SHIELD\n    - STR_PSIONIC_LABORATORY\n    - STR_HYPER_WAVE_DECODER\n    - STR_HANGAR\n  items:\n    - STR_STINGRAY_LAUNCHER\n    - STR_AVALANCHE_LAUNCHER\n    - STR_CANNON\n    - STR_FUSION_BALL_LAUNCHER\n    - STR_LASER_CANNON\n    - STR_PLASMA_BEAM\n    - STR_STINGRAY_MISSILES\n    - STR_AVALANCHE_MISSILES\n    - STR_CANNON_ROUNDS_X50\n    - STR_FUSION_BALL\n    - STR_TANK_CANNON\n    - STR_TANK_ROCKET_LAUNCHER\n    - STR_TANK_LASER_CANNON\n    - STR_HOVERTANK_PLASMA\n    - STR_HOVERTANK_LAUNCHER\n    - STR_PISTOL\n    - STR_PISTOL_CLIP\n    - STR_RIFLE\n    - STR_RIFLE_CLIP\n    - STR_HEAVY_CANNON\n    - STR_HC_AP_AMMO\n    - STR_HC_HE_AMMO\n    - STR_HC_I_AMMO\n    - STR_AUTO_CANNON\n    - STR_AC_AP_AMMO\n    - STR_AC_HE_AMMO\n    - STR_AC_I_AMMO\n    - STR_ROCKET_LAUNCHER\n    - STR_SMALL_ROCKET\n    - STR_LARGE_ROCKET\n    - STR_INCENDIARY_ROCKET\n    - STR_LASER_PISTOL\n    - STR_LASER_RIFLE\n    - STR_HEAVY_LASER\n    - STR_GRENADE\n    - STR_SMOKE_GRENADE\n    - STR_PROXIMITY_GRENADE\n    - STR_HIGH_EXPLOSIVE\n    - STR_MOTION_SCANNER\n    - STR_MEDI_KIT\n    - STR_PSI_AMP\n    - STR_STUN_ROD\n    - STR_ELECTRO_FLARE\n    - \"\"\n    - \"\"\n    - \"\"\n    - \"\"\n    - \"\"\n    - \"\"\n    - STR_HEAVY_PLASMA\n    - STR_HEAVY_PLASMA_CLIP\n    - STR_PLASMA_RIFLE\n    - STR_PLASMA_RIFLE_CLIP\n    - STR_PLASMA_PISTOL\n    - STR_PLASMA_PISTOL_CLIP\n    - STR_BLASTER_LAUNCHER\n    - STR_BLASTER_BOMB\n    - STR_SMALL_LAUNCHER\n    - STR_STUN_BOMB\n    - STR_ALIEN_GRENADE\n    - STR_ELERIUM_115\n    - STR_MIND_PROBE\n    - \"\"\n    - \"\"\n    - \"\"\n    - STR_SECTOID_CORPSE\n    - STR_SNAKEMAN_CORPSE\n    - STR_ETHEREAL_CORPSE\n    - STR_MUTON_CORPSE\n    - STR_FLOATER_CORPSE\n    - STR_CELATID_CORPSE\n    - STR_SILACOID_CORPSE\n    - STR_CHRYSSALID_CORPSE\n    - STR_REAPER_CORPSE\n    - STR_SECTOPOD_CORPSE\n    - STR_CYBERDISC_CORPSE\n    - \"\"\n    - \"\"\n    - \"\"\n    - \"\"\n    - STR_UFO_POWER_SOURCE\n    - STR_UFO_NAVIGATION\n    - STR_UFO_CONSTRUCTION\n    - STR_ALIEN_FOOD\n    - STR_ALIEN_REPRODUCTION\n    - STR_ALIEN_ENTERTAINMENT\n    - STR_ALIEN_SURGERY\n    - STR_EXAMINATION_ROOM\n    - STR_ALIEN_ALLOYS\n    - STR_ALIEN_HABITAT\n    - STR_PERSONAL_ARMOR\n    - STR_POWER_SUIT\n    - STR_FLYING_SUIT\n    - STR_HWP_CANNON_SHELLS\n    - STR_HWP_ROCKETS\n    - STR_HWP_FUSION_BOMB\n  crews:\n    - STR_SECTOID\n    - STR_SNAKEMAN\n    - STR_ETHEREAL\n    - STR_MUTON\n    - STR_FLOATER\n    - STR_MIXED\n  crafts:\n    - STR_SKYRANGER\n    - STR_LIGHTNING\n    - STR_AVENGER\n    - STR_INTERCEPTOR\n    - STR_FIRESTORM\n  ufos:\n    - STR_SMALL_SCOUT\n    - STR_MEDIUM_SCOUT\n    - STR_LARGE_SCOUT\n    - STR_HARVESTER\n    - STR_ABDUCTOR\n    - STR_TERROR_SHIP\n    - STR_BATTLESHIP\n    - STR_SUPPLY_SHIP\n  craftWeapons:\n    - STR_STINGRAY\n    - STR_AVALANCHE\n    - STR_CANNON_UC\n    - STR_FUSION_BALL_UC\n    - STR_LASER_CANNON_UC\n    - STR_PLASMA_BEAM_UC\n  missions:\n    - STR_ALIEN_RESEARCH\n    - STR_ALIEN_HARVEST\n    - STR_ALIEN_ABDUCTION\n    - STR_ALIEN_INFILTRATION\n    - STR_ALIEN_BASE\n    - STR_ALIEN_TERROR\n    - STR_ALIEN_RETALIATION\n    - STR_ALIEN_SUPPLY\n  armor:\n    - STR_NONE_UC\n    - STR_PERSONAL_ARMOR_UC\n    - STR_POWER_SUIT_UC\n    - STR_FLYING_SUIT_UC\n  alienRaces:\n    - \"\"\n    - STR_SECTOID\n    - STR_SNAKEMAN\n    - STR_ETHEREAL\n    - STR_MUTON\n    - STR_FLOATER\n    - STR_CELATID\n    - STR_SILACOID\n    - STR_CHRYSSALID\n    - STR_REAPER\n    - STR_SECTOPOD\n    - STR_CYBERDISC\n  alienRanks:\n    - \"\"\n    - _COMMANDER\n    - _LEADER\n    - _ENGINEER\n    - _MEDIC\n    - _NAVIGATOR\n    - _SOLDIER\n    - _TERRORIST\n  research:\n    - STR_LASER_WEAPONS\n    - STR_MOTION_SCANNER\n    - STR_MEDI_KIT\n    - STR_PSI_AMP\n    - STR_HEAVY_PLASMA\n    - STR_HEAVY_PLASMA_CLIP\n    - STR_PLASMA_RIFLE\n    - STR_PLASMA_RIFLE_CLIP\n    - STR_PLASMA_PISTOL\n    - STR_PLASMA_PISTOL_CLIP\n    - STR_BLASTER_LAUNCHER\n    - STR_BLASTER_BOMB\n    - STR_SMALL_LAUNCHER\n    - STR_STUN_BOMB\n    - STR_ALIEN_GRENADE\n    - STR_ELERIUM_115\n    - STR_MIND_PROBE\n    - STR_UFO_POWER_SOURCE\n    - STR_UFO_NAVIGATION\n    - STR_UFO_CONSTRUCTION\n    - STR_ALIEN_FOOD\n    - STR_ALIEN_REPRODUCTION\n    - STR_ALIEN_ENTERTAINMENT\n    - STR_ALIEN_SURGERY\n    - STR_EXAMINATION_ROOM\n    - STR_ALIEN_ALLOYS\n    - STR_NEW_FIGHTER_CRAFT\n    - STR_NEW_FIGHTER_TRANSPORTER\n    - STR_ULTIMATE_CRAFT\n    - STR_LASER_PISTOL\n    - STR_LASER_RIFLE\n    - STR_HEAVY_LASER\n    - STR_LASER_CANNON\n    - STR_PLASMA_CANNON\n    - STR_FUSION_MISSILE\n    - STR_LASER_DEFENSE\n    - STR_PLASMA_DEFENSE\n    - STR_FUSION_DEFENSE\n    - STR_GRAV_SHIELD\n    - STR_MIND_SHIELD\n    - STR_PSI_LAB\n    - STR_HYPER_WAVE_DECODER\n    - \"\"\n    - \"\"\n    - \"\"\n    - STR_SECTOID_CORPSE\n    - STR_SNAKEMAN_CORPSE\n    - STR_ETHEREAL_CORPSE\n    - STR_MUTON_CORPSE\n    - STR_FLOATER_CORPSE\n    - STR_CELATID_CORPSE\n    - STR_SILACOID_CORPSE\n    - STR_CHRYSSALID_CORPSE\n    - STR_REAPER_CORPSE\n    - STR_SECTOPOD_CORPSE\n    - STR_CYBERDISC_CORPSE\n    - STR_ALIEN_ORIGINS\n    - STR_THE_MARTIAN_SOLUTION\n    - STR_CYDONIA_OR_BUST\n    - STR_PERSONAL_ARMOR\n    - STR_POWER_SUIT\n    - STR_FLYING_SUIT\n    - STR_SECTOID_COMMANDER\n    - STR_SECTOID_LEADER\n    - STR_SECTOID_ENGINEER\n    - STR_SECTOID_MEDIC\n    - STR_SECTOID_NAVIGATOR\n    - STR_SECTOID_SOLDIER\n    - STR_SNAKEMAN_COMMANDER\n    - STR_SNAKEMAN_LEADER\n    - STR_SNAKEMAN_ENGINEER\n    - STR_SNAKEMAN_MEDIC\n    - STR_SNAKEMAN_NAVIGATOR\n    - STR_SNAKEMAN_SOLDIER\n    - STR_ETHEREAL_COMMANDER\n    - STR_ETHEREAL_LEADER\n    - STR_ETHEREAL_ENGINEER\n    - STR_ETHEREAL_MEDIC\n    - STR_ETHEREAL_NAVIGATOR\n    - STR_ETHEREAL_SOLDIER\n    - STR_MUTON_COMMANDER\n    - STR_MUTON_LEADER\n    - STR_MUTON_ENGINEER\n    - STR_MUTON_MEDIC\n    - STR_MUTON_NAVIGATOR\n    - STR_MUTON_SOLDIER\n    - STR_FLOATER_COMMANDER\n    - STR_FLOATER_LEADER\n    - STR_FLOATER_ENGINEER\n    - STR_FLOATER_MEDIC\n    - STR_FLOATER_NAVIGATOR\n    - STR_FLOATER_SOLDIER\n    - STR_CELATID_TERRORIST\n    - STR_SILACOID_TERRORIST\n    - STR_CHRYSSALID_TERRORIST\n    - STR_REAPER_TERRORIST\n  manufacture:\n    - STR_FUSION_BALL_LAUNCHER\n    - STR_LASER_CANNON\n    - STR_PLASMA_BEAM\n    - STR_FUSION_BALL\n    - STR_TANK_LASER_CANNON\n    - STR_HOVERTANK_PLASMA\n    - STR_HOVERTANK_LAUNCHER\n    - STR_HWP_FUSION_BOMB\n    - STR_LASER_PISTOL\n    - STR_LASER_RIFLE\n    - STR_HEAVY_LASER\n    - STR_MOTION_SCANNER\n    - STR_MEDI_KIT\n    - STR_PSI_AMP\n    - STR_HEAVY_PLASMA\n    - STR_HEAVY_PLASMA_CLIP\n    - STR_PLASMA_RIFLE\n    - STR_PLASMA_RIFLE_CLIP\n    - STR_PLASMA_PISTOL\n    - STR_PLASMA_PISTOL_CLIP\n    - STR_BLASTER_LAUNCHER\n    - STR_BLASTER_BOMB\n    - STR_SMALL_LAUNCHER\n    - STR_STUN_BOMB\n    - STR_ALIEN_GRENADE\n    - STR_MIND_PROBE\n    - STR_PERSONAL_ARMOR\n    - STR_POWER_SUIT\n    - STR_FLYING_SUIT\n    - STR_ALIEN_ALLOYS\n    - STR_UFO_POWER_SOURCE\n    - STR_UFO_NAVIGATION\n    - STR_FIRESTORM\n    - STR_LIGHTNING\n    - STR_AVENGER\n  ufopaedia:\n    - STR_SKYRANGER\n    - STR_LIGHTNING\n    - STR_AVENGER\n    - STR_INTERCEPTOR\n    - STR_FIRESTORM\n    - STR_STINGRAY\n    - STR_AVALANCHE\n    - STR_CANNON_UC\n    - STR_FUSION_BALL_UC\n    - STR_LASER_CANNON_UC\n    - STR_PLASMA_BEAM_UC\n    - STR_TANK_CANNON\n    - STR_TANK_ROCKET_LAUNCHER\n    - STR_TANK_LASER_CANNON\n    - STR_HOVERTANK_PLASMA\n    - STR_HOVERTANK_LAUNCHER\n    - STR_PERSONAL_ARMOR_UC\n    - STR_POWER_SUIT_UC\n    - STR_FLYING_SUIT_UC\n    - STR_PISTOL\n    - STR_RIFLE\n    - STR_HEAVY_CANNON\n    - STR_AUTO_CANNON\n    - STR_ROCKET_LAUNCHER\n#    - STR_SMALL_ROCKET        # doesn't exist in UP.DAT\n#    - STR_LARGE_ROCKET        # doesn't exist in UP.DAT\n#    - STR_INCENDIARY_ROCKET   # doesn't exist in UP.DAT\n    - STR_LASER_PISTOL\n    - STR_LASER_RIFLE\n    - STR_HEAVY_LASER\n    - STR_GRENADE\n    - STR_SMOKE_GRENADE\n    - STR_PROXIMITY_GRENADE\n    - STR_HIGH_EXPLOSIVE\n    - STR_MOTION_SCANNER\n    - STR_MEDI_KIT\n    - STR_PSI_AMP\n    - STR_STUN_ROD\n    - STR_ELECTRO_FLARE\n    - STR_HEAVY_PLASMA\n    - STR_HEAVY_PLASMA_CLIP\n    - STR_PLASMA_RIFLE\n    - STR_PLASMA_RIFLE_CLIP\n    - STR_PLASMA_PISTOL\n    - STR_PLASMA_PISTOL_CLIP\n    - STR_BLASTER_LAUNCHER\n    - STR_BLASTER_BOMB\n    - STR_SMALL_LAUNCHER\n    - STR_STUN_BOMB\n    - STR_ALIEN_GRENADE\n    - STR_ELERIUM_115\n    - STR_MIND_PROBE\n    - STR_ACCESS_LIFT\n    - STR_LIVING_QUARTERS\n    - STR_LABORATORY\n    - STR_WORKSHOP\n    - STR_SMALL_RADAR_SYSTEM\n    - STR_LARGE_RADAR_SYSTEM\n    - STR_MISSILE_DEFENSES\n    - STR_GENERAL_STORES\n    - STR_ALIEN_CONTAINMENT\n    - STR_LASER_DEFENSES\n    - STR_PLASMA_DEFENSES\n    - STR_FUSION_BALL_DEFENSES\n    - STR_GRAV_SHIELD\n    - STR_MIND_SHIELD\n    - STR_PSIONIC_LABORATORY\n    - STR_HYPER_WAVE_DECODER\n    - STR_HANGAR\n    - STR_SECTOID\n    - STR_SECTOID_AUTOPSY\n    - STR_SNAKEMAN\n    - STR_SNAKEMAN_AUTOPSY\n    - STR_ETHEREAL\n    - STR_ETHEREAL_AUTOPSY\n    - STR_MUTON\n    - STR_MUTON_AUTOPSY\n    - STR_FLOATER\n    - STR_FLOATER_AUTOPSY\n    - STR_CELATID\n    - STR_CELATID_AUTOPSY\n    - STR_SILACOID\n    - STR_SILACOID_AUTOPSY\n    - STR_CHRYSSALID\n    - STR_CHRYSSALID_AUTOPSY\n    - STR_REAPER\n    - STR_REAPER_AUTOPSY\n    - STR_SECTOPOD\n    - STR_SECTOPOD_AUTOPSY\n    - STR_CYBERDISC\n    - STR_CYBERDISC_AUTOPSY\n    - STR_ALIEN_ORIGINS\n    - STR_THE_MARTIAN_SOLUTION\n    - STR_CYDONIA_OR_BUST\n    - STR_ALIEN_RESEARCH\n    - STR_ALIEN_HARVEST\n    - STR_ALIEN_ABDUCTION\n    - STR_ALIEN_INFILTRATION\n    - STR_ALIEN_BASE\n    - STR_ALIEN_TERROR\n    - STR_ALIEN_RETALIATION\n    - STR_ALIEN_SUPPLY\n    - STR_UFO_POWER_SOURCE\n    - STR_UFO_NAVIGATION\n    - STR_UFO_CONSTRUCTION\n    - STR_ALIEN_FOOD\n    - STR_ALIEN_REPRODUCTION\n    - STR_ALIEN_ENTERTAINMENT\n    - STR_ALIEN_SURGERY\n    - STR_EXAMINATION_ROOM\n    - STR_ALIEN_ALLOYS\n    - STR_SMALL_SCOUT\n    - STR_MEDIUM_SCOUT\n    - STR_LARGE_SCOUT\n    - STR_HARVESTER\n    - STR_ABDUCTOR\n    - STR_TERROR_SHIP\n    - STR_BATTLESHIP\n    - STR_SUPPLY_SHIP"
  },
  {
    "path": "bin/standard/xcom1/countries.rul",
    "content": "countries:\n  - type: STR_USA\n    fundingBase: 600\n    fundingCap: 10000\n    labelLon: 260\n    labelLat: -40\n    areas:\n      - [235, 255, -49, -32]\n      - [255, 277.5, -49, -29]\n      - [260, 265, -29, -26]\n      - [277, 280, -32, -25]\n      - [277.5, 286, -44, -32]\n      - [286, 292.5, -45.5, -40]\n  - type: STR_RUSSIA\n    fundingBase: 230\n    fundingCap: 8000\n    labelLon: 60\n    labelLat: -60\n    areas:\n      - [30, 50, -70, -45]\n      - [24, 30, -60, -42]\n      - [50, 75, -77, -40]\n      - [75, 165, -80, -50]\n      - [165, 170, -70, -59]\n  - type: STR_UK\n    fundingBase: 240\n    fundingCap: 7000\n    labelLon: 358\n    labelLat: -53.625\n    areas:\n      - [352, 2, -60, -50]\n  - type: STR_FRANCE\n    fundingBase: 320\n    fundingCap: 8000\n    labelLon: 2.5\n    labelLat: -46.5\n    areas:\n      - [355, 7, -50, -43]\n  - type: STR_GERMANY\n    fundingBase: 250\n    fundingCap: 9000\n    labelLon: 11.5\n    labelLat: -50\n    areas:\n      - [6, 15, -55, -47.5]\n  - type: STR_ITALY\n    fundingBase: 160\n    fundingCap: 6000\n    labelLon: 12.5\n    labelLat: -43.875\n    areas:\n      - [7, 15, -46.5, -43]\n      - [11, 18, -43, -37]\n  - type: STR_SPAIN\n    fundingBase: 140\n    fundingCap: 5000\n    labelLon: 357.5\n    labelLat: -42.625\n    areas:\n      - [353, 3, -43, -36.5]\n      - [351, 353, -43, -42.25]\n  - type: STR_CHINA\n    fundingBase: 245\n    fundingCap: 7000\n    labelLon: 100\n    labelLat: -35\n    areas:\n      - [75, 98, -50, -30]\n      - [98, 122, -50, -22]\n      - [122, 133, -54, -40]\n  - type: STR_JAPAN\n    fundingBase: 400\n    fundingCap: 10000\n    labelLon: 138\n    labelLat: -38.25\n    areas:\n      - [130, 143, -40, -30]\n      - [138, 147, -46, -40]\n  - type: STR_INDIA\n    fundingBase: 150\n    fundingCap: 5000\n    labelLon: 80\n    labelLat: -24\n    areas:\n      - [70, 85, -30, -8]\n      - [74, 79, -35, -30]\n      - [85, 95, -27, -20]\n  - type: STR_BRAZIL\n    fundingBase: 300\n    fundingCap: 4000\n    labelLon: 305\n    labelLat: 5\n    areas:\n      - [290, 302, -2.5, 17]\n      - [302, 310, -2.5, 22]\n      - [310, 325, 0, 24]\n      - [305, 313, 22, 32]\n  - type: STR_AUSTRALIA\n    fundingBase: 280\n    fundingCap: 5000\n    labelLon: 135\n    labelLat: 25\n    areas:\n      - [110, 156, 10, 40]\n  - type: STR_NIGERIA\n    fundingBase: 180\n    fundingCap: 2000\n    labelLon: 7.5\n    labelLat: -10\n    areas:\n      - [3, 14, -14, -4]\n  - type: STR_SOUTH_AFRICA\n    fundingBase: 230\n    fundingCap: 3000\n    labelLon: 25\n    labelLat: 30\n    areas:\n      - [15, 25, 26, 35]\n      - [25, 32.5, 22, 35]\n  - type: STR_EGYPT\n    fundingBase: 230\n    fundingCap: 2000\n    labelLon: 29\n    labelLat: -26\n    areas:\n      - [25, 35, -32, -22]\n  - type: STR_CANADA\n    fundingBase: 230\n    fundingCap: 4000\n    labelLon: 260\n    labelLat: -55\n    areas:\n      - [219, 230, -70, -55]\n      - [230, 305, -75, -40]"
  },
  {
    "path": "bin/standard/xcom1/craftWeapons.rul",
    "content": "craftWeapons:\n  - type: STR_STINGRAY\n    sprite: 0\n    sound: 5\n    damage: 70\n    range: 30\n    accuracy: 70\n    reloadCautious: 64\n    reloadStandard: 48\n    reloadAggressive: 32\n    ammoMax: 6\n    launcher: STR_STINGRAY_LAUNCHER\n    clip: STR_STINGRAY_MISSILES\n    projectileType: 0\n    projectileSpeed: 8\n  - type: STR_AVALANCHE\n    sprite: 1\n    sound: 5\n    damage: 100\n    range: 60\n    accuracy: 80\n    reloadCautious: 96\n    reloadStandard: 72\n    reloadAggressive: 48\n    ammoMax: 3\n    launcher: STR_AVALANCHE_LAUNCHER\n    clip: STR_AVALANCHE_MISSILES\n    projectileType: 1\n    projectileSpeed: 8\n  - type: STR_CANNON_UC\n    sprite: 2\n    sound: 4\n    damage: 10\n    range: 10\n    accuracy: 25\n    reloadCautious: 4\n    reloadStandard: 4\n    reloadAggressive: 4\n    ammoMax: 200\n    rearmRate: 100\n    launcher: STR_CANNON\n    clip: STR_CANNON_ROUNDS_X50\n    projectileType: 2\n    projectileSpeed: 8\n  - type: STR_FUSION_BALL_UC\n    sprite: 3\n    sound: 7\n    damage: 230\n    range: 65\n    accuracy: 100\n    reloadCautious: 64\n    reloadStandard: 48\n    reloadAggressive: 32\n    ammoMax: 2\n    launcher: STR_FUSION_BALL_LAUNCHER\n    clip: STR_FUSION_BALL\n    projectileType: 3\n    projectileSpeed: 8\n  - type: STR_LASER_CANNON_UC\n    sprite: 4\n    sound: 8\n    damage: 70\n    range: 21\n    accuracy: 35\n    reloadCautious: 24\n    reloadStandard: 24\n    reloadAggressive: 24\n    ammoMax: 100\n    rearmRate: 50\n    launcher: STR_LASER_CANNON\n    projectileType: 4\n  - type: STR_PLASMA_BEAM_UC\n    sprite: 5\n    sound: 9\n    damage: 140\n    range: 52\n    accuracy: 50\n    reloadCautious: 24\n    reloadStandard: 24\n    reloadAggressive: 24\n    ammoMax: 100\n    rearmRate: 50\n    launcher: STR_PLASMA_BEAM\n    projectileType: 5"
  },
  {
    "path": "bin/standard/xcom1/crafts.rul",
    "content": "crafts:\n  - type: STR_SKYRANGER\n    sprite: 0\n    fuelMax: 1500\n    damageMax: 150\n    speedMax: 760\n    accel: 2\n    soldiers: 14\n    vehicles: 3\n    costBuy: 500000\n    costRent: 500000\n    forceShowInMonthlyCosts: true\n    refuelRate: 50\n    transferTime: 72\n    score: 200\n    battlescapeTerrainData:\n      name: PLANE\n      mapDataSets:\n        - BLANKS\n        - PLANE\n      mapBlocks:\n        - name: PLANE\n          width: 10\n          length: 20\n  - type: STR_LIGHTNING\n    requires:\n      - STR_NEW_FIGHTER_TRANSPORTER\n    sprite: 1\n    fuelMax: 30\n    damageMax: 800\n    speedMax: 3100\n    accel: 9\n    weapons: 1\n    soldiers: 12\n    refuelItem: STR_ELERIUM_115\n    refuelRate: 5\n    score: 300\n    battlescapeTerrainData:\n      name: LIGHTNIN\n      mapDataSets:\n        - BLANKS\n        - LIGHTNIN\n      mapBlocks:\n        - name: LIGHTNIN\n          width: 20\n          length: 10\n    deployment:\n      - [10, 5, 1, 2]\n      - [10, 6, 1, 2]\n      - [10, 4, 1, 2]\n      - [9, 7, 1, 2]\n      - [9, 3, 1, 2]\n      - [8, 7, 1, 2]\n      - [8, 3, 1, 2]\n      - [7, 7, 1, 2]\n      - [7, 3, 1, 2]\n      - [6, 6, 1, 2]\n      - [6, 4, 1, 2]\n      - [6, 5, 1, 2]\n  - type: STR_AVENGER\n    requires:\n      - STR_ULTIMATE_CRAFT\n    sprite: 2\n    fuelMax: 60\n    damageMax: 1200\n    speedMax: 5400\n    accel: 10\n    weapons: 2\n    soldiers: 26\n    vehicles: 4\n    refuelItem: STR_ELERIUM_115\n    refuelRate: 5\n    score: 400\n    spacecraft: true\n    battlescapeTerrainData:\n      name: AVENGER\n      mapDataSets:\n        - BLANKS\n        - AVENGER\n      mapBlocks:\n        - name: AVENGER\n          width: 10\n          length: 20\n    deployment:\n      - [4, 9, 1, 0]\n      - [5, 9, 1, 0]\n      - [4, 10, 1, 0]\n      - [5, 10, 1, 0]\n      - [4, 11, 1, 0]\n      - [5, 11, 1, 0]\n      - [4, 12, 1, 0]\n      - [5, 12, 1, 0]\n      - [4, 13, 1, 0]\n      - [5, 13, 1, 0]\n      - [4, 14, 1, 0]\n      - [5, 14, 1, 0]\n      - [4, 15, 1, 0]\n      - [5, 15, 1, 0]\n      - [4, 16, 1, 0]\n      - [5, 16, 1, 0]\n      - [3, 10, 1, 0]\n      - [3, 11, 1, 0]\n      - [3, 12, 1, 0]\n      - [3, 13, 1, 0]\n      - [3, 14, 1, 0]\n      - [6, 10, 1, 0]\n      - [6, 11, 1, 0]\n      - [6, 12, 1, 0]\n      - [6, 13, 1, 0]\n      - [6, 14, 1, 0]\n  - type: STR_INTERCEPTOR\n    sprite: 3\n    fuelMax: 1000\n    damageMax: 100\n    speedMax: 2100\n    accel: 3\n    weapons: 2\n    costBuy: 600000\n    costRent: 600000\n    forceShowInMonthlyCosts: true\n    refuelRate: 50\n    transferTime: 96\n    score: 250\n  - type: STR_FIRESTORM\n    requires:\n      - STR_NEW_FIGHTER_CRAFT\n    sprite: 4\n    fuelMax: 20\n    damageMax: 500\n    speedMax: 4200\n    accel: 9\n    weapons: 2\n    refuelItem: STR_ELERIUM_115\n    refuelRate: 5\n    score: 250"
  },
  {
    "path": "bin/standard/xcom1/cutscenes.rul",
    "content": "cutscenes:\n  - type: intro\n    useUfoAudioSequence: true\n    videos:\n      - UFOINTRO/UFOINT.FLI\n  - type: winGame\n    winGame: true\n    slideshow:\n      transitionSeconds: 30\n      musicId: GMWIN\n      slides:\n        - imagePath: UFOINTRO/PICT1.LBM\n          caption: STR_VICTORY_1\n          captionSize: [195, 56]\n          captionPos: [5, 0]\n          captionColor: 249\n        - imagePath: UFOINTRO/PICT2.LBM\n          caption: STR_VICTORY_2\n          captionSize: [232, 64]\n          captionPos: [88, 136]\n          captionColor: 249\n        - imagePath: UFOINTRO/PICT3.LBM\n          caption: STR_VICTORY_3\n          captionSize: [254, 48]\n          captionPos: [66, 152]\n          captionColor: 249\n        - imagePath: UFOINTRO/PICT6.LBM\n          caption: STR_VICTORY_4\n          captionSize: [300, 200]\n          captionPos: [5, 0]\n          captionColor: 249\n        - imagePath: UFOINTRO/PICT7.LBM\n          caption: STR_VICTORY_5\n          captionSize: [310, 42]\n          captionPos: [5, 158]\n          captionColor: 249\n  - type: loseGame\n    loseGame: true\n    slideshow:\n      transitionSeconds: 30\n      musicId: GMLOSE\n      slides:\n        - imagePath: UFOINTRO/PICT4.LBM\n          caption: STR_GAME_OVER_1\n          captionSize: [190, 104]\n          captionPos: [0, 0]\n          captionColor: 249\n        - imagePath: UFOINTRO/PICT5.LBM\n          caption: STR_GAME_OVER_2\n          captionSize: [200, 34]\n          captionPos: [32, 0]\n          captionColor: 249\n"
  },
  {
    "path": "bin/standard/xcom1/difficulty.rul",
    "content": "difficultyCoefficient: [0, 1, 2, 3, 4]\naimAndArmorMultipliers: [0.5, 1.0, 1.0, 1.0, 1.0]\nstatGrowthMultipliers:\n  tu: 4\n  stamina: 4\n  health: 0\n  bravery: 0\n  reactions: 6\n  firing: 6\n  throwing: 0\n  strength: 2\n  psiStrength: 4\n  psiSkill: 4\n  melee: 4\n# for more information on what these numbers mean, see\n# http://ufopaedia.org/index.php?title=Alien_Stats_(TFTD)#Calculating_Statistics\n# statGrowthMultipliers are the increments\n# difficultyCoefficients are MultiplierA\n# aimAndArmorMultipliers are MultiplierB\nturnAIUseGrenade: 3\nturnAIUseBlaster: 3\ndefeatScore: -900\ndefeatFunds: -1000000\nconstants:\n  - damageRange: 100\n  - explosiveDamageRange: 50\n  - fireDamageRange: [5, 10]"
  },
  {
    "path": "bin/standard/xcom1/extraSprites.rul",
    "content": "extraSprites:\n  - type: Touch\n    width: 64\n    height: 120\n    subX: 32\n    subY: 24\n    files:\n      0: Resources/Extended/Touch/Touch_UFOEU.png\n  - type: oxceLinks\n    width: 32\n    height: 16\n    singleImage: true\n    files:\n      0: Resources/Extended/oxceLinks.png\n  - type: oxceLinksInv\n    width: 23\n    height: 22\n    singleImage: true\n    files:\n      0: Resources/Extended/oxceLinksInv.png\n  - type: TinyRanks\n    width: 42\n    height: 7\n    subX: 7\n    subY: 7\n    files:\n      0: Resources/Extended/TinyRanks.png\n  - type: ExtendedPediaBackgroundPalBasescape\n    width: 320\n    height: 200\n    singleImage: true\n    files:\n      0: Resources/Extended/Pedia/PAL_BASESCAPE/background-ufo.png\n  - type: ExtendedPediaBackgroundPalBasescape-InfoButton\n    width: 320\n    height: 200\n    singleImage: true\n    files:\n      0: Resources/Extended/Pedia/PAL_BASESCAPE/info-button-ufo.png\n  - type: ExtendedPediaBackgroundPalBattlepedia\n    width: 320\n    height: 200\n    singleImage: true\n    files:\n      0: Resources/Extended/Pedia/PAL_BATTLEPEDIA/background-ufo.png\n  - type: ExtendedPediaBackgroundPalBattlepedia-InfoButton\n    width: 320\n    height: 200\n    singleImage: true\n    files:\n      0: Resources/Extended/Pedia/PAL_BATTLEPEDIA/info-button-ufo.png\n  - type: ExtendedPediaBackgroundPalGeoscape\n    width: 320\n    height: 200\n    singleImage: true\n    files:\n      0: Resources/Extended/Pedia/PAL_GEOSCAPE/background-ufo.png\n  - type: ExtendedPediaBackgroundPalGeoscape-InfoButton\n    width: 320\n    height: 200\n    singleImage: true\n    files:\n      0: Resources/Extended/Pedia/PAL_GEOSCAPE/info-button-ufo.png\n  - type: ExtendedPediaBackgroundPalUfopaedia\n    width: 320\n    height: 200\n    singleImage: true\n    files:\n      0: Resources/Extended/Pedia/PAL_UFOPAEDIA/background-ufo.png\n  - type: ExtendedPediaBackgroundPalUfopaedia-InfoButton\n    width: 320\n    height: 200\n    singleImage: true\n    files:\n      0: Resources/Extended/Pedia/PAL_UFOPAEDIA/info-button-ufo.png\n  - type: Pathfinding\n    files:\n      0: Resources/Pathfinding/Pathfinding.png\n    width: 384\n    height: 80\n    subX: 32\n    subY: 40\n  - type: Projectiles\n    width: 105\n    height: 33\n    subX: 3\n    subY: 3\n    files:\n      0: Resources/BulletSprites/BulletSprites.png\n  - type: TFTDReserve\n    width: 59\n    height: 24\n    singleImage: true\n    files:\n      0: Resources/UI/reserve.png\n  - type: KneelButton\n    width: 32\n    height: 32\n    subX: 32\n    subY: 16\n    files:\n      0: Resources/UI/kneelButton.png\n  - type: InvCopy\n    width: 32\n    height: 22\n    singleImage: true\n    files:\n      0: Resources/UI/invcopy.png\n  - type: InvCopyActive\n    width: 32\n    height: 22\n    singleImage: true\n    files:\n      0: Resources/UI/invcopy_active.png\n  - type: InvPaste\n    width: 32\n    height: 22\n    singleImage: true\n    files:\n      0: Resources/UI/invpaste.png\n  - type: InvPasteEmpty\n    width: 32\n    height: 22\n    singleImage: true\n    files:\n      0: Resources/UI/invpaste_empty.png\n  - type: BIGOBS.PCK\n    width: 64\n    height: 96\n    subX: 32\n    subY: 48\n    files:\n      58: Resources/Weapons/Terror.png\n  - type: BIGOBS.PCK\n    width: 32\n    height: 48\n    files:\n      57: Resources/Weapons/Zombie.png\n  - type: GlobeMarkers\n    width: 27\n    height: 3\n    subX: 3\n    subY: 3\n    files:\n      0: Resources/UI/globe_ufo.png\n  - type: WpnActive\n    width: 36\n    height: 52\n    singleImage: true\n    files:\n      0: Resources/UI/WpnActive.png\n"
  },
  {
    "path": "bin/standard/xcom1/facilities.rul",
    "content": "facilities:\n  - type: STR_ACCESS_LIFT\n    spriteShape: 2\n    spriteFacility: 17\n    lift: true\n    buildCost: 300000\n    buildTime: 1\n    monthlyCost: 4000\n    mapName: XBASE_00\n  - type: STR_LIVING_QUARTERS\n    spriteShape: 1\n    spriteFacility: 18\n    buildCost: 400000\n    buildTime: 16\n    monthlyCost: 10000\n    personnel: 50\n    mapName: XBASE_01\n  - type: STR_LABORATORY\n    spriteShape: 1\n    spriteFacility: 19\n    buildCost: 750000\n    buildTime: 26\n    monthlyCost: 30000\n    labs: 50\n    mapName: XBASE_02\n  - type: STR_WORKSHOP\n    spriteShape: 1\n    spriteFacility: 20\n    buildCost: 800000\n    buildTime: 32\n    monthlyCost: 35000\n    workshops: 50\n    mapName: XBASE_03\n  - type: STR_SMALL_RADAR_SYSTEM\n    spriteShape: 2\n    spriteFacility: 21\n    buildCost: 500000\n    buildTime: 12\n    monthlyCost: 10000\n    radarRange: 1695\n    radarChance: 10\n    mapName: XBASE_04\n  - type: STR_LARGE_RADAR_SYSTEM\n    spriteShape: 1\n    spriteFacility: 22\n    buildCost: 800000\n    buildTime: 25\n    monthlyCost: 15000\n    radarRange: 2577\n    radarChance: 20\n    mapName: XBASE_05\n  - type: STR_MISSILE_DEFENSES\n    spriteShape: 2\n    spriteFacility: 23\n    buildCost: 200000\n    buildTime: 16\n    monthlyCost: 5000\n    defense: 500\n    hitRatio: 50\n    fireSound: 5\n    hitSound: 10\n    mapName: XBASE_06\n  - type: STR_GENERAL_STORES\n    spriteShape: 1\n    spriteFacility: 24\n    buildCost: 150000\n    buildTime: 10\n    monthlyCost: 5000\n    storage: 50\n    mapName: XBASE_07\n  - type: STR_ALIEN_CONTAINMENT\n    spriteShape: 1\n    spriteFacility: 25\n    buildCost: 400000\n    buildTime: 18\n    monthlyCost: 15000\n    aliens: 10\n    mapName: XBASE_08\n  - type: STR_LASER_DEFENSES\n    requires:\n      - STR_LASER_DEFENSE\n    spriteShape: 3\n    spriteFacility: 26\n    buildCost: 400000\n    buildTime: 24\n    monthlyCost: 10000\n    defense: 600\n    hitRatio: 60\n    fireSound: 8\n    hitSound: 10\n    mapName: XBASE_09\n  - type: STR_PLASMA_DEFENSES\n    requires:\n      - STR_PLASMA_DEFENSE\n    spriteShape: 3\n    spriteFacility: 27\n    buildCost: 600000\n    buildTime: 34\n    monthlyCost: 12000\n    defense: 900\n    hitRatio: 70\n    fireSound: 9\n    hitSound: 10\n    mapName: XBASE_10\n  - type: STR_FUSION_BALL_DEFENSES\n    requires:\n      - STR_FUSION_DEFENSE\n    spriteShape: 3\n    spriteFacility: 28\n    buildCost: 800000\n    buildTime: 34\n    monthlyCost: 14000\n    defense: 1200\n    hitRatio: 80\n    fireSound: 7\n    hitSound: 10\n    mapName: XBASE_11\n  - type: STR_GRAV_SHIELD\n    requires:\n      - STR_GRAV_SHIELD\n    grav: true\n    spriteShape: 2\n    spriteFacility: 29\n    buildCost: 1200000\n    buildTime: 38\n    monthlyCost: 15000\n    mapName: XBASE_12\n  - type: STR_MIND_SHIELD\n    requires:\n      - STR_MIND_SHIELD\n    mind: true\n    spriteShape: 2\n    spriteFacility: 30\n    buildCost: 1300000\n    buildTime: 33\n    monthlyCost: 5000\n    mapName: XBASE_13\n  - type: STR_PSIONIC_LABORATORY\n    requires:\n      - STR_PSI_LAB\n    spriteShape: 1\n    spriteFacility: 31\n    buildCost: 750000\n    buildTime: 24\n    monthlyCost: 16000\n    psiLabs: 10\n    mapName: XBASE_14\n  - type: STR_HYPER_WAVE_DECODER\n    requires:\n      - STR_HYPER_WAVE_DECODER\n    hyper: true\n    spriteShape: 2\n    spriteFacility: 32\n    buildCost: 1400000\n    buildTime: 26\n    monthlyCost: 30000\n    radarRange: 2759\n    radarChance: 100\n    mapName: XBASE_15\n  - type: STR_HANGAR\n    spriteShape: 9\n    spriteFacility: 9\n    size: 2\n    buildCost: 200000\n    buildTime: 25\n    monthlyCost: 25000\n    crafts: 1\n    storage: 5 #OXCE bonus because of change in handling craft storage\n    storageTiles: [[-1, -1, -1]]\n    mapName: XBASE_16"
  },
  {
    "path": "bin/standard/xcom1/globe.rul",
    "content": "globe:\n  data: GEODATA/WORLD.DAT\n  oceanPalette: 12\n  countryColor: 239\n  cityColor: 138\n  baseColor: 133\n  lineColor: 162\n  polylines:\n    - [68.125, -23.625, 71, -24.375, 69.5, -27, 70.375, -28.125, 70.75, -27.625, 74.625, -31, 74.125, -34.875, 77.875, -35.375, 79.125, -30.875, 80.875, -30.375, 80, -28.875, 87.75, -26.375, 88.25, -28, 88.875, -28.125, 89, -26.75, 91.875, -26.875, 91.625, -28, 96, -29.625, 97.125, -27.25, 92.625, -22.125, 92.375, -25, 89.875, -25.25, 89.625, -26.375, 88.375, -26.5, 88, -25.75, 89.125, -21.375]\n    - [351.25, -41.625, 353.875, -41.625, 352.375, -37]\n    - [358.25, -43.5, 0.625, -42.125, 3.25, -42.5]\n    - [7.375, -43.625, 7, -45.875, 5.875, -46.25, 7.5, -47.5, 8.25, -48.875, 6.375, -49.5, 4.125, -49.875, 2.875, -50.75]\n    - [7, -45.875, 8.5, -46.5, 9.125, -45.875, 12.125, -47, 13.75, -46.5, 13.75, -45.5]\n    - [6.375, -49.5, 5.875, -52, 6.75, -51.875, 7, -53.75]\n    - [8, -55, 10.375, -54.625]\n    - [14.25, -54, 15, -50.875, 12.25, -50.25, 13.875, -48.875, 13.125, -47.5, 7.5, -47.5]\n    - [2.625, -6.25, 2.75, -8.5, 3.75, -10.625, 4, -13.625, 5.625, -14, 7, -12.875, 9.75, -12.75, 13.25, -13.5, 14.75, -12.125, 11.25, -6.5, 10.125, -7.25, 8.5, -4.375]\n    - [25.125, -31.75, 25, -22, 34.125, -22, 36, -23.5]\n    - [33.875, -31.375, 35.5, -28.25]\n    - [16.25, 28.625, 20, 28.375, 20, 24.875, 20.75, 26.875, 23.375, 25.25, 25.625, 25.75, 29.25, 22.125, 31.25, 22.375, 32, 26.875, 33, 26.625]\n    - [307.25, 33.25, 302.5, 30, 306, 25.75, 302, 22.125, 301.75, 16.25, 294.75, 10, 289.625, 11.125, 286.25, 8.25, 287.375, 5, 290.125, 4.375, 290.25, -1.75, 296.875, -2.125, 295.375, -4, 299.25, -5.375, 301.25, -1.125, 307, -1.875, 308.625, -4.25]\n    - [235, -48.875, 255, -48.875, 265, -49, 270.375, -48]\n    - [293.125, -44.5, 291.375, -47.25, 288.375, -45, 285, -45, 283.625, -44.125]\n    - [219, -69.625, 219, -60.375, 230, -56, 226.875, -54.375]\n    - [242.875, -32.625, 253.625, -31.75, 256.75, -28.875, 258.625, -29.75, 261, -26.375, 263, -26.125]\n    - [276.5, -41.75, 277.875, -43]\n    - [275.375, -46.625, 276.625, -45.875]\n    - [31.25, -69.875, 31.5, -62.875, 28.125, -60.25]\n    - [28, -59.75, 28.125, -56.25, 32.625, -53.5, 31.75, -52.125, 40, -49.5, 38.125, -46.875]\n    - [39.75, -43.75, 49.125, -41.875]\n    - [49.375, -46.125, 47.625, -50.375, 60, -50.75, 61.375, -54.125, 68.875, -55.375, 76.875, -54.5, 80, -50.75, 88, -49.125, 98, -50, 98.875, -52.125, 110, -49.25, 116.75, -49.875, 119.25, -50, 120.125, -52.875, 125.875, -53, 127.875, -49.625, 134.5, -48.25, 133, -45, 131, -44.875, 130.625, -42.125, 124.25, -40]\n    - [107.875, -21.5, 105.625, -23.375, 101.75, -21.25, 99.125, -22.125, 98.875, -24.25, 97.5, -24, 98.875, -27.375, 97.125, -27.25]\n    - [91.625, -28, 88.875, -28.125]\n    - [88.25, -28, 80.875, -30.375]\n    - [77.875, -35.375, 73.375, -39.375, 80.5, -42.25, 80, -45, 82.5, -45.125, 82.875, -47.25, 85.75, -47.125, 86.375, -49.125, 88, -49.125, 90.625, -45.25, 96.25, -42.75, 105, -41.5, 112, -43.625, 112.125, -45, 119.875, -46.75, 115.75, -47.75, 116.75, -49.875]\n  textures:\n    - id: 0\n      terrain:\n        - name: FOREST\n          area: [0, 360, -90, 0]\n        - name: JUNGLE\n          area: [0, 360, 0, 90]\n    - id: 1\n      terrain:\n        - name: CULTA\n    - id: 2\n      terrain:\n        - name: CULTA\n    - id: 3\n      terrain:\n        - name: CULTA\n    - id: 4\n      terrain:\n        - name: CULTA\n    - id: 5\n      terrain:\n        - name: MOUNT\n    - id: 6\n      terrain:\n        - name: FOREST\n          area: [0, 360, -90, 0]\n        - name: JUNGLE\n          area: [0, 360, 0, 90]\n    - id: 7\n      terrain:\n        - name: DESERT\n    - id: 8\n      terrain:\n        - name: DESERT\n    - id: 9\n      terrain:\n        - name: POLAR\n    - id: 10\n      terrain:\n        - name: FOREST\n          area: [0, 360, -90, 0]\n        - name: JUNGLE\n          area: [0, 360, 0, 90]\n    - id: 11\n      terrain:\n        - name: FOREST\n          area: [0, 360, -90, 0]\n        - name: JUNGLE\n          area: [0, 360, 0, 90]\n    - id: 12\n      terrain:\n        - name: POLAR\n    - id: -1\n      deployments:\n        STR_TERROR_MISSION: 100"
  },
  {
    "path": "bin/standard/xcom1/interfaces.rul",
    "content": "interfaces:\n  - type: mainMenu\n    backgroundImage: BACK01.SCR\n    music: GMSTORY\n    elements:\n      - id: palette\n        color: 0     # brown\n      - id: window\n        color: 133   # minty green\n      - id: text\n        color: 138   # yellow\n      - id: button\n        color: 133   # minty green\n      - id: battlescapeTheme\n        color: -1\n        color2: -1\n        border: 0\n  - type: tests\n    backgroundImage: BACK05.SCR\n    elements:\n      - id: palette\n        color: 0     # brown\n      - id: window\n        color: 133   # minty green\n      - id: heading\n        color: 239   # bright green\n      - id: text\n        color: 138   # yellow\n      - id: frames\n        color: 239   # bright green\n      - id: button1\n        color: 239   # bright green\n      - id: button2\n        color: 133   # minty green\n  - type: newBattleMenu\n    backgroundImage: BACK01.SCR\n    elements:\n      - id: palette\n        color: 0     # brown\n      - id: window\n        color: 133   # minty green\n      - id: heading\n        color: 239   # bright green\n      - id: text\n        color: 138   # yellow\n      - id: frames\n        color: 239   # bright green\n      - id: button1\n        color: 239   # bright green\n      - id: button2\n        color: 133   # minty green\n      - id: list\n        color: 133   # minty green\n        color2: 138  # yellow\n        border: 239  # bright green\n  - type: newGameMenu\n    backgroundImage: BACK01.SCR\n    elements:\n      - id: palette\n        color: 0     # brown\n      - id: window\n        color: 133   # minty green\n      - id: text\n        color: 138   # yellow\n      - id: ironman\n        color: 138   # yellow\n      - id: button\n        color: 133   # minty green\n  - type: endGameStatistics\n    backgroundImage: BACK01.SCR\n    elements:\n      - id: palette\n        color: 0     # brown\n      - id: window\n        color: 133   # minty green\n      - id: text\n        color: 239   # bright green\n        color2: 138  # yellow\n      - id: list\n        color: 138   # yellow\n        color2: 133  # minty green\n        border: 133  # minty green\n      - id: button\n        color: 133   # minty green\n  - type: optionsMenu\n    backgroundImage: BACK01.SCR\n    elements:\n      - id: palette\n        color: 0     # brown\n      - id: window\n        color: 133   # minty green\n      - id: tooltip\n        color: 133   # minty green\n        color2: 138  # yellow\n      - id: button\n        color: 133   # minty green\n      - id: confirmDefaults\n        color: 138   # yellow\n      - id: confirmVideo\n        color: 239   # bright green\n  - type: videoMenu\n    elements:\n      - id: text\n        color: 138   # yellow\n      - id: resolution\n        color: 239   # bright green\n      - id: button\n        color: 239   # bright green\n  - type: audioMenu\n    elements:\n      - id: text\n        color: 138   # yellow\n      - id: button\n        color: 239   # bright green\n  - type: controlsMenu\n    elements:\n      - id: button\n        color: 239   # bright green\n      - id: optionLists\n        color: 138   # yellow\n        color2: 239  # bright green\n        border: 133  # minty green\n  - type: geoscapeMenu\n    elements:\n      - id: text\n        color: 138   # yellow\n      - id: button\n        color: 239   # bright green\n  - type: battlescapeMenu\n    elements:\n      - id: text\n        color: 138   # yellow\n      - id: button\n        color: 239   # bright green\n  - type: advancedMenu\n    elements:\n      - id: button\n        color: 239   # bright green\n      - id: optionLists\n        color: 138   # yellow\n        color2: 239  # bright green\n        border: 133  # minty green\n      - id: disabledUserOption\n        color: 100   # grey\n  - type: foldersMenu\n    elements:\n      - id: text1\n        color: 239   # bright green\n      - id: text2\n        color: 138   # yellow\n  - type: modsMenu\n    backgroundImage: BACK01.SCR\n    elements:\n      - id: palette\n        color: 0     # brown\n      - id: window\n        color: 133   # minty green\n      - id: optionLists\n        color: 138   # yellow\n        border: 133  # minty green\n      - id: text\n        color: 138   # yellow\n      - id: tooltip\n        color: 133   # minty green\n      - id: button1\n        color: 239   # bright green\n      - id: button2\n        color: 133   # minty green\n  - type: modsWindow\n    elements:\n      - id: palette\n        color: 0     # brown\n      - id: window\n        color: 239   # bright green\n      - id: heading\n        color: 239   # bright green\n      - id: text\n        color: 138   # yellow\n      - id: button1\n        color: 239   # bright green\n      - id: button2\n        color: 133   # minty green\n  - type: saveMenus\n    backgroundImage: BACK01.SCR\n    elements:\n      - id: palette\n        color: 6     # oxide\n      - id: window\n        color: 133   # minty green\n      - id: text\n        color: 239   # bright green\n        color2: 138  # yellow\n      - id: list\n        color: 138   # yellow\n        color2: 133  # minty green\n        border: 133  # minty green\n      - id: button\n        color: 133   # minty green\n      - id: confirmLoad\n        color: 239   # bright green\n      - id: confirmDelete\n        color: 138   # yellow\n  - type: pauseMenu\n    backgroundImage: BACK01.SCR\n    elements:\n      - id: palette\n        color: 0     # brown\n      - id: window\n        color: 239   # bright green\n      - id: text\n        color: 239   # bright green\n      - id: button\n        color: 239   # bright green\n  - type: noteMenu\n    backgroundImage: BACK01.SCR\n    elements:\n      - id: palette\n        color: 6     # oxide\n      - id: window\n        color: 133   # minty green\n      - id: text\n        color: 239   # bright green\n        color2: 138  # yellow\n      - id: list\n        color: 138   # yellow\n        color2: 133  # minty green\n        border: 133  # minty green\n      - id: button\n        color: 133   # minty green\n  - type: errorMessages\n    elements:\n      - id: geoscapePalette\n        color: 6   # oxide\n      - id: battlescapePalette\n        color: -1 # greyscale\n      - id: geoscapeColor\n        color: 138   # yellow\n      - id: battlescapeColor\n        color: 0    # white\n  - type: geoCraft\n    backgroundImage: BACK12.SCR\n    elements:\n      - id: palette\n        color: 4     # aqua\n        color2: 6    # oxide\n      - id: window\n        color: 239   # bright green\n      - id: text1\n        color: 239   # bright green\n        color2: 138  # yellow\n        border: 133  # minty green\n      - id: text2\n        color: 133   # minty green\n        color2: 138  # yellow\n        border: 133  # minty green\n      - id: text3\n        color: 239   # bright green\n        color2: 133  # minty green\n        border: 239  # bright green\n      - id: button\n        color: 133   # minty green\n      - id: list\n        color: 239   # bright green\n        color2: 138  # yellow\n        border: 133  # minty green\n  - type: selectMusicTrack\n    backgroundImage: BACK01.SCR\n    elements:\n      - id: palette\n        color: 0     # brown\n      - id: window\n        color: 239   # bright green\n      - id: text\n        color: 138   # yellow\n      - id: list\n        color: 133   # minty green\n        color2: 138  # yellow\n        border: 239  # bright green\n      - id: button\n        color: 133   # minty green\n  - type: dogfightExperience\n    backgroundImage: BACK01.SCR\n    elements:\n      - id: palette\n        color: 0     # brown\n      - id: window\n        color: 239   # bright green\n      - id: text1\n        color: 239   # bright green\n        color2: 138  # yellow\n        border: 133  # minty green\n      - id: text2\n        color: 133   # minty green\n        color2: 138  # yellow\n        border: 133  # minty green\n      - id: button\n        color: 133   # minty green\n      - id: list\n        color: 239   # bright green\n        color2: 138  # yellow\n        border: 133  # minty green\n  - type: intercept\n    backgroundImage: BACK12.SCR\n    elements:\n      - id: palette\n        color: 4     # aqua\n        color2: 6    # oxide\n      - id: window\n        color: 239   # bright green\n      - id: text1\n        color: 239   # bright green\n        color2: 138  # yellow\n        border: 133  # minty green\n      - id: text2\n        color: 133   # minty green\n        color2: 138  # yellow\n        border: 133  # minty green\n      - id: button\n        color: 133   # minty green\n      - id: list\n        color: 239   # bright green\n        color2: 138  # yellow\n        border: 133  # minty green\n      - id: disabled\n        color: 100   # grey\n  - type: ufoTracker\n    backgroundImage: BACK12.SCR\n    elements:\n      - id: palette\n        color: 4     # aqua\n        color2: 6    # oxide\n      - id: window\n        color: 239   # bright green\n      - id: text1\n        color: 239   # bright green\n        color2: 138  # yellow\n        border: 133  # minty green\n      - id: text2\n        color: 133   # minty green\n        color2: 138  # yellow\n        border: 133  # minty green\n      - id: button\n        color: 133   # minty green\n      - id: list\n        color: 239   # bright green\n        color2: 138  # yellow\n        border: 133  # minty green\n  - type: craftPatrol\n    backgroundImage: BACK12.SCR\n    elements:\n      - id: palette\n        color: 4     # aqua\n        color2: 6    # oxide\n      - id: window\n        color: 239   # bright green\n      - id: text1\n        color: 239   # bright green\n        color2: 138  # yellow\n        border: 133  # minty green\n      - id: button\n        color: 133   # minty green\n  - type: craftError\n    backgroundImage: BACK12.SCR\n    elements:\n      - id: palette\n        color: 4     # aqua\n        color2: 6    # oxide\n      - id: window\n        color: 239   # bright green\n      - id: text1\n        color: 239   # bright green\n        color2: 138  # yellow\n        border: 133  # minty green\n      - id: button\n        color: 133   # minty green\n  - type: craftPilotError\n    backgroundImage: BACK12.SCR\n    elements:\n      - id: palette\n        color: 4     # aqua\n        color2: 6    # oxide\n      - id: window\n        color: 239   # bright green\n      - id: text1\n        color: 239   # bright green\n        color2: 138  # yellow\n        border: 133  # minty green\n      - id: button\n        color: 133   # minty green\n  - type: targetInfo\n    backgroundImage: BACK01.SCR\n    elements:\n      - id: palette\n        color: 0     # brown\n      - id: window\n        color: 138   # yellow\n      - id: text1\n        color: 239   # bright green\n      - id: text2\n        color: 138  # yellow\n      - id: button\n        color: 133   # minty green\n  - type: confirmDestination\n    backgroundImage: BACK12.SCR\n    elements:\n      - id: palette\n        color: 4     # aqua\n        color2: 6    # oxide\n      - id: window\n        color: 239   # bright green\n      - id: text\n        color: 239   # bright green\n        color2: 138  # yellow\n        border: 133  # minty green\n      - id: button\n        color: 133   # minty green\n  - type: confirmCydonia\n    backgroundImage: BACK12.SCR\n    elements:\n      - id: palette\n        color: 5     # red\n      - id: window\n        color: 133   # minty green\n      - id: button\n        color: 133   # minty green\n      - id: text\n        color: 138   # yellow\n  - type: confirmLanding\n    backgroundImage: BACK15.SCR\n    elements:\n      - id: palette\n        color: 3     # pink\n      - id: window\n        color: 133   # minty green\n      - id: text\n        color: 133   # minty green\n        color2: 138  # yellow\n      - id: button\n        color: 133   # minty green\n  - type: lowFuel\n    backgroundImage: BACK12.SCR\n    elements:\n      - id: palette\n        color: 4     # aqua\n      - id: text\n        color: 138  # yellow\n      - id: window\n        color: 239   # bright green\n      - id: button\n        color: 133   # minty green\n  - type: UFOInfo\n    backgroundImage: BACK15.SCR\n    elements:\n      - id: palette\n        color: 7     # dark blue/purple\n        color2: 2    # red/orange\n      - id: window\n        color: 133   # minty green\n      - id: text\n        color: 133   # minty green\n        color2: 138  # yellow\n      - id: button\n        color: 133   # minty green\n  - type: UFOLost\n    backgroundImage: BACK15.SCR\n    elements:\n      - id: palette\n        color: 7     # dark blue/purple\n        color2: 2    # red/orange\n      - id: window\n        color: 133   # minty green\n      - id: text\n        color: 133   # minty green\n        color2: 138  # yellow\n      - id: button\n        color: 133   # minty green\n  - type: multipleTargets\n    backgroundImage: BACK15.SCR\n    elements:\n      - id: palette\n        color: 7     # dark blue/purple\n        color2: 2    # red/orange\n      - id: window\n        color: 133   # minty green\n      - id: text\n        color: 133   # minty green\n        color2: 138  # yellow\n      - id: button\n        color: 133   # minty green\n  - type: baseDestroyed\n    backgroundImage: BACK15.SCR\n    elements:\n      - id: palette\n        color: 7     # dark blue/purple\n        color2: 2    # red/orange\n      - id: window\n        color: 133   # minty green\n      - id: text\n        color: 133   # minty green\n        color2: 138  # yellow\n      - id: button\n        color: 133   # minty green\n  - type: dogfightInfo\n    backgroundImage: BACK15.SCR\n    elements:\n      - id: palette\n        color: 0     # brown\n      - id: window\n        color: 239   # bright green\n      - id: text\n        color: 138   # yellow\n      - id: button\n        color: 133   # minty green\n  - type: baseDefense\n    backgroundImage: BACK04.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 2     # red/orange\n      - id: window\n        color: 246   # purple\n      - id: text\n        color: 218   # blue\n      - id: button\n        color: 218   # blue\n  - type: baseDefense_geo\n    backgroundImage: BACK04.SCR\n    elements:\n      - id: palette\n        color: 2     # red/orange\n      - id: window\n        color: 133   # minty green\n      - id: text\n        color: 239   # bright green\n        color2: 138  # yellow\n      - id: button\n        color: 133   # minty green\n  - type: terrorSite\n    elements:\n      - id: palette\n        color: 3     # pink\n      - id: window\n        color: 133   # minty green\n      - id: text\n        color: 133   # minty green\n      - id: button\n        color: 133   # minty green\n  - type: alienBase\n    backgroundImage: BACK13.SCR\n    elements:\n      - id: palette\n        color: 3     # pink\n      - id: window\n        color: 239   # bright green\n      - id: text\n        color: 133   # minty green\n      - id: button\n        color: 138   # yellow\n  - type: itemsArriving\n    backgroundImage: BACK13.SCR\n    elements:\n      - id: palette\n        color: 6     # oxide\n      - id: window\n        color: 133   # minty green\n      - id: text1\n        color: 133   # minty green\n      - id: text2\n        color: 138   # yellow\n        border: 133  # minty green\n      - id: button\n        color: 133   # minty green\n  - type: geoResearch\n    backgroundImage: BACK05.SCR\n    elements:\n      - id: palette\n        color: 0     # brown\n      - id: window\n        color: 239   # bright green\n      - id: text1\n        color: 239   # bright green\n      - id: text2\n        color: 138   # yellow\n      - id: button\n        color: 133   # minty green\n  - type: geoResearchComplete\n    backgroundImage: BACK05.SCR\n    elements:\n      - id: palette\n        color: 0     # brown\n      - id: window\n        color: 239   # bright green\n      - id: text1\n        color: 239   # bright green\n      - id: text2\n        color: 138   # yellow\n      - id: button\n        color: 133   # minty green\n  - type: geoResearchRequired\n    backgroundImage: BACK05.SCR\n    elements:\n      - id: palette\n        color: 0     # brown\n      - id: window\n        color: 239   # bright green\n      - id: text1\n        color: 239   # bright green\n      - id: text2\n        color: 138   # yellow\n      - id: button\n        color: 133   # minty green\n  - type: trainingFinished\n    backgroundImage: BACK02.SCR\n    elements:\n      - id: palette\n        color: 6     # oxide\n      - id: window\n        color: 239   # bright green\n      - id: text1\n        color: 239   # bright green\n      - id: text2\n        color: 138   # yellow\n      - id: button\n        color: 133   # minty green\n  - type: geoNewCraft\n    backgroundImage: BACK13.SCR\n    elements:\n      - id: palette\n        color: 6     # oxide\n      - id: window\n        color: 239   # bright green\n      - id: text1\n        color: 239   # bright green\n      - id: text2\n        color: 138   # yellow\n      - id: button\n        color: 133   # minty green\n  - type: geoNewFacility\n    backgroundImage: BACK13.SCR\n    elements:\n      - id: palette\n        color: 6     # oxide\n      - id: window\n        color: 239   # bright green\n      - id: text1\n        color: 239   # bright green\n      - id: text2\n        color: 138   # yellow\n      - id: button\n        color: 133   # minty green\n  - type: geoNewItem\n    backgroundImage: BACK13.SCR\n    elements:\n      - id: palette\n        color: 6     # oxide\n      - id: window\n        color: 239   # bright green\n      - id: text1\n        color: 239   # bright green\n      - id: text2\n        color: 138   # yellow\n      - id: button\n        color: 133   # minty green\n  - type: geoManufacture\n    backgroundImage: BACK17.SCR\n    elements:\n      - id: palette\n        color: 6     # oxide\n      - id: window\n        color: 239   # bright green\n      - id: text1\n        color: 239   # bright green\n      - id: text2\n        color: 138   # yellow\n      - id: button\n        color: 133   # minty green\n  - type: geoManufactureComplete\n    backgroundImage: BACK17.SCR\n    elements:\n      - id: palette\n        color: 6     # oxide\n      - id: window\n        color: 239   # bright green\n      - id: text1\n        color: 239   # bright green\n      - id: text2\n        color: 138   # yellow\n      - id: button\n        color: 133   # minty green\n      - id: list\n        color: 138   # yellow\n        color2: 239  # bright green\n        border: 133  # minty green\n  - type: dogfight\n    elements:\n      - id: minimizeButtonDummy\n        color: 80\n      - id: standoffButton\n        color: 81\n      - id: cautiousButton\n        color: 81\n      - id: standardButton\n        color: 81\n      - id: aggressiveButton\n        color: 81\n      - id: disengageButton\n        color: 81\n      - id: ufoButton\n        color: 81\n      - id: text\n        color: 89\n      - id: numbers\n        color: 89\n      - id: distance\n        color: 89\n      - id: oceanIndicator\n        color: 80\n      - id: minimizedNumber\n        color: 80\n      - id: radarDetail\n        color: 108\n        color2: 111\n      - id: craftRange\n        color: 160\n        color2: 176\n      - id: radarRange\n        color: 112\n        color2: 128\n      - id: damageRange\n        color: 13\n        color2: 14\n      - id: disabledWeapon\n        color: 24\n        color2: 7\n      - id: disabledAmmo\n        color: 24\n      - id: shieldRange\n        color: 80\n        color2: 85\n      - id: previewTop\n        pos: [0, 96]\n        size: [160, 15]\n      - id: previewBot\n        pos: [0, 111]\n        size: [160, 29]\n      - id: previewMid\n        pos: [0, 140]\n        size: [160, 52]\n  - type: baseNaming\n    backgroundImage: BACK01.SCR\n    elements:\n      - id: palette\n        color: 0     # brown\n      - id: window\n        color: 133   # minty green\n      - id: text\n        color: 133   # minty green\n      - id: button\n        color: 133   # minty green\n  - type: monthlyReport\n    backgroundImage: BACK13.SCR\n    elements:\n      - id: palette\n        color: 3\n      - id: window\n        color: 239   # bright green\n        color2: 138  # yellow\n      - id: text1\n        color: 239   # bright green\n        color2: 138  # yellow\n      - id: text2\n        color: 138   # yellow\n      - id: button\n        color: 239   # bright green\n  - type: psiTraining\n    backgroundImage: BACK01.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 7     # violet\n      - id: window\n        color: 246   # purple\n      - id: text\n        color: 218   # light blue\n      - id: button1\n        color: 246   # purple\n      - id: button2\n        color: 218   # light blue\n  - type: martialTraining\n    backgroundImage: BACK02.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 7     # violet\n      - id: window\n        color: 246   # purple\n      - id: text\n        color: 218   # light blue\n      - id: button1\n        color: 246   # purple\n      - id: button2\n        color: 218   # light blue\n  - type: allocatePsi\n    backgroundImage: BACK01.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 7     # violet\n      - id: window\n        color: 218   # blue\n      - id: text\n        color: 218   # blue\n        color2: 208  # white\n      - id: list\n        color: 246   # purple\n        color2: 213  # yellow\n        border: 218  # blue\n      - id: button\n        color: 218   # blue\n  - type: allocateMartial\n    backgroundImage: BACK02.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 7     # violet\n      - id: window\n        color: 218   # blue\n      - id: text\n        color: 218   # blue\n        color2: 208  # white\n      - id: list\n        color: 246   # purple\n        color2: 213  # yellow\n        border: 218  # blue\n      - id: button\n        color: 218   # blue\n  - type: fundingWindow\n    backgroundImage: BACK13.SCR\n    elements:\n      - id: palette\n        color: 0     # brown\n      - id: window\n        color: 239   # bright green\n      - id: text1\n        color: 239   # bright green\n      - id: text2\n        color: 133   # minty green\n      - id: list\n        color: 239   # bright green\n        color2: 138  # yellow\n      - id: button\n        color: 239   # bright green\n  - type: oxceLinks\n    backgroundImage: BACK01.SCR\n    elements:\n      - id: palette\n        color: 0     # brown\n      - id: window\n        color: 239   # bright green\n      - id: text\n        color: 138   # yellow\n      - id: button\n        color: 133   # minty green\n  - type: geoscapeEvent\n    elements:\n      - id: palette\n        color: 0     # brown\n      - id: window\n        color: 239   # bright green\n      - id: text1\n        color: 138   # yellow\n        color2: 239  # bright green\n      - id: text2\n        color: 239   # bright green\n        color2: 133  # minty green\n      - id: list\n        color: 133   # minty green\n        color2: 138  # yellow\n        border: 239  # bright green\n      - id: button\n        color: 239   # bright green\n  - type: graphs\n    palette: PAL_GRAPHS\n    elements:\n      - id: text\n        color: 135   # red\n      - id: scale\n        color: 103   # minty green\n      - id: graph\n        color: 160   # green\n      - id: button\n        color: 151   # grey\n      - id: regionTotal\n        color: 133    # salmon (inverted button offset)\n        color2: 136  # also salmon (the line itself)\n      - id: countryTotal\n        color: 141    # magenta (inverted button offset)\n        color2: 144  # also magenta (the line itself)\n  - type: ufopaedia\n    backgroundImage: BACK01.SCR\n    elements:\n      - id: palette\n        color: 0     # brown\n      - id: window\n        color: 239   # bright green\n      - id: text\n        color: 138   # yellow\n      - id: list\n        color: 133\n        color2: 90\n        border: 239\n      - id: listExtended\n        color: 100\n        color2: 138\n        border: 239\n      - id: button1\n        color: 133   # minty green\n      - id: button2\n        color: 239   # bright green\n  - type: promotions\n    backgroundImage: BACK01.SCR\n    elements:\n      - id: palette\n        color: 0     # brown\n      - id: window\n        color: 239   # bright green\n      - id: heading\n        color: 133   # minty green\n      - id: text\n        color: 239   # bright green\n      - id: list\n        color: 138   # yellow\n      - id: button\n        color: 239   # bright green\n  - type: cannotReequip\n    backgroundImage: BACK01.SCR\n    elements:\n      - id: palette\n        color: 0     # brown\n      - id: window\n        color: 239   # bright green\n      - id: heading\n        color: 133   # minty green\n      - id: text\n        color: 239   # bright green\n      - id: list\n        color: 138   # yellow\n      - id: button\n        color: 133   # minty green\n  - type: debriefing\n    backgroundImage: BACK01.SCR\n    elements:\n      - id: palette\n        color: 0     # brown\n      - id: window\n        color: 239   # bright green\n      - id: heading\n        color: 133   # minty green\n      - id: text\n        color: 133   # minty green\n      - id: list\n        color: 239   # bright green\n        color2: 138  # yellow\n        custom: 254  # min=90, max=254\n      - id: totals\n        color: 133   # minty green\n      - id: button\n        color: 239   # bright green\n      - id: errorPalette\n        color: 0     # brown\n      - id: errorMessage\n        color: 133   # minty green\n  - type: commendations\n    backgroundImage: BACK01.SCR\n    elements:\n      - id: palette\n        color: 0     # brown\n      - id: window\n        color: 239   # bright green\n      - id: heading\n        color: 133   # minty green\n      - id: list\n        color: 239   # bright green\n        color2: 138  # yellow\n      - id: button\n        color: 239   # bright green\n  - type: commendationsLate\n    backgroundImage: BACK02.SCR\n    music: GMLOSE\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 7     # violet\n      - id: window\n        color: 218   # blue\n      - id: text\n        color: 218   # blue\n        color2: 208  # white\n      - id: list\n        color: 246   # purple\n        color2: 218  # blue\n        border: 218  # blue\n      - id: button\n        color: 218   # blue\n  - type: geoscape\n    backgroundImage: BACK01.SCR\n    elements:\n      - id: palette\n        color: 0     # brown\n        color2: 6\n      - id: textLoad\n        color: 133   # minty green\n      - id: button\n        color: 246   # light blue\n        color2: 245  # slightly lighter blue\n      - id: text\n        color: 244   # even lighter blue\n      - id: slackingIndicator\n        color: 244   # even lighter blue\n        color2: 133  # minty green\n        custom: -12  # above Intercept button\n      - id: trainingIndicator\n        color: 244   # even lighter blue\n        color2: 133  # minty green\n        custom: 4  # below standard visible area\n      - id: genericWindow\n        color: 239   # bright green\n      - id: genericText\n        color: 239   # bright green\n        color2: 138  # yellow\n        border: 133  # minty green\n      - id: genericButton1\n        color: 133   # minty green\n      - id: genericButton2\n        color: 239   # bright green\n      - id: errorPalette\n        color: 6     # brown\n      - id: errorMessage\n        color: 239   # bright green\n  - type: sellMenu\n    backgroundImage: BACK13.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 0     # brown\n      - id: window\n        color: 218   # blue\n      - id: text\n        color: 218   # blue\n        color2: 208  # white\n      - id: list\n        color: 218   # blue\n        color2: 208  # white\n      - id: ammoColor\n        color: 246   # purple\n      - id: button\n        color: 218   # blue\n      - id: button2\n        color: 241   # pink\n      - id: touchButton\n        color: 241   # pink\n  - type: dependencyTree\n    backgroundImage: BACK13.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 0     # brown\n      - id: window\n        color: 218   # blue\n      - id: text\n        color: 218   # blue\n        color2: 208  # white\n      - id: list\n        color: 218   # blue\n        color2: 241  # pink\n      - id: button\n        color: 218   # blue\n  - type: itemLocations\n    backgroundImage: BACK13.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 0     # brown\n      - id: window\n        color: 218   # blue\n      - id: text\n        color: 218   # blue\n        color2: 208  # white\n      - id: list\n        color: 208   # white\n        color2: 241  # pink\n      - id: button\n        color: 218   # blue\n  - type: buyMenu\n    backgroundImage: BACK13.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 0     # brown\n      - id: window\n        color: 218   # blue\n      - id: text\n        color: 218   # blue\n        color2: 208  # white\n      - id: list\n        color: 218   # blue\n        color2: 208  # white\n      - id: ammoColor\n        color: 246   # purple\n      - id: button\n        color: 218   # blue\n      - id: button2\n        color: 241   # pink\n      - id: touchButton\n        color: 241   # pink\n      - id: errorPalette\n        color: 0     # brown\n      - id: errorMessage\n        color: 241   # pink\n        color2: 246  # purple\n  - type: manageContainment\n    backgroundImage: BACK05.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 1     # burgundy\n      - id: window\n        color: 218   # blue\n      - id: text\n        color: 218   # blue\n        color2: 208  # white\n      - id: list\n        color: 208   # white\n        color2: 218  # blue\n        border: 218  # blue\n      - id: button\n        color: 218   # blue\n      - id: button2\n        color: 241   # pink\n      - id: touchButton\n        color: 241   # pink\n      - id: errorPalette\n        color: 6     # oxide\n      - id: errorMessage\n        color: 241   # pink\n  - type: globalContainmentMenu\n    backgroundImage: BACK05.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 1     # burgundy\n      - id: window\n        color: 218   # blue\n      - id: text\n        color: 218   # blue\n        color2: 208  # white\n      - id: list\n        color: 246   # purple\n        color2: 208  # white\n        border: 218  # blue\n      - id: button\n        color: 246   # purple\n  - type: transferBaseSelect\n    backgroundImage: BACK13.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 4     # dark green\n      - id: window\n        color: 213   # gold\n      - id: button\n        color: 213   # gold\n      - id: text\n        color: 213   # gold\n        color2: 208  # white\n      - id: list\n        color: 241   # pink\n        color2: 213  # gold\n  - type: transferMenu\n    backgroundImage: BACK13.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 0     # brown\n      - id: window\n        color: 218   # blue\n      - id: text\n        color: 218   # blue\n      - id: list\n        color: 218   # blue\n        color2: 208  # white\n      - id: ammoColor\n        color: 246   # purple\n      - id: button\n        color: 246   # purple\n      - id: button2\n        color: 241   # pink\n      - id: touchButton\n        color: 241   # pink\n      - id: errorPalette\n        color: 0     # brown\n      - id: errorMessage\n        color: 241   # pink\n  - type: transferConfirm\n    backgroundImage: BACK13.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 6     # oxide\n      - id: window\n        color: 213   # gold\n      - id: button\n        color: 246   # purple\n      - id: text\n        color: 218   # blue\n        color2: 241  # pink\n  - type: transferInfo\n    backgroundImage: BACK13.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 6     # oxide\n      - id: window\n        color: 246   # purple\n      - id: button\n        color: 246   # purple\n      - id: text\n        color: 246   # purple\n      - id: list\n        color: 218   # blue\n        border: 246  # purple\n  - type: selectFacility\n    backgroundImage: BACK05.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 6     # oxide\n      - id: window\n        color: 213   # gold\n      - id: button\n        color: 213   # gold\n      - id: text\n        color: 208   # white\n      - id: list\n        color: 213   # gold\n        color2: 208  # white\n  - type: placeFacility\n    backgroundImage: BACK01.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 6     # oxide\n      - id: window\n        color: 218   # blue\n      - id: button\n        color: 218   # blue\n      - id: text\n        color: 218   # blue\n      - id: numbers\n        color: 208   # white\n      - id: errorPalette\n        color: 0     # brown\n      - id: errorMessage\n        color: 241   # pink\n  - type: dismantleFacility\n    backgroundImage: BACK13.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 6     # oxide\n      - id: window\n        color: 241   # pink\n      - id: button\n        color: 246   # purple\n      - id: text\n        color: 218   # blue\n        color2: 208  # white\n  - type: manufactureMenu\n    backgroundImage: BACK17.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 6     # oxide\n      - id: window\n        color: 246   # purple\n      - id: text1\n        color: 246   # purple\n        color2: 208  # white\n      - id: text2\n        color: 241   # pink\n      - id: list\n        color: 218   # blue\n        border: 246  # purple\n      - id: button\n        color: 218   # blue\n  - type: globalManufactureMenu\n    backgroundImage: BACK17.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 6     # oxide\n      - id: window\n        color: 246   # purple\n      - id: text1\n        color: 246   # purple\n        color2: 208  # white\n      - id: text2\n        color: 241   # pink\n      - id: list\n        color: 218   # blue\n        color2: 208  # white\n        border: 246  # purple\n      - id: button\n        color: 218   # blue\n  - type: selectNewManufacture\n    backgroundImage: BACK17.SCR\n    parent: manufactureMenu\n    elements:\n      - id: window\n        color: 241   # pink\n      - id: text\n        color: 241   # pink\n      - id: list\n        color: 208   # white\n        color2: 218  # light blue\n        border: 241  # pink\n      - id: listExtended\n        color: 246   # purple\n        color2: 213  # gold\n      - id: button\n        color: 218   # blue\n      - id: button2\n        color: 213   # gold\n      - id: touchButton\n        color: 213   # gold\n      - id: catBox\n        color: 241   # pink\n  - type: allocateManufacture\n    backgroundImage: BACK17.SCR\n    parent: manufactureMenu\n    elements:\n      - id: window\n        color: 218   # blue\n      - id: text\n        color: 218   # blue\n        color2: 208  # white\n      - id: list\n        color: 218   # blue\n        color2: 208  # white\n      - id: button\n        color: 218   # blue\n  - type: manufactureInfo\n    backgroundImage: BACK17.SCR\n    parent: manufactureMenu\n    elements:\n      - id: window\n        color: 241   # pink\n      - id: text\n        color: 241   # pink\n        color2: 208  # white\n      - id: list\n        color: 218   # blue\n        color2: 208  # white\n      - id: button1\n        color: 241   # pink\n      - id: button2\n        color: 246   # purple\n  - type: researchMenu\n    backgroundImage: BACK05.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 1     # burgundy\n      - id: window\n        color: 218   # blue\n      - id: text\n        color: 218   # blue\n        color2: 208  # white\n      - id: list\n        color: 246   # purple\n        border: 218  # blue\n      - id: button\n        color: 246   # purple\n  - type: globalResearchMenu\n    backgroundImage: BACK05.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 1     # burgundy\n      - id: window\n        color: 218   # blue\n      - id: text\n        color: 218   # blue\n        color2: 208  # white\n      - id: list\n        color: 246   # purple\n        color2: 208  # white\n        border: 218  # blue\n      - id: button\n        color: 246   # purple\n  - type: globalResearchDiary\n    backgroundImage: BACK05.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 1     # burgundy\n      - id: window\n        color: 218   # blue\n      - id: text\n        color: 218   # blue\n        color2: 208  # white\n      - id: list\n        color: 246   # purple\n        color2: 208  # white\n        border: 218  # blue\n      - id: button\n        color: 246   # purple\n  - type: selectNewResearch\n    backgroundImage: BACK05.SCR\n    parent: researchMenu\n    elements:\n      - id: window\n        color: 218   # blue\n      - id: text\n        color: 218   # blue\n      - id: list\n        color: 208   # white\n        color2: 241  # pink\n        border: 218  # blue\n      - id: listExtended\n        color: 246   # purple\n        color2: 213  # gold\n      - id: button\n        color: 246   # purple\n      - id: button2\n        color: 213   # gold\n      - id: touchButton\n        color: 213   # gold\n  - type: allocateResearch\n    backgroundImage: BACK05.SCR\n    parent: researchMenu\n    elements:\n      - id: window\n        color: 213   # gold\n      - id: text\n        color: 213   # gold\n        color2: 208  # white\n      - id: button1\n        color: 213   # gold\n      - id: button2\n        color: 218   # blue\n  - type: techTreeViewer\n    backgroundImage: BACK05.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 1     # burgundy\n      - id: window\n        color: 218   # blue\n      - id: text\n        color: 218   # blue\n        color2: 208  # white\n      - id: list\n        color: 246   # purple\n        color2: 241  # pink\n        border: 218  # blue\n      - id: listExtended\n        color: 208   # white\n        color2: 213  # gold\n        border: 70   # grey\n      - id: button\n        color: 246   # purple\n  - type: techTreeSelect\n    backgroundImage: BACK05.SCR\n    parent: techTreeViewer\n    elements:\n      - id: window\n        color: 213   # gold\n      - id: text\n        color: 213   # gold\n        color2: 208  # white\n      - id: list\n        color: 246   # purple\n        color2: 241  # pink\n        border: 218  # blue\n      - id: button\n        color: 218   # blue\n  - type: baseInfo\n    palette: PAL_BASESCAPE\n    elements:\n      - id: text1\n        color: 241   # pink\n      - id: text2\n        color: 213   # gold\n      - id: numbers\n        color: 208   # white\n      - id: button\n        color: 246   # purple\n      - id: personnelBars\n        color: 16    # orange\n      - id: facilityBars\n        color: 48    # light green\n      - id: defenceBar\n        color: 32    # sorta red\n      - id: detectionBars\n        color: 128   # pale blue\n  - type: storesInfo\n    backgroundImage: BACK13.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 0     # brown\n      - id: window\n        color: 218   # blue\n      - id: text\n        color: 218   # blue\n      - id: list\n        color: 218   # blue\n      - id: button\n        color: 218   # blue\n  - type: costsInfo\n    backgroundImage: BACK13.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 6     # oxide\n      - id: window\n        color: 241   # pink\n      - id: text1\n        color: 241   # pink\n        color2: 218  # blue\n      - id: text2\n        color: 208   # white\n      - id: list\n        color: 218   # blue\n      - id: button\n        color: 241   # pink\n  - type: soldierList\n    backgroundImage: BACK02.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 2     # orange\n      - id: window\n        color: 241   # pink\n      - id: text1\n        color: 218   # blue\n      - id: text2\n        color: 241   # pink\n      - id: list\n        color: 218   # blue\n        color2: 246  # purple\n        border: 241  # pink\n      - id: button\n        color: 218   # blue\n  - type: soldierInfo\n    palette: PAL_BASESCAPE\n    elements:\n      - id: text1\n        color: 218   # blue\n        color2: 208  # white\n      - id: text2\n        color: 241   # pink\n      - id: numbers\n        color: 208   # white\n        color2: 208 \n      - id: button\n        color: 246   # purple\n      - id: barTUs\n        color: 52\n        color2: 56\n        border: 48\n      - id: barEnergy\n        color: 148\n        color2: 152\n        border: 144\n      - id: barHealth\n        color: 36\n        color2: 40\n        border: 32\n      - id: barBravery\n        color: 68\n        color2: 72\n        border: 64\n      - id: barReactions\n        color: 20\n        color2: 24\n        border: 16\n      - id: barFiring\n        color: 132\n        color2: 136\n        border: 128\n      - id: barThrowing\n        color: 164\n        color2: 168\n        border: 160\n      - id: barMelee\n        color: 68\n        color2: 72\n        border: 64\n      - id: barStrength\n        color: 84\n        color2: 88\n        border: 80\n      - id: barMana\n        color: 132\n        color2: 136\n        border: 128\n      - id: barPsiStrength\n        color: 180\n        color2: 184\n        border: 176\n      - id: barPsiSkill\n        color: 180\n        color2: 184\n        border: 176\n      - id: errorPalette\n        color: 0     # brown\n      - id: errorMessage\n        color: 241   # pink\n  - type: sackSoldier\n    backgroundImage: BACK13.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 6     # oxide\n      - id: window\n        color: 241   # pink\n      - id: text\n        color: 218   # blue\n      - id: button\n        color: 246   # purple\n  - type: soldierArmor\n    backgroundImage: BACK14.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 4     # green\n      - id: window\n        color: 218   # blue\n      - id: text\n        color: 213   # gold\n      - id: list\n        color: 208   # white\n        border: 213  # gold\n      - id: button\n        color: 213   # gold\n  - type: soldierTransform\n    backgroundImage: BACK14.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 4     # green\n      - id: window\n        color: 218   # blue\n      - id: text\n        color: 213   # gold\n      - id: list\n        color: 208   # white\n        border: 213  # gold\n      - id: button\n        color: 213   # gold\n  - type: soldierRank\n    backgroundImage: BACK14.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 4     # green\n      - id: window\n        color: 218   # blue\n      - id: text\n        color: 213   # gold\n      - id: list\n        color: 208   # white\n        color2: 246  # purple\n        border: 213  # gold\n      - id: button\n        color: 213   # gold\n  - type: soldierAvatar\n    backgroundImage: BACK14.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 4     # green\n      - id: window\n        color: 218   # blue\n      - id: text\n        color: 213   # gold\n      - id: list\n        color: 208   # white\n        border: 213  # gold\n      - id: button\n        color: 213   # gold\n  - type: soldierDiaryLight\n    backgroundImage: BACK14.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 4     # green\n      - id: window\n        color: 218   # blue\n      - id: text\n        color: 213   # gold\n      - id: list\n        color: 208   # white\n        border: 213  # gold\n      - id: button\n        color: 213   # gold\n  - type: soldierBonus\n    backgroundImage: BACK14.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 4     # green\n      - id: window\n        color: 218   # blue\n      - id: text\n        color: 213   # gold\n      - id: list\n        color: 208   # white\n        border: 213  # gold\n      - id: button\n        color: 213   # gold\n  - type: soldierMemorial\n    backgroundImage: BACK02.SCR\n    music: GMLOSE\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 7     # violet\n      - id: window\n        color: 218   # blue\n      - id: text\n        color: 218   # blue\n        color2: 208  # white\n      - id: list\n        color: 246   # purple\n        color2: 218  # blue\n        border: 218  # blue\n      - id: button\n        color: 218   # blue\n  - type: soldierDiary\n    backgroundImage: BACK02.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 7     # violet\n      - id: window\n        color: 241   # pink\n      - id: text1\n        color: 218   # blue\n      - id: text2\n        color: 241   # pink\n        color2: 218  # blue\n      - id: text3\n        color: 218   # blue\n      - id: list\n        color: 218   # blue\n        color2: 241   # pink\n        border: 241  # pink\n      - id: button\n        color: 246   # purple\n  - type: soldierDiaryPerformance\n    backgroundImage: BACK02.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 7     # violet\n      - id: window\n        color: 241   # pink\n      - id: text1\n        color: 218   # blue\n      - id: text2\n        color: 241   # pink\n        color2: 218  # blue\n      - id: list\n        color: 218   # blue\n        color2: 241   # pink\n        border: 241  # pink\n      - id: button\n        color: 246   # purple\n  - type: soldierDiaryMission\n    backgroundImage: BACK16.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 1     # burgundy\n      - id: window\n        color: 218   # blue\n      - id: text\n        color: 213   # gold\n        color2: 208  # white\n      - id: list\n        color: 208   # white\n        border: 213  # gold\n      - id: button\n        color: 213   # gold\n  - type: craftEquipment\n    backgroundImage: BACK04.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 2     # orange\n      - id: window\n        color: 241   # pink\n      - id: text\n        color: 241   # pink\n        color2: 208  # white\n      - id: button\n        color: 241   # pink\n      - id: button2\n        color: 218   # blue\n      - id: touchButton\n        color: 218   # blue\n      - id: list\n        color: 218   # blue\n        color2: 208  # white\n        border: 241  # pink\n      - id: ammoColor\n        color: 246   # purple\n      - id: errorPalette\n        color: 2     # orange\n      - id: errorMessage\n        color: 241   # pink\n  - type: craftEquipmentSave\n    backgroundImage: BACK04.SCR\n    parent: craftEquipment\n    elements:\n      - id: window\n        color: 241   # pink\n      - id: text\n        color: 241   # pink\n        color2: 208  # white\n      - id: button\n        color: 241   # pink\n      - id: list\n        color: 218   # blue\n        color2: 208  # white\n        border: 241  # pink\n  - type: craftEquipmentLoad\n    backgroundImage: BACK04.SCR\n    parent: craftEquipment\n    elements:\n      - id: window\n        color: 241   # pink\n      - id: text\n        color: 241   # pink\n        color2: 208  # white\n      - id: button\n        color: 241   # pink\n      - id: list\n        color: 218   # blue\n        color2: 208  # white\n        border: 241  # pink\n  - type: craftArmor\n    backgroundImage: BACK14.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 4     # aqua\n      - id: window\n        color: 218   # blue\n      - id: text\n        color: 218   # blue\n      - id: button\n        color: 218   # blue\n      - id: button2\n        color: 241   # pink\n      - id: touchButton\n        color: 241   # pink\n      - id: list\n        color: 218   # blue\n        color2: 208  # white\n      - id: otherCraft\n        color: 246   # purple\n  - type: craftInfo\n    backgroundImage: BACK14.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 3     # pink\n      - id: window\n        color: 218   # blue\n      - id: text1\n        color: 218   # blue\n        color2: 208  # white\n      - id: text2\n        color: 213   # gold\n      - id: text3\n        color: 218   # blue\n        color2: 213  # gold\n      - id: button\n        color: 218   # blue\n  - type: craftWeapons\n    backgroundImage: BACK14.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 4     # aqua\n      - id: window\n        color: 246   # purple\n      - id: text\n        color: 246   # purple\n        color2: 218  # blue\n      - id: list\n        color: 218   # blue\n      - id: button\n        color: 246   # purple\n      - id: errorPalette\n        color: 4     # aqua\n      - id: errorMessage\n        color: 246   # purple\n  - type: craftSoldiers\n    backgroundImage: BACK02.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 2     # orange\n      - id: window\n        color: 246   # purple\n      - id: text\n        color: 246   # purple\n        color2: 208  # white\n      - id: list\n        color: 218   # blue\n        color2: 208  # white\n        border: 246  # purple\n      - id: button\n        color: 218   # blue\n      - id: button2\n        color: 241   # pink\n      - id: touchButton\n        color: 241   # pink\n      - id: otherCraft\n        color: 246   # purple\n  - type: craftPilots\n    backgroundImage: BACK02.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 6     # oxide\n      - id: window\n        color: 241   # pink\n      - id: text1\n        color: 241   # pink\n        color2: 218  # blue\n      - id: text2\n        color: 208   # white\n      - id: list\n        color: 218   # blue\n      - id: button\n        color: 241   # pink\n  - type: craftPilotsSelect\n    backgroundImage: BACK02.SCR\n    parent: craftPilots\n    elements:\n      - id: window\n        color: 241   # pink\n      - id: text1\n        color: 241   # pink\n        color2: 218  # blue\n      - id: text2\n        color: 208   # white\n      - id: list\n        color: 218   # blue\n      - id: button\n        color: 241   # pink\n  - type: craftSelect\n    backgroundImage: BACK14.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 3     # pink\n      - id: window\n        color: 241   # pink\n      - id: text\n        color: 241   # pink\n      - id: list\n        color: 218   # blue\n        border: 241  # pink\n      - id: button\n        color: 218   # blue\n      - id: errorPalette\n        color: 0     # brown\n      - id: errorMessage\n        color: 241   # pink\n  - type: basescape\n    palette: PAL_BASESCAPE\n    elements:\n      - id: button\n        color: 213   # gold\n      - id: text1\n        color: 241   # pink\n      - id: text2\n        color: 246   # purple\n      - id: text3\n        color: 218   # blue\n      - id: textTooltip\n        color: 218   # blue\n      - id: baseView\n        color: 213   # gold   (time remaining)\n        color2: 16   # orange (selector color)\n      - id: trafficLights\n        color: 32    # red\n        color2: 144  # yellow\n        border: 48   # green\n        TFTDMode: false\n      - id: errorPalette\n        color: 6     # oxide\n      - id: errorMessage\n        color: 241   # pink\n      - id: miniBase\n        color: 48    # green\n        color2: 32   # red\n        border: 218  # blue\n  - type: battlescape\n    palette: PAL_BATTLESCAPE\n    elements:\n      - id: textLoad\n        color: 15\n      - id: textName\n        color: 128\n      - id: numTUs\n        color: 64\n      - id: numEnergy\n        color: 16\n      - id: numHealth\n        color: 32\n      - id: numMorale\n        color: 192\n      - id: barTUs\n        color: 64\n      - id: barEnergy\n        color: 16\n      - id: barHealth\n        color: 32\n        color2: 82\n      - id: barMorale\n        color: 192\n      - id: barMana\n        color: 208\n      - id: numAmmoLeft\n        color: 2\n      - id: numAmmoRight\n        color: 2\n      - id: textTooltip\n        color: -1\n      - id: buttonReserveNone\n        color: 67\n      - id: buttonReserveSnap\n        color: 35\n      - id: buttonReserveAimed\n        color: 35\n      - id: buttonReserveAuto\n        color: 35\n      - id: buttonReserveKneel\n        color: 35\n      - id: buttonZeroTUs\n        color: 35\n      - id: infoBoxOK\n        color: 15\n        color2: 27\n        border: 20\n      - id: infoBoxOKButton\n        color: 15\n      - id: infoBox\n        color: -1\n        color2: 10\n        border: 2\n      - id: infoBoxText\n        color: -1\n        color2: 14\n        border: 2\n      - id: grenadeMenu\n        color: 15\n        color2: 27\n        border: 20\n      # The usage of the following is hard-coded, these ones MUST be defined\n      - id: visibleUnits\n        pos: [300, -16]\n        color: 16\n      - id: squadsightUnits\n        color: 54\n      - id: woundedUnits\n        color: 134\n      - id: passingOutUnits\n        color: 198\n      - id: icons\n        size: [320, 56]\n      - id: numLayers\n        color: 15\n      - id: warning\n        color: 16\n        color2: 32\n      - id: messageWindows\n        color: -1\n        color2: 14\n        border: 7\n      - id: thinkingProgressBar\n        color: 33\n        color2: 65\n        border: 1\n      - id: optionLists\n        color: -1\n        color2: 14\n        border: -1\n      - id: disabledUserOption\n        color: 238\n      - id: messageWindowButtons\n        color: -1\n      - id: messageWindowBorder\n        color: -1\n      - id: actionMenu\n        color: -1\n        color2: 14\n        border: 3\n      - id: grenadeBackground\n        color: 24\n        color2: 28\n        border: 15\n      - id: medikitRed\n        color: 2\n      - id: medikitGreen\n        color: 4\n      - id: medikitBlue\n        color: 13\n      - id: medikitOrange\n        color: 6\n      - id: twoHandedRed\n        color: 36\n      - id: twoHandedGreen\n        color: 52\n  - type: briefing\n    elements:\n      - id: window\n        color: 239\n      - id: button\n        color: 133\n        color2: 133\n      - id: text\n        color: 133\n  - type: inventory\n    elements:\n      - id: textSlot\n        color: 64\n        color2: 16\n        pos: [65, 95]\n        size: [70, 9]\n      - id: textName\n        color: 64\n      - id: textTUs\n        color: 64\n        color2: 16\n      - id: textWeight\n        color: 64\n        color2: 16\n      - id: textStatLine1\n        custom: 1\n        color: 64\n        color2: 16\n      - id: textStatLine2\n        custom: 2\n        color: 64\n        color2: 16\n      - id: textStatLine3\n        custom: 3\n        color: 64\n        color2: 16\n      - id: textStatLine4\n        custom: 4\n        color: 64\n        color2: 16\n      - id: textItem\n        color: 48\n        color2: 16\n      - id: textAmmo\n        color: 64\n        color2: 16\n      # required\n      - id: textSlots\n        color: 63\n      - id: weight\n        color: 16     # gold (acceptable)\n        color2: 32    # red (overweight)\n      - id: grid\n        color: 8\n      - id: numStack\n        color: 66\n        color2: 32\n  - type: stats\n    elements:\n      - id: numMaxHealth\n        color: 144\n        pos: [278, 0]    # only X counts, Y is ignored (because it's dynamic)\n        custom: 2        # 0 + 1(=show also when current hp is equal to max hp) + 2(=show '/' prefix)\n      - id: textName\n        color: 64\n      - id: barTUs\n        color: 64\n      - id: barEnergy\n        color: 144\n      - id: barHealth\n        color: 32\n        color2: 82\n      - id: barWounds\n        color: 32\n      - id: barBravery\n        color: 192\n      - id: barMorale\n        color: 192\n      - id: barReactions\n        color: 144\n      - id: barFiring\n        color: 128\n      - id: barThrowing\n        color: 96\n      - id: barMelee\n        color: 224\n      - id: barStrength\n        color: 48\n      - id: barMana\n        color: 128\n      - id: barPsiStrength\n        color: 192\n      - id: barPsiSkill\n        color: 192\n      - id: barFrontArmor\n        color: 80\n      - id: barLeftArmor\n        color: 80\n      - id: barRightArmor\n        color: 80\n      - id: barRearArmor\n        color: 80\n      - id: barUnderArmor\n        color: 80\n      - id: button\n        color: 64\n      # required\n      - id: text\n        color: 48\n        color2: 144\n  - type: minimap\n    elements:\n      # required\n      - id: textLevel\n        color: 64\n      - id: emptySpace\n        color: 260\n  - type: medikit\n    elements:\n      - id: numPK\n        color: 16\n      - id: numStim\n        color: 16\n      - id: numHeal\n        color: 16\n      - id: textPart\n        color: 32\n      - id: numWounds\n        color: 32\n      - id: buttonEnd\n        pos: [220, 140]\n        size: [20, 20]\n  - type: systemMenu\n    elements:\n      - id: text\n        color: 138   # yellow\n      - id: button\n        color: 239   # bright green\n  - type: articleUnit\n    elements:\n      - id: button\n        color: 80    # light grey, 239 = grey\n      - id: title\n        color: 244   # light blue\n        color2: 239  # grey\n      - id: text\n        color: 239   # grey\n        color2: 244  # light blue\n      - id: list\n        color: 244   # light blue\n        color2: 239  # grey\n  - type: articleSoldier\n    elements:\n      - id: button\n        color: 80    # light grey, 239 = grey\n      - id: title\n        color: 244   # light blue\n        color2: 239  # grey\n      - id: text\n        color: 239   # grey\n        color2: 244  # light blue\n      - id: list\n        color: 244   # light blue\n        color2: 239  # grey\n  - type: articleText\n    elements:\n      - id: button\n        color: 80    # very light grey\n      - id: title\n        color: 244   # light blue\n      - id: text\n        color: 239   # grey\n        color2: 244  # light blue\n  - type: articleTextImage\n    elements:\n      - id: button\n        color: 83    # light grey\n      - id: title\n        color: 244   # light blue\n      - id: text\n        color: 239   # grey\n        color2: 244  # light blue\n  - type: articleArmor\n    elements:\n      - id: button\n        color: 15    # orange\n      - id: text\n        color: 239   # grey\n        color2: 244  # light blue\n      - id: list\n        color: 239   # grey\n        color2: 244  # light blue\n  - type: articleCraftWeapon\n    elements:\n      - id: button\n        color: 16    # orange\n      - id: text\n        color: 239   # grey\n        color2: 244  # light blue\n      - id: list\n        color: 239   # grey\n        color2: 244  # light blue\n  - type: articleItem\n    elements:\n      - id: button\n        color: 144   # orange\n      - id: text\n        color: 239   # grey\n        color2: 244  # light blue\n      - id: list\n        color: 239   # grey\n        color2: 244  # light blue\n      - id: ammoColor\n        color: 32    # red\n      #- id: ammoColorDTNone\n      #  color: 32    # red\n      #- id: ammoColorDTAP\n      #  color: 32    # red\n      #- id: ammoColorDTIN\n      #  color: 32    # red\n      #- id: ammoColorDTHE\n      #  color: 32    # red\n      #- id: ammoColorDTLaser\n      #  color: 32    # red\n      #- id: ammoColorDTPlasma\n      #  color: 32    # red\n      #- id: ammoColorDTStun\n      #  color: 32    # red\n      #- id: ammoColorDTMelee\n      #  color: 32    # red\n      #- id: ammoColorDTAcid\n      #  color: 32    # red\n      #- id: ammoColorDTSmoke\n      #  color: 32    # red\n      #- id: ammoColorDT10\n      #  color: 32    # red\n      #- id: ammoColorDT11\n      #  color: 32    # red\n      #- id: ammoColorDT12\n      #  color: 32    # red\n      #- id: ammoColorDT13\n      #  color: 32    # red\n      #- id: ammoColorDT14\n      #  color: 32    # red\n      #- id: ammoColorDT15\n      #  color: 32    # red\n      #- id: ammoColorDT16\n      #  color: 32    # red\n      #- id: ammoColorDT17\n      #  color: 32    # red\n      #- id: ammoColorDT18\n      #  color: 32    # red\n      #- id: ammoColorDT19\n      #  color: 32    # red\n  - type: articleTFTD\n    palette: PAL_UFOPAEDIA\n    backgroundImage: ExtendedPediaBackgroundPalUfopaedia\n    elements:\n      - id: button\n        color: 239      # grey (was 83: light grey)\n      - id: text\n        color: 239      # grey\n        color2: 244     # turquoise\n      - id: list\n        color: 239      # grey\n        color2: 244     # turquoise\n  - type: articleCraftTFTD\n    palette: PAL_UFOPAEDIA\n    backgroundImage: ExtendedPediaBackgroundPalUfopaedia\n    elements:\n      - id: button\n        color: 239      # grey\n      - id: text\n        color: 239      # grey\n        color2: 244     # turquoise\n      - id: list\n        color: 239      # grey\n        color2: 244     # turquoise\n  - type: articleCraftWeaponTFTD\n    palette: PAL_BATTLEPEDIA\n    backgroundImage: ExtendedPediaBackgroundPalBattlepedia\n    elements:\n      - id: button\n        color: 144      # orange (was 16: orange)\n      - id: text\n        color: 239      # grey\n        color2: 244     # light blue\n      - id: list\n        color: 239      # grey\n        color2: 244     # light blue\n  - type: articleVehicleTFTD\n    palette: PAL_BATTLEPEDIA\n    backgroundImage: ExtendedPediaBackgroundPalBattlepedia\n    elements:\n      - id: button\n        color: 144      # orange (in vanilla PAL_UFOPAEDIA was used! but PAL_BATTLEPEDIA allows for pictures to be reused for inventory)\n      - id: text\n        color: 239      # grey\n        color2: 244     # light blue\n      - id: list\n        color: 239      # grey\n        color2: 244     # light blue\n  - type: articleItemTFTD\n    palette: PAL_BATTLEPEDIA\n    backgroundImage: ExtendedPediaBackgroundPalBattlepedia\n    elements:\n      - id: button\n        color: 144      # orange\n      - id: text\n        color: 239      # grey\n        color2: 244     # light blue\n      - id: list\n        color: 239      # grey\n        color2: 244     # light blue\n      - id: ammoColor\n        color: 32       # red\n  - type: articleArmorTFTD\n    palette: PAL_BATTLEPEDIA\n    backgroundImage: ExtendedPediaBackgroundPalBattlepedia\n    elements:\n      - id: button\n        color: 144      # orange (was 15: orange)\n      - id: text\n        color: 239      # grey\n        color2: 244     # light blue\n      - id: list\n        color: 239      # grey\n        color2: 244     # light blue\n  - type: articleBaseFacilityTFTD\n    palette: PAL_BASESCAPE\n    backgroundImage: ExtendedPediaBackgroundPalBasescape\n    elements:\n      - id: button\n        color: 208      # white\n      - id: text\n        color: 208      # white\n        color2: 218     # blue\n      - id: list\n        color: 208      # white\n        color2: 218     # blue\n  - type: articleUsoTFTD\n    palette: PAL_GEOSCAPE\n    backgroundImage: ExtendedPediaBackgroundPalGeoscape\n    elements:\n      - id: button\n        color: 133      # minty green\n      - id: text\n        color: 133      # minty green\n        color2: 138     # yellow\n      - id: list\n        color: 133      # minty green\n        color2: 138     # yellow\n  - type: statsForNerds\n    backgroundImage: BACK05.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 1     # burgundy\n      - id: window\n        color: 218   # blue\n      - id: text\n        color: 218   # blue\n        color2: 208  # white\n      - id: list\n        color: 246   # purple\n        color2: 241  # pink\n        border: 218  # blue\n      - id: listExtended\n        color: 208   # white\n        color2: 213  # gold\n      - id: button\n        color: 246   # purple\n      - id: comboBox\n        color: 241   # pink\n  - type: soldierTransformation\n    backgroundImage: BACK02.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 2     # orange\n      - id: window\n        color: 241   # pink\n      - id: text\n        color: 218   # blue\n        color2: 208  # white\n      - id: list1\n        color: 246   # purple\n        color2: 208  # white\n        border: 218  # blue\n      - id: list2\n        color: 218   # blue\n        color2: 208  # white\n        border: 218  # blue\n      - id: button\n        color: 218   # blue\n  - type: transformationList\n    backgroundImage: BACK02.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 2     # orange\n      - id: window\n        color: 241   # pink\n      - id: text1\n        color: 218   # blue\n      - id: text2\n        color: 241   # pink\n      - id: list\n        color: 246   # purple\n        border: 241  # pink\n      - id: button\n        color: 218   # blue\n      - id: button2\n        color: 241   # pink\n"
  },
  {
    "path": "bin/standard/xcom1/inventories.rul",
    "content": "invs:\n  - id: STR_GROUND\n    x: 0\n    y: 152\n    type: 2\n    costs:\n      STR_BACK_PACK: 20\n      STR_BELT: 12\n      STR_LEFT_HAND: 8\n      STR_LEFT_LEG: 10\n      STR_LEFT_SHOULDER: 12\n      STR_RIGHT_HAND: 8\n      STR_RIGHT_LEG: 10\n      STR_RIGHT_SHOULDER: 12\n  - id: STR_RIGHT_HAND\n    x: 0\n    y: 63\n    type: 1\n    costs:\n      STR_BACK_PACK: 14\n      STR_BELT: 8\n      STR_GROUND: 2\n      STR_LEFT_HAND: 4\n      STR_LEFT_LEG: 10\n      STR_LEFT_SHOULDER: 10\n      STR_RIGHT_LEG: 8\n      STR_RIGHT_SHOULDER: 10\n  - id: STR_LEFT_HAND\n    x: 128\n    y: 63\n    type: 1\n    costs:\n      STR_BACK_PACK: 14\n      STR_BELT: 8\n      STR_GROUND: 2\n      STR_LEFT_LEG: 8\n      STR_LEFT_SHOULDER: 10\n      STR_RIGHT_HAND: 4\n      STR_RIGHT_LEG: 10\n      STR_RIGHT_SHOULDER: 10\n  - id: STR_BELT\n    x: 192\n    y: 104\n    slots:\n      - [0, 0]\n      - [1, 0]\n      - [2, 0]\n      - [3, 0]\n      - [0, 1]\n      - [3, 1]\n    costs:\n      STR_BACK_PACK: 16\n      STR_GROUND: 6\n      STR_LEFT_HAND: 4\n      STR_LEFT_LEG: 10\n      STR_LEFT_SHOULDER: 12\n      STR_RIGHT_HAND: 4\n      STR_RIGHT_LEG: 10\n      STR_RIGHT_SHOULDER: 12\n  - id: STR_RIGHT_LEG\n    x: 0\n    y: 120\n    slots:\n      - [0, 0]\n      - [1, 0]\n    costs:\n      STR_BACK_PACK: 18\n      STR_BELT: 10\n      STR_GROUND: 6\n      STR_LEFT_HAND: 6\n      STR_LEFT_LEG: 10\n      STR_LEFT_SHOULDER: 10\n      STR_RIGHT_HAND: 4\n      STR_RIGHT_SHOULDER: 10\n  - id: STR_LEFT_LEG\n    x: 128\n    y: 120\n    slots:\n      - [0, 0]\n      - [1, 0]\n    costs:\n      STR_BACK_PACK: 18\n      STR_BELT: 10\n      STR_GROUND: 6\n      STR_LEFT_HAND: 4\n      STR_LEFT_SHOULDER: 10\n      STR_RIGHT_HAND: 6\n      STR_RIGHT_LEG: 10\n      STR_RIGHT_SHOULDER: 10\n  - id: STR_RIGHT_SHOULDER\n    x: 16\n    y: 37\n    slots:\n      - [0, 0]\n      - [1, 0]\n    costs:\n      STR_BACK_PACK: 16\n      STR_BELT: 10\n      STR_GROUND: 4\n      STR_LEFT_HAND: 3\n      STR_LEFT_LEG: 12\n      STR_LEFT_SHOULDER: 8\n      STR_RIGHT_HAND: 3\n      STR_RIGHT_LEG: 12\n  - id: STR_LEFT_SHOULDER\n    x: 112\n    y: 37\n    slots:\n      - [0, 0]\n      - [1, 0]\n    costs:\n      STR_BACK_PACK: 16\n      STR_BELT: 10\n      STR_GROUND: 4\n      STR_LEFT_HAND: 3\n      STR_LEFT_LEG: 12\n      STR_RIGHT_HAND: 3\n      STR_RIGHT_LEG: 12\n      STR_RIGHT_SHOULDER: 8\n  - id: STR_BACK_PACK\n    x: 192\n    y: 37\n    slots:\n      - [0, 0]\n      - [1, 0]\n      - [2, 0]\n      - [0, 1]\n      - [1, 1]\n      - [2, 1]\n      - [0, 2]\n      - [1, 2]\n      - [2, 2]\n    costs:\n      STR_BELT: 12\n      STR_GROUND: 10\n      STR_LEFT_HAND: 8\n      STR_LEFT_LEG: 16\n      STR_LEFT_SHOULDER: 14\n      STR_RIGHT_HAND: 8\n      STR_RIGHT_LEG: 16\n      STR_RIGHT_SHOULDER: 14"
  },
  {
    "path": "bin/standard/xcom1/items.rul",
    "content": "items:\n  - type: STR_STINGRAY_LAUNCHER\n    size: 0.8\n    costBuy: 16000\n    costSell: 12000\n    transferTime: 48\n  - type: STR_STINGRAY_MISSILES\n    size: 0.4\n    costBuy: 3000\n    costSell: 2400\n    transferTime: 48\n    clipSize: 1\n  - type: STR_AVALANCHE_LAUNCHER\n    size: 1\n    costBuy: 17000\n    costSell: 12750\n    transferTime: 48\n  - type: STR_AVALANCHE_MISSILES\n    size: 1.5\n    costBuy: 9000\n    costSell: 7200\n    transferTime: 48\n    clipSize: 1\n  - type: STR_CANNON\n    size: 1.5\n    costBuy: 30000\n    costSell: 22500\n    transferTime: 48\n  - type: STR_CANNON_ROUNDS_X50\n    size: 0.1\n    costBuy: 1240\n    costSell: 1012\n    transferTime: 96\n    clipSize: 50\n  - type: STR_FUSION_BALL_LAUNCHER\n    size: 2.0\n    costSell: 281000\n    transferTime: 48\n  - type: STR_FUSION_BALL\n    size: 0.6\n    costSell: 53300\n    transferTime: 48\n    clipSize: 1\n  - type: STR_LASER_CANNON\n    size: 2.0\n    costSell: 211000\n    transferTime: 48\n  - type: STR_PLASMA_BEAM\n    size: 1.2\n    costSell: 267300\n    transferTime: 48\n  - type: STR_TANK_CANNON\n    size: 6\n    costBuy: 420000\n    costSell: 340000\n    transferTime: 96\n    weight: 1\n    bigSprite: 43\n    floorSprite: 0\n    handSprite: 0\n    bulletSprite: 4\n    fireSound: 12\n    compatibleAmmo:\n      - STR_HWP_CANNON_SHELLS\n    accuracySnap: 60\n    accuracyAimed: 90\n    tuSnap: 33\n    tuAimed: 80\n    battleType: 1\n    fixedWeapon: true\n    invWidth: 2\n    invHeight: 3\n    turretType: 0\n  - type: STR_HWP_CANNON_SHELLS\n    size: 0.1\n    costBuy: 200\n    costSell: 100\n    transferTime: 48\n    weight: 1\n    hitSound: 13\n    hitAnimation: 26\n    power: 60\n    damageType: 1\n    clipSize: 30\n    battleType: 2\n  - type: STR_TANK_ROCKET_LAUNCHER\n    size: 6\n    costBuy: 480000\n    costSell: 360000\n    transferTime: 96\n    weight: 1\n    bigSprite: 42\n    floorSprite: 0\n    handSprite: 0\n    bulletSprite: 0\n    fireSound: 52\n    compatibleAmmo:\n      - STR_HWP_ROCKETS\n    accuracySnap: 55\n    accuracyAimed: 115\n    tuSnap: 45\n    tuAimed: 75\n    battleType: 1\n    fixedWeapon: true\n    invWidth: 2\n    invHeight: 3\n    turretType: 1\n  - type: STR_HWP_ROCKETS\n    size: 0.6\n    costBuy: 3000\n    costSell: 2250\n    transferTime: 48\n    weight: 1\n    hitSound: 0\n    hitAnimation: 0\n    power: 85\n    damageType: 3\n    clipSize: 8\n    battleType: 2\n  - type: STR_TANK_LASER_CANNON\n    size: 6\n    costSell: 594000\n    transferTime: 96\n    weight: 1\n    bigSprite: 54\n    floorSprite: 0\n    handSprite: 0\n    bulletSprite: 5\n    fireSound: 11\n    hitSound: 19\n    hitAnimation: 36\n    power: 110\n    damageType: 4\n    accuracySnap: 50\n    accuracyAimed: 85\n    tuSnap: 33\n    tuAimed: 75\n    battleType: 1\n    fixedWeapon: true\n    clipSize: -1\n    invWidth: 2\n    invHeight: 3\n    turretType: 2\n  - type: STR_HOVERTANK_PLASMA\n    size: 6\n    costSell: 980000\n    transferTime: 96\n    weight: 1\n    bigSprite: 40\n    floorSprite: 0\n    handSprite: 0\n    bulletSprite: 8\n    fireSound: 18\n    hitSound: 19\n    power: 110\n    damageType: 5\n    hitAnimation: 46\n    accuracySnap: 85\n    accuracyAimed: 100\n    tuSnap: 30\n    tuAimed: 60\n    battleType: 1\n    fixedWeapon: true\n    clipSize: -1\n    invWidth: 2\n    invHeight: 3\n    turretType: 3\n  - type: STR_HOVERTANK_LAUNCHER\n    size: 6\n    costSell: 1043000\n    transferTime: 96\n    weight: 1\n    bigSprite: 40\n    floorSprite: 0\n    handSprite: 0\n    bulletSprite: 10\n    fireSound: 53\n    compatibleAmmo:\n      - STR_HWP_FUSION_BOMB\n    accuracyAimed: 100\n    tuAimed: 66\n    battleType: 1\n    fixedWeapon: true\n    waypoints: 9\n    invWidth: 2\n    invHeight: 3\n    turretType: 4\n  - type: STR_HWP_FUSION_BOMB\n    size: 0.6\n    costSell: 31500\n    transferTime: 48\n    weight: 1\n    hitSound: 0\n    hitAnimation: 0\n    power: 140\n    damageType: 3\n    clipSize: 8\n    battleType: 2\n    blastRadius: 11\n  - type: STR_PISTOL\n    size: 0.1\n    costBuy: 800\n    costSell: 600\n    weight: 5\n    bigSprite: 3\n    floorSprite: 3\n    handSprite: 96\n    bulletSprite: 1\n    fireSound: 4\n    compatibleAmmo:\n      - STR_PISTOL_CLIP\n    accuracySnap: 60\n    accuracyAimed: 78\n    tuSnap: 18\n    tuAimed: 30\n    battleType: 1\n    invWidth: 1\n    invHeight: 2\n  - type: STR_PISTOL_CLIP\n    size: 0.1\n    costBuy: 70\n    costSell: 52\n    weight: 3\n    bigSprite: 4\n    floorSprite: 4\n    hitSound: 22\n    hitAnimation: 26\n    power: 26\n    damageType: 1\n    clipSize: 12\n    battleType: 2\n    armor: 12\n  - type: STR_RIFLE\n    size: 0.2\n    costBuy: 3000\n    costSell: 2250\n    weight: 8\n    bigSprite: 1\n    floorSprite: 1\n    handSprite: 0\n    bulletSprite: 2\n    fireSound: 4\n    compatibleAmmo:\n      - STR_RIFLE_CLIP\n    accuracyAuto: 35\n    accuracySnap: 60\n    accuracyAimed: 110\n    tuAuto: 35\n    tuSnap: 25\n    tuAimed: 80\n    battleType: 1\n    twoHanded: true\n    invWidth: 1\n    invHeight: 3\n  - type: STR_RIFLE_CLIP\n    size: 0.1\n    costBuy: 200\n    costSell: 150\n    weight: 3\n    bigSprite: 2\n    floorSprite: 2\n    hitSound: 22\n    hitAnimation: 26\n    power: 30\n    damageType: 1\n    clipSize: 20\n    battleType: 2\n  - type: STR_HEAVY_CANNON\n    size: 0.3\n    costBuy: 6400\n    costSell: 4800\n    weight: 18\n    bigSprite: 11\n    floorSprite: 11\n    handSprite: 24\n    bulletSprite: 4\n    fireSound: 12\n    compatibleAmmo:\n      - STR_HC_AP_AMMO\n      - STR_HC_HE_AMMO\n      - STR_HC_I_AMMO\n    accuracySnap: 60\n    accuracyAimed: 90\n    tuSnap: 33\n    tuAimed: 80\n    battleType: 1\n    twoHanded: true\n    invWidth: 2\n    invHeight: 3\n  - type: STR_HC_AP_AMMO\n    size: 0.1\n    costBuy: 300\n    costSell: 225\n    weight: 6\n    bigSprite: 12\n    floorSprite: 12\n    hitSound: 13\n    hitAnimation: 26\n    power: 56\n    damageType: 1\n    clipSize: 6\n    battleType: 2\n    invWidth: 2\n    invHeight: 1\n  - type: STR_HC_HE_AMMO\n    size: 0.1\n    costBuy: 500\n    costSell: 275\n    weight: 6\n    bigSprite: 13\n    floorSprite: 13\n    hitSound: 0\n    hitAnimation: 0\n    power: 52\n    damageType: 3\n    clipSize: 6\n    battleType: 2\n    invWidth: 2\n    invHeight: 1\n  - type: STR_HC_I_AMMO\n    size: 0.1\n    costBuy: 400\n    costSell: 300\n    weight: 6\n    bigSprite: 14\n    floorSprite: 14\n    hitSound: 0\n    hitAnimation: 0\n    power: 60\n    damageType: 2\n    clipSize: 6\n    battleType: 2\n    invWidth: 2\n    invHeight: 1\n  - type: STR_AUTO_CANNON\n    size: 0.3\n    costBuy: 13500\n    costSell: 10125\n    weight: 19\n    bigSprite: 7\n    floorSprite: 7\n    handSprite: 32\n    bulletSprite: 3\n    fireSound: 12\n    compatibleAmmo:\n      - STR_AC_AP_AMMO\n      - STR_AC_HE_AMMO\n      - STR_AC_I_AMMO\n    accuracyAuto: 32\n    accuracySnap: 56\n    accuracyAimed: 82\n    tuAuto: 40\n    tuSnap: 33\n    tuAimed: 80\n    battleType: 1\n    twoHanded: true\n    invWidth: 2\n    invHeight: 3\n  - type: STR_AC_AP_AMMO\n    size: 0.1\n    costBuy: 500\n    costSell: 400\n    weight: 5\n    bigSprite: 8\n    floorSprite: 8\n    hitSound: 13\n    hitAnimation: 26\n    power: 42\n    damageType: 1\n    clipSize: 14\n    battleType: 2\n    invWidth: 2\n    invHeight: 1\n  - type: STR_AC_HE_AMMO\n    size: 0.1\n    costBuy: 700\n    costSell: 560\n    weight: 5\n    bigSprite: 9\n    floorSprite: 9\n    hitSound: 0\n    hitAnimation: 0\n    power: 44\n    damageType: 3\n    clipSize: 14\n    battleType: 2\n    invWidth: 2\n    invHeight: 1\n  - type: STR_AC_I_AMMO\n    size: 0.1\n    costBuy: 650\n    costSell: 520\n    weight: 5\n    bigSprite: 10\n    floorSprite: 10\n    hitSound: 0\n    hitAnimation: 0\n    power: 48\n    damageType: 2\n    clipSize: 14\n    battleType: 2\n    invWidth: 2\n    invHeight: 1\n  - type: STR_ROCKET_LAUNCHER\n    size: 0.4\n    costBuy: 4000\n    costSell: 3000\n    weight: 10\n    bigSprite: 15\n    floorSprite: 15\n    handSprite: 72\n    bulletSprite: 0\n    fireSound: 52\n    compatibleAmmo:\n      - STR_SMALL_ROCKET\n      - STR_LARGE_ROCKET\n      - STR_INCENDIARY_ROCKET\n    accuracySnap: 55\n    accuracyAimed: 115\n    tuSnap: 45\n    tuAimed: 75\n    battleType: 1\n    twoHanded: true\n    invWidth: 2\n    invHeight: 3\n  - type: STR_SMALL_ROCKET\n    size: 0.2\n    costBuy: 600\n    costSell: 480\n    weight: 6\n    bigSprite: 16\n    floorSprite: 16\n    hitSound: 0\n    hitAnimation: 0\n    power: 75\n    damageType: 3\n    clipSize: 1\n    battleType: 2\n    invWidth: 1\n    invHeight: 3\n  - type: STR_LARGE_ROCKET\n    size: 0.2\n    costBuy: 900\n    costSell: 720\n    weight: 8\n    bigSprite: 17\n    floorSprite: 17\n    hitSound: 0\n    hitAnimation: 0\n    power: 100\n    damageType: 3\n    clipSize: 1\n    battleType: 2\n    invWidth: 1\n    invHeight: 3\n  - type: STR_INCENDIARY_ROCKET\n    size: 0.2\n    costBuy: 1200\n    costSell: 960\n    weight: 8\n    bigSprite: 18\n    floorSprite: 18\n    hitSound: 0\n    hitAnimation: 0\n    power: 90\n    damageType: 2\n    clipSize: 1\n    battleType: 2\n    invWidth: 1\n    invHeight: 3\n  - type: STR_LASER_PISTOL\n    size: 0.1\n    costSell: 20000\n    weight: 7\n    bigSprite: 5\n    floorSprite: 5\n    handSprite: 112\n    bulletSprite: 5\n    fireSound: 11\n    hitSound: 19\n    hitAnimation: 36\n    power: 46\n    damageType: 4\n    accuracyAuto: 28\n    accuracySnap: 40\n    accuracyAimed: 68\n    tuAuto: 25\n    tuSnap: 20\n    tuAimed: 55\n    clipSize: -1\n    battleType: 1\n    invWidth: 1\n    invHeight: 2\n  - type: STR_LASER_RIFLE\n    size: 0.2\n    costSell: 36900\n    weight: 8\n    bigSprite: 0\n    floorSprite: 0\n    handSprite: 8\n    bulletSprite: 6\n    fireSound: 11\n    hitSound: 19\n    hitAnimation: 36\n    power: 60\n    damageType: 4\n    accuracyAuto: 46\n    accuracySnap: 65\n    accuracyAimed: 100\n    tuAuto: 34\n    tuSnap: 25\n    tuAimed: 50\n    clipSize: -1\n    battleType: 1\n    twoHanded: true\n    invWidth: 1\n    invHeight: 3\n  - type: STR_HEAVY_LASER\n    size: 0.3\n    costSell: 61000\n    weight: 18\n    bigSprite: 6\n    floorSprite: 6\n    handSprite: 16\n    bulletSprite: 7\n    fireSound: 11\n    hitSound: 19\n    hitAnimation: 36\n    power: 85\n    damageType: 4\n    accuracySnap: 50\n    accuracyAimed: 84\n    tuSnap: 33\n    tuAimed: 75\n    clipSize: -1\n    battleType: 1\n    twoHanded: true\n    invWidth: 2\n    invHeight: 3\n  - type: STR_GRENADE\n    size: 0.1\n    costBuy: 300\n    costSell: 240\n    weight: 3\n    bigSprite: 19\n    floorSprite: 19\n    power: 50\n    damageType: 3\n    battleType: 4\n    blastRadius: 5\n  - type: STR_SMOKE_GRENADE\n    size: 0.1\n    costBuy: 150\n    costSell: 120\n    weight: 3\n    bigSprite: 20\n    floorSprite: 20\n    power: 60\n    damageType: 9\n    battleType: 4\n    blastRadius: 5\n  - type: STR_PROXIMITY_GRENADE\n    size: 0.1\n    costBuy: 500\n    costSell: 400\n    weight: 3\n    bigSprite: 21\n    floorSprite: 21\n    power: 70\n    damageType: 3\n    battleType: 5\n    blastRadius: 5\n  - type: STR_HIGH_EXPLOSIVE\n    size: 0.2\n    costBuy: 1500\n    costSell: 1200\n    weight: 6\n    bigSprite: 22\n    floorSprite: 22\n    power: 110\n    damageType: 3\n    battleType: 4\n    invWidth: 2\n    invHeight: 1\n    blastRadius: 5\n  - type: STR_MOTION_SCANNER\n    size: 0.1\n    costSell: 45600\n    weight: 3\n    bigSprite: 23\n    floorSprite: 23\n    battleType: 7\n    tuUse: 25\n  - type: STR_MEDI_KIT\n    size: 0.1\n    costSell: 46500\n    weight: 5\n    bigSprite: 24\n    floorSprite: 24\n    battleType: 6\n    invWidth: 1\n    invHeight: 2\n    painKiller: 10\n    heal: 10\n    stimulant: 10\n    woundRecovery: 1\n    healthRecovery: 3\n    stunRecovery: 4\n    energyRecovery: 10\n    tuUse: 10\n    flatRate: true\n  - type: STR_PSI_AMP\n    requires:\n      - STR_PSI_AMP\n    size: 0.1\n    costSell: 194700\n    weight: 10\n    bigSprite: 33\n    floorSprite: 32\n    handSprite: 88\n    hitSound: 36\n    battleType: 9\n    twoHanded: true\n    invWidth: 1\n    invHeight: 3\n    tuUse: 25\n    flatRate: true\n  - type: STR_STUN_ROD\n    size: 0.1\n    costBuy: 1260\n    costSell: 945\n    weight: 6\n    bigSprite: 26\n    floorSprite: 26\n    handSprite: 80\n    meleeSound: 54\n    power: 65\n    damageType: 6\n    accuracyMelee: 100\n    tuMelee: 30\n    battleType: 3\n    twoHanded: true\n    invWidth: 1\n    invHeight: 3\n    skillApplied: false\n    clipSize: -1\n  - type: STR_ELECTRO_FLARE\n    size: 0.1\n    costBuy: 60\n    costSell: 40\n    weight: 3\n    bigSprite: 55\n    floorSprite: 72\n    power: 15\n    battleType: 10\n    armor: 8\n  - type: STR_CORPSE\n    weight: 22\n    bigSprite: 45\n    floorSprite: 39\n    invWidth: 2\n    invHeight: 3\n    battleType: 11\n    recover: false\n  - type: STR_CORPSE_ARMOR\n    name: STR_CORPSE\n    weight: 24\n    bigSprite: 28\n    floorSprite: 40\n    invWidth: 2\n    invHeight: 3\n    armor: 30\n    battleType: 11\n    recover: false\n  - type: STR_CORPSE_SUIT\n    name: STR_CORPSE\n    weight: 26\n    bigSprite: 44\n    floorSprite: 41\n    invWidth: 2\n    invHeight: 3\n    armor: 40\n    battleType: 11\n    recover: false\n  - type: STR_HEAVY_PLASMA\n    requires:\n      - STR_HEAVY_PLASMA\n    size: 0.2\n    costSell: 171600\n    weight: 8\n    bigSprite: 30\n    floorSprite: 29\n    handSprite: 40\n    bulletSprite: 8\n    fireSound: 18\n    compatibleAmmo:\n      - STR_HEAVY_PLASMA_CLIP\n    accuracyAuto: 50\n    accuracySnap: 75\n    accuracyAimed: 110\n    tuAuto: 35\n    tuSnap: 30\n    tuAimed: 60\n    battleType: 1\n    twoHanded: true\n    invWidth: 2\n    invHeight: 3\n    recoveryPoints: 5\n    armor: 50\n  - type: STR_HEAVY_PLASMA_CLIP\n    requires:\n      - STR_HEAVY_PLASMA_CLIP\n    size: 0.3\n    costSell: 9590\n    weight: 3\n    bigSprite: 25\n    floorSprite: 33\n    hitSound: 19\n    hitAnimation: 46\n    power: 115\n    damageType: 5\n    clipSize: 35\n    battleType: 2\n    recoveryPoints: 1\n  - type: STR_PLASMA_RIFLE\n    requires:\n      - STR_PLASMA_RIFLE\n    size: 0.2\n    costSell: 126500\n    weight: 5\n    bigSprite: 31\n    floorSprite: 30\n    handSprite: 48\n    bulletSprite: 8\n    fireSound: 18\n    compatibleAmmo:\n      - STR_PLASMA_RIFLE_CLIP\n    accuracyAuto: 55\n    accuracySnap: 86\n    accuracyAimed: 100\n    tuAuto: 36\n    tuSnap: 30\n    tuAimed: 60\n    battleType: 1\n    twoHanded: true\n    invWidth: 1\n    invHeight: 3\n    recoveryPoints: 4\n    armor: 50\n  - type: STR_PLASMA_RIFLE_CLIP\n    requires:\n      - STR_PLASMA_RIFLE_CLIP\n    size: 0.1\n    costSell: 6290\n    weight: 3\n    bigSprite: 41\n    floorSprite: 33\n    hitSound: 19\n    hitAnimation: 46\n    power: 80\n    damageType: 5\n    clipSize: 28\n    battleType: 2\n    recoveryPoints: 1\n  - type: STR_PLASMA_PISTOL\n    requires:\n      - STR_PLASMA_PISTOL\n    size: 0.1\n    costSell: 84000\n    weight: 3\n    bigSprite: 32\n    floorSprite: 31\n    handSprite: 104\n    bulletSprite: 8\n    fireSound: 18\n    compatibleAmmo:\n      - STR_PLASMA_PISTOL_CLIP\n    accuracyAuto: 50\n    accuracySnap: 65\n    accuracyAimed: 85\n    tuAuto: 30\n    tuSnap: 30\n    tuAimed: 60\n    battleType: 1\n    invWidth: 1\n    invHeight: 2\n    recoveryPoints: 3\n    armor: 45\n  - type: STR_PLASMA_PISTOL_CLIP\n    requires:\n      - STR_PLASMA_PISTOL_CLIP\n    size: 0.1\n    costSell: 4440\n    weight: 3\n    bigSprite: 34\n    floorSprite: 33\n    hitSound: 19\n    hitAnimation: 46\n    power: 52\n    damageType: 5\n    clipSize: 26\n    battleType: 2\n    recoveryPoints: 1\n  - type: STR_BLASTER_LAUNCHER\n    requires:\n      - STR_BLASTER_LAUNCHER\n    size: 0.3\n    costSell: 144000\n    weight: 16\n    bigSprite: 35\n    floorSprite: 34\n    handSprite: 56\n    bulletSprite: 10\n    fireSound: 53\n    compatibleAmmo:\n      - STR_BLASTER_BOMB\n    accuracyAimed: 120\n    tuAimed: 66\n    battleType: 1\n    twoHanded: true\n    waypoints: 9\n    invWidth: 2\n    invHeight: 3\n    recoveryPoints: 5\n    armor: 40\n  - type: STR_BLASTER_BOMB\n    requires:\n      - STR_BLASTER_BOMB\n    size: 0.2\n    costSell: 17028\n    weight: 3\n    bigSprite: 36\n    floorSprite: 35\n    hitSound: 0\n    hitAnimation: 0\n    power: 200\n    damageType: 3\n    clipSize: 1\n    battleType: 2\n    invWidth: 1\n    invHeight: 2\n    recoveryPoints: 1\n    blastRadius: 10\n  - type: STR_SMALL_LAUNCHER\n    requires:\n      - STR_SMALL_LAUNCHER\n    size: 0.2\n    costSell: 120000\n    weight: 10\n    bigSprite: 37\n    floorSprite: 36\n    handSprite: 64\n    bulletSprite: 9\n    fireSound: 53\n    compatibleAmmo:\n      - STR_STUN_BOMB\n    accuracySnap: 65\n    accuracyAimed: 110\n    tuSnap: 40\n    tuAimed: 75\n    battleType: 1\n    twoHanded: true\n    invWidth: 2\n    invHeight: 2\n    recoveryPoints: 4\n  - type: STR_STUN_BOMB\n    requires:\n      - STR_STUN_BOMB\n    size: 0.1\n    costSell: 15200\n    weight: 3\n    bigSprite: 38\n    floorSprite: 37\n    hitSound: 0\n    hitAnimation: 0\n    power: 90\n    damageType: 6\n    clipSize: 1\n    battleType: 2\n    recoveryPoints: 1\n  - type: STR_ALIEN_GRENADE\n    requires:\n      - STR_ALIEN_GRENADE\n    size: 0.1\n    costSell: 14850\n    weight: 3\n    bigSprite: 39\n    floorSprite: 38\n    power: 90\n    damageType: 3\n    battleType: 4\n    recoveryPoints: 1\n    blastRadius: 5\n  - type: STR_ELERIUM_115\n    size: 0.1\n    costSell: 5000\n    weight: 3\n    bigSprite: 56\n    floorSprite: 37\n    invWidth: 1\n    invHeight: 1\n    recoveryPoints: 5\n  - type: STR_MIND_PROBE\n    requires:\n      - STR_MIND_PROBE\n    size: 0.1\n    costSell: 304000\n    weight: 5\n    bigSprite: 29\n    floorSprite: 28\n    hitSound: 37\n    battleType: 8\n    invWidth: 2\n    invHeight: 2\n    tuUse: 50\n    recoveryPoints: 1\n  - type: STR_SECTOID_CORPSE\n    size: 0.4\n    costSell: 20000\n    weight: 30\n    bigSprite: 46\n    floorSprite: 42\n    invWidth: 2\n    invHeight: 3\n    recoveryPoints: 5\n    battleType: 11\n    armor: 26\n  - type: STR_SNAKEMAN_CORPSE\n    size: 0.4\n    costSell: 20000\n    weight: 40\n    bigSprite: 50\n    floorSprite: 46\n    invWidth: 2\n    invHeight: 3\n    recoveryPoints: 5\n    battleType: 11\n    armor: 26\n  - type: STR_ETHEREAL_CORPSE\n    size: 0.4\n    costSell: 20000\n    weight: 25\n    bigSprite: 49\n    floorSprite: 45\n    invWidth: 2\n    invHeight: 3\n    recoveryPoints: 5\n    battleType: 11\n    armor: 26\n  - type: STR_MUTON_CORPSE\n    size: 0.4\n    costSell: 20000\n    weight: 40\n    bigSprite: 48\n    floorSprite: 44\n    invWidth: 2\n    invHeight: 3\n    recoveryPoints: 5\n    battleType: 11\n    armor: 26\n  - type: STR_FLOATER_CORPSE\n    size: 0.4\n    costSell: 20000\n    weight: 20\n    bigSprite: 52\n    floorSprite: 48\n    invWidth: 2\n    invHeight: 3\n    recoveryPoints: 5\n    battleType: 11\n    armor: 26\n  - type: STR_CELATID_CORPSE\n    size: 0.4\n    costSell: 20000\n    weight: 35\n    bigSprite: 47\n    floorSprite: 43\n    invWidth: 2\n    invHeight: 3\n    recoveryPoints: 3\n    battleType: 11\n    armor: 26\n  - type: STR_SILACOID_CORPSE\n    size: 0.4\n    costSell: 20000\n    weight: 40\n    bigSprite: 51\n    floorSprite: 47\n    invWidth: 2\n    invHeight: 3\n    recoveryPoints: 3\n    battleType: 11\n    armor: 26\n  - type: STR_CHRYSSALID_CORPSE\n    size: 0.4\n    costSell: 20000\n    weight: 40\n    bigSprite: 53\n    floorSprite: 49\n    invWidth: 2\n    invHeight: 3\n    recoveryPoints: 3\n    battleType: 11\n  - type: STR_REAPER_CORPSE\n    size: 1\n    costSell: 20000\n    battleType: 11\n  - type: REAPER_CORPSE_1\n    name: STR_REAPER_CORPSE\n    floorSprite: 52\n    invWidth: 0\n    invHeight: 0\n    battleType: 11\n    recoveryPoints: 3\n  - type: REAPER_CORPSE_2\n    floorSprite: 55\n    invWidth: 0\n    invHeight: 0\n    battleType: 11\n    recover: false\n  - type: REAPER_CORPSE_3\n    floorSprite: 54\n    invWidth: 0\n    invHeight: 0\n    battleType: 11\n    recover: false\n  - type: REAPER_CORPSE_4\n    floorSprite: 53\n    invWidth: 0\n    invHeight: 0\n    battleType: 11\n    recover: false\n  - type: STR_SECTOPOD_CORPSE\n    size: 1\n    costSell: 20000\n    battleType: 11\n  - type: SECTOPOD_CORPSE_1\n    name: STR_SECTOPOD_CORPSE\n    floorSprite: 60\n    invWidth: 0\n    invHeight: 0\n    battleType: 11\n    recoveryPoints: 3\n  - type: SECTOPOD_CORPSE_2\n    floorSprite: 61\n    invWidth: 0\n    invHeight: 0\n    battleType: 11\n    recover: false\n  - type: SECTOPOD_CORPSE_3\n    floorSprite: 62\n    invWidth: 0\n    invHeight: 0\n    battleType: 11\n    recover: false\n  - type: SECTOPOD_CORPSE_4\n    floorSprite: 63\n    invWidth: 0\n    invHeight: 0\n    battleType: 11\n    recover: false\n  - type: STR_CYBERDISC_CORPSE\n    size: 1\n    costSell: 20000\n    battleType: 11\n    power: 120\n    blastRadius: 6\n  - type: CYBERDISC_CORPSE_1\n    name: STR_CYBERDISC_CORPSE\n    floorSprite: 56\n    invWidth: 0\n    invHeight: 0\n    battleType: 11\n    recoveryPoints: 3\n  - type: CYBERDISC_CORPSE_2\n    floorSprite: 57\n    invWidth: 0\n    invHeight: 0\n    battleType: 11\n    recover: false\n  - type: CYBERDISC_CORPSE_3\n    name: STR_CYBERDISC_CORPSE\n    floorSprite: 58\n    invWidth: 0\n    invHeight: 0\n    battleType: 11\n    recover: false\n  - type: CYBERDISC_CORPSE_4\n    name: STR_CYBERDISC_CORPSE\n    floorSprite: 59\n    invWidth: 0\n    invHeight: 0\n    battleType: 11\n    recover: false\n  - type: HOVERTANK_CORPSE_1\n    floorSprite: 64\n    invWidth: 0\n    invHeight: 0\n    battleType: 11\n    recover: false\n  - type: HOVERTANK_CORPSE_2\n    floorSprite: 65\n    invWidth: 0\n    invHeight: 0\n    battleType: 11\n    recover: false\n  - type: HOVERTANK_CORPSE_3\n    floorSprite: 66\n    invWidth: 0\n    invHeight: 0\n    battleType: 11\n    recover: false\n  - type: HOVERTANK_CORPSE_4\n    floorSprite: 67\n    invWidth: 0\n    invHeight: 0\n    battleType: 11\n    recover: false\n  - type: TANK_CORPSE_1\n    floorSprite: 68\n    invWidth: 0\n    invHeight: 0\n    battleType: 11\n    recover: false\n  - type: TANK_CORPSE_2\n    floorSprite: 69\n    invWidth: 0\n    invHeight: 0\n    battleType: 11\n    recover: false\n  - type: TANK_CORPSE_3\n    floorSprite: 70\n    invWidth: 0\n    invHeight: 0\n    battleType: 11\n    recover: false\n  - type: TANK_CORPSE_4\n    floorSprite: 71\n    invWidth: 0\n    invHeight: 0\n    battleType: 11\n    recover: false\n  - type: CIVM_CORPSE\n    name: STR_CORPSE\n    weight: 30\n    bigSprite: 45\n    floorSprite: 50\n    invWidth: 2\n    invHeight: 3\n    armor: 12\n    battleType: 11\n    recover: false\n  - type: CIVF_CORPSE\n    name: STR_CORPSE\n    weight: 50\n    bigSprite: 45\n    floorSprite: 51\n    invWidth: 2\n    invHeight: 3\n    armor: 12\n    battleType: 11\n    recover: false\n  - type: STR_UFO_POWER_SOURCE\n    size: 0.7\n    costSell: 250000\n    specialType: 2\n    recoveryPoints: 20\n  - type: STR_UFO_NAVIGATION\n    size: 0.2\n    costSell: 80000\n    specialType: 3\n    recoveryPoints: 5\n  - type: STR_UFO_CONSTRUCTION\n    size: 0.1\n    costSell: 20000\n    specialType: 4\n    recoveryPoints: 2\n  - type: STR_ALIEN_FOOD\n    size: 0.2\n    costSell: 5000\n    specialType: 5\n    recoveryPoints: 2\n  - type: STR_ALIEN_REPRODUCTION\n    size: 0.2\n    costSell: 40000\n    specialType: 6\n    recoveryPoints: 2\n  - type: STR_ALIEN_ENTERTAINMENT\n    size: 0.2\n    costSell: 20000\n    specialType: 7\n    recoveryPoints: 2\n  - type: STR_ALIEN_SURGERY\n    size: 0.2\n    costSell: 38000\n    specialType: 8\n    recoveryPoints: 2\n  - type: STR_EXAMINATION_ROOM\n    size: 0.2\n    costSell: 9000\n    specialType: 9\n    recoveryPoints: 2\n  - type: STR_ALIEN_ALLOYS\n    size: 0.1\n    costSell: 6500\n    specialType: 10\n    recoveryPoints: 1\n    recoveryDividers:\n      STR_UFO: 10\n      STR_OTHER: 150\n  - type: STR_ALIEN_HABITAT\n    size: 0.1\n    costSell: 100\n    specialType: 11\n    recoveryPoints: 1\n  - type: STR_PERSONAL_ARMOR\n    size: 0.8\n    costSell: 54000\n  - type: STR_POWER_SUIT\n    size: 0.8\n    costSell: 85000\n  - type: STR_FLYING_SUIT\n    size: 0.8\n    costSell: 115000\n  - type: CYBERDISC_WEAPON\n    weight: 3\n    bigSprite: 60\n    floorSprite: 31\n    handSprite: 104\n    bulletSprite: 8\n    fireSound: 18\n    hitSound: 19\n    hitAnimation: 46\n    power: 130\n    damageType: 5\n    accuracySnap: 75\n    accuracyAimed: 110\n    tuSnap: 30\n    tuAimed: 60\n    clipSize: -1\n    battleType: 1\n    fixedWeapon: true\n    invWidth: 2\n    invHeight: 3\n    recover: false\n  - type: REAPER_WEAPON\n    weight: 3\n    bigSprite: 59\n    floorSprite: 31\n    handSprite: 104\n    meleeSound: 48\n    clipSize: -1\n    strengthApplied: true\n    damageType: 7\n    accuracyMelee: 100\n    tuMelee: 15\n    battleType: 3\n    fixedWeapon: true\n    invWidth: 2\n    invHeight: 3\n    recover: false\n    flatRate: true\n  - type: CHRYSSALID_WEAPON\n    weight: 3\n    bigSprite: 61\n    floorSprite: 31\n    handSprite: 104\n    meleeSound: 49\n    clipSize: -1\n    strengthApplied: true\n    damageType: 7\n    accuracyMelee: 100\n    tuMelee: 15\n    battleType: 3\n    fixedWeapon: true\n    invWidth: 2\n    invHeight: 3\n    recover: false\n    zombieUnit: STR_ZOMBIE\n    flatRate: true\n  - type: CELATID_WEAPON\n    weight: 3\n    bigSprite: 60\n    floorSprite: 31\n    handSprite: 104\n    bulletSprite: 8\n    fireSound: 51\n    hitSound: 19\n    hitAnimation: 46\n    power: 140\n    damageType: 8\n    accuracySnap: 75\n    accuracyAimed: 110\n    tuSnap: 30\n    tuAimed: 60\n    battleType: 1\n    fixedWeapon: true\n    invWidth: 2\n    invHeight: 3\n    clipSize: -1\n    recover: false\n    arcingShot: true\n  - type: SILACOID_WEAPON\n    weight: 3\n    bigSprite: 58\n    floorSprite: 31\n    handSprite: 104\n    meleeSound: 50\n    strengthApplied: true\n    damageType: 7\n    accuracyMelee: 100\n    tuMelee: 15\n    clipSize: -1\n    battleType: 3\n    fixedWeapon: true\n    invWidth: 2\n    invHeight: 3\n    recover: false\n    flatRate: true\n  - type: SECTOPOD_WEAPON\n    weight: 3\n    bigSprite: 60\n    floorSprite: 31\n    handSprite: 104\n    fireSound: 18\n    hitSound: 19\n    hitAnimation: 46\n    power: 100\n    damageType: 4\n    accuracyAuto: 50\n    accuracySnap: 75\n    accuracyAimed: 110\n    tuAuto: 35\n    tuSnap: 30\n    tuAimed: 60\n    battleType: 1\n    fixedWeapon: true\n    invWidth: 2\n    invHeight: 3\n    clipSize: -1\n    bulletSprite: 8\n    recover: false\n  - type: ZOMBIE_WEAPON\n    weight: 3\n    bigSprite: 57\n    meleeSound: 48\n    strengthApplied: true\n    damageType: 7\n    accuracyMelee: 100\n    tuMelee: 15\n    battleType: 3\n    fixedWeapon: true\n    invWidth: 2\n    invHeight: 3\n    clipSize: -1\n    recover: false\n    flatRate: true\n  - type: STR_SECTOID_COMMANDER\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 60000\n  - type: STR_SECTOID_LEADER\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 60000\n  - type: STR_SECTOID_ENGINEER\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 60000\n  - type: STR_SECTOID_MEDIC\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 60000\n  - type: STR_SECTOID_NAVIGATOR\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 60000\n  - type: STR_SECTOID_SOLDIER\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 40000\n  - type: STR_SNAKEMAN_COMMANDER\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 60000\n  - type: STR_SNAKEMAN_LEADER\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 60000\n  - type: STR_SNAKEMAN_ENGINEER\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 60000\n  - type: STR_SNAKEMAN_NAVIGATOR\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 60000\n  - type: STR_SNAKEMAN_SOLDIER\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 40000\n  - type: STR_ETHEREAL_COMMANDER\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 80000\n  - type: STR_ETHEREAL_LEADER\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 60000\n  - type: STR_ETHEREAL_SOLDIER\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 60000\n  - type: STR_MUTON_ENGINEER\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 60000\n  - type: STR_MUTON_NAVIGATOR\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 60000\n  - type: STR_MUTON_SOLDIER\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 40000\n  - type: STR_FLOATER_COMMANDER\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 60000\n  - type: STR_FLOATER_LEADER\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 60000\n  - type: STR_FLOATER_ENGINEER\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 60000\n  - type: STR_FLOATER_MEDIC\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 60000\n  - type: STR_FLOATER_NAVIGATOR\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 60000\n  - type: STR_FLOATER_SOLDIER\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 40000\n  - type: STR_CELATID_TERRORIST\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 40000\n  - type: STR_SILACOID_TERRORIST\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 40000\n  - type: STR_CHRYSSALID_TERRORIST\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 60000\n  - type: STR_REAPER_TERRORIST\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 40000\n  - type: STR_SECTOPOD_TERRORIST\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 80000\n  - type: STR_CYBERDISC_TERRORIST\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 80000\n# Special Psi Weapon for Aliens.\n# Usage of this is hard-coded.\n# DO NOT DELETE!\n  - type: ALIEN_PSI_WEAPON\n    hitSound: 36\n    battleType: 9\n    tuUse: 25\n    flatRate: true\n    recover: false"
  },
  {
    "path": "bin/standard/xcom1/manufacture.rul",
    "content": "manufacture:\n  - name: STR_FUSION_BALL_LAUNCHER\n    category: STR_CRAFT_WEAPON\n    requires:\n      - STR_FUSION_MISSILE\n    space: 6\n    time: 400\n    cost: 242000\n    requiredItems:\n      STR_ALIEN_ALLOYS: 1\n  - name: STR_LASER_CANNON\n    category: STR_CRAFT_WEAPON\n    requires:\n      - STR_LASER_CANNON\n    space: 6\n    time: 300\n    cost: 182000\n  - name: STR_PLASMA_BEAM\n    category: STR_CRAFT_WEAPON\n    requires:\n      - STR_PLASMA_CANNON\n    space: 8\n    time: 500\n    cost: 226000\n    requiredItems:\n      STR_ELERIUM_115: 15\n  - name: STR_FUSION_BALL\n    category: STR_CRAFT_AMMUNITION\n    requires:\n      - STR_FUSION_MISSILE\n    space: 6\n    time: 600\n    cost: 28000\n    requiredItems:\n      STR_ELERIUM_115: 4\n  - name: STR_TANK_LASER_CANNON\n    category: STR_HEAVY_WEAPONS_PLATFORM\n    requires:\n      - STR_LASER_CANNON\n    space: 25\n    time: 1200\n    cost: 500000\n  - name: STR_HOVERTANK_PLASMA\n    category: STR_HEAVY_WEAPONS_PLATFORM\n    requires:\n      - STR_PLASMA_CANNON\n      - STR_NEW_FIGHTER_CRAFT\n    space: 30\n    time: 1200\n    cost: 850000\n    requiredItems:\n      STR_ALIEN_ALLOYS: 5\n      STR_ELERIUM_115: 30\n  - name: STR_HOVERTANK_LAUNCHER\n    category: STR_HEAVY_WEAPONS_PLATFORM\n    requires:\n      - STR_FUSION_MISSILE\n      - STR_NEW_FIGHTER_CRAFT\n    space: 30\n    time: 1400\n    cost: 900000\n    requiredItems:\n      STR_ALIEN_ALLOYS: 8\n      STR_ELERIUM_115: 25\n  - name: STR_HWP_FUSION_BOMB\n    category: STR_HWP_CANNON_SHELLS\n    requires:\n      - STR_FUSION_MISSILE\n      - STR_NEW_FIGHTER_CRAFT\n    space: 25\n    time: 400\n    cost: 15000\n    requiredItems:\n      STR_ALIEN_ALLOYS: 8\n      STR_ELERIUM_115: 5\n  - name: STR_LASER_PISTOL\n    category: STR_WEAPON\n    requires:\n      - STR_LASER_PISTOL\n    space: 2\n    time: 300\n    cost: 8000\n  - name: STR_LASER_RIFLE\n    category: STR_WEAPON\n    requires:\n      - STR_LASER_RIFLE\n    space: 3\n    time: 400\n    cost: 20000\n  - name: STR_HEAVY_LASER\n    category: STR_WEAPON\n    requires:\n      - STR_HEAVY_LASER\n    space: 4\n    time: 700\n    cost: 32000\n  - name: STR_MOTION_SCANNER\n    category: STR_EQUIPMENT\n    requires:\n      - STR_MOTION_SCANNER\n    space: 4\n    time: 220\n    cost: 34000\n  - name: STR_MEDI_KIT\n    category: STR_EQUIPMENT\n    requires:\n      - STR_MEDI_KIT\n    space: 4\n    time: 420\n    cost: 28000\n  - name: STR_PSI_AMP\n    category: STR_EQUIPMENT\n    requires:\n      - STR_PSI_AMP\n    space: 6\n    time: 500\n    cost: 160000\n    requiredItems:\n      STR_ELERIUM_115: 1\n  - name: STR_HEAVY_PLASMA\n    category: STR_WEAPON\n    requires:\n      - STR_HEAVY_PLASMA\n      - STR_HEAVY_PLASMA_CLIP\n    space: 4\n    time: 1000\n    cost: 122000\n    requiredItems:\n      STR_ALIEN_ALLOYS: 1\n  - name: STR_HEAVY_PLASMA_CLIP\n    category: STR_AMMUNITION\n    requires:\n      - STR_HEAVY_PLASMA_CLIP\n    space: 4\n    time: 80\n    cost: 6000\n    requiredItems:\n      STR_ELERIUM_115: 3\n  - name: STR_PLASMA_RIFLE\n    category: STR_WEAPON\n    requires:\n      - STR_PLASMA_RIFLE\n      - STR_PLASMA_RIFLE_CLIP\n    space: 4\n    time: 820\n    cost: 88000\n    requiredItems:\n      STR_ALIEN_ALLOYS: 1\n  - name: STR_PLASMA_RIFLE_CLIP\n    category: STR_AMMUNITION\n    requires:\n      - STR_PLASMA_RIFLE_CLIP\n    space: 4\n    time: 80\n    cost: 3000\n    requiredItems:\n      STR_ELERIUM_115: 2\n  - name: STR_PLASMA_PISTOL\n    category: STR_WEAPON\n    requires:\n      - STR_PLASMA_PISTOL\n      - STR_PLASMA_PISTOL_CLIP\n    space: 3\n    time: 600\n    cost: 56000\n    requiredItems:\n      STR_ALIEN_ALLOYS: 1\n  - name: STR_PLASMA_PISTOL_CLIP\n    category: STR_AMMUNITION\n    requires:\n      - STR_PLASMA_PISTOL_CLIP\n    space: 4\n    time: 60\n    cost: 2000\n    requiredItems:\n      STR_ELERIUM_115: 1\n  - name: STR_BLASTER_LAUNCHER\n    category: STR_WEAPON\n    requires:\n      - STR_BLASTER_LAUNCHER\n      - STR_BLASTER_BOMB\n    space: 5\n    time: 1200\n    cost: 90000\n    requiredItems:\n      STR_ALIEN_ALLOYS: 1\n  - name: STR_BLASTER_BOMB\n    category: STR_AMMUNITION\n    requires:\n      - STR_BLASTER_BOMB\n    space: 3\n    time: 220\n    cost: 8000\n    requiredItems:\n      STR_ELERIUM_115: 3\n  - name: STR_SMALL_LAUNCHER\n    category: STR_WEAPON\n    requires:\n      - STR_SMALL_LAUNCHER\n      - STR_STUN_BOMB\n    space: 3\n    time: 900\n    cost: 78000\n    requiredItems:\n      STR_ALIEN_ALLOYS: 1\n  - name: STR_STUN_BOMB\n    category: STR_AMMUNITION\n    requires:\n      - STR_STUN_BOMB\n    space: 2\n    time: 200\n    cost: 7000\n    requiredItems:\n      STR_ELERIUM_115: 1\n  - name: STR_ALIEN_GRENADE\n    category: STR_WEAPON\n    requires:\n      - STR_ALIEN_GRENADE\n    space: 2\n    time: 200\n    cost: 6700\n    requiredItems:\n      STR_ELERIUM_115: 2\n  - name: STR_MIND_PROBE\n    category: STR_EQUIPMENT\n    requires:\n      - STR_MIND_PROBE\n    space: 4\n    time: 1200\n    cost: 262000\n    requiredItems:\n      STR_ELERIUM_115: 1\n  - name: STR_PERSONAL_ARMOR\n    category: STR_PERSONAL_ARMOR\n    requires:\n      - STR_PERSONAL_ARMOR\n    space: 12\n    time: 800\n    cost: 22000\n    requiredItems:\n      STR_ALIEN_ALLOYS: 4\n  - name: STR_POWER_SUIT\n    category: STR_PERSONAL_ARMOR\n    requires:\n      - STR_POWER_SUIT\n    space: 16\n    time: 1000\n    cost: 42000\n    requiredItems:\n      STR_ALIEN_ALLOYS: 5\n      STR_ELERIUM_115: 5\n  - name: STR_FLYING_SUIT\n    category: STR_PERSONAL_ARMOR\n    requires:\n      - STR_FLYING_SUIT\n    space: 16\n    time: 1400\n    cost: 58000\n    requiredItems:\n      STR_ALIEN_ALLOYS: 5\n      STR_ELERIUM_115: 16\n  - name: STR_ALIEN_ALLOYS\n    category: STR_UFO_COMPONENT\n    requires:\n      - STR_ALIEN_ALLOYS\n    space: 10\n    time: 100\n    cost: 3000\n  - name: STR_UFO_POWER_SOURCE\n    category: STR_UFO_COMPONENT\n    requires:\n      - STR_UFO_POWER_SOURCE\n    space: 22\n    time: 1400\n    cost: 130000\n    requiredItems:\n      STR_ALIEN_ALLOYS: 5\n      STR_ELERIUM_115: 16\n  - name: STR_UFO_NAVIGATION\n    category: STR_UFO_COMPONENT\n    requires:\n      - STR_UFO_NAVIGATION\n    space: 18\n    time: 1600\n    cost: 150000\n    requiredItems:\n      STR_ALIEN_ALLOYS: 3\n  - name: STR_FIRESTORM\n    category: STR_CRAFT\n    requires:\n      - STR_NEW_FIGHTER_CRAFT\n    space: 30\n    time: 14000\n    cost: 400000\n    requiredItems:\n      STR_ALIEN_ALLOYS: 65\n      STR_UFO_POWER_SOURCE: 1\n      STR_UFO_NAVIGATION: 1\n  - name: STR_LIGHTNING\n    category: STR_CRAFT\n    requires:\n      - STR_NEW_FIGHTER_TRANSPORTER\n    space: 34\n    time: 18000\n    cost: 600000\n    requiredItems:\n      STR_ALIEN_ALLOYS: 85\n      STR_UFO_POWER_SOURCE: 1\n      STR_UFO_NAVIGATION: 1\n  - name: STR_AVENGER\n    category: STR_CRAFT\n    requires:\n      - STR_ULTIMATE_CRAFT\n    space: 36\n    time: 34000\n    cost: 900000\n    requiredItems:\n      STR_ALIEN_ALLOYS: 120\n      STR_UFO_POWER_SOURCE: 2\n      STR_UFO_NAVIGATION: 1"
  },
  {
    "path": "bin/standard/xcom1/mapScripts.rul",
    "content": "mapScripts:\n  - type: STR_CRAFT_DEPLOYMENT_PREVIEW\n    commands:\n    - type: addCraft\n    - type: fillArea\n  - type: DEFAULT # forest, mountain\n    commands:\n    - type: addUFO\n    - type: addCraft\n    - type: addBlock\n      size: 2\n      executions: 2\n    - type: fillArea\n  - type: FARM\n    commands:\n    - type: addUFO\n    - type: addCraft\n    - type: fillArea\n      blocks: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]\n      maxUses: [3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]\n  - type: DESERT\n    commands:\n    - type: addUFO\n    - type: addCraft\n    - type: addBlock\n      size: 2\n      executions: 3\n    - type: fillArea\n  - type: JUNGLE\n    commands:\n    - type: addUFO\n    - type: addCraft\n    - type: fillArea\n      blocks: [3, 4, 5, 6, 7, 8, 9, 10, 11]\n      freqs: [2, 2, 2, 2, 2, 2, 2, 1, 1]\n  - type: POLAR\n    commands:\n    - type: addUFO\n    - type: addCraft\n    - type: addBlock\n      size: 2\n    - type: fillArea\n  - type: URBAN\n    commands:\n    - type: addCraft\n    - type: addLine\n      label: 1\n      direction: vertical\n      executionChances: 50\n      rects:\n        - [1, 1, 4, 1]\n    - type: addLine\n      label: 2\n      conditionals: -1\n      executionChances: 50\n      direction: horizontal\n      rects:\n        - [1, 1, 1, 4]\n    - type: addLine\n      conditionals: [-1, -2]\n      direction: both\n      rects:\n        - [1, 1, 4, 4]\n    - type: addBlock\n      size: 2\n      executions: 4\n    - type: fillArea\n      # URBAN set is lacking blocks 10-13, so the numbers don't correlate properly here,\n      # because these are references to the block numbers within the sets, not the file names.\n      blocks: [3, 4, 10, 11, 12, 13, 14]\n      freqs: [3, 3, 2, 2, 2, 2, 2]\n  - type: MARS\n    commands:\n    - type: addCraft\n    - type: addBlock\n      groups: 2\n    - type: fillArea\n  - type: ALIENBASE\n    commands:\n    - type: addBlock\n      groups: 2\n      executions: 2\n    - type: addBlock\n      size: 2\n      groups: 3\n    - type: addBlock\n      size: 2\n      executions: 3\n    - type: fillArea\n      groups: [0, 1]\n      freqs: [3, 2]\n    - type: digTunnel\n      direction: both\n      tunnelData:\n        level: 0\n        MCDReplacements:\n          - type: westWall\n            set: 2\n            entry: 18\n          - type: northWall\n            set: 2\n            entry: 17\n          - type: corner\n            set: 2\n            entry: 19\n          - type: floor\n            set: 1\n            entry: 63\n  - type: BOSSBATTLE\n    commands:\n    - type: addBlock\n      groups: 2\n      executions: 2\n    - type: addBlock\n      groups: 4\n      size: 2\n    - type: addBlock\n      size: 2\n      executions: 3\n    - type: fillArea\n      groups: [0, 1]\n      freqs: [3, 2]\n    - type: digTunnel\n      direction: both\n      tunnelData:\n        level: 0\n        MCDReplacements:\n          - type: westWall\n            set: 2\n            entry: 18\n          - type: northWall\n            set: 2\n            entry: 17\n          - type: corner\n            set: 2\n            entry: 19\n          - type: floor\n            set: 1\n            entry: 63\n  - type: XBASE\n    commands:\n    - type: digTunnel\n      direction: both\n      tunnelData:\n        level: 0\n        MCDReplacements:\n          - type: westWall\n            set: 1\n            entry: 13\n          - type: northWall\n            set: 1\n            entry: 14\n    - type: fillArea\n      blocks: 20"
  },
  {
    "path": "bin/standard/xcom1/mcdPatches.rul",
    "content": "MCDPatches:\n# pathFinding Hacks.\n# bigWall 1 = regular bigwall, no movement allowed.\n# bigWall 2 = can walk by north-east/south-west\n# bigWall 3 = can walk by north-west/south-east\n# bigWall 4 = acts as west wall\n# bigWall 5 = acts as north wall\n# bigWall 6 = acts as east wall\n# bigWall 7 = acts as south wall\n# bigWall 8 = acts as east and south wall\n  - type: XBASE1\n    data:\n      - MCDIndex: 2\n        bigWall: 2\n      - MCDIndex: 3\n        bigWall: 2\n      - MCDIndex: 4\n        bigWall: 3\n      - MCDIndex: 5\n        bigWall: 3\n      - MCDIndex: 19\n        bigWall: 2\n  - type: AVENGER\n    data:\n      - MCDIndex: 12\n        bigWall: 2\n      - MCDIndex: 14\n        bigWall: 3\n      - MCDIndex: 16\n        bigWall: 3\n      - MCDIndex: 26\n        bigWall: 4\n      - MCDIndex: 30\n        bigWall: 4\n      - MCDIndex: 31\n        bigWall: 4\n      - MCDIndex: 32\n        bigWall: 4\n      - MCDIndex: 33\n        bigWall: 4\n      - MCDIndex: 33\n        bigWall: 4\n      - MCDIndex: 39\n        LOFTS: [6,29,29,29,29,29,0,0,0,0,0,0]\n      - MCDIndex: 43\n        bigWall: 6\n      - MCDIndex: 44\n        bigWall: 6\n      - MCDIndex: 45\n        bigWall: 6\n      - MCDIndex: 46\n        bigWall: 6\n      - MCDIndex: 48\n        bigWall: 2\n      - MCDIndex: 54\n        TUSlide: 2\n      - MCDIndex: 56\n        terrainHeight: -7\n  - type: LIGHTNIN\n    data:\n      - MCDIndex: 0\n        bigWall: 6\n      - MCDIndex: 1\n        bigWall: 6\n      - MCDIndex: 2\n        bigWall: 2\n      - MCDIndex: 3\n        bigWall: 7\n      - MCDIndex: 4\n        bigWall: 3\n      - MCDIndex: 5\n        bigWall: 5\n      - MCDIndex: 6\n        bigWall: 5\n      - MCDIndex: 7\n        bigWall: 2\n      - MCDIndex: 8\n        bigWall: 2\n      - MCDIndex: 9\n        bigWall: 4\n      - MCDIndex: 10\n        bigWall: 4\n      - MCDIndex: 11\n        bigWall: 3\n      - MCDIndex: 12\n        bigWall: 2\n      - MCDIndex: 13\n        bigWall: 7\n        LOFTS: [44,44,44,44,44,44,44,44,44,44,44,44]\n  - type: PLANE\n    data:\n      - MCDIndex: 13\n        bigWall: 6\n      - MCDIndex: 14\n        bigWall: 6\n      - MCDIndex: 49\n        LOFTS: [6,6,6,6,6,6,6,6,6,6,6,6]\n      - MCDIndex: 51\n        LOFTS: [6,6,6,6,6,6,6,6,6,6,6,6]\n      - MCDIndex: 62\n        bigWall: 0\n  - type: U_EXT02\n    data:\n      - MCDIndex: 2\n        bigWall: 6\n      - MCDIndex: 3\n        bigWall: 7\n      - MCDIndex: 4\n        bigWall: 2\n      - MCDIndex: 5\n        bigWall: 2\n      - MCDIndex: 6\n        bigWall: 3\n      - MCDIndex: 7\n        bigWall: 3\n      - MCDIndex: 8\n        bigWall: 8\n      - MCDIndex: 13\n        bigWall: 2\n      - MCDIndex: 14\n        bigWall: 2\n      - MCDIndex: 15\n        bigWall: 2\n  - type: U_BITS\n    data:\n      - MCDIndex: 6\n        TUWalk: 4\n        TUFly: 4\n        TUSlide: 4\n      - MCDIndex: 7\n        TUWalk: 4\n        TUFly: 4\n        TUSlide: 4\n  - type: U_BASE\n    data:\n      - MCDIndex: 9\n        TUFly: 2\n      - MCDIndex: 10\n        deathTile: 30\n      - MCDIndex: 17\n        armor: 60\n        HEBlock: 60\n      - MCDIndex: 22\n        flammability: 40\n        fuel: 4\n      - MCDIndex: 23\n        flammability: 40\n        fuel: 4\n      - MCDIndex: 24\n        flammability: 40\n        fuel: 4\n      - MCDIndex: 25\n        flammability: 40\n        fuel: 4\n# Mountain terrain death tile fix\n  - type: MOUNT\n    data:\n      - MCDIndex: 0\n        deathTile: 77\n      - MCDIndex: 1\n        deathTile: 77\n      - MCDIndex: 2\n        deathTile: 77\n      - MCDIndex: 3\n        deathTile: 77\n      - MCDIndex: 4\n        deathTile: 77\n      - MCDIndex: 5\n        deathTile: 77\n      - MCDIndex: 6\n        deathTile: 77\n      - MCDIndex: 7\n        deathTile: 77\n      - MCDIndex: 8\n        deathTile: 77\n      - MCDIndex: 9\n        deathTile: 77\n      - MCDIndex: 10\n        deathTile: 77\n      - MCDIndex: 11\n        deathTile: 77\n      - MCDIndex: 12\n        deathTile: 77\n      - MCDIndex: 13\n        deathTile: 77\n      - MCDIndex: 14\n        deathTile: 77\n      - MCDIndex: 15\n        deathTile: 77\n      - MCDIndex: 16\n        deathTile: 77\n      - MCDIndex: 17\n        deathTile: 77\n      - MCDIndex: 18\n        deathTile: 77\n      - MCDIndex: 19\n        deathTile: 77\n      - MCDIndex: 20\n        deathTile: 77\n      - MCDIndex: 21\n        deathTile: 77\n      - MCDIndex: 22\n        deathTile: 77\n      - MCDIndex: 23\n        deathTile: 77\n      - MCDIndex: 71\n        deathTile: 74\n      - MCDIndex: 72\n        deathTile: 75\n      - MCDIndex: 73\n        deathTile: 76\n  - type: U_PODS\n    data:\n      - MCDIndex: 6\n        TUWalk: 4\n        TUFly: 4\n        TUSlide: 4\n  - type: U_OPER2\n    data:\n      - MCDIndex: 6\n        TUWalk: 4\n        TUFly: 4\n        TUSlide: 4\n      - MCDIndex: 7\n        TUWalk: 4\n        TUFly: 4\n        TUSlide: 4\n  - type: URBITS\n    data:\n      - MCDIndex: 6\n        TUFly: 2\n      - MCDIndex: 7\n        TUFly: 2\n  - type: POLAR\n    data:\n      - MCDIndex: 0\n        TUFly: 4\n        noFloor: true\n      - MCDIndex: 63\n        noFloor: true\n      - MCDIndex: 64\n        noFloor: true\n      - MCDIndex: 65\n        noFloor: true\n      - MCDIndex: 66\n        noFloor: true\n      - MCDIndex: 67\n        noFloor: true\n      - MCDIndex: 68\n        noFloor: true\n      - MCDIndex: 69\n        noFloor: true\n      - MCDIndex: 70\n        noFloor: true\n      - MCDIndex: 71\n        noFloor: true\n      - MCDIndex: 72\n        noFloor: true\n      - MCDIndex: 73\n        noFloor: true\n      - MCDIndex: 74\n        noFloor: true\n      - MCDIndex: 75\n        noFloor: true\n      - MCDIndex: 76\n        noFloor: true\n      - MCDIndex: 77\n        noFloor: true\n      - MCDIndex: 78\n        noFloor: true\n      - MCDIndex: 79\n        noFloor: true\n      - MCDIndex: 80\n        noFloor: true"
  },
  {
    "path": "bin/standard/xcom1/metadata.yml",
    "content": "#\n# metadata.yaml for XCOM1\n\nname: \"UFO: Enemy Unknown / X-Com: UFO Defense\"\nversion: 8.6.0\ndescription: \"The original UFO: Enemy Unknown / X-Com: UFO Defense\"\nauthor: Microprose\nid: xcom1\n\nisMaster: true\nloadResources:\n  - UFO\n"
  },
  {
    "path": "bin/standard/xcom1/missionScripts.rul",
    "content": "#  - type: example                       # the type/name is used for overwriting or deleting purposes.\n#    firstMonth: 0                       # months this command runs on, 0 runs on startup of a new game (default 0)\n#    lastMonth: 0                        # don't run after this month. in this context we mean \"run once\". -1 denotes no limit (default -1)\n#    label: 1                            # label, used for conditionals (default 0)\n#    conditionals: [1, -2]               # conditional list, just like mapscripts (default none)\n#    missionWeights:                     # the type of mission to spawn (omit to pick one from the mission table) (default none)\n#      0:                                # these are split into monthly chunks, and can contain multiple entries,\n#        STR_ALIEN_RESEARCH: 20          # including weighted odds, but there is a caveat here:\n#        STR_ALIEN_ABDUCTION: 30         # you cannot mix and match missions with mission site objectives (ie: terror) with regular missions,\n#        STR_ALIEN_CROP_CIRCLES: 30      # they are generated too differently. using executionOdds and conditionals instead can achieve\n#        STR_CATTLE_MUTILATION: 20       # exactly the same thing. similarly, terror missions should not appear in regional mission weights (regions.rul)\n#    executionOdds: 100                  # % chances of this command executing (default 100)\n#    targetBaseOdds: 75                  # % chances of this mission targeting a region containing an xcom base instead of random (default 0)\n#    startDelay: 120                     # number of minutes to delay the start of the mission (rounded down to the nearest 30, 0 to use the wave timer from the mission itself) (default 0)\n#    raceWeights:                        # can override established monthly race weights here if desired (default empty)\n#      0:\n#        STR_SECTOID: 100                # in this case we want a sectoid mission, so they get 100%\n#    regionWeights:                      # again, this can override the defined mission region weights (default empty)\n#      0:                                # this won't come into play here unless the mission doesn't target an xcom base, as described above.\n#        STR_SAMPLE_REGION1: 20          # IF OMITTED:\n#        STR_SAMPLE_REGION2: 30          # for a terror type mission, all regions that meet the criteria will be weighed equally.\n#        STR_SAMPLE_REGION3: 50          # for regular missions the normal regional distribution weights will be applied.\n#    minDifficulty: 0                    # this command only applies to difficulty levels of this or above (default 0)\n#    researchTriggers:                   # a list of research topics that can influence the execution of this mission (default empty)\n#      STR_THE_MARTIAN_SOLUTION: true    # in this case, the mission would only run if the player has the martian solution\n#      STR_CYDONIA_OR_BUST: false        # and does NOT have Cydonia or bust\n#    maxRuns: 12                         # this mission type can only execute this number of times, -1 for infinite (default -1)\n#    avoidRepeats: 12                    # this means \"store an array of the 12 previous coordinates, and don't use them again\" (default 0)\n#    varName: researching                # this is an internal variable name, used for tracking maxruns and avoidRepeats (default none)\n#    useTable: false                     # check this mission type appears in the mission tables, and remove it if it does? (default true)\n\nmissionScripts:\n  - type: gameStart\n    missionWeights:\n      0:\n        STR_ALIEN_RESEARCH: 100\n    lastMonth: 0\n    targetBaseOdds: 100\n    raceWeights:\n      0:\n        STR_SECTOID: 100\n    startDelay: 120\n\n  - type: recurringTerror\n    missionWeights:\n      0:\n        STR_ALIEN_TERROR: 100\n    useTable: false\n    startDelay: 150\n\n  - type: recon\n    firstMonth: 1\n\n  - type: invasion\n    firstMonth: 6\n\n  - type: researchRetaliation\n    missionWeights:\n      0:\n        STR_ALIEN_RETALIATION: 100\n    researchTriggers:\n      STR_THE_MARTIAN_SOLUTION: true\n    startDelay: 150\n    targetBaseOdds: 100\n    useTable: false\n    label: 1\n\n  - type: beginnerRetaliation\n    missionWeights:\n      0:\n        STR_ALIEN_RETALIATION: 100\n    firstMonth: 14\n    targetBaseOdds: 100\n    useTable: false\n    conditionals: [-1]\n    label: 2\n    startDelay: 150\n\n  - type: experiencedRetaliation\n    minDifficulty: 1\n    missionWeights:\n      0:\n        STR_ALIEN_RETALIATION: 100\n    firstMonth: 13\n    targetBaseOdds: 100\n    useTable: false\n    conditionals: [-1, -2]\n    label: 3\n    startDelay: 150\n\n  - type: veteranRetaliation\n    minDifficulty: 2\n    missionWeights:\n      0:\n        STR_ALIEN_RETALIATION: 100\n    firstMonth: 12\n    targetBaseOdds: 100\n    useTable: false\n    conditionals: [-1, -2, -3]\n    label: 4\n    startDelay: 150\n\n  - type: geniusRetaliation\n    minDifficulty: 3\n    missionWeights:\n      0:\n        STR_ALIEN_RETALIATION: 100\n    firstMonth: 11\n    targetBaseOdds: 100\n    useTable: false\n    conditionals: [-1, -2, -3, -4]\n    label: 5\n    startDelay: 150\n\n  - type: superhumanRetaliation\n    minDifficulty: 4\n    missionWeights:\n      0:\n        STR_ALIEN_RETALIATION: 100\n    firstMonth: 10\n    targetBaseOdds: 100\n    useTable: false\n    conditionals: [-1, -2, -3, -4, -5]\n    startDelay: 150"
  },
  {
    "path": "bin/standard/xcom1/music.rul",
    "content": "musics:\n  - type: GMDEFEND\n    catPos: 3\n    normalization: 0.76\n  - type: GMENBASE\n    catPos: 6\n    normalization: 0.83\n  - type: GMGEO1\n    catPos: 0\n    normalization: 1.19\n  - type: GMGEO2\n    catPos: 18\n    normalization: 1.0\n  - type: GMGEO3\n  - type: GMGEO4\n  - type: GMGEO5\n  - type: GMGEO6\n  - type: GMGEO7\n  - type: GMGEO8\n  - type: GMGEO9\n  - type: GMGEO10\n  - type: GMINTER\n    catPos: 2\n    normalization: 0.74\n  - type: GMINTRO1\n    catPos: 19\n    normalization: 0.8\n  - type: GMINTRO2\n    catPos: 20\n    normalization: 0.8\n  - type: GMINTRO3\n    catPos: 21\n    normalization: 0.8\n  - type: GMLOSE\n    catPos: 10\n    normalization: 1.0\n  - type: GMMARS\n    catPos: 9\n    normalization: 0.92\n  - type: GMNEWMAR\n    catPos: 8\n    normalization: 0.81\n  - type: GMSTORY\n    catPos: 12\n    normalization: 1.0\n  - type: GMTACTIC\n    catPos: 17\n    normalization: 1.14\n  - type: GMTACTIC1\n  - type: GMTACTIC2\n  - type: GMTACTIC3\n  - type: GMTACTIC4\n  - type: GMTACTIC5\n  - type: GMTACTIC6\n  - type: GMTACTIC7\n  - type: GMTACTIC8\n  - type: GMTACTIC9\n  - type: GMTACTIC10\n  - type: GMWIN\n    catPos: 11\n    normalization: 0.84"
  },
  {
    "path": "bin/standard/xcom1/regions.rul",
    "content": "regions:\n  - type: STR_NORTH_AMERICA\n    cost: 800000\n    areas:\n      - [195, 305, -70, -55]\n      - [230, 305, -55, -30]\n      - [240, 300, -30, -10]\n    regionWeight: 18\n    missionWeights:\n      STR_ALIEN_RESEARCH: 14\n      STR_ALIEN_HARVEST: 17\n      STR_ALIEN_ABDUCTION: 20\n      STR_ALIEN_INFILTRATION: 20\n      STR_ALIEN_BASE: 20\n    missionZones:\n      -\n        - [200, 220, -65, -60]\n        - [230, 260, -65, -55]\n        - [280, 290, -50, -40]\n        - [230, 250, -50, -40]\n        - [260, 280, -50, -40]\n        - [230, 250, -40, -30]\n        - [250, 272, -40, -28]\n        - [270, 290, -42, -25]\n        - [275, 295, -35, -10]\n        - [240, 280, -30, -10]\n      -\n        - [200, 225, -63.75, -60.75]\n        - [245, 260, -54, -50]\n        - [250, 260, -50, -40]\n        - [270, 280, -37, -34]\n        - [255, 260, -40, -30]\n        - [255, 260, -25, -20]\n        - [258.75, 263.75, -19, -17.5]\n        - [286.5, 289.5, -19.375, -18.625]\n        - [240, 242, -45, -44]\n        - [260, 270, -44, -34]\n      -\n        - [236, 240, -50, -45]\n        - [260, 262, -50, -45]\n        - [265, 270, -18, -17]\n        - [273.125, 275.75, -13.25, -12.25]\n        - [241.875, 245.875, -36.5, -34.625]\n        - [286.375, 291, -46.625, -45]\n        - [252.75, 263.125, -42.25, -39]\n        - [286.875, 289, -19, -18.5]\n        - [274.5, 276.25, -44.375, -43.375]\n        - [200.625, 216.75, -64.75, -62.25]\n      -\n        - [286.125, 286.125, -40.75, -40.75, -1, STR_NEW_YORK]\n        - [282.875, 282.875, -38.75, -38.75, -1, STR_WASHINGTON]\n        - [241.75, 241.75, -34.125, -34.125, -1, STR_LOS_ANGELES]\n        - [284.25, 284.25, -45.5, -45.5, -1, STR_MONTREAL]\n        - [277.625, 277.625, -22.5, -22.5, -1, STR_HAVANA]\n        - [260.875, 260.875, -19.375, -19.375, -1, STR_MEXICO_CITY]\n        - [272.375, 272.375, -41.875, -41.875, -1, STR_CHICAGO]\n        - [236.75, 236.75, -49.375, -49.375, -1, STR_VANCOUVER]\n        - [263.375, 263.375, -32.75, -32.75, -1, STR_DALLAS]\n      -\n        - [250, 270, -66, -64]\n        - [280, 292.5, -51, -46]\n        - [267.5, 269.5, -30, -29.5]\n        - [240, 246, -45, -38]\n        - [277.5, 278.5, -31, -28]\n        - [286.875, 288.75, -19.5, -18.75]\n        - [273.25, 275.75, -13.125, -11.875]\n        - [247, 247.5, -27.25, -26.75]\n        - [222.875, 239.25, -63.625, -59.875]\n        - [258.125, 267.125, -40.75, -36.875]\n      -\n        - [0, 359.875, -90, -80]\n        - [0, 359.875, 80, 90]\n        - [180, 200, 0, 10]\n        - [355, 365, -5, 5]\n        - [170, 190, -60, -40]\n        - [305, 325, -60, -30]\n        - [280, 300, 16.125, 36.125]\n        - [4.75, 27.625, -52, -44.375]\n        - [75, 89, -39, -34.375]\n        - [115, 132.5, 21, 25.5]\n  - type: STR_ARCTIC\n    cost: 950000\n    areas:\n      - [0, 360, -90, -70]\n    regionWeight: 4\n    missionWeights:\n      STR_ALIEN_RESEARCH: 25\n      STR_ALIEN_BASE: 35\n    missionZones:\n      -\n        - [305.25, 333.125, -79.25, -75.25]\n        - [273.25, 282.125, -73.375, -71.625]\n        - [159.375, 205.75, -78.625, -75]\n        - [8.5, 72.75, -80.375, -74.125]\n        - [74.875, 165.875, -79.75, -74]\n        - [0, 359.875, -90, -85]\n      -\n        - [302.25, 323.625, -80.75, -78.625]\n        - [62, 66, -76.125, -75.25]\n        - [13.625, 20.875, -79.25, -78.5]\n        - [168.5, 184.625, -83.375, -82.25]\n        - [268.625, 280.75, -78.875, -76.75]\n        - [0, 359.875, -90, -88.125]\n      -\n        - [302.25, 323.625, -80.75, -78.625]\n        - [62, 66, -76.125, -75.25]\n        - [13.625, 20.875, -79.25, -78.5]\n        - [168.5, 184.625, -83.375, -82.25]\n        - [268.625, 280.75, -78.875, -76.75]\n        - [0, 359.875, -90, -88.125]\n      -\n        - [302.25, 323.625, -80.75, -78.625]\n        - [62, 66, -76.125, -75.25]\n      -\n        - [302.25, 323.625, -80.75, -78.625]\n        - [62, 66, -76.125, -75.25]\n        - [13.625, 20.875, -79.25, -78.5]\n        - [168.5, 184.625, -83.375, -82.25]\n        - [268.625, 280.75, -78.875, -76.75]\n        - [0, 359.875, -90, -88.125]\n      -\n        - [121.625, 176.125, -46.25, -21.75]\n        - [0, 359.875, 80, 90]\n        - [180, 200, 0, 10]\n        - [355, 365, -5, 5]\n        - [170, 190, -60, -40]\n        - [305, 325, -60, -30]\n        - [280, 300, 16.125, 36.125]\n        - [4.75, 27.625, -52, -44.375]\n        - [75, 89, -39, -34.375]\n        - [115, 132.5, 21, 25.5]\n  - type: STR_ANTARCTICA\n    cost: 900000\n    areas:\n      - [0, 360, 60, 90]\n    regionWeight: 4\n    missionWeights:\n      STR_ALIEN_RESEARCH: 25\n      STR_ALIEN_BASE: 35\n    missionZones:\n      -\n        - [77, 108.125, 62.125, 76.125]\n        - [340.75, 408.5, 57.25, 72.75]\n        - [104.375, 148.875, 49.625, 66.25]\n        - [175.75, 257.125, 55.625, 73.625]\n        - [0, 359.875, 85, 90]\n      -\n        - [291.125, 296.25, 68.25, 70.5]\n        - [129.625, 152.75, 69.75, 73.625]\n        - [6.625, 35.125, 72.875, 77]\n        - [148.125, 154.75, 70, 72.75]\n        - [0, 359.875, 87.5, 90]\n      -\n        - [291.125, 296.25, 68.25, 70.5]\n        - [129.625, 152.75, 69.75, 73.625]\n        - [6.625, 35.125, 72.875, 77]\n        - [148.125, 154.75, 70, 72.75]\n        - [0, 359.875, 87.5, 90]\n      -\n        - [291.125, 296.25, 68.25, 70.5]\n        - [129.625, 152.75, 69.75, 73.625]\n      -\n        - [291.125, 296.25, 68.25, 70.5]\n        - [129.625, 152.75, 69.75, 73.625]\n        - [6.625, 35.125, 72.875, 77]\n        - [148.125, 154.75, 70, 72.75]\n        - [0, 359.875, 87.5, 90]\n      -\n        - [121.625, 176.125, -46.25, -21.75]\n        - [195.75, 238, -29, 2]\n        - [180, 200, 0, 10]\n        - [355, 365, -5, 5]\n        - [170, 190, -60, -40]\n        - [305, 325, -60, -30]\n        - [280, 300, 16.125, 36.125]\n        - [4.75, 27.625, -52, -44.375]\n        - [75, 89, -39, -34.375]\n        - [115, 132.5, 21, 25.5]\n  - type: STR_SOUTH_AMERICA\n    cost: 600000\n    areas:\n      - [270, 315, -10, 0]\n      - [275, 330, 0, 15]\n      - [275, 325, 15, 60]\n    regionWeight: 10\n    missionWeights:\n      STR_ALIEN_RESEARCH: 10\n      STR_ALIEN_HARVEST: 24\n      STR_ALIEN_ABDUCTION: 12\n      STR_ALIEN_INFILTRATION: 18\n      STR_ALIEN_BASE: 22\n    missionZones:\n      -\n        - [280.375, 297.625, -11.875, -4.125]\n        - [279.125, 301.375, -1, 7.75]\n        - [305.5, 323.75, 0.875, 11]\n        - [281.625, 292.25, 10.75, 26.625]\n        - [302, 314.375, 22.75, 31.875]\n        - [289.125, 297.75, 38.5, 49.5]\n        - [281.375, 303.75, 48, 56.125]\n      -\n        - [312.875, 320.25, 6.25, 11.5]\n        - [290.75, 293.75, -8.625, -6.125]\n        - [290.5, 294.375, 28.875, 31.5]\n        - [303, 312.75, 21.75, 24.5]\n      -\n        - [284.25, 289.75, -8.375, -6.5]\n        - [305.375, 312, 13.25, 16.125]\n        - [289.875, 294.625, 34.625, 37.625]\n        - [287.875, 292.25, 47.25, 49.25]\n        - [299.5, 301.125, 51.375, 51.875]\n      -\n        - [312.125, 312.125, 15.75, 15.75, -1, STR_BRASILIA]\n        - [285.875, 285.875, -4.5, -4.5, -1, STR_BOGOTA]\n        - [302.5, 302.5, 34.5, 34.5, -1, STR_BUENOS_AIRES]\n        - [289.375, 289.375, 33.375, 33.375, -1, STR_SANTIAGO]\n        - [316.875, 316.875, 22.875, 22.875, -1, STR_RIO_DE_JANEIRO]\n        - [283, 283, 12, 12, -1, STR_LIMA]\n        - [293.125, 293.125, -10.5, -10.5, -1, STR_CARACAS]\n      -\n        - [290.125, 305.5, 1.5, 7.625]\n        - [285.875, 289.5, 13.625, 15.625]\n        - [290, 294.125, 41.25, 44.875]\n        - [289.375, 294.125, 22.875, 27.125]\n      -\n        - [0, 359.875, -90, -80]\n        - [0, 359.875, 80, 90]\n        - [180, 200, 0, 10]\n        - [355, 365, -5, 5]\n        - [170, 190, -60, -40]\n        - [21.5, 51.75, -31.875, -15.875]\n        - [238.625, 258.625, -53.375, -33.375]\n        - [4.75, 27.625, -52, -44.375]\n        - [75, 89, -39, -34.375]\n        - [115, 132.5, 21, 25.5]\n  - type: STR_EUROPE\n    cost: 1000000\n    areas:\n      - [335, 60, -70, -35]\n    regionWeight: 16\n    missionWeights:\n      STR_ALIEN_RESEARCH: 10\n      STR_ALIEN_HARVEST: 10\n      STR_ALIEN_ABDUCTION: 15\n      STR_ALIEN_INFILTRATION: 20\n      STR_ALIEN_BASE: 6\n    missionZones:\n      -\n        - [334, 396.125, -66.125, -58.125]\n        - [348, 361.875, -59.375, -49.375]\n        - [9.125, 27.75, -43.875, -37.875]\n        - [17.125, 50.25, -53.75, -48]\n        - [346.875, 363.5, -45.125, -38.5]\n      -\n        - [356.5, 360.25, -53, -51.875]\n        - [352.75, 357.5, -41.625, -39.125]\n        - [3.625, 12.5, -49.625, -48.25]\n        - [19.125, 24.75, -47.875, -45.5]\n      -\n        - [338.5, 341.5, -65.25, -64]\n        - [354.25, 355.75, -57.5, -56.625]\n        - [8.625, 10.375, -57, -56]\n        - [17.125, 27.875, -45.75, -43.125]\n        - [352.625, 358.875, -39.375, -37.75]\n      -\n        - [359.875, 359.875, -51.5, -51.5, -1, STR_LONDON]\n        - [2.375, 2.375, -48.75, -48.75, -1, STR_PARIS]\n        - [13.375, 13.375, -52.5, -52.5, -1, STR_BERLIN]\n        - [37.625, 37.625, -55.75, -55.75, -1, STR_MOSCOW]\n        - [12.5, 12.5, -41.875, -41.875, -1, STR_ROME]\n        - [356.25, 356.25, -40.375, -40.375, -1, STR_MADRID]\n        - [19.125, 19.125, -47.5, -47.5, -1, STR_BUDAPEST]\n      -\n        - [355.875, 357.25, -57.625, -57]\n        - [17.5, 29, -69.375, -67.625]\n        - [351.625, 353.25, -40.125, -38]\n        - [45.625, 51.5, -49.5, -47]\n        - [13.625, 26.625, -52.375, -47.625]\n      -\n        - [0, 359.875, -90, -80]\n        - [0, 359.875, 80, 90]\n        - [180, 200, 0, 10]\n        - [282.25, 322.875, 9.375, 38.375]\n        - [9.375, 45.375, -1, 35.75]\n        - [21.5, 51.75, -31.875, -15.875]\n        - [238.625, 258.625, -53.375, -33.375]\n        - [64.5, 125.5, -55.5, -44]\n        - [72.875, 105.25, -25, -11.75]\n        - [115, 132.5, 21, 25.5]\n  - type: STR_NORTH_AFRICA\n    cost: 650000\n    areas:\n      - [335, 40, -35, -15]\n      - [335, 55, -15, 0]\n    regionWeight: 12\n    missionWeights:\n      STR_ALIEN_RESEARCH: 8\n      STR_ALIEN_HARVEST: 8\n      STR_ALIEN_ABDUCTION: 8\n      STR_ALIEN_INFILTRATION: 8\n      STR_ALIEN_BASE: 19\n    missionZones:\n      -\n        - [348.5, 384.5, -34.5, -25]\n        - [339.625, 365.75, -18.375, -4.75]\n        - [13, 48.5, -14.625, -7.25]\n        - [29.625, 50.125, -30.75, -17.25]\n      -\n        - [354.25, 365.125, -34.5, -32.875]\n        - [345.625, 360.25, -13.875, -11.25]\n        - [29.5, 41.25, -13.25, -5.25]\n        - [20.625, 24.625, -32.125, -31.125]\n      -\n        - [348.625, 358.75, -27.125, -20.125]\n        - [23.375, 40.125, -13.75, -3.875]\n        - [348, 357.125, -10.75, -7.5]\n        - [2.25, 8.5, -35.875, -34.625]\n      -\n        - [3.125, 3.125, -6.5, -6.5, -1, STR_LAGOS]\n        - [31.25, 31.25, -30, -30, -1, STR_CAIRO]\n        - [352.375, 352.375, -33.5, -33.5, -1, STR_CASABLANCA]\n      -\n        - [5.625, 9, -6.125, -5]\n        - [15.75, 31.75, -26.125, -18.75]\n        - [350.375, 355.625, -8.375, -6.125]\n        - [348.125, 357.375, -26, -19]\n      -\n        - [0, 359.875, -90, -80]\n        - [0, 359.875, 80, 90]\n        - [180, 200, 0, 10]\n        - [282.25, 322.875, 9.375, 38.375]\n        - [66, 102, 2.625, 39.375]\n        - [354.5, 393.375, -56.625, -46.375]\n        - [238.625, 258.625, -53.375, -33.375]\n        - [64.5, 125.5, -55.5, -44]\n        - [72.875, 105.25, -25, -11.75]\n        - [115, 132.5, 21, 25.5]\n  - type: STR_SOUTHERN_AFRICA\n    cost: 550000\n    areas:\n      - [5, 55, 0, 40]\n    regionWeight: 8\n    missionWeights:\n      STR_ALIEN_RESEARCH: 7\n      STR_ALIEN_HARVEST: 8\n      STR_ALIEN_ABDUCTION: 8\n      STR_ALIEN_INFILTRATION: 8\n      STR_ALIEN_BASE: 9\n    missionZones:\n      -\n        - [7.125, 27, -0.375, 7.625]\n        - [40.875, 56.625, 12, 30.625]\n        - [11.25, 37, 21.75, 35.875]\n        - [27, 45.375, -3.875, 11]\n      -\n        - [19.875, 24.25, 28.5, 31.25]\n        - [44.75, 48.75, 16.875, 21.375]\n        - [14.125, 20.625, 6.125, 10.875]\n        - [13.375, 21.375, 16.625, 20.5]\n      -\n        - [12.375, 23.25, -1.5, 4.625]\n        - [30.5, 38.375, 11.625, 16.75]\n        - [17.75, 29.75, 26.25, 29.875]\n        - [45, 48.75, 16.25, 18.75]\n      -\n        - [28.125, 28.125, 26.25, 26.25, -1, STR_PRETORIA]\n        - [36.75, 36.75, 1.25, 1.25, -1, STR_NAIROBI]\n        - [18.5, 18.5, 34, 34, -1, STR_CAPE_TOWN]\n        - [15.375, 15.375, 4.375, 4.375, -1, STR_KINSHASA]\n      -\n        - [17.125, 23.25, 22.75, 27.125]\n        - [12, 26.875, -2.625, 4]\n        - [48.5, 49.875, 15.25, 17]\n        - [31.25, 36.75, 12.25, 15.625]\n      -\n        - [0, 359.875, -90, -80]\n        - [0, 359.875, 80, 90]\n        - [180, 200, 0, 10]\n        - [282.25, 322.875, 9.375, 38.375]\n        - [66, 102, 2.625, 39.375]\n        - [354.5, 393.375, -56.625, -46.375]\n        - [238.625, 258.625, -53.375, -33.375]\n        - [64.5, 125.5, -55.5, -44]\n        - [72.875, 105.25, -25, -11.75]\n        - [115, 132.5, 21, 25.5]\n  - type: STR_CENTRAL_ASIA\n    cost: 500000\n    areas:\n      - [40, 70, -35, -15]\n      - [60, 90, -50, -35]\n      - [70, 90, -35, -5]\n    regionWeight: 12\n    missionWeights:\n      STR_ALIEN_RESEARCH: 5\n      STR_ALIEN_HARVEST: 5\n      STR_ALIEN_ABDUCTION: 6\n      STR_ALIEN_INFILTRATION: 10\n      STR_ALIEN_BASE: 8\n    missionZones:\n      -\n        - [39.5, 53.125, -27.625, -16.125]\n        - [46.75, 65.25, -36.75, -29.75]\n        - [69.75, 86.625, -24.125, -5.25]\n        - [27.875, 49.25, -40.375, -35.625]\n        - [67.25, 86, -45.875, -31.5]\n      -\n        - [38.25, 47, -38.625, -35]\n        - [74.25, 79.75, -20.125, -15.375]\n        - [65.5, 70.25, -36.375, -31.875]\n        - [62.25, 80.625, -49.25, -46]\n      -\n        - [33.625, 47, -39.5, -37.875]\n        - [79.875, 81.125, -8.25, -6.875]\n        - [66.75, 81.5, -46.125, -43.5]\n        - [77.875, 89.375, -27, -23.375]\n      -\n        - [32.75, 32.75, -39.875, -39.875, -1, STR_ANKARA]\n        - [77.25, 77.25, -28.625, -28.625, -1, STR_DELHI]\n        - [67, 67, -24.875, -24.875, -1, STR_KARACHI]\n        - [44.5, 44.5, -33.25, -33.25, -1, STR_BAGHDAD]\n        - [51.5, 51.5, -35.625, -35.625, -1, STR_TEHRAN]\n        - [73.125, 73.125, -18.875, -18.875, -1, STR_BOMBAY]\n        - [88.375, 88.375, -22.625, -22.625, -1, STR_CALCUTTA]\n      -\n        - [42.375, 52.125, -23.5, -18.375]\n        - [77.75, 84.875, -36, -32.75]\n        - [80.75, 84.875, -22.875, -20.625]\n        - [80.125, 81.625, -7.375, -6.75]\n      -\n        - [0, 359.875, -90, -80]\n        - [0, 359.875, 80, 90]\n        - [180, 200, 0, 10]\n        - [282.25, 322.875, 9.375, 38.375]\n        - [66, 102, 2.625, 39.375]\n        - [354.5, 393.375, -56.625, -46.375]\n        - [238.625, 258.625, -53.375, -33.375]\n        - [7.5, 38.625, 4.125, 18.625]\n        - [137.125, 169.5, -54, -40.75]\n        - [115, 132.5, 21, 25.5]\n  - type: STR_SOUTH_EAST_ASIA\n    cost: 750000\n    areas:\n      - [90, 105, -50, 10]\n      - [105, 150, -50, -5]\n    regionWeight: 15\n    missionWeights:\n      STR_ALIEN_RESEARCH: 8\n      STR_ALIEN_HARVEST: 13\n      STR_ALIEN_ABDUCTION: 21\n      STR_ALIEN_INFILTRATION: 13\n      STR_ALIEN_BASE: 8\n    missionZones:\n      -\n        - [90.125, 108.25, -36.625, -22.625]\n        - [93.125, 124.75, -16.375, 6.75]\n        - [113.75, 143, -40, -20.75]\n        - [115.125, 148, -54.5, -39.625]\n      -\n        - [92.875, 102.5, -36.5, -31.125]\n        - [100.625, 106.375, -16.75, -13.625]\n        - [113.75, 129.375, -46.625, -41.375]\n        - [91.625, 104.75, -49.5, -46.875]\n      -\n        - [111.125, 117.5, -2, -0.375]\n        - [141, 143.75, -44.125, -42.625]\n        - [127, 137, -48.5, -45]\n        - [101.25, 111.875, -43.875, -37.875]\n      -\n        - [139.75, 139.75, -35.625, -35.625, -1, STR_TOKYO]\n        - [116.375, 116.375, -39.875, -39.875, -1, STR_BEIJING]\n        - [100.625, 100.625, -13.625, -13.625, -1, STR_BANGKOK]\n        - [121, 121, -14.625, -14.625, -1, STR_MANILA]\n        - [127, 127, -37.5, -37.5, -1, STR_SEOUL]\n        - [103.875, 103.875, -1.375, -1.375, -1, STR_SINGAPORE]\n        - [106.75, 106.75, 6.25, 6.25, -1, STR_JAKARTA]\n        - [121.5, 121.5, -31.25, -31.25, -1, STR_SHANGHAI]\n        - [114.125, 114.125, -22.25, -22.25, -1, STR_HONG_KONG]\n      -\n        - [100.625, 103.125, -0.375, 0.75]\n        - [96.125, 104.75, -42.625, -39]\n        - [142.125, 143.875, -51.25, -49.125]\n        - [122.875, 123.625, -8.375, -7.875]\n      -\n        - [0, 359.875, -90, -80]\n        - [0, 359.875, 80, 90]\n        - [180, 200, 0, 10]\n        - [282.25, 322.875, 9.375, 38.375]\n        - [53.125, 89.125, 4.5, 41.25]\n        - [354.5, 393.375, -56.625, -46.375]\n        - [238.625, 258.625, -53.375, -33.375]\n        - [7.5, 38.625, 4.125, 18.625]\n        - [50.5, 82.875, -64.5, -51.25]\n        - [115, 132.5, 21, 25.5]\n  - type: STR_SIBERIA\n    cost: 800000\n    areas:\n      - [60, 180, -70, -50]\n    regionWeight: 10\n    missionWeights:\n      STR_ALIEN_RESEARCH: 6\n      STR_ALIEN_ABDUCTION: 4\n      STR_ALIEN_BASE: 9\n    missionZones:\n      -\n        - [49.875, 80.125, -66.75, -46.5]\n        - [67.25, 188.75, -72.5, -57.75]\n        - [86.25, 164.25, -61.75, -52.875]\n        - [65, 85.125, -52.25, -49.25]\n      -\n        - [63.125, 78.375, -66.5, -62]\n        - [157.75, 162.5, -57.25, -55.625]\n        - [166.125, 181.25, -68.625, -66]\n        - [99.625, 139.125, -66.125, -58.125]\n      -\n        - [53.25, 66.625, -64.875, -61]\n        - [86, 97.75, -73.25, -68.875]\n        - [125.875, 141.5, -64.25, -59.5]\n        - [91.375, 108.875, -61.375, -57.375]\n      -\n        - [82.75, 82.75, -55, -55, -1, STR_NOVOSIBIRSK]\n      -\n        - [63.125, 78.375, -66.5, -62]\n        - [157.75, 162.5, -57.25, -55.625]\n        - [166.125, 181.25, -68.625, -66]\n        - [99.625, 139.125, -66.125, -58.125]\n      -\n        - [0, 359.875, -90, -80]\n        - [0, 359.875, 80, 90]\n        - [180, 200, 0, 10]\n        - [282.25, 322.875, 9.375, 38.375]\n        - [53.125, 89.125, 4.5, 41.25]\n        - [354.5, 393.375, -56.625, -46.375]\n        - [238.625, 258.625, -53.375, -33.375]\n        - [7.5, 38.625, 4.125, 18.625]\n        - [91.875, 124.25, -30.75, -17.5]\n        - [115, 132.5, 21, 25.5]\n  - type: STR_AUSTRALASIA\n    cost: 750000\n    areas:\n      - [105, 180, -5, 60]\n    regionWeight: 10\n    missionWeights:\n      STR_ALIEN_RESEARCH: 15\n      STR_ALIEN_HARVEST: 11\n      STR_ALIEN_ABDUCTION: 4\n      STR_ALIEN_INFILTRATION: 8\n      STR_ALIEN_BASE: 16\n    missionZones:\n      -\n        - [129.625, 155.375, -1.875, 9.75]\n        - [165.75, 179.5, 33.125, 47.125]\n        - [136.125, 153.25, 11.5, 46]\n        - [109, 134.75, 13.375, 35.125]\n      -\n        - [115.75, 123.125, 30.375, 33.125]\n        - [129.875, 134.25, 14, 16.5]\n        - [141.125, 147, 29.875, 32.75]\n        - [175, 177, 37.875, 39.375]\n      -\n        - [138.125, 144.125, 2.5, 5]\n        - [145.625, 147.625, 41, 41.75]\n        - [168.5, 170.375, 44.25, 45.25]\n        - [141.375, 150.125, 32.875, 36.375]\n      -\n        - [149.125, 149.125, 35.375, 35.375, -1, STR_CANBERRA]\n        - [175.125, 175.125, 41.25, 41.25, -1, STR_WELLINGTON]\n        - [145, 145, 37.875, 37.875, -1, STR_MELBOURNE]\n        - [115.75, 115.75, 32, 32, -1, STR_PERTH]\n      -\n        - [122.25, 135.375, 21, 27.5]\n        - [149.875, 151.25, 4.75, 5.5]\n        - [140.875, 143.625, 8.125, 8.875]\n        - [145.75, 147.625, 41, 41.625]\n      -\n        - [0, 359.875, -90, -80]\n        - [0, 359.875, 80, 90]\n        - [180, 200, 0, 10]\n        - [282.25, 322.875, 9.375, 38.375]\n        - [53.125, 89.125, 4.5, 41.25]\n        - [354.5, 393.375, -56.625, -46.375]\n        - [238.625, 258.625, -53.375, -33.375]\n        - [7.5, 38.625, 4.125, 18.625]\n        - [91.875, 124.25, -30.75, -17.5]\n        - [62.125, 101.375, -66.625, -57.125]\n  - type: STR_PACIFIC\n    cost: 600000\n    areas:\n      - [180, 195, -70, -55]\n      - [180, 230, -55, -30]\n      - [180, 240, -30, -10]\n      - [180, 270, -10, -0]\n      - [180, 275, 0, 60]\n      - [150, 180, -50, -5]\n    regionWeight: 5\n    missionWeights:\n      STR_ALIEN_RESEARCH: 15\n      STR_ALIEN_BASE: 27\n    missionZones:\n      -\n        - [194.5, 225.625, -29.25, -15.25]\n        - [172.5, 186.875, 10.875, 26.375]\n        - [158.375, 171.375, 12.25, 27.75]\n        - [202.625, 245.625, -2.25, 18.375]\n      -\n        - [209.125, 209.625, -19.875, -19.375]\n        - [207, 207.125, -21.625, -21.5]\n        - [177.75, 178.25, 17.5, 17.875]\n        - [164.625, 164.75, 20.5, 20.75]\n      -\n        - [209.125, 209.625, -19.875, -19.375]\n        - [207, 207.125, -21.625, -21.5]\n        - [177.75, 178.25, 17.5, 17.875]\n        - [164.625, 164.75, 20.5, 20.75]\n      -\n        - [209.125, 209.625, -19.875, -19.375]\n        - [207, 207.125, -21.625, -21.5]\n      -\n        - [209.125, 209.625, -19.875, -19.375]\n        - [207, 207.125, -21.625, -21.5]\n        - [177.75, 178.25, 17.5, 17.875]\n        - [164.625, 164.75, 20.5, 20.75]\n      -\n        - [0, 359.875, -90, -80]\n        - [0, 359.875, 80, 90]\n        - [119.625, 139.625, 19.25, 29.25]\n        - [282.25, 322.875, 9.375, 38.375]\n        - [53.125, 89.125, 4.5, 41.25]\n        - [354.5, 393.375, -56.625, -46.375]\n        - [238.625, 258.625, -53.375, -33.375]\n        - [7.5, 38.625, 4.125, 18.625]\n        - [91.875, 124.25, -30.75, -17.5]\n        - [62.125, 101.375, -66.625, -57.125]\n  - type: STR_NORTH_ATLANTIC\n    cost: 500000\n    missionRegion: STR_NORTH_AMERICA\n    areas:\n      - [305, 335, -70, -30]\n      - [300, 335, -30, -10]\n      - [315, 335, -10, 0]\n  - type: STR_SOUTH_ATLANTIC\n    cost: 500000\n    missionRegion: STR_ANTARCTICA\n    areas:\n      - [330, 5, 0,  15]\n      - [325, 5, 15, 60]\n      - [5, 55, 40, 60]\n  - type: STR_INDIAN_OCEAN\n    cost: 500000\n    missionRegion: STR_SOUTHERN_AFRICA\n    areas:\n      - [55, 70, -15, 10]\n      - [70, 90, -5, 10]\n      - [55, 105, 10, 60]"
  },
  {
    "path": "bin/standard/xcom1/research.rul",
    "content": "research:\n  - name: STR_LASER_WEAPONS\n    cost: 50\n    points: 10\n  - name: STR_MOTION_SCANNER\n    cost: 180\n    points: 20\n  - name: STR_MEDI_KIT\n    cost: 210\n    points: 20\n  - name: STR_PSI_AMP\n    cost: 500\n    points: 20\n    dependencies:\n      - STR_PSI_LAB\n  - name: STR_HEAVY_PLASMA\n    cost: 800\n    points: 30\n    needItem: true\n  - name: STR_HEAVY_PLASMA_CLIP\n    cost: 400\n    points: 7\n    needItem: true\n  - name: STR_PLASMA_RIFLE\n    cost: 700\n    points: 25\n    needItem: true\n  - name: STR_PLASMA_RIFLE_CLIP\n    cost: 400\n    points: 6\n    needItem: true\n  - name: STR_PLASMA_PISTOL\n    cost: 600\n    points: 20\n    needItem: true\n  - name: STR_PLASMA_PISTOL_CLIP\n    cost: 400\n    points: 5\n    needItem: true\n  - name: STR_BLASTER_LAUNCHER\n    cost: 900\n    points: 10\n    needItem: true\n  - name: STR_BLASTER_BOMB\n    cost: 300\n    points: 10\n    needItem: true\n  - name: STR_SMALL_LAUNCHER\n    cost: 550\n    points: 30\n    needItem: true\n  - name: STR_STUN_BOMB\n    cost: 180\n    points: 10\n    needItem: true\n  - name: STR_ALIEN_GRENADE\n    cost: 200\n    points: 20\n    needItem: true\n  - name: STR_ELERIUM_115\n    cost: 450\n    points: 60\n    needItem: true\n  - name: STR_MIND_PROBE\n    cost: 600\n    points: 25\n    needItem: true\n  - name: STR_UFO_POWER_SOURCE\n    cost: 450\n    points: 30\n    needItem: true\n  - name: STR_UFO_NAVIGATION\n    cost: 450\n    points: 30\n    needItem: true\n  - name: STR_UFO_CONSTRUCTION\n    cost: 450\n    points: 30\n    dependencies:\n      - STR_ALIEN_ALLOYS\n      - STR_ELERIUM_115\n      - STR_UFO_POWER_SOURCE\n      - STR_UFO_NAVIGATION\n  - name: STR_ALIEN_FOOD\n    cost: 150\n    points: 30\n    needItem: true\n  - name: STR_ALIEN_REPRODUCTION\n    cost: 150\n    points: 30\n    needItem: true\n  - name: STR_ALIEN_ENTERTAINMENT\n    cost: 150\n    points: 30\n    needItem: true\n  - name: STR_ALIEN_SURGERY\n    cost: 150\n    points: 30\n    needItem: true\n  - name: STR_EXAMINATION_ROOM\n    cost: 150\n    points: 30\n    needItem: true\n  - name: STR_ALIEN_ALLOYS\n    cost: 400\n    points: 30\n    needItem: true\n  - name: STR_NEW_FIGHTER_CRAFT\n    cost: 600\n    points: 30\n    dependencies:\n      - STR_UFO_CONSTRUCTION\n  - name: STR_NEW_FIGHTER_TRANSPORTER\n    cost: 700\n    points: 30\n    dependencies:\n      - STR_NEW_FIGHTER_CRAFT\n  - name: STR_ULTIMATE_CRAFT\n    cost: 900\n    points: 30\n    dependencies:\n      - STR_NEW_FIGHTER_TRANSPORTER\n  - name: STR_LASER_PISTOL\n    cost: 100\n    points: 10\n    dependencies:\n      - STR_LASER_WEAPONS\n  - name: STR_LASER_RIFLE\n    cost: 300\n    points: 10\n    dependencies:\n      - STR_LASER_PISTOL\n  - name: STR_HEAVY_LASER\n    cost: 460\n    points: 10\n    dependencies:\n      - STR_LASER_RIFLE\n  - name: STR_LASER_CANNON\n    cost: 420\n    points: 15\n    dependencies:\n      - STR_HEAVY_LASER\n  - name: STR_PLASMA_CANNON\n    cost: 660\n    points: 25\n    dependencies:\n      - STR_PLASMA_CANNON_DEP1\n      - STR_PLASMA_CANNON_DEP2\n  - name: STR_FUSION_MISSILE\n    cost: 880\n    points: 25\n    dependencies:\n      - STR_BLASTER_LAUNCHER\n      - STR_BLASTER_BOMB\n  - name: STR_LASER_DEFENSE\n    cost: 510\n    points: 15\n    dependencies:\n      - STR_LASER_CANNON\n  - name: STR_PLASMA_DEFENSE\n    cost: 620\n    points: 25\n    dependencies:\n      - STR_PLASMA_CANNON\n  - name: STR_FUSION_DEFENSE\n    cost: 800\n    points: 25\n    dependencies:\n      - STR_FUSION_MISSILE\n  - name: STR_GRAV_SHIELD\n    cost: 930\n    points: 25\n    dependencies:\n      - STR_NEW_FIGHTER_TRANSPORTER\n  - name: STR_MIND_SHIELD\n    cost: 360\n    points: 25\n    dependencies:\n      - STR_PSI_LAB\n  - name: STR_PSI_LAB\n    cost: 420\n    points: 25\n    dependencies:\n      - STR_ETHEREAL_COMMANDER\n      - STR_ETHEREAL_LEADER\n      - STR_ETHEREAL_SOLDIER\n      - STR_SECTOID_LEADER\n      - STR_SECTOID_COMMANDER\n  - name: STR_HYPER_WAVE_DECODER\n    cost: 670\n    points: 25\n    dependencies:\n      - STR_FLOATER_NAVIGATOR\n      - STR_SNAKEMAN_NAVIGATOR\n      - STR_MUTON_NAVIGATOR\n      - STR_SECTOID_NAVIGATOR\n  - name: STR_LEADER_PLUS\n    requires:\n      - STR_ALIEN_ORIGINS\n    dependencies:\n      - STR_SECTOID_COMMANDER\n      - STR_SECTOID_LEADER\n      - STR_SNAKEMAN_COMMANDER\n      - STR_SNAKEMAN_LEADER\n      - STR_ETHEREAL_COMMANDER\n      - STR_ETHEREAL_LEADER\n      - STR_FLOATER_COMMANDER\n      - STR_FLOATER_LEADER\n  - name: STR_COMMANDER_PLUS\n    unlocks:\n      - STR_CYDONIA_OR_BUST\n    requires:\n      - STR_THE_MARTIAN_SOLUTION\n    dependencies:\n      - STR_SECTOID_COMMANDER\n      - STR_SNAKEMAN_COMMANDER\n      - STR_ETHEREAL_COMMANDER\n      - STR_FLOATER_COMMANDER\n  - name: STR_SECTOID_CORPSE\n    cost: 180\n    points: 50\n    lookup: STR_SECTOID_AUTOPSY\n    needItem: true\n  - name: STR_SNAKEMAN_CORPSE\n    cost: 180\n    points: 50\n    lookup: STR_SNAKEMAN_AUTOPSY\n    needItem: true\n  - name: STR_ETHEREAL_CORPSE\n    cost: 180\n    points: 50\n    lookup: STR_ETHEREAL_AUTOPSY\n    needItem: true\n  - name: STR_MUTON_CORPSE\n    cost: 180\n    points: 50\n    lookup: STR_MUTON_AUTOPSY\n    needItem: true\n  - name: STR_FLOATER_CORPSE\n    cost: 180\n    points: 50\n    lookup: STR_FLOATER_AUTOPSY\n    needItem: true\n  - name: STR_CELATID_CORPSE\n    cost: 180\n    points: 50\n    lookup: STR_CELATID_AUTOPSY\n    needItem: true\n  - name: STR_SILACOID_CORPSE\n    cost: 180\n    points: 50\n    lookup: STR_SILACOID_AUTOPSY\n    needItem: true\n  - name: STR_CHRYSSALID_CORPSE\n    cost: 180\n    points: 50\n    lookup: STR_CHRYSSALID_AUTOPSY\n    needItem: true\n  - name: STR_REAPER_CORPSE\n    cost: 180\n    points: 50\n    lookup: STR_REAPER_AUTOPSY\n    needItem: true\n  - name: STR_SECTOPOD_CORPSE\n    cost: 180\n    points: 50\n    lookup: STR_SECTOPOD_AUTOPSY\n    needItem: true\n  - name: STR_CYBERDISC_CORPSE\n    cost: 180\n    points: 50\n    lookup: STR_CYBERDISC_AUTOPSY\n    needItem: true\n  - name: STR_ALIEN_ORIGINS\n    cost: 300\n    points: 60\n    dependencies:\n      - STR_SECTOID_COMMANDER\n      - STR_SECTOID_LEADER\n      - STR_SECTOID_ENGINEER\n      - STR_SECTOID_MEDIC\n      - STR_SECTOID_NAVIGATOR\n      - STR_SECTOID_SOLDIER\n      - STR_CYBERDISC_TERRORIST\n      - STR_SNAKEMAN_COMMANDER\n      - STR_SNAKEMAN_LEADER\n      - STR_SNAKEMAN_ENGINEER\n      - STR_SNAKEMAN_NAVIGATOR\n      - STR_SNAKEMAN_SOLDIER\n      - STR_CHRYSSALID_TERRORIST\n      - STR_ETHEREAL_COMMANDER\n      - STR_ETHEREAL_LEADER\n      - STR_ETHEREAL_SOLDIER\n      - STR_SECTOPOD_TERRORIST\n      - STR_MUTON_ENGINEER\n      - STR_MUTON_NAVIGATOR\n      - STR_MUTON_SOLDIER\n      - STR_SILACOID_TERRORIST\n      - STR_CELATID_TERRORIST\n      - STR_FLOATER_COMMANDER\n      - STR_FLOATER_LEADER\n      - STR_FLOATER_ENGINEER\n      - STR_FLOATER_MEDIC\n      - STR_FLOATER_NAVIGATOR\n      - STR_FLOATER_SOLDIER\n      - STR_REAPER_TERRORIST\n  - name: STR_THE_MARTIAN_SOLUTION\n    cost: 500\n    points: 60\n    dependencies:\n      - STR_ALIEN_ORIGINS\n      - STR_LEADER_PLUS\n  - name: STR_CYDONIA_OR_BUST\n    cost: 600\n    points: 60\n    unlockFinalMission: true\n    dependencies:\n      - STR_COMMANDER_PLUS\n  - name: STR_PERSONAL_ARMOR\n    cost: 180\n    points: 20\n    dependencies:\n      - STR_ALIEN_ALLOYS\n  - name: STR_POWER_SUIT\n    cost: 205\n    points: 20\n    dependencies:\n      - STR_ELERIUM_115\n      - STR_UFO_POWER_SOURCE\n      - STR_PERSONAL_ARMOR\n  - name: STR_FLYING_SUIT\n    cost: 330\n    points: 20\n    dependencies:\n      - STR_POWER_SUIT\n      - STR_UFO_NAVIGATION\n  - name: STR_SECTOID_COMMANDER\n    cost: 190\n    points: 50\n    needItem: true\n    destroyItem: true\n    lookup: STR_SECTOID\n    unlocks:\n      - STR_LEADER_PLUS\n      - STR_COMMANDER_PLUS\n      - STR_ALIEN_ORIGINS\n      - STR_PSI_LAB\n  - name: STR_SECTOID_LEADER\n    cost: 192\n    points: 50\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_LEADER_PLUS\n      - STR_PSI_LAB\n      - STR_ALIEN_ORIGINS\n    lookup: STR_SECTOID\n  - name: STR_SECTOID_ENGINEER\n    cost: 192\n    points: 50\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_ALIEN_ORIGINS\n    lookup: STR_SECTOID\n    getOneFree:\n      - STR_SMALL_SCOUT\n      - STR_MEDIUM_SCOUT\n      - STR_LARGE_SCOUT\n      - STR_HARVESTER\n      - STR_ABDUCTOR\n      - STR_TERROR_SHIP\n      - STR_BATTLESHIP\n      - STR_SUPPLY_SHIP\n  - name: STR_SECTOID_MEDIC\n    cost: 192\n    points: 50\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_ALIEN_ORIGINS\n    lookup: STR_SECTOID\n    getOneFree:\n      - STR_SNAKEMAN\n      - STR_MUTON\n      - STR_ETHEREAL\n      - STR_FLOATER\n      - STR_CHRYSSALID\n      - STR_SECTOPOD\n      - STR_CYBERDISC\n      - STR_SILACOID\n      - STR_CELATID\n      - STR_REAPER\n      - STR_SECTOID_CORPSE\n      - STR_SNAKEMAN_CORPSE\n      - STR_MUTON_CORPSE\n      - STR_ETHEREAL_CORPSE\n      - STR_FLOATER_CORPSE\n      - STR_CHRYSSALID_CORPSE\n      - STR_SECTOPOD_CORPSE\n      - STR_CYBERDISC_CORPSE\n      - STR_SILACOID_CORPSE\n      - STR_CELATID_CORPSE\n      - STR_REAPER_CORPSE\n  - name: STR_SECTOID_NAVIGATOR\n    cost: 192\n    points: 50\n    lookup: STR_SECTOID\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_ALIEN_ORIGINS\n      - STR_HYPER_WAVE_DECODER\n    getOneFree:\n      - STR_ALIEN_RESEARCH\n      - STR_ALIEN_HARVEST\n      - STR_ALIEN_ABDUCTION\n      - STR_ALIEN_INFILTRATION\n      - STR_ALIEN_BASE\n      - STR_ALIEN_TERROR\n      - STR_ALIEN_RETALIATION\n      - STR_ALIEN_SUPPLY\n  - name: STR_SECTOID_SOLDIER\n    cost: 192\n    points: 50\n    lookup: STR_SECTOID\n    unlocks:\n      - STR_ALIEN_ORIGINS\n    needItem: true\n    destroyItem: true\n  - name: STR_SNAKEMAN_COMMANDER\n    cost: 192\n    points: 50\n    lookup: STR_SNAKEMAN\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_LEADER_PLUS\n      - STR_COMMANDER_PLUS\n      - STR_ALIEN_ORIGINS\n  - name: STR_SNAKEMAN_LEADER\n    cost: 192\n    points: 50\n    lookup: STR_SNAKEMAN\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_LEADER_PLUS\n      - STR_ALIEN_ORIGINS\n  - name: STR_SNAKEMAN_ENGINEER\n    cost: 192\n    points: 50\n    lookup: STR_SNAKEMAN\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_ALIEN_ORIGINS\n    getOneFree:\n      - STR_SMALL_SCOUT\n      - STR_MEDIUM_SCOUT\n      - STR_LARGE_SCOUT\n      - STR_HARVESTER\n      - STR_ABDUCTOR\n      - STR_TERROR_SHIP\n      - STR_BATTLESHIP\n      - STR_SUPPLY_SHIP\n  - name: STR_SNAKEMAN_MEDIC\n    needItem: true\n    destroyItem: true\n  - name: STR_SNAKEMAN_NAVIGATOR\n    cost: 192\n    points: 50\n    lookup: STR_SNAKEMAN\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_ALIEN_ORIGINS\n      - STR_HYPER_WAVE_DECODER\n    getOneFree:\n      - STR_ALIEN_RESEARCH\n      - STR_ALIEN_HARVEST\n      - STR_ALIEN_ABDUCTION\n      - STR_ALIEN_INFILTRATION\n      - STR_ALIEN_BASE\n      - STR_ALIEN_TERROR\n      - STR_ALIEN_RETALIATION\n      - STR_ALIEN_SUPPLY\n  - name: STR_SNAKEMAN_SOLDIER\n    cost: 192\n    points: 50\n    lookup: STR_SNAKEMAN\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_ALIEN_ORIGINS\n  - name: STR_ETHEREAL_COMMANDER\n    cost: 192\n    points: 50\n    lookup: STR_ETHEREAL\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_LEADER_PLUS\n      - STR_COMMANDER_PLUS\n      - STR_ALIEN_ORIGINS\n      - STR_PSI_LAB\n  - name: STR_ETHEREAL_LEADER\n    cost: 192\n    points: 50\n    lookup: STR_ETHEREAL\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_LEADER_PLUS\n      - STR_ALIEN_ORIGINS\n      - STR_PSI_LAB\n  - name: STR_ETHEREAL_ENGINEER\n    needItem: true\n    destroyItem: true\n  - name: STR_ETHEREAL_MEDIC\n    needItem: true\n    destroyItem: true\n  - name: STR_ETHEREAL_NAVIGATOR\n    needItem: true\n    destroyItem: true\n  - name: STR_ETHEREAL_SOLDIER\n    cost: 192\n    points: 50\n    lookup: STR_ETHEREAL\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_ALIEN_ORIGINS\n      - STR_PSI_LAB\n  - name: STR_MUTON_COMMANDER\n    needItem: true\n    destroyItem: true\n  - name: STR_MUTON_LEADER\n    needItem: true\n    destroyItem: true\n  - name: STR_MUTON_ENGINEER\n    cost: 192\n    points: 50\n    lookup: STR_MUTON\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_ALIEN_ORIGINS\n    getOneFree:\n      - STR_SMALL_SCOUT\n      - STR_MEDIUM_SCOUT\n      - STR_LARGE_SCOUT\n      - STR_HARVESTER\n      - STR_ABDUCTOR\n      - STR_TERROR_SHIP\n      - STR_BATTLESHIP\n      - STR_SUPPLY_SHIP\n  - name: STR_MUTON_MEDIC\n    needItem: true\n    destroyItem: true\n  - name: STR_MUTON_NAVIGATOR\n    cost: 192\n    points: 50\n    lookup: STR_MUTON\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_ALIEN_ORIGINS\n      - STR_HYPER_WAVE_DECODER\n    getOneFree:\n      - STR_ALIEN_RESEARCH\n      - STR_ALIEN_HARVEST\n      - STR_ALIEN_ABDUCTION\n      - STR_ALIEN_INFILTRATION\n      - STR_ALIEN_BASE\n      - STR_ALIEN_TERROR\n      - STR_ALIEN_RETALIATION\n      - STR_ALIEN_SUPPLY\n  - name: STR_MUTON_SOLDIER\n    cost: 192\n    points: 50\n    lookup: STR_MUTON\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_ALIEN_ORIGINS\n  - name: STR_FLOATER_COMMANDER\n    cost: 192\n    points: 50\n    lookup: STR_FLOATER\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_LEADER_PLUS\n      - STR_COMMANDER_PLUS\n      - STR_ALIEN_ORIGINS\n  - name: STR_FLOATER_LEADER\n    cost: 192\n    points: 50\n    lookup: STR_FLOATER\n    unlocks:\n      - STR_LEADER_PLUS\n      - STR_ALIEN_ORIGINS\n    needItem: true\n    destroyItem: true\n  - name: STR_FLOATER_ENGINEER\n    cost: 192\n    points: 50\n    lookup: STR_FLOATER\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_ALIEN_ORIGINS\n    getOneFree:\n      - STR_SMALL_SCOUT\n      - STR_MEDIUM_SCOUT\n      - STR_LARGE_SCOUT\n      - STR_HARVESTER\n      - STR_ABDUCTOR\n      - STR_TERROR_SHIP\n      - STR_BATTLESHIP\n      - STR_SUPPLY_SHIP\n  - name: STR_FLOATER_MEDIC\n    cost: 192\n    points: 50\n    lookup: STR_FLOATER\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_ALIEN_ORIGINS\n    getOneFree:\n      - STR_SECTOID\n      - STR_SNAKEMAN\n      - STR_MUTON\n      - STR_ETHEREAL\n      - STR_CHRYSSALID\n      - STR_SECTOPOD\n      - STR_CYBERDISC\n      - STR_SILACOID\n      - STR_CELATID\n      - STR_REAPER\n      - STR_SECTOID_CORPSE\n      - STR_SNAKEMAN_CORPSE\n      - STR_MUTON_CORPSE\n      - STR_ETHEREAL_CORPSE\n      - STR_FLOATER_CORPSE\n      - STR_CHRYSSALID_CORPSE\n      - STR_SECTOPOD_CORPSE\n      - STR_CYBERDISC_CORPSE\n      - STR_SILACOID_CORPSE\n      - STR_CELATID_CORPSE\n      - STR_REAPER_CORPSE\n  - name: STR_FLOATER_NAVIGATOR\n    cost: 192\n    points: 50\n    lookup: STR_FLOATER\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_ALIEN_ORIGINS\n      - STR_HYPER_WAVE_DECODER\n    getOneFree:\n      - STR_ALIEN_RESEARCH\n      - STR_ALIEN_HARVEST\n      - STR_ALIEN_ABDUCTION\n      - STR_ALIEN_INFILTRATION\n      - STR_ALIEN_BASE\n      - STR_ALIEN_TERROR\n      - STR_ALIEN_RETALIATION\n      - STR_ALIEN_SUPPLY\n  - name: STR_FLOATER_SOLDIER\n    cost: 192\n    points: 50\n    lookup: STR_FLOATER\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_ALIEN_ORIGINS\n  - name: STR_CELATID_TERRORIST\n    cost: 170\n    points: 50\n    lookup: STR_CELATID\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_ALIEN_ORIGINS\n  - name: STR_SILACOID_TERRORIST\n    cost: 170\n    points: 50\n    lookup: STR_SILACOID\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_ALIEN_ORIGINS\n  - name: STR_CHRYSSALID_TERRORIST\n    cost: 170\n    points: 50\n    lookup: STR_CHRYSSALID\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_ALIEN_ORIGINS\n  - name: STR_REAPER_TERRORIST\n    cost: 170\n    points: 50\n    lookup: STR_REAPER\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_ALIEN_ORIGINS\n  - name: STR_SECTOPOD_TERRORIST\n    cost: 170\n    points: 50\n    lookup: STR_SECTOPOD\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_ALIEN_ORIGINS\n  - name: STR_CYBERDISC_TERRORIST\n    cost: 170\n    points: 50\n    lookup: STR_CYBERDISC\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_ALIEN_ORIGINS\n  - name: STR_PLASMA_CANNON_DEP1\n    dependencies:\n      - STR_HEAVY_PLASMA\n      - STR_HEAVY_PLASMA_CLIP\n    unlocks:\n      - STR_PLASMA_CANNON\n  - name: STR_PLASMA_CANNON_DEP2\n    dependencies:\n      - STR_PLASMA_RIFLE\n      - STR_PLASMA_RIFLE_CLIP\n    unlocks:\n      - STR_PLASMA_CANNON\n  - name: STR_SECTOID_AUTOPSY\n    points: 50\n    needItem: true\n  - name: STR_SNAKEMAN_AUTOPSY\n    points: 50\n    needItem: true\n  - name: STR_ETHEREAL_AUTOPSY\n    points: 50\n    needItem: true\n  - name: STR_MUTON_AUTOPSY\n    points: 50\n    needItem: true\n  - name: STR_FLOATER_AUTOPSY\n    points: 50\n    needItem: true\n  - name: STR_CELATID_AUTOPSY\n    points: 50\n    needItem: true\n  - name: STR_SILACOID_AUTOPSY\n    points: 50\n    needItem: true\n  - name: STR_CHRYSSALID_AUTOPSY\n    points: 50\n    needItem: true\n  - name: STR_REAPER_AUTOPSY\n    points: 50\n    needItem: true\n  - name: STR_SECTOPOD_AUTOPSY\n    points: 50\n    needItem: true\n  - name: STR_CYBERDISC_AUTOPSY\n    points: 50\n    needItem: true\n  - name: STR_SECTOID\n    points: 50\n    needItem: true\n  - name: STR_SNAKEMAN\n    points: 50\n    needItem: true\n  - name: STR_ETHEREAL\n    points: 50\n    needItem: true\n  - name: STR_MUTON\n    points: 50\n    needItem: true\n  - name: STR_FLOATER\n    points: 50\n    needItem: true\n  - name: STR_CELATID\n    points: 50\n    needItem: true\n  - name: STR_SILACOID\n    points: 50\n    needItem: true\n  - name: STR_CHRYSSALID\n    points: 50\n    needItem: true\n  - name: STR_REAPER\n    points: 50\n    needItem: true\n  - name: STR_SECTOPOD\n    points: 50\n    needItem: true\n  - name: STR_CYBERDISC\n    points: 50\n    needItem: true\n  - name: STR_ALIEN_RESEARCH\n    points: 50\n    needItem: true\n  - name: STR_ALIEN_HARVEST\n    points: 50\n    needItem: true\n  - name: STR_ALIEN_ABDUCTION\n    points: 50\n    needItem: true\n  - name: STR_ALIEN_INFILTRATION\n    points: 50\n    needItem: true\n  - name: STR_ALIEN_BASE\n    points: 50\n    needItem: true\n  - name: STR_ALIEN_TERROR\n    points: 50\n    needItem: true\n  - name: STR_ALIEN_RETALIATION\n    points: 50\n    needItem: true\n  - name: STR_ALIEN_SUPPLY\n    points: 50\n    needItem: true\n  - name: STR_SMALL_SCOUT\n    points: 50\n    needItem: true\n  - name: STR_MEDIUM_SCOUT\n    points: 50\n    needItem: true\n  - name: STR_LARGE_SCOUT\n    points: 50\n    needItem: true\n  - name: STR_HARVESTER\n    points: 50\n    needItem: true\n  - name: STR_ABDUCTOR\n    points: 50\n    needItem: true\n  - name: STR_TERROR_SHIP\n    points: 50\n    needItem: true\n  - name: STR_BATTLESHIP\n    points: 50\n    needItem: true\n  - name: STR_SUPPLY_SHIP\n    points: 50\n    needItem: true\n"
  },
  {
    "path": "bin/standard/xcom1/soldiers.rul",
    "content": "soldiers:\n  - type: STR_SOLDIER\n    costBuy: 40000\n    costSalary: 20000\n    minStats:\n      tu: 50\n      stamina: 40\n      health: 25\n      bravery: 10\n      reactions: 30\n      firing: 40\n      throwing: 50\n      strength: 20\n      psiStrength: 0\n      psiSkill: 0\n      melee: 20\n    maxStats:\n      tu: 60\n      stamina: 70\n      health: 40\n      bravery: 60\n      reactions: 60\n      firing: 70\n      throwing: 80\n      strength: 40\n      psiStrength: 100\n      psiSkill: 16\n      melee: 40\n    statCaps:\n      tu: 80\n      stamina: 100\n      health: 60\n      bravery: 100\n      reactions: 100\n      firing: 120\n      throwing: 120\n      strength: 70\n      psiStrength: 100\n      psiSkill: 100\n      melee: 120\n    armor: STR_NONE_UC\n    standHeight: 22\n    kneelHeight: 14\n    femaleFrequency: 25\n    soldierNames:\n      - SoldierName/\n    deathMale: [41, 42, 43]\n    deathFemale: [44, 45, 46]"
  },
  {
    "path": "bin/standard/xcom1/startingBase.rul",
    "content": "startingBase:\n  facilities:\n    - type: STR_ACCESS_LIFT\n      x: 2\n      y: 2\n    - type: STR_HANGAR\n      x: 2\n      y: 0\n    - type: STR_HANGAR\n      x: 0\n      y: 4\n    - type: STR_HANGAR\n      x: 4\n      y: 4\n    - type: STR_LIVING_QUARTERS\n      x: 3\n      y: 2\n    - type: STR_GENERAL_STORES\n      x: 2\n      y: 3\n    - type: STR_LABORATORY\n      x: 3\n      y: 3\n    - type: STR_WORKSHOP\n      x: 4\n      y: 3\n    - type: STR_SMALL_RADAR_SYSTEM\n      x: 1\n      y: 3\n  randomSoldiers: 8\n  crafts:\n    - type: STR_SKYRANGER\n      id: 1\n      fuel: 1500\n      damage: 0\n      items:\n        STR_GRENADE: 8\n        STR_HC_AP_AMMO: 2\n        STR_HC_HE_AMMO: 2\n        STR_HEAVY_CANNON: 1\n        STR_PISTOL: 3\n        STR_PISTOL_CLIP: 5\n        STR_RIFLE: 6\n        STR_RIFLE_CLIP: 12\n      status: STR_READY\n    - type: STR_INTERCEPTOR\n      id: 1\n      fuel: 1000\n      damage: 0\n      weapons:\n        - type: STR_STINGRAY\n          ammo: 6\n        - type: STR_CANNON_UC\n          ammo: 200\n      status: STR_READY\n    - type: STR_INTERCEPTOR\n      id: 2\n      fuel: 1000\n      damage: 0\n      weapons:\n        - type: STR_STINGRAY\n          ammo: 6\n        - type: STR_CANNON_UC\n          ammo: 200\n  items:\n    STR_AC_AP_AMMO: 6\n    STR_AUTO_CANNON: 1\n    STR_AVALANCHE_LAUNCHER: 1\n    STR_AVALANCHE_MISSILES: 10\n    STR_CANNON: 2\n    STR_CANNON_ROUNDS_X50: 1\n    STR_GRENADE: 5\n    STR_HC_AP_AMMO: 6\n    STR_HEAVY_CANNON: 1\n    STR_PISTOL: 2\n    STR_PISTOL_CLIP: 8\n    STR_RIFLE: 2\n    STR_RIFLE_CLIP: 8\n    STR_ROCKET_LAUNCHER: 1\n    STR_SMALL_ROCKET: 4\n    STR_SMOKE_GRENADE: 5\n    STR_STINGRAY_LAUNCHER: 1\n    STR_STINGRAY_MISSILES: 25\n  scientists: 10\n  engineers: 10"
  },
  {
    "path": "bin/standard/xcom1/terrains.rul",
    "content": "terrains:\n  - name: CULTA\n    script: FARM\n    mapDataSets:\n      - BLANKS\n      - CULTIVAT\n      - BARN\n    mapBlocks:\n      - name: CULTA00\n        width: 10\n        length: 10\n        groups: 1\n      - name: CULTA01\n        width: 10\n        length: 10\n      - name: CULTA02\n        width: 10\n        length: 10\n      - name: CULTA03\n        width: 10\n        length: 10\n      - name: CULTA04\n        width: 10\n        length: 10\n      - name: CULTA05\n        width: 10\n        length: 10\n      - name: CULTA06\n        width: 10\n        length: 10\n      - name: CULTA07\n        width: 10\n        length: 10\n        groups: 1\n      - name: CULTA08\n        width: 10\n        length: 10\n      - name: CULTA09\n        width: 10\n        length: 10\n      - name: CULTA10\n        width: 10\n        length: 10\n      - name: CULTA11\n        width: 10\n        length: 10\n        groups: 1\n      - name: CULTA12\n        width: 10\n        length: 10\n      - name: CULTA13\n        width: 10\n        length: 10\n      - name: CULTA14\n        width: 10\n        length: 10\n      - name: CULTA15\n        width: 10\n        length: 10\n      - name: CULTA16\n        width: 10\n        length: 10\n      - name: CULTA17\n        width: 10\n        length: 10\n      - name: CULTA18\n        width: 10\n        length: 10\n  - name: DESERT\n    mapDataSets:\n      - BLANKS\n      - DESERT\n    script: DESERT\n    mapBlocks:\n      - name: DESERT00\n        width: 10\n        length: 10\n        groups: [0, 1]\n      - name: DESERT01\n        width: 10\n        length: 10\n        groups: [0, 1]\n      - name: DESERT02\n        width: 10\n        length: 10\n        groups: [0, 1]\n      - name: DESERT03\n        width: 10\n        length: 10\n      - name: DESERT04\n        width: 10\n        length: 10\n      - name: DESERT05\n        width: 10\n        length: 10\n      - name: DESERT06\n        width: 10\n        length: 10\n      - name: DESERT07\n        width: 10\n        length: 10\n      - name: DESERT08\n        width: 10\n        length: 10\n      - name: DESERT09\n        width: 20\n        length: 20\n      - name: DESERT10\n        width: 20\n        length: 20\n      - name: DESERT11\n        width: 20\n        length: 20\n  - name: FOREST\n    mapDataSets:\n      - BLANKS\n      - FOREST\n    mapBlocks:\n      - name: FOREST00\n        width: 10\n        length: 10\n        groups: 1\n      - name: FOREST01\n        width: 10\n        length: 10\n        groups: 1\n      - name: FOREST02\n        width: 10\n        length: 10\n      - name: FOREST03\n        width: 10\n        length: 10\n      - name: FOREST04\n        width: 10\n        length: 10\n      - name: FOREST05\n        width: 10\n        length: 10\n      - name: FOREST06\n        width: 10\n        length: 10\n      - name: FOREST07\n        width: 10\n        length: 10\n      - name: FOREST08\n        width: 10\n        length: 10\n      - name: FOREST09\n        width: 10\n        length: 10\n      - name: FOREST10\n        width: 20\n        length: 20\n      - name: FOREST11\n        width: 20\n        length: 20\n  - name: JUNGLE\n    mapDataSets:\n      - BLANKS\n      - JUNGLE\n    script: JUNGLE\n    mapBlocks:\n      - name: JUNGLE00\n        width: 10\n        length: 10\n        groups: 1\n      - name: JUNGLE01\n        width: 10\n        length: 10\n        groups: 1\n      - name: JUNGLE02\n        width: 10\n        length: 10\n        groups: 1\n      - name: JUNGLE03\n        width: 10\n        length: 10\n      - name: JUNGLE04\n        width: 10\n        length: 10\n      - name: JUNGLE05\n        width: 10\n        length: 10\n      - name: JUNGLE06\n        width: 10\n        length: 10\n      - name: JUNGLE07\n        width: 10\n        length: 10\n      - name: JUNGLE08\n        width: 10\n        length: 10\n      - name: JUNGLE09\n        width: 10\n        length: 10\n      - name: JUNGLE10\n        width: 10\n        length: 10\n      - name: JUNGLE11\n        width: 10\n        length: 10\n  - name: MARS\n    mapDataSets:\n      - BLANKS\n      - MARS\n      - U_WALL02\n    script: MARS\n    mapBlocks:\n      - name: MARS00\n        width: 10\n        length: 10\n        groups: [0, 1]\n      - name: MARS01\n        width: 10\n        length: 10\n      - name: MARS02\n        width: 10\n        length: 10\n      - name: MARS03\n        width: 10\n        length: 10\n      - name: MARS04\n        width: 10\n        length: 10\n      - name: MARS05\n        width: 10\n        length: 10\n      - name: MARS06\n        width: 10\n        length: 10\n      - name: MARS07\n        width: 10\n        length: 10\n      - name: MARS08\n        width: 10\n        length: 10\n      - name: MARS09\n        width: 10\n        length: 10\n      - name: MARS10\n        width: 10\n        length: 10\n        groups: 2\n  - name: MOUNT\n    mapDataSets:\n      - BLANKS\n      - MOUNT\n    mapBlocks:\n      - name: MOUNT00\n        width: 10\n        length: 10\n        groups: 1\n      - name: MOUNT01\n        width: 10\n        length: 10\n        groups: 1\n      - name: MOUNT02\n        width: 10\n        length: 10\n        groups: 1\n      - name: MOUNT03\n        width: 10\n        length: 10\n      - name: MOUNT04\n        width: 10\n        length: 10\n      - name: MOUNT05\n        width: 10\n        length: 10\n      - name: MOUNT06\n        width: 10\n        length: 10\n      - name: MOUNT07\n        width: 10\n        length: 10\n      - name: MOUNT08\n        width: 10\n        length: 10\n      - name: MOUNT09\n        width: 10\n        length: 10\n      - name: MOUNT10\n        width: 10\n        length: 10\n      - name: MOUNT11\n        width: 20\n        length: 20\n      - name: MOUNT12\n        width: 20\n        length: 20\n  - name: POLAR\n    mapDataSets:\n      - BLANKS\n      - POLAR\n    script: POLAR\n    mapBlocks:\n      - name: POLAR00\n        width: 10\n        length: 10\n        groups: [0, 1]\n      - name: POLAR01\n        width: 10\n        length: 10\n        groups: [0, 1]\n      - name: POLAR02\n        width: 10\n        length: 10\n        groups: [0, 1]\n      - name: POLAR03\n        width: 10\n        length: 10\n      - name: POLAR04\n        width: 10\n        length: 10\n      - name: POLAR05\n        width: 10\n        length: 10\n      - name: POLAR06\n        width: 10\n        length: 10\n      - name: POLAR07\n        width: 10\n        length: 10\n      - name: POLAR08\n        width: 10\n        length: 10\n      - name: POLAR09\n        width: 10\n        length: 10\n      - name: POLAR10\n        width: 10\n        length: 10\n      - name: POLAR11\n        width: 10\n        length: 10\n      - name: POLAR12\n        width: 20\n        length: 20\n      - name: POLAR13\n        width: 20\n        length: 20\n  - name: UBASE\n    mapDataSets:\n      - BLANKS\n      - U_BASE\n      - U_WALL02\n      - U_PODS\n      - BRAIN\n    mapBlocks:\n      - name: UBASE_00\n        width: 20\n        length: 20\n        groups: 3\n      - name: UBASE_01\n        width: 20\n        length: 20\n      - name: UBASE_02\n        width: 20\n        length: 20\n      - name: UBASE_03\n        width: 20\n        length: 20\n        items:\n          STR_ELERIUM_115:\n            - [2, 14, 1]\n      - name: UBASE_04\n        width: 10\n        length: 10\n        groups: 2\n        revealedFloors: 1\n      - name: UBASE_05\n        width: 10\n        length: 10\n      - name: UBASE_06\n        width: 10\n        length: 10\n      - name: UBASE_07\n        width: 10\n        length: 10\n        groups: 1\n      - name: UBASE_08\n        width: 10\n        length: 10\n      - name: UBASE_09\n        width: 10\n        length: 10\n      - name: UBASE_10\n        width: 10\n        length: 10\n      - name: UBASE_11\n        width: 10\n        length: 10\n#       UBASE_12 is impassable, 13 and 14 are apparently unused.\n#       in the interest of preserving an original experience,\n#       they have been disabled by being added to group 5, which is unused in the scripts.\n      - name: UBASE_12\n        width: 10\n        length: 10\n        groups: 5\n      - name: UBASE_13\n        width: 10\n        length: 10\n        groups: 5\n      - name: UBASE_14\n        width: 10\n        length: 10\n        groups: 5\n      - name: UBASE_15\n        width: 20\n        length: 20\n        groups: 4\n  - name: URBAN\n    mapDataSets:\n      - BLANKS\n      - ROADS\n      - URBITS\n      - URBAN\n      - FRNITURE\n    civilianTypes:\n      - MALE_CIVILIAN\n      - FEMALE_CIVILIAN\n    script: URBAN\n    mapBlocks:\n      - name: URBAN00\n        width: 10\n        length: 10\n        groups: 2\n      - name: URBAN01\n        width: 10\n        length: 10\n        groups: 3\n      - name: URBAN02\n        width: 10\n        length: 10\n        groups: 4\n      - name: URBAN03\n        width: 10\n        length: 10\n        groups: [0, 1]\n      - name: URBAN04\n        width: 10\n        length: 10\n        groups: [0, 1]\n      - name: URBAN05\n        width: 20\n        length: 20\n      - name: URBAN06\n        width: 20\n        length: 20\n      - name: URBAN07\n        width: 20\n        length: 20\n      - name: URBAN08\n        width: 20\n        length: 20\n      - name: URBAN09\n        width: 20\n        length: 20\n      - name: URBAN14\n        width: 10\n        length: 10\n      - name: URBAN15\n        width: 10\n        length: 10\n      - name: URBAN16\n        width: 10\n        length: 10\n      - name: URBAN17\n        width: 10\n        length: 10\n      - name: URBAN18\n        width: 10\n        length: 10\n  - name: XBASE\n    mapDataSets:\n      - BLANKS\n      - XBASE1\n      - XBASE2\n    script: XBASE\n    mapBlocks:\n      - name: XBASE_00\n        width: 10\n        length: 10\n      - name: XBASE_01\n        width: 10\n        length: 10\n      - name: XBASE_02\n        width: 10\n        length: 10\n      - name: XBASE_03\n        width: 10\n        length: 10\n      - name: XBASE_04\n        width: 10\n        length: 10\n      - name: XBASE_05\n        width: 10\n        length: 10\n      - name: XBASE_06\n        width: 10\n        length: 10\n      - name: XBASE_07\n        width: 10\n        length: 10\n      - name: XBASE_08\n        width: 10\n        length: 10\n      - name: XBASE_09\n        width: 10\n        length: 10\n      - name: XBASE_10\n        width: 10\n        length: 10\n      - name: XBASE_11\n        width: 10\n        length: 10\n      - name: XBASE_12\n        width: 10\n        length: 10\n      - name: XBASE_13\n        width: 10\n        length: 10\n      - name: XBASE_14\n        width: 10\n        length: 10\n      - name: XBASE_15\n        width: 10\n        length: 10\n      - name: XBASE_16\n        width: 10\n        length: 10\n      - name: XBASE_17\n        width: 10\n        length: 10\n      - name: XBASE_18\n        width: 10\n        length: 10\n      - name: XBASE_19\n        width: 10\n        length: 10\n      - name: XBASE_20\n        width: 10\n        length: 10"
  },
  {
    "path": "bin/standard/xcom1/ufoTrajectories.rul",
    "content": "ufoTrajectories:\n  - id: P0\n    groundTimer: 3000\n    waypoints:\n      - [5, 4, 100]\n      - [0, 3, 74]\n      - [0, 1, 28]\n      - [1, 1, 47]\n      - [5, 2, 100]\n  - id: P1\n    groundTimer: 4000\n    waypoints:\n      - [5, 4, 100]\n      - [0, 2, 76]\n      - [0, 2, 20]\n      - [1, 1, 44]\n      - [0, 0, 20]\n      - [0, 2, 32]\n      - [2, 1, 65]\n      - [5, 0, 100]\n  - id: P2\n    groundTimer: 5000\n    waypoints:\n      - [5, 4, 100]\n      - [0, 3, 57]\n      - [0, 2, 26]\n      - [1, 1, 50]\n      - [5, 0, 100]\n  - id: P3\n    groundTimer: 6000\n    waypoints:\n      - [5, 4, 100]\n      - [0, 3, 30]\n      - [0, 2, 25]\n      - [2, 1, 20]\n      - [5, 0, 100]\n  - id: P4\n    groundTimer: 7000\n    waypoints:\n      - [5, 4, 100]\n      - [0, 2, 67]\n      - [0, 2, 52]\n      - [2, 1, 40]\n      - [0, 0, 30]\n      - [0, 2, 20]\n      - [2, 1, 30]\n      - [5, 0, 100]\n  - id: P5\n    groundTimer: 4000\n    waypoints:\n      - [5, 4, 100]\n      - [0, 2, 50]\n      - [0, 2, 20]\n      - [4, 1, 15]\n      - [0, 0, 20]\n      - [0, 2, 29]\n      - [4, 1, 42]\n      - [5, 0, 90]\n  - id: P6\n    groundTimer: 5000\n    waypoints:\n      - [5, 4, 100]\n      - [0, 3, 50]\n      - [0, 2, 25]\n      - [4, 1, 16]\n      - [5, 0, 100]\n  - id: P7\n    groundTimer: 9000\n    waypoints:\n      - [5, 4, 100]\n      - [0, 3, 60]\n      - [0, 2, 30]\n      - [3, 1, 20]\n      - [5, 0, 100]\n  - id: P8\n    groundTimer: 6000\n    waypoints:\n      - [5, 4, 100]\n      - [1, 1, 60]\n      - [2, 1, 20]\n      - [3, 1, 30]\n      - [4, 1, 20]\n      - [0, 1, 42]\n      - [2, 1, 56]\n      - [5, 4, 100]\n  - id: P9\n    groundTimer: 2000\n    waypoints:\n      - [5, 4, 80]\n      - [5, 0, 100]\n  - id: __RETALIATION_ASSAULT_RUN\n    groundTimer: 1000\n    waypoints:\n      - [5, 4, 100] #This should always be 5, 4, 100\n      - [5, 0, 100] #only the 0 altitude matters"
  },
  {
    "path": "bin/standard/xcom1/ufopaedia.rul",
    "content": "ufopaedia:\n  - id: STR_SKYRANGER\n    type_id: 1\n    section: STR_XCOM_CRAFT_ARMAMENT\n    image_id: UP004.SPK\n    rect_stats:\n      x: 160\n      y: 5\n      width: 160\n      height: 60\n    rect_text:\n      x: 5\n      y: 40\n      width: 140\n      height: 100\n    text: STR_SKYRANGER_UFOPEDIA\n  - id: STR_LIGHTNING\n    type_id: 1\n    section: STR_XCOM_CRAFT_ARMAMENT\n    requires:\n      - STR_NEW_FIGHTER_TRANSPORTER\n    image_id: UP003.SPK\n    rect_stats:\n      x: 5\n      y: 132\n      width: 160\n      height: 60\n    rect_text:\n      x: 5\n      y: 40\n      width: 310\n      height: 60\n    text: STR_LIGHTNING_UFOPEDIA\n  - id: STR_AVENGER\n    type_id: 1\n    section: STR_XCOM_CRAFT_ARMAMENT\n    requires:\n      - STR_ULTIMATE_CRAFT\n    image_id: UP001.SPK\n    rect_stats:\n      x: 160\n      y: 5\n      width: 160\n      height: 60\n    rect_text:\n      x: 5\n      y: 40\n      width: 140\n      height: 100\n    text: STR_AVENGER_UFOPEDIA\n  - id: STR_INTERCEPTOR\n    type_id: 1\n    section: STR_XCOM_CRAFT_ARMAMENT\n    image_id: UP002.SPK\n    rect_stats:\n      x: 5\n      y: 110\n      width: 160\n      height: 60\n    rect_text:\n      x: 5\n      y: 40\n      width: 210\n      height: 60\n    text: STR_INTERCEPTOR_UFOPEDIA\n  - id: STR_FIRESTORM\n    type_id: 1\n    section: STR_XCOM_CRAFT_ARMAMENT\n    requires:\n      - STR_NEW_FIGHTER_CRAFT\n    image_id: UP005.SPK\n    rect_stats:\n      x: 160\n      y: 5\n      width: 160\n      height: 60\n    rect_text:\n      x: 5\n      y: 40\n      width: 140\n      height: 100\n    text: STR_FIRESTORM_UFOPEDIA\n  - id: STR_STINGRAY\n    type_id: 2\n    section: STR_XCOM_CRAFT_ARMAMENT\n    image_id: UP006.SPK\n    text: STR_STINGRAY_UFOPEDIA\n  - id: STR_AVALANCHE\n    type_id: 2\n    section: STR_XCOM_CRAFT_ARMAMENT\n    image_id: UP007.SPK\n    text: STR_AVALANCHE_UFOPEDIA\n  - id: STR_CANNON_UC\n    type_id: 2\n    section: STR_XCOM_CRAFT_ARMAMENT\n    image_id: UP008.SPK\n    text: STR_CANNON_UFOPEDIA\n  - id: STR_FUSION_BALL_UC\n    type_id: 2\n    section: STR_XCOM_CRAFT_ARMAMENT\n    requires:\n      - STR_FUSION_MISSILE\n    image_id: UP009.SPK\n    text: STR_FUSION_BALL_UFOPEDIA\n  - id: STR_LASER_CANNON_UC\n    type_id: 2\n    section: STR_XCOM_CRAFT_ARMAMENT\n    requires:\n      - STR_LASER_CANNON\n    image_id: UP010.SPK\n    text: STR_LASER_CANNON_UFOPEDIA\n  - id: STR_PLASMA_BEAM_UC\n    type_id: 2\n    section: STR_XCOM_CRAFT_ARMAMENT\n    requires:\n      - STR_PLASMA_CANNON\n    image_id: UP011.SPK\n    text: STR_PLASMA_BEAM_UFOPEDIA\n  - id: STR_TANK_CANNON\n    type_id: 3\n    section: STR_HEAVY_WEAPONS_PLATFORMS\n    text: STR_TANK_CANNON_UFOPEDIA\n    weapon: STR_CANNON\n  - id: STR_TANK_ROCKET_LAUNCHER\n    type_id: 3\n    section: STR_HEAVY_WEAPONS_PLATFORMS\n    text: STR_TANK_ROCKET_LAUNCHER_UFOPEDIA\n    weapon: STR_ROCKET_LAUNCHER\n  - id: STR_TANK_LASER_CANNON\n    type_id: 3\n    section: STR_HEAVY_WEAPONS_PLATFORMS\n    weapon: STR_LASER_CANNON\n    requires:\n      - STR_LASER_CANNON\n    text: STR_TANK_LASER_CANNON_UFOPEDIA\n  - id: STR_HOVERTANK_PLASMA\n    type_id: 3\n    section: STR_HEAVY_WEAPONS_PLATFORMS\n    weapon: STR_PLASMA_CANNON\n    requires:\n      - STR_PLASMA_CANNON\n      - STR_NEW_FIGHTER_CRAFT\n    text: STR_HOVERTANK_PLASMA_UFOPEDIA\n  - id: STR_HOVERTANK_LAUNCHER\n    type_id: 3\n    section: STR_HEAVY_WEAPONS_PLATFORMS\n    weapon: STR_FUSION_BALL_LAUNCHER\n    requires:\n      - STR_FUSION_MISSILE\n      - STR_NEW_FIGHTER_CRAFT\n    text: STR_HOVERTANK_LAUNCHER_UFOPEDIA\n  - id: STR_PERSONAL_ARMOR_UC\n    type_id: 5\n    section: STR_WEAPONS_AND_EQUIPMENT\n    requires:\n      - STR_PERSONAL_ARMOR\n    text: STR_PERSONAL_ARMOR_UFOPEDIA\n  - id: STR_POWER_SUIT_UC\n    type_id: 5\n    section: STR_WEAPONS_AND_EQUIPMENT\n    requires:\n      - STR_POWER_SUIT\n    text: STR_POWER_SUIT_UFOPEDIA\n  - id: STR_FLYING_SUIT_UC\n    type_id: 5\n    section: STR_WEAPONS_AND_EQUIPMENT\n    requires:\n      - STR_FLYING_SUIT\n    text: STR_FLYING_SUIT_UFOPEDIA\n  - id: STR_PISTOL\n    type_id: 4\n    section: STR_WEAPONS_AND_EQUIPMENT\n    text: STR_PISTOL_UFOPEDIA\n  - id: STR_PISTOL_CLIP\n    type_id: 4\n    section: STR_NOT_AVAILABLE\n  - id: STR_RIFLE\n    type_id: 4\n    section: STR_WEAPONS_AND_EQUIPMENT\n    text: STR_RIFLE_UFOPEDIA\n  - id: STR_RIFLE_CLIP\n    type_id: 4\n    section: STR_NOT_AVAILABLE\n  - id: STR_HEAVY_CANNON\n    type_id: 4\n    section: STR_WEAPONS_AND_EQUIPMENT\n    text: STR_HEAVY_CANNON_UFOPEDIA\n  - id: STR_HC_AP_AMMO\n    type_id: 4\n    section: STR_NOT_AVAILABLE\n  - id: STR_HC_HE_AMMO\n    type_id: 4\n    section: STR_NOT_AVAILABLE\n  - id: STR_HC_I_AMMO\n    type_id: 4\n    section: STR_NOT_AVAILABLE\n  - id: STR_AUTO_CANNON\n    type_id: 4\n    section: STR_WEAPONS_AND_EQUIPMENT\n    text: STR_AUTO_CANNON_UFOPEDIA\n  - id: STR_AC_AP_AMMO\n    type_id: 4\n    section: STR_NOT_AVAILABLE\n  - id: STR_AC_HE_AMMO\n    type_id: 4\n    section: STR_NOT_AVAILABLE\n  - id: STR_AC_I_AMMO\n    type_id: 4\n    section: STR_NOT_AVAILABLE\n  - id: STR_ROCKET_LAUNCHER\n    type_id: 4\n    section: STR_WEAPONS_AND_EQUIPMENT\n    text: STR_ROCKET_LAUNCHER_UFOPEDIA\n  - id: STR_SMALL_ROCKET\n    type_id: 4\n    section: STR_NOT_AVAILABLE\n  - id: STR_LARGE_ROCKET\n    type_id: 4\n    section: STR_NOT_AVAILABLE\n  - id: STR_INCENDIARY_ROCKET\n    type_id: 4\n    section: STR_NOT_AVAILABLE\n  - id: STR_LASER_PISTOL\n    type_id: 4\n    section: STR_WEAPONS_AND_EQUIPMENT\n    requires:\n      - STR_LASER_PISTOL\n    text: STR_LASER_PISTOL_UFOPEDIA\n  - id: STR_LASER_RIFLE\n    type_id: 4\n    section: STR_WEAPONS_AND_EQUIPMENT\n    requires:\n      - STR_LASER_RIFLE\n    text: STR_LASER_RIFLE_UFOPEDIA\n  - id: STR_HEAVY_LASER\n    type_id: 4\n    section: STR_WEAPONS_AND_EQUIPMENT\n    requires:\n      - STR_HEAVY_LASER\n    text: STR_HEAVY_LASER_UFOPEDIA\n  - id: STR_GRENADE\n    type_id: 4\n    section: STR_WEAPONS_AND_EQUIPMENT\n    text: STR_GRENADE_UFOPEDIA\n  - id: STR_SMOKE_GRENADE\n    type_id: 4\n    section: STR_WEAPONS_AND_EQUIPMENT\n    text: STR_SMOKE_GRENADE_UFOPEDIA\n  - id: STR_PROXIMITY_GRENADE\n    type_id: 4\n    section: STR_WEAPONS_AND_EQUIPMENT\n    text: STR_PROXIMITY_GRENADE_UFOPEDIA\n  - id: STR_HIGH_EXPLOSIVE\n    type_id: 4\n    section: STR_WEAPONS_AND_EQUIPMENT\n    text: STR_HIGH_EXPLOSIVE_UFOPEDIA\n  - id: STR_MOTION_SCANNER\n    type_id: 4\n    section: STR_WEAPONS_AND_EQUIPMENT\n    requires:\n      - STR_MOTION_SCANNER\n    text: STR_MOTION_SCANNER_UFOPEDIA\n  - id: STR_MEDI_KIT\n    type_id: 4\n    section: STR_WEAPONS_AND_EQUIPMENT\n    requires:\n      - STR_MEDI_KIT\n    text: STR_MEDI_KIT_UFOPEDIA\n  - id: STR_PSI_AMP\n    type_id: 4\n    section: STR_WEAPONS_AND_EQUIPMENT\n    requires:\n      - STR_PSI_AMP\n    text: STR_PSI_AMP_UFOPEDIA\n  - id: STR_STUN_ROD\n    type_id: 4\n    section: STR_WEAPONS_AND_EQUIPMENT\n    text: STR_STUN_ROD_UFOPEDIA\n  - id: STR_ELECTRO_FLARE\n    type_id: 4\n    section: STR_WEAPONS_AND_EQUIPMENT\n    text: STR_ELECTRO_FLARE_UFOPEDIA\n  - id: STR_HEAVY_PLASMA\n    type_id: 4\n    section: STR_ALIEN_ARTIFACTS\n    requires:\n      - STR_HEAVY_PLASMA\n    text: STR_HEAVY_PLASMA_UFOPEDIA\n  - id: STR_HEAVY_PLASMA_CLIP\n    type_id: 4\n    section: STR_ALIEN_ARTIFACTS\n    requires:\n      - STR_HEAVY_PLASMA_CLIP\n    text: STR_HEAVY_PLASMA_CLIP_UFOPEDIA\n  - id: STR_PLASMA_RIFLE\n    type_id: 4\n    section: STR_ALIEN_ARTIFACTS\n    requires:\n      - STR_PLASMA_RIFLE\n    text: STR_PLASMA_RIFLE_UFOPEDIA\n  - id: STR_PLASMA_RIFLE_CLIP\n    type_id: 4\n    section: STR_ALIEN_ARTIFACTS\n    requires:\n      - STR_PLASMA_RIFLE_CLIP\n    text: STR_PLASMA_RIFLE_CLIP_UFOPEDIA\n  - id: STR_PLASMA_PISTOL\n    type_id: 4\n    section: STR_ALIEN_ARTIFACTS\n    requires:\n      - STR_PLASMA_PISTOL\n    text: STR_PLASMA_PISTOL_UFOPEDIA\n  - id: STR_PLASMA_PISTOL_CLIP\n    type_id: 4\n    section: STR_ALIEN_ARTIFACTS\n    requires:\n      - STR_PLASMA_PISTOL_CLIP\n    text: STR_PLASMA_PISTOL_CLIP_UFOPEDIA\n  - id: STR_BLASTER_LAUNCHER\n    type_id: 4\n    section: STR_ALIEN_ARTIFACTS\n    requires:\n      - STR_BLASTER_LAUNCHER\n    text: STR_BLASTER_LAUNCHER_UFOPEDIA\n  - id: STR_BLASTER_BOMB\n    type_id: 4\n    section: STR_ALIEN_ARTIFACTS\n    requires:\n      - STR_BLASTER_BOMB\n    text: STR_BLASTER_BOMB_UFOPEDIA\n  - id: STR_SMALL_LAUNCHER\n    type_id: 4\n    section: STR_ALIEN_ARTIFACTS\n    requires:\n      - STR_SMALL_LAUNCHER\n    text: STR_SMALL_LAUNCHER_UFOPEDIA\n  - id: STR_STUN_BOMB\n    type_id: 4\n    section: STR_ALIEN_ARTIFACTS\n    requires:\n      - STR_STUN_BOMB\n    text: STR_STUN_BOMB_UFOPEDIA\n  - id: STR_ALIEN_GRENADE\n    type_id: 4\n    section: STR_ALIEN_ARTIFACTS\n    requires:\n      - STR_ALIEN_GRENADE\n    text: STR_ALIEN_GRENADE_UFOPEDIA\n  - id: STR_ELERIUM_115\n    type_id: 4\n    section: STR_ALIEN_ARTIFACTS\n    requires:\n      - STR_ELERIUM_115\n    text: STR_ELERIUM_115_UFOPEDIA\n  - id: STR_MIND_PROBE\n    type_id: 4\n    section: STR_ALIEN_ARTIFACTS\n    text: STR_MIND_PROBE_UFOPEDIA\n    requires:\n      - STR_MIND_PROBE\n  - id: STR_ACCESS_LIFT\n    type_id: 6\n    section: STR_BASE_FACILITIES\n    text: STR_ACCESS_LIFT_UFOPEDIA\n  - id: STR_LIVING_QUARTERS\n    type_id: 6\n    section: STR_BASE_FACILITIES\n    text: STR_LIVING_QUARTERS_UFOPEDIA\n  - id: STR_LABORATORY\n    type_id: 6\n    section: STR_BASE_FACILITIES\n    text: STR_LABORATORY_UFOPEDIA\n  - id: STR_WORKSHOP\n    type_id: 6\n    section: STR_BASE_FACILITIES\n    text: STR_WORKSHOP_UFOPEDIA\n  - id: STR_SMALL_RADAR_SYSTEM\n    type_id: 6\n    section: STR_BASE_FACILITIES\n    text: STR_SMALL_RADAR_SYSTEM_UFOPEDIA\n  - id: STR_LARGE_RADAR_SYSTEM\n    type_id: 6\n    section: STR_BASE_FACILITIES\n    text: STR_LARGE_RADAR_SYSTEM_UFOPEDIA\n  - id: STR_MISSILE_DEFENSES\n    type_id: 6\n    section: STR_BASE_FACILITIES\n    text: STR_MISSILE_DEFENSES_UFOPEDIA\n  - id: STR_GENERAL_STORES\n    type_id: 6\n    section: STR_BASE_FACILITIES\n    text: STR_GENERAL_STORES_UFOPEDIA\n  - id: STR_ALIEN_CONTAINMENT\n    type_id: 6\n    section: STR_BASE_FACILITIES\n    text: STR_ALIEN_CONTAINMENT_UFOPEDIA\n  - id: STR_LASER_DEFENSES\n    type_id: 6\n    section: STR_BASE_FACILITIES\n    requires:\n      - STR_LASER_DEFENSE\n    text: STR_LASER_DEFENSES_UFOPEDIA\n  - id: STR_PLASMA_DEFENSES\n    type_id: 6\n    section: STR_BASE_FACILITIES\n    requires:\n      - STR_PLASMA_DEFENSE\n    text: STR_PLASMA_DEFENSES_UFOPEDIA\n  - id: STR_FUSION_BALL_DEFENSES\n    type_id: 6\n    section: STR_BASE_FACILITIES\n    text: STR_FUSION_BALL_DEFENSES_UFOPEDIA\n    requires:\n      - STR_FUSION_DEFENSE\n  - id: STR_GRAV_SHIELD\n    type_id: 6\n    section: STR_BASE_FACILITIES\n    requires:\n      - STR_GRAV_SHIELD\n    text: STR_GRAV_SHIELD_UFOPEDIA\n  - id: STR_MIND_SHIELD\n    type_id: 6\n    section: STR_BASE_FACILITIES\n    requires:\n      - STR_MIND_SHIELD\n    text: STR_MIND_SHIELD_UFOPEDIA\n  - id: STR_PSIONIC_LABORATORY\n    type_id: 6\n    section: STR_BASE_FACILITIES\n    requires:\n      - STR_PSI_LAB\n    text: STR_PSIONIC_LABORATORY_UFOPEDIA\n  - id: STR_HYPER_WAVE_DECODER\n    type_id: 6\n    section: STR_BASE_FACILITIES\n    requires:\n      - STR_HYPER_WAVE_DECODER\n    text: STR_HYPER_WAVE_DECODER_UFOPEDIA\n  - id: STR_HANGAR\n    type_id: 6\n    section: STR_BASE_FACILITIES\n    text: STR_HANGAR_UFOPEDIA\n  - id: STR_SECTOID\n    type_id: 7\n    section: STR_ALIEN_LIFE_FORMS\n    requires:\n      - STR_SECTOID\n    image_id: UP024.SPK\n    text: STR_SECTOID_UFOPEDIA\n    text_width: 158\n  - id: STR_SECTOID_AUTOPSY\n    type_id: 7\n    section: STR_ALIEN_LIFE_FORMS\n    image_id: UP025.SPK\n    text: STR_SECTOID_AUTOPSY_UFOPEDIA\n    requires:\n      - STR_SECTOID_CORPSE\n    text_width: 158\n  - id: STR_SNAKEMAN\n    type_id: 7\n    section: STR_ALIEN_LIFE_FORMS\n    requires:\n      - STR_SNAKEMAN\n    image_id: UP030.SPK\n    text: STR_SNAKEMAN_UFOPEDIA\n    text_width: 158\n  - id: STR_SNAKEMAN_AUTOPSY\n    type_id: 7\n    section: STR_ALIEN_LIFE_FORMS\n    requires:\n      - STR_SNAKEMAN_CORPSE\n    image_id: UP031.SPK\n    text: STR_SNAKEMAN_AUTOPSY_UFOPEDIA\n    text_width: 158\n  - id: STR_ETHEREAL\n    type_id: 7\n    section: STR_ALIEN_LIFE_FORMS\n    requires:\n      - STR_ETHEREAL\n    image_id: UP016.SPK\n    text: STR_ETHEREAL_UFOPEDIA\n    text_width: 158\n  - id: STR_ETHEREAL_AUTOPSY\n    type_id: 7\n    section: STR_ALIEN_LIFE_FORMS\n    requires:\n      - STR_ETHEREAL_CORPSE\n    image_id: UP017.SPK\n    text: STR_ETHEREAL_AUTOPSY_UFOPEDIA\n    text_width: 158\n  - id: STR_MUTON\n    type_id: 7\n    section: STR_ALIEN_LIFE_FORMS\n    requires:\n      - STR_MUTON\n    image_id: UP020.SPK\n    text: STR_MUTON_UFOPEDIA\n    text_width: 158\n  - id: STR_MUTON_AUTOPSY\n    type_id: 7\n    section: STR_ALIEN_LIFE_FORMS\n    requires:\n      - STR_MUTON_CORPSE\n    image_id: UP021.SPK\n    text: STR_MUTON_AUTOPSY_UFOPEDIA\n    text_width: 158\n  - id: STR_FLOATER\n    type_id: 7\n    section: STR_ALIEN_LIFE_FORMS\n    requires:\n      - STR_FLOATER\n    image_id: UP018.SPK\n    text: STR_FLOATER_UFOPEDIA\n    text_width: 158\n  - id: STR_FLOATER_AUTOPSY\n    type_id: 7\n    section: STR_ALIEN_LIFE_FORMS\n    requires:\n      - STR_FLOATER_CORPSE\n    image_id: UP019.SPK\n    text: STR_FLOATER_AUTOPSY_UFOPEDIA\n    text_width: 158\n  - id: STR_CELATID\n    type_id: 7\n    section: STR_ALIEN_LIFE_FORMS\n    requires:\n      - STR_CELATID\n    image_id: UP012.SPK\n    text: STR_CELATID_UFOPEDIA\n    text_width: 158\n  - id: STR_CELATID_AUTOPSY\n    type_id: 7\n    section: STR_ALIEN_LIFE_FORMS\n    requires:\n      - STR_CELATID_CORPSE\n    image_id: UP013.SPK\n    text: STR_CELATID_AUTOPSY_UFOPEDIA\n    text_width: 158\n  - id: STR_SILACOID\n    type_id: 7\n    section: STR_ALIEN_LIFE_FORMS\n    requires:\n      - STR_SILACOID\n    image_id: UP028.SPK\n    text: STR_SILACOID_UFOPEDIA\n    text_width: 158\n  - id: STR_SILACOID_AUTOPSY\n    type_id: 7\n    section: STR_ALIEN_LIFE_FORMS\n    requires:\n      - STR_SILACOID_CORPSE\n    image_id: UP029.SPK\n    text: STR_SILACOID_AUTOPSY_UFOPEDIA\n    text_width: 158\n  - id: STR_CHRYSSALID\n    type_id: 7\n    section: STR_ALIEN_LIFE_FORMS\n    requires:\n      - STR_CHRYSSALID\n    image_id: UP014.SPK\n    text: STR_CHRYSSALID_UFOPEDIA\n    text_width: 158\n  - id: STR_CHRYSSALID_AUTOPSY\n    type_id: 7\n    section: STR_ALIEN_LIFE_FORMS\n    requires:\n      - STR_CHRYSSALID_CORPSE\n    image_id: UP015.SPK\n    text: STR_CHRYSSALID_AUTOPSY_UFOPEDIA\n    text_width: 158\n  - id: STR_REAPER\n    type_id: 7\n    section: STR_ALIEN_LIFE_FORMS\n    requires:\n      - STR_REAPER\n    image_id: UP022.SPK\n    text: STR_REAPER_UFOPEDIA\n    text_width: 158\n  - id: STR_REAPER_AUTOPSY\n    type_id: 7\n    section: STR_ALIEN_LIFE_FORMS\n    requires:\n      - STR_REAPER_CORPSE\n    image_id: UP023.SPK\n    text: STR_REAPER_AUTOPSY_UFOPEDIA\n    text_width: 158\n  - id: STR_SECTOPOD\n    type_id: 7\n    section: STR_ALIEN_LIFE_FORMS\n    requires:\n      - STR_SECTOPOD\n    image_id: UP026.SPK\n    text: STR_SECTOPOD_UFOPEDIA\n    text_width: 158\n  - id: STR_SECTOPOD_AUTOPSY\n    type_id: 7\n    section: STR_ALIEN_LIFE_FORMS\n    requires:\n      - STR_SECTOPOD_CORPSE\n    image_id: UP027.SPK\n    text: STR_SECTOPOD_AUTOPSY_UFOPEDIA\n    text_width: 158\n  - id: STR_CYBERDISC\n    type_id: 7\n    section: STR_ALIEN_LIFE_FORMS\n    requires:\n      - STR_CYBERDISC\n    image_id: UP041.SPK\n    text: STR_CYBERDISC_UFOPEDIA\n    text_width: 158\n  - id: STR_CYBERDISC_AUTOPSY\n    type_id: 7\n    section: STR_ALIEN_LIFE_FORMS\n    requires:\n      - STR_CYBERDISC_CORPSE\n    image_id: UP042.SPK\n    text: STR_CYBERDISC_AUTOPSY_UFOPEDIA\n    text_width: 158\n  - id: STR_ALIEN_ORIGINS\n    type_id: 8\n    section: STR_ALIEN_RESEARCH_UC\n    requires:\n      - STR_ALIEN_ORIGINS\n    text: STR_ALIEN_ORIGINS_UFOPEDIA\n  - id: STR_THE_MARTIAN_SOLUTION\n    type_id: 8\n    section: STR_ALIEN_RESEARCH_UC\n    requires:\n      - STR_THE_MARTIAN_SOLUTION\n    text: STR_THE_MARTIAN_SOLUTION_UFOPEDIA\n  - id: STR_CYDONIA_OR_BUST\n    type_id: 8\n    section: STR_ALIEN_RESEARCH_UC\n    requires:\n      - STR_CYDONIA_OR_BUST\n    text: STR_CYDONIA_OR_BUST_UFOPEDIA\n  - id: STR_ALIEN_RESEARCH\n    type_id: 8\n    section: STR_ALIEN_RESEARCH_UC\n    requires:\n      - STR_ALIEN_RESEARCH\n    text: STR_ALIEN_RESEARCH_UFOPEDIA\n  - id: STR_ALIEN_HARVEST\n    type_id: 8\n    section: STR_ALIEN_RESEARCH_UC\n    requires:\n      - STR_ALIEN_HARVEST\n    text: STR_ALIEN_HARVEST_UFOPEDIA\n  - id: STR_ALIEN_ABDUCTION\n    type_id: 8\n    section: STR_ALIEN_RESEARCH_UC\n    requires:\n      - STR_ALIEN_ABDUCTION\n    text: STR_ALIEN_ABDUCTION_UFOPEDIA\n  - id: STR_ALIEN_INFILTRATION\n    type_id: 8\n    section: STR_ALIEN_RESEARCH_UC\n    requires:\n      - STR_ALIEN_INFILTRATION\n    text: STR_ALIEN_INFILTRATION_UFOPEDIA\n  - id: STR_ALIEN_BASE\n    type_id: 8\n    section: STR_ALIEN_RESEARCH_UC\n    requires:\n      - STR_ALIEN_BASE\n    text: STR_ALIEN_BASE_UFOPEDIA\n  - id: STR_ALIEN_TERROR\n    type_id: 8\n    section: STR_ALIEN_RESEARCH_UC\n    requires:\n      - STR_ALIEN_TERROR\n    text: STR_ALIEN_TERROR_UFOPEDIA\n  - id: STR_ALIEN_RETALIATION\n    type_id: 8\n    section: STR_ALIEN_RESEARCH_UC\n    requires:\n      - STR_ALIEN_RETALIATION\n    text: STR_ALIEN_RETALIATION_UFOPEDIA\n  - id: STR_ALIEN_SUPPLY\n    type_id: 8\n    section: STR_ALIEN_RESEARCH_UC\n    requires:\n      - STR_ALIEN_SUPPLY\n    text: STR_ALIEN_SUPPLY_UFOPEDIA\n  - id: STR_UFO_POWER_SOURCE\n    type_id: 7\n    section: STR_UFO_COMPONENTS\n    requires:\n      - STR_UFO_POWER_SOURCE\n    image_id: UP032.SPK\n    text: STR_UFO_POWER_SOURCE_UFOPEDIA\n    text_width: 163\n  - id: STR_UFO_NAVIGATION\n    type_id: 7\n    section: STR_UFO_COMPONENTS\n    requires:\n      - STR_UFO_NAVIGATION\n    image_id: UP033.SPK\n    text: STR_UFO_NAVIGATION_UFOPEDIA\n    text_width: 147\n  - id: STR_UFO_CONSTRUCTION\n    type_id: 7\n    section: STR_UFO_COMPONENTS\n    requires:\n      - STR_UFO_CONSTRUCTION\n    image_id: UP034.SPK\n    text: STR_UFO_CONSTRUCTION_UFOPEDIA\n    text_width: 148\n  - id: STR_ALIEN_FOOD\n    type_id: 7\n    section: STR_UFO_COMPONENTS\n    requires:\n      - STR_ALIEN_FOOD\n    image_id: UP035.SPK\n    text: STR_ALIEN_FOOD_UFOPEDIA\n    text_width: 173\n  - id: STR_ALIEN_REPRODUCTION\n    type_id: 7\n    section: STR_UFO_COMPONENTS\n    requires:\n      - STR_ALIEN_REPRODUCTION\n    image_id: UP036.SPK\n    text: STR_ALIEN_REPRODUCTION_UFOPEDIA\n    text_width: 167\n  - id: STR_ALIEN_ENTERTAINMENT\n    type_id: 7\n    section: STR_UFO_COMPONENTS\n    requires:\n      - STR_ALIEN_ENTERTAINMENT\n    image_id: UP037.SPK\n    text: STR_ALIEN_ENTERTAINMENT_UFOPEDIA\n    text_width: 146\n  - id: STR_ALIEN_SURGERY\n    type_id: 7\n    section: STR_UFO_COMPONENTS\n    requires:\n      - STR_ALIEN_SURGERY\n    image_id: UP038.SPK\n    text: STR_ALIEN_SURGERY_UFOPEDIA\n    text_width: 108\n  - id: STR_EXAMINATION_ROOM\n    type_id: 7\n    section: STR_UFO_COMPONENTS\n    requires:\n      - STR_EXAMINATION_ROOM\n    image_id: UP039.SPK\n    text: STR_EXAMINATION_ROOM_UFOPEDIA\n    text_width: 150\n  - id: STR_ALIEN_ALLOYS\n    type_id: 7\n    section: STR_UFO_COMPONENTS\n    requires:\n      - STR_ALIEN_ALLOYS\n    image_id: UP040.SPK\n    text: STR_ALIEN_ALLOYS_UFOPEDIA\n    text_width: 145\n  - id: STR_SMALL_SCOUT\n    type_id: 9\n    section: STR_UFOS\n    requires:\n      - STR_SMALL_SCOUT\n    text: STR_SMALL_SCOUT_UFOPEDIA\n  - id: STR_MEDIUM_SCOUT\n    type_id: 9\n    section: STR_UFOS\n    requires:\n      - STR_MEDIUM_SCOUT\n    text: STR_MEDIUM_SCOUT_UFOPEDIA\n  - id: STR_LARGE_SCOUT\n    type_id: 9\n    section: STR_UFOS\n    requires:\n      - STR_LARGE_SCOUT\n    text: STR_LARGE_SCOUT_UFOPEDIA\n  - id: STR_HARVESTER\n    type_id: 9\n    section: STR_UFOS\n    requires:\n      - STR_HARVESTER\n    text: STR_HARVESTER_UFOPEDIA\n  - id: STR_ABDUCTOR\n    type_id: 9\n    section: STR_UFOS\n    requires:\n      - STR_ABDUCTOR\n    text: STR_ABDUCTOR_UFOPEDIA\n  - id: STR_TERROR_SHIP\n    type_id: 9\n    section: STR_UFOS\n    requires:\n      - STR_TERROR_SHIP\n    text: STR_TERROR_SHIP_UFOPEDIA\n  - id: STR_BATTLESHIP\n    type_id: 9\n    section: STR_UFOS\n    requires:\n      - STR_BATTLESHIP\n    text: STR_BATTLESHIP_UFOPEDIA\n  - id: STR_SUPPLY_SHIP\n    type_id: 9\n    section: STR_UFOS\n    requires:\n      - STR_SUPPLY_SHIP\n    text: STR_SUPPLY_SHIP_UFOPEDIA"
  },
  {
    "path": "bin/standard/xcom1/ufos.rul",
    "content": "ufos:\n  - type: STR_SMALL_SCOUT\n    size: STR_VERY_SMALL\n    sprite: 0\n    damageMax: 50\n    speedMax: 2200\n    power: 0\n    range: 0\n    score: 50\n    reload: 56\n    breakOffTime: 200\n    battlescapeTerrainData:\n      name: UFO1A\n      mapDataSets:\n        - BLANKS\n        - UFO1\n      mapBlocks:\n        - name: UFO1A\n          width: 10\n          length: 10\n  - type: STR_MEDIUM_SCOUT\n    size: STR_SMALL\n    sprite: 1\n    damageMax: 200\n    speedMax: 2400\n    power: 20\n    range: 15\n    score: 75\n    reload: 56\n    breakOffTime: 250\n    battlescapeTerrainData:\n      name: UFO_110\n      mapDataSets:\n        - BLANKS\n        - U_EXT02\n        - U_WALL02\n        - U_BITS\n      mapBlocks:\n        - name: UFO_110\n          width: 10\n          length: 10\n  - type: STR_LARGE_SCOUT\n    size: STR_SMALL\n    sprite: 2\n    damageMax: 250\n    speedMax: 2700\n    power: 20\n    range: 34\n    score: 125\n    reload: 48\n    breakOffTime: 300\n    battlescapeTerrainData:\n      name: UFO_120\n      mapDataSets:\n        - BLANKS\n        - U_EXT02\n        - U_WALL02\n        - U_BITS\n      mapBlocks:\n        - name: UFO_120\n          width: 20\n          length: 20\n  - type: STR_HARVESTER\n    size: STR_MEDIUM_UC\n    sprite: 3\n    damageMax: 500\n    speedMax: 4000\n    power: 40\n    range: 22\n    score: 250\n    reload: 48\n    breakOffTime: 500\n    battlescapeTerrainData:\n      name: UFO_130\n      mapDataSets:\n        - BLANKS\n        - U_EXT02\n        - U_WALL02\n        - U_DISEC2\n        - U_BITS\n      mapBlocks:\n        - name: UFO_130\n          width: 20\n          length: 20\n  - type: STR_ABDUCTOR\n    size: STR_MEDIUM_UC\n    sprite: 4\n    damageMax: 500\n    speedMax: 4300\n    power: 40\n    range: 20\n    score: 250\n    reload: 32\n    breakOffTime: 500\n    battlescapeTerrainData:\n      name: UFO_140\n      mapDataSets:\n        - BLANKS\n        - U_EXT02\n        - U_WALL02\n        - U_OPER2\n        - U_BITS\n      mapBlocks:\n        - name: UFO_140\n          width: 20\n          length: 20\n  - type: STR_TERROR_SHIP\n    size: STR_LARGE\n    sprite: 5\n    damageMax: 1200\n    speedMax: 4800\n    power: 120\n    range: 42\n    score: 500\n    reload: 24\n    breakOffTime: 2000\n    battlescapeTerrainData:\n      name: UFO_150\n      mapDataSets:\n        - BLANKS\n        - U_EXT02\n        - U_WALL02\n        - U_PODS\n        - U_BITS\n      mapBlocks:\n        - name: UFO_150\n          width: 30\n          length: 20\n  - type: STR_BATTLESHIP\n    size: STR_VERY_LARGE\n    sprite: 6\n    damageMax: 3000\n    speedMax: 5000\n    power: 140\n    range: 65\n    score: 700\n    reload: 24\n    breakOffTime: 4000\n    battlescapeTerrainData:\n      name: UFO_160\n      mapDataSets:\n        - BLANKS\n        - U_EXT02\n        - U_WALL02\n        - U_PODS\n        - U_BITS\n      mapBlocks:\n        - name: UFO_160\n          width: 30\n          length: 30\n  - type: STR_SUPPLY_SHIP\n    size: STR_LARGE\n    sprite: 7\n    damageMax: 2200\n    speedMax: 3200\n    power: 60\n    range: 36\n    score: 400\n    reload: 24\n    breakOffTime: 3000\n    battlescapeTerrainData:\n      name: UFO_170\n      mapDataSets:\n        - BLANKS\n        - U_EXT02\n        - U_WALL02\n        - U_DISEC2\n        - U_BITS\n      mapBlocks:\n        - name: UFO_170\n          width: 30\n          length: 20"
  },
  {
    "path": "bin/standard/xcom1/units.rul",
    "content": "units:\n  - type: STR_TANK_CANNON\n    race: STR_TANK_CANNON\n    stats:\n      tu: 70\n      stamina: 100\n      health: 90\n      bravery: 110\n      reactions: 20\n      firing: 60\n      throwing: 0\n      strength: 60\n      psiStrength: 100\n      psiSkill: 0\n      melee: 70\n    armor: TANK_ARMOR\n    standHeight: 16\n    kneelHeight: 16\n    value: 20\n    deathSound: 23\n    moveSound: 14\n    energyRecovery: 50\n  - type: STR_TANK_ROCKET_LAUNCHER\n    race: STR_TANK_ROCKET_LAUNCHER\n    stats:\n      tu: 70\n      stamina: 100\n      health: 90\n      bravery: 110\n      reactions: 20\n      firing: 60\n      throwing: 0\n      strength: 60\n      psiStrength: 100\n      psiSkill: 0\n      melee: 70\n    armor: TANK_ARMOR\n    standHeight: 16\n    kneelHeight: 16\n    value: 20\n    deathSound: 23\n    moveSound: 14\n    energyRecovery: 50\n  - type: STR_TANK_LASER_CANNON\n    race: STR_TANK_LASER_CANNON\n    stats:\n      tu: 70\n      stamina: 100\n      health: 90\n      bravery: 110\n      reactions: 20\n      firing: 60\n      throwing: 0\n      strength: 60\n      psiStrength: 100\n      psiSkill: 0\n      melee: 7\n    armor: TANK_ARMOR\n    standHeight: 16\n    kneelHeight: 16\n    value: 20\n    deathSound: 23\n    moveSound: 14\n    energyRecovery: 50\n  - type: STR_HOVERTANK_PLASMA\n    race: STR_HOVERTANK_PLASMA\n    stats:\n      tu: 100\n      stamina: 100\n      health: 90\n      bravery: 110\n      reactions: 30\n      firing: 60\n      throwing: 0\n      strength: 60\n      psiStrength: 100\n      psiSkill: 0\n      melee: 70\n    armor: HOVERTANK_ARMOR\n    standHeight: 12\n    kneelHeight: 12\n    floatHeight: 6\n    value: 20\n    deathSound: 23\n    moveSound: 40\n    energyRecovery: 50\n  - type: STR_HOVERTANK_LAUNCHER\n    race: STR_HOVERTANK_LAUNCHER\n    stats:\n      tu: 100\n      stamina: 100\n      health: 90\n      bravery: 110\n      reactions: 30\n      firing: 60\n      throwing: 0\n      strength: 60\n      psiStrength: 100\n      psiSkill: 0\n      melee: 60\n    armor: HOVERTANK_ARMOR\n    standHeight: 12\n    kneelHeight: 12\n    floatHeight: 6\n    value: 20\n    deathSound: 23\n    moveSound: 40\n    energyRecovery: 50\n  - type: MALE_CIVILIAN\n    race: STR_CIVILIAN\n    stats:\n      tu: 35\n      stamina: 65\n      health: 30\n      bravery: 80\n      reactions: 30\n      firing: 30\n      throwing: 50\n      strength: 20\n      psiStrength: 5\n      psiSkill: 0\n      melee: 50\n    armor: CIVM_ARMOR\n    standHeight: 21\n    kneelHeight: 14\n    value: 30\n    intelligence: 4\n    energyRecovery: 20\n    deathSound: [41, 42, 43]\n  - type: FEMALE_CIVILIAN\n    race: STR_CIVILIAN\n    stats:\n      tu: 35\n      stamina: 65\n      health: 30\n      bravery: 80\n      reactions: 30\n      firing: 30\n      throwing: 50\n      strength: 20\n      psiStrength: 5\n      psiSkill: 0\n      melee: 50\n    armor: CIVF_ARMOR\n    standHeight: 21\n    kneelHeight: 14\n    value: 30\n    intelligence: 4\n    energyRecovery: 20\n    deathSound: [44, 45, 46]\n  - type: STR_SECTOID_SOLDIER\n    race: STR_SECTOID\n    rank: STR_LIVE_SOLDIER\n    stats:\n      tu: 54\n      stamina: 90\n      health: 30\n      bravery: 80\n      reactions: 63\n      firing: 52\n      throwing: 58\n      strength: 30\n      psiStrength: 40\n      psiSkill: 0\n      melee: 76\n    armor: SECTOID_ARMOR0\n    standHeight: 16\n    kneelHeight: 12\n    value: 10\n    deathSound: 10\n    intelligence: 3\n    aggression: 2\n  - type: STR_SECTOID_ENGINEER\n    race: STR_SECTOID\n    rank: STR_LIVE_ENGINEER\n    stats:\n      tu: 54\n      stamina: 90\n      health: 30\n      bravery: 80\n      reactions: 63\n      firing: 52\n      throwing: 58\n      strength: 30\n      psiStrength: 40\n      psiSkill: 0\n      melee: 76\n    armor: SECTOID_ARMOR0\n    standHeight: 16\n    kneelHeight: 12\n    value: 16\n    deathSound: 10\n    intelligence: 6\n    aggression: 2\n  - type: STR_SECTOID_MEDIC\n    race: STR_SECTOID\n    rank: STR_LIVE_MEDIC\n    stats:\n      tu: 54\n      stamina: 90\n      health: 30\n      bravery: 80\n      reactions: 63\n      firing: 52\n      throwing: 58\n      strength: 30\n      psiStrength: 40\n      psiSkill: 0\n      melee: 76\n    armor: SECTOID_ARMOR0\n    standHeight: 16\n    kneelHeight: 12\n    value: 14\n    deathSound: 10\n    intelligence: 5\n    aggression: 1\n  - type: STR_SECTOID_NAVIGATOR\n    race: STR_SECTOID\n    rank: STR_LIVE_NAVIGATOR\n    stats:\n      tu: 54\n      stamina: 90\n      health: 30\n      bravery: 80\n      reactions: 63\n      firing: 52\n      throwing: 58\n      strength: 30\n      psiStrength: 40\n      psiSkill: 0\n      melee: 76\n    armor: SECTOID_ARMOR0\n    standHeight: 16\n    kneelHeight: 12\n    value: 12\n    deathSound: 10\n    intelligence: 4\n    aggression: 2\n  - type: STR_SECTOID_LEADER\n    race: STR_SECTOID\n    rank: STR_LIVE_LEADER\n    stats:\n      tu: 54\n      stamina: 90\n      health: 30\n      bravery: 80\n      reactions: 63\n      firing: 52\n      throwing: 58\n      strength: 30\n      psiStrength: 50\n      psiSkill: 50\n      melee: 76\n    armor: SECTOID_ARMOR0\n    standHeight: 16\n    kneelHeight: 12\n    value: 20\n    deathSound: 10\n    intelligence: 7\n    aggression: 1\n  - type: STR_SECTOID_COMMANDER\n    race: STR_SECTOID\n    rank: STR_LIVE_COMMANDER\n    stats:\n      tu: 54\n      stamina: 90\n      health: 30\n      bravery: 80\n      reactions: 63\n      firing: 52\n      throwing: 58\n      strength: 30\n      psiStrength: 50\n      psiSkill: 60\n      melee: 76\n    armor: SECTOID_ARMOR0\n    standHeight: 16\n    kneelHeight: 12\n    value: 25\n    deathSound: 10\n    intelligence: 8\n    aggression: 0\n  - type: STR_CYBERDISC_TERRORIST\n    race: STR_CYBERDISC\n    rank: STR_LIVE_TERRORIST\n    liveAlien: \"\"\n    stats:\n      tu: 62\n      stamina: 90\n      health: 120\n      bravery: 110\n      reactions: 64\n      firing: 60\n      throwing: 0\n      strength: 90\n      psiStrength: 100\n      psiSkill: 0\n      melee: 0\n    armor: CYBERDISC_ARMOR\n    standHeight: 15\n    kneelHeight: 15\n    floatHeight: 2\n    value: 20\n    deathSound: 23\n    moveSound: 40\n    intelligence: 5\n    aggression: 1\n    energyRecovery: 50\n    specab: 1\n    livingWeapon: true\n    capturable: false\n  - type: STR_FLOATER_SOLDIER\n    race: STR_FLOATER\n    rank: STR_LIVE_SOLDIER\n    stats:\n      tu: 50\n      stamina: 90\n      health: 35\n      bravery: 80\n      reactions: 50\n      firing: 50\n      throwing: 58\n      strength: 40\n      psiStrength: 35\n      psiSkill: 0\n      melee: 70\n    armor: FLOATER_ARMOR0\n    standHeight: 21\n    kneelHeight: 16\n    floatHeight: 2\n    value: 12\n    deathSound: 10\n    moveSound: 15\n    intelligence: 4\n    aggression: 2\n  - type: STR_FLOATER_ENGINEER\n    race: STR_FLOATER\n    rank: STR_LIVE_ENGINEER\n    stats:\n      tu: 50\n      stamina: 90\n      health: 35\n      bravery: 80\n      reactions: 50\n      firing: 50\n      throwing: 58\n      strength: 40\n      psiStrength: 35\n      psiSkill: 0\n      melee: 70\n    armor: FLOATER_ARMOR0\n    standHeight: 21\n    kneelHeight: 16\n    floatHeight: 2\n    value: 18\n    deathSound: 10\n    moveSound: 15\n    intelligence: 7\n    aggression: 2\n  - type: STR_FLOATER_NAVIGATOR\n    race: STR_FLOATER\n    rank: STR_LIVE_NAVIGATOR\n    stats:\n      tu: 50\n      stamina: 90\n      health: 35\n      bravery: 80\n      reactions: 50\n      firing: 50\n      throwing: 58\n      strength: 40\n      psiStrength: 35\n      psiSkill: 0\n      melee: 70\n    armor: FLOATER_ARMOR0\n    standHeight: 21\n    kneelHeight: 16\n    floatHeight: 2\n    value: 14\n    deathSound: 10\n    moveSound: 15\n    intelligence: 5\n    aggression: 2\n  - type: STR_FLOATER_MEDIC\n    race: STR_FLOATER\n    rank: STR_LIVE_MEDIC\n    stats:\n      tu: 50\n      stamina: 90\n      health: 35\n      bravery: 80\n      reactions: 50\n      firing: 50\n      throwing: 58\n      strength: 40\n      psiStrength: 35\n      psiSkill: 0\n      melee: 70\n    armor: FLOATER_ARMOR0\n    standHeight: 21\n    kneelHeight: 16\n    floatHeight: 2\n    value: 16\n    deathSound: 10\n    moveSound: 15\n    intelligence: 6\n    aggression: 1\n  - type: STR_FLOATER_LEADER\n    race: STR_FLOATER\n    rank: STR_LIVE_LEADER\n    stats:\n      tu: 55\n      stamina: 95\n      health: 40\n      bravery: 80\n      reactions: 60\n      firing: 60\n      throwing: 58\n      strength: 47\n      psiStrength: 40\n      psiSkill: 0\n      melee: 70\n    armor: FLOATER_ARMOR1\n    standHeight: 21\n    kneelHeight: 16\n    floatHeight: 2\n    value: 25\n    deathSound: 10\n    moveSound: 15\n    intelligence: 8\n    aggression: 0\n  - type: STR_FLOATER_COMMANDER\n    race: STR_FLOATER\n    rank: STR_LIVE_COMMANDER\n    stats:\n      tu: 60\n      stamina: 100\n      health: 45\n      bravery: 80\n      reactions: 66\n      firing: 63\n      throwing: 65\n      strength: 48\n      psiStrength: 45\n      psiSkill: 0\n      melee: 76\n    armor: FLOATER_ARMOR2\n    standHeight: 21\n    kneelHeight: 16\n    floatHeight: 2\n    value: 35\n    deathSound: 10\n    moveSound: 15\n    intelligence: 8\n    aggression: 0\n  - type: STR_REAPER_TERRORIST\n    race: STR_REAPER\n    rank: STR_LIVE_TERRORIST\n    stats:\n      tu: 62\n      stamina: 90\n      health: 148\n      bravery: 90\n      reactions: 64\n      firing: 0\n      throwing: 0\n      strength: 90\n      psiStrength: 35\n      psiSkill: 0\n      melee: 80\n    armor: REAPER_ARMOR\n    standHeight: 23\n    kneelHeight: 16\n    value: 25\n    deathSound: 10\n    intelligence: 2\n    aggression: 2\n    energyRecovery: 34\n    livingWeapon: true\n  - type: STR_SNAKEMAN_SOLDIER\n    race: STR_SNAKEMAN\n    rank: STR_LIVE_SOLDIER\n    stats:\n      tu: 40\n      stamina: 80\n      health: 45\n      bravery: 80\n      reactions: 45\n      firing: 58\n      throwing: 65\n      strength: 47\n      psiStrength: 40\n      psiSkill: 0\n      melee: 76\n    armor: SNAKEMAN_ARMOR0\n    standHeight: 18\n    kneelHeight: 18\n    value: 15\n    deathSound: 8\n    moveSound: 0\n    intelligence: 2\n    aggression: 2\n  - type: STR_SNAKEMAN_NAVIGATOR\n    race: STR_SNAKEMAN\n    rank: STR_LIVE_NAVIGATOR\n    stats:\n      tu: 40\n      stamina: 80\n      health: 45\n      bravery: 80\n      reactions: 45\n      firing: 58\n      throwing: 65\n      strength: 47\n      psiStrength: 40\n      psiSkill: 0\n      melee: 76\n    armor: SNAKEMAN_ARMOR0\n    standHeight: 18\n    kneelHeight: 18\n    value: 17\n    deathSound: 8\n    moveSound: 0\n    intelligence: 3\n    aggression: 2\n  - type: STR_SNAKEMAN_ENGINEER\n    race: STR_SNAKEMAN\n    rank: STR_LIVE_ENGINEER\n    stats:\n      tu: 40\n      stamina: 80\n      health: 45\n      bravery: 80\n      reactions: 45\n      firing: 58\n      throwing: 65\n      strength: 47\n      psiStrength: 40\n      psiSkill: 0\n      melee: 76\n    armor: SNAKEMAN_ARMOR0\n    standHeight: 18\n    kneelHeight: 18\n    value: 20\n    deathSound: 8\n    moveSound: 0\n    intelligence: 4\n    aggression: 2\n  - type: STR_SNAKEMAN_LEADER\n    race: STR_SNAKEMAN\n    rank: STR_LIVE_LEADER\n    stats:\n      tu: 40\n      stamina: 80\n      health: 45\n      bravery: 80\n      reactions: 55\n      firing: 65\n      throwing: 65\n      strength: 47\n      psiStrength: 45\n      psiSkill: 0\n      melee: 76\n    armor: SNAKEMAN_ARMOR1\n    standHeight: 18\n    kneelHeight: 18\n    value: 28\n    deathSound: 8\n    moveSound: 0\n    intelligence: 5\n    aggression: 2\n  - type: STR_SNAKEMAN_COMMANDER\n    race: STR_SNAKEMAN\n    rank: STR_LIVE_COMMANDER\n    stats:\n      tu: 45\n      stamina: 84\n      health: 55\n      bravery: 80\n      reactions: 65\n      firing: 58\n      throwing: 65\n      strength: 47\n      psiStrength: 50\n      psiSkill: 0\n      melee: 76\n    armor: SNAKEMAN_ARMOR2\n    standHeight: 18\n    kneelHeight: 18\n    value: 36\n    deathSound: 8\n    moveSound: 0\n    intelligence: 6\n    aggression: 2\n    energyRecovery: 40\n  - type: STR_CHRYSSALID_TERRORIST\n    race: STR_CHRYSSALID\n    rank: STR_LIVE_TERRORIST\n    stats:\n      tu: 110\n      stamina: 140\n      health: 96\n      bravery: 100\n      reactions: 70\n      firing: 0\n      throwing: 0\n      strength: 110\n      psiStrength: 50\n      psiSkill: 0\n      melee: 80\n    armor: CHRYSSALID_ARMOR\n    standHeight: 21\n    kneelHeight: 16\n    value: 25\n    deathSound: 9\n    intelligence: 4\n    aggression: 1\n    energyRecovery: 40\n    livingWeapon: true\n  - type: STR_MUTON_SOLDIER\n    race: STR_MUTON\n    rank: STR_LIVE_SOLDIER\n    stats:\n      tu: 56\n      stamina: 90\n      health: 125\n      bravery: 80\n      reactions: 60\n      firing: 54\n      throwing: 62\n      strength: 70\n      psiStrength: 25\n      psiSkill: 0\n      melee: 76\n    armor: MUTON_ARMOR0\n    standHeight: 21\n    kneelHeight: 16\n    value: 15\n    deathSound: 6\n    intelligence: 2\n    aggression: 2\n    energyRecovery: 40\n  - type: STR_MUTON_NAVIGATOR\n    race: STR_MUTON\n    rank: STR_LIVE_NAVIGATOR\n    stats:\n      tu: 56\n      stamina: 90\n      health: 125\n      bravery: 80\n      reactions: 60\n      firing: 54\n      throwing: 62\n      strength: 70\n      psiStrength: 25\n      psiSkill: 0\n      melee: 76\n    armor: MUTON_ARMOR1\n    standHeight: 21\n    kneelHeight: 16\n    value: 17\n    deathSound: 6\n    intelligence: 3\n    aggression: 2\n    energyRecovery: 40\n  - type: STR_MUTON_ENGINEER\n    race: STR_MUTON\n    rank: STR_LIVE_ENGINEER\n    stats:\n      tu: 56\n      stamina: 90\n      health: 125\n      bravery: 80\n      reactions: 60\n      firing: 54\n      throwing: 62\n      strength: 70\n      psiStrength: 25\n      psiSkill: 0\n      melee: 76\n    armor: MUTON_ARMOR2\n    standHeight: 21\n    kneelHeight: 16\n    value: 19\n    deathSound: 6\n    intelligence: 4\n    aggression: 2\n    energyRecovery: 40\n  - type: STR_SILACOID_TERRORIST\n    race: STR_SILACOID\n    rank: STR_LIVE_TERRORIST\n    stats:\n      tu: 40\n      stamina: 80\n      health: 114\n      bravery: 100\n      reactions: 40\n      firing: 0\n      throwing: 0\n      strength: 70\n      psiStrength: 80\n      psiSkill: 0\n      melee: 80\n    armor: SILACOID_ARMOR\n    standHeight: 10\n    kneelHeight: 10\n    value: 20\n    deathSound: 8\n    moveSound: 47\n    intelligence: 3\n    aggression: 2\n    energyRecovery: 40\n    specab: 2\n    livingWeapon: true\n  - type: STR_CELATID_TERRORIST\n    race: STR_CELATID\n    rank: STR_LIVE_TERRORIST\n    stats:\n      tu: 70\n      stamina: 90\n      health: 68\n      bravery: 90\n      reactions: 40\n      firing: 100\n      throwing: 0\n      strength: 70\n      psiStrength: 80\n      psiSkill: 0\n      melee: 80\n    armor: CELATID_ARMOR\n    standHeight: 12\n    kneelHeight: 12\n    floatHeight: 6\n    value: 20\n    deathSound: 7\n    moveSound: 16\n    intelligence: 3\n    aggression: 2\n    energyRecovery: 40\n    livingWeapon: true\n  - type: STR_ETHEREAL_SOLDIER\n    race: STR_ETHEREAL\n    rank: STR_LIVE_SOLDIER\n    stats:\n      tu: 68\n      stamina: 96\n      health: 55\n      bravery: 80\n      reactions: 75\n      firing: 74\n      throwing: 80\n      strength: 48\n      psiStrength: 50\n      psiSkill: 40\n      melee: 85\n    armor: ETHEREAL_ARMOR0\n    standHeight: 20\n    kneelHeight: 15\n    value: 20\n    deathSound: 9\n    intelligence: 6\n    aggression: 1\n    energyRecovery: 40\n  - type: STR_ETHEREAL_LEADER\n    race: STR_ETHEREAL\n    rank: STR_LIVE_LEADER\n    stats:\n      tu: 68\n      stamina: 96\n      health: 55\n      bravery: 80\n      reactions: 75\n      firing: 74\n      throwing: 80\n      strength: 48\n      psiStrength: 60\n      psiSkill: 45\n      melee: 85\n    armor: ETHEREAL_ARMOR1\n    standHeight: 20\n    kneelHeight: 15\n    value: 30\n    deathSound: 9\n    intelligence: 7\n    aggression: 1\n    energyRecovery: 40\n  - type: STR_ETHEREAL_COMMANDER\n    race: STR_ETHEREAL\n    rank: STR_LIVE_COMMANDER\n    stats:\n      tu: 68\n      stamina: 96\n      health: 55\n      bravery: 80\n      reactions: 75\n      firing: 74\n      throwing: 80\n      strength: 48\n      psiStrength: 65\n      psiSkill: 50\n      melee: 85\n    armor: ETHEREAL_ARMOR2\n    standHeight: 20\n    kneelHeight: 15\n    value: 40\n    deathSound: 9\n    intelligence: 8\n    aggression: 1\n    energyRecovery: 40\n  - type: STR_SECTOPOD_TERRORIST\n    race: STR_SECTOPOD\n    rank: STR_LIVE_TERRORIST\n    liveAlien: \"\"\n    stats:\n      tu: 62\n      stamina: 90\n      health: 96\n      bravery: 110\n      reactions: 64\n      firing: 60\n      throwing: 0\n      strength: 90\n      psiStrength: 100\n      psiSkill: 0\n      melee: 80\n    armor: SECTOPOD_ARMOR\n    standHeight: 23\n    kneelHeight: 16\n    value: 30\n    deathSound: 23\n    intelligence: 4\n    aggression: 1\n    energyRecovery: 50\n    livingWeapon: true\n    capturable: false\n  - type: STR_ZOMBIE\n    race: STR_ZOMBIE\n    rank: STR_LIVE_TERRORIST\n    stats:\n      tu: 40\n      stamina: 110\n      health: 84\n      bravery: 110\n      reactions: 40\n      firing: 0\n      throwing: 0\n      strength: 84\n      psiStrength: 80\n      psiSkill: 0\n      melee: 80\n    armor: ZOMBIE_ARMOR\n    standHeight: 18\n    kneelHeight: 18\n    value: 18\n    intelligence: 3\n    aggression: 2\n    energyRecovery: 20\n    spawnUnit: STR_CHRYSSALID_TERRORIST\n    livingWeapon: true\n    # Zombies are silent on death, no deathSound\n"
  },
  {
    "path": "bin/standard/xcom1/vars.rul",
    "content": "# X-COM 1 (UFO: Enemy Unknown) ruleset\n# For documentation on these values, see http://ufopaedia.org/index.php?title=Rulesets_(OpenXcom)\nstartingTime:\n  second: 0\n  minute: 0\n  hour: 12\n  weekday: 6\n  day: 1\n  month: 1\n  year: 1999\ncostEngineer: 25000\ncostScientist: 30000\ntimePersonnel: 72\ninitialFunding: 6000\nalienFuel: [STR_ELERIUM_115, 50]\nfontName: Font.dat"
  },
  {
    "path": "bin/standard/xcom2/Language/OXCE/cs.yml",
    "content": "cs:\n  STR_AVATAR_NAME_1: \"#01 Dolph\"\n  STR_AVATAR_NAME_2: \"#02 Will\"\n  STR_AVATAR_NAME_3: \"#03 Silvestr\"\n  STR_AVATAR_NAME_4: \"#04 Dwayne\"\n  STR_AVATAR_NAME_5: \"#05 Linda\"\n  STR_AVATAR_NAME_6: \"#06 Uma\"\n  STR_AVATAR_NAME_7: \"#07 Halle\"\n  STR_AVATAR_NAME_8: \"#08 Angelína\"\n  STR_PSI_SHORT: \"M.K.>{ALT}{0}/{1}\"\n  STR_EVASIVE_MANEUVERS: \"ÚHYBNÉ MANÉVRY\"\n  STR_UFO_DESTROYED_BY_SPLASHDOWN: \"CIZÁCKÁ PONORKA ZNIČENA!\"\n  STR_UFO_SURVIVED_SPLASHDOWN: \"CIZÁCKÁ PONORKA POTOPENA!\"\n  STR_UFO_HAS_LANDED: \"USO přistálo na pozici{NEWLINE}{0}\"\n  GMGEO1: \"Hudba glóbusu č. 1\"\n  GMGEO2: \"Hudba glóbusu č. 2\"\n  GMGEO3: \"Hudba glóbusu č. 3\"\n  GMGEO4: \"Hudba glóbusu č. 4\"\n  GMGEO5: \"Hudba glóbusu č. 5\"\n  GMGEO6: \"Hudba glóbusu č. 6\"\n  GMTACDRY: \"Hudba bojiště (souš)\"\n  GMTACWET: \"Hudba bojiště (voda)\"\n  GMINTER0: \"Hudba honička #0\"\n  GMINTER1: \"Hudba honička #1\"\n  GMINTER2: \"Hudba honička #2\"\n  GMINTER3: \"Hudba honička #3\"\n  STR_SHOT_TYPE_AUTO: \"Auto (x{0})\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/OXCE/da.yml",
    "content": "da:\n  STR_AVATAR_NAME_1: \"#01 Dolph\"\n  STR_AVATAR_NAME_2: \"#02 Will\"\n  STR_AVATAR_NAME_3: \"#03 Sylvester\"\n  STR_AVATAR_NAME_4: \"#04 Dwayne\"\n  STR_AVATAR_NAME_5: \"#05 Linda\"\n  STR_AVATAR_NAME_6: \"#06 Uma\"\n  STR_AVATAR_NAME_7: \"#07 Halle\"\n  STR_EVASIVE_MANEUVERS: \"UNDVIGENDE MANØVRER\"\n  STR_SHOT_TYPE_AUTO: \"Auto (x{0})\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/OXCE/de.yml",
    "content": "de:\n  STR_FACILITY_IN_USE_STORAGE: \"AQUA-ZELLE IN GEBRAUCH!{SMALLLINE}Nicht genug Lagerraum.\"\n  STR_FACILITY_IN_USE_QUARTERS: \"AQUA-ZELLE IN GEBRAUCH!{SMALLLINE}Nicht genug Wohnquartiere.\"\n  STR_FACILITY_IN_USE_LABORATORIES: \"AQUA-ZELLE IN GEBRAUCH!{SMALLLINE}Nicht genug Labore.\"\n  STR_FACILITY_IN_USE_WORKSHOPS: \"AQUA-ZELLE IN GEBRAUCH!{SMALLLINE}Nicht genug Werkstätten.\"\n  STR_FACILITY_IN_USE_HANGARS: \"AQUA-ZELLE IN GEBRAUCH!{SMALLLINE}Nicht genug U-Boot-Boxen\"\n  STR_FACILITY_IN_USE_PSI_LABS: \"AQUA-ZELLE IN GEBRAUCH!{SMALLLINE}Nicht genug M.S. Labore.\"\n  STR_FACILITY_IN_USE_GYMS: \"AQUA-ZELLE IN GEBRAUCH!{SMALLLINE}Nicht genug Gyms.\"\n  STR_FACILITY_IN_USE_PRISONS: \"AQUA-ZELLE IN GEBRAUCH!{SMALLLINE}Nicht genug Außerirdischen-Klimazellen.\"\n  STR_NOT_ENOUGH_HWP_CAPACITY: \"NICHT GENÜGEND UWS-KAPAZITÄT VERFÜGBAR!{SMALLLINE}Verwenden Sie ein anderes Modul oder reduzieren Sie die Anzahl der zugewiesenen UWSs.\"\n  STR_AVATAR_NAME_1: \"#01 Männlich, Dolph\"\n  STR_AVATAR_NAME_2: \"#02 Männlich, Will\"\n  STR_AVATAR_NAME_3: \"#03 Männlich, Sylvester\"\n  STR_AVATAR_NAME_4: \"#04 Männlich, Dwayne\"\n  STR_AVATAR_NAME_5: \"#05 Weiblich, Linda\"\n  STR_AVATAR_NAME_6: \"#06 Weiblich, Uma\"\n  STR_AVATAR_NAME_7: \"#07 Weiblich, Halle\"\n  STR_AVATAR_NAME_8: \"#08 Weiblich, Angelina\"\n  STR_PSI_SHORT: \"M.C.>{ALT}{0}/{1}\"\n  STR_EVASIVE_MANEUVERS: \"AUSWEICHMANÖVER\"\n  STR_UFO_DESTROYED_BY_SPLASHDOWN: \"AUSSERIRDISCHES U-BOOT ZERSTÖRT!\"\n  STR_UFO_SURVIVED_SPLASHDOWN: \"AUSSERIRDISCHES U-BOOT VERSENKT!\"\n  STR_UFO_HAS_LANDED: \"USO auf Grund gegangen an{NEWLINE}{0}\"\n  GMGEO1: \"Weltkarte Track #1\"\n  GMGEO2: \"Weltkarte Track #2\"\n  GMGEO3: \"Weltkarte Track #3\"\n  GMGEO4: \"Weltkarte Track #4\"\n  GMGEO5: \"Weltkarte Track #5\"\n  GMGEO6: \"Weltkarte Track #6\"\n  GMTACDRY: \"Gefechtskarte Track (Land)\"\n  GMTACWET: \"Gefechtskarte Track (Wasser)\"\n  GMINTER0: \"Luftkampf Musiktitel #0\"\n  GMINTER1: \"Luftkampf Musiktitel #1\"\n  GMINTER2: \"Luftkampf Musiktitel #2\"\n  GMINTER3: \"Luftkampf Musiktitel #3\"\n  GLOBE_TEXTURE_0: \"Meeresboden/Korallenriff 1\"\n  GLOBE_TEXTURE_1: \"Forschungseinrichtung 1\"\n  GLOBE_TEXTURE_2: \"Flugzeugwrack\"\n  GLOBE_TEXTURE_3: \"Atlantis\"\n  GLOBE_TEXTURE_4: \"Maya Tempel 1\"\n  GLOBE_TEXTURE_5: \"Versunkene Galeone\"\n  GLOBE_TEXTURE_6: \"Versunkenes Linienschiff 1\"\n  GLOBE_TEXTURE_7: \"Vulkanisch 1\"\n  GLOBE_TEXTURE_8: \"Meeresboden/Korallenriff 2\"\n  GLOBE_TEXTURE_9: \"Vulkanisch 2\"\n  GLOBE_TEXTURE_10: \"Versunkenes Linienschiff 2\"\n  GLOBE_TEXTURE_11: \"Forschungseinrichtung 2\"\n  GLOBE_TEXTURE_12: \"Maya Tempel 2\"\n  STR_SHOT_TYPE_AUTO: \"Autoschuss (x{0})\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/OXCE/el.yml",
    "content": "el:\n  STR_FACILITY_IN_USE_STORAGE: \"ΥΔΡΟ-ΛΕΜΒΟΣ ΣΕ ΧΡΗΣΗ!{SMALLLINE}Δεν υπάρχει αρκετός αποθηκευτικός χώρος.\"\n  STR_FACILITY_IN_USE_QUARTERS: \"ΥΔΡΟ-ΛΕΜΒΟΣ ΣΕ ΧΡΗΣΗ!{SMALLLINE}Δεν υπάρχουν αρκετοί χώροι διαβίωσης.\"\n  STR_FACILITY_IN_USE_LABORATORIES: \"ΥΔΡΟ-ΛΕΜΒΟΣ ΣΕ ΧΡΗΣΗ!{SMALLLINE}Ανεπαρκής χώρος εργαστηρίου.\"\n  STR_FACILITY_IN_USE_WORKSHOPS: \"ΥΔΡΟ-ΛΕΜΒΟΣ ΣΕ ΧΡΗΣΗ!{SMALLLINE}Ανεπαρκής χώρος εργαταξίου.\"\n  STR_FACILITY_IN_USE_HANGARS: \"ΥΔΡΟ-ΛΕΜΒΟΣ ΣΕ ΧΡΗΣΗ!{SMALLLINE}Ανεπαρκείς υπόστεγα υποβρυχίου.\"\n  STR_FACILITY_IN_USE_PSI_LABS: \"ΥΔΡΟ-ΛΕΜΒΟΣ ΣΕ ΧΡΗΣΗ!{SMALLLINE}Ανεπαρκείς εργαστήρια Ε.Μ.\"\n  STR_FACILITY_IN_USE_GYMS: \"ΥΔΡΟ-ΛΕΜΒΟΣ ΣΕ ΧΡΗΣΗ!{SMALLLINE}Ανεπαρεκίς γυμναστήρια.\"\n  STR_FACILITY_IN_USE_PRISONS: \"ΥΔΡΟ-ΛΕΜΒΟΣ ΣΕ ΧΡΗΣΗ!{SMALLLINE}Ανεπαρκείς χώροι περιορισμού εξωγήινων.\"\n  STR_NOT_ENOUGH_HWP_CAPACITY: \"ΔΕΝ ΥΠΑΡΧΕΙ ΑΡΚΕΤΗ ΧΩΡΗΤΙΚΟΤΗΤΑ ΥΟΣ!{SMALLLINE}Χρησιμοποιήστε διαφορετική μονάδα ή μειώστε τον αριθμό των εκχωρημένων ΥΟΣ.\"\n  STR_AVATAR_NAME_1: \"#1 Ντολφ\"\n  STR_AVATAR_NAME_2: \"#2 Γουίλ\"\n  STR_AVATAR_NAME_3: \"#03 Συλβέστερ\"\n  STR_AVATAR_NAME_4: \"#04 Ντουέιν\"\n  STR_AVATAR_NAME_5: \"#05 Λίντα\"\n  STR_AVATAR_NAME_6: \"#06 Ούμα\"\n  STR_AVATAR_NAME_7: \"#07 Χάλλε\"\n  STR_AVATAR_NAME_8: \"#08 Αγγελίνα\"\n  STR_PSI_SHORT: \"E.M.>{ALT}{0}/{1}\"\n  STR_EVASIVE_MANEUVERS: \"ΕΛΙΓΜΟΙ ΑΠΟΦΥΓΗΣ\"\n  STR_UFO_DESTROYED_BY_SPLASHDOWN: \"ΕΞΩΓΗΙΝΟ ΥΠΟΒΡΥΧΙΟ ΚΑΤΑΣΤΡΑΦΗΚΕ!\"\n  STR_UFO_SURVIVED_SPLASHDOWN: \"ΚΑΤΑΡΡΙΦΘΈΝ ΕΞΩΓΗΙΝΟ ΥΠΟΒΡΥΧΙΟ!\"\n  STR_UFO_HAS_LANDED: \"Το ΑΤΥΑ έπεσε στο{NEWLINE}{0}\"\n  GMGEO1: \"Υδρόγειος Τροχιά #1\"\n  GMGEO2: \"Υδρόγειος Τροχιά #2\"\n  GMGEO3: \"Υδρόγειος Τροχιά #3\"\n  GMGEO4: \"Υδρόγειος Τροχιά #4\"\n  GMGEO5: \"Υδρόγειος Τροχιά #5\"\n  GMGEO6: \"Υδρόγειος Τροχιά #6\"\n  GMTACDRY: \"Τροχιά Πεδίου Μάχης (Έδαφος)\"\n  GMTACWET: \"Τροχιά Πεδίου Μάχης (Νερό)\"\n  GMINTER0: \"Τροχιά Αερομαχίας #0\"\n  GMINTER1: \"Τροχιά Αερομαχίας #1\"\n  GMINTER2: \"Τροχιά Αερομαχίας #2\"\n  GMINTER3: \"Τροχιά Αερομαχίας #3\"\n  GLOBE_TEXTURE_0: \"Βυθός/Κοράλλι 1\"\n  GLOBE_TEXTURE_1: \"Ερευνητική Εγκατάσταση 1\"\n  GLOBE_TEXTURE_2: \"Συντριβή αεροπλάνου\"\n  GLOBE_TEXTURE_3: \"Ατλαντίδα\"\n  GLOBE_TEXTURE_4: \"Ναός Μάγια 1\"\n  GLOBE_TEXTURE_5: \"Βυθισμένη Γκαλέρα\"\n  GLOBE_TEXTURE_6: \"Βυθισμένο Πλοίο Γραμμής 1\"\n  GLOBE_TEXTURE_7: \"Ηφαιστειακό 1\"\n  GLOBE_TEXTURE_8: \"Βυθός/Κοράλλι 2\"\n  GLOBE_TEXTURE_9: \"Ηφαιστειακό 2\"\n  GLOBE_TEXTURE_10: \"Βυθισμένο Πλοίο Γραμμής 2\"\n  GLOBE_TEXTURE_11: \"Ερευνητική Εγκατάσταση 2\"\n  GLOBE_TEXTURE_12: \"Ναός Μάγια 2\"\n  STR_LANDED: \"Προσγειώθηκε\"\n  STR_SHOT_TYPE_AUTO: \"Αύτο (x{0})\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/OXCE/en-GB.yml",
    "content": "en-GB:\n#=================== Basescape ===================\n#BasescapeState.cpp\n  STR_FACILITY_IN_USE_STORAGE: \"AQUA-POD IN USE!{SMALLLINE}Not enough storage space.\"\n  STR_FACILITY_IN_USE_QUARTERS: \"AQUA-POD IN USE!{SMALLLINE}Not enough living quarters.\"\n  STR_FACILITY_IN_USE_LABORATORIES: \"AQUA-POD IN USE!{SMALLLINE}Not enough lab space.\"\n  STR_FACILITY_IN_USE_WORKSHOPS: \"AQUA-POD IN USE!{SMALLLINE}Not enough workshop space.\"\n  STR_FACILITY_IN_USE_HANGARS: \"AQUA-POD IN USE!{SMALLLINE}Not enough sub pens.\"\n  STR_FACILITY_IN_USE_PSI_LABS: \"AQUA-POD IN USE!{SMALLLINE}Not enough M.C. labs.\"\n  STR_FACILITY_IN_USE_GYMS: \"AQUA-POD IN USE!{SMALLLINE}Not enough gyms.\"\n  STR_FACILITY_IN_USE_PRISONS: \"AQUA-POD IN USE!{SMALLLINE}Not enough alien containment.\"\n#CraftWeaponsState.cpp\n  STR_NOT_ENOUGH_HWP_CAPACITY: \"NOT ENOUGH SWS CAPACITY AVAILABLE!{SMALLLINE}Use a different module or reduce the number of assigned SWSs.\"\n#SoldierAvatarState.cpp\n  STR_AVATAR_NAME_1: \"#01 Dolph\"\n  STR_AVATAR_NAME_2: \"#02 Will\"\n  STR_AVATAR_NAME_3: \"#03 Sylvester\"\n  STR_AVATAR_NAME_4: \"#04 Dwayne\"\n  STR_AVATAR_NAME_5: \"#05 Linda\"\n  STR_AVATAR_NAME_6: \"#06 Uma\"\n  STR_AVATAR_NAME_7: \"#07 Halle\"\n  STR_AVATAR_NAME_8: \"#08 Angelina\"\n#=================== Battlescape ===================\n#InventoryState.cpp\n  STR_PSI_SHORT: \"M.C.>{ALT}{0}/{1}\"\n#=================== Geoscape ===================\n#DogfightState.cpp\n  STR_EVASIVE_MANEUVERS: \"EVASIVE MANEUVERS\"\n  STR_UFO_DESTROYED_BY_SPLASHDOWN: \"ALIEN SUB DESTROYED!\"\n  STR_UFO_SURVIVED_SPLASHDOWN: \"ALIEN SUB DOWNED!\"\n#GeoscapeState.cpp\n  STR_UFO_HAS_LANDED: \"USO has touched down at{NEWLINE}{0}\"\n#SelectMusicTrackState.cpp\n  GMGEO1: \"Geoscape Track #1\"\n  GMGEO2: \"Geoscape Track #2\"\n  GMGEO3: \"Geoscape Track #3\"\n  GMGEO4: \"Geoscape Track #4\"\n  GMGEO5: \"Geoscape Track #5\"\n  GMGEO6: \"Geoscape Track #6\"\n  GMTACDRY: \"Battlescape Track (Land)\"\n  GMTACWET: \"Battlescape Track (Water)\"\n  GMINTER0: \"Dogfight Track #0\"\n  GMINTER1: \"Dogfight Track #1\"\n  GMINTER2: \"Dogfight Track #2\"\n  GMINTER3: \"Dogfight Track #3\"\n#=================== Menu ===================\n#NewBattleState.cpp\n  GLOBE_TEXTURE_0: \"Seabed/Coral 1\"\n  GLOBE_TEXTURE_1: \"Research Facility 1\"\n  GLOBE_TEXTURE_2: \"Crashed Plane\"\n  GLOBE_TEXTURE_3: \"Atlantis\"\n  GLOBE_TEXTURE_4: \"Mayan Temple 1\"\n  GLOBE_TEXTURE_5: \"Sunken Galleon\"\n  GLOBE_TEXTURE_6: \"Sunken Liner 1\"\n  GLOBE_TEXTURE_7: \"Volcanic 1\"\n  GLOBE_TEXTURE_8: \"Seabed/Coral 2\"\n  GLOBE_TEXTURE_9: \"Volcanic 2\"\n  GLOBE_TEXTURE_10: \"Sunken Liner 2\"\n  GLOBE_TEXTURE_11: \"Research Facility 2\"\n  GLOBE_TEXTURE_12: \"Mayan Temple 2\"\n  STR_LANDED: \"Touched Down\"\n#==================================================================================================================\n  STR_SHOT_TYPE_AUTO: \"Auto (x{0})\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/OXCE/en-US.yml",
    "content": "en-US:\n#=================== Basescape ===================\n#BasescapeState.cpp\n  STR_FACILITY_IN_USE_STORAGE: \"AQUA-POD IN USE!{SMALLLINE}Not enough storage space.\"\n  STR_FACILITY_IN_USE_QUARTERS: \"AQUA-POD IN USE!{SMALLLINE}Not enough living quarters.\"\n  STR_FACILITY_IN_USE_LABORATORIES: \"AQUA-POD IN USE!{SMALLLINE}Not enough lab space.\"\n  STR_FACILITY_IN_USE_WORKSHOPS: \"AQUA-POD IN USE!{SMALLLINE}Not enough workshop space.\"\n  STR_FACILITY_IN_USE_HANGARS: \"AQUA-POD IN USE!{SMALLLINE}Not enough sub pens.\"\n  STR_FACILITY_IN_USE_PSI_LABS: \"AQUA-POD IN USE!{SMALLLINE}Not enough M.C. labs.\"\n  STR_FACILITY_IN_USE_GYMS: \"AQUA-POD IN USE!{SMALLLINE}Not enough gyms.\"\n  STR_FACILITY_IN_USE_PRISONS: \"AQUA-POD IN USE!{SMALLLINE}Not enough alien containment.\"\n#CraftWeaponsState.cpp\n  STR_NOT_ENOUGH_HWP_CAPACITY: \"NOT ENOUGH SWS CAPACITY AVAILABLE!{SMALLLINE}Use a different module or reduce the number of assigned SWSs.\"\n#SoldierAvatarState.cpp\n  STR_AVATAR_NAME_1: \"#01 Dolph\"\n  STR_AVATAR_NAME_2: \"#02 Will\"\n  STR_AVATAR_NAME_3: \"#03 Sylvester\"\n  STR_AVATAR_NAME_4: \"#04 Dwayne\"\n  STR_AVATAR_NAME_5: \"#05 Linda\"\n  STR_AVATAR_NAME_6: \"#06 Uma\"\n  STR_AVATAR_NAME_7: \"#07 Halle\"\n  STR_AVATAR_NAME_8: \"#08 Angelina\"\n#=================== Battlescape ===================\n#InventoryState.cpp\n  STR_PSI_SHORT: \"M.C.>{ALT}{0}/{1}\"\n#=================== Geoscape ===================\n#DogfightState.cpp\n  STR_EVASIVE_MANEUVERS: \"EVASIVE MANEUVERS\"\n  STR_UFO_DESTROYED_BY_SPLASHDOWN: \"ALIEN SUB DESTROYED!\"\n  STR_UFO_SURVIVED_SPLASHDOWN: \"ALIEN SUB DOWNED!\"\n#GeoscapeState.cpp\n  STR_UFO_HAS_LANDED: \"USO has touched down at{NEWLINE}{0}\"\n#SelectMusicTrackState.cpp\n  GMGEO1: \"Geoscape Track #1\"\n  GMGEO2: \"Geoscape Track #2\"\n  GMGEO3: \"Geoscape Track #3\"\n  GMGEO4: \"Geoscape Track #4\"\n  GMGEO5: \"Geoscape Track #5\"\n  GMGEO6: \"Geoscape Track #6\"\n  GMTACDRY: \"Battlescape Track (Land)\"\n  GMTACWET: \"Battlescape Track (Water)\"\n  GMINTER0: \"Dogfight Track #0\"\n  GMINTER1: \"Dogfight Track #1\"\n  GMINTER2: \"Dogfight Track #2\"\n  GMINTER3: \"Dogfight Track #3\"\n#=================== Menu ===================\n#NewBattleState.cpp\n  GLOBE_TEXTURE_0: \"Seabed/Coral 1\"\n  GLOBE_TEXTURE_1: \"Research Facility 1\"\n  GLOBE_TEXTURE_2: \"Crashed Plane\"\n  GLOBE_TEXTURE_3: \"Atlantis\"\n  GLOBE_TEXTURE_4: \"Mayan Temple 1\"\n  GLOBE_TEXTURE_5: \"Sunken Galleon\"\n  GLOBE_TEXTURE_6: \"Sunken Liner 1\"\n  GLOBE_TEXTURE_7: \"Volcanic 1\"\n  GLOBE_TEXTURE_8: \"Seabed/Coral 2\"\n  GLOBE_TEXTURE_9: \"Volcanic 2\"\n  GLOBE_TEXTURE_10: \"Sunken Liner 2\"\n  GLOBE_TEXTURE_11: \"Research Facility 2\"\n  GLOBE_TEXTURE_12: \"Mayan Temple 2\"\n  STR_LANDED: \"Touched Down\"\n#==================================================================================================================\n  STR_SHOT_TYPE_AUTO: \"Auto (x{0})\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/OXCE/es-419.yml",
    "content": "es-419:\n  STR_AVATAR_NAME_1: \"#01 Dolph\"\n  STR_AVATAR_NAME_2: \"#02 Will\"\n  STR_AVATAR_NAME_3: \"#03 Sylvester\"\n  STR_AVATAR_NAME_4: \"#04 Dwayne\"\n  STR_AVATAR_NAME_5: \"#05 Linda\"\n  STR_AVATAR_NAME_6: \"#06 Uma\"\n  STR_AVATAR_NAME_7: \"#07 Halle\"\n  STR_AVATAR_NAME_8: \"#08 Angelina\"\n  STR_PSI_SHORT: \"M.C.>{ALT}{0}/{1}\"\n  STR_EVASIVE_MANEUVERS: \"MANIOBRAS EVASIVAS\"\n  STR_UFO_HAS_LANDED: \"OVNI aterrizó en{NEWLINE}{0}\"\n  GMGEO1: \"Pista Geoscape #1\"\n  GMGEO2: \"Pista Geoscape #2\"\n  GMGEO3: \"Pista Geoscape #3\"\n  GMGEO4: \"Pista Geoscape #4\"\n  GMGEO5: \"Pista Geoscape #5\"\n  GMGEO6: \"Pista Geoscape #6\"\n  GMTACDRY: \"Pista Battlescape (Tierra)\"\n  GMTACWET: \"Pista Battlescape (Agua)\"\n  STR_SHOT_TYPE_AUTO: \"Auto (x{0})\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/OXCE/es-ES.yml",
    "content": "es-ES:\n  STR_NOT_ENOUGH_HWP_CAPACITY: \"¡NO HAY SUFICIENTE CAPACIDAD DE SWS DISPONIBLE!{SMALLLINE}Utilice un módulo diferente o reduzca la cantidad de SWS asignados.\"\n  STR_EVASIVE_MANEUVERS: \"MANIOBRAS EVASIVAS\"\n  STR_UFO_DESTROYED_BY_SPLASHDOWN: \"¡SUBMARINO ALIENÍGENA DESTRUIDO!\"\n  STR_UFO_SURVIVED_SPLASHDOWN: \"¡SUBMARINO ALIENÍGENA DERRIBADO!\"\n  STR_UFO_HAS_LANDED: \"OSNI ha amerizado en{NEWLINE}{0}\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/OXCE/et.yml",
    "content": "et:\n  STR_AVATAR_NAME_1: \"#01 Dolph\"\n  STR_AVATAR_NAME_2: \"#02 Will\"\n  STR_AVATAR_NAME_3: \"#03 Sylvester\"\n  STR_AVATAR_NAME_4: \"#04 Dwayne\"\n  STR_AVATAR_NAME_5: \"#05 Linda\"\n  STR_AVATAR_NAME_6: \"#06 Uma\"\n  STR_AVATAR_NAME_7: \"#07 Halle\"\n  STR_AVATAR_NAME_8: \"#08 Angelina\"\n  STR_PSI_SHORT: \"M.C.>{ALT}{0}/{1}\"\n  STR_EVASIVE_MANEUVERS: \"VÄLTIV MANÖÖVER VAJALIK\"\n  STR_UFO_DESTROYED_BY_SPLASHDOWN: \"TULNUKATE ALLVEELAEV HÄVITATUD!\"\n  STR_UFO_SURVIVED_SPLASHDOWN: \"TULNUKATE ALLVEELAEV ALLA LASTUD!\"\n  STR_UFO_HAS_LANDED: \"USO on maandunud{NEWLINE}{0}\"\n  GMGEO1: \"Maakera lugu #1\"\n  GMGEO2: \"Maakera lugu #2\"\n  GMGEO3: \"Maakera lugu #3\"\n  GMGEO4: \"Maakera lugu #4\"\n  GMGEO5: \"Maakera lugu #5\"\n  GMGEO6: \"Maakera lugu #6\"\n  GMTACDRY: \"Lahingmaastiku lugu (maapeale)\"\n  GMTACWET: \"Lahingmaastiku lugu (veealune)\"\n  STR_SHOT_TYPE_AUTO: \"Auto (x{0})\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/OXCE/fi.yml",
    "content": "fi:\n  STR_AVATAR_NAME_1: \"#01 Dolph\"\n  STR_AVATAR_NAME_2: \"#02 Will\"\n  STR_AVATAR_NAME_3: \"#03 Sylvester\"\n  STR_AVATAR_NAME_4: \"#04 Dwayne\"\n  STR_AVATAR_NAME_5: \"#05 Linda\"\n  STR_AVATAR_NAME_6: \"#06 Uma\"\n  STR_AVATAR_NAME_7: \"#07 Halle\"\n  STR_AVATAR_NAME_8: \"#08 Angelina\"\n  STR_PSI_SHORT: \"MH>{ALT}{0}/{1}\"\n  STR_EVASIVE_MANEUVERS: \"VÄISTÖLIIKKEET\"\n  STR_UFO_DESTROYED_BY_SPLASHDOWN: \"MUUKALAISALUS TUHOUTUI!\"\n  STR_UFO_SURVIVED_SPLASHDOWN: \"MUUKALAISALUS AMMUTTU ALAS!\"\n  STR_UFO_HAS_LANDED: \"Muukalaisalus on laskeutunut sijainnissa{NEWLINE}{0}\"\n  GMGEO1: \"Geomaisemakappale #1\"\n  GMGEO2: \"Geomaisemakappale #2\"\n  GMGEO3: \"Geomaisemakappale #3\"\n  GMGEO4: \"Geomaisemakappale #4\"\n  GMGEO5: \"Geomaisemakappale #5\"\n  GMGEO6: \"Geomaisemakappale #6\"\n  GMTACDRY: \"Taistelukenttäkappale (maa)\"\n  GMTACWET: \"Taistelukenttäkappale (vesi)\"\n  GMINTER0: \"Ilmataisteluraita 0\"\n  GMINTER1: \"Ilmataisteluraita 1\"\n  GMINTER2: \"Ilmataisteluraita 2\"\n  GMINTER3: \"Ilmataisteluraita 3\"\n  STR_SHOT_TYPE_AUTO: \"Sarja ({0})\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/OXCE/fr.yml",
    "content": "fr:\n  STR_FACILITY_IN_USE_STORAGE: \"AQUA-POD EN UTILISATION !{SMALLLINE}Espace de stockage insuffisant.\"\n  STR_FACILITY_IN_USE_QUARTERS: \"AQUA-POD EN UTILISATION !{SMALLLINE}Espace de vie insuffisant.\"\n  STR_FACILITY_IN_USE_LABORATORIES: \"AQUA-POD EN UTILISATION !{SMALLLINE}Espace de laboratoire insuffisant.\"\n  STR_FACILITY_IN_USE_WORKSHOPS: \"AQUA-POD EN UTILISATION !{SMALLLINE}Espace d'atelier insuffisant.\"\n  STR_FACILITY_IN_USE_HANGARS: \"AQUA-POD EN UTILISATION !{SMALLLINE}Pas assez de hangars à sous-marins.\"\n  STR_FACILITY_IN_USE_PSI_LABS: \"AQUA-POD EN UTILISATION !{SMALLLINE}Pas assez de laboratoires de C.M.\"\n  STR_FACILITY_IN_USE_GYMS: \"AQUA-POD EN UTILISATION !{SMALLLINE}Pas assez de salles de sport.\"\n  STR_FACILITY_IN_USE_PRISONS: \"AQUA-POD EN UTILISATION !{SMALLLINE}Pas assez d'espace de confinement extraterrestre.\"\n  STR_NOT_ENOUGH_HWP_CAPACITY: \"CAPACITÉ SAS DISPONIBLE INSUFFISANTE !{SMALLLINE}Utilisez un autre module ou réduisez le nombre de SAS attribués.\"\n  STR_AVATAR_NAME_1: \"#01 Dolph\"\n  STR_AVATAR_NAME_2: \"#02 Will\"\n  STR_AVATAR_NAME_3: \"#03 Sylvester\"\n  STR_AVATAR_NAME_4: \"#04 Dwayne\"\n  STR_AVATAR_NAME_5: \"#05 Linda\"\n  STR_AVATAR_NAME_6: \"#06 Uma\"\n  STR_AVATAR_NAME_7: \"#07 Halle\"\n  STR_AVATAR_NAME_8: \"#08 Angelina\"\n  STR_PSI_SHORT: \"C.M.>{ALT}{0}/{1}\"\n  STR_EVASIVE_MANEUVERS: \"MANOEUVRES ÉVASIVES\"\n  STR_UFO_DESTROYED_BY_SPLASHDOWN: \"OSNI DÉTRUIT !\"\n  STR_UFO_SURVIVED_SPLASHDOWN: \"OSNI ABATTU !\"\n  STR_UFO_HAS_LANDED: \"L'OSNI a atterri à{NEWLINE}{0}\"\n  GMGEO1: \"Géoscape Piste #1\"\n  GMGEO2: \"Géoscape Piste #2\"\n  GMGEO3: \"Géoscape Piste #3\"\n  GMGEO4: \"Géoscape Piste #4\"\n  GMGEO5: \"Géoscape Piste #5\"\n  GMGEO6: \"Géoscape Piste #6\"\n  GMTACDRY: \"Piste de bataille (Terre)\"\n  GMTACWET: \"Piste de bataille (Mer)\"\n  GMINTER0: \"Piste de combat sous-marin #0\"\n  GMINTER1: \"Piste de combat sous-marin #1\"\n  GMINTER2: \"Piste de combat sous-marin #2\"\n  GMINTER3: \"Piste de combat sous-marin #3\"\n  GLOBE_TEXTURE_0: \"Fond marin / Corail 1\"\n  GLOBE_TEXTURE_1: \"Laboratoire de recherche 1\"\n  GLOBE_TEXTURE_2: \"Avion écrasé\"\n  GLOBE_TEXTURE_3: \"Atlantis\"\n  GLOBE_TEXTURE_4: \"Temple Maya 1\"\n  GLOBE_TEXTURE_5: \"Galion coulé\"\n  GLOBE_TEXTURE_6: \"Paquebot coulé 1\"\n  GLOBE_TEXTURE_7: \"Volcanique 1\"\n  GLOBE_TEXTURE_8: \"Fond marin / Corail 2\"\n  GLOBE_TEXTURE_9: \"Volcanique 2\"\n  GLOBE_TEXTURE_10: \"Paquebot coulé 2\"\n  GLOBE_TEXTURE_11: \"Laboratoire de recherche 2\"\n  GLOBE_TEXTURE_12: \"Temple Maya 2\"\n  STR_LANDED: \"Atterri\"\n  STR_SHOT_TYPE_AUTO: \"Auto (x{0})\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/OXCE/hu.yml",
    "content": "hu:\n  STR_AVATAR_NAME_1: \"#01 Dolph\"\n  STR_AVATAR_NAME_2: \"#02 Will\"\n  STR_AVATAR_NAME_3: \"#03 Szilveszter\"\n  STR_AVATAR_NAME_4: \"#04 Dwayne\"\n  STR_AVATAR_NAME_5: \"#05 Linda\"\n  STR_AVATAR_NAME_6: \"#06 Uma\"\n  STR_AVATAR_NAME_7: \"#07 Halle\"\n  STR_AVATAR_NAME_8: \"#08 Angelina\"\n  STR_PSI_SHORT: \"E.I.>{ALT}{0}/{1}\"\n  STR_EVASIVE_MANEUVERS: \"KITÉRŐ MANŐVEREK\"\n  STR_UFO_HAS_LANDED: \"Az USO itt szállt le:{NEWLINE}{0}\"\n  GMGEO1: \"Földgömb háttérzene #1\"\n  GMGEO2: \"Földgömb háttérzene #2\"\n  GMGEO3: \"Földgömb háttérzene #3\"\n  GMGEO4: \"Földgömb háttérzene #4\"\n  GMGEO5: \"Földgömb háttérzene #5\"\n  GMGEO6: \"Földgömb háttérzene #6\"\n  GMTACDRY: \"Harci háttérzene (Szárazon)\"\n  GMTACWET: \"Harci háttérzene (Vízben)\"\n  STR_SHOT_TYPE_AUTO: \"Auto (x{0})\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/OXCE/it.yml",
    "content": "it:\n  STR_FACILITY_IN_USE_STORAGE: \"STRUTTURA ACQUATICA IN USO!{SMALLLINE}Non ci sono abbastanza spazi di magazzino.\"\n  STR_FACILITY_IN_USE_QUARTERS: \"STRUTTURA ACQUATICA IN USO!{SMALLLINE}Non ci sono abbastanza alloggi.\"\n  STR_FACILITY_IN_USE_LABORATORIES: \"STRUTTURA ACQUATICA IN USO!{SMALLLINE}Non ci sono abbastanza laboratori.\"\n  STR_FACILITY_IN_USE_WORKSHOPS: \"STRUTTURA ACQUATICA IN USO!{SMALLLINE}Non ci sono abbastanza officine.\"\n  STR_FACILITY_IN_USE_HANGARS: \"STRUTTURA ACQUATICA IN USO!{SMALLLINE}Non ci sono abbastanza rimesse per sottomarini.\"\n  STR_FACILITY_IN_USE_PSI_LABS: \"STRUTTURA ACQUATICA IN USO!{SMALLLINE}Non ci sono abbastanza laboratori C.M.\"\n  STR_FACILITY_IN_USE_GYMS: \"STRUTTURA ACQUATICA IN USO!{SMALLLINE}Non ci sono abbastanza palestre.\"\n  STR_FACILITY_IN_USE_PRISONS: \"STRUTTURA ACQUATICA IN USO!{SMALLLINE}Non ci sono abbastanza contenimenti alieni.\"\n  STR_NOT_ENOUGH_HWP_CAPACITY: \"CAPACITÀ PER SWS INSUFFICIENTE!{SMALLLINE}Usa un modulo diverso o riduci il numero di SWS assegnati.\"\n  STR_AVATAR_NAME_1: \"#01 Dolph\"\n  STR_AVATAR_NAME_2: \"#02 Will\"\n  STR_AVATAR_NAME_3: \"#03 Sylvester\"\n  STR_AVATAR_NAME_4: \"#04 Dwayne\"\n  STR_AVATAR_NAME_5: \"#05 Linda\"\n  STR_AVATAR_NAME_6: \"#06 Uma\"\n  STR_AVATAR_NAME_7: \"#07 Halle\"\n  STR_AVATAR_NAME_8: \"#08 Angelina\"\n  STR_PSI_SHORT: \"C.M.>{ALT}{0}/{1}\"\n  STR_EVASIVE_MANEUVERS: \"MANOVRE EVASIVE\"\n  STR_UFO_DESTROYED_BY_SPLASHDOWN: \"SUB ALIENO DISTRUTTO!\"\n  STR_UFO_SURVIVED_SPLASHDOWN: \"SUB ALIENO AFFONDATO!\"\n  STR_UFO_HAS_LANDED: \"USO è atterrato a{NEWLINE}{0}\"\n  GMGEO1: \"Traccia Geoscape #1\"\n  GMGEO2: \"Traccia Geoscape #2\"\n  GMGEO3: \"Traccia Geoscape #3\"\n  GMGEO4: \"Traccia Geoscape #4\"\n  GMGEO5: \"Traccia Geoscape #5\"\n  GMGEO6: \"Traccia Geoscape #6\"\n  GMTACDRY: \"Traccia Battlescape (Terra)\"\n  GMTACWET: \"Traccia Battlescape (Acqua)\"\n  GMINTER0: \"Traccia Intercettazione #0\"\n  GMINTER1: \"Traccia Intercettazione #1\"\n  GMINTER2: \"Traccia Intercettazione #2\"\n  GMINTER3: \"Traccia Intercettazione #3\"\n  GLOBE_TEXTURE_0: \"Fondale/Corallo 1\"\n  GLOBE_TEXTURE_1: \"Struttura di Ricerca 1\"\n  GLOBE_TEXTURE_2: \"Aereo Schiantato\"\n  GLOBE_TEXTURE_3: \"Atlantide\"\n  GLOBE_TEXTURE_4: \"Tempio Maya 1\"\n  GLOBE_TEXTURE_5: \"Galeone Inabissato\"\n  GLOBE_TEXTURE_6: \"Transatlantico Inabissato 1\"\n  GLOBE_TEXTURE_7: \"Vulcanico 1\"\n  GLOBE_TEXTURE_8: \"Fondale/Corallo 2\"\n  GLOBE_TEXTURE_9: \"Vulcanico 2\"\n  GLOBE_TEXTURE_10: \"Transatlantico Inabissato 2\"\n  GLOBE_TEXTURE_11: \"Struttura di Ricerca 2\"\n  GLOBE_TEXTURE_12: \"Tempio Maya 2\"\n  STR_LANDED: \"Fermo\"\n  STR_SHOT_TYPE_AUTO: \"Auto (x{0})\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/OXCE/ja.yml",
    "content": "ja:\n  STR_FACILITY_IN_USE_STORAGE: \"アクアポッドは使用中！{SMALLLINE}倉庫のスペースが足りません\"\n  STR_FACILITY_IN_USE_QUARTERS: \"アクアポッドは使用中！{SMALLLINE}居住スペースが足りません\"\n  STR_FACILITY_IN_USE_LABORATORIES: \"アクアポッドは使用中！{SMALLLINE}研究スペースが足りません\"\n  STR_FACILITY_IN_USE_WORKSHOPS: \"アクアポッドは使用中！{SMALLLINE}ワークショップのスペースが足りません\"\n  STR_FACILITY_IN_USE_HANGARS: \"アクアポッドは使用中！{SMALLLINE}ドックスペースが足りません\"\n  STR_FACILITY_IN_USE_PSI_LABS: \"アクアポッドは使用中！{SMALLLINE}MC研究所が足りません\"\n  STR_FACILITY_IN_USE_GYMS: \"アクアポッドは使用中！{SMALLLINE}ジムが足りません\"\n  STR_FACILITY_IN_USE_PRISONS: \"アクアポッドは使用中！{SMALLLINE}エイリアン隔離スペースが足りません\"\n  STR_NOT_ENOUGH_HWP_CAPACITY: \"SWS格納スペースが足りません！{SMALLLINE}異なる船体を選ぶか数を減らしてください\"\n  STR_AVATAR_NAME_1: \"#01 ドルフ\"\n  STR_AVATAR_NAME_2: \"#02 ウィル\"\n  STR_AVATAR_NAME_3: \"#03 シルベスター\"\n  STR_AVATAR_NAME_4: \"#04 ドウェイン\"\n  STR_AVATAR_NAME_5: \"#05 リンダ\"\n  STR_AVATAR_NAME_6: \"#06 ユーマ\"\n  STR_AVATAR_NAME_7: \"#07 ハレィ\"\n  STR_AVATAR_NAME_8: \"#08 アンジェリーナ\"\n  STR_PSI_SHORT: \"M.C.>{ALT}{0}/{1}\"\n  STR_EVASIVE_MANEUVERS: \"回避行動\"\n  STR_UFO_DESTROYED_BY_SPLASHDOWN: \"USOは破壊された！\"\n  STR_UFO_SURVIVED_SPLASHDOWN: \"USOが轟沈！\"\n  STR_UFO_HAS_LANDED: \"USOが着艦>{NEWLINE}{0}\"\n  GMGEO1: \"ジオスケープの記録 #1\"\n  GMGEO2: \"ジオスケープの記録 #2\"\n  GMGEO3: \"ジオスケープの記録 #3\"\n  GMGEO4: \"ジオスケープの記録 #4\"\n  GMGEO5: \"ジオスケープの記録 #5\"\n  GMGEO6: \"ジオスケープの記録 #6\"\n  GMTACDRY: \"バトルスケープの記録 (地上)\"\n  GMTACWET: \"バトルスケープの記録 (水中)\"\n  GMINTER0: \"艦戦の軌跡 #0\"\n  GMINTER1: \"艦戦の軌跡 #1\"\n  GMINTER2: \"艦戦の軌跡 #2\"\n  GMINTER3: \"艦戦の軌跡 #3\"\n  GLOBE_TEXTURE_0: \"海底/珊瑚 1\"\n  GLOBE_TEXTURE_1: \"研究施設 1\"\n  GLOBE_TEXTURE_2: \"墜落現場\"\n  GLOBE_TEXTURE_3: \"アトランティス\"\n  GLOBE_TEXTURE_4: \"マヤ寺院 1\"\n  GLOBE_TEXTURE_5: \"沈没ガレオン船\"\n  GLOBE_TEXTURE_6: \"沈没ライナー船 1\"\n  GLOBE_TEXTURE_7: \"海底火山 1\"\n  GLOBE_TEXTURE_8: \"海底/珊瑚 2\"\n  GLOBE_TEXTURE_9: \"海底火山 2\"\n  GLOBE_TEXTURE_10: \"沈没ライナー船 2\"\n  GLOBE_TEXTURE_11: \"研究施設 2\"\n  GLOBE_TEXTURE_12: \"マヤ寺院 2\"\n  STR_LANDED: \"着床\"\n  STR_SHOT_TYPE_AUTO: \"自動 (x{0})\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/OXCE/ko.yml",
    "content": "ko:\n  STR_FACILITY_IN_USE_STORAGE: \"수상 모듈을 이용 중이다!{SMALLLINE}저장 공간이 충분하지 않다.\"\n  STR_FACILITY_IN_USE_QUARTERS: \"수상 모듈을 이용 중이다!{SMALLLINE}생활관 공간이 충분하지 않다.\"\n  STR_FACILITY_IN_USE_LABORATORIES: \"수상 모듈을 이용 중이다!{SMALLLINE}연구 공간이 충분하지 않다.\"\n  STR_FACILITY_IN_USE_WORKSHOPS: \"수상 모듈을 이용 중이다!{SMALLLINE}작업 공간이 충분하지 않다.\"\n  STR_FACILITY_IN_USE_HANGARS: \"수상 모듈을 이용 중이다!{SMALLLINE}비행잠수함 격납고가 충분하지 않다.\"\n  STR_FACILITY_IN_USE_PSI_LABS: \"수상 모듈을 이용 중이다!{SMALLLINE}M.C. 연구실 공간이 충분하지 않다.\"\n  STR_FACILITY_IN_USE_GYMS: \"수상 모듈을 이용 중이다!{SMALLLINE}체육관 공간이 충분하지 않다.\"\n  STR_FACILITY_IN_USE_PRISONS: \"수상 모듈을 이용 중이다!{SMALLLINE}외계인 격리실 공간이 충분하지 않다.\"\n  STR_NOT_ENOUGH_HWP_CAPACITY: \"쓸 수 있는 무장 잠수정 수용량이 충분하지 않다!{SMALLLINE}다른 비행잠수함을 이용하거나 할당된 무장 잠수정을 줄여라.\"\n  STR_AVATAR_NAME_1: \"#01 돌프 룬드그렌\"\n  STR_AVATAR_NAME_2: \"#02 윌 스미스\"\n  STR_AVATAR_NAME_3: \"#03 실베스터 스탤론\"\n  STR_AVATAR_NAME_4: \"#04 드웨인 힉스\"\n  STR_AVATAR_NAME_5: \"#05 린다 해밀턴\"\n  STR_AVATAR_NAME_6: \"#06 우마 서먼\"\n  STR_AVATAR_NAME_7: \"#07 할레 베리\"\n  STR_AVATAR_NAME_8: \"#08 안젤리나 졸리\"\n  STR_PSI_SHORT: \"M.C.>{ALT}{0}/{1}\"\n  STR_EVASIVE_MANEUVERS: \"회피 기동\"\n  STR_UFO_DESTROYED_BY_SPLASHDOWN: \"외계인 잠수함 파괴됨!\"\n  STR_UFO_SURVIVED_SPLASHDOWN: \"외계인 잠수함 가라앉음!\"\n  STR_UFO_HAS_LANDED: \"{0}{NEWLINE}에 USO가 착지했다\"\n  GMGEO1: \"지구화면 음악 #1\"\n  GMGEO2: \"지구화면 음악 #2\"\n  GMGEO3: \"지구화면 음악 #3\"\n  GMGEO4: \"지구화면 음악 #4\"\n  GMGEO5: \"지구화면 음악 #5\"\n  GMGEO6: \"지구화면 음악 #6\"\n  GMTACDRY: \"전투화면 음악 (지상)\"\n  GMTACWET: \"전투화면 음악 (수중)\"\n  GMINTER0: \"교전 음악 #0\"\n  GMINTER1: \"교전 음악 #1\"\n  GMINTER2: \"교전 음악 #2\"\n  GMINTER3: \"교전 음악 #3\"\n  GLOBE_TEXTURE_0: \"해저/산호 1\"\n  GLOBE_TEXTURE_1: \"연구시설 1\"\n  GLOBE_TEXTURE_2: \"추락한 비행기\"\n  GLOBE_TEXTURE_3: \"아틀란티스\"\n  GLOBE_TEXTURE_4: \"마야 사원 1\"\n  GLOBE_TEXTURE_5: \"가라앉은 갈레온선\"\n  GLOBE_TEXTURE_6: \"가라앉은 여객선 1\"\n  GLOBE_TEXTURE_7: \"화산 1\"\n  GLOBE_TEXTURE_8: \"해저/산호 2\"\n  GLOBE_TEXTURE_9: \"화산 2\"\n  GLOBE_TEXTURE_10: \"가라앉은 여객선 2\"\n  GLOBE_TEXTURE_11: \"연구시설 2\"\n  GLOBE_TEXTURE_12: \"마야 사원 2\"\n  STR_LANDED: \"착지\"\n  STR_SHOT_TYPE_AUTO: \"자동사격 (x{0})\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/OXCE/nl.yml",
    "content": "nl:\n  STR_AVATAR_NAME_1: \"#01 Dolph\"\n  STR_AVATAR_NAME_2: \"#02 Will\"\n  STR_AVATAR_NAME_3: \"#03 Sylvester\"\n  STR_AVATAR_NAME_4: \"#04 Dwayne\"\n  STR_AVATAR_NAME_5: \"#05 Linda\"\n  STR_AVATAR_NAME_6: \"#06 Uma\"\n  STR_AVATAR_NAME_7: \"#07 Halle\"\n  STR_AVATAR_NAME_8: \"#08 Angelina\"\n  STR_PSI_SHORT: \"M.C.>{ALT}{0}/{1}\"\n  STR_EVASIVE_MANEUVERS: \"ONTWIJKENDE MANEUVERS\"\n  STR_UFO_DESTROYED_BY_SPLASHDOWN: \"BUITENAARDSE DUIKBOOT VERNIETIGD!\"\n  STR_UFO_SURVIVED_SPLASHDOWN: \"BUITENAARDSE DUIKBOOT NEERGEHAALD!\"\n  STR_UFO_HAS_LANDED: \"USO is geland op{NEWLINE}{0}\"\n  GMGEO1: \"Geoscape Muziekstuk #1\"\n  GMGEO2: \"Geoscape Muziekstuk #2\"\n  GMGEO3: \"Geoscape Muziekstuk #3\"\n  GMGEO4: \"Geoscape Muziekstuk #4\"\n  GMGEO5: \"Geoscape Muziekstuk #5\"\n  GMGEO6: \"Geoscape Muziekstuk #6\"\n  GMTACDRY: \"Battlescape Muziekstuk (Land)\"\n  GMTACWET: \"Battlescape Muziekstuk (Water)\"\n  GMINTER0: \"Luchtgevecht Muziekstuk #0\"\n  GMINTER1: \"Luchtgevecht Muziekstuk #1\"\n  GMINTER2: \"Luchtgevecht Muziekstuk #2\"\n  GMINTER3: \"Luchtgevecht Muziekstuk #3\"\n  STR_SHOT_TYPE_AUTO: \"Auto (x{0})\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/OXCE/pl.yml",
    "content": "pl:\n  STR_FACILITY_IN_USE_STORAGE: \"KAPSUŁA W UŻYCIU!{SMALLLINE}Za mało miejsca w magazynach.\"\n  STR_FACILITY_IN_USE_QUARTERS: \"KAPSUŁA W UŻYCIU!{SMALLLINE}Za mało kwater mieszkalnych.\"\n  STR_FACILITY_IN_USE_LABORATORIES: \"KAPSUŁA W UŻYCIU!{SMALLLINE}Za mało stanowisk badawczych.\"\n  STR_FACILITY_IN_USE_WORKSHOPS: \"KAPSUŁA W UŻYCIU!{SMALLLINE}Za mało stanowisk produkcyjnych.\"\n  STR_FACILITY_IN_USE_HANGARS: \"KAPSUŁA W UŻYCIU!{SMALLLINE}Za mało doków.\"\n  STR_FACILITY_IN_USE_PSI_LABS: \"KAPSUŁA W UŻYCIU!{SMALLLINE}Za mało laboratoriów K.M.\"\n  STR_FACILITY_IN_USE_GYMS: \"KAPSUŁA W UŻYCIU!{SMALLLINE}Za mało stanowisk treningowych.\"\n  STR_FACILITY_IN_USE_PRISONS: \"KAPSUŁA W UŻYCIU!{SMALLLINE}Za mało cel.\"\n  STR_NOT_ENOUGH_HWP_CAPACITY: \"ZA MAŁO MIEJSC DLA PSB!{SMALLLINE}Użyj innego modułu lub zmniejsz liczbę przydzielonych PSB.\"\n  STR_AVATAR_NAME_1: \"#01 Dolph\"\n  STR_AVATAR_NAME_2: \"#02 Will\"\n  STR_AVATAR_NAME_3: \"#03 Sylvester\"\n  STR_AVATAR_NAME_4: \"#04 Dwayne\"\n  STR_AVATAR_NAME_5: \"#05 Linda\"\n  STR_AVATAR_NAME_6: \"#06 Uma\"\n  STR_AVATAR_NAME_7: \"#07 Halle\"\n  STR_AVATAR_NAME_8: \"#08 Angelina\"\n  STR_PSI_SHORT: \"K.M.>{ALT}{0}/{1}\"\n  STR_EVASIVE_MANEUVERS: \"MANEWRY UNIKOWE\"\n  STR_UFO_DESTROYED_BY_SPLASHDOWN: \"OBCA ŁÓDŹ ZNISZCZONA!\"\n  STR_UFO_SURVIVED_SPLASHDOWN: \"OBCA ŁÓDŹ ZESTRZELONA!\"\n  STR_UFO_HAS_LANDED: \"UFO wylądowało w{NEWLINE}{0}\"\n  GMGEO1: \"Ekran globu: motyw #1\"\n  GMGEO2: \"Ekran globu: motyw #2\"\n  GMGEO3: \"Ekran globu: motyw #3\"\n  GMGEO4: \"Ekran globu: motyw #4\"\n  GMGEO5: \"Ekran globu: motyw #5\"\n  GMGEO6: \"Ekran globu: motyw #6\"\n  GMTACDRY: \"Motyw z ekranu bitwy (ląd)\"\n  GMTACWET: \"Motyw z ekranu bitwy (woda)\"\n  GMINTER0: \"Motyw walki powietrznej #0\"\n  GMINTER1: \"Motyw walki powietrznej #1\"\n  GMINTER2: \"Motyw walki powietrznej #2\"\n  GMINTER3: \"Motyw walki powietrznej #3\"\n  GLOBE_TEXTURE_0: \"Dno/Koral 1\"\n  GLOBE_TEXTURE_1: \"Stanowisko badawcze 1\"\n  GLOBE_TEXTURE_2: \"Rozbity samolot\"\n  GLOBE_TEXTURE_3: \"Atlantyda\"\n  GLOBE_TEXTURE_4: \"Świątynia Majów 1\"\n  GLOBE_TEXTURE_5: \"Zatopiony galeon\"\n  GLOBE_TEXTURE_6: \"Zatopiony liniowiec 1\"\n  GLOBE_TEXTURE_7: \"Wulkaniczny 1\"\n  GLOBE_TEXTURE_8: \"Dno/Koral 2\"\n  GLOBE_TEXTURE_9: \"Wulkaniczny 2\"\n  GLOBE_TEXTURE_10: \"Zatopiony liniowiec 2\"\n  GLOBE_TEXTURE_11: \"Stanowisko badawcze 2\"\n  GLOBE_TEXTURE_12: \"Świątynia Majów 2\"\n  STR_LANDED: \"Osiadnięcie\"\n  STR_SHOT_TYPE_AUTO: \"Seria (x{0})\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/OXCE/pt-BR.yml",
    "content": "pt-BR:\n  STR_FACILITY_IN_USE_STORAGE: \"AQUAMÓDULO EM USO!{SMALLLINE}Espaço de armazenamento insuficiente.\"\n  STR_FACILITY_IN_USE_QUARTERS: \"AQUAMÓDULO EM USO!{SMALLLINE}Habitações insuficientes.\"\n  STR_FACILITY_IN_USE_LABORATORIES: \"AQUAMÓDULO EM USO!{SMALLLINE}Espaço de laboratório insuficiente.\"\n  STR_FACILITY_IN_USE_WORKSHOPS: \"AQUAMÓDULO EM USO!{SMALLLINE}Espaço de oficina insuficiente.\"\n  STR_FACILITY_IN_USE_HANGARS: \"AQUAMÓDULO EM USO!{SMALLLINE}Espaço para aerosubmarinos insuficiente.\"\n  STR_FACILITY_IN_USE_PSI_LABS: \"AQUAMÓDULO EM USO!{SMALLLINE}Espaço de laboratório C.M insuficiente.\"\n  STR_FACILITY_IN_USE_GYMS: \"AQUAMÓDULO EM USO!{SMALLLINE}Academias insuficientes.\"\n  STR_FACILITY_IN_USE_PRISONS: \"AQUAMÓDULO EM USO!{SMALLLINE}Contenção alienígena insuficiente.\"\n  STR_NOT_ENOUGH_HWP_CAPACITY: \"CAPACIDADE DE SAS INSUFICIENTE DISPONÍVEL!{SMALLLINE}Use um módulo diferente ou reduza o número de SAS atribuídas.\"\n  STR_AVATAR_NAME_1: \"#01 Dolph\"\n  STR_AVATAR_NAME_2: \"#02 Will\"\n  STR_AVATAR_NAME_3: \"#03 Sylvester\"\n  STR_AVATAR_NAME_4: \"#04 Dwayne\"\n  STR_AVATAR_NAME_5: \"#05 Linda\"\n  STR_AVATAR_NAME_6: \"#06 Uma\"\n  STR_AVATAR_NAME_7: \"#07 Halle\"\n  STR_AVATAR_NAME_8: \"#08 Angelina\"\n  STR_PSI_SHORT: \"C.M.>{ALT}{0}/{1}\"\n  STR_EVASIVE_MANEUVERS: \"MANOBRAS EVASIVAS\"\n  STR_UFO_DESTROYED_BY_SPLASHDOWN: \"SUBMARINO ALIENÍGENA DESTRUÍDO!\"\n  STR_UFO_SURVIVED_SPLASHDOWN: \"SUBMARINO ALIENÍGENA ABATIDO!\"\n  STR_UFO_HAS_LANDED: \"OSNI pousou em{NEWLINE}{0}\"\n  GMGEO1: \"Faixa nº 1 da Tela Global\"\n  GMGEO2: \"Faixa nº 2 da Tela Global\"\n  GMGEO3: \"Faixa nº 3 da Tela Global\"\n  GMGEO4: \"Faixa nº 4 da Tela Global\"\n  GMGEO5: \"Faixa nº 5 da Tela Global\"\n  GMGEO6: \"Faixa nº 6 da Tela Global\"\n  GMTACDRY: \"Faixa da Tela de Combate (Terra)\"\n  GMTACWET: \"Faixa da Tela de Combate (Água)\"\n  GMINTER0: \"Faixa Nº 0 do Combate Aéreo\"\n  GMINTER1: \"Faixa Nº 1 do Combate Aéreo\"\n  GMINTER2: \"Faixa Nº 2 do Combate Aéreo\"\n  GMINTER3: \"Faixa Nº 3 do Combate Aéreo\"\n  GLOBE_TEXTURE_0: \"Fundo marinho/Coral 1\"\n  GLOBE_TEXTURE_1: \"Instalação de Pesquisa 1\"\n  GLOBE_TEXTURE_2: \"Avião Acidentado\"\n  GLOBE_TEXTURE_3: \"Atlântida\"\n  GLOBE_TEXTURE_4: \"Templo Maia 1\"\n  GLOBE_TEXTURE_5: \"Galeão Afundado\"\n  GLOBE_TEXTURE_6: \"Navio Afundado 1\"\n  GLOBE_TEXTURE_7: \"Vulcânico 1\"\n  GLOBE_TEXTURE_8: \"Fundo do mar/Coral 2\"\n  GLOBE_TEXTURE_9: \"Vulcânico 2\"\n  GLOBE_TEXTURE_10: \"Navio Afundado 2\"\n  GLOBE_TEXTURE_11: \"Instalação de Pesquisa 2\"\n  GLOBE_TEXTURE_12: \"Templo Maia 2\"\n  STR_SHOT_TYPE_AUTO: \"Auto (x{0})\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/OXCE/ro.yml",
    "content": "ro:\n  STR_AVATAR_NAME_1: \"#01 Dolph\"\n  STR_AVATAR_NAME_2: \"#02 Will\"\n  STR_AVATAR_NAME_3: \"#03 Sylvester\"\n  STR_AVATAR_NAME_4: \"#04 Dwayne\"\n  STR_AVATAR_NAME_5: \"#05 Linda\"\n  STR_AVATAR_NAME_6: \"#06 Uma\"\n  STR_AVATAR_NAME_7: \"#07 Halle\"\n  STR_AVATAR_NAME_8: \"#08 Angelina\"\n  STR_PSI_SHORT: \"M.C.>{ALT}{0}/{1}\"\n  STR_EVASIVE_MANEUVERS: \"MANEVRE EVAZIVE\"\n  STR_UFO_HAS_LANDED: \"USN a aterizat la {NEWLINE}{0}\"\n  GMGEO1: \"Geosferă  Pista #1\"\n  GMGEO2: \"Geosferă Pista #2\"\n  GMGEO3: \"Geosferă Pista #3\"\n  GMGEO4: \"Geosferă Pista #4\"\n  GMGEO5: \"Geosferă Pista #5\"\n  GMGEO6: \"Geosferă Pista #6\"\n  GMTACDRY: \"Geosferă Pista (Teren)\"\n  GMTACWET: \"Geosferă Pista (Apa)\"\n  STR_SHOT_TYPE_AUTO: \"Auto (x{0})\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/OXCE/ru.yml",
    "content": "ru:\n  STR_FACILITY_IN_USE_STORAGE: \"ОТСЕК ИСПОЛЬЗУЕТСЯ!{SMALLLINE}Недостаточно места на складе.\"\n  STR_FACILITY_IN_USE_QUARTERS: \"ОТСЕК ИСПОЛЬЗУЕТСЯ!{SMALLLINE}Недостаточно места в жилых модулях.\"\n  STR_FACILITY_IN_USE_LABORATORIES: \"ОТСЕК ИСПОЛЬЗУЕТСЯ!{SMALLLINE}Недостаточно рабочего пространства в лаборатории.\"\n  STR_FACILITY_IN_USE_WORKSHOPS: \"ОТСЕК ИСПОЛЬЗУЕТСЯ!{SMALLLINE}Недостаточно рабочего пространства в мастерской.\"\n  STR_FACILITY_IN_USE_HANGARS: \"ОТСЕК ИСПОЛЬЗУЕТСЯ!{SMALLLINE}Недостаточно места в доках.\"\n  STR_FACILITY_IN_USE_PSI_LABS: \"ОТСЕК ИСПОЛЬЗУЕТСЯ!{SMALLLINE}Недостаточно рабочего пространства в лаборатории М.К.\"\n  STR_FACILITY_IN_USE_GYMS: \"ОТСЕК ИСПОЛЬЗУЕТСЯ!{SMALLLINE}Недостаточно места в спортзале.\"\n  STR_FACILITY_IN_USE_PRISONS: \"ОТСЕК ИСПОЛЬЗУЕТСЯ!{SMALLLINE}Недостаточно места в изоляторе пришельцев.\"\n  STR_NOT_ENOUGH_HWP_CAPACITY: \"НЕДОСТАТОЧНО МЕСТ ПОД ПБС!{SMALLLINE}Установите другой грузовой отсек или уберите часть ПБС.\"\n  STR_AVATAR_NAME_1: \"#01 Дольф\"\n  STR_AVATAR_NAME_2: \"#02 Уилл\"\n  STR_AVATAR_NAME_3: \"#03 Сильвестр\"\n  STR_AVATAR_NAME_4: \"#04 Дуэйн\"\n  STR_AVATAR_NAME_5: \"#05 Линда\"\n  STR_AVATAR_NAME_6: \"#06 Ума\"\n  STR_AVATAR_NAME_7: \"#07 Халле\"\n  STR_AVATAR_NAME_8: \"#08 Анджелина\"\n  STR_PSI_SHORT: \"М.К.>{ALT}{0}/{1}\"\n  STR_EVASIVE_MANEUVERS: \"УКЛОНЕНИЕ\"\n  STR_UFO_DESTROYED_BY_SPLASHDOWN: \"НПО УНИЧТОЖЕН!\"\n  STR_UFO_SURVIVED_SPLASHDOWN: \"НПО ПОТОПЛЕН!\"\n  STR_UFO_HAS_LANDED: \"НПО лег на дно.{NEWLINE}Место: {NEWLINE}{0}\"\n  GMGEO1: \"Трек #1 в страт. режиме\"\n  GMGEO2: \"Трек #2 в страт. режиме\"\n  GMGEO3: \"Трек #3 в страт. режиме\"\n  GMGEO4: \"Трек #4 в страт. режиме\"\n  GMGEO5: \"Трек #5 в страт. режиме\"\n  GMGEO6: \"Трек #6 в страт. режиме\"\n  GMTACDRY: \"Трек в такт. режиме (Суша)\"\n  GMTACWET: \"Трек в такт. режиме (Вода)\"\n  GMINTER0: \"Трек перехвата #0\"\n  GMINTER1: \"Трек перехвата #1\"\n  GMINTER2: \"Трек перехвата #2\"\n  GMINTER3: \"Трек перехвата #3\"\n  GLOBE_TEXTURE_0: \"Океанское дно/Кораллы 1\"\n  GLOBE_TEXTURE_1: \"Подводная станция 1\"\n  GLOBE_TEXTURE_2: \"Разбившийся самолет\"\n  GLOBE_TEXTURE_3: \"Атлантида\"\n  GLOBE_TEXTURE_4: \"Храм майя 1\"\n  GLOBE_TEXTURE_5: \"Затонувший галеон\"\n  GLOBE_TEXTURE_6: \"Затонувший лайнер 1\"\n  GLOBE_TEXTURE_7: \"Вулканы 1\"\n  GLOBE_TEXTURE_8: \"Океанское дно/Кораллы 2\"\n  GLOBE_TEXTURE_9: \"Вулканы 2\"\n  GLOBE_TEXTURE_10: \"Затонувший лайнер 2\"\n  GLOBE_TEXTURE_11: \"Подводная станция 2\"\n  GLOBE_TEXTURE_12: \"Храм майя 2\"\n  STR_LANDED: \"Посадка\"\n  STR_SHOT_TYPE_AUTO: \"Очер. (x{0})\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/OXCE/uk.yml",
    "content": "uk:\n  STR_FACILITY_IN_USE_STORAGE: \"АКВА-МОДУЛЬ ВИКОРИСТОВУЄТЬСЯ! {SMALLLINE}Не вистачає місця для зберігання.\"\n  STR_FACILITY_IN_USE_QUARTERS: \"АКВА-МОДУЛЬ ВИКОРИСТОВУЄТЬСЯ!{SMALLLINE}Недостатньо житлових приміщень.\"\n  STR_FACILITY_IN_USE_LABORATORIES: \"АКВА-МОДУЛЬ ВИКОРИСТОВУЄТЬСЯ!{SMALLLINE}Недостатньо місця в лабораторії.\"\n  STR_FACILITY_IN_USE_WORKSHOPS: \"АКВА-МОДУЛЬ ВИКОРИСТОВУЄТЬСЯ!{SMALLLINE}Не вистачає місця в майстерні.\"\n  STR_FACILITY_IN_USE_HANGARS: \"АКВА-МОДУЛЬ ВИКОРИСТОВУЄТЬСЯ!{SMALLLINE}Не вистачає доків.\"\n  STR_FACILITY_IN_USE_PSI_LABS: \"АКВА-МОДУЛЬ ВИКОРИСТОВУЄТЬСЯ!{SMALLLINE}Не вистачає лабораторій М.К.\"\n  STR_FACILITY_IN_USE_GYMS: \"АКВА-МОДУЛЬ ВИКОРИСТОВУЄТЬСЯ!{SMALLLINE}Не вистачає спортзалів.\"\n  STR_FACILITY_IN_USE_PRISONS: \"АКВА-МОДУЛЬ ВИКОРИСТОВУЄТЬСЯ!{SMALLLINE}Не вистачає тюрм для прибульців.\"\n  STR_NOT_ENOUGH_HWP_CAPACITY: \"НЕ ДОСТАТНЬО МІСТКОСТІ ДЛЯ ВБП!{SMALLLINE}Використайте інший модуль або зменшіть кількість призначених ВБП.\"\n  STR_AVATAR_NAME_1: \"#01 Дольф\"\n  STR_AVATAR_NAME_2: \"#02 Вілл\"\n  STR_AVATAR_NAME_3: \"#03 Сильвестр\"\n  STR_AVATAR_NAME_4: \"#04 Двейн\"\n  STR_AVATAR_NAME_5: \"#05 Лінда\"\n  STR_AVATAR_NAME_6: \"#06 Ума\"\n  STR_AVATAR_NAME_7: \"#07 Хеллі\"\n  STR_AVATAR_NAME_8: \"#08 Анджеліна\"\n  STR_PSI_SHORT: \"PSI>{ALT}{0}/{1}\"\n  STR_EVASIVE_MANEUVERS: \"УХИЛЬНІ МАНЕВРИ\"\n  STR_UFO_DESTROYED_BY_SPLASHDOWN: \"СУБМАРИНА ПРИБУЛЬЦІВ ЗНИЩЕНА!\"\n  STR_UFO_SURVIVED_SPLASHDOWN: \"СУБМАРИНА ПРИБУЛЬЦІВ ПІДБИТА!\"\n  STR_UFO_HAS_LANDED: \"НПО приводнився у{NEWLINE}{0}\"\n  GMGEO1: \"Трек планетарного вигляду #1\"\n  GMGEO2: \"Трек планетарного вигляду #2\"\n  GMGEO3: \"Трек планетарного вигляду #3\"\n  GMGEO4: \"Трек планетарного вигляду #4\"\n  GMGEO5: \"Трек планетарного вигляду #5\"\n  GMGEO6: \"Трек планетарного вигляду #6\"\n  GMTACDRY: \"Трек поля бою (Суходіл)\"\n  GMTACWET: \"Трек поля бою (Вода)\"\n  GMINTER0: \"Трек перехоплення №0\"\n  GMINTER1: \"Трек перехоплення №1\"\n  GMINTER2: \"Трек перехоплення №2\"\n  GMINTER3: \"Трек перехоплення №3\"\n  GLOBE_TEXTURE_0: \"Морське дно/кораллові рифи 1\"\n  GLOBE_TEXTURE_1: \"Науково-дослідний центр 1\"\n  GLOBE_TEXTURE_2: \"Розбитий літак\"\n  GLOBE_TEXTURE_3: \"Атлантида\"\n  GLOBE_TEXTURE_4: \"Храм майя 1\"\n  GLOBE_TEXTURE_5: \"Затонулий галеон\"\n  GLOBE_TEXTURE_6: \"Затонулий лайнер 1\"\n  GLOBE_TEXTURE_7: \"Вулкан 1\"\n  GLOBE_TEXTURE_8: \"Морське дно/кораллові рифи 2\"\n  GLOBE_TEXTURE_9: \"Вулкан 2\"\n  GLOBE_TEXTURE_10: \"Затонулий лайнер 2\"\n  GLOBE_TEXTURE_11: \"Науково-дослідний центр 2\"\n  GLOBE_TEXTURE_12: \"Храм майя 2\"\n  STR_LANDED: \"Причалив\"\n  STR_SHOT_TYPE_AUTO: \"Авто (x{0})\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/bg.yml",
    "content": "bg:\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"ЦЕНТРИРАНЕ-ВРЕМЕ=5 сек\"\n  STR_CANCEL_UC: \"ОТКАЗ\"\n  STR_NONE: \"Няма\"\n  STR_UNKNOWN: \"Неизвестен\"\n  STR_POOR: \"Слаб\"\n  STR_AVERAGE: \"Среден\"\n  STR_GOOD: \"Добър\"\n  STR_EXCELLENT: \"Отличен\"\n  STR_BUILD_NEW_BASE_UC: \"НОВА БАЗА\"\n  STR_BASE_INFORMATION: \"ИНФОРМАЦИЯ ЗА БАЗАТА\"\n  STR_BUILD_FACILITIES: \"СТРОЕЖ НА МОДУЛИ\"\n  STR_RESEARCH: \"ИЗСЛЕДВАНЕ\"\n  STR_MANUFACTURE: \"ИЗРАБОТКА\"\n  STR_TRANSFER_UC: \"ПРЕХВЪРЛЯНЕ\"\n  STR_PURCHASE_RECRUIT: \"КУПУВАНЕ/НАЕМАНЕ\"\n  STR_SACK: \"УВОЛНЯВАНЕ\"\n  STR_SELL_SACK_UC: \"ПРОДАВАНЕ/УВОЛНЯВАНЕ\"\n  STR_GEOSCAPE_UC: \"ГЛОБАЛНА КАРТА\"\n  STR_NAME: \"Име\"\n  STR_AREA: \"Регион\"\n  STR_BUILD_NEW_BASE: \"Build New Base\"\n  STR_CANCEL: \"Отказ\"\n  STR_COST_UC: \"ЦЕНА>\"\n  STR_CONSTRUCTION_TIME_UC: \"ВРЕМЕ ЗА СТРОЕЖ>\"\n  STR_MAINTENANCE_UC: \"ПОДДРЪЖКА>\"\n  STR_OK: \"БИВА\"\n  STR_INSTALLATION: \"Инсталиране\"\n  STR_CURRENT_RESEARCH: \"ТЕКУЩИ ИЗСЛЕДВАНИЯ\"\n  STR_SCIENTISTS_AVAILABLE: \"Свободни учени>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Заети учени>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Свободна лабораторна площ>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"НАУЧЕН ПРОЕКТ\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"АНГАЖИРАНИ УЧЕНИ\"\n  STR_PROGRESS: \"НАПРЕДЪК\"\n  STR_NEW_PROJECT: \"Нов проект\"\n  STR_CANCEL_PROJECT: \"СПРЕТЕ ПРОЕКТА\"\n  STR_NEW_RESEARCH_PROJECTS: \"НОВИ НАУЧНИ ПРОЕКТИ\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"СВОБОДНИ УЧЕНИ>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"СВОБОДНА ЛАБОРАТОРНА ПЛОЩ>{ALT}{0}\"\n  STR_INCREASE: \"Увеличаване\"\n  STR_DECREASE: \"Намаляване\"\n  STR_START_PROJECT: \"ЗАПОЧНЕТЕ ПРОЕКТА\"\n  STR_CURRENT_PRODUCTION: \"ТЕКУЩО ПРОИЗВОДСТВО\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Свободна работна площ>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Текущи средства>{ALT}{0}\"\n  STR_ITEM: \"АРТИКУЛ\"\n  STR_UNITS_PRODUCED: \"Изработени{NEWLINE}изделия\"\n  STR_TOTAL_TO_PRODUCE: \"Общо за изработка\"\n  STR_COST__PER__UNIT: \"Един{NEWLINE}ична{NEWLINE}цена\"\n  STR_DAYS_HOURS_LEFT: \"Оставащи{NEWLINE}дни/часове\"\n  STR_NEW_PRODUCTION: \"Нова партида\"\n  STR_PRODUCTION_ITEMS: \"Въможни изделия\"\n  STR_CATEGORY: \"КАТЕГОРИЯ\"\n  STR_START_PRODUCTION: \"ЗАПОЧНЕТЕ ИЗРАБОТКА\"\n  STR_COST_PER_UNIT_: \"Единична цена>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Нужна работна площ>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"ИЗИСКВАТ СЕ СПЕЦИАЛНИ МАТЕРИАЛИ\"\n  STR_ITEM_REQUIRED: \"НЕОБХОДИМИ ЕЛЕМЕНТИ\"\n  STR_UNITS_REQUIRED: \"НЕОБХОДИМО КОЛИЧЕСТВО\"\n  STR_UNITS_AVAILABLE: \"НАЛИЧНО КОЛИЧЕСТВО\"\n  STR_STOP_PRODUCTION: \"СПРЕТЕ ИЗРАБОТКА\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"СВОБОДНА РАБОТНА ПЛОЩ>{ALT}{0}\"\n  STR_INCREASE_UC: \"УВЕЛИЧАВАНЕ\"\n  STR_DECREASE_UC: \"НАМАЛЯВАНЕ\"\n  STR_UNITS_TO_PRODUCE: \"Бройки за изработка\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Закупуване/Наемане на персонал\"\n  STR_COST_OF_PURCHASES: \"Цена на покупките>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"ЕДИНИЧНА ЦЕНА\"\n  STR_QUANTITY_UC: \"КОЛИЧ-ВО\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"СВОБОДЕН ПЕРСОНАЛ:ОБЩО ПЕРСОНАЛ>\"\n  STR_SCIENTISTS: \"Учени\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"ИЗПОЛЗВАНА ПЛОЩ:ОБЩА ПЛОЩ>\"\n  STR_LIVING_QUARTERS: \"Жилища\"\n  STR_STORES: \"Запаси\"\n  STR_LABORATORIES: \"Лаборатории\"\n  STR_WORK_SHOPS: \"Работилници\"\n  STR_DEFENSE_STRENGTH: \"Сила на защитата\"\n  STR_TRANSFERS_UC: \"ПРИСТИГАЩИ\"\n  STR_TRANSFERS: \"Пристигащи\"\n  STR_ARRIVAL_TIME_HOURS: \"Пристигане след (часа)\"\n  STR_COST_: \"Цена>{ALT}{0}\"\n  STR_AREA_: \"Регион>{ALT}{0}\"\n  STR_BASE_NAME: \"Име на базата?\"\n  STR_TRANSFER: \"Прехвърляне\"\n  STR_AMOUNT_TO_TRANSFER: \"ИЗПРАЩАНО{NEWLINE}КОЛИЧ-ВО\"\n  STR_SELECT_DESTINATION_BASE: \"Прехвърляне в коя база?\"\n  STR_COST: \"Цена\"\n  STR_TOTAL_UC: \"ОБЩО\"\n  STR_INCOME: \"Приходи\"\n  STR_EXPENDITURE: \"Разходи\"\n  STR_MAINTENANCE: \"Поддръжка\"\n  STR_BALANCE: \"Салдо\"\n  STR_FINANCE: \"Финанси\"\n  STR_DATE_FIRST: \"{0}ви\"\n  STR_DATE_SECOND: \"{0}ри\"\n  STR_DATE_THIRD: \"{0}ти\"\n  STR_DATE_FOURTH: \"{0}и\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Няма достатъчно специални материали за изработката на{NEWLINE}{0}{NEWLINE}в{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Няма достатъчно средства за изработката на{NEWLINE}{0}{NEWLINE}в{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"Изработката на{NEWLINE}{0}{NEWLINE}в{NEWLINE}{1}{NEWLINE}приключи\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"Построяването на{NEWLINE}{0}{NEWLINE}в{NEWLINE}{1}{NEWLINE}приключи\"\n  STR_OK_5_SECONDS: \"ОК - 5 сек\"\n  STR_RESEARCH_COMPLETED: \"Завършихме изследване\"\n  STR_VIEW_REPORTS: \"РЕЗУЛТАТИ\"\n  STR_WE_CAN_NOW_RESEARCH: \"Вече можем да проучим\"\n  STR_WE_CAN_NOW_PRODUCE: \"Вече можем да изработваме\"\n  STR_SUNDAY: \"НЕДЕЛЯ\"\n  STR_MONDAY: \"ПОНЕДЕЛНИК\"\n  STR_TUESDAY: \"ВТОРНИК\"\n  STR_WEDNESDAY: \"СРЯДА\"\n  STR_THURSDAY: \"ЧЕТВЪРТЪК\"\n  STR_FRIDAY: \"ПЕТЪК\"\n  STR_SATURDAY: \"СЪБОТА\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Недостатъчно {0} да презаредим {1} в {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Недостатъчно {0} да въоръжим {1} в {2}\"\n  STR_ALIENS_DEFEATED: \"Пришълци претърпяват поражение\"\n  STR_BASE_IS_LOST: \"Загубена е база\"\n  STR_BASE_IS_SAVED: \"Спасена е база\"\n  STR_ALIENS_KILLED: \"УБИТИ ИЗВЪНЗЕМНИ\"\n  STR_ALIEN_CORPSES_RECOVERED: \"ПРИБРАНИ ИЗВЪНЗЕМНИ ТРУПОВЕ\"\n  STR_LIVE_ALIENS_RECOVERED: \"ПРИБРАНИ ЖИВИ ИЗВЪНЗЕМНИ\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"ПРИБРАНИ ИЗВЪНЗЕМНИ АРТЕФАКТИ\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"ЦИВИЛНИ УБИТИ ОТ ИЗВЪНЗЕМНИ\"\n  STR_CIVILIANS_SAVED: \"СПАСЕНИ ЦИВИЛНИ\"\n  STR_BASE_UNDER_ATTACK: \"Нападение над {0}!\"\n  STR_BASE_DEFENSES_INITIATED: \"ЗАДЕЙСТВА СЕ ЗАЩИТАТА НА БАЗАТА\"\n  STR_HIT: \"ПОПАДЕНИЕ!\"\n  STR_MISSED: \"НЕ УЛУЧИ!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Продажба/Уволняване на персонал\"\n  STR_VALUE_OF_SALES: \"СТОЙНОСТ НА ПРОДАЖБИТЕ> {ALT}{0}\"\n  STR_FUNDS: \"СРЕДСТВА> {ALT}{0}\"\n  STR_SELL_SACK: \"Прод./Увол.\"\n  STR_VALUE: \"Стойност\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_BASE_DEFENSE: \"ОТБРАНА НА БАЗА\"\n  STR_BASE_UC_: \"БАЗА> {0}\"\n  STR_NO_FREE_ACCOMODATION: \"НЯМА СВОБОДНИ ЖИЛИЩА!{SMALLLINE}В жилищните помещения на целевата база няма достатъчно място.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"НЕ ДОСТИГА РАБОТНА ПЛОЩ!{SMALLLINE}Простоете нова работилница или намалете работата по други проекти.\"\n  STR_NOT_ENOUGH_MONEY: \"НЕ ДОСТИГАТ СРЕДСТВА!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"НЕ ДОСТИГА СКЛАДОВА ПЛОЩ!{SMALLLINE}Построете още складови помещения или прехвърлете наличните запаси в други бази.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"НЕ ДОСТИГА ЖИЛИЩНА ПЛОЩ!{SMALLLINE}Построете още жилищни помещения или прехвърлете личен състав в други бази.\"\n  STR_LAUNCH_INTERCEPTION: \"ИЗПРАЩАНЕ НА ПРЕХВАЩАЧИ\"\n  STR_CRAFT: \"ЛЕТАТЕЛЕН АПАРАТ\"\n  STR_STATUS: \"СЪСТОЯНИЕ\"\n  STR_BASE: \"БАЗА\"\n  STR_READY: \"ГОТОВНОСТ\"\n  STR_OUT: \"В ПОЛЕТ\"\n  STR_REPAIRS: \"ПОПРАВКИ\"\n  STR_REFUELLING: \"ПРЕЗАРЕЖДАНЕ\"\n  STR_REARMING: \"ВЪОРЪЖАВАНЕ\"\n  STR_TARGET: \"ЦЕЛ: {0}\"\n  STR_WAY_POINT: \"УСЛОВНА ТОЧКА\"\n  STR_YES: \"ДА\"\n  STR_NO: \"НЕ\"\n  STR_SELECT_DESTINATION: \"ИЗБОР НА ЦЕЛ\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"ИЗБЕРЕТЕ МЯСТО ЗА НОВА БАЗА\"\n  STR_RETURN_TO_BASE: \"ЗАВРЪЩАНЕ В БАЗАТА\"\n  STR_SELECT_NEW_TARGET: \"ИЗБОР НА НОВА ЦЕЛ\"\n  STR_PATROL: \"ПАТРУЛИРАНЕ\"\n  STR_STATUS_: \"СЪСТОЯНИЕ>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"ЗАВРЪЩА СЕ - ПОВРЕДИ\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"ЗАВРЪЩА СЕ - МАЛКО ГОРИВО\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"КРАЙ НА МИСИЯТА - ЗАВРЪЩА СЕ\"\n  STR_PATROLLING: \"ПАТРУЛИРА\"\n  STR_RETURNING_TO_BASE: \"ЗАВРЪЩА СЕ В БАЗАТА\"\n  STR_DESTINATION_UC_: \"ЦЕЛ: {0}\"\n  STR_BASE_UC: \"БАЗА>{ALT}{0}\"\n  STR_SPEED_: \"СКОРОСТ>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"МАКСИМАЛНА СКОРОСТ>{ALT}{0}{ALT}\"\n  STR_FUEL: \"ГОРИВО>{ALT}{0}\"\n  STR_WEAPON_ONE: \"ОРЪЖИЕ-1>{ALT}{0}\"\n  STR_NONE_UC: \"НЯМА\"\n  STR_ROUNDS_: \"МУНИЦИИ>{ALT}{0}\"\n  STR_WEAPON_TWO: \"ОРЪЖИЕ-2>{ALT}{0}\"\n  STR_BASE_: \"База>{0}\"\n  STR_NAME_UC: \"ИМЕ\"\n  STR_AMMO_: \"МУНИЦИИ>{ALT}{0}\"\n  STR_CREW: \"ЕКИПАЖ\"\n  STR_EQUIPMENT_UC: \"СНАРЯЖЕНИЕ\"\n  STR_ARMOR: \"БРОНЯ\"\n  STR_MAX: \"МАКС>{ALT}{0}\"\n  STR_COLONEL: \"Командир\"\n  STR_COMMANDER: \"Капитан\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Екипаж на {0}\"\n  STR_SPACE_AVAILABLE: \"СВОБОДНИ МЕСТА>{ALT}{0}\"\n  STR_SPACE_USED: \"ЗАЕТИ МЕСТА>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"ЗАЕТА ПЛОЩ\"\n  STR_RANK: \"РАНГ\"\n  STR_WOUNDED: \"ЛЕКУВА СЕ\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Снаряжение в {0}\"\n  STR_DEFENSE_VALUE: \"Защитна стойност\"\n  STR_HIT_RATIO: \"Вероятност за попадение\"\n  STR_BEGIN_MISSION: \"Започване на операция?\"\n  STR_SELECT_ARMAMENT: \"Избор на въоръжение\"\n  STR_AMMUNITION_AVAILABLE: \"НАЛИЧНИ МУНИЦИИ\"\n  STR_ARMAMENT: \"ВЪОРЪЖЕНИЕ\"\n  STR_NOT_AVAILABLE: \"НЯМА\"\n  STR_TYPE: \"ВИД\"\n  STR_SELECT_ARMOR: \"Избор на броня\"\n  STR_NORTH: \"СЕВЕР\"\n  STR_NORTH_EAST: \"СЕВЕРОИЗТОК\"\n  STR_EAST: \"ИЗТОК\"\n  STR_SOUTH_EAST: \"ЮГОИЗТОК\"\n  STR_SOUTH: \"ЮГ\"\n  STR_SOUTH_WEST: \"ЮГОЗАПАД\"\n  STR_WEST: \"ЗАПАД\"\n  STR_NORTH_WEST: \"СЕВЕРОЗАПАД\"\n  STR_SELECT_ACTION: \"ИЗБЕРИ ДЕЙСТВИЕ\"\n  STR_VERY_LARGE: \"МНОГО ГОЛЯМ\"\n  STR_LARGE: \"ГОЛЯМ\"\n  STR_MEDIUM_UC: \"СРЕДЕН\"\n  STR_SMALL: \"МАЛЪК\"\n  STR_VERY_SMALL: \"МНОГО МАЛЪК\"\n  STR_DETECTED: \"Засечено\"\n  STR_SIZE_UC: \"РАЗМЕР\"\n  STR_HEADING: \"НАПРАВЛЕНИЕ\"\n  STR_SPEED: \"СКОРОСТ\"\n  STR_TRACKING_LOST: \"ЗАГУБЕН БЕ КОНТАКТ\"\n  STR_REDIRECT_CRAFT: \"ПРЕНАСОЧВАНЕ\"\n  STR_CRASH_SITE_: \"РАЗБИВАНЕ-{0}\"\n  STR_WAY_POINT_: \"УСЛОВНА ТОЧКА-{0}\"\n  STR_TERROR_SITE: \"ТЕРОР-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}достигна{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"и в момента патрулира\"\n  STR_ALIEN_ORIGINS: \"Произход на пришълците\"\n  STR_UFOPAEDIA: \"НЛОпедия\"\n  STR_SELECT_ITEM: \"ИЗБЕРЕТЕ ТЕМА\"\n  STR_ACCELERATION: \"УСКОРЕНИЕ>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"ГОРИВЕН ЗАПАС>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"ОРЪЖЕЙНИ ГНЕЗДА>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"ПОНЕСИМИ ПОРАЖЕНИЯ>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"ТОВАРЕН КАПАЦИТЕТ>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Поражения\"\n  STR_RANGE: \"Обсег\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Точност\"\n  STR_RE_LOAD_TIME: \"Презарежда за\"\n  STR_SECONDS: \"{0}s\"\n  STR_DAMAGE_ARMOR_PIERCING: \"БРОНЕБОЕН\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"ЕКСПЛОЗИВЕН\"\n  STR_DAMAGE_MELEE: \"МЕХАНИЧЕН\"\n  STR_DAMAGE_ACID: \"КИСЕЛИНЕН\"\n  STR_DAMAGE_SMOKE: \"ДИМ\"\n  STR_SHOT_TYPE: \"ВИД\"\n  STR_ACCURACY_UC: \"ТОЧНОСТ\"\n  STR_TIME_UNIT_COST: \"НУЖНИ ТД\"\n  STR_DAMAGE_UC: \"ЕФЕКТ\"\n  STR_AMMO: \"МУНИЦИИ\"\n  STR_SHOT_TYPE_AUTO: \"Автоматичен избор\"\n  STR_SHOT_TYPE_SNAP: \"Припрян\"\n  STR_SHOT_TYPE_AIMED: \"Прицелен\"\n  STR_CONSTRUCTION_TIME: \"Време за построяване\"\n  STR_CONSTRUCTION_COST: \"Цена за построяване\"\n  STR_MAINTENANCE_COST: \"Цена за поддръжка\"\n  STR_WEAPON: \"Оръжие\"\n  STR_AMMUNITION: \"Боеприпаси\"\n  STR_EQUIPMENT: \"Снаряжение\"\n  STR_ALIEN_CORPSE: \"Труп на извънземно\"\n  STR_PERSONAL_ARMOR: \"Лична броня\"\n  STR_RAW_MATERIALS: \"Суровини\"\n  STR_ALIEN: \"Извънземно\"\n  STR_ZOMBIE: \"Зомби\"\n  STR_LIVE_COMMANDER: \"Командир\"\n  STR_LIVE_NAVIGATOR: \"Навигатор\"\n  STR_LIVE_MEDIC: \"Медик\"\n  STR_LIVE_SOLDIER: \"Войник\"\n  STR_LIVE_TERRORIST: \"Терорист\"\n  STR_EXAMINATION_ROOM: \"Операционна маса\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Нов изтребител/транспорт\"\n  STR_ARMOR_PIERCING: \"БРОНЕБОЕН\"\n  STR_SCIENTIST: \"Учен\"\n  STR_NORTH_ATLANTIC: \"Северен Атлантик\"\n  STR_SOUTH_ATLANTIC: \"Южен Атлантик\"\n  STR_INDIAN_OCEAN: \"Индийски океан\"\n  STR_ARCTIC: \"Арктика\"\n  STR_NORTH_AMERICA: \"Северна Америка\"\n  STR_MAXIMUM_SPEED: \"Максимална скорост\"\n  STR_DAMAGE_CAPACITY: \"Понесими поражения\"\n  STR_WEAPON_POWER: \"Огнева мощ\"\n  STR_WEAPON_RANGE: \"Оръжеен обсег\"\n  STR_LABORATORY: \"Лаборатория\"\n  STR_WORKSHOP: \"Работилница\"\n  STR_GENERAL_STORES: \"Складово помещение\"\n  STR_ALIEN_CONTAINMENT: \"Изолационна\"\n  STR_USA: \"САЩ\"\n  STR_CIVILIAN: \"Цивилно лице\"\n  STR_JAN: \"яну\"\n  STR_FEB: \"фев\"\n  STR_MAR: \"мар\"\n  STR_APR: \"апр\"\n  STR_MAY: \"май\"\n  STR_JUN: \"юни\"\n  STR_JUL: \"юли\"\n  STR_AUG: \"авг\"\n  STR_SEP: \"сеп\"\n  STR_OCT: \"окт\"\n  STR_NOV: \"ное\"\n  STR_DEC: \"дек\"\n  STR_INTERNATIONAL_RELATIONS: \"МЕЖДУНАРОДНИ ОТНОШЕНИЯ\"\n  STR_COUNTRY: \"Страна\"\n  STR_FUNDING: \"Финансиране\"\n  STR_CHANGE: \"Промяна\"\n  STR_WEAPON_SYSTEMS: \"ОРЪЖЕЙНИ СИСТЕМИ\"\n  STR_DAMAGE_UC_: \"ПОВРЕДИ>{ALT}{0}\"\n  STR_MAGNA_BLAST_GRENADE_UFOPEDIA: \"Стандартна граната с точен и усложнен забавител за прецизен контрол.\"\n  STR_BATTLESHIP: \"Боен кораб\"\n  STR_RATING: \"ОЦЕНКА> {0}\"\n  STR_RATING_TERRIBLE: \"УЖАСНА!\"\n  STR_RATING_POOR: \"ЛОША!\"\n  STR_RATING_OK: \"БИВА\"\n  STR_RATING_GOOD: \"ДОБРА!\"\n  STR_RATING_EXCELLENT: \"ОТЛИЧНА!\"\n  STR_SCORE: \"ТОЧКИ\"\n  STR_MONTH: \"Месец> {ALT}{0} {1}\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"Управниците на {0} са особено доволни от способността ни да се справяме с локализираната заплаха и са съгласни да увеличат отпусканите от тях средства.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} и {1}\"\n  STR_KNOTS: \"{0} взл.\"\n  STR_MONTHLY_RATING: \"Месечна оценка> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Промяна във финансирането> {ALT}{0}\"\n  STR_RACE: \"ВИД\"\n  STR_MISSION: \"МИСИЯ\"\n  STR_ZONE: \"РЕГИОН\"\n  STR_ALLOCATE_RESEARCH: \"Задаване на изследвания\"\n  STR_ALLOCATE_MANUFACTURE: \"Задаване на изработка\"\n  STR_NEW_YORK: \"Ню Йорк\"\n  STR_VANCOUVER: \"Ванкувър\"\n  STR_WELLINGTON: \"Уелингтън\"\n  STR_MANILA: \"Манила\"\n  STR_HONG_KONG: \"Хонконг\"\n  STR_SINGAPORE: \"Сингапур\"\n  STR_BANGKOK: \"Банкок\"\n  STR_BOMBAY: \"Бомбай\"\n  STR_TOKYO: \"Токио\"\n  STR_SHANGHAI: \"Шанхай\"\n  STR_LONDON: \"Лондон\"\n  STR_IN_TRAINING: \"За{NEWLINE}обучение?\"\n  STR_TARGETTED_BY: \"В МОМЕНТА ЦЕЛ НА:\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"привършва горивото,{NEWLINE}завръща се в базата\"\n  STR_RANK_: \"РАНГ> {ALT}{0}\"\n  STR_MISSIONS: \"ОПЕРАЦИИ> {ALT}{0}\"\n  STR_KILLS: \"УБИТИ> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"ИЗЛЕКУВАНЕ СЛЕД> {ALT}{0}\"\n  STR_TIME_UNITS: \"ТОЧКИ ЗА ДЕЙСТВИЕ\"\n  STR_STAMINA: \"ИЗДЪРЖЛИВОСТ\"\n  STR_HEALTH: \"ЗДРАВЕ\"\n  STR_BRAVERY: \"СМЕЛОСТ\"\n  STR_REACTIONS: \"РЕАКЦИИ\"\n  STR_FIRING_ACCURACY: \"ТОЧНОСТ НА СТРЕЛБА\"\n  STR_THROWING_ACCURACY: \"ТОЧНОСТ НА ХВЪРЛЯНЕ\"\n  STR_STRENGTH: \"ФИЗИЧЕСКА СИЛА\"\n  STR_NEW_RANK: \"НОВ РАНГ\"\n  STR_PROMOTIONS: \"Повишения\"\n  STR_ALIEN_INFILTRATION: \"Внедряване на пришълци\"\n  STR_DISMANTLE: \"Демонтиране на\"\n  STR_TRANSFER_ITEMS_TO: \"Изпращане в {0}\"\n  STR_AMOUNT_AT_DESTINATION: \"КОЛИЧ-ВО{NEWLINE}ТАМ\"\n  STR_ITEMS_ARRIVING: \"Получена пратка\"\n  STR_DESTINATION_UC: \"ЦЕЛ\"\n  STR_MEDI_KIT: \"Аптечка\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Недостиг за пълно снаряжаване на отряда\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Ще трябва да проучим{NEWLINE}{0}{NEWLINE}за да можем да изработваме{NEWLINE}{1}\"\n  STR_STANDOFF: \"НАБЛЮДЕНИЕ\"\n  STR_CAUTIOUS_ATTACK: \"ПРЕДПАЗЛИВА АТАКА\"\n  STR_STANDARD_ATTACK: \"СТАНДАРТНА АТАКА\"\n  STR_AGGRESSIVE_ATTACK: \"АГРЕСИВНА АТАКА\"\n  STR_DISENGAGING: \"ОТТЕГЛЯНЕ\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Смаляване само при наблюдение\"\n  STR_STORES_UC: \"ЗАПАСИ\"\n  STR_DIFFICULTY_LEVEL: \"Ниво на трудност\"\n  STR_INTERCEPT: \"ПРЕХВАЩАНЕ\"\n  STR_BASES: \"БАЗИ\"\n  STR_GRAPHS: \"СТАТИСТИКА\"\n  STR_OPTIONS_UC: \"НАСТРОЙКИ\"\n  STR_FUNDING_UC: \"ФИНАНСИРАНЕ\"\n  STR_5_SECONDS: \"5 сек\"\n  STR_1_MINUTE: \"1 мин\"\n  STR_5_MINUTES: \"5 мин\"\n  STR_30_MINUTES: \"30 мин\"\n  STR_1_HOUR: \"1 час\"\n  STR_1_DAY: \"1 ден\"\n  STR_ENTER_NAME: \"Въведи име\"\n  STR_VICTORY_DATE: \"Дата на победата\"\n  STR_MONTHLY_COSTS: \"Месечни разходи\"\n  STR_SALARIES: \"Заплати\"\n  STR_BASE_MAINTENANCE: \"Поддръжка на базата\"\n  STR_COST_PER_UNIT: \"Единична цена\"\n  STR_QUANTITY: \"Количество\"\n  STR_TOTAL: \"Общо\"\n  STR_FRONT_ARMOR: \"Защита отпред\"\n  STR_LEFT_ARMOR: \"Защита отляво\"\n  STR_RIGHT_ARMOR: \"Защита отдясно\"\n  STR_REAR_ARMOR: \"Защита отзад\"\n  STR_UNDER_ARMOR: \"Защита отдолу\"\n  STR_UNIT: \"ЕДИНИЦА> {0}\"\n  STR_ENERGY: \"ЕНЕРГИЯ\"\n  STR_MORALE: \"БОЕН ДУХ\"\n  STR_ARMOR_: \"БРОНЯ> {0}\"\n  STR_FRONT_ARMOR_UC: \"ЗАЩИТА ОТПРЕД\"\n  STR_LEFT_ARMOR_UC: \"ЗАЩИТА ОТЛЯВО\"\n  STR_RIGHT_ARMOR_UC: \"ЗАЩИТА ОТДЯСНО\"\n  STR_REAR_ARMOR_UC: \"ЗАЩИТА ОТЗАД\"\n  STR_SKILLS: \"УМЕНИЯ> {0}\"\n  STR_LEVEL: \"НИВО> {0}\"\n  STR_HEAD: \"ГЛАВА\"\n  STR_TORSO: \"ТОРС\"\n  STR_RIGHT_ARM: \"ДЯСНА РЪКА\"\n  STR_LEFT_ARM: \"ЛЯВА РЪКА\"\n  STR_RIGHT_LEG: \"ДЕСЕН КРАК\"\n  STR_LEFT_LEG: \"ЛЯВ КРАК\"\n  STR_PAIN_KILLER: \"АНАЛГЕТИК\"\n  STR_STIMULANT: \"СТИМУЛАНТ\"\n  STR_HEAL: \"ПРЕВРЪЗКА\"\n  STR_TIME_UNITS_SHORT: \"ТД>{ALT}{0}\"\n  STR_WEIGHT: \"Тегло>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"Реакц>{ALT}{0}\"\n  STR_AMMO_ROUNDS_LEFT: \"МУНИЦИИ:{NEWLINE}ОСТАВАТ={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Аналг>{ALT}{0}{ALT}{NEWLINE}Стим>{ALT}{1}{ALT}{NEWLINE}Превр>{ALT}{2}\"\n  STR_THROW: \"Хвърляне\"\n  STR_AUTO_SHOT: \"Откос\"\n  STR_SNAP_SHOT: \"Припрян\"\n  STR_AIMED_SHOT: \"Прицелен\"\n  STR_STUN: \"Зашеметяване\"\n  STR_PRIME_GRENADE: \"Задействане\"\n  STR_USE_MEDI_KIT: \"Преглед\"\n  STR_ACCURACY_SHORT: \"Точ>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Не достигат точки за действие!\"\n  STR_NOT_ENOUGH_ENERGY: \"Не достига енергия!\"\n  STR_NO_ROUNDS_LEFT: \"Няма повече муниции!\"\n  STR_NO_AMMUNITION_LOADED: \"Оръжието не е заредено!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Неподходящи муниции за това оръжие!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"Оръжието вече е заредено!\"\n  STR_NO_LINE_OF_FIRE: \"Няма видимост към целта!\"\n  STR_GRENADE_IS_ACTIVATED: \"Гранатата е задействана!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Гранатата е обезвредена!\"\n  STR_THERE_IS_NO_ONE_THERE: \"Няма никой тук!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Извънземният артефакт не е проучен!\"\n  STR_OUT_OF_RANGE: \"Извън обсег!\"\n  STR_UNABLE_TO_THROW_HERE: \"Не може да хвърли тук!\"\n  STR_SET_TIMER: \"Забавяне\"\n  STR_HIDDEN_MOVEMENT: \"СКРИТИ ДВИЖЕНИЯ\"\n  STR_TURN: \"ХОД> {0}\"\n  STR_SIDE: \"СТРАНА> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Натиснете клавиш да продължите\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Бойният дух бе снижен!\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}изпадна в бяс\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}изпадна в бяс\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}изпадна в паника\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}изпадна в паника\"\n  STR_ALIENS: \"Пришълци\"\n  STR_RIGHT_HAND: \"ДЯСНА РЪКА\"\n  STR_LEFT_HAND: \"ЛЯВА РЪКА\"\n  STR_RIGHT_SHOULDER: \"ДЯСНО РАМО\"\n  STR_LEFT_SHOULDER: \"ЛЯВО РАМО\"\n  STR_BACK_PACK: \"РАНИЦА\"\n  STR_BELT: \"КОЛАН\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}изпадна в безсъзнание\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}изпадна в безсъзнание\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}умря заради смъртоносна рана\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}умря заради смъртоносна рана\"\n  STR_FATAL_WOUNDS: \"СМЪРТОНОСНИ РАНИ\"\n  STR_UNDER_ARMOR_UC: \"ЗАЩИТА ОТДОЛУ\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Точките действие са запазени за припрян изстрел\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Точките действие са запазени за откос\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Точките действие са запазени за прицелен изстрел\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Точките действие са запазени за коленичене\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"ТД са запазени за стрелба от коляно\"\n  STR_ABORT_MISSION_QUESTION: \"Изтегляне от операцията?\"\n  STR_CORPSE: \"Труп\"\n  STR_UNLOAD_CRAFT: \"Разтоварване\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}беше убита\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}беше убита\"\n  STR_HIT_MELEE: \"Удар\"\n  STR_GROUND: \"НА ЗЕМЯТА\"\n  STR_LIVING_QUARTERS_PLURAL: \"Жилища\"\n  STR_LIST_ITEM: \"АРТИКУЛ\"\n  STR_RESET: \"Изчистване\"\n  STR_MEMORIAL: \"Мемориал\"\n  STR_DATE_UC: \"ДАТА\"\n  STR_REMOVE_SELECTED: \"Изваждане на избраните\"\n  STR_CONTAINMENT_EXCEEDED: \"ИЗОЛАЦИОННИТЕ СА ПРЕПЪЛНЕНИ!{SMALLLINE}Не достига място в изолационните на {0}. Трябва да извадите от тях излишните извънземни (което ще причини смъртта им).\"\n  STR_MANAGE_CONTAINMENT: \"Задържани под изолация\"\n  STR_STORAGE_EXCEEDED: \"НАДВИШАВАНЕ НА КАПАЦИТЕТА!{SMALLLINE}Не достига място за съхранение в {0}. Трябва да продадете излишните неща.\"\n  STR_GO_TO_BASE: \"Показване на базата\"\n  STR_MELEE_ACCURACY: \"ТОЧНОСТ ПРИ РЪКОПАШЕН БОЙ\"\n  STR_SELL_PRODUCTION: \"ПРОДАВАНЕ\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"И двете ръце трябва да са свободни!\"\n  STR_ALL_ITEMS: \"ВСИЧКИ ПРЕДМЕТИ\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/cs.yml",
    "content": "cs:\n  STR_LEVIATHAN_UFOPEDIA: \"TRANSPORTNÍ A STÍHACÍ LÉTAJÍCÍ PONORKA SE SCHOPNOSTÍ PONORU DO EXTRÉMNÍCH HLOUBEK. VINIKAJÍCÍ SPOJENÍ MIMOZEMSKÉ A LIDSKÉ TECHNOLOGIE VYUŽÍVAJÍCÍ SYSTÉMY IONTOVÝCH POHONŮ A POLE MAGNETICKÉ NAVIGACE\"\n  STR_BARRACUDA_UFOPEDIA: \"BARACUDA OD BRITISH HYDROSPACE, POHÁNĚNÁ PŘEHŘÁTÝMI LASEROVÝMI MOTORY. JEDEN Z NEJRYCHLEJŠÍCH STÍHACÍCH STROJŮ NA SVĚTĚ, SCHOPNÝ PODVODNÍHO I VZDUŠNÉHO LETU. KLÍČOVÁ LOĎ V NASTÁVAJÍCÍ BITVĚ.\"\n  STR_HAMMERHEAD_UFOPEDIA: \"TRANSPORTNÍ A STÍHACÍ STROJ. REPLIKA MAGNETICKÉHO NAVIGAČNÍHO SYSTÉMU V LODI X-COM. AČKOLIV JE MALÁ, JEDNÁ SE O ÚŽASNÉ TECHNICKÉ PROVEDENÍ.\"\n  STR_TRITON_UFOPEDIA: \"TRITON, TRANSPORTÉR PRO ÚTOČNÉ KOMANDO, PLNĚ VYBAVENÝ VZDUŠNÝMI I VODNÍMI LETOVÝMI MOTORY. JEHO VYSOKÁ KAPACITA A ROBUSTNÍ KONSTRUKCE HO PASUJE MEZI HLAVNÍ DLOHODOBĚ UŽÍVANÉ STROJE VE FLOTILE X-COM.\"\n  STR_MANTA_UFOPEDIA: \"MANTA JE VYSOKORYCHLOSTNÍ STROJ, LÉTAJÍCÍ STÍHACÍ PONORKA PRO JEDNU OSOBU, BLÍZCE SE PODOBAJÍCÍ CIZÁCKÝM LODÍM S IONTOVÝM POHONEM. VELMI EFEKTIVNÍ ÚDERNÝ STROJ VE STUPŇUJÍCÍM SE KONFLIKTU.\"\n  STR_AJAX_UFOPEDIA: \"TORPÉDO AJAX JE CELOSVĚTOVĚ STANDARDNÍ PODMOŘSKÁ ZBRAŇ NASAZOVANÁ JAKO PŘESNÝ A SILNÝ ZASTRAŠUJÍCÍ PROSTŘEDEK.\"\n  STR_DUP_HEAD_UFOPEDIA: \"TECHNOLOGIE ZBRANÍ S HLAVICEMI Z PELET OCHUZENÉHO URANU JE POMĚRNĚ NOVÁ A TOTO JE PRVNÍ KOMERČNÍ ŘEŠENÍ, KTERÉ JI PLNĚ VYUŽÍVÁ.\"\n  STR_CRAFT_GAS_CANNON_UFOPEDIA: \"DĚLO POHÁNĚNÉ STLAČENÝM PLYNEM STŘÍLÍ TUHÉ STŘELY S VYSOKOU PRŮRAZNOU SCHOPNOSTÍ.\"\n  STR_PWT_CANNON_UFOPEDIA: \"PULSNÍ TORPÉDO VYUŽÍVÁ PŘEHŘÁTÝ PALIVOVÝ SYSTÉM A EXPLOZIVNÍ HLAVICI O EXTRÉMNÍ HUSTOTĚ, KTERÁ DOKÁŽE PRORAZIT VĚTŠINU SLITIN.\"\n  STR_GAUSS_CANNON_UFOPEDIA: \"MAGNETICKÝ KANÓN JE X-COMEM NOVĚ VYNALEZENÁ TECHNOLOGIE. ČÁSTICOVÝ AKCELERÁTOR TOHOTO SYSTÉMU JE NAPÁJEN KOMPAKTNÍM, TEKUTÝM VODÍKEM CHLAZENÝM, FŮZNÍM REAKTOREM.\"\n  STR_SONIC_OSCILLATOR_UFOPEDIA: \"MOHUTNÝ ZVUKOVÝ OSCILÁTOR VYTVÁŘÍ VLNY SONICKÉ SÍLY. SVŮJ CÍL NIČÍ ROZVIBROVÁNÍM JEHO MOLEKULÁRNÍCH VAZEB TAK, ŽE SE ROZPADNOU.\"\n  STR_AQUATOID_UFOPEDIA: \"Rasa akvatoidů je prastará společnost, která existovala již milenia před prvními nesmělými lidskými krůčky na zemi. Kompaktní forma a cibulovité části jsou připomínkou na jejich vesmírné příbuzné, sektany. Jejich síla spočívá ve vyspělé technologii molekulární kontroly. Akvatoidi se snaží prosadit svojí sterilní rasu genetickými modifikacemi, pro které jsou ideální lidské bytosti. Tyto experimenty jsou příčnou mnoha hybridních ras.\"\n  STR_AQUATOID_AUTOPSY: \"Pitva akvatoida\"\n  STR_AQUATOID_AUTOPSY_UFOPEDIA: \"Detailní analýza tohoto tvora nám dovoluje vyslovit hypotézu, že je to sektan, náš dřívější nepřítel. Je jen pozměněn chirurgickými metodami a implantáty tak, aby se z něj stalo vodní stvoření. Jeho zbytky plic mu umožňují omezený pohyb po souši. Kybernetické implantáty po celém těle zvyšují sílu jeho atrofovaných končetin a zlepšují funkce orgánů. Protože všichni členové této rasy jsou identičtí, lze se domnívat, že se jedná o klony.\"\n  STR_GILLMAN_UFOPEDIA: \"Téměř člověk, podivný tvor, zdá se být ještěřím humanoidem. Velmi blízce příbuzný člověku. Má extrémní sílu a rychlost pohybu v podmořském prostředí. Žábrouni jsou plně vyvinutou rasou. Vyskytují se jako samice a samci různých věkových skupin. Nezdá se, že by na nich byly provedeny jakékoliv genetické úpravy, nebo chirurgické deformace. Je možné, že se díváme na jednu z prastarých vývojových větví našeho vlastního druhu.\"\n  STR_GILLMAN_AUTOPSY: \"Pitva žábrouna\"\n  STR_GILLMAN_AUTOPSY_UFOPEDIA: \"Pitva prokázala, že toto není cizák, ale pozemský tvor. Prehistorická rasa, která měla vyhynout, jakmile začali převládat savci. V dobách dinosaurů, byly žábrouni inteligentní a silní obojživelníci. Katastrofa, která ukončila nadvládu ještěrů přinutila tyto tvory k symbióze s nově příchozími cizáky. V jejich lebkách je uloženo malé elektronické zařízení.\"\n  STR_LOBSTERMAN_UFOPEDIA: \"Toto je ohromující druh. Velikost převyšující člověka a šest úctyhodných končetin z něj nedělá nic jiného než vodního démona. Podobnosti tohoto tvora s pozemským krabem mu u jednotek X-COM vysloužili jméno kraboun. Je to nestvůra z hlubin. Pečlivě navržený bojový netvor s neuvěřitelnou silou je prakticky nezranitelný průraznými střelami. Samotná jeho klepeta mohou rozdrtit ocel.\"\n  STR_LOBSTERMAN_AUTOPSY: \"Pitva krabouna\"\n  STR_LOBSTERMAN_AUTOPSY_UFOPEDIA: \"Po překonání prakticky nezničitelného krunýře se vyjevila ohromující tělesná stavba tohoto tvora. Mocné svalstvo obepíná titanovou kostru, sofistikovaný zaměřovací systém s vícepásmovou detekční schopností je napojený přímo do mozku. Jeho několik očí je chráněno plastem tvrdším než ocel a je zřejmé, že pokud je jejich pánové nasadí ve větším množství, jsou nezastavitelní. Hluboko uvnitř jejich těl je ukryto několik zařízení neznámé konstrukce a funkce.\"\n  STR_TASOTH_UFOPEDIA: \"Tito mrštní a rychlí nepřátelé jsou hlavním prvkem cizácké armády. Jsou po stovkách chováni v ohromných kádích hloboko v srdci cizáckých kolonií. Tasot je mnohem silnější než člověk. Jedná se o zkutečného cizáka, jehož chování a masožravost je nesrovnatelná s čímkoliv z naší planety. Tasoti často tvoří zásadní složku cizáckých útoků, která nejspíš neustoupí z boje ani při zdrcující přesile.\"\n  STR_TASOTH_AUTOPSY: \"Pitva tasota\"\n  STR_TASOTH_AUTOPSY_UFOPEDIA: \"Rozbor odhalil kybernetický organismus obdařený zvláštní silou. Uvnitř tělesné schránky je malá pohonná jednotka, ale žádné identifikovatelné orgány. Výkon je v těle přenášen bio-elektrickým rozvodným systémem. Mrtvola postrádá jakékoliv kosti, nebo jinou podpůrnou strukturu. Jakmile tvor zemře, stane se z něj bezvládná hromada slizkého cizáckého masa a tekutin. Jediná další vnitřní konstrukce je pár keramických článků, které po dodání energie tvora náhle oživí.\"\n  STR_DEEP_ONE_UFOPEDIA: \"Hlubiňák je biologický zlý sen, kříženec, vyprodukovaný při zvrácených experimentech akvatoidů. Zaznamenali jsme několik variací těchto kreatur. Po rozsáhlém výzkumu docházíme k závěru, že jsou vyrobeny cizáky z dodávek čerstvého lidského materiálu, čímž tak rozšiřují své vlastní řady. Každý z těchto podlidí útočí elektrickými výboji energie, dost silnými k zabití akvanauta.\"\n  STR_DEEP_ONE_AUTOPSY: \"Pitva hlubiňáka\"\n  STR_DEEP_ONE_AUTOPSY_UFOPEDIA: \"Tvor je tvořen cizáckým organismem naroubovaným na člověka. Lidský mozek je značně přispůsoben k ovládání elektroniky a cizácké mozkové kůry. Všechny zbytky lidského těla se zdají být ztracené kromě jediného: očí. Chirurgický štěp nejspíš umožňuje cizáckému zárodku konzumovat lidského hostitele, než doroste. Houževnatá kůže tvora je zřejmě anorganická, z kovové síťoviny, extrémně silná a ohebná. Výsledný kříženec je silný, rychlý a pod úplnou kontrolou cizáků.\"\n  STR_BIODRONE_UFOPEDIA: \"Biodron je výtvor, který mohla stvořit jen cizácká mysl. Je to mozek, (lidský nebo cizácký), zachycený v plodových tekutinách a připojený k pohonné základové jednotce, která může létat nad zemí, nebo pod vodou. Každý biodron je ozbrojen výkonným zvukovým disruptorem. Trochu stroj a trochu organismus. Někteří naši vědci naznačují, že zbraň je řízena původními hlasivkami hostitelského organismu. Tito vysoce přesní a neúprosní super hlídací psi jsou často používáni cizáky k ochraně největších cenností.\"\n  STR_BIODRONE_AUTOPSY: \"Pitva biodrona\"\n  STR_BIODRONE_AUTOPSY_UFOPEDIA: \"Hypotéza, že tato zvuková rušička je biologické zařízení, se potvrdila. Tento nešťastný tvor doslova ukřičí své objeti k smrti. Každý ze vzorků vykazuje masivní jizvy po chirurgických zásazích a je značně zmrzačený. Cizáci zřejmě takto zlomí mozek k poslušnosti. Většina mozkové kůry tvora je cizáckého původu, ale nic se nevyrovná zděšení ze zjištění, že se jedná o jednotku založenou na člověku. Biodroni jsou napájeni iontovým pohonem a obsahují jakousi formu systému vzdáleného dálkového řízení.\"\n  STR_TENTACULAT_UFOPEDIA: \"Ani nejtemnější hrůzy Lovercrafta nemohly zplodit takovou nepopsatelnou stvůru. Mezi pozemskými zvířaty nemá srovnání, a prostředí, kde by takový tvor mohl vzniknout, je mimo představivost. Je vyzbrojen dlouhými chapadly, kterými tentakulát paralyzuje své oběti a následně je přemění v nemyslící mátohy. Toto potomstvo může způsobit smrt pouhým dotekem, i přes brnění. Tentakulát je nejnebezpečnější cizák, se keterým se zatím X-COM setkalo.\"\n  STR_TENTACULAT_AUTOPSY: \"Pitva tentakuláta\"\n  STR_TENTACULAT_AUTOPSY_UFOPEDIA: \"Pivtva odhalila malé kybernetické implantáty, uložené v obrovském mozku tvora. Systém vidění je tvořen složitou kombinací spojující obraz viditelného a tepelného světla. I v temných hlubinách oceánu se tato nestvůra zvládne orientovat s neomylnou přesností. Lze identifikovat zbytkové orgány, které zřejmě jen taktak dokáží plnit svou funkci pro přežití. Každý tvor má malý žaludek s externím konektorem, čili je logické se domnívat, že je svými pány krmen přímým dodáním živin.\"\n  STR_CALCINITE_UFOPEDIA: \"Jako potápěčské obleky ztracených vojáků, tito cizáci přepadají na mořském dně neopatrné akvanauty. Zákeřný úder spárem pevnějším než ocel může stačit, aby skolil i nejlepší potápěče. V průzoru obličejové masky lze spatřit vířící zeleně želatiovou postavu. Nelze vytušit žádnou známku skutečného tvora, který stojí za často smrtelnými setkáními, která jsme s nimi měli.\"\n  STR_CALCINITE_AUTOPSY: \"Pitva kalcinita\"\n  STR_CALCINITE_AUTOPSY_UFOPEDIA: \"Po odstranění obrněného obleku kalcinita se neobjevilo nic než beztvará louže protoplazmy. Nebyl nalezen žádný viditelný mozek, končetiny, nebo vjemové orgány. Jen hluboko tekutého těla se nachází malá kovová součástka. Po smrti již můžeme pouze odhadovat jeho pravou podstatu. Je to nevysvětlitelné tajemství našich cizáckých nepřátel.\"\n  STR_TRISCENE_UFOPEDIA: \"Tento dvounohý plaz je pamětníkem éry dinosaurů. Zdá se, že tuto jurskou příšeru zachránila její schopnost přežít ve vodě i na souši. Tvor je opásán nosičem zbraní a jeho čelisti jsou opatřeny mocnými kovovými zuby. Tato monstra se často nacházejí v centru cizáckých útočných formací, když cizáci zaútočí na zemi.  Trisceni jsou těžkotonážní a schopnou zbraňí,  nasazovanou Krabounskými veliteli.\"\n  STR_TRISCENE_AUTOPSY: \"Pitva triscena\"\n  STR_TRISCENE_AUTOPSY_UFOPEDIA: \"Po podrobení triscena chirurgickému noži se ukazuje, že je to prastarý tvor, vybavený kybernetickými implantáty a zbraňovými systémy. Jeho drobný mozek je doplněn malým počítačovým modulem pro ovládání veškerého vybavení. Odolná přirozená kůže a instinkty predátora obohacené přidanými zbraněmi z něj dělají smrtonosného protivníka ve všech prostředích.\"\n  STR_HALLUCINOID_UFOPEDIA: \"V hlubinách oceánů, chovají cizáci tyto mohutné pozemské tvory jako zbraně.  Nenechme se ukolébat falešným pocitem bezpečí v blízkosti tohoto neškodně vypadajícího obyvatele hlubin.  Vybaven účinnou dalekonosnou, ochromující, dusivou a šokující zbraní, je Halucinoid smrtelně nebezpečný.\"\n  STR_HALLUCINOID_AUTOPSY: \"Pitva halucinoida\"\n  STR_HALLUCINOID_AUTOPSY_UFOPEDIA: \"Hluboko pod mnoha vrstvami želatinového těla tohoto organismu je uložen výkonný chemický zmrazovač. Jeho hlavní útočná schopnost. Měkká a ohebná kůže halucinoida se zdá být citlivá na tepelné útoky. Tito mutanti se vyskytují v doprovodu svých pánů, akvatoidů.\"\n  STR_XARQUID_UFOPEDIA: \"Další modifikovaný pozemský bezobratlý. Xarkid je tvor velmi krásný, ale též značně nebezpečný. Tento rychlý plovoucí gigant skrývá devastující arzenál zbraní, zavalující inkoustový rozprašovač a proud ionizovaných částic. Při našich setkáních s tímto mocným tvorem se musíme mít na pozoru před jeho silou a jeho pomstychtivými dozorci, žábrouny.\"\n  STR_XARQUID_AUTOPSY: \"Pitva xarkida\"\n  STR_XARQUID_AUTOPSY_UFOPEDIA: \"Tento přerostlý hlavonožec byl stvořen pomocí vydatných dávek cizáckých farmak a chirurgických úprav. Kromě zprznění tvora proti přírodě mu žábrouni přidali mechanický ovládací systém, a tak z jeho původní nátury nezbylo zhola nic. Je nasazován jako biologický zbraňový systém. Xarkidova tvrdá ulita a pohyblivost z něj tvoří impozantního protivníka.\"\n  STR_ION_BEAM_ACCELERATORS_UFOPEDIA: \"Cizácké létající ponorky jsou založeny na složitých napájecích systémech, díky kterých jsou schopné dosahovat neuvěřitelných rychlostí ve vodních hlubinách. Základním kamenem jejich technologie je IONTOVÝ POHON využívající zrbit jako katalizátor. Pohon je tak schopen za sekundu protlačit stonásobek svého objemu. Takový enormní výkon cizákům umožňuje uniknout většině pozemských ponorek. Iontový propulsní systém jsme schopni replikovat pomocí akva-plastiku a zrbitových článků.\"\n  STR_MAGNETIC_NAVIGATION_UFOPEDIA: \"Tyto jednotky tvoří kulovité mnohovrstvé magnetické pole, jehož matice je promítána až do 1000m kolem ponorky. Cizáčtí navigátoři jsou přímo napojeni k těmto strojům a vycítí tak správnou cestu skrz neviditelný svět pod hladinou. Systém využívá rozhraní cizácké modifikované mozkové hmoty. Ta komunikuje bezprostředně s mozkem operátora pomocí nervového spoje.\"\n  STR_ALIEN_SUB_CONSTRUCTION_UFOPEDIA: \"Každé plavidlo má konstrukci jako chameleon. Je pečlivě modelováno podle mořských živočichů, sestaveno z akvaplastiku. Všechny ponorky fungují jako organismus: posádka s lodí tvoří harmonii. Většinu těchto systémů lze replikovat a vyvinout tak hybridní technologie, které nám umožní dosáhnout stejné technologické úrovně.\"\n  STR_ALIEN_CRYOGENICS_UFOPEDIA: \"Bezpočet cizáků, kteří jsou potají uloženi na Zemi jsou udržováni při životě kryogenicky zmražení. Všichni tvorové jsou uzavřeni do zařízení a teplota jejich těl snížena k bodu, kdy veškeré tělesné funkce ustanou. Průzkum těchto jednotek nakonec odhalil neuvěřitelné časové období po která byla těla ponechána v suspendovaném stavu. Některá přes 60 milionů let.\"\n  STR_ALIEN_CLONING_UFOPEDIA: \"Mnoho cizáků, které jsme chytili, je identických i na úrovni DNA. jsou to duplikáty ve všech směrech. Buněčné vzorky jsou vloženy do takovýchto zařízení ze zmrazených cizáckých genových bank. Některé jednotky obsahují lidi, nebo části těl. Je rovněž možné, že další využití těchto klonovacích jednotek je vytváření cizácko-lidských hybridů.\"\n  STR_ALIEN_LEARNING_ARRAYS_UFOPEDIA: \"Pomocí implantátů molekulární kontroly v lebkách cizáků dokážou tyto stroje injektovat informace přímo do mozku. Čerstvě naklonovaní cizáci jsou přiváděni k těmto zařízením, které nahrají vzpomínky rasy a veškeré vědecké a bojové informace do jejich čistých myslí.\"\n  STR_ALIEN_IMPLANTER_UFOPEDIA: \"Toto zařízení je užíváno k vybavení cizáků implantáty molekulární kontroly, oplodňování reprodukujících se ras a vkládání, či vyjímání orgánů a elektroniky z libovolného tvora. Uvažovalo se o využití procesu na uspaných pacientech, ale ti ho až příliš vnímají, ačkoliv zařízení je na lidskou anatomii velmi dobře připraveno.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"Nyní máme jistotu, proč cizáci chytají lidi. Nikoliv jako potravu, ani pro oplodnění cizáckými zárodky, ale hlavně jako základ pro různé tvory a řídící systémy. Cizácká technologie je založena na běžné mysli a sdílené inteligenci. Lidský mozek je pro tyto systémy ideální nádobou. Tkáň lidského mozku je užívána ve většině cizáckých biologických počítačových úložištích a načítacích systémech. Zbytky jsou užity jako stavební materiál a pro množení.\"\n  STR_AQUA_PLASTICS_UFOPEDIA: \"Cizácké ponorky a konstrukce využívají neuvěřitelně pevného, pružného a odolného materiálu na většinu svých částí. Akva-plastik je komplexem multipojiv a materiálů katalizovaných zrbitem. Hustá, přesto lehká, substance je pevnější než titan nebo kevlar.\"\n  STR_ZRBITE_UFOPEDIA: \"Toto je cizácká slitina, částečně ze zlata a cizáckého biomateriálu. Použije li se jako zdroj energie, malé množství vygeneruje více energie než 10krát větší atomová jednotka. Replikace tohoto materiálu je mimo naše možnosti, protože většina jeho složek je cizáckého původu.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"Cizáci útočí po celé zemi s bezcitnou účinností. Jejich zdroj nedokážeme určit. Může to být v některém oceánu tak nedosažitelně hluboko, že jeho lokalizace je pro nás nemožná? Ne všechny organismy, se kterými jsme se setkali, jsou cizácké. Některé jsou velmi staré, jiné pochází z evolučních větví, o kterých se soudilo, že jsou dávno vyhynulé. Řešíme hrozbu, která zde dřímala po milénia jako křehká simbióza lidí a cizáků. Hluboko v oceánech jsou ukryty prastaré prostory užívané pro kontakt s cizáckými vesmírnými příbuznými. Každé z těchto dvanácti míst obsahuje vyspělou cizáckou techniku - synomické zářízení. Nyní, kdy cizáci rozjeli svou válečnou mašinérii, znovuzprovozňují tato zařízení pro posílení sítě molekulární kontroly. Tato zařízení musíme zničit za každou cenu.\"\n  STR_THE_ULTIMATE_THREAT_UFOPEDIA: \"Před 68 milióny let byla vyslána k Zemi ohromná kolonizační loď ze vzdáleného cizáckého světa. Ale ve chvíli, kdy se loď přiblížila k mladičké Zemi, masivní a ničivá sluneční erupce způsobila výpadek navigačních systémů. Ochromená a selhávající gigantická masa klesala skrz stratosféru do křídového nebe. Na Zemi pak nesčetné množství živočišných druhů sledovoalo svými pohledy, jak se jejich zkáza zarývá do povrchu planety. Náraz zvedl do atmosféry obrovský oblak prachu, čímž došlo k ochlazení prostředí, a tak dominantní život, mocní dinosauři, vzali za své. Jenže 400 miliard tun lodi T'leth nebylo nárazem zničeno. Sofistikované superpočítače zahájili kryogenický spánkový cyklus tvorů, jež loď přenášela. Po uplynulých éonech počítače vzbudili skupiny cizáků, aby se pokusili o komunikaci se svými vesmírnými příbuznými. Vše bylo ale marné, protože jádro cizácké síly stále spalo.\"\n  STR_TLETH_THE_ALIEN_CITY: \"T'leth, město cizáků\"\n  STR_TLETH_THE_ALIEN_CITY_UFOPEDIA: \"T'leth, obrovská cizácká kolonizační loď leží v Sigsbee Deep, oblasti Mexického zálivu. V srdci tohoto města spočívá cizácká noční můra, tak odporná a mocná, že ani smrt se jí nezachvátí. V kovové síni leží spící forma velkého spáče, Posledního Cizáka. Výstupem T'lethu nad mořskou hladinu započne jeho oživovací cyklus, který, až bude dokončen, bude Cizák nezastavitelný. I když není při životě, ale jaksi ani mrtvý, jeho mysl řídí cizáckou armádu. Podivná technologie molekulární kontroly propojuje všechny cizáky do jediné mysli a jednu mysl ke všem cizákům. Geneticky mutované cizácké či lidské zárodky dodávají Cizákovi energii a tvoří spojení mezi vladařem a jeho poddanými. Mýtus o Posledním Cizákovi existoval v srdcích a myslích lidí po staletí. Moře vždy ukrývalo konečnou pravdu.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"VYSTŘEDIT NA POZICI (ČAS=5 Sek)\"\n  STR_CANCEL_UC: \"ZRUŠIT\"\n  STR_NONE: \"Nic\"\n  STR_UNKNOWN: \"Neznámo\"\n  STR_POOR: \"Ubohý\"\n  STR_AVERAGE: \"Průměrný\"\n  STR_GOOD: \"Dobrý\"\n  STR_EXCELLENT: \"Výborný\"\n  STR_BUILD_NEW_BASE_UC: \"POSTAVIT NOVOU ZÁKLADNU\"\n  STR_BASE_INFORMATION: \"INFORMACE O ZÁKLADNĚ\"\n  STR_EQUIP_CRAFT: \"VYBAVIT PONORKU\"\n  STR_BUILD_FACILITIES: \"VYBUDOVAT ZAŘÍZENÍ\"\n  STR_RESEARCH: \"VÝZKUM\"\n  STR_MANUFACTURE: \"VÝROBA\"\n  STR_TRANSFER_UC: \"PŘESUN\"\n  STR_PURCHASE_RECRUIT: \"NÁKUP / NÁBOR\"\n  STR_SACK: \"PROPUŠTĚNÍ\"\n  STR_SELL_SACK_UC: \"PRODEJ / PROPUŠTĚNÍ\"\n  STR_GEOSCAPE_UC: \"GLÓBUS\"\n  STR_NAME: \"Jméno\"\n  STR_AREA: \"Oblast\"\n  STR_BUILD_NEW_BASE: \"Postavit novou základnu\"\n  STR_CANCEL: \"Zrušit\"\n  STR_COST_UC: \"NÁKLADY>\"\n  STR_CONSTRUCTION_TIME_UC: \"DOBA KONSTRUKCE>\"\n  STR_DAY:\n    one: \"{N} den\"\n    few: \"{N} dny\"\n    many: \"{N} dnů\"\n    other: \"{N} dnů\"\n  STR_HOUR:\n    one: \"{N} hodina\"\n    few: \"{N} hodiny\"\n    many: \"{N} hodin\"\n    other: \"{N} hodin\"\n  STR_MAINTENANCE_UC: \"ÚDRŽBA>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Instalace\"\n  STR_CURRENT_RESEARCH: \"PROBÍHAJÍCÍ VÝZKUM\"\n  STR_SCIENTISTS_AVAILABLE: \"Vědců k dispozici>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Vědců přiřazeno>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Dostupné místo v laboratoři>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"VÝZKUMNÝ PROJEKT\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"PŘIŘAZENO VĚDCŮ\"\n  STR_PROGRESS: \"POKROK\"\n  STR_NEW_PROJECT: \"Nový projekt\"\n  STR_CANCEL_PROJECT: \"ZRUŠIT PROJEKT\"\n  STR_NEW_RESEARCH_PROJECTS: \"NOVÉ VÝZKUMNÉ PROJEKTY\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"VĚDCŮ K DISPOZICI>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"DOSTUPNÉ MÍSTO V LABORATOŘI>{ALT}{0}\"\n  STR_INCREASE: \"Zvýšit\"\n  STR_DECREASE: \"Snížit\"\n  STR_START_PROJECT: \"ZAHÁJIT PROJEKT\"\n  STR_CURRENT_PRODUCTION: \"SOUČASNÁ PRODUKCE\"\n  STR_ENGINEERS_AVAILABLE: \"Inženýrů k dispozici>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Inženýrů přiřazeno>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Dostupné místo v dílně>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Aktuální finance>{ALT}{0}\"\n  STR_ITEM: \"POLOŽKA\"\n  STR_ENGINEERS__ALLOCATED: \"Přiřazeno inženýrů\"\n  STR_UNITS_PRODUCED: \"Vyrobeno kusů\"\n  STR_TOTAL_TO_PRODUCE: \"Celkem vyrobit\"\n  STR_COST__PER__UNIT: \"Cena{NEWLINE}za{NEWLINE}kus\"\n  STR_DAYS_HOURS_LEFT: \"Dnů/Hodin zbývá\"\n  STR_NEW_PRODUCTION: \"Nová výroba\"\n  STR_PRODUCTION_ITEMS: \"Předměty k výrobě\"\n  STR_CATEGORY: \"KATEGORIE\"\n  STR_START_PRODUCTION: \"ZAHÁJIT VÝROBU\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} hodin na inženýra pro výrobu jednoho kusu\"\n  STR_COST_PER_UNIT_: \"Cena za kus>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Potřebný výrobní prostor>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"VYŽADOVÁNY SPECIÁLNÍ MATERIÁLY\"\n  STR_ITEM_REQUIRED: \"NUTNÝ PŘEDMĚT\"\n  STR_UNITS_REQUIRED: \"POŽADOVANÝCH JEDNOTEK\"\n  STR_UNITS_AVAILABLE: \"JEDNOTEK K DISPOZICI\"\n  STR_STOP_PRODUCTION: \"UKONČIT VÝROBU\"\n  STR_ENGINEERS_AVAILABLE_UC: \"INŽENÝRŮ K DISPOZICI>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"VOLNÉ MÍSTO V DÍLNĚ>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"MĚSÍČNÍ ZISK>{ALT}{0}\"\n  STR_INCREASE_UC: \"ZVÝŠIT\"\n  STR_DECREASE_UC: \"SNÍŽIT\"\n  STR_UNITS_TO_PRODUCE: \"Vyrobit kusů\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Nákup/Nábor personálů\"\n  STR_COST_OF_PURCHASES: \"Cena za nákup>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"CENA ZA KUS\"\n  STR_QUANTITY_UC: \"MNOŽSTVÍ\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"ZAMĚSTNANCŮ VOLNÝCH:ZAMĚSTNANCŮ CELKEM>\"\n  STR_SOLDIERS: \"Akvanauti\"\n  STR_SCIENTISTS: \"Vědci\"\n  STR_ENGINEERS: \"Inženýři\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"VYUŽITÝ PROSTOR:VOLNÝ PROSTOR>\"\n  STR_LIVING_QUARTERS: \"Obytné buňky\"\n  STR_STORES: \"Sklady\"\n  STR_LABORATORIES: \"Laboratoře\"\n  STR_WORK_SHOPS: \"Dílny\"\n  STR_HANGARS: \"Doky létajících ponorek\"\n  STR_SHORT_RANGE_DETECTION: \"Sonar krátkého dosahu\"\n  STR_DEFENSE_STRENGTH: \"Síla obrany\"\n  STR_TRANSFERS_UC: \"PŘESUNY\"\n  STR_TRANSFERS: \"Přesuny\"\n  STR_ARRIVAL_TIME_HOURS: \"Doba dodání (hodiny)\"\n  STR_COST_: \"Cena>{ALT}{0}\"\n  STR_AREA_: \"Oblast>{ALT}{0}\"\n  STR_BASE_NAME: \"Jméno základny?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"ZVOLTE POZICI PŘECHODOVÉ KOMORY\"\n  STR_TRANSFER: \"Přesun\"\n  STR_AMOUNT_TO_TRANSFER: \"MNOŽSTVÍ K PŘESUNU\"\n  STR_SELECT_DESTINATION_BASE: \"Zvolte cílovou základnu \"\n  STR_COST: \"Cena\"\n  STR_INTRO_1: \"Copyright 1995 MicroProse\"\n  STR_INTRO_2: \"Mars: Zánik Cydonie\"\n  STR_INTRO_3: \"Vítězoslavný X-Com zničil samotné jádro Cizácké válečné mašinérie, a odstartoval k domovu. Jenomže ve zpustošené marťanské základně nezůstali jen mrtví.\"\n  STR_INTRO_4: \"Mohutný tachyonový paprsek vychází z trosek nervového centra Cydonie, řítící se vzduchoprázdnem. Jeho cíl..........\"\n  STR_INTRO_5: \"Země.\"\n  STR_INTRO_6: \"Hluboko v oceánu paprsek aktivuje dávno uspaný receptor. Rozsáhlé spící počítače začínají konat. V hlubinách, daleko z dohledu lidí, v rozlehlých sálech plných spících cizáků začíná jejich oživovací proces.\"\n  STR_INTRO_7: \"2040: Země nic netuší. Hrůzy z cizácké války jsou dávno zapomenuty. Ale na ztracených a skrytých místech oceánu jsou cizácké davy připraveny - připraveny vymést lidstvo a ovládnout svět.\"\n  STR_INTRO_8: \"Cizácké akce proti lidstvu: Vyhledávání druhů pro jejich zvrácené experimenty, razie na pozemské cenné nerosty a zdroje, plenění moří. Po té se cizáci zaměří více nad hladinu. \"\n  STR_INTRO_9: \"Mocné létající ponorky podivných konstrukcí plynou v oceánech - vyhlížející, hledající, lovící........\"\n  STR_INTRO_10: \"Jakmile najdou kořist, zaútočí.\"\n  STR_INTRO_11: \"Proti bezbrannému světu jsou používány nové hrozné zbraně. Jsme nyní naprosto vydáni na milost cizácké hrozbě.{NEWLINE}Pouze jediná organizace nás může zachránit. Ale k té už jsme se dávno obrátili zády......\"\n  STR_INTRO_12: \"Experimentální podmořské zařízení X-COM\"\n  STR_INTRO_13: \"'Mayday! Mayday!' 'Zde transatlantická loď Hyperion'. ' Jsme pod útokem'.\\n'Mayday! Mayd............'\"\n  STR_INTRO_14: \"'Rozkaz pro dok létající ponorky jedna: Otevřete vodní vrata', 'vypusťte Barracudu nula jedna. Nastala situace útoku cizáků - červený poplach'.{NEWLINE}'Opakuji: červený poplach'\"\n  STR_INTRO_15: \"Cizáci jsou krutě učinní...\"\n  STR_INTRO_16: \"....a neomylně přesní.\"\n  STR_INTRO_17: \"'Barracuda nula jedna základně' - 'přibližujeme se k tomu, co zbylo z Hyperionu'.\"\n  STR_INTRO_18: \"'Snižujeme rychlost'.{NEWLINE}'Dva metry'{NEWLINE}'Jeden metr'{NEWLINE}'Všichni akvanauti, připravte se na okamžitý výstup.\"\n  STR_INTRO_19: \".....'Přechodová komora čistá' ... 'přibližujeme se k vraku.'{NEWLINE}'Proboha!'{NEWLINE}'Vidíte z mé kamery ty postavy?'\"\n  STR_GAMEOVER_1: \"Selhali jsme. Cizáci zlikvidovali naši poslední naději na záchranu.{NEWLINE} X-Com je zničen a Země leží u nohou prastarého nepřítele.\"\n  STR_GAMEOVER_2: \"T'leth se s burácením vznesl do stratosféry a a začal se pohybovat po tváři světa rozdávající smrt a sklízející poslední zbytky lidské rasy. Hluboko v jeho střevech se sama vzbouzí vražedná cizácká mysl.\"\n  STR_GAMEOVER_3: \"V hlavních městech všech národů jsou navrhovány beznadějné plány. Vše je k ničemu. Bez technologií poskytovaných výzkumem X-Com jsou naše zbraně neúčinné.\"\n  STR_GAMEOVER_4: \"Cizáci založili základny na polárních čepičkách Země a začali tavit led. Svět se brzy stane jedním velkým oceánem. Zbytky lidské rasy jsou shromážděny a využity na odporné chovatelské experimenty s bůhví jakými cizáckými záměry. Nebe potemnělo a na všechny krajiny Země dopadl hladomor.\"\n  STR_GAMEOVER_5: \"Nejsme schopni se postavit na odpor vůči novému světovému řádu. Ti, kteří proti němu povstali, dospěli ke spalujícímu osudu neznámými cizáckými zbraněmi. Ani ostatní nečekají žádné světlé zítřky. Matka Země se stane světem cizáků a lidstvo bude ztraceno pod jejich hemžící hrůzou.\"\n  STR_OUTRO_1: \"Hrobka je zpustošena a zdecimována. Jen z rakve uprostřed se ozývá bublavý řev.{NEWLINE}Vy hlupáci! Všichni zemřete....................\"\n  STR_OUTRO_2: \"...............živí se odsud nedostanete.\"\n  STR_OUTRO_3: \"Obrovská exploze vyšlehla z hrobky a šíří se městem. Trosky a kouř víří v prostoru. Plány Vetřelců jsou zmařeny........\"\n  STR_OUTRO_4: \"Obrovská konstrukce T'lethu se začíná bortit. Plameny a dým vyrážejí z jeho blyštivých spirál a adamantiových sálů.\"\n  STR_OUTRO_5: \"Ohromná cizácká pevnost se hroutí do moře. Skřípot týraného kovu a duší naplnil vzduch.  Velký snílek už nikdy nebude snít své sny o vládě nad planetou.\"\n  STR_OUTRO_6: \"Poslední uširvoucí zvukový ráz a T'leth se roztrhl na kusy.{NEWLINE}Cizácká hrozba je zažehnána, Země je očištěna..................\"\n  STR_OUTRO_7: \"Ospalá modrozelená planeta ve vzdáleném koutu galaxie.\"\n  STR_OUTRO_8: \"Na čas znovu bezpečné místo k žití.\"\n  STR_OUTRO_9: \"Cizácká hrozba je už dlouho přemožena.\"\n  STR_OUTRO_10: \"Obrovské metropole a města jsou zaplněna miliardami lidí.\"\n  STR_OUTRO_11: \"Hrdinské činy členů X-COM ve válce s cizáky se staly báchorkami pro děti.\"\n  STR_OUTRO_12: \"Ale legendy vždy rády ukrývaly zrnka pravdy........\"\n  STR_RISE_1: \"T'leth, mnohokrát zmiňován v mnoha legendách mnoha národů.\"\n  STR_RISE_2: \"S drásavým jekotem, který dolehl do všech zákoutí na zemi se T'leth odlepil od mořského dna.\"\n  STR_RISE_3: \"Kolosální masiv se vzedmul z vod Mexického zálivu.\"\n  STR_RISE_4: \"400 miliard tun cizáckého kovu, blyštivé cizácké město, ve kterém spočívá spící tělo Posledního cizáka. Po 65 miliónech let uvěznění na Zemi se tento vesmírný zlobůh probouzí.\"\n  STR_RISE_5: \"Moře bouří a vře, jak se hrobka Velkého spáče vynořuje na světlo................\"\n  STR_RISE_6: \"........na světlo, které nebude svítit moc dlouho, pokud X-Com včas nezničí tento cizácký válečný stroj.\"\n  STR_YOU_HAVE_FAILED: \"Nepodařilo se ti zastavit cizáckou válečnou mašinérii. Přispívající organizace, zklamané tvou neschopností, se postupně snaží vyjednat mírové vztahy s cizáky. Ti však mají zcela odlišné plány a brzy si celý svět uvědomuje, jaká je pravda...\"\n  STR_TOTAL_UC: \"CELKEM\"\n  STR_INCOME: \"Příjmy\"\n  STR_EXPENDITURE: \"Výdaje\"\n  STR_MAINTENANCE: \"Údržba\"\n  STR_BALANCE: \"Zůstatek\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"Aktivita cizáků v mořích\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"Aktivita cizaků v oblastech\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"Aktivita X-Com v mořích\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"Aktivita X-Com v oblastech\"\n  STR_FINANCE: \"Finance\"\n  STR_DATE_FIRST: \"{0}.\"\n  STR_DATE_SECOND: \"{0}.\"\n  STR_DATE_THIRD: \"{0}.\"\n  STR_DATE_FOURTH: \"{0}.\"\n  STR_FINANCE_THOUSANDS: \"$1000\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Nedostatek speciálních materiálů k výrobě{NEWLINE}{0}{NEWLINE}v{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Nedostatek peněz k výrobě{NEWLINE}{0}{NEWLINE}v{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"Výroba{NEWLINE}{0}{NEWLINE}v{NEWLINE}{1}{NEWLINE}je dokončena\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"V základně{NEWLINE}{1}{NEWLINE} byla dokončena stavba:{NEWLINE}{0}\"\n  STR_OK_5_SECONDS: \"OK - 5 sek\"\n  STR_RESEARCH_COMPLETED: \"Výzkum dokončen\"\n  STR_VIEW_REPORTS: \"ČÍST VÝSLEDKY\"\n  STR_WE_CAN_NOW_RESEARCH: \"Nyní lze zkoumat\"\n  STR_WE_CAN_NOW_PRODUCE: \"Nyní můžeme vyrábět\"\n  STR_SUNDAY: \"Neděle\"\n  STR_MONDAY: \"Pondělí\"\n  STR_TUESDAY: \"ÚTERÝ\"\n  STR_WEDNESDAY: \"STŘEDA\"\n  STR_THURSDAY: \"ČTVRTEK\"\n  STR_FRIDAY: \"PÁTEK\"\n  STR_SATURDAY: \"SOBOTA\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Schází {0} pro doplnění paliva stroje {1} v {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Nedosatatek {0} na přezbrojení {1} na {2}\"\n  STR_UFO_IS_NOT_RECOVERED: \"CIZÁCKÁ PONORKA nebyla zajištěna\"\n  STR_UFO_IS_RECOVERED: \"CIZÁCKÁ PONORKA byla zajištěna\"\n  STR_CRAFT_IS_LOST: \"Létající ponorka je ztracena\"\n  STR_TERROR_CONTINUES: \"Cizácká aktivita pokračuje\"\n  STR_ALIENS_DEFEATED: \"Cizáci byli poraženi\"\n  STR_BASE_IS_LOST: \"Základna je ztracena\"\n  STR_BASE_IS_SAVED: \"Základna je zachráněna\"\n  STR_ALIEN_BASE_STILL_INTACT: \"Cizácká kolonie zůstala nedotčená\"\n  STR_ALIEN_BASE_DESTROYED: \"Cizácká kolonie zničena\"\n  STR_ALIENS_KILLED: \"CIZÁKŮ ZABITO\"\n  STR_ALIEN_CORPSES_RECOVERED: \"CIZÁCKÝCH MRTVOL ZÍSKÁNO\"\n  STR_LIVE_ALIENS_RECOVERED: \"ŽIVÝCH CIZÁKŮ ZÍSKÁNO\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"CIZÁCKÝCH ARTEFAKTŮ ZÍSKÁNO\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"ŘÍZENÍ CIZÁCKÉ KOLONIE ZNIČENO\"\n  STR_ALIEN_SYNOMIUM_DEVICE_DESTROYED: \"CIZÁCKÉ SYNOMICKÉ ZAŘÍZENÍ ZNIČENO\"\n  STR_ALIEN_SYNOMIUM_DEVICE_FAILED: \"SYNOMICKÉ ZAŘÍZENÍ NEBYLO ZNIČENO\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"CIVILISTŮ ZABITO CIZÁKY\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"CIVILISTŮ ZABITO PŘÍSLUŠNÍKY X-COM\"\n  STR_CIVILIANS_SAVED: \"CIVILISTŮ ZACHRÁNĚNO\"\n  STR_XCOM_OPERATIVES_KILLED: \"PŘÍSLUŠNÍKŮ X-COM ZABITO\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"PŘÍSLUŠNÍKŮ X-COM ZTRACENO V AKCI\"\n  STR_TANKS_DESTROYED: \"ZBRAŇOVÝCH SYSTÉMŮ X-COM ZNIČENO\"\n  STR_XCOM_CRAFT_LOST: \"PONOREK X-COM ZTRACENO\"\n  STR_UFO_RECOVERY: \"VÝSLEDEK PRŮZKUMU PONORKY\"\n  STR_ALIEN_BASE_RECOVERY: \"VÝSLEDEK PRŮZKUMU KOLONIE\"\n  STR_BASE_UNDER_ATTACK: \"{0} je napadena!\"\n  STR_BASE_DEFENSES_INITIATED: \"OBRANA ZÁKLADNY ZAHÁJENA\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"ŠTÍTY ODPUZUJÍ CIZÁCKOU PONORKU!\"\n  STR_FIRING: \"STŘÍLÍ\"\n  STR_HIT: \"ZÁSAH!\"\n  STR_UFO_DESTROYED: \"CIZÁCKÁ PONORKA ZNIČENA!\"\n  STR_MISSED: \"MIMO!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Prodat věci/propustit personál\"\n  STR_VALUE_OF_SALES: \"HODNOTA PRODEJE> {ALT}{0}\"\n  STR_FUNDS: \"FINANCE> {ALT}{0}\"\n  STR_SELL_SACK: \"Prodat/propustit\"\n  STR_VALUE: \"Hodnota\"\n  STR_CRAFT_: \"LÉTAJÍCÍ PONORKA> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"PRŮZKUM POTOPENÉ PONORKY\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"MAXIMÁLNÍ OPATRNOST - Uvnitř a v okolí ponorky se pohybují cizáci. Mise bude dokočena, budou-li všechny nepřátelské jednotky zneškodněny nebo zničeny. Poté bude zahájeno zajišťování zbytků cizácké ponorky, techniky, mrtvol a vybavení. Chcete-li přerušit misi, navraťte se s akvanauty zpět do ponorky a klikněte na ikonu 'Zrušit misi'.\"\n  STR_UFO_GROUND_ASSAULT: \"ÚTOK NA CIZÁCKOU PONORKU\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"Prozkoumejte místo přistání a pokuste se získat přístup do cizácké ponorky. Mise bude úspěšná, budou-li všechny cizácké jednotky zneškodněny nebo zlikvidovány. Poté může být zahájeno zkoumání ponorky, pozůstatků a mrtvol. Chcete-li přerušit misi, navraťte se s akvanauty do ponorky a klikněte na ikonu 'Zrušit misi'.\"\n  STR_BASE_DEFENSE: \"OBRANA ZÁKLADNY\"\n  STR_BASE_UC_: \"ZÁKLADNA> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"Cizácká loď přistála nedaleko. Vaše základna je ve vážném nebezpečí. Všechen nevojenský personál a vybavení bylo evakuováno obvyklým postupem. Cizáci vstoupí do základny skrz doky nebo vstupní komorou. Zachraňte základnu a její důležité vybavení za každou cenu - je to boj na život a na smrt. Kliknutím na ikonu 'Zrušit misi' vzdáte boj a ztratíte základnu.\"\n  STR_ALIEN_COLONY_ATTACK_MISSION: \"ÚTOK NA CIZÁCKOU KOLONII\"\n  STR_ALIEN_BASE_ASSAULT: \"CIZÁCKÁ KOLONIE ČÁST PRVNÍ\"\n  STR_ALIEN_COLONY_P1_BRIEFING: \"Tato mise je přepadením cizácké kolonie a skládá se ze dvou částí. V první dostaňte akvanauty k hlavnímu vchodu do podzemí a klikněte na ikonu 'Zrušit misi', nebo zlikvidujte všechny cizáky. Všechno vybavení, zanechané na mořském dně zde však zůstane, až do rozhodnutí druhé části. Chcete-li přerušit misi, navraťte se s akvanauty zpět do ponorky a klikněte na ikonu 'Zrušit misi'.\"\n  STR_ALIEN_COLONY_P2: \"CIZÁCKÁ KOLONIE ČÁST DRUHÁ\"\n  STR_ALIEN_COLONY_P2_BRIEFING: \"Opustili jste první úroveň a pronikli do jádra kolonie. Nyní je vaším úkolem zničení Synomického zařízení řídícího centra, nebo likvidace všech cizáků. Pro přerušení mise rozestavte akvanauty na zelená startovní pole a klikněte na ikonu 'Zrušit misi'. Všechno provozuschopné vybavení se vrátí zpět na základnu.\"\n  STR_ALIENS_LAUNCH_PORT_TERROR: \"CIZÁCI ÚTOČÍ{NEWLINE}NA PŘÍSTAV\"\n  STR_PORT_TERROR: \"CIZÁCI ÚTOČÍ NA PŘÍSTAV\"\n  STR_PORT_TERROR_BRIEFING: \"Cizáci zaútočili na souši. Přístav a jeho civilní obyvatelstvo jsou v bezprostředním ohrožení. Vaše jednotky musí zneškodnit všechny cizáky a ochránit co nejvíce nevinných obětí cizáckého vpádu. Pro přerušení mise shromážděte akvanauty do ponorky a klikněte na ikonu 'Zrušit misi'.\"\n  STR_ALIENS_LAUNCH_ISLAND_TERROR: \"CIZÁCI ÚTOČÍ{NEWLINE}NA OSTROV\"\n  STR_ISLAND_TERROR: \"CIZÁCI ÚTOČÍ NA OSTROV\"\n  STR_ISLAND_TERROR_BRIEFING: \"Cizáci zaútočili na území na souši. Přístav a jeho civilní obyvatelstvo jsou v ohrožení. Vaše jednotky musí zneškodnit všechny cizáky a ochránit co nejvíce nevinných civilistů před tímto cizáckým vpádem. Pro přerušení shromážděte akvanauty do ponorky a klikněte na ikonu 'Zrušit misi'.\"\n  STR_ALIENS_ATTACK_SHIPPING_ROUTE: \"CIZÁCI ÚTOČÍ{NEWLINE}NA NÁMOŘNÍ LOĎ\"\n  STR_CARGO_SHIP_P1: \"NÁKLADNÍ LOĎ ČÁST PRVNÍ\"\n  STR_CARGO_SHIP_P2: \"NÁKLADNÍ LOĎ ČÁST DRUHÁ\"\n  STR_CRUISE_SHIP_P1: \"VÝLETNÍ LOĎ ČÁST PRVNÍ\"\n  STR_CRUISE_SHIP_P2: \"VÝLETNÍ LOĎ ČÁST DRUHÁ\"\n  STR_SHIP_RESCUE_MISSION: \"ZÁCHRANA NÁMOŘNÍ LODĚ\"\n  STR_SHIP_RESCUE_P1_BRIEFING: \"Úkolem této mise je vyčištění lodi od havěti. Zlikvidujte všechny cizáky na lodi a zachraňte životy osob na palubě. Cizáci jsou rozmístěni na palubách i v podpalubí. Vyčistěte paluby, abyste mohli pokračovat v podpalubí. Chcete-li přerušit misi, navraťte se s akvanauty zpět do ponorky a klikněte na ikonu 'Zrušit misi'.\"\n  STR_SHIP_RESCUE_P2_BRIEFING: \"Horní paluby jsou vyčištěny, pokračujete v podpalubí. Použitím nákladního výtahu, jste sestoupili dovnitř. Vaše posádka musí zlikvidovat všechny cizáky. Pro přerušení shromážděte akvanauty do oblasti výtahu a klikněte na ikonu 'Zrušit misi'.\"\n  STR_ALIEN_ACTIVITY_DETECTED: \"ZJIŠTĚNA CIZÁCKÁ AKTIVITA\"\n  STR_ALIEN_CONTACT_SITE_MISSION: \"ÚTOK NA CIZÁCKOU KOMUNIKAČNÍ ZÁKLADNU\"\n  STR_ARTIFACT_SITE_P1: \"KOMUNIKAČNÍ ZÁKLADNA ČÁST PRVNÍ\"\n  STR_ARTIFACT_SITE_P1_BRIEFING: \"Tato mise je útokem na čerstvě vybudovanou cizáckou komunikační základnu. Skládá se ze dvou úrovní: Mořského dna s cizáckými pyramidami a skrytého podzemního komplexu. Dojděte se všemi akvanauty na žlutá pole vchodu do komplexu a klikněte na ikonu 'Zrušit misi', anebo zlikvidujte všechny cizáky, pro přechod do druhé části. Chcete-li přerušit misi, navraťte se s akvanauty zpět do ponorky a klikněte na ikonu 'Zrušit misi'.\"\n  STR_ARTIFACT_SITE_P2: \"KOMUNIKAČNÍ ZÁKLADNA ČÁST DRUHÁ\"\n  STR_ARTIFACT_SITE_P2_BRIEFING: \"Prozkoumali jste cizácké struktury a vnikli do podzemního komplexu. Probijte se do srdce cizácké základny a zničte Synomické zařízení Molekulární kontroly, což je hlavním cílem mise. Pro zrušení shromážděte všechny akvanauty na vstupních polích a klikněte na ikonu 'Zrušit misi'.\"\n  STR_SIGSBEE_DEEP_MISSION: \"MISE V HLUBINĚ SIGSBEE{NEWLINE}CIZÁCKÉ MĚSTO PRVNÍ ÚROVEŇ\"\n  STR_TLETH_P1_BRIEFING: \"Vstoupili jste do neznáma, kde na vás může čekat cokoliv. V této a dalších dvou částech cizáckého města, musí vaše jednotky najít východ a bezpečně se k němu dopravit, aby mohly pokračovat. Shromážděte všechny akvanauty v prostoru východu a klikněte na ikonu 'Zrušit misi'. V jiném případě ikona přeruší misi.\"\n  STR_TLETH_ATTACK_MISSION: \"ÚTOK NA T'LETH{NEWLINE}CIZÁCKÉ MĚSTO DRUHÁ ÚROVEŇ\"\n  STR_TLETH_P2_BRIEFING: \"Dále do neznáma, kde na nás může čekat cokoliv. Toto je další část cizáckého města. Vaše jednotky musí opět najít a dorazit k východu aby mohly přejít do další části. Shromážděte všechny akvanauty v prostoru východu a klikněte na ikonu 'Zrušit misi'. V jiném případě ikona přeruší misi.\"\n  STR_FINAL_TLETH_MISSION: \"ZÁVĚREČNÝ ÚTOK NA T'LETH{NEWLINE}CIZÁCKÉ MĚSTO TŘETÍ ÚROVEŇ\"\n  STR_TLETH_P3_BRIEFING: \"Konec je již na dohled. Nyní je třeba najít kryptu Posledního cizáka. Zničte 8 napáječů vyživujících sarkofág. Cizácká hrozba tím bude zničena. Nevzdávejte se! Přerušením mise byste vše ztratili.\"\n  STR_TLETH_P1: \"CIZÁCKÉ MĚSTO PRVNÍ ÚROVEŇ\"\n  STR_TLETH_P2: \"CIZÁCKÉ MĚSTO DRUHÁ ÚROVEŇ\"\n  STR_TLETH_P3: \"CIZÁCKÉ MĚSTO TŘETÍ ÚROVEŇ\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"ŽÁDNÝ VOLNÝ DOK PRO VÝROBU PONORKY!{SMALLLINE}Na cílové základně není dostatek doků. Vybudujte nový dok, nebo přesuňte ponorku na jinou základnu.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"ŽÁDNÝ VOLNÝ DOK PRO NÁKUP!{SMALLLINE}Každá létající ponorka umístěná na základně, přesouvaná jinam, objednaná nebo vyráběná vyžaduje svůj dok. Vybudujte nový dok, nebo přesuňte ponorku na jinou základnu.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"ŽÁDNÝ VOLNÝ DOK PRO PŘESUN!{SMALLINE}Každá ponorka umístěná na základně, přesouvaná jinam, objednaná nebo vyráběná vyžaduje svůj dok. Vybudujte nový dok, nebo přesuňte ponorku na jinou základnu.\"\n  STR_CANNOT_BUILD_HERE: \"ZDE NELZE STAVĚT!{SMALLLINE}Můžete stavět jen vedle již hotových staveb.\"\n  STR_NO_FREE_ACCOMODATION: \"ŽÁDNÉ VOLNÉ UBYTOVÁNÍ!{SMALLLINE}Cílová základna již nemá dost místa v ubikacích.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"NEDOSTATEK PRACOVNÍHO PROSTORU!{SMALLLINE}Vybudujte nové dílny, nebo omezte práci na jiných projektech.\"\n  STR_NOT_ENOUGH_MONEY: \"NEDOSTATEK PENĚZ!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"NEDOSTATEK SKLADOVACÍHO PROSTORU!{SMALLLINE}Vybudujte nové sklady, nebo přesuňte část zásob na jinou základnu.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"NEDOSTATEK UBYTOVACÍCH KAPACIT!{SMALLLINE}Vybudujte nové ubikace, nebo přesuňte část personálu na jinou základnu.\"\n  STR_LAUNCH_INTERCEPTION: \"ZAHÁJIT PRONÁSLEDOVÁNÍ\"\n  STR_CRAFT: \"STROJ\"\n  STR_STATUS: \"STAV\"\n  STR_BASE: \"ZÁKLADNA\"\n  STR_READY: \"PŘIPRAVEN\"\n  STR_OUT: \"PRYČ\"\n  STR_REPAIRS: \"OPRAVOVÁN\"\n  STR_REFUELLING: \"TANKUJE\"\n  STR_REARMING: \"PŘEZBROJOVÁN\"\n  STR_TARGET: \"CÍL: {0}\"\n  STR_WAY_POINT: \"VYTYČENÝ BOD\"\n  STR_ARE_YOU_SURE_CYDONIA: \"Jste opravdu rozhodnuti poslat tuto ponorku na misi do T'lethu?\"\n  STR_YES: \"ANO\"\n  STR_NO: \"NE\"\n  STR_SELECT_DESTINATION: \"VYBERTE CÍL\"\n  STR_CYDONIA: \"T'LETH\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"VYBERTE MÍSTO PRO NOVOU ZÁKLADNU\"\n  STR_RETURN_TO_BASE: \"NÁVRAT NA ZÁKLADNU\"\n  STR_SELECT_NEW_TARGET: \"URČETE NOVÝ CÍL\"\n  STR_PATROL: \"HLÍDKOVAT\"\n  STR_STATUS_: \"STAV>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"POŠKOZEN - VRACÍ SE NA ZÁKLADNU\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"MÁLO PALIVA - VRACÍ SE NA ZÁKLADNU\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"MISE UKONČENA - VRACÍ SE NA ZÁKLADNU\"\n  STR_PATROLLING: \"HLÍDKUJE\"\n  STR_TAILING_UFO: \"SLEDUJE CIZÁCKOU PONORKU\"\n  STR_INTERCEPTING_UFO: \"STÍHÁ CIZÁCKOU PONORKU-{0}\"\n  STR_RETURNING_TO_BASE: \"VRACÍ SE NA ZÁKLADNU\"\n  STR_DESTINATION_UC_: \"CÍL: {0}\"\n  STR_BASE_UC: \"ZÁKLADNA>{ALT}{0}\"\n  STR_SPEED_: \"RYCHLOST>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"MAX. RYCHLOST>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"HLOUBKA>{ALT}{0}\"\n  STR_AIRBORNE: \"VE VZDUCHU\"\n  STR_VERY_LOW: \"MĚLKO\"\n  STR_LOW_UC: \"NORMÁLNÍ\"\n  STR_HIGH_UC: \"HLUBOKO\"\n  STR_VERY_HIGH: \"VELMI HLUBOKO\"\n  STR_FUEL: \"PALIVO>{ALT}{0}\"\n  STR_WEAPON_ONE: \"ZBRAŇ-1>{ALT}{0}\"\n  STR_NONE_UC: \"ŽÁDNÁ\"\n  STR_ROUNDS_: \"VÝSTŘELŮ>{ALT}{0}\"\n  STR_WEAPON_TWO: \"ZBRAŇ-2>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"LÉTAJÍCÍ PONORKA\"\n  STR_BASE_: \"Základna>{0}\"\n  STR_NAME_UC: \"JMÉNO\"\n  STR_AMMO_: \"MUNICE>{ALT}{0}\"\n  STR_CREW: \"POSÁDKA\"\n  STR_EQUIPMENT_UC: \"VYBAVENÍ\"\n  STR_ARMOR: \"ZBROJ\"\n  STR_MAX: \"MAX>{ALT}{0}\"\n  STR_ROOKIE: \"Námořník\"\n  STR_SQUADDIE: \"Zkušený námořník\"\n  STR_SERGEANT: \"Podporučík\"\n  STR_CAPTAIN: \"Poručík\"\n  STR_COLONEL: \"Velitel\"\n  STR_COMMANDER: \"Kapitán\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Určete posádku pro {0}\"\n  STR_SORT_BY: \"ŘADIT DLE...\"\n  STR_ORIGINAL_ORDER: \"PŮVODNÍ ŘAZENÍ\"\n  STR_MISSIONS2: \"MISE\"\n  STR_KILLS2: \"ZABITÍ\"\n  STR_WOUND_RECOVERY2: \"DOBA LÉČENÍ\"\n  STR_SPACE_AVAILABLE: \"VOLNÝ PROSTOR>{ALT}{0}\"\n  STR_SPACE_USED: \"VYUŽITÝ PROSTOR>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"VYUŽITÝ PROSTOR\"\n  STR_RANK: \"HODNOST\"\n  STR_WOUNDED: \"ZRANĚNÍ\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Vybavení pro {0}\"\n  STR_DEFENSE_VALUE: \"Úroveň obrany\"\n  STR_HIT_RATIO: \"Přesnost\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}je připraven{NEWLINE}k přistání poblíž{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"Zahájit misi?\"\n  STR_SELECT_ARMAMENT: \"Zvolte výzbroj\"\n  STR_AMMUNITION_AVAILABLE: \"MUNICE K DISPOZICI\"\n  STR_ARMAMENT: \"VÝZBROJ\"\n  STR_NOT_AVAILABLE: \"-\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"VYBERTE ZBROJ PRO{NEWLINE}{ALT}{0}\"\n  STR_TYPE: \"TYP\"\n  STR_PLASTIC_AQUA_ARMOR_UC: \"ZBROJ Z AKVAPLASTIKU\"\n  STR_ION_ARMOR_UC: \"IONTOVÁ ZBROJ\"\n  STR_MAGNETIC_ION_ARMOR_UC: \"MAGNETO-IONTOVÁ ZBROJ\"\n  STR_PLASTIC_AQUA_ARMOR_UFOPEDIA: \"Tato zbroj využívá nově objevený cizácký materiál, Akvaplastik. Zvyšuje tak akvanautovy šance v boji proti nepřátelským vetřelcům.\"\n  STR_ION_ARMOR_UFOPEDIA: \"Nová a silná ochrana akvanautů. Tato zbroj je napájena iontovým zdrojem, a znásobuje tak sílu a rychlost svého nositele. V současnosti nabízí nejlepší možnou ochranu pro bojové oddíly.\"\n  STR_MAGNETIC_ION_ARMOR_UFOPEDIA: \"Vylepšení iontové zbroje. Doplněním technologiemi magnetického pole, získává ve vodním prostředí maximální volnost pohybu všemi směry.\"\n  STR_SELECT_ARMOR: \"Vyberte zbroj\"\n  STR_NORTH: \"SEVER\"\n  STR_NORTH_EAST: \"SEVEROVÝCHOD\"\n  STR_EAST: \"VÝCHOD\"\n  STR_SOUTH_EAST: \"JIHOVÝCHOD\"\n  STR_SOUTH: \"JIH\"\n  STR_SOUTH_WEST: \"JIHOZÁPAD\"\n  STR_WEST: \"ZÁPAD\"\n  STR_NORTH_WEST: \"SEVEROZÁPAD\"\n  STR_SELECT_ACTION: \"VYBERTE AKCI\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"POKRAČOVAT VE STÍHÁNÍ\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"SLEDOVAT BEZ ÚTOČENÍ\"\n  STR_VERY_LARGE: \"VELMI VELKÁ\"\n  STR_LARGE: \"VELKÁ\"\n  STR_MEDIUM_UC: \"STŘEDNÍ\"\n  STR_SMALL: \"MALÁ\"\n  STR_VERY_SMALL: \"VELMI MALÁ\"\n  STR_GROUNDED: \"NA DNĚ\"\n  STR_DETECTED: \"Zjištěno\"\n  STR_SIZE_UC: \"VELIKOST\"\n  STR_ALTITUDE: \"HLOUBKA\"\n  STR_HEADING: \"SMĚR\"\n  STR_SPEED: \"RYCHLOST\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"VYSTŘEDIT NA PONORKU-ČAS=5s\"\n  STR_TRACKING_LOST: \"STOPA ZTRACENA\"\n  STR_REDIRECT_CRAFT: \"PŘESMĚROVAT STROJ\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"NA POSLEDNÍ ZNÁMOU POZICI PONORKY\"\n  STR_UFO_: \"CIZÁCKÁ PONORKA-{0}\"\n  STR_ALIEN_BASE_: \"CIZÁCKÁ KOLONIE-{0}\"\n  STR_CRASH_SITE_: \"MÍSTO HAVÁRIE-{0}\"\n  STR_LANDING_SITE_: \"MÍSTO PŘISTÁNÍ-{0}\"\n  STR_WAY_POINT_: \"URČENÝ BOD-{0}\"\n  STR_TERROR_SITE: \"MÍSTO TERORU-{0}\"\n  STR_ARTIFACT_SITE: \"MÍSTO CIZÁCKÉ AKTIVITY-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}dosáhla{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"Zahájila hlídku\"\n  STR_ALIEN_ORIGINS: \"Cizácký původ\"\n  STR_THE_ULTIMATE_THREAT: \"Krajní ohrožení\"\n  STR_TLETH_ALIEN_CITY: \"T'leth, město cizáků\"\n  STR_UFOPAEDIA: \"UFOpedie\"\n  STR_XCOM_CRAFT_ARMAMENT: \"STROJE A ZBRANĚ X-COM\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"PONORNÉ ZBRAŇOVÉ SYSTÉMY\"\n  STR_WEAPONS_AND_EQUIPMENT: \"ZÁKLADNÍ VYBAVENÍ\"\n  STR_ALIEN_ARTIFACTS: \"PODVODNÍ ARTEFAKTY\"\n  STR_BASE_FACILITIES: \"STAVBY X-COM\"\n  STR_ALIEN_LIFE_FORMS: \"CIZÁČTÍ TVOROVÉ\"\n  STR_ALIEN_RESEARCH_UC: \"CIZÁCKÁ TECHNOLOGIE\"\n  STR_UFO_COMPONENTS: \"NOVÉ PODVODNÍ TECHNOLOGIE\"\n  STR_UFOS: \"CIZÁCKÉ PONORKY\"\n  STR_SELECT_ITEM: \"VYBERTE POLOŽKU\"\n  STR_ACCELERATION: \"ZRYCHLENÍ>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"KAPACITA PALIVA>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"NOSIČE ZBRANÍ>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"ODOLNOST>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"PŘEPRAVNÍ KAPACITA>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"KAPACITA PRO PZS>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Síla\"\n  STR_RANGE: \"Dosah\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Přesnost\"\n  STR_RE_LOAD_TIME: \"Znovunabití\"\n  STR_SECONDS: \"{0}s\"\n  STR_DAMAGE_ARMOR_PIERCING: \"PRŮRAZNÝ\"\n  STR_DAMAGE_INCENDIARY: \"FOSFOROVÝ\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"EXPLOZIVNÍ\"\n  STR_DAMAGE_LASER_BEAM: \"MAGNETICKÝ PAPRSEK\"\n  STR_DAMAGE_PLASMA_BEAM: \"SONICKÝ PAPRSEK\"\n  STR_DAMAGE_STUN: \"OCHROMENÍ\"\n  STR_DAMAGE_MELEE: \"ZBLÍZKA\"\n  STR_DAMAGE_ACID: \"KYSELINA\"\n  STR_DAMAGE_SMOKE: \"KOUŘ\"\n  STR_SHOT_TYPE: \"TYP\"\n  STR_ACCURACY_UC: \"PŘESNONST\"\n  STR_TIME_UNIT_COST: \"ČAS\"\n  STR_DAMAGE_UC: \"SÍLA\"\n  STR_AMMO: \"MUNICE\"\n  STR_SHOT_TYPE_AUTO: \"Automat\"\n  STR_SHOT_TYPE_SNAP: \"Od boku\"\n  STR_SHOT_TYPE_AIMED: \"Mířená\"\n  STR_CONSTRUCTION_TIME: \"Doba výstavby\"\n  STR_CONSTRUCTION_COST: \"Náklady na výstavbu\"\n  STR_MAINTENANCE_COST: \"Náklady na údržbu\"\n  STR_LOW: \"Nízký\"\n  STR_MEDIUM: \"Střední\"\n  STR_HIGH: \"Vysoký\"\n  STR_CRAFT_WEAPON: \"Ponorková zbraň\"\n  STR_CRAFT_AMMUNITION: \"Ponorková munice\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Težký zbraňový systém\"\n  STR_WEAPON: \"Zbraň\"\n  STR_AMMUNITION: \"Munice\"\n  STR_EQUIPMENT: \"Vybavení\"\n  STR_ALIEN_CORPSE: \"Mrtvola cizáka\"\n  STR_UFO_COMPONENT: \"Součást cizácké ponorky\"\n  STR_PERSONAL_ARMOR: \"Osobní zbroj\"\n  STR_RAW_MATERIALS: \"Suroviny\"\n  STR_HWP_SOLID_HARPOON_BOLTS: \"Těžké harpunové hroty\"\n  STR_ALIEN: \"Cizák\"\n  STR_AQUATOID: \"Akvatoid\"\n  STR_GILLMAN: \"Žábroun\"\n  STR_LOBSTERMAN: \"Kraboun\"\n  STR_TASOTH: \"Tasot\"\n  STR_CALCINITE: \"Kalcinit\"\n  STR_DEEP_ONE: \"Hlubiňák\"\n  STR_BIODRONE: \"Biodron\"\n  STR_TENTACULAT: \"Tentakulát\"\n  STR_TRISCENE: \"Triscen\"\n  STR_HALLUCINOID: \"Halucinoid\"\n  STR_XARQUID: \"Xarkid\"\n  STR_ZOMBIE: \"Zombie\"\n  STR_LIVE_COMMANDER: \"Velitel\"\n  STR_LIVE_NAVIGATOR: \"Navigátor\"\n  STR_LIVE_MEDIC: \"Medik\"\n  STR_LIVE_TECHNICIAN: \"Inženýr\"\n  STR_LIVE_SQUAD_LEADER: \"Vůdce\"\n  STR_LIVE_SOLDIER: \"Voják\"\n  STR_LIVE_TERRORIST: \"Terorista\"\n  STR_AQUATOID_COMMANDER: \"Akvatoid velitel\"\n  STR_AQUATOID_NAVIGATOR: \"Akvatoid navigátor\"\n  STR_AQUATOID_MEDIC: \"Akvatoid medik\"\n  STR_AQUATOID_TECHNICIAN: \"Akvatoid inženýr\"\n  STR_AQUATOID_SQUAD_LEADER: \"Akvatoid vůdce\"\n  STR_AQUATOID_SOLDIER: \"Akvatoid voják\"\n  STR_GILLMAN_COMMANDER: \"Žábroun velitel\"\n  STR_GILLMAN_TECHNICIAN: \"Žábroun inženýr\"\n  STR_GILLMAN_SQUAD_LEADER: \"Žábroun vůdce\"\n  STR_GILLMAN_SOLDIER: \"Žábroun voják\"\n  STR_LOBSTERMAN_COMMANDER: \"Kraboun velitel\"\n  STR_LOBSTERMAN_NAVIGATOR: \"Kraboun navigátor\"\n  STR_LOBSTERMAN_TECHNICIAN: \"Kraboun inženýr\"\n  STR_LOBSTERMAN_SQUAD_LEADER: \"Kraboun vůdce\"\n  STR_LOBSTERMAN_SOLDIER: \"Kraboun voják\"\n  STR_TASOTH_SQUAD_LEADER: \"Tasot vůdce\"\n  STR_TASOTH_SOLDIER: \"Tasot voják\"\n  STR_CALCINITE_TERRORIST: \"Kalcinit terorista\"\n  STR_DEEP_ONE_TERRORIST: \"Hlubiňák terorista\"\n  STR_BIODRONE_TERRORIST: \"Biodron terorista\"\n  STR_TENTACULAT_TERRORIST: \"Tentakulát terorista\"\n  STR_TRISCENE_TERRORIST: \"Triscen terorista\"\n  STR_HALLUCINOID_TERRORIST: \"Halucinoid terorista\"\n  STR_XARQUID_TERRORIST: \"Xarkid terorista\"\n  STR_ION_BEAM_ACCELERATORS: \"Urychlovače iontových paprsků\"\n  STR_MAGNETIC_NAVIGATION: \"Magnetická navigace\"\n  STR_ALIEN_SUB_CONSTRUCTION: \"Konstrukce cizáckých ponorek\"\n  STR_ALIEN_CRYOGENICS: \"Cizácká kryogenika\"\n  STR_ALIEN_CLONING: \"Cizácké klonování\"\n  STR_ALIEN_LEARNING_ARRAYS: \"Cizácká učební pole\"\n  STR_ALIEN_IMPLANTER: \"Cizácký implanter\"\n  STR_EXAMINATION_ROOM: \"Pokusná místnost\"\n  STR_AQUA_PLASTICS: \"Akvaplastik\"\n  STR_ALIEN_REANIMATION_ZONE: \"Cizácký oživovací systém\"\n  STR_PLASTIC_AQUA_ARMOR: \"Akvaplastiková zbroj\"\n  STR_ION_ARMOR: \"Iontová zbroj\"\n  STR_MAGNETIC_ION_ARMOR: \"Magneto-iontová zbroj\"\n  STR_HWP_AQUA_JET_MISSILES: \"Vodní trysková torpéda\"\n  STR_HWP_DISPLACER_PWT: \"Pulsní torpédo\"\n  STR_GAUSS_TECH: \"Magneto-technologie\"\n  STR_NEW_FIGHTER_FLYING_SUB: \"Nová útočná létající ponorka\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Nový bojový transportér\"\n  STR_THE_LATEST_FLYING_SUB: \"Nejmodernější létající ponorka\"\n  STR_ARMOR_PIERCING: \"PRŮRAZNÝ\"\n  STR_COELACANTH_GAS_CANNON: \"Coelacanth s plynovým dělem\"\n  STR_COELACANTH_AQUA_JET: \"Coelacanth s torpédometem\"\n  STR_COELACANTH_GAUSS: \"Coelacanth s magn. dělem\"\n  STR_DISPLACER_SONIC: \"Bojovník se sonickým dělem\"\n  STR_DISPLACER_PWT: \"Bojovník s pulsními torpédy\"\n  STR_AJAX_LAUNCHER: \"Odpalovač torpéd Ajax\"\n  STR_DUP_HEAD_LAUNCHER: \"Odpalovač D.U.P. hlavic\"\n  STR_CRAFT_GAS_CANNON: \"Plynové dělo\"\n  STR_PWT_CANNON: \"Pulsní dělo\"\n  STR_GAUSS_CANNON: \"Magnetické dělo\"\n  STR_GAUSS_CANNON_AMMO: \"Náboje do magnetického děla\"\n  STR_SONIC_OSCILLATOR: \"Sonický oscilátor\"\n  STR_AJAX_TORPEDOES: \"Torpéda Ajax\"\n  STR_DUP_HEAD_TORPEDOES: \"Torpéda s D.U.P. hlavicí\"\n  STR_CRAFT_GAS_CANNON_ROUNDS_X50: \"Plynové střely(x50)\"\n  STR_SONIC_WAVE: \"Sonické vlny\"\n  STR_PULSE_WAVE_TORPEDOES: \"Pulsní náboje\"\n  STR_SOLDIER: \"Akvanaut\"\n  STR_SCIENTIST: \"Vědec\"\n  STR_ENGINEER: \"Inženýr\"\n  STR_NORTH_ATLANTIC: \"Severní Atlantik\"\n  STR_SOUTH_ATLANTIC: \"Jižní Atlantik\"\n  STR_NORTH_PACIFIC: \"Severní Pacifik\"\n  STR_SOUTH_PACIFIC: \"Jižní Pacifik\"\n  STR_MEDITERRANEAN: \"Středomoří\"\n  STR_SOUTH_CHINA_SEA: \"Jihočínské moře\"\n  STR_INDIAN_OCEAN: \"Indický ocean\"\n  STR_THE_EAST_SEA: \"Japonské moře\"\n  STR_NORTH_SEA: \"Severní moře\"\n  STR_CARRIBEAN: \"Karibik\"\n  STR_ANTARCTIC: \"Antarktida\"\n  STR_ARCTIC: \"Arktida\"\n  STR_EURASIA: \"Eurasie\"\n  STR_NORTH_AMERICA: \"Severní Amerika\"\n  STR_AFRICA: \"Afrika\"\n  STR_MAXIMUM_SPEED: \"Maximální rychlost\"\n  STR_TRANSMISSION_RESOLVER_UC: \"DEKODÉR VYSÍLÁNÍ\"\n  STR_TRITON: \"TRITON\"\n  STR_HAMMERHEAD: \"KLADIVOUN\"\n  STR_LEVIATHAN: \"LEVIATAN\"\n  STR_BARRACUDA: \"BARAKUDA\"\n  STR_MANTA: \"MANTA\"\n  STR_UFO: \"CIZÁCKÁ PONORKA\"\n  STR_AJAX: \"AJAX\"\n  STR_DUP_HEAD: \"V.U.P. HLAVICE\"\n  STR_CRAFT_GAS_CANNON_UC: \"PLYNOVÉ DĚLO\"\n  STR_PWT_CANNON_UC: \"PULSNÍ DĚLO\"\n  STR_GAUSS_CANNON_UC: \"MAGNETICKÉ DĚLO\"\n  STR_SONIC_OSCILLATOR_UC: \"SONICKÝ OSCILÁTOR\"\n  STR_DAMAGE_CAPACITY: \"Odolnost proti poškození\"\n  STR_WEAPON_POWER: \"Síla zbraně\"\n  STR_WEAPON_RANGE: \"Dostřel\"\n  STR_AIR_LOCK: \"Vstupní komora\"\n  STR_LABORATORY: \"Laboratoř\"\n  STR_WORKSHOP: \"Dílna\"\n  STR_STANDARD_SONAR: \"Standardní sonar\"\n  STR_WIDE_ARRAY_SONAR: \"Širokopásmový sonar\"\n  STR_TORPEDO_DEFENSES: \"Torpédová obrana\"\n  STR_GENERAL_STORES: \"Sklady\"\n  STR_ALIEN_CONTAINMENT: \"Cizacká cela\"\n  STR_GAUSS_DEFENSES: \"Magnetická obrana\"\n  STR_SONIC_DEFENSES: \"Sonická obrana\"\n  STR_PWT_DEFENSES: \"Plasmová obrana\"\n  STR_BOMBARDMENT_SHIELD: \"Tlakový štít\"\n  STR_MC_GENERATOR: \"Generátor M.K.\"\n  STR_MC_LAB: \"M.K. laboratoř\"\n  STR_TRANSMISSION_RESOLVER: \"Dekodér vysílání\"\n  STR_SUB_PEN: \"Dok\"\n  STR_USA: \"USA\"\n  STR_ALASKA: \"ALJAŠKA\"\n  STR_EU_SYNDICATE: \"EURO-SYNDIKÁT\"\n  STR_ARABIAN_BLOC: \"ARABSKÝ BLOK\"\n  STR_EGYPTIAN_CARTEL: \"EGYPTSKÝ KARTEL\"\n  STR_AFRICA_CORP: \"AFRICKÁ KORPORACE\"\n  STR_BRAZILIAN_UNION: \"BRAZILSKÁ UNIE\"\n  STR_NEW_MEXICO: \"NOVÉ MEXICO\"\n  STR_ASIAN_COALITION: \"ASIJSKÁ KOALICE\"\n  STR_SCANDINAVIA: \"SKANDINÁVIE\"\n  STR_NEO_JAPAN: \"NOVÉ JAPONSKO\"\n  STR_FREE_CHINA: \"SVOBODNÁ ČÍNA\"\n  STR_AUSTRALASIA: \"AUSTRALASIE\"\n  STR_FED_KOREA: \"KOREJSKÁ FEDERACE\"\n  STR_EURASIA_UC: \"EURASIE\"\n  STR_ICELANDIC_UNION: \"ISLANDSKÁ UNIE\"\n  STR_TANK: \"Podvodní zbraňové systémy\"\n  STR_CIVILIAN: \"Civilista\"\n  STR_JAN: \"Led\"\n  STR_FEB: \"Úno\"\n  STR_MAR: \"Bře\"\n  STR_APR: \"Dub\"\n  STR_MAY: \"Kvě\"\n  STR_JUN: \"Čvn\"\n  STR_JUL: \"Čvc\"\n  STR_AUG: \"Srp\"\n  STR_SEP: \"Zář\"\n  STR_OCT: \"Říj\"\n  STR_NOV: \"Lis\"\n  STR_DEC: \"Pro\"\n  STR_INTERNATIONAL_RELATIONS: \"Mezinárodní vztahy\"\n  STR_COUNTRY: \"Země\"\n  STR_FUNDING: \"Financování\"\n  STR_CHANGE: \"Změna\"\n  STR_WEAPON_SYSTEMS: \"ZBRAŇOVÉ SYSTÉMY\"\n  STR_HWPS: \"PZS zbraně\"\n  STR_DAMAGE_UC_: \"POŠKOZENÍ>{ALT}{0}\"\n  STR_AIR_LOCK_UFOPEDIA: \"Vstupní komora umožňuje transport materiálu a personálu dovnitř anebo ven z podmořské základny. Je to vždy první zařízení, budované při výstavbě nové základny. Oblast vstupní komory je snadno zranitelná vniknutím nepřátelských útočných sil.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Každá ubytovací jednotka poskytuje prostor až pro 50 osob. Vybavení je základní a funkční.\"\n  STR_LABORATORY_UFOPEDIA: \"V jednom laboratorním bloku může pracovat až padesát vědců. Laboratoře jsou vybaveny nejnovějšími technologiemi pro výzkumy materiálů, biochemií a zbrojírenství. X-Com má přístup do databází všech nejlepších vědeckých ústavů na celém světě, jak civilních tak i vojenských.\"\n  STR_WORKSHOP_UFOPEDIA: \"Dílny jsou vybaveny veškerým zařízením, potřebným pro výrobu součástí základny i nejnovějších objevů výzkumných laboratoří. V jedné dílně může pracovat až 50 inženýrů, ale vyráběné věci rovněž zabírají prostor.\"\n  STR_STANDARD_SONAR_UFOPEDIA: \"Standardní sonarový systém s efektivním dosahem kolem 450 km ve většině hloubek. Je napojen na síť geostacionárních satelitů analyzujících povrch planety. Každý senzor má 10% šanci na zjištění podvodního nebo vzdušného stroje každých 30 minut.\"\n  STR_WIDE_ARRAY_SONAR_UFOPEDIA: \"Širokopásmový sonarový systém s efektivním dosahem kolem 700 km ve všech hloubkách. Je napojen na síť geostacionárních satelitů, analyzujících povrch země. Každý senzor má 20% šanci na zjištění podvodního nebo vzdušného stroje každých 30 minut.\"\n  STR_TORPEDO_DEFENSES_UFOPEDIA: \"Systém torpédové obrany zajišťuje ochranu proti útoku nepřátelských ponorek, snažících se proniknout do doků základny.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"Všechno vybavení, zbraňové systémy, munice, získaný materiál a podvodní ozbrojené systémy jsou umístěny ve skladech, s výjimkou vybavení příslušejícího ponorkám v docích.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"Živí cizáci potřebují pro svoje přežití, umístění v odpovídajícím speciálním prostředí. Tyto cely udržují jejich životní funkce a omezují jejich bojovou schopnost na nulu. Je zde možné udržovat až 10 cizáckých životních forem v oddělených kójích.\"\n  STR_GAUSS_DEFENSES_UFOPEDIA: \"Magnetická obrana zabezpečuje nejnovější a nejefektivnější obranu proti útoku nepřátelských ponorek.\"\n  STR_SONIC_DEFENSES_UFOPEDIA: \"Sonický oscilátor poskytuje silnou a účinnou obranu proti případným útočníkům.\"\n  STR_PWT_DEFENSES_UFOPEDIA: \"Pulsní torpéda poskytují nejefektivnější obranu proti cizáckému útoku. Tato střela je vybavena extrémně výbušnou hlavicí, která prorazí všechny známé pancíře. Magnetické pulzy které vytváří, vyřazují i elektronické obranné systémy.\"\n  STR_BOMBARDMENT_SHIELD_UFOPEDIA: \"Tlakový obranný štít chrání základnu proti podmořskému přistání a nastavuje rezonanční pole na odpuzování útočících ponorek, čímž umožňuje obrannému systému opakovat palbu. Výsledkem je zdvojnásobení efektivity každého obranného systému.\"\n  STR_MC_GENERATOR_UFOPEDIA: \"Cizácké stroje využívají technologii Molekulární kontroly ke zjišťování přítomnosti živých bytostí. Použití negativního M.K. emitoru, zakryje základnu neproniknutelným štítem, který splete cizáky natolik, že nebudou schopni detekovat naši přítomnost.\"\n  STR_MC_LAB_UFOPEDIA: \"Laboratoř molekulární kontroly může vkládat implantáty a zvyšovat schopnosti až deseti akvanautům najednou. Implantáty jsou chirurgicky instalovány do lebek akvanautů. Rozsáhlý trénink jim pak umožňuje využití těchto implantátů. Získaná dovednost je využívána ve spojení s Molekulárním zařízením a může být použita pro útok během boje.\"\n  STR_TRANSMISSION_RESOLVER_UFOPEDIA: \"Cizácká komunikace využívá vybudovanou síť implantátů M.K. Dekodér vysílání zachycuje zprávy cizáckých ponorek a dekóduje informace. Dokáže zjistit typ stroje, cizáckou rasu a typ aktivity, kterou provádí.\"\n  STR_SUB_PEN_UFOPEDIA: \"Každý dok může pojmout jednu ponorku. Je zařízen pro údržbu, tankování a opravy strojů ponorkové flotily X-Com. Každá létající ponorka musí mít přidělen svůj dok, který nemůže být využíván jiným strojem, ani když je přidělená ponorka pryč na misi.\"\n  STR_DART_PISTOL_UFOPEDIA: \"Šipkostříl ve výzbroji X-Com je malá, přesná a vysoce účinná zbraň se zásobníkem na 12 dutých šipek. Šipky jsou vystřelovány plynovou patronou v zásobníku.\"\n  STR_JET_HARPOON_UFOPEDIA: \"Tato vodní puška je přesná a výkonná. Střílí duté ocelové harpuny ze zásobníku s 10 kusy. Každá harpuna má vlastní zásobník plynu.\"\n  STR_GAS_CANNON_UFOPEDIA: \"Nejtěžší z rodiny plynem poháněných zbraní. Tento kanón vystřeluje buď pevné hroty, nebo hroty obsahující výbušninu či fosfor. Oblíbená zbraň mezi zkušenými akvanauty.\"\n  STR_HYDRO_JET_CANNON_UFOPEDIA: \"Vodní tryskové kanóny jsou těžkou pěchotní zbraní. Vystřelují minitorpéda s magneziovým pohonem. Vodní kanón je neskladný a těžkopádný, i když velmi výkonný. Je použitelný pouze pod vodou.\"\n  STR_TORPEDO_LAUNCHER_UFOPEDIA: \"Opravdová těžká váha. Tento torpédomet vystřeluje tři typy torpéd s vlastním propulsním pohonem. Ničivá zbraň, jejíž nevýhodou je pouze ruční nabíjení. Munice se skládá z malých nebo velkých explozivních, či fosforem plněných torpéd. Použitelný je pouze pod vodou.\"\n  STR_GAUSS_PISTOL_UFOPEDIA: \"Magnetická pistole používá technologii urychlovaných částic, nové odvětví moderní zbrojní výroby. Je rychlá, přesná a funguje nad i pod vodou. Magnetická technologie je rozvinutím plazmové technologie, poznané v předchozí válce.\"\n  STR_GAUSS_PISTOL_CLIP_UFOPEDIA: \"Magnetická pistole používá technologii urychlovaných částic, nové odvětví moderní zbrojní výroby. Je rychlá, přesná a funguje nad i pod vodou. Magnetická technologie je rozvinutím plazmové technologie, poznané v předchozí válce.\"\n  STR_GAUSS_RIFLE_UFOPEDIA: \"Vylepšená magnetická pistole s vyšší průrazností, díky dvojitému urychlovači částic. Na rozdíl od plazmových systémů na bázi Eleria, používá částicový mikro-urychlovač produkující svazek antiprotonů.\"\n  STR_GAUSS_RIFLE_CLIP_UFOPEDIA: \"Vylepšená magnetická pistole s vyšší průrazností, díky dvojitému urychlovači částic. Na rozdíl od plazmových systémů na bázi Eleria, používá částicový mikro-urychlovač produkující svazek antiprotonů.\"\n  STR_HEAVY_GAUSS_UFOPEDIA: \"Magnetický kanón je těžkopádný, ale extrémně efektivní. Využívá trojitý urychlovač, před nímž není ochrany. Svazek antiprotonů je vytvářen uvnitř galiumarzenidového pouzdra, jež nárazem částic imploduje a uvolňuje antihmotu.\"\n  STR_HEAVY_GAUSS_CLIP_UFOPEDIA: \"Magnetický kanón je těžkopádný, ale extrémně efektivní. Využívá trojitý urychlovač, před nímž není ochrany. Svazek antiprotonů je vytvářen uvnitř galiumarzenidového pouzdra, jež nárazem částic imploduje a uvolňuje antihmotu.\"\n  STR_MAGNA_BLAST_GRENADE_UFOPEDIA: \"Standardně dodávaný granát. Má přesný a spolehlivý časovač pro precizní nastavení.\"\n  STR_DYE_GRENADE_UFOPEDIA: \"Granáty s obsahem barviva plní dvojí roli při krytí jednotek ve vyhrocených situacích. Použitím ve vodě, je barva rozptýlena do oblaku připomínajícího inkoust chobotnice, použitím na souši, je rozptýlena do mraku kouře.\"\n  STR_PARTICLE_DISTURBANCE_GRENADE_UFOPEDIA: \"Může být hozen stejně jako obyčejný granát, ale po dopadu se pouze uvede do pohotovosti.   K explozi dojde při pohybu v jeho blízkosti. Ke správnému použití je třeba zručnost a zkušenost.\"\n  STR_MAGNA_PACK_EXPLOSIVE_UFOPEDIA: \"Tato nálož je vhodná výhradně k demoličním účelům. Zkušenosti však ukazují, že tato silná výbušnina je téměř ideální zbraní pro vymýcení cizáků. Vzhledem k vysokému okruhu účinnosti je nutné, aby byli všichni akvanauti v bezpečné vzdálenosti.\"\n  STR_PARTICLE_DISTURBANCE_SENSOR_UFOPEDIA: \"Toto nové zařízení využívá množství senzorů a zdokonalený počítačový systém pro identifikaci pohybujících se nepřátelských jednotek ve vodě. Klikněte na ikonku vibračního senzoru. Zvolte 'Použít senzor' v menu. Zobrazí se senzor. Šipka uprostřed ukazuje orientaci akvanauta (sever je nahoře). Blikající značky ukazují jednotky, které se v poslední době pohnuly. Velké, nebo rychle se pohybující jednotky, znázorňují větší značky. Statické jednotky nejsou zobrazeny.\"\n  STR_MEDI_KIT_UFOPEDIA: \"Pro použití je třeba stát čelem k léčenému akvanautovi, případně nad jeho tělem.{NEWLINE}LÉČIT> Klikněte na červeně zvýrazněná poranění a poté na tlačítko 'Uzdravit'. Bude vyléčeno jedno smrtelné zranění a obnoveno zdraví.{NEWLINE}STIMULOVAT> Obnoví energii a oživí ochromeného akvanauta. Oživující akvanaut musí stát přímo nad jeho tělem.{NEWLINE}UTIŠIT> Obnoví morálku zraněného akvanauta.\"\n  STR_MC_DISRUPTOR_UFOPEDIA: \"Ultimátní M.K. technologie. Mohou ho však používat jen ti akvanauti, kteří mají definovanou úroveň M.K. schopností. Po kliknutí na Rušičku vyberte typ útoku a naveďte kurzor na cíl. Jsou dva typy útoku rušičkou:\\nRUŠIT IMPLANTÁT> Je-li úspěšný, jednotka je zmatena a může zpanikařit.\\nOVLÁDNOUT IMPLANTÁT> Je-li úspěšný, získáte nad nepřátelskou jednotkou plnou kontrolu.\"\n  STR_THERMAL_TAZER_UFOPEDIA: \"Zařízení pouze pro boj zblízka. Působením tepelného šoku je schopen omráčit živé organizmy, bez jejich usmrcení.\"\n  STR_VIBRO_BLADE_UFOPEDIA: \"Vibrační pilka je dlouhá, jako nůž ostrá, čepel z titanu, s otáčkami přes 6000/min. Toto zařízení dokáže rozlousknout i nejodolnější potápěčský skafandr. Pohon je cizáckým vynálezem. Naše předchozí pokusy o výrobu tohoto zařízení končily zdrcujícími neúspěchy. Jejich ostří rotovalo příliš pomalu, nebo tlakem explodovalo.\"\n  STR_THERMIC_LANCE_UFOPEDIA: \"Termický oštěp je dalším logickým krokem od vibrační pilky. Ostří rotuje vysokou rychlostí a Zrbitem napájený zdroj ho rozžhavuje tak, že proniká materiálem, jak horký nůž máslem.\"\n  STR_HEAVY_THERMIC_LANCE_UFOPEDIA: \"Těžký termický oštěp je mnohem výkonnější verzí termického oštěpu. Dvojice tepelných zdrojů a extrémně vysoké otáčky znamenají, že těžký termický oštěp je účinný na jakékoliv materiály.\"\n  STR_SONIC_CANNON_UFOPEDIA: \"Sonický kanón je nejsilnější z rodiny sonických zbraní. Je charakteristický zvýšeným rozsahem audio oscilátoru a větší rezonanční komorou než sonická puška. Je rovněž vybaven pulsně detonačním systémem, který modulací ultrazvukových vln zvyšuje efektivitu sonického úderu.\"\n  STR_CANNON_POWER_CLIP_UFOPEDIA: \"Toto kompaktní zařízení slouží jako munice sonického kanónu. Obsahuje malé množství Zrbitu.\"\n  STR_SONIC_BLASTA_RIFLE_UFOPEDIA: \"Další sonické zařízení s vyšším výkonem. Dokonce ani silně legovaná ocel není imunní proti této zbrani. Kompaktní emitor vln je rozšířen supravodivým zesilovačem, který dále zvyšuje výkon této zbraně.\"\n  STR_BLASTA_POWER_CLIP_UFOPEDIA: \"Tento malý předmět slouží jako zdroj energie pro Sonickou pušku, výkonnou cizáckou zbraň. Obsahuje malé množství Zrbitu.\"\n  STR_SONIC_PISTOL_UFOPEDIA: \"Sonické pistole jsou cizáckou zbraní, založenou na ultrazvukových vlnách, které mohou během vteřiny rozdrtit kosti. Ultrazvukové vlny se nachází v oblasti nad hranicí lidské slyšitelnosti.\"\n  STR_PISTOL_POWER_CLIP_UFOPEDIA: \"Energetický článek pro cizáckou sonickou pistoli. Obsahuje Zrbit - zdroj veškeré cizácké síly.\"\n  STR_DISRUPTOR_PULSE_LAUNCHER_UFOPEDIA: \"Toto je cizácká zbraň, použitelná pouze pod vodou, vystřelující samonaváděcí 'disruptorové projektily'. Kliknete-li na střelbu, je třeba umístit 'naváděcí body', podle kterých se bude střela orientovat. Po umístění dostatečného počtu těchto bodů klikněte na ikonku odpálení.\"\n  STR_DISRUPTOR_AMMO_UFOPEDIA: \"Toto zařízení je projektil s disruptorovým pulsem, řízený vestavěným naváděcím počítačem. Je vystřelován z Odpalovače disruptorových pulsů.\"\n  STR_THERMAL_SHOK_LAUNCHER_UFOPEDIA: \"Malý odpalovač termických bomb, který vystřeluje chemické ochromující bomby. Velmi vhodný pro zajímání živých cizáků.\"\n  STR_THERMAL_SHOK_BOMB_UFOPEDIA: \"Termická šoková bomba je užívána k zajímání živých lidských exemplářů, ale stejně účinná je i na většinu cizáckých ras. Je vypouštěna z Odpalovače termických bomb.\"\n  STR_SONIC_PULSER_UFOPEDIA: \"Toto zařízení funguje stejně jako standardní výbušný granát, ale je mnohokrát účinnější. Granát generuje sonický puls, směrovaný současně do všech stran.\"\n  STR_MC_READER_UFOPEDIA: \"V tělech cizáků nacházíme malé, chirurgicky implantované jednotky. Jsou to víceúčelové implantáty, vytvořené Akvatoidy k zajištění stálého přísunu informací z bitevního pole, dokonce i na obrovské vzdálenosti. Čtečka molekulární kontroly je cizácké komunikační zařízení, používané k získávání informací přímo z M.K. implantátů. Jednotky X-Com mohou toto zařízení používat v boji, k zobrazení charakteristik cizáka. Vyberte ikonku 'použít' a klikněte kurzorem na cizáka.\"\n  STR_SURVEY_SHIP: \"Průzkumná loď\"\n  STR_ESCORT: \"Doprovodná loď\"\n  STR_CRUISER: \"Křižník\"\n  STR_HEAVY_CRUISER: \"Těžký křižník\"\n  STR_HUNTER: \"Lovec\"\n  STR_BATTLESHIP: \"Bitevní loď\"\n  STR_DREADNOUGHT: \"Bitevník\"\n  STR_FLEET_SUPPLY_CRUISER: \"Zásobovací křižník\"\n  MAP_SEABED: \"Mořské dno\"\n  MAP_PIPES: \"Výzkumné zařízení\"\n  MAP_PLANE: \"Havarované letadlo\"\n  MAP_ATLAN: \"Atlantis\"\n  MAP_MU: \"Mayský chrám\"\n  MAP_GAL: \"Potopená galeona\"\n  MAP_MSUNK: \"Potopená zaoceánská loď\"\n  MAP_VOLC: \"Vulkán\"\n  MAP_CORAL: \"Korál\"\n  MAP_PORT: \"Přístav\"\n  MAP_ISLAND: \"Ostrov\"\n  MAP_CARGO: \"Nákladní loď\"\n  MAP_LINERT: \"Výletní loď, část 1.\"\n  MAP_LINERB: \"Výletní loď, část 2.\"\n  MAP_ALART: \"Artefakt, část 1.\"\n  MAP_GRUNGE: \"Artefakt, část 2.\"\n  MAP_ENTRY: \"Kolonie, část 1.\"\n  MAP_A_BASE: \"Kolonie, část 2.\"\n  MAP_ALSHIP: \"T'leth, část 1.\"\n  MAP_LEVEL: \"T'leth, část 2.\"\n  MAP_CRYPT: \"T'leth, část 3.\"\n  MAP_XBASES: \"Základna X-Com\"\n  STR_MIXED_CREW: \"Smíšená posádka\"\n  STR_MIXED_CREW_2: \"Smíšená posádka 2\"\n  STR_RATING: \"HODNOCENÍ> {0}\"\n  STR_RATING_TERRIBLE: \"OTŘESNÉ!\"\n  STR_RATING_POOR: \"UBOHÉ!\"\n  STR_RATING_OK: \"OK\"\n  STR_RATING_GOOD: \"DOBRÉ!\"\n  STR_RATING_EXCELLENT: \"VÝBORNÉ!\"\n  STR_SCORE: \"SKÓRE\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"MĚSÍČNÍ HLÁŠENÍ PROJEKTU X-COM\"\n  STR_MONTH: \"Měsíc> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"Sdružení členských organizací je vcelku spokojeno s výsledky vašich akcí.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"Společenství příspěvkových organizací je velmi potěšeno vaším vynikajícím postupem. Pokračujte v dobré práci.\"\n  STR_COUNCIL_IS_DISSATISFIED: \"Společenství příspěvkových organizací, není potěšeno vaším výkonem. Musíte zvýšit vaši snahu v boji s cizáckou hrozbou, jinak riskujete ukončení financování projektu X-Com.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"Nebyli jste úspěšní v boji s cizáckou invazí a tak Sdružení příspěvkových organizací definitivně rozhodlo o ukončení projektu X-Com. Každá organizace bude řešit problém cizáků podle svých sil. Můžeme pouze doufat, že dojde k nějaké dohodě s těmito prastarými silami, a že běžná populace přistoupí na podmínky těchto vodních návštěvníků.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} je částečně potěšen/a s vaší schopností vypořádat se s lokálními hrozbami a souhlasila se zvýšením financování.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} jsou částečně potěšeni s vaší schopností vypořádat se s lokálními cizáckými nájezdy a souhlasili se zvýšením financování.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} a {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} není spokojen/a s vaší schopností poradit si s aktivitou cizáků v jejich vodách a proto snižuje své finanční příspěvky.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} nejsou spokojení s vaší schopností poradit si s aktivitou cizáků v jejich vodách a rozhodli se snížit své finanční příspěvky.\"\n  STR_KNOTS: \"{0} uzlů\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} uzavřel/a smlouvu o spolupráci s cizáky a odstoupil/a od financování projektu X-Com.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} uzavřeli smlouvu o spolupráci s cizáky a odstoupili od financování projektu X-Com.\"\n  STR_MONTHLY_RATING: \"Měsíční hodnocení> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Změna financování> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"Společenství financujících organizací není spokojeno s vaší finanční situací. Musíte své dluhy zredukovat pod 1 million dolarů, jinak bude projekt X-Com ukončen.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"VYSÍLÁNÍ NA SUB-ČÁSTICÍCH JE ROZLUŠTĚNO\"\n  STR_CRAFT_TYPE: \"TYP PONORKY\"\n  STR_RACE: \"RASA\"\n  STR_MISSION: \"MISE\"\n  STR_ZONE: \"ZÓNA\"\n  STR_ALLOCATE_RESEARCH: \"Začít výzkum\"\n  STR_ALLOCATE_MANUFACTURE: \"Naplánovat výrobu\"\n  STR_AZORES: \"Azory\"\n  STR_REYKJAVIK: \"Rejkjavík\"\n  STR_BERMUDA: \"Bermudy\"\n  STR_NEW_YORK: \"New York\"\n  STR_BOSTON: \"Boston\"\n  STR_FORT_SEVERN: \"Fort Severn\"\n  STR_DAKAR: \"Dakar\"\n  STR_RECIFE: \"Recife\"\n  STR_ACCRA: \"Accra\"\n  STR_ASCENSION_ISLAND: \"Ostrov Ascension\"\n  STR_TRINIDADE_ISLAND: \"Ostrov Trindade\"\n  STR_FALKLAND_ISLAND: \"Falklandské ostrovy\"\n  STR_CANARY_ISLANDS: \"Kanárské ostrovy\"\n  STR_ANCHORAGE: \"Anchorage\"\n  STR_ST_LAWRENCE_ISLAND: \"Ostrov sv. Vavřince\"\n  STR_SAN_FRANCISCO: \"San Francisco\"\n  STR_MIDWAY_ISLAND: \"Ostrov Midway\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_TASMANIA: \"Tazmánie\"\n  STR_HAWAII: \"Havaj\"\n  STR_FIJI: \"Fidži\"\n  STR_TONGA: \"Tonga\"\n  STR_EASTER_ISLAND: \"Velikonoční ostrov\"\n  STR_GALAPAGOS_ISLAND: \"Galapágy\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_SOLOMON_ISLAND: \"Šalamounovy ostrovy\"\n  STR_CRETE: \"Kréta\"\n  STR_LISBON: \"Lisabon\"\n  STR_PORT_SAID: \"Port Said\"\n  STR_MARSEILLES: \"Marseille\"\n  STR_TRIPOLI: \"Tripolis\"\n  STR_MANILA: \"Manila\"\n  STR_HONG_KONG: \"Hong Kong\"\n  STR_SINGAPORE: \"Singapur\"\n  STR_BANGKOK: \"Bangkok\"\n  STR_DARWIN: \"Darwin\"\n  STR_BOMBAY: \"Bombaj\"\n  STR_SAYCHELLES_ISLAND: \"Seychely\"\n  STR_MALDIVE_ISLAND: \"Maledivy\"\n  STR_SRI_LANKA: \"Srí Lanka\"\n  STR_MAURITIUS: \"Mauricius\"\n  STR_TOKYO: \"Tokio\"\n  STR_SHANGHAI: \"Šanghaj\"\n  STR_VLADIVOSTOK: \"Vladivostok\"\n  STR_LONDON: \"Londýn\"\n  STR_FAEROE_ISLAND: \"Faerské ostrovy\"\n  STR_ABERDEEN: \"Aberdeen\"\n  STR_OSLO: \"Oslo\"\n  STR_JAMAICA: \"Jamajka\"\n  STR_PANAMA: \"Panama\"\n  STR_MIAMI: \"Miami\"\n  STR_PSI_TRAINING: \"Trénik M.K.\"\n  STR_PSIONIC_TRAINING: \"TRÉNINK MOLEKULÁRNÍ KONTROLY\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Volné místo pro M.K.> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"M.K.{NEWLINE}síla\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"M.K. praxe{NEWLINE}/zlepšení\"\n  STR_IN_TRAINING: \"V{NEWLINE}tréninku?\"\n  STR_TARGETTED_BY: \"ZACÍLENO:\"\n  STR_WEAPONS_CREW_HWPS: \"ZBRANĚ/{NEWLINE}POSÁDKA/P.Z.S.\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"má málo paliva,{NEWLINE}vrací se na základnu\"\n  STR_SOLDIER_LIST: \"Seznam akvanautů\"\n  STR_RANK_: \"HODNOST> {ALT}{0}\"\n  STR_MISSIONS: \"MISÍ> {ALT}{0}\"\n  STR_KILLS: \"ZABITÍ> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"DOBA LÉČENÍ> {ALT}{0}\"\n  STR_TIME_UNITS: \"ČASOVÝCH JEDNOTEK\"\n  STR_STAMINA: \"ENERGIE\"\n  STR_HEALTH: \"ZDRAVÍ\"\n  STR_BRAVERY: \"ODVAHA\"\n  STR_REACTIONS: \"REAKCE\"\n  STR_FIRING_ACCURACY: \"PŘESNOST STŘELBY\"\n  STR_THROWING_ACCURACY: \"PŘESNOST HODU\"\n  STR_STRENGTH: \"SÍLA\"\n  STR_PSIONIC_STRENGTH: \"M.K. SÍLA\"\n  STR_PSIONIC_SKILL: \"M.K. PRAXE\"\n  STR_NEW_RANK: \"NOVÁ HODNOST\"\n  STR_PROMOTIONS: \"Povýšení\"\n  STR_SOLDIERS_UC: \"AKVANAUTI\"\n  STR_COELACANTH_GAS_CANNON_UFOPEDIA: \"Automatické PZS mají vysokou manévrovatelnost a odolný trup. Poskytují podporu útočným oddílům v každé hloubce. PZS se nabíjí automaticky, máte-li dostatek munice.\"\n  STR_COELACANTH_AQUA_JET_UFOPEDIA: \"Tento ponorný systém je vybaven vodními tryskovými torpédy, takže je jeho zbraň použitelná pouze pod vodou. Dbejte na dostatečnou zásobu vodních tryskových torpéd ve skladech.\"\n  STR_COELACANTH_GAUSS_UFOPEDIA: \"Magnetická technologie poskytuje mocnou výzbroj pro PZS. Ve srovnání s předchozími modely nabízí zvýšenou palebnou sílu, s využitím proprietárních technologií X-Com.\"\n  STR_DISPLACER_SONIC_UFOPEDIA: \"Cizácká technologie dává nový směr vývoje PZS. Použití iontových přenašečů znamená, že PZS už není omezen jen na pohyb po zemi a mořském dně. Sonické dělo znamená skutečnou výhodu v boji.\"\n  STR_DISPLACER_PWT_UFOPEDIA: \"Tento PZS používá výzbroj s pulzními vlnami, použitelnými jen pod vodou. Musíte pro něj také vyrábět pulsní torpéda, aby byl vždy plně ozbrojen. Pro střelbu určete několik 'naváděcích bodů' a klikněte na ikonu pro odpálení.\"\n  STR_ALIEN_PROBE_MISSION: \"Cizácká výzkumná mise\"\n  STR_ALIEN_INTERDICTION: \"Cizácká taktická příprava\"\n  STR_ALIEN_RESOURCE_RAID: \"Cizácké zásobovací nájezdy\"\n  STR_ALIEN_INFILTRATION: \"Cizácká infiltrace\"\n  STR_ALIEN_BASE: \"Rozšiřování cizácké kolonie\"\n  STR_ALIEN_SURFACE_ATTACK: \"Cizácké pozemní útoky\"\n  STR_ALIEN_RETALIATION: \"Útok na základnu\"\n  STR_ALIEN_SUPPLY: \"Zásobování kolonií\"\n  STR_ALIEN_PROBE_MISSION_UFOPEDIA: \"Cizácké průzkumné mise slouží pro získávání údajů o mořském dně, těžbě, lodních a leteckých koridorech. Cizácké stroje plnící tyto úkoly pro nás nepředstavují ohrožení, ale indikují budoucí místa cizácké aktivity.\"\n  STR_ALIEN_INTERDICTION_UFOPEDIA: \"Cizáci zachovávají v oblastech jejich zájmů tento postup: vyšlou stroj, se zvláštním určením, k zajištění prostoru pro zahájení intenzivnější činnosti. Přistanou ve vytipovaných místech, kde hodlají později zaútočit, aby zajistili tyto oblasti a připravili na další stupně aktivity.\"\n  STR_ALIEN_RESOURCE_RAID_UFOPEDIA: \"Potápění lodí a sestřelování letadel jsou základní prvky cizácké strategie. Získávání materiálů je primární cizáckou snahou a je spojeno s touto otevřenou agresí. Cizáci také okupují oblasti s geotermální aktivitou, důlní oblasti a místa se zbytky civilizace, aby zde získávali minerály, kovy nebo lidmi zhotovené věci.\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"Jejím důsledkem jsou oficiální kontakty mezi cizáky a společnostmi nebo vládami na nejvyšší úrovni. Vrchol této aktivity je charakterizován zvýšenou aktivitou cizáckých ponorek ve vodách příslušejících těmto organizacím. Cizáci se snaží uzavřít smlouvu s vládou nebo organizací, s nabídkou poskytnutí znalostí jejich vyspělé technologie. Tato cizácká aktivita představuje pro projekt X-Com největší nebezpečí. Jestliže vlády, nebo organizace začnou spolupracovat s vetřelci, zastaví financování.\"\n  STR_ALIEN_BASE_UFOPEDIA: \"Cizáci budují tajné podvodní kolonie v odlehlých oblastech. Po počátečním průzkumu, je zahájení stavby signalizováno zvýšenou aktivitou cizáckých ponorek. Tyto kolonie obsahují laboratoře, klonovací centra a chirurgická zařízení pro experimenty na lidech i cizácích. Přítomnost cizácké kolonie způsobuje zvýšení cizácké aktivity, bez přítomnosti ponorek. Aby bylo možno lokalizovat cizáckou kolonii, musí stroje X-Com hlídkovat několik hodin poblíž předpokládaného místa.\"\n  STR_ALIEN_SURFACE_ATTACK_UFOPEDIA: \"Potřebují-li cizáci lidi, terorizují přístav, napadnou ostrov nebo námořní loď. Kvůli těmto zvrhlým chovným potřebám cizáků a jejich obludným experimentům, jsou civilisté v přímém ohrožení života.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"Je-li X-Com mimořádně úspěšný při potopení cizáckého stroje, můžou cizáci podniknout agresivní odvetnou akci. Jejím výsledkem může být přímý útok na zařízení X-Com. Nejdříve však musí cizáci základnu X-Com lokalizovat. Budete-li úspěšně likvidovat cizácké ponorky, je riziko útoku minimální.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"Jakmile je dokončena výstavba cizácké kolonie, musí být pravidelně zásobována speciální zásobovací lodí. Je-li zjištěno přistání tohoto plavidla, je jisté, že se nedaleko nachází cizácká kolonie.\"\n  STR_SURVEY_SHIP_UFOPEDIA: \"Tato malá ponorka slouží pro průzkumné a kontrolní účely. Je obyčejně předvojem větších plavidel na začátku cizáckých aktivit.\"\n  STR_ESCORT_UFOPEDIA: \"Doprovodné plavidlo střední velikosti, samo o sobě nepředstavující nebezpečí. Tato loď předchází větší plavidla a předznamenává zvýšení cizácké aktivity.\"\n  STR_CRUISER_UFOPEDIA: \"Křižník je základní užitková loď, podporující cizáckou flotilu. Používá se při všech typech cizáckých misí a je nebezpečným protivníkem.\"\n  STR_HEAVY_CRUISER_UFOPEDIA: \"Těžký křižník je výkonnějším plavidlem než křižník. Silnější výzbroj a propulsní systém zvyšují jeho schopnosti. Těžký křižník slouží pro těžební úkoly. Je schopen pojmout velká množství minerálů a vybavení.\"\n  STR_HUNTER_UFOPEDIA: \"Lovec je vybaven pokusnými místnostmi pro provozování experimentální chirurgie na lidských subjektech. Oběti jsou podrobovány odpornému týrání a často je jejich mozek oddělen a uschován pro další zpracování.\"\n  STR_BATTLESHIP_UFOPEDIA: \"Bitevník je nejagresivnějším plavidlem, které cizáci vlastní. Disponuje veškerou cizáckou technologií a systémy. Slouží jako základ pro všechny typy agresivních aktivit, které chtějí cizáci provést. Nese velkou škálu účinných zbraní.\"\n  STR_DREADNOUGHT_UFOPEDIA: \"Záškodník slouží k přepravě výsadkových jednotek. Je plně vybaven cizáckými technologiemi a velkým přepravním prostorem. Záškodník je těžkým a obávaným protivníkem.\"\n  STR_FLEET_SUPPLY_CRUISER_UFOPEDIA: \"Zásobovací loď je používána během konstrukcí cizáckých kolonií nebo zásobování již vybudovaných. Přepravuje cizáckou výživu, DNA, zárodky a další biologické materiály.\"\n  STR_DISMANTLE: \"Rozebrat\"\n  STR_FACILITY_IN_USE: \"DOK JE VYUŽÍVÁN\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"DOK NELZE ROZEBRAT!{SMALLLINE}Všechno vybavení základny musí být spojeno se vstupní komorou.\"\n  STR_TRANSFER_ITEMS_TO: \"Přesunout položky do {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"PRO PŘESUN CHYBÍ CIZÁCKÉ CELY!{SMALLLINE}Živí cizáci potřebují své cely pro přežití.\"\n  STR_AMOUNT_AT_DESTINATION: \"MNOŽTVÍ{NEWLINE}V CÍLI\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"Cizák zemřel, neboť není k dispozici cizácká cela\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"OBYTNÝ PROSTOR JE PLNÝ!{SMALLLINE}Cílová základna nemá dostatek místa v obytných buňkách pro posádku ponorky.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"NEDOSTATEK SKLADOVACÍCH PROSTOR! {SMALLLINE} Cílová základna nemá dostatek místa pro vybavení přidělené ponorky.\"\n  STR_ITEMS_ARRIVING: \"Dodané předměty\"\n  STR_DESTINATION_UC: \"CÍL\"\n  STR_DART_PISTOL: \"Šipkostříl\"\n  STR_DART_POD: \"Zásobník šipkostřílu\"\n  STR_JET_HARPOON: \"Harpunomet\"\n  STR_HARPOON_POD: \"Zásobník harpunometu\"\n  STR_GAS_CANNON: \"Plynový kanón\"\n  STR_GC_AP_AMMO: \"PK-Průbojné střely\"\n  STR_GC_HE_AMMO: \"PK-Explozivní střely\"\n  STR_GC_P_AMMO: \"PK-Fosforové střely\"\n  STR_HYDRO_JET_CANNON: \"Vodní proudový kanón\"\n  STR_HJC_AP_AMMO: \"VK-Průrazné náboje\"\n  STR_HJC_HE_AMMO: \"VK-Explozívní náboje\"\n  STR_HJC_P_AMMO: \"VK-Fosforové náboje\"\n  STR_TORPEDO_LAUNCHER: \"Torpédomet\"\n  STR_SMALL_TORPEDO: \"Malé torpédo\"\n  STR_LARGE_TORPEDO: \"Velké torpédo\"\n  STR_PHOSPHOROUS_TORPEDO: \"Fosforové torpédo\"\n  STR_MAGNA_BLAST_GRENADE: \"Výbušný granát\"\n  STR_DYE_GRENADE: \"Granát s barvou\"\n  STR_PARTICLE_DISTURBANCE_GRENADE: \"Nástrahový granát\"\n  STR_MAGNA_PACK_EXPLOSIVE: \"Výbušná nálož\"\n  STR_PARTICLE_DISTURBANCE_SENSOR: \"Vibrační senzor pohybu\"\n  STR_MEDI_KIT: \"Medikit\"\n  STR_MC_DISRUPTOR: \"Rušička M.K.\"\n  STR_THERMAL_TAZER: \"Termální omračovač\"\n  STR_GAUSS_PISTOL: \"Magnetická pistole\"\n  STR_GAUSS_PISTOL_CLIP: \"Zásobník magn. pistole\"\n  STR_GAUSS_RIFLE: \"Magnetická puška\"\n  STR_GAUSS_RIFLE_CLIP: \"Zásobník magn. pušky\"\n  STR_HEAVY_GAUSS: \"Magnetický kanón\"\n  STR_HEAVY_GAUSS_CLIP: \"Zásobník magn. kanónu\"\n  STR_SONIC_CANNON: \"Sonický kanón\"\n  STR_CANNON_POWER_CLIP: \"Zdroj sonického kanónu\"\n  STR_SONIC_BLASTA_RIFLE: \"Sonická puška\"\n  STR_BLASTA_POWER_CLIP: \"Zdroj sonické pušky\"\n  STR_SONIC_PISTOL: \"Sonická pistole\"\n  STR_PISTOL_POWER_CLIP: \"Zdroj sonické pistole\"\n  STR_DISRUPTOR_PULSE_LAUNCHER: \"Odpalovač disruptorových pulsů\"\n  STR_DISRUPTOR_AMMO: \"Disruptorové náboje\"\n  STR_THERMAL_SHOK_LAUNCHER: \"Odpalovač termických bomb\"\n  STR_THERMAL_SHOK_BOMB: \"Termická bomba\"\n  STR_SONIC_PULSER: \"Sonický pulser\"\n  STR_ZRBITE: \"Zrbit\"\n  STR_MC_READER: \"Čtečka M.K.\"\n  STR_VIBRO_BLADE: \"Vibrační pilka\"\n  STR_THERMIC_LANCE: \"Termický oštěp\"\n  STR_HEAVY_THERMIC_LANCE: \"Těžký termický oštěp\"\n  STR_AQUATOID_CORPSE: \"Mrtvola Akvatoida\"\n  STR_GILLMAN_CORPSE: \"Mrtvola Žábrouna\"\n  STR_LOBSTERMAN_CORPSE: \"Mrtvola Krabouna\"\n  STR_TASOTH_CORPSE: \"Mrtvola Tasota\"\n  STR_CALCINITE_CORPSE: \"Mrtvola Kalcinita\"\n  STR_DEEP_ONE_CORPSE: \"Mrtvola Hlubiňáka\"\n  STR_BIODRONE_CORPSE: \"Mrtvola Biodrona\"\n  STR_TENTACULAT_CORPSE: \"Mrtvola Tentakuláta\"\n  STR_TRISCENE_CORPSE: \"Mrtvola Triscena\"\n  STR_HALLUCINOID_CORPSE: \"Mrtvola Halucinoida\"\n  STR_XARQUID_CORPSE: \"Mrtvola Xarkida\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"Nedostatek munice pro PZS{SMALLLINE}Pro každý PZS je třeba {0} {1}.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Nedostatek materiálu k znovu-vybavení bojové jednotky\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Je nutné vyzkoumat{NEWLINE}{0}{NEWLINE}aby bylo možné vyrobit{NEWLINE}{1}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"Cizáci zničili nebráněnou základnu {0}\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"Hlídka X-Com lokalizovala cizáckou kolonii v {0}\"\n  STR_STANDOFF: \"SLEDOVÁNÍ\"\n  STR_CAUTIOUS_ATTACK: \"OPATRNÝ ÚTOK\"\n  STR_STANDARD_ATTACK: \"BĚŽNÝ ÚTOK\"\n  STR_AGGRESSIVE_ATTACK: \"AGRESIVNÍ ÚTOK\"\n  STR_DISENGAGING: \"ODPOUTÁNÍ\"\n  STR_UFO_HIT: \"CIZÁCKÁ PONORKA ZASAŽENA!\"\n  STR_UFO_CRASH_LANDS: \"CIZÁCKÁ PONORKA HAVAROVALA!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Minimalizovat pouze při sledování\"\n  STR_UFO_RETURN_FIRE: \"CIZÁCKÁ PONORKA OPĚTUJE PALBU!\"\n  STR_INTERCEPTOR_DAMAGED: \">>> LÉTAJÍCÍ PONORKA POŠKOZENA <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> LÉTAJÍCÍ PONORKA ZNIČENA <<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"CIZÁCKÁ LÉTAJÍCÍ PONORKA UNIKÁ!\"\n  STR_LONG_RANGE_DETECTION: \"Širokopásmová detekce\"\n  STR_STORES_UC: \"SKLADY\"\n  STR_DIFFICULTY_LEVEL: \"Úroveň obtížnosti\"\n  STR_INTERCEPT: \"PRONÁSLEDOVAT\"\n  STR_BASES: \"ZÁKLADNY\"\n  STR_GRAPHS: \"GRAFY\"\n  STR_UFOPAEDIA_UC: \"UFOPEDIE\"\n  STR_OPTIONS_UC: \"MOŽNOSTI\"\n  STR_FUNDING_UC: \"FINANCOVÁNÍ\"\n  STR_5_SECONDS: \"5 sek\"\n  STR_1_MINUTE: \"1 min\"\n  STR_5_MINUTES: \"5 min\"\n  STR_30_MINUTES: \"30 min\"\n  STR_1_HOUR: \"1 hod\"\n  STR_1_DAY: \"1 den\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"Rozpiska výkonu X-com\"\n  STR_ENTER_NAME: \"Vložte jméno\"\n  STR_PERFORMANCE_RATING: \"Hodnocení výkonu\"\n  STR_VICTORY_DATE: \"Datum vítězství\"\n  STR_CHEMICAL_FLARE: \"Chemická světlice\"\n  STR_CHEMICAL_FLARE_UFOPEDIA: \"Toto kompaktní zařízení produkuje Intenzívní světelnou záři v každé hloubce nebo na souši. Takto je možné osvětlit nepřátelské jednotky v okolí světlice během misí v temném moři či v noci.\"\n  STR_MONTHLY_COSTS: \"Měsíční náklady\"\n  STR_CRAFT_RENTAL: \"Pronájem létajících ponorek\"\n  STR_SALARIES: \"Platy\"\n  STR_BASE_MAINTENANCE: \"Údržba základny \"\n  STR_COST_PER_UNIT: \"Cena za jednotku\"\n  STR_QUANTITY: \"Množství\"\n  STR_TOTAL: \"Celkem\"\n  STR_IN_PSIONIC_TRAINING: \"Probíhá implantace M.K.\"\n  STR_FRONT_ARMOR: \"Čelní zbroj\"\n  STR_LEFT_ARMOR: \"Levá zbroj\"\n  STR_RIGHT_ARMOR: \"Pravá zbroj\"\n  STR_REAR_ARMOR: \"Zadní zbroj\"\n  STR_UNDER_ARMOR: \"Spodní zbroj\"\n  STR_ROUNDS: \"STŘEL\"\n  STR_UNIT: \"JEDNOTKA> {0}\"\n  STR_ENERGY: \"ENERGIE\"\n  STR_MORALE: \"MORÁLKA\"\n  STR_ARMOR_: \"ZBROJ> {0}\"\n  STR_FRONT_ARMOR_UC: \"ČELNÍ ZBROJ\"\n  STR_LEFT_ARMOR_UC: \"LEVÁ ZBROJ\"\n  STR_RIGHT_ARMOR_UC: \"PRAVÁ ZBROJ\"\n  STR_REAR_ARMOR_UC: \"ZADNÍ ZBROJ\"\n  STR_SKILLS: \"DOVEDNOSTI> {0}\"\n  STR_LEVEL: \"ÚROVEŇ> {0}\"\n  STR_HEAD: \"HLAVA\"\n  STR_TORSO: \"TORZO\"\n  STR_RIGHT_ARM: \"PRAVÁ PAŽE\"\n  STR_LEFT_ARM: \"LEVÁ PAŽE\"\n  STR_RIGHT_LEG: \"PRAVÁ NOHA\"\n  STR_LEFT_LEG: \"LEVÁ NOHA\"\n  STR_PAIN_KILLER: \"UTIŠIT\"\n  STR_STIMULANT: \"STIMULOVAT\"\n  STR_HEAL: \"UZDRAVIT\"\n  STR_TIME_UNITS_SHORT: \"ČJ>{ALT}{0}\"\n  STR_WEIGHT: \"Hmotnost>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"Reagovat>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"M.Praxe>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"M.Síla>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Cizácký artefakt\"\n  STR_AMMO_ROUNDS_LEFT: \"NÁBOJE:{NEWLINE}ZBÝVÁ{NEWLINE}VÝSTŘELŮ={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Utišit>{ALT}{0}{ALT}{NEWLINE}Stimulovat>{ALT}{1}{ALT}{NEWLINE}Léčit>{ALT}{2}\"\n  STR_THROW: \"Hodit\"\n  STR_AUTO_SHOT: \"Automat\"\n  STR_SNAP_SHOT: \"Od boku\"\n  STR_AIMED_SHOT: \"Zamířit\"\n  STR_STUN: \"Omráčit\"\n  STR_PRIME_GRENADE: \"Odjistit granát\"\n  STR_USE_SCANNER: \"Použít vibr. senzor\"\n  STR_USE_MEDI_KIT: \"Použít Medkit\"\n  STR_LAUNCH_MISSILE: \"Odpálit torpédo\"\n  STR_ACCURACY_SHORT: \"Přes>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Nedostatek časových jednotek!\"\n  STR_NOT_ENOUGH_ENERGY: \"Nedostatek energie!\"\n  STR_NO_ROUNDS_LEFT: \"Došly náboje!\"\n  STR_NO_AMMUNITION_LOADED: \"Není nabito!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Munice neodpovídá typu zbraně!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"Zbraň je již nabitá!\"\n  STR_NO_LINE_OF_FIRE: \"Překažka v linii střelby!\"\n  STR_GRENADE_IS_ACTIVATED: \"Granát je odjištěn!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Granát zajištěn!\"\n  STR_THERE_IS_NO_ONE_THERE: \"Tam nikdo není!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Neprozkoumaný cizácký předmět nelze použít!\"\n  STR_OUT_OF_RANGE: \"Mimo dostřel!\"\n  STR_UNABLE_TO_THROW_HERE: \"Překážka v trajektorii hodu!\"\n  STR_SET_TIMER: \"Nastavit časovač\"\n  STR_HIDDEN_MOVEMENT: \"SKRYTÝ POHYB\"\n  STR_TURN: \"KOLO> {0}\"\n  STR_SIDE: \"STRANA> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Pro pokračování stiskněte tlačítko\"\n  STR_MIND_CONTROL: \"Molekulární kontrola\"\n  STR_PANIC_UNIT: \"Blokovat implantát\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Podlomení morálky bylo úspěšné\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Ovládnutí implantátu se zdařilo\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}propadl amoku\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}propadla amoku\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}zpanikařil\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}zpanikařila\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Cizáci\"\n  STR_RIGHT_HAND: \"PRAVÁ RUKA\"\n  STR_LEFT_HAND: \"LEVÁ RUKA\"\n  STR_RIGHT_SHOULDER: \"PRAVÉ RAMENO \"\n  STR_LEFT_SHOULDER: \"LEVÉ RAMENO\"\n  STR_BACK_PACK: \"TORNA\"\n  STR_BELT: \"OPASEK\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}je pod molekulární kontrolou\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}je pod molekulární kontrolou\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}omdlel\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}omdlela\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}zemřel na smrtelné zranění\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}zemřela na smrtelné zranění\"\n  STR_USE_MIND_PROBE: \"Použít molekulární čtečku\"\n  STR_FATAL_WOUNDS: \"SMRTELNÁ ZRANĚNÍ\"\n  STR_UNDER_ARMOR_UC: \"SPODNÍ ZBROJ\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Čas vyhrazen pro výstřel od boku\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Čas vyhrazen pro automatickou střelbu\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Čas vyhrazen pro mířenou střelbu\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Čas vyhrazen pro zakleknutí\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"Čas vyhrazen pro zakleknutí a střelbu\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} jednotka ve stroji X-Com\"\n    few: \"{N} jednotky ve stroji X-Com\"\n    many: \"{N} jednotek ve stroji X-Com\"\n    other: \"{N} jednotek ve stroji X-Com\"\n  STR_UNITS_OUTSIDE:\n    one: \"{N} jednotka zanecháno venku\"\n    few: \"{N} jednotky zanecháno venku\"\n    many: \"{N} jednotek zanecháno venku\"\n    other: \"{N} jednotek zanecháno venku\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} jednotka ve vchodu\"\n    few: \"{N} jednotky ve vchodu\"\n    many: \"{N} jednotek ve vchodu\"\n    other: \"{N} jednotek ve vchodu\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} jednotka v cílovém východu\"\n    few: \"{N} jednotky v cílovém východu\"\n    many: \"{N} jednotek v cílovém východu\"\n    other: \"{N} jednotek v cílovém východu\"\n  STR_ABORT_MISSION_QUESTION: \"Přerušit misi?\"\n  STR_CORPSE: \"Mrtvola\"\n  STR_UNLOAD_CRAFT: \"Odzbrojit\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}byl zabit\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}byla zabita\"\n  STR_HIT_MELEE: \"Zásah\"\n  STR_GROUND: \"ZEMĚ\"\n  STR_LIVING_QUARTERS_PLURAL: \"Obytné buňky\"\n  STR_LIST_ITEM: \"POLOŽKA\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"Všichni cizaci byli zabiti při havárii ponorky,{NEWLINE}automatický průzkum začal\"\n  STR_RESET: \"Reset\"\n  STR_MEMORIAL: \"Památník\"\n  STR_DATE_UC: \"DATUM\"\n  STR_SOLDIERS_RECRUITED_UC: \"AKVANAUTŮ REKRUTOVÁNO>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"AKVANAUTŮ ZTRACENO>{ALT}{0}\"\n  STR_REMOVE_SELECTED: \"Odstranit vybrané\"\n  STR_LIVE_ALIENS: \"Živé{NEWLINE}exempláře\"\n  STR_DEAD_ALIENS: \"Vyřazené{NEWLINE}exempláře\"\n  STR_UNDER_INTERROGATION: \"Nyní{NEWLINE}zkoumané\"\n  STR_CONTAINMENT_EXCEEDED: \"PŘEKROČENA KAPACITA CIZÁCKÝCH CEL!{SMALLLINE}Nedostatečný prostor v celách v {0}. Musíte odstranit přebytečné cizáky z cel (tím zemřou).\"\n  STR_MANAGE_CONTAINMENT: \"Spravovat cizácké cely\"\n  STR_STORAGE_EXCEEDED: \"PŘEPLNĚNÉ SKLADY!{SMALLLINE}Nedostatek skladovacího prostoru v {0}. Musíte prodat nadbytečné předměty.\"\n  STR_GO_TO_BASE: \"Přejít k základně\"\n  STR_MELEE_ACCURACY: \"PŘESNOST ZBLÍZKA\"\n  STR_SELL_PRODUCTION: \"PRODAT\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Obě ruce musí být prázdné!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Nedostatek kusů pro zkopírování šablony!\"\n  STR_UNLOAD_WEAPON: \"Vyprázdnit zbraň\"\n  STR_ALL_ITEMS: \"Všechny věci\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"ŽÁDNÉ DALŠÍ VYBAVENÍ NELZE VZÍT NA PALUBU!{SMALLLINE}Můžete vzít pouze nejvíc {N} kus vybavení na tuto ponorku.\"\n    few: \"ŽÁDNÉ DALŠÍ VYBAVENÍ NELZE VZÍT NA PALUBU!{SMALLLINE}Můžete vzít pouze nejvíc {N} kusů vybavení na tuto ponorku.\"\n    many: \"ŽÁDNÉ DALŠÍ VYBAVENÍ NELZE VZÍT NA PALUBU!{SMALLLINE}Můžete vzít pouze nejvíc {N} kusů vybavení na tuto ponorku.\"\n    other: \"ŽÁDNÉ DALŠÍ VYBAVENÍ NELZE VZÍT NA PALUBU!{SMALLLINE}Můžete vzít pouze nejvíc {N} kusů vybavení na tuto ponorku.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}KONTROLNÍ CENTRUM ZNIČENO{NEWLINE}Dostaň se ke vstupu a zruš misi.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"Vodní zařízení X-Com nelze vybudovat na povrchu\"\n  STR_UNABLE_TO_ENGAGE_DEPTH: \"NELZE ZAÚTOČIT NA NEPŘÍTELE{NEWLINE}V TÉTO HLOUBCE\"\n  STR_UNABLE_TO_ENGAGE_AIRBORNE: \"NELZE ZAÚTOČIT NA NEPŘÍTELE{NEWLINE}KDYŽ JE VE VZDUCHU\"\n  STR_UNDERWATER_EQUIPMENT: \"Toto vybavení nebude fungovat nad vodou!\"\n  STR_LAND_EQUIPMENT: \"Toto vybavení nebude fungovat pod vodou.\"\n  STR_LEVEL_SHORT: \"L{0}\"\n  STR_PERSONNEL: \"Personál\"\n  STR_CRAFT_ARMAMENT: \"Letadla a výzbroj\"\n  STR_COMPONENTS: \"Komponenty\"\n  STR_SOLDIERS_RECRUITED: \"Akvanautů rekrutováno\"\n  STR_SOLDIERS_LOST: \"Akvanautů ztaceno\"\n  STR_TOTAL_UFOS: \"Detekováno letajících ponorek\"\n  STR_TOTAL_ALIEN_BASES: \"Cizáckých kolonií detekováno\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"MSL\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"MSD\"\n  FEMALE_CIVILIAN: \"Civilistka\"\n  MALE_CIVILIAN: \"Civilista\"\n  DOCKER_CIVILIAN: \"Civilista, přístavní dělník\"\n  SAILOR_CIVILIAN: \"Civilista, námořník\"\n  STR_BIODRONE_MELEE_WEAPON: \"Zbraň na blízko Biodronu\"\n  HALLUCINOID_WEAPON: \"Zbraň Halucinoida\"\n  STR_LOBSTERMAN_MELEE_WEAPON: \"Zbraň na blízko Krabouna\"\n  CALCINITE_WEAPON: \"Zbraň Kalcinita\"\n  DEEP_ONE_WEAPON: \"Zbraň Hlubiňáka\"\n  STR_TRISCENE_MELEE_WEAPON: \"Zbraň Triscena\"\n  STR_TRIBIO_SONIC_WEAPON: \"Cizácká sonická zbraň\"\n  XARQUID_WEAPON: \"Zbraň Xarkida\"\n  TENTACULAT_WEAPON: \"Zbraň Tentakuláta\"\n  ZOMBIE_WEAPON: \"Zbraň Zombie\"\n  ALIEN_PSI_WEAPON: \"Cizácká zbraň molekulární kontroly\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/da.yml",
    "content": "da:\n  STR_LEVIATHAN_UFOPEDIA: \"EN TRANSPORT- OG KORTRÆKKENDE FLYVENDE UBÅD MED EKSTREM DYBDEKAPACITET. EN SUPERB SYNTESE AF RUMVÆSNERNES TEKNOLOGI MED VORES EGEN TEKNOLOGI DER UDNYTTER ION-FREMDRIFTSSYSTEMER OG MAGNETISK NAVIGATION.\"\n  STR_BARRACUDA_UFOPEDIA: \"DET BRITISKE HYDROSPACE BARRACUDA, DREVET AF OVEROPHEDET LASERMOTORER. ET AF DE HURTIGSTE SKIBE I VERDEN, KAN DYKKE OG FLYVE, ET NØGLEFARTØJ I DE KOMMENDE SLAG.\"\n  STR_HAMMERHEAD_UFOPEDIA: \"ET TRANSPORT- OG ANGREBSFARTØJ. EN REPLIKATION AF MAGNETISKE MATRIXSYSTEMER I ET X-COM-SKIB. SELVOM LILLE, ER DETS DESIGN EN IMPONERENDE TEKNOLOGISK LANDVINDING.\"\n  STR_TRITON_UFOPEDIA: \"TRITON, ET FARTØJ MED ANGREBSHOLD, TILPASSET MED FULDE ATMOSFÆRISKE- OG VANDMOTORER. DETS STORE KAPACITET OG ROBUSTE KONSTRUKTION SIKRER, AT DET ER GRUNDPILLEN I X-COM-FLÅDEN.\"\n  STR_MANTA_UFOPEDIA: \"MANTA HØJHASTIGHEDSFARTØJ, EN FLYVENDE UBÅD FOR EN PERSON SOM LIGNER DET ION-DREVNE RUMVÆSENSKIB. ET MEGET EFFEKTIVT ANGREBSVÅBEN I DEN ESKALERENDE KONFLIKT.\"\n  STR_AJAX_UFOPEDIA: \"AJAXTORPEDOEN ER STANDARDVÅBEN FOR UNDERSØISK KAMP OVER HELE VERDEN. BRUGES SOM ET PRÆCIST OG KRAFTFULDT AFSKRÆKNINGSVÅBEN\"\n  STR_DUP_HEAD_UFOPEDIA: \"UDTØMT URAN I PILLEFORM ER EN RELATIV NY VÅBENTEKNOLOGI OG DETTE ER DET FØRSTE KOMMERCIELLE UNDERVANDSSYSTEM SOM ANVENDER DET TIL FULDE.\"\n  STR_CRAFT_GAS_CANNON_UFOPEDIA: \"ET KOMPRIMERET GASDREVET KANONSYSTEM DER AFFYRER MASSIVE BOLTE MED HØJ GENNEMTRÆNGNINGSKRAFT.\"\n  STR_PWT_CANNON_UFOPEDIA: \"PULSBØLGETORPEDOEN UDNYTTER ET OVEROPHEDET BRÆNDSTOFSYSTEM OG EN EKSTREM TÆT SPIDS, SOM KAN TRÆNGE IGENNEM DE FLESTE LEGERINGER.\"\n  STR_GAUSS_CANNON_UFOPEDIA: \"GAUSS-VÅBNET ER NY X-COM-TEKNOLOGI. DETTE SYSTEMS PARTIKELACCELERATOR ER DREVET AF EN KOMPAKT, FLYDENDE OG NITROGENNEDKØLET FUSIONSREAKTOR.\"\n  STR_SONIC_OSCILLATOR_UFOPEDIA: \"EN KRAFTFUL AUDITIV OSCILLATOR, SOM SKABER ØDELÆGGENDE LYDBØLGER, DER FÅR MÅLETS MOLEKYLÆRE BÅND TIL AT VIBRERE FRA HINANDEN.\"\n  STR_AQUATOID_UFOPEDIA: \"Aquatioidracen er et oldgammelt samfund, med en historie der tælles i årtusinder før mennesket tog sine første trin på jorden. Deres kompakte form og pæreagtige træk er et træk fra deres rumfarende brødre, sectoiderne. Deres magt er baseret på den kraftfulde teknologi indenfor molekylær kontrol. Aquatoidracen søger at udbrede sin sterile race ved genetisk modifikation, de ideelle emner er mennesker. Eksperimenter har skabt mange hybridracer.\"\n  STR_AQUATOID_AUTOPSY: \"Obduktion - Aquatoid\"\n  STR_AQUATOID_AUTOPSY_UFOPEDIA: \"En detaljeret analyse af denne skabning gør det muligt at foretage nogle grundlæggende antagelser. Det er en sectoid, vores tidligere fjende, men ændret kirurgisk og implantater til en undervandsskabning. Vestigiale lunger tillader vejrtrækning og begrænset bevægelighed i overfladen. Der er cybernetiske implantater i hele kroppen, der øger styrken af dets atrofierede lemmer og funktionen af dets organer. Da alle medlemmer af denne race er identiske, kan vi antage at disse skabninger er kloner.\"\n  STR_GILLMAN_UFOPEDIA: \"Næsten menneskelig, et mærkeligt væsen som fremstår som en reptil humanoid, meget tæt på mennesket. Denne skabning er ekstrem stærk og hurtig i den undersøiske verden. Gællemænd er en fuld race, med mænd og kvinder i forskellige aldre. De er anderledes end hovedparten af undervandsrumvæsnerne, da de ingen tegn har på genetisk ændring eller kirurgisk deformation. Det er muligt, at vi har at gøre med en ældgammel gren af vores egen race.\"\n  STR_GILLMAN_AUTOPSY: \"Obduktion - Gællemand\"\n  STR_GILLMAN_AUTOPSY_UFOPEDIA: \"Da obduktionen kom i gang var det klart at dette ikke er et rumvæsen, men en skabning født på jorden, en gammel historisk race som mentes uddød i det øjeblik pattedyrene blev dominerende. På samme tidspunkt som dinosaurerne regerede levede disse skabninger, gællemænd amfibiske, intelligente og stærke. Den katastrofe, der sluttede reptildominansen på denne planet, tvang disse skabninger til et symbiotisk forhold med de nyankomne rumvæsner. En lille elektronisk enhed er anbragt i kranierne på skabningerne.\"\n  STR_LOBSTERMAN_UFOPEDIA: \"Dette er et svimlende væsen, højere end en mand og med seks lemmer, det ligner ikke mindre end en vanddæmon. Lighederne mellem dette væsen og Jordhummeren har givet væsenet kaldenavnet Hummermand blandt X-Com-tropperne. Dette er en skabning fra dybet. En omhyggeligt designet kampskabning med utrolig styrke og praktisk talt uskadelig over for missilild. Væsenets klør alene kan knuse stål.\"\n  STR_LOBSTERMAN_AUTOPSY: \"Obduktion - Hummermand\"\n  STR_LOBSTERMAN_AUTOPSY_UFOPEDIA: \"Når først bag dets næsten uforgængelige skal har skabningen en imponerende konstruktion. Kraftige muskler omkring et titanskelet, et sofistikeret målsystem med skanning i flere bånd er koblet direkte til skabningens hjerne. Dets mange øjne er beskyttet af plastik, der er hårdere end stål, og det står klart at når de er placeret korrekt af deres overordnede, så kan disse skabninger ikke stoppes. Begravet dybt i deres kroppe er enheder af ukendt konstruktion og funktion.\"\n  STR_TASOTH_UFOPEDIA: \"Disse adrætte og hurtige fjender er en grundpille i rumvæsnernes hær. Hundredvis fødes, i massive ynglekar dybt i hjertet af rumvæsnernes kolonier. Langt mere kraftfuld end en mand, er tasoth'en et rigtigt rumvæsen og dets adfærd og kødædende natur er uovertruffen på planeten. Tasoth'en danner ofte spydspids i et rumvæsenangreb og synes aldrig at flygte fra kampen selv i lyset af overvældende modstand.\"\n  STR_TASOTH_AUTOPSY: \"Obduktion - Tasoth\"\n  STR_TASOTH_AUTOPSY_UFOPEDIA: \"Dissektion afslørede en kybernetisk organisme besiddende en mærkelig magt. Inde i kroppen hulrum er en lille motor, men ingen identificerbare organer. Kraftoverførslen i hele kroppen udføres af et bio-elektrisk transmissionssystem. Hele kroppen mangler knogler eller anden bærende konstruktion. Når død stopper strømmen og væsenet bliver en livløs kludedukke af osende rumvæsenkød og -væsker. Den eneste anden indre konstruktion er et par keramiske celler, som, hvis de får strøm kortvarigt genopliver skabningen.\"\n  STR_DEEP_ONE_UFOPEDIA: \"Dybhavsskabningen er et biologisk mareridt, en krydsning, fremstillet ved warping-eksperimenter hos aquatoiderne. Vi har mødt flere variationer af disse skabninger. Efter omfattende forskning har vi konkluderet, at disse er fremstillet af invasionsstyrkerne. De fylder deres rækker med friske menneskelagre efter tilfangetagelse. Hver af disse undervandsmennesker er armeret med en elektrisk energiudladning stærk nok til at dræbe en dykker.\"\n  STR_DEEP_ONE_AUTOPSY: \"Obduktion - Dybhavsskabning\"\n  STR_DEEP_ONE_AUTOPSY_UFOPEDIA: \"Væsenet er en podning af menneske og en fremmed organisme. Den menneskelige hjerne er massivt ændret for at rumme kontrolelektronik og rumvæsenets hjernebark. Alle delene fra menneskekroppen virker tabt, undtagen en: øjnene. Den kirurgiske podning ser ud til at tillade det fremmede foster at spise den menneskelige vært efterhånden som den vokser. Skabningens hårde hud ser ud til at være et ikke-organisk, metalnet, ekstremt stærkt og fleksibelt. Den resulterende blandingsrace er stærk, hurtig og fuldstændig under rumvæsnernes kontrol.\"\n  STR_BIODRONE_UFOPEDIA: \"Biodronen er en skabning kun en rumvæsenhjerne kan forstå. Det er en hjerne (menneske eller rumvæsen) ophængt i fostervand og tilsluttet en elektrisk basenhed, som kan flyve på land eller under vand. Hver biodrone er bevæbnet med en kraftig auditiv disruptor, delvis maskine og delvis organisme. Nogle af vores forskere har antydet, at våbenet drives af værtsorganismens originale stemmebånd. Meget nøjagtige og ihærdige, så disse supervagthunde er meget udbredt blandt rumvæsnerne til at beskytte deres værdifulde aktiver.\"\n  STR_BIODRONE_AUTOPSY: \"Obduktion - Biodrone\"\n  STR_BIODRONE_AUTOPSY_UFOPEDIA: \"Hypotesen om, at den auditive disruptor er en biologisk enhed, er sand. Denne uheldige skabning skriger bogstaveligt talt sine fjender til døden. Hvert eksemplar har massive kirurgiske ar og er alvorligt lemlæstet. Rumvæsnerne synes at slagte hjernen til lydighed. De fleste af cortex'erne, der anvendes i skabningerne, er fremmede, men intet kan sammenlignes med rædslen om at finde en menneskelig baseret enhed. Biodronerne drives af en ION-motor og indbygger en form for et fjernbetjeningssystem.\"\n  STR_TENTACULAT_UFOPEDIA: \"Ikke engang dybden af et Lovecraftian-mareridt kunne gyde som dette ubeskrivelige væsen. Ingen sammenligning med noget jorddyr eksisterer, det miljø, der kan producere som dette, er ud over vores fantasi. Bevæbnet med lange tentakler lammer tentaculat sine ofre og gør dem til tankeløse ting. Disse afkom kan forårsage død ved berøring, selv gennem panser. Tentaculat er det mest frygtede rumvæsen, der endnu har ramt af X-Com.\"\n  STR_TENTACULAT_AUTOPSY: \"Obduktion - Tentaculat\"\n  STR_TENTACULAT_AUTOPSY_UFOPEDIA: \"Obduktionen afslører, at små cybernetiske implantater placeres i skabningens store hjerne. Synssystemet er en kompleks kombination af synligt lys og erhvervelse af termisk billeddannelse. Selv i havets dybde dybder kan dette monster navigere med sikker præcision. Der er vestigiale organer, der ser ud til at være det blotte minimum for overlevelse. Hver væsen har en lille mave med et eksternt stik, det er logisk at antage, at væsenet bliver fodret med direkte næringsstofindgang fra dem der styrer det.\"\n  STR_CALCINITE_UFOPEDIA: \"Som forliste sjæle afsøger disse rumvæsner havets bund efter de uforsigtige. Et slag fra dette væsens stålagtige klør er nok til at sende selv den bedste dykker til bunds. Bag deres ansigtsmasker anes en grøn gelatineagtig substans bevæge sig. I vores møder med disse væsner har vi endnu ikke fundet nogle spor på reel organisk liv. \"\n  STR_CALCINITE_AUTOPSY: \"Obduktion - Calcinite\"\n  STR_CALCINITE_AUTOPSY_UFOPEDIA: \"Når panseret fjernes ses Calciniten i form af en stor amorf klat af protoplasma. Der er ingen synlig tegn på hjerne, lemmer eller sanseorganer hos dette væsen. Inde i klatten findes en lille metallisk komponent. Vi kan kun gisne om dette rumvæsens adfærd i levende live.\\nDette er en uforklarlig gåde hos de fjendtlige rumvæsner.\"\n  STR_TRISCENE_UFOPEDIA: \"Disse bi-pedale reptiler vækker minder fra dinosaurtiden. Det virker til at disse væsner fuldt ud er fra Kridttiden, med undtagelse af deres evne til at overleve på land og i havet. Disse skabninger er udstyret med våbenplatforme og deres kæber er fyldt med store metaltænder. Ofte har disse væsner været den centrale del af rumvæsnernes angrebsstyrker ved angreb på landmål. Tasoth generalerne anvender disse tunge og potente våben med høj effektivitet. \"\n  STR_TRISCENE_AUTOPSY: \"Obduktion - Triscene\"\n  STR_TRISCENE_AUTOPSY_UFOPEDIA: \"Efter nogen tid i selskab med forskeren's kniv, afslører Triscenen at den er et oldgammelt væsen, suppleret af cybernetiske implantater og våbensystemer. Dens lille hjerne er suppleret af et lille computermodul, monteret på kontrolseletøjet, som alle væsnerne har på. Et tykt, naturligt skind, et rovdyrsinstinkt styrket af yderligere våben, gør dette til en dødbringende fjende i ethvert miljø.\"\n  STR_HALLUCINOID_UFOPEDIA: \"Efter at have høstet havene, har rumvæsnerne fremavlet disse enorme jordiske væsner som et våben. Bliv ikke naret til en falsk følelse af sikkerhed, når du står foran disse dybhavssømænd af harmløst udseende. Besiddende et isnende nærkampsangreb, er Hallucinoiden en dødbringende fjende.\"\n  STR_HALLUCINOID_AUTOPSY: \"Obduktion - Hallucinoid\"\n  STR_HALLUCINOID_AUTOPSY_UFOPEDIA: \"Indlejret i de mange lag af den gelatinøse krop hos denne organisme er en stærk kemisk fryser, dens hovedevne i offensiven. Den bløde og smidige hud hos hallucinoid forekommer modtagelig for varmebaserede angreb. Ofte findes denne mutant i selskab med sine herrer, aquatoider.\"\n  STR_XARQUID_UFOPEDIA: \"Endnu et modificeret hvirveldyr af jordisk oprindelse, Xarquid'en er et væsen af stor skønhed og fare. Den hurtigtsvømmende gigant skjuler et ødelæggende arsenal af våben, en kvælende blækspray og en ioniserende partikeltrykbølge. Siden vores første møde med dette kraftfulde væsen, har vi været på vagt for dens styrke og dens tæmmere, de forbitrede Gællemænd.\"\n  STR_XARQUID_AUTOPSY: \"Obduktion - Xarquid\"\n  STR_XARQUID_AUTOPSY_UFOPEDIA: \"Denne forvoksede Nautilus har vokset sig kæmpe på diæt af rumvæsenmedikamenter og større kirurgiske indgreb. Perverteret udover naturens grænser, har Gællemændene tilføjet mekaniske kontrolsystemer til dyret og dermed udslettet det sidste af dyrets orignale natur. Brugt som en organisk våbenplatform, Xarquids har en stærk skal og en mobilitet der gør dem til formidable modstandere.\"\n  STR_ION_BEAM_ACCELERATORS_UFOPEDIA: \"Rumvæsen flyvende ubåde beror på et komplekst energisystem til at drive dem frem gennem dybet ved utrolige hastigheder. Fundamentet for deres teknologi er ION FORTRÆNGER, der udnytter Zrbite som en katalysator, motorerne fortrænger 100 gange deres egen volumen i vand per sekund. Denne enorme kraft betyder at rumvæsnerne er istand til at overgå de fleste af jordens ubåde. Vi kan replikere dette fremdriftssystem ved at bruge vand-plastik og Zrbite energiceller.\"\n  STR_MAGNETIC_NAVIGATION_UFOPEDIA: \"Disse enheder genererer en sfærisk, multi-lagret magnetisk felt, som systemet kan projektere op til 1000m omkring ubåden. Rumvæsen navigatører er direkte forbundne med maskinerne og føler deres vej rundt i den usynlige verden under bølgerne. Brugerfladesystemet opererer ved hjælp af modificeret rumvæsenhjernestof, der kommunikerer direkte med operatøren's hjerne via en neural forbindelse.\"\n  STR_ALIEN_SUB_CONSTRUCTION_UFOPEDIA: \"Hvert fartøj har en kamæleonlignende struktur, nøje modelleret efter havvæsner, og konstrueret af Vand Plastik. Hver ubåd fungerer som en organisme: besætning og fartøj i harmoni. De fleste af systemerne kan kopieres og en hybridteknologi kan udvikles, der vil tillade os at komme op på samme teknologiske niveau.\"\n  STR_ALIEN_CRYOGENICS_UFOPEDIA: \"De utallige rumvæsner, der har ligget i hi på jorden er holdt i live, kryogenisk frosset. Alle væsnerne er forseglet i enheder, deres kropstempereatur reduceret til et punkt, hvor kropslige funktioner nærmest er stoppet. En nærmere undersøgelse har vist at kroppene har været holdt i live i utrolige tidsperioder, nogen over 60 millioner år.\"\n  STR_ALIEN_CLONING_UFOPEDIA: \"Mange af rumvæsnerne vi har fanget er identiske, helt ned til deres DNA, fuldstændige duplikater. Celleprøver fra rumvæsnernes frosne genbanke er placeret i enhederne. Nogen enheder indeholder mennesker eller kropsdele. Det er muligt at det også er tiltænkt at benytte disse kloningenheder til at skabe en slags rumvæsen-menneskehybrid.\"\n  STR_ALIEN_LEARNING_ARRAYS_UFOPEDIA: \"Ved at udnytte Molekylære Kontrol Implantater i kranierne på alle rumvæsner er disse maskiner istand til at injektere information direkte ind i hjernen. Friskklonede rumvæsner er bragt til disse enheder og får racehukommelser and alle videnskabelige eller kampinformationer downloaded direkte ind i deres tomme hjerner.\"\n  STR_ALIEN_IMPLANTER_UFOPEDIA: \"Denne enhed bruges ofte til at udstyre rumvæsner med Molekylære Kontrol Implantater, befrugte reproducerende racer og indsætte eller fjerne organer og elektronik fra væsner. Vi troede oprindeligt at processen var udført på bedøvede patienter, men disse er helt ved bevidsthed under processen og denne enhed ser uheldigvis til at passe perfekt til den menneskelige anatomi.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"Vi har nu bevis nok til at fastlå hvorfor rumvæsnerne fanger mennesker. De er ikke tiltænkt som føde, de bliver ikke befrugtet med rumvæsenfostre, istedet lader de til at udgøre fundamentet for en række væsner og kontrolsystemer. Rumvæsenteknologi er baseret på et fælles sind, et delt intellekt og menneskehjernen er en ideel beholder for disse systemer. Menneskets hjernevæv benyttes i de fleste rumvæsenbiologiske computerlagrings- og hentningssystemer, resterne bruges til at bygge og avle.\"\n  STR_AQUA_PLASTICS_UFOPEDIA: \"Rumvæsenubåde og konstruktioner udnytter et utrolig stærkt, fleksibelt og holdbart materiale for størstedelen af deres konstruktioner. Vand plastik er komplekst multi-bundne og Zrbite katalyseret materialer. Tæt, dog let, sustanset har en styrke der overgår selv titanium eller kevlar.\"\n  STR_ZRBITE_UFOPEDIA: \"Dette er en legering af rumvæsenoprindelse, del guld, del rumvæsenbiomateriale. Når det udnyttes som energikilde, vil selv små mængder generere mere energi end en 10 gange større nuklear enhed. Det er udover vores tekniske færdigheder at replikere dette materiale, da de flere at dets bestandele er af rumvæsen oprindelse.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"Rumvæsnerne angriber over hele kloden, med hensynsløs effektivitet. Vi kan ikke gennemskue deres kilde. Kunne det være dybt i havet, uigennemtrængeligt for vores lokalisering? Ikke alle organismerne vi er stødt på er rumvæsner, nogle er meget gamle, nogle er fra evolutionære veje, længe troet uddøet. Vi har at gøre med en trussel der har sovet i årtusinder, en subtil symbiose af mennesker og rumvæsner. Dybt i havene ligger et oldgammelt sted, som rumvæsnerne har brugt til at kontakte deres familie blandt stjernerne. Hvert af disse tolv steder indeholder en Synomium enhed, kraftfuld rumvæsenteknologi. Nu med deres krigsmaskine sat igang, genaktiverer rumvæsnerne disse steder for at udvide deres Molekylær Kontrolnet, vi må destruere disse steder, koste hvad det vil.\"\n  STR_THE_ULTIMATE_THREAT_UFOPEDIA: \"For 65 millioner år siden blev et stort koloniskib sendt til jorden fra en fjern rumvæsenverden. Efterhånden som det enorme fartøj nærmede sig planeten, medførte en massiv og voldsom solstorm at navigationssystemerne fejlede. Forkrøblet og fejlramt faldt den enorme masse gennem stratosfæren for at dukke op i kridthimmelen. På jorden rettede utallige livsformer deres blik mod himlen, da deres nemesis pløjede sig ind i planeten. En stor støvklump tilstoppede atmosfæren, og da jorden blev afkølet, døde det dominerende liv, de mægtige dinosaurer. Men de 400 milliarder ton T'leth blev ikke ødelagt i kollisionen, sofistikerede supercomputere indledte en kryogensøvncyklus for skabningerne dybt i skibets indre. Mens æonerne forløb vækkede computere dele af rumvæsnerne for at forsøge at kommunikere med deres stjernefætre, alt dog forgæves for kernen i rumvæsenmagten sov videre.\"\n  STR_TLETH_THE_ALIEN_CITY: \"T'leth - Rumvæsnernes By\"\n  STR_TLETH_THE_ALIEN_CITY_UFOPEDIA: \"T'leth den kæmpe store rumvæsenkoloni ligger indlejret i Sigsbee Dybet, i den Mexikanske Golf. I hjertet af byen er en rumvæsensrædsel, så modbydelig og så kraftfuld at ikke engang døden kan tage den. I et kammer af rumvæsenmetal ligger en sovende form af den store drømmer, det Ultimative rumvæsen. Rejses T'leth over bølgerne vil hans genoplivningscyklus begynde, og rejser han sig først vil han være ustoppelig. Selvom den ikke er i live og på en eller anden måde ikke død, kontrollerer rumvæsensindet rumvæsenhæren. Den mærkelige teknologi af molekylær kontrol forbinder alle rumvæsner til det Ene sind og det Ene sind til alle rumvæsner. genetisk muteret rumvæsen/menneskefostre forsyner rumvæsensindet med energi og skaber en forbindelse mellem herskeren og hans subjekter. Myten om det Ultimative rumvæsen har eksisteret i hjertet og i sindet i menneskeheden for århundreder, havet har altid gemt på den ultimative sandhed.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"CENTRER PÅ STED-TID=5 Sek.\"\n  STR_CANCEL_UC: \"ANNULLER\"\n  STR_NONE: \"Ingen\"\n  STR_UNKNOWN: \"Ukendt\"\n  STR_POOR: \"Dårligt\"\n  STR_AVERAGE: \"Gennemsnitligt\"\n  STR_GOOD: \"Godt\"\n  STR_EXCELLENT: \"Fantastisk\"\n  STR_BUILD_NEW_BASE_UC: \"BYG NY BASE\"\n  STR_BASE_INFORMATION: \"BASEINFORMATION\"\n  STR_EQUIP_CRAFT: \"UDSTYR UBÅD\"\n  STR_BUILD_FACILITIES: \"BYG FACILITETER\"\n  STR_RESEARCH: \"FORSKNING\"\n  STR_MANUFACTURE: \"PRODUCER\"\n  STR_TRANSFER_UC: \"OVERFØR\"\n  STR_PURCHASE_RECRUIT: \"KØB/ANSÆT\"\n  STR_SACK: \"FYR\"\n  STR_SELL_SACK_UC: \"SÆLG/FYR\"\n  STR_GEOSCAPE_UC: \"LANDKORT\"\n  STR_NAME: \"Navn\"\n  STR_AREA: \"Område\"\n  STR_BUILD_NEW_BASE: \"Byg Ny Base\"\n  STR_CANCEL: \"Annuller\"\n  STR_COST_UC: \"PRIS>\"\n  STR_CONSTRUCTION_TIME_UC: \"KONSTRUKTIONSTID>\"\n  STR_DAY:\n    one: \"{N} dag\"\n    other: \"{N} dage\"\n  STR_HOUR:\n    one: \"{N} time\"\n    other: \"{N} timer\"\n  STR_MAINTENANCE_UC: \"VEDLIGEHOLDELSE>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Installation\"\n  STR_CURRENT_RESEARCH: \"NUVÆRENDE FORSKNING\"\n  STR_SCIENTISTS_AVAILABLE: \"Forskere til Rådighed>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Forskere Tildelt>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Laboratorieplads til Rådighed>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"FORSKNINGSPROJEKT\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"FORSKERE TILDELT\"\n  STR_PROGRESS: \"FREMDRIFT\"\n  STR_NEW_PROJECT: \"Nyt projekt\"\n  STR_CANCEL_PROJECT: \"AFBRYD PROJEKT\"\n  STR_NEW_RESEARCH_PROJECTS: \"NYE FORSKNINGSPROJEKTER\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"FORSKERE TIL RÅDIGHED>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"TILGÆNGELIG LABORATORIEPLADS>{ALT}{0}\"\n  STR_INCREASE: \"Flere\"\n  STR_DECREASE: \"Færre\"\n  STR_START_PROJECT: \"START PROJEKT\"\n  STR_CURRENT_PRODUCTION: \"NUVÆRENDE PRODUKTION\"\n  STR_ENGINEERS_AVAILABLE: \"Teknikere til Rådighed>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Teknikere Tildelt>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Tilgængelig Værkstedsplads>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Nuværende Midler>{ALT}{0}\"\n  STR_ITEM: \"UDSTYR\"\n  STR_ENGINEERS__ALLOCATED: \"Teknikere Tildelt\"\n  STR_UNITS_PRODUCED: \"Enheder Produceret\"\n  STR_TOTAL_TO_PRODUCE: \"I alt til Produktion\"\n  STR_COST__PER__UNIT: \"Pris{NEWLINE}per{NEWLINE}Enhed\"\n  STR_DAYS_HOURS_LEFT: \"Resterende Dage/Timer\"\n  STR_NEW_PRODUCTION: \"Ny produktion\"\n  STR_PRODUCTION_ITEMS: \"Enheder der kan produceres\"\n  STR_CATEGORY: \"KATEGORI\"\n  STR_START_PRODUCTION: \"START PRODUKTION\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} Teknikertimer til at fremstille en enhed\"\n  STR_COST_PER_UNIT_: \"Pris pr. enhed>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Påkrævet arbejdsareal>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"SPECIELLE MATERIALER ER KRÆVET\"\n  STR_ITEM_REQUIRED: \"UDSTYR KRÆVET\"\n  STR_UNITS_REQUIRED: \"ENHEDER KRÆVET\"\n  STR_UNITS_AVAILABLE: \"ENHEDER TIL RÅDIGHED\"\n  STR_STOP_PRODUCTION: \"STOP PRODUKTION\"\n  STR_ENGINEERS_AVAILABLE_UC: \"TEKNIKERE TIL RÅDIGHED>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"VÆRKSTEDSAREAL TIL RÅDIGHED>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"MÅNEDLIG PROFIT>{ALT}{0}\"\n  STR_INCREASE_UC: \"FLERE\"\n  STR_DECREASE_UC: \"FÆRRE\"\n  STR_UNITS_TO_PRODUCE: \"Enheder at Producere\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Køb/Ansæt Personale\"\n  STR_COST_OF_PURCHASES: \"Pris for Indkøb>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"PRIS PER ENHED\"\n  STR_QUANTITY_UC: \"ANTAL\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"TILGÆNGELIG PERSONALE:PERSONALE I ALT>\"\n  STR_SOLDIERS: \"Dykkere\"\n  STR_SCIENTISTS: \"Forskere\"\n  STR_ENGINEERS: \"Teknikere\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"ANVENDT PLADS:TILGÆNGELIG PLADS>\"\n  STR_LIVING_QUARTERS: \"Beboelsesrum\"\n  STR_STORES: \"Lager\"\n  STR_LABORATORIES: \"Laboratorier\"\n  STR_WORK_SHOPS: \"Værksted\"\n  STR_HANGARS: \"Flyvende Ubådsbunkere\"\n  STR_SHORT_RANGE_DETECTION: \"Kortrækkende Sonar\"\n  STR_DEFENSE_STRENGTH: \"Forsvarsstyrke\"\n  STR_TRANSFERS_UC: \"OVERFØRSLER\"\n  STR_TRANSFERS: \"Overførsler\"\n  STR_ARRIVAL_TIME_HOURS: \"Ankomsttid (timer)\"\n  STR_COST_: \"Pris>{ALT}{0}\"\n  STR_AREA_: \"Område>{ALT}{0}\"\n  STR_BASE_NAME: \"Basenavn?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"VÆLG LUFT-SLUSENS PLACERING\"\n  STR_TRANSFER: \"Overfør\"\n  STR_AMOUNT_TO_TRANSFER: \"MÆNGDE DER SKAL OVERFØRES\"\n  STR_SELECT_DESTINATION_BASE: \"Vælg Destinationsbase\"\n  STR_COST: \"Pris\"\n  STR_INTRO_1: \"Ophavsret 1995 MicroProse\"\n  STR_INTRO_2: \"Mars: Cydonias fald.\"\n  STR_INTRO_3: \"Et triumferende X-Com, der har destrueret selve kerne i rumvæsenkrigsmaskinen, fyrer afsted hjemad. Men, alt er ikke dødt i den sønderrevne Marsbase.\"\n  STR_INTRO_4: \"En kraftfuld tachyon stråle strømmer fra resterne af det Cydonianske nervecenter - drøner gennem tomrummet. Dens destination............\"\n  STR_INTRO_5: \"Jorden.\"\n  STR_INTRO_6: \"Dybt i havet rammer strålen en længe afventende receptor. Omfattende, sovende computere begynder at vågne. I dybet, væk fra menneskeøjne, begynder omfattende kamre af sovende rumvæsner deres lange genoplivningscyklus.\"\n  STR_INTRO_7: \"2040: En ignorant jord. Terroren fra rumvæsenkrigen er glemt. Men i glemte og skjulte områder af havet, er rumvæsenhorderne klar - klar til at overrumple menneskene og overtage verden.\"\n  STR_INTRO_8: \"Rumvæsnerne slår til mod menneskeheden; søger eksemplarer til deres forskruede eksperimenter; Driver rovdrift på verden for værdigfulde mineraler og ressourcer; og plyndrer havene. Og så retter rumvæsnerne deres sigte til over bølgerne.\"\n  STR_INTRO_9: \"Kraftfulde flyvende ubåde af mærkeligt design pløjer gennem havene - spejder, søger, jager.........\"\n  STR_INTRO_10: \"Finder ofre de kan angribe.\"\n  STR_INTRO_11: \"Underlige nye våben er sat ind for at beskytte vores forsvarløse verden. Vi er fuldstændigt i rumvæsentruslens nåde.{NEWLINE}Kun én organisation kan redde os; men, vi vendte dem ryggen for lang tid siden......\"\n  STR_INTRO_12: \"X-Com Eksperimentiel Undervandsfacilitet\"\n  STR_INTRO_13: \"'Mayday! Mayday!' 'Dette er den transatlantiske færge Hyperion'. 'Vi er under angreb'. 'Mayday! Mayd............'\"\n  STR_INTRO_14: \"'Kommandokontrol til Ubådsbunker Et: Åben havdørene', 'udsæt Barracuda Nul Et. Vi har en rumvæsenangrebssituation - betingelse Rød'.{NEWLINE}'Jeg gentager: betingelse Rød'\"\n  STR_INTRO_15: \"Rumvæsnerne er hensynsløse i deres effektivitet ...\"\n  STR_INTRO_16: \"...klippefast i deres præcision\"\n  STR_INTRO_17: \"»Barracuda Nul Et til basen« - »nærmer os resterne af Hyperion«.\"\n  STR_INTRO_18: \"'Decelererer'.{NEWLINE}'To meter'{NEWLINE}'En meter'{NEWLINE}'Alle dykkere forbered til øjeblikkelig indsættelse'.\"\n  STR_INTRO_19: \"...........'Luftsluse klargjort'...'nærmer os vraget'.{NEWLINE}'Ved den hellige!'{NEWLINE}'Ser du de skabninger på mit kropskamera?'\"\n  STR_GAMEOVER_1: \"Vi har fejlet, rumvæsnerne har udslettet vores sidste håb for frelse.{NEWLINE}X-Com er ødelagt og jorden ligger på knæ for den oldgamle fjendes fødder.\"\n  STR_GAMEOVER_2: \"T'leth tordner højt oppe i stratosfæren og begynder at bevæge sig henover verdens overflade. Udløsende død og høstende resterne af menneskeracen. Dybt inde i dets tarme, begynder den morderiske rumvæsenhjerne at opildne sig selv.\"\n  STR_GAMEOVER_3: \"I hovedstaderne i alle nationer udtænkes desperate planer. Alt er forgæves, uden teknologien udvundet af X-Com udviklingsprojekterne er vores våben virkningsløse.\"\n  STR_GAMEOVER_4: \"Rumvæsnerne sætter baser på polarisen og begynder at smelte isen, verden vil blive til et stort hav. Resterne af menneskeracen rundes op og udnyttes i modbydelige parringseksperimenter til ukendte rumvæsenformål. Himlen bliver mørk og en mægtig pestilens omslutter landet på jorden.\"\n  STR_GAMEOVER_5: \"Vi kan ikke tilbyde at gøre modstand overfor den nye verdensorden, dem der forsøger vil møde en brændende skæbne fra de ufattelige rumvæsenvåben. For resten af os vil der ikke være nogen sådan velsignet afgang, moder jord bliver en rumvæsenverden og menneskeheden er tabt under en kravlende rædsel.\"\n  STR_OUTRO_1: \"Graven, sønderrevet og decimeret, et boblende skrål kommer fra kisten i dets center.{NEWLINE}Fjolser I vil alle dø....................\"\n  STR_OUTRO_2: \"................. ingen kan undslippe.\"\n  STR_OUTRO_3: \"En kæmpestor eksplosion bryder ud fra gravene og den løber igennem byen, rester og røg fylder luften. Rumvæsnernes plan er forpurret........\"\n  STR_OUTRO_4: \"Det snoede massive T'leth begynder at sprænges. Flammer og røg spyr ud fra dets glinsende spir og adamantium haller.\"\n  STR_OUTRO_5: \"Den mægtige rumvæsenskjul falder mod havet, skrigene af tortureret metal og sjæle fylder luften. Den Store Srømmer vil ikke længere drømme om at erobre verden.\"\n  STR_OUTRO_6: \"Et sidste øresplittende slag af lyd og T'leth flår sig selv i stykker.{NEWLINE}Rumvæsentruslen er væk, jorden er renset..................\"\n  STR_OUTRO_7: \"En søvnig blå-grøn planet, i et fjernt hjørne af galaksen.\"\n  STR_OUTRO_8: \"Den kommende fremtid, et sikkert sted at være.\"\n  STR_OUTRO_9: \"Rumvæsnernes trussel mod jorden er blevet fjernet.\"\n  STR_OUTRO_10: \"Store metropoler som byer er hjem for billioner af mennesker.\"\n  STR_OUTRO_11: \"X-com og krigene mod rumvæsnerne er blevet til børnehistorier.\"\n  STR_OUTRO_12: \"Men legender har altid haft en evne til at indeholde en snert af sandhed .......\"\n  STR_RISE_1: \"T'leth, kaldt mange ting i mange legender fra mange lande.\"\n  STR_RISE_2: \"Med et eksplosivt skrig der giver genlyd på tværs af globen T'leth begynder at rejse sig fra havbunden.\"\n  STR_RISE_3: \"Den enorme konstruktion stormer gennem vandet i den Mexikanske Golf.\"\n  STR_RISE_4: \"400 milliarder tons af rumvæsenmetal, den mægtige rumvæsenby hvori kroppen af det Ultimative rumvæsen sover. Efter at være fanget på jorden i 65 millioner år, begynder denne modbydelige rum Gud at røre på sig.\"\n  STR_RISE_5: \"Vandet koger og pisker idet den Store Drømmer's grav kommer til syne i lyset................\"\n  STR_RISE_6: \".........et kortlivet lys, medmindre X-Com kan destruere denne rumvæsenskrigsmaskine.\"\n  STR_YOU_HAVE_FAILED: \"Du har fejlet i at stoppe rumvæsenskrigsmaskinen. De finansierende organisationer, desillusioneret med din evne forsøger at forhandle en ikke-militær løsning med rumvæsnerne. De invaderende har en meget anderledes agenda og snart vil hele verden være klar over sandheden...\"\n  STR_TOTAL_UC: \"I ALT\"\n  STR_INCOME: \"Indtægter\"\n  STR_EXPENDITURE: \"Udgifter\"\n  STR_MAINTENANCE: \"Vedligeholdelse\"\n  STR_BALANCE: \"Resultat\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"Rumvæsenaktivitet i Have\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"Rumvæsenaktivitet i Zoner\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"X-Com-aktivitet i Have\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"X-Com-aktivitet i Zoner\"\n  STR_FINANCE: \"Finanser\"\n  STR_DATE_FIRST: \"{0}.\"\n  STR_DATE_SECOND: \"{0}.\"\n  STR_DATE_THIRD: \"{0}.\"\n  STR_DATE_FOURTH: \"{0}.\"\n  STR_FINANCE_THOUSANDS: \"i 1.000 kr.\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Ikke nok specielle materialer til at fremstille{NEWLINE}{0}{NEWLINE}på{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Ikke nok penge til at producere{NEWLINE}{0}{NEWLINE}på{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"Produktion af{NEWLINE}{0}{NEWLINE}på{NEWLINE}{1}{NEWLINE}er færdig\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"Konstruktion af{NEWLINE}{0}{NEWLINE}på{NEWLINE}{1}{NEWLINE}er færdig\"\n  STR_OK_5_SECONDS: \"OK - 5 sek.\"\n  STR_RESEARCH_COMPLETED: \"Forskning Fuldendt\"\n  STR_VIEW_REPORTS: \"GENNEMSE RAPPORTER\"\n  STR_WE_CAN_NOW_RESEARCH: \"Vi kan nu forske i\"\n  STR_WE_CAN_NOW_PRODUCE: \"Vi kan nu producere\"\n  STR_SUNDAY: \"SØNDAG\"\n  STR_MONDAY: \"MANDAG\"\n  STR_TUESDAY: \"TIRSDAG\"\n  STR_WEDNESDAY: \"ONSDAG\"\n  STR_THURSDAY: \"TORSDAG\"\n  STR_FRIDAY: \"FREDAG\"\n  STR_SATURDAY: \"LØRDAG\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Ikke tilstrækkelig {0} til at tanke {1} på {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Ikke nok {0} til at udruste {1} på {2}\"\n  STR_UFO_IS_NOT_RECOVERED: \"Rumvæsenubåd blev ikke bjærget\"\n  STR_UFO_IS_RECOVERED: \"Rumvæsenubåd blev bjærget\"\n  STR_CRAFT_IS_LOST: \"Flyvende Ubåd mistet\"\n  STR_TERROR_CONTINUES: \"Rumvæsenaktivitet fortsætter\"\n  STR_ALIENS_DEFEATED: \"Rumvæsner besejret\"\n  STR_BASE_IS_LOST: \"Base er tabt\"\n  STR_BASE_IS_SAVED: \"Base er reddet\"\n  STR_ALIEN_BASE_STILL_INTACT: \"Rumvæsnernes Koloni er stadig intakt\"\n  STR_ALIEN_BASE_DESTROYED: \"Rumvæsnernes Koloni er ødelagt\"\n  STR_ALIENS_KILLED: \"RUMVÆSNER DRÆBT\"\n  STR_ALIEN_CORPSES_RECOVERED: \"FUNDNE RUMVÆSENLIG\"\n  STR_LIVE_ALIENS_RECOVERED: \"RUMVÆSNER FANGET I LIVE\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"UDSTYR FRA RUMVÆSNER BJÆRGET\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"RUMVÆSNERNES KONTROLBASE ER ØDELAGT\"\n  STR_ALIEN_SYNOMIUM_DEVICE_DESTROYED: \"RUMVÆSEN SYNOMIUM ENHED DESTRUERET\"\n  STR_ALIEN_SYNOMIUM_DEVICE_FAILED: \"KUNNE IKKE ØDELÆGGE SYNOMIUMENHED\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"CIVILE DRÆBT AF RUMVÆSNER\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"CIVILE DRÆBT AF X-COM-SOLDATER\"\n  STR_CIVILIANS_SAVED: \"CIVILE REDDET\"\n  STR_XCOM_OPERATIVES_KILLED: \"X-COM-SOLDATER DRÆBT\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"X-COM-SOLDATER FORSVUNDET I KAMP\"\n  STR_TANKS_DESTROYED: \"X-COM-VÅBENPLATFORM ØDELAGT\"\n  STR_XCOM_CRAFT_LOST: \"X-COM-UNDERVANDSBÅD MISTET\"\n  STR_UFO_RECOVERY: \"RUMVÆSENUBÅDSBJÆRGNING\"\n  STR_ALIEN_BASE_RECOVERY: \"RUMVÆSENKOLONIBJÆRGNING\"\n  STR_BASE_UNDER_ATTACK: \"{0} under angreb!\"\n  STR_BASE_DEFENSES_INITIATED: \"BASEFORSVAR INITIERET\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"SKJOLD AFVÆRGER RUMVÆSENUBÅD!\"\n  STR_FIRING: \"SKYDER\"\n  STR_HIT: \"RAMT!\"\n  STR_UFO_DESTROYED: \"RUMVÆSENUBÅD ØDELAGT!\"\n  STR_MISSED: \"FORBIER!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Sælg Udstyr/Fyr Personale\"\n  STR_VALUE_OF_SALES: \"SALGSVÆRDI> {ALT}{0}\"\n  STR_FUNDS: \"MIDLER> {ALT}{0}\"\n  STR_SELL_SACK: \"Sælg/Fyr\"\n  STR_VALUE: \"Værdi\"\n  STR_CRAFT_: \"FLYVENDE UBÅD> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"RUMVÆSENUBÅDSSTYRTBJÆRGNING\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"VÆR FORSIGTIG - Der vil være rumvæsner i ubåden og rundt omkring stedet. Denne mission vil være succesfuld når alle fjendtlige enheder er blevet elimineret eller neutraliseret. Bjærgning af rester fra rumvæsenubåden, teknologi og rumvæsenlig kan så påbegyndes. For at afbryde missionen skal du returnere X-Com-dykkerne til ubåden og klikke på ikonet »Afbryd mission«.\"\n  STR_UFO_GROUND_ASSAULT: \"ANGREB MOD RUMVÆSENUBÅD\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"Udforsk landingsstedet, og hvis det er muligt, skaf dig adgang til rumvæsnernes ubåd. Missionen vil være en succes, når alle fjendtlige enheder er blevet elimineret eller neutraliseret. Bjærgning af rumvæsenubåd, udstyr og rumvæsenernes lig kan derefter igangsættes. For at afbryde missionen skal du returnere dine X-Com-dykkere til transportflyet og klikke på ikonet »Afbryd mission«.\"\n  STR_BASE_DEFENSE: \"BASEFORSVAR\"\n  STR_BASE_UC_: \"BASE> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"Et af rumvæsnernes fartøjer er landet i området. Vores base er i alvorlig fare. Som standardprocedure er alt ikkemilitært personel og funktionelle X-Com-ubåde blevet evakueret. Rumvæsnerne vil angribe basen via ubådsåbningerne eller luftslusen. Forsvar basen og dens vitale installationer uanset omkostningerne - dette er en kamp til døden. Hvis du klikker på ikonet »afbryd mission« bliver du besejret og mister basen.\"\n  STR_ALIEN_COLONY_ATTACK_MISSION: \"ANGREBSMISSION MOD RUMVÆSENKOLONI\"\n  STR_ALIEN_BASE_ASSAULT: \"RUMVÆSENKOLONI - DEL ET\"\n  STR_ALIEN_COLONY_P1_BRIEFING: \"Denne mission er et angreb på en rumvæsenkoloni. Der er to niveauer på dette sted, få alle dykkerne til den glødende udgang i det første kompleks og klik på ikonet »Afbryd mission« for at fortsætte. Efterladt udstyr vil forblive på søbunden indtil det andet niveau er klaret. For at afbryde missionen skal du returnere X-Com-dykkerne til ubåden og klikke på ikonet »Afbryd mission«.\"\n  STR_ALIEN_COLONY_P2: \"RUMVÆSENKOLONI - DEL TO\"\n  STR_ALIEN_COLONY_P2_BRIEFING: \"Du har overvundet det første niveau og er gået ind i hjertet af kolonien. Missionen er at destruere kontrolcenteret, Synomium Enheden, eller eliminér alle rumvæsner. For at afbryde, så placer alle dykkerne tilbage på liften og klik på 'Afbryd Mission' ikonet. Alt gyldigt X-Com udstyr vil blive returneret til basen.\"\n  STR_ALIENS_LAUNCH_PORT_TERROR: \"RUMVÆSNERNE STARTER{NEWLINE}ET HAVNEANGREB PÅ\"\n  STR_PORT_TERROR: \"RUMVÆSNER STARTER HAVNEANGREB\"\n  STR_PORT_TERROR_BRIEFING: \"Rumvæsnerne har startet et angreb mod et landmål. Havnen og dens civile befolkning er i fare. Din kampenhed skal eliminere alle rumvæsnerne og beskytte de uskyldige tilskuere fra rumvæsnernes angreb. For at afslutte placeres dykkerne i den flyvende ubåd og der klikkes på ikonet »Afbryd mission«.\"\n  STR_ALIENS_LAUNCH_ISLAND_TERROR: \"RUMVÆSNERNES STARTER{NEWLINE}ET ANGREB MOD ØEN\"\n  STR_ISLAND_TERROR: \"RUMVÆSNER STARTER Ø-ANGREB\"\n  STR_ISLAND_TERROR_BRIEFING: \"Rumvæsner har startet et angreb mod et overflademål. Øen og dens civile befolkning er i fare. Din kampenhed skal eliminere alle rumvæsner og beskytte de uskyldige civile fra dette rumvæsenangreb. For at afslutte, placeres dykkerne i den flyvende ubåd og der klikkes på ikonet »Afbryd mission«.\"\n  STR_ALIENS_ATTACK_SHIPPING_ROUTE: \"RUMVÆSNERNE ANGRIBER{NEWLINE}EN SEJLRUTE\"\n  STR_CARGO_SHIP_P1: \"LASTSKIB DEL ET\"\n  STR_CARGO_SHIP_P2: \"LASTSKIB DEL TO\"\n  STR_CRUISE_SHIP_P1: \"KRYDSTOGTSKIB DEL ET\"\n  STR_CRUISE_SHIP_P2: \"KRYDSTOGTSKIB DEL TO\"\n  STR_SHIP_RESCUE_MISSION: \"SKIBREDNINGSMISSION\"\n  STR_SHIP_RESCUE_P1_BRIEFING: \"Denne mission er en insektjagt, eliminer alle rumvæsnerne på skibet, og sikr dig at de civile på skibet overlever. Rumvæsnerne er spredt over dækkene og på dækkene, sikr de øverste dæk før du går til de nedre. For at afslutte, placeres dykkerne i den flyvende ubåd og der klikkes på ikonet »Afbryd mission«.\"\n  STR_SHIP_RESCUE_P2_BRIEFING: \"Nu hvor det øvre dæk er ryddet, skal der fortsættes mod de nedre dæk. Via vareliften kan du komme længere ned. Din kampenhed skal eliminere alle rumvæsnerne på dette niveau for at fuldføre missionen. For at afslutte placeres dykkerne på liften og der klikkes på ikonet »Afbryd mission«.\"\n  STR_ALIEN_ACTIVITY_DETECTED: \"RUMVÆSENAKTIVITET REGISTRERET\"\n  STR_ALIEN_CONTACT_SITE_MISSION: \"MISSION TIL RUMVÆSENKONTAKTSTED\"\n  STR_ARTIFACT_SITE_P1: \"RUMVÆSENKONTAKTSTED DEL ET\"\n  STR_ARTIFACT_SITE_P1_BRIEFING: \"Denne mission er et angreb på en nyligt aktiveret rumvæsen kommunikationssted. Der er 2 niveauer på stedet, havbunden med dets rumvæsenpyramider og en gemt rumvæsenkompleks. Få alle dykkerne til indgangen af komplekset og klik på 'Afbryd Mission' ikonet for at fortsætte. For at Afbryde, så placer alle dykkere inde i den flyvende ubåd og klik på 'Afbryd Mission' ikonet.\"\n  STR_ARTIFACT_SITE_P2: \"RUMVÆSENKONTAKTSTED DEL TO\"\n  STR_ARTIFACT_SITE_P2_BRIEFING: \"Efter at have bekæmpet de ydre rumvæsenstrukturer og sat fod i komplekset, er missionens mål klare. Penetrér hjertet af rumvæsenfaciliteten og destruer Synomium Molekylær Kontrolenheden for at fuldføre missionen. For at afbryde, så placer alle dykkerne tilbage på liften og klik 'Afbryd Mission' ikonet.\"\n  STR_SIGSBEE_DEEP_MISSION: \"SIGBEE DYBMISSION{NEWLINE}RUMVÆSEN BY NIVEAU ET\"\n  STR_TLETH_P1_BRIEFING: \"Vi træder ind i det ukendte, herfra kan hvad som helst ske. Vi ved der er to videre niveauer i rumvæsenbyen og din kampenhed må skynde sig til udgangen af dette niveau for at komme til næste niveau. Placer alle dykkere ved udgangen og klik 'Afbryd Mission' ikonet for at fortsætte. Afbryder du et andet sted, vil missionen afsluttes.\"\n  STR_TLETH_ATTACK_MISSION: \"T'LETH ANGREBSMISSION{NEWLINE}RUMVÆSEN BY NIVEAU TO\"\n  STR_TLETH_P2_BRIEFING: \"Videre ind i det ukendte, herfra kan hvad som helst ske. Vi ved der er ét videre niveau i rumvæsenbyen og din kampenhed må skynde sig til udgangen af dette niveau for at komme til næste niveau. Placer alle dykkere ved udgangen og klik 'Afbryd Mission' ikonet for at fortsætte. Afbryder du et andet sted, vil missionen afsluttes.\"\n  STR_FINAL_TLETH_MISSION: \"ENDELIG T'LETH MISSION{NEWLINE}RUMVÆSEN BY NIVEAU TRE\"\n  STR_TLETH_P3_BRIEFING: \"Enden er nær, herfra leder vi efter det Ultimative rumvæsen i krypten. Destruer de 8 energikilder til graven for at gøre en ende på rumvæsentruslen. Giv ikke op nu! Afbryder du, bliver missionen afsluttet.\"\n  STR_TLETH_P1: \"RUMVÆSEN BY NIVEAU ET\"\n  STR_TLETH_P2: \"RUMVÆSEN BY NIVEAU TO\"\n  STR_TLETH_P3: \"RUMVÆSEN BY NIVEAU TRE\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"INGEN LEDIGE UBÅDSBUNKERE TIL FARTØJSPRODUKTION!{SMALLLINE}Hver Flyvende Ubåd tildelt en base, overført til en base, købt eller konstrueret bruger én Ubåd Hal. Byg en ny Ubåd Hal eller overfør en ubåd til en anden base.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"INGEN LEDIGE UBÅDSBUNKERE TIL INDKØBET!{SMALLLINE}Hver Flyvende Ubåd tildelt en base, overført til en base, købt eller konstrueret bruger én Ubåd Hal. Byg en ny Ubåd Hal eller overfør en ubåd til en anden base.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"INGEN LEDIGE UBÅDSBUNKERE TIL OVERFØRSEL!{SMALLLINE}Hver Flyvende Ubåd tildelt en base, overført til en base, købt eller konstrueret bruger én Ubåd Hal. Byg en ny Ubåd Hal eller overfør en ubåd til en anden base.\"\n  STR_CANNOT_BUILD_HERE: \"DU KAN IKKE BYGGE HER!{SMALLLINE}Du er nødt til at bygge ved siden af en eksisterende kapsel.\"\n  STR_NO_FREE_ACCOMODATION: \"INGEN LEDIGE RUM!{SMALLLINE}Destinationsbasen har ikke plads nok i beboelsesområdet.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"IKKE NOK TILGÆNGELIGT ARBEJDSAREAL!{SMALLLINE}Byg et nyt værksted eller reducer arbejdet på andre projekter.\"\n  STR_NOT_ENOUGH_MONEY: \"IKKE NOK PENGE!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"IKKE NOK LAGERRUM!{SMALLLINE}Byg et nyt lagerrum eller overfør eksisterende udstyr til andre baser.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"IKKE NOK BEBOELSESRUM!{SMALLLINE}Byg nye beboelsesområder eller overfør personale til andre baser.\"\n  STR_LAUNCH_INTERCEPTION: \"PÅBEGYND ANGREB\"\n  STR_CRAFT: \"FARTØJ\"\n  STR_STATUS: \"STATUS\"\n  STR_BASE: \"BASE\"\n  STR_READY: \"KLAR\"\n  STR_OUT: \"UDE\"\n  STR_REPAIRS: \"REPARATIONER\"\n  STR_REFUELLING: \"TANKER OP\"\n  STR_REARMING: \"GENLADER\"\n  STR_TARGET: \"MÅL: {0}\"\n  STR_WAY_POINT: \"VIA-PUNKT\"\n  STR_ARE_YOU_SURE_CYDONIA: \"Er du sikker på, at du vil sende denne ubåd på en mission til T'leth?\"\n  STR_YES: \"JA\"\n  STR_NO: \"NEJ\"\n  STR_SELECT_DESTINATION: \"VÆLG DESTINATION\"\n  STR_CYDONIA: \"T'LETH\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"VÆLG PLACERING AF NY BASE\"\n  STR_RETURN_TO_BASE: \"RETURNER TIL BASEN\"\n  STR_SELECT_NEW_TARGET: \"VÆLG NYT MÅL\"\n  STR_PATROL: \"PATRULJÉR\"\n  STR_STATUS_: \"STATUS>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"BESKADIGET - RETURNERER TIL BASEN\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"LAVT BRÆNDSTOFNIVEAU - RETURNERER TIL BASEN\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"MISSION FULDENDT - RETURNERER TIL BASEN\"\n  STR_PATROLLING: \"PATRULJERER\"\n  STR_TAILING_UFO: \"FORFØLGER RUMVÆSENUBÅD\"\n  STR_INTERCEPTING_UFO: \"ANGRIBER RUMVÆSENUBÅD-{0}\"\n  STR_RETURNING_TO_BASE: \"RETURNERER TIL BASEN\"\n  STR_DESTINATION_UC_: \"DESTINATION: {0}\"\n  STR_BASE_UC: \"BASE>{ALT}{0}\"\n  STR_SPEED_: \"FART>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"MAKSIMAL FART>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"DYBDE>{ALT}{0}\"\n  STR_AIRBORNE: \"LUFTBÅREN\"\n  STR_VERY_LOW: \"LAVVANDET\"\n  STR_LOW_UC: \"NORMAL\"\n  STR_HIGH_UC: \"DYB\"\n  STR_VERY_HIGH: \"MEGET DYB\"\n  STR_FUEL: \"BRÆNDSTOF>{ALT}{0}\"\n  STR_WEAPON_ONE: \"VÅBEN-1>{ALT}{0}\"\n  STR_NONE_UC: \"INGEN\"\n  STR_ROUNDS_: \"SKUD>{ALT}{0}\"\n  STR_WEAPON_TWO: \"VÅBEN-2>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"FLYVENDE UBÅD\"\n  STR_BASE_: \"Base>{0}\"\n  STR_NAME_UC: \"NAVN\"\n  STR_AMMO_: \"AMMO>{ALT}{0}\"\n  STR_CREW: \"BESÆTNING\"\n  STR_EQUIPMENT_UC: \"UDSTYR\"\n  STR_ARMOR: \"PANSER\"\n  STR_MAX: \"MAKS>{ALT}{0}\"\n  STR_ROOKIE: \"Marineelev\"\n  STR_SQUADDIE: \"Marinekonstabel\"\n  STR_SERGEANT: \"Marineoverkonstabel\"\n  STR_CAPTAIN: \"Løjtnant\"\n  STR_COLONEL: \"Øverstbefalende\"\n  STR_COMMANDER: \"Kaptajn\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Vælg Kampenhed til {0}\"\n  STR_SORT_BY: \"SORTER EFTER...\"\n  STR_ORIGINAL_ORDER: \"OPRINDELIG RÆKKEFØLGE\"\n  STR_MISSIONS2: \"MISSIONER\"\n  STR_KILLS2: \"DRAB\"\n  STR_WOUND_RECOVERY2: \"SÅRGENDANNELSE\"\n  STR_SPACE_AVAILABLE: \"TILGÆNGELIG PLADS>{ALT}{0}\"\n  STR_SPACE_USED: \"ANVENDT PLADS>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"ANVENDT PLADS\"\n  STR_RANK: \"RANG\"\n  STR_WOUNDED: \"SÅRET\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Udstyr til {0}\"\n  STR_DEFENSE_VALUE: \"Forsvarsværdi\"\n  STR_HIT_RATIO: \"Træfningssucces\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}parat til{NEWLINE}landing nær{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"Begynd Mission?\"\n  STR_SELECT_ARMAMENT: \"Vælg Udrustning\"\n  STR_AMMUNITION_AVAILABLE: \"AMMUNITION TIL RÅDIGHED\"\n  STR_ARMAMENT: \"BEVÆBNING\"\n  STR_NOT_AVAILABLE: \"-\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"VÆLG PANSER FOR{NEWLINE}{ALT}{0}\"\n  STR_TYPE: \"TYPE\"\n  STR_PLASTIC_AQUA_ARMOR_UC: \"PLASTISK VAND PANSER\"\n  STR_ION_ARMOR_UC: \"ION PANSER\"\n  STR_MAGNETIC_ION_ARMOR_UC: \"MAGNETISK ION PANSER\"\n  STR_PLASTIC_AQUA_ARMOR_UFOPEDIA: \"Denne panser udnytter den nyligt fundne rumvæsensubstans, Vand-plastik, og sikrer at vores dykkere får en reel chance mod rumvæseninvasionen.\"\n  STR_ION_ARMOR_UFOPEDIA: \"En kraftfuld ny beskyttelse til dykkere, denne panser er drevet af en ION energikilde, og forstærker væsentligt farten og styrken af brugeren, den giver den bedste beskyttelse til dato for kamptropper.\"\n  STR_MAGNETIC_ION_ARMOR_UFOPEDIA: \"En forbedring til ION panser, der inkorporerer den Magnetiske System teknologi, der tillader fuld bevægelig frihed i undervandsmiljøer.\"\n  STR_SELECT_ARMOR: \"Vælg Panser\"\n  STR_NORTH: \"NORD\"\n  STR_NORTH_EAST: \"NORDØST\"\n  STR_EAST: \"ØST\"\n  STR_SOUTH_EAST: \"SYDØST\"\n  STR_SOUTH: \"SYD\"\n  STR_SOUTH_WEST: \"SYDVEST\"\n  STR_WEST: \"VEST\"\n  STR_NORTH_WEST: \"NORDVEST\"\n  STR_SELECT_ACTION: \"VÆLG HANDLING\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"FORTSÆT FORFØLGELSEN AF UFOEN\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"EFTERFØLG UDEN AT ANGRIBE\"\n  STR_VERY_LARGE: \"MEGET STOR\"\n  STR_LARGE: \"STOR\"\n  STR_MEDIUM_UC: \"MELLEM\"\n  STR_SMALL: \"LILLE\"\n  STR_VERY_SMALL: \"MEGET LILLE\"\n  STR_GROUNDED: \"LANDET\"\n  STR_DETECTED: \"Detekteret\"\n  STR_SIZE_UC: \"STØRRELSE\"\n  STR_ALTITUDE: \"DYBDE\"\n  STR_HEADING: \"RETNING\"\n  STR_SPEED: \"FART\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"CENTRER PÅ RUMVÆSENUBÅD-TID=5 Sek.\"\n  STR_TRACKING_LOST: \"SIGNAL MISTET\"\n  STR_REDIRECT_CRAFT: \"OMDIRIGER FARTØJ\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"FORTSÆT TIL SIDST KENDTE POSITION FOR RUMVÆSNERNES UBÅD\"\n  STR_UFO_: \"RUMVÆSENUBÅD-{0}\"\n  STR_ALIEN_BASE_: \"RUMVÆSENKOLONI-{0}\"\n  STR_CRASH_SITE_: \"NEDSTYRTNINGSOMRÅDE-{0}\"\n  STR_LANDING_SITE_: \"NEDSTYRTNINGSSTED-{0}\"\n  STR_WAY_POINT_: \"VIA-PUNKT-{0}\"\n  STR_TERROR_SITE: \"TERRORSTED-{0}\"\n  STR_ARTIFACT_SITE: \"UDSTYRSOMRÅDE-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}er ankommet{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"Patruljerer nu\"\n  STR_ALIEN_ORIGINS: \"Rumvæsnernes Oprindelse\"\n  STR_THE_ULTIMATE_THREAT: \"Den Ultimative Trussel\"\n  STR_TLETH_ALIEN_CITY: \"T'leth, Rumvæsnernes By\"\n  STR_UFOPAEDIA: \"UFOpædi\"\n  STR_XCOM_CRAFT_ARMAMENT: \"X-COM-FARTØJER & VÅBEN\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"UNDERVANDSVÅBENSYSTEMER\"\n  STR_WEAPONS_AND_EQUIPMENT: \"GENERELT UDSTYR\"\n  STR_ALIEN_ARTIFACTS: \"VANDUDSTYR\"\n  STR_BASE_FACILITIES: \"X-COM-FACILITETER\"\n  STR_ALIEN_LIFE_FORMS: \"RUMVÆSNER\"\n  STR_ALIEN_RESEARCH_UC: \"RUMVÆSENTEKNOLOGI\"\n  STR_UFO_COMPONENTS: \"NYE UNDERVANDSTEKNOLOGIER\"\n  STR_UFOS: \"RUMVÆSENUBÅDE\"\n  STR_SELECT_ITEM: \"VÆLG ENHED\"\n  STR_ACCELERATION: \"ACCELERATION>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"BRÆNDSTOFKAPACITET>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"VÅBENPLADSER>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"SKADE-KAPACITET>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"LASTRUM>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"KAPACITET FOR SVS>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Skade\"\n  STR_RANGE: \"Rækkevidde\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Præcision\"\n  STR_RE_LOAD_TIME: \"Ladetid\"\n  STR_SECONDS: \"{0}er\"\n  STR_DAMAGE_ARMOR_PIERCING: \"PANSERBRYDENDE\"\n  STR_DAMAGE_INCENDIARY: \"FOSFOR\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"HØJEKSPLOSIV\"\n  STR_DAMAGE_LASER_BEAM: \"GAUSS-STRÅLE\"\n  STR_DAMAGE_PLASMA_BEAM: \"LYDBØLGE\"\n  STR_DAMAGE_STUN: \"FRYS\"\n  STR_DAMAGE_MELEE: \"NÆRKAMP\"\n  STR_DAMAGE_ACID: \"SYRE\"\n  STR_DAMAGE_SMOKE: \"RØG\"\n  STR_SHOT_TYPE: \"TYPE\"\n  STR_ACCURACY_UC: \"TRÆFSIKKERHED\"\n  STR_TIME_UNIT_COST: \"TE-FORBRUG\"\n  STR_DAMAGE_UC: \"SKADE\"\n  STR_AMMO: \"AMMO\"\n  STR_SHOT_TYPE_AUTO: \"Auto\"\n  STR_SHOT_TYPE_SNAP: \"Hurtig\"\n  STR_SHOT_TYPE_AIMED: \"Sigtet\"\n  STR_CONSTRUCTION_TIME: \"Konstruktionstid\"\n  STR_CONSTRUCTION_COST: \"Konstruktionsomkostninger\"\n  STR_MAINTENANCE_COST: \"Vedligeholdelsesomkostninger\"\n  STR_LOW: \"Lav\"\n  STR_MEDIUM: \"Mellem\"\n  STR_HIGH: \"Høj\"\n  STR_CRAFT_WEAPON: \"Ubådsvåben\"\n  STR_CRAFT_AMMUNITION: \"Ubådssammunition\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Tungt Våbensystem\"\n  STR_WEAPON: \"Våben\"\n  STR_AMMUNITION: \"Ammunition\"\n  STR_EQUIPMENT: \"Udstyr\"\n  STR_ALIEN_CORPSE: \"Rumvæsenlig\"\n  STR_UFO_COMPONENT: \"RUMVÆSENUBÅD-komponent\"\n  STR_PERSONAL_ARMOR: \"Personlig vest\"\n  STR_RAW_MATERIALS: \"Råmaterialer\"\n  STR_HWP_SOLID_HARPOON_BOLTS: \"Massive Harpun Bolte\"\n  STR_ALIEN: \"Rumvæsen\"\n  STR_AQUATOID: \"Aquatoid\"\n  STR_GILLMAN: \"Gællemand\"\n  STR_LOBSTERMAN: \"Hummermand\"\n  STR_TASOTH: \"Tasoth\"\n  STR_CALCINITE: \"Calcinite\"\n  STR_DEEP_ONE: \"Dybhavsskabning\"\n  STR_BIODRONE: \"Biodrone\"\n  STR_TENTACULAT: \"Tentaculat\"\n  STR_TRISCENE: \"Triscene\"\n  STR_HALLUCINOID: \"Hallucinoid\"\n  STR_XARQUID: \"Xarquid\"\n  STR_ZOMBIE: \"Zombie\"\n  STR_LIVE_COMMANDER: \"Øverstbefalende\"\n  STR_LIVE_NAVIGATOR: \"Navigatør\"\n  STR_LIVE_MEDIC: \"Samarit\"\n  STR_LIVE_TECHNICIAN: \"Tekniker\"\n  STR_LIVE_SQUAD_LEADER: \"Gruppeleder\"\n  STR_LIVE_SOLDIER: \"Soldat\"\n  STR_LIVE_TERRORIST: \"Terrorist\"\n  STR_AQUATOID_COMMANDER: \"Aquatoid - Øverstbefalende\"\n  STR_AQUATOID_NAVIGATOR: \"Aquatoid - Navigatør\"\n  STR_AQUATOID_MEDIC: \"Aquatoid - Samarit\"\n  STR_AQUATOID_TECHNICIAN: \"Aquatoid - Tekniker\"\n  STR_AQUATOID_SQUAD_LEADER: \"Aquatoid - Gruppeleder\"\n  STR_AQUATOID_SOLDIER: \"Aquatoid - Soldat\"\n  STR_GILLMAN_COMMANDER: \"Gællemand Kommandør\"\n  STR_GILLMAN_TECHNICIAN: \"Gællemand Teknikker\"\n  STR_GILLMAN_SQUAD_LEADER: \"Gællemand Gruppeleder\"\n  STR_GILLMAN_SOLDIER: \"Gællemand Soldat\"\n  STR_LOBSTERMAN_COMMANDER: \"Hummermand - Øverstbefalende\"\n  STR_LOBSTERMAN_NAVIGATOR: \"Hummermand - Navigatør\"\n  STR_LOBSTERMAN_TECHNICIAN: \"Hummermand - Tekniker\"\n  STR_LOBSTERMAN_SQUAD_LEADER: \"Hummermand - Gruppeleder\"\n  STR_LOBSTERMAN_SOLDIER: \"Hummermand - Soldat\"\n  STR_TASOTH_SQUAD_LEADER: \"Tasoth Gruppeleder\"\n  STR_TASOTH_SOLDIER: \"Tasoth - Soldat\"\n  STR_CALCINITE_TERRORIST: \"Calcinite - Terrorist\"\n  STR_DEEP_ONE_TERRORIST: \"Dybhavsterrorist\"\n  STR_BIODRONE_TERRORIST: \"Biodroneterrorist\"\n  STR_TENTACULAT_TERRORIST: \"Tentaculat - Terrorist\"\n  STR_TRISCENE_TERRORIST: \"Triscene - Terrorist\"\n  STR_HALLUCINOID_TERRORIST: \"Hallucinoid - Terrorist\"\n  STR_XARQUID_TERRORIST: \"Xarquid - Terrorist\"\n  STR_ION_BEAM_ACCELERATORS: \"Ion-Stråle Acceleratorer\"\n  STR_MAGNETIC_NAVIGATION: \"Magnetisk Navigation\"\n  STR_ALIEN_SUB_CONSTRUCTION: \"Rumvæsenubådskonstruktion\"\n  STR_ALIEN_CRYOGENICS: \"Rumvæsen Kryogener\"\n  STR_ALIEN_CLONING: \"Rumvæsenkloning\"\n  STR_ALIEN_LEARNING_ARRAYS: \"Rumvæsen Læringssystemer\"\n  STR_ALIEN_IMPLANTER: \"Rumvæsen Implanterer\"\n  STR_EXAMINATION_ROOM: \"Undersøgelseslokale\"\n  STR_AQUA_PLASTICS: \"Vandplastik\"\n  STR_ALIEN_REANIMATION_ZONE: \"Rumvæsen Genoplivningszone\"\n  STR_PLASTIC_AQUA_ARMOR: \"Plastisk Vand-Panser\"\n  STR_ION_ARMOR: \"Ion Panser\"\n  STR_MAGNETIC_ION_ARMOR: \"Mag. Ion Panser\"\n  STR_HWP_AQUA_JET_MISSILES: \"Vand Jet Torpedoer\"\n  STR_HWP_DISPLACER_PWT: \"P.W. Torpedo\"\n  STR_GAUSS_TECH: \"Gauss Teknologi\"\n  STR_NEW_FIGHTER_FLYING_SUB: \"Ny Jæger Flyvende Ubåd\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Nyt Kampfly/Transportfly\"\n  STR_THE_LATEST_FLYING_SUB: \"Den Seneste Flyvende Ubåd\"\n  STR_ARMOR_PIERCING: \"PANSERBRYDENDE\"\n  STR_COELACANTH_GAS_CANNON: \"Coelacanth/G. Kanon\"\n  STR_COELACANTH_AQUA_JET: \"Coelacanth/Vand Jet\"\n  STR_COELACANTH_GAUSS: \"Coelacanth/Gauss\"\n  STR_DISPLACER_SONIC: \"Fortrænger/Lydbølge\"\n  STR_DISPLACER_PWT: \"Fortrænger/P.W.T.\"\n  STR_AJAX_LAUNCHER: \"Ajax-raketstyr\"\n  STR_DUP_HEAD_LAUNCHER: \"D.U.P. Hoved Raketstyr\"\n  STR_CRAFT_GAS_CANNON: \"Fartøj Gaskanon\"\n  STR_PWT_CANNON: \"P.W.T. Kanon\"\n  STR_GAUSS_CANNON: \"Gauss Kanon\"\n  STR_GAUSS_CANNON_AMMO: \"Gauss Kanon - ammo\"\n  STR_SONIC_OSCILLATOR: \"Lydoscillator\"\n  STR_AJAX_TORPEDOES: \"Ajax Torpedoer\"\n  STR_DUP_HEAD_TORPEDOES: \"D.U.P. Hoved Torpedoer\"\n  STR_CRAFT_GAS_CANNON_ROUNDS_X50: \"Gasskud(x50)\"\n  STR_SONIC_WAVE: \"Lydbølge\"\n  STR_PULSE_WAVE_TORPEDOES: \"P.W.T. ammo\"\n  STR_SOLDIER: \"Dykker\"\n  STR_SCIENTIST: \"Forsker\"\n  STR_ENGINEER: \"Tekniker\"\n  STR_NORTH_ATLANTIC: \"Nordatlanterhavet\"\n  STR_SOUTH_ATLANTIC: \"Sydatlanterhavet\"\n  STR_NORTH_PACIFIC: \"Nordlige Stillehav\"\n  STR_SOUTH_PACIFIC: \"Sydlige Stillehav\"\n  STR_MEDITERRANEAN: \"Middelhavet\"\n  STR_SOUTH_CHINA_SEA: \"Sydkinesiske Hav\"\n  STR_INDIAN_OCEAN: \"Indiske Ocean\"\n  STR_THE_EAST_SEA: \"Det Japanske Hav\"\n  STR_NORTH_SEA: \"Nordsøen\"\n  STR_CARRIBEAN: \"Caribien\"\n  STR_ANTARCTIC: \"Antarktis\"\n  STR_ARCTIC: \"Arktis\"\n  STR_EURASIA: \"Euroasien\"\n  STR_NORTH_AMERICA: \"Nordamerika\"\n  STR_AFRICA: \"Afrika\"\n  STR_MAXIMUM_SPEED: \"Maksimal Fart\"\n  STR_TRANSMISSION_RESOLVER_UC: \"TRANSMISSIONSAFHJÆLPER\"\n  STR_TRITON: \"TRITON\"\n  STR_HAMMERHEAD: \"HAMMERHOVED\"\n  STR_LEVIATHAN: \"LEVIATHAN\"\n  STR_BARRACUDA: \"BARRACUDA\"\n  STR_MANTA: \"MANTA\"\n  STR_UFO: \"RUMVÆSENUBÅD\"\n  STR_AJAX: \"AJAX\"\n  STR_DUP_HEAD: \"D.U.P. HOVED\"\n  STR_CRAFT_GAS_CANNON_UC: \"FARTØJSGASKANON\"\n  STR_PWT_CANNON_UC: \"P.W.T.-KANON\"\n  STR_GAUSS_CANNON_UC: \"GAUSSKANON\"\n  STR_SONIC_OSCILLATOR_UC: \"LYDOSCILLATOR\"\n  STR_DAMAGE_CAPACITY: \"Skadeskapacitet\"\n  STR_WEAPON_POWER: \"Våbenkraft\"\n  STR_WEAPON_RANGE: \"Våbenrækkevidde\"\n  STR_AIR_LOCK: \"Luftsluse\"\n  STR_LABORATORY: \"Laboratorium\"\n  STR_WORKSHOP: \"Værksted\"\n  STR_STANDARD_SONAR: \"Standardsonar\"\n  STR_WIDE_ARRAY_SONAR: \"Langtrækkende sonar\"\n  STR_TORPEDO_DEFENSES: \"Torpedoforsvar\"\n  STR_GENERAL_STORES: \"Lager\"\n  STR_ALIEN_CONTAINMENT: \"Opb.rum til rumvæsner\"\n  STR_GAUSS_DEFENSES: \"Gauss-forsvar\"\n  STR_SONIC_DEFENSES: \"Lydforsvar\"\n  STR_PWT_DEFENSES: \"P.W.T. Forsvar\"\n  STR_BOMBARDMENT_SHIELD: \"Bombningsskjold\"\n  STR_MC_GENERATOR: \"M.K. Generator\"\n  STR_MC_LAB: \"M.K.-Lab\"\n  STR_TRANSMISSION_RESOLVER: \"Transmissionsafhjælper\"\n  STR_SUB_PEN: \"Undervandsbunker\"\n  STR_USA: \"USA\"\n  STR_ALASKA: \"ALASKA\"\n  STR_EU_SYNDICATE: \"SYNDIKAT EUROPA\"\n  STR_ARABIAN_BLOC: \"DEN ARABISKE BLOK\"\n  STR_EGYPTIAN_CARTEL: \"DET ÆGYPTISKE KARTEL\"\n  STR_AFRICA_CORP: \"FIRMA AFRIKA\"\n  STR_BRAZILIAN_UNION: \"DEN BRASILIANSKE UNION\"\n  STR_NEW_MEXICO: \"NY MEXICO\"\n  STR_ASIAN_COALITION: \"DEN ASIATISKE KOALITION\"\n  STR_SCANDINAVIA: \"SKANDINAVIA\"\n  STR_NEO_JAPAN: \"NEO-JAPAN\"\n  STR_FREE_CHINA: \"FRIT KINA\"\n  STR_AUSTRALASIA: \"AUSTRALASIEN\"\n  STR_FED_KOREA: \"FØD. KOREA\"\n  STR_EURASIA_UC: \"EUROASIA\"\n  STR_ICELANDIC_UNION: \"ISLANDSKE UNION\"\n  STR_TANK: \"Undervandsvåbensystemer\"\n  STR_CIVILIAN: \"Civil\"\n  STR_JAN: \"Jan\"\n  STR_FEB: \"Feb\"\n  STR_MAR: \"Mar\"\n  STR_APR: \"Apr\"\n  STR_MAY: \"Maj\"\n  STR_JUN: \"Jun\"\n  STR_JUL: \"Jul\"\n  STR_AUG: \"Aug\"\n  STR_SEP: \"Sep\"\n  STR_OCT: \"Okt\"\n  STR_NOV: \"Nov\"\n  STR_DEC: \"Dec\"\n  STR_INTERNATIONAL_RELATIONS: \"Internationale Relationer\"\n  STR_COUNTRY: \"Land\"\n  STR_FUNDING: \"Midler\"\n  STR_CHANGE: \"Ændr\"\n  STR_WEAPON_SYSTEMS: \"VÅBENSYSTEMER\"\n  STR_HWPS: \"SVS'er\"\n  STR_DAMAGE_UC_: \"ØDELÆGGELSE>{ALT}{0}\"\n  STR_AIR_LOCK_UFOPEDIA: \"Luftslusen gør det muligt for udstyr og personer at komme ind og ud af den undersøiske base. Det er altid den første konstruktion på en ny lokalitet. Området omkring luftslusen er sårbar over for angreb fra potentielle fjendtlige styrker.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Hvert beboelsesområde tilbyder en kapacitet på 50 personer. Faciliteterne er noget primitive og funktionelle.\"\n  STR_LABORATORY_UFOPEDIA: \"50 forskerer kan arbejde i en enkelt laboratorieblok. Laboratorier er udstyret med alle de seneste teknologier indenfor forskning om materialer, biokemi og våben. X-Com har adgang til alle de bedste forskningslaboratorier over hele verden, både civile og militære.\"\n  STR_WORKSHOP_UFOPEDIA: \"Et værksted indeholder al det nødvendige udstyr til at fremstille udstyr baseret på de seneste design fra videnskabslaboratorierne. 50 teknikere kan anvende et værksted på samme tid, udstyr under konstruktion vil også bruge plads.\"\n  STR_STANDARD_SONAR_UFOPEDIA: \"Et sonarsystem har en effektiv rækkevidde på over 450 kilometer på de fleste dybder og er forbundet til  geostationære satellitnet for overfladeanalyse. Hver skanner har en 10 % sandsynlighed for at detektere et neddykket eller luftbåren fartøj per 30 minutters skanningscyklus.\"\n  STR_WIDE_ARRAY_SONAR_UFOPEDIA: \"Et langtrækkende sonarsystem har en effekt rækkevidde på over 700 kilometer på alle dybder og er forbundet til geostationære satellitnet for overfladeanalyse. Hver skanner har en 20 % sandsynlighed for at detektere et neddykket eller luftbåren fartøj per 30 minutters skanningscyklus.\"\n  STR_TORPEDO_DEFENSES_UFOPEDIA: \"Torpedoforsvarssystemer tilbyder beskyttelse mod angreb fra fjendtlige neddykkede fartøjer, som forsøger at trænge ind i basen.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"Alt udstyr, våbensystemer, ammunition, opsamlede materialer og undervandsvåbensystemer placeres i lagerrum, inklusive udstyr for dine ubåde i bunkere.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"Levende rumvæsner vil kræve særlige opbevaringsfaciliteter for at holde dem. Disse enheder opretholder deres livsfunktioner og sætter deres kamppotentiale til nul. Opbevaringsfaciliteten kan holde 10 rumvæsenarter i isolationsenheder.\"\n  STR_GAUSS_DEFENSES_UFOPEDIA: \"Gauss forsvaret giver den seneste og mest effektive beskyttelse mod angreb fra fjendtlige ubåde.\"\n  STR_SONIC_DEFENSES_UFOPEDIA: \"Lydoscillatorforsvar tilbyder funktionsrig og effektiv beskyttelse mod angribere.\"\n  STR_PWT_DEFENSES_UFOPEDIA: \"Puls Bølge Torpedoer giver det mest effektive forsvar mod rumvæsen angreb. Disse missiler har supertætpakkede sprænghoveder, som kan penetrere alt kendt panser. De magnetiske bølger de producerer lammer elektronisk forsvar.\"\n  STR_BOMBARDMENT_SHIELD_UFOPEDIA: \"Trykbombardementskjoldet beskytter basen mod rumvæsenundervandsfartøjer der forsøger at lægge til og opsætter et genlydende område, der holder angribene ubåde væk længe nok til at forsvarssystemerne kan affyre flere gange. I praksis fordobler dette effektiviteten af ethvert forsvarssystem, som allerede er tilstede.\"\n  STR_MC_GENERATOR_UFOPEDIA: \"Siden rumvæsenubåde udnytter Molekylær Kontrol Teknologi til at detektere tilstedeværelsen af levende væsner, vil brugen af en negativ M.K. udsender lægge et tæppe henover en base, med et uigennemtrængeligt skjold, til at forvirre rumvæsnerne og skjule vores tilstedeværelse.\"\n  STR_MC_LAB_UFOPEDIA: \"Det molekylære kontrollaboratorium kan implantere og træne op til ti dykkere på samme tid. Implantater installeres kirurgisk i hjernen på dykkerne. Omfattende træning gør det muligt for dem at udnytte deres implantater. Implantatevner bruges sammen med en molekylær enhed og kan bruges til angreb under kamp.\"\n  STR_TRANSMISSION_RESOLVER_UFOPEDIA: \"Rumvæsenkommunikation udnytter det Molekylære kontrolimplantatnetværk som rumvæsnerne har bygget. Transmissionsafhjælperfacliteten opfanger rumvæsenubådstransmissioner og afkoder informationen. Dette vil vise typen af rumvæsenubåd, rumvæsenracen og aktivitetstypen som finder sted.\"\n  STR_SUB_PEN_UFOPEDIA: \"Hver bunker kan rumme en ubåd. Der er faciliteter til vedligehold, tankning og reparation af X-Coms ubådsflåde. Hver Flyvende ubåd stationeret i en base skal have tildelt en ledig bunker, der ikke kan benyttes af andre Ubåde, selv ikke hvis ubåden er ude på en mission.\"\n  STR_DART_PISTOL_UFOPEDIA: \"X-Com dartpistolen er en lille, præcis, kraftig enhed med et 12 hule dart-ammunitionsmagasin. Dartene affyres med en gaspatron i ammunitionskammeret.\"\n  STR_JET_HARPOON_UFOPEDIA: \"Denne vandriffel er præcis og kraftfuld. Den affyrer hule stårharpuner fra forsejlede pakke med 10. Hver harpun har sit eget gasreservoir.\"\n  STR_GAS_CANNON_UFOPEDIA: \"Sværvægteren indenfor gasteknologifamilien, denne kanon affyrer massive bolte, nogen med HE eller fosforspidse. Et favoritvåben blandt erfarne dykkere.\"\n  STR_HYDRO_JET_CANNON_UFOPEDIA: \"Hydro-Jet Kanoner er et tungt infanterivåbensystem. Kanonen affyrer magnesiumdrevne mini-torpedoer. Selvom den er kraftfuld, er Hydro-JetKanonen en klodset og uhåndterlig enhed, kun egnet til undervandsbrug.\"\n  STR_TORPEDO_LAUNCHER_UFOPEDIA: \"En rigtig sværvægter, dette store raketstyr affyrer tre typer torpedoer, hver med deres egen fremdriftsenhed. Et altødelæggende våben, med den ene ulempe at den har manuel genladning. Tilgængelige ammunitionstyper inkluderer store og små højeksplosiver og torpedoer med fosforspids, alle udelukkende til undervands brug.\"\n  STR_GAUSS_PISTOL_UFOPEDIA: \"Gauss pistolen benytter accelleret-partikelteknologi, en nyudvikling indenfor moderne våben. Den er hurtig, præcis og fungerer over- og under vandet. Gauss-teknologien er en videreudvikling fra Plasma-teknologien, som vi tillærte os gennem den forrige krig.\"\n  STR_GAUSS_PISTOL_CLIP_UFOPEDIA: \"Gauss pistolen benytter accelleret-partikelteknologi, en nyudvikling indenfor moderne våben. Den er hurtig, præcis og fungerer over- og under vandet. Gauss-teknologien er en videreudvikling fra Plasma-teknologien, som vi tillærte os gennem den forrige krig.\"\n  STR_GAUSS_RIFLE_UFOPEDIA: \"Et skridt udover Gauss pistolen, har riflen en betragtelig gennemslagskraft, med dets dobbelt-partikelacceleratorer. Til at erstatte Plasmasystemets Elerium-afhængighed, har vi benyttet en mikropartikelaccelerator som genererer en strøm af anti-protoner.\"\n  STR_GAUSS_RIFLE_CLIP_UFOPEDIA: \"Et skridt udover Gauss pistolen, har riflen en betragtelig gennemslagskraft, med dets dobbelt-partikelacceleratorer. Til at erstatte Plasmasystemets Elerium-afhængighed, har vi benyttet en mikropartikelaccelerator som genererer en strøm af anti-protoner.\"\n  STR_HEAVY_GAUSS_UFOPEDIA: \"Den tunge Gauss er besværlig, men ekstremt effektiv. Den opererer med 3 partikelacceleratorer og er næsten ustoppelig. Anti-proton strømmen er indeholdt i en galliumarsenid-skal som imploderer ved impakt, og udløser antistoffet.\"\n  STR_HEAVY_GAUSS_CLIP_UFOPEDIA: \"Den tunge Gauss er besværlig, men ekstremt effektiv. Den opererer med 3 partikelacceleratorer og er næsten ustoppelig. Anti-proton strømmen er indeholdt i en galliumarsenid-skal som imploderer ved impakt, og udløser antistoffet.\"\n  STR_MAGNA_BLAST_GRENADE_UFOPEDIA: \"Denne standardhåndgranat har en præcis og sofistikeret tidsudløser til præcisionskontrol.\"\n  STR_DYE_GRENADE_UFOPEDIA: \"Farvegranater har dobblet anvendelse, brugbare til at lave dække i udsatte situationer. Fungerer både i vand- og på landmiljøer, farven er skudt ud som en partikelsky, og laver et blæksprutteagtig blæksprøjt i vand eller en tyk luftbåren sky på land.\"\n  STR_PARTICLE_DISTURBANCE_GRENADE_UFOPEDIA: \"En nærhedsfølsom granat der kan kastes som en almindelig granat, men reagerer på bevægelse i nærheden, efter udløseren er aktiveret. Færdighed og træning er krævet, for at benytte disse ordentligt.\"\n  STR_MAGNA_PACK_EXPLOSIVE_UFOPEDIA: \"Denne eksplosiv burde kun benyttes til nedrivningsformål. Men tidligere erfaringer har vist, at disse kraftfulde eksplosivpakker er ideale våben til at udluge rumvæsner. Trykbølgeradiusen er stor, så sørg for at ingen dykkere er indenfor minimumssikkerhedsafstanden.\"\n  STR_PARTICLE_DISTURBANCE_SENSOR_UFOPEDIA: \"Denne anordning benytter en bred vifte af detektorer og advancerede computersystemer for at identificere fjendtlige enheder i bevægelse. Klik på Forstyrrelse Sensor ikonet på den taktiske skærm. Vælg 'Brug Sensor' fra menuen. Sensorskærmen viser en pil i midten, som er retningen dykkeren peger (nord er i toppen). Pletterne viser hvilke enheder der har bevæget sig for nyligt. Store enheder, eller hurtige enheder, vil producere større pletter. Statiske enheder vil ikke være synlige.\"\n  STR_MEDI_KIT_UFOPEDIA: \"Vend mod den sårede X-Com agent for at bruge denne eller stå henover kroppen på den bedøvede dykker.{NEWLINE}HELBRED> Rød indikerer sår. Vælg kropsdel og klik på 'Helbred' knappen. Et fatalt sår vil blive helet og liv genoprettet.{NEWLINE}STIMULANS> Genopretter energi og genopliver bedøvede dykkere. For at genoplive en bevidstløs dykker skal du stå direkte over kroppen.{NEWLINE}SMERTESTILLENDE> Genopretter moralen hos sårede dykkerer.\"\n  STR_MC_DISRUPTOR_UFOPEDIA: \"Det ultimative i M.K. teknologi. Dette kan kun benyttes af dykkere med M.K. færdigheder. Klik på Afbryderen, vælg en type angreb, og vælg en enhed som mål, med pilen. Der er to typer af Afbryder angreb:{NEWLINE}BLOKERINGS IMPLANTAT> Hvis succesfuldt bliver enheden forvirret og kan gå i panik.{NEWLINE}KONTROL IMPLANTAT> Hvis succesfuldt overtager du kontrollen med den fjendtlige enhed.\"\n  STR_THERMAL_TAZER_UFOPEDIA: \"Denne anordning kan kun bruges i nærkamp, men vil lamme en levende organisme uden at slå den ihjel ved at fryse skabningen.\"\n  STR_VIBRO_BLADE_UFOPEDIA: \"Vibrobladet er et langt skarpt knivblad af titanium, som drejer med over 6000 o/m, dette udstyr kan flække selv den hårdste panser. Energikilden er en rumvæsenopfindelse, vores forhenværende forsøg på at bygge disse genstande mislykkedes grusomt, vores blade roterede for langsomt eller eksploderede under tryk.\"\n  STR_THERMIC_LANCE_UFOPEDIA: \"Den Termiske Lanse er en logisk forlængelse af Vibrobladsteknologien. Bladet drejer rundt ved høj fart og en Zrbite energikilde overopheder bladet til at kunne skære gennem panser som en varm kniv gennem smør.\"\n  STR_HEAVY_THERMIC_LANCE_UFOPEDIA: \"Den Tunge Termiske Lanse er en mere kraftfuld version af TL'en. Dobbeltvarmekilden og den ekstremt høje rotationshastighed, betyder at den Tunge Termiske lanse er nærmest ustoppeligt mod ethvert materiale.\"\n  STR_SONIC_CANNON_UFOPEDIA: \"Lydkanonen er den meste effektive blandt lydbølgevåbene. Den har en lydoscillator i et højere interval og et større efterklangskammer end Blasta'en. Kanonen har også et pulsdetoneringssystem, der ændrer ultralydbølgen efter modulation for at fremstille effektive lydchok.\"\n  STR_CANNON_POWER_CLIP_UFOPEDIA: \"Denne kompakte enhed bruges som ammunition for en lydkanon. Den indeholder en lille mængde Zrbite.\"\n  STR_SONIC_BLASTA_RIFLE_UFOPEDIA: \"En mere kraftfuldt Lyd anordning. Ikke engang kulstofrigt stål kan modstå dette våben. Den enormt kompakte bølgeudsender er styrkes af en super strømførende forstærker, der forøger kraften i dette våben.\"\n  STR_BLASTA_POWER_CLIP_UFOPEDIA: \"Disse små objekter bruges som energikilder for en Lyd Riffel, et potent rumvæsenvåben, og indeholder en lille mængde Zrbite.\"\n  STR_SONIC_PISTOL_UFOPEDIA: \"Lydpistoler er et rumvæsenvåben baseret på ultralyd-lydbølger, som kan blødgøre knogler på sekunder. Ultralyd-lydbølgerne ligger i en skala udenfor menneskets høreevne.\"\n  STR_PISTOL_POWER_CLIP_UFOPEDIA: \"Energikilde for rumvæsnernes kompakte Lyd Pistol. Indeholder Zrbite - rumvæsnernes energikilder.\"\n  STR_DISRUPTOR_PULSE_LAUNCHER_UFOPEDIA: \"Dette er et rumvæsen, kun til undervandsbrug, styret våben, affyrende selvdrevne 'Afbryder Projektiler'. Når du klikker for at affyre våbnet, genererer det 'landmærker' som Projektilet følger. Når du har sat nok landmærker, klik på affyr ikonet.\"\n  STR_DISRUPTOR_AMMO_UFOPEDIA: \"Denne anordning er et Afbryder Puls Projektil udstyret med en onboard computerstyringssystem. Det affyres fra en Afbryder Puls Raketstyr.\"\n  STR_THERMAL_SHOK_LAUNCHER_UFOPEDIA: \"En lille Termisk Chok raketstyr som affyrer kemiske frysebomber. Meget nyttig til at fange levende rumvæsner.\"\n  STR_THERMAL_SHOK_BOMB_UFOPEDIA: \"Den Termiske Chok bombe benyttes til at fange levende mennesker, men kan også bruges mod rumvæsenracer. Den affyres fra en Termisk Chok Raketstyr.\"\n  STR_SONIC_PULSER_UFOPEDIA: \"Denne anordning virker på samme måde som en standard granat - bortset fra at den er meget mere kraftfuld. Granaten benytter en enkelt puls lydtrykbølge, som udledes samtidigt i alle retninger.\"\n  STR_MC_READER_UFOPEDIA: \"Inden i kroppene hos rumvæsenerne har vi fundet små kirurgiske implanterede enheder. Disse er kontrolimplantater designet af aquatoider til at sikre konstant levering af information fra slagmarken, selv over store afstande. Den molekylære kontrollæser er en kommunikationsenhed, som bruges til at hente information direkte fra M.K.-implantater. X-Com-enheder kan bruge denne enhed i kampsituationer til at se et rumvæsens karakteristika. Vælg indstillingen »brug«. Klik derefter på et rumvæsen med markøren.\"\n  STR_SURVEY_SHIP: \"Opmålingsfartøj\"\n  STR_ESCORT: \"Eskorte\"\n  STR_CRUISER: \"Krydser\"\n  STR_HEAVY_CRUISER: \"Tung Krydser\"\n  STR_HUNTER: \"Jæger\"\n  STR_BATTLESHIP: \"Slagskib\"\n  STR_DREADNOUGHT: \"Panserskib\"\n  STR_FLEET_SUPPLY_CRUISER: \"Flådeforsyningsskib\"\n  MAP_SEABED: \"Havbund\"\n  MAP_PIPES: \"Forskningsfacilitet\"\n  MAP_PLANE: \"Nedstyrtet Fly\"\n  MAP_ATLAN: \"Atlantis\"\n  MAP_MU: \"Mayatempel\"\n  MAP_GAL: \"Sunket Galleon\"\n  MAP_MSUNK: \"Sunket Færge\"\n  MAP_VOLC: \"Vulkansk\"\n  MAP_CORAL: \"Koral\"\n  MAP_PORT: \"Havn\"\n  MAP_ISLAND: \"Ø\"\n  MAP_CARGO: \"Lastskib\"\n  MAP_LINERT: \"Krydstogtskib P1\"\n  MAP_LINERB: \"Krydstogtskib P2\"\n  MAP_ALART: \"Artefakt P1\"\n  MAP_GRUNGE: \"Artefakt P2\"\n  MAP_ENTRY: \"Koloni P1\"\n  MAP_A_BASE: \"Koloni P2\"\n  MAP_ALSHIP: \"T'leth P1\"\n  MAP_LEVEL: \"T'leth P2\"\n  MAP_CRYPT: \"T'leth P3\"\n  MAP_XBASES: \"X-Com-Base\"\n  STR_MIXED_CREW: \"Blandet Besætning\"\n  STR_MIXED_CREW_2: \"Blandet Besætning 2\"\n  STR_RATING: \"BEDØMMELSE> {0}\"\n  STR_RATING_TERRIBLE: \"FORFÆRDELIGT!\"\n  STR_RATING_POOR: \"DÅRLIG!\"\n  STR_RATING_OK: \"OK\"\n  STR_RATING_GOOD: \"GODT!\"\n  STR_RATING_EXCELLENT: \"FANTASTISK!\"\n  STR_SCORE: \"POINT\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"DEN MÅNEDLIGE RAPPORT FOR X-COM\"\n  STR_MONTH: \"Måned> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"Komiteen med økonomisk støttende organisationer er generelt tilfredse med din fremgang indtil videre.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"Komiteen med økonomisk støttende organisationer er meget tilfredse med din glimrende fremgang. Fortsæt det gode arbejde.\"\n  STR_COUNCIL_IS_DISSATISFIED: \"Komiteen med økonomisk støttende organisationer er utilfredse med din indsats. Du må håndtere den fremmede trussel mere effektivt eller risikere, at finansieringen af X-Com stoppes.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"Du har fejlet i at håndtere truslen fra rumvæsnerne, og rådet af økonomisk støttende nationer har desværre besluttet sig for at lukke X-Com ned. Hver nation vil selv tage sig af problemet på måder de selv finder fordelagtige. Vi kan kun håbe, at vi i sidste ende får en ordning med disse fremmede styrker, og at befolkningen som helhed kan affinde sig med de fremmede.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} er særlig tilfreds med din evne til at håndtere den lokalbestemte trussel og har indvilget i at øge deres bidrag.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} er særligt tilfredse med dine fremskridt i at håndtere rumvæsnernes indtrængen lokalt på deres område og er gået med til at øge deres bidrag. \"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} og {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} er utilfreds med din evne til at håndtere rumvæsnernes aktivitet i deres have og har besluttet at reducere deres økonomiske bidrag.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} er ikke tilfreds med din evne til at håndtere rumvæsnernes aktivitet i deres have og har derfor besluttet at reducere deres bidrag.\"\n  STR_KNOTS: \"{0} knob\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} har underskrevet en samarbejdsaftale med rumvæsnerne og har trukket sin støtte til X-Com.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} har underskrevet en samarbejdsaftale med rumvæsnerne og har trukket sin støtte til X-Com.\"\n  STR_MONTHLY_RATING: \"Månedlig Bedømmelse> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Ændring i bidrag> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"Rådet af økonomisk støttende nationer er ikke tilfredse med din finansielle position. Du er blevet pålagt at reducere din gæld til under $1 million, ellers vil X-Com blive nedlagt.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"SUB-PARTIKEL TRANSMISSIONER AFHJULPET\"\n  STR_CRAFT_TYPE: \"UBÅDSTYPE\"\n  STR_RACE: \"RACE\"\n  STR_MISSION: \"MISSION\"\n  STR_ZONE: \"ZONE\"\n  STR_ALLOCATE_RESEARCH: \"Start forskning\"\n  STR_ALLOCATE_MANUFACTURE: \"Start produktion\"\n  STR_AZORES: \"Azorerne\"\n  STR_REYKJAVIK: \"Reykjavik\"\n  STR_BERMUDA: \"Bermuda\"\n  STR_NEW_YORK: \"New York\"\n  STR_BOSTON: \"Boston\"\n  STR_FORT_SEVERN: \"Severn Fortet\"\n  STR_DAKAR: \"Dakar\"\n  STR_RECIFE: \"Recife\"\n  STR_ACCRA: \"Accra\"\n  STR_ASCENSION_ISLAND: \"Ascension Ø\"\n  STR_TRINIDADE_ISLAND: \"Trindade\"\n  STR_FALKLAND_ISLAND: \"Falklandsøerne\"\n  STR_CANARY_ISLANDS: \"Kanarieøerne\"\n  STR_ANCHORAGE: \"Anchorage\"\n  STR_ST_LAWRENCE_ISLAND: \"St Lawrence-ø\"\n  STR_SAN_FRANCISCO: \"San Francisco\"\n  STR_MIDWAY_ISLAND: \"Midway\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_TASMANIA: \"Tasmanien\"\n  STR_HAWAII: \"Hawaii\"\n  STR_FIJI: \"Fiji\"\n  STR_TONGA: \"Tonga\"\n  STR_EASTER_ISLAND: \"Påskeøen\"\n  STR_GALAPAGOS_ISLAND: \"Galapagosøerne\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_SOLOMON_ISLAND: \"Solomonø\"\n  STR_CRETE: \"Kreta\"\n  STR_LISBON: \"Lissabon\"\n  STR_PORT_SAID: \"Port Said\"\n  STR_MARSEILLES: \"Marseilles\"\n  STR_TRIPOLI: \"Tripoli\"\n  STR_MANILA: \"Manila\"\n  STR_HONG_KONG: \"Hong Kong\"\n  STR_SINGAPORE: \"Singapore\"\n  STR_BANGKOK: \"Bangkok\"\n  STR_DARWIN: \"Darwin\"\n  STR_BOMBAY: \"Bombay\"\n  STR_SAYCHELLES_ISLAND: \"Seychellerne\"\n  STR_MALDIVE_ISLAND: \"Maldiverne\"\n  STR_SRI_LANKA: \"Sri Lanka\"\n  STR_MAURITIUS: \"Mauritius\"\n  STR_TOKYO: \"Tokyo\"\n  STR_SHANGHAI: \"Shanghai\"\n  STR_VLADIVOSTOK: \"Vladivostok\"\n  STR_LONDON: \"London\"\n  STR_FAEROE_ISLAND: \"Færøerne\"\n  STR_ABERDEEN: \"Aberdeen\"\n  STR_OSLO: \"Oslo\"\n  STR_JAMAICA: \"Jamaica\"\n  STR_PANAMA: \"Panama\"\n  STR_MIAMI: \"Miami\"\n  STR_PSI_TRAINING: \"M.K. Træning\"\n  STR_PSIONIC_TRAINING: \"MOLEKYLÆR KONTROL TRÆNING\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Resterende M.K. kapacitet> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"M.K.{NEWLINE}Styrke\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"M.K.Skill{NEWLINE}/Forbedring\"\n  STR_IN_TRAINING: \"I{NEWLINE}Træning?\"\n  STR_TARGETTED_BY: \"RETTET MOD:\"\n  STR_WEAPONS_CREW_HWPS: \"VÅBEN/{NEWLINE}MANDSKAB/SVS'er\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"mangler brændstof,{NEWLINE}vender tilbage til basen\"\n  STR_SOLDIER_LIST: \"Dykkerliste\"\n  STR_RANK_: \"RANG> {ALT}{0}\"\n  STR_MISSIONS: \"MISSIONER> {ALT}{0}\"\n  STR_KILLS: \"DRÆBT> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"SÅRGENDANNELSE> {ALT}{0}\"\n  STR_TIME_UNITS: \"TIDSENHEDER\"\n  STR_STAMINA: \"UDHOLDENHED\"\n  STR_HEALTH: \"HELBRED\"\n  STR_BRAVERY: \"MOD\"\n  STR_REACTIONS: \"REAKTION\"\n  STR_FIRING_ACCURACY: \"PRÆCISION VED SKUD\"\n  STR_THROWING_ACCURACY: \"PRÆCISION VED KAST\"\n  STR_STRENGTH: \"STYRKE\"\n  STR_PSIONIC_STRENGTH: \"M.K. STYRKE\"\n  STR_PSIONIC_SKILL: \"M.K. FÆRDIGHED\"\n  STR_NEW_RANK: \"NY RANG\"\n  STR_PROMOTIONS: \"Forfremmelser\"\n  STR_SOLDIERS_UC: \"DYKKERE\"\n  STR_COELACANTH_GAS_CANNON_UFOPEDIA: \"Automatiske SVS'er har høj manøvredygtighed og skrogstyrke. De giver tunge tropper støtte på alle dybder. SWS'er genlades automatisk, hvis du har nok ammunition.\"\n  STR_COELACANTH_AQUA_JET_UFOPEDIA: \"Dette undervandfartøj er bevæbnet med Vand-Jet-torpedoer. Dette våbensystem fungerer kun under vand. Sørg for at lagrene er godt fyldt op med Vand-Jet-torpedoer.\"\n  STR_COELACANTH_GAUSS_UFOPEDIA: \"Gauss-teknologi tilbyder et funktionsrigt våbensystem for SVS'er. Tilbyder tung ildkraft sammenlignet med tidligere modeller og bruger proprietær X-Com-teknologi.\"\n  STR_DISPLACER_SONIC_UFOPEDIA: \"Rumvæsnernes teknolig har omdefineret SVS'er. Evnen til at udnytte ion-fortrængeren betyder at SVS'er ikke længere er begrænset til land/havbunden. Lydbølgevåben giver en reel fordel i kamp.\"\n  STR_DISPLACER_PWT_UFOPEDIA: \"Denne SVS har våben med pulsbølger for undervandsbrug. Du skal fremstille PWT'er for at holde dem fuldt armeret. For at skyde vælges et antal »punkter« og klik så på affyr-ikonet.\"\n  STR_ALIEN_PROBE_MISSION: \"Rumvæsen Sonde Mission\"\n  STR_ALIEN_INTERDICTION: \"Rumvæsen Forbud\"\n  STR_ALIEN_RESOURCE_RAID: \"Rumvæsen Ressource Angreb\"\n  STR_ALIEN_INFILTRATION: \"Rumvæsen-Infiltrering\"\n  STR_ALIEN_BASE: \"Udvidelse af Rumvæsenkoloni\"\n  STR_ALIEN_SURFACE_ATTACK: \"Landangreb af Rumvæsener\"\n  STR_ALIEN_RETALIATION: \"Angreb på Flydende Base\"\n  STR_ALIEN_SUPPLY: \"Koloniforsyningsmissioner\"\n  STR_ALIEN_PROBE_MISSION_UFOPEDIA: \"Rumvæsen Sonde Missionen benyttes til at korrelere data om havbunden, ressourcerne og skibs- og luftfartsruter i et område. Rumvæsenubåde der er involveret i disse missioner er ikke en større trussel i sig selv, men de indikerer områder med aktivitet, som når som helst kan blusse op.\"\n  STR_ALIEN_INTERDICTION_UFOPEDIA: \"Rumvæsnerne har det med at patruljere områder de er interesseret i, sende fartøjer ud med det ene formål at sikre et område, før mere intense missioner begynder. De vil lande i specifikke områder, hvor de har i sinde at angribe senere, for at afskærme områderne og forberede til næste niveau af aktivitet.\"\n  STR_ALIEN_RESOURCE_RAID_UFOPEDIA: \"Sænkningen af skibe og nedskydningen af fly er nøgleelementer i rumvæsnernes strategi. Erhvervelsen af materialer er en af de primære rumvæsenaktiviteter og som sådan forbundet med disse åbenlyst aggressive handlinger. Rumvæsnerne angriber også områder med geotermisk aktivitet, miner, og oldtidsområder for mineraler og forædlede metaller og andre menneskeskabte genstande.\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"Dette kan resultere i en officiel kontakt mellem rumvæsnerne og selskaber eller regeringer på højeste niveau. Højdepunktet af denne aktivitet karakteriseres ved intens rumvæsenubådsaktivitet i nærheden af den omhandlende organisation.\\nRumvæsnerne vil forsøge at underskrive en aftale med en regering eller organisation, ved at tilbyde viden om deres overlegne teknologier. Denne rumvæsenaktivitet repræsenterer en større trussel mod X-Com. Hvis et selskab eller en regering samarbejder med de invaderende, mistes deres finansering.\"\n  STR_ALIEN_BASE_UFOPEDIA: \"Rumvæsnerne vil konstruere hemmelige underhavskolonier i øde områder. Efter nogle rekognosceringer, vil der opstå mere omfattende rumvæsenubådsaktivitet mens kolonien bliver bygget. Disse kolonier er kendt for at indeholde laboratorier, kloningscentre og kirurgiske faciliteter til menneske- og rumvæseneksperimenter. Tilstedeværelsen af rumvæsenkolonier vil skabe mere rumvæsenaktivitet uden tilstedeværelse af rumnvæsenubåde. For at lokalisere en koloni, skal en X-Com ubåd patruljere et område i nogle timer, for at have en chance for succesfuld detektering.\"\n  STR_ALIEN_SURFACE_ATTACK_UFOPEDIA: \"Når rumvæsnerne har brug for mennesker, terroriserer de havne, angriber en ø eller et skib. Civile vil blive truet til at udføre rumvæsnernes perverse parringsbehov og afskyelige eksperimenter.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"Hvis X-Com jægerubåde er usædvanligt succesfulde i at sænke rumvæsenfartøjer, kan rumvæsnerne tænkes at udføre aggressive gengældelseshandlinger. Dette kunne resultere i et direkte angreb på en X-Com facilitet. Men rumvæsnerne skal først finde en X-Com base, for at kunne angribe den, og så længe rumvæsenubåde er holdt på afstand, burde der ikke være stor fare for et angreb.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"Når først rumvæsnerne har anlagt en koloni, så forsynes den med faste intervaller af et forsyningsskib. Hvis et af disse fartøjer detekteres at lægge an til landing, så er det sikkert, at en rumvæsenkoloni ligger i området.\"\n  STR_SURVEY_SHIP_UFOPEDIA: \"Denne lille ubåd benyttes til rekognoscerings- og undersøgelsesmissioner. Den ses ofte før større fartøjer i begyndelsen af en rumvæsen-taskforce.\"\n  STR_ESCORT_UFOPEDIA: \"Et mellemstort eskorteringsfartøj, der i sig selv knap udgør en trussel. Dette fartøj ses ofte før ankomsten af større fartøjer og stigende aktivitet.\"\n  STR_CRUISER_UFOPEDIA: \"Krydseren er et bredt anvendeligt fartøj, grundpillen i rumvæsnernes flåde, bruges på alle typer missioner og er en farlig modstander.\"\n  STR_HEAVY_CRUISER_UFOPEDIA: \"Større våben og fremdriftssystemer gør den tunge krydser til et stærkere fartøj end krydseren. Den tunge krydser anvendes på ressourcemissioner til indsamling af store mængder mineraler og udstyr.\"\n  STR_HUNTER_UFOPEDIA: \"Dette fartøj er udstyert med et undersøgelsesrum til at udføre eksperimenter og kirurgi på mennesker.\\nOfrene er udsat for den mest grusomme tortur og hjernen er ofte fjernet og lagret til processering undervejs.\"\n  STR_BATTLESHIP_UFOPEDIA: \"Slagskibet er det mest aggressive fartøj rumvæsnerne besidder. Det indeholder al teknologi og systemer til at fungere som en operationsbase for enhver for som aggressiv handling som rumvæsnerne ønsker at udføre. Fartøjet bærer en bred vifte af våben. \"\n  STR_DREADNOUGHT_UFOPEDIA: \"Panserskibet en super troppetransporter, fuldt udstyret med rumvæsenteknologier og en kæmpe nyttelast. Panserskibet er en hård og formidabel modstander.\"\n  STR_FLEET_SUPPLY_CRUISER_UFOPEDIA: \"Forsyningsfartøjet benyttes under konstruktion af rumvæsnernes kolonier eller til at forsyne eksisterende kolonier. Det medbringer rumvæsensnærringstoffer, DNA, fostrer og andre biologiske komponenter.\"\n  STR_DISMANTLE: \"Nedlæg\"\n  STR_FACILITY_IN_USE: \"VAND-KAPSEL I BRUG\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"KAN IKKE NEDLÆGGE VAND-KAPSEL!{SMALLLINE}Alle basekapsler skal være forbundet til luftslusen.\"\n  STR_TRANSFER_ITEMS_TO: \"Overfør Udstyr til {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"INTET OPB.RUM FOR RUMVÆSENER!{SMALLLINE}Levende rumvæsner kræver et opbevaringsrum for rumvæsner for at overleve.\"\n  STR_AMOUNT_AT_DESTINATION: \"MÆNGDE VED{NEWLINE}DESTINATION\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"Rumvæsenet dør, da der ikke er noget opbevaringsrum for rumvæsner\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"INGEN LEDIGE BEBOELSESRUM!{SMALLLINE}Destinationsbasen har ikke beboelsesplads nok til det mandskab, som er ombord på fartøjet.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"IKKE NOK LAGERRUM!{SMALLLINE}Destinationsbasen har ikke nok lagerrum til det udstyr, som er tildelt fartøjet.\"\n  STR_ITEMS_ARRIVING: \"Udstyr Ankommer\"\n  STR_DESTINATION_UC: \"DESTINATION\"\n  STR_DART_PISTOL: \"Dartpistol\"\n  STR_DART_POD: \"Dartmagasin\"\n  STR_JET_HARPOON: \"Jet-harpun\"\n  STR_HARPOON_POD: \"Harpunmagasin\"\n  STR_GAS_CANNON: \"Gas-kanon\"\n  STR_GC_AP_AMMO: \"GC-AP Bolte\"\n  STR_GC_HE_AMMO: \"GC-HE Bolte\"\n  STR_GC_P_AMMO: \"GC-Fosfor Bolte\"\n  STR_HYDRO_JET_CANNON: \"Vand-jet-kanon\"\n  STR_HJC_AP_AMMO: \"HJ-AP ammo\"\n  STR_HJC_HE_AMMO: \"HJ-HE ammo\"\n  STR_HJC_P_AMMO: \"HJ-P ammo\"\n  STR_TORPEDO_LAUNCHER: \"Torpedo Raketstyr\"\n  STR_SMALL_TORPEDO: \"Lille Torpedo\"\n  STR_LARGE_TORPEDO: \"Stor Torpedo\"\n  STR_PHOSPHOROUS_TORPEDO: \"Fosfortorpedo\"\n  STR_MAGNA_BLAST_GRENADE: \"Magna-Trykbølge Granat\"\n  STR_DYE_GRENADE: \"Farvegranat\"\n  STR_PARTICLE_DISTURBANCE_GRENADE: \"Partikelforstyrrelsesgranat\"\n  STR_MAGNA_PACK_EXPLOSIVE: \"Magna-Pakke Eksplosiver\"\n  STR_PARTICLE_DISTURBANCE_SENSOR: \"Partikelforstyrrelsessensor\"\n  STR_MEDI_KIT: \"Førstehjælpssæt\"\n  STR_MC_DISRUPTOR: \"M.K. Afbryder\"\n  STR_THERMAL_TAZER: \"Termisk lammepistol\"\n  STR_GAUSS_PISTOL: \"Gauss-pistol\"\n  STR_GAUSS_PISTOL_CLIP: \"Gausspistol-magasin\"\n  STR_GAUSS_RIFLE: \"Gaussgevær\"\n  STR_GAUSS_RIFLE_CLIP: \"Gaussgevær-magasin\"\n  STR_HEAVY_GAUSS: \"Tung Gauss\"\n  STR_HEAVY_GAUSS_CLIP: \"Tungt Gauss-Magasin\"\n  STR_SONIC_CANNON: \"Lydkanon\"\n  STR_CANNON_POWER_CLIP: \"Kanonmagasin\"\n  STR_SONIC_BLASTA_RIFLE: \"Lydblastagevær\"\n  STR_BLASTA_POWER_CLIP: \"Ammo til Blasta'en\"\n  STR_SONIC_PISTOL: \"Lydpistol\"\n  STR_PISTOL_POWER_CLIP: \"Pistolmagasin\"\n  STR_DISRUPTOR_PULSE_LAUNCHER: \"Afbrydningspuls Raketstyr\"\n  STR_DISRUPTOR_AMMO: \"Afbryder ammo\"\n  STR_THERMAL_SHOK_LAUNCHER: \"Termisk Chok Raketstyr\"\n  STR_THERMAL_SHOK_BOMB: \"Termisk chok-bombe\"\n  STR_SONIC_PULSER: \"Lydpulsvåben\"\n  STR_ZRBITE: \"Zrbite\"\n  STR_MC_READER: \"M.K. Læser\"\n  STR_VIBRO_BLADE: \"Vibroblad\"\n  STR_THERMIC_LANCE: \"Termisk lanse\"\n  STR_HEAVY_THERMIC_LANCE: \"Tung termisk lanse\"\n  STR_AQUATOID_CORPSE: \"Aquatoid-lig\"\n  STR_GILLMAN_CORPSE: \"Gællemandslig\"\n  STR_LOBSTERMAN_CORPSE: \"Hummermandslig\"\n  STR_TASOTH_CORPSE: \"Tasoth-lig\"\n  STR_CALCINITE_CORPSE: \"Calcinite-lig\"\n  STR_DEEP_ONE_CORPSE: \"Dybhavsskabningslig\"\n  STR_BIODRONE_CORPSE: \"Biodronelig\"\n  STR_TENTACULAT_CORPSE: \"Tentaculat-lig\"\n  STR_TRISCENE_CORPSE: \"Triscene-lig\"\n  STR_HALLUCINOID_CORPSE: \"Hallucionid-lig\"\n  STR_XARQUID_CORPSE: \"Xarquid-lig\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"Ikke nok ammunition til at armere SVS{SMALLLINE}Hver SVS kræver {0} {1}.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Ikke nok inventar til fuldt ud at udstyre din kampenhed\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Du skal forske i{NEWLINE}{0}{NEWLINE}for at producere{NEWLINE}{1}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"Rumvæsnerne har destrueret den ubeskyttede base {0}\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"XCom-agenter har lokaliseret en rumvæsenkoloni i {0}\"\n  STR_STANDOFF: \"AFVENTENDE\"\n  STR_CAUTIOUS_ATTACK: \"FORSIGTIGT ANGREB\"\n  STR_STANDARD_ATTACK: \"STANDARDANGREB\"\n  STR_AGGRESSIVE_ATTACK: \"AGGRESSIVT ANGREB\"\n  STR_DISENGAGING: \"AFSLUTTER ANGREB\"\n  STR_UFO_HIT: \"RUMVÆSNERNES UBÅD ER RAMT!\"\n  STR_UFO_CRASH_LANDS: \"RUMVÆSENUBÅD RAMT!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Minimer Kun ved Afventende Afstand\"\n  STR_UFO_RETURN_FIRE: \"RUMVÆSENUBÅD SKYDER IGEN!\"\n  STR_INTERCEPTOR_DAMAGED: \">>> FLYVENDE UBÅD SKADET <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> FLYVENDE UBÅD SKUDT NED <<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"RUMVÆSENERNES FLYVENDE UBÅD UNDVIGER!\"\n  STR_LONG_RANGE_DETECTION: \"Stor detektionsradius\"\n  STR_STORES_UC: \"LAGRE\"\n  STR_DIFFICULTY_LEVEL: \"Sværhedsgrad\"\n  STR_INTERCEPT: \"ANGRIB\"\n  STR_BASES: \"BASER\"\n  STR_GRAPHS: \"GRAFER\"\n  STR_UFOPAEDIA_UC: \"UFOPÆDI\"\n  STR_OPTIONS_UC: \"INDSTILLINGER\"\n  STR_FUNDING_UC: \"FINANSIERING\"\n  STR_5_SECONDS: \"5 Sek.\"\n  STR_1_MINUTE: \"1 Min.\"\n  STR_5_MINUTES: \"5 Min.\"\n  STR_30_MINUTES: \"30 Min.\"\n  STR_1_HOUR: \"1 Time\"\n  STR_1_DAY: \"1 Dag\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"X-Com-Præstationsliste\"\n  STR_ENTER_NAME: \"Indtast Navn\"\n  STR_PERFORMANCE_RATING: \"Præstationsbedømmelse\"\n  STR_VICTORY_DATE: \"Dato for Sejr\"\n  STR_CHEMICAL_FLARE: \"Kemisk-knæklys\"\n  STR_CHEMICAL_FLARE_UFOPEDIA: \"Denne kompakte anordning producerer et skarpt lysskær på enhver dybde eller på land. Dette oplyser fjendtlige enheder i nærheden af lyset under dybhavsmissioner eller missioner om natten. \"\n  STR_MONTHLY_COSTS: \"Månedlige Udgifter\"\n  STR_CRAFT_RENTAL: \"Flyvende Ubåd Udlejning\"\n  STR_SALARIES: \"Lønninger\"\n  STR_BASE_MAINTENANCE: \"Basevedligeholdelse\"\n  STR_COST_PER_UNIT: \"Pris per enhed\"\n  STR_QUANTITY: \"Mængde\"\n  STR_TOTAL: \"I alt\"\n  STR_IN_PSIONIC_TRAINING: \"I M.K. Implantering\"\n  STR_FRONT_ARMOR: \"Frontpanser\"\n  STR_LEFT_ARMOR: \"Venstre panser\"\n  STR_RIGHT_ARMOR: \"Højre panser\"\n  STR_REAR_ARMOR: \"Rygpanser\"\n  STR_UNDER_ARMOR: \"Underliggende panser\"\n  STR_ROUNDS: \"SKUD\"\n  STR_UNIT: \"Enhed> {0}\"\n  STR_ENERGY: \"ENERGI\"\n  STR_MORALE: \"MORAL\"\n  STR_ARMOR_: \"PANSER> {0}\"\n  STR_FRONT_ARMOR_UC: \"FRONTPANSER\"\n  STR_LEFT_ARMOR_UC: \"VENSTRE PANSER\"\n  STR_RIGHT_ARMOR_UC: \"HØJRE PANSER\"\n  STR_REAR_ARMOR_UC: \"BAGPANSER\"\n  STR_SKILLS: \"EVNER> {0}\"\n  STR_LEVEL: \"NIVEAU> {0}\"\n  STR_HEAD: \"HOVED\"\n  STR_TORSO: \"OVERKROP\"\n  STR_RIGHT_ARM: \"HØJRE ARM\"\n  STR_LEFT_ARM: \"VENSTRE ARM\"\n  STR_RIGHT_LEG: \"HØJRE BEN\"\n  STR_LEFT_LEG: \"VENSTRE BEN\"\n  STR_PAIN_KILLER: \"SMERTESTILLENDE\"\n  STR_STIMULANT: \"STIMULANS\"\n  STR_HEAL: \"HELBRED\"\n  STR_TIME_UNITS_SHORT: \"TE>{ALT}{0}\"\n  STR_WEIGHT: \"Vægt>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"Reaktion>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"M.Skill>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"M.Str>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Rumvæsenartefakt\"\n  STR_AMMO_ROUNDS_LEFT: \"AMMO:{NEWLINE}SKUD{NEWLINE}LEFT={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Smerte>{ALT}{0}{ALT}{NEWLINE}Stim.>{ALT}{1}{ALT}{NEWLINE}Behandl>{ALT}{2}\"\n  STR_THROW: \"Kast\"\n  STR_AUTO_SHOT: \"Auto-skud\"\n  STR_SNAP_SHOT: \"Hurtigt skud\"\n  STR_AIMED_SHOT: \"Sigtet skud\"\n  STR_STUN: \"Bedøv\"\n  STR_PRIME_GRENADE: \"Aktiver granat\"\n  STR_USE_SCANNER: \"Benyt Dist. Sensor\"\n  STR_USE_MEDI_KIT: \"Brug Førstehjælpskasse\"\n  STR_LAUNCH_MISSILE: \"Affyr Torpedo\"\n  STR_ACCURACY_SHORT: \"Acc>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Ikke Nok Tidsenheder!\"\n  STR_NOT_ENOUGH_ENERGY: \"Ikke Nok Energi!\"\n  STR_NO_ROUNDS_LEFT: \"Ingen Skud Tilbage!\"\n  STR_NO_AMMUNITION_LOADED: \"Ingen Ammunition!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Forkert Ammunitionstype til dette Våben!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"Våbnet er allerede ladt!\"\n  STR_NO_LINE_OF_FIRE: \"Intet Frit Skud!\"\n  STR_GRENADE_IS_ACTIVATED: \"Granat er Aktiveret!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Granat Deaktiveret!\"\n  STR_THERE_IS_NO_ONE_THERE: \"Der er ingen!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Umuligt at bruge rumvæsenartefakt indtil det er undersøgt!\"\n  STR_OUT_OF_RANGE: \"Udenfor Rækkevidde!\"\n  STR_UNABLE_TO_THROW_HERE: \"Umuligt at kaste hertil!\"\n  STR_SET_TIMER: \"Sæt Tidsudløser\"\n  STR_HIDDEN_MOVEMENT: \"SKJULT BEVÆGELSE\"\n  STR_TURN: \"RUNDE> {0}\"\n  STR_SIDE: \"SIDE> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Tryk på en tast for at fortsætte\"\n  STR_MIND_CONTROL: \"Molekylær Kontrol\"\n  STR_PANIC_UNIT: \"Blokeringsimplantat\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Moralangreb Udført med Succes\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Implantatkontrol Succesfuldt\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}er gået Bersærk\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}er gået Bersærk\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}er gået i Panik\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}er gået i Panik\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Rumvæsner\"\n  STR_RIGHT_HAND: \"HØJRE HÅND\"\n  STR_LEFT_HAND: \"VENSTRE HÅND\"\n  STR_RIGHT_SHOULDER: \"HØJRE SKULDER\"\n  STR_LEFT_SHOULDER: \"VENSTRE SKULDER\"\n  STR_BACK_PACK: \"RYGSÆK\"\n  STR_BELT: \"BÆLTE\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}er under Molekylær Kontrol\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}er under Molekylær Kontrol\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}er blevet bevidstløs\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}er blevet bevidstløs\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}er død af fatale sår\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}er død af fatale sår\"\n  STR_USE_MIND_PROBE: \"Anvend M.K. Læser\"\n  STR_FATAL_WOUNDS: \"FATALE SÅR\"\n  STR_UNDER_ARMOR_UC: \"UNDERPANSER\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Tidsenheder reserveret til Hurtigt Skud\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Tidsenheder reserveret til Autoskud\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Tidsenheder reserveret til Sigtet Skud\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Tidsenheder reserveret til at Knæle\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"TE'er reserveret til at Knæle og Skyde\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} enhed i X-Com-fly\"\n    other: \"{N} Enheder i X-Com Fartøj\"\n  STR_UNITS_OUTSIDE:\n    one: \"{N} enhed efterladt udenfor\"\n    other: \"{N} Enheder efterladt udenfor\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} enhed i indgangsparti\"\n    other: \"{N} Enheder i indgangsparti\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} enhed i måludgang\"\n    other: \"{N} Enheder i måludgang\"\n  STR_ABORT_MISSION_QUESTION: \"Afslut mission?\"\n  STR_CORPSE: \"Lig\"\n  STR_UNLOAD_CRAFT: \"Aflad\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}er blevet dræbt\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}er blevet dræbt\"\n  STR_HIT_MELEE: \"Ramte\"\n  STR_GROUND: \"JORDEN\"\n  STR_LIVING_QUARTERS_PLURAL: \"Beboelsesrum\"\n  STR_LIST_ITEM: \"UDSTYR\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"Alle rumvæsner dræbt i styrtet,{NEWLINE}Automatisk bjærgning påbegyndt\"\n  STR_RESET: \"Nulstil\"\n  STR_MEMORIAL: \"Gravskrift\"\n  STR_DATE_UC: \"DATO\"\n  STR_SOLDIERS_RECRUITED_UC: \"DYKKERE REKRUTTERET>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"MISTEDE DYKKERE>{ALT}{0}\"\n  STR_REMOVE_SELECTED: \"Fjern valgte\"\n  STR_LIVE_ALIENS: \"Levende{NEWLINE}Eksemplarer\"\n  STR_DEAD_ALIENS: \"Afviste{NEWLINE}Eksemplarer\"\n  STR_UNDER_INTERROGATION: \"Bliver{NEWLINE}Undersøgt\"\n  STR_CONTAINMENT_EXCEEDED: \"BEGRÆNSNING PÅ OPBEVARING AF RUMVÆSENER ER NÅET!{SMALLLINE}Der er ikke mere plads hos  {0}. Du må fjerne overskydende rumvæsner fra opbevaringslokalet (de vil derefter dø).\"\n  STR_MANAGE_CONTAINMENT: \"Håndter Rumvæsnernes Opbevaringsrum\"\n  STR_STORAGE_EXCEEDED: \"LAGERPLADS ER OVERSKREDET!{SMALLLINE}Der er ikke nok lagerplads hos {0}. Du må sælge overskydende udstyr.\"\n  STR_GO_TO_BASE: \"Gå til Base\"\n  STR_MELEE_ACCURACY: \"NÆRKAMPSPRÆCISION\"\n  STR_SELL_PRODUCTION: \"SÆLG\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Begge hænder skal være tomme!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Ikke nok udstyr til at kopiere skabelon!\"\n  STR_UNLOAD_WEAPON: \"Aflad våben\"\n  STR_ALL_ITEMS: \"Alt udstyr\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"IKKE MERE UDSTYR TILLADT OMBORD!{SMALLLINE}Du må kun medtage maksimalt {N} enheds udstyr med på denne ubåd.\"\n    other: \"IKKE MERE UDSTYR TILLADT OMBORD!{SMALLLINE}Du må kun medtage et maksimum af {N} stykker udstyr på denne ubåd.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}KONTROLCENTER ØDELAGT{NEWLINE}Gå til indgangen og afbryd.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"X-COM vand-faciliteter kan ikke bygges på land\"\n  STR_UNABLE_TO_ENGAGE_DEPTH: \"KAN IKKE ANGRIBE FJENDEN{NEWLINE}PÅ DENNE DYBDE\"\n  STR_UNABLE_TO_ENGAGE_AIRBORNE: \"KAN IKKE ANGRIBE FJENDEN{NEWLINE}NÅR I LUFTEN\"\n  STR_UNDERWATER_EQUIPMENT: \"Dette udstyr vil ikke fungere over vand!\"\n  STR_LAND_EQUIPMENT: \"Dette udstyr vil ikke fungere under vand!\"\n  STR_LEVEL_SHORT: \"L{0}\"\n  STR_PERSONNEL: \"Personale\"\n  STR_CRAFT_ARMAMENT: \"Fartøj og udrustning\"\n  STR_COMPONENTS: \"Komponenter\"\n  STR_SOLDIERS_RECRUITED: \"Dykkere rekrutteret\"\n  STR_SOLDIERS_LOST: \"Mistede dykkere\"\n  STR_TOTAL_UFOS: \"Flyvende ubåde detekteret\"\n  STR_TOTAL_ALIEN_BASES: \"Rumvæsenkolonier opdaget\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"MST\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"MSK\"\n  FEMALE_CIVILIAN: \"Civil, Kvinde\"\n  MALE_CIVILIAN: \"Civil, Mand\"\n  DOCKER_CIVILIAN: \"Civil, Havnearbejder\"\n  SAILOR_CIVILIAN: \"Civil, Sømand\"\n  STR_BIODRONE_MELEE_WEAPON: \"Biodrone - Nærkamp\"\n  HALLUCINOID_WEAPON: \"Hallucinoid - Våben\"\n  STR_LOBSTERMAN_MELEE_WEAPON: \"Hummermand - Nærkamp\"\n  CALCINITE_WEAPON: \"Calcinite - Våben\"\n  DEEP_ONE_WEAPON: \"Dybhavsskabning - Våben\"\n  STR_TRISCENE_MELEE_WEAPON: \"Triscene - Våben\"\n  STR_TRIBIO_SONIC_WEAPON: \"Rumvæsen - Lydvåben\"\n  XARQUID_WEAPON: \"Xarquid - Våben\"\n  TENTACULAT_WEAPON: \"Tentaculat - Våben\"\n  ZOMBIE_WEAPON: \"Zombievåben\"\n  ALIEN_PSI_WEAPON: \"Rumvæsen - M.K.-Våben\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/de.yml",
    "content": "de:\n  STR_LEVIATHAN_UFOPEDIA: \"EIN TRANSPORT- UND ABFANG-U-BOOT MIT BESONDERER TIEFENTAUGLICHKEIT. EINE HERVORRAGENDE SYNTHESE UNTERSCHIEDLICHER TECHNOLOGIEN, MIT IONENPROPULSIONSSYSTEMEN UND MAGNETISCHER VEKTORNAVIGATION.\"\n  STR_BARRACUDA_UFOPEDIA: \"DIE BRITISCHE HYDROSPACE-BARRACUDA, ANGETRIEBEN VON HEISS-LASER- MOTOREN. EINER DER SCHNELLSTEN ABFANGJÄGER DER WELT, UNTER WASSER UND IN DER LUFT EINSETZBAR UND BESTIMMT EIN ENTSCHEIDENDER FAKTOR IM KOMMENDEN KAMPF.\"\n  STR_HAMMERHEAD_UFOPEDIA: \"EIN TRANSPORT- UND ABFANGFAHRZEUG. EINE REPLIKATION MAGNETISCHER ARRAY-SYSTEME IN EINEM X-COM-SCHIFF. TROTZ SEINER GERINGEN GRÖSSE EIN WICHTIGER TECHNISCHER DURCHBRUCH.\"\n  STR_TRITON_UFOPEDIA: \"EIN VON SUB AM ENTWORFENER TRITON-STOSSTRUPPTRANSPORTER. AUSGESTATTET MIT KOMPLETTEN LUFT- UND WASSERFLUGMOTOREN. SEINE KAPAZITÄT UND SEINE ROBUSTE KONSTRUKTION MACHEN IHN ZUM HAUPTSCHIFF DER X-COM-FLOTTE.\"\n  STR_MANTA_UFOPEDIA: \"MANTA-SCHNELLFAHRZEUG, EIN EINSITZIGES FLIEGENDES ABFANG-U-BOOT, DEN IONENGETRIEBENEN ALIEN-SCHIFFEN SEHR ÄHNLICH. EIN ÄUSSERST WIRKSAMES ANGRIFFSFAHRZEUG IM ESKALIERENDEN KONFLIKT.\"\n  STR_AJAX_UFOPEDIA: \"DER AJAX-TORPEDO IST ÜBERALL DIE STANDARDWAFFE IM UNTERWASSERKAMPF. EINGESETZT ALS TREFFSICHERE UND GEWALTIGE ABSCHRECKUNG.\"\n  STR_DUP_HEAD_UFOPEDIA: \"KUGELN MIT ABGEREICHERTEM URAN SIND WAFFENTECHNOLOGISCH RELATIV NEU, UND DIES IST DAS ERSTE KOMMERZIELLE AQUATISCHE WAFFENSYSTEM, DAS DIESE TECHNIK NUTZT.\"\n  STR_CRAFT_GAS_CANNON_UFOPEDIA: \"EIN DRUCKGASGETRIEBENES KANONENSYSTEM; DESSEN BOLZEN FAST JEDE PANZERUNG DURCHDRINGEN\"\n  STR_PWT_CANNON_UFOPEDIA: \"DER IMPULS-TORPEDO VERWENDET EIN ÜBERHITZESYSTEM UND EINEN ÄUSSERST DICHTEN SPRENGKOPF, DER FAST ALLE LEGIERUNGEN DURCHBRECHEN KANN.\"\n  STR_GAUSS_CANNON_UFOPEDIA: \"DIE GAUSS-WAFFE IST TEIL DER ALLERNEUESTEN X-COM-TECHNOLOGIE. DER TEILCHENBESCHLEUNIGER DIESES SYSTEMS WIRD VON EINEM KOMPAKTEN, STICKSTOFF-GEKÜHLTEN FUSIONSREAKTOR ANGETRIEBEN.\"\n  STR_SONIC_OSCILLATOR_UFOPEDIA: \"EIN STARKER HÖROSZILLATOR ERZEUGT WELLEN VON SCHALL-ENERGIE, DIE DAS ZIEL DURCH VIBRATION SEINER MOLEKÜLBINDUNG ZERSTÖREN.\"\n  STR_AQUATOID_UFOPEDIA: \"Die Aquatoiden sind eine alte Kultur, die schon Jahrtausende vor dem Erscheinen des Menschen blühte. In ihrer kompakten Form und ihren knolligen Gesichtszügen kommen ihre raumfahrenden Brüder, die Sektoiden, durch. Ihre Macht beruht auf der Technik der Molekülsteuerung. Die Aquatoiden müssen sich, da sie unfruchtbar sind, durch Genmanipulation vermehren, wobei die Menschen ideale Objekte sind. In Experimenten sind zahlreiche Hybridformen entstanden.\"\n  STR_AQUATOID_AUTOPSY: \"Aquatoide Autopsie\"\n  STR_AQUATOID_AUTOPSY_UFOPEDIA: \"Eine Analyse dieser Kreatur gibt uns Grund zu folgenden Annahmen: Es handelt sich um einen Sektoiden, unsere früheren Gegner, durch operative Eingriffe und Implantate zu einem Wasserlebewesen verändert. Rudimentäre Lungen ermöglichen das Einatmen von Sauerstoff und begrenzte Oberflächenmobilität. Kybernetische Implantate im gesamten Körper erhöhen die Kraft der atrophierten Gliedmaßen und die Organfunktionen. Da alle Angehörigen dieser Gruppe identisch sind, vermuten wir, daß es sich bei diesen Kreaturen um Klone handelt.\"\n  STR_GILLMAN_UFOPEDIA: \"Ein menschenähnliches Wesen, das ein reptilienartiger Humanoid zu sein scheint. Diese Kreatur ist in der Unterwasserwelt äußerst kräftig und schnell. Es handelt sich um eine ausgewachsene Spezies mit männlichen und weiblichen Vertretern unterschiedlichen Alters. Sie unterscheiden sich vom Großteil der Unterwasserbewohner, da sie keine Anzeichen von Genmanipulation oder chirurgischen Eingriffen zeigen. Warscheinlich haben wir einen entfernt verwandten Urahnen unserer eigenen Spezies vor uns.\"\n  STR_GILLMAN_AUTOPSY: \"Kiemenmensch Autopsie\"\n  STR_GILLMAN_AUTOPSY_UFOPEDIA: \"Es war klar, daß es sich nicht um einen Alien handelte, sondern um eine Erdkreatur, eine prähistorische Spezies, von der man annahm, daß sie in dem Moment ausstarb, als die Säugetiere dominant wurden. Diese starken und klugen Amphibier lebten zu einer Zeit, als die Dinosaurier die Wälder durchstreiften. Die Umwälzung, die die Herrschaft der Reptilien auf diesem Planet beendete, zwang diese Kreaturen in eine Symbiose mit den gerade angekommenen Aliens. Ein kleines Elektronengerät steckt im Schädel der Kreaturen.\"\n  STR_LOBSTERMAN_UFOPEDIA: \"Eine übewältigende Kreatur, größer als ein Mensch und mit sechs Gliedmaßen, ein wenig wie ein Wasserdämon. Die Ähnlichkeit dieser Kreatur mit einem Hummer hat ihr bei den X-Com-Truppen den Spitznamen Hummermensch eingetragen. Ein Monstrum der Tiefe. Eine überlegt entworfene Kampfkreatur, ungeheuer stark und durch Geschoßfeuer praktisch unverwundbar. Allein seine Scheren können Stahl zermalmen.\"\n  STR_LOBSTERMAN_AUTOPSY: \"Hummermensch Autopsie\"\n  STR_LOBSTERMAN_AUTOPSY_UFOPEDIA: \"Hinter dieser fast unzerstörbaren Schale verbirgt sich eine verblüffende Konstruktion. Mächtige Muskeln sind an einem Titaniumskelett befestigt, und ein ausgeklügeltes Zielsystem mit multipler Scan-Kapazität ist direkt in das Gehirn der Kreatur eingebaut. Die Facettenaugen sind durch Plastik geschützt, das härter als Stahl ist. Bei guter Aufstellung durch ihre Herren sind diese Kreaturen nicht mehr zu halten. Tief in ihrem Körper verborgen sind Geräte von bisher unbekannter Konstruktion und Funktion.\"\n  STR_TASOTH_UFOPEDIA: \"Diese agilen und schnellen Gegner bilden die Stütze der Alien-Armee. Hunderte werden in riesigen Brutkesseln im Herzen der Alien-Kolonien geboren. Der Tasoth ist um einiges stärker als ein Mann, ein echter Alien, und weder sein Verhalten noch seine karnivore Natur haben bisher auf der Erde ihresgleichen gefunden. Der Tasoth bildet oft die Speerspitze des gegnerischen Angriffs und scheint nie vor einem Kampf zurückzuschrecken, selbst angesichts einer gewaltigen Übermacht.\"\n  STR_TASOTH_AUTOPSY: \"Tasoth Autopsie\"\n  STR_TASOTH_AUTOPSY_UFOPEDIA: \"Die Sektion zeigte einen kybernetischen Organismus. In der Körperhöhle befindet sich ein kleiner Antrieb, aber keinerlei Organe. Energie wird innerhalb des Körpers von einem bio- elektrischen System übertragen. Knochen und Stützorgane sind nicht vorhanden. Bei Eintreten des Todes bricht die Energie ab, und die Kreatur wird zu einer leblosen Puppe verwesenden Fleisches und verströmender Flüssigkeiten. Im Körper befindet sich einige keramischer Zellen, die mittels Energiestoß die Kreatur kurzfristig wiederbeleben können.\"\n  STR_DEEP_ONE_UFOPEDIA: \"Das Ungetüm ist ein biologischer Alptraum, eine Kreuzung, geschaffen durch die Gehirnexperimente der Aquatoiden. Mehrere Variationen dieser Kreatur wurden bisher beobachtet. Nach intensiver Forschung können wir sagen, daß sie von den Invasoren hergestellt werden. Sie nehmen zu, wenn menschlicher Bestand erbeutet werden konnte. Jede dieser entsetzlichen Kreaturen ist mit einer Ladung elektrischer Energie ausgestattet, die einen Aquanauten töten kann.\"\n  STR_DEEP_ONE_AUTOPSY: \"Ungetüm Autopsie\"\n  STR_DEEP_ONE_AUTOPSY_UFOPEDIA: \"Diese Kreatur ist ein Transplantat aus menschlichen Organismen und Aliens. Das menschliche Gehirn wurde massiv geändert, um Steuerungselektronik und die Alien-Hirnrinde unterbringen zu können. Nur die Augen erinnern noch an einen Menschen. Die Transplantation ermöglicht es dem Alien-Fötus, den menschlichen Wirt zu verzehren. Die Haut der Kreatur scheint nicht organisch, sondern eine metallische Verzahnung, die äußerst flexibel und haltbar ist. Die so geschaffene Kreuzung ist stark und schnell.\"\n  STR_BIODRONE_UFOPEDIA: \"Die Bio-Drohne wurde von den Aliens erdacht. Es ist ein Gehirn, das in amniotischer Flüssigkeit schwimmt und mit einer angetriebenen Grundeinheit verbunden ist, die auf dem Land oder unter Wasser fliegen kann. Jede Bio-Drohne ist mit einem Schallstörer ausgestattet, teils Maschine, teils organisch. Wissenschaftler vermuten, daß die Waffe von den Stimmbändern der Wirtsorganismen angetrieben wird. Diese zuverlässigen und hartnäckigen Super-Wächter werden von den Aliens oft eingesetzt, um wertvollen Besitz zu bewachen.\"\n  STR_BIODRONE_AUTOPSY: \"Bio-Drohnen Autopsie\"\n  STR_BIODRONE_AUTOPSY_UFOPEDIA: \"Es hat sich bestätigt, daß der Schallstörer aus organischem Material besteht. Diese Kreatur schreit ihre Gegner buchstäblich tot. Jedes Exemplar ist schwer verstümmelt. Die Aliens haben das Gehirn bis zur Gefügigkeit zerstückelt. Viele der verwendeten Großhirnrinden sind außerirdischen Ursprungs, doch haben wir zu unserem Schrecken auch Einheiten menschlichen Ursprungs gefunden. Die Bio-Drohnen werden von einem IONEN-Motor angetrieben und besitzen eine Art Fernlenksystem.\"\n  STR_TENTACULAT_UFOPEDIA: \"Nicht einmal ein Lovecraft'scher Alptraum hätte diese unbeschreibliche Kreatur hervorbringen können. Kein vergleichbares Tier existiert auf der Erde, eine Umgebung, die so etwas erzeugt, ist nicht vorstellbar. Mit langen Tentakeln bewaffnet lähmt der Tentakulat seine Opfer und verwandelt sie in hirnlose Masse. Diese können durch Berührung töten, auch durch Panzerung hindurch.  Der Tentakulat ist der furchtbarste Alien, auf den die X-Com gestoßen ist.\"\n  STR_TENTACULAT_AUTOPSY: \"Tentakulat Autopsie\"\n  STR_TENTACULAT_AUTOPSY_UFOPEDIA: \"Die Autopsie erwies, daß kleine kybernetische Implantate im Gehirn der Kreatur vorhanden sind. Das Sehsystem ist eine komplexe Kombination aus sichtbarem Licht und thermischem Bilderwerb. Selbst in den grössten Tiefen des Ozeans kann dieses Monster mit unfehlbarer Genauigkeit navigieren. Rudimentäre Organe sind vorhanden, die das reine Überleben sichern. Jede Kreatur besitzt einen kleinen Magen mit einer Verbindung nach außen. Das Wesen wird durch direkte Nährstoffzufuhr ernährt.\"\n  STR_CALCINITE_UFOPEDIA: \"Wie Tauchanzü\\x81ge verschollener Seeleute jagen diese Aliens auf dem Meeresboden nach Beute. Ein schneller Zugriff der Zangen, die stärker sind als Stahl, kann auch die besten Taucher zu Boden bringen. Hinter der Tauchermaske kann man eine gallertartige grüne Masse sehen. Aus den Begegnungen mit dieser Kreatur, die oft tödlich verlaufen, können wir keine Rückschlüsse auf ihren wahren Charakter ziehen.\"\n  STR_CALCINITE_AUTOPSY: \"Calcinit Autopsie\"\n  STR_CALCINITE_AUTOPSY_UFOPEDIA: \"Ist die Panzerung durchbrochen, erweist sich der Calcinit als ein riesiger amorpher Kloß aus Protoplasma. Kein erkennbares Gehirn, keine Gliedmaßen oder Sinnesorgane scheinen vorhanden, nur ein kleines metallisches Teil ist tief in dem flüssigen Körper verborgen. Die tote Kreatur läßt nur Vermutungen zu. Ein unerklärliches Rätsel, das uns unsere außerirdischen Gegner aufgeben.\"\n  STR_TRISCENE_UFOPEDIA: \"Dieses zweibeinige Reptil ist eine Rückkehr in das Zeitalter der Dinosaurier. Es scheint in jeder Hinsicht ein Tier aus der Kreidezeit zu sein, außer seiner Fähigkeit, sowohl im Wasser als auch an Land zu überleben. Diese Kreaturen sind mit Waffenhalterungen ausgestattet und haben einen Kiefer mit großen Metallzähnen. Diese Monster bilden oft den Kern von attackierenden Alientruppen, wenn die Aliens Landangriffe starten. Eine schwergewichtige und wirksame Waffe, entfalten sie mit den Tasoth-Kommandeuren tödliche Effizienz.\"\n  STR_TRISCENE_AUTOPSY: \"Triszenen Autopsie\"\n  STR_TRISCENE_AUTOPSY_UFOPEDIA: \"Unter dem Messer der Wissenschaftler hat sich der Triszene als eine sehr alte Kreatur erwiesen, die durch kybernetische Implantate und Waffensysteme ergänzt wurde. Das winzige Gehirn ist durch ein kleines Computermodul ersetzt, das im Steuerharnisch angebracht ist, den alle Kreaturen tragen. Eine harte, natürliche Haut und ein durch zusätzliche Waffen verstärkter Jagdinstinkt machen diese Kreatur in allen Umgebungen zu einem tödlichen Gegner.\"\n  STR_HALLUCINOID_UFOPEDIA: \"Nach der Ausbeutung der Meere haben die Aliens diese riesigen Erdkreaturen als Waffe gezüchtet. Lassen Sie sich nicht durch das harmlose Äußere dieser Segler der Tiefe täuschen. Mit seinem Nahkampf-Eisschlag ist der Halluzinoid ein tödlicher Gegner.\"\n  STR_HALLUCINOID_AUTOPSY: \"Halluzinoiden Autopsie\"\n  STR_HALLUCINOID_AUTOPSY_UFOPEDIA: \"In den vielen Lagen dieses gallertartigen Körpers ruht ein höchst wirksamer chemischer Gefrierer, seine Hauptangriffswaffe. Die weiche und elastische Haut des Halluzinoiden scheint gegenüber auf Wärme basierenden Angriffen sehr anfällig. Diese Mutation ist oft in der Gesellschaft seiner Herren, den Aquatoiden, anzutreffen.\"\n  STR_XARQUID_UFOPEDIA: \"Auch bei den Xintfischen, wirbellosen Erdmutationen, handelt es sich um Kreaturen von großer Schönheit und Gefahr. Der schnell schwimmende Riese birgt ein verheerendes Arsenal von Waffen, darunter einen Tintenspray und einen Ionenpartikelstrahl.  Seit unseren ersten Zusammentreffen mit diesen Kreaturen sind wir vor ihnen und ihren Herren, den rachedürstenden Kiemenmenschen, sehr achtsam geworden.\"\n  STR_XARQUID_AUTOPSY: \"Xintfisch Autopsie\"\n  STR_XARQUID_AUTOPSY_UFOPEDIA: \"Dieser \\x81übergroße Nautilus wurde mit außerirdischen Drogen gemästet und auch durch operativen Eingriff verändert. Bereits weit \\x81über das natürliche Maß hinaus pervertiert, haben die Kiemenmenschen mechanische Steuersysteme hinzugefügt und die Kreatur mehr oder weniger neu geschaffen. Als organische Waffenplattform werden die Xintfische aufgrund ihrer harten Schale und ihrer Beweglichkeit zu einem mächtigen Gegner.\"\n  STR_ION_BEAM_ACCELERATORS_UFOPEDIA: \"Die fliegenden U-Boote der Aliens basieren auf komplexen Antriebssystemen, die hohe Geschwindigkeiten ermöglichen. Die Grundlage ihrer Technologie ist der IONENVERDRÄNGER; unter Verwendung von Zrbit als Katalysator können die Motoren im Wasser mehr als das Hundertfache ihres eigenen Volumens pro Sekunde verdrängen. Diese gewaltige Kraft bedeutet, daß die Aliens schneller sind als die meisten U-Boote. Wir können dieses System mit Hilfe von  Aqua-Kunststoffen und Zrbit-Energiezellen kopieren.\"\n  STR_MAGNETIC_NAVIGATION_UFOPEDIA: \"Diese Einheiten erzeugen ein sphärisches, viellagiges Magnetfeld, das das Array bis zu 1000 m um das U-Boot verbreiten kann. Die außerirdischen Navigatoren sind direkt mit den Maschinen verbunden und ertasten sich ihren Weg durch die unsichtbare Welt unter dem Meer. Das Interface-System operiert auf von den Aliens modifiziertem zerebralen Material, das direkt durch eine neurale Verbindung mit dem Gehirn des Bedieners verbunden ist.\"\n  STR_ALIEN_SUB_CONSTRUCTION_UFOPEDIA: \"Alle Boote haben eine chamäleonartige Struktur, die eng an die von Meeresgeschöpfen angelehnt und aus Aqua-Kunststoffen gefertigt ist. Die U-Boote operieren wie ein Organismus: Mannschaft und Fahrzeug arbeiten in Harmonie. Die meisten dieser Systeme können kopiert werden und eine Hybrid-Technologie kann entwickelt werden, die es uns erlaubt, das gleiche technologische Niveau zu erreichen.\"\n  STR_ALIEN_CRYOGENICS_UFOPEDIA: \"Die unzähligen Aliens, die auf der Erde verborgen waren, wurden im Tiefschlaf gehalten, im Tieftemperaturspeicher. Alle diese Kreaturen sind in Einheiten versiegelt, ihre Körpertemperatur ist auf einen Punkt gesenkt, an dem alle Körperfunktionen gerade noch aufrecht erhalten werden. Eine Untersuchung der Einheiten ergab unglaubliche Lagerzeiten dieser Kreaturen, zum Teil bis zu 60 Millionen Jahre.\"\n  STR_ALIEN_CLONING_UFOPEDIA: \"Viele der Aliens, die wir gefangen haben, sind identisch, sogar ihre DNS, in jeder Hinsicht Duplikate. Zellproben wurden in die Einheiten der gefrorenen Genbanken der Aliens eingeführt. Einige Einheiten enthalten Menschen oder Körperteile. Es ist möglich, daß diese Klon-Einheiten zur Schaffung eines Hybriden aus Mensch und Alien verwendet werden sollten.\"\n  STR_ALIEN_LEARNING_ARRAYS_UFOPEDIA: \"Unter Verwendung von Molekülsteuerimplantaten im Schädel aller Aliens können diese Maschinen Information direkt in das Gehirn injizieren. Neu geklonte Aliens werden zu diesen Einheiten gebracht und biologische oder wissenschaftliche Informationen oder Daten, die den Kampf betreffen, werden in die leeren Gehirne geladen.\"\n  STR_ALIEN_IMPLANTER_UFOPEDIA: \"Diese Einheit stattet Aliens mit Molekülsteuerimplantaten aus, macht die Spezies reproduzierfähig und setzt Organe oder Elektronik in alle Kreaturen ein oder entnimmt sie. Das Verfahren wird nicht, wie ursprünglich vermutet, am betäubten Patienten vorgenommen, sondern das Objekt ist während des gesamten Vorgangs bei Bewußtsein, und leider scheint die menschliche Anatomie am geeignetsten für diese Einheit zu sein.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"Wir wissen nun, warum die Aliens Menschen gefangennehmen. Nicht als Nahrung, nicht als Brutkästen für außerirdische Embryos, sondern als Basis für eine Reihe von Kreaturen und Steuersystemen. Die Technologie der Aliens beruht auf einem einzigen Willen, einem gemeinsamen Intellekt, und das menschliche Gehirn ist der ideale Behälter für diese Systeme. Menschliches Gehirngewebe wird in den meisten Systemen biologischer Computerspeicherung der Aliens verwendet, der Rest dient der Konstruktion und der Züchtung.\"\n  STR_AQUA_PLASTICS_UFOPEDIA: \"U-Boote und Gebäude der Aliens verwenden ein unglaublich starkes, flexibles und haltbares Material für den Großteil ihrer Konstruktionen. Aqua-Kunststoffe sind komplexe, multi-gebundene und mit Zrbit katalysierte Materialien. Die dichte, jedoch leichte Substanz hat eine noch größere Haltbarkeit als Titanium oder Kevlar.\"\n  STR_ZRBITE_UFOPEDIA: \"Dies ist eine Legierung außerirdischer Herkunft, teils Gold, teils Bio-Material der Aliens. Als Energiequelle genutzt, können geringe Mengen mehr Energie erzeugen als eine nukleare Einheit zehnfacher Größe. Es übersteigt unsere technologischen Fähigkeiten, dieses Material zu kopieren, da die meisten Bestandteile außerirdischer Herkunft sind.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"Die Aliens greifen mit erbarmungsloser Effizienz überall auf der Welt an. Wir können einfach nicht feststellen, wo sie herkommen. Könnte ihre Basis irgendwo in den für uns unerreichbaren Tiefen der Meere liegen? Nicht alle Organismen, die wir beobachtet haben, sind außerirdisch. Einige sind sehr alt, andere stammen aus Evolutionszweigen, die man für ausgestorben hielt. Wir haben es mit einer Bedrohung zu tun, die Jahrtausende lang schlummerte, einer subtilen Symbiose aus Mensch und Alien. Tief in den Meeren liegen uralte Stätten verborgen, von denen aus die Aliens versuchten, Kontakt zu ihren stellaren Brüdern aufzunehmen. Jede dieser zwölf Stätten enthält einen Synomiumapparat, eine mächtige außerirdische Technologie. Gestärkt durch ihre gewaltige Kriegsmaschinerie nehmen die Aliens diese Stätten wieder in Betrieb, um ihr Molekülsteuerungsnetz auszuweiten. Wir müssen diese Stätten um jeden Preis zerstören.\"\n  STR_THE_ULTIMATE_THREAT_UFOPEDIA: \"Vor 65 Millionen Jahren wurde ein riesiges Kolonisationsschiff von einer fernen außerirdischen Welt zur Erde geschickt. Als das gewaltige Raumschiff sich dem jungen Planeten näherte, versagten aufgrund einer enormen Sonneneruption plötzlich die Navigationssysteme. Das beschädigte Raumschiff raste ungesteuert durch die Stratosphäre und erreichte schließlich den Erdenhimmel. Dort sahen die unzähligen Spezies der Kreidezeit gebannt zu, wie dieser unbekannte Feind auf ihren Planeten herabstürzte. Eine ungeheure Staubwolke stieg in die Atmosphäre auf, die sich so weit abkühlte, daß die herrschenden Lebewesen, die gewaltigen Dinosaurier, starben. Doch die 400 Milliarden Tonnen der Stadt T'leth wurden bei dem Aufprall nicht völlig zerstört. Hochentwickelte Supercomputer aktivierten einen kryogenen Schlafzyklus für die Kreaturen in den Frachträumen. Im Lauf der Jahrtausende weckten die Computers einzelne Gruppen von Aliens, damit sie eine Verbindung zu ihren stellaren Brüdern herstellen konnten, doch vergebens. Der Kern der außerirdischen Macht schlief weiter.\"\n  STR_TLETH_THE_ALIEN_CITY: \"T'leth, die Stadt der Aliens\"\n  STR_TLETH_THE_ALIEN_CITY_UFOPEDIA: \"T'leth, das riesige Kolonisationsschiff der Aliens, liegt im Sigsbee-Graben im Golf von Mexiko. Im Innern dieser Stadt lauert ein außerirdischer Schrecken, so grauenvoll und mächtig, daß nicht einmal der Tod ihn berühren kann. In einer Kammer aus seltsamem Metall liegt der schlafende Körper des Großen Träumers, des Mächtigsten Außerirdischen. Der Aufstieg T'leths aus den Wellen wird seinen Reanimationszyklus starten, und ist er erst erwacht, kann ihn niemand mehr aufhalten. Weder lebendig noch wirklich tot, steuert das Gehirn des Alien seine außerirdische Armee. Die erstaunliche Technologie der molekularen Steuerung verbindet alle Aliens mit dem Gehirn des Einen und ihn mit allen Aliens. Genetisch manipulierte außerirdisch-menschliche Föten versorgen das Gehirn des Alien mit Energie und bilden die Verbindung zwischen dem Herrscher und seinen Untertanen. Der Mythos vom Mächtigsten Außerirdischen existiert seit Jahrhunderten in den Köpfen der Menschen, doch das Meer hielt die ganze schreckliche Wahrheit bisher verborgen.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"AUF STANDORT ZENTRIEREN-ZEIT=5 Sek.\"\n  STR_CANCEL_UC: \"ABBRECHEN\"\n  STR_NONE: \"Keine\"\n  STR_UNKNOWN: \"Unbekannt\"\n  STR_POOR: \"Schwach\"\n  STR_AVERAGE: \"Durchschnitt\"\n  STR_GOOD: \"Gut\"\n  STR_EXCELLENT: \"Ausgezeichnet\"\n  STR_BUILD_NEW_BASE_UC: \"NEUE BASIS ERRICHTEN\"\n  STR_BASE_INFORMATION: \"BASIS-INFORMATIONEN\"\n  STR_EQUIP_CRAFT: \"U-BOOT AUSSTATTEN\"\n  STR_BUILD_FACILITIES: \"EINRICHTUNGEN BAUEN\"\n  STR_RESEARCH: \"FORSCHUNG\"\n  STR_MANUFACTURE: \"HERSTELLUNG\"\n  STR_TRANSFER_UC: \"TRANSFER\"\n  STR_PURCHASE_RECRUIT: \"KAUFEN/REKRUTIEREN\"\n  STR_SACK: \"ENTLASSEN\"\n  STR_SELL_SACK_UC: \"VERKAUFEN/ENTLASSEN\"\n  STR_GEOSCAPE_UC: \"GEOSCAPE\"\n  STR_NAME: \"Name\"\n  STR_AREA: \"Gebiet\"\n  STR_BUILD_NEW_BASE: \"Neue Basis errichten\"\n  STR_CANCEL: \"Abbrechen\"\n  STR_COST_UC: \"KOSTEN>\"\n  STR_CONSTRUCTION_TIME_UC: \"BAUZEIT>\"\n  STR_DAY:\n    one: \"{N} Tage\"\n    other: \"{N} Tage\"\n  STR_HOUR:\n    one: \"{N} Stunden\"\n    other: \"{N} Stunden\"\n  STR_MAINTENANCE_UC: \"INSTANDHALTUNG>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Installation\"\n  STR_CURRENT_RESEARCH: \"FORSCHUNGSSTAND\"\n  STR_SCIENTISTS_AVAILABLE: \"Verfügbare Wissenschaftler>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Zugeteilte Wissenschaftler>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Verfügbare Laborräume>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"FORSCHUNGSPROJEKT\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"ZUGETEILTE WISSENSCHAFTLER\"\n  STR_PROGRESS: \"FORTSCHRITT\"\n  STR_NEW_PROJECT: \"Neues Projekt\"\n  STR_CANCEL_PROJECT: \"PROJEKT ABBRECHEN\"\n  STR_NEW_RESEARCH_PROJECTS: \"NEUE FORSCHUNGSPROJEKTE\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"VERFÜGBARE WISSENSCHAFTLER>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"VERFÜGBARE LABORRÄUME>{ALT}{0}\"\n  STR_INCREASE: \"Erhöhen\"\n  STR_DECREASE: \"Verringern\"\n  STR_START_PROJECT: \"PROJEKT STARTEN\"\n  STR_CURRENT_PRODUCTION: \"LAUFENDE PRODUKTION\"\n  STR_ENGINEERS_AVAILABLE: \"Verfügbare Techniker>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Zugeteilte Techniker>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Verfügbarer Werkstattraum>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Momentane Mittel>{ALT}{0}\"\n  STR_ITEM: \"ARTIKEL\"\n  STR_ENGINEERS__ALLOCATED: \"Techniker Zugeteilt\"\n  STR_UNITS_PRODUCED: \"Einheiten Produziert\"\n  STR_TOTAL_TO_PRODUCE: \"Gesamt-produktion\"\n  STR_COST__PER__UNIT: \"Kosten{NEWLINE}pro{NEWLINE}Einheit\"\n  STR_DAYS_HOURS_LEFT: \"Verbleibende Tage\"\n  STR_NEW_PRODUCTION: \"Neue Produktion\"\n  STR_PRODUCTION_ITEMS: \"Produktionsartikel\"\n  STR_CATEGORY: \"KATEGORIE\"\n  STR_START_PRODUCTION: \"PRODUKTION STARTEN\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} Technikerstunden für eine Einheit\"\n  STR_COST_PER_UNIT_: \"Kosten pro Einheit>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Erforderlicher Arbeitsraum>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"SPEZIALMATERIAL ERFORDERLICH\"\n  STR_ITEM_REQUIRED: \"BENÖTIGTE ARTIKEL\"\n  STR_UNITS_REQUIRED: \"BENÖTIGTE EINHEITEN\"\n  STR_UNITS_AVAILABLE: \"VERFÜGBARE EINHEITEN\"\n  STR_STOP_PRODUCTION: \"PRODUKTION STOPPEN\"\n  STR_ENGINEERS_AVAILABLE_UC: \"VERFÜGBARE TECHNIKER>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"VERFÜGBARER WERKSTATTRAUM>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"MONATLICHER PROFIT>{ALT}{0}\"\n  STR_INCREASE_UC: \"ERHÖHEN\"\n  STR_DECREASE_UC: \"VERRINGERN\"\n  STR_UNITS_TO_PRODUCE: \"Zu produzierende Einheiten\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Personal erwerben/einstellen\"\n  STR_COST_OF_PURCHASES: \"Kaufpreis>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"KOSTEN PRO EINHEIT\"\n  STR_QUANTITY_UC: \"MENGE\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"VERFÜGBARES PERSONAL:PERSONAL INSGESAMT>\"\n  STR_SOLDIERS: \"Aquanauten\"\n  STR_SCIENTISTS: \"Wissenschaftler\"\n  STR_ENGINEERS: \"Techniker\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"BENUTZTER RAUM:VERFÜGBARER RAUM>\"\n  STR_LIVING_QUARTERS: \"Wohnblocks\"\n  STR_STORES: \"Lager\"\n  STR_LABORATORIES: \"Labors\"\n  STR_WORK_SHOPS: \"Werkstätten\"\n  STR_HANGARS: \"Fliegende U-Boot-Boxen\"\n  STR_SHORT_RANGE_DETECTION: \"Kurzstreckensonar\"\n  STR_DEFENSE_STRENGTH: \"Verteidigungsstärke\"\n  STR_TRANSFERS_UC: \"TRANSFERS\"\n  STR_TRANSFERS: \"Transfers\"\n  STR_ARRIVAL_TIME_HOURS: \"Ankunft (Stunden)\"\n  STR_COST_: \"Kosten>{ALT}{0}\"\n  STR_AREA_: \"Gebiet>{ALT}{0}\"\n  STR_BASE_NAME: \"Name der Basis?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"POSITION FÜR LUFTSCHLEUSE WÄHLEN\"\n  STR_TRANSFER: \"Transfer\"\n  STR_AMOUNT_TO_TRANSFER: \"MENGE FÜR TRANSFER\"\n  STR_SELECT_DESTINATION_BASE: \"Zielbasis wählen\"\n  STR_COST: \"Kosten\"\n  STR_INTRO_1: \"Copyright 1995 MicroProse\"\n  STR_INTRO_2: \"Mars: Der Untergang Cydonias\"\n  STR_INTRO_3: \"Nachdem sie das Herzstück der außerirdischen Kriegsmaschinerie zerstört hat, reist eine triumphierende X-Com nach Hause zurück. Doch in den Trümmern der Basis auf dem Mars ist noch Leben.\"\n  STR_INTRO_4: \"Ein kräftiger Tachyonenstrahl wird aus den Überresten des cydonischen Kommandozentrums ausgesandt und rast durch den leeren Raum auf sein Ziel zu............\"\n  STR_INTRO_5: \"Erde.\"\n  STR_INTRO_6: \"Tief unter dem Meer trifft der Strahl einen verborgenen Rezeptor. Riesige Computer erwachen wie aus einem Schlummer. In den Tiefen, für den Menschen unsichtbar, beginnen unzählige Aliens in ihren Kammern einen langsamen Reanimationszyklus\"\n  STR_INTRO_7: \"2040: Die nichtsahnenden Erdbewohner haben die Schrecken der Außerirdischen-Kriege vergessen. Doch an unbekannten Orten im Ozean machen sich die Heerscharen der Aliens bereit, die Menschheit zu stürzen und die Erde an sich zu reißen.\"\n  STR_INTRO_8: \"Die Aliens terrorisieren die Menschen und benutzen sie zu grauenvollen Experimenten. Sie rauben auf dem ganzen Erdball wertvolle Mineralien und Rohstoffe und plündern die Meere. Schließlich richtet sich ihre Gier auf die Welt der Menschen über den Wellen.\"\n  STR_INTRO_9: \"Gewaltige Flug-U-Boote von seltsamer Gestalt durchkreuzen die Meere, lauern, suchen, jagen.........\"\n  STR_INTRO_10: \"und finden Beute, die sie gnadenlos angreifen.\"\n  STR_INTRO_11: \"Seltsame neue Waffen werden gegen die wehrlose Menschheit eingesetzt, und wir sind der außerirdischen Bedrohung völlig ausgeliefert.{NEWLINE}Nur eine Organisation kann uns retten, doch wir haben uns vor langer Zeit von ihr abgewandt.\"\n  STR_INTRO_12: \"Experimentale Unterwassereinrichtung der X-Com\"\n  STR_INTRO_13: \"Mayday! Mayday! Hier spricht das transatlantische Linienschiff Hyperion, wir werden angegriffen. Mayday! Mayd............\"\n  STR_INTRO_14: \"Kommandozentrale an U-Boot-Box Eins: Unterwasserschleusen öffnen, Barracuda Null Eins aussenden. Alien-Angriffssituation, Alarmstufe Rot.{NEWLINE}Ich wiederhole, Alarmstufe Rot.\"\n  STR_INTRO_15: \"Die Außerirdischen sind von erbarmungsloser Effizienz,....\"\n  STR_INTRO_16: \"...eiskalt und gnadenlos genau.\"\n  STR_INTRO_17: \"Barracuda Null Eins an Basis, nähern uns den Überresten der Hyperion.\"\n  STR_INTRO_18: \"'Verlangsamen' {NEWLINE} 'Zwei Meter' {NEWLINE} 'Einen Meter' {NEWLINE} 'Alle Aquanauten bereiten sich auf den sofortigen Einsatz vor'.\"\n  STR_INTRO_19: \"...........Luftschleuse verlassen, nähern uns dem Wrack.{NEWLINE}Großer Gott!{NEWLINE}Könnt ihr diese Kreaturen auf meiner Kamera erkennen?\"\n  STR_GAMEOVER_1: \"Wir haben versagt. Die Aliens haben unsere letzte Hoffnung auf Rettung zunichte gemacht.{NEWLINE}X-Com ist besiegt und die Erde liegt dem uralten Gegner wehrlos zu Füßen.\"\n  STR_GAMEOVER_2: \"T'leth erhebt sich donnernd hoch bis in die Stratosphäre und beginnt sich über das Angesicht der Erde zu bewegen. Todbringend; die menschlichen Rasse aberntend. Und tief in ihren Eingeweiden.. ein mörderisches Alienhirn.. dass sich zu regen beginnt.\"\n  STR_GAMEOVER_3: \"In den Hauptstädten aller Länder sucht man verzweifelt nach einem Abwehrplan. Doch alles ist vergebens; ohne die Technologie aus dem X-Com-Forschungsprojekt sind unsere Waffen nutzlos.\"\n  STR_GAMEOVER_4: \"Die Aliens errichten Stützpunkte an den Polarkappen und beginnen das Eis zu schmelzen. Die Welt wird ein einziges, weites Meer. Übriggebliebene Menschen werden zusammengetrieben und für abscheuliche Züchtungsexperimente mit unbekanntem Ziel missbraucht. Der Himmel verdunkelt sich und eine schreckliche Seuche breitet sich über der Erde aus. \"\n  STR_GAMEOVER_5: \"Wir haben dieser neuen Weltordnung nichts entgegenzusetzen, die die es versuchen erwartet ein feuriges Ende durch die unfassbaren Waffen der Aliens. Für uns übrige gibt es eine solche, gnädige Erlösung nicht. Mutter Erde wird zu einer fremden Welt und die Menschheit, begraben unter einem monströsen, kriechenden Schrecken, ist verloren.\"\n  STR_OUTRO_1: \"Die Grabstätte in Trümmern, verwüstet. Ein gurgelndes Brüllen aus dem Sarg in ihrer Mitte.{NEWLINE}Narren, ihr werdet alle sterben....................\"\n  STR_OUTRO_2: \".................es gibt kein Entkommen.\"\n  STR_OUTRO_3: \"Eine gewaltige Explosion zerreist das Grab und erschüttert die Stadt. Schutt und Asche liegen in der Luft. Die Pläne der Außerirdischen sind vereitelt.\"\n  STR_OUTRO_4: \"Die gewaltigen, abnormen Massen T'leths beginnen zu bersten. Flammen und Rauch schießen aus ihren gleisenden Türmen und adamantenen Hallen hervor.\"\n  STR_OUTRO_5: \"Die mächtige Alien-Festung stürzt taumelt der Meersoberfläche entgegen; die Schreie gequälten Metalls und verzweifelter Seelen erfüllen die Luft. Nie mehr wird der große Träumer von der Eroberung der Welt träumen.\"\n  STR_OUTRO_6: \"Eine letzte, ohrenzerreißende Erschütterung und T'leth reißt sich selbst entzwei.{NEWLINE}Die außerirdische Bedrohung ist abgewendet, die Erde gesäubert..................\"\n  STR_OUTRO_7: \"Ein verschlafener blau-grüner Planet, in einer entfernten Ecke der Galaxie.\"\n  STR_OUTRO_8: \"Die nahe Zukunft, ein sicherer Ort.\"\n  STR_OUTRO_9: \"Die außerirdische Bedrohung für die Erde ist seit langem besiegt.\"\n  STR_OUTRO_10: \"Gewaltige Metropolen beherbergen die wimmelnden Milliarden der Menschheit.\"\n  STR_OUTRO_11: \"Die Taten der X-Com und die Alien-Kriege sind Geschichten die man Kindern erzählt.\"\n  STR_OUTRO_12: \"Aber Legenden haben es immer an sich, ein Körnchen Wahrheit zu beinhalten............\"\n  STR_RISE_1: \"T'leth, in vielen Legenden aus vielen Ländern mit vielen Namen benannt.\"\n  STR_RISE_2: \"Mit einem explosiven Schrei der über den gesamten Erdball wiederhallt beginnt sich T'leth vom Meeresboden zu erheben.\"\n  STR_RISE_3: \"Das gewaltige Bauwerk bricht durch die Gewässer des Golfs von Mexiko.\"\n  STR_RISE_4: \"400 Milliarden Tonnen außerirdischen Metalls, die mächtige Stadt der Außerirdischen in der schlafend der Körper des ultimativen Aliens liegt. Seit 65 Millionen Jahren auf der Erde eingesperrt beginnt sich der abnorme, uralte Gott in seiner Ruhestätte zu regen.\"\n  STR_RISE_5: \"Das Meer kocht und brodelt als das Grab des großen Träumers in das helle Licht des Tages emporsteigt................\"\n  STR_RISE_6: \".........ein Licht, dass schon bald erlischen wird, sollte X-Com diese Kriegsmaschine der Aliens nicht zerstören können.\"\n  STR_YOU_HAVE_FAILED: \"Sie konnten die Kriegsmaschine der Aliens nicht aufhalten. Die Geldgeber versuchen nun, aus Enttäuschung ü\\x81ber Ihre mangelnden Fähigkeiten eine nicht-militärische Lösung mit den Aliens auszuhandeln. Die Invasoren haben jedoch andere Pläne, und bald kennt die ganze Welt die furchtbare Wahrheit...\"\n  STR_TOTAL_UC: \"GESAMT\"\n  STR_INCOME: \"Einkommen\"\n  STR_EXPENDITURE: \"Ausgaben\"\n  STR_MAINTENANCE: \"Instandhaltung\"\n  STR_BALANCE: \"Bilanz\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"Aktivitäten der Aliens in Ozeanen\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"Aktivitäten der Aliens in Zonen\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"X-Com-Aktivitäten in Ozeanen\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"X-Com-Aktivitäten in Zonen\"\n  STR_FINANCE: \"Finanzen\"\n  STR_DATE_FIRST: \"{0}.\"\n  STR_DATE_SECOND: \"{0}.\"\n  STR_DATE_THIRD: \"{0}.\"\n  STR_DATE_FOURTH: \"{0}.\"\n  STR_FINANCE_THOUSANDS: \"$1000er\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Nicht genug Spezialmaterial zur Produktion von{NEWLINE}{0}{NEWLINE}auf{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Nicht genug Geld zur Produktion von{NEWLINE}{0}{NEWLINE}auf{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"Produktion von{NEWLINE}{0}{NEWLINE}auf{NEWLINE}{1}{NEWLINE}ist beendet\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"Konstruktion von{NEWLINE}{0}{NEWLINE}auf{NEWLINE}{1}{NEWLINE}ist beendet\"\n  STR_OK_5_SECONDS: \"OK - 5 Sek.\"\n  STR_RESEARCH_COMPLETED: \"Forschung beendet\"\n  STR_VIEW_REPORTS: \"BERICHTE ANSCHAUEN\"\n  STR_WE_CAN_NOW_RESEARCH: \"Forschung in folg. Bereich möglich:\"\n  STR_WE_CAN_NOW_PRODUCE: \"Produktion folg. Artikel jetzt möglich:\"\n  STR_SUNDAY: \"SONNTAG\"\n  STR_MONDAY: \"MONTAG\"\n  STR_TUESDAY: \"DIENSTAG\"\n  STR_WEDNESDAY: \"MITTWOCH\"\n  STR_THURSDAY: \"DONNERSTAG\"\n  STR_FRIDAY: \"FREITAG\"\n  STR_SATURDAY: \"SAMSTAG\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Nicht genug {0} zum Auftanken {1} auf {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Nicht genug {0} zum Neuladen {1} auf {2}\"\n  STR_UFO_IS_NOT_RECOVERED: \"U-Boot der Aliens nicht geborgen\"\n  STR_UFO_IS_RECOVERED: \"U-Boot der Aliens geborgen\"\n  STR_CRAFT_IS_LOST: \"Fliegendes U-Boot verloren\"\n  STR_TERROR_CONTINUES: \"Fortgesetzte Aktivitäten der Aliens\"\n  STR_ALIENS_DEFEATED: \"Aliens besiegt\"\n  STR_BASE_IS_LOST: \"Basis verloren\"\n  STR_BASE_IS_SAVED: \"Basis gerettet\"\n  STR_ALIEN_BASE_STILL_INTACT: \"Kolonie der Aliens noch intakt\"\n  STR_ALIEN_BASE_DESTROYED: \"Kolonie der Aliens zerstört\"\n  STR_ALIENS_KILLED: \"ALIENS GETÖTET\"\n  STR_ALIEN_CORPSES_RECOVERED: \"GEBORGENE LEICHEN DER ALIENS\"\n  STR_LIVE_ALIENS_RECOVERED: \"GEFANGENGENOMMENE ALIENS\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"GEFUNDENE ARTEFAKTE DER ALIENS\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"KONTROLLE DER ALIENS ÜBER KOLONIE GEBROCHEN\"\n  STR_ALIEN_SYNOMIUM_DEVICE_DESTROYED: \"Synomiumapparat der Aliens zerstört\"\n  STR_ALIEN_SYNOMIUM_DEVICE_FAILED: \"Zerstörung des Synomiumapparats gescheitert\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"VON ALIENS GETÖTETE ZIVILISTEN\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"VON X-COM-SOLDATEN GETÖTETE ZIVILISTEN\"\n  STR_CIVILIANS_SAVED: \"GERETTETE ZIVILISTEN\"\n  STR_XCOM_OPERATIVES_KILLED: \"X-COM-SOLDATEN GETÖTET\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"X-COM-SOLDATEN VERMISST\"\n  STR_TANKS_DESTROYED: \"X-COM-WAFFENPLATTFORM ZERSTÖRT\"\n  STR_XCOM_CRAFT_LOST: \"X-COM-U-BOOT VERLOREN\"\n  STR_UFO_RECOVERY: \"UFO-BERGUNG\"\n  STR_ALIEN_BASE_RECOVERY: \"KOLONIE DER ALIENS GEBORGEN\"\n  STR_BASE_UNDER_ATTACK: \"{0} angegriffen!\"\n  STR_BASE_DEFENSES_INITIATED: \"BASISVERTEIDIGUNG EINGELEITET\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"SCHILDE WEHREN U-BOOT DER ALIENS AB!\"\n  STR_FIRING: \"FEUER\"\n  STR_HIT: \"TREFFER!\"\n  STR_UFO_DESTROYED: \"U-BOOT DER ALIENS ZERSTÖRT!\"\n  STR_MISSED: \"DANEBEN!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Artikel verkaufen/Personal entlassen\"\n  STR_VALUE_OF_SALES: \"VERKAUFSERLÖS> {ALT}{0}\"\n  STR_FUNDS: \"MITTEL> {ALT}{0}\"\n  STR_SELL_SACK: \"Verkaufen/Entlassen\"\n  STR_VALUE: \"Wert\"\n  STR_CRAFT_: \"FLIEGENDES U-BOOT> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"BERGUNG EINES VERUNGLÜCKTEN U-BOOTS DER ALIENS\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"VORSICHT - Aliens in U-Boot und Umgebung. Der Einsatz ist beendet, wenn alle gegnerischen Einheiten vernichtet oder unschädlich gemacht wurden. Bergung der U-Boot-Teile, der Technik und Leichen kann dann beginnen. Um den Einsatz abzubrechen, bringen Sie die X-Com-Aquanauten ins U-Boot zurück und klicken das Icon 'Einsatz abbrechen' an.\"\n  STR_UFO_GROUND_ASSAULT: \"GEGNERISCHER U-BOOT-ANGRIFF\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"Landeplatz untersuchen und, wenn möglich, Zugang zum  gegnerischen USO verschaffen. Der Einsatz ist erfolgreich abgeschlossen, wenn alle gegnerischen Einheiten eliminiert oder neutralisiert sind. Danach kann mit der Bergung des USOs, der Artefakte und toten Außerirdischen begonnen werden. Um die Mission abzubrechen, bringen Sie die XCom-Mitarbeiter zum Transporter zurück und klicken das Icon 'Mission abbrechen' an.\"\n  STR_BASE_DEFENSE: \"VERTEIDIGUNG DER BASIS\"\n  STR_BASE_UC_: \"BASIS> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"Ein Schiff der Aliens ist in der Nähe gelandet. Unsere Basis ist in höchster Gefahr. Das gesamte nicht-militärische Personal und alle funktionstüchtigen X-Com-U-Boote wurden evakuiert. Die Aliens werden die Basis über die U-Boot-Boxentore oder die Luftschleuse betreten. Verteidigen Sie die Basis und ihre lebenswichtigen Einrichtungen um jeden Preis - es geht um Leben und Tod. Wird das Icon 'Einsatz abbrechen' angeklickt, ergeben Sie sich und die Basis ist verloren.\"\n  STR_ALIEN_COLONY_ATTACK_MISSION: \"ANGRIFF AUF ALIEN-KOLONIE\"\n  STR_ALIEN_BASE_ASSAULT: \"ALIEN-KOLONIE TEIL EINS\"\n  STR_ALIEN_COLONY_P1_BRIEFING: \"Hier handelt es sich um einen Überfall auf eine Kolonie der Aliens. Es gibt 2 Levels. Bringen Sie alle Aquanauten zum leuchtenden Ausgang des ersten Gebäudekomplexes, und klicken Sie das Icon 'Einsatz abbrechen' an. Zurückgelassene Ausrüstung bleibt am Meeresboden liegen, bis der 2. Abschnitt abgeschlossen ist. Um das Spiel abzubrechen, bringen Sie die Aquanauten ins U-Boot und klicken das Icon 'Einsatz abbrechen' an.\"\n  STR_ALIEN_COLONY_P2: \"ALIEN-KOLONIE TEIL ZWEI\"\n  STR_ALIEN_COLONY_P2_BRIEFING: \"Nach dem ersten Level sind Sie nun im Herzen der Kolonie. Ihre Aufgabe besteht darin, die Kommandozentrale zu zerstören, den Synomiumapparat zu bergen oder alle Aliens zu eliminieren. Um das Spiel abzubrechen, bringen Sie alle Aquanauten zum Startpunkt und klicken das Icon 'Einsatz abbrechen' an. Jegliche funktionstüchtige X-Com-Ausrüstung wird zur Basis zurückgebracht.\"\n  STR_ALIENS_LAUNCH_PORT_TERROR: \"ALIENS STARTEN{NEWLINE}HAFENANGRIFF AUF\"\n  STR_PORT_TERROR: \"ALIENS BEGINNEN EINEN HAFENANGRIFF\"\n  STR_PORT_TERROR_BRIEFING: \"Aliens haben einen Bodenangriff begonnen. Der Hafen und die Zivilbevölkerung sind in Gefahr. Ihr Trupp muß alle Aliens eliminieren und die Unbeteiligten vor den Aliens beschützen. Um das Spiel abzubrechen, bringen Sie die Aquanauten in das Fliegende U-Boot, und klicken Sie das Icon 'Einsatz abbrechen' an.\"\n  STR_ALIENS_LAUNCH_ISLAND_TERROR: \"ALIENS STARTEN{NEWLINE}INSELANGRIFF AUF\"\n  STR_ISLAND_TERROR: \"ALIENS BEGINNEN EINEN INSELANGRIFF\"\n  STR_ISLAND_TERROR_BRIEFING: \"Aliens haben einen Bodenangriff begonnen. Der Hafen und die Zivilbevölkerung sind in Gefahr. Ihr Trupp muß alle Aliens eliminieren und die Unbeteiligten vor den Aliens beschützen. Um das Spiel abzubrechen, bringen Sie die Aquanauten in das Fliegende U-Boot, und klicken Sie das Icon 'Einsatz abbrechen' an.\"\n  STR_ALIENS_ATTACK_SHIPPING_ROUTE: \"ALIENS GREIFEN{NEWLINE}SCHIFFSROUTE AN\"\n  STR_CARGO_SHIP_P1: \"FRACHTSCHIFF TEIL EINS\"\n  STR_CARGO_SHIP_P2: \"FRACHTSCHIFF TEIL ZWEI\"\n  STR_CRUISE_SHIP_P1: \"KREUZFAHRTSCHIFF TEIL EINS\"\n  STR_CRUISE_SHIP_P2: \"KREUZFAHRTSCHIFF TEIL ZWEI\"\n  STR_SHIP_RESCUE_MISSION: \"SCHIFFSRETTUNGSEINSATZ\"\n  STR_SHIP_RESCUE_P1_BRIEFING: \"Bei diesem Einsatz geht es darum, alle Einheiten der Aliens auf dem Schiff zu eliminieren und das Leben der Zivilisten an Bord zu schützen.  Die Aliens befinden sich auf den Ober- und Unterdecks. Sichern Sie die Oberdecks, bevor Sie sich unter Deck begeben.  Um das Spiel abzubrechen, bringen Sie die Aquanauten in das Fliegende U-Boot und klicken das Icon 'Einsatz abbrechen' an.\"\n  STR_SHIP_RESCUE_P2_BRIEFING: \"Das Oberdeck ist frei; Sie können sich zu den Unterdecks begeben.  Fahren Sie mit dem Gü\\x81terlift in den Frachtraum hinab.  Ihr Trupp muß alle Aliens auf diesem Deck eliminieren, um den Einsatz zu beenden. Um das Spiel abzubrechen, bringen Sie die Aquanauten zum Lift-Startpunkt und klicken das Icon 'Einsatz abbrechen' an.\"\n  STR_ALIEN_ACTIVITY_DETECTED: \"AKTIVITÄTEN DER ALIENS ENTDECKT\"\n  STR_ALIEN_CONTACT_SITE_MISSION: \"EINSATZ AM KONTAKTORT DER ALIENS\"\n  STR_ARTIFACT_SITE_P1: \"ALIEN KOLONIE TEIL EINS\"\n  STR_ARTIFACT_SITE_P1_BRIEFING: \"Bei diesem Einsatz handelt es sich um einen Überfall auf eine gerade aktivierte Kommunikationsstellung. Es gibt 2 Ebenen, den Meeresboden mit den Pyramiden der Aliens und einem geheimen Komplex. Bringen Sie alle Aquanauten an den Eingang des Gebäudekomplexes, und klicken Sie auf das Icon 'Einsatz abbrechen'. Um das Spiel abzubrechen, bringen Sie die Aquanauten in das Fliegende U-Boot und klicken Sie auf das 'Icon 'Einsatz abbrechen'.\"\n  STR_ARTIFACT_SITE_P2: \"ALIEN KOLONIE TEIL ZWEI\"\n  STR_ARTIFACT_SITE_P2_BRIEFING: \"Nach Durchquerung der Gebäude und dem Eindringen in den Komplex werden die Einsatzziele klar. Dringen Sie ins Herz der Einrichtungen vor, zerstören Sie das Synomium-Molekülsteuerungsgerät, und bringen Sie den Einsatz zum Abschluß. Um das Spiel abzubrechen, bringen Sie alle Aquanauten zum Startpunkt des Zugangslifts, und klicken Sie das Icon 'Einsatz abbrechen' an.\"\n  STR_SIGSBEE_DEEP_MISSION: \"EINSATZ SIGSBEE DEEP[NEWLINE]AUSSERIRDISCHE STADT STUFE EINS\"\n  STR_TLETH_P1_BRIEFING: \"Wir betreten nun das Unbekannte, von nun an ist alles möglich. Wir wissen, daß es 1 weiteren Level in die Stadt der Aliens gibt, und Ihr Trupp muß zum Ausgang dieses Levels rennen, um den nächsten betreten zu können. Bringen Sie alle Aquanauten zum Ausgang, und klicken Sie das Icon 'Einsatz abbrechen' an. Wird das Icon von einer anderen Stelle aus angeklickt, bricht das Spiel ab.\"\n  STR_TLETH_ATTACK_MISSION: \"T'LETH ANGRIFFS MISSION[NEWLINE]AUSSERIRDISCHE STADT STUFE ZWEI\"\n  STR_TLETH_P2_BRIEFING: \"Hier im Unbekannten ist nun alles möglich. Wir wissen, daß es weitere Levels in die Stadt der Aliens gibt, und Ihr Trupp muß zum Ausgang dieses Levels rennen, um den nächsten betreten zu können. Bringen Sie alle Aquanauten zum Ausgang, und klicken Sie das Icon 'Einsatz abbrechen' an. Wird das Icon von einer anderen Stelle aus angeklickt, bricht das Spiel ab.\"\n  STR_FINAL_TLETH_MISSION: \"LETZTE T'LETH MISSION[NEWLINE]AUSSERIRDISCHE STADT STUFE DREI\"\n  STR_TLETH_P3_BRIEFING: \"Das Ende ist nah, nun suchen wir die Gruft des Höchsten Aliens. Zerstören Sie die 8 Energiezufuhren in das Grabmal, und beenden Sie die Bedrohung durch die Aliens. Jetzt nicht aufgeben! Mit Abbruch des Spiels wird auch der Einsatz abgebrochen.\"\n  STR_TLETH_P1: \"AUSSERIRDISCHE STADT STUFE EINS\"\n  STR_TLETH_P2: \"AUSSERIRDISCHE STADT STUFE ZWEI\"\n  STR_TLETH_P3: \"AUSSERIRIDISCHE STADT STUFE DREI\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"KEINE U-BOOT-BOXEN ZUR SCHIFFSPRODUKTION FREI!{SMALLLINE}Jedes Fliegende U-Boot, das zur Basis transferiert, gekauft oder dort produziert wird, nimmt eine U-Boot-Box ein. Bauen Sie eine neue Box, oder transferieren Sie ein U-Boot auf eine andere Basis.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"KEINE U-BOOT-BOXEN FÜR GEKAUFTES SCHIFF FREI!{SMALLLINE}Jedes Fliegende U-Boot, das zur Basis transferiert, gekauft oder dort produziert wird, nimmt eine U-Boot-Box ein. Bauen Sie eine neue Box, oder transferieren Sie ein U-Boot auf eine andere Basis.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"KEINE U-BOOT-BOXEN FÜR TRANSFER FREI!{SMALLLINE}Jedes Fliegende U-Boot, das zur Basis transferiert, gekauft oder dort produziert wird, nimmt eine U-Boot-Box ein. Bauen Sie eine neue Box, oder transferieren Sie ein U-Boot auf eine andere Basis.\"\n  STR_CANNOT_BUILD_HERE: \"KANN HIER NICHT BAUEN!{SMALLLINE}Sie können nur neben einer bereits vorhandenen Zelle bauen.\"\n  STR_NO_FREE_ACCOMODATION: \"KEIN WOHNRAUM FREI!{SMALLLINE}Zielbasis hat nicht genügend Raum in den Wohnblocks.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"NICHT GENUG WERKRAUM!{SMALLLINE}Bauen Sie eine neue Werkstatt, oder verringern Sie die Arbeit an anderen Projekten.\"\n  STR_NOT_ENOUGH_MONEY: \"NICHT GENUG GELD!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"NICHT GENUG LAGERRAUM!{SMALLLINE}Erstellen Sie neuen Lagerraum, oder verlegen Sie Bestände auf andere Basen.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"NICHT GENUG WOHNRAUM!{SMALLLINE}Bauen Sie neue Wohnblocks, oder transferieren Sie Personal auf andere Basen.\"\n  STR_LAUNCH_INTERCEPTION: \"ABFANGMANÖVER STARTEN\"\n  STR_CRAFT: \"FAHRZEUG\"\n  STR_STATUS: \"STATUS\"\n  STR_BASE: \"BASIS\"\n  STR_READY: \"FERTIG\"\n  STR_OUT: \"DRAUSSEN\"\n  STR_REPAIRS: \"REPARATUREN\"\n  STR_REFUELLING: \"AUFTANKEN\"\n  STR_REARMING: \"BEWAFFNEN\"\n  STR_TARGET: \"ZIEL: {0}\"\n  STR_WAY_POINT: \"WEGMARKE\"\n  STR_ARE_YOU_SURE_CYDONIA: \"Wollen Sie dieses U-Boot tatsächlich auf einen Einsatz nach T'leth schicken?\"\n  STR_YES: \"JA\"\n  STR_NO: \"NEIN\"\n  STR_SELECT_DESTINATION: \"BESTIMMUNGSORT WÄHLEN \"\n  STR_CYDONIA: \"T'LETH\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"ORT FÜR NEUE BASIS WÄHLEN\"\n  STR_RETURN_TO_BASE: \"RÜCKKEHR ZUR BASIS\"\n  STR_SELECT_NEW_TARGET: \"NEUES ZIEL WÄHLEN\"\n  STR_PATROL: \"PATROUILLE\"\n  STR_STATUS_: \"STATUS>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"Beschädigt - Kehren zur Basis zurü\\x81ck\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"Kein Treibstoff - Rückkehr zur Basis\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"MISSION KOMPLETT - RÜCKKEHR ZUR BASIS\"\n  STR_PATROLLING: \"PATROUILLIEREN\"\n  STR_TAILING_UFO: \"VERFOLGEN U-BOOT DER ALIENS\"\n  STR_INTERCEPTING_UFO: \"FANGEN AUSSERIRDISCHES U-BOOT-{0} AB\"\n  STR_RETURNING_TO_BASE: \"KEHREN ZUR BASIS ZURÜCK\"\n  STR_DESTINATION_UC_: \"ZIEL: WEGMARKE-{0}\"\n  STR_BASE_UC: \"BASIS>{ALT}{0}\"\n  STR_SPEED_: \"GESCHWINDIGKEIT>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"HÖCHSTGESCHWINDIGKEIT>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"TIEFE>{ALT}{0}\"\n  STR_AIRBORNE: \"IN DER LUFT\"\n  STR_VERY_LOW: \"SEICHT\"\n  STR_LOW_UC: \"NORMAL\"\n  STR_HIGH_UC: \"TIEF\"\n  STR_VERY_HIGH: \"SEHR TIEF\"\n  STR_FUEL: \"TREIBSTOFF>{ALT}{0}\"\n  STR_WEAPON_ONE: \"WAFFE-1>{ALT}{0}\"\n  STR_NONE_UC: \"KEINE\"\n  STR_ROUNDS_: \"RUNDE>{ALT}{0}\"\n  STR_WEAPON_TWO: \"WAFFE-2>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"FLIEGENDES U-BOOT\"\n  STR_BASE_: \"Basis>{0}\"\n  STR_NAME_UC: \"NAME\"\n  STR_AMMO_: \"MUNITION>{ALT}{0}\"\n  STR_CREW: \"CREW\"\n  STR_EQUIPMENT_UC: \"AUSRÜSTUNG\"\n  STR_ARMOR: \"PANZERUNG\"\n  STR_MAX: \"MAX>{ALT}{0}\"\n  STR_ROOKIE: \"Seemann\"\n  STR_SQUADDIE: \"Vollmatrose\"\n  STR_SERGEANT: \"Fähnrich\"\n  STR_CAPTAIN: \"Leutnant\"\n  STR_COLONEL: \"Oberleutnant\"\n  STR_COMMANDER: \"Kapitän\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Truppe wählen für {0}\"\n  STR_SORT_BY: \"SORTIERE NACH...\"\n  STR_ORIGINAL_ORDER: \"ORIGINALE REIHENFOLGE\"\n  STR_MISSIONS2: \"MISSIONEN\"\n  STR_KILLS2: \"ABSCHÜSSE\"\n  STR_WOUND_RECOVERY2: \"WUNDHEILUNG\"\n  STR_SPACE_AVAILABLE: \"RAUM VORHANDEN>{ALT}{0}\"\n  STR_SPACE_USED: \"PLATZ GENUTZT>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"PLATZ GENUTZT\"\n  STR_RANK: \"RANG\"\n  STR_WOUNDED: \"VERWUNDET\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Ausrüstung für {0}\"\n  STR_DEFENSE_VALUE: \"Verteidigungswert\"\n  STR_HIT_RATIO: \"Trefferquote\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}Fertig zur{NEWLINE}Landung nahe{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"Einsatz starten?\"\n  STR_SELECT_ARMAMENT: \"Bewaffnung wählen\"\n  STR_AMMUNITION_AVAILABLE: \"MUNITION\"\n  STR_ARMAMENT: \"BEWAFFNUNG\"\n  STR_NOT_AVAILABLE: \"-\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"PANZERUNG WÄHLEN FÜR{NEWLINE}{ALT}{0}\"\n  STR_TYPE: \"TYP\"\n  STR_PLASTIC_AQUA_ARMOR_UC: \"AQUA-PLASTIK-PANZER\"\n  STR_ION_ARMOR_UC: \"IONENPANZER\"\n  STR_MAGNETIC_ION_ARMOR_UC: \"MAGNET. IONEN-PANZER\"\n  STR_PLASTIC_AQUA_ARMOR_UFOPEDIA: \"Diese Panzerung benutzt eine neu entdeckte Substanz der Aliens, Aqua-Kunststoffe, die unseren Aquanauten eine bessere Chance gegen die Invasion der Aliens gibt\"\n  STR_ION_ARMOR_UFOPEDIA: \"Ein neuer Schutz \\x81für Aquanauten, eine Panzerung mit einer Ionenenergiequelle, die die Geschwindigkeit des Trägers erhöht und den Kampftruppen den besten Schutz bietet.\"\n  STR_MAGNETIC_ION_ARMOR_UFOPEDIA: \"Eine Verbesserung der Ionenpanzerung, mit Magnet-Technologie, die Bewegungsfreiheit in der Wasserumgebung bietet.\"\n  STR_SELECT_ARMOR: \"Panzerung wählen\"\n  STR_NORTH: \"NORD\"\n  STR_NORTH_EAST: \"NORDOST\"\n  STR_EAST: \"OST\"\n  STR_SOUTH_EAST: \"SÜDOST\"\n  STR_SOUTH: \"SÜD\"\n  STR_SOUTH_WEST: \"SÜDWEST\"\n  STR_WEST: \"WEST\"\n  STR_NORTH_WEST: \"NORDWEST\"\n  STR_SELECT_ACTION: \"AKTION WÄHLEN\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"ABFANGVERFOLGUNG FORTSETZEN\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"VERFOLGEN OHNE ABZUFANGEN\"\n  STR_VERY_LARGE: \"SEHR GROSS\"\n  STR_LARGE: \"GROSS\"\n  STR_MEDIUM_UC: \"MITTELGROSS\"\n  STR_SMALL: \"KLEIN\"\n  STR_VERY_SMALL: \"SEHR KLEIN\"\n  STR_GROUNDED: \"GELANDET\"\n  STR_DETECTED: \"Entdeckt\"\n  STR_SIZE_UC: \"GRÖSSE\"\n  STR_ALTITUDE: \"TIEFE\"\n  STR_HEADING: \"KURS\"\n  STR_SPEED: \"GESCHWINDIGKEIT\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"USO ZENTRIEREN-ZEIT=5 Sek\"\n  STR_TRACKING_LOST: \"ZIELVERFOLGUNG VERLOREN\"\n  STR_REDIRECT_CRAFT: \"FAHRZEUG UMLEITEN\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"Rückkehr auf letzte bekannte U-Boot-Position\"\n  STR_UFO_: \"AUSSERIRDISCHES U-BOOT-{0}\"\n  STR_ALIEN_BASE_: \"AUSSERIRDISCHE KOLONIE-{0}\"\n  STR_CRASH_SITE_: \"ABSTURZSTELLE-{0}\"\n  STR_LANDING_SITE_: \"LANDEORT-{0}\"\n  STR_WAY_POINT_: \"WEGMARKE-{0}\"\n  STR_TERROR_SITE: \"TERROR-ORT-{0}\"\n  STR_ARTIFACT_SITE: \"ARTEFAKT-STANDORT-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}erreichte Ziel{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"Patrouillieren\"\n  STR_ALIEN_ORIGINS: \"Außerirdischer Herkunft\"\n  STR_THE_ULTIMATE_THREAT: \"Die schwerste Bedrohung\"\n  STR_TLETH_ALIEN_CITY: \"T'leth, die Stadt der Aliens \"\n  STR_UFOPAEDIA: \"UFOpedia\"\n  STR_XCOM_CRAFT_ARMAMENT: \"X-COM-FAHRZEUGE & -WAFFEN\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"UNTERWASSERWAFFENSYSTEME (UWS)\"\n  STR_WEAPONS_AND_EQUIPMENT: \"ALLGEMEINE AUSRÜSTUNG\"\n  STR_ALIEN_ARTIFACTS: \"AQUATISCHE ARTEFAKTE\"\n  STR_BASE_FACILITIES: \"X-COM-EINRICHTUNGEN\"\n  STR_ALIEN_LIFE_FORMS: \"AUSSERIRDISCHE KREATUREN\"\n  STR_ALIEN_RESEARCH_UC: \"AUSSERIRDISCHE TECHNOLOGIE\"\n  STR_UFO_COMPONENTS: \"NEUE U-TECHNOLOGIEN\"\n  STR_UFOS: \"AUSSERIRDISCHE U-BOOTE\"\n  STR_SELECT_ITEM: \"GEGENSTAND WÄHLEN\"\n  STR_ACCELERATION: \"BESCHLEUNIGUNG>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"TREIBSTOFFKAPAZITÄT>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"WAFFENZELLEN>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"SCHADENSKAPAZITÄT>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"FRACHTRAUM>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"UWS KAPAZITÄT>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Schaden\"\n  STR_RANGE: \"Reichweite\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Genauigkeit\"\n  STR_RE_LOAD_TIME: \"Zeit zum Neuladen....\"\n  STR_SECONDS: \"{0}Sek\"\n  STR_DAMAGE_ARMOR_PIERCING: \"PANZERBRECHEND\"\n  STR_DAMAGE_INCENDIARY: \"PHOSPHORHALTIG\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"HOCHEXPLOSIV\"\n  STR_DAMAGE_LASER_BEAM: \"GAUßSCHER STRAHL\"\n  STR_DAMAGE_PLASMA_BEAM: \"SONARSTRAHL\"\n  STR_DAMAGE_STUN: \"EINFRIEREN\"\n  STR_DAMAGE_MELEE: \"NAHKAMPF\"\n  STR_DAMAGE_ACID: \"SÄURE\"\n  STR_DAMAGE_SMOKE: \"RAUCH\"\n  STR_SHOT_TYPE: \"TYP\"\n  STR_ACCURACY_UC: \"GENAUIGKEIT\"\n  STR_TIME_UNIT_COST: \"ZE-KOSTEN\"\n  STR_DAMAGE_UC: \"SCHADEN\"\n  STR_AMMO: \"MUNITION\"\n  STR_SHOT_TYPE_AUTO: \"Automatisch\"\n  STR_SHOT_TYPE_SNAP: \"Schnellschuss\"\n  STR_SHOT_TYPE_AIMED: \"Zeilschuss\"\n  STR_CONSTRUCTION_TIME: \"Bauzeit\"\n  STR_CONSTRUCTION_COST: \"Baukosten\"\n  STR_MAINTENANCE_COST: \"Instandhaltungskosten\"\n  STR_LOW: \"Niedrig\"\n  STR_MEDIUM: \"Mittel\"\n  STR_HIGH: \"Hoch\"\n  STR_CRAFT_WEAPON: \"U-Waffe\"\n  STR_CRAFT_AMMUNITION: \"U-Munition\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Schwere Waffensysteme\"\n  STR_WEAPON: \"Waffe\"\n  STR_AMMUNITION: \"Munition\"\n  STR_EQUIPMENT: \"Ausrüstung\"\n  STR_ALIEN_CORPSE: \"Leiche eines Alien\"\n  STR_UFO_COMPONENT: \"Teil der außerirdischen U-Boote\"\n  STR_PERSONAL_ARMOR: \"Rüstung\"\n  STR_RAW_MATERIALS: \"Rohmaterialien\"\n  STR_HWP_SOLID_HARPOON_BOLTS: \"Harpunenbolzen\"\n  STR_ALIEN: \"Außerirdischer\"\n  STR_AQUATOID: \"Aquatoide\"\n  STR_GILLMAN: \"Kiemenmensch\"\n  STR_LOBSTERMAN: \"Hummermensch\"\n  STR_TASOTH: \"Tasoth\"\n  STR_CALCINITE: \"Calcinite\"\n  STR_DEEP_ONE: \"Ungetüm\"\n  STR_BIODRONE: \"Bio-Drohne\"\n  STR_TENTACULAT: \"Tentakulat\"\n  STR_TRISCENE: \"Triszene\"\n  STR_HALLUCINOID: \"Halluzinoide\"\n  STR_XARQUID: \"Xintfisch\"\n  STR_ZOMBIE: \"Zombie\"\n  STR_LIVE_COMMANDER: \" Kapitän\"\n  STR_LIVE_NAVIGATOR: \" Navigator\"\n  STR_LIVE_MEDIC: \" Arzt\"\n  STR_LIVE_TECHNICIAN: \" Techniker\"\n  STR_LIVE_SQUAD_LEADER: \" Truppenführer\"\n  STR_LIVE_SOLDIER: \" Soldat\"\n  STR_LIVE_TERRORIST: \" Terrorist\"\n  STR_AQUATOID_COMMANDER: \"Aquatoiden Kommandant\"\n  STR_AQUATOID_NAVIGATOR: \"Aquatoiden Navigator\"\n  STR_AQUATOID_MEDIC: \"Aquatoiden Arzt\"\n  STR_AQUATOID_TECHNICIAN: \"Aquatoiden Techniker \"\n  STR_AQUATOID_SQUAD_LEADER: \"Aquatoiden Truppenführer\"\n  STR_AQUATOID_SOLDIER: \"Aquatoiden Soldat\"\n  STR_GILLMAN_COMMANDER: \"Kiemenmensch Kommandant\"\n  STR_GILLMAN_TECHNICIAN: \"Kiemenmensch Techniker\"\n  STR_GILLMAN_SQUAD_LEADER: \"Kiemenmensch Truppenführer\"\n  STR_GILLMAN_SOLDIER: \"Kiemenmensch Soldat\"\n  STR_LOBSTERMAN_COMMANDER: \"Hummermensch Kommandant\"\n  STR_LOBSTERMAN_NAVIGATOR: \"Hummermensch Navigator\"\n  STR_LOBSTERMAN_TECHNICIAN: \"Hummermensch Techniker\"\n  STR_LOBSTERMAN_SQUAD_LEADER: \"Hummermensch Truppenführer \"\n  STR_LOBSTERMAN_SOLDIER: \"Hummermensch Soldat\"\n  STR_TASOTH_SQUAD_LEADER: \"Tasoth Truppenführer\"\n  STR_TASOTH_SOLDIER: \"Tasoth Soldat\"\n  STR_CALCINITE_TERRORIST: \"Calciniten Terrorist\"\n  STR_DEEP_ONE_TERRORIST: \"Ungetüm Terrorist\"\n  STR_BIODRONE_TERRORIST: \"Bio-Drohne Terrorist\"\n  STR_TENTACULAT_TERRORIST: \"Tentakulat Terrorist\"\n  STR_TRISCENE_TERRORIST: \"Triszene Terrorist\"\n  STR_HALLUCINOID_TERRORIST: \"Halluzinoiden Terrorist\"\n  STR_XARQUID_TERRORIST: \"Xintfisch Terrorist\"\n  STR_ION_BEAM_ACCELERATORS: \"Ionenstrahlbeschleuniger\"\n  STR_MAGNETIC_NAVIGATION: \"Magnetische Navigation\"\n  STR_ALIEN_SUB_CONSTRUCTION: \"U-Boot-Bau der Aliens\"\n  STR_ALIEN_CRYOGENICS: \"Außerirdische Kryogenzellen\"\n  STR_ALIEN_CLONING: \"Alien-Klonapparaturen\"\n  STR_ALIEN_LEARNING_ARRAYS: \"Außerirdische Lernmaschinen\"\n  STR_ALIEN_IMPLANTER: \"Außerirdischer Implantierer\"\n  STR_EXAMINATION_ROOM: \"Untersuchungsraum\"\n  STR_AQUA_PLASTICS: \"Aqua-Kunststoffe\"\n  STR_ALIEN_REANIMATION_ZONE: \"Außerirdische Re-Animierungszone\"\n  STR_PLASTIC_AQUA_ARMOR: \"Aqua-Kunststoff-Panzerung\"\n  STR_ION_ARMOR: \"Ionenpanzerung\"\n  STR_MAGNETIC_ION_ARMOR: \"Magnet-Ionenpanzerung\"\n  STR_HWP_AQUA_JET_MISSILES: \"Wasser Jet Torpedo\"\n  STR_HWP_DISPLACER_PWT: \"P.W.-Torpedo\"\n  STR_GAUSS_TECH: \"Gauss'sche Technologie\"\n  STR_NEW_FIGHTER_FLYING_SUB: \"Neues Fliegendes Kampf-U-Boot\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Neuer Kampf-Transporter\"\n  STR_THE_LATEST_FLYING_SUB: \"Das neueste Fliegende U-Boot\"\n  STR_ARMOR_PIERCING: \"PANZERBRECHEND\"\n  STR_COELACANTH_GAS_CANNON: \"Coelacanth/Gaskanone\"\n  STR_COELACANTH_AQUA_JET: \"Coelacanth/Aqua-Jet\"\n  STR_COELACANTH_GAUSS: \"Coelacanth/Gauss\"\n  STR_DISPLACER_SONIC: \"Verdränger/Sonar\"\n  STR_DISPLACER_PWT: \"Verdränger /P. W. T.\"\n  STR_AJAX_LAUNCHER: \"Ajax -Werfer\"\n  STR_DUP_HEAD_LAUNCHER: \"A.U.P.-Sprengkopfwerfer\"\n  STR_CRAFT_GAS_CANNON: \"U-Boot-Gaskanone\"\n  STR_PWT_CANNON: \"I.W.V.-Kanone\"\n  STR_GAUSS_CANNON: \"Gauss'sche Kanone\"\n  STR_GAUSS_CANNON_AMMO: \"Munition für Gauss'sche Kanone\"\n  STR_SONIC_OSCILLATOR: \"Sonaroszillator\"\n  STR_AJAX_TORPEDOES: \"Ajax-Torpedos\"\n  STR_DUP_HEAD_TORPEDOES: \"A.U.P.-Sprengkopftorpedos\"\n  STR_CRAFT_GAS_CANNON_ROUNDS_X50: \"Gasmunition(x50)\"\n  STR_SONIC_WAVE: \"Sonarwelle\"\n  STR_PULSE_WAVE_TORPEDOES: \"I.W.V.-Munition\"\n  STR_SOLDIER: \"Aquanaut\"\n  STR_SCIENTIST: \"Wissenschaftler\"\n  STR_ENGINEER: \"Techniker\"\n  STR_NORTH_ATLANTIC: \"Nordatlantik\"\n  STR_SOUTH_ATLANTIC: \"Südatlantik\"\n  STR_NORTH_PACIFIC: \"Nordpazifik\"\n  STR_SOUTH_PACIFIC: \"Südpazifik\"\n  STR_MEDITERRANEAN: \"Mittelmeer\"\n  STR_SOUTH_CHINA_SEA: \"Südchinesische See\"\n  STR_INDIAN_OCEAN: \"Indischer Ozean\"\n  STR_THE_EAST_SEA: \"Japanisches Meer\"\n  STR_NORTH_SEA: \"Nordsee\"\n  STR_CARRIBEAN: \"Karibik\"\n  STR_ANTARCTIC: \"Antarktis\"\n  STR_ARCTIC: \"Arktis\"\n  STR_EURASIA: \"Eurasien\"\n  STR_NORTH_AMERICA: \"Nordamerika\"\n  STR_AFRICA: \"Afrika\"\n  STR_MAXIMUM_SPEED: \"Höchstgeschwindigkeit\"\n  STR_TRANSMISSION_RESOLVER_UC: \"TRANSMISSIONSRESOLVER\"\n  STR_TRITON: \"TRITON\"\n  STR_HAMMERHEAD: \"HAMMERHEAD\"\n  STR_LEVIATHAN: \"LEVIATHAN\"\n  STR_BARRACUDA: \"BARRACUDA\"\n  STR_MANTA: \"MANTA\"\n  STR_UFO: \"AUSSERIRDISCHES U-BOOT\"\n  STR_AJAX: \"AJAX\"\n  STR_DUP_HEAD: \"A.U.P.-SPRENGKOPF\"\n  STR_CRAFT_GAS_CANNON_UC: \"U-BOOT-GASKANONE\"\n  STR_PWT_CANNON_UC: \"I.W.V.-KANONE\"\n  STR_GAUSS_CANNON_UC: \"GAUSS'SCHE KANONE\"\n  STR_SONIC_OSCILLATOR_UC: \"SONAROSZILLATOR\"\n  STR_DAMAGE_CAPACITY: \"Schadenskapazität\"\n  STR_WEAPON_POWER: \"Waffenstärke\"\n  STR_WEAPON_RANGE: \"Waffenreichweite\"\n  STR_AIR_LOCK: \"Luftschleuse\"\n  STR_LABORATORY: \"Labor\"\n  STR_WORKSHOP: \"Werkstatt\"\n  STR_STANDARD_SONAR: \"Standard-Sonar\"\n  STR_WIDE_ARRAY_SONAR: \"Langstrecken-Sonar\"\n  STR_TORPEDO_DEFENSES: \"Torpedoverteidigung\"\n  STR_GENERAL_STORES: \"Allgemeine Lager\"\n  STR_ALIEN_CONTAINMENT: \"Quarantänestation\"\n  STR_GAUSS_DEFENSES: \"Gauss'sche Verteidigung\"\n  STR_SONIC_DEFENSES: \"Sonarverteidigung\"\n  STR_PWT_DEFENSES: \"I.W.V.-Verteidigung\"\n  STR_BOMBARDMENT_SHIELD: \"Druckbombardment-Schild\"\n  STR_MC_GENERATOR: \"M.S.-Generator\"\n  STR_MC_LAB: \"M.S.-Labor\"\n  STR_TRANSMISSION_RESOLVER: \"Transmissionsresolver\"\n  STR_SUB_PEN: \"U-Boot-Box\"\n  STR_USA: \"USA\"\n  STR_ALASKA: \"Alaska\"\n  STR_EU_SYNDICATE: \"Euro-Syndikat\"\n  STR_ARABIAN_BLOC: \"Arabischer Block\"\n  STR_EGYPTIAN_CARTEL: \"Ägyptisches Kartell\"\n  STR_AFRICA_CORP: \"Afrikakonzern\"\n  STR_BRAZILIAN_UNION: \"Brasilianische Union\"\n  STR_NEW_MEXICO: \"Neu-Mexiko\"\n  STR_ASIAN_COALITION: \"Asiatische Koalition\"\n  STR_SCANDINAVIA: \"Skandinavien\"\n  STR_NEO_JAPAN: \"Neo-Japan\"\n  STR_FREE_CHINA: \"Freies China\"\n  STR_AUSTRALASIA: \"Australasien\"\n  STR_FED_KOREA: \"Vereinigtes Korea\"\n  STR_EURASIA_UC: \"EURASIEN\"\n  STR_ICELANDIC_UNION: \"Isländische Union\"\n  STR_TANK: \"U-Waffensystem\"\n  STR_CIVILIAN: \"Zivilist\"\n  STR_JAN: \"Jan\"\n  STR_FEB: \"Feb\"\n  STR_MAR: \"Mär\"\n  STR_APR: \"Apr\"\n  STR_MAY: \"Mai\"\n  STR_JUN: \"Jun\"\n  STR_JUL: \"Jul\"\n  STR_AUG: \"Aug\"\n  STR_SEP: \"Sep\"\n  STR_OCT: \"Okt\"\n  STR_NOV: \"Nov\"\n  STR_DEC: \"Dez\"\n  STR_INTERNATIONAL_RELATIONS: \"Internationale Beziehungen\"\n  STR_COUNTRY: \"Organisation\"\n  STR_FUNDING: \"Finanzierung\"\n  STR_CHANGE: \"Änderung\"\n  STR_WEAPON_SYSTEMS: \"WAFFEN-SYSTEME\"\n  STR_HWPS: \"UWS\"\n  STR_DAMAGE_UC_: \"SCHADEN>{ALT}{0}\"\n  STR_AIR_LOCK_UFOPEDIA: \"Durch die Luftschleuse kann Ausrüstung und Personal in die Unterwasser-Basis gebracht werden oder sie verlassen. Daher wird sie immer zuerst gebaut. Auch gegnerische Kräfte können durch den Luftschleusenbereich eindringen.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Jeder Wohnblock kann bis zu 50 Mitarbeiter beherbergen. Die Einrichtung ist recht primitiv und funktional gehalten.\"\n  STR_LABORATORY_UFOPEDIA: \"Fünfzig Wissenschaftler können in einem Laborblock arbeiten.  Die Labors sind komplett mit der neuesten Technologie zur Untersuchung von Materialproben, biochemischen Vorgängen und Waffen ausgestattet.  Die X-Com hat Zugang zu den besten Forschungslabors der Welt, militärisch wie kommerziell.\"\n  STR_WORKSHOP_UFOPEDIA: \"Eine Werkstatt enthält alle Einrichtungen, die nötig sind, um die neuesten Entwicklungen aus den Labors zu bauen. 50 Techniker können in einer Werkstatt arbeiten. Die im Bau befindlichen Werkstücke nehmen weiteren Platz ein.\"\n  STR_STANDARD_SONAR_UFOPEDIA: \"Ein Standardsonarsystem besitzt eine Reichweite von über 450 Kilometer in fast allen Tiefen und ist mit geostationären Satellitennetzen zur Oberflächenanalyse verbunden. Jeder Scanner hat eine Chance von 10%, ein Unterwasser- oder Luftfahrzeug pro Abtastzyklus (10 min) zu erfassen.\"\n  STR_WIDE_ARRAY_SONAR_UFOPEDIA: \"Ein Standardsonarsystem besitzt eine Reichweite von über 700 Kilometer in fast allen Tiefen und ist mit geostationären Satellitennetzen zur Oberflächenanalyse verbunden. Jeder Scanner hat eine Chance von 20%, ein Unterwasser- oder Luftfahrzeug pro Abtastzyklus (30 min) zu erfassen.\"\n  STR_TORPEDO_DEFENSES_UFOPEDIA: \"Torpedoverteidigungssysteme bieten Schutz vor Angriffen durch gegnerische Unterwasserfahrzeuge, die an der Basis andocken wollen.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"Alle Ausrüstungen, Waffensysteme, Munition, geborgenen Materialien und Schweren Waffensysteme werden gelagert, außer Ausrüstung, die für U-Boote in Boxen bestimmt ist.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"Lebende Aliens müssen in besonderen Einrichtungen gehalten werden. In diesen Einheiten können sie am Leben gehalten, und ihr Kampfpotential kann auf Null verringert werden. Die Quarantänestation kann bis zu 10 Aliens fassen.\"\n  STR_GAUSS_DEFENSES_UFOPEDIA: \"Die Gauss'sche Verteidigung ist der allerneueste und effektivste Schutz vor Angriffen durch gegnerische U-Boote.\"\n  STR_SONIC_DEFENSES_UFOPEDIA: \"Die Sonaroszillatorverteidigung bietet starken und effektiven Schutz vor Aggressoren.\"\n  STR_PWT_DEFENSES_UFOPEDIA: \"Impulswellentorpedos bieten die effektivste Verteidigung gegen Angriffe der Aliens. Diese Geschosse haben superdichte Gefechtsköpfe, die alle bekannten Arten von Panzerung durchdringen können. Die von ihnen erzeugten Magnetwellen deaktivieren elektronische Verteidigungssysteme.\"\n  STR_BOMBARDMENT_SHIELD_UFOPEDIA: \"Das Druckbombardmentschild schützt die Basis vor außerirdischen U-Booten und erzeugt ein Hallfeld, das die angreifenden U-Boote lang genug abwehrt, damit die Verteidigungssysteme wiederholt feuern können. Dadurch wird die Wirkung jedes Verteidigungssystems verdoppelt.\"\n  STR_MC_GENERATOR_UFOPEDIA: \"Da die Aliens Molekülsteuerungstechniken verwenden, um die Präsenz von Lebewesen zu entdecken, kann mit Hilfe eines negativen M.S.-Emitters die Basis mit einem undurchdringlichen Schild umgeben werden, der die Aliens verwirrt und unsere Anwesenheit verbirgt.\"\n  STR_MC_LAB_UFOPEDIA: \"Im Labor für Molekularsteuerung (M.S.) können bis zu zehn Aquanauten mit Implantaten ausgestattet und trainiert werden. Die Implantate werden operativ in die Schädel der Aquanauten eingepflanzt. Ausgiebiges Training ermöglicht es ihnen schließlich ihre Implantate zu benutzen. Die durch das Implantat erlangten Fähigkeiten können in Verbindung mit einem M.S.-Störer im Kampf als Waffe eingesetzt werden.\"\n  STR_TRANSMISSION_RESOLVER_UFOPEDIA: \"Aliens kommunizieren mit Hilfe des implantierten Molekülsteuerungsnetzwerks, das sie eingerichtet haben. Der Übertragungs-Resolver fängt die Sendungen der U-Boote auf und dekodiert die Informationen. Typ des außerirdischen U-Bootes, Spezies und Art der Aktivität können so ermittelt werden.\"\n  STR_SUB_PEN_UFOPEDIA: \"Jede Box kann ein U-Boot aufnehmen. Hier werden Wartung, Auftanken und Reparaturen für die X-Com-U-Boot-Flotte durchgeführt.  Jedes Fliegende U-Boot, das auf der Basis stationiert ist, muß eine freie Box zugeteilt bekommen, die von anderen U-Booten nicht verwendet werden kann, auch wenn das zugeteilte U-Boot im Einsatz ist.\"\n  STR_DART_PISTOL_UFOPEDIA: \"Die X-Com Dartpistole ist eine kleine, genaue und leistungsstarke Einheit mit einem Magazin für 12 Dart-Projektile. Die Darts werden über eine Gaspatrone in der Munitionshalterung abgefeuert.\"\n  STR_JET_HARPOON_UFOPEDIA: \"Das Aqua-Gewehr, das aus versiegelten Paketen 10 hohle Stahlharpunen feuert, ist treffsicher und durchschlagend. Jede Harpune hat ihren eigenen Gasvorrat.\"\n  STR_GAS_CANNON_UFOPEDIA: \"Dieses Schwergewicht einer Kanone aus der Gastechnologiefamilie feuert massive Bolzen mit HE- oder Phosphor-Spitzen. Sehr beliebte Waffe bei erfahrenen Aquanauten.\"\n  STR_HYDRO_JET_CANNON_UFOPEDIA: \"Hydro-Jet-Kanonen gehören zum Waffensystem der schweren Infanterie. Die Kanone feuert magnesiumbetriebene Mini-Torpedos. Sie ist zwar effektiv, aber auch unbeweglich, unhandlich und nur für den Einsatz unter Wasser geeignet.\"\n  STR_TORPEDO_LAUNCHER_UFOPEDIA: \"Dieses wahre Schwergewicht von einem Werfer feuert drei Arten von Torpedos, jeder mit eigenem Antrieb. Eine verheerende Waffe, die jedoch manuell geladen werden muß. Die Munition besteht aus großen oder kleinen hochexplosiven Torpedos mit Phosphorköpfen die alle nur unter Wasser eingesetzt werden Können.\"\n  STR_GAUSS_PISTOL_UFOPEDIA: \"Die Gauss'sche Pistole verwendet beschleunigte Teilchen, eine Neuentwicklung in der modernen Waffentechnik. Sie ist schnell, genau und funktioniert \\x81über und unter Wasser. Die Gauss-Technologie ist eine Fortführung der Plasmatechnologie des letzten  Krieges.\"\n  STR_GAUSS_PISTOL_CLIP_UFOPEDIA: \"Die Gauss'sche Pistole verwendet beschleunigte Teilchen, eine Neuentwicklung in der modernen Waffentechnik. Sie ist schnell, genau und funktioniert \\x81über und unter Wasser. Die Gauss-Technologie ist eine Fortführung der Plasmatechnologie des letzten Krieges.\"\n  STR_GAUSS_RIFLE_UFOPEDIA: \"Dieses Gewehr ist durch seinen Doppelteilchenbeschleuniger ein Fortschritt gegenüber der Gauss'schen Pistole. Statt eines eleriumbetriebenen Plasmasystems verwenden wir einen Mikroteilchenbeschleuniger, der einen Strahl von Anti-Protonen erzeugt.\"\n  STR_GAUSS_RIFLE_CLIP_UFOPEDIA: \"Dieses Gewehr ist durch seinen Doppelteilchenbeschleuniger ein Fortschritt gegenüber der Gauss'schen Pistole. Statt eines eleriumbetriebenen Plasmasystems verwenden wir einen Mikroteilchenbeschleuniger, der einen Strahl von Anti-Protonen erzeugt.\"\n  STR_HEAVY_GAUSS_UFOPEDIA: \"Die schwere Gauss ist unhandlich, aber „äußerst wirksam. Sie besitzt drei Teilchenbeschleuniger und kommt praktisch überall durch. Der Anti-Proton-Strahl ist in einem Gallium-Arsen-Behälter, der bei Aufprall explodiert und die Anti-Materie entlädt.\"\n  STR_HEAVY_GAUSS_CLIP_UFOPEDIA: \"Die schwere Gauss ist unhandlich, aber „äußerst wirksam. Sie besitzt drei Teilchenbeschleuniger und kommt praktisch überall durch. Der Anti-Proton-Strahl ist in einem Gallium-Arsen-Behälter, der bei Aufprall explodiert und die Anti-Materie entlädt.\"\n  STR_MAGNA_BLAST_GRENADE_UFOPEDIA: \"Diese standardmäßige Granate hat einen präzise arbeitenden, komplexen Timer.\"\n  STR_DYE_GRENADE_UFOPEDIA: \"Farbgranaten haben eine doppelte Funktion, einmal bieten sie Deckung in ungeschützten Situationen. Die Farbe, die sowohl im Wasser wie auf dem Land funktioniert, wird in einer Teilchenwolke ausgestoßen und erzeugt im Wasser, ähnlich wie bei Tintenfischen, eine dunkle Flüssigkeit oder in der Luft eine dichte Wolke.\"\n  STR_PARTICLE_DISTURBANCE_GRENADE_UFOPEDIA: \"Eine Näherungsgranate, die wie eine normale Granate geworfen, doch erst durch Bewegungen in ihrer Nähe gezündet wird. Erfahrung und Training sind für den richtigen Gebrauch erforderlich.\"\n  STR_MAGNA_PACK_EXPLOSIVE_UFOPEDIA: \"Dieser Sprengstoff sollte nur zu Abrißzwecken verwendet werden. Doch hat die Erfahrung gelehrt, daß er auch fü\\x81r die Vernichtung von Aliens verwendbar ist. Der Explosionsradius ist groß, daher sollten sich keine Aquanauten innerhalb des Sicherheitsabstandes aufhalten.\"\n  STR_PARTICLE_DISTURBANCE_SENSOR_UFOPEDIA: \"Dieses Gerät verwendet einige Detektoren und Computersysteme zur Erkennung sich bewegender Einheiten. Klicken Sie das Störsensor-Icon auf dem Taktikschirm an. Wählen Sie die Option 'Sensor Benutzen' aus dem Menü. Die Anzeige gibt durch einen Pfeil im Zentrum die Blickrichtung des Aquanauten an (Norden ist oben). Die Echoanzeigen zeigen Einheiten an, die kürzlich ihre Stellung gewechselt haben. Große Einheiten oder sich schnell bewegende Einheiten erzeugen größere Echoanzeigen. Statische Einheiten werden nicht angezeigt.\"\n  STR_MEDI_KIT_UFOPEDIA: \"Hierbei stehen Sie einem verwundeten X-Com-Soldaten gegenüber oder befinden sich über dem Körper eines bewußtlosen Aquanauten..{NEWLINE}HEILEN> Rot zeigt Wunden an. Wählen Sie die entsprechende Körperstelle, und klicken Sie den Knopf 'Heilen' an. Eine sonst tödliche Wunde wird geheilt und die Gesundheit wiederhergestellt.{NEWLINE}STIMULANS> Gibt Energie zurück und belebt bewußtlose Aquanauten. Dabei müssen Sie direkt über dem Körper des Aquanauten stehen.{NEWLINE}SCHMERZMITTEL> Stellt die Moral eines verwundeten Aquanauten wieder her.\"\n  STR_MC_DISRUPTOR_UFOPEDIA: \"Das Allerneueste in der M.S.-Technologie. Kann nur unter Wasser von Aquanauten mit M.S.-Fähigkeiten verwendet werden. Klicken Sie das Störer-Icon an, wählen Sie die Art des Angriffs, und geben Sie mit dem Cursor ein Ziel an. Es gibt zwei Arten des Angriffs per Störer:{NEWLINE}BLOCKIEREN DES IMPLANTATS> Im Erfolgsfall wird die Einheit verwirrt und kann in Panik geraten.{NEWLINE}IMPLANTATKONTROLLE> Im Erfolgsfall gewinnen Sie die Kontrolle über die gegnerische Einheit.\"\n  STR_THERMAL_TAZER_UFOPEDIA: \"Dieses Gerät kann nur im Nahkampf eingesetzt werden, es betäubt einen lebenden Organismus, ohne ihn zu töten, durch Tiefgefrieren.\"\n  STR_VIBRO_BLADE_UFOPEDIA: \"Die Vibroklinge ist eine scharfe Klinge aus Titanium, die sich mit \\x81ber 6000 U/Min dreht und auch die beste Panzerung durchdringen kann. Die Energiequelle ist eine Erfindung der Aliens; frühere Versuche, diese Objekte nachzubauen, scheiterten, unsere Klingen waren zu langsam oder explodierten unter dem Druck.\"\n  STR_THERMIC_LANCE_UFOPEDIA: \"Die Thermische Lanze ist eine logische Weiterentwicklung der Vibroklingentechnologie. Die Klinge dreht sich schneller und eine Zrbit-Energiequelle überhitzt die Klinge, so daß Panzerung wie weiche Butter zerschnitten werden kann.\"\n  STR_HEAVY_THERMIC_LANCE_UFOPEDIA: \"Die schwere termische Lanze ist eine leistungsstärkere Version der termischen Lanze. Dual-Hitzegeneratoren und eine extrem hohe Rotationsgeschwindigkeit bedeuten, dass die schwere termische Lanze gegen jede Art von Material praktisch unaufhaltbar ist.\"\n  STR_SONIC_CANNON_UFOPEDIA: \"Die Sonarkanone ist die mächtigste aus der Familie der Sonarwaffen. Ihr Audio-Oszilator hat eine höhere Bandbreite und ihre Echokammer ist größer als die des Blaster-Gewehrs. Die Kanone besitzt außerdem ein Puls-Detonations-System welches die emitierte Ultraschallwelle durch Modulation verändert, sodass der akustische Schock noch wirkungsvoller ist.\"\n  STR_CANNON_POWER_CLIP_UFOPEDIA: \"Dieses kompakte Gerät wird als Munition für schwere Plasmageschütze verwendet.  Es enthält eine kleine Menge Elerium.\"\n  STR_SONIC_BLASTA_RIFLE_UFOPEDIA: \"Eine verbesserte Version, die auch mit Schall arbeitet. Nicht einmal Stahl kann dieser Waffe widerstehen. Der hochkompakte Wellensender wird durch Supraleiter-verstärker maximiert, um die Wirkung der Waffe zu erhöhen.\"\n  STR_BLASTA_POWER_CLIP_UFOPEDIA: \"Dieser kleine Gegenstand wird als Energiequelle für ein Sonargewehr verwendet, eine effektive Waffe der Aliens, und enthält geringe Mengen Zrbit\"\n  STR_SONIC_PISTOL_UFOPEDIA: \"Sonarpistolen sind eine Waffe der Aliens, die auf Ultraschallwellen beruht, die Knochen innerhalb von Sekunden in Gelee verwandeln.  Die Ultraschallwellen liegen über dem Hörumfang von Menschen.\"\n  STR_PISTOL_POWER_CLIP_UFOPEDIA: \"Die Energiequelle der kompakten Sonarpistole. Enthält Zrbit - die Quelle der außerirdischen Macht.\"\n  STR_DISRUPTOR_PULSE_LAUNCHER_UFOPEDIA: \"Hierbei handelt es sich um ein gelenktes U-Waffensystem der Aliens, das selbsttreibende 'Störprojektile' feuert. Wird die Waffe durch Anklicken ausgelöst, so setzt sie 'Wegmarken', denen die Projektile folgen. Sind genug Wegmarken platziert, klicken Sie das Start-Icon an.\"\n  STR_DISRUPTOR_AMMO_UFOPEDIA: \"Hierbei handelt es sich um eine hochexplosive Rakete mit einem intelligenten Lenksystem.  Sie wird mit Hilfe einer Blaster-Vorrichtung abgeschossen.\"\n  STR_THERMAL_SHOK_LAUNCHER_UFOPEDIA: \"Ein kleiner Thermoschock-Werfer, der chemische Frostbomben abfeuert. Sehr nützlich, um Aliens lebend zu fangen.\"\n  STR_THERMAL_SHOK_BOMB_UFOPEDIA: \"Die Betäubungsbombe wird zum Fangen von lebenden Menschen verwendet, sie kann jedoch auch gegen Außerirdische Rassen eingesetzt werden.\\nAbgefeuert wird sie durch die kleine Abschussrampe.\"\n  STR_SONIC_PULSER_UFOPEDIA: \"Dieses Gerät arbeitet wie eine standardmäßige Granate - nur ist es sehr viel stärker. Die Granate verwendet eine einzige Impulssonarexplosion, die in alle Richtungen gleichzeitig ausgeschickt wird.\"\n  STR_MC_READER_UFOPEDIA: \"Im Körper der Aliens haben wir operativ eingesetzte Einheiten gefunden. Es handelt sich um von den Aquatoiden konstruierte Kontrollimplantate, die Informationen ü\\x81ber große Entfernung vom Schlachtfeld senden. Das M.S.-Lesegerät ist ein Kommunikationsgerät der Aliens, mit dem Informationen direkt von M.S.-Implantaten eingeholt werden können. X-Com-Einheiten können dieses Gerät benutzen, um die Merkmale eines Aliens anzeigen zu können. Wählen Sie die Option 'Benutzen'. Klicken Sie dann einen Alien mit dem Cursor an.\"\n  STR_SURVEY_SHIP: \"Vermessungsschiff\"\n  STR_ESCORT: \"Begleitschiff\"\n  STR_CRUISER: \"Kreuzer\"\n  STR_HEAVY_CRUISER: \"Schwerer Kreuzer\"\n  STR_HUNTER: \"Jäger\"\n  STR_BATTLESHIP: \"Schlachtschiff\"\n  STR_DREADNOUGHT: \"Dreadnought\"\n  STR_FLEET_SUPPLY_CRUISER: \"Flottenversorgungskreuzer\"\n  MAP_SEABED: \"Meeresboden\"\n  MAP_PIPES: \"Forschungseinrichtung\"\n  MAP_PLANE: \"Flugzeugwrack\"\n  MAP_ATLAN: \"Atlantis\"\n  MAP_MU: \"Maya Tempel\"\n  MAP_GAL: \"Versunkene Galeone\"\n  MAP_MSUNK: \"Versunkenes Linienschiff\"\n  MAP_VOLC: \"Vulkanisch\"\n  MAP_CORAL: \"Korallenriff\"\n  MAP_PORT: \"Hafen\"\n  MAP_ISLAND: \"Insel\"\n  MAP_CARGO: \"Containerschiff\"\n  MAP_LINERT: \"Kreuzfahrtschiff P1\"\n  MAP_LINERB: \"Kreuzfahrtschiff P2\"\n  MAP_ALART: \"Artefakt P1\"\n  MAP_GRUNGE: \"Artefakt P2\"\n  MAP_ENTRY: \"Kolonie P1\"\n  MAP_A_BASE: \"Kolonie P2\"\n  MAP_ALSHIP: \"T'leth P1\"\n  MAP_LEVEL: \"T'leth P2\"\n  MAP_CRYPT: \"T'leth P3\"\n  MAP_XBASES: \"X-COM Basis\"\n  STR_MIXED_CREW: \"Mischbesatzung\"\n  STR_MIXED_CREW_2: \"Mischbesatzung 2\"\n  STR_RATING: \"ERGEBNIS> {0}\"\n  STR_RATING_TERRIBLE: \"ERBÄRMLICH!\"\n  STR_RATING_POOR: \"SCHWACH!\"\n  STR_RATING_OK: \"OK\"\n  STR_RATING_GOOD: \"GUT!\"\n  STR_RATING_EXCELLENT: \"SPITZE!\"\n  STR_SCORE: \"PUNKTE\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"X-COM-MONATSBERICHT\"\n  STR_MONTH: \"Monat> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"Das Komitee der Finanzierungsorganisationen ist im allgemeinen mit Ihrem Fortschritt zufrieden.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"Das Komitee der Finanzierungsorganisationen ist sehr zufrieden mit Ihrer ausgezeichneten Arbeit. Machen Sie weiter so.\"\n  STR_COUNCIL_IS_DISSATISFIED: \"Das Komitee der Finanzierungsorganisationen ist mit Ihren Leistungen nicht zufrieden. Entweder Sie leisten bessere Arbeit gegen die Aliens, oder die Gelder für X-Com werden gestrichen.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"Es ist Ihnen nicht gelungen, die Invasion der Aliens aufzuhalten, und das Komitee der Finanzierungsorganisationen hat leider beschlossen, die Gelder für X-Com zu streichen. Jede Organisation wird mit dem Problem nun auf ihre Weise umgehen. Wir können nur hoffen, daß wir zu einer Einigung mit diesen uralten Kräften kommen können und die Bevölkerung sich mit den aquatischen Besuchern arrangieren wird.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} ist besonders zufrieden mit Ihren Fähigkeiten, sich der lokalen Bedrohung zu erwehren, und hat beschlossen, die Mittel zu erhöhen.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} sind im höchsten Maße zufrieden, wie Sie mit dem lokalen Eindringen der Aliens fertigwerden, und haben beschlossen, die Mittel zu erhöhen.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} und {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} ist mit Ihren Fähigkeiten, die Aktivitäten der Aliens in den Meeren zu unterbinden, recht unzufrieden und hat beschlossen, die Mittel zu verringern.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} sind mit Ihren Fähigkeiten, die Aktivitäten der Aliens im Meer zu unterbinden, recht unzufrieden und haben beschlossen, die Mittel zu verringern.\"\n  STR_KNOTS: \"{0} km\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} hat ein Kooperationsabkommen mit den außerirdischen Kräften geschlossen und sich aus der X-Com-Finanzierung zurückgezogen.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} haben ein Kooperationsabkommen mit den außerirdischen Kräften geschlossen und sich aus der X-Com-Finanzierung zurückgezogen.\"\n  STR_MONTHLY_RATING: \"Monatliche Einschätzung> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Änderung in der Finanzierung> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"Die Finanzierungsorganisation ist mit Ihren Finanzen nicht zufrieden.  Verringern Sie Ihre Schulden auf einen Betrag unter $2 Millionen, oder die X-Com wird abgewickelt.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"U-BOOT-TEILCHENÜBERTRAGUNG AUFGELÖST\"\n  STR_CRAFT_TYPE: \"U-BOOTTYP\"\n  STR_RACE: \"SPEZIES\"\n  STR_MISSION: \"EINSATZ\"\n  STR_ZONE: \"ZONE\"\n  STR_ALLOCATE_RESEARCH: \"Forschungsauftrag vergeben\"\n  STR_ALLOCATE_MANUFACTURE: \"Produktion einleiten\"\n  STR_AZORES: \"Azoren\"\n  STR_REYKJAVIK: \"Reykjavik\"\n  STR_BERMUDA: \"Bermuda\"\n  STR_NEW_YORK: \"New York\"\n  STR_BOSTON: \"Boston\"\n  STR_FORT_SEVERN: \"Fort Severn\"\n  STR_DAKAR: \"Dakar\"\n  STR_RECIFE: \"Recife\"\n  STR_ACCRA: \"Accra\"\n  STR_ASCENSION_ISLAND: \"Ascension\"\n  STR_TRINIDADE_ISLAND: \"Trinidad\"\n  STR_FALKLAND_ISLAND: \"Falkland-Inseln\"\n  STR_CANARY_ISLANDS: \"Kanarische Inseln\"\n  STR_ANCHORAGE: \"Anchorage\"\n  STR_ST_LAWRENCE_ISLAND: \"St Lawrence Island\"\n  STR_SAN_FRANCISCO: \"San Francisco\"\n  STR_MIDWAY_ISLAND: \"Midway-Inseln\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_TASMANIA: \"Tasmanien\"\n  STR_HAWAII: \"Hawaii\"\n  STR_FIJI: \"Fidschi\"\n  STR_TONGA: \"Tonga\"\n  STR_EASTER_ISLAND: \"Osterinseln\"\n  STR_GALAPAGOS_ISLAND: \"Galapagos-Inseln\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_SOLOMON_ISLAND: \"Solomon\"\n  STR_CRETE: \"Kreta\"\n  STR_LISBON: \"Lissabon\"\n  STR_PORT_SAID: \"Port Said\"\n  STR_MARSEILLES: \"Marseilles\"\n  STR_TRIPOLI: \"Tripoli\"\n  STR_MANILA: \"Manila\"\n  STR_HONG_KONG: \"Hong Kong\"\n  STR_SINGAPORE: \"Singapur\"\n  STR_BANGKOK: \"Bangkok\"\n  STR_DARWIN: \"Darwin\"\n  STR_BOMBAY: \"Bombay\"\n  STR_SAYCHELLES_ISLAND: \"Seychellen\"\n  STR_MALDIVE_ISLAND: \"Malediven\"\n  STR_SRI_LANKA: \"Sri Lanka\"\n  STR_MAURITIUS: \"Mauritius\"\n  STR_TOKYO: \"Tokio\"\n  STR_SHANGHAI: \"Shanghai\"\n  STR_VLADIVOSTOK: \"Wladiwostok\"\n  STR_LONDON: \"London\"\n  STR_FAEROE_ISLAND: \"Faeroe Island\"\n  STR_ABERDEEN: \"Aberdeen\"\n  STR_OSLO: \"Oslo\"\n  STR_JAMAICA: \"Jamaica\"\n  STR_PANAMA: \"Panama\"\n  STR_MIAMI: \"Miami\"\n  STR_PSI_TRAINING: \"M.S. Training\"\n  STR_PSIONIC_TRAINING: \"MOLEKÜLSTEUERUNGSTRAINING\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Verbleibende M.S.-Kapazität> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"M.S.{NEWLINE}Stärke\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"Verbesserung der{NEWLINE}/M.S.-Fähigkeiten\"\n  STR_IN_TRAINING: \"Im{NEWLINE}Training?\"\n  STR_TARGETTED_BY: \"VERFOLGER:\"\n  STR_WEAPONS_CREW_HWPS: \"WAFFEN/{NEWLINE}CREW/UWS\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"hat zu wenig Treibstoff,{NEWLINE}kehrt zur Basis zurü\\x81ck\"\n  STR_SOLDIER_LIST: \"Liste der Aquanauten\"\n  STR_RANK_: \"RANG> {ALT}{0}\"\n  STR_MISSIONS: \"EINSÄTZE> {ALT}{0}\"\n  STR_KILLS: \"ABSCHÜSSE> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"WUNDHEILUNG> {ALT}{0}\"\n  STR_TIME_UNITS: \"ZEITEINHEITEN\"\n  STR_STAMINA: \"AUSDAUER\"\n  STR_HEALTH: \"GESUNDHEIT\"\n  STR_BRAVERY: \"MUT\"\n  STR_REACTIONS: \"REAKTIONEN\"\n  STR_FIRING_ACCURACY: \"TREFFGENAUIGKEIT\"\n  STR_THROWING_ACCURACY: \"WURFGENAUIGKEIT\"\n  STR_STRENGTH: \"STÄRKE\"\n  STR_PSIONIC_STRENGTH: \"M.S.-STÄRKE\"\n  STR_PSIONIC_SKILL: \"M.S.-FÄHIGKEITEN\"\n  STR_NEW_RANK: \"NEUER RANG\"\n  STR_PROMOTIONS: \"Beförderungen\"\n  STR_SOLDIERS_UC: \"AQUANAUTEN\"\n  STR_COELACANTH_GAS_CANNON_UFOPEDIA: \"Automatische UWS sind sehr manövrierfähig und haben einen starken Rumpf. Sie können Truppen in allen Tiefen  unterstützen. UWS werden automatisch wieder geladen, wenn genug Munition vorhanden ist.\"\n  STR_COELACANTH_AQUA_JET_UFOPEDIA: \"Dieses U-Boot ist mit Aqua-Jet-Torpedos bewaffnet. Ein der Gaskanone überlegenes System. Vergewissern Sie sich, daß immer genug Aqua-Jet-Torpedos vorhanden sind.\"\n  STR_COELACANTH_GAUSS_UFOPEDIA: \"Die Gauss'sche Technologie bietet ein starkes Waffensystem für UWS. Sie bietet im Vergleich zu früheren Modellen schwereres Feuer und nutzt eigene X-Com-Technologie.\"\n  STR_DISPLACER_SONIC_UFOPEDIA: \"Die Technologie der Aliens hat die UWS revolutioniert. Durch den Ionenverdränger sind die UWS nicht länger auf den Einsatz an Land/auf dem Meeresboden beschränkt. Sonarwaffen bieten im Kampf einen erheblichen Vorteil.\"\n  STR_DISPLACER_PWT_UFOPEDIA: \"Dieses UWS ist mit Impulswellenwaffen für den Unterwassereinsatz ausgestattet. Sie müssen IW-Torpedos herstellen, um stets kampfbereit zu sein. Zum Feuern setzen Sie eine Reihe von Wegmarken und klicken dann das Start-Icon an.\"\n  STR_ALIEN_PROBE_MISSION: \"Außerirdischer Sondereinsatz\"\n  STR_ALIEN_INTERDICTION: \"Alien-Interdiktion\"\n  STR_ALIEN_RESOURCE_RAID: \"Ressourcenplünderung\"\n  STR_ALIEN_INFILTRATION: \"Außerirdische Infiltration\"\n  STR_ALIEN_BASE: \"Expansion der Alien-Kolonien\"\n  STR_ALIEN_SURFACE_ATTACK: \"Landangriff der Aliens\"\n  STR_ALIEN_RETALIATION: \"Angriff auf Schwimmende Basis\"\n  STR_ALIEN_SUPPLY: \"Kolonie-Versorgungsmissionen\"\n  STR_ALIEN_PROBE_MISSION_UFOPEDIA: \"Der Sondereinsatz wird zur Korrelierung von Daten über Meeresboden, Ressourcen, Schiffs- und Flugzeugrouten eines Gebietes verwendet. Die hier tätigen U-Boote der Aliens stellen an sich keine Gefahr dar, zeigen aber Aktivitäten an, die jederzeit eskalieren könnten. \"\n  STR_ALIEN_INTERDICTION_UFOPEDIA: \"Die Aliens beobachten gerne Gebiete, an denen sie interessiert sind, und senden oft Fahrzeuge aus, um ein Gebiet zu sichern, bevor intensivere Einsätze starten. Dabei landen sie an bestimmten Orten, von denen aus sie später das Gebiet abriegeln, um den nächsten Schritt vorzubereiten.\"\n  STR_ALIEN_RESOURCE_RAID_UFOPEDIA: \"Das Versenken von Schiffen und das Abschießen von Flugzeugen gehören zu den Schlüsselelementen der Strategie der Aliens. Dazu gehört auch der Erwerb von Materialien, der auch von aggressiven Handlungen begleitet ist. Die Aliens führen auch Überfälle auf Gebiete mit geothermischer Aktivität, Bergbauregionen und historische Stätten aus, um Minerale, Metalle und andere menschliche Erzeugnisse zu erwerben.\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"Dies kann zu offiziellen Kontakten zwischen den Aliens und Unternehmen oder Regierungen auf höchster Ebene führen. Den Höhepunkt dieser Aktivitäten bilden intensive U-Boot-Aktivitäten in den entsprechenden Gewässern. Die Aliens möchten mit der Regierung oder dem Unternehmen einen Vertrag unterzeichnen, in dem sie die Weitergabe ihrer überlegenen Technologie anbieten. Diese Aktivitäten stellen eine große Bedrohung für X-Com dar.  Mit Beginn der Zusammenarbeit eines Unternehmens oder einer Regierung mit den Aliens bleiben die Gelder aus. \"\n  STR_ALIEN_BASE_UFOPEDIA: \"Aliens bauen geheime Unterwasserkolonien in entfernten Gegenden. Nach ersten Erkundungsflügen erfolgt eine erhöhte Aktivität der U-Boote der Aliens nach dem Baubeginn. Diese Kolonien sind mit Labors, Klon-Zentren und Operationsräumen für Human- und Alienexperimente ausgestattet. Die Präsenz der Kolonien zieht weitere Aktivitäten der Aliens nach sich, ohne daß U-Boote anzutreffen wären. Zur Lokalisierung einer Kolonie muß ein X-Com-U-Boot einige Stunden lang patrouillieren, bevor es eine Kolonie entdecken kann.\"\n  STR_ALIEN_SURFACE_ATTACK_UFOPEDIA: \"Wenn die Aliens Menschen brauchen, terrorisieren sie einen Hafen, greifen eine Insel an oder \\x81überfallen ein Schiff. Zivilisten sind direkt bedroht, da sie für Zuchtzwecke und Experimente der Aliens gebraucht werden.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"Wenn die X-Com-Abfang-U-Boote erfolgreich gegen Fahrzeuge der Aliens vorgehen, kann es zu Vergeltungsmaßnahmen kommen. Diese könnten zu einem direkten Angriff gegen eine X-Com-Einrichtung führen. Doch müssen die Aliens zunächst eine X-Com-Basis finden, die sie angreifen können; solange die U-Boote der Aliens ferngehalten werden können, sollte die Gefahr eines Angriffs gering sein.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"Wurde eine Kolonie durch die Aliens errichtet, wird sie in regelmäßigen Abständen von einem besonderen Versorgungsschiff beliefert. Wird eines dieser Schiffe bei der Landung beobachtet, kann auf eine Kolonie der Aliens geschlossen werden.\"\n  STR_SURVEY_SHIP_UFOPEDIA: \"Dieses winzige U-Boot wird zu Aufklärungs- und Vermessungszwecken verwendet. Normalerweise führt es einen Stoßtrupp der Aliens an.\"\n  STR_ESCORT_UFOPEDIA: \"Ein mittelgroßes Geleitschiff, das allein keine große Gefahr darstellt. Dieses Schiff kündigt die Ankunft größerer Schiffe und vermehrte Aktivität an.\"\n  STR_CRUISER_UFOPEDIA: \"Der Kreuzer ist ein Universalschiff, das Hauptstück der Flotte der Aliens. Es wird bei Einsätzen aller Arten verwendet und ist ein gefährlicher Gegner.\"\n  STR_HEAVY_CRUISER_UFOPEDIA: \"Der Schwere Kreuzer ist mächtiger als ein Kreuzer; größere Waffen und Antriebssysteme erhöhen seine Kraft. Der Schwere Kreuzer wird für Beschaffungseinsätze verwendet, um große Mengen an Mineralien und Ausrüstung zu sammeln.\"\n  STR_HUNTER_UFOPEDIA: \"Dieses Schiff ist mit einem Untersuchungsraum ausgestattet, in dem Experimente an menschlichen Objekten vorgenommen werden können. Die Opfer werden den schrecklichsten Torturen unterworfen. Oft wird das Gehirn entfernt und dann aufbewahrt.\"\n  STR_BATTLESHIP_UFOPEDIA: \"Das Schlachtschiff ist das aggressivste Schiff im Besitz der Aliens. Es enthält alle Technologien und Systeme um als Operationsbasis für jegliche Art aggressiver Handlung dienen zu können und führt ein breites Arsenal an Waffen mit sich.\"\n  STR_DREADNOUGHT_UFOPEDIA: \"Die Dreadnought ist ein Truppenträger, der sämtliche Technologien und eine riesige Nutzlast besitzt. Die Dreadnought ist ein harter und gefährlicher Gegner.\"\n  STR_FLEET_SUPPLY_CRUISER_UFOPEDIA: \"Das Versorgungsschiff wird während der Aufbauphase der Kolonien eingesetzt oder zur Belieferung bereits existierender Kolonien. Es transportiert Nahrung, DNS-Material, Föten und andere biologische Komponenten.\"\n  STR_DISMANTLE: \"Abbauen\"\n  STR_FACILITY_IN_USE: \"AQUA-ZELLE IN GEBRAUCH\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"AQUA-ZELLE KANN NICHT ABGEBAUT WERDEN!{SMALLLINE}Alle Basiszellen müssen mit der Luftschleuse verbunden sein.\"\n  STR_TRANSFER_ITEMS_TO: \"Gegenstände transferieren nach {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"KEINE QUARANTÄNESTATION FÜR TRANSFER!{SMALLLINE}Lebende Aliens können nur in einer Quarantänestation am Leben erhalten werden.\"\n  STR_AMOUNT_AT_DESTINATION: \"MENGE AM{NEWLINE}ZIELORT\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"Alien stirbt, da keine Quarantänestation vorhanden\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"KEIN FREIER WOHNRAUM!{SMALLLINE}Zielbasis hat nicht genug Wohnraum für die dem U-Boot zugeteilte Crew.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"NICHT GENUG LAGERRAUM!{SMALLLINE}Erstellen Sie neuen Lagerraum, oder verlegen Sie Bestände auf andere Basen.\"\n  STR_ITEMS_ARRIVING: \"Gegenstände kommen an\"\n  STR_DESTINATION_UC: \"ZIEL\"\n  STR_DART_PISTOL: \"Pfeilgewehr\"\n  STR_DART_POD: \"Pfeilladestreifen\"\n  STR_JET_HARPOON: \"Jet-Harpune\"\n  STR_HARPOON_POD: \"Harpunenladestreifen\"\n  STR_GAS_CANNON: \"Gaskanone\"\n  STR_GC_AP_AMMO: \"GK-PB-Bolzen\"\n  STR_GC_HE_AMMO: \"GK-HE-Bolzen\"\n  STR_GC_P_AMMO: \"GK-Phosphorbolzen\"\n  STR_HYDRO_JET_CANNON: \"Hydro-Jetkanone\"\n  STR_HJC_AP_AMMO: \"HJ-PB-Munition\"\n  STR_HJC_HE_AMMO: \"HJ-HE-Munition\"\n  STR_HJC_P_AMMO: \"HJ-I-Munition\"\n  STR_TORPEDO_LAUNCHER: \"Torpedowerfer\"\n  STR_SMALL_TORPEDO: \"Kleiner Torpedo\"\n  STR_LARGE_TORPEDO: \"Großer Torpedo\"\n  STR_PHOSPHOROUS_TORPEDO: \"Phosphortorpedo\"\n  STR_MAGNA_BLAST_GRENADE: \"Magnastrahl-Granate\"\n  STR_DYE_GRENADE: \"Farbgranate\"\n  STR_PARTICLE_DISTURBANCE_GRENADE: \"Teilchenstörgranate\"\n  STR_MAGNA_PACK_EXPLOSIVE: \"Magnabündel-Sprengstoff\"\n  STR_PARTICLE_DISTURBANCE_SENSOR: \"Teilchenstörsensor\"\n  STR_MEDI_KIT: \"Verbandskasten\"\n  STR_MC_DISRUPTOR: \"M.S.-Störer\"\n  STR_THERMAL_TAZER: \"Thermo-Taser\"\n  STR_GAUSS_PISTOL: \"Gauss'sche Pistole\"\n  STR_GAUSS_PISTOL_CLIP: \"Magazin für Gauss'sche Pistole\"\n  STR_GAUSS_RIFLE: \"Gauss'sches Gewehr\"\n  STR_GAUSS_RIFLE_CLIP: \"Magazin für Gauss'sches Gewehr\"\n  STR_HEAVY_GAUSS: \"Schwere Gauss\"\n  STR_HEAVY_GAUSS_CLIP: \"Magazin für schwere Gauss\"\n  STR_SONIC_CANNON: \"Sonarkanone\"\n  STR_CANNON_POWER_CLIP: \"Kanonenladestreifen\"\n  STR_SONIC_BLASTA_RIFLE: \"Sonar-Blasta-Gewehr\"\n  STR_BLASTA_POWER_CLIP: \"Blasta-Ladestreifen\"\n  STR_SONIC_PISTOL: \"Sonarpistole\"\n  STR_PISTOL_POWER_CLIP: \"Pistolenladestreifen\"\n  STR_DISRUPTOR_PULSE_LAUNCHER: \"Störimpulswerfer\"\n  STR_DISRUPTOR_AMMO: \"Störermunition\"\n  STR_THERMAL_SHOK_LAUNCHER: \"Thermalschockwerfer\"\n  STR_THERMAL_SHOK_BOMB: \"Thermalschockbombe\"\n  STR_SONIC_PULSER: \"Sonarimpulsgeber\"\n  STR_ZRBITE: \"Zrbit\"\n  STR_MC_READER: \"M.S.-Lesegerät\"\n  STR_VIBRO_BLADE: \"Vibroklinge\"\n  STR_THERMIC_LANCE: \"Thermische Lanze\"\n  STR_HEAVY_THERMIC_LANCE: \"Schwere Thermische Lanze\"\n  STR_AQUATOID_CORPSE: \"Aquatoiden-Leiche\"\n  STR_GILLMAN_CORPSE: \"Kiemenmenschen-Leiche\"\n  STR_LOBSTERMAN_CORPSE: \"Hummermenschen-Leiche\"\n  STR_TASOTH_CORPSE: \"Tasoth-Leiche\"\n  STR_CALCINITE_CORPSE: \"Calciniten-Leiche\"\n  STR_DEEP_ONE_CORPSE: \"Ungetüm-Leiche\"\n  STR_BIODRONE_CORPSE: \"Bio-Drohnenleiche\"\n  STR_TENTACULAT_CORPSE: \"Tentakulaten-Leiche\"\n  STR_TRISCENE_CORPSE: \"Triszenen-Leiche\"\n  STR_HALLUCINOID_CORPSE: \"Halluzinoiden-Leiche\"\n  STR_XARQUID_CORPSE: \"Xintfisch-Leiche\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"Nicht genug Munition zum Ausrüsten des SWS vohanden{SMALLLINE}Jedes SWS benötigt {0} {1}.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Nicht genügend Ausrüstung für die Truppe\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Zur Nutzung oder Produktion von{NEWLINE}{1}{NEWLINE}müssen Sie Folgendes erforschen{NEWLINE}{0}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"Die Aliens zerstörten die nicht verteidigte Basis {0}\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"X-Com-Patrouillen haben hier eine Kolonie der Aliens ausgemacht: {0}\"\n  STR_STANDOFF: \"SICHERHEITSABSTAND\"\n  STR_CAUTIOUS_ATTACK: \"VORSICHTIGER ANGRIFF\"\n  STR_STANDARD_ATTACK: \"STANDARDANGRIFF\"\n  STR_AGGRESSIVE_ATTACK: \"VEHEMENTER ANGRIFF\"\n  STR_DISENGAGING: \"RÜCKZUG\"\n  STR_UFO_HIT: \"U-BOOT DER ALIENS GETROFFEN!\"\n  STR_UFO_CRASH_LANDS: \"ALIENS ABGESTÜRZT!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Verkleinerung nur bei Fernangriff\"\n  STR_UFO_RETURN_FIRE: \"U-BOOTE ERWIDERN FEUER!\"\n  STR_INTERCEPTOR_DAMAGED: \">>> U-BOOT BESCHÄDIGT <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> U-BOOT ZERSTÖRT <<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"ALIEN-FLUG-U-BOOT ENTKOMMT!\"\n  STR_LONG_RANGE_DETECTION: \"Breitbanderfassung\"\n  STR_STORES_UC: \"LAGER\"\n  STR_DIFFICULTY_LEVEL: \"Schwierigkeitsstufe\"\n  STR_INTERCEPT: \"ABFANGEN\"\n  STR_BASES: \"STÜTZPUNKTE\"\n  STR_GRAPHS: \"DIAGRAMME\"\n  STR_UFOPAEDIA_UC: \"UFOPEDIA\"\n  STR_OPTIONS_UC: \"OPTIONEN\"\n  STR_FUNDING_UC: \"GELDER\"\n  STR_5_SECONDS: \"5 Sek\"\n  STR_1_MINUTE: \"1 Min\"\n  STR_5_MINUTES: \"5 Min\"\n  STR_30_MINUTES: \"30 Min\"\n  STR_1_HOUR: \"1 Std\"\n  STR_1_DAY: \"1 Tag\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"X-Com-Bewertungsliste\"\n  STR_ENTER_NAME: \"Name eingeben\"\n  STR_PERFORMANCE_RATING: \"Leistungseinschätzung\"\n  STR_VICTORY_DATE: \"Siegesdatum\"\n  STR_CHEMICAL_FLARE: \"Chemische Leuchtrakete\"\n  STR_CHEMICAL_FLARE_UFOPEDIA: \"Dieses kompakte Gerät erzeugt ein helles Licht in jeder Höhe oder Wassertiefe. Dies beleuchtet gegnerische Einheiten auf Tiefsee- oder Nachteinsätzen.\"\n  STR_MONTHLY_COSTS: \"Monatliche Kosten\"\n  STR_CRAFT_RENTAL: \"Mieten des Fliegenden U-Bootes\"\n  STR_SALARIES: \"Gehälter\"\n  STR_BASE_MAINTENANCE: \"Basisinstandhaltung\"\n  STR_COST_PER_UNIT: \"Kosten pro Einheit  \"\n  STR_QUANTITY: \"  Menge\"\n  STR_TOTAL: \"Gesamt\"\n  STR_IN_PSIONIC_TRAINING: \"In M.S. implantation\"\n  STR_FRONT_ARMOR: \"Vordere Panzerung\"\n  STR_LEFT_ARMOR: \"Linke Panzerung\"\n  STR_RIGHT_ARMOR: \"Rechte Panzerung\"\n  STR_REAR_ARMOR: \"Hintere Panzerung\"\n  STR_UNDER_ARMOR: \"Untere Panzerung\"\n  STR_ROUNDS: \"SCHÜSSE\"\n  STR_UNIT: \"EINHEIT> {0}\"\n  STR_ENERGY: \"ENERGIE\"\n  STR_MORALE: \"MORAL\"\n  STR_ARMOR_: \"PANZERUNG> {0}\"\n  STR_FRONT_ARMOR_UC: \"VORDERE PANZERUNG\"\n  STR_LEFT_ARMOR_UC: \"LINKE PANZERUNG\"\n  STR_RIGHT_ARMOR_UC: \"RECHTE PANZERUNG\"\n  STR_REAR_ARMOR_UC: \"HINTERE PANZERUNG\"\n  STR_SKILLS: \"FÄHIGKEITEN> {0}\"\n  STR_LEVEL: \"LEVEL> {0}\"\n  STR_HEAD: \"KOPF\"\n  STR_TORSO: \"RUMPF\"\n  STR_RIGHT_ARM: \"RECHTER ARM\"\n  STR_LEFT_ARM: \"LINKER ARM\"\n  STR_RIGHT_LEG: \"RECHTES BEIN\"\n  STR_LEFT_LEG: \"LINKES BEIN\"\n  STR_PAIN_KILLER: \"SCHMERZMITTEL\"\n  STR_STIMULANT: \"STIMULANS\"\n  STR_HEAL: \"HEILEN\"\n  STR_TIME_UNITS_SHORT: \"ZE>{ALT}{0}\"\n  STR_WEIGHT: \"Gewicht>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"Reakt.>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"M.Skill>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"M.Str>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Artefakt der Aliens\"\n  STR_AMMO_ROUNDS_LEFT: \"MUNITION:{NEWLINE}SCHUSS{NEWLINE}ÜBRIG={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Schmerz>{ALT}{0}{ALT}{NEWLINE}Stimulans>{ALT}{1}{ALT}{NEWLINE}Heilung>{ALT}{2}\"\n  STR_THROW: \"Werfen\"\n  STR_AUTO_SHOT: \"Auto-Schuss\"\n  STR_SNAP_SHOT: \"Schnellschuss\"\n  STR_AIMED_SHOT: \"Zielschuss\"\n  STR_STUN: \"Betäuben\"\n  STR_PRIME_GRENADE: \"Granate aktivieren\"\n  STR_USE_SCANNER: \"Teilchenstörsensor verwenden\"\n  STR_USE_MEDI_KIT: \"Arzttasche benutzen\"\n  STR_LAUNCH_MISSILE: \"Torpedo abfeuern\"\n  STR_ACCURACY_SHORT: \"SG>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Nicht genug Zeiteinheiten!\"\n  STR_NOT_ENOUGH_ENERGY: \"Nicht genug Energie!\"\n  STR_NO_ROUNDS_LEFT: \"Nicht genug Munition zum Neuladen\"\n  STR_NO_AMMUNITION_LOADED: \"Keine Munition geladen!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Falsche Munition für diese Waffe!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"Waffe bereits geladen!\"\n  STR_NO_LINE_OF_FIRE: \"Keine Schusslinie!\"\n  STR_GRENADE_IS_ACTIVATED: \"Granate aktiviert!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Granate deaktiviert!\"\n  STR_THERE_IS_NO_ONE_THERE: \"Niemand da!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Artefakt muß erst untersucht werden!\"\n  STR_OUT_OF_RANGE: \"Außer Reichweite!\"\n  STR_UNABLE_TO_THROW_HERE: \"Kann hier nicht geworfen werden!\"\n  STR_SET_TIMER: \"Timer einstellen\"\n  STR_HIDDEN_MOVEMENT: \"VERSTECKTE BEWEGUNG\"\n  STR_TURN: \"RUNDE> {0}\"\n  STR_SIDE: \"SEITE> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Zur Fortsetzung Knopf drücken\"\n  STR_MIND_CONTROL: \"Molekülsteuerung\"\n  STR_PANIC_UNIT: \"Implantat blockieren\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Moral Angriff erfolgreich\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Implantatkontrolle erfolgreich\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}ist durchgedreht\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}ist durchgedreht\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}ist in Panik\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}ist in Panik\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Aliens\"\n  STR_RIGHT_HAND: \"RECHTE HAND\"\n  STR_LEFT_HAND: \"LINKE HAND\"\n  STR_RIGHT_SHOULDER: \"RECHTE SCHULTER\"\n  STR_LEFT_SHOULDER: \"LINKE SCHULTER\"\n  STR_BACK_PACK: \"RUCKSACK\"\n  STR_BELT: \"GÜRTEL\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}ist unter Molekülsteuerung\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}ist unter Molekülsteuerung\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}ist bewußtlos\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}ist bewußtlos\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}ist den Verletzungen erlegen\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}ist den Verletzungen erlegen\"\n  STR_USE_MIND_PROBE: \"M.S.-Lesegerät einsetzen\"\n  STR_FATAL_WOUNDS: \"TÖDLICHE VERLETZUNG\"\n  STR_UNDER_ARMOR_UC: \"UNTERE PANZERUNG\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Zeiteinheiten reserviert für Schnellschuss\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Zeiteinheiten reserviert für Auto-Schuss\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Zeiteinheiten reserviert für Zielschuss\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Zeiteinheiten reserviert für Stehen/Knien\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"Zeiteinheiten reserviert fürs Hinknien und Feuern\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} Einheit in X-Com-Fahrzeug\"\n    other: \"{N} Einheiten in X-Com-Fahrzeug\"\n  STR_UNITS_OUTSIDE:\n    one: \"{N} Einheit noch draußen\"\n    other: \"{N} Einheiten noch draußen\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} Einheit im Eingang\"\n    other: \"{N} Einheiten im Eingang\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} Einheit im Zielausgang\"\n    other: \"{N} Einheiten im Zielausgang\"\n  STR_ABORT_MISSION_QUESTION: \"Einsatz abbrechen?\"\n  STR_CORPSE: \"Toter\"\n  STR_UNLOAD_CRAFT: \"Entladen\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}wurde getötet\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}wurde getötet\"\n  STR_HIT_MELEE: \"Treffer\"\n  STR_GROUND: \"BODEN\"\n  STR_LIVING_QUARTERS_PLURAL: \"Wohnblocks\"\n  STR_LIST_ITEM: \"ARTIKEL\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"Alle Aliens bei U-Boot-Absturz getötet,{NEWLINE}Automatische Bergung eingeleitet\"\n  STR_RESET: \"Zurücksetzen\"\n  STR_MEMORIAL: \"Gedenkstätte\"\n  STR_DATE_UC: \"DATUM\"\n  STR_SOLDIERS_RECRUITED_UC: \"REKRUTIERTE AQUANAUTEN>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"GEFALLENE AQUANAUTEN>{ALT}{0}\"\n  STR_REMOVE_SELECTED: \"Ausgewählte entfernen\"\n  STR_LIVE_ALIENS: \"Lebende{NEWLINE}Exemplare\"\n  STR_DEAD_ALIENS: \"Exemplare{NEWLINE}Abgelehnt\"\n  STR_UNDER_INTERROGATION: \"Derzeit{NEWLINE}Untersucht.\"\n  STR_CONTAINMENT_EXCEEDED: \"KAPAZITÄT DER QUARANTÄNESTATION ÜBERSCHRITTEN!{SMALLLINE}Nicht genug Platz in der Quarantänestation von {0}. Du musst überzählige Außerirdische aus der Quarantäne entfernen (diese werden sterben).\"\n  STR_MANAGE_CONTAINMENT: \"Quarantänestation verwalten\"\n  STR_STORAGE_EXCEEDED: \"LAGERKAPAZITÄT ÜBERSCHRITTEN!{SMALLLINE}Nicht genügend Lagerfläche in {0}. Sie müssen überschüssige Gegenstände verkaufen.\"\n  STR_GO_TO_BASE: \"Geh zur Basis\"\n  STR_MELEE_ACCURACY: \"NAHKAMPFGENAUIGKEIT\"\n  STR_SELL_PRODUCTION: \"VERKAUFEN\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Beide Hände müssen frei sein!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Nicht genug Teile um Vorlage zu kopieren!\"\n  STR_UNLOAD_WEAPON: \"Waffe entladen\"\n  STR_ALL_ITEMS: \"Alle Artikel\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"KEINE WEITERE AUSRÜSTUNG AN BORD ERLAUBT!{SMALLLINE}Sie dürfen höchstens {N} Ausrüstungsgegenstände auf eine Mission mitnehmen.\"\n    other: \"KEINE WEITERE AUSRÜSTUNG AN BORD ERLAUBT!{SMALLLINE}Sie dürfen höchstens {N} Ausrüstungsgegenstände auf eine Mission mitnehmen.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}Kommandozentrale zerstört{NEWLINE} Begeben Sie sich zum Eingang um abzubrechen.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"X-Com-Aqua-Einrichtungen können nicht an Land gebaut werden.\"\n  STR_UNABLE_TO_ENGAGE_DEPTH: \"ANGRIFF IN DER TIEFE{NEWLINE}NICHT MÖGLICH\"\n  STR_UNABLE_TO_ENGAGE_AIRBORNE: \"ANGRIFF AUS DER LUFT{NEWLINE}NICHT MÖGLICH\"\n  STR_UNDERWATER_EQUIPMENT: \"Sensor nur unter Wasser einsetzbar!\"\n  STR_LAND_EQUIPMENT: \"Diese Ausrüstung funktioniert nicht unter Wasser!\"\n  STR_LEVEL_SHORT: \"L{0}\"\n  STR_PERSONNEL: \"Personal\"\n  STR_CRAFT_ARMAMENT: \"Raumschiffe & Bewaffnung\"\n  STR_COMPONENTS: \"Bauteile\"\n  STR_SOLDIERS_RECRUITED: \"Rekrutierte Aquanauten\"\n  STR_SOLDIERS_LOST: \"Gefallene Aquanauten\"\n  STR_TOTAL_UFOS: \"Entdeckte fliegende U-Boote\"\n  STR_TOTAL_ALIEN_BASES: \"Entdeckte außerirdische Kolonien\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"PST\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"PF\"\n  FEMALE_CIVILIAN: \"Zivilistin, Weiblich\"\n  MALE_CIVILIAN: \"Zivilist, Männlich\"\n  DOCKER_CIVILIAN: \"Zivilist, Hafenarbeiter\"\n  SAILOR_CIVILIAN: \"Zivilist, Seemann\"\n  STR_BIODRONE_MELEE_WEAPON: \"Nahkampf Bio-Drone\"\n  HALLUCINOID_WEAPON: \"Halluzinoiden Waffe\"\n  STR_LOBSTERMAN_MELEE_WEAPON: \"Hummermensch Nahkampfwaffe\"\n  CALCINITE_WEAPON: \"Calcinite Waffe\"\n  DEEP_ONE_WEAPON: \"Ungetüm Waffe\"\n  STR_TRISCENE_MELEE_WEAPON: \"Triszene Nahkampfwaffe\"\n  STR_TRIBIO_SONIC_WEAPON: \"Ausserirdische Sonarwaffe\"\n  XARQUID_WEAPON: \"Xintfisch Waffe\"\n  TENTACULAT_WEAPON: \"Tentakulaten-Waffe\"\n  ZOMBIE_WEAPON: \"Zombie Waffe\"\n  ALIEN_PSI_WEAPON: \"Ausserirdische M.S.-Waffe \"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/el.yml",
    "content": "el:\n  STR_LEVIATHAN_UFOPEDIA: \"ΜΕΤΑΓΩΓΙΚΟ ΚΑΙ ΚΑΤΑΔΙΩΚΤΙΚΟ ΙΠΤΑΜΕΝΟ ΥΠΟΒΡΥΧΙΟ, ΜΕ ΙΚΑΝΟΤΗΤΑ ΚΑΤΑΔΥΣΗΣ ΣΕ ΠΟΛΥ ΜΕΓΑΛΑ ΒΑΘΥ. ΕΝΑ ΕΞΑΙΡΕΤΙΚΟ ΕΠΙΤΕΥΓΜΑ ΕΞΩΓΗΙΝΗΣ ΚΑΙ ΑΝΘΡΩΠΙΝΗΣ ΤΕΧΝΟΛΟΓΙΑΣ, ΧΡΗΣΙΜΟΠΟΙΕΙ ΣΥΣΤΗΜΑΤΑ ΠΡΟΩΘΗΣΗΣ ΙΟΝΤΩΝ ΚΑΙ ΠΛΟΗΓΗΣΗ ΜΑΓΝΗΤΙΚΗΣ ΣΥΣΤΑΞΗΣ\"\n  STR_BARRACUDA_UFOPEDIA: \"ΒΡΕΤΑΝΙΚΟ ΥΔΡΟΔΙΑΣΤΙΜΙΚΟ ΠΛΟΙΟ ΜΕ ΟΝΟΜΑ \\\"ΣΦΥΡΑΙΝΑ\\\", ΠΟΥ ΤΡΟΦΟΔΟΤΕΙΤΑΙ ΑΠΟ ΥΠΕΡΘΕΡΜΟΜΕΝΟΥΣ ΚΙΝΗΤΗΡΕΣ ΛΑΖΕΡ. ΕΝΑ ΑΠΟ ΤΑ ΠΙΟ ΓΡΗΓΟΡΑ ΚΑΤΑΔΙΩΚΤΙΚΑ ΣΚΑΦΗ ΣΤΟΝ ΚΟΣΜΟ, ΙΚΑΝΟ ΓΙΑ ΥΠΟΒΡΥΧΙΕΣ ΚΑΙ ΕΞΩΑΤΜΟΣΦΑΙΡΙΚΗΣ ΠΤΗΣΗΣ, ΕΝΑ ΣΚΑΦΟΣ ΚΛΕΙΔΙ ΣΤΗΝ ΕΠΕΡΧΟΜΕΝΗ ΜΑΧΗ.\"\n  STR_HAMMERHEAD_UFOPEDIA: \"ΜΕΤΑΓΩΓΙΚΟ ΚΑΙ ΚΑΤΑΔΙΟΚΤΙΚΟ ΣΚΑΦΟΣ. ΜΙΑ ΑΝΑΠΑΡΑΓΩΓΗ ΣΥΣΤΗΜΑΤΩΝ ΜΑΓΝΗΤΙΚΩΝ ΠΑΡΑΤΑΞΕΩΝ ΣΕ ΕΝΑ ΠΛΟΙΟ X-COM. ΑΝ ΚΑΙ ΜΙΚΡΟ, Ο ΣΧΕΔΙΑΣΜΟΣ ΤΟΥ ΕΙΝΑΙ ΕΝΑ ΤΕΧΝΙΚΟ ΕΠΙΤΕΥΓΜΑ ΠΟΥ ΚΟΒΕΙ ΤΗΝ ΑΝΑΣΑ.\"\n  STR_TRITON_UFOPEDIA: \"ΤΟ ΤΡΙΤΩΝ, ΕΝΑ ΜΕΤΑΦΟΡΙΚΟ ΟΜΑΔΑΣ ΚΡΟΥΣΗΣ, ΕΞΟΠΛΙΣΜΕΝΟ ΜΕ ΠΛΗΡΕΣ ΚΙΝΗΤΗΡΕΣ ΠΤΗΣΗΣ ΚΑΙ ΚΑΤΑΔΥΣΗΣ. Η ΜΕΓΑΛΗ ΧΩΡΗΤΙΚΟΤΗΤΑ ΚΑΙ Η ΣΤΙΒΑΡΗ ΚΑΤΑΣΚΕΥΗ ΤΟΥ ΔΙΑΣΦΑΛΙΖΟΥΝ ΟΤΙ ΕΙΝΑΙ Η ΚΥΡΙΑ ΣΤΗΡΙΞΗ ΤΟΥ ΣΤΟΛΟΥ X-COM.\"\n  STR_MANTA_UFOPEDIA: \"MANTA ΥΨΗΛΗΣ ΤΑΧΥΤΗΤΑΣ ΣΚΑΦΟΣ, ΜΟΝΟΘΕΣΙΟ ΙΠΤΑΜΕΝΟ ΥΠΟΒΡΥΧΙΟ ΟΜΟΙΟ ΜΕ ΕΞΩΓΗΙΝΑ ΣΚΑΦΗ ΚΙΝΗΤΗΡΩΝ ΙΟΝΤΩΝ . ΕΝΑ ΥΨΗΛΑ ΑΠΟΤΕΛΕΣΜΑΤΙΚΟ ΜΑΧΗΤΙΚΟ ΣΚΑΦΟΣ ΣΕ ΜΙΑ ΚΛΙΜΑΚΟΥΜΕΝΗ ΣΥΓΚΡΟΥΣΗ.\"\n  STR_AJAX_UFOPEDIA: \"Η ΤΟΡΠΙΛΛΗ AJAX ΕΙΝΑΙ ΤΟ ΠΡΟΤΥΠΟ ΟΠΛΟ ΤΗΣ ΥΠΟΘΑΛΑΣΣΙΑΣ ΜΑΧΗΣ ΣΤΟΝ ΠΑΓΚΟΣΜΙΑ. ΧΡΗΣΙΜΟΠΟΙΕΙΤΑΙ ΩΣ ΑΚΡΙΒΕΣ ΚΑΙ ΙΣΧΥΡΟ ΑΠΟΤΡΕΠΤΙΚΟ ΜΕΣΟ.\"\n  STR_DUP_HEAD_UFOPEDIA: \"ΤΕΧΝΟΛΟΓΙΑ ΟΠΛΩΝ ΑΠΕΜΠΛΟΥΤΙΣΜΕΝΟΥ ΟΥΡΑΝΙΟΥ ΜΕ ΚΕΦΑΛΕΣ ΠΕΛΛΕΤ ΕΙΝΑΙ ΣΧΕΤΙΚΑ ΚΑΙΝΟΥΡΓΙΑ, ΚΑΙ ΑΥΤΟ ΕΙΝΑΙ ΤΟ ΠΡΩΤΟ ΕΜΠΟΡΙΚΟ ΥΔΡΟΒΙΟ ΟΠΛΙΚΟ ΣΥΣΤΗΜΑ ΠΟΥ ΕΧΕΙ ΠΛΗΡΗΣ ΕΦΑΡΜΟΓΗ.\"\n  STR_CRAFT_GAS_CANNON_UFOPEDIA: \"ΕΝΑ ΠΥΡΟΒΟΛΟ ΣΥΣΤΗΜΑ ΤΡΟΦΟΔΟΤΟΥΜΕΝΟ ΑΠΟ ΣΥΜΠΙΕΣΜΕΝΟ ΑΕΡΙΟ ΠΥΡΟΒΟΛΕΙ ΣΥΜΠΑΓΕΣ ΟΒΙΔΕΣ ΜΕ ΥΨΗΛΗ ΔΙΑΤΡΗΤΙΚΗ ΙΚΑΝΟΤΗΤΑ ΘΩΡΑΚΙΣΗΣ.\"\n  STR_PWT_CANNON_UFOPEDIA: \"Η ΤΟΡΠΙΛΙ ΠΑΛΜΙΚΟΥ ΚΥΜΑΤΟΣ ΧΡΗΣΙΜΟΠΟΙΕΙ ΕΝΑ ΣΥΣΤΗΜΑ ΥΠΕΡΘΕΡΜΑΣΜΕΝΟΥ ΚΑΥΣΙΜΟΥ ΚΑΙ ΜΙΑ ΕΞΑΙΡΕΤΙΚΑ ΠΥΚΝΗ ΚΕΦΑΛΗ ΠΟΥ ΜΠΟΡΕΙ ΝΑ ΔΙΑΠΕΡΑΣΕΙ ΤΗΣ ΠΕΡΙΣΣΟΤΕΡΕΣ ΘΩΡΑΚΙΣΕΙΣ.\"\n  STR_GAUSS_CANNON_UFOPEDIA: \"ΤΟ ΟΠΛΟ GAUSS ΕΙΝΑΙ ΝΕΑ ΑΝΑΠΤΥΞΗ ΤΕΧΝΟΛΟΓΙΑΣ X-COM. Ο ΕΠΙΤΑΧΥΝΤΗΣ ΣΩΜΑΤΙΔΙΩΝ ΑΥΤΟΥ ΤΟΥ ΣΥΣΤΗΜΑΤΟΣ ΤΡΟΦΟΔΟΤΕΙΤΑΙ ΑΠΟ ΑΝΤΙΔΡΑΣΤΗΡΑ ΣΥΝΤΗΞΗΣ ΣΥΓΚΕΚΡΙΜΕΝΟΥ ΥΓΡΟΥ ΨΥΧΜΕΝΟΥ ΑΖΩΤΟΥ .\"\n  STR_SONIC_OSCILLATOR_UFOPEDIA: \"ΕΝΑΣ ΙΣΧΥΡΟΣ ΑΚΟΥΣΤΙΚΟΣ ΤΑΛΑΝΤΩΤΗΣ  ΠΟΥ ΔΗΜΙΟΥΡΓΕΙ ΚΥΜΑΤΑ ΗΧΗΤΙΚΗΣ ΔΥΝΑΜΗΣ. ΚΑΤΑΣΤΡΕΦΟΝΤΑΣ ΤΟΥΣ ΜΟΡΙΚΟΥΣ ΔΕΣΜΟΥΣ ΤΟΥ ΣΤΟΧΟΥ ΜΕ ΤΑΛΑΝΤΩΣΗ ΚΑΙ ΑΠΟΔΕΣΜΕΥΣΗ.\"\n  STR_AQUATOID_UFOPEDIA: \"Η Aquatoid Race είναι μια αρχαία φυλή, που υπήρχε χιλιετίες πριν από τα πρώτα βήματα του ανθρώπου στον κόσμο. Η συμπαγής τους μορφή και τα βολβώδη χαρακτηριστικά τους είναι μια αναδρομή στα διαστημικά αδέρφια τους, τους Sectoids. Η δύναμή τους βασίζεται στην ισχυρή τεχνολογία Molecular Control. Η Aquatoid φυλή επιδιώκει να πολλαπλασιάσει τη στείρα φυλή της με γενετική τροποποίηση, με ιδανικά υποκείμενα τα ανθρώπινα όντα. Πειράματα έχουν δημιουργήσει πολλές υβριδικές φυλές.\"\n  STR_AQUATOID_AUTOPSY: \"Αυτοψία Υδατόμορφου\"\n  STR_AQUATOID_AUTOPSY_UFOPEDIA: \"Η λεπτομερής ανάλυση αυτού του πλάσματος μας επιτρέπει να κάνουμε ορισμένες βασικές υποθέσεις. Είναι ένα Σεκτόιντ, οι πρώην εχθροί μας, αλλά αλλαγμένο με χειρουργικές μεθόδους και εμφυτεύματα σε υδρόβιο πλάσμα. Οι υποτυπώδεις πνεύμονες επιτρέπουν την αναπνοή του αέρα και την περιορισμένη επιφανειακή κινητικότητα. Υπάρχουν κυβερνοκινητικά εμφυτεύματα σε όλο το σώμα, που ενισχύουν τη δύναμη των ατροφικών άκρων του και τη λειτουργία των οργάνων του. Καθώς όλα τα μέλη αυτής της φυλής είναι πανομοιότυπα, μπορούμε να υποθέσουμε ότι τα πλάσματα αυτά είναι κλώνοι.\"\n  STR_GILLMAN_UFOPEDIA: \"Σχεδόν άνθρωπος, ένα παράξενο πλάσμα που φαίνεται να είναι ερπετοειδές ανθρωποειδές, πολύ στενά συνδεδεμένο με τον άνθρωπο. Αυτό το πλάσμα είναι εξαιρετικά ισχυρό και γρήγορο στον υποθαλάσσιο κόσμο. Οι Gillmen είναι μια πλήρως αναπτυγμένη φυλή, με αρσενικά και θηλυκά δείγματα διαφόρων ηλικιών. Διαφέρουν από την πλειονότητα των υποβρύχιων εξωγήινων, καθώς δεν φέρουν κανένα σημάδι γενετικής αλλοίωσης ή χειρουργικής παραμόρφωσης. Είναι πιθανό να βλέπουμε κάποιο αρχαίο παρακλάδι του δικού μας είδους.\"\n  STR_GILLMAN_AUTOPSY: \"Αυτοψία Γκίλμεν\"\n  STR_GILLMAN_AUTOPSY_UFOPEDIA: \"Μόλις άρχισε η χειρουργική επέμβαση έγινε σαφές ότι δεν πρόκειται για εξωγήινο, αλλά για ένα πλάσμα που γεννήθηκε στη Γη, μια αρχαία προϊστορική φυλή που θεωρήθηκε ότι καταστράφηκε τη στιγμή που τα θηλαστικά έγιναν κυρίαρχα. Σε μια εποχή που οι δεινόσαυροι τριγυρνούσαν αυτά τα πλάσματα ζούσαν, οι Gillmen - αμφίβιοι, έξυπνοι και δυνατοί. Ο κατακλυσμός που τερμάτισε την κυριαρχία των ερπετών σε αυτόν τον πλανήτη ανάγκασε αυτά τα πλάσματα σε μια συμβιωτική σχέση με τους νεοαφιχθέντες εξωγήινους. Μια μικρή ηλεκτρονική συσκευή είναι τοποθετημένη στο κρανίο των πλασμάτων.\"\n  STR_LOBSTERMAN_UFOPEDIA: \"Πρόκειται για ένα συγκλονιστικό πλάσμα, ψηλότερο από έναν άνθρωπο και με έξι άκρα, που δεν μοιάζει με τίποτα περισσότερο από έναν υδρόβιο Δαίμονα. Οι ομοιότητες μεταξύ αυτού του πλάσματος και του γήινου αστακού του χάρισαν το παρατσούκλι Αστακάνθρωπος στα στρατεύματα της X-Com. Πρόκειται για ένα μεγαθήριο του βυθού. Ένα προσεκτικά σχεδιασμένο πολεμικό πλάσμα απίστευτης δύναμης και πρακτικά άτρωτο στα πυρά πυραύλων. Μόνο οι τανάλιες του μπορούν να συνθλίψουν το ατσάλι.\"\n  STR_LOBSTERMAN_AUTOPSY: \"Αυτοψία Αστακάνθρωπου\"\n  STR_LOBSTERMAN_AUTOPSY_UFOPEDIA: \"Μόλις περάσει το σχεδόν άφθαρτο κέλυφός του, το πλάσμα είναι μια εκπληκτική κατασκευή. Ισχυροί μύες κυματίζουν γύρω από έναν σκελετό τιτανίου, ένα εξελιγμένο σύστημα στόχευσης με δυνατότητα σάρωσης πολλαπλών ζωνών είναι συνδεδεμένο απευθείας στον εγκέφαλο του πλάσματος. Τα πολλαπλά μάτια του προστατεύονται από πλαστικό σκληρότερο από ατσάλι και είναι σαφές ότι όταν τα πλάσματα αυτά αναπτύσσονται σωστά από τους αφέντες τους είναι σχεδόν ασταμάτητα. Βαθιά μέσα στο σώμα του είναι θαμμένες συσκευές άγνωστης κατασκευής και λειτουργίας.\"\n  STR_TASOTH_UFOPEDIA: \"Αυτοί οι ευκίνητοι και γρήγοροι εχθροί αποτελούν βασικό στήριγμα του εξωγήινου στρατού. Εκατοντάδες γεννιούνται, σε τεράστιες δεξαμενές αναπαραγωγής βαθιά στην καρδιά των αποικιών των εξωγήινων. Πολύ πιο ισχυρό από έναν άνθρωπο, το Τάσοθ είναι ένας αληθινός εξωγήινος και η συμπεριφορά και η σαρκοβόρα φύση του είναι απαράμιλλη στον πλανήτη. Το Τάσοθ αποτελεί συχνά την αιχμή του δόρατος μιας εξωγήινης επίθεσης και δεν φαίνεται ποτέ να αποφεύγει τη μάχη ακόμα και μπροστά σε συντριπτικές πιθανότητες.\"\n  STR_TASOTH_AUTOPSY: \"Αυτοψία Τάσοθ\"\n  STR_TASOTH_AUTOPSY_UFOPEDIA: \"Η ανατομία αποκάλυψε έναν κυβερνοκινητικό οργανισμό που διέθετε παράξενες δυνάμεις. Μέσα στην κοιλότητα του σώματος υπάρχει μια μικρή μονάδα ισχύος, αλλά δεν υπάρχουν αναγνωρίσιμα όργανα. Η ισχύς μεταδίδεται σε όλο το σώμα μέσω ενός βιοηλεκτρικού συστήματος μετάδοσης. Ολόκληρο το σώμα στερείται οστών ή οποιασδήποτε άλλης υποστηρικτικής δομής. Μόλις πεθάνει, η δύναμη σταματά και το πλάσμα μετατρέπεται σε μια άψυχη κουρελού από εξωγήινη σάρκα και υγρά που αναβλύζουν. Η μόνη άλλη εσωτερική κατασκευή είναι ένα ζεύγος κεραμικών κυψελών, τα οποία αν ενεργοποιηθούν για λίγο αναβιώνουν το πλάσμα.\"\n  STR_DEEP_ONE_UFOPEDIA: \"Ο Deep One είναι ένας βιολογικός εφιάλτης, μια διασταύρωση, που δημιουργήθηκε από τα πειράματα των Υδατοειδών που διαστρεβλώνουν το μυαλό. Έχουμε συναντήσει διάφορες παραλλαγές αυτού του πλάσματος. Μετά από εκτεταμένη έρευνα καταλήξαμε στο συμπέρασμα ότι αυτά κατασκευάζονται από τους εισβολείς. Αυξάνουν τις τάξεις τους όταν αιχμαλωτίζονται φρέσκα ανθρώπινα αποθέματα. Κάθε ένας από αυτούς τους υπανθρώπους είναι οπλισμένος με μια ηλεκτρική εκκένωση ενέργειας αρκετά ισχυρή για να σκοτώσει έναν υδατοναύτη.\"\n  STR_DEEP_ONE_AUTOPSY: \"Αυτοψία Deep One\"\n  STR_DEEP_ONE_AUTOPSY_UFOPEDIA: \"Το πλάσμα είναι ένα μόσχευμα ανθρώπινου και εξωγήινου οργανισμού. Ο ανθρώπινος εγκέφαλος έχει τροποποιηθεί μαζικά για να φιλοξενήσει τα ηλεκτρονικά συστήματα ελέγχου και τον εξωγήινο φλοιό. Όλα τα απομεινάρια του ανθρώπινου σώματος φαίνονται χαμένα εκτός από ένα: τα μάτια. Το χειρουργικό μόσχευμα φαίνεται να επιτρέπει στο εξωγήινο έμβρυο να καταναλώνει τον ανθρώπινο ξενιστή καθώς μεγαλώνει. Το σκληρό δέρμα του πλάσματος φαίνεται να είναι ένα μη οργανικό, μεταλλικό πλέγμα, εξαιρετικά ισχυρό και εύκαμπτο. Η προκύπτουσα διασταύρωση είναι ισχυρή, γρήγορη και τελείως υπό τον έλεγχο των εξωγήινων.\"\n  STR_BIODRONE_UFOPEDIA: \"Το Bio-drone είναι ένα δημιούργημα που μόνο ένα εξωγήινο μυαλό θα μπορούσε να επινοήσει. Πρόκειται για έναν εγκέφαλο (ανθρώπινο ή εξωγήινο) που αιωρείται σε αμνιακά υγρά και συνδέεται με μια τροφοδοτούμενη μονάδα βάσης που μπορεί να πετάξει στην ξηρά ή κάτω από το νερό. Κάθε Bio-drone είναι οπλισμένος με έναν ισχυρό ακουστικό διασπαστή, εν μέρει μηχανή και εν μέρει οργανισμός. Ορισμένοι από τους επιστήμονές μας έχουν προτείνει ότι το όπλο κινείται από τις αρχικές φωνητικές χορδές του οργανισμού-ξενιστή. Εξαιρετικά ακριβή και επίμονα αυτά τα σούπερ σκυλιά-φύλακες χρησιμοποιούνται ευρέως από τους εξωγήινους για την προστασία πολύτιμων περιουσιακών αγαθών.\"\n  STR_BIODRONE_AUTOPSY: \"Αυτοψία Bio-drone\"\n  STR_BIODRONE_AUTOPSY_UFOPEDIA: \"Η υπόθεση ότι ο ακουστικός διασπαστής είναι μια βιολογική συσκευή είναι αληθής. Αυτό το άτυχο πλάσμα κυριολεκτικά κραυγάζει τους εχθρούς του μέχρι θανάτου. Κάθε παράδειγμα έχει τεράστια σημάδια από χειρουργικά τραύματα και είναι σοβαρά ακρωτηριασμένο. Οι εξωγήινοι φαίνεται να κατακρεουργούν τον εγκέφαλο για να υπακούσει. Οι περισσότεροι από τους φλοιούς που χρησιμοποιούνται στα πλάσματα είναι εξωγήινης προέλευσης, αλλά τίποτα δεν μπορεί να συγκριθεί με τη φρίκη της εύρεσης μιας μονάδας που βασίζεται σε άνθρωπο. Τα Bio-drones τροφοδοτούνται από έναν κινητήρα ION και ενσωματώνουν κάποια μορφή συστήματος τηλεχειρισμού.\"\n  STR_TENTACULAT_UFOPEDIA: \"Ούτε τα βάθη ενός Λαβκραφτιανού εφιάλτη δεν θα μπορούσαν να γεννήσουν αυτό το απερίγραπτο πλάσμα. Δεν υπάρχει καμία σύγκριση με οποιοδήποτε γήινο ζώο, το περιβάλλον που θα μπορούσε να δημιουργήσει κάτι τέτοιο είναι πέρα από κάθε φαντασία. Οπλισμένο με μακριά πλοκάμια το Τεντακουλάτ παραλύει τα θύματά του και στη συνέχεια τα μετατρέπει σε άβουλα πράγματα. Αυτοί οι απόγονοι μπορούν να προκαλέσουν θάνατο με το άγγιγμα, ακόμα και μέσα από πανοπλίες. Το Τεντακουλάτ είναι ο πιο τρομακτικός εξωγήινος που έχει συναντήσει η X-Com.\"\n  STR_TENTACULAT_AUTOPSY: \"Αυτοψία Τεντακουλάτ\"\n  STR_TENTACULAT_AUTOPSY_UFOPEDIA: \"Η αυτοψία αποκαλύπτει ότι μικρά κυβερνητικά εμφυτεύματα έχουν τοποθετηθεί στον μεγάλο εγκέφαλο του πλάσματος. Το σύστημα όρασης είναι ένας πολύπλοκος συνδυασμός απόκτησης ορατού φωτός και θερμικής απεικόνισης. Ακόμη και στα σκοτεινά βάθη του ωκεανού αυτό το τέρας μπορεί να πλοηγηθεί με αλάνθαστη ακρίβεια. Υπάρχουν υποτυπώδη όργανα που φαίνεται να είναι το ελάχιστο για την επιβίωση. Κάθε πλάσμα έχει ένα μικρό στομάχι με εξωτερικό σύνδεσμο, είναι λογικό να υποθέσουμε ότι το ον τρέφεται με άμεση εισαγωγή θρεπτικών ουσιών από τους αφέντες του.\"\n  STR_CALCINITE_UFOPEDIA: \"Όπως οι στολές κατάδυσης των χαμένων ναυτικών, αυτοί οι εξωγήινοι παραμονεύουν στο βυθό της θάλασσας για τους απρόσεκτους. Ένα σφοδρό πλήγμα από τα δυνατότερα και από ατσάλινα νύχια του πλάσματος μπορεί να είναι αρκετά για να στείλουν και τους καλύτερους δύτες στον βυθό. Μέσα στη μάσκα προσώπου μπορεί να δει κανείς μια ζελατινώδη πράσινη μορφή να στροβιλίζει. Καμία ένδειξη του αληθινού πλάσματος δεν μπορεί να μαντέψει κανείς από τις συχνές θανατηφόρες συναντήσεις που είχαμε μαζί του.\"\n  STR_CALCINITE_AUTOPSY: \"Αυτοψία Καλσινίτη\"\n  STR_CALCINITE_AUTOPSY_UFOPEDIA: \"Μόλις αφαιρεθεί η θωρακισμένη στολή, ο Καλσινίτης αποκαλύπτεται ότι είναι μια τεράστια άμορφη μάζα πρωτοπλάσματος. Δεν υπάρχει ορατός εγκέφαλος, άκρα ή αισθητήρια όργανα, ένα μικρό μεταλλικό συστατικό βρίσκεται βαθιά μέσα στο υγρό σώμα. Μόλις πεθάνει μπορούμε μόνο να μαντέψουμε τη φύση του πλάσματος. Ένα ανεξήγητο αίνιγμα των εξωγήινων εχθρών μας.\"\n  STR_TRISCENE_UFOPEDIA: \"Αυτό το δίποδο ερπετό είναι μια αναδρομή στην εποχή των δεινοσαύρων. Φαίνεται να είναι ένα πλάσμα της Κρητιδικής εποχής από κάθε άποψη, εκτός από την ικανότητά του να επιβιώνει στο νερό και στην ξηρά. Αυτά τα πλάσματα είναι ζωσμένα με λοβούς όπλων και έχουν ένα σαγόνι επενδεδυμένο με τεράστια μεταλλικά δόντια. Συχνά αυτά τα τέρατα βρίσκονται στον πυρήνα των δυνάμεων επίθεσης των εξωγήινων, καθώς οι εξωγήινοι εξαπολύουν επιθέσεις στη γη. Ένα βαρύ και ισχυρό όπλο, οι διοικητές των Τασόθ τα αξιοποιούν με θανατηφόρα αποτελεσματικότητα.\"\n  STR_TRISCENE_AUTOPSY: \"Αυτοψία Τρισκένου\"\n  STR_TRISCENE_AUTOPSY_UFOPEDIA: \"Μόλις εκτεθεί στο μαχαίρι του επιστήμονα, ο Τρισκένιος αποκαλύπτει ότι είναι ένα αρχαίο πλάσμα, συμπληρωμένο με κυβερνοκινητικά εμφυτεύματα και οπλικά συστήματα. Ο μικροσκοπικός εγκέφαλός του συμπληρώνεται από μια μικρή μονάδα υπολογιστή τοποθετημένη στην καλωδίωση ελέγχου που φορούν όλα τα πλάσματα. Ένα σκληρό φυσικό δέρμα, ένα αρπακτικό ένστικτο ενισχυμένο με πρόσθετα όπλα το καθιστούν θανατηφόρο αντίπαλο σε όλα τα περιβάλλοντα.\"\n  STR_HALLUCINOID_UFOPEDIA: \"Έχοντας θερίσει τους ωκεανούς, οι εξωγήινοι έχουν εκθρέψει αυτά τα τεράστια γήινα πλάσματα ως όπλο. Μην παρασύρεστε σε μια ψεύτικη αίσθηση ασφάλειας όταν αντιμετωπίζετε αυτούς τους ακίνδυνους ναυτικούς του βυθού. Διαθέτοντας ένα παγωμένο χτύπημα μάχης από κοντά, το Χαλλουκινοειδές είναι ένας θανατηφόρος εχθρός.\"\n  STR_HALLUCINOID_AUTOPSY: \"Αυτοψία Υπναγωγικού\"\n  STR_HALLUCINOID_AUTOPSY_UFOPEDIA: \"Μέσα στα πολλά στρώματα του ζελατινώδους σώματος αυτού του οργανισμού υπάρχει ένας ισχυρός χημικός καταψύκτης, η κύρια επιθετική του ικανότητα. Το μαλακό και εύκαμπτο δέρμα του Χαλλουκινοειδές φαίνεται ευαίσθητο σε επιθέσεις με βάση τη θερμότητα. Συχνά αυτός ο μεταλλαγμένος βρίσκεται με την παρέα των αφεντικών του, των Υδατοειδών.\"\n  STR_XARQUID_UFOPEDIA: \"Άλλο ένα τροποποιημένο ασπόνδυλο της Γης, το Ζαρκουίντ είναι ένα πλάσμα μεγάλης ομορφιάς και κινδύνου. Ο γοργός κολυμβητικός κολοσσός κρύβει ένα καταστροφικό οπλοστάσιο, ένα αποπνικτικό σπρέι μελανιού και μια ιονισμένη έκρηξη σωματιδίων. Από τις πρώτες μας συναντήσεις με αυτό το πανίσχυρο πλάσμα είμαστε επιφυλακτικοί απέναντι στη δύναμή του και στους ελεγκτές του, τους εκδικητικούς Γκίλμεν.\"\n  STR_XARQUID_AUTOPSY: \"Αυτοψία Ζαρκουίντ\"\n  STR_XARQUID_AUTOPSY_UFOPEDIA: \"Αυτός ο υπεραναπτυγμένος Ναυτίλος έχει γίνει τεράστιος με μια δίαιτα από εξωγήινα φάρμακα και χειρουργικές επεμβάσεις. Διαστρεβλωμένοι πέρα από τα όρια της φύσης, οι Γκίλμεν έχουν προσθέσει μηχανικά συστήματα ελέγχου στο πλάσμα και τώρα δεν υπάρχει τίποτα από την αρχική φύση του πλάσματος. Ανεπτυγμένο ως οργανική πλατφόρμα όπλων, το σκληρό κέλυφος και η κινητικότητα των Ζαρκουίντ το καθιστούν ένα φοβερό αντίπαλο.\"\n  STR_ION_BEAM_ACCELERATORS_UFOPEDIA: \"Τα εξωγήινα ιπτάμενα υποβρύχια βασίζονται σε πολύπλοκα συστήματα ενέργειας για να κινούνται με απίστευτη ταχύτητα στα βάθη. Η βάση για την τεχνολογία τους είναι ο ΙΟΝΙΚΟΣ ΔΙΑΝΟΜΕΑΣ, χρησιμοποιώντας τον Ζρμπίτη ως καταλύτη, οι κινητήρες εκτοπίζουν 100 φορές τον όγκο τους σε νερό ανά δευτερόλεπτο. Αυτή η τεράστια ισχύς σημαίνει ότι οι εξωγήινοι είναι σε θέση να ξεπεράσουν τα περισσότερα γήινα υποβρύχια. Μπορούμε να αναπαράγουμε αυτό το σύστημα προώθησης χρησιμοποιώντας υδατοπλαστικά και ενεργειακές μπαταρίες Ζρμπίτη.\"\n  STR_MAGNETIC_NAVIGATION_UFOPEDIA: \"Αυτές οι μονάδες δημιουργούν ένα σφαιρικό μαγνητικό πεδίο πολλαπλών επιπέδων, το οποίο η συστοιχία προβάλλει έως και 1000 μέτρα γύρω από το υποβρύχιο. Οι εξωγήινοι πλοηγοί είναι άμεσα συνδεδεμένοι με τις μηχανές και αισθάνονται το δρόμο τους στον αόρατο κόσμο κάτω από τα κύματα. Το σύστημα διασύνδεσης λειτουργεί χρησιμοποιώντας τροποποιημένη από τους Εξωγήινους εγκεφαλική ύλη που επικοινωνεί απευθείας με τον εγκέφαλο του χειριστή μέσω νευρικής διασύνδεσης.\"\n  STR_ALIEN_SUB_CONSTRUCTION_UFOPEDIA: \"Κάθε σκάφος έχει μια δομή που μοιάζει με χαμαιλέοντα, προσεκτικά διαμορφωμένη σε θαλάσσια πλάσματα και κατασκευασμένη από Υδατο Πλαστικό. Κάθε υποβρύχιο λειτουργεί ως οργανισμός: πλήρωμα και σκάφος σε αρμονία. Τα περισσότερα από αυτά τα συστήματα μπορούν να αντιγραφούν και να αναπτυχθεί μια υβριδική τεχνολογία που θα μας επιτρέψει να κινηθούμε στο ίδιο τεχνολογικό επίπεδο.\"\n  STR_ALIEN_CRYOGENICS_UFOPEDIA: \"Οι αναρίθμητοι εξωγήινοι που έχουν κρυφτεί στη Γη κρατούνται σε αναστολή ζωής, κρυογονικά παγωμένοι. Όλα τα πλάσματα είναι σφραγισμένα σε μονάδες, η θερμοκρασία του σώματός τους μειώνεται σε ένα σημείο όπου οι σωματικές λειτουργίες σχεδόν σταματούν. Μια εξέταση των μονάδων μέχρι στιγμής αποκαλύπτει τα απίστευτα χρονικά διαστήματα που οι σώματα κρατήθηκαν ανασταλμένα, μερικά από αυτά για πάνω από 60 εκατομμύρια χρόνια.\"\n  STR_ALIEN_CLONING_UFOPEDIA: \"Πολλοί από τους εξωγήινους που έχουμε αιχμαλωτίσει είναι πανομοιότυποι μέχρι και στο DNA τους, κανονικά πιστά αντίγραφα. Δείγματα κυττάρων τοποθετούνται στις μονάδες από τις παγωμένες τράπεζες γονιδίων των εξωγήινων. Ορισμένες μονάδες περιέχουν ανθρώπους ή μέρη του ανθρώπινου σώματος. Είναι δυνατόν να υπάρχει και άλλη χρήση για αυτές τις μονάδες κλωνοποίησης, όπως η δημιουργία ενός υβριδικού εξωγήινου-ανθρώπου.\"\n  STR_ALIEN_LEARNING_ARRAYS_UFOPEDIA: \"Χρησιμοποιώντας Μοριακά Εμφυτεύματα Ελέγχου στους κροτάφους όλων των Εξωγήινων, αυτές οι μηχανές εισάγουν πληροφορίες απευθείας στον εγκέφαλο. Φρεσκοκλωνοποιημένα Εξωγήινα μεταφέρονται σε αυτές τις μονάδες και έχουν τις φυλετικές μνήμες και όλες τις επιστημονικές ή πολεμικές πληροφορίες μεταφορτωμένες στο κενό μυαλό τους.\"\n  STR_ALIEN_IMPLANTER_UFOPEDIA: \"Αυτή η μονάδα χρησιμοποιείται για να τοποθετήσει εξωγήινους με μοριακά ελεγχόμενα εμφυτεύματα, να γονιμοποιήσει αναπαραγωγικές φυλές και να εισάγει ή να αφαιρεί όργανα και ηλεκτρονικά είδη από οποιοδήποτε πλάσμα. Ο διαδικασία υποτίθεται ότι γίνεται σε υποταγμένους ασθενείς, αλλά το υποκείμενο είναι πολύ ενήμερο για τη διαδικασία και δυστυχώς η ανθρώπινη ανατομία φαίνεται να ταιριάζει απόλυτα στη μονάδα.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"Έχουμε τώρα όλα τα στοιχεία για να βρούμε γιατί οι εξωγήινοι αιχμαλωτίζουν ανθρώπους. Δεν είναι τροφή, δεν γίνονται γονιμοποίηση με εξωγήινα εμβρυα, αλλά αποτελούν τη βάση μιας σειράς πλασμάτων και συστημάτων ελέγχου. Η τεχνολογία των εξωγήινων βασίζεται σε μια κοινή σκέψη, ένα κοινό νου και ο ανθρώπινος εγκέφαλος είναι το ιδανικός φορέας για αυτά τα συστήματα. Ο ανθρώπινος εγκεφαλικός ιστός χρησιμοποιείται στην πλειοψηφία των εξωγήινων βιολογικών συστημάτων αποθήκευσης και ανάκτησης πληροφοριών, τα απομεινάρια χρησιμοποιούνται για κατασκευή και αναπαραγωγή.\"\n  STR_AQUA_PLASTICS_UFOPEDIA: \"Τα υποβρύχια εξωγήινων και οι κατασκευές τους χρησιμοποιούν ένα απίστευτα ισχυρό, ευέλικτο και ανθεκτικό υλικό για την πλειοψηφία των κατασκευών τους. Τα  ύδροπλαστικά είναι πολύπλοκα υλικά με πολλαπλές συνδέσεις και καταλυτική δράση του Zrbite. Πυκνά, αλλά ελαφριά, η υπόσταση έχει αντοχή ακόμα και πάνω από το τιτάνιο ή το Kevlar.\"\n  STR_ZRBITE_UFOPEDIA: \"Αυτό είναι ένα κράμα εξωγήινης προέλευσης, ένα μέρος χρυσό ένα μέρος εξωγήινο βιο-υλικό. Όταν χρησιμοποιούνται ως πηγή ενέργειας, μικρές ποσότητες θα παράγουν περισσότερη ισχύ από μια πυρηνική μονάδα δεκαπλάσιου μεγέθους..Είναι πέρα από την τεχνική μας ικανότητα να αναπαράγουμε αυτό το υλικό καθώς τα περισσότερα από τα συστατικά του είναι εξωγήινης προέλευσής.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"Οι εξωγήινοι επιτίθενται σε όλο τον κόσμο, με ανελέητη ικανότητα. Δεν μπορούμε να εντοπίσουμε την πηγή τους. Μήπως βρίσκεται σε κάποιον ωκεανό τόσο αδιαπέραστο που δεν μπορούμε να τον εντοπίσουμε; Όχι όλοι οι οργανισμοί που έχουμε συναντήσει είναι εξωγήινοι, κάποιοι είναι πολύ αρχαίοι, κάποιοι ανήκουν σε εξελικτικά μονοπάτια που πιστεύαμε ότι εξαφανίστηκαν πριν καιρό. Αντιμετωπίζουμε μια απειλή που κοιμόταν για χιλιετίες, μια διακριτική συμβίωση ανθρώπου και εξωγήινου. Βαθιά στους ωκεανούς υπάρχουν αρχαίες τοποθεσίες που χρησιμοποιούν οι εξωγήινοι για να επικοινωνήσουν με τους αστρικούς τους συγγενείς. Κάθε μία από αυτές τις δώδεκα τοποθεσίες περιέχει μία συσκευή Synomium, μια ισχυρή τεχνολογία εξωγήινων. Τώρα, με την πολεμική τους μηχανή σε δράση, οι εξωγήινοι επανενεργοποιούν αυτές τις τοποθεσίες για να διευρύνουν το δίχτυ Μοριακού Ελέγχου τους, πρέπει να καταστρέψουμε αυτές τις τοποθεσίες με κάθε κόστος.\"\n  STR_THE_ULTIMATE_THREAT_UFOPEDIA: \"Πριν από εξήντα πέντε εκατομμύρια χρόνια, ένα τεράστιο πλοίο αποικιοποίησης στάλθηκε στη Γη από ένα απομακρυσμένο εξωγήινο κόσμο. Καθώς το τεράστιο σκάφος πλησίαζε το νεογέννητο πλανήτη, μια μαζική και βίαιη ηλιακή έκλαμψη προκάλεσε βλάβη των συστημάτων πλοήγησης. Παραλυμένος και αποτυχημένος ο τεράστιος όγκος κατρακύλησε μέσα από τη στρατόσφαιρα για να καταδυθεί στους Κρητιδικούς ουρανούς.. Στη Γη, αναρίθμητα είδη ζωής παρατηρούσαν με αγωνία τον ουρανό καθώς ο εχθρός τους όργωνε τον πλανήτη. Ένας τεράστιο σύννεφο σκόνης έφραξε την ατμόσφαιρα και καθώς η γη κρύωνε, έτσι και η κυρίαρχη ζωή, οι μεγαλοπρεπείς δεινόσαυροι, πέθαναν. Αλλά τα 400 δισεκατομμύρια τόνοι του T'leth δεν καταστράφηκαν από την πρόσκρουση, εξελίγμενοι υπερυπολογιστές ξεκίνησαν έναν κρυογενή κύκλο ύπνου για τα πλάσματα βαθιά μέσα στις αποθήκες του. Καθώς περνούσαν τα αιώνια, οι υπολογιστές ξύπνησαν ομάδες Εξωγήινων για να προσπαθήσουν να επικοινωνήσουν με τους αστρικούς τους συγγενείς, όλα μάταια, καθώς ο πυρήνας της εξωγήινης δύναμης κοιμόταν.\"\n  STR_TLETH_THE_ALIEN_CITY: \"T'leth η Πόλη των Εξωγήινων\"\n  STR_TLETH_THE_ALIEN_CITY_UFOPEDIA: \"Το τεράστιο διαστημόπλοιο των εξωγήινων, T'leth, βρίσκεται βυθισμένο στον Sigsbee Deep, στον Κόλπο του Μεξικού. Στην καρδιά της πόλης βρίσκεται ένας εξωγήινος τρόμος, τόσο ποταπός και τόσο δυνατός που ούτε ο θάνατος δεν μπορεί να το διεκδικήσει. Σε ένα θάλαμο από εξωγήινο μέταλλο βρίσκεται η κοιμισμένη μορφή του μεγάλου ονειροπόλου, του Απόλυτου Εξωγήινου. Η ανύψωση του T'leth πάνω από τα κύματα θα ξεκινήσει τον κύκλο της επαναφοράς του και μόλις ανασηκωθεί, θα είναι ασταμάτητος. Παρόλο που δεν είναι ζωντανός αλλά ούτε και νεκρός, ο εξωγήινος νους ελέγχει τον εξωγήινο στρατό. Η παράξενη τεχνολογία του μοριακού ελέγχου συνδέει όλους τους εξωγήινους με τον Ένα Νου και τον Ένα Νου με όλους τους εξωγήινους. Γενετικά μεταλλαγμένα εμβρυϊκά εξωγήινα/ανθρώπινα όντα παρέχουν ενέργεια στον εξωγήινο νου και αποτελούν τον κρίκο σύνδεσης μεταξύ του κυρίαρχου και των υπηκόων του. Ο μύθος του Απόλυτου Εξωγήινου υπάρχει στις καρδιές και στα μυαλά της ανθρωπότητας εδώ και αιώνες, η θάλασσα πάντα έκρυβε την απόλυτη αλήθεια.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"ΚΕΝΤΡΑΡΕ ΣΤΗΝ ΤΟΠΟΘΕΣΙΑ - ΧΡΟΝΟΣ = 5 Δευτ.\"\n  STR_CANCEL_UC: \"ΑΚΥΡΟ\"\n  STR_NONE: \"Τίποτα\"\n  STR_UNKNOWN: \"Άγνωστο\"\n  STR_POOR: \"Φτωχά\"\n  STR_AVERAGE: \"Μέσος\"\n  STR_GOOD: \"Καλά\"\n  STR_EXCELLENT: \"Άριστα\"\n  STR_BUILD_NEW_BASE_UC: \"ΧΤΙΣΕ ΝΕΑ ΒΑΣΗ\"\n  STR_BASE_INFORMATION: \"ΠΛΗΡΟΦΟΡΙΕΣ ΒΑΣΗΣ\"\n  STR_EQUIP_CRAFT: \"ΕΞΟΠΛΙΣΤΕ ΤΟ ΥΠΟΒΡΥΧΙΟ\"\n  STR_BUILD_FACILITIES: \"ΚΑΤΑΣΚΕΥΗ ΕΓΚΑΤΑΣΤΑΣΕΩΝ\"\n  STR_RESEARCH: \"ΕΡΕΥΝΑ\"\n  STR_MANUFACTURE: \"ΠΑΡΑΓΩΓΗ\"\n  STR_TRANSFER_UC: \"ΜΕΤΑΦΟΡΑ\"\n  STR_PURCHASE_RECRUIT: \"ΑΓΟΡΑ/ΠΡΟΣΛΗΨΗ\"\n  STR_SACK: \"ΑΠΟΛΥΣΕ\"\n  STR_SELL_SACK_UC: \"ΠΩΛΗΣΗ/ΑΠΟΛΥΣΗ\"\n  STR_GEOSCAPE_UC: \"ΓΕΩΤΟΠΙΟ\"\n  STR_NAME: \"Όνομα\"\n  STR_AREA: \"Περιοχή\"\n  STR_BUILD_NEW_BASE: \"Χτίσε Νέα Βάση\"\n  STR_CANCEL: \"Άκυρο\"\n  STR_COST_UC: \"ΚΟΣΤΟΣ>\"\n  STR_CONSTRUCTION_TIME_UC: \"ΧΡΟΝΟΣ ΚΑΤΑΣΚΕΥΗΣ>\"\n  STR_DAY:\n    one: \"{N} μέρα\"\n    other: \"{N} days\"\n  STR_HOUR:\n    one: \"{N} ώρες\"\n    other: \"{N} ώρες\"\n  STR_MAINTENANCE_UC: \"ΣΥΝΤΗΡΗΣΗ>\"\n  STR_OK: \"ΟΚ\"\n  STR_INSTALLATION: \"ΕΓΚΑΤΑΣΤΑΣΕΙΣ\"\n  STR_CURRENT_RESEARCH: \"ΤΡΕΧΟΥΣΑ ΕΡΕΥΝΑ\"\n  STR_SCIENTISTS_AVAILABLE: \"Διαθέσιμοι Επιστήμονες>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Κατανεμημένοι Επιστήμονες>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Ελεύθερος Χώρος Εργαστηρίου>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"ΕΡΕΥΝΗΤΙΚΟ ΠΡΟΓΡΑΜΜΑ\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"ΚΑΤΑΝΕΜΗΜΕΝΟΙ ΕΠΙΣΤΗΜΟΝΕΣ\"\n  STR_PROGRESS: \"ΠΡΟΟΔΟΣ\"\n  STR_NEW_PROJECT: \"Νέο Πρόγραμμα\"\n  STR_CANCEL_PROJECT: \"ΑΚΥΡΩΣΗ ΕΡΓΟΥ\"\n  STR_NEW_RESEARCH_PROJECTS: \"ΝΕΑ ΕΡΕΥΝΗΤΙΚΑ ΠΡΟΓΡΑΜΜΑΤΑ\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"ΔΙΑΘΕΣΙΜΟΙ ΕΠΙΣΤΗΜΟΝΕΣ>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"ΕΛΕΥΘΕΡΟΣ ΧΩΡΟΣ ΕΡΓΑΣΤΗΡΙΟΥ>{ALT}{0}\"\n  STR_INCREASE: \"Αύξησε\"\n  STR_DECREASE: \"Μείωσε\"\n  STR_START_PROJECT: \"ΕΝΑΡΞΗ\"\n  STR_CURRENT_PRODUCTION: \"ΤΡΕΧΟΥΣΑ ΠΑΡΑΓΩΓΗ\"\n  STR_ENGINEERS_AVAILABLE: \"Διαθέσιμοι Τεχνικοί >{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Τεχνικοί Ανατέθηκαν>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Ελεύθερος χώρος>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Τρέχοντα Κονδύλια>{ALT}{0}\"\n  STR_ITEM: \"ΑΝΤΙΚΕΙΜΕΝΟ\"\n  STR_ENGINEERS__ALLOCATED: \"Τεχνικοί Ανατέθηκαν\"\n  STR_UNITS_PRODUCED: \"Παραγμένες Μονάδες\"\n  STR_TOTAL_TO_PRODUCE: \"Σύνολο Παραγωγής\"\n  STR_COST__PER__UNIT: \"Κόστος{NEWLINE}ανά{NEWLINE}Μονάδα\"\n  STR_DAYS_HOURS_LEFT: \"Υπόλοιπες Μέρες/Ώρες\"\n  STR_NEW_PRODUCTION: \"Νέα Παραγωγή\"\n  STR_PRODUCTION_ITEMS: \"Αντικείμενα Παραγωγής\"\n  STR_CATEGORY: \"ΚΑΤΗΓΟΡΙΑ\"\n  STR_START_PRODUCTION: \"ΞΕΚΙΝΑ ΠΑΡΑΓΩΓΗ\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} Ώρες τεχνικού για την παραγωγή μίας μονάδας\"\n  STR_COST_PER_UNIT_: \"Κόστος ανά μονάδα>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Απαιτούμενος Χώρος>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"ΑΠΑΙΤΟΥΝΤΑΙ ΕΙΔΙΚΑ ΥΛΙΚΑ\"\n  STR_ITEM_REQUIRED: \"ΑΠΑΙΤΟΥΜΕΝΑ ΑΝΤΙΚΕΙΜΕΝΑ\"\n  STR_UNITS_REQUIRED: \"ΑΠΑΙΤΟΥΜΕΝΕΣ ΜΟΝΑΔΕΣ\"\n  STR_UNITS_AVAILABLE: \"ΔΙΑΘΕΣΙΜΕΣ ΜΟΝΑΔΕΣ\"\n  STR_STOP_PRODUCTION: \"ΣΤΑΜΑΤΗΜΑ ΠΑΡΑΓΩΓΗΣ\"\n  STR_ENGINEERS_AVAILABLE_UC: \"ΤΕΧΝΙΚΟΙ ΔΙΑΘΕΣΙΜΟΙ>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"ΕΛΕΥΘΕΡΟΣ ΧΩΡΟΣ ΜΗΧΑΝΟΥΡΓΕΙΟΥ>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"ΜΗΝΙΑΙΟ ΚΕΡΔΟΣ>{ALT}{0}\"\n  STR_INCREASE_UC: \"ΑΥΞΗΣΕ\"\n  STR_DECREASE_UC: \"ΜΕΙΩΣΕ\"\n  STR_UNITS_TO_PRODUCE: \"Μονάδες να Παραχθούν\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"ΑΓΟΡΕΣ/ΠΡΟΣΛΗΨΕΙΣ\"\n  STR_COST_OF_PURCHASES: \"Κόστος Αγορών>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"ΚΟΣΤΟΣ ΑΝΑ ΜΟΝΑΔΑ\"\n  STR_QUANTITY_UC: \"ΠΟΣΟΤΗΤΑ\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"ΔΙΑΘΕΣΙΜΟ ΠΡΟΣΩΠΙΚΟ:ΣΥΝΟΛΙΚΟ ΠΡΟΣΩΠΙΚΟ>\"\n  STR_SOLDIERS: \"Υδροναύτες\"\n  STR_SCIENTISTS: \"Επιστήμονες\"\n  STR_ENGINEERS: \"Τεχνικοί\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"ΧΡΗΣΙΜΟΠΟΙΟΥΜΕΝΟΣ:ΕΛΕΥΘΕΡΟΣ ΧΩΡΟΣ>\"\n  STR_LIVING_QUARTERS: \"Κοιτώνες\"\n  STR_STORES: \"Αποθήκες\"\n  STR_LABORATORIES: \"Εργαστήρια\"\n  STR_WORK_SHOPS: \"Μηχανουργεία\"\n  STR_HANGARS: \"Υπόστυλο Ιπτάμενου Υποβρύχιου\"\n  STR_SHORT_RANGE_DETECTION: \"Σονάρ Μικρής Εμβέλιας\"\n  STR_DEFENSE_STRENGTH: \"Αμυντική Δύναμη\"\n  STR_TRANSFERS_UC: \"ΜΕΤΑΦΟΡΕΣ\"\n  STR_TRANSFERS: \"Μεταφορές\"\n  STR_ARRIVAL_TIME_HOURS: \"Ώρα Άφιξης (ώρες)\"\n  STR_COST_: \"Κόστος>{ALT}{0}\"\n  STR_AREA_: \"Περιοχή>{ALT}{0}\"\n  STR_BASE_NAME: \"Όνομα Βάσης;\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"ΕΠΙΛΕΞΤΕ ΘΕΣΗ ΓΙΑ ΑΕΡΟΘΑΛΑΜΟ\"\n  STR_TRANSFER: \"Μεταφορά\"\n  STR_AMOUNT_TO_TRANSFER: \"ΠΟΣΟΤΗΤΑ ΜΕΤΑΦΟΡΑΣ\"\n  STR_SELECT_DESTINATION_BASE: \"Επέλεξε Βάση Προορισμού\"\n  STR_COST: \"Κόστος\"\n  STR_INTRO_1: \"Πνευματικά δικαιώματα 1995 MicroProse\"\n  STR_INTRO_2: \"Άρης: Η πτώση της Κυδωνίας.\"\n  STR_INTRO_3: \"Ένας νικηφόρος X-Com, έχοντας καταστρέψει τον ίδιο τον πυρήνα της εξωγήινης πολεμικής μηχανής, απογειώνεται για το σπίτι. Ωστόσο, δεν είναι όλα νεκρά στην κατεστραμμένη βάση του Άρη.\"\n  STR_INTRO_4: \"Μια ισχυρή δέσμη ταχυόντος ρέει από τα ερείπια του νευρικού κέντρου της Κυδωνίας - εκτοξεύεται μέσα στο κενό. Ο προορισμός του..............\"\n  STR_INTRO_5: \"Γη.\"\n  STR_INTRO_6: \"Βαθιά μέσα στον ωκεανό ο δέσμη χτυπά έναν παλιό ανενεργό δέκτη. Τεράστιοι υπολογιστές που κοιμούνται ξεκινούν να ξυπνούν. Στα βάθη, πέρα από την όραση των ανθρώπων, τεράστιες αίθουσες με κοιμώμενους εξωγήινους ξεκινούν τον μακρύ κύκλο αναζωογόνησής τους.\"\n  STR_INTRO_7: \"2040: Μία αδαής Γη. Οι τρόμοι του πολέμου με τους εξωγήινους έχουν ξεχαστεί. Ωστόσο, στις χαμένες και κρυμμένες γωνιές του ωκεανού, οι στρατοί των εξωγήινων είναι έτοιμοι - έτοιμοι να ανατρέψουν την ανθρωπότητα και να καταλάβουν τον κόσμο.\"\n  STR_INTRO_8: \"Οι εξωγήινοι επιτίθενται εναντίον της ανθρωπότητας· αναζητώντας δείγματα για τα διαστρεβλωμένα τους πειράματα· λεηλατώντας τον κόσμο για πολύτιμα μεταλλεύματα και πόρους· και λεηλατώντας από τις θάλασσες. Στη συνέχεια, οι εξωγήινοι στρέφουν το βλέμμα τους πάνω από τα κύματα.\"\n  STR_INTRO_9: \"Ισχυρά υποβρύχια που πετούν με παράξενο σχεδιασμό πλέουν στους ωκεανούς - κοιτώντας, αναζητώντας, κυνηγώντας...\"\n  STR_INTRO_10: \"Βρίσκοντας λεία επιτίθενται.\"\n  STR_INTRO_11: \"Περίεργα νέα όπλα κατευθύνονται εναντίον ενός ανυπεράσπιστου κόσμου. Είμαστε απόλυτα στο έλεος της απειλής των εξωγήινων.{NEWLINE}Μόνο ένας οργανισμός μπορεί να μας σώσει, αλλά τους γυρίσαμε την πλάτη εδώ και πολύ καιρό......\"\n  STR_INTRO_12: \"Πειραματική Υποβρύχια Εγκατάσταση X-COM\"\n  STR_INTRO_13: \"\\\"Κίνδυνος βοήθεια! Βοήθεια!\\\" \\\"Εδώ, το υπερατλαντικό πλοίο Hyperion\\\". \\\"Βρισκόμαστε υπό επίθεση\\\". \\\"Βοήθεια! Κίνδ............\\\"\"\n  STR_INTRO_14: \"\\\"Πύργος ελέγχου Διοίκησης προς Υποθαλάσσιο Κέντρο Ένα: Ανοίξτε τις θαλάσσιες πόρτες\\\", \\\"εκτοξεύστε το Barracuda Zero One. Δεχόμαστε επίθεση από εξωγήινους - κατάσταση συναγερμού Κόκκινο\\\".{NEWLINE}\\\"Επαναλαμβάνω: κατάσταση συναγερμού Κόκκινο\\\"\"\n  STR_INTRO_15: \"Οι εξωγήινοι είναι αδίστακτοι στην αποτελεσματικότητά τους....\"\n  STR_INTRO_16: \"...αλάθητοι στην ακρίβειά τους\"\n  STR_INTRO_17: \"«Barracuda Zero One προς βάση» - «προσεγγίζουμε ό,τι έχει απομείνει από το Hyperion».\"\n  STR_INTRO_18: \"Επιβραδύνοντας\\\". {NEWLINE} \\\"Δύο μέτρα\\\". {NEWLINE} \\\"Ένα μέτρο\\\". {NEWLINE} \\\"Όλοι οι καταδρομείς ετοιμαστείτε για άμεση αποστολή\\\".\"\n  STR_INTRO_19: \"...........'Ο αεροσυμπιεστής είναι καθαρός'...'πλησιάζουμε τα ερείπια'.{NEWLINE}'Άγιε μου!'{NEWLINE}'Τα βλέπετε αυτά τα πλάσματα από την κάμερα μου;'\"\n  STR_GAMEOVER_1: \"Αποτύχαμε, οι εξωγήινοι εξολόθρευσαν τις τελευταίες μας ελπίδες σωτηρίας.{NEWLINE}Το X-Com καταστράφηκε και η Γη βρίσκεται στα πόδια του αρχαίου εχθρού.\"\n  STR_GAMEOVER_2: \"Ο T'leth βροντά ψηλά στη στρατόσφαιρα και αρχίζει να κινείται σε όλη την επιφάνεια του κόσμου. Διανέμοντας θάνατο και συλλέγοντας τα ερείπια της ανθρώπινης φυλής. Βαθιά στα σπλάχνα του, το δολοφονικό μυαλό των εξωγήινων αρχίζει να ξεσηκώνεται.\"\n  STR_GAMEOVER_3: \"Στις πρωτεύουσες όλων των χωρών σχεδιάζονται απεγνωσμένα σχέδια. Όλα είναι μάταια, χωρίς την τεχνολογία που παρέχεται από το ερευνητικό πρόγραμμα του X-Com τα όπλα μας είναι αναποτελεσματικά.\"\n  STR_GAMEOVER_4: \"Οι εξωγήινοι τοποθετούν βάσεις στους πόλους και αρχίζουν να λιώνουν τον πάγο, ο κόσμος θα γίνει ένας τεράστιος ωκεανός. Τα κατάλοιπα της ανθρώπινης φυλής συλλέγονται και χρησιμοποιούνται σε αποτρόπαια πειράματα εκτροφής για άγνωστους σκοπούς των εξωγήινων. Οι ουρανοί σκοτεινιάζουν και ένας πανίσχυρος λοιμός είναι πάνω απο τα εδάφη της Γης.\"\n  STR_GAMEOVER_5: \"Δεν μπορούμε να προσφέρουμε καμία αντίσταση στη νέα παγκόσμια τάξη πραγμάτων, όσοι προσπαθούν συναντούν μια φλογερή μοίρα στα χέρια των ακατανόητων όπλων των εξωγήινων. Για τους υπόλοιπους εμάς, δεν υπάρχει τέτοια ευλογημένη απελευθέρωση, η μητέρα Γη γίνεται ένας εξωγήινος κόσμος και η ανθρωπότητα χάνεται κάτω από μια φρίκη που σέρνεται.\"\n  STR_OUTRO_1: \"Ο τάφος, ερειπωμένος και αποδεκατισμένος, ένας βρυχηθμός βγαίνει από το φέρετρο στο κέντρο του.{NEWLINE}Ανόητοι, θα πεθάνετε όλοι....................\"\n  STR_OUTRO_2: \".................κανείς δεν μπορεί να ξεφύγει.\"\n  STR_OUTRO_3: \"Μια τεράστια έκρηξη σημειώνετε στον τάφο και το κύμα σκίζει την πόλη, συντρίμμια και καπνός γεμίζουν τον αέρα. Τα σχέδια των Εξωγήινων ματαιώνονται.........\"\n  STR_OUTRO_4: \"Το ανατριχιαστικό μέγεθος του T'leth αρχίζει να διαρρηγνύεται. Φλόγες και καπνός αναβλύζουν από τους λαμπρούς πύργους και τις αδαμαντίνες αίθουσες του.\"\n  STR_OUTRO_5: \"Η πανίσχυρη εξωγήινη δύναμη πέφτει προς τη θάλασσα, οι κραυγές του ταλαιπωρημένου μετάλλου και οι ψυχές γεμίζουν τον αέρα. Πλέον ο Μεγάλος Ονειροπόλος δεν θα ονειρεύεται να κυριεύσει τον κόσμο.\"\n  STR_OUTRO_6: \"Μια τελική καταιγιστική βροντή που σπάει αυτιά και ο T'leth διαλύεται σε κομμάτια.{NEWLINE}Η απειλή των εξωγήινων έχει εξαφανιστεί, η Γη είναι καθαρή..................\"\n  STR_OUTRO_7: \"Ένας νυσταγμένος γαλαζοπράσινος πλανήτης, σε μια μακρινή γωνιά του γαλαξία.\"\n  STR_OUTRO_8: \"Το εγγύς μέλλον, ένα ασφαλές μέρος για να είσαι.\"\n  STR_OUTRO_9: \"Η απειλή των εξωγήινων για τη Γη έχει ηττηθεί εδώ και πολύ καιρό.\"\n  STR_OUTRO_10: \"Τεράστια μητρόπολη σαν πόλεις στεγάζουν δισεκατομμύρια ανθρωπίνου γένους.\"\n  STR_OUTRO_11: \"Τα κατορθώματα του X-Com και οι εξωγήινοι πολέμοι είναι ιστορίες για παραμύθια παιδιών.\"\n  STR_OUTRO_12: \"Αλλά οι θρύλοι είχαν πάντα τη συνήθεια να περιέχουν έναν κόκκο αλήθειας............\"\n  STR_RISE_1: \"T'leth, αποκαλείται από πολλά πράγματα σε πολλούς θρύλους από πολλές χώρες.\"\n  STR_RISE_2: \"Με μια εκρηκτική κραυγή που αντηχεί σε όλη την υδρόγειο ο T'leth αρχίζει να ανεβαίνει από τον βυθό της θάλασσας.\"\n  STR_RISE_3: \"Το τεράστιο οικοδόμημα ξεχύνεται στα νερά του Κόλπου του Μεξικού.\"\n  STR_RISE_4: \"400 δισεκατομμύρια τόνοι εξωγήινου μετάλλου, η ισχυρή εξωγήινη πόλη όπου κρύβεται το κοιμώμενο σώμα του Τελικού Εξωγήινου. Κρατούμενος στη Γη για 65 εκατομμύρια χρόνια, αυτός ο αποτρόπαιος διαστρεβλωτικός Θεός αρχίζει να κινείται.\"\n  STR_RISE_5: \"Τα νερά βράζουν και αναστρέφονται καθώς ο τάφος του Μεγάλου Ονειροπόλου εμφανίζεται στο φως...........\"\n  STR_RISE_6: \".........ένα φως που θα είναι σύντομο, εκτός και αν το X-Com καταστρέψει την πολεμική μηχανή των εξωγήινων.\"\n  STR_YOU_HAVE_FAILED: \"Δεν καταφέρατε να σταματήσετε την πολεμική μηχανή των εξωγήινων. Οι οργανισμοί χρηματοδότησης, απογοητευμένοι από την ικανότητά σας προσπαθούν να διαπραγματευτούν μια μη στρατιωτική λύση με τους Εξωγήινους. Οι εισβολείς έχουν μια πολύ διαφορετική ατζέντα και σύντομα όλος ο κόσμος αντιλαμβάνεται την αλήθεια...\"\n  STR_TOTAL_UC: \"ΣΥΝΟΛΟ\"\n  STR_INCOME: \"Έσοδα\"\n  STR_EXPENDITURE: \"Έξοδα\"\n  STR_MAINTENANCE: \"Συντήρηση\"\n  STR_BALANCE: \"Ταμείο\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"Δραστηριότητα εξωγήινων σε θάλασσες\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"Δραστηριότητα εξωγήινων σε Ζώνες\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"Δραστηριότητα X-Com σε θάλασσες\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"Δραστηριότητα X-Com σε Ζώνες\"\n  STR_FINANCE: \"Οικονομικά\"\n  STR_DATE_FIRST: \"{0}η\"\n  STR_DATE_SECOND: \"{0}η\"\n  STR_DATE_THIRD: \"{0}η\"\n  STR_DATE_FOURTH: \"{0}η\"\n  STR_FINANCE_THOUSANDS: \"$1000's\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Ανεπαρκή υλικά για την παραγωγή {NEWLINE}{0}{NEWLINE}στη{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Ανεπαρκή λεφτά για την παραγωγή {NEWLINE}{0}{NEWLINE}στη{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"Η παραγωγή{NEWLINE}{0}{NEWLINE}στη{NEWLINE}{1}{NEWLINE}τελείωσε\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"Η κατασκευή {NEWLINE}{0}{NEWLINE} στη {NEWLINE}{1}{NEWLINE} τελείωσε\"\n  STR_OK_5_SECONDS: \"ΟΚ - 5 δεύτερα\"\n  STR_RESEARCH_COMPLETED: \"Έρευνα Ολοκληρώθηκε\"\n  STR_VIEW_REPORTS: \"ΔΕΙΞΕ ΑΝΑΦΟΡΕΣ\"\n  STR_WE_CAN_NOW_RESEARCH: \"Πλέον μπορούμε να ερευνήσουμε\"\n  STR_WE_CAN_NOW_PRODUCE: \"Πλέον μπορούμε να παράγουμε\"\n  STR_SUNDAY: \"ΚΥΡΙΑΚΗ\"\n  STR_MONDAY: \"ΔΕΥΤΕΡΑ\"\n  STR_TUESDAY: \"ΤΡΙΤΗ\"\n  STR_WEDNESDAY: \"ΤΕΤΑΡΤΗ\"\n  STR_THURSDAY: \"ΠΕΜΠΤΗ\"\n  STR_FRIDAY: \"ΠΑΡΑΣΚΕΥΗ\"\n  STR_SATURDAY: \"ΣΑΒΒΑΤΟ\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Ανεπαρκή {0} για ανεφοδιασμό {1} στη {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Ανεπαρκή {0} για να ξαναοπλιστεί {1} στη {2}\"\n  STR_UFO_IS_NOT_RECOVERED: \"ΕΞΩΓΗΙΝΟ ΥΠΟΒΡΥΧΙΟ δεν ανακτήθηκε\"\n  STR_UFO_IS_RECOVERED: \"ΕΞΩΓΗΙΝΟ ΥΠΟΒΡΥΧΙΟ ανακτήθηκε\"\n  STR_CRAFT_IS_LOST: \"Το Υπτάμενο Υποβρύχιο έχει χαθεί\"\n  STR_TERROR_CONTINUES: \"Η δραστηριότητα των εξωγήινων συνεχίζεται\"\n  STR_ALIENS_DEFEATED: \"Οι Εξωγήινοι Νικήθηκαν\"\n  STR_BASE_IS_LOST: \"Η βάση χάθηκε\"\n  STR_BASE_IS_SAVED: \"Η βάση σώθηκε\"\n  STR_ALIEN_BASE_STILL_INTACT: \"Η αποικία εξωγήινων είναι ακόμα άθικτη\"\n  STR_ALIEN_BASE_DESTROYED: \"Η αποικία εξωγήινων καταστράφηκε\"\n  STR_ALIENS_KILLED: \"ΕΞΩΓΗΙΝΟΙ ΠΟΥ ΣΚΟΤΩΘΗΚΑΝ\"\n  STR_ALIEN_CORPSES_RECOVERED: \"ΕΞΩΓΗΙΝΑ ΠΤΩΜΑΤΑ ΑΝΑΣΥΡΘΗΚΑΝ\"\n  STR_LIVE_ALIENS_RECOVERED: \"ΖΩΝΤΑΝΟΙ ΕΞΩΓΗΙΝΟΙ ΑΝΑΣΥΡΘΗΚΑΝ\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"ΑΝΕΚΤΗΜΕΝΑ ΕΞΩΓΗΙΝΑ ΕΥΡΗΜΑΤΑ\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"Ο ΕΛΕΓΧΟΣ ΤΗΣ ΕΞΩΓΗΙΝΗΣ ΑΠΟΙΚΙΑΣ ΚΑΤΑΣΤΡΑΦΗΚΕ\"\n  STR_ALIEN_SYNOMIUM_DEVICE_DESTROYED: \"ΚΑΤΑΣΤΡΑΦΗΚΕ Η ΣΥΣΚΕΥΗ ΣΥΝΟΜΙΟΥ ΕΞΩΓΗΙΝΩΝ\"\n  STR_ALIEN_SYNOMIUM_DEVICE_FAILED: \"ΑΠΟΤΥΧΑΤΕ ΝΑ ΚΑΤΑΣΤΡΕΨΕΤΕ ΤΗΝ ΣΥΣΚΕΥΗ ΣΥΝΟΜΙΟΥ\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"ΠΟΛΙΤΕΣ ΠΟΥ ΣΚΟΤΩΘΗΚΑΝ ΑΠΟ ΕΞΩΓΗΙΝΟΥΣ\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"ΠΟΛΙΤΕΣ ΠΟΥ ΣΚΟΤΩΘΗΚΑΝ ΑΠΟ ΠΡΑΚΤΟΡΕΣ X-COM\"\n  STR_CIVILIANS_SAVED: \"ΠΟΛΙΤΕΣ ΠΟΥ ΣΩΘΗΚΑΝ\"\n  STR_XCOM_OPERATIVES_KILLED: \"ΠΡΑΚΤΟΡΕΣ X-COM ΣΚΟΤΩΘΗΚΑΝ\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"X-COM ΠΡΑΚΤΟΡΕΣ ΠΟΥ ΑΓΝΟΟΥΝΤΑΙ\"\n  STR_TANKS_DESTROYED: \"Η ΠΛΑΤΦΟΡΜΑ ΟΠΛΩΝ X-COM ΚΑΤΑΣΤΡΕΦΗΚΕ\"\n  STR_XCOM_CRAFT_LOST: \"ΤΟ ΥΠΟΒΡΥΧΙΟ X-COM ΧΑΘΗΚΕ\"\n  STR_UFO_RECOVERY: \"ΕΠΑΝΑΚΤΗΣΗ ΕΞΩΓΗΙΝΟΥ ΥΠΟΒΡΥΧΙΟΥ\"\n  STR_ALIEN_BASE_RECOVERY: \"ΕΠΑΝΑΚΤΗΣΗ ΕΞΩΓΗΙΝΗΣ ΑΠΟΙΚΙΑΣ\"\n  STR_BASE_UNDER_ATTACK: \"{0} δέχεται επίθεση!\"\n  STR_BASE_DEFENSES_INITIATED: \"ΑΜΥΝΕΣ ΒΑΣΗΣ ΕΝΕΡΓΟΠΟΙΗΘΗΚΑΝ\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"ΑΣΠΙΔΕΣ ΑΠΩΘΕΣΑΝ ΕΠΙΘΕΣΗ ΕΞΩΓΗΙΝΟΥ ΥΠΟΒΡΥΧΙΟΥ!\"\n  STR_FIRING: \"ΠΥΡΟΒΟΛΕΙ\"\n  STR_HIT: \"ΧΤΥΠΗΜΑ!\"\n  STR_UFO_DESTROYED: \"ΤΟ ΕΞΩΓΗΙΝΟ ΥΠΟΒΡΥΧΙΟ ΕΧΕΙ ΚΑΤΑΣΤΡΑΦΕΙ!\"\n  STR_MISSED: \"ΑΣΤΟΧΗΣΕ!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Πώληση Αντικειμένων/Απολύσεις\"\n  STR_VALUE_OF_SALES: \"Αξία Πωλήσεων> {ALT}{0}\"\n  STR_FUNDS: \"Κονδύλια> {ALT}{0}\"\n  STR_SELL_SACK: \"Πώληση/Απόλυση\"\n  STR_VALUE: \"Αξία\"\n  STR_CRAFT_: \"ΥΠΤΑΜΕΝΟ ΥΠΟΒΡΥΧΙΟ> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"ΑΝΕΓΕΡΣΗ ΕΞΩΓΗΙΝΟΥ ΥΠΟΒΡΥΧΙΟΥ\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"ΜΕΓΑΛΗ ΠΡΟΣΟΧΗ - Θα υπάρχουν εξωγήινοι στο υποβρύχιο και γύρω από τον τόπο. Αυτή η αποστολή θα ολοκληρωθεί όταν έχουν εξουδετερωθεί ή εξαλειφθεί όλες οι εχθρικές μονάδες. Η ανάκτηση υπολειμμάτων υποβρυχίου εξωγήινων, τεχνολογίας και σορών εξωγήινων μπορεί να ξεκινήσει στη συνέχεια . Για να ακυρώσετε την αποστολή, επιστρέψτε τους υδροναύτες του X-Com στο υποβρύχιο και κάντε κλικ στο εικονίδιο \\\"Ακύρωση Αποστολής\\\".\"\n  STR_UFO_GROUND_ASSAULT: \"ΕΠΙΘΕΣΗ ΕΞΩΓΗΙΝΟΥ ΥΠΟΒΡΥΧΙΟΥ\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"Εξερευνήστε τον τόπο προσγείωσης και, εάν είναι δυνατόν, αποκτήστε είσοδο στο Εξωγήινο Υποβρύχιο. Η αποστολή θα είναι επιτυχής όταν όλες οι εχθρικές μονάδες έχουν εξαλειφθεί ή εξουδετερωθεί. Στη συνέχεια, μπορεί να ξεκινήσει η ανάκτηση του Εξωγήινου Υποβρυχίου, αντικειμένων και πτωμάτων των εξωγήινων. Για να ματαιώσετε την αποστολή, επιστρέψτε τους υδροναύτες X-Com στο υποβρύχιο και κάντε κλικ στο εικονίδιο 'Ακύρωση αποστολής'.\"\n  STR_BASE_DEFENSE: \"ΑΜΥΝΑ ΒΑΣΗΣ\"\n  STR_BASE_UC_: \"ΒΑΣΗ> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"Ένα εξωγήινο σκάφος έχει προσγειωθεί κοντά. Η βάση μας βρίσκεται σε σοβαρό κίνδυνο. Σύμφωνα με την τυπική διαδικασία, όλο το μη στρατιωτικό προσωπικό και τα υποβρύχια σκάφη της X-Com έχουν εκκενωθεί. Οι εξωγήινες μονάδες εισέρχονται στη βάση μέσω των θυρών του υπόστεγου υποβρυχίων ή του αεροθαλάμου πρόσβασης. Υπερασπίστε τη βάση και τις ζωτικές εγκαταστάσεις της με κάθε κόστος - αυτή είναι μία μάχη μέχρι θανάτου. Εάν κάνετε κλικ στο εικονίδιο 'ακύρωση αποστολής'  θα παραδεχθείτε την ήττα και θα χάσετε τη βάση.\"\n  STR_ALIEN_COLONY_ATTACK_MISSION: \"ΑΠΟΣΤΟΛΗ ΕΠΙΘΕΣΗΣ ΚΑΤΑ ΤΩΝ ΕΞΩΓΗΙΝΩΝ ΑΠΟΙΚΙΩΝ\"\n  STR_ALIEN_BASE_ASSAULT: \"ΕΞΩΓΗΙΝΗ ΑΠΟΙΚΙΑ ΜΕΡΟΣ ΠΡΩΤΟ\"\n  STR_ALIEN_COLONY_P1_BRIEFING: \"Αυτή η αποστολή είναι μια επιδρομή σε μια τοποθεσία αποικίας εξωγήινων. Υπάρχουν 2 επίπεδα στον χώρο, μεταφέρετε όλους τους ακουαναύτες στη λαμπυρίζουσα έξοδο στο πρώτο συγκρότημα και κάντε κλικ στο εικονίδιο 'Ακύρωση αποστολής' για να συνεχίσετε. Οποιοσδήποτε εξοπλισμός έχει μείνει πίσω θα παραμείνει στον βυθό της θάλασσας μέχρι να επιλυθεί το 2ο μέρος της αποστολής. Για να εγκαταλείψετε, τοποθετήστε τους υδροναύτες στο Υποβρύχιο και κάντε κλικ στο εικονίδιο «Ματαίωση αποστολής».\"\n  STR_ALIEN_COLONY_P2: \"ΕΞΩΓΗΙΝΗ ΑΠΟΙΚΙΑ ΜΕΡΟΣ ΔΕΥΤΕΡΟ\"\n  STR_ALIEN_COLONY_P2_BRIEFING: \"Έχοντας διαπραγματευτεί το πρώτο επίπεδο και εισέλθει στον πυρήνα της αποικίας. Η αποστολή σας τώρα είναι να καταστρέψετε το κέντρο ελέγχου, τη συσκευή Synomium ή να εξουδετερώσετε όλους τους Εξωγήινους. Για να ματαιώσετε την αποστολή, τοποθετήστε όλους τους υδροναύτες στο σημείο εκκίνησης και κάντε κλικ στο εικονίδιο «Ακύρωση αποστολής». Όλος ο βιώσιμος εξοπλισμός X-Com θα επιστραφεί στη βάση.\"\n  STR_ALIENS_LAUNCH_PORT_TERROR: \"ΕΞΩΓΗΙΝΟΙ ΞΕΚΙΝΟΥΝ{NEWLINE}ΕΠΙΘΕΣΗ ΣΤΟ ΛΙΜΑΝΙ\"\n  STR_PORT_TERROR: \"ΕΞΩΓΗΙΝΟΙ ΞΕΚΙΝΟΥΝ ΕΠΙΘΕΣΗ ΣΤΟ ΛΙΜΑΝΙ\"\n  STR_PORT_TERROR_BRIEFING: \"Οι εξωγήινοι έχουν εξαπολύσει επίθεση εναντίον επιφανειακών τοποθεσιών. Το λιμάνι και ο άμαχος πληθυσμός του έχουν τεθεί σε κίνδυνο. Η ομάδα σας πρέπει να εξαλείψει όλους τους εξωγήινους και να προστατεύσει τους αθώους περαστικούς από αυτήν την εισβολή εξωγήινων. Για να σταματήσετε, τοποθετήστε τους υδροναύτες στο υπτάμενο υποβρύχιο και κάντε κλικ στο εικονίδιο «Ακύρωση αποστολής».\"\n  STR_ALIENS_LAUNCH_ISLAND_TERROR: \"ΕΞΩΓΗΙΝΟΙ ΞΕΚΙΝΟΥΝ{NEWLINE}ΕΠΙΘΕΣΗ ΣΤΟ ΝΗΣΙ\"\n  STR_ISLAND_TERROR: \"ΕΞΩΓΗΙΝΟΙ ΞΕΚΙΝΟΥΝ ΕΠΙΘΕΣΗ ΣΤΟ ΝΗΣΙ\"\n  STR_ISLAND_TERROR_BRIEFING: \"Οι εξωγήινοι έχουν εξαπολύσει επίθεση εναντίον επιφανειακών τοποθεσιών. Το νησί και ο άμαχος πληθυσμός του έχουν τεθεί σε κίνδυνο. Η ομάδα σας πρέπει να εξαλείψει όλους τους εξωγήινους και να προστατεύσει τους αθώους περαστικούς από αυτήν την εισβολή εξωγήινων. Για να σταματήσετε, τοποθετήστε τους υδροναύτες στο υπτάμενο υποβρύχιο και κάντε κλικ στο εικονίδιο «Ακύρωση αποστολής».\"\n  STR_ALIENS_ATTACK_SHIPPING_ROUTE: \"ΕΠΙΘΕΣΗ ΕΞΩΓΗΙΝΩΝ{NEWLINE}ΣΤΗ ΔΙΑΔΡΟΜΗ ΑΠΟΣΤΟΛΩΝ\"\n  STR_CARGO_SHIP_P1: \"ΠΛΟΙΟ ΦΟΡΤΙΟΥ ΜΕΡΟΣ ΠΡΩΤΟ\"\n  STR_CARGO_SHIP_P2: \"ΠΛΟΙΟ ΦΟΡΤΙΟΥ ΜΕΡΟΣ ΔΕΥΤΕΡΟ\"\n  STR_CRUISE_SHIP_P1: \"ΚΡΟΥΑΖΙΕΡΟΠΛΟΙΟ ΜΕΡΟΣ ΠΡΩΤΟ\"\n  STR_CRUISE_SHIP_P2: \"ΚΡΟΥΑΖΙΕΡΟΠΛΟΙΟ ΜΕΡΟΣ ΔΕΥΤΕΡΟ\"\n  STR_SHIP_RESCUE_MISSION: \"ΑΠΟΣΤΟΛΗ ΔΙΑΣΩΣΗΣ ΠΛΟΙΟΥ\"\n  STR_SHIP_RESCUE_P1_BRIEFING: \"Αυτή η αποστολή είναι ένα κυνήγι εντόμων, εξουδετερώστε όλες τις εξωγήινες μονάδες στο πλοίο και διαφυλάξτε τις ζωές οποιωνδήποτε πολιτών βρίσκονται επι του πλοίου. Οι εξωγήινοι είναι διασπαρμένοι στα πάνω και κάτω κατάστρωματα. Ασφαλίστε τα ανώτερα κατάστρωματα πριν μπείτε στα κατώτερα. Για να αποχωρήσετε, τοποθετήστε τους υδροναύτες στο υποβρύχιο και κάντε κλικ στο εικονίδιο \\\"Ακύρωση Αποστολής\\\".\"\n  STR_SHIP_RESCUE_P2_BRIEFING: \"Τώρα που το επάνω κατάστρωμα είναι ελεύθερο, προχώρησε στα κατώτερα κατάστρωματα. Χρησιμοποιώντας το ανελκυστήρα φορτίων κατεβαίνεις στην αποθήκη. Η ομάδα σου πρέπει να εξουδετερώσει όλους τους εξωγήινους σε αυτό το επίπεδο για να ολοκληρώσει την αποστολή. Για να ακυρώσεις την αποστολή, τοποθέτησε όλους τους υδροναύτες στο σημείο εκκίνησης του ανελκυστήρα και κάνε κλικ στο εικονίδιο \\\"Ακύρωση αποστολής\\\".\"\n  STR_ALIEN_ACTIVITY_DETECTED: \"ΑΝΙΧΝΕΥΤΗΚΕ ΔΡΑΣΤΗΡΙΟΤΗΤΑ ΕΞΩΓΗΙΝΩΝ\"\n  STR_ALIEN_CONTACT_SITE_MISSION: \"ΑΠΟΣΤΟΛΗ ΣΕ ΤΟΠΟ ΕΞΩΓΗΙΝΗΣ ΕΠΑΦΗΣ\"\n  STR_ARTIFACT_SITE_P1: \"ΤΟΠΟΣ ΕΞΩΓΗΙΝΗΣ ΕΠΑΦΗΣ ΜΕΡΟΣ ΠΡΩΤΟ\"\n  STR_ARTIFACT_SITE_P1_BRIEFING: \"Αυτή η αποστολή είναι μια επιδρομή σε έναν πρόσφατα ενεργοποιημένο ιστότοπο επικοινωνίας των εξωγήινων. Υπάρχουν 2 επίπεδα στην τοποθεσία, ο βυθός με τις πυραμίδες εξωγήινων και ένα κρυμμένο συγκρότημα εξωγήινων. Μεταφέρετε όλους τους υδροναύτες στην είσοδο του συγκροτήματος και κάντε κλικ στο εικονίδιο 'Ακύρωση αποστολής' για να συνεχίσετε. Για να τα παρατήσετε, τοποθετήστε τους aquanauts στο flying sub και κάντε κλικ στο εικονίδιο 'Ακύρωση αποστολής'.\"\n  STR_ARTIFACT_SITE_P2: \"ΤΟΠΟΣ ΕΞΩΓΗΙΝΗΣ ΕΠΑΦΗΣ ΜΕΡΟΣ ΔΕΥΤΕΡΟ\"\n  STR_ARTIFACT_SITE_P2_BRIEFING: \"Έχοντας διαπραγματευτεί τις εξωγήινες δομές και εισέλθει στο χώρο, οι στόχοι της αποστολής είναι σαφείς. Διεισδύστε στην καρδιά της εξωγήινης εγκατάστασης και καταστρέψτε την Συνομιακή Μοριακή Συσκευή Ελέγχου για να ολοκληρώσετε την αποστολή. Για να ακυρώσετε, τοποθετήστε όλους τους υδροναύτες στο σημείο εκκίνησης του ανελκυστήρα πρόσβασης και κάντε κλικ στο εικονίδιο 'Ακύρωση Αποστολής'.\"\n  STR_SIGSBEE_DEEP_MISSION: \"ΑΠΟΣΤΟΛΗ SIGSBEE DEEP{NEWLINE}ΕΞΩΓΗΙΝΗ ΠΟΛΗ ΕΠΙΠΕΔΟ ΕΝΑ\"\n  STR_TLETH_P1_BRIEFING: \"Μπαίνουμε στο άγνωστο, από εδώ και πέρα μπορεί να μας περιμένει οτιδήποτε. Γνωρίζουμε ότι υπάρχουν 2 ακόμη επίπεδα στην πόλη των εξωγήινων και η ομάδα σας πρέπει να αγωνιστεί μέχρι την έξοδο σε αυτό το επίπεδο για να μπει στο επόμενο. Τοποθετήστε όλους τους υδροναύτες στην έξοδο και κάντε κλικ στο εικονίδιο 'Ακύρωση αποστολής' για να προχωρήσετε. Η ματαίωση αλλού θα τερματίσει την αποστολή.\"\n  STR_TLETH_ATTACK_MISSION: \"ΑΠΟΣΤΟΛΗ ΕΠΙΘΕΣΗΣ T'LETH{NEWLINE}ΕΞΩΓΗΙΝΗ ΠΟΛΗ ΕΠΙΠΕΔΟ ΔΕΥΤΕΡΟ\"\n  STR_TLETH_P2_BRIEFING: \"Πιο πέρα στο άγνωστο, από εδώ και πέρα θα μπορούσε να μας περιμένει οτιδήποτε. Γνωρίζουμε ότι υπάρχει ένα ακόμη επίπεδο στην πόλη των εξωγήινων και η ομάδα σας πρέπει να αγωνιστεί μέχρι την έξοδο σε αυτό το επίπεδο για να μπει στο επόμενο. Τοποθετήστε όλους τους υδροναύτες στην έξοδο και κάντε κλικ στο εικονίδιο 'Ακύρωση αποστολής' για να προχωρήσετε. Η ματαίωση αλλού θα τερματίσει την αποστολή.\"\n  STR_FINAL_TLETH_MISSION: \"ΤΕΛΙΚΗ ΑΠΟΣΤΟΛΗ T'LETH{NEWLINE}ΕΞΩΓΗΙΝΗ ΠΟΛΗ ΕΠΙΠΕΔΟ ΤΡΙΑ\"\n  STR_TLETH_P3_BRIEFING: \"Το τέλος είναι κοντά, από εδώ και πέρα αναζητούμε την κρύπτη του Απόλυτου Εξωγήινου. Καταστρέψτε τις 8 τροφοδοσίες ισχύος στον τάφο για να τερματίσετε την απειλή του Εξωγήινου. Μην εγκαταλείπετε τώρα! Η ματαίωση θα τερματίσει την αποστολή.\"\n  STR_TLETH_P1: \"ΕΞΩΓΗΙΝΗ ΠΟΛΗ ΕΠΙΠΕΔΟ ΕΝΑ\"\n  STR_TLETH_P2: \"ΕΞΩΓΗΙΝΗ ΠΟΛΗ ΕΠΙΠΕΔΟ ΔΥΟ\"\n  STR_TLETH_P3: \"ΕΞΩΓΗΙΝΗ ΠΟΛΗ ΕΠΙΠΕΔΟ ΤΡΙΑ\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"ΔΕΝ ΥΠΑΡΧΕΙ ΕΛΕΥΘΕΡΟΣ ΣΤΑΘΜΟΣ ΓΙΑ ΠΑΡΑΓΩΓΗ ΥΠΟΒΡΥΧΙΟΥ!{SMALLLINE}Κάθε ιπτάμενο υποβρύχιο που ανατίθεται σε μια βάση, μεταφέρεται σε μια βάση, αγοράζεται ή κατασκευάζεται χρησιμοποιεί ένα Υποβρύχιο Σταθμό. Κατασκευάστε έναν νέο Υποβρύχιο Σταθμό ή μεταφέρετε ένα υποβρύχιο σε μια άλλη βάση.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"ΔΕΝ ΥΠΑΡΧΕΙ ΕΛΕΥΘΕΡΟΣ ΣΤΑΘΜΟΣ ΓΙΑ ΑΓΟΡΑ ΥΠΟΒΡΥΧΙΟΥ!{SMALLLINE}Κάθε ιπτάμενο υποβρύχιο που ανατίθεται σε μια βάση, μεταφέρεται σε μια βάση, αγοράζεται ή κατασκευάζεται χρησιμοποιεί ένα Υποβρύχιο Σταθμό. Κατασκευάστε έναν νέο Υποβρύχιο Σταθμό ή μεταφέρετε ένα υποβρύχιο σε μια άλλη βάση.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"ΔΕΝ ΥΠΑΡΧΕΙ ΕΛΕΥΘΕΡΟΣ ΣΤΑΘΜΟΣ ΓΙΑ ΜΕΤΑΦΟΡΑ ΥΠΟΒΡΥΧΙΟΥ!{SMALLLINE}Κάθε ιπτάμενο υποβρύχιο που ανατίθεται σε μια βάση, μεταφέρεται σε μια βάση, αγοράζεται ή κατασκευάζεται χρησιμοποιεί ένα Υποβρύχιο Σταθμό. Κατασκευάστε έναν νέο Υποβρύχιο Σταθμό ή μεταφέρετε ένα υποβρύχιο σε μια άλλη βάση.\"\n  STR_CANNOT_BUILD_HERE: \"ΔΕΝ ΜΠΟΡΕΙΤΕ ΝΑ ΚΑΤΑΣΚΕΥΑΣΕΤΕ ΕΔΩ!{SMALLLINE}Πρέπει να κατασκευάσετε δίπλα σε μία υπάρχον μονάδα.\"\n  STR_NO_FREE_ACCOMODATION: \"ΑΝΕΠΑΡΚΕΙΣ ΧΩΡΟΣ ΔΙΑΜΟΝΗΣ{SMALLLINE}Η βάση προορισμού δεν έχει αρκετό χώρο στους κοιτώνες για το πλήρωμα που έχει ανατεθεί στο σκάφος.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"ΔΕΝ ΥΠΑΡΧΕΙ ΑΡΚΕΤΟΣ ΧΩΡΟΣ ΕΡΓΑΣΙΑΣ!{SMALLLINE}Χτίσε καινούργια μηχανουργεία ή μείωσε τη δουλεία σε άλλα έργα.\"\n  STR_NOT_ENOUGH_MONEY: \"ΑΝΕΠΑΡΚΗ ΚΕΦΑΛΑΙΑ\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"ΑΝΕΠΑΡΚΕΙΣ ΧΩΡΟΣ ΔΙΑΒΙΩΣΗΣ!{SMALLLINE}Φτιάξτε νέους κοιτώνες ή μεταφερετε προσωπικό σε άλλες βάσεις.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"ΑΝΕΠΑΡΚΕΙΣ ΧΩΡΟΣ ΔΙΑΒΙΩΣΗΣ!{SMALLLINE}Φτιάξε νέους κοιτώνες ή μετέφερε προσωπικό σε άλλες βάσεις.\"\n  STR_LAUNCH_INTERCEPTION: \"ΑΠΟΓΕΙΩΣΗ ΑΝΑΧΑΙΤΙΣΤΙΚΟΥ\"\n  STR_CRAFT: \"ΣΚΑΦΟΣ\"\n  STR_STATUS: \"ΚΑΤΑΣΤΑΣΗ\"\n  STR_BASE: \"ΒΑΣΗ\"\n  STR_READY: \"ETOIMO\"\n  STR_OUT: \"ΕΞΩ\"\n  STR_REPAIRS: \"ΕΠΙΣΚΕΥΕΣ\"\n  STR_REFUELLING: \"ΑΝΕΦΟΔΙΑΣΜΟΣ\"\n  STR_REARMING: \"ΑΝΑΤΡΟΦΟΔΟΤΗΣΗ\"\n  STR_TARGET: \"ΣΤΟΧΟΣ: {0}\"\n  STR_WAY_POINT: \"ΣΗΜΕΙΟ\"\n  STR_ARE_YOU_SURE_CYDONIA: \"Είστε βέβαιοι ότι θέλετε να στείλετε αυτό το υποβρύχειο σε αποστολή στο T'leth;\"\n  STR_YES: \"ΝΑΙ\"\n  STR_NO: \"ΟΧΙ\"\n  STR_SELECT_DESTINATION: \"ΕΠΕΛΕΞΕ ΠΡΟΟΡΙΣΜΟ\"\n  STR_CYDONIA: \"T'LETH\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"ΕΠΙΛΟΓΗ ΠΕΡΙΟΧΗΣ ΓΙΑ ΝΕΑ ΒΑΣΗ\"\n  STR_RETURN_TO_BASE: \"ΕΠΙΣΤΡΟΦΗ ΣΤΗ ΒΑΣΗ\"\n  STR_SELECT_NEW_TARGET: \"ΕΠΙΛΟΓΗ ΝΕΟΥ ΣΤΟΧΟΥ\"\n  STR_PATROL: \"ΠΕΡΙΠΟΛΙΑ\"\n  STR_STATUS_: \"ΚΑΤΑΣΤΑΣΗ>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"ΧΤΥΠΗΜΕΝΟ - ΕΠΙΣΤΡΟΦΗ ΣΤΗ ΒΑΣΗ\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"ΧΑΜΗΛΑ ΚΑΥΣΙΜΑ - ΕΠΙΣΤΡΕΦΕΙ ΣΤΗ ΒΑΣΗ\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"Η ΑΠΟΣΤΟΛΗ ΕΚΠΛΗΡΩΘΗΚΕ - ΕΠΙΣΤΡΟΦΗ ΣΤΗ ΒΑΣΗ\"\n  STR_PATROLLING: \"ΠΕΡΙΠΟΛΕΙ\"\n  STR_TAILING_UFO: \"ΚΑΤΑΔΙΩΚΟΝΤΑΣ ΕΞΩΓΗΙΝΟ ΥΠΟΒΡΥΧΙΟ\"\n  STR_INTERCEPTING_UFO: \"ΠΑΡΑΚΟΛΟΥΘΩΝΤΑΣ ΕΞΩΓΗΙΝΟ ΥΠΟΒΡΥΧΙΟ-{0}\"\n  STR_RETURNING_TO_BASE: \"ΕΠΙΣΤΡΟΦΗ ΣΤΗ ΒΑΣΗ\"\n  STR_DESTINATION_UC_: \"ΠΡΟΟΡΙΣΜΟΣ: {0}\"\n  STR_BASE_UC: \"ΒΑΣΗ>{ALT}{0}\"\n  STR_SPEED_: \"ΤΑΧΥΤΗΤΑ>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"ΜΕΓΙΣΤΗ ΤΑΧΥΤΗΤΑ>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"ΒΑΘΟΣ>{ALT}{0}\"\n  STR_AIRBORNE: \"ΥΠΤΑΜΕΝΟΣ\"\n  STR_VERY_LOW: \"ΡΗΧΟΣ\"\n  STR_LOW_UC: \"ΚΑΝΟΝΙΚΟ\"\n  STR_HIGH_UC: \"ΒΑΘΥ\"\n  STR_VERY_HIGH: \"ΠΟΛΥ ΒΑΘΥ\"\n  STR_FUEL: \"ΚΑΥΣΙΜΑ>{ALT}{0}\"\n  STR_WEAPON_ONE: \"ΟΠΛΟ-1>{ALT}{0}\"\n  STR_NONE_UC: \"ΚΑΝΕΝΑ\"\n  STR_ROUNDS_: \"ΒΟΛΕΣ>{ALT}{0}\"\n  STR_WEAPON_TWO: \"ΟΠΛΟ-2>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"ΥΠΤΑΜΕΝΟ ΥΠΟΒΡΥΧΙΟ\"\n  STR_BASE_: \"Βάση>{0} \"\n  STR_NAME_UC: \"ΟΝΟΜΑ\"\n  STR_AMMO_: \"ΠΥΡ/ΧΙΚA>{ALT}{0}\"\n  STR_CREW: \"ΠΛΗΡΩΜΑ\"\n  STR_EQUIPMENT_UC: \"ΕΞΟΠΛΙΣΜΟΣ\"\n  STR_ARMOR: \"ΠΑΝΟΠΛΙΑ\"\n  STR_MAX: \"ΜΕΓΙΣΤΟ>{ALT}{0}\"\n  STR_ROOKIE: \"Ναύτης\"\n  STR_SQUADDIE: \"Ικανός Ναύτης\"\n  STR_SERGEANT: \"Αρχισημαιοφόρος\"\n  STR_CAPTAIN: \"Λοχίας\"\n  STR_COLONEL: \"Διοικητής\"\n  STR_COMMANDER: \"Λοχαγός\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Επέλεξε Ομάδα για {0}\"\n  STR_SORT_BY: \"ΤΑΞΙΝΟΜΗΣΗ ΚΑΤΑ...\"\n  STR_ORIGINAL_ORDER: \"ΑΡΧΙΚΗ ΔΙΑΤΑΓΗ\"\n  STR_MISSIONS2: \"ΑΠΟΣΤΟΛΕΣ\"\n  STR_KILLS2: \"ΘΑΝΑΤΟΙ\"\n  STR_WOUND_RECOVERY2: \"ΑΝΑΡΡΩΣΗ ΑΠΟ ΤΡΑΥΜΑ\"\n  STR_SPACE_AVAILABLE: \"ΔΙΑΘΕΣΙΜΟΣ ΧΩΡΟΣ>{ALT}{0}\"\n  STR_SPACE_USED: \"ΚΑΤΕΙΛΗΜΜΕΝΟΣ>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"ΚΑΤ/ΜΕΝΟΣ ΧΩΡ.\"\n  STR_RANK: \"ΒΑΘΜΙΔΑ\"\n  STR_WOUNDED: \"ΤΡΑΥΜΑΤΙΑΣ\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Εξοπλισμός για {0}\"\n  STR_DEFENSE_VALUE: \"Αμυντική Αξία\"\n  STR_HIT_RATIO: \"Πιθανότητα Προσβολής\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}έτοιμοι να{NEWLINE}προσγειωθούν κοντά σε{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"Άρχισε Αποστολή;\"\n  STR_SELECT_ARMAMENT: \"Επιλογή Οπλισμού\"\n  STR_AMMUNITION_AVAILABLE: \"ΔΙΑΘΕΣΙΜΑ ΠΥΡΟΜΑΧΙΚΑ\"\n  STR_ARMAMENT: \"ΟΠΛΙΣΜΟΣ\"\n  STR_NOT_AVAILABLE: \"Δ/Ι\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"ΕΠΙΛΕΞΤΕ ΠΑΝΟΠΛΙΑ ΓΙΑ{NEWLINE}{ALT}{0}\"\n  STR_TYPE: \"ΤΥΠΟΣ\"\n  STR_PLASTIC_AQUA_ARMOR_UC: \"Πλαστική Υδροπανοπλία.\"\n  STR_ION_ARMOR_UC: \"ΠΑΝΟΠΛΙΑ ΙΟΝΤΩΝ\"\n  STR_MAGNETIC_ION_ARMOR_UC: \"ΜΑΓΝΙΤΙΚΗ ΠΑΝΟΠΛΙΑ ΙΟΝΤΩΝ\"\n  STR_PLASTIC_AQUA_ARMOR_UFOPEDIA: \"Αυτή η πανοπλία χρησιμοποιεί τη νεοανακαλυφθεί εξωγήινο υλικό, Υδρο-πλαστικό, και εξασφαλίζει ότι οι υδροναύτες μας έχουν μια πιθανότητα αντίστασης ενάντια στην εισβολή των εξωγήινων.\"\n  STR_ION_ARMOR_UFOPEDIA: \"Ένα ισχυρό νέο προστατευτικό για τους Υδροναύτες, αυτή η πανοπλία τροφοδοτείται από μια πηγή ενέργειας IONΤΩΝ και ενισχύει σημαντικά την ταχύτητα και τη δύναμη του χρήστη, προσφέροντας την καλύτερη προστασία μέχρι στιγμής για τα στρατεύματα αντίστασης.\"\n  STR_MAGNETIC_ION_ARMOR_UFOPEDIA: \"Μια βελτίωση για την πανοπλία IONΤΩΝ που ενσωματώνει την τεχνολογία του Μαγνητικού Συστήματος για να επιτρέπει πλήρη ελευθερία κίνησης στο υδάτινο περιβάλλον.\"\n  STR_SELECT_ARMOR: \"Επιλογή Πανοπλίας\"\n  STR_NORTH: \"ΒΟΡΡΑΣ\"\n  STR_NORTH_EAST: \"ΒΟΡΕΙΟΑΝΑΤΟΛΙΚΑ\"\n  STR_EAST: \"ΑΝΑΤΟΛΗ\"\n  STR_SOUTH_EAST: \"ΝΟΤΙΟΑΝΑΤΟΛΙΚΑ\"\n  STR_SOUTH: \"ΝΟΤΟΣ\"\n  STR_SOUTH_WEST: \"ΝΟΤΙΟΔΥΤΙΚΑ\"\n  STR_WEST: \"ΔΥΣΗ\"\n  STR_NORTH_WEST: \"ΒΟΡΕΙΟΔΥΤΙΚΑ\"\n  STR_SELECT_ACTION: \"ΕΠΙΛΟΓΗ ΕΝΕΡΓΕΙΑΣ\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"ΣΥΝΕΧΙΣΕ ΑΝΑΧΑΙΤΙΣΤΙΚΗ ΚΑΤΑΔΙΩΞΗ\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"ΚΑΤΑΔΙΩΞΗ ΧΩΡΙΣ ΑΝΑΧΑΙΤΙΣΗ\"\n  STR_VERY_LARGE: \"ΠΟΛΥ ΜΕΓΑΛΟ\"\n  STR_LARGE: \"ΜΕΓΑΛΟ\"\n  STR_MEDIUM_UC: \"ΜΕΣΑΙΟ\"\n  STR_SMALL: \"ΜΙΚΡΟ\"\n  STR_VERY_SMALL: \"ΠΟΛΥ ΜΙΚΡΟ\"\n  STR_GROUNDED: \"ΠΡΟΣΓΕΙΩΘΗΚΕ\"\n  STR_DETECTED: \"Ανιχνεύτηκε\"\n  STR_SIZE_UC: \"ΜΕΓΕΘΟΣ\"\n  STR_ALTITUDE: \"ΒΑΘΟΣ\"\n  STR_HEADING: \"ΠΡΟΟΡΙΣΜΟΣ\"\n  STR_SPEED: \"ΤΑΧΥΤΗΤΑ\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"ΠΡΟΣΕΓΗΣΗ ΕΞΩΓΗΙΝΟΥ ΥΠΟΒΡΥΧΙΟΥ-ΧΡΟΝΟΣ=5 δευ\"\n  STR_TRACKING_LOST: \"ΙΧΝΟΣ ΧΑΘΗΚΕ\"\n  STR_REDIRECT_CRAFT: \"ΝΕΑ ΠΟΡΕΙΑ ΣΚΑΦΟΥΣ\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"ΜΕΤΑΒΑΣΗ ΣΤΗΝ ΤΕΛΕΥΤΑΙΑ ΓΝΩΣΤΗ ΘΕΣΗ ΕΞΩΓΗΙΝΟΥ ΥΠΟΒΡΥΧΙΟΥ\"\n  STR_UFO_: \"ΕΞΩΓΗΙΝΟ ΥΠΟΒΡΥΧΙΟ-{0}\"\n  STR_ALIEN_BASE_: \"ΕΞΩΓΗΙΝΗ ΑΠΟΙΚΙΑ-{0}\"\n  STR_CRASH_SITE_: \"ΣΗΜΕΙΟ ΣΥΝΤΡΙΒΗΣ-{0}\"\n  STR_LANDING_SITE_: \"ΤΟΠΟΘΕΣΙΑ ΠΡΟΣΕΔΑΦΗΣΗΣ-{0}\"\n  STR_WAY_POINT_: \"ΣΗΜΕΙΟ-{0}\"\n  STR_TERROR_SITE: \"ΤΡΟΜΟΚΡΑΤΙΚΟ ΧΤΥΠΗΜΑ-{0}\"\n  STR_ARTIFACT_SITE: \"ΤΟΠΟΘΕΣΙΑ ΕΥΡΗΜΑΤΟΣ-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}έφτασε{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"Τώρα περιπολεί\"\n  STR_ALIEN_ORIGINS: \"Προέλευση Εξωγήινων\"\n  STR_THE_ULTIMATE_THREAT: \"Η Απόλυτη Απειλή\"\n  STR_TLETH_ALIEN_CITY: \"T'leth, η Πόλη των Εξωγήινων\"\n  STR_UFOPAEDIA: \"ΟΥΦΟπαιδεία\"\n  STR_XCOM_CRAFT_ARMAMENT: \"X-COM ΣΚΑΦΟΙ & ΟΠΛΑ\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"ΣΥΣΤΗΜΑΤΑ ΥΠΟΒΡΥΧΙΩΝ ΟΠΛΩΝ\"\n  STR_WEAPONS_AND_EQUIPMENT: \"ΓΕΝΙΚΟΣ ΕΞΟΠΛΙΣΜΟΣ\"\n  STR_ALIEN_ARTIFACTS: \"ΥΔΑΤΙΝΑ ΕΥΡΗΜΑΤΑ\"\n  STR_BASE_FACILITIES: \"X-COM ΕΓΚΑΤΑΣΤΑΣΕΙΣ\"\n  STR_ALIEN_LIFE_FORMS: \"ΕΞΩΓΗΙΝΑ ΟΝΤΑ\"\n  STR_ALIEN_RESEARCH_UC: \"ΕΞΩΓΗΙΝΗ ΤΕΧΝΟΛΟΓΙΑ\"\n  STR_UFO_COMPONENTS: \"ΝΕΕΣ ΥΠΟΒΡΥΧΙΕΣ ΤΕΧΝΟΛΟΓΙΕΣ\"\n  STR_UFOS: \"ΕΞΩΓΗΙΝΑ ΥΠΟΒΡΥΧΙΑ\"\n  STR_SELECT_ITEM: \"ΕΠΕΛΕΞΕ ΑΝΤΙΚΕΙΜΕΝΟ\"\n  STR_ACCELERATION: \"ΕΠΙΤΑΧΥΝΣΗ>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"ΧΩΡΗΤΙΚΟΤΗΤΑ ΚΑΥΣΙΜΩΝ>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"ΘΕΣΕΙΣ ΟΠΛΩΝ>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"ΑΝΟΧΗ ΖΗΜΙΑΣ>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"ΧΩΡΟΣ ΦΟΡΤΙΟΥ>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"ΧΩΡΗΤΙΚΟΤΗΤΑ ΥΟΣ>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Ζημιά\"\n  STR_RANGE: \"Εμβέλεια\"\n  STR_KILOMETERS: \"{0} χλμ\"\n  STR_ACCURACY: \"Ευστοχία\"\n  STR_RE_LOAD_TIME: \"Χρόνος επαναγέμισης Όπλου\"\n  STR_SECONDS: \"{0}δ\"\n  STR_DAMAGE_ARMOR_PIERCING: \"ΔΙΑΤΡΗΤΙΚΟ\"\n  STR_DAMAGE_INCENDIARY: \"ΦΩΣΦΟΡΙΚΟΣ\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"ΕΚΡΗΚΤΙΚΟ\"\n  STR_DAMAGE_LASER_BEAM: \"GAUSS ΔΕΣΜΗ\"\n  STR_DAMAGE_PLASMA_BEAM: \"ΗΧΗΤΙΚΗ ΔΕΣΜΗ\"\n  STR_DAMAGE_STUN: \"ΑΚΙΝΗΤΟΠΟΙΗΣΗ\"\n  STR_DAMAGE_MELEE: \"ΣΥΜΠΛΟΚΗ\"\n  STR_DAMAGE_ACID: \"ΟΞΥ\"\n  STR_DAMAGE_SMOKE: \"ΚΑΠΝΟΣ\"\n  STR_SHOT_TYPE: \"ΤΥΠΟΣ\"\n  STR_ACCURACY_UC: \"ΕΥΣΤΟΧΙΑ\"\n  STR_TIME_UNIT_COST: \"Κόστος ΧΜ\"\n  STR_DAMAGE_UC: \"ΖΗΜΙΑ\"\n  STR_AMMO: \"ΠΥΡ/ΧΙΚΑ\"\n  STR_SHOT_TYPE_AUTO: \"ΚΒ\"\n  STR_SHOT_TYPE_SNAP: \"Γρήγορη\"\n  STR_SHOT_TYPE_AIMED: \"Στοχευμένη\"\n  STR_CONSTRUCTION_TIME: \"Χρόνος Κατασκευής\"\n  STR_CONSTRUCTION_COST: \"Κόστος Κατασκευής\"\n  STR_MAINTENANCE_COST: \"Κόστος Συντήρησης\"\n  STR_LOW: \"Χαμηλό\"\n  STR_MEDIUM: \"Μεσαίο\"\n  STR_HIGH: \"Ψηλά\"\n  STR_CRAFT_WEAPON: \"Υποβρύχιο Όπλο\"\n  STR_CRAFT_AMMUNITION: \"Υποβρύχια Πυτομαχικά\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Σύστημα Βαριών Όπλων\"\n  STR_WEAPON: \"Όπλο\"\n  STR_AMMUNITION: \"Πυρομαχικά\"\n  STR_EQUIPMENT: \"Εξοπλισμός\"\n  STR_ALIEN_CORPSE: \"Εξωγήινο Πτώμα\"\n  STR_UFO_COMPONENT: \"Εξάρτημα ΕΞΩΓΗΙΝΟΥ ΥΠΟΒΡΥΧΙΟΥ\"\n  STR_PERSONAL_ARMOR: \"Προσωπική Θωράκιση\"\n  STR_RAW_MATERIALS: \"Πρώτες Ύλες\"\n  STR_HWP_SOLID_HARPOON_BOLTS: \"Στερεά Βέλη από Καμάκι\"\n  STR_ALIEN: \"Εξωγήινος\"\n  STR_AQUATOID: \"Υδρόβιος\"\n  STR_GILLMAN: \"Άνθρωπος των Γιλλ\"\n  STR_LOBSTERMAN: \"Άνθρωπος Αστακός\"\n  STR_TASOTH: \"Τάσοθ\"\n  STR_CALCINITE: \"Καλσινίτης\"\n  STR_DEEP_ONE: \"Βαθύ Ον\"\n  STR_BIODRONE: \"Βιο-ντρον\"\n  STR_TENTACULAT: \"Τεντακουλάτ\"\n  STR_TRISCENE: \"Τρισκίνης\"\n  STR_HALLUCINOID: \"Υπναγωγικός\"\n  STR_XARQUID: \"Ξαρκίντ\"\n  STR_ZOMBIE: \"Ζόμπι\"\n  STR_LIVE_COMMANDER: \"Διοικητής\"\n  STR_LIVE_NAVIGATOR: \"Πλοηγός\"\n  STR_LIVE_MEDIC: \"Γιατρός\"\n  STR_LIVE_TECHNICIAN: \"Τεχνικός\"\n  STR_LIVE_SQUAD_LEADER: \"Αρχηγός Ομάδας\"\n  STR_LIVE_SOLDIER: \"Στρατιώτης\"\n  STR_LIVE_TERRORIST: \"Τρομοκράτης\"\n  STR_AQUATOID_COMMANDER: \"Υδρόβιος Διοικητής\"\n  STR_AQUATOID_NAVIGATOR: \"Υδρόβιος Πλοηγός\"\n  STR_AQUATOID_MEDIC: \"Υδρόβιος Ιατρός\"\n  STR_AQUATOID_TECHNICIAN: \"Υδρόβιος Τεχνικός\"\n  STR_AQUATOID_SQUAD_LEADER: \"Υδρόβιος Αρχηγός Ομάδας\"\n  STR_AQUATOID_SOLDIER: \"Υδρόβιος Στρατιώτης\"\n  STR_GILLMAN_COMMANDER: \"Άνθρωπος του Γιλλ Διοικητής\"\n  STR_GILLMAN_TECHNICIAN: \"Άνθρωπος του Γιλλ Τεχνικός\"\n  STR_GILLMAN_SQUAD_LEADER: \"Άνθρωπος του Γιλλ Αρχηγός Ομάδας\"\n  STR_GILLMAN_SOLDIER: \"Άνθρωπος του Γιλλ Στρατιώτης\"\n  STR_LOBSTERMAN_COMMANDER: \"Άνθρωπος Αστακός Διοικητής\"\n  STR_LOBSTERMAN_NAVIGATOR: \"Άνθρωπος Αστακός Πλοηγός\"\n  STR_LOBSTERMAN_TECHNICIAN: \"Άνθρωπος Αστακός Τεχνικός\"\n  STR_LOBSTERMAN_SQUAD_LEADER: \"Άνθρωπος Αστακός Αρχηγός Ομάδας\"\n  STR_LOBSTERMAN_SOLDIER: \"Άνθρωπος Αστακός Στρατιώτης\"\n  STR_TASOTH_SQUAD_LEADER: \"Τάσοθ Αρχηγός Ομάδας\"\n  STR_TASOTH_SOLDIER: \"Τάσοθ Στρατιώτης\"\n  STR_CALCINITE_TERRORIST: \"Καλσινίτης Τρομοκράτης\"\n  STR_DEEP_ONE_TERRORIST: \"Βαθύ Ον Τρομοκράτης\"\n  STR_BIODRONE_TERRORIST: \"Βιο-ντρον Τρομοκράτης\"\n  STR_TENTACULAT_TERRORIST: \"Τεντακουλάτ Τρομοκράτης\"\n  STR_TRISCENE_TERRORIST: \"Τρισκίνης Τρομοκράτης\"\n  STR_HALLUCINOID_TERRORIST: \"Υπναγωγικός Τρομοκράτης\"\n  STR_XARQUID_TERRORIST: \"Ξαρκίντ Τρομοκράτης\"\n  STR_ION_BEAM_ACCELERATORS: \"Ιονικοί Επιταχυντές\"\n  STR_MAGNETIC_NAVIGATION: \"Μαγνητική Πλοήγηση\"\n  STR_ALIEN_SUB_CONSTRUCTION: \"Υποθαλάσσια Εξωγήινη Κατασκευή\"\n  STR_ALIEN_CRYOGENICS: \"Εξωγήινη Κρυογονική\"\n  STR_ALIEN_CLONING: \"Εξωγήινη Κλωνοποίηση\"\n  STR_ALIEN_LEARNING_ARRAYS: \"Εξωγήινοι Πίνακες Εκμάθησης\"\n  STR_ALIEN_IMPLANTER: \"Εξωγήινος Εμφυτευτής\"\n  STR_EXAMINATION_ROOM: \"Δωμάτιο Εξέτασης\"\n  STR_AQUA_PLASTICS: \"Ύδροπλαστικό\"\n  STR_ALIEN_REANIMATION_ZONE: \"Ζώνη Επαναφοράς Εξωγήινου\"\n  STR_PLASTIC_AQUA_ARMOR: \"Πλαστική Υδάτινη Πανοπλία\"\n  STR_ION_ARMOR: \"Πανοπλία Ιόντων\"\n  STR_MAGNETIC_ION_ARMOR: \"Μαγ. Πανοπλία Ιόντων\"\n  STR_HWP_AQUA_JET_MISSILES: \"Τορπίλες Υδατοσκάφους\"\n  STR_HWP_DISPLACER_PWT: \"Τορπίλη Π.Κ.\"\n  STR_GAUSS_TECH: \"Gauss Τεχνολογία\"\n  STR_NEW_FIGHTER_FLYING_SUB: \"Νέο Μαχητικό Ιπτάμενο Υποβρύχιο\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Νέο Μαχητικό-Μεταγωγικό\"\n  STR_THE_LATEST_FLYING_SUB: \"Το πιο Πρόσφατο Ιπτάμενο Υποβρύχιο\"\n  STR_ARMOR_PIERCING: \"ΔΙΑΤΡΗΤΙΚΟ\"\n  STR_COELACANTH_GAS_CANNON: \"Κοιλάκανθος/G. Κανόνι\"\n  STR_COELACANTH_AQUA_JET: \"Κοιλάκανθος/Υδρόβιο Τζετ\"\n  STR_COELACANTH_GAUSS: \"Κοιλάκανθος/Gauss\"\n  STR_DISPLACER_SONIC: \"Εκτοπιστής/Ηχητικός\"\n  STR_DISPLACER_PWT: \"Εκτοπιστής/Π.Κ.Τ.\"\n  STR_AJAX_LAUNCHER: \"Εκτοξευτής Αϊάς\"\n  STR_DUP_HEAD_LAUNCHER: \"Εκτοξευτής Κεφάλης Δ.Τ.Ο.\"\n  STR_CRAFT_GAS_CANNON: \"Πυροβόλο Αερίου Χειροτεχνίας\"\n  STR_PWT_CANNON: \"Π.Κ.Τ. Κανόνι\"\n  STR_GAUSS_CANNON: \"Gauss Κανόνι\"\n  STR_GAUSS_CANNON_AMMO: \"Πυρομαχικά Gauss Κανονιού\"\n  STR_SONIC_OSCILLATOR: \"Ηχητικός Ταλαντωτής\"\n  STR_AJAX_TORPEDOES: \"Αϊάς Τορπίλη\"\n  STR_DUP_HEAD_TORPEDOES: \"Δ.Τ.Ο. Κεφαλής Τορπίλη\"\n  STR_CRAFT_GAS_CANNON_ROUNDS_X50: \"Φυσίγγια Αερίου (x50)\"\n  STR_SONIC_WAVE: \"Ηχητικό κύμα\"\n  STR_PULSE_WAVE_TORPEDOES: \"Πυρομαχικά Π.Κ.Τ. \"\n  STR_SOLDIER: \"Υδροναύτης\"\n  STR_SCIENTIST: \"Επιστήμονας\"\n  STR_ENGINEER: \"Τεχνικός\"\n  STR_NORTH_ATLANTIC: \"Βόρειος Ατλαντικός\"\n  STR_SOUTH_ATLANTIC: \"Νότιος Ατλαντικός\"\n  STR_NORTH_PACIFIC: \"Βόρειος Ειρηνικός\"\n  STR_SOUTH_PACIFIC: \"Νότιος Ειρηνικός\"\n  STR_MEDITERRANEAN: \"Μεσόγειος\"\n  STR_SOUTH_CHINA_SEA: \"Νότια Θάλασσα της Κίνας\"\n  STR_INDIAN_OCEAN: \"Ινδικός Ωκεανός\"\n  STR_THE_EAST_SEA: \"Θάλασσα της Ιαπωνίας\"\n  STR_NORTH_SEA: \"Βόρεια Θάλασσα\"\n  STR_CARRIBEAN: \"Καραϊβική\"\n  STR_ANTARCTIC: \"Ανταρκτική\"\n  STR_ARCTIC: \"Αρκτική\"\n  STR_EURASIA: \"Ευρασία\"\n  STR_NORTH_AMERICA: \"Βόρεια Αμερική\"\n  STR_AFRICA: \"Αφρική\"\n  STR_MAXIMUM_SPEED: \"Μέγιστη Ταχύτητα\"\n  STR_TRANSMISSION_RESOLVER_UC: \"ΕΠΙΛΥΤΗΣ ΔΙΑΒΙΒΑΣΗΣ\"\n  STR_TRITON: \"ΤΡΙΤΩΝ\"\n  STR_HAMMERHEAD: \"ΣΦΥΡΟΚΕΦΑΛΟΣ\"\n  STR_LEVIATHAN: \"Λεβιάθαν\"\n  STR_BARRACUDA: \"ΣΦΥΡΑΙΝΑ\"\n  STR_MANTA: \"ΣΑΛΑΧΙ\"\n  STR_UFO: \"ΕΞΩΓΗΙΝΟ ΥΠΟΒΡΥΧΙΟ\"\n  STR_AJAX: \"ΑΙΑΣ\"\n  STR_DUP_HEAD: \"Δ.Τ.Ο. ΚΕΦΑΛΗ\"\n  STR_CRAFT_GAS_CANNON_UC: \"ΠΥΡΟΒΟΛΟ ΑΕΡΙΟΥ ΧΕΙΡΟΤΕΧΝΙΑΣ\"\n  STR_PWT_CANNON_UC: \"Π.Κ.Τ. ΚΑΝΟΝΙ\"\n  STR_GAUSS_CANNON_UC: \"GAUSS ΚΑΝΟΝΙ\"\n  STR_SONIC_OSCILLATOR_UC: \"ΗΧΗΤΙΚΟΣ ΤΑΛΑΝΤΩΤΗΣ\"\n  STR_DAMAGE_CAPACITY: \"Ανοχή Ζημίας\"\n  STR_WEAPON_POWER: \"Δύναμη Όπλου\"\n  STR_WEAPON_RANGE: \"Εμβέλεια Όπλου\"\n  STR_AIR_LOCK: \"Αεροθάλαμος\"\n  STR_LABORATORY: \"Εργαστήριο\"\n  STR_WORKSHOP: \"Μηχανουργείο\"\n  STR_STANDARD_SONAR: \"Πρότυπο Υποβρύχειο Ραντάρ\"\n  STR_WIDE_ARRAY_SONAR: \"Σόναρ Ευρείας Διάταξης\"\n  STR_TORPEDO_DEFENSES: \"Αντιτορπιλική Αμυντικά Συστήματα\"\n  STR_GENERAL_STORES: \"Γενικές Αποθήκες\"\n  STR_ALIEN_CONTAINMENT: \"Μονάδα Περιορισμού Εξωγήινων\"\n  STR_GAUSS_DEFENSES: \"Αμυντικά Συστήματα Gauss\"\n  STR_SONIC_DEFENSES: \"Ηχητικά Αμυντικά Συστήματα\"\n  STR_PWT_DEFENSES: \"Π.Κ.Τ. Αμυντικά Συστήματα\"\n  STR_BOMBARDMENT_SHIELD: \"Ασπίδα Βομβαρδισμού\"\n  STR_MC_GENERATOR: \"Γεννήτρια Μ.Ε.\"\n  STR_MC_LAB: \"Εργαστήριο Μ.Ε.\"\n  STR_TRANSMISSION_RESOLVER: \"Επιλυτής Διαβίβασης\"\n  STR_SUB_PEN: \"Υποβρύχια Αποθήκη\"\n  STR_USA: \"ΗΠΑ\"\n  STR_ALASKA: \"ΑΛΑΣΚΑ\"\n  STR_EU_SYNDICATE: \"ΕΥΡΩ-ΣΥΝΔΙΚΑΤΟ\"\n  STR_ARABIAN_BLOC: \"ΑΡΑΒΙΚΟ ΜΠΛΟΚ\"\n  STR_EGYPTIAN_CARTEL: \"ΑΙΓΥΠΤΙΚΟ ΚΑΡΤΕΛ\"\n  STR_AFRICA_CORP: \"ΑΦΡΙΚΑΝΙΚΗ ΣΤΡΑΤΙΩΤΙΚΗ ΔΙΟΙΚΗΣΗ\"\n  STR_BRAZILIAN_UNION: \"ΒΡΑΖΙΛΙΑΝΙΚΗ ΕΝΩΣΗ\"\n  STR_NEW_MEXICO: \"ΝΕΟ ΜΕΞΙΚΟ\"\n  STR_ASIAN_COALITION: \"ΑΣΙΑΤΙΚΟΣ ΣΥΝΑΣΠΙΣΜΟΣ\"\n  STR_SCANDINAVIA: \"ΣΚΑΝΔΙΝΑΒΙΑ\"\n  STR_NEO_JAPAN: \"ΝΕΑ-ΙΑΠΩΝΙΑ\"\n  STR_FREE_CHINA: \"ΕΛΕΥΘΕΡΗ ΚΙΝΑ\"\n  STR_AUSTRALASIA: \"ΑΥΣΤΡΑΛΑΣΙΑ\"\n  STR_FED_KOREA: \"ΟΜΟΣΠΟΝΔΙΑ ΚΟΡΕΑΣ\"\n  STR_EURASIA_UC: \"ΕΥΡΑΣΙΑ\"\n  STR_ICELANDIC_UNION: \"ΙΣΛΑΝΔΙΚΗ ΕΝΩΣΗ\"\n  STR_TANK: \"Υποβρύχιο Οπλικό Σύστημα\"\n  STR_CIVILIAN: \"Πολίτης\"\n  STR_JAN: \"Ιαν\"\n  STR_FEB: \"Φεβ\"\n  STR_MAR: \"Μαρ\"\n  STR_APR: \"Απρ\"\n  STR_MAY: \"Μαΐος\"\n  STR_JUN: \"Ιουν\"\n  STR_JUL: \"Ιουλ\"\n  STR_AUG: \"Αυγ\"\n  STR_SEP: \"Σεπτ\"\n  STR_OCT: \"Οκτ\"\n  STR_NOV: \"Νοεμ\"\n  STR_DEC: \"Δεκ\"\n  STR_INTERNATIONAL_RELATIONS: \"Διεθνείς Σχέσεις\"\n  STR_COUNTRY: \"Χώρα\"\n  STR_FUNDING: \"Χρηματοδότηση\"\n  STR_CHANGE: \"Αλλαγή\"\n  STR_WEAPON_SYSTEMS: \"ΟΠΛΙΚΑ ΣΥΣΤΗΜΑΤΑ\"\n  STR_HWPS: \"ΥΟΣα\"\n  STR_DAMAGE_UC_: \"ΖΗΜΙΑ>{ALT}{0}\"\n  STR_AIR_LOCK_UFOPEDIA: \"Ο αεροθάλαμος επιτρέπει τη μεταφορά εξοπλισμού και προσωπικού μέσα ή έξω από μια υποθαλάσσια βάση. Είναι πάντα η πρώτη εγκατάσταση που κατασκευάζεται σε μια νέα τοποθεσία. Η περιοχή αεροθαλάμου είναι ευάλωτη σε εισβολή από οποιαδήποτε πιθανή εχθρική δύναμη.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Κάθε χώρος διαμονής μπορεί να φιλοξενήσει έως και 50 άτομα. Οι εγκαταστάσεις είναι κάπως βασικές και λειτουργικές.\"\n  STR_LABORATORY_UFOPEDIA: \"Πενήντα επιστήμονες μπορούν να εργαστούν σε ένα μόνο εργαστηριακό μπλοκ. Τα εργαστήρια είναι εξοπλισμένα με όλες τις πιο πρόσφατες τεχνολογίες για την έρευνα, όπως σε υλικά, τόσο σε βιοχημεία και όπλα. Η X-Com έχει πρόσβαση σε καλύτερα ερευνητικά εργαστήρια σε όλο τον κόσμο, τόσο πολιτικά όσο και στρατιωτικά.\"\n  STR_WORKSHOP_UFOPEDIA: \"Ένα εργαστήριο περιέχει όλο τον απαραίτητο εξοπλισμό για την κατασκευή του, με βάση τα πιο πρόσφατα σχέδια από τα επιστημονικά εργαστήρια. 50 τεχνικοί μπορούν να απασχοληθούν σε ένα συνεργείο, τα αντικείμενα υπό κατασκευή θα καταναλώσουν επίσης χώρο.\"\n  STR_STANDARD_SONAR_UFOPEDIA: \"Ένα πρότυπο υποβρύχειο σύστημα ραντάρ έχει αποτελεσματική εμβέλεια άνω των 450 χιλιομέτρων στα περισσότερα βάθη και είναι συνδεδεμένο με γεωστατικά δορυφορικά δίκτυα για ανάλυση επιφάνειας. Κάθε σαρωτής έχει 10% πιθανότητα να ανιχνεύσει ένα υποβρύχιο ή αερομεταφερόμενο σκάφος ανά 30λεπτο κύκλο σάρωσης.\"\n  STR_WIDE_ARRAY_SONAR_UFOPEDIA: \"Ένα υποβρύχειο σύστημα ραντάρ ευρείας συστοιχίας έχει αποτελεσματική εμβέλεια άνω των 700 χιλιομέτρων σε όλα τα βάθη και είναι συνδεδεμένο με γεωστατικά δορυφορικά δίκτυα για ανάλυση επιφάνειας. Κάθε σαρωτής έχει 20% πιθανότητα ανίχνευσης υποβρύχιου ή αερομεταφερόμενου σκάφους κάθε 30 λεπτά κύκλου σάρωσης.\"\n  STR_TORPEDO_DEFENSES_UFOPEDIA: \"Τα αμυντικά συστήματα τορπίλης παρέχουν προστασία από επίθεση από εχθρικά υποβρύχια που προσπαθούν να προσδέσουν στη βάση.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"Όλος ο εξοπλισμός, τα συστήματα όπλων, τα πυρομαχικά, το ανακτηθέν υλικό και τα Υποβρύχια Συστήματα Όπλων τοποθετούνται στους αποθηκευτικούς χώρους, συμπεριλαμβανομένου του εξοπλισμού που είναι ανατεθειμένος στα Υποβρύχια σε υπόστεγα.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"Οι ζωντανοί εξωγήινοι θα χρειαστούν ειδικές εγκαταστάσεις περιορισμού για να τους κρατήσουν. Αυτές οι μονάδες διατηρούν τα συστήματα ζωής τους και μηδενίζουν τις δυνατότητες μάχης τους. Η εγκατάσταση περιορισμού μπορεί να κρατήσει 10 μορφές ζωής εξωγήινων σε μονάδες περιορισμού.\"\n  STR_GAUSS_DEFENSES_UFOPEDIA: \"Η άμυνα Gauss παρέχει την πιο πρόσφατη και αποτελεσματική προστασία ενάντια στην επίθεση από εχθρικά υποβρύχια.\"\n  STR_SONIC_DEFENSES_UFOPEDIA: \"Οι άμυνες Ηχητικού Ταλαντωτή παρέχουν ισχυρή και αποτελεσματική προστασία έναντι των επιτιθέμενων.\"\n  STR_PWT_DEFENSES_UFOPEDIA: \"Οι τορπίλες Παλμικών Κυμάτων παρέχουν την πιο αποτελεσματική άμυνα έναντι επιθέσεων εξωγήινων. Αυτοί οι πύραυλοι έχουν εξαιρετικά συμπαγές πολεμικές κεφαλές που μπορούν να διαπεράσουν όλες τις γνωστές θωρακήσεις. Τα μαγνητικά κύματα που παράγουν απενεργοποιούν τις ηλεκτρονικές άμυνες.\"\n  STR_BOMBARDMENT_SHIELD_UFOPEDIA: \"Η ασπίδα βομβαρδισμού πίεσης προστατεύει τη βάση από την πρόσδεση εξωγήινων υποβρυχίων και δημιουργεί ένα πεδίο συντονισμού που αποκρούει τα επιτιθέμενα υποβρύχια για αρκετό χρονικό διάστημα ώστε τα αμυντικά συστήματα να πυροβολούν επανειλημμένα. Ουσιαστικά αυτό διπλασιάζει την αποτελεσματικότητα οποιωνδήποτε αμυντικών συστημάτων που έχουν ήδη αναπτυχθεί.\"\n  STR_MC_GENERATOR_UFOPEDIA: \"Δεδομένου ότι τα υποβρύχια εξωγήινων χρησιμοποιούν Τεχνολογία Μοριακού Ελέγχου για να ανιχνεύουν την παρουσία ζωντανών όντων, η χρήση ενός αρνητικού εκπομπέα Μ.Ε. θα καλύψει μία βάση με ένα αδιάβλητο προστατευτικό θόλο για να μπερδέψει τους εξωγήινους και να κρύψει την παρουσία μας.\"\n  STR_MC_LAB_UFOPEDIA: \"Το εργαστήριο Μοριακού Ελέγχου μπορεί να εμφυτεύσει και να εκπαιδεύσει έως και δέκα υδατοναύτες ταυτόχρονα. Οι εμφυτεύσεις τοποθετούνται χειρουργικά στους κροτάφους των υδατοναυτών. Η εκτεταμένη εκπαίδευση τους επιτρέπει να χρησιμοποιούν τις εμφυτεύσεις τους. Οι δεξιότητες των εμφυτεύσεων χρησιμοποιούνται σε συνδυασμό με ένα Μοριακό Μηχάνημα και μπορούν να χρησιμοποιηθούν για επιθέσεις κατά τη διάρκεια μάχης.\"\n  STR_TRANSMISSION_RESOLVER_UFOPEDIA: \"Οι εξωγήινες επικοινωνίες χρησιμοποιούν το δίκτυο ελέγχου μοριακής εμφύτευσης που έχουν δημιουργήσει οι εξωγήινοι. Το κέντρο αποκωδικοποίησης μεταδόσεων ανιχνεύει τις υπομονάδες εξωγήινων και αποκωδικοποιεί τις πληροφορίες. Αυτό θα εμφανίσει τον τύπο της εξωγήινης υποβρύχιας μονάδας, τη φυλή των εξωγήινων και τον τύπο της δραστηριότητας που συμβαίνει.\"\n  STR_SUB_PEN_UFOPEDIA: \"Κάθε υπόστεγο μπορεί να φιλοξενήσει ένα υποβρύχιο. Υπάρχουν εγκαταστάσεις για τη συντήρηση, τον ανεφοδιασμό και την επισκευή του υποβρυχίου στόλου X-Com. Κάθε Ιπτάμενο Υποβρύχιο που βρίσκεται σε μια βάση πρέπει να έχει ένα διαθέσιμο υπόστεγο ανατεθειμένο σε αυτό, το οποίο δεν μπορεί να χρησιμοποιηθεί από άλλα υποβρύχια, ακόμα και αν το ανατεθειμένο υποβρύχιο είναι σε αποστολή.\"\n  STR_DART_PISTOL_UFOPEDIA: \"Το πιστόλι βελών X-Com είναι μια μικρή, ακριβής, υψηλής ισχύος μονάδα με κλιπ πυρομαχικών 12 κοίλων βελών. Τα βελάκια εκτοξεύονται από ένα φυσιγγίου αερίου στο περίβλημα βολής.\"\n  STR_JET_HARPOON_UFOPEDIA: \"Αυτό το υδατοβόλο είναι πολύ ακρυβές και ισχυρό, εκτοξεύει κοίλα ατσάλινα καμάκια απο σφραγυσμένα σε ένα γεμιστήρα των 10. Κάθε καμάκι έχει δική του δεξαμενή αερίου.\"\n  STR_GAS_CANNON_UFOPEDIA: \"Το βαρύτερο μέλος της οικογένειας της τεχνολογίας αερίου, αυτό το κανόνι εκτοξεύει συμπαγείς οβίδες με εκρηκτικές ή φωσφορικές άκρες. Ένα αγαπημένο όπλο μεταξύ έμπειρων υδροναυτών.\"\n  STR_HYDRO_JET_CANNON_UFOPEDIA: \"Τα κανόνια Ύδρο-Τζετ είναι ένα βαρύ οπλικό σύστημα πεζικού. Το κανόνι εκτοξεύει μίνι τορπίλες με καύσιμα το μαγνήσιο. Αν και ισχυρό, το Ύδρο-Τζετ Κανόνι είναι μια αδέξια και δυσκίνητη συσκευή, κατάλληλη μόνο για χρήση σε υδάτινο περιβάλλον.\"\n  STR_TORPEDO_LAUNCHER_UFOPEDIA: \"Ένας πραγματικός αρσιβαρίστας, αυτός ο μεγάλος εκτοξευτής πυροβολεί τρία είδη τορπίλης, καθένα με τη δική του μονάδα κίνησης. Ένα καταστροφικό όπλο, με μόνο μειονέκτημα την χειροκίνητη φόρτωση. Οι διαθέσιμοι τύποι πυρομαχικών περιλαμβάνουν μεγάλες ή μικρές υψηλής εκρηκτικότητας τορπίλες με φωσφόρο στην άκρη, όλες για χρήση στο νερό μόνο.\"\n  STR_GAUSS_PISTOL_UFOPEDIA: \"Το πιστόλι Gauss χρησιμοποιεί τεχνολογία επιτάχυνσεις σωματιδίων, μια νέα εξέλιξη στη σύγχρονη οπλική τεχνολογία. Είναι γρήγορο, ακριβές και λειτουργεί τόσο πάνω όσο και κάτω από το νερό. Η τεχνολογία Gauss είναι μια εξέλιξη των τεχνολογιών πλάσματος, που αποκτήθηκαν από τον προηγούμενο πόλεμο.\"\n  STR_GAUSS_PISTOL_CLIP_UFOPEDIA: \"Το πιστόλι Gauss χρησιμοποιεί τεχνολογία επιτάχυνσεις σωματιδίων, μια νέα εξέλιξη στη σύγχρονη οπλική τεχνολογία. Είναι γρήγορο, ακριβές και λειτουργεί τόσο πάνω όσο και κάτω από το νερό. Η τεχνολογία Gauss είναι μια εξέλιξη των τεχνολογιών πλάσματος, που αποκτήθηκαν από τον προηγούμενο πόλεμο.\"\n  STR_GAUSS_RIFLE_UFOPEDIA: \"Ένα βήμα πιο πέρα από το πιστόλι Gauss, το τουφέκι έχει μια πραγματική γροθιά, με τους διπλούς επιταχυντές σωματιδίων. Αντικαθιστώντας το σύστημα Plasma που τροφοδοτείται με Ελέριουμ, χρησιμοποιήσαμε έναν επιταχυντή μικροσωματιδίων που παράγει μια ροή αντι-πρωτονίων.\"\n  STR_GAUSS_RIFLE_CLIP_UFOPEDIA: \"Ένα βήμα πιο πέρα από το πιστόλι Gauss, το τουφέκι έχει μια πραγματική γροθιά, με τους διπλούς επιταχυντές σωματιδίων. Αντικαθιστώντας το σύστημα Plasma που τροφοδοτείται με Ελέριουμ, χρησιμοποιήσαμε έναν επιταχυντή μικροσωματιδίων που παράγει μια ροή αντι-πρωτονίων.\"\n  STR_HEAVY_GAUSS_UFOPEDIA: \"Το βαρύ Gauss είναι δυσκίνητο, αλλά εξαιρετικά αποτελεσματικό. Λειτουργεί με 3 επιταχυντές σωματιδίων και είναι ουσιαστικά ασταμάτητο. Το ρεύμα αντι-πρωτονίου περιορίζεται μέσα σε ένα κέλυφος αρσενιδίου του γαλλίου που εκρήγνυται κατά την πρόσκρουση απελευθερώνοντας την αντιύλη.\"\n  STR_HEAVY_GAUSS_CLIP_UFOPEDIA: \"Το βαρύ Gauss είναι δυσκίνητο, αλλά εξαιρετικά αποτελεσματικό. Λειτουργεί με 3 επιταχυντές σωματιδίων και είναι ουσιαστικά ασταμάτητο. Το ρεύμα αντι-πρωτονίου περιορίζεται μέσα σε ένα κέλυφος αρσενιδίου του γαλλίου που εκρήγνυται κατά την πρόσκρουση απελευθερώνοντας την αντιύλη.\"\n  STR_MAGNA_BLAST_GRENADE_UFOPEDIA: \"Η βασική χειροβομβίδα έχει έναν ακριβή και εξελιγμένο χρονοδιακόπτη για τον έλεγχο της.\"\n  STR_DYE_GRENADE_UFOPEDIA: \"Οι χειροβομβίδες βαφής είναι αντικείμενα διπλού ρόλου, χρήσιμα για την παροχή κάλυψης σε εκτεθειμένες καταστάσεις. Λειτουργώντας τόσο στο υδάτινο όσο και στο χερσαίο περιβάλλον, η χρωστική ουσία εκτοξεύεται ως σύννεφο σωματιδίων, παράγοντας ένα σπρέι μελάνης σαν χταποδιού στο νερό ή πυκνό νέφος που μεταφέρεται από τον αέρα στη στεριά.\"\n  STR_PARTICLE_DISTURBANCE_GRENADE_UFOPEDIA: \"Μια χειροβομβίδα εγγύτητας που μπορεί να πεταχτεί σαν μια συνηθισμένη χειροβομβίδα, αλλά ενεργοποιείται από κοντινή κίνηση μετά την εκτόξευση. Απαιτούνται δεξιότητες και εκπαίδευση για τη σωστή χρήση αυτών των συσκευών.\"\n  STR_MAGNA_PACK_EXPLOSIVE_UFOPEDIA: \"Αυτή η εκρηκτική ύλη πρέπει να χρησιμοποιείται μόνο για σκοπούς κατεδάφισης. Ωστόσο, η προηγούμενη εμπειρία έχει δείξει ότι αυτά τα ισχυρά πακέτα εκρηκτικών είναι ιδανικά όπλα για την εξόντωση των εξωγήινων. Η ακτίνα έκρηξης είναι μεγάλη, επομένως βεβαιωθείτε ότι κανένας υδροναύτης δεν βρίσκεται στην ελάχιστη απόσταση ασφαλείας.\"\n  STR_PARTICLE_DISTURBANCE_SENSOR_UFOPEDIA: \"Αυτή η νέα συσκευή χρησιμοποιεί μια ποικιλία αισθητήρων και προηγμένα υπολογιστικά συστήματα για να ανιχνεύει κινούμενες εχθρικές μονάδες. Κάντε κλικ στο εικονίδιο του Αισθητήρα Διαταραχής στην τακτική οθόνη. Επιλέξτε 'Χρήση Αισθητήρα' από το μενού. Η οθόνη του αισθητήρα δείχνει ένα βέλος στο κέντρο, το οποίο δείχνει την κατεύθυνση προς την οποία κοιτάει ο ακουαναύτης (Ο Βορράς είναι στο πάνω μέρος). Τα σημάδια δείχνουν μονάδες που έχουν κινηθεί πρόσφατα. Μεγάλες μονάδες ή μονάδες που κινούνται γρήγορα θα παράγουν μεγαλύτερα σημάδια. Οι στατικές μονάδες δεν θα εμφανίζονται.\"\n  STR_MEDI_KIT_UFOPEDIA: \"Για να το χρησιμοποιήσετε, αντιμετωπίζετε τον τραυματισμένο πράκτορα X-Com ή στέκεστε πάνω από το σώμα ενός αποσβολωμένου υδροχόου.{NEWLINE}HEALING> Το κόκκινο υποδηλώνει πληγές. Επιλέξτε μέρος του σώματος και κάντε κλικ στο κουμπί «Θεραπεία». Μια θανατηφόρα πληγή θα επουλωθεί και θα αποκατασταθεί η υγεία.{NEWLINE}STIMULANT>  Αποκαθιστά την ενέργεια και αναζωογονεί τους ζαλισμένους υδροναύτες. Για να αναζωογονήσετε έναν αναίσθητο υδροχόο, πρέπει να σταθείτε ακριβώς πάνω από το σώμα.{NEWLINE}PAIN KILLER> Αποκαθιστά το ηθικό των τραυματισμένων υδροναυτών.\"\n  STR_MC_DISRUPTOR_UFOPEDIA: \"Η απόλυτη τεχνολογία Μ.Ε. Αυτό μπορεί να χρησιμοποιηθεί μόνο από υδροναύτες με M.C. ικανότητες. Κάντε κλικ στο Disruptor, επιλέξτε τον τύπο της επίθεσης και επιλέξτε μια μονάδα στόχο με τον κέρσορα. Υπάρχουν δύο τύποι επίθεσης Disruptor:{NEWLINE}JAM IMPLANT> Εάν είναι επιτυχής, η μονάδα μπερδευτεί και μπορεί να πανικοβληθεί.{NEWLINE}CONTROL IMPLANT> Εάν είναι επιτυχής, θα αποκτήσετε τον έλεγχο της εχθρικής μονάδας.\"\n  STR_THERMAL_TAZER_UFOPEDIA: \"Αυτή η συσκευή μπορεί να χρησιμοποιηθεί μόνο σε κοντινή μάχες, αλλά θα αναισθητοποιήσει έναν ζωντανό οργανισμό χωρίς να τον σκοτώσει παγώνοντας το πλάσμα.\"\n  STR_VIBRO_BLADE_UFOPEDIA: \"Το Vibroblade είναι ένα μακρύ και αιχμηρό μαχαίρι από τιτάνιο που περιστρέφεται με πάνω από 6000 στροφές ανά λεπτό. Αυτή η συσκευή μπορεί να σπάσει ακόμα και την πιο σκληρή θωράκιση κατάδυσης. Η πηγή ενέργειας είναι μια εξωγήινη εφεύρεση, η προσπάθειά μας να κατασκευάσουμε αυτά τα αντικείμενα πριν, αποτύχαμε θλιβερά. Οι λεπίδες μας περιστρέφονταν πολύ αργά ή εξερράγησαν κάτω από πίεση.\"\n  STR_THERMIC_LANCE_UFOPEDIA: \"Η Θερμική Λόγχη αποτελεί μια λογική επέκταση της τεχνολογίας του Vibroblade. Η λεπίδα περιστρέφεται με υψηλή ταχύτητα και μια πηγή ενέργειας Zrbite υπερθερμαίνει τη λεπίδα για να κόψει την πανοπλία σαν ένα ζεστό μαχαίρι το βούτυρο.\"\n  STR_HEAVY_THERMIC_LANCE_UFOPEDIA: \"Η Βαριά Θερμική Λόγχη είναι μια πιο ισχυρή έκδοση της Θερμικής Λόγχης. Δίδυμες πηγές θερμότητας και μια εξαιρετικά υψηλή ταχύτητα περιστροφής σημαίνει ότι η Βαριά Θερμική Λόγχη είναι ουσιαστικά ασταμάτητη σε όλα τα υλικά.\"\n  STR_SONIC_CANNON_UFOPEDIA: \"Το Ηχητικό Κανόνι είναι το πιο ισχυρό μέλος της οικογένειας των ηχητικών όπλων. Διαθέτει έναν πιο ευρύ φάσμα ηχητικού ταλαντωτή και ένα μεγαλύτερο θάλαμο ανακλάσεων από το Blasta. Το Κανόνι έχει επίσης ένα σύστημα έκρηξης παλμών που τροποποιεί τον υπερήχο κατά την διαμόρφωση για να παράγει ένα πιο αποτελεσματικό Ηχητικό Σοκ.\"\n  STR_CANNON_POWER_CLIP_UFOPEDIA: \"Αυτή η μικρή συσκευή χρησιμοποιείται ως πυρομαχικό για ένα Κανόνι Ήχου. Περιέχει μικρή ποσότητα Zrbite.\"\n  STR_SONIC_BLASTA_RIFLE_UFOPEDIA: \"Ένα πιο ισχυρό Ηχητικό μηχάνημα. Ούτε καν το υψηλού άνθρακα χάλυβας είναι ανθεκτικός σε αυτό το όπλο. Ο υψηλής συμπίεσης εκπομπέας κύματος ενισχύεται από έναν υπεραγωγό ενισχυτή για να αυξήσει την ισχύ αυτού του όπλου.\"\n  STR_BLASTA_POWER_CLIP_UFOPEDIA: \"Αυτό το μικρό αντικείμενο χρησιμοποιείται ως πηγή ενέργειας για ένα ηχητικό τουφέκι, ένα ισχυρό όπλο των εξωγήινων, και περιέχει μια μικρή ποσότητα Zrbite.\"\n  STR_SONIC_PISTOL_UFOPEDIA: \"Τα ηχητικά πιστόλια είναι ένα εξωγήινο όπλο που βασίζεται σε υπερηχητικά κύματα ήχου που μπορούν να ζελατινοποιήσουν τα οστά σε δευτερόλεπτα. Τα κύματα υπερήχων καταλαμβάνουν ένα εύρος πέρα από το πεδίο της ανθρώπινης ακοής.\"\n  STR_PISTOL_POWER_CLIP_UFOPEDIA: \"Πηγή ενέργειας για το συμπαγές Εξωγήινο Ηχητικό Πιστόλι. Περιέχει Zrbite - την πηγή όλης της ενέργειας των Εξωγήινων.\"\n  STR_DISRUPTOR_PULSE_LAUNCHER_UFOPEDIA: \"Αυτό είναι ένα κατευθυνόμενο όπλο για χρήση μόνο από εξωγήινους, που εκτοξεύει αυτοπροωθούμενα «Διαταρακτικά Βλήματα». Όταν κάνετε κλικ για να πυροβολήσετε το όπλο, θα δημιουργήσει «σημεία πορείας» για να ακολουθήσει το Βλήμα. Όταν έχετε τοποθετήσει αρκετά σημεία, κάντε κλικ στο εικονίδιο εκκίνησης.\"\n  STR_DISRUPTOR_AMMO_UFOPEDIA: \"Αυτή η συσκευή είναι ένα Βλήμα Διαταράκτη Παλμών με ενσωματωμένο σύστημα καθοδήγησης υπολογιστή. Εκτοξεύεται από Εκτοξευτή Παλμού Διαταραχής.\"\n  STR_THERMAL_SHOK_LAUNCHER_UFOPEDIA: \"Ένας μικρός εκτοξευτής θερμικού σοκ που εκτοξεύει χημικές βόμβες ψύξης. Πολύ χρήσιμο για την παγίδευση ζωντανών εξωγήινων.\"\n  STR_THERMAL_SHOK_BOMB_UFOPEDIA: \"Η βόμβα Θερμικού Σοκ χρησιμοποιείται για τη σύλληψη ζωντανών ανθρώπων, αλλά μπορεί επίσης να χρησιμοποιηθεί ενάντια στις περισσότερες φυλές εξωγήινων. Πυροδοτείται από Εκτοξευτή Θερμικού Σοκ.\"\n  STR_SONIC_PULSER_UFOPEDIA: \"Αυτή η συσκευή λειτουργεί με τον ίδιο τρόπο όπως μια τυπική χειροβομβίδα εκτόξευσης - με τη διαφορά ότι είναι πολλές φορές πιο ισχυρή. Η χειροβομβίδα χρησιμοποιεί μια ηχητική έκρηξη ενός παλμού που εκπέμπεται ταυτόχρονα προς όλες τις κατευθύνσεις.\"\n  STR_MC_READER_UFOPEDIA: \"Μέσα στα σώματα των εξωγήινων έχουμε βρει μικρές χειρουργικά εμφυτευμένες μονάδες. Πρόκειται για εμφυτεύματα ελέγχου που έχουν σχεδιαστεί από τους Ακουατοϊδες για να επιτρέπουν τη συνεχή παροχή πληροφοριών από το πεδίο της μάχης, ακόμη και σε μεγάλες αποστάσεις. Ο Αναγνώστης Μοριακού Ελέγχου είναι μια συσκευή επικοινωνίας Εξωγήινων που χρησιμοποιείται για τη λήψη πληροφοριών  απευθείας από τα εμφυτεύματα Μ.Ε. Οι μονάδες X-Com μπορούν να χρησιμοποιήσουν αυτήν τη συσκευή στη μάχη για να εμφανίσουν τα χαρακτηριστικά ενός εξωγήινου. Επιλέξτε την επιλογή «χρήση». Στη συνέχεια, κάντε κλικ σε έναν εξωγήινο με τον κέρσορα.\"\n  STR_SURVEY_SHIP: \"Πλοίο Έρευνας\"\n  STR_ESCORT: \"Συνοδεία\"\n  STR_CRUISER: \"Καταδρομικό\"\n  STR_HEAVY_CRUISER: \"Βαρύ Καταδρομικό\"\n  STR_HUNTER: \"Κυνηγός\"\n  STR_BATTLESHIP: \"Θωρυκτό\"\n  STR_DREADNOUGHT: \"Μεγάλο Θωρηκτό\"\n  STR_FLEET_SUPPLY_CRUISER: \"Καταδρομικό Εφοδιασμού Στόλου\"\n  MAP_SEABED: \"Βυθός της Θάλασσας\"\n  MAP_PIPES: \"Ερευνητικό Κέντρο\"\n  MAP_PLANE: \"Συντριβή Αεροπλάνου\"\n  MAP_ATLAN: \"Ατλαντίδα\"\n  MAP_MU: \"Ναός των Μάγια\"\n  MAP_GAL: \"Βυθισμένη Γαλλέρα\"\n  MAP_MSUNK: \"Βυθισμένο Σκάφος\"\n  MAP_VOLC: \"Ηφαιστειογενής\"\n  MAP_CORAL: \"Κοράλλι\"\n  MAP_PORT: \"Λιμάνι\"\n  MAP_ISLAND: \"Νησί\"\n  MAP_CARGO: \"Φορτηγό πλοίο\"\n  MAP_LINERT: \"Κρουαζιερόπλοιο P1\"\n  MAP_LINERB: \"Κρουαζιερόπλοιο P2\"\n  MAP_ALART: \"Εξάρτημα P1\"\n  MAP_GRUNGE: \"Εξάρτημα P2\"\n  MAP_ENTRY: \"Αποικία P1\"\n  MAP_A_BASE: \"Αποικία P2\"\n  MAP_ALSHIP: \"T'leth P1\"\n  MAP_LEVEL: \"T'leth P2\"\n  MAP_CRYPT: \"T'leth P3\"\n  MAP_XBASES: \"Βάση X-Com\"\n  STR_MIXED_CREW: \"Μικτό πλήρωμα\"\n  STR_MIXED_CREW_2: \"Μικτό πλήρωμα 2\"\n  STR_RATING: \"ΑΞΙΟΛΟΓΗΣΗ> {0}\"\n  STR_RATING_TERRIBLE: \"ΑΘΛΙΑ!\"\n  STR_RATING_POOR: \"ΦΤΩΧΑ!\"\n  STR_RATING_OK: \"ΟΚ\"\n  STR_RATING_GOOD: \"ΚΑΛΑ!\"\n  STR_RATING_EXCELLENT: \"ΑΡΙΣΤΑ!\"\n  STR_SCORE: \"ΠΟΝΤΟΙ\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"ΜΗΝΙΑΙΑ ΑΝΑΦΟΡΑ X-COM\"\n  STR_MONTH: \"Μήνας> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"Η επιτροπή των οργανισμών χρηματοδότησης είναι γενικά ικανοποιημένη με την πρόοδό σας μέχρι στιγμής.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"Η επιτροπή των οργανισμών χρηματοδότησης είναι πολύ ικανοποιημένη με την εξαιρετική σας πρόοδο. Συνεχίστε την καλή δουλειά.\"\n  STR_COUNCIL_IS_DISSATISFIED: \"Η επιτροπή των φορέων χρηματοδότησης δεν είναι ικανοποιημένη με την απόδοσή σας. Πρέπει να βελτιώσετε την αποτελεσματικότητά σας στην αντιμετώπιση του εξωγήινου κινδύνου, διαφορετικά υπάρχει κίνδυνος διακοπής της χρηματοδοτικής στήριξης για το X-Com.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"Δεν έχετε καταφέρει να αντιμετωπίσετε την εισβολή των εξωγήινων και το συνέδριο των οργανισμών χρηματοδότησης, δυστυχώς, αποφάσισε να τερματίσει τη χρηματοδότηση της X-Com. Κάθε οργανισμός θα αντιμετωπίσει το πρόβλημα όπως κρίνει κατάλληλο. Μπορούμε μόνο να ελπίζουμε ότι θα επιτευχθεί κάποια συμφωνία με αυτές τις αρχαίες δυνάμεις και ότι ο γενικός πληθυσμός θα αποδεχθεί τους υδρόβιους επισκέπτες.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} είναι ιδιαίτερα ικανοποιημένη με την ικανότητά σου να αντιμετωπίσεις την τοπική απειλή και συμφώνησε να αυξήσει τη χρηματοδότησή της.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"\\\"{0} είναι ιδιαίτερα ευχαριστημένοι με την πρόοδό σας στην αντιμετώπιση της τοπικής εισβολής Εξωγήινων και έχουν συμφωνήσει να αυξήσουν τη χρηματοδότησή τους.\\\"\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} και {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} είναι δυσαρεστημένο με την ικανότητά σας να αντιμετωπίσετε τη δραστηριότητα Εξωγήινων στα θαλάσσια της περιοχής και έχει αποφασίσει να μειώσει τη χρηματοδοτική της δέσμευση.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} δεν είναι ικανοποιημένοι με την ικανότητά σας να αντιμετωπίσετε τη δραστηριότητα των εξωγήινων στη θάλασσά τους και έχουν αποφασίσει να μειώσουν τη χρηματοδότησή τους.\"\n  STR_KNOTS: \"{0} κόμβοι\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} υπέγραψε συμφωνία συνεργασίας με τις εξωγήινες δυνάμεις και απέσυρε τη χρηματοδότησή του από το X-Com.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} έχουν υπογράψει συμφωνία συνεργασίας με εξωγήινες δυνάμεις και έχουν αποσυρθεί από τη χρηματοδότηση του Προγράμματος X-Com.\"\n  STR_MONTHLY_RATING: \"Μηνιαία Βα8μολογία> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Αλλαγή χρηματοδότησης> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"Ο οργανισμός χρηματοδότησης δεν είναι ευχαριστημένος με την οικονομική σας κατάσταση. Πρέπει να μειώσετε τα χρέη σας κάτω από 1 εκατομμύριο δολάρια, διαφορετικά το X-Com θα τερματιστεί.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"ΕΠΙΛΥΘΗΚΑΝ ΜΕΤΑΔΟΣΕΙΣ ΥΠΟ-ΣΩΜΑΤΙΔΙΩΝ\"\n  STR_CRAFT_TYPE: \"ΤΥΠΟΣ ΥΠΟΒΡΥΧΙΟΥ\"\n  STR_RACE: \"ΦΥΛΗ\"\n  STR_MISSION: \"ΑΠΟΣΤΟΛΗ\"\n  STR_ZONE: \"ΖΩΝΗ\"\n  STR_ALLOCATE_RESEARCH: \"Κατανομή Έρευνας\"\n  STR_ALLOCATE_MANUFACTURE: \"Κατανομή  Παραγωγής\"\n  STR_AZORES: \"Αζόρες\"\n  STR_REYKJAVIK: \"Ρέικιαβικ\"\n  STR_BERMUDA: \"Βερμούδες\"\n  STR_NEW_YORK: \"Νέα Υόρκη\"\n  STR_BOSTON: \"Βοστώνη\"\n  STR_FORT_SEVERN: \"Φρούριο Σέβερν\"\n  STR_DAKAR: \"Ντακάρ\"\n  STR_RECIFE: \"Ρεσίφε\"\n  STR_ACCRA: \"Άκρα\"\n  STR_ASCENSION_ISLAND: \"Νήσος Αναλήψεως\"\n  STR_TRINIDADE_ISLAND: \"Νήσος Τριντάντε\"\n  STR_FALKLAND_ISLAND: \"Νήσος Φόκλαντ\"\n  STR_CANARY_ISLANDS: \"Κανάριοι Νήσοι\"\n  STR_ANCHORAGE: \"Αγκυροβόλιο\"\n  STR_ST_LAWRENCE_ISLAND: \"Νησί Αγίου Λαυρεντίου\"\n  STR_SAN_FRANCISCO: \"Σαν Φρανσίσκο\"\n  STR_MIDWAY_ISLAND: \"Νησί Μίντγουεϊ\"\n  STR_VANCOUVER: \"Βανκούβερ\"\n  STR_TASMANIA: \"Ταζμανία\"\n  STR_HAWAII: \"Χαβάη\"\n  STR_FIJI: \"Φίτζι\"\n  STR_TONGA: \"Τόνγκα\"\n  STR_EASTER_ISLAND: \"Το νησί του Πάσχα\"\n  STR_GALAPAGOS_ISLAND: \"Νησιά Γκαλάπαγκος\"\n  STR_WELLINGTON: \"Γουέλινγκτον\"\n  STR_SOLOMON_ISLAND: \"Νήσος Σολομώντα\"\n  STR_CRETE: \"Κρήτη\"\n  STR_LISBON: \"Λισαβόνα\"\n  STR_PORT_SAID: \"Πορτ Σάιντ\"\n  STR_MARSEILLES: \"Μασσαλία\"\n  STR_TRIPOLI: \"Τρίπολη\"\n  STR_MANILA: \"Μανίλα\"\n  STR_HONG_KONG: \"Χονγκ Κονγκ\"\n  STR_SINGAPORE: \"Σινγκαπούρη\"\n  STR_BANGKOK: \"Μπανγκόκ\"\n  STR_DARWIN: \"Δαρβίνος\"\n  STR_BOMBAY: \"Βομβάη\"\n  STR_SAYCHELLES_ISLAND: \"Νησιά Σεϋχέλλες\"\n  STR_MALDIVE_ISLAND: \"Νησί Μαλδίβες\"\n  STR_SRI_LANKA: \"Σρι Λάνκα\"\n  STR_MAURITIUS: \"Μαυρίκιος\"\n  STR_TOKYO: \"Τόκιο\"\n  STR_SHANGHAI: \"Σαγκάη\"\n  STR_VLADIVOSTOK: \"Βλαντιβοστόκ\"\n  STR_LONDON: \"Λονδίνο\"\n  STR_FAEROE_ISLAND: \"Νήσοι Φερόε\"\n  STR_ABERDEEN: \"Αμπερντίν\"\n  STR_OSLO: \"Όσλο\"\n  STR_JAMAICA: \"Τζαμάικα\"\n  STR_PANAMA: \"Παναμάς\"\n  STR_MIAMI: \"Μαϊάμι\"\n  STR_PSI_TRAINING: \"Εκπαίδευση Μ.Ε.\"\n  STR_PSIONIC_TRAINING: \"ΕΚΠΑΙΔΕΥΣΗ ΜΟΡΙΑΚΟΥ ΕΛΕΓΧΟΥ\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Υπόλοιπο Μ.Ε. χωρητικότητα> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"Μ.Ε.{NEWLINE}Δύναμη\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"Μ.Ε. Ικανότητα{NEWLINE}/Βελτίωση\"\n  STR_IN_TRAINING: \"Σε{NEWLINE}Εξάσκηση;\"\n  STR_TARGETTED_BY: \"ΣΤΟΧΕΥΜΕΝΟ ΑΠΟ:\"\n  STR_WEAPONS_CREW_HWPS: \"ΟΠΛΑ/{NEWLINE}ΠΛΗΡΩΜΑ/ΥΟΣα\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"έχει χαμήλα καύσιμα,{NEWLINE}επιστροφή στη βάση\"\n  STR_SOLDIER_LIST: \"Λίστα Υδροναυτών\"\n  STR_RANK_: \"ΒΑΘΜΙΔΑ> {ALT}{0}\"\n  STR_MISSIONS: \"ΑΠΟΣΤΟΛΕΣ> {ALT}{0}\"\n  STR_KILLS: \"ΘΑΝΑΤΟΙ> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"ΑΝΑΡΡΩΣΗ ΤΡΑΥΜΑΤΩΝ> {ALT}{0}\"\n  STR_TIME_UNITS: \"ΜΟΝΑΔΕΣ ΧΡΟΝΟΥ\"\n  STR_STAMINA: \"ΑΝΤΟΧΗ\"\n  STR_HEALTH: \"ΥΓΕΙΑ\"\n  STR_BRAVERY: \"ΘΑΡΡΟΣ\"\n  STR_REACTIONS: \"ΑΝΤΙΔΡΑΣΕΙΣ\"\n  STR_FIRING_ACCURACY: \"ΕΥΣΤΟΧΙΑ ΒΟΛΗΣ\"\n  STR_THROWING_ACCURACY: \"ΕΥΣΤΟΧΙΑ ΡΙΨΗΣ\"\n  STR_STRENGTH: \"ΔΥΝΑΜΗ\"\n  STR_PSIONIC_STRENGTH: \"Μ.Ε. ΔΥΝΑΜΗ\"\n  STR_PSIONIC_SKILL: \"Μ.Ε. ΙΚΑΝΟΤΗΤΑ\"\n  STR_NEW_RANK: \"ΝΕΑ ΒΑΘΜΙΔΑ\"\n  STR_PROMOTIONS: \"Προαγωγές\"\n  STR_SOLDIERS_UC: \"ΥΔΡΟΝΑΥΤΕΣ\"\n  STR_COELACANTH_GAS_CANNON_UFOPEDIA: \"Τα αυτοματοποιημένα ΥΟΣ'α έχουν υψηλή ευελιξία και αντοχή στη θωράκιση. Παρέχουν βαριά υποστήριξη στρατευμάτων σε όλα τα βάθη. Τα ΥΟΣ επανοπλίζονται αυτόματα εάν έχετε αρκετά πυρομαχικά.\"\n  STR_COELACANTH_AQUA_JET_UFOPEDIA: \"Αυτό το υποβρύχιο είναι εξοπλισμένο με τορπίλες Άκουα-Τζετ. Αυτό το όπλο λειτουργεί μόνο κάτω από το νερό. Βεβαιωθείτε ότι οι αποθήκες είναι καλά εφοδιασμένες με τορπίλες Άκουα-Τζετ.\"\n  STR_COELACANTH_GAUSS_UFOPEDIA: \"Η τεχνολογία Gauss παρέχει ένα ισχυρό σύστημα όπλων για τα ΥΟΣ'α. Προσφέρει μεγάλη οπλική δύναμη σε σύγκριση με προηγούμενα μοντέλα και χρησιμοποιεί αποκλειστική τεχνολογία X-Com.\"\n  STR_DISPLACER_SONIC_UFOPEDIA: \"Η εξωγήινη τεχνολογία έχει επαναπροσδιορίσει τα Υποβρύχια Οπλικά Συστήματα ΥΟΣ. Η δυνατότητα χρήσης ανιονικών αποκρουστών σημαίνει ότι τα ΥΟΣ δεν περιορίζονται πλέον σε ξηρά/υποθαλάσσιες επιφάνειες. Ο ήχος ως όπλο προσφέρει πραγματικό πλεονέκτημα στη μάχη.\"\n  STR_DISPLACER_PWT_UFOPEDIA: \"Αυτό το ΥΟΣ διαθέτει όπλα Παλμικού Κύματος για χρήση στο νερό. Πρέπει να κατασκευάσετε ΤΠΚ για να τα κρατήσετε πλήρως οπλισμένα. Για να πυροβολήσετε, επιλέξτε έναν αριθμό από 'σημεία πορείας' και κάντε κλικ στο εικονίδιο εκτόξευσης.\"\n  STR_ALIEN_PROBE_MISSION: \"Αποστολή Έρευνας Εξωγήινων\"\n  STR_ALIEN_INTERDICTION: \"Εξωγήινη Αποκλειστική Δράση\"\n  STR_ALIEN_RESOURCE_RAID: \"Εξωγήινη Επιδρομή Πόρων\"\n  STR_ALIEN_INFILTRATION: \"Εξωγήινη Διείσδυση\"\n  STR_ALIEN_BASE: \"Επέκταση Αποικιών Εξωγήινων\"\n  STR_ALIEN_SURFACE_ATTACK: \"Επηφανιακή Επίθεση Εξωγήινων\"\n  STR_ALIEN_RETALIATION: \"Επίθεση πλωτής βάσης\"\n  STR_ALIEN_SUPPLY: \"Αποστολή Εφοδιασμού Αποικιών\"\n  STR_ALIEN_PROBE_MISSION_UFOPEDIA: \"Η Εξωγήινων Πόρων αποστολή χρησιμοποιείται για τη συσχέτιση δεδομένων σχετικά με τον βυθό της θάλασσας, τους πόρους, τη ναυτιλία και τις διαδρομές πτήσης αεροπλάνων μιας περιοχής. Τα υποβρύχια Εξωγήινων που συμμετέχουν σε αυτές τις αποστολές δεν αποτελούν κύρια απειλή από μόνα τους, αλλά υποδεικνύουν τοποθεσίες δραστηριότητας που ενδέχεται να εκδηλωθούν οποιαδήποτε στιγμή.\"\n  STR_ALIEN_INTERDICTION_UFOPEDIA: \"Οι Εξωγήινοι έχουν μια πολιτική εποπτείας των περιοχών που τους ενδιαφέρουν, αποστέλλοντας σκάφη με τον ρητό σκοπό να ασφαλίσουν μια περιοχή πριν ξεκινήσουν πιο εντατικές αποστολές. Θα προσγειωθούν σε συγκεκριμένες τοποθεσίες που προτίθενται να λεηλατήσουν αργότερα, προκειμένου να κλειδώσουν τις περιοχές και να ετοιμάσουν τον δρόμο για τον επόμενο επίπεδο δραστηριοτήτων.\"\n  STR_ALIEN_RESOURCE_RAID_UFOPEDIA: \"Η βύθιση πλοίων και η κατάρριψη αεροσκαφών είναι βασικά στοιχεία της στρατηγικής των Εξωγήινων. Η απόκτηση υλικών είναι μια από τις κύριες δραστηριότητες των εξωγήινων και ως εκ τούτου συνδέεται με αυτές τις απροκάλυπτα επιθετικές πράξεις. Οι Εξωγήινοι επιτίθενται επίσης σε περιοχές γεωθερμικής δραστηριότητας, τοποθεσίες εξόρυξης και τοποθεσίες της αρχαιότητας για ορυκτά και εξευγενισμένα μέταλλα και άλλα αντικείμενα που παράγονται από τον άνθρωπο.\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"Αυτό μπορεί να έχει ως αποτέλεσμα την επίσημη επαφή μεταξύ Εξωγήινων και εταιρειών ή κυβερνήσεων στο υψηλότερο επίπεδο. Το αποκορύφωμα αυτής της δραστηριότητας χαρακτηρίζεται από έντονη δραστηριότητα Εξωγήινων Υποβρυχίων στα νερά του ενδιαφερόμενου οργανισμού. Οι Εξωγήινοι θα επιχειρήσουν να υπογράψουν μια συμφωνία με μια κυβέρνηση ή έναν οργανισμό προσφέροντας γνώση των ανώτερων τεχνολογιών τους. Αυτή η δραστηριότητα των εξωγήινων αντιπροσωπεύει μια σημαντική απειλή για την X-Com. Εάν μια εταιρεία ή μια κυβέρνηση συνεργαστεί με τους εισβολείς, τότε η χρηματοδότησή της σταματά.\"\n  STR_ALIEN_BASE_UFOPEDIA: \"Οι εξωγήινοι θα κατασκευάσουν μυστικές υποθαλάσσιες αποικίες σε απομακρυσμένες τοποθεσίες. Μετά από μερικές αρχικές αναγνωριστικές πτήσεις θα εμφανιστεί κάποια έντονη δραστηριότητα Εξωγήινων Υποβρυχίων καθώς η αποικία χτίζεται. Αυτές οι αποικίες είναι γνωστό ότι περιέχουν εργαστήρια, κέντρα κλωνοποίησης, χειρουργικές εγκαταστάσεις για πειραματισμούς σε ανθρώπους και εξωγήινους. Η παρουσία εξωγήινων αποικιών θα δημιουργήσει περισσότερη δραστηριότητα εξωγήινων χωρίς την παρουσία Υποβρυχίων τους. Προκειμένου να εντοπιστεί μια αποικία, ένα υποβρύχιο της X-Com πρέπει να περιπολεί σε μια περιοχή για μερικές ώρες για να έχει κάποιες πιθανότητες επιτυχούς εντοπισμού.\"\n  STR_ALIEN_SURFACE_ATTACK_UFOPEDIA: \"Όταν οι Εξωγήινοι χρειάζονται ανθρώπους τρομοκρατούν ένα λιμάνι, επιτίθενται σε ένα νησί ή σε πλοίο. Οι άμαχοι θα απειληθούν άμεσα, για να ικανοποιήσουν τις διεστραμμένες ανάγκες αναπαραγωγής των Εξωγήινων και τα φρικτά πειράματά τους.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"Εάν τα υποβρύχια αναχαίτισης της X-Com είναι ιδιαίτερα επιτυχημένα στο να βυθίζουν σκάφη εξωγήινων, τότε οι εξωγήινοι ενδέχεται να λάβουν κάποια επιθετική ενέργεια αντίποινων. Αυτό θα μπορούσε να οδηγήσει σε άμεση επίθεση εναντίον μιας εγκατάστασης X-Com. Ωστόσο, οι Εξωγήινοι πρέπει να βρουν την βάση X-Com για να της επιτεθούν, και με την προϋπόθεση ότι τα Εξωγήινα Υποβρύχια κρατηθούν μακριά, τότε θα υπάρχει μικρός κίνδυνος για επίθεση.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"Μόλις κατασκευαστεί μια αποικία Εξωγήινων, τότε ανεφοδιάζεται εκ νέου σε τακτική βάση από ένα ειδικό πλοίο εφοδιασμού. Εάν ένα από αυτά τα σκάφη ανιχνευθεί ενώ προσγειώνετε, τότε είναι βέβαιο ότι μια αποικία εξωγήινων βρίσκεται κοντά.\"\n  STR_SURVEY_SHIP_UFOPEDIA: \"Αυτό το μικροσκοπικό υποβρύχιο χρησιμοποιείται για αποστολές αναγνώρισης και έρευνας. Συνήθως προηγείται των μεγαλύτερων σκαφών κατά την έναρξη μιας ομάδας εργασίας των Εξωγήινων.\"\n  STR_ESCORT_UFOPEDIA: \"Ένα μεσαίου μεγέθους σκάφος συνοδείας που δεν απειλεί από μόνο του. Αυτό το σκάφος προηγείται της άφιξης μεγαλύτερων σκαφών και των αυξημένων δραστηριοτήτων.\"\n  STR_CRUISER_UFOPEDIA: \"Το Καταδρομικό είναι ένα σκάφος γενικής χρήσης, το στήριγμα του στόλου των εξωγήινων, χρησιμοποιείται σε όλους τους τύπους αποστολών εξωγήινων και είναι επικίνδυνος αντίπαλος.\"\n  STR_HEAVY_CRUISER_UFOPEDIA: \"Το Βαρύ Καταδρομικό είναι ένα πιο ισχυρό πλοίο από το καταδρομικό, με μεγαλύτερα όπλα και συστήματα κίνησης που αυξάνουν τη δύναμή του. Το Βαρύ Καταδρομικό χρησιμοποιείται για αποστολές πόρων, για τη συλλογή μεγάλων ποσοτήτων μεταλλευμάτων και εξοπλισμού.\"\n  STR_HUNTER_UFOPEDIA: \"Αυτό το σκάφος είναι εξοπλισμένο με αίθουσα εξετάσεων για την πραγματοποίηση πειραμάτων και χειρουργικών επεμβάσεων σε ανθρώπους. Τα θύματα υποβάλλονται στα πιο αποκρουστικά βασανιστήρια και ο εγκέφαλος συχνά αφαιρείται και αποθηκεύεται για επεξεργασία καθ' οδόν.\"\n  STR_BATTLESHIP_UFOPEDIA: \"Το θωρηκτό είναι το πιο επιθετικό πλοίο που διαθέτουν οι εξωγήινοι, διαθέτει όλες τις τεχνολογίες και συστήματα για να λειτουργεί ως βάση επιχειρήσεων για οποιαδήποτε μορφή επιθετικής πράξης που μπορεί να θέλουν να εκτελέσουν οι Εξωγήινοι, φέρει μεγάλο οπλισμό.\"\n  STR_DREADNOUGHT_UFOPEDIA: \"Το Μεγάλο Θωρηκτό είναι ένα σούπερ στρατιωτικό σκάφος, πλήρως εξοπλισμένο με όλες τις Εξωγήινες τεχνολογίες και τεράστιο ωφέλιμο φορτίο. Το Μεγάλο Θωρηκτό είναι ένας σκληρός και φοβερός αντίπαλος.\"\n  STR_FLEET_SUPPLY_CRUISER_UFOPEDIA: \"Το σκάφος ανεφοδιασμού χρησιμοποιείται κατά την κατασκευή αποικιών εξωγήινων ή για την προμήθεια υφιστάμενων αποικιών. Μεταφέρει εξωγήινες θρεπτικές ουσίες, DNA, έμβρυα και άλλα βιολογικά συστατικά.\"\n  STR_DISMANTLE: \"Διάλυση\"\n  STR_FACILITY_IN_USE: \"ΥΔΡΟ-ΥΠΟΣΤΕΓΟ ΣΕ ΧΡΗΣΗ\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"ΑΔΥΝΑΤΗ ΑΠΟΣΥΝΑΡΜΟΛΟΓΙΣΗ ΤΟΥ ΥΔΡΟ-ΥΠΟΣΤΕΓΟΥ!{SMALLLINE}Όλα τα Υπόστεγα της βάσης πρέπει να είναι συνδεδεμένα με τον αεροθάλαμο.\"\n  STR_TRANSFER_ITEMS_TO: \"Μεταφορά Αντικειμένου σε {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"ΚΑΝΕΝΑΣ ΠΕΡΙΟΡΙΣΜΕΝΟΣ ΕΞΩΓΗΙΝΟΣ ΓΙΑ ΜΕΤΑΦΟΡΑ!{SMALLLINE}Ζωντανοί εξωγήινοι χρειάζονται μια συσκευή περιορισμού εξωγήινων προκειμένου να επιβιώσουν.\"\n  STR_AMOUNT_AT_DESTINATION: \"ΠΟΣΟΤΗΤΑ{NEWLINE}ΠΡΟΟΡΙΣΜΟY\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"Ο εξωγήινος πεθαίνει καθώς δεν υπάρχει χώρος περιορισμού του εξωγήινου\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"ΧΩΡΙΣ ΔΩΡΕΑΝ ΔΙΑΜΟΝΗ!{SMALLLINE}Η βάση προορισμού δεν έχει αρκετό χώρο στους θαλάμους διαβίωσης για το πλήρωμα που έχει ανατεθεί στο υποβρύχιο.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"ΑΝΕΠΑΡΚΕΙΑ  ΑΠΟΘΗΚΕΥΤΙΚΟΥ ΧΩΡΟΥ!{SMALLLINE}Η βάση προορισμού δεν έχει αρκετό χώρο αποθήκευσης για τον εξοπλισμό που έχει ανατεθεί στο υποβρύχιο.\"\n  STR_ITEMS_ARRIVING: \"Άφηση Αντικειμένων\"\n  STR_DESTINATION_UC: \"ΠΡΟΟΡΙΣΜΟΣ\"\n  STR_DART_PISTOL: \"Όπλο Εκτόξευσης Βελών\"\n  STR_DART_POD: \"Γεμηστήρας για βελάκια\"\n  STR_JET_HARPOON: \"Καμάκι\"\n  STR_HARPOON_POD: \"Γεμηστήρας απο Καμάκι\"\n  STR_GAS_CANNON: \"Κανόνι Αερίου\"\n  STR_GC_AP_AMMO: \"GC-AP Bolts\"\n  STR_GC_HE_AMMO: \"GC-HE Οβίδες\"\n  STR_GC_P_AMMO: \"GC-Οβίδες Φωσφόρου\"\n  STR_HYDRO_JET_CANNON: \"Κανόνι Υδρο-Τζετ\"\n  STR_HJC_AP_AMMO: \"HJ-AP Σφαίρα\"\n  STR_HJC_HE_AMMO: \"HJ-HE Σφαίρα\"\n  STR_HJC_P_AMMO: \"HJ-P Σφαίρα\"\n  STR_TORPEDO_LAUNCHER: \"Εκτοξευτής Τορπίλης\"\n  STR_SMALL_TORPEDO: \"Μικρή Τορπίλη\"\n  STR_LARGE_TORPEDO: \"Μεγάλη Τορπίλη\"\n  STR_PHOSPHOROUS_TORPEDO: \"Τορπίλη Φωσφόρου\"\n  STR_MAGNA_BLAST_GRENADE: \"Χειροβομβίδα Εκρηκτικής Δέσμης\"\n  STR_DYE_GRENADE: \"Χειροβομβίδα Χρώματος\"\n  STR_PARTICLE_DISTURBANCE_GRENADE: \"Χειροβομβίδα Διαταραχής Σωματιδίων\"\n  STR_MAGNA_PACK_EXPLOSIVE: \"Δυναμίτηδα Εκρηκτικής Δέσμης\"\n  STR_PARTICLE_DISTURBANCE_SENSOR: \"Αισθητήρας Κίνησης Σωματιδίων\"\n  STR_MEDI_KIT: \"Κουτί Α' Βοηθειών\"\n  STR_MC_DISRUPTOR: \"Καταλύτης Μ.Ε.\"\n  STR_THERMAL_TAZER: \"Θερμικό Τέιζερ\"\n  STR_GAUSS_PISTOL: \"Gauss Πιστόλι\"\n  STR_GAUSS_PISTOL_CLIP: \"Γεμιστήρας Πιστολιού Gauss\"\n  STR_GAUSS_RIFLE: \"Τουφέκι Gauss\"\n  STR_GAUSS_RIFLE_CLIP: \"Γεμιστήρας Τουφεκίου Gauss\"\n  STR_HEAVY_GAUSS: \"Πολυβόλο Gauss\"\n  STR_HEAVY_GAUSS_CLIP: \"Γεμιστήρας Πολυβόλου Gauss\"\n  STR_SONIC_CANNON: \"Ηχητικό Κανόνι\"\n  STR_CANNON_POWER_CLIP: \"Γεμηστήρας για Ηχητικό Κανόνι\"\n  STR_SONIC_BLASTA_RIFLE: \"Ηχητικό Τουφέκι\"\n  STR_BLASTA_POWER_CLIP: \"Γεμηστήρας για Ηχητικό Τουφέκι\"\n  STR_SONIC_PISTOL: \"Ηχητικό Πιστόλι\"\n  STR_PISTOL_POWER_CLIP: \"Γεμηστήρας για Ηχητικό Πιστόλι\"\n  STR_DISRUPTOR_PULSE_LAUNCHER: \"Εκτοξευτής Διαταραχής Παλμών\"\n  STR_DISRUPTOR_AMMO: \"Σφαίρα Διαταρακτικού\"\n  STR_THERMAL_SHOK_LAUNCHER: \"Εκτοξευτής Θερμικού Σοκ\"\n  STR_THERMAL_SHOK_BOMB: \"Βόμβα Θερμικού Σοκ\"\n  STR_SONIC_PULSER: \"Ήχος Παλμικού Κύματος\"\n  STR_ZRBITE: \"Zrbite\"\n  STR_MC_READER: \"Αναγώστης Μ.Ε.\"\n  STR_VIBRO_BLADE: \"Λεπίδα Δόνησης\"\n  STR_THERMIC_LANCE: \"Θερμική Λεπίδα\"\n  STR_HEAVY_THERMIC_LANCE: \"Βαριά Θερμική Λεπίδα\"\n  STR_AQUATOID_CORPSE: \"Πτώμα Υδρόβιου\"\n  STR_GILLMAN_CORPSE: \"Πτώμα Ανθρώπου του Γιλλ\"\n  STR_LOBSTERMAN_CORPSE: \"Πτώμα Ανθρώπου Αστακού\"\n  STR_TASOTH_CORPSE: \"Πτώμα Τάσοθ\"\n  STR_CALCINITE_CORPSE: \"Πτώμα Καλσινίτη\"\n  STR_DEEP_ONE_CORPSE: \"Πτώμα Βαθύ Ον\"\n  STR_BIODRONE_CORPSE: \"Συντρίμμια Βιο-Ντρον\"\n  STR_TENTACULAT_CORPSE: \"Πτώμα Τεντακουλάτ\"\n  STR_TRISCENE_CORPSE: \"Πτώμα Τρισκένου\"\n  STR_HALLUCINOID_CORPSE: \"Πτώμα Υπναγωγικού\"\n  STR_XARQUID_CORPSE: \"Πτώμα Ζαρκουίντ\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"Δεν υπάρχουν αρκετά πυρομαχικά για το ΥΟΣ{SMALLLINE}Κάθε ΥΟΣ απαιτεί {0} {1}.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Ανεπαρκή εφόδια για πλήρη ανεφοδιασμό ομάδας\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Πρέπει να ερευνήσεις {NEWLINE}{0}{NEWLINE} προκειμένου να παράγεις {NEWLINE}{1}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"Οι εξωγήινοι έχουν καταστρέψει την ανυπεράσπιστη βάση {0}\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"Οι περίπολοι της X-Com εντόπισαν μια αποικία εξωγήινων στο {0}\"\n  STR_STANDOFF: \"ΚΡΑΤΑ ΑΠΟΣΤΑΣΗ\"\n  STR_CAUTIOUS_ATTACK: \"ΠΡΟΣΕΚΤΙΚΗ ΕΠΙΘΕΣΗ\"\n  STR_STANDARD_ATTACK: \"ΚΑΝΟΝΙΚΗ ΕΠΙΘΕΣΗ\"\n  STR_AGGRESSIVE_ATTACK: \"ΔΥΝΑΜΙΚΗ ΕΠΙΘΕΣΗ\"\n  STR_DISENGAGING: \"ΑΠΕΜΠΛΟΚΗ\"\n  STR_UFO_HIT: \"ΤΟ ΕΞΩΓΗΙΝΟ ΥΠΟΒΡΥΧΙΟ ΧΤΥΠΗΘΗΚΕ!\"\n  STR_UFO_CRASH_LANDS: \"ΤΟ ΕΞΩΓΗΙΝΟ ΥΠΟΒΡΥΧΙΟ ΚΑΤΑΡΡΙΦΘΗΚΕ!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Σμίκρυνση μόνο όταν Κρατάς Απόσταση\"\n  STR_UFO_RETURN_FIRE: \"ΕΞΩΓΗΙΝΟ ΥΠΟΒΡΥΧΙΟ ΑΝΤΑΠΩΔΙΔΕΙ ΠΥΡΑ!\"\n  STR_INTERCEPTOR_DAMAGED: \">>> ΙΠΤΑΜΕΝΟ ΥΠΟΒΡΥΧΙΟ ΕΧΕΙ ΒΛΑΒΗ<<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> ΙΠΤΑΜΕΝΟ ΥΠΟΒΡΥΧΙΟ ΚΑΤΑΣΤΡΑΦΗΚΕ<<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"ΕΞΩΓΗΙΝΟ ΙΠΤΑΜΕΝΟ ΥΠΟΒΡΥΧΙΟ ΞΕΦΕΥΓΕΙ!\"\n  STR_LONG_RANGE_DETECTION: \"Εντοπισμός ευρείας ζώνης\"\n  STR_STORES_UC: \"ΑΠΟΘΗΚΕΣ\"\n  STR_DIFFICULTY_LEVEL: \"Επίπεδο Δυσκολίας\"\n  STR_INTERCEPT: \"ΑΝΑΧΑΙΤΙΣΗ\"\n  STR_BASES: \"ΒΑΣΕΙΣ\"\n  STR_GRAPHS: \"ΓΡΑΦΙΜΑΤΑ\"\n  STR_UFOPAEDIA_UC: \"ΟΥΦΟΠΑΙΔΕΙΑ\"\n  STR_OPTIONS_UC: \"ΕΠΙΛΟΓΕΣ\"\n  STR_FUNDING_UC: \"ΧΡΗΜΑΤΟΔΟΤΗΣΗ\"\n  STR_5_SECONDS: \"5 δευτ.\"\n  STR_1_MINUTE: \"1 Λεπτό\"\n  STR_5_MINUTES: \"5 Λεπτ.\"\n  STR_30_MINUTES: \"30 Λεπ.\"\n  STR_1_HOUR: \"1 Ώρα\"\n  STR_1_DAY: \"1 Μέρα\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"Πίνακας Επίδοσης X-Com\"\n  STR_ENTER_NAME: \"Καταχώρηση Ονόματος\"\n  STR_PERFORMANCE_RATING: \"Αξιολόγηση Απόδοσης\"\n  STR_VICTORY_DATE: \"Ημερομηνία Νίκης\"\n  STR_CHEMICAL_FLARE: \"Χημική-φωτοβολίδα\"\n  STR_CHEMICAL_FLARE_UFOPEDIA: \"Αυτή η συμπαγής συσκευή παράγει ένα φωτεινό φλας σε οποιοδήποτε βάθος ή σε ξηρά επιφάνεια. Αυτό φωτίζει μονάδες του εχθρού που βρίσκονται κοντά στο φλας κατά τις αποστολές στη βαθιά θάλασσα ή τη νύχτα.\"\n  STR_MONTHLY_COSTS: \"Μηνιαία Έξοδα\"\n  STR_CRAFT_RENTAL: \"Μισθωμένο Ιπτάμενο Υοβρύχιο\"\n  STR_SALARIES: \"Μισθοί\"\n  STR_BASE_MAINTENANCE: \"Συντήρηση Βάσης\"\n  STR_COST_PER_UNIT: \"Κόστος/μονάδα\"\n  STR_QUANTITY: \"Ποσότητα\"\n  STR_TOTAL: \"Σύνολο\"\n  STR_IN_PSIONIC_TRAINING: \"Στην Μ.Ε. Εμφύτευση\"\n  STR_FRONT_ARMOR: \"Μπροστινή Θωράκιση\"\n  STR_LEFT_ARMOR: \"Αριστερή Θωράκιση\"\n  STR_RIGHT_ARMOR: \"Δεξιά Θωράκιση\"\n  STR_REAR_ARMOR: \"Πίσω Θωράκιση\"\n  STR_UNDER_ARMOR: \"Κάτω Θωράκιση\"\n  STR_ROUNDS: \"ΒΟΛΕΣ\"\n  STR_UNIT: \"ΜΟΝΑΔΑ> {0}\"\n  STR_ENERGY: \"ΕΝΕΡΓΕΙΑ\"\n  STR_MORALE: \"ΗΘΙΚΟ\"\n  STR_ARMOR_: \"ΠΑΝΟΠΛΙΑ> {0}\"\n  STR_FRONT_ARMOR_UC: \"ΜΠΡΟΣΤΑ ΘΩΡΑΚΙΣΗ\"\n  STR_LEFT_ARMOR_UC: \"ΑΡΙΣΤΕΡΗ ΘΩΡΑΚΙΣΗ\"\n  STR_RIGHT_ARMOR_UC: \"ΔΕΞΙΑ ΘΩΡΑΚΙΣΗ\"\n  STR_REAR_ARMOR_UC: \"ΠΙΣΩ ΘΩΡΑΚΙΣΗ\"\n  STR_SKILLS: \"ΙΚΑΝΟΤΗΤΕΣ> {0}\"\n  STR_LEVEL: \"ΕΠΙΠΕΔΟ> {0}\"\n  STR_HEAD: \"ΚΕΦΑΛΗ\"\n  STR_TORSO: \"ΚΟΡΜΟΣ\"\n  STR_RIGHT_ARM: \"ΔΕΞΙ ΧΕΡΙ\"\n  STR_LEFT_ARM: \"ΑΡΙΣΤΕΡΟ ΧΕΡΙ\"\n  STR_RIGHT_LEG: \"ΔΕΞΙ ΠΟΔΙ\"\n  STR_LEFT_LEG: \"ΑΡΙΣΤΕΡΟ ΠΟΔΙ\"\n  STR_PAIN_KILLER: \"ΠΑΥΣΙΠΟΝΟ\"\n  STR_STIMULANT: \"ΔΙΕΓΕΡΤΙΚΟ\"\n  STR_HEAL: \"ΕΠΟΥΛΩΣΗ\"\n  STR_TIME_UNITS_SHORT: \"ΧΜ>{ALT}{0}\"\n  STR_WEIGHT: \"Βάρος>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"Αντιδρ.>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"Μ.Ικαν>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"Μ.Δυν>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Εξωγήινο Εξάρτημα\"\n  STR_AMMO_ROUNDS_LEFT: \"Πυρομαχικά:{NEWLINE}ROUNDS{NEWLINE}LEFT={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"ΠΟΝΟΣ>{ALT}{0}{ALT}{NEWLINE}ΕΝΕΣΗ>{ALT}{1}{ALT}{NEWLINE}ΙΑΣΗ>{ALT}{2}\"\n  STR_THROW: \"Ρήξε\"\n  STR_AUTO_SHOT: \"Αυτόματη Βολή\"\n  STR_SNAP_SHOT: \"Γρήγορη Βολή\"\n  STR_AIMED_SHOT: \"Στοχ/μένη Βολή\"\n  STR_STUN: \"Αναισθησία\"\n  STR_PRIME_GRENADE: \"Όπλισε Χειροβομβίδα\"\n  STR_USE_SCANNER: \"Χρήση Αισθητήρα Απ.\"\n  STR_USE_MEDI_KIT: \"Χρήση Πρώτων Βοηθειών\"\n  STR_LAUNCH_MISSILE: \"Εκτόξευση Τορπίλης\"\n  STR_ACCURACY_SHORT: \"Ευσ>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Ανεπαρκείς Μονάδες Χρόνου!\"\n  STR_NOT_ENOUGH_ENERGY: \"Ανεπαρκής Ενέργεια!\"\n  STR_NO_ROUNDS_LEFT: \"Χωρίς πυρομαχικά!\"\n  STR_NO_AMMUNITION_LOADED: \"Χωρίς Πυρομαχικά!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Λάθος Πυρομαχικό για αυτο το Όπλο!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"Το όπλο είναι ήδη γεμάτο!\"\n  STR_NO_LINE_OF_FIRE: \"Καμία Γραμμή Βολής!\"\n  STR_GRENADE_IS_ACTIVATED: \"Η χειροβομβίδα ενεργοποιήθηκε!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Η χειροβομβίδα απενεργοποιήθηκε!\"\n  STR_THERE_IS_NO_ONE_THERE: \"Δεν είναι κανείς εκεί!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Η χρήση εξωγήινων ευρημάτων είιναι αδύνατη προτού αναλυθούν!\"\n  STR_OUT_OF_RANGE: \"Εκτός Εμβέλειας!\"\n  STR_UNABLE_TO_THROW_HERE: \"Αδύνατο να ρίξει εκεί\"\n  STR_SET_TIMER: \"Θέσε χρονοδιακόπτη\"\n  STR_HIDDEN_MOVEMENT: \"ΚΡΥΦΕΣ ΚΙΝΗΣΕΙΣ\"\n  STR_TURN: \"ΓΥΡΟΣ> {0}\"\n  STR_SIDE: \"ΠΛΕΥΡΑ> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Πάτησε κουμπί για συνέχεια\"\n  STR_MIND_CONTROL: \"Μοριακός Έλεγχος\"\n  STR_PANIC_UNIT: \"Εμπλοκή Εμφυτεύματος\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Επίθεση κατά του Ηθικού Επιτυχής\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Έλεγχος Εμφυτεύματος Επιτυχής\"\n  STR_HAS_GONE_BERSERK_MALE: \"Ο/Η {0}{NEWLINE} τρελάθηκε\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"Ο/Η {0}{NEWLINE} τρελάθηκε\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}πανικοβλήθηκε\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}πανικοβλήθηκε\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Εξωγήινοι\"\n  STR_RIGHT_HAND: \"ΔΕΞΙ ΧΕΡΙ\"\n  STR_LEFT_HAND: \"ΑΡΙΣΤΕΡΟ ΧΕΡΙ\"\n  STR_RIGHT_SHOULDER: \"ΔΕΞΙΟΣ ΩΜΟΣ\"\n  STR_LEFT_SHOULDER: \"ΑΡΙΣΤΕΡΟΣ ΩΜΟΣ\"\n  STR_BACK_PACK: \"ΣΑΚΙΔΙΟ\"\n  STR_BELT: \"ΖΩΝΗ\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}είναι ύπο Μοριακό Έλεγχο\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}είναι ύπο Μοριακό Έλεγχο\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}έχασε τισ αισθήσεις\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}έχασε τισ αισθήσεις\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}πέθανε από θανάσιμο τράυμα\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}πέθανε από θανάσιμο τράυμα\"\n  STR_USE_MIND_PROBE: \"Χρήση Αναγνώστη M.Ε.\"\n  STR_FATAL_WOUNDS: \"ΘΑΝΑΣΙΜΑ ΤΡΑΥΜΑΤΑ\"\n  STR_UNDER_ARMOR_UC: \"ΚΑΤΩ ΘΩΡΑΚΙΣΗ\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Μονάδες Χρόνου φυλαγμένες για Γρήγορη Βολή\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Μονάδες Χρόνου φυλαγμένες για Αυτόματη Βολή\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Μονάδες Χρόνου φυλαγμένες για Στοχευμένη Βολή\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Μονάδες Χρόνου φυλαγμένες για Γονάτισμα\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"ΜΧ φυλαγμένες για Γονάτισμα και Πύρ\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} Μονάδες στο X-Com Craft\"\n    other: \"{N} Μονάδες στο X-Com Craft\"\n  STR_UNITS_OUTSIDE:\n    one: \"{N} Μονάδες έμειναν έξω\"\n    other: \"{N} Μονάδες έμειναν έξω\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} Μονάδες στην είσοδο\"\n    other: \"{N} Μονάδες στην είσοδο\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} Μονάδες σε έξοδο στόχου\"\n    other: \"{N} Μονάδες σε έξοδο στόχου\"\n  STR_ABORT_MISSION_QUESTION: \"Ματαίωση Αποστολής;\"\n  STR_CORPSE: \"Πτώμα\"\n  STR_UNLOAD_CRAFT: \"Ξεφόρτωσε\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}σκοτώθηκε\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}σκοτώθηκε\"\n  STR_HIT_MELEE: \"Χτύπημα\"\n  STR_GROUND: \"ΕΔΑΦΟΣ\"\n  STR_LIVING_QUARTERS_PLURAL: \"Κοιτώνες\"\n  STR_LIST_ITEM: \"ΑΝΤΙΚΕΙΜΕΝΟ\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"Όλοι οι εξωγήινη πέθαναν στη σύγκρουση,{NEWLINE}Αυτόματη ανάκτηση ξεκίνησε\"\n  STR_RESET: \"Επαναφορά\"\n  STR_MEMORIAL: \"Μνημείο\"\n  STR_DATE_UC: \"ΗΡΕΜΟΜΗΝΙΑ\"\n  STR_SOLDIERS_RECRUITED_UC: \"Επιλαχόντες ΥΔΡΟΝΑΥΤΕΣ>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"ΧΑΜΕΝΟΙ ΥΔΡΟΝΑΥΤΕΣ>{ALT}{0}\"\n  STR_REMOVE_SELECTED: \"Αφαίρεση Επιλεγμένου\"\n  STR_LIVE_ALIENS: \"Ζωντανά{NEWLINE}Δείγματα\"\n  STR_DEAD_ALIENS: \"Απορριφθέντα{NEWLINE}Δείγματα\"\n  STR_UNDER_INTERROGATION: \"Δείγμα{NEWLINE}Υπο Μελετη\"\n  STR_CONTAINMENT_EXCEEDED: \"ΥΠΕΡΒΑΣΗ ΧΩΡΟΥ ΚΡΑΤΗΣΗΣ ΕΞΩΓΕΝΩΝ!{SMALLLINE}Ανεπαρκής χώρος περιορισμού στο {0}. Πρέπει να αφαιρέσετε τους πλεονάζοντες εξωγήινους από τον περιορισμό (οι οποίοι θα πεθάνουν στη συνέχεια).\"\n  STR_MANAGE_CONTAINMENT: \"Διαχείριση Μονάδας περιορισμού Εξωγήινων\"\n  STR_STORAGE_EXCEEDED: \"ΥΠΕΡΒΑΣΗ ΑΠΟΘΗΚΕΥΤΙΚΟΥ ΧΩΡΟΥ!{SMALLLINE}Ανεπαρκής χώρος αποθήκευσης στο {0}. Πρέπει να πουλήσετε τα περιττά αντικείμενα.\"\n  STR_GO_TO_BASE: \"Πήγαινε στη Βάση\"\n  STR_MELEE_ACCURACY: \"ΑΚΡΙΒΕΙΑ ΜΑΧΗΣ ΣΩΜΑ ΜΕ ΣΩΜΑ\"\n  STR_SELL_PRODUCTION: \"ΠΩΛΗΣΗ\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Και τα δυο χέρια πρέπει να είναι άδεια!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Δεν υπάρχουν αρκετά στοιχεία για αντιγραφή προτύπου!\"\n  STR_UNLOAD_WEAPON: \"Αφόπληση όπλου\"\n  STR_ALL_ITEMS: \"Ολα τα αντικείμενα\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"ΔΕΝ ΕΠΙΤΡΕΠΕΤΑΙ ΑΛΛΟΣ ΕΞΟΠΛΙΣΜΟΣ ΣΤΟ ΚΑΤΑΣΤΡΩΜΑ!{SMALLLINE}Επιτρέπεται να πάρετε έως και {N} είδη εξοπλισμού σε αυτό το υποβρύχιο.\"\n    other: \"ΔΕΝ ΕΠΙΤΡΕΠΕΤΑΙ ΑΛΛΟΣ ΕΞΟΠΛΙΣΜΟΣ ΣΤΟ ΚΑΤΑΣΤΡΩΜΑ!{SMALLLINE}Επιτρέπεται να πάρετε έως και {N} είδη εξοπλισμού σε αυτό το υποβρύχιο.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}ΚΕΝΤΡΟ ΕΛΕΓΧΟΥ ΚΑΤΑΣΤΡΕΦΘΗΚΕ{NEWLINE}Προχωρήστε στην είσοδο και ματαιώστε.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"Οι Άκουα-εγκαταστάσεις X-Com δεν μπορούν να κατασκευαστούν στην ξηρά.\"\n  STR_UNABLE_TO_ENGAGE_DEPTH: \"ΑΔΥΝΑΤΗ Η ΠΡΟΣΕΓΗΣΗ ΕΧΘΡΟΥ{NEWLINE}ΣΕ ΑΥΤΟ ΤΟ ΒΑΘΟΣ\"\n  STR_UNABLE_TO_ENGAGE_AIRBORNE: \"ΑΔΥΝΑΤΗ Η ΠΡΟΣΕΓΗΣΗ ΕΧΘΡΟΥ{NEWLINE}ΠΟΥ ΕΙΝΑΙ ΣΤΟΝ ΑΕΡΑ\"\n  STR_UNDERWATER_EQUIPMENT: \"Ο εξοπλησμός δεν λειτουργεί έξω απο το νερό!\"\n  STR_LAND_EQUIPMENT: \"Ο εξοπλησμός δεν λειτουργεί μέσα στο νερό!\"\n  STR_LEVEL_SHORT: \"L{0}\"\n  STR_PERSONNEL: \"Προσωπικό\"\n  STR_CRAFT_ARMAMENT: \"Χειροτεχνία & Οπλισμός\"\n  STR_COMPONENTS: \"Εξαρτήματα\"\n  STR_SOLDIERS_RECRUITED: \"Επιλαχόντες Υδροναύτες \"\n  STR_SOLDIERS_LOST: \"Χαμένοι Υδροναύτες\"\n  STR_TOTAL_UFOS: \"Εντοπίστηκαν ιπτάμενα υποβρύχια\"\n  STR_TOTAL_ALIEN_BASES: \"Εξωγήινες αποικίες που εντοπίστηκαν\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"MST\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"MSK\"\n  FEMALE_CIVILIAN: \"Πολίτης, θυλικιά\"\n  MALE_CIVILIAN: \"Πολίτης, Αρσενικός\"\n  DOCKER_CIVILIAN: \"Πολίτης, Λιμενεργάτης\"\n  SAILOR_CIVILIAN: \"Πολίτης, Ναυτικός\"\n  STR_BIODRONE_MELEE_WEAPON: \"Βιο-Ντρον Κοντινή Μάχη\"\n  HALLUCINOID_WEAPON: \"Όπλο Υπναγωγικού\"\n  STR_LOBSTERMAN_MELEE_WEAPON: \"Όπλο Αστακάνθρωπου\"\n  CALCINITE_WEAPON: \"Όπλο Καλσινίτη\"\n  DEEP_ONE_WEAPON: \"Όπλο Βαθύ Ον\"\n  STR_TRISCENE_MELEE_WEAPON: \"Όπλο Τρισκένου\"\n  STR_TRIBIO_SONIC_WEAPON: \"Εξωγήινο Ηχητικό Όπλο\"\n  XARQUID_WEAPON: \"Όπλο Ζαρκουίντ\"\n  TENTACULAT_WEAPON: \"Όπλο Τεντακουλάτ\"\n  ZOMBIE_WEAPON: \"Όπλο Ζόμπι\"\n  ALIEN_PSI_WEAPON: \"Εξωγήινο Όπλο Μ.Ε.\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/en-GB.yml",
    "content": "en-GB:\n  STR_LEVIATHAN_UFOPEDIA: \"A TRANSPORT AND INTERCEPT FLYING SUB, WITH EXTREME DEPTH CAPABILITY. A SUPERB SYNTHESIS OF ALIEN AND HUMAN TECHNOLOGY, UTILISING ION PROPULSION SYSTEMS AND MAGNETIC ARRAY NAVIGATION.\"\n  STR_BARRACUDA_UFOPEDIA: \"THE BRITISH HYDROSPACE BARRACUDA, POWERED BY SUPER-HEATED LASER ENGINES. ONE OF THE FASTEST INTERCEPT SHIPS IN THE WORLD, CAPABLE OF SUBMERSIBLE AND ATMOSPHERIC FLIGHT, A KEY CRAFT IN THE COMING BATTLE.\"\n  STR_HAMMERHEAD_UFOPEDIA: \"A TRANSPORT AND INTERCEPT CRAFT. A REPLICATION OF MAGNETIC ARRAY SYSTEMS IN AN X-COM SHIP. ALTHOUGH SMALL, ITS' DESIGN IS A BREATHTAKING TECHNICAL ACHIEVEMENT.\"\n  STR_TRITON_UFOPEDIA: \"THE TRITON, AN ASSAULT SQUAD TRANSPORTER, FITTED WITH FULL ATMOSPHERIC AND AQUATIC FLIGHT ENGINES. ITS LARGE CAPACITY AND ROBUST CONSTRUCTION ENSURES IT IS THE MAINSTAY OF THE X-COM FLEET.\"\n  STR_MANTA_UFOPEDIA: \"MANTA HIGH SPEED CRAFT, A ONE-MAN INTERCEPT FLYING SUBMARINE CLOSELY RESEMBLING ION-POWERED ALIEN SHIPS. A HIGHLY EFFECTIVE STRIKE CRAFT IN THE ESCALATING CONFLICT.\"\n  STR_AJAX_UFOPEDIA: \"THE AJAX TORPEDO IS THE STANDARD WEAPON OF UNDERSEA COMBAT THE WORLD OVER. EMPLOYED AS AN ACCURATE AND POWERFUL DETERRENT.\"\n  STR_DUP_HEAD_UFOPEDIA: \"DEPLETED URANIUM PELLET HEADED WEAPON TECHNOLOGY IS RELATIVELY NEW, AND THIS IS THE FIRST COMMERCIAL AQUATIC WEAPON SYSTEM TO EMPLOY IT FULLY.\"\n  STR_CRAFT_GAS_CANNON_UFOPEDIA: \"A COMPRESSED GAS POWERED CANNON SYSTEM FIRING SOLID BOLTS WITH HIGH ARMOUR PIERCING CAPABILITY.\"\n  STR_PWT_CANNON_UFOPEDIA: \"THE PULSE WAVE TORPEDO UTILIZES A SUPERHEATED FUEL SYSTEM AND AN EXTREMELY DENSE WARHEAD WHICH CAN PUNCH THROUGH MOST ALLOYS.\"\n  STR_GAUSS_CANNON_UFOPEDIA: \"THE GAUSS WEAPON IS NEWLY DEVELOPED X-COM TECHNOLOGY. THIS SYSTEM'S PARTICLE ACCELERATOR IS POWERED BY A COMPACT, LIQUID NITROGEN COOLED, FUSION REACTOR.\"\n  STR_SONIC_OSCILLATOR_UFOPEDIA: \"A POWERFUL AUDITORY OSCILLATOR CREATES WAVES OF SONIC FORCE. DESTROYING THE TARGET BY VIBRATING ITS MOLECULAR BONDS APART.\"\n  STR_AQUATOID_UFOPEDIA: \"The Aquatoid Race is an ancient society, having existed millennia before man's first faltering steps upon the world. Their compact form and bulbous features are a throwback to their space faring brethren, the Sectoids. Their power is based on the powerful Molecular Control technology. The Aquatoid race seeks to propagate its sterile race by genetic modification, the ideal subjects being human beings. Experiments have spawned numerous hybrid races.\"\n  STR_AQUATOID_AUTOPSY: \"Aquatoid autopsy\"\n  STR_AQUATOID_AUTOPSY_UFOPEDIA: \"A detailed analysis of this creature allows us to make some basic assumptions. It is a Sectoid, our former foes, but changed by surgical methods and implants to be an aquatic creature. Vestigial lungs allow the breathing of air and limited surface mobility. There are cybernetic implants throughout the body, enhancing the strength of its atrophied limbs and the function of its organs. As all the members of this race are identical, we may hypothesize that these creatures are clones.\"\n  STR_GILLMAN_UFOPEDIA: \"Almost human, a strange creature who appears to be a reptilian humanoid, very closely related to man. This creature is extremely powerful and fast in the undersea world. Gillmen are a fully fledged race, there being male and female specimens of varying ages. They are unlike the majority of the underwater aliens as they bear none of the signs of genetic alteration or surgical deformation. It is possible we are looking at some ancient branch of our own species.\"\n  STR_GILLMAN_AUTOPSY: \"Gillman autopsy\"\n  STR_GILLMAN_AUTOPSY_UFOPEDIA: \"Once surgery began it became clear this is no alien, but an Earth born creature, an ancient pre-historic race that was thought destroyed at the very moment mammals became dominant. In a time when dinosaurs roamed these creatures lived, the Gillmen- amphibious, intelligent and strong. The cataclysm that ended the reptile rule on this planet forced these creatures into a symbiotic relationship with the newly arrived aliens. A small electronic device is lodged in the skulls of the creatures.\"\n  STR_LOBSTERMAN_UFOPEDIA: \"This is a staggering creature, taller than a man and boasting six limbs, it resembles nothing more than an aquatic Demon. The similarities between this creature and the Earth lobster have earned it the nickname of Lobsterman with the X-Com troops. This is a behemoth of the deep. A carefully designed fighting creature of incredible strength and practically invulnerable to missile fire. Its pincers alone can crush steel.\"\n  STR_LOBSTERMAN_AUTOPSY: \"Lobsterman autopsy\"\n  STR_LOBSTERMAN_AUTOPSY_UFOPEDIA: \"Once past its virtually indestructible shell the creature is an amazing construction. Powerful muscles ripple around a titanium skeleton, a sophisticated targeting system with multi-band scanning ability is hooked directly into the creature's brain. Its multiple eyes are protected by harder than steel plastics and it is clear that when well deployed by their masters these creatures are all but unstoppable. Buried deep within its body are devices of unknown construction and function.\"\n  STR_TASOTH_UFOPEDIA: \"These agile and fast enemies are a mainstay of the alien army. Hundreds are birthed, in massive breeding vats deep in the heart of the Alien colonies. Vastly more powerful than a man, the Tasoth is a true alien and its behaviour and carnivorous nature unmatched on the planet. The Tasoth often forms the spearhead of an alien attack and never seems to shrink from the fight even in the face of overwhelming odds.\"\n  STR_TASOTH_AUTOPSY: \"Tasoth autopsy\"\n  STR_TASOTH_AUTOPSY_UFOPEDIA: \"Dissection revealed a cybernetic organism possessed of strange power. Inside the body cavity is a small power unit, but no identifiable organs. The power is transmitted throughout the body by a Bio-electric transmission system. The whole body lacks bones or any other supporting structure. Once dead the power stops and the creature becomes a lifeless rag doll of oozing alien flesh and fluids. The only other internal construction is a pair of ceramic cells, which if energized briefly revive the creature.\"\n  STR_DEEP_ONE_UFOPEDIA: \"The Deep One is a biological nightmare, a cross breed, produced by the mind warping experiments of the Aquatoids. We have encountered several variations of this creature. After extensive research we conclude that these are manufactured by the invaders. Swelling their ranks when fresh human stock has been captured. Each of these sub-humans is armed with an electrical energy discharge powerful enough to kill an aquanaut.\"\n  STR_DEEP_ONE_AUTOPSY: \"Deep One autopsy\"\n  STR_DEEP_ONE_AUTOPSY_UFOPEDIA: \"The creature is a graft of man and alien organism. The human brain is massively altered to accommodate control electronics and the Alien cortex. All vestiges of the human body seem lost save one: the eyes. The surgical graft appears to allow the alien foetus to consume the human host as it grows. The tough skin of the creature appears to be a non-organic, metallic mesh, extremely strong and flexible. The resulting cross breed is strong, fast and utterly under the control of the aliens.\"\n  STR_BIODRONE_UFOPEDIA: \"The Bio-drone is a creation only an alien mind could conceive of. It is a brain, (human or alien) suspended in amniotic fluids and connected to a powered base unit that can fly on land or below water. Each Bio-drone is armed with a powerful auditory disruptor, part machine and part organism. Some of our scientists have suggested that the weapon is driven by the host organism's original vocal cords. Highly accurate and tenacious these super guard dogs are widely used by the aliens to protect valuable assets.\"\n  STR_BIODRONE_AUTOPSY: \"Bio-drone autopsy\"\n  STR_BIODRONE_AUTOPSY_UFOPEDIA: \"The hypothesis that the auditory disruptor is a biological device are true. This unfortunate creature literally screams its enemies to death. Every example has massive surgical trauma scars and is severely mutilated. The aliens appear to butcher the brain into obedience. Most of the cortex's used in the creatures are alien in origin, but nothing can compare to the horror of finding a human based unit. The Bio-drones are powered by an ION engine and incorporate some form of remote control system.\"\n  STR_TENTACULAT_UFOPEDIA: \"Not even the depths of a Lovecraftian nightmare could spawn such as this indescribable creature. No comparison to any Earth animal exists, the environment that could produce such as this is beyond imagination. Armed with long tentacles the Tentaculat paralyzes its victims then transmutes them into mindless things. These progeny can cause death on touch, even through armour. The Tentaculat is the most fearsome alien yet encountered by X-Com.\"\n  STR_TENTACULAT_AUTOPSY: \"Tentaculat autopsy\"\n  STR_TENTACULAT_AUTOPSY_UFOPEDIA: \"The autopsy reveals small cybernetic implants are lodged in the creature's large brain. The vision system is a complex combination of visible light and thermal imaging acquisition. Even in the inky depths of the ocean this monster can navigate with unerring accuracy. There are vestigial organs that seem to be the bare minimum for survival. Each creature has a small stomach with an external connector, it is logical to assume the being is fed by direct nutrient input by its masters.\"\n  STR_CALCINITE_UFOPEDIA: \"Like the diving suits of lost mariners these aliens stalk the seabed for the unwary. A vicious swipe by the creature's stronger than steel claws can be enough to send the best divers to the bottom. Swirling around in the face mask a gelatinous green form can be seen. No hint of the real creature can be divined from the often lethal encounters we have had with them.\"\n  STR_CALCINITE_AUTOPSY: \"Calcinite autopsy\"\n  STR_CALCINITE_AUTOPSY_UFOPEDIA: \"Once the armoured suit is stripped away the Calcinite is revealed to be a huge amorphous blob of protoplasm. No visible brain, limbs or sensory organs exist, a small metallic component resides deep in the liquid body. Once dead we can only guess at the creature's nature. An inexplicable enigma of our alien enemies.\"\n  STR_TRISCENE_UFOPEDIA: \"This bipedal reptile is a throwback to the age of the Dinosaurs. It seems to be a Cretaceous creature in every sense save its ability to survive in water and on land. These creatures are slung with weapons pods and have a jaw lined with huge metallic teeth. Often these monsters have been at the core of the alien attack forces as the Aliens launch assaults upon the land. A heavyweight and potent weapon, the Tasoth commanders deploy them with lethal efficiency.\"\n  STR_TRISCENE_AUTOPSY: \"Triscene autopsy\"\n  STR_TRISCENE_AUTOPSY_UFOPEDIA: \"Once subjected to the scientist's knife the Triscene reveals that it is an ancient creature, supplemented with cybernetic implants and weapons systems. Its tiny brain is supplemented by a small computer module mounted in the control harness all the creatures wear. A tough natural skin, a predatory instinct enhanced by additional weapons makes this a lethal opponent in all environments.\"\n  STR_HALLUCINOID_UFOPEDIA: \"Having harvested the oceans the aliens have bred these huge Earth creatures as a weapon. Do not be lulled into a false sense of security when facing these harmless looking sailors of the deeps. Possessed of a close combat icy strike, the Hallucinoid is a deadly foe.\"\n  STR_HALLUCINOID_AUTOPSY: \"Hallucinoid autopsy\"\n  STR_HALLUCINOID_AUTOPSY_UFOPEDIA: \"Nested in the many layers of the gelatinous body of this organism is a powerful chemical freezer, its' main offensive capability. The soft and supple skin of the Hallucinoid seems susceptible to heat based attacks. Often this mutant is found in the company of its masters, the Aquatoids.\"\n  STR_XARQUID_UFOPEDIA: \"Another modified Earth invertebrate, the Xarquid is a creature of great beauty and danger. The swift swimming gargantuan hides a devastating arsenal of weapons, a smothering ink spray and an ionized particle blast. Since our first encounters with this powerful creature we have been wary of its power and its controllers the vengeful Gillmen.\"\n  STR_XARQUID_AUTOPSY: \"Xarquid autopsy\"\n  STR_XARQUID_AUTOPSY_UFOPEDIA: \"This overgrown Nautilus has been made huge on a diet of Alien drugs and surgical alterations. Perverted beyond the scope of nature, the Gillmen have added mechanical control systems to the creature and now none of the creature's original nature exists. Deployed as an organic weapons platform, the Xarquids tough shell and mobility make it a formidable opponent.\"\n  STR_ION_BEAM_ACCELERATORS_UFOPEDIA: \"Alien flying submarines rely on complex power systems to drive them at incredible speed through the deeps. The basis for their technology is the ION DISPLACER, utilizing Zrbite as a catalyst, the engines displace 100 times their own volume in water per second. This enormous power means that the aliens are capable of outrunning most Earth subs. We can replicate this system of propulsion using aqua-plastics and Zrbite power cells.\"\n  STR_MAGNETIC_NAVIGATION_UFOPEDIA: \"These units generate a spherical multi-layer magnetic field, which the array projects up to 1000m around the sub. The Alien navigators are directly linked into the machines and feel their way around the invisible world beneath the waves. The interface system operates using Alien modified cerebral matter that communicates directly with the operator's brain via a neural link.\"\n  STR_ALIEN_SUB_CONSTRUCTION_UFOPEDIA: \"Each vessel has a chameleon-like structure, carefully modelled on sea creatures, and constructed of Aqua Plastics. Each submarine functions as an organism: crew and craft in harmony. Most of these systems can be replicated and a hybrid technology can be evolved to allow us to move up to the same technological level.\"\n  STR_ALIEN_CRYOGENICS_UFOPEDIA: \"The innumerable Aliens that have lain hidden on the Earth are held in suspended animation, cryogenically frozen. All the creatures are sealed into units, their body temperature reduced to a point where bodily functions are all but stopped. An examination of the units so far reveals the unbelievable time periods that the bodies have been kept suspended for, some over 60 million years.\"\n  STR_ALIEN_CLONING_UFOPEDIA: \"Many of the Aliens we have captured are identical even down to their DNA, duplicates in every way. Cell samples are placed into the units from the frozen gene banks of the Aliens. Some units contain humans or body parts. It is possible that another use for these cloning units is to create some Alien-human hybrid.\"\n  STR_ALIEN_LEARNING_ARRAYS_UFOPEDIA: \"Utilizing Molecular Control Implants in the skulls of all Aliens these machines inject information directly into the brain. Freshly cloned Aliens are brought to these units and have racial memories and all scientific or combat information downloaded into their blank minds.\"\n  STR_ALIEN_IMPLANTER_UFOPEDIA: \"This unit is used to fit Aliens with Molecular Control Implants, fertilize reproducing races, and insert or remove organs and electronics from any creature. The process was thought to be done on subdued patients, but the subject is very aware of the process and unfortunately human anatomy seems to fit the unit perfectly.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"We now have the evidence to work out why Aliens capture humans. They are not food, they are not fertilized with Alien embryos, rather they form the basis of a range of creatures and control systems. Alien technology is based on a common mind, a shared intellect and the human brain is the ideal receptacle for these systems. Human brain tissue is used in most of the Alien biological computer storage and retrieval systems, the remains are used for building and for breeding.\"\n  STR_AQUA_PLASTICS_UFOPEDIA: \"Alien submarines and structures utilize an incredibly strong, flexible and durable material for the majority of their construction. Aqua plastics are complex multi-bonded and Zrbite catalysed materials. Dense, yet light, the substance has strength above even Titanium or Kevlar.\"\n  STR_ZRBITE_UFOPEDIA: \"This is an alloy of Alien origin, part gold part Alien Bio-material. When utilized as a power source, small quantities will generate more power than a nuclear unit of 10 times the size. It is beyond our technical ability to replicate this material as most of its constituents are Alien in origin.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"The Aliens strike all across the globe, with ruthless efficiency. We cannot pin down their source. Could it be in some ocean deep too impenetrable for us to locate? Not all the organisms we have encountered are Alien, some are very old, some are from evolutionary paths long thought extinct. We are dealing with a menace that has been sleeping for millennia, a subtle symbiosis of human and Alien. Deep in the oceans there lie ancient sites used by the Aliens to contact their stellar cousins. Each of these twelve sites contains a Synomium device, a powerful Alien technology. Now with their war machine on the march the Aliens are re-activating these sites to widen their Molecular Control net, we must destroy these sites at all costs.\"\n  STR_THE_ULTIMATE_THREAT_UFOPEDIA: \"Sixty-five million years ago a vast colony ship was sent to the Earth from a distant Alien world. As the enormous craft approached the infant planet a massive and violent solar flare caused a navigation systems failure. Crippled and failing the vast bulk plummeted through the stratosphere to emerge into Cretaceous skies. On the Earth innumerable species of life strained their gazes skywards as their nemesis ploughed into the planet. A vast cloud of dust clogged the atmosphere and as the land cooled so the dominant life, the mighty dinosaurs, perished. But the 400 billion tonnes of T'leth was not destroyed in the impact, sophisticated super computers initiated a cryogenic sleep cycle for the creatures deep in its holds.  As the aeons passed the computers woke parties of Aliens to attempt communication with their stellar cousins, all in vain for the core of the Alien power slept on.\"\n  STR_TLETH_THE_ALIEN_CITY: \"T'leth the Alien's City\"\n  STR_TLETH_THE_ALIEN_CITY_UFOPEDIA: \"T'leth the huge Alien colony ship lies embedded in the Sigsbee Deep, in the Gulf of Mexico.  At the Heart of the city is an Alien horror, so vile and so powerful that not even death can claim it. In a chamber of Alien metal lies the sleeping form of the great dreamer, the Ultimate Alien. Raising T'leth above the waves will begin his re-animation cycle, and once risen he will be unstoppable. Although not alive and somehow not dead the Alien mind controls the Alien army. The weird technology of molecular control connects all Aliens to the One mind and the One mind to all the Aliens. Genetically mutated Alien/human foetuses supply the Alien mind with energy and form the link between the ruler and his subjects. The myth of the Ultimate Alien has existed in the hearts and minds of humankind for centuries, the sea has always hidden the ultimate truth.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"CENTRE ON SITE-TIME=5 Secs\"\n  STR_CANCEL_UC: \"CANCEL\"\n  STR_NONE: \"None\"\n  STR_UNKNOWN: \"Unknown\"\n  STR_POOR: \"Poor\"\n  STR_AVERAGE: \"Average\"\n  STR_GOOD: \"Good\"\n  STR_EXCELLENT: \"Excellent\"\n  STR_BUILD_NEW_BASE_UC: \"BUILD NEW BASE\"\n  STR_BASE_INFORMATION: \"BASE INFORMATION\"\n  STR_EQUIP_CRAFT: \"EQUIP SUBMARINE\"\n  STR_BUILD_FACILITIES: \"BUILD FACILITIES\"\n  STR_RESEARCH: \"RESEARCH\"\n  STR_MANUFACTURE: \"MANUFACTURE\"\n  STR_TRANSFER_UC: \"TRANSFER\"\n  STR_PURCHASE_RECRUIT: \"PURCHASE/RECRUIT\"\n  STR_SACK: \"SACK\"\n  STR_SELL_SACK_UC: \"SELL/SACK\"\n  STR_GEOSCAPE_UC: \"GEOSCAPE\"\n  STR_NAME: \"Name\"\n  STR_AREA: \"Area\"\n  STR_BUILD_NEW_BASE: \"Build New Base\"\n  STR_CANCEL: \"Cancel\"\n  STR_COST_UC: \"COST>\"\n  STR_CONSTRUCTION_TIME_UC: \"CONSTRUCTION TIME>\"\n  STR_DAY:\n    one: \"{N} day\"\n    other: \"{N} days\"\n  STR_HOUR:\n    one: \"{N} hour\"\n    other: \"{N} hours\"\n  STR_MAINTENANCE_UC: \"MAINTENANCE>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Installation\"\n  STR_CURRENT_RESEARCH: \"CURRENT RESEARCH\"\n  STR_SCIENTISTS_AVAILABLE: \"Scientists Available>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Scientists Allocated>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Laboratory Space Available>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"RESEARCH PROJECT\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"SCIENTISTS ALLOCATED\"\n  STR_PROGRESS: \"PROGRESS\"\n  STR_NEW_PROJECT: \"New Project\"\n  STR_CANCEL_PROJECT: \"CANCEL PROJECT\"\n  STR_NEW_RESEARCH_PROJECTS: \"NEW RESEARCH PROJECTS\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"SCIENTISTS AVAILABLE>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"LABORATORY SPACE AVAILABLE>{ALT}{0}\"\n  STR_INCREASE: \"Increase\"\n  STR_DECREASE: \"Decrease\"\n  STR_START_PROJECT: \"START PROJECT\"\n  STR_CURRENT_PRODUCTION: \"CURRENT PRODUCTION\"\n  STR_ENGINEERS_AVAILABLE: \"Technicians Available>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Technicians Allocated>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Workshop Space Available>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Current Funds>{ALT}{0}\"\n  STR_ITEM: \"ITEM\"\n  STR_ENGINEERS__ALLOCATED: \"Technicians Allocated\"\n  STR_UNITS_PRODUCED: \"Units Produced\"\n  STR_TOTAL_TO_PRODUCE: \"Total to Produce\"\n  STR_COST__PER__UNIT: \"Cost{NEWLINE}per{NEWLINE}Unit\"\n  STR_DAYS_HOURS_LEFT: \"Days/Hours Left\"\n  STR_NEW_PRODUCTION: \"New Production\"\n  STR_PRODUCTION_ITEMS: \"Production Items\"\n  STR_CATEGORY: \"CATEGORY\"\n  STR_START_PRODUCTION: \"START PRODUCTION\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} Technician hours to produce one unit\"\n  STR_COST_PER_UNIT_: \"Cost per unit>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Work Space Required>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"SPECIAL MATERIALS REQUIRED\"\n  STR_ITEM_REQUIRED: \"ITEM REQUIRED\"\n  STR_UNITS_REQUIRED: \"UNITS REQUIRED\"\n  STR_UNITS_AVAILABLE: \"UNITS AVAILABLE\"\n  STR_STOP_PRODUCTION: \"STOP PRODUCTION\"\n  STR_ENGINEERS_AVAILABLE_UC: \"TECHNICIANS AVAILABLE>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"WORKSHOP SPACE AVAILABLE>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"MONTHLY PROFIT>{ALT}{0}\"\n  STR_INCREASE_UC: \"INCREASE\"\n  STR_DECREASE_UC: \"DECREASE\"\n  STR_UNITS_TO_PRODUCE: \"Units to Produce\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Purchase/Hire Personnel\"\n  STR_COST_OF_PURCHASES: \"Cost of Purchases>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"COST PER UNIT\"\n  STR_QUANTITY_UC: \"QUANTITY\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"PERSONNEL AVAILABLE:PERSONNEL TOTAL>\"\n  STR_SOLDIERS: \"Aquanauts\"\n  STR_SCIENTISTS: \"Scientists\"\n  STR_ENGINEERS: \"Technicians\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"SPACE USED:SPACE AVAILABLE>\"\n  STR_LIVING_QUARTERS: \"Living Quarters\"\n  STR_STORES: \"Stores\"\n  STR_LABORATORIES: \"Laboratories\"\n  STR_WORK_SHOPS: \"Work Shops\"\n  STR_HANGARS: \"Flying Sub Pens\"\n  STR_SHORT_RANGE_DETECTION: \"Short Range Sonar\"\n  STR_DEFENSE_STRENGTH: \"Defence Strength\"\n  STR_TRANSFERS_UC: \"TRANSFERS\"\n  STR_TRANSFERS: \"Transfers\"\n  STR_ARRIVAL_TIME_HOURS: \"Arrival Time (hours)\"\n  STR_COST_: \"Cost>{ALT}{0}\"\n  STR_AREA_: \"Area>{ALT}{0}\"\n  STR_BASE_NAME: \"Base Name?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"SELECT POSITION FOR AIR-LOCK\"\n  STR_TRANSFER: \"Transfer\"\n  STR_AMOUNT_TO_TRANSFER: \"AMOUNT TO TRANSFER\"\n  STR_SELECT_DESTINATION_BASE: \"Select Destination Base\"\n  STR_COST: \"Cost\"\n\n  STR_INTRO_1: \"Copyright 1995 MicroProse\"\n  STR_INTRO_2: \"Mars: The fall of Cydonia.\"\n  STR_INTRO_3: \"A triumphant X-Com, having destroyed the very core of the Alien war machine, blasts off for home. However, all is not dead in the ravaged Martian base.\"\n  STR_INTRO_4: \"A powerful tachyon beam streams from the rubble of the Cydonian nerve centre - hurtling through the void. Its destination............\"\n  STR_INTRO_5: \"Earth.\"\n  STR_INTRO_6: \"Deep in the ocean the beam strikes a long dormant receptor. Vast sleeping computers begin to stir. In the deep, beyond the sight of humans, vast chambers of sleeping Aliens begin their long re-animation cycle.\"\n  STR_INTRO_7: \"2040: An ignorant Earth. The terrors of the Alien war are forgotten. But, in the lost and hidden places of the ocean the Alien hordes are ready - ready to topple humankind and take over the world.\"\n  STR_INTRO_8: \"The Aliens strike against humankind; seeking specimens for their warped experiments; raiding the globe for valuable minerals and resources; and plundering from the seas. Then, the Aliens set their sights above the waves.\"\n  STR_INTRO_9: \"Powerful flying subs of strange design ply the oceans - looking, searching, hunting.........\"\n  STR_INTRO_10: \"Finding prey they attack.\"\n  STR_INTRO_11: \"Weird new weapons are brought to bear against a defenceless world. We are utterly at the mercy of the Alien threat.{NEWLINE}Only one organisation can save us; but, we turned our backs on them long ago......\"\n  STR_INTRO_12: \"X-COM Experimental Underwater Facility\"\n  STR_INTRO_13: \"'Mayday! Mayday!' 'This is the transatlantic liner Hyperion'. 'We are under attack'. 'Mayday! Mayd............'\"\n  STR_INTRO_14: \"'Command Control to Sub Pen One: Open ocean doors', 'deploy Barracuda Zero One. We have an Alien attack situation - condition Red'.{NEWLINE}'I repeat: condition Red'\"\n  STR_INTRO_15: \"The Aliens are ruthless in their efficiency....\"\n  STR_INTRO_16: \"...unerring in their accuracy\"\n  STR_INTRO_17: \"'Barracuda Zero One to base' - 'approaching what's left of the Hyperion'.\"\n  STR_INTRO_18: \"'Decelerating'.{NEWLINE}'Two metres'{NEWLINE}'One metre'{NEWLINE}'All aquanauts prepare for immediate deployment'.\"\n  STR_INTRO_19: \"...........'Airlock cleared'...'approaching wreckage'.{NEWLINE}'Holy!'{NEWLINE}'Are you picking up those creatures on my suit cam?'\"\n\n  STR_GAMEOVER_1: \"We have failed, the Aliens have annihilated our last hopes of salvation.{NEWLINE}X-Com is destroyed and the Earth is laid at the feet of the ancient enemy.\"\n  STR_GAMEOVER_2: \"T'leth thunders high into the stratosphere and begins to move across the face of the world.  Dispensing death and harvesting the remnants of the human race. Deep in its bowels the murderous Alien mind begins to rouse itself.\"\n  STR_GAMEOVER_3: \"In the capital cities of all nations desperate plans are drawn up.  All is for nought, without the technology afforded by the X-Com research project our weapons are ineffectual.\"\n  STR_GAMEOVER_4: \"The Aliens set up bases at the polar caps and begin to melt the ice, the world will become a vast sea. The remains of the human race are rounded up and utilised in vile breeding experiments for unknown Alien ends. Skies darken and a mighty pestilence is upon the lands of the Earth.\"\n  STR_GAMEOVER_5: \"We can offer no resistance to the new world order, those that try meet a fiery fate at the hands of incomprehensible Alien weapons. For the rest of us no such blessed release, mother Earth becomes an Alien world and humankind is lost beneath a crawling horror.\"\n\n  STR_OUTRO_1: \"The Tomb, ravaged and decimated, a bubbling roar comes from the casket in its centre.{NEWLINE}Fools you will all perish....................\"\n  STR_OUTRO_2: \".................none can escape.\"\n  STR_OUTRO_3: \"A massive explosion erupts from the tomb and rips through the city, debris and smoke fill the air. The plans of the Aliens are foiled........\"\n  STR_OUTRO_4: \"The twisting hugeness of T'leth begins to rupture. Flames and smoke spew from its gleaming spires and adamantium halls.\"\n  STR_OUTRO_5: \"The mighty Alien fastness tumbles towards the sea, the screams of tortured metal and souls fills the air. No longer will the Great Dreamer dream of conquering the world.\"\n  STR_OUTRO_6: \"One final ear-splitting concussion of sound and T'leth tears itself apart.{NEWLINE}The Alien threat is gone, the Earth is cleansed..................\"\n  STR_OUTRO_7: \"A sleepy blue-green planet, in a distant corner of the galaxy.\"\n  STR_OUTRO_8: \"The near future, a safe place to be.\"\n  STR_OUTRO_9: \"The Alien menace to the Earth has been long vanquished.\"\n  STR_OUTRO_10: \"Vast metropolis like cities house the teeming billions of humankind.\"\n  STR_OUTRO_11: \"The deeds of X-Com and the Alien wars are the stuff of children's stories.\"\n  STR_OUTRO_12: \"But legends have always had a habit of containing a grain of truth............\"\n\n  STR_RISE_1: \"T'leth, called many things in many legends from many lands.\"\n  STR_RISE_2: \"With an explosive scream that reverberates across the globe T'leth begins to rise from the seabed.\"\n  STR_RISE_3: \"The huge edifice surges through the waters of the Gulf of Mexico.\"\n  STR_RISE_4: \"400 billion tonnes of Alien metal, the mighty Alien city wherein lies the sleeping body of the Ultimate Alien. Imprisoned on earth for 65 million years this vile space God begins to stir.\"\n  STR_RISE_5: \"The waters boil and churn as the tomb of the Great Dreamer emerges into the light................\"\n  STR_RISE_6: \".........a light that will be short lived unless X-Com can destroy the Alien war machine.\"\n\n  STR_YOU_HAVE_FAILED: \"You have failed to stop the Alien war machine. The funding organisations, disillusioned with your ability try to negotiate a non military solution with the Aliens. The Invaders have a very different agenda and soon the whole world is aware of the truth...\"\n\n  STR_TOTAL_UC: \"TOTAL\"\n  STR_INCOME: \"Income\"\n  STR_EXPENDITURE: \"Expenditure\"\n  STR_MAINTENANCE: \"Maintenance\"\n  STR_BALANCE: \"Balance\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"Alien Activity in Seas\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"Alien Activity in Zones\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"X-Com Activity in Seas\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"X-Com Activity in Zones\"\n  STR_FINANCE: \"Finance\"\n  STR_DATE_FIRST: \"{0}st\"\n  STR_DATE_SECOND: \"{0}nd\"\n  STR_DATE_THIRD: \"{0}rd\"\n  STR_DATE_FOURTH: \"{0}th\"\n  STR_FINANCE_THOUSANDS: \"$1000's\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Not enough special materials to produce{NEWLINE}{0}{NEWLINE}at{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Not enough money to produce{NEWLINE}{0}{NEWLINE}at{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"Production of{NEWLINE}{0}{NEWLINE}at{NEWLINE}{1}{NEWLINE}is complete\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"Construction of{NEWLINE}{0}{NEWLINE}at{NEWLINE}{1}{NEWLINE}is complete\"\n  STR_OK_5_SECONDS: \"OK - 5 secs\"\n  STR_RESEARCH_COMPLETED: \"Research Completed\"\n  STR_VIEW_REPORTS: \"VIEW REPORTS\"\n  STR_WE_CAN_NOW_RESEARCH: \"We can now research\"\n  STR_WE_CAN_NOW_PRODUCE: \"We can now produce\"\n  STR_SUNDAY: \"SUNDAY\"\n  STR_MONDAY: \"MONDAY\"\n  STR_TUESDAY: \"TUESDAY\"\n  STR_WEDNESDAY: \"WEDNESDAY\"\n  STR_THURSDAY: \"THURSDAY\"\n  STR_FRIDAY: \"FRIDAY\"\n  STR_SATURDAY: \"SATURDAY\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Not enough {0} to refuel {1} at {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Not enough {0} to rearm {1} at {2}\"\n  STR_UFO_IS_NOT_RECOVERED: \"ALIEN SUB is not recovered\"\n  STR_UFO_IS_RECOVERED: \"ALIEN SUB is recovered\"\n  STR_CRAFT_IS_LOST: \"Flying Sub is lost\"\n  STR_TERROR_CONTINUES: \"Alien Activity continues\"\n  STR_ALIENS_DEFEATED: \"Aliens defeated\"\n  STR_BASE_IS_LOST: \"Base is lost\"\n  STR_BASE_IS_SAVED: \"Base is saved\"\n  STR_ALIEN_BASE_STILL_INTACT: \"Alien Colony still intact\"\n  STR_ALIEN_BASE_DESTROYED: \"Alien Colony destroyed\"\n  STR_ALIENS_KILLED: \"ALIENS KILLED\"\n  STR_ALIEN_CORPSES_RECOVERED: \"ALIEN CORPSES RECOVERED\"\n  STR_LIVE_ALIENS_RECOVERED: \"LIVE ALIENS RECOVERED\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"ALIEN ARTEFACTS RECOVERED\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"ALIEN COLONY CONTROL DESTROYED\"\n  STR_ALIEN_SYNOMIUM_DEVICE_DESTROYED: \"ALIEN SYNOMIUM DEVICE DESTROYED\"\n  STR_ALIEN_SYNOMIUM_DEVICE_FAILED: \"FAILED TO DESTROY SYNOMIUM DEVICE\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"CIVILIANS KILLED BY ALIENS\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"CIVILIANS KILLED BY X-COM OPERATIVES\"\n  STR_CIVILIANS_SAVED: \"CIVILIANS SAVED\"\n  STR_XCOM_OPERATIVES_KILLED: \"X-COM OPERATIVES KILLED\"\n\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"X-COM OPERATIVES MISSING IN ACTION\"\n  STR_TANKS_DESTROYED: \"X-COM WEAPONS PLATFORM DESTROYED\"\n  STR_XCOM_CRAFT_LOST: \"X-COM SUBMARINE LOST\"\n  STR_UFO_RECOVERY: \"ALIEN SUB RECOVERY\"\n  STR_ALIEN_BASE_RECOVERY: \"ALIEN COLONY RECOVERY\"\n  STR_BASE_UNDER_ATTACK: \"{0} under attack!\"\n  STR_BASE_DEFENSES_INITIATED: \"BASE DEFENCES INITIATED\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"SHIELDS REPEL ALIEN SUB!\"\n  STR_FIRING: \"FIRING\"\n  STR_HIT: \"HIT!\"\n  STR_UFO_DESTROYED: \"ALIEN SUB DESTROYED!\"\n  STR_MISSED: \"MISSED!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Sell Items/Sack Personnel\"\n  STR_VALUE_OF_SALES: \"VALUE OF SALES> {ALT}{0}\"\n  STR_FUNDS: \"FUNDS> {ALT}{0}\"\n  STR_SELL_SACK: \"Sell/Sack\"\n  STR_VALUE: \"Value\"\n  STR_CRAFT_: \"FLYING SUB> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n\n  STR_UFO_CRASH_RECOVERY: \"ALIEN SUB CRASH RECOVERY\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"EXTREME CAUTION - There will be Aliens in the submarine and around the site. This mission will be completed when all enemy units have been eliminated or neutralized. Recovery of Alien Sub remains, technology and alien corpses can then be initiated. To abort the mission return X-Com aquanauts to the submarine and click on the 'Abort Mission' icon.\"\n  STR_UFO_GROUND_ASSAULT: \"ALIEN SUBMARINE ASSAULT\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"Explore the touchdown site and, if possible, gain entry to the Alien Sub. The mission will be successful when all enemy units have been eliminated or neutralized. Recovery of the Alien Sub, artefacts and Alien corpses can then be initiated. To abort the mission return X-Com aquanauts to the submarine and click on the 'Abort Mission' icon.\"\n  STR_BASE_DEFENSE: \"BASE DEFENCE\"\n  STR_BASE_UC_: \"BASE> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"An Alien vessel has touched down nearby. Our base is in severe danger. As per standard procedure all non combat personnel and functional X-Com subs have been evacuated. Aliens will enter the base via Submarine Pen gates or the air-lock. Defend the base and its vital installations at all costs - this is a fight to the death. If you click on the 'abort mission' icon you will concede defeat and lose the base.\"\n\n  STR_ALIEN_COLONY_ATTACK_MISSION: \"ALIEN COLONY ATTACK MISSION\"\n  STR_ALIEN_BASE_ASSAULT: \"ALIEN COLONY PART ONE\"\n  STR_ALIEN_COLONY_P1_BRIEFING: \"This mission is a raid on an Alien colony site. There are 2 levels to the site, get all the aquanauts to the glowing exit in the first complex and click on the 'Abort Mission' icon to proceed. Any equipment left behind will stay on the seabed until the 2nd section is resolved. To quit, place aquanauts into the Submarine and click on the 'Abort Mission' icon.\"\n  STR_ALIEN_COLONY_P2: \"ALIEN COLONY PART TWO\"\n  STR_ALIEN_COLONY_P2_BRIEFING: \"Having negotiated the first level and entered the core of the colony. The mission is to now destroy the control centre, the Synomium Device, or eliminate all Aliens. To abort place all aquanauts on the start point and click on 'Abort Mission' icon. All viable X-Com equipment will be returned to base. \"\n\n  STR_ALIENS_LAUNCH_PORT_TERROR: \"ALIENS LAUNCH{NEWLINE}PORT ATTACK ON\"\n  STR_PORT_TERROR: \"ALIENS LAUNCH PORT ATTACK\"\n  STR_PORT_TERROR_BRIEFING: \"Aliens have launched an attack against surface sites. The port and its civilian population have been put at risk. Your squad must eliminate all Aliens and protect the innocent bystanders from this Alien incursion. To quit, place aquanauts into the flying sub and click on the 'Abort Mission' icon.\"\n\n  STR_ALIENS_LAUNCH_ISLAND_TERROR: \"ALIENS LAUNCH{NEWLINE}ISLAND ATTACK ON\"\n  STR_ISLAND_TERROR: \"ALIENS LAUNCH ISLAND ATTACK\"\n  STR_ISLAND_TERROR_BRIEFING: \"Aliens have launched an attack against surface sites. The island and its civilian population have been put at risk. Your squad must eliminate all Aliens and protect the innocent bystanders from this Alien incursion. To quit, place aquanauts into the flying sub and click on the 'Abort Mission' icon.\"\n\n  STR_ALIENS_ATTACK_SHIPPING_ROUTE: \"ALIENS ATTACK{NEWLINE}SHIPPING ROUTE\"\n  STR_CARGO_SHIP_P1: \"CARGO SHIP PART ONE\"\n  STR_CARGO_SHIP_P2: \"CARGO SHIP PART TWO\"\n  STR_CRUISE_SHIP_P1: \"CRUISE SHIP PART ONE\"\n  STR_CRUISE_SHIP_P2: \"CRUISE SHIP PART TWO\"\n  STR_SHIP_RESCUE_MISSION: \"SHIP RESCUE MISSION\"\n  STR_SHIP_RESCUE_P1_BRIEFING: \"This mission is a bug hunt, eliminate all Alien units on the ship, and preserve the lives of any civilians onboard. The Aliens are dispersed above and below decks, secure the upper decks before entering the lower ones. To quit, place aquanauts into the flying sub and click on the 'Abort Mission' icon.\"\n  STR_SHIP_RESCUE_P2_BRIEFING: \"Now the upper deck is clear proceed to the lower decks. Using the cargo lift you descend into the hold. Your squad must eliminate all Aliens on this level to complete the mission. To abort place all aquanauts on the lift start point and click on 'Abort Mission' icon.\"\n\n  STR_ALIEN_ACTIVITY_DETECTED: \"ALIEN ACTIVITY DETECTED\"\n  STR_ALIEN_CONTACT_SITE_MISSION: \"ALIEN CONTACT SITE MISSION\"\n  STR_ARTIFACT_SITE_P1: \"ALIEN CONTACT SITE PART ONE\"\n  STR_ARTIFACT_SITE_P1_BRIEFING: \"This mission is a raid on a freshly activated Alien communications site. There are 2 levels to the site, the seabed with its Alien pyramids and a hidden Alien complex. Get all the aquanauts to the entrance of the complex and click on the 'Abort Mission' icon to proceed. To quit, place aquanauts into the flying sub and click on the 'Abort Mission' icon.\"\n  STR_ARTIFACT_SITE_P2: \"ALIEN CONTACT SITE PART TWO\"\n  STR_ARTIFACT_SITE_P2_BRIEFING: \"Having negotiated the Alien structures and entered the complex the mission goals are clear. Penetrate the heart of the Alien facility and destroy the Synomium Molecular Control Device to complete the mission. To abort place all aquanauts on the access lift start point and click on 'Abort Mission' icon.\"\n\n  STR_SIGSBEE_DEEP_MISSION: \"SIGSBEE DEEP MISSION{NEWLINE}ALIEN CITY LEVEL ONE\"\n  STR_TLETH_P1_BRIEFING: \"We are entering the unknown, from here on in there could be anything waiting for us. We know there are 2 further levels to the Alien city and your squad must race to the exit on this level to enter the next. Place all aquanauts on the exit and click the 'Abort Mission' icon to advance. Aborting elsewhere will terminate the mission.\"\n  STR_TLETH_ATTACK_MISSION: \"T'LETH ATTACK MISSION{NEWLINE}ALIEN CITY LEVEL TWO\"\n  STR_TLETH_P2_BRIEFING: \"Further into the unknown, from here on in there could be anything waiting for us. We know there is a further level to the Alien city and your squad must race to the exit on this level to enter the next. Place all aquanauts on the exit and click the 'Abort Mission' icon to advance. Aborting elsewhere will terminate the mission.\"\n  STR_FINAL_TLETH_MISSION: \"FINAL T'LETH MISSION{NEWLINE}ALIEN CITY LEVEL THREE\"\n  STR_TLETH_P3_BRIEFING: \"The end is in sight, from here on in we are searching for the crypt of the Ultimate Alien. Destroy the 8 power feeds to the tomb to finish off the Alien threat. Don't give up now! Aborting will terminate the mission.\"\n  STR_TLETH_P1: \"ALIEN CITY LEVEL ONE\"\n  STR_TLETH_P2: \"ALIEN CITY LEVEL TWO\"\n  STR_TLETH_P3: \"ALIEN CITY LEVEL THREE\"\n\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"NO FREE SUB PENS FOR CRAFT PRODUCTION!{SMALLLINE}Each Flying Sub assigned to a base, transferred to a base, purchased or constructed uses one Sub Pen. Build a new Sub Pen or transfer a sub to another base.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"NO FREE SUB PENS FOR PURCHASE!{SMALLLINE}Each Flying Sub assigned to a base, transferred to a base, purchased or constructed uses one Sub Pen. Build a new Sub Pen or transfer a sub to another base.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"NO FREE SUB PENS FOR TRANSFER!{SMALLLINE}Each Flying Sub assigned to a base, transferred to a base, purchased or constructed uses one Sub Pen. Build a new Sub Pen or transfer a sub to another base.\"\n  STR_CANNOT_BUILD_HERE: \"CANNOT BUILD HERE!{SMALLLINE}You must build next to an existing pod.\"\n  STR_NO_FREE_ACCOMODATION: \"NO FREE ACCOMMODATION!{SMALLLINE}The destination base does not have enough space in living quarters.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"NOT ENOUGH WORK SPACE AVAILABLE!{SMALLLINE}Build a new workshop or reduce work on other projects.\"\n  STR_NOT_ENOUGH_MONEY: \"NOT ENOUGH MONEY!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"NOT ENOUGH STORE SPACE!{SMALLLINE}Build a new store facility or transfer existing stores to other bases.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"NOT ENOUGH LIVING SPACE!{SMALLLINE}Build new living quarters or transfer personnel to other bases.\"\n  STR_LAUNCH_INTERCEPTION: \"LAUNCH INTERCEPTION\"\n  STR_CRAFT: \"CRAFT\"\n  STR_STATUS: \"STATUS\"\n  STR_BASE: \"BASE\"\n  STR_READY: \"READY\"\n  STR_OUT: \"OUT\"\n  STR_REPAIRS: \"REPAIRS\"\n  STR_REFUELLING: \"REFUELING\"\n  STR_REARMING: \"REARMING\"\n  STR_TARGET: \"TARGET: {0}\"\n  STR_WAY_POINT: \"WAY POINT\"\n  STR_ARE_YOU_SURE_CYDONIA: \"Are you sure you want to send this Sub on a mission to T'leth?\"\n  STR_YES: \"YES\"\n  STR_NO: \"NO\"\n  STR_SELECT_DESTINATION: \"SELECT DESTINATION\"\n  STR_CYDONIA: \"T'LETH\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"SELECT SITE FOR NEW BASE\"\n  STR_RETURN_TO_BASE: \"RETURN TO BASE\"\n  STR_SELECT_NEW_TARGET: \"SELECT NEW TARGET\"\n  STR_PATROL: \"PATROL\"\n  STR_STATUS_: \"STATUS>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"DAMAGED - RETURNING TO BASE\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"LOW FUEL - RETURNING TO BASE\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"MISSION COMPLETE - RETURNING TO BASE\"\n  STR_PATROLLING: \"PATROLLING\"\n  STR_TAILING_UFO: \"TAILING ALIEN SUB\"\n  STR_INTERCEPTING_UFO: \"INTERCEPTING ALIEN SUB-{0}\"\n  STR_RETURNING_TO_BASE: \"RETURNING TO BASE\"\n  STR_DESTINATION_UC_: \"DESTINATION: {0}\"\n  STR_BASE_UC: \"BASE>{ALT}{0}\"\n  STR_SPEED_: \"SPEED>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"MAXIMUM SPEED>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"DEPTH>{ALT}{0}\"\n  STR_AIRBORNE: \"AIRBORNE\"\n  STR_VERY_LOW: \"SHALLOW\"\n  STR_LOW_UC: \"NORMAL\"\n  STR_HIGH_UC: \"DEEP\"\n  STR_VERY_HIGH: \"VERY DEEP\"\n  STR_FUEL: \"FUEL>{ALT}{0}\"\n  STR_WEAPON_ONE: \"WEAPON-1>{ALT}{0}\"\n  STR_NONE_UC: \"NONE\"\n  STR_ROUNDS_: \"ROUNDS>{ALT}{0}\"\n  STR_WEAPON_TWO: \"WEAPON-2>{ALT}{0}\"\n\n  STR_INTERCEPTION_CRAFT: \"FLYING SUB\"\n  STR_BASE_: \"Base>{0}\"\n  STR_NAME_UC: \"NAME\"\n  STR_AMMO_: \"AMMO>{ALT}{0}\"\n  STR_CREW: \"CREW\"\n  STR_EQUIPMENT_UC: \"EQUIPMENT\"\n  STR_ARMOR: \"ARMOUR\"\n  STR_MAX: \"MAX>{ALT}{0}\"\n  STR_ROOKIE: \"Seaman\"\n  STR_SQUADDIE: \"Able Seaman\"\n  STR_SERGEANT: \"Ensign\"\n  STR_CAPTAIN: \"Lieutenant\"\n  STR_COLONEL: \"Commander\"\n  STR_COMMANDER: \"Captain\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Select Squad for {0}\"\n  STR_SORT_BY: \"SORT BY...\"\n  STR_ORIGINAL_ORDER: \"ORIGINAL ORDER\"\n  STR_MISSIONS2: \"MISSIONS\"\n  STR_KILLS2: \"KILLS\"\n  STR_WOUND_RECOVERY2: \"WOUND RECOVERY\"\n  STR_SPACE_AVAILABLE: \"SPACE AVAILABLE>{ALT}{0}\"\n  STR_SPACE_USED: \"SPACE USED>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"SPACE USED\"\n  STR_RANK: \"RANK\"\n  STR_WOUNDED: \"WOUNDED\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Equipment for {0}\"\n  STR_DEFENSE_VALUE: \"Defence Value\"\n  STR_HIT_RATIO: \"Hit Ratio\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}ready to{NEWLINE}touchdown near{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"Begin Mission?\"\n  STR_SELECT_ARMAMENT: \"Select Armament\"\n  STR_AMMUNITION_AVAILABLE: \"AMMUNITION AVAILABLE\"\n  STR_ARMAMENT: \"ARMAMENT\"\n  STR_NOT_AVAILABLE: \"N.A.\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"SELECT ARMOUR FOR{NEWLINE}{ALT}{0}\"\n  STR_TYPE: \"TYPE\"\n  STR_PLASTIC_AQUA_ARMOR_UC: \"PLASTIC AQUA ARMOUR\"\n  STR_ION_ARMOR_UC: \"ION ARMOUR\"\n  STR_MAGNETIC_ION_ARMOR_UC: \"MAGNETIC ION ARMOUR\"\n\n  STR_PLASTIC_AQUA_ARMOR_UFOPEDIA: \"This Armour utilizes the newly discovered Alien substance, Aqua-plastic, and ensures our Aquanauts are given a fighting chance against the Alien incursion\"\n  STR_ION_ARMOR_UFOPEDIA: \"A powerful new protection for Aquanauts, this armour is powered by an ION energy source and greatly amplifies the speed and strength of the wearer, it offers the best protection yet for combat troops.\"\n  STR_MAGNETIC_ION_ARMOR_UFOPEDIA: \"An enhancement for the ION armour incorporating the Magnetic Array technology to allow full freedom of movement in the aquatic environment.\"\n  STR_SELECT_ARMOR: \"Select Armour\"\n  STR_NORTH: \"NORTH\"\n  STR_NORTH_EAST: \"NORTH EAST\"\n  STR_EAST: \"EAST\"\n  STR_SOUTH_EAST: \"SOUTH EAST\"\n  STR_SOUTH: \"SOUTH\"\n  STR_SOUTH_WEST: \"SOUTH WEST\"\n  STR_WEST: \"WEST\"\n  STR_NORTH_WEST: \"NORTH WEST\"\n  STR_SELECT_ACTION: \"SELECT ACTION\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"CONTINUE INTERCEPTION PURSUIT\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"PURSUE WITHOUT INTERCEPTION\"\n  STR_VERY_LARGE: \"VERY LARGE\"\n  STR_LARGE: \"LARGE\"\n  STR_MEDIUM_UC: \"MEDIUM\"\n  STR_SMALL: \"SMALL\"\n  STR_VERY_SMALL: \"VERY SMALL\"\n  STR_GROUNDED: \"TOUCHED DOWN\"\n  STR_DETECTED: \"Detected\"\n  STR_SIZE_UC: \"SIZE\"\n  STR_ALTITUDE: \"DEPTH\"\n  STR_HEADING: \"HEADING\"\n  STR_SPEED: \"SPEED\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"CENTRE ON ALIEN SUB-TIME=5 Secs\"\n  STR_TRACKING_LOST: \"TRACKING LOST\"\n  STR_REDIRECT_CRAFT: \"REDIRECT CRAFT\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"GO TO LAST KNOWN ALIEN SUB POSITION\"\n  STR_UFO_: \"ALIEN SUB-{0}\"\n  STR_ALIEN_BASE_: \"ALIEN COLONY-{0}\"\n  STR_CRASH_SITE_: \"CRASH SITE-{0}\"\n  STR_LANDING_SITE_: \"TOUCHDOWN SITE-{0}\"\n  STR_WAY_POINT_: \"WAY POINT-{0}\"\n  STR_TERROR_SITE: \"TERROR SITE-{0}\"\n  STR_ARTIFACT_SITE: \"ARTEFACT SITE-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}has reached{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"Now patrolling\"\n  STR_ALIEN_ORIGINS: \"Alien Origins\"\n  STR_THE_ULTIMATE_THREAT: \"The Ultimate Threat\"\n  STR_TLETH_ALIEN_CITY: \"T'leth, the Alien's City\"\n  STR_UFOPAEDIA: \"UFOpaedia\"\n  STR_XCOM_CRAFT_ARMAMENT: \"X-COM CRAFT & WEAPONS\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"SUBMERSIBLE WEAPONS SYSTEMS\"\n  STR_WEAPONS_AND_EQUIPMENT: \"GENERAL EQUIPMENT\"\n  STR_ALIEN_ARTIFACTS: \"AQUATIC ARTEFACTS\"\n  STR_BASE_FACILITIES: \"X-COM FACILITIES\"\n  STR_ALIEN_LIFE_FORMS: \"ALIEN CREATURES\"\n  STR_ALIEN_RESEARCH_UC: \"ALIEN TECHNOLOGY\"\n  STR_UFO_COMPONENTS: \"NEW SUBMERSIBLE TECHNOLOGIES\"\n  STR_UFOS: \"ALIEN SUBMARINES\"\n  STR_SELECT_ITEM: \"SELECT ITEM\"\n  STR_ACCELERATION: \"ACCELERATION>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"FUEL CAPACITY>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"WEAPON PODS>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"DAMAGE CAPACITY>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"CARGO SPACE>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"SWS CAPACITY>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Damage\"\n  STR_RANGE: \"Range\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Accuracy\"\n  STR_RE_LOAD_TIME: \"Re-load time\"\n  STR_SECONDS: \"{0}s\"\n  STR_DAMAGE_ARMOR_PIERCING: \"ARMOUR PIERCING\"\n  STR_DAMAGE_INCENDIARY: \"PHOSPHOROUS\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"HIGH EXPLOSIVE\"\n  STR_DAMAGE_LASER_BEAM: \"GAUSS BEAM\"\n  STR_DAMAGE_PLASMA_BEAM: \"SONIC BEAM\"\n  STR_DAMAGE_STUN: \"FREEZE\"\n  STR_DAMAGE_MELEE: \"MELEE\"\n  STR_DAMAGE_ACID: \"ACID\"\n  STR_DAMAGE_SMOKE: \"SMOKE\"\n  STR_SHOT_TYPE: \"TYPE\"\n  STR_ACCURACY_UC: \"ACCURACY\"\n  STR_TIME_UNIT_COST: \"TU COST\"\n  STR_DAMAGE_UC: \"DAMAGE\"\n  STR_AMMO: \"AMMO\"\n  STR_SHOT_TYPE_AUTO: \"Auto\"\n  STR_SHOT_TYPE_SNAP: \"Snap\"\n  STR_SHOT_TYPE_AIMED: \"Aimed\"\n  STR_CONSTRUCTION_TIME: \"Construction Time\"\n  STR_CONSTRUCTION_COST: \"Construction Cost\"\n  STR_MAINTENANCE_COST: \"Maintenance Cost\"\n  STR_LOW: \"Low\"\n  STR_MEDIUM: \"Medium\"\n  STR_HIGH: \"High\"\n  STR_CRAFT_WEAPON: \"Sub Weapon\"\n  STR_CRAFT_AMMUNITION: \"Sub Ammunition\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Heavy Weapons System\"\n  STR_WEAPON: \"Weapon\"\n  STR_AMMUNITION: \"Ammunition\"\n  STR_EQUIPMENT: \"Equipment\"\n  STR_ALIEN_CORPSE: \"Alien Corpse\"\n  STR_UFO_COMPONENT: \"ALIEN SUB component\"\n  STR_PERSONAL_ARMOR: \"Personal Armour\"\n  STR_RAW_MATERIALS: \"Raw Materials\"\n  STR_HWP_SOLID_HARPOON_BOLTS: \"Solid Harpoon Bolts\"\n  STR_ALIEN: \"Alien\"\n\n  STR_AQUATOID: \"Aquatoid\"\n  STR_GILLMAN: \"Gill Man\"\n  STR_LOBSTERMAN: \"Lobster Man\"\n  STR_TASOTH: \"Tasoth\"\n  STR_CALCINITE: \"Calcinite\"\n  STR_DEEP_ONE: \"Deep One\"\n  STR_BIODRONE: \"Bio-drone\"\n  STR_TENTACULAT: \"Tentaculat\"\n  STR_TRISCENE: \"Triscene\"\n  STR_HALLUCINOID: \"Hallucinoid\"\n  STR_XARQUID: \"Xarquid\"\n  STR_ZOMBIE: \"Zombie\"\n\n  STR_LIVE_COMMANDER: \"Commander\"\n  STR_LIVE_NAVIGATOR: \"Navigator\"\n  STR_LIVE_MEDIC: \"Medic\"\n  STR_LIVE_TECHNICIAN: \"Technician\"\n  STR_LIVE_SQUAD_LEADER: \"Squad Leader\"\n  STR_LIVE_SOLDIER: \"Soldier\"\n  STR_LIVE_TERRORIST: \"Terrorist\"\n  STR_AQUATOID_COMMANDER: \"Aquatoid Commander\"\n  STR_AQUATOID_NAVIGATOR: \"Aquatoid Navigator\"\n  STR_AQUATOID_MEDIC: \"Aquatoid Medic\"\n  STR_AQUATOID_TECHNICIAN: \"Aquatoid Technician\"\n  STR_AQUATOID_SQUAD_LEADER: \"Aquatoid Squad Leader\"\n  STR_AQUATOID_SOLDIER: \"Aquatoid Soldier\"\n  STR_GILLMAN_COMMANDER: \"Gill Man Commander\"\n  STR_GILLMAN_TECHNICIAN: \"Gill Man Technician\"\n  STR_GILLMAN_SQUAD_LEADER: \"Gill Man Squad Leader\"\n  STR_GILLMAN_SOLDIER: \"Gill Man Soldier\"\n  STR_LOBSTERMAN_COMMANDER: \"Lobster Man Commander\"\n  STR_LOBSTERMAN_NAVIGATOR: \"Lobster Man Navigator\"\n  STR_LOBSTERMAN_TECHNICIAN: \"Lobster Man Technician\"\n  STR_LOBSTERMAN_SQUAD_LEADER: \"Lobster Man Squad Leader\"\n  STR_LOBSTERMAN_SOLDIER: \"Lobster Man Soldier\"\n  STR_TASOTH_SQUAD_LEADER: \"Tasoth Squad Leader\"\n  STR_TASOTH_SOLDIER: \"Tasoth Soldier\"\n  STR_CALCINITE_TERRORIST: \"Calcinite Terrorist\"\n  STR_DEEP_ONE_TERRORIST: \"Deep One Terrorist\"\n  STR_BIODRONE_TERRORIST: \"Bio-drone Terrorist\"\n  STR_TENTACULAT_TERRORIST: \"Tentaculat Terrorist\"\n  STR_TRISCENE_TERRORIST: \"Triscene Terrorist\"\n  STR_HALLUCINOID_TERRORIST: \"Hallucinoid Terrorist\"\n  STR_XARQUID_TERRORIST: \"Xarquid Terrorist\"\n\n  STR_ION_BEAM_ACCELERATORS: \"Ion-Beam Accelerators\"\n  STR_MAGNETIC_NAVIGATION: \"Magnetic Navigation\"\n  STR_ALIEN_SUB_CONSTRUCTION: \"Alien Sub Construction\"\n  STR_ALIEN_CRYOGENICS: \"Alien Cryogenics\"\n  STR_ALIEN_CLONING: \"Alien Cloning\"\n  STR_ALIEN_LEARNING_ARRAYS: \"Alien Learning Arrays\"\n  STR_ALIEN_IMPLANTER: \"Alien Implanter\"\n  STR_EXAMINATION_ROOM: \"Examination Room\"\n  STR_AQUA_PLASTICS: \"Aqua Plastics\"\n  STR_ALIEN_REANIMATION_ZONE: \"Alien Re-animation Zone\"\n\n  STR_PLASTIC_AQUA_ARMOR: \"Plastic Aqua-Armour\"\n  STR_ION_ARMOR: \"Ion Armour\"\n  STR_MAGNETIC_ION_ARMOR: \"Mag. Ion Armour\"\n  STR_HWP_AQUA_JET_MISSILES: \"Aqua Jet Torpedoes\"\n  STR_HWP_DISPLACER_PWT: \"P.W. Torpedo\"\n\n  STR_GAUSS_TECH: \"Gauss Technology\"\n  STR_NEW_FIGHTER_FLYING_SUB: \"New Fighter Flying Sub\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"New Fighter-Transporter\"\n  STR_THE_LATEST_FLYING_SUB: \"The Latest Flying Sub\"\n\n  STR_ARMOR_PIERCING: \"ARMOUR PIERCING\"\n  STR_COELACANTH_GAS_CANNON: \"Coelacanth/G. Cannon\"\n  STR_COELACANTH_AQUA_JET: \"Coelacanth/Aqua Jet\"\n  STR_COELACANTH_GAUSS: \"Coelacanth/Gauss\"\n  STR_DISPLACER_SONIC: \"Displacer/Sonic\"\n  STR_DISPLACER_PWT: \"Displacer/P.W.T.\"\n  STR_AJAX_LAUNCHER: \"Ajax Launcher\"\n  STR_DUP_HEAD_LAUNCHER: \"D.U.P. Head Launcher\"\n  STR_CRAFT_GAS_CANNON: \"Craft Gas Cannon\"\n  STR_PWT_CANNON: \"P.W.T. Cannon\"\n  STR_GAUSS_CANNON: \"Gauss Cannon\"\n  STR_GAUSS_CANNON_AMMO: \"Gauss Cannon Ammo\"\n  STR_SONIC_OSCILLATOR: \"Sonic Oscillator\"\n  STR_AJAX_TORPEDOES: \"Ajax Torpedoes\"\n  STR_DUP_HEAD_TORPEDOES: \"D.U.P. Head Torpedoes\"\n  STR_CRAFT_GAS_CANNON_ROUNDS_X50: \"Gas Rounds(x50)\"\n  STR_SONIC_WAVE: \"Sonic Wave\"\n  STR_PULSE_WAVE_TORPEDOES: \"P.W.T. Ammo\"\n  STR_SOLDIER: \"Aquanaut\"\n  STR_SCIENTIST: \"Scientist\"\n  STR_ENGINEER: \"Technician\"\n\n\n  STR_NORTH_ATLANTIC: \"North Atlantic\"\n  STR_SOUTH_ATLANTIC: \"South Atlantic\"\n  STR_NORTH_PACIFIC: \"North Pacific\"\n  STR_SOUTH_PACIFIC: \"South Pacific\"\n  STR_MEDITERRANEAN: \"Mediterranean\"\n  STR_SOUTH_CHINA_SEA: \"South China Sea\"\n  STR_INDIAN_OCEAN: \"Indian Ocean\"\n  STR_THE_EAST_SEA: \"Sea of Japan\"\n  STR_NORTH_SEA: \"North Sea\"\n  STR_CARRIBEAN: \"Caribbean\"\n  STR_ANTARCTIC: \"Antarctic\"\n  STR_ARCTIC: \"Arctic\"\n  STR_EURASIA: \"Eurasia\"\n  STR_NORTH_AMERICA: \"North America\"\n  STR_AFRICA: \"Africa\"\n\n  STR_MAXIMUM_SPEED: \"Maximum Speed\"\n  STR_TRANSMISSION_RESOLVER_UC: \"TRANSMISSION RESOLVER\"\n\n  STR_TRITON: \"TRITON\"\n  STR_HAMMERHEAD: \"HAMMERHEAD\"\n  STR_LEVIATHAN: \"LEVIATHAN\"\n  STR_BARRACUDA: \"BARRACUDA\"\n  STR_MANTA: \"MANTA\"\n  STR_UFO: \"ALIEN SUB\"\n  STR_AJAX: \"AJAX\"\n  STR_DUP_HEAD: \"D.U.P. HEAD\"\n  STR_CRAFT_GAS_CANNON_UC: \"CRAFT GAS CANNON\"\n  STR_PWT_CANNON_UC: \"P.W.T. CANNON\"\n  STR_GAUSS_CANNON_UC: \"GAUSS CANNON\"\n  STR_SONIC_OSCILLATOR_UC: \"SONIC OSCILLATOR\"\n  STR_DAMAGE_CAPACITY: \"Damage Capacity\"\n  STR_WEAPON_POWER: \"Weapon Power\"\n  STR_WEAPON_RANGE: \"Weapon Range\"\n\n  STR_AIR_LOCK: \"Air-Lock\"\n  STR_LABORATORY: \"Laboratory\"\n  STR_WORKSHOP: \"Workshop\"\n  STR_STANDARD_SONAR: \"Standard Sonar\"\n  STR_WIDE_ARRAY_SONAR: \"Wide Array Sonar\"\n  STR_TORPEDO_DEFENSES: \"Torpedo Defences\"\n  STR_GENERAL_STORES: \"General Stores\"\n  STR_ALIEN_CONTAINMENT: \"Alien Containment\"\n  STR_GAUSS_DEFENSES: \"Gauss Defences\"\n  STR_SONIC_DEFENSES: \"Sonic Defences\"\n  STR_PWT_DEFENSES: \"P.W.T. Defences\"\n# STR_BOMBARDMENT_SHIELD: \"Pressure Bombardment Shield\"\n# STR_MC_GENERATOR: \"Molecular Control Shield\"\n# STR_MC_LAB: \"Molecular Control Laboratory\"\n# short versions for the list?\n  STR_BOMBARDMENT_SHIELD: \"Bombardment Shield\"\n  STR_MC_GENERATOR: \"M.C. Generator\"\n  STR_MC_LAB: \"M.C.-Lab\"\n  STR_TRANSMISSION_RESOLVER: \"Transmission Resolver\"\n  STR_SUB_PEN: \"Sub Pen\"\n\n  STR_USA: \"USA\"\n  STR_ALASKA: \"ALASKA\"\n  STR_EU_SYNDICATE: \"EURO-SYNDICATE\"\n  STR_ARABIAN_BLOC: \"ARABIAN BLOC\"\n  STR_EGYPTIAN_CARTEL: \"EGYPTIAN CARTEL\"\n  STR_AFRICA_CORP: \"AFRICA CORP\"\n  STR_BRAZILIAN_UNION: \"BRAZILIAN UNION\"\n  STR_NEW_MEXICO: \"NEW MEXICO\"\n  STR_ASIAN_COALITION: \"ASIAN COALITION\"\n  STR_SCANDINAVIA: \"SCANDINAVIA\"\n  STR_NEO_JAPAN: \"NEO-JAPAN\"\n  STR_FREE_CHINA: \"FREE CHINA\"\n  STR_AUSTRALASIA: \"AUSTRALASIA\"\n  STR_FED_KOREA: \"FED KOREA\"\n  STR_EURASIA_UC: \"EURASIA\"\n  STR_ICELANDIC_UNION: \"ICELANDIC UNION\"\n  STR_TANK: \"Submersible Weapons System\"\n  STR_CIVILIAN: \"Civilian\"\n  STR_JAN: \"Jan\"\n  STR_FEB: \"Feb\"\n  STR_MAR: \"Mar\"\n  STR_APR: \"Apr\"\n  STR_MAY: \"May\"\n  STR_JUN: \"Jun\"\n  STR_JUL: \"Jul\"\n  STR_AUG: \"Aug\"\n  STR_SEP: \"Sep\"\n  STR_OCT: \"Oct\"\n  STR_NOV: \"Nov\"\n  STR_DEC: \"Dec\"\n  STR_INTERNATIONAL_RELATIONS: \"International Relations\"\n  STR_COUNTRY: \"Country\"\n  STR_FUNDING: \"Funding\"\n  STR_CHANGE: \"Change\"\n  STR_WEAPON_SYSTEMS: \"WEAPON SYSTEMS\"\n  STR_HWPS: \"SWSs\"\n  STR_DAMAGE_UC_: \"DAMAGE>{ALT}{0}\"\n\n  STR_AIR_LOCK_UFOPEDIA: \"The Air-lock allows equipment and personnel to be transferred into or out of an undersea base. It is always the first facility to be constructed at a new site. The Air-lock area is vulnerable to intrusion from any potential hostile force.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Each accommodation area provides for up to 50 personnel. The facilities are somewhat basic and functional.\"\n  STR_LABORATORY_UFOPEDIA: \"Fifty scientists can work in a single laboratory block. Laboratories are equipped with all the latest technologies for research into materials, biochemistry and weaponry. X-Com has access to all the best research labs throughout the world, both civilian and military.\"\n  STR_WORKSHOP_UFOPEDIA: \"A workshop contains all the equipment necessary to manufacture equipment based on the latest designs from the science labs. 50 Technicians can occupy one workshop, items under construction will also consume space.\"\n  STR_STANDARD_SONAR_UFOPEDIA: \"A standard sonar system has an effective range of over 450 kilometres at most depths and is linked to geostationary satellite nets for surface analysis. Each scanner has a 10% chance of detecting a submersible or airborne craft per 30 minute scan cycle.\"\n  STR_WIDE_ARRAY_SONAR_UFOPEDIA: \"A wide array sonar system has an effective range of over 700 kilometres at all depths and is linked to geostationary satellite nets for surface analysis. Each scanner has a 20% chance of detecting a submersible or airborne craft every 30 minute scan cycle.\"\n  STR_TORPEDO_DEFENSES_UFOPEDIA: \"Torpedo defence systems provide protection against attack by hostile submersibles which are attempting to dock at the base.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"All equipment, weapons systems, munitions, recovered material and Submersible Weapons Systems are placed in stores, including equipment assigned to Subs in Pens.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"Live Aliens will require special containment facilities to hold them. These units maintain their life systems and render their combat potential to zero. The containment facility can keep 10 Alien life forms in confinement units.\"\n  STR_GAUSS_DEFENSES_UFOPEDIA: \"The Gauss defence provides the latest and most effective protection against attack by hostile submarines.\"\n  STR_SONIC_DEFENSES_UFOPEDIA: \"Sonic Oscillator defences provide powerful and efficient protection against aggressors.\"\n  STR_PWT_DEFENSES_UFOPEDIA: \"Pulse Wave Torpedoes provide the most effective defence against Alien attacks. These missiles have super dense war heads which can penetrate all known armour. The magnetic waves they produce disable electronic defences.\"\n  STR_BOMBARDMENT_SHIELD_UFOPEDIA: \"The Pressure Bombardment shield protects the base from Alien submersibles docking and sets up a resonating field that repulses attacking subs long enough for defence systems to fire repeatedly. In effect this doubles the effectiveness of any defence systems already deployed.\"\n  STR_MC_GENERATOR_UFOPEDIA: \"Since Alien subs utilize Molecular Control Technology to detect the presence of living creatures, using a negative M.C. emitter will blanket a base with an impenetrable shield to confuse the Aliens and disguise our presence.\"\n  STR_MC_LAB_UFOPEDIA: \"The Molecular Control lab can implant and train up to ten aquanauts at one time. Implants are surgically installed in the skulls of aquanauts. Extensive training allows them to utilize their implants. Implant skills are used in conjunction with a Molecular Device and can be used for attacks during combat.\"\n  STR_TRANSMISSION_RESOLVER_UFOPEDIA: \"Alien communications utilize the Molecular control implant network the Aliens have built up. The transmission resolver facility intercepts Alien Sub transmissions and decodes the information. This will show the type of Alien Sub, the Alien race and the type of activity that is occurring.\"\n  STR_SUB_PEN_UFOPEDIA: \"Each Pen can accommodate one submarine. There are facilities for maintenance, refuelling and repair of the X-Com submarine fleet. Each Flying Sub stationed at a base must have a free Pen assigned to it which cannot be used by other Subs, even if the assigned submarine is out on a mission.\"\n  STR_DART_PISTOL_UFOPEDIA: \"The X-Com dart gun is a small, accurate, high powered unit with a 12 hollow dart ammo clip. The darts are fired by a gas cartridge in the ammo pod.\"\n  STR_JET_HARPOON_UFOPEDIA: \"This aqua-rifle is accurate and powerful, firing hollow steel harpoons from sealed packs of 10. Each harpoon has its own gas reservoir.\"\n  STR_GAS_CANNON_UFOPEDIA: \"The heavyweight of the gas technology family, this cannon fires solid bolts, some with HE or phosphor tips. A favourite weapon amongst experienced aquanauts.\"\n  STR_HYDRO_JET_CANNON_UFOPEDIA: \"Hydro-Jet Cannons are a heavy infantry weapon system. The cannon fires magnesium fuelled mini-torpedoes. Although powerful, the Hydro-Jet Cannon is a clumsy and unwieldy device, suitable for aquatic use only.\"\n  STR_TORPEDO_LAUNCHER_UFOPEDIA: \"A real heavyweight, this large launcher fires three types of torpedo, each with its own propulsion unit. A devastating weapon, with only manual loading being its drawback. Ammunition types available include large or small high explosive and phosphor tipped torpedoes, all for submerged use only.\"\n  STR_GAUSS_PISTOL_UFOPEDIA: \"The Gauss pistol uses accelerated particle technology, a new development in modern weaponry. It is fast, accurate and functions above and below water. Gauss technology is a development of the Plasma technologies learned from the previous war.\"\n  STR_GAUSS_PISTOL_CLIP_UFOPEDIA: \"The Gauss pistol uses accelerated particle technology, a new development in modern weaponry. It is fast, accurate and functions above and below water. Gauss technology is a development of the Plasma technologies learned from the previous war.\"\n  STR_GAUSS_RIFLE_UFOPEDIA: \"A step beyond the Gauss pistol, the rifle packs a real punch, with its twin particle accelerators. Replacing the Elerium powered Plasma system we have utilized a micro particle accelerator that generates a stream of anti-protons.\"\n  STR_GAUSS_RIFLE_CLIP_UFOPEDIA: \"A step beyond the Gauss pistol, the rifle packs a real punch, with its twin particle accelerators. Replacing the Elerium powered Plasma system we have utilized a micro particle accelerator that generates a stream of anti-protons.\"\n  STR_HEAVY_GAUSS_UFOPEDIA: \"The heavy Gauss is cumbersome, but extremely effective. It operates with 3 particle accelerators and is virtually unstoppable. The anti-proton stream is confined inside a Gallium Arsenide shell that implodes on impact releasing the anti-matter.\"\n  STR_HEAVY_GAUSS_CLIP_UFOPEDIA: \"The heavy Gauss is cumbersome, but extremely effective. It operates with 3 particle accelerators and is virtually unstoppable. The anti-proton stream is confined inside a Gallium Arsenide shell that implodes on impact releasing the anti-matter.\"\n  STR_MAGNA_BLAST_GRENADE_UFOPEDIA: \"This standard issue grenade has an accurate and sophisticated timer for precision control.\"\n  STR_DYE_GRENADE_UFOPEDIA: \"Dye grenades are dual role items, useful for providing cover in exposed situations. Functioning in both water and land environments the dye is ejected as a particle cloud, producing an octopus like ink spray in water or dense air borne cloud on land.\"\n  STR_PARTICLE_DISTURBANCE_GRENADE_UFOPEDIA: \"A proximity grenade which can be thrown like an ordinary grenade but is triggered by nearby movement after it is deployed. Skill and training are required to use these devices properly.\"\n  STR_MAGNA_PACK_EXPLOSIVE_UFOPEDIA: \"This explosive should only be used for demolition purposes. However past experience has shown that these powerful explosive packs are ideal weapons for rooting out Aliens. The blast radius is large so ensure no aquanauts are within the minimum safe distance.\"\n  STR_PARTICLE_DISTURBANCE_SENSOR_UFOPEDIA: \"This new device uses a variety of detectors and advanced computer systems to identify moving enemy units. Click on the Disturbance Sensor icon on the tactical display. Select 'Use Sensor' from the menu. The Sensor display shows an arrow in the centre which is the direction the aquanaut is facing (North is at the top). The blips show units which have moved recently. Large units, or fast moving units, will produce larger blips. Static units will not show up.\"\n  STR_MEDI_KIT_UFOPEDIA: \"To use this you face the injured X-Com agent or stand over the body of a stunned aquanaut.{NEWLINE}HEALING> Red indicates wounds. Select body part and click on the 'Heal' button. One fatal wound will be healed and health restored.{NEWLINE}STIMULANT> Restores energy and revives stunned aquanauts. To revive an unconscious aquanaut you must stand directly over the body.{NEWLINE}PAIN KILLER> Restores the morale of wounded aquanauts.\"\n  STR_MC_DISRUPTOR_UFOPEDIA: \"The ultimate in M.C. technology. This can only be used by aquanauts with M.C. skills. Click on the Disruptor, select the type of attack, and select a target unit with the cursor. There are two types of Disruptor attack:{NEWLINE}JAM IMPLANT> If successful the unit becomes confused and it may panic.{NEWLINE}CONTROL IMPLANT> If successful you will gain control of the enemy unit.\"\n  STR_THERMAL_TAZER_UFOPEDIA: \"This device can only be used in close combat, but will stun a living organism without killing it by freezing the creature.\"\n  STR_VIBRO_BLADE_UFOPEDIA: \"The Vibroblade is a long sharp knife blade of titanium which spins at over 6000 rpm, this device can crack even the toughest diving armour. The power source is an Alien invention, our attempt at building these items before met with dismal failure, our blades rotated too slowly or exploded under pressure.\"\n  STR_THERMIC_LANCE_UFOPEDIA: \"The Thermic Lance is a logical extension of the Vibroblade technology The blade revolves at high speed and a Zrbite power source superheats the blade to cut armour like a warm knife through butter \"\n  STR_HEAVY_THERMIC_LANCE_UFOPEDIA: \"The Heavy Thermic Lance is a more powerful version of the TL. Twin heat sources and a extremely high rotation speed means that the Heavy Thermic lance is virtually unstoppable against all materials.\"\n  STR_SONIC_CANNON_UFOPEDIA: \"The Sonic Cannon the most potent of the Sonic weapons family. Featuring a higher range audio oscillator and a larger reverberation chamber than the Blasta. The Cannon also has a pulse detonation system that alters the ultra-sonic wave by modulation to produce a more effective Sonic Shock.\"\n  STR_CANNON_POWER_CLIP_UFOPEDIA: \"This compact device is used as ammunition for a Sonic Cannon. It contains a small quantity of Zrbite.\"\n  STR_SONIC_BLASTA_RIFLE_UFOPEDIA: \"A more powerful Sonic device. Not even high carbon steel is immune to this weapon. The highly compact wave emitter is enhanced by a super conductor amplifier to increase the power of this weapon.\"\n  STR_BLASTA_POWER_CLIP_UFOPEDIA: \"This small object is used as a power source for a Sonic Rifle, a potent Alien weapon, and contains a small quantity of Zrbite.\"\n  STR_SONIC_PISTOL_UFOPEDIA: \"Sonic pistols are an Alien weapon based on ultra-sonic audio waves that can jellify bone in seconds. The Ultra-Sonic waves occupy a range beyond the scope of human hearing.\"\n  STR_PISTOL_POWER_CLIP_UFOPEDIA: \"Power source for the compact Alien Sonic Pistol. Contains Zrbite - the source of all Alien power.\"\n  STR_DISRUPTOR_PULSE_LAUNCHER_UFOPEDIA: \"This is an Alien aquatic use only guided weapon firing self propelled 'Disruptor Projectiles'. When you click to fire the weapon it will generate 'way points' for the Projectile to follow. When you have positioned enough way points click on the launch icon.\"\n  STR_DISRUPTOR_AMMO_UFOPEDIA: \"This device is a Disruptor Pulse Projectile fitted with an onboard computer guidance system. It is fired from a Disruptor Pulse launcher.\"\n  STR_THERMAL_SHOK_LAUNCHER_UFOPEDIA: \"A small Thermal Shok launcher which fires chemical freeze bombs. Very useful for capturing live Aliens.\"\n  STR_THERMAL_SHOK_BOMB_UFOPEDIA: \"The Thermal Shok bomb is used for capturing live humans, but it can also be used against most Alien races. It is fired from a Thermal Shok Launcher.\"\n  STR_SONIC_PULSER_UFOPEDIA: \"This device works in the same way as a standard issue grenade - except that it is many times more powerful. The grenade uses a single pulse sonic blast that is emitted in all directions simultaneously.\"\n  STR_MC_READER_UFOPEDIA: \"Inside the bodies of Aliens we have found small surgically implanted units. These are Control Implants designed by the Aquatoids to allow the constant supply of information from the battlefield, even at great distances. The Molecular Control Reader is an Alien communication device which is used to take information directly from M.C. Implants. X-Com units can use this device in combat to display an Alien's characteristics. Select the 'use' option. Then click on an Alien with the cursor.\"\n\n  STR_SURVEY_SHIP: \"Survey Ship\"\n  STR_ESCORT: \"Escort\"\n  STR_CRUISER: \"Cruiser\"\n  STR_HEAVY_CRUISER: \"Heavy Cruiser\"\n  STR_HUNTER: \"Hunter\"\n  STR_BATTLESHIP: \"Battleship\"\n  STR_DREADNOUGHT: \"Dreadnought\"\n  STR_FLEET_SUPPLY_CRUISER: \"Fleet Supply Cruiser\"\n\n  MAP_SEABED: \"Seabed\"\n  MAP_PIPES: \"Research Facility\"\n  MAP_PLANE: \"Crashed Plane\"\n  MAP_ATLAN: \"Atlantis\"\n  MAP_MU: \"Mayan Temple\"\n  MAP_GAL: \"Sunken Galleon\"\n  MAP_MSUNK: \"Sunken Liner\"\n  MAP_VOLC: \"Volcanic\"\n  MAP_CORAL: \"Coral\"\n  MAP_PORT: \"Port\"\n  MAP_ISLAND: \"Island\"\n  MAP_CARGO: \"Cargo Ship\"\n  MAP_LINERT: \"Cruise Ship P1\"\n  MAP_LINERB: \"Cruise Ship P2\"\n  MAP_ALART: \"Artefact P1\"\n  MAP_GRUNGE: \"Artefact P2\"\n  MAP_ENTRY: \"Colony P1\"\n  MAP_A_BASE: \"Colony P2\"\n  MAP_ALSHIP: \"T'leth P1\"\n  MAP_LEVEL: \"T'leth P2\"\n  MAP_CRYPT: \"T'leth P3\"\n  MAP_XBASES: \"X-Com Base\"\n\n  STR_MIXED_CREW: \"Mixed Crew\"\n  STR_MIXED_CREW_2: \"Mixed Crew 2\"\n\n  STR_RATING: \"RATING> {0}\"\n  STR_RATING_TERRIBLE: \"TERRIBLE!\"\n  STR_RATING_POOR: \"POOR!\"\n  STR_RATING_OK: \"OK\"\n  STR_RATING_GOOD: \"GOOD!\"\n  STR_RATING_EXCELLENT: \"EXCELLENT!\"\n  STR_SCORE: \"SCORE\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"X-COM MONTHLY REPORT\"\n  STR_MONTH: \"Month> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"The committee of funding organisations is generally satisfied with your progress so far.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"The committee of funding organisations is very pleased with your excellent progress. Keep up the good work.\"\n  STR_COUNCIL_IS_DISSATISFIED: \"The committee of funding organisations is dissatisfied with your performance. You must improve your effectiveness in dealing with the Alien menace or risk termination funding support for X-Com.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"You have not succeeded in dealing with the Alien invasion and the committee of funding organisations has regrettably decided to terminate funding X-Com. Each organisation shall deal with the problem as they see fit. We can only hope that we can come to some accommodation with these ancient forces, and that the general population will come to terms with the aquatic visitors.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} is particularly pleased with your ability to deal with the localized threat and has agreed to increase its funding.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} are particularly happy with your progress in dealing with local Alien incursion and have agreed to increase their funding.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} and {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} is unhappy with your ability to deal with Alien activity in its Seas and has decided to reduce its financial commitment.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} are unhappy with your ability to deal with Alien activity in their Sea and have decided to reduce their funding.\"\n  STR_KNOTS: \"{0} knots\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} has signed a co-operation agreement with the Alien forces and has withdrawn from X-Com funding.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} have signed a co-operation agreement with Alien forces and have withdrawn from the X-Com funding.\"\n  STR_MONTHLY_RATING: \"Monthly Rating> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Funding change> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"The funding organisation is not happy with your financial position. You must reduce your debts below $1 million or the X-Com will be terminated.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"SUB-PARTICLE TRANSMISSIONS RESOLVED\"\n  STR_CRAFT_TYPE: \"SUB TYPE\"\n  STR_RACE: \"RACE\"\n  STR_MISSION: \"MISSION\"\n  STR_ZONE: \"ZONE\"\n  STR_ALLOCATE_RESEARCH: \"Allocate Research\"\n  STR_ALLOCATE_MANUFACTURE: \"Allocate Manufacture\"\n\n  STR_AZORES: \"Azores\"\n  STR_REYKJAVIK: \"Reykjavik\"\n  STR_BERMUDA: \"Bermuda\"\n  STR_NEW_YORK: \"New York\"\n  STR_BOSTON: \"Boston\"\n  STR_FORT_SEVERN: \"Fort Severn\"\n  STR_DAKAR: \"Dakar\"\n  STR_RECIFE: \"Recife\"\n  STR_ACCRA: \"Accra\"\n  STR_ASCENSION_ISLAND: \"Ascension Island\"\n  STR_TRINIDADE_ISLAND: \"Trindade Island\"\n  STR_FALKLAND_ISLAND: \"Falkland Island\"\n  STR_CANARY_ISLANDS: \"Canary Islands\"\n  STR_ANCHORAGE: \"Anchorage\"\n  STR_ST_LAWRENCE_ISLAND: \"St Lawrence Island\"\n  STR_SAN_FRANCISCO: \"San Francisco\"\n  STR_MIDWAY_ISLAND: \"Midway Island\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_TASMANIA: \"Tasmania\"\n  STR_HAWAII: \"Hawaii\"\n  STR_FIJI: \"Fiji\"\n  STR_TONGA: \"Tonga\"\n  STR_EASTER_ISLAND: \"Easter Island\"\n  STR_GALAPAGOS_ISLAND: \"Galapagos Island\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_SOLOMON_ISLAND: \"Solomon Island\"\n  STR_CRETE: \"Crete\"\n  STR_LISBON: \"Lisbon\"\n  STR_PORT_SAID: \"Port Said\"\n  STR_MARSEILLES: \"Marseilles\"\n  STR_TRIPOLI: \"Tripoli\"\n  STR_MANILA: \"Manila\"\n  STR_HONG_KONG: \"Hong Kong\"\n  STR_SINGAPORE: \"Singapore\"\n  STR_BANGKOK: \"Bangkok\"\n  STR_DARWIN: \"Darwin\"\n  STR_BOMBAY: \"Bombay\"\n  STR_SAYCHELLES_ISLAND: \"Seychelles Island\"\n  STR_MALDIVE_ISLAND: \"Maldive Island\"\n  STR_SRI_LANKA: \"Sri Lanka\"\n  STR_MAURITIUS: \"Mauritius\"\n  STR_TOKYO: \"Tokyo\"\n  STR_SHANGHAI: \"Shanghai\"\n  STR_VLADIVOSTOK: \"Vladivostok\"\n  STR_LONDON: \"London\"\n  STR_FAEROE_ISLAND: \"Faeroe Island\"\n  STR_ABERDEEN: \"Aberdeen\"\n  STR_OSLO: \"Oslo\"\n  STR_JAMAICA: \"Jamaica\"\n  STR_PANAMA: \"Panama\"\n  STR_MIAMI: \"Miami\"\n\n  STR_PSI_TRAINING: \"M.C. Training\"\n  STR_PSIONIC_TRAINING: \"MOLECULAR CONTROL TRAINING\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Remaining M.C. capacity> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"M.C.{NEWLINE}Strength\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"M.C. Skill{NEWLINE}/Improvement\"\n  STR_IN_TRAINING: \"In{NEWLINE}Training?\"\n  STR_TARGETTED_BY: \"TARGETTED BY:\"\n  STR_WEAPONS_CREW_HWPS: \"WEAPONS/{NEWLINE}CREW/SWSs\"\n\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"is low on fuel,{NEWLINE}returning to base\"\n  STR_SOLDIER_LIST: \"Aquanaut List\"\n  STR_RANK_: \"RANK> {ALT}{0}\"\n  STR_MISSIONS: \"MISSIONS> {ALT}{0}\"\n  STR_KILLS: \"KILLS> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"WOUND RECOVERY> {ALT}{0}\"\n  STR_TIME_UNITS: \"TIME UNITS\"\n  STR_STAMINA: \"STAMINA\"\n  STR_HEALTH: \"HEALTH\"\n  STR_BRAVERY: \"BRAVERY\"\n  STR_REACTIONS: \"REACTIONS\"\n  STR_FIRING_ACCURACY: \"FIRING ACCURACY\"\n  STR_THROWING_ACCURACY: \"THROWING ACCURACY\"\n  STR_STRENGTH: \"STRENGTH\"\n  STR_PSIONIC_STRENGTH: \"M.C. STRENGTH\"\n  STR_PSIONIC_SKILL: \"M.C. SKILL\"\n  STR_NEW_RANK: \"NEW RANK\"\n  STR_PROMOTIONS: \"Promotions\"\n  STR_SOLDIERS_UC: \"AQUANAUTS\"\n  STR_COELACANTH_GAS_CANNON_UFOPEDIA: \"Automated SWS's have high manoeuvrability and hull strength. They provide heavy troop support at all depths. SWS's are re-armed automatically if you have enough ammunition.\"\n  STR_COELACANTH_AQUA_JET_UFOPEDIA: \"This submersible is armed with Aqua-Jet torpedoes. This weapon system only functions underwater. Ensure stores are well stocked with Aqua-Jet Torpedoes.\"\n  STR_COELACANTH_GAUSS_UFOPEDIA: \"Gauss technology provides a powerful weapon system for SWS's. Offering heavy firepower compared with earlier models, and uses proprietary X-Com technology.\"\n  STR_DISPLACER_SONIC_UFOPEDIA: \"Alien technology has redefined the SWS. The ability to utilize Ion Displacers means that SWS's are no longer restricted to the land/seabed. Sonic weaponry gives a real advantage in battle.\"\n  STR_DISPLACER_PWT_UFOPEDIA: \"This SWS features Pulse Wave weapons for aquatic use. You must manufacture PWT's to keep them fully armed. To fire, select a number of 'way points' then click on the launch icon.\"\n\n  STR_ALIEN_PROBE_MISSION: \"Alien Probe Mission\"\n  STR_ALIEN_INTERDICTION: \"Alien Interdiction\"\n  STR_ALIEN_RESOURCE_RAID: \"Alien Resource Raid\"\n  STR_ALIEN_INFILTRATION: \"Alien Infiltration\"\n  STR_ALIEN_BASE: \"Alien Colony Expansion\"\n  STR_ALIEN_SURFACE_ATTACK: \"Alien Surface Attacks\"\n  STR_ALIEN_RETALIATION: \"Floating Base Attack\"\n  STR_ALIEN_SUPPLY: \"Colony Supply Missions\"\n\n  STR_ALIEN_PROBE_MISSION_UFOPEDIA: \"The Alien Probe Mission is used for correlating data about the seabed, the resources, shipping and aeroplane flight paths of an area. The Alien subs involved in these missions are not a major threat in themselves, but they indicate sites of activity that may flare at any time.\"\n  STR_ALIEN_INTERDICTION_UFOPEDIA: \"The Aliens have a policy of policing areas they are interested in, sending out craft with the express purpose of securing an area before more intensive missions are begun. They will land at specific sites they intend to raid later to lock down the areas and prepare the way for the next level of activity.\"\n  STR_ALIEN_RESOURCE_RAID_UFOPEDIA: \"The sinking of ships and the downing of aircraft are key elements of the Alien strategy. The acquisition of materials is one of the prime Alien activities and as such is allied to these overtly aggressive acts. The Aliens also raid areas of geo-thermal activity, mining sites and sites of antiquity for minerals and refined metals and other human produced items.\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"This can result in official contact between Aliens and corporations or governments at the highest level. The climax of this activity is characterized by intense Alien Sub activity in the waters of the organisation concerned. The Aliens will attempt to sign an agreement with a government or organisation by offering knowledge of their superior technologies. This Alien activity represents a major threat to X-Com. If a corporation or government co-operates with the invaders then its funding ceases.\"\n  STR_ALIEN_BASE_UFOPEDIA: \"Aliens will construct secret undersea colonies in remote locations. After some initial reconnaissance flights some intense Alien Sub activity will occur as the colony is being built. These colonies are known to contain labs, cloning centres, surgical facilities for human and Alien experimentation. The presence of Alien colonies will generate more Alien activity without the presence of Alien Subs. In order to locate a colony an X-Com sub must patrol an area for a few hours to stand some chance of successful detection.\"\n  STR_ALIEN_SURFACE_ATTACK_UFOPEDIA: \"When the Aliens need humans they terrorize a port, attack an island, or raid a ship. Civilians will be directly threatened, to fulfil the perverse breeding needs of the Aliens and their hideous experiments.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"If X-Com intercept subs are being particularly successful in sinking Alien craft then the Aliens may take some aggressive retaliatory action. This could result in a direct attack against an X-Com facility. However, the Aliens have to find an X-Com base in order to attack it, and provided Alien Subs are kept away then there should be little danger of an assault.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"Once an Alien colony is constructed then it is re-supplied on a regular basis by a special supply ship. If one of these vessels is detected while touching down then it is certain that an Alien colony is nearby.\"\n\n  STR_SURVEY_SHIP_UFOPEDIA: \"This tiny submarine is used for reconnaissance and survey missions. It normally precedes larger vessels at the start of an Alien task force.\"\n  STR_ESCORT_UFOPEDIA: \"A medium sized escort vessel that is of little threat on its own. This craft precedes the arrival of larger vessels and increased activities.\"\n  STR_CRUISER_UFOPEDIA: \"The Cruiser is a general purpose craft, the mainstay of the Alien fleet, it is used in all types of Alien missions and is a dangerous adversary.\"\n  STR_HEAVY_CRUISER_UFOPEDIA: \"The heavy cruiser is a more powerful ship than the cruiser, larger weapons and propulsion systems boost its power. The Heavy Cruiser is used for resource missions to collect large quantities of minerals and equipment.\"\n  STR_HUNTER_UFOPEDIA: \"This vessel is equipped with an examination room for performing experiments and surgery on human subjects. The victims are subjected to the foulest tortures and the brain is often removed and stored for processing en-route.\"\n  STR_BATTLESHIP_UFOPEDIA: \"The battleship is the most aggressive ship the Aliens possess, it features all the Alien technologies and systems to act as a base of operations for any form of aggressive act the Aliens may want to perform, it carries a wide array of weapons.\"\n  STR_DREADNOUGHT_UFOPEDIA: \"The Dreadnought is a super troop carrier, fully equipped with all Alien technologies and a vast payload. The Dreadnought is a tough and formidable opponent.\"\n  STR_FLEET_SUPPLY_CRUISER_UFOPEDIA: \"The supply vessel is used during the construction of Alien colonies or for supplying existing colonies. It carries Alien nutrients, DNA, foetuses and other biological components.\"\n\n  STR_DISMANTLE: \"Dismantle\"\n  STR_FACILITY_IN_USE: \"AQUA-POD IN USE\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"CANNOT DISMANTLE AQUA-POD!{SMALLLINE}All base Pods must be linked to the air-lock.\"\n  STR_TRANSFER_ITEMS_TO: \"Transfer Items to {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"NO ALIEN CONTAINMENT FOR TRANSFER!{SMALLLINE}Live Aliens need an Alien containment equipment in order to survive.\"\n  STR_AMOUNT_AT_DESTINATION: \"AMOUNT AT{NEWLINE}DESTINATION\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"Alien dies as there is no Alien containment facility\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"NO FREE ACCOMMODATION!{SMALLLINE}The destination base does not have enough space in the living quarters for the crew assigned to the sub.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"NOT ENOUGH STORE SPACE!{SMALLLINE}The destination base does not have enough store space for the equipment assigned to the sub.\"\n  STR_ITEMS_ARRIVING: \"Items Arriving\"\n  STR_DESTINATION_UC: \"DESTINATION\"\n\n  STR_DART_PISTOL: \"Dart Gun\"\n  STR_DART_POD: \"Dart Clip\"\n  STR_JET_HARPOON: \"Jet Harpoon\"\n  STR_HARPOON_POD: \"Harpoon Clip\"\n  STR_GAS_CANNON: \"Gas Cannon\"\n  STR_GC_AP_AMMO: \"GC-AP Bolts\"\n  STR_GC_HE_AMMO: \"GC-HE Bolts\"\n  STR_GC_P_AMMO: \"GC-Phosphorous Bolts\"\n  STR_HYDRO_JET_CANNON: \"Hydro-Jet Cannon\"\n  STR_HJC_AP_AMMO: \"HJ-AP Ammo\"\n  STR_HJC_HE_AMMO: \"HJ-HE Ammo\"\n  STR_HJC_P_AMMO: \"HJ-P Ammo\"\n  STR_TORPEDO_LAUNCHER: \"Torpedo Launcher\"\n  STR_SMALL_TORPEDO: \"Small Torpedo\"\n  STR_LARGE_TORPEDO: \"Large Torpedo\"\n  STR_PHOSPHOROUS_TORPEDO: \"Phosphor Torpedo\"\n  STR_MAGNA_BLAST_GRENADE: \"Magna-Blast Grenade\"\n  STR_DYE_GRENADE: \"Dye Grenade\"\n  STR_PARTICLE_DISTURBANCE_GRENADE: \"Particle Disturbance Grenade\"\n  STR_MAGNA_PACK_EXPLOSIVE: \"Magna-Pack Explosive\"\n  STR_PARTICLE_DISTURBANCE_SENSOR: \"Particle Disturbance Sensor\"\n  STR_MEDI_KIT: \"Medi-Kit\"\n  STR_MC_DISRUPTOR: \"M.C. Disruptor\"\n  STR_THERMAL_TAZER: \"Thermal Tazer\"\n\n  STR_GAUSS_PISTOL: \"Gauss Pistol\"\n  STR_GAUSS_PISTOL_CLIP: \"Gauss Pistol Clip\"\n  STR_GAUSS_RIFLE: \"Gauss Rifle\"\n  STR_GAUSS_RIFLE_CLIP: \"Gauss Rifle Clip\"\n  STR_HEAVY_GAUSS: \"Heavy Gauss\"\n  STR_HEAVY_GAUSS_CLIP: \"Heavy Gauss Clip\"\n\n  STR_SONIC_CANNON: \"Sonic Cannon\"\n  STR_CANNON_POWER_CLIP: \"Cannon Power Clip\"\n  STR_SONIC_BLASTA_RIFLE: \"Sonic-Blasta Rifle\"\n  STR_BLASTA_POWER_CLIP: \"Blasta Power Clip\"\n  STR_SONIC_PISTOL: \"Sonic Pistol\"\n  STR_PISTOL_POWER_CLIP: \"Pistol Power Clip\"\n  STR_DISRUPTOR_PULSE_LAUNCHER: \"Disruptor Pulse Launcher\"\n  STR_DISRUPTOR_AMMO: \"Disruptor Ammo\"\n  STR_THERMAL_SHOK_LAUNCHER: \"Thermal Shok Launcher\"\n  STR_THERMAL_SHOK_BOMB: \"Thermal Shok Bomb\"\n  STR_SONIC_PULSER: \"Sonic Pulser\"\n  STR_ZRBITE: \"Zrbite\"\n  STR_MC_READER: \"M.C. Reader\"\n  STR_VIBRO_BLADE: \"Vibro Blade\"\n  STR_THERMIC_LANCE: \"Thermic Lance\"\n  STR_HEAVY_THERMIC_LANCE: \"Heavy Thermic Lance\"\n  STR_AQUATOID_CORPSE: \"Aquatoid Corpse\"\n  STR_GILLMAN_CORPSE: \"Gill Man Corpse\"\n  STR_LOBSTERMAN_CORPSE: \"Lobster Man Corpse\"\n  STR_TASOTH_CORPSE: \"Tasoth Corpse\"\n  STR_CALCINITE_CORPSE: \"Calcinite Corpse\"\n  STR_DEEP_ONE_CORPSE: \"Deep One Corpse\"\n  STR_BIODRONE_CORPSE: \"Bio-Drone Corpse\"\n  STR_TENTACULAT_CORPSE: \"Tentaculat Corpse\"\n  STR_TRISCENE_CORPSE: \"Triscene Corpse\"\n  STR_HALLUCINOID_CORPSE: \"Hallucinoid Corpse\"\n  STR_XARQUID_CORPSE: \"Xarquid Corpse\"\n\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"Not enough ammunition to arm SWS{SMALLLINE}Each SWS requires {0} {1}.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Not enough equipment to fully re-equip squad\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"You will need to research a{NEWLINE}{0}{NEWLINE}in order to produce the{NEWLINE}{1}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"The Aliens have destroyed the undefended base {0}\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"X-Com patrols have located an Alien colony in {0}\"\n  STR_STANDOFF: \"STANDOFF\"\n  STR_CAUTIOUS_ATTACK: \"CAUTIOUS ATTACK\"\n  STR_STANDARD_ATTACK: \"STANDARD ATTACK\"\n  STR_AGGRESSIVE_ATTACK: \"AGGRESSIVE ATTACK\"\n  STR_DISENGAGING: \"DISENGAGING\"\n  STR_UFO_HIT: \"ALIEN SUB HIT!\"\n  STR_UFO_CRASH_LANDS: \"ALIEN SUB DOWNED!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Minimize at Standoff Range Only\"\n  STR_UFO_RETURN_FIRE: \"ALIEN SUB RETURNS FIRE!\"\n  STR_INTERCEPTOR_DAMAGED: \">>> FLYING SUB DAMAGED <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> FLYING SUB DESTROYED <<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"ALIEN FLYING SUB ESCAPING!\"\n  STR_LONG_RANGE_DETECTION: \"Wide band Detection\"\n  STR_STORES_UC: \"STORES\"\n  STR_DIFFICULTY_LEVEL: \"Difficulty Level\"\n  STR_INTERCEPT: \"INTERCEPT\"\n  STR_BASES: \"BASES\"\n  STR_GRAPHS: \"GRAPHS\"\n  STR_UFOPAEDIA_UC: \"UFOPAEDIA\"\n  STR_OPTIONS_UC: \"OPTIONS\"\n  STR_FUNDING_UC: \"FUNDING\"\n  STR_5_SECONDS: \"5 Secs\"\n  STR_1_MINUTE: \"1 Min\"\n  STR_5_MINUTES: \"5 Mins\"\n  STR_30_MINUTES: \"30 Mins\"\n  STR_1_HOUR: \"1 Hour\"\n  STR_1_DAY: \"1 Day\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"X-Com Performance Roster\"\n  STR_ENTER_NAME: \"Enter Name\"\n  STR_PERFORMANCE_RATING: \"Performance Rating\"\n  STR_VICTORY_DATE: \"Victory Date\"\n  STR_CHEMICAL_FLARE: \"Chemical-flare\"\n  STR_CHEMICAL_FLARE_UFOPEDIA: \"This compact device produces a bright flare of light at any depth or on dry land. This illuminates enemy units in the vicinity of the flare during deep sea or night missions.\"\n  STR_MONTHLY_COSTS: \"Monthly Costs\"\n  STR_CRAFT_RENTAL: \"Flying Sub Rental\"\n  STR_SALARIES: \"Salaries\"\n  STR_BASE_MAINTENANCE: \"Base maintenance\"\n  STR_COST_PER_UNIT: \"Cost per unit\"\n  STR_QUANTITY: \"Quantity\"\n  STR_TOTAL: \"Total\"\n  STR_IN_PSIONIC_TRAINING: \"In M.C. Implantation\"\n  STR_FRONT_ARMOR: \"Front Armour\"\n  STR_LEFT_ARMOR: \"Left Armour\"\n  STR_RIGHT_ARMOR: \"Right Armour\"\n  STR_REAR_ARMOR: \"Rear Armour\"\n  STR_UNDER_ARMOR: \"Under Armour\"\n  STR_ROUNDS: \"SHOTS\"\n  STR_UNIT: \"UNIT> {0}\"\n  STR_ENERGY: \"ENERGY\"\n  STR_MORALE: \"MORALE\"\n  STR_ARMOR_: \"ARMOR> {0}\"\n  STR_FRONT_ARMOR_UC: \"FRONT ARMOUR\"\n  STR_LEFT_ARMOR_UC: \"LEFT ARMOUR\"\n  STR_RIGHT_ARMOR_UC: \"RIGHT ARMOUR\"\n  STR_REAR_ARMOR_UC: \"REAR ARMOUR\"\n  STR_SKILLS: \"SKILLS> {0}\"\n  STR_LEVEL: \"LEVEL> {0}\"\n  STR_HEAD: \"HEAD\"\n  STR_TORSO: \"TORSO\"\n  STR_RIGHT_ARM: \"RIGHT ARM\"\n  STR_LEFT_ARM: \"LEFT ARM\"\n  STR_RIGHT_LEG: \"RIGHT LEG\"\n  STR_LEFT_LEG: \"LEFT LEG\"\n  STR_PAIN_KILLER: \"PAIN KILLER\"\n  STR_STIMULANT: \"STIMULANT\"\n  STR_HEAL: \"HEAL\"\n  STR_TIME_UNITS_SHORT: \"TU>{ALT}{0}\"\n  STR_WEIGHT: \"Weight>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"React>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"M.Skill>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"M.Str>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Alien Artefact\"\n  STR_AMMO_ROUNDS_LEFT: \"AMMO:{NEWLINE}ROUNDS{NEWLINE}LEFT={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Pain>{ALT}{0}{ALT}{NEWLINE}Stim>{ALT}{1}{ALT}{NEWLINE}Heal>{ALT}{2}\"\n  STR_THROW: \"Throw\"\n  STR_AUTO_SHOT: \"Auto Shot\"\n  STR_SNAP_SHOT: \"Snap Shot\"\n  STR_AIMED_SHOT: \"Aimed Shot\"\n  STR_STUN: \"Stun\"\n  STR_PRIME_GRENADE: \"Prime Grenade\"\n  STR_USE_SCANNER: \"Use Dist. Sensor\"\n  STR_USE_MEDI_KIT: \"Use Medi-kit\"\n  STR_LAUNCH_MISSILE: \"Launch Torpedo\"\n  STR_ACCURACY_SHORT: \"Acc>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Not Enough Time Units!\"\n  STR_NOT_ENOUGH_ENERGY: \"Not Enough Energy!\"\n  STR_NO_ROUNDS_LEFT: \"No Rounds left!\"\n  STR_NO_AMMUNITION_LOADED: \"No Ammunition Loaded!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Wrong Ammunition for this Weapon!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"Weapon is already loaded!\"\n  STR_NO_LINE_OF_FIRE: \"No Line of Fire!\"\n  STR_GRENADE_IS_ACTIVATED: \"Grenade is Activated!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Grenade De-activated!\"\n  STR_THERE_IS_NO_ONE_THERE: \"There is no one there!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Unable to use alien artefact until researched!\"\n  STR_OUT_OF_RANGE: \"Out of Range!\"\n  STR_UNABLE_TO_THROW_HERE: \"Unable to throw here!\"\n  STR_SET_TIMER: \"Set Timer\"\n  STR_HIDDEN_MOVEMENT: \"HIDDEN MOVEMENT\"\n  STR_TURN: \"TURN> {0}\"\n  STR_SIDE: \"SIDE> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Press button to continue\"\n  STR_MIND_CONTROL: \"Molecular Control\"\n  STR_PANIC_UNIT: \"Jam Implant\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Morale Attack Successful\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Implant Control Successful\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}has gone Berserk\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}has gone Berserk\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}has Panicked\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}has Panicked\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Aliens\"\n  STR_RIGHT_HAND: \"RIGHT HAND\"\n  STR_LEFT_HAND: \"LEFT HAND\"\n  STR_RIGHT_SHOULDER: \"RIGHT SHOULDER\"\n  STR_LEFT_SHOULDER: \"LEFT SHOULDER\"\n  STR_BACK_PACK: \"BACK PACK\"\n  STR_BELT: \"BELT\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}is under Molecular Control\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}is under Molecular Control\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}has become unconscious\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}has become unconscious\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}has died from a fatal wound\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}has died from a fatal wound\"\n  STR_USE_MIND_PROBE: \"Use M.C. Reader\"\n  STR_FATAL_WOUNDS: \"FATAL WOUNDS\"\n  STR_UNDER_ARMOR_UC: \"UNDER ARMOUR\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Time Units reserved for Snap Shot\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Time Units reserved for Auto Shot\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Time Units reserved for Aimed Shot\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Time Units reserved for Kneeling\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"TUs reserved for Kneeling and Firing\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} Unit in X-Com Craft\"\n    other: \"{N} Units in X-Com Craft\"\n  STR_UNITS_OUTSIDE:\n    one: \"{N} Unit left outside\"\n    other: \"{N} Units left outside\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} Unit in Entrance\"\n    other: \"{N} Units in Entrance\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} Unit in Target Exit\"\n    other: \"{N} Units in Target Exit\"\n  STR_ABORT_MISSION_QUESTION: \"Abort Mission?\"\n  STR_CORPSE: \"Corpse\"\n  STR_UNLOAD_CRAFT: \"Unload\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}has been killed\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}has been killed\"\n  STR_HIT_MELEE: \"Hit\"\n  STR_GROUND: \"GROUND\"\n  STR_LIVING_QUARTERS_PLURAL: \"Living Quarters\"\n  STR_LIST_ITEM: \"ITEM\"\n\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"All Aliens killed in subcrash,{NEWLINE}Auto recovery initiated\"\n  STR_RESET: \"Reset\"\n  STR_MEMORIAL: \"Memorial\"\n  STR_DATE_UC: \"DATE\"\n  STR_SOLDIERS_RECRUITED_UC: \"AQUANAUTS RECRUITED>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"AQUANAUTS LOST>{ALT}{0}\"\n  STR_REMOVE_SELECTED: \"Remove Selected\"\n  STR_LIVE_ALIENS: \"Live{NEWLINE}Specimens\"\n  STR_DEAD_ALIENS: \"Rejected{NEWLINE}Specimens\"\n  STR_UNDER_INTERROGATION: \"Being{NEWLINE}Studied\"\n  STR_CONTAINMENT_EXCEEDED: \"ALIEN CONTAINMENT LIMITS EXCEEDED!{SMALLLINE}Insufficient containment space at {0}. You must remove excess aliens from containment (who will then die).\"\n  STR_MANAGE_CONTAINMENT: \"Manage Alien Containment\"\n  STR_STORAGE_EXCEEDED: \"STORAGE SPACE EXCEEDED!{SMALLLINE}Insufficient storage space at {0}. You must sell off excess items.\"\n  STR_GO_TO_BASE: \"Go to Base\"\n  STR_MELEE_ACCURACY: \"MELEE ACCURACY\"\n  STR_SELL_PRODUCTION: \"SELL\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Both hands must be empty!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Not enough items to copy template!\"\n  STR_UNLOAD_WEAPON: \"Unload weapon\"\n  STR_ALL_ITEMS: \"All Items\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"NO MORE EQUIPMENT ALLOWED ON BOARD!{SMALLLINE}You are only allowed to take a maximum of {N} item of equipment on this sub.\"\n    other: \"NO MORE EQUIPMENT ALLOWED ON BOARD!{SMALLLINE}You are only allowed to take a maximum of {N} items of equipment on this sub.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}CONTROL CENTER DESTROYED{NEWLINE}Make your way to the entrance and abort.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"X-Com Aqua-facilities cannot be built on land\"\n  STR_UNABLE_TO_ENGAGE_DEPTH: \"UNABLE TO ENGAGE ENEMY{NEWLINE}AT THIS DEPTH\"\n  STR_UNABLE_TO_ENGAGE_AIRBORNE: \"UNABLE TO ENGAGE ENEMY{NEWLINE}WHEN AIRBORNE\"\n  STR_UNDERWATER_EQUIPMENT: \"This equipment will not function above water!\"\n  STR_LAND_EQUIPMENT: \"This equipment will not function underwater!\"\n  STR_LEVEL_SHORT: \"L{0}\"\n  STR_PERSONNEL: \"Personnel\"\n  STR_CRAFT_ARMAMENT: \"Craft & Armament\"\n  STR_COMPONENTS: \"Components\"\n  STR_SOLDIERS_RECRUITED: \"Aquanauts recruited\"\n  STR_SOLDIERS_LOST: \"Aquanauts lost\"\n  STR_TOTAL_UFOS: \"Flying subs detected\"\n  STR_TOTAL_ALIEN_BASES: \"Alien colonies discovered\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"MST\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"MSK\"\n  FEMALE_CIVILIAN: \"Civilian, Female\"\n  MALE_CIVILIAN: \"Civilian, Male\"\n  DOCKER_CIVILIAN: \"Civilian, Docker\"\n  SAILOR_CIVILIAN: \"Civilian, Sailor\"\n  STR_BIODRONE_MELEE_WEAPON: \"Bio-drone Melee\"\n  HALLUCINOID_WEAPON: \"Hallucinoid Weapon\"\n  STR_LOBSTERMAN_MELEE_WEAPON: \"Lobsterman Melee\"\n  CALCINITE_WEAPON: \"Calcinite Weapon\"\n  DEEP_ONE_WEAPON: \"Deep One Weapon\"\n  STR_TRISCENE_MELEE_WEAPON: \"Triscene Melee\"\n  STR_TRIBIO_SONIC_WEAPON: \"Alien Sonic Weapon\"\n  XARQUID_WEAPON: \"Xarquid Weapon\"\n  TENTACULAT_WEAPON: \"Tentaculat Weapon\"\n  ZOMBIE_WEAPON: \"Zombie Weapon\"\n  ALIEN_PSI_WEAPON: \"Alien M.C. Weapon\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/en-US.yml",
    "content": "en-US:\n  STR_LEVIATHAN_UFOPEDIA: \"A TRANSPORT AND INTERCEPT FLYING SUB, WITH EXTREME DEPTH CAPABILITY. A SUPERB SYNTHESIS OF ALIEN AND HUMAN TECHNOLOGY, UTILISING ION PROPULSION SYSTEMS AND MAGNETIC ARRAY NAVIGATION.\"\n  STR_BARRACUDA_UFOPEDIA: \"THE BRITISH HYDROSPACE BARRACUDA, POWERED BY SUPER-HEATED LASER ENGINES. ONE OF THE FASTEST INTERCEPT SHIPS IN THE WORLD, CAPABLE OF SUBMERSIBLE AND ATMOSPHERIC FLIGHT, A KEY CRAFT IN THE COMING BATTLE.\"\n  STR_HAMMERHEAD_UFOPEDIA: \"A TRANSPORT AND INTERCEPT CRAFT. A REPLICATION OF MAGNETIC ARRAY SYSTEMS IN AN X-COM SHIP. ALTHOUGH SMALL, ITS' DESIGN IS A BREATHTAKING TECHNICAL ACHIEVEMENT.\"\n  STR_TRITON_UFOPEDIA: \"THE TRITON, AN ASSAULT SQUAD TRANSPORTER, FITTED WITH FULL ATMOSPHERIC AND AQUATIC FLIGHT ENGINES. ITS LARGE CAPACITY AND ROBUST CONSTRUCTION ENSURES IT IS THE MAINSTAY OF THE X-COM FLEET.\"\n  STR_MANTA_UFOPEDIA: \"MANTA HIGH SPEED CRAFT, A ONE-MAN INTERCEPT FLYING SUBMARINE CLOSELY RESEMBLING ION-POWERED ALIEN SHIPS. A HIGHLY EFFECTIVE STRIKE CRAFT IN THE ESCALATING CONFLICT.\"\n  STR_AJAX_UFOPEDIA: \"THE AJAX TORPEDO IS THE STANDARD WEAPON OF UNDERSEA COMBAT THE WORLD OVER. EMPLOYED AS AN ACCURATE AND POWERFUL DETERRENT.\"\n  STR_DUP_HEAD_UFOPEDIA: \"DEPLETED URANIUM PELLET HEADED WEAPON TECHNOLOGY IS RELATIVELY NEW, AND THIS IS THE FIRST COMMERCIAL AQUATIC WEAPON SYSTEM TO EMPLOY IT FULLY.\"\n  STR_CRAFT_GAS_CANNON_UFOPEDIA: \"A COMPRESSED GAS POWERED CANNON SYSTEM FIRING SOLID BOLTS WITH HIGH ARMOR PIERCING CAPABILITY.\"\n  STR_PWT_CANNON_UFOPEDIA: \"THE PULSE WAVE TORPEDO UTILIZES A SUPERHEATED FUEL SYSTEM AND AN EXTREMELY DENSE WARHEAD WHICH CAN PUNCH THROUGH MOST ALLOYS.\"\n  STR_GAUSS_CANNON_UFOPEDIA: \"THE GAUSS WEAPON IS NEWLY DEVELOPED X-COM TECHNOLOGY. THIS SYSTEM'S PARTICLE ACCELERATOR IS POWERED BY A COMPACT, LIQUID NITROGEN COOLED, FUSION REACTOR.\"\n  STR_SONIC_OSCILLATOR_UFOPEDIA: \"A POWERFUL AUDITORY OSCILLATOR CREATES WAVES OF SONIC FORCE. DESTROYING THE TARGET BY VIBRATING ITS MOLECULAR BONDS APART.\"\n  STR_AQUATOID_UFOPEDIA: \"The Aquatoid Race is an ancient society, having existed millennia before man's first faltering steps upon the world. Their compact form and bulbous features are a throwback to their space faring brethren, the Sectoids. Their power is based on the powerful Molecular Control technology. The Aquatoid race seeks to propagate its sterile race by genetic modification, the ideal subjects being human beings. Experiments have spawned numerous hybrid races.\"\n  STR_AQUATOID_AUTOPSY: \"Aquatoid autopsy\"\n  STR_AQUATOID_AUTOPSY_UFOPEDIA: \"A detailed analysis of this creature allows us to make some basic assumptions. It is a Sectoid, our former foes, but changed by surgical methods and implants to be an aquatic creature. Vestigial lungs allow the breathing of air and limited surface mobility. There are cybernetic implants throughout the body, enhancing the strength of its atrophied limbs and the function of its organs. As all the members of this race are identical, we may hypothesize that these creatures are clones.\"\n  STR_GILLMAN_UFOPEDIA: \"Almost human, a strange creature who appears to be a reptilian humanoid, very closely related to man. This creature is extremely powerful and fast in the undersea world. Gillmen are a fully fledged race, there being male and female specimens of varying ages. They are unlike the majority of the underwater aliens as they bear none of the signs of genetic alteration or surgical deformation. It is possible we are looking at some ancient branch of our own species.\"\n  STR_GILLMAN_AUTOPSY: \"Gillman autopsy\"\n  STR_GILLMAN_AUTOPSY_UFOPEDIA: \"Once surgery began it became clear this is no alien, but an Earth born creature, an ancient pre-historic race that was thought destroyed at the very moment mammals became dominant. In a time when dinosaurs roamed these creatures lived, the Gillmen- amphibious, intelligent and strong. The cataclysm that ended the reptile rule on this planet forced these creatures into a symbiotic relationship with the newly arrived aliens. A small electronic device is lodged in the skulls of the creatures.\"\n  STR_LOBSTERMAN_UFOPEDIA: \"This is a staggering creature, taller than a man and boasting six limbs, it resembles nothing more than an aquatic Demon. The similarities between this creature and the Earth lobster have earned it the nickname of Lobsterman with the X-Com troops. This is a behemoth of the deep. A carefully designed fighting creature of incredible strength and practically invulnerable to missile fire. Its pincers alone can crush steel.\"\n  STR_LOBSTERMAN_AUTOPSY: \"Lobsterman autopsy\"\n  STR_LOBSTERMAN_AUTOPSY_UFOPEDIA: \"Once past its virtually indestructible shell the creature is an amazing construction. Powerful muscles ripple around a titanium skeleton, a sophisticated targeting system with multi-band scanning ability is hooked directly into the creature's brain. Its multiple eyes are protected by harder than steel plastics and it is clear that when well deployed by their masters these creatures are all but unstoppable. Buried deep within its body are devices of unknown construction and function.\"\n  STR_TASOTH_UFOPEDIA: \"These agile and fast enemies are a mainstay of the alien army. Hundreds are birthed, in massive breeding vats deep in the heart of the Alien colonies. Vastly more powerful than a man, the Tasoth is a true alien and its behavior and carnivorous nature unmatched on the planet. The Tasoth often forms the spearhead of an alien attack and never seems to shrink from the fight even in the face of overwhelming odds.\"\n  STR_TASOTH_AUTOPSY: \"Tasoth autopsy\"\n  STR_TASOTH_AUTOPSY_UFOPEDIA: \"Dissection revealed a cybernetic organism possessed of strange power. Inside the body cavity is a small power unit, but no identifiable organs. The power is transmitted throughout the body by a Bio-electric transmission system. The whole body lacks bones or any other supporting structure. Once dead the power stops and the creature becomes a lifeless rag doll of oozing alien flesh and fluids. The only other internal construction is a pair of ceramic cells, which if energized briefly revive the creature.\"\n  STR_DEEP_ONE_UFOPEDIA: \"The Deep One is a biological nightmare, a cross breed, produced by the mind warping experiments of the Aquatoids. We have encountered several variations of this creature. After extensive research we conclude that these are manufactured by the invaders. Swelling their ranks when fresh human stock has been captured. Each of these sub-humans is armed with an electrical energy discharge powerful enough to kill an aquanaut.\"\n  STR_DEEP_ONE_AUTOPSY: \"Deep One autopsy\"\n  STR_DEEP_ONE_AUTOPSY_UFOPEDIA: \"The creature is a graft of man and alien organism. The human brain is massively altered to accommodate control electronics and the Alien cortex. All vestiges of the human body seem lost save one: the eyes. The surgical graft appears to allow the alien fetus to consume the human host as it grows. The tough skin of the creature appears to be a non-organic, metallic mesh, extremely strong and flexible. The resulting cross breed is strong, fast and utterly under the control of the aliens.\"\n  STR_BIODRONE_UFOPEDIA: \"The Bio-drone is a creation only an alien mind could conceive of. It is a brain, (human or alien) suspended in amniotic fluids and connected to a powered base unit that can fly on land or below water. Each Bio-drone is armed with a powerful auditory disruptor, part machine and part organism. Some of our scientists have suggested that the weapon is driven by the host organism's original vocal cords. Highly accurate and tenacious these super guard dogs are widely used by the aliens to protect valuable assets.\"\n  STR_BIODRONE_AUTOPSY: \"Bio-drone autopsy\"\n  STR_BIODRONE_AUTOPSY_UFOPEDIA: \"The hypothesis that the auditory disruptor is a biological device are true. This unfortunate creature literally screams its enemies to death. Every example has massive surgical trauma scars and is severely mutilated. The aliens appear to butcher the brain into obedience. Most of the cortex's used in the creatures are alien in origin, but nothing can compare to the horror of finding a human based unit. The Bio-drones are powered by an ION engine and incorporate some form of remote control system.\"\n  STR_TENTACULAT_UFOPEDIA: \"Not even the depths of a Lovecraftian nightmare could spawn such as this indescribable creature. No comparison to any Earth animal exists, the environment that could produce such as this is beyond imagination. Armed with long tentacles the Tentaculat paralyzes its victims then transmutes them into mindless things. These progeny can cause death on touch, even through armor. The Tentaculat is the most fearsome alien yet encountered by X-Com.\"\n  STR_TENTACULAT_AUTOPSY: \"Tentaculat autopsy\"\n  STR_TENTACULAT_AUTOPSY_UFOPEDIA: \"The autopsy reveals small cybernetic implants are lodged in the creature's large brain. The vision system is a complex combination of visible light and thermal imaging acquisition. Even in the inky depths of the ocean this monster can navigate with unerring accuracy. There are vestigial organs that seem to be the bare minimum for survival. Each creature has a small stomach with an external connector, it is logical to assume the being is fed by direct nutrient input by its masters.\"\n  STR_CALCINITE_UFOPEDIA: \"Like the diving suits of lost mariners these aliens stalk the seabed for the unwary. A vicious swipe by the creature's stronger than steel claws can be enough to send the best divers to the bottom. Swirling around in the face mask a gelatinous green form can be seen. No hint of the real creature can be divined from the often lethal encounters we have had with them.\"\n  STR_CALCINITE_AUTOPSY: \"Calcinite autopsy\"\n  STR_CALCINITE_AUTOPSY_UFOPEDIA: \"Once the armored suit is stripped away the Calcinite is revealed to be a huge amorphous blob of protoplasm. No visible brain, limbs or sensory organs exist, a small metallic component resides deep in the liquid body. Once dead we can only guess at the creature's nature. An inexplicable enigma of our alien enemies.\"\n  STR_TRISCENE_UFOPEDIA: \"This bipedal reptile is a throwback to the age of the Dinosaurs. It seems to be a Cretaceous creature in every sense save its ability to survive in water and on land. These creatures are slung with weapons pods and have a jaw lined with huge metallic teeth. Often these monsters have been at the core of the alien attack forces as the Aliens launch assaults upon the land. A heavyweight and potent weapon, the Tasoth commanders deploy them with lethal efficiency.\"\n  STR_TRISCENE_AUTOPSY: \"Triscene autopsy\"\n  STR_TRISCENE_AUTOPSY_UFOPEDIA: \"Once subjected to the scientist's knife the Triscene reveals that it is an ancient creature, supplemented with cybernetic implants and weapons systems. Its tiny brain is supplemented by a small computer module mounted in the control harness all the creatures wear. A tough natural skin, a predatory instinct enhanced by additional weapons makes this a lethal opponent in all environments.\"\n  STR_HALLUCINOID_UFOPEDIA: \"Having harvested the oceans the aliens have bred these huge Earth creatures as a weapon. Do not be lulled into a false sense of security when facing these harmless looking sailors of the deeps. Possessed of a close combat icy strike, the Hallucinoid is a deadly foe.\"\n  STR_HALLUCINOID_AUTOPSY: \"Hallucinoid autopsy\"\n  STR_HALLUCINOID_AUTOPSY_UFOPEDIA: \"Nested in the many layers of the gelatinous body of this organism is a powerful chemical freezer, its' main offensive capability. The soft and supple skin of the Hallucinoid seems susceptible to heat based attacks. Often this mutant is found in the company of its masters, the Aquatoids.\"\n  STR_XARQUID_UFOPEDIA: \"Another modified Earth invertebrate, the Xarquid is a creature of great beauty and danger. The swift swimming gargantuan hides a devastating arsenal of weapons, a smothering ink spray and an ionized particle blast. Since our first encounters with this powerful creature we have been wary of its power and its controllers the vengeful Gillmen.\"\n  STR_XARQUID_AUTOPSY: \"Xarquid autopsy\"\n  STR_XARQUID_AUTOPSY_UFOPEDIA: \"This overgrown Nautilus has been made huge on a diet of Alien drugs and surgical alterations. Perverted beyond the scope of nature, the Gillmen have added mechanical control systems to the creature and now none of the creature's original nature exists. Deployed as an organic weapons platform, the Xarquids tough shell and mobility make it a formidable opponent.\"\n  STR_ION_BEAM_ACCELERATORS_UFOPEDIA: \"Alien flying submarines rely on complex power systems to drive them at incredible speed through the deeps. The basis for their technology is the ION DISPLACER, utilizing Zrbite as a catalyst, the engines displace 100 times their own volume in water per second. This enormous power means that the aliens are capable of outrunning most Earth subs. We can replicate this system of propulsion using aqua-plastics and Zrbite power cells.\"\n  STR_MAGNETIC_NAVIGATION_UFOPEDIA: \"These units generate a spherical multi-layer magnetic field, which the array projects up to 1000m around the sub. The Alien navigators are directly linked into the machines and feel their way around the invisible world beneath the waves. The interface system operates using Alien modified cerebral matter that communicates directly with the operator's brain via a neural link.\"\n  STR_ALIEN_SUB_CONSTRUCTION_UFOPEDIA: \"Each vessel has a chameleon-like structure, carefully modelled on sea creatures, and constructed of Aqua Plastics. Each submarine functions as an organism: crew and craft in harmony. Most of these systems can be replicated and a hybrid technology can be evolved to allow us to move up to the same technological level.\"\n  STR_ALIEN_CRYOGENICS_UFOPEDIA: \"The innumerable Aliens that have lain hidden on the Earth are held in suspended animation, cryogenically frozen. All the creatures are sealed into units, their body temperature reduced to a point where bodily functions are all but stopped. An examination of the units so far reveals the unbelievable time periods that the bodies have been kept suspended for, some over 60 million years.\"\n  STR_ALIEN_CLONING_UFOPEDIA: \"Many of the Aliens we have captured are identical even down to their DNA, duplicates in every way. Cell samples are placed into the units from the frozen gene banks of the Aliens. Some units contain humans or body parts. It is possible that another use for these cloning units is to create some Alien-human hybrid.\"\n  STR_ALIEN_LEARNING_ARRAYS_UFOPEDIA: \"Utilizing Molecular Control Implants in the skulls of all Aliens these machines inject information directly into the brain. Freshly cloned Aliens are brought to these units and have racial memories and all scientific or combat information downloaded into their blank minds.\"\n  STR_ALIEN_IMPLANTER_UFOPEDIA: \"This unit is used to fit Aliens with Molecular Control Implants, fertilize reproducing races, and insert or remove organs and electronics from any creature. The process was thought to be done on subdued patients, but the subject is very aware of the process and unfortunately human anatomy seems to fit the unit perfectly.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"We now have the evidence to work out why Aliens capture humans. They are not food, they are not fertilized with Alien embryos, rather they form the basis of a range of creatures and control systems. Alien technology is based on a common mind, a shared intellect and the human brain is the ideal receptacle for these systems. Human brain tissue is used in most of the Alien biological computer storage and retrieval systems, the remains are used for building and for breeding.\"\n  STR_AQUA_PLASTICS_UFOPEDIA: \"Alien submarines and structures utilize an incredibly strong, flexible and durable material for the majority of their construction. Aqua plastics are complex multi-bonded and Zrbite catalyzed materials. Dense, yet light, the substance has strength above even Titanium or Kevlar.\"\n  STR_ZRBITE_UFOPEDIA: \"This is an alloy of Alien origin, part gold part Alien Bio-material. When utilized as a power source, small quantities will generate more power than a nuclear unit of 10 times the size. It is beyond our technical ability to replicate this material as most of its constituents are Alien in origin.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"The Aliens strike all across the globe, with ruthless efficiency. We cannot pin down their source. Could it be in some ocean deep too impenetrable for us to locate? Not all the organisms we have encountered are Alien, some are very old, some are from evolutionary paths long thought extinct. We are dealing with a menace that has been sleeping for millennia, a subtle symbiosis of human and Alien. Deep in the oceans there lie ancient sites used by the Aliens to contact their stellar cousins. Each of these twelve sites contains a Synomium device, a powerful Alien technology. Now with their war machine on the march the Aliens are re-activating these sites to widen their Molecular Control net, we must destroy these sites at all costs.\"\n  STR_THE_ULTIMATE_THREAT_UFOPEDIA: \"Sixty-five million years ago a vast colony ship was sent to the Earth from a distant Alien world. As the enormous craft approached the infant planet a massive and violent solar flare caused a navigation systems failure. Crippled and failing the vast bulk plummeted through the stratosphere to emerge into Cretaceous skies. On the Earth innumerable species of life strained their gazes skywards as their nemesis ploughed into the planet. A vast cloud of dust clogged the atmosphere and as the land cooled so the dominant life, the mighty dinosaurs, perished. But the 400 billion tonnes of T'leth was not destroyed in the impact, sophisticated super computers initiated a cryogenic sleep cycle for the creatures deep in its holds. As the aeons passed the computers woke parties of Aliens to attempt communication with their stellar cousins, all in vain for the core of the Alien power slept on.\"\n  STR_TLETH_THE_ALIEN_CITY: \"T'leth the Alien's City\"\n  STR_TLETH_THE_ALIEN_CITY_UFOPEDIA: \"T'leth the huge Alien colony ship lies embedded in the Sigsbee Deep, in the Gulf of Mexico.  At the Heart of the city is an Alien horror, so vile and so powerful that not even death can claim it. In a chamber of Alien metal lies the sleeping form of the great dreamer, the Ultimate Alien. Raising T'leth above the waves will begin his re-animation cycle, and once risen he will be unstoppable. Although not alive and somehow not dead the Alien mind controls the Alien army. The weird technology of molecular control connects all Aliens to the One mind and the One mind to all the Aliens. Genetically mutated Alien/human fetuses supply the Alien mind with energy and form the link between the ruler and his subjects. The myth of the Ultimate Alien has existed in the hearts and minds of humankind for centuries, the sea has always hidden the ultimate truth.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"CENTER ON SITE-TIME=5 Secs\"\n  STR_CANCEL_UC: \"CANCEL\"\n  STR_NONE: \"None\"\n  STR_UNKNOWN: \"Unknown\"\n  STR_POOR: \"Poor\"\n  STR_AVERAGE: \"Average\"\n  STR_GOOD: \"Good\"\n  STR_EXCELLENT: \"Excellent\"\n  STR_BUILD_NEW_BASE_UC: \"BUILD NEW BASE\"\n  STR_BASE_INFORMATION: \"BASE INFORMATION\"\n  STR_EQUIP_CRAFT: \"EQUIP SUBMARINE\"\n  STR_BUILD_FACILITIES: \"BUILD FACILITIES\"\n  STR_RESEARCH: \"RESEARCH\"\n  STR_MANUFACTURE: \"MANUFACTURE\"\n  STR_TRANSFER_UC: \"TRANSFER\"\n  STR_PURCHASE_RECRUIT: \"PURCHASE/RECRUIT\"\n  STR_SACK: \"SACK\"\n  STR_SELL_SACK_UC: \"SELL/SACK\"\n  STR_GEOSCAPE_UC: \"GEOSCAPE\"\n  STR_NAME: \"Name\"\n  STR_AREA: \"Area\"\n  STR_BUILD_NEW_BASE: \"Build New Base\"\n  STR_CANCEL: \"Cancel\"\n  STR_COST_UC: \"COST>\"\n  STR_CONSTRUCTION_TIME_UC: \"CONSTRUCTION TIME>\"\n  STR_DAY:\n    one: \"{N} day\"\n    other: \"{N} days\"\n  STR_HOUR:\n    one: \"{N} hour\"\n    other: \"{N} hours\"\n  STR_MAINTENANCE_UC: \"MAINTENANCE>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Installation\"\n  STR_CURRENT_RESEARCH: \"CURRENT RESEARCH\"\n  STR_SCIENTISTS_AVAILABLE: \"Scientists Available>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Scientists Allocated>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Laboratory Space Available>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"RESEARCH PROJECT\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"SCIENTISTS ALLOCATED\"\n  STR_PROGRESS: \"PROGRESS\"\n  STR_NEW_PROJECT: \"New Project\"\n  STR_CANCEL_PROJECT: \"CANCEL PROJECT\"\n  STR_NEW_RESEARCH_PROJECTS: \"NEW RESEARCH PROJECTS\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"SCIENTISTS AVAILABLE>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"LABORATORY SPACE AVAILABLE>{ALT}{0}\"\n  STR_INCREASE: \"Increase\"\n  STR_DECREASE: \"Decrease\"\n  STR_START_PROJECT: \"START PROJECT\"\n  STR_CURRENT_PRODUCTION: \"CURRENT PRODUCTION\"\n  STR_ENGINEERS_AVAILABLE: \"Technicians Available>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Technicians Allocated>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Workshop Space Available>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Current Funds>{ALT}{0}\"\n  STR_ITEM: \"ITEM\"\n  STR_ENGINEERS__ALLOCATED: \"Technicians Allocated\"\n  STR_UNITS_PRODUCED: \"Units Produced\"\n  STR_TOTAL_TO_PRODUCE: \"Total to Produce\"\n  STR_COST__PER__UNIT: \"Cost{NEWLINE}per{NEWLINE}Unit\"\n  STR_DAYS_HOURS_LEFT: \"Days/Hours Left\"\n  STR_NEW_PRODUCTION: \"New Production\"\n  STR_PRODUCTION_ITEMS: \"Production Items\"\n  STR_CATEGORY: \"CATEGORY\"\n  STR_START_PRODUCTION: \"START PRODUCTION\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} Technician hours to produce one unit\"\n  STR_COST_PER_UNIT_: \"Cost per unit>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Work Space Required>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"SPECIAL MATERIALS REQUIRED\"\n  STR_ITEM_REQUIRED: \"ITEM REQUIRED\"\n  STR_UNITS_REQUIRED: \"UNITS REQUIRED\"\n  STR_UNITS_AVAILABLE: \"UNITS AVAILABLE\"\n  STR_STOP_PRODUCTION: \"STOP PRODUCTION\"\n  STR_ENGINEERS_AVAILABLE_UC: \"TECHNICIANS AVAILABLE>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"WORKSHOP SPACE AVAILABLE>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"MONTHLY PROFIT>{ALT}{0}\"\n  STR_INCREASE_UC: \"INCREASE\"\n  STR_DECREASE_UC: \"DECREASE\"\n  STR_UNITS_TO_PRODUCE: \"Units to Produce\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Purchase/Hire Personnel\"\n  STR_COST_OF_PURCHASES: \"Cost of Purchases>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"COST PER UNIT\"\n  STR_QUANTITY_UC: \"QUANTITY\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"PERSONNEL AVAILABLE:PERSONNEL TOTAL>\"\n  STR_SOLDIERS: \"Aquanauts\"\n  STR_SCIENTISTS: \"Scientists\"\n  STR_ENGINEERS: \"Technicians\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"SPACE USED:SPACE AVAILABLE>\"\n  STR_LIVING_QUARTERS: \"Living Quarters\"\n  STR_STORES: \"Stores\"\n  STR_LABORATORIES: \"Laboratories\"\n  STR_WORK_SHOPS: \"Work Shops\"\n  STR_HANGARS: \"Flying Sub Pens\"\n  STR_SHORT_RANGE_DETECTION: \"Short Range Sonar\"\n  STR_DEFENSE_STRENGTH: \"Defense Strength\"\n  STR_TRANSFERS_UC: \"TRANSFERS\"\n  STR_TRANSFERS: \"Transfers\"\n  STR_ARRIVAL_TIME_HOURS: \"Arrival Time (hours)\"\n  STR_COST_: \"Cost>{ALT}{0}\"\n  STR_AREA_: \"Area>{ALT}{0}\"\n  STR_BASE_NAME: \"Base Name?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"SELECT POSITION FOR AIR-LOCK\"\n  STR_TRANSFER: \"Transfer\"\n  STR_AMOUNT_TO_TRANSFER: \"AMOUNT TO TRANSFER\"\n  STR_SELECT_DESTINATION_BASE: \"Select Destination Base\"\n  STR_COST: \"Cost\"\n\n  STR_INTRO_1: \"Copyright 1995 MicroProse\"\n  STR_INTRO_2: \"Mars: The fall of Cydonia.\"\n  STR_INTRO_3: \"A triumphant X-Com, having destroyed the very core of the Alien war machine, blasts off for home. However, all is not dead in the ravaged Martian base.\"\n  STR_INTRO_4: \"A powerful tachyon beam streams from the rubble of the Cydonian nerve center - hurtling through the void. Its destination............\"\n  STR_INTRO_5: \"Earth.\"\n  STR_INTRO_6: \"Deep in the ocean the beam strikes a long dormant receptor. Vast sleeping computers begin to stir. In the deep, beyond the sight of humans, vast chambers of sleeping Aliens begin their long re-animation cycle.\"\n  STR_INTRO_7: \"2040: An ignorant Earth. The terrors of the Alien war are forgotten. But, in the lost and hidden places of the ocean the Alien hordes are ready - ready to topple humankind and take over the world.\"\n  STR_INTRO_8: \"The Aliens strike against humankind; seeking specimens for their warped experiments; raiding the globe for valuable minerals and resources; and plundering from the seas. Then, the Aliens set their sights above the waves.\"\n  STR_INTRO_9: \"Powerful flying subs of strange design ply the oceans - looking, searching, hunting.........\"\n  STR_INTRO_10: \"Finding prey they attack.\"\n  STR_INTRO_11: \"Weird new weapons are brought to bear against a defenseless world. We are utterly at the mercy of the Alien threat.{NEWLINE}Only one organization can save us; but, we turned our backs on them long ago......\"\n  STR_INTRO_12: \"X-COM Experimental Underwater Facility\"\n  STR_INTRO_13: \"'Mayday! Mayday!' 'This is the transatlantic liner Hyperion'. 'We are under attack'. 'Mayday! Mayd............'\"\n  STR_INTRO_14: \"'Command Control to Sub Pen One: Open ocean doors', 'deploy Barracuda Zero One. We have an Alien attack situation - condition Red'.{NEWLINE}'I repeat: condition Red'\"\n  STR_INTRO_15: \"The Aliens are ruthless in their efficiency....\"\n  STR_INTRO_16: \"...unerring in their accuracy\"\n  STR_INTRO_17: \"'Barracuda Zero One to base' - 'approaching what's left of the Hyperion'.\"\n  STR_INTRO_18: \"'Decelerating'.{NEWLINE}'Two meters'{NEWLINE}'One meter'{NEWLINE}'All aquanauts prepare for immediate deployment'.\"\n  STR_INTRO_19: \"...........'Airlock cleared'...'approaching wreckage'.{NEWLINE}'Holy!'{NEWLINE}'Are you picking up those creatures on my suit cam?'\"\n\n  STR_GAMEOVER_1: \"We have failed, the Aliens have annihilated our last hopes of salvation.{NEWLINE}X-Com is destroyed and the Earth is laid at the feet of the ancient enemy.\"\n  STR_GAMEOVER_2: \"T'leth thunders high into the stratosphere and begins to move across the face of the world.  Dispensing death and harvesting the remnants of the human race. Deep in its bowels the murderous Alien mind begins to rouse itself.\"\n  STR_GAMEOVER_3: \"In the capital cities of all nations desperate plans are drawn up.  All is for naught, without the technology afforded by the X-Com research project our weapons are ineffectual.\"\n  STR_GAMEOVER_4: \"The Aliens set up bases at the polar caps and begin to melt the ice, the world will become a vast sea. The remains of the human race are rounded up and utilized in vile breeding experiments for unknown Alien ends. Skies darken and a mighty pestilence is upon the lands of the Earth.\"\n  STR_GAMEOVER_5: \"We can offer no resistance to the new world order, those that try meet a fiery fate at the hands of incomprehensible Alien weapons. For the rest of us no such blessed release, mother Earth becomes an Alien world and humankind is lost beneath a crawling horror.\"\n\n  STR_OUTRO_1: \"The Tomb, ravaged and decimated, a bubbling roar comes from the casket in its center.{NEWLINE}Fools you will all perish....................\"\n  STR_OUTRO_2: \".................none can escape.\"\n  STR_OUTRO_3: \"A massive explosion erupts from the tomb and rips through the city, debris and smoke fill the air. The plans of the Aliens are foiled........\"\n  STR_OUTRO_4: \"The twisting hugeness of T'leth begins to rupture. Flames and smoke spew from its gleaming spires and adamantium halls.\"\n  STR_OUTRO_5: \"The mighty Alien fastness tumbles towards the sea, the screams of tortured metal and souls fills the air. No longer will the Great Dreamer dream of conquering the world.\"\n  STR_OUTRO_6: \"One final ear-splitting concussion of sound and T'leth tears itself apart.{NEWLINE}The Alien threat is gone, the Earth is cleansed..................\"\n  STR_OUTRO_7: \"A sleepy blue-green planet, in a distant corner of the galaxy.\"\n  STR_OUTRO_8: \"The near future, a safe place to be.\"\n  STR_OUTRO_9: \"The Alien menace to the Earth has been long vanquished.\"\n  STR_OUTRO_10: \"Vast metropolis like cities house the teeming billions of humankind.\"\n  STR_OUTRO_11: \"The deeds of X-Com and the Alien wars are the stuff of children's stories.\"\n  STR_OUTRO_12: \"But legends have always had a habit of containing a grain of truth............\"\n\n  STR_RISE_1: \"T'leth, called many things in many legends from many lands.\"\n  STR_RISE_2: \"With an explosive scream that reverberates across the globe T'leth begins to rise from the seabed.\"\n  STR_RISE_3: \"The huge edifice surges through the waters of the Gulf of Mexico.\"\n  STR_RISE_4: \"400 billion tons of Alien metal, the mighty Alien city wherein lies the sleeping body of the Ultimate Alien. Imprisoned on earth for 65 million years this vile space God begins to stir.\"\n  STR_RISE_5: \"The waters boil and churn as the tomb of the Great Dreamer emerges into the light................\"\n  STR_RISE_6: \".........a light that will be short lived unless X-Com can destroy the Alien war machine.\"\n\n  STR_YOU_HAVE_FAILED: \"You have failed to stop the Alien war machine. The funding organizations, disillusioned with your ability try to negotiate a non military solution with the Aliens. The Invaders have a very different agenda and soon the whole world is aware of the truth...\"\n\n  STR_TOTAL_UC: \"TOTAL\"\n  STR_INCOME: \"Income\"\n  STR_EXPENDITURE: \"Expenditure\"\n  STR_MAINTENANCE: \"Maintenance\"\n  STR_BALANCE: \"Balance\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"Alien Activity in Seas\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"Alien Activity in Zones\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"X-Com Activity in Seas\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"X-Com Activity in Zones\"\n  STR_FINANCE: \"Finance\"\n  STR_DATE_FIRST: \"{0}st\"\n  STR_DATE_SECOND: \"{0}nd\"\n  STR_DATE_THIRD: \"{0}rd\"\n  STR_DATE_FOURTH: \"{0}th\"\n  STR_FINANCE_THOUSANDS: \"$1000's\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Not enough special materials to produce{NEWLINE}{0}{NEWLINE}at{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Not enough money to produce{NEWLINE}{0}{NEWLINE}at{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"Production of{NEWLINE}{0}{NEWLINE}at{NEWLINE}{1}{NEWLINE}is complete\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"Construction of{NEWLINE}{0}{NEWLINE}at{NEWLINE}{1}{NEWLINE}is complete\"\n  STR_OK_5_SECONDS: \"OK - 5 secs\"\n  STR_RESEARCH_COMPLETED: \"Research Completed\"\n  STR_VIEW_REPORTS: \"VIEW REPORTS\"\n  STR_WE_CAN_NOW_RESEARCH: \"We can now research\"\n  STR_WE_CAN_NOW_PRODUCE: \"We can now produce\"\n  STR_SUNDAY: \"SUNDAY\"\n  STR_MONDAY: \"MONDAY\"\n  STR_TUESDAY: \"TUESDAY\"\n  STR_WEDNESDAY: \"WEDNESDAY\"\n  STR_THURSDAY: \"THURSDAY\"\n  STR_FRIDAY: \"FRIDAY\"\n  STR_SATURDAY: \"SATURDAY\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Not enough {0} to refuel {1} at {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Not enough {0} to rearm {1} at {2}\"\n  STR_UFO_IS_NOT_RECOVERED: \"ALIEN SUB is not recovered\"\n  STR_UFO_IS_RECOVERED: \"ALIEN SUB is recovered\"\n  STR_CRAFT_IS_LOST: \"Flying Sub is lost\"\n  STR_TERROR_CONTINUES: \"Alien Activity continues\"\n  STR_ALIENS_DEFEATED: \"Aliens defeated\"\n  STR_BASE_IS_LOST: \"Base is lost\"\n  STR_BASE_IS_SAVED: \"Base is saved\"\n  STR_ALIEN_BASE_STILL_INTACT: \"Alien Colony still intact\"\n  STR_ALIEN_BASE_DESTROYED: \"Alien Colony destroyed\"\n  STR_ALIENS_KILLED: \"ALIENS KILLED\"\n  STR_ALIEN_CORPSES_RECOVERED: \"ALIEN CORPSES RECOVERED\"\n  STR_LIVE_ALIENS_RECOVERED: \"LIVE ALIENS RECOVERED\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"ALIEN ARTIFACTS RECOVERED\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"ALIEN COLONY CONTROL DESTROYED\"\n  STR_ALIEN_SYNOMIUM_DEVICE_DESTROYED: \"ALIEN SYNOMIUM DEVICE DESTROYED\"\n  STR_ALIEN_SYNOMIUM_DEVICE_FAILED: \"FAILED TO DESTROY SYNOMIUM DEVICE\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"CIVILIANS KILLED BY ALIENS\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"CIVILIANS KILLED BY X-COM OPERATIVES\"\n  STR_CIVILIANS_SAVED: \"CIVILIANS SAVED\"\n  STR_XCOM_OPERATIVES_KILLED: \"X-COM OPERATIVES KILLED\"\n\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"X-COM OPERATIVES MISSING IN ACTION\"\n  STR_TANKS_DESTROYED: \"X-COM WEAPONS PLATFORM DESTROYED\"\n  STR_XCOM_CRAFT_LOST: \"X-COM SUBMARINE LOST\"\n  STR_UFO_RECOVERY: \"ALIEN SUB RECOVERY\"\n  STR_ALIEN_BASE_RECOVERY: \"ALIEN COLONY RECOVERY\"\n  STR_BASE_UNDER_ATTACK: \"{0} under attack!\"\n  STR_BASE_DEFENSES_INITIATED: \"BASE DEFENSES INITIATED\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"SHIELDS REPEL ALIEN SUB!\"\n  STR_FIRING: \"FIRING\"\n  STR_HIT: \"HIT!\"\n  STR_UFO_DESTROYED: \"ALIEN SUB DESTROYED!\"\n  STR_MISSED: \"MISSED!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Sell Items/Sack Personnel\"\n  STR_VALUE_OF_SALES: \"VALUE OF SALES> {ALT}{0}\"\n  STR_FUNDS: \"FUNDS> {ALT}{0}\"\n  STR_SELL_SACK: \"Sell/Sack\"\n  STR_VALUE: \"Value\"\n  STR_CRAFT_: \"FLYING SUB> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n\n  STR_UFO_CRASH_RECOVERY: \"ALIEN SUB CRASH RECOVERY\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"EXTREME CAUTION - There will be Aliens in the submarine and around the site. This mission will be completed when all enemy units have been eliminated or neutralized. Recovery of Alien Sub remains, technology and alien corpses can then be initiated. To abort the mission return X-Com aquanauts to the submarine and click on the 'Abort Mission' icon.\"\n  STR_UFO_GROUND_ASSAULT: \"ALIEN SUBMARINE ASSAULT\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"Explore the touchdown site and, if possible, gain entry to the Alien Sub. The mission will be successful when all enemy units have been eliminated or neutralized. Recovery of the Alien Sub, artifacts and Alien corpses can then be initiated. To abort the mission return X-Com aquanauts to the submarine and click on the 'Abort Mission' icon.\"\n  STR_BASE_DEFENSE: \"BASE DEFENSE\"\n  STR_BASE_UC_: \"BASE> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"An Alien vessel has touched down nearby. Our base is in severe danger. As per standard procedure all non combat personnel and functional X-Com subs have been evacuated. Aliens will enter the base via Submarine Pen gates or the air-lock. Defend the base and its vital installations at all costs - this is a fight to the death. If you click on the 'abort mission' icon you will concede defeat and lose the base.\"\n\n  STR_ALIEN_COLONY_ATTACK_MISSION: \"ALIEN COLONY ATTACK MISSION\"\n  STR_ALIEN_BASE_ASSAULT: \"ALIEN COLONY PART ONE\"\n  STR_ALIEN_COLONY_P1_BRIEFING: \"This mission is a raid on an Alien colony site. There are 2 levels to the site, get all the aquanauts to the glowing exit in the first complex and click on the 'Abort Mission' icon to proceed. Any equipment left behind will stay on the seabed until the 2nd section is resolved. To quit, place aquanauts into the Submarine and click on the 'Abort Mission' icon.\"\n  STR_ALIEN_COLONY_P2: \"ALIEN COLONY PART TWO\"\n  STR_ALIEN_COLONY_P2_BRIEFING: \"Having negotiated the first level and entered the core of the colony. The mission is to now destroy the control center, the Synomium Device, or eliminate all Aliens. To abort place all aquanauts on the start point and click on 'Abort Mission' icon. All viable X-Com equipment will be returned to base. \"\n\n  STR_ALIENS_LAUNCH_PORT_TERROR: \"ALIENS LAUNCH{NEWLINE}PORT ATTACK ON\"\n  STR_PORT_TERROR: \"ALIENS LAUNCH PORT ATTACK\"\n  STR_PORT_TERROR_BRIEFING: \"Aliens have launched an attack against surface sites. The port and its civilian population have been put at risk. Your squad must eliminate all Aliens and protect the innocent bystanders from this Alien incursion. To quit, place aquanauts into the flying sub and click on the 'Abort Mission' icon.\"\n\n  STR_ALIENS_LAUNCH_ISLAND_TERROR: \"ALIENS LAUNCH{NEWLINE}ISLAND ATTACK ON\"\n  STR_ISLAND_TERROR: \"ALIENS LAUNCH ISLAND ATTACK\"\n  STR_ISLAND_TERROR_BRIEFING: \"Aliens have launched an attack against surface sites. The island and its civilian population have been put at risk. Your squad must eliminate all Aliens and protect the innocent bystanders from this Alien incursion. To quit, place aquanauts into the flying sub and click on the 'Abort Mission' icon.\"\n\n  STR_ALIENS_ATTACK_SHIPPING_ROUTE: \"ALIENS ATTACK{NEWLINE}SHIPPING ROUTE\"\n  STR_CARGO_SHIP_P1: \"CARGO SHIP PART ONE\"\n  STR_CARGO_SHIP_P2: \"CARGO SHIP PART TWO\"\n  STR_CRUISE_SHIP_P1: \"CRUISE SHIP PART ONE\"\n  STR_CRUISE_SHIP_P2: \"CRUISE SHIP PART TWO\"\n  STR_SHIP_RESCUE_MISSION: \"SHIP RESCUE MISSION\"\n  STR_SHIP_RESCUE_P1_BRIEFING: \"This mission is a bug hunt, eliminate all Alien units on the ship, and preserve the lives of any civilians onboard. The Aliens are dispersed above and below decks, secure the upper decks before entering the lower ones. To quit, place aquanauts into the flying sub and click on the 'Abort Mission' icon.\"\n  STR_SHIP_RESCUE_P2_BRIEFING: \"Now the upper deck is clear proceed to the lower decks. Using the cargo lift you descend into the hold. Your squad must eliminate all Aliens on this level to complete the mission. To abort place all aquanauts on the lift start point and click on 'Abort Mission' icon.\"\n\n  STR_ALIEN_ACTIVITY_DETECTED: \"ALIEN ACTIVITY DETECTED\"\n  STR_ALIEN_CONTACT_SITE_MISSION: \"ALIEN CONTACT SITE MISSION\"\n  STR_ARTIFACT_SITE_P1: \"ALIEN CONTACT SITE PART ONE\"\n  STR_ARTIFACT_SITE_P1_BRIEFING: \"This mission is a raid on a freshly activated Alien communications site. There are 2 levels to the site, the seabed with its Alien pyramids and a hidden Alien complex. Get all the aquanauts to the entrance of the complex and click on the 'Abort Mission' icon to proceed. To quit, place aquanauts into the flying sub and click on the 'Abort Mission' icon.\"\n  STR_ARTIFACT_SITE_P2: \"ALIEN CONTACT SITE PART TWO\"\n  STR_ARTIFACT_SITE_P2_BRIEFING: \"Having negotiated the Alien structures and entered the complex the mission goals are clear. Penetrate the heart of the Alien facility and destroy the Synomium Molecular Control Device to complete the mission. To abort place all aquanauts on the access lift start point and click on 'Abort Mission' icon.\"\n\n  STR_SIGSBEE_DEEP_MISSION: \"SIGSBEE DEEP MISSION{NEWLINE}ALIEN CITY LEVEL ONE\"\n  STR_TLETH_P1_BRIEFING: \"We are entering the unknown, from here on in there could be anything waiting for us. We know there are 2 further levels to the Alien city and your squad must race to the exit on this level to enter the next. Place all aquanauts on the exit and click the 'Abort Mission' icon to advance. Aborting elsewhere will terminate the mission.\"\n  STR_TLETH_ATTACK_MISSION: \"T'LETH ATTACK MISSION{NEWLINE}ALIEN CITY LEVEL TWO\"\n  STR_TLETH_P2_BRIEFING: \"Further into the unknown, from here on in there could be anything waiting for us. We know there is a further level to the Alien city and your squad must race to the exit on this level to enter the next. Place all aquanauts on the exit and click the 'Abort Mission' icon to advance. Aborting elsewhere will terminate the mission.\"\n  STR_FINAL_TLETH_MISSION: \"FINAL T'LETH MISSION{NEWLINE}ALIEN CITY LEVEL THREE\"\n  STR_TLETH_P3_BRIEFING: \"The end is in sight, from here on in we are searching for the crypt of the Ultimate Alien. Destroy the 8 power feeds to the tomb to finish off the Alien threat. Don't give up now! Aborting will terminate the mission.\"\n  STR_TLETH_P1: \"ALIEN CITY LEVEL ONE\"\n  STR_TLETH_P2: \"ALIEN CITY LEVEL TWO\"\n  STR_TLETH_P3: \"ALIEN CITY LEVEL THREE\"\n\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"NO FREE SUB PENS FOR CRAFT PRODUCTION!{SMALLLINE}Each Flying Sub assigned to a base, transferred to a base, purchased or constructed uses one Sub Pen. Build a new Sub Pen or transfer a sub to another base.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"NO FREE SUB PENS FOR PURCHASE!{SMALLLINE}Each Flying Sub assigned to a base, transferred to a base, purchased or constructed uses one Sub Pen. Build a new Sub Pen or transfer a sub to another base.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"NO FREE SUB PENS FOR TRANSFER!{SMALLLINE}Each Flying Sub assigned to a base, transferred to a base, purchased or constructed uses one Sub Pen. Build a new Sub Pen or transfer a sub to another base.\"\n  STR_CANNOT_BUILD_HERE: \"CANNOT BUILD HERE!{SMALLLINE}You must build next to an existing pod.\"\n  STR_NO_FREE_ACCOMODATION: \"NO FREE ACCOMMODATION!{SMALLLINE}The destination base does not have enough space in living quarters.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"NOT ENOUGH WORK SPACE AVAILABLE!{SMALLLINE}Build a new workshop or reduce work on other projects.\"\n  STR_NOT_ENOUGH_MONEY: \"NOT ENOUGH MONEY!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"NOT ENOUGH STORE SPACE!{SMALLLINE}Build a new store facility or transfer existing stores to other bases.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"NOT ENOUGH LIVING SPACE!{SMALLLINE}Build new living quarters or transfer personnel to other bases.\"\n  STR_LAUNCH_INTERCEPTION: \"LAUNCH INTERCEPTION\"\n  STR_CRAFT: \"CRAFT\"\n  STR_STATUS: \"STATUS\"\n  STR_BASE: \"BASE\"\n  STR_READY: \"READY\"\n  STR_OUT: \"OUT\"\n  STR_REPAIRS: \"REPAIRS\"\n  STR_REFUELLING: \"REFUELING\"\n  STR_REARMING: \"REARMING\"\n  STR_TARGET: \"TARGET: {0}\"\n  STR_WAY_POINT: \"WAY POINT\"\n  STR_ARE_YOU_SURE_CYDONIA: \"Are you sure you want to send this Sub on a mission to T'leth?\"\n  STR_YES: \"YES\"\n  STR_NO: \"NO\"\n  STR_SELECT_DESTINATION: \"SELECT DESTINATION\"\n  STR_CYDONIA: \"T'LETH\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"SELECT SITE FOR NEW BASE\"\n  STR_RETURN_TO_BASE: \"RETURN TO BASE\"\n  STR_SELECT_NEW_TARGET: \"SELECT NEW TARGET\"\n  STR_PATROL: \"PATROL\"\n  STR_STATUS_: \"STATUS>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"DAMAGED - RETURNING TO BASE\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"LOW FUEL - RETURNING TO BASE\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"MISSION COMPLETE - RETURNING TO BASE\"\n  STR_PATROLLING: \"PATROLLING\"\n  STR_TAILING_UFO: \"TAILING ALIEN SUB\"\n  STR_INTERCEPTING_UFO: \"INTERCEPTING ALIEN SUB-{0}\"\n  STR_RETURNING_TO_BASE: \"RETURNING TO BASE\"\n  STR_DESTINATION_UC_: \"DESTINATION: {0}\"\n  STR_BASE_UC: \"BASE>{ALT}{0}\"\n  STR_SPEED_: \"SPEED>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"MAXIMUM SPEED>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"DEPTH>{ALT}{0}\"\n  STR_AIRBORNE: \"AIRBORNE\"\n  STR_VERY_LOW: \"SHALLOW\"\n  STR_LOW_UC: \"NORMAL\"\n  STR_HIGH_UC: \"DEEP\"\n  STR_VERY_HIGH: \"VERY DEEP\"\n  STR_FUEL: \"FUEL>{ALT}{0}\"\n  STR_WEAPON_ONE: \"WEAPON-1>{ALT}{0}\"\n  STR_NONE_UC: \"NONE\"\n  STR_ROUNDS_: \"ROUNDS>{ALT}{0}\"\n  STR_WEAPON_TWO: \"WEAPON-2>{ALT}{0}\"\n\n  STR_INTERCEPTION_CRAFT: \"FLYING SUB\"\n  STR_BASE_: \"Base>{0}\"\n  STR_NAME_UC: \"NAME\"\n  STR_AMMO_: \"AMMO>{ALT}{0}\"\n  STR_CREW: \"CREW\"\n  STR_EQUIPMENT_UC: \"EQUIPMENT\"\n  STR_ARMOR: \"ARMOR\"\n  STR_MAX: \"MAX>{ALT}{0}\"\n  STR_ROOKIE: \"Seaman\"\n  STR_SQUADDIE: \"Able Seaman\"\n  STR_SERGEANT: \"Ensign\"\n  STR_CAPTAIN: \"Lieutenant\"\n  STR_COLONEL: \"Commander\"\n  STR_COMMANDER: \"Captain\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Select Squad for {0}\"\n  STR_SORT_BY: \"SORT BY...\"\n  STR_ORIGINAL_ORDER: \"ORIGINAL ORDER\"\n  STR_MISSIONS2: \"MISSIONS\"\n  STR_KILLS2: \"KILLS\"\n  STR_WOUND_RECOVERY2: \"WOUND RECOVERY\"\n  STR_SPACE_AVAILABLE: \"SPACE AVAILABLE>{ALT}{0}\"\n  STR_SPACE_USED: \"SPACE USED>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"SPACE USED\"\n  STR_RANK: \"RANK\"\n  STR_WOUNDED: \"WOUNDED\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Equipment for {0}\"\n  STR_DEFENSE_VALUE: \"Defense Value\"\n  STR_HIT_RATIO: \"Hit Ratio\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}ready to{NEWLINE}touchdown near{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"Begin Mission?\"\n  STR_SELECT_ARMAMENT: \"Select Armament\"\n  STR_AMMUNITION_AVAILABLE: \"AMMUNITION AVAILABLE\"\n  STR_ARMAMENT: \"ARMAMENT\"\n  STR_NOT_AVAILABLE: \"N.A.\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"SELECT ARMOR FOR{NEWLINE}{ALT}{0}\"\n  STR_TYPE: \"TYPE\"\n  STR_PLASTIC_AQUA_ARMOR_UC: \"PLASTIC AQUA ARMOR\"\n  STR_ION_ARMOR_UC: \"ION ARMOR\"\n  STR_MAGNETIC_ION_ARMOR_UC: \"MAGNETIC ION ARMOR\"\n\n  STR_PLASTIC_AQUA_ARMOR_UFOPEDIA: \"This Armor utilizes the newly discovered Alien substance, Aqua-plastic, and ensures our Aquanauts are given a fighting chance against the Alien incursion\"\n  STR_ION_ARMOR_UFOPEDIA: \"A powerful new protection for Aquanauts, this armor is powered by an ION energy source and greatly amplifies the speed and strength of the wearer, it offers the best protection yet for combat troops.\"\n  STR_MAGNETIC_ION_ARMOR_UFOPEDIA: \"An enhancement for the ION armor incorporating the Magnetic Array technology to allow full freedom of movement in the aquatic environment.\"\n  STR_SELECT_ARMOR: \"Select Armor\"\n  STR_NORTH: \"NORTH\"\n  STR_NORTH_EAST: \"NORTH EAST\"\n  STR_EAST: \"EAST\"\n  STR_SOUTH_EAST: \"SOUTH EAST\"\n  STR_SOUTH: \"SOUTH\"\n  STR_SOUTH_WEST: \"SOUTH WEST\"\n  STR_WEST: \"WEST\"\n  STR_NORTH_WEST: \"NORTH WEST\"\n  STR_SELECT_ACTION: \"SELECT ACTION\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"CONTINUE INTERCEPTION PURSUIT\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"PURSUE WITHOUT INTERCEPTION\"\n  STR_VERY_LARGE: \"VERY LARGE\"\n  STR_LARGE: \"LARGE\"\n  STR_MEDIUM_UC: \"MEDIUM\"\n  STR_SMALL: \"SMALL\"\n  STR_VERY_SMALL: \"VERY SMALL\"\n  STR_GROUNDED: \"TOUCHED DOWN\"\n  STR_DETECTED: \"Detected\"\n  STR_SIZE_UC: \"SIZE\"\n  STR_ALTITUDE: \"DEPTH\"\n  STR_HEADING: \"HEADING\"\n  STR_SPEED: \"SPEED\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"CENTER ON ALIEN SUB-TIME=5 Secs\"\n  STR_TRACKING_LOST: \"TRACKING LOST\"\n  STR_REDIRECT_CRAFT: \"REDIRECT CRAFT\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"GO TO LAST KNOWN ALIEN SUB POSITION\"\n  STR_UFO_: \"ALIEN SUB-{0}\"\n  STR_ALIEN_BASE_: \"ALIEN COLONY-{0}\"\n  STR_CRASH_SITE_: \"CRASH SITE-{0}\"\n  STR_LANDING_SITE_: \"TOUCHDOWN SITE-{0}\"\n  STR_WAY_POINT_: \"WAY POINT-{0}\"\n  STR_TERROR_SITE: \"TERROR SITE-{0}\"\n  STR_ARTIFACT_SITE: \"ARTIFACT SITE-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}has reached{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"Now patrolling\"\n  STR_ALIEN_ORIGINS: \"Alien Origins\"\n  STR_THE_ULTIMATE_THREAT: \"The Ultimate Threat\"\n  STR_TLETH_ALIEN_CITY: \"T'leth, the Alien's City\"\n  STR_UFOPAEDIA: \"UFOpedia\"\n  STR_XCOM_CRAFT_ARMAMENT: \"X-COM CRAFT & WEAPONS\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"SUBMERSIBLE WEAPONS SYSTEMS\"\n  STR_WEAPONS_AND_EQUIPMENT: \"GENERAL EQUIPMENT\"\n  STR_ALIEN_ARTIFACTS: \"AQUATIC ARTIFACTS\"\n  STR_BASE_FACILITIES: \"X-COM FACILITIES\"\n  STR_ALIEN_LIFE_FORMS: \"ALIEN CREATURES\"\n  STR_ALIEN_RESEARCH_UC: \"ALIEN TECHNOLOGY\"\n  STR_UFO_COMPONENTS: \"NEW SUBMERSIBLE TECHNOLOGIES\"\n  STR_UFOS: \"ALIEN SUBMARINES\"\n  STR_SELECT_ITEM: \"SELECT ITEM\"\n  STR_ACCELERATION: \"ACCELERATION>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"FUEL CAPACITY>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"WEAPON PODS>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"DAMAGE CAPACITY>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"CARGO SPACE>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"SWS CAPACITY>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Damage\"\n  STR_RANGE: \"Range\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Accuracy\"\n  STR_RE_LOAD_TIME: \"Re-load time\"\n  STR_SECONDS: \"{0}s\"\n  STR_DAMAGE_ARMOR_PIERCING: \"ARMOR PIERCING\"\n  STR_DAMAGE_INCENDIARY: \"PHOSPHOROUS\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"HIGH EXPLOSIVE\"\n  STR_DAMAGE_LASER_BEAM: \"GAUSS BEAM\"\n  STR_DAMAGE_PLASMA_BEAM: \"SONIC BEAM\"\n  STR_DAMAGE_STUN: \"FREEZE\"\n  STR_DAMAGE_MELEE: \"MELEE\"\n  STR_DAMAGE_ACID: \"ACID\"\n  STR_DAMAGE_SMOKE: \"SMOKE\"\n  STR_SHOT_TYPE: \"TYPE\"\n  STR_ACCURACY_UC: \"ACCURACY\"\n  STR_TIME_UNIT_COST: \"TU COST\"\n  STR_DAMAGE_UC: \"DAMAGE\"\n  STR_AMMO: \"AMMO\"\n  STR_SHOT_TYPE_AUTO: \"Auto\"\n  STR_SHOT_TYPE_SNAP: \"Snap\"\n  STR_SHOT_TYPE_AIMED: \"Aimed\"\n  STR_CONSTRUCTION_TIME: \"Construction Time\"\n  STR_CONSTRUCTION_COST: \"Construction Cost\"\n  STR_MAINTENANCE_COST: \"Maintenance Cost\"\n  STR_LOW: \"Low\"\n  STR_MEDIUM: \"Medium\"\n  STR_HIGH: \"High\"\n  STR_CRAFT_WEAPON: \"Sub Weapon\"\n  STR_CRAFT_AMMUNITION: \"Sub Ammunition\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Heavy Weapons System\"\n  STR_WEAPON: \"Weapon\"\n  STR_AMMUNITION: \"Ammunition\"\n  STR_EQUIPMENT: \"Equipment\"\n  STR_ALIEN_CORPSE: \"Alien Corpse\"\n  STR_UFO_COMPONENT: \"ALIEN SUB component\"\n  STR_PERSONAL_ARMOR: \"Personal Armor\"\n  STR_RAW_MATERIALS: \"Raw Materials\"\n  STR_HWP_SOLID_HARPOON_BOLTS: \"Solid Harpoon Bolts\"\n  STR_ALIEN: \"Alien\"\n\n  STR_AQUATOID: \"Aquatoid\"\n  STR_GILLMAN: \"Gill Man\"\n  STR_LOBSTERMAN: \"Lobster Man\"\n  STR_TASOTH: \"Tasoth\"\n  STR_CALCINITE: \"Calcinite\"\n  STR_DEEP_ONE: \"Deep One\"\n  STR_BIODRONE: \"Bio-drone\"\n  STR_TENTACULAT: \"Tentaculat\"\n  STR_TRISCENE: \"Triscene\"\n  STR_HALLUCINOID: \"Hallucinoid\"\n  STR_XARQUID: \"Xarquid\"\n  STR_ZOMBIE: \"Zombie\"\n\n  STR_LIVE_COMMANDER: \"Commander\"\n  STR_LIVE_NAVIGATOR: \"Navigator\"\n  STR_LIVE_MEDIC: \"Medic\"\n  STR_LIVE_TECHNICIAN: \"Technician\"\n  STR_LIVE_SQUAD_LEADER: \"Squad Leader\"\n  STR_LIVE_SOLDIER: \"Soldier\"\n  STR_LIVE_TERRORIST: \"Terrorist\"\n  STR_AQUATOID_COMMANDER: \"Aquatoid Commander\"\n  STR_AQUATOID_NAVIGATOR: \"Aquatoid Navigator\"\n  STR_AQUATOID_MEDIC: \"Aquatoid Medic\"\n  STR_AQUATOID_TECHNICIAN: \"Aquatoid Technician\"\n  STR_AQUATOID_SQUAD_LEADER: \"Aquatoid Squad Leader\"\n  STR_AQUATOID_SOLDIER: \"Aquatoid Soldier\"\n  STR_GILLMAN_COMMANDER: \"Gill Man Commander\"\n  STR_GILLMAN_TECHNICIAN: \"Gill Man Technician\"\n  STR_GILLMAN_SQUAD_LEADER: \"Gill Man Squad Leader\"\n  STR_GILLMAN_SOLDIER: \"Gill Man Soldier\"\n  STR_LOBSTERMAN_COMMANDER: \"Lobster Man Commander\"\n  STR_LOBSTERMAN_NAVIGATOR: \"Lobster Man Navigator\"\n  STR_LOBSTERMAN_TECHNICIAN: \"Lobster Man Technician\"\n  STR_LOBSTERMAN_SQUAD_LEADER: \"Lobster Man Squad Leader\"\n  STR_LOBSTERMAN_SOLDIER: \"Lobster Man Soldier\"\n  STR_TASOTH_SQUAD_LEADER: \"Tasoth Squad Leader\"\n  STR_TASOTH_SOLDIER: \"Tasoth Soldier\"\n  STR_CALCINITE_TERRORIST: \"Calcinite Terrorist\"\n  STR_DEEP_ONE_TERRORIST: \"Deep One Terrorist\"\n  STR_BIODRONE_TERRORIST: \"Bio-drone Terrorist\"\n  STR_TENTACULAT_TERRORIST: \"Tentaculat Terrorist\"\n  STR_TRISCENE_TERRORIST: \"Triscene Terrorist\"\n  STR_HALLUCINOID_TERRORIST: \"Hallucinoid Terrorist\"\n  STR_XARQUID_TERRORIST: \"Xarquid Terrorist\"\n\n  STR_ION_BEAM_ACCELERATORS: \"Ion-Beam Accelerators\"\n  STR_MAGNETIC_NAVIGATION: \"Magnetic Navigation\"\n  STR_ALIEN_SUB_CONSTRUCTION: \"Alien Sub Construction\"\n  STR_ALIEN_CRYOGENICS: \"Alien Cryogenics\"\n  STR_ALIEN_CLONING: \"Alien Cloning\"\n  STR_ALIEN_LEARNING_ARRAYS: \"Alien Learning Arrays\"\n  STR_ALIEN_IMPLANTER: \"Alien Implanter\"\n  STR_EXAMINATION_ROOM: \"Examination Room\"\n  STR_AQUA_PLASTICS: \"Aqua Plastics\"\n  STR_ALIEN_REANIMATION_ZONE: \"Alien Re-animation Zone\"\n\n  STR_PLASTIC_AQUA_ARMOR: \"Plastic Aqua-Armor\"\n  STR_ION_ARMOR: \"Ion Armor\"\n  STR_MAGNETIC_ION_ARMOR: \"Mag. Ion Armor\"\n  STR_HWP_AQUA_JET_MISSILES: \"Aqua Jet Torpedoes\"\n  STR_HWP_DISPLACER_PWT: \"P.W. Torpedo\"\n\n  STR_GAUSS_TECH: \"Gauss Technology\"\n  STR_NEW_FIGHTER_FLYING_SUB: \"New Fighter Flying Sub\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"New Fighter-Transporter\"\n  STR_THE_LATEST_FLYING_SUB: \"The Latest Flying Sub\"\n\n  STR_ARMOR_PIERCING: \"ARMOR PIERCING\"\n  STR_COELACANTH_GAS_CANNON: \"Coelacanth/G. Cannon\"\n  STR_COELACANTH_AQUA_JET: \"Coelacanth/Aqua Jet\"\n  STR_COELACANTH_GAUSS: \"Coelacanth/Gauss\"\n  STR_DISPLACER_SONIC: \"Displacer/Sonic\"\n  STR_DISPLACER_PWT: \"Displacer/P.W.T.\"\n  STR_AJAX_LAUNCHER: \"Ajax Launcher\"\n  STR_DUP_HEAD_LAUNCHER: \"D.U.P. Head Launcher\"\n  STR_CRAFT_GAS_CANNON: \"Craft Gas Cannon\"\n  STR_PWT_CANNON: \"P.W.T. Cannon\"\n  STR_GAUSS_CANNON: \"Gauss Cannon\"\n  STR_GAUSS_CANNON_AMMO: \"Gauss Cannon Ammo\"\n  STR_SONIC_OSCILLATOR: \"Sonic Oscillator\"\n  STR_AJAX_TORPEDOES: \"Ajax Torpedoes\"\n  STR_DUP_HEAD_TORPEDOES: \"D.U.P. Head Torpedoes\"\n  STR_CRAFT_GAS_CANNON_ROUNDS_X50: \"Gas Rounds(x50)\"\n  STR_SONIC_WAVE: \"Sonic Wave\"\n  STR_PULSE_WAVE_TORPEDOES: \"P.W.T. Ammo\"\n  STR_SOLDIER: \"Aquanaut\"\n  STR_SCIENTIST: \"Scientist\"\n  STR_ENGINEER: \"Technician\"\n\n\n  STR_NORTH_ATLANTIC: \"North Atlantic\"\n  STR_SOUTH_ATLANTIC: \"South Atlantic\"\n  STR_NORTH_PACIFIC: \"North Pacific\"\n  STR_SOUTH_PACIFIC: \"South Pacific\"\n  STR_MEDITERRANEAN: \"Mediterranean\"\n  STR_SOUTH_CHINA_SEA: \"South China Sea\"\n  STR_INDIAN_OCEAN: \"Indian Ocean\"\n  STR_THE_EAST_SEA: \"Sea of Japan\"\n  STR_NORTH_SEA: \"North Sea\"\n  STR_CARRIBEAN: \"Caribbean\"\n  STR_ANTARCTIC: \"Antarctic\"\n  STR_ARCTIC: \"Arctic\"\n  STR_EURASIA: \"Eurasia\"\n  STR_NORTH_AMERICA: \"North America\"\n  STR_AFRICA: \"Africa\"\n\n  STR_MAXIMUM_SPEED: \"Maximum Speed\"\n  STR_TRANSMISSION_RESOLVER_UC: \"TRANSMISSION RESOLVER\"\n\n  STR_TRITON: \"TRITON\"\n  STR_HAMMERHEAD: \"HAMMERHEAD\"\n  STR_LEVIATHAN: \"LEVIATHAN\"\n  STR_BARRACUDA: \"BARRACUDA\"\n  STR_MANTA: \"MANTA\"\n  STR_UFO: \"ALIEN SUB\"\n  STR_AJAX: \"AJAX\"\n  STR_DUP_HEAD: \"D.U.P. HEAD\"\n  STR_CRAFT_GAS_CANNON_UC: \"CRAFT GAS CANNON\"\n  STR_PWT_CANNON_UC: \"P.W.T. CANNON\"\n  STR_GAUSS_CANNON_UC: \"GAUSS CANNON\"\n  STR_SONIC_OSCILLATOR_UC: \"SONIC OSCILLATOR\"\n  STR_DAMAGE_CAPACITY: \"Damage Capacity\"\n  STR_WEAPON_POWER: \"Weapon Power\"\n  STR_WEAPON_RANGE: \"Weapon Range\"\n\n  STR_AIR_LOCK: \"Air-Lock\"\n  STR_LABORATORY: \"Laboratory\"\n  STR_WORKSHOP: \"Workshop\"\n  STR_STANDARD_SONAR: \"Standard Sonar\"\n  STR_WIDE_ARRAY_SONAR: \"Wide Array Sonar\"\n  STR_TORPEDO_DEFENSES: \"Torpedo Defenses\"\n  STR_GENERAL_STORES: \"General Stores\"\n  STR_ALIEN_CONTAINMENT: \"Alien Containment\"\n  STR_GAUSS_DEFENSES: \"Gauss Defenses\"\n  STR_SONIC_DEFENSES: \"Sonic Defenses\"\n  STR_PWT_DEFENSES: \"P.W.T. Defenses\"\n# STR_BOMBARDMENT_SHIELD: \"Pressure Bombardment Shield\"\n# STR_MC_GENERATOR: \"Molecular Control Shield\"\n# STR_MC_LAB: \"Molecular Control Laboratory\"\n# short versions for the list?\n  STR_BOMBARDMENT_SHIELD: \"Bombardment Shield\"\n  STR_MC_GENERATOR: \"M.C. Generator\"\n  STR_MC_LAB: \"M.C.-Lab\"\n  STR_TRANSMISSION_RESOLVER: \"Transmission Resolver\"\n  STR_SUB_PEN: \"Sub Pen\"\n\n  STR_USA: \"USA\"\n  STR_ALASKA: \"ALASKA\"\n  STR_EU_SYNDICATE: \"EURO-SYNDICATE\"\n  STR_ARABIAN_BLOC: \"ARABIAN BLOC\"\n  STR_EGYPTIAN_CARTEL: \"EGYPTIAN CARTEL\"\n  STR_AFRICA_CORP: \"AFRICA CORP\"\n  STR_BRAZILIAN_UNION: \"BRAZILIAN UNION\"\n  STR_NEW_MEXICO: \"NEW MEXICO\"\n  STR_ASIAN_COALITION: \"ASIAN COALITION\"\n  STR_SCANDINAVIA: \"SCANDINAVIA\"\n  STR_NEO_JAPAN: \"NEO-JAPAN\"\n  STR_FREE_CHINA: \"FREE CHINA\"\n  STR_AUSTRALASIA: \"AUSTRALASIA\"\n  STR_FED_KOREA: \"FED KOREA\"\n  STR_EURASIA_UC: \"EURASIA\"\n  STR_ICELANDIC_UNION: \"ICELANDIC UNION\"\n  STR_TANK: \"Submersible Weapons System\"\n  STR_CIVILIAN: \"Civilian\"\n  STR_JAN: \"Jan\"\n  STR_FEB: \"Feb\"\n  STR_MAR: \"Mar\"\n  STR_APR: \"Apr\"\n  STR_MAY: \"May\"\n  STR_JUN: \"Jun\"\n  STR_JUL: \"Jul\"\n  STR_AUG: \"Aug\"\n  STR_SEP: \"Sep\"\n  STR_OCT: \"Oct\"\n  STR_NOV: \"Nov\"\n  STR_DEC: \"Dec\"\n  STR_INTERNATIONAL_RELATIONS: \"International Relations\"\n  STR_COUNTRY: \"Country\"\n  STR_FUNDING: \"Funding\"\n  STR_CHANGE: \"Change\"\n  STR_WEAPON_SYSTEMS: \"WEAPON SYSTEMS\"\n  STR_HWPS: \"SWSs\"\n  STR_DAMAGE_UC_: \"DAMAGE>{ALT}{0}\"\n\n  STR_AIR_LOCK_UFOPEDIA: \"The Air-lock allows equipment and personnel to be transferred into or out of an undersea base. It is always the first facility to be constructed at a new site. The Air-lock area is vulnerable to intrusion from any potential hostile force.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Each accommodation area provides for up to 50 personnel. The facilities are somewhat basic and functional.\"\n  STR_LABORATORY_UFOPEDIA: \"Fifty scientists can work in a single laboratory block. Laboratories are equipped with all the latest technologies for research into materials, biochemistry and weaponry. X-Com has access to all the best research labs throughout the world, both civilian and military.\"\n  STR_WORKSHOP_UFOPEDIA: \"A workshop contains all the equipment necessary to manufacture equipment based on the latest designs from the science labs. 50 Technicians can occupy one workshop, items under construction will also consume space.\"\n  STR_STANDARD_SONAR_UFOPEDIA: \"A standard sonar system has an effective range of over 450 kilometers at most depths and is linked to geostationary satellite nets for surface analysis. Each scanner has a 10% chance of detecting a submersible or airborne craft per 30 minute scan cycle.\"\n  STR_WIDE_ARRAY_SONAR_UFOPEDIA: \"A wide array sonar system has an effective range of over 700 kilometers at all depths and is linked to geostationary satellite nets for surface analysis. Each scanner has a 20% chance of detecting a submersible or airborne craft every 30 minute scan cycle.\"\n  STR_TORPEDO_DEFENSES_UFOPEDIA: \"Torpedo defense systems provide protection against attack by hostile submersibles which are attempting to dock at the base.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"All equipment, weapons systems, munitions, recovered material and Submersible Weapons Systems are placed in stores, including equipment assigned to Subs in Pens.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"Live Aliens will require special containment facilities to hold them. These units maintain their life systems and render their combat potential to zero. The containment facility can keep 10 Alien life forms in confinement units.\"\n  STR_GAUSS_DEFENSES_UFOPEDIA: \"The Gauss defense provides the latest and most effective protection against attack by hostile submarines.\"\n  STR_SONIC_DEFENSES_UFOPEDIA: \"Sonic Oscillator defenses provide powerful and efficient protection against aggressors.\"\n  STR_PWT_DEFENSES_UFOPEDIA: \"Pulse Wave Torpedoes provide the most effective defense against Alien attacks. These missiles have super dense war heads which can penetrate all known armor. The magnetic waves they produce disable electronic defenses.\"\n  STR_BOMBARDMENT_SHIELD_UFOPEDIA: \"The Pressure Bombardment shield protects the base from Alien submersibles docking and sets up a resonating field that repulses attacking subs long enough for defense systems to fire repeatedly. In effect this doubles the effectiveness of any defense systems already deployed.\"\n  STR_MC_GENERATOR_UFOPEDIA: \"Since Alien subs utilize Molecular Control Technology to detect the presence of living creatures, using a negative M.C. emitter will blanket a base with an impenetrable shield to confuse the Aliens and disguise our presence.\"\n  STR_MC_LAB_UFOPEDIA: \"The Molecular Control lab can implant and train up to ten aquanauts at one time. Implants are surgically installed in the skulls of aquanauts. Extensive training allows them to utilize their implants. Implant skills are used in conjunction with a Molecular Device and can be used for attacks during combat.\"\n  STR_TRANSMISSION_RESOLVER_UFOPEDIA: \"Alien communications utilize the Molecular control implant network the Aliens have built up. The transmission resolver facility intercepts Alien Sub transmissions and decodes the information. This will show the type of Alien Sub, the Alien race and the type of activity that is occurring.\"\n  STR_SUB_PEN_UFOPEDIA: \"Each Pen can accommodate one submarine. There are facilities for maintenance, refueling and repair of the X-Com submarine fleet. Each Flying Sub stationed at a base must have a free Pen assigned to it which cannot be used by other Subs, even if the assigned submarine is out on a mission.\"\n  STR_DART_PISTOL_UFOPEDIA: \"The X-Com dart gun is a small, accurate, high powered unit with a 12 hollow dart ammo clip. The darts are fired by a gas cartridge in the ammo pod.\"\n  STR_JET_HARPOON_UFOPEDIA: \"This aqua-rifle is accurate and powerful, firing hollow steel harpoons from sealed packs of 10. Each harpoon has its own gas reservoir.\"\n  STR_GAS_CANNON_UFOPEDIA: \"The heavyweight of the gas technology family, this cannon fires solid bolts, some with HE or phosphor tips. A favorite weapon amongst experienced aquanauts.\"\n  STR_HYDRO_JET_CANNON_UFOPEDIA: \"Hydro-Jet Cannons are a heavy infantry weapon system. The cannon fires magnesium fueled mini-torpedoes. Although powerful, the Hydro-Jet Cannon is a clumsy and unwieldy device, suitable for aquatic use only.\"\n  STR_TORPEDO_LAUNCHER_UFOPEDIA: \"A real heavyweight, this large launcher fires three types of torpedo, each with its own propulsion unit. A devastating weapon, with only manual loading being its drawback. Ammunition types available include large or small high explosive and phosphor tipped torpedoes, all for submerged use only.\"\n  STR_GAUSS_PISTOL_UFOPEDIA: \"The Gauss pistol uses accelerated particle technology, a new development in modern weaponry. It is fast, accurate and functions above and below water. Gauss technology is a development of the Plasma technologies learned from the previous war.\"\n  STR_GAUSS_PISTOL_CLIP_UFOPEDIA: \"The Gauss pistol uses accelerated particle technology, a new development in modern weaponry. It is fast, accurate and functions above and below water. Gauss technology is a development of the Plasma technologies learned from the previous war.\"\n  STR_GAUSS_RIFLE_UFOPEDIA: \"A step beyond the Gauss pistol, the rifle packs a real punch, with its twin particle accelerators. Replacing the Elerium powered Plasma system we have utilized a micro particle accelerator that generates a stream of anti-protons.\"\n  STR_GAUSS_RIFLE_CLIP_UFOPEDIA: \"A step beyond the Gauss pistol, the rifle packs a real punch, with its twin particle accelerators. Replacing the Elerium powered Plasma system we have utilized a micro particle accelerator that generates a stream of anti-protons.\"\n  STR_HEAVY_GAUSS_UFOPEDIA: \"The heavy Gauss is cumbersome, but extremely effective. It operates with 3 particle accelerators and is virtually unstoppable. The anti-proton stream is confined inside a Gallium Arsenide shell that implodes on impact releasing the anti-matter.\"\n  STR_HEAVY_GAUSS_CLIP_UFOPEDIA: \"The heavy Gauss is cumbersome, but extremely effective. It operates with 3 particle accelerators and is virtually unstoppable. The anti-proton stream is confined inside a Gallium Arsenide shell that implodes on impact releasing the anti-matter.\"\n  STR_MAGNA_BLAST_GRENADE_UFOPEDIA: \"This standard issue grenade has an accurate and sophisticated timer for precision control.\"\n  STR_DYE_GRENADE_UFOPEDIA: \"Dye grenades are dual role items, useful for providing cover in exposed situations. Functioning in both water and land environments the dye is ejected as a particle cloud, producing an octopus like ink spray in water or dense air borne cloud on land.\"\n  STR_PARTICLE_DISTURBANCE_GRENADE_UFOPEDIA: \"A proximity grenade which can be thrown like an ordinary grenade but is triggered by nearby movement after it is deployed. Skill and training are required to use these devices properly.\"\n  STR_MAGNA_PACK_EXPLOSIVE_UFOPEDIA: \"This explosive should only be used for demolition purposes. However past experience has shown that these powerful explosive packs are ideal weapons for rooting out Aliens. The blast radius is large so ensure no aquanauts are within the minimum safe distance.\"\n  STR_PARTICLE_DISTURBANCE_SENSOR_UFOPEDIA: \"This new device uses a variety of detectors and advanced computer systems to identify moving enemy units. Click on the Disturbance Sensor icon on the tactical display. Select 'Use Sensor' from the menu. The Sensor display shows an arrow in the center which is the direction the aquanaut is facing (North is at the top). The blips show units which have moved recently. Large units, or fast moving units, will produce larger blips. Static units will not show up.\"\n  STR_MEDI_KIT_UFOPEDIA: \"To use this you face the injured X-Com agent or stand over the body of a stunned aquanaut.{NEWLINE}HEALING> Red indicates wounds. Select body part and click on the 'Heal' button. One fatal wound will be healed and health restored.{NEWLINE}STIMULANT> Restores energy and revives stunned aquanauts. To revive an unconscious aquanaut you must stand directly over the body.{NEWLINE}PAIN KILLER> Restores the morale of wounded aquanauts.\"\n  STR_MC_DISRUPTOR_UFOPEDIA: \"The ultimate in M.C. technology. This can only be used by aquanauts with M.C. skills. Click on the Disruptor, select the type of attack, and select a target unit with the cursor. There are two types of Disruptor attack:{NEWLINE}JAM IMPLANT> If successful the unit becomes confused and it may panic.{NEWLINE}CONTROL IMPLANT> If successful you will gain control of the enemy unit.\"\n  STR_THERMAL_TAZER_UFOPEDIA: \"This device can only be used in close combat, but will stun a living organism without killing it by freezing the creature.\"\n  STR_VIBRO_BLADE_UFOPEDIA: \"The Vibroblade is a long sharp knife blade of titanium which spins at over 6000 rpm, this device can crack even the toughest diving armor. The power source is an Alien invention, our attempt at building these items before met with dismal failure, our blades rotated too slowly or exploded under pressure.\"\n  STR_THERMIC_LANCE_UFOPEDIA: \"The Thermic Lance is a logical extension of the Vibroblade technology The blade revolves at high speed and a Zrbite power source superheats the blade to cut armor like a warm knife through butter.\"\n  STR_HEAVY_THERMIC_LANCE_UFOPEDIA: \"The Heavy Thermic Lance is a more powerful version of the TL. Twin heat sources and a extremely high rotation speed means that the Heavy Thermic lance is virtually unstoppable against all materials.\"\n  STR_SONIC_CANNON_UFOPEDIA: \"The Sonic Cannon the most potent of the Sonic weapons family. Featuring a higher range audio oscillator and a larger reverberation chamber than the Blasta. The Cannon also has a pulse detonation system that alters the ultra-sonic wave by modulation to produce a more effective Sonic Shock.\"\n  STR_CANNON_POWER_CLIP_UFOPEDIA: \"This compact device is used as ammunition for a Sonic Cannon. It contains a small quantity of Zrbite.\"\n  STR_SONIC_BLASTA_RIFLE_UFOPEDIA: \"A more powerful Sonic device. Not even high carbon steel is immune to this weapon. The highly compact wave emitter is enhanced by a super conductor amplifier to increase the power of this weapon.\"\n  STR_BLASTA_POWER_CLIP_UFOPEDIA: \"This small object is used as a power source for a Sonic Rifle, a potent Alien weapon, and contains a small quantity of Zrbite.\"\n  STR_SONIC_PISTOL_UFOPEDIA: \"Sonic pistols are an Alien weapon based on ultra-sonic audio waves that can jellify bone in seconds. The Ultra-Sonic waves occupy a range beyond the scope of human hearing.\"\n  STR_PISTOL_POWER_CLIP_UFOPEDIA: \"Power source for the compact Alien Sonic Pistol. Contains Zrbite - the source of all Alien power.\"\n  STR_DISRUPTOR_PULSE_LAUNCHER_UFOPEDIA: \"This is an Alien aquatic use only guided weapon firing self propelled 'Disruptor Projectiles'. When you click to fire the weapon it will generate 'way points' for the Projectile to follow. When you have positioned enough way points click on the launch icon.\"\n  STR_DISRUPTOR_AMMO_UFOPEDIA: \"This device is a Disruptor Pulse Projectile fitted with an onboard computer guidance system. It is fired from a Disruptor Pulse launcher.\"\n  STR_THERMAL_SHOK_LAUNCHER_UFOPEDIA: \"A small Thermal Shok launcher which fires chemical freeze bombs. Very useful for capturing live Aliens.\"\n  STR_THERMAL_SHOK_BOMB_UFOPEDIA: \"The Thermal Shok bomb is used for capturing live humans, but it can also be used against most Alien races. It is fired from a Thermal Shok Launcher.\"\n  STR_SONIC_PULSER_UFOPEDIA: \"This device works in the same way as a standard issue grenade - except that it is many times more powerful. The grenade uses a single pulse sonic blast that is emitted in all directions simultaneously.\"\n  STR_MC_READER_UFOPEDIA: \"Inside the bodies of Aliens we have found small surgically implanted units. These are Control Implants designed by the Aquatoids to allow the constant supply of information from the battlefield, even at great distances. The Molecular Control Reader is an Alien communication device which is used to take information directly from M.C. Implants. X-Com units can use this device in combat to display an Alien's characteristics. Select the 'use' option. Then click on an Alien with the cursor.\"\n\n  STR_SURVEY_SHIP: \"Survey Ship\"\n  STR_ESCORT: \"Escort\"\n  STR_CRUISER: \"Cruiser\"\n  STR_HEAVY_CRUISER: \"Heavy Cruiser\"\n  STR_HUNTER: \"Hunter\"\n  STR_BATTLESHIP: \"Battleship\"\n  STR_DREADNOUGHT: \"Dreadnought\"\n  STR_FLEET_SUPPLY_CRUISER: \"Fleet Supply Cruiser\"\n\n  MAP_SEABED: \"Seabed\"\n  MAP_PIPES: \"Research Facility\"\n  MAP_PLANE: \"Crashed Plane\"\n  MAP_ATLAN: \"Atlantis\"\n  MAP_MU: \"Mayan Temple\"\n  MAP_GAL: \"Sunken Galleon\"\n  MAP_MSUNK: \"Sunken Liner\"\n  MAP_VOLC: \"Volcanic\"\n  MAP_CORAL: \"Coral\"\n  MAP_PORT: \"Port\"\n  MAP_ISLAND: \"Island\"\n  MAP_CARGO: \"Cargo Ship\"\n  MAP_LINERT: \"Cruise Ship P1\"\n  MAP_LINERB: \"Cruise Ship P2\"\n  MAP_ALART: \"Artefact P1\"\n  MAP_GRUNGE: \"Artefact P2\"\n  MAP_ENTRY: \"Colony P1\"\n  MAP_A_BASE: \"Colony P2\"\n  MAP_ALSHIP: \"T'leth P1\"\n  MAP_LEVEL: \"T'leth P2\"\n  MAP_CRYPT: \"T'leth P3\"\n  MAP_XBASES: \"X-Com Base\"\n\n  STR_MIXED_CREW: \"Mixed Crew\"\n  STR_MIXED_CREW_2: \"Mixed Crew 2\"\n\n  STR_RATING: \"RATING> {0}\"\n  STR_RATING_TERRIBLE: \"TERRIBLE!\"\n  STR_RATING_POOR: \"POOR!\"\n  STR_RATING_OK: \"OK\"\n  STR_RATING_GOOD: \"GOOD!\"\n  STR_RATING_EXCELLENT: \"EXCELLENT!\"\n  STR_SCORE: \"SCORE\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"X-COM MONTHLY REPORT\"\n  STR_MONTH: \"Month> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"The committee of funding organizations is generally satisfied with your progress so far.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"The committee of funding organizations is very pleased with your excellent progress. Keep up the good work.\"\n  STR_COUNCIL_IS_DISSATISFIED: \"The committee of funding organizations is dissatisfied with your performance. You must improve your effectiveness in dealing with the Alien menace or risk termination funding support for X-Com.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"You have not succeeded in dealing with the Alien invasion and the committee of funding organizations has regrettably decided to terminate funding X-Com. Each organization shall deal with the problem as they see fit. We can only hope that we can come to some accommodation with these ancient forces, and that the general population will come to terms with the aquatic visitors.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} is particularly pleased with your ability to deal with the localized threat and has agreed to increase its funding.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} are particularly happy with your progress in dealing with local Alien incursion and have agreed to increase their funding.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} and {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} is unhappy with your ability to deal with Alien activity in its Seas and has decided to reduce its financial commitment.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} are unhappy with your ability to deal with Alien activity in their Sea and have decided to reduce their funding.\"\n  STR_KNOTS: \"{0} knots\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} has signed a co-operation agreement with the Alien forces and has withdrawn from X-Com funding.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} have signed a co-operation agreement with Alien forces and have withdrawn from the X-Com funding.\"\n  STR_MONTHLY_RATING: \"Monthly Rating> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Funding change> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"The funding organization is not happy with your financial position. You must reduce your debts below $1 million or the X-Com will be terminated.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"SUB-PARTICLE TRANSMISSIONS RESOLVED\"\n  STR_CRAFT_TYPE: \"SUB TYPE\"\n  STR_RACE: \"RACE\"\n  STR_MISSION: \"MISSION\"\n  STR_ZONE: \"ZONE\"\n  STR_ALLOCATE_RESEARCH: \"Allocate Research\"\n  STR_ALLOCATE_MANUFACTURE: \"Allocate Manufacture\"\n\n  STR_AZORES: \"Azores\"\n  STR_REYKJAVIK: \"Reykjavik\"\n  STR_BERMUDA: \"Bermuda\"\n  STR_NEW_YORK: \"New York\"\n  STR_BOSTON: \"Boston\"\n  STR_FORT_SEVERN: \"Fort Severn\"\n  STR_DAKAR: \"Dakar\"\n  STR_RECIFE: \"Recife\"\n  STR_ACCRA: \"Accra\"\n  STR_ASCENSION_ISLAND: \"Ascension Island\"\n  STR_TRINIDADE_ISLAND: \"Trindade Island\"\n  STR_FALKLAND_ISLAND: \"Falkland Island\"\n  STR_CANARY_ISLANDS: \"Canary Islands\"\n  STR_ANCHORAGE: \"Anchorage\"\n  STR_ST_LAWRENCE_ISLAND: \"St Lawrence Island\"\n  STR_SAN_FRANCISCO: \"San Francisco\"\n  STR_MIDWAY_ISLAND: \"Midway Island\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_TASMANIA: \"Tasmania\"\n  STR_HAWAII: \"Hawaii\"\n  STR_FIJI: \"Fiji\"\n  STR_TONGA: \"Tonga\"\n  STR_EASTER_ISLAND: \"Easter Island\"\n  STR_GALAPAGOS_ISLAND: \"Galapagos Island\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_SOLOMON_ISLAND: \"Solomon Island\"\n  STR_CRETE: \"Crete\"\n  STR_LISBON: \"Lisbon\"\n  STR_PORT_SAID: \"Port Said\"\n  STR_MARSEILLES: \"Marseilles\"\n  STR_TRIPOLI: \"Tripoli\"\n  STR_MANILA: \"Manila\"\n  STR_HONG_KONG: \"Hong Kong\"\n  STR_SINGAPORE: \"Singapore\"\n  STR_BANGKOK: \"Bangkok\"\n  STR_DARWIN: \"Darwin\"\n  STR_BOMBAY: \"Bombay\"\n  STR_SAYCHELLES_ISLAND: \"Seychelles Island\"\n  STR_MALDIVE_ISLAND: \"Maldive Island\"\n  STR_SRI_LANKA: \"Sri Lanka\"\n  STR_MAURITIUS: \"Mauritius\"\n  STR_TOKYO: \"Tokyo\"\n  STR_SHANGHAI: \"Shanghai\"\n  STR_VLADIVOSTOK: \"Vladivostok\"\n  STR_LONDON: \"London\"\n  STR_FAEROE_ISLAND: \"Faeroe Island\"\n  STR_ABERDEEN: \"Aberdeen\"\n  STR_OSLO: \"Oslo\"\n  STR_JAMAICA: \"Jamaica\"\n  STR_PANAMA: \"Panama\"\n  STR_MIAMI: \"Miami\"\n\n  STR_PSI_TRAINING: \"M.C. Training\"\n  STR_PSIONIC_TRAINING: \"MOLECULAR CONTROL TRAINING\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Remaining M.C. capacity> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"M.C.{NEWLINE}Strength\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"M.C. Skill{NEWLINE}/Improvement\"\n  STR_IN_TRAINING: \"In{NEWLINE}Training?\"\n  STR_TARGETTED_BY: \"TARGETTED BY:\"\n  STR_WEAPONS_CREW_HWPS: \"WEAPONS/{NEWLINE}CREW/SWSs\"\n\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"is low on fuel,{NEWLINE}returning to base\"\n  STR_SOLDIER_LIST: \"Aquanaut List\"\n  STR_RANK_: \"RANK> {ALT}{0}\"\n  STR_MISSIONS: \"MISSIONS> {ALT}{0}\"\n  STR_KILLS: \"KILLS> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"WOUND RECOVERY> {ALT}{0}\"\n  STR_TIME_UNITS: \"TIME UNITS\"\n  STR_STAMINA: \"STAMINA\"\n  STR_HEALTH: \"HEALTH\"\n  STR_BRAVERY: \"BRAVERY\"\n  STR_REACTIONS: \"REACTIONS\"\n  STR_FIRING_ACCURACY: \"FIRING ACCURACY\"\n  STR_THROWING_ACCURACY: \"THROWING ACCURACY\"\n  STR_STRENGTH: \"STRENGTH\"\n  STR_PSIONIC_STRENGTH: \"M.C. STRENGTH\"\n  STR_PSIONIC_SKILL: \"M.C. SKILL\"\n  STR_NEW_RANK: \"NEW RANK\"\n  STR_PROMOTIONS: \"Promotions\"\n  STR_SOLDIERS_UC: \"AQUANAUTS\"\n  STR_COELACANTH_GAS_CANNON_UFOPEDIA: \"Automated SWS's have high maneuverability and hull strength. They provide heavy troop support at all depths. SWS's are re-armed automatically if you have enough ammunition.\"\n  STR_COELACANTH_AQUA_JET_UFOPEDIA: \"This submersible is armed with Aqua-Jet torpedoes. This weapon system only functions underwater. Ensure stores are well stocked with Aqua-Jet Torpedoes.\"\n  STR_COELACANTH_GAUSS_UFOPEDIA: \"Gauss technology provides a powerful weapon system for SWS's. Offering heavy firepower compared with earlier models, and uses proprietary X-Com technology.\"\n  STR_DISPLACER_SONIC_UFOPEDIA: \"Alien technology has redefined the SWS. The ability to utilize Ion Displacers means that SWS's are no longer restricted to the land/seabed. Sonic weaponry gives a real advantage in battle.\"\n  STR_DISPLACER_PWT_UFOPEDIA: \"This SWS features Pulse Wave weapons for aquatic use. You must manufacture PWT's to keep them fully armed. To fire, select a number of 'way points' then click on the launch icon.\"\n\n  STR_ALIEN_PROBE_MISSION: \"Alien Probe Mission\"\n  STR_ALIEN_INTERDICTION: \"Alien Interdiction\"\n  STR_ALIEN_RESOURCE_RAID: \"Alien Resource Raid\"\n  STR_ALIEN_INFILTRATION: \"Alien Infiltration\"\n  STR_ALIEN_BASE: \"Alien Colony Expansion\"\n  STR_ALIEN_SURFACE_ATTACK: \"Alien Surface Attacks\"\n  STR_ALIEN_RETALIATION: \"Floating Base Attack\"\n  STR_ALIEN_SUPPLY: \"Colony Supply Missions\"\n\n  STR_ALIEN_PROBE_MISSION_UFOPEDIA: \"The Alien Probe Mission is used for correlating data about the seabed, the resources, shipping and airplane flight paths of an area. The Alien subs involved in these missions are not a major threat in themselves, but they indicate sites of activity that may flare at any time.\"\n  STR_ALIEN_INTERDICTION_UFOPEDIA: \"The Aliens have a policy of policing areas they are interested in, sending out craft with the express purpose of securing an area before more intensive missions are begun. They will land at specific sites they intend to raid later to lock down the areas and prepare the way for the next level of activity.\"\n  STR_ALIEN_RESOURCE_RAID_UFOPEDIA: \"The sinking of ships and the downing of aircraft are key elements of the Alien strategy. The acquisition of materials is one of the prime Alien activities and as such is allied to these overtly aggressive acts. The Aliens also raid areas of geo-thermal activity, mining sites and sites of antiquity for minerals and refined metals and other human produced items.\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"This can result in official contact between Aliens and corporations or governments at the highest level. The climax of this activity is characterized by intense Alien Sub activity in the waters of the organization concerned. The Aliens will attempt to sign an agreement with a government or organization by offering knowledge of their superior technologies. This Alien activity represents a major threat to X-Com. If a corporation or government co-operates with the invaders then its funding ceases.\"\n  STR_ALIEN_BASE_UFOPEDIA: \"Aliens will construct secret undersea colonies in remote locations. After some initial reconnaissance flights some intense Alien Sub activity will occur as the colony is being built. These colonies are known to contain labs, cloning centers, surgical facilities for human and Alien experimentation. The presence of Alien colonies will generate more Alien activity without the presence of Alien Subs. In order to locate a colony an X-Com sub must patrol an area for a few hours to stand some chance of successful detection.\"\n  STR_ALIEN_SURFACE_ATTACK_UFOPEDIA: \"When the Aliens need humans they terrorize a port, attack an island, or raid a ship. Civilians will be directly threatened, to fulfil the perverse breeding needs of the Aliens and their hideous experiments.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"If X-Com intercept subs are being particularly successful in sinking Alien craft then the Aliens may take some aggressive retaliatory action. This could result in a direct attack against an X-Com facility. However, the Aliens have to find an X-Com base in order to attack it, and provided Alien Subs are kept away then there should be little danger of an assault.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"Once an Alien colony is constructed then it is re-supplied on a regular basis by a special supply ship. If one of these vessels is detected while touching down then it is certain that an Alien colony is nearby.\"\n\n  STR_SURVEY_SHIP_UFOPEDIA: \"This tiny submarine is used for reconnaissance and survey missions. It normally precedes larger vessels at the start of an Alien task force.\"\n  STR_ESCORT_UFOPEDIA: \"A medium sized escort vessel that is of little threat on its own. This craft precedes the arrival of larger vessels and increased activities.\"\n  STR_CRUISER_UFOPEDIA: \"The Cruiser is a general purpose craft, the mainstay of the Alien fleet, it is used in all types of Alien missions and is a dangerous adversary.\"\n  STR_HEAVY_CRUISER_UFOPEDIA: \"The heavy cruiser is a more powerful ship than the cruiser, larger weapons and propulsion systems boost its power. The Heavy Cruiser is used for resource missions to collect large quantities of minerals and equipment.\"\n  STR_HUNTER_UFOPEDIA: \"This vessel is equipped with an examination room for performing experiments and surgery on human subjects. The victims are subjected to the foulest tortures and the brain is often removed and stored for processing en-route.\"\n  STR_BATTLESHIP_UFOPEDIA: \"The battleship is the most aggressive ship the Aliens possess, it features all the Alien technologies and systems to act as a base of operations for any form of aggressive act the Aliens may want to perform, it carries a wide array of weapons.\"\n  STR_DREADNOUGHT_UFOPEDIA: \"The Dreadnought is a super troop carrier, fully equipped with all Alien technologies and a vast payload. The Dreadnought is a tough and formidable opponent.\"\n  STR_FLEET_SUPPLY_CRUISER_UFOPEDIA: \"The supply vessel is used during the construction of Alien colonies or for supplying existing colonies. It carries Alien nutrients, DNA, fetuses and other biological components.\"\n\n  STR_DISMANTLE: \"Dismantle\"\n  STR_FACILITY_IN_USE: \"AQUA-POD IN USE\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"CANNOT DISMANTLE AQUA-POD!{SMALLLINE}All base Pods must be linked to the air-lock.\"\n  STR_TRANSFER_ITEMS_TO: \"Transfer Items to {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"NO ALIEN CONTAINMENT FOR TRANSFER!{SMALLLINE}Live Aliens need an Alien containment equipment in order to survive.\"\n  STR_AMOUNT_AT_DESTINATION: \"AMOUNT AT{NEWLINE}DESTINATION\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"Alien dies as there is no Alien containment facility\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"NO FREE ACCOMMODATION!{SMALLLINE}The destination base does not have enough space in the living quarters for the crew assigned to the sub.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"NOT ENOUGH STORE SPACE!{SMALLLINE}The destination base does not have enough store space for the equipment assigned to the sub.\"\n  STR_ITEMS_ARRIVING: \"Items Arriving\"\n  STR_DESTINATION_UC: \"DESTINATION\"\n\n  STR_DART_PISTOL: \"Dart Gun\"\n  STR_DART_POD: \"Dart Clip\"\n  STR_JET_HARPOON: \"Jet Harpoon\"\n  STR_HARPOON_POD: \"Harpoon Clip\"\n  STR_GAS_CANNON: \"Gas Cannon\"\n  STR_GC_AP_AMMO: \"GC-AP Bolts\"\n  STR_GC_HE_AMMO: \"GC-HE Bolts\"\n  STR_GC_P_AMMO: \"GC-Phosphorous Bolts\"\n  STR_HYDRO_JET_CANNON: \"Hydro-Jet Cannon\"\n  STR_HJC_AP_AMMO: \"HJ-AP Ammo\"\n  STR_HJC_HE_AMMO: \"HJ-HE Ammo\"\n  STR_HJC_P_AMMO: \"HJ-P Ammo\"\n  STR_TORPEDO_LAUNCHER: \"Torpedo Launcher\"\n  STR_SMALL_TORPEDO: \"Small Torpedo\"\n  STR_LARGE_TORPEDO: \"Large Torpedo\"\n  STR_PHOSPHOROUS_TORPEDO: \"Phosphor Torpedo\"\n  STR_MAGNA_BLAST_GRENADE: \"Magna-Blast Grenade\"\n  STR_DYE_GRENADE: \"Dye Grenade\"\n  STR_PARTICLE_DISTURBANCE_GRENADE: \"Particle Disturbance Grenade\"\n  STR_MAGNA_PACK_EXPLOSIVE: \"Magna-Pack Explosive\"\n  STR_PARTICLE_DISTURBANCE_SENSOR: \"Particle Disturbance Sensor\"\n  STR_MEDI_KIT: \"Medi-Kit\"\n  STR_MC_DISRUPTOR: \"M.C. Disruptor\"\n  STR_THERMAL_TAZER: \"Thermal Tazer\"\n\n  STR_GAUSS_PISTOL: \"Gauss Pistol\"\n  STR_GAUSS_PISTOL_CLIP: \"Gauss Pistol Clip\"\n  STR_GAUSS_RIFLE: \"Gauss Rifle\"\n  STR_GAUSS_RIFLE_CLIP: \"Gauss Rifle Clip\"\n  STR_HEAVY_GAUSS: \"Heavy Gauss\"\n  STR_HEAVY_GAUSS_CLIP: \"Heavy Gauss Clip\"\n\n  STR_SONIC_CANNON: \"Sonic Cannon\"\n  STR_CANNON_POWER_CLIP: \"Cannon Power Clip\"\n  STR_SONIC_BLASTA_RIFLE: \"Sonic-Blasta Rifle\"\n  STR_BLASTA_POWER_CLIP: \"Blasta Power Clip\"\n  STR_SONIC_PISTOL: \"Sonic Pistol\"\n  STR_PISTOL_POWER_CLIP: \"Pistol Power Clip\"\n  STR_DISRUPTOR_PULSE_LAUNCHER: \"Disruptor Pulse Launcher\"\n  STR_DISRUPTOR_AMMO: \"Disruptor Ammo\"\n  STR_THERMAL_SHOK_LAUNCHER: \"Thermal Shok Launcher\"\n  STR_THERMAL_SHOK_BOMB: \"Thermal Shok Bomb\"\n  STR_SONIC_PULSER: \"Sonic Pulser\"\n  STR_ZRBITE: \"Zrbite\"\n  STR_MC_READER: \"M.C. Reader\"\n  STR_VIBRO_BLADE: \"Vibro Blade\"\n  STR_THERMIC_LANCE: \"Thermic Lance\"\n  STR_HEAVY_THERMIC_LANCE: \"Heavy Thermic Lance\"\n  STR_AQUATOID_CORPSE: \"Aquatoid Corpse\"\n  STR_GILLMAN_CORPSE: \"Gill Man Corpse\"\n  STR_LOBSTERMAN_CORPSE: \"Lobster Man Corpse\"\n  STR_TASOTH_CORPSE: \"Tasoth Corpse\"\n  STR_CALCINITE_CORPSE: \"Calcinite Corpse\"\n  STR_DEEP_ONE_CORPSE: \"Deep One Corpse\"\n  STR_BIODRONE_CORPSE: \"Bio-Drone Corpse\"\n  STR_TENTACULAT_CORPSE: \"Tentaculat Corpse\"\n  STR_TRISCENE_CORPSE: \"Triscene Corpse\"\n  STR_HALLUCINOID_CORPSE: \"Hallucinoid Corpse\"\n  STR_XARQUID_CORPSE: \"Xarquid Corpse\"\n\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"Not enough ammunition to arm SWS{SMALLLINE}Each SWS requires {0} {1}.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Not enough equipment to fully re-equip squad\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"You will need to research a{NEWLINE}{0}{NEWLINE}in order to produce the{NEWLINE}{1}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"The Aliens have destroyed the undefended base {0}\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"X-Com patrols have located an Alien colony in {0}\"\n  STR_STANDOFF: \"STANDOFF\"\n  STR_CAUTIOUS_ATTACK: \"CAUTIOUS ATTACK\"\n  STR_STANDARD_ATTACK: \"STANDARD ATTACK\"\n  STR_AGGRESSIVE_ATTACK: \"AGGRESSIVE ATTACK\"\n  STR_DISENGAGING: \"DISENGAGING\"\n  STR_UFO_HIT: \"ALIEN SUB HIT!\"\n  STR_UFO_CRASH_LANDS: \"ALIEN SUB DOWNED!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Minimize at Standoff Range Only\"\n  STR_UFO_RETURN_FIRE: \"ALIEN SUB RETURNS FIRE!\"\n  STR_INTERCEPTOR_DAMAGED: \">>> FLYING SUB DAMAGED <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> FLYING SUB DESTROYED <<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"ALIEN FLYING SUB ESCAPING!\"\n  STR_LONG_RANGE_DETECTION: \"Wide band Detection\"\n  STR_STORES_UC: \"STORES\"\n  STR_DIFFICULTY_LEVEL: \"Difficulty Level\"\n  STR_INTERCEPT: \"INTERCEPT\"\n  STR_BASES: \"BASES\"\n  STR_GRAPHS: \"GRAPHS\"\n  STR_UFOPAEDIA_UC: \"UFOPAEDIA\"\n  STR_OPTIONS_UC: \"OPTIONS\"\n  STR_FUNDING_UC: \"FUNDING\"\n  STR_5_SECONDS: \"5 Secs\"\n  STR_1_MINUTE: \"1 Min\"\n  STR_5_MINUTES: \"5 Mins\"\n  STR_30_MINUTES: \"30 Mins\"\n  STR_1_HOUR: \"1 Hour\"\n  STR_1_DAY: \"1 Day\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"X-Com Performance Roster\"\n  STR_ENTER_NAME: \"Enter Name\"\n  STR_PERFORMANCE_RATING: \"Performance Rating\"\n  STR_VICTORY_DATE: \"Victory Date\"\n  STR_CHEMICAL_FLARE: \"Chemical-flare\"\n  STR_CHEMICAL_FLARE_UFOPEDIA: \"This compact device produces a bright flare of light at any depth or on dry land. This illuminates enemy units in the vicinity of the flare during deep sea or night missions.\"\n  STR_MONTHLY_COSTS: \"Monthly Costs\"\n  STR_CRAFT_RENTAL: \"Flying Sub Rental\"\n  STR_SALARIES: \"Salaries\"\n  STR_BASE_MAINTENANCE: \"Base maintenance\"\n  STR_COST_PER_UNIT: \"Cost per unit\"\n  STR_QUANTITY: \"Quantity\"\n  STR_TOTAL: \"Total\"\n  STR_IN_PSIONIC_TRAINING: \"In M.C. Implantation\"\n  STR_FRONT_ARMOR: \"Front Armor\"\n  STR_LEFT_ARMOR: \"Left Armor\"\n  STR_RIGHT_ARMOR: \"Right Armor\"\n  STR_REAR_ARMOR: \"Rear Armor\"\n  STR_UNDER_ARMOR: \"Under Armor\"\n  STR_ROUNDS: \"SHOTS\"\n  STR_UNIT: \"UNIT> {0}\"\n  STR_ENERGY: \"ENERGY\"\n  STR_MORALE: \"MORALE\"\n  STR_ARMOR_: \"ARMOR> {0}\"\n  STR_FRONT_ARMOR_UC: \"FRONT ARMOR\"\n  STR_LEFT_ARMOR_UC: \"LEFT ARMOR\"\n  STR_RIGHT_ARMOR_UC: \"RIGHT ARMOR\"\n  STR_REAR_ARMOR_UC: \"REAR ARMOR\"\n  STR_SKILLS: \"SKILLS> {0}\"\n  STR_LEVEL: \"LEVEL> {0}\"\n  STR_HEAD: \"HEAD\"\n  STR_TORSO: \"TORSO\"\n  STR_RIGHT_ARM: \"RIGHT ARM\"\n  STR_LEFT_ARM: \"LEFT ARM\"\n  STR_RIGHT_LEG: \"RIGHT LEG\"\n  STR_LEFT_LEG: \"LEFT LEG\"\n  STR_PAIN_KILLER: \"PAIN KILLER\"\n  STR_STIMULANT: \"STIMULANT\"\n  STR_HEAL: \"HEAL\"\n  STR_TIME_UNITS_SHORT: \"TU>{ALT}{0}\"\n  STR_WEIGHT: \"Weight>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"React>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"M.Skill>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"M.Str>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Alien Artefact\"\n  STR_AMMO_ROUNDS_LEFT: \"AMMO:{NEWLINE}ROUNDS{NEWLINE}LEFT={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Pain>{ALT}{0}{ALT}{NEWLINE}Stim>{ALT}{1}{ALT}{NEWLINE}Heal>{ALT}{2}\"\n  STR_THROW: \"Throw\"\n  STR_AUTO_SHOT: \"Auto Shot\"\n  STR_SNAP_SHOT: \"Snap Shot\"\n  STR_AIMED_SHOT: \"Aimed Shot\"\n  STR_STUN: \"Stun\"\n  STR_PRIME_GRENADE: \"Prime Grenade\"\n  STR_USE_SCANNER: \"Use Dist. Sensor\"\n  STR_USE_MEDI_KIT: \"Use Medi-kit\"\n  STR_LAUNCH_MISSILE: \"Launch Torpedo\"\n  STR_ACCURACY_SHORT: \"Acc>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Not Enough Time Units!\"\n  STR_NOT_ENOUGH_ENERGY: \"Not Enough Energy!\"\n  STR_NO_ROUNDS_LEFT: \"No Rounds left!\"\n  STR_NO_AMMUNITION_LOADED: \"No Ammunition Loaded!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Wrong Ammunition for this Weapon!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"Weapon is already loaded!\"\n  STR_NO_LINE_OF_FIRE: \"No Line of Fire!\"\n  STR_GRENADE_IS_ACTIVATED: \"Grenade is Activated!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Grenade De-activated!\"\n  STR_THERE_IS_NO_ONE_THERE: \"There is no one there!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Unable to use alien artifact until researched!\"\n  STR_OUT_OF_RANGE: \"Out of Range!\"\n  STR_UNABLE_TO_THROW_HERE: \"Unable to throw here!\"\n  STR_SET_TIMER: \"Set Timer\"\n  STR_HIDDEN_MOVEMENT: \"HIDDEN MOVEMENT\"\n  STR_TURN: \"TURN> {0}\"\n  STR_SIDE: \"SIDE> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Press button to continue\"\n  STR_MIND_CONTROL: \"Molecular Control\"\n  STR_PANIC_UNIT: \"Jam Implant\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Morale Attack Successful\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Implant Control Successful\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}has gone Berserk\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}has gone Berserk\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}has Panicked\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}has Panicked\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Aliens\"\n  STR_RIGHT_HAND: \"RIGHT HAND\"\n  STR_LEFT_HAND: \"LEFT HAND\"\n  STR_RIGHT_SHOULDER: \"RIGHT SHOULDER\"\n  STR_LEFT_SHOULDER: \"LEFT SHOULDER\"\n  STR_BACK_PACK: \"BACK PACK\"\n  STR_BELT: \"BELT\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}is under Molecular Control\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}is under Molecular Control\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}has become unconscious\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}has become unconscious\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}has died from a fatal wound\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}has died from a fatal wound\"\n  STR_USE_MIND_PROBE: \"Use M.C. Reader\"\n  STR_FATAL_WOUNDS: \"FATAL WOUNDS\"\n  STR_UNDER_ARMOR_UC: \"UNDER ARMOR\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Time Units reserved for Snap Shot\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Time Units reserved for Auto Shot\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Time Units reserved for Aimed Shot\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Time Units reserved for Kneeling\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"TUs reserved for Kneeling and Firing\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} Unit in X-Com Craft\"\n    other: \"{N} Units in X-Com Craft\"\n  STR_UNITS_OUTSIDE:\n    one: \"{N} Unit left outside\"\n    other: \"{N} Units left outside\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} Unit in Entrance\"\n    other: \"{N} Units in Entrance\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} Unit in Target Exit\"\n    other: \"{N} Units in Target Exit\"\n  STR_ABORT_MISSION_QUESTION: \"Abort Mission?\"\n  STR_CORPSE: \"Corpse\"\n  STR_UNLOAD_CRAFT: \"Unload\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}has been killed\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}has been killed\"\n  STR_HIT_MELEE: \"Hit\"\n  STR_GROUND: \"GROUND\"\n  STR_LIVING_QUARTERS_PLURAL: \"Living Quarters\"\n  STR_LIST_ITEM: \"ITEM\"\n\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"All Aliens killed in subcrash,{NEWLINE}Auto recovery initiated\"\n  STR_RESET: \"Reset\"\n  STR_MEMORIAL: \"Memorial\"\n  STR_DATE_UC: \"DATE\"\n  STR_SOLDIERS_RECRUITED_UC: \"AQUANAUTS RECRUITED>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"AQUANAUTS LOST>{ALT}{0}\"\n  STR_REMOVE_SELECTED: \"Remove Selected\"\n  STR_LIVE_ALIENS: \"Live{NEWLINE}Specimens\"\n  STR_DEAD_ALIENS: \"Rejected{NEWLINE}Specimens\"\n  STR_UNDER_INTERROGATION: \"Being{NEWLINE}Studied\"\n  STR_CONTAINMENT_EXCEEDED: \"ALIEN CONTAINMENT LIMITS EXCEEDED!{SMALLLINE}Insufficient containment space at {0}. You must remove excess aliens from containment (who will then die).\"\n  STR_MANAGE_CONTAINMENT: \"Manage Alien Containment\"\n  STR_STORAGE_EXCEEDED: \"STORAGE SPACE EXCEEDED!{SMALLLINE}Insufficient storage space at {0}. You must sell off excess items.\"\n  STR_GO_TO_BASE: \"Go to Base\"\n  STR_MELEE_ACCURACY: \"MELEE ACCURACY\"\n  STR_SELL_PRODUCTION: \"SELL\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Both hands must be empty!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Not enough items to copy template!\"\n  STR_UNLOAD_WEAPON: \"Unload weapon\"\n  STR_ALL_ITEMS: \"All Items\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"NO MORE EQUIPMENT ALLOWED ON BOARD!{SMALLLINE}You are only allowed to take a maximum of {N} item of equipment on this sub.\"\n    other: \"NO MORE EQUIPMENT ALLOWED ON BOARD!{SMALLLINE}You are only allowed to take a maximum of {N} items of equipment on this sub.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}CONTROL CENTER DESTROYED{NEWLINE}Make your way to the entrance and abort.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"X-Com Aqua-facilities cannot be built on land\"\n  STR_UNABLE_TO_ENGAGE_DEPTH: \"UNABLE TO ENGAGE ENEMY{NEWLINE}AT THIS DEPTH\"\n  STR_UNABLE_TO_ENGAGE_AIRBORNE: \"UNABLE TO ENGAGE ENEMY{NEWLINE}WHEN AIRBORNE\"\n  STR_UNDERWATER_EQUIPMENT: \"This equipment will not function above water!\"\n  STR_LAND_EQUIPMENT: \"This equipment will not function underwater!\"\n  STR_LEVEL_SHORT: \"L{0}\"\n  STR_PERSONNEL: \"Personnel\"\n  STR_CRAFT_ARMAMENT: \"Craft & Armament\"\n  STR_COMPONENTS: \"Components\"\n  STR_SOLDIERS_RECRUITED: \"Aquanauts recruited\"\n  STR_SOLDIERS_LOST: \"Aquanauts lost\"\n  STR_TOTAL_UFOS: \"Flying subs detected\"\n  STR_TOTAL_ALIEN_BASES: \"Alien colonies discovered\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"MST\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"MSK\"\n  FEMALE_CIVILIAN: \"Civilian, Female\"\n  MALE_CIVILIAN: \"Civilian, Male\"\n  DOCKER_CIVILIAN: \"Civilian, Docker\"\n  SAILOR_CIVILIAN: \"Civilian, Sailor\"\n  STR_BIODRONE_MELEE_WEAPON: \"Bio-drone Melee\"\n  HALLUCINOID_WEAPON: \"Hallucinoid Weapon\"\n  STR_LOBSTERMAN_MELEE_WEAPON: \"Lobsterman Melee\"\n  CALCINITE_WEAPON: \"Calcinite Weapon\"\n  DEEP_ONE_WEAPON: \"Deep One Weapon\"\n  STR_TRISCENE_MELEE_WEAPON: \"Triscene Melee\"\n  STR_TRIBIO_SONIC_WEAPON: \"Alien Sonic Weapon\"\n  XARQUID_WEAPON: \"Xarquid Weapon\"\n  TENTACULAT_WEAPON: \"Tentaculat Weapon\"\n  ZOMBIE_WEAPON: \"Zombie Weapon\"\n  ALIEN_PSI_WEAPON: \"Alien M.C. Weapon\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/es-419.yml",
    "content": "es-419:\n  STR_LEVIATHAN_UFOPEDIA: \"SUBMARINO VOLANTE DE CAZA Y TRANSPORTE, CAPAZ DE ALCANZAR UNA PROFUNDIDAD ASOMBROSA. UNA SÍNTESIS FABULOSA DE TECNOLOGÍA HUMANA Y ALIENÍGENA CONSISTENTE EN SISTEMAS DE PROPULSIÓN IÓNICA Y NAVEGACIÓN DE RED MAGNÉTICA\"\n  STR_BARRACUDA_UFOPEDIA: \"NAVE SUBMARINA BRITÁNICA, IMPULSADA POR MOTORES LÁSER SUPER CALENTADOS, CAPAZ DE SUMERGIRSE Y VOLAR, UNA DE LAS NAVES CAZA MÁS VELOCES DEL MUNDO Y PIEZA CLAVE PARA LA BATALLA QUE SE APROXIMA.\"\n  STR_HAMMERHEAD_UFOPEDIA: \"NAVE DE CAZA Y TRANSPORTE. REPLICA DE LOS SISTEMAS DE RED MAGNÉTICA EN UNA NAVE X-COM. AUNQUE PEQUEÑA, SU DISEÑO ES UN LOGRO TÉCNICO ASOMBROSO.\"\n  STR_TRITON_UFOPEDIA: \"NAVE DE TRANSPORTE, EQUIPADO CON MOTORES ACUÁTICOS Y ATMOSFÉRICOS. SU GRAN CAPACIDAD Y RESISTENTE CONSTRUCCIÓN LO HACE UN PILAR DE LA FLOTA X-COM.\"\n  STR_MANTA_UFOPEDIA: \"NAVE DE ALTA VELOCIDAD, UN SUBMARINO VOLANTE DE CAZA MONO-PLAZA, PARECIDO A LAS NAVES ALIENÍGENAS MOVIDAS POR IONES. MUY EFICAZ EN EL CONFLICTO QUE SE AGRAVA.\"\n  STR_AJAX_UFOPEDIA: \"EL TORPEDO AJAX ES EL ARMA ESTÁNDAR DE COMBATE SUBMARINO. ALREDEDOR DEL MUNDO. SE USA COMO UN DISUASIVO POTENTE Y PRECISO.\"\n  STR_DUP_HEAD_UFOPEDIA: \"LA TECNOLOGíA DE ARMAS CON CABEZA DE URANIO REBAJADO (C.U.R) ES RELATIVAMENTE NUEVA,  Y ÉSTA ES LA PRIMERA ARMA ACUÁTICA COMERCIAL QUE LA EMPLEA.\"\n  STR_CRAFT_GAS_CANNON_UFOPEDIA: \"UN CAÑÓN DE GAS COMPRIMIDO QUE DISPARA PROYECTILES SÓLIDOS CAPACES DE PERFORAR BLINDAJES.\"\n  STR_PWT_CANNON_UFOPEDIA: \"EL TORPEDO DE ONDAS DE IMPULSOS (T.O.I) UTILIZA UN SISTEMA DE COMBUSTIBLE SOBRE-CALENTADO Y UNA CABEZA SUMAMENTE DENSA QUE PUEDE PERFORAR LA MAYORÍA DE LAS ALEACIONES.\"\n  STR_GAUSS_CANNON_UFOPEDIA: \"EL ARMA GAUSS HA SIDO FABRICADA CON LA  RECIÉN DESARROLLADA TECNOLOGÍA X-COM. UN REACTOR DE FUSIÓN REFRIGERADO CON NITRÓGENO LÍQUIDO MUEVE SU ACELERADOR DE PARTÍCULAS.\"\n  STR_SONIC_OSCILLATOR_UFOPEDIA: \"UN POTENTE OSCILADOR ACUSTICO CREA ONDAS DE FUERZA SÓNICA QUE DESTRUYEN EL BLANCO AL ROMPER SUS ENLACES MOLECULARES CON LAS VIBRACIONES.\"\n  STR_AQUATOID_UFOPEDIA: \"La raza Aquatoide forma una sociedad ancestral que ya existía antes de que el hombre diera sus primeros pasos sobre la Tierra. Su aspecto compacto y sus rasgos bulbosos suponen una retroceso con respecto a sus hermanos los sectoides, que también viajan por el espacio. Su poder se basa en la tecnología del control molecular. Los aquatoides quieren propagar su raza estéril por medio de la codificación genética y, para ello, experimentan con seres humanos, dando origen a numerosas razas híbridas.\"\n  STR_AQUATOID_AUTOPSY: \"Autopsia de Aquatoide\"\n  STR_AQUATOID_AUTOPSY_UFOPEDIA: \"Un examen detallado de esta criatura nos permite llegar a unas suposiciones básicas. Es un sectoide, nuestro antiguo enemigo, pero ha sido modificado por métodos quirúrgicos e implantes y ahora es una criatura acuática. Tiene pulmones vestigiales que le permiten respirar y moverse por tierra, e implantes cibernéticos que aumentan la fuerza de sus miembros atrofiados y mejoran el funcionamiento de sus órganos. Dado que todos los miembros de esta raza son idénticos, suponemos que son clones.\"\n  STR_GILLMAN_UFOPEDIA: \"Una extraña criatura medio humana medio reptil, estrechamente relacionada con el hombre y extraordinariamente fuerte y rápida bajo el agua. Los hombres-branquia son una raza plenamente desarrollada, con hembras y machos de distintas edades. Se diferencian de la mayor¡a de los alienígenas submarinos en que no presentan ningún signo de alteración genética ni de deformación quirúrgica. Puede que estemos ante un grupo arcaico de nuestra propia especie.\"\n  STR_GILLMAN_AUTOPSY: \"Autopsia de Hombre-Branquia\"\n  STR_GILLMAN_AUTOPSY_UFOPEDIA: \"Una vez iniciada la intervención quirúrgica, se vio claro que no era un alienígena, sino una criatura de la Tierra, una raza prehistórica que se creía desaparecida desde que los mamíferos predominaron en este planeta. Los hombres-branquia, inteligentes y fuertes, vivieron en el tiempo de los dinosaurios. El cataclismo que acabó con el predominio de los reptiles obligó a estas criaturas a establecer una relación simbiótica con los alienígenas recién llegados. Tienen un dispositivo electrónico en el cráneo.\"\n  STR_LOBSTERMAN_UFOPEDIA: \"Esta es una criatura asombrosa, más alta que un hombre y tiene seis pulmones. A lo único que se parece es a un demonio acuático. El parecido entre esta criatura y la langosta terrestre le ganó el apodo Hombre-Langosta por las tropas X-Com. Esto es un monstruo de las profundidades. Una criatura de increíble fuerza diseñada cuidadosamente para luchar, y prácticamente invulnerable al fuego de proyectiles. Sus tenazas son suficientes para triturar acero.\"\n  STR_LOBSTERMAN_AUTOPSY: \"Autopsia de Hombre-Langosta\"\n  STR_LOBSTERMAN_AUTOPSY_UFOPEDIA: \"Bajo un caparazón prácticamente indestructible hay una criatura de construcción asombrosa: un esqueleto de titanio cubierto de músculos poderosos y un sofisticado sistema de blancos con un dispositivo de exploración multi-banda implantado en el cerebro. Sus múltiples ojos están protegidos con un plástico duro como el acero y cuando sus amos las despliegan estratégica mente, estas criaturas son imparables. Llevan unos dispositivos de construcción y función desconocidas.\"\n  STR_TASOTH_UFOPEDIA: \"Estos enemigos giles y veloces son un elemento esencial del ejército enemigo. En el corazón de las colonias alienígenas nacen cientos de ellos, criados en cubas enormes. Los Tasoth son verdaderos alienígenas, carnívoros y mucho más fuertes que los hombres. A menudo se sitúan en la vanguardia durante los ataques enemigos y nunca parecen amedrentarse, incluso cuando llevan claramente las de perder.\"\n  STR_TASOTH_AUTOPSY: \"Autopsia de Tasoth\"\n  STR_TASOTH_AUTOPSY_UFOPEDIA: \"La disección reveló un organismo cibernético dotado de una extraña energía. En el interior lleva una pequeña unidad energética, pero no se puede identificar ningún órgano. Un sistema de transmisión bioeléctrico reparte la energía por el cuerpo. No hay huesos ni ninguna otra estructura de sostén. Al morir, la energía se detiene y la criatura se convierte en un muñeco de carne y fluidos alienígenas retumbantes. Un par de células de cerámica reviven brevemente a la criatura si reciben energía.\"\n  STR_DEEP_ONE_UFOPEDIA: \"El Anuroide es una pesadilla biológica, un mestizaje resultado de los experimentos cerebrales de los aquatoides. Hemos visto algunas variaciones de esta criatura. Tras una costosa investigación hemos concluido que los fabrican los invasores, quienes aumentan su producción cada vez que capturan carne humana fresca. Cada uno de estos sub-humanos es capaz de soltar una descarga de energía eléctrica suficiente para matar a un aquanauta.\"\n  STR_DEEP_ONE_AUTOPSY: \"Autopsia de Anuroide\"\n  STR_DEEP_ONE_AUTOPSY_UFOPEDIA: \"Esta criatura es el resultado de injertos humanos y alienígenas. El cerebro humano ha sido alterado para ubicar dispositivos electrónicos de control y la corteza cerebral de un alienígena. La única característica humana son los ojos. Según parece, el feto alienígena va consumiendo a su anfitrión humano a medida que crece. Su resistente piel parece ser una mezcla metálica e inorgánica muy dura y flexible. El resultado es un híbrido fuerte y veloz que está  bajo el control total de los alienígenas.\"\n  STR_BIODRONE_UFOPEDIA: \"El telecerebro es una creación que sólo una mente alienígena podía concebir. Es un cerebro (humano o alienígena) envuelto en líquidos amnióticos y conectado a una unidad base con energía para volar o moverse bajo el agua. Llevan un potente disruptor sónico, parte mecánico, parte organismo vivo. Nuestros científicos han sugerido que las cuerdas vocales del organismo anfitrión mueven esta arma. Los alienígenas los emplean como perros guardianes para proteger sus valiosas propiedades.\"\n  STR_BIODRONE_AUTOPSY: \"Autopsia de Telecerebro\"\n  STR_BIODRONE_AUTOPSY_UFOPEDIA: \"La hipótesis de que el disruptor sónico es biológico es cierta. Esta criatura mata a sus enemigos gritando. Tienen grandes cicatrices y graves mutilaciones. Los alienígenas hacen una carnicería con el cerebro hasta conseguir que les obedezca. La mayor parte de las cortezas cerebrales usadas  son de origen alienígena, pero nada se puede comparar al horror de hallar una criatura basada en un humano. Los Telecerebros se mueven gracias a un motor Iónico y llevan un sistema de control remoto.\"\n  STR_TENTACULAT_UFOPEDIA: \"Ni siquiera de una pesadilla  de Lovecraft podrían salir criaturas indescriptibles como esta. No se puede comparar con ningún animal de la Tierra, el entorno en el que pueda haber surgido es inimaginable. Armado con largos tentáculos, el Tentáculat paraliza a sus víctimas y luego las transforma en objetos sin cerebro. Esta especie puede matar con sólo tocar, incluso a través de un blindaje. El tentáculat es el alienígena más temible de los que X-Com se ha encontrado hasta ahora.\"\n  STR_TENTACULAT_AUTOPSY: \"Autopsia de Tentáculat\"\n  STR_TENTACULAT_AUTOPSY_UFOPEDIA: \"La autopsia revela pequeños implantes cibernéticos en el gran cerebro de la criatura. Su sistema visual es una compleja combinación de percepción de imágenes luminosas y térmicas. Este monstruo puede moverse con un rumbo exacto incluso en las tenebrosas profundidades del océano. Tiene algunos órganos vestigiales que parecen ser los mínimos que necesita para sobrevivir. Cada criatura tiene un pequeño estómago con un conector externo, por lo que creemos que las alimentan sus amos.\"\n  STR_CALCINITE_UFOPEDIA: \"Estas criaturas similares a los trajes de buceadores perdidos acechan a los distraídos en el fondo del mar. Les basta dar un golpe con sus pinzas más fuertes que el acero para mandar al fondo al mejor de los buceadores. Sólo se ve una forma gelatinosa y verde girando alrededor de la mascarilla. No hemos podido adivinar nada sobre su verdadera naturaleza en ninguno de nuestros encuentros, a menudo letales, con ellas.\"\n  STR_CALCINITE_AUTOPSY: \"Autopsia de  Calcinite\"\n  STR_CALCINITE_AUTOPSY_UFOPEDIA: \"Una vez desprovisto del traje blindado, el Calcinite es una masa amorfa de protoplasma sin cerebro, extremidades u órganos sensores visibles. En el interior del cuerpo líquido hay un pequeño elemento metálico. Una vez muerta, sólo podemos hacer conjeturas sobre la naturaleza de esta criatura. Es un enigma de los alienígenas.\"\n  STR_TRISCENE_UFOPEDIA: \"Este reptil bípedo es un retroceso a la edad de los dinosaurios. Todo, excepto su habilidad para vivir dentro y fuera del agua, indica que es una criatura del Cretáceo. Estas criaturas llevan compartimientos de armas y tienen una mandíbula con enormes dientes de acero. A menudo, estos monstruos se colocan en el centro de las fuerzas de ataque alienígenas cuando estas lanzan un ataque terrestre. Constituyen un arma potente y pesada que los comandantes Tasoth despliegan con mortal eficacia.\"\n  STR_TRISCENE_AUTOPSY: \"Autopsia de Triscene\"\n  STR_TRISCENE_AUTOPSY_UFOPEDIA: \"Una vez sometidos al bisturí del científico, el Triscene resulta ser una criatura prehistórica modificada con implantes cibernéticos y sistemas de armas. Su diminuto cerebro ha sido completado con un pequeño ordenador acoplado al arnés de control que llevan todas las criaturas. Una piel natural resistente y un instinto depredador mejorado con armas hacen de él un oponente mortal en cualquier ambiente.\"\n  STR_HALLUCINOID_UFOPEDIA: \"Tras explotar los océanos, los alienígenas han criado esta enorme criatura terrestre y la utilizan como arma. No te dejes engañar por el falso aspecto inofensivo de este marino de las profundidades. Poseedor de un ataque cortante como el hielo el Alucinoide es un enemigo mortal.\"\n  STR_HALLUCINOID_AUTOPSY: \"Autopsia de Alucinoide\"\n  STR_HALLUCINOID_AUTOPSY_UFOPEDIA: \"En las muchas capas del cuerpo gelatinoso de este organismo hay un congelador químico potente, su principal medio de ataque. La piel suave y flexible del alucinoide indica que es vulnerable a ataques basados en el calor. Es frecuente ver a este mutante en compañía de sus amos, los Aquatoides.\"\n  STR_XARQUID_UFOPEDIA: \"El Calaxmar es otro invertebrado terrestre modificado, una criatura bella y peligrosa. Este nadador rápido y gigantesco oculta un arsenal de armas devastador, un chorro de tinta sofocante y un rayo de partículas ionizadas. Desde nuestros primeros encuentros con esta poderosa criatura hemos desconfiado de sus habilidades y de sus controladores, los vengativos Hombres-Branquia.\"\n  STR_XARQUID_AUTOPSY: \"Autopsia de Calaxmar\"\n  STR_XARQUID_AUTOPSY_UFOPEDIA: \"Este enorme cefalópodo ha llegado a este tamaño con una dieta de drogas alienígenas y alteraciones quirúrgicas. Los Hombres-Branquia, pervertidos hasta lo inimaginable, han implantado sistemas mecánicos de control en la criatura y ahora no queda ni uno de sus rasgos originales. Su resistente concha y su movilidad hacen que el Calaxmar sea un oponente formidable, empleado como plataforma orgánica para armas.\"\n  STR_ION_BEAM_ACCELERATORS_UFOPEDIA: \"Los submarinos volantes alienígenas tienen complejos sistemas de energía que les permiten surcar las profundidades a velocidad increíble. Su tecnología  se basa en el DESPLAZADOR DE IONES que usa Zrbita como catalizador y los motores mueven un volumen de agua 100 veces mayor que el suyo propio cada segundo. Esta potencia enorme implica que un submarino alienígena es más veloz que cualquiera de la Tierra. Podemos reproducir su sistema de propulsión con aquaplásticos y células de Zrbita.\"\n  STR_MAGNETIC_NAVIGATION_UFOPEDIA: \"Estas unidades generan un campo magnético esférico y de varias capas que es proyectado hasta 1 Km alrededor del submarino. Los alienígenas que navegan en el interior se comunican directamente y van palpando el camino a seguir bajo las olas. Un sistema interfaz funciona con la materia cerebral modificada de los alienígenas, que se comunica directamente con la mente del operador por unión neural.\"\n  STR_ALIEN_SUB_CONSTRUCTION_UFOPEDIA: \"La estructura de las naves es como la de un camaleón, imita rasgos de las criaturas marinas y está hecha de aquaplásticos. Cada submarino funciona como un organismo: tripulación y nave en armonía. La mayoría de sus sistemas se pueden reproducir y es posible crear una tecnología híbrida que nos permita llegar a su nivel.\"\n  STR_ALIEN_CRYOGENICS_UFOPEDIA: \"Muchos alienígenas permanecen escondidos en la Tierra en estado inactivo, sometidos a una congelación criogénica. Estas criaturas son encerradas en unidades en las que su temperatura corporal es reducida hasta que sus funciones vitales están a punto de detenerse. El examen de estas unidades ha revelado que los cuerpos han permanecido inactivos por periodos increíbles, algunos más de 60 millones de años.\"\n  STR_ALIEN_CLONING_UFOPEDIA: \"Muchos de los alienígens capturados son idénticos, incluso tienen el mismo ADN. Son copias exactas. Los alienígenas extraen muestras de células de sus bancos de genes y las meten en las unidades criogénicas. Algunas de ellas guardan humanos o partes de su cuerpo. Puede que algunas sirvan para crear híbridos.\"\n  STR_ALIEN_LEARNING_ARRAYS_UFOPEDIA: \"Gracias a los implantes de Control Molecular que hay en los cráneos de todos los alienígenas, estas máquinas inyectan directamente información en sus cerebros. Los alienígenas recién clonados son llevados hasta estas unidades para introducirles recuerdos de su raza e información científica y bélica en sus mentes vacías.\"\n  STR_ALIEN_IMPLANTER_UFOPEDIA: \"Esta máquina sirve para equipar a los alienígenas con implantes de Control Molecular, fertilizar razas reproductoras e insertar o extraer órganos y dispositivos electrónicos de cualquier criatura. Creemos que el paciente está anestesiado pero es consciente del proceso y, por desgracia, la anatomía humana se acopla perfectamente a esta unidad.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"Ya tenemos pruebas que nos permiten saber por qué‚ los alienígenas capturan humanos. No se los comen ni los fertilizan con sus propios embriones, los usan como base de una serie de criaturas y sistemas de control. Su tecnología se basa en una mente única, una inteligencia común, y el cerebro humano es el receptáculo ideal para ello. El tejido del cerebro humano se utiliza en la mayoría de los sistemas informático-biológicos de almacenamiento y extracción de datos, el resto sirve para crear y criar criaturas.\"\n  STR_AQUA_PLASTICS_UFOPEDIA: \"En la mayor parte de la construcción de los submarinos y estructuras alienígenas se utiliza un material increíblemente fuerte y duradero. Los Aquaplásticos son materiales complejos de enlaces múltiples y catalizados con Zrbita. Esta sustancia densa pero ligera es más resistente que el Titanio o el Kevlar.\"\n  STR_ZRBITE_UFOPEDIA: \"Esta es una aleación de origen alienígena, hecha de oro y de bio-material alienígena. Cuando se utiliza como fuente de energía, pequeñas cantidades generan más energía que una unidad nuclear 10 veces más grande. No podemos reproducir este material con nuestra tecnología debido a que la mayoría de sus componentes son alienígenas.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"Los alienígenas atacan por todo el planeta con eficacia despiadada. No conseguimos averiguar dónde está su base, ¨en alguna parte impenetrable del fondo del océano que no podemos localizar? No todos los organismos encontrados son alienígenas, unos son viejísimos, otros son ejemplares evolucionados de especies que creíamos extintas hace mucho. Nos enfrentamos a una amenaza que ha estado aletargada durante milenios, una sutil simbiosis de humano y alienígena. Las antiguas bases desde donde contactan con sus primos de las estrellas están en la profundidad del océano. Cada una de estas doce bases tiene un dispositivo Synonium  de alta tecnología alienígena. Ahora que su maquinaria bélica está en marcha, los alienígenas están reactivando estas bases para ampliar su red de Control Molecular, tenemos que destruir esas bases cueste lo que cueste.\"\n  STR_THE_ULTIMATE_THREAT_UFOPEDIA: \"Hace sesenta y cinco millones de años una inmensa nave-ciudad fue enviada a la Tierra desde un planeta lejano. Mientras el enorme aparato se aproximaba al joven planeta, una violenta erupción solar provocó un fallo de navegación. La enorme mole, inutilizada y averiada se precipitó a través de la estratosfera del cielo del Cretáceo. En la superficie, numerosas especies animales levantaron la vista hacia el cielo y vieron a su enemigo abrirse paso hacia el planeta. La atmósfera se saturó de polvo y, al enfriarse el planeta, la especie animal dominante, el dinosaurio, se extinguió. Pero los 400 mil toneladas de metal de T'leth no quedaron destruidos en el impacto; unos sofisticados ordenadores pusieron en hibernación a las criaturas que había en el interior. Durante eones, los ordenadores despertaron a grupos de alienígenas para que intentaran comunicarse con sus primos estelares, pero fue en vano, porque el núcleo del poder alienígena seguía dormido.\"\n  STR_TLETH_THE_ALIEN_CITY: \"T'leth la Ciudad Alienígena\"\n  STR_TLETH_THE_ALIEN_CITY_UFOPEDIA: \"La enorme nave-ciudad alienígena T'leth yace en Sigsbee, en el Golfo de México. En el centro de la ciudad hay un horror alienígena, tan malvado y poderoso que ni siquiera la muerte lo reclama. En una cámara de metal alienígena yace dormido el Soñador, el Alienígena Supremo. Cuando T'leth emerja de las aguas, Él iniciará su ciclo de reanimación y una vez despierto nada le detendrá. Aunque no esté vivo, y en cierto modo tampoco muerto, su mente controla el ejército alienígena. La desconocida tecnología del Control Molecular conecta todos los alienígenas a un único cerebro y viceversa. Unos fetos, resultado de la mutación genética de hombre y alienígena, proporcionan energía a ese cerebro y sirven de unión entre él y sus súbditos. El mito del Alienígena Supremo vive desde hace siglos en la memoria y en el corazón de los hombres, pero sólo el mar sabe la verdad.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"CENTRAR EN SITIO - TIEMPO = 5 Seg\"\n  STR_CANCEL_UC: \"CANCELAR\"\n  STR_NONE: \"Ninguno\"\n  STR_UNKNOWN: \"Desconocido\"\n  STR_POOR: \"Pobre\"\n  STR_AVERAGE: \"Normal\"\n  STR_GOOD: \"Bueno\"\n  STR_EXCELLENT: \"Excelente\"\n  STR_BUILD_NEW_BASE_UC: \"NUEVA BASE\"\n  STR_BASE_INFORMATION: \"INFORMACIÓN DE BASE\"\n  STR_EQUIP_CRAFT: \"EQUIPAR SUBMARINO\"\n  STR_BUILD_FACILITIES: \"CONSTRUIR INSTALACIONES\"\n  STR_RESEARCH: \"INVESTIGAR\"\n  STR_MANUFACTURE: \"MANUFACTURAR\"\n  STR_TRANSFER_UC: \"TRANSFERIR\"\n  STR_PURCHASE_RECRUIT: \"COMPRAR/RECLUTAR\"\n  STR_SACK: \"DESPEDIR\"\n  STR_SELL_SACK_UC: \"VENDER/DESPEDIR\"\n  STR_GEOSCAPE_UC: \"GEOESCAPE\"\n  STR_NAME: \"Nombre\"\n  STR_AREA: \"Zona\"\n  STR_BUILD_NEW_BASE: \"Construir Nueva Base\"\n  STR_CANCEL: \"Cancelar\"\n  STR_COST_UC: \"COSTO> \"\n  STR_CONSTRUCTION_TIME_UC: \"TIEMPO DE CONSTRUCCIÓN> \"\n  STR_DAY:\n    one: \"{N} día\"\n    many: \"{N} días\"\n    other: \"{N} días\"\n  STR_HOUR:\n    one: \"{N} hora\"\n    many: \"{N} horas\"\n    other: \"{N} horas\"\n  STR_MAINTENANCE_UC: \"MANTENIMIENTO> \"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Instalación\"\n  STR_CURRENT_RESEARCH: \"INVESTIGACIÓN ACTUAL\"\n  STR_SCIENTISTS_AVAILABLE: \"Científicos Disponibles>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Científicos Asignados>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Espacio de Laboratorio Disponible>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"PROYECTO\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"CIENTÍFICOS ASIGNADOS\"\n  STR_PROGRESS: \"PROGRESO\"\n  STR_NEW_PROJECT: \"Nuevo Proyecto\"\n  STR_CANCEL_PROJECT: \"CANCELAR PROYECTO\"\n  STR_NEW_RESEARCH_PROJECTS: \"NUEVOS PROYECTOS DE INVESTIGACIÓN\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"CIENTÍFICOS DISPONIBLES>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"ESPACIO DE LABORATORIO DISPONIBLE>{ALT}{0}\"\n  STR_INCREASE: \"Aumentar\"\n  STR_DECREASE: \"Disminuir\"\n  STR_START_PROJECT: \"INICIAR PROYECTO\"\n  STR_CURRENT_PRODUCTION: \"PRODUCCIÓN ACTUAL\"\n  STR_ENGINEERS_AVAILABLE: \"Técnicos Disponibles>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Técnicos Asignados>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Espacio de Taller Disponible>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Fondos Actuales>{ALT}{0}\"\n  STR_ITEM: \"ARTÍCULO\"\n  STR_ENGINEERS__ALLOCATED: \"Técnicos Asignados\"\n  STR_UNITS_PRODUCED: \"Unidades Producidas\"\n  STR_TOTAL_TO_PRODUCE: \"Total a Producir\"\n  STR_COST__PER__UNIT: \"Costo{NEWLINE}p/u\"\n  STR_DAYS_HOURS_LEFT: \"Dias/Horas Restantes\"\n  STR_NEW_PRODUCTION: \"Nueva Producción\"\n  STR_PRODUCTION_ITEMS: \"Artículos Disponibles\"\n  STR_CATEGORY: \"CATEGORÍA\"\n  STR_START_PRODUCTION: \"INICIAR PRODUCCIÓN\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} Horas para producir una unidad\"\n  STR_COST_PER_UNIT_: \"Costo por unidad>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Espacio de Trabajo Requerido>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"MATERIALES REQUERIDOS\"\n  STR_ITEM_REQUIRED: \"ARTÍCULOS NECESARIOS\"\n  STR_UNITS_REQUIRED: \"UNIDADES REQUERIDAS\"\n  STR_UNITS_AVAILABLE: \"UNIDADES DISPONIBLES\"\n  STR_STOP_PRODUCTION: \"DETENER PRODUCCIÓN\"\n  STR_ENGINEERS_AVAILABLE_UC: \"TÉCNICOS DISPONIBLES>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"ESPACIO DE TALLER DISPONIBLE>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"UTILIDAD MENSUAL>{ALT}{0}\"\n  STR_INCREASE_UC: \"INCREMENTAR\"\n  STR_DECREASE_UC: \"DISMINUIR\"\n  STR_UNITS_TO_PRODUCE: \"Unidades a Producir\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Comprar/Contratar Personal\"\n  STR_COST_OF_PURCHASES: \"Costo>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"COSTO P/U\"\n  STR_QUANTITY_UC: \"CANTIDAD\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"DISPONIBLE : TOTAL> \"\n  STR_SOLDIERS: \"Aquanautas\"\n  STR_SCIENTISTS: \"Científicos\"\n  STR_ENGINEERS: \"Técnicos\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"OCUPADO : DISPONIBLE> \"\n  STR_LIVING_QUARTERS: \"Viviendas\"\n  STR_STORES: \"Almacenes\"\n  STR_LABORATORIES: \"Laboratorios\"\n  STR_WORK_SHOPS: \"Talleres\"\n  STR_HANGARS: \"Submarino Volante\"\n  STR_SHORT_RANGE_DETECTION: \"Sonar de Corto Alcanze\"\n  STR_DEFENSE_STRENGTH: \"Fuerza Defensiva\"\n  STR_TRANSFERS_UC: \"TRANSFERENCIAS\"\n  STR_TRANSFERS: \"Transferencias\"\n  STR_ARRIVAL_TIME_HOURS: \"Arrivo (h)\"\n  STR_COST_: \"Costo>{ALT}{0}\"\n  STR_AREA_: \"Zona>{ALT}{0}\"\n  STR_BASE_NAME: \"¿Nombre de la Base?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"SELECCIONE UBICACIÓN DE LA ESCOTILLA\"\n  STR_TRANSFER: \"Transferir\"\n  STR_AMOUNT_TO_TRANSFER: \"CANTIDAD A TRANSFERIR\"\n  STR_SELECT_DESTINATION_BASE: \"Seleccione Destino\"\n  STR_COST: \"Costo\"\n  STR_INTRO_1: \"Copyright 1995 MicroProse\"\n  STR_INTRO_2: \"Marte: La Caída de Cydonia.\"\n  STR_INTRO_3: \"Un triunfante X-Com, habiendo destruido el núcleo mismo de la máquina de guerra Alienígena, despega hacia el hogar. Sin embargo, no todo está muerto en la base marciana devastada.\"\n  STR_INTRO_4: \"Un poderoso rayo de taquiones fluye desde los escombros del centro neurálgico de Cydonia, a toda velocidad a través del vacío. Su destino............\"\n  STR_INTRO_5: \"La Tierra.\"\n  STR_INTRO_6: \"En lo profundo del océano el haz golpea un receptor inactivo. Grandes ordenadores, comienzan a activarse. En lo profundo, más allá de los ojos de los seres humanos, vastas cámaras de Alienígenas dormidos comienzan su largo ciclo de reanimación.\"\n  STR_INTRO_7: \"2040: Una Tierra ignorante. Los terrores de la guerra Alienígena se olvidan. Pero, en los lugares perdidos y ocultos del océano las hordas alienígenas están listas, listas para derrocar a la humanidad y dominar el mundo.\"\n  STR_INTRO_8: \"Los Alienígenas arremeten contra la humanidad; buscan especímenes para sus retorcidos experimentos; asaltando el mundo por valiosos minerales y recursos; y saqueando los mares. Entonces, posan sus ojos sobre las olas.\"\n  STR_INTRO_9: \"Poderosos submarinos voladores de extraño diseño surcan los océanos, observando, buscando, cazando.........\"\n  STR_INTRO_10: \"Buscando presas, atacan.\"\n  STR_INTRO_11: \"Nuevas armas extrañas se lanzan contra un mundo indefenso. Estamos completamente a merced de la amenaza alienígena. {NEWLINE}Sólo una organización puede salvarnos; pero, les dimos la espalda hace mucho tiempo......\"\n  STR_INTRO_12: \"Instalación subacuática experimental X-COM\"\n  STR_INTRO_13: \"'¡May Day! ¡May Day! ''Este es el transatlántico Hyperion'. \\\"Estamos bajo ataque\\\". '¡May Day! Mayd............ \\\"\"\n  STR_INTRO_14: \"\\\"Centro de Comando a Submarino Uno: Abrir Esclusas\\\", \\\"desplegar Barracuda Cero Uno. Tenemos una situación de ataque alienígena, Alerta Roja\\\".{NEWLINE}\\\"Repito: Alerta Roja\\\"\"\n  STR_INTRO_15: \"Los Alienígenas son implacables en su eficiencia....\"\n  STR_INTRO_16: \"...infalibles en su exactitud\"\n  STR_INTRO_17: \"\\\"Barracuda Cero Uno a base\\\" - \\\"acercándose a lo que queda de la Hyperion\\\".\"\n  STR_INTRO_18: \"\\\"Desacelerando\\\".{NEWLINE}\\\"Dos metros\\\"{NEWLINE}\\\"Un metro\\\"{NEWLINE}\\\"Todos los aquanautas prepararse para su despliegue inmediato\\\".\"\n  STR_INTRO_19: \"...........\\\"Esclusa despejada\\\"... \\\"acercándose al naufragio\\\".{NEWLINE}\\\"Santo!\\\"{NEWLINE}\\\"¿Están captando esas criaturas con mi cámara de traje?\\\"\"\n  STR_GAMEOVER_1: \"Hemos fallado, los Alienígenas han aniquilado nuestras últimas esperanzas de salvación.{NEWLINE}X-Com está destruido y la Tierra se puso a los pies de del antiguo enemigo.\"\n  STR_GAMEOVER_2: \"T'leth truena en la estratosfera y comienza a moverse a través de la faz del mundo. Dispensando la muerte y cosechando los restos de la raza humana. En lo profundo de sus entrañas la asesina mente alienígena comienza a despertarse.\"\n  STR_GAMEOVER_3: \"En las capitales de todas las naciones, planes desesperados se elaboran. Todo es en vano, sin la tecnología que ofrece el proyecto de investigación X-Com nuestras armas son ineficaces.\"\n  STR_GAMEOVER_4: \"Los Alienígenas establecieron bases en los casquetes polares y empiezan a derretir el hielo, el mundo se convertirá en un vasto mar. Los restos de la raza humana son capturados y se utilizan en viles experimentos de reproducción con fines desconocidos. Los cielos se oscurecen y una fuerte pestilencia está sobre las tierras del Mundo.\"\n  STR_GAMEOVER_5: \"No podemos ofrecer ninguna resistencia al nuevo orden mundial, aquellos que lo intentan se encuentran  con un destino de fuego a manos de las incomprensibles armas alienígenas. Para el resto de nosotros no hay liberación bendita, la madre tierra se convierte en un mundo alienígena y la humanidad se pierde debajo de un progresivo horror.\"\n  STR_OUTRO_1: \"La tumba, asolada y diezmada, un rugido burbujeante proviene del centro de la urna.{NEWLINE}Tontos, todos perecerán....................\"\n  STR_OUTRO_2: \".................nadie puede escapar.\"\n  STR_OUTRO_3: \"Una enorme explosión brota de la tumba y atraviesa la ciudad, los escombros y el humo llenan el aire. Los planes de los alienígenas se ven frustrados........\"\n  STR_OUTRO_4: \"La retorcida vastedad de T'leth comienza a romperse. Llamas y humo se arrojan desde sus torres relucientes y salas de adamantium.\"\n  STR_OUTRO_5: \"El fastuoso gran Alienígena se desploma hacia el mar, los gritos de metal y almas torturadas llenan el aire. El Gran Soñador ya no soñara con conquistar el mundo.\"\n  STR_OUTRO_6: \"Un ensordecedor sonido final conmociona a la propia T'leth que rompe en lágrimas. {NEWLINE}La amenaza alienígena se ha ido, la Tierra es limpiada..................\"\n  STR_OUTRO_7: \"Un dormido planeta verde-azulado, en un rincón lejano de la galaxia.\"\n  STR_OUTRO_8: \"El futuro cercano, un lugar seguro para estar.\"\n  STR_OUTRO_9: \"La amenaza Alienígena a la Tierra se derroto hace mucho tiempo.\"\n  STR_OUTRO_10: \"Vastas  ciudades metrópolis albergan rebosantes miles de millones de humanos.\"\n  STR_OUTRO_11: \"Las obras de X-Com y las guerras Alienígenas son argumento de historias para niños.\"\n  STR_OUTRO_12: \"Pero las leyendas siempre han tenido el habito de contener una pizca de verdad..........\"\n  STR_RISE_1: \"T'leth, fue llamado muchas cosas en muchas leyendas de muchas tierras.\"\n  STR_RISE_2: \"Con un explosivo grito que reverbera a través del globo T'leth comienza a alzarse del fondo del mar.\"\n  STR_RISE_3: \"El enorme complejo surge a través de las aguas del Golfo de Méjico.\"\n  STR_RISE_4: \"400 mil millones de toneladas de metal alienígena, la enorme ciudad alienígena en donde se encuentra el cuerpo dormido del alienígena definitivo. Encarcelado en la tierra por 65 millones de años, este vil dios del espacio comienza a moverse.\"\n  STR_RISE_5: \"Las aguas hierven y se agitan mientas la tumba del Gran Soñador emerge a la luz................\"\n  STR_RISE_6: \".........una luz que durara poco a menos que X-Com pueda destruir la maquinaria de guerra alienígena.\"\n  STR_YOU_HAVE_FAILED: \"Has fracasado en detener la máquina de guerra alienígena. Las organizaciones de financiación, desilusionados con su capacidad tratan de negociar una solución no militar con los alienígenas. Los invasores tienen una agenda muy diferente y pronto todo el mundo es consciente de la verdad ...\"\n  STR_TOTAL_UC: \"TOTAL\"\n  STR_INCOME: \"Ingresos\"\n  STR_EXPENDITURE: \"Gastos\"\n  STR_MAINTENANCE: \"Mantenimiento\"\n  STR_BALANCE: \"Saldo\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"Actividad Alienígena en Los Mares\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"Actividad Alienígena en Zonas\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"Actividad X-Com en Los Mares\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"Actividad X-Com en Zonas\"\n  STR_FINANCE: \"Finanzas\"\n  STR_DATE_FIRST: \"{0}º\"\n  STR_DATE_SECOND: \"{0}º\"\n  STR_DATE_THIRD: \"{0}.º\"\n  STR_DATE_FOURTH: \"{0}.º\"\n  STR_FINANCE_THOUSANDS: \"$1000's\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Insuficientes materiales para producir{NEWLINE}{0}{NEWLINE}en{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Insuficiente dinero para producir{NEWLINE}{0}{NEWLINE}en{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"Producción de{NEWLINE}{0}{NEWLINE}en{NEWLINE}{1}{NEWLINE}finalizada\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"Construcción de{NEWLINE}{0}{NEWLINE}en{NEWLINE}{1}{NEWLINE}finalizada\"\n  STR_OK_5_SECONDS: \"OK - 5 seg\"\n  STR_RESEARCH_COMPLETED: \"Investigación Finalizada\"\n  STR_VIEW_REPORTS: \"VER REPORTES\"\n  STR_WE_CAN_NOW_RESEARCH: \"Podemos investigar\"\n  STR_WE_CAN_NOW_PRODUCE: \"Podemos fabricar\"\n  STR_SUNDAY: \"DOMINGO\"\n  STR_MONDAY: \"LUNES\"\n  STR_TUESDAY: \"MARTES\"\n  STR_WEDNESDAY: \"MIÉRCOLES\"\n  STR_THURSDAY: \"JUEVES\"\n  STR_FRIDAY: \"VIERNES\"\n  STR_SATURDAY: \"SÁBADO\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Insuficiente {0} para repostar {1} en {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Insuficientes {0} para rearmar {1} en {2}\"\n  STR_UFO_IS_NOT_RECOVERED: \"OSNI no fue recuperado\"\n  STR_UFO_IS_RECOVERED: \"OSNI recuperado\"\n  STR_CRAFT_IS_LOST: \"Submarino Volante perdido\"\n  STR_TERROR_CONTINUES: \"Actividad Alienígena continua\"\n  STR_ALIENS_DEFEATED: \"Alienígenas derrotados\"\n  STR_BASE_IS_LOST: \"Se ha perdido la Base\"\n  STR_BASE_IS_SAVED: \"Hemos defendido la Base\"\n  STR_ALIEN_BASE_STILL_INTACT: \"Colonia Alienígena intacta\"\n  STR_ALIEN_BASE_DESTROYED: \"Colonia Alienígena destruida\"\n  STR_ALIENS_KILLED: \"BAJAS ALIENÍGENAS\"\n  STR_ALIEN_CORPSES_RECOVERED: \"CADÁVERES ALIENÍGENAS RECUPERADOS\"\n  STR_LIVE_ALIENS_RECOVERED: \"ALIENÍGENAS VIVOS CAPTURADOS\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"ARTEFACTOS ALIENÍGENAS RECUPERADOS\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"CONTROL DE LA COLONIA ALIENÍGENA DESTRUIDO\"\n  STR_ALIEN_SYNOMIUM_DEVICE_DESTROYED: \"DISPOSITIVO SYNOMIUM DESTRUIDO\"\n  STR_ALIEN_SYNOMIUM_DEVICE_FAILED: \"FLLA AL DESTRUIR DISPOSITIVO SYNOMIUM\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"BAJAS CIVILES CAUSADAS POR LOS ALIENÍGENAS\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"BAJAS CIVILES CAUSADAS POR X-COM\"\n  STR_CIVILIANS_SAVED: \"CIVILES RESCATADOS\"\n  STR_XCOM_OPERATIVES_KILLED: \"BAJAS X-COM\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"OPERATIVOS X-COM DESAPARECIDOS EN COMBATE\"\n  STR_TANKS_DESTROYED: \"PLATAFORMAS DE ARMAS X-COM DESTRUIDAS\"\n  STR_XCOM_CRAFT_LOST: \"SUBMARINO X-COM DESTRUIDO\"\n  STR_UFO_RECOVERY: \"RECUPERACIÓN DE OSNI\"\n  STR_ALIEN_BASE_RECOVERY: \"RECUPERACIÓN DE COLONIA ALIENÍGENA\"\n  STR_BASE_UNDER_ATTACK: \"¡{0} bajo ataque!\"\n  STR_BASE_DEFENSES_INITIATED: \"DEFENSA DE LA BASE INICIADA\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"¡ESCUDO DE GRAV. REPELE OSNI!\"\n  STR_FIRING: \"DISPARANDO\"\n  STR_HIT: \"¡IMPACTO!\"\n  STR_UFO_DESTROYED: \"¡OSNI DESTRUIDO!\"\n  STR_MISSED: \"¡DISPARO FALLÓ!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Vender/Despedir \"\n  STR_VALUE_OF_SALES: \"VALOR DE VENTAS> {ALT}{0}\"\n  STR_FUNDS: \"FUNDOS> {ALT}{0}\"\n  STR_SELL_SACK: \"Vender/Despedir\"\n  STR_VALUE: \"Valor\"\n  STR_CRAFT_: \"SUBMARINO VOLANTE> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"RECUPERACIÓN DE OSNI DERRIBADO\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"EXTREMA PRECAUCIÓN - Habrá alienígenas en el submarino y alrededor del sitio. Esta misión se completará cuando todas las unidades enemigas hayan sido eliminadas o neutralizadas. La recuperación de restos del submarino alienígena, tecnología y cadáveres alienígenas podrá entonces ser iniciada. Para abortar la misión regrese los acuanautas X-Com al submarino y haga clic en el icono 'Abortar Misión'.\"\n  STR_UFO_GROUND_ASSAULT: \"ASALTO A SUBMARINO ALIENÍGENA\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"Explore el punto de amerizaje y, si es posible, gane acceso al submarino alienígena. Esta misión se completará cuando todas las unidades enemigas hayan sido eliminadas o neutralizadas. La recuperación de restos del submarino alienígena, tecnología y cadáveres alienígenas podrá entonces ser iniciada. Para abortar la misión regrese los acuanautas X-Com al submarino y haga clic en el icono 'Abortar Misión'.\"\n  STR_BASE_DEFENSE: \"DEFENSA DE BASE\"\n  STR_BASE_UC_: \"BASE>{0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"Una nave alienígena ha amerizado muy cerca. Nuestra base está en peligro. Según el procedimiento habitual, se ha evacuado todo el personal no combatiente y los submarinos X-Com. Los alienígenas accederán a la base por las compuertas del hangar o por la escotilla de acceso. Defienda la base y sus instalaciones vitales a toda costa, es una lucha a vida o muerte. Si presiona en el icono de 'Abortar misión' aceptará la derrota y perderá la base.\"\n  STR_ALIEN_COLONY_ATTACK_MISSION: \"ATAQUE A COLONIA ALIENÍGENA\"\n  STR_ALIEN_BASE_ASSAULT: \"COLONIA ALIENÍGENA PARTE UNO\"\n  STR_ALIEN_COLONY_P1_BRIEFING: \"Esta misión consiste en un ataque a una colonia alienígena. Hay dos niveles, lleva a todos los aquanautas a la salida brillante del primer complejo y pulsa en 'Abortar misión' para proseguir. Todo el equipo que abandones se quedará en el fondo del mar hasta que completes la segunda parte. Para Cancelar, pon a los aquanautas en el submarino y pulsa en el icono 'Abortar misión'.\"\n  STR_ALIEN_COLONY_P2: \"COLONIA ALIENÍGENA PARTE DOS\"\n  STR_ALIEN_COLONY_P2_BRIEFING: \"Tras haber completado el primer nivel y entrado en el núcleo de la colonia, ahora tu misión es destruir el centro de control, recoger el dispositivo Synomium o eliminar a todos los alienígenas. Para Cancelar, pon a todos los aquanautas en el punto de partida y pulsa en el icono 'Abortar misión'. Todo el equipo X-Com útil regresará a la base.\"\n  STR_ALIENS_LAUNCH_PORT_TERROR: \"ALIENÍGENAS LANZAN{NEWLINE}ATAQUE EN PUERTO\"\n  STR_PORT_TERROR: \"ALIENÍGENAS LANZAN ATAQUE A PUERTO\"\n  STR_PORT_TERROR_BRIEFING: \"Los alienígenas han lanzado un ataque contra instalaciones en la superficie. El puerto y su población civil se han puesto en riesgo. Su escuadrón debe eliminar todos los alienígenas y proteger a las personas inocentes de esta incursión alienígena. Para Cancelar, coloque los aquanautas en el submarino volante y haz clic en el icono 'Abortar Misión'.\"\n  STR_ALIENS_LAUNCH_ISLAND_TERROR: \"ALIENÍGENAS LANZAN{NEWLINE}ATAQUE EN ISLA\"\n  STR_ISLAND_TERROR: \"ALIENÍGENAS LANZAN ATAQUE A ISLA\"\n  STR_ISLAND_TERROR_BRIEFING: \"Los alienígenas han lanzado un ataque contra instalaciones en la superficie. La Isla y su población se han puesto en riesgo. Su escuadrón debe eliminar todos los alienígenas y proteger a los inocentes transeúntes de esta incursión alienígena. Para Cancelar, coloque los aquanautas en el submarino volante y haz clic en el icono 'Abortar Misión'.\"\n  STR_ALIENS_ATTACK_SHIPPING_ROUTE: \"ALIENÍGENAS ATACAN{NEWLINE}RUTA DE ENVÍO\"\n  STR_CARGO_SHIP_P1: \"BUQUE DE CARGA PARTE UNO\"\n  STR_CARGO_SHIP_P2: \"BUQUE DE CARGA PARTE DOS\"\n  STR_CRUISE_SHIP_P1: \"CRUCERO PARTE UNO\"\n  STR_CRUISE_SHIP_P2: \"CRUCERO PARTE DOS\"\n  STR_SHIP_RESCUE_MISSION: \"MISIÓN DE RESCATE A BUQUE\"\n  STR_SHIP_RESCUE_P1_BRIEFING: \"Esta misión es una cacería, elimine todas las unidades alienígenas en el barco, y preserve la vida de los civiles a bordo. Los alienígenas están dispersos por encima y debajo de la cubierta, asegure las cubiertas superiores antes de entrar en los inferiores. Para Cancelar, coloque los aquanautas en el submarino volante y haz clic en el icono 'Abortar Misión'.\"\n  STR_SHIP_RESCUE_P2_BRIEFING: \"Ahora que la cubierta superior está despejada proceda a las cubiertas inferiores. Utilizando el ascensor de carga se desciende a la bodega. Su escuadrón debe eliminar todos los alienígenas en este nivel para completar la misión. Para abortar coloque todos los aquanautas en el ascensor inicial y haga clic en el icono 'Abortar Misión'.\"\n  STR_ALIEN_ACTIVITY_DETECTED: \"ACTIVIDAD ALIENÍGENA DETECTADA\"\n  STR_ALIEN_CONTACT_SITE_MISSION: \"ASALTO A COMUNICACIONES ALIENÍGENAS\"\n  STR_ARTIFACT_SITE_P1: \"COMUNICACIONES ALIENÍGENAS PARTE UNO\"\n  STR_ARTIFACT_SITE_P1_BRIEFING: \"Esta misión es un asalto en un sitio de comunicación alienígena recién activado. Hay 2 niveles para alcanzar el sitio, el fondo del mar con sus pirámides alienígenas y un complejo alienígena escondido. Lleve todos los aquanautas a la entrada del complejo y haga clic en el icono 'Abortar Misión' para proceder. Para Cancelar, coloque los aquanautas en el submarino volante y haga clic en el icono 'Abortar Misión'.\"\n  STR_ARTIFACT_SITE_P2: \"COMUNICACIONES ALIENÍGENAS PARTE DOS\"\n  STR_ARTIFACT_SITE_P2_BRIEFING: \"Habiendo arrazado las estructuras alienígenas y entrado en el complejo, los objetivos de la misión son claros. Penetrar el corazón de la instalación alienígena y destruir el dispositivo de Control Molecular Synomium. Para abortar coloque todos los aquanautas en el ascensor inicial y haga clic en el icono 'Abortar Misión'.\"\n  STR_SIGSBEE_DEEP_MISSION: \"ASALTO A CIUDAD ALIENÍGENA{NEWLINE}BAJA SIGSBEE NIVEL UNO\"\n  STR_TLETH_P1_BRIEFING: \"Nos adentramos en lo desconocido, de aquí en adelante podemos encontrarnos cualquier cosa. Sabemos que hay dos niveles en la ciudad, tu escuadrón debe llegar rápido a la salida del  nivel para pasar al siguiente. Lleva a todos los aquanautas a la salida y pulsa en 'Arbortar misión' para avanzar.Si la cancelas en otro lugar, la misión se terminará.\"\n  STR_TLETH_ATTACK_MISSION: \"ASALTO A CIUDAD ALIENÍGENA{NEWLINE}T'LETH NIVEL DOS\"\n  STR_TLETH_P2_BRIEFING: \"Seguimos avanzando hacia lo desconocido, de aquí en adelante podemos encontrarnos cualquier cosa. Sabemos que hay otro nivel en la ciudad, tu escuadrón debe llegar rápido a la salida de este nivel para pasar al siguiente. Lleva a todos los aquanautas a la salida y pulsa en 'Abortar misión' para  avanzar. Si la abortas en otro lugar, la misión se terminará.\"\n  STR_FINAL_TLETH_MISSION: \"ASALTO FINAL A CIUDAD ALIENÍGENA{NEWLINE}T'LETH NIVEL TRES\"\n  STR_TLETH_P3_BRIEFING: \"El final está a la vista, a partir de ahora debemos buscar la cripta del Alienígena Supremo. Destruye los 8 alimentadores de la  tumba para acabar con la amenaza alienígena. ¡No te rindas! Si pulsas en 'Abortar misión', la anulará.\"\n  STR_TLETH_P1: \"CIUDAD ALIENÍGENA PARTE UNO\"\n  STR_TLETH_P2: \"CIUDAD ALIENÍGENA PARTE DOS\"\n  STR_TLETH_P3: \"CIUDAD ALIENÍGENA PARTE TRES\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"¡NO HAY MUELLES LIBRES PARA CONSTRUIR NAVES!{SMALLLINE}Cada submarino volante asignado o trasladado a una base, comprado o construido ocupa un muelle. Construye un nuevo muelle para submarinos o traslada un submarino a otra base.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"¡NO HAY MUELLES LIBRES PARA COMPRAR SUBMARINOS!{SMALLLINE}Cada submarino volante asignado o trasladado a una base, comprado o construido ocupa un muelle. Construye un nuevo muelle para submarinos o traslada un submarino a otra base.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"¡NO HAY MUELLES LIBRES PARA TRASLADAR SUBMARINOS!{SMALLLINE}Cada submarino volante asignado o trasladado a una base, comprado o construido ocupa un muelle. Construye un nuevo muelle para submarinos o traslada un submarino a otra base.\"\n  STR_CANNOT_BUILD_HERE: \"¡NO PUEDE CONSTRUIR AQUÍ!{SMALLLINE}Sólo junto a una escotilla.\"\n  STR_NO_FREE_ACCOMODATION: \"¡NO HAY ESPACIO DISPONIBLE!{SMALLLINE}La base de destino no tiene espacio suficiente en las viviendas.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"¡NO HAY ESPACIO PARA TRABAJAR!{SMALLLINE}Construya un taller nuevo o redusca los técnicos de otros proyectos.\"\n  STR_NOT_ENOUGH_MONEY: \"¡NO HAY DINERO SUFICIENTE!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"¡NO HAY SUFICIENTE ESPACIO DE ALMACENAJE!{SMALLLINE}Construya un almacén nuevo o traslade artículos a otras bases.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"¡NO HAY SUFICIENTE ESPACIO HABITABLE!{SMALLLINE}Construya nuevas viviendas o traslade personal a otras bases.\"\n  STR_LAUNCH_INTERCEPTION: \"INICIAR INTERCEPCIÓN\"\n  STR_CRAFT: \"NAVE\"\n  STR_STATUS: \"SITUACIÓN\"\n  STR_BASE: \"BASE\"\n  STR_READY: \"LISTO\"\n  STR_OUT: \"FUERA\"\n  STR_REPAIRS: \"REPARACIONES\"\n  STR_REFUELLING: \"REPOSTANDO\"\n  STR_REARMING: \"REARMANDO\"\n  STR_TARGET: \"OBJETIVO: {0}\"\n  STR_WAY_POINT: \"DESTINO\"\n  STR_ARE_YOU_SURE_CYDONIA: \"¿Estás seguro de que quieres mandar este submarino a T'leth en una misión?\"\n  STR_YES: \"SÍ\"\n  STR_NO: \"NO\"\n  STR_SELECT_DESTINATION: \"SELECCIONE DESTINO\"\n  STR_CYDONIA: \"T'LETH\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"SELECCIONE UBICACIÓN DE LA{NEWLINE}NUEVA BASE\"\n  STR_RETURN_TO_BASE: \"REGRESAR A LA BASE\"\n  STR_SELECT_NEW_TARGET: \"SELECCIONE OTRO BLANCO\"\n  STR_PATROL: \"PATRULLAR\"\n  STR_STATUS_: \"SITUACIÓN>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"AVERIADO - REGRESANDO A LA BASE\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"POCO COMBUSTIBLE - REGRESANDO A LA BASE\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"MISIÓN COMPLETA - REGRESANDO A BASE\"\n  STR_PATROLLING: \"PATRULLANDO\"\n  STR_TAILING_UFO: \"SIGUIENDO A UN OSNI\"\n  STR_INTERCEPTING_UFO: \"INTERCEPTANDO OSNI-{0}\"\n  STR_RETURNING_TO_BASE: \"REGRESANDO A LA BASE\"\n  STR_DESTINATION_UC_: \"DESTINO: {0}\"\n  STR_BASE_UC: \"BASE>{ALT}{0}\"\n  STR_SPEED_: \"VELOCIDAD>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"VELOCIDAD MÁXIMA>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"PROFUNDIDAD>{ALT}{0}\"\n  STR_AIRBORNE: \"POR AIRE\"\n  STR_VERY_LOW: \"SUPERFICIAL\"\n  STR_LOW_UC: \"NORMAL\"\n  STR_HIGH_UC: \"PROFUNDO\"\n  STR_VERY_HIGH: \"MUY PROFUNDO\"\n  STR_FUEL: \"COMBUSTIBLE>{ALT}{0}\"\n  STR_WEAPON_ONE: \"ARMA-1>{ALT}{0}\"\n  STR_NONE_UC: \"NINGUNA\"\n  STR_ROUNDS_: \"BALAS>{ALT}{0}\"\n  STR_WEAPON_TWO: \"ARMA-2>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"SUBMARINO VOLANTE\"\n  STR_BASE_: \"Base>{0}\"\n  STR_NAME_UC: \"NOMBRE\"\n  STR_AMMO_: \"MUNICIÓN>{ALT}{0}\"\n  STR_CREW: \"TRIPULACIÓN\"\n  STR_EQUIPMENT_UC: \"ARMAMENTO\"\n  STR_ARMOR: \"ARMADURA\"\n  STR_MAX: \"MAX>{ALT}{0}\"\n  STR_ROOKIE: \"Marinero\"\n  STR_SQUADDIE: \"Cabo\"\n  STR_SERGEANT: \"Alférez\"\n  STR_CAPTAIN: \"Teniente\"\n  STR_COLONEL: \"Comandante\"\n  STR_COMMANDER: \"Capitán\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Elija el Escuadrón para {0}\"\n  STR_SORT_BY: \"ORDENAR POR...\"\n  STR_ORIGINAL_ORDER: \"ORDEN ORIGINAL\"\n  STR_MISSIONS2: \"MISIÓNES\"\n  STR_KILLS2: \"MUERTES\"\n  STR_WOUND_RECOVERY2: \"RECUPERACIÓN DE HERIDA\"\n  STR_SPACE_AVAILABLE: \"ESPACIO DISPONIBLE>{ALT}{0}\"\n  STR_SPACE_USED: \"ESPACIO USADO>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"ESPACIO USADO\"\n  STR_RANK: \"RANGO\"\n  STR_WOUNDED: \"HERIDO\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Equipo para {0}\"\n  STR_DEFENSE_VALUE: \"Valor Defensivo\"\n  STR_HIT_RATIO: \"Proporción\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}listo para{NEWLINE}amerizar cerca de{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"¿Iniciar la misión?\"\n  STR_SELECT_ARMAMENT: \"Seleccione Armamento\"\n  STR_AMMUNITION_AVAILABLE: \"MUNICIÓN DISPONIBLE\"\n  STR_ARMAMENT: \"ARMAMENTO\"\n  STR_NOT_AVAILABLE: \"N.D.\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"SELECCIONAR ARMADURA PARA{NEWLINE}{0}\"\n  STR_TYPE: \"TIPO\"\n  STR_PLASTIC_AQUA_ARMOR_UC: \"ARMADURA DE AQUAPLASTICOS\"\n  STR_ION_ARMOR_UC: \"ARMADURA DE IONES\"\n  STR_MAGNETIC_ION_ARMOR_UC: \"ARMADURA MAGNÉTICA DE IONES\"\n  STR_PLASTIC_AQUA_ARMOR_UFOPEDIA: \"Este blindaje emplea la sustancia alienígena recién descubierta, el aquaplástico, y les da a nuestros aquanautas una oportunidad de luchar contra las incursiones alienígenas.\"\n  STR_ION_ARMOR_UFOPEDIA: \"Una protección para los aquanautas, nueva y poderosa. Está reforzada con energía de iones y aumenta la fuerza y la velocidad del que la lleva. Es la mejor protección para las tropas de combate.\"\n  STR_MAGNETIC_ION_ARMOR_UFOPEDIA: \"Una mejora de la armadura de iones, incorpora la tecnología magnética para permitir total libertad de movimientos en el medio acuático.\"\n  STR_SELECT_ARMOR: \"Seleccione Armadura\"\n  STR_NORTH: \"NORTE\"\n  STR_NORTH_EAST: \"NORESTE\"\n  STR_EAST: \"ESTE\"\n  STR_SOUTH_EAST: \"SURESTE\"\n  STR_SOUTH: \"SUR\"\n  STR_SOUTH_WEST: \"SUROESTE\"\n  STR_WEST: \"OESTE\"\n  STR_NORTH_WEST: \"NOROESTE\"\n  STR_SELECT_ACTION: \"SELECCIONE ACCIÓN\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"CONTINUAR PERSECUCIÓN\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"PERSECUCIÓN SIN INTERCEPCIÓN\"\n  STR_VERY_LARGE: \"MUY GRANDE\"\n  STR_LARGE: \"GRANDE\"\n  STR_MEDIUM_UC: \"NORMAL\"\n  STR_SMALL: \"PEQUEÑO\"\n  STR_VERY_SMALL: \"MUY PEQUEÑO\"\n  STR_GROUNDED: \"CAÍDO\"\n  STR_DETECTED: \"Detectado\"\n  STR_SIZE_UC: \"TAMAÑO\"\n  STR_ALTITUDE: \"PROFUNDIDAD\"\n  STR_HEADING: \"RUMBO\"\n  STR_SPEED: \"VELOCIDAD\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"CENTRAR EN OSNI - TIEMPO = 5 Seg\"\n  STR_TRACKING_LOST: \"RASTRO PERDIDO\"\n  STR_REDIRECT_CRAFT: \"CAMBIAR RUMBO\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"IR A ÚLTIMA POSICIÓN CONOCIDA DEL OSNI \"\n  STR_UFO_: \"OSNI-{0}\"\n  STR_ALIEN_BASE_: \"COLONIA ALIENÍGENA-{0}\"\n  STR_CRASH_SITE_: \"SITIO DE CHOQUE-{0}\"\n  STR_LANDING_SITE_: \"SITIO DE CAÍDA-{0}\"\n  STR_WAY_POINT_: \"DESTINO-{0}\"\n  STR_TERROR_SITE: \"LUGAR DE INCURSIÓN-{0}\"\n  STR_ARTIFACT_SITE: \"SITIO DEL ARTEFACTO-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}ha llegado a{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"Está patrullando\"\n  STR_ALIEN_ORIGINS: \"Origen de los Alienígenas\"\n  STR_THE_ULTIMATE_THREAT: \"La Amenaza Definitiva\"\n  STR_TLETH_ALIEN_CITY: \"T'leth, la Ciudad Alienígena\"\n  STR_UFOPAEDIA: \"OSNIpedia\"\n  STR_XCOM_CRAFT_ARMAMENT: \"NAVES Y ARMAS DE X-COM\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"SISTEMAS DE ARMAS SUMERGIBLES\"\n  STR_WEAPONS_AND_EQUIPMENT: \"ARMAMENTO GENERAL\"\n  STR_ALIEN_ARTIFACTS: \"ARTEFACTOS AQUÁTICOS\"\n  STR_BASE_FACILITIES: \"INSTALACIONES X-COM\"\n  STR_ALIEN_LIFE_FORMS: \"CRIATURAS ALIENÍGENAS\"\n  STR_ALIEN_RESEARCH_UC: \"TECNOLOGÍA ALIENÍGENA\"\n  STR_UFO_COMPONENTS: \"NUEVAS TECNOLOGÍAS SUMERGIBLES\"\n  STR_UFOS: \"SUBMARINOS ALIENÍGENAS\"\n  STR_SELECT_ITEM: \"SELECCIONE ARTÍCULO\"\n  STR_ACCELERATION: \"ACELERACIÓN>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"CAPACIDAD DE COMBUSTIBLE>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"TORRE DE ARMAS>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"RESISTENCIA>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"ESPACIO DE CARGA>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"CAPACIDAD SAS>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Daño\"\n  STR_RANGE: \"Alcance\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Precisión\"\n  STR_RE_LOAD_TIME: \"Tiempo de recarga\"\n  STR_SECONDS: \"{0}s\"\n  STR_DAMAGE_ARMOR_PIERCING: \"PERFORANTE\"\n  STR_DAMAGE_INCENDIARY: \"FÓSFORO\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"EXPLOSIVO\"\n  STR_DAMAGE_LASER_BEAM: \"RAYO GAUSS\"\n  STR_DAMAGE_PLASMA_BEAM: \"RAYO SóNICO\"\n  STR_DAMAGE_STUN: \"CONGELAR\"\n  STR_DAMAGE_MELEE: \"CUERPO A CUERPO\"\n  STR_DAMAGE_ACID: \"ÁCIDO\"\n  STR_DAMAGE_SMOKE: \"HUMO\"\n  STR_SHOT_TYPE: \"TIPO\"\n  STR_ACCURACY_UC: \"PRECISIÓN\"\n  STR_TIME_UNIT_COST: \"COSTO UT\"\n  STR_DAMAGE_UC: \"DAÑO\"\n  STR_AMMO: \"MUNICIÓN\"\n  STR_SHOT_TYPE_AUTO: \"Automático\"\n  STR_SHOT_TYPE_SNAP: \"Simple\"\n  STR_SHOT_TYPE_AIMED: \"Precisión\"\n  STR_CONSTRUCTION_TIME: \"Tiempo de Construcción\"\n  STR_CONSTRUCTION_COST: \"Costo de Construcción\"\n  STR_MAINTENANCE_COST: \"Costo de Cantenimiento\"\n  STR_LOW: \"Bajo\"\n  STR_MEDIUM: \"Mediano\"\n  STR_HIGH: \"Pesado\"\n  STR_CRAFT_WEAPON: \"Arma de Submarino\"\n  STR_CRAFT_AMMUNITION: \"Munición de Submarino\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Sistema de Armas Pesadas\"\n  STR_WEAPON: \"Arma\"\n  STR_AMMUNITION: \"Munición\"\n  STR_EQUIPMENT: \"Equipo\"\n  STR_ALIEN_CORPSE: \"Cadáver Alienígena\"\n  STR_UFO_COMPONENT: \"Pieza de un OSNI\"\n  STR_PERSONAL_ARMOR: \"Armadura Personal\"\n  STR_RAW_MATERIALS: \"Materias Primas\"\n  STR_HWP_SOLID_HARPOON_BOLTS: \"Arpones Sólidos\"\n  STR_ALIEN: \"Alienígena\"\n  STR_AQUATOID: \"Aquatoide\"\n  STR_GILLMAN: \"Hombre-Branquia\"\n  STR_LOBSTERMAN: \"Hombre-Langosta\"\n  STR_TASOTH: \"Tasoth\"\n  STR_CALCINITE: \"Calcinite\"\n  STR_DEEP_ONE: \"Anuroide\"\n  STR_BIODRONE: \"Telecerebro\"\n  STR_TENTACULAT: \"Tentaculat\"\n  STR_TRISCENE: \"Triscene\"\n  STR_HALLUCINOID: \"Alucinoide\"\n  STR_XARQUID: \"Calaxmar\"\n  STR_ZOMBIE: \"Zombi\"\n  STR_LIVE_COMMANDER: \"Comandante\"\n  STR_LIVE_NAVIGATOR: \"Navegante\"\n  STR_LIVE_MEDIC: \"Médico\"\n  STR_LIVE_TECHNICIAN: \"Técnico\"\n  STR_LIVE_SQUAD_LEADER: \"Líder de Escuadrón\"\n  STR_LIVE_SOLDIER: \"Soldado\"\n  STR_LIVE_TERRORIST: \"Terrorista\"\n  STR_AQUATOID_COMMANDER: \"Comandante Aquatoide\"\n  STR_AQUATOID_NAVIGATOR: \"Navegante Aquatoide\"\n  STR_AQUATOID_MEDIC: \"Médico Aquatoide\"\n  STR_AQUATOID_TECHNICIAN: \"Técnico Aquatoide\"\n  STR_AQUATOID_SQUAD_LEADER: \"Líder de Escuadrón Aquatoide\"\n  STR_AQUATOID_SOLDIER: \"Soldado Aquatoide\"\n  STR_GILLMAN_COMMANDER: \"Comandante Hombre-Branquia\"\n  STR_GILLMAN_TECHNICIAN: \"Técnico Hombre-Branquia\"\n  STR_GILLMAN_SQUAD_LEADER: \"Líder de Escuadrón Hombre-Branquia\"\n  STR_GILLMAN_SOLDIER: \"Soldado Hombre-Branquia\"\n  STR_LOBSTERMAN_COMMANDER: \"Comandante Hombre-Langosta\"\n  STR_LOBSTERMAN_NAVIGATOR: \"Navegante Hombre-Langosta\"\n  STR_LOBSTERMAN_TECHNICIAN: \"Técnico Hombre-Langosta\"\n  STR_LOBSTERMAN_SQUAD_LEADER: \"Líder de Escuadrón Hombre-Langosta\"\n  STR_LOBSTERMAN_SOLDIER: \"Soldado Hombre-Langosta\"\n  STR_TASOTH_SQUAD_LEADER: \"Líder de Escuadrón Tasoth\"\n  STR_TASOTH_SOLDIER: \"Soldado Tasoth\"\n  STR_CALCINITE_TERRORIST: \"Calcinite Terrorista\"\n  STR_DEEP_ONE_TERRORIST: \"Anuroide Terrorista\"\n  STR_BIODRONE_TERRORIST: \"Telecerebro Terrorista\"\n  STR_TENTACULAT_TERRORIST: \"Tentaculat Terrorista\"\n  STR_TRISCENE_TERRORIST: \"Triscene Terrorista\"\n  STR_HALLUCINOID_TERRORIST: \"Alucinoide Terrorista\"\n  STR_XARQUID_TERRORIST: \"Calaxmar Terrorista\"\n  STR_ION_BEAM_ACCELERATORS: \"Aceleradores de Rayos de Iones\"\n  STR_MAGNETIC_NAVIGATION: \"Navegación Magnética\"\n  STR_ALIEN_SUB_CONSTRUCTION: \"Construcción de Subm. Alienígenas\"\n  STR_ALIEN_CRYOGENICS: \"Hibernación Alienígena\"\n  STR_ALIEN_CLONING: \"Clonación Alienígena\"\n  STR_ALIEN_LEARNING_ARRAYS: \"Unidades de Enseñanza Alienígenas\"\n  STR_ALIEN_IMPLANTER: \"Implantador Alienígena\"\n  STR_EXAMINATION_ROOM: \"Sala de Exámenes\"\n  STR_AQUA_PLASTICS: \"Aquaplásticos\"\n  STR_ALIEN_REANIMATION_ZONE: \"Zona de Reanimación de Alienígenas\"\n  STR_PLASTIC_AQUA_ARMOR: \"Blindaje de Aquaplástico\"\n  STR_ION_ARMOR: \"Blindaje Iónico\"\n  STR_MAGNETIC_ION_ARMOR: \"Blindaje Magné. de Iones\"\n  STR_HWP_AQUA_JET_MISSILES: \"Torpedos Aquajet \"\n  STR_HWP_DISPLACER_PWT: \"Torpedo O.I.\"\n  STR_GAUSS_TECH: \"Tecnología Gauss\"\n  STR_NEW_FIGHTER_FLYING_SUB: \"Nuevo Submarino Volante tipo Caza\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Nuevo Caza-Transporte\"\n  STR_THE_LATEST_FLYING_SUB: \"Lo Último en Submarinos Volantes\"\n  STR_ARMOR_PIERCING: \"PERFORANTE\"\n  STR_COELACANTH_GAS_CANNON: \"Coelacanth/Cañón Gas\"\n  STR_COELACANTH_AQUA_JET: \"Coelacanth/Aquajet\"\n  STR_COELACANTH_GAUSS: \"Coelacanth/Gauss\"\n  STR_DISPLACER_SONIC: \"Desplazador/Sónico\"\n  STR_DISPLACER_PWT: \"Desplazador/T.O.I.\"\n  STR_AJAX_LAUNCHER: \"Lanzador Ajax\"\n  STR_DUP_HEAD_LAUNCHER: \"Lanzamisiles CUR\"\n  STR_CRAFT_GAS_CANNON: \"Cañón de Gas de la Nave\"\n  STR_PWT_CANNON: \"Cañón O.I.\"\n  STR_GAUSS_CANNON: \"Cañón Gauss\"\n  STR_GAUSS_CANNON_AMMO: \"Munición de Cañón Gauss\"\n  STR_SONIC_OSCILLATOR: \"Oscilador Sónico\"\n  STR_AJAX_TORPEDOES: \"Torpedos Ajax\"\n  STR_DUP_HEAD_TORPEDOES: \"Torpedos CUR\"\n  STR_CRAFT_GAS_CANNON_ROUNDS_X50: \"Disparos del CG(x50)\"\n  STR_SONIC_WAVE: \"Onda Sónica\"\n  STR_PULSE_WAVE_TORPEDOES: \"Munición T.O.I.\"\n  STR_SOLDIER: \"Aquanauta\"\n  STR_SCIENTIST: \"Científico\"\n  STR_ENGINEER: \"Técnico\"\n  STR_NORTH_ATLANTIC: \"Atlántico Norte\"\n  STR_SOUTH_ATLANTIC: \"Atlántico Sur\"\n  STR_NORTH_PACIFIC: \"Pacifico Norte\"\n  STR_SOUTH_PACIFIC: \"Pacifico Sur\"\n  STR_MEDITERRANEAN: \"Mediterraneo\"\n  STR_SOUTH_CHINA_SEA: \"Mar de China\"\n  STR_INDIAN_OCEAN: \"Océano Índico\"\n  STR_THE_EAST_SEA: \"Mar de Japon\"\n  STR_NORTH_SEA: \"Mar del Norte\"\n  STR_CARRIBEAN: \"Caribe\"\n  STR_ANTARCTIC: \"Antártico\"\n  STR_ARCTIC: \"Ártico\"\n  STR_EURASIA: \"Eurasia\"\n  STR_NORTH_AMERICA: \"Norteamérica\"\n  STR_AFRICA: \"África\"\n  STR_MAXIMUM_SPEED: \"Velocidad Máxima\"\n  STR_TRANSMISSION_RESOLVER_UC: \"ESCODIFICADOR TARNS\"\n  STR_TRITON: \"TRITÓN\"\n  STR_HAMMERHEAD: \"HAMMERHEAD\"\n  STR_LEVIATHAN: \"LEVIATHAN\"\n  STR_BARRACUDA: \"BARRACUDA\"\n  STR_MANTA: \"MANTA\"\n  STR_UFO: \"SUBMARINO ALIENíGENA\"\n  STR_AJAX: \"AJAX\"\n  STR_DUP_HEAD: \"CABEZA C.U.R.\"\n  STR_CRAFT_GAS_CANNON_UC: \"CG DE LA NAVE\"\n  STR_PWT_CANNON_UC: \"CAÑÓN T.O.I.\"\n  STR_GAUSS_CANNON_UC: \"CAÑÓN GAUSS\"\n  STR_SONIC_OSCILLATOR_UC: \"OSCILADOR SÓNICO\"\n  STR_DAMAGE_CAPACITY: \"Resistencia\"\n  STR_WEAPON_POWER: \"Potencia del Arma\"\n  STR_WEAPON_RANGE: \"Alcance del Arma\"\n  STR_AIR_LOCK: \"Esclusa\"\n  STR_LABORATORY: \"Laboratorio\"\n  STR_WORKSHOP: \"Taller\"\n  STR_STANDARD_SONAR: \"Sonar Estándar\"\n  STR_WIDE_ARRAY_SONAR: \"Sonar de Red Amplia\"\n  STR_TORPEDO_DEFENSES: \"Torpedos de Defensa\"\n  STR_GENERAL_STORES: \"Almacenes Generales\"\n  STR_ALIEN_CONTAINMENT: \"Confinamiento Alienígena\"\n  STR_GAUSS_DEFENSES: \"Defensas Gauss\"\n  STR_SONIC_DEFENSES: \"Defensas Sónicas\"\n  STR_PWT_DEFENSES: \"Defensas de T.O.I.\"\n  STR_BOMBARDMENT_SHIELD: \"Escudo de Resonancia\"\n  STR_MC_GENERATOR: \"Escudo de Control Molecular\"\n  STR_MC_LAB: \"Laboratorio de Control Molecular\"\n  STR_TRANSMISSION_RESOLVER: \"Descodificador Tarns\"\n  STR_SUB_PEN: \"Muelle para Submarinos\"\n  STR_USA: \"EE.UU.\"\n  STR_ALASKA: \"ALASKA\"\n  STR_EU_SYNDICATE: \"EURO-SINDICATO\"\n  STR_ARABIAN_BLOC: \"BLOQUE ÁRABE\"\n  STR_EGYPTIAN_CARTEL: \"CÁRTEL EGIPSIO\"\n  STR_AFRICA_CORP: \"CORP. AFRICANA\"\n  STR_BRAZILIAN_UNION: \"UNIÓN BRASILEÑA\"\n  STR_NEW_MEXICO: \"NUEVO MÉJICO \"\n  STR_ASIAN_COALITION: \"COALICIÓN ASIÁTICA\"\n  STR_SCANDINAVIA: \"ESCANDINAVIA\"\n  STR_NEO_JAPAN: \"NUEVO JAPON\"\n  STR_FREE_CHINA: \"CHINA LIBRE\"\n  STR_AUSTRALASIA: \"AUSTRALASIA\"\n  STR_FED_KOREA: \"FED COREANA\"\n  STR_EURASIA_UC: \"EURASIA\"\n  STR_ICELANDIC_UNION: \"UNIÓN ISLÁNDICA\"\n  STR_TANK: \"Sistema de Armas Sumergibles\"\n  STR_CIVILIAN: \"Civil\"\n  STR_JAN: \"Ene\"\n  STR_FEB: \"Feb\"\n  STR_MAR: \"Mar\"\n  STR_APR: \"Abr\"\n  STR_MAY: \"May\"\n  STR_JUN: \"Jun\"\n  STR_JUL: \"Jul\"\n  STR_AUG: \"Ago\"\n  STR_SEP: \"Sep\"\n  STR_OCT: \"Oct\"\n  STR_NOV: \"Nov\"\n  STR_DEC: \"Dic\"\n  STR_INTERNATIONAL_RELATIONS: \"Relaciones Internacionales\"\n  STR_COUNTRY: \"País\"\n  STR_FUNDING: \"Financiación\"\n  STR_CHANGE: \"Cambio\"\n  STR_WEAPON_SYSTEMS: \"SISTEMAS DE ARMAS\"\n  STR_HWPS: \"SASs\"\n  STR_DAMAGE_UC_: \"DAÑO>{ALT}{0}\"\n  STR_AIR_LOCK_UFOPEDIA: \"La esclusa de aire permite transportar equipo y personal de una base submarina a otra. Es lo primero que se construye en un emplazamiento nuevo. Este compartimiento es vulnerable y puede ser invadido.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Cada zona de alojamiento puede albergar a 50 miembros del personal. Las instalaciones son un tanto básicas y funcionales.\"\n  STR_LABORATORY_UFOPEDIA: \"En un bloque de laboratorios pueden trabajar cincuenta científicos.Los laboratorios están equipados con las tecnologías más modernas para la investigación de materiales, bioquímica y armamento. X-Com tiene acceso a los mejores laboratorios de investigación del mundo,tanto civiles como militares.\"\n  STR_WORKSHOP_UFOPEDIA: \"En un taller se puede encontrar todo lo necesario para fabricar un equipo construido a partir de los diseños científicos más avanzados. El taller puede contener 50 técnicos, y los objetos que se estén fabricando también ocupan sitio.\"\n  STR_STANDARD_SONAR_UFOPEDIA: \"Un sistema de sonar normal tiene un alcance efectivo de 450 km a casi cualquier profundidad, y está conectado a una red de satélites fijos de tierra para el análisis de superficie. Los escáneres tienen una probabilidad del 10% de detectar una nave sumergible o volante por cada ciclo de 30 minutos.\"\n  STR_WIDE_ARRAY_SONAR_UFOPEDIA: \"Un sistema de sonar de largo alcance cubre una zona de más de 700 kilómetros a cualquier profundidad, y está conectado a una red de satélites fijos de tierra para el análisis de superficie. Los escáneres tienen una probabilidad del 20% de detectar una nave sumergible o volante por cada ciclo de 30 minutos.\"\n  STR_TORPEDO_DEFENSES_UFOPEDIA: \"Los sistemas de defensa contra torpedos proporcionan protección contra los ataques de sumergibles hostiles que intenten atracar en la base.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"Todo el equipo, armas, municiones, materiales recuperados y armas pesadas están situadas en almacenes, incluyendo equipo asignado los submarinos en el muelle.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"A los alienígenas capturados con vida hay que retenerlos en  instalaciones especiales. Estas unidades mantienen sus constantes vitales y reducen a cero su capacidad de lucha. En cada celda caben 10 formas de vida alienígena.\"\n  STR_GAUSS_DEFENSES_UFOPEDIA: \"Los sistemas de defensa Gauss proporcionan la protección más eficaz y moderna contra submarinos enemigos.\"\n  STR_SONIC_DEFENSES_UFOPEDIA: \"El oscilador sónico de defensa constituye una protección eficaz y poderosa contra los agresores.\"\n  STR_PWT_DEFENSES_UFOPEDIA: \"Los torpedos de ondas de impulsos son lo mejor contra los ataques  alienígenas. Estos misiles tienen cabezas de gran densidad capaces de atravesar  cualquier blindaje, y emiten ondas magnéticas que anulan las defensas electrónicas\"\n  STR_BOMBARDMENT_SHIELD_UFOPEDIA: \"El escudo de resonancia anti bombardeos evita que sumergibles alienígenas atraquen en la base, y crea un campo de resonancia que repele los ataques submarinos dando tiempo suficiente para que los sistemas de defensa abran fuego a  discreción. Así se duplica la eficacia de otros sistemas de defensa ya en activo.\"\n  STR_MC_GENERATOR_UFOPEDIA: \"Puesto que los submarinos alienígenas emplean la tecnología de Control Molecular para detectar formas de vida, podemos usar un emisor que contrarreste dicha tecnología, y así escudar la base y ocultar nuestra presencia.\"\n  STR_MC_LAB_UFOPEDIA: \"El laboratorio de Control Molecular puede implantar y entrenar a diez aquanautas a la vez. Realizan un implante en el cráneo de los aquanautas, quienes aprenden a usarlos con un entrenamiento intensivo. Esta técnica se utiliza conjuntamente con Dispositivos Moleculares que pueden emplearse en el combate.\"\n  STR_TRANSMISSION_RESOLVER_UFOPEDIA: \"Las comunicaciones alienígenas emplean la red de implantes por control molecular que ellos mismos han creado. El descodificador tarns intercepta las transmisiones de submarinos enemigos y descodifica la información.  Muestra el tipo de submarino, la raza alienígena y qué actividad está en curso.\"\n  STR_SUB_PEN_UFOPEDIA: \"Cada muelle puede cobijar un submarino y cuenta con instalaciones para el mantenimiento, reabastecimiento y reparación de la flota de X-Com. Cada submarino volante atracado en una base debe tener un muelle reservado exclusivamente para él, incluso cuando ha salido en una misión.\"\n  STR_DART_PISTOL_UFOPEDIA: \"El lanza saetas X-Com, es una unidad pequeña, precisa y de gran potencia con un cargador de 12 dardos que son disparados por un cartucho de gas.\"\n  STR_JET_HARPOON_UFOPEDIA: \"El aqua rifle dispara de forma precisa arpones de acero, que van  en bloques sellados de 10. Cada uno tiene su reserva de gas individual.\"\n  STR_GAS_CANNON_UFOPEDIA: \"El peso pesado de las armas de gas es el cañón de proyectiles sólidos con la punta altamente explosiva (AE) o de fósforo; la preferida de los aquanautas.\"\n  STR_HYDRO_JET_CANNON_UFOPEDIA: \"Los cañones hidrojet son armas de infantería pesada. Disparan minitorpedos impulsados con magnesio. Aunque poderoso, es un armatoste de difícil manejo que funciona sólo en el agua.\"\n  STR_TORPEDO_LAUNCHER_UFOPEDIA: \"Este gran lanzatorpedos, un auténtico peso pesado, dispara tres tipos de proyectiles, cada  uno con su unidad propulsora. Un arma devastadora, la única pega es que es de carga manual. La munición puede ser: torpedos grandes o pequeños con punta altamente explosiva  (AE) o punta de fósforo (P), todos para ataques submarinos.\"\n  STR_GAUSS_PISTOL_UFOPEDIA: \"La pistola Gauss emplea la reciente tecnología de aceleración de partículas. Rápida y precisa, funciona dentro y fuera del agua. La tecnología Gauss se desarrolló a partir de la de Plasma, nacida en la guerra anterior.\"\n  STR_GAUSS_PISTOL_CLIP_UFOPEDIA: \"La pistola Gauss emplea la reciente tecnología de aceleración de partículas. Rápida y precisa, funciona dentro y fuera del agua. La tecnología Gauss se desarrolló a partir de la de Plasma, nacida en la guerra anterior.\"\n  STR_GAUSS_RIFLE_UFOPEDIA: \"El rifle Gauss supera a la pistola: lleva dos aceleradores de partículas. Se ha reemplazado el sistema Plasma accionado por elerio y se ha colocado un acelerador de micropartículas que genera una estela de antiprotones.\"\n  STR_GAUSS_RIFLE_CLIP_UFOPEDIA: \"El rifle Gauss supera a la pistola: lleva dos aceleradores de partículas. Se ha reemplazado el sistema Plasma accionado por elerio y se ha colocado un acelerador de micropartículas que genera una estela de antiprotones.\"\n  STR_HEAVY_GAUSS_UFOPEDIA: \"El Gauss pesado es algo engorroso pero muy eficaz. Funciona con 3 aceleradores de partículas y es prácticamente imparable. La estela de antiprotones está confinada en una cápsula de arseniuro de galio que explota al hacer impacto y suelta la antimateria.\"\n  STR_HEAVY_GAUSS_CLIP_UFOPEDIA: \"El Gauss pesado es algo engorroso pero muy eficaz. Funciona con 3 aceleradores de partículas y es prácticamente imparable. La estela de antiprotones está confinada en una cápsula de arseniuro de galio que explota al hacer impacto y suelta la antimateria.\"\n  STR_MAGNA_BLAST_GRENADE_UFOPEDIA: \"Esta granada estándar tiene un temporizador sofisticado y preciso para un control más exacto.\"\n  STR_DYE_GRENADE_UFOPEDIA: \"Las granadas Dye cumplen dos funciones y son muy útiles cuando se está al descubierto. Funcionan tanto en tierra como en agua y salen proyectadas  como una nube de partículas: en el agua sueltan una especie de tinta como si fueran un calamar, y en el aire crean una cortina de humo.\"\n  STR_PARTICLE_DISTURBANCE_GRENADE_UFOPEDIA: \"Una granada de proximidad que se puede lanzar como las normales, pero lo que la activa es el movimiento que se produzca cerca de ella. Se necesitan habilidad y práctica para utilizarlas.\"\n  STR_MAGNA_PACK_EXPLOSIVE_UFOPEDIA: \"Este explosivo debe emplearse únicamente para demolición. La experiencia ha demostrado que estos poderosos explosivos son armas ideales para eliminar de raíz a los alienígenas. La onda expansiva es muy grande, así que debes asegurarte de que los aquanautas están a una distancia segura.\"\n  STR_PARTICLE_DISTURBANCE_SENSOR_UFOPEDIA: \"Este nuevo dispositivo emplea sistemas informáticos y una variedad de detectores para identificar a las unidades enemigas en movimiento. Presione el icono del Sensor de Perturbaciones en la pantalla táctica. Elige 'Usar sensor' en el menú. En el centro del sensor aparece una flecha que indica la dirección en la que mira el aquanauta (el Norte es la de arriba). Los 'bips' indican unidades que se han movido recientemente. Las unidades grandes o las que se desplazan rápidamente emiten 'bips' largos. Las que están paradas no aparecerán en la pantalla.\"\n  STR_MEDI_KIT_UFOPEDIA: \"Para utilizar esto debes ponerte enfrente del agente de X-Com herido o colocarte junto a un aquanauta aturdido.{NEWLINE}REMEDIO> El rojo indica heridas. Elige una parte del cuerpo y dale al botón de 'Curar'. Se curarán las heridas mortales y el individuo recuperar la salud.{NEWLINE}ESTIMULANTE> Ayuda a recuperar la energía y reaviva a un aquanauta aturdido. Para ello debes colocarte justo al lado del cuerpo del aquanauta inconsciente.{NEWLINE}CALMANTE> Le sube la moral a un aquanauta herido.\"\n  STR_MC_DISRUPTOR_UFOPEDIA: \"Lo último en tecnología de Control Molecular. Sólo pueden usarlo, los aquanautas con habilidades en C.M. Presione en el Disruptor, elige un tipo de ataque y selecciona un objetivo con el cursor. Hay 2 tipos de ataques:{NEWLINE}INTERFERIR IMPLANTE> Si el ataque tiene éxito, reducirá la moral del objetivo con la probabilidad de inducir panico.{NEWLINE}CONTROLAR IMPLANTE> Si este ataque es exitoso, ganara control de la unidad enemiga.\"\n  STR_THERMAL_TAZER_UFOPEDIA: \"Este dispositivo sólo se puede usar en el combate cuerpo a cuerpo y aturde a un organismo vivo, congelándolo sin llegar a matarlo.\"\n  STR_VIBRO_BLADE_UFOPEDIA: \"La Vibroespada es un arma blanca larga y afilada cuya hoja está hecha de titanio. Gira a 600 rpm y puede perforar el blindaje más duro. Su fuente motriz es de invención alienígena. Nuestros intentos de fabricar un arma de este tipo, han fracasado: las hojas giraban demasiado despacio o explotaban con la presión.\"\n  STR_THERMIC_LANCE_UFOPEDIA: \"La Lanza Térmica ha derivado de la tecnología de la Vibroespada. La hoja gira a gran velocidad y un motor de Zrbita la calienta de modo que puede cortar un blindaje como si fuera mantequilla.\"\n  STR_HEAVY_THERMIC_LANCE_UFOPEDIA: \"La lanza térmica pesada es una versión más potente de la lanza térmica normal. Dos fuentes de calor y una asombrosa velocidad de rotación hacen que esta lanza atraviese cualquier tipo de material.\"\n  STR_SONIC_CANNON_UFOPEDIA: \"El Cañón Sónico es la más potente de la familia de las armas sónicas. Presenta un oscilador de mayor radio y una cámara reverberante más grande que el rifle. También tiene un sistema de detonación de impulsos que altera la onda ultra-sónica por modulación, produciendo un impacto sónico más eficaz.\"\n  STR_CANNON_POWER_CLIP_UFOPEDIA: \"Este compacto artefacto se usa como munición para el Cañón Sónico. Contiene una pequeña cantidad de Zrbita.\"\n  STR_SONIC_BLASTA_RIFLE_UFOPEDIA: \"Un dispositivo sónico más poderoso. Ni siquiera el acero rico en carbono es inmune a esta arma. El compacto emisor de ondas se ha mejorado con un súper amplificador conductor que aumenta la potencia del arma.\"\n  STR_BLASTA_POWER_CLIP_UFOPEDIA: \"Este pequeño objeto es la fuente de energía de un Rifle Sónico, una potente arma alienígena que lleva algo de Zrbita.\"\n  STR_SONIC_PISTOL_UFOPEDIA: \"Las Pistolas Sónicas son un arma alienígena que emplea ondas ultra-sónicas para convertir los huesos en gelatina en cuestión de segundos. Estos sonidos no pueden ser captados por el oído humano.\"\n  STR_PISTOL_POWER_CLIP_UFOPEDIA: \"Fuente de energía de la compacta Pistola Sónica alienígena. Lleva Zrbita, la fuente de toda la energía alienígena.\"\n  STR_DISRUPTOR_PULSE_LAUNCHER_UFOPEDIA: \"Es un arma alienígena acuática que lanza proyectiles de disrupción auto-impulsados y dirigibles. Al pulsar para disparar el arma, aparecerán puntos en el mapa que indican el rumbo del proyectil. Cuando hayas colocado los puntos suficientes, pulsa el icono de lanzar proyectiles.\"\n  STR_DISRUPTOR_AMMO_UFOPEDIA: \"Este aparato es un Proyectil Disruptor de Impulsos que lleva instalado un sistema de guía por ordenador. Lo dispara un lanza proyectiles de disrupción.\"\n  STR_THERMAL_SHOK_LAUNCHER_UFOPEDIA: \"Un pequeño lanza proyectiles de impacto térmico que dispara bombas químicas de congelación. Muy útil para capturar vivos a los alienígenas.\"\n  STR_THERMAL_SHOK_BOMB_UFOPEDIA: \"La Bomba de Impacto Térmico se usa para capturar vivos a los humanos, pero también se puede usar contra varias razas alienígenas. La dispara un Cañón de Impacto Térmico.\"\n  STR_SONIC_PULSER_UFOPEDIA: \"Este artefacto funciona igual que una granada normal, pero es mucho más poderoso, y emplea un rayo sónico que sale en todas las direcciones a la vez.\"\n  STR_MC_READER_UFOPEDIA: \"Hemos encontrado pequeñas unidades implantadas en los alienígenas. Son los Implantes de Control creados por los aquatoides, que suministran información desde el campo de batalla, incluso a grandes distancias. El Lector de Control Molecular es un aparato de comunicaciones alienígena que extrae información de los implantes por C.M.; las unidades X-Com lo pueden usar en combate para ver las características de un alienígena. Selecciona la opción 'Usar' y luego pulsa con el cursor en un alienígena.\"\n  STR_SURVEY_SHIP: \"Buque Hidrógrafo\"\n  STR_ESCORT: \"Escolta\"\n  STR_CRUISER: \"Crucero\"\n  STR_HEAVY_CRUISER: \"Crucero Pesado\"\n  STR_HUNTER: \"Buscador\"\n  STR_BATTLESHIP: \"Acorazado\"\n  STR_DREADNOUGHT: \"Acorazado Pesado\"\n  STR_FLEET_SUPPLY_CRUISER: \"Crucero de Suministro \"\n  MAP_SEABED: \"Lecho Marino\"\n  MAP_PIPES: \"Instalación de Investigación\"\n  MAP_PLANE: \"Avión Estrellado\"\n  MAP_ATLAN: \"Atlántida\"\n  MAP_MU: \"Templo Maya\"\n  MAP_GAL: \"Galeón Hundido\"\n  MAP_MSUNK: \"Revestimiento Hundido\"\n  MAP_VOLC: \"Volcánico \"\n  MAP_CORAL: \"Coral\"\n  MAP_PORT: \"Puerto\"\n  MAP_ISLAND: \"Isla\"\n  MAP_CARGO: \"Buques de Carga\"\n  MAP_LINERT: \"Crucero P1\"\n  MAP_LINERB: \"Crucero P2\"\n  MAP_ALART: \"Artefacto P1\"\n  MAP_GRUNGE: \"Artefacto P2\"\n  MAP_ENTRY: \"Colonia P1\"\n  MAP_A_BASE: \"Colonia P2\"\n  MAP_ALSHIP: \"T'leth P1\"\n  MAP_LEVEL: \"T'leth P2\"\n  MAP_CRYPT: \"T'leth P3\"\n  MAP_XBASES: \"Base X-Com\"\n  STR_MIXED_CREW: \"Tripulación Mezclada\"\n  STR_MIXED_CREW_2: \"Tripulación Mezclada 2\"\n  STR_RATING: \"RENDIMIENTO> {0}\"\n  STR_RATING_TERRIBLE: \"¡TERRIBLE!\"\n  STR_RATING_POOR: \"¡MALA!\"\n  STR_RATING_OK: \"OK\"\n  STR_RATING_GOOD: \"¡BUENA!\"\n  STR_RATING_EXCELLENT: \"¡EXCELENTE!\"\n  STR_SCORE: \"PUNTAJE\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"INFORME MENSUAL DE X-COM\"\n  STR_MONTH: \"Mes> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"El comité para la provisión de fondos está satisfecho con los progresos que has hecho hasta el momento.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"El comité para la provisión de fondos está muy satisfecho con los progresos que has hecho hasta el momento. Sigue así.\"\n  STR_COUNCIL_IS_DISSATISFIED: \"El comité para la provisión de fondos no está satisfecho con tu actuación. Debes ser más eficaz a la hora de enfrentarte a la amenaza alienígena o te arriesgas a que suspendan la financiación de X-Com.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"Has fracasado en tu lucha contra la invasión alienígena y el comité para la provisión de fondos se ha visto obligado a suprimir la financiación a X-Com. Cada organización se enfrentará al problema como pueda. Esperamos que sea posible llegar a un acuerdo con las antiguas fuerzas y que la población se acostumbre a los visitantes acuáticos.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} está muy complacido con tu habilidad para tratar la amenaza localizada y ha acordado aumentar los fondos de financiación.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} están tan satisfechos con tus progresos en la lucha contra las incursiones alienígenas que han decidido aumentar los fondos de financiación.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} y {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} no está satisfecho con tu lucha contra la actividad alienígena  en sus aguas y ha decidido reducir su aportación económica.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} no está satisfecho con tu lucha contra la actividad alienígena en sus aguas y ha decidido reducir su financiación.\"\n  STR_KNOTS: \"{0} nudos\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} ha firmado un acuerdo de cooperación con las fuerzas alienígenas y ha retirado su financiación a X-Com.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} han firmado un acuerdo de cooperación con las fuerzas alienígenas y han retirado su financiación a X-Com.\"\n  STR_MONTHLY_RATING: \"Evaluación Mensual> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Cambio en financiación> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"La organización para la provisión de fondos no esta contenta con tu situación financiera. Tus deudas deben bajar $1 millón o será el fin de X-Com.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"TRANSMISIÓN DE SUBPARTíCULAS RESUELTA\"\n  STR_CRAFT_TYPE: \"TIPO DE SUBMARINO\"\n  STR_RACE: \"RAZA\"\n  STR_MISSION: \"MISIÓN\"\n  STR_ZONE: \"ZONA\"\n  STR_ALLOCATE_RESEARCH: \"Asignar Investigación\"\n  STR_ALLOCATE_MANUFACTURE: \"Asignar Fabricación\"\n  STR_AZORES: \"Azores\"\n  STR_REYKJAVIK: \"Reykjavik\"\n  STR_BERMUDA: \"Bermudas\"\n  STR_NEW_YORK: \"Nueva York\"\n  STR_BOSTON: \"Boston\"\n  STR_FORT_SEVERN: \"Fuerte Severn\"\n  STR_DAKAR: \"Dakar\"\n  STR_RECIFE: \"Recife\"\n  STR_ACCRA: \"Acra\"\n  STR_ASCENSION_ISLAND: \"Isla Ascensión\"\n  STR_TRINIDADE_ISLAND: \"Isla Trinidad\"\n  STR_FALKLAND_ISLAND: \"Islas Malvinas\"\n  STR_CANARY_ISLANDS: \"Islas Canarias\"\n  STR_ANCHORAGE: \"Anchorage\"\n  STR_ST_LAWRENCE_ISLAND: \"Isla San Lorenzo\"\n  STR_SAN_FRANCISCO: \"San Francisco\"\n  STR_MIDWAY_ISLAND: \"Islas Midway\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_TASMANIA: \"Tasmania\"\n  STR_HAWAII: \"Hawái\"\n  STR_FIJI: \"Fiji\"\n  STR_TONGA: \"Tonga\"\n  STR_EASTER_ISLAND: \"Isla de Pascua\"\n  STR_GALAPAGOS_ISLAND: \"Isla Galapagos\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_SOLOMON_ISLAND: \"Islas Salomón\"\n  STR_CRETE: \"Creta\"\n  STR_LISBON: \"Lisboa\"\n  STR_PORT_SAID: \"Puerto Saíd\"\n  STR_MARSEILLES: \"Marsella\"\n  STR_TRIPOLI: \"Trípoli\"\n  STR_MANILA: \"Manila\"\n  STR_HONG_KONG: \"Hong Kong\"\n  STR_SINGAPORE: \"Singapur\"\n  STR_BANGKOK: \"Bangkok\"\n  STR_DARWIN: \"Darwin\"\n  STR_BOMBAY: \"Bombay\"\n  STR_SAYCHELLES_ISLAND: \"Islas Seychelles\"\n  STR_MALDIVE_ISLAND: \"Islas Maldivas\"\n  STR_SRI_LANKA: \"Sri Lanka\"\n  STR_MAURITIUS: \"Mauricio\"\n  STR_TOKYO: \"Tokio\"\n  STR_SHANGHAI: \"Shanghái\"\n  STR_VLADIVOSTOK: \"Vladivostok\"\n  STR_LONDON: \"Londres\"\n  STR_FAEROE_ISLAND: \"Islas Feroe\"\n  STR_ABERDEEN: \"Aberdeen\"\n  STR_OSLO: \"Oslo\"\n  STR_JAMAICA: \"Jamaica\"\n  STR_PANAMA: \"Panamá\"\n  STR_MIAMI: \"Miami\"\n  STR_PSI_TRAINING: \"Entrenam. C.M.\"\n  STR_PSIONIC_TRAINING: \"ENTRENAMIENTO CONTROL MOLECULAR\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Capacidad restante del lab. C.M..> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"Fuerza{NEWLINE}C.M.\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"Habilidad{NEWLINE}/Mejora\"\n  STR_IN_TRAINING: \"¿Entrenando?\"\n  STR_TARGETTED_BY: \"OBJETIVO DE:\"\n  STR_WEAPONS_CREW_HWPS: \"ARMAS/{NEWLINE}TRIPULACIÓN/SAS\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"tiene poco combustible,{NEWLINE}regresando a la base\"\n  STR_SOLDIER_LIST: \"Listado de Aquanautas\"\n  STR_RANK_: \"RANGO> {ALT}{0}\"\n  STR_MISSIONS: \"MISIONES> {ALT}{0}\"\n  STR_KILLS: \"BAJAS> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"RECUPERACIÓN DE HERIDA> {ALT}{0}\"\n  STR_TIME_UNITS: \"UNIDADES DE TIEMPO\"\n  STR_STAMINA: \"VIGOR\"\n  STR_HEALTH: \"SALUD\"\n  STR_BRAVERY: \"VALENTÍA\"\n  STR_REACTIONS: \"REFLEJOS\"\n  STR_FIRING_ACCURACY: \"PUNTERÍA\"\n  STR_THROWING_ACCURACY: \"PRECISIÓN DE LANZAMIENTO\"\n  STR_STRENGTH: \"FUERZA\"\n  STR_PSIONIC_STRENGTH: \"FUERZA en C.M.\"\n  STR_PSIONIC_SKILL: \"HABILIDAD en C.M.\"\n  STR_NEW_RANK: \"NUEVO RANGO\"\n  STR_PROMOTIONS: \"Promociones\"\n  STR_SOLDIERS_UC: \"AQUANAUTAS\"\n  STR_COELACANTH_GAS_CANNON_UFOPEDIA: \"Los SAS automáticos tienen mucha maniobrabilidad y un casco resistente. Son un fuerte apoyo para las tropas a cualquier profundidad. Si tienes suficiente munición se recargan automáticamente.\"\n  STR_COELACANTH_AQUA_JET_UFOPEDIA: \"Este sumergible va armado con Torpedos Aquajet. Es una unidad mejor que el cañón de gas. Asegúrate de que los almacenes están bien surtidos de estos torpedos.\"\n  STR_COELACANTH_GAUSS_UFOPEDIA: \"La tecnología Gauss proporciona un poderoso sistema de armamento para los sistemas de armas sumergibles (SAS). Mayor potencia de fuego que los primeros modelos y tecnología propia de X-Com.\"\n  STR_DISPLACER_SONIC_UFOPEDIA: \"La tecnología alienígena ha rediseñado los SAS. Ahora emplean Desplazadores de Iones, así que su uso ya no se restringe al fondo marino y la tierra firme. El armamento sónico supone una gran ventaja en el combate.\"\n  STR_DISPLACER_PWT_UFOPEDIA: \"Este tanque sumergible lleva armas acuáticas de Ondas de Impulsos. Para mantenerlas cargadas debes fabricar Torpedos de Ondas de Impulsos (TOI). Para disparar marca en el mapa varias coordenadas del rumbo que han de seguir y pulsa el icono de lanzamiento.\"\n  STR_ALIEN_PROBE_MISSION: \"Alienígena de Exploración\"\n  STR_ALIEN_INTERDICTION: \"Interdicción Alienígena\"\n  STR_ALIEN_RESOURCE_RAID: \"Asalto Alienígena\"\n  STR_ALIEN_INFILTRATION: \"Infiltración Alienígena\"\n  STR_ALIEN_BASE: \"Expansión de las Colonias Alien.\"\n  STR_ALIEN_SURFACE_ATTACK: \"Ataques Alien. de Superficie\"\n  STR_ALIEN_RETALIATION: \"Ataque a Base Flotante\"\n  STR_ALIEN_SUPPLY: \"Misiones de Suministro a Colonias\"\n  STR_ALIEN_PROBE_MISSION_UFOPEDIA: \"La misión de exploración alienígena se usa para comparar datos sobre el lecho marino, los recursos y las rutas de navegación y vuelo de una zona. Los submarinos que participan en estas misiones no son una gran amenaza, pero indican focos de actividad que pueden estallar en cualquier momento.\"\n  STR_ALIEN_INTERDICTION_UFOPEDIA: \"Los alienígenas siempre patrullan las zonas que les interesan enviando naves con el propósito de asegurar la zona antes de comenzar misiones más en profundidad. Si quieren atacar un lugar, desembarcarán en él para asegurarlo y preparar el camino para la siguiente fase.\"\n  STR_ALIEN_RESOURCE_RAID_UFOPEDIA: \"La clave estratégica alienígena está en hundir naves y abatir aviones.Una de sus actividades primordiales es adquirir materiales y de ahí sus acciones abiertamente agresivas. También atacan zonas de actividad geotérmica, zonas mineras lugares con tradición de ser ricos en minerales, en metales preciosos y en objetos fabricados por el hombre.\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"Esto puede acabar en un contacto oficial al más alto nivel entre alienígenas y las corporaciones o gobiernos.El clímax de esta situación es una actividad intensa en aguas de la organización interesada. Los alienígenas intentarán firmar un acuerdo con un gobierno u organización ofreciéndoles su avanzada tecnología. Esta actividad alienígena supone una gran amenaza para X-Com. Si una corporación o gobierno coopera con los invasores, cesará su financiación a X-Com.\"\n  STR_ALIEN_BASE_UFOPEDIA: \"Los alienígenas construirán colonias submarinas secretas en zonas remotas. Tras ciertos vuelos iniciales de reconocimiento, comenzará una actividad intensa de submarinos mientras construyen una colonia. En ellas hay laboratorios,centros de clonación y quirófanos para experimentos humanos y alienígenas. Estas colonias generarán más presencia alienígena sin la presencia de sus submarinos. Para localizar una colonia, un submarino de X-Com debe patrullar por una zona  durante una serie de horas si quiere tener alguna posibilidad de éxito.\"\n  STR_ALIEN_SURFACE_ATTACK_UFOPEDIA: \"Cuando los alienígenas necesitan humanos, amenazan un puerto atacan una isla o abordan un nave. Los civiles son amenazados directamente, para cubrir las necesidades de los alienígenas y sus horribles experimentos.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"Si los Submarinos interceptores de X-Com hunden muchas naves alienígenas, los enemigos podrían tomar represalias. Ello podría acabar en un ataque directo contra las instalaciones de X-Com. Sin embargo, si quieren atacarnos, primero deben encontrar la base X-Com y si se mantiene alejados a los Submarinos enemigos, el peligro de ataque es menor.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"Una vez que una colonia alienígena está construida, comienza a recibir abastecimientos, traídos por una nave especial. Si se detecta a una de éstas cuando va a atracar, es que hay una colonia cerca.\"\n  STR_SURVEY_SHIP_UFOPEDIA: \"Este mini submarino se emplea para misiones de reconocimiento e investigación. Suele preceder a grandes navíos, encabezando una fuerza operativa.\"\n  STR_ESCORT_UFOPEDIA: \"Un buque escolta de tamaño medio que no supone una gran amenaza si va solo. Precede a otros buques de mayor tamaño y preludia gran actividad.\"\n  STR_CRUISER_UFOPEDIA: \"El crucero es un barco multiuso, el sostén de la flota enemiga, y se usa en toda clase de misiones alienígenas: un peligroso adversario.\"\n  STR_HEAVY_CRUISER_UFOPEDIA: \"El crucero pesado es una nave más poderosa que el crucero, con armas mayores y sistemas de propulsión. Se usa para misiones de búsqueda de recursos: recogida de minerales y equipo.\"\n  STR_HUNTER_UFOPEDIA: \"Este buque va equipado con una sala de examen para realizar experimentos y operaciones con humanos. Las víctimas son horriblemente torturadas y se les suele extirpar el cerebro, que es almacenado y estudiado durante el viaje.\"\n  STR_BATTLESHIP_UFOPEDIA: \"El Acorazado es el más agresivo del grupo alienígena. Tiene todos los sistemas y avances tecnológicos para actuar como base de operaciones de cualquier tipo de acto agresivo que los alienígenas quieran cometer. Lleva una amplia gama de armamento.\"\n  STR_DREADNOUGHT_UFOPEDIA: \"El acorazado pesado es un transportador de tropas, equipado con toda la tecnología alienígena y con carga útil. Es un adversario duro y formidable.\"\n  STR_FLEET_SUPPLY_CRUISER_UFOPEDIA: \"El buque de suministros se emplea durante la construcción de colonias alienígenas y para llevar suministros a las ya existentes. Transporta ADN, fetos, nutrientes alienígenas y otros componentes biológicos.\"\n  STR_DISMANTLE: \"Desmantelar\"\n  STR_FACILITY_IN_USE: \"COMPARTIMIENTO ACUÁTICO EN USO\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"¡NO SE PUEDE DESMANTELAR EL COMP. ACUÁTICO!{SMALLLINE}Todos los compartimientos de la base deben ir unidos a la esclusa de aire.\"\n  STR_TRANSFER_ITEMS_TO: \"Transferir articulos a {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"¡NO HAY UNIDAD DE CONFINAMIENTO PARA TRASLADO!{SMALLLINE}\\x02Los alienígenas necesitan una unidad de confinamiento para sobrevivir.\"\n  STR_AMOUNT_AT_DESTINATION: \"EN DESTINO\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"Alienígena muere porque no hay confinamiento alienígena.\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"¡NO HAY ALOJAMIENTO!{SMALLLINE}\\x02La base de destino no tiene suficiente espacio para la tripulación del submarino.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"¡NO HAY SUFICIENTE ESPACIO DE ALMACENAJE!{SMALLLINE}La base de destino no tiene espacio suficiente para almacenar el equipo asignado a el submarino..\"\n  STR_ITEMS_ARRIVING: \"Artículos Trasladados\"\n  STR_DESTINATION_UC: \"DESTINO\"\n  STR_DART_PISTOL: \"Lanzasaetas\"\n  STR_DART_POD: \"Cargador de Saetas\"\n  STR_JET_HARPOON: \"Lanzador de Arpones\"\n  STR_HARPOON_POD: \"Cargador de Arpones\"\n  STR_GAS_CANNON: \"Cañón de Gas\"\n  STR_GC_AP_AMMO: \"Proyectiles PB del CG\"\n  STR_GC_HE_AMMO: \"Proyectiles AE del CG\"\n  STR_GC_P_AMMO: \"Proyectiles de Fósforo del CG\"\n  STR_HYDRO_JET_CANNON: \"Cañón Hidrojet\"\n  STR_HJC_AP_AMMO: \"Munición PB del CH\"\n  STR_HJC_HE_AMMO: \"Munición AE del CH\"\n  STR_HJC_P_AMMO: \"Munición de P del CH\"\n  STR_TORPEDO_LAUNCHER: \"Lanzatorpedos\"\n  STR_SMALL_TORPEDO: \"Torpedo Pequeño\"\n  STR_LARGE_TORPEDO: \"Torpedo Grande\"\n  STR_PHOSPHOROUS_TORPEDO: \"Torpedo de Fósforo\"\n  STR_MAGNA_BLAST_GRENADE: \"Granada de Gran Impacto\"\n  STR_DYE_GRENADE: \"Granada Dye\"\n  STR_PARTICLE_DISTURBANCE_GRENADE: \"Granada de Partículas\"\n  STR_MAGNA_PACK_EXPLOSIVE: \"Explosivo de Gran Impacto\"\n  STR_PARTICLE_DISTURBANCE_SENSOR: \"Sensor de Partículas\"\n  STR_MEDI_KIT: \"Botiquín\"\n  STR_MC_DISRUPTOR: \"Disruptor de Control Molecular\"\n  STR_THERMAL_TAZER: \"Tazer Térmico\"\n  STR_GAUSS_PISTOL: \"Pistola Gauss\"\n  STR_GAUSS_PISTOL_CLIP: \"Cargador de Pistola Gauss\"\n  STR_GAUSS_RIFLE: \"Rifle Gauss\"\n  STR_GAUSS_RIFLE_CLIP: \"Cargador de Rifle Gauss\"\n  STR_HEAVY_GAUSS: \"Cañón Pesado Gauss\"\n  STR_HEAVY_GAUSS_CLIP: \"Cargador de Gauss Pesado\"\n  STR_SONIC_CANNON: \"Cañón Sónico\"\n  STR_CANNON_POWER_CLIP: \"Cargador de Cañón Sónico\"\n  STR_SONIC_BLASTA_RIFLE: \"Rifle de Ráfagas Sónicas\"\n  STR_BLASTA_POWER_CLIP: \"Cargador del Rifle Sónico\"\n  STR_SONIC_PISTOL: \"Pistola Sónica\"\n  STR_PISTOL_POWER_CLIP: \"Cargador de Pistola Sónica\"\n  STR_DISRUPTOR_PULSE_LAUNCHER: \"Lanzaproyectiles de Disrupción\"\n  STR_DISRUPTOR_AMMO: \"Proyectiles Disruptores\"\n  STR_THERMAL_SHOK_LAUNCHER: \"Lanzaproyectiles Impacto Térmico\"\n  STR_THERMAL_SHOK_BOMB: \"Bomba de Impacto Térmico\"\n  STR_SONIC_PULSER: \"Granada Sónica\"\n  STR_ZRBITE: \"Zrbita\"\n  STR_MC_READER: \"Lector de Control Molecular\"\n  STR_VIBRO_BLADE: \"Vibroespada\"\n  STR_THERMIC_LANCE: \"Lanza Térmica\"\n  STR_HEAVY_THERMIC_LANCE: \"Lanza Térmica Pesada\"\n  STR_AQUATOID_CORPSE: \"Cadáver de Aquatoide\"\n  STR_GILLMAN_CORPSE: \"Cadáver de Hombre-Branquia\"\n  STR_LOBSTERMAN_CORPSE: \"Cadáver de Hombre-Langosta\"\n  STR_TASOTH_CORPSE: \"Cadáver de Tasoth\"\n  STR_CALCINITE_CORPSE: \"Cadáver de  Calcinite\"\n  STR_DEEP_ONE_CORPSE: \"Cadáver de Anuroide\"\n  STR_BIODRONE_CORPSE: \"Cadáver de Telecerebro\"\n  STR_TENTACULAT_CORPSE: \"Cadáver de Tentáculat\"\n  STR_TRISCENE_CORPSE: \"Cadáver de Triscene\"\n  STR_HALLUCINOID_CORPSE: \"Cadáver de Alucinoide\"\n  STR_XARQUID_CORPSE: \"Cadáver de Calaxmar\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"Insuficiente munición para armar SAS{SMALLLINE}Cada SAS requiere {0} {1}.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Insuficiente armamento para re-equipar pelotón \"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Tiene que investigar {NEWLINE}{0}{NEWLINE}para producir{NEWLINE}{1}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"Los Alienígenas han destruido la base indefensa {0}\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"Agentes X-Com han localizado una colonia Alienígena en {0}\"\n  STR_STANDOFF: \"RETIRARSE\"\n  STR_CAUTIOUS_ATTACK: \"ATAQUE CAUTELOSO\"\n  STR_STANDARD_ATTACK: \"ATAQUE NORMAL\"\n  STR_AGGRESSIVE_ATTACK: \"ATAQUE AGRESIVO\"\n  STR_DISENGAGING: \"ABANDONAR COMBATE\"\n  STR_UFO_HIT: \"¡SUBMARINO ALIENíGENA TOCADO!\"\n  STR_UFO_CRASH_LANDS: \"¡SUBM. ALIENíGENA DERRIBADO!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Minimizar sólo cuando esta retirado.\"\n  STR_UFO_RETURN_FIRE: \"SUBM. ALIEN. DEVUELVE EL FUEGO\"\n  STR_INTERCEPTOR_DAMAGED: \">>> SUBMARINO VOLANTE DAÑADO<<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> SUBMARINO VOLANTE DESTRUIDO<<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"¡SUBM. ALIENíGENA ESCAPA!\"\n  STR_LONG_RANGE_DETECTION: \"Detección en Banda Amplia\"\n  STR_STORES_UC: \"ALMACENES\"\n  STR_DIFFICULTY_LEVEL: \"DIFICULTAD\"\n  STR_INTERCEPT: \"INTERCEPTAR\"\n  STR_BASES: \"BASES\"\n  STR_GRAPHS: \"ESTADÍSTICAS\"\n  STR_UFOPAEDIA_UC: \"OSNIPEDIA\"\n  STR_OPTIONS_UC: \"OPCIONES\"\n  STR_FUNDING_UC: \"FINANZAS\"\n  STR_5_SECONDS: \"5 seg \"\n  STR_1_MINUTE: \"1 min \"\n  STR_5_MINUTES: \"5 min \"\n  STR_30_MINUTES: \"30 min \"\n  STR_1_HOUR: \"1 hora\"\n  STR_1_DAY: \"1 día\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"Lista de Rendimiento de X-Com\"\n  STR_ENTER_NAME: \"Escriba el Nombre\"\n  STR_PERFORMANCE_RATING: \"Evaluación de Rendimiento\"\n  STR_VICTORY_DATE: \"Fecha de Victoria\"\n  STR_CHEMICAL_FLARE: \"Bengala Química\"\n  STR_CHEMICAL_FLARE_UFOPEDIA: \"Este artefacto produce una señal luminosa brillante a cualquier profundidad o en tierra firme. Ilumina las unidades enemigas que haya cerca  en misiones submarinas o nocturnas.\"\n  STR_MONTHLY_COSTS: \"Gastos Mensuales\"\n  STR_CRAFT_RENTAL: \"Alquiler de Submarino Volante\"\n  STR_SALARIES: \"Salarios\"\n  STR_BASE_MAINTENANCE: \"Mantenimiento de bases\"\n  STR_COST_PER_UNIT: \"Costo\"\n  STR_QUANTITY: \"Cantidad\"\n  STR_TOTAL: \"Total\"\n  STR_IN_PSIONIC_TRAINING: \"En implante por CM\"\n  STR_FRONT_ARMOR: \"Blindaje Frontal\"\n  STR_LEFT_ARMOR: \"Blindaje Izquierdo\"\n  STR_RIGHT_ARMOR: \"Blindaje Derecho\"\n  STR_REAR_ARMOR: \"Blindaje Trasero\"\n  STR_UNDER_ARMOR: \"Blindaje Inferior\"\n  STR_ROUNDS: \"DISPAROS\"\n  STR_UNIT: \"UNIDAD> {0}\"\n  STR_ENERGY: \"ENERGÍA\"\n  STR_MORALE: \"MORAL\"\n  STR_ARMOR_: \"ARMADURA> {0}\"\n  STR_FRONT_ARMOR_UC: \"BLINDAJE FRONTAL\"\n  STR_LEFT_ARMOR_UC: \"BLINDAJE IZQUIERDO\"\n  STR_RIGHT_ARMOR_UC: \"BLINDAJE DERECHO\"\n  STR_REAR_ARMOR_UC: \"BLINDAJE TRASERO\"\n  STR_SKILLS: \"HABILIDADES> {0}\"\n  STR_LEVEL: \"NIVEL> {0}\"\n  STR_HEAD: \"CABEZA\"\n  STR_TORSO: \"TORSO\"\n  STR_RIGHT_ARM: \"BRAZO DCHO.\"\n  STR_LEFT_ARM: \"BRAZO IZQ.\"\n  STR_RIGHT_LEG: \"PIERNA DCHA.\"\n  STR_LEFT_LEG: \"PIERNA IZQ.\"\n  STR_PAIN_KILLER: \"ANALGÉSICO\"\n  STR_STIMULANT: \"ESTIMULANTE\"\n  STR_HEAL: \"CURAR\"\n  STR_TIME_UNITS_SHORT: \"UT>{ALT}{0}\"\n  STR_WEIGHT: \"Peso>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"Reacción>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"Abilidad Psí.>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"Fuerza Psí.>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Artefacto Alienígena\"\n  STR_AMMO_ROUNDS_LEFT: \"MUNICIÓN:{NEWLINE}RESTANTE={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Analgésico>{ALT}{0}{ALT}{NEWLINE}Estimulante>{ALT}{1}{ALT}{NEWLINE}Curar>{ALT}{2}\"\n  STR_THROW: \"Lanzar\"\n  STR_AUTO_SHOT: \"Ráfaga\"\n  STR_SNAP_SHOT: \"Simple\"\n  STR_AIMED_SHOT: \"Precisión\"\n  STR_STUN: \"Aturdir\"\n  STR_PRIME_GRENADE: \"Activar Granada\"\n  STR_USE_SCANNER: \"Usar Sensor de Part.\"\n  STR_USE_MEDI_KIT: \"Utilizar Botiquín\"\n  STR_LAUNCH_MISSILE: \"Lanzar Torpedo\"\n  STR_ACCURACY_SHORT: \"Punteria>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"¡Unidades de Tiempo Insuficientes!\"\n  STR_NOT_ENOUGH_ENERGY: \"¡Energía Insuficiente!\"\n  STR_NO_ROUNDS_LEFT: \"¡No queda Munición!\"\n  STR_NO_AMMUNITION_LOADED: \"¡El arma no está cargada!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"¡Munición incorrecta para esta arma!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"¡El arma ya está cargada!\"\n  STR_NO_LINE_OF_FIRE: \"¡No hay línea de tiro!\"\n  STR_GRENADE_IS_ACTIVATED: \"¡La granada está activada!\"\n  STR_GRENADE_IS_DEACTIVATED: \"¡La granada está desactivada!\"\n  STR_THERE_IS_NO_ONE_THERE: \"¡Allí no hay nadie!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"¡Incapaz de ulilizar artefacto hasta después de ser estudiado!\"\n  STR_OUT_OF_RANGE: \"¡Fuera de Alcance!\"\n  STR_UNABLE_TO_THROW_HERE: \"¡Imposible lanzar aquí!\"\n  STR_SET_TIMER: \"Ajustar Temporizador\"\n  STR_HIDDEN_MOVEMENT: \"MOVIMIENTO OCULTO\"\n  STR_TURN: \"TURNO> {0}\"\n  STR_SIDE: \"BANDO> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Presione un botón para continuar\"\n  STR_MIND_CONTROL: \"Controlar Implante\"\n  STR_PANIC_UNIT: \"Interferir Implante\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Ataque Moral Exitoso\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Control de Implante Exitoso\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}ha entrado en Cólera\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}ha entrado en Cólera\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}es presa del Pánico\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}es presa del Pánico\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Alienígenas\"\n  STR_RIGHT_HAND: \"MANO DCHA.\"\n  STR_LEFT_HAND: \"MANO IZQ.\"\n  STR_RIGHT_SHOULDER: \"HOMBRO DCHO.\"\n  STR_LEFT_SHOULDER: \"HOMBRO IZQ.\"\n  STR_BACK_PACK: \"MOCHILA\"\n  STR_BELT: \"CINTURÓN\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}esta bajo Control Molecular\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}esta bajo Control Molecular\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}se ha desmayado\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}ha caído inconsciente\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}ha muerto de una herida mortal\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}ha muerto de una herida fatal\"\n  STR_USE_MIND_PROBE: \"Usar Lector de C.M.\"\n  STR_FATAL_WOUNDS: \"HERIDAS MORTALES\"\n  STR_UNDER_ARMOR_UC: \"PROTECCIÓN INFERIOR\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"UT reservadas para Disparo Simple\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"UT reservadas para Ráfagas\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"UT reservadas para Disparo de Precisión\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"UTs reservadas para Arrodillarse\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"UTs reservadas para Arrodillarse y Disparar\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} Unidad en Nave X-Com\"\n    many: \"{N} Unidades en Nave X-Com\"\n    other: \"{N} Unidades en Nave X-Com\"\n  STR_UNITS_OUTSIDE:\n    one: \"{N} Unidad dejada fuera\"\n    many: \"{N} Unidades dejadas fuera\"\n    other: \"{N} Unidades dejadas fuera\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} Unidad en la Entrada\"\n    many: \"{N} Unidades en la Entrada\"\n    other: \"{N} Unidades en la Entrada\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} Unidad en la Meta de Salida \"\n    many: \"{N} Unidades en la Meta de Salida \"\n    other: \"{N} Unidades en la Meta de Salida \"\n  STR_ABORT_MISSION_QUESTION: \"¿Cancelar la Misión?\"\n  STR_CORPSE: \"Cadáver\"\n  STR_UNLOAD_CRAFT: \"Descargar\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}ha muerto\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}ha muerto\"\n  STR_HIT_MELEE: \"Impacto\"\n  STR_GROUND: \"SUELO\"\n  STR_LIVING_QUARTERS_PLURAL: \"Viviendas\"\n  STR_LIST_ITEM: \"ARTÍCULO\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"Todos los alianigenas han muerto{NEWLINE} Recuperación automática iniciada\"\n  STR_RESET: \"Reiniciar\"\n  STR_MEMORIAL: \"Conmemoración\"\n  STR_DATE_UC: \"FECHA\"\n  STR_SOLDIERS_RECRUITED_UC: \"AQUANAUTAS RECLUTADOS>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"BAJAS>{ALT}{0}\"\n  STR_REMOVE_SELECTED: \"Eliminar Elejidos\"\n  STR_LIVE_ALIENS: \"Especímenes{NEWLINE}Vivos\"\n  STR_DEAD_ALIENS: \"Especímenes{NEWLINE}Rechazados\"\n  STR_UNDER_INTERROGATION: \"Siendo{NEWLINE}Estudiados\"\n  STR_CONTAINMENT_EXCEEDED: \"¡LÍMITE DE CONFINAMIENTO ALIENÍGENAS EXCEDIDO!{SMALLLINE} El espacio en la sala de confinamiento es insuficiente en {0}. Debe eliminar el exceso de alienígenas (¿quien morirá entonces?).\"\n  STR_MANAGE_CONTAINMENT: \"Administrar Confinamiento Alienígena\"\n  STR_STORAGE_EXCEEDED: \"¡ESPACIO DE ALMACENAMIENTO SUPERADO!{SMALLLINE}Espacio de almacenamiento insuficiente en {0}. Debe vender artículos excedentes.\"\n  STR_GO_TO_BASE: \"Ir a la Base\"\n  STR_MELEE_ACCURACY: \"PRECISIÓN CUERPO A CUERPO\"\n  STR_SELL_PRODUCTION: \"VENDER\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"¡Ambas manos deben estar vacías!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"¡Elementos insuficientes para copiar la plantilla!\"\n  STR_UNLOAD_WEAPON: \"Descargar Arma\"\n  STR_ALL_ITEMS: \"Todos los Items\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"¡NO MÁS EQUIPO PERMITIDO A BORDO!{SMALLLINE}solamente se le permite tomar un máximo de {N} elemento del equipo en este Submarino.\"\n    many: \"¡NO MÁS EQUIPO PERMITIDO A BORDO!{SMALLLINE}solamente se le permite tomar un máximo de {N} elementos del equipo en este Submarino.\"\n    other: \"¡NO MÁS EQUIPO PERMITIDO A BORDO!{SMALLLINE}solamente se le permite tomar un máximo de {N} elementos del equipo en este Submarino.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}CENTRO DE CONTROL DESTRUIDO{NEWLINE}Diríjase a la entrada y aborte.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"Las instalaciones acuáticas X-Com no se pueden construir en tierra firme\"\n  STR_UNABLE_TO_ENGAGE_DEPTH: \"IMPOSIBLE ALCANZAR ENEMIGO{NEWLINE}A ESTA PROFUNDIDAD\"\n  STR_UNABLE_TO_ENGAGE_AIRBORNE: \"IMPOSIBLE ALCANZAR ENEMIGO{NEWLINE}DURANTE VUELO\"\n  STR_UNDERWATER_EQUIPMENT: \"¡Este equipo no funcionará fuera del agua!\"\n  STR_LAND_EQUIPMENT: \"Este equipo no funcionara bajo el agua!\"\n  STR_LEVEL_SHORT: \"L{0}\"\n  STR_PERSONNEL: \"Personal\"\n  STR_CRAFT_ARMAMENT: \"Nave y Armamento\"\n  STR_COMPONENTS: \"Componentes\"\n  STR_SOLDIERS_RECRUITED: \"Aquanautas reclutados\"\n  STR_SOLDIERS_LOST: \"Bajas\"\n  STR_TOTAL_UFOS: \"OSNIs detectados\"\n  STR_TOTAL_ALIEN_BASES: \"Colonias Alienígenas descubiertas\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"FCM\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"MCM\"\n  FEMALE_CIVILIAN: \"Civil, Femenino\"\n  MALE_CIVILIAN: \"Civil, Masculino\"\n  DOCKER_CIVILIAN: \"Civil, Estibador\"\n  SAILOR_CIVILIAN: \"Civil, Marinero\"\n  STR_BIODRONE_MELEE_WEAPON: \"Arma Telecerebro\"\n  HALLUCINOID_WEAPON: \"Arma Alucinoide\"\n  STR_LOBSTERMAN_MELEE_WEAPON: \"Arma Hombre-Langosta\"\n  CALCINITE_WEAPON: \"Arma Calcinite\"\n  DEEP_ONE_WEAPON: \"Arma Anuroide\"\n  STR_TRISCENE_MELEE_WEAPON: \"Arma Triscene\"\n  STR_TRIBIO_SONIC_WEAPON: \"Arma Sónica Alien\"\n  XARQUID_WEAPON: \"Arma Calaxmar\"\n  TENTACULAT_WEAPON: \"Arma Tentáculat\"\n  ZOMBIE_WEAPON: \"Arma Zombi \"\n  ALIEN_PSI_WEAPON: \"Arma C.M. Alien\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/es-ES.yml",
    "content": "es-ES:\n  STR_LEVIATHAN_UFOPEDIA: \"AEROSUBMARINO DEL TIPO CAZA-TRANSPORTE, CAPAZ DE ALCANZAR UNA PROFUNDIDAD ASOMBROSA. UNA SÍNTESIS FABULOSA DE TECNOLOGÍA HUMANA Y ALIENÍGENA CONSISTENTE EN SISTEMAS DE PROPULSIÓN IÓNICA Y NAVEGACIÓN CON RED MAGNÉTICA\"\n  STR_BARRACUDA_UFOPEDIA: \"LA NAVE SUBMARINA BRITÁNICA BARRACUDA, IMPULSADA POR MOTORES LÁSER SUPER CALENTADOS, PUEDE SUMERGIRSE Y VOLAR, UNA DE LAS NAVES CAZA MÁS VELOCES DEL MUNDO Y PIEZA CLAVE PARA LA BATALLA CONTRA LOS OSNI U OBJETO SUMERGIBLE NO IDENTIFICADO.\"\n  STR_HAMMERHEAD_UFOPEDIA: \"UNA NAVE DE CAZA-TRANSPORTE. COPIA LOS SISTEMAS DE RED MAGNÉTICA EN UNA NAVE X-COM. AUNQUE PEQUEÑA, SU DISEÑO ES UN LOGRO TÉCNICO ASOMBROSO.\"\n  STR_TRITON_UFOPEDIA: \"EL TRITÓN, UN TRANSPORTE DE ESCUADRÓN DE ASALTO MAR-AIRE, ESTÁ EQUIPADO CON MOTORES ACUÁTICOS Y ATMOSFÉRICOS. SU GRAN CAPACIDAD Y RESISTENTE CONSTRUCCIÓN LO HACE UN PILAR DE LA FLOTA X-COM.\"\n  STR_MANTA_UFOPEDIA: \"UN AEROSUBMARINO DE ALTA VELOCIDAD  CAZA MONO-PLAZA, PARECIDO A LAS NAVES ALIENÍGENAS MOVIDAS POR IONES. MUY EFICAZ EN EL CONFLICTO QUE SE AGRAVA.\"\n  STR_AJAX_UFOPEDIA: \"EL TORPEDO AJAX ES EL ARMA ESTÁNDAR DE COMBATE SUBMARINO. ALREDEDOR DEL MUNDO. SE USA COMO ARMA DISUASIVA, ES POTENTE Y PRECISO.\"\n  STR_DUP_HEAD_UFOPEDIA: \"LA TECNOLOGíA DE ARMAS CON CABEZA DE URANIO REBAJADO C.U.R ES RELATIVAMENTE NUEVA, Y ÉSTA ES LA PRIMERA ARMA ACUÁTICA COMERCIAL QUE LA EMPLEA.\"\n  STR_CRAFT_GAS_CANNON_UFOPEDIA: \"UN CAÑÓN DE GAS COMPRIMIDO QUE DISPARA PROYECTILES SÓLIDOS CAPACES DE PERFORAR BLINDAJES.\"\n  STR_PWT_CANNON_UFOPEDIA: \"EL TORPEDO DE ONDAS DE IMPULSOS T.O.I UTILIZA UN SISTEMA DE COMBUSTIBLE SOBRE-CALENTADO Y UNA CABEZA SUMAMENTE DENSA QUE PUEDE PERFORAR LA MAYORÍA DE LAS ALEACIONES.\"\n  STR_GAUSS_CANNON_UFOPEDIA: \"EL CAÑÓN GAUSS ES UNA TECNOLOGÍA X-COM RECIENTEMENTE DESARROLLADA. EL ACELERADOR DE PARTÍCULAS DE ESTE SISTEMA SE ALIMENTA CON UN COMPACTO REACTOR DE FUSIÓN ENFRIADO CON NITRÓGENO LÍQUIDO.\"\n  STR_SONIC_OSCILLATOR_UFOPEDIA: \"UN POTENTE OSCILADOR ACUSTICO CREA ONDAS DE FUERZA SÓNICA QUE DESTRUYEN EL BLANCO AL ROMPER SUS ENLACES MOLECULARES CON LAS VIBRACIONES.\"\n  STR_AQUATOID_UFOPEDIA: \"La raza Aquatoide forma una sociedad ancestral que ya existía antes de que el hombre diera sus primeros pasos sobre la Tierra. Su aspecto compacto y sus rasgos bulbosos suponen una retroceso con respecto a sus hermanos los sectoides, que también viajan por el espacio. Su poder se basa en la tecnología del control molecular. Los aquatoides quieren propagar su raza estéril por medio de la codificación genética y, para ello, experimentan con seres humanos, dando origen a numerosas razas híbridas.\"\n  STR_AQUATOID_AUTOPSY: \"Autopsia de Aquatoide\"\n  STR_AQUATOID_AUTOPSY_UFOPEDIA: \"Un examen detallado de esta criatura nos permite llegar a unas suposiciones básicas. Es un sectoide, nuestro antiguo enemigo, pero ha sido modificado por métodos quirúrgicos e implantes y ahora es una criatura acuática. Tiene pulmones vestigiales que le permiten respirar y moverse por tierra, e implantes cibernéticos que aumentan la fuerza de sus miembros atrofiados y mejoran el funcionamiento de sus órganos. Dado que todos los miembros de esta raza son idénticos, suponemos que son clones.\"\n  STR_GILLMAN_UFOPEDIA: \"Una extraña criatura medio humana medio reptil, estrechamente relacionada con el hombre y extraordinariamente fuerte y rápida bajo el agua. Los hombres-branquia son una raza plenamente desarrollada, con hembras y machos de distintas edades. Se diferencian de la mayor¡a de los alienígenas submarinos en que no presentan ningún signo de alteración genética ni de deformación quirúrgica. Puede que estemos ante un grupo arcaico de nuestra propia especie.\"\n  STR_GILLMAN_AUTOPSY: \"Autopsia de Hombre-Branquia\"\n  STR_GILLMAN_AUTOPSY_UFOPEDIA: \"Una vez iniciada la intervención quirúrgica, se vio claro que no era un alienígena, sino una criatura de la Tierra, una raza prehistórica que se creía desaparecida desde que los mamíferos predominaron en este planeta. Los hombres-branquia, inteligentes y fuertes, vivieron en el tiempo de los dinosaurios. El cataclismo que acabó con el predominio de los reptiles obligó a estas criaturas a establecer una relación simbiótica con los alienígenas recién llegados. Tienen un dispositivo electrónico en el cráneo.\"\n  STR_LOBSTERMAN_UFOPEDIA: \"Esta es una criatura asombrosa, más alta que un hombre y tiene seis pulmones. A lo único que se parece es a un demonio acuático. El parecido entre esta criatura y la langosta terrestre le ganó el apodo Hombre-Langosta por las tropas X-Com. Esto es un monstruo de las profundidades. Una criatura de increíble fuerza diseñada cuidadosamente para luchar, y prácticamente invulnerable al fuego de proyectiles. Sus tenazas son suficientes para triturar acero.\"\n  STR_LOBSTERMAN_AUTOPSY: \"Autopsia de Hombre-Langosta\"\n  STR_LOBSTERMAN_AUTOPSY_UFOPEDIA: \"Bajo un caparazón prácticamente indestructible hay una criatura de construcción asombrosa: un esqueleto de titanio cubierto de músculos poderosos y un sofisticado sistema de blancos con un dispositivo de exploración multi-banda implantado en el cerebro. Sus múltiples ojos están protegidos con un plástico duro como el acero y cuando sus amos las despliegan estratégica mente, estas criaturas son imparables. Llevan unos dispositivos de construcción y función desconocidas. ¡¡¡NO SE COCINAN!!!\"\n  STR_TASOTH_UFOPEDIA: \"Estos enemigos agiles y veloces son un elemento esencial del ejército enemigo. En el corazón de las colonias alienígenas nacen cientos de ellos, criados en cubas enormes. Los Tasoth son verdaderos alienígenas, carnívoros y mucho más fuertes que los hombres. A menudo se sitúan en la vanguardia durante los ataques enemigos y nunca parecen amedrentarse, incluso cuando llevan claramente las de perder.\"\n  STR_TASOTH_AUTOPSY: \"Autopsia de Tasoth\"\n  STR_TASOTH_AUTOPSY_UFOPEDIA: \"La disección reveló un organismo cibernético dotado de una extraña energía. En el interior lleva una pequeña unidad energética, pero no se puede identificar ningún órgano. Un sistema de transmisión bioeléctrico reparte la energía por el cuerpo. No hay huesos ni ninguna otra estructura de sostén. Al morir, la energía se detiene y la criatura se convierte en un muñeco de carne y fluidos alienígenas retumbantes. Un par de células de cerámica reviven brevemente a la criatura si reciben energía.\"\n  STR_DEEP_ONE_UFOPEDIA: \"El Anuroide es una pesadilla biológica, un mestizaje resultado de los experimentos cerebrales de los aquatoides. Hemos visto algunas variaciones de esta criatura. Tras una costosa investigación hemos concluido que los fabrican los invasores, quienes aumentan su producción cada vez que capturan carne humana fresca. Cada uno de estos sub-humanos es capaz de soltar una descarga de energía eléctrica suficiente para matar a un aquanauta.\"\n  STR_DEEP_ONE_AUTOPSY: \"Autopsia de Anuroide\"\n  STR_DEEP_ONE_AUTOPSY_UFOPEDIA: \"Esta criatura es el resultado de injertos humanos y alienígenas. El cerebro humano ha sido alterado para ubicar dispositivos electrónicos de control y la corteza cerebral de un alienígena. La única característica humana son los ojos. Según parece, el feto alienígena va consumiendo a su anfitrión humano a medida que crece. Su resistente piel parece ser una mezcla metálica e inorgánica muy dura y flexible. El resultado es un híbrido fuerte y veloz que está  bajo el control total de los alienígenas.\"\n  STR_BIODRONE_UFOPEDIA: \"El Telecerebro es una creación que solo una mente alienígena podría concebir. Es un cerebro (humano o extraterrestre) suspendido en fluidos amnióticos y conectado a una unidad de alimentación energética que le permite volar en tierra o bajo el agua. Cada Telecerebro está armado con un poderoso disruptor sónico, parte mecánico y parte biológico. Algunos de nuestros científicos han sugerido que el arma es impulsada por las cuerdas vocales originales del organismo huésped. Altamente precisos y tenaces, estos super perros guardianes son ampliamente utilizados por los extraterrestres para proteger activos valiosos.\"\n  STR_BIODRONE_AUTOPSY: \"Autopsia de Telecerebro\"\n  STR_BIODRONE_AUTOPSY_UFOPEDIA: \"La hipótesis de que el disruptor sónico es biológico es cierta. Esta criatura mata a sus enemigos gritando. Tienen grandes cicatrices y graves mutilaciones. Los alienígenas hacen una carnicería con el cerebro hasta conseguir que les obedezca. La mayor parte de las cortezas cerebrales usadas son de origen alienígena, pero nada se puede comparar al horror de hallar una criatura basada en un humano. Los Telecerebros se mueven gracias a un motor Iónico y llevan un sistema de control remoto.\"\n  STR_TENTACULAT_UFOPEDIA: \"Ni siquiera de una pesadilla de Lovecraft podrían salir criaturas indescriptibles como esta. No se puede comparar con ningún animal de la Tierra, el entorno en el que pueda haber surgido es inimaginable. Armado con largos tentáculos, el Tentáculat paraliza a sus víctimas y luego las transforma en objetos sin cerebro. Esta especie puede matar con sólo tocar, incluso a través de un blindaje. El tentáculat es el alienígena más temible de los que X-Com se ha encontrado hasta ahora.\"\n  STR_TENTACULAT_AUTOPSY: \"Autopsia de Tentáculat\"\n  STR_TENTACULAT_AUTOPSY_UFOPEDIA: \"La autopsia revela pequeños implantes cibernéticos en el gran cerebro de la criatura. Su sistema visual es una compleja combinación de percepción de imágenes luminosas y térmicas. Este monstruo puede moverse con un rumbo exacto incluso en las tenebrosas profundidades del océano. Tiene algunos órganos vestigiales que parecen ser los mínimos que necesita para sobrevivir. Cada criatura tiene un pequeño estómago con un conector externo, por lo que creemos que las alimentan sus amos.\"\n  STR_CALCINITE_UFOPEDIA: \"Estas criaturas similares a los trajes de buceadores perdidos acechan a los distraídos en el fondo del mar. Les basta dar un golpe con sus pinzas más fuertes que el acero para mandar al fondo al mejor de los buceadores. Sólo se ve una forma gelatinosa y verde girando alrededor de la mascarilla. No hemos podido adivinar nada sobre su verdadera naturaleza en ninguno de nuestros encuentros, a menudo letales, con ellas.\"\n  STR_CALCINITE_AUTOPSY: \"Autopsia de Calcinite\"\n  STR_CALCINITE_AUTOPSY_UFOPEDIA: \"Una vez desprovisto del traje blindado, el Calcinite es una masa amorfa de protoplasma sin cerebro, extremidades u órganos sensores visibles. En el interior del cuerpo líquido hay un pequeño elemento metálico. Una vez muerta, sólo podemos hacer conjeturas sobre la naturaleza de esta criatura. Es un enigma de los alienígenas.\"\n  STR_TRISCENE_UFOPEDIA: \"Este reptil bípedo es un retroceso a la edad de los dinosaurios. Todo, excepto su habilidad para vivir en el agua y fuera de ella, indica que es una criatura del Cretáceo. Estas criaturas llevan compartimientos de armas y tienen una mandíbula con enormes dientes de acero. A menudo, estos monstruos se colocan en el centro de las fuerzas de ataque alienígenas cuando estas lanzan un ataque terrestre. Constituyen un arma potente y pesada que los Tasoth de alto rango despliegan con una eficacia mortal.\"\n  STR_TRISCENE_AUTOPSY: \"Autopsia de Triscene\"\n  STR_TRISCENE_AUTOPSY_UFOPEDIA: \"Una vez sometidos al bisturí del científico, el Triscene resulta ser una criatura prehistórica modificada con implantes cibernéticos y sistemas de armas. Su diminuto cerebro ha sido completado con un pequeño ordenador acoplado al arnés de control que llevan todas las criaturas. Una piel natural resistente y un instinto depredador mejorado con armas hacen de él un oponente mortal en cualquier ambiente.\"\n  STR_HALLUCINOID_UFOPEDIA: \"Tras explotar los océanos, los alienígenas han criado esta enorme criatura terrestre y la utilizan como arma. No te dejes engañar por el falso aspecto inofensivo de estos marineros de las profundidades. El Alucinoide es un enemigo mortal que ataca de lejos con explosiones congeladoras y de cerca con golpes cortantes como el hielo.\"\n  STR_HALLUCINOID_AUTOPSY: \"Autopsia de Alucinoide\"\n  STR_HALLUCINOID_AUTOPSY_UFOPEDIA: \"En las muchas capas del cuerpo gelatinoso de este organismo hay un congelador químico potente, su principal medio de ataque. La piel suave y flexible del alucinoide indica que es vulnerable a ataques basados en el calor. Es frecuente ver a este mutante en compañía de sus amos, los Aquatoides.\"\n  STR_XARQUID_UFOPEDIA: \"El Calaxmar es otro invertebrado terrestre modificado, una criatura bella y peligrosa. Este nadador rápido y gigantesco oculta un arsenal de armas devastador, un chorro de tinta sofocante y un rayo de partículas ionizadas. Desde nuestros primeros encuentros con esta poderosa criatura hemos desconfiado de sus habilidades y de sus controladores, los vengativos Hombres-Branquia.\"\n  STR_XARQUID_AUTOPSY: \"Autopsia de Calaxmar\"\n  STR_XARQUID_AUTOPSY_UFOPEDIA: \"Este enorme cefalópodo ha llegado a este tamaño con una dieta de drogas alienígenas y alteraciones quirúrgicas. Los Hombres-Branquia, pervertidos hasta lo inimaginable, han implantado sistemas mecánicos de control en la criatura y ahora no queda ni uno de sus rasgos originales. Su resistente concha y su movilidad hacen que el Calaxmar sea un oponente formidable, empleado como plataforma orgánica para armas.\"\n  STR_ION_BEAM_ACCELERATORS_UFOPEDIA: \"Los OSNI dependen de sistemas de energía complejos para llevarlos a una velocidad increíble a través de las profundidades. La base de su tecnología es el ACELERADOR DE RAYOS DE IONES, utilizando Zrbita como catalizador, los motores desplazan 100 veces su propio volumen en agua por segundo. Este enorme poder significa que los alienígenas son capaces de superar a la mayoría de los submarinos de la Tierra. Podemos replicar este sistema de propulsión usando Aquaplásticos y células de energía Zrbita.\"\n  STR_MAGNETIC_NAVIGATION_UFOPEDIA: \"Estas unidades generan un campo magnético esférico y de varias capas que es proyectado hasta 1 Km alrededor del submarino. Los alienígenas que navegan en el interior se comunican directamente y van palpando el camino a seguir bajo las olas. Un sistema interfaz funciona con la materia cerebral modificada de los alienígenas, que se comunica directamente con la mente del operador por unión neural.\"\n  STR_ALIEN_SUB_CONSTRUCTION_UFOPEDIA: \"La estructura de las naves es como la de un camaleón, imita rasgos de las criaturas marinas y está hecha de aquaplásticos. Cada submarino funciona como un organismo: tripulación y nave en armonía. La mayoría de sus sistemas se pueden reproducir y es posible crear una tecnología híbrida que nos permita llegar a su nivel.\"\n  STR_ALIEN_CRYOGENICS_UFOPEDIA: \"Muchos alienígenas permanecen escondidos en la Tierra en estado inactivo, sometidos a una congelación criogénica. Estas criaturas son encerradas en unidades en las que su temperatura corporal es reducida hasta que sus funciones vitales están a punto de detenerse. El examen de estas unidades ha revelado que los cuerpos han permanecido inactivos por periodos increíbles, algunos más de 60 millones de años.\"\n  STR_ALIEN_CLONING_UFOPEDIA: \"Muchos de los alienígens capturados son idénticos, incluso tienen el mismo ADN. Son copias exactas. Los alienígenas extraen muestras de células de sus bancos de genes y las meten en las unidades criogénicas. Algunas de ellas guardan humanos o partes de su cuerpo. Puede que algunas sirvan para crear híbridos.\"\n  STR_ALIEN_LEARNING_ARRAYS_UFOPEDIA: \"Gracias a los implantes de Control Molecular que hay en los cráneos de todos los alienígenas, estas máquinas inyectan directamente información en sus cerebros. Los alienígenas recién clonados son llevados hasta estas unidades para introducirles recuerdos de su raza e información científica y bélica en sus mentes vacías.\"\n  STR_ALIEN_IMPLANTER_UFOPEDIA: \"Esta máquina sirve para equipar a los alienígenas con implantes de Control Molecular, fertilizar razas reproductoras e insertar o extraer órganos y dispositivos electrónicos de cualquier criatura. Creemos que el paciente está anestesiado pero es consciente del proceso y, por desgracia, la anatomía humana se acopla perfectamente a esta unidad.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"Ya tenemos pruebas que nos permiten saber por qué‚ los alienígenas capturan humanos. No se los comen ni los fertilizan con sus propios embriones, los usan como base de una serie de criaturas y sistemas de control. Su tecnología se basa en una mente única, una inteligencia común, y el cerebro humano es el receptáculo ideal para ello. El tejido del cerebro humano se utiliza en la mayoría de los sistemas informático-biológicos de almacenamiento y extracción de datos, el resto sirve para crear y criar criaturas.\"\n  STR_AQUA_PLASTICS_UFOPEDIA: \"En la mayor parte de la construcción de los submarinos y estructuras alienígenas se utiliza un material increíblemente fuerte y duradero. Los Aquaplásticos son materiales complejos de enlaces múltiples y catalizados con Zrbita. Esta sustancia densa pero ligera es más resistente que el Titanio o el Kevlar.\"\n  STR_ZRBITE_UFOPEDIA: \"Esta es una aleación de origen alienígena, hecha de oro y de bio-material alienígena. Cuando se utiliza como fuente de energía, pequeñas cantidades generan más energía que una unidad nuclear 10 veces más grande. No podemos reproducir este material con nuestra tecnología debido a que la mayoría de sus componentes son alienígenas.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"Los alienígenas atacan por todo el planeta con eficacia despiadada. No conseguimos averiguar dónde está su base, ¨en alguna parte impenetrable del fondo del océano que no podemos localizar? No todos los organismos encontrados son alienígenas, unos son viejísimos, otros son ejemplares evolucionados de especies que creíamos extintas hace mucho. Nos enfrentamos a una amenaza que ha estado aletargada durante milenios, una sutil simbiosis de humano y alienígena. Las antiguas bases desde donde contactan con sus primos de las estrellas están en la profundidad del océano. Cada una de estas doce bases tiene un dispositivo Synonium de alta tecnología alienígena. Ahora que su maquinaria bélica está en marcha, los alienígenas están reactivando estas bases para ampliar su red de Control Molecular, tenemos que destruir esas bases cueste lo que cueste.\"\n  STR_THE_ULTIMATE_THREAT_UFOPEDIA: \"Hace sesenta y cinco millones de años, una gigantesca nave colonizadora fue enviada a la Tierra desde un lejano mundo alienígena. Cuando la enorme nave se acercó al joven planeta, una masiva y violenta erupción solar causó una falla en los sistemas de navegación. Deteriorado y fallando la gran masa cayó en picado a través de la estratosfera para emerger en los cielos del Cretácico. En la Tierra innumerables especies fijaban sus miradas hacia el cielo cuando su némesis se estrelló contra el planeta. Una gran nube de polvo obstruyó la atmósfera y la tierra se enfrió por lo que la vida dominante, los poderosos dinosaurios, perecieron. Pero los 400 mil millones de toneladas de T'leth no se destruyeron en el impacto, sofisticados superordenadores iniciaron un ciclo de sueño criogénico para las criaturas en lo profundo de sus bodegas. A medida que pasaron los eones, los ordenadores despertaron a grupos de alienígenas para intentar comunicarse con sus primos estelares, todo en vano porque el poder Alien dormía.\"\n  STR_TLETH_THE_ALIEN_CITY: \"T'leth la Ciudad Alienígena\"\n  STR_TLETH_THE_ALIEN_CITY_UFOPEDIA: \"La enorme nave-ciudad alienígena T'leth yace en Sigsbee, en el Golfo de México. En el centro de la ciudad hay un horror alienígena, tan malvado y poderoso que ni siquiera la muerte lo reclama. En una cámara de metal alienígena yace dormido el Soñador, el Alienígena Supremo. Cuando T'leth emerja de las aguas, Él iniciará su ciclo de reanimación y una vez despierto nada le detendrá. Aunque no esté vivo, y en cierto modo tampoco muerto, su mente controla el ejército alienígena. La desconocida tecnología del Control Molecular conecta todos los alienígenas a un único cerebro y viceversa. Unos fetos, resultado de la mutación genética de hombre y alienígena, proporcionan energía a ese cerebro y sirven de unión entre él y sus súbditos. El mito del Alienígena Supremo vive desde hace siglos en la memoria y en el corazón de los hombres, pero sólo el mar sabe la verdad.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"CENTRAR EN SITIO-TIEMPO=5 Seg\"\n  STR_CANCEL_UC: \"CANCELAR\"\n  STR_NONE: \"Ninguno\"\n  STR_UNKNOWN: \"Desconocido\"\n  STR_POOR: \"Pobre\"\n  STR_AVERAGE: \"Normal\"\n  STR_GOOD: \"Bueno\"\n  STR_EXCELLENT: \"Excelente\"\n  STR_BUILD_NEW_BASE_UC: \"CONSTRUIR NUEVA BASE\"\n  STR_BASE_INFORMATION: \"INFORMACIÓN DE BASES\"\n  STR_EQUIP_CRAFT: \"EQUIPAR AEROSUBMARINO\"\n  STR_BUILD_FACILITIES: \"CONSTRUIR INSTALACIONES\"\n  STR_RESEARCH: \"INVESTIGAR\"\n  STR_MANUFACTURE: \"FABRICAR\"\n  STR_TRANSFER_UC: \"TRANSFERIR\"\n  STR_PURCHASE_RECRUIT: \"COMPRAR/RECLUTAR\"\n  STR_SACK: \"DESPEDIR\"\n  STR_SELL_SACK_UC: \"VENDER/DESPEDIR\"\n  STR_GEOSCAPE_UC: \"GEOESCAPE\"\n  STR_NAME: \"Nombre\"\n  STR_AREA: \"Zona\"\n  STR_BUILD_NEW_BASE: \"Construir nueva base\"\n  STR_CANCEL: \"Cancelar\"\n  STR_COST_UC: \"COSTE>\"\n  STR_CONSTRUCTION_TIME_UC: \"TIEMPO DE CONSTRUCCIÓN>\"\n  STR_DAY:\n    one: \"{N} día\"\n    many: \"{N} días\"\n    other: \"{N} días\"\n  STR_HOUR:\n    one: \"{N} hora\"\n    many: \"{N} horas\"\n    other: \"{N} horas\"\n  STR_MAINTENANCE_UC: \"MANTENIMIENTO>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Instalación\"\n  STR_CURRENT_RESEARCH: \"INVESTIGACIÓN EN CURSO\"\n  STR_SCIENTISTS_AVAILABLE: \"Científicos disponibles>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Científicos asignados>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Espacio de Laboratorio Disponible>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"PROYECTO DE INVESTIGACIÓN\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"CIENTÍFICOS ASIGNADOS\"\n  STR_PROGRESS: \"PROGRESO\"\n  STR_NEW_PROJECT: \"Nuevo proyecto\"\n  STR_CANCEL_PROJECT: \"CANCELAR PROYECTO\"\n  STR_NEW_RESEARCH_PROJECTS: \"Nuevos proyectos de investigación\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"CIENTIFICOS DISPONIBLES>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"ESPACIO DE LABORATORIO DISPONIBLE>{ALT}{0}\"\n  STR_INCREASE: \"Aumentar\"\n  STR_DECREASE: \"Disminuir\"\n  STR_START_PROJECT: \"INICIAR PROYECTO\"\n  STR_CURRENT_PRODUCTION: \"PRODUCCIÓN ACTUAL\"\n  STR_ENGINEERS_AVAILABLE: \"Ingenieros Disponibles>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Ingenieros Disponibles>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Espacio de Taller Disponible>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Fondos actuales>{ALT}{0}\"\n  STR_ITEM: \"Objeto\"\n  STR_ENGINEERS__ALLOCATED: \"Ingenieros Disponibles\"\n  STR_UNITS_PRODUCED: \"Unidades producidas\"\n  STR_TOTAL_TO_PRODUCE: \"Total a Producir\"\n  STR_COST__PER__UNIT: \"Coste{NEWLINE}por{NEWLINE}unidad\"\n  STR_DAYS_HOURS_LEFT: \"Dias/Horas restantes\"\n  STR_NEW_PRODUCTION: \"Nueva producción\"\n  STR_PRODUCTION_ITEMS: \"Artículos en producción\"\n  STR_CATEGORY: \"CATEGORÍA\"\n  STR_START_PRODUCTION: \"INICIAR FABRICACIÓN\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} Horas/ingeniero para producir una unidad\"\n  STR_COST_PER_UNIT_: \"Coste por unidad>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Espacio de trabajo necesario>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"MATERIALES ESPECIALES NECESARIOS\"\n  STR_ITEM_REQUIRED: \"ELEMENTO REQUERIDO\"\n  STR_UNITS_REQUIRED: \"UNIDADES NECESARIAS\"\n  STR_UNITS_AVAILABLE: \"UNIDADES DISPONIBLES\"\n  STR_STOP_PRODUCTION: \"DETENER PRODUCCIÓN\"\n  STR_ENGINEERS_AVAILABLE_UC: \"INGENIEROS DISPONIBLES>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"ESPACIO DE TALLER DISPONIBLE>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"BENEFICIOS MENSUALES>{ALT}{0}\"\n  STR_INCREASE_UC: \"AUMENTAR\"\n  STR_DECREASE_UC: \"DISMINUIR\"\n  STR_UNITS_TO_PRODUCE: \"Unidades a producir\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Comprar/Contratar personal\"\n  STR_COST_OF_PURCHASES: \"Coste de Compras>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"COSTE POR UNIDAD\"\n  STR_QUANTITY_UC: \"CANTIDAD\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"PERSONAL DISPONIBLE:PERSONAL TOTAL>\"\n  STR_SOLDIERS: \"Aquanautas\"\n  STR_SCIENTISTS: \"Científicos\"\n  STR_ENGINEERS: \"Ingenieros\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"ESPACIO USADO:ESPACIO DISPONIBLE>\"\n  STR_LIVING_QUARTERS: \"Cuarteles\"\n  STR_STORES: \"Almacenes\"\n  STR_LABORATORIES: \"Laboratorios\"\n  STR_WORK_SHOPS: \"Talleres\"\n  STR_HANGARS: \"Aerosubmarino\"\n  STR_SHORT_RANGE_DETECTION: \"Detección de corto alcance\"\n  STR_DEFENSE_STRENGTH: \"Fuerza defensiva\"\n  STR_TRANSFERS_UC: \"TRANSFERENCIAS\"\n  STR_TRANSFERS: \"Transferencias\"\n  STR_ARRIVAL_TIME_HOURS: \"Hora de llegada (horas)\"\n  STR_COST_: \"Coste>{ALT}{0}\"\n  STR_AREA_: \"Area>{ALT}{0}\"\n  STR_BASE_NAME: \"¿Nombre de la base?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"SELECCIONAR POSICIÓN DE LA ESCLUSA DE ACCESO\"\n  STR_TRANSFER: \"Transferir\"\n  STR_AMOUNT_TO_TRANSFER: \"CANTIDAD A TRANSFERIR\"\n  STR_SELECT_DESTINATION_BASE: \"Seleccionar base de destino\"\n  STR_COST: \"Coste\"\n  STR_INTRO_1: \"Copyright 1995 MicroProse\"\n  STR_INTRO_2: \"Marte: La caida de Cydonia.\"\n  STR_INTRO_3: \"Un triunfante X-Com, habiendo destruido el núcleo mismo de la máquina de guerra Alienígena, despega hacia el hogar. Sin embargo, no todo está muerto en la base marciana devastada.\"\n  STR_INTRO_4: \"Un poderoso rayo de taquiones fluye desde los escombros del centro neurálgico de Cydonia, a toda velocidad a través del vacío. Su destino............\"\n  STR_INTRO_5: \"Tierra.\"\n  STR_INTRO_6: \"En lo profundo del océano el haz golpea un receptor inactivo. Grandes ordenadores, comienzan a activarse. En lo profundo, más allá de los ojos de los seres humanos, vastas cámaras de Alienígenas dormidos comienzan su largo ciclo de reanimación.\"\n  STR_INTRO_7: \"2040: Una Tierra ignorante. Los terrores de la guerra Alienígena se olvidan. Pero, en los lugares perdidos y ocultos del océano las hordas alienígenas están listas, listas para derrocar a la humanidad y dominar el mundo.\"\n  STR_INTRO_8: \"Los Alienígenas arremeten contra la humanidad; buscan especímenes para sus retorcidos experimentos; asaltando el mundo por valiosos minerales y recursos; y saqueando los mares. Entonces, posan sus ojos sobre las olas.\"\n  STR_INTRO_9: \"Poderosos submarinos voladores de extraño diseño surcan los océanos, observando, buscando, cazando.........\"\n  STR_INTRO_10: \"Buscando presas, atacan.\"\n  STR_INTRO_11: \"Nuevas armas extrañas se lanzan contra un mundo indefenso. Estamos completamente a merced de la amenaza alienígena. {NEWLINE}Sólo una organización puede salvarnos; pero, les dimos la espalda hace mucho tiempo......\"\n  STR_INTRO_12: \"Instalación subacuática experimental X-COM\"\n  STR_INTRO_13: \"'¡s o s! ¡s o s! ''Este es el trans-atlántico Hyperion'. \\\"Estamos bajo ataque\\\". '¡s o s! socorrrr............ \\\"\"\n  STR_INTRO_14: \"\\\"Centro de Comando a Submarino Uno: Abrir Esclusas\\\", \\\"desplegar Barracuda Cero Uno. Tenemos una situación de ataque alienígena, Alerta Roja\\\".{NEWLINE}\\\"Repito: Alerta Roja\\\"\"\n  STR_INTRO_15: \"Los Alienígenas son implacables en su eficiencia....\"\n  STR_INTRO_16: \"...infalibles en su exactitud\"\n  STR_INTRO_17: \"\\\"Barracuda Cero Uno a base\\\" - \\\"acercándose a lo que queda del Hyperion\\\".\"\n  STR_INTRO_18: \"'Reduciendo velocidad'.{NEWLINE}'Dos metros'{NEWLINE}'Un metro'{NEWLINE}' A todos los Aquanautas, prepárense para  despliegue inmediato'.\"\n  STR_INTRO_19: \".........\\\"Esclusa despejada\\\"... \\\"acercándose al naufragio\\\".{NEWLINE}\\\"Santo!\\\"{NEWLINE}\\\"¿Están captando esas criaturas con mi cámara de traje?\\\"\"\n  STR_GAMEOVER_1: \"Hemos fallado, los Alienígenas han aniquilado nuestras últimas esperanzas de salvación.{NEWLINE}X-Com está destruido y la Tierra se puso a los pies del antiguo enemigo.\"\n  STR_GAMEOVER_2: \"T'leth truena en la estratosfera y comienza a moverse a través de la faz del mundo. Dispensando la muerte y cosechando los restos de la raza humana. En lo profundo de sus entrañas la asesina mente alienígena comienza a despertarse.\"\n  STR_GAMEOVER_3: \"En las capitales de todas las naciones, planes desesperados se elaboran. Todo es en vano, sin la tecnología que ofrece el proyecto de investigación X-Com nuestras armas son ineficaces.\"\n  STR_GAMEOVER_4: \"Los Alienígenas establecieron bases en los casquetes polares y empiezan a derretir el hielo, el mundo se convertirá en un vasto mar. Los restos de la raza humana son capturados y se utilizan en viles experimentos de reproducción con fines desconocidos. Los cielos se oscurecen y una fuerte pestilencia está sobre las tierras del Mundo.\"\n  STR_GAMEOVER_5: \"No podemos ofrecer ninguna resistencia al nuevo orden mundial, aquellos que lo intentan se encuentran con un destino de fuego a manos de las incomprensibles armas alienígenas. Para el resto de nosotros no hay liberación bendita, la madre tierra se convierte en un mundo alienígena y la humanidad se pierde debajo de un progresivo horror.\"\n  STR_OUTRO_1: \"La tumba, asolada y diezmada, un rugido burbujeante proviene del centro de la urna.{NEWLINE}Tontos, todos perecerán....................\"\n  STR_OUTRO_2: \".................nadie puede escapar.\"\n  STR_OUTRO_3: \"Una enorme explosión brota de la tumba y atraviesa la ciudad, los escombros y el humo llenan el aire. Los planes de los alienígenas se ven frustrados........\"\n  STR_OUTRO_4: \"La retorcida vastedad de T'leth comienza a romperse. Llamas y humo se arrojan desde sus torres relucientes y salas de adamantium.\"\n  STR_OUTRO_5: \"El fastuoso gran Alienígena se desploma hacia el mar, los gritos de metal y almas torturadas llenan el aire. El Gran Soñador ya no soñara con conquistar el mundo.\"\n  STR_OUTRO_6: \"Un ensordecedor sonido final conmociona a la propia T'leth que rompe en lágrimas. {NEWLINE}La amenaza alienígena se ha ido, la Tierra es libre..................\"\n  STR_OUTRO_7: \"Un dormido planeta verde-azulado, en un rincón lejano de la galaxia.\"\n  STR_OUTRO_8: \"El futuro cercano, un lugar seguro para estar.\"\n  STR_OUTRO_9: \"La amenaza Alienígena fue derrotada hace mucho tiempo.\"\n  STR_OUTRO_10: \"Vastas ciudades metrópolis albergan rebosantes miles de millones de humanos.\"\n  STR_OUTRO_11: \"Las batallas de X-Com y las guerras Alienígenas son argumento de historias para niños.\"\n  STR_OUTRO_12: \"Pero las leyendas siempre han tenido el habito de contener una pizca de verdad..........\"\n  STR_RISE_1: \"T'leth, fue llamado muchas cosas en muchas leyendas de muchas tierras.\"\n  STR_RISE_2: \"Con un explosivo grito que resuena a través del globo T'leth comienza a alzarse del fondo del mar.\"\n  STR_RISE_3: \"El enorme complejo surge a través de las aguas del Golfo de Méjico.\"\n  STR_RISE_4: \"400 mil millones de toneladas de metal alienígena, la enorme ciudad alienígena en donde se encuentra el cuerpo latente del alienígena definitivo. Encarcelado en la tierra hace 65 millones de años, este vil dios del espacio comienza a moverse.\"\n  STR_RISE_5: \"Las aguas hierven y se agitan mientas la tumba del Gran Soñador emerge a la luz................\"\n  STR_RISE_6: \".........una luz que durara poco a menos que X-Com pueda destruir la maquinaria de guerra alienígena.\"\n  STR_YOU_HAVE_FAILED: \"Has fracasado en detener la máquina de guerra alienígena. Las organizaciones de financiación, desilusionados con su capacidad tratan de negociar una solución no militar con los alienígenas. Los invasores tienen una agenda muy diferente y pronto todo el mundo es consciente de la verdad ...\"\n  STR_TOTAL_UC: \"TOTAL\"\n  STR_INCOME: \"Ingresos\"\n  STR_EXPENDITURE: \"Gastos\"\n  STR_MAINTENANCE: \"Mantenimiento\"\n  STR_BALANCE: \"Balance\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"Actividad OSNI en mares\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"Actividad Alienígena en Zonas\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"Actividad X-Com en Los Mares\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"Actividad X-Com en Zonas\"\n  STR_FINANCE: \"Finanzas\"\n  STR_DATE_FIRST: \"{0}º\"\n  STR_DATE_SECOND: \"{0}º\"\n  STR_DATE_THIRD: \"{0}º\"\n  STR_DATE_FOURTH: \"{0}º\"\n  STR_FINANCE_THOUSANDS: \"1000$\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"No hay suficientes materiales para producir{NEWLINE}{0}{NEWLINE}en{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"No hay dinero suficiente para producir {NEWLINE}{0}{NEWLINE}en{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"Producción de{NEWLINE}{0}{NEWLINE}en{NEWLINE}{1}{NEWLINE}completada\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"Construcción de{NEWLINE}{0}{NEWLINE}en{NEWLINE}{1}{NEWLINE}completada\"\n  STR_OK_5_SECONDS: \"OK - 5 seg\"\n  STR_RESEARCH_COMPLETED: \"Investigación finalizada\"\n  STR_VIEW_REPORTS: \"VER INFORMES\"\n  STR_WE_CAN_NOW_RESEARCH: \"Preparados para investigar\"\n  STR_WE_CAN_NOW_PRODUCE: \"Preparados para fabricar\"\n  STR_SUNDAY: \"DOMINGO\"\n  STR_MONDAY: \"LUNES\"\n  STR_TUESDAY: \"MARTES\"\n  STR_WEDNESDAY: \"MIÉRCOLES\"\n  STR_THURSDAY: \"JUEVES\"\n  STR_FRIDAY: \"VIERNES\"\n  STR_SATURDAY: \"SÁBADO\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"No hay suficiente {0} para repostar {1} en {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"No hay suficiente {0} para rearmar{1} en {2}\"\n  STR_UFO_IS_NOT_RECOVERED: \"OSNI no recuperado\"\n  STR_UFO_IS_RECOVERED: \"OSNI recuperado\"\n  STR_CRAFT_IS_LOST: \"Aerosubmarino Perdido\"\n  STR_TERROR_CONTINUES: \"Actividades Alienigenas continuan\"\n  STR_ALIENS_DEFEATED: \"Alienígenas derrotados\"\n  STR_BASE_IS_LOST: \"La base se ha perdido\"\n  STR_BASE_IS_SAVED: \"La base se ha salvado\"\n  STR_ALIEN_BASE_STILL_INTACT: \"Base alienígena intacta\"\n  STR_ALIEN_BASE_DESTROYED: \"Base alienígena destruida\"\n  STR_ALIENS_KILLED: \"BAJAS ALIENÍGENAS\"\n  STR_ALIEN_CORPSES_RECOVERED: \"CADÁVERES ALIENÍGENAS RECUPERADOS\"\n  STR_LIVE_ALIENS_RECOVERED: \"ALIENÍGENAS VIVOS CAPTURADOS\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"ARTEFACTOS ALIENÍGENAS RECUPERADOS\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"CONTROL DE LA COLONIA ALIENÍGENA DESTRUIDO\"\n  STR_ALIEN_SYNOMIUM_DEVICE_DESTROYED: \"DISPOSITIVO SYNOMIUM DESTRUIDO\"\n  STR_ALIEN_SYNOMIUM_DEVICE_FAILED: \"FALLO AL DESTRUIR EL DISPOSITIVO SYNOMIUM\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"BAJAS CIVILES CAUSADAS POR LOS ALIENÍGENAS\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"BAJAS CIVILES CAUSADAS POR X-COM\"\n  STR_CIVILIANS_SAVED: \"CIVILES RESCATADOS\"\n  STR_XCOM_OPERATIVES_KILLED: \"BAJAS X-COM\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"OPERATIVOS X-COM DESAPARECIDOS EN ACCIÓN\"\n  STR_TANKS_DESTROYED: \"SISTEMAS DE ARMAS X-COM DESTRUIDAS\"\n  STR_XCOM_CRAFT_LOST: \"SUBMARINO X-COM DESTRUIDO\"\n  STR_UFO_RECOVERY: \"RECUPERACIÓN DE OSNI\"\n  STR_ALIEN_BASE_RECOVERY: \"RECUPERACIÓN EN COLONIA ALIENÍGENA\"\n  STR_BASE_UNDER_ATTACK: \"{0} bajo ataque!\"\n  STR_BASE_DEFENSES_INITIATED: \"INICIADA DEFENSA DE LA BASE\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"¡ESCUDO DE GRAV. REPELE OSNI !\"\n  STR_FIRING: \"DISPARANDO\"\n  STR_HIT: \"¡TOCADO!\"\n  STR_UFO_DESTROYED: \"¡OSNI DESTRUIDO!\"\n  STR_MISSED: \"¡DISPARO FALLIDO!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Vender artículos/Despedir personal\"\n  STR_VALUE_OF_SALES: \"VALOR DE LAS VENTAS> {ALT}{0}\"\n  STR_FUNDS: \"FONDOS> {ALT}{0}\"\n  STR_SELL_SACK: \"Vender/Despedir\"\n  STR_VALUE: \"Valor\"\n  STR_CRAFT_: \"de Aerosubmarino> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"RECUPERACIÓN DE OSNI DERRIBADO\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"EXTREMA PRECAUCIÓN - Habrá alienígenas en el submarino y alrededor del sitio. Esta misión se completará cuando todas las unidades enemigas hayan sido eliminadas o neutralizadas. La recuperación de restos del submarino alienígena, tecnología y cadáveres alienígenas podrá entonces ser iniciada. Para abortar la misión regrese los acuanautas X-Com al submarino y haga clic en el icono 'Abortar Misión'.\"\n  STR_UFO_GROUND_ASSAULT: \"ASALTO A SUBMARINO ALIENÍGENA\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"Explore el punto de amerizaje y, si es posible, gane acceso al submarino alienígena. Esta misión se completará cuando todas las unidades enemigas hayan sido eliminadas o neutralizadas. La recuperación de restos del submarino alienígena, tecnología y cadáveres alienígenas podrá entonces ser iniciada. Para abortar la misión regrese los acuanautas X-Com al submarino y haga clic en el icono 'Abortar Misión'.\"\n  STR_BASE_DEFENSE: \"DEFENSA DE LA BASE\"\n  STR_BASE_UC_: \"BASE> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"Una nave alienígena ha ATERRIZADO muy cerca. Nuestra base está en peligro. Según el procedimiento habitual, se ha evacuado todo el personal no combatiente en los submarinos X-Com. Los alienígenas accederán a la base por las compuertas de los muelles o por la esclusa de acceso. Defienda la base y sus instalaciones vitales a toda costa, es una lucha a vida o muerte. Si presiona en el icono de 'Abortar misión' aceptará la derrota y perderá la base.\"\n  STR_ALIEN_COLONY_ATTACK_MISSION: \"ATAQUE A COLONIA ALIENÍGENA\"\n  STR_ALIEN_BASE_ASSAULT: \"COLONIA ALIENÍGENA PARTE UNO\"\n  STR_ALIEN_COLONY_P1_BRIEFING: \"Esta misión consiste en un ataque a una colonia alienígena. Hay dos niveles, lleva a todos los aquanautas a la salida brillante del primer complejo y pulsa en 'Cancelar misión' para proseguir. Todo el equipo que abandones se quedará en el fondo del mar hasta que completes la segunda parte. Para salir, pon a los aquanautas en el submarino y pulsa en el icono 'Abortar misión'.\"\n  STR_ALIEN_COLONY_P2: \"COLONIA ALIENÍGENA PARTE DOS\"\n  STR_ALIEN_COLONY_P2_BRIEFING: \"Tras haber completado el primer nivel y entrado en el núcleo de la colonia, ahora tu misión es destruir el centro de control, recoger el dispositivo Synomium o eliminar a todos los alienígenas. Para cancelar, pon a todos los aquanautas en el punto de partida y pulsa en el icono 'Abortar misión'. Todo el equipo X-Com útil regresará a la base.\"\n  STR_ALIENS_LAUNCH_PORT_TERROR: \"ALIENÍGENAS LANZAN{NEWLINE}ATAQUE EN PUERTO\"\n  STR_PORT_TERROR: \"ALIENÍGENAS LANZAN ATAQUE A PUERTO\"\n  STR_PORT_TERROR_BRIEFING: \"Los alienígenas han lanzado un ataque contra instalaciones en la superficie. El puerto y su población civil se han puesto en riesgo. Su escuadrón debe eliminar todos los alienígenas y proteger a las personas inocentes de esta incursión alienígena. Para Cancelar, coloque los aquanautas en el aerosubmarino y haz clic en el icono 'Abortar Misión'.\"\n  STR_ALIENS_LAUNCH_ISLAND_TERROR: \"ALIENÍGENAS LANZAN{NEWLINE}ATAQUE EN ISLA\"\n  STR_ISLAND_TERROR: \"ALIENÍGENAS LANZAN ATAQUE A ISLA\"\n  STR_ISLAND_TERROR_BRIEFING: \"Los alienígenas han lanzado un ataque contra instalaciones en la superficie. La Isla y su población se han puesto en riesgo. Su escuadrón debe eliminar todos los alienígenas y proteger a los inocentes transeúntes de esta incursión alienígena. Para Cancelar, coloque los aquanautas en el aerosubmarino y haz clic en el icono 'Abortar Misión'.\"\n  STR_ALIENS_ATTACK_SHIPPING_ROUTE: \"ALIENÍGENAS ATACAN{NEWLINE}RUTA DE ENVÍO\"\n  STR_CARGO_SHIP_P1: \"BUQUE DE CARGA PARTE UNO\"\n  STR_CARGO_SHIP_P2: \"BUQUE DE CARGA PARTE DOS\"\n  STR_CRUISE_SHIP_P1: \"CRUCERO PARTE UNO\"\n  STR_CRUISE_SHIP_P2: \"CRUCERO PARTE DOS\"\n  STR_SHIP_RESCUE_MISSION: \"MISIÓN DE RESCATE A BUQUE\"\n  STR_SHIP_RESCUE_P1_BRIEFING: \"Esta misión es una cacería, elimine todas las unidades alienígenas en el barco, y preserve la vida de los civiles a bordo. Los alienígenas están dispersos por encima y debajo de la cubierta, asegure las cubiertas superiores antes de entrar en los inferiores. Para cancelar, coloque los aquanautas en el aerosubmarino y haz clic en el icono 'Abortar Misión'.\"\n  STR_SHIP_RESCUE_P2_BRIEFING: \"Ahora que la cubierta superior está despejada proceda a las cubiertas inferiores. Utilizando el ascensor de carga se desciende a la bodega. Su escuadrón debe eliminar todos los alienígenas en este nivel para completar la misión. Para abortar coloque todos los aquanautas en el ascensor inicial y haga clic en el icono 'Abortar Misión'.\"\n  STR_ALIEN_ACTIVITY_DETECTED: \"ACTIVIDAD ALIENÍGENA DETECTADA\"\n  STR_ALIEN_CONTACT_SITE_MISSION: \"ASALTO A COMUNICACIONES ALIENÍGENAS\"\n  STR_ARTIFACT_SITE_P1: \"COMUNICACIONES ALIENÍGENAS PARTE UNO\"\n  STR_ARTIFACT_SITE_P1_BRIEFING: \"Esta misión es un asalto en un sitio de comunicación alienígena recién activado. Hay 2 niveles para alcanzar el sitio, el fondo del mar con sus pirámides alienígenas y un complejo alienígena escondido. Lleve todos los aquanautas a la entrada del complejo y haga clic en el icono 'Abortar Misión' para proceder. Para Cancelar, coloque los aquanautas en el  aerosubmarino y haga clic en el icono 'Abortar Misión'.\"\n  STR_ARTIFACT_SITE_P2: \"COMUNICACIONES ALIENÍGENAS PARTE DOS\"\n  STR_ARTIFACT_SITE_P2_BRIEFING: \"Después de haber negociado las estructuras alienígenas y entrado en el complejo de los objetivos de la misión son claros. Penetrar el corazón de la instalación alienígena y destruir el dispositivo de control molecular Synomium para completar la misión. Para abortar coloque todos los aquanautas en el ascensor inicial y haga clic en el icono 'Abortar Misión'.\"\n  STR_SIGSBEE_DEEP_MISSION: \"MISIÓN EN FOSA SIGSBEE{NEWLINE}CIUDAD ALIENÍGENA PARTE UNO\"\n  STR_TLETH_P1_BRIEFING: \"Nos adentramos en lo desconocido, de aquí en adelante podemos encontrarnos cualquier cosa. Sabemos que hay dos niveles en la ciudad, tu escuadrón debe llegar rápido a la salida del nivel para pasar al siguiente. Lleva a todos los aquanautas a la salida y pulsa en 'Arbortar misión' para avanzar.Si la cancelas en otro lugar, la misión se terminará.\"\n  STR_TLETH_ATTACK_MISSION: \"MISIÓN DE ATAQUE A T'LETH{NEWLINE}CIUDAD ALIENÍGENA PARTE DOS\"\n  STR_TLETH_P2_BRIEFING: \"Seguimos avanzando hacia lo desconocido, de aquí en adelante podemos encontrarnos cualquier cosa. Sabemos que hay otro nivel en la ciudad, tu escuadrón debe llegar rápido a la salida de este nivel para pasar al siguiente. Lleva a todos los aquanautas a la salida y pulsa en 'Abortar misión' para avanzar. Si la abortas en otro lugar, la misión se terminará.\"\n  STR_FINAL_TLETH_MISSION: \"MISIÓN FINAL EN T'LETH{NEWLINE}CIUDAD ALIENÍGENA PARTE TRES\"\n  STR_TLETH_P3_BRIEFING: \"El final está a la vista, a partir de ahora debemos buscar la cripta del Alienígena Supremo. Destruye los 8 alimentadores de la tumba para acabar con la amenaza alienígena. ¡No te rindas! Si pulsas en 'Abortar misión', la misión se terminará.\"\n  STR_TLETH_P1: \"CIUDAD ALIENÍGENA PARTE UNO\"\n  STR_TLETH_P2: \"CIUDAD ALIENÍGENA PARTE DOS\"\n  STR_TLETH_P3: \"CIUDAD ALIENÍGENA PARTE TRES\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"¡NO HAY MUELLES LIBRES PARA CONSTRUIR AEROSUBMARINOS!{SMALLLINE}Cada aerosubmarino asignado o trasladado a una base, comprado o construido ocupa un muelle. Construye un nuevo muelle para aerosubmarino o traslada un aerosubmarino a otra base.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"¡NO HAY MUELLES LIBRES PARA COMPRAR AEROSUBMARINOS!{SMALLLINE}Cada aerosubmarino asignado o trasladado a una base, comprado o construido ocupa un muelle. Construye un nuevo muelle para aerosubmarino o traslada un aerosubmarino a otra base.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"¡NO HAY MUELLES LIBRES PARA TRASLADAR AEROSUBMARINOS!{SMALLLINE}Cada aerosubmarino asignado o trasladado a una base, comprado o construido ocupa un muelle. Construye un nuevo muelle para aerosubmarino o traslada un aerosubmarino a otra base.\"\n  STR_CANNOT_BUILD_HERE: \"¡NO PUEDES CONSTRUIR AQUÍ!{SMALLLINE}Sólo junto a una instalación finalizada.\"\n  STR_NO_FREE_ACCOMODATION: \"¡NO HAY ALOJAMIENTO DISPONIBLE!{SMALLLINE}La base de destino no tiene espacio suficiente en la zona de alojamiento.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"¡NO HAY SUFICIENTE ESPACIO PARA TRABAJAR!{SMALLLINE}Construye un taller nuevo o reduce los trabajos relacionados con otros proyectos.\"\n  STR_NOT_ENOUGH_MONEY: \"¡NO HAY DINERO SUFICIENTE!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"¡NO HAY SUFICIENTE ESPACIO DE ALMACENAJE!{SMALLLINE}Construye un almacén nuevo o traslada las existencias a otras bases.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"¡NO HAY SUFICIENTE ESPACIO HABITABLE!{SMALLLINE}Construye nuevos alojamientos o traslada personal a otras bases.\"\n  STR_LAUNCH_INTERCEPTION: \"INICIAR INTERCEPCIÓN\"\n  STR_CRAFT: \"NAVE\"\n  STR_STATUS: \"SITUACIÓN\"\n  STR_BASE: \"BASE\"\n  STR_READY: \"LISTO\"\n  STR_OUT: \"FUERA\"\n  STR_REPAIRS: \"REPARACIONES\"\n  STR_REFUELLING: \"REPOSTANDO\"\n  STR_REARMING: \"REARMANDO\"\n  STR_TARGET: \"OBJETIVO: {0}\"\n  STR_WAY_POINT: \"PUNTO DE DESTINO\"\n  STR_ARE_YOU_SURE_CYDONIA: \"¿Estás seguro de que quieres mandar este submarino a T'leth en una misión?\"\n  STR_YES: \"SÍ\"\n  STR_NO: \"NO\"\n  STR_SELECT_DESTINATION: \"SELECCIONAR DESTINO\"\n  STR_CYDONIA: \"T'LETH\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"SELECCIONE UBICACIÓN DE LA{NEWLINE}NUEVA BASE\"\n  STR_RETURN_TO_BASE: \"REGRESAR A LA BASE\"\n  STR_SELECT_NEW_TARGET: \"SELECCIONAR OTRO BLANCO\"\n  STR_PATROL: \"PATRULLAR\"\n  STR_STATUS_: \"SITUACIÓN>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"AVERIADO - REGRESA A LA BASE\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"POCO COMBUSTIBLE - REGRESA A LA BASE\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"MISIÓN COMPLETADA - REGRESANDO A LA BASE\"\n  STR_PATROLLING: \"PATRULLANDO\"\n  STR_TAILING_UFO: \"SIGUIENDO A UN OSNI\"\n  STR_INTERCEPTING_UFO: \"INTERCEPTANDO OSNI-{0}\"\n  STR_RETURNING_TO_BASE: \"REGRESANDO A LA BASE\"\n  STR_DESTINATION_UC_: \"DESTINO: {0}\"\n  STR_BASE_UC: \"BASE>{ALT}{0}\"\n  STR_SPEED_: \"VELOCIDAD>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"VELOCIDAD MAXIMA>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"PROFUNDIDAD>{ALT}{0}\"\n  STR_AIRBORNE: \"POR AIRE\"\n  STR_VERY_LOW: \"SUPERFICIAL\"\n  STR_LOW_UC: \"NORMAL\"\n  STR_HIGH_UC: \"PROFUNDO\"\n  STR_VERY_HIGH: \"MUY PROFUNDO\"\n  STR_FUEL: \"COMBUSTIBLE>{ALT}{0}\"\n  STR_WEAPON_ONE: \"ARMA-1>{ALT}{0}\"\n  STR_NONE_UC: \"NINGUNA\"\n  STR_ROUNDS_: \"DISPAROS>{ALT}{0}\"\n  STR_WEAPON_TWO: \"ARMA-2>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"AEROSUBMARINO\"\n  STR_BASE_: \"Base>{0}\"\n  STR_NAME_UC: \"NOMBRE\"\n  STR_AMMO_: \"MUNICION>{ALT}{0}\"\n  STR_CREW: \"TRIPULACIÓN\"\n  STR_EQUIPMENT_UC: \"ARMAMENTO\"\n  STR_ARMOR: \"BLINDAJE\"\n  STR_MAX: \"MAX>{ALT}{0}\"\n  STR_ROOKIE: \"Aquanauta\"\n  STR_SQUADDIE: \"Cabo\"\n  STR_SERGEANT: \"Alférez\"\n  STR_CAPTAIN: \"Capitán\"\n  STR_COLONEL: \"Almirante\"\n  STR_COMMANDER: \"Comodoro\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Elija escuadra para {0}\"\n  STR_SORT_BY: \"ORDENAR POR...\"\n  STR_ORIGINAL_ORDER: \"ORDEN ORIGINAL\"\n  STR_MISSIONS2: \"MISIONES\"\n  STR_KILLS2: \"MUERTES\"\n  STR_WOUND_RECOVERY2: \"RECUPERACIÓN DE HERIDAS\"\n  STR_SPACE_AVAILABLE: \"ESPACIO DISPONIBLE>{ALT}{0}\"\n  STR_SPACE_USED: \"ESPACIO USADO>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"ESPACIO USADO\"\n  STR_RANK: \"RANGO\"\n  STR_WOUNDED: \"HERIDO\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Equipo para {0}\"\n  STR_DEFENSE_VALUE: \"Valor defensivo\"\n  STR_HIT_RATIO: \"Media de impactos\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}preparado para{NEWLINE}aterrizar cerca de{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"¿Iniciar la misión?\"\n  STR_SELECT_ARMAMENT: \"Seleccionar armamento\"\n  STR_AMMUNITION_AVAILABLE: \"MUNICIÓN DISPONIBLE\"\n  STR_ARMAMENT: \"ARMAMENTO\"\n  STR_NOT_AVAILABLE: \"N.D.\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"SELECCIONAR ARMADURA PARA{NEWLINE}{ALT}{0}\"\n  STR_TYPE: \"TIPO\"\n  STR_PLASTIC_AQUA_ARMOR_UC: \"ARMADURA DE AQUAPLASTICOS\"\n  STR_ION_ARMOR_UC: \"ARMADURA DE IONES\"\n  STR_MAGNETIC_ION_ARMOR_UC: \"ARMADURA MAGNÉTICA DE IONES\"\n  STR_PLASTIC_AQUA_ARMOR_UFOPEDIA: \"Este blindaje emplea la sustancia alienígena recién descubierta, el aquaplástico, y les da a nuestros aquanautas una oportunidad de luchar contra las incursiones alienígenas.\"\n  STR_ION_ARMOR_UFOPEDIA: \"Una protección para los aquanautas, nueva y poderosa. Está reforzada con energía de iones y aumenta la fuerza y la velocidad del que la lleva. Es la mejor protección para las tropas de combate.\"\n  STR_MAGNETIC_ION_ARMOR_UFOPEDIA: \"Una mejora de la armadura de iones, incorpora la tecnología magnética para permitir total libertad de movimientos en el medio acuático.\"\n  STR_SELECT_ARMOR: \"Selección de Blindaje\"\n  STR_NORTH: \"NORTE\"\n  STR_NORTH_EAST: \"NORESTE\"\n  STR_EAST: \"ESTE\"\n  STR_SOUTH_EAST: \"SURESTE\"\n  STR_SOUTH: \"SUR\"\n  STR_SOUTH_WEST: \"SUROESTE\"\n  STR_WEST: \"OESTE\"\n  STR_NORTH_WEST: \"NOROESTE\"\n  STR_SELECT_ACTION: \"SELECCIONAR ACCIÓN\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"CONTINUAR PERSECUCIÓN DE OSNI\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"PERSECUCIÓN SIN INTERCEPCIÓN\"\n  STR_VERY_LARGE: \"MUY GRANDE\"\n  STR_LARGE: \"GRANDE\"\n  STR_MEDIUM_UC: \"NORMAL\"\n  STR_SMALL: \"PEQUEÑO\"\n  STR_VERY_SMALL: \"MUY PEQUEÑO\"\n  STR_GROUNDED: \"AMERIZADO\"\n  STR_DETECTED: \"Detectado\"\n  STR_SIZE_UC: \"TAMAÑO\"\n  STR_ALTITUDE: \"PROFUNDIDAD\"\n  STR_HEADING: \"RUMBO\"\n  STR_SPEED: \"VELOCIDAD\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"CENTRAR EN OSNI - TIEMPO = 5 Seg\"\n  STR_TRACKING_LOST: \"RASTRO PERDIDO\"\n  STR_REDIRECT_CRAFT: \"CAMBIAR RUMBO\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"IR A ÚLTIMA POSICIÓN CONOCIDA DEL OSNI\"\n  STR_UFO_: \"OSNI-{0}\"\n  STR_ALIEN_BASE_: \"COLONIA ALIENÍGENA-{0}\"\n  STR_CRASH_SITE_: \"LUGAR DE IMPACTO-{0}\"\n  STR_LANDING_SITE_: \"SITIO DE AMERIZAJE-{0}\"\n  STR_WAY_POINT_: \"PUNTO DE DESTINO-{0}\"\n  STR_TERROR_SITE: \"LUGAR DEL TERROR-{0}\"\n  STR_ARTIFACT_SITE: \"SITIO DEL ARTEFACTO-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}ha llegado a{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"Está patrullando\"\n  STR_ALIEN_ORIGINS: \"Origen de los alienígenas\"\n  STR_THE_ULTIMATE_THREAT: \"La Amenaza Definitiva\"\n  STR_TLETH_ALIEN_CITY: \"T'leth, la Ciudad Alienígena\"\n  STR_UFOPAEDIA: \"Osnipedia\"\n  STR_XCOM_CRAFT_ARMAMENT: \"NAVES Y ARMAS DE X-COM\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"SISTEMAS DE ARMAS SUMERGIBLES S.A.S.\"\n  STR_WEAPONS_AND_EQUIPMENT: \"ARMAMENTO GENERAL\"\n  STR_ALIEN_ARTIFACTS: \"ARTEFACTOS AQUÁTICOS\"\n  STR_BASE_FACILITIES: \"INSTALACIONES X-COM\"\n  STR_ALIEN_LIFE_FORMS: \"CRIATURAS ALIENÍGENAS\"\n  STR_ALIEN_RESEARCH_UC: \"TECNOLOGÍA ALIENÍGENA\"\n  STR_UFO_COMPONENTS: \"NUEVAS TECNOLOGÍAS SUMERGIBLES\"\n  STR_UFOS: \"OBJETO SUMERGIBLE NO IDENTIFICADO \\\"OSNI\\\"\"\n  STR_SELECT_ITEM: \"SELECCIONAR ARTÍCULO\"\n  STR_ACCELERATION: \"ACELERACION>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"COMBUSTIBLE>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"RANURAS DE ARMAS>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"RESISTENCIA>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"ESPACIO DE CARGA>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"CAPACIDAD SAS>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Daño\"\n  STR_RANGE: \"Alcance\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Precisión\"\n  STR_RE_LOAD_TIME: \"Tiempo de recarga\"\n  STR_SECONDS: \"{0}s\"\n  STR_DAMAGE_ARMOR_PIERCING: \"PERFORANTE\"\n  STR_DAMAGE_INCENDIARY: \"FÓSFORO\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"DAÑO EXPLOSIVO\"\n  STR_DAMAGE_LASER_BEAM: \"RAYO GAUSS\"\n  STR_DAMAGE_PLASMA_BEAM: \"RAYO SóNICO\"\n  STR_DAMAGE_STUN: \"CONGELAR\"\n  STR_DAMAGE_MELEE: \"CUERPO A CUERPO\"\n  STR_DAMAGE_ACID: \"ÁCIDO\"\n  STR_DAMAGE_SMOKE: \"HUMO\"\n  STR_SHOT_TYPE: \"TIPO\"\n  STR_ACCURACY_UC: \"PRECISIÓN\"\n  STR_TIME_UNIT_COST: \"COSTE UT\"\n  STR_DAMAGE_UC: \"DAÑO\"\n  STR_AMMO: \"MUNICIÓN\"\n  STR_SHOT_TYPE_AUTO: \"Automático\"\n  STR_SHOT_TYPE_SNAP: \"Rápido\"\n  STR_SHOT_TYPE_AIMED: \"Precisión\"\n  STR_CONSTRUCTION_TIME: \"Tiempo de construcción\"\n  STR_CONSTRUCTION_COST: \"Coste de construcción\"\n  STR_MAINTENANCE_COST: \"Coste de mantenimiento\"\n  STR_LOW: \"Baja\"\n  STR_MEDIUM: \"Media\"\n  STR_HIGH: \"Alta\"\n  STR_CRAFT_WEAPON: \"Arma de Submarino\"\n  STR_CRAFT_AMMUNITION: \"Munición de Submarino\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Sistema de Armas Submarinas\"\n  STR_WEAPON: \"Arma\"\n  STR_AMMUNITION: \"Munición\"\n  STR_EQUIPMENT: \"Equipo\"\n  STR_ALIEN_CORPSE: \"Cadáver alienígena\"\n  STR_UFO_COMPONENT: \"Pieza de un Submarino Alienígena\"\n  STR_PERSONAL_ARMOR: \"Blindaje personal\"\n  STR_RAW_MATERIALS: \"Materias primas\"\n  STR_HWP_SOLID_HARPOON_BOLTS: \"Arpones Sólidos\"\n  STR_ALIEN: \"Alienígena\"\n  STR_AQUATOID: \"Aquatoide\"\n  STR_GILLMAN: \"Hombre-Branquia\"\n  STR_LOBSTERMAN: \"Hombre-Langosta\"\n  STR_TASOTH: \"Tasoth\"\n  STR_CALCINITE: \"Calcinite\"\n  STR_DEEP_ONE: \"Anuroide\"\n  STR_BIODRONE: \"Telecerebro\"\n  STR_TENTACULAT: \"Tentaculat\"\n  STR_TRISCENE: \"Triscene\"\n  STR_HALLUCINOID: \"Alucinoide\"\n  STR_XARQUID: \"Calaxmar\"\n  STR_ZOMBIE: \"Zombi\"\n  STR_LIVE_COMMANDER: \"Comandante\"\n  STR_LIVE_NAVIGATOR: \"Navegante\"\n  STR_LIVE_MEDIC: \"Médico\"\n  STR_LIVE_TECHNICIAN: \"Ingeniero\"\n  STR_LIVE_SQUAD_LEADER: \"Líder de Escuadrón\"\n  STR_LIVE_SOLDIER: \"Soldado\"\n  STR_LIVE_TERRORIST: \"Terrorista\"\n  STR_AQUATOID_COMMANDER: \"Comandante Aquatoide\"\n  STR_AQUATOID_NAVIGATOR: \"Navegante Aquatoide\"\n  STR_AQUATOID_MEDIC: \"Médico Aquatoide\"\n  STR_AQUATOID_TECHNICIAN: \"Técnico Aquatoide\"\n  STR_AQUATOID_SQUAD_LEADER: \"Líder de Escuadrón Aquatoide\"\n  STR_AQUATOID_SOLDIER: \"Soldado Aquatoide\"\n  STR_GILLMAN_COMMANDER: \"Comandante Hombre-Branquia\"\n  STR_GILLMAN_TECHNICIAN: \"Técnico Hombre-Branquia\"\n  STR_GILLMAN_SQUAD_LEADER: \"Líder de Escuadrón Hombre-Branquia\"\n  STR_GILLMAN_SOLDIER: \"Soldado Hombre-Branquia\"\n  STR_LOBSTERMAN_COMMANDER: \"Comandante Hombre-Langosta\"\n  STR_LOBSTERMAN_NAVIGATOR: \"Navegante Hombre-Langosta\"\n  STR_LOBSTERMAN_TECHNICIAN: \"Técnico Hombre-Langosta\"\n  STR_LOBSTERMAN_SQUAD_LEADER: \"Líder de Escuadrón Hombre-Langosta\"\n  STR_LOBSTERMAN_SOLDIER: \"Soldado Hombre-Langosta\"\n  STR_TASOTH_SQUAD_LEADER: \"Líder de Escuadrón Tasoth\"\n  STR_TASOTH_SOLDIER: \"Tasoth Soldado\"\n  STR_CALCINITE_TERRORIST: \"Calcinite Terrorista\"\n  STR_DEEP_ONE_TERRORIST: \"Anuroide Terrorista\"\n  STR_BIODRONE_TERRORIST: \"Telecerebro Terrorista\"\n  STR_TENTACULAT_TERRORIST: \"Tentaculat Terrorista\"\n  STR_TRISCENE_TERRORIST: \"Triscene Terrorista\"\n  STR_HALLUCINOID_TERRORIST: \"Alucinoide Terrorista\"\n  STR_XARQUID_TERRORIST: \"Calaxmar Terrorista\"\n  STR_ION_BEAM_ACCELERATORS: \"Aceleradores de Rayos de Iones\"\n  STR_MAGNETIC_NAVIGATION: \"Navegación Magnética\"\n  STR_ALIEN_SUB_CONSTRUCTION: \"Construcción de Subm. Alienígenas\"\n  STR_ALIEN_CRYOGENICS: \"Hibernación Alienígena\"\n  STR_ALIEN_CLONING: \"Clonación Alienígena\"\n  STR_ALIEN_LEARNING_ARRAYS: \"Unidades de Enseñanza Alienígenas\"\n  STR_ALIEN_IMPLANTER: \"Implantador Alienígena\"\n  STR_EXAMINATION_ROOM: \"Sala de exámenes\"\n  STR_AQUA_PLASTICS: \"Aquaplásticos\"\n  STR_ALIEN_REANIMATION_ZONE: \"Zona de Reanimación Alienígenas\"\n  STR_PLASTIC_AQUA_ARMOR: \"Blindaje de Aquaplástico\"\n  STR_ION_ARMOR: \"Blindaje Iónico\"\n  STR_MAGNETIC_ION_ARMOR: \"Blindaje Magné. de Iones\"\n  STR_HWP_AQUA_JET_MISSILES: \"Torpedos AquaJet\"\n  STR_HWP_DISPLACER_PWT: \"Torpedo O.I.\"\n  STR_GAUSS_TECH: \"Tecnología Gauss\"\n  STR_NEW_FIGHTER_FLYING_SUB: \"Nuevo Aerosubmarino tipo Caza\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Nuevo Caza-Transporte\"\n  STR_THE_LATEST_FLYING_SUB: \"Lo Último en Aerosubmarinos\"\n  STR_ARMOR_PIERCING: \"PERFORADOR DE BLINDAJE\"\n  STR_COELACANTH_GAS_CANNON: \"Coelacanth/Cañón de Gas\"\n  STR_COELACANTH_AQUA_JET: \"Coelacanth/Torpedos\"\n  STR_COELACANTH_GAUSS: \"Coelacanth/Gauss\"\n  STR_DISPLACER_SONIC: \"Desplazador/Sónico\"\n  STR_DISPLACER_PWT: \"Desplazador/T.O.I.\"\n  STR_AJAX_LAUNCHER: \"Lanzador Ajax\"\n  STR_DUP_HEAD_LAUNCHER: \"Lanzador CUR\"\n  STR_CRAFT_GAS_CANNON: \"Cañón de Gas de la Nave\"\n  STR_PWT_CANNON: \"Cañón O.I.\"\n  STR_GAUSS_CANNON: \"Cañón Gauss\"\n  STR_GAUSS_CANNON_AMMO: \"Munición de Cañón Gauss\"\n  STR_SONIC_OSCILLATOR: \"Oscilador Sónico\"\n  STR_AJAX_TORPEDOES: \"Torpedo Ajax\"\n  STR_DUP_HEAD_TORPEDOES: \"Torpedo CUR\"\n  STR_CRAFT_GAS_CANNON_ROUNDS_X50: \"Disparos del CG(x50)\"\n  STR_SONIC_WAVE: \"Onda Sónica\"\n  STR_PULSE_WAVE_TORPEDOES: \"Munición T.O.I.\"\n  STR_SOLDIER: \"Aquanauta\"\n  STR_SCIENTIST: \"Científico\"\n  STR_ENGINEER: \"Ingenieros\"\n  STR_NORTH_ATLANTIC: \"Atlántico Norte\"\n  STR_SOUTH_ATLANTIC: \"Atlántico Sur\"\n  STR_NORTH_PACIFIC: \"Pacifico Norte\"\n  STR_SOUTH_PACIFIC: \"Pacifico Sur\"\n  STR_MEDITERRANEAN: \"Mediterraneo\"\n  STR_SOUTH_CHINA_SEA: \"Mar del sur de China\"\n  STR_INDIAN_OCEAN: \"Océano Índico\"\n  STR_THE_EAST_SEA: \"Mar de Japón\"\n  STR_NORTH_SEA: \"Mar del Norte\"\n  STR_CARRIBEAN: \"Caribe\"\n  STR_ANTARCTIC: \"Antártico\"\n  STR_ARCTIC: \"Ártico\"\n  STR_EURASIA: \"Eurasia\"\n  STR_NORTH_AMERICA: \"Norteamérica\"\n  STR_AFRICA: \"África\"\n  STR_MAXIMUM_SPEED: \"Velocidad máxima\"\n  STR_TRANSMISSION_RESOLVER_UC: \"DECODIFICADOR TARNS\"\n  STR_TRITON: \"TRITON\"\n  STR_HAMMERHEAD: \"HAMMERHEAD\"\n  STR_LEVIATHAN: \"LEVIATHAN\"\n  STR_BARRACUDA: \"BARRACUDA\"\n  STR_MANTA: \"MANTA\"\n  STR_UFO: \"SUBMARINO ALIENíGENA\"\n  STR_AJAX: \"LANZADOR AJAX\"\n  STR_DUP_HEAD: \"LANZADOR C.U.R.\"\n  STR_CRAFT_GAS_CANNON_UC: \"CG DE LA NAVE\"\n  STR_PWT_CANNON_UC: \"CAÑÓN T.O.I.\"\n  STR_GAUSS_CANNON_UC: \"CAÑÓN GAUSS\"\n  STR_SONIC_OSCILLATOR_UC: \"OSCILADOR SÓNICO\"\n  STR_DAMAGE_CAPACITY: \"Resistencia\"\n  STR_WEAPON_POWER: \"Potencia del arma\"\n  STR_WEAPON_RANGE: \"Alcance del arma\"\n  STR_AIR_LOCK: \"Esclusa\"\n  STR_LABORATORY: \"Laboratorio\"\n  STR_WORKSHOP: \"Taller\"\n  STR_STANDARD_SONAR: \"Sonar Estándar\"\n  STR_WIDE_ARRAY_SONAR: \"Sonar de Red Amplia\"\n  STR_TORPEDO_DEFENSES: \"Torpedos de Defensa\"\n  STR_GENERAL_STORES: \"Almacenes generales\"\n  STR_ALIEN_CONTAINMENT: \"Contención alienígena\"\n  STR_GAUSS_DEFENSES: \"Defensas Gauss\"\n  STR_SONIC_DEFENSES: \"Defensas Sónicas\"\n  STR_PWT_DEFENSES: \"Defensas de T.O.I.\"\n  STR_BOMBARDMENT_SHIELD: \"Escudo de Resonancia\"\n  STR_MC_GENERATOR: \"Escudo de Control Molecular\"\n  STR_MC_LAB: \"Laboratorio de Control Molecular\"\n  STR_TRANSMISSION_RESOLVER: \"Descodificador Tarns\"\n  STR_SUB_PEN: \"Muelle\"\n  STR_USA: \"USA\"\n  STR_ALASKA: \"ALASKA\"\n  STR_EU_SYNDICATE: \"EURO-SINDICATO\"\n  STR_ARABIAN_BLOC: \"BLOQUE ÁRABE\"\n  STR_EGYPTIAN_CARTEL: \"CÁRTEL EGIPCIO\"\n  STR_AFRICA_CORP: \"CORPORACIÓN AFRICANA\"\n  STR_BRAZILIAN_UNION: \"UNIÓN BRASILEÑA\"\n  STR_NEW_MEXICO: \"NUEVO MÉJICO\"\n  STR_ASIAN_COALITION: \"COALICIÓN ASIÁTICA\"\n  STR_SCANDINAVIA: \"ESCANDINAVIA\"\n  STR_NEO_JAPAN: \"NUEVO JAPON\"\n  STR_FREE_CHINA: \"CHINA LIBRE\"\n  STR_AUSTRALASIA: \"AUSTRALASIA\"\n  STR_FED_KOREA: \"FEDERACIÓN COREANA\"\n  STR_EURASIA_UC: \"EURASIA\"\n  STR_ICELANDIC_UNION: \"UNIÓN ISLÁNDICA\"\n  STR_TANK: \"Sistema de Armas Sumergibles\"\n  STR_CIVILIAN: \"Civil\"\n  STR_JAN: \"Ene\"\n  STR_FEB: \"Feb\"\n  STR_MAR: \"Mar\"\n  STR_APR: \"Abr\"\n  STR_MAY: \"May\"\n  STR_JUN: \"Jun\"\n  STR_JUL: \"Jul\"\n  STR_AUG: \"Ago\"\n  STR_SEP: \"Sep\"\n  STR_OCT: \"Oct\"\n  STR_NOV: \"Nov\"\n  STR_DEC: \"Dic\"\n  STR_INTERNATIONAL_RELATIONS: \"Relaciones internacionales\"\n  STR_COUNTRY: \"País\"\n  STR_FUNDING: \"Financiación\"\n  STR_CHANGE: \"Cambio\"\n  STR_WEAPON_SYSTEMS: \"SISTEMAS DE ARMAS\"\n  STR_HWPS: \"SASs\"\n  STR_DAMAGE_UC_: \"DAÑO>{ALT}{0}\"\n  STR_AIR_LOCK_UFOPEDIA: \"La esclusa de aire permite transportar equipo y personal de una base submarina a otra. Es lo primero que se construye en un emplazamiento nuevo. Este compartimiento es vulnerable y puede ser invadido.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Cada zona de alojamiento puede albergar a 50 miembros del personal. Las instalaciones son un tanto básicas y funcionales.\"\n  STR_LABORATORY_UFOPEDIA: \"En un bloque de laboratorios pueden trabajar cincuenta científicos.Los laboratorios están equipados con las tecnologías más modernas para la investigación de materiales, bioquímica y armamento. X-Com tiene acceso a los mejores laboratorios de investigación del mundo,tanto civiles como militares.\"\n  STR_WORKSHOP_UFOPEDIA: \"En un taller se puede encontrar todo lo necesario para fabricar un equipo construido a partir de los diseños científicos más avanzados. El taller puede contener 50 técnicos, y los objetos que se estén fabricando también ocupan sitio.\"\n  STR_STANDARD_SONAR_UFOPEDIA: \"Un sistema de sonar normal tiene un alcance efectivo de 450 km a casi cualquier profundidad, y está conectado a una red de satélites fijos de tierra para el análisis de superficie. Los escáneres tienen una probabilidad del 10% casi de detectar una nave sumergible o aérea por cada ciclo de 30 minutos.\"\n  STR_WIDE_ARRAY_SONAR_UFOPEDIA: \"Un sistema de sonar de largo alcance cubre una zona de más de 700 kilómetros a cualquier profundidad, y está conectado a una red de satélites fijos de tierra para el análisis de superficie. Los escáneres tienen una probabilidad del 20% casi de detectar una nave sumergible o aérea por cada ciclo de 30 minutos.\"\n  STR_TORPEDO_DEFENSES_UFOPEDIA: \"Los sistemas de defensa contra torpedos proporcionan protección contra los ataques de sumergibles hostiles que intenten atracar en la base.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"Todo el equipo, armas, municiones, materiales recuperados y armas pesadas están situadas en almacenes, incluyendo equipo asignado a los submarinos en el muelle.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"A los alienígenas capturados con vida hay que retenerlos en instalaciones especiales. Estas unidades mantienen sus constantes vitales y reducen a cero su capacidad de lucha. En cada celda caben 10 formas de vida alienígena.\"\n  STR_GAUSS_DEFENSES_UFOPEDIA: \"Los sistemas de defensa Gauss proporcionan la protección más eficaz y moderna contra submarinos enemigos.\"\n  STR_SONIC_DEFENSES_UFOPEDIA: \"El oscilador sónico de defensa constituye una protección eficaz y poderosa contra los agresores.\"\n  STR_PWT_DEFENSES_UFOPEDIA: \"Los torpedos de ondas de impulsos TOI son lo mejor contra los ataques alienígenas. Estos misiles tienen cabezas de gran densidad capaces de atravesar cualquier blindaje, y emiten ondas magnéticas que anulan las defensas electrónicas\"\n  STR_BOMBARDMENT_SHIELD_UFOPEDIA: \"El escudo de resonancia anti bombardeos evita que sumergibles alienígenas atraquen en la base, y crea un campo de resonancia que repele los ataques submarinos dando tiempo suficiente para que los sistemas de defensa abran fuego a discreción. Así se duplica la eficacia de otros sistemas de defensa ya en activo.\"\n  STR_MC_GENERATOR_UFOPEDIA: \"Puesto que los submarinos alienígenas emplean la tecnología de Control Molecular para detectar formas de vida, podemos usar un emisor que contrarreste dicha tecnología, y así escudar la base y ocultar nuestra presencia.\"\n  STR_MC_LAB_UFOPEDIA: \"El Laboratorio de Control Molecular puede implantar y entrenar a diez aquanautas a la vez. Realizan un implante en el cráneo de los aquanautas, quienes aprenden a usarlos con un entrenamiento intensivo. Esta técnica se utiliza conjuntamente con dispositivos moleculares que pueden emplearse para atacar en el combate.\"\n  STR_TRANSMISSION_RESOLVER_UFOPEDIA: \"Las comunicaciones alienígenas emplean la red de implantes por control molecular que ellos mismos han creado. El descodificador tarns intercepta las transmisiones de submarinos enemigos y descodifica la información. Muestra el tipo de submarino, la raza alienígena y qué actividad está en curso.\"\n  STR_SUB_PEN_UFOPEDIA: \"Cada muelle puede cobijar un aerosubmarino y cuenta con instalaciones para el mantenimiento, reabastecimiento y reparación de la flota de X-Com. Cada aerosubmarino atracado en una base debe tener un muelle reservado exclusivamente para él, incluso cuando ha salido en una misión.\"\n  STR_DART_PISTOL_UFOPEDIA: \"El lanzadardos de X-Com es una unidad pequeña, precisa y de gran potencia con un cargador de 12 dardos que son disparados por un cartucho de gas.\"\n  STR_JET_HARPOON_UFOPEDIA: \"Dispara de forma precisa arpones de acero, que van en bloques sellados de 10. Cada uno tiene su reserva de gas individual.\"\n  STR_GAS_CANNON_UFOPEDIA: \"El peso pesado de las armas de gas es el cañón de proyectiles sólidos con la punta altamente explosiva AE o de fósforo; la preferida de los aquanautas.\"\n  STR_HYDRO_JET_CANNON_UFOPEDIA: \"Los Cañones Hidrojet son un sistema de arma de infantería pesada. El cañón dispara mini-torpedos alimentados con magnesio. Aunque potente, el Cañón Hidrojet es un dispositivo torpe e inmanejable, adecuado solo para uso acuático.\"\n  STR_TORPEDO_LAUNCHER_UFOPEDIA: \"Este gran lanzatorpedos, un auténtico peso pesado, dispara tres tipos de proyectiles, cada uno con su unidad propulsora. Un arma devastadora, la única pega es que es de carga manual. La munición puede ser: torpedos grandes o pequeños con punta altamente explosiva AE o punta de fósforo P, todos para ataques submarinos.\"\n  STR_GAUSS_PISTOL_UFOPEDIA: \"La pistola Gauss emplea la reciente tecnología de aceleración de partículas. Rápida y precisa, funciona dentro y fuera del agua. La tecnología Gauss se desarrolló a partir de la de Plasma, nacida en la guerra anterior.\"\n  STR_GAUSS_PISTOL_CLIP_UFOPEDIA: \"La pistola Gauss emplea la reciente tecnología de aceleración de partículas. Rápida y precisa, funciona dentro y fuera del agua. La tecnología Gauss se desarrolló a partir de la de Plasma, nacida en la guerra anterior.\"\n  STR_GAUSS_RIFLE_UFOPEDIA: \"El rifle Gauss supera a la pistola: lleva dos aceleradores de partículas. Se ha reemplazado el sistema Plasma accionado por elerio y se ha colocado un acelerador de micropartículas que genera una estela de antiprotones.\"\n  STR_GAUSS_RIFLE_CLIP_UFOPEDIA: \"El rifle Gauss supera a la pistola: lleva dos aceleradores de partículas. Se ha reemplazado el sistema Plasma accionado por elerio y se ha colocado un acelerador de micropartículas que genera una estela de antiprotones.\"\n  STR_HEAVY_GAUSS_UFOPEDIA: \"El Gauss pesado es algo engorroso pero muy eficaz. Funciona con 3 aceleradores de partículas y es prácticamente imparable. La estela de antiprotones está confinada en una cápsula de arseniuro de galio que explota al hacer impacto y suelta la antimateria.\"\n  STR_HEAVY_GAUSS_CLIP_UFOPEDIA: \"El Gauss pesado es algo engorroso pero muy eficaz. Funciona con 3 aceleradores de partículas y es prácticamente imparable. La estela de antiprotones está confinada en una cápsula de arseniuro de galio que explota al hacer impacto y suelta la antimateria.\"\n  STR_MAGNA_BLAST_GRENADE_UFOPEDIA: \"Esta granada estándar tiene un temporizador sofisticado y preciso para un control más exacto.\"\n  STR_DYE_GRENADE_UFOPEDIA: \"Las granadas Dye cumplen dos funciones y son muy útiles cuando se está al descubierto. Funcionan tanto en tierra como en agua y salen proyectadas como una nube de partículas: en el agua sueltan una especie de tinta como si fueran un calamar, y en el aire crean una cortina de humo.\"\n  STR_PARTICLE_DISTURBANCE_GRENADE_UFOPEDIA: \"Una granada de proximidad que se puede lanzar como las normales, pero lo que la activa es el movimiento que se produzca cerca de ella. Se necesitan habilidad y práctica para utilizarlas.\"\n  STR_MAGNA_PACK_EXPLOSIVE_UFOPEDIA: \"Este explosivo debe emplearse únicamente para demolición. La experiencia ha demostrado que estos poderosos explosivos son armas ideales para eliminar de raíz a los alienígenas. La onda expansiva es muy grande, así que debes asegurarte de que los aquanautas están a una distancia segura.\"\n  STR_PARTICLE_DISTURBANCE_SENSOR_UFOPEDIA: \"Este nuevo dispositivo emplea sistemas informáticos y una variedad de detectores para identificar a las unidades enemigas en movimiento. Presione el icono del Sensor de Perturbaciones en la pantalla táctica. Elige 'Usar sensor' en el menú. En el centro del sensor aparece una flecha que indica la dirección en la que mira el aquanauta (el Norte es la de arriba). Los 'bips' indican unidades que se han movido recientemente. Las unidades grandes o las que se desplazan rápidamente emiten 'bips' largos. Las que están paradas no aparecerán en la pantalla.\"\n  STR_MEDI_KIT_UFOPEDIA: \"Para utilizar esto debes ponerte enfrente del agente de X-Com herido o colocarte junto a un aquanauta aturdido.{NEWLINE}REMEDIO> El rojo indica heridas. Elige una parte del cuerpo y dale al botón de 'Curar'. Se curarán las heridas mortales y el individuo recuperar la salud.{NEWLINE}ESTIMULANTE> Ayuda a recuperar la energía y reaviva a un aquanauta aturdido. Para ello debes colocarte justo al lado del cuerpo del aquanauta inconsciente.{NEWLINE}CALMANTE> Le sube la moral a un aquanauta herido.\"\n  STR_MC_DISRUPTOR_UFOPEDIA: \"Lo último en tecnología de Control Molecular. Sólo pueden usarlo, los aquanautas con habilidades en C.M. Presione en el Disruptor, elige un tipo de ataque y selecciona un objetivo con el cursor. Hay 2 tipos de ataques:{NEWLINE}INTERFERIR IMPLANTE> Si el ataque tiene éxito, reducirá la moral del objetivo con la probabilidad de inducir panico.{NEWLINE}CONTROLAR IMPLANTE> Si este ataque es exitoso, ganara control de la unidad enemiga.\"\n  STR_THERMAL_TAZER_UFOPEDIA: \"Este dispositivo sólo se puede usar en el combate cuerpo a cuerpo y aturde a un organismo vivo, congelándolo sin llegar a matarlo.\"\n  STR_VIBRO_BLADE_UFOPEDIA: \"La Vibroespada es un arma blanca larga y afilada cuya hoja está hecha de titanio. Gira a 600 rpm y puede perforar el blindaje más duro. Su fuente motriz es de invención alienígena. Nuestros intentos de fabricar un arma de este tipo, han fracasado: las hojas giraban demasiado despacio o explotaban con la presión.\"\n  STR_THERMIC_LANCE_UFOPEDIA: \"La Lanza Térmica ha derivado de la tecnología de la Vibroespada. La hoja gira a gran velocidad y un motor de Zrbita la calienta de modo que puede cortar un blindaje como si fuera mantequilla.\"\n  STR_HEAVY_THERMIC_LANCE_UFOPEDIA: \"La lanza térmica pesada es una versión más potente de la lanza térmica normal. Dos fuentes de calor y una asombrosa velocidad de rotación hacen que esta lanza atraviese cualquier tipo de material.\"\n  STR_SONIC_CANNON_UFOPEDIA: \"El Cañón Sónico es la más potente de la familia de las armas sónicas. Presenta un oscilador auditivo de mayor radio y una cámara reverberante más grande que el rifle. También tiene un sistema de detonación de impulsos que altera la onda ultra-sónica por modulación, produciendo un impacto sónico más eficaz.\"\n  STR_CANNON_POWER_CLIP_UFOPEDIA: \"Este compacto artefacto se usa como munición para el Cañón Sónico. Contiene una pequeña cantidad de Zrbita.\"\n  STR_SONIC_BLASTA_RIFLE_UFOPEDIA: \"Un dispositivo sónico más poderoso. Ni siquiera el acero rico en carbono es inmune a esta arma. El compacto emisor de ondas se ha mejorado con un súper amplificador conductor que aumenta la potencia del arma.\"\n  STR_BLASTA_POWER_CLIP_UFOPEDIA: \"Este pequeño objeto es la fuente de energía de un Rifle Sónico, una potente arma alienígena que lleva algo de Zrbita.\"\n  STR_SONIC_PISTOL_UFOPEDIA: \"Las Pistolas Sónicas son un arma alienígena que emplea ondas ultra-sónicas para convertir los huesos en gelatina en cuestión de segundos. Estos sonidos no pueden ser captados por el oído humano.\"\n  STR_PISTOL_POWER_CLIP_UFOPEDIA: \"Fuente de energía de la compacta Pistola Sónica alienígena. Lleva Zrbita, la fuente de toda la energía alienígena.\"\n  STR_DISRUPTOR_PULSE_LAUNCHER_UFOPEDIA: \"Es un arma alienígena acuática que lanza proyectiles de disrupción auto-impulsados y dirigibles. Al pulsar para disparar el arma, aparecerán puntos en el mapa que indican el rumbo del proyectil. Cuando hayas colocado los puntos suficientes, pulsa el icono de lanzar proyectiles.\"\n  STR_DISRUPTOR_AMMO_UFOPEDIA: \"Este aparato es un Proyectil Disruptor de Impulsos que lleva instalado un sistema de guía por ordenador. Lo dispara un lanza proyectiles de disrupción.\"\n  STR_THERMAL_SHOK_LAUNCHER_UFOPEDIA: \"Un pequeño lanza proyectiles de impacto térmico que dispara bombas químicas de congelación. Muy útil para capturar vivos a los alienígenas.\"\n  STR_THERMAL_SHOK_BOMB_UFOPEDIA: \"La Bomba de Impacto Térmico se usa para capturar vivos a los humanos, pero también se puede usar contra las razas alienígenas. La dispara un Cañón de Impacto Térmico.\"\n  STR_SONIC_PULSER_UFOPEDIA: \"Este artefacto funciona igual que una granada normal, pero es mucho más poderoso, y emplea un rayo sónico que sale en todas las direcciones a la vez.\"\n  STR_MC_READER_UFOPEDIA: \"Hemos encontrado pequeñas unidades implantadas en los alienígenas. Son los Implantes de Control creados por los aquatoides, que suministran información desde el campo de batalla, incluso a grandes distancias. El Lector de Control Molecular es un aparato de comunicaciones alienígena que extrae información de los implantes por C.M.; las unidades X-Com lo pueden usar en combate para ver las características de un alienígena. Selecciona la opción 'Usar' y luego pulsa con el cursor en un alienígena.\"\n  STR_SURVEY_SHIP: \"Nave de reconocimiento\"\n  STR_ESCORT: \"Escolta\"\n  STR_CRUISER: \"Crucero\"\n  STR_HEAVY_CRUISER: \"Crucero pesado\"\n  STR_HUNTER: \"Cazador\"\n  STR_BATTLESHIP: \"Acorazado\"\n  STR_DREADNOUGHT: \"Acorazado pesado\"\n  STR_FLEET_SUPPLY_CRUISER: \"Crucero de suministros\"\n  MAP_SEABED: \"Lecho Marino\"\n  MAP_PIPES: \"Instalación de investigación\"\n  MAP_PLANE: \"Avión hundido\"\n  MAP_ATLAN: \"Atlántida\"\n  MAP_MU: \"Templo Maya\"\n  MAP_GAL: \"Galeón hundido\"\n  MAP_MSUNK: \"Barco de línea hundido\"\n  MAP_VOLC: \"Volcánico\"\n  MAP_CORAL: \"Coral\"\n  MAP_PORT: \"Puerto\"\n  MAP_ISLAND: \"Isla\"\n  MAP_CARGO: \"Buque de Carga\"\n  MAP_LINERT: \"Crucero P1\"\n  MAP_LINERB: \"Crucero P2\"\n  MAP_ALART: \"Artefacto P1\"\n  MAP_GRUNGE: \"Artefacto P2\"\n  MAP_ENTRY: \"Colonia P1\"\n  MAP_A_BASE: \"Colonia P2\"\n  MAP_ALSHIP: \"T'leth P1\"\n  MAP_LEVEL: \"T'leth P2\"\n  MAP_CRYPT: \"T'leth P3\"\n  MAP_XBASES: \"Base X-Com\"\n  STR_MIXED_CREW: \"Tripulación combinada\"\n  STR_MIXED_CREW_2: \"Tripulación combinada 2\"\n  STR_RATING: \"EVALUACION> {0}\"\n  STR_RATING_TERRIBLE: \"¡TERRIBLE!\"\n  STR_RATING_POOR: \"¡MAL!\"\n  STR_RATING_OK: \"BIEN\"\n  STR_RATING_GOOD: \"¡BUENO!\"\n  STR_RATING_EXCELLENT: \"¡EXCELENTE!\"\n  STR_SCORE: \"PUNTUACIóN\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"INFORME MENSUAL DEL PROYECTO DE XCOM\"\n  STR_MONTH: \"Mes> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"El comité de naciones patrocinadoras está satisfecho con los progresos que has hecho hasta el momento.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"El comité de naciones patrocinadoras está muy satisfecho con los progresos que has hecho hasta el momento. Sigue así.\"\n  STR_COUNCIL_IS_DISSATISFIED: \"El comité de naciones patrocinadoras no está satisfecho con tu actuación. Debes ser más eficaz a la hora de enfrentarte a la amenaza alienígena o te arriesgas a que se suspenda el proyecto.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"Has fracasado en tu lucha contra la invasión alienígena y el comité de naciones patrocinadoras se ha visto obligado a cancelar el proyecto. Cada nación se enfrentará al problema como pueda. Esperamos que sea posible llegar a un acuerdo con estas fuerzas aparentemente hostiles y que la población se adapte a la presencia de los visitantes alienígenas.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} esta particularmente satisfecho con tu forma de hacer frente a la amenaza y accede a aumentar su financiación.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} están particularmente contentos con tus avances haciendo frente a la incursión alienígena local y han accedido a aumentar sus fondos.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} y {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} no esta contento con tu forma de hacer frente a la actividad alienígena en su territorio y ha decidido reducir su aportación económica.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} no estan contentos con tu forma de hacer frente a la actividad alienígena en su territorio y han decidido reducir su aportación económica.\"\n  STR_KNOTS: \"{0} nudos\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} han firmado un pacto secreto con fuerzas alienígenas desconocidas y han abandonado el proyecto.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} han firmado un pacto secreto con fuerzas alienígenas desconocidas y han abandonado el proyecto.\"\n  STR_MONTHLY_RATING: \"Valoración mensual> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Cambio de financiación> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"El consejo de naciones no esta contento con tu situación económica. Debes reducir tus deudas por debajo de 1 millón de dólares o el proyecto será cancelado.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"TRANSMISIóN DE SUBPARTíCULAS RESUELTA\"\n  STR_CRAFT_TYPE: \"Tipo de Sub\"\n  STR_RACE: \"RAZA\"\n  STR_MISSION: \"MISIÓN\"\n  STR_ZONE: \"ZONA\"\n  STR_ALLOCATE_RESEARCH: \"Asignar investigación\"\n  STR_ALLOCATE_MANUFACTURE: \"Asignar fabricación\"\n  STR_AZORES: \"Las Azores\"\n  STR_REYKJAVIK: \"Reykjavik\"\n  STR_BERMUDA: \"Las Bermudas\"\n  STR_NEW_YORK: \"Nueva York\"\n  STR_BOSTON: \"Boston\"\n  STR_FORT_SEVERN: \"Fort Severn\"\n  STR_DAKAR: \"Dakar\"\n  STR_RECIFE: \"Recife\"\n  STR_ACCRA: \"Acra\"\n  STR_ASCENSION_ISLAND: \"Isla Ascensión\"\n  STR_TRINIDADE_ISLAND: \"Isla de Trinidad\"\n  STR_FALKLAND_ISLAND: \"Islas Malvinas\"\n  STR_CANARY_ISLANDS: \"Islas Canarias\"\n  STR_ANCHORAGE: \"Anchorage\"\n  STR_ST_LAWRENCE_ISLAND: \"Isla San Lorenzo\"\n  STR_SAN_FRANCISCO: \"San Francisco\"\n  STR_MIDWAY_ISLAND: \"Islas Midway\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_TASMANIA: \"Tasmania\"\n  STR_HAWAII: \"Hawaii\"\n  STR_FIJI: \"Fiji\"\n  STR_TONGA: \"Tonga\"\n  STR_EASTER_ISLAND: \"Isla de Pascua\"\n  STR_GALAPAGOS_ISLAND: \"Islas Galápagos\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_SOLOMON_ISLAND: \"Islas Salomón\"\n  STR_CRETE: \"Creta\"\n  STR_LISBON: \"Lisboa\"\n  STR_PORT_SAID: \"Puerto Saíd\"\n  STR_MARSEILLES: \"Marsella\"\n  STR_TRIPOLI: \"Tripoli\"\n  STR_MANILA: \"Manila\"\n  STR_HONG_KONG: \"Hong Kong\"\n  STR_SINGAPORE: \"Singapur\"\n  STR_BANGKOK: \"Bangkok\"\n  STR_DARWIN: \"Darwin\"\n  STR_BOMBAY: \"Bombay\"\n  STR_SAYCHELLES_ISLAND: \"Seychelles\"\n  STR_MALDIVE_ISLAND: \"Las Maldivas\"\n  STR_SRI_LANKA: \"Sri Lanka\"\n  STR_MAURITIUS: \"Mauritius\"\n  STR_TOKYO: \"Tokio\"\n  STR_SHANGHAI: \"Shanghai\"\n  STR_VLADIVOSTOK: \"Vladivostok\"\n  STR_LONDON: \"Londres\"\n  STR_FAEROE_ISLAND: \"Islas Feroe\"\n  STR_ABERDEEN: \"Aberdeen\"\n  STR_OSLO: \"Oslo\"\n  STR_JAMAICA: \"Jamaica\"\n  STR_PANAMA: \"Panama\"\n  STR_MIAMI: \"Miami\"\n  STR_PSI_TRAINING: \"Entrenam. C.M.\"\n  STR_PSIONIC_TRAINING: \"ENTRENAMIENTO DE CONTROL MOLECULAR\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Capacidad del lab. C.M.> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"Fuerza{NEWLINE}C.M.\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"Mejora de {NEWLINE}/Habilidad C.M.\"\n  STR_IN_TRAINING: \"¿De{NEWLINE}entrenamiento?\"\n  STR_TARGETTED_BY: \"OBJETIVO DE:\"\n  STR_WEAPONS_CREW_HWPS: \"ARMAS/{NEWLINE}TRIPULACIÓN/SAS\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"tiene poco combustible,{NEWLINE}regresa a la base\"\n  STR_SOLDIER_LIST: \"Lista de Aquanautas\"\n  STR_RANK_: \"RANGO> {ALT}{0}\"\n  STR_MISSIONS: \"MISIONES> {ALT}{0}\"\n  STR_KILLS: \"MUERTES> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"RECUPERACION DE HERIDAS> {ALT}{0}\"\n  STR_TIME_UNITS: \"UNIDADES DE TIEMPO\"\n  STR_STAMINA: \"AGUANTE\"\n  STR_HEALTH: \"SALUD\"\n  STR_BRAVERY: \"CORAJE\"\n  STR_REACTIONS: \"REFLEJOS\"\n  STR_FIRING_ACCURACY: \"PUNTERÍA\"\n  STR_THROWING_ACCURACY: \"PRECISIÓN\"\n  STR_STRENGTH: \"FUERZA\"\n  STR_PSIONIC_STRENGTH: \"FUERZA C.M.\"\n  STR_PSIONIC_SKILL: \"HABILIDAD C.M.\"\n  STR_NEW_RANK: \"NUEVO RANGO\"\n  STR_PROMOTIONS: \"Ascensos\"\n  STR_SOLDIERS_UC: \"AQUANAUTAS\"\n  STR_COELACANTH_GAS_CANNON_UFOPEDIA: \"Los SAS automáticos tienen mucha maniobrabilidad y un casco resistente. Son un fuerte apoyo para las tropas a cualquier profundidad. Si tienes suficiente munición se recargan automáticamente.\"\n  STR_COELACANTH_AQUA_JET_UFOPEDIA: \"Este sumergible va armado con Torpedos. Es una unidad mejor que el cañón de gas. Asegúrate de que los almacenes están bien surtidos de estos torpedos.\"\n  STR_COELACANTH_GAUSS_UFOPEDIA: \"La tecnología Gauss proporciona un poderoso sistema de armamento para los sistemas de armas sumergibles SAS. Mayor potencia de fuego que los primeros modelos y tecnología propia de X-Com.\"\n  STR_DISPLACER_SONIC_UFOPEDIA: \"La tecnología alienígena ha rediseñado los SAS. Ahora emplean Desplazadores de Iones, así que su uso ya no se restringe al fondo marino y la tierra firme. El armamento sónico supone una gran ventaja en el combate.\"\n  STR_DISPLACER_PWT_UFOPEDIA: \"Este tanque sumergible lleva armas acuáticas de Ondas de Impulsos. Para mantenerlas cargadas debes fabricar Torpedos de Ondas de Impulsos TOI. Para disparar marca en el mapa varias coordenadas del rumbo que han de seguir y pulsa el icono de lanzamiento\"\n  STR_ALIEN_PROBE_MISSION: \"Misión de Exploración\"\n  STR_ALIEN_INTERDICTION: \"Interdicción Alienígena\"\n  STR_ALIEN_RESOURCE_RAID: \"Asalto Alienígena por recursos\"\n  STR_ALIEN_INFILTRATION: \"Infiltración Alienígena\"\n  STR_ALIEN_BASE: \"Expansión de Colonia Alienígena\"\n  STR_ALIEN_SURFACE_ATTACK: \"Ataques Alien en Superficie\"\n  STR_ALIEN_RETALIATION: \"Ataque a Base Flotante\"\n  STR_ALIEN_SUPPLY: \"Misiones de Suministro a Colonias\"\n  STR_ALIEN_PROBE_MISSION_UFOPEDIA: \"La misión de exploración alienígena se usa para comparar datos sobre el lecho marino, los recursos y las rutas de navegación y vuelo de una zona. Los submarinos que participan en estas misiones no son una gran amenaza, pero indican focos de actividad que pueden estallar en cualquier momento.\"\n  STR_ALIEN_INTERDICTION_UFOPEDIA: \"Los alienígenas siempre patrullan las zonas que les interesan enviando naves con el propósito de asegurar la zona antes de comenzar misiones más en profundidad. Si quieren atacar un lugar, desembarcarán en él para asegurarlo y preparar el camino para la siguiente fase.\"\n  STR_ALIEN_RESOURCE_RAID_UFOPEDIA: \"La clave estratégica alienígena está en hundir naves y abatir aviones.Una de sus actividades primordiales es adquirir materiales y de ahí sus acciones abiertamente agresivas. También atacan zonas de actividad geotérmica, zonas mineras lugares con tradición de ser ricos en minerales, en metales preciosos y en objetos fabricados por el hombre.\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"Esto puede acabar en un contacto oficial al más alto nivel entre alienígenas y las corporaciones o gobiernos.El clímax de esta situación es una actividad intensa en aguas de la organización interesada. Los alienígenas intentarán firmar un acuerdo con un gobierno u organización ofreciéndoles su avanzada tecnología. Esta actividad alienígena supone una gran amenaza para X-Com. Si una corporación o gobierno coopera con los invasores, cesará su financiación a X-Com.\"\n  STR_ALIEN_BASE_UFOPEDIA: \"Los alienígenas construirán colonias submarinas secretas en zonas remotas. Tras ciertos vuelos iniciales de reconocimiento, comenzará una actividad intensa de submarinos mientras construyen una colonia. En ellas hay laboratorios,centros de clonación y quirófanos para experimentos humanos y alienígenas. Estas colonias generarán más presencia alienígena sin la presencia de sus submarinos. Para localizar una colonia, un submarino de X-Com debe patrullar por una zona durante una serie de horas si quiere tener alguna posibilidad de éxito.\"\n  STR_ALIEN_SURFACE_ATTACK_UFOPEDIA: \"Cuando los alienígenas necesitan humanos, amenazan un puerto atacan una isla o abordan un nave. Los civiles son amenazados directamente, para cubrir las necesidades de los alienígenas y sus horribles experimentos.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"Si los Submarinos interceptores de X-Com hunden muchas naves alienígenas, los enemigos podrían tomar represalias. Ello podría acabar en un ataque directo contra las instalaciones de X-Com. Sin embargo, si quieren atacarnos, primero deben encontrar la base X-Com y si se mantiene alejados a los Submarinos enemigos, el peligro de ataque es menor.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"Una vez que una colonia alienígena está construida, comienza a recibir abastecimientos, traídos por una nave especial. Si se detecta a una de éstas cuando va a atracar, es que hay una colonia cerca.\"\n  STR_SURVEY_SHIP_UFOPEDIA: \"Este mini submarino se emplea para misiones de reconocimiento e investigación. Suele preceder a grandes navíos, encabezando una fuerza operativa.\"\n  STR_ESCORT_UFOPEDIA: \"Un buque escolta de tamaño medio que no supone una gran amenaza si va solo. Precede a otros buques de mayor tamaño y preludia gran actividad.\"\n  STR_CRUISER_UFOPEDIA: \"El crucero es un barco multiuso, el sostén de la flota enemiga, y se usa en toda clase de misiones alienígenas: un peligroso adversario.\"\n  STR_HEAVY_CRUISER_UFOPEDIA: \"El crucero pesado es una nave más poderosa que el crucero, con armas mayores y sistemas de propulsión. Se usa para misiones de búsqueda de recursos: recogida de minerales y equipo.\"\n  STR_HUNTER_UFOPEDIA: \"Este buque va equipado con una sala de examen para realizar experimentos y operaciones con humanos. Las víctimas son horriblemente torturadas y se les suele extirpar el cerebro, que es almacenado y estudiado durante el viaje.\"\n  STR_BATTLESHIP_UFOPEDIA: \"El acorazado es el más agresivo del grupo alienígena. Tiene todos los sistemas y avances tecnológicos para actuar como base de operaciones de cualquier tipo de acto agresivo. Lleva una amplia gama de armamento.\"\n  STR_DREADNOUGHT_UFOPEDIA: \"El acorazado pesado es un transportador de tropas, equipado con toda la tecnología alienígena y con carga útil. Es un adversario duro y formidable.\"\n  STR_FLEET_SUPPLY_CRUISER_UFOPEDIA: \"El buque de suministros se emplea durante la construcción de bases alienígenas y para llevar suministros a las ya existentes. Transporta contenedores de alimentos para alienígenas y cámaras de reproducción.\"\n  STR_DISMANTLE: \"Desmantelar\"\n  STR_FACILITY_IN_USE: \"COMPARTIMIENTO ACUÁTICO EN USO\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"¡NO SE PUEDE DESMANTELAR LA INSTALACIóN!{SMALLLINE}Todas las instalaciones de la base deben estar unidas ala esclusa de acceso.\"\n  STR_TRANSFER_ITEMS_TO: \"Transferir elementos a {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"NO HAY UNIDAD DE CONTENCION PARA TRASLADO!{SMALLLINE}Los alienígenas necesitan una unidad de contencion para sobrevivir.\"\n  STR_AMOUNT_AT_DESTINATION: \"CANTIDAD EN{NEWLINE}DESTINO\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"Alienígena muere porque no hay unidad de contención.\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"NO HAY ALOJAMIENTO{SMALLLINE}La base de destino no tiene suficiente espacio para la tripulación de la nave.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"¡INSUFICIENTE ESPACIO DE ALMACENAMIENTO!{SMALLLINE}La base de destino no tiene espacio suficiente para almacenar el equipo asignado al submarino.\"\n  STR_ITEMS_ARRIVING: \"Artículos trasladados\"\n  STR_DESTINATION_UC: \"DESTINO\"\n  STR_DART_PISTOL: \"Lanza-dardos\"\n  STR_DART_POD: \"Dardos\"\n  STR_JET_HARPOON: \"Lanza-arpones\"\n  STR_HARPOON_POD: \"Arpones\"\n  STR_GAS_CANNON: \"Cañón de Gas\"\n  STR_GC_AP_AMMO: \"Munición CG-PB\"\n  STR_GC_HE_AMMO: \"Munición CG-AE\"\n  STR_GC_P_AMMO: \"Munición CG-Fósforo\"\n  STR_HYDRO_JET_CANNON: \"Cañón Hidrojet\"\n  STR_HJC_AP_AMMO: \"Munición PB del CH\"\n  STR_HJC_HE_AMMO: \"Munición AE del CH\"\n  STR_HJC_P_AMMO: \"Munición F del CH\"\n  STR_TORPEDO_LAUNCHER: \"Lanzatorpedos\"\n  STR_SMALL_TORPEDO: \"Torpedo Pequeño\"\n  STR_LARGE_TORPEDO: \"Torpedo Grande\"\n  STR_PHOSPHOROUS_TORPEDO: \"Torpedo de Fósforo\"\n  STR_MAGNA_BLAST_GRENADE: \"Granada de Gran Impacto\"\n  STR_DYE_GRENADE: \"Granada Dye\"\n  STR_PARTICLE_DISTURBANCE_GRENADE: \"Granada de Partículas\"\n  STR_MAGNA_PACK_EXPLOSIVE: \"Explosivo de Demolición\"\n  STR_PARTICLE_DISTURBANCE_SENSOR: \"Sensor de Partículas\"\n  STR_MEDI_KIT: \"Botiquín\"\n  STR_MC_DISRUPTOR: \"Disruptor de Control Molecular\"\n  STR_THERMAL_TAZER: \"Táser Térmico\"\n  STR_GAUSS_PISTOL: \"Pistola Gauss\"\n  STR_GAUSS_PISTOL_CLIP: \"Cargador de Pistola Gauss\"\n  STR_GAUSS_RIFLE: \"Rifle Gauss\"\n  STR_GAUSS_RIFLE_CLIP: \"Cargador de Rifle Gauss\"\n  STR_HEAVY_GAUSS: \"Cañón Pesado Gauss\"\n  STR_HEAVY_GAUSS_CLIP: \"Cargador de Gauss pesado\"\n  STR_SONIC_CANNON: \"Cañón Sónico\"\n  STR_CANNON_POWER_CLIP: \"Cargador de Cañón Sónico\"\n  STR_SONIC_BLASTA_RIFLE: \"Rifle Blaster Sónico\"\n  STR_BLASTA_POWER_CLIP: \"Cargador del Rifle Sónico\"\n  STR_SONIC_PISTOL: \"Pistola Sónica\"\n  STR_PISTOL_POWER_CLIP: \"Cargador de Pistola Sónica\"\n  STR_DISRUPTOR_PULSE_LAUNCHER: \"Lanzaproyectiles de Disrupción\"\n  STR_DISRUPTOR_AMMO: \"Proyectiles de Disrupción\"\n  STR_THERMAL_SHOK_LAUNCHER: \"Lanzador Impacto Térmico\"\n  STR_THERMAL_SHOK_BOMB: \"Bomba de Impacto Térmico\"\n  STR_SONIC_PULSER: \"Granada Sónica\"\n  STR_ZRBITE: \"Zrbite\"\n  STR_MC_READER: \"Lector de Control Molecular\"\n  STR_VIBRO_BLADE: \"Vibroespada\"\n  STR_THERMIC_LANCE: \"Lanza Térmica\"\n  STR_HEAVY_THERMIC_LANCE: \"Lanza Térmica Pesada\"\n  STR_AQUATOID_CORPSE: \"Cadáver de Aquatoide\"\n  STR_GILLMAN_CORPSE: \"Cadáver de Hombre-Branquia\"\n  STR_LOBSTERMAN_CORPSE: \"Cadáver de Hombre-Langosta\"\n  STR_TASOTH_CORPSE: \"Cadáver de Tasoth\"\n  STR_CALCINITE_CORPSE: \"Cadáver de Calcinite\"\n  STR_DEEP_ONE_CORPSE: \"Cadáver de Anuroide\"\n  STR_BIODRONE_CORPSE: \"Cadáver de Telecerebro\"\n  STR_TENTACULAT_CORPSE: \"Cadáver de Tentáculat\"\n  STR_TRISCENE_CORPSE: \"Cadáver de Triscene\"\n  STR_HALLUCINOID_CORPSE: \"Cadáver de Alucinoide\"\n  STR_XARQUID_CORPSE: \"Cadáver de Calaxmar\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"No hay suficiente munición SWS para armar{SMALLLINE}Cada SWS requiere {0} {1}.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Equipo insuficiente para reequipar el escuadrón\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Necesitas investigar {NEWLINE}{0}{NEWLINE}para producir el{NEWLINE}{1}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"Los alienígenas han destruido la base indefensa {0}\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"Agentes XCom han localizado una base alienígena en {0}\"\n  STR_STANDOFF: \"APARTARSE\"\n  STR_CAUTIOUS_ATTACK: \"ATAQUE CAUTO\"\n  STR_STANDARD_ATTACK: \"ATAQUE NORMAL\"\n  STR_AGGRESSIVE_ATTACK: \"ATAQUE AGRESIVO\"\n  STR_DISENGAGING: \"ABANDONAR COMBATE\"\n  STR_UFO_HIT: \"¡SUBMARINO ALIENíGENA TOCADO!\"\n  STR_UFO_CRASH_LANDS: \"¡SUBM. ALIENíGENA DERRIBADO!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Minimizar sólo a distancia prudente.\"\n  STR_UFO_RETURN_FIRE: \"¡EL OSNI DEVUELVE EL FUEGO!\"\n  STR_INTERCEPTOR_DAMAGED: \">>> AEROSUBMARINO DAÑADO <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> AEROSUBMARINO DESTRUIDO <<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"OSNI escapando...\"\n  STR_LONG_RANGE_DETECTION: \"Detección de largo alcance\"\n  STR_STORES_UC: \"ALMACENES\"\n  STR_DIFFICULTY_LEVEL: \"Nivel de dificultad\"\n  STR_INTERCEPT: \"INTERCEPTAR\"\n  STR_BASES: \"BASES\"\n  STR_GRAPHS: \"GRÁFICOS\"\n  STR_UFOPAEDIA_UC: \"OSNIPEDIA\"\n  STR_OPTIONS_UC: \"OPCIONES\"\n  STR_FUNDING_UC: \"FINANCIACIÓN\"\n  STR_5_SECONDS: \"5 seg\"\n  STR_1_MINUTE: \"1 min\"\n  STR_5_MINUTES: \"5 min\"\n  STR_30_MINUTES: \"30 min\"\n  STR_1_HOUR: \"1 hora\"\n  STR_1_DAY: \"1 día\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"Lista de Rendimiento de X-Com\"\n  STR_ENTER_NAME: \"Introducir nombre\"\n  STR_PERFORMANCE_RATING: \"Evaluación de Rendimiento\"\n  STR_VICTORY_DATE: \"Fecha de victoria\"\n  STR_CHEMICAL_FLARE: \"Bengala\"\n  STR_CHEMICAL_FLARE_UFOPEDIA: \"Este artefacto produce una señal luminosa brillante. Ilumina a las unidades tanto amigas como enemigas que haya cerca durante misiones nocturnas.\"\n  STR_MONTHLY_COSTS: \"Gastos mensuales\"\n  STR_CRAFT_RENTAL: \"Alquiler de Aerosubmarino\"\n  STR_SALARIES: \"Salarios\"\n  STR_BASE_MAINTENANCE: \"Mantenimiento\"\n  STR_COST_PER_UNIT: \"Coste por unidad\"\n  STR_QUANTITY: \"Cantidad\"\n  STR_TOTAL: \"Total\"\n  STR_IN_PSIONIC_TRAINING: \"en C.M. \"\n  STR_FRONT_ARMOR: \"Blindaje frontal\"\n  STR_LEFT_ARMOR: \"Blindaje izquierdo\"\n  STR_RIGHT_ARMOR: \"Blindaje derecho\"\n  STR_REAR_ARMOR: \"Blindaje trasero\"\n  STR_UNDER_ARMOR: \"Blindaje inferior\"\n  STR_ROUNDS: \"Disparos\"\n  STR_UNIT: \"UNIDAD> {0}\"\n  STR_ENERGY: \"ENERGÍA\"\n  STR_MORALE: \"MORAL\"\n  STR_ARMOR_: \"BLINDAJE> {0}\"\n  STR_FRONT_ARMOR_UC: \"BLINDAJE DELANTERO\"\n  STR_LEFT_ARMOR_UC: \"BLINDAJE IZQUIERDO\"\n  STR_RIGHT_ARMOR_UC: \"BLINDAJE DERECHO\"\n  STR_REAR_ARMOR_UC: \"BLINDAJE TRASERO\"\n  STR_SKILLS: \"HABILIDADES> {0}\"\n  STR_LEVEL: \"NIVEL> {0}\"\n  STR_HEAD: \"CABEZA\"\n  STR_TORSO: \"TORSO\"\n  STR_RIGHT_ARM: \"Brazo Dcho.\"\n  STR_LEFT_ARM: \"Brazo Izdo.\"\n  STR_RIGHT_LEG: \"Pierna Dcha.\"\n  STR_LEFT_LEG: \"Pierna Izda.\"\n  STR_PAIN_KILLER: \"CALMANTE\"\n  STR_STIMULANT: \"ESTIMULANTE\"\n  STR_HEAL: \"CURAR\"\n  STR_TIME_UNITS_SHORT: \"UT>{ALT}{0}\"\n  STR_WEIGHT: \"Peso>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"Reacción>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"Habilidad M.C>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"Fuerza M.C.>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Artefacto Alienígena\"\n  STR_AMMO_ROUNDS_LEFT: \"MUNICIÓN:{NEWLINE}CARGADORES{NEWLINE}RESTANTES={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Calmar>{ALT}{0}{ALT}{NEWLINE}Estim.>{ALT}{1}{ALT}{NEWLINE}Curar>{ALT}{2}\"\n  STR_THROW: \"Lanzar\"\n  STR_AUTO_SHOT: \"Disparo auto.\"\n  STR_SNAP_SHOT: \"Disparo rápido\"\n  STR_AIMED_SHOT: \"Disparo preciso\"\n  STR_STUN: \"Aturdir\"\n  STR_PRIME_GRENADE: \"Activar granada\"\n  STR_USE_SCANNER: \"Usar Sensor de Part.\"\n  STR_USE_MEDI_KIT: \"Utilizar botiquín\"\n  STR_LAUNCH_MISSILE: \"Lanzar Torpedo\"\n  STR_ACCURACY_SHORT: \"Acc>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"¡Unidades de tiempo insuficientes!\"\n  STR_NOT_ENOUGH_ENERGY: \"¡Energía insuficiente!\"\n  STR_NO_ROUNDS_LEFT: \"¡No queda munición!\"\n  STR_NO_AMMUNITION_LOADED: \"¡El arma no está cargada!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"¡Esta munición no sirve para esta arma!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"¡El arma ya está cargada!\"\n  STR_NO_LINE_OF_FIRE: \"¡No hay línea de tiro!\"\n  STR_GRENADE_IS_ACTIVATED: \"¡La granada está activada!\"\n  STR_GRENADE_IS_DEACTIVATED: \"¡Granada desactivada!\"\n  STR_THERE_IS_NO_ONE_THERE: \"¡Allí no hay nadie!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"¡Artefacto alienígena inutilizable hasta después de investigación!\"\n  STR_OUT_OF_RANGE: \"¡Fuera de alcance!\"\n  STR_UNABLE_TO_THROW_HERE: \"¡Imposible lanzar aquí!\"\n  STR_SET_TIMER: \"Ajustar temporizador\"\n  STR_HIDDEN_MOVEMENT: \"MOVIMIENTO OCULTO\"\n  STR_TURN: \"TURNO> {0}\"\n  STR_SIDE: \"LADO> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Pulsar un botón para continuar\"\n  STR_MIND_CONTROL: \"Control Molecular\"\n  STR_PANIC_UNIT: \"Interferir Implante\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Ataque con Exito a la Moral\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Control Mental con éxito\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}ha Enloquecido\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}ha Enloquecido\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}ha entrado en pánico\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}ha entrado en pánico\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Alienígenas\"\n  STR_RIGHT_HAND: \"MANO DCHA.\"\n  STR_LEFT_HAND: \"MANO IZQ.\"\n  STR_RIGHT_SHOULDER: \"HOMBRO DCHO.\"\n  STR_LEFT_SHOULDER: \"HOMBRO IZQ.\"\n  STR_BACK_PACK: \"MOCHILA\"\n  STR_BELT: \"CINTURÓN\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}está bajo control Molecular\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}está bajo control Molecular\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}ha quedado inconsciente\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}ha quedado inconsciente\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}ha muerto de una herida mortal\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}ha muerto de una herida mortal\"\n  STR_USE_MIND_PROBE: \"Usar lector Control Molecular\"\n  STR_FATAL_WOUNDS: \"HERIDAS MORTALES\"\n  STR_UNDER_ARMOR_UC: \"BLINDAJE TRASERO\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Uni. de tiempo reservadas para disparo rápido\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Uni. de tiempo reservadas para disparo automático\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Uni. de tiempo reservadas para disparo de precisión\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Unidades de Tiempo reservadas para arrodillarse\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"UTs reservadas para arrodillarse y disparar\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} Unidad en Nave X-Com\"\n    many: \"{N} Unidades en Nave X-Com\"\n    other: \"{N} Unidades en Nave X-Com\"\n  STR_UNITS_OUTSIDE:\n    one: \"{N} Unidad abandonada\"\n    many: \"{N} Unidades abandonadas\"\n    other: \"{N} Unidades abandonadas\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} Unidad en la Entrada\"\n    many: \"{N} Unidades en la Entrada\"\n    other: \"{N} Unidades en la Entrada\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} Unidades en la Meta de Salida\"\n    many: \"{N} Unidades en la Meta de Salida\"\n    other: \"{N} Unidades en la Meta de Salida\"\n  STR_ABORT_MISSION_QUESTION: \"Abortar Misión?\"\n  STR_CORPSE: \"Cadaver\"\n  STR_UNLOAD_CRAFT: \"Descargar\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}ha muerto\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}ha muerto\"\n  STR_HIT_MELEE: \"Golpe\"\n  STR_GROUND: \"Tierra\"\n  STR_LIVING_QUARTERS_PLURAL: \"Cuarteles\"\n  STR_LIST_ITEM: \"Objeto\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"Todos los alienígenas han muerto en el accidente,{NEWLINE}Recuperación automática iniciada.\"\n  STR_RESET: \"Reiniciar\"\n  STR_MEMORIAL: \"Memorial\"\n  STR_DATE_UC: \"Fecha\"\n  STR_SOLDIERS_RECRUITED_UC: \"ACUANAUTAS RECLUTADOS>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"ACUANAUTAS PERDIDOS>{ALT}{0}\"\n  STR_REMOVE_SELECTED: \"Eliminar seleccionado\"\n  STR_LIVE_ALIENS: \"Especímenes{NEWLINE}Vivos\"\n  STR_DEAD_ALIENS: \"Especímenes{NEWLINE}Rechazados\"\n  STR_UNDER_INTERROGATION: \"Siendo{NEWLINE}Estudiados\"\n  STR_CONTAINMENT_EXCEEDED: \"¡EXCEDIDO LÍMITE DE CONTENCIÓN ALIENÍGENA!{SMALLLINE}Insuficiente espacio de contención en {0}. Debes reducir el exceso de alienígenas del compartimento (los seleccionados morirán).\"\n  STR_MANAGE_CONTAINMENT: \"Administrar Contención Alienígena\"\n  STR_STORAGE_EXCEEDED: \"¡ESPACIO DE ALMACENAJE SOBREPASADO!{SMALLLINE}Espacio de almacenamiento insuficiente en {0}. Debes vender elementos para hacer sitio.\"\n  STR_GO_TO_BASE: \"Ir a la base\"\n  STR_MELEE_ACCURACY: \"Precisión cuerpo a cuerpo\"\n  STR_SELL_PRODUCTION: \"Vender\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"¡Las dos manos tienen que estar libres!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"¡Objetos insuficientes para copiar la plantilla!\"\n  STR_UNLOAD_WEAPON: \"Descargar Arma\"\n  STR_ALL_ITEMS: \"Todos los objetos\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"¡NO MÁS EQUIPO PERMITIDO A BORDO!{SMALLLINE}solamente se le permite tomar un máximo de {N} elementos del equipo en este Submarino.\"\n    many: \"¡NO MÁS EQUIPO PERMITIDO A BORDO!{SMALLLINE}solamente se le permite tomar un máximo de {N} elementos del equipo en este Submarino.\"\n    other: \"¡NO MÁS EQUIPO PERMITIDO A BORDO!{SMALLLINE}solamente se le permite tomar un máximo de {N} elementos del equipo en este Submarino.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}CENTRO DE CONTROL DESTRUIDO{NEWLINE}Diríjase a la entrada y aborte.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"Las instalaciones acuáticas de X-Com no se pueden construir en tierra firme\"\n  STR_UNABLE_TO_ENGAGE_DEPTH: \"IMPOSIBLE ALCANZAR ENEMIGO{NEWLINE}A ESTA PROFUNDIDAD\"\n  STR_UNABLE_TO_ENGAGE_AIRBORNE: \"IMPOSIBLE ALCANZAR ENEMIGO{NEWLINE}DURANTE VUELO\"\n  STR_UNDERWATER_EQUIPMENT: \"¡Este equipo no funcionará fuera del agua!\"\n  STR_LAND_EQUIPMENT: \"¡Este equipo no funcionará bajo el agua!\"\n  STR_LEVEL_SHORT: \"L{0}\"\n  STR_PERSONNEL: \"Personal\"\n  STR_CRAFT_ARMAMENT: \"Naves y Armamento\"\n  STR_COMPONENTS: \"Componentes\"\n  STR_SOLDIERS_RECRUITED: \"Acuanautas reclutados\"\n  STR_SOLDIERS_LOST: \"Acuanautas perdidos\"\n  STR_TOTAL_UFOS: \"Submarinos volantes detectados\"\n  STR_TOTAL_ALIEN_BASES: \"Colonia alienígena descubierta\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"FCM\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"HCM\"\n  FEMALE_CIVILIAN: \"Civil, Mujer\"\n  MALE_CIVILIAN: \"Civil, Varón\"\n  DOCKER_CIVILIAN: \"Civil, Bastidor\"\n  SAILOR_CIVILIAN: \"Civil, Marinero\"\n  STR_BIODRONE_MELEE_WEAPON: \"Telecerebro cuerpo a cuerpo\"\n  HALLUCINOID_WEAPON: \"Arma de Alucinoide\"\n  STR_LOBSTERMAN_MELEE_WEAPON: \"Hombre-Langosta cuerpo a cuerpo\"\n  CALCINITE_WEAPON: \"Arma de Calcinite\"\n  DEEP_ONE_WEAPON: \"Arma de Anuroide\"\n  STR_TRISCENE_MELEE_WEAPON: \"Triscene cuerpo a cuerpo\"\n  STR_TRIBIO_SONIC_WEAPON: \"Arma Sónica Alien\"\n  XARQUID_WEAPON: \"Arma de Calaxmar\"\n  TENTACULAT_WEAPON: \"Arma de Tentáculat\"\n  ZOMBIE_WEAPON: \"Arma de Zombi\"\n  ALIEN_PSI_WEAPON: \"Arma de Control Molecular\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/et.yml",
    "content": "et:\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"UFO KESKELE-AEG=5 S\"\n  STR_CANCEL_UC: \"TÜHISTA\"\n  STR_NONE: \"Pole\"\n  STR_UNKNOWN: \"Teadmata\"\n  STR_POOR: \"Kehva\"\n  STR_AVERAGE: \"Keskmine\"\n  STR_GOOD: \"Hea\"\n  STR_EXCELLENT: \"Suurepärane\"\n  STR_BUILD_NEW_BASE_UC: \"EHITA UUS BAAS\"\n  STR_BASE_INFORMATION: \"BAASI INFORMATSIOON\"\n  STR_BUILD_FACILITIES: \"EHITA HOONEID\"\n  STR_RESEARCH: \"UURIMUSTÖÖ\"\n  STR_MANUFACTURE: \"TOOTMINE\"\n  STR_TRANSFER_UC: \"ÜLEKANNE\"\n  STR_PURCHASE_RECRUIT: \"OSTA/PALKA\"\n  STR_SACK: \"VALLANDA\"\n  STR_SELL_SACK_UC: \"Müü/Vallanda\"\n  STR_GEOSCAPE_UC: \"MAAILM\"\n  STR_NAME: \"Nimi\"\n  STR_AREA: \"Ala\"\n  STR_BUILD_NEW_BASE: \"Ehita Uus Baas\"\n  STR_CANCEL: \"Tühista\"\n  STR_COST_UC: \"HIND>\"\n  STR_CONSTRUCTION_TIME_UC: \"EHITUSAEG>\"\n  STR_DAY:\n    one: \"{N} päev\"\n    other: \"{N} päeva\"\n  STR_HOUR:\n    one: \"{N} tund\"\n    other: \"{N} tundi\"\n  STR_MAINTENANCE_UC: \"ÜLALHOID>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Installeerimine\"\n  STR_CURRENT_RESEARCH: \"HETKENE UURIMUSTÖÖ\"\n  STR_SCIENTISTS_AVAILABLE: \"Vabu  Teadlasi>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Teadlaseid Töötamas>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Labori pinda saadaval>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"UURIMIS PROJEKT\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"TEADLASED TÖÖLE PANDUD\"\n  STR_PROGRESS: \"EDASIMINEK\"\n  STR_NEW_PROJECT: \"Uus Projekt\"\n  STR_CANCEL_PROJECT: \"TÜHISTA PROJEKT\"\n  STR_NEW_RESEARCH_PROJECTS: \"UUS UURIMUSTÖÖ PROJEKT\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"TEADLASEID VABA>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"LABORIS RUUMI>{ALT}{0}\"\n  STR_INCREASE: \"Suurenda\"\n  STR_DECREASE: \"Vähenda\"\n  STR_START_PROJECT: \"ALUSTA PROJEKTIGA\"\n  STR_CURRENT_PRODUCTION: \"ALUSTA TOOTMIST\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Töökoja pinda saadaval>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Hetkel Raha>{ALT}{0}\"\n  STR_ITEM: \"ASI\"\n  STR_UNITS_PRODUCED: \"Toodetud Kogus\"\n  STR_TOTAL_TO_PRODUCE: \"Kokku Toota\"\n  STR_COST__PER__UNIT: \"Hind{NEWLINE}ühiku{NEWLINE}kohta\"\n  STR_DAYS_HOURS_LEFT: \"Päevi/Tunde Jäänud\"\n  STR_NEW_PRODUCTION: \"Uus Tootmine\"\n  STR_PRODUCTION_ITEMS: \"Tootmine\"\n  STR_CATEGORY: \"KATEGOORIA\"\n  STR_START_PRODUCTION: \"ALUSTA TOOTMIST\"\n  STR_COST_PER_UNIT_: \"Tüki hind>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Töökoja ruumi vaja>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"ERIMATERJALID VAJALIKUD\"\n  STR_ITEM_REQUIRED: \"VAJALIK ESE\"\n  STR_UNITS_REQUIRED: \"VAJALIK{NEWLINE}KOGUS\"\n  STR_UNITS_AVAILABLE: \"KOGUS{NEWLINE}SAADAVAL\"\n  STR_STOP_PRODUCTION: \"PEATA TOOTMINE\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"TOOTMISES RUUMI>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"KASU KUU KOHTA>{ALT}{0}\"\n  STR_INCREASE_UC: \"SUURENDA\"\n  STR_DECREASE_UC: \"VÄHENDA\"\n  STR_UNITS_TO_PRODUCE: \"Ühikuid Toota\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Osta/Palka Personali\"\n  STR_COST_OF_PURCHASES: \"Ostmiste Koguhind>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"TÜKI HIND\"\n  STR_QUANTITY_UC: \"KOGUS\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"PERSONALI SAADAVAL:PERSONALI KOKKU>\"\n  STR_SCIENTISTS: \"Teadlased\"\n  STR_ENGINEERS: \"Tehnikud\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"RUUMI KASUTATUD:RUUMI VABA>\"\n  STR_LIVING_QUARTERS: \"Majutus\"\n  STR_STORES: \"Poed\"\n  STR_LABORATORIES: \"Laborid\"\n  STR_WORK_SHOPS: \"Töökoda\"\n  STR_DEFENSE_STRENGTH: \"Kaitsetugevus\"\n  STR_TRANSFERS_UC: \"ÜLEKANDED\"\n  STR_TRANSFERS: \"Ülekanded\"\n  STR_ARRIVAL_TIME_HOURS: \"Jõuavad Kohale (tunnid)\"\n  STR_COST_: \"Hind>{ALT}{0}\"\n  STR_AREA_: \"Ala>{ALT}{0}\"\n  STR_BASE_NAME: \"Baasi Nimi?\"\n  STR_TRANSFER: \"Ülekanne\"\n  STR_AMOUNT_TO_TRANSFER: \"ÜLEKANDE KOGUS\"\n  STR_SELECT_DESTINATION_BASE: \"Vali Baasi Asukoht\"\n  STR_COST: \"Hind\"\n  STR_INTRO_1: \"Copyright 1995 MicroProse\"\n  STR_INTRO_5: \"Maa.\"\n  STR_TOTAL_UC: \"KOKKU\"\n  STR_INCOME: \"Sissetulek\"\n  STR_EXPENDITURE: \"Kulu\"\n  STR_MAINTENANCE: \"Korrashoid\"\n  STR_BALANCE: \"Tasakaal\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"Tulnukate aktiivsus meredel\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"Tulnukate aktiivsus tsoonides\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"X-Comi aktiivsus meredel\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"X-Comi aktiivsus tsoonides\"\n  STR_FINANCE: \"Finants\"\n  STR_DATE_FIRST: \"{0}.\"\n  STR_DATE_SECOND: \"{0}.\"\n  STR_DATE_THIRD: \"{0}.\"\n  STR_DATE_FOURTH: \"{0}.\"\n  STR_FINANCE_THOUSANDS: \"$1000.\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Liiga vähe erikomponente, et toota {NEWLINE}{0}{NEWLINE}{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Liiga vähe raha, e toota {NEWLINE}{0}{NEWLINE}{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"{NEWLINE}{0}{NEWLINE}tootmine{NEWLINE}{1}{NEWLINE} on valmis.\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"{NEWLINE}{0}{NEWLINE}ehitamine{NEWLINE}{1}{NEWLINE} on valmis.\"\n  STR_OK_5_SECONDS: \"OK - 5 s\"\n  STR_RESEARCH_COMPLETED: \"Uurimine valmis\"\n  STR_VIEW_REPORTS: \"VAATA RAPORDIT\"\n  STR_WE_CAN_NOW_RESEARCH: \"Me saame nüüd uurida\"\n  STR_WE_CAN_NOW_PRODUCE: \"Me saame nüüd uurida\"\n  STR_SUNDAY: \"PÜHAPÄEV\"\n  STR_MONDAY: \"ESMASPÄEV\"\n  STR_TUESDAY: \"TEISIPÄEV\"\n  STR_WEDNESDAY: \"KOLMAPÄEV\"\n  STR_THURSDAY: \"NELJAPÄEV\"\n  STR_FRIDAY: \"REEDE\"\n  STR_SATURDAY: \"LAUPÄEV\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Liiga vähe {0} et tankida {1} {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Pole piisavalt {0} ,et taasrelvastada {1} {2}\"\n  STR_ALIENS_DEFEATED: \"Tulnukat hävitatud\"\n  STR_BASE_IS_LOST: \"Baas kaotatud\"\n  STR_BASE_IS_SAVED: \"Baas päästetud\"\n  STR_ALIEN_BASE_STILL_INTACT: \"Tulnukate koloonia on ikka veel töökorras\"\n  STR_ALIEN_BASE_DESTROYED: \"Tulnukate koloonia hävitatud\"\n  STR_ALIENS_KILLED: \"TAPETUD TULNUKAID\"\n  STR_ALIEN_CORPSES_RECOVERED: \"Tulnukate kaasa toodud karkassid\"\n  STR_LIVE_ALIENS_RECOVERED: \"Elusalt tabatud tulnukad\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"Tulnukate vidinad leitud\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"TULNUKATE POOLT TAPETUD TSIVIILE\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"X-COMI POOLT TAPETUD TSIVIILID\"\n  STR_CIVILIANS_SAVED: \"PÄÄSTETUD TSIVIILID\"\n  STR_XCOM_OPERATIVES_KILLED: \"LANGENUD X-COM OPERATIIVTÖÖTAJAD\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"LAHINGUS KADUMA JÄÄNUD X-COMI OPERATIIVTÖÖTAJAD\"\n  STR_BASE_UNDER_ATTACK: \"{0} rünnatakse!\"\n  STR_BASE_DEFENSES_INITIATED: \"BAASI KAITSEMEHHANISMID ALUSTATUD\"\n  STR_FIRING: \"TULISTAMINE\"\n  STR_HIT: \"PIHTAS!\"\n  STR_UFO_DESTROYED: \"TULNUKAS HÄVITATUD!\"\n  STR_MISSED: \"MÖÖDA!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Müü Asju/Vallanda Personali\"\n  STR_SELL_SACK: \"Müü/Vallanda\"\n  STR_VALUE: \"Väärtus\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_BASE_DEFENSE: \"BAASI KAITSE\"\n  STR_BASE_UC_: \"BAAS> {0}\"\n  STR_NO_FREE_ACCOMODATION: \"POLE ROHKEM VOODIKOHTI!{SMALLLINE}Baasis pole rohkem eluruumi.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"POLE PIISAVALT TÖÖKOJA RUUMI SAADAVAL!{SMALLLINE}Ehita uus töökoda või vähenda teiste projektide tööd.\"\n  STR_NOT_ENOUGH_MONEY: \"POLE PIIRAVALT RAHA!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"POLE PIISAVALT LAORUUMI!{SMALLLINE}Ehitage uus laoruum või viige osad kaubad üle teise baasi.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"POLE PIISAVALT ELURUUME!{SMALLLINE}Ehita juurde eluruume või vii kaadrit üle teistesse baasidesse.\"\n  STR_CRAFT: \"ALUS\"\n  STR_STATUS: \"STAATUS\"\n  STR_BASE: \"BAAS\"\n  STR_READY: \"VALMIS\"\n  STR_OUT: \"VÄLJAS\"\n  STR_REPAIRS: \"PARANDUSED\"\n  STR_REFUELLING: \"KÜTUSE TANKIMINE\"\n  STR_REARMING: \"ÜMBER RELVASTUMINE\"\n  STR_TARGET: \"SIHTMÄRK: {0}\"\n  STR_ARE_YOU_SURE_CYDONIA: \"Oled kindel, et soovid seda allveelaeva saata T'lethi missioonile?\"\n  STR_YES: \"JAH\"\n  STR_NO: \"EI\"\n  STR_SELECT_DESTINATION: \"VALI ASUKOHT\"\n  STR_CYDONIA: \"T'LETH\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"VALI UUE BAASI ASUKOHT\"\n  STR_RETURN_TO_BASE: \"TAGASI BAASI\"\n  STR_SELECT_NEW_TARGET: \"VALI UUS SIHTMÄRK\"\n  STR_PATROL: \"PATRULL\"\n  STR_STATUS_: \"STAATUS>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"VIGASTATU - BAASI NAASMINE\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"KÜTUST VÄHE - NAASEME BAASI\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"ÜLESANNE TÄIDETUD - NAASEME BAASI\"\n  STR_PATROLLING: \"PATRULLIMAS\"\n  STR_RETURNING_TO_BASE: \"TAGASI BAASI\"\n  STR_DESTINATION_UC_: \"SIHTPUNKT: {0}\"\n  STR_BASE_UC: \"BAAS>{ALT}{0}\"\n  STR_SPEED_: \"KIIRUS>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"TIPPKIIRUS>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"SÜGAVUS>{ALT}{0}\"\n  STR_AIRBORNE: \"ÕHUS\"\n  STR_VERY_LOW: \"MADAL\"\n  STR_LOW_UC: \"NORMAALNE\"\n  STR_HIGH_UC: \"SÜGAV\"\n  STR_VERY_HIGH: \"VÄGA SÜGAV\"\n  STR_FUEL: \"KÜTUS>{ALT}{0}\"\n  STR_WEAPON_ONE: \"RELV-1>{ALT}{0}\"\n  STR_NONE_UC: \"EI OLE\"\n  STR_ROUNDS_: \"LASKE>{ALT}{0}\"\n  STR_WEAPON_TWO: \"RELV-2>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"LENDAV ALLVEELAEV\"\n  STR_BASE_: \"Baas>{0}\"\n  STR_NAME_UC: \"NIMI\"\n  STR_AMMO_: \"LASKEMOON>{ALT}{0}\"\n  STR_CREW: \"MEESKOND\"\n  STR_EQUIPMENT_UC: \"VARUSTUS\"\n  STR_ARMOR: \"TURVIS\"\n  STR_MAX: \"MAKS.>{ALT}{0}\"\n  STR_COLONEL: \"Komandör\"\n  STR_COMMANDER: \"Kapten\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Vali meeskond {0} jaoks\"\n  STR_SORT_BY: \"SORTEERI\"\n  STR_ORIGINAL_ORDER: \"ORIGINAALNE JÄRJESTUS\"\n  STR_MISSIONS2: \"MISSIOONID\"\n  STR_KILLS2: \"VÕIDUD\"\n  STR_WOUND_RECOVERY2: \"HAAVADES PARANEMINE\"\n  STR_SPACE_AVAILABLE: \"VABARUUMI>{ALT}{0}\"\n  STR_RANK: \"AUASTE\"\n  STR_WOUNDED: \"HAAVATUD\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Varustus {0}\"\n  STR_DEFENSE_VALUE: \"Kaitse väärtus\"\n  STR_HIT_RATIO: \"Tabamisprotsent\"\n  STR_BEGIN_MISSION: \"Alusta Missiooni?\"\n  STR_SELECT_ARMAMENT: \"Vali relvastus\"\n  STR_AMMUNITION_AVAILABLE: \"OLEMASOLEV LASKEMOON\"\n  STR_ARMAMENT: \"RELVASTUS\"\n  STR_NOT_AVAILABLE: \"PUUDUB\"\n  STR_TYPE: \"TÜÜP\"\n  STR_SELECT_ARMOR: \"Vali Turvise\"\n  STR_NORTH: \"PÕHI\"\n  STR_NORTH_EAST: \"KIRRE\"\n  STR_EAST: \"IDA\"\n  STR_SOUTH_EAST: \"KAGU\"\n  STR_SOUTH: \"LÕUNA\"\n  STR_SOUTH_WEST: \"EDEL\"\n  STR_WEST: \"LÄÄS\"\n  STR_NORTH_WEST: \"LOE\"\n  STR_SELECT_ACTION: \"VALI TEGEVUS\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"JÄTKA RÜNNAKUT\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"JÄLITA ILMA RÜNDAMATA\"\n  STR_VERY_LARGE: \"VÄGA SUUR\"\n  STR_LARGE: \"SUUR\"\n  STR_MEDIUM_UC: \"KESKMINE\"\n  STR_SMALL: \"VÄIKE\"\n  STR_VERY_SMALL: \"VÄGA VÄIKE\"\n  STR_DETECTED: \"Avastatud\"\n  STR_SIZE_UC: \"SUURUS\"\n  STR_HEADING: \"KURSS\"\n  STR_SPEED: \"KIIRUS\"\n  STR_TRACKING_LOST: \"KADUS RADARILT\"\n  STR_REDIRECT_CRAFT: \"SUUNA ALUS ÜMBER\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}jõudis{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"Patrullimas\"\n  STR_ALIEN_ORIGINS: \"Tulnukate päritolu\"\n  STR_UFOPAEDIA: \"UFOpedia\"\n  STR_SELECT_ITEM: \"Vali\"\n  STR_ACCELERATION: \"KIIRENDUS>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"KÜTUSE MAHUTUVUS>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Kahjustused\"\n  STR_RANGE: \"Raadius\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Täpsus\"\n  STR_RE_LOAD_TIME: \"Laadimis aeg\"\n  STR_SECONDS: \"{0} sek\"\n  STR_DAMAGE_ARMOR_PIERCING: \"SOOMUSLÄBISTATAVUS\"\n  STR_DAMAGE_MELEE: \"KÄSIVÕITLUS\"\n  STR_DAMAGE_ACID: \"HAPE\"\n  STR_DAMAGE_SMOKE: \"SUITS\"\n  STR_SHOT_TYPE: \"TÜÜP\"\n  STR_ACCURACY_UC: \"TÄPSUS\"\n  STR_TIME_UNIT_COST: \"AÜ MAKSUMUS\"\n  STR_DAMAGE_UC: \"KAHJUSTUSED\"\n  STR_AMMO: \"LASKEMOON\"\n  STR_SHOT_TYPE_AUTO: \"Automaatne\"\n  STR_SHOT_TYPE_SNAP: \"Puusalt\"\n  STR_SHOT_TYPE_AIMED: \"Sihitud\"\n  STR_CONSTRUCTION_TIME: \"Ehitus aeg\"\n  STR_CONSTRUCTION_COST: \"Ehitus Hind\"\n  STR_MAINTENANCE_COST: \"Korrashoiu hind\"\n  STR_LOW: \"Madal\"\n  STR_MEDIUM: \"Keskmine\"\n  STR_HIGH: \"Kõrge\"\n  STR_WEAPON: \"Relv\"\n  STR_AMMUNITION: \"Laskemoon\"\n  STR_EQUIPMENT: \"Varustus\"\n  STR_ALIEN_CORPSE: \"Tulnuka laip\"\n  STR_PERSONAL_ARMOR: \"Isiklik Turvis\"\n  STR_RAW_MATERIALS: \"Toorained\"\n  STR_ALIEN: \"Tulnukas\"\n  STR_ZOMBIE: \"Zombie\"\n  STR_LIVE_COMMANDER: \"Komandör\"\n  STR_LIVE_NAVIGATOR: \"Navigaator\"\n  STR_LIVE_MEDIC: \"Meedik\"\n  STR_LIVE_TECHNICIAN: \"Tehnik\"\n  STR_LIVE_SOLDIER: \"Sõdur\"\n  STR_LIVE_TERRORIST: \"Terrorist\"\n  STR_EXAMINATION_ROOM: \"Uurimisruum\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Uus hävitus-transporter\"\n  STR_ARMOR_PIERCING: \"SOOMUSLÄBISTATAVUS\"\n  STR_SCIENTIST: \"Teadlane\"\n  STR_ENGINEER: \"Tehnik\"\n  STR_NORTH_ATLANTIC: \"Põhja-Atlant\"\n  STR_SOUTH_ATLANTIC: \"Lõuna-Atlant\"\n  STR_INDIAN_OCEAN: \"India Ookean\"\n  STR_ARCTIC: \"Arktika\"\n  STR_NORTH_AMERICA: \"Põhja-Ameerika\"\n  STR_MAXIMUM_SPEED: \"Tippkiirus\"\n  STR_WEAPON_RANGE: \"Relva Ulatuvus\"\n  STR_LABORATORY: \"Labor\"\n  STR_WORKSHOP: \"Töökoda\"\n  STR_GENERAL_STORES: \"Laoruumid\"\n  STR_ALIEN_CONTAINMENT: \"Tulnukate vangla\"\n  STR_USA: \"USA\"\n  STR_ALASKA: \"ALASKA\"\n  STR_EU_SYNDICATE: \"EURO-SÜNDIKAAT\"\n  STR_ARABIAN_BLOC: \"ARAABIA BLOKK\"\n  STR_EGYPTIAN_CARTEL: \"EGIPTUSE KARTELL\"\n  STR_AFRICA_CORP: \"AAFRIKA KORP\"\n  STR_BRAZILIAN_UNION: \"BRASIILIA UNIOON\"\n  STR_NEW_MEXICO: \"UUS_MEHHIKO\"\n  STR_ASIAN_COALITION: \"AASIA KOALITSIOON\"\n  STR_SCANDINAVIA: \"SKANDINAAVIA\"\n  STR_NEO_JAPAN: \"NEO-JAAPAN\"\n  STR_FREE_CHINA: \"VABA HIINA\"\n  STR_AUSTRALASIA: \"AUSTRALAASIA\"\n  STR_FED_KOREA: \"KOREA FÖD\"\n  STR_EURASIA_UC: \"EURAASIA\"\n  STR_ICELANDIC_UNION: \"ISLANDLIK UNIOON\"\n  STR_CIVILIAN: \"Tsivilist\"\n  STR_JAN: \"Jan\"\n  STR_FEB: \"Veeb\"\n  STR_MAR: \"Mär\"\n  STR_APR: \"Apr\"\n  STR_MAY: \"Mai\"\n  STR_JUN: \"Jun\"\n  STR_JUL: \"Jul\"\n  STR_AUG: \"Aug\"\n  STR_SEP: \"Sept\"\n  STR_OCT: \"Okt\"\n  STR_NOV: \"Nov\"\n  STR_DEC: \"Dets\"\n  STR_INTERNATIONAL_RELATIONS: \"Rahvusvahelised suhted\"\n  STR_COUNTRY: \"Riik\"\n  STR_FUNDING: \"Rahastus\"\n  STR_CHANGE: \"Muuda\"\n  STR_WEAPON_SYSTEMS: \"RELVASÜSTEEMID\"\n  STR_DAMAGE_UC_: \"KAHJUSTUSED>{ALT}{0}\"\n  STR_MAGNA_BLAST_GRENADE_UFOPEDIA: \"Standartne granaat oma keerulist kuid täpset ajamõõtjat.\"\n  STR_BATTLESHIP: \"Lahinglaev\"\n  MAP_ISLAND: \"Saar\"\n  MAP_XBASES: \"X-Com Baas\"\n  STR_RATING: \"HINNANG> {0}\"\n  STR_RATING_TERRIBLE: \"KOHUTAV!\"\n  STR_RATING_POOR: \"KEHVA!\"\n  STR_RATING_OK: \"OK\"\n  STR_RATING_GOOD: \"HEA!\"\n  STR_RATING_EXCELLENT: \"SUUREPÄRANE!\"\n  STR_SCORE: \"SKOOR\"\n  STR_MONTH: \"Kuu> {ALT}{0} {1}\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} on eriti rahul teie tegevusega kohaliku ohu neutraliseerimisega ning on nõustunud rahastust suurendama.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} ja {1}\"\n  STR_KNOTS: \"{0} sõlme\"\n  STR_RACE: \"RASS\"\n  STR_MISSION: \"MISSIOON\"\n  STR_ZONE: \"TSOON\"\n  STR_ALLOCATE_RESEARCH: \"Määra teaduslik töö\"\n  STR_ALLOCATE_MANUFACTURE: \"Määra tootmine\"\n  STR_AZORES: \"Assoori\"\n  STR_REYKJAVIK: \"Reykjavik\"\n  STR_BERMUDA: \"Bermuda\"\n  STR_NEW_YORK: \"New York\"\n  STR_BOSTON: \"Boston\"\n  STR_FORT_SEVERN: \"Fort Severn\"\n  STR_DAKAR: \"Dakar\"\n  STR_RECIFE: \"Recife\"\n  STR_ACCRA: \"Accra\"\n  STR_ASCENSION_ISLAND: \"Ascensioni saar\"\n  STR_TRINIDADE_ISLAND: \"Trinidadi saar\"\n  STR_FALKLAND_ISLAND: \"Falklandi saar\"\n  STR_CANARY_ISLANDS: \"Kanaari saared\"\n  STR_ANCHORAGE: \"Anchorage\"\n  STR_ST_LAWRENCE_ISLAND: \"St Lawrence saar\"\n  STR_SAN_FRANCISCO: \"San Francisco\"\n  STR_MIDWAY_ISLAND: \"Midway saar\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_TASMANIA: \"Tasmaania\"\n  STR_HAWAII: \"Hawaii\"\n  STR_FIJI: \"Fiji\"\n  STR_TONGA: \"Tonga\"\n  STR_EASTER_ISLAND: \"Lihavõtte saar\"\n  STR_GALAPAGOS_ISLAND: \"Galapagose saar\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_SOLOMON_ISLAND: \"Soolomoni saar\"\n  STR_CRETE: \"Kreeta\"\n  STR_LISBON: \"Lissabon\"\n  STR_PORT_SAID: \"Port Said\"\n  STR_MARSEILLES: \"Marseilles\"\n  STR_TRIPOLI: \"Tripoli\"\n  STR_MANILA: \"Manila\"\n  STR_HONG_KONG: \"Hong Kong\"\n  STR_SINGAPORE: \"Singapur\"\n  STR_BANGKOK: \"Bangkok\"\n  STR_DARWIN: \"Darwin\"\n  STR_BOMBAY: \"Bombay\"\n  STR_SAYCHELLES_ISLAND: \"Seišellide saar\"\n  STR_MALDIVE_ISLAND: \"Maldiviidi saar\"\n  STR_SRI_LANKA: \"Sri Lanka\"\n  STR_MAURITIUS: \"Mauriitius\"\n  STR_TOKYO: \"Tokio\"\n  STR_SHANGHAI: \"Shanghai\"\n  STR_VLADIVOSTOK: \"Vladivastok\"\n  STR_LONDON: \"London\"\n  STR_FAEROE_ISLAND: \"Fääri Saared\"\n  STR_ABERDEEN: \"Aberdeen\"\n  STR_OSLO: \"Oslo\"\n  STR_JAMAICA: \"Jamaica\"\n  STR_PANAMA: \"Panama\"\n  STR_MIAMI: \"Miami\"\n  STR_IN_TRAINING: \"Treenimisel?\"\n  STR_TARGETTED_BY: \"SIHIKUL:\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"kütus hakkab otsa saama,{NEWLINE}naaseme baasi.\"\n  STR_RANK_: \"AUASTE> {ALT}{0}\"\n  STR_MISSIONS: \"MISSIOONID> {ALT}{0}\"\n  STR_KILLS: \"TAPMISED>{ALT}{0}\"\n  STR_WOUND_RECOVERY: \"HAAVADEST PARANEMINE> {ALT}{0}\"\n  STR_TIME_UNITS: \"AJA ÜHIKUD\"\n  STR_STAMINA: \"VASTUPIDAVUS\"\n  STR_HEALTH: \"TERVIS\"\n  STR_BRAVERY: \"JULGUS\"\n  STR_REACTIONS: \"REAKTSIOONID\"\n  STR_FIRING_ACCURACY: \"LASKE TÄPSUS\"\n  STR_THROWING_ACCURACY: \"VISKE TÄPSUS\"\n  STR_STRENGTH: \"TUGEVUS\"\n  STR_NEW_RANK: \"UUS AUASTE\"\n  STR_PROMOTIONS: \"Edutamised\"\n  STR_DISMANTLE: \"Lammuta\"\n  STR_TRANSFER_ITEMS_TO: \"Suuna asjad {0}sse\"\n  STR_ITEMS_ARRIVING: \"Saabuvad asjad\"\n  STR_DESTINATION_UC: \"SIHTPUNKT\"\n  STR_MEDI_KIT: \"Ravimikott\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Pole piisavalt varustust, et rühma täielikult uuesti relvastuda.\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Peate avastama kõigepealt {NEWLINE}{0}{NEWLINE}et toota {NEWLINE}{1}\"\n  STR_STANDOFF: \"HOIA KAUGUST\"\n  STR_CAUTIOUS_ATTACK: \"ETTEVAATLIK RÜNNAK\"\n  STR_STANDARD_ATTACK: \"STANDARD RÜNNAK\"\n  STR_AGGRESSIVE_ATTACK: \"AGRESIIVNE RÜNNAK\"\n  STR_DISENGAGING: \"EEMALDU\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Minimiseeri ainult mittelähenemise korral.\"\n  STR_STORES_UC: \"LADU\"\n  STR_DIFFICULTY_LEVEL: \"Raskustase\"\n  STR_INTERCEPT: \"RÜNDA\"\n  STR_BASES: \"BAASID\"\n  STR_GRAPHS: \"DIAGRAMMID\"\n  STR_OPTIONS_UC: \"VALIKUD\"\n  STR_FUNDING_UC: \"RAHASTUS\"\n  STR_5_SECONDS: \"5 s\"\n  STR_1_MINUTE: \"1 Min\"\n  STR_5_MINUTES: \"5 Min\"\n  STR_30_MINUTES: \"30 Min\"\n  STR_1_HOUR: \"1 Tund\"\n  STR_1_DAY: \"1 Päev\"\n  STR_ENTER_NAME: \"Sisesta Nimi\"\n  STR_VICTORY_DATE: \"Võidu Kuupäev\"\n  STR_MONTHLY_COSTS: \"Kuu maksumus\"\n  STR_CRAFT_RENTAL: \"Lendava allveelaeva rent\"\n  STR_SALARIES: \"Palgad\"\n  STR_BASE_MAINTENANCE: \"Baasi kulud\"\n  STR_COST_PER_UNIT: \"Tüki hind\"\n  STR_QUANTITY: \"Kogus\"\n  STR_TOTAL: \"Kokku\"\n  STR_FRONT_ARMOR: \"Eesmine Turvis\"\n  STR_LEFT_ARMOR: \"Vasak Turvis\"\n  STR_RIGHT_ARMOR: \"Parem Turvis\"\n  STR_REAR_ARMOR: \"Tagumine Turvis\"\n  STR_UNDER_ARMOR: \"Alumine Turvis\"\n  STR_UNIT: \"ÜKSUS> {0}\"\n  STR_ENERGY: \"ENERGIA\"\n  STR_MORALE: \"MORAAL\"\n  STR_ARMOR_: \"TURVIS> {0}\"\n  STR_FRONT_ARMOR_UC: \"EESMINE TURVIS\"\n  STR_LEFT_ARMOR_UC: \"VASAK TURVIS\"\n  STR_RIGHT_ARMOR_UC: \"PAREM TURVIS\"\n  STR_REAR_ARMOR_UC: \"TAGUMINE TURVIS\"\n  STR_SKILLS: \"OSKUSED> {0}\"\n  STR_LEVEL: \"TASE> {0}\"\n  STR_HEAD: \"PEA\"\n  STR_TORSO: \"KEHA\"\n  STR_RIGHT_ARM: \"PAREM KÄSI\"\n  STR_LEFT_ARM: \"VASAK KÄSI\"\n  STR_RIGHT_LEG: \"PAREM JALG\"\n  STR_LEFT_LEG: \"VASAK JALG\"\n  STR_PAIN_KILLER: \"VALUVAIGISTI\"\n  STR_STIMULANT: \"STIMULANT\"\n  STR_HEAL: \"RAVIDA\"\n  STR_TIME_UNITS_SHORT: \"TU>{ALT}{0}\"\n  STR_WEIGHT: \"Kaal>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"Reakts>{ALT}{0}\"\n  STR_AMMO_ROUNDS_LEFT: \"LASKEMOON:{NEWLINE}KUULE{NEWLINE}ALLES={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Valuvaigisti>{ALT}{0}{ALT}{NEWLINE}Stim>{ALT}{1}{ALT}{NEWLINE}Ravi>{ALT}{2}\"\n  STR_THROW: \"Viska\"\n  STR_AUTO_SHOT: \"Valang\"\n  STR_SNAP_SHOT: \"Lask puusalt\"\n  STR_AIMED_SHOT: \"Sihitud Lask\"\n  STR_STUN: \"Uimastama\"\n  STR_PRIME_GRENADE: \"Aktiveeri Granaat\"\n  STR_USE_MEDI_KIT: \"Ravima\"\n  STR_ACCURACY_SHORT: \"Acc>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Pole piisavalt ajaühikuid\"\n  STR_NOT_ENOUGH_ENERGY: \"Pole piisavalt energiat\"\n  STR_NO_ROUNDS_LEFT: \"Kuulid otsas!\"\n  STR_NO_AMMUNITION_LOADED: \"Laskemoon laadimata!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Laskemoon ei sobi sellele relvale!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"Relv juba laetud!\"\n  STR_NO_LINE_OF_FIRE: \"Puudub tulejoon!\"\n  STR_GRENADE_IS_ACTIVATED: \"Granaat Aktiveeritud!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Granaat deaktiveeritud\"\n  STR_THERE_IS_NO_ONE_THERE: \"Seal pole kedagi!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Ilma uuringuta tulnukate asju kasutada ei saa!\"\n  STR_OUT_OF_RANGE: \"Väljaspool ulatuvust\"\n  STR_UNABLE_TO_THROW_HERE: \"Pole võimalik visata sinna!\"\n  STR_SET_TIMER: \"Määra aeg\"\n  STR_HIDDEN_MOVEMENT: \"PEIDETUD LIIKUMINE\"\n  STR_TURN: \"KÄIK> {0}\"\n  STR_SIDE: \"POOL> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Väjuta nuppu, et jätkata\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Rünnak moraalile õnnestus\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}läks Segaseks\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}läks Segaseks\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}on Paanikas\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}on Paanikas\"\n  STR_XCOM: \"X-COM\"\n  STR_ALIENS: \"Tulnukad\"\n  STR_RIGHT_HAND: \"Paremkäsi\"\n  STR_LEFT_HAND: \"VASAK KÄSI\"\n  STR_RIGHT_SHOULDER: \"PAREM ÕLG\"\n  STR_LEFT_SHOULDER: \"VASAK ÕLG\"\n  STR_BACK_PACK: \"SELJAKOTT\"\n  STR_BELT: \"VÖÖ\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}kaotas teadvuse\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}kaotas teadvuse\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}suri haavadesse\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}suri haavadesse\"\n  STR_USE_MIND_PROBE: \"Kasuta mõistulugejat\"\n  STR_FATAL_WOUNDS: \"SURMAVAD HAAVAD\"\n  STR_UNDER_ARMOR_UC: \"ALUMINE TURVIS\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Ajaühikud reserveeritud puusalt lasuks\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Ajaühikud reserveeritud valanguks\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Ajaühikud reserveeritud täpsuslasuks\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Ajaühikud reserveeritud põlvitamiseks\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"Ajaühikud reserveeritud põlvili tulistamiseks\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} üksust X-Comi sõidukis\"\n    other: \"{N} üksust X-Comi sõidukis\"\n  STR_ABORT_MISSION_QUESTION: \"Abordi Missioon\"\n  STR_CORPSE: \"Laip\"\n  STR_UNLOAD_CRAFT: \"Lae tühjaks\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}tapetud\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}tapetud\"\n  STR_HIT_MELEE: \"Pihtas\"\n  STR_GROUND: \"MAAPIND\"\n  STR_LIVING_QUARTERS_PLURAL: \"Majutus\"\n  STR_LIST_ITEM: \"ASI\"\n  STR_RESET: \"Taasta\"\n  STR_MEMORIAL: \"Memoriaal\"\n  STR_DATE_UC: \"KUUPÄEV\"\n  STR_REMOVE_SELECTED: \"Eemalda Valitud\"\n  STR_MANAGE_CONTAINMENT: \"Manageeri tulnukhoidlat\"\n  STR_STORAGE_EXCEEDED: \"LAORUUMID ON TÄIS!{SMALLLINE}{0} pole rohkem ruumi asjade jaoks, olete sunnitud üleliigse maha müüma.\"\n  STR_GO_TO_BASE: \"Mine Baasi\"\n  STR_MELEE_ACCURACY: \"LÄHIVÕITLUSE TÄPSUS\"\n  STR_SELL_PRODUCTION: \"MÜÜ\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Mõlemad käed peavad olema tühjad\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Pole piisavalt varustust malli kopeerimiseks!\"\n  STR_UNLOAD_WEAPON: \"Eemalda laskemoonasalv.\"\n  STR_ALL_ITEMS: \"Kogu inventar\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}JUHTIMISKESKUS HÄVITATUD!{NEWLINE}Siirdu algusesse ja katkesta.\"\n  STR_UNDERWATER_EQUIPMENT: \"See riistvara ei tööta vee peal!\"\n  STR_LAND_EQUIPMENT: \"See riistvara ei tööta vee all!\"\n  STR_LEVEL_SHORT: \"T{0}\"\n  STR_PERSONNEL: \"Personal\"\n  STR_CRAFT_ARMAMENT: \"Lennukid & Kahurid\"\n  STR_COMPONENTS: \"Komponendid\"\n  FEMALE_CIVILIAN: \"Tsiviilisik, naine\"\n  MALE_CIVILIAN: \"Tsiviilisik, mees\"\n  DOCKER_CIVILIAN: \"Tsiviilisik, dokitööline\"\n  SAILOR_CIVILIAN: \"Tsiviilisik, madrus\"\n  ZOMBIE_WEAPON: \"Zombie relv\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/fi.yml",
    "content": "fi:\n  STR_LEVIATHAN_UFOPEDIA: \"ÄÄRIMMÄISIIN SYVYYKSIIN YLTÄVÄ KULJETUS- JA HÄVITTÄJÄLENTOSUKELLUSVENE. LOISTAVA MUUKALAIS- JA IHMISTEKNOLOGIAN SYNTEESI, JOKA HYÖDYNTÄÄ IONITYÖNTÖVOIMANLÄHDE-JÄRJESTELMIÄ JA MAGNEETTIKENTTÄNAVIGOINTIA.\"\n  STR_BARRACUDA_UFOPEDIA: \"BRITISH HYDROSPACEN BARRAKUDA, VOIMANLÄHTEENÄÄN YLIKUUMENNETUT LASERMOOTTORIT, ON YKSI MAAILMAN NOPEIMMISTA HÄVITTÄJÄALUKSISTA. SE KYKENEE SEKÄ SUKELTAMAAN ETTÄ LENTÄMÄÄN, MINKÄ ANSIOSTA SE ON AVAINASEMASSA TULEVASSA TAISTOSSA.\"\n  STR_HAMMERHEAD_UFOPEDIA: \"KULJETUS- JA HÄVITTÄJÄALUS, JOKA JÄLJITTELEE MAGNEETTIKENTTÄJÄRJESTELMIÄ X-COM-ALUKSESSA. VAIKKA SE ON PIENIKOKOINEN, SEN SUUNNITTELU ON HENKEÄSALPAAVA TEKNINEN SAAVUTUS.\"\n  STR_TRITON_UFOPEDIA: \"TRITON ON ISKURYHMÄN KULJETUSALUS, JOKA ON SOVITETTU TÄYTEEN LENTOON JA SUKELLUKSEEN KYKENEVILLÄ MOOTTOREILLA. SEN SUURI KANTOKYKY JA VANKKA RAKENNE TAKAAVAT SEN ASEMAN X-COM-LAIVASTON KANTAVANA VOIMANA.\"\n  STR_MANTA_UFOPEDIA: \"RAUSKU ON NOPEA YHDEN MIEHEN HÄVITTÄJÄLENTOSUKELLUSVENE, JOKA MUISTUTTAA LÄHEISESTI MUUKALAISTEN IONIKÄYTTÖISIÄ ALUKSIA. SE ON HYVIN TEHOKAS ISKUALUS KIIHTYVÄSSÄ KONFLIKTISSA.\"\n  STR_AJAX_UFOPEDIA: \"AJAX-TORPEDO ON MERENALAISEN SODANKÄYNNIN VAKIOASE MAAILMANLAAJUISESTI, JOKA ON TARKKA JA TEHOKAS PELOTE. \"\n  STR_DUP_HEAD_UFOPEDIA: \"KÖYHDYTETYT URAANIPELLETTIKÄRJET OVAT SUHTEELLISEN UUTTA ASETEKNOLOGIAA, JA TÄMÄ ON ENSIMMÄINEN KAUPALLINEN VEDENALAINEN ASEJÄRJESTELMÄ, JOKA HYÖDYNTÄÄ SITÄ TÄYSIMITTAISESTI.\"\n  STR_CRAFT_GAS_CANNON_UFOPEDIA: \"TYKKI, JONKA TOIMINTA PERUSTUU PURISTETTUUN KAASUUN, AMMUKSINAAN KOKOVAIPPANUOLET, JOILLA ON KORKEA PANSSARINLÄPÄISYKYKY. \"\n  STR_PWT_CANNON_UFOPEDIA: \"KANTTIAALTOTORPEDO HYÖDYNTÄÄ YLIKUUMENNUKSEEN PERUSTUVAA POLTTOAINEJÄRJESTELMÄÄ SEKÄ ÄÄRIMMÄISEN TIHEÄÄ TAISTELUKÄRKEÄ, JOKA PYSTYY LÄPÄISEMÄÄN USEIMMAT METALLISEOKSET.\"\n  STR_GAUSS_CANNON_UFOPEDIA: \"GAUSS-ASE ON HILJATTAIN KEHITETTY X-COM-TEKNOLOGIA. TÄMÄN JÄRJESTELMÄN HIUKKASKIIHDYTIN KÄYTTÄÄ VOIMANLÄHTEENÄÄN KOMPAKTIA NESTETYPPIJÄÄHDYTTEISTÄ FUUSIOREAKTORIA.\"\n  STR_SONIC_OSCILLATOR_UFOPEDIA: \"TEHOKAS AUDITIIVINEN VÄRÄHTELIJÄ TUOTTAA ÄÄNIVOIMA-AALTOJA, JONKA VÄRÄHTELYT TUHOAVAT KOHTEEN MOLEKYYLISIDOKSET.\"\n  STR_AQUATOID_UFOPEDIA: \"Akvatoidien yhteiskunta on muinainen, ja se on ollut olemassa vuosituhansia ennen ihmiskunnan haparoivia ensiaskelia maan päällä. Niiden pieni muotonsa sekä sipulimaiset piirteensä muistuttavat sektoideja, avaruudessa vaeltavia veljiään. Niiden voima perustuu vahvaan molekulaariseen hallintateknologiaan. Lisääntymiskyvyttömät akvatoidit pyrkivät lisääntymään geenimuuntelulla, jonka ihanteelliset koekappaleet ovat ihmiset. Kokeista on syntynyt lukuisia risteytyslajeja.\"\n  STR_AQUATOID_AUTOPSY: \"Akvatoidin ruumiinavaus\"\n  STR_AQUATOID_AUTOPSY_UFOPEDIA: \"Yksityiskohtaisen analyysin perusteella voimme olettaa tämän olennon olevan sektoidi, entisiä vihollisiamme, mutta joka on kirurgisten implanttien avulla muunnettu akvaattiseksi olennoksi. Surkastuneet keuhkot mahdollistavat hengittämisen ilmassa ja rajoitetun liikkuvuuden maanpinnalla. Yltympäri ruumista on kyberneettisiä implantteja, jotka parantavat näivettyneiden raajojen voimaa ja elinten toimintakykyä. Koska kaikki tämän lajin yksilöt ovat keskenään identtisiä, voimme olettaa näiden olentojen olevan klooneja.\"\n  STR_GILLMAN_UFOPEDIA: \"Outo lähes ihmisenkaltainen olio, joka vaikuttaa olevan liskohumanoidi, hyvin läheistä sukua ihmiselle. Tämä olento on hyvin voimakas ja nopea merenalaisessa maailmassa. Kidusihminen on oikea kokonainen laji eri ikäisine mies- ja naisyksilöineen. Toisin kuin enemmistössä vedenalaisista muukalaisista, niissä ei ole merkkejä geenimuuntelusta tai kirurgisista epämuodostumista. On mahdollista, että olemme tarkastelemassa oman lajimme jotain muinaista haaraa. \"\n  STR_GILLMAN_AUTOPSY: \"Kidusihmisen ruumiinavaus\"\n  STR_GILLMAN_AUTOPSY_UFOPEDIA: \"Ruumiinavauksesta kävi selväksi, että tämä ei ole muukalainen, vaan maasta lähtöisin oleva olento, muinainen esihistoriallinen laji, jonka luultiin kuolleen sukupuuttoon nisäkkäiden valtakauden alkaessa. Nämä maalla ja vedessä elävät, älykkäät ja voimakkaat kidusihmiset elivät samaan aikaan dinosaurusten kanssa. Liskojen valtakauden päättänyt luonnonmullistus pakotti nämä olennot symbioottiseen vuorovaikutussuhteeseen vasta saapuneiden muukalaisten kanssa. Pieni elektroninen laite on istutettu näiden olentojen pääkalloihin.\"\n  STR_LOBSTERMAN_UFOPEDIA: \"Tämä on ällistyttävä olento: ihmistä pidempi ja kuusiraajainen, se muistuttaa mitä enemmissä määrin akvaattista demonia. Tämän olennon sekä maan hummerin välisten samankaltaisuuksien myötä se on ansainnut X-Com-joukkojen keskuudessa lempinimekseen hummerimies. Tämä on mahtava syvyyden hirviö, huolella suunniteltu ja uskomattoman voimakas taisteluolento, joka on käytännössä haavoittumaton ohjustulelle. Sen sakset yksinään pystyvät murskaamaan terästä.\"\n  STR_LOBSTERMAN_AUTOPSY: \"Hummerimiehen ruumiinavaus\"\n  STR_LOBSTERMAN_AUTOPSY_UFOPEDIA: \"Tämän olennon käytännössä läpäisemättömän panssarin alla piilee hämmästyttävä rakenne: Voimakkaat lihakset mutkittelevat titaanitukirangan ympärillä, ja kehittynyt tähtäyslaitteisto monikaistaisella skannauskyvyllä on kytketty suoraan olennon aivoihin. Sen lukuisia silmiä suojaa terästä vahvempi muovi, ja on selvää, että isäntiensä hyvin käyttäminä nämä olennot ovat lähes pysäyttämättömiä. Syvällä sen ruumiin sisällä on kätkettyinä laitteita, joiden rakennetta ja tarkoitusta emme tunne.\"\n  STR_TASOTH_UFOPEDIA: \"Nämä ketterät ja nopeat viholliset ovat muukalaisarmeijan tuki ja turva. Satoja synnytetään valtavissa kasvatussammioissa syvällä muukalaisyhdyskuntien sydämessä. Ihmistä paljon voimakkaampi tasootti on aito muukalainen, ja sen käyttäytyminen sekä luontainen lihansyöntivietti ovat planeetassa vertaansa vailla. Tasootit toimivat usein muukalaishyökkäyksen keihäänkärkenä eivätkä ikinä vaikuta vetäytyvän taistelusta musertavankin ylivoiman kohdatessa.\"\n  STR_TASOTH_AUTOPSY: \"Tasootin ruumiinavaus\"\n  STR_TASOTH_AUTOPSY_UFOPEDIA: \"Leikkaus paljasti kyberneettisen organismin, jolla on outo voimanlähde. Ruumiinontelon sisällä on pieni voimanlähde, muttei lainkaan tunnistettavia elimiä. Voimansiirto tapahtuu biosähköisen voimansiirtojärjestelmän välityksellä. Koko ruumiissa ei ole luita tai muuta tukirankaa. Olennon kuoltua voimansiirto lakkaa ja se muuttuu elottomaksi räsynukeksi täynnä muukalaislihaa ja nesteitä. Ainoa muu sisäinen rakenne on keraaminen sähköpari, joka sähköistyksen yhteydessä hetkellisesti elvyttää olion henkiin.\"\n  STR_DEEP_ONE_UFOPEDIA: \"Syväläinen on biologinen painajainen, risteytys, joka on akvatoidien kieroutuneiden kokeiden tuotos. Olemme kohdanneet useita muunnelmia tästä olennosta. Laajan tutkimuksen perusteella päättelemme, että nämä ovat hyökkääjien valmistamia rivintäydennyksiä, kun tuoretta ihmiskantaa on kaapattu. Kukin näistä ali-ihmisistä on aseistettu sähköisellä energiapurkauksella, joka on riittävän tehokas tappamaan akvanautin.\"\n  STR_DEEP_ONE_AUTOPSY: \"Syväläisen ruumiinavaus\"\n  STR_DEEP_ONE_AUTOPSY_UFOPEDIA: \"Olento on ihmisen ja muukalaisorganismin risteytys. Ihmisaivoja on muunneltu massiivisesti sovittamaan niihin ohjauselektroniikkaa ja muukalaisaivokuoren. Kaikki jäljet ihmisruumiista näyttävät hävinneen silmiä lukuun ottamatta. Kirurginen siirre vaikuttaa sallivan muukalaissikiön kasvaessaan tuhota ihmisisäntänsä. Olion kestävä iho näyttää olevan äärimmäisen luja ja taipuisa ei-orgaaninen metalliverkko. Tuloksena on voimakas ja nopea risteymä, joka on täydellisesti muukalaisten hallinnassa.\"\n  STR_BIODRONE_UFOPEDIA: \"Biodroidi on luomus, jollaisen ainoastaan muukalaismieli voisi kuvitella. Se on lapsivedessä säilötyt (ihmis- tai muukalais)aivot, jotka on yhdistetty alustaan, joka kykenee lentämään maalla ja veden alla. Jokainen biodroidi on aseistettu tehokkaalla auditiivisella hajottimella, joka on osittain kone, osittain organismi. Aseen toiminta saattaa perustua isäntäorganismin alkuperäisiin äänihuuliin. Muukalaiset käyttävät laajalti näitä erittäin tarkkoja ja sitkeitä supervahtikoiria suojelemaan tärkeitä varojaan.\"\n  STR_BIODRONE_AUTOPSY: \"Biodroidin ruumiinavaus\"\n  STR_BIODRONE_AUTOPSY_UFOPEDIA: \"Hypoteesi, että auditiivinen hajotin on biologinen laite, on tosi. Tämä kovan onnen olento kirjaimellisesti kirkuu vihollisensa kuoliaiksi. Kussakin yksilössä on valtavia kirurgisia arpia vakavan silvonnan seurauksena. Muukalaiset vaikuttavat runtelevan aivot kuuliaisuuteen. Useimmat olioissa käytetyistä aivokuorista vaikuttavat olevan muukalaisperäisiä, mutta mikään ei ole verrattavissa siihen kauhuun, kun ihmisperäinen yksilö löytyy. Biodroidit käyvät ionimoottorilla, ja niihin sisältyy jonkinlainen kauko-ohjausjärjestelmä.\"\n  STR_TENTACULAT_UFOPEDIA: \"Edes lovecraftilaisen painajaisen syvyydet ei voisi synnyttää tällaista sanoin kuvaamatonta oliota. Mitään verrattavissa olevaa Maan eläintä ei ole olemassa; ympäristö, joka voisi tuottaa jotain tällaista, ei ole kuviteltavissa. Lonkeromanaaja lamaannuttaa uhrinsa pitkillä lonkeroillaan ja sitten muuttaa ne mielettömiksi olioiksi. Nämä jälkeläiset pystyvät tappamaan kosketuksellaan jopa panssarin läpi. Lonkeromanaaja on hirvittävin X-Comin tähän saakka kohtaamista muukalaisista.\"\n  STR_TENTACULAT_AUTOPSY: \"Lonkeromanaajan ruumiinavaus\"\n  STR_TENTACULAT_AUTOPSY_UFOPEDIA: \"Ruumiinavaus paljastaa, että olennon suuriin aivoihin on istutettu pieniä kyberneettisiä implantteja. Näköaisti on monimutkainen yhdistelmä näkyvän valon ja lämmön kuvantamista. Jopa valtamerten sysimustissa syvyyksissä tämä hirviö pystyy suunnistamaan erehtymättömällä tarkkuudella. Surkastuneet elimet näyttävät juuri ja juuri mahdollistavan sen selviytymisen. Kunkin yksilön pieni mahalaukku on kytkettu ulkoiseen liittimeen, ja on loogista olettaa, että oliota ruokkivat sen isännät suoralla ravintoainesyötöllä.\"\n  STR_CALCINITE_UFOPEDIA: \"Muistuttaen kadonneiden merimiesten sukelluspukuja nämä muukalaiset vaanivat varomattomia merenpohjan kulkijoita. Raju isku olennon terästä vahvemmista kynsistä voi riittää upottamaan parhaimmatkin sukeltajat pohjalle. Naamarin sisällä voi nähdä pyörteilemässä hyytelömäisen vihreän muodon. Vihjettäkään todellisesta olennosta ei pysty aavistamaan usein tappavista kohtaamisista, joita meillä on ollut niiden kanssa.\"\n  STR_CALCINITE_AUTOPSY: \"Kalsiniitin ruumiinavaus\"\n  STR_CALCINITE_AUTOPSY_UFOPEDIA: \"Kun panssaroitu puku on riisuttu, kalsiniitti paljastuu valtavaksi amorfiseksi möykyksi protoplasmaa. Mitään näkyviä aivoja, raajoja tai aistielimiä ei ole. Pieni metallinen komponentti sijaitsee syvällä nestemäisessä ruumiissa. Olennon kerran kuoltua voimme vain tehdä arvailuja olennon luonnosta; muukalaisvihollistemme selittämätön arvoitus.\"\n  STR_TRISCENE_UFOPEDIA: \"Tämä kaksijalkainen matelija on kaiku dinorausten aikakaudelta. Se vaikuttaa olevan liitukauden olento joka suhteessa, lukuun ottamatta sen kykyä selviytyä sekä vedessä että maalla. Näihin olentoihin on sidottu asekotelot, ja niiden leuoilla on valtavat metallihampaat. Usein nämä hirviöt ovat olleet muukalaisten hyökkäysjoukkojen keskiössä muukalaisten rynnäköidessä maalle. Raskaan sarjan voimakas ase, jota tasoottikomentajat käyttävät tappavalla tehokkuudella.\"\n  STR_TRISCENE_AUTOPSY: \"Triasliskon ruumiinavaus\"\n  STR_TRISCENE_AUTOPSY_UFOPEDIA: \"Tiedemiehen veitsen alle altistamisen jälkeen triasliskosta paljastuu, että se on muinainen olento kybeneettisin implantein ja asejärjestelmin täydennettynä. Sen hyvin pieniä aivoja täydentää pieni tietokonemoduuli, joka on kiinnitetty ohjausvaljaisiin, joihin kaikki liskot on puettu. Luontaisesti vahva nahka sekä saalistusvaisto parannettuina lisäaseistuksella tekevät triasliskosta tappavan vastustajan kaikissa ympäristöissä.\"\n  STR_HALLUCINOID_UFOPEDIA: \"Meriä talteen korjattuaan muukalaiset ovat jalostaneet näitä valtavia Maan olentoja aseeksi. Älä tuudittaudu väärään turvallisuuden tunteeseen kohdatessasi näitä harmittoman näköisiä syvyyksien purhehtijoita. Käyttäen lähitaisteluaseenaan jäistä iskua hallusinoidi on tappava vihollinen.\"\n  STR_HALLUCINOID_AUTOPSY: \"Hallusinoidin ruumiinavaus\"\n  STR_HALLUCINOID_AUTOPSY_UFOPEDIA: \"Tämän organismin hyytelömäisen ruumiin monien kerrosten sisällä pesiytyneenä on kemiallinen jäädytin, joka on olion pääasiallinen hyökkäyskeino. Hallusinoidin pehmeä ja notkea iho vaikuttaa olevan herkkä lämpöpohjaisille hyökkäyksille. Tämä mutantti esiintyy usein akvatoidi-isäntiensä seurassa.\"\n  STR_XARQUID_UFOPEDIA: \"Kalmanhelmi on jälleen yksi muunnelluista Maan selkärangattomista. Siinä piilee sekä suurta kauneutta että vaaraa. Tämä nopea jättiläinen pitää sisällään tuhoisan aseistuksen: tukahduttavan mustesuihkun ja ionisuidun hiukkaspaineaallon. Ensikohtaamisistamme lähtien tämän mahtavan olennon kanssa olemme olleet varuillamme sen voimasta sekä sen hallitsijoistaan: kostonhimoisista kidusihmisistä.\"\n  STR_XARQUID_AUTOPSY: \"Kalmanhelmen ruumiinavaus\"\n  STR_XARQUID_AUTOPSY_UFOPEDIA: \"Tämä ylisuuri helmivene on kasvastettu valtavaksi muukalaislääkkeiden sekä kirurgisen muuntelun avulla. Kidusihmiset ovat vääristäneet olennon yli luonnonrajojen ja lisänneet siihen mekaanisia ohjausjärjestelmiä, eikä olennon alkuperäisestä luonteesta ole nyt mitään jäljellä. Kalmanhelmeä käytetään orgaanisena asealustana, ja sen kova kuori sekä liikkuvuus tekevät siitä pelottavan vihollisen.\"\n  STR_ION_BEAM_ACCELERATORS_UFOPEDIA: \"Muukalaisten lentosukellusveneet turvautuvat monimutkaisiin voima-järjestelmiin kuljettamaan niitä uskomattomilla nopeuksilla syvyyk-sissä. Heidän teknologiansa perus-tana on ionisyrjäytin. Hyödyntäen zrbiittiä katalyyttinaan moottorit syrjäyttävät vettä satakertai-sesti oman tilavuutensa verran sekunnissa. Tämä suunnaton voima tarkoittaa, että muukalaisten sukellusveneet ovat nopeampia kuin useimmat Maan sukellusveneet. Pystymme jäljentämään tämän työntövoimajärjestelmän käyttämällä akvaplastiikkaa sekä zrbiitti-kennoja.\"\n  STR_MAGNETIC_NAVIGATION_UFOPEDIA: \"Nämä yksiköt synnyttävät pallon muotoisen monitasoisen magneettikentän, jonka lähetin projisoi parhaimmillaan 1000 m päähän sukellusveneen ympärille. Muukalaisnavigoijat on yhdistetty suoraan koneisiin, ja he tunnustelevat tiensä läpi merenalaisen näkymättömän maailman. Rajapintajärjestelmä toimii käyttämällä muukalaisten muuntelemaa aivomassaa, joka viestii suoraan käyttäjän aivojen kanssa hermoratayhteyden välityksellä.\"\n  STR_ALIEN_SUB_CONSTRUCTION_UFOPEDIA: \"Kullakin aluksella on kameleonttimainen rakenne, jonka muotoilun mallina on huolellisesti käytetty meren olentoja ja rakennusmateriaalina akvaplastiikkaa. Kukin sukellusvene toimii organismin lailla, jossa miehistö sekä alus ovat keskinäisessä sopusoinnussa. Useimmat näistä järjestelmistä pystytään toistamaan, ja hybriditeknologiaa voidaan kehittää noustaksemme samalle teknologiselle tasolle.\"\n  STR_ALIEN_CRYOGENICS_UFOPEDIA: \"Lukemattomia muukalaisia, jotka ovat maanneet Maassa piilossa, pidetään valekuolleina kryogeenisessä jäädytyksessä. Kaikki olennot on suljettu yksiköihin, joissa niiden ruumiinlämpötilat on laskettu pisteeseen, jossa elintoiminnot ovat lähes tyystiin lakanneet. Tähänastinen yksiköiden tarkastelu paljastaa uskomattomat ajanjaksot, joina ruumiita on pidetty tässä tilassa, joitain yli 60 miljoonaa vuotta.\"\n  STR_ALIEN_CLONING_UFOPEDIA: \"Monet kaappaamistamme muukalaisista ovat keskenään identtisiä DNA:ta myöten, kaikin tavoin kopioita. Muukalaisten jäädytetyistä geenipankeista asetetaan solunäytteitä kloonausyksiköihin. Jotkin yksiköt sisältävät ihmisiä tai ruumiinosia. On mahdollista, että näiden kloonausyksiköiden toinen käyttötarkoitus on luoda jokin muukalaisen ja ihmisen risteymä.\"\n  STR_ALIEN_LEARNING_ARRAYS_UFOPEDIA: \"Hyödyntämällä molekulaarisen hallinan implantteja muukalaisten pääkalloissa nämä koneet ruiskuttavat tietoa suoraan aivoihin. Tuoreeltaan kloonatut muukalaiset tuodaan näiden yksiköiden luokse, ja niiden lajikohtaiset muistikuvat sekä kaikki tieteellinen tieto ja taistelutaidot ladataan niiden tyhjiin mieliin.\"\n  STR_ALIEN_IMPLANTER_UFOPEDIA: \"Tätä yksikköä käytetään istuttamaan muukalaisiin molekulaarisen hallinan implantteja, hedelmöittämään lisääntymiskykyisiä rotuja sekä lisäämään tai poistamaan elimiä ja elektroniikkaa mistä tahansa olennosta. Käsittelyn uskottiin aiemmin tehdyn rauhoitetuille potilaille, mutta koehenkilö onkin hyvin tietoinen tapahtumasarjasta, ja valitettavasti ihmisanatomia vaikuttaa sopivan yksikköön täydellisesti.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"Meillä on nyt todistusaineisto ratkaisemaan, miksi muukalaiset kaappaavat ihmisiä. He eivät ole ruokaa eikä heitä hedelmöitetä muukalaisalkioilla, vaan muodostavat pohjan liudalle erilaisia olioita ja komentojärjestelmiä. Muukalaisteknologia perustuu tavalliseen mieleen, jaettuun älyyn, ja ihmisaivot on ihanteellinen alusta näille järjestelmille. Ihmisen aivokudosta käytetään useimmissa muukalaisten biologisissa tietokone- ja hakujärjestelmissä. Loput kudoksesta käytetään rakentamiseen ja kasvatukseen.\"\n  STR_AQUA_PLASTICS_UFOPEDIA: \"Muukalaisten sukellusveneet ja rakennukset käyttävät hämmästyttävän lujaa, notkeaa ja kestävää materiaalia valtaosassa rakenteistaan. Akvaplastiikka on kompleksi monisidoksinen ja zrbiitin katalysoima materiaali. Tämän lujan, mutta kuitenkin kevyen materiaalin lujuus on jopa titaania ja kevlaria suurempi.\"\n  STR_ZRBITE_UFOPEDIA: \"Tämä metalliseos on muukalaisalkuperää, osin kultaa, osin muukalaisten biomateriaalia. Kun sitä käytetään voimanlähteenä, pieni määrä tuottaa enemmän voimaa kuin kymmenen kertaa suurempi ydinvoimanlähde. Meidän on teknisesti mahdotonta toisintaa tätä materiaalia, koska useimmat sen ainesosista ovat muukalaisalkuperää.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"Muukalaiset iskevät kaikkialle ympäri maapalloa säälimättömällä tehokkuudella. Emme kykene osoittamaan heidän lähdettään. Voisiko se olla jossakin niin läpipääsemättömässä meren syvyydessä, että voisimme sen paikantaa? Kaikki kohtaamistamme organismeista eivät ole muukalaisperäisiä, jotkin ovat hyvin vanhoja, jotkin evoluutiohaaroista, joiden luultiin jo kauan sitten kuolleen sukupuuttoon. Olemme tekemisissä uhan kanssa, joka on uinunut vuosituhansia, hienovaraisen ihmisen ja muukalaisten symbioosin kanssa. Syvällä valtamerissä on haudattuina muinaisia kohteita, joita muukalaiset käyttävät luodakseen yhteyden veljiinsä tähdissä. Kussakin näistä kahdestatoista paikasta on Synomium-laite, mahtava muukalaisteknologia. Sotakoneistonsa marssiessaan muukalaiset ovat aktivoimassa uudestaan näitä kohteita levittääkseen molekulaarisen hallinnan verkkoaan, minkä takia meidän on tuhottava nämä kohteet hinnalla millä hyvänsä.\"\n  STR_THE_ULTIMATE_THREAT_UFOPEDIA: \"65 miljoonaa vuotta sitten valtava siirtokunta-alus lähetettiin Maahan kaukaisesta muukalaismaailmasta. Suunnattoman aluksen lähestyessä alkuasteella olevaa planeettaa massiivinen ja raju auringonpurkaus aiheutti navigointijärjestelmien vikaantumisen. Lamaantunut ja hajoava suurlasti syöksyi stratosfäärin läpi ja ilmestyi liitukauden taivaalle. Maassa lukemattomat lajit suuntasivat katseensa taivaalle heidän kohtalonsa tunkeutuessaan planeettaan. Valtava pilvi tukki ilmakehän, ja kun maa viileni, niin myös hallitsevat eliöt, mahtavat dinosaurukset, kuolivat. Mutta T'lethin 400 miljardia tonnia ei tuhoutunut törmäyksessä. Kehittyneet supertietokoneet käynnistivät kryogenisen unijakson aluksen olennoille syvällä sen ruumassaan. Ajanjaksojen mittaan tietokoneet herättivät muukalaisia yrittämään turhaan luoda yhteyttä veljiinsä tähdissä, sillä suurin osa muukalaisaluksen voimasta jatkoi lepotilassa.\"\n  STR_TLETH_THE_ALIEN_CITY: \"T'leth, muukalaisten kaupunki\"\n  STR_TLETH_THE_ALIEN_CITY_UFOPEDIA: \"T'leth, muukalaisten valtava siirtokunta-alus, makaa Meksikonlahdessa uppoutuneena Sigsbeen syvänteeseen. Kaupungin ytimessä sijaitsee muukalaishirvitys, niin kamala ja voimakas, ettei edes kuolemalla ole siihen valtaa. Muukalaismetallista rakennetussa kammiossa lepää horroksessa Suuri Uneksija, Korkein Muukalainen. T'lethin nostaminen merten ylle käynnistää sen henkiinherätyssyklin, ja kerran herättyään siitä tulee pysäyttämätön. Jotenkin elävän ja kuolleen rajamailla oleva muukalainen hallitsee muukalsarmeijan mieliä. Molekulaarisen hallinnan outo teknologia yhdistää kaikki muukalaiset Yhteen mieleen ja sen kaikkiin muukalaisiin. Geneettisesti muunneltuja muukalais- ja ihmissikiöitä syötetään Muukalaismielelle energiaksi ja muodostamaan yhdyssiteen hallitsijan ja sen alamaistensa välille. Myytti Korkeimmasta muukalaisesta on ollut olemassa ihmiskunnan sydämissä ja mielissä vuosisatoja, ja lopullinen totuus on aina ollut kätkeytyneenä mereen.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"KOHDISTA PAIKKAAN - AIKA=5 s\"\n  STR_CANCEL_UC: \"PERUUTA\"\n  STR_NONE: \"Ei mitään\"\n  STR_UNKNOWN: \"Tuntematon\"\n  STR_POOR: \"Huono\"\n  STR_AVERAGE: \"Keskiverto\"\n  STR_GOOD: \"Hyvä\"\n  STR_EXCELLENT: \"Erinomainen\"\n  STR_BUILD_NEW_BASE_UC: \"RAKENNA UUSI TUKIKOHTA\"\n  STR_BASE_INFORMATION: \"TUKIKOHDAN TIEDOT\"\n  STR_EQUIP_CRAFT: \"ALUKSET\"\n  STR_BUILD_FACILITIES: \"RAKENNA LAITOKSIA\"\n  STR_RESEARCH: \"TUTKIMUS\"\n  STR_MANUFACTURE: \"TUOTANTOPROJEKTIT\"\n  STR_TRANSFER_UC: \"SIIRRÄ\"\n  STR_PURCHASE_RECRUIT: \"OSTA/VÄRVÄÄ\"\n  STR_SACK: \"EROTA\"\n  STR_SELL_SACK_UC: \"MYY/EROTA\"\n  STR_GEOSCAPE_UC: \"GEOMAISEMA\"\n  STR_NAME: \"Nimi\"\n  STR_AREA: \"Alue\"\n  STR_BUILD_NEW_BASE: \"Rakenna uusi tukikohta\"\n  STR_CANCEL: \"Peruuta\"\n  STR_COST_UC: \"HINTA>\"\n  STR_CONSTRUCTION_TIME_UC: \"RAKENNUSAIKA>\"\n  STR_DAY:\n    one: \"{N} päivä\"\n    other: \"{N} päivää\"\n  STR_HOUR:\n    one: \"{N} tunti\"\n    other: \"{N} tuntia\"\n  STR_MAINTENANCE_UC: \"YLLÄPITO>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Rakenna\"\n  STR_CURRENT_RESEARCH: \"TUTKIMUSPROJEKTIT\"\n  STR_SCIENTISTS_AVAILABLE: \"Tiedemiehiä vapaana>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Tiedemiehiä projekteissa>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Laboratoriotilaa vapaana>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"TUTKIMUSPROJEKTI\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"TIEDEMIEHIÄ\"\n  STR_PROGRESS: \"EDISTYMINEN\"\n  STR_NEW_PROJECT: \"Uusi projekti\"\n  STR_CANCEL_PROJECT: \"PERUUTA PROJEKTI\"\n  STR_NEW_RESEARCH_PROJECTS: \"UUDET TUTKIMUSPROJEKTIT\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"TIEDEMIEHIÄ VAPAANA>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"LABORATORIOTILAA VAPAANA>{ALT}{0}\"\n  STR_INCREASE: \"Lisää\"\n  STR_DECREASE: \"Vähennä\"\n  STR_START_PROJECT: \"ALOITA PROJEKTI\"\n  STR_CURRENT_PRODUCTION: \"TUOTANTOPROJEKTIT\"\n  STR_ENGINEERS_AVAILABLE: \"Teknikkoja vapaana>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Teknikkoja projekteissa>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Työpajatilaa vapaana>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Nykyiset varat>{ALT}{0}\"\n  STR_ITEM: \"TAVARA\"\n  STR_ENGINEERS__ALLOCATED: \"Teknikkoja projektissa\"\n  STR_UNITS_PRODUCED: \"Tuotetut yksiköt\"\n  STR_TOTAL_TO_PRODUCE: \"Tuotetaan yht.\"\n  STR_COST__PER__UNIT: \"Hinta{NEWLINE}per{NEWLINE}yksikkö\"\n  STR_DAYS_HOURS_LEFT: \"Aikaa (d/h) jäljellä\"\n  STR_NEW_PRODUCTION: \"Uusi tuotantoprojekti\"\n  STR_PRODUCTION_ITEMS: \"Mahdolliset projektit\"\n  STR_CATEGORY: \"LUOKITUS\"\n  STR_START_PRODUCTION: \"ALOITA TUOTANTO\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} teknikkotyötuntia yhden yksikön tuottamiseksi\"\n  STR_COST_PER_UNIT_: \"Hinta / yks.>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Tarvittava työpajatila>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"TARVITTAVAT ERITYISTARVIKKEET\"\n  STR_ITEM_REQUIRED: \"TARVITTAVA TAVARA\"\n  STR_UNITS_REQUIRED: \"TARVITTAVAT YKSIKÖT\"\n  STR_UNITS_AVAILABLE: \"YKSIKKÖÄ SAATAVANA\"\n  STR_STOP_PRODUCTION: \"LOPETA TUOTANTO\"\n  STR_ENGINEERS_AVAILABLE_UC: \"TEKNIKKOJA VAPAANA>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"TYÖPAJATILAA VAPAANA>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"TUOTOT / KK>{ALT}{0}\"\n  STR_INCREASE_UC: \"LISÄÄ\"\n  STR_DECREASE_UC: \"VÄHENNÄ\"\n  STR_UNITS_TO_PRODUCE: \"Tuotettavat yksiköt\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Osta/Palkkaa henkilökuntaa\"\n  STR_COST_OF_PURCHASES: \"Tilauksen hinta>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"HINTA / YKS.\"\n  STR_QUANTITY_UC: \"MÄÄRÄ\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"HENKILÖKUNTAA VAPAANA:HENKILÖKUNTAA YHTEENSÄ>\"\n  STR_SOLDIERS: \"Akvanautit\"\n  STR_SCIENTISTS: \"Tutkijat\"\n  STR_ENGINEERS: \"Teknikot\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"TILAA KÄYTETTY:TILAA JÄLJELLÄ>\"\n  STR_LIVING_QUARTERS: \"Asuintila\"\n  STR_STORES: \"Varastot\"\n  STR_LABORATORIES: \"Laboratoriot\"\n  STR_WORK_SHOPS: \"Työpajat\"\n  STR_HANGARS: \"Lentosukellusvenetelakat\"\n  STR_SHORT_RANGE_DETECTION: \"Peruskaikuluotaimet\"\n  STR_DEFENSE_STRENGTH: \"Puolustusvoima\"\n  STR_TRANSFERS_UC: \"SIIRROT\"\n  STR_TRANSFERS: \"Siirrot\"\n  STR_ARRIVAL_TIME_HOURS: \"Saapumisaika (tuntia)\"\n  STR_COST_: \"Hinta>{ALT}{0}\"\n  STR_AREA_: \"Alue>{ALT}{0}\"\n  STR_BASE_NAME: \"Tukikohdan nimi?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"VALITSE ILMALUKON SIJAINTI\"\n  STR_TRANSFER: \"Siirrä\"\n  STR_AMOUNT_TO_TRANSFER: \"SIIRRETTÄVÄ MÄÄRÄ\"\n  STR_SELECT_DESTINATION_BASE: \"Valitse kohdetukikohta\"\n  STR_COST: \"Hinta\"\n  STR_INTRO_1: \"Tekijänoikeus 1995 MicroProse\"\n  STR_INTRO_2: \"Mars: Kydonian tuho\"\n  STR_INTRO_3: \"Tuhottuaan muukalaissotakoneiston ytimen voitokas X-Com-ryhmä laukaisee aluksensa takaisin kotiin. Kaikki ei ole kuitenkaan kuollut runnellussa marsilaistukikohdassa.\"\n  STR_INTRO_4: \"Voimakas takyonisäde kumpuaa Kydonian hermokeskuksen raunioista halkoen läpi avaruuden tyhjyyden, määränpäänään............\"\n  STR_INTRO_5: \"Maa.\"\n  STR_INTRO_6: \"Säde osuu kauan lepotilassa olleeseen vastaanottimeen valtameren syvyydessä. Valtavat uinuvat tietokoneet alkavat herätä. Syvällä ihmiskatseiden ulottumattomissa suurissa kammioissa nukkuvat muukalaiset aloittavat pitkän heräämisjaksonsa.\"\n  STR_INTRO_7: \"Vuosi 2040: tietämätön Maa. Muukalaissodan kauhut on unohdettu. Mutta kadonneissa ja salaisissa valtameren kolkissa muukalaislaumat ovat valmiita - valmiita kaatamaan ihmiskunnan ja valtaamaan maailman.\"\n  STR_INTRO_8: \"Muukalaiset iskevät ihmiskuntaa vastaan etsien näytteitä kieroutuneita kokeitaan varten ja ryöstellen maapallon merten arvokkaita mineraaleja ja luonnonvaroja. Sen jälkeen muukalaiset suuntaavat katseensa aaltojen yläpuolelle.\"\n  STR_INTRO_9: \"Voimakkaat oudon malliset lentävät sukellusveneet halkovat valtameriä tutkien, koluten, metsästäen...\"\n  STR_INTRO_10: \"Etsien saalista, jonka kimppuun hyökätä.\"\n  STR_INTRO_11: \"Outoja uusia aseita aletaan käyttää puolustuskyvytöntä maailmaa vastaan. Olemme täysin muukalaisuhan armoilla.{NEWLINE}Ainoastaan yksi organisaatio voi pelastaa meidät, mutta me käänsimme selkämme heille kauan sitten...\"\n  STR_INTRO_12: \"X-COM:n kokeellinen vedenalainen laitos\"\n  STR_INTRO_13: \"\\\"Mayday! Mayday! Tämä on transatlanttinen valtamerialus Hyperion. Kimppuumme on hyökätty. Mayday! Mayd...\\\"\"\n  STR_INTRO_14: \"\\\"Komentokeskus sukellusvenetelakalle 1: Aukaiskaa valtameriluukut, asettakaa merille Barrakuda 01. Kyseessä on muukalaishyökkäys - tila punainen.{NEWLINE}Toistan: tila punainen.\\\"\"\n  STR_INTRO_15: \"Muukalaiset ovat armottomia tehokkuudessaan...\"\n  STR_INTRO_16: \"...erehtymättömiä tarkkuudessaan.\"\n  STR_INTRO_17: \"\\\"Barrakuda 01 tukikohdalle: lähestymme sitä, mitä Hyperionista on jäljellä.\\\"\"\n  STR_INTRO_18: \"\\\"Vähennämme nopeutta\\\"{NEWLINE}\\\"Kaksi metriä\\\"{NEWLINE}\\\"Yksi metri\\\"{NEWLINE}\\\"Kaikki akvanautit valmistautukaa välittömään sijoitukseen.\\\"\"\n  STR_INTRO_19: \"...\\\"Ilmalukko tyhjä\\\"...\\\"Lähestymme hylkyä.\\\"{NEWLINE}\\\"Juma!\\\"{NEWLINE}\\\"Näettekö nuo oliot pukukamerastani?\\\"\"\n  STR_GAMEOVER_1: \"Olemme epäonnistuneet; muukalaiset ovat hävittäneet loputkin toivomme pelastuksesta.{NEWLINE}X-Com on tuhottu ja Maa on jätetty muinaisen vihollisen jalkojen juurelle.\"\n  STR_GAMEOVER_2: \"T'leth tempautuu korkealle stratosfääriin ja alkaa liikkua maanpinnan yllä jakaen kuolemaa ja korjaten talteen ihmiskunnan rippeitä. Syvällä sen sisuksissa murhanhimoinen muukalaismieli alkaa herätä.\"\n  STR_GAMEOVER_3: \"Kaikki kansakunnat laativat epätoivoisia suunnitelmia pääkaupungeissaan, mutta turhaan. Ilman X-Comin tutkimusprojektin suomaa teknologiaa aseemme ovat tehottomia.\"\n  STR_GAMEOVER_4: \"Muukalaiset perustavat tukikohtia napajäätiköille ja alkavat sulattaa jäätä muuttaen maailman valtavan suureksi mereksi. Ihmiskunnan jäänteet kootaan yhteen ja hyödynnetään hirveissä jalostuskokeissa muukalaisten tuntemattomia tarkoitusperiä varten. Taivas pimenee ja suuri rutto lankeaa Maan ylle.\"\n  STR_GAMEOVER_5: \"Emme kykene vastustamaan uutta maailmanjärjestystä. Niiden osana, jotka yrittävät, on tulinen kohtalo käsittämättömien muukalaisaseiden edessä. Lopuille meistä ei jää sellaista autuasta irtautusta; maaäidistä tulee muukalaismaailma, ja ihmiskunta on menetetty ryömivän hirvityksen alle.\"\n  STR_OUTRO_1: \"Runnellun ja hävitetyn hautakammion keskeltä ruumisarkusta kantautuu kupliva jylinä.{NEWLINE}\\\"Typerykset, te kaikki tuhoudutte...\\\"\"\n  STR_OUTRO_2: \"\\\"...kukaan ei voi paeta.\\\"\"\n  STR_OUTRO_3: \"Massiivinen räjähdys purkautuu haudasta ja repii kaupungin halki pirstaleiden ja savun täyttäessä ilman. Muukalaisten suunnitelmat ovat rauenneet tyhjiin.\"\n  STR_OUTRO_4: \"Valtava vääntelehtivä T'leth alkaa repeillä. Liekit ja savu syöksyvät sen välkehtivistä torneista ja adamanttisista käytävistä\"\n  STR_OUTRO_5: \"Mahtava muukalaislinnoitus romahtaa merta päin kirkuvien sielujen ja metallin täyttäessä ilman. Enää Suuri Uneksija ei unelmoi maailman valloittamisesta.\"\n  STR_OUTRO_6: \"Viimeinen korvia särkevä tärähdys ja T'leth repeää hajalle.{NEWLINE}Muukalaisuhka on ohi, Maa on puhdistettu.\"\n  STR_OUTRO_7: \"Uinuva sinivihreä planeetta kaukaisessa galaksin nurkassa.\"\n  STR_OUTRO_8: \"Lähitulevaisuus; turvallinen paikka olla.\"\n  STR_OUTRO_9: \"Maan muukalaisuhka on kauan sitten kukistettu.\"\n  STR_OUTRO_10: \"Valtavat metropolikaupungit, joita asuttavat ihmiskunnan miljardien vilinä.\"\n  STR_OUTRO_11: \"X-Comin teot ja muukalaissodat ovat lastentarinoiden ainesta.\"\n  STR_OUTRO_12: \"Mutta tarinoilla on aina ollut tapana sisältää jyvä totuutta...\"\n  STR_RISE_1: \"T'leth, joka tunnetaan monella nimellä useissa eri maiden legendoissa.\"\n  STR_RISE_2: \"T'leth alkaa nousta merenpohjasta räjähtävän huudon saattelemana, joka kajahtelee maapallon halki.\"\n  STR_RISE_3: \"Mahtava rakennelma nousee kuohuen Meksikonlahden vetten läpi.\"\n  STR_RISE_4: \"400 miljardia tonnia muukalaismetallia, mahtava muukalaiskaupunki, jossa lepää Korkeimman Muukalaisen uinuva ruumis. Oltuaan maahan vangittuna 65 miljoonaa vuotta tämä hirveä avaruusjumala alkaa havahtua.\"\n  STR_RISE_5: \"Vedet kiehuvat ja kuohuvat Suuren Uneksijan haudan ilmestyessä valoon...\"\n  STR_RISE_6: \"...valoon, joka jää lyhytaikaiseksi, ellei X-Com kykene tuhoamaan muukalaisten sotakoneistoa.\"\n  STR_YOU_HAVE_FAILED: \"Olet epäonnistunut pysäyttämään muukalaisten sotakoneiston. Pettyneinä kykyihisi rahoittavat organisaatiot yrittävät neuvotella rauhanomaista ratkaisua muukalaisten kanssa. Hyökkääjillä on kuitenkin täysin erilaiset aikeet, ja pian koko maailma tulee tietoiseksi totuudesta...\"\n  STR_TOTAL_UC: \"YHTEENSÄ\"\n  STR_INCOME: \"Tulot\"\n  STR_EXPENDITURE: \"Menot\"\n  STR_MAINTENANCE: \"Ylläpito\"\n  STR_BALANCE: \"Saldo\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"Muukalaisaktiivisuus merissä\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"Muukalaisaktiivisuus alueittain\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"X-Comin aktiivisuus merissä\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"X-Comin aktiivisuus alueittain\"\n  STR_FINANCE: \"Talous\"\n  STR_DATE_FIRST: \"{0}.\"\n  STR_DATE_SECOND: \"{0}.\"\n  STR_DATE_THIRD: \"{0}.\"\n  STR_DATE_FOURTH: \"{0}.\"\n  STR_FINANCE_THOUSANDS: \"1000 $\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Ei riittävästi erityistarvikkeita tuotteen {NEWLINE}{0}{NEWLINE}tuottamiseen tukikohdassa{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Rahat eivät riitä {NEWLINE}{0}{NEWLINE}tuottamiseen tukikohdassa{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"Tuotantoprojektin{NEWLINE}{0}{NEWLINE}tuotanto tukikohdassa{NEWLINE}{1}{NEWLINE}on valmis\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"{NEWLINE}{0}{NEWLINE}on valmistunut{NEWLINE}tukikohdassa{NEWLINE}{1}\"\n  STR_OK_5_SECONDS: \"OK - 5 s\"\n  STR_RESEARCH_COMPLETED: \"Tutkimusprojekti valmis\"\n  STR_VIEW_REPORTS: \"NÄYTÄ RAPORTTI\"\n  STR_WE_CAN_NOW_RESEARCH: \"Uudet tutkimusprojektit:\"\n  STR_WE_CAN_NOW_PRODUCE: \"Uudet tuotantoprojektit:\"\n  STR_SUNDAY: \"SUNNUNTAI\"\n  STR_MONDAY: \"MAANANTAI\"\n  STR_TUESDAY: \"TIISTAI\"\n  STR_WEDNESDAY: \"KESKIVIIKKO\"\n  STR_THURSDAY: \"TORSTAI\"\n  STR_FRIDAY: \"PERJANTAI\"\n  STR_SATURDAY: \"LAUANTAI\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Ei riittävästi {0}-polttoainetta aluksen {1} tankkaamiseksi tukikohdassa {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Ei riittävästi ammustyyppiä {0} {1}:n uudelleen aseistamiseksi tukikohdassa {2}\"\n  STR_UFO_IS_NOT_RECOVERED: \"Muukalaisalusta ei saatu korjattua talteen\"\n  STR_UFO_IS_RECOVERED: \"Muukalaisalus korjattu talteen\"\n  STR_CRAFT_IS_LOST: \"Lentosukellusvene menetettiin\"\n  STR_TERROR_CONTINUES: \"Muukalaistoiminta jatkuu\"\n  STR_ALIENS_DEFEATED: \"Muukalaiset hävisivät\"\n  STR_BASE_IS_LOST: \"Tukikohta menetettiin\"\n  STR_BASE_IS_SAVED: \"Tukikohta pelastettu\"\n  STR_ALIEN_BASE_STILL_INTACT: \"Muukalaisyhdyskunta edelleen toiminnassa\"\n  STR_ALIEN_BASE_DESTROYED: \"Muukalaisyhdyskunta tuhottu\"\n  STR_ALIENS_KILLED: \"TAPETUT MUUKALAISET\"\n  STR_ALIEN_CORPSES_RECOVERED: \"MUUKALAISTEN RUUMIITA LÖYDETTY\"\n  STR_LIVE_ALIENS_RECOVERED: \"ELÄVIÄ MUUKALAISIA KAAPATTU\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"MUUKALAISTEN ESINEITÄ LÖYDETTY\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"MUUKALAISYHDYSKUNNAN KOMENTOKESKUS TUHOTTU\"\n  STR_ALIEN_SYNOMIUM_DEVICE_DESTROYED: \"MUUKALAISTEN SYNOMIUM-LAITE TUHOTTU\"\n  STR_ALIEN_SYNOMIUM_DEVICE_FAILED: \"SYNOMIUM-LAITTEEN TUHOAMINEN EPÄONNISTUNUT\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"SIVIILEJÄ TAPETTU MUUKALAISTEN TOIMESTA\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"X-COMIN TAPPAMAT SIVIILIT\"\n  STR_CIVILIANS_SAVED: \"SIVIILEJÄ PELASTETTU\"\n  STR_XCOM_OPERATIVES_KILLED: \"KAATUNEET X-COM-SOTILAAT\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"KADONNEET X-COM-SOTILAAT\"\n  STR_TANKS_DESTROYED: \"X-Comin miehittämätön taistelukone tuhoutunut\"\n  STR_XCOM_CRAFT_LOST: \"X-COM-ALUS MENETETTIIN\"\n  STR_UFO_RECOVERY: \"MUUKALAISALUKSEN LAITTEISTO\"\n  STR_ALIEN_BASE_RECOVERY: \"MUUKALAISYHDYSKUNNAN SAALIS\"\n  STR_BASE_UNDER_ATTACK: \"{0} hyökkäyksen kohteena!\"\n  STR_BASE_DEFENSES_INITIATED: \"TUKIKOHDAN PUOLUSTUKSET AKTIVOITU\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"SUOJAT HYLKIVÄT MUUKALAISALUSTA!\"\n  STR_FIRING: \"TULITTAA\"\n  STR_HIT: \"OSUMA!\"\n  STR_UFO_DESTROYED: \"MUUKALAISALUS TUHOUTUI!\"\n  STR_MISSED: \"OHI!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Myy tavaraa/Erota henkilökuntaa\"\n  STR_VALUE_OF_SALES: \"MYYNTIEN ARVO> {ALT}{0}\"\n  STR_FUNDS: \"VARAT> {ALT}{0}\"\n  STR_SELL_SACK: \"Myy/erota\"\n  STR_VALUE: \"Arvo\"\n  STR_CRAFT_: \"ALUS> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"MUUKALAISALUKSEN HYLYN HALTUUNOTTO\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"ÄÄRIMMÄINEN VAROITUS - Sukellusveneen sisällä ja sen ympäristössä on muukalaisia. Tehtävä on onnistunut, kun kaikki vihollisen yksiköt on tapettu tai tehty muutoin taistelukyvyttömiksi. Vasta sitten voidaan aloittaa muukalaissukellusveneen purku sekä teknologian ja ruumiiden talteenotto. Keskeyttääksesi tehtävän palauta kaikki X-Com-akvanautit sukellusveneeseen ja napsauta \\\"Keskeytä tehtävä\\\"-kuvaketta.\"\n  STR_UFO_GROUND_ASSAULT: \"HYÖKKÄYS MUUKALAISSUKELLUSVENEESEEN\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"Tutki laskeutumisalue ja sen ympäristö ja, mikäli mahdollista, pyri pääsemään sisään muukalaissukellusveneeseen. Tehtävä on onnistunut, kun kaikki vihollisen yksiköt on tapettu tai tehty muutoin taistelukyvyttömiksi. Vasta sitten voidaan aloittaa muukalaissukellusveneen purku sekä esineiden ja ruumiiden talteenotto. Keskeyttääksesi tehtävän palauta kaikki X-Com-akvanautit sukellusveneeseen ja napsauta \\\"Keskeytä tehtävä\\\"-kuvaketta.\"\n  STR_BASE_DEFENSE: \"TUKIKOHDAN PUOLUSTUS\"\n  STR_BASE_UC_: \"TUKIKOHTA> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"Muukalaisalus on laskeutunut lähettyville. Tukikohtamme on vakavassa vaarassa. Normaalikäytännön mukaisesti kaikki ei-sotilaallinen henkilökunta sekä toimintakuntoiset X-Com-sukellusveneet on evakuoitu. Muukalaiset pyrkivät tukikohtaan joko sukellusvenetelakkaovien tai ilmalukon kautta. Puolusta tukikohtaa ja sen elintärkeitä laitoksia kaikin mahdollisin keinoin - tämän taistelun hintana on tämä tukikohta. Mikäli napsautat \\\"Keskeytä tehtävä\\\"-kuvaketta, myönnät häviön ja menetät tukikohdan.\"\n  STR_ALIEN_COLONY_ATTACK_MISSION: \"HYÖKKÄYS MUUKALAISYHDYSKUNTAAN\"\n  STR_ALIEN_BASE_ASSAULT: \"MUUKALAISYHDYSKUNTA OSA YKSI\"\n  STR_ALIEN_COLONY_P1_BRIEFING: \"Tehtävänä on hyökkäys muukalaisyhdyskuntaan. Alue on kaksikerroksinen. Saata kaikki akvanautit ensimmäisen kerroksen kiiltävään uloskäyntiin ja napsauta \\\"Keskeytä tehtävä\\\"-kuvaketta jatkaaksesi. Kaikki taakse jätetty kalusto odottaa merenpohjassa, kunnes toinen osuus on päätetty. Keskeyttääksesi tehtävän sijoita akvanautit sukellusveneeseen ja napsauta \\\"Keskeytä tehtävä\\\"-kuvaketta.\"\n  STR_ALIEN_COLONY_P2: \"MUUKALAISYHDYSKUNTA OSA KAKSI\"\n  STR_ALIEN_COLONY_P2_BRIEFING: \"Nyt, kun ensimmäinen kerros on selvitetty ja yhdyskunnan ytimeen on päästy, tehtävänä on tuhota Synonium-laite-komentokeskus tai tappaa kaikki muukalaiset. Keskeyttääksesi tehtävän sijoita kaikki akvanautit aloituspisteeseen ja napsauta \\\"Keskeytä tehtävä\\\"-kuvaketta. Kaikki toimintakuntoinen X-Com-kalusto palautetaan tukikohtaan.\"\n  STR_ALIENS_LAUNCH_PORT_TERROR: \"MUUKALAISET{NEWLINE}HYÖKKÄÄVÄT SATAMAAN\"\n  STR_PORT_TERROR: \"MUUKALAISTEN HYÖKKÄYS SATAMAAN\"\n  STR_PORT_TERROR_BRIEFING: \"Muukalaiset ovat iskeneet maakohteeseen. Satama ja sen siviiliväestö ovat vaarassa. Ryhmäsi on eliminoitava kaikki muukalaiset ja suojeltava viattomia sivustakatsojia tältä muukalaisten hyökkäykseltä. Keskeyttääksesi tehtävän sijoita akvanautit lentosukellusveneeseen ja napsauta \\\"Keskeytä tehtävä\\\"-kuvaketta.\"\n  STR_ALIENS_LAUNCH_ISLAND_TERROR: \"MUUKALAISET{NEWLINE}HYÖKKÄÄVÄT SAAREEN\"\n  STR_ISLAND_TERROR: \"MUUKALAISTEN HYÖKKÄYS SAAREEN\"\n  STR_ISLAND_TERROR_BRIEFING: \"Muukalaiset ovat iskeneet maakohteeseen. Saari ja sen siviiliväestö ovat vaarassa. Ryhmäsi on eliminoitava kaikki muukalaiset ja suojeltava viattomia sivustakatsojia tältä muukalaisten hyökkäykseltä. Keskeyttääksesi tehtävän sijoita akvanautit lentosukellusveneeseen ja napsauta \\\"Keskeytä tehtävä\\\"-kuvaketta.\"\n  STR_ALIENS_ATTACK_SHIPPING_ROUTE: \"MUUKALAISET ISKEVÄT{NEWLINE}MERIVÄYLÄÄN\"\n  STR_CARGO_SHIP_P1: \"RAHTILAIVA OSA YKSI\"\n  STR_CARGO_SHIP_P2: \"RAHTIALUS OSA KAKSI\"\n  STR_CRUISE_SHIP_P1: \"RISTEILYALUS OSA YKSI\"\n  STR_CRUISE_SHIP_P2: \"RISTEILYALUS OSA KAKSI\"\n  STR_SHIP_RESCUE_MISSION: \"MERIPELASTUSTEHTÄVÄ\"\n  STR_SHIP_RESCUE_P1_BRIEFING: \"Tämä tehtävä on tuholaistorjunta; eliminoi kaikki muukalaisyksiköt aluksessa ja suojele aluksessa olevia siviilihenkiä. Muukalaiset ovat levittäytyneet ylä- ja alakansille; varmista yläkannet ennen alakansiin siirtymistä. Keskeyttääksesi tehtävän sijoita akvanautit lentosukellusveneeseen ja napsauta \\\"Keskeytä tehtävä\\\"-kuvaketta.\"\n  STR_SHIP_RESCUE_P2_BRIEFING: \"Nyt, kun olet selvittänyt yläkannen, etene alakansille. Tavarahissiä käyttäen laskeudut ruumaan. Ryhmäsi on eliminoitava kaikki muukalaiset tällä tasolla suorittaaksesi tehtävän. Keskeyttääksesi tehtävän sijoita kaikki akvanautit hissin aloituspisteeseen ja napsauta \\\"Keskeytä tehtävä\\\"-kuvaketta.\"\n  STR_ALIEN_ACTIVITY_DETECTED: \"MUUKALAISTOIMINTAA HAVAITTU\"\n  STR_ALIEN_CONTACT_SITE_MISSION: \"MUUKALAISVIESTINTÄLAITOSTEHTÄVÄ\"\n  STR_ARTIFACT_SITE_P1: \"MUUKALAISVIESTINTÄLAITOS OSA YKSI\"\n  STR_ARTIFACT_SITE_P1_BRIEFING: \"Tehtävänä on hyökkäys vastikään aktivoidulle muukalaisten viestintälaitokselle. Kohde on kaksikerroksinen: merenpohja muukalaispyramideineen sekä salainen muukalaiskompleksi. Saata kaikki akvanautit kompleksin sisäänkäynnille ja napsauta \\\"Keskeytä tehtävä\\\"-kuvaketta jatkaaksesi. Keskeyttääksesi tehtävän sijoita akvanautit lentosukellusveneeseen ja napsauta \\\"Keskeytä tehtävä\\\"-kuvaketta.\"\n  STR_ARTIFACT_SITE_P2: \"MUUKALAISVIESTINTÄLAITOS OSA KAKSI\"\n  STR_ARTIFACT_SITE_P2_BRIEFING: \"Nyt, kun muukalaisrakennusten läpi on päästy ja kompleksiin on murtauduttu, tehtävä on selvä: Tunkeudu muukalaislaitoksen sydämeen ja tuhoa molekulaarisen hallinnan Synomium-laite suorittaaksesi tehtävän loppuun. Keskeyttääksesi tehtävän sijoita kaikki akvanautit laitoshissin aloituspisteeseen ja napsauta \\\"Keskeytä tehtävä\\\"-kuvaketta.\"\n  STR_SIGSBEE_DEEP_MISSION: \"SIGSBEEN SYVÄNNE{NEWLINE}MUUKALAISTEN KAUPUNKI TASO YKSI\"\n  STR_TLETH_P1_BRIEFING: \"Astumme tuntemattomaan; tästä eteenpäin mitä tahansa voi olla odottamassa meitä. Tiedämme, että muukalaiskaupungissa on kaksi kerrosta lisää, ja ryhmäsi on kiirehdittävä tämän kerroksen uloskäynnille siirtyäkseen seuraavaan. Sijoita kaikki akvanautit uloskäynnille ja napsauta \\\"Keskeytä tehtävä\\\"-kuvaketta edetäksesi. Tehtävän keskeyttäminen muualla lopettaa tehtävän.\"\n  STR_TLETH_ATTACK_MISSION: \"HYÖKKÄYS T'LETHIIN{NEWLINE}MUUKALAISTEN KAUPUNKI TASO KAKSI\"\n  STR_TLETH_P2_BRIEFING: \"Syvemmälle tuntemattomaan; tästä eteenpäin mitä tahansa voi olla odottamassa meitä. Tiedämme, että muukalaiskaupungissa on vielä yksi lisäkerros, ja ryhmäsi on kiirehdittävä tämän kerroksen uloskäynnille siirtyäkseen seuraavaan. Sijoita kaikki akvanautit uloskäynnille ja napsauta \\\"Keskeytä tehtävä\\\"-kuvaketta edetäksesi. Tehtävän keskeyttäminen muualla lopettaa tehtävän.\"\n  STR_FINAL_TLETH_MISSION: \"VIIMEINEN TEHTÄVÄ{NEWLINE}MUUKALAISTEN KAUPUNKI TASO KOLME\"\n  STR_TLETH_P3_BRIEFING: \"Loppu häämöttää; tästä eteenpäin etsimme Korkeimman Muukalaisen kryptaa. Tuhoa haudan kahdeksan voiman syöttölähdettä tehdäksesi lopun muukalaisuhasta. Älä luovuta nyt! Keskeyttäminen lopettaa tehtävän.\"\n  STR_TLETH_P1: \"MUUKALAISTEN KAUPUNKI TASO YKSI\"\n  STR_TLETH_P2: \"MUUKALAISTEN KAUPUNKI TASO KAKSI\"\n  STR_TLETH_P3: \"MUUKALAISTEN KAUPUNKI TASO KOLME\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"EI VAPAATA TELAKKAA RAKENNUSPROJEKTIA VARTEN!{SMALLLINE}Jokainen tukikohtaan sijoitettu, siirretty, hankittu tai rakennettu lentosukellusvene vie yhden telakan verran tilaa. Rakenna uusi telakka tai siirrä jokin toinen alus toiseen tukikohtaan.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"EI VAPAATA TELAKKAA TILAUSTA VARTEN!{SMALLLINE}Jokainen tukikohtaan sijoitettu, siirretty, hankittu tai rakennettu lentosukellusvene vie yhden telakan verran tilaa. Rakenna uusi telakka tai siirrä jokin toinen alus toiseen tukikohtaan.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"EI VAPAATA TELAKKAA SIIRTOA VARTEN!{SMALLLINE}Jokainen tukikohtaan sijoitettu, siirretty, hankittu tai rakennettu lentosukellusvene vie yhden telakan verran tilaa. Rakenna uusi telakka tai siirrä jokin toinen alus toiseen tukikohtaan.\"\n  STR_CANNOT_BUILD_HERE: \"TÄHÄN EI VOI RAKENTAA!{SMALLLINE}Sinun täytyy rakentaa jonkin toisen valmiin laitoksen viereen.\"\n  STR_NO_FREE_ACCOMODATION: \"EI RIITTÄVIÄ ASUINTILOJA!{SMALLLINE}Kohdetukikohdassa ei ole riittävästi asuintiloja.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"TYÖSKENTELYTILAA EI OLE TARPEEKSI!{SMALLLINE}Rakenna lisää työpajoja tai vähennä työskenteleviä insinöörejä muissa projekteissa.\"\n  STR_NOT_ENOUGH_MONEY: \"RAHAA EI OLE RIITTÄVÄSTI!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"VARASTOTILA LOPPU!{SMALLLINE}Rakenna uusi varasto tai siirrä esineitä toisiin tukikohtiin.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"ASUINTILOJA EI OLE RIITTÄVÄSTI!{SMALLLINE}Rakenna lisää asuintiloja tai siirrä henkilökuntaa toisiin tukikohtiin.\"\n  STR_LAUNCH_INTERCEPTION: \"LÄHETÄ ALUS\"\n  STR_CRAFT: \"ALUS\"\n  STR_STATUS: \"TILA\"\n  STR_BASE: \"TUKIKOHTA\"\n  STR_READY: \"VALMIS\"\n  STR_OUT: \"ULKONA\"\n  STR_REPAIRS: \"KORJATAAN\"\n  STR_REFUELLING: \"TANKATAAN\"\n  STR_REARMING: \"ASEISTETAAN\"\n  STR_TARGET: \"KOHDE: {0}\"\n  STR_WAY_POINT: \"VÄLIETAPPI\"\n  STR_ARE_YOU_SURE_CYDONIA: \"Oletko varma, että haluat lähettää tämän aluksen tehtävälle T'lethiin?\"\n  STR_YES: \"KYLLÄ\"\n  STR_NO: \"EI\"\n  STR_SELECT_DESTINATION: \"VALITSE MÄÄRÄNPÄÄ\"\n  STR_CYDONIA: \"T'LETH\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"VALITSE SIJAINTI UUDELLE TUKIKOHDALLE\"\n  STR_RETURN_TO_BASE: \"PALAA TUKIKOHTAAN\"\n  STR_SELECT_NEW_TARGET: \"VALITSE UUSI KOHDE\"\n  STR_PATROL: \"PARTIO\"\n  STR_STATUS_: \"TILA>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"VAURIOITUNUT - PALAA TUKIKOHTAAN\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"POLTTOAINE VÄHISSÄ - PALAA TUKIKOHTAAN\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"TEHTÄVÄ PÄÄTTYNYT - PALAA TUKIKOHTAAN\"\n  STR_PATROLLING: \"PARTIOI\"\n  STR_TAILING_UFO: \"SEURATAAN MUUKALAISALUSTA\"\n  STR_INTERCEPTING_UFO: \"KOHTEENA MUUKALAISALUS-{0}\"\n  STR_RETURNING_TO_BASE: \"PALAA TUKIKOHTAAN\"\n  STR_DESTINATION_UC_: \"MÄÄRÄNPÄÄ: {0}\"\n  STR_BASE_UC: \"TUKIKOHTA>{ALT}{0}\"\n  STR_SPEED_: \"NOPEUS>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"MAKSIMINOPEUS>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"SYVYYS>{ALT}{0}\"\n  STR_AIRBORNE: \"ILMASSA\"\n  STR_VERY_LOW: \"LÄHELLÄ PINTAA\"\n  STR_LOW_UC: \"NORMAALI\"\n  STR_HIGH_UC: \"SYVÄLLÄ\"\n  STR_VERY_HIGH: \"ERITTÄIN SYVÄLLÄ\"\n  STR_FUEL: \"POLTTOAINE>{ALT}{0}\"\n  STR_WEAPON_ONE: \"ASE 1>{ALT}{0}\"\n  STR_NONE_UC: \"EI MITÄÄN\"\n  STR_ROUNDS_: \"AMMUKSIA>{ALT}{0}\"\n  STR_WEAPON_TWO: \"ASE 2>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"LENTOSUKELLUSVENE\"\n  STR_BASE_: \"Tukikohta>{0}\"\n  STR_NAME_UC: \"NIMI\"\n  STR_AMMO_: \"AMMUKSET>{ALT}{0}\"\n  STR_CREW: \"MIEHISTÖ\"\n  STR_EQUIPMENT_UC: \"VARUSTEET\"\n  STR_ARMOR: \"PANSSARIT\"\n  STR_MAX: \"MAKSIMI>{ALT}{0}\"\n  STR_ROOKIE: \"Matruusi\"\n  STR_SQUADDIE: \"Ylimatruusi\"\n  STR_SERGEANT: \"Aliluutnantti\"\n  STR_CAPTAIN: \"Luutnantti\"\n  STR_COLONEL: \"Komentajakapteeni\"\n  STR_COMMANDER: \"Komentaja\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Sotilaat aluksessa {0}\"\n  STR_SORT_BY: \"LAJITTELUPERUSTE...\"\n  STR_ORIGINAL_ORDER: \"ALKUPERÄISJÄRJESTYS\"\n  STR_MISSIONS2: \"TEHTÄVÄT\"\n  STR_KILLS2: \"TAPOT\"\n  STR_WOUND_RECOVERY2: \"TOIPILASAIKA\"\n  STR_SPACE_AVAILABLE: \"TILAA VAPAANA>{ALT}{0}\"\n  STR_SPACE_USED: \"TILANKÄYTTÖ>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"KÄYTETTY TILA\"\n  STR_RANK: \"SOTILASARVO\"\n  STR_WOUNDED: \"HAAVOITTUNUT\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Varusteet aluksessa {0}\"\n  STR_DEFENSE_VALUE: \"Puolustusarvo\"\n  STR_HIT_RATIO: \"Osumatarkkuus\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}on valmis laskeutumaan:{NEWLINE}{ALT}{1}{NEWLINE}\"\n  STR_BEGIN_MISSION: \"Aloitetaanko tehtävä?\"\n  STR_SELECT_ARMAMENT: \"Valitse aseistus\"\n  STR_AMMUNITION_AVAILABLE: \"AMMUKSIA SAATAVANA\"\n  STR_ARMAMENT: \"ASEISTUS\"\n  STR_NOT_AVAILABLE: \"EI TARV\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"VALITSE PANSSARI SOTILAALLE{NEWLINE}{ALT}{0}\"\n  STR_TYPE: \"TYYPPI\"\n  STR_PLASTIC_AQUA_ARMOR_UC: \"AKVAMUOVIPANSSARI\"\n  STR_ION_ARMOR_UC: \"IONIPANSSARI\"\n  STR_MAGNETIC_ION_ARMOR_UC: \"MAGNEETTINEN IONIPANSSARI\"\n  STR_PLASTIC_AQUA_ARMOR_UFOPEDIA: \"Tämä panssari hyödyntää hiljan löydettyä muukalaisainetta, akvaplastiikkaa, ja antaa akvanauteillemme pienen mahdollisuuden taistella muukalaisten hyökkäystä vastaan.\"\n  STR_ION_ARMOR_UFOPEDIA: \"Uusi voimakas suojus akvanauteille; tämä panssari käyttää ionivoimanlähdettä ja vahvistaa suuresti pukijan nopeutta ja voimaa tarjoten tähän mennessä parhaan suojauksen taistelujoukoille.\"\n  STR_MAGNETIC_ION_ARMOR_UFOPEDIA: \"Parannus, joka sisällyttää magneettikenttäteknologian ionipanssariin mahdollistaen täyden liikkumavapauden vedenalaisessa ympäristössä.\"\n  STR_SELECT_ARMOR: \"Valitse panssari\"\n  STR_NORTH: \"POHJOINEN\"\n  STR_NORTH_EAST: \"KOILLINEN\"\n  STR_EAST: \"ITÄ\"\n  STR_SOUTH_EAST: \"KAAKKO\"\n  STR_SOUTH: \"ETELÄ\"\n  STR_SOUTH_WEST: \"LOUNAS\"\n  STR_WEST: \"LÄNSI\"\n  STR_NORTH_WEST: \"LUODE\"\n  STR_SELECT_ACTION: \"VALITSE TOIMINTO\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"JATKA TORJUNTATEHTÄVÄÄ\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"JATKA ILMAN HYÖKKÄYSTÄ\"\n  STR_VERY_LARGE: \"ERITTÄIN SUURI\"\n  STR_LARGE: \"SUURI\"\n  STR_MEDIUM_UC: \"KESKIKOKOINEN\"\n  STR_SMALL: \"PIENI\"\n  STR_VERY_SMALL: \"HYVIN PIENI\"\n  STR_GROUNDED: \"LASKEUTUNUT\"\n  STR_DETECTED: \"Havaittu\"\n  STR_SIZE_UC: \"KÄYTÖSSÄ\"\n  STR_ALTITUDE: \"SYVYYS\"\n  STR_HEADING: \"SUUNTA\"\n  STR_SPEED: \"NOPEUS\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"KOHDISTA MUUKALAISALUKSEEN - AIKA=5 s\"\n  STR_TRACKING_LOST: \"SEURANTAJÄLKI KATOSI\"\n  STR_REDIRECT_CRAFT: \"UUDELLEENOHJAA ALUS\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"MENE VIIMEISEEN TUNNETTUUN SIJAINTIIN\"\n  STR_UFO_: \"MUUKALAISALUS-{0}\"\n  STR_ALIEN_BASE_: \"MUUKALAISYHDYSKUNTA-{0}\"\n  STR_CRASH_SITE_: \"PAKKOLASKUKOHDE-{0}\"\n  STR_LANDING_SITE_: \"LASKEUTUNUT MUUKALAISALUS-{0}\"\n  STR_WAY_POINT_: \"VÄLIETAPPI {0}\"\n  STR_TERROR_SITE: \"TERRORIKOHDE-{0}\"\n  STR_ARTIFACT_SITE: \"ARTEFAKTIKOHDE {0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}on saapunut{NEWLINE}{1}:een\"\n  STR_NOW_PATROLLING: \"Partiointi aloitettu\"\n  STR_ALIEN_ORIGINS: \"Muukalaisten alkuperä\"\n  STR_THE_ULTIMATE_THREAT: \"Suurin uhka\"\n  STR_TLETH_ALIEN_CITY: \"T'leth, muukalaisten kaupunki\"\n  STR_UFOPAEDIA: \"Ufopedia\"\n  STR_XCOM_CRAFT_ARMAMENT: \"X-COMIN ALUKSET JA ASEISTUS\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"MIEHITTÄMÄTTÖMÄT TAISTELUKONEET\"\n  STR_WEAPONS_AND_EQUIPMENT: \"YLEISVARUSTEET\"\n  STR_ALIEN_ARTIFACTS: \"AKVAATTISET VARUSTEET\"\n  STR_BASE_FACILITIES: \"X-COMIN LAITOKSET\"\n  STR_ALIEN_LIFE_FORMS: \"MUUKALAISOLENNOT\"\n  STR_ALIEN_RESEARCH_UC: \"MUUKALAISTEKNOLOGIA\"\n  STR_UFO_COMPONENTS: \"UUDET VEDENALAISET TEKNOLOGIAT\"\n  STR_UFOS: \"MUUKALAISSUKELLUSVENEET\"\n  STR_SELECT_ITEM: \"VALITSE AIHE\"\n  STR_ACCELERATION: \"KIIHTYVYYS>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"POLTTOAINETANKKI>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"ASEPAIKAT>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"KESTÄVYYS>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"RAHTITILA>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"MTK-TILA>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Tuhovoima\"\n  STR_RANGE: \"Kantama\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Tarkkuus\"\n  STR_RE_LOAD_TIME: \"Uudelleenlatausaika\"\n  STR_SECONDS: \"{0}s\"\n  STR_DAMAGE_ARMOR_PIERCING: \"TAVALLINEN(AP)\"\n  STR_DAMAGE_INCENDIARY: \"FOSFORI\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"RÄJÄHDE\"\n  STR_DAMAGE_LASER_BEAM: \"GAUSS\"\n  STR_DAMAGE_PLASMA_BEAM: \"ÄÄNIAALTO\"\n  STR_DAMAGE_STUN: \"JÄÄDYTYS\"\n  STR_DAMAGE_MELEE: \"LÄHITAISTELU\"\n  STR_DAMAGE_ACID: \"HAPPO\"\n  STR_DAMAGE_SMOKE: \"SAVU\"\n  STR_SHOT_TYPE: \"TYYPPI\"\n  STR_ACCURACY_UC: \"TARKKUUS\"\n  STR_TIME_UNIT_COST: \"AY HINTA\"\n  STR_DAMAGE_UC: \"TYYPPI\"\n  STR_AMMO: \"AMMUS\"\n  STR_SHOT_TYPE_AUTO: \"Sarjatuli\"\n  STR_SHOT_TYPE_SNAP: \"Kertatuli\"\n  STR_SHOT_TYPE_AIMED: \"Tähdätty\"\n  STR_CONSTRUCTION_TIME: \"Rakennusaika\"\n  STR_CONSTRUCTION_COST: \"Rakennuskustannukset\"\n  STR_MAINTENANCE_COST: \"Ylläpitokustannukset\"\n  STR_LOW: \"Matala\"\n  STR_MEDIUM: \"Keskikokoinen\"\n  STR_HIGH: \"Korkea\"\n  STR_CRAFT_WEAPON: \"Aluksen ase\"\n  STR_CRAFT_AMMUNITION: \"Aluksen ammukset\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Miehittämätön taistelukone\"\n  STR_WEAPON: \"Ase\"\n  STR_AMMUNITION: \"Ammukset\"\n  STR_EQUIPMENT: \"Varusteet\"\n  STR_ALIEN_CORPSE: \"Muukalaisen ruumis\"\n  STR_UFO_COMPONENT: \"MUUKALAISALUKSEN osa\"\n  STR_PERSONAL_ARMOR: \"Henkilöpanssari\"\n  STR_RAW_MATERIALS: \"Raaka-aineet\"\n  STR_HWP_SOLID_HARPOON_BOLTS: \"Kokovaippaharppuunat\"\n  STR_ALIEN: \"Muukalainen\"\n  STR_AQUATOID: \"Akvatoidi\"\n  STR_GILLMAN: \"Kidusihminen\"\n  STR_LOBSTERMAN: \"Hummerimies\"\n  STR_TASOTH: \"Tasootti\"\n  STR_CALCINITE: \"Kalsiniitti\"\n  STR_DEEP_ONE: \"Syväläinen\"\n  STR_BIODRONE: \"Biodroidi\"\n  STR_TENTACULAT: \"Lonkeromanaaja\"\n  STR_TRISCENE: \"Triaslisko\"\n  STR_HALLUCINOID: \"Hallusinoidi\"\n  STR_XARQUID: \"Kalmanhelmi\"\n  STR_ZOMBIE: \"Zombi\"\n  STR_LIVE_COMMANDER: \"Komentaja\"\n  STR_LIVE_NAVIGATOR: \"Navigoija\"\n  STR_LIVE_MEDIC: \"Lääkintämies\"\n  STR_LIVE_TECHNICIAN: \"Teknikko\"\n  STR_LIVE_SQUAD_LEADER: \"Ryhmänjohtaja\"\n  STR_LIVE_SOLDIER: \"Sotilas\"\n  STR_LIVE_TERRORIST: \"Terroristi\"\n  STR_AQUATOID_COMMANDER: \"Akvatoidikomentaja\"\n  STR_AQUATOID_NAVIGATOR: \"Akvatoidinavigoija\"\n  STR_AQUATOID_MEDIC: \"Akvatoidilääkintämies\"\n  STR_AQUATOID_TECHNICIAN: \"Akvatoiditeknikko\"\n  STR_AQUATOID_SQUAD_LEADER: \"Akvatoidiryhmänjohtaja\"\n  STR_AQUATOID_SOLDIER: \"Akvatoidisotilas\"\n  STR_GILLMAN_COMMANDER: \"Kidusihmiskomentaja\"\n  STR_GILLMAN_TECHNICIAN: \"Kidusihmisteknikko\"\n  STR_GILLMAN_SQUAD_LEADER: \"Kidusihmisryhmänjohtaja\"\n  STR_GILLMAN_SOLDIER: \"Kidusihmissotilas\"\n  STR_LOBSTERMAN_COMMANDER: \"Hummerimieskomentaja\"\n  STR_LOBSTERMAN_NAVIGATOR: \"Hummerimiesnavigoija\"\n  STR_LOBSTERMAN_TECHNICIAN: \"Hummerimiesteknikko\"\n  STR_LOBSTERMAN_SQUAD_LEADER: \"Hummerimiesryhmänjohtaja\"\n  STR_LOBSTERMAN_SOLDIER: \"Hummerimiessotilas\"\n  STR_TASOTH_SQUAD_LEADER: \"Tasoottiryhmänjohtaja\"\n  STR_TASOTH_SOLDIER: \"Tasoottisotilas\"\n  STR_CALCINITE_TERRORIST: \"Kalsiniittiterroristi\"\n  STR_DEEP_ONE_TERRORIST: \"Syväläisterroristi\"\n  STR_BIODRONE_TERRORIST: \"Biodroiditerroristi\"\n  STR_TENTACULAT_TERRORIST: \"Lonkeromanaajaterroristi\"\n  STR_TRISCENE_TERRORIST: \"Triasliskoterroristi\"\n  STR_HALLUCINOID_TERRORIST: \"Hallusinoiditerroristi\"\n  STR_XARQUID_TERRORIST: \"Kalmanhelmiterroristi\"\n  STR_ION_BEAM_ACCELERATORS: \"Ionisädekiihdyttimet\"\n  STR_MAGNETIC_NAVIGATION: \"Magneettinen navigointilaite\"\n  STR_ALIEN_SUB_CONSTRUCTION: \"Muukalaissukellusveneen rakennus\"\n  STR_ALIEN_CRYOGENICS: \"Muukalaiskryogeniikka\"\n  STR_ALIEN_CLONING: \"Muukalaiskloonaus\"\n  STR_ALIEN_LEARNING_ARRAYS: \"Muukalaisten oppimislähetin\"\n  STR_ALIEN_IMPLANTER: \"Muukalaisten istuttaja\"\n  STR_EXAMINATION_ROOM: \"Tutkimushuone\"\n  STR_AQUA_PLASTICS: \"Akvaplastiikka\"\n  STR_ALIEN_REANIMATION_ZONE: \"Muukalaisten henkiinherättäjä\"\n  STR_PLASTIC_AQUA_ARMOR: \"Akvamuovipanssari\"\n  STR_ION_ARMOR: \"Ionipanssari\"\n  STR_MAGNETIC_ION_ARMOR: \"Magn. ionipanssari\"\n  STR_HWP_AQUA_JET_MISSILES: \"Akvasuihkutorpedot\"\n  STR_HWP_DISPLACER_PWT: \"KA-torpedo\"\n  STR_GAUSS_TECH: \"Gauss-teknologia\"\n  STR_NEW_FIGHTER_FLYING_SUB: \"Uusi hävittäjälentosukellusvene\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Uusi hävittäjä-kuljetusalus\"\n  STR_THE_LATEST_FLYING_SUB: \"Huippulentosukellusvene\"\n  STR_ARMOR_PIERCING: \"TAVALLINEN(AP)\"\n  STR_COELACANTH_GAS_CANNON: \"Varsieväkala/kaasutykki\"\n  STR_COELACANTH_AQUA_JET: \"Varsieväkala/akvasuihku\"\n  STR_COELACANTH_GAUSS: \"Varsieväkala/Gauss\"\n  STR_DISPLACER_SONIC: \"Syrjäytin/ääni\"\n  STR_DISPLACER_PWT: \"Syrjäytin/KAT\"\n  STR_AJAX_LAUNCHER: \"Ajax-torpedolaukaisin\"\n  STR_DUP_HEAD_LAUNCHER: \"KUP-kärkitorpedolaukaisin\"\n  STR_CRAFT_GAS_CANNON: \"Aluksen kaasutykki\"\n  STR_PWT_CANNON: \"KAT-tykki\"\n  STR_GAUSS_CANNON: \"Gauss-tykki\"\n  STR_GAUSS_CANNON_AMMO: \"Gauss-tykin ammukset\"\n  STR_SONIC_OSCILLATOR: \"Äänivärähtelijä\"\n  STR_AJAX_TORPEDOES: \"Ajax-torpedot\"\n  STR_DUP_HEAD_TORPEDOES: \"KUP-kärkitorpedot\"\n  STR_CRAFT_GAS_CANNON_ROUNDS_X50: \"Kaasuammus(x50)\"\n  STR_SONIC_WAVE: \"Ääniaalto\"\n  STR_PULSE_WAVE_TORPEDOES: \"KAT-ammukset\"\n  STR_SOLDIER: \"Akvanautti\"\n  STR_SCIENTIST: \"Tiedemies\"\n  STR_ENGINEER: \"Teknikko\"\n  STR_NORTH_ATLANTIC: \"Pohjois-Atlantti\"\n  STR_SOUTH_ATLANTIC: \"Etelä-Atlantti\"\n  STR_NORTH_PACIFIC: \"Pohjois-Tyynimeri\"\n  STR_SOUTH_PACIFIC: \"Etelä-Tyynimeri\"\n  STR_MEDITERRANEAN: \"Välimeri\"\n  STR_SOUTH_CHINA_SEA: \"Etelä-Kiinanmeri\"\n  STR_INDIAN_OCEAN: \"Intian valtameri\"\n  STR_THE_EAST_SEA: \"Japaninmeri\"\n  STR_NORTH_SEA: \"Pohjanmeri\"\n  STR_CARRIBEAN: \"Karibia\"\n  STR_ANTARCTIC: \"Eteläinen jäämeri\"\n  STR_ARCTIC: \"Pohjoinen jäämeri\"\n  STR_EURASIA: \"Euraasia\"\n  STR_NORTH_AMERICA: \"Pohjois-Amerikka\"\n  STR_AFRICA: \"Afrikka\"\n  STR_MAXIMUM_SPEED: \"Maksiminopeus\"\n  STR_TRANSMISSION_RESOLVER_UC: \"Viestiselvitin\"\n  STR_TRITON: \"TRITON\"\n  STR_HAMMERHEAD: \"VASARAHAI\"\n  STR_LEVIATHAN: \"LEVIATAN\"\n  STR_BARRACUDA: \"BARRAKUDA\"\n  STR_MANTA: \"RAUSKU\"\n  STR_UFO: \"MUUKALAISSUKELLUSVENE\"\n  STR_AJAX: \"AJAX\"\n  STR_DUP_HEAD: \"KUP-KÄRKI\"\n  STR_CRAFT_GAS_CANNON_UC: \"ALUKSEN KAASUTYKKI\"\n  STR_PWT_CANNON_UC: \"KAT-TYKKI\"\n  STR_GAUSS_CANNON_UC: \"GAUSS-TYKKI\"\n  STR_SONIC_OSCILLATOR_UC: \"ÄÄNIVÄRÄHTELIJÄ\"\n  STR_DAMAGE_CAPACITY: \"Kestävyys\"\n  STR_WEAPON_POWER: \"Tulivoima\"\n  STR_WEAPON_RANGE: \"Aseen kantama\"\n  STR_AIR_LOCK: \"Ilmalukko\"\n  STR_LABORATORY: \"Laboratorio\"\n  STR_WORKSHOP: \"Työpaja\"\n  STR_STANDARD_SONAR: \"Peruskaikuluotain\"\n  STR_WIDE_ARRAY_SONAR: \"Laajakaistaluotain\"\n  STR_TORPEDO_DEFENSES: \"Torpedopuolustus\"\n  STR_GENERAL_STORES: \"Varasto\"\n  STR_ALIEN_CONTAINMENT: \"Muukalaisten vankilaitos\"\n  STR_GAUSS_DEFENSES: \"Gauss-puolustus\"\n  STR_SONIC_DEFENSES: \"Äänipuolustus\"\n  STR_PWT_DEFENSES: \"KAT-puolustus\"\n  STR_BOMBARDMENT_SHIELD: \"Pommitussuoja\"\n  STR_MC_GENERATOR: \"MH-generaattori\"\n  STR_MC_LAB: \"MH-laboratorio\"\n  STR_TRANSMISSION_RESOLVER: \"Viestinselvitin\"\n  STR_SUB_PEN: \"Telakka\"\n  STR_USA: \"YHDYSVALLAT\"\n  STR_ALASKA: \"ALASKA\"\n  STR_EU_SYNDICATE: \"EUROSYNDIKAATTI\"\n  STR_ARABIAN_BLOC: \"ARABIBLOKKI\"\n  STR_EGYPTIAN_CARTEL: \"EGYPTIN KARTELLI\"\n  STR_AFRICA_CORP: \"AFRIKAN YHTEISÖ\"\n  STR_BRAZILIAN_UNION: \"BRASILIAN UNIONI\"\n  STR_NEW_MEXICO: \"UUSI-MEKSIKO\"\n  STR_ASIAN_COALITION: \"AASIAN KOALITIO\"\n  STR_SCANDINAVIA: \"SKANDINAVIA\"\n  STR_NEO_JAPAN: \"UUSI-JAPANI\"\n  STR_FREE_CHINA: \"VAPAA KIINA\"\n  STR_AUSTRALASIA: \"AUSTRALAASIA\"\n  STR_FED_KOREA: \"KOREAN LIITTO\"\n  STR_EURASIA_UC: \"EURAASIA\"\n  STR_ICELANDIC_UNION: \"ISLANNIN UNIONI\"\n  STR_TANK: \"Miehittämätön taistelukone\"\n  STR_CIVILIAN: \"Siviili\"\n  STR_JAN: \"1.\"\n  STR_FEB: \"2.\"\n  STR_MAR: \"3.\"\n  STR_APR: \"4.\"\n  STR_MAY: \"5.\"\n  STR_JUN: \"6.\"\n  STR_JUL: \"7.\"\n  STR_AUG: \"8.\"\n  STR_SEP: \"9.\"\n  STR_OCT: \"10.\"\n  STR_NOV: \"11.\"\n  STR_DEC: \"12.\"\n  STR_INTERNATIONAL_RELATIONS: \"Kansainväliset suhteet\"\n  STR_COUNTRY: \"Maa\"\n  STR_FUNDING: \"Rahoitus\"\n  STR_CHANGE: \"Muutos\"\n  STR_WEAPON_SYSTEMS: \"ASE-{NEWLINE}PAIKAT\"\n  STR_HWPS: \"MTKt\"\n  STR_DAMAGE_UC_: \"VAURIOASTE>{ALT}{0}\"\n  STR_AIR_LOCK_UFOPEDIA: \"Ilmalukko on ainoa reitti, jota kautta henkilökuntaa ja tarvikkeita voidaan siirtää vedenalaiseen tukikohtaan ja sieltä pois. Se on aina ensimmäinen osa tukikohtaa, joka rakennetaan. Ilmalukko ja sen ympäristö on haavoittuvainen mahdollisen ulkopuolisen hyökkäyksen tapauksessa.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Jokainen asuintilakompleksi sisältää riittävästi asuintilaa 50:lle henkilölle. Tilat ovat jokseenkin peruslaatuiset ja toimivat.\"\n  STR_LABORATORY_UFOPEDIA: \"50 tiedemiestä pystyy työskentelemään yksittäisessä laboratoriolohkossa. Laboratorioissa on viimeisin teknologia materiaalien, biokemian ja aseiden tutkimukseen. X-Comilla on etuoikeutettu etäyhteys maailman johtaviin niin siviili- kuin sotilaallisiin laboratorioihin.\"\n  STR_WORKSHOP_UFOPEDIA: \"Työpaja sisältää kaiken tarvittavan laitteiston erilaisten tarvikkeiden ja osien tuottamiseen tiedemiesten viimeisimpien suunnitelmien pohjalta. 50 teknikkoa voi työskennellä yhdessä työpajassa, joskin itse osien tuottaminen vie jonkin verran myös tästä tilasta.\"\n  STR_STANDARD_SONAR_UFOPEDIA: \"Peruskaikuluotaimella on yli 450 kilometrin toimintasäde useimmilla syvyyksillä, ja se on linkitetty geostationaarisiin satelliittiverkkoihin pintakohteiden analysointia varten. Kullakin luotaimella on 10 % todennäköisyys havaita sukellusvene tai lentokone kutakin 30 minuutin kuvausjaksoa kohden.\"\n  STR_WIDE_ARRAY_SONAR_UFOPEDIA: \"Laajakaistakaikuluotaimella on yli 700 kilometrin toimintasäde kaikilla syvyyksillä, ja se on linkitetty geostationaarisiin satelliittiverkkoihin pintakohteiden analysointia varten. Kullakin luotaimella on 20 % todennäköisyys havaita sukellusvene tai lentokone kutakin 30 minuutin kuvausjaksoa kohden.\"\n  STR_TORPEDO_DEFENSES_UFOPEDIA: \"Torpedopuolustusjärjestelmä tarjoaa suojaa vihamielisten sukellusveneiden yrittäessä telakoitua tukikohtaan.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"Kaikki varusteet, asejärjestelmät, ammukset, saaliiksi saadut materiaalit ja miehittämättömät taistelukoneet (MTK:t) varastoidaan, myös silloin, kun ne on määrätty johonkin sukellusveneeseen telakassa.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"Elävät muukalaiset tarvitsevat erityisen eristyslaitoksen niiden pitämiseksi. Nämä yksiköt pitävät yllä niiden elintoimintoja ja nollaavat niiden taistelupotentiaalin. Tällaiseen vankilaitokseen mahtuu 10 muukalaista vankiyksiköihin.\"\n  STR_GAUSS_DEFENSES_UFOPEDIA: \"Gauss-puolustusjärjestelmä tarjoaa viimeisintä ja tehokkainta suojaa vihamielisten sukellusveneiden lähestyessä tukikohtaa.\"\n  STR_SONIC_DEFENSES_UFOPEDIA: \"Äänivärähtelijäpuolustusjärjestelmä tarjoaa voimakasta ja tehokasta suojaa hyökkääjiä vastaan.\"\n  STR_PWT_DEFENSES_UFOPEDIA: \"Kanttiaaltotorpedojen avulla on mahdollista toteuttaa tehokkain tunnettu puolustus muukalaisten hyökkäystä vastaan. Näillä ohjuksilla on erittäin tiheä taistelukärki, joka pystyy läpäisemään kaiken tunnetun panssarin. Niiden tuottamat magneettiset aallot lamaannuttavat elektroniset puolustusjärjestelmät.\"\n  STR_BOMBARDMENT_SHIELD_UFOPEDIA: \"Painepommitussuoja suojaa tukikohtaa telakoituvilta muukalaissukellusveneiltä pystyttämällä resonoivan kentän, joka hylkii hyökkääviä sukellusveneitä tarpeeksi pitkään, jotta puolustusjärjestelmät ehtivät ampua toistuvasti. Käytännössä tämä tarkoittaa, että jo valjastettujen puolustusjärjestelmien tehokkuus kaksinkertaistuu.\"\n  STR_MC_GENERATOR_UFOPEDIA: \"Koska muukalaissukellusveneet käyttävät molekulaarista hallintateknologiaa havaitsemaan elävien olentojen läsnäoloa, negatiivisen MH-lähettimen käyttäminen verhoaa tukikohdan läpitunkemattomalla kilvellä muukalaisten hämäämiseksi ja läsnäolomme naamioimiseksi.\"\n  STR_MC_LAB_UFOPEDIA: \"Molekulaarisen hallinnan laboratorio voi istuttaa ja kouluttaa enimmillään kymmentä akvanauttia kerrallaan. Implantit asennetaan kirurgisesti akvanauttien pääkalloihin. Kattava koulutus antaa heille kyvyn hyödyntää implanttejaan. Implanttitaitoja käytetään yhdessä molekulaarisen häirintälaitteen kanssa, ja niitä voi käyttää hyökkäyksiin taistelun aikana.\"\n  STR_TRANSMISSION_RESOLVER_UFOPEDIA: \"Muukalaisten viestintä hyödyntää heidän rakentamaansa molekulaarisen hallinnan implanttiverkkoaan. Viestinselvitinlaitos kaappaa muukalaissukellusveneiden viestit sekä tulkitsee niiden sisältämän tiedon. Näin saamme tietoomme sukelusveneen tyypin, kyseessä olevan muukalaislajin sekä minkälaisella tehtävällä alus on.\"\n  STR_SUB_PEN_UFOPEDIA: \"Jokaiseen sukellusvenetelakkaan mahtuu yksi lentosukellusvene. Näissä halleissa on kaikki tarvittava X-Com-laivueen huoltoa, tankkausta ja korjausta varten. Jokainen alus, joka on määrätty tukikohtaan, vaatii oman telakkansa, eikä sitä voi käyttää samanaikaisesti mikään muu alus, ei vaikka laitokseen määrätty sukellusvene olisi suorittamassa tehtävää.\"\n  STR_DART_PISTOL_UFOPEDIA: \"X-Com-nuolipyssy on pieni, tarkka ja suuritehoinen laite, jonka lippaaseen mahtuu 12 onttoa nuoliammusta. Nuolet laukaistaan ammuskotelon kaasupatruunan avulla.\"\n  STR_JET_HARPOON_UFOPEDIA: \"Tämä tarkka ja tehokas akvakivääri ampuu onttoja teräsharppuunoita tiivistetyistä 10 kappaleen koteloista. Kullakin harppuunalla on oma kaasulähteensä.\"\n  STR_GAS_CANNON_UFOPEDIA: \"Tämä kaasuteknologiaperheen raskassarjalainen ampuu umpinaisia nuolia, jotka voidaan varustaa räjähtävillä tai fosforikärjillä. Suosikkiase kokeneiden akvanauttien keskuudessa.\"\n  STR_HYDRO_JET_CANNON_UFOPEDIA: \"Hydrosuihkukanuuna on raskaan jalkaväen asejärjestelmä. Se ampuu magnesiumkäyttöisiä minitorpedoja. Vaikkakin tehokas, hydrosuihkukanuuna on kömpelö ja painava laite, joka soveltuu ainoastaan vedenalaiseen käyttöön.\"\n  STR_TORPEDO_LAUNCHER_UFOPEDIA: \"Todellisena raskassarjalaisena tämä suuri laukaisin ampuu kolmea eri tyyppistä torpedoa, joista kullakin on oma työntövoimayksikkönsä. Tuhoisa ase, jonka heikkoutena on, että se on mahdollista ladata ainoastaan käsin. Saatavilla olevat ammustyypit ovat pien- ja suurräjähde- sekä fosforikärkiset torpedot, joista kaikki soveltuvat ainoastaan vedenalaiseen käyttöön.\"\n  STR_GAUSS_PISTOL_UFOPEDIA: \"Gauss-pistooli käyttää hiukkaskiihdytinteknologiaa, joka on uusi kehitysaskel nykyaikaisessa asetekniikassa. Se on nopea, tarkka ja toimii sekä veden yllä että alla. Gauss-teknologia on kehitetty viime sodasta opitun plasmateknologian pohjalta.\"\n  STR_GAUSS_PISTOL_CLIP_UFOPEDIA: \"Gauss-pistooli käyttää hiukkaskiihdytinteknologiaa, joka on uusi kehitysaskel nykyaikaisessa asetekniikassa. Se on nopea, tarkka ja toimii sekä veden yllä että alla. Gauss-teknologia on kehitetty viime sodasta opitun plasmateknologian pohjalta.\"\n  STR_GAUSS_RIFLE_UFOPEDIA: \"Seuraavana askeleena gauss-pistoolista on tulivoimainen kivääri kaksoishiukkaskiihdyttimineen. Olemme korvanneet eleriumpohjaisen plasmajärjestelmän mikrohiukkaskiihdyttimellä, joka synnyttää antiprotonisuihkun.\"\n  STR_GAUSS_RIFLE_CLIP_UFOPEDIA: \"Seuraavana askeleena gauss-pistoolista on tulivoimainen kivääri kaksoishiukkaskiihdyttimineen. Olemme korvanneet eleriumpohjaisen plasmajärjestelmän mikrohiukkaskiihdyttimellä, joka synnyttää antiprotonisuihkun.\"\n  STR_HEAVY_GAUSS_UFOPEDIA: \"Gauss-käsitykki on kömpelö käsiase, joskin erittäin tehokas. Se käyttää kolmea hiukkaskiihdytintä ja on lähes pysäyttämätön. Antiprotonisuihku on vangittu galliumarsenidikuoreen, joka törmätessään kohteeseensa luhistuu vapauttaen antimaterian.\"\n  STR_HEAVY_GAUSS_CLIP_UFOPEDIA: \"Gauss-käsitykki on kömpelö käsiase, joskin erittäin tehokas. Se käyttää kolmea hiukkaskiihdytintä ja on lähes pysäyttämätön. Antiprotonisuihku on vangittu galliumarsenidikuoreen, joka törmätessään kohteeseensa luhistuu vapauttaen antimaterian.\"\n  STR_MAGNA_BLAST_GRENADE_UFOPEDIA: \"Tämä käsikranaatti on varustettu hienostuneella ajastinmekanismilla, joka mahdollistaa räjähtämisajan tarkan kontrolloinnin.\"\n  STR_DYE_GRENADE_UFOPEDIA: \"Kahta roolia täyttävät väriainekranaatit ovat hyödyllisiä vähentämään näkyvyyttä avonaisilla alueilla. Toimien sekä vesi- että maaolosuhteissa väriaine poistuu pisarapilvenä tuottaen mustekalamaisen mustesuihkun vedessä tai tiiviin ilmassa leijuvan pilven maalla.\"\n  STR_PARTICLE_DISTURBANCE_GRENADE_UFOPEDIA: \"Sensorikranaattia voidaan käyttää kuten tavallista kranaattia, mutta se räjähtää vasta, kun sen liiketunnistin havaitsee liikettä riittävän lähellä asetetun aktivoitumisajan jälkeen. Sen tehokas käyttö taistelutilanteessa vaatii paljon taitoa sekä koulutusta.\"\n  STR_MAGNA_PACK_EXPLOSIVE_UFOPEDIA: \"Tätä räjähdettä tulisi käyttää vain purkutöihin. Aiempi kokemus on kuitenkin osoittanut, että nämä voimakkaat räjäytepanokset ovat ihanteellisia aseita muukalaisten esiin kaivamiseen. Räjähdyksen vaikutusalue on laaja, joten varmista, että akvanautit ovat vähimmäisturvavälimatkan päässä.\"\n  STR_PARTICLE_DISTURBANCE_SENSOR_UFOPEDIA: \"Tämä uusi laite käyttää useita erilaisia ilmaisimia ja kehittyneitä tietokonealgoritmeja tunnistaakseen liikkuvia kohteita. Napsauta häiriöilmaisinkuvaketta taktisessa taistelunäkymässä. Valitse \\\"Käytä ilmaisinta\\\" valikosta. Ilmaisimen näytössä näkyy nuoli, joka kuvaa käyttäjän katselusuuntaa (pohjoinen on aina ylhäällä). Näytöllä vilkkuvat täplät ilmaisevat kohteet, jotka ovat hiljattain liikkuneet. Suuret ja/tai nopeasti liikkuvat kohteet synnyttävät suurempia täpliä. Liikkumattomat kohteet eivät näy.\"\n  STR_MEDI_KIT_UFOPEDIA: \"Käytä seisomalla vastatusten haavoittuneen X-Com-agentin kanssa tai suoraan tajuttoman akvanautin yllä.{NEWLINE}PARANNA> Punainen ilmaisee haavo-ja. Valitse ruumiinosa ja napsauta \\\"Paranna\\\"-nappia. Yksi vakava haava parannetaan ja osa terveydestä palautuu.{NEWLINE}PIRISTE> Palauttaa osan potilaan energiasta sekä herättää tajut-toman akvanautin. Herättääksesi tajuttoman akvanautin sinun tulee seistä aivan sotilaan yläpuolella. {NEWLINE}KIPULÄÄKE> Kipulääkkeen antaminen palauttaa haavoittuneen sotilaan taistelutahtoa.\"\n  STR_MC_DISRUPTOR_UFOPEDIA: \"MH-teknologian huipentuma, jota voivat käyttää ainoastaan akvanautit, joilla on MH-kykyjä. Napsauta häirintälaitetta valitaksesi hyökkäyksen tyypin ja sen jälkeen hyökkäyksen kohteen. Hyökkäyksiä on kahta eri tyyppiä:{NEWLINE}HÄIRITSE IMPLANTTIA>Jos hyökkäys onnistuu, se hämmentää kohdetta, mikä saattaa johtaa kohteen panikointiin.{NEWLINE}KAAPPAA IMPLANTTI>Jos hyökkäys onnistuu, saat vihollisyksikön hallintaasi.\"\n  STR_THERMAL_TAZER_UFOPEDIA: \"Tätä laitetta voidaan käyttää vain lähietäisyydeltä. Se tainnuttaa kohteen tappamatta sitä jäädyttämällä kohteen.\"\n  STR_VIBRO_BLADE_UFOPEDIA: \"Titaaninen veitsenterävä pitkä vibroterä, jonka kierrosluku on yli 6000 rpm, kykenee tunkeutumaan vahvimmankin sukelluspanssarin läpi. Voimanlähde on muukalaiskeksintö. Aiemmat yrityksemme rakentaa näitä esineitä epäonnistuivat surkeasti terien pyöriessä liian hitaasti tai räjähtäessä paineen vaikutuksesta.\"\n  STR_THERMIC_LANCE_UFOPEDIA: \"Terminen peitsi on looginen vibroteräteknologian jatkumo. Terä pyörii suurella nopeudella, ja zrbiittivoimanlähde ylikuumentaa terän leikkaamaan panssaria, kuin lämmin veitsi leikkaa voita.\"\n  STR_HEAVY_THERMIC_LANCE_UFOPEDIA: \"Raskas terminen peitsi on TP:n tehokkaampi versio. Kaksoislämmönlähteet sekä äärimmäisen korkea kierrosluku tekevät raskaasta termisestä peitsestä käytännössä pysäyttämättömän kaikkia materiaaleja vastaan.\"\n  STR_SONIC_CANNON_UFOPEDIA: \"Äänikanuuna on ääniaseperheen voimakkain. Siinä on korkeamman äänialan värähtelijä ja suurempi kaikukammio kuin Blastassa. Kanuunassa on myös pulssiräjäytysjärjestelmä, joka muuntaa ultraääniaallon modulaatiolla, joka tuottaa tehokkaamman äänenpaineaallon.\"\n  STR_CANNON_POWER_CLIP_UFOPEDIA: \"Tämä kompakti laite toimii äänikanuunan ammuslippaana. Se sisältää pienen määrän zrbiittiä.\"\n  STR_SONIC_BLASTA_RIFLE_UFOPEDIA: \"Voimakkaampi ääniase. Edes runsashiiliteräs ei ole immuuni tälle aseelle. Erittäin kompaktia aaltolähdettä tehostaa suprajohdevahvistin, joka lisää aseen tehoa.\"\n  STR_BLASTA_POWER_CLIP_UFOPEDIA: \"Tämä pieni esine toimii voimanlähteenä äänikiväärille, voimakkaalle muukalaisaseelle, ja sisältää pienen määrän zrbiittiä.\"\n  STR_SONIC_PISTOL_UFOPEDIA: \"Äänipistoolit ovat muukalaisaseita, jotka perustuvat ultraääniaaltoihin, jotka voivat hyytelöidä luun sekunneissa. Ultraääniaallot ovat ihmiskuuloaistin ulkopuolella.\"\n  STR_PISTOL_POWER_CLIP_UFOPEDIA: \"Kompaktin muukalaisäänipistoolin voimanlähde sisältää zrbiittiä, joka on kaiken muukalaisten käyttövoiman lähde.\"\n  STR_DISRUPTOR_PULSE_LAUNCHER_UFOPEDIA: \"Tämä on muukalaisten vain veden alla toimiva älykäs ase, joka laukaisee \\\"hajotusammuksia\\\". Kun napsautat laukaisutoimintoa, voit kohdistaa etappipisteitä, joiden kautta ohjus kulkee viimeiseen ohjelmoituun etappipisteeseen asti. Kun olet ohjelmoinut riittävästi etappipisteitä, napsauta laukaisukuvaketta.\"\n  STR_DISRUPTOR_AMMO_UFOPEDIA: \"Tämä laite on hajotuspulssiammus, jossa on tietokoneohjausjärjestelmä. Se laukaistaan hajotuspulssilaukaisimen avulla.\"\n  STR_THERMAL_SHOK_LAUNCHER_UFOPEDIA: \"Ase, jolla voi laukaista kemiallisia jäädytyspommeja. Se on erittäin käyttökelpoinen elävien muukalaisten kaappaamisessa.\"\n  STR_THERMAL_SHOK_BOMB_UFOPEDIA: \"Lämpösokkipommia käytetään elävien ihmisten kaappaamiseen, mutta se on käyttökelpoinen myös useimpien muukalaisten tainnuttamisessa. Sen ampumiseen käytetään lämpösokkilaukaisinta.\"\n  STR_SONIC_PULSER_UFOPEDIA: \"Tämä laite toimii samalla tavalla kuin vakiokranaatti, paitsi että se on monta kertaa tehokkaampi. Kranaatti lähettää samanaikaisesti kaikkiin suuntiin yksittäisen äänenpaineaaltopulssin.\"\n  STR_MC_READER_UFOPEDIA: \"Olemme löytäneet muukalaisruumiista pieniä kirugisesti istutettuja laitteita. Nämä ovat akvatoidien kehittämiä hallintaimplantteja, jotka mahdollistavat jatkuvan tiedonsyötön taistelukentältä suurtenkin etäisyyksien päästä. Molekulaarisen hallinan lukijalaite on muukalaisten viestintälaite, jolla voi lukea tietoa suoraan MH-implanteista. X-Com-sotilaat pystyvät käyttämään tätä laitetta taistelussa saadakseen tietoa muukalaisen ominaisuuksista. Valitse \\\"Käytä lukijaa\\\"-vaihtoehto, ja sen jälkeen valitse muukalainen osoittimella.\"\n  STR_SURVEY_SHIP: \"Kartoitusalus\"\n  STR_ESCORT: \"Saattuealus\"\n  STR_CRUISER: \"Risteilijä\"\n  STR_HEAVY_CRUISER: \"Raskas risteilijä\"\n  STR_HUNTER: \"Saalistaja\"\n  STR_BATTLESHIP: \"Taistelualus\"\n  STR_DREADNOUGHT: \"Dreadnought\"\n  STR_FLEET_SUPPLY_CRUISER: \"Kuljetusristeilijä\"\n  MAP_SEABED: \"Merenpohja\"\n  MAP_PIPES: \"Tutkimuslaitos\"\n  MAP_PLANE: \"Maahansyöksynyt lentokone\"\n  MAP_ATLAN: \"Atlantis\"\n  MAP_MU: \"Mayatemppeli\"\n  MAP_GAL: \"Uponnut kaljuuna\"\n  MAP_MSUNK: \"Uponnut linjalaiva\"\n  MAP_VOLC: \"Vulkaaninen\"\n  MAP_CORAL: \"Koralli\"\n  MAP_PORT: \"Satama\"\n  MAP_ISLAND: \"Saari\"\n  MAP_CARGO: \"Rahtilaiva\"\n  MAP_LINERT: \"Risteilijäalus 1\"\n  MAP_LINERB: \"Risteilijäalus 2\"\n  MAP_ALART: \"Artefakti 1\"\n  MAP_GRUNGE: \"Artefakti 2\"\n  MAP_ENTRY: \"Yhdyskunta osa 1\"\n  MAP_A_BASE: \"Yhdyskunta osa 2\"\n  MAP_ALSHIP: \"T'leth 1\"\n  MAP_LEVEL: \"T'leth 2\"\n  MAP_CRYPT: \"T'leth 3\"\n  MAP_XBASES: \"X-Com-tukikohta\"\n  STR_MIXED_CREW: \"Sekaryhmä 1\"\n  STR_MIXED_CREW_2: \"Sekaryhmä 2\"\n  STR_RATING: \"ARVIO> {0}\"\n  STR_RATING_TERRIBLE: \"KAMALA!\"\n  STR_RATING_POOR: \"HUONO!\"\n  STR_RATING_OK: \"OK\"\n  STR_RATING_GOOD: \"HYVÄ!\"\n  STR_RATING_EXCELLENT: \"ERINOMAINEN!\"\n  STR_SCORE: \"PISTEET\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"X-COMIN KUUKAUSIRAPORTTI\"\n  STR_MONTH: \"Kuukausi> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"Rahoittavien organisaatioiden komitea on toistaiseksi tyytyväinen toimintaansi.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"Rahoittavien organisaatioiden komitea on erittäin tyytyväinen loistavaan edistymiseesi. Pidä yllä hyvää työn tasoa!\"\n  STR_COUNCIL_IS_DISSATISFIED: \"Rahoittavien organisaatioiden komitea on tyytymätön suoritukseesi. Sinun täytyy parantaa tulostasi muukalaisuhan torjumisessa tai X-Comin rahoitusta uhkaa lakkautus.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"Olet epäonnistunut käsittelemään muukalaisten invaasiota, ja rahoittavien organisaatioiden komitea on valitettavasti päättänyt lopettaa X-Comin rahoittamisen. Jokainen organisaatio käsittelee ongelmaa parhaaksi katsomallaan tavalla. Voimme vain toivoa, että voimme päästä jonkinlaiseen yhteisymmärykseen näiden muinaisten olentojen kanssa, ja että väestö hyväksyy vedenalaisten muukalaisten vierailun.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} on erittäin kiitollinen kykyysi torjua paikallista muukalaisten uhkaa ja päättänyt nostaa rahoitustaan.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} ovat erityisen tyytyväisiä kykyysi torjua paikallista muukalaisten tunkeutumista alueillensa ja ovat päättäneet nostaa rahoitustaan.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} ja {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} on tyytymätön kykyysi torjua muukalaisten toimintaa merissään ja on päättänyt vähentää rahoitustaan.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} ovat tyytymättömiä kykyysi torjua muukalaisten toimintaa merissään ja ovat päättäneet vähentää rahoitustaan.\"\n  STR_KNOTS: \"{0} solmua\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} on tehnyt yhteistyösopimuksen muukalaisjoukkojen kanssa ja lopettanut X-Comin rahoittamisen.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} ovat tehneet yhteistyösopimuksen muukalaisjoukkojen kanssa ja lopettaneet X-Comin rahoittamisen.\"\n  STR_MONTHLY_RATING: \"Kuukausiarvio> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Rahoituksen muutos> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"Rahoitusorganisaatio ei ole tyytyväinen taloustilanteeseesi. Sinun täytyy vähentää velkojasi alle $1 miljoonaan tai X-Com lakkautetaan.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"Alkeishiukkasviestit selvitetty\"\n  STR_CRAFT_TYPE: \"ALUSTYYPPI\"\n  STR_RACE: \"LAJI\"\n  STR_MISSION: \"TEHTÄVÄ\"\n  STR_ZONE: \"ALUE\"\n  STR_ALLOCATE_RESEARCH: \"Kohdenna tutkimusta\"\n  STR_ALLOCATE_MANUFACTURE: \"Kohdenna tuotantoa\"\n  STR_AZORES: \"Azorit\"\n  STR_REYKJAVIK: \"Reykjavík\"\n  STR_BERMUDA: \"Bermuda\"\n  STR_NEW_YORK: \"New York\"\n  STR_BOSTON: \"Boston\"\n  STR_FORT_SEVERN: \"Fort Severn\"\n  STR_DAKAR: \"Dakar\"\n  STR_RECIFE: \"Recife\"\n  STR_ACCRA: \"Accra\"\n  STR_ASCENSION_ISLAND: \"Ascension\"\n  STR_TRINIDADE_ISLAND: \"Trinidad\"\n  STR_FALKLAND_ISLAND: \"Falklandinsaaret\"\n  STR_CANARY_ISLANDS: \"Kanariansaaret\"\n  STR_ANCHORAGE: \"Anchorage\"\n  STR_ST_LAWRENCE_ISLAND: \"St. Lawrence -saari\"\n  STR_SAN_FRANCISCO: \"San Francisco\"\n  STR_MIDWAY_ISLAND: \"Midwaysaaret\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_TASMANIA: \"Tasmania\"\n  STR_HAWAII: \"Havaiji\"\n  STR_FIJI: \"Fidži\"\n  STR_TONGA: \"Tonga\"\n  STR_EASTER_ISLAND: \"Pääsiäissaaret\"\n  STR_GALAPAGOS_ISLAND: \"Galápagossaaret\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_SOLOMON_ISLAND: \"Solomonsaaret\"\n  STR_CRETE: \"Kreeta\"\n  STR_LISBON: \"Lissabon\"\n  STR_PORT_SAID: \"Port Said\"\n  STR_MARSEILLES: \"Marseille\"\n  STR_TRIPOLI: \"Tripoli\"\n  STR_MANILA: \"Manila\"\n  STR_HONG_KONG: \"Hong Kong\"\n  STR_SINGAPORE: \"Singapore\"\n  STR_BANGKOK: \"Bangkok\"\n  STR_DARWIN: \"Darwin\"\n  STR_BOMBAY: \"Bombay\"\n  STR_SAYCHELLES_ISLAND: \"Seychellit\"\n  STR_MALDIVE_ISLAND: \"Malediivit\"\n  STR_SRI_LANKA: \"Sri Lanka\"\n  STR_MAURITIUS: \"Mauritius\"\n  STR_TOKYO: \"Tokio\"\n  STR_SHANGHAI: \"Shanghai\"\n  STR_VLADIVOSTOK: \"Vladivostok\"\n  STR_LONDON: \"Lontoo\"\n  STR_FAEROE_ISLAND: \"Färsaaret\"\n  STR_ABERDEEN: \"Aberdeen\"\n  STR_OSLO: \"Oslo\"\n  STR_JAMAICA: \"Jamaika\"\n  STR_PANAMA: \"Panama\"\n  STR_MIAMI: \"Miami\"\n  STR_PSI_TRAINING: \"MH-koulutus\"\n  STR_PSIONIC_TRAINING: \"MOLEKULAARISEN HALLINAN KOULUTUS\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Vapaa MH-laitostila> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"MH-{NEWLINE}voima\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"MH-taito{NEWLINE}/Kehitys\"\n  STR_IN_TRAINING: \"Koulutuk-{NEWLINE}sessa?\"\n  STR_TARGETTED_BY: \"KOHTEENA ALUKSELLA:\"\n  STR_WEAPONS_CREW_HWPS: \"ASEET/{NEWLINE}MIEH./MTKt\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"-aluksella on polttoaine vähissä,{NEWLINE}joten se palaa tukikohtaan\"\n  STR_SOLDIER_LIST: \"Akvanauttilista\"\n  STR_RANK_: \"SOTILASARVO> {ALT}{0}\"\n  STR_MISSIONS: \"TEHTÄVÄT> {ALT}{0}\"\n  STR_KILLS: \"TAPOT> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"TOIPILASAIKA> {ALT}{0}\"\n  STR_TIME_UNITS: \"AIKAYKSIKÖT\"\n  STR_STAMINA: \"KESTÄVYYS\"\n  STR_HEALTH: \"TERVEYS\"\n  STR_BRAVERY: \"ROHKEUS\"\n  STR_REACTIONS: \"REAKTIOKYKY\"\n  STR_FIRING_ACCURACY: \"AMPUMATARKKUUS\"\n  STR_THROWING_ACCURACY: \"HEITTOTARKKUUS\"\n  STR_STRENGTH: \"VOIMA\"\n  STR_PSIONIC_STRENGTH: \"MH-VOIMA\"\n  STR_PSIONIC_SKILL: \"MH-TAITO\"\n  STR_NEW_RANK: \"UUSI SOTILASARVO\"\n  STR_PROMOTIONS: \"Ylennykset\"\n  STR_SOLDIERS_UC: \"JOUKOT\"\n  STR_COELACANTH_GAS_CANNON_UFOPEDIA: \"Miehittämättömillä taistelukoneilla on korkea ohjattavuus ja rakenteellinen kestävyys. Ne tarjoavat joukoille raskasta tulitukea kaikissa syvyyksissä. MTK:t aseistetaan uudelleen automaattisesti, jos sinulla on riittävästi ammuksia.\"\n  STR_COELACANTH_AQUA_JET_UFOPEDIA: \"Tämä taistelukone on aseistettu akvasuihkutorpedoilla. Asejärjestelmä toimii ainoastaan veden alla. Varmista, että varastoissa on riittävästi akvasuihkutorpedoja.\"\n  STR_COELACANTH_GAUSS_UFOPEDIA: \"Gauss-teknologia tarjoaa MTK:ille tehokkaan asejärjestelmän, joka aiempiin malleihin verrattuna tarjoaa raskasta tulivoimaa ja käyttää X-Comin omistamaa teknologiaa.\"\n  STR_DISPLACER_SONIC_UFOPEDIA: \"Muukalaisteknologia on määrittänyt uudelleen MTK:n. Kyky hyödyntää ionisyrjäyttimiä tarkoittaa, etteivät MTK:t ole enää rajoitettu maalle/merenpohjalle. Ääniaseistus antaa todellisen etulyöntiaseman taistelussa.\"\n  STR_DISPLACER_PWT_UFOPEDIA: \"Tämä MTK hyödyntää kanttiaaltoaseita vedenalaiseen käyttöön. Sinun on valmistettava KA-torpedoja pitääksesi ne täysin aseistetuina. Ampuaksesi valitse etappipisteitä ja sitten napsauta laukaisukuvaketta.\"\n  STR_ALIEN_PROBE_MISSION: \"Muukalaisten luotaus\"\n  STR_ALIEN_INTERDICTION: \"Muukalaisten tiedustelu\"\n  STR_ALIEN_RESOURCE_RAID: \"Muukalaisten resurssiryöstö\"\n  STR_ALIEN_INFILTRATION: \"Muukalaissoluttautuminen\"\n  STR_ALIEN_BASE: \"Yhdyskunnan perustus\"\n  STR_ALIEN_SURFACE_ATTACK: \"Muukalaisten maaiskut\"\n  STR_ALIEN_RETALIATION: \"Muukalaisten hyökkäys\"\n  STR_ALIEN_SUPPLY: \"Yhdyskunnan huolto\"\n  STR_ALIEN_PROBE_MISSION_UFOPEDIA: \"Muukalaisten luotaustehtävän tarkoituksena on yhdistää tietoa alueen merenpohjasta, luonnonvaroista sekä meri- ja ilmareiteistä. Näihin tehtäviin osallistuvat muukalaissukellusveneet eivät itsessään ole suuri uhka, mutta ne ovat merkkinä toimintapaikoista, jotka saattavat leimahtaa minä hetkenä hyvänsä.\"\n  STR_ALIEN_INTERDICTION_UFOPEDIA: \"Muukalaisilla on käytäntönä valvoa heitä kiinnostavia alueita lähettämällä aluksia, joiden nimenomaisena tarkoituksena on turvata alue ennen intensiivisempien tehtävien aloittamista. Ne laskeutuvat tietyille alueille, joihin on myöhemmin tarkoitus hyökätä, varmistamaan ne ja tekemään tien selväksi seuraavan tason toimintaa varten.\"\n  STR_ALIEN_RESOURCE_RAID_UFOPEDIA: \"Laivojen upottaminen ja lentokoneiden alasampuminen ovat muukalaisstrategian avainasemassa. Materiaalihankinta on yksi muukalaisten päätoiminnoista ja sellaisenaan liittolainen näiden avoimesti vihamielisten toimien kanssa. Muukalaiset iskevät myös geotermisesti aktiivisiin alueisiin, louhoksiin ja antiikkikohteilsiin hankkiakseen mineraaleja, jalostuneita metalleja sekä muita ihmisten tuottamia esineitä.\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"Tämän toiminnan lopputuloksena voi olla korkeimman tason virallinen yhteydenotto muukalaisten ja yritysten tai hallitusten välillä. Tämän toiminnan huipentumalle on ominaista voimakas muukalaissukellusveneliikehdintä asianosaisen organisaation vesillä. Muukalaiset yrittävät solmia sopimuksen hallituksen tai organisaation kanssa tarjoamalla heidän ylivertaisia teknologioitaan. Tämäntyyppinen muukalaistoiminta on valtava uhka X-Comille. Jos jokin yritys tai hallitus ryhtyy yhteistyöhön maahantunkeutujien kanssa, sen rahoitus lakkaa.\"\n  STR_ALIEN_BASE_UFOPEDIA: \"Muukalaiset rakentavat salaisia merenalaisia yhdyskuntia syrjäisiin paikkoihin. Aluksi muukalaiset yleensä suorittavat tiedusteluja mielestään sopivalla alueella, minkä jälkeen tukikohdan rakentamisen yhteydessä havaitaan intensiivistä muukalaissukellusveneiden aktiivisuutta alueella. Näissä tukikohdissa on laboratorioita, kloonauskeskuksia sekä kirurgisia laitoksia ihmis- ja muukalaiskokeita varten. Tukikohtien läsnäolo lisää muukalaisaktiivisuutta alueella ilman muukalaissukellusveneiden läsnäoloa. Jotta voimme löytää muukalaisten yhdyskunnan, tulee meidän lähettää alus partioimaan epäillylle alueelle. Aluetta on partioitava muutaman tunnin ajan, jotta aluksella olisi minkäänlaista käytännön mahdollisuutta havaita mahdollista yhdyskuntaa.\"\n  STR_ALIEN_SURFACE_ATTACK_UFOPEDIA: \"Muukalaisten tarvitessa ihmisiä he terrorisoivat satamaa, hyökkäävät saarelle tai iskevät laivaan. Siviilejä uhataan suoraan muukalaisten kieroutuneiden jalostustarpeiden ja hirvittävien kokeiden tyydyttämiseksi.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"Jos X-Com-hävittäjät onnistuvat erityisen hyvin upottamaan muukalaisaluksia, saattavat muukalaiset ryhtyä aggressiivisiin vastatoimiin. Tämä saattaa johtaa suoraan hyökkäykseen X-Com-tukikohtaan. Muukalaisten pitää kuitenkin ensin löytää tukikohta hyökätäkseen siihen, ja jos muukalaissukellusveneet onnistutaan pitämään loitolla, pitäisi suoran hyökkäyksen riskin olla pieni.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"Kun muukalaiset ovat rakentaneet yhdyskunnan, sitä täytyy ylläpitää säännöllisesti erityisillä huoltoaluksilla. Jos tällainen huoltoalus havaitaan laskeutuneena, on varmaa, että lähistöllä on muukalaisyhdyskunta.\"\n  STR_SURVEY_SHIP_UFOPEDIA: \"Tätä pikkuriikkistä sukellusvenettä käytetään yleensä tiedusteluun ja kartoitustehtäviin. Yleensä se edeltää suurempia muukalaisten aluksia muukalaisten tehtävien alussa.\"\n  STR_ESCORT_UFOPEDIA: \"Keskikokoinen saattuealus, joka yksinään on pieni uhka. Tämä alus edeltää suurempia aluksia ja lisääntynyttä toimintaa.\"\n  STR_CRUISER_UFOPEDIA: \"Risteilijä on yleiskäyttöinen alus. Muukalaislaivaston kantavana voimana sitä käytetään kaikentyyppisiin tehtäviin, ja se on vaarallinen vastus.\"\n  STR_HEAVY_CRUISER_UFOPEDIA: \"Raskas risteilijä on risteilijää voimakkaampi alus suurempine aseineen ja työntövoimajärjestelmineen, jotka lisäävät sen voimaa. Alusta käytetään raaka-ainetehtäviin keräämään suuria määriä mineraaleja ja varusteita.\"\n  STR_HUNTER_UFOPEDIA: \"Tämä alus on varustettu tutkimushuoneella, jossa tehdään kokeita ja leikkauksia ihmisillä. Uhrit altistetaan mitä inhottavimpiin kidutuksiin, ja aivot usein poistetaan ja varastoidaan jalostusta varten matkan aikana.\"\n  STR_BATTLESHIP_UFOPEDIA: \"Taistelualus on aggressivisin alus, joka muukalaisilla on. Siinä on kaikki tarvittavat muukalaisteknologiat ja -järjestelmät aluksen toimiakseen tukikohtana mille tahansa muukalaisten vihamiehiselle toimelle, jonka muukalaiset saattavat haluta suorittaa. Sillä on laaja asevalikoima.\"\n  STR_DREADNOUGHT_UFOPEDIA: \"Dreadnought on supermiehistönkuljetusalus, joka on täysin varustettu kaikilla muukalaisteknologioilla ja valtavalla hyötykuormalla. Se on vahva ja pelottava vastus.\"\n  STR_FLEET_SUPPLY_CRUISER_UFOPEDIA: \"Huoltoalusta käytetään rakennettaessa uusia yhdyskuntia sekä ylläpidettäessä vanhoja. Se kantaa muukalaisten ravintoaineita, DNA:ta, sikiöitä sekä muita biologisia osia.\"\n  STR_DISMANTLE: \"Pura\"\n  STR_FACILITY_IN_USE: \"LAITOS KÄYTÖSSÄ\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"LAITOSTA EI VOI PURKAA!{SMALLLINE}Jokaisesta tukikohdan laitoksesta täytyy olla yhteys ilmalukkoon.\"\n  STR_TRANSFER_ITEMS_TO: \"Siirrä tavarat tukikohtaan {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"MUUKALAISTEN VANKILAITOSTA EI OLE KOHTEESSA{SMALLLINE}Elävät muukalaiset tarvitsevat erityisen vankilaitoksen, johon voidaan luoda niiden tarvitsemat elinolosuhteet.\"\n  STR_AMOUNT_AT_DESTINATION: \"MÄÄRÄ{NEWLINE}KOHTEESSA\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"Muukalainen kuolee, koska muukalaisten vankilaitosta ei ole\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"EI RIITTÄVIÄ ASUINTILOJA!{SMALLLINE}Kohdetukikohdassa ei ole riittävästi asuintiloja aluksen miehistöä varten.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"EI TARPEEKSI VARASTOTILAA!{SMALLLINE}Määränpäässä ei ole tarpeeksi varastotilaa alukselle määrätylle varustukselle.\"\n  STR_ITEMS_ARRIVING: \"Kuljetus saapui\"\n  STR_DESTINATION_UC: \"MÄÄRÄNPÄÄ\"\n  STR_DART_PISTOL: \"Nuolipyssy\"\n  STR_DART_POD: \"Nuolilipas\"\n  STR_JET_HARPOON: \"Suihkuharppuunapyssy\"\n  STR_HARPOON_POD: \"Harppuunalipas\"\n  STR_GAS_CANNON: \"Kaasukanuuna\"\n  STR_GC_AP_AMMO: \"KK-AP-nuolet\"\n  STR_GC_HE_AMMO: \"KK-HE-nuolet\"\n  STR_GC_P_AMMO: \"KK-P-nuolet\"\n  STR_HYDRO_JET_CANNON: \"Hydrosuihkukanuuna\"\n  STR_HJC_AP_AMMO: \"HS-AP-ammukset\"\n  STR_HJC_HE_AMMO: \"HS-HE-ammukset\"\n  STR_HJC_P_AMMO: \"HS-P-ammukset\"\n  STR_TORPEDO_LAUNCHER: \"Torpedolaukaisin\"\n  STR_SMALL_TORPEDO: \"Pieni torpedo\"\n  STR_LARGE_TORPEDO: \"Suuri torpedo\"\n  STR_PHOSPHOROUS_TORPEDO: \"Fosforitorpedo\"\n  STR_MAGNA_BLAST_GRENADE: \"Magna-räjähdekranaatti\"\n  STR_DYE_GRENADE: \"Väriainekranaatti\"\n  STR_PARTICLE_DISTURBANCE_GRENADE: \"Hiukkashäiriökranaatti\"\n  STR_MAGNA_PACK_EXPLOSIVE: \"Magna-latausräjähde\"\n  STR_PARTICLE_DISTURBANCE_SENSOR: \"Hiukkashäiriöilmaisin\"\n  STR_MEDI_KIT: \"Ensiapulaite\"\n  STR_MC_DISRUPTOR: \"MH-häirintälaite\"\n  STR_THERMAL_TAZER: \"Lämpötainnutin\"\n  STR_GAUSS_PISTOL: \"Gauss-pistooli\"\n  STR_GAUSS_PISTOL_CLIP: \"Gauss-pistoolin lipas\"\n  STR_GAUSS_RIFLE: \"Gauss-kivääri\"\n  STR_GAUSS_RIFLE_CLIP: \"Gauss-kiväärin lipas\"\n  STR_HEAVY_GAUSS: \"Gauss-käsitykki\"\n  STR_HEAVY_GAUSS_CLIP: \"Gauss-käsitykin lipas\"\n  STR_SONIC_CANNON: \"Äänikanuuna\"\n  STR_CANNON_POWER_CLIP: \"Kanuunan voimanlähdelipas\"\n  STR_SONIC_BLASTA_RIFLE: \"Ääni-Blastakivääri\"\n  STR_BLASTA_POWER_CLIP: \"Blastan voimanlähdelipas\"\n  STR_SONIC_PISTOL: \"Äänipistooli\"\n  STR_PISTOL_POWER_CLIP: \"Pistoolin voimanlähdelipas\"\n  STR_DISRUPTOR_PULSE_LAUNCHER: \"Hajotuspulssilaukaisin\"\n  STR_DISRUPTOR_AMMO: \"Hajotusammus\"\n  STR_THERMAL_SHOK_LAUNCHER: \"Lämpösokkilaukaisin\"\n  STR_THERMAL_SHOK_BOMB: \"Lämpösokkipommi\"\n  STR_SONIC_PULSER: \"Äänisykähdin\"\n  STR_ZRBITE: \"Zrbiitti\"\n  STR_MC_READER: \"MH-lukijalaite\"\n  STR_VIBRO_BLADE: \"Vibroterä\"\n  STR_THERMIC_LANCE: \"Terminen peitsi\"\n  STR_HEAVY_THERMIC_LANCE: \"Raskas terminen peitsi\"\n  STR_AQUATOID_CORPSE: \"Akvatoidin ruumis\"\n  STR_GILLMAN_CORPSE: \"Kidusihmisen ruumis\"\n  STR_LOBSTERMAN_CORPSE: \"Hummerimiehen ruumis\"\n  STR_TASOTH_CORPSE: \"Tasootin ruumis\"\n  STR_CALCINITE_CORPSE: \"Kalsiniitin ruumis\"\n  STR_DEEP_ONE_CORPSE: \"Syväläisen ruumis\"\n  STR_BIODRONE_CORPSE: \"Biodroidin jäännökset\"\n  STR_TENTACULAT_CORPSE: \"Lonkeromanaajan ruumis\"\n  STR_TRISCENE_CORPSE: \"Triasliskon ruumis\"\n  STR_HALLUCINOID_CORPSE: \"Hallusinoidin ruumis\"\n  STR_XARQUID_CORPSE: \"Kalmanhelmen ruumis\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"Ei riittävästi ammuksia MTK:n lataamiseksi{SMALLLINE}Kukin MTK vaatii {0} kpl ammustyyppiä {1}.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Varusteita ei ole tarpeeksi täydentämiseen\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Sinun täytyy tutkia ensin:{NEWLINE}{0}{NEWLINE}ennen kuin voit rakentaa{NEWLINE}{1}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"Muukalaiset ovat tuhonneet puolustamattoman tukikohdan: {0}\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"X-Com-partiot ovat paikallistaneet muukalaisyhdyskunnan alueella: {0}\"\n  STR_STANDOFF: \"SEURAA\"\n  STR_CAUTIOUS_ATTACK: \"VAROVAINEN HYÖKKÄYS\"\n  STR_STANDARD_ATTACK: \"TAVALLINEN HYÖKKÄYS\"\n  STR_AGGRESSIVE_ATTACK: \"AGGRESSIIVINEN HYÖKKÄYS\"\n  STR_DISENGAGING: \"PERÄÄNNYTÄÄN\"\n  STR_UFO_HIT: \"MUUKALAISALUKSEEN OSUI!\"\n  STR_UFO_CRASH_LANDS: \"MUUKALAISALUS AMMUTTU ALAS!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Pienennys vain seuratessa\"\n  STR_UFO_RETURN_FIRE: \"MUUKALAISALUS VASTAA TULEEN!\"\n  STR_INTERCEPTOR_DAMAGED: \">>> LENTOSUKELLUSVENE VAURIOITUI <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> LENTOSUKELLUSVENE TUHOUTUI <<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"MUUKALAISALUS KARKAAMASSA!\"\n  STR_LONG_RANGE_DETECTION: \"Laajakaistaluotaimet\"\n  STR_STORES_UC: \"VARASTOT\"\n  STR_DIFFICULTY_LEVEL: \"Vaikeusaste\"\n  STR_INTERCEPT: \"ALUKSET\"\n  STR_BASES: \"TUKIKOHDAT\"\n  STR_GRAPHS: \"KUVAAJAT\"\n  STR_UFOPAEDIA_UC: \"UFOPEDIA\"\n  STR_OPTIONS_UC: \"ASETUKSET\"\n  STR_FUNDING_UC: \"RAHOITUS\"\n  STR_5_SECONDS: \"5 s\"\n  STR_1_MINUTE: \"1 min\"\n  STR_5_MINUTES: \"5 min\"\n  STR_30_MINUTES: \"30 min\"\n  STR_1_HOUR: \"1 tunti\"\n  STR_1_DAY: \"1 päivä\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"X-Comin suoritustaulukko\"\n  STR_ENTER_NAME: \"Nimi\"\n  STR_PERFORMANCE_RATING: \"Suorituksen arvosana\"\n  STR_VICTORY_DATE: \"Voiton päivänmäärä\"\n  STR_CHEMICAL_FLARE: \"Kemiallinen valonlähde\"\n  STR_CHEMICAL_FLARE_UFOPEDIA: \"Tämä pienikokoinen laite tuottaa kirkasta valoa missä tahansa syvyydessä tai kuivalla maalla. Se on erittäin hyödyllinen vihollisten paljastamiseksi pimeissä olosuhteissa.\"\n  STR_MONTHLY_COSTS: \"Menot/kk\"\n  STR_CRAFT_RENTAL: \"Lentosukellusveneiden vuokra\"\n  STR_SALARIES: \"Palkat\"\n  STR_BASE_MAINTENANCE: \"Tukikohdan ylläpito\"\n  STR_COST_PER_UNIT: \"Hinta / yks.\"\n  STR_QUANTITY: \"Määrä\"\n  STR_TOTAL: \"Yhteensä\"\n  STR_IN_PSIONIC_TRAINING: \"MH-istutuksessa\"\n  STR_FRONT_ARMOR: \"Etupanssari\"\n  STR_LEFT_ARMOR: \"Vasen panssari\"\n  STR_RIGHT_ARMOR: \"Oikea panssari\"\n  STR_REAR_ARMOR: \"Takapanssari\"\n  STR_UNDER_ARMOR: \"Alapanssari\"\n  STR_ROUNDS: \"LAUKAUKSET\"\n  STR_UNIT: \"YKSIKKÖ> {0}\"\n  STR_ENERGY: \"ENERGIA\"\n  STR_MORALE: \"TAISTELUTAHTO\"\n  STR_ARMOR_: \"PANSSARI> {0}\"\n  STR_FRONT_ARMOR_UC: \"ETUPANSSARI\"\n  STR_LEFT_ARMOR_UC: \"VASEN PANSSARI\"\n  STR_RIGHT_ARMOR_UC: \"OIKEA PANSSARI\"\n  STR_REAR_ARMOR_UC: \"TAKAPANSSARI\"\n  STR_SKILLS: \"TAIDOT> {0}\"\n  STR_LEVEL: \"TASO> {0}\"\n  STR_HEAD: \"PÄÄ\"\n  STR_TORSO: \"VARTALO\"\n  STR_RIGHT_ARM: \"O KÄSI\"\n  STR_LEFT_ARM: \"V KÄSI\"\n  STR_RIGHT_LEG: \"O JALKA\"\n  STR_LEFT_LEG: \"V JALKA\"\n  STR_PAIN_KILLER: \"KIPULÄÄKE\"\n  STR_STIMULANT: \"PIRISTE\"\n  STR_HEAL: \"PARANNA\"\n  STR_TIME_UNITS_SHORT: \"AY>{ALT}{0}\"\n  STR_WEIGHT: \"Paino>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"Reakt>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"M.Taito>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"M.Voima>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Muukalaisten laite\"\n  STR_AMMO_ROUNDS_LEFT: \"AMMUS:{NEWLINE}{NEWLINE}JÄLJELLÄ={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Kipulääke>{ALT}{0}{ALT}{NEWLINE}Piriste>{ALT}{1}{ALT}{NEWLINE}Paranna>{ALT}{2}\"\n  STR_THROW: \"Heitä\"\n  STR_AUTO_SHOT: \"Sarjatuli\"\n  STR_SNAP_SHOT: \"Kertatuli\"\n  STR_AIMED_SHOT: \"Tähdätty\"\n  STR_STUN: \"Tainnuta\"\n  STR_PRIME_GRENADE: \"Ajasta kranaatti\"\n  STR_USE_SCANNER: \"Käytä häiriöilmaisinta\"\n  STR_USE_MEDI_KIT: \"Käytä ensiapulaitetta\"\n  STR_LAUNCH_MISSILE: \"Laukaise torpedo\"\n  STR_ACCURACY_SHORT: \"Tark>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Ei riittävästi aikayksiköitä!\"\n  STR_NOT_ENOUGH_ENERGY: \"Ei tarpeeksi energiaa!\"\n  STR_NO_ROUNDS_LEFT: \"Ei ammuksia jäljellä!\"\n  STR_NO_AMMUNITION_LOADED: \"Ase ei ole ladattu!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Väärä ammus tätä asetta varten!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"Ase on jo ladattu!\"\n  STR_NO_LINE_OF_FIRE: \"Ei tulilinjaa!\"\n  STR_GRENADE_IS_ACTIVATED: \"Kranaatti on aktivoitu!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Kranaatti on deaktivoitu!\"\n  STR_THERE_IS_NO_ONE_THERE: \"Siinä kohtaa ei ole ketään!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Muukalaisten laitteita ei voi käyttää ennen tutkimusprojektin valmistumista!\"\n  STR_OUT_OF_RANGE: \"Kantaman ulkopuolella!\"\n  STR_UNABLE_TO_THROW_HERE: \"Tähän ei voi heittää!\"\n  STR_SET_TIMER: \"Aseta ajastin\"\n  STR_HIDDEN_MOVEMENT: \"VIHOLLISEN VUORO\"\n  STR_TURN: \"VUORO> {0}\"\n  STR_SIDE: \"PUOLI> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Paina näppäintä jatkaaksesi\"\n  STR_MIND_CONTROL: \"Molekulaarinen hallinta\"\n  STR_PANIC_UNIT: \"Häiritse implanttia\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Kohteen taistelutahtoa vähennetty\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Implantin kaappaus onnistui\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}on mennyt sekaisin\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}on mennyt sekaisin\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}on joutunut paniikkiin\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}on joutunut paniikkiin\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Muukalaiset\"\n  STR_RIGHT_HAND: \"OIKEA KÄSI\"\n  STR_LEFT_HAND: \"VASEN KÄSI\"\n  STR_RIGHT_SHOULDER: \"OIKEA OLKAPÄÄ\"\n  STR_LEFT_SHOULDER: \"VASEN OLKAPÄÄ\"\n  STR_BACK_PACK: \"REPPU\"\n  STR_BELT: \"VYÖ\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}on molekulaarisessa hallinnassa\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}on molekulaarisessa hallinnassa\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}on menettänyt tajuntansa\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}on menettänyt tajuntansa\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}kuoli vakavan haavan vuoksi\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}kuoli vakavan haavan vuoksi\"\n  STR_USE_MIND_PROBE: \"Käytä lukijaa\"\n  STR_FATAL_WOUNDS: \"VAKAVAT HAAVAT\"\n  STR_UNDER_ARMOR_UC: \"ALAPANSSARI\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Aikayksiköitä varattu kertatulta varten\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Aikayksiköitä varattu sarjatulta varten\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Aikayksiköitä varattu tähdättyä laukausta varten\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Aikayksiköitä varattu polvistumista varten\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"AY:t varattu polvistumista ja ampumista varten\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} yksikkö X-Com-aluksessa\"\n    other: \"{N} yksikköä X-Com-aluksessa\"\n  STR_UNITS_OUTSIDE:\n    one: \"{N} yksikkö jätetty ulkopuolelle\"\n    other: \"{N} yksikköä jätetty ulkopuolelle\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} yksikkö sisäänkäynnillä\"\n    other: \"{N} yksikköä sisäänkäynnillä\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} yksikkö kohdepoistumisalueella\"\n    other: \"{N} yksikköä kohdepoistumisalueella\"\n  STR_ABORT_MISSION_QUESTION: \"Keskeytetäänkö tehtävä?\"\n  STR_CORPSE: \"Ruumis\"\n  STR_UNLOAD_CRAFT: \"Pura varustelasti\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}on kuollut\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}on kuollut\"\n  STR_HIT_MELEE: \"Osuma\"\n  STR_GROUND: \"MAA\"\n  STR_LIVING_QUARTERS_PLURAL: \"Asuintilat\"\n  STR_LIST_ITEM: \"TAVARA\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"Kaikki muukalaiset kuolivat pakkolaskussa,{NEWLINE}Pakkolaskun saalista kerätään\"\n  STR_RESET: \"Nollaa\"\n  STR_MEMORIAL: \"Muistomerkki\"\n  STR_DATE_UC: \"PVM\"\n  STR_SOLDIERS_RECRUITED_UC: \"AKVANAUTTEJA VÄRVÄTTY>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"AKVANAUTTEJA MENETETTY>{ALT}{0}\"\n  STR_REMOVE_SELECTED: \"Poista valitut\"\n  STR_LIVE_ALIENS: \"Eläviä{NEWLINE}yksilöjä\"\n  STR_DEAD_ALIENS: \"Hylättäviä{NEWLINE}yksilöjä\"\n  STR_UNDER_INTERROGATION: \"Tutkit-{NEWLINE}tavana\"\n  STR_CONTAINMENT_EXCEEDED: \"MUUKALAISTEN VANKILAPAIKAT TÄYNNÄ{SMALLLINE}Ei riittävästi vankilatilaa tukikohdassa {0}. Sinun täytyy poistaa turhia muukalaisia vankilasta (toisin sanoen tappaa ne).\"\n  STR_MANAGE_CONTAINMENT: \"Hallitse muukalaisten vankilaitosta\"\n  STR_STORAGE_EXCEEDED: \"VARASTOTILA YLITETTY!{SMALLLINE}Riittämättömästi varastotilaa tukikohdassa {0}. Liika tavara on myytävä pois.\"\n  STR_GO_TO_BASE: \"Mene tukikohtaan\"\n  STR_MELEE_ACCURACY: \"LÄHITAISTELUTARKKUUS\"\n  STR_SELL_PRODUCTION: \"MYY\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Molempien käsien täytyy olla vapaina!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Ei tarpeeksi varusteita mallin kopioimiseksi!\"\n  STR_UNLOAD_WEAPON: \"Poista ammukset\"\n  STR_ALL_ITEMS: \"Kaikki esineet\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"EI ENEMPÄÄ VARUSTEITA SALLITTU ALUKSEEN!{SMALLLINE}Alukseen sallitaan korkeintaan {N} varuste.\"\n    other: \"EI ENEMPÄÄ VARUSTEITA SALLITTU ALUKSEEN!{SMALLLINE}Alukseen sallitaan korkeintaan {N} varustetta.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}KOMENTOKESKUS TUHOTTU{NEWLINE}Palaa sisäänkäynnille ja keskeytä tehtävä.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"X-Com-laitoksia ei voi rakentaa maalle\"\n  STR_UNABLE_TO_ENGAGE_DEPTH: \"EI VOI HYÖKÄTÄ TÄSSÄ SYVYYDESSÄ\"\n  STR_UNABLE_TO_ENGAGE_AIRBORNE: \"EI VOI HYÖKÄTÄ ILMASSA\"\n  STR_UNDERWATER_EQUIPMENT: \"Tämä varustus ei toimi vedenpinnan yläpuolella!\"\n  STR_LAND_EQUIPMENT: \"Tämä varustus ei toimi vedenpinnan alapuolella!\"\n  STR_LEVEL_SHORT: \"L{0}\"\n  STR_PERSONNEL: \"Henkilökunta\"\n  STR_CRAFT_ARMAMENT: \"Alukset & aseistus\"\n  STR_COMPONENTS: \"Komponentit\"\n  STR_SOLDIERS_RECRUITED: \"Akvanautteja värvätty\"\n  STR_SOLDIERS_LOST: \"Akvanautteja menetetty\"\n  STR_TOTAL_UFOS: \"Lentosukellusveneitä havaittu\"\n  STR_TOTAL_ALIEN_BASES: \"Muukalaisyhdyskuntia löydetty\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"MHV\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"MHT\"\n  FEMALE_CIVILIAN: \"Siviili, nainen\"\n  MALE_CIVILIAN: \"Siviili, mies\"\n  DOCKER_CIVILIAN: \"Siviili, ahtaaja\"\n  SAILOR_CIVILIAN: \"Siviili, merimies\"\n  STR_BIODRONE_MELEE_WEAPON: \"Biodroidin ase\"\n  HALLUCINOID_WEAPON: \"Hallusinoidin ase\"\n  STR_LOBSTERMAN_MELEE_WEAPON: \"Hummerimiehen ase\"\n  CALCINITE_WEAPON: \"Kalsiniitin ase\"\n  DEEP_ONE_WEAPON: \"Syväläisen ase\"\n  STR_TRISCENE_MELEE_WEAPON: \"Triasliskon ase\"\n  STR_TRIBIO_SONIC_WEAPON: \"Muukalaisten ääniase\"\n  XARQUID_WEAPON: \"Kalmanhelmen ase\"\n  TENTACULAT_WEAPON: \"Lonkeromanaajan ase\"\n  ZOMBIE_WEAPON: \"Zombin ase\"\n  ALIEN_PSI_WEAPON: \"Muukalaisten MH-ase\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/fr-CA.yml",
    "content": "fr-CA:\n  STR_LEVIATHAN_UFOPEDIA: \"UN SOUS-MARIN VOLANT DE TRANSPORT ET D'INTERCEPTION, POUVANT ÉVOLUER EN EXTRÊME PROFONDEUR. UNE SUPERBE SYNTHÈSE DE TECHNOLOGIE ALIEN ET HUMAINE, UTILISANT DES SYSTÈMES À PROPULSION IONIQUE ET UNE NAVIGATION À MATRICE MAGNÉTIQUE.\"\n  STR_BARRACUDA_UFOPEDIA: \"LE BARRACUDA BRITANNIQUE HYDROSPATIAL, ALIMENTÉ PAR DES MOTEURS LASER SURCHAUFFÉS. UN DES VAISSEAUX D'INTERCEPTION LES PLUS RAPIDE AU MONDE, CAPABLE DE VOLER SOUS LA MER ET EN SURFACE, UN VAISSEAU CLÉ DANS LA BATAILLE.\"\n  STR_HAMMERHEAD_UFOPEDIA: \"UN VAISSEAU DE TRANSPORT ET D'INTERCEPTION. UNE RÉPLIQUE DES SYSTÈMES DE MATRICE MAGNÉTIQUE DANS UN VAISSEAU X-COM. MALGRÉ SA PETITE TAILLE, SON DESIGN EST UNE PROUESSE TECHNIQUE À COUPER LE SOUFFLE.\"\n  STR_TRITON_UFOPEDIA: \"LE TRITON, UN TRANSPORTEUR D'ESCOUADES D'ASSAUT, ÉQUIPÉ DE MOTEURS PERMETTANT DE SE DÉPLACER SOUS LA MER COMME EN SURFACE. SA GRANDE CAPACITÉ ET SA FABRICATION ROBUSTE ASSURENT D'ÊTRE LE PILIER DE TOUTE LA FLOTTE X-COM.\"\n  STR_MANTA_UFOPEDIA: \"VAISSEAU MANTA GRANDE VITESSE, UN SOUS-MARIN VOLANT MONOPLACE D'INTERCEPTION RESSEMBLANT BEAUCOUP AUX VAISSEAUX IONIQUES ALIENS. UN VAISSEAU D'ATTAQUE TRÈS EFFICACE DANS L'ESCALADE DU CONFLIT.\"\n  STR_AJAX_UFOPEDIA: \"LA TORPILLE AJAX EST L'ARME CLASSIQUE DES COMBATS SOUS-MARINS PARTOUT DANS LE MONDE. C'EST UNE FORCE DE DISSUASION PRÉCISE ET PUISSANTE.\"\n  STR_DUP_HEAD_UFOPEDIA: \"ISSU D'UNE TECHNOLOGIE RÉCENTE, CETTE ARME À TÊTE DE PASTILLE D'URANIUM APPAUVRI EST LA PREMIÈRE ARME SOUS-MARINE COMMERCIALE À L'EXPLOITER TOTALEMENT.\"\n  STR_CRAFT_GAS_CANNON_UFOPEDIA: \"UN SYSTÈME DE CANON À GAZ COMPRIMÉ QUI TIRE DES OBUS-HARPONS SOLIDES CAPABLES DE PERCER DES ARMURES TRÈS RÉSISTANTES.\"\n  STR_PWT_CANNON_UFOPEDIA: \"LA TORPILLE À ONDES DE CHOC UTILISE UN SYSTÈME DE CARBURANT SURCHAUFFÉ ET UNE OGIVE TRÈS DENSE POUVANT PERCER LA PLUPART DES ALLIAGES.\"\n  STR_GAUSS_CANNON_UFOPEDIA: \"LE CANON GAUSS EST DE TECHNOLOGIE X-COM RÉCENTE. L'ACCÉLÉRATEUR DE PARTICULES DE CE SYSTÈME EST ACTIVÉ PAR UN RÉACTEUR À FUSION COMPACT REFROIDI À L'AZOTE LIQUIDE.\"\n  STR_SONIC_OSCILLATOR_UFOPEDIA: \"L'OSCILLATEUR AUDITIF PUISSANT CRÉE DES ONDES DE FORCE SONIQUE, DÉTRUISANT UNE CIBLE EN CRÉANT UN CHAMP VIBRATOIRE QUI DÉSTABILISE SON SYSTÈME MOLÉCULAIRE.\"\n  STR_AQUATOID_UFOPEDIA: \"La race Aquatoïde est issue d'une société ancienne, qui a existé des milliers d'années avant l'apparition de l'homme dans le monde. La forme compacte et les traits bulbeux rappellent leurs proches cousins, les Sectoïdes qui, eux, vivent dans l'espace. Leur force vient de leur puissante technologie de contrôle moléculaire. Les Aquatoïdes veulent perpétuer leur race stérile en opérant des modifications génétiques. Les humains sont leurs cobayes et ils ont ainsi généré de nombreuses races hybrides.\"\n  STR_AQUATOID_AUTOPSY: \"Autopsie d'Aquatoïde\"\n  STR_AQUATOID_AUTOPSY_UFOPEDIA: \"Après une analyse détaillée de la créature, il apparaît qu'il s'agit d'un Sectoïde, nos anciens ennemis, ayant subi des changements par intervention chirurgicale et par des implants pour devenir une créature aquatique. Les poumons atrophiés permettent la respiration de l'air et une mobilité limitée à la surface. On trouve des implants cybernétiques partout dans son corps qui améliorent la force de ses membres atrophiés et les fonctions organiques. Comme tous les membres de cette race sont identiques, on peut en conclure que ces créatures sont des clones.\"\n  STR_GILLMAN_UFOPEDIA: \"Presque humain, cette étrange créature ressemblant à un reptile humanoïde est très proche de l'homme. Elle est très puissante et rapide dans le monde sous-marin. Ces Hommes-Poissons sont une race à part entière, composée de spécimens mâles et femelles de classes d'âge différentes. Ils ne ressemblent pas aux autres créatures aquatiques car ils ne portent pas les traces de modification génétique, ni de déformations chirurgicaux. Il pourrait s'agir d'une ancienne branche de notre espèce.\"\n  STR_GILLMAN_AUTOPSY: \"Autopsie d'Homme-Poisson\"\n  STR_GILLMAN_AUTOPSY_UFOPEDIA: \"Aussitôt que les opérations chirurgicales ont commencé, il était clair qu'il ne s'agissait pas d'un alien, mais d'une race née sur Terre, une ancienne race préhistorique qu'on avait crue détruite dès la domination des mammifères. Ces Hommes-Poissons amphibiens, intelligents et forts, vivaient à l'époque des dinosaures. Le cataclysme qui acheva le règne reptilien sur Terre les força à vivre dans une relation symbiotique avec les nouveaux arrivants aliens. Un petit appareil électronique est d'ailleurs incrusté dans leur crâne.\"\n  STR_LOBSTERMAN_UFOPEDIA: \"C'est une créature stupéfiante, plus grande qu'un homme et dotée de six membres, ayant tout du démon aquatique. Du fait de sa ressemblance avec le homard terrien, les troupes X-Com l'ont surnommé l'Homme-Homard. C'est le monstre des profondeurs par excellence. Une créature d'une force incroyable et pratiquement indestructible face aux tirs de missiles. Ses pinces à elles seules peuvent broyer l'acier.\"\n  STR_LOBSTERMAN_AUTOPSY: \"Autopsie d'Homme-Homard\"\n  STR_LOBSTERMAN_AUTOPSY_UFOPEDIA: \"Une fois sa carapace quasiment indestructible passée, cette créature est d'une construction étonnante. Des muscles puissants ondulent autour d'un squelette en titane, et un système de ciblage sophistiqué aux capacités de détection multibande a été inséré directement dans le cerveau de la créature. Ses yeux multiples sont protégés par du plastique plus résistant que l'acier et il est clair que lorsque ces créatures sont déployées par leurs maîtres, elles deviennent implacables. Enfouis dans son corps se trouvent des appareils de fabrication et de fonction inconnues.\"\n  STR_TASOTH_UFOPEDIA: \"Ces ennemis agiles et rapides constituent le fer de lance de l'armée alien. Ils naissent par centaines dans des cuves de reproduction au cœur des colonies aliens. Largement plus puissant que l'homme, son comportement et sa nature carnassière font du Tasoth un alien sans pareil sur la planète. Le Tasoth est le fer de lance des attaques aliens et ne semble jamais altéré par les combats, même les plus éprouvants.\"\n  STR_TASOTH_AUTOPSY: \"Autopsie de Tasoth\"\n  STR_TASOTH_AUTOPSY_UFOPEDIA: \"La dissection révèle un organisme cybernétique possédé d'une étrange énergie. Il y a une petite unité centrale dans le corps, mais pas d'organes connus. L'énergie est transmise dans tout le corps par un système de transmission bio-électrique. Il n'est maintenu par aucune ossature. Une fois morte, le système d'alimentation ne fonctionne plus et la créature devient une poupée de chiffon de chair et de fluides aliens puants. Deux piles en céramique sont aussi présentes dans le corps et peuvent, une fois chargées, ressusciter la créature.\"\n  STR_DEEP_ONE_UFOPEDIA: \"Le Profond est un cauchemar biologique, une race hybride née des expériences tordues des Aquatoïdes. Nous avons rencontré plusieurs variétés de cette créature. Après d'intenses recherches, nous pensons qu'ils sont les produits fabriqués des envahisseurs, grossissant leurs rangs après chaque capture de nouveaux humains. Chacun de ces sous-humains est armé d'une charge d'énergie électrique assez puissante pour tuer un aquanaute.\"\n  STR_DEEP_ONE_AUTOPSY: \"Autopsie de Profond\"\n  STR_DEEP_ONE_AUTOPSY_UFOPEDIA: \"La créature a un organisme mi-humain, mi-alien. Le cerveau humain a été massivement modifié pour recevoir de l'électronique de contrôle et un cortex alien. Tout vestige du corps humain semble avoir disparu, sauf un : les yeux. La greffe chirurgicale pratiquée semble permettre au fœtus alien de consommer graduellement l'hôte humain dans lequel il grandit. Sa peau rugueuse semble être en mailles métalliques non-organiques d'une extrême résistance et souplesse. Le résultat est une race hybride forte et rapide, entièrement contrôlée par les aliens.\"\n  STR_BIODRONE_UFOPEDIA: \"Le Biodrone est une création que seul un esprit alien peut concevoir. C'est un cerveau (humain ou alien) maintenu dans un liquide amniotique et relié à une unité de base alimentée qui peut voler sur la terre ou sous l'eau. Chaque Biodrone est armé d'un puissant perturbateur auditif mi-machine, mi-organique. Certains de nos scientifiques pensent que l'arme est contrôlée par les cordes vocales des organismes récepteurs. Très tenaces et précis, ces chiens de garde sont communément utilisés par les aliens pour protéger leurs biens de valeur.\"\n  STR_BIODRONE_AUTOPSY: \"Autopsie de Biodrone\"\n  STR_BIODRONE_AUTOPSY_UFOPEDIA: \"L'hypothèse que le perturbateur auditif s'avère être un appareil biologique semble vraie. Cette pauvre créature tue littéralement ses ennemis avec ses cris. Chaque cas présente des cicatrices de traumatisme chirurgicale massives et est sévèrement mutilé. Les aliens semblent charcuter les cerveaux pour obtenir l'obéissance. La plupart des cortex utilisés sont d'origine alien, mais il n'y a rien de plus horrible que d'y trouver une unité humaine. Les Biodrones sont alimentés par un moteur ionique et incorporent une sorte de système de contrôle à distance.\"\n  STR_TENTACULAT_UFOPEDIA: \"Même les profondeurs d'un cauchemar Lovecraftien ne sont rien à côté de cette créature indescriptible. Il n'existe aucune comparaison avec les animaux terrestres, l'environnement qui pourrait produire cette monstruosité va au-delà de l'imagination. Armé de longues tentacules, le Tentaculat paralyse ses victimes puis les réduit à l'état d'insignifiance. Un simple toucher peut être mortel, même avec une armure. Le Tentaculat est l'alien le plus redoutable jamais rencontré par X-Com.\"\n  STR_TENTACULAT_AUTOPSY: \"Autopsie de Tentaculat\"\n  STR_TENTACULAT_AUTOPSY_UFOPEDIA: \"L'autopsie révèle la présence de petits implants cybernétiques dans le gros cerveau de la créature. Son système de vision est une combinaison complexe de lumière visible et d'acquisition d'imagerie thermique. Ce monstre pourrait naviguer avec une extrême précision dans les profondeurs marines les plus sombres. Il y a des organes atrophiés qui semblent assurer le minimum nécessaire pour sa survie. Chaque créature a un petit estomac relié à l'extérieur; il est logique de conclure qu'elle est alimentée par des nutriments directement de ses maîtres.\"\n  STR_CALCINITE_UFOPEDIA: \"À l'instar des scaphandriers de marins perdus, ces aliens écument le fond des mers à la recherche des imprudents. D'un méchant coup de griffes d'un alliage plus puissant que l'acier, la créature peut envoyer les meilleurs plongeurs au fond des mers. Si on s'approche de sa tête, on peut voir derrière son masque une forme verte gélatineuse. Les confrontations souvent mortelles avec la créature n'ont pas permis de révéler de nouveaux indices sur sa véritable nature.\"\n  STR_CALCINITE_AUTOPSY: \"Autopsie de Calcinite\"\n  STR_CALCINITE_AUTOPSY_UFOPEDIA: \"Une fois débarrassé de l'armure, le Calcinite se révèle être un énorme amas de protoplasme. Il n'y a pas de cerveau apparent, ni de membres ou d'organes sensoriels. Un petit composant métallique baigne au cœur de ce corps liquide. Une fois morte, il est difficile de deviner la nature de cette créature. Une énigme inexplicable de nos ennemis aliens.\"\n  STR_TRISCENE_UFOPEDIA: \"Ce reptile bipède nous ramène à l'âge des dinosaures. Il ressemble à une créature du Crétacé dans tous les sens, sauf son habileté à survivre dans l'eau et sur terre. Ces créatures disposent de poches d'armes et sont dotées d'une énorme mâchoire métallique. Lors d'attaques terrestres lancées par les aliens, ces monstres constituaient souvent leur fer de lance. Les commandants Tasoth déploient ces armes poids lourd puissantes avec une efficacité redoutable.\"\n  STR_TRISCENE_AUTOPSY: \"Autopsie de Triscène\"\n  STR_TRISCENE_AUTOPSY_UFOPEDIA: \"Après dissection, le Triscène se révèle être une créature ancienne, dotée d'implants cybernétiques et de systèmes d'armes. Son minuscule cerveau est complété par un petit module informatique fixé dans le harnais de contrôle que toutes les créatures portent. Sa peau dure, son instinct de prédateur décuplé par un arsenal d'armes en font un adversaire implacable dans tous types d'environnement.\"\n  STR_HALLUCINOID_UFOPEDIA: \"Après avoir écumé les océans, les aliens ont créé ces énormes créatures terrestres à des fins meurtrières. Ne vous trompez pas d'être en sécurité par l'apparence inoffensive de ces marins des profondeurs. Possédant une formidable frappe glaciale en combat rapproché, l'Hallucinoïde est un adversaire mortel.\"\n  STR_HALLUCINOID_AUTOPSY: \"Autopsie d'Hallucinoïde\"\n  STR_HALLUCINOID_AUTOPSY_UFOPEDIA: \"Enfoui sous les nombreuses couches gélatineuses de cet organisme se trouve un puissant congélateur chimique, constituant la principale force offensive de la créature. Il semblerait, d'après les attaques perpétrées, que la peau douce et souple de l'Hallucinoïde soit sensible à la chaleur. Ces mutants accompagnent souvent leurs maîtres, les Aquatoïdes.\"\n  STR_XARQUID_UFOPEDIA: \"Le Xarquid, autre vertébré terrestre modifié, est une créature aussi belle que mortelle. Le gargantuesque et souple nageur cache un arsenal d'armes dévastateur, un jet d'encre étouffant et une rafale de particules ionisées. Depuis les premières rencontres avec cette créature puissante, nous nous sommes méfiés de ses pouvoirs et des vindicatifs Hommes-Poissons qui la contrôlent.\"\n  STR_XARQUID_AUTOPSY: \"Autopsie de Xarquid\"\n  STR_XARQUID_AUTOPSY_UFOPEDIA: \"Ce nautile a acquis sa trop grande taille à coups de drogues aliens et d'opérations chirurgicales. Dénaturée à outrance, les Hommes-Poissons ont doté la créature de systèmes de contrôle mécaniques, la privant ainsi totalement de ses qualités originelles. Utilisés comme plate-forme organique militaire, les Xarquids sont, du fait de leur solide armature et de leur rapide mobilité, de puissants adversaires.\"\n  STR_ION_BEAM_ACCELERATORS_UFOPEDIA: \"Les sous-marins volants aliens comptent sur leurs systèmes d'alimentation complexes pour les propulser à d'incroyables vitesses sous l'eau. Leur technologie se base sur le 'DÉPLACEUR IONIQUE' qui utilise le zrbite comme catalyseur; les moteurs pouvant ainsi déplacer jusqu'à 100 fois leur propre volume en eau par seconde. Avec cette énorme puissance, les aliens sont donc capables de dépasser la plupart des sous-marins humains. Nous pouvons créer le même système de propulsion grâce à des batteries aqua-plastiques et zrbites.\"\n  STR_MAGNETIC_NAVIGATION_UFOPEDIA: \"Ces unités génèrent un champ magnétique sphérique multicouche qui se projette dans un rayon de 1000 m autour du sous-marin. Les navigateurs aliens sont alors directement connectés aux machines et se frayent un chemin sensoriellement autour du monde invisible sous les vagues. Le système d'interface opère en utilisant des matières cérébrales aliens modifiées qui communiquent directement avec le cerveau de son utilisateur, par liaison neurale.\"\n  STR_ALIEN_SUB_CONSTRUCTION_UFOPEDIA: \"Chaque vaisseau a une structure de type caméléon, fidèlement inspirée des créatures marines et faites d'aqua-plastiques. Chaque sous-marin fonctionne comme un organisme : l'équipage est en symbiose avec le vaisseau. La plupart de ces systèmes peuvent être reproduits et il est possible de développer une technologie hybride qui nous permette d'atteindre le même niveau technologique.\"\n  STR_ALIEN_CRYOGENICS_UFOPEDIA: \"Les innombrables aliens venus en secret sur la Terre sont gardés en hibernation artificielle, par cryogénie. Toutes les créatures sont maintenues dans des unités, leurs températures corporelles réduites, mais permettant de maintenir actif leurs activités corporelles. Les examens faits jusqu'à présent ont révélé que certains des corps sont conservés depuis plus de 60 millions d'années.\"\n  STR_ALIEN_CLONING_UFOPEDIA: \"La plupart des aliens que nous avons capturés sont, jusque dans leur code ADN, des répliques identiques. Des échantillons de cellules, choisis dans les banques de gènes gelés des Aliens, sont placés dans les unités. Certaines unités contiennent des humains ou des parties du corps. Il est aussi possible que ces unités cloniques aient été conçues pour créer une race hybride d'aliens-humains.\"\n  STR_ALIEN_LEARNING_ARRAYS_UFOPEDIA: \"À l'aide d'implants de contrôle moléculaire dans leurs crânes, tous les aliens reçoivent directement l'information injectée dans leur cerveau par ces machines. Les aliens récemment clonés sont amenés dans ces unités où des souvenirs propres à leur race et des informations scientifiques et de combat sont téléchargés dans leurs esprits vierges.\"\n  STR_ALIEN_IMPLANTER_UFOPEDIA: \"Cette unité sert à fixer des implants de contrôle moléculaire chez les aliens, fertiliser les races reproductives, et à insérer ou enlever des organes et des éléments électroniques d'une créature. On pensait que cette opération était effectuée sur des patients faibles, mais le sujet est très conscient de ce qui se passe, et malheureusement, c'est l'anatomie humaine qui semble le mieux se marier à l'unité.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"Nous commençons à comprendre pourquoi les aliens capturent les humains. Ni pour se nourrir, ni pour la fertilisation des embryons aliens, ils s'en servent pour concevoir des créatures et des systèmes de contrôle. Leur technique s'appuie sur un esprit commun, un intellect partagé, pour lesquels le cerveau humain est idéal. Le tissu cervical est utilisé dans la plupart des systèmes biologiques de recherche et de mémoire informatiques aliens; le reste est utilisé pour les constructions et la reproduction.\"\n  STR_AQUA_PLASTICS_UFOPEDIA: \"Les structures et les sous-marins aliens utilisent dans la plupart de leur construction un matériau extrêmement solide, flexible et durable. L'aqua-plastique est un matériau complexe catalysé à base de zrbite. Dense et pourtant très léger, la force de cette substance dépasse même celle du titane ou du Kevlar.\"\n  STR_ZRBITE_UFOPEDIA: \"C'est un alliage alien, mi-or, mi-biomatériau alien. Utilisé comme source d'énergie, de faibles quantités génèrent plus de puissance qu'une unité nucléaire faisant 10 fois sa taille. Nous n'avons pas les moyens techniques de reproduire ce matériau, la plupart de ses composants étant d'origine alien.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"Les aliens frappent tout autour du globe, avec une efficacité sans faille. Nous n'arrivons pas à localiser la source. Pourrait-elle se trouver dans des profondeurs trop impénétrables pour que nous puissions la localiser? Les organismes que nous avons rencontrés ne sont pas tous aliens; certains sont très vieux, d'autres proviennent de races que l'on croyait disparues. Nous devons faire face à une menace qui sommeille depuis des millénaires, une symbiose subtile entre aliens et humains. Au cœur des océans se trouvent d'anciens sites utilisés par les aliens pour contacter leurs cousins stellaires. Chacun de ces douze sites contient un appareil de Synomium, une puissante technologie alien. Leur machine de guerre étant en marche, les aliens réactivent ces sites pour agrandir leur réseau de contrôle moléculaire; nous devons détruire ces sites à tout prix.\"\n  STR_THE_ULTIMATE_THREAT_UFOPEDIA: \"Il y a soixante-cinq millions d'années, un grand vaisseau-colonie fut envoyé sur Terre depuis un monde alien éloigné. Alors que l'énorme vaisseau s'approchait de la jeune planète, une éruption solaire d'une violence extrême endommagea les systèmes de navigation. Estropiée, l'énorme masse fendit la stratosphère et émergea dans le ciel du Crétacé. Sur Terre, d'innombrables espèces vivantes levèrent les yeux pour la voir s'écraser sur leur planète. Un gros nuage de poussière vint saturer l'atmosphère et en même temps que la Terre refroidit, la forme de vie dominante, les puissants dinosaures, périt. Mais les 400 milliards de tonnes du T'leth ne furent pas détruites au cours de l'impact, et des ordinateurs sophistiqués entamèrent un cycle de sommeil cryogénique pour les créatures dissimulées dans les soutes. Alors que les siècles passaient, les ordinateurs réveillèrent des groupes d'aliens pour essayer de communiquer avec leurs cousins stellaires, sans résultat car le cœur de la puissance alien continua de dormir.\"\n  STR_TLETH_THE_ALIEN_CITY: \"T'leth, la ville des aliens\"\n  STR_TLETH_THE_ALIEN_CITY_UFOPEDIA: \"T'leth, l'énorme vaisseau-colonie alien, repose au fond du Sigsbee Deep, dans le Golfe du Mexique. Au cœur de la ville erre une horreur alien si vile et si puissante que même la mort ne peut pas la vaincre. Dans une pièce de métal alien repose la forme assoupie du Grand Rêveur, l'Ultime Alien. Lorsque T'leth s'élèvera au-dessus des vagues, il commencera à s'agiter et une fois réveillé, personne ne pourra plus l'arrêter. Ni vivant, ni mort, l'esprit alien contrôle l'armée alien. L'étrange technologie du contrôle moléculaire relie tous les aliens à l'esprit unique et l'esprit unique à tous les aliens. Des fœtus aliens/humains génétiquement mutés alimentent l'esprit alien en énergie et forment le lien entre le maître et ses sujets. Le mythe de l'Ultime Alien a existé dans les cœurs et les esprits humains depuis des siècles, mais la mer avait toujours dissimulé l'ultime vérité.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"CENTRER SUR LE SITE - TEMPS = 5 s\"\n  STR_CANCEL_UC: \"ANNULER\"\n  STR_NONE: \"Rien\"\n  STR_UNKNOWN: \"Inconnu\"\n  STR_POOR: \"Médiocre\"\n  STR_AVERAGE: \"Moyen\"\n  STR_GOOD: \"Bon\"\n  STR_EXCELLENT: \"Excellent\"\n  STR_BUILD_NEW_BASE_UC: \"CONSTRUIRE NOUVELLE BASE\"\n  STR_BASE_INFORMATION: \"INFORMATIONS SUR LA BASE\"\n  STR_EQUIP_CRAFT: \"ÉQUIPER SOUS-MARIN\"\n  STR_BUILD_FACILITIES: \"CONSTRUIRE INSTALLATIONS\"\n  STR_RESEARCH: \"RECHERCHE\"\n  STR_MANUFACTURE: \"FABRICATION\"\n  STR_TRANSFER_UC: \"TRANSFERT\"\n  STR_PURCHASE_RECRUIT: \"ACHETER/RECRUTER\"\n  STR_SACK: \"RENVOYER\"\n  STR_SELL_SACK_UC: \"VENDRE/RENVOYER\"\n  STR_GEOSCAPE_UC: \"GÉOSCAPE\"\n  STR_NAME: \"Nom\"\n  STR_AREA: \"Zone\"\n  STR_BUILD_NEW_BASE: \"Construire une nouvelle base\"\n  STR_CANCEL: \"Annuler\"\n  STR_COST_UC: \"PRIX>\"\n  STR_CONSTRUCTION_TIME_UC: \"DURÉE DE CONSTRUCTION>\"\n  STR_DAY:\n    one: \"{N} jour\"\n    many: \"{N} jours\"\n    other: \"{N} jours\"\n  STR_HOUR:\n    one: \"{N} heure\"\n    many: \"{N} heures\"\n    other: \"{N} heures\"\n  STR_MAINTENANCE_UC: \"ENTRETIEN>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Installations\"\n  STR_CURRENT_RESEARCH: \"RECHERCHE ACTUELLE\"\n  STR_SCIENTISTS_AVAILABLE: \"Savants disponibles> {ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Savants affectés> {ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Espace de laboratoire disponible> {ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"PROJET DE RECHERCHE\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"SAVANTS AFFECTÉS\"\n  STR_PROGRESS: \"PROGRESSION\"\n  STR_NEW_PROJECT: \"Nouveau projet\"\n  STR_CANCEL_PROJECT: \"ANNULER LE PROJET\"\n  STR_NEW_RESEARCH_PROJECTS: \"NOUVEAUX PROJETS DE RECHERCHE\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"SAVANTS DISPONIBLES> {ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"ESPACE DE LABORATOIRE DISPONIBLE> {ALT}{0}\"\n  STR_INCREASE: \"Augmenter\"\n  STR_DECREASE: \"Diminuer\"\n  STR_START_PROJECT: \"LANCER LE PROJET\"\n  STR_CURRENT_PRODUCTION: \"PRODUCTION ACTUELLE\"\n  STR_ENGINEERS_AVAILABLE: \"Techniciens disponibles> {ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Techniciens affectés> {ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Espace d'atelier disponible> {ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Budget actuel> {ALT}{0}\"\n  STR_ITEM: \"OBJET\"\n  STR_ENGINEERS__ALLOCATED: \"Techniciens affectés\"\n  STR_UNITS_PRODUCED: \"Unités produites\"\n  STR_TOTAL_TO_PRODUCE: \"Total à produire\"\n  STR_COST__PER__UNIT: \"Coût{NEWLINE}par{NEWLINE}unité\"\n  STR_DAYS_HOURS_LEFT: \"Jours/heures restants\"\n  STR_NEW_PRODUCTION: \"Nouvelle production\"\n  STR_PRODUCTION_ITEMS: \"Objets à produire\"\n  STR_CATEGORY: \"CATÉGORIE\"\n  STR_START_PRODUCTION: \"COMMENCER LA PRODUCTION\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} heures de technicien pour produire une unité\"\n  STR_COST_PER_UNIT_: \"Coût par unité> {ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Espace de travail requis> {ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"MATÉRIAUX SPÉCIAUX REQUIS\"\n  STR_ITEM_REQUIRED: \"OBJET REQUIS\"\n  STR_UNITS_REQUIRED: \"UNITÉS REQUISES\"\n  STR_UNITS_AVAILABLE: \"UNITÉS DISPONIBLES\"\n  STR_STOP_PRODUCTION: \"ARRÊTER LA PRODUCTION\"\n  STR_ENGINEERS_AVAILABLE_UC: \"TECHNICIENS DISPONIBLES> {ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"ESPACE D'ATELIER DISPONIBLE> {ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"PROFIT MENSUEL> {ALT}{0}\"\n  STR_INCREASE_UC: \"AUGMENTER\"\n  STR_DECREASE_UC: \"DIMINUER\"\n  STR_UNITS_TO_PRODUCE: \"Unités à produire\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Acheter/recruter\"\n  STR_COST_OF_PURCHASES: \"Prix d'achat> {ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"COÛT PAR UNITÉ\"\n  STR_QUANTITY_UC: \"QUANTITÉ\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"PERSONNEL DISPONIBLE:PERSONNEL TOTAL>\"\n  STR_SOLDIERS: \"Aquanautes\"\n  STR_SCIENTISTS: \"Savants\"\n  STR_ENGINEERS: \"Techniciens\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"ESPACE UTILISÉ:ESPACE DISPONIBLE>\"\n  STR_LIVING_QUARTERS: \"Quartier d'habitation\"\n  STR_STORES: \"Entrepôts\"\n  STR_LABORATORIES: \"Laboratoires\"\n  STR_WORK_SHOPS: \"Ateliers\"\n  STR_HANGARS: \"Abris pour sous-marins\"\n  STR_SHORT_RANGE_DETECTION: \"Sonar à courte portée\"\n  STR_DEFENSE_STRENGTH: \"Force de défense\"\n  STR_TRANSFERS_UC: \"TRANSFERTS\"\n  STR_TRANSFERS: \"Transferts\"\n  STR_ARRIVAL_TIME_HOURS: \"ARRIVÉE PRÉVUE (H)\"\n  STR_COST_: \"Prix> {ALT}{0}\"\n  STR_AREA_: \"Zone> {ALT}{0}\"\n  STR_BASE_NAME: \"Nom de la base?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"SÉLECTIONNEZ LA POSITION DU SAS\"\n  STR_TRANSFER: \"Transfert\"\n  STR_AMOUNT_TO_TRANSFER: \"QUANTITÉ À TRANSFÉRER\"\n  STR_SELECT_DESTINATION_BASE: \"Sélectionnez la destination\"\n  STR_COST: \"Prix\"\n  STR_INTRO_1: \"Copyright 1995 MicroProse\"\n  STR_INTRO_2: \"Mars : La chute de Cydonia\"\n  STR_INTRO_3: \"X-Com triomphant, ayant réussi à détruire le cœur même de la machine de guerre alien, a pris le chemin du retour à plein gaz. Cependant, tout n'est pas mort sur la base martienne ravagée.\"\n  STR_INTRO_4: \"Un puissant rayon tachyon émerge des décombres du centre nerveux Cydonien, et fend le vide pour atteindre sa destination............\"\n  STR_INTRO_5: \".......... la Terre.\"\n  STR_INTRO_6: \"Au cœur de l'océan, le rayon touche un récepteur depuis longtemps endormi. D'immenses ordinateurs assoupis commencent à s'agiter. Dans les profondeurs, à l'abri des regards humains, dans de vastes pièces remplies d'aliens endormis, le long cycle de réanimation commence.\"\n  STR_INTRO_7: \"2040 : la Terre a retrouvé son ignorance, les terreurs de la guerre contre les aliens ont été oubliées. Mais, cachées dans les profondeurs de l'océan, les hordes aliens s'apprêtent à renverser l'humanité et prendre le contrôle du monde entier.\"\n  STR_INTRO_8: \"Les aliens attaquent l'humanité, cherchant des cobayes pour leurs viles expériences, écumant la surface du globe pour extorquer minéraux précieux et ressources, pillant toutes les richesses des mers. Alors, les yeux des aliens se posent au-delà des vagues, sur le monde des hommes.\"\n  STR_INTRO_9: \"De puissants sous-marins volants de conception étrange parcourent les océans, regardant, cherchant, chassant.........\"\n  STR_INTRO_10: \"....... et trouvant des proies à attaquer.\"\n  STR_INTRO_11: \"Un monde sans défense doit faire face à de nouvelles armes singulières. Nous sommes totalement à la merci de la menace alien.{NEWLINE}Une seule organisation peut nous sauver, mais nous lui avons tourné le dos il y a bien longtemps......\"\n  STR_INTRO_12: \"L'installation sous-marine expérimentale de X-COM\"\n  STR_INTRO_13: \"'SOS! SOS! Ici le paquebot transatlantique Hyperion. Nous sommes attaqués. SOS! SO............'\"\n  STR_INTRO_14: \"'Contrôle de commandes appelle abri pour sous-marins un : ouvrez les portes vers l'océan, déployez Barracuda zéro un. Nous avons repéré une attaque alien - alerte rouge.'{NEWLINE}'Je répète : alerte rouge.'\"\n  STR_INTRO_15: \"Les aliens font preuve d'une efficacité impitoyable....\"\n  STR_INTRO_16: \"... d'une précision infaillible.\"\n  STR_INTRO_17: \"'Barracuda zéro un appelle la base, nous approchons de ce qui reste de l'Hyperion.'\"\n  STR_INTRO_19: \"........... 'Sas prêt... Nous approchons de l'épave.'{NEWLINE}'Ouaouh!'{NEWLINE}'Est-ce que vous voyez ces créatures à travers ma caméra?'\"\n  STR_GAMEOVER_1: \"Nous avons échoué, les aliens ont anéanti nos derniers espoirs de salut.{NEWLINE}X-Com a été détruit et la Terre est offerte, pieds et poings liés, à notre ancien ennemi.\"\n  STR_GAMEOVER_2: \"T'leth fait frémir la stratosphère et commence à bouger à la surface du monde. Il répand la mort et récolte les restes de la race humaine. Au plus profond de ses entrailles, l'esprit alien meurtrier se réveille.\"\n  STR_GAMEOVER_3: \"Dans les capitales de toutes les nations, des plans désespérés sont élaborés. Tout cela ne sert à rien, sans la technologie du projet de recherche de X-Com, nos armes sont inefficaces.\"\n  STR_GAMEOVER_4: \"Les aliens établissent des bases aux pôles et commencent à faire fondre la glace; le monde ne sera bientôt plus qu'un vaste océan. Les survivants de la race humaine sont rassemblés et utilisés pour de viles expériences de reproduction, à des fins aliens inconnues. Les cieux s'assombrissent et une puissante épidémie s'abat sur la Terre.\"\n  STR_GAMEOVER_5: \"Nous ne pouvons pas résister au nouvel ordre mondial, ceux qui essaient connaissent une fin atroce face à des armes aliens incompréhensibles. Pour le reste d'entre nous, pas de telle délivrance, notre chère Terre est devenue un monde alien et l'humanité est perdue et écrasée sous une horreur rampante.\"\n  STR_OUTRO_1: \"La tombe, ravagée et décimée, un rugissement bouillonnant s'échappe du cercueil en son centre.{NEWLINE}Imbéciles, vous périrez tous....................\"\n  STR_OUTRO_2: \".................personne ne s'échappera.\"\n  STR_OUTRO_3: \"La tombe est secouée par une énorme explosion qui déchire la ville; l'air se remplit de fumée et de débris. Les plans des aliens ont été déjoués........\"\n  STR_OUTRO_4: \"L'immensité tordue de T'leth commence à se rompre. Ses flèches luisantes et ses couloirs d'adamantine vomissent des flammes et de la fumée.\"\n  STR_OUTRO_5: \"Le puissant repaire alien titube vers la mer, les gémissements du métal et des âmes torturés envahissent l'air. Plus jamais le Grand Rêveur ne rêvera de conquérir le monde.\"\n  STR_OUTRO_6: \"Dans une dernière explosion assourdissante, T'leth se brise et se déchire.{NEWLINE}La menace alien a disparu, la Terre est nettoyée..................\"\n  STR_OUTRO_7: \"Une planète bleu-vert assoupie, dans un recoin éloigné de la galaxie.\"\n  STR_OUTRO_8: \"Le futur proche, un endroit sûr.\"\n  STR_OUTRO_9: \"La menace alien sur la Terre a été vaincue il y a bien longtemps.\"\n  STR_OUTRO_10: \"De vastes métropoles pullulent de millions d'êtres humains.\"\n  STR_OUTRO_11: \"Les exploits de X-Com et les guerres aliens sont l'essence des nouveaux contes pour enfants.\"\n  STR_OUTRO_12: \"Mais les légendes ne contiennent-elles pas toujours une part de vérité............\"\n  STR_RISE_1: \"T'leth, connue sous de nombreux noms dans de nombreuses légendes et de nombreuses contrées.\"\n  STR_RISE_2: \"Dans un hurlement explosif qui se répercute à travers le globe tout entier, T'leth commence à s'élever des fonds marins.\"\n  STR_RISE_3: \"L'immense édifice fait soudain surface dans le Golfe du Mexique.\"\n  STR_RISE_4: \"400 milliards de tonnes de métal alien, la puissante ville alien où repose le corps assoupi de l'Ultime Alien. Emprisonné sur Terre depuis 65 millions d'années, ce vil dieu de l'espace commence à s'agiter.\"\n  STR_RISE_5: \"Les eaux se mettent à bouillonner alors que la tombe du Grand Rêveur émerge à la lumière................\"\n  STR_RISE_6: \"......... une lumière qui mourra bientôt si X-Com ne parvient pas à détruire la machine de guerre alien.\"\n  STR_YOU_HAVE_FAILED: \"Vous n'avez pas réussi à arrêter la machine de guerre alien. Les organisations qui vous ont financé, déçues de vos performances, essaient de négocier une solution non militaire avec les aliens. Les envahisseurs ont des plans très différents et bientôt le monde entier connaît la vérité...\"\n  STR_TOTAL_UC: \"TOTAL\"\n  STR_INCOME: \"Revenu\"\n  STR_EXPENDITURE: \"Dépenses\"\n  STR_MAINTENANCE: \"Entretien\"\n  STR_BALANCE: \"Solde\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"Activité des aliens par mer\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"Activité des aliens par zone\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"Activité X-Com par mer\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"Activité X-Com par zone\"\n  STR_FINANCE: \"Finances\"\n  STR_DATE_FIRST: \"{0}er\"\n  STR_DATE_SECOND: \"{0}\"\n  STR_DATE_THIRD: \"{0}\"\n  STR_DATE_FOURTH: \"{0}\"\n  STR_FINANCE_THOUSANDS: \"x $1000\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Pas assez de matériaux spéciaux pour produire{NEWLINE}{0}{NEWLINE}à{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Pas assez d'argent pour produire{NEWLINE}{0}{NEWLINE}à{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"Production de{NEWLINE}{0}{NEWLINE}à{NEWLINE}{1}{NEWLINE}terminée\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"Construction de{NEWLINE}{0}{NEWLINE}à{NEWLINE}{1}{NEWLINE}terminée\"\n  STR_OK_5_SECONDS: \"OK - 5 s\"\n  STR_RESEARCH_COMPLETED: \"Recherche terminée\"\n  STR_VIEW_REPORTS: \"VOIR RAPPORTS\"\n  STR_WE_CAN_NOW_RESEARCH: \"Nous pouvons maintenant étudier\"\n  STR_WE_CAN_NOW_PRODUCE: \"Nous pouvons maintenant produire\"\n  STR_SUNDAY: \"DIMANCHE\"\n  STR_MONDAY: \"LUNDI\"\n  STR_TUESDAY: \"MARDI\"\n  STR_WEDNESDAY: \"MERCREDI\"\n  STR_THURSDAY: \"JEUDI\"\n  STR_FRIDAY: \"VENDREDI\"\n  STR_SATURDAY: \"SAMEDI\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Pas assez de {0} pour ravitailler le sous-marin {1} à {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Pas assez de {0} pour réarmer le sous-marin {1} à {2}\"\n  STR_UFO_IS_NOT_RECOVERED: \"L'osni n'est pas récupéré\"\n  STR_UFO_IS_RECOVERED: \"L'osni est récupéré\"\n  STR_CRAFT_IS_LOST: \"Le sous-marin volant est perdu\"\n  STR_TERROR_CONTINUES: \"L'activité alien continue\"\n  STR_ALIENS_DEFEATED: \"Les aliens sont vaincus\"\n  STR_BASE_IS_LOST: \"La base est perdue\"\n  STR_BASE_IS_SAVED: \"La base est sauvée\"\n  STR_ALIEN_BASE_STILL_INTACT: \"La colonie alien est intacte\"\n  STR_ALIEN_BASE_DESTROYED: \"La colonie alien est détruite\"\n  STR_ALIENS_KILLED: \"ALIENS TUÉS\"\n  STR_ALIEN_CORPSES_RECOVERED: \"CORPS ALIENS RÉCUPÉRÉS\"\n  STR_LIVE_ALIENS_RECOVERED: \"ALIENS VIVANTS RÉCUPÉRÉS\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"OBJETS ALIENS RÉCUPÉRÉS\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"CONTRÔLE DE COLONIE ALIEN DÉTRUIT\"\n  STR_ALIEN_SYNOMIUM_DEVICE_DESTROYED: \"APPAREIL DE SYNOMIUM ALIEN DÉTRUIT\"\n  STR_ALIEN_SYNOMIUM_DEVICE_FAILED: \"APPAREIL DE SYNOMIUM ALIEN NON DÉTRUIT\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"CIVILS TUÉS PAR DES ALIENS\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"CIVILS TUÉS PAR DES AGENTS X-COM\"\n  STR_CIVILIANS_SAVED: \"CIVILS SAUVÉS\"\n  STR_XCOM_OPERATIVES_KILLED: \"AGENTS X-COM TUÉS\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"AGENTS X-COM PORTÉS DISPARU\"\n  STR_TANKS_DESTROYED: \"PLATES-FORMES D'ARMES X-COM DÉTRUITES\"\n  STR_XCOM_CRAFT_LOST: \"SOUS-MARIN X-COM PERDU\"\n  STR_UFO_RECOVERY: \"RÉCUPÉRATION D'OSNI\"\n  STR_ALIEN_BASE_RECOVERY: \"RÉCUPÉRATION DE COLONIE ALIEN\"\n  STR_BASE_UNDER_ATTACK: \"{0} est attaqué!\"\n  STR_BASE_DEFENSES_INITIATED: \"DÉFENSES DE LA BASE ACTIVÉES\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"LE BOUCLIER REPOUSSE L'OSNI!\"\n  STR_FIRING: \"MISE À FEU\"\n  STR_HIT: \"TOUCHÉ!\"\n  STR_UFO_DESTROYED: \"OSNI DÉTRUIT!\"\n  STR_MISSED: \"RATÉ!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Vendre/renvoyer\"\n  STR_VALUE_OF_SALES: \"VALEUR DES VENTES> {ALT}{0}\"\n  STR_FUNDS: \"BUDGET> {ALT}{0}\"\n  STR_SELL_SACK: \"Vendre/virer\"\n  STR_VALUE: \"Valeur\"\n  STR_CRAFT_: \"SOUS-MARIN> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"RÉCUPÉRATION D'OSNI ÉCRASÉ\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"AVERTISSEMENT - Il y aura des aliens dans le sous-marin et autour du site. La mission sera complétée quand toutes les unités ennemies auront été éliminées ou neutralisées. La récupération des restes du sous-marin alien, de la technologie et des corps aliens pourra alors commencer. Pour abandonner la mission, ramenez les aquanautes X-Com au sous-marin et cliquez sur l'icône 'Abandonner la mission'.\"\n  STR_UFO_GROUND_ASSAULT: \"ATTAQUE AU SOL DE L'OSNI\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"Explorez le site où le sous-marin alien a touché le fond et, si possible, entrez à l'intérieur. La mission sera réussie quand toutes les unités ennemies auront été éliminées ou neutralisées. La récupération du sous-marin alien, des objets et des corps aliens pourra alors commencer. Pour abandonner la mission, ramenez les aquanautes X-Com au sous-marin et cliquez sur l'icône 'Abandonner la mission'.\"\n  STR_BASE_DEFENSE: \"DÉFENSE DE LA BASE\"\n  STR_BASE_UC_: \"BASE> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"Un vaisseau alien a touché le fond tout près. Notre base court un grand danger. Selon la procédure habituelle, tout le personnel non-combattant et les sous-marins X-Com fonctionnels ont été évacués. Les unités aliens vont entrer dans la base par les portes des abris pour sous-marins ou par le sas. Défendez la base et ses installations vitales à tout prix - c'est un combat à mort. Si vous cliquez sur l'icône 'Abandonner la mission', vous serez vaincu et perdrez la base.\"\n  STR_ALIEN_COLONY_ATTACK_MISSION: \"ATTAQUE DE LA COLONIE ALIEN\"\n  STR_ALIEN_BASE_ASSAULT: \"COLONIE ALIEN PARTIE UN\"\n  STR_ALIEN_COLONY_P1_BRIEFING: \"Cette mission est un raid sur le site d'une colonie alien. Le site a deux niveaux, amenez tous les aquanautes à la sortie lumineuse du premier complexe et cliquez sur l'icône 'Abandonner la mission' pour procéder. Tout équipement laissé derrière restera sur le fond marin jusqu'à ce que la deuxième section soit résolue. Pour quitter, placez les aquanautes dans le sous-marin et cliquez sur l'icône 'Abandonner la mission'.\"\n  STR_ALIEN_COLONY_P2: \"COLONIE ALIEN PARTIE DEUX\"\n  STR_ALIEN_COLONY_P2_BRIEFING: \"Après avoir négocié le premier niveau et d'être entré au cœur de la colonie, la mission est de détruire le centre de contrôle, l'appareil de Synomium, ou d'éliminer tous les aliens. Pour abandonner, placez tous les aquanautes sur le point de départ et cliquez sur l'icône 'Abandonner la mission'. Tout équipement X-Com viable sera ramené à la base.\"\n  STR_ALIENS_LAUNCH_PORT_TERROR: \"LES ALIENS ATTAQUENT{NEWLINE}UN PORT SUR\"\n  STR_PORT_TERROR: \"LES ALIENS ATTAQUENT UN PORT\"\n  STR_PORT_TERROR_BRIEFING: \"Les aliens ont lancé une attaque contre les sites de surface. Le port et sa population civile sont en danger. Votre escouade doit éliminer tous les aliens et protéger les témoins innocents de l'incursion alien. Pour quitter, placez les aquanautes dans le sous-marin volant et cliquez sur l'icône 'Abandonner la mission'.\"\n  STR_ALIENS_LAUNCH_ISLAND_TERROR: \"LES ALIENS ATTAQUENT{NEWLINE}UNE ÎLE SUR\"\n  STR_ISLAND_TERROR: \"LES ALIENS ATTAQUENT UNE ÎLE\"\n  STR_ISLAND_TERROR_BRIEFING: \"Les aliens ont lancé une attaque contre les sites de surface. L'île et sa population civile sont en danger. Votre escouade doit éliminer tous les aliens et protéger les témoins innocents de l'incursion alien. Pour quitter, placez les aquanautes dans le sous-marin volant et cliquez sur l'icône 'Abandonner la mission'.\"\n  STR_ALIENS_ATTACK_SHIPPING_ROUTE: \"LES ALIENS ATTAQUENT{NEWLINE}UNE ROUTE MARITIME\"\n  STR_CARGO_SHIP_P1: \"CARGO PARTIE UN\"\n  STR_CARGO_SHIP_P2: \"CARGO PARTIE DEUX\"\n  STR_CRUISE_SHIP_P1: \"NAVIRE DE CROISIÈRE PARTIE UN\"\n  STR_CRUISE_SHIP_P2: \"NAVIRE DE CROISIÈRE PARTIE DEUX\"\n  STR_SHIP_RESCUE_MISSION: \"MISSION DE SAUVETAGE D'UN NAVIRE\"\n  STR_SHIP_RESCUE_P1_BRIEFING: \"Cette mission est une chasse aux insectes, éliminez toutes les unités aliens sur le navire, et épargnez la vie des civils se trouvant à bord. Les aliens sont dispersés au-dessus et en-dessous des ponts, protégez le pont supérieur avant d'entrer aux ponts inférieurs. Pour quitter, placez les aquanautes dans le sous-marin volant et cliquez sur l'icône 'Abandonner la mission'.\"\n  STR_SHIP_RESCUE_P2_BRIEFING: \"Maintenant que la voie est libre sur le pont supérieur, procédez aux ponts inférieurs. Vous descendez dans la cale avec le monte-charge. Votre équipe doit éliminer tous les aliens de ce niveau pour compléter la mission. Pour abandonner, placez tous les aquanautes sur le point de départ du monte-charge et cliquez sur l'icône 'Abandonner la mission'.\"\n  STR_ALIEN_ACTIVITY_DETECTED: \"ACTIVITÉ ALIEN DÉTECTÉE\"\n  STR_ALIEN_CONTACT_SITE_MISSION: \"SITE DE CONTACT ALIEN\"\n  STR_ARTIFACT_SITE_P1: \"SITE DE CONTACT ALIEN PARTIE UN\"\n  STR_ARTIFACT_SITE_P1_BRIEFING: \"Cette mission est un raid sur un site de communications aliens récemment activé. Le site a deux niveaux, le fond des mers avec ses pyramides aliens et un complexe alien secret. Dirigez tous les aquanautes à l'entrée du complexe et cliquez sur l'icône 'Abandonner la mission' pour procéder. Pour quitter, placez les aquanautes dans le sous-marin volant et cliquez sur l'icône 'Abandonner la mission'.\"\n  STR_ARTIFACT_SITE_P2: \"SITE DE CONTACT ALIEN PARTIE DEUX\"\n  STR_ARTIFACT_SITE_P2_BRIEFING: \"Après avoir négocié les structures aliens et d'être entré dans le complexe, les buts de la mission sont clairs. Pénétrez au cœur du complexe alien et détruisez l'appareil de contrôle moléculaire de Synomium pour compléter la mission. Pour abandonner, placez tous les aquanautes sur l'ascenseur d'accès et cliquez sur l'icône 'Abandonner la mission'.\"\n  STR_SIGSBEE_DEEP_MISSION: \"MISSION DU SIGSBEE DEEP{NEWLINE}VILLE ALIEN NIVEAU UN\"\n  STR_TLETH_P1_BRIEFING: \"Nous pénétrons dans l'inconnu, et n'importe quoi pourrait nous attendre. Nous savons qu'il y a deux autres niveaux dans la ville alien et votre escouade doit courir vers la sortie de ce niveau pour entrer dans le prochain. Placez tous les aquanautes sur la sortie et cliquez sur l'icône 'Abandonner la mission' pour avancer. Si vous abandonnez ailleurs, vous terminerez la mission.\"\n  STR_TLETH_ATTACK_MISSION: \"MISSION D'ATTAQUE DU T'LETH{NEWLINE}VILLE ALIEN NIVEAU DEUX\"\n  STR_TLETH_P2_BRIEFING: \"En s'avançant dans l'inconnu, n'importe quoi pourrait nous attendre. Nous savons qu'il y a un autre niveau dans la ville alien et votre escouade doit courir vers la sortie de ce niveau pour entrer dans le prochain. Placez tous les aquanautes sur la sortie et cliquez sur l'icône 'Abandonner la mission' pour avancer. Si vous abandonnez ailleurs, vous terminerez la mission.\"\n  STR_FINAL_TLETH_MISSION: \"MISSION T'LETH FINALE{NEWLINE}VILLE ALIEN NIVEAU TROIS\"\n  STR_TLETH_P3_BRIEFING: \"La fin est proche, à partir d'ici, nous cherchons la crypte de l'Ultime Alien. Détruisez les huit unités d'alimentation de la tombe pour éliminer la menace alien. N'abandonnez pas maintenant! Autrement, si vous le faites, tous nos efforts jusqu'ici seront vains et la mission sera terminée.\"\n  STR_TLETH_P1: \"VILLE ALIEN NIVEAU UN\"\n  STR_TLETH_P2: \"VILLE ALIEN NIVEAU DEUX\"\n  STR_TLETH_P3: \"VILLE ALIEN NIVEAU TROIS\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"AUCUN ABRI DE LIBRE POUR LA PRODUCTION D'UN SOUS-MARIN!{SMALLLINE}Tout sous-marin volant affecté à une base, transféré à une base, acheté ou construit a besoin d'un abri. Construisez un nouvel abri pour sous-marins ou transférez un sous-marin à une autre base.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"AUCUN ABRI POUR SOUS-MARINS DE LIBRE POUR L'ACHAT!{SMALLLINE}Tout sous-marin volant affecté à une base, transféré à une base, acheté ou construit a besoin d'un abri. Construisez un nouvel abri pour sous-marins ou transférez un sous-marin à une autre base.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"AUCUN ABRI POUR SOUS-MARINS DE LIBRE POUR LE TRANSFERT!{SMALLLINE}Tout sous-marin volant affecté à une base, transféré à une base, acheté ou construit a besoin d'un abri. Construisez un nouvel abri pour sous-marins ou transférez un sous-marin à une autre base.\"\n  STR_CANNOT_BUILD_HERE: \"IMPOSSIBLE DE CONSTRUIRE ICI!{SMALLLINE}Vous devez construire à côté d'une nacelle existante.\"\n  STR_NO_FREE_ACCOMODATION: \"AUCUN LOGEMENT DE LIBRE!{SMALLLINE}La base de destination n'a pas assez de place dans les quartiers d'habitation.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"PAS ASSEZ D'ESPACE DE TRAVAIL!{SMALLLINE}Construisez un nouvel atelier ou réduisez le travail sur d'autres projets.\"\n  STR_NOT_ENOUGH_MONEY: \"PAS ASSEZ D'ARGENT!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"PAS ASSEZ D'ESPACE DE STOCKAGE!{SMALLLINE}Construisez un nouvel entrepôt ou transférez les stocks existants aux autres bases.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"PAS ASSEZ D'ESPACE VITAL!{SMALLLINE}Construisez de nouveaux quartiers d'habitation ou transférez le personnel aux autres bases.\"\n  STR_LAUNCH_INTERCEPTION: \"LANCER UNE INTERCEPTION\"\n  STR_CRAFT: \"SOUS-MARIN\"\n  STR_STATUS: \"STATUT\"\n  STR_BASE: \"BASE\"\n  STR_READY: \"PRÊT\"\n  STR_OUT: \"ABSENT\"\n  STR_REPAIRS: \"RÉPARATION\"\n  STR_REFUELLING: \"RAVITAILLE\"\n  STR_REARMING: \"RÉARMEMENT\"\n  STR_TARGET: \"CIBLE : {0}\"\n  STR_WAY_POINT: \"POINT DE REPÈRE\"\n  STR_ARE_YOU_SURE_CYDONIA: \"Voulez-vous vraiment envoyer ce sous-marin en mission à T'leth?\"\n  STR_YES: \"OUI\"\n  STR_NO: \"NON\"\n  STR_SELECT_DESTINATION: \"SÉLECTIONNEZ LA DESTINATION\"\n  STR_CYDONIA: \"T'LETH\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"SÉLECTIONNEZ LE SITE POUR LA NOUVELLE BASE À CONSTRUIRE\"\n  STR_RETURN_TO_BASE: \"RETOURNER À LA BASE\"\n  STR_SELECT_NEW_TARGET: \"SÉLECTIONNER UNE NOUVELLE CIBLE\"\n  STR_PATROL: \"PATROUILLER\"\n  STR_STATUS_: \"STATUT> {ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"ENDOMMAGÉ - RETOURNE À LA BASE\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"CARBURANT BAS - RETOURNE À LA BASE\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"MISSION TERMINÉE - RETOURNE À LA BASE\"\n  STR_PATROLLING: \"EN PATROUILLE\"\n  STR_TAILING_UFO: \"POURSUIT UN OSNI\"\n  STR_INTERCEPTING_UFO: \"INTERCEPTE L'OSNI-{0}\"\n  STR_RETURNING_TO_BASE: \"RETOURNE À LA BASE\"\n  STR_DESTINATION_UC_: \"DESTINATION : {0}\"\n  STR_BASE_UC: \"BASE> {ALT}{0}\"\n  STR_SPEED_: \"VITESSE> {ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"VITESSE MAXIMUM> {ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"PROFONDEUR> {ALT}{0}\"\n  STR_AIRBORNE: \"EN VOL\"\n  STR_VERY_LOW: \"PEU PROFOND\"\n  STR_LOW_UC: \"NORMAL\"\n  STR_HIGH_UC: \"PROFOND\"\n  STR_VERY_HIGH: \"TRÈS PROFOND\"\n  STR_FUEL: \"CARBURANT> {ALT}{0}\"\n  STR_WEAPON_ONE: \"ARME-1> {ALT}{0}\"\n  STR_NONE_UC: \"RIEN\"\n  STR_ROUNDS_: \"MUNITIONS> {ALT}{0}\"\n  STR_WEAPON_TWO: \"ARME-2> {ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"SOUS-MARINS VOLANTS\"\n  STR_BASE_: \"Base> {0}\"\n  STR_NAME_UC: \"NOM\"\n  STR_AMMO_: \"MUNITIONS> {ALT}{0}\"\n  STR_CREW: \"ÉQUIPAGE\"\n  STR_EQUIPMENT_UC: \"ÉQUIPEMENT\"\n  STR_ARMOR: \"ARMURE\"\n  STR_MAX: \"MAX> {ALT}{0}\"\n  STR_ROOKIE: \"Matelot\"\n  STR_SQUADDIE: \"Matelot breveté\"\n  STR_SERGEANT: \"Enseigne\"\n  STR_CAPTAIN: \"Lieutenant\"\n  STR_COLONEL: \"Commandant\"\n  STR_COMMANDER: \"Capitaine\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Formez l'équipe pour {0}\"\n  STR_SORT_BY: \"TRIER PAR...\"\n  STR_ORIGINAL_ORDER: \"ORDRE ORIGINAL\"\n  STR_MISSIONS2: \"MISSIONS\"\n  STR_KILLS2: \"VICTIMES\"\n  STR_WOUND_RECOVERY2: \"GUÉRISON DE BLESSURE\"\n  STR_SPACE_AVAILABLE: \"ESPACE DISPONIBLE> {ALT}{0}\"\n  STR_SPACE_USED: \"ESPACE UTILISÉ> {ALT}{0}\"\n  STR_SPACE_USED_UC: \"ESPACE UTILISÉ\"\n  STR_RANK: \"GRADE\"\n  STR_WOUNDED: \"BLESSÉ\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Équipement pour {0}\"\n  STR_DEFENSE_VALUE: \"Valeur défensive\"\n  STR_HIT_RATIO: \"Ratio de tirs réussis\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}prêt à toucher{NEWLINE}le sol près de{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"Commencer la mission?\"\n  STR_SELECT_ARMAMENT: \"Sélectionnez l'armement\"\n  STR_AMMUNITION_AVAILABLE: \"MUNITIONS DISPONIBLES\"\n  STR_ARMAMENT: \"ARMEMENT\"\n  STR_NOT_AVAILABLE: \"N.D.\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"SÉLECTIONNEZ L'ARMURE POUR{NEWLINE}{ALT}{0}\"\n  STR_TYPE: \"TYPE\"\n  STR_PLASTIC_AQUA_ARMOR_UC: \"ARMURE AQUA-PLASTIQUE\"\n  STR_ION_ARMOR_UC: \"ARMURE IONIQUE\"\n  STR_MAGNETIC_ION_ARMOR_UC: \"ARMURE IONIQUE MAGNÉTIQUE\"\n  STR_PLASTIC_AQUA_ARMOR_UFOPEDIA: \"Cette armure utilise l'aqua-plastique, une nouvelle substance alien découverte, et assure à nos aquanautes d'avoir une chance dans les combats contre les incursions aliens.\"\n  STR_ION_ARMOR_UFOPEDIA: \"D'une puissante nouvelle protection pour les aquanautes, cette armure est alimentée par une source d'énergie ionique et amplifie grandement la vitesse et la force de celui ou celle qui la porte. Elle offre la meilleure protection pour les troupes de combat.\"\n  STR_MAGNETIC_ION_ARMOR_UFOPEDIA: \"Une version améliorée de l'armure ionique, incorporant la technologie de matrice magnétique pour permettre une totale liberté de mouvements en milieu aquatique.\"\n  STR_SELECT_ARMOR: \"Sélectionnez une armure\"\n  STR_NORTH: \"NORD\"\n  STR_NORTH_EAST: \"NORD-EST\"\n  STR_EAST: \"EST\"\n  STR_SOUTH_EAST: \"SUD-EST\"\n  STR_SOUTH: \"SUD\"\n  STR_SOUTH_WEST: \"SUD-OUEST\"\n  STR_WEST: \"OUEST\"\n  STR_NORTH_WEST: \"NORD-OUEST\"\n  STR_SELECT_ACTION: \"SÉLECTIONNEZ UNE ACTION\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"CONTINUER L'INTERCEPTION\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"POURSUIVRE SANS INTERCEPTION\"\n  STR_VERY_LARGE: \"TRÈS GROS\"\n  STR_LARGE: \"GROS\"\n  STR_MEDIUM_UC: \"MOYEN\"\n  STR_SMALL: \"PETIT\"\n  STR_VERY_SMALL: \"TRÈS PETIT\"\n  STR_GROUNDED: \"AU FOND\"\n  STR_DETECTED: \"Détecté\"\n  STR_SIZE_UC: \"TAILLE\"\n  STR_ALTITUDE: \"PROFONDEUR\"\n  STR_HEADING: \"CAP\"\n  STR_SPEED: \"VITESSE\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"CENTRER SUR L'OSNI - TEMPS = 5 s\"\n  STR_TRACKING_LOST: \"L'OSNI A DISPARU\"\n  STR_REDIRECT_CRAFT: \"REDIRIGER LE SOUS-MARIN\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"ALLER À SA DERNIÈRE POSITION CONNUE\"\n  STR_UFO_: \"OSNI-{0}\"\n  STR_ALIEN_BASE_: \"COLONIE ALIEN-{0}\"\n  STR_CRASH_SITE_: \"LIEU DU CRASH-{0}\"\n  STR_LANDING_SITE_: \"FOND TOUCHÉ-{0}\"\n  STR_WAY_POINT_: \"POINT DE REPÈRE-{0}\"\n  STR_TERROR_SITE: \"SITE DE TERREUR-{0}\"\n  STR_ARTIFACT_SITE: \"SITE D'ARTÉFACT-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}a atteint{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"En patrouille\"\n  STR_ALIEN_ORIGINS: \"Origines des aliens\"\n  STR_THE_ULTIMATE_THREAT: \"La menace ultime\"\n  STR_TLETH_ALIEN_CITY: \"T'leth, la ville des aliens\"\n  STR_UFOPAEDIA: \"Ovnipédie\"\n  STR_XCOM_CRAFT_ARMAMENT: \"SOUS-MARINS ET ARMES X-COM\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"SYSTÈMES D'ARMES SUBMERSIBLES\"\n  STR_WEAPONS_AND_EQUIPMENT: \"ÉQUIPEMENT GÉNÉRAL\"\n  STR_ALIEN_ARTIFACTS: \"OBJETS AQUATIQUES\"\n  STR_BASE_FACILITIES: \"INSTALLATIONS X-COM\"\n  STR_ALIEN_LIFE_FORMS: \"CRÉATURES ALIENS\"\n  STR_ALIEN_RESEARCH_UC: \"TECHNOLOGIE ALIEN\"\n  STR_UFO_COMPONENTS: \"NOUVELLES TECHNOLOGIES SUBMERSIBLES\"\n  STR_UFOS: \"OBJETS SOUS-MARINS NON IDENTIFIÉS (OSNIs)\"\n  STR_SELECT_ITEM: \"SÉLECTIONNEZ UN ARTICLE\"\n  STR_ACCELERATION: \"ACCÉLÉRATION> {ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"CAPACITÉ DE CARBURANT> {ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"NACELLES D'ARMES> {ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"CAPACITÉ DE DÉGÂTS> {ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"ESPACE DE LA SOUTE> {ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"CAPACITÉ DES SAS> {ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Dégâts\"\n  STR_RANGE: \"Portée\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Précision\"\n  STR_RE_LOAD_TIME: \"Rechargement\"\n  STR_SECONDS: \"{0} s\"\n  STR_DAMAGE_ARMOR_PIERCING: \"PERCE-ARMURE\"\n  STR_DAMAGE_INCENDIARY: \"PHOSPHOREUX\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"EXPLOSIF\"\n  STR_DAMAGE_LASER_BEAM: \"RAYON GAUSS\"\n  STR_DAMAGE_PLASMA_BEAM: \"RAYON SONIQUE\"\n  STR_DAMAGE_STUN: \"GELER\"\n  STR_DAMAGE_MELEE: \"MÊLÉE\"\n  STR_DAMAGE_ACID: \"ACIDE\"\n  STR_DAMAGE_SMOKE: \"FUMÉE\"\n  STR_SHOT_TYPE: \"TYPE\"\n  STR_ACCURACY_UC: \"PRÉCISION\"\n  STR_TIME_UNIT_COST: \"COÛT D'UT\"\n  STR_DAMAGE_UC: \"DÉGÂTS\"\n  STR_AMMO: \"MUNITIONS\"\n  STR_SHOT_TYPE_AUTO: \"Automatique\"\n  STR_SHOT_TYPE_SNAP: \"Rapide\"\n  STR_SHOT_TYPE_AIMED: \"Précis\"\n  STR_CONSTRUCTION_TIME: \"Durée de construction\"\n  STR_CONSTRUCTION_COST: \"Coût de construction\"\n  STR_MAINTENANCE_COST: \"Coût d'entretien\"\n  STR_LOW: \"Basse\"\n  STR_MEDIUM: \"Moyenne\"\n  STR_HIGH: \"Haute\"\n  STR_CRAFT_WEAPON: \"Arme de sous-marin\"\n  STR_CRAFT_AMMUNITION: \"Munitions de sous-marin\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Système d'armes lourdes\"\n  STR_WEAPON: \"Arme\"\n  STR_AMMUNITION: \"Munitions\"\n  STR_EQUIPMENT: \"Équipement\"\n  STR_ALIEN_CORPSE: \"Corps alien\"\n  STR_UFO_COMPONENT: \"Composant d'osni\"\n  STR_PERSONAL_ARMOR: \"Armure personnelle\"\n  STR_RAW_MATERIALS: \"Matières premières\"\n  STR_HWP_SOLID_HARPOON_BOLTS: \"Solides obus-harpons\"\n  STR_ALIEN: \"Alien\"\n  STR_AQUATOID: \"Aquatoïde\"\n  STR_GILLMAN: \"Homme-Poisson\"\n  STR_LOBSTERMAN: \"Homme-Homard\"\n  STR_TASOTH: \"Tasoth\"\n  STR_CALCINITE: \"Calcinite\"\n  STR_DEEP_ONE: \"Profond\"\n  STR_BIODRONE: \"Biodrone\"\n  STR_TENTACULAT: \"Tentaculat\"\n  STR_TRISCENE: \"Triscène\"\n  STR_HALLUCINOID: \"Hallucinoïde\"\n  STR_XARQUID: \"Xarquid\"\n  STR_ZOMBIE: \"Zombie\"\n  STR_LIVE_COMMANDER: \"Commandant\"\n  STR_LIVE_NAVIGATOR: \"Navigateur\"\n  STR_LIVE_MEDIC: \"Infirmier\"\n  STR_LIVE_TECHNICIAN: \"Technicien\"\n  STR_LIVE_SQUAD_LEADER: \"Leader d'escouade\"\n  STR_LIVE_SOLDIER: \"Soldat\"\n  STR_LIVE_TERRORIST: \"Terroriste\"\n  STR_AQUATOID_COMMANDER: \"Commandant Aquatoïde\"\n  STR_AQUATOID_NAVIGATOR: \"Navigateur Aquatoïde\"\n  STR_AQUATOID_MEDIC: \"Infirmier Aquatoïde\"\n  STR_AQUATOID_TECHNICIAN: \"Technicien Aquatoïde\"\n  STR_AQUATOID_SQUAD_LEADER: \"Leader d'escouade Aquatoïde\"\n  STR_AQUATOID_SOLDIER: \"Soldat Aquatoïde\"\n  STR_GILLMAN_COMMANDER: \"Commandant Homme-Poisson\"\n  STR_GILLMAN_TECHNICIAN: \"Technicien Homme-Poisson\"\n  STR_GILLMAN_SQUAD_LEADER: \"Leader d'escouade Homme-Poisson\"\n  STR_GILLMAN_SOLDIER: \"Soldat Homme-Poisson\"\n  STR_LOBSTERMAN_COMMANDER: \"Commandant Homme-Homard\"\n  STR_LOBSTERMAN_NAVIGATOR: \"Navigateur Homme-Homard\"\n  STR_LOBSTERMAN_TECHNICIAN: \"Technicien Homme-Homard\"\n  STR_LOBSTERMAN_SQUAD_LEADER: \"Leader d'escouade Homme-Homard\"\n  STR_LOBSTERMAN_SOLDIER: \"Soldat Homme-Homard\"\n  STR_TASOTH_SQUAD_LEADER: \"Leader d'escouade Tasoth\"\n  STR_TASOTH_SOLDIER: \"Soldat Tasoth\"\n  STR_CALCINITE_TERRORIST: \"Terroriste Calcinite\"\n  STR_DEEP_ONE_TERRORIST: \"Terroriste Profond\"\n  STR_BIODRONE_TERRORIST: \"Terroriste Biodrone\"\n  STR_TENTACULAT_TERRORIST: \"Terroriste Tentaculat\"\n  STR_TRISCENE_TERRORIST: \"Terroriste Triscène\"\n  STR_HALLUCINOID_TERRORIST: \"Terroriste Hallucinoïde\"\n  STR_XARQUID_TERRORIST: \"Terroriste Xarquid\"\n  STR_ION_BEAM_ACCELERATORS: \"Accélérateurs à rayon ionique\"\n  STR_MAGNETIC_NAVIGATION: \"Navigation magnétique\"\n  STR_ALIEN_SUB_CONSTRUCTION: \"Construction de sous-marin alien\"\n  STR_ALIEN_CRYOGENICS: \"Cryogénie alien\"\n  STR_ALIEN_CLONING: \"Clonage alien\"\n  STR_ALIEN_LEARNING_ARRAYS: \"Séries d'apprentissage alien\"\n  STR_ALIEN_IMPLANTER: \"Implanteur alien\"\n  STR_EXAMINATION_ROOM: \"Salle d'examen\"\n  STR_AQUA_PLASTICS: \"Aqua-plastiques\"\n  STR_ALIEN_REANIMATION_ZONE: \"Zone de réanimation alien\"\n  STR_PLASTIC_AQUA_ARMOR: \"Armure aqua-plastique\"\n  STR_ION_ARMOR: \"Armure ionique\"\n  STR_MAGNETIC_ION_ARMOR: \"Armure ionique magnétique\"\n  STR_HWP_AQUA_JET_MISSILES: \"Torpilles aqua-jet\"\n  STR_HWP_DISPLACER_PWT: \"Torpilles à ondes de choc\"\n  STR_GAUSS_TECH: \"Technologie Gauss\"\n  STR_NEW_FIGHTER_FLYING_SUB: \"Nouveau sous-marin chasseur\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Nouveau chasseur-transporteur\"\n  STR_THE_LATEST_FLYING_SUB: \"L'ultime sous-marin volant\"\n  STR_ARMOR_PIERCING: \"PERCE-ARMURE\"\n  STR_COELACANTH_GAS_CANNON: \"Canon à gaz de Cœlacanthe\"\n  STR_COELACANTH_AQUA_JET: \"Lance-torpilles de Cœlacanthe\"\n  STR_COELACANTH_GAUSS: \"Canon Gauss de Cœlacanthe\"\n  STR_DISPLACER_SONIC: \"Canon sonique de Displacer\"\n  STR_DISPLACER_PWT: \"Canon à T.O.C. de Displacer\"\n  STR_AJAX_LAUNCHER: \"Lance-torpilles Ajax\"\n  STR_DUP_HEAD_LAUNCHER: \"Lance-torpilles à tête de P.U.A.\"\n  STR_CRAFT_GAS_CANNON: \"Canon à gaz de sous-marin\"\n  STR_PWT_CANNON: \"Canon à T.O.C.\"\n  STR_GAUSS_CANNON: \"Canon Gauss\"\n  STR_GAUSS_CANNON_AMMO: \"Munitions de canon Gauss\"\n  STR_SONIC_OSCILLATOR: \"Oscillateur sonique\"\n  STR_AJAX_TORPEDOES: \"Torpilles Ajax\"\n  STR_DUP_HEAD_TORPEDOES: \"Torpilles à tête de P.U.A.\"\n  STR_CRAFT_GAS_CANNON_ROUNDS_X50: \"Cartouches de gaz (x50)\"\n  STR_SONIC_WAVE: \"Impulsion sonique\"\n  STR_PULSE_WAVE_TORPEDOES: \"Torpilles à ondes de choc\"\n  STR_SOLDIER: \"Aquanaute\"\n  STR_SCIENTIST: \"Scientifique\"\n  STR_ENGINEER: \"Technicien\"\n  STR_NORTH_ATLANTIC: \"Atlantique Nord\"\n  STR_SOUTH_ATLANTIC: \"Atlantique Sud\"\n  STR_NORTH_PACIFIC: \"Pacifique Nord\"\n  STR_SOUTH_PACIFIC: \"Pacifique Sud\"\n  STR_MEDITERRANEAN: \"Méditerranée\"\n  STR_SOUTH_CHINA_SEA: \"Mer de Chine Sud\"\n  STR_INDIAN_OCEAN: \"Océan Indien\"\n  STR_THE_EAST_SEA: \"Mer du Japon\"\n  STR_NORTH_SEA: \"Mer du Nord\"\n  STR_CARRIBEAN: \"Caraïbes\"\n  STR_ANTARCTIC: \"Antarctique\"\n  STR_ARCTIC: \"Arctique\"\n  STR_EURASIA: \"Eurasie\"\n  STR_NORTH_AMERICA: \"Amérique du Nord\"\n  STR_AFRICA: \"Afrique\"\n  STR_MAXIMUM_SPEED: \"Vitesse maximum\"\n  STR_TRANSMISSION_RESOLVER_UC: \"DÉCODEUR DE DIFFUSION\"\n  STR_TRITON: \"TRITON\"\n  STR_HAMMERHEAD: \"REQUIN-MARTEAU\"\n  STR_LEVIATHAN: \"LÉVIATHAN\"\n  STR_BARRACUDA: \"BARRACUDA\"\n  STR_MANTA: \"MANTA\"\n  STR_UFO: \"SOUS-MARIN ALIEN\"\n  STR_AJAX: \"AJAX\"\n  STR_DUP_HEAD: \"TÊTE DE P.U.A.\"\n  STR_CRAFT_GAS_CANNON_UC: \"CANON À GAZ DE S-M\"\n  STR_PWT_CANNON_UC: \"CANON À T.O.C.\"\n  STR_GAUSS_CANNON_UC: \"CANON GAUSS\"\n  STR_SONIC_OSCILLATOR_UC: \"OSCILLATEUR SONIQUE\"\n  STR_DAMAGE_CAPACITY: \"Capacité de dégâts\"\n  STR_WEAPON_POWER: \"Force d'arme\"\n  STR_WEAPON_RANGE: \"Portée de l'arme\"\n  STR_AIR_LOCK: \"Sas\"\n  STR_LABORATORY: \"Laboratoire\"\n  STR_WORKSHOP: \"Atelier\"\n  STR_STANDARD_SONAR: \"Sonar standard\"\n  STR_WIDE_ARRAY_SONAR: \"Sonar large bande\"\n  STR_TORPEDO_DEFENSES: \"Défenses à torpilles\"\n  STR_GENERAL_STORES: \"Entrepôt\"\n  STR_ALIEN_CONTAINMENT: \"Centre de détention\"\n  STR_GAUSS_DEFENSES: \"Défenses Gauss\"\n  STR_SONIC_DEFENSES: \"Défenses soniques\"\n  STR_PWT_DEFENSES: \"Défenses à T.O.C.\"\n  STR_BOMBARDMENT_SHIELD: \"Bouclier à pression\"\n  STR_MC_GENERATOR: \"Générateur de C.M.\"\n  STR_MC_LAB: \"Laboratoire de C.M.\"\n  STR_TRANSMISSION_RESOLVER: \"Décodeur de diffusion\"\n  STR_SUB_PEN: \"Abri\"\n  STR_USA: \"ÉTATS-UNIS\"\n  STR_ALASKA: \"ALASKA\"\n  STR_EU_SYNDICATE: \"EURO-SYNDICAT\"\n  STR_ARABIAN_BLOC: \"BLOC ARABE\"\n  STR_EGYPTIAN_CARTEL: \"CARTEL ÉGYPTIEN\"\n  STR_AFRICA_CORP: \"CORP. AFRICAINE\"\n  STR_BRAZILIAN_UNION: \"UNION BRÉSILIENNE\"\n  STR_NEW_MEXICO: \"NOUVEAU-MEXIQUE\"\n  STR_ASIAN_COALITION: \"COALITION D'ASIE\"\n  STR_SCANDINAVIA: \"SCANDINAVIE\"\n  STR_NEO_JAPAN: \"NÉO-JAPON\"\n  STR_FREE_CHINA: \"CHINE LIBRE\"\n  STR_AUSTRALASIA: \"AUSTRALASIE\"\n  STR_FED_KOREA: \"CORÉE FÉDÉRALE\"\n  STR_EURASIA_UC: \"EURASIE\"\n  STR_ICELANDIC_UNION: \"UNION ISLANDAISE\"\n  STR_TANK: \"Système d'armes submersibles\"\n  STR_CIVILIAN: \"Civil\"\n  STR_JAN: \"Jan\"\n  STR_FEB: \"Fév\"\n  STR_MAR: \"Mar\"\n  STR_APR: \"Avr\"\n  STR_MAY: \"Mai\"\n  STR_JUN: \"Jun\"\n  STR_JUL: \"Jui\"\n  STR_AUG: \"Aoû\"\n  STR_SEP: \"Sep\"\n  STR_OCT: \"Oct\"\n  STR_NOV: \"Nov\"\n  STR_DEC: \"Déc\"\n  STR_INTERNATIONAL_RELATIONS: \"Relations internationales\"\n  STR_COUNTRY: \"Pays\"\n  STR_FUNDING: \"Budget\"\n  STR_CHANGE: \"Écart\"\n  STR_WEAPON_SYSTEMS: \"SYSTÈMES D'ARMES\"\n  STR_HWPS: \"SAS\"\n  STR_DAMAGE_UC_: \"DÉGÂTS> {ALT}{0}\"\n  STR_AIR_LOCK_UFOPEDIA: \"Le sas permet d'entrer ou de sortir l'équipement et le personnel d'une base sous-marine. C'est toujours la première installation à être construite sur un nouveau site. Le sas est vulnérable aux intrusions de toute force hostile potentielle.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Chaque quartier d'habitation peut abriter jusqu'à 50 personnes. Ces installations sont plutôt simples et fonctionnelles.\"\n  STR_LABORATORY_UFOPEDIA: \"Un maximum de 50 scientifiques peuvent travailler dans un laboratoire. Les laboratoires sont équipés des toutes dernières technologies en matière de recherche de matériaux, de biochimie et d'armement. X-Com peut avoir accès aux meilleurs laboratoires de recherche du monde entier, qu'ils soient civils ou militaires.\"\n  STR_WORKSHOP_UFOPEDIA: \"Un atelier contient tout l'équipement nécessaire à la fabrication de produits basés sur les dernières conceptions des laboratoires scientifiques. 50 techniciens peuvent travailler dans un atelier, mais les objets en construction prennent également de la place.\"\n  STR_STANDARD_SONAR_UFOPEDIA: \"Un sonar standard a une portée sous-marine générale de plus de 450 kilomètres et est relié à des réseaux satellites géostationnaires pour les analyses en surface. Chaque scanner a 10 % de chance de détecter un submersible ou un vaisseau en vol par cycle de balayage de 30 minutes.\"\n  STR_WIDE_ARRAY_SONAR_UFOPEDIA: \"Un sonar large bande a une portée de 700 kilomètres dans toutes les profondeurs et est relié à des réseaux satellites géostationnaires pour les analyses en surface. Chaque scanner a 20 % de chance de détecter un submersible ou un vaisseau en vol par cycle de balayage de 30 minutes.\"\n  STR_TORPEDO_DEFENSES_UFOPEDIA: \"Les systèmes de défense à torpilles protègent contre les attaques des submersibles ennemis qui essaieraient de s'amarrer à la base.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"Tout l'équipement, les systèmes d'armes, les munitions, le matériel récupéré et les systèmes d'armes submersibles sont placés dans les entrepôts, y compris l'équipement destiné aux sous-marins qui sont dans les abris.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"Les aliens vivants vont nécessiter des installations particulières de détention pour les détenir. Ces unités maintiennent leurs fonctions vitales et réduisent à néant leur potentiel de combat. L'installation de détention peut contenir jusqu'à 10 formes de vie aliens dans des unités indépendantes.\"\n  STR_GAUSS_DEFENSES_UFOPEDIA: \"Les défenses Gauss fournissent la plus récente et la plus efficace protection contre les attaques de sous-marins ennemis.\"\n  STR_SONIC_DEFENSES_UFOPEDIA: \"Les défenses à oscillateur sonique fournissent une protection puissante et efficace contre les agresseurs.\"\n  STR_PWT_DEFENSES_UFOPEDIA: \"Les torpilles à ondes de choc sont la défense la plus efficace contre les attaques aliens. Ces torpilles ont des ogives très denses qui peuvent transpercer toutes les armures connues. Leurs ondes magnétiques neutralisent les défenses électroniques.\"\n  STR_BOMBARDMENT_SHIELD_UFOPEDIA: \"Le bouclier de bombardement à pression protège la base contre l'amarrage des submersibles et déclenche un champ de résonance repoussant les sous-marins attaquants assez longtemps pour permettre aux systèmes de défenses de lancer des tirs nourris. Concrètement, il double l'efficacité des systèmes de défense déjà déployés.\"\n  STR_MC_GENERATOR_UFOPEDIA: \"Les sous-marins aliens utilisent la technologie de contrôle moléculaire pour détecter la présence de créatures vivantes. À l'aide d'un émetteur de C.M. négatif, on peut créer une couverture impénétrable qui masquera notre présence et trompera les aliens.\"\n  STR_MC_LAB_UFOPEDIA: \"Le labo de contrôle moléculaire peut implanter et former jusqu'à 10 aquanautes à la fois. Les implants sont d'abord installés chirurgicalement dans le crâne des aquanautes, puis de l'entraînement intensif leur permet de les utiliser. Les compétences acquises sont utilisées avec un appareil moléculaire et peuvent être utilisées comme attaques dans les combats.\"\n  STR_TRANSMISSION_RESOLVER_UFOPEDIA: \"Les communications aliens utilisent le réseau d'implant de contrôle moléculaire qu'ils ont construit. Le décodeur de diffusion intercepte les transmissions des sous-marins aliens et décode l'information. On obtient ainsi le type de sous-marin alien, la race d'alien et le type d'activité qui s'opère.\"\n  STR_SUB_PEN_UFOPEDIA: \"Chaque abri peut contenir un sous-marin. Il y a des installations pour l'entretien, le ravitaillement et la réparation de la flotte de sous-marins X-Com. Chaque sous-marin volant posté dans une base doit avoir un abri libre qui lui est affecté et qui ne peut être utilisé par aucun autre sous-marin, même si le sous-marin affecté est parti en mission.\"\n  STR_DART_PISTOL_UFOPEDIA: \"Le pistolet à fléchettes X-Com est une petite unité précise et très puissante munie d'un chargeur creux de 12 fléchettes. Les fléchettes sont activées par une cartouche à gaz située dans la capsule de munitions.\"\n  STR_JET_HARPOON_UFOPEDIA: \"Ce fusil harpon aquatique est précis et puissant, tirant des harpons creux en acier contenus en paquets scellés de 10. Chaque harpon a son propre réservoir à gaz.\"\n  STR_GAS_CANNON_UFOPEDIA: \"Ce canon lourd de la famille des armes à gaz tire des obus solides, dont certains ont le bout explosif ou phosphoreux. L'arme favorite des aquanautes expérimentés.\"\n  STR_HYDRO_JET_CANNON_UFOPEDIA: \"Les canons hydro-jet font partie du système d'armes d'infanterie lourde. Le canon tire des mini-torpilles alimentées au magnésium. Bien que puissant, le canon hydro-jet est une arme peu maniable qui ne peut être utilisée que sous l'eau.\"\n  STR_TORPEDO_LAUNCHER_UFOPEDIA: \"Cet imposant lance-torpilles utilise 3 types de torpilles ayant chacune sa propre unité de propulsion. Le seul point faible de cette arme dévastatrice est son chargement manuel. Parmi les types de munitions, on trouve des grandes et des petites torpilles au bout explosif ou phosphoreux, toutes pour usage aquatique seulement.\"\n  STR_GAUSS_PISTOL_UFOPEDIA: \"Le pistolet Gauss utilise la technologie des particules accélérées, la dernière nouveauté dans l'armement moderne. Il est rapide, précis et fonctionne en surface, comme en profondeur. La technologie Gauss s'appuie sur les technologies plasma acquises durant la précédente guerre.\"\n  STR_GAUSS_PISTOL_CLIP_UFOPEDIA: \"Ce petit objet est utilisé comme source d'énergie pour le pistolet Gauss.\"\n  STR_GAUSS_RIFLE_UFOPEDIA: \"Supérieur au pistolet Gauss, ce fusil a vraiment du punch avec ses deux accélérateurs de particules. En remplaçant le système plasma alimenté à l'élérium, nous avons utilisé un accélérateur à micro particules qui génère un courant d'anti-protons.\"\n  STR_GAUSS_RIFLE_CLIP_UFOPEDIA: \"Ce petit objet est utilisé comme source d'énergie pour le fusil Gauss.\"\n  STR_HEAVY_GAUSS_UFOPEDIA: \"Le canon lourd Gauss est plutôt encombrant, mais extrêmement efficace. Il fonctionne avec trois accélérateurs de particules et rien ne peut pratiquement l'arrêter. Le courant anti-protons est contenu dans un obus d'arséniure de gallium qui, en implosant, libère de l'anti-matière.\"\n  STR_HEAVY_GAUSS_CLIP_UFOPEDIA: \"Ce petit objet est utilisé comme source d'énergie pour le canon lourd Gauss.\"\n  STR_MAGNA_BLAST_GRENADE_UFOPEDIA: \"Cette grenade standard a un détonateur précis et sophistiqué, permettant un contrôle de précision.\"\n  STR_DYE_GRENADE_UFOPEDIA: \"Les grenades colorantes sont des objets à double rôle, utiles pour le camouflage durant des combats exposés. Fonctionnant sous l'eau comme en surface, le colorant est éjecté en un nuage de particules, produisant le même effet qu'un jet d'encre d'une pieuvre sous l'eau ou d'une épaisse fumée en surface.\"\n  STR_PARTICLE_DISTURBANCE_GRENADE_UFOPEDIA: \"Une grenade de proximité qui peut être lancée comme une grenade ordinaire, mais qui est déclenchée par tout mouvement à proximité une fois lancée. De l'entraînement et de l'habileté sont nécessaires pour utiliser correctement ces armes.\"\n  STR_MAGNA_PACK_EXPLOSIVE_UFOPEDIA: \"Cet explosif ne devrait être utilisé que pour démolir. Cependant, des expériences ont montré que ces puissants explosifs sont parfaits pour débusquer les aliens. Son rayon d'explosion est vaste, alors assurez-vous qu'aucun aquanaute n'est directement exposé.\"\n  STR_PARTICLE_DISTURBANCE_SENSOR_UFOPEDIA: \"Ce nouvel appareil utilise toutes sortes de détecteurs et de systèmes informatiques avancés pour identifier les unités ennemies mouvantes. Cliquez sur l'icône de 'Capteur d'agitation' sur l'affichage tactique. Sélectionnez 'Utiliser le capteur' dans le menu. L'affichage du capteur montre une flèche au centre qui représente la direction vers laquelle l'aquanaute est orientée (le Nord est en haut). Les points clignotants montrent les unités qui ont récemment bougé. Les grosses unités ou les unités rapides auront des points plus gros. Les unités statiques ne seront pas détectées.\"\n  STR_MEDI_KIT_UFOPEDIA: \"Pour l'utiliser, l'agent X-Com doit faire face à un autre agent blessé ou se tenir au-dessus du corps d'un aquanaute assommé.{NEWLINE}SOIGNER> Les parties du corps en rouge représentent les blessures. Sélectionnez une partie du corps et cliquez sur le bouton 'Soigner'. La blessure grave sera soignée et la santé sera restaurée.{NEWLINE}STIMULANT> Restaure l'énergie et ranime les aquanautes assommés. L'agent doit se tenir directement sur le corps de l'aquanaute pour le ranimer.{NEWLINE}CALMANT> Restaure le moral des aquanautes blessés.\"\n  STR_MC_DISRUPTOR_UFOPEDIA: \"Le summum de la technologie en contrôle moléculaire destinée à l'usage exclusif des aquanautes spécialisés. Cliquez sur le perturbateur, sélectionnez le type d'attaque et sélectionnez une cible avec le curseur. Il existe deux types d'attaques :{NEWLINE}BROUILLER L'IMPLANT> Si l'attaque réussit, l'unité devient confuse et peut paniquer.{NEWLINE}CONTRÔLER L'IMPLANT> Si cela marche, vous prendrez le contrôle de l'unité ennemie.\"\n  STR_THERMAL_TAZER_UFOPEDIA: \"Cet appareil ne peut être utilisé qu'en combat rapproché. Il permet d'assommer un organisme vivant sans le tuer en gelant la créature.\"\n  STR_VIBRO_BLADE_UFOPEDIA: \"La vibrolame est une longue lame de couteau tranchante en titane qui tournoie d'une vitesse de rotation de 6000 tpm. Elle peut percer les armures de plongée les plus solides. Sa source d'énergie est une invention alien, nos tentatives pour reproduire cette arme ont échoué, nos lames tournant trop lentement ou explosant sous la pression.\"\n  STR_THERMIC_LANCE_UFOPEDIA: \"La lance thermique est une extension logique de la technologie de vibrolame. La lame tourne à une vitesse de rotation très élevée et une source d'énergie zrbite la surchauffe à haute température pour ainsi couper les armures, tel un couteau chaud dans du beurre.\"\n  STR_HEAVY_THERMIC_LANCE_UFOPEDIA: \"La lance thermique lourde est une version plus puissante que la lance thermique. Grâce à sa double source de chaleur et son extrême vitesse de rotation, aucun matériau ne peut résister à la lance thermique lourde.\"\n  STR_SONIC_CANNON_UFOPEDIA: \"Le canon sonique est la plus puissante des armes soniques. Son oscillateur auditif est d'une plus grande portée et sa chambre de réverbération est plus grande que celle du fusil blasta. Ce canon dispose aussi d'un système de détonation à impulsions qui modifie l'onde ultra-sonique par modulation pour créer un choc sonique bien plus efficace.\"\n  STR_CANNON_POWER_CLIP_UFOPEDIA: \"Cet appareil compact sert de munitions pour un canon sonique et contient une petite quantité de zrbite.\"\n  STR_SONIC_BLASTA_RIFLE_UFOPEDIA: \"Même l'acier enrichi en carbone ne peut résister à cette arme sonique puissante. Son émetteur d'ondes très compact est accru par un super amplificateur conducteur pour augmenter la puissance de cette arme.\"\n  STR_BLASTA_POWER_CLIP_UFOPEDIA: \"Ce petit objet sert de source d'énergie pour un fusil sonique, une puissante arme alien, et contient une petite quantité de zrbite.\"\n  STR_SONIC_PISTOL_UFOPEDIA: \"Le pistolet sonique est une arme alien basée sur des ondes auditives ultrasoniques, capable de réduire les os en purée en quelques secondes. Les ondes ultrasoniques sont d'une portée dépassant l'entendement humain.\"\n  STR_PISTOL_POWER_CLIP_UFOPEDIA: \"C'est une source d'énergie pour le compact pistolet sonique alien. Il contient du zrbite - source d'énergie de toutes les armes aliens.\"\n  STR_DISRUPTOR_PULSE_LAUNCHER_UFOPEDIA: \"Cette arme guidée alien à usage aquatique uniquement tire des 'projectiles perturbateurs' autopropulsés. Lorsque vous cliquez pour tirer, vous verrez apparaître des 'points de repère' que le projectile suivra. Lorsque vous avez positionné assez de points de repère, cliquez sur l'icône 'Tirer'.\"\n  STR_DISRUPTOR_AMMO_UFOPEDIA: \"Cet appareil est un projectile à onde perturbatrice équipé d'un système de guidage informatique. Il est tiré par le lance-projectiles perturbateurs.\"\n  STR_THERMAL_SHOK_LAUNCHER_UFOPEDIA: \"Un petit lanceur à choc thermique qui tire des bombes chimiques paralysantes. Très utile pour capturer des aliens vivants.\"\n  STR_THERMAL_SHOK_BOMB_UFOPEDIA: \"La bombe à choc thermique est utilisée pour capturer des humains vivants, mais elle peut aussi être utilisée contre la plupart des races aliens. Elle est lancée à partir d'un lance-bombes à choc thermique.\"\n  STR_SONIC_PULSER_UFOPEDIA: \"Cette arme fonctionne de la même façon qu'une grenade ordinaire - à l'exception qu'elle est extrêmement plus puissante. La grenade utilise une seule explosion à impulsion sonique qui est émise dans toutes les directions simultanément.\"\n  STR_MC_READER_UFOPEDIA: \"Nous avons trouvé des petites unités implantées à l'intérieur des corps aliens. Ce sont des implants de contrôle conçus par les Aquatoïdes pour permettre l'envoi permanent d'informations du champ de bataille, même à longue distance. Le lecteur de C.M. est un appareil de communication alien utilisé pour lire l'information directement des implants de C.M. Les unités X-Com peuvent également l'utiliser pour connaître les caractéristiques d'un alien. Sélectionnez l'option 'Utiliser le lecteur'. Puis cliquez sur un alien avec le curseur.\"\n  STR_SURVEY_SHIP: \"Navire d'inspection\"\n  STR_ESCORT: \"Escorte\"\n  STR_CRUISER: \"Croiseur\"\n  STR_HEAVY_CRUISER: \"Croiseur lourd\"\n  STR_HUNTER: \"Chasseur\"\n  STR_BATTLESHIP: \"Navire de guerre\"\n  STR_DREADNOUGHT: \"Cuirassé\"\n  STR_FLEET_SUPPLY_CRUISER: \"Croiseur de renfort\"\n  MAP_SEABED: \"Fond marin\"\n  MAP_PIPES: \"Centre de recherche\"\n  MAP_PLANE: \"Épave d'avion\"\n  MAP_ATLAN: \"Atlantide\"\n  MAP_MU: \"Temple Maya\"\n  MAP_GAL: \"Galion englouti\"\n  MAP_MSUNK: \"Paquebot englouti\"\n  MAP_VOLC: \"Volcanique\"\n  MAP_CORAL: \"Corail\"\n  MAP_PORT: \"Port\"\n  MAP_ISLAND: \"Île\"\n  MAP_CARGO: \"Cargo\"\n  MAP_LINERT: \"Navire de croisière P1\"\n  MAP_LINERB: \"Navire de croisière P2\"\n  MAP_ALART: \"Artéfact P1\"\n  MAP_GRUNGE: \"Artéfact P2\"\n  MAP_ENTRY: \"Colonie P1\"\n  MAP_A_BASE: \"Colonie P2\"\n  MAP_ALSHIP: \"T'leth P1\"\n  MAP_LEVEL: \"T'leth P2\"\n  MAP_CRYPT: \"T'leth P3\"\n  MAP_XBASES: \"Base X-Com\"\n  STR_MIXED_CREW: \"Équipage mixte\"\n  STR_MIXED_CREW_2: \"Équipage mixte 2\"\n  STR_RATING: \"ÉVALUATION> {0}\"\n  STR_RATING_TERRIBLE: \"TERRIBLE!\"\n  STR_RATING_POOR: \"MÉDIOCRE!\"\n  STR_RATING_OK: \"PASSABLE\"\n  STR_RATING_GOOD: \"BIEN!\"\n  STR_RATING_EXCELLENT: \"EXCELLENT!\"\n  STR_SCORE: \"SCORE\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"RAPPORT MENSUEL DU PROJET X-COM\"\n  STR_MONTH: \"Mois> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"Le Comité des Organisations participant au financement est dans l'ensemble satisfait de vos progrès jusqu'ici.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"Le Comité des Organisations participant au financement est très satisfait de vos excellents progrès. Continuez comme ça.\"\n  STR_COUNCIL_IS_DISSATISFIED: \"Le Comité des Organisations participant au financement n'est pas satisfait de votre travail. Vous devez améliorer votre efficacité à combattre la menace alien, sinon, il risque de mettre fin au support financer du projet X-Com.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"Vous n'avez pas réussi à combattre l'invasion alien et le Comité des Organisations participant au financement a malheureusement décidé de mettre fin au projet. Chaque organisation va s'occuper elle-même du problème comme elle l'entend. Nous ne pouvons qu'espérer arriver à un accord avec ces anciennes forces, et souhaiter que la population s'entendra avec les visiteurs aquatiques.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} est particulièrement satisfait de votre aptitude à combattre la menace localisée et est d'accord pour augmenter votre budget.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} sont particulièrement satisfaits de vos progrès dans le combat contre les incursions aliens localisées et sont d'accord pour augmenter votre budget.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} et {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} n'est pas satisfait de votre aptitude à combattre l'activité alien sur son territoire et a décidé de réduire sa participation financière.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} ne sont pas satisfaits de votre aptitude à combattre l'activité alien sur leur territoire et ont décidé de réduire leur participation financière.\"\n  STR_KNOTS: \"{0} nœuds\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} a signé un accord de coopération avec des forces aliens et a arrêté de financer X-Com.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} ont signé un accord de coopération avec des forces aliens et ont arrêté de financer X-Com.\"\n  STR_MONTHLY_RATING: \"Évaluation mensuelle> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Changement de financement> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"Le Comité n'est pas satisfait de votre situation financière. Vous devez réduire vos dettes en-dessous de 1 million $ ou X-Com cessera ses activités.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"TRANSMISSIONS À PARTICULES DÉCODÉES\"\n  STR_CRAFT_TYPE: \"TYPE DE SOUS-MARIN\"\n  STR_RACE: \"RACE\"\n  STR_MISSION: \"MISSION\"\n  STR_ZONE: \"ZONE\"\n  STR_ALLOCATE_RESEARCH: \"Allouer la recherche\"\n  STR_ALLOCATE_MANUFACTURE: \"Allouer la fabrication\"\n  STR_AZORES: \"Açores\"\n  STR_REYKJAVIK: \"Reykjavik\"\n  STR_BERMUDA: \"Bermudes\"\n  STR_NEW_YORK: \"New York\"\n  STR_BOSTON: \"Boston\"\n  STR_FORT_SEVERN: \"Fort Severn\"\n  STR_DAKAR: \"Dakar\"\n  STR_RECIFE: \"Récife\"\n  STR_ACCRA: \"Accra\"\n  STR_ASCENSION_ISLAND: \"Île de l'Ascension\"\n  STR_TRINIDADE_ISLAND: \"Trinité\"\n  STR_FALKLAND_ISLAND: \"Îles Malouines\"\n  STR_CANARY_ISLANDS: \"Îles Canaries\"\n  STR_ANCHORAGE: \"Anchorage\"\n  STR_ST_LAWRENCE_ISLAND: \"Île Saint-Laurent\"\n  STR_SAN_FRANCISCO: \"San Francisco\"\n  STR_MIDWAY_ISLAND: \"Îles Midway\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_TASMANIA: \"Tasmanie\"\n  STR_HAWAII: \"Hawaï\"\n  STR_FIJI: \"Îles Fidji\"\n  STR_TONGA: \"Tonga\"\n  STR_EASTER_ISLAND: \"Île de Pâques\"\n  STR_GALAPAGOS_ISLAND: \"Îles Galápagos\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_SOLOMON_ISLAND: \"Îles Salomon\"\n  STR_CRETE: \"Crète\"\n  STR_LISBON: \"Lisbonne\"\n  STR_PORT_SAID: \"Port-Saïd\"\n  STR_MARSEILLES: \"Marseille\"\n  STR_TRIPOLI: \"Tripoli\"\n  STR_MANILA: \"Manille\"\n  STR_HONG_KONG: \"Hong Kong\"\n  STR_SINGAPORE: \"Singapour\"\n  STR_BANGKOK: \"Bangkok\"\n  STR_DARWIN: \"Darwin\"\n  STR_BOMBAY: \"Bombay\"\n  STR_SAYCHELLES_ISLAND: \"Seychelles\"\n  STR_MALDIVE_ISLAND: \"Maldives\"\n  STR_SRI_LANKA: \"Sri Lanka\"\n  STR_MAURITIUS: \"Île Maurice\"\n  STR_TOKYO: \"Tokyo\"\n  STR_SHANGHAI: \"Shanghai\"\n  STR_VLADIVOSTOK: \"Vladivostok\"\n  STR_LONDON: \"Londres\"\n  STR_FAEROE_ISLAND: \"Îles Féroé\"\n  STR_ABERDEEN: \"Aberdeen\"\n  STR_OSLO: \"Oslo\"\n  STR_JAMAICA: \"Jamaïque\"\n  STR_PANAMA: \"Panama\"\n  STR_MIAMI: \"Miami\"\n  STR_PSI_TRAINING: \"Formation au C.M.\"\n  STR_PSIONIC_TRAINING: \"FORMATION : CONTRÔLE MOLÉCULAIRE\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Capacité restante du Labo de C.M.> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"Force{NEWLINE}au C.M.\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"Compétence{NEWLINE}/progression au C.M.\"\n  STR_IN_TRAINING: \"En{NEWLINE}formation?\"\n  STR_TARGETTED_BY: \"VISÉ PAR :\"\n  STR_WEAPONS_CREW_HWPS: \"ARMES/{NEWLINE}ÉQUIPAGE/SAS\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"est à court de carburant,{NEWLINE}retourne à la base\"\n  STR_SOLDIER_LIST: \"Liste des aquanautes\"\n  STR_RANK_: \"GRADE> {ALT}{0}\"\n  STR_MISSIONS: \"MISSIONS> {ALT}{0}\"\n  STR_KILLS: \"VICTIMES> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"GUÉRISON DE BLESSURE> {ALT}{0}\"\n  STR_TIME_UNITS: \"UNITÉS DE TEMPS\"\n  STR_STAMINA: \"ENDURANCE\"\n  STR_HEALTH: \"SANTÉ\"\n  STR_BRAVERY: \"COURAGE\"\n  STR_REACTIONS: \"RÉACTIONS\"\n  STR_FIRING_ACCURACY: \"PRÉCISION AU TIR\"\n  STR_THROWING_ACCURACY: \"PRÉCISION AU LANCER\"\n  STR_STRENGTH: \"FORCE\"\n  STR_PSIONIC_STRENGTH: \"FORCE AU C.M.\"\n  STR_PSIONIC_SKILL: \"COMPÉTENCE AU C.M.\"\n  STR_NEW_RANK: \"NOUVEAU GRADE\"\n  STR_PROMOTIONS: \"Promotions\"\n  STR_SOLDIERS_UC: \"AQUANAUTES\"\n  STR_COELACANTH_GAS_CANNON_UFOPEDIA: \"Les SAS automatisés sont très maniables et résistants. Ils fournissent le support à vos troupes à toutes les profondeurs. Si vous avez assez de munitions, ils sont automatiquement réarmés.\"\n  STR_COELACANTH_AQUA_JET_UFOPEDIA: \"Ce submersible est doté de torpilles aqua-jet. Ce système d'arme ne fonctionne que sous l'eau. Il assure l'approvisionnement des stocks en torpilles aqua-jet.\"\n  STR_COELACANTH_GAUSS_UFOPEDIA: \"La technologie Gauss renforce les SAS. Par rapport aux premiers modèles, elle offre une forte puissance de tir et utilise la technologie propre à X-Com.\"\n  STR_DISPLACER_SONIC_UFOPEDIA: \"La technologie alien a redéfini les SAS. Grâce aux déplaceurs ioniques, les SAS ne se cantonnent plus au fond des mers. L'armement sonique donne un réel avantage lors des combats.\"\n  STR_DISPLACER_PWT_UFOPEDIA: \"Ce SAS est équipé d'armes à ondes de choc pour usage aquatique. Vous devez fabriquer des T.O.C. pour les garder armés. Pour tirer, sélectionnez plusieurs 'points de repère', puis cliquez sur l'icône 'Tirer'.\"\n  STR_ALIEN_PROBE_MISSION: \"Mission d'investigation alien\"\n  STR_ALIEN_INTERDICTION: \"Interdiction alien\"\n  STR_ALIEN_RESOURCE_RAID: \"Raid de ressources aliens\"\n  STR_ALIEN_INFILTRATION: \"Infiltration alien\"\n  STR_ALIEN_BASE: \"Expansion coloniale alien\"\n  STR_ALIEN_SURFACE_ATTACK: \"Attaques aliens en surface\"\n  STR_ALIEN_RETALIATION: \"Attaque de base flottante\"\n  STR_ALIEN_SUPPLY: \"Missions de fourniture de colonie\"\n  STR_ALIEN_PROBE_MISSION_UFOPEDIA: \"La mission d'investigation alien a pour but de vérifier des données sur le fond des mers, les ressources, les voies d'accès et de transport aériens d'une zone. Les sous-marins aliens chargés de ces missions ne constituent pas de vraies menaces, mais indiquent des sites d'activité qui pourraient s'enflammer à tout moment.\"\n  STR_ALIEN_INTERDICTION_UFOPEDIA: \"La politique des aliens consiste à maintenir l'ordre des zones qui les intéressent en y envoyant un vaisseau dans le but précis de sécuriser une zone avant d'entamer des missions plus intensives. Ils atterrissent sur des sites spécifiques où ils feront ensuite des incursions pour boucler ces zones afin de préparer le terrain pour la prochain niveau d'activité.\"\n  STR_ALIEN_RESOURCE_RAID_UFOPEDIA: \"Faire couler des navires et abattre des avions font partie de la stratégie des aliens. L'acquisition de matériaux est l'une des activités principales des aliens, c'est pourquoi ils agissent de manière très agressive. Les aliens font aussi des incursions dans les zones d'activité géothermique, minant différents sites, et même des sites antiques, pour trouver des minéraux et des métaux traités ainsi que d'autres objets de construction humaine.\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"Des contacts officiels entre aliens et gouvernements ou corporations au plus haut niveau peuvent en résulter. Le point culminant de cette activité se traduit par une activité sous-marine alien intense dans les mers appartenant aux organisations concernées. Les aliens essayeront de signer un accord avec un gouvernement ou une organisation, en échange de l'enseignement de leurs technologies supérieures. Cette activité alien représente une grande menace pour X-Com. Si une corporation ou un gouvernement coopère avec les envahisseurs, il cesse automatiquement son financement.\"\n  STR_ALIEN_BASE_UFOPEDIA: \"Les aliens vont construire des colonies sous-marines secrètes dans des endroits isolés. Après quelques vols de reconnaissance, une intense activité sous-marine alien se produira pendant la construction de la colonie. On sait que ces colonies ont des laboratoires, des centres de clonage et des blocs opératoires pour des expérimentations humaines et aliens. La présence de colonies aliens va créer une intense activité alien sans la présence de sous-marins aliens. Afin de localiser une colonie, un sous-marin X-Com doit patrouiller dans une région pendant quelques heures pour avoir une chance de la détecter.\"\n  STR_ALIEN_SURFACE_ATTACK_UFOPEDIA: \"Lorsque les aliens ont besoin d'humains, ils terrorisent un port, attaquent une île, ou un navire. Les civils seront la première cible des besoins pervers de reproduction des aliens et de leurs horribles expériences.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"Si les sous-marins d'interception X-Com réussissent particulièrement bien à abattre des vaisseaux aliens, alors ils pourraient commettre des actions de représailles. Cela pourrait aboutir à une attaque directe contre une base X-Com. Cependant, les aliens doivent trouver cette base avant de l'attaquer, et tant que les sous-marins aliens sont tenus à l'écart, il y a peu de risque d'une attaque.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"Une fois qu'une colonie alien est construite, elle est régulièrement approvisionnée par un navire de ravitaillement spécial. Si l'un de ces vaisseaux est détecté alors qu'il touche le fond, vous pouvez alors être certain qu'il y a une base alien à proximité.\"\n  STR_SURVEY_SHIP_UFOPEDIA: \"Ce minuscule sous-marin est utilisé essentiellement pour les missions de reconnaissance et d'inspection. Il précède normalement des vaisseaux plus grands au début d'une expédition alien.\"\n  STR_ESCORT_UFOPEDIA: \"Un vaisseau escorte de taille moyenne qui ne représente pas une grande menace. Il précède l'arrivé de vaisseaux plus grands et de l'intensification des activités.\"\n  STR_CRUISER_UFOPEDIA: \"Le croiseur est un vaisseau utilisé dans tous les types de missions aliens. Il est le fer de lance de la flotte alien et est un redoutable adversaire.\"\n  STR_HEAVY_CRUISER_UFOPEDIA: \"Le croiseur lourd est muni de systèmes d'armes et de propulseurs plus importants et plus puissants que le croiseur. Il est utilisé pour transporter de grandes quantités de minéraux et d'équipement.\"\n  STR_HUNTER_UFOPEDIA: \"Ce vaisseau est équipé d'une salle d'examen utilisée pour des expériences et des opérations sur des sujets humains. Les victimes sont sujets à des tortures les plus atroces et on leur enlève souvent le cerveau qui est stocké avant d'être, en route, soumis à des expériences.\"\n  STR_BATTLESHIP_UFOPEDIA: \"Ce navire de guerre est le vaisseau le plus agressif de la flotte alien. Il dispose de toutes les technologies et systèmes aliens pour servir de base d'opérations à tous les actes d'agression des aliens et dispose aussi d'un vaste arsenal d'armes.\"\n  STR_DREADNOUGHT_UFOPEDIA: \"Le cuirassé est un super transporteur de troupes, équipé de toutes les technologies aliens et d'un puissant arsenal. C'est un adversaire rude et redoutable.\"\n  STR_FLEET_SUPPLY_CRUISER_UFOPEDIA: \"Le vaisseau de ravitaillement est utilisé durant la construction de colonies aliens ou pour l'approvisionnement de colonies existantes. Il transporte des nutriments aliens, de l'ADN, des fœtus et d'autres composants biologiques.\"\n  STR_DISMANTLE: \"Démonter\"\n  STR_FACILITY_IN_USE: \"NACELLE AQUATIQUE EN UTILISATION\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"IMPOSSIBLE DE DÉMONTER LA NACELLE AQUATIQUE!{SMALLLINE}Toutes les nacelles de la base doivent être reliées au sas.\"\n  STR_TRANSFER_ITEMS_TO: \"Transférer les objets vers {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"PAS DE CENTRE DE DÉTENTION DES ALIENS POUR LE TRANSFERT!{SMALLLINE}Les aliens vivants ont besoin d'une installation de centre de détention des aliens pour survivre.\"\n  STR_AMOUNT_AT_DESTINATION: \"QUANTITÉ À{NEWLINE}DESTINATION\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"L'alien meurt car il n'y a pas d'installation de centre de détention des aliens.\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"AUCUN LOGEMENT DE LIBRE!{SMALLLINE}La base de destination n'a pas assez de place dans les quartiers d'habitation pour l'équipage affecté au sous-marin.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"PAS ASSEZ D'ESPACE DE STOCKAGE!{SMALLLINE}La base de destination n'a pas assez de place dans les entrepôts pour l'équipement attribué au sous-marin.\"\n  STR_ITEMS_ARRIVING: \"Le matériel arrive\"\n  STR_DESTINATION_UC: \"DESTINATION\"\n  STR_DART_PISTOL: \"Pistolet à fléchettes\"\n  STR_DART_POD: \"Chargeur de fléchettes\"\n  STR_JET_HARPOON: \"Fusil harpon\"\n  STR_HARPOON_POD: \"Chargeur de harpons\"\n  STR_GAS_CANNON: \"Canon à gaz\"\n  STR_GC_AP_AMMO: \"Obus CG-PA\"\n  STR_GC_HE_AMMO: \"Obus CG-E\"\n  STR_GC_P_AMMO: \"Obus CG-P\"\n  STR_HYDRO_JET_CANNON: \"Canon hydro-jet\"\n  STR_HJC_AP_AMMO: \"Munitions HJ-PA\"\n  STR_HJC_HE_AMMO: \"Munitions HJ-E\"\n  STR_HJC_P_AMMO: \"Munitions HJ-P\"\n  STR_TORPEDO_LAUNCHER: \"Lance-torpilles\"\n  STR_SMALL_TORPEDO: \"Petite torpille\"\n  STR_LARGE_TORPEDO: \"Grande torpille\"\n  STR_PHOSPHOROUS_TORPEDO: \"Torpille phosphoreuse\"\n  STR_MAGNA_BLAST_GRENADE: \"Grenade magna-blast\"\n  STR_DYE_GRENADE: \"Grenade colorante\"\n  STR_PARTICLE_DISTURBANCE_GRENADE: \"Grenade agitatrice de particules\"\n  STR_MAGNA_PACK_EXPLOSIVE: \"Explosif magna-pack\"\n  STR_PARTICLE_DISTURBANCE_SENSOR: \"Capteur d'agitation de particules\"\n  STR_MEDI_KIT: \"Trousse de soins\"\n  STR_MC_DISRUPTOR: \"Perturbateur de C.M.\"\n  STR_THERMAL_TAZER: \"Tazer thermique\"\n  STR_GAUSS_PISTOL: \"Pistolet Gauss\"\n  STR_GAUSS_PISTOL_CLIP: \"Chargeur de pistolet Gauss\"\n  STR_GAUSS_RIFLE: \"Fusil Gauss\"\n  STR_GAUSS_RIFLE_CLIP: \"Chargeur de fusil Gauss\"\n  STR_HEAVY_GAUSS: \"Canon lourd Gauss\"\n  STR_HEAVY_GAUSS_CLIP: \"Chargeur de canon lourd Gauss\"\n  STR_SONIC_CANNON: \"Canon sonique\"\n  STR_CANNON_POWER_CLIP: \"Chargeur de canon sonique\"\n  STR_SONIC_BLASTA_RIFLE: \"Fusil blasta-sonique\"\n  STR_BLASTA_POWER_CLIP: \"Chargeur d'énergie blasta\"\n  STR_SONIC_PISTOL: \"Pistolet sonique\"\n  STR_PISTOL_POWER_CLIP: \"Chargeur de pistolet sonique\"\n  STR_DISRUPTOR_PULSE_LAUNCHER: \"Lance-projectiles perturbateurs\"\n  STR_DISRUPTOR_AMMO: \"Projectile à onde perturbatrice\"\n  STR_THERMAL_SHOK_LAUNCHER: \"Lance-bombes à choc thermique\"\n  STR_THERMAL_SHOK_BOMB: \"Bombe à choc thermique\"\n  STR_SONIC_PULSER: \"Émetteur d'impulsion sonique\"\n  STR_ZRBITE: \"Zrbite\"\n  STR_MC_READER: \"Lecteur de C.M.\"\n  STR_VIBRO_BLADE: \"Vibrolame\"\n  STR_THERMIC_LANCE: \"Lance thermique\"\n  STR_HEAVY_THERMIC_LANCE: \"Lance thermique lourde\"\n  STR_AQUATOID_CORPSE: \"Corps d'Aquatoïde\"\n  STR_GILLMAN_CORPSE: \"Corps d'Homme-Poisson\"\n  STR_LOBSTERMAN_CORPSE: \"Corps d'Homme-Homard\"\n  STR_TASOTH_CORPSE: \"Corps de Tasoth\"\n  STR_CALCINITE_CORPSE: \"Corps de Calcinite\"\n  STR_DEEP_ONE_CORPSE: \"Corps de Profond\"\n  STR_BIODRONE_CORPSE: \"Corps de Biodrone\"\n  STR_TENTACULAT_CORPSE: \"Corps de Tentaculat\"\n  STR_TRISCENE_CORPSE: \"Corps de Triscène\"\n  STR_HALLUCINOID_CORPSE: \"Corps d'Hallucinoïde\"\n  STR_XARQUID_CORPSE: \"Corps de Xarquid\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"Pas assez de munitions pour armer le SAS{SMALLLINE}Chaque SAS requiert {0} {1}.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Pas assez d'équipement pour rééquiper entièrement l'escouade\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Vous aurez besoin d'étudier{NEWLINE}{0}{NEWLINE}afin de pouvoir produire{NEWLINE}{1}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"Les aliens ont détruit la base {0} non défendue\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"Les patrouilles X-Com ont localisé une colonie alien en {0}\"\n  STR_STANDOFF: \"RESTER À DISTANCE\"\n  STR_CAUTIOUS_ATTACK: \"ATTAQUE PRUDENTE\"\n  STR_STANDARD_ATTACK: \"ATTAQUE STANDARD\"\n  STR_AGGRESSIVE_ATTACK: \"ATTAQUE AGRESSIVE\"\n  STR_DISENGAGING: \"DÉSENGAGEMENT\"\n  STR_UFO_HIT: \"L'OSNI EST TOUCHÉ!\"\n  STR_UFO_CRASH_LANDS: \"L'OSNI A COULÉ!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Réduire à une distance sûre seulement\"\n  STR_UFO_RETURN_FIRE: \"L'OSNI RIPOSTE!\"\n  STR_INTERCEPTOR_DAMAGED: \">>> SOUS-MARIN ENDOMMAGÉ <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> SOUS-MARIN DÉTRUIT <<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"L'OSNI S'ÉCHAPPE!\"\n  STR_LONG_RANGE_DETECTION: \"Sonar large bande\"\n  STR_STORES_UC: \"STOCKS\"\n  STR_DIFFICULTY_LEVEL: \"Niveau de difficulté\"\n  STR_INTERCEPT: \"INTERCEPTER\"\n  STR_BASES: \"BASES\"\n  STR_GRAPHS: \"GRAPHIQUES\"\n  STR_UFOPAEDIA_UC: \"OVNIPÉDIE\"\n  STR_OPTIONS_UC: \"OPTIONS\"\n  STR_FUNDING_UC: \"BUDGET\"\n  STR_5_SECONDS: \"5 s\"\n  STR_1_MINUTE: \"1 min\"\n  STR_5_MINUTES: \"5 min\"\n  STR_30_MINUTES: \"30 min\"\n  STR_1_HOUR: \"1 heure\"\n  STR_1_DAY: \"1 jour\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"Tableau de performance X-Com\"\n  STR_ENTER_NAME: \"Entrez un nom\"\n  STR_PERFORMANCE_RATING: \"Évaluation de performance\"\n  STR_VICTORY_DATE: \"Date de victoire\"\n  STR_CHEMICAL_FLARE: \"Torche chimique\"\n  STR_CHEMICAL_FLARE_UFOPEDIA: \"Cet appareil compact produit une lumière vive sur la terre ou sous l'eau, peu importe la profondeur, permettant d'illuminer les unités ennemies à proximité durant les missions abyssales ou nocturnes.\"\n  STR_MONTHLY_COSTS: \"Coûts mensuels\"\n  STR_CRAFT_RENTAL: \"Location de sous-marins\"\n  STR_SALARIES: \"Salaires\"\n  STR_BASE_MAINTENANCE: \"Entretien de la base\"\n  STR_COST_PER_UNIT: \"Coût par unité\"\n  STR_QUANTITY: \"Quantité\"\n  STR_TOTAL: \"Total\"\n  STR_IN_PSIONIC_TRAINING: \"En implantation de C.M.\"\n  STR_FRONT_ARMOR: \"Armure avant\"\n  STR_LEFT_ARMOR: \"Armure gauche\"\n  STR_RIGHT_ARMOR: \"Armure droite\"\n  STR_REAR_ARMOR: \"Armure arrière\"\n  STR_UNDER_ARMOR: \"Armure de dessous\"\n  STR_ROUNDS: \"Munitions\"\n  STR_UNIT: \"UNITÉ> {0}\"\n  STR_ENERGY: \"ÉNERGIE\"\n  STR_MORALE: \"MORAL\"\n  STR_ARMOR_: \"ARMURE> {0}\"\n  STR_FRONT_ARMOR_UC: \"ARMURE AVANT\"\n  STR_LEFT_ARMOR_UC: \"ARMURE GAUCHE\"\n  STR_RIGHT_ARMOR_UC: \"ARMURE DROITE\"\n  STR_REAR_ARMOR_UC: \"ARMURE ARRIÈRE\"\n  STR_SKILLS: \"COMPÉTENCES> {0}\"\n  STR_LEVEL: \"NIVEAU> {0}\"\n  STR_HEAD: \"TÊTE\"\n  STR_TORSO: \"TORSE\"\n  STR_RIGHT_ARM: \"BRAS DROIT\"\n  STR_LEFT_ARM: \"BRAS GAUCHE\"\n  STR_RIGHT_LEG: \"JAMBE DROITE\"\n  STR_LEFT_LEG: \"JAMBE GAUCHE\"\n  STR_PAIN_KILLER: \"CALMANT\"\n  STR_STIMULANT: \"STIMULANT\"\n  STR_HEAL: \"SOIGNER\"\n  STR_TIME_UNITS_SHORT: \"UT> {ALT}{0}\"\n  STR_WEIGHT: \"Poids> {ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"Réact> {ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Objet alien\"\n  STR_AMMO_ROUNDS_LEFT: \"MUNITIONS{NEWLINE}RESTANTES{NEWLINE}{ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Calm> {ALT}{0}{ALT}{NEWLINE}Stim> {ALT}{1}{ALT}{NEWLINE}Soin> {ALT}{2}\"\n  STR_THROW: \"Lancer\"\n  STR_AUTO_SHOT: \"Tir auto.\"\n  STR_SNAP_SHOT: \"Tir rapide\"\n  STR_AIMED_SHOT: \"Tir précis\"\n  STR_STUN: \"Geler\"\n  STR_PRIME_GRENADE: \"Amorcer la grenade\"\n  STR_USE_SCANNER: \"Utiliser le capteur\"\n  STR_USE_MEDI_KIT: \"Utiliser la trousse\"\n  STR_LAUNCH_MISSILE: \"Tirer\"\n  STR_ACCURACY_SHORT: \"Pr> {ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Pas assez d'unités de temps!\"\n  STR_NOT_ENOUGH_ENERGY: \"Pas assez d'énergie!\"\n  STR_NO_ROUNDS_LEFT: \"Plus de munitions!\"\n  STR_NO_AMMUNITION_LOADED: \"Pas de munitions de chargées!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Mauvais type de munition pour cette arme!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"L'arme est déjà chargée!\"\n  STR_NO_LINE_OF_FIRE: \"Pas de ligne de tir!\"\n  STR_GRENADE_IS_ACTIVATED: \"La grenade est activée!\"\n  STR_GRENADE_IS_DEACTIVATED: \"La grenade est désactivée!\"\n  STR_THERE_IS_NO_ONE_THERE: \"Il n'y a personne ici!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Impossible d'utiliser l'objet alien avant son étude!\"\n  STR_OUT_OF_RANGE: \"Hors de portée!\"\n  STR_UNABLE_TO_THROW_HERE: \"Impossible de lancer à cet endroit!\"\n  STR_SET_TIMER: \"Détonateur\"\n  STR_HIDDEN_MOVEMENT: \"MOUVEMENTS CACHÉS\"\n  STR_TURN: \"TOUR> {0}\"\n  STR_SIDE: \"CAMP> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Cliquez pour continuer\"\n  STR_MIND_CONTROL: \"Contrôler l'implant\"\n  STR_PANIC_UNIT: \"Brouiller l'implant\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Attaque d'implant réussie\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Contrôle d'implant réussi\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}est devenu fou furieux\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}est devenue folle furieuse\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}panique et s'affole\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}panique et s'affole\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Aliens\"\n  STR_RIGHT_HAND: \"MAIN DROITE\"\n  STR_LEFT_HAND: \"MAIN GAUCHE\"\n  STR_RIGHT_SHOULDER: \"ÉPAULE DROITE\"\n  STR_LEFT_SHOULDER: \"ÉPAULE GAUCHE\"\n  STR_BACK_PACK: \"SAC À DOS\"\n  STR_BELT: \"CEINTURE\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}est sous contrôle moléculaire\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}est sous contrôle moléculaire\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}a perdu connaissance\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}a perdu connaissance\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}est mort d'une blessure mortelle\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}est morte d'une blessure mortelle\"\n  STR_USE_MIND_PROBE: \"Utiliser le lecteur\"\n  STR_FATAL_WOUNDS: \"BLESSURES MORTELLES\"\n  STR_UNDER_ARMOR_UC: \"ARMURE DE DESSOUS\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Unités de temps réservées au tir rapide\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Unités de temps réservées au tir automatique\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Unités de temps réservées au tir précis\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Unités de temps réservées pour s'agenouiller\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"Unités de temps réservées pour tirer à genoux\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} unité dans le sous-marin X-Com\"\n    many: \"{N} unités dans le sous-marin X-Com\"\n    other: \"{N} unités dans le sous-marin X-Com\"\n  STR_UNITS_OUTSIDE:\n    one: \"{N} unité laissée dehors\"\n    many: \"{N} unités laissées dehors\"\n    other: \"{N} unités laissées dehors\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} unité à l'entrée\"\n    many: \"{N} unités à l'entrée\"\n    other: \"{N} unités à l'entrée\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} unité à la sortie cible\"\n    many: \"{N} unités à la sortie cible\"\n    other: \"{N} unités à la sortie cible\"\n  STR_ABORT_MISSION_QUESTION: \"Abandonner la mission?\"\n  STR_CORPSE: \"Corps\"\n  STR_UNLOAD_CRAFT: \"Décharger\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}a été tué\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}a été tuée\"\n  STR_HIT_MELEE: \"Frapper\"\n  STR_GROUND: \"SOL\"\n  STR_LIVING_QUARTERS_PLURAL: \"Quartiers d'habitation\"\n  STR_LIST_ITEM: \"OBJET\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"Tous les aliens sont morts lors du crash sous-marin.{NEWLINE}Procédure de récupération automatique activée\"\n  STR_RESET: \"Réinitialiser\"\n  STR_MEMORIAL: \"Mémorial\"\n  STR_DATE_UC: \"DATE\"\n  STR_SOLDIERS_RECRUITED_UC: \"AQUANAUTES RECRUTÉS> {ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"AQUANAUTES PERDUS> {ALT}{0}\"\n  STR_REMOVE_SELECTED: \"Enlever ceux sélectionnés\"\n  STR_LIVE_ALIENS: \"Spécimens{NEWLINE}vivants\"\n  STR_DEAD_ALIENS: \"Spécimens{NEWLINE}rejetés\"\n  STR_UNDER_INTERROGATION: \"En cours{NEWLINE}d'interrogation\"\n  STR_CONTAINMENT_EXCEEDED: \"LIMITES DE DÉTENTION D'ALIENS EXCÉDÉES!{SMALLLINE}Pas assez d'espace de détention à {0}. Vous devez enlever l'excès d'aliens de la détention (qui mourront ensuite).\"\n  STR_MANAGE_CONTAINMENT: \"Gestion de la détention des aliens\"\n  STR_STORAGE_EXCEEDED: \"ESPACE DE STOCKAGE EXCÉDÉE!{SMALLLINE}Pas assez d'espace de stockage à {0}. Vous devez vendre l'excès de matériel.\"\n  STR_GO_TO_BASE: \"Aller à la base\"\n  STR_MELEE_ACCURACY: \"PRÉCISION EN MÊLÉE\"\n  STR_SELL_PRODUCTION: \"VENDRE\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Les deux mains doivent être vides!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Pas assez d'objets pour copier le modèle!\"\n  STR_UNLOAD_WEAPON: \"Décharger l'arme\"\n  STR_ALL_ITEMS: \"Tous les objets\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"AUCUN ÉQUIPEMENT DE PLUS N'EST AUTORISÉ À BORD !{SMALLLINE}Vous êtes uniquement autorisé de transporter un maximum d'{N} objet sur ce sous-marin.\"\n    many: \"AUCUN ÉQUIPEMENT DE PLUS N'EST AUTORISÉ À BORD!{SMALLLINE}Vous êtes uniquement autorisé de transporter un maximum de {N} objets sur ce sous-marin.\"\n    other: \"AUCUN ÉQUIPEMENT DE PLUS N'EST AUTORISÉ À BORD!{SMALLLINE}Vous êtes uniquement autorisé de transporter un maximum de {N} objets sur ce sous-marin.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}CENTRE DE CONTRÔLE DÉTRUIT{NEWLINE}Retournez à l'entrée et abandonnez la mission.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"Les installations aquatiques X-Com ne peuvent pas être construites sur la terre\"\n  STR_UNABLE_TO_ENGAGE_DEPTH: \"IMPOSSIBLE D'ATTAQUER L'ENNEMI{NEWLINE}À CETTE PROFONDEUR\"\n  STR_UNABLE_TO_ENGAGE_AIRBORNE: \"IMPOSSIBLE D'ATTAQUER L'ENNEMI{NEWLINE}EN VOL\"\n  STR_UNDERWATER_EQUIPMENT: \"Cet équipement ne fonctionne que sous l'eau!\"\n  STR_LAND_EQUIPMENT: \"Cet équipement ne fonctionne qu'à la surface!\"\n  STR_LEVEL_SHORT: \"N{0}\"\n  STR_PERSONNEL: \"Personnel\"\n  STR_CRAFT_ARMAMENT: \"Sous-marins/armement\"\n  STR_COMPONENTS: \"Composants\"\n  STR_SOLDIERS_RECRUITED: \"Aquanautes recrutés\"\n  STR_SOLDIERS_LOST: \"Aquanautes perdus\"\n  STR_TOTAL_UFOS: \"Sous-marins aliens détectés\"\n  STR_TOTAL_ALIEN_BASES: \"Colonies aliens découvertes\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"FCM\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"CCM\"\n  FEMALE_CIVILIAN: \"Civile\"\n  MALE_CIVILIAN: \"Civil\"\n  DOCKER_CIVILIAN: \"Civil, docker\"\n  SAILOR_CIVILIAN: \"Civil, marin\"\n  STR_BIODRONE_MELEE_WEAPON: \"Arme de mêlée de Biodrone\"\n  HALLUCINOID_WEAPON: \"Arme d'Hallucinoïde\"\n  STR_LOBSTERMAN_MELEE_WEAPON: \"Arme de mêlée d'Homme-Homard\"\n  CALCINITE_WEAPON: \"Arme de Calcinite\"\n  DEEP_ONE_WEAPON: \"Arme de Profond\"\n  STR_TRISCENE_MELEE_WEAPON: \"Arme de Triscène\"\n  STR_TRIBIO_SONIC_WEAPON: \"Arme sonique alien\"\n  XARQUID_WEAPON: \"Arme de Xarquid\"\n  TENTACULAT_WEAPON: \"Arme de Tentaculat\"\n  ZOMBIE_WEAPON: \"Arme de Zombie\"\n  ALIEN_PSI_WEAPON: \"Arme de C.M. alien\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/fr.yml",
    "content": "fr:\n  STR_LEVIATHAN_UFOPEDIA: \"SUBMERSIBLE DE TRANSPORT ET D'INTERCEPTION VOLANT, CAPABLE D'ATTEINDRE DES PROFONDEURS EXTRÊMES. UNE SYNTHÈSE EXEMPLAIRE DE TECHNOLOGIE HUMAINE ET ALIEN, UTILISANT UN SYSTÈME DE PROPULSION IONIQUE ET UNE NAVIGATION PAR CHAINE MAGNÉTIQUE.\"\n  STR_BARRACUDA_UFOPEDIA: \"LE 'BRITISH HYDROSPACE BARRACUDA', ALIMENTÉ EN ÉNERGIE PAR DES MOTEURS A LASER SUR-CHAUFFÉS. L'UN DES INTERCEPTEURS LES PLUS RAPIDES AU MONDE, AVEC CAPACITÉS SUBMERSIBLES ET VOLS ATMOSPHÉRIQUE, UN ATOUT CLÉ POUR LA BATAILLE A VENIR.\"\n  STR_HAMMERHEAD_UFOPEDIA: \"UN VAISSEAU DE TRANSPORT ET D'INTERCEPTION. UNE REPRODUCTION DES SYSTÈMES DE CHAINES MAGNÉTIQUES DANS UN VAISSEAU DE X-COM. MALGRÉ SA PETITE TAILLE, SA CONCEPTION EST UNE INCROYABLE PERFORMANCE TECHNIQUE.\"\n  STR_TRITON_UFOPEDIA: \"LE TRITON EST UN TRANSPORTEUR D'ESCOUADES D'ASSAUT, ÉQUIPÉ DE MOTEURS AUX PLEINES CAPACITÉS DE VOL AQUATIQUES ET ATMOSPHÉRIQUES. SA GRANDE CAPACITÉ DE STOCKAGE ET SA CONSTRUCTION ROBUSTE EN FONT UN DES PILIERS DE LA FLOTTE X-COM.\"\n  STR_MANTA_UFOPEDIA: \"LE MANTA EST UN SUBMERSIBLE MONOPLACE A GRANDE VITESSE ALIMENTÉ PAR DES GÉNÉRATEURS A IONS SEMBLABLES A CEUX DES VAISSEAUX ALIENS. UN VAISSEAU D'ATTAQUE TRÈS EFFICACE DANS CE CONFLIT GRANDISSANT.\"\n  STR_AJAX_UFOPEDIA: \"LA TORPILLE AJAX EST L'ARME STANDARD POUR LE COMBAT SOUS-MARIN DANS LE MONDE ENTIER. SA PUISSANCE ET SA PRÉCISION EN FONT UNE EXCELLENTE ARME DE DISSUASION.\"\n  STR_DUP_HEAD_UFOPEDIA: \"LA TECHNOLOGIE DES ARMES AVEC TÊTES EN URANIUM APPAUVRIS -TUA- EST RELATIVEMENT RÉCENTE ET CETTE ARME AQUATIQUE EST LA PREMIÈRE APPLICATION COMMERCIAL A L'EXPLOITER COMPLÉTEMENT.\"\n  STR_CRAFT_GAS_CANNON_UFOPEDIA: \"UN SYSTÈME DE CANON A GAZ PRESSURISÉS ÉJECTANT DE SOLIDES CARREAUX CAPABLES DE PÉNÉTRER LES BLINDAGES.\"\n  STR_PWT_CANNON_UFOPEDIA: \"LA TORPILLE A ONDES DE PERTURBATIONS UTILISE UN SYSTÈME DE PROPULSION AU CARBURATION SURCHAUFFÉ ET UNE OGIVE EXTRÊMEMENT DENSE QUI PEUT ENFONCER LA PLUPART DES ALLIAGES.\"\n  STR_GAUSS_CANNON_UFOPEDIA: \"LA NOUVELLE TECHNOLOGIE D'ARMEMENT GAUSS DÉVELOPPÉ PAR X-COM EST BASÉ SUR LE PRINCIPE DE L'ACCÉLÉRATION DES PARTICULES. L’ÉNERGIE REQUISE EST OBTENU PAR UN RÉACTEUR A FUSION COMPACTE, REFROIDI PAR DE L'AZOTE LIQUIDE.\"\n  STR_SONIC_OSCILLATOR_UFOPEDIA: \"UN PUISSANT OSCILLATEUR AUDITIF QUI GÉNÈRE DES VAGUES SONIQUES CAPABLES DE DÉTRUIRE DES CIBLES EN PERTURBANT LEUR STRUCTURE MOLÉCULAIRE.\"\n  STR_AQUATOID_UFOPEDIA: \"La race des Aquatoïdes est une société ancienne qui a existé plusieurs millénaires avant que l'homme ne pose le pied sur le monde. Leur forme compacte et leur tête hypertrophiée sont un héritage de leurs cousins venus de l'espace, les Sectoïdes. Leur force provient de la puissante technologie de Contrôle Moléculaire. Les Aquatoïdes cherchent à propager leur race stérile par les modifications génétiques, les sujets de test idéaux étant les êtres humains. Ces expériences sont à l'origine de nombreuses races hybrides.\"\n  STR_AQUATOID_AUTOPSY: \"Autopsie de l'Aquatoïde\"\n  STR_AQUATOID_AUTOPSY_UFOPEDIA: \"Une analyse détaillée de cette créature nous permet d'émettre quelques hypothèses. Il s'agit d'un Sectoïde, nos anciens ennemis, mais transformés par des opérations chirurgicales et des implants pour devenir une créature aquatique. Des poumons atrophiés permettent de respirer de l'air et d'avoir une mobilité limitée à la surface. Il y a des implants cybernétiques dans tout le corps qui améliorent la force de ses membres atrophiés et le fonctionnement de ses organes. Comme tous les membres de cette race sont identiques, on peut émettre l'hypothèse que ces créatures sont des clones.\"\n  STR_GILLMAN_UFOPEDIA: \"Presque humaine, une créature étrange qui apparait sous les traits d'un reptile humanoïde, plus proche de l'humain que du reptile. Cette créature est extrêmement puissance et rapide dans le monde sous-marin. Les hommes-poissons, sont une race à part entière qui comporte des spécimens mâle et femelle appartenant d'âge variable. Ils sont différent de la majorité des aliens aquatiques de par leur absence d'altérations génétiques ou d'opérations chirurgicales. Il est possible que nous ayons devant les yeux un antique chaînon de notre propre espèce.\"\n  STR_GILLMAN_AUTOPSY: \"Autopsie d'homme-poisson\"\n  STR_GILLMAN_AUTOPSY_UFOPEDIA: \"Dès que nous avons commencé la dissection de cette créature, il est devenu clair qu'il ne s'agit pas d'un alien, mais d'une créature native de la Terre, une antique race préhistorique que l'on pensait éteinte lorsque les mammifères sont devenus l'espèce dominante. Alors que les dinosaures arpentaient le monde, les hommes-poissons vivaient au grand jour : amphibiens, intelligents et puissants. Le cataclysme qui mit fin au règne reptilien sur cette planète les a forcés à établir une liaison symbiotique avec les nouveaux arrivants aliens. De petits appareils électroniques sont logés dans leurs crânes.\"\n  STR_LOBSTERMAN_UFOPEDIA: \"C'est une créature chancelante plus grande qu'un homme et comportant 6 membres, on dirait un Démon aquatique. Les similitudes entre cette créature et les homards Terriens lui ont valut de se voir affublé du surnom d'Homme-Homard par les troupes d'X-Com. C'est un béhémoth des profondeurs, une créature soigneusement conçue pour le combat avec une force incroyable et pratiquement invulnérable aux tirs de missiles ou de torpilles. Ses pinces peuvent à elles seules broyer l'acier.\"\n  STR_LOBSTERMAN_AUTOPSY: \"Autopsie de l'Homme-Homard\"\n  STR_LOBSTERMAN_AUTOPSY_UFOPEDIA: \"Une fois passé la carapace virtuellement indestructible de la créature, on remarque une stupéfiante construction. Des muscles puissants fixés sur un squelette en titane, un système de visée sophistiqué avec capacité de balayage multi-bandes est fixé directement dans le cerveau de la créature. Ses yeux multiples sont protégés pas des plastiques plus résistants que l'acier et il est clair que quand ils sont bien déployés par leur maitres, ils sont complètement inarrêtables. Enfouis profondément dans son corps se trouvent des appareils de construction et de fonction inconnues.\"\n  STR_TASOTH_UFOPEDIA: \"Ces ennemis rapides et agiles sont un pilier de l'armée Alienne. Des centaines sont mis au monde dans de vastes chambres de reproduction au plus profond des colonies Aliennes. Bien plus puissant qu'un homme, le Tasoth est un véritable Alien, son comportement et sa nature carnivore n'ont pas d'égal sur la planète. Le Tasoth forme souvent le fer de lance d'une attaque Alienne et ne semble jamais se résigner, même quand les chances sont contre lui.\"\n  STR_TASOTH_AUTOPSY: \"Autopsie du Tasoth\"\n  STR_TASOTH_AUTOPSY_UFOPEDIA: \"La dissection révèle un organisme cybernétique animé par un pouvoir étrange. A l'intérieur du corps on trouve une cavité avec une petite unité de puissance, mais aucun organe reconnaissable. La puissance est transmise à travers le corps par un système de transmission Bio-électrique. Le corps entier est exempt de tout os ou structure de soutien. Une fois la créature morte, la puissance ne circule plus à travers son corps et elle devient une poupée de chiffon inerte, un amas de chair et de fluides Aliens. Sinon, on remarque une paire de cellules en céramique qui, tel un défibrillateur, peut brièvement faire revivre la créature.\"\n  STR_DEEP_ONE_UFOPEDIA: \"'Celui des Profondeurs', aussi nommé 'Profond', est un cauchemar biologique, une espèce hybride produite par les expériences tordues des Aquatoïdes. Nous avons rencontré plusieurs versions de cette créature, et après des recherches approfondies nous en avons conclus qu'elles ont été fabriquées par les envahisseurs, qui gonflent leurs rangs chaque fois qu'ils ont un nouveau stock d'humains capturés. Chacun de ces sous-hommes est armé avec un lanceur de décharges électriques, suffisamment puissantes pour tuer un aquanaute.\"\n  STR_DEEP_ONE_AUTOPSY: \"Autopsie du Profond\"\n  STR_DEEP_ONE_AUTOPSY_UFOPEDIA: \"La créature est un ensemble de greffes d'organismes humains et Aliens. Le cerveau humain est massivement altéré pour accueillir l'électronique de contrôle et le cortex Alien. Tous les vestiges du corps humain semblent avoir disparut, sauf un : les yeux. La greffe semble permettre au foetus Alien de progressivement remplacer l'hôte humain pendant sa croissance. La peau de la créature semble être non-organique, un maillage métallique extrêmement résistant et flexible.  Le résultat de cet hybridation est une créature puissante, rapide et entièrement contrôlée par les Aliens.\"\n  STR_BIODRONE_UFOPEDIA: \"Le Bio-Drone est une création qui ne peut avoir trouvé sa source que dans l'esprit d'un Alien. Il s'agit d'un cerveau (humain ou Alien) suspendu dans des fluides amniotiques et connecté à une unité capable de volet sur terre ou de flotter sous l'eau. Chaque Bio-Drone est armé avec un puissant perturbateur auditif, mi-machine mi-organique. Certains de nos scientifiques ont suggéré que l'arme est manipulée par les cordes vocales d'origine de l'organisme hôte. Hautement précis et tenaces, ces super chien de garde sont largement utilisés par les Aliens pour protéger leurs avoirs de valeur.\"\n  STR_BIODRONE_AUTOPSY: \"Autopsie du Bio-Drone\"\n  STR_BIODRONE_AUTOPSY_UFOPEDIA: \"Le perturbateur auditif est effectivement un appareil biologique. Cette créature malchanceuse tue littéralement ses ennemis avec ses cris. Chacune montre de sérieux traumatismes chirurgicaux et de graves mutilations. Les Aliens semblent prêts à charcuter le cerveau pour obtenir l'obéissance. La majeure partie du cortex utilisé pour créer la créature est d'origine Alienne, mais rien n'est comparable à l'horreur que l'on peut éprouver en se rendant compte que l'unité est basée sur un cerveau humain.  Les Bio-Drones sont alimentés par un moteur IONIQUE et une forme de système de contrôle à distance a été incorporé.\"\n  STR_TENTACULAT_UFOPEDIA: \"Même les horreurs sorties des cauchemars Lovecraftiens ne pourraient donner naissance à cette créature indescriptible. Toute comparaison avec quelque animal Terrien est inutile, l’environnement qui a pu produire une telle abomination dépasse l'entendement. Armé de longues tentacules, le Tentaculaire paralyse ses victimes et les transforme en créatures décérébrées. Cette progéniture peut apporter la mort d'un simple toucher, et nul armure ne l'arrête. Le Tentaculaire est l'Alien le plus redoutable que X-Com ait rencontré à ce jour.\"\n  STR_TENTACULAT_AUTOPSY: \"Autopsie du Tentaculaire\"\n  STR_TENTACULAT_AUTOPSY_UFOPEDIA: \"L'autopsie révèle de petits implants cybernétiques logés dans l'énorme cerveau de la créature. Le système de la vision est une combinaison complexe d'acquisitions par imageries lumineuses et thermiques. Même dans les profondeurs les plus sombres de l'océan, ce monstre peut naviguer avec une précision infaillible. Il y a des organes atrophiés qui semblent assurer le minimum vital. Chaque créature a un petit estomac avec un connecteur externe, on peut donc en déduire qu'elle reçoit directement les substances nutritives par l'intermédiaire de ses maitres.\"\n  STR_CALCINITE_UFOPEDIA: \"Comme les combinaisons de plongée des marins perdus en mer, ces Aliens rôdent sur les fonds marins à la recherche des imprudents. Un coup vicieux infligé par les pinces de la créature,  toutes deux plus résistantes que l'acier, suffit à renvoyer les meilleurs plongeurs par le fond. Tourbillonnant derrière son masque, une forme verte gélatineuse est visible. Nous n'avons aucun indice pour deviner ce qu'est vraiment la créature malgré les rencontres, souvent létales, que nous avons eu avec elle.\"\n  STR_CALCINITE_AUTOPSY: \"Autopsie du Calcinite\"\n  STR_CALCINITE_AUTOPSY_UFOPEDIA: \"Une fois la combinaison blindée retirée, le Calcinite se révèle être une énorme masse de protoplasme amorphe. Pas de cerveau visible, pas de membres ou d'organes sensoriels existants, seul un composant métallique réside profondément dans le corps liquide. Une fois morte, nous pouvons seulement présumer de ce qu'est la vraie nature de la créature. Une énigme inexplicable venant de nos ennemis Aliens.\"\n  STR_TRISCENE_UFOPEDIA: \"Ce reptile bipède nous renvoi à l'ère des Dinosaures. Il semblerait que ce soit une créature du Crétacé dans tous les sens du terme, qui conserve sa capacité à survivre aussi bien dans l'eau que sur terre. Ces créatures sont affublées de modules d'armes et on une mâchoire garnie de rangées de grandes dents métalliques. Ces créatures ont souvent été au coeur des forces d'attaque Aliennes vu que ces derniers lancent des assauts sur les terres. Un poids-lourd et une arme puissante que les Commandants Tasoth déploient avec une efficacité létale.\"\n  STR_TRISCENE_AUTOPSY: \"Autopsie du Triscène\"\n  STR_TRISCENE_AUTOPSY_UFOPEDIA: \"Une fois soumis au scalpel des scientifiques, le Triscène se révèle être une créature antique à laquelle on a ajouté des implants cybernétiques et des systèmes d'armes. A son cerveau étriqué a été ajouté un petit module informatique installé sur le harnais de contrôle que toutes les créatures portent. Une peau naturellement résistante, un instinct de prédateur et des armes supplémentaires en font un adversaire létal dans tous les environnements.\"\n  STR_HALLUCINOID_UFOPEDIA: \"Ayant moissonné les océans, les Aliens ont élevé ces gigantesques créatures Terriennes pour en faire une arme. Ne vous laissez pas abuser par le faux sentiment de sécurité qui vous envahit lorsque vous affrontez ces marins des profondeurs à l'aspect inoffensif. Pouvant lancer des attaques gelantes en mêlée, l'Hallucinoïde est un ennemi mortel.\"\n  STR_HALLUCINOID_AUTOPSY: \"Autopsie de l'Hallucinoïde\"\n  STR_HALLUCINOID_AUTOPSY_UFOPEDIA: \"Niché dans les nombreuses couches du corps gélatineux de cet organisme se trouve un puissant congélateur chimique, sa principale capacité offensive. La peau douce et souple de l'Hallucinoïde semble sensible aux attaques à base de chaleur. On retrouve souvent ce mutant en compagnie de ses maitres, les Aquatoïdes.\"\n  STR_XARQUID_UFOPEDIA: \"Autre exemple de créature terrienne invertébrée ayant subis des altérations, le xarquide est une créature aussi belle que dangereuse. Cette créature rapide et gargantuesque cache un arsenal dévastateur, comprenant un jet d'encre étouffant et un tir de particules ionisées. Depuis nos premières rencontres avec cette puissante créature, nous avons appris à craindre sa puissance ainsi que les vindicatifs hommes-poissons qui les contrôlent.\"\n  STR_XARQUID_AUTOPSY: \"Autopsie du Xarquide\"\n  STR_XARQUID_AUTOPSY_UFOPEDIA: \"Ce nautile surdéveloppé a grandi avec un régime à base de drogues aliennes et d'opérations chirurgicales. Pervertis au-delà de tout ce qui est naturellement possible, les hommes-poissons ont ajouté des systèmes de contrôle mécanique à la créature et tout ce qu'elle avait de naturel a disparu. Déployés comme des plateformes d'armes organiques, les xarquides possèdent une coquille résistante et une grande mobilité qui en font de formidables adversaires.\"\n  STR_ION_BEAM_ACCELERATORS_UFOPEDIA: \"Les submersibles volants des Aliens dépendent d'un système de puissance complexe pour les propulser à une vitesse incroyable à travers les profondeurs. La base de leur technologie est de DÉPLACEUR IONIQUE qui utilise du Zrbite comme catalyseur, les moteurs déplacent 100 fois leur propre volume en eau par seconde. Cette énorme puissance signifie que les Aliens sont capable de surclasser la plupart des submersibles sur Terre. Nous pouvons reproduire ce système de propulsion en utilisant de l'aqua-plastique et des cellule de puissance au Zrbite.\"\n  STR_MAGNETIC_NAVIGATION_UFOPEDIA: \"Ces unités génèrent un champ magnétique multi-couches de forme sphérique, projeté à 1 kilomètre autour du submersible. Les navigateurs Aliens sont directement liés à ces machines et se déplacent en fonction des sensations qu'ils ressentent à travers le monde invisible qui se trouve sous les vagues. Le système d'interface opère en utilisant de la matière cérébrale Alienne modifiée qui communique directement avec le cerveau de l'opérateur via un lien neural.\"\n  STR_ALIEN_SUB_CONSTRUCTION_UFOPEDIA: \"Chaque vaisseau a une structure semblable à celle d'un caméléon, fidèlement modelé selon les créatures marines, est construit avec de l'Aqua-Plastique. Chaque submersible fonctionne comme un organisme : l'équipage et le vaisseau sont en harmonie. La plupart de ces systèmes peut être reproduit et une technologie hybride peut évoluer pour atteindre le même niveau technologique.\"\n  STR_ALIEN_CRYOGENICS_UFOPEDIA: \"Les innombrable Aliens qui sont resté caché sur Terre sont maintenus par animation suspendue en cryogénie. Toutes les créatures sont enfermées dans des unités, leur température corporelle réduite à un point où les fonctions vitales sont complètement arrêtées. Un examen de ces unités a jusqu'ici révélé l'incroyable durée de la période pendant laquelle les corps ont été maintenus en suspension : supérieure à 60 millions d'années.\"\n  STR_ALIEN_CLONING_UFOPEDIA: \"De nombreux Aliens que nous avons capturés sont identiques jusque dans leur ADN, reproduits dans tous les sens du terme. Des échantillons cellulaires sont placés dans les unités à partir de banques génétiques Aliennes où ils sont conservés dans la glace. Certaines unités contiennent des humains ou des parties du corps. Il est possible qu'une autre utilisation de ces unités de clonage consiste à créer des hybrides Humains/Aliens.\"\n  STR_ALIEN_LEARNING_ARRAYS_UFOPEDIA: \"Utilisant les Implants de Contrôle Moléculaire présents dans les crânes de tous les Aliens, ces machines infusent l'information directement dans le cerveau. Les Aliens récemment clonés sont amenés vers ces unités, les souvenirs de leurs races respectives et toutes les informations scientifiques et militaires sont téléchargées directement dans leurs esprits vierges.\"\n  STR_ALIEN_IMPLANTER_UFOPEDIA: \"Cette unité est utilisée pour poser des Implants de Contrôle Moléculaire aux Aliens, féconder les races reproductrices, et insérer ou retirer des organes et des composants électroniques aux créatures. On pensait que le processus s'effectuait sur des patients soumis, mais le sujet est parfaitement conscient du processus et malheureusement l'anatomie humaine semble parfaitement adaptée à l'unité.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"Nous avons maintenant des preuves qui expliquent pourquoi les Aliens capturent des humains. Ils ne constituent pas une source de nourriture, ils ne sont pas fécondés avec des embryons Aliens, ils forment plutôt la base d'une gamme de créatures et de systèmes de contrôle. La technologie Alienne est basée sur un esprit collectif, une intelligence partagée et les cerveaux humains sont le réceptacle idéal pour ces systèmes. Le cerveau humain est utilisé dans la plupart des stockages d'ordinateurs biologiques Aliens et des systèmes de sauvegarde, le reste est utilisé pour la construction et la reproduction.\"\n  STR_AQUA_PLASTICS_UFOPEDIA: \"Les submersibles et les structures des Aliens utilisent un matériau résistant, flexible et durable pour la majorité de leur construction. Les Aqua-Plastiques sont des matériaux complexes à liaisons multiples et à base de Zrbite catalysé. Dense mais léger, la substance a une résistance qui dépasse celle du Titane ou du Kevlar.\"\n  STR_ZRBITE_UFOPEDIA: \"Ceci est un alliage d'origine Alienne, mi-or mi-Bio-matériaux Alien. Quand on s'en sert comme source de puissance, une petite quantité génèrera plus de puissance qu'un réacteur nucléaire faisant 10 fois sa taille. Nous n'avons pas les moyens techniques de reproduire ce matériau vu que la plus grande partie de ses composants sont d'origine Alienne.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"Les Aliens lancent des frappes autour du globe, avec une efficacité implacable. Nous ne pouvons en déterminer la source. Se pourrait il qu'elle se trouve dans un gouffre océanique impénétrable dans lequel nous ne pouvons la localiser ? Tous les organismes que nous avons rencontré ne sont pas Alien, certains sont très anciens, d'autres sont des chainons dans l'évolution qui se sont éteint il y a bien longtemps. Nous faisons face à une menace qui a dormi pendant des millénaires, une symbiose subtile d'humains et d'Aliens. Dans les profondeurs des océans reposent des sites antiques utilisés par les Aliens pour contacter leurs cousin stellaires. Chacun de ces 12 sites contiennent un dispositif au Synomium, une puissante technologie Alienne. Maintenant que leur machine de guerre est en marche, les Aliens ré-activent ces sites pour agrandir leur réseau de Contrôle Moléculaire, nous devons les détruire à tous prix.\"\n  STR_THE_ULTIMATE_THREAT_UFOPEDIA: \"Il y a 65 Millions d'années, un immense vaisseau/colonie fut envoyé sur Terre à partir d'un monde éloigné. Tandis que l'énorme vaisseau approchait de la toute jeune planète, une violente éruption solaire provoqua la défaillance du système de navigation. Estropié, il dériva et pénétra dans la stratosphère pour traverser le ciel du Crétacé. Sur Terre, d'innombrable formes de vies posèrent leurs yeux sur leur ennemi juré qui s'écrasait sur la planète. Un immense nuage de poussière envahit l'atmosphère, et tandis que les terres refroidissaient, la forme de vie dominante, les dinosaures, périt. Mais les 400 milliards de tonnes de T'leth ne furent pas détruits dans l'impact, des super-ordinateurs sophistiqués initièrent un cycle de sommeil cryogénique pour les créatures qui y étaient profondément enfouies. Tandis que les éons passaient, les ordinateurs réveillèrent certains Aliens pour tenter de communiquer avec leurs cousins stellaires, mais en vain et le noyau de la puissance Alienne demeura endormie.\"\n  STR_TLETH_THE_ALIEN_CITY: \"T'leth, la cité Alienne\"\n  STR_TLETH_THE_ALIEN_CITY_UFOPEDIA: \"T'leth, l'immense vaisseau/colonie Alien, repose au fond du Gouffre de Sigsbee, dans le Golfe du Mexique. Au coeur de la cité Alien se trouve une horreur Alienne, si ignoble et puissante que même la mort rebrousse chemin. Dans une chambre de métal Alien repose la forme endormie du Grand Rêveur, l'Alien Suprême. Quand T'leth s'élèvera au dessus des vagues, son cycle de ré-animation débutera, et une fois à son zénith, nul ne l'arrêtera. Ni mort ni vivant, l'esprit Alien contrôle l'armée Alienne. L'étrange technologie du contrôle moléculaire connecte tous les Aliens à l'esprit, et ce dernier au collectif. Des foetus Humains/Aliens génétiquement modifiés fournisse à l'esprit Alien son énergie et forment le lien entre le dirigeant et ses sujets. Le mythe de L'Alien Suprême a existé dans les coeurs et les esprits des humains pendant des siècles, les mers ont toujours caché la vérité ultime.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"CENTRER SUR SITE-TEMPS=5 Sec\"\n  STR_CANCEL_UC: \"ANNULER\"\n  STR_NONE: \"Aucun\"\n  STR_UNKNOWN: \"Inconnu\"\n  STR_POOR: \"Médiocre\"\n  STR_AVERAGE: \"Moyen\"\n  STR_GOOD: \"Bon\"\n  STR_EXCELLENT: \"Excellent\"\n  STR_BUILD_NEW_BASE_UC: \"CONSTRUIRE NOUVELLE BASE\"\n  STR_BASE_INFORMATION: \"INFORMATIONS SUR LA BASE\"\n  STR_EQUIP_CRAFT: \"ÉQUIPER SUBMERSIBLE\"\n  STR_BUILD_FACILITIES: \"CONSTRUIRE INSTALLATIONS\"\n  STR_RESEARCH: \"RECHERCHE\"\n  STR_MANUFACTURE: \"FABRICATION\"\n  STR_TRANSFER_UC: \"TRANSFERT\"\n  STR_PURCHASE_RECRUIT: \"ACHETER/RECRUTER\"\n  STR_SACK: \"LICENCIER\"\n  STR_SELL_SACK_UC: \"VENDRE/LICENCIER\"\n  STR_GEOSCAPE_UC: \"GÉOSCAPE\"\n  STR_NAME: \"Nom\"\n  STR_AREA: \"Zone\"\n  STR_BUILD_NEW_BASE: \"Construire Nouvelle Base\"\n  STR_CANCEL: \"Annuler\"\n  STR_COST_UC: \"PRIX>\"\n  STR_CONSTRUCTION_TIME_UC: \"TEMPS DE CONSTRUCTION>\"\n  STR_DAY:\n    one: \"{N} jour\"\n    many: \"{N} jours\"\n    other: \"{N} jours\"\n  STR_HOUR:\n    one: \"{N} heure\"\n    many: \"{N} heures\"\n    other: \"{N} heures\"\n  STR_MAINTENANCE_UC: \"ENTRETIEN>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Installation\"\n  STR_CURRENT_RESEARCH: \"RECHERCHE ACTUELLE\"\n  STR_SCIENTISTS_AVAILABLE: \"Scientifiques Disponibles> {ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Scientifiques Assignés> {ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Espace Laboratoire Disponible> {ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"PROJET DE RECHERCHE\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"SCIENTIFIQUES ASSIGNÉS\"\n  STR_PROGRESS: \"PROGRÈS\"\n  STR_NEW_PROJECT: \"Nouveau Projet\"\n  STR_CANCEL_PROJECT: \"ANNULER PROJET\"\n  STR_NEW_RESEARCH_PROJECTS: \"NOUVEAUX PROJETS DE RECHERCHE\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"SCIENTIFIQUES DISPONIBLES> {ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"ESPACE LABORATOIRE DISPONIBLE> {ALT}{0}\"\n  STR_INCREASE: \"Augmenter\"\n  STR_DECREASE: \"Réduire\"\n  STR_START_PROJECT: \"COMMENCER PROJET\"\n  STR_CURRENT_PRODUCTION: \"PRODUCTION ACTUELLE\"\n  STR_ENGINEERS_AVAILABLE: \"Ingénieurs Disponibles> {ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Ingénieurs Attribués> {ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Espace Atelier Disponible> {ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Fonds Actuels> {ALT}{0}\"\n  STR_ITEM: \"OBJET\"\n  STR_ENGINEERS__ALLOCATED: \"Ingénieurs Attribués\"\n  STR_UNITS_PRODUCED: \"Unités Produites\"\n  STR_TOTAL_TO_PRODUCE: \"Total à Produire\"\n  STR_COST__PER__UNIT: \"Coût{NEWLINE}par{NEWLINE}Unité\"\n  STR_DAYS_HOURS_LEFT: \"Jours/Heures restants\"\n  STR_NEW_PRODUCTION: \"Nouvelle Production\"\n  STR_PRODUCTION_ITEMS: \"Objets à Produire\"\n  STR_CATEGORY: \"CATÉGORIE\"\n  STR_START_PRODUCTION: \"COMMENCER PRODUCTION\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} heures d'Ingénieur pour produire une unité\"\n  STR_COST_PER_UNIT_: \"Coût par Unité> {ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Espace de Travail Requis> {ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"MATÉRIAUX SPÉCIAUX NÉCESSAIRES\"\n  STR_ITEM_REQUIRED: \"OBJET REQUIS\"\n  STR_UNITS_REQUIRED: \"UNITÉS REQUISES\"\n  STR_UNITS_AVAILABLE: \"UNITÉS DISPONIBLES\"\n  STR_STOP_PRODUCTION: \"ARRÊTER PRODUCTION\"\n  STR_ENGINEERS_AVAILABLE_UC: \"INGÉNIEURS DISPONIBLES> {ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"ESPACE ATELIER DISPONIBLE> {ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"BÉNÉFICE MENSUEL> {ALT}{0}\"\n  STR_INCREASE_UC: \"AUGMENTER\"\n  STR_DECREASE_UC: \"RÉDUIRE\"\n  STR_UNITS_TO_PRODUCE: \"Unités à Produire\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Acheter/Recruter Personnel\"\n  STR_COST_OF_PURCHASES: \"Prix d'Achat> {ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"COÛT PAR UNITÉ\"\n  STR_QUANTITY_UC: \"QUANTITÉ\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"PERSONNEL DISPONIBLE:PERSONNEL TOTAL>\"\n  STR_SOLDIERS: \"Aquanautes\"\n  STR_SCIENTISTS: \"Scientifiques\"\n  STR_ENGINEERS: \"Ingénieurs\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"ESPACE UTILISÉ:ESPACE DISPONIBLE>\"\n  STR_LIVING_QUARTERS: \"Quartiers du Personnel\"\n  STR_STORES: \"Entrepôts\"\n  STR_LABORATORIES: \"Laboratoires\"\n  STR_WORK_SHOPS: \"Ateliers\"\n  STR_HANGARS: \"Quais à Submersibles\"\n  STR_SHORT_RANGE_DETECTION: \"Sonar Courte Portée\"\n  STR_DEFENSE_STRENGTH: \"Force de Défense\"\n  STR_TRANSFERS_UC: \"TRANSFERTS\"\n  STR_TRANSFERS: \"Transferts\"\n  STR_ARRIVAL_TIME_HOURS: \"Arrivée Prévue (heures)\"\n  STR_COST_: \"Prix> {ALT}{0}\"\n  STR_AREA_: \"Zone> {ALT}{0}\"\n  STR_BASE_NAME: \"Nom de la Base ?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"SÉLECTIONNER POSITION DU SAS D'ACCÈS\"\n  STR_TRANSFER: \"Transfert\"\n  STR_AMOUNT_TO_TRANSFER: \"QUANTITÉS A TRANSFÉRER\"\n  STR_SELECT_DESTINATION_BASE: \"Sélectionner Base de Destination\"\n  STR_COST: \"Prix\"\n  STR_INTRO_1: \"MicroProse 1995 / Firaxis , Tous droits réservés\"\n  STR_INTRO_2: \"Mars : La chute de Cydonia.\"\n  STR_INTRO_3: \"X-Com, après sa victoire écrasante sur le noyau même de la machine de guerre Extra-Terrestre, retourne en trombe sur Terre. Toutefois, tous les ennemis ne sont pas morts dans la base Martienne ravagée.\"\n  STR_INTRO_4: \"Un puissant rayon tachyon émerge du centre névralgique de Cydonia, parcourant le vide. Ayant pour destination............\"\n  STR_INTRO_5: \"La Terre.\"\n  STR_INTRO_6: \"Le rayon atteint le fond des océans et touche un récepteur dormant. D'immenses ordinateurs endormis commencent à s'agiter. Dans les profondeurs, loin des yeux humains, d'immense chambres remplies d'Aliens endormis débutent un long cycle de ré-animation.\"\n  STR_INTRO_7: \"2040 : Une Terre insouciante. Les terreurs de la guerre Extra-Terrestre ont été oubliées. Mais, dans des endroits perdus et cachés de l'océan, les hordes Aliennes sont prêtes... prêtes à renverser la civilisation humaine et prendre le contrôle du monde.\"\n  STR_INTRO_8: \"Les Aliens lancent des frappes sur l'humanité, cherchent des spécimens pour leurs expériences tordues, lancent des raids autour du globe pour trouver des minéraux et autres ressources de valeur, et pillent les mers. Et finalement posent leur yeux sur ce qui se trouve au dessus des vagues.\"\n  STR_INTRO_9: \"De puissants OSNIS volants de conception étrange parcourent les océans... ils observent, ils recherchent, ils chassent.........\"\n  STR_INTRO_10: \"Ils trouvent des proies à attaquer.\"\n  STR_INTRO_11: \"De nouvelles armes étranges sont dirigées contre un monde sans défenses. Nous sommes entièrement à la merci de la menace Alienne.{NEWLINE}Seule une organisation peut nous sauver... mais nous lui avons tourné le dos il y a longtemps......\"\n  STR_INTRO_12: \"L'Installation Sous-Marine Expérimentale d'X-Com\"\n  STR_INTRO_13: \"'Mayday ! Mayday !' 'Ici le paquebot transatlantique Hypérion'. 'Nous sommes attaqués'. 'Mayday ! Mayd............'\"\n  STR_INTRO_14: \"'Centre de Contrôle à Quai Un : Ouvrez les portes', 'déployez le Barracuda Zéro Un. Nous avons une situation impliquant une attaque Alienne : condition Rouge'.{NEWLINE}'Je répète : condition Rouge'\"\n  STR_INTRO_15: \"Les Aliens sont d'une efficacité implacable....\"\n  STR_INTRO_16: \"...et d'une précision infaillible\"\n  STR_INTRO_17: \"'Barracuda Zéro Un à la base' : 'j'approche de ce qu'il reste de l'Hyperion'.\"\n  STR_INTRO_18: \"'Je ralentis'.{NEWLINE}'Deux mètres'{NEWLINE}'Un mètre'{NEWLINE}'A tous les aquanautes, préparez vous pour un déploiement immédiant'.\"\n  STR_INTRO_19: \"...........'J'ai quitté le sas'...'j'approche de l'épave'.{NEWLINE}'Ho mon dieu !'{NEWLINE}'Vous voyez ces créatures sur votre écran ?'\"\n  STR_GAMEOVER_1: \"Nous avons échoué, les Aliens ont réduit nos derniers espoirs à néant.{NEWLINE}X-Com a été détruit et la Terre est vouée à un ennemi antique.\"\n  STR_GAMEOVER_2: \"T'leth s'élève dans la stratosphère et commence à se déplacer sur la face du monde. Apportant la mort et récoltant les humains survivants. Au plus profond de ses boyaux, le funeste esprit Alien se réveille.\"\n  STR_GAMEOVER_3: \"Dans les différentes capitales des nations, on imagine des plans désespérés. Mais en vain, car sans les technologies mises au point par X-Com, nos armes sont inefficaces.\"\n  STR_GAMEOVER_4: \"Les Aliens installent des bases et les calottes glacières commencent à fondre, le monde deviendra un vaste océan. Les humains survivants sont capturés et utilisés pour d'ignobles expériences de reproduction à des fins inconnues, sauf pour les Aliens. Les cieux s'obscurcissent et une puissante pestilence s’abat sur les terres.\"\n  STR_GAMEOVER_5: \"Nous ne pouvons nous opposer au nouvel ordre mondial, et ceux qui tente connaissent un destin funeste face à des armes Aliennes incompréhensibles. Mais les autres ne connaissent pas un destin meilleur, la Terre devient un monde Alien et l'humanité est submergée par une horreur rampante.\"\n  STR_OUTRO_1: \"La Tombe a été ravagée et décimée, un rugissement s'échappe du cercueil en son centre.{NEWLINE}Imbéciles, vous allez tous périr....................\"\n  STR_OUTRO_2: \".................nul ne peut s'échapper.\"\n  STR_OUTRO_3: \"Une explosion gigantesque prend sa source dans la tombe et se propage à travers la cité, les débris et la fumée saturent les airs. Les plans des Aliens ont été contrecarrés........\"\n  STR_OUTRO_4: \"La grandeur de T'leth commence à s’effriter. Les flammes et la fumée s'échappent de ses tours luisantes et de ses couloirs d'adamantium.\"\n  STR_OUTRO_5: \"La puissante forteresse Alienne chute vers la mer, les cris du métal et des âmes torturées saturent les airs. Le Grand Rêveur ne rêvera plus jamais de conquérir le monde.\"\n  STR_OUTRO_6: \"Dans un dernier bourdonnement, T'leth se disloque.{NEWLINE}La menace Alienne a disparut, la Terre a été purifiée..................\"\n  STR_OUTRO_7: \"Une planète dormante aux reflets bleu/vert, dans un coin éloigné de la galaxie.\"\n  STR_OUTRO_8: \"Le futur proche, un endroit sure.\"\n  STR_OUTRO_9: \"La menace Alienne qui pesait sur la Terre a depuis longtemps été vaincue.\"\n  STR_OUTRO_10: \"De vastes métropoles abritent désormais par milliards les masses grouillantes de l'humanité.\"\n  STR_OUTRO_11: \"Les faits d'armes d'X-Com et les guerres Aliennes font l'objet d'histoires à destination des enfants.\"\n  STR_OUTRO_12: \"Mais les légendes ont toujours eu une part de vérité............\"\n  STR_RISE_1: \"T'leth, ayant porté bien des noms, l'objet de nombreuses légendes de nombreuses contrées.\"\n  STR_RISE_2: \"Avec un hurlement explosif qui résonne à travers le globe, T'leth commence à s'élever des fonds marins.\"\n  STR_RISE_3: \"L'énorme édifice émerge des eaux du Golfe du Mexique.\"\n  STR_RISE_4: \"Les 400 Milliards de tonnes de métaux Aliens de la puissante cité Alienne renferment le corps léthargique de l'Alien Suprême. Emprisonné sur terre depuis 65 millions d'années, cette abominable divinité venue de l'espace commence à s'agiter.\"\n  STR_RISE_5: \"Les eaux bouillonnent tandis que la tombe du Grand Rêveur s'élèvent dans la lumière................\"\n  STR_RISE_6: \".........une lumière qui ne fera pas long feu si X-Com ne parvient pas à détruire la machine de guerre Alienne.\"\n  STR_YOU_HAVE_FAILED: \"Vous avez échoué à stopper la machine de guerre Alienne. Les organisations qui vous financent, ayant perdu toute illusion dans vos capacités, essayent de négocier une solution pacifique avec les Aliens. Les envahisseurs ont un agenda très différent, et bientôt le monde connaitra la vérité...\"\n  STR_TOTAL_UC: \"TOTAL\"\n  STR_INCOME: \"Revenu\"\n  STR_EXPENDITURE: \"Dépenses\"\n  STR_MAINTENANCE: \"Entretien\"\n  STR_BALANCE: \"Solde\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"Activité Alien par Mers\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"Activité Alien par Zones\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"Activité X-Com par Mers\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"Activité X-Com par Zones\"\n  STR_FINANCE: \"Finances\"\n  STR_DATE_FIRST: \"{0}er\"\n  STR_DATE_SECOND: \"{0}ème\"\n  STR_DATE_THIRD: \"{0}ème\"\n  STR_DATE_FOURTH: \"{0}ème\"\n  STR_FINANCE_THOUSANDS: \"$1000\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Pas assez de matériaux spéciaux pour produire{NEWLINE}{0}{NEWLINE}à{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Pas Assez d'Argent pour Produire{NEWLINE}{0}{NEWLINE}à{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"Production de{NEWLINE}{0}{NEWLINE}à{NEWLINE}{1}{NEWLINE}terminée.\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"Construction de{NEWLINE}{0}{NEWLINE}à{NEWLINE}{1}{NEWLINE}terminée\"\n  STR_OK_5_SECONDS: \"OK - 5 sec\"\n  STR_RESEARCH_COMPLETED: \"Recherche terminée\"\n  STR_VIEW_REPORTS: \"VOIR RAPPORTS\"\n  STR_WE_CAN_NOW_RESEARCH: \"Nous pouvons maintenant rechercher\"\n  STR_WE_CAN_NOW_PRODUCE: \"Nous pouvons maintenant produire\"\n  STR_SUNDAY: \"DIMANCHE\"\n  STR_MONDAY: \"LUNDI\"\n  STR_TUESDAY: \"MARDI\"\n  STR_WEDNESDAY: \"MERCREDI\"\n  STR_THURSDAY: \"JEUDI\"\n  STR_FRIDAY: \"VENDREDI\"\n  STR_SATURDAY: \"SAMEDI\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Pas assez de {0} pour faire le plein de {1} à {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Pas assez de {0} pour réarmer {1} à {2}\"\n  STR_UFO_IS_NOT_RECOVERED: \"L'OSNI n'a pas été récupéré\"\n  STR_UFO_IS_RECOVERED: \"L'OSNI a été récupéré\"\n  STR_CRAFT_IS_LOST: \"Le Submersible volant est perdu\"\n  STR_TERROR_CONTINUES: \"L'Activité Alienne se poursuit\"\n  STR_ALIENS_DEFEATED: \"Les Aliens sont vaincus\"\n  STR_BASE_IS_LOST: \"La base est perdue\"\n  STR_BASE_IS_SAVED: \"La Base est sauvée\"\n  STR_ALIEN_BASE_STILL_INTACT: \"Colonie Alienne intacte\"\n  STR_ALIEN_BASE_DESTROYED: \"Colonie Alienne détruite\"\n  STR_ALIENS_KILLED: \"ALIENS TUÉS\"\n  STR_ALIEN_CORPSES_RECOVERED: \"CORPS ALIENS RÉCUPÉRÉS\"\n  STR_LIVE_ALIENS_RECOVERED: \"ALIENS VIVANTS CAPTURÉS\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"ARTEFACTS DES ALIENS RÉCUPÉRÉS\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"LE CONTRÔLE DE LA COLONIE ALIENNE EST DÉTRUIT\"\n  STR_ALIEN_SYNOMIUM_DEVICE_DESTROYED: \"LE DISPOSITIF AU SYNOMIUM DES ALIENS EST DÉTRUIT\"\n  STR_ALIEN_SYNOMIUM_DEVICE_FAILED: \"ÉCHEC DE LA DESTRUCTION DU DISPOSITIF AU SYNOMIUM DES ALIENS\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"CIVILS TUÉS PAR DES ALIENS\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"CIVILS TUÉS PAR DES AGENTS X-COM\"\n  STR_CIVILIANS_SAVED: \"CIVILS SAUVÉS\"\n  STR_XCOM_OPERATIVES_KILLED: \"AGENTS X-COM TUÉS\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"AGENTS X-COM PORTÉS DISPARUS\"\n  STR_TANKS_DESTROYED: \"PLATES-FORME D'ARME LOURDE X-COM DÉTRUITE\"\n  STR_XCOM_CRAFT_LOST: \"SOUS-MARIN X-COM PERDU\"\n  STR_UFO_RECOVERY: \"RÉCUPÉRATION D'OSNI\"\n  STR_ALIEN_BASE_RECOVERY: \"RÉCUPÉRATION DE COLONIE EXTRATERRESTRE\"\n  STR_BASE_UNDER_ATTACK: \"{0} est attaqué !\"\n  STR_BASE_DEFENSES_INITIATED: \"DÉFENSES DE LA BASE ACTIVÉES\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"LE BOUCLIER REPOUSSE L'OSNI !\"\n  STR_FIRING: \"TIR\"\n  STR_HIT: \"TOUCHÉ !\"\n  STR_UFO_DESTROYED: \"OSNI DÉTRUIT !\"\n  STR_MISSED: \"MANQUÉ !\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Vendre/Licencier Personnel\"\n  STR_VALUE_OF_SALES: \"VALEUR DE VENTE> {ALT}{0}\"\n  STR_FUNDS: \"FONDS> {ALT}{0}\"\n  STR_SELL_SACK: \"Vendre/Licencier\"\n  STR_VALUE: \"Valeur\"\n  STR_CRAFT_: \"SUBMERSIBLE VOLANT> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"RÉCUPÉRATION D'OSNI ABATTU\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"SOYEZ TRÈS PRUDENT : Il y aura des Aliens dans l'OSNI et autour du site. Cette mission sera achevée quand tous les ennemis auront été éliminé ou neutralisé. La récupération des restes de l'OSNI, de la technologie et des corps Aliens pourra alors commencer. Pour abandonner la mission, renvoyez les aquanautes au submersible volant et cliquez sur 'Annuler la Mission'.\"\n  STR_UFO_GROUND_ASSAULT: \"ASSAUT SUR OSNI\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"Explorez le site d’amerrissage et, si possible, entrez dans l'OSNI. La mission sera un succès quand tous les ennemis auront été éliminé ou neutralisé. La récupération de l'OSNI, des artéfacts et des corps Aliens pourra alors commencer. Pour abandonner la mission, renvoyez les aquanautes au submersible volant et cliquez sur 'Annuler la Mission'.\"\n  STR_BASE_DEFENSE: \"DÉFENSE DE BASE\"\n  STR_BASE_UC_: \"BASE> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"Un vaisseau Alien a amerri à proximité. Notre base est en grand danger. Comme le veut la procédure standard, le personnel non combattant et les submersibles X-COM fonctionnels ont été évacués. Les Aliens vont entre dans la base par les Quais ou par le Sas. Défendez la base et ses installations vitales à tous prix : c'est un combat à mort. Si vous cliquez sur 'Annuler la Mission', vous vous résignez à la défaite et perdez la base.\"\n  STR_ALIEN_COLONY_ATTACK_MISSION: \"MISSION ATTAQUE SUR COLONIE ALIENNE\"\n  STR_ALIEN_BASE_ASSAULT: \"COLONIE ALIENNE PARTIE UNE\"\n  STR_ALIEN_COLONY_P1_BRIEFING: \"Cette mission est un raid sur le site d'une colonie Alienne. Il existe 2 niveaux  pour ce site, envoyez tous les aquanautes à la sortie brillante du premier complexe et cliquez sur 'Annuler la Mission' pour continuer. Tout équipement laissé derrière restera sur le fond marin jusqu'à ce que la 2e section ait été nettoyée. Pour quitter la zone, renvoyez les aquanautes au Submersible volant et cliquez sir 'Annuler la Mission'.\"\n  STR_ALIEN_COLONY_P2: \"COLONIE ALIENNE PARTIE DEUX\"\n  STR_ALIEN_COLONY_P2_BRIEFING: \"Après avoir négocié le premier niveau et être entré dans le noyau de la colonie, la mission consiste maintenant à détruire le centre de contrôle, le Dispositif au Synomium, et éliminer tous les Aliens. Pour abandonner, renvoyez les aquanautes au point de départ et cliquez sur 'Annuler la Mission'. Tout équipement X-Com viable sera renvoyé à la base.\"\n  STR_ALIENS_LAUNCH_PORT_TERROR: \"LES ALIENS ATTAQUENT{NEWLINE}UNE ZONE PORTUAIRE\"\n  STR_PORT_TERROR: \"LES ALIENS ATTAQUENT UN PORT\"\n  STR_PORT_TERROR_BRIEFING: \"Les Aliens ont lancé une attaque sur des sites en surface. Le port et ses populations civiles sont menacés. Votre escouade doit éliminer tous les Aliens et protéger les témoins innocents de cette incursion Alienne. Pour quitter la zone, faites revenir les aquanautes au submersible volant et cliquez sur 'Annuler la Mission'.\"\n  STR_ALIENS_LAUNCH_ISLAND_TERROR: \"LES ALIENS ATTAQUENT{NEWLINE}UNE ILE OU UN ARCHIPEL\"\n  STR_ISLAND_TERROR: \"LES ALIENS ATTAQUENT UNE ILE\"\n  STR_ISLAND_TERROR_BRIEFING: \"Les Aliens ont lancé une attaque sur des sites en surface. L'ile et ses populations civiles sont menacées. Votre escouade doit éliminer tous les Aliens et protéger les témoins innocents de cette incursion Alienne. Pour quitter la zone, faites revenir les aquanautes au submersible volant et cliquez sur 'Annuler la Mission'.\"\n  STR_ALIENS_ATTACK_SHIPPING_ROUTE: \"LES ALIENS ATTAQUENT{NEWLINE}UNE VOIE MARITIME\"\n  STR_CARGO_SHIP_P1: \"NAVIRE DE TANSPORT PARTIE UNE\"\n  STR_CARGO_SHIP_P2: \"NAVIRE DE TRANSPORT PARTIE DEUX\"\n  STR_CRUISE_SHIP_P1: \"NAVIRE DE CROISIÈRE PARTIE UNE\"\n  STR_CRUISE_SHIP_P2: \"NAVIRE DE CROISIÈRE PARTIE DEUX\"\n  STR_SHIP_RESCUE_MISSION: \"MISSION SAUVETAGE DE NAVIRE\"\n  STR_SHIP_RESCUE_P1_BRIEFING: \"Cette mission consiste à dératiser, éliminez tous les Aliens sur le navire, et protégez les civils qui sont à bord. Les Aliens sont éparpillés sur les ponts supérieurs et inférieurs, sécurisez les ponts supérieurs avant d'entrer dans les ponts inférieurs. Pour quitter la zone, faites revenir les aquanautes au submersible volant et cliquez sur 'Annuler la Mission'.\"\n  STR_SHIP_RESCUE_P2_BRIEFING: \"Maintenant que les ponts supérieurs sont nettoyés, continuez vers les ponts inférieurs. Vous empruntez le monte-charge du cargo pour descendre dans la cale. Votre escouade doit éliminer tous les Aliens de ce niveau pour achever la mission. Pour abandonner, renvoyez tous les aquanautes au point de départ et cliquez sur 'Annuler la Mission'.\"\n  STR_ALIEN_ACTIVITY_DETECTED: \"ACTIVITÉ ALIENNE DÉTECTÉE\"\n  STR_ALIEN_CONTACT_SITE_MISSION: \"MISSION SITE DE CONTACTE ALIEN\"\n  STR_ARTIFACT_SITE_P1: \"SITE DE CONTACTE ALIEN PARTIE UNE\"\n  STR_ARTIFACT_SITE_P1_BRIEFING: \"Cette mission est un raid sur un site de communication Alien récemment activé. Il existe 2 niveaux pour ce site, le fond marin avec ses pyramides Aliennes et un complexe Alien caché. Envoyez tous les aquanautes à l'entrée du complexe et cliquez sur 'Annuler la Mission' pour continuer. Pour quitter la zone, faites revenir les aquanautes au submersible volant et cliquez sur 'Annuler la Mission'.\"\n  STR_ARTIFACT_SITE_P2: \"SITE DE CONTACTE ALIEN PARTIE DEUX\"\n  STR_ARTIFACT_SITE_P2_BRIEFING: \"Après avoir négocié les structures Aliennes et être entré dans le complexe, les objectifs de missions sont clairs. Pénétrez au coeur de l'installation Alienne et détruisez le Dispositif de Contrôle Moléculaire au Synomium pour achever la mission. Pour abandonner, faites revenir les aquanautes au point de départ et cliquez sur 'Annuler la Mission'.\"\n  STR_SIGSBEE_DEEP_MISSION: \"MISSION GOUFFRE DE SIGSBEE{NEWLINE}CITE ALIENNE NIVEAU UN\"\n  STR_TLETH_P1_BRIEFING: \"Nous pénétrons dans l'inconnu, à partir d'ici nous devons nous attendre à tout. Nous savons qu'il existe 2 autres niveaux dans la Cité Alienne et que votre escouade doit rapidement rejoindre la sortie de ce niveau pour atteindre le suivant. Placez tous les aquanautes sur la sortie et cliquez sur 'Annuler la Mission' pour avancer. Abandonner ailleurs mettra fin à la mission.\"\n  STR_TLETH_ATTACK_MISSION: \"MISSION D'ATTAQUE, T'LETH{NEWLINE}CITE ALIENNE NIVEAU DEUX\"\n  STR_TLETH_P2_BRIEFING: \"Nous progressons dans l'inconnu, à partir d'ici il faut s'attendre à tout. Nous savons qu'il existe un autre niveau dans la Cité Alienne et que votre escouade doit rejoindre rapidement la sortie de ce niveau pour atteindre le suivant. Placez tous les aquanautes sur la sortie et cliquez sur 'Annuler la mission' pour avancer. Abandonner ailleurs mettra fin à la mission.\"\n  STR_FINAL_TLETH_MISSION: \"MISSION FINALE, T'LETH{NEWLINE}CITE ALIENNE NIVEAU TROIS\"\n  STR_TLETH_P3_BRIEFING: \"Le dénouement est proche, à partir d'ici nous recherchons la crypte de l'Alien Suprême. Détruisez les 8 sources de puissance qui alimentent la tombe pour mettre fin à la menace Alienne. N'abandonnez pas maintenant ! Annuler la mission y mettra fin.\"\n  STR_TLETH_P1: \"CITE ALIEN NIVEAU UN\"\n  STR_TLETH_P2: \"CITE ALIEN NIVEAU DEUX\"\n  STR_TLETH_P3: \"CITE ALIEN NIVEAU TROIS\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"PAS DE QUAI DISPONIBLE POUR LA PRODUCTION DE SUBMERSIBLE !{SMALLLINE}Tout submersible affecté à une base, transféré à une base, acheté ou construit, a besoin d'un quai.  Construisez un nouveau quai ou transférez un submersible vers une autre base.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"PAS DE QUAI DISPONIBLE POUR L'ACHAT !{SMALLLINE}Tout submersible affecté à une base, transféré à une base, acheté ou construit, a besoin d'un quai.  Construisez un nouveau quai ou transférez un submersible vers une autre base.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"PAS DE QUAI DISPONIBLE POUR LE TRANSFERT !{SMALLLINE}Tout submersible affecté à une base, transféré à une base, acheté ou construit, a besoin d'un quai.  Construisez un nouveau quai ou transférez un submersible vers une autre base.\"\n  STR_CANNOT_BUILD_HERE: \"IMPOSSIBLE DE CONSTRUIRE ICI !{SMALLLINE}Vous devez construire à côté d'une installation déjà existante.\"\n  STR_NO_FREE_ACCOMODATION: \"PAS DE LOGEMENT DE LIBRE !{SMALLLINE}La base de destination n'a pas assez de place dans ses quartiers du personnel.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"ESPACE DE TRAVAIL INSUFFISANT ! {SMALLLINE}Construisez un nouvel atelier ou réduisez le travail sur d'autres projets.\"\n  STR_NOT_ENOUGH_MONEY: \"ARGENT INSUFFISANT !\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"PAS ASSEZ DE PLACE POUR STOCKER !{SMALLLINE}Construisez un nouvel entrepôt ou transférez les stocks existants aux autres bases.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"PAS DE LOGEMENTS LIBRES !{SMALLLINE}Construisez de nouveaux baraquements ou transférez le personnel vers d'autres bases.\"\n  STR_LAUNCH_INTERCEPTION: \"LANCER INTERCEPTION\"\n  STR_CRAFT: \"VAISSEAU\"\n  STR_STATUS: \"STATUT\"\n  STR_BASE: \"BASE\"\n  STR_READY: \"PRÊT\"\n  STR_OUT: \"EN DÉPLACEMENT\"\n  STR_REPAIRS: \"RÉPARATION\"\n  STR_REFUELLING: \"RAVITAILLEMENT\"\n  STR_REARMING: \"RÉARMEMENT\"\n  STR_TARGET: \"CIBLE : {0}\"\n  STR_WAY_POINT: \"POINT DE REPÈRE\"\n  STR_ARE_YOU_SURE_CYDONIA: \"Êtes-vous sûr de vouloir envoyer ce submersible en mission à T'leth ?\"\n  STR_YES: \"OUI\"\n  STR_NO: \"NON\"\n  STR_SELECT_DESTINATION: \"SÉLECTIONNER DESTINATION\"\n  STR_CYDONIA: \"T'LETH\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"SÉLECTIONNER SITE POUR NOUVELLE BASE\"\n  STR_RETURN_TO_BASE: \"RETOUR À LA BASE\"\n  STR_SELECT_NEW_TARGET: \"SÉLECTIONNER NOUVELLE CIBLE\"\n  STR_PATROL: \"PATROUILLE\"\n  STR_STATUS_: \"STATUT> {ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"ENDOMMAGÉ - RETOUR À LA BASE\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"CARBURANT BAS - RETOUR À LA BASE\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"MISSION TERMINÉE - RETOUR À LA BASE\"\n  STR_PATROLLING: \"EN PATROUILLE\"\n  STR_TAILING_UFO: \"POURSUIVRE UN OSNI\"\n  STR_INTERCEPTING_UFO: \"INTERCEPTION DE OSNI-{0}\"\n  STR_RETURNING_TO_BASE: \"RETOUR À LA BASE\"\n  STR_DESTINATION_UC_: \"DESTINATION : {0}\"\n  STR_BASE_UC: \"BASE> {ALT}{0}\"\n  STR_SPEED_: \"VITESSE> {ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"VITESSE DE POINTE> {ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"PROFONDEUR> {ALT}{0}\"\n  STR_AIRBORNE: \"AÉRIEN\"\n  STR_VERY_LOW: \"PEU PROFOND\"\n  STR_LOW_UC: \"NORMAL\"\n  STR_HIGH_UC: \"PROFOND\"\n  STR_VERY_HIGH: \"TRÈS PROFOND\"\n  STR_FUEL: \"CARBURANT> {ALT}{0}\"\n  STR_WEAPON_ONE: \"ARME-1> {ALT}{0}\"\n  STR_NONE_UC: \"RIEN\"\n  STR_ROUNDS_: \"CARTOUCHES> {ALT}{0}\"\n  STR_WEAPON_TWO: \"ARME-2> {ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"SUBMERSIBLE\"\n  STR_BASE_: \"Base> {0}\"\n  STR_NAME_UC: \"NOM\"\n  STR_AMMO_: \"MUNITIONS> {ALT}{0}\"\n  STR_CREW: \"ÉQUIPAGE\"\n  STR_EQUIPMENT_UC: \"ÉQUIPEMENT\"\n  STR_ARMOR: \"ARMURE\"\n  STR_MAX: \"MAX> {ALT}{0}\"\n  STR_ROOKIE: \"Matelot\"\n  STR_SQUADDIE: \"Matelot de 1er classe\"\n  STR_SERGEANT: \"Enseigne\"\n  STR_CAPTAIN: \"Lieutenant\"\n  STR_COLONEL: \"Capitaine\"\n  STR_COMMANDER: \"Commandant\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Sélectionner l'Escouade pour {0}\"\n  STR_SORT_BY: \"TRIER PAR...\"\n  STR_ORIGINAL_ORDER: \"ORDRE D'ORIGINE\"\n  STR_MISSIONS2: \"MISSIONS\"\n  STR_KILLS2: \"TUÉS\"\n  STR_WOUND_RECOVERY2: \"CONVALESCENCE\"\n  STR_SPACE_AVAILABLE: \"ESPACE DISPONIBLE> {ALT}{0}\"\n  STR_SPACE_USED: \"ESPACE UTILISÉ> {ALT}{0}\"\n  STR_SPACE_USED_UC: \"ESPACE UT.\"\n  STR_RANK: \"GRADE\"\n  STR_WOUNDED: \"BLESSÉ\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Équipement pour {0}\"\n  STR_DEFENSE_VALUE: \"Valeur Défensive\"\n  STR_HIT_RATIO: \"Ratio de Tirs Réussis \"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}prêt à{NEWLINE}se poser près de{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"Commencer la Mission ?\"\n  STR_SELECT_ARMAMENT: \"Sélectionner Armement\"\n  STR_AMMUNITION_AVAILABLE: \"MUNITIONS DISPONIBLES\"\n  STR_ARMAMENT: \"ARMEMENT\"\n  STR_NOT_AVAILABLE: \"N.D.\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"SÉLECTIONNEZ ARMURE POUR{NEWLINE}{ALT}{0}\"\n  STR_TYPE: \"TYPE\"\n  STR_PLASTIC_AQUA_ARMOR_UC: \"ARMURE AQUA-PLASTIQUE\"\n  STR_ION_ARMOR_UC: \"ARMURE IONIQUE\"\n  STR_MAGNETIC_ION_ARMOR_UC: \"ARMURE IONIQUE MAGNÉTIQUE\"\n  STR_PLASTIC_AQUA_ARMOR_UFOPEDIA: \"Cette armure exploite le matériau alien récemment découvert nommé Aqua-Plastiques. Cet équipement va à coup sûr améliorer l'équilibre des forces en faveur de nos aquanautes combattant l'incursion Alienne.\"\n  STR_ION_ARMOR_UFOPEDIA: \"Cette armure intégralement renforcé par un champs d'énergie ionique accroit également la mobilité et la force de son porteur. Elle offre une excellente protection pour nos troupes.\"\n  STR_MAGNETIC_ION_ARMOR_UFOPEDIA: \"Amélioration de l'armure ionique, la technologie magnétique permet une totale liberté de mouvement en milieu aquatique.\"\n  STR_SELECT_ARMOR: \"Sélectionner Armure\"\n  STR_NORTH: \"NORD\"\n  STR_NORTH_EAST: \"NORD EST\"\n  STR_EAST: \"EST\"\n  STR_SOUTH_EAST: \"SUD EST\"\n  STR_SOUTH: \"SUD\"\n  STR_SOUTH_WEST: \"SUD OUEST\"\n  STR_WEST: \"OUEST\"\n  STR_NORTH_WEST: \"NORD OUEST\"\n  STR_SELECT_ACTION: \"SÉLECTIONNER ACTION\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"CONTINUER L'INTERCEPTION\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"POURSUIVRE SANS INTERCEPTION\"\n  STR_VERY_LARGE: \"TRÈS GRAND\"\n  STR_LARGE: \"GRAND\"\n  STR_MEDIUM_UC: \"MOYEN\"\n  STR_SMALL: \"PETIT\"\n  STR_VERY_SMALL: \"TRÈS PETIT\"\n  STR_GROUNDED: \"AMERRI\"\n  STR_DETECTED: \"Détecté\"\n  STR_SIZE_UC: \"TAILLE\"\n  STR_ALTITUDE: \"PROFONDEUR\"\n  STR_HEADING: \"CAP\"\n  STR_SPEED: \"VITESSE\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"CENTRER SUR OSNI-TEMPS=5 Sec\"\n  STR_TRACKING_LOST: \"OSNI DISPARU\"\n  STR_REDIRECT_CRAFT: \"REDIRIGER VAISSEAU\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"ALLER À LA DERNIÈRE POSITION CONNUE\"\n  STR_UFO_: \"OSNI-{0}\"\n  STR_ALIEN_BASE_: \"COLONIE ALIENNE-{0}\"\n  STR_CRASH_SITE_: \"SITE DE CRASH-{0}\"\n  STR_LANDING_SITE_: \"SITE D'AMERRISSAGE-{0}\"\n  STR_WAY_POINT_: \"POINT DE REPÈRE-{0}\"\n  STR_TERROR_SITE: \"SITE DE TERREUR-{0}\"\n  STR_ARTIFACT_SITE: \"SITE D'ARTEFACT-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}a atteint{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"En Patrouille\"\n  STR_ALIEN_ORIGINS: \"Origines Extraterrestres\"\n  STR_THE_ULTIMATE_THREAT: \"La Menace Suprême\"\n  STR_TLETH_ALIEN_CITY: \"T'leth, la Cité Alienne\"\n  STR_UFOPAEDIA: \"OVNIpédie\"\n  STR_XCOM_CRAFT_ARMAMENT: \"VAISSEAUX ET ARMEMENTS X-COM\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"SYSTÈMES D'ARMES SUBMERSIBLE\"\n  STR_WEAPONS_AND_EQUIPMENT: \"ÉQUIPEMENT GÉNÉRAL\"\n  STR_ALIEN_ARTIFACTS: \"ARTEFACTS AQUATIQUES\"\n  STR_BASE_FACILITIES: \"INSTALLATIONS X-COM\"\n  STR_ALIEN_LIFE_FORMS: \"FORMES DE VIES ALIENNES\"\n  STR_ALIEN_RESEARCH_UC: \"TECHNOLOGIE ALIENNE\"\n  STR_UFO_COMPONENTS: \"NOUVELLES TECHNOLOGIES SUBMERSIBLES\"\n  STR_UFOS: \"OSNIS\"\n  STR_SELECT_ITEM: \"SÉLECTIONNER ARTICLE\"\n  STR_ACCELERATION: \"ACCÉLÉRATION> {ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"CAPACITÉ CARBURANT> {ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"NACELLES D'ARMES> {ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"BLINDAGE> {ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"ESPACE SOUTE> {ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"CAPACITÉ SAS> {ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Dégâts\"\n  STR_RANGE: \"Portée\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Précision\"\n  STR_RE_LOAD_TIME: \"Temps de Recharge\"\n  STR_SECONDS: \"{0}s\"\n  STR_DAMAGE_ARMOR_PIERCING: \"PERFORANT\"\n  STR_DAMAGE_INCENDIARY: \"PHOSPHORESCENT\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"EXPLOSIF\"\n  STR_DAMAGE_LASER_BEAM: \"RAYON GAUSS\"\n  STR_DAMAGE_PLASMA_BEAM: \"RAYON SONIQUE\"\n  STR_DAMAGE_STUN: \"GEL\"\n  STR_DAMAGE_MELEE: \"MÊLÉE\"\n  STR_DAMAGE_ACID: \"ACIDE\"\n  STR_DAMAGE_SMOKE: \"FUMÉE\"\n  STR_SHOT_TYPE: \"TYPE\"\n  STR_ACCURACY_UC: \"PRÉCISION\"\n  STR_TIME_UNIT_COST: \"COÛT UT\"\n  STR_DAMAGE_UC: \"DÉGÂTS\"\n  STR_AMMO: \"MUNITIONS\"\n  STR_SHOT_TYPE_AUTO: \"Automatique\"\n  STR_SHOT_TYPE_SNAP: \"Rapide\"\n  STR_SHOT_TYPE_AIMED: \"Précis\"\n  STR_CONSTRUCTION_TIME: \"Temps de Construction\"\n  STR_CONSTRUCTION_COST: \"Coût de Construction\"\n  STR_MAINTENANCE_COST: \"Coût d'Entretien\"\n  STR_LOW: \"Basse\"\n  STR_MEDIUM: \"Moyenne\"\n  STR_HIGH: \"Haute\"\n  STR_CRAFT_WEAPON: \"Arme du Submersible\"\n  STR_CRAFT_AMMUNITION: \"Munitions du Submersible\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Système d'Arme Submersible\"\n  STR_WEAPON: \"Arme\"\n  STR_AMMUNITION: \"Munitions\"\n  STR_EQUIPMENT: \"Équipement\"\n  STR_ALIEN_CORPSE: \"Corps Alien\"\n  STR_UFO_COMPONENT: \"Composant OSNI\"\n  STR_PERSONAL_ARMOR: \"Armure Personnelle\"\n  STR_RAW_MATERIALS: \"Matières Premières\"\n  STR_HWP_SOLID_HARPOON_BOLTS: \"Harpon Renforcé SAS\"\n  STR_ALIEN: \"Alien\"\n  STR_AQUATOID: \"Aquatoïde\"\n  STR_GILLMAN: \"Homme-poisson\"\n  STR_LOBSTERMAN: \"Homme-Homard\"\n  STR_TASOTH: \"Tasoth\"\n  STR_CALCINITE: \"Calcinite\"\n  STR_DEEP_ONE: \"Profond\"\n  STR_BIODRONE: \"Bio-drone\"\n  STR_TENTACULAT: \"Tentaculaire\"\n  STR_TRISCENE: \"Triscène\"\n  STR_HALLUCINOID: \"Hallucinoïde\"\n  STR_XARQUID: \"Xarquide\"\n  STR_ZOMBIE: \"Zombi\"\n  STR_LIVE_COMMANDER: \"Commandant\"\n  STR_LIVE_NAVIGATOR: \"Navigateur\"\n  STR_LIVE_MEDIC: \"Médecin\"\n  STR_LIVE_TECHNICIAN: \"Technicien\"\n  STR_LIVE_SQUAD_LEADER: \"Chef d'Escouade\"\n  STR_LIVE_SOLDIER: \"Soldat\"\n  STR_LIVE_TERRORIST: \"Terroriste\"\n  STR_AQUATOID_COMMANDER: \"Commandant Aquatoïde\"\n  STR_AQUATOID_NAVIGATOR: \"Navigateur Aquatoïde\"\n  STR_AQUATOID_MEDIC: \"Docteur Aquatoïde\"\n  STR_AQUATOID_TECHNICIAN: \"Technicien Aquatoïde\"\n  STR_AQUATOID_SQUAD_LEADER: \"Chef d'Escouade Aquatoïde\"\n  STR_AQUATOID_SOLDIER: \"Soldat Aquatoïde\"\n  STR_GILLMAN_COMMANDER: \"Commandant homme-poisson\"\n  STR_GILLMAN_TECHNICIAN: \"Technicien homme-poisson\"\n  STR_GILLMAN_SQUAD_LEADER: \"Chef d'Escouade homme-poisson\"\n  STR_GILLMAN_SOLDIER: \"Soldat homme-poisson\"\n  STR_LOBSTERMAN_COMMANDER: \"Commandant Homme-Homard\"\n  STR_LOBSTERMAN_NAVIGATOR: \"Navigateur Homme-Homard\"\n  STR_LOBSTERMAN_TECHNICIAN: \"Technicien Homme-Homard\"\n  STR_LOBSTERMAN_SQUAD_LEADER: \"Chef d'Escouade Homme-Homard\"\n  STR_LOBSTERMAN_SOLDIER: \"Soldat Homme-Homard\"\n  STR_TASOTH_SQUAD_LEADER: \"Chef d'Escouade Tasoth\"\n  STR_TASOTH_SOLDIER: \"Soldat Tasoth\"\n  STR_CALCINITE_TERRORIST: \"Terroriste Calcinite\"\n  STR_DEEP_ONE_TERRORIST: \"Terroriste Profond\"\n  STR_BIODRONE_TERRORIST: \"Terroriste Bio-drone\"\n  STR_TENTACULAT_TERRORIST: \"Terroriste Tentaculaire\"\n  STR_TRISCENE_TERRORIST: \"Terroriste Triscène\"\n  STR_HALLUCINOID_TERRORIST: \"Terroriste Hallucinoïde\"\n  STR_XARQUID_TERRORIST: \"Terroriste Xarquide\"\n  STR_ION_BEAM_ACCELERATORS: \"Accélérateurs à Rayons Ioniques\"\n  STR_MAGNETIC_NAVIGATION: \"Navigation Magnétique\"\n  STR_ALIEN_SUB_CONSTRUCTION: \"Plans de construction d'OSNIS\"\n  STR_ALIEN_CRYOGENICS: \"Cryogénie Alienne\"\n  STR_ALIEN_CLONING: \"Clonage Alien\"\n  STR_ALIEN_LEARNING_ARRAYS: \"Zone d'apprentissage Alienne\"\n  STR_ALIEN_IMPLANTER: \"Implanteur Alien\"\n  STR_EXAMINATION_ROOM: \"Salle d'Examen\"\n  STR_AQUA_PLASTICS: \"Aqua-plastiques\"\n  STR_ALIEN_REANIMATION_ZONE: \"Chambre de Réanimation Alienne\"\n  STR_PLASTIC_AQUA_ARMOR: \"Armure Aqua-Plastiques\"\n  STR_ION_ARMOR: \"Armure Ionique\"\n  STR_MAGNETIC_ION_ARMOR: \"Armure Ionique Magnétique\"\n  STR_HWP_AQUA_JET_MISSILES: \"Torpilles Aqua-Jet SAS\"\n  STR_HWP_DISPLACER_PWT: \"Torpille Ondes Perturbations SAS\"\n  STR_GAUSS_TECH: \"Technologie Gauss\"\n  STR_NEW_FIGHTER_FLYING_SUB: \"Nouveau Chasseur Submersible\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Nouveau Chasseur-Transporteur\"\n  STR_THE_LATEST_FLYING_SUB: \"Le Submersible Volant Ultime\"\n  STR_ARMOR_PIERCING: \"PERFORANT\"\n  STR_COELACANTH_GAS_CANNON: \"Coelacanthe/Harpon\"\n  STR_COELACANTH_AQUA_JET: \"Coelacanthe/Aqua-Jet\"\n  STR_COELACANTH_GAUSS: \"Coelacanthe/Gauss\"\n  STR_DISPLACER_SONIC: \"Déplaceur/Sonique\"\n  STR_DISPLACER_PWT: \"Déplaceur/T.O.P\"\n  STR_AJAX_LAUNCHER: \"Lanceur Ajax\"\n  STR_DUP_HEAD_LAUNCHER: \"Lanceur à T.U.A\"\n  STR_CRAFT_GAS_CANNON: \"Canon à Gaz\"\n  STR_PWT_CANNON: \"Canon T.O.P\"\n  STR_GAUSS_CANNON: \"Canon Gauss\"\n  STR_GAUSS_CANNON_AMMO: \"Munition de Canon Gauss\"\n  STR_SONIC_OSCILLATOR: \"Oscillateur Sonique\"\n  STR_AJAX_TORPEDOES: \"Torpille Ajax\"\n  STR_DUP_HEAD_TORPEDOES: \"Torpille à T.U.A\"\n  STR_CRAFT_GAS_CANNON_ROUNDS_X50: \"Munitions de Gaz (x50)\"\n  STR_SONIC_WAVE: \"Onde Sonique\"\n  STR_PULSE_WAVE_TORPEDOES: \"Munition T.O.P\"\n  STR_SOLDIER: \"Aquanaute\"\n  STR_SCIENTIST: \"Scientifique\"\n  STR_ENGINEER: \"Ingénieur\"\n  STR_NORTH_ATLANTIC: \"Atlantique Nord\"\n  STR_SOUTH_ATLANTIC: \"Atlantique Sud\"\n  STR_NORTH_PACIFIC: \"Pacifique Nord\"\n  STR_SOUTH_PACIFIC: \"Pacifique Sud\"\n  STR_MEDITERRANEAN: \"Méditerranée\"\n  STR_SOUTH_CHINA_SEA: \"Mer de Chine du Sud\"\n  STR_INDIAN_OCEAN: \"Océan Indien\"\n  STR_THE_EAST_SEA: \"Mer du Japon\"\n  STR_NORTH_SEA: \"Mer du Nord\"\n  STR_CARRIBEAN: \"Caraïbes\"\n  STR_ANTARCTIC: \"Antarctique\"\n  STR_ARCTIC: \"Arctique\"\n  STR_EURASIA: \"Eurasie\"\n  STR_NORTH_AMERICA: \"Amérique du Nord\"\n  STR_AFRICA: \"Afrique\"\n  STR_MAXIMUM_SPEED: \"Vitesse Maximum\"\n  STR_TRANSMISSION_RESOLVER_UC: \"DÉCODEUR DE TRANSMISSIONS\"\n  STR_TRITON: \"TRITON\"\n  STR_HAMMERHEAD: \"REQUIN-MARTEAU\"\n  STR_LEVIATHAN: \"LEVIATHAN\"\n  STR_BARRACUDA: \"BARRACUDA\"\n  STR_MANTA: \"MANTA\"\n  STR_UFO: \"OSNI\"\n  STR_AJAX: \"AJAX\"\n  STR_DUP_HEAD: \"OGIVE T.U.A\"\n  STR_CRAFT_GAS_CANNON_UC: \"CANON A GAZ\"\n  STR_PWT_CANNON_UC: \"CANON T.O.P\"\n  STR_GAUSS_CANNON_UC: \"CANON GAUSS\"\n  STR_SONIC_OSCILLATOR_UC: \"OSCILLATEUR SONIQUE\"\n  STR_DAMAGE_CAPACITY: \"Capacité de Dégâts\"\n  STR_WEAPON_POWER: \"Puissance d'Arme\"\n  STR_WEAPON_RANGE: \"Portée de l'Arme\"\n  STR_AIR_LOCK: \"Sas d’Accès\"\n  STR_LABORATORY: \"Laboratoire\"\n  STR_WORKSHOP: \"Atelier\"\n  STR_STANDARD_SONAR: \"Sonar Standard\"\n  STR_WIDE_ARRAY_SONAR: \"Sonar à Large Bande\"\n  STR_TORPEDO_DEFENSES: \"Défenses à Torpilles\"\n  STR_GENERAL_STORES: \"Entrepôts\"\n  STR_ALIEN_CONTAINMENT: \"Prison des Aliens\"\n  STR_GAUSS_DEFENSES: \"Défenses Gauss\"\n  STR_SONIC_DEFENSES: \"Défenses Sonique\"\n  STR_PWT_DEFENSES: \"Défenses T.O.P\"\n  STR_BOMBARDMENT_SHIELD: \"Bouclier Anti-Bombardements\"\n  STR_MC_GENERATOR: \"Générateur de C.M.\"\n  STR_MC_LAB: \"Laboratoire de C.M.\"\n  STR_TRANSMISSION_RESOLVER: \"Décodeur de Transmissions\"\n  STR_SUB_PEN: \"Quai à Submersibles\"\n  STR_USA: \"ETATS UNIS\"\n  STR_ALASKA: \"ALASKA\"\n  STR_EU_SYNDICATE: \"UNION EUROPÉENNE\"\n  STR_ARABIAN_BLOC: \"BLOC ARABE\"\n  STR_EGYPTIAN_CARTEL: \"CARTEL ÉGYPTIEN\"\n  STR_AFRICA_CORP: \"CORPORATION AFRICAINE\"\n  STR_BRAZILIAN_UNION: \"UNION BRÉSILIENNE\"\n  STR_NEW_MEXICO: \"NOUVEAU MEXIQUE\"\n  STR_ASIAN_COALITION: \"COALITION ASIATIQUE\"\n  STR_SCANDINAVIA: \"SCANDINAVIE\"\n  STR_NEO_JAPAN: \"NEO-JAPON\"\n  STR_FREE_CHINA: \"CHINE LIBRE\"\n  STR_AUSTRALASIA: \"AUSTRALASIE\"\n  STR_FED_KOREA: \"CORÉE FÉDÉRALE\"\n  STR_EURASIA_UC: \"EURASIE\"\n  STR_ICELANDIC_UNION: \"UNION ISLANDAISE\"\n  STR_TANK: \"Système d'Arme Submersible\"\n  STR_CIVILIAN: \"Civil\"\n  STR_JAN: \"Jan\"\n  STR_FEB: \"Fév\"\n  STR_MAR: \"Mar\"\n  STR_APR: \"Avr\"\n  STR_MAY: \"Mai\"\n  STR_JUN: \"Jui\"\n  STR_JUL: \"Juil\"\n  STR_AUG: \"Aoû\"\n  STR_SEP: \"Sep\"\n  STR_OCT: \"Oct\"\n  STR_NOV: \"Nov\"\n  STR_DEC: \"Déc\"\n  STR_INTERNATIONAL_RELATIONS: \"Relations Internationales\"\n  STR_COUNTRY: \"Pays\"\n  STR_FUNDING: \"Budget\"\n  STR_CHANGE: \"Écart\"\n  STR_WEAPON_SYSTEMS: \"SYSTÈMES D'ARME\"\n  STR_HWPS: \"SAS\"\n  STR_DAMAGE_UC_: \"DÉGÂTS> {ALT}{0}\"\n  STR_AIR_LOCK_UFOPEDIA: \"Le sas d'accès permet à l'équipement et au personnel d'être transféré vers une base ou d'en sortir. C'est toujours la première installation à être construite sur un nouveau site. Le sas d'accès est vulnérable aux intrusions de toutes les forces potentiellement hostiles.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Chaque quartier du personnel fournis l'espace vital pour 50 personnes. Les installations sont rudimentaires mais fonctionnelles.\"\n  STR_LABORATORY_UFOPEDIA: \"Jusqu'à 50 scientifiques peuvent travailler dans un laboratoire. Les laboratoires sont équipés des dernières technologies pour les recherches sur les matériaux, la biochimie et l'armement. X-Com a accès à l'ensemble des meilleurs laboratoires du monde, aussi bien civils que militaires.\"\n  STR_WORKSHOP_UFOPEDIA: \"Un atelier contient tout l'équipement nécessaire pour fabriquer l'équipement basé sur les derniers designs fournis par les laboratoires. Jusqu'à 50 Techniciens peuvent occuper un atelier, mais les objets en construction prennent aussi de la place.\"\n  STR_STANDARD_SONAR_UFOPEDIA: \"Un système de sonars standard a une portée effective de 450 miles nautiques à toutes les profondeurs et est lié à un réseau de satellites géo-stationnaires pour les analyses en surface. Chaque scanner a 10% de chances de détecter un submersible ou un appareil volant toutes les 30 minutes, la durée d'un balayage.\"\n  STR_WIDE_ARRAY_SONAR_UFOPEDIA: \"Un système de sonars à large bandes a une portée effective de 700 miles nautiques à toutes les profondeurs et est lié à un réseau de satellites géo-stationnaires pour les analyses en surface. Chaque scanner a 20% de chances de détecter un submersible ou un appareil volant toutes les 30 minutes, la durée d'un balayage.\"\n  STR_TORPEDO_DEFENSES_UFOPEDIA: \"Les systèmes de défense Torpilles fournissent une protection contre les attaques de submersibles hostiles qui tentent de s'arrimer à la base.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"Tous les équipements, systèmes d'armes, munitions, matériaux récupérés et  les SAS sont stockées ici, y compris l'équipement assigné aux submersibles dans les hangars.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"Les Aliens vivants nécessitent des installations spéciales pour les garder. Ces unités maintiennent leur systèmes vitaux et réduisent leur potentiel de combat à zéro. Ces installation de confinement permettent d'abriter jusqu’à 10 formes de vies simultanément dans ses unités de confinement.\"\n  STR_GAUSS_DEFENSES_UFOPEDIA: \"Les défenses Gauss fournissent la protection la plus récente et la plus efficace contre les attaques des submersibles hostiles.\"\n  STR_SONIC_DEFENSES_UFOPEDIA: \"Les défenses à Oscillateur Sonique fournissent une protection puissante et efficace contres les agresseurs.\"\n  STR_PWT_DEFENSES_UFOPEDIA: \"Les Torpilles à Ondes de Perturbation fournissent la défense la plus efficace contres les attaques Aliennes. Ces missiles ont une tête extrêmement dense qui peut pénétrer toutes les armures connues. Les ondes magnétiques qu'elles produisent désactivent les défenses électroniques.\"\n  STR_BOMBARDMENT_SHIELD_UFOPEDIA: \"Le bouclier Anti-Bombardements protège la base des OSNIS voulant s’arrimer et génère un champ de résonance qui les repousse le temps que les systèmes de défense soient en mesure d'effectuer un deuxième tir, doublant ainsi leurs efficacité.\"\n  STR_MC_GENERATOR_UFOPEDIA: \"Maintenant que l'on sait que les OSNIS utilisent la technologie du Contrôle Moléculaire pour détecter des signes de vies, nous allons utiliser des émetteurs C.M. inversés pour créer un bouclier impénétrable afin de tromper les Aliens et rendre nos bases furtives.\"\n  STR_MC_LAB_UFOPEDIA: \"Le laboratoire de Contrôle Moléculaire peut poser des implants et entrainer un maximum de 10 aquanautes à la fois. Un entrainement intensif leur permet d'utiliser leurs implants. Les aptitudes liées à l'implant s'utilisent en tandem avec un Appareil Moléculaire et peuvent être utilisées pour lancer des attaques pendant les combats.\"\n  STR_TRANSMISSION_RESOLVER_UFOPEDIA: \"Les communications Aliennes utilisent le réseau d'implants de Contrôle Moléculaire construit par ces derniers. Le décodeur de transmissions intercepte les transmissions des OSNIS et décodent les informations : le type d'OSNI, la race de l'équipage ainsi que la mission en cours.\"\n  STR_SUB_PEN_UFOPEDIA: \"Chaque Quai peut accueillir un submersible. Ces installations fournissent la maintenance, le carburant et les réparations pour les submersibles de la flotte d'X-Com. Chaque submersible volant stationné à la base doit être assigné à un Quai libre qui ne sera pas utilisé par les autres, même si le submersible assigné part en mission.\"\n  STR_DART_PISTOL_UFOPEDIA: \"Le fusil à fléchette d'X-COM est une unité petits, précise et puissante avec son chargeur de 12 fléchettes creuses. Les fléchettes sont tirées par une cartouche de gaz dans la capsule des munitions.\"\n  STR_JET_HARPOON_UFOPEDIA: \"Ce fusil aquatique est précis et puissant, tirant des harpons en acier creux par packs de 10. Chaque harpon a son propre réservoir de gaz.\"\n  STR_GAS_CANNON_UFOPEDIA: \"En poids-lourd des armes utilisant la technologie du gaz, ce canon tire de solides carreaux, certains sont explosifs et d'autres au phosphore. L'une des armes favorites des aquanautes expérimentés.\"\n  STR_HYDRO_JET_CANNON_UFOPEDIA: \"Les Canons Hydro-Jet sont un système d'armement lourd pour l'infanterie. Le canon tire des mini-torpilles alimentées au magnésium. Bien que puissant, le Canon Hydro-jet est maladroit et peu pratique, exclusivement adapté à l'usage aquatique.\"\n  STR_TORPEDO_LAUNCHER_UFOPEDIA: \"En vrai poids-lourd de l'armement, ce grand lanceur tire 3 types de torpilles, chacune possédant son unité de propulsion. Une arme dévastatrice avec son rechargement manuel comme seul inconvénient. Les munitions disponibles incluent des torpilles explosives de faible et forte intensité ainsi que des torpilles au phosphore, exclusivement pour un usage aquatique.\"\n  STR_GAUSS_PISTOL_UFOPEDIA: \"Le Pistolet Gauss utilise la technologie de l'accélération des particules, un développement récent dans l'armement moderne. Il est rapide, précis et fonctionne aussi bien sous l'eau qu'en surface. La technologie Gauss a été développée à partir des technologies Plasma apprises lors de la dernière guerre.\"\n  STR_GAUSS_PISTOL_CLIP_UFOPEDIA: \"Le Pistolet Gauss utilise la technologie de l'accélération des particules, un développement récent dans l'armement moderne. Il est rapide, précis et fonctionne aussi bien sous l'eau qu'en surface. La technologie Gauss a été développée à partir des technologies Plasma apprises lors de la dernière guerre.\"\n  STR_GAUSS_RIFLE_UFOPEDIA: \"Un cran au dessus du Pistolet Gauss, la Carabine Gauss a un sacré punch avec ses accélérateurs de particules jumelés. Remplaçant l'ancien système au Plasma alimenté à l'élérium par un micro-accélérateur à particules qui génère un flux d'anti-protons.\"\n  STR_GAUSS_RIFLE_CLIP_UFOPEDIA: \"Un cran au dessus du Pistolet Gauss, la Carabine Gauss a un sacré punch  avec ses accélérateurs de particules jumelés. Remplaçant l'ancien système au Plasma alimenté à l'élérium par un micro-accélérateur à particules qui génère un flux d'anti-protons.\"\n  STR_HEAVY_GAUSS_UFOPEDIA: \"Le Canon Gauss Lourd est encombrant mais extrêmement efficace. Il opère avec 3 accélérateurs de particules et est virtuellement inarrêtable. Le flux d'anti-protons est confiné dans une cartouche en Gallium/Arsenic qui implose à l'impact en libérant de l'anti-matière.\"\n  STR_HEAVY_GAUSS_CLIP_UFOPEDIA: \"Le Canon Gauss Lourd est encombrant mais extrêmement efficace. Il opère avec 3 accélérateurs de particules et est virtuellement inarrêtable. Le flux d'anti-protons est confiné dans une cartouche en Gallium/Arsenic qui implose à l'impact en libérant de l'anti-matière.\"\n  STR_MAGNA_BLAST_GRENADE_UFOPEDIA: \"Cette grenade standard possède un minuteur précis et sophistiqué pour un contrôle de haute précision.\"\n  STR_DYE_GRENADE_UFOPEDIA: \"Les grenades colorantes sont des objets à double usage, utiles pour offrir une couverture en terrains ouverts. Elles fonctionnent aussi bien dans l'eau qu'en surface, le colorant est éjecté sous la forme d'un nuage de particules, produisant l'équivalent d'un jet d'encre de poulpe sous l'eau ou d'un épais nuage en surface.\"\n  STR_PARTICLE_DISTURBANCE_GRENADE_UFOPEDIA: \"Une grenade de proximité qui se lance comme une grenade ordinaire, mais ne se déclenchera qu'en cas de mouvement rapproché par rapport à l'endroit précis où elle est déployée. Il faut de l'expérience et de la pratique pour vraiment en tirer partie.\"\n  STR_MAGNA_PACK_EXPLOSIVE_UFOPEDIA: \"Cet explosif devrait être utilisé exclusivement pour la démolition. Quoique, par expérience, ces puissants explosifs sont idéaux pour mettre les Aliens au tapis. Le rayon de l'explosion est vaste, il faut donc s'assurer que les aquanautes soient à l'abri.\"\n  STR_PARTICLE_DISTURBANCE_SENSOR_UFOPEDIA: \"Ce nouvel appareil utilise une gamme de détecteurs et de systèmes informatiques pour identifié les unités ennemies en mouvement. Cliquez sur l'icône du Détecteur à Perturbations, sélectionnez 'Utiliser le Détecteur', l'écran du Détecteur montrera une flèche en son centre, elle désigne l'orientation de l'aquanaute (le Nord est en haut). Les signaux désignent les unités qui se sont déplacé récemment. Les grandes unités, ou celles se déplaçant rapidement, produiront de plus grand signaux. Les unités restées statiques ne seront pas affichées.\"\n  STR_MEDI_KIT_UFOPEDIA: \"Pour utiliser cet objet vous devez vous placer près de l'aquanaute blessé ou sur son corps s'il est assommé.{NEWLINE}SOIGNER> Les parties du corps blessées sont indiquées en rouge, sélectionnez en une et cliquez sur le bouton 'Soigner', une blessure mortelle sera soignée et une fraction de la santé sera rétablie.{NEWLINE}STIMULANT> Rétablie l'énergie et ranime les aquanautes assommés. Pour ranimer un aquanaute inconscient vous devez vous tenir directement sur son corps.{NEWLINE}CALMANT> Rétablie le moral des aquanautes blessés.\"\n  STR_MC_DISRUPTOR_UFOPEDIA: \"Le Perturbateur est l'arme ultime de la technologie C.M.,  exclusivement destiné aux aquanautes préalablement initiés à l'usage du Contrôle Moléculaire.  Cliquez sur le Perturbateur, sélectionnez le type d'attaque, et sélectionnez une cible avec le curseur. Il y a deux types d'attaque C.M. : {NEWLINE}BROUILLER L'IMPLANT> En cas de succès, la cible est perturbée et peut paniquer. {NEWLINE}CONTRÔLER L'IMPLANT> En cas de succès, vous gagnez le contrôle immédiat de l'unité ennemie.\"\n  STR_THERMAL_TAZER_UFOPEDIA: \"Cet appareil s'utilise exclusivement en mêlée, mais il assommera un organisme vivant sans le tuer en gelant la créature visée.\"\n  STR_VIBRO_BLADE_UFOPEDIA: \"La Vibro-Lame est une longue lame en titane aiguisée qui tourne à une fréquence de 6000 tours/min, cet appareil peut venir à bout des armures de plongée les plus résistantes. La source de puissance est une invention Alienne, avant son étude toutes nos tentatives de reproduire cet objet se sont soldées par des échecs, nos lames tournant trop lentement ou explosant sous la pression.\"\n  STR_THERMIC_LANCE_UFOPEDIA: \"La Lance Thermique est, en toute logique, l'étape suivante dans le développement de la technologie des Vibro-Lames. La lame a une haute fréquence de tours et une source de puissance au Zrbite la surchauffe pour découper les armures, comme un couteau chaud dans du beurre.\"\n  STR_HEAVY_THERMIC_LANCE_UFOPEDIA: \"La Lance Thermique Lourde est une version plus puissante de la LT.  Face à ses sources de chaleur jumelées et sa vitesse de rotation extrêmement élevée, tous les matériaux sont virtuellement vulnérables à la Lance Thermique Lourde.\"\n  STR_SONIC_CANNON_UFOPEDIA: \"Le Canon Sonique est la plus puissante des armes Soniques. Possédant un oscillateur sonique à plus hautes fréquences et une chambre de réverbération plus grande que la Carabine Blasta-S. Le Canon possède aussi un système de détonation à impulsions qui module les ondes ultra-soniques pour produire un Choc Sonique plus efficace.\"\n  STR_CANNON_POWER_CLIP_UFOPEDIA: \"Cet appareil compacte fournis des munitions à un Canon Sonique. Il contient une petite quantité de Zrbite.\"\n  STR_SONIC_BLASTA_RIFLE_UFOPEDIA: \"Un appareil Sonique de puissance plus élevée. Même l'acier enrichi en fibres de carbone est vulnérable à cette arme. Le petit émetteur d'ondes est amélioré par un amplificateur aux super-conducteurs pour augmenter la puissance de cette arme.\"\n  STR_BLASTA_POWER_CLIP_UFOPEDIA: \"Ce petit objets est utilisé comme source de puissance pour une Carabine Blasta-Sonique, une arme Alienne puissante, et contient une petite quantité de Zrbite.\"\n  STR_SONIC_PISTOL_UFOPEDIA: \"Les Pistolets Soniques sont des armes Aliennes basées sur le principe des ondes ultra-soniques, elles peuvent transformer les os en gelée en l'espace de quelques secondes. L'oreille humaine n'est pas sensible aux ondes Ultra-Soniques.\"\n  STR_PISTOL_POWER_CLIP_UFOPEDIA: \"Source de puissance pour le Pistolet Sonique Alien. Contient du Zrbite, la source de puissance des Aliens.\"\n  STR_DISRUPTOR_PULSE_LAUNCHER_UFOPEDIA: \"C'est une arme Alienne exclusivement aquatique qui lance des 'Projectiles à Ondes de Perturbations' guidés et auto-propulsés. Quand vous cliquez sur 'Tirer', vous pouvez générer des points de passage que le Projectile s'efforcera de suivre. Quand vous aurez positionné le nombre de points de passages désiré, cliquez sur l’icône de lancement.\"\n  STR_DISRUPTOR_AMMO_UFOPEDIA: \"Cet appareil est un Projectile à Ondes de Perturbations doté d'un système de guidage informatique intégré. Il est tiré à partir d'un Lanceur à Ondes de Perturbations.\"\n  STR_THERMAL_SHOK_LAUNCHER_UFOPEDIA: \"Un petit Lanceur à Chocs Thermiques qui tire des bombes chimiques à effet gel. Très utiles pour capturer des Aliens vivants.\"\n  STR_THERMAL_SHOK_BOMB_UFOPEDIA: \"La Bombe à Chocs Thermiques est utilisée pour capturer des humains vivants, mais est tout aussi efficace contre la plupart des races Aliennes. Elle est tirée à partir d'un Lanceur à Chocs Thermiques.\"\n  STR_SONIC_PULSER_UFOPEDIA: \"Cet appareil fonctionne de la même manière qu'une grenade standard, sauf qu'elle est bien plus puissante. la grenade ne lance qu'une seule impulsion sonique qui est émise simultanément dans toutes les directions.\"\n  STR_MC_READER_UFOPEDIA: \"Lors des autopsies nous avons découvert des petits implants introduits chirurgicalement. Ce dispositif de contrôle est conçu par les Aquatoïdes afin de récolter des informations directement depuis le champ de bataille, même sur de grandes distances. Le Lecteur de Contrôle Moléculaire est un appareil de communication alien qui est utilisée pour prendre l'information directement des implants C.M.  Les unités X-Com peuvent utiliser cette technique durant le combat pour connaître les caractéristiques des extraterrestres. Cliquez sur l'option 'utiliser', puis sur un extraterrestre.\"\n  STR_SURVEY_SHIP: \"Enquêteur\"\n  STR_ESCORT: \"Escorteur\"\n  STR_CRUISER: \"Croiseur\"\n  STR_HEAVY_CRUISER: \"Croiseur Lourd\"\n  STR_HUNTER: \"Chasseur\"\n  STR_BATTLESHIP: \"Destroyer\"\n  STR_DREADNOUGHT: \"Cuirassé\"\n  STR_FLEET_SUPPLY_CRUISER: \"Chaland\"\n  MAP_SEABED: \"Fonds Sablonneux\"\n  MAP_PIPES: \"Centres de Recherche\"\n  MAP_PLANE: \"Épaves d'Avions\"\n  MAP_ATLAN: \"Atlantide\"\n  MAP_MU: \"Temples Mayas\"\n  MAP_GAL: \"Épaves de Galions\"\n  MAP_MSUNK: \"Épaves de Paquebots\"\n  MAP_VOLC: \"Fonds Volcaniques\"\n  MAP_CORAL: \"Massifs Coralliens\"\n  MAP_PORT: \"Zones Portuaires\"\n  MAP_ISLAND: \"Iles\"\n  MAP_CARGO: \"Cargo\"\n  MAP_LINERT: \"Vaisseau Amiral P1\"\n  MAP_LINERB: \"Vaisseau Amiral P2\"\n  MAP_ALART: \"Artefact P1\"\n  MAP_GRUNGE: \"Artefact P2\"\n  MAP_ENTRY: \"Colonie P1\"\n  MAP_A_BASE: \"Colonie P2\"\n  MAP_ALSHIP: \"T'leth P1\"\n  MAP_LEVEL: \"T'leth P2\"\n  MAP_CRYPT: \"T'leth P3\"\n  MAP_XBASES: \"Base X-Com\"\n  STR_MIXED_CREW: \"Équipage Mixte\"\n  STR_MIXED_CREW_2: \"Équipage Mixte 2\"\n  STR_RATING: \"ÉVALUATION> {0}\"\n  STR_RATING_TERRIBLE: \"TERRIBLE !\"\n  STR_RATING_POOR: \"MÉDIOCRE !\"\n  STR_RATING_OK: \"PASSABLE\"\n  STR_RATING_GOOD: \"BIEN !\"\n  STR_RATING_EXCELLENT: \"EXCELLENT !\"\n  STR_SCORE: \"SCORE\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"RAPPORT MENSUEL X-COM\"\n  STR_MONTH: \"Mois> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"Le Comité des Organisations participant au financement est jusqu'ici satisfait de vos progrès. \"\n  STR_COUNCIL_IS_VERY_PLEASED: \"Le Comité des Organisations participant au financement est très satisfait de vos excellents progrès. Continuez comme ça. \"\n  STR_COUNCIL_IS_DISSATISFIED: \"Le Comité des Organisations participant au financement n'est pas satisfait de votre travail. Vous devez améliorer votre efficacité à combattre la menace alienne, sinon, il risque de mettre fin au projet. \"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"Vous n'avez pas réussi à combattre l'invasion alienne et le conseil des nations participant au financement a malheureusement décidé de cesser le financement d'X-Com. Chaque nation va s'occuper elle-même du problème comme elle l'entend. Nous ne pouvons qu'espérer arriver à un accord avec ces forces antiques, et souhaiter que la population s'entende avec les visiteurs aquatiques.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} est particulièrement satisfait de votre aptitude à gérer la menace dans ses mers et a accepté d'augmenter son financement. \"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} sont particulièrement satisfaits de vos progrès dans le combat contre les incursions aliennes dans leurs mers, et ont accepté d'augmenter votre budget. \"\n  STR_COUNTRIES_COMMA: \"{0}, {1} \"\n  STR_COUNTRIES_AND: \"{0} et {1} \"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} est mécontent de votre aptitude à contenir l'activité alien dans ses mers, et a décidé de réduire sa contribution financière. \"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} sont mécontents de votre aptitude à contenir l'activité alien dans leurs mers, et ont décidé de réduire leur contribution financière. \"\n  STR_KNOTS: \"{0} nœuds \"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} a signé un pacte de coopération avec les forces aliens et s'est retiré du projet. \"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} ont signé un pacte de coopération avec les forces aliens et se sont retirés du projet. \"\n  STR_MONTHLY_RATING: \"Évaluation Mensuelle> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Évolution du Financement> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"L'organisation n'est pas satisfaite de votre situation financière. Vous devez réduire vos dettes en dessous d'1 million de $ ou le projet sera terminé.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"LES TRANSMISSIONS A SOUS-PARTICULES SONT DÉCODÉES\"\n  STR_CRAFT_TYPE: \"TYPE OSNI\"\n  STR_RACE: \"RACE\"\n  STR_MISSION: \"MISSION\"\n  STR_ZONE: \"ZONE\"\n  STR_ALLOCATE_RESEARCH: \"Allouer Recherche\"\n  STR_ALLOCATE_MANUFACTURE: \"Allouer Fabrication\"\n  STR_AZORES: \"Les Açores\"\n  STR_REYKJAVIK: \"Reykjavík\"\n  STR_BERMUDA: \"Les Bermudes\"\n  STR_NEW_YORK: \"New York\"\n  STR_BOSTON: \"Boston\"\n  STR_FORT_SEVERN: \"Fort Severn\"\n  STR_DAKAR: \"Dakar\"\n  STR_RECIFE: \"Recife\"\n  STR_ACCRA: \"Accra\"\n  STR_ASCENSION_ISLAND: \"L'Île de l'Ascension\"\n  STR_TRINIDADE_ISLAND: \"Trindade et Martin Vaz\"\n  STR_FALKLAND_ISLAND: \"Les Malouines\"\n  STR_CANARY_ISLANDS: \"Les Canaries\"\n  STR_ANCHORAGE: \"Anchorage\"\n  STR_ST_LAWRENCE_ISLAND: \"L'Île Saint-Laurent\"\n  STR_SAN_FRANCISCO: \"San Francisco\"\n  STR_MIDWAY_ISLAND: \"Midway\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_TASMANIA: \"Tasmanie\"\n  STR_HAWAII: \"Hawaï\"\n  STR_FIJI: \"Les Îles Fidji\"\n  STR_TONGA: \"Tonga\"\n  STR_EASTER_ISLAND: \"L'Île de Pâques\"\n  STR_GALAPAGOS_ISLAND: \"Les Galápagos\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_SOLOMON_ISLAND: \"Les Îles Salomon\"\n  STR_CRETE: \"Crète\"\n  STR_LISBON: \"Lisbonne\"\n  STR_PORT_SAID: \"Port-Saïd\"\n  STR_MARSEILLES: \"Marseille\"\n  STR_TRIPOLI: \"Tripoli\"\n  STR_MANILA: \"Manille\"\n  STR_HONG_KONG: \"Hong Kong\"\n  STR_SINGAPORE: \"Singapour\"\n  STR_BANGKOK: \"Bangkok\"\n  STR_DARWIN: \"Darwin\"\n  STR_BOMBAY: \"Bombay\"\n  STR_SAYCHELLES_ISLAND: \"Les Seychelles\"\n  STR_MALDIVE_ISLAND: \"Les Maldives\"\n  STR_SRI_LANKA: \"Sri Lanka\"\n  STR_MAURITIUS: \"L'Île Maurice\"\n  STR_TOKYO: \"Tokyo\"\n  STR_SHANGHAI: \"Shanghai\"\n  STR_VLADIVOSTOK: \"Vladivostok\"\n  STR_LONDON: \"Londre\"\n  STR_FAEROE_ISLAND: \"Les Îles Féroé\"\n  STR_ABERDEEN: \"Aberdeen\"\n  STR_OSLO: \"Oslo\"\n  STR_JAMAICA: \"Jamaïque\"\n  STR_PANAMA: \"Panama\"\n  STR_MIAMI: \"Miami\"\n  STR_PSI_TRAINING: \"Entrainement au C.M.\"\n  STR_PSIONIC_TRAINING: \"ENTRAINEMENT AU CONTRÔLE MOLÉCULAIRE\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Place C.M. restante> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"Puissance {NEWLINE}C.M.\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"Amélioration{NEWLINE}/Aptitude C.M.\"\n  STR_IN_TRAINING: \"{NEWLINE}Inscrit ?\"\n  STR_TARGETTED_BY: \"VISÉ PAR :\"\n  STR_WEAPONS_CREW_HWPS: \"ARMES/{NEWLINE}ÉQUIPAGE/SAS\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"à court de carburant,{NEWLINE}retourne à la base\"\n  STR_SOLDIER_LIST: \"Effectif des Aquanautes\"\n  STR_RANK_: \"GRADE> {ALT}{0}\"\n  STR_MISSIONS: \"MISSIONS> {ALT}{0}\"\n  STR_KILLS: \"VICTIMES> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"GUÉRISON DE BLESSURE> {ALT}{0}\"\n  STR_TIME_UNITS: \"UNITÉS DE TEMPS\"\n  STR_STAMINA: \"ENDURANCE\"\n  STR_HEALTH: \"SANTÉ\"\n  STR_BRAVERY: \"COURAGE\"\n  STR_REACTIONS: \"RÉACTIONS\"\n  STR_FIRING_ACCURACY: \"PRÉCISION AU TIR\"\n  STR_THROWING_ACCURACY: \"PRÉCISION AU LANCER\"\n  STR_STRENGTH: \"FORCE\"\n  STR_PSIONIC_STRENGTH: \"PUISSANCE C.M.\"\n  STR_PSIONIC_SKILL: \"APTITUDE C.M.\"\n  STR_NEW_RANK: \"NOUVEAU GRADE\"\n  STR_PROMOTIONS: \"Promotions\"\n  STR_SOLDIERS_UC: \"AQUANAUTES\"\n  STR_COELACANTH_GAS_CANNON_UFOPEDIA: \"Les Systèmes d'Armes Submersibles automatisés sont d'une grande résistance et très maniable. Ils procurent un appui de gros calibre a nos troupes et ce à n'importe quelle profondeur. Les SAS sont automatiquement réapprovisionné depuis nos stocks.\"\n  STR_COELACANTH_AQUA_JET_UFOPEDIA: \"Ce SAS est doté de torpilles Aqua-Jet, système d'arme uniquement opérationnel en milieu aquatique. Assurez-vous d'approvisionner le stock en munitions.\"\n  STR_COELACANTH_GAUSS_UFOPEDIA: \"La technologie Gauss offre pour nos unités SAS une puissance de feu bien plus importante que nos armements classiques.\"\n  STR_DISPLACER_SONIC_UFOPEDIA: \"La technologie Alienne nous ouvre de nouvelles perspectives pour nos unités SAS. Le moteur à Ion permet de décoller du fond et l'armement Sonique donne un avantage tactique considérable sur le champ de bataille.\"\n  STR_DISPLACER_PWT_UFOPEDIA: \"Ce nouveau SAS possède des armes à Ondes Pulsées dévastatrice spécialement conçu pour l'environnement aquatique. Vous pouvez guider la vague d'énergie en enregistrant des points de repères avant de faire feu. Les munitions spécifiques \\\"TOP\\\" doivent être fabriqués dans vos ateliers.\"\n  STR_ALIEN_PROBE_MISSION: \"Mission d'Exploration Alienne\"\n  STR_ALIEN_INTERDICTION: \"Interdiction Alienne\"\n  STR_ALIEN_RESOURCE_RAID: \"Raid de Ressources Alien\"\n  STR_ALIEN_INFILTRATION: \"Infiltration Alienne\"\n  STR_ALIEN_BASE: \"Expansion Coloniale Alienne\"\n  STR_ALIEN_SURFACE_ATTACK: \"Attaques Aliennes en surface\"\n  STR_ALIEN_RETALIATION: \"Représailles Aliennes\"\n  STR_ALIEN_SUPPLY: \"Ravitaillement de Colonie Alienne\"\n  STR_ALIEN_PROBE_MISSION_UFOPEDIA: \"La Mission d'Exploration Alienne sert à recueillir des données sur le fond marin, les ressources, les voies maritimes et aériennes d'une région. Les OSNIS impliqués dans ces missions ne représentent pas une grande menace en eux-mêmes, mais indiquent des sites où l'activité pourrait exploser à tout moment.\"\n  STR_ALIEN_INTERDICTION_UFOPEDIA: \"Les Aliens ont pour usage de surveiller les régions qui les intéressent, en envoyant un submersible avec pour ordre clair de sécuriser la région avant que des missions plus importantes ne débutent. Ils vont amerrir sur des sites spécifiques qu'ils voudront occuper, pour verrouiller l'accès à ces régions et ouvrir la voie au niveau d'activité suivant.\"\n  STR_ALIEN_RESOURCE_RAID_UFOPEDIA: \"Couler des navires et abattre des avions sont des éléments clés de la stratégie des Aliens. L'acquisition de matériaux est une des principales activités des Aliens et justifie de tels actes d'agression. Les Aliens lancent aussi des incursions dans des régions avec activité géothermique, des sites miniers et des ruines antiques pour récupérer des minéraux, des métaux raffinés et autres objets produits par les humains.\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"De ceci peut résulter des contactes officiels entre les Aliens et des corporations ou gouvernements au plus haut niveau. Le pic de cette activité se caractérise par une intense activité d'OSNIS dans les mers de l'organisation concernée. Les Aliens tenteront de signer un accord avec un gouvernement ou une organisation en proposant les connaissances de leurs technologies supérieures. Cette activité Alienne représente une menace majeure pour X-Com. Si une corporation ou un gouvernement coopère avec les envahisseurs ils cesseront leurs financements.\"\n  STR_ALIEN_BASE_UFOPEDIA: \"Les Aliens vont construire des colonies sous-marines secrètes dans des endroits isolés. Après quelques vols de reconnaissance, une intense activité OSNIS se produira pendant la phase de construction de la base. Ces bases sont sans doute équipés de laboratoires, de centres de clonage et de blocs chirurgicaux pour les expériences sur les humains et les Aliens. La présence de colonies Aliennes va générer davantage d'activité Alienne sans même la présence d'OSNIS. Afin de localiser une colonie, un submersible d'X-Com doit patrouiller dans une région pendant quelques heures pour avoir une chance de la détecter. \"\n  STR_ALIEN_SURFACE_ATTACK_UFOPEDIA: \"Quand les Aliens ont besoin d'humains ils terrorisent un port, attaquent une ile ou lancent un raid sur un navire. Les civils seront directement menacés pour satisfaire les besoins de reproduction pervers des Aliens et leurs expériences hideuses.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"Si les intercepteurs submersibles d'X-Com réussissent particulièrement bien à couler des OSNIS, alors les extraterrestres pourraient commettre des actions de représailles. Cela pourrait aboutir à une attaque directe contre une base X-Com. Cependant, les extraterrestres doivent trouver cette base avant de l'attaquer, et tant que les OSNIS sont tenus à l'écart, il y a peu de risques d'une attaque.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"Une fois qu'une colonie alienne est construite, elle est régulièrement approvisionnée par un vaisseau cargo spécial. Si l'un de ses vaisseaux est détecté lors de son amerrissage, vous pouvez alors être certain qu'il y a une colonie alienne à proximité.\"\n  STR_SURVEY_SHIP_UFOPEDIA: \"Ce minuscule submersible est utilisé essentiellement pour la reconnaissance ou la recherche. Il précède normalement des vaisseaux plus grands au début d'un corps expéditionnaire Alien. \"\n  STR_ESCORT_UFOPEDIA: \"Un vaisseau d'escorte de taille moyenne qui ne représente pas une grande menace en lui-même. Ce vaisseau précède l'arrivée de plus grands vaisseaux et d’une activité plus intense.\"\n  STR_CRUISER_UFOPEDIA: \"Le Croiseur est un vaisseau polyvalent, le fer de lance de la flotte Alienne, il est utilisé pour tous les types de missions aliennes et se révèle un adversaire dangereux.\"\n  STR_HEAVY_CRUISER_UFOPEDIA: \"Le Croiseur Lourd est un vaisseau plus puissant que le Croiseur, possédant de plus grandes armes et systèmes de propulsion pour le renforcer. Le Croiseur Lourd est utilisé pour les missions de ressources pour collecter de grandes quantités de minéraux et d'équipement.\"\n  STR_HUNTER_UFOPEDIA: \"Ce vaisseau est équipé d'une salle d'examen utilisée pour les expériences sur des sujets humains. Les victimes sont soumises aux pires tortures et le cerveau est souvent retiré et stocké pour utilisation ultérieure. \"\n  STR_BATTLESHIP_UFOPEDIA: \"Le Destroyer est le plus agressif des submersibles Aliens, il possède toutes les technologies et systèmes Aliens pour agir en tant que base d'opération pouvant effectuer tous les actes d'agression entrepris par les Aliens, il transporte une grande quantité d'armes.\"\n  STR_DREADNOUGHT_UFOPEDIA: \"Le Cuirassé est un super transporteur de troupes, équipé de toutes les technologies Aliennes et d'une énorme cargaison. Le Cuirassé est un adversaire dont la résistance n'a d'égal que sa puissance de feu.\"\n  STR_FLEET_SUPPLY_CRUISER_UFOPEDIA: \"Le Chaland est utilisé durant la construction de colonies aliennes ou pour l'approvisionnement de colonies existantes. Il transporte des nutriments pour les aliens, de l'ADN, des foetus et autres composants biologiques. \"\n  STR_DISMANTLE: \"Démanteler\"\n  STR_FACILITY_IN_USE: \"AQUA-NACELLE ACTIVE\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"IMPOSSIBLE DE DEMANTELER CETTE AQUA-NACELLE !{SMALLLINE} Toutes les nacelles de la base doivent être liées au sas.\"\n  STR_TRANSFER_ITEMS_TO: \"Transférer les objets vers {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"PAS D'INSTALLATION DE QUARANTAINE EXTRATERRESTRES POUR LE TRANSFERT !{SMALLLINE}Les extraterrestres vivants ont besoin d'une installation d'isolement sécurisé pour maintenir leurs fonctions vitales.\"\n  STR_AMOUNT_AT_DESTINATION: \"QUANTITÉ VERS {NEWLINE}LA DESTINATION\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"L'extraterrestre est mort faute de place en zone de quarantaine extraterrestre.\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"PAS DE LOGEMENT DE LIBRE !{SMALLLINE}La base de destination n'a pas assez de place dans les quartiers du personnel pour l'équipage affecté au submersible.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"PAS SUFFISAMENT D'ESPACE DE STOCKAGE !{SMALLLINE}La base de destination n'a pas suffisamment de place pour l’équipement attribué au submersible.\"\n  STR_ITEMS_ARRIVING: \"Matériel en Livraison\"\n  STR_DESTINATION_UC: \"DESTINATION\"\n  STR_DART_PISTOL: \"Fusil à Fléchettes\"\n  STR_DART_POD: \"Fléchettes\"\n  STR_JET_HARPOON: \"Lance Harpon\"\n  STR_HARPOON_POD: \"Harpons\"\n  STR_GAS_CANNON: \"Canon à Gaz\"\n  STR_GC_AP_AMMO: \"Projectile à Gaz Anti-Armure\"\n  STR_GC_HE_AMMO: \"Projectile à Gaz Explosif\"\n  STR_GC_P_AMMO: \"Projectile à Gaz au Phosphore\"\n  STR_HYDRO_JET_CANNON: \"Canon Hydro-Jet\"\n  STR_HJC_AP_AMMO: \"Munition HJ Anti-Armure\"\n  STR_HJC_HE_AMMO: \"Munition HJ Explosive\"\n  STR_HJC_P_AMMO: \"Munition HJ au Phosphore\"\n  STR_TORPEDO_LAUNCHER: \"Lance-Torpille\"\n  STR_SMALL_TORPEDO: \"Petite Torpille\"\n  STR_LARGE_TORPEDO: \"Grande Torpille\"\n  STR_PHOSPHOROUS_TORPEDO: \"Torpille au Phosphore\"\n  STR_MAGNA_BLAST_GRENADE: \"Grenade Magna-Blast\"\n  STR_DYE_GRENADE: \"Grenade Colorante\"\n  STR_PARTICLE_DISTURBANCE_GRENADE: \"Grenade à Perturbations de Particules\"\n  STR_MAGNA_PACK_EXPLOSIVE: \"Explosif Magna-Pack\"\n  STR_PARTICLE_DISTURBANCE_SENSOR: \"Détecteur à Perturbations de Particules\"\n  STR_MEDI_KIT: \"Trousse de Soins\"\n  STR_MC_DISRUPTOR: \"Perturbateur C.M.\"\n  STR_THERMAL_TAZER: \"Tazer Thermique\"\n  STR_GAUSS_PISTOL: \"Pistolet Gauss\"\n  STR_GAUSS_PISTOL_CLIP: \"Chargeur de Pistolet Gauss\"\n  STR_GAUSS_RIFLE: \"Fusil Gauss\"\n  STR_GAUSS_RIFLE_CLIP: \"Chargeur de Fusil Gauss\"\n  STR_HEAVY_GAUSS: \"Gauss Lourd\"\n  STR_HEAVY_GAUSS_CLIP: \"Chargeur de Gauss Lourd\"\n  STR_SONIC_CANNON: \"Canon Sonique\"\n  STR_CANNON_POWER_CLIP: \"Cellule P de Canon Sonique\"\n  STR_SONIC_BLASTA_RIFLE: \"Carabine Blasta-Sonique\"\n  STR_BLASTA_POWER_CLIP: \"Cellule P de Carabine Blasta-S\"\n  STR_SONIC_PISTOL: \"Pistolet Sonique\"\n  STR_PISTOL_POWER_CLIP: \"Cellule P de Pistolet Sonique\"\n  STR_DISRUPTOR_PULSE_LAUNCHER: \"Lanceur à Ondes à Perturbation\"\n  STR_DISRUPTOR_AMMO: \"Munition du Lanceur D'Ondes\"\n  STR_THERMAL_SHOK_LAUNCHER: \"Lanceur à Chocs Thermiques\"\n  STR_THERMAL_SHOK_BOMB: \"Bombe à Chocs Thermiques\"\n  STR_SONIC_PULSER: \"Grenade à Impulsion Sonique\"\n  STR_ZRBITE: \"Zrbite\"\n  STR_MC_READER: \"Lecteur C.M.\"\n  STR_VIBRO_BLADE: \"Vibro-lame\"\n  STR_THERMIC_LANCE: \"Lance Thermique\"\n  STR_HEAVY_THERMIC_LANCE: \"Lance Thermique Lourde\"\n  STR_AQUATOID_CORPSE: \"Corps d'Aquatoïde\"\n  STR_GILLMAN_CORPSE: \"Corps de homme-poisson\"\n  STR_LOBSTERMAN_CORPSE: \"Corps d'Homme-Homard\"\n  STR_TASOTH_CORPSE: \"Corps de Tasoth\"\n  STR_CALCINITE_CORPSE: \"Corps de Calcinite\"\n  STR_DEEP_ONE_CORPSE: \"Corps de Profond\"\n  STR_BIODRONE_CORPSE: \"Corps de Bio-Drone\"\n  STR_TENTACULAT_CORPSE: \"Corps de Tentaculaire\"\n  STR_TRISCENE_CORPSE: \"Corps de Triscène\"\n  STR_HALLUCINOID_CORPSE: \"Corps d'Hallucinoïde\"\n  STR_XARQUID_CORPSE: \"Corps de Xarquide\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"Munitions insuffisantes pour équiper ces SAS {SMALLLINE}{0} {1} requis.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Pas assez d'équipement pour ré-équiper l'escouade\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Vous devez rechercher {NEWLINE}{0}{NEWLINE}pour pouvoir produire{NEWLINE}{1}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"Les Aliens ont détruit la base non défendue {0}\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"Les patrouilles X-Com ont localisé une colonie Alien en {0}\"\n  STR_STANDOFF: \"ATTENTE\"\n  STR_CAUTIOUS_ATTACK: \"ATTAQUE PRUDENTE \"\n  STR_STANDARD_ATTACK: \"ATTAQUE STANDARD \"\n  STR_AGGRESSIVE_ATTACK: \"ATTAQUE AGRESSIVE \"\n  STR_DISENGAGING: \"DÉSENGAGEMENT\"\n  STR_UFO_HIT: \"OSNI TOUCHÉ !\"\n  STR_UFO_CRASH_LANDS: \"OSNI ABATTU !\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Réduction en mode attente seulement \"\n  STR_UFO_RETURN_FIRE: \"L'OSNI RIPOSTE !\"\n  STR_INTERCEPTOR_DAMAGED: \">>>SUBMERSIBLE VOLANT ENDOMMAGÉ<<< \"\n  STR_INTERCEPTOR_DESTROYED: \">>>SUBMERSIBLE VOLANT DÉTRUIT<<< \"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"OSNI EN FUITE !\"\n  STR_LONG_RANGE_DETECTION: \"Détection à Large Bande\"\n  STR_STORES_UC: \"STOCK \"\n  STR_DIFFICULTY_LEVEL: \"Niveau de difficulté \"\n  STR_INTERCEPT: \"INTERCEPTER\"\n  STR_BASES: \"BASES \"\n  STR_GRAPHS: \"GRAPHIQUES\"\n  STR_UFOPAEDIA_UC: \"OSNIPÉDIE\"\n  STR_OPTIONS_UC: \"OPTIONS \"\n  STR_FUNDING_UC: \"BUDGET \"\n  STR_5_SECONDS: \"5 s \"\n  STR_1_MINUTE: \"1 min \"\n  STR_5_MINUTES: \"5 min \"\n  STR_30_MINUTES: \"30 min \"\n  STR_1_HOUR: \"1 heure \"\n  STR_1_DAY: \"1 jour \"\n  STR_XCOM_PERFORMANCE_ROSTER: \"Rapport de Performances Xcom \"\n  STR_ENTER_NAME: \"Entrer nom \"\n  STR_PERFORMANCE_RATING: \"Évaluation de Performance \"\n  STR_VICTORY_DATE: \"Date de victoire \"\n  STR_CHEMICAL_FLARE: \"Torche Chimique\"\n  STR_CHEMICAL_FLARE_UFOPEDIA: \"Cette balise éclairante produit une lumière vive à toutes les profondeurs ou sur la terre ferme. Ceci illumine les unités ennemies proches lors des missions sous-marines ou de nuit. \"\n  STR_MONTHLY_COSTS: \"Coûts Mensuels \"\n  STR_CRAFT_RENTAL: \"Location de Submersibles\"\n  STR_SALARIES: \"Salaires \"\n  STR_BASE_MAINTENANCE: \"Entretien de la Base \"\n  STR_COST_PER_UNIT: \"Coût par Unité \"\n  STR_QUANTITY: \"Quantité \"\n  STR_TOTAL: \"Total\"\n  STR_IN_PSIONIC_TRAINING: \"En cours d'implantation C.M.\"\n  STR_FRONT_ARMOR: \"ARMURE AVANT \"\n  STR_LEFT_ARMOR: \"ARMURE GAUCHE \"\n  STR_RIGHT_ARMOR: \"ARMURE DROITE \"\n  STR_REAR_ARMOR: \"ARMURE ARRIÈRE \"\n  STR_UNDER_ARMOR: \"ARMURE DE DESSOUS \"\n  STR_ROUNDS: \"TIRS\"\n  STR_UNIT: \"UNITÉ> {0}\"\n  STR_ENERGY: \"ÉNERGIE \"\n  STR_MORALE: \"MORAL\"\n  STR_ARMOR_: \"ARMURE> {0} \"\n  STR_FRONT_ARMOR_UC: \"ARMURE AVANT \"\n  STR_LEFT_ARMOR_UC: \"ARMURE GAUCHE \"\n  STR_RIGHT_ARMOR_UC: \"ARMURE DROITE \"\n  STR_REAR_ARMOR_UC: \"ARMURE ARRIÈRE \"\n  STR_SKILLS: \"COMPÉTENCES> {0} \"\n  STR_LEVEL: \"NIVEAU> {0} \"\n  STR_HEAD: \"TÊTE\"\n  STR_TORSO: \"TORSE\"\n  STR_RIGHT_ARM: \"BRAS DROIT \"\n  STR_LEFT_ARM: \"BRAS GAUCHE \"\n  STR_RIGHT_LEG: \"JAMBE DROITE \"\n  STR_LEFT_LEG: \"JAMBE GAUCHE \"\n  STR_PAIN_KILLER: \"CALMANT\"\n  STR_STIMULANT: \"STIMULANT\"\n  STR_HEAL: \"SOIGNER\"\n  STR_TIME_UNITS_SHORT: \"UT> {ALT}{0}\"\n  STR_WEIGHT: \"Poids> {ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"Réac> {ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"M.Talent> {ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"M.For> {ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Artéfact Alien\"\n  STR_AMMO_ROUNDS_LEFT: \"MUNITIONS :{NEWLINE}CARTOUCHES{NEWLINE}RESTANTES={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Calm> {ALT}{0}{ALT}{NEWLINE}Stim> {ALT}{1}{ALT}{NEWLINE}Soin> {ALT}{2}\"\n  STR_THROW: \"Lancer\"\n  STR_AUTO_SHOT: \"Tir Automatique \"\n  STR_SNAP_SHOT: \"Tir Rapide \"\n  STR_AIMED_SHOT: \"Tir Précis \"\n  STR_STUN: \"Assommer\"\n  STR_PRIME_GRENADE: \"Armer Grenade \"\n  STR_USE_SCANNER: \"Utiliser Détecteur à Particules\"\n  STR_USE_MEDI_KIT: \"Utiliser Trousse de Soins \"\n  STR_LAUNCH_MISSILE: \"Lancer Torpille\"\n  STR_ACCURACY_SHORT: \"Pré> {ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Unités de Temps insuffisantes ! \"\n  STR_NOT_ENOUGH_ENERGY: \"Énergie Épuisée ! \"\n  STR_NO_ROUNDS_LEFT: \"A court de Munitions ! \"\n  STR_NO_AMMUNITION_LOADED: \"Pas de Munitions Chargées ! \"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Mauvaise Munition pour cette Arme ! \"\n  STR_WEAPON_IS_ALREADY_LOADED: \"L'Arme est Déjà Chargée ! \"\n  STR_NO_LINE_OF_FIRE: \"Pas de Ligne de Tir ! \"\n  STR_GRENADE_IS_ACTIVATED: \"La Grenade est Activée ! \"\n  STR_GRENADE_IS_DEACTIVATED: \"La Grenade est Désactivée ! \"\n  STR_THERE_IS_NO_ONE_THERE: \"Il n'y a Personne ici ! \"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Impossible d'utiliser Artéfact Alien sans recherche ! \"\n  STR_OUT_OF_RANGE: \"Hors de Portée ! \"\n  STR_UNABLE_TO_THROW_HERE: \"Impossible de Lancer à cet Endroit ! \"\n  STR_SET_TIMER: \"Détonateur \"\n  STR_HIDDEN_MOVEMENT: \"MOUVEMENT CACHÉ \"\n  STR_TURN: \"TOUR> {0} \"\n  STR_SIDE: \"CAMP> {0} \"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Cliquez pour continuer \"\n  STR_MIND_CONTROL: \"Contrôle Moléculaire\"\n  STR_PANIC_UNIT: \"Brouiller Implant\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Attaque Moléculaire Réussie \"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Contrôle de l'Implant Réussi \"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}a perdu son sang-froid \"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}a perdu son sang-froid \"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}a paniqué \"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}a paniqué \"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Aliens\"\n  STR_RIGHT_HAND: \"MAIN DROITE \"\n  STR_LEFT_HAND: \"MAIN GAUCHE \"\n  STR_RIGHT_SHOULDER: \"ÉPAULE DROITE \"\n  STR_LEFT_SHOULDER: \"ÉPAULE GAUCHE \"\n  STR_BACK_PACK: \"SAC À DOS \"\n  STR_BELT: \"CEINTURE \"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}est sous contrôle moléculaire\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}est sous contrôle moléculaire\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}a perdu connaissance \"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}a perdu connaissance \"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}a succombé à une blessure mortelle.\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}a succombé à une blessure mortelle.\"\n  STR_USE_MIND_PROBE: \"Utiliser Lecteur C.M.\"\n  STR_FATAL_WOUNDS: \"BLESSURES MORTELLES \"\n  STR_UNDER_ARMOR_UC: \"ARMURE DE DESSOUS \"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Unités de temps réservées pour le tir rapide \"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Unités de temps réservées pour le tir automatique \"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Unités de temps réservées pour le tir précis \"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Unités de temps réservées pour s'agenouiller\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"UTs réservées pour s'agenouiller et tirer\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} Unités dans Vaisseau X-Com \"\n    many: \"{N} Unités dans Vaisseau X-Com \"\n    other: \"{N} Unités dans Vaisseau X-Com \"\n  STR_UNITS_OUTSIDE:\n    one: \"{N} Unités laissées à l'extérieur \"\n    many: \"{N} Unités laissées à l'extérieur \"\n    other: \"{N} Unités laissées à l'extérieur \"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} Unités en Zone d’Insertion \"\n    many: \"{N} Unités en Zone d’Insertion \"\n    other: \"{N} Unités en Zone d’Insertion \"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} Unités en Zone d'Extraction \"\n    many: \"{N} Unités en Zone d'Extraction \"\n    other: \"{N} Unités en Zone d'Extraction \"\n  STR_ABORT_MISSION_QUESTION: \"Abandonner la Mission ? \"\n  STR_CORPSE: \"Corps \"\n  STR_UNLOAD_CRAFT: \"Décharger \"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}a été tué \"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}a été tué \"\n  STR_HIT_MELEE: \"Mêlée \"\n  STR_GROUND: \"SOL \"\n  STR_LIVING_QUARTERS_PLURAL: \"Quartiers du personnel\"\n  STR_LIST_ITEM: \"OBJET \"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"Tous les aliens sont morts lors du crash {NEWLINE}Procédure de récupération automatique activée \"\n  STR_RESET: \"Réinitialiser \"\n  STR_MEMORIAL: \"Mémorial \"\n  STR_DATE_UC: \"DATE \"\n  STR_SOLDIERS_RECRUITED_UC: \"AQUANAUTES RECRUTÉS> {ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"AQUANAUTES PERDUS> {ALT}{0}\"\n  STR_REMOVE_SELECTED: \"Supprimer les Spécimens Choisis \"\n  STR_LIVE_ALIENS: \"Spécimens{NEWLINE}Vivants \"\n  STR_DEAD_ALIENS: \"Spécimens{NEWLINE}Rejetés \"\n  STR_UNDER_INTERROGATION: \"Interrogatoire{NEWLINE}En cours \"\n  STR_CONTAINMENT_EXCEEDED: \"LA ZONE DE QUARANTAINE E.T. EST SATURÉE !{SMALLLINE}Toutes les cellules à {0} sont occupées. Vous devez éliminer les spécimens surnuméraires.\"\n  STR_MANAGE_CONTAINMENT: \"Gestion de la Détention des Aliens\"\n  STR_STORAGE_EXCEEDED: \"ESPACE DE STOCKAGE SATURÉ !{SMALLLINE}Espace de stockage insuffisant à {0}. Les objets en surplus doivent êtres vendus. \"\n  STR_GO_TO_BASE: \"Aller à la Base \"\n  STR_MELEE_ACCURACY: \"PRÉCISION EN MÊLÉE \"\n  STR_SELL_PRODUCTION: \"VENDRE \"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Nécessite les deux mains libres ! \"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Matériel insuffisant pour appliquer le template \"\n  STR_UNLOAD_WEAPON: \"Décharger l'arme \"\n  STR_ALL_ITEMS: \"Tous les objets \"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"LIMITE DE MATÉRIEL À BORD ATTEINTE !{SMALLLINE}Vous n'êtes pas autorisé à embarquer plus de {N} objets à bord de ce submersible. \"\n    many: \"LIMITE DE MATÉRIEL À BORD ATTEINTE !{SMALLLINE}Vous n'êtes pas autorisé à embarquer plus de {N} objets à bord de ce submersible. \"\n    other: \"LIMITE DE MATÉRIEL À BORD ATTEINTE !{SMALLLINE}Vous n'êtes pas autorisé à embarquer plus de {N} objets à bord de ce submersible. \"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}CENTRE DE CONTRÔLE DÉTRUIT{NEWLINE}Trouvez votre chemin jusqu'à l'entrée et abandonnez.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"Les aqua-installations X-Com ne peuvent être construites sur la terre \"\n  STR_UNABLE_TO_ENGAGE_DEPTH: \"IMPOSSIBLE D'ENGAGER L’ENNEMI{NEWLINE}A CETTE PROFONDEUR\"\n  STR_UNABLE_TO_ENGAGE_AIRBORNE: \"IMPOSSIBLE D'ENGAGER L’ENNEMI{NEWLINE}DANS LES AIRS\"\n  STR_UNDERWATER_EQUIPMENT: \"Cet équipement fonctionne exclusivement sous l'eau !\"\n  STR_LAND_EQUIPMENT: \"Cet équipement fonctionne exclusivement sur terre !\"\n  STR_LEVEL_SHORT: \"L{0}\"\n  STR_PERSONNEL: \"Personnel\"\n  STR_CRAFT_ARMAMENT: \"Vaisseau & Armement\"\n  STR_COMPONENTS: \"Composants\"\n  STR_SOLDIERS_RECRUITED: \"Aquanautes recrutés\"\n  STR_SOLDIERS_LOST: \"Aquanautes perdus\"\n  STR_TOTAL_UFOS: \"OSNIS volants détecté\"\n  STR_TOTAL_ALIEN_BASES: \"Colonies alien découverte \"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"PCM\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"ACM\"\n  FEMALE_CIVILIAN: \"Civile, Femme\"\n  MALE_CIVILIAN: \"Civil, Homme\"\n  DOCKER_CIVILIAN: \"Civil, Docker\"\n  SAILOR_CIVILIAN: \"Civil, Marin\"\n  STR_BIODRONE_MELEE_WEAPON: \"Attaque en Mêlée du Bio-Drone\"\n  HALLUCINOID_WEAPON: \"Arme de l'Hallucinoïde\"\n  STR_LOBSTERMAN_MELEE_WEAPON: \"Attaque en Mêlée de l'Homme-Homard\"\n  CALCINITE_WEAPON: \"Arme du Calcinite\"\n  DEEP_ONE_WEAPON: \"Arme du Profond\"\n  STR_TRISCENE_MELEE_WEAPON: \"Attaque en mêlée du Triscène\"\n  STR_TRIBIO_SONIC_WEAPON: \"Arme Sonique Alien\"\n  XARQUID_WEAPON: \"Arme du Xarquide\"\n  TENTACULAT_WEAPON: \"Arme du Tentaculaire\"\n  ZOMBIE_WEAPON: \"Arme du Zombi\"\n  ALIEN_PSI_WEAPON: \"Arme C.M. Alien\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/hr.yml",
    "content": "hr:\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"CENTRIRAJ NA MJESTO-VRIJEME=5 sek\"\n  STR_CANCEL_UC: \"PONIŠTI\"\n  STR_NONE: \"Nema\"\n  STR_AVERAGE: \"Osrednje\"\n  STR_EXCELLENT: \"Izvrsno\"\n  STR_RESEARCH: \"ISTRAŽIVANJE\"\n  STR_MANUFACTURE: \"PROIZVEDI\"\n  STR_PURCHASE_RECRUIT: \"KUPI/UNOVAČI\"\n  STR_SACK: \"OTPUSTI\"\n  STR_SELL_SACK_UC: \"PRODAJ/OTPUSTI\"\n  STR_BUILD_NEW_BASE: \"Izgradi Novu Bazu\"\n  STR_CANCEL: \"Poništi\"\n  STR_COST_UC: \"CIJENA>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Instalacija\"\n  STR_SCIENTISTS_AVAILABLE: \"Raspoloživo Znanstvenika>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Znanstvenika na Projektu>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Dostupno Laboratorijskog Prostora>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"ISTRAŽIVAČKI PROJEKT\"\n  STR_PROGRESS: \"NAPREDAK\"\n  STR_NEW_PROJECT: \"Novi Projekt\"\n  STR_CANCEL_PROJECT: \"PREKINI PROJEKT\"\n  STR_NEW_RESEARCH_PROJECTS: \"Nove istraživačke projekte\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"RASPOLOŽIVO ZNANSTVENIKA>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"DOSTUPNO LABORATORIJSKOG PROSTORA>{ALT}{0}\"\n  STR_INCREASE: \"Povećaj\"\n  STR_DECREASE: \"Smanji\"\n  STR_START_PROJECT: \"POKRENI PROJEKT\"\n  STR_CURRENT_PRODUCTION: \"TRENUTAČNA PROIZVODNJA\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Dostupan Radionički Prostor>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Raspoloživa Sredstva>{ALT}{0}\"\n  STR_ITEM: \"PREDMET\"\n  STR_UNITS_PRODUCED: \"Proizvedeno Jedinica\"\n  STR_TOTAL_TO_PRODUCE: \"Ukupno za Proizvesti\"\n  STR_COST__PER__UNIT: \"Trošak{NEWLINE}po{NEWLINE}Jedinici\"\n  STR_DAYS_HOURS_LEFT: \"Dana/sati ostalo\"\n  STR_NEW_PRODUCTION: \"Nova Proizvodnja\"\n  STR_PRODUCTION_ITEMS: \"Predmeti za Proizvodnju\"\n  STR_CATEGORY: \"KATEGORIJA\"\n  STR_COST_PER_UNIT_: \"Trošak po jedinici>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Potrebno Prostora za Rad>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"POTREBNI SU POSEBNI MATERIJALI\"\n  STR_ITEM_REQUIRED: \"POTREBAN PREDMET\"\n  STR_UNITS_REQUIRED: \"POTREBNO JEDINICA\"\n  STR_UNITS_AVAILABLE: \"JEDINICA NA RASPOLAGANJU\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"DOSTUPAN RADIONIČKI PROSTOR>{ALT}{0}\"\n  STR_INCREASE_UC: \"POVEĆAJ\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Kupi/Unajmi Osoblje\"\n  STR_COST_OF_PURCHASES: \"Cijena Kupljenog>{ALT}{0}\"\n  STR_QUANTITY_UC: \"KOLIČINA\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"RASPOLOŽIVO LJUDSTVO:UKUPNO LJUDSTVO>\"\n  STR_SCIENTISTS: \"Znanstvenici\"\n  STR_LIVING_QUARTERS: \"Prostor za življenje\"\n  STR_STORES: \"Skladišta\"\n  STR_LABORATORIES: \"Laboratoriji\"\n  STR_TRANSFERS_UC: \"TRANSFERI\"\n  STR_TRANSFERS: \"Transferi\"\n  STR_ARRIVAL_TIME_HOURS: \"Vrijeme do Dolaska (sati)\"\n  STR_COST_: \"Cijena>{ALT}{0}\"\n  STR_AREA_: \"Područje>{ALT}{0}\"\n  STR_BASE_NAME: \"Ime baze?\"\n  STR_AMOUNT_TO_TRANSFER: \"KOLIČINA ZA TRANSFERIRANJE\"\n  STR_SELECT_DESTINATION_BASE: \"Izaberi Bazu Odredište\"\n  STR_COST: \"Cijena\"\n  STR_TOTAL_UC: \"UKUPNO\"\n  STR_INCOME: \"Prihod\"\n  STR_EXPENDITURE: \"Trošak\"\n  STR_MAINTENANCE: \"Održavanje\"\n  STR_BALANCE: \"Bilansa\"\n  STR_DATE_FIRST: \"{0}\"\n  STR_DATE_SECOND: \"{0}\"\n  STR_DATE_THIRD: \"{0}\"\n  STR_DATE_FOURTH: \"{0}\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Nema dovoljno posebnih materijala za proizvodnju{NEWLINE}{0}{NEWLINE}u{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Nemamo dovoljno sredstava za proizvodnju{NEWLINE}{0}{NEWLINE}u{NEWLINE}{1}\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"Izgradnja {NEWLINE}{0}{NEWLINE} u {NEWLINE}{1}{NEWLINE} je završena.\"\n  STR_OK_5_SECONDS: \"OK - 5 sec\"\n  STR_RESEARCH_COMPLETED: \"Istraživanje završeno\"\n  STR_VIEW_REPORTS: \"VIDI IZVJEŠTAJE\"\n  STR_WE_CAN_NOW_RESEARCH: \"Sada možemo istražiti\"\n  STR_WE_CAN_NOW_PRODUCE: \"Sada možemo proizvesti\"\n  STR_SUNDAY: \"NEDJELJA\"\n  STR_MONDAY: \"PONEDJELJAK\"\n  STR_TUESDAY: \"UTORAK\"\n  STR_WEDNESDAY: \"SRIJEDA\"\n  STR_THURSDAY: \"ČETVRTAK\"\n  STR_FRIDAY: \"PETAK\"\n  STR_SATURDAY: \"SUBOTA\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"U {2} nema dovoljno {0} za opskrbljivanje {1} s gorivom.\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Nema dovoljno {0} za naoružavanje {1} pri {2}\"\n  STR_BASE_IS_LOST: \"Baza je izgubljena\"\n  STR_BASE_IS_SAVED: \"Baza je obranjena\"\n  STR_ALIENS_KILLED: \"UBIJENI IZVANZEMALJCI\"\n  STR_ALIEN_CORPSES_RECOVERED: \"PRONAĐENO IZVANZEMALJSKIH LEŠINA\"\n  STR_LIVE_ALIENS_RECOVERED: \"PRONAĐENO ŽIVIH IZVANZEMALJACA\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"ZAPLIJENJENI IZVANZEMALJSKI ARTEFAKTI\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"CIVILA UBIJENO OD STRANE IZVANZEMALJACA\"\n  STR_CIVILIANS_SAVED: \"SPAŠENO CIVILA\"\n  STR_BASE_UNDER_ATTACK: \"{0} je napadnuta!\"\n  STR_BASE_DEFENSES_INITIATED: \"OBRANA BAZE PRIPRAVNA\"\n  STR_FIRING: \"GAĐANJE\"\n  STR_HIT: \"POGODAK!\"\n  STR_MISSED: \"PROMAŠAJ!\"\n  STR_FUNDS: \"SREDSTVA> {ALT}{0}\"\n  STR_VALUE: \"Vrijednost\"\n  STR_BASE_UC_: \"BAZA> {0}\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"NEMA DOVOLJNO PROSTORA ZA RAD!{SMALLLINE}Izgradi novu radionicu ili smanji broj inženjera koji rade na drugim projektima.\"\n  STR_NOT_ENOUGH_MONEY: \"NEMAMO DOVOLJNO SREDSTAVA!\"\n  STR_LAUNCH_INTERCEPTION: \"NAREDI PRESRETANJE\"\n  STR_BASE: \"BAZA\"\n  STR_READY: \"SPREMNO\"\n  STR_REARMING: \"NAORUŽAVANJE\"\n  STR_TARGET: \"CILJ: {0}\"\n  STR_WAY_POINT: \"MEĐUTOČKA\"\n  STR_YES: \"DA\"\n  STR_NO: \"NE\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"IZABERI MJESTO ZA NOVU BAZU\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"MISIJA ZAVRŠENA - VRAĆA SE U BAZU\"\n  STR_PATROLLING: \"PATROLIRANJE\"\n  STR_RETURNING_TO_BASE: \"VRAĆA SE U BAZU\"\n  STR_DESTINATION_UC_: \"ODREDIŠTE: {0}\"\n  STR_SPEED_: \"BRZINA>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"MAKSIMALNA BRZINA>{ALT}{0}{ALT}\"\n  STR_FUEL: \"GORIVO>{ALT}{0}\"\n  STR_WEAPON_ONE: \"ORUŽJE-1>{ALT}{0}\"\n  STR_NONE_UC: \"NIŠTA\"\n  STR_ROUNDS_: \"Metaka>{ALT}{0}\"\n  STR_BASE_: \"Baza>{0}\"\n  STR_NAME_UC: \"IME\"\n  STR_AMMO_: \"STRELJIVO>{ALT}{0}\"\n  STR_EQUIPMENT_UC: \"OPREMA\"\n  STR_ARMOR: \"OKLOP\"\n  STR_COLONEL: \"Vrhovni Zapovjednik\"\n  STR_COMMANDER: \"Satnik\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Izaberi Desetinu za {0}\"\n  STR_SPACE_AVAILABLE: \"DOSTUPNO PROSTORA>{ALT}{0}\"\n  STR_SPACE_USED: \"ZAUZETI PROSTOR>{ALT}{0}\"\n  STR_WOUNDED: \"RANJEN(A)\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Oprema za {0}\"\n  STR_DEFENSE_VALUE: \"Obrambena Vrijednost\"\n  STR_SELECT_ARMAMENT: \"Izaberi Naoružanje\"\n  STR_AMMUNITION_AVAILABLE: \"RASPOLOŽIVO STRELJIVO\"\n  STR_TYPE: \"VRSTA\"\n  STR_SELECT_ARMOR: \"Izaberi Oklop\"\n  STR_NORTH: \"SJEVER\"\n  STR_NORTH_EAST: \"SJEVEROISTOK\"\n  STR_EAST: \"ISTOK\"\n  STR_SOUTH_EAST: \"JUGOISTOK\"\n  STR_SOUTH: \"JUG\"\n  STR_SOUTH_WEST: \"JUGOZAPAD\"\n  STR_WEST: \"ZAPAD\"\n  STR_NORTH_WEST: \"SJEVEROZAPAD\"\n  STR_SELECT_ACTION: \"IZABERI AKCIJU\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"NASTAVI POTJERU\"\n  STR_VERY_LARGE: \"VRLO VELIK\"\n  STR_LARGE: \"VELIK\"\n  STR_MEDIUM_UC: \"SREDNJI\"\n  STR_SMALL: \"MALI\"\n  STR_VERY_SMALL: \"VRLO MALI\"\n  STR_DETECTED: \"Otkriven\"\n  STR_SIZE_UC: \"VELIČINA\"\n  STR_HEADING: \"SMJER KRETANJA\"\n  STR_SPEED: \"BRZINA\"\n  STR_REDIRECT_CRAFT: \"PREUSMJERI LETJELICU\"\n  STR_CRASH_SITE_: \"OBORENI NLO-{0}\"\n  STR_WAY_POINT_: \"MEĐUTOČKA-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}je došao do{NEWLINE}{1}\"\n  STR_ALIEN_ORIGINS: \"Porijeklo Izvanzemaljaca\"\n  STR_UFOPAEDIA: \"NLOpedija\"\n  STR_ACCELERATION: \"UBRZANJE>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"KAPACITET GORIVA>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"MJESTA ZA ORUŽJE>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"OTPORNOST>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"TERETNI PROSTOR>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Oštećenje\"\n  STR_RANGE: \"Domet\"\n  STR_ACCURACY: \"Točnost\"\n  STR_RE_LOAD_TIME: \"Vrijeme do idućeg hitca\"\n  STR_DAMAGE_ARMOR_PIERCING: \"PROTUOKLOPNO\"\n  STR_DAMAGE_MELEE: \"PRSA O PRSA\"\n  STR_DAMAGE_ACID: \"KISELINA\"\n  STR_DAMAGE_SMOKE: \"DIM\"\n  STR_SHOT_TYPE: \"VRSTA\"\n  STR_ACCURACY_UC: \"TOČNOST\"\n  STR_TIME_UNIT_COST: \"POTREBNO VJ\"\n  STR_DAMAGE_UC: \"OŠTEĆENJE\"\n  STR_AMMO: \"STRELJIVO\"\n  STR_SHOT_TYPE_AUTO: \"Automatski\"\n  STR_SHOT_TYPE_SNAP: \"Brzi\"\n  STR_SHOT_TYPE_AIMED: \"Ciljano\"\n  STR_CONSTRUCTION_COST: \"Cijena Izgradnje\"\n  STR_MAINTENANCE_COST: \"Cijena Održavanja\"\n  STR_MEDIUM: \"Srednje\"\n  STR_HIGH: \"Visoko\"\n  STR_WEAPON: \"Oružje\"\n  STR_EQUIPMENT: \"Oprema\"\n  STR_ALIEN_CORPSE: \"Izvanzemaljski Leš\"\n  STR_PERSONAL_ARMOR: \"Osobni Oklop\"\n  STR_ALIEN: \"Izvanzemaljac\"\n  STR_ZOMBIE: \"Zombi\"\n  STR_LIVE_COMMANDER: \"Vrhovni Zapovjednik\"\n  STR_LIVE_MEDIC: \"Liječnik\"\n  STR_LIVE_SOLDIER: \"Vojnik\"\n  STR_LIVE_TERRORIST: \"Terorist\"\n  STR_EXAMINATION_ROOM: \"Prostorija za Proučavanje\"\n  STR_ARMOR_PIERCING: \"PROTUOKLOPNO\"\n  STR_SCIENTIST: \"Znanstvenik\"\n  STR_NORTH_ATLANTIC: \"Sjeverni Atlantik\"\n  STR_SOUTH_ATLANTIC: \"Južni Atlantik\"\n  STR_INDIAN_OCEAN: \"Indijski ocean\"\n  STR_ARCTIC: \"Arktik\"\n  STR_NORTH_AMERICA: \"Sjeverna Amerika\"\n  STR_MAXIMUM_SPEED: \"Maksimalna brzina\"\n  STR_DAMAGE_CAPACITY: \"Otpornost\"\n  STR_WEAPON_POWER: \"Snaga Oružja\"\n  STR_WEAPON_RANGE: \"Domet Oružja\"\n  STR_LABORATORY: \"Laboratorij\"\n  STR_WORKSHOP: \"Radiona\"\n  STR_GENERAL_STORES: \"Skladište\"\n  STR_ALIEN_CONTAINMENT: \"Prostorija za Internaciju Izvanzemaljaca\"\n  STR_USA: \"SAD\"\n  STR_CIVILIAN: \"Civil\"\n  STR_JAN: \"sij\"\n  STR_FEB: \"velj\"\n  STR_MAR: \"ožu\"\n  STR_APR: \"tra\"\n  STR_MAY: \"svi\"\n  STR_JUN: \"lip\"\n  STR_JUL: \"srp\"\n  STR_AUG: \"kol\"\n  STR_SEP: \"ruj\"\n  STR_OCT: \"lis\"\n  STR_NOV: \"stu\"\n  STR_DEC: \"pro\"\n  STR_INTERNATIONAL_RELATIONS: \"Međunarodni Odnosi\"\n  STR_COUNTRY: \"Država\"\n  STR_FUNDING: \"Financiranje\"\n  STR_CHANGE: \"Promjena\"\n  STR_WEAPON_SYSTEMS: \"ORUŽJA\"\n  STR_DAMAGE_UC_: \"OŠTEĆENJE>{ALT}{0}\"\n  STR_RATING: \"OCJENA> {0}\"\n  STR_RATING_TERRIBLE: \"GROZNO!\"\n  STR_RATING_POOR: \"SLABO!\"\n  STR_RATING_OK: \"OK\"\n  STR_RATING_EXCELLENT: \"IZVRSNO!\"\n  STR_SCORE: \"BODOVI\"\n  STR_MONTH: \"Mjesec> {ALT}{0} {1}\"\n  STR_COUNTRIES_AND: \"{0} i {1}\"\n  STR_KNOTS: \"{0} čvorova\"\n  STR_MONTHLY_RATING: \"Mjesečna Ocjena> {ALT}{0}{ALT}{1}\"\n  STR_FUNDING_CHANGE: \"Promjena u razini sponzoriranja> {ALT}{0}\"\n  STR_RACE: \"RASA\"\n  STR_MISSION: \"MISIJA\"\n  STR_ZONE: \"ZONA\"\n  STR_NEW_YORK: \"New York\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_MANILA: \"Manila\"\n  STR_HONG_KONG: \"Hong Kong\"\n  STR_SINGAPORE: \"Singapur\"\n  STR_BANGKOK: \"Bangkok\"\n  STR_BOMBAY: \"Mumbai\"\n  STR_TOKYO: \"Tokio\"\n  STR_SHANGHAI: \"Šangaj\"\n  STR_LONDON: \"London\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"ponestaje gotiva,{NEWLINE}se vraća u bazu\"\n  STR_RANK_: \"RANG> {ALT}{0}\"\n  STR_MISSIONS: \"MISIJE> {ALT}{0}\"\n  STR_KILLS: \"UBIJENO NEPRIJATELJA> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"VRIJEME ZA OPORAVAK> {ALT}{0}\"\n  STR_TIME_UNITS: \"VREMENSKE JEDINICE\"\n  STR_STAMINA: \"IZDRŽLJIVOST\"\n  STR_HEALTH: \"ZDRAVLJE\"\n  STR_BRAVERY: \"HRABROST\"\n  STR_REACTIONS: \"REFLEKSI\"\n  STR_FIRING_ACCURACY: \"PRECIZNOST GAĐANJA\"\n  STR_THROWING_ACCURACY: \"PRECIZNOST PRILIKOM BACANJA\"\n  STR_STRENGTH: \"SNAGA\"\n  STR_NEW_RANK: \"NOVI RANK\"\n  STR_PROMOTIONS: \"Promaknuća\"\n  STR_ALIEN_INFILTRATION: \"Vanzemaljska Infiltracija\"\n  STR_TRANSFER_ITEMS_TO: \"Transferiraj Predmete do {0}\"\n  STR_DESTINATION_UC: \"ODREDIŠTE\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Nema dovoljno opreme za ponovno opskrbljavanje desetine\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Potrebno je istražiti{NEWLINE}{0}{NEWLINE}prije no što možemo proizvesti{NEWLINE}{1}\"\n  STR_STANDOFF: \"SIGURNA UDALJENOST\"\n  STR_CAUTIOUS_ATTACK: \"OPREZAN NAPAD\"\n  STR_STANDARD_ATTACK: \"STANDARDNI NAPAD\"\n  STR_AGGRESSIVE_ATTACK: \"AGRESIVNI NAPAD\"\n  STR_DISENGAGING: \"PREKIDANJE KONTAKTA\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Minimiziraj isključivo na Sigurnoj Udaljenosti\"\n  STR_STORES_UC: \"SKLADIŠTA\"\n  STR_DIFFICULTY_LEVEL: \"Razina Težine\"\n  STR_INTERCEPT: \"PRESRETANJE\"\n  STR_BASES: \"BAZE\"\n  STR_GRAPHS: \"GRAFIKONI\"\n  STR_OPTIONS_UC: \"OPCIJE\"\n  STR_FUNDING_UC: \"FINANCIRANJE\"\n  STR_5_SECONDS: \"5 sec\"\n  STR_1_MINUTE: \"1 min\"\n  STR_5_MINUTES: \"5 min\"\n  STR_30_MINUTES: \"30 min\"\n  STR_1_HOUR: \"1 sat\"\n  STR_1_DAY: \"1 dan\"\n  STR_ENTER_NAME: \"Upiši ime\"\n  STR_PERFORMANCE_RATING: \"Ocjena Učinkovitosti\"\n  STR_VICTORY_DATE: \"Datum Pobjede\"\n  STR_MONTHLY_COSTS: \"Mjesečni Izdaci\"\n  STR_SALARIES: \"Plaće\"\n  STR_BASE_MAINTENANCE: \"Održavanje baza\"\n  STR_COST_PER_UNIT: \"Trošak po jedinici\"\n  STR_QUANTITY: \"Količina\"\n  STR_TOTAL: \"Ukupno\"\n  STR_FRONT_ARMOR: \"Prednji Oklop\"\n  STR_LEFT_ARMOR: \"Lijevi Oklop\"\n  STR_RIGHT_ARMOR: \"Desni oklop\"\n  STR_REAR_ARMOR: \"Stražnji Oklop\"\n  STR_UNDER_ARMOR: \"Donji Oklop\"\n  STR_UNIT: \"JEDINICA>{0}\"\n  STR_ENERGY: \"ENERGIJA\"\n  STR_MORALE: \"MORAL\"\n  STR_ARMOR_: \"OKLOP> {0}\"\n  STR_FRONT_ARMOR_UC: \"PREDNJI OKLOP\"\n  STR_LEFT_ARMOR_UC: \"LIJEVI OKLOP\"\n  STR_RIGHT_ARMOR_UC: \"DESNI OKLOP\"\n  STR_REAR_ARMOR_UC: \"STRAŽNJI OKLOP\"\n  STR_SKILLS: \"VJEŠTINE> {0}\"\n  STR_LEVEL: \"RAZINA> {0}\"\n  STR_HEAD: \"GLAVA\"\n  STR_TORSO: \"TORZO\"\n  STR_RIGHT_ARM: \"DESNA RUKA\"\n  STR_LEFT_ARM: \"LIJEVA RUKA\"\n  STR_RIGHT_LEG: \"DESNA NOGA\"\n  STR_LEFT_LEG: \"LIJEVA NOGA\"\n  STR_PAIN_KILLER: \"ANALGETIK\"\n  STR_STIMULANT: \"STIMULANS\"\n  STR_HEAL: \"IZLIJEČI\"\n  STR_TIME_UNITS_SHORT: \"VJ>{ALT}{0}\"\n  STR_WEIGHT: \"Težina>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"Reakc>{ALT}{0}\"\n  STR_AMMO_ROUNDS_LEFT: \"STRELJIVO:{NEWLINE}METAKA ZA{NEWLINE}PREOSTALO={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Anal>{ALT}{0}{ALT}{NEWLINE}Stim>{ALT}{1}{ALT}{NEWLINE}Lije>{ALT}{2}\"\n  STR_THROW: \"Baci\"\n  STR_AUTO_SHOT: \"Rafalna Paljba\"\n  STR_SNAP_SHOT: \"Brzi Hitac\"\n  STR_AIMED_SHOT: \"Ciljana Paljba\"\n  STR_STUN: \"Onesvijesti\"\n  STR_USE_MEDI_KIT: \"Upotrijebi Medicinski Komplet\"\n  STR_ACCURACY_SHORT: \"Ubrzanje>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Nema Dovoljno Vremenskih Jedinica!\"\n  STR_NOT_ENOUGH_ENERGY: \"Nema dovoljno energije!\"\n  STR_NO_ROUNDS_LEFT: \"Nema više Metaka!\"\n  STR_NO_AMMUNITION_LOADED: \"Oružje nema streljiva!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Pogrešno Streljivo za ovo Oružje!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"Oružje je već napunjeno!\"\n  STR_NO_LINE_OF_FIRE: \"Nema čiste vatrene linije!\"\n  STR_GRENADE_IS_ACTIVATED: \"Granata je aktivirana!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Granata je deaktivirana!\"\n  STR_THERE_IS_NO_ONE_THERE: \"Nema nikoga na tom mjestu!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Ne možemo koristiti izvanzemaljski artefakt dok ga ne istražimo u laboratoriju!\"\n  STR_OUT_OF_RANGE: \"Izvan Dometa!\"\n  STR_UNABLE_TO_THROW_HERE: \"Nemoguće baciti ovdje!\"\n  STR_SET_TIMER: \"Namjesti Vremenski Detonator\"\n  STR_HIDDEN_MOVEMENT: \"SKRIVENO KRETANJE\"\n  STR_TURN: \"POTEZ> {0}\"\n  STR_SIDE: \"STRANA> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Pritisni gumb za nastavak\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Protivniku je Smanjen Moral\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}je zahvatio bijes\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}je zahvatio bijes\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}Paničari\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}Paničari\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Izvanzemaljci\"\n  STR_RIGHT_HAND: \"DESNA RUKA\"\n  STR_LEFT_HAND: \"LIJEVA RUKA\"\n  STR_RIGHT_SHOULDER: \"DESNO RAME\"\n  STR_LEFT_SHOULDER: \"LIJEVO RAME\"\n  STR_BACK_PACK: \"NAPRTNJAČA\"\n  STR_BELT: \"REMEN\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}je pala u nesvijest\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}je pala u nesvijest\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}je poginula od smrtonosne rane\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}je poginula od smrtonosne rane\"\n  STR_FATAL_WOUNDS: \"SMRTONOSNE RANE\"\n  STR_UNDER_ARMOR_UC: \"DONJI OKLOP\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Vremenske jedinice rezervirane za brzi hitac\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Vremenske jedinice rezervitane za automatsku paljbu\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Vremenske jedinice rezervitane za ciljanu paljbu\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Vremenske jedinice rezervitane za klečanje\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"Vremenske jedinice rezervitane za klečanje i pucanje\"\n  STR_ABORT_MISSION_QUESTION: \"Prekini misiju?\"\n  STR_CORPSE: \"Leš\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}je ubijen\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}je ubijen\"\n  STR_HIT_MELEE: \"Pogodak\"\n  STR_GROUND: \"TLO\"\n  STR_LIVING_QUARTERS_PLURAL: \"Prostor za življenje\"\n  STR_LIST_ITEM: \"PREDMET\"\n  STR_RESET: \"Vrati na početak\"\n  STR_MEMORIAL: \"Pali Borci\"\n  STR_DATE_UC: \"DATUM\"\n  STR_REMOVE_SELECTED: \"Izbaci Izabrano\"\n  STR_GO_TO_BASE: \"Idi u Bazu\"\n  STR_SELL_PRODUCTION: \"PRODAJ\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Obje ruke moraju biti prazne!\"\n  STR_ALL_ITEMS: \"Svi Predmeti\"\n  STR_PERSONNEL: \"Osoblje\"\n  FEMALE_CIVILIAN: \"Civil, žena\"\n  MALE_CIVILIAN: \"Civil, muškarac\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/hu.yml",
    "content": "hu:\n  STR_LEVIATHAN_UFOPEDIA: \"SZÁLLÍTÓ ÉS ELFOGÓ KÉTÉLTŰ GÉP. AZ EMBERI ÉS AZ IDEGEN TECHNOLÓGIA LEGTÖKÉLETESEBB ÖTVÖZÉSE, MELY FELHASZNÁLJA AZ ION MEGHAJTÁST ÉS A MÁGNESES SZONÁRT.\"\n  STR_BARRACUDA_UFOPEDIA: \"A BRIT HYDROSPACE BARRACUDA, MELYET MAGAS HŐMÉRSÉKLETŰ LÉZERMOTOROK REPÍTENEK AZ EGYIK LEGGYORSABB ELFOGÓ GÉP A VILÁGON. KÉPES LÉGTÉRI ÉS BÚVÁR BEVETÉSEKRE IS EZZEL KULCSFONTOSSÁGÚ SZEREPET TÖLT BE AZ ELKÖVETKEZŐ HARCBAN.\"\n  STR_HAMMERHEAD_UFOPEDIA: \"SZÁLLÍTÓ ÉS ELFOGÓ GÉP. EGY X-COM HAJÓ MELY RENDELKEZIK A MÁGNESES SZONÁR MÁSOLATÁVAL. KIS MÉRETE ELLENÉRE  LÉLEGZETELÁLLÍTÓ TECHNOLÓGIAI ÁTTÖRÉS.\"\n  STR_TRITON_UFOPEDIA: \"A TRITON EGY ROHAMCSAPAT SZÁLLÍTÓ, MELYET LÉGTÉRI ÉS BÚVÁRMOTORRAL IS FELSZERELTEK. NAGY KAPACITÁSA ÉS ROBUSZTUS FELÉPÍTÉSE BIZTOSÍTJA HELYÉT AZ X-COM FLOTTÁBAN.\"\n  STR_MANTA_UFOPEDIA: \"A MANTA EGY NAGYON GYORS EGYSZEMÉLYES KÉTÉLTŰ ELFOGÓ GÉP. HASONLÍT AZ IONMEGHAJTÁSÚ IDEGEN HAJÓKRA. RENDKÍVÜL HATÉKONY VADÁSZGÉP A FOKOZÓDÓ KONFLIKTUSBAN.\"\n  STR_AJAX_UFOPEDIA: \"AZ AJAX TORPEDÓ VILÁGSZERTE ELTERJEDT ALAPVETŐ VÍZALATTI FEGYVER. EGY PONTOS ÉS ERŐTELJES ELRETTENTŐ FEGYVER.\"\n  STR_DUP_HEAD_UFOPEDIA: \"A KIMERÜLT URIÁNIUMGÖMB-FEJES FEGYVERTECHNOLÓGIA VISZONYLAG ÚJ ÉS EZ AZ ELSŐ OLYAN KERESKEDELMI VÍZALATTI FEGYVERRENDSZER, MELY TELJESEN KIHASZNÁLJA.\"\n  STR_CRAFT_GAS_CANNON_UFOPEDIA: \"EGY GÁZKOMPRESSZIÓS ÁGYÚRENDSZER MELY NAGY HATÉKONYSÁGÚ SZILÁRD PÁNCÉLTÖRŐ LÖVEDÉKEKET TÜZEL.\"\n  STR_PWT_CANNON_UFOPEDIA: \"A PULZUSHULLÁM TORPEDÓ TÚLFŰTÖTT ÜZEMANYAGRENDSZERE ÉS EXTRÉMSŰRŰ ROBBANÓFEJE SZINTE BÁRMILYEN ANYAGON ÁTÜTI MAGÁT.\"\n  STR_GAUSS_CANNON_UFOPEDIA: \"A GAUSS FEGYVER EGY ÚJONNAN FEJLESZTETT X-COM TECHNOLÓGIA. A RENDSZER KOMPAKT RÉSZECSKEGYORSÍTÓJÁT EGY FOLYÉKONY NITROGÉNNEL HŰTÖTT FÚZIÓS REAKTOR LÁTJA EL ENERGIÁVAL.\"\n  STR_SONIC_OSCILLATOR_UFOPEDIA: \"A SZÓNIKUS OSZCILLÁTOR OLYAN ERŐTELJES HANGHULLÁMOKAT GENERÁL, MELYEK A CÉLPONT MOLEKULÁRIS KÖTÉSEINEK SZÉTREZGETÉSÉVEL PUSZTÍTJÁK EL AZT.\"\n  STR_AQUATOID_UFOPEDIA: \"Az Akvatoid faj egy ősi társadalom; már azelőtt léteztek, mielőtt az ember a lábát megvetette volna a világon. Egyszerű formájuk visszalépés űrutazó testvéreikhez, a Szektoidokhoz képest. Erejük a Molekuláris irányítás technológiáján alapul. Az Akvatoid faj szaporodása csak génmódosítás útján valósulhat meg, mivel eredendően sterilek. Ilyen célra ideális alanyok az emberek. A kísérletek során rengeteg hibrid faj keletkezett.\"\n  STR_AQUATOID_AUTOPSY: \"Akvatoid boncolás\"\n  STR_AQUATOID_AUTOPSY_UFOPEDIA: \"A részletes analízis eredménye alapján megengedhető néhány alapvető következtetés. Ez egy Szektoid, előző ellenségünk, de sebészeti úton történt beültetésekkel vízalatti életmódra felkészítve. Az elcsökevényesedett tüdő korlátozott mértékben lehetővé teszik a légzést szárazföldön is. Kibernetikus beültetések a testben mindenhol találhatók, növelik az elsenyvedt végtagok erejét és a belső szervek funkcióit. A faj minden egyede egyforma, feltételezzük, hogy klónok\"\n  STR_GILLMAN_UFOPEDIA: \"Ez a furcsa lény első ránézésre hüllőszerű, de valójában nagyon közel áll az emberhez. Különösen erős és gyors a víz alatti világban. A Kopoltyúsok teljes értékű faj, vannak különböző életkorú hím és nőstény egyedeik. Különböznek az összes többi vízalatti idegentől, mivel nem viselik semmiféle nyomát sebészeti vagy genetikai beavatkozásnak. Lehetséges, hogy saját fajunk egy ősi mellékága.\"\n  STR_GILLMAN_AUTOPSY: \"Kopoltyús boncolás\"\n  STR_GILLMAN_AUTOPSY_UFOPEDIA: \" Miután a boncolás megkezdődött, világossá vált, hogy ez nem idegen, hanem egy földi teremtmény; egy történelem előtti faj, amely az emlősök dominánssá válása idején pusztult ki. A Kopoltyúsok már a dinoszauruszok idejében is éltek - kétéltűek, intelligensek és erősek. A hüllők idejének véget vető kataklizma ezeket a teremtményeket szimbiózisra kényszerítette az újonnan érkezett idegenekkel. Egy kis elektronikus eszköz található a koponyájukban.\"\n  STR_LOBSTERMAN_UFOPEDIA: \"Ez a döbbenetes, embernél magasabb teremtmény hat végtaggal dicsekedhet. Olyan, mint egy vízi démon. A földi rákkal mutatott enyhe hasonlósága miatt X-Com berkekben csak Rákember néven emlegetik. A mélységek behemótja. Gondosan megtervezett harci teremtmény hihetetlen erővel és rakéták elleni gyakorlatilag sebezhetetlenséggel. Az ollói képesek szétzúzni az acélt...\"\n  STR_LOBSTERMAN_AUTOPSY: \"Rákember boncolás\"\n  STR_LOBSTERMAN_AUTOPSY_UFOPEDIA: \"Miután lefejtettük a látszólag megsemmisíthetetlen héjat, feltárul az izgalmas felépítése. Rendkívüli izmok borítják a titánium csontvázat. Egy rendkívül kifinomult célzórendszer többsávú szkennerrel van egyenesen az agyra kapcsolva. Minden egyes szemet az acélnál keményebb műanyag borít és teljesen világos hogy miután mestereik bevetik őket, gyakorlatilag megállíthatatlanok. Mélyen a testben eltemetve ismeretlen eredetű és funkciójú eszközök találhatók.\"\n  STR_TASOTH_UFOPEDIA: \"Ezek a gyors, mozgékony idegenek alkotják az idegen sereg gerincét. Százával születnek, óriás rajzóvermekben az idegen kolóniák szívében. Messze erőteljesebbek az embernél és idegen, ragadozó természetük páratlan a bolygón. A Taszot mindig az idegen támadási frontvonal élén harcol, soha nem vonul vissza, még elsöprő túlerő elől sem.\"\n  STR_TASOTH_AUTOPSY: \"Tasoth boncolás\"\n  STR_TASOTH_AUTOPSY_UFOPEDIA: \"A boncolás felfedi a különös, kibernetikus szerkezetű organizmust. A testüregben a kis erőforrás mellett nincsenek elkülöníthető szervek. Az energiát a test bioelektronikus átviteli rendszere továbbítja. A testben nem találhatók csontok vagy egyéb vázszerkezet. Ha meghal, az energia elapad és az egész test egy idegen húsból és folyadékból álló rongybabához válik hasonlóvá. Ezen kívül belül csak egy pár porceláncella található, melyeket energiával feltöltve a teremtmény pillanatnyira újraéled.\"\n  STR_DEEP_ONE_UFOPEDIA: \"A Mélységi egy biológiai rémálom, az Akvatoidok őrjítő keresztezési kísérleteinek eredménye. Néhány különböző változatával találkoztunk. Hosszas kutatás után úgy találjuk, hogy a Mélységieket 'gyártják', méghozzá a frissen beszerzett emberek felhasználásával, erősítve soraikat. Ezen alfaj mindegyike képes egy akvanauta megöléséhez elég erős elektromos kisülés generálására.\"\n  STR_DEEP_ONE_AUTOPSY: \"Mélységi boncolás\"\n  STR_DEEP_ONE_AUTOPSY_UFOPEDIA: \"Ez a teremtmény egymásba oltott idegen és emberi szervekből áll. Az emberi agy erős változáson megy át, hogy képes legyen befogadni az irányító elektronikát és az idegen agykérget. Az emberi szemeken kívül minden testrész teljes változáson megy keresztül. Az idegen magzat bekebelezi az emberi gazdatestet ahogy fejlődik. A teremtmény kemény bőre egy szervetlen fémkeverék, hihetetlenül erős és rugalmas. A végeredmény így egy gyors, erős megbízhatóan irányítható lény.\"\n  STR_BIODRONE_UFOPEDIA: \"A biodrón csak egy idegen elme szüleménye lehet. Egy agy (emberi vagy idegen), mely tápfolyadékban helyezkedik el egy energiával ellátott mechanikus egységben. Képes víz alatti és feletti repülésre. Minden biorobotnak van egy félig szerves, félig gépi hangsugárvetője, amely egyes vélemények szerint a befogadó organizmus hangszálaiból képződött. Szívós és pontos teremtmények, tökéletesen ellátják őrző-védő feladatukat.\"\n  STR_BIODRONE_AUTOPSY: \"Biodrón boncolás\"\n  STR_BIODRONE_AUTOPSY_UFOPEDIA: \"A feltételezés, miszerint a hangsugárvető szerves eredetű, igaz. Ez a szerencsétlen az ellenségeit valójában 'halálra ordítja'. Mindegyikükön hatalmas forradások látszanak és komoly csonkítási nyomok. Az idegenek, úgy tűnik, az agyat az engedelmességig csonkolták. A kéregállomány nagy része idegen eredetű, de semmi sem hasonlítható egy-egy emberi eredetű egyed felfedezésének borzalmához. Az energiájukat ION motor biztosítja, valamiféle távirányító rendszeren keresztül.\"\n  STR_TENTACULAT_UFOPEDIA: \"Még a Lovecrafti rémálmok legmélye sem közelíti meg ezt a leírhatatlan valamit. A Földön még hasonló sincs, az a környezet, melyben kifejlődött, minden képzeletet felülmúlhat. A csápjai segítségével az áldozatait elkábítja majd lélektelen hússá változtatja. Minden érintése halálos páncélon keresztül is.  Az X-Com nem találkozott még a Csápolatnál félelmetesebb teremtménnyel.\"\n  STR_TENTACULAT_AUTOPSY: \"Csápolat boncolás\"\n  STR_TENTACULAT_AUTOPSY_UFOPEDIA: \"A boncolás felfedi a nagy agy minden területén található számos kicsi kibernetikus beültetést. A látása a látható fénytől a hőképérzékelésig terjed. Még a legmélyebb óceán fenekén is tévedhetetlenül pontosan tud navigálni. Csökevényes szervei mindössze a túléléséhez szükséges létminimumot biztosítják. Minden lénynek apró gyomra van egy külső csatlakozóval. Logikus feltevés hogy mesterei táplálják közvetlen tápanyagbevitellel.\"\n  STR_CALCINITE_UFOPEDIA: \"A régi idők búvárruháira emlékeztető teremtmény acélnál is erősebb ollóinak egy gonosz csapása minden bizonnyal nem egy óvatlan és könnyelmű búvárnak oltotta ki az életét. Az arc környékén valamiféle zöldes zselészerű forma látható. Az igazi lényről semmit nem tudunk a gyakori gyilkos találkozások ellenére sem.\"\n  STR_CALCINITE_AUTOPSY: \"Kalcinit boncolás\"\n  STR_CALCINITE_AUTOPSY_UFOPEDIA: \"A páncélt eltávolítva feltárul hogy a Kalcinit egy hatalmas protoplazma buborék. Nincs látható agy, végtag vagy érzékelő szervek. Egy kis fémes eszköz azonban található a folyékony testben. Ha meghalt csak tippelni tudunk az idegen viselkedésére. Egy nagy megmagyarázhatatlan rejtély az egész idegen.\"\n  STR_TRISCENE_UFOPEDIA: \"Ez a kétlábú ragadozó a dinoszauruszok korából származik. A krétakori teremtmény minden érzékelő és létfenntartó szerve alkalmas a vízi és a szárazföldi életre egyaránt. Meg van pakolva fegyverállványokkal és állkapcsán hatalmas fémes fogak sorakoznak. A szárazföldi idegentámadások fő gerincét ők adják. Nehézsúlyú és hatásos fegyver, a Taszot parancsnokok előszeretettel vetik be őket.\"\n  STR_TRISCENE_AUTOPSY: \"Triszcén boncolás\"\n  STR_TRISCENE_AUTOPSY_UFOPEDIA: \"A tudósok kése alatt bebizonyosodott, hogy a Triszcén ősi teremtmény, kibernetikus beültetésekkel és fegyverrendszerekkel fejlesztve. A kis agyat segíti egy kis számítógépmodul mely az irányítóöveken helyezkedik el melyet a lényre raktak. A kemény természetes bőr és a feggyverekkel segített ragadozó ösztön halálos ellenféllé teszik bármilyen környezetben.\"\n  STR_HALLUCINOID_UFOPEDIA: \"Az óceánokat kizsákmányolva az idegenek kitenyésztették a földi medúza gigantikus mását. Nehogy azt hidd, hogy biztonságban vagy, amikor szemben állsz ezekkel az ártalmatlannak tűnő lényekkel. Képesek közelharcban szörnyű jeges csapást mérni ellenségeikre. A Hallucinoid halálos ellenfél.\"\n  STR_HALLUCINOID_AUTOPSY: \"Hallucinoid boncolás\"\n  STR_HALLUCINOID_AUTOPSY_UFOPEDIA: \"A többrétegű bőrt lefejtve a zselés testről kiderül, hogy az egész organizmus egy nagy teljesítményű harcra képzett fagyasztó. A puha és rugalmas bőr sérülékenynek tűnik a hőátadáson alapuló fegyverekkel szemben. Az Akvatoidok kedvenc kísérője ez a mutáns faj.\"\n  STR_XARQUID_UFOPEDIA: \"Még egy módosított földi gerinctelen. A Xarkvid egyszerre gyönyörű és veszélyes. A fürgén úszó óriási étvágyú teremtmény pusztító fegyverek arzenálját rejtegeti, köztük egy fojtó tintapatront és egy ionizált részecske kilövőt. Első találkozásunk óta bebizonyosodott, hogy ez a hatékony élőlény a bosszúszomjas Kopoltyúsok irányítása alatt áll.\"\n  STR_XARQUID_AUTOPSY: \"Xarkvid boncolás\"\n  STR_XARQUID_AUTOPSY_UFOPEDIA: \"Az óriási fejlábú méretét az idegen drogokon alapuló étrendjének és sebészeti beavatkozásoknak köszönheti. A lény most már eredeti természetétől teljesen idegen a Kopoltyúsok által beültetett mechanikus irányítórendszer miatt. Biológiai nehézegységként vetik be kemény páncéljának és mozgékonyságának köszönhetően.\"\n  STR_ION_BEAM_ACCELERATORS_UFOPEDIA: \"Az idegen kétéltűek erőforrása egy komplikált erőforrás-rendszeren alapul. A technológia az Ion áthelyező, amely Zrbite katalizátorral működik. A motorok a tömegük százszorosa mennyiségű vizet képesek áthelyezni. Ez a hihetetlen erő teszi képessé a idegen kétéltűeket a mieink lehagyására. A meghajtási rendszert lemásolhatjuk a vízműanyagok és a Zrbite felhasználásával.\"\n  STR_MAGNETIC_NAVIGATION_UFOPEDIA: \"Ezek az egységek egy ezer méter sugarú többrétegű mágneses gömböt produkálnak a kétéltű körül. Az idegen navigátorok egyenes összeköttetésben vannak a gépekkel, így érzékelik a kétéltű körüli láthatatlan világot. Az összekötő rendszer módosított agyi alapanyag, ez pedig neurális kapcsolatban van az irányító agyával.\"\n  STR_ALIEN_SUB_CONSTRUCTION_UFOPEDIA: \"Minden kétéltű vízműanyagból készül és egy kaméleon-szerű felépítéssel rendelkezik; ügyesen másolva a vízi élőlények formáját. Minden kétéltű egy élő szervezet: a legénység és a kétéltű harmóniában. Ezen rendszerek többsége lemásolható és egy hibrid technológiával megvalósítható. Elérhetővé válik így számunkra is ez a technológiai szint.\"\n  STR_ALIEN_CRYOGENICS_UFOPEDIA: \"A megszámlálhatatlan idegen mind kriogenetikailag volt lefagyasztva. Testhőmérsékletük egy-egy ilyen egységben a minimális testi funkciók szintjén van. A vizsgálatok szerint néhány ilyen egység több mint 60 millió éve őriz testeket.\"\n  STR_ALIEN_CLONING_UFOPEDIA: \"Az elfogott idegenek többsége a DNS-ükig egyezik. A sejtmintákat a génbankjaik őrzik, azonban ezekben emberek és testrészek is találhatók. Lehetséges, hogy használhatjuk ezeket a klónozókat valamiféle ember-idegen hibrid előállítására.\"\n  STR_ALIEN_LEARNING_ARRAYS_UFOPEDIA: \"A Molekuláris irányítás agyi beültetéseit ezek a gépek töltik fel az információkkal. A friss klón a gép mellet azonnal megszerzi a faji emlékeit és minden tudományos és harci információt.\"\n  STR_ALIEN_IMPLANTER_UFOPEDIA: \"Ez a felszerelés látja el az idegeneket a Molekuláris irányítás beültetéseivel, szaporítja a fajokat, beültet vagy eltávolít szerveket vagy elektronikát. A folyamat alatt a páciens kába, de öntudatánál van. Szerencsétlenségünkre az emberi anatómia tökéletes illesztéseket tesz lehetővé az egység számára.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"Itt a bizonyíték az emberek elfogására. Nem élelemnek, nem keltetőnek, hanem ők alkotják a bázisát a sok teremtménynek és irányító rendszernek. Az idegen technológia a közös elmén alapul, egy megosztott intellektuson, amely emberi aggyal tökéletesen megvalósítható. A emberi agyszövet az alapja a legtöbb idegen bioszámítógép-rendszernek. A maradékból lényeket építenek vagy keltetnek.\"\n  STR_AQUA_PLASTICS_UFOPEDIA: \"Az idegen gépek különleges tulajdonságokkal bíró anyagból épülnek fel. A vízműanyag bonyolult többszörös kötésű anyag, katalizátora a Zrbite. Sűrű, mégis rendkívül könnyű és erősebb akár a titániumnál vagy a kevlárnál is.\"\n  STR_ZRBITE_UFOPEDIA: \"Ez a fém idegen eredetű, részben arany, részben idegen bioanyag. Erőforrásként használva kis mennyisége is több energiát produkál, mint a tízszeres méretének megfelelő nukleáris egység. Gyártása már túlmutat technológiai lehetőségeinken, mivel majdnem minden összetevője idegen eredetű.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"Az idegenek a bolygó akármely részén lecsapnak, mindig könyörtelenek és hatékonyak. Nem találjuk az erejük forrását. Lehet, hogy az óceánok fenekén, melyek túl mélyen vannak számunkra? Hiszen nem minden organizmus idegen teljesen, néhányuk már ősidők óta létezik, évezredek óta alszik. Az óceánok legmélyén lehetnek a legősibb helyek, amelyek az csillagbeli testvéreikkel tartották a kapcsolatot. Kutatásaink szerint legalább 12 ilyen helyen van Synomium gép. Ez szélesíti az idegenek Molekuláris irányítás hálózatát, mivel az idegenek újraindítják ezeket a bázisokat. Nem tétovázhatunk, ezeknek a bázisoknak mindenáron pusztulniuk kell.\"\n  STR_THE_ULTIMATE_THREAT_UFOPEDIA: \"65 millió éve egy óriási kolonizáló hajó érkezett egy távoli, idegen világból. Ahogy a gigász megközelítette a fiatal bolygót egy erős napkitörés tönkretette a navigációs rendszert. A behemót fényesen izzva zúgott alá a krétakori égből és csapódott be, miközben a Föld számtalan teremtménye erőlködve bámulta.\\nAz órási porfelhő okozta lehűlés következtében a domináns életforma, a dinoszauruszok kihaltak. De 400 milliárd tonnája a T'leth-nek működöképes maradt. A nagy bonyolultságú szuperszámítógépek megkezdték a benn tartózkodó lények kriogenetikus altatását. Eonok múltával felébredtek és kommunikálni próbáltak csillagbéli testvéreikkel, mindhiába.\"\n  STR_TLETH_THE_ALIEN_CITY: \"T'leth, az idegenek városa\"\n  STR_TLETH_THE_ALIEN_CITY_UFOPEDIA: \"T'leth, a hatalmas idegen hajó a Sigsbee-mélységben fekszik, a Mexikói-öbölben, az óceán fenekébe ágyazódva. A város szíve maga az örökkévaló gonosz. Egy fémszobában fekszik a nagy álmodó, a Végső Idegen. Ha a T'leth a hullámok fölé emelkedik, ismét felébred és akkor megállíthatatlanná válik. A nem élő és mégsem halott idegen elme irányítja az egész idegen sereget. A különös Molekuláris irányítás technológia összeköti mindnyájukat a Nagy elmével. Idegen-ember mutánsok látják el energiával és tartják fenn közöttük a kapcsolatot. A Végső Idegen mítosza századok óta létezik az emberek szívében és elméjében, azonban a tenger mindig elrejtette a valóságot magát.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"KÖZÉPRE ÁLL-IDŐ=5 Mp\"\n  STR_CANCEL_UC: \"MÉGSEM\"\n  STR_NONE: \"Nincs\"\n  STR_UNKNOWN: \"Ismeretlen\"\n  STR_POOR: \"Gyenge\"\n  STR_AVERAGE: \"Átlagos\"\n  STR_GOOD: \"Jó\"\n  STR_EXCELLENT: \"Kiváló\"\n  STR_BUILD_NEW_BASE_UC: \"ÚJ BÁZIS ÉPÍTÉSE\"\n  STR_BASE_INFORMATION: \"BÁZIS INFORMÁCIÓ\"\n  STR_EQUIP_CRAFT: \"GÉPFELSZERELÉS\"\n  STR_BUILD_FACILITIES: \"ÉPÜLET EMELÉSE\"\n  STR_RESEARCH: \"KUTATÁS\"\n  STR_MANUFACTURE: \"GYÁRTÁS\"\n  STR_TRANSFER_UC: \"ÁTCSOPORTOSÍTÁS\"\n  STR_PURCHASE_RECRUIT: \"VÁSÁRLÁS/SOROZÁS\"\n  STR_SACK: \"KIRÚG\"\n  STR_SELL_SACK_UC: \"ELADÁS/KIRÚGÁS\"\n  STR_GEOSCAPE_UC: \"FÖLDGÖMB\"\n  STR_NAME: \"Név\"\n  STR_AREA: \"Terület\"\n  STR_BUILD_NEW_BASE: \"Új bázis építése\"\n  STR_CANCEL: \"Mégsem\"\n  STR_COST_UC: \"ÁR>\"\n  STR_CONSTRUCTION_TIME_UC: \"ÉPÍTÉS IDEJE>\"\n  STR_DAY:\n    one: \"{N} nap\"\n    other: \"{N} nap\"\n  STR_HOUR:\n    one: \"{N} óra\"\n    other: \"{N} óra\"\n  STR_MAINTENANCE_UC: \"KARBANTARTÁS>\"\n  STR_OK: \"OKÉ\"\n  STR_INSTALLATION: \"Építkezés\"\n  STR_CURRENT_RESEARCH: \"JELENLEGI KUTATÁS\"\n  STR_SCIENTISTS_AVAILABLE: \"Elérhető tudósok>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Tudósok beosztva>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Szabad laborkapacitás>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"KUTATÁSI PROGRAM\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"TUDÓSOK BEOSZTVA\"\n  STR_PROGRESS: \"HALADÁS\"\n  STR_NEW_PROJECT: \"Új program\"\n  STR_CANCEL_PROJECT: \"KUTATÁS LEÁLLÍTÁSA\"\n  STR_NEW_RESEARCH_PROJECTS: \"ÚJ KUTATÁSI PROGRAMOK\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"ELÉRHETŐ TUDÓSOK>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"SZABAD LABORKAPACITÁS>{ALT}{0}\"\n  STR_INCREASE: \"Növelés\"\n  STR_DECREASE: \"Csökkentés\"\n  STR_START_PROJECT: \"PROGRAM INDÍTÁSA\"\n  STR_CURRENT_PRODUCTION: \"JELENLEGI GYÁRTÁS\"\n  STR_ENGINEERS_AVAILABLE: \"Elérhető mérnökök>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Mérnökök beosztva>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Szabad műhelykapacitás>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Jelenlegi tőke>{ALT}{0}\"\n  STR_ITEM: \"TÉTEL\"\n  STR_ENGINEERS__ALLOCATED: \"Mérnökök beosztva\"\n  STR_UNITS_PRODUCED: \"Legyártott darabszám\"\n  STR_TOTAL_TO_PRODUCE: \"Összes gyártandó\"\n  STR_COST__PER__UNIT: \"Ár{NEWLINE}per{NEWLINE}egység\"\n  STR_DAYS_HOURS_LEFT: \"Hátralévő napok/órák\"\n  STR_NEW_PRODUCTION: \"Új gyártás\"\n  STR_PRODUCTION_ITEMS: \"Gyártható tételek\"\n  STR_CATEGORY: \"KATEGÓRIA\"\n  STR_START_PRODUCTION: \"GYÁRTÁS INDÍTÁSA\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} mérnöki munkaóra szükséges egy darab legyártásához\"\n  STR_COST_PER_UNIT_: \"Egységár>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Szükséges műhely kapacitás>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"SPECIÁLIS ANYAGSZÜKSÉGLET\"\n  STR_ITEM_REQUIRED: \"SZÜKSÉGES TÁRGY\"\n  STR_UNITS_REQUIRED: \"SZÜKSÉGES DARABSZÁM\"\n  STR_UNITS_AVAILABLE: \"ELÉRHETŐ DARABSZÁM\"\n  STR_STOP_PRODUCTION: \"GYÁRTÁS LEÁLLÍTÁSA\"\n  STR_ENGINEERS_AVAILABLE_UC: \"ELÉRHETŐ MÉRNÖKÖK>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"SZABAD MŰHELY KAPACITÁS>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"HAVI BEVÉTEL>{ALT}{0}\"\n  STR_INCREASE_UC: \"NÖVELÉS\"\n  STR_DECREASE_UC: \"CSÖKKENTÉS\"\n  STR_UNITS_TO_PRODUCE: \"Gyártandó darabszám\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Vásárlás/Bérlés/Sorozás\"\n  STR_COST_OF_PURCHASES: \"Beszerzési költség>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"EGYSÉGÁR\"\n  STR_QUANTITY_UC: \"MENNYISÉG\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"FELHASZNÁLHATÓ SZEMÉLYZET:TELJES SZEMÉLYZET>\"\n  STR_SOLDIERS: \"Akvanauták\"\n  STR_SCIENTISTS: \"Tudósok\"\n  STR_ENGINEERS: \"Mérnökök\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"KIHASZNÁLT HELY:SZABAD HELY>\"\n  STR_LIVING_QUARTERS: \"Lakónegyed\"\n  STR_STORES: \"Raktár\"\n  STR_LABORATORIES: \"Laboratórium\"\n  STR_WORK_SHOPS: \"Műhely\"\n  STR_HANGARS: \"Dokkok\"\n  STR_SHORT_RANGE_DETECTION: \"Rövid távú szonár\"\n  STR_DEFENSE_STRENGTH: \"Védelmi erősség\"\n  STR_TRANSFERS_UC: \"ÁTCSOPORTOSÍTÁS\"\n  STR_TRANSFERS: \"Átcsoportosítások\"\n  STR_ARRIVAL_TIME_HOURS: \"Érkezés: (óra)\"\n  STR_COST_: \"Ár>{ALT}{0}\"\n  STR_AREA_: \"Terület>{ALT}{0}\"\n  STR_BASE_NAME: \"Bázis neve?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"VÁLASSZ HELYET A KÖZPONTI LIFTNEK\"\n  STR_TRANSFER: \"Átcsoportosítás\"\n  STR_AMOUNT_TO_TRANSFER: \"SZÁLLÍTANDÓ MENNYISÉG\"\n  STR_SELECT_DESTINATION_BASE: \"Válaszd ki a célbázist\"\n  STR_COST: \"Ár\"\n  STR_INTRO_1: \"Copyright 1995 MicroProse\"\n  STR_INTRO_2: \"Mars: Cydonia bukása.\"\n  STR_INTRO_3: \"A diadalmas X-Com szétzúzta az idegen háborús gépezet magját és hazatér. Azonban nem halott minden a lerombolt marsi bázison...\"\n  STR_INTRO_4: \"Erőteljes tachion sugár tör elő a a cydoniai központ romjai közül. Száguld az ürességen keresztül. A célja........ \"\n  STR_INTRO_5: \"A Föld.\"\n  STR_INTRO_6: \"Az óceán mélyén a sugár becsapódik egy régóta várakozó érzékelőbe. Alvó számítógépek kelnek életre. A mélyben, az emberiség látókörén túl, óriási termekben alvó idegenek kezdik meg a hosszú újraéledési ciklusukat.\"\n  STR_INTRO_7: \"2040: Egy tudatlan Föld. Az idegen terror rég feledésbe merült. De az óceán elveszett és rejtett részein az idegen horda készen áll - készen arra, hogy végezzen az emberiséggel és elfoglalja a világot.\"\n  STR_INTRO_8: \"Az idegen csapás az emberiségre: egyedek szerzése hibbant kísérleteikhez, portyázás értékes ásványokért és erőforrásokért és a tengerek kifosztása. Ezután a hullámok fölé emelték tekintetüket.....\"\n  STR_INTRO_9: \"Hatalmas, furcsa formájú kétéltűek járják az óceánokat - nézelődve, kutatva, vadászva.......\"\n  STR_INTRO_10: \"Megtalálva a zsákmányt - lecsapnak.\"\n  STR_INTRO_11: \"Különös, új fegyvereket gyártanak a védtelen világ ellen. Tökéletesen ki vagyunk szolgáltatva az idegenek kényének-kedvének. {NEWLINE}Csak egy szervezet menthet meg minket, de mi réges-régen elfordultunk tôlük.........\"\n  STR_INTRO_12: \"X-COM Kísérleti Vízalatti Bázis\"\n  STR_INTRO_13: \"'Segítség!' 'Segítség!' 'Itt a Hyperion kereskedelmi hajó' 'Megtámadtak bennünket!' 'Segítség! Segí..........'\"\n  STR_INTRO_14: \"'Irányítóközpont Dokk Egynek: kijáratot nyitni', {NEWLINE}'Barracuda Zéró-egyet indítani. Helyzetfelmérés: Idegen támadás - vörös készültség.' {NEWLINE}'Megismétlem: vörös készültség'\"\n  STR_INTRO_15: \"Az idegenek könyörtelenül hatékonyak.....\"\n  STR_INTRO_16: \"...tévedhetetlenül pontosak\"\n  STR_INTRO_17: \"'Barracuda Zéró-egy a bázisnak' - 'megközelítjük a Hyperion maradványait'\"\n  STR_INTRO_18: \"'Lassítás folyamatban.'{NEWLINE}'Két méter'{NEWLINE}'Egy méter'{NEWLINE}'Minden akvanauta készüljön fel az azonnali bevetésre'\"\n  STR_INTRO_19: \"'Zsilip nyitva' 'Roncs megközelítése'{NEWLINE}'Mi az isten...'{NEWLINE}''Látjátok ôket? Működik a kamerám?'\"\n  STR_GAMEOVER_1: \"Elbuktunk. Az idegenek lemészárolták az utolsó reményünket a megváltásra.{NEWLINE}Az X-Com elpusztult és a föld ősi ellenségünk lábai előtt hever.\"\n  STR_GAMEOVER_2: \"T'leth magasan a sztratoszférába villámzik és keresztülsuhan a világ arculatán. Halált hozva learatja az emberi faj utolsó túlélőit. Mélyen a gyomrában a gyilkos elme elkezdi feléleszteni magát.\"\n  STR_GAMEOVER_3: \"A nemzetek fővárosaiban kétségbeesett terveket vázolnak fel. Mindennek semmi haszna nincs, az X-Com kutatási projekt technológiája nélkül a fegyvereink hatástalanok.\"\n  STR_GAMEOVER_4: \"Az idegenek bázisokat állítanak fel a sarki jégsapkákon és megolvasztják a jeget, míg az egész világ egy hatalmas óceánná válik. Az emberi faj maradékát begyűjtik és ismeretlen célú gonosz szaporító kísérletekre használják fel. Az ég elsötétül és ez a ragály söpör végig a Földön.\"\n  STR_GAMEOVER_5: \"Nem tudunk ellenállást szervezni az új világ rendje ellen, aki mégis megpróbálja tüzes sors várja felfoghatatlan idegen fegyverek által. A maradékunknak nincs ily áldott feloldozásban része. Anyaföld egy idegen világgá vált és az emberiség elveszett a hullámok alatt rejtőző borzalomban.\"\n  STR_OUTRO_1: \"A Nyughely feldúlt és megtizedelt. Egy feltörő üvöltés hallatszik a központjából.{NEWLINE}Bolondok, mind meghaltok............\"\n  STR_OUTRO_2: \"..........senki nem menekül.\"\n  STR_OUTRO_3: \"Egy erős robbanás rázza meg a nyughelyet, feltépve a város utcáit. Törmelék és füst tölti be a levegőt. Az Idegenek terveit keresztülhúztuk........\"\n  STR_OUTRO_4: \"T'leth hatalmas formája elkezd szétrepedni. Tűz és füst tör elő csillogó tornyaiból és adamantium termeiből.\"\n  STR_OUTRO_5: \"A hatalmas Idegen erődítmény a tenger felé bukfencezik, meggyötört fém és lelkek sikolya tölti be a levegőt. Többé már a Nagy Álmodozó nem álmodik a világuralomról.\"\n  STR_OUTRO_6: \"Egy utolsó fültépő hang és nyomáshullám, mellyel T'leth széttépi magát.{NEWLINE}Az Idegen fenyegetésnek vége. A Föld megtisztult.........................\"\n  STR_OUTRO_7: \"Egy álmos zöldeskék bolygó a galaxis távoli sarkában.\"\n  STR_OUTRO_8: \"A közeljövő egy biztonságos hely.\"\n  STR_OUTRO_9: \"Az Idegen rémálom a Föld számára rég eltűnt.\"\n  STR_OUTRO_10: \"Hatalmas metropolisz-szerű városokat népesítenek be emberek milliárdjai.\"\n  STR_OUTRO_11: \"Az X-Com tettei és az idegen háborúk pusztán gyerekmesék.\"\n  STR_OUTRO_12: \"De a legendáknak mindig szokása némi igazságot tartalmazni..........\"\n  STR_RISE_1: \"T'leth-et többféle legendákban többféleképpen hívják többféle földön.\"\n  STR_RISE_2: \"Egy robbanásszerű sikoly visszhangzik föld minden részén ahogy T'leth elkezd emelkedni a tengerfenékről.\"\n  STR_RISE_3: \"A hatalmas építmény átsuhan a Mexikói-öböl vizein.\"\n  STR_RISE_4: \"400 milliárd tonna Idegen fém a hatalmas Idegen város, melyben a Tökéletes Idegen alvó teste fekszik. 65 millió évig a földbe börtönözve a gonosz űristenség éledezik.\"\n  STR_RISE_5: \"A vizek felforrnak és kavarognak ahogy a Nagy Álmodozó nyughelye felbukkan a fényben..................\"\n  STR_RISE_6: \"............a fényben mely rövid életű lesz hacsak az X-Com nem képes leszámolni az Idegen harci gépezettel.\"\n  STR_YOU_HAVE_FAILED: \"Elbuktál az Idegen harci gépezet megállításában. A pénzelő szervezetek, melyeket eltántorított a képességeid hiánya, megpróbálnak egy békés megodást kialkudni az Idegenekkel. A Megszállóknak azonban teljesen más elképzelésük van, melyre rövidesen az egész világ rájön...\"\n  STR_TOTAL_UC: \"ÖSSZESEN\"\n  STR_INCOME: \"Bevétel\"\n  STR_EXPENDITURE: \"Kiadás\"\n  STR_MAINTENANCE: \"Fenntartás\"\n  STR_BALANCE: \"Egyenleg\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"Idegen aktivitás (tengerek)\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"Idegen aktivitás (zónák)\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"X-Com aktivitás (tengerek)\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"X-Com aktivitás (zónák)\"\n  STR_FINANCE: \"Pénzügy\"\n  STR_DATE_FIRST: \"{0}.\"\n  STR_DATE_SECOND: \"{0}.\"\n  STR_DATE_THIRD: \"{0}.\"\n  STR_DATE_FOURTH: \"{0}.\"\n  STR_FINANCE_THOUSANDS: \"$1000-ek\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Nincs elég speciális alapanyag{NEWLINE}{0}{NEWLINE}gyártásához itt:{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Nincs elég pénz{NEWLINE}{0}{NEWLINE}gyártásához itt:{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"{0}{NEWLINE}elkészült.{NEWLINE}Bázis:{NEWLINE}{1}\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"{0}{NEWLINE}építése befejeződött.{NEWLINE}Bázis:{NEWLINE}{1}\"\n  STR_OK_5_SECONDS: \"OKÉ - 5 mp\"\n  STR_RESEARCH_COMPLETED: \"Kutatás befejezve\"\n  STR_VIEW_REPORTS: \"JELENTÉS MEGEKINTÉSE\"\n  STR_WE_CAN_NOW_RESEARCH: \"Most már tudunk kutatni:\"\n  STR_WE_CAN_NOW_PRODUCE: \"Most már tudunk gyártani:\"\n  STR_SUNDAY: \"Vasárnap\"\n  STR_MONDAY: \"Hétfő\"\n  STR_TUESDAY: \"Kedd\"\n  STR_WEDNESDAY: \"Szerda\"\n  STR_THURSDAY: \"Csütörtök\"\n  STR_FRIDAY: \"Péntek\"\n  STR_SATURDAY: \"Szombat\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"{1} feltöltéséhez nincs elég {0} a(z) {2} bázison\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"{1} felfegyverzéséhez nincs elég {0} a(z) {2} bázison\"\n  STR_UFO_IS_NOT_RECOVERED: \"IDEGEN KÉTÉLTŰ nem lett felderítve\"\n  STR_UFO_IS_RECOVERED: \"IDEGEN KÉTÉLTŰ felderítve\"\n  STR_CRAFT_IS_LOST: \"Kétéltű elveszett\"\n  STR_TERROR_CONTINUES: \"Idegen tevékenység folytatódik\"\n  STR_ALIENS_DEFEATED: \"Idegenek legyőzve\"\n  STR_BASE_IS_LOST: \"A bázis elveszett\"\n  STR_BASE_IS_SAVED: \"A bázis megmenekült\"\n  STR_ALIEN_BASE_STILL_INTACT: \"Az idegen bázis továbbra is sértetlen\"\n  STR_ALIEN_BASE_DESTROYED: \"Az idegen bázis lerombolva\"\n  STR_ALIENS_KILLED: \"MEGÖLT IDEGENEK\"\n  STR_ALIEN_CORPSES_RECOVERED: \"IDEGEN TETEMEK BEGYŰJTVE\"\n  STR_LIVE_ALIENS_RECOVERED: \"ÉLŐ IDEGENEK BEGYŰJTVE\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"IDEGEN SZERKEZETEK BEGYŰJTVE\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"IDEGEN BÁZIS KÖZPONTJA LEROMBOLVA\"\n  STR_ALIEN_SYNOMIUM_DEVICE_DESTROYED: \"IDEGEN SYNOMIUM GÉP MEGSEMMISÍTVE\"\n  STR_ALIEN_SYNOMIUM_DEVICE_FAILED: \"NEM TUDTAD MEGSEMMISÍTENI A SYNOMIUM GÉPET\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"CIVIL ÁLDOZATOK (IDEGENEK ÁLTAL)\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"CIVIL ÁLDOZATOK X-COM ÜGYNÖKÖK ÁLTAL \"\n  STR_CIVILIANS_SAVED: \"MEGMENTETT CIVILEK\"\n  STR_XCOM_OPERATIVES_KILLED: \"MEGÖLT X-COM ÜGYNÖKÖK \"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"BEVETÉS KÖZBEN ELTŰNT X-COM ÜGYNÖKÖK: \"\n  STR_TANKS_DESTROYED: \"MEGSEMMISÜLT VFP \"\n  STR_XCOM_CRAFT_LOST: \"X-COM GÉP ELVESZTETT \"\n  STR_UFO_RECOVERY: \"KÉTÉLTŰ BEGYŰJTÉSE\"\n  STR_ALIEN_BASE_RECOVERY: \"IDEGEN BÁZIS BEGYŰJTÉSE\"\n  STR_BASE_UNDER_ATTACK: \"A(z) {0} bázis támadás alatt!\"\n  STR_BASE_DEFENSES_INITIATED: \"BÁZIS VÉDELME MŰKÖDÉSBE LÉP\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"PAJZS ELTASZÍTJA A KÉTÉLTŰT!\"\n  STR_FIRING: \"TÜZEL\"\n  STR_HIT: \"TALÁLT!\"\n  STR_UFO_DESTROYED: \"KÉTÉLTŰ MEGSEMMISÜLT\"\n  STR_MISSED: \"MELLÉ!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Eladás/Kirúgás\"\n  STR_VALUE_OF_SALES: \"ELADÁSOK ÉRTÉKE> {ALT}{0}\"\n  STR_FUNDS: \"TŐKE> {ALT}{0}\"\n  STR_SELL_SACK: \"Elad/Kirúg\"\n  STR_VALUE: \"Értéke\"\n  STR_CRAFT_: \"KÉTÉLTŰ> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"IDEGEN KÉTÉLTŰ RONCS FELDERÍTÉSE\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"Figyelem - Maradhattak idegenek a kétéltűben vagy a környékén. A küldetés sikeres teljesítésének feltétele: az összes ellenséges egység megsemmisítése vagy semlegesítése. A kétéltű maradványai, az idegen testek és szerkezetek felderítése csak ez után kezdődhet meg. A küldetés megszakításához az X-Com akvanautáknak vissza kell térnie a száll¡tóeszközbe, majd kattints a 'Küldetés megszakítása' ikonra\"\n  STR_UFO_GROUND_ASSAULT: \"IDEGEN KÉTÉLTŰ TÁMADÁSA\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"Derítsd fel a leszállóhelyet, majd - ha lehetséges - hatolj be a kétéltűbe. A küldetés sikeres teljesítésének feltétele: az összes ellenséges egység megsemmisítése vagy semlegesítése. A kétéltű-maradványok, az idegen testek és szerkezetek felderítése csak ez után kezdődhet meg. A küldetés megszakításához az X-Com akvanautáknak vissza kell térni a kétéltűjükhöz, majd kattints a 'Küldetés megszakítása' ikonra\"\n  STR_BASE_DEFENSE: \"BÁZIS VÉDELEM\"\n  STR_BASE_UC_: \"BÁZIS> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"Egy idegen jármű landolt a közelben. A bázisunk komoly veszélyben van. A harci gépek és személyzet kivételével a bázist kiürítettük. Az idegenek a dokkok ajtajain vagy a zsilipen keresztül hatolnak be. Védd meg a bázist és a létfontosságú épületeket mindenáron - ez élet-halál küzdelem. Ha a 'Küldetés megszakítása' ikonra kattintasz, elfogadod a vereséget és elveszted a bázist.\"\n  STR_ALIEN_COLONY_ATTACK_MISSION: \"IDEGEN BÁZIS TÁMADÁS\"\n  STR_ALIEN_BASE_ASSAULT: \"IDEGEN BÁZIS TÁMADÁS ELSŐ SZINT\"\n  STR_ALIEN_COLONY_P1_BRIEFING: \"A küldetés: megtisztítani egy idegen kolóniát lakóitól. A hely kétszintes, az átjutáshoz az akvanautáknak a villogó átjáróhoz kell menniük, majd kattints a küldetés megszakítása ikonra (vagy az összes idegent semlegesítsd). Bármilyen visszamaradó felszerelés csak a második rész befejezése után szedhető össze.\"\n  STR_ALIEN_COLONY_P2: \"IDEGEN BÁZIS TÁMADÁS MÁSODIK SZINT\"\n  STR_ALIEN_COLONY_P2_BRIEFING: \"A kolónia magja felé tartasz. Küldetésed a Synomium gép lerombolása, vagy az összes ellenséges egység semlegesítése. A visszatéréshez az akvanautáknak a kezdőpontra kell visszatérniük, majd kattints a küldetés megszakítása ikonra.\"\n  STR_ALIENS_LAUNCH_PORT_TERROR: \"KIKÖTŐI TÁMADÁS{NEWLINE}\"\n  STR_PORT_TERROR: \"IDEGENEK KIKÖTŐT TÁMADNAK\"\n  STR_PORT_TERROR_BRIEFING: \"Az idegenek szárazföldi létesítményeket támadnak. A kikötő és a civil lakosság veszélyben van. Az összes ellenséges egységet semlegesítsd és védd meg az ártatlanokat. A küldetés megszakításához az akvanautáknak vissza kell térni a kétéltűbe, majd kattints a megfelelő ikonra.\"\n  STR_ALIENS_LAUNCH_ISLAND_TERROR: \"SZIGET TÁMADÁSA{NEWLINE} \"\n  STR_ISLAND_TERROR: \"IDEGENEK SZIGETET TÁMADNAK\"\n  STR_ISLAND_TERROR_BRIEFING: \"Az idegenek szárazföldi támadást indítottak. A sziget és lakosai veszélyben vannak. Az összes ellenséges egységet semlegesítsed és védd meg az ártatlan járókelőket. A küldetés befejezéséhez az akvanautáknak vissza kell térni a kétéltűbe, majd kattints a küldetés megszakítása ikonra.\"\n  STR_ALIENS_ATTACK_SHIPPING_ROUTE: \"IDEGEN TÁMADÁS{NEWLINE}HAJÓZÁSI ÚTVONALON\"\n  STR_CARGO_SHIP_P1: \"TEHERHAJÓ ELSŐ RÉSZ\"\n  STR_CARGO_SHIP_P2: \"TEHERHAJÓ MÁSODIK RÉSZ\"\n  STR_CRUISE_SHIP_P1: \"ÓCEÁNJÁRÓ ELSŐ RÉSZ\"\n  STR_CRUISE_SHIP_P2: \"ÓCEÁNJÁRÓ MÁSODIK RÉSZ\"\n  STR_SHIP_RESCUE_MISSION: \"HAJÓ MENTÉSE\"\n  STR_SHIP_RESCUE_P1_BRIEFING: \"Poloskavadászat: minden ellenséges egységet semlegesíts és óvd meg a civilek életét. Az idegenek szétszóródtak az alsó és a felső fedélzeten. Biztosítsd a felső fedélzetet, mielőtt az alsónak nekifogsz. A küldetés megszakításához az akvanauták térjenek vissza a kétéltűbe, majd kattints a küldetés megszakítása ikonra.\"\n  STR_SHIP_RESCUE_P2_BRIEFING: \"Most tiszta a felső fedélzet. A teherlifttel leszállsz a raktérbe. Minden idegent semlegesítened kell a küldetés sikeres teljesítéséhez. A küldetés megszakításához az akvanauták térjenek vissza a lifthez, majd kattints a küldetés megszakítása ikonra.\"\n  STR_ALIEN_ACTIVITY_DETECTED: \"IDEGEN AKTIVITÁS ÉSZLELVE\"\n  STR_ALIEN_CONTACT_SITE_MISSION: \"IDEGEN KOMMUNIKÁCIÓS KÖZPONT\"\n  STR_ARTIFACT_SITE_P1: \"IDEGEN KOMMUNIKÁCIÓS KÖZPONT ELSŐ SZINT\"\n  STR_ARTIFACT_SITE_P1_BRIEFING: \"Ez a küldetés egy újonnan épített kommunikációs központ megtisztítására irányul. A hely kétszintes, az egyik a tengerfenék, a másik az alatta fekvő komplexum. Minden akvanauta mejnen a komplexum bejáratához és kattints a küldetés megszakítása ikonra hogy továbblépj, kilépéshez menjenek a kétéltűbe.\"\n  STR_ARTIFACT_SITE_P2: \"IDEGEN KOMMUNIKÁCIÓS KÖZPONT MÁSODIK SZINT\"\n  STR_ARTIFACT_SITE_P2_BRIEFING: \"Belépve az épületbe küldetésed célja világossá válik. Hatolj be a komplexum szívébe és rombold le a Synomium Molekuláris Irányító gépet. A küldetés megszakításához az akvanautákat vidd a kezdőpontra és kattints a küldetés megszakítása ikonra.\"\n  STR_SIGSBEE_DEEP_MISSION: \"SIGSBEE-MÉLYSÉG{NEWLINE}IDEGEN VAROS: ELSŐ SZINT\"\n  STR_TLETH_P1_BRIEFING: \"A nagy ismeretlen áll előttünk, bármi várhat ránk. Csak azt tudjuk, hogy még két szintes ez a város. Az átjáró helyének kivételével a küldetés megszakítása ikon befejezi a küldetést.\"\n  STR_TLETH_ATTACK_MISSION: \"T'LETH TÁMADÁSA{NEWLINE}IDEGEN VÁROS: MÁSODIK SZINT\"\n  STR_TLETH_P2_BRIEFING: \"Még mindig sötétben tapogatózunk, bármi megtörténhet. Ismét el kell verekednünk magunkat valahogy az átjáróig, hogy továbbjuthassunk.\"\n  STR_FINAL_TLETH_MISSION: \"T'LETH: UTOLSÓ KÜLDETÉS{NEWLINE}IDEGEN VÁROS: HARMADIK SZINT\"\n  STR_TLETH_P3_BRIEFING: \"A cél közel! Keresd meg a Végső Idegen kriptáját és rombold le a 8 tápellátását. Ezzel pontot teszel a háború végére. Ne add fel!\"\n  STR_TLETH_P1: \"IDEGEN VÁROS ELSŐ SZINT\"\n  STR_TLETH_P2: \"IDEGEN VÁROS MÁSODIK SZINT\"\n  STR_TLETH_P3: \"IDEGEN VÁROS HARMADIK SZINT\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"NINCS SZABAD DOKK A KÉTÉLTŰ GYÁRTÁSÁHOZ!{SMALLLINE}Minden kétéltű egy dokkot foglal el azon a bázison, amelyen állomásozik, illetve ahová átcsoportosítod, megvásárolod vagy legyártod.  Építs egy új dokkot vagy csoportosíts át egy kétéltűt egy másik bázisra.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"NINCS SZABAD DOKK A KÉTÉLTŰ VÁSÁRLÁSÁHOZ!{SMALLLINE}Minden kétéltű egy dokkot foglal el azon a bázison, amelyen állomásozik, illetve ahová átcsoportosítod, megvásárolod vagy legyártod. Építs egy új dokkot vagy csoportosíts át egy kétéltűt egy másik bázisra.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"NINCS SZABAD DOKK A KÉTÉLTŰ ÁTCSOPORTOSÍTÁSÁHOZ!{SMALLLINE}Minden kétéltű egy dokkot foglal el azon a bázison, amelyen állomásozik, illetve ahová átcsoportosítod, megvásárolod vagy legyártod. Építs egy új dokkot vagy csoportosíts át egy kétéltűt egy másik bázisra.\"\n  STR_CANNOT_BUILD_HERE: \"NEM ÉPÍTHETSZ IDE!{SMALLLINE}Építkezni csak egy már létező épület mellé lehet.\"\n  STR_NO_FREE_ACCOMODATION: \"NINCS SZABAD LAKÓHELY!{SMALLLINE}A célbázis nem rendelkezik a lakónegyedeiben elegendő hellyel.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"NINCS ELÉG MŰHELY!{SMALLLINE}Építs új műhelyt, vagy csökkentsd a munkát más programokon.\"\n  STR_NOT_ENOUGH_MONEY: \"NINCS ELÉG PÉNZ!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"NINCS ELÉG RAKTÁRHELY!{SMALLLINE}Építs új raktárat vagy küldj át néhány dolgot más bázisokra.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"NINCS ELÉG LAKÓHELY!{SMALLLINE}Építs új lakónegyedeket vagy küldj át valamennyi személyzetet más bázisokra.\"\n  STR_LAUNCH_INTERCEPTION: \"ELFOGÁS INDÍTÁSA\"\n  STR_CRAFT: \"GÉP\"\n  STR_STATUS: \"ÁLLAPOT\"\n  STR_BASE: \"BÁZIS\"\n  STR_READY: \"KÉSZ\"\n  STR_OUT: \"KINT\"\n  STR_REPAIRS: \"JAVÍTJÁK\"\n  STR_REFUELLING: \"TANKOL\"\n  STR_REARMING: \"FEGYVERZIK\"\n  STR_TARGET: \"CÉLPONT: {0}\"\n  STR_WAY_POINT: \"TEREPPONT\"\n  STR_ARE_YOU_SURE_CYDONIA: \"Biztos vagy benne, hogy ezt a gépet el akarod küldeni  T'leth-be?\"\n  STR_YES: \"IGEN\"\n  STR_NO: \"NEM\"\n  STR_SELECT_DESTINATION: \"VÁLASSZ CÉLPONTOT\"\n  STR_CYDONIA: \"T'LETH\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"VÁLASSZ HELYET AZ ÚJ BÁZISNAK\"\n  STR_RETURN_TO_BASE: \"VISSZATÉRÉS A BÁZISRA\"\n  STR_SELECT_NEW_TARGET: \"ÚJ CÉLPONT VÁLASZTÁSA\"\n  STR_PATROL: \"ŐRJÁRAT\"\n  STR_STATUS_: \"ÁLLAPOT>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"MEGSÉRÜLT - VISSZATÉR A BÁZISRA\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"KEVÉS AZ ÜZEMANYAG - VISSZATÉR A BÁZISRA\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"KÜLDETÉS VÉGREHAJTVA - VISSZATÉR A BÁZISRA\"\n  STR_PATROLLING: \"ŐRJÁRATBAN\"\n  STR_TAILING_UFO: \"KÖVETI A KÉTÉLTŰT\"\n  STR_INTERCEPTING_UFO: \"ELFOGÁS: {0}. KÉTÉLTŰ\"\n  STR_RETURNING_TO_BASE: \"VISSZATÉR A BÁZISRA\"\n  STR_DESTINATION_UC_: \"CÉL: {0}\"\n  STR_BASE_UC: \"BÁZIS>{ALT}{0}\"\n  STR_SPEED_: \"SEBESSÉG>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"MAXIMÁLIS SEBESSÉG>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"MÉLYSÉG>{ALT}{0}\"\n  STR_AIRBORNE: \"LEVEGŐBEN\"\n  STR_VERY_LOW: \"FELSZÍNEN\"\n  STR_LOW_UC: \"NORMÁL\"\n  STR_HIGH_UC: \"MÉLYEN\"\n  STR_VERY_HIGH: \"NAGYON MÉLYEN\"\n  STR_FUEL: \"ÜZEMANYAG>{ALT}{0}\"\n  STR_WEAPON_ONE: \"1. FEGYVER>{ALT}{0}\"\n  STR_NONE_UC: \"SEMMI\"\n  STR_ROUNDS_: \"LŐSZER>{ALT}{0}\"\n  STR_WEAPON_TWO: \"2. FEGYVER>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"KÉTÉLTŰ\"\n  STR_BASE_: \"Bázis>{0}\"\n  STR_NAME_UC: \"NÉV\"\n  STR_AMMO_: \"LŐSZER>{ALT}{0}\"\n  STR_CREW: \"LEGÉNYSÉG\"\n  STR_EQUIPMENT_UC: \"FELSZERELÉS\"\n  STR_ARMOR: \"PÁNCÉL\"\n  STR_MAX: \"MAX>{ALT}{0}\"\n  STR_ROOKIE: \"Matróz\"\n  STR_SQUADDIE: \"Altiszt\"\n  STR_SERGEANT: \"Zászlós\"\n  STR_CAPTAIN: \"Korvetthadnagy\"\n  STR_COLONEL: \"Altengernagy\"\n  STR_COMMANDER: \"Tengernagy\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Válassz osztagot a(z) {0} szállítóra\"\n  STR_SORT_BY: \"RENDEZÉS...\"\n  STR_ORIGINAL_ORDER: \"EREDETI SORREND\"\n  STR_MISSIONS2: \"KÜLDETÉSEK\"\n  STR_KILLS2: \"ÖLÉSEK\"\n  STR_WOUND_RECOVERY2: \"SEBGYÓGYULÁS\"\n  STR_SPACE_AVAILABLE: \"SZABAD HELY>{ALT}{0}\"\n  STR_SPACE_USED: \"FOGLALT HELY>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"FOGLALT HELY\"\n  STR_RANK: \"RENDFOKOZAT\"\n  STR_WOUNDED: \"SEBESÜLT\"\n  STR_EQUIPMENT_FOR_CRAFT: \"{0}-n lévő felszerelések\"\n  STR_DEFENSE_VALUE: \"Védelmi érték\"\n  STR_HIT_RATIO: \"Találati arány\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}készen áll{NEWLINE}a leszállásra:{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"Kezdődhet a küldetés?\"\n  STR_SELECT_ARMAMENT: \"Válassz fegyverzetet\"\n  STR_AMMUNITION_AVAILABLE: \"ELÉRHETŐ LŐSZER\"\n  STR_ARMAMENT: \"FEGYVERZET\"\n  STR_NOT_AVAILABLE: \"N.A.\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"PÁNCÉLVÁLASZTÁS:{NEWLINE}{0}\"\n  STR_TYPE: \"TÍPUS\"\n  STR_PLASTIC_AQUA_ARMOR_UC: \"VÍZMŰANYAG PÁNCÉL\"\n  STR_ION_ARMOR_UC: \"IONPÁNCÉL\"\n  STR_MAGNETIC_ION_ARMOR_UC: \"MÁGNESES IONPÁNCÉL\"\n  STR_PLASTIC_AQUA_ARMOR_UFOPEDIA: \"A páncél az újonnan felfedezett vízműanyagból készül és hatékonyabb fellépést biztosít az akvanautáinknak az idegenek ellen.\"\n  STR_ION_ARMOR_UFOPEDIA: \"A páncél az ion enrgiaforrás által nagyobb védelmet biztosít és nagyban növeli a viselőjének sebességét és erejét. A harci csapatok jobb védelmét ígéri.\"\n  STR_MAGNETIC_ION_ARMOR_UFOPEDIA: \"Az ionpáncél ötvözése a mágnestömb technológiával a vízalatti környezetben teljes mozgási szabadságot biztosít.\"\n  STR_SELECT_ARMOR: \"Válassz páncélt\"\n  STR_NORTH: \"ÉSZAK\"\n  STR_NORTH_EAST: \"ÉSZAKKELET\"\n  STR_EAST: \"KELET\"\n  STR_SOUTH_EAST: \"DÉLKELET\"\n  STR_SOUTH: \"DÉL\"\n  STR_SOUTH_WEST: \"DÉLNYUGAT\"\n  STR_WEST: \"NYUGAT\"\n  STR_NORTH_WEST: \"ÉSZAKNYUGAT\"\n  STR_SELECT_ACTION: \"VÁLASSZ MŰVELETET\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"FOLYTASD AZ ELFOGÓ ÜLDÖZÉST\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"ELFOGÁS NÉLKÜLI ÜLDÖZÉS\"\n  STR_VERY_LARGE: \"NAGYON NAGY\"\n  STR_LARGE: \"NAGY\"\n  STR_MEDIUM_UC: \"KÖZEPES\"\n  STR_SMALL: \"KICSI\"\n  STR_VERY_SMALL: \"NAGYON KICSI\"\n  STR_GROUNDED: \"LESZÁLLT\"\n  STR_DETECTED: \"Észlelve\"\n  STR_SIZE_UC: \"MÉRET\"\n  STR_ALTITUDE: \"MÉLYSÉG\"\n  STR_HEADING: \"IRÁNY\"\n  STR_SPEED: \"SEBESSÉG\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"KÉTÉLTŰRE ÁLL-IDŐ=5 Mp\"\n  STR_TRACKING_LOST: \"NYOMA VESZETT\"\n  STR_REDIRECT_CRAFT: \"GÉP ÁTIRÁNYÍTÁSA\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"MENJ A KÉTÉLTŰ UTOLSÓ ISMERT POZÍCIÓJÁRA\"\n  STR_UFO_: \"{0}. IDEGEN KÉTÉLTŰ\"\n  STR_ALIEN_BASE_: \"{0}. IDEGEN BÁZIS\"\n  STR_CRASH_SITE_: \"{0}. LEZUHANÁSI HELY\"\n  STR_LANDING_SITE_: \"{0}. LESZÁLLÁSI HELY\"\n  STR_WAY_POINT_: \"{0}. TEREPPONT\"\n  STR_TERROR_SITE: \"{0}. TERROR HELY\"\n  STR_ARTIFACT_SITE: \"{0}. LELET HELYE\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}célba ért:{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"Most őrjáratban van\"\n  STR_ALIEN_ORIGINS: \"Idegen eredet\"\n  STR_THE_ULTIMATE_THREAT: \"A végső fenyegetés\"\n  STR_TLETH_ALIEN_CITY: \"T'leth, az idegenek városa\"\n  STR_UFOPAEDIA: \"UFOpédia\"\n  STR_XCOM_CRAFT_ARMAMENT: \"X-COM GÉP ÉS FEGYVERZET\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"VÍZALATTI FEGYVERZET PROGRAM (VFP)\"\n  STR_WEAPONS_AND_EQUIPMENT: \"FEGYVEREK ÉS FELSZERELÉS\"\n  STR_ALIEN_ARTIFACTS: \"IDEGEN SZERKEZETEK\"\n  STR_BASE_FACILITIES: \"BÁZIS ÉPÜLETEI\"\n  STR_ALIEN_LIFE_FORMS: \"IDEGEN ÉLETFORMÁK\"\n  STR_ALIEN_RESEARCH_UC: \"IDEGEN KUTATÁS\"\n  STR_UFO_COMPONENTS: \"VÍZALATTI TECHNOLÓGIA\"\n  STR_UFOS: \"IDEGEN KÉTÉLTŰEK\"\n  STR_SELECT_ITEM: \"VÁLASSZ TÉTELT\"\n  STR_ACCELERATION: \"GYORSULÁS>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"ÜZEMANYAG-KAPACITÁS>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"FEGYVERFOGLALATOK>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"SÉRÜLÉSTŰRÉS>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"RAKODÓKAPACITÁS>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"VFP KAPACITÁS>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Roncsolás\"\n  STR_RANGE: \"Hatótáv\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Pontosság\"\n  STR_RE_LOAD_TIME: \"Újratöltési idő\"\n  STR_SECONDS: \"{0} mp.\"\n  STR_DAMAGE_ARMOR_PIERCING: \"PÁNCÉLTÖRŐ\"\n  STR_DAMAGE_INCENDIARY: \"GYÚJTÓ\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"DETONÁCIÓS\"\n  STR_DAMAGE_LASER_BEAM: \"GAUSS SUGÁR\"\n  STR_DAMAGE_PLASMA_BEAM: \"SZÓNIKUS SUGÁR\"\n  STR_DAMAGE_STUN: \"FAGYASZTÁS\"\n  STR_DAMAGE_MELEE: \"KÖZELHARC\"\n  STR_DAMAGE_ACID: \"SAV\"\n  STR_DAMAGE_SMOKE: \"FÜST\"\n  STR_SHOT_TYPE: \"TÍPUS\"\n  STR_ACCURACY_UC: \"PONTOSSÁG\"\n  STR_TIME_UNIT_COST: \"IE KÖLTSÉG\"\n  STR_DAMAGE_UC: \"RONCSOLÁS\"\n  STR_AMMO: \"LŐSZER\"\n  STR_SHOT_TYPE_AUTO: \"Automata\"\n  STR_SHOT_TYPE_SNAP: \"Kapás\"\n  STR_SHOT_TYPE_AIMED: \"Célzott\"\n  STR_CONSTRUCTION_TIME: \"Építési idő\"\n  STR_CONSTRUCTION_COST: \"Építés költsége\"\n  STR_MAINTENANCE_COST: \"Fenntartás költsége\"\n  STR_LOW: \"Alacsony\"\n  STR_MEDIUM: \"Közepes\"\n  STR_HIGH: \"Magas\"\n  STR_CRAFT_WEAPON: \"Kétéltű fegyver\"\n  STR_CRAFT_AMMUNITION: \"Kétéltű lőszer\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Vízalatti Fegyverzet Program\"\n  STR_WEAPON: \"Fegyver\"\n  STR_AMMUNITION: \"Lőszer\"\n  STR_EQUIPMENT: \"Felszerelés\"\n  STR_ALIEN_CORPSE: \"Idegen tetem\"\n  STR_UFO_COMPONENT: \"IDEGEN KÉTÉLTŰ ALKATRÉSZ\"\n  STR_PERSONAL_ARMOR: \"Személyi páncél\"\n  STR_RAW_MATERIALS: \"Nyersanyagok\"\n  STR_HWP_SOLID_HARPOON_BOLTS: \"VFP lövedék\"\n  STR_ALIEN: \"Idegen\"\n  STR_AQUATOID: \"Akvatoid\"\n  STR_GILLMAN: \"Kopoltyús\"\n  STR_LOBSTERMAN: \"Rákember\"\n  STR_TASOTH: \"Tasoth\"\n  STR_CALCINITE: \"Kalcinit\"\n  STR_DEEP_ONE: \"Mélységi\"\n  STR_BIODRONE: \"Biodrón\"\n  STR_TENTACULAT: \"Csápolat\"\n  STR_TRISCENE: \"Triszcén\"\n  STR_HALLUCINOID: \"Hallucinoid\"\n  STR_XARQUID: \"Xarkvid\"\n  STR_ZOMBIE: \"Zombi\"\n  STR_LIVE_COMMANDER: \"Parancsnok\"\n  STR_LIVE_NAVIGATOR: \"Navigátor\"\n  STR_LIVE_MEDIC: \"Orvos\"\n  STR_LIVE_TECHNICIAN: \"Mérnökök\"\n  STR_LIVE_SQUAD_LEADER: \"Csapatvezető\"\n  STR_LIVE_SOLDIER: \"Katona\"\n  STR_LIVE_TERRORIST: \"Terrorista\"\n  STR_AQUATOID_COMMANDER: \"Akvatoid parancsnok\"\n  STR_AQUATOID_NAVIGATOR: \"Akvatoid navigátor\"\n  STR_AQUATOID_MEDIC: \"Akvatoid orvos\"\n  STR_AQUATOID_TECHNICIAN: \"Akvatoid mérnök\"\n  STR_AQUATOID_SQUAD_LEADER: \"Akvatoid csapatvezető\"\n  STR_AQUATOID_SOLDIER: \"Akvatoid katona\"\n  STR_GILLMAN_COMMANDER: \"Kopoltyús parancsnok\"\n  STR_GILLMAN_TECHNICIAN: \"Kopoltyús mérnök\"\n  STR_GILLMAN_SQUAD_LEADER: \"Kopoltyús csapatvezető\"\n  STR_GILLMAN_SOLDIER: \"Kopoltyús katona\"\n  STR_LOBSTERMAN_COMMANDER: \"Rákember parancsnok\"\n  STR_LOBSTERMAN_NAVIGATOR: \"Rákember navigátor\"\n  STR_LOBSTERMAN_TECHNICIAN: \"Rákember mérnök\"\n  STR_LOBSTERMAN_SQUAD_LEADER: \"Rákember csapatvezető\"\n  STR_LOBSTERMAN_SOLDIER: \"Rákember katona\"\n  STR_TASOTH_SQUAD_LEADER: \"Tasoth csapatvezető\"\n  STR_TASOTH_SOLDIER: \"Tasoth katona\"\n  STR_CALCINITE_TERRORIST: \"Kalcinit terrorista\"\n  STR_DEEP_ONE_TERRORIST: \"Mélységi terrorista\"\n  STR_BIODRONE_TERRORIST: \"Biodrón terrorista\"\n  STR_TENTACULAT_TERRORIST: \"Csápolat terrorista\"\n  STR_TRISCENE_TERRORIST: \"Triszcén terrorista\"\n  STR_HALLUCINOID_TERRORIST: \"Hallucinoid terrorista\"\n  STR_XARQUID_TERRORIST: \"Xarkvid terrorista\"\n  STR_ION_BEAM_ACCELERATORS: \"Ionsugár gyorsítók\"\n  STR_MAGNETIC_NAVIGATION: \"Mágneses navigáció\"\n  STR_ALIEN_SUB_CONSTRUCTION: \"Idegen kétéltű építés\"\n  STR_ALIEN_CRYOGENICS: \"Idegen kriogenetika\"\n  STR_ALIEN_CLONING: \"Idegen klónozás\"\n  STR_ALIEN_LEARNING_ARRAYS: \"Idegen betanítás\"\n  STR_ALIEN_IMPLANTER: \"Idegen beültetés\"\n  STR_EXAMINATION_ROOM: \"Kivizsgálószoba\"\n  STR_AQUA_PLASTICS: \"Vízműanyag\"\n  STR_ALIEN_REANIMATION_ZONE: \"Idegen újraélesztő\"\n  STR_PLASTIC_AQUA_ARMOR: \"Vízműanyag páncél\"\n  STR_ION_ARMOR: \"Ionpáncél\"\n  STR_MAGNETIC_ION_ARMOR: \"Mágneses ionpáncél\"\n  STR_HWP_AQUA_JET_MISSILES: \"VFP torpedók\"\n  STR_HWP_DISPLACER_PWT: \"P.H. torpedó\"\n  STR_GAUSS_TECH: \"Gauss-technológia\"\n  STR_NEW_FIGHTER_FLYING_SUB: \"Új harci kétéltű\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Új harci/szállító gép\"\n  STR_THE_LATEST_FLYING_SUB: \"A végső kétéltű\"\n  STR_ARMOR_PIERCING: \"PÁNCÉLTÖRŐ\"\n  STR_COELACANTH_GAS_CANNON: \"Tank/Gázágyú\"\n  STR_COELACANTH_AQUA_JET: \"Tank/Torpedókilövő\"\n  STR_COELACANTH_GAUSS: \"Tank/Gauss ágyú\"\n  STR_DISPLACER_SONIC: \"Lebegőtank/Szónikus\"\n  STR_DISPLACER_PWT: \"Lebegőtank/P.H.T.\"\n  STR_AJAX_LAUNCHER: \"Ajax kilövő\"\n  STR_DUP_HEAD_LAUNCHER: \"Urániumfejes torpedó kilövő\"\n  STR_CRAFT_GAS_CANNON: \"Kétéltű gázágyú\"\n  STR_PWT_CANNON: \"P.H.T. ágyú\"\n  STR_GAUSS_CANNON: \"Gauss ágyú\"\n  STR_GAUSS_CANNON_AMMO: \"Gauss ágyú lőszer\"\n  STR_SONIC_OSCILLATOR: \"Szónikus oszcillátor\"\n  STR_AJAX_TORPEDOES: \"Ajax torpedó\"\n  STR_DUP_HEAD_TORPEDOES: \"Urániumfejes torpedó\"\n  STR_CRAFT_GAS_CANNON_ROUNDS_X50: \"Gázlövedék(x50)\"\n  STR_SONIC_WAVE: \"Szónikus hullám\"\n  STR_PULSE_WAVE_TORPEDOES: \"P.H.T. muníció\"\n  STR_SOLDIER: \"Akvanauta\"\n  STR_SCIENTIST: \"Tudós\"\n  STR_ENGINEER: \"Mérnök\"\n  STR_NORTH_ATLANTIC: \"Észak-Atlanti\"\n  STR_SOUTH_ATLANTIC: \"Dél-Atlanti\"\n  STR_NORTH_PACIFIC: \"Észak-Csendes-óceán\"\n  STR_SOUTH_PACIFIC: \"Dél-Csendes-óceán\"\n  STR_MEDITERRANEAN: \"Mediterrán\"\n  STR_SOUTH_CHINA_SEA: \"Dél-kínai tenger\"\n  STR_INDIAN_OCEAN: \"Indiai-óceán\"\n  STR_THE_EAST_SEA: \"Japán-tenger\"\n  STR_NORTH_SEA: \"Északi-tenger\"\n  STR_CARRIBEAN: \"Karib-tenger\"\n  STR_ANTARCTIC: \"Antarktisz\"\n  STR_ARCTIC: \"Arktisz\"\n  STR_EURASIA: \"Eurázsia\"\n  STR_NORTH_AMERICA: \"Észak-Amerika\"\n  STR_AFRICA: \"Afrika\"\n  STR_MAXIMUM_SPEED: \"Maximális sebesség\"\n  STR_TRANSMISSION_RESOLVER_UC: \"ADÁSDEKÓDER\"\n  STR_TRITON: \"TRITON\"\n  STR_HAMMERHEAD: \"KALAPÁCSFEJ\"\n  STR_LEVIATHAN: \"LEVIATÁN\"\n  STR_BARRACUDA: \"BARRACUDA\"\n  STR_MANTA: \"MANTA\"\n  STR_UFO: \"IDEGEN KÉTÉLTŰ\"\n  STR_AJAX: \"AJAX\"\n  STR_DUP_HEAD: \"URÁNIUMFEJES\"\n  STR_CRAFT_GAS_CANNON_UC: \"KÉTÉLTŰ GÁZÁGYÚ\"\n  STR_PWT_CANNON_UC: \"P.H.T. ÁGYÚ\"\n  STR_GAUSS_CANNON_UC: \"GAUSS ÁGYÚ\"\n  STR_SONIC_OSCILLATOR_UC: \"SZÓNIKUS OSZCILLÁTOR\"\n  STR_DAMAGE_CAPACITY: \"Sérüléstűrés\"\n  STR_WEAPON_POWER: \"Tűzerő\"\n  STR_WEAPON_RANGE: \"Hatótávolság\"\n  STR_AIR_LOCK: \"Légzsilip\"\n  STR_LABORATORY: \"Laboratórium\"\n  STR_WORKSHOP: \"Műhely\"\n  STR_STANDARD_SONAR: \"Szonár\"\n  STR_WIDE_ARRAY_SONAR: \"Szélessávú szonár\"\n  STR_TORPEDO_DEFENSES: \"Torpedó védelem\"\n  STR_GENERAL_STORES: \"Raktár\"\n  STR_ALIEN_CONTAINMENT: \"Idegen tároló\"\n  STR_GAUSS_DEFENSES: \"Gauss védelem\"\n  STR_SONIC_DEFENSES: \"Szónikus védelem\"\n  STR_PWT_DEFENSES: \"P.H.T. védelem\"\n  STR_BOMBARDMENT_SHIELD: \"Bombázópajzs\"\n  STR_MC_GENERATOR: \"M.I. pajzs\"\n  STR_MC_LAB: \"M.I. labor\"\n  STR_TRANSMISSION_RESOLVER: \"Adásdekóder\"\n  STR_SUB_PEN: \"Dokk\"\n  STR_USA: \"USA\"\n  STR_ALASKA: \"ALASZKA\"\n  STR_EU_SYNDICATE: \"EURO-SZINDIKÁTUS\"\n  STR_ARABIAN_BLOC: \"ARAB BLOKK\"\n  STR_EGYPTIAN_CARTEL: \"EGYIPTOMI KARTELL\"\n  STR_AFRICA_CORP: \"AFRIKA TEST\"\n  STR_BRAZILIAN_UNION: \"BRAZIL UNIÓ\"\n  STR_NEW_MEXICO: \"ÚJ-MEXIKÓ\"\n  STR_ASIAN_COALITION: \"ÁZSIAI KOALÍCIÓ\"\n  STR_SCANDINAVIA: \"SKANDINÁVIA\"\n  STR_NEO_JAPAN: \"ÚJ-JAPÁN\"\n  STR_FREE_CHINA: \"SZABAD KÍNA\"\n  STR_AUSTRALASIA: \"AUSZTRÁLÁZSIA\"\n  STR_FED_KOREA: \"SZÖV. KOREA\"\n  STR_EURASIA_UC: \"EURÁZSIA\"\n  STR_ICELANDIC_UNION: \"IZLANDI UNIÓ\"\n  STR_TANK: \"Vízalatti fegyverzet program\"\n  STR_CIVILIAN: \"Civil\"\n  STR_JAN: \"Jan\"\n  STR_FEB: \"Feb\"\n  STR_MAR: \"Már\"\n  STR_APR: \"Ápr\"\n  STR_MAY: \"Máj\"\n  STR_JUN: \"Jún\"\n  STR_JUL: \"Júl\"\n  STR_AUG: \"Aug\"\n  STR_SEP: \"Szep\"\n  STR_OCT: \"Okt\"\n  STR_NOV: \"Nov\"\n  STR_DEC: \"Dec\"\n  STR_INTERNATIONAL_RELATIONS: \"Nemzetközi kapcsolatok\"\n  STR_COUNTRY: \"Ország\"\n  STR_FUNDING: \"Támogatás\"\n  STR_CHANGE: \"Változás\"\n  STR_WEAPON_SYSTEMS: \"FEGYVERRENDSZER\"\n  STR_HWPS: \"VFP-k\"\n  STR_DAMAGE_UC_: \"RONGÁLÓDÁS>{ALT}{0}\"\n  STR_AIR_LOCK_UFOPEDIA: \"A központi zsilipen keresztül történik a személy- és az anyagforgalom a vízalatti bázisba. Mindig ez az első épület amely az új helyen épül. A zsilip területe a legsebezhetőbb pont bármilyen lehetséges ellenséges erő behatolása esetén.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Minden lakóblokk maximum 50 személy ellátásáról gondoskodik. A blokk tartalmaz pihenő-, alvó-, étkezőterületeket, valamint kisebb edzőtermeket.\"\n  STR_LABORATORY_UFOPEDIA: \"Maximum 50 tudós képes egyszerre dolgozni egy laboratóriumban. A laborok a legmodernebb felszereléssel vannak ellátva akár anyagvizsgálatról, biokémiáról vagy kozmológiáról van szó. Megkülönböztetett hozzáféréssel rendelkezik a világ kutatólaboratóriumainak legjobbjaihoz, sőt katonai laborokhoz is.\"\n  STR_WORKSHOP_UFOPEDIA: \"Egy ilyen műhely minden felszerelést tartalmaz, amely szükséges a kutatólaboratóriumok eredményeinek megvalósításához. Maximum 50 mérnök képes egyszerre dolgozni egyben, de helyigényes termelés elfoglalhat némi plusz helyet.\"\n  STR_STANDARD_SONAR_UFOPEDIA: \"A szonár hatótávolsága kb. 450 km a legtöbb mélységi szinten. Csatlakozik geostacionárius műholdas rendszerekhez, melyek szintén segítik a keresést. Minden rendszer 10%-os eséllyel rendelkezik 30 percenként egy vízalatti vagy atmoszférában tartózkodó tárgy felfedezésére.\"\n  STR_WIDE_ARRAY_SONAR_UFOPEDIA: \"A szélessávú szonár hatotávolsága kb. 700 km minden mélységi szinten. Csatlakozik geostacionárius műholdas rendszerekhez, melyek szintén segítik a keresést. Minden rendszer 20%-os eséllyel rendelkezik 30 percenként egy vízalatti vagy atmoszférában tartózkodó tárgy felfedezésére.\"\n  STR_TORPEDO_DEFENSES_UFOPEDIA: \"A torpedós védelem gondoskodik némi védelemről, ha egy ellenséges gép próbálna leszállni a bázis közelében.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"Minden felszerelés, fegyverrendszer, lőszer, küldetésből beszerzett anyag, valamint VFR a raktárakban kerül elhelyezésre, kivéve a dokkbeli kétéltűkön elhelyezett felszerelést.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"Az élő idegeneknek egy speciális lakóhelyet kell biztosítani életben maradásuk érdekében. Ezekben teljesen ártalmatlanná válnak. A tárolórendszer egyszerre 10 idegent képes tárolni.\"\n  STR_GAUSS_DEFENSES_UFOPEDIA: \"A Gauss védelem a legújabb és leghatásosabb védelem ellenséges kétéltű behatolásával szemben.\"\n  STR_SONIC_DEFENSES_UFOPEDIA: \"A Szónikus védelem erőteljes és hatásos védelemről gondoskodik az ellenséggel szemben.\"\n  STR_PWT_DEFENSES_UFOPEDIA: \"A Pulzushullám torpedók a leghatékonyabb védelem idegen támadás esetén. Ezen torpedók rendkívüli áthatolóképességű robbanófejei minden ismert páncélzaton áthatolnak. Másodsorban mágneses hullámokat is gerjesztenek, amely működésképtelenné teszi az elektronikus védelmet.\"\n  STR_BOMBARDMENT_SHIELD_UFOPEDIA: \"A Nyomásbombázó pajzs visszataszítja a dokkoláshoz készülődő idegen kétéltűt egy rezonáló mezőt létrehozva, elég időt nyerve így a védelmi rendszereknek az újbóli tüzeléshez. Gyakorlatilag megduplázza bármely védelmi rendszer hatékonyságát.\"\n  STR_MC_GENERATOR_UFOPEDIA: \"Mivel az idegen kétéltűk a Molekuláris irányítás technológiáját használják az élő teremtmények felfedezésére, egy negatív M.I. gerjesztő leárnyékolja a bázist. Ez az épület drasztikusan csökkenti az idegenek esélyét a bázis felfedezését illetően.\"\n  STR_MC_LAB_UFOPEDIA: \"A Molekuláris irányítás labor egyszerre 10 akvanautát képezhet és végezhet rajtuk beültetést. Intenzív gyakorlatokkal fejlesztik a beültetések használatát. A Molekuláris eszközökkel együtt támadásra használható harc közben.\"\n  STR_TRANSMISSION_RESOLVER_UFOPEDIA: \"Az idegenek közti kommunikáció egy általuk épített Molekuláris irányítás beültetés hálózaton alapszik. Az épület segítségével lehetőség nyílik az idegen kétéltűk üzeneteinek elfogására, dekódolására. Kideríthető a kétéltű, az idegen faj, a tevékenység típusa.\"\n  STR_SUB_PEN_UFOPEDIA: \"Minden dokk egy kétéltű befogadására alkalmas; egyben tartalmazza a szükséges fenntartó, javító, feltöltő egységeket. Minden kétéltű egy bázison állomásozik és egy dokk tartozik hozzá, melyet más kétéltű még akkor sem használhat, ha esetleg ez éppen küldetést teljesít.\"\n  STR_DART_PISTOL_UFOPEDIA: \"Az X-Com nyílpuska kicsi, pontos, nagy erejű egység 12 üreges nyilat tartalmazó tárral. A nyilak kilövését a tárban elhelyezett gáztartály biztosítja.\"\n  STR_JET_HARPOON_UFOPEDIA: \"Ez a szigonypuska pontos és erőteljes, a 10-es tárból az üreges szigonyokat lövi ki. Minden szigony maga tartalmazza a gáztartályát.\"\n  STR_GAS_CANNON_UFOPEDIA: \"A gáztechnológia nehézsúlyú fegyvere. Töltényei lehetnek páncéltörők, robbanófejes vagy foszforos. A tapasztalt akvanauták kedvence.\"\n  STR_HYDRO_JET_CANNON_UFOPEDIA: \"A hidrolöveg ötlete a nehéz gyalogságtól származik. A löveg magnézium üzemanyagú mini-torpedókat lő ki. Habár nagy erejű, a hidrolöveg ormótlan és esetlen fegyver, csak víz alatt használható.\"\n  STR_TORPEDO_LAUNCHER_UFOPEDIA: \"Egy igazi nehézsúlyú. Ez a kilövő háromféle torpedót képes kilőni, mindegyike saját meghajtással rendelkezik. Manuális töltésű, pusztító fegyver. A torpedók: nagyobb vagy kisebb robbanótorpedók vagy foszforos torpedó. Csak vízalatti használatra.\"\n  STR_GAUSS_PISTOL_UFOPEDIA: \"A Gauss pisztoly a részecskegyorsító technológia terméke, a modern hadviselés fejlesztése. Gyors, pontos, víz alatt és fölött egyaránt használható. Az előző háború plazmatechnológiájának továbbfejlesztése.\"\n  STR_GAUSS_PISTOL_CLIP_UFOPEDIA: \"A Gauss pisztoly a részecskegyorsító technológia terméke, a modern hadviselés fejlesztése. Gyors, pontos, víz alatt és fölött egyaránt használható. Az előző háború plazmatechnológiájának továbbfejlesztése.\"\n  STR_GAUSS_RIFLE_UFOPEDIA: \"A pisztolyon túllépve a puska már sokkal erősebb fegyver. Iker részecskegyorsító váltotta fel az Elerium üzemű plazmarendszert, amely mikro-részecskegyorsítójában anti-proton sugarat hoz létre.\"\n  STR_GAUSS_RIFLE_CLIP_UFOPEDIA: \"A pisztolyon túllépve a puska már sokkal erősebb fegyver. Iker részecskegyorsító váltotta fel az Elerium üzemű plazmarendszert, amely mikro-részecskegyorsítójában anti-proton sugarat hoz létre.\"\n  STR_HEAVY_GAUSS_UFOPEDIA: \"A nehézgauss kényelmetlen, de rendkívül hatásos. Három részecskegyorsító, így látszólag folyamatos üzemű. Az anti-proton sugarat a gallium-arzenid héjon belül bombázott antianyagból nyeri.\"\n  STR_HEAVY_GAUSS_CLIP_UFOPEDIA: \"A nehézgauss kényelmetlen, de rendkívül hatásos. Három részecskegyorsító, így látszólag folyamatos üzemű. Az anti-proton sugarat a gallium-arzenid héjon belül bombázott antianyagból nyeri.\"\n  STR_MAGNA_BLAST_GRENADE_UFOPEDIA: \"Ez a szabványgránát pontos, kifinomult időzítővel rendelkezik.\"\n  STR_DYE_GRENADE_UFOPEDIA: \"A festékgránát takarásról gondoskodik, hasznos kihegyezett harci helyzetekben. Egyaránt működik vízi és szárazföldi környezetben. A festékrészecskéket szétterítve tintahal-szerű festékfelhőt hoz létre.\"\n  STR_PARTICLE_DISTURBANCE_GRENADE_UFOPEDIA: \"A szomszédgránát ugyanúgy használatos, mint egy normális gránát, de ez landolása után közeli mozgásra aktiválódik. Nagy ügyesség és odafigyelés szükséges használatához.\"\n  STR_MAGNA_PACK_EXPLOSIVE_UFOPEDIA: \"A robbanószer kizárólag rombolási célokat szolgál. Azonban a múltbeli tapasztalatok szerint ideális fegyverek az idegenek irtására. Igen nagy sugarú a robbanás hatótávolsága, ezért vigyázz az embereidre.\"\n  STR_PARTICLE_DISTURBANCE_SENSOR_UFOPEDIA: \"Ez a kifinomult eszköz érzékelők tucatját tartalmazza, melyek jelzései alapján képes behatárolni a vízben mozgó ellenséges egységeket. Kattints a zavarérzékelő ikonra a taktikai kijelzőn. Válaszd ki a 'Zavarérzékelő'-t a menüből. A kijelző középre egy nyilat tesz, mely arra mutat, amerre az akvanauta néz (Észak van fent). A villogó foltok az előzőleg mozgó egységeket jelzik. Nagyobb vagy gyorsabb egységek nagyobb foltokat eredményeznek. A mozdulatlan egységek nem kerülnek kijelzésre.\"\n  STR_MEDI_KIT_UFOPEDIA: \"Az elsősegély-csomag használatához a páciens mellett, felé fordulva kell állni.{NEWLINE}GYÓGYITÁS> A vörös testrészek végzetes sebeket jeleznek. Kattints a sebesült testrészre. Kattints a 'Gyógyít' gombra. Egy végzetes seb meg lesz gyógyítva.{NEWLINE}STIMULÁNS> Visszaállitja az energiáját és újraéleszti a lebénult katonákat. A bénult katona fölé kell állni.{NEWLINE}FÁJDALOMCSILLAPÍTÓ> Vissza- állítja a sebesült akvanauta morálját.\"\n  STR_MC_DISRUPTOR_UFOPEDIA: \"A M.I. technológia csúcsa. Víz alatt használhatják M.I. képzést kapott akvanauták. Kattints a Megszakítóra, válaszd ki a támadás típusát, majd válaszd ki az áldozatot. Kétféle támadás lehetséges:{NEWLINE}MEGKEVERÉS> Ha sikeres, az áldozat megzavarodhat és pánikba eshet.{NEWLINE}IRÁNYÍTÁS> Ha sikerül, átveheted az irányítást az áldozat felett.\"\n  STR_THERMAL_TAZER_UFOPEDIA: \"Ez az eszköz csak test-test elleni harcban használható. Képes ölés nélkül megbénítani egy élő szervezetet.\"\n  STR_VIBRO_BLADE_UFOPEDIA: \"A vibropenge egy hosszú, éles titániumpenge, mely több, mint hatezerszer rezeg másodpercenként. A legkeményebb páncélon is áthatol. Az erőforrása idegen találmány. A találkozásunk előtti pengéink vagy túl lassúak voltak, vagy nyomás alatt szétrobbantak.\"\n  STR_THERMIC_LANCE_UFOPEDIA: \"A termolándzsa a vibropenge technológia logikai továbbvitele. A penge rezeg, a Zrbite erőforrás pedig még túl is fűti. Úgy vág, mint meleg kés a vajat.\"\n  STR_HEAVY_THERMIC_LANCE_UFOPEDIA: \"A nehéz termolándzsa a termolándzsa erősebb verziója. Iker hőforrás és extrém rezgési gyorsaság jellemzi, ezért látszólag semmi sem képes ellenállni neki\"\n  STR_SONIC_CANNON_UFOPEDIA: \"A Szónikus ágyú a legerősebb a szónikus fegyverek családjában. Nagyobb visszhangosító kamrával és szélesebb sávú rezgéskeltővel rendelkezik, mint a puska. Az ágyú pulzusdetonációs rendszere modulálja az ultrahangot és ezért képes sokkal hatékonyabb szónikus sokkot okozni.\"\n  STR_CANNON_POWER_CLIP_UFOPEDIA: \"Ez a kis eszköz a szónikus ágyú lőszere. Kis mennyiségű Zrbite van benne.\"\n  STR_SONIC_BLASTA_RIFLE_UFOPEDIA: \"Egy még erősebb szónikus eszköz. Még a szerszámacél sem képes ellenállni neki. Az öngerjesztő hullámgenerátor hatását egy szupravezető erősítő fokozza tovább.\"\n  STR_BLASTA_POWER_CLIP_UFOPEDIA: \"Ez a kis eszköz a szónikus puska - egy hathatós idegen fegyver - lőszere. Kis mennyiségű Zrbite van benne.\"\n  STR_SONIC_PISTOL_UFOPEDIA: \"A szónikus pisztolyok idegen fegyverek, melyek az ultrahang-hullámok csontokat is kocsonyává változtató hatásán alapulnak. Az ultrahang az ember számára hallhatatlan.\"\n  STR_PISTOL_POWER_CLIP_UFOPEDIA: \"A szónikus pisztoly lőszere. Zrbite van benne - ez minden idegen erő forrása.\"\n  STR_DISRUPTOR_PULSE_LAUNCHER_UFOPEDIA: \"Ez egy idegen fegyver, csak vízben működőképes, célra tartó szakító lövedékeket lő ki. Amikor lőni akarsz a fegyverrel, összeállíthatsz egy útvonalat, amelyet a lövedék követ. Amikor már elég pontot kijelöltél, kattints a speciális kilövés ikonra.\"\n  STR_DISRUPTOR_AMMO_UFOPEDIA: \"Ez az automata célra vezérlő eszköz nagy erejű robbanást produkál. A szakító lövedék kilövő használatával juttatható célba.\"\n  STR_THERMAL_SHOK_LAUNCHER_UFOPEDIA: \"A termosokk kilövő kémiai bénító bombákat lő ki. Nagyon hasznos élő idegenek elfogására.\"\n  STR_THERMAL_SHOK_BOMB_UFOPEDIA: \"A termosokk bomba élő emberi egyedek elfogására használatos. Ettől függetlenül használható a legtöbb idegen faj ellen is. A termosokk kilövő juttatja célba.\"\n  STR_SONIC_PULSER_UFOPEDIA: \"Ez az eszköz ugyanúgy működik, mint földi megfelelője. Csak sokkal hatékonyabb. Egy egyszeres, de nagy erejű szónikus hullámot produkál minden irányba.\"\n  STR_MC_READER_UFOPEDIA: \"Az idegenek testében kis, sebészetileg beültetett egységek találhatók. Ezek az Irányító beültetések, amelyeket az Akvatoidok terveztek a csata pontos állásának meghatározásához akár nagy távolságból is. Az irányító-leolvasó egy ilyen eszköz, amely az információt a beültetett egységből nyeri. Az X-Com akvanauták az idegenek jellemzőinek meghatározására használhatják csata közben. Válaszd a 'Leolvasó'-t. Ezután válaszd ki az idegent.\"\n  STR_SURVEY_SHIP: \"Felderítő\"\n  STR_ESCORT: \"Kísérő\"\n  STR_CRUISER: \"Cirkáló\"\n  STR_HEAVY_CRUISER: \"Vezércirkáló\"\n  STR_HUNTER: \"Vadász\"\n  STR_BATTLESHIP: \"Csatahajó\"\n  STR_DREADNOUGHT: \"Csapatszállító\"\n  STR_FLEET_SUPPLY_CRUISER: \"Ellátó hajó\"\n  MAP_SEABED: \"Tengerfenék\"\n  MAP_PIPES: \"Kutató bázis\"\n  MAP_PLANE: \"Repülőgéproncs\"\n  MAP_ATLAN: \"Atlantisz\"\n  MAP_MU: \"Maja templom\"\n  MAP_GAL: \"Hajóroncs\"\n  MAP_MSUNK: \"Óceánjáró roncsa\"\n  MAP_VOLC: \"Vulkanikus\"\n  MAP_CORAL: \"Korall\"\n  MAP_PORT: \"Kikötő\"\n  MAP_ISLAND: \"Sziget\"\n  MAP_CARGO: \"Teherhajó\"\n  MAP_LINERT: \"Óceánjáró P1\"\n  MAP_LINERB: \"Óceánjáró P2\"\n  MAP_ALART: \"Szerkezetek P1\"\n  MAP_GRUNGE: \"Szerkezetek P2\"\n  MAP_ENTRY: \"Kolónia P1\"\n  MAP_A_BASE: \"Kolónia P2\"\n  MAP_ALSHIP: \"T'leth L1\"\n  MAP_LEVEL: \"T'leth L2\"\n  MAP_CRYPT: \"T'leth L3\"\n  MAP_XBASES: \"X-Com Bázis\"\n  STR_MIXED_CREW: \"Vegyes legénység\"\n  STR_MIXED_CREW_2: \"Vegyes legénység 2\"\n  STR_RATING: \"ÉRTÉKELÉS> {0}\"\n  STR_RATING_TERRIBLE: \"BORZALMAS!\"\n  STR_RATING_POOR: \"GYENGE!\"\n  STR_RATING_OK: \"OKÉ\"\n  STR_RATING_GOOD: \"JÓ!\"\n  STR_RATING_EXCELLENT: \"KIVÁLÓ!\"\n  STR_SCORE: \"PONTSZÁM\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"X-COM - HAVI JELENTÉS\"\n  STR_MONTH: \"Hónap> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"Az alapító nemzetek tanácsa általában elégedett a haladásoddal.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"Az alapító nemzetek tanácsa rendkívül elégedett a kitűnő eredményeddel. Csak így tovább.\"\n  STR_COUNCIL_IS_DISSATISFIED: \"Az alapító nemzetek tanácsa elégedetlen a teljesítményeddel. Hatékonyabban kell az idegen veszély ellen fellépned, vagy a tervezet befejezését kockáztatod.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"Nem sikerült az invázió ellen hatékonyan fellépned, ezért az alapító nemzetek tanácsa sajnálattal elhatározta a tervezet befejezését. Minden nemzet megpróbálja a saját keretein belül megoldani a problémát. Csak remélni tudjuk, hogy alkalmazkodni tudunk valahogy ezekhez a nyilvánvalóan ellenséges erőkhöz és a népek valahogy kiegyeznek az idegen látogatókkal.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} különösen meg van elégedve a képességeiddel a fenyegetés elhárítását illetően, ezért egyetért a támogatás növelésével.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} különösen örvendenek a helyi idegen portyázásokkal szembeni fellépéseddel ezért egyetértenek a támogatás növelésével.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} és {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} nincs megelégedve a területein belüli idegen tevékenységre való reagálásoddal, ezért eldöntötte, hogy csökkenti a hozzájárulását.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} nincsenek megelégedve a területeiken belüli idegen tevékenységre való reagálásoddal, ezért csökkentik a támogatásukat.\"\n  STR_KNOTS: \"{0} csomó\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} aláírt egy szerződést az idegen erőkkel és visszavonult a tervezettől.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} aláírtak egy szerződést az idegen erőkkel és visszavonultak a tervezettől.\"\n  STR_MONTHLY_RATING: \"Havi értékelés> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Támogatás változása> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"Az alapító tanács nincs megelégedve az anyagi helyzeteddel. Az adósságodat 1 millió dollár alá kell csökkentened vagy a tervezet véget ér.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"SZUBRÉSZECSKE  ADÁSOK DEKÓDOLVA\"\n  STR_CRAFT_TYPE: \"UFO TÍPUS\"\n  STR_RACE: \"FAJ\"\n  STR_MISSION: \"KÜLDETÉS\"\n  STR_ZONE: \"ZÓNA\"\n  STR_ALLOCATE_RESEARCH: \"Kutatás kijelölése\"\n  STR_ALLOCATE_MANUFACTURE: \"Gyártás kijelölése\"\n  STR_AZORES: \"Azori-szigetek\"\n  STR_REYKJAVIK: \"Reykjavík\"\n  STR_BERMUDA: \"Bermuda\"\n  STR_NEW_YORK: \"New York\"\n  STR_BOSTON: \"Boston\"\n  STR_FORT_SEVERN: \"Fort Severn\"\n  STR_DAKAR: \"Dakar\"\n  STR_RECIFE: \"Recife\"\n  STR_ACCRA: \"Accra\"\n  STR_ASCENSION_ISLAND: \"Ascension-sziget\"\n  STR_TRINIDADE_ISLAND: \"Trindade-sziget\"\n  STR_FALKLAND_ISLAND: \"Falkland-sziget\"\n  STR_CANARY_ISLANDS: \"Kanári-szigetek\"\n  STR_ANCHORAGE: \"Anchorage\"\n  STR_ST_LAWRENCE_ISLAND: \"Szt. Lőrinc-sziget\"\n  STR_SAN_FRANCISCO: \"San Francisco\"\n  STR_MIDWAY_ISLAND: \"Midway-szigetek\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_TASMANIA: \"Tasmánia\"\n  STR_HAWAII: \"Hawaii\"\n  STR_FIJI: \"Fidzsi\"\n  STR_TONGA: \"Tonga\"\n  STR_EASTER_ISLAND: \"Húsvét-szigetek\"\n  STR_GALAPAGOS_ISLAND: \"Galápagos-szigetek\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_SOLOMON_ISLAND: \"Salamon-szigetek\"\n  STR_CRETE: \"Kréta\"\n  STR_LISBON: \"Lisszabon\"\n  STR_PORT_SAID: \"Port Szaíd\"\n  STR_MARSEILLES: \"Marseille\"\n  STR_TRIPOLI: \"Tripoli\"\n  STR_MANILA: \"Manila\"\n  STR_HONG_KONG: \"Hong Kong\"\n  STR_SINGAPORE: \"Szingapúr\"\n  STR_BANGKOK: \"Bangkok\"\n  STR_DARWIN: \"Darwin\"\n  STR_BOMBAY: \"Bombay\"\n  STR_SAYCHELLES_ISLAND: \"Seychelle-szigetek\"\n  STR_MALDIVE_ISLAND: \"Maldív-szigetek\"\n  STR_SRI_LANKA: \"Sri Lanka\"\n  STR_MAURITIUS: \"Mauritius\"\n  STR_TOKYO: \"Tokió\"\n  STR_SHANGHAI: \"Sanghaj\"\n  STR_VLADIVOSTOK: \"Vlagyivosztok\"\n  STR_LONDON: \"London\"\n  STR_FAEROE_ISLAND: \"Feröer-szigetek\"\n  STR_ABERDEEN: \"Aberdeen\"\n  STR_OSLO: \"Oslo\"\n  STR_JAMAICA: \"Jamaica\"\n  STR_PANAMA: \"Panama\"\n  STR_MIAMI: \"Miami\"\n  STR_PSI_TRAINING: \"M.I. képzés\"\n  STR_PSIONIC_TRAINING: \"MOLEKURÁLIS IRÁNYÍTÁS KÉPZÉS\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Szabad M.I.-labor kapacitás> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"M.I. {NEWLINE}erő\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"M.I. {NEWLINE}ügyesség/javulás\"\n  STR_IN_TRAINING: \"Kiképzés{NEWLINE}alatt?\"\n  STR_TARGETTED_BY: \"BECÉLOZTA:\"\n  STR_WEAPONS_CREW_HWPS: \"FEGYVEREK/{NEWLINE}LEGÉNYSÉG/VFPk\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"kevés az üzemanyag,{NEWLINE}visszatér a bázisra\"\n  STR_SOLDIER_LIST: \"Akvanauták listája\"\n  STR_RANK_: \"RENDFOKOZAT> {ALT}{0}\"\n  STR_MISSIONS: \"KÜLDETÉSEK> {ALT}{0}\"\n  STR_KILLS: \"ÁLDOZATOK> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"SEBGYÓGYULÁS> {ALT}{0}\"\n  STR_TIME_UNITS: \"IDŐEGYSÉG\"\n  STR_STAMINA: \"ÁLLÓKÉPESSÉG\"\n  STR_HEALTH: \"EGÉSZSÉG\"\n  STR_BRAVERY: \"BÁTORSÁG\"\n  STR_REACTIONS: \"REAKCIÓ\"\n  STR_FIRING_ACCURACY: \"TÜZELÉSI PONTOSSÁG\"\n  STR_THROWING_ACCURACY: \"DOBÁSI PONTOSSÁG\"\n  STR_STRENGTH: \"ERŐ\"\n  STR_PSIONIC_STRENGTH: \"M.I. ERŐ\"\n  STR_PSIONIC_SKILL: \"M.I. ÜGYESSÉG\"\n  STR_NEW_RANK: \"ÚJ RENDFOKOZAT\"\n  STR_PROMOTIONS: \"Előléptetések\"\n  STR_SOLDIERS_UC: \"AKVANAUTÁK\"\n  STR_COELACANTH_GAS_CANNON_UFOPEDIA: \"A vízalatti fegyverzet-program termékei nagy manőverező- képességgel és hatalmas erővel rendelkeznek. Erős támogatást adnak minden mélységben. Újrafelfegyverzése automatikus.\"\n  STR_COELACANTH_AQUA_JET_UFOPEDIA: \"Ez a VFP hatékony torpedókkal van felszerelve. Csak víz alatt működik. A raktáraid legyenek jól ellátva Aqua-Jet torpedókkal.\"\n  STR_COELACANTH_GAUSS_UFOPEDIA: \"A Gauss technológia hatékonyabb VFP-ket tesz lehetővé. Előnye a nagyobb tűzerő a korábbi modellekhez képest.\"\n  STR_DISPLACER_SONIC_UFOPEDIA: \"Az idegen technológia adott egy lökést az VFP-nek. Az Ion áthelyező segítségével nincs többé talajhoz kötve. A szónikus fegyvere pedig igazi előny a csatában.\"\n  STR_DISPLACER_PWT_UFOPEDIA: \"Ez a VFP víz alatt használatos, P.H.T.-val felszerelve. Gyárts elég P.H.T-t, hogy mindig teljesen fel legyen szerelve. A torpedó útvonala megadása után kattints a speciális kilövés ikonra.\"\n  STR_ALIEN_PROBE_MISSION: \"Idegen szondázás\"\n  STR_ALIEN_INTERDICTION: \"Idegen kisajátítás\"\n  STR_ALIEN_RESOURCE_RAID: \"Idegen portya\"\n  STR_ALIEN_INFILTRATION: \"Idegen beszivárgás\"\n  STR_ALIEN_BASE: \"Idegen bázis-bővítés\"\n  STR_ALIEN_SURFACE_ATTACK: \"Idegen felszíni támadás\"\n  STR_ALIEN_RETALIATION: \"Bázis támadás\"\n  STR_ALIEN_SUPPLY: \"Bázis ellátás\"\n  STR_ALIEN_PROBE_MISSION_UFOPEDIA: \"Az idegen szondázás adatok gyűjtése egy területen a tengerfenékről, az erőforrásokról, a hajózási és repülési útvonalakról. Ezek a kétéltűk maguk nem veszélyesek, de jelzik, hogy idővel a területen erősen felfokozódhat az idegen tevékenység.\"\n  STR_ALIEN_INTERDICTION_UFOPEDIA: \"Az idegenek, ha egy területet ki akarnak maguknak sajátítani, kiküldenek egy kétéltűt, amellyel biztosítják a terepet, mielőtt bármi intenzív tevékenységet indítanának. A megfelelő helyet megtalálva nekiállnak lezárni a terepet, előkészítve a következő lépésre.\"\n  STR_ALIEN_RESOURCE_RAID_UFOPEDIA: \"A hajók elsüllyesztése, a repülőgépek lelövése az idegen stratégia alapelemei. Az ásványok, erőforrások megszerzése szintén az elsődleges céljaik között vannak, ezért is gyakori a feltűnésük geotermikus aktivitások helyei, bányák, kohók közelében.\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"Földi kormányzatokba beszivároghatnak idegen ügynökök emberi megjelenéssel. Ez hivatalos kapcsolatot eredményezhet az idegenek és a kormányzatok között a legmagasabb szinten. A tevékenységük tetőpontján ez intenzív UFO aktivitással jár a nagyobb városok vonzáskörzetében. Az idegenek egyezményt próbálnak aláíratni egy kormányzattal, felajánlva a tudásukat és a felsőbbrendű technológiájukat. Viszonzásképp a kormányzat engedélyezi az idegeneknek tevékenységük akadálytalan folytatását. Az idegen küldetések jelentik a lehető legnagyobb fenyegetést az X-Com számára. Ha egy kormányzat elfogadja az egyezményt, minden támogatást megvon a tervezettől.\"\n  STR_ALIEN_BASE_UFOPEDIA: \"Az idegenek titkos vízalatti bázisokat építenek távol eső helyeken. Némi felderítés után intenzív kétéltű tevékenység kezdődik; ez bázis építésére utal. Ezek a bázisok laborokat, klónozóközpontokat és beültetőközpontokat tartalmaznak. Az idegen bázisok jelenléte nagy mennyiségű idegen tevékenységet okoz kétéltű aktivitás nélkül. Egy bázis megtalálásához egy X-Com gépnek órákat kell őrjáratozni a terület fölött, hogy egyáltalán esélye legyen megtalálnia azt.\"\n  STR_ALIEN_SURFACE_ATTACK_UFOPEDIA: \"Amikor az idegeneknek ember-alapanyagra van szükségük terrorizálnak egy kikötőt, megtámadnak egy szigetet vagy egy hajót. A civileket megfélemlítik, hogy kiteljesíthessék a tenyésztési és egyéb rejtélyes igényeiket.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"Ha az X-Com kétéltűi különösen sikeresek az idegen kétéltűek lelövésében, az idegenek beindítanak egy-egy megtorló akciót, amely általában egyenes támadást jelent egy X-Com bázis ellen. Bár először meg kell találniuk a bázist, hogy megtámadják. Ha sikerül a kétéltűiket a bázisoktól távol tartani, akkor kicsi a valószínűsége egy támadásnak\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"Ha egy idegen bázis megépült, azt el kell látni. Ezek szerint ha egy speciális ellátó hajó száll le valahol, az azt jelenti, hogy a közelben egy bázis van.\"\n  STR_SURVEY_SHIP_UFOPEDIA: \"Ez a kis gép elsődlegesen felderítésre és kutatásra szolgál. Általános esetben megelőz egy-egy nagyobb hajót, mielőtt az elindulna útjára.\"\n  STR_ESCORT_UFOPEDIA: \"A közepes méretű kísérő alig jelent veszélyt a földi erőkre. Általában nagyobb hajók küldetése előtt fordul elő.\"\n  STR_CRUISER_UFOPEDIA: \"A legnagyobb idegen felderítő általános célú, mindenféle típusú idegen küldetésben használatos.\"\n  STR_HEAVY_CRUISER_UFOPEDIA: \"A vezércirkáló sokkal veszélyesebb, mint a cirkáló, erősebb és több fegyverrel van felszerelve. Az ásványok és erőforrások nagy mennyiségű begyűjtésére használatos.\"\n  STR_HUNTER_UFOPEDIA: \"Ez a gép egy kivizsgáló szobával van felszerelve, melynek segítségével kísérleteket hajthatnak végre embereken. Az áldozatok a legborzalmasabb dolgokat állják ki, azután az agyat általában eltávolítják.\"\n  STR_BATTLESHIP_UFOPEDIA: \"A csatahajó a legagresszívabb idegen hajó. Mindennel fel van szerelve, ami a pusztításhoz és romboláshoz szükséges, továbbá egy-egy ilyen küldetés bázisául szolgál.\"\n  STR_DREADNOUGHT_UFOPEDIA: \"A csapatszállító mindennel fel van szerelve, ami csak létezik, és mellesleg óriási raktérrel rendelkezik. Kemény ellenfél.\"\n  STR_FLEET_SUPPLY_CRUISER_UFOPEDIA: \"Az ellátó hajó az épülő vagy a kész idegen bázis ellátására szolgál. Idegen tápanyagot, DNS-t, embriókat és egyéb biológiai komponenseket szállít\"\n  STR_DISMANTLE: \"Szétszedés\"\n  STR_FACILITY_IN_USE: \"ÉPÜLET HASZNÁLATBAN\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"AZ ÉPÜLET NEM SZEDHETŐ SZÉT!{SMALLLINE}Minden épületnek összeköttetésben kell lenni a központi lifttel.\"\n  STR_TRANSFER_ITEMS_TO: \"Tárgyak átcsoportosítása ide: {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"NINCS IDEGEN TÁROLÓ A CÉLBÁZISON!{SMALLLINE}Az élő idegeneknek szüksége van egy idegen tárolóra a túléléshez.\"\n  STR_AMOUNT_AT_DESTINATION: \"CÉLBELI{NEWLINE}MENNYISÉG\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"Az idegen meghal, mivel nincs idegen tároló épület\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"NINCS SZABAD LAKÓHELY!{SMALLLINE}A célbázis nem rendelkezik elég lakóhellyel a lakónegyedeiben, hogy képes legyen befogadni a géphez rendelt legénységet.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"NINCS ELÉG RAKTÁRHELY!{SMALLLINE}A célbázis nem rendelkezik elegendő raktárhellyel a gép fedélzetén lévő felszerelések számára.\"\n  STR_ITEMS_ARRIVING: \"Érkező tételek\"\n  STR_DESTINATION_UC: \"CÉLBÁZIS\"\n  STR_DART_PISTOL: \"Nyílpuska\"\n  STR_DART_POD: \"Nyilak\"\n  STR_JET_HARPOON: \"Szigonypuska\"\n  STR_HARPOON_POD: \"Szigonyok\"\n  STR_GAS_CANNON: \"Gázágyú\"\n  STR_GC_AP_AMMO: \"GÁ-PT Lőszer\"\n  STR_GC_HE_AMMO: \"GÁ-D Lőszer\"\n  STR_GC_P_AMMO: \"GÁ-F Lőszer\"\n  STR_HYDRO_JET_CANNON: \"Hidrolöveg\"\n  STR_HJC_AP_AMMO: \"HL-PT Lőszer\"\n  STR_HJC_HE_AMMO: \"HL-D Lőszer\"\n  STR_HJC_P_AMMO: \"HL-F Lőszer\"\n  STR_TORPEDO_LAUNCHER: \"Torpedókilövő\"\n  STR_SMALL_TORPEDO: \"Kis torpedó\"\n  STR_LARGE_TORPEDO: \"Nagy torpedó\"\n  STR_PHOSPHOROUS_TORPEDO: \"Foszforos Torpedó\"\n  STR_MAGNA_BLAST_GRENADE: \"DURRBELE gránát\"\n  STR_DYE_GRENADE: \"Tintagránát\"\n  STR_PARTICLE_DISTURBANCE_GRENADE: \"Részecskezavar-gránát\"\n  STR_MAGNA_PACK_EXPLOSIVE: \"DURRBELE robbanóanyag\"\n  STR_PARTICLE_DISTURBANCE_SENSOR: \"Részecskezavar-érzékelő\"\n  STR_MEDI_KIT: \"Elsősegélycsomag\"\n  STR_MC_DISRUPTOR: \"M.I. megszakító\"\n  STR_THERMAL_TAZER: \"Termobénító\"\n  STR_GAUSS_PISTOL: \"Gauss pisztoly\"\n  STR_GAUSS_PISTOL_CLIP: \"Gauss pisztoly tár\"\n  STR_GAUSS_RIFLE: \"Gauss puska\"\n  STR_GAUSS_RIFLE_CLIP: \"Gauss puska tár\"\n  STR_HEAVY_GAUSS: \"Nehézgauss\"\n  STR_HEAVY_GAUSS_CLIP: \"Nehézgauss tár\"\n  STR_SONIC_CANNON: \"Szónikus ágyú\"\n  STR_CANNON_POWER_CLIP: \"Szónikus ágyú tár\"\n  STR_SONIC_BLASTA_RIFLE: \"Szónikus puska\"\n  STR_BLASTA_POWER_CLIP: \"Szónikus puska tár\"\n  STR_SONIC_PISTOL: \"Szónikus pisztoly\"\n  STR_PISTOL_POWER_CLIP: \"Szónikus pisztoly tár\"\n  STR_DISRUPTOR_PULSE_LAUNCHER: \"Szakító lövedék kilövő\"\n  STR_DISRUPTOR_AMMO: \"Szakító lövedék\"\n  STR_THERMAL_SHOK_LAUNCHER: \"Termosokk kilövő\"\n  STR_THERMAL_SHOK_BOMB: \"Termosokk bomba\"\n  STR_SONIC_PULSER: \"Szónikus gránát\"\n  STR_ZRBITE: \"Zrbite\"\n  STR_MC_READER: \"M.I. leolvasó\"\n  STR_VIBRO_BLADE: \"Vibropenge\"\n  STR_THERMIC_LANCE: \"Termolándzsa\"\n  STR_HEAVY_THERMIC_LANCE: \"Nehéz termolándzsa\"\n  STR_AQUATOID_CORPSE: \"Akvatoid tetem\"\n  STR_GILLMAN_CORPSE: \"Kopoltyús tetem\"\n  STR_LOBSTERMAN_CORPSE: \"Rákember tetem\"\n  STR_TASOTH_CORPSE: \"Tasoth tetem\"\n  STR_CALCINITE_CORPSE: \"Kalcinit tetem\"\n  STR_DEEP_ONE_CORPSE: \"Mélységi tetem\"\n  STR_BIODRONE_CORPSE: \"Biorobot tetem\"\n  STR_TENTACULAT_CORPSE: \"Csápolat tetem\"\n  STR_TRISCENE_CORPSE: \"Triszcén tetem\"\n  STR_HALLUCINOID_CORPSE: \"Hallucinoid tetem\"\n  STR_XARQUID_CORPSE: \"Xarkvid tetem\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"Nincs elég lőszer az VFP felfegyverzéséhez{SMALLLINE}Minden VFP számára {0} {1} szükséges.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Nincs elég felszerelés az osztag újrafelfegyverzéséhez\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Ki kell kutatnod:{NEWLINE}{0}{NEWLINE}hogy ilyet gyárthass:{NEWLINE}{1}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"Az idegenek lerombolták a védtelen {0} bázist\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"X-Com ügynökök bemértek egy idegen bázist {0} területén.\"\n  STR_STANDOFF: \"KÖVETÉS\"\n  STR_CAUTIOUS_ATTACK: \"ÓVATOS TÁMADÁS\"\n  STR_STANDARD_ATTACK: \"NORMÁL TÁMADÁS\"\n  STR_AGGRESSIVE_ATTACK: \"AGRESSZÍV TÁMADÁS\"\n  STR_DISENGAGING: \"ELSZAKADÁS\"\n  STR_UFO_HIT: \"KÉTÉLTŰ ELTALÁLVA!\"\n  STR_UFO_CRASH_LANDS: \"KÉTÉLTŰ KÉNYSZERLESZÁLL!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Minimizálás követési távolsággal\"\n  STR_UFO_RETURN_FIRE: \"AZ IDEGEN KÉTÉLTŰ VISSZALŐ!\"\n  STR_INTERCEPTOR_DAMAGED: \">>> KÉTÉLTŰ MEGSÉRÜLT <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> KÉTÉLTŰ MEGSEMMISÜLT <<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"AZ IDEGEN KÉTÉLTŰ ELMENEKÜL\"\n  STR_LONG_RANGE_DETECTION: \"Hosszú távú észlelés\"\n  STR_STORES_UC: \"RAKTÁRAK\"\n  STR_DIFFICULTY_LEVEL: \"Nehézségi szint\"\n  STR_INTERCEPT: \"ELFOGÁS\"\n  STR_BASES: \"BÁZISOK\"\n  STR_GRAPHS: \"GRAFIKONOK\"\n  STR_UFOPAEDIA_UC: \"UFOPÉDIA\"\n  STR_OPTIONS_UC: \"OPCIÓK\"\n  STR_FUNDING_UC: \"FINANSZÍROZÁS\"\n  STR_5_SECONDS: \"5 mp\"\n  STR_1_MINUTE: \"1 perc\"\n  STR_5_MINUTES: \"5 perc\"\n  STR_30_MINUTES: \"30 perc\"\n  STR_1_HOUR: \"1 óra\"\n  STR_1_DAY: \"1 nap\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"X-Com teljesítményjegyzék\"\n  STR_ENTER_NAME: \"Írd be a neved\"\n  STR_PERFORMANCE_RATING: \"Teljesítmény értékelés\"\n  STR_VICTORY_DATE: \"Győzelem dátuma\"\n  STR_CHEMICAL_FLARE: \"Kemofáklya\"\n  STR_CHEMICAL_FLARE_UFOPEDIA: \"Ez a kis eszköz éles fényt produkál akár szárazföldön, akár a tengermélyén. Rendkívül hasznos éjszakai vagy mélytengeri bevetések esetén\"\n  STR_MONTHLY_COSTS: \"Havi költségek\"\n  STR_CRAFT_RENTAL: \"Kétéltű bérlése\"\n  STR_SALARIES: \"Fizetések\"\n  STR_BASE_MAINTENANCE: \"Bázis fenntartása\"\n  STR_COST_PER_UNIT: \"Egységár\"\n  STR_QUANTITY: \"Mennyiség\"\n  STR_TOTAL: \"Összesen\"\n  STR_IN_PSIONIC_TRAINING: \"M.I. képzés alatt\"\n  STR_FRONT_ARMOR: \"Páncél elöl\"\n  STR_LEFT_ARMOR: \"Páncél baloldalt\"\n  STR_RIGHT_ARMOR: \"Páncél jobboldalt\"\n  STR_REAR_ARMOR: \"Páncél hátul\"\n  STR_UNDER_ARMOR: \"Páncél alul\"\n  STR_ROUNDS: \"LÖVÉSEK\"\n  STR_UNIT: \"EGYSÉG> {0}\"\n  STR_ENERGY: \"ENERGIA\"\n  STR_MORALE: \"MORÁL\"\n  STR_ARMOR_: \"PÁNCÉL> {0}\"\n  STR_FRONT_ARMOR_UC: \"PÁNCÉL ELÖL\"\n  STR_LEFT_ARMOR_UC: \"PÁNCÉL BALOLDALT\"\n  STR_RIGHT_ARMOR_UC: \"PÁNCÉL JOBBOLDALT\"\n  STR_REAR_ARMOR_UC: \"PÁNCÉL HÁTUL\"\n  STR_SKILLS: \"ÜGYESSÉG> {0}\"\n  STR_LEVEL: \"SZINT> {0}\"\n  STR_HEAD: \"FEJ\"\n  STR_TORSO: \"TÖRZS\"\n  STR_RIGHT_ARM: \"JOBB KAR\"\n  STR_LEFT_ARM: \"BAL KAR\"\n  STR_RIGHT_LEG: \"JOBB LÁB\"\n  STR_LEFT_LEG: \"BAL LÁB\"\n  STR_PAIN_KILLER: \"FÁJ.CS.PÍTÓ\"\n  STR_STIMULANT: \"STIMULÁNS\"\n  STR_HEAL: \"GYÓGYÍTÁS\"\n  STR_TIME_UNITS_SHORT: \"IE>{ALT}{0}\"\n  STR_WEIGHT: \"Súly>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"Reakc>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"M.Ügyesség>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"M.Erő>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Idegen szerkezet\"\n  STR_AMMO_ROUNDS_LEFT: \"LŐSZER:{NEWLINE}MARADÉK{NEWLINE}LÖVEDÉK={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"F.cs.>{ALT}{0}{ALT}{NEWLINE}Stim.>{ALT}{1}{ALT}{NEWLINE}Gyógy.>{ALT}{2}\"\n  STR_THROW: \"Dobás\"\n  STR_AUTO_SHOT: \"Sorozatlövés\"\n  STR_SNAP_SHOT: \"Kapáslövés\"\n  STR_AIMED_SHOT: \"Célzott lövés\"\n  STR_STUN: \"Bénítás\"\n  STR_PRIME_GRENADE: \"Gránát időzítése\"\n  STR_USE_SCANNER: \"Zavarérzékelés\"\n  STR_USE_MEDI_KIT: \"Elsősegélycsomag használata\"\n  STR_LAUNCH_MISSILE: \"Torpedó indítása\"\n  STR_ACCURACY_SHORT: \"Pts>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Nincs elég Időegység!\"\n  STR_NOT_ENOUGH_ENERGY: \"Nincs elég Energia!\"\n  STR_NO_ROUNDS_LEFT: \"Nincs több lőszer!\"\n  STR_NO_AMMUNITION_LOADED: \"Nincs lőszer betöltve!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Ebbe a fegyverbe nem ilyen lőszer való!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"A fegyver már meg van töltve!\"\n  STR_NO_LINE_OF_FIRE: \"Nincs tűzvonalban!\"\n  STR_GRENADE_IS_ACTIVATED: \"Gránát élesítve!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Gránát hatástalanítva!\"\n  STR_THERE_IS_NO_ONE_THERE: \"Nincs ott senki!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Kutatás nélkül még használhatatlan!\"\n  STR_OUT_OF_RANGE: \"Túl messze van!\"\n  STR_UNABLE_TO_THROW_HERE: \"Képtelenség oda dobni!\"\n  STR_SET_TIMER: \"Időzítés\"\n  STR_HIDDEN_MOVEMENT: \"REJTETT CSAPATMOZGÁS\"\n  STR_TURN: \"KÖR> {0}\"\n  STR_SIDE: \"OLDAL> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Gombnyomásra tovább\"\n  STR_MIND_CONTROL: \"Molekuláris irányítás\"\n  STR_PANIC_UNIT: \"Megkeverés\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Morál elleni támadás sikeres\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Sikeres elmekontroll\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}megvadult\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}megvadult\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}pánikba esett\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}pánikba esett\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Idegenek\"\n  STR_RIGHT_HAND: \"JOBB KÉZ\"\n  STR_LEFT_HAND: \"BAL KÉZ\"\n  STR_RIGHT_SHOULDER: \"JOBB VÁLL\"\n  STR_LEFT_SHOULDER: \"BAL VÁLL\"\n  STR_BACK_PACK: \"HÁTIZSÁK\"\n  STR_BELT: \"ÖV\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}idegen irányítás alá került\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}idegen irányítás alá került\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}eszméletét vesztette\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}eszméletét vesztette\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}meghalt egy végzetes seb miatt\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}meghalt egy végzetes seb miatt\"\n  STR_USE_MIND_PROBE: \"M.I. leolvasó használata\"\n  STR_FATAL_WOUNDS: \"VÉGZETES SEBEK\"\n  STR_UNDER_ARMOR_UC: \"PÁNCÉL ALUL\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Az időegységek Kapáslövésre fenntartva\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Az időegységek Sorozatlövésre fenntartva\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Az időegységek Célzott Lövésre fenntartva\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Időegységek Térdelésre fenntartva\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"IE-ek Térdelésre és Lövésre fenntartva\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} Egység X-Com Repülőben\"\n    other: \"{N} egység X-Com kétéltűben\"\n  STR_UNITS_OUTSIDE:\n    one: \"{N} Egység maradt kint\"\n    other: \"{N} egység maradt kint\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} Egység a Bejáratnál\"\n    other: \"{N} egység a bejáratnál\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} Egység a Célkijáratnál\"\n    other: \"{N} egység a célkijáratnál\"\n  STR_ABORT_MISSION_QUESTION: \"Abbahagyod a küldetést?\"\n  STR_CORPSE: \"Tetem\"\n  STR_UNLOAD_CRAFT: \"Kiürít\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}meghalt\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}meghalt\"\n  STR_HIT_MELEE: \"Ütés\"\n  STR_GROUND: \"TALAJ\"\n  STR_LIVING_QUARTERS_PLURAL: \"Lakónegyed\"\n  STR_LIST_ITEM: \"TÉTEL\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"Nincs túlélő,{NEWLINE}begyűjtés automatikusan elindult.\"\n  STR_RESET: \"Visszaállítás\"\n  STR_MEMORIAL: \"Emlékmű\"\n  STR_DATE_UC: \"DÁTUM\"\n  STR_SOLDIERS_RECRUITED_UC: \"TOBORZOTT KATONÁK>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"ELESETT KATONÁK>{ALT}{0}\"\n  STR_REMOVE_SELECTED: \"Kijelöltek eltávolítása\"\n  STR_LIVE_ALIENS: \"Élő{NEWLINE}példányok\"\n  STR_DEAD_ALIENS: \"Visszautasított{NEWLINE}példányok\"\n  STR_UNDER_INTERROGATION: \"Tanulmányozás{NEWLINE}alatt\"\n  STR_CONTAINMENT_EXCEEDED: \"AZ IDEGENTÁROLÓ MEGTELT!{SMALLLINE}Nincs elegendő hely: {0}. El kell távolítanod a felesleges idegeneket (amelyek így aztán meghalnak).\"\n  STR_MANAGE_CONTAINMENT: \"Idegen tároló kezelése\"\n  STR_STORAGE_EXCEEDED: \"A TÁRHELY MEGTELT!{SMALLLINE}Nincs elegendő tárhely: {0}. A felesleget el kell adnod.\"\n  STR_GO_TO_BASE: \"Bázis mutatása\"\n  STR_MELEE_ACCURACY: \"ÜGYESSÉG KÖZELHARCBAN\"\n  STR_SELL_PRODUCTION: \"ELADÁSRA\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Mindkét kéznek üresnek kell lennie!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Nincs elég tárgy a felszereléshez!\"\n  STR_UNLOAD_WEAPON: \"Fegyver kiürítése\"\n  STR_ALL_ITEMS: \"Minden tétel\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"NINCS TÖBB FELSZERELÉS ENGEDÉLYEZVE!{SMALLLINE}A küldetéseidre maximum {N} felszerelési tárgyat vihetsz.\"\n    other: \"NINCS TÖBB FELSZERELÉS ENGEDÉLYEZVE!{SMALLLINE}A küldetéseidre maximum {N} felszerelési tárgyat vihetsz.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}IRÁNYÍTÓKÖZPONT MEGSEMMISÜLT{NEWLINE}Juss el a bejáratig és szakítsd meg a küldetést.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"X-Com létesítményeket nem lehet víz alá építeni.\"\n  STR_UNABLE_TO_ENGAGE_DEPTH: \"NEM LEHET MEGTÁMADNI{NEWLINE} EBBEN A MÉLYSÉGBEN\"\n  STR_UNABLE_TO_ENGAGE_AIRBORNE: \"NEM LEHET MEGTÁMADNI{NEWLINE}HA LEVEGŐBEN VAN\"\n  STR_UNDERWATER_EQUIPMENT: \"Ez az eszköz csak víz alatt működik!\"\n  STR_LAND_EQUIPMENT: \"Ez az eszköz víz alatt nem működik!\"\n  STR_LEVEL_SHORT: \"{0}.sz.\"\n  STR_PERSONNEL: \"Személyzet\"\n  STR_CRAFT_ARMAMENT: \"Repülő és fegyverzet\"\n  STR_COMPONENTS: \"Alkatrészek\"\n  STR_SOLDIERS_RECRUITED: \"Akvanauta besorozva\"\n  STR_SOLDIERS_LOST: \"Akvanauta elveszett\"\n  STR_TOTAL_UFOS: \"Kétéltű felfedezve\"\n  STR_TOTAL_ALIEN_BASES: \"Idegen bázisok felfedezve\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"MIE\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"MIÜ\"\n  FEMALE_CIVILIAN: \"Civil, nő\"\n  MALE_CIVILIAN: \"Civil, férfi\"\n  DOCKER_CIVILIAN: \"Civil, dokkmunkás\"\n  SAILOR_CIVILIAN: \"Civil, tengerész\"\n  STR_BIODRONE_MELEE_WEAPON: \"Biodrón közelharc\"\n  HALLUCINOID_WEAPON: \"Hallucinoid fegyver\"\n  STR_LOBSTERMAN_MELEE_WEAPON: \"Rákember közelharc\"\n  CALCINITE_WEAPON: \"Kalcinit fegyver\"\n  DEEP_ONE_WEAPON: \"Mélységi fegyver\"\n  STR_TRISCENE_MELEE_WEAPON: \"Triszcén közelharc\"\n  STR_TRIBIO_SONIC_WEAPON: \"Idegen szónikus fegyver\"\n  XARQUID_WEAPON: \"Xarkvid fegyver\"\n  TENTACULAT_WEAPON: \"Csápolat fegyver\"\n  ZOMBIE_WEAPON: \"Zombi fegyver\"\n  ALIEN_PSI_WEAPON: \"Idegen M.I. fegyver\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/it.yml",
    "content": "it:\n  STR_LEVIATHAN_UFOPEDIA: \"UN SOTTOMARINO VOLANTE D'ASSALTO E DA TRASPORTO, CAPACE DI RAGGIUNGERE ENORMI PROFONDITÀ. UNA SINTESI SUPERBA DELLA TECNOLOGIA UMANA E DI QUELLA ALIENA, IMPIEGA SISTEMI DI PROPULSIONE IONICA INSIEME AD UN APPARATO DI NAVIGAZIONE MAGNETICA.\"\n  STR_BARRACUDA_UFOPEDIA: \"IL BRITISH HYDROSPACE BARRACUDA, POTENZIATO DA MOTORI A LASER SURRISCALDATO. UNO DEGLI SCAFI VOLANTI PIÙ VELOCI AL MONDO, CAPACE DI VOLO SOTTOMARINO ED ATMOSFERICO, UNO SCAFO FONDAMENTALE PER LA BATTAGLIA INCOMBENTE.\"\n  STR_HAMMERHEAD_UFOPEDIA: \"UNO SCAFO PER L'ATTACCO ED IL TRASPORTO. UNA REPLICA DEI SISTEMI DI GUIDA A VETTORE MAGNETICO APPLICATI SU DI UN MEZZO X-COM. ANCHE SE DI DIMENSIONI RIDOTTE, IL SUO DESIGN È UN RISULTATO TECNICO SORPRENDENTE.\"\n  STR_TRITON_UFOPEDIA: \"IL TRITONE, UNO SCAFO DA TRASPORTO PER SQUADRE D'ASSALTO, DOTATO DI MOTORI ADATTI PER IL VOLO ATMOSFERICO E ACQUATICO. L'AMPIA CAPIENZA E LA SUA ROBUSTEZZA LO RENDONO UN PILASTRO DELLA FLOTTA DELLA X-COM.\"\n  STR_MANTA_UFOPEDIA: \"LO SCAFO AD ALTA VELOCITÀ MANTA, UN SOTTOMARINO VOLANTE MONOPOSTO PER L'INTERCETTAZIONE MOLTO SIMILE AGLI SCAFI ALIENI A PROPULSIONE IONICA. UN MEZZO D'ATTACCO ALTAMENTE EFFICACE IN QUESTO CONFLITTO SEMPRE PIU' INTENSO.\"\n  STR_AJAX_UFOPEDIA: \"IL SILURO AJAX È L'ARMA STANDARD A LIVELLO MONDIALE PER IL COMBATTIMENTO SUBACQUEO. IMPIEGATO COME DETERRENTE PRECISO E POTENTE.\"\n  STR_DUP_HEAD_UFOPEDIA: \"LA TECNOLOGIA DI ARMAMENTI BASATI SU TESTATE ALL'URANIO IMPOVERITO È RELATIVAMENTE NUOVA, E QUESTO È IL PRIMO SISTEMA D'ARMAMENTO ACQUATICO COMMERCIALE AD UTILIZZARLA.\"\n  STR_CRAFT_GAS_CANNON_UFOPEDIA: \"UN CANNONE AZIONATO A GAS COMPRESSO, CHE SPARA PROIETTILI AD ALTA CAPACITÀ DI PENETRAZIONE.\"\n  STR_PWT_CANNON_UFOPEDIA: \"IL SILURO AD ONDE PULSANTI È DOTATO DI UN SISTEMA A CARBURANTE SURRISCALDATO E UNA TESTATA ESTREMAMENTE DENSA, CAPACE DI PERFORARE BUONA PARTE DEI MATERIALI.\"\n  STR_GAUSS_CANNON_UFOPEDIA: \"IL SISTEMA DI ARMAMENTO GAUSS È UNA TECNOLOGIA DELLA X-COM SVILUPPATA RECENTEMENTE. L'ACCELERATORE DI PARTICELLE DI QUEST'ARMA È ALIMENTATO DA UN COMPATTO REATTORE A FUSIONE RAFFREDDATO AD AZOTO LIQUIDO.\"\n  STR_SONIC_OSCILLATOR_UFOPEDIA: \"UN POTENTE OSCILLATORE ACUSTICO CREA ONDE DI FORZA SONICA. DISTRUGGE IL BERSAGLIO DEMOLENDONE I LEGAMI MOLECOLARI ATTRAVERSO LE VIBRAZIONI.\"\n  STR_AQUATOID_UFOPEDIA: \"La razza degli Aquatoidi è una società antica, esistente da millenni prima che l'uomo muovesse il primo vacillante passo sulla Terra. La loro forma ridotta ed i tratti bulbosi sono un'eredità dei loro parenti spaziali, i Sectoidi. Il loro potere si basa sulla potente tecnologia del Controllo Molecolare. Gli Aquatoidi cercano di propagare la loro sterile razza attraverso modificazioni genetiche, utilizzando come soggetti ideali gli esseri umani. I loro esperimenti hanno creato numerose razze ibride.\"\n  STR_AQUATOID_AUTOPSY: \"Autopsia: Aquatoide\"\n  STR_AQUATOID_AUTOPSY_UFOPEDIA: \"Una dettagliata analisi di questa creatura ci permette di fare alcune assunzioni di base. È un Sectoide, uno dei nostri nemici, ma modificato attraverso metodi chirurgici ed impianti per essere una creatura acquatica. Polmoni vestigiali permettono di respirare aria e di agire limitatamente in superficie. Ci sono impianti cibernetici in tutto il corpo, che aumentano la forza degli arti atrofizzati e le funzioni degli organi. Visto che tutti i membri di questa razza sono identici, possiamo quindi ipotizzare che queste creature siano cloni.\"\n  STR_GILLMAN_UFOPEDIA: \"Pressoché umana, questa strana creatura sembra essere un rettiliano umanoide, imparentata molto strettamente con l'uomo. Questa creatura è estremamente potente e veloce nel mondo sottomarino.  Gli Uomini-Branchia sono una razza vera e propria, con esemplari maschi e femmine di diverse età. Si differenziano dagli altri alieni sottomarini nel non avere nessun segno di alterazioni genetiche o deformazioni chirurgiche. È possibile che ci troviamo davanti ad un qualche ramo antico della nostra stessa specie.\"\n  STR_GILLMAN_AUTOPSY: \"Autopsia: Gillman\"\n  STR_GILLMAN_AUTOPSY_UFOPEDIA: \"Ad un primo esame chirurgico, è risultato chiaramente che questa creatura non è di origine aliena, ma terrestre, un'antica razza preistorica che credevamo estinta dal momento in cui i mammiferi divennero dominanti. Gli Uomini-Branchia, anfibi, intelligenti e forti, vivevano in un tempo dove i dinosauri vagavano per il pianeta. Il cataclisma che rovesciò il domino dei rettili dal pianeta ha costretto queste creature in una relazione simbiotica con gli alieni appena arrivati. Un piccolo impianto elettronico è conficcato nei crani di queste creature.\"\n  STR_LOBSTERMAN_UFOPEDIA: \"Questa è una creatura sconcertante, più alta di un uomo e dotata di sei arti, con l'aspetto di un demonio sottomarino. Le somiglianze tra questa creatura e le aragoste terrestri le hanno guadagnato il nomignolo di Uomo-Aragosta tra le truppe della X-Com. Questo è un colosso degli abissi. Una creatura da combattimento meticolosamente progettata, dalla forza incredibile e praticamente invulnerabile al fuoco dei missili. Con solamente le sue chele può frantumare l'acciaio.\"\n  STR_LOBSTERMAN_AUTOPSY: \"Autopsia Uomo-Aragosta\"\n  STR_LOBSTERMAN_AUTOPSY_UFOPEDIA: \"Una volta penetrata la sua armatura praticamente indistruttibile, la creatura cela una struttura stupefacente. Potenti muscoli avvolgono uno scheletro in titanio ed un sofisticato sistema di puntamento con capacità di scansione multi-banda è collegato direttamente al cervello della creatura. I suoi molteplici occhi sono protetti da plastiche più resistenti dell'acciaio ed è evidente che, se ben schierati dai propri padroni, queste creature sono praticamente inarrestabili. Nascosti nel corpo vi sono dispositivi di costruzione e funzionalità sconosciute.\"\n  STR_TASOTH_UFOPEDIA: \"Questi avversari agili e veloci sono il pilastro dell'esercito nemico. Vengono creati a centinaia, in enormi vasche di gestazione nel cuore delle colonie Aliene. Di gran lunga più forti di un uomo, il Tasoth è un alieno nel vero termine della parola ed il suo comportamento e natura carnivora non ha eguali nel pianeta. Il Tasoth costituisce spesso l'avanguardia di un attacco alieno e non mostra nessuna paura in combattimento anche di fronte a forze schiaccianti.\"\n  STR_TASOTH_AUTOPSY: \"Autopsia Tasoth\"\n  STR_TASOTH_AUTOPSY_UFOPEDIA: \"La dissezione svela un organismo cibernetico dotato di uno strano potere. Dentro la cavità corporea risiede una piccola unità energetica, ma nessun organo identificabile. L'energia è trasmessa attraverso il corpo da un sistema bio-elettrico. L'organismo è privo di ossa o qualsiasi tipo di struttura di supporto. Una volta morto l'energia cessa e la creatura diviene un fantoccio senza vita dal quale colano carne e fluidi alieni. L'unica altra costruzione interna presente è un paio di pile ceramiche, che se energizzate, riportano in vita la creatura.\"\n  STR_DEEP_ONE_UFOPEDIA: \"L'Essere Abissale è un incubo biologico, un incrocio, prodotto dai folli esperimenti degli Aquatoidi. Abbiamo incontrato diverse variazioni di questa creatura e dopo una estesa ricerca abbiamo concluso che questi esseri sono prodotti dagli invasori, che ne aumentano i ranghi con la cattura di nuovi gruppi di umani. Ognuno di questi sub-umani è armato di uno scaricatore di energia elettrica abbastanza potente da uccidere un acquanauta.\"\n  STR_DEEP_ONE_AUTOPSY: \"Autopsia di Essere Abissale\"\n  STR_DEEP_ONE_AUTOPSY_UFOPEDIA: \"La creatura è un innesto tra un uomo ed un organismo alieno. Il cervello umano è massicciamente modificato per accogliere l'elettronica di controllo e la corteccia aliena. Tutte le caratteristiche del corpo umano sembrano sparite tranne una: gli occhi. L'innesto chirurgico sembra permettere al feto alieno di consumare l'ospite umano durante la crescita. La robusta pelle della creatura sembra essere una maglia metallica, non organica, incredibilmente resistente e flessibile. L'incrocio risultante è forte, veloce e totalmente sotto il controllo degli alieni.\"\n  STR_BIODRONE_UFOPEDIA: \"Il Bio-drone è una creazione che solo una mente aliena poteva concepire. È un cervello (umano o alieno) immerso in fluidi amniotici e connesso ad un supporto energetico capace di volare sopra la terra e sott'acqua. Ogni Bio-drone è armato con un potente disintegratore sonico, in parte macchina ed in parte organico. Alcuni dei nostri scienziati hanno ipotizzato che l'arma sia comandata dalle corde vocali dell'organismo ospite originario. Altamente precisi e tenaci, questi super cani da guardia vengono ampiamente utilizzati dagli alieni per proteggere risorse preziose.\"\n  STR_BIODRONE_AUTOPSY: \"Autopsia di Bio-drone\"\n  STR_BIODRONE_AUTOPSY_UFOPEDIA: \"Le ipotesi che il disintegratore sonico fosse un dispositivo biologico sono vere. Questa disgraziata creatura uccide i suoi nemici proprio urlando. Ogni esemplare presenta enormi cicatrici da interventi chirurgici e serie mutilazioni. Sembrerebbe che gli alieni operino il cervello per indurlo all'obbedienza. La maggior parte dei cervelli adottati nelle creature sono di origine aliena, ma niente potrebbe eguagliare l'orrore di trovare un'unità basata su parti umane. I Bio-droni sono potenziati attraverso un motore IONICO ed incorporano una qualche forma di sistema di controllo remoto.\"\n  STR_TENTACULAT_UFOPEDIA: \"Neppure i meandri più oscuri degli incubi di Lovecraft possono generare una creatura così indescrivibile. Non esiste nessun confronto con qualsiasi animale Terrestre, l'ambiente che ha potuto produrlo è al di là della nostra immaginazione. Armato di lunghi tentacoli, il Tentacolato paralizza le sue vittime e le trasmuta in esseri senza cervello. Questa progenie può uccidere con il solo contatto, anche attraverso una corazza. Il Tentacolato è il più terribile alieno mai incontrato dalla X-Com.\"\n  STR_TENTACULAT_AUTOPSY: \"Autopsia Tentacolato\"\n  STR_TENTACULAT_AUTOPSY_UFOPEDIA: \"L'autopsia rivela piccoli impianti cibernetici conficcati nel largo cervello della creatura. Il sistema visivo è una complessa combinazione di percezione luminosa ed acquisizione di immagini termiche. Anche nelle oscure profondità oceaniche questo mostro può muoversi con infallibile precisione. Ci sono organi vestigiali che sembrerebbero essere il minimo per la sopravvivenza. Ogni creatura ha un piccolo stomaco con un connettore esterno, è logico supporre che l'essere venga nutrito con l'introduzione diretta di nutrimenti dai suoi padroni.\"\n  STR_CALCINITE_UFOPEDIA: \"Simile all'aspetto degli scafandri dei marinai dispersi, questi alieni tendono agguati agli incauti sui fondali marini. Un violento colpo proveniente dalla creatura, tramite i suoi artigli più duri dell'acciaio, possono bastare per mandare a terra anche il sommozzatore migliore. Una forma verde e gelatinosa può essere vista turbinare nella maschera della tuta. Nessun indizio sulla vera natura della creatura può essere determinato dagli incontri, spesso letali, che abbiamo avuto con essa.\"\n  STR_CALCINITE_AUTOPSY: \"Autopsia Calcinite\"\n  STR_CALCINITE_AUTOPSY_UFOPEDIA: \"Una volta tolto lo scafandro, il Calcinite si rivela essere una grossa massa amorfa di protoplasma. Non esiste nessuna traccia di cervello, arti o organi sensoriali, solo un piccolo componente metallico risiede all'interno del corpo liquido. Una volta morto possiamo solo fare ipotesi sulla natura della creatura. Un inspiegabile enigma dei nostri nemici alieni.\"\n  STR_TRISCENE_UFOPEDIA: \"Questo rettile bipede è un relitto dell'era dei Dinosauri. Sembra in tutto e per tutto una creatura del Cretaceo salvo per la sua abilità di sopravvivere nell'acqua e sulla terra. Queste creature hanno alloggiamenti per le armi e mascelle dotate di denti metallici. Spesso questi mostri sono stati al centro delle forze d'attacco aliene negli assalti sulla terraferma. Un arma pesante e potente, che i comandanti Tasoth schierano con letale efficacia.\"\n  STR_TRISCENE_AUTOPSY: \"Autopsia Triscene\"\n  STR_TRISCENE_AUTOPSY_UFOPEDIA: \"Sotto il bisturi degli scienziati il Triscene si rivela essere un'antica creatura, potenziata con impianti cibernetici e sistemi di armamento. Il suo piccolo cervello è affiancato da un piccolo computer installato nella bardatura indossata da ogni creatura. Una resistente pelle naturale, un istinto predatorio affinato dalle armi aggiuntive lo rendono un nemico letale in ogni situazione.\"\n  STR_HALLUCINOID_UFOPEDIA: \"Setacciando gli oceani, gli alieni hanno allevato queste grosse creature terrestri come armi. Non farti tranquillizzare da un falso senso di sicurezza quando incontri queste meduse apparentemente inoffensive. Dotato di un colpo congelante a distanza ravvicinata, l'Allucinoide è un nemico micidiale.\"\n  STR_HALLUCINOID_AUTOPSY: \"Autopsia Allucinoide\"\n  STR_HALLUCINOID_AUTOPSY_UFOPEDIA: \"Racchiuso dai numerosi strati di corpo gelatinoso della creatura risiede un potente congelante chimico, il suo principale mezzo offensivo. La pelle morbida ed elastica dell'Allucinoide sembra sensibile agli attacchi termici. Spesso questo mutante si trova in compagnia dei propri padroni, gli Aquatoidi.\"\n  STR_XARQUID_UFOPEDIA: \"Un altro invertebrato terrestre modificato, lo Xarquide è una creatura di grande bellezza e pericolosità. Questo gigante daila rapida nuotata nasconde un devastante arsenale di armi, un soffocante getto di inchiostro e un raggio di particelle ionizzate. Fin dal primo incontro con questa potente creatura siamo stati in guardia dal suo potere e dai suoi controllori, i vendicativi Uomini-Branchia.\"\n  STR_XARQUID_AUTOPSY: \"Autopsia Xarquide\"\n  STR_XARQUID_AUTOPSY_UFOPEDIA: \"Questo Nautilo troppo cresciuto è stato ingigantito con una dieta di droghe aliene ed alterazioni chirurgiche. Alterato oltre le leggi della natura, gli Uomini-Branchia hanno aggiunto sistemi di controllo meccanici alla creatura e ora nulla rimane della sua natura originale. Impiegato come piattaforma organica armata, il robusto guscio e la mobilità degli Xarquidi lo rende un avversario formidabile.\"\n  STR_ION_BEAM_ACCELERATORS_UFOPEDIA: \"I sottomarini volanti alieni si affidano a complessi sistemi di propulsione per muoversi a velocità incredibili attraverso gli abissi. Alla base della loro tecnologia vi è il DISLOCATORE IONICO che, utilizzando la Zrbite come catalizzatore, permette ai motori di muovere 100 volte al secondo il loro volume in acqua. Questa enorme potenza implica che gli alieni possono seminare buona parte dei sottomarini terrestri. Possiamo replicare questo sistema di propulsione utilizzando acqua-plastiche e celle d'energia di Zrbite.\"\n  STR_MAGNETIC_NAVIGATION_UFOPEDIA: \"Queste unità generano un campo magnetico sferico multi-strato, il cui vettore si estende fino a 1000m attorno al sottomarino. I navigatori Alieni sono collegati direttamente alle macchine e sentono con i propri sensi il mondo invisibile sotto le onde. Il sistema di interfaccia opera utilizzando materia celebrale aliena modificata che comunica direttamente con la mente dell'operatore attraverso un collegamento neurale.\"\n  STR_ALIEN_SUB_CONSTRUCTION_UFOPEDIA: \"Ogni vascello ha una struttura camaleontica, attentamente modellata sulle creature marine, e composta da Acqua-Plastiche. Ogni sottomarino opera come un organismo: l'equipaggio e lo scafo sono in armonia. Buona parte di questi sistemi può essere replicata ed è possibile sviluppare una tecnologia ibrida che ci permetterà di raggiungere lo stesso livello tecnologico.\"\n  STR_ALIEN_CRYOGENICS_UFOPEDIA: \"Gli innumerevoli alieni che sono rimasti nascosti sulla Terra sono stati mantenuti in animazione sospesa, congelati criogenicamente. Tutte le creature sono sigillate in unità, la loro temperatura corporea ridotta fino al punto che le funzioni corporee siano quasi del tutto ferme. Fin'ora un'ispezione delle unità ha rivelato l'incredibile lasso di tempo in cui i corpi sono stati tenuti in sospensione, alcuni per circa 60 milioni di anni.\"\n  STR_ALIEN_CLONING_UFOPEDIA: \"Molti degli alieni che abbiamo catturato sono identici fino al livello del loro DNA, duplicati in tutto e per tutto. Campioni di cellule sono immessi nelle unità dalle banche genetiche congelate degli alieni. Alcune unità contengono umani o parti del corpo. È possibile che un altro utilizzo di queste unità sia di creare qualche ibrido tra alieni e umani.\"\n  STR_ALIEN_LEARNING_ARRAYS_UFOPEDIA: \"Utilizzando gli impianti di Controllo Molecolare presenti nei crani di tutti gli alieni, queste macchine immettono informazioni direttamente nel cervello. Gli alieni appena clonati vengono condotti a queste unità le quali scaricano nelle loro menti vuote le memorie della razza e tutte le informazioni scientifiche o di combattimento.\"\n  STR_ALIEN_IMPLANTER_UFOPEDIA: \"Quest'unità è usata per dotare gli alieni degli impianti di Controllo Molecolare, fertilizzare specie riproduttive ed inserire o rimuovere organi e dispositivi elettronici da qualsiasi creatura. Il processo era pensato per essere compiuto su pazienti sottomessi, ma il soggetto è del tutto consapevole del procedimento e sfortunatamente l'anatomia umana sembra adattarsi perfettamente con l'unità.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"Ora abbiamo le prove per capire il motivo per cui gli alieni catturano gli umani. Non sono usati come cibo, non sono fertilizzati con embrioni alieni, piuttosto costituiscono la base di una serie di creature e sistemi di controllo. La tecnologia aliena è basata su una mente comune, un intelletto condiviso ed il cervello umano è un ricettacolo ideale per questi sistemi. Il tessuto cerebrale umano è usato in buona parte nei sistemi di immagazzinamento ed estrapolazione dati dei computer biologici alieni, i resti sono usati per costruire e per allevare.\"\n  STR_AQUA_PLASTICS_UFOPEDIA: \"I sottomarini e le strutture Aliene utilizzano un materiale incredibilmente forte, flessibile e durevole per la maggior parte della loro costruzione. Le Acqua-plastiche sono complessi materiali multi-legame catalizzati con Zrbite. Densa, ma leggera, la sostanza ha una resistenza anche superiore del Titanio e del Kevlar.\"\n  STR_ZRBITE_UFOPEDIA: \"Questa è una lega di origine aliena, in parte oro ed in parte Bio-materiale alieno. Se utilizzata come fonte energetica, piccole quantità generano più energia di un'unità nucleare 10 volte più grande. Riprodurre questo materiale va oltre le nostre abilità tecniche visto che la maggior parte dei suoi componenti sono di origine aliena.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"Gli alieni colpiscono in tutto il globo, con spietata efficienza. Non riusciamo a identificare la loro provenienza. Che sia in qualche fossa oceanica così impenetrabile da impedirci di localizzarla?  Non tutti gli organismi che abbiamo incontrato sono alieni, alcuni sono molto antichi, altri provengono da percorsi evolutivi da ritenuti estinti da molto. Abbiamo a che fare con una minaccia rimasta dormiente per millenni, una sottile simbiosi di umani e alieni. Nel profondo degli oceani giacciono antichi siti utilizzati dagli alieni per contattare i loro cugini spaziali. Ognuno di questi dodici siti contiene un dispositivo Synomium, una potente tecnologia Aliena. Ora, con la loro macchina bellica in marcia, gli alieni stanno riattivando questi siti per allargare la loro rete di Controllo Molecolare, dobbiamo distruggere questi siti ad ogni costo.\"\n  STR_THE_ULTIMATE_THREAT_UFOPEDIA: \"Sessantacinque milioni di anni fa un'enorme nave colonia fu inviata sulla Terra da un lontano pianeta alieno. Mentre la gigantesca nave si avvicinava al giovane pianeta un imponente e violento bagliore solare causò un guasto ai sistemi di navigazione. Danneggiata e malfunzionante l'enorme massa precipitò attraverso la stratosfera comparendo nei cieli del Cretaceo. Sulla Terra innumerevoli specie volsero lo sguardo al cielo mentre la loro fine piombava sul pianeta. Una vasta nuvola di polvere offuscò l'atmosfera e con il raffreddamento della terra scomparve la forma di vita dominante, i potenti dinosauri. Ma i 400 miliardi di tonnellate di T'leth non si distrussero nell'impatto, sofisticati super computer avviarono un ciclo di sonno criogenico per le creature al suo interno. Con il passare degli eoni i computer risvegliarono gruppi di Alieni per tentare di comunicare con i loro cugini stellari, ma inutilmente, in quanto il cuore delle forze aliene continuava a dormire.\"\n  STR_TLETH_THE_ALIEN_CITY: \"T'leth la città Aliena\"\n  STR_TLETH_THE_ALIEN_CITY_UFOPEDIA: \"T'leth, l'enorme nave colonia Aliena, posa sul fondo della Fossa di Sigsbee, nel Golfo del Messico. Nel cuore della città risiede un orrore Alieno, così malvagio e potente che neppure la morte lo può reclamare. In una stanza di metallo alieno risiede la forma dormiente del grande sognatore, l'Alieno Supremo. Sollevare T'leth sopra le onde avvierà il suo ciclo di rianimazione, ed una volta risorto sarà inarrestabile. Benché non vivo ed in qualche maniera neanche morto, la mente Aliena controlla l'armata Aliena. La misteriosa tecnologia del controllo molecolare connette tutti gli Alieni alla mente dell'Essere e la mente dell'Essere a tutti gli Alieni. Feti alieno/umani geneticamente mutati riforniscono di energia la mente Aliena e formano il legame tra il sovrano e i suoi sudditi. Il mito dell'Alieno Supremo è esistito nel cuore e nella mente dell'umanità per secoli, il mare ha sempre nascosto la verità definitiva.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"CENTRA SU SITO-TEMPO=5 Sec\"\n  STR_CANCEL_UC: \"ANNULLA\"\n  STR_NONE: \"Nessuno\"\n  STR_UNKNOWN: \"Sconosciuto\"\n  STR_POOR: \"Povero\"\n  STR_AVERAGE: \"Medio\"\n  STR_GOOD: \"Buono\"\n  STR_EXCELLENT: \"Eccellente\"\n  STR_BUILD_NEW_BASE_UC: \"COSTRUISCI NUOVA BASE\"\n  STR_BASE_INFORMATION: \"INFORMAZIONI BASE\"\n  STR_EQUIP_CRAFT: \"EQUIPAGGIA SOTTOMARINO\"\n  STR_BUILD_FACILITIES: \"COSTRUISCI STRUTTURE\"\n  STR_RESEARCH: \"RICERCA\"\n  STR_MANUFACTURE: \"PRODUZIONE\"\n  STR_TRANSFER_UC: \"TRASFERISCI\"\n  STR_PURCHASE_RECRUIT: \"ACQUISTA/ASSUMI\"\n  STR_SACK: \"LICENZIA\"\n  STR_SELL_SACK_UC: \"VENDI/LICENZIA\"\n  STR_GEOSCAPE_UC: \"GEOSCAPE\"\n  STR_NAME: \"Nome\"\n  STR_AREA: \"Area\"\n  STR_BUILD_NEW_BASE: \"Costruisci Nuova Base\"\n  STR_CANCEL: \"Annulla\"\n  STR_COST_UC: \"COSTO>\"\n  STR_CONSTRUCTION_TIME_UC: \"TEMPO COSTRUZIONE>\"\n  STR_DAY:\n    one: \"{N} giorno\"\n    many: \"{N} giorni\"\n    other: \"{N} giorni\"\n  STR_HOUR:\n    one: \"{N} ora\"\n    many: \"{N} ore\"\n    other: \"{N} ore\"\n  STR_MAINTENANCE_UC: \"MANUTENZIONE>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Installazione\"\n  STR_CURRENT_RESEARCH: \"RICERCA ATTUALE\"\n  STR_SCIENTISTS_AVAILABLE: \"Scienziati Disponibili>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Scienziati Assegnati>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Spazio Laboratorio Disponibile>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"PROGETTO DI RICERCA\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"SCIENZIATI ASSEGNATI\"\n  STR_PROGRESS: \"PROGRESSO\"\n  STR_NEW_PROJECT: \"Nuovo Progetto\"\n  STR_CANCEL_PROJECT: \"ANNULLA PROGETTO\"\n  STR_NEW_RESEARCH_PROJECTS: \"NUOVI PROGETTI DI RICERCA\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"SCIENZIATI DISPONIBILI>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"SPAZIO LABORATORIO DISPONIBILE>{ALT}{0}\"\n  STR_INCREASE: \"Aumenta\"\n  STR_DECREASE: \"Diminuisci\"\n  STR_START_PROJECT: \"AVVIA PROGETTO\"\n  STR_CURRENT_PRODUCTION: \"PRODUZIONE ATTUALE\"\n  STR_ENGINEERS_AVAILABLE: \"Tecnici Disponibili>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Tecnici Assegnati>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Spazio Officina Disponibile>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Finanze Attuali>{ALT}{0}\"\n  STR_ITEM: \"OGGETTO\"\n  STR_ENGINEERS__ALLOCATED: \"Tecnici Assegnati\"\n  STR_UNITS_PRODUCED: \"Unità Prodotte\"\n  STR_TOTAL_TO_PRODUCE: \"Totale da Produrre\"\n  STR_COST__PER__UNIT: \"Costo{NEWLINE}per{NEWLINE}Unità\"\n  STR_DAYS_HOURS_LEFT: \"Giorni/Ore alla Conclusione\"\n  STR_NEW_PRODUCTION: \"Nuova Produzione\"\n  STR_PRODUCTION_ITEMS: \"Articoli Realizzabili\"\n  STR_CATEGORY: \"CATEGORIA\"\n  STR_START_PRODUCTION: \"AVVIA PRODUZIONE\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} ore Tecnico per produrre una unità\"\n  STR_COST_PER_UNIT_: \"Costo per unità>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Spazio Officina Richiesto>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"MATERIALI SPECIALI RICHIESTI\"\n  STR_ITEM_REQUIRED: \"OGGETTO\"\n  STR_UNITS_REQUIRED: \"UNITÀ RICHIESTE\"\n  STR_UNITS_AVAILABLE: \"UNITÀ DISPONIBILI\"\n  STR_STOP_PRODUCTION: \"INTERROMPI PRODUZIONE\"\n  STR_ENGINEERS_AVAILABLE_UC: \"TECNICI DISPONIBILI>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"SPAZIO OFFICINA DISPONIBILE>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"PROFITTO MENSILE>{ALT}{0}\"\n  STR_INCREASE_UC: \"AUMENTA\"\n  STR_DECREASE_UC: \"DIMINUISCI\"\n  STR_UNITS_TO_PRODUCE: \"Unità da Produrre\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Acquista Oggetti/Assumi Personale\"\n  STR_COST_OF_PURCHASES: \"Costo degli Acquisti>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"COSTO UNITÀ\"\n  STR_QUANTITY_UC: \"QUANTITÀ\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"PERSONALE DISPONIBILE:PERSONALE TOTALE>\"\n  STR_SOLDIERS: \"Acquanauti\"\n  STR_SCIENTISTS: \"Scienziati\"\n  STR_ENGINEERS: \"Tecnici\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"SPAZIO UTILIZZATO:SPAZIO UTILIZZABILE>\"\n  STR_LIVING_QUARTERS: \"Alloggi\"\n  STR_STORES: \"Magazzini\"\n  STR_LABORATORIES: \"Laboratori\"\n  STR_WORK_SHOPS: \"Officine\"\n  STR_HANGARS: \"Rimesse Sottomarini\"\n  STR_SHORT_RANGE_DETECTION: \"Sonar a Corto Raggio\"\n  STR_DEFENSE_STRENGTH: \"Potere Difensivo\"\n  STR_TRANSFERS_UC: \"TRASFERIMENTI\"\n  STR_TRANSFERS: \"Trasferimenti\"\n  STR_ARRIVAL_TIME_HOURS: \"TEMPO ALL'ARRIVO (ore)\"\n  STR_COST_: \"Costo>{ALT}{0}\"\n  STR_AREA_: \"Area>{ALT}{0}\"\n  STR_BASE_NAME: \"Nome della Base?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"SELEZIONA LA POSIZIONE DELL'ASCENSORE D'ACCESSO\"\n  STR_TRANSFER: \"Trasferisci\"\n  STR_AMOUNT_TO_TRANSFER: \"TOTALE DA TRASFERIRE\"\n  STR_SELECT_DESTINATION_BASE: \"Seleziona Base di Destinazione\"\n  STR_COST: \"Costo\"\n  STR_INTRO_1: \"Copyright 1995 MicroProse\"\n  STR_INTRO_2: \"Marte: La caduta di Cydonia.\"\n  STR_INTRO_3: \"Una trionfante X-Com, dopo la distruzione del nucleo centrale della macchina bellica Aliena, decolla per tornare a casa. Tuttavia, non è tutto morto nella devastata base Marziana.\"\n  STR_INTRO_4: \"Un potente raggio di tachioni balena dalle rovine del centro nevralgico di Cydonia - rimbombando nel vuoto. La sua destinazione............\"\n  STR_INTRO_5: \"Terra.\"\n  STR_INTRO_6: \"Nel profondo dell'oceano il raggio colpisce un recettore inattivo da tempo. Immensi computer dormienti cominciano a risvegliarsi. Nelle profondità, all'oscuro degli occhi dell'umanità, enormi camere di Alieni dormienti cominciano il loro lungo ciclo di rianimazione.\"\n  STR_INTRO_7: \"2040: una Terra inconsapevole. I terrori della guerra Aliena sono ormai dimenticati. Ma, nelle zone più remote e nascoste dell'oceano le orde Aliene sono pronte - pronte a rovesciare l'umanità e prendere il controllo del mondo.\"\n  STR_INTRO_8: \"Gli Alieni colpiscono l'umanità; alla ricerca di esemplari per i loro esperimenti degenerati; razziando il globo di preziosi minerali e risorse; e depredando dai mari. Quindi, gli Alieni volgono il loro sguardo sopra le onde.\"\n  STR_INTRO_9: \"Potenti sottomarini volanti dalle forme bizzarre traversano gli oceani - osservando, cercando, cacciando.........\"\n  STR_INTRO_10: \"E trovando una preda, attaccano.\"\n  STR_INTRO_11: \"Armi nuove e misteriose sono impiegate contro un mondo senza difese. Siamo totalmente alla mercé della minaccia aliena.{NEWLINE}Solo un'organizzazione può salvarci; ma gli abbiamo voltato le spalle tanto tempo fa......\"\n  STR_INTRO_12: \"Struttura Sottomarina Sperimentale X-COM\"\n  STR_INTRO_13: \"'Mayday! Mayday!' 'Qui è il transatlantico Hyperion'. 'Siamo sotto attacco'. 'Mayday! Mayd............'\"\n  STR_INTRO_14: \"'Centro di Comando a Rimessa Sottomarino Uno: Aprire porte oceaniche', 'schierare Barracuda Zero Uno. È in corso una situazione di attacco Alieno - codice Rosso'.{NEWLINE}'Ripeto: codice Rosso'\"\n  STR_INTRO_15: \"Gli alieni sono spietati nella loro efficienza....\"\n  STR_INTRO_16: \"...ed infallibili nella loro precisione.\"\n  STR_INTRO_17: \"'Barracuda Zero Uno a base' - 'in avvicinamento a quello che rimane dell'Hyperion'.\"\n  STR_INTRO_18: \"'Decelerazione'.{NEWLINE}'Due metri'{NEWLINE}'Un metro'{NEWLINE}'A tutti gli acquanauti, prepararsi per il dispiegamento immediato'.\"\n  STR_INTRO_19: \"...........'Camera stagna aperta'...'in avvicinamento al relitto'.{NEWLINE}'Porca!'{NEWLINE}'Vedi anche tu quelle creature sulla telecamera della mia tuta?'\"\n  STR_GAMEOVER_1: \"Abbiamo fallito, gli alieni hanno annientato l'ultima nostra speranza di salvezza.{NEWLINE}X-Com è distrutta e la Terra è alla mercé dell'antico nemico.\"\n  STR_GAMEOVER_2: \"T'leth rimbomba nella stratosfera e comincia a muoversi per la crosta terrestre. Elargendo distruzione e catturando quello che rimane della razza umana. Nel profondo delle sue viscere la feroce mente Aliena inizia a risvegliarsi.\"\n  STR_GAMEOVER_3: \"Nelle capitali di tutte le nazioni sono elaborati piani disperati. È tutto inutile, senza la tecnologia fornita dal progetto di ricerca X-Com le nostre armi sono inefficaci.\"\n  STR_GAMEOVER_4: \"Gli alieni costruiscono basi nelle calotte polari ed iniziano a sciogliere il ghiaccio, rendendo il mondo un enorme mare. Il resto della popolazione umana è riunito e utilizzato in orribili esperimenti di riproduzione per fini Alieni sconosciuti. I cieli si scuriscono e una terribile pestilenza si abbatte sulla Terra.\"\n  STR_GAMEOVER_5: \"Non possiamo opporre resistenza al nuovo ordine mondiale, coloro che ci provano vanno incontro ad una morte ardente per mano delle ineffabili armi Aliene. Per noi restanti non c'è alcuna benedizione, la madre Terra diventa un mondo Alieno e l'umanità è sconfitta sotto il passo di un lento orrore.\"\n  STR_OUTRO_1: \"La Tomba, razziata e decimata; un ruggito gorgogliante proviene dalla bara al suo centro.{NEWLINE}Sciocchi, morirete tutti....................\"\n  STR_OUTRO_2: \".................nessuno può scappare.\"\n  STR_OUTRO_3: \"Un'enorme esplosione erompe dalla tomba e si diffonde per tutta la città, il fumo e le macerie riempiono l'aria. I piani degli alieni sono stati sventati........\"\n  STR_OUTRO_4: \"L'immensa massa contorta di T'leth inizia a creparsi. Fuoco e fumo fuoriescono dai suoi scintillanti pinnacoli palazzi di adamantio.\"\n  STR_OUTRO_5: \"La potente nave Aliena si precipita con velocità verso il mare, le urla del metallo torturato e delle anime riempiono l'aria. Il Grande Sognatore non potrà più sognare la conquista del mondo.\"\n  STR_OUTRO_6: \"Un ultimo assordante boato e T'leth va in pezzi.{NEWLINE}La minaccia aliena è terminata, la Terra è purificata..................\"\n  STR_OUTRO_7: \"Un addormentato pianeta verde e blu, in un remoto angolo della galassia.\"\n  STR_OUTRO_8: \"Il prossimo futuro, un posto sicuro in cui stare.\"\n  STR_OUTRO_9: \"La minaccia Aliena sulla Terra è stata da tanto tempo neutralizzata.\"\n  STR_OUTRO_10: \"Vaste città dalle dimensioni di metropoli ospitano miliardi di umani.\"\n  STR_OUTRO_11: \"Le gesta della X-Com e le guerre Aliene sono materiale da storie per bambini.\"\n  STR_OUTRO_12: \"Ma le leggende hanno sempre l'abitudine di contenere un briciolo di verità............\"\n  STR_RISE_1: \"T'leth, chiamata in molti modi da molte leggende di molti paesi.\"\n  STR_RISE_2: \"Con un urlo esplosivo che riverbera in tutto il globo T'leth inizia la sua ascensione dal fondo del mare.\"\n  STR_RISE_3: \"L'enorme edificio risale le acque del Golfo del Messico.\"\n  STR_RISE_4: \"400 miliardi di tonnellate di metallo Alieno, la potente città Aliena dove riposa il corpo dormiente dell'Alieno Supremo. Imprigionato sulla terra per 65 milioni di anni questa malvagia Divinità dello spazio comincia a risvegliarsi.\"\n  STR_RISE_5: \"Le acque ribollono e schiumano all'emergere alla luce della tomba del Grande Sognatore................\"\n  STR_RISE_6: \".........una luce che durerà poco almeno che X-Com non riuscirà a distruggere la macchina bellica Aliena.\"\n  STR_YOU_HAVE_FAILED: \"Non sei riuscito a fermare la macchina bellica aliena. Le organizzazioni finanziatrici, deluse dalle tue abilità, provano a negoziare una soluzione non militare con gli Alieni. Ma gli Invasori hanno ben altri piani ed in breve il mondo intero viene al corrente della verità...\"\n  STR_TOTAL_UC: \"TOTALE\"\n  STR_INCOME: \"Entrate\"\n  STR_EXPENDITURE: \"Uscite\"\n  STR_MAINTENANCE: \"Spese Mensili\"\n  STR_BALANCE: \"Bilancio\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"Attività Aliena nei Mari\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"Attività Aliena nelle Zone\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"Attività X-Com nei Mari\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"Attività X-Com nelle Zone\"\n  STR_FINANCE: \"Finanze\"\n  STR_DATE_FIRST: \"{0}°\"\n  STR_DATE_SECOND: \"{0}°\"\n  STR_DATE_THIRD: \"{0}°\"\n  STR_DATE_FOURTH: \"{0}°\"\n  STR_FINANCE_THOUSANDS: \"$1000\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Non ci sono abbastanza materiali speciali per produrre{NEWLINE}{0}{NEWLINE}nella base{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Non ci sono abbastanza soldi per produrre{NEWLINE}{0}{NEWLINE}nella base{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"La Produzione di{NEWLINE}{0}{NEWLINE}nella base{NEWLINE}{1}{NEWLINE}è stata completata\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"La Costruzione di{NEWLINE}{0}{NEWLINE}nella base{NEWLINE}{1}{NEWLINE}è stata completata\"\n  STR_OK_5_SECONDS: \"OK - 5 sec\"\n  STR_RESEARCH_COMPLETED: \"Ricerca Completata\"\n  STR_VIEW_REPORTS: \"VEDI RELAZIONE\"\n  STR_WE_CAN_NOW_RESEARCH: \"Ora possiamo ricercare\"\n  STR_WE_CAN_NOW_PRODUCE: \"Ora possiamo produrre\"\n  STR_SUNDAY: \"DOMENICA\"\n  STR_MONDAY: \"LUNEDÌ\"\n  STR_TUESDAY: \"MARTEDÌ\"\n  STR_WEDNESDAY: \"MERCOLEDÌ\"\n  STR_THURSDAY: \"GIOVEDÌ\"\n  STR_FRIDAY: \"VENERDÌ\"\n  STR_SATURDAY: \"SABATO\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Non c'è abbastanza {0} per rifornire {1} nella base {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Non ci sono abbastanza {0} per riarmare {1} nella base {2}\"\n  STR_UFO_IS_NOT_RECOVERED: \"SOTTOMARINO ALIENO non recuperato\"\n  STR_UFO_IS_RECOVERED: \"SOTTOMARINO ALIENO recuperato\"\n  STR_CRAFT_IS_LOST: \"Sottomarino Volante perduto\"\n  STR_TERROR_CONTINUES: \"L'Attività Aliena prosegue\"\n  STR_ALIENS_DEFEATED: \"Alieni sconfitti\"\n  STR_BASE_IS_LOST: \"Base perduta\"\n  STR_BASE_IS_SAVED: \"Base salvata\"\n  STR_ALIEN_BASE_STILL_INTACT: \"Colonia Aliena ancora intatta\"\n  STR_ALIEN_BASE_DESTROYED: \"Colonia Aliena distrutta\"\n  STR_ALIENS_KILLED: \"ALIENI UCCISI\"\n  STR_ALIEN_CORPSES_RECOVERED: \"CADAVERI ALIENI RECUPERATI\"\n  STR_LIVE_ALIENS_RECOVERED: \"ALIENI VIVI RECUPERATI\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"ARTEFATTI ALIENI RECUPERATI\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"COMANDO DELLA COLONIA ALIENA DISTRUTTO\"\n  STR_ALIEN_SYNOMIUM_DEVICE_DESTROYED: \"DISPOSITIVO SYNOMIUM ALIENO DISTRUTTO\"\n  STR_ALIEN_SYNOMIUM_DEVICE_FAILED: \"MANCATA DISTRUZIONE DISPOSITIVO SYNOMIUM\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"CIVILI UCCISI DAGLI ALIENI\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"CIVILI UCCISI DA OPERATORI X-COM\"\n  STR_CIVILIANS_SAVED: \"CIVILI SALVATI\"\n  STR_XCOM_OPERATIVES_KILLED: \"OPERATORI X-COM UCCISI\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"OPERATORI X-COM DISPERSI IN AZIONE\"\n  STR_TANKS_DESTROYED: \"PIATTAFORME ARMI X-COM DISTRUTTE\"\n  STR_XCOM_CRAFT_LOST: \"SOTTOMARINO X-COM PERDUTO\"\n  STR_UFO_RECOVERY: \"RECUPERO SOTTOMARINO ALIENO\"\n  STR_ALIEN_BASE_RECOVERY: \"RECUPERO COLONIA ALIENA\"\n  STR_BASE_UNDER_ATTACK: \"{0} sotto attacco!\"\n  STR_BASE_DEFENSES_INITIATED: \"AVVIATE DIFESE DELLA BASE\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"SOTTOM. RESPINTO DA SCUDO!\"\n  STR_FIRING: \"MIRA\"\n  STR_HIT: \"COLPITO!\"\n  STR_UFO_DESTROYED: \"SOTTOM. ALIENO DISTRUTTO!\"\n  STR_MISSED: \"MANCATO!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Vendi Oggetti/Licenzia Personale\"\n  STR_VALUE_OF_SALES: \"VALORE VENDITE> {ALT}{0}\"\n  STR_FUNDS: \"FINANZE> {ALT}{0}\"\n  STR_SELL_SACK: \"Vendi/Licenzia\"\n  STR_VALUE: \"Valore\"\n  STR_CRAFT_: \"SCAFO> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"RECUPERO SOTTOMARINO ALIENO PRECIPITATO\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"PRESTARE MASSIMA ATTENZIONE - Saranno presenti Alieni nel sottomarino e presso il sito dello schianto. Questa missione sarà completata quando tutte le unità nemiche saranno eliminate o neutralizzate. Sarà quindi possibile iniziare il recupero dei resti del sottomarino, della tecnologia e dei corpi alieni. Per abbandonare la missione riporta gli acquanauti X-Com al sottomarino e clicca sull'icona 'Abbandona Missione'.\"\n  STR_UFO_GROUND_ASSAULT: \"ASSALTO SOTTOMARINO ALIENO\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"Esplora il sito dell'atterraggio e, se possibile, fatti strada nel sottomarino Alieno. La missione avrà successo quando tutte le unità nemiche saranno eliminate o neutralizzate. Sarà quindi possibile iniziare il recupero dei resti del sottomarino, della tecnologia e dei corpi alieni. Per abbandonare la missione riporta gli acquanauti X-Com al sottomarino e clicca sull'icona 'Abbandona Missione'.\"\n  STR_BASE_DEFENSE: \"DIFESA DELLA BASE\"\n  STR_BASE_UC_: \"BASE> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"Un vascello alieno è atterrato nelle vicinanze. La nostra base è in serio pericolo. Come per procedura standard tutto il personale non combattente ed i sottomarini funzionali della X-Com sono stati evacuati. Gli Alieni si infiltreranno nella base attraverso i cancelli delle Rimesse Sottomarini o dall'ascensore d'accesso. Difendi la base e le sue strutture vitali a tutti i costi - questa è una battaglia all'ultimo sangue. Se clicchi sull'icona 'Abbandona Missione' concederai la sconfitta e perderai la base.\"\n  STR_ALIEN_COLONY_ATTACK_MISSION: \"MISSIONE DI ASSALTO A COLONIA ALIENA\"\n  STR_ALIEN_BASE_ASSAULT: \"COLONIA ALIENA PARTE UNO\"\n  STR_ALIEN_COLONY_P1_BRIEFING: \"Questa missione è un assalto ad una colonia Aliena. Il sito ha 2 livelli, porta tutti gli acquanauti nell'uscita luminosa del primo complesso e clicca sull'icona 'Abbandona Missione' per continuare. Qualsiasi equipaggiamento lasciato indietro rimarrà sul fondale marino fino al completamento della 2° parte. Per abbandonare, posiziona gli acquanauti nel Sottomarino e clicca sull'icona 'Abbandona Missione'.\"\n  STR_ALIEN_COLONY_P2: \"COLONIA ALIENA PARTE DUE\"\n  STR_ALIEN_COLONY_P2_BRIEFING: \"Avendo affrontato il primo livello ed essendo entrato nel cuore della colonia. Adesso la missione è distruggere il centro di controllo, il Dispositivo Synomium, o eliminare tutti gli Alieni. Per abbandonare posiziona tutti gli acquanauti nel punto di partenza e clicca sull'icona 'Abbandona Missione'. Saranno riportati alla base tutti gli equipaggiamenti X-Com possibili.\"\n  STR_ALIENS_LAUNCH_PORT_TERROR: \"GLI ALIENI DANNO INIZIO A{NEWLINE}UN ATTACCO AL PORTO DI\"\n  STR_PORT_TERROR: \"ATTACCO ALIENO AL PORTO\"\n  STR_PORT_TERROR_BRIEFING: \"Gli alieni hanno dato inizio ad un attacco sulla terra ferma. Il porto e la sua popolazione civile sono in grave pericolo. La tua squadra deve eliminare tutti gli Alieni e proteggere gli innocenti civili sul posto da quest'incursione Aliena. Per abbandonare, posiziona gli acquanauti nel sottomarino volante e clicca l'icona 'Abbandona Missione'.\"\n  STR_ALIENS_LAUNCH_ISLAND_TERROR: \"GLI ALIENI DANNO INIZIO A{NEWLINE}UN ATTACCO SULL'ISOLA\"\n  STR_ISLAND_TERROR: \"ATTACCO ALIENO SULL'ISOLA\"\n  STR_ISLAND_TERROR_BRIEFING: \"Gli alieni hanno dato inizio ad un attacco sulla terra ferma. L'isola e la sua popolazione civile sono in grave pericolo. La tua squadra deve eliminare tutti gli Alieni e proteggere gli innocenti civili sul posto da quest'incursione Aliena. Per abbandonare, posiziona gli acquanauti nel sottomarino volante e clicca l'icona 'Abbandona Missione'.\"\n  STR_ALIENS_ATTACK_SHIPPING_ROUTE: \"ATTACCO ALIENO{NEWLINE}ROTTA MARITTIMA\"\n  STR_CARGO_SHIP_P1: \"NAVE MERCANTILE PARTE UNO\"\n  STR_CARGO_SHIP_P2: \"NAVE MERCANTILE PARTE DUE\"\n  STR_CRUISE_SHIP_P1: \"NAVE DA CROCIERA PARTE UNO\"\n  STR_CRUISE_SHIP_P2: \"NAVE DA CROCIERA PARTE DUE\"\n  STR_SHIP_RESCUE_MISSION: \"MISSIONE SALVATAGGIO NAVE\"\n  STR_SHIP_RESCUE_P1_BRIEFING: \"Questa missione è una caccia all'insetto, elimina tutte le unità Aliene sulla nave e proteggi le vite di qualsiasi civile a bordo. Gli Alieni sono sparsi sopra e sotto coperta, prendi il controllo dei ponti superiori prima di addentrarti nei ponti inferiori. Per abbandonare, posiziona gli acquanauti nel sottomarino volante e clicca l'icona 'Abbandona Missione'.\"\n  STR_SHIP_RESCUE_P2_BRIEFING: \"Ora che il ponte superiore è stato ripulito procedi sotto coperta. Sei sceso fino alla stiva utilizzando il montacarichi. La tua squadra deve eliminare tutti gli Alieni di questo livello per completare la missione. Per abbandonare posiziona tutti gli acquanauti sul montacarichi e clicca sull'icona 'Abbandona missione'.\"\n  STR_ALIEN_ACTIVITY_DETECTED: \"RILEVATA ATTIVITÀ ALIENA\"\n  STR_ALIEN_CONTACT_SITE_MISSION: \"MISSIONE SITO COMUNICAZIONI ALIENO\"\n  STR_ARTIFACT_SITE_P1: \"SITO COMUNICAZIONI ALIENO PARTE UNO\"\n  STR_ARTIFACT_SITE_P1_BRIEFING: \"Questa missione è un raid di un sito di comunicazioni Alieno recentemente attivato. Il sito ha 2 livelli, il fondale marino con le sue piramidi Aliene ed un complesso Alieno nascosto. Porta tutti gli acquanauti all'entrata del complesso e clicca sull'icona 'Abbandona Missione' per procedere. Per abbandonare, posiziona gli acquanauti nel sottomarino volante e clicca sull'icona 'Abbandona Missione'.\"\n  STR_ARTIFACT_SITE_P2: \"SITO COMUNICAZIONI ALIENO PARTE DUE\"\n  STR_ARTIFACT_SITE_P2_BRIEFING: \"Avendo affrontato le strutture Aliene ed essendo entrato nel complesso gli obbiettivi della missione sono chiare. Addentrarsi nel cuore della struttura Aliena e distruggere il Dispositivo Synomium per il Controllo Molecolare per completare la missione. Per abbandonare posiziona tutti gli acquanauti sull'ascensore d'ingresso al punto iniziale e clicca sull'icona 'Abbandona Missione'.\"\n  STR_SIGSBEE_DEEP_MISSION: \"MISSIONE FOSSA DI SIGSBEE{NEWLINE}CITTÀ ALIENA LIVELLO UNO\"\n  STR_TLETH_P1_BRIEFING: \"Ci stiamo addentrando nell'ignoto, da qui in poi può attenderci qualsiasi cosa. Sappiamo che ci sono altri 2 livelli nella città Aliena e la tua squadra deve correre all'uscita di questo livello per accedere al prossimo. Posiziona tutti gli acquanauti sull'uscita e clicca sull'icona 'Abbandona Missione' per avanzare. Abbandonare in qualsiasi altro posto terminerà la missione.\"\n  STR_TLETH_ATTACK_MISSION: \"MISSIONE ATTACCO T'LETH{NEWLINE}CITTÀ ALIENA LIVELLO DUE\"\n  STR_TLETH_P2_BRIEFING: \"Ancora più nell'ignoto, da qui in poi può attenderci qualsiasi cosa. Sappiamo che c'è un altro livello nella città Aliena e la tua squadra deve correre all'uscita di questo livello per accedere al prossimo. Posiziona tutti gli acquanauti sull'uscita e clicca sull'icona 'Abbandona Missione' per avanzare. Abbandonare in qualsiasi altro posto terminerà la missione.\"\n  STR_FINAL_TLETH_MISSION: \"MISSIONE FINALE T'LETH{NEWLINE}CITTÀ ALIENA LIVELLO TRE\"\n  STR_TLETH_P3_BRIEFING: \"La fine è vicina, da qui in poi siamo alla ricerca della cripta dell'Alieno Supremo. Distruggi gli 8 sostentatori della tomba per mettere fine alla minaccia Aliena. Non arrenderti ora! Abbandonare terminerà la missione.\"\n  STR_TLETH_P1: \"CITTÀ ALIENA LIVELLO UNO\"\n  STR_TLETH_P2: \"CITTÀ ALIENA LIVELLO DUE\"\n  STR_TLETH_P3: \"CITTÀ ALIENA LIVELLO TRE\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"NESSUNA RIMESSA DISPONIBILE PER LA COSTRUZIONE DELLO SCAFO!{SMALLLINE}Ogni Sottomarino Volante assegnato ad una base, trasferito ad una base, acquistato o costruito utilizza una Rimessa. Costruisci una nuova Rimessa Sottomarino o trasferisci un sottomarino ad un'altra base.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"NESSUNA RIMESSA DISPONIBILE PER L'ACQUISTO!{SMALLLINE}Ogni Sottomarino Volante assegnato ad una base, trasferito ad una base, acquistato o costruito utilizza una Rimessa. Costruisci una nuova Rimessa Sottomarino o trasferisci un sottomarino ad un'altra base.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"NESSUNA RIMESSA DISPONIBILE PER IL TRASFERIMENTO!{SMALLLINE}Ogni Sottomarino Volante assegnato ad una base, trasferito ad una base, acquistato o costruito utilizza una Rimessa. Costruisci una nuova Rimessa Sottomarino o trasferisci un sottomarino ad un'altra base.\"\n  STR_CANNOT_BUILD_HERE: \"NON È POSSIBILE COSTRUIRE QUI!{SMALLLINE}Devi costruire accanto ad una struttura già esistente.\"\n  STR_NO_FREE_ACCOMODATION: \"NON CI SONO ALLOGGI DISPONIBILI!{SMALLLINE}La base di destinazione non ha abbastanza posto nelle aree abitative.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"NON C'È ABBASTANZA SPAZIO LAVORO!{SMALLLINE}Costruisci una nuova officina o riduci il lavoro in altri progetti.\"\n  STR_NOT_ENOUGH_MONEY: \"NON CI SONO ABBASTANZA SOLDI!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"NON C'È ABBASTANZA SPAZIO DI IMMAGAZZINAMENTO!{SMALLLINE}Costruisci un nuovo magazzino o trasferisci scorte ad altre basi.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"NON C'È ABBASTANZA SPAZIO VITALE!{SMALLLINE}Costruisci nuove aree abitative o trasferisci personale ad altre basi.\"\n  STR_LAUNCH_INTERCEPTION: \"SCHIERA SCAFO\"\n  STR_CRAFT: \"SCAFO\"\n  STR_STATUS: \"STATO\"\n  STR_BASE: \"BASE\"\n  STR_READY: \"PRONTO\"\n  STR_OUT: \"FUORI\"\n  STR_REPAIRS: \"IN RIPARAZIONE\"\n  STR_REFUELLING: \"IN RIFORNIMENTO\"\n  STR_REARMING: \"IN RIARMO\"\n  STR_TARGET: \"OBIETTIVO:{NEWLINE}{0}\"\n  STR_WAY_POINT: \"PUNTO DI RIFERIMENTO\"\n  STR_ARE_YOU_SURE_CYDONIA: \"Sei sicuro di voler mandare questo Sottomarino in missione a T'leth?\"\n  STR_YES: \"SÌ\"\n  STR_NO: \"NO\"\n  STR_SELECT_DESTINATION: \"SELEZIONA LA DESTINAZIONE\"\n  STR_CYDONIA: \"T'LETH\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"SELEZIONA L'UBICAZIONE DELLA NUOVA BASE\"\n  STR_RETURN_TO_BASE: \"RIENTRA ALLA BASE\"\n  STR_SELECT_NEW_TARGET: \"SELEZIONA NUOVO OBIETTIVO\"\n  STR_PATROL: \"PATTUGLIA\"\n  STR_STATUS_: \"STATO>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"DANNEGGIATO{NEWLINE}     » IN RIENTRO ALLA BASE\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"CARBURANTE SCARSO{NEWLINE}     » IN RIENTRO ALLA BASE\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"MISSIONE COMPLETATA{NEWLINE}     » IN RIENTRO ALLA BASE\"\n  STR_PATROLLING: \"IN RICOGNIZIONE\"\n  STR_TAILING_UFO: \"INSEGUIMENTO SOTTOMARINO ALIENO\"\n  STR_INTERCEPTING_UFO: \"INTERCETTAZIONE SOTTOM. ALIENO-{0}\"\n  STR_RETURNING_TO_BASE: \"IN RIENTRO ALLA BASE\"\n  STR_DESTINATION_UC_: \"DESTINAZIONE:{NEWLINE}{0}\"\n  STR_BASE_UC: \"BASE>{ALT}{0}\"\n  STR_SPEED_: \"VELOCITÀ>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"VELOCITÀ MASSIMA>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"PROFONDITÀ>{ALT}{0}\"\n  STR_AIRBORNE: \"IN VOLO\"\n  STR_VERY_LOW: \"SUPERFICIALE\"\n  STR_LOW_UC: \"NORMALE\"\n  STR_HIGH_UC: \"PROFONDO\"\n  STR_VERY_HIGH: \"MOLTO PROFONDA\"\n  STR_FUEL: \"CARBURANTE>{ALT}{0}\"\n  STR_WEAPON_ONE: \"ARMA-1>{ALT}{0}\"\n  STR_NONE_UC: \"NESSUNO\"\n  STR_ROUNDS_: \"COLPI>{ALT}{0}\"\n  STR_WEAPON_TWO: \"ARMA-2>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"SOTTOMARINI VOLANTI\"\n  STR_BASE_: \"Base>{0}\"\n  STR_NAME_UC: \"NOME\"\n  STR_AMMO_: \"MUNIZIONI>{ALT}{0}\"\n  STR_CREW: \"EQUIPAGGIO\"\n  STR_EQUIPMENT_UC: \"ATTREZZATURA\"\n  STR_ARMOR: \"ARMATURA\"\n  STR_MAX: \"MASSIMO>{ALT}{0}\"\n  STR_ROOKIE: \"Marinaio\"\n  STR_SQUADDIE: \"Marinaio Scelto\"\n  STR_SERGEANT: \"Guardiamarina\"\n  STR_CAPTAIN: \"Tenente\"\n  STR_COLONEL: \"Comandante\"\n  STR_COMMANDER: \"Capitano\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Seleziona la Squadra per {0}\"\n  STR_SORT_BY: \"ORDINA PER...\"\n  STR_ORIGINAL_ORDER: \"ORDINE ORIGINALE\"\n  STR_MISSIONS2: \"MISSIONI\"\n  STR_KILLS2: \"UCCISIONI\"\n  STR_WOUND_RECOVERY2: \"GUARIGIONE FERITA\"\n  STR_SPACE_AVAILABLE: \"SPAZIO DISPONIBILE>{ALT}{0}\"\n  STR_SPACE_USED: \"SPAZIO UTILIZZATO>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"SPAZIO OCCUPATO\"\n  STR_RANK: \"GRADO\"\n  STR_WOUNDED: \"FERITO\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Attrezzatura per {0}\"\n  STR_DEFENSE_VALUE: \"Potere Difensivo\"\n  STR_HIT_RATIO: \"Probabilità di Colpire\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}pronto per{NEWLINE}atterrare presso{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"Iniziare la Missione?\"\n  STR_SELECT_ARMAMENT: \"Selezionare Armamento\"\n  STR_AMMUNITION_AVAILABLE: \"MUNIZIONI DISPONIBILI\"\n  STR_ARMAMENT: \"ARMAMENTO\"\n  STR_NOT_AVAILABLE: \"N.D.\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"SELEZIONA ARMATURA PER{NEWLINE}{ALT}{0}\"\n  STR_TYPE: \"TIPO\"\n  STR_PLASTIC_AQUA_ARMOR_UC: \"ARM. ACQUA-PLASTICA\"\n  STR_ION_ARMOR_UC: \"ARM. IONICA\"\n  STR_MAGNETIC_ION_ARMOR_UC: \"ARM. IONICA MAGNETICA\"\n  STR_PLASTIC_AQUA_ARMOR_UFOPEDIA: \"Questo Scafandro è costruito con la sostanza Aliena recentemente scoperta, l'Acqua-plastica, e garantisce ai nostri Acquanauti di avere una possibilità in combattimento contro l'incursione Aliena.\"\n  STR_ION_ARMOR_UFOPEDIA: \"Un nuovo e potente tipo di protezione per gli Acquanauti, quest'armatura è potenziata da una sorgente di energia IONICA ed amplifica enormemente la velocità e la forza di chi la indossa, offrendo per il momento la migliore protezione per le truppe combattenti.\"\n  STR_MAGNETIC_ION_ARMOR_UFOPEDIA: \"Un miglioramento dell'armatura IONICA che incorpora la tecnologia dei Campi Magnetici per permettere completa libertà di movimento nell'ambiente acquatico.\"\n  STR_SELECT_ARMOR: \"Seleziona Armatura\"\n  STR_NORTH: \"NORD\"\n  STR_NORTH_EAST: \"NORD-EST\"\n  STR_EAST: \"EST\"\n  STR_SOUTH_EAST: \"SUD-EST\"\n  STR_SOUTH: \"SUD\"\n  STR_SOUTH_WEST: \"SUD-OVEST\"\n  STR_WEST: \"OVEST\"\n  STR_NORTH_WEST: \"NORD-OVEST\"\n  STR_SELECT_ACTION: \"SELEZIONA AZIONE\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"PROSEGUI CON L'INTERCETTAZIONE\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"INSEGUI SENZA INTERCETTAZIONE\"\n  STR_VERY_LARGE: \"MOLTO GRANDE\"\n  STR_LARGE: \"GRANDE\"\n  STR_MEDIUM_UC: \"MEDIO\"\n  STR_SMALL: \"PICCOLO\"\n  STR_VERY_SMALL: \"MOLTO PICCOLO\"\n  STR_GROUNDED: \"POSATO SUL FONDALE\"\n  STR_DETECTED: \"Rilevato\"\n  STR_SIZE_UC: \"DIMENSIONE\"\n  STR_ALTITUDE: \"PROFONDITÀ\"\n  STR_HEADING: \"DIREZIONE\"\n  STR_SPEED: \"VELOCITÀ\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"CENTRA SUL SOTTOM. ALIENO-TEMPO=5 Sec\"\n  STR_TRACKING_LOST: \"PERSA LA TRACCIA\"\n  STR_REDIRECT_CRAFT: \"REINDIRIZZA SCAFO\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"VAI ALLA SUA ULTIMA POSIZIONE NOTA\"\n  STR_UFO_: \"SOTTOMAR. ALIENO-{0}\"\n  STR_ALIEN_BASE_: \"COLONIA ALIENA-{0}\"\n  STR_CRASH_SITE_: \"SITO SCHIANTO-{0}\"\n  STR_LANDING_SITE_: \"SITO ATTERRAGGIO-{0}\"\n  STR_WAY_POINT_: \"PUNTO DI RIFERIMENTO-{0}\"\n  STR_TERROR_SITE: \"SITO TERRORE-{0}\"\n  STR_ARTIFACT_SITE: \"SITO ARTEFATTO-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}ha raggiunto{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"In pattugliamento\"\n  STR_ALIEN_ORIGINS: \"Origini Aliene\"\n  STR_THE_ULTIMATE_THREAT: \"La Minaccia Suprema\"\n  STR_TLETH_ALIEN_CITY: \"T'leth, la Città Aliena\"\n  STR_UFOPAEDIA: \"UFOpedia\"\n  STR_XCOM_CRAFT_ARMAMENT: \"SCAFI X-COM E ARMAMENTO\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"SISTEMI ARMATI SOMMERGIBILI\"\n  STR_WEAPONS_AND_EQUIPMENT: \"ATTREZZATURA GENERICA\"\n  STR_ALIEN_ARTIFACTS: \"ARTEFATTI ACQUATICI\"\n  STR_BASE_FACILITIES: \"STRUTTURE X-COM\"\n  STR_ALIEN_LIFE_FORMS: \"CREATURE ALIENE\"\n  STR_ALIEN_RESEARCH_UC: \"TECNOLOGIA ALIENA\"\n  STR_UFO_COMPONENTS: \"NUOVE TECNOLOGIE SOTTOMARINE\"\n  STR_UFOS: \"SOTTOMARINI ALIENI\"\n  STR_SELECT_ITEM: \"SELEZIONA VOCE\"\n  STR_ACCELERATION: \"ACCELERAZIONE>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"CAPACITÀ CARBURANTE>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"SCOMPARTI ARMAMENTO>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"DANNI SOSTENIBILI>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"CAPACITÀ CARICO>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"CAPACITÀ SAS>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Danno\"\n  STR_RANGE: \"Gittata\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Precisione\"\n  STR_RE_LOAD_TIME: \"Tempo di Riarmo\"\n  STR_SECONDS: \"{0} sec\"\n  STR_DAMAGE_ARMOR_PIERCING: \"PERFORANTE\"\n  STR_DAMAGE_INCENDIARY: \"INCENDIARIO\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"ESPLOSIVO\"\n  STR_DAMAGE_LASER_BEAM: \"RAGGIO GAUSS\"\n  STR_DAMAGE_PLASMA_BEAM: \"RAGGIO SONICO\"\n  STR_DAMAGE_STUN: \"CONGELANTE\"\n  STR_DAMAGE_MELEE: \"MELEE\"\n  STR_DAMAGE_ACID: \"ACIDO\"\n  STR_DAMAGE_SMOKE: \"FUMOGENO\"\n  STR_SHOT_TYPE: \"TIPO\"\n  STR_ACCURACY_UC: \"PRECISIONE\"\n  STR_TIME_UNIT_COST: \"COSTO U.T.\"\n  STR_DAMAGE_UC: \"DANNI\"\n  STR_AMMO: \"MUNIZIONI\"\n  STR_SHOT_TYPE_AUTO: \"Automatico\"\n  STR_SHOT_TYPE_SNAP: \"Rapido\"\n  STR_SHOT_TYPE_AIMED: \"Mirato\"\n  STR_CONSTRUCTION_TIME: \"Tempo di Costruzione\"\n  STR_CONSTRUCTION_COST: \"Costo di Costruzione\"\n  STR_MAINTENANCE_COST: \"Costo di Mantenimento\"\n  STR_LOW: \"Basso\"\n  STR_MEDIUM: \"Medio\"\n  STR_HIGH: \"Alto\"\n  STR_CRAFT_WEAPON: \"Armamento Sottomarino\"\n  STR_CRAFT_AMMUNITION: \"Munizioni Sottomarino\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Sistema d'Arma Pesante\"\n  STR_WEAPON: \"Arma\"\n  STR_AMMUNITION: \"Munizioni\"\n  STR_EQUIPMENT: \"Equipaggiamento\"\n  STR_ALIEN_CORPSE: \"Cadavere alieno\"\n  STR_UFO_COMPONENT: \"Componente SOTTOM. ALIENO\"\n  STR_PERSONAL_ARMOR: \"Arm. Personale\"\n  STR_RAW_MATERIALS: \"Materiali Grezzi\"\n  STR_HWP_SOLID_HARPOON_BOLTS: \"Dardi Arpione Massicci\"\n  STR_ALIEN: \"Alieno\"\n  STR_AQUATOID: \"Aquatoide\"\n  STR_GILLMAN: \"Branchiato\"\n  STR_LOBSTERMAN: \"Uomo-Aragosta\"\n  STR_TASOTH: \"Tasoth\"\n  STR_CALCINITE: \"Calcinite\"\n  STR_DEEP_ONE: \"Essere Abissale\"\n  STR_BIODRONE: \"Bio-drone\"\n  STR_TENTACULAT: \"Tentacolato\"\n  STR_TRISCENE: \"Triscene\"\n  STR_HALLUCINOID: \"Allucinoide\"\n  STR_XARQUID: \"Xarquide\"\n  STR_ZOMBIE: \"Zombi\"\n  STR_LIVE_COMMANDER: \"Comandante\"\n  STR_LIVE_NAVIGATOR: \"Navigatore\"\n  STR_LIVE_MEDIC: \"Medico\"\n  STR_LIVE_TECHNICIAN: \"Tecnico\"\n  STR_LIVE_SQUAD_LEADER: \"Caposquadra\"\n  STR_LIVE_SOLDIER: \"Soldato\"\n  STR_LIVE_TERRORIST: \"Terrorista\"\n  STR_AQUATOID_COMMANDER: \"Aquatoide Comandante\"\n  STR_AQUATOID_NAVIGATOR: \"Aquatoide Navigatore\"\n  STR_AQUATOID_MEDIC: \"Aquatoide Medico\"\n  STR_AQUATOID_TECHNICIAN: \"Aquatoide Tecnico\"\n  STR_AQUATOID_SQUAD_LEADER: \"Aquatoide Caposquadra\"\n  STR_AQUATOID_SOLDIER: \"Aquatoide Soldato\"\n  STR_GILLMAN_COMMANDER: \"Comandante Gillman\"\n  STR_GILLMAN_TECHNICIAN: \"Tecnico Gillman\"\n  STR_GILLMAN_SQUAD_LEADER: \"Caposquadra Gillman\"\n  STR_GILLMAN_SOLDIER: \"Soldato Gillman\"\n  STR_LOBSTERMAN_COMMANDER: \"Uomo-Aragosta Comandante\"\n  STR_LOBSTERMAN_NAVIGATOR: \"Uomo-Aragosta Navigatore\"\n  STR_LOBSTERMAN_TECHNICIAN: \"Uomo-Aragosta Tecnico\"\n  STR_LOBSTERMAN_SQUAD_LEADER: \"Uomo-Aragosta Caposquadra\"\n  STR_LOBSTERMAN_SOLDIER: \"Uomo-Aragosta Soldato\"\n  STR_TASOTH_SQUAD_LEADER: \"Tasoth Caposquadra\"\n  STR_TASOTH_SOLDIER: \"Tasoth Soldato\"\n  STR_CALCINITE_TERRORIST: \"Calcinite Terrorista\"\n  STR_DEEP_ONE_TERRORIST: \"Essere Abissale Terrorista\"\n  STR_BIODRONE_TERRORIST: \"Bio-drone Terrorista\"\n  STR_TENTACULAT_TERRORIST: \"Tentacolato Terrorista\"\n  STR_TRISCENE_TERRORIST: \"Triscene Terrorista\"\n  STR_HALLUCINOID_TERRORIST: \"Allucinoide Terrorista\"\n  STR_XARQUID_TERRORIST: \"Xarquide Terrorista\"\n  STR_ION_BEAM_ACCELERATORS: \"Acceleratori a Raggi Ionici\"\n  STR_MAGNETIC_NAVIGATION: \"Navigazione Magnetica\"\n  STR_ALIEN_SUB_CONSTRUCTION: \"Struttura Sottomarino Alieno\"\n  STR_ALIEN_CRYOGENICS: \"Sistema di Criogenia Alieno\"\n  STR_ALIEN_CLONING: \"Sistema di Clonazione Alieno\"\n  STR_ALIEN_LEARNING_ARRAYS: \"Sistema di Apprendimento Alieno\"\n  STR_ALIEN_IMPLANTER: \"Sistema Impiantatore Alieno\"\n  STR_EXAMINATION_ROOM: \"Sala di Esaminazione\"\n  STR_AQUA_PLASTICS: \"Acqua-Plastiche\"\n  STR_ALIEN_REANIMATION_ZONE: \"Zona Rianimazione Aliena\"\n  STR_PLASTIC_AQUA_ARMOR: \"Armatura di Acqua-Plastiche\"\n  STR_ION_ARMOR: \"Armatura Ionica\"\n  STR_MAGNETIC_ION_ARMOR: \"Armatura Ionica Magnetica\"\n  STR_HWP_AQUA_JET_MISSILES: \"Siluri Aqua Jet\"\n  STR_HWP_DISPLACER_PWT: \"Siluro O.P.\"\n  STR_GAUSS_TECH: \"Tecnologia Gauss\"\n  STR_NEW_FIGHTER_FLYING_SUB: \"Nuovo Caccia Sottomarino Volante\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Nuovo Caccia-Trasportatore\"\n  STR_THE_LATEST_FLYING_SUB: \"Il Sottomarino Volante Definitivo\"\n  STR_ARMOR_PIERCING: \"PERFORANTE\"\n  STR_COELACANTH_GAS_CANNON: \"Celacanto/Cannone a Gas\"\n  STR_COELACANTH_AQUA_JET: \"Celacanto/Aqua Jet\"\n  STR_COELACANTH_GAUSS: \"Celacanto/Gauss\"\n  STR_DISPLACER_SONIC: \"Dislocatore/Sonico\"\n  STR_DISPLACER_PWT: \"Dislocatore/S.O.P.\"\n  STR_AJAX_LAUNCHER: \"Lanciasiluri Ajax\"\n  STR_DUP_HEAD_LAUNCHER: \"Lanciasiluri Testata U.I.\"\n  STR_CRAFT_GAS_CANNON: \"Cannone a Gas Compresso\"\n  STR_PWT_CANNON: \"Cannone S.O.P.\"\n  STR_GAUSS_CANNON: \"Cannone Gauss\"\n  STR_GAUSS_CANNON_AMMO: \"Munizioni Cannone Gauss\"\n  STR_SONIC_OSCILLATOR: \"Oscillatore Sonico\"\n  STR_AJAX_TORPEDOES: \"Siluri Ajax\"\n  STR_DUP_HEAD_TORPEDOES: \"Siluri Testata U.I.\"\n  STR_CRAFT_GAS_CANNON_ROUNDS_X50: \"Munizioni Gas(x50)\"\n  STR_SONIC_WAVE: \"Onda Sonica\"\n  STR_PULSE_WAVE_TORPEDOES: \"Munizioni S.O.P.\"\n  STR_SOLDIER: \"Acquanauta\"\n  STR_SCIENTIST: \"Scienziato\"\n  STR_ENGINEER: \"Tecnico\"\n  STR_NORTH_ATLANTIC: \"Atlantico Settentr.\"\n  STR_SOUTH_ATLANTIC: \"Atlantico Merid.\"\n  STR_NORTH_PACIFIC: \"Pacifico Settentr.\"\n  STR_SOUTH_PACIFIC: \"Pacifico Merid.\"\n  STR_MEDITERRANEAN: \"Mediterraneo\"\n  STR_SOUTH_CHINA_SEA: \"Mar Cinese Merid.\"\n  STR_INDIAN_OCEAN: \"Oceano Indiano\"\n  STR_THE_EAST_SEA: \"Mar del Giappone\"\n  STR_NORTH_SEA: \"Mare del Nord\"\n  STR_CARRIBEAN: \"Caraibi\"\n  STR_ANTARCTIC: \"Antartide\"\n  STR_ARCTIC: \"Artide\"\n  STR_EURASIA: \"Eurasia\"\n  STR_NORTH_AMERICA: \"America del Nord\"\n  STR_AFRICA: \"Africa\"\n  STR_MAXIMUM_SPEED: \"Velocità Massima\"\n  STR_TRANSMISSION_RESOLVER_UC: \"DECIFRATORE TRASMISSIONI\"\n  STR_TRITON: \"TRITON\"\n  STR_HAMMERHEAD: \"HAMMERHEAD\"\n  STR_LEVIATHAN: \"LEVIATHAN\"\n  STR_BARRACUDA: \"BARRACUDA\"\n  STR_MANTA: \"MANTA\"\n  STR_UFO: \"SOTTOM. ALIENO\"\n  STR_AJAX: \"AJAX\"\n  STR_DUP_HEAD: \"TESTATA U.I.\"\n  STR_CRAFT_GAS_CANNON_UC: \"CANNONE A GAS COMPRESSO\"\n  STR_PWT_CANNON_UC: \"CANNONE S.O.P.\"\n  STR_GAUSS_CANNON_UC: \"CANNONE GAUSS\"\n  STR_SONIC_OSCILLATOR_UC: \"OSCILLATORE SONICO\"\n  STR_DAMAGE_CAPACITY: \"Danni Sostenibili\"\n  STR_WEAPON_POWER: \"Potenza Arma\"\n  STR_WEAPON_RANGE: \"Portata Arma\"\n  STR_AIR_LOCK: \"Camera Stagna\"\n  STR_LABORATORY: \"Laboratorio\"\n  STR_WORKSHOP: \"Officina\"\n  STR_STANDARD_SONAR: \"Sonar Standard\"\n  STR_WIDE_ARRAY_SONAR: \"Sonar ad Ampio Raggio\"\n  STR_TORPEDO_DEFENSES: \"Sistema difensivo a Siluri\"\n  STR_GENERAL_STORES: \"Magazzini\"\n  STR_ALIEN_CONTAINMENT: \"Contenimento Alieni\"\n  STR_GAUSS_DEFENSES: \"Sistema difensivo Gauss\"\n  STR_SONIC_DEFENSES: \"Sistema difensivo Sonico\"\n  STR_PWT_DEFENSES: \"Sistema difensivo S.O.P.\"\n  STR_BOMBARDMENT_SHIELD: \"Scudo Bombardamento\"\n  STR_MC_GENERATOR: \"Generatore C.M.\"\n  STR_MC_LAB: \"Laboratorio C.M.\"\n  STR_TRANSMISSION_RESOLVER: \"Decifratore Trasmissioni\"\n  STR_SUB_PEN: \"Rimessa Sottomarino\"\n  STR_USA: \"USA\"\n  STR_ALASKA: \"ALASKA\"\n  STR_EU_SYNDICATE: \"EURO-UNIONE\"\n  STR_ARABIAN_BLOC: \"BLOCCO ARABICO\"\n  STR_EGYPTIAN_CARTEL: \"CARTELLO EGIZIANO\"\n  STR_AFRICA_CORP: \"CORPORAZ. AFRICANA\"\n  STR_BRAZILIAN_UNION: \"UNIONE BRASILIANA\"\n  STR_NEW_MEXICO: \"NUOVO MESSICO\"\n  STR_ASIAN_COALITION: \"COALIZION. ASIATICA\"\n  STR_SCANDINAVIA: \"SCANDINAVIA\"\n  STR_NEO_JAPAN: \"NEO-GIAPPONE\"\n  STR_FREE_CHINA: \"CINA LIBERA\"\n  STR_AUSTRALASIA: \"AUSTRALASIA\"\n  STR_FED_KOREA: \"FEDERAZ. COREANA\"\n  STR_EURASIA_UC: \"EURASIA\"\n  STR_ICELANDIC_UNION: \"UNIONE ISLANDESE\"\n  STR_TANK: \"Sistema di Armamento Sottomarino\"\n  STR_CIVILIAN: \"Civile\"\n  STR_JAN: \"Gen\"\n  STR_FEB: \"Feb\"\n  STR_MAR: \"Mar\"\n  STR_APR: \"Apr\"\n  STR_MAY: \"Mag\"\n  STR_JUN: \"Giu\"\n  STR_JUL: \"Lug\"\n  STR_AUG: \"Ago\"\n  STR_SEP: \"Set\"\n  STR_OCT: \"Ott\"\n  STR_NOV: \"Nov\"\n  STR_DEC: \"Dic\"\n  STR_INTERNATIONAL_RELATIONS: \"Relazioni Internazionali\"\n  STR_COUNTRY: \"Nazione\"\n  STR_FUNDING: \"Finanziamenti\"\n  STR_CHANGE: \"Variazione\"\n  STR_WEAPON_SYSTEMS: \"SISTEMI DI ARMAMENTO\"\n  STR_HWPS: \"SAS\"\n  STR_DAMAGE_UC_: \"DANNO>{ALT}{0}\"\n  STR_AIR_LOCK_UFOPEDIA: \"L'Ascensore d'Accesso permette all'equipaggiamento e al personale di essere trasferito da o nella base sottomarina. È sempre la prima struttura ad essere costruita in una nuova base. L'Ascensore d'Accesso è vulnerabile alle intrusioni da qualsiasi potenziale forza ostile.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Ogni area abitativa può accogliere fino a 50 persone. Le strutture sono piuttosto spartane e funzionali.\"\n  STR_LABORATORY_UFOPEDIA: \"In un blocco laboratorio possono lavorare fino a cinquanta scienziati. I laboratori sono dotati delle ultime tecnologie scientifiche per la ricerca sui materiali, sulla biochimica e sulle armi. X-Com ha l'accesso ai migliori laboratori di ricerca del mondo, sia quelli civili che quelli militari.\"\n  STR_WORKSHOP_UFOPEDIA: \"Un'officina contiene tutti gli strumenti necessari per produrre equipaggiamento basato sugli ultimi progetti dei laboratori. Un massimo di 50 Tecnici può occupare una sola officina, anche gli oggetti in costruzione occuperanno spazio.\"\n  STR_STANDARD_SONAR_UFOPEDIA: \"Un sistema di sonar standard ha un raggio efficace di oltre 450 chilometri in buona parte delle profondità marine ed è collegato a reti di satelliti geostazionari per analisi della superficie. Ogni sistema ha un 10% di probabilità di individuare un sottomarino o uno scafo volante per ogni ciclo di scansione di 30 minuti.\"\n  STR_WIDE_ARRAY_SONAR_UFOPEDIA: \"Un sistema di sonar ad ampio raggio ha un raggio efficace di oltre 700 chilometri a tutte le profondità ed è collegato a reti di satelliti geostazionari per analisi della superficie. Ogni sistema ha un 20% di probabilità di individuare un sottomarino o uno scafo volante per ogni ciclo di scansione di 30 minuti.\"\n  STR_TORPEDO_DEFENSES_UFOPEDIA: \"I sistemi difensivi a siluri offrono protezione contro l'attacco dei sottomarini nemici che tentano di attraccare alla base.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"Tutti gli equipaggiamenti, i sistemi d'arma, le munizioni, i materiali recuperati ed i Sistemi di Armamento Sottomarini sono riposti nei magazzini, incluso l'equipaggiamento assegnato ai Sottomarini nelle Rimesse.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"Gli Alieni Vivi richiedono speciali strutture di contenimento per trattenerli. Queste unità mantengono i loro sistemi vitali ed azzereranno il loro potenziale di combattimento. La struttura di contenimento può contenere fino a 10 forme di vita aliena in unità di reclusione.\"\n  STR_GAUSS_DEFENSES_UFOPEDIA: \"La difesa Gauss fornisce la protezione più innovativa ed efficace contro l'attacco da parte dei sottomarini nemici.\"\n  STR_SONIC_DEFENSES_UFOPEDIA: \"Le difese a Oscillatore Sonico offrono una protezione potente ed efficiente contro gli aggressori.\"\n  STR_PWT_DEFENSES_UFOPEDIA: \"I Siluri ad Onde Pulsanti offrono la migliore difesa contro gli attacchi Alieni. Questi missili hanno testate super dense che possono penetrare qualsiasi corazzatura conosciuta. Le onde magnetiche da loro prodotte disabilitano le difese elettroniche.\"\n  STR_BOMBARDMENT_SHIELD_UFOPEDIA: \"Lo scudo di Bombardamento a Pressione protegge la base dagli attracchi dei sottomarini Alieni ed attiva un campo di risonanza che respinge i sottomarini attaccanti per un tempo sufficiente da permettere ai sistemi di difesa di sparare ripetutamente. In pratica questo raddoppia l'efficacia di ogni sistema di difesa già impiegato.\"\n  STR_MC_GENERATOR_UFOPEDIA: \"Dato che i sottomarini Alieni utilizzano la Tecnologia del Controllo Molecolare per individuare la presenza di creature viventi, utilizzando un C.M negativo l'emettitore coprirà la base con uno scudo impenetrabile per confondere gli Alieni e mascherare la nostra presenza.\"\n  STR_MC_LAB_UFOPEDIA: \"Il laboratorio di Controllo Molecolare può impiantare ed addestrare fino a dieci acquanauti alla volta. Gli impianti sono istallati chirurgicamente nei crani degli acquanauti. Un allenamento estensivo gli permetterà di utilizzare i propri impianti. Le abilità degli impianti sono usate insieme ad un Dispositivo Molecolare e possono essere utilizzate in attacchi in combattimento.\"\n  STR_TRANSMISSION_RESOLVER_UFOPEDIA: \"Le comunicazioni Aliene utilizzano la rete dell'impianto di controllo Molecolare che gli alieni hanno costruito. La struttura di decifrazione trasmissioni intercetta le trasmissioni dei Sottomarini Alieni e decodifica le informazioni. Questo mostrerà il tipo di Sottomarino Alieno, la razza Aliena presente ed il tipo di attività svolta.\"\n  STR_SUB_PEN_UFOPEDIA: \"Ogni Rimessa può accogliere un sottomarino. Sono presenti macchinari per la manutenzione, il rifornimento e la riparazione della flotta sottomarina X-Com. Ogni Sottomarino Volante stazionante in base deve avere una Rimessa libera assegnatagli che non può essere utilizzata da altri Sottomarini, anche se il sottomarino assegnato è fuori in missione.\"\n  STR_DART_PISTOL_UFOPEDIA: \"La pistola a dardi X-Com è una unità piccola, precisa e potente con un caricatore di 12 dardi a punta cava. I dardi vengono sparati da una cartuccia a gas nel serbatoio delle munizioni.\"\n  STR_JET_HARPOON_UFOPEDIA: \"Questo fucile marino è preciso e potente e spara potenti arpioni d'acciaio dalle confezioni ermetiche da 10. Ogni arpione ha la propria riserva di gas.\"\n  STR_GAS_CANNON_UFOPEDIA: \"Il peso massimo della famiglia tecnologica a gas, questo cannone spara massicci pallettoni, alcuni con punte esplosive o al fosforo. Una delle armi preferite dagli acquanauti esperti.\"\n  STR_HYDRO_JET_CANNON_UFOPEDIA: \"I cannoni Idro-Jet sono sistemi di armamento pesante per la fanteria. Il cannone spara mini-siluri alimentati al magnesio. Anche se potente, il Cannone Idro-Jet è un congegno goffo ed ingombrante, adatto solo per l'uso subacqueo.\"\n  STR_TORPEDO_LAUNCHER_UFOPEDIA: \"Un vero peso massimo, questo grosso lanciatore può usare tre tipi di siluro, ognuno con la propria unità di propulsione. Un'arma devastante, il cui unico svantaggio è il caricamento manuale. I tipi di munizione disponibili comprendono siluri ad alto potenziale esplosivo grandi o piccoli e siluri con punta al fosforo, tutti per l'uso esclusivamente subacqueo.\"\n  STR_GAUSS_PISTOL_UFOPEDIA: \"La pistola Gauss utilizza la tecnologia delle particelle accelerate, un nuovo ritrovato negli armamenti moderni. È veloce, precisa e funziona sia fuori che sotto l'acqua. La tecnologia Gauss è uno sviluppo delle tecnologie al Plasma appresa dalla guerra precedente.\"\n  STR_GAUSS_PISTOL_CLIP_UFOPEDIA: \"La pistola Gauss utilizza la tecnologia delle particelle accelerate, un nuovo ritrovato negli armamenti moderni. È veloce, precisa e funziona sia fuori che sotto l'acqua. La tecnologia Gauss è uno sviluppo delle tecnologie al Plasma appresa dalla guerra precedente.\"\n  STR_GAUSS_RIFLE_UFOPEDIA: \"Un passo avanti rispetto alla pistola Gauss, il fucile è un'arma estremamente potente, con i suoi acceleratori di particelle combinati. Al posto del sistema al Plasma alimentato all'Elerium abbiamo utilizzato un micro acceleratore di particelle il quale genera un fascio di anti-protoni.\"\n  STR_GAUSS_RIFLE_CLIP_UFOPEDIA: \"Un passo avanti rispetto alla pistola Gauss, il fucile è un'arma estremamente potente, con i suoi acceleratori di particelle combinati. Al posto del sistema al Plasma alimentato all'Elerium abbiamo utilizzato un micro acceleratore di particelle il quale genera un fascio di anti-protoni.\"\n  STR_HEAVY_GAUSS_UFOPEDIA: \"Il Gauss pesante è ingombrante, ma estremamente efficace. Funziona grazie a 3 acceleratori di particelle ed è praticamente inarrestabile. Il fascio di anti-protoni è contenuto dentro una capsula di Arseniuro di Gallio che implode all'impatto rilasciando l'antimateria.\"\n  STR_HEAVY_GAUSS_CLIP_UFOPEDIA: \"Il Gauss pesante è ingombrante, ma estremamente efficace. Funziona grazie a 3 acceleratori di particelle ed è praticamente inarrestabile. Il fascio di anti-protoni è contenuto dentro una capsula di Arseniuro di Gallio che implode all'impatto rilasciando l'antimateria.\"\n  STR_MAGNA_BLAST_GRENADE_UFOPEDIA: \"Questa granata di ordinanaza ha un timer preciso e sofisticato per un controllo di precisione.\"\n  STR_DYE_GRENADE_UFOPEDIA: \"Le granate a tinta sono oggetti dalla duplice funzionalità, che offrono copertura in situazioni dove le truppe sono esposte. Capaci di funzionare sia in acqua che sulla terra ferma la tinta è espulsa in una nuvola di particelle, producendo un getto di inchiostro simile ad un polpo nell'acqua o una densa nuvola aerea sulla terra ferma.\"\n  STR_PARTICLE_DISTURBANCE_GRENADE_UFOPEDIA: \"Una granata di prossimità che può essere lanciata come una normale granata ma è attivata da qualsiasi movimento nelle sue vicinanze dopo che è stata piazzata. Abilità ed allenamento sono richiesti per poter utilizzare correttamente questi dispositivi.\"\n  STR_MAGNA_PACK_EXPLOSIVE_UFOPEDIA: \"Questo esplosivo dovrebbe essere utilizzato solo per fini demolitivi. Tuttavia esperienze passate hanno insegnato che questi potenti pacchi esplosivi sono un'arma ideale per stanare gli Alieni. Il raggio di esplosione è ampio quindi assicurati che nessun acquanauta sia entro la minima distanza di sicurezza.\"\n  STR_PARTICLE_DISTURBANCE_SENSOR_UFOPEDIA: \"Questo apparecchio innovativo utilizza una gamma di rilevatori e di avanzati sistemi computeristici per individuare unità nemiche in movimento. Clicca sull'icona del Sensore di Interferenze sul display tattico. Seleziona 'Usa Sensore' dal menu. Il display del Sensore mostra una freccia al centro che rispecchia la direzione dell'acquanauta (con il Nord in alto). I lampeggi rappresentano le unità mosse recentemente. Grosse unità, o unità mosse rapidamente, producono lampeggi più grossi. Unità ferme non verranno mostrate.\"\n  STR_MEDI_KIT_UFOPEDIA: \"Per utilizzare questo dispositivo devi essere rivolto verso l'agente X-Com ferito o posizionarti sopra il corpo di un acquanauta stordito.{NEWLINE}CURA> Il colore rosso indica le ferite. Seleziona la parte del corpo e clicca sul pulsante 'Cura'. Sarà curata una ferita mortale e ripristinata un po' di salute.{NEWLINE}STIMOLANTE> Ripristina il vigore e risveglia gli acquanauti storditi. Per risvegliare un acquanauta stordito devi posizionarti direttamente sopra il suo corpo.{NEWLINE}ANTIDOLORIFICO> Ripristina il morale degli acquanauti feriti.\"\n  STR_MC_DISRUPTOR_UFOPEDIA: \"L'ultimo ritrovato nella tecnologia C.M.. Può essere utilizzato solo da acquanauti con abilità di C.M.. Clicca sul Perturbatore, seleziona il tipo di attacco e seleziona un'unità bersaglio con il cursore. Esistono due tipi di attacchi con il Perturbatore:{NEWLINE}DISTURBA IMPIANTO> Se ha successo l'unità sarà confusa è può cadere in preda al panico.{NEWLINE}CONTROLLA IMPIANTO> Se ha successo potrai prendere controllo dell'unità nemica.\"\n  STR_THERMAL_TAZER_UFOPEDIA: \"Questo dispositivo può essere utilizzato solo in combattimento corpo a corpo, ma stordirà un organismo vivente senza ucciderlo assiderando la creatura.\"\n  STR_VIBRO_BLADE_UFOPEDIA: \"La Vibro-Lama è una lunga lama di titanio affilata che gira ad oltre 6000 rpm, questo dispositivo può penetrare anche lo scafandro più resistente. La fonte di energia è un'invenzione Aliena, i nostri primi tentativi nel costruire questi oggetti hanno dato risultati scadenti, in quanto le nostre lame giravano troppo lente o esplodevano sotto pressione.\"\n  STR_THERMIC_LANCE_UFOPEDIA: \"La Lancia Termica è una evoluzione logica della tecnologia della Vibro-Lama. La lama ruota ad alta velocità ed una fonte di energia di Zrbite surriscalda la lama per tagliare le armature come un coltello caldo attraversa il burro.\"\n  STR_HEAVY_THERMIC_LANCE_UFOPEDIA: \"La Lancia Termica Pesante è una versione potenziata della LT. Due fonti di calore ed una velocità di rotazione estremamente alta comporta che la Lancia Termica Pesante sia praticamente inarrestabile da qualsiasi materiale.\"\n  STR_SONIC_CANNON_UFOPEDIA: \"Il Cannone Sonico è la più potente della famiglia delle armi Soniche. È dotato di un oscillatore audio a maggiore estensione e di una camera di riverbero più larga rispetto al Blasta. Il Cannone ha inoltre un sistema di detonazione ad impulsi che altera la modulazione dell'onda ultrasonica per produrre uno Shock Sonico ancora più efficace.\"\n  STR_CANNON_POWER_CLIP_UFOPEDIA: \"Questo dispositivo di ridotte dimensioni è utilizzato come munizione per il Cannone Sonico. Contiene una piccola quantità di Zrbite.\"\n  STR_SONIC_BLASTA_RIFLE_UFOPEDIA: \"Un dispositivo sonico di maggiore potenza. Neppure l'acciaio ad alto tenore di carbonio è immune a quest'arma. L'emettitore di onde estremamente compatto è potenziato da un amplificatore a superconduttori che aumenta la potenza dell'arma.\"\n  STR_BLASTA_POWER_CLIP_UFOPEDIA: \"Questo piccolo oggetto è utilizzato come fonte di energia per il Fucile Blasta-Sonico, una potente arma Aliena, e contiene una piccola quantità di Zrbite.\"\n  STR_SONIC_PISTOL_UFOPEDIA: \"Le pistole soniche sono un'arma Aliena basate sulle onde sonore ultrasoniche capace di gelatinizzare le ossa in pochi secondi. Le onde Ultrasoniche coprono un'estensione oltre la portata dell'udito umano.\"\n  STR_PISTOL_POWER_CLIP_UFOPEDIA: \"Fonte di energia per la compatta Pistola Sonica Aliena. Contiene Zrbite - la fonte di tutto il potere Alieno.\"\n  STR_DISRUPTOR_PULSE_LAUNCHER_UFOPEDIA: \"Questa è una arma guidata Aliena per uso esclusivamente acquatico che lancia 'Proiettili Disgreganti' autopropulsi. Quando clicchi per fare fuoco con l'arma questa genererà 'punti guida' che il Proiettile seguirà. Quando hai posizionato abbastanza punti guida clicca sull'icona di lancio.\"\n  STR_DISRUPTOR_AMMO_UFOPEDIA: \"Questo dispositivo è un Proiettile a Impulsi Disgreganti dotato di un sistema di guida computerizzato interno. Viene sparato da un Lanciamissili a Impulso Disgregante.\"\n  STR_THERMAL_SHOK_LAUNCHER_UFOPEDIA: \"Un piccolo Lanciagranate a Shok Termico che spara bombe a congelamento chimico. Molto utile per catturare Alieni vivi.\"\n  STR_THERMAL_SHOK_BOMB_UFOPEDIA: \"La bomba a Shok Termico viene utilizzata per catturare umani vivi, ma può essere utilizzata anche contro buona parte delle razze Aliene. Viene sparata da un Lanciagranate a Shok Termico.\"\n  STR_SONIC_PULSER_UFOPEDIA: \"Questo dispositivo funziona nella stessa maniera di una granata di ordinanza - solo che è di gran lunga più potente. La granata utilizza un singolo impulso sonico esplosivo emesso in tutte le direzioni simultaneamente.\"\n  STR_MC_READER_UFOPEDIA: \"Dentro i corpi degli Alieni abbiamo trovato piccole unità impiantate chirurgicamente. Questi sono Impianti di Controllo progettati dagli Aquatoidi per permettere un costante flusso di informazioni dal campo di battaglia, anche a grandi distanze. Il Lettore di Controllo Molecolare è un dispositivo di comunicazione Alieno utilizzato per cogliere informazioni direttamente dagli Impianti C.M.. Le unità X-Com possono utilizzare questo dispositivo in combattimento per visualizzare le caratteristiche di un Alieno. Seleziona l'opzione 'usa'. Quindi clicca su di un Alieno con il cursore.\"\n  STR_SURVEY_SHIP: \"Nave Esploratrice\"\n  STR_ESCORT: \"Scorta\"\n  STR_CRUISER: \"Incrociatore\"\n  STR_HEAVY_CRUISER: \"Incrociatore Pesante\"\n  STR_HUNTER: \"Cacciatore\"\n  STR_BATTLESHIP: \"Nave da Guerra\"\n  STR_DREADNOUGHT: \"Corazzata\"\n  STR_FLEET_SUPPLY_CRUISER: \"Incrociatore Rifornimento Flotta\"\n  MAP_SEABED: \"Fondale marino\"\n  MAP_PIPES: \"Impianto di ricerca\"\n  MAP_PLANE: \"Relitto di aeroplano\"\n  MAP_ATLAN: \"Atlantide\"\n  MAP_MU: \"Tempio Maya\"\n  MAP_GAL: \"Relitto di Galeone\"\n  MAP_MSUNK: \"Relitto di Transatlantico\"\n  MAP_VOLC: \"Vulcano\"\n  MAP_CORAL: \"Corallo\"\n  MAP_PORT: \"Porto\"\n  MAP_ISLAND: \"Isola\"\n  MAP_CARGO: \"Nave da carico\"\n  MAP_LINERT: \"Nave da Crociera P1\"\n  MAP_LINERB: \"Nave da Crociera P2\"\n  MAP_ALART: \"Artefatto P1\"\n  MAP_GRUNGE: \"Artefatto P2\"\n  MAP_ENTRY: \"Colonia P1\"\n  MAP_A_BASE: \"Colonia P2\"\n  MAP_ALSHIP: \"T'leth P1\"\n  MAP_LEVEL: \"T'leth P2\"\n  MAP_CRYPT: \"T'leth P3\"\n  MAP_XBASES: \"Base X-Com\"\n  STR_MIXED_CREW: \"Equipaggio Misto\"\n  STR_MIXED_CREW_2: \"Equipaggio Misto 2\"\n  STR_RATING: \"VALUTAZIONE> {0}\"\n  STR_RATING_TERRIBLE: \"PESSIMO!\"\n  STR_RATING_POOR: \"SCARSO!\"\n  STR_RATING_OK: \"OK\"\n  STR_RATING_GOOD: \"BUONO!\"\n  STR_RATING_EXCELLENT: \"ECCELLENTE!\"\n  STR_SCORE: \"PUNTEGGIO\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"RAPPORTO MENSILE X-COM\"\n  STR_MONTH: \"Mese> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"Il comitato delle organizzazioni finanziatrici è complessivamente soddisfatto dei tuoi progressi.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"Il comitato delle organizzazioni finanziatrici è molto contento dei tuoi sforzi eccellenti. Continua così.\"\n  STR_COUNCIL_IS_DISSATISFIED: \"Il comitato delle organizzazioni finanziatrici è insoddisfatto dei tuoi risultati. Devi migliorare la tua efficacia nell'affrontare la minaccia Aliena o rischierai l'interruzione del supporto finanziario ad X-Com.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"Non sei riuscito ad affrontare l'invasione Aliena ed il comitato delle organizzazioni finanziatrici ha sfortunatamente deciso di interrompere i finanziamenti ad X-Com. Ogni organizzazione affronterà il problema come meglio crede. Possiamo solo sperare che riescano a trovare qualche accordo con queste antiche forze, e che la popolazione mondiale raggiunga un accordo con i visitatori acquatici.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} è particolarmente soddisfatta della tua abilità nell'affrontare la minaccia nei suoi territori e ha deciso di aumentare i loro finanziamenti.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} sono particolarmente felici dei tuoi progressi nell'affrontare le incursioni Aliene nei loro territori ed hanno deciso di aumentare i loro finanziamenti.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} e {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} è insoddisfatta della tua abilità nell'affrontare l'attività Aliena nei suoi Mari ed ha deciso di diminuire i propri contributi finanziari.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} sono insoddisfatti della tua abilità nell'affrontare l'attività Aliena nei loro Mari ed hanno deciso di ridurre i propri contributi finanziari.\"\n  STR_KNOTS: \"{0} nodi\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} ha firmato un patto di cooperazione con le forze Aliene e si è ritirato dai finanziamenti ad X-Com.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} hanno firmato un patto di cooperazione con le forze Aliene e si sono ritirati dai finanziamenti ad X-Com.\"\n  STR_MONTHLY_RATING: \"Valutazione mensile> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Cambio finanziamenti> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"L'organizzazione dei finanziatori non è felice della tua situazione finanziaria. Devi ridurre i tuoi debiti sotto $1 milione oppure la X-Com sarà terminata.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"DECIFRATE TRASMISSIONI SUB-PARTICELLARI\"\n  STR_CRAFT_TYPE: \"TIPO SOTTOM.\"\n  STR_RACE: \"RAZZA\"\n  STR_MISSION: \"MISSIONE\"\n  STR_ZONE: \"ZONA\"\n  STR_ALLOCATE_RESEARCH: \"Assegna Ricerca\"\n  STR_ALLOCATE_MANUFACTURE: \"Assegna Produzione\"\n  STR_AZORES: \"Azzorre\"\n  STR_REYKJAVIK: \"Reykjavik\"\n  STR_BERMUDA: \"Bermuda\"\n  STR_NEW_YORK: \"New York\"\n  STR_BOSTON: \"Boston\"\n  STR_FORT_SEVERN: \"Fort Severn\"\n  STR_DAKAR: \"Dakar\"\n  STR_RECIFE: \"Recife\"\n  STR_ACCRA: \"Accra\"\n  STR_ASCENSION_ISLAND: \"Isola dell'Ascensione\"\n  STR_TRINIDADE_ISLAND: \"Isola di Trinidade\"\n  STR_FALKLAND_ISLAND: \"Isole Falkland\"\n  STR_CANARY_ISLANDS: \"Isole Canarie\"\n  STR_ANCHORAGE: \"Anchorage\"\n  STR_ST_LAWRENCE_ISLAND: \"Isola di San Lorenzo\"\n  STR_SAN_FRANCISCO: \"San Francisco\"\n  STR_MIDWAY_ISLAND: \"Isole Midway\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_TASMANIA: \"Tasmania\"\n  STR_HAWAII: \"Hawaii\"\n  STR_FIJI: \"Figi\"\n  STR_TONGA: \"Tonga\"\n  STR_EASTER_ISLAND: \"Isola di Pasqua\"\n  STR_GALAPAGOS_ISLAND: \"Isole Galapagos\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_SOLOMON_ISLAND: \"Isole Salomone\"\n  STR_CRETE: \"Creta\"\n  STR_LISBON: \"Lisbona\"\n  STR_PORT_SAID: \"Porto Said\"\n  STR_MARSEILLES: \"Marsiglia\"\n  STR_TRIPOLI: \"Tripoli\"\n  STR_MANILA: \"Manila\"\n  STR_HONG_KONG: \"Hong Kong\"\n  STR_SINGAPORE: \"Singapore\"\n  STR_BANGKOK: \"Bangkok\"\n  STR_DARWIN: \"Darwin\"\n  STR_BOMBAY: \"Bombay\"\n  STR_SAYCHELLES_ISLAND: \"Isole Seychelles\"\n  STR_MALDIVE_ISLAND: \"Isole Maldive\"\n  STR_SRI_LANKA: \"Sri Lanka\"\n  STR_MAURITIUS: \"Mauritius\"\n  STR_TOKYO: \"Tokyo\"\n  STR_SHANGHAI: \"Shanghai\"\n  STR_VLADIVOSTOK: \"Vladivostok\"\n  STR_LONDON: \"Londra\"\n  STR_FAEROE_ISLAND: \"Isole Fær Øer\"\n  STR_ABERDEEN: \"Aberdeen\"\n  STR_OSLO: \"Oslo\"\n  STR_JAMAICA: \"Jamaica\"\n  STR_PANAMA: \"Panama\"\n  STR_MIAMI: \"Miami\"\n  STR_PSI_TRAINING: \"Addestramento C.M.\"\n  STR_PSIONIC_TRAINING: \"ADDESTRAMENTO CONTROLLO MOLECOLARE\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Spazio Laboratorio C.M. rimanente> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"Forza{NEWLINE}C.M.\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"Abilità C.M./{NEWLINE}Miglioramento\"\n  STR_IN_TRAINING: \"In{NEWLINE}Allenamento?\"\n  STR_TARGETTED_BY: \"OBIETTIVO DI:\"\n  STR_WEAPONS_CREW_HWPS: \"ARMI/{NEWLINE}EQUIPAGGIO/SAS\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"è a corto di carburante,{NEWLINE}in rientro alla base\"\n  STR_SOLDIER_LIST: \"Lista Acquanauti\"\n  STR_RANK_: \"GRADO> {ALT}{0}\"\n  STR_MISSIONS: \"MISSIONI> {ALT}{0}\"\n  STR_KILLS: \"UCCISIONI> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"GUARIGIONE FERITA> {ALT}{0}\"\n  STR_TIME_UNITS: \"UNITÀ DI TEMPO\"\n  STR_STAMINA: \"STAMINA\"\n  STR_HEALTH: \"SALUTE\"\n  STR_BRAVERY: \"CORAGGIO\"\n  STR_REACTIONS: \"REAZIONI\"\n  STR_FIRING_ACCURACY: \"MIRA\"\n  STR_THROWING_ACCURACY: \"TIRO\"\n  STR_STRENGTH: \"FORZA\"\n  STR_PSIONIC_STRENGTH: \"FORZA C.M.\"\n  STR_PSIONIC_SKILL: \"ABILITÀ C.M.\"\n  STR_NEW_RANK: \"NUOVO GRADO\"\n  STR_PROMOTIONS: \"Promozioni\"\n  STR_SOLDIERS_UC: \"ACQUANAUTI\"\n  STR_COELACANTH_GAS_CANNON_UFOPEDIA: \"SAS automatizzati dalla elevata manovrabilità e resistenza della carena. Possono offrire supporto pesante alle truppe a qualsiasi profondità. I SAS sono riarmati automaticamente nel caso in cui ci siano abbastanza munizioni.\"\n  STR_COELACANTH_AQUA_JET_UFOPEDIA: \"Questo sommergibile è armato con siluri Aqua-Jet. Questo sistema di armamento funziona solamente sott'acqua. Assicurati che i tuoi magazzini siano ben forniti di Siluri Aqua-Jet.\"\n  STR_COELACANTH_GAUSS_UFOPEDIA: \"La tecnologia Gauss offre un potente sistema di armamento per i SAS. Offrendo pesante potenza di fuoco in confronto ai modelli precedenti, e utilizza tecnologia proprietaria di X-Com.\"\n  STR_DISPLACER_SONIC_UFOPEDIA: \"La tecnologia Aliena ha ridefinito I SAS. La capacità di utilizzare i Dislocatori Ionici comporta che i SAS non siano più ancorati alla terra o al fondale. Le armi soniche offrono un effettivo vantaggio in battaglia.\"\n  STR_DISPLACER_PWT_UFOPEDIA: \"Questo SAS è dotato di armi a Onde Pulsanti per uso acquatico. Devi costruire S.O.P. per mantenerli perfettamente armati. Per sparare, seleziona un insieme di 'punti guida' quindi clicca sull'icona di lancio.\"\n  STR_ALIEN_PROBE_MISSION: \"Missione Esplorazione Aliena\"\n  STR_ALIEN_INTERDICTION: \"Interdizione Aliena\"\n  STR_ALIEN_RESOURCE_RAID: \"Raid Risorse Alieno\"\n  STR_ALIEN_INFILTRATION: \"Infiltrazione Aliena\"\n  STR_ALIEN_BASE: \"Espansione Colonia Aliena\"\n  STR_ALIEN_SURFACE_ATTACK: \"Attacchi Alieni in Superficie\"\n  STR_ALIEN_RETALIATION: \"Attacco Base Sottomarina\"\n  STR_ALIEN_SUPPLY: \"Missioni Rifornimento Colonia\"\n  STR_ALIEN_PROBE_MISSION_UFOPEDIA: \"La Missione Esplorazione Aliena è utilizzata per raccogliere i dati sul fondale marino, le risorse, le rotte navali ed aeree di un'area. Da soli i sottomarini Alieni impiegati in queste missioni non sono una grave minaccia, ma indicano siti in cui l'attività aliena potrebbe divampare in ogni momento.\"\n  STR_ALIEN_INTERDICTION_UFOPEDIA: \"Gli Alieni sono soliti monitorare aree a cui sono interessati, mandando scafi con il preciso scopo di assicurare un area prima che inizino missioni più laboriose. Atterrano in siti specifici che intenderanno successivamente razziare per isolare l'area e preparare il terreno per le nuove attività.\"\n  STR_ALIEN_RESOURCE_RAID_UFOPEDIA: \"Affondare le navi ed abbattere gli aerei sono elementi chiave della strategia Aliena. L'acquisizione di materiali è una delle principali attività Aliene ed in quanto tale è unita a queste azioni palesemente aggressive. Inoltre gli Alieni razziano aree con attività geotermica, miniere e siti archeologici per minerali, metalli raffinati e altri oggetti prodotti dagli umani.\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"Questa missione può portare ad un contatto ufficiale tra gli Alieni ed i capi di corporazioni o governi. L'apice di questa attività si caratterizza da intense attività di Sottomarini Alieni nelle acque dell'organizzazione interessata. Gli Alieni tenteranno di firmare un accordo con un governo o un'organizzazione offrendo la conoscenza delle loro tecnologie superiori. Questa attività Aliena rappresenta una seria minaccia per X-Com. Se una corporazione o un governo coopera con gli invasori i loro finanziamenti verranno ritirati.\"\n  STR_ALIEN_BASE_UFOPEDIA: \"Gli Alieni costruiranno colonie sottomarine segrete in ubicazioni remote. Dopo alcuni voli iniziali di ricognizione si verificherà della intensa attività di Sottomarini Alieni nel corso della costruzione della colonia. È risaputo che queste colonie contengono laboratori, centri di clonazione, strutture chirurgiche per esperimenti su umani e Alieni. La presenza di colonie Aliene genererà più attività Aliena senza la presenza di Sottomarini Alieni. Per poter individuare una colonia un sottomarino X-Com deve pattugliare un'area per qualche ora se vuole avere qualche possibilità di individuarla.\"\n  STR_ALIEN_SURFACE_ATTACK_UFOPEDIA: \"Quando gli Alieni hanno bisogno di umani essi terrorizzano un porto, attaccano un'isola, o assaltano una nave. I civili sono direttamente minacciati, per soddisfare i deviati bisogni di riproduzione degli Alieni e dei loro orribili esperimenti.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"Se i sottomarini intercettori X-Com sono particolarmente efficaci nell'affondare gli scafi Alieni allora questi ultimi potrebbero decidere di prendere contromisure aggressive. Ciò può dare origine ad un attacco diretto contro una base X-Com. Tuttavia, gli Alieni devono per prima cosa individuare una costruzione X-Com per poterla attaccare, e purché i Sottomarini Alieni sono tenuti lontani dovrebbe esserci poco rischio di un assalto.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"Una volta che una colonia Aliena è costruita viene rifornita regolarmente da una speciale nave da rifornimento. Se uno di questi vascelli viene individuato mentre è posato sul fondale, si può star certi che ci sia una colonia Aliena nelle vicinanze.\"\n  STR_SURVEY_SHIP_UFOPEDIA: \"Questo minuscolo sottomarino viene utilizzato per missioni di ricognizione e di rilevamento. Normalmente precede vascelli più grandi, come avanguardia di una squadra speciale Aliena.\"\n  STR_ESCORT_UFOPEDIA: \"Un vascello scorta di medie dimensioni è poco minaccioso di per sé. Questo precede l'arrivo di vascelli più grandi e attività intensificate.\"\n  STR_CRUISER_UFOPEDIA: \"L'Incrociatore è un vascello multiruolo, il pilastro della flotta Aliena, viene utilizzato in tutti i tipi di missioni Aliene ed è un avversario pericoloso.\"\n  STR_HEAVY_CRUISER_UFOPEDIA: \"L'incrociatore pesante è una nave più potente dell'incrociatore, armi e sistemi di propulsione più grandi ne incrementano il potere. L'Incrociatore Pesante è utilizzato in missioni di raccolta risorse per ottenere grandi quantità di minerali ed equipaggiamento.\"\n  STR_HUNTER_UFOPEDIA: \"Questo vascello è dotato di una sala operatoria per eseguire esperimenti e operazioni chirurgiche su esemplari umani. Le vittime sono sottoposte alle torture più disgustose e il cervello è spesso rimosso e conservato per lavorazioni lungo il viaggio.\"\n  STR_BATTLESHIP_UFOPEDIA: \"La nave da battaglia è la nave più aggressiva che gli Alieni possiedono, dotata di tutti i sistemi e le tecnologie Aliene per fungere da base operativa per ogni forma di azione aggressiva che gli Alieni potrebbero voler attuare, e di un vasto arsenale di armi.\"\n  STR_DREADNOUGHT_UFOPEDIA: \"La Corazzata è un enorme trasporto truppe, dotata di tutte le tecnologie Aliene e di un vasto equipaggio. La Corazzata è un avversario resistente e formidabile.\"\n  STR_FLEET_SUPPLY_CRUISER_UFOPEDIA: \"L'incrociatore di rifornimento è utilizzato durante la costruzione di colonie Aliene o per il rifornimento di colonie già esistenti. Trasporta nutrienti Alieni, DNA, feti ed altri componenti biologici.\"\n  STR_DISMANTLE: \"Smantella\"\n  STR_FACILITY_IN_USE: \"STRUTTURA ACQUATICA IN USO\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"NON È POSSIBILE SMANTELLARE LA STRUTTURA ACQUATICA!{SMALLLINE}Tutte le Strutture della base devono essere collegate all'ascensore d'accesso.\"\n  STR_TRANSFER_ITEMS_TO: \"Trasferisci oggetti a {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"NESSUN CONTENIMENTO ALIENI PER IL TRASFERIMENTO!{SMALLLINE}Gli Alieni vivi necessitano di una struttura di contenimento Alieni per poter sopravvivere.\"\n  STR_AMOUNT_AT_DESTINATION: \"QUANTITÀ A{NEWLINE}DESTINAZIONE\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"L'Alieno è morto per la mancanza di una struttura di contenimento Alieni.\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"NESSUN ALLOGGIO LIBERO!{SMALLLINE}La base di destinazione non ha abbastanza spazio nelle aree abitative per l'equipaggio assegnato al sottomarino.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"NON C'È ABBASTANZA SPAZIO DI IMMAGAZZINAMENTO!{SMALLLINE}La base di destinazione non ha abbastanza spazio nei magazzini per l'equipaggiamento assegnato al sottomarino.\"\n  STR_ITEMS_ARRIVING: \"Oggetti in Arrivo\"\n  STR_DESTINATION_UC: \"DESTINAZIONE\"\n  STR_DART_PISTOL: \"Pistola a Dardi\"\n  STR_DART_POD: \"Caricatore Dardi\"\n  STR_JET_HARPOON: \"Fucile ad Arpioni\"\n  STR_HARPOON_POD: \"Caricatore Arpioni\"\n  STR_GAS_CANNON: \"Cannone a Gas\"\n  STR_GC_AP_AMMO: \"Pallettoni CG-Perf\"\n  STR_GC_HE_AMMO: \"Pallettoni CG-Espl\"\n  STR_GC_P_AMMO: \"Pallettoni CG-Fosf\"\n  STR_HYDRO_JET_CANNON: \"Cannone Idro-Jet\"\n  STR_HJC_AP_AMMO: \"Munizioni IJ-Perf\"\n  STR_HJC_HE_AMMO: \"Munizioni IJ-Espl\"\n  STR_HJC_P_AMMO: \"Munizioni IJ-Fosf\"\n  STR_TORPEDO_LAUNCHER: \"Lanciasiluri\"\n  STR_SMALL_TORPEDO: \"Siluro Piccolo\"\n  STR_LARGE_TORPEDO: \"Siluro Grande\"\n  STR_PHOSPHOROUS_TORPEDO: \"Siluro al Fosforo\"\n  STR_MAGNA_BLAST_GRENADE: \"Granata Esplosiva\"\n  STR_DYE_GRENADE: \"Granata a Tinta\"\n  STR_PARTICLE_DISTURBANCE_GRENADE: \"Granata Interferenze Particellari\"\n  STR_MAGNA_PACK_EXPLOSIVE: \"Pacco Esplosivo\"\n  STR_PARTICLE_DISTURBANCE_SENSOR: \"Sensore Interferenze Particellari\"\n  STR_MEDI_KIT: \"Kit Medico\"\n  STR_MC_DISRUPTOR: \"Perturbatore C.M.\"\n  STR_THERMAL_TAZER: \"Tazer Termico\"\n  STR_GAUSS_PISTOL: \"Pistola Gauss\"\n  STR_GAUSS_PISTOL_CLIP: \"Caricatore Pistola Gauss\"\n  STR_GAUSS_RIFLE: \"Fucile Gauss\"\n  STR_GAUSS_RIFLE_CLIP: \"Caricatore Fucile Gauss\"\n  STR_HEAVY_GAUSS: \"Gauss Pesante\"\n  STR_HEAVY_GAUSS_CLIP: \"Caricatore Gauss Pesante\"\n  STR_SONIC_CANNON: \"Cannone Sonico\"\n  STR_CANNON_POWER_CLIP: \"Caricatore Energia Cannone\"\n  STR_SONIC_BLASTA_RIFLE: \"Fucile Blasta-Sonico\"\n  STR_BLASTA_POWER_CLIP: \"Caricatore Energia Fucile Blasta\"\n  STR_SONIC_PISTOL: \"Pistola Sonica\"\n  STR_PISTOL_POWER_CLIP: \"Caricatore Energia Pistola\"\n  STR_DISRUPTOR_PULSE_LAUNCHER: \"Lanciamissili a Impulso Disgregante\"\n  STR_DISRUPTOR_AMMO: \"Munizioni Disgreganti\"\n  STR_THERMAL_SHOK_LAUNCHER: \"Lanciagranate Shok Termico\"\n  STR_THERMAL_SHOK_BOMB: \"Bomba Shok Termico\"\n  STR_SONIC_PULSER: \"Pulsatore Sonico\"\n  STR_ZRBITE: \"Zrbite\"\n  STR_MC_READER: \"Lettore C.M.\"\n  STR_VIBRO_BLADE: \"Vibro-Lama\"\n  STR_THERMIC_LANCE: \"Lancia Termica\"\n  STR_HEAVY_THERMIC_LANCE: \"Lancia Termica Pesante\"\n  STR_AQUATOID_CORPSE: \"Cadavere Aquatoide\"\n  STR_GILLMAN_CORPSE: \"Cadavere Gillman\"\n  STR_LOBSTERMAN_CORPSE: \"Cadavere di Uomo-Aragosta\"\n  STR_TASOTH_CORPSE: \"Cadavere Tasoth\"\n  STR_CALCINITE_CORPSE: \"Cadavere Calcinite\"\n  STR_DEEP_ONE_CORPSE: \"Cadavere di Essere Abissale\"\n  STR_BIODRONE_CORPSE: \"Cadavere Bio-Drone\"\n  STR_TENTACULAT_CORPSE: \"Cadavere Tentacolato\"\n  STR_TRISCENE_CORPSE: \"Cadavere Triscene\"\n  STR_HALLUCINOID_CORPSE: \"Cadavere Allucinoide\"\n  STR_XARQUID_CORPSE: \"Cadavere Xarquide\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"Non ci sono abbastanza munizioni per armare il SAS{SMALLLINE}Ogni SAS richiede {0} {1}.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Attrezzatura mancante per riequipaggiare squadra\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Dovrai ricercare un{NEWLINE}{0}{NEWLINE}per poter produrre{NEWLINE}{1}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"Gli Alieni hanno distrutto la base {0} lasciata senza difese\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"Le pattuglie X-Com hanno individuato una colonia Aliena in {0}\"\n  STR_STANDOFF: \"DISTANZA DI SICUREZZA\"\n  STR_CAUTIOUS_ATTACK: \"ATTACCO CAUTO\"\n  STR_STANDARD_ATTACK: \"ATTACCO STANDARD\"\n  STR_AGGRESSIVE_ATTACK: \"ATTACCO AGGRESSIVO\"\n  STR_DISENGAGING: \"RITIRATA\"\n  STR_UFO_HIT: \"SOTTOM. ALIENO COLPITO!\"\n  STR_UFO_CRASH_LANDS: \"SOTTOM. ALIENO ABBATTUTO!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Minimizza solo a Dist. di Sicurezza\"\n  STR_UFO_RETURN_FIRE: \"GLI ALIENI RISPONDONO AL FUOCO!\"\n  STR_INTERCEPTOR_DAMAGED: \">>> SCAFO X-COM DANNEGGIATO <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> SCAFO X-COM DISTRUTTO <<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"SOTTOM. ALIENO IN FUGA!\"\n  STR_LONG_RANGE_DETECTION: \"Sonar ad Ampio Raggio\"\n  STR_STORES_UC: \"MAGAZZINI\"\n  STR_DIFFICULTY_LEVEL: \"Livello di Difficoltà\"\n  STR_INTERCEPT: \"INTERCETTA\"\n  STR_BASES: \"BASI\"\n  STR_GRAPHS: \"GRAFICI\"\n  STR_UFOPAEDIA_UC: \"UFOPEDIA\"\n  STR_OPTIONS_UC: \"OPZIONI\"\n  STR_FUNDING_UC: \"FINANZIAMENTI\"\n  STR_5_SECONDS: \"5 Sec\"\n  STR_1_MINUTE: \"1 Min\"\n  STR_5_MINUTES: \"5 Min\"\n  STR_30_MINUTES: \"30 Min\"\n  STR_1_HOUR: \"1 Ora\"\n  STR_1_DAY: \"1 Giorno\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"Lista Prestazioni X-Com\"\n  STR_ENTER_NAME: \"Inserisci il nome\"\n  STR_PERFORMANCE_RATING: \"Valutazione Prestazioni\"\n  STR_VICTORY_DATE: \"Data della Vittoria\"\n  STR_CHEMICAL_FLARE: \"Bengala Chimico\"\n  STR_CHEMICAL_FLARE_UFOPEDIA: \"Questo dispositivo compatto produce un bagliore luminoso sia nell'acqua a qualsiasi profondità che sulla terraferma. Questo illumina le unità nemiche nei pressi del bengala durante le missioni nelle profondità marine o in quelle notturne.\"\n  STR_MONTHLY_COSTS: \"Costi Mensili\"\n  STR_CRAFT_RENTAL: \"Noleggio Sottomarini Volanti\"\n  STR_SALARIES: \"Stipendi\"\n  STR_BASE_MAINTENANCE: \"Mantenimento Base\"\n  STR_COST_PER_UNIT: \"Costo per unità\"\n  STR_QUANTITY: \"Quantità\"\n  STR_TOTAL: \"Totale\"\n  STR_IN_PSIONIC_TRAINING: \"In Procedura Impianto C.M.\"\n  STR_FRONT_ARMOR: \"Armatura Anteriore\"\n  STR_LEFT_ARMOR: \"Armatura Sinistra\"\n  STR_RIGHT_ARMOR: \"Armatura Destra\"\n  STR_REAR_ARMOR: \"Armatura Posteriore\"\n  STR_UNDER_ARMOR: \"Armatura Inferiore\"\n  STR_ROUNDS: \"COLPI\"\n  STR_UNIT: \"UNITÀ> {0}\"\n  STR_ENERGY: \"ENERGIA\"\n  STR_MORALE: \"MORALE\"\n  STR_ARMOR_: \"ARMATURA> {0}\"\n  STR_FRONT_ARMOR_UC: \"ARMATURA ANTERIORE\"\n  STR_LEFT_ARMOR_UC: \"ARMATURA SINISTRA\"\n  STR_RIGHT_ARMOR_UC: \"ARMATURA DESTRA\"\n  STR_REAR_ARMOR_UC: \"ARMATURA POSTERIORE\"\n  STR_SKILLS: \"ABILITÀ> {0}\"\n  STR_LEVEL: \"LIVELLO> {0}\"\n  STR_HEAD: \"TESTA\"\n  STR_TORSO: \"TORSO\"\n  STR_RIGHT_ARM: \"BRACCIO DX\"\n  STR_LEFT_ARM: \"BRACCIO SX\"\n  STR_RIGHT_LEG: \"GAMBA DX\"\n  STR_LEFT_LEG: \"GAMBA SX\"\n  STR_PAIN_KILLER: \"ANTIDOLORIFICO\"\n  STR_STIMULANT: \"STIMOLANTE\"\n  STR_HEAL: \"CURA\"\n  STR_TIME_UNITS_SHORT: \"UdT>{ALT}{0}\"\n  STR_WEIGHT: \"Peso>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"Rea>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"ACM>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"FCC>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Artefatto Alieno\"\n  STR_AMMO_ROUNDS_LEFT: \"MUNIZIONI:{NEWLINE}COLPI{NEWLINE}RIMASTI={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Antidol>{ALT}{0}{ALT}{NEWLINE}Stimolanti>{ALT}{1}{ALT}{NEWLINE}Cura>{ALT}{2}\"\n  STR_THROW: \"Lancia\"\n  STR_AUTO_SHOT: \"Colpo Auto\"\n  STR_SNAP_SHOT: \"Colpo Rapido\"\n  STR_AIMED_SHOT: \"Colpo Mirato\"\n  STR_STUN: \"Stordisci\"\n  STR_PRIME_GRENADE: \"Innesca Granata\"\n  STR_USE_SCANNER: \"Usa Sensore Interf.\"\n  STR_USE_MEDI_KIT: \"Usa Kit Medico\"\n  STR_LAUNCH_MISSILE: \"Lancia Siluro\"\n  STR_ACCURACY_SHORT: \"Prec>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Unità di Tempo insufficienti!\"\n  STR_NOT_ENOUGH_ENERGY: \"Energia Insufficiente!\"\n  STR_NO_ROUNDS_LEFT: \"Munizioni nell'arma esaurite!\"\n  STR_NO_AMMUNITION_LOADED: \"Munizioni non caricate!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Munizioni non adatte a questa Arma!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"Arma già carica!\"\n  STR_NO_LINE_OF_FIRE: \"Non c'è Linea di Fuoco!\"\n  STR_GRENADE_IS_ACTIVATED: \"Granata Attivata!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Granata Disattivata!\"\n  STR_THERE_IS_NO_ONE_THERE: \"Qui non c'è nessuno!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Incapace di usare l'artefatto alieno prima di averlo ricercato!\"\n  STR_OUT_OF_RANGE: \"Fuori Portata!\"\n  STR_UNABLE_TO_THROW_HERE: \"Non è possibile lanciare qui!\"\n  STR_SET_TIMER: \"Regola il Timer\"\n  STR_HIDDEN_MOVEMENT: \"MOVIMENTO NASCOSTO\"\n  STR_TURN: \"TURNO> {0}\"\n  STR_SIDE: \"FAZIONE> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Premi un tasto per continuare\"\n  STR_MIND_CONTROL: \"Controllo Molecolare\"\n  STR_PANIC_UNIT: \"Disturba Impianto\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Attacco al Morale riuscito\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Controllo dell'Impianto riuscito\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}è Impazzito\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}è Impazzita\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}è in preda al panico\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}è in preda al panico\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Alieni\"\n  STR_RIGHT_HAND: \"MANO DX\"\n  STR_LEFT_HAND: \"MANO SX\"\n  STR_RIGHT_SHOULDER: \"SPALLA DX\"\n  STR_LEFT_SHOULDER: \"SPALLA SX\"\n  STR_BACK_PACK: \"ZAINO\"\n  STR_BELT: \"CINTURA\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}è sotto Controllo Molecolare\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}è sotto Controllo Molecolare\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}ha perso i sensi\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}ha perso i sensi\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}è deceduto a causa di una ferita mortale\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}è deceduta per una ferita mortale\"\n  STR_USE_MIND_PROBE: \"Usa Lettore C.M.\"\n  STR_FATAL_WOUNDS: \"FERITE MORTALI\"\n  STR_UNDER_ARMOR_UC: \"ARMATURA INFERIORE\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Unità di Tempo riservate per Colpo Immediato\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Unità di Tempo riservate per Colpo Automatico\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Unità di Tempo riservate per Colpo Mirato\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Unità di Tempo riservate per Inginocchiarsi\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"UdT riservate per Inginocchiarsi e Sparare\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} Unità nello Scafo X-Com\"\n    many: \"{N} Unità nello Scafo X-Com\"\n    other: \"{N} Unità nello Scafo X-Com\"\n  STR_UNITS_OUTSIDE:\n    one: \"{N} Unità rimasta fuori\"\n    many: \"{N} Unità rimaste fuori\"\n    other: \"{N} Unità rimaste fuori\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} Unità sull'Entrata\"\n    many: \"{N} Unità sull'Entrata\"\n    other: \"{N} Unità sull'Entrata\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} Unità sull'Obiettivo d'Uscita\"\n    many: \"{N} Unità sull'Obiettivo d'Uscita\"\n    other: \"{N} Unità sull'Obiettivo d'Uscita\"\n  STR_ABORT_MISSION_QUESTION: \"Annullare la missione?\"\n  STR_CORPSE: \"Cadavere\"\n  STR_UNLOAD_CRAFT: \"Scarica\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}è stato ucciso\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}è stato uccisa\"\n  STR_HIT_MELEE: \"Colpisci\"\n  STR_GROUND: \"A TERRA\"\n  STR_LIVING_QUARTERS_PLURAL: \"Alloggi\"\n  STR_LIST_ITEM: \"OGGETTO\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"Tutti gli Alieni sono deceduti nello schianto,{NEWLINE}Avviata procedura di auto recupero\"\n  STR_RESET: \"Reimposta\"\n  STR_MEMORIAL: \"Memoriale\"\n  STR_DATE_UC: \"DATA\"\n  STR_SOLDIERS_RECRUITED_UC: \"ACQUANAUTI RECLUTATI>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"ACQUANAUTI PERDUTI>{ALT}{0}\"\n  STR_REMOVE_SELECTED: \"Rimuovi Selezionati\"\n  STR_LIVE_ALIENS: \"Esemplari{NEWLINE}Vivi\"\n  STR_DEAD_ALIENS: \"Esemplari{NEWLINE}Scartati\"\n  STR_UNDER_INTERROGATION: \"Sotto{NEWLINE}Esamine\"\n  STR_CONTAINMENT_EXCEEDED: \"LIMITE CONTENIMENTO ALIENI SUPERATO!{SMALLLINE}Spazio di contenimento insufficente nella base {0}. Devi rimuovere gli alieni in eccesso dal contenimento (questo provocherà la loro morte).\"\n  STR_MANAGE_CONTAINMENT: \"Gestisci Contenimento Alieni\"\n  STR_STORAGE_EXCEEDED: \"SPAZIO DEI MAGAZZINI SUPERATO!{SMALLLINE}Spazio nei magazzini insufficente nella base {0}. Devi vendere gli oggetti in eccesso.\"\n  STR_GO_TO_BASE: \"Vai alla Base\"\n  STR_MELEE_ACCURACY: \"MELEE\"\n  STR_SELL_PRODUCTION: \"VENDI\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Entrambe le mani devono essere libere!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Oggetti insufficienti per copiare il modello!\"\n  STR_UNLOAD_WEAPON: \"Scarica l'arma\"\n  STR_ALL_ITEMS: \"Tutti gli Oggetti\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"NON È POSSIBILE AGGIUNGERE ALTRO EQUIPAGGIAMENTO A BORDO!{SMALLLINE}È possibile portare un massimo di {N} oggetto di equipaggiamento su questo sottomarino.\"\n    many: \"NON È POSSIBILE AGGIUNGERE ALTRA ATTREZZATURA A BORDO!{SMALLLINE}Ti è permesso di portare solo un massimo di {N} oggetti di equipaggiamento su questo sottomarino.\"\n    other: \"NON È POSSIBILE AGGIUNGERE ALTRA ATTREZZATURA A BORDO!{SMALLLINE}Ti è permesso di portare solo un massimo di {N} oggetti di equipaggiamento su questo sottomarino.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}CENTRO DI CONTROLLO DISTRUTTO{SMALLLINE}Dirigiti all'entrata ed abbandona la missione.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"Le strutture sottomarine di X-Com non possono essere costruite sulla terra ferma\"\n  STR_UNABLE_TO_ENGAGE_DEPTH: \"IMPOSSIBILE INGAGGIARE IL NEMICO{NEWLINE}A QUESTA PROFONDITÀ \"\n  STR_UNABLE_TO_ENGAGE_AIRBORNE: \"IMPOSSIBILE INGAGGIARE IL NEMICO{NEWLINE}MENTRE È IN VOLO\"\n  STR_UNDERWATER_EQUIPMENT: \"Quest'attrezzatura non funziona fuori dall'acqua!\"\n  STR_LAND_EQUIPMENT: \"Quest'attrezzatura non funziona sott'acqua!\"\n  STR_LEVEL_SHORT: \"L{0}\"\n  STR_PERSONNEL: \"Personale\"\n  STR_CRAFT_ARMAMENT: \"Scafi ed Armamenti\"\n  STR_COMPONENTS: \"Componenti\"\n  STR_SOLDIERS_RECRUITED: \"Acquanauti reclutati\"\n  STR_SOLDIERS_LOST: \"Acquanauti perduti\"\n  STR_TOTAL_UFOS: \"Sottomarini volanti individuati\"\n  STR_TOTAL_ALIEN_BASES: \"Colonie aliene scoperte\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"FCM\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"ACM\"\n  FEMALE_CIVILIAN: \"Civile, Femmina\"\n  MALE_CIVILIAN: \"Civile, Maschio\"\n  DOCKER_CIVILIAN: \"Civile, Portuale\"\n  SAILOR_CIVILIAN: \"Civile, Marinaio\"\n  STR_BIODRONE_MELEE_WEAPON: \"Melee Bio-drone\"\n  HALLUCINOID_WEAPON: \"Arma Allucinoide\"\n  STR_LOBSTERMAN_MELEE_WEAPON: \"Melee Uomo-Aragosta\"\n  CALCINITE_WEAPON: \"Arma Calcinite\"\n  DEEP_ONE_WEAPON: \"Arma Essere Abissale\"\n  STR_TRISCENE_MELEE_WEAPON: \"Melee Triscene\"\n  STR_TRIBIO_SONIC_WEAPON: \"Arma Sonica Aliena\"\n  XARQUID_WEAPON: \"Arma Xarquide\"\n  TENTACULAT_WEAPON: \"Arma Tentacolato\"\n  ZOMBIE_WEAPON: \"Arma Zombie\"\n  ALIEN_PSI_WEAPON: \"Arma C.M. Aliena\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/ja.yml",
    "content": "ja:\n  STR_LEVIATHAN_UFOPEDIA: \"輸送と迎撃が可能な超深海用飛空潜水艇。人類とエイリアンの技術の高レベルな融合により、イオン推進装置と磁気センサーによる航行を可能にした。\"\n  STR_BARRACUDA_UFOPEDIA: \"加熱レーザー式エンジン搭載の英国製バラクーダ級潜水艇。世界最速の空水両用機として、来たるべき戦いで活躍が期待される\"\n  STR_HAMMERHEAD_UFOPEDIA: \"輸送と迎撃が可能な機体。X-COMの機体に搭載された磁気センサーの複製品は、小型ながらも我々の技術の粋を結集させたものである\"\n  STR_TRITON_UFOPEDIA: \"トリトンと名付けられたこの輸送強襲艇は、空水両対応のエンジンと大容量且つ堅牢な機体で兵員輸送の要となる\"\n  STR_MANTA_UFOPEDIA: \"エイ型の快速艇。一人乗りの空水両用迎撃機で、エイリアンのイオン推進機に迫る性能を持つ。激しさを増しつつある戦闘で戦果を上げるだろう\"\n  STR_AJAX_UFOPEDIA: \"AJAX魚雷は水中戦で主力となる兵器である。高い命中精度と抑止力を併せ持つ\"\n  STR_DUP_HEAD_UFOPEDIA: \"劣化ウラン弾頭を用いた兵器は比較的新しいが、この水中兵器は世界で初めて商品化され、実戦配備された\"\n  STR_CRAFT_GAS_CANNON_UFOPEDIA: \"圧縮ガスを用いて徹甲ボルトを発射する、高い貫通力を持つキャノン砲\"\n  STR_PWT_CANNON_UFOPEDIA: \"パルス波魚雷は超加熱式燃料システムと圧縮弾頭によってほぼ全ての装甲を貫くことができる\"\n  STR_GAUSS_CANNON_UFOPEDIA: \"電磁兵器はX-COMで新しく開発されたもので、粒子加速器の動力は液体窒素冷却による小型の核融合炉から供給される\"\n  STR_SONIC_OSCILLATOR_UFOPEDIA: \"強力な振動波発振器による音波は、対象を分子レベルで崩壊させる\"\n  STR_AQUATOID_UFOPEDIA: \"アクアトイドは古代社会において人類が最初の一歩を踏み始める数千年前から存在した。小柄で四肢の細い特徴は宇宙へと向かった親戚のセクトイドにも受け継がれている。{NEWLINE}彼らは分子構造を操作する高度なテクノロジーに支えられていたが、不妊を解消する為に遺伝子操作を用い、理想的な被検体として人類を選んだ。その結果多くの混血種を生み出した。\"\n  STR_AQUATOID_AUTOPSY: \"アクアトイドの解剖\"\n  STR_AQUATOID_AUTOPSY_UFOPEDIA: \"この生物の精密な分析の結果、アクアトイドは我々のかつての敵、セクトイドに外科手術とインプラントを施して水棲種に改造したものではないかという仮説が立てられた。{NEWLINE}退化した肺は呼吸を許すが、短期間しか地上で活動できない。全身をサイボーグ化することで、四肢と臓器を強化している。{NEWLINE}全ての個体は同一で、クローン技術によって生み出されたものだと思われる。\"\n  STR_GILLMAN_UFOPEDIA: \"この種族は殆ど人類と変わらず、ハチュウ類型の人間に見える位我々に似ている。水中では非常に強靱で素早く動ける。{NEWLINE}ギルマンは他の多くの水棲種と違って遺伝子操作や外科手術の痕跡が見当たらず、男女の性差と加齢の特徴がある独自の種族である。古代に枝分かれした人類の遠い親戚かもしれない\"\n  STR_GILLMAN_AUTOPSY: \"ギルマンの解剖\"\n  STR_GILLMAN_AUTOPSY_UFOPEDIA: \"解剖によって明らかになったが、この種族はエイリアンではなく地球由来の生物であり、古代の有史以前、ほ乳類が地上を支配した頃に絶滅した種族である。{NEWLINE}恐竜が闊歩していた時代、ギルマンは両生で知的であり、隆盛を誇った。恐竜を絶滅に導いた大災害が彼らとエイリアンを深く結びつけたようだ。彼らの頭蓋には小さな電子装置が埋め込まれている\"\n  STR_LOBSTERMAN_UFOPEDIA: \"これは驚くべき生物である。人間より大きく手足は6本あり、海の悪魔としか言いようのない姿をしている。地球のロブスターに似ている事からX-COMの隊員によってロブスターマンと名付けられた。この深海の醜い巨獣は非常に巧みな構造をした戦闘生物で、強大な筋力を持ち火器に対してほぼ無敵である。そのハサミは鋼鉄をも押しつぶす\"\n  STR_LOBSTERMAN_AUTOPSY: \"ロブスターマンの解剖\"\n  STR_LOBSTERMAN_AUTOPSY_UFOPEDIA: \"この生物の非常に固い外殻の下には驚くべき体構造が隠されている。強靱な筋肉がチタンの骨格を取り巻き、複数の知覚器官らなる感受システムは脳に直結している。複数の眼球は鋼鉄よりも固い樹脂で守られ、効果的に戦闘に投入されれば手の付けようのない相手となる。{NEWLINE}体の奥深くには正体不明の機能と構造をもつ装置が埋め込まれている\"\n  STR_TASOTH_UFOPEDIA: \"この俊敏な敵はエイリアン部隊の主戦力である。エイリアンの居住区では一度に何百もの個体が養育槽で育てられる。タソスは純粋なエイリアンであり、その行動パターンと共食いの習性は地球上のいかなる生物にも見受けられない。{NEWLINE}戦闘では先鋒を勤める事が多く、絶望的な状況でも怯む事がない。\"\n  STR_TASOTH_AUTOPSY: \"タソスの解剖\"\n  STR_TASOTH_AUTOPSY_UFOPEDIA: \"解剖によってサイボーグ化された器官は変わった動力を持っている事が判明した。体腔には小さな動力源があるのみで、他に確認できる器官はない。動力は生体伝導によって全身に行き渡る。骨格や体を支える為の部位がなく、死後動力源が停止すると粘液質の肉と体液で満たされた着ぐるみ状態になる。{NEWLINE}他に唯一確認できたのは対になったセラミック製の電池で、蘇生を試みる短い間だけ機能する様だ\"\n  STR_DEEP_ONE_UFOPEDIA: \"深きものは異種交配と精神歪曲よって生まれた生物学上の悪夢である。我々は何種類ものタイプと遭遇したが、詳細な調査の結果、彼らはエイリアンによって造られたという結論に達した。人類を捕獲する事でその数は増え続ける。{NEWLINE}彼らは潜水兵を殺傷するのに十分な威力をもつ放電器を装備している\"\n  STR_DEEP_ONE_AUTOPSY: \"深きものの解剖\"\n  STR_DEEP_ONE_AUTOPSY_UFOPEDIA: \"人間にエイリアンの臓器移植を施した生物である。脳は人間のものだが大脳皮質はエイリアンのものに置き換えられ、電子装置の制御に適応する様に改造されている。人間の肉体としての痕跡は眼球のみである。移植されたエイリアンの芽胞は宿主を成長の過程で消化吸収するようだ。皮膚は生体ではなく強靱でしなやかな網状の金属製である。臓器移植の結果、強く、素早くなった彼らは完全にエイリアンの支配下にある\"\n  STR_BIODRONE_UFOPEDIA: \"バイオドローンはエイリアンしか思いつかない様な代物だ。動力源に接続された羊水の中に(人間もしくはエイリアンの) 脳が浮かんでおり、陸上あるいは水中を浮遊可能である。強力な音波撹乱器を備える機械化生物であり、科学者の中にはこの兵器は声帯を利用したものだと主張する者も居る。この鋭くしつこい超番犬はエイリアンの資産を守る為に広く用いられる\"\n  STR_BIODRONE_AUTOPSY: \"バイオドローンの解剖\"\n  STR_BIODRONE_AUTOPSY_UFOPEDIA: \"音波撹乱器が生体装置だという仮説は正しかった。この不運な被害者は文字通り標的が死に至るまで叫び続ける。全ての検体には外科手術による酷い外傷と変容が見受けられる。エイリアンは脳を服従させる為に切り刻んだようだ。{NEWLINE}大脳皮質はエイリアンの物が使われているが、元が人間だと思うとこれ程恐ろしい物はない。バイオドローンはイオンエンジンを動力とし、遠隔制御が組み込まれている\"\n  STR_TENTACULAT_UFOPEDIA: \"ラブクラフトの悪夢の様な深淵でさえ、この様な名状しがたい存在は生み出さなかった。地球上のいかなる生物とも異なる’それ’を生み出す環境とは一体何なのか。長い触手は獲物を捕らえると麻痺させ、自我のない抜け殻へと変えてしまう。{NEWLINE}こうして'子'となった者に触れられると例え防護服を着ていても死に至る。{NEWLINE}テンタクラットはX-COMが遭遇した中で最も怖ろしいエイリアンである\"\n  STR_TENTACULAT_AUTOPSY: \"テンタクラットの解剖\"\n  STR_TENTACULAT_AUTOPSY_UFOPEDIA: \"解剖によってこの生物の大脳に埋め込まれた小型のインプラントを発見した。視覚は可視光線と熱像感知の複合によるものであり、漆黒の深海においてもこの怪物は位置を的確に把握する。{NEWLINE}確認できた器官は生存に必要最低限のものであり、それぞれの個体は小さな胃を持つが外部コネクターが付いており、上位の存在から直接栄養補給を受けていると推測できる\"\n  STR_CALCINITE_UFOPEDIA: \"遭難したダイバーの潜水服の様なこのエイリアンは、海底から不注意なダイバーに忍び寄る。その鉄よりも固い爪による痛烈な一撃は熟練ダイバーさえも海の底へと沈める。{NEWLINE}フェイスマスクからはゼリー状の物体が蠢く様が見えるが、彼らとの遭遇は死を意味し、未だ正体を見た者は居ない\"\n  STR_CALCINITE_AUTOPSY: \"カルシナイトの解剖\"\n  STR_CALCINITE_AUTOPSY_UFOPEDIA: \"カルシナイトの装甲スーツを取り除くと不定形の原形質の大きな塊がある。脳や四肢、感覚器官は見当たらないが、小さな金属製の装置が液体状の体の中にある。{NEWLINE}死後の状態ではこの生物の実態は推測によるしかなく、不可解な謎を秘めている。\"\n  STR_TRISCENE_UFOPEDIA: \"この二足歩行のハチュウ類は恐竜時代の面影を残している。水中と陸上で生存可能な様に進化しており、これは白亜紀の恐竜の典型的な特徴である。武器ポッドからの射撃と金属製の歯を持つ顎で攻撃をする。{NEWLINE}彼らはエイリアンの陸上強襲部隊の主力となる事が多いが、その重量級の体躯と強力な武装はタソスの指揮官の下で最大の効果を発揮する\"\n  STR_TRISCENE_AUTOPSY: \"トリシーンの解剖\"\n  STR_TRISCENE_AUTOPSY_UFOPEDIA: \"トリシーンは科学者の解剖によってサイボーグ化と武器システムが付与された古代種である事が判明した。小さな脳には小型のコンピュータが取付けられ、全身に張り巡らされた配線を通じてコントロールしている。持ち前の固い皮膚と狩猟本能は武器によって強化され、あらゆる環境下で脅威となるだろう。\"\n  STR_HALLUCINOID_UFOPEDIA: \"エイリアン達は海洋を培養槽にしてこの巨大な海洋生物を兵器へと改造した。この深海の水夫の無害そうな外観に惑わされてはいけない。接近すると凍結攻撃を仕掛けてくる。ハルシノイドは油断できない敵である。\"\n  STR_HALLUCINOID_AUTOPSY: \"ハルシノイドの解剖\"\n  STR_HALLUCINOID_AUTOPSY_UFOPEDIA: \"何層ものゼラチン状の組織からなる体の中に化学反応を利用した冷却器官があり、主に攻撃時に機能する。柔らかくしなやかなハルシノイドの皮膚は熱攻撃に対して耐性を持っている様だ。この生物は主人であるアクアトイドと共によく見られる。\"\n  STR_XARQUID_UFOPEDIA: \"これも地球上の生物を改造したものである。ザーカッドは非常に美しく、そして危険な生き物だ。素早く泳ぎまわる巨大な体躯の下には墨とイオン化粒子を発射する強力な武器が隠されている。{NEWLINE}まだこの強大な敵とは遭遇したばかりなので、その能力と指揮官である執念深いギルマンに油断してはならない\"\n  STR_XARQUID_AUTOPSY: \"ザーカッドの解剖\"\n  STR_XARQUID_AUTOPSY_UFOPEDIA: \"この発育過剰のオウム貝はエイリアンの薬物と特殊な外科手術によって造られた。恣意的な目的の為にギルマンによって制御装置を埋め込まれ、本来持つ性質は完全に失われている。{NEWLINE}固い外殻と運動能力、そして生来持つ武器によってザーカッドは侮れない敵である。\"\n  STR_ION_BEAM_ACCELERATORS_UFOPEDIA: \"エイリアンの飛行潜水艇は複雑な動力系のお陰で信じられない位高速で深海まで潜行する。技術的にはイオン変換がその核となり、ザーバイトを媒体としてエンジンは秒間あたり何百倍もの質量変換を水中で行う。その過程で生じる莫大なエネルギーによって我々の持ついかなる潜水艦をも凌ぐ速度で運航する。{NEWLINE}アクアプラスチックを用いた船体とザーバイト動力炉があればこの潜水艇の複製は可能である。\"\n  STR_MAGNETIC_NAVIGATION_UFOPEDIA: \"この装置は球形の多層型磁力フィールドを発生するが、積層化することでそのフィールドは潜水艇を中心に直径1000mまで広がる。エイリアンの潜水艇はこの装置に直結しており、海中の視界が利かない世界を苦も無く進む。{NEWLINE}航行装置のインターフェースは神経節を経てエイリアンの改造された大脳皮質へ直結している。\"\n  STR_ALIEN_SUB_CONSTRUCTION_UFOPEDIA: \"それぞれの船体はカメレオンの様な擬態構造を持っていて、海洋生物に巧みに似せたアクアプラスチック製である。潜水艇は乗組員と一体化することで機能する。{NEWLINE}これらの殆どの技術は複製可能で、彼らのテクノロジーを取り入れる事で我々は次なる技術レベルに達するだろう。\"\n  STR_ALIEN_CRYOGENICS_UFOPEDIA: \"地球上に隠された数限りないエイリアンは普段は冷凍睡眠状態で保存されている。全ての個体は装置に密閉され、体機能が殆ど停止する体温まで下げられる。{NEWLINE}驚くべきことに、これまでの調査によってこれらの個体は6千万年もの間保存されていた事が判明した。\"\n  STR_ALIEN_CLONING_UFOPEDIA: \"多くの捕獲されたエイリアンはDNAレベルまで掘り下げても同一体であり、あらゆる部位において複製体である。細胞サンプルは冷凍保存されたエイリアンのDNAバンクから引き出されたものだろう。{NEWLINE}いくつかの個体に人体もしくはその部位が用いられており、人類とエイリアンの複合種を造ろうとした形跡がある。\"\n  STR_ALIEN_LEARNING_ARRAYS_UFOPEDIA: \"これらの装置はエイリアンの頭蓋に埋め込まれた分子制御のインプラントを介して直接脳へその情報を伝達する。新たなクローン体はこの装置を通じて種族全体の記憶と全ての科学的もしくは戦闘に関する情報を空白の脳にダウンロードする。\"\n  STR_ALIEN_IMPLANTER_UFOPEDIA: \"この装置はエイリアンを分子制御用インプラントに適応させる時、繁殖や生物に対し電子あるいは生体パーツを組み込んだり取り除く時に用いられる。{NEWLINE}こうした処置は患者の意識がある状態で行われるが、不幸な事に人類の体はこの装置に適合している。\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"ついにエイリアンによる人間捕獲の理由が判明し、証拠も入手した。人間の捕獲の理由は食料としてでもなく、受胎させる為の母体としてでもない。むしろ生体資源として支配体系を維持する用途に用いられる。{NEWLINE}エイリアンのテクノロジーは共有意識の元に成り立っているが、共通普遍の知性の'器'として人類の脳が最適だからである。{NEWLINE}人間の脳の繊維は殆どのエイリアンの生体コンピューターの保存、読み出しシステムに用いられており、残りが繁殖および外科的処置に流用される。\"\n  STR_AQUA_PLASTICS_UFOPEDIA: \"エイリアンの潜水艇と建物は驚異的な強靱さ、しなやかさ、そして耐久力を持つ素材を用いている。アクアプラスチックは塑型用途に、ザーバイトは触媒としてである。{NEWLINE}高密度で軽量なアクアプラスチックはチタンやケブラーよりも強靱である\"\n  STR_ZRBITE_UFOPEDIA: \"このエイリアン由来の合金は黄金と生体物質から造られる。動力源として用いられる場合、10倍以上のサイズの原子炉より多くのエネルギーを少量で発生させる。{NEWLINE}この物質の成分の殆どがエイリアン由来のものである為、複製は不可能である\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"エイリアンの襲撃は非情なまでの正確さで地球上のあらゆる場所で発生している。彼らの本拠地は未だ不明だが、大洋のどこか我々の目の届かない深みにあるのだろうか?　遭遇した生物も全てがエイリアンではなく、中には古代種や絶滅した筈の種族も混じっていた。{NEWLINE}{NEWLINE}我々は数百万年の時を経た脅威と相対している事になるが、これは人類とエイリアンの関係そのものでもある。{NEWLINE}{NEWLINE}海洋の奥深くに宇宙の同胞と交信可能なエイリアンの遺跡があり、12あるそれら全ての遺跡には同一の、そして強固なエイリアンの施設が存在する。{NEWLINE}{NEWLINE}エイリアン軍の進撃が始まった今、これらの遺跡は再び目覚め、粒子制御網を通じて勢力を拡大していくだろう。我々は何としてもこれらの遺跡を破壊しなければならない。\"\n  STR_THE_ULTIMATE_THREAT_UFOPEDIA: \"6500万年前、巨大な植民船が遙か彼方のエイリアンの世界からやってきた。その巨大な船体がまだ幼い地球に接近した時、超大型の太陽フレアが発生し、航行システムが故障した。制御を失い墜落する巨大な船体は成層圏を突き破り、白亜紀の空に姿を現わした。{NEWLINE}地球上の数限りない生物達が緊迫した面持ちで空を見上げる中、'災厄'は遂に地表に達した。広大な範囲で粉塵が巻き起こり、大気に充満して太陽光を遮った。地表が冷えていくと支配者であった恐竜達は死に絶えた。しかし4000億トンのテ・レスは墜落の衝撃では破壊されず、高度に洗練されたスーパーコンピューターが中に居た者達に冷凍睡眠を開始させた。{NEWLINE}年月が経ちコンピュータが幾人かのエイリアンを目覚めさせると宇宙の同胞へ向けて通信を開始したが、動力源の中枢が停止していた為、全ては無駄な試みに終わった。\"\n  STR_TLETH_THE_ALIEN_CITY: \"エイリアン都市　'テ・レス'\"\n  STR_TLETH_THE_ALIEN_CITY_UFOPEDIA: \"テ・レスはメキシコ湾の奥深くにあるシグスビー海丘に埋もれたエイリアンの巨大な移民船である。都市の中枢は死よりも怖ろしいエイリアンの邪悪さとパワーに充ちている。エイリアン合金でできた玄室の中で野望を抱く究極のエイリアンが眠っていた。{NEWLINE}{NEWLINE}テ・レスが浮上すると彼の活性化が始まる。完全に目覚めたら何者も彼を止められないだろう。半死半生にも関わらず彼の精神はエイリアン軍を指揮していた。エイリアンの不可思議な粒子制御テクノロジーのお陰で個と全、全と個は繋がり、一つの意識になっているからだった。遺伝操作で改造されたエイリアンもしくは人間の胎児はエイリアンの精神構造と精神エネルギーを提供し、支配機構にリンクする。{NEWLINE}{NEWLINE}究極のエイリアンに関する神話は何世紀もの間受け継がれてきたが、真実は常に海に隠されてきた。\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"現場を中央に表示 - 時間=5秒\"\n  STR_CANCEL_UC: \"取消\"\n  STR_NONE: \"なし\"\n  STR_UNKNOWN: \"0%\"\n  STR_POOR: \"25%\"\n  STR_AVERAGE: \"50%\"\n  STR_GOOD: \"75%\"\n  STR_EXCELLENT: \"95%\"\n  STR_BUILD_NEW_BASE_UC: \"新基地を建設する\"\n  STR_BASE_INFORMATION: \"基地情報\"\n  STR_EQUIP_CRAFT: \"潜水艇の武装\"\n  STR_BUILD_FACILITIES: \"施設を建設する\"\n  STR_RESEARCH: \"研究する\"\n  STR_MANUFACTURE: \"製造する\"\n  STR_TRANSFER_UC: \"移動する\"\n  STR_PURCHASE_RECRUIT: \"購入する/雇う\"\n  STR_SACK: \"解雇する\"\n  STR_SELL_SACK_UC: \"売る/解雇する\"\n  STR_GEOSCAPE_UC: \"ジオスケープ\"\n  STR_NAME: \"名前\"\n  STR_AREA: \"エリア\"\n  STR_BUILD_NEW_BASE: \"新基地を建設する\"\n  STR_CANCEL: \"取消\"\n  STR_COST_UC: \"建設費用>\"\n  STR_CONSTRUCTION_TIME_UC: \"建設期間>\"\n  STR_DAY:\n    other: \"{N} 日\"\n  STR_HOUR:\n    other: \"{N} 時間\"\n  STR_MAINTENANCE_UC: \"維持費>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"軍事施設\"\n  STR_CURRENT_RESEARCH: \"研究プロジェクト\"\n  STR_SCIENTISTS_AVAILABLE: \"配属可能な科学者>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"配属済み科学者>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"研究室内の空きスペース>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"研究課題\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"科学者\"\n  STR_PROGRESS: \"経過\"\n  STR_NEW_PROJECT: \"研究課題の選択\"\n  STR_CANCEL_PROJECT: \"プロジェクトを取り消す\"\n  STR_NEW_RESEARCH_PROJECTS: \"研究課題\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"配属可能な科学者>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"実験室内の有効スペース>{ALT}{0}\"\n  STR_INCREASE: \"増加\"\n  STR_DECREASE: \"減少\"\n  STR_START_PROJECT: \"この課題の研究開始\"\n  STR_CURRENT_PRODUCTION: \"現在の生産\"\n  STR_ENGINEERS_AVAILABLE: \"配属可能な技術者>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"配属済み技術者>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"工作室内の有効スペース>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"現在の資金>{ALT}{0}\"\n  STR_ITEM: \"アイテム\"\n  STR_ENGINEERS__ALLOCATED: \"配属済み技術者\"\n  STR_UNITS_PRODUCED: \"生産\"\n  STR_TOTAL_TO_PRODUCE: \"生産数済/総\"\n  STR_COST__PER__UNIT: \"生産単価\"\n  STR_DAYS_HOURS_LEFT: \"残りの日/時\"\n  STR_NEW_PRODUCTION: \"生産物の選択\"\n  STR_PRODUCTION_ITEMS: \"生産アイテム\"\n  STR_CATEGORY: \"カテゴリー\"\n  STR_START_PRODUCTION: \"生産をスタートする\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} 1ユニットの作成に要するエンジニアの工数\"\n  STR_COST_PER_UNIT_: \"ユニットごとの費用>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"必要な作業スペース>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"必要な特殊材料\"\n  STR_ITEM_REQUIRED: \"必要なアイテム\"\n  STR_UNITS_REQUIRED: \"必要なユニット\"\n  STR_UNITS_AVAILABLE: \"使用可能なユニット\"\n  STR_STOP_PRODUCTION: \"生産を中止する\"\n  STR_ENGINEERS_AVAILABLE_UC: \"配属可能な技術者>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"作業場内の有効スペース>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"月間収入 >{ALT}{0}\"\n  STR_INCREASE_UC: \"増加\"\n  STR_DECREASE_UC: \"減少\"\n  STR_UNITS_TO_PRODUCE: \"生産するユニット\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"購入する/雇う\"\n  STR_COST_OF_PURCHASES: \"購入価格>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"ユニットごとの費用\"\n  STR_QUANTITY_UC: \"数量\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"待機:総数\"\n  STR_SOLDIERS: \"潜水兵\"\n  STR_SCIENTISTS: \"科学者\"\n  STR_ENGINEERS: \"技術者\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"使用済みスペース:有効スペース\"\n  STR_LIVING_QUARTERS: \"居住区\"\n  STR_STORES: \"倉　庫\"\n  STR_LABORATORIES: \"研究室\"\n  STR_WORK_SHOPS: \"工作室\"\n  STR_HANGARS: \"ドック\"\n  STR_SHORT_RANGE_DETECTION: \"短距離ソナー\"\n  STR_DEFENSE_STRENGTH: \"防衛力\"\n  STR_TRANSFERS_UC: \"受領\"\n  STR_TRANSFERS: \"移動\"\n  STR_ARRIVAL_TIME_HOURS: \"到着時間(時間)\"\n  STR_COST_: \"費用>{ALT}{0}\"\n  STR_AREA_: \"エリア>{ALT}{0}\"\n  STR_BASE_NAME: \"基地の名前は?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"エア・ロックの位置を選択する\"\n  STR_TRANSFER: \"移動\"\n  STR_AMOUNT_TO_TRANSFER: \"移動 総数\"\n  STR_SELECT_DESTINATION_BASE: \"移動先を選択する\"\n  STR_COST: \"費用\"\n  STR_INTRO_1: \"Copyright 1995 MicroProse\"\n  STR_INTRO_2: \"火星 : サイドニアの終焉\"\n  STR_INTRO_3: \"X-COMはエイリアンの軍事力の中核を叩くことに成功し、意気揚々と地球へ凱旋する。{NEWLINE}しかし、破壊された火星基地には生き残りが居た\"\n  STR_INTRO_4: \"鋭いタキオンビームが瓦礫に覆われたサイドニアの中枢から宙空へと発せられる。{NEWLINE}その目的地は...\"\n  STR_INTRO_5: \"地球だった。\"\n  STR_INTRO_6: \"海の奥深く、永らく不活性だったアンテナにビームが到達すると、休止状態だった巨大コンピューターが動き出し、人類の目の届かない場所にある巨大な玄室で長き眠りから目覚めたエイリアン達が活動を再開し始める\"\n  STR_INTRO_7: \"2040年 ： 平和な地球{NEWLINE}エイリアンとの戦争は過去のものとなっていた。だが、大洋の片隅に隠れてエイリアンの軍勢は準備を終え、人類を打倒し世界を征服しようとしていた。\"\n  STR_INTRO_8: \"エイリアンは人間を襲った。歪んだ実験の為に、貴重なミネラルと資源の為に。{NEWLINE}そして海からの略奪はやがて水上へと舞台を移した\"\n  STR_INTRO_9: \"奇妙な形をした強力な飛行潜水艇が海原を縫っては監視し、探し、そして狩り出す...\"\n  STR_INTRO_10: \"餌食となる者を。\"\n  STR_INTRO_11: \"未知の異形の兵器が無防備な人類に突き付けられる。人類は為す術もなくエイリアンの脅威に晒される事となった。{NEWLINE}事態を解決する事ができる組織はただ一つ。しかし人々はとうの昔にに彼らに背を向けていた...\"\n  STR_INTRO_12: \"X-COMの海底研究基地\"\n  STR_INTRO_13: \"'メーデー! メーデー! こちら大西洋航路定期船ハイペリオン!'  '我々は現在襲撃を受けている! メーデー! メーデ・・・'\"\n  STR_INTRO_14: \"'司令室よりドック１へ。水門開け。'  'バラクーダ01を発進させよ。現在エイリアンが襲撃中。緊急事態発生' '繰り返す、緊急事態発生'\"\n  STR_INTRO_15: \"エイリアンは非情なまでに手際良く...\"\n  STR_INTRO_16: \"襲撃は必ず成功した\"\n  STR_INTRO_17: \"'バラクーダ01より司令部へ'  'ハイペリオンの残骸に接近中'\"\n  STR_INTRO_18: \"'減速開始...'{NEWLINE}'後2メートル...'{NEWLINE}'後1メートル'{NEWLINE}'全ての水兵は直ちに行動を開始せよ'\"\n  STR_INTRO_19: \"'...エアロック解放'  '...残骸に接近中...' {NEWLINE}'なんてこった！'{NEWLINE}'潜水服のカメラに映る様にその生き物を持ち上げてくれないか?'\"\n  STR_GAMEOVER_1: \"プロジェクトは失敗に終わり、エイリアンの手によって最後の希望も絶たれた。{NEWLINE}X-COMは壊滅し、地球は太古からの宿敵の支配下となった。\"\n  STR_GAMEOVER_2: \"テ・レスが轟音と共に成層圏まで浮かび上がると、地表に沿って動き出す。死を撒き散らし、人類の残滓を敷き詰めていく。{NEWLINE}その奥深くでは殺意に満ちたエイリアンの心が目覚めようとしていた。\"\n  STR_GAMEOVER_3: \"全ての国の首都で自暴自棄な計画が立案されたが、悉く失敗に終わった。{NEWLINE}X-COMの研究によってもたらされるテクノロジーを欠いた今、人類の兵器は無力だった\"\n  STR_GAMEOVER_4: \"エイリアンは基地を両極に構えると万年氷を溶かし始め、世界は水没し広大な海となっていく。{NEWLINE}生き残った人々も家畜の様に狩り集められ、エイリアン達のおそろしく邪悪な実験の贄となる。{NEWLINE}空は黒ずみ、地上には恐ろしい疫病が蔓延した\"\n  STR_GAMEOVER_5: \"もはや新しい秩序に抗う術は無い。抵抗を試みようとすれば超越的なエイリアンの兵器によって悲惨な最期が待ち受ける。{NEWLINE}不幸にも生き残った人類にとって、母なる地球はエイリアンの世界となり果て、恐怖が渦巻く地となった。\"\n  STR_OUTRO_1: \"墓は暴かれ、そして踏みにじられた。中央の棺からくぐもった唸り声が響く。'愚か者どもよ、滅ぶがよい.....\"\n  STR_OUTRO_2: \"........逃れる事は能わぬ。'\"\n  STR_OUTRO_3: \"すさまじい爆発が墳墓から起こり、都市を引き裂く。大気は粉塵と煙で満たされ、エイリアンの企みは阻止された....\"\n  STR_OUTRO_4: \"巨大なテ・レスの偉景が崩壊を始める。煌びやかな尖塔と威容を誇る殿堂から炎と煙がもうもうと巻き上がる\"\n  STR_OUTRO_5: \"不落の砦が海へ向かって傾くと、金属がきしむ音とエイリアン達の悲鳴が響き渡る。{NEWLINE}世界の征服を夢見た者は消え去った。\"\n  STR_OUTRO_6: \"耳をつんざく衝撃音を最後にテ・レスは完全に崩壊した。{NEWLINE}エイリアンの脅威は去り、地球は清められた...\"\n  STR_OUTRO_7: \"宇宙の片隅に静かに佇む青い星\"\n  STR_OUTRO_8: \"ほどなくして安全な地となるだろう\"\n  STR_OUTRO_9: \"エイリアンの脅威が去ってから時が経ち\"\n  STR_OUTRO_10: \"巨大な都市部には何十億もの人々がひしめいていた\"\n  STR_OUTRO_11: \"X-COMの活躍とエイリアンとの戦争は既におとぎ話になっていたが\"\n  STR_OUTRO_12: \"伝説はいつも真実から生まれる....\"\n  STR_RISE_1: \"テ・レスはあまたの国の数々の伝説を通じて語られてきた。\"\n  STR_RISE_2: \"地球全体に響き渡る轟音と共にテ・レスが海底から浮上し始める\"\n  STR_RISE_3: \"メキシコ湾を沸き立たせながら、巨大な宮殿が浮かび上がる\"\n  STR_RISE_4: \"4000億トンのエイリアン金属から成る都市の中枢には究極のエイリアンが眠っている。{NEWLINE}今まさに邪悪な宇宙神が6500万年の長き眠りから目覚めようとしていた\"\n  STR_RISE_5: \"海が沸きあがり泡立ちながらどす黒い野望を抱く者の墓を白日の下に晒した....\"\n  STR_RISE_6: \"...その白日もX-COMがエイリアンの軍勢を打倒しなければ失われてしまう。\"\n  STR_YOU_HAVE_FAILED: \"あなたはエイリアンの軍勢を阻止できなかった。資金提供組織はあなたの能力に疑問を持ち、エイリアンと平和協定を結ぼうとしている。{SMALLLINE}しかし、すぐにも彼らの思惑が全く異なるものだったと思い知るだろう...\"\n  STR_TOTAL_UC: \"合計\"\n  STR_INCOME: \"収入\"\n  STR_EXPENDITURE: \"支出\"\n  STR_MAINTENANCE: \"維持\"\n  STR_BALANCE: \"残高\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"海域別のエイリアンの活動\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"ゾーン別のエイリアンの活動\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"海域別のXComの活動\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"ゾーン別のX-COMの活動\"\n  STR_FINANCE: \"財政\"\n  STR_DATE_FIRST: \"{0}日目\"\n  STR_DATE_SECOND: \"{0}日目\"\n  STR_DATE_THIRD: \"{0}日目\"\n  STR_DATE_FOURTH: \"{0}日目\"\n  STR_FINANCE_THOUSANDS: \"1000ドル\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"{0}の製造に必要な材料が{1}で不足しています。\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"{1}で{0}の製造に必要な資金が足りません\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"{1}で{0}の製造が完了しました\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"{1}で{0}の工事は完了しました{NEWLINE}{NEWLINE}\"\n  STR_OK_5_SECONDS: \"OK - 5秒\"\n  STR_RESEARCH_COMPLETED: \"研究完了\"\n  STR_VIEW_REPORTS: \"レポートを見る\"\n  STR_WE_CAN_NOW_RESEARCH: \"現在研究可能です\"\n  STR_WE_CAN_NOW_PRODUCE: \"現在生産可能です\"\n  STR_SUNDAY: \"日曜日\"\n  STR_MONDAY: \"月曜日\"\n  STR_TUESDAY: \"火曜日\"\n  STR_WEDNESDAY: \"水曜日\"\n  STR_THURSDAY: \"木曜日\"\n  STR_FRIDAY: \"金曜日\"\n  STR_SATURDAY: \"土曜日\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"{0}が {2}で{1}を補給するのは十分ではありません\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"{2}で{1}を備えるには{0}が足りません\"\n  STR_UFO_IS_NOT_RECOVERED: \"宇宙人の潜水艇は未回収です\"\n  STR_UFO_IS_RECOVERED: \"宇宙人の潜水艇を回収しました\"\n  STR_CRAFT_IS_LOST: \"飛行潜水艇を失いました\"\n  STR_TERROR_CONTINUES: \"エイリアンの活動継続中\"\n  STR_ALIENS_DEFEATED: \"エイリアンは打倒されました\"\n  STR_BASE_IS_LOST: \"基地を失いました\"\n  STR_BASE_IS_SAVED: \"基地を守りました\"\n  STR_ALIEN_BASE_STILL_INTACT: \"宇宙人のコロニーは依然無傷\"\n  STR_ALIEN_BASE_DESTROYED: \"宇宙人のコロニーは破壊された\"\n  STR_ALIENS_KILLED: \"XComに射殺された宇宙人\"\n  STR_ALIEN_CORPSES_RECOVERED: \"回収された宇宙人の死体\"\n  STR_LIVE_ALIENS_RECOVERED: \"XComが捕虜にした宇宙人\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"回収された宇宙人の製造品\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"破壊した敵コロニーの制御装置\"\n  STR_ALIEN_SYNOMIUM_DEVICE_DESTROYED: \"破壊したシノミウム装置\"\n  STR_ALIEN_SYNOMIUM_DEVICE_FAILED: \"破壊に失敗したシノミウム装置\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"宇宙人に殺された民間人\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"XComに誤殺された民間人\"\n  STR_CIVILIANS_SAVED: \"無事に救助された民間人\"\n  STR_XCOM_OPERATIVES_KILLED: \"戦闘で死亡したXCom隊員\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"行方不明になったXCom隊員\"\n  STR_TANKS_DESTROYED: \"破壊されたWP\"\n  STR_XCOM_CRAFT_LOST: \"失われたXComの潜水艇\"\n  STR_UFO_RECOVERY: \"エイリアンの潜水艇の回収\"\n  STR_ALIEN_BASE_RECOVERY: \"宇宙人コロニーの回収\"\n  STR_BASE_UNDER_ATTACK: \"{0}は攻撃を受けています!\"\n  STR_BASE_DEFENSES_INITIATED: \"基地防衛戦開始\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"シールドで宇宙人の潜水艇撃退!\"\n  STR_FIRING: \"攻撃中\"\n  STR_HIT: \"迎撃成功!\"\n  STR_UFO_DESTROYED: \"エイリアンの潜水艇を破壊しました!\"\n  STR_MISSED: \"迎撃失敗!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"アイテムを売る/人員を解雇する\"\n  STR_VALUE_OF_SALES: \"販売価格> {ALT}{0}\"\n  STR_FUNDS: \"資金> {ALT}{0}\"\n  STR_SELL_SACK: \"売る/解雇する\"\n  STR_VALUE: \"価格\"\n  STR_CRAFT_: \"飛行潜水艇の燃料>{ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"エイリアン潜水艇の残骸回収\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"潜水艇の内部またはその周囲にエイリアンの生存者が存在する可能性があるので、充分注意せよ。敵の全ユニットを倒すかまたは無力化した後、潜水艇の残骸や兵器死体の回収を行うことができる。任務を中断する場合は全ての隊員を輸送艇に戻した後'任務中断'を実行せよ。\"\n  STR_UFO_GROUND_ASSAULT: \"エイリアン潜水艇の強襲\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"エイリアン潜水艇の停泊地点を捜索し、可能ならば潜水艇内部に侵入せよ。敵の全ユニットを倒すか、または無力化すると任務は達成される。その後、潜水艇や兵器、エイリアンの死体の回収を行うことができる。任務を中断する場合は全ての隊員を輸送艇に戻した後'任務中断'を実行せよ。\"\n  STR_BASE_DEFENSE: \"基地防衛\"\n  STR_BASE_UC_: \"基地> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"エイリアンの強襲艇が付近に着鑑し、我々の基地は深刻な危険に晒されている。規定によって非戦闘員と潜水艇は退避済である。エイリアンはドックの扉やエア・ロックから侵入を試みるはずだ。基地の防衛は最重要任務であり、基地の存亡を賭けた戦いである。'任務中断'を実行した場合は敗北を認めることになり、基地を失う。\"\n  STR_ALIEN_COLONY_ATTACK_MISSION: \"エイリアンコロニーの強襲\"\n  STR_ALIEN_BASE_ASSAULT: \"宇宙人のコロニー Part.1\"\n  STR_ALIEN_COLONY_P1_BRIEFING: \"これはエイリアンのコロニーを襲撃するミッションである。コロニーは2層から成り、1層目の光る退出マスの上に全員を配置してから'任務中断'を実行することで2層目へ進む。海底に落ちている装備類は2層目が無力化するまで保持される。撤退する場合は、全隊員を潜水艇に戻してから'任務中断'を実行すること。\"\n  STR_ALIEN_COLONY_P2: \"宇宙人のコロニー Part.2\"\n  STR_ALIEN_COLONY_P2_BRIEFING: \"1層目をクリアし、コロニーの中枢へ到達した。コントロールセンターにあるシノミウム装置を破壊するか、全ての敵ユニットを倒す/無力化せよ。作戦を中断する場合は全隊員をスタート地点に戻し、'任務中断'を実行せよ。その際視認可能な味方の装備類は全て回収される\"\n  STR_ALIENS_LAUNCH_PORT_TERROR: \"エイリアンが港を襲撃\"\n  STR_PORT_TERROR: \"エイリアンの港への襲撃\"\n  STR_PORT_TERROR_BRIEFING: \"エイリアンが地上攻撃を開始した。港と民間人が危険に晒されている。全てのエイリアンを一掃して民間人を守らなければならない。中断する場合は全隊員を輸送艇に戻してから'任務中断'を実行すること。\"\n  STR_ALIENS_LAUNCH_ISLAND_TERROR: \"エイリアンが島を襲撃\"\n  STR_ISLAND_TERROR: \"エイリアンの島への襲撃\"\n  STR_ISLAND_TERROR_BRIEFING: \"エイリアンが地上攻撃を開始した。島と民間人が危険に晒されている。全てのエイリアンを一掃して民間人を守らなければならない。中断する場合は全隊員を輸送艇に戻してから'任務中断'を実行すること。\"\n  STR_ALIENS_ATTACK_SHIPPING_ROUTE: \"エイリアンが航路を襲撃\"\n  STR_CARGO_SHIP_P1: \"貨物船 Part.1\"\n  STR_CARGO_SHIP_P2: \"貨物船 Part.2\"\n  STR_CRUISE_SHIP_P1: \"クルーザー Part.1\"\n  STR_CRUISE_SHIP_P2: \"クルーザー Part.2\"\n  STR_SHIP_RESCUE_MISSION: \"船舶救助ミッション\"\n  STR_SHIP_RESCUE_P1_BRIEFING: \"これは掃討作戦である。船上の全てのエイリアンを一掃して乗船中の民間人を守らなければならない。エイリアンは甲板上と下層に居るものと思われる。上層をクリアしてから下層へ向かえ。中断する場合は全隊員を輸送艇に戻してから'任務中断'を実行すること。\"\n  STR_SHIP_RESCUE_P2_BRIEFING: \"上層をクリアし、リフトを使って下層の貨物室へ降りた。全てのエイリアンを一掃してミッションを完了せよ。中断する場合、全隊員をリフト上に戻してから'任務中断'を実行すること。\"\n  STR_ALIEN_ACTIVITY_DETECTED: \"エイリアンの活動を確認\"\n  STR_ALIEN_CONTACT_SITE_MISSION: \"エイリアンの通信基地ミッション\"\n  STR_ARTIFACT_SITE_P1: \"エイリアンの通信基地 Part.1\"\n  STR_ARTIFACT_SITE_P1_BRIEFING: \"これはエイリアンの通信基地を襲撃するミッションである。ピラミッドのある海底とその下に隠された階層から成り、2層目の入り口のマスの上に全員を配置してから'任務中断'を実行することで階下へ進む。撤退する場合は、全隊員を輸送艇に戻してから'任務中断'を実行すること。\"\n  STR_ARTIFACT_SITE_P2: \"エイリアンの通信基地 Part.2\"\n  STR_ARTIFACT_SITE_P2_BRIEFING: \"ピラミッドに隠された入り口を通じて、地下に到達した。施設の中心に向かいシノミウム装置を破壊して任務を完了せよ。作戦を中断する場合は全隊員をアクセスリフトに戻し、'任務中断'を実行せよ。\"\n  STR_SIGSBEE_DEEP_MISSION: \"シグスビー海底ミッションエイリアンの都市一階\"\n  STR_TLETH_P1_BRIEFING: \"我々は未知の場所に侵入した。ここから先何が待ち受けているか判らない。エイリアンの都市にはさらに2つの階層がある事が分かっている。なるべく早く出口へ向かい、全ての隊員を出口のマスに配置して'任務中断'を実行して次の階層に進め。それ以外のマスで中断すると完全な任務放棄と見なされる。\"\n  STR_TLETH_ATTACK_MISSION: \"テ・レス襲撃ミッションエイリアンの都市二階\"\n  STR_TLETH_P2_BRIEFING: \"我々はさらなる未知の領域に侵入した。エイリアンの都市にはもう一つ階層がある事が分かっている。なるべく早く出口へ向かい、全ての隊員を出口のマスに配置して'任務中断'を実行して次の階層に進め。それ以外のマスで中断すると完全な任務放棄と見なされる。\"\n  STR_FINAL_TLETH_MISSION: \"最終テ・レスミッションエイリアンの都市三階\"\n  STR_TLETH_P3_BRIEFING: \"ゴールは目前である。究極のエイリアンが眠る墳墓を探し出し、8個あるパワーソースを全て破壊してエイリアンの脅威を闇に葬り去るのだ。くじけるな!ここで中断すると完全な任務放棄と見なされる。\"\n  STR_TLETH_P1: \"エイリアンの都市一階\"\n  STR_TLETH_P2: \"エイリアンの都市二階\"\n  STR_TLETH_P3: \"エイリアンの都市三階\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"生産する潜水艇のための空きドックがありません!{SMALLLINE}ドックで待機中の潜水艇を別の基地に移動するか、新しいドックを建設して、保管場所を確保してから生産してください。\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"購入する潜水艇のための空きドックがありません!{SMALLLINE}ドックで待機中の潜水艇を別の基地に移動するか、新しいドックを建設して、保管場所を確保してから購入してください。\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"移動する潜水艇のための空きドックがありません!{SMALLLINE}移動先で待機中の潜水艇をその他の基地に移動するか、移動先に新しいドックを建設してから潜水艇を移動してください。\"\n  STR_CANNOT_BUILD_HERE: \"そこに施設を建設することはできません!{SMALLLINE}新しい施設は、すでに建設されている施設のとなりに建設してください。\"\n  STR_NO_FREE_ACCOMODATION: \"移動させられません!{SMALLLINE}移動先の基地に、人員を収容するスペースがありません。\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"作業スペースが足りません!{SMALLLINE}新しい工作室を建設するか、他の製造プロジェクトの作業スペースを削減して下さい。\"\n  STR_NOT_ENOUGH_MONEY: \"資金不足です!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"貯蔵スペースがありません!{SMALLLINE}新しい倉庫を建設するか、別の基地へ貯蔵品を移動して、スペースを確保して下さい。\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"居住スペースがありません!{SMALLLINE}新しい居住区を建設するか、別の基地へ人員を移動して、スペースを確保して下さい。\"\n  STR_LAUNCH_INTERCEPTION: \"出撃命令\"\n  STR_CRAFT: \"潜水艇\"\n  STR_STATUS: \"ステイタス\"\n  STR_BASE: \"所属基地\"\n  STR_READY: \"発進待機中\"\n  STR_OUT: \"出撃中\"\n  STR_REPAIRS: \"修理中\"\n  STR_REFUELLING: \"燃料補給中\"\n  STR_REARMING: \"兵器搭載中\"\n  STR_TARGET: \"ターゲット: {0}\"\n  STR_WAY_POINT: \"ガイド・ポイント\"\n  STR_ARE_YOU_SURE_CYDONIA: \"本当に、この潜水艇をテ・レス襲撃任務に出撃させるのですか?\"\n  STR_YES: \"はい\"\n  STR_NO: \"いいえ\"\n  STR_SELECT_DESTINATION: \"目的地を選択する\"\n  STR_CYDONIA: \"テ・レス\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"新基地の建設場所を指定する\"\n  STR_RETURN_TO_BASE: \"基地へ戻る\"\n  STR_SELECT_NEW_TARGET: \"新しいターゲットを選択する\"\n  STR_PATROL: \"パトロール\"\n  STR_STATUS_: \"ステイタス>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"被弾破損 - 基地へ帰投中\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"燃料不足 - 基地へ帰投中\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"ミッション完了-帰投せよ\"\n  STR_PATROLLING: \"パトロール中\"\n  STR_TAILING_UFO: \"宇宙人の潜水艇を追跡中\"\n  STR_INTERCEPTING_UFO: \"宇宙人の潜水艇を攻撃中-{0}\"\n  STR_RETURNING_TO_BASE: \"基地へ帰投中\"\n  STR_DESTINATION_UC_: \"目標: {0}\"\n  STR_BASE_UC: \"基地>{ALT}{0}\"\n  STR_SPEED_: \"速度>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"最高速度>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"深度>{ALT}{0}\"\n  STR_AIRBORNE: \"空中\"\n  STR_VERY_LOW: \"浅瀬\"\n  STR_LOW_UC: \"海中\"\n  STR_HIGH_UC: \"深海\"\n  STR_VERY_HIGH: \"超深海\"\n  STR_FUEL: \"燃料>{ALT}{0}\"\n  STR_WEAPON_ONE: \"武器プライマリー>{ALT}{0}\"\n  STR_NONE_UC: \"なし\"\n  STR_ROUNDS_: \"弾薬>{ALT}{0}\"\n  STR_WEAPON_TWO: \"武器セカンダリ>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"飛行潜水艇\"\n  STR_BASE_: \"基地>{0}\"\n  STR_NAME_UC: \"名前\"\n  STR_AMMO_: \"弾薬>{ALT}{0}\"\n  STR_CREW: \"搭乗員\"\n  STR_EQUIPMENT_UC: \"装備\"\n  STR_ARMOR: \"アーマー\"\n  STR_MAX: \"最大>{ALT}{0}\"\n  STR_ROOKIE: \"一等水兵\"\n  STR_SQUADDIE: \"上等水兵\"\n  STR_SERGEANT: \"少尉\"\n  STR_CAPTAIN: \"大尉\"\n  STR_COLONEL: \"中佐\"\n  STR_COMMANDER: \"大佐\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"{0}の部隊を選択\"\n  STR_SORT_BY: \"ソートの条件...\"\n  STR_ORIGINAL_ORDER: \"元の順列\"\n  STR_MISSIONS2: \"ミッション\"\n  STR_KILLS2: \"倒した数\"\n  STR_WOUND_RECOVERY2: \"治療中\"\n  STR_SPACE_AVAILABLE: \"有効スペース>{ALT}{0}\"\n  STR_SPACE_USED: \"使用済みスペース>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"使用済みスペース\"\n  STR_RANK: \"階級\"\n  STR_WOUNDED: \"負傷\"\n  STR_EQUIPMENT_FOR_CRAFT: \"{0}の装備\"\n  STR_DEFENSE_VALUE: \"防衛力\"\n  STR_HIT_RATIO: \"迎撃成功率\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}は{ALT}{1}の近くで着鑑準備完了\"\n  STR_BEGIN_MISSION: \"任務を開始しますか?\"\n  STR_SELECT_ARMAMENT: \"武装を選択する\"\n  STR_AMMUNITION_AVAILABLE: \"弾薬使用可能\"\n  STR_ARMAMENT: \"武装\"\n  STR_NOT_AVAILABLE: \"N.A.\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"{0}のアーマーを選択\"\n  STR_TYPE: \"タイプ\"\n  STR_PLASTIC_AQUA_ARMOR_UC: \"プラスチックアーマー\"\n  STR_ION_ARMOR_UC: \"イオンアーマー\"\n  STR_MAGNETIC_ION_ARMOR_UC: \"マグネティックアーマー\"\n  STR_PLASTIC_AQUA_ARMOR_UFOPEDIA: \"この新しいアーマーには宇宙人の新素材アクア・プラスチックを用いており、我々が宇宙人の襲撃に打ち勝つチャンスをもたらす。\"\n  STR_ION_ARMOR_UFOPEDIA: \"潜水兵の為のこの新しい強化アーマーはイオンを動力源とし、着用者の素早さと強さを大幅に増幅させる事によって、戦闘部隊にとっていまだかつて無い最高の防護を提供する。\"\n  STR_MAGNETIC_ION_ARMOR_UFOPEDIA: \"イオンアーマーの強化バージョンには磁気アレイが組み込まれており、水中を自由自在に移動する事を可能とする。\"\n  STR_SELECT_ARMOR: \"装甲の選択\"\n  STR_NORTH: \"北\"\n  STR_NORTH_EAST: \"北東\"\n  STR_EAST: \"東\"\n  STR_SOUTH_EAST: \"南東\"\n  STR_SOUTH: \"南\"\n  STR_SOUTH_WEST: \"南西\"\n  STR_WEST: \"西\"\n  STR_NORTH_WEST: \"北西\"\n  STR_SELECT_ACTION: \"行動を選択する\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"迎撃を続ける\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"攻撃せずに追跡する\"\n  STR_VERY_LARGE: \"非常に大きい\"\n  STR_LARGE: \"大きい\"\n  STR_MEDIUM_UC: \"中型\"\n  STR_SMALL: \"小さい\"\n  STR_VERY_SMALL: \"非常に小さい\"\n  STR_GROUNDED: \"着艦中\"\n  STR_DETECTED: \"発見しました\"\n  STR_SIZE_UC: \"サイズ\"\n  STR_ALTITUDE: \"深度\"\n  STR_HEADING: \"進路\"\n  STR_SPEED: \"速度\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"敵潜水艇を中央に表示する - 時間=5秒\"\n  STR_TRACKING_LOST: \"追跡失敗\"\n  STR_REDIRECT_CRAFT: \"行動の選択\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"最後に敵潜水艇が確認された地点へ行く\"\n  STR_UFO_: \"宇宙人の潜水艇-{0}\"\n  STR_ALIEN_BASE_: \"宇宙人のコロニー-{0}\"\n  STR_CRASH_SITE_: \"沈没地点-{0}\"\n  STR_LANDING_SITE_: \"停泊地点\"\n  STR_WAY_POINT_: \"ガイド・ポイント-{0}\"\n  STR_TERROR_SITE: \"テロ活動地点-{0}\"\n  STR_ARTIFACT_SITE: \"建造地-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{1}は{0}に到達した\"\n  STR_NOW_PATROLLING: \"現在パトロール中\"\n  STR_ALIEN_ORIGINS: \"エイリアンの起源\"\n  STR_THE_ULTIMATE_THREAT: \"究極の脅威\"\n  STR_TLETH_ALIEN_CITY: \"エイリアン都市　'テ・レス'\"\n  STR_UFOPAEDIA: \"UFOペディア\"\n  STR_XCOM_CRAFT_ARMAMENT: \"Xcomの戦闘艇と兵器\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"SWS (重火器車両)\"\n  STR_WEAPONS_AND_EQUIPMENT: \"一般装備\"\n  STR_ALIEN_ARTIFACTS: \"宇宙人の製造品\"\n  STR_BASE_FACILITIES: \"X-COMの施設\"\n  STR_ALIEN_LIFE_FORMS: \"宇宙人\"\n  STR_ALIEN_RESEARCH_UC: \"宇宙人の研究\"\n  STR_UFO_COMPONENTS: \"潜水艇の新テクノロジー\"\n  STR_UFOS: \"宇宙人の潜水艇\"\n  STR_SELECT_ITEM: \"アイテムを選択せよ\"\n  STR_ACCELERATION: \"加速力>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"燃料搭載量>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"武装搭載数>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"ダメージ容量>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"搭載スペース>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"SWS搭載数>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"破壊力\"\n  STR_RANGE: \"射程距離\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"命中精度\"\n  STR_RE_LOAD_TIME: \"再装填に要する時間\"\n  STR_SECONDS: \"{0}秒\"\n  STR_DAMAGE_ARMOR_PIERCING: \"徹甲弾\"\n  STR_DAMAGE_INCENDIARY: \"リン弾\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"りゅう弾\"\n  STR_DAMAGE_LASER_BEAM: \"ガウス\"\n  STR_DAMAGE_PLASMA_BEAM: \"音波\"\n  STR_DAMAGE_STUN: \"凍結\"\n  STR_DAMAGE_MELEE: \"格闘\"\n  STR_DAMAGE_ACID: \"酸\"\n  STR_DAMAGE_SMOKE: \"煙幕\"\n  STR_SHOT_TYPE: \"タイプ\"\n  STR_ACCURACY_UC: \"命中精度\"\n  STR_TIME_UNIT_COST: \"TUコスト\"\n  STR_DAMAGE_UC: \"弾頭/破壊力\"\n  STR_AMMO: \"弾薬\"\n  STR_SHOT_TYPE_AUTO: \"3連射\"\n  STR_SHOT_TYPE_SNAP: \"急速\"\n  STR_SHOT_TYPE_AIMED: \"精密\"\n  STR_CONSTRUCTION_TIME: \"建造期間\"\n  STR_CONSTRUCTION_COST: \"建造費\"\n  STR_MAINTENANCE_COST: \"維持費\"\n  STR_LOW: \"低い\"\n  STR_MEDIUM: \"中位\"\n  STR_HIGH: \"高い\"\n  STR_CRAFT_WEAPON: \"潜水艇の兵器\"\n  STR_CRAFT_AMMUNITION: \"潜水艇の弾薬\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"HWP\"\n  STR_WEAPON: \"兵器\"\n  STR_AMMUNITION: \"弾薬\"\n  STR_EQUIPMENT: \"装備\"\n  STR_ALIEN_CORPSE: \"宇宙人の死体\"\n  STR_UFO_COMPONENT: \"宇宙人の潜水艇パーツ\"\n  STR_PERSONAL_ARMOR: \"個人用アーマー\"\n  STR_RAW_MATERIALS: \"原材料\"\n  STR_HWP_SOLID_HARPOON_BOLTS: \"硬化銛\"\n  STR_ALIEN: \"エイリアン\"\n  STR_AQUATOID: \"アクアトイド\"\n  STR_GILLMAN: \"ギルマン\"\n  STR_LOBSTERMAN: \"ロブスターマン\"\n  STR_TASOTH: \"タソス\"\n  STR_CALCINITE: \"カルシナイト\"\n  STR_DEEP_ONE: \"深きもの\"\n  STR_BIODRONE: \"バイオドローン\"\n  STR_TENTACULAT: \"テンタクラット\"\n  STR_TRISCENE: \"トリシーン\"\n  STR_HALLUCINOID: \"ハルシノイド\"\n  STR_XARQUID: \"ザーカッド\"\n  STR_ZOMBIE: \"ゾンビ\"\n  STR_LIVE_COMMANDER: \"司令官\"\n  STR_LIVE_NAVIGATOR: \"ナビゲーター\"\n  STR_LIVE_MEDIC: \"衛生兵\"\n  STR_LIVE_TECHNICIAN: \"技術者\"\n  STR_LIVE_SQUAD_LEADER: \"小隊長\"\n  STR_LIVE_SOLDIER: \"兵士\"\n  STR_LIVE_TERRORIST: \"テロリスト\"\n  STR_AQUATOID_COMMANDER: \"アクアトイド司令官\"\n  STR_AQUATOID_NAVIGATOR: \"アクアトイドのナビゲーター\"\n  STR_AQUATOID_MEDIC: \"アクアトイド衛生兵\"\n  STR_AQUATOID_TECHNICIAN: \"アクアトイド技術者\"\n  STR_AQUATOID_SQUAD_LEADER: \"アクアトイド小隊長\"\n  STR_AQUATOID_SOLDIER: \"アクアトイド兵士\"\n  STR_GILLMAN_COMMANDER: \"ギルマン司令官\"\n  STR_GILLMAN_TECHNICIAN: \"ギルマン技術者\"\n  STR_GILLMAN_SQUAD_LEADER: \"ギルマン小隊長\"\n  STR_GILLMAN_SOLDIER: \"ギルマン兵士\"\n  STR_LOBSTERMAN_COMMANDER: \"ロブスターマン司令官\"\n  STR_LOBSTERMAN_NAVIGATOR: \"ロブスターマンのナビゲーター\"\n  STR_LOBSTERMAN_TECHNICIAN: \"ロブスターマン技術者\"\n  STR_LOBSTERMAN_SQUAD_LEADER: \"ロブスターマン小隊長\"\n  STR_LOBSTERMAN_SOLDIER: \"ロブスターマン兵士\"\n  STR_TASOTH_SQUAD_LEADER: \"タソス小隊長\"\n  STR_TASOTH_SOLDIER: \"タソス兵士\"\n  STR_CALCINITE_TERRORIST: \"カルシナイトテロリスト\"\n  STR_DEEP_ONE_TERRORIST: \"深きものテロリスト\"\n  STR_BIODRONE_TERRORIST: \"バイオドローンテロリスト\"\n  STR_TENTACULAT_TERRORIST: \"テンタクラットテロリスト\"\n  STR_TRISCENE_TERRORIST: \"トリシーンテロリスト\"\n  STR_HALLUCINOID_TERRORIST: \"ハルシノイドテロリスト\"\n  STR_XARQUID_TERRORIST: \"ザーカッドテロリスト\"\n  STR_ION_BEAM_ACCELERATORS: \"イオンビーム加速器\"\n  STR_MAGNETIC_NAVIGATION: \"磁気ナビゲーション\"\n  STR_ALIEN_SUB_CONSTRUCTION: \"宇宙人の船体\"\n  STR_ALIEN_CRYOGENICS: \"宇宙人の冷凍睡眠装置\"\n  STR_ALIEN_CLONING: \"宇宙人のクローンマシン\"\n  STR_ALIEN_LEARNING_ARRAYS: \"宇宙人の学習機\"\n  STR_ALIEN_IMPLANTER: \"宇宙人のインプランター\"\n  STR_EXAMINATION_ROOM: \"検査室\"\n  STR_AQUA_PLASTICS: \"アクア・プラスチック\"\n  STR_ALIEN_REANIMATION_ZONE: \"宇宙人の活性装置\"\n  STR_PLASTIC_AQUA_ARMOR: \"プラスチックアーマー\"\n  STR_ION_ARMOR: \"イオンアーマー\"\n  STR_MAGNETIC_ION_ARMOR: \"マグネットアーマー\"\n  STR_HWP_AQUA_JET_MISSILES: \"水中ジェット魚雷\"\n  STR_HWP_DISPLACER_PWT: \"P.W.T.魚雷\"\n  STR_GAUSS_TECH: \"ガウス・テクノロジー\"\n  STR_NEW_FIGHTER_FLYING_SUB: \"新飛行潜水艇\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"新戦闘輸送艇\"\n  STR_THE_LATEST_FLYING_SUB: \"最新飛行潜水艇\"\n  STR_ARMOR_PIERCING: \"徹甲弾\"\n  STR_COELACANTH_GAS_CANNON: \"シーラカンス/G.キャノン\"\n  STR_COELACANTH_AQUA_JET: \"シーラカンス/アクアジェット\"\n  STR_COELACANTH_GAUSS: \"シーラカンス/ガウス\"\n  STR_DISPLACER_SONIC: \"ディスプレーサ/ソニック\"\n  STR_DISPLACER_PWT: \"ディスプレーサ/P.W.T.\"\n  STR_AJAX_LAUNCHER: \"AJaxランチャ\"\n  STR_DUP_HEAD_LAUNCHER: \"D.U.P.弾頭ランチャ\"\n  STR_CRAFT_GAS_CANNON: \"潜水艇用ガス・キャノン\"\n  STR_PWT_CANNON: \"P.W.T.キャノン\"\n  STR_GAUSS_CANNON: \"ガウスキャノン\"\n  STR_GAUSS_CANNON_AMMO: \"ガウスキャノン砲弾\"\n  STR_SONIC_OSCILLATOR: \"音波発振器\"\n  STR_AJAX_TORPEDOES: \"AJax魚雷\"\n  STR_DUP_HEAD_TORPEDOES: \"D.U.P.弾頭魚雷\"\n  STR_CRAFT_GAS_CANNON_ROUNDS_X50: \"ガス砲弾(x50)\"\n  STR_SONIC_WAVE: \"音波\"\n  STR_PULSE_WAVE_TORPEDOES: \"P.W.T.魚雷\"\n  STR_SOLDIER: \"潜水兵\"\n  STR_SCIENTIST: \"科学者\"\n  STR_ENGINEER: \"技術者\"\n  STR_NORTH_ATLANTIC: \"北大西洋\"\n  STR_SOUTH_ATLANTIC: \"南大西洋\"\n  STR_NORTH_PACIFIC: \"北太平洋\"\n  STR_SOUTH_PACIFIC: \"南太平洋\"\n  STR_MEDITERRANEAN: \"地中海\"\n  STR_SOUTH_CHINA_SEA: \"南シナ海\"\n  STR_INDIAN_OCEAN: \"インド洋\"\n  STR_THE_EAST_SEA: \"日本海\"\n  STR_NORTH_SEA: \"北海\"\n  STR_CARRIBEAN: \"カリブ海\"\n  STR_ANTARCTIC: \"南極海\"\n  STR_ARCTIC: \"北極海\"\n  STR_EURASIA: \"ユーラシア\"\n  STR_NORTH_AMERICA: \"北アメリカ\"\n  STR_AFRICA: \"アフリカ\"\n  STR_MAXIMUM_SPEED: \"最高速度\"\n  STR_TRANSMISSION_RESOLVER_UC: \"通信解読器\"\n  STR_TRITON: \"トリトン\"\n  STR_HAMMERHEAD: \"ハンマーヘッド\"\n  STR_LEVIATHAN: \"リバイアサン\"\n  STR_BARRACUDA: \"バラクーダ\"\n  STR_MANTA: \"マンタ\"\n  STR_UFO: \"宇宙人の潜水艇\"\n  STR_AJAX: \"AJax\"\n  STR_DUP_HEAD: \"D.U.P.弾頭\"\n  STR_CRAFT_GAS_CANNON_UC: \"潜水艇用ガス・キャノン\"\n  STR_PWT_CANNON_UC: \"P.W.T.キャノン\"\n  STR_GAUSS_CANNON_UC: \"ガウスキャノン\"\n  STR_SONIC_OSCILLATOR_UC: \"音波発振器\"\n  STR_DAMAGE_CAPACITY: \"ダメージ容量\"\n  STR_WEAPON_POWER: \"兵器の破壊力\"\n  STR_WEAPON_RANGE: \"射程距離\"\n  STR_AIR_LOCK: \"エア・ロック\"\n  STR_LABORATORY: \"研究室\"\n  STR_WORKSHOP: \"工作室\"\n  STR_STANDARD_SONAR: \"標準ソナー\"\n  STR_WIDE_ARRAY_SONAR: \"広域ソナー\"\n  STR_TORPEDO_DEFENSES: \"魚雷防衛\"\n  STR_GENERAL_STORES: \"倉庫\"\n  STR_ALIEN_CONTAINMENT: \"隔離拘束施設\"\n  STR_GAUSS_DEFENSES: \"ガウス防衛\"\n  STR_SONIC_DEFENSES: \"ソニック防衛\"\n  STR_PWT_DEFENSES: \"P.W.T.防衛\"\n  STR_BOMBARDMENT_SHIELD: \"圧力シールド\"\n  STR_MC_GENERATOR: \"M.C.発生器\"\n  STR_MC_LAB: \"M.C.研究所\"\n  STR_TRANSMISSION_RESOLVER: \"通信解読器\"\n  STR_SUB_PEN: \"ドック\"\n  STR_USA: \"USA\"\n  STR_ALASKA: \"アラスカ\"\n  STR_EU_SYNDICATE: \"ユーロ・シンジケート\"\n  STR_ARABIAN_BLOC: \"アラビア圏\"\n  STR_EGYPTIAN_CARTEL: \"エジプト・カルテル\"\n  STR_AFRICA_CORP: \"アフリカ共同体\"\n  STR_BRAZILIAN_UNION: \"ブラジル連合\"\n  STR_NEW_MEXICO: \"ニューメキシコ\"\n  STR_ASIAN_COALITION: \"アジア連合\"\n  STR_SCANDINAVIA: \"スカンジナビア\"\n  STR_NEO_JAPAN: \"新日本\"\n  STR_FREE_CHINA: \"中華自由連合\"\n  STR_AUSTRALASIA: \"オーストラル・アジア\"\n  STR_FED_KOREA: \"朝鮮連邦\"\n  STR_EURASIA_UC: \"ユーラシア\"\n  STR_ICELANDIC_UNION: \"アイスランド・ユニオン\"\n  STR_TANK: \"重火器プラットフォーム\"\n  STR_CIVILIAN: \"民間人\"\n  STR_JAN: \"1月\"\n  STR_FEB: \"2月\"\n  STR_MAR: \"3月\"\n  STR_APR: \"4月\"\n  STR_MAY: \"5月\"\n  STR_JUN: \"6月\"\n  STR_JUL: \"7月\"\n  STR_AUG: \"8月\"\n  STR_SEP: \"9月\"\n  STR_OCT: \"10月\"\n  STR_NOV: \"11月\"\n  STR_DEC: \"12月\"\n  STR_INTERNATIONAL_RELATIONS: \"国際関係\"\n  STR_COUNTRY: \"国名\"\n  STR_FUNDING: \"提供資金額\"\n  STR_CHANGE: \"変更\"\n  STR_WEAPON_SYSTEMS: \"武器システム\"\n  STR_HWPS: \"SWS\"\n  STR_DAMAGE_UC_: \"ダメージ>{ALT}{0}\"\n  STR_AIR_LOCK_UFOPEDIA: \"エア・ロックにより、装備や人員を海底基地の内部へ、または基地から外部へと移動することができる。新しく基地を建設する場合には、この施設を最初に建設する必要がある。エア・ロック付近は、敵の侵入の危険に絶えず晒されているので要注意。\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"各居住区の収容人員は最大50名である。居住区には基本的な食事および睡眠のためのエリアと、簡単な娯楽設備が設けてある。\"\n  STR_LABORATORY_UFOPEDIA: \"研究室には最大50名迄の科学者用の研究スペースがある。研究室には素材、生化学、兵器などを研究するための最新の設備が備えられており、さらに軍事施設を含む世界中のあらゆる研究施設のコンピュータにアクセスできるという特権がある。\"\n  STR_WORKSHOP_UFOPEDIA: \"工作室には、研究室で行われた研究成果に基づいてデザインされた装備を製造する為の生産用設備が全てそろっている。製造中のアイテムもいくらかスペースを必要とするが、基本的には技術者は最大50名まで工作室に入ることができる。\"\n  STR_STANDARD_SONAR_UFOPEDIA: \"標準ソナー・システムの有効捜索範囲は約450キロであり、地上探査用の衛星システムとリンクしている。各システムは10%の公算で、30分ごとに空中および海中の目標を探知することが可能である。\"\n  STR_WIDE_ARRAY_SONAR_UFOPEDIA: \"広域ソナー・アレイの有効捜索範囲は約700キロであり、地上探査用の衛星システムとリンクしている。各システムは20%の公算で、30分ごとに空中および海中の目標を探知することが可能である。\"\n  STR_TORPEDO_DEFENSES_UFOPEDIA: \"魚雷防衛は、基地の付近に敵の潜航艇が着艦を試みた際に、ある程度の防衛力を提供する。\"\n  STR_GENERAL_STORES_UFOPEDIA: \"全ての装備、武器、弾薬、回収した物品およびHWP(重兵器プラットホーム)は、この倉庫内に保管されている。ただし、輸送機や襲撃艇に搭載されるべき装備や兵器類は、格納庫内に保管されている。\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"生け捕りにしたエイリアンは、その生命を維持するため特別な生息環境を必要とする。隔離拘束施設には特殊な生命維持装置を備えた10個の独居房が備えられている。\"\n  STR_GAUSS_DEFENSES_UFOPEDIA: \"ガウス防衛は敵の侵入に対し現時点で最高の防御効果を発揮する。\"\n  STR_SONIC_DEFENSES_UFOPEDIA: \"音波発振防衛は、敵の侵入に対して強力且つ効果的な防御力を発揮する。\"\n  STR_PWT_DEFENSES_UFOPEDIA: \"パルス波魚雷は、エイリアンの攻撃に対し最も効果的な防衛手段を提供する。この魚雷は超圧縮弾頭によってあらゆる装甲を貫通し、電磁波を発生させて敵の電気系統を無力化する。\"\n  STR_BOMBARDMENT_SHIELD_UFOPEDIA: \"この圧力衝突式シールドは、基地の周辺に着艦を試みるエイリアンの潜水艇の着艦速度を低下させる。そのために、防衛システムが攻撃を行う時間は倍増するので、事実上、基地の防衛効果も2倍になる。\"\n  STR_MC_GENERATOR_UFOPEDIA: \"エイリアンは分子制御装置によって生命体の存在を知覚している為、貫通不可能なマイナスの分子を放出して基地全体を覆うことでエイリアンの探知の目を眩まし、我々の存在を隠すことができる。\"\n  STR_MC_LAB_UFOPEDIA: \"分子制御研究室は、M.C.インプラントを潜水兵の頭蓋に埋め込む手術と訓練を最大10名まで同時に行える。激しい訓練によって兵士達はインプラントを扱う術を身に付ける。スキルを上達させることで戦闘中に分子制御装置を使って攻撃する事が可能になる。\"\n  STR_TRANSMISSION_RESOLVER_UFOPEDIA: \"エイリアンの通信は分子制御インプラントによるネットワークを用いている。この通信解読施設が宇宙人の潜水艇の通信を傍受して、暗号情報を解読する。これにより、潜水艇のタイプやエイリアンの種類、活動の目的などが判明する。\"\n  STR_SUB_PEN_UFOPEDIA: \"それぞれのドックには潜水艇１艘を収納することができる。そして、船体の修理や整備、さらに燃料や武器弾薬の補給を行うための設備も備えている。基地に所属する潜水艇は、必ず一つのドックを占有し、他の潜水艇がその格納庫を重複して使用することはできない。\"\n  STR_DART_PISTOL_UFOPEDIA: \"X-COMのダーツガンは小型、高精度、高威力の銃で、12発のHPダーツを弾倉に備える。{NEWLINE}ダーツは薬莢内のガスカートリッジによって発射される。\"\n  STR_JET_HARPOON_UFOPEDIA: \"水中銃は高精度で高威力の鋼鉄製のHP銛を10発分纏められた弾倉から発射する。{NEWLINE}銛本体にガスタンクが備わっている。\"\n  STR_GAS_CANNON_UFOPEDIA: \"ガスを用いた武器の中でもこのキャノンは硬質、ＨＥおよびリンを用いたボルトがあり、用途によって使い分けられる。熟練した潜水兵に好まれる。\"\n  STR_HYDRO_JET_CANNON_UFOPEDIA: \"水素ジェットキャノンは潜水兵用の重火器である。マグネシウムを燃料とした小型魚雷を発射する。強力だがかさばり、扱いにくい。{NEWLINE}{NEWLINE}水中専用。\"\n  STR_TORPEDO_LAUNCHER_UFOPEDIA: \"3種の魚雷が発射可能な非常に重い大型のランチャーで、魚雷本体にプロペラが備わっている。再装填が手動である欠点を除けば非常に強力な火器である。魚雷のタイプは大小の炸裂弾頭とリン弾頭である。{NEWLINE}{NEWLINE}水中専用。\"\n  STR_GAUSS_PISTOL_UFOPEDIA: \"ガウスピストルは加速粒子テクノロジーを用いた新兵器である。水中での使用に際し、高速で高精度を誇る。先のエイリアンとの戦争で得られたプラズマテクノロジーから発展した。\"\n  STR_GAUSS_PISTOL_CLIP_UFOPEDIA: \"ガウスピストルは加速粒子テクノロジーを用いた新兵器である。水中での使用に際し、高速で高精度を誇る。先のエイリアンとの戦争で得られたプラズマテクノロジーから発展した。\"\n  STR_GAUSS_RIFLE_UFOPEDIA: \"ガウスピストルを改良したこのライフルは粒子加速装置を2基搭載して威力を上げたものである。エレリウムを使用するプラズマシステムを超小型粒子加速装置に置き換える事で反陽子の流束を発射する。\"\n  STR_GAUSS_RIFLE_CLIP_UFOPEDIA: \"ガウスピストルを改良したこのライフルは粒子加速装置を2基搭載して威力を上げたものである。エレリウムを使用するプラズマシステムを超小型粒子加速装置に置き換える事で反陽子の流束を発射する。\"\n  STR_HEAVY_GAUSS_UFOPEDIA: \"重ガウスライフルはかさばるが、威力は絶大である。粒子加速装置を3基搭載し、これに耐え得る敵は居ないだろう。{NEWLINE}ガリウムひ素を用いたカートリッジから発せられる反陽子ビームは目標に命中すると内部を反物質が破壊する。\"\n  STR_HEAVY_GAUSS_CLIP_UFOPEDIA: \"重ガウスライフルはかさばるが、威力は絶大である。粒子加速装置を3基搭載し、これに耐え得る敵は居ないだろう。{NEWLINE}ガリウムひ素を用いたカートリッジから発せられる反陽子ビームは目標に命中すると内部を反物質が破壊する。\"\n  STR_MAGNA_BLAST_GRENADE_UFOPEDIA: \"この手りゅう弾は、正確なコントロールを行うために、精密かつ精巧なタイマーを備えている。\"\n  STR_DYE_GRENADE_UFOPEDIA: \"カラー手りゅう弾は、二通りに使用でき、敵の目から姿を隠す場合に有効である。水陸両用で、染料の粒子が放出され、水中ではタコの墨の様に広がり、陸上では濃い煙幕となる。\"\n  STR_PARTICLE_DISTURBANCE_GRENADE_UFOPEDIA: \"近接手りゅう弾は、普通の手りゅう弾と同様に投げることができるが、その爆発はタイマー信管ではなく近接信管による。この種の兵器を使用するには、熟練した技術と最大の注意力が必要である。\"\n  STR_MAGNA_PACK_EXPLOSIVE_UFOPEDIA: \"この高性能時限爆弾は、建造物の破壊等の目的にのみ使用しなければならない。しかしながら、エイリアンを一網打尽にする理想的な武器だという事も周知である。爆発半径が大きいので人員が安全な場所に居ることを確認してから使用すること。\"\n  STR_PARTICLE_DISTURBANCE_SENSOR_UFOPEDIA: \"この新しい装置は、種々の探知器とコンピュータ・アルゴリズムを駆使しており、移動中の敵ユニットを探知することができる。{NEWLINE}{NEWLINE}この装置を使用するには、まずタクティカル・ディスプレイでスキャナを選択し、メニューから‘スキャナを使う’を選択する。{NEWLINE}{NEWLINE}スキャナの中央に表示された矢印が、兵士の向きを表している(上は常に北)。点滅しているドットは移動中のユニットを示す。ドットは高速で移動するほど、またはユニットのサイズが大きくなるほど大きく表示される。ただし、この装置は静止しているユニットは探知できない。\"\n  STR_MEDI_KIT_UFOPEDIA: \"この装置は負傷した兵士の方を向いて、または気絶した兵士の体の上で使用する。{NEWLINE}{NEWLINE}治療> 赤い部分が負傷した部位を示す。治療する部位を選択して‘治療’ボタンを押す。傷が治療され健康を回復する。{NEWLINE}{NEWLINE}興奮剤> エネルギーを回復し、気絶した兵士の意識を回復する。気絶した兵士の意識を回復させるには、身体の上に直接立って操作を行う。{NEWLINE}{NEWLINE}鎮痛剤> 負傷した兵の士気を取り戻す。\"\n  STR_MC_DISRUPTOR_UFOPEDIA: \"M.C.テクノロジーを最も効果的に使用した装置。これはM.C.スキルを持つ兵士のみが使用できる。この装置で可能なM.C.攻撃には以下の２タイプがある。{NEWLINE}{NEWLINE}インプラント・ジャム>攻撃が成功すれば、ターゲットは士気をくじかれ、パニックにおちいる。{NEWLINE}{NEWLINE}インプラント・コントロール>この攻撃が成功すれば、敵ユニットを自分のユニットの様に直接コントロールできる\"\n  STR_THERMAL_TAZER_UFOPEDIA: \"この装置は接近戦でしか使用できないが、凍らせることで相手を殺さずに気絶させることができる。{NEWLINE}{NEWLINE}使用法>スタンさせたい相手に隣接し、その方向を向いて用いる。\"\n  STR_VIBRO_BLADE_UFOPEDIA: \"振動ブレードはチタン製の長いナイフで、秒間100回転する事でいかなる敵の装甲をも貫く。動力源はエイリアンが発明したもので、我々の技術で造られたものは回転が遅すぎるか水圧が高い場所では爆発してしまうので使い物にならなかった。\"\n  STR_THERMIC_LANCE_UFOPEDIA: \"ヒート・ランスは振動ブレードの原理を応用した武器で、刃が高速回転しながらザーバイトを熱源とする超発熱を帯びて敵のアーマーを熱したナイフがバターを切る様に切り裂く。\"\n  STR_HEAVY_THERMIC_LANCE_UFOPEDIA: \"重ヒート・ランスはヒート・ランスの強化版である。熱源を2基搭載し、超高速回転によってあらゆる物質を貫く。\"\n  STR_SONIC_CANNON_UFOPEDIA: \"ソニックキャノンは音波兵器の中でも最も効果を期待できる武器である。ブラスターより広範囲に対応した音波発振器とより大きな反響腔を持つ。さらに超音波をより効果的に衝撃波に変換することで振動爆発を発生させる。\"\n  STR_CANNON_POWER_CLIP_UFOPEDIA: \"この小型の装置はソニック・キャノン用の弾倉である。極少量のザーバイトを含有している。\"\n  STR_SONIC_BLASTA_RIFLE_UFOPEDIA: \"より強化された音波兵器。高炭素鋼ですら破壊する。コンパクトな音波発生器は超伝導によって威力を増している。\"\n  STR_BLASTA_POWER_CLIP_UFOPEDIA: \"この小さな装置はソニック・ブラスター用の弾倉である。エイリアンの有力な武器であり、極少量のザーバイトを含有している。\"\n  STR_SONIC_PISTOL_UFOPEDIA: \"ソニックピストルは超音波を用いたエイリアンの武器で、骨を数秒でゼリー状にする力を持つ。超音波は人間の可聴域を越えた音波である。\"\n  STR_PISTOL_POWER_CLIP_UFOPEDIA: \"ソニック・ピストル用弾倉。エイリアンのパワーの源であるザーバイトを用いている。\"\n  STR_DISRUPTOR_PULSE_LAUNCHER_UFOPEDIA: \"これはプロペラ駆動する'崩壊弾'を発射することができるエイリアンの誘導型水中兵器である。{NEWLINE}{NEWLINE}この武器を使用する場合、魚雷が通過するガイド・ポイントを設定し、それが終了したら特別な'発射'のアイコンをクリックする。\"\n  STR_DISRUPTOR_AMMO_UFOPEDIA: \"これは高度な知的誘導システムを備えた崩壊波を用いる魚雷である。崩壊波ランチャーから発射される。\"\n  STR_THERMAL_SHOK_LAUNCHER_UFOPEDIA: \"化学凍結を用いた爆弾を発射するための凍結ショックランチャ。この兵器を使用すると、エイリアンを生きたまま捕獲することができる。\"\n  STR_THERMAL_SHOK_BOMB_UFOPEDIA: \"TSボムは生きたまま人間の標本を捕獲するために使用される。が、それはまた殆どのエイリアン種族に対しても有効である。これはTSランチャーから発射される。\"\n  STR_SONIC_PULSER_UFOPEDIA: \"この手榴弾は通常の手榴弾と同様に扱えるが、数倍強力である。爆発すると全方向に衝撃波を発生させる。\"\n  STR_MC_READER_UFOPEDIA: \"エイリアンの体には小さな装置が埋め込まれている。それらの装置はアクアトイドが戦場の情報を逐一把握する為に作られたインプラントを制御し、距離の影響を受けない。{NEWLINE}M.C.測定器はエイリアンの通信装置であり、インプラントから直接情報を収集する事ができる。XComもこの装置を用いて、特定のエイリアンの情報を得ることができる。\"\n  STR_SURVEY_SHIP: \"調査船\"\n  STR_ESCORT: \"護衛鑑\"\n  STR_CRUISER: \"巡洋艦\"\n  STR_HEAVY_CRUISER: \"重巡洋艦\"\n  STR_HUNTER: \"駆逐艦\"\n  STR_BATTLESHIP: \"戦艦\"\n  STR_DREADNOUGHT: \"弩級戦艦\"\n  STR_FLEET_SUPPLY_CRUISER: \"補給艦\"\n  MAP_SEABED: \"海底\"\n  MAP_PIPES: \"研究施設\"\n  MAP_PLANE: \"墜落機\"\n  MAP_ATLAN: \"アトランティス\"\n  MAP_MU: \"ムー\"\n  MAP_GAL: \"沈没したガレオン船\"\n  MAP_MSUNK: \"沈没した定期船\"\n  MAP_VOLC: \"火山帯\"\n  MAP_CORAL: \"珊瑚礁\"\n  MAP_PORT: \"港\"\n  MAP_ISLAND: \"島\"\n  MAP_CARGO: \"貨物船\"\n  MAP_LINERT: \"クルーズ船 P1\"\n  MAP_LINERB: \"クルーズ船 P2\"\n  MAP_ALART: \"遺物 P1\"\n  MAP_GRUNGE: \"遺物 P2\"\n  MAP_ENTRY: \"コロニー P1\"\n  MAP_A_BASE: \"コロニー P2\"\n  MAP_ALSHIP: \"テ・レス P1\"\n  MAP_LEVEL: \"テ・レス P2\"\n  MAP_CRYPT: \"テ・レス P3\"\n  MAP_XBASES: \"X-COM基地\"\n  STR_MIXED_CREW: \"混合構成員\"\n  STR_MIXED_CREW_2: \"混合構成員2\"\n  STR_RATING: \"評価> {0}\"\n  STR_RATING_TERRIBLE: \"劣悪!\"\n  STR_RATING_POOR: \"不十分!\"\n  STR_RATING_OK: \"OK\"\n  STR_RATING_GOOD: \"良い!\"\n  STR_RATING_EXCELLENT: \"優秀!\"\n  STR_SCORE: \"スコア\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"XCOM月間レポート\"\n  STR_MONTH: \"月> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"資金提供組織の評議会は、これまでのあなたの働きにおおむね満足しています。\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"資金提供組織の評議会は、あなたの素晴らしい働きに大変満足しています。その調子で続けて下さい。\"\n  STR_COUNCIL_IS_DISSATISFIED: \"資金提供組織の評議会はあなたの働きに不満です。エイリアン対策の効率を高めなければ、プロジェクトは停止される恐れがあります。\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"あなたは宇宙人の侵略に対し、処置を講じ損ないました。資金提供組織の議会は、残念ながらプロジェクトの停止を決定しました。{NEWLINE}各国は、それぞれに問題を処理することになります。今、我々にできることは、これらの明らかに敵と思われる軍隊と和解することと、民間人がエイリアンの視察員との協定に納得するようにと願うことだけです。\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0}は脅威を局部的に食い止めたあなたの処置能力に 特に満足して、資金提供額を増やすことに同意しました。\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0}は、特定海域におけるエイリアンの侵略に対するあなたの働きに特に満足して、資金提供額を増やすことに同意しました。\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} と {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0}は、領海内でのエイリアンの活動に対するあなたの処置能力に不満足で、経済的な援助を削減することを決定しました。\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0}は、領海内でのエイリアンの活動に対するあなたの処置能力に不満足で、経済的な援助を削減することを決定しました。\"\n  STR_KNOTS: \"{0} ノット\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0}は、エイリアン軍との秘密条約にサインし、プロジェクトから離脱しました。\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0}は、エイリアン軍との秘密条約にサインし、プロジェクトから離脱しました。\"\n  STR_MONTHLY_RATING: \"月間評価> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"資金変更> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"資金提供評議会は、あなたの経済状況を好ましく思っていません。負債を百万ドル以下に落とさなければ、プロジェクトは停止されます。\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"素粒子通信を解読しました\"\n  STR_CRAFT_TYPE: \"潜水艇のタイプ\"\n  STR_RACE: \"種族\"\n  STR_MISSION: \"任務\"\n  STR_ZONE: \"ゾーン\"\n  STR_ALLOCATE_RESEARCH: \"研究を割り当てる\"\n  STR_ALLOCATE_MANUFACTURE: \"製造を割り当てる\"\n  STR_AZORES: \"アゾレス諸島\"\n  STR_REYKJAVIK: \"レイキャビク\"\n  STR_BERMUDA: \"バミューダ\"\n  STR_NEW_YORK: \"ニューヨーク\"\n  STR_BOSTON: \"ボストン\"\n  STR_FORT_SEVERN: \"フォートセバーン\"\n  STR_DAKAR: \"ダカール\"\n  STR_RECIFE: \"レシフェ\"\n  STR_ACCRA: \"アクラ\"\n  STR_ASCENSION_ISLAND: \"アセンション島\"\n  STR_TRINIDADE_ISLAND: \"トリニダード島\"\n  STR_FALKLAND_ISLAND: \"フォークランド島\"\n  STR_CANARY_ISLANDS: \"カナリア諸島\"\n  STR_ANCHORAGE: \"アンカレッジ\"\n  STR_ST_LAWRENCE_ISLAND: \"セントローレンス島\"\n  STR_SAN_FRANCISCO: \"サンフランシスコ\"\n  STR_MIDWAY_ISLAND: \"ミッドウェー諸島\"\n  STR_VANCOUVER: \"バンクーバー\"\n  STR_TASMANIA: \"タスマニア\"\n  STR_HAWAII: \"ハワイ\"\n  STR_FIJI: \"フィジー諸島\"\n  STR_TONGA: \"トンガ\"\n  STR_EASTER_ISLAND: \"イースター島\"\n  STR_GALAPAGOS_ISLAND: \"ガラパゴス島\"\n  STR_WELLINGTON: \"ウエリントン\"\n  STR_SOLOMON_ISLAND: \"ソロモン島\"\n  STR_CRETE: \"クレタ\"\n  STR_LISBON: \"リスボン\"\n  STR_PORT_SAID: \"ポートサイド\"\n  STR_MARSEILLES: \"マルセイユ\"\n  STR_TRIPOLI: \"トリポリ\"\n  STR_MANILA: \"マニラ\"\n  STR_HONG_KONG: \"香港\"\n  STR_SINGAPORE: \"シンガポール\"\n  STR_BANGKOK: \"バンコク\"\n  STR_DARWIN: \"ダーウィン\"\n  STR_BOMBAY: \"ボンベイ\"\n  STR_SAYCHELLES_ISLAND: \"セイシェル島\"\n  STR_MALDIVE_ISLAND: \"モルジブ島\"\n  STR_SRI_LANKA: \"スリランカ\"\n  STR_MAURITIUS: \"モーリシャス\"\n  STR_TOKYO: \"東京\"\n  STR_SHANGHAI: \"上海\"\n  STR_VLADIVOSTOK: \"ウラジオストック\"\n  STR_LONDON: \"ロンドン\"\n  STR_FAEROE_ISLAND: \"フェロー諸島\"\n  STR_ABERDEEN: \"アバディーン\"\n  STR_OSLO: \"オスロ\"\n  STR_JAMAICA: \"ジャマイカ\"\n  STR_PANAMA: \"パナマ\"\n  STR_MIAMI: \"マイアミ\"\n  STR_PSI_TRAINING: \"M.C.訓練\"\n  STR_PSIONIC_TRAINING: \"分子制御トレーニング\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"M.C.訓練室 残り容量> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"M.C.強度\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"M.C.技術/向上\"\n  STR_IN_TRAINING: \"訓練中?\"\n  STR_TARGETTED_BY: \"の目的地です\"\n  STR_WEAPONS_CREW_HWPS: \"武装:戦闘員:HWP\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"は燃料不足により、基地へ帰投します。\"\n  STR_SOLDIER_LIST: \"潜水兵のリスト\"\n  STR_RANK_: \"階級> {ALT}{0}\"\n  STR_MISSIONS: \"任務> {ALT}{0}\"\n  STR_KILLS: \"倒した敵> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"傷回復> {ALT}{0}\"\n  STR_TIME_UNITS: \"時間ユニット\"\n  STR_STAMINA: \"スタミナ\"\n  STR_HEALTH: \"H.P.\"\n  STR_BRAVERY: \"勇敢さ\"\n  STR_REACTIONS: \"反応度\"\n  STR_FIRING_ACCURACY: \"射撃能力\"\n  STR_THROWING_ACCURACY: \"投てき能力\"\n  STR_STRENGTH: \"筋力\"\n  STR_PSIONIC_STRENGTH: \"M.C.強度\"\n  STR_PSIONIC_SKILL: \"M.C.スキル\"\n  STR_NEW_RANK: \"新しい階級\"\n  STR_PROMOTIONS: \"昇進\"\n  STR_SOLDIERS_UC: \"潜水兵\"\n  STR_COELACANTH_GAS_CANNON_UFOPEDIA: \"自動化SWSは高い機動性と耐久力を備える。SWSはあらゆる深度で小隊を支援可能で、予備弾薬があれば自動的に装填する\"\n  STR_COELACANTH_AQUA_JET_UFOPEDIA: \"この潜水兵器はアクアジェット魚雷を装備している。この武器は水中でしか使用できない。予備弾薬が十分にあるか注意せよ\"\n  STR_COELACANTH_GAUSS_UFOPEDIA: \"ガウステクノロジーはSWSの武器システムに従来のものより強力な火力を提供する、X-COM独自の技術である。\"\n  STR_DISPLACER_SONIC_UFOPEDIA: \"宇宙人のテクノロジーに合わせSWSは改良された。イオン変換器によって水陸両用となった音波兵器は戦闘を有利にするだろう\"\n  STR_DISPLACER_PWT_UFOPEDIA: \"SWSに水中戦用のパルス波兵器を搭載した。パルス波魚雷を製造して装填しておくこと。{NEWLINE}{NEWLINE}この武器を使用する場合、魚雷が通過するガイド・ポイントを設定し、それが終了したら特別な'発射'アイコンをクリックする\"\n  STR_ALIEN_PROBE_MISSION: \"調査\"\n  STR_ALIEN_INTERDICTION: \"偵察\"\n  STR_ALIEN_RESOURCE_RAID: \"資源の略奪\"\n  STR_ALIEN_INFILTRATION: \"政府への侵入\"\n  STR_ALIEN_BASE: \"コロニーの拡大\"\n  STR_ALIEN_SURFACE_ATTACK: \"陸上への攻撃\"\n  STR_ALIEN_RETALIATION: \"浮遊基地の攻撃\"\n  STR_ALIEN_SUPPLY: \"コロニーの補給\"\n  STR_ALIEN_PROBE_MISSION_UFOPEDIA: \"エイリアンの調査ミッションは海底でそのエリア内の資源、航路そして空路等の情報収集を目的としている。{NEWLINE}{NEWLINE}調査ミッションに携わる潜水艇はさほど脅威ではないが、現地の状況はいつ他のエイリアンの注意を喚起するか判らない。\"\n  STR_ALIEN_INTERDICTION_UFOPEDIA: \"エイリアンは関心のある地域にまず先遣隊を送り、本格的なミッションの前にそのエリアを監視し、確実性を高めようとする。{NEWLINE}{NEWLINE}偵察任務のエイリアンは着艦した地域を封鎖し、次の段階の下準備をする。\"\n  STR_ALIEN_RESOURCE_RAID_UFOPEDIA: \"船舶と航空機への攻撃はエイリアンの基本戦略である。主目的は略奪であり、過度に攻撃的なのはその為である。同時に襲撃エリアの地熱の変動を計測し、採掘所や天然資源、精錬金属、さらに人類の生産資源が無いか調査する。\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"エイリアンは政府もしくは企業に対し最高レベルでの正式な折衝を実現させようとしている。この活動が最高潮に達すると、主要地域付近の水域で猛烈な潜水艇の活動が見受けられる。宇宙人は政府もしくは相手の組織に対し、協定にサインすれば自分たちの優れた技術を提供しても良いとアプローチする。{NEWLINE}{NEWLINE}この活動は、XComにとって最大の脅威である。もし人類側が協定を結べば、その組織からの資金の提供は停止される。\"\n  STR_ALIEN_BASE_UFOPEDIA: \"エイリアンは人里離れた海底にコロニーを建設する。建設の前には、まずその海域の調査が数回行われる。それからコロニー建設中には頻繁に輸送艇が行き来するのが確認される。コロニーには実験室、クローン工場、エイリアン及び人間の為の手術室が備えられる。宇宙人のコロニーがあれば、潜水艇が現れなくても、非常に多くの宇宙人の活動が報告されることになるだろう。{NEWLINE}{NEWLINE}コロニーの所在地を発見するには、偵察艇を目的の地域へ派遣し、数時間かけて同エリアをパトロールしなければならない。\"\n  STR_ALIEN_SURFACE_ATTACK_UFOPEDIA: \"エイリアンは必要に迫られると、港湾や島、船舶に襲撃をかける。彼らの繁殖や残酷な実験の為にその地域の民間人が直接狙われる。\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"もし、XComの潜水艇が敵潜水艇を撃沈した場合、エイリアンが何らかの報復活動を起こすかも知れない。XComの基地を直接攻撃してくる可能性もある。{NEWLINE}しかし基地を攻撃するためにはその位置を知らなければならないので、常に敵の潜水艇を遠ざけておけば、襲撃される危険はほとんどないはずである。\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"エイリアンのコロニーが建設されると、大型の輸送艇が定期的に物資の補給を行うために行き来する。{NEWLINE}{NEWLINE}もし着艦している輸送艇を発見したら、近くに宇宙人のコロニーが存在するはずだ。\"\n  STR_SURVEY_SHIP_UFOPEDIA: \"この小さな潜水艇は主として偵察や観測に用いられる。エイリアンが任務を開始する場合、この小型潜水艇を用いて初期の情報収集を行う。\"\n  STR_ESCORT_UFOPEDIA: \"この中型の偵察艇はXComにとって全く脅威とはなり得ない。防御力は弱く、武装も貧弱だからである。{NEWLINE}通常は襲撃任務の前に姿を現し、任務のための詳細な情報収集を行っている。\"\n  STR_CRUISER_UFOPEDIA: \"この大型の偵察艇はある程度強力な装甲と兵器を備えており、威力偵察などの任務に用いられる。\"\n  STR_HEAVY_CRUISER_UFOPEDIA: \"重巡洋艦は通常の巡洋艦よりも大型の船体と武装によって強化されている。{NEWLINE}重巡洋艦は大量の天然資源を獲得する為に造られている。\"\n  STR_HUNTER_UFOPEDIA: \"この宇宙船には誘拐した人間に対して、恐ろしい人体実験を行うための検査室や各種の実験用器具が備わっている。{NEWLINE}通常犠牲者は酷い拷問を受けた後、脳を取り除かれる。取り出された脳は移送されるまで保管される。\"\n  STR_BATTLESHIP_UFOPEDIA: \"戦艦はエイリアンが持つ艦艇の中で最も攻撃的なもので、あらゆるタイプのエイリアンのテクノロジーといかなる任務にも対応できる管制設備を併せ持ち、多種多様の兵器を備えている。\"\n  STR_DREADNOUGHT_UFOPEDIA: \"弩級戦艦は全てのエイリアンテクノロジーと膨大な量の兵器を搭載した超突撃艦である。{NEWLINE}重装甲であり、最大の難敵と言える。\"\n  STR_FLEET_SUPPLY_CRUISER_UFOPEDIA: \"補給艦は宇宙人コロニーへの各種物資の輸送に使用される。この船には食物やDNA、繁殖室及び生体用機材が備えられている。{NEWLINE}{NEWLINE}この補給艦が頻繁に現れるような場合は、どこかに新しいコロニーを建設していると思われる。\"\n  STR_DISMANTLE: \"施設を撤去する\"\n  STR_FACILITY_IN_USE: \"ドックは使用中です\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"この施設は撤去できません!{SMALLLINE}基地の全施設は、エア・ロックと直接または間接的に接続される必要があります。\"\n  STR_TRANSFER_ITEMS_TO: \"{0}にアイテムを移動する\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"隔離拘束施設がありません!{SMALLLINE}移動するエイリアンの生命を維持するためには、移動先の基地に隔離施設が必要です。\"\n  STR_AMOUNT_AT_DESTINATION: \"移動先の保有数\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"捕獲したエイリアンは基地に隔離拘束施設がないために死亡しました\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"居住区に空きがありません!{SMALLLINE}移動先の基地に、移動する潜水艇の搭乗員のための居住スペースを確保できません。\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"格納スペースがありません！{SMALLLINE}潜水艇に割り当てられた機材の格納スペースが輸送先の基地にありません\"\n  STR_ITEMS_ARRIVING: \"アイテム到着\"\n  STR_DESTINATION_UC: \"目的地\"\n  STR_DART_PISTOL: \"ダーツ・ガン\"\n  STR_DART_POD: \"ダーツガン弾倉\"\n  STR_JET_HARPOON: \"ジェット銛\"\n  STR_HARPOON_POD: \"銛マガジン\"\n  STR_GAS_CANNON: \"ガス・キャノン\"\n  STR_GC_AP_AMMO: \"GC-徹甲 ボルト\"\n  STR_GC_HE_AMMO: \"GC-炸薬 ボルト\"\n  STR_GC_P_AMMO: \"GC-リン ボルト\"\n  STR_HYDRO_JET_CANNON: \"水素ジェット・キャノン\"\n  STR_HJC_AP_AMMO: \"HJ-徹甲弾\"\n  STR_HJC_HE_AMMO: \"HJ-炸薬弾\"\n  STR_HJC_P_AMMO: \"HJ-リン弾\"\n  STR_TORPEDO_LAUNCHER: \"魚雷ランチャ\"\n  STR_SMALL_TORPEDO: \"小型魚雷\"\n  STR_LARGE_TORPEDO: \"大型魚雷\"\n  STR_PHOSPHOROUS_TORPEDO: \"リン魚雷\"\n  STR_MAGNA_BLAST_GRENADE: \"マグナブラスト手榴弾\"\n  STR_DYE_GRENADE: \"カラー手榴弾\"\n  STR_PARTICLE_DISTURBANCE_GRENADE: \"粒子干渉手榴弾\"\n  STR_MAGNA_PACK_EXPLOSIVE: \"マグナ収束手榴弾\"\n  STR_PARTICLE_DISTURBANCE_SENSOR: \"粒子干渉探知機\"\n  STR_MEDI_KIT: \"医療キット\"\n  STR_MC_DISRUPTOR: \"分子崩壊銃\"\n  STR_THERMAL_TAZER: \"凍結テーザー\"\n  STR_GAUSS_PISTOL: \"ガウス・ピストル\"\n  STR_GAUSS_PISTOL_CLIP: \"Gピストル用弾倉\"\n  STR_GAUSS_RIFLE: \"ガウス・ライフル\"\n  STR_GAUSS_RIFLE_CLIP: \"ガウスR用弾倉\"\n  STR_HEAVY_GAUSS: \"重ガウス・ライフル\"\n  STR_HEAVY_GAUSS_CLIP: \"HガウスR弾倉\"\n  STR_SONIC_CANNON: \"ソニック・キャノン\"\n  STR_CANNON_POWER_CLIP: \"Sキャノン弾倉\"\n  STR_SONIC_BLASTA_RIFLE: \"ソニック・ブラスター\"\n  STR_BLASTA_POWER_CLIP: \"Sブラスター用電池\"\n  STR_SONIC_PISTOL: \"ソニック・ピストル\"\n  STR_PISTOL_POWER_CLIP: \"Sピストル用電池\"\n  STR_DISRUPTOR_PULSE_LAUNCHER: \"崩壊波ランチャ\"\n  STR_DISRUPTOR_AMMO: \"Dランチャ弾倉\"\n  STR_THERMAL_SHOK_LAUNCHER: \"凍結ショック・ランチャ\"\n  STR_THERMAL_SHOK_BOMB: \"TSランチャ用爆弾\"\n  STR_SONIC_PULSER: \"衝撃波手榴弾\"\n  STR_ZRBITE: \"ザーバイト\"\n  STR_MC_READER: \"M.C.測定器\"\n  STR_VIBRO_BLADE: \"振動ブレード\"\n  STR_THERMIC_LANCE: \"ヒート・ランス\"\n  STR_HEAVY_THERMIC_LANCE: \"重ヒート・ランス\"\n  STR_AQUATOID_CORPSE: \"アクアトイドの死体\"\n  STR_GILLMAN_CORPSE: \"ギルマンの死体\"\n  STR_LOBSTERMAN_CORPSE: \"ロブスターマンの死体\"\n  STR_TASOTH_CORPSE: \"タソスの死体\"\n  STR_CALCINITE_CORPSE: \"カルシナイトの死体\"\n  STR_DEEP_ONE_CORPSE: \"深きものの死体\"\n  STR_BIODRONE_CORPSE: \"バイオドローンの死体\"\n  STR_TENTACULAT_CORPSE: \"テンタクラットの死体\"\n  STR_TRISCENE_CORPSE: \"トリシーンの死体\"\n  STR_HALLUCINOID_CORPSE: \"ハルシノイドの死体\"\n  STR_XARQUID_CORPSE: \"ザーカッドの死体\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"SWSを充填するのに十分な弾薬がありません。{SMALLLINE}それぞれのSWSには {0} {1}が必要です。\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"戦闘部隊の戦力を維持するための兵員または装備が不足しています\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"{1} を開発するには {0} を研究する必要がある。\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"エイリアンはXComの無防備な基地{0}を破壊した\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"XCom のエージェントは {0} にエイリアンのコロニーを発見した。\"\n  STR_STANDOFF: \"射程外\"\n  STR_CAUTIOUS_ATTACK: \" 慎重な攻撃\"\n  STR_STANDARD_ATTACK: \" 通常攻撃\"\n  STR_AGGRESSIVE_ATTACK: \" 猛攻撃\"\n  STR_DISENGAGING: \" 離脱\"\n  STR_UFO_HIT: \"敵潜水艇被弾!\"\n  STR_UFO_CRASH_LANDS: \"敵潜水艇撃沈!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \" 攻撃中は無効\"\n  STR_UFO_RETURN_FIRE: \"敵潜水艇反撃!\"\n  STR_INTERCEPTOR_DAMAGED: \"味方潜水艇破損\"\n  STR_INTERCEPTOR_DESTROYED: \"味方潜水艇撃沈\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"敵潜水艇は逃走中!\"\n  STR_LONG_RANGE_DETECTION: \"広域探知\"\n  STR_STORES_UC: \"在庫\"\n  STR_DIFFICULTY_LEVEL: \"難易度\"\n  STR_INTERCEPT: \"迎撃\"\n  STR_BASES: \"基地\"\n  STR_GRAPHS: \"グラフ\"\n  STR_UFOPAEDIA_UC: \"UFOペディア\"\n  STR_OPTIONS_UC: \"オプション\"\n  STR_FUNDING_UC: \"資金提供国\"\n  STR_5_SECONDS: \"5秒\"\n  STR_1_MINUTE: \"1分\"\n  STR_5_MINUTES: \"5分\"\n  STR_30_MINUTES: \"30分\"\n  STR_1_HOUR: \"1時間\"\n  STR_1_DAY: \"1日\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"XCom勤務表\"\n  STR_ENTER_NAME: \"名前を入力する\"\n  STR_PERFORMANCE_RATING: \"勤務評価\"\n  STR_VICTORY_DATE: \"勝利の日\"\n  STR_CHEMICAL_FLARE: \"ケミカル・フレア\"\n  STR_CHEMICAL_FLARE_UFOPEDIA: \"この発光器は、陸地および海底に落ちた瞬間にまばゆく発光する。深海で敵のユニットを発見するのに役立つ。\"\n  STR_MONTHLY_COSTS: \"毎月の費用\"\n  STR_CRAFT_RENTAL: \"潜水艇の維持費\"\n  STR_SALARIES: \"人件費\"\n  STR_BASE_MAINTENANCE: \"基地の維持費\"\n  STR_COST_PER_UNIT: \"ユニットごとの費用\"\n  STR_QUANTITY: \"数量\"\n  STR_TOTAL: \"合計\"\n  STR_IN_PSIONIC_TRAINING: \"M.C.インプラント手術中\"\n  STR_FRONT_ARMOR: \"前面装甲\"\n  STR_LEFT_ARMOR: \"左側装甲\"\n  STR_RIGHT_ARMOR: \"右側装甲\"\n  STR_REAR_ARMOR: \"背面装甲\"\n  STR_UNDER_ARMOR: \"下面装甲\"\n  STR_ROUNDS: \"発\"\n  STR_UNIT: \"ユニット> {0}\"\n  STR_ENERGY: \"スタミナ\"\n  STR_MORALE: \"士気\"\n  STR_ARMOR_: \"装甲> {0}\"\n  STR_FRONT_ARMOR_UC: \"正面装甲\"\n  STR_LEFT_ARMOR_UC: \"左側装甲\"\n  STR_RIGHT_ARMOR_UC: \"右側装甲\"\n  STR_REAR_ARMOR_UC: \"背面装甲\"\n  STR_SKILLS: \"スキル> {0}\"\n  STR_LEVEL: \"レベル> {0}\"\n  STR_HEAD: \"頭部\"\n  STR_TORSO: \"胴体\"\n  STR_RIGHT_ARM: \"右腕\"\n  STR_LEFT_ARM: \"左腕\"\n  STR_RIGHT_LEG: \"右足\"\n  STR_LEFT_LEG: \"左足\"\n  STR_PAIN_KILLER: \"鎮痛剤\"\n  STR_STIMULANT: \"興奮剤\"\n  STR_HEAL: \"治療\"\n  STR_TIME_UNITS_SHORT: \"TU>{ALT}{0}\"\n  STR_WEIGHT: \"重量>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"反応>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"M.スキル>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"M.強度>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"エイリアンの製造品\"\n  STR_AMMO_ROUNDS_LEFT: \"弾薬:弾丸残り={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"痛み>{ALT}{0}{ALT}興奮>{ALT}{1}{ALT}治療>{ALT}{2}\"\n  STR_THROW: \"投げる\"\n  STR_AUTO_SHOT: \"3連射撃\"\n  STR_SNAP_SHOT: \"急速射撃\"\n  STR_AIMED_SHOT: \"精密射撃\"\n  STR_STUN: \"気絶させる\"\n  STR_PRIME_GRENADE: \"時限設定\"\n  STR_USE_SCANNER: \"粒子干渉探知機\"\n  STR_USE_MEDI_KIT: \"医療キットを使う\"\n  STR_LAUNCH_MISSILE: \"魚雷発射\"\n  STR_ACCURACY_SHORT: \"命中精度>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"時間ユニットが足りません!\"\n  STR_NOT_ENOUGH_ENERGY: \"スタミナが足りません!\"\n  STR_NO_ROUNDS_LEFT: \"残弾がありません!\"\n  STR_NO_AMMUNITION_LOADED: \"弾が装填されていません!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"別の武器用の弾薬です!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"弾は既に装填されています!\"\n  STR_NO_LINE_OF_FIRE: \"射線上に障害あり!\"\n  STR_GRENADE_IS_ACTIVATED: \"手りゅう弾作動中!\"\n  STR_GRENADE_IS_DEACTIVATED: \"手りゅう弾解除！\"\n  STR_THERE_IS_NO_ONE_THERE: \"そこには誰もいません!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"研究終了まで使用できません!\"\n  STR_OUT_OF_RANGE: \"射程距離外です!\"\n  STR_UNABLE_TO_THROW_HERE: \"そこには投げられません!\"\n  STR_SET_TIMER: \"タイマーをセットする\"\n  STR_HIDDEN_MOVEMENT: \"エイリアン行動中\"\n  STR_TURN: \"ターン> {0}\"\n  STR_SIDE: \"サイド> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"ボタンを押して下さい\"\n  STR_MIND_CONTROL: \"分子制御\"\n  STR_PANIC_UNIT: \"インプラントを妨害する\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"精神攻撃に成功\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"インプラント・コントロール成功\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}が狂暴化した\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}が狂暴化した\"\n  STR_HAS_PANICKED_MALE: \"{0}はパニックに陥った\"\n  STR_HAS_PANICKED_FEMALE: \"{0}はパニックに陥った\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"エイリアン\"\n  STR_RIGHT_HAND: \"右手\"\n  STR_LEFT_HAND: \"左手\"\n  STR_RIGHT_SHOULDER: \"右肩\"\n  STR_LEFT_SHOULDER: \"左肩\"\n  STR_BACK_PACK: \"バックパック\"\n  STR_BELT: \"ベルト\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}は支配されている\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}は支配されている\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}は昏倒した\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}は昏倒した\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}は致命傷が原因で死亡した\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}は致命傷が原因で死亡した\"\n  STR_USE_MIND_PROBE: \"M.C.測定器を使う\"\n  STR_FATAL_WOUNDS: \"致命傷\"\n  STR_UNDER_ARMOR_UC: \"下面装甲\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"残りT.U.は急速射撃用リザーブ\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"残りT.U.は3連射撃用リザーブ\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"残りT.U.は精密射撃用リザーブ\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"屈みこむためのTUをリザーブする\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"屈みこみ射撃するためのTUをリザーブする\"\n  STR_UNITS_IN_CRAFT:\n    other: \"{N}Xcomの機体に居るユニット\"\n  STR_UNITS_OUTSIDE:\n    other: \"{N}外に居るユニット\"\n  STR_UNITS_IN_ENTRANCE:\n    other: \"{N}入り口に居るユニット\"\n  STR_UNITS_IN_EXIT:\n    other: \"{N}目標の出口に居るユニット\"\n  STR_ABORT_MISSION_QUESTION: \"任務を中断しますか?\"\n  STR_CORPSE: \"死体\"\n  STR_UNLOAD_CRAFT: \"弾薬を抜き取る\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}は死亡した\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}は死亡した\"\n  STR_HIT_MELEE: \"近接攻撃\"\n  STR_GROUND: \"着艦中\"\n  STR_LIVING_QUARTERS_PLURAL: \"居住区\"\n  STR_LIST_ITEM: \"アイテム\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"敵潜水艇の沈没でエイリアンが死亡し、自動回収された\"\n  STR_RESET: \"リセット\"\n  STR_MEMORIAL: \"墓碑\"\n  STR_DATE_UC: \"日付\"\n  STR_SOLDIERS_RECRUITED_UC: \"登庸した潜水兵 >{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"失った潜水兵 >{ALT}{0}\"\n  STR_REMOVE_SELECTED: \"選択範囲を消去\"\n  STR_LIVE_ALIENS: \"捕虜にした宇宙人\"\n  STR_DEAD_ALIENS: \"殺害した宇宙人\"\n  STR_UNDER_INTERROGATION: \"現在尋問中\"\n  STR_CONTAINMENT_EXCEEDED: \"隔離拘束施設の許容範囲を超えました！{SMALLLINE}収容スペースが{0} 人分不足しています。彼らが死んでしまう前に超過分のエイリアンを除去する必要があります\"\n  STR_MANAGE_CONTAINMENT: \"隔離拘束施設の管理\"\n  STR_STORAGE_EXCEEDED: \"格納スペースを超過しています！{SMALLLINE}{0}分スペースが足りません。アイテムを売ってください\"\n  STR_GO_TO_BASE: \"基地に戻る\"\n  STR_MELEE_ACCURACY: \"格闘精度\"\n  STR_SELL_PRODUCTION: \"売る\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"両手が空いていなければなりません!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"装備品のストックが足りません!\"\n  STR_UNLOAD_WEAPON: \"弾倉を外す\"\n  STR_ALL_ITEMS: \"選択可能なアイテム\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    other: \"これ以上、武器および装備を搭載することはできません!{SMALLLINE}輸送艇に搭載できるアイテムは{N}個に制限されています。\"\n  STR_CONTROL_CENTER_DESTROYED: \"コントロールセンターは破壊されました。入り口へ戻り、'任務中断'を実行してください。\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"X-COMの海底基地は陸地には建てられません\"\n  STR_UNABLE_TO_ENGAGE_DEPTH: \"この深度では敵と交戦できません\"\n  STR_UNABLE_TO_ENGAGE_AIRBORNE: \"空中では敵と交戦できません\"\n  STR_UNDERWATER_EQUIPMENT: \"この装備は水上では使用できません!\"\n  STR_LAND_EQUIPMENT: \"陸戦用装備\"\n  STR_LEVEL_SHORT: \"{0}L\"\n  STR_PERSONNEL: \"構成員\"\n  STR_CRAFT_ARMAMENT: \"軍備\"\n  STR_COMPONENTS: \"パーツ\"\n  STR_SOLDIERS_RECRUITED: \"雇用した潜水兵\"\n  STR_SOLDIERS_LOST: \"失った潜水兵\"\n  STR_TOTAL_UFOS: \"探知した敵飛行潜水艇\"\n  STR_TOTAL_ALIEN_BASES: \"発見した宇宙人コロニー\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"M.C.訓練\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"M.C.能力\"\n  FEMALE_CIVILIAN: \"民間人-女\"\n  MALE_CIVILIAN: \"民間人-男\"\n  DOCKER_CIVILIAN: \"民間人-労働者\"\n  SAILOR_CIVILIAN: \"民間人-船員\"\n  STR_BIODRONE_MELEE_WEAPON: \"バイオドローンの近接武器\"\n  HALLUCINOID_WEAPON: \"ハルシノイドの武器\"\n  STR_LOBSTERMAN_MELEE_WEAPON: \"ロブスターマンの近接武器\"\n  CALCINITE_WEAPON: \"カルシナイトの武器\"\n  DEEP_ONE_WEAPON: \"深きものの武器\"\n  STR_TRISCENE_MELEE_WEAPON: \"トリシーンの近接武器\"\n  STR_TRIBIO_SONIC_WEAPON: \"トリバイオの音波兵器\"\n  XARQUID_WEAPON: \"ザーカッドの武器\"\n  TENTACULAT_WEAPON: \"テンタクラットの武器\"\n  ZOMBIE_WEAPON: \"ゾンビの武器\"\n  ALIEN_PSI_WEAPON: \"エイリアンのPSI兵器\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/ko.yml",
    "content": "ko:\n  STR_LEVIATHAN_UFOPEDIA: \"대단한 잠항 능력을 지닌 수송 및 요격용 비행잠수함이다. 외계인과 인간 기술의 놀라운 합성 작품으로, 이온 추진 장치와 자기 배열 항법 장치를 활용한다.\"\n  STR_BARRACUDA_UFOPEDIA: \"초고열 레이저 엔진으로 움직이는, 브리티쉬 하이드로스페이스 사의 바라쿠다다. 세상에서 가장 빠른 요격선 중 하나로, 잠수 및 공중 비행 능력이 있어, 다가오는 전투의 핵심 기체다.\"\n  STR_HAMMERHEAD_UFOPEDIA: \"수송 및 요격용 기체다. X-COM 선박에 자기 배열 항법 장치를 재현했다. 비록 작지만, 그 설계는 경탄할 만한 기술적 성과다.\"\n  STR_TRITON_UFOPEDIA: \"트리톤은, 강습 분대 수송함으로, 온전한 공중 및 수중 항행 엔진이 달렸다. 그 커다란 수용량과 강인한 구조는 이걸 X-COM 함대의 주력이 되게 한다.\"\n  STR_MANTA_UFOPEDIA: \"이온 추진식 외계인 선박을 똑같이 모방한 1인승의 요격용 비행잠수함인, 만타 고속정이다. 고조되는 갈등에 대단히 효과적인 공격 기체다.\"\n  STR_AJAX_UFOPEDIA: \"에이잭스 어뢰는 세계 전역의 해저 전투에서 표준 무기다. 정확하고 강력한 억제 수단으로 활용된다.\"\n  STR_DUP_HEAD_UFOPEDIA: \"열화 우라늄 소결체 탄두 무기 기술은 상대적으로 새로운 것이고, 이것은 그걸 온전히 활용한 최초의 상업적 수중 무기 체계다.\"\n  STR_CRAFT_GAS_CANNON_UFOPEDIA: \"높은 장갑 관통 능력이 있는 경질 화살을 쏘는 압축 공기 구동 기관포 장치다.\"\n  STR_PWT_CANNON_UFOPEDIA: \"펄스파 어뢰는 초고온의 연소 장치와 대다수 합금을 뚫을 수 있는 엄청나게 조밀한 탄두를 활용한다.\"\n  STR_GAUSS_CANNON_UFOPEDIA: \"가우스 무기는 새롭게 개발된 X-COM 기술이다. 이 장치의 입자 가속기는 자그마하고, 액체 질소로 냉각되는, 핵융합 반응로로 작동된다.\"\n  STR_SONIC_OSCILLATOR_UFOPEDIA: \"강력한 음향 공진기는 소닉 에너지의 파동을 만든다. 분자 결합을 찢어서 표적을 파괴한다.\"\n  STR_AQUATOID_UFOPEDIA: \"세상을 향한 인간의 첫 부들거리는 발걸음이 있기 수천 년 전에 존재했었던, 아쿠아토이드 종족은 고대 사회의 일원이었다. 그들의 자그마한 형상과 풍선 같은 특징은 그들의 우주를 여행하는 형제, 섹토이드와 닮은꼴이다. 그들의 힘은 강력한 분자 제어 기술에 기반한다. 아쿠아토이드 종족은 유전자 조작으로 불임인 자기 종족을 전파하려 하며, 이상적인 표존은 인류가 되었다. 실험은 다수의 혼합 종족을 낳았다.\"\n  STR_AQUATOID_AUTOPSY: \"아쿠아토이드 검시\"\n  STR_AQUATOID_AUTOPSY_UFOPEDIA: \"이 생물에 대한 자세한 분석은 우리에게 약간의 기본적 가정을 하게 하였다. 그건 우리의 과거 적, 섹토이드이나, 해양 종족이 되기 위해 수술적 방법과 삽입물을 써서 변화되었다. 퇴화된 허파는 공기 호흡과 제한적인 지상 이동을 하게 한다. 몸 전체에 사이버네틱 삽입물이 있어, 그 위축된 사지의 근력과 장기의 기능을 강화한다. 이 종족의 모든 일원이 동일하기에,우리는 이 생물이 복제품이라는 가설을 세울 수 있다.\"\n  STR_GILLMAN_UFOPEDIA: \"파충 인류인 것으로 보이고, 인간과 아주 가깝게 관련된 거의 인간 같고, 이상한 생물이다. 이 생물은 해저 세계에서 엄청나게 힘세고 빠르다. 다양한 연령대의 남성 및 여성 표본이 있기에, 길맨은 성숙한 종족이다. 그들이 아무런 유전자 변화 또는 수술적 변형의 징후가 나타나지 않기에 그들은 수중 외계인의 주류 같지는 않다. 우리가 우리 인류의어떤 고대 아종을 보고 있는 지 모른다.\"\n  STR_GILLMAN_AUTOPSY: \"길맨 검시\"\n  STR_GILLMAN_AUTOPSY_UFOPEDIA: \"일단 수술을 시작했을 때 이게 전혀 외계인이 아니고, 지구 태생의 생물로, 포유류가 주류가 된 바로 그 시점에 멸종했다고 여겨졌던 과거의 선사 시대 종족임이 명확해졌다. 공룡이 포효했을 때 이 생물이 살았던, 길맨은 양서류이자, 지적이고, 힘이 세다. 이 행성에서 파충류의 지배를 끝장낸 대격변은 이 생물을 새롭게 도착했던 외계인과 공생 관계를 맺게 강제했다. 작은 전자 장치가 이 생물의 두개골 안에 끼워졌다.\"\n  STR_LOBSTERMAN_UFOPEDIA: \"이건 경이적인 생물로, 인간보다 더 크고 여섯 팔다리를 뽐내는, 그건 바다의 악마 그 이상도 이하도 아니다. 이 생물과 지구의 가재 사이의 유사성은 X-Com 병사들이 이것에게 랍스터맨이라는 별명을 짓게 하였다. 이건 심해의 거대 괴수다. 믿을 수 없는 근력과 실탄 사격에 실질적으로 무적인 주의 깊게 설계된 전투용 생물이다. 그 집게 단독으로 강철을 찌그러뜨릴 수 있다.\"\n  STR_LOBSTERMAN_AUTOPSY: \"랍스터맨 검시\"\n  STR_LOBSTERMAN_AUTOPSY_UFOPEDIA: \"과거에 한때 사실상 파괴할 수 없는 껍질이 씌워진 이 생물은 놀라운 구조물이다. 강력한 근육은 티타늄 골격 주변에 붙어 있고, 다중 대역 스캔 능력을 지닌 정교한 조준 장치는 이 생물의 두뇌에 직접 연결되었다. 그 겹눈은 강철보다 딱딱한 플라스틱에 의해 보호되며 그 주인에 의해 잘 배치될 때 이 생물이 거의 멈출 수 없다는 게 명확하다. 그 육체 내부에 깊숙이 묻혀 있는 건 미지의 구조 및 기능을 가진 장치다.\"\n  STR_TASOTH_UFOPEDIA: \"이 민첩하고 재빠른 적은 외계인 군대의 주력이다. 외계인 식민지의 핵심부 깊숙한 곳의 광대한 부화 용기에서, 수백 마리가 태어난다. 인간보다 훨씬 더 힘센, 타소쓰는 진정한 외계인이고 그 습성과 포식자의 본성은 이 행성에서 비할 게 없다. 타소쓰는 종종 외계인 공격에서 첨병을 형성하며 압도적인 곤란을 직면할 때조차 싸움에 결코 위축되지 않는 듯하다.\"\n  STR_TASOTH_AUTOPSY: \"타소쓰 검시\"\n  STR_TASOTH_AUTOPSY_UFOPEDIA: \"해부는 신기한 힘을 보유한 사이버네틱 생물을 드러냈다. 복강 내부는 작은 동력 장치가 있으나, 아무런 확인 가능한 장기도 없다. 동력은 생체전기 전송 장치에 의해 몸 구석구석으로 전달된다. 몸 전체는 뼈나 어떤 다른 지지 구조도 빠져 있다. 일단 죽으면 동력이 정지되며 이 생물은 흐물거리는 외계인 살점과 체액이 든 생기 없는 걸레 인형이 된다. 유일한 다른 내부 장기는 한 쌍의 세라믹 전지인데, 만약 활성화되면 이 생물을 일으키는 듯하다.\"\n  STR_DEEP_ONE_UFOPEDIA: \"딥원은 생물학적 재앙이자, 이종 교배의 산물로, 아쿠아토이드의 정신이 뒤틀리는 실험으로 제작되었다. 우리는 이 생물의 여러 변종과 마주쳤었다. 폭넓은 연구 후 우리는 이게 침략자들에 의해 제작되었다고 결론지었다. 신선한 인간 무리가 포획될 때 그들의 규모는 팽창한다. 이들 아인종 각각은 잠수요원을 죽이기 충분할 만큼 강력한 전기 에너지 방출기로 무장했다.\"\n  STR_DEEP_ONE_AUTOPSY: \"딥원 검시\"\n  STR_DEEP_ONE_AUTOPSY_UFOPEDIA: \"이 생물은 인간과 외계 생물을 접목한 것이다. 인간의 두뇌는 제어용 전자 장치와 외계인의 피질을 수용하기 위해 엄청나게 변경되었다. 인간 몸의 모든 흔적은 하나를 남기고 잃어버린 듯하다: 눈이다. 수술적 접목은 외계 태아가 성장하면서 인간 숙주를 삼키도록 하는 것으로 보인다. 이 생물의 억센 피부는 무기물인, 금속제 그물로, 엄청나게 강하고 유연한 것으로 보인다. 결과적인 혼종은 힘세고, 재빠르며 외계인의 제어에 절대 복종한다.\"\n  STR_BIODRONE_UFOPEDIA: \"바이오드론은 오직 외계인의 정신으로만 떠올릴 수 있었을 창조물이다. 그건 두뇌로(인간 또는 외계인의), 양수에 띄워졌고 육지 위나 물 속에서 날 수 있는 동력 받침에 연결되었다. 각각의 바이오드론은 강력한 음향 분열기로 무장했는데, 일부는 기계고 일부는 생체이다. 우리 과학자 일부는 이 무기가 숙주 생물의 원래 성대로 구동된다고 추측했었다. 대단히 정확하고 끈질긴 이 슈퍼 경비견은 외계인에 의해 소중한 자산을 보호하고자 널리 이용된다.\"\n  STR_BIODRONE_AUTOPSY: \"바이오드론 검시\"\n  STR_BIODRONE_AUTOPSY_UFOPEDIA: \"음향 분열기가 생물학적 장치라는 가설은 진실이다. 이 불운한 생물은 그 적에게 죽으라고 문자 그대로 비명을 지른다. 모든 표본은 엄청난 수술 흉터를 지니며 심각하게 훼손되었다. 외계인은 이 두뇌는 정해진 대로 도축한 것으로 보인다. 이 생물에 이용된 피질의 대부분은 외계인에게서 온 것이나, 어느 것도 인간 기반의 유닛을 발견했다는 끔직함에는 비교할 수 없다. 바이오드론은 이온 엔진에 의해 움직이며 어떤 형태의 원격 제어 장치를 내장한다.\"\n  STR_TENTACULAT_UFOPEDIA: \"러브크래프트산 악몽의 밑바닥조차 이러한 형용할 수 없는 생물을 태어나게 할 수 없었다. 어떠한 지구 동물과 아무런 비교가 되지 않고, 이와 같은 걸 만들 수 있는 환경은 상상 밖의 것이다. 긴 촉수로 무장한 텐타쿨러트는 피해자를 마비시키고 그들을 정신 나간 존재로 변환한다. 이 파종은 접촉 시 죽을 수 있고, 장갑조차 뚫는다. 텐타쿨러트는 X-Com이 지금까지 마주쳤던 가장 무시무시한 외계인이다.\"\n  STR_TENTACULAT_AUTOPSY: \"텐타쿨러트 검시\"\n  STR_TENTACULAT_AUTOPSY_UFOPEDIA: \"검시 결과는 이 생물의 커다란 두뇌에 끼워진 작은 사이버네틱 삽입물을 드러낸다. 시각은 가시광선 및 열영상 획득의 복잡한 조합이다. 대양의 흐릿한 심해 속에서조차 이 괴물은 오차 없는 정확도로 돌아다닐 수 있다. 생존을 위한 거의 최소한인 듯한 흔적 기관들이 있다. 각각의 생물은 외부 접속기가 있는 작은 위를 지니며, 이 존재가 주인에게 직접 양분 주입을 받아 육성된다고 가정하는 게 논리적이다.\"\n  STR_CALCINITE_UFOPEDIA: \"실종된 뱃사람의 잠수복과 비슷한 이 외계인은 해저에서 조심성 없는 이들을 쫓아다닌다. 이 생물의 강철보다 강한 손톱에 의한 잔혹한 휘둘러치기는 최고의 잠수부를 수장시키기에 충분할 수 있다. 안면 마스크 주변을 휘몰아치는 끈적거리는 녹색 형태가 보여질 수 있다. 우리가 그들과 가졌던 종종 치명적인 만남으로부터 이게 진짜 어떤 생물인 지에 대한 아무런 힌트도 추측할 수 없었다.\"\n  STR_CALCINITE_AUTOPSY: \"캘시나이트 검시\"\n  STR_CALCINITE_AUTOPSY_UFOPEDIA: \"일단 갑옷이 벗겨지자 캘시나이트는 거대한 비정형의 원형질 덩어리인 것이 드러났다. 아무런 눈에 보이는 두뇌도, 사지도, 감각 기관도 존재하지 않으며, 액체인 몸 깊숙한 곳에 작은 금속 부품이 자리한다. 일단 죽으면 우리는 이 생물의 본성에 대해 단지 추측만 할 수 있을 뿐이다. 우리 외계인 적의 풀리지 않는 수수께끼다.\"\n  STR_TRISCENE_UFOPEDIA: \"이 이족보행 파충류는 공룡의 시대를 떠오르게 한다. 그건 물 속과 땅 위에서 살아남을 능력을 보존한 여러모로 백악기의 생물인 듯하다. 이 생물은 무기 포드를 둘러메었고 거대한 금속 이빨이 줄지어 늘어선 아가리를 지닌다. 종종 이 괴물은 외계인이 지상에 강습을 걸 때 외계인 공격 부대의 핵심이 된다. 무게가 무겁고 강력한 무기로, 타소쓰 사령관은 그들을 놀라운 효율로 배치한다.\"\n  STR_TRISCENE_AUTOPSY: \"트라이신 검시\"\n  STR_TRISCENE_AUTOPSY_UFOPEDIA: \"일단 과학자의 칼날 앞에 선 트라이신은 자신이 고대의 생물이며, 사이버네틱 삽입물과 무기 체계의 보조를 받음을 드러낸다. 그 자그마한 두뇌는 이 생물이 착용한 제어 장치에 탑재된 작은 컴퓨터 모듈의 보조를 받는다. 억센 원래 피부, 추가적인 무기로 강화된 포식자의 본능은 이걸 모든 환경에서 치명적인 적으로 만든다.\"\n  STR_HALLUCINOID_UFOPEDIA: \"대양을 수확하는 외계인은 이 거대한 지구 생물을 무기로 육성했다. 이 무해하게 보이는 심해의 선원과 마주할 때 괜찮을 것이라는 착각에 빠지지 마라. 근접 전투용 냉기의 일격을 보유한, 할루시노이드는 위험한 적이다. \"\n  STR_HALLUCINOID_AUTOPSY: \"할루시노이드 검시\"\n  STR_HALLUCINOID_AUTOPSY_UFOPEDIA: \"이 생물이 지닌 여러 층의 끈적이는 몸 안에 들어있었던 건 강력한 화학 냉동기로, 그 주 공격 능력이다. 할루시노이드의 부드럽고 유연한 피부는 열 기반의 공격에 취약한 듯하다. 종종 이 돌연변이는 그 주인인, 아쿠아토이드 무리에서 발견된다.\"\n  STR_XARQUID_UFOPEDIA: \"또 다른 지구의 개조된 무척추동물인, 자퀴드는 대단히 아름다우면서도 위험한 생물이다. 이 빠르게 헤엄치는 괴수는 파괴적인 무기고를 감추고 있는데, 숨이 막히는 잉크 분사기와 이온화된 입자 방출기다. 이 강력한 생물과의 첫 만남부터 우리는 그 힘과 복수심에 불타는 길맨이라는 지휘자를 경계해 왔다.\"\n  STR_XARQUID_AUTOPSY: \"자퀴드 검시\"\n  STR_XARQUID_AUTOPSY_UFOPEDIA: \"이 과도하게 키워진 앵무조개는 외계인의 약물로 이루어진 식단과 수술에 의한 변형으로 거대하게 만들어졌다. 대자연의 범위를 벗어나 타락한, 길맨은 이 생물에 기계적 제어 장치를 더했고 이제 이 생물의 원래 본성은 아무 것도 존재하지 않는다. 유기체 무장 차량으로 배치된, 자퀴드의 억센 껍질과 기동력은 그걸 만만치 않은 적으로 만든다.\"\n  STR_ION_BEAM_ACCELERATORS_UFOPEDIA: \"외계인의 비행잠수함은 심해 속을 믿을 수 없는 속도로 달리게 하는 복잡한 동력계에 의존한다. 이 기술의 기반은 이온 추진기로, 지바이트를 촉매로 활용해, 이 엔진은 초당 자기 부피의 100배 만큼의 물을 밀어낸다. 이 막대한 힘은 외계인이 대다수 인류 잠수함을 추월할 능력이 있다는 뜻이다. 우리는 아쿠아 플라스틱과 지바이트 축전지를 이용해 이 장치를 재현할 수 있다.\"\n  STR_MAGNETIC_NAVIGATION_UFOPEDIA: \"이 장치는 구형의 다층 자기장을 생성하는데, 이 자기장 배열은 잠수함 주변 1000m에 이르도록 투영된다. 외계인 항법사는 기계와 직접 연결되며 파도 아래의 보이지 않는 세상 주변의 길을 느낀다. 인터페이스 장치는 신경 연결을 통해 기사의 두뇌와 직접 교신하는 외계인의 수정된 대뇌 피질을 이용해 조작한다.\"\n  STR_ALIEN_SUB_CONSTRUCTION_UFOPEDIA: \"각각의 함선은 카멜레온 같은 구조를 지니는데, 바다 생물을 주의 깊게 모방했고 아쿠아 플라스틱으로 건조된다. 각각의 잠수함은 생물처럼 동작한다: 승무원과 기체가 혼연일체로. 이 체계의 대부분은 재현 가능하고, 우리에게 동일한 정도의 기술 수준에 이르도록 해 주는 혼성 기술이 출현할 수 있다.\"\n  STR_ALIEN_CRYOGENICS_UFOPEDIA: \"지구에 숨겨져 있는 셀 수 없이 많은 외계인들은 극저온으로 냉동되어, 움직임이 정지된 상태로 보관된다. 모든 생물은 장치에 봉해지며, 그 신체 온도는 육체의 기능이 완전 정지되는 지점까지 내려간다. 지금까지 행해진 이 장치에 대한 실험은 그 육체가 믿을 수 없는 기간 동안 정지된 채 유지되었음을 드러내는데, 일부는 6000만년 이상 되었다.\"\n  STR_ALIEN_CLONING_UFOPEDIA: \"우리가 포획했던 외계인의 다수는 DNA 수준까지 동일하며, 모든 면에서 판박이다. 세포 견본은 외계인의 동결된 유전자 은행에서 이 장치에 넣어진다. 일부 장치는 인간 또는 신체 일부가 들어 있다. 이 복제 장치의 또 다른 용도가 어떤 외계인과 인간의 혼종을 만들기 위한 것일 수 있다.\"\n  STR_ALIEN_LEARNING_ARRAYS_UFOPEDIA: \"모든 외계인의 두개골에 있는 분자 제어 삽입물을 활용해 이 기계는 두뇌에 직접 정보를 주입한다. 막 복제된 외계인은 이 장치로 옮겨지고 그들의 텅 빈 정신에 종족의 기억과 모든 과학 또는 전투 정보가 기록된다.\"\n  STR_ALIEN_IMPLANTER_UFOPEDIA: \"이 장치는 외계인에 분자 제어 삽입물을 집어넣고, 번식할 수 있는 종족을 임신시키며, 어떠한 생물에게 장기 또는 전자 장치를 삽입 또는 제거하는 데 이용된다. 이 과정은 진정된 환자에게 행해진 것으로 여겨졌으나, 실험체는 이 과정을 아주 잘 인식하며 불행하게도 인간의 신체 구조는 이 장치에 완벽하게 맞는 듯하다.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"우리는 이제 외계인이 왜 인간을 포획하는지 알아내는 데 필요한 증거가 있다. 그들은 식량이 아니고, 외계 배아로 수태되지도 않는 대신, 포획된 인간은 생물 및 제어 장치의 기초를 형성한다. 외계 기술은 공통의 정신, 공유되는 지식에 기반하며 인간의 두뇌는 이 체계에서 이상적인 수용체다. 인간의 뇌 조직은 외계인의 생물 컴퓨터의 기록 및 입출력 장치의 대부분에 이용된다. 남은 부분은 건축 및 양육에 이용된다.\"\n  STR_AQUA_PLASTICS_UFOPEDIA: \"외계인의 잠수함과 구조물은 자기들의 구조물 대다수에 믿을 수 없이 강력하고, 유연하며, 튼튼한 재료를 활용한다. 아쿠아 플라스틱은 복잡한 다중 결합체이며 지바이트로 변성된 재료다. 조밀하면서도, 동시에 가벼운, 이 물질은 티타늄이나 케블라보다도 높은 강도를 지닌다.\"\n  STR_ZRBITE_UFOPEDIA: \"이건 외계 기원의 합금으로, 일부는 금이고 일부는 외계의 생물 재료다. 동력원으로 활용될 때, 이 물질 소량은 같은 크기인 단위 핵연료의 10배 이상의 동력을 생성할 것이다. 그 성분의 대부분이 외계에서 온 것이기에 이 재료를 재현하는 것은 우리의 기술적 역량을 넘어선다.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"무자비한 효율로, 외계인은 지구 전역을 타격한다. 우리는 그들의 원천을 집어낼 수 없다. 그게 우리에게 있어 뚫고 들어갈 수 없을 만큼 깊은 자리에 있을까? 우리가 마주쳤던 모든 생명체가 외계인은 아닌데, 일부는 아주 오래된 것이며, 일부는 오래 전 멸종했다고 여겨진 진화의 경로에서 왔다. 우리는 인간과 외계인이 미묘한 공생 관계였던, 수천 년 전부터 동면해 왔던 위협을 처리하고 있다. 대양의 깊숙한 곳에 외계인이 자신들의 우주 친척들과 접촉하기 위해 이용했던 고대 유적이 놓여 있다. 그 12개 현장 각각은 강력한 외계인의 장치인, 시노미움 장치가 들어 있다. 이제 외계인의 전쟁 기계가 진군하면서 그들은 자신들의 분자 제어망을 확대하고자 이 현장을 다시 활성화시키고 있어, 우리는 어떠한 대가를 치르더라도 이 현장을 반드시 부수어야 한다.\"\n  STR_THE_ULTIMATE_THREAT_UFOPEDIA: \"6500만년 전 광대한 식민선이 머나먼 외계인의 세상에서 지구로 보내졌었다. 그 엄청난 기체가 이 미숙한 행성에 접근하는 동안 엄청나게 크고 격렬한 태양풍이 항법 장치의 고장을 일으켰다. 비틀거리고 망가진 이 광대한 덩어리는 백악기의 하늘에 출현해 성층권으로 곤두박질쳤다. 지구 상의 셀 수 없는 생명을 가진 종족들은 자신들의 파멸이 이 행성을 갈아엎는 동안 하늘에서 눈을 떼지 못했다. 광대한 먼지 구름이 대기권을 뒤덮었고 땅이 식으면서 지구를 지배하던 생명체인, 강대한 공룡은, 사라졌다. 그러나 4000억 톤의 티'레쓰는 충격으로 부서지지 않았었고, 정교한 슈퍼컴퓨터는 깊숙한 곳에 담고 있는 생물에 대한 극저온 냉동 절차를 개시했다. 세월이 지나면서 그 컴퓨터는 자기들의 우주 사촌과 교신을 시도하려고 외계인 무리를 깨웠으나, 외계인 힘의 중심이 잠들었었기에 무산되었다.\"\n  STR_TLETH_THE_ALIEN_CITY: \"외계인의 도시 티'레스\"\n  STR_TLETH_THE_ALIEN_CITY_UFOPEDIA: \"티'레쓰, 거대한 외계인 식민선은, 멕시코 만 지그스비 분지 속에 놓여 있다. 그 도시의 심장부는, 죽음조차 피해갈 만큼 비열하고 강력한 외계인의 공포다. 외계 금속으로 된 방에는 위대한 몽상가, 궁극 외계인의 동면체가 놓여 있다. 티'레쓰를 파도 위로 들어 올리는 것은 그것의 부활 절차를 시작할 것이고, 일단 깨어나면 저지할 수 없을 것이다. 비록 살아있지 않고 어쩐지 죽지도 않았음에도 외계인의 정신은 외계인 군대를 통솔한다. 분자 제어라는 이상한 기술은 모든 외계인을 하나의 마음과 연결하고 하나의 마음을 모든 외계인에 연결한다. 유전적으로 변이된 외계인/인간 배아는 외계인 정신에 에너지를 보급하고 지배자와 그 수하들 사이의 연결을 형성한다. 궁극 외계인에 대한 신화는 수 세기에 걸쳐 인류의 가슴과 마음 속에 존재했었으나, 바다는 언제나 최후의 진실을 숨겼었다.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"현장을 화면 가운데로-시간=5초\"\n  STR_CANCEL_UC: \"취소\"\n  STR_NONE: \"없음\"\n  STR_UNKNOWN: \"불명\"\n  STR_POOR: \"나쁨\"\n  STR_AVERAGE: \"보통\"\n  STR_GOOD: \"좋음\"\n  STR_EXCELLENT: \"훌륭함\"\n  STR_BUILD_NEW_BASE_UC: \"새 기지 짓기\"\n  STR_BASE_INFORMATION: \"기지 정보\"\n  STR_EQUIP_CRAFT: \"비행잠수함 정비\"\n  STR_BUILD_FACILITIES: \"시설 건설\"\n  STR_RESEARCH: \"연구\"\n  STR_MANUFACTURE: \"제조\"\n  STR_TRANSFER_UC: \"이송\"\n  STR_PURCHASE_RECRUIT: \"구매/고용\"\n  STR_SACK: \"해고\"\n  STR_SELL_SACK_UC: \"매각/해고\"\n  STR_GEOSCAPE_UC: \"지구 화면\"\n  STR_NAME: \"이름\"\n  STR_AREA: \"영역\"\n  STR_BUILD_NEW_BASE: \"새 기지 짓기\"\n  STR_CANCEL: \"취소\"\n  STR_COST_UC: \"비용>\"\n  STR_CONSTRUCTION_TIME_UC: \"건설 시간>\"\n  STR_DAY:\n    other: \"{N} 일\"\n  STR_HOUR:\n    other: \"{N} 시간\"\n  STR_MAINTENANCE_UC: \"유지비>\"\n  STR_OK: \"확인\"\n  STR_INSTALLATION: \"설비\"\n  STR_CURRENT_RESEARCH: \"현재 연구\"\n  STR_SCIENTISTS_AVAILABLE: \"쓸 수 있는 과학자>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"할당된 과학자>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"쓸 수 있는 연구 공간>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"연구 과제\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"할당된 과학자\"\n  STR_PROGRESS: \"진도\"\n  STR_NEW_PROJECT: \"새로운 과제\"\n  STR_CANCEL_PROJECT: \"과제 취소\"\n  STR_NEW_RESEARCH_PROJECTS: \"새로운 연구 과제\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"쓸 수 있는 과학자>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"쓸 수 있는 연구 공간>{ALT}{0}\"\n  STR_INCREASE: \"증가\"\n  STR_DECREASE: \"감소\"\n  STR_START_PROJECT: \"과제 시작\"\n  STR_CURRENT_PRODUCTION: \"현재 생산\"\n  STR_ENGINEERS_AVAILABLE: \"쓸 수 있는 기술자>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"할당된 기술자>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"쓸 수 있는 작업 공간>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"현재 자금>{ALT}{0}\"\n  STR_ITEM: \"물품\"\n  STR_ENGINEERS__ALLOCATED: \"할당된{NEWLINE}기술자 수\"\n  STR_UNITS_PRODUCED: \"생산된{NEWLINE}유닛\"\n  STR_TOTAL_TO_PRODUCE: \"생산하려는 총수\"\n  STR_COST__PER__UNIT: \"유닛{NEWLINE}당{NEWLINE}비용\"\n  STR_DAYS_HOURS_LEFT: \"남은 기간\"\n  STR_NEW_PRODUCTION: \"새로운 생산\"\n  STR_PRODUCTION_ITEMS: \"생산 물품\"\n  STR_CATEGORY: \"분류\"\n  STR_START_PRODUCTION: \"생산 시작\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"유닛 하나 생산하는 데 {0} 인시\"\n  STR_COST_PER_UNIT_: \"유닛 당 비용>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"요구되는 작업 공간>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"요구되는 특별 재료\"\n  STR_ITEM_REQUIRED: \"요구되는 물품\"\n  STR_UNITS_REQUIRED: \"요구되는 개수\"\n  STR_UNITS_AVAILABLE: \"쓸 수 있는 개수\"\n  STR_STOP_PRODUCTION: \"생산 정지\"\n  STR_ENGINEERS_AVAILABLE_UC: \"쓸 수 있는 기술자>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"쓸 수 있는 작업 공간>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"월 수익>{ALT}{0}\"\n  STR_INCREASE_UC: \"증가\"\n  STR_DECREASE_UC: \"감소\"\n  STR_UNITS_TO_PRODUCE: \"생산할{NEWLINE}개수\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"구매/직원 고용\"\n  STR_COST_OF_PURCHASES: \"구매 비용>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"단가\"\n  STR_QUANTITY_UC: \"수량\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"쓸 수 있는 직원:총 직원>\"\n  STR_SOLDIERS: \"잠수요원\"\n  STR_SCIENTISTS: \"과학자\"\n  STR_ENGINEERS: \"기술자\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"사용된 공간:쓸 수 있는 공간>\"\n  STR_LIVING_QUARTERS: \"생활관\"\n  STR_STORES: \"창고\"\n  STR_LABORATORIES: \"연구실\"\n  STR_WORK_SHOPS: \"작업실\"\n  STR_HANGARS: \"비행잠수함 격납고\"\n  STR_SHORT_RANGE_DETECTION: \"단거리 소나\"\n  STR_DEFENSE_STRENGTH: \"방위력\"\n  STR_TRANSFERS_UC: \"이송\"\n  STR_TRANSFERS: \"이송\"\n  STR_ARRIVAL_TIME_HOURS: \"도착 소요시간(시간)\"\n  STR_COST_: \"비용>{ALT}{0}\"\n  STR_AREA_: \"영역>{ALT}{0}\"\n  STR_BASE_NAME: \"기지 이름?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"기밀 출입구 위치 지정\"\n  STR_TRANSFER: \"이송\"\n  STR_AMOUNT_TO_TRANSFER: \"이송하려는 양\"\n  STR_SELECT_DESTINATION_BASE: \"행선지 기지 선택\"\n  STR_COST: \"비용\"\n  STR_INTRO_1: \"Copyright 1995 MicroProse\"\n  STR_INTRO_2: \"화성: 사이도니아의 함락.\"\n  STR_INTRO_3: \"승리를 거둔 X-Com은, 외계인 전쟁 기계의 가장 중심부를 부수었고, 귀환을 위해 발진했다. 그렇지만, 폐허가 된 화성 기지 안의 전부가 죽지는 않았다.\"\n  STR_INTRO_4: \"강력한 타키온 빔이 사이도이나에 있는 신경 중추의 잔해로부터 흘러나온다 - 공허 속을 가르며. 그 행선지는............\"\n  STR_INTRO_5: \"지구다.\"\n  STR_INTRO_6: \"대양 속 심해에 그 빔은 오랫동안 잠든 수신기를 때린다. 광대한 수면 중인 컴퓨터가 작동을 시작한다. 심해 속, 인간의 시야 너머에서, 잠자는 외계인이 든 광대한 방은 오랜 재활 절차를 시작한다.\"\n  STR_INTRO_7: \"2040년: 무관심한 지구다. 외계인 전쟁에 대한 공포는 잊혀졌다. 그러나, 대양의 잊혀지고 숨겨진 장소 안에서 외계인 무리는 준비를 한다 - 인류를 썰어버리고 세상을 지배할 준비를.\"\n  STR_INTRO_8: \"외계인은 인류를 공격한다; 그들의 왜곡된 실험의 표본을 찾고자; 소중한 광물 및 자원을 위해 지구를 약탈하고자; 그리고 바다를 탈취하고자. 그리고, 외계인은 파도 위로 시선을 돌린다.\"\n  STR_INTRO_9: \"신기한 모양의 강력한 비행잠수함이 대양을 누빈다 - 보고, 찾으며, 사냥하면서.........\"\n  STR_INTRO_10: \"먹잇감을 찾으면 그들은 공격한다.\"\n  STR_INTRO_11: \"이상한 신무기는 무방비한 세상에 효과적으로 쓰인다. 우리는 외계인의 위협에 자비를 구할 뿐이다.{NEWLINE}오직 한 조직만이 우리를 구할 수 있다; 그러나, 우리는 오래 전 그들에게서 등을 돌렸다......\"\n  STR_INTRO_12: \"X-COM 시제 수중 시설\"\n  STR_INTRO_13: \"'메이데이! 메이데이!' '여기는 대서양 횡단 여객선 하이페리온'. '우리는 공격 받고 있다'. '메이데이! 메이데............'\"\n  STR_INTRO_14: \"'지휘통제실에서 1번 격납고에: 갑문 개방', '바라쿠다 제로 원 발진. 외계인 공격 상황이다 - 실제 상황이다'.{NEWLINE}'반복한다: 실제 상황이다'\"\n  STR_INTRO_15: \"외계인은 효율 면에서 무자비할 정도이고....\"\n  STR_INTRO_16: \"...정확도 면에서 오차가 없다\"\n  STR_INTRO_17: \"'바라쿠다 제로 원에서 본부에' - '하이페리온 잔해에 접근 중'.\"\n  STR_INTRO_18: \"'감속 개시'.{NEWLINE}'2미터'{NEWLINE}'1미터'{NEWLINE}'모든 잠수요원은 즉각 배치 준비'.\"\n  STR_INTRO_19: \"...........'기밀 출입구 개방'...'잔해에 접근한다'.{NEWLINE}'세상에!'{NEWLINE}'내 잠수복 카메라에 찍힌 저 생물 봤어?'\"\n  STR_GAMEOVER_1: \"우리는 실패했고, 외계인은 구원에 대한 우리의 마지막 희망을 소멸시켰다.{NEWLINE}X-Com은 멸망했고 지구는 고대 적의 발 아래에 놓였다.\"\n  STR_GAMEOVER_2: \"티'레쓰는 성층권으로 치솟았고 세계의 이곳 저곳으로 이동하기 시작한다. 죽음을 퍼트리고 남은 인류를 수확하면서. 그 내부의 깊은 곳에서 잔혹한 외계인 정신이 스스로 깨어나기 시작한다.\"\n  STR_GAMEOVER_3: \"모든 국가의 수도에서 비상 계획이 작성되었다. 그 모든 건 수포로 돌아갔는데, X-Com 연구 과제로 도출된 기술이 없는 우리 무기는 효과가 없었다.\"\n  STR_GAMEOVER_4: \"외계인은 극관에 기지를 세우고 얼음을 녹이기 시작했으며, 세계는 광대한 바다가 될 것이다. 남은 인류는 모여서 미지의 외계인을 위한 사악한 교배 실험에 활용되었다. 하늘은 어두워지고 강력한 전염병은 지구의 땅을 덮는다.\"\n  STR_GAMEOVER_5: \"우리는 새로운 세계 질서에 어떠한 저항도 할 수 없고, 저항을 시도하는 자들은 이해할 수 없는 외계인의 무기 앞에 가혹한 운명을 맞이한다. 남은 이들에게는 이러한 축복 받은 해방이 없으며, 어머니 지구는 외계인의 세상이 되었고 인류는 천천히 다가오는 공포 아래 길을 잃었다.\"\n  STR_OUTRO_1: \"그 무덤은, 처참하게 부서졌고, 부글부글 끓는 듯한 외침이 중심부에 놓인 관에서 터져 나온다.{NEWLINE}바보들 너희는 전부 죽으리라....................\"\n  STR_OUTRO_2: \".................아무도 탈출할 수 없었다.\"\n  STR_OUTRO_3: \"엄청나게 큰 폭발이 무덤에서 발생하고 도시를 찢어발겼고, 잔해와 매연이 공기를 채운다. 외계인의 계획은 좌절되었다........\"\n  STR_OUTRO_4: \"뒤틀리는 티'레쓰의 거대한 덩어리는 찢어지기 시작한다. 화염과 매연이 그 반짝이는 첨탑과 아다만티움제 광장에서 뿜어져 나온다.\"\n  STR_OUTRO_5: \"거대한 외계인의 요새는 바다를 향해 무너져 내리고, 뒤틀린 금속과 고통받는 영혼이 내는 비명이 공기를 채운다. 더 이상 위대한 몽상가는 세계를 지배한다는 꿈을 꿀  수 없을 것이다.\"\n  STR_OUTRO_6: \"최후의 고막을 찢는 충격음이 있었고 티'레쓰는 스스로 갈라졌다.{NEWLINE}외계인의 위협은 사라졌고, 지구는 정화되었다..................\"\n  STR_OUTRO_7: \"우리 은하의 외딴 구석, 고요한 청록색의 행성.\"\n  STR_OUTRO_8: \"가까운 미래, 안전한 장소가 된\"\n  STR_OUTRO_9: \"지구를 향한 외계인의 위협은 오래 전에 극복해냈다.\"\n  STR_OUTRO_10: \"거대한 광역시와 같은 도시는 북적거리는 수십억 명의 인류를 수용한다.\"\n  STR_OUTRO_11: \"X-Com의 위업과 외계인 전쟁은 어린이용 동화의 소재이다.\"\n  STR_OUTRO_12: \"그러나 전설은 언제나 한 줌의 진실을 담는 경향이 있었다............\"\n  STR_RISE_1: \"티'레쓰, 여러 지방의 많은 전설에서 여러 이름으로 불렀다.\"\n  STR_RISE_2: \"지구 전체를 울리는 폭발적인 비명과 함께 티'레쓰는 바다 밑에서 떠오르기 시작한다.\"\n  STR_RISE_3: \"그 거대하고 웅장한 구조물은 멕시코 만의 물을 가르며 솟구친다.\"\n  STR_RISE_4: \"4000억 톤의 외계 금속으로 이루어진, 궁극 외계인의 잠든 몸이 놓인 강력한 외계인의 도시다. 6500만년 동안 지구에 갇힌 이 강력한 우주 신은 기지개를 켜기 시작한다.\"\n  STR_RISE_5: \"위대한 몽상가의 무덤이 빛을 보면서 물은 일렁이며 끓어오른다................\"\n  STR_RISE_6: \".........X-Com이 외계인의 전쟁 기계를 파괴할 수 없다면 오래 갈 수 없을 빛으로.\"\n  STR_YOU_HAVE_FAILED: \"당신은 외계인의 전쟁 기계를 저지하는 데 실패했다. 후원 기구는 당신의 무능함에 넌더리를 내며 외계인과 비군사적 해법을 협상하려 시도한다. 침략자들은 아주 다른 안건을 올렸고, 곧 온 세상이 진실을 알게 된다...\"\n  STR_TOTAL_UC: \"합계\"\n  STR_INCOME: \"수입\"\n  STR_EXPENDITURE: \"지출\"\n  STR_MAINTENANCE: \"유지비\"\n  STR_BALANCE: \"수지\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"해역 별 외계인 활동\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"구역 내 외계인 활동\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"해역 별 X-Com 활동\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"구역 내 X-Com 활동\"\n  STR_FINANCE: \"재정\"\n  STR_DATE_FIRST: \"{0}일\"\n  STR_DATE_SECOND: \"{0}일\"\n  STR_DATE_THIRD: \"{0}일\"\n  STR_DATE_FOURTH: \"{0}일\"\n  STR_FINANCE_THOUSANDS: \"$1000's\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"{1}{NEWLINE}에서{NEWLINE}{0}{NEWLINE}의 생산을 위한 특별 재료가 부족하다\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"{1}{NEWLINE}에서{NEWLINE}{0}{NEWLINE}의 생산을 위한 돈이 부족하다\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"{1}{NEWLINE}에서{NEWLINE}{0}{NEWLINE}의 생산을{NEWLINE}마쳤다\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"{1}{NEWLINE}에서{NEWLINE}{0}{NEWLINE}의 건설을{NEWLINE}마쳤다\"\n  STR_OK_5_SECONDS: \"확인 - 5초\"\n  STR_RESEARCH_COMPLETED: \"연구 완료\"\n  STR_VIEW_REPORTS: \"보고서 열람\"\n  STR_WE_CAN_NOW_RESEARCH: \"이제 아래를 연구할 수 있다\"\n  STR_WE_CAN_NOW_PRODUCE: \"이제 아래를 생산할 수 있다\"\n  STR_SUNDAY: \"일요일\"\n  STR_MONDAY: \"월요일\"\n  STR_TUESDAY: \"화요일\"\n  STR_WEDNESDAY: \"수요일\"\n  STR_THURSDAY: \"목요일\"\n  STR_FRIDAY: \"금요일\"\n  STR_SATURDAY: \"토요일\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"{2}에서 {1}에 주유하기 위한 {0}가 충분하지 않다\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"{2}에서 {1}를 재무장하기 위한 {0}이 충분하지 않다\"\n  STR_UFO_IS_NOT_RECOVERED: \"외계인의 비행잠수함이 회수되지 않았다\"\n  STR_UFO_IS_RECOVERED: \"외계인의 비행잠수함은 회수되었다\"\n  STR_CRAFT_IS_LOST: \"비행잠수함을 잃었다\"\n  STR_TERROR_CONTINUES: \"외계인 활동이 계속된다\"\n  STR_ALIENS_DEFEATED: \"외계인은 물러났다\"\n  STR_BASE_IS_LOST: \"기지를 잃었다\"\n  STR_BASE_IS_SAVED: \"기지는 무사하다\"\n  STR_ALIEN_BASE_STILL_INTACT: \"외계인 식민지는 여전히 활동한다\"\n  STR_ALIEN_BASE_DESTROYED: \"외계인 식민지를 부수었다\"\n  STR_ALIENS_KILLED: \"죽인 외계인\"\n  STR_ALIEN_CORPSES_RECOVERED: \"회수한 외계인 시체\"\n  STR_LIVE_ALIENS_RECOVERED: \"회수한 살아있는 외계인\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"회수한 외계인 유물\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"부순 외계인 식민지 제어부\"\n  STR_ALIEN_SYNOMIUM_DEVICE_DESTROYED: \"부순 외계인 시노미움 장치\"\n  STR_ALIEN_SYNOMIUM_DEVICE_FAILED: \"시노미움 장치 파괴 실패\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"외계인이 죽인 민간인\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"X-COM 요원이 죽인 민간인\"\n  STR_CIVILIANS_SAVED: \"구출한 민간인\"\n  STR_XCOM_OPERATIVES_KILLED: \"죽은 X-COM 요원\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"작전 중 실종된 X-COM 요원\"\n  STR_TANKS_DESTROYED: \"부서진 X-COM 무장 잠수정\"\n  STR_XCOM_CRAFT_LOST: \"잃어버린 X-COM 비행잠수함\"\n  STR_UFO_RECOVERY: \"외계인 비행잠수함 회수\"\n  STR_ALIEN_BASE_RECOVERY: \"외계인 식민지 회수\"\n  STR_BASE_UNDER_ATTACK: \"{0} 기지가 공격을 받는다!\"\n  STR_BASE_DEFENSES_INITIATED: \"기지 방어 개시\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"방어막이 외계인 비행잠수함을 밀어냄!\"\n  STR_FIRING: \"발포\"\n  STR_HIT: \"명중!\"\n  STR_UFO_DESTROYED: \"외계인 비행잠수함 파괴!\"\n  STR_MISSED: \"빗나감!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"물품 매각/직원 해고\"\n  STR_VALUE_OF_SALES: \"판매가> {ALT}{0}\"\n  STR_FUNDS: \"자금> {ALT}{0}\"\n  STR_SELL_SACK: \"매각/해고\"\n  STR_VALUE: \"가격\"\n  STR_CRAFT_: \"비행잠수함> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}호\"\n  STR_UFO_CRASH_RECOVERY: \"외계인 비행잠수함 잔해 회수\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"각별한 주의 - 잠수함 안과 현장 주변에 외계인이 있을 것이다. 이 임무는 모든 적 유닛이 제거되거나 무력화될 때 완료될 것이다. 외계인 비행잠수함의 잔해, 기술 및 외계인 시체에 대한 회수는 이후에 개시될 것이다. 임무를 중단하려면 X-Com 잠수요원을 비행잠수함으로 보내고 '임무 중단' 아이콘을 눌러라.\"\n  STR_UFO_GROUND_ASSAULT: \"외계인 비행잠수함 강습\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"착지 현장을 탐험하고, 만약 가능하다면, 외계인 비행잠수함에 진입하라. 이 임무는 모든 적 유닛이 제거되거나 무력화될 때 완료될 것이다. 외계인 비행잠수함, 기술 및 외계인 시체에 대한 회수는 이후에 개시될 수 있다. 임무를 중단하려면 X-Com 잠수요원을 비행잠수함으로 보내고 '임무 중단' 아이콘을 눌러라.\"\n  STR_BASE_DEFENSE: \"기지 방어\"\n  STR_BASE_UC_: \"기지> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"외계인 함선 하나가 근처에 착지했다. 우리 기지는 심각한 위험에 처해 있다. 표준 절차에 따라 모든 비전투 직원과 작동하는 X-Com 비행잠수함은 대피했다. 외계인은 비행잠수함 격납고 갑문 또는 기밀 출입구를 통해 기지로 들어올 것이다. 무슨 수를 쓰더라도 기지와 중요 설비를 방어하라 - 이것은 목숨을 건 싸움이다. 만약 '임무 중단' 아이콘을 누르면 당신은 패배를 인정하고 기지를 잃을 것이다.\"\n  STR_ALIEN_COLONY_ATTACK_MISSION: \"외계인 식민지 공격 임무\"\n  STR_ALIEN_BASE_ASSAULT: \"외계인 식민지 제1부\"\n  STR_ALIEN_COLONY_P1_BRIEFING: \"이 임무는 외계인 식민지 현장에 대한 습격이다. 이 현장에는 2개의 층이 있고, 진행하려면 모든 잠수요원을 첫 번째 단지 내의 반짝이는 출구에 놓고 '임무 중단' 아이콘을 눌러라. 어떠한 남겨진 장비도 2번째 구역이 해결될 때까지 해저에 남아 있을 것이다. 이탈하려면, 잠수요원을 비행잠수함 안에 배치하고 '임무 중단' 아이콘을 눌러라.\"\n  STR_ALIEN_COLONY_P2: \"외계인 식민지 제2부\"\n  STR_ALIEN_COLONY_P2_BRIEFING: \"첫 번째 층을 통과했고 식민지의 중심부에 들어갔다. 이 임무는 이제 제어부, 시노미움 장치를 부수거나, 모든 외계인을 제거하는 것이다. 중단하려면 모든 잠수요원을 시작 지점으로 보내고 '임무 중단' 아이콘을 눌러라. 쓸 수 있는 모든 X-Com 장비는 기지로 돌아올 것이다.\"\n  STR_ALIENS_LAUNCH_PORT_TERROR: \"외계인은 아래의 항구에{NEWLINE}공격을 감행한다\"\n  STR_PORT_TERROR: \"외계인이 항구에 공격을 감행한다\"\n  STR_PORT_TERROR_BRIEFING: \"외계인은 지상 현장에 대해 공격을 감행했다. 항구와 그곳의 민간인은 위험에 처했다. 당신의 분대는 모든 외계인을 반드시 제거하고 이 외계인 침략으로부터 무고한 행인들을 보호해야 한다. 이탈하려면, 잠수요원을 비행잠수함 안에 배치하고 '임무 중단' 아이콘을 눌러라.\"\n  STR_ALIENS_LAUNCH_ISLAND_TERROR: \"외계인은 아래의 섬에{NEWLINE}공격을 감행한다\"\n  STR_ISLAND_TERROR: \"외계인이 섬에 공격을 감행한다\"\n  STR_ISLAND_TERROR_BRIEFING: \"외계인은 지상 현장에 대해 공격을 감행했다. 이 섬과 그곳의 민간인은 위험에 처했다. 당신의 분대는 모든 외계인을 반드시 제거하고 이 외계인 침략으로부터 무고한 행인들을 보호해야 한다. 이탈하려면, 잠수요원을 비행잠수함 안에 배치하고 '임무 중단' 아이콘을 눌러라.\"\n  STR_ALIENS_ATTACK_SHIPPING_ROUTE: \"외계인이 항로 상의{NEWLINE}선박을 공격한다\"\n  STR_CARGO_SHIP_P1: \"화물선 제1부\"\n  STR_CARGO_SHIP_P2: \"화물선 제2부\"\n  STR_CRUISE_SHIP_P1: \"여객선 제1부\"\n  STR_CRUISE_SHIP_P2: \"여객선 제2부\"\n  STR_SHIP_RESCUE_MISSION: \"선박 구조 임무\"\n  STR_SHIP_RESCUE_P1_BRIEFING: \"이 임무는 지루한 소탕 작전으로, 선박 내의 모든 외계인 유닛을 제거하고 탑승한 어떠한 민간인의 목숨도 보전하라. 외계인은 상부와 하부 갑판에 흩어졌고, 하부 갑판에 들어가기 전에 상부 갑판을 확보하라. 이탈하려면, 잠수요원을 비행잠수함 안에 배치하고 '임무 중단' 아이콘을 눌러라.\"\n  STR_SHIP_RESCUE_P2_BRIEFING: \"이제 상부 갑판이 정리되었으므로 하부 갑판으로 진행하라. 화물 승강기를 이용해 당신은 화물 칸으로 내려간다. 당신의 분대는 이 임무를 끝내려면 이 층에 있는 모든 외계인을 반드시 제거해야 한다. 중단하려면 모든 잠수요원을 시작 지점에 있는 승강기에 배치하고 '임무 중단' 아이콘을 눌러라.\"\n  STR_ALIEN_ACTIVITY_DETECTED: \"외계인 활동이 탐지되었다\"\n  STR_ALIEN_CONTACT_SITE_MISSION: \"외계인 연락 현장 임무\"\n  STR_ARTIFACT_SITE_P1: \"외계인 연락 현장 제1부\"\n  STR_ARTIFACT_SITE_P1_BRIEFING: \"이 임무는 막 활성화된 외계인 통신 현장에 대한 습격이다. 이 현장에는 2개의 층이 있는데, 외계인의 피라미드가 있는 해저와 숨겨진 외계인 단지다. 진행하려면 모든 잠수요원을 단지 입구에 놓고 '임무 중단' 아이콘을 눌러라. 이탈하려면, 잠수요원을 비행잠수함 안에 배치하고 '임무 중단' 아이콘을 눌러라.\"\n  STR_ARTIFACT_SITE_P2: \"외계인 연락 현장 제2부\"\n  STR_ARTIFACT_SITE_P2_BRIEFING: \"외계인 구조물을 통과했고 단지에 들어갔으므로 임무 목표는 명확하다. 임무를 완료하려면 외계인 시설의 심장부로 파고 들어가 시노미움 분자 제어 장치를 부수어라. 중단하려면 모든 잠수요원을 시작 지점의 진입용 승강기에 놓고 '임무 중단' 아이콘을 눌러라.\"\n  STR_SIGSBEE_DEEP_MISSION: \"지그스비 심해 임무{NEWLINE}외계인 도시 제1층\"\n  STR_TLETH_P1_BRIEFING: \"우리는 알려지지 않은 곳으로 들어가고 있으며, 이제부터 우리에게는 어떤 일이라도 있을 수 있다. 우리는 외계인 도시에 2개의 후속 층이 있다는 걸 알고 있으며 당신의 분대는 다음 층으로 들어가기 위해 이 층에 있는 출구를 향해 달려야 한다. 진행하려면 출구에 모든 잠수요원을 배치하고 '임무 중단' 아이콘을 눌러라. 그 외의 다른 곳에서 중단하는 건 임무를 종료할 것이다.\"\n  STR_TLETH_ATTACK_MISSION: \"티'레스 공격 임무{NEWLINE}외계인 도시 제2층\"\n  STR_TLETH_P2_BRIEFING: \"알려지지 않은 곳 안으로 더 들어가, 이제부터 우리에게는 어떤 일이라도 있을 수 있다. 우리는 외계인 도시에 후속 층이 있다는 걸 알고 있으며 당신의 분대는 다음 층에 들어가기 위해 이 층에 있는 출구를 향해 달려야 한다. 진행하려면 출구에 모든 잠수요원을 배치하고 '임무 중단' 아이콘을 눌러라. 그 외의 다른 곳에서 중단하는 건 임무를 종료할 것이다.\"\n  STR_FINAL_TLETH_MISSION: \"마지막 티'레스 임무{NEWLINE}외계인 도시 제3층\"\n  STR_TLETH_P3_BRIEFING: \"끝이 바로 앞이고, 이제부터 우리는 궁극 외계인의 묘실을 찾는다. 외계인의 위협을 끝내기 위해 무덤으로 가는 8개의 동력 공급기를 부수어라. 이제 포기하지 마라! 중단하는 건 임무를 종료할 것이다.\"\n  STR_TLETH_P1: \"외계인 도시 제1층\"\n  STR_TLETH_P2: \"외계인 도시 제2층\"\n  STR_TLETH_P3: \"외계인 도시 제3층\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"기체 생산에 필요한 빈 비행잠수함 격납고가 없다!{SMALLLINE}기지에 할당, 기지로 이송, 구매 또는 건조한 각각의 비행잠수함은 하나의 비행잠수함 격납고를 이용한다. 새로운 비행잠수함 격납고를 짓거나 또 다른 기지로 비행잠수함을 이송하라.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"구매에 필요한 빈 비행잠수함 격납고가 없다!{SMALLLINE}기지에 할당, 기지로 이송, 구매 또는 건조한 각각의 비행잠수함은 하나의 비행잠수함 격납고를 이용한다. 새로운 비행잠수함 격납고를 짓거나 또 다른 기지로 비행잠수함을 이송하라.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"이송에 필요한 빈 비행잠수함 격납고가 없다!{SMALLLINE}기지에 할당, 기지로 이송, 구매 또는 건조한 각각의 비행잠수함은 하나의 비행잠수함 격납고를 이용한다. 새로운 비행잠수함 격납고를 짓거나 또 다른 기지로 비행잠수함을 이송하라.\"\n  STR_CANNOT_BUILD_HERE: \"여기에 지을 수 없다!{SMALLLINE}당신은 반드시 기존 수상 모듈 옆에 지어야 한다.\"\n  STR_NO_FREE_ACCOMODATION: \"빈 생활 공간이 없다!{SMALLLINE}행선지 기지는 생활관 안에 충분한 공간을 지니지 않는다.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"쓸 수 있는 작업 공간이 충분하지 않다!{SMALLLINE}새 작업실을 짓거나 다른 과제의 일을 줄여라.\"\n  STR_NOT_ENOUGH_MONEY: \"돈이 충분하지 않다!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"저장 공간이 충분하지 않다!{SMALLLINE}새로운 저장 시설을 짓거나 기존 창고 내 물건을 다른 기지로 이송하라.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"생활 공간이 충분하지 않다!{SMALLLINE}새로운 생활관을 짓거나 직원을 다른 기지로 이송하라.\"\n  STR_LAUNCH_INTERCEPTION: \"요격함 출항\"\n  STR_CRAFT: \"기체\"\n  STR_STATUS: \"상태\"\n  STR_BASE: \"기지\"\n  STR_READY: \"대기\"\n  STR_OUT: \"출항했음\"\n  STR_REPAIRS: \"수리 중\"\n  STR_REFUELLING: \"급유 중\"\n  STR_REARMING: \"재무장 중\"\n  STR_TARGET: \"표적: {0}\"\n  STR_WAY_POINT: \"경유지\"\n  STR_ARE_YOU_SURE_CYDONIA: \"당신은 이 비행잠수함을 티'레쓰로 가는 임무에 보내길 원하는 게 확실한가?\"\n  STR_YES: \"예\"\n  STR_NO: \"아니오\"\n  STR_SELECT_DESTINATION: \"행선지 선택\"\n  STR_CYDONIA: \"티'레쓰\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"새로운 기지를 위한 현장 선택\"\n  STR_RETURN_TO_BASE: \"기지로 복귀\"\n  STR_SELECT_NEW_TARGET: \"새로운 표적 선택\"\n  STR_PATROL: \"순찰\"\n  STR_STATUS_: \"상태>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"손상됨 - 기지로 복귀함\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"연료 부족 - 기지로 복귀함\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"임무 완료 - 기지로 복귀함\"\n  STR_PATROLLING: \"순찰 중\"\n  STR_TAILING_UFO: \"외계인 비행잠수함 추격 중\"\n  STR_INTERCEPTING_UFO: \"외계인 비행잠수함-{0}호 요격 중\"\n  STR_RETURNING_TO_BASE: \"기지로 복귀함\"\n  STR_DESTINATION_UC_: \"행선지: {0}\"\n  STR_BASE_UC: \"기지>{ALT}{0}\"\n  STR_SPEED_: \"속도>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"최대 속도>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"심도>{ALT}{0}\"\n  STR_AIRBORNE: \"공중\"\n  STR_VERY_LOW: \"얕음\"\n  STR_LOW_UC: \"보통\"\n  STR_HIGH_UC: \"깊음\"\n  STR_VERY_HIGH: \"매우 깊음\"\n  STR_FUEL: \"연료>{ALT}{0}\"\n  STR_WEAPON_ONE: \"무기-1>{ALT}{0}\"\n  STR_NONE_UC: \"없음\"\n  STR_ROUNDS_: \"잔탄>{ALT}{0}\"\n  STR_WEAPON_TWO: \"무기-2>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"비행잠수함\"\n  STR_BASE_: \"기지>{0}\"\n  STR_NAME_UC: \"이름\"\n  STR_AMMO_: \"탄약>{ALT}{0}\"\n  STR_CREW: \"승무원\"\n  STR_EQUIPMENT_UC: \"장비\"\n  STR_ARMOR: \"갑옷\"\n  STR_MAX: \"최대>{ALT}{0}\"\n  STR_ROOKIE: \"이병\"\n  STR_SQUADDIE: \"일병\"\n  STR_SERGEANT: \"소위\"\n  STR_CAPTAIN: \"대위\"\n  STR_COLONEL: \"중령\"\n  STR_COMMANDER: \"대령\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"{0}에 탑승할 분대를 선택\"\n  STR_SORT_BY: \"정렬 기준\"\n  STR_ORIGINAL_ORDER: \"원래 순서\"\n  STR_MISSIONS2: \"참여 임무 수\"\n  STR_KILLS2: \"사살 수\"\n  STR_WOUND_RECOVERY2: \"부상 회복일\"\n  STR_SPACE_AVAILABLE: \"쓸 수 있는 공간>{ALT}{0}\"\n  STR_SPACE_USED: \"이용된 공간>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"이용된 공간\"\n  STR_RANK: \"계급\"\n  STR_WOUNDED: \"부상\"\n  STR_EQUIPMENT_FOR_CRAFT: \"{0}에 실을 장비\"\n  STR_DEFENSE_VALUE: \"방위력\"\n  STR_HIT_RATIO: \"명중률\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}가{NEWLINE}{ALT}{1}{NEWLINE}근처에{NEWLINE}착지 대기\"\n  STR_BEGIN_MISSION: \"임무 개시?\"\n  STR_SELECT_ARMAMENT: \"무장 선택\"\n  STR_AMMUNITION_AVAILABLE: \"쓸 수 있는 탄약\"\n  STR_ARMAMENT: \"무장\"\n  STR_NOT_AVAILABLE: \"필요 없음\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"{ALT}{0}{NEWLINE}에 입힐 갑옷 선택\"\n  STR_TYPE: \"유형\"\n  STR_PLASTIC_AQUA_ARMOR_UC: \"아쿠아 플라스틱 갑옷\"\n  STR_ION_ARMOR_UC: \"이온 갑옷\"\n  STR_MAGNETIC_ION_ARMOR_UC: \"마그네틱 이온 갑옷\"\n  STR_PLASTIC_AQUA_ARMOR_UFOPEDIA: \"이 갑옷은 새롭게 발견된 외계 물질, 아쿠아 플라스틱을 활용하며, 우리 잠수요원이 외계인의 침략에 대해 싸울 기회를 확실하게 보장한다.\"\n  STR_ION_ARMOR_UFOPEDIA: \"잠수요원을 위한 강력한 새 보호 수단인, 이 갑옷은 이온 에너지원으로 작동되며 착용자의 속도와 근력을 엄청나게 증폭해, 전투 부대를 위해 지금까지 없었던 최고의 보호를 제공한다.\"\n  STR_MAGNETIC_ION_ARMOR_UFOPEDIA: \"수중 환경에서 완전한 이동의 자유를 얻기 위해 이온 추진기와 자기 배열 기술을 통합한 개량형 이온 갑옷이다.\"\n  STR_SELECT_ARMOR: \"갑옷 선택\"\n  STR_NORTH: \"북쪽\"\n  STR_NORTH_EAST: \"북동쪽\"\n  STR_EAST: \"동쪽\"\n  STR_SOUTH_EAST: \"남동쪽\"\n  STR_SOUTH: \"남쪽\"\n  STR_SOUTH_WEST: \"남서쪽\"\n  STR_WEST: \"서쪽\"\n  STR_NORTH_WEST: \"북서쪽\"\n  STR_SELECT_ACTION: \"행동 선택\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"요격 추적 계속\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"요격 없이 추적\"\n  STR_VERY_LARGE: \"초대형\"\n  STR_LARGE: \"대형\"\n  STR_MEDIUM_UC: \"중형\"\n  STR_SMALL: \"소형\"\n  STR_VERY_SMALL: \"초소형\"\n  STR_GROUNDED: \"착지\"\n  STR_DETECTED: \"탐지됨\"\n  STR_SIZE_UC: \"크기\"\n  STR_ALTITUDE: \"심도\"\n  STR_HEADING: \"이동 방향\"\n  STR_SPEED: \"속도\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"외계인 비행잠수함을 화면 가운데로-시간=5초\"\n  STR_TRACKING_LOST: \"추적 소실\"\n  STR_REDIRECT_CRAFT: \"기체 행선지 재지정\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"마지막으로 알려진 외계인 잠수함 위치로 이동\"\n  STR_UFO_: \"외계인 비행잠수함-{0}호\"\n  STR_ALIEN_BASE_: \"외계인 식민지-{0}호\"\n  STR_CRASH_SITE_: \"추락 현장-{0}호\"\n  STR_LANDING_SITE_: \"착지 현장-{0}호\"\n  STR_WAY_POINT_: \"경유지-{0}호\"\n  STR_TERROR_SITE: \"테러 현장-{0}호\"\n  STR_ARTIFACT_SITE: \"유적 현장-{0}호\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{1}에{NEWLINE}{0}{NEWLINE}도착했음\"\n  STR_NOW_PATROLLING: \"지금 순찰 시작\"\n  STR_ALIEN_ORIGINS: \"외계인의 기원\"\n  STR_THE_ULTIMATE_THREAT: \"궁극의 위협\"\n  STR_TLETH_ALIEN_CITY: \"티'레쓰, 외계인의 도시\"\n  STR_UFOPAEDIA: \"USO 사전\"\n  STR_XCOM_CRAFT_ARMAMENT: \"X-COM 기체 & 무장\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"무장 잠수정\"\n  STR_WEAPONS_AND_EQUIPMENT: \"범용 장비\"\n  STR_ALIEN_ARTIFACTS: \"수상의 유물\"\n  STR_BASE_FACILITIES: \"X-COM 수상 모듈\"\n  STR_ALIEN_LIFE_FORMS: \"외계 생물\"\n  STR_ALIEN_RESEARCH_UC: \"외계인의 기술\"\n  STR_UFO_COMPONENTS: \"새로운 비행잠수함 기술\"\n  STR_UFOS: \"외계인의 비행잠수함\"\n  STR_SELECT_ITEM: \"물품 선택\"\n  STR_ACCELERATION: \"가속력>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"연료 용량>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"무장 공간>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"내구도>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"병력 수용량>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"무장잠수정 수용량>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"피해량\"\n  STR_RANGE: \"사거리\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"명중률\"\n  STR_RE_LOAD_TIME: \"발사 간격\"\n  STR_SECONDS: \"{0}초\"\n  STR_DAMAGE_ARMOR_PIERCING: \"철갑\"\n  STR_DAMAGE_INCENDIARY: \"인화\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"폭발\"\n  STR_DAMAGE_LASER_BEAM: \"가우스 빔\"\n  STR_DAMAGE_PLASMA_BEAM: \"소닉 빔\"\n  STR_DAMAGE_STUN: \"동결\"\n  STR_DAMAGE_MELEE: \"근접\"\n  STR_DAMAGE_ACID: \"강산\"\n  STR_DAMAGE_SMOKE: \"연막\"\n  STR_SHOT_TYPE: \"유형\"\n  STR_ACCURACY_UC: \"정확도\"\n  STR_TIME_UNIT_COST: \"TU 소비\"\n  STR_DAMAGE_UC: \"피해량\"\n  STR_AMMO: \"탄종\"\n  STR_SHOT_TYPE_AUTO: \"자동사격\"\n  STR_SHOT_TYPE_SNAP: \"지향사격\"\n  STR_SHOT_TYPE_AIMED: \"조준사격\"\n  STR_CONSTRUCTION_TIME: \"건설 기간\"\n  STR_CONSTRUCTION_COST: \"건설 비용\"\n  STR_MAINTENANCE_COST: \"유지 비용\"\n  STR_LOW: \"낮음\"\n  STR_MEDIUM: \"보통\"\n  STR_HIGH: \"높음\"\n  STR_CRAFT_WEAPON: \"비행잠수함 무기\"\n  STR_CRAFT_AMMUNITION: \"비행잠수함 탄약\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"무장 잠수정\"\n  STR_WEAPON: \"무기\"\n  STR_AMMUNITION: \"탄약\"\n  STR_EQUIPMENT: \"장비\"\n  STR_ALIEN_CORPSE: \"외계인 시체\"\n  STR_UFO_COMPONENT: \"외계인 비행잠수함 부품\"\n  STR_PERSONAL_ARMOR: \"개인용 갑옷\"\n  STR_RAW_MATERIALS: \"원재료\"\n  STR_HWP_SOLID_HARPOON_BOLTS: \"경질 작살\"\n  STR_ALIEN: \"외계인\"\n  STR_AQUATOID: \"아쿠아토이드\"\n  STR_GILLMAN: \"길맨\"\n  STR_LOBSTERMAN: \"랍스터맨\"\n  STR_TASOTH: \"타소쓰\"\n  STR_CALCINITE: \"캘시나이트\"\n  STR_DEEP_ONE: \"딥원\"\n  STR_BIODRONE: \"바이오드론\"\n  STR_TENTACULAT: \"텐타쿨러트\"\n  STR_TRISCENE: \"트라이신\"\n  STR_HALLUCINOID: \"할루시노이드\"\n  STR_XARQUID: \"자퀴드\"\n  STR_ZOMBIE: \"좀비\"\n  STR_LIVE_COMMANDER: \"사령관\"\n  STR_LIVE_NAVIGATOR: \"항법사\"\n  STR_LIVE_MEDIC: \"의무병\"\n  STR_LIVE_TECHNICIAN: \"기술자\"\n  STR_LIVE_SQUAD_LEADER: \"분대장\"\n  STR_LIVE_SOLDIER: \"병사\"\n  STR_LIVE_TERRORIST: \"테러분자\"\n  STR_AQUATOID_COMMANDER: \"아쿠아토이드 사령관\"\n  STR_AQUATOID_NAVIGATOR: \"아쿠아토이드 항법사\"\n  STR_AQUATOID_MEDIC: \"아쿠아토이드 의무병\"\n  STR_AQUATOID_TECHNICIAN: \"아쿠아토이드 기술자\"\n  STR_AQUATOID_SQUAD_LEADER: \"아쿠아토이드 분대장\"\n  STR_AQUATOID_SOLDIER: \"아쿠아토이드 병사\"\n  STR_GILLMAN_COMMANDER: \"길맨 사령관\"\n  STR_GILLMAN_TECHNICIAN: \"길맨 기술자\"\n  STR_GILLMAN_SQUAD_LEADER: \"길맨 분대장\"\n  STR_GILLMAN_SOLDIER: \"길맨 병사\"\n  STR_LOBSTERMAN_COMMANDER: \"랍스터맨 사령관\"\n  STR_LOBSTERMAN_NAVIGATOR: \"랍스터맨 항법사\"\n  STR_LOBSTERMAN_TECHNICIAN: \"랍스터맨 기술자\"\n  STR_LOBSTERMAN_SQUAD_LEADER: \"랍스터맨 분대장\"\n  STR_LOBSTERMAN_SOLDIER: \"랍스터맨 병사\"\n  STR_TASOTH_SQUAD_LEADER: \"타소쓰 분대장\"\n  STR_TASOTH_SOLDIER: \"타소쓰 병사\"\n  STR_CALCINITE_TERRORIST: \"캘시나이트 테러분자\"\n  STR_DEEP_ONE_TERRORIST: \"딥원 테러분자\"\n  STR_BIODRONE_TERRORIST: \"바이오드론 테러분자\"\n  STR_TENTACULAT_TERRORIST: \"텐타쿨러트 테러분자\"\n  STR_TRISCENE_TERRORIST: \"트라이신 테러분자\"\n  STR_HALLUCINOID_TERRORIST: \"할루시노이드 테러분자\"\n  STR_XARQUID_TERRORIST: \"자퀴드 테러분자\"\n  STR_ION_BEAM_ACCELERATORS: \"이온 빔 가속기\"\n  STR_MAGNETIC_NAVIGATION: \"자기 항법장치\"\n  STR_ALIEN_SUB_CONSTRUCTION: \"외계인 잠수함 구조\"\n  STR_ALIEN_CRYOGENICS: \"외계인 동면기\"\n  STR_ALIEN_CLONING: \"외계인 복제기\"\n  STR_ALIEN_LEARNING_ARRAYS: \"외계인 학습기\"\n  STR_ALIEN_IMPLANTER: \"외계인 삽입기\"\n  STR_EXAMINATION_ROOM: \"시험 장치\"\n  STR_AQUA_PLASTICS: \"아쿠아 플라스틱\"\n  STR_ALIEN_REANIMATION_ZONE: \"외계인 재활 장치\"\n  STR_PLASTIC_AQUA_ARMOR: \"아쿠아 플라스틱 갑옷\"\n  STR_ION_ARMOR: \"이온 갑옷\"\n  STR_MAGNETIC_ION_ARMOR: \"마그네틱 이온 갑옷\"\n  STR_HWP_AQUA_JET_MISSILES: \"아쿠아 제트 어뢰\"\n  STR_HWP_DISPLACER_PWT: \"펄스파 어뢰\"\n  STR_GAUSS_TECH: \"가우스 기술\"\n  STR_NEW_FIGHTER_FLYING_SUB: \"새로운 전투 비행잠수함\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"새로운 전투 수송기\"\n  STR_THE_LATEST_FLYING_SUB: \"최신 비행잠수함\"\n  STR_ARMOR_PIERCING: \"철갑\"\n  STR_COELACANTH_GAS_CANNON: \"실러캔스/가스 기관포\"\n  STR_COELACANTH_AQUA_JET: \"실러캔스/아쿠아제트 어뢰\"\n  STR_COELACANTH_GAUSS: \"실러캔스/가우스 포\"\n  STR_DISPLACER_SONIC: \"디스플레이서/소닉 포\"\n  STR_DISPLACER_PWT: \"디스플레이서/펄스파 어뢰\"\n  STR_AJAX_LAUNCHER: \"에이잭스 발사기\"\n  STR_DUP_HEAD_LAUNCHER: \"D.U.P. 탄두 발사기\"\n  STR_CRAFT_GAS_CANNON: \"가스 기관포\"\n  STR_PWT_CANNON: \"펄스파 어뢰 발사기\"\n  STR_GAUSS_CANNON: \"가우스 기관포\"\n  STR_GAUSS_CANNON_AMMO: \"가우스 기관포 탄약\"\n  STR_SONIC_OSCILLATOR: \"소닉 발진기\"\n  STR_AJAX_TORPEDOES: \"에이잭스 어뢰\"\n  STR_DUP_HEAD_TORPEDOES: \"D.U.P. 탄두 어뢰\"\n  STR_CRAFT_GAS_CANNON_ROUNDS_X50: \"가스 기관포 탄환(x50)\"\n  STR_SONIC_WAVE: \"소닉 파동\"\n  STR_PULSE_WAVE_TORPEDOES: \"펄스파 어뢰\"\n  STR_SOLDIER: \"잠수요원\"\n  STR_SCIENTIST: \"과학자\"\n  STR_ENGINEER: \"기술자\"\n  STR_NORTH_ATLANTIC: \"북대서양\"\n  STR_SOUTH_ATLANTIC: \"남대서양\"\n  STR_NORTH_PACIFIC: \"북태평양\"\n  STR_SOUTH_PACIFIC: \"남태평양\"\n  STR_MEDITERRANEAN: \"지중해\"\n  STR_SOUTH_CHINA_SEA: \"남중국해\"\n  STR_INDIAN_OCEAN: \"인도양\"\n  STR_THE_EAST_SEA: \"동해\"\n  STR_NORTH_SEA: \"북해\"\n  STR_CARRIBEAN: \"카리브해\"\n  STR_ANTARCTIC: \"남극\"\n  STR_ARCTIC: \"북극\"\n  STR_EURASIA: \"유라시아\"\n  STR_NORTH_AMERICA: \"북아메리카\"\n  STR_AFRICA: \"아프리카\"\n  STR_MAXIMUM_SPEED: \"최대 속도\"\n  STR_TRANSMISSION_RESOLVER_UC: \"지령 해석기\"\n  STR_TRITON: \"트리톤\"\n  STR_HAMMERHEAD: \"해머헤드\"\n  STR_LEVIATHAN: \"리바이어던\"\n  STR_BARRACUDA: \"바라쿠다\"\n  STR_MANTA: \"만타\"\n  STR_UFO: \"외계인 비행잠수함\"\n  STR_AJAX: \"에이잭스 어뢰\"\n  STR_DUP_HEAD: \"D.U.P. 탄두 어뢰\"\n  STR_CRAFT_GAS_CANNON_UC: \"가스 기관포\"\n  STR_PWT_CANNON_UC: \"펄스파 어뢰\"\n  STR_GAUSS_CANNON_UC: \"가우스 기관포\"\n  STR_SONIC_OSCILLATOR_UC: \"소닉 발진기\"\n  STR_DAMAGE_CAPACITY: \"내구도\"\n  STR_WEAPON_POWER: \"무기 위력\"\n  STR_WEAPON_RANGE: \"무기 사거리\"\n  STR_AIR_LOCK: \"기밀 출입구\"\n  STR_LABORATORY: \"연구실\"\n  STR_WORKSHOP: \"작업실\"\n  STR_STANDARD_SONAR: \"표준 소나\"\n  STR_WIDE_ARRAY_SONAR: \"광역 소나\"\n  STR_TORPEDO_DEFENSES: \"어뢰 방어시설\"\n  STR_GENERAL_STORES: \"범용 창고\"\n  STR_ALIEN_CONTAINMENT: \"외계인 격리실\"\n  STR_GAUSS_DEFENSES: \"가우스 방어시설\"\n  STR_SONIC_DEFENSES: \"소닉 방어시설\"\n  STR_PWT_DEFENSES: \"펄스파 어뢰 방어시설\"\n  STR_BOMBARDMENT_SHIELD: \"수압 충격 방어막\"\n  STR_MC_GENERATOR: \"M.C. 신호 발생기\"\n  STR_MC_LAB: \"M.C. 연구실\"\n  STR_TRANSMISSION_RESOLVER: \"지령 해석기\"\n  STR_SUB_PEN: \"비행잠수함 격납고\"\n  STR_USA: \"미합중국\"\n  STR_ALASKA: \"알래스카\"\n  STR_EU_SYNDICATE: \"유로신디케이트\"\n  STR_ARABIAN_BLOC: \"아라비아 블록\"\n  STR_EGYPTIAN_CARTEL: \"이집트 카르텔\"\n  STR_AFRICA_CORP: \"아프리카 주식회사\"\n  STR_BRAZILIAN_UNION: \"브라질 연합\"\n  STR_NEW_MEXICO: \"뉴 멕시코\"\n  STR_ASIAN_COALITION: \"아시아 연정\"\n  STR_SCANDINAVIA: \"스칸디나비아\"\n  STR_NEO_JAPAN: \"네오 재팬\"\n  STR_FREE_CHINA: \"자유 중국\"\n  STR_AUSTRALASIA: \"오스트랄라시아\"\n  STR_FED_KOREA: \"대한 연방\"\n  STR_EURASIA_UC: \"유라시아\"\n  STR_ICELANDIC_UNION: \"아이슬란드 연합\"\n  STR_TANK: \"무장 잠수정\"\n  STR_CIVILIAN: \"민간인\"\n  STR_JAN: \"1월\"\n  STR_FEB: \"2월\"\n  STR_MAR: \"3월\"\n  STR_APR: \"4월\"\n  STR_MAY: \"5월\"\n  STR_JUN: \"6월\"\n  STR_JUL: \"7월\"\n  STR_AUG: \"8월\"\n  STR_SEP: \"9월\"\n  STR_OCT: \"10월\"\n  STR_NOV: \"11월\"\n  STR_DEC: \"12월\"\n  STR_INTERNATIONAL_RELATIONS: \"국제 관계\"\n  STR_COUNTRY: \"국가\"\n  STR_FUNDING: \"후원금\"\n  STR_CHANGE: \"변동\"\n  STR_WEAPON_SYSTEMS: \"무기 체계\"\n  STR_HWPS: \"SWS\"\n  STR_DAMAGE_UC_: \"피해량>{ALT}{0}\"\n  STR_AIR_LOCK_UFOPEDIA: \"기밀 출입구는 수중 기지 안과 밖으로 장비와 직원을 옮기도록 한다. 그건 언제나 새로운 현장에서 건설되는 첫 수상 모듈이다. 기밀 출입구는 어떠한 잠재적 적대 세력의 침입에도 취약하다.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"각 거주 영역은 50명에 이르는 직원을 위한 공간을 제공한다. 이 수상 모듈은 어쩐지 기본적이고 기능적이다.\"\n  STR_LABORATORY_UFOPEDIA: \"하나의 연구 구역에서 50명의 과학자가 작업할 수 있다. 연구실은 재료공학, 생화학, 병기의 연구를 위한 모든 최신 기술이 집약되어 있다. X-Com은 민간 및 군사 양쪽에서, 세계 전역에 걸친 모든 최고의 연구 시설에 접근할 수 있다.\"\n  STR_WORKSHOP_UFOPEDIA: \"작업실은 과학 연구실에서 나온 최신의 설계에 기반한 장비를 제조하기에 필요한 모든 장비가 들어 있다. 50명의 기술자가 한 작업실을 차지할 수 있으나, 건조 중인 물품 또한 공간을 잡아먹을 것이다.\"\n  STR_STANDARD_SONAR_UFOPEDIA: \"표준 소나 장치는 대다수 심도에서 450km의 유효 범위를 지니며 지표 분석을 위한 정지 위성 네트워크와 연결되어 있다. 각각의 스캐너는 30분의 스캔 주기 당 10%의 잠수정 또는 공중 기체를 탐지할 기회를 지닌다.\"\n  STR_WIDE_ARRAY_SONAR_UFOPEDIA: \"광역 소나 장치는 모든 심도에서 700km의 유효 범위를 지니며 지표 분석을 위한 정지 위성 네트워크와 연결되어 있다. 각각의 스캐너는 30분의 스캔 주기 당 20%의 잠수정 또는 공중 기체를 탐지할 기회를 지닌다.\"\n  STR_TORPEDO_DEFENSES_UFOPEDIA: \"어뢰 방어시설은 기지에 정박하려 하는 적대적 잠수함의 공격에 대한 보호를 제공한다.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"격납고 안의 비행잠수함에 할당된 장비를 포함해, 모든 장비, 무기 체계, 탄약, 회수된 재료 및 무장 잠수정은 창고에 저장된다.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"살아있는 외계인은 붙들어 놓기 위해 특별한 격리 시설을 요구할 것이다. 이 장치는 그들의 생명을 유지하고 전투 역량을 0으로 만든다. 이 격리 시설은 구속 장치 안에 10마리의 외계 생명체를 보관할 수 있다.\"\n  STR_GAUSS_DEFENSES_UFOPEDIA: \"가우스 방어시설은 적대적인 잠수함의 공격에 대해 가장 효과적인 최신의 보호를 제공한다.\"\n  STR_SONIC_DEFENSES_UFOPEDIA: \"소닉 공진기 방어시설은 공격자에 대한 강력하고 효과적인 보호를 제공한다.\"\n  STR_PWT_DEFENSES_UFOPEDIA: \"펄스파 어뢰는 외계인의 공격에 대한 가장 효과적인 방어를 제공한다. 이 미사일은 알려진 모든 장갑을 관통할 수 있는 초밀도물질 탄두를 지닌다. 그게 만들어내는 자기 파동은 전자 방어를 무력화한다.\"\n  STR_BOMBARDMENT_SHIELD_UFOPEDIA: \"수압 충격 방어막은 외계인 잠수정의 접안으로부터 기지를 보호하고 방어 체계가 반복적으로 사격하기 충분할 만큼 오랫동안 공격 잠수함을 밀어내는 공진 역장을 설치한다. 실제로 이는 이미 배치된 어떠한 방어 체계의 효력을 두 배로 한다.\"\n  STR_MC_GENERATOR_UFOPEDIA: \"외계인의 잠수함이 살아있는 생물의 존재를 탐지하기 위해 분자 제어 기술을 활용하기에, 음의 M.C. 신호 방출기를 이용하는 건 기지를 외계인을 혼란에 빠트리고 우리 존재를 숨기기 위한 뚫을 수 없는 방어막으로 기지를 가릴 것이다.\"\n  STR_MC_LAB_UFOPEDIA: \"분자 제어 연구실은 한번에 10명에 이르는 잠수요원에 삽입물을 이식하고 훈련할 수 있다. 삽입물은 잠수요원의 두개골에 수술로 설치된다. 집중적인 훈련은 그들에게 자신의 삽입물을 활용하도록 한다. 삽입물의 활용 기술은 M.C. 장치와 함께 이용되며 전투 중 공격에 이용될 수 있다.\"\n  STR_TRANSMISSION_RESOLVER_UFOPEDIA: \"외계인의 통신은 그들이 구축했던 분자 제어 삽입물 통신망을 활용한다. 지령 해석기는 외계인 잠수함의 지령을 가로채 정보를 해석한다. 이는 외계인 잠수함의 유형, 외계인 종족, 일어날 활동의 유형을 보여줄 것이다.\"\n  STR_SUB_PEN_UFOPEDIA: \"각 비행잠수함 격납고는 비행잠수함 하나를 할당할 수 있다. 이건 X-Com 잠수 함대의 유지, 급유 및 수리를 위한 시설이다. 기지에 머무르는 각 비행잠수함은 설령 그 비행잠수함이 임무로 나갔다 해도, 다른 비행잠수함이 이용할 수 없는 자기만의 빈 비행잠수함 격납고가 반드시 있어야 한다.\"\n  STR_DART_PISTOL_UFOPEDIA: \"이 X-Com 다트 권총은 12발의 속이 빈 다트 탄창이 있는 작고 정확하며 높은 위력의 권총이다. 이 다트는 탄의 약실 안 가스 카트리지에 의해 날아간다.\"\n  STR_JET_HARPOON_UFOPEDIA: \"이 수중 소총은 정확하고 강력하며, 9발이 든 밀봉된 탄창에서 속이 빈 강철 작살을 쏜다. 각각의 작살은 자체적인 가스 저장기를 지닌다.\"\n  STR_GAS_CANNON_UFOPEDIA: \"가스 기술군의 중화기인, 이 포는 실탄을 쏘는데, 실탄 일부에는 고폭 또는 백린 탄두가 달려있다. 숙련된 잠수요원들의 선호 무기다.\"\n  STR_HYDRO_JET_CANNON_UFOPEDIA: \"하이드로제트 기관포는 보병용 중화기다. 이 기관포는 마그네슘으로 날아가는 초소형 어뢰를 쏜다. 비록 강력하지만, 하이드로제트 기관포는 투박하고 다루기 어려운 장치로, 오직 수중 이용에만 적합하다.\"\n  STR_TORPEDO_LAUNCHER_UFOPEDIA: \"정말 무거운, 이 커다란 발사기는 세 가지 유형의 어뢰를 쏘는데, 각각은 자체적인 추진 장치가 달려있다. 파괴적인 무기로, 오직 수동 장전만이 약점일 뿐이다. 탄종은 소형 또는 대형 고폭 탄두와 백린 탄두를 단 어뢰를 포함하며, 이 모두는 오직 수중 이용을 위한 것이다.\"\n  STR_GAUSS_PISTOL_UFOPEDIA: \"가우스 권총은 현대 병기 분야의 새로운 성과인, 입자 가속 기술을 이용한다. 그건 빠르고, 정확하며 지상과 수중에서 동작한다. 가우스 기술은 이전 전쟁에서 배웠던 플라스마 기술로부터 얻어진 기술이다.\"\n  STR_GAUSS_PISTOL_CLIP_UFOPEDIA: \"가우스 권총은 현대 병기 분야의 새로운 성과인, 입자 가속 기술을 이용한다. 그건 빠르고, 정확하며 지상과 수중에서 동작한다. 가우스 기술은 이전 전쟁에서 배웠던 플라스마 기술로부터 얻어진 기술이다.\"\n  STR_GAUSS_RIFLE_UFOPEDIA: \"가우스 권총에서 한 발 더 나아간, 이 소총은 쌍 입자가속기로, 정말 센 한 방을 날린다. 엘레리움 구동 플라스마 장치를 대신해 우리는 반양성자의 흐름을 생성하는 초소형 입자가속기를 활용했다.\"\n  STR_GAUSS_RIFLE_CLIP_UFOPEDIA: \"가우스 권총에서 한 발 더 나아간, 이 소총은 쌍 입자가속기로, 정말 센 한 방을 날린다. 엘레리움 구동 플라스마 장치를 대신해 우리는 반양성자의 흐름을 생성하는 초소형 입자가속기를 활용했다.\"\n  STR_HEAVY_GAUSS_UFOPEDIA: \"중형 가우스 총은 거추장스러우나, 엄청나게 효과적이다. 그건 3개의 입자가속기로 동작하며 사실상 멈출 수 없다. 반양성자의 흐름은 충격 시 반물질을 방출하며 내파하는 갈륨 비소 피모 내부에 구속되어 있다.\"\n  STR_HEAVY_GAUSS_CLIP_UFOPEDIA: \"중형 가우스 총은 거추장스러우나, 엄청나게 효과적이다. 그건 3개의 입자가속기로 동작하며 사실상 멈출 수 없다. 반양성자의 흐름은 충격 시 반물질을 방출하며 내파하는 갈륨 비소 피모 내부에 구속되어 있다.\"\n  STR_MAGNA_BLAST_GRENADE_UFOPEDIA: \"이 제식 수류탄은 정교한 기폭 시점 제어를 위한 정확하고 복잡한 타이머를 지닌다.\"\n  STR_DYE_GRENADE_UFOPEDIA: \"물감 수류탄은 다목적 물품으로, 노출된 상황에서 엄폐를 제공하는 데 유용하다. 수중 및 지상 환경 양쪽에서 기능을 발휘하는 이 염료는 입자 구름으로 방출되어, 물 속에서 문어 비슷한 먹물 방울을 만들거나 지상에서 뻑뻑한 공기 중 안개 구름을 만든다.\"\n  STR_PARTICLE_DISTURBANCE_GRENADE_UFOPEDIA: \"평범한 수류탄 같이 던질 수 있으나 착지한 후 근처의 움직임에 의해 격발되는 근접 수류탄이다. 이 장치를 적절하게 이용하려면 기술과 훈련이 요구된다.\"\n  STR_MAGNA_PACK_EXPLOSIVE_UFOPEDIA: \"이 폭발물은 오직 철거 용도로만 이용되어야 한다. 그렇지만 지난 경험은 이 강력한 폭발물 꾸러미가 외계인을 뿌리 뽑는 데 이상적인 무기임을 보여 주었다. 폭발 반경이 크므로, 최소 안전 거리 안에 아무 잠수요원도 없게 확인하라.\"\n  STR_PARTICLE_DISTURBANCE_SENSOR_UFOPEDIA: \"이 새로운 장치는 이동하는 적 유닛을 식별하기 위해 다양한 탐지기와 발전된 컴퓨터 장치를 이용한다. 전술 화면에서 입자 교란 센서 아이콘을 눌러라. 메뉴에서 '센서 이용'을 눌러라. 센서 디스플레이는 중앙의 화살표로 잠수요원이 바라보는 방향을 보여 준다(북쪽은 위에 있다). 깜빡임은 최근에 움직였던 유닛을 보여 준다. 커다란 유닛, 또는 빠르게 움직이는 유닛은, 더 커다란 깜빡임을 만들 것이다. 정지한 유닛은 나타나지 않을 것이다.\"\n  STR_MEDI_KIT_UFOPEDIA: \"이걸 이용하려면 당신은 다친 X-Com 잠수요원을 바라보거나 기절한 잠수요원의 몸 위에 선다.{NEWLINE}치료> 적색은 치명상을 가리킨다. 다친 신체 부위를 선택하고 '치료' 버튼을 눌러라. 하나의 치명상이 치료되며 약간의 체력이 회복될 것이다.{NEWLINE}각성제> 기력을 회복하고 기절한 잠수요원을 깨운다. 의식불명인 잠수요원을 깨우려면 당신은 반드시 그 몸 바로 위에 서야 한다.{NEWLINE}진통제> 다친 병사의 사기를 회복한다.\"\n  STR_MC_DISRUPTOR_UFOPEDIA: \"M.C. 기술의 걸작이다. 이건 오직 M.C. 기술이 있는 잠수요원만 이용할 수 있다. 분열기를 마우스로 누르고, 공격의 유형을 고른 후, 마우스 커서로 대상 유닛을 골라라. 두 가지 유형의 분열기 공격이 있다.{NEWLINE}삽입물 간섭> 만약 성공하면 그 유닛은 혼란을 일으키고 공황에 빠지게 할 지도 모른다.{NEWLINE}삽입물 제어> 만약 성공하면 당신은 적 유닛을 조종할 것이다.\"\n  STR_THERMAL_TAZER_UFOPEDIA: \"이 장치는 오직 근접 전투에서만 이용될 수 있으나, 살아있는 생물을 얼려서 죽이지 않고 기절시킬 것이다.\"\n  STR_VIBRO_BLADE_UFOPEDIA: \"초진동 칼날은 초당 6000회 이상 회전하는 티타늄으로 만들어진 길고 날카로운 비수로, 이 장치는 가장 억센 잠수용 갑옷조차 부술 수 있다. 동력원은 외계인의 발명품으로, 이전에 이런 물품을 만들려던 우리의 시도는 처참한 실패로 끝났었는데, 우리 칼날은 과도한 수압 하에서 너무 느리게 돌거나 폭발했다.\"\n  STR_THERMIC_LANCE_UFOPEDIA: \"써믹 랜스는 초진동 칼날 기술의 논리적 연장이다. 그 칼날은 빠른 속도로 회전하며 지바이트 동력원은 갑옷을 두부 자르듯 베어버리도록 칼날을 초 가열한다.\"\n  STR_HEAVY_THERMIC_LANCE_UFOPEDIA: \"중형 써믹 랜스는 더 강력한 형태의 써믹 랜스다. 이중 열원과 엄청나게 높은 회전 속도는 중형 써믹 랜스를 사실상 어떤 물질로도 막을 수 없다는 뜻이다.\"\n  STR_SONIC_CANNON_UFOPEDIA: \"소닉 포는 소닉 무기 계열 중에서 가장 강한 것이다. 블래스타 소총보다 더 높은 대역의 음향 공진기와 더 커다래진 잔향실이 특징이다. 이 무기는 또한 더 효과적인 소닉 충격을 만들어내기 위해 변조를 통해 초음파 파동을 변형하는 펄스 기폭 장치를 지닌다.\"\n  STR_CANNON_POWER_CLIP_UFOPEDIA: \"이 자그마한 장치는 소닉 포의 탄약으로 이용된다. 그건 적은 양의 지바이트가 들어 있다.\"\n  STR_SONIC_BLASTA_RIFLE_UFOPEDIA: \"더 강력한 소닉 장치다. 고탄소강조차 이 무기에 면역이 아니다. 대단히 자그마한 파동 방출기는 이 무기의 위력을 올리기 위한 초전도 증폭기로 강화되었다.\"\n  STR_BLASTA_POWER_CLIP_UFOPEDIA: \"이 작은 물건은 강력한 외계인의 무기인, 소닉 블래스타 소총의 동력원으로 이용되고, 적은 양의 지바이트가 들어 있다.\"\n  STR_SONIC_PISTOL_UFOPEDIA: \"소닉 권총은 뼈를 수 초 만에 흐물거리게 할 수 있는 초고주파 음향 파동에 기반한 외계인의 무기다. 초고주파 음향 파동은 인간의 가청 영역을 넘어서는 주파수 대역을 점유한다.\"\n  STR_PISTOL_POWER_CLIP_UFOPEDIA: \"자그마한 외계인의 소닉 권총용 동력원이다. 지바이트 - 모든 외계인 힘의 원천이 들어 있다.\"\n  STR_DISRUPTOR_PULSE_LAUNCHER_UFOPEDIA: \"이건 자가 추진되는 '디스럽터 발사체'를 쏘는 외계인의 수중 전용 유도 무기다. 당신이 무기를 쏘려고 누를 때 그건 발사체가 따라갈 '경유지'를 생성할 것이다. 당신이 충분한 경유지를 지정했을 때 발사 아이콘을 눌러라.\"\n  STR_DISRUPTOR_AMMO_UFOPEDIA: \"이 장치는 내장 컴퓨터 유도 체계가 적용된 디스럽터 펄스 발사체다. 그건 디스럽터 펄스 발사기에서 쏘아진다.\"\n  STR_THERMAL_SHOK_LAUNCHER_UFOPEDIA: \"화학 동결 폭탄을 쏘는 작은 열충격탄 발사기다. 살아있는 외계인을 포획하는 데 아주 유용하다.\"\n  STR_THERMAL_SHOK_BOMB_UFOPEDIA: \"열충격 폭탄은 살아있는 인간을 포획하는 데 이용되나, 또한 대다수 외계인 종족에 대해 이용될 수 있다.그건 열충격탄 발사기에서 쏘아진다.\"\n  STR_SONIC_PULSER_UFOPEDIA: \"이 장치는 제식 수류탄과 같은 방식으로 동작한다 - 수 배 더 강력하다는 걸 제외하면. 이 수류탄은 모든 방향으로 동시에 방출되는 단일 펄스 소닉 폭발을 이용한다.\"\n  STR_MC_READER_UFOPEDIA: \"외계인의 몸 안에서 우리는 수술로 삽입된 작은 장치를 찾아냈다. 이는 대단히 먼 거리에서도, 전장에서 정보를 지속적으로 공급하도록 하는 아쿠아토이드에 의해 설계된 제어 삽입물이다. M.C. 판독기는 M.C. 삽입물에서 직접 정보를 얻는데 이용되는 외계인의 통신 장치다. X-Com 유닛은 외계인의 상태를 표시하기 위해 전투 중 이 장치를 이용할 수 있다. '사용' 선택지를 골라라. 그리고 커서로 외계인을 눌러라.\"\n  STR_SURVEY_SHIP: \"조사선\"\n  STR_ESCORT: \"호위선\"\n  STR_CRUISER: \"순양함\"\n  STR_HEAVY_CRUISER: \"중순양함\"\n  STR_HUNTER: \"사냥함\"\n  STR_BATTLESHIP: \"전함\"\n  STR_DREADNOUGHT: \"드레드노트\"\n  STR_FLEET_SUPPLY_CRUISER: \"함대 보급 순양함\"\n  MAP_SEABED: \"해저\"\n  MAP_PIPES: \"연구 시설\"\n  MAP_PLANE: \"추락한 비행기\"\n  MAP_ATLAN: \"아틀란티스\"\n  MAP_MU: \"마야 사원\"\n  MAP_GAL: \"침몰한 갤리온\"\n  MAP_MSUNK: \"침몰한 여객선\"\n  MAP_VOLC: \"화산지대\"\n  MAP_CORAL: \"산호초\"\n  MAP_PORT: \"항구\"\n  MAP_ISLAND: \"섬\"\n  MAP_CARGO: \"화물선\"\n  MAP_LINERT: \"여객선 제1부\"\n  MAP_LINERB: \"여객선 제2부\"\n  MAP_ALART: \"유적 제1부\"\n  MAP_GRUNGE: \"유적 제2부\"\n  MAP_ENTRY: \"식민지 제1부\"\n  MAP_A_BASE: \"식민지 제2부\"\n  MAP_ALSHIP: \"티'레스 제1부\"\n  MAP_LEVEL: \"티'레스 제2부\"\n  MAP_CRYPT: \"티'레스 제3부\"\n  MAP_XBASES: \"X-Com 기지\"\n  STR_MIXED_CREW: \"혼성 승무원\"\n  STR_MIXED_CREW_2: \"혼성 승무원 2\"\n  STR_RATING: \"평가> {0}\"\n  STR_RATING_TERRIBLE: \"끔찍함!\"\n  STR_RATING_POOR: \"나쁨!\"\n  STR_RATING_OK: \"보통\"\n  STR_RATING_GOOD: \"좋음!\"\n  STR_RATING_EXCELLENT: \"훌륭함!\"\n  STR_SCORE: \"평점\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"X-COM 월간 보고서\"\n  STR_MONTH: \"시기> {ALT}{1}년 {0}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"후원 기구 협의회는 지금까지 당신의 성과에 전반적으로 만족했다.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"후원 기구 협의회는 당신의 탁월한 성과에 아주 기뻐했다. 좋은 활동을 지속하라.\"\n  STR_COUNCIL_IS_DISSATISFIED: \"후원 기구 협의회는 당신의 성과에 만족하지 못했다. 당신은 외계인의 위협을 다루는 효율성을 반드시 개선하거나 X-Com에 대한 재정 지원 종료를 감수해야 한다.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"당신은 외계인의 침략을 처리하는 데 성공하지 못했고, 후원 기구 협의회는 유감스럽게도 X-Com의 후원을 끝낸다고 결정했다. 각 기구는 자기들이 적절하다 보이는 방식으로 이 문제를 다룰 것이다. 우리는 오직 이 고대의 세력과 어떤 화해를 할 수 있고, 일반 대중이 수중의 방문자를 받아들일 것인지 기대할 수밖에 없다.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0}에서는 국지적인 위협을 다루는 당신의 능력에 특히 기뻐했고 후원을 올리는 데 동의했다.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0}에서는 국지적인 위협을 다루는 당신의 능력에 특히 기뻐했고 후원을 올리는 데 동의했다.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0}과 {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0}에서는 자기 영해의 외계인 활동을 다루는 당신의 능력에 불평했고 재정적 지원을 줄이기로 결정했다.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0}에서는 자기 영해의 외계인 활동을 다루는 당신의 능력에 불평했고 재정적 지원을 줄이기로 결정했다.\"\n  STR_KNOTS: \"{0} 노트\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} 당국은 외계인 세력과 협력 조약을 체결했고 X-Com 후원을 철회했다.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} 당국은 외계인 세력과 협력 조약을 체결했고 X-Com 후원을 철회했다.\"\n  STR_MONTHLY_RATING: \"월간 평가> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"후원금 변동> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"후원 기구는 당신의 재정 상황에 기뻐하지 않는다. 당신은 빚을 $1,000,000 이하로 반드시 낮추어야 하고 아니면 X-Com은 종료될 것이다.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"소립자 지령 해석됨\"\n  STR_CRAFT_TYPE: \"비행잠수함 유형\"\n  STR_RACE: \"종족\"\n  STR_MISSION: \"임무\"\n  STR_ZONE: \"구역\"\n  STR_ALLOCATE_RESEARCH: \"연구 할당\"\n  STR_ALLOCATE_MANUFACTURE: \"제조 할당\"\n  STR_AZORES: \"아조레스\"\n  STR_REYKJAVIK: \"레이캬비크\"\n  STR_BERMUDA: \"버뮤다\"\n  STR_NEW_YORK: \"뉴욕\"\n  STR_BOSTON: \"보스턴\"\n  STR_FORT_SEVERN: \"포트 세번\"\n  STR_DAKAR: \"다카르\"\n  STR_RECIFE: \"레시페\"\n  STR_ACCRA: \"아크라\"\n  STR_ASCENSION_ISLAND: \"어센션 섬\"\n  STR_TRINIDADE_ISLAND: \"트리니다드 섬\"\n  STR_FALKLAND_ISLAND: \"포클랜드 섬\"\n  STR_CANARY_ISLANDS: \"카나리 섬\"\n  STR_ANCHORAGE: \"앵커리지\"\n  STR_ST_LAWRENCE_ISLAND: \"세인트로렌스 섬\"\n  STR_SAN_FRANCISCO: \"샌프란시스코\"\n  STR_MIDWAY_ISLAND: \"미드웨이 섬\"\n  STR_VANCOUVER: \"밴쿠버\"\n  STR_TASMANIA: \"태즈매니아\"\n  STR_HAWAII: \"하와이\"\n  STR_FIJI: \"피지\"\n  STR_TONGA: \"통가\"\n  STR_EASTER_ISLAND: \"이스터 섬\"\n  STR_GALAPAGOS_ISLAND: \"갈라파고스 섬\"\n  STR_WELLINGTON: \"웰링턴\"\n  STR_SOLOMON_ISLAND: \"솔로몬 섬\"\n  STR_CRETE: \"크레타\"\n  STR_LISBON: \"리스본\"\n  STR_PORT_SAID: \"포트 사이드\"\n  STR_MARSEILLES: \"마르세유\"\n  STR_TRIPOLI: \"트리폴리\"\n  STR_MANILA: \"마닐라\"\n  STR_HONG_KONG: \"홍콩\"\n  STR_SINGAPORE: \"싱가포르\"\n  STR_BANGKOK: \"방콕\"\n  STR_DARWIN: \"다윈\"\n  STR_BOMBAY: \"봄베이\"\n  STR_SAYCHELLES_ISLAND: \"세이셜 섬\"\n  STR_MALDIVE_ISLAND: \"몰디브 섬\"\n  STR_SRI_LANKA: \"스리랑카\"\n  STR_MAURITIUS: \"모리셔스\"\n  STR_TOKYO: \"도쿄\"\n  STR_SHANGHAI: \"상하이\"\n  STR_VLADIVOSTOK: \"블라디보스톡\"\n  STR_LONDON: \"런던\"\n  STR_FAEROE_ISLAND: \"페로 섬\"\n  STR_ABERDEEN: \"애버딘\"\n  STR_OSLO: \"오슬로\"\n  STR_JAMAICA: \"자메이카\"\n  STR_PANAMA: \"파나마\"\n  STR_MIAMI: \"마이애미\"\n  STR_PSI_TRAINING: \"M.C. 훈련\"\n  STR_PSIONIC_TRAINING: \"분자 제어 훈련\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"잔여 M.C. 연구실 공간> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"M.C.{NEWLINE}강도\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"M.C. 기술{NEWLINE}/개선\"\n  STR_IN_TRAINING: \"훈련{NEWLINE}중인가?\"\n  STR_TARGETTED_BY: \"다음이 노림: \"\n  STR_WEAPONS_CREW_HWPS: \"무기/{NEWLINE}승무원/SWS\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"는 연료가 부족해,{NEWLINE}기지로 복귀함\"\n  STR_SOLDIER_LIST: \"잠수요원 명단\"\n  STR_RANK_: \"계급> {ALT}{0}\"\n  STR_MISSIONS: \"임무> {ALT}{0}\"\n  STR_KILLS: \"사살> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"부상 회복> {ALT}{0}\"\n  STR_TIME_UNITS: \"행동력\"\n  STR_STAMINA: \"기력\"\n  STR_HEALTH: \"체력\"\n  STR_BRAVERY: \"용기\"\n  STR_REACTIONS: \"반응\"\n  STR_FIRING_ACCURACY: \"사격술\"\n  STR_THROWING_ACCURACY: \"투척술\"\n  STR_STRENGTH: \"근력\"\n  STR_PSIONIC_STRENGTH: \"M.C. 강도\"\n  STR_PSIONIC_SKILL: \"M.C. 기술\"\n  STR_NEW_RANK: \"새로운 계급\"\n  STR_PROMOTIONS: \"진급\"\n  STR_SOLDIERS_UC: \"잠수요원\"\n  STR_COELACANTH_GAS_CANNON_UFOPEDIA: \"자율적인 무장 잠수정은 높은 기동성 및 동체 강도를 지닌다. 그건 모든 심도에서 중화기 지원을 제공한다. 무장 잠수정은 충분한 탄약을 채워 놓았다면 자동으로 재무장된다.\"\n  STR_COELACANTH_AQUA_JET_UFOPEDIA: \"이 잠수정은 아쿠아제트 어뢰로 무장했다. 이 무기 체계는 오직 물 속에서만 동작한다. 창고에 아쿠아제트 어뢰가 잘 채워졌는지 확인하라.\"\n  STR_COELACANTH_GAUSS_UFOPEDIA: \"가우스 기술은 무장 잠수정을 위한 강력한 무기 체계를 제공한다. 이전 물건에 비해 강한 화력을 제공하고, 독자적인 X-Com 기술을 이용한다.\"\n  STR_DISPLACER_SONIC_UFOPEDIA: \"외계인의 기술은 무장 잠수정을 다시 정의했다. 이온 추진기를 활용하는 능력은 무장 잠수정이 더 이상 지면/해저에 구속되지 않는다는 뜻이다. 소닉 병기는 전장에서 진정한 이점을 준다.\"\n  STR_DISPLACER_PWT_UFOPEDIA: \"이 무장 잠수정은 수중 이용을 위한 펄스파 무기가 특징이다. 당신은 완전 무장을 유지하도록 반드시 펄스파 어뢰를 제조해야 한다. 쏘려면, 일련의 '경유지'를 선택한 후 발사 아이콘을 눌러라.\"\n  STR_ALIEN_PROBE_MISSION: \"외계인 탐사 임무\"\n  STR_ALIEN_INTERDICTION: \"외계인 차단\"\n  STR_ALIEN_RESOURCE_RAID: \"외계인 자원 약탈\"\n  STR_ALIEN_INFILTRATION: \"외계인 잠입\"\n  STR_ALIEN_BASE: \"외계인 식민지 확장\"\n  STR_ALIEN_SURFACE_ATTACK: \"외계인 지상 공격\"\n  STR_ALIEN_RETALIATION: \"부유 기지 공격\"\n  STR_ALIEN_SUPPLY: \"식민지 보급 임무\"\n  STR_ALIEN_PROBE_MISSION_UFOPEDIA: \"외계인 탐사 임무는 한 영역의 해저, 그 자원, 그리고 선박의 항해 및 항공기의 비행 경로에 관한 자료를 수집하는 데 이용된다. 이 임무에 투입된 외계인의 잠수함은 그 자체로 중대한 위협은 아니나, 그들은 언제라도 터질 지 모르는 활동 현장을 가리킨다.\"\n  STR_ALIEN_INTERDICTION_UFOPEDIA: \"외계인은 관심 있는 영역을 감시하는 정책을 지니는데, 더 집중적인 임무를 개시하기 전에 한 영역을 확보하려는 목적을 드러내는 기체를 보낸다. 그들은 그 영역을 봉쇄하고 다음 단계의 활동을 위한 방안을 준비하기 위해 이후 습격할 생각인 특정 현장에 착륙할 것이다.\"\n  STR_ALIEN_RESOURCE_RAID_UFOPEDIA: \"선박을 침몰시키는 것과 항공기를 추락시키는 것은 외계인 전략의 핵심 요소다. 재료의 획득은 주요 외계인 활동 중 한 가지고 이러한 것은 그들의 노골적인 적대 행동과 연계된다. 외계인은 또한 광물과 정제된 금속 및 다른 인간이 제조한 물품을 얻고자 지열 활동이 일어나는 현장, 채굴 현장 및 유적이 있는 현장을 습격한다.\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"이건 최고위 수준에서 외계인과 기업 또는 정부 간 공식적 접촉을 초래할 수 있다. 이 활동의 정점은 관련된 기구의 수역에서 집중적인 외계인 잠수함의 활동으로 구분된다. 외계인은 자신들의 우월한 기술에 대한 지식을 제공하는 것으로 정부 또는 조직과 협정을 체결하려 시도할 것이다. 이 외계인 활동은 X-Com에 대한 중대한 위협을 나타낸다. 만약 기업 또는 정부가 침략자와 협력한다면 그의 후원은 중지된다.\"\n  STR_ALIEN_BASE_UFOPEDIA: \"외계인은 외딴 지점에 비밀 해저 식민지를 건설할 것이다. 약간의 초기 정찰 비행 후 식민지가 지어지고 있는 동안 집중적인 외계 잠수함의 활동이 일어날 것이다. 이 식민지는 연구실, 복제실, 그리고 인간과 외계인의 실험을 위한 수술 시설이 들어 있다고 알려졌다. 외계인 식민지의 존재는 외계인 잠수함의 존재 없이도 더 많은 외계인 활동을 생성할 것이다. 식민지의 자리를 잡아 내려면 X-Com 비행잠수함은 성공적인 탐지 확률을 얻기 위해 어떤 영역을 수 시간 동안 반드시 순찰해야 한다.\"\n  STR_ALIEN_SURFACE_ATTACK_UFOPEDIA: \"외계인이 인간을 필요로 할 때 그들은 항구에 테러를 일으키거나, 섬을 공격하거나, 선박을 습격한다. 외계인의 비뚤어진 교배 필요성 및 그들의 추악한 실험을 채우기 위해, 민간인은 직접적으로 위협을 받을 것이다.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"만약 X-Com이 외계인 기체를 침몰시키는 데 특히 성공적이라면 외계인은 어떤 공격적인 보복 행동을 취할 지도 모른다. 이는 X-Com 시설에 대한 직접 공격을 초래할 수 있다. 그렇지만, 외계인은 X-Com을 공격하려면 그 기지를 찾아야 하고, 외계인 잠수함과 거리를 두면 강습의 위험은 거의 없을 것이다.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"일단 외계인 식민지가 건설된 후에 그건 특별한 보급 선박에 의해 정기적으로 재 보급을 받는다. 만약 이러한 함선 중 하나가 착지한 동안 탐지되었다면 이는 외계인 식민지가 주변에 있는 게 확실하다.\"\n  STR_SURVEY_SHIP_UFOPEDIA: \"이 조그마한 비행잠수함은 수색 및 조사 임무에 이용된다. 그건 외계인 특별 임무 활동의 시작 시 보통 더 커다란 함선에 앞서 나온다.\"\n  STR_ESCORT_UFOPEDIA: \"자체적으로 별 위협이 되지 않는 중간 크기의 호위 함선이다. 이 기체는 더 커다란 함선의 도착 및 늘어난 활동에 앞서 나온다.\"\n  STR_CRUISER_UFOPEDIA: \"순양함은 다목적 기체로, 외계인 함대의 주력이며, 모든 유형의 외계인 임무에 이용되고 위험한 상대다.\"\n  STR_HEAVY_CRUISER_UFOPEDIA: \"중순양함은 순양함보다 더 강력한 선박으로, 더 커다란 무기와 추진 장치는 그 위력을 강화한다. 중순양함은 커다란 양의 자원 및 장비를 수집하는 자원 임무에 이용된다.\"\n  STR_HUNTER_UFOPEDIA: \"이 함선은 인간 표본에 대한 실험 및 수술을 수행하는 실험실이 장착되었다. 피해자는 가장 악독한 고문의 대상이 되며 그 두뇌는 종종 제거되어 후속 처리를 위해 저장된다.\"\n  STR_BATTLESHIP_UFOPEDIA: \"전함은 외계인이 보유한 가장 공격적인 선박으로, 외계인이 행하기를 원하는 어떠한 형태의 공격적 행동도 행하기 위한 작전 기지로 쓰이는 데 필요한 모든 외계 기술 및 장치가 특징이다. 그건 내부에 다양한 종류의 무기가 실린다.\"\n  STR_DREADNOUGHT_UFOPEDIA: \"드레드노트는 엄청난 병력 수송함으로, 모든 외계인 기술과 광대한 화물로 완전 무장했다. 드레드노트는 억세고 만만치 않은 상대다.\"\n  STR_FLEET_SUPPLY_CRUISER_UFOPEDIA: \"함대 보급 순양함은 외계인 식민지의 건설이나 기존 식민지의 보급에 이용된다. 그건 외계인의 양분, DNA, 태아 및 다른 생물학적 부품을 나른다.\"\n  STR_DISMANTLE: \"철거\"\n  STR_FACILITY_IN_USE: \"수상 모듈을 이용 중이다\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"수상 모듈을 철거할 수 없다!{SMALLLINE}모든 기지의 수상 모듈은 반드시 기밀 출입구에 연결되어야 한다.\"\n  STR_TRANSFER_ITEMS_TO: \"물품을 {0} 기지로 이송\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"이송에 필요한 외계인 격리실이 없다!{SMALLLINE}산 외계인은 살려 두려면 외계인 격리실이 필요하다.\"\n  STR_AMOUNT_AT_DESTINATION: \"행선지에{NEWLINE}있는 양\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"외계인 격리실이 없기에 외계인이 죽었다.\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"빈 생활 공간이 없다!{SMALLLINE}행선지 기지는 생활관 안에 비행잠수함에 배속된 승무원을 위한 충분한 공간이 없다.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"저장 공간이 없다!{SMALLLINE}행선지 기지는 비행잠수함에 배속된 장비를 위한 충분한 저장 공간이 없다.\"\n  STR_ITEMS_ARRIVING: \"도착한 물품\"\n  STR_DESTINATION_UC: \"행선지\"\n  STR_DART_PISTOL: \"다트 권총\"\n  STR_DART_POD: \"다트 권총 탄창\"\n  STR_JET_HARPOON: \"제트 하푼 소총\"\n  STR_HARPOON_POD: \"제트 하푼 탄창\"\n  STR_GAS_CANNON: \"가스 포\"\n  STR_GC_AP_AMMO: \"가스 포 탄창/철갑\"\n  STR_GC_HE_AMMO: \"가스 포 탄창/고폭\"\n  STR_GC_P_AMMO: \"가스 포 탄창/인화\"\n  STR_HYDRO_JET_CANNON: \"하이드로제트 포\"\n  STR_HJC_AP_AMMO: \"하이드로제트 포 탄약/철갑\"\n  STR_HJC_HE_AMMO: \"하이드로제트 포 탄약/고폭\"\n  STR_HJC_P_AMMO: \"하이드로제트 포 탄약/인화\"\n  STR_TORPEDO_LAUNCHER: \"어뢰 발사기\"\n  STR_SMALL_TORPEDO: \"어뢰/소형\"\n  STR_LARGE_TORPEDO: \"어뢰/대형\"\n  STR_PHOSPHOROUS_TORPEDO: \"어뢰/백린\"\n  STR_MAGNA_BLAST_GRENADE: \"매그나블래스트 수류탄\"\n  STR_DYE_GRENADE: \"물감 수류탄\"\n  STR_PARTICLE_DISTURBANCE_GRENADE: \"입자 교란 수류탄\"\n  STR_MAGNA_PACK_EXPLOSIVE: \"매그나팩 고폭탄\"\n  STR_PARTICLE_DISTURBANCE_SENSOR: \"입자 교란 센서\"\n  STR_MEDI_KIT: \"메디킷\"\n  STR_MC_DISRUPTOR: \"M.C. 분열기\"\n  STR_THERMAL_TAZER: \"열 충격봉\"\n  STR_GAUSS_PISTOL: \"가우스 권총\"\n  STR_GAUSS_PISTOL_CLIP: \"가우스 권총 탄창\"\n  STR_GAUSS_RIFLE: \"가우스 소총\"\n  STR_GAUSS_RIFLE_CLIP: \"가우스 소총 탄창\"\n  STR_HEAVY_GAUSS: \"중형 가우스 총\"\n  STR_HEAVY_GAUSS_CLIP: \"중형 가우스 총 탄창\"\n  STR_SONIC_CANNON: \"소닉 포\"\n  STR_CANNON_POWER_CLIP: \"소닉 포 탄창\"\n  STR_SONIC_BLASTA_RIFLE: \"소닉 블래스타 소총\"\n  STR_BLASTA_POWER_CLIP: \"소닉 블래스타 탄창\"\n  STR_SONIC_PISTOL: \"소닉 권총\"\n  STR_PISTOL_POWER_CLIP: \"소닉 권총 탄창\"\n  STR_DISRUPTOR_PULSE_LAUNCHER: \"디스럽터 펄스 폭탄 발사기\"\n  STR_DISRUPTOR_AMMO: \"디스럽터 탄\"\n  STR_THERMAL_SHOK_LAUNCHER: \"열충격탄 발사기\"\n  STR_THERMAL_SHOK_BOMB: \"열충격 폭탄\"\n  STR_SONIC_PULSER: \"소닉 펄서\"\n  STR_ZRBITE: \"지바이트\"\n  STR_MC_READER: \"M.C. 판독기\"\n  STR_VIBRO_BLADE: \"초진동 칼날\"\n  STR_THERMIC_LANCE: \"써믹 랜스\"\n  STR_HEAVY_THERMIC_LANCE: \"중형 써믹 랜스\"\n  STR_AQUATOID_CORPSE: \"아쿠아토이드 시체\"\n  STR_GILLMAN_CORPSE: \"길맨 시체\"\n  STR_LOBSTERMAN_CORPSE: \"랍스터 맨 시체\"\n  STR_TASOTH_CORPSE: \"타소쓰 시체\"\n  STR_CALCINITE_CORPSE: \"캘시나이트 시체\"\n  STR_DEEP_ONE_CORPSE: \"딥원 시체\"\n  STR_BIODRONE_CORPSE: \"바이오드론 시체\"\n  STR_TENTACULAT_CORPSE: \"텐타쿨러트 시체\"\n  STR_TRISCENE_CORPSE: \"트라이신 시체\"\n  STR_HALLUCINOID_CORPSE: \"할루시노이드 시체\"\n  STR_XARQUID_CORPSE: \"자퀴드 시체\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"무장 잠수정을 무장하기 위한 탄약이 부족하다{SMALLLINE}각 무장 잠수정은 {0} {1}를 요구한다.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"분대를 완전히 재정비할 장비가 충분하지 않다\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"{1}{NEWLINE}의 생산을 위해{NEWLINE}{0}{NEWLINE}의 연구가 필요할 것이다.\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"외계인들은 무방비한 {0} 기지를 부수었다.\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"X-Com 순찰대가 {0}에서 외계인 식민지의 자리를 잡아 냈다\"\n  STR_STANDOFF: \"대치\"\n  STR_CAUTIOUS_ATTACK: \"소극적 공격\"\n  STR_STANDARD_ATTACK: \"표준적 공격\"\n  STR_AGGRESSIVE_ATTACK: \"적극적 공격\"\n  STR_DISENGAGING: \"교전 이탈\"\n  STR_UFO_HIT: \"외계인 비행잠수함에 명중!\"\n  STR_UFO_CRASH_LANDS: \"외계인 비행잠수함 격침!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"최소화는 대치 거리에서만 가능\"\n  STR_UFO_RETURN_FIRE: \"외계인 비행잠수함이 응사!\"\n  STR_INTERCEPTOR_DAMAGED: \">>> 비행잠수함 손상 <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> 비행잠수함 파괴 <<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"외계인 비행잠수함이 도망친다!\"\n  STR_LONG_RANGE_DETECTION: \"광대역 탐지기\"\n  STR_STORES_UC: \"창고\"\n  STR_DIFFICULTY_LEVEL: \"난이도\"\n  STR_INTERCEPT: \"요격\"\n  STR_BASES: \"기지\"\n  STR_GRAPHS: \"그래프\"\n  STR_UFOPAEDIA_UC: \"USO 사전\"\n  STR_OPTIONS_UC: \"옵션\"\n  STR_FUNDING_UC: \"후원금\"\n  STR_5_SECONDS: \"5초\"\n  STR_1_MINUTE: \"1분\"\n  STR_5_MINUTES: \"5분\"\n  STR_30_MINUTES: \"30분\"\n  STR_1_HOUR: \"1시간\"\n  STR_1_DAY: \"하루\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"X-Com 성과 내역\"\n  STR_ENTER_NAME: \"이름 입력\"\n  STR_PERFORMANCE_RATING: \"성과 평점\"\n  STR_VICTORY_DATE: \"승리한 날\"\n  STR_CHEMICAL_FLARE: \"화학 조명기\"\n  STR_CHEMICAL_FLARE_UFOPEDIA: \"이 조그마한 장치는 어떠한 심도나 마른 땅 위에서 밝은 섬광을 만들어낸다. 이는 깊은 바다 또는 야간 임무 중에 조명기 주변에 있는 적 유닛을 비춘다.\"\n  STR_MONTHLY_COSTS: \"월간 비용\"\n  STR_CRAFT_RENTAL: \"비행잠수함 대여비\"\n  STR_SALARIES: \"급여\"\n  STR_BASE_MAINTENANCE: \"기지 유지비\"\n  STR_COST_PER_UNIT: \"유닛 당 비용\"\n  STR_QUANTITY: \"수량\"\n  STR_TOTAL: \"합계\"\n  STR_IN_PSIONIC_TRAINING: \"M.C. 삽입물 이식 중\"\n  STR_FRONT_ARMOR: \"전면 장갑\"\n  STR_LEFT_ARMOR: \"좌측 장갑\"\n  STR_RIGHT_ARMOR: \"우측 장갑\"\n  STR_REAR_ARMOR: \"후면 장갑\"\n  STR_UNDER_ARMOR: \"하부 장갑\"\n  STR_ROUNDS: \"잔탄\"\n  STR_UNIT: \"유닛> {0}\"\n  STR_ENERGY: \"기력\"\n  STR_MORALE: \"사기\"\n  STR_ARMOR_: \"갑옷> {0}\"\n  STR_FRONT_ARMOR_UC: \"전면 장갑\"\n  STR_LEFT_ARMOR_UC: \"좌측 장갑\"\n  STR_RIGHT_ARMOR_UC: \"우측 장갑\"\n  STR_REAR_ARMOR_UC: \"후면 장갑\"\n  STR_SKILLS: \"기술> {0}\"\n  STR_LEVEL: \"층수> {0}\"\n  STR_HEAD: \"머리\"\n  STR_TORSO: \"몸통\"\n  STR_RIGHT_ARM: \"오른팔\"\n  STR_LEFT_ARM: \"왼팔\"\n  STR_RIGHT_LEG: \"오른발\"\n  STR_LEFT_LEG: \"왼발\"\n  STR_PAIN_KILLER: \"진통제\"\n  STR_STIMULANT: \"각성제\"\n  STR_HEAL: \"치료\"\n  STR_TIME_UNITS_SHORT: \"행동>{ALT}{0}\"\n  STR_WEIGHT: \"무게>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"반응>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"M.기술>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"M.강도>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"외계인 유물\"\n  STR_AMMO_ROUNDS_LEFT: \"탄종:{NEWLINE}남은{NEWLINE}탄환={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"진통제>{ALT}{0}{ALT}{NEWLINE}각성제>{ALT}{1}{ALT}{NEWLINE}치료>{ALT}{2}\"\n  STR_THROW: \"투척\"\n  STR_AUTO_SHOT: \"자동사격\"\n  STR_SNAP_SHOT: \"지향사격\"\n  STR_AIMED_SHOT: \"조준사격\"\n  STR_STUN: \"기절시키기\"\n  STR_PRIME_GRENADE: \"신관 설정\"\n  STR_USE_SCANNER: \"센서 이용\"\n  STR_USE_MEDI_KIT: \"메디킷 이용\"\n  STR_LAUNCH_MISSILE: \"어뢰 발사\"\n  STR_ACCURACY_SHORT: \"정확>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"행동력이 부족하다!\"\n  STR_NOT_ENOUGH_ENERGY: \"기력이 부족하다!\"\n  STR_NO_ROUNDS_LEFT: \"남은 탄환이 없다!\"\n  STR_NO_AMMUNITION_LOADED: \"장전된 탄약이 없다!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"이 무기의 탄약이 아니다!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"무기가 이미 장전되었다!\"\n  STR_NO_LINE_OF_FIRE: \"사선이 안 나온다!\"\n  STR_GRENADE_IS_ACTIVATED: \"수류탄이 켜졌다!\"\n  STR_GRENADE_IS_DEACTIVATED: \"수류탄이 꺼졌다!\"\n  STR_THERE_IS_NO_ONE_THERE: \"그곳에는 아무도 없다!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"연구할 때까지 외계인 유물은 이용할 수 없다!\"\n  STR_OUT_OF_RANGE: \"사거리 밖이다!\"\n  STR_UNABLE_TO_THROW_HERE: \"여기 던질 수 없다!\"\n  STR_SET_TIMER: \"타이머 설정\"\n  STR_HIDDEN_MOVEMENT: \"보이지 않는 이동\"\n  STR_TURN: \"턴> {0}\"\n  STR_SIDE: \"진영> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"계속하려면 버튼을 눌러라\"\n  STR_MIND_CONTROL: \"분자 제어\"\n  STR_PANIC_UNIT: \"삽입물 간섭\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"사기 공격 성공\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"삽입물 제어 성공\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}대원은 난폭해졌다\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}대원은 난폭해졌다\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}대원은 공황에 빠졌다\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}대원은 공황에 빠졌다\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"외계인\"\n  STR_RIGHT_HAND: \"오른손\"\n  STR_LEFT_HAND: \"왼손\"\n  STR_RIGHT_SHOULDER: \"오른어깨\"\n  STR_LEFT_SHOULDER: \"왼어깨\"\n  STR_BACK_PACK: \"배낭\"\n  STR_BELT: \"벨트\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}대원은 분자 제어 당한다\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}대원은 분자 제어 당한다\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}대원은 의식불명에 빠졌다\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}대원은 의식불명에 빠졌다\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}대원은 치명상으로 사망했다\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}대원은 치명상으로 사망했다\"\n  STR_USE_MIND_PROBE: \"M.C. 판독기 이용\"\n  STR_FATAL_WOUNDS: \"치명상\"\n  STR_UNDER_ARMOR_UC: \"하부 장갑\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"지향사격에 필요한 행동력을 남김\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"자동사격에 필요한 행동력을 남김\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"조준사격에 필요한 행동력을 남김\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"무릎꿇기에 필요한 행동력을 남김\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"무릎쏴에 필요한 행동력을 남김\"\n  STR_UNITS_IN_CRAFT:\n    other: \"{N} 명의 대원이 X-Com 기체에 있다\"\n  STR_UNITS_OUTSIDE:\n    other: \"{N} 명의 대원이 밖에 남겨져 있다\"\n  STR_UNITS_IN_ENTRANCE:\n    other: \"{N} 명의 대원이 입구에 있다\"\n  STR_UNITS_IN_EXIT:\n    other: \"{N} 명의 대원이 표적 출구에 있다\"\n  STR_ABORT_MISSION_QUESTION: \"임무 중단?\"\n  STR_CORPSE: \"시신\"\n  STR_UNLOAD_CRAFT: \"탄창 제거\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}대원은 살해되었다\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}대원은 살해되었다\"\n  STR_HIT_MELEE: \"타격\"\n  STR_GROUND: \"지면\"\n  STR_LIVING_QUARTERS_PLURAL: \"생활관\"\n  STR_LIST_ITEM: \"물품\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"잠수함 침몰로 모든 외계인이 죽었고.{NEWLINE}자동 회수를 개시했다\"\n  STR_RESET: \"초기화\"\n  STR_MEMORIAL: \"추모비\"\n  STR_DATE_UC: \"날짜\"\n  STR_SOLDIERS_RECRUITED_UC: \"고용된 잠수요원>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"잃은 잠수요원>{ALT}{0}\"\n  STR_REMOVE_SELECTED: \"선택된 목록 삭제\"\n  STR_LIVE_ALIENS: \"산{NEWLINE}표본\"\n  STR_DEAD_ALIENS: \"버릴{NEWLINE}표본\"\n  STR_UNDER_INTERROGATION: \"연구{NEWLINE}중\"\n  STR_CONTAINMENT_EXCEEDED: \"외계인 격리실 한도를 초과했다!{SMALLLINE}{0}에 있는 격리 공간이 불충분하다. 당신은 격리실에서 여분의 외계인을 반드시 제거해야 한다(그건 이후 죽을 것이다).\"\n  STR_MANAGE_CONTAINMENT: \"외계인 격리실 관리\"\n  STR_STORAGE_EXCEEDED: \"저장 공간을 초과했다!{SMALLLINE}{0}의 저장 공간이 불충분하다. 당신은 여분의 물품을 반드시 팔아 치워야 한다.\"\n  STR_GO_TO_BASE: \"기지로 이동\"\n  STR_MELEE_ACCURACY: \"격투술\"\n  STR_SELL_PRODUCTION: \"매각\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"양손 모두가 반드시 비어 있어야 한다!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"템플릿을 복사하기 위한 물품이 충분하지 않다!\"\n  STR_UNLOAD_WEAPON: \"탄창 제거\"\n  STR_ALL_ITEMS: \"모든 물품\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    other: \"더 이상 적재할 수 없다!{SMALLLINE}당신은 이 비행잠수함에 오직 최대 {N}개의 물품만 가져갈 수 있다.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}제어부를 부수었다{NEWLINE}입구로 길을 떠난 후 임무를 중단하라.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"X-Com 수상 모듈은 육지에 지어질 수 없다\"\n  STR_UNABLE_TO_ENGAGE_DEPTH: \"이 심도에서는{NEWLINE}적을 상대할 수 없다\"\n  STR_UNABLE_TO_ENGAGE_AIRBORNE: \"공중에 있을 때에는{NEWLINE}적을 상대할 수 없다\"\n  STR_UNDERWATER_EQUIPMENT: \"이 장비는 물 위에서 동작하지 않을 것이다.\"\n  STR_LAND_EQUIPMENT: \"이 장비는 수중에서 동작하지 않을 것이다!\"\n  STR_LEVEL_SHORT: \"L{0}\"\n  STR_PERSONNEL: \"직원\"\n  STR_CRAFT_ARMAMENT: \"기체 & 무장\"\n  STR_COMPONENTS: \"부품\"\n  STR_SOLDIERS_RECRUITED: \"고용한 잠수요원\"\n  STR_SOLDIERS_LOST: \"잃은 잠수요원\"\n  STR_TOTAL_UFOS: \"탐지된 비행잠수함\"\n  STR_TOTAL_ALIEN_BASES: \"발견된 외계인 식민지\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"MST\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"MSK\"\n  FEMALE_CIVILIAN: \"여성 민간인\"\n  MALE_CIVILIAN: \"남성 민간인\"\n  DOCKER_CIVILIAN: \"부두 근무 민간인\"\n  SAILOR_CIVILIAN: \"선원 민간인\"\n  STR_BIODRONE_MELEE_WEAPON: \"바이오드론 근접무기\"\n  HALLUCINOID_WEAPON: \"할루시노이드 무기\"\n  STR_LOBSTERMAN_MELEE_WEAPON: \"랍스터맨 근접무기\"\n  CALCINITE_WEAPON: \"캘시나이트 무기\"\n  DEEP_ONE_WEAPON: \"딥원 무기\"\n  STR_TRISCENE_MELEE_WEAPON: \"트라이신 근접무기\"\n  STR_TRIBIO_SONIC_WEAPON: \"외계인 소닉 무기\"\n  XARQUID_WEAPON: \"자퀴드 무기\"\n  TENTACULAT_WEAPON: \"텐타쿨러트 무기\"\n  ZOMBIE_WEAPON: \"좀비 무기\"\n  ALIEN_PSI_WEAPON: \"외계인 M.C. 무기\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/lb.yml",
    "content": "lb:\n  STR_SONIC_OSCILLATOR_UFOPEDIA: \"E STARKEN AKUSTESCHEN OSCILLATOR GENERÉIERT ENG WELL VUN SCHALLWELLEN DÉI D'ZIL DURCH MOLEKULARVIBRATIOUN ZERSTÉIERT.\"\n  STR_AQUATOID_AUTOPSY: \"Aquatoid Autopsie\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"OP DE SITE ZENTRÉIREN-ZÄIT=5 Sek.\"\n  STR_CANCEL_UC: \"OFBRIECHEN\"\n  STR_NONE: \"Keng\"\n  STR_UNKNOWN: \"Onbekannt\"\n  STR_POOR: \"Schlecht\"\n  STR_AVERAGE: \"Mëttel\"\n  STR_GOOD: \"Gutt\"\n  STR_EXCELLENT: \"Exzellent\"\n  STR_BUILD_NEW_BASE_UC: \"NEI BASIS BAUEN\"\n  STR_BASE_INFORMATION: \"BASIS INFO\"\n  STR_BUILD_FACILITIES: \"RAIMLECHKEETEN BAUEN\"\n  STR_RESEARCH: \"FORSCHUNG\"\n  STR_MANUFACTURE: \"HIERSTELLUNG\"\n  STR_TRANSFER_UC: \"TRANSFEREIREN\"\n  STR_PURCHASE_RECRUIT: \"KAFEN/ASTELLEN\"\n  STR_SACK: \"ENTLOOSSEN\"\n  STR_SELL_SACK_UC: \"VERKAFEN/ENTLOOSSEN\"\n  STR_GEOSCAPE_UC: \"GEOSCAPE\"\n  STR_NAME: \"Numm\"\n  STR_AREA: \"Areal\"\n  STR_BUILD_NEW_BASE: \"Nei Basis bauen\"\n  STR_CANCEL: \"Ofbriechen\"\n  STR_COST_UC: \"KÄSCHTEN>\"\n  STR_CONSTRUCTION_TIME_UC: \"KONSTRUKTIOUNSZÄIT>\"\n  STR_MAINTENANCE_UC: \"ËNNERHALT>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Installatioun\"\n  STR_CURRENT_RESEARCH: \"AKTUELL FORSCHUNG\"\n  STR_SCIENTISTS_AVAILABLE: \"Wëssenschaftler verfügbar>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Wëssenschaftler zougedeelt>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Laboen verfügbar>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"FORSCHUNGSPROJET\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"WËSSENSCHAFTLER ZOUGEDEELT\"\n  STR_PROGRESS: \"FORTSCHRËTT\"\n  STR_NEW_PROJECT: \"Neie Projet\"\n  STR_CANCEL_PROJECT: \"PROJET OFBRIECHEN\"\n  STR_NEW_RESEARCH_PROJECTS: \"NEI FORSCHUNGSPROJEKTER\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"WESSENTSCHAFTLER VERFÜGBAR>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"LABO PLAZ VERFÜGBAR>{ALT}{0}\"\n  STR_INCREASE: \"Méi\"\n  STR_DECREASE: \"Manner\"\n  STR_START_PROJECT: \"PROJET STARTEN\"\n  STR_CURRENT_PRODUCTION: \"AKTUELL PRODUKTIOUN\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Atelieren verfügbar>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Momentan Gelder>{ALT}{0}\"\n  STR_ITEM: \"DEEL\"\n  STR_UNITS_PRODUCED: \"Eenheeten produzéiert\"\n  STR_TOTAL_TO_PRODUCE: \"Unzuel déi produzéiert gëtt\"\n  STR_COST__PER__UNIT: \"Käschten{NEWLINE}pro{NEWLINE}Eenheet\"\n  STR_DAYS_HOURS_LEFT: \"Deeg/Stonnen iwwreg\"\n  STR_NEW_PRODUCTION: \"Nei Produktioun\"\n  STR_PRODUCTION_ITEMS: \"Produktioun\"\n  STR_CATEGORY: \"KATEGORIE\"\n  STR_START_PRODUCTION: \"PRODUKTIOUN STARTEN\"\n  STR_COST_PER_UNIT_: \"Käschten pro Eenheet>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Atelieren gebraucht>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"BRAUCH SPEZIALMATERIAL\"\n  STR_ITEM_REQUIRED: \"DEEL GEBRAUCHT\"\n  STR_UNITS_REQUIRED: \"EENHEETEN GEBRAUCHT\"\n  STR_UNITS_AVAILABLE: \"EENHEETEN VERFUGBAR\"\n  STR_STOP_PRODUCTION: \"PRODUKTIOUN STOPPEN\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"ATELIERS PLAZ VERFÜGBAR>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"PROFIT PRO MOUNT>{ALT}{0}\"\n  STR_INCREASE_UC: \"MÉI\"\n  STR_DECREASE_UC: \"MANNER\"\n  STR_UNITS_TO_PRODUCE: \"Eenheeten déi produzéiert ginn\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Personal kafen/astellen\"\n  STR_COST_OF_PURCHASES: \"Kafkàschten>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"KÄSCHTEN PRO EENHEET\"\n  STR_QUANTITY_UC: \"UNZUEL\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"PERSONAL VERFÜGBAR:PERSONAL TOTAL>\"\n  STR_SCIENTISTS: \"Wëssenschaftler\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"PLAZ BENOTZT:PLAZ VERFÜGBAR>\"\n  STR_LIVING_QUARTERS: \"Wunnräim\"\n  STR_STORES: \"Lager\"\n  STR_LABORATORIES: \"Laboen\"\n  STR_WORK_SHOPS: \"Atelieren\"\n  STR_DEFENSE_STRENGTH: \"Verteidegungsstäerkt\"\n  STR_TRANSFERS_UC: \"TRANSFEREN\"\n  STR_TRANSFERS: \"Transferen\"\n  STR_ARRIVAL_TIME_HOURS: \"Ukonftszäit (Stonnen)\"\n  STR_COST_: \"Käschten>{ALT}{0}\"\n  STR_AREA_: \"Areal>{ALT}{0}\"\n  STR_BASE_NAME: \"Numm fir d'Basis?\"\n  STR_TRANSFER: \"Transfer\"\n  STR_AMOUNT_TO_TRANSFER: \"UNZUEL FIR ZE TRANSFERÉIREN\"\n  STR_SELECT_DESTINATION_BASE: \"Zilbasis auswielen\"\n  STR_COST: \"Käschten\"\n  STR_TOTAL_UC: \"TOTAL\"\n  STR_INCOME: \"Akommes\"\n  STR_EXPENDITURE: \"Ausgaben\"\n  STR_MAINTENANCE: \"Ënnerhalt\"\n  STR_BALANCE: \"Bilanz\"\n  STR_FINANCE: \"Finanzen\"\n  STR_DATE_FIRST: \"{0}t(en)\"\n  STR_DATE_SECOND: \"{0}t(en)\"\n  STR_DATE_THIRD: \"{0}t(en)\"\n  STR_DATE_FOURTH: \"{0}t(en)\"\n  STR_FINANCE_THOUSANDS: \"$1000\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Net genuch Spezialmaterial fir d'Konstruktioun vun{NEWLINE}{0}{NEWLINE}Basis:{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Net genuch Finanzen fir{NEWLINE}{0}{NEWLINE}ze produzéiren zu{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"Produktioun vun{NEWLINE}{0}{NEWLINE}ass faerdeg{NEWLINE}Basis:{1}{NEWLINE}\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"Konstruktioun vun{NEWLINE}{0}{NEWLINE}ass faerdeg{NEWLINE}Basis:{1}{NEWLINE}\"\n  STR_OK_5_SECONDS: \"OK - 5 Sek\"\n  STR_RESEARCH_COMPLETED: \"Fuerschung fäerdeg\"\n  STR_VIEW_REPORTS: \"RAPPORT LIESEN\"\n  STR_WE_CAN_NOW_RESEARCH: \"Nei Forschungsméiglechkeet\"\n  STR_WE_CAN_NOW_PRODUCE: \"Nei Produktiounsméiglechkeet \"\n  STR_SUNDAY: \"SONNDEN\"\n  STR_MONDAY: \"MÉINDEN\"\n  STR_TUESDAY: \"DËNSCHDEN\"\n  STR_WEDNESDAY: \"MËTTWOCH\"\n  STR_THURSDAY: \"DONNESCHDEG\"\n  STR_FRIDAY: \"FREIDEG\"\n  STR_SATURDAY: \"SAMSDEN\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Net genuch {0} fir den {1} zu {2} opzefëllen\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Net genuch {0} fir {1} an {2} nei ze lueden\"\n  STR_ALIENS_DEFEATED: \"Aliens vernicht\"\n  STR_BASE_IS_LOST: \"Basis ass verluer\"\n  STR_BASE_IS_SAVED: \"Basis gouf gerett\"\n  STR_ALIENS_KILLED: \"ALIEN EMBRUED\"\n  STR_ALIEN_CORPSES_RECOVERED: \"ALIEN KIERPER GEBUERGEN\"\n  STR_LIVE_ALIENS_RECOVERED: \"LIEWEG ALIEN GEBUERGEN\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"ALIEN ARTEFAKTER GEBUERGEN\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"ZIVILISTEN VUN ALIEN GEKILLT\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"ZIVILISTEN EMBRUED VUN X-COM LEIT\"\n  STR_CIVILIANS_SAVED: \"ZIVILISTE GERETT\"\n  STR_XCOM_OPERATIVES_KILLED: \"X-COM LEIT EMBRUED GINN\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"X-COM LEIT VERMËSST\"\n  STR_BASE_UNDER_ATTACK: \"{0} gëtt ugegraff!\"\n  STR_BASE_DEFENSES_INITIATED: \"BASISVERTEIDEGUNG AGELEED\"\n  STR_FIRING: \"SCHÉISST\"\n  STR_HIT: \"TREFFER!\"\n  STR_MISSED: \"LAANSCHT!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Deeler verkafen/Personal entloossen\"\n  STR_VALUE_OF_SALES: \"WÄERT VUN DEN VERKEEF>{ALT}{0}\"\n  STR_FUNDS: \"GELDER> {ALT}{0}\"\n  STR_SELL_SACK: \"Verkafen/Entloossen\"\n  STR_VALUE: \"Wäert\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_BASE_DEFENSE: \"BASISVERTEIDEGUNG\"\n  STR_BASE_UC_: \"BASIS> {0}\"\n  STR_ALIENS_LAUNCH_ISLAND_TERROR: \"ALIEN STARTEN{NEWLINE}INSELATTACK ZU\"\n  STR_ISLAND_TERROR: \"ALIEN STARTEN INSELATTACK\"\n  STR_ALIENS_ATTACK_SHIPPING_ROUTE: \"ALIEN ATTACKÉIREN{NEWLINE}SCHËFFROUTE\"\n  STR_CARGO_SHIP_P1: \"CARGOSCHËFF DEEL EENT\"\n  STR_CARGO_SHIP_P2: \"CARGOSCHËFF DEEL ZWEE\"\n  STR_CRUISE_SHIP_P1: \"CROISIERESSCHËFF DEEL EENT\"\n  STR_CRUISE_SHIP_P2: \"CROISIERESSCHËFF DEEL ZWEE\"\n  STR_SHIP_RESCUE_MISSION: \"SCHËFFSRETTUNGSMISSIOUN\"\n  STR_ALIEN_ACTIVITY_DETECTED: \"ALIENAKTIVITÉIT ENTDECKT\"\n  STR_ALIEN_CONTACT_SITE_MISSION: \"ALIENKONTAKTSITESMISSIOUN\"\n  STR_ARTIFACT_SITE_P1: \"ALIENKONTAKTSITE DEEL EENT\"\n  STR_ARTIFACT_SITE_P2: \"ALIENKONTAKTSITE DEEL ZWEE\"\n  STR_NO_FREE_ACCOMODATION: \"KENG FRAI RAIM!{SMALLLINE}D'Zilbasis huet net genuch fräi Plaz an de Wunnräim.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"NET GENUCH ARBESCHTSRAIM VERFÜGBAR!{SMALLLINE}Bau en neien Atelier oder reduzéier d'Arbeschter vun aneren Projeten.\"\n  STR_NOT_ENOUGH_MONEY: \"NET GENUCH GELD!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"NET GENUCH PLAZ AM STOCK!{SMALLLINE}Bau en neien Stock oder transferéier Wueren aus dem Stock op eng aner Basis.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"NET GENUCH WUNNRAUM!{SMALLLINE}Bau nei Wunnquartéier oder transferéier Personal op eng aner Basis.\"\n  STR_LAUNCH_INTERCEPTION: \"OFFANGMANÖVER STARTEN\"\n  STR_CRAFT: \"FLIGER\"\n  STR_STATUS: \"STATUS\"\n  STR_BASE: \"BASIS\"\n  STR_READY: \"BEREED\"\n  STR_OUT: \"DOBAUSSEN\"\n  STR_REPAIRS: \"REPARATIOUN\"\n  STR_REFUELLING: \"NOTANKEN\"\n  STR_REARMING: \"BEWAFFNEN\"\n  STR_TARGET: \"ZIL: {0}\"\n  STR_WAY_POINT: \"WEEPUNKT\"\n  STR_YES: \"JO\"\n  STR_NO: \"NEE\"\n  STR_SELECT_DESTINATION: \"ZIL WIELEN\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"NEIE SITE FIR BASIS WIELEN\"\n  STR_RETURN_TO_BASE: \"ZERÉCK OP D'BASIS\"\n  STR_SELECT_NEW_TARGET: \"WIEL NEIT ZIL\"\n  STR_PATROL: \"PATRULLÉIREN\"\n  STR_STATUS_: \"STATUS>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"BESCHIEDEGT - FLITT ZERÉCK OP D'BASIS\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"WÉINEG BENSIN - FLITT ZERÉCK OP D'BASIS\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"MISSIOUN FÄERDEG - FLITT ZERÉCK OP D'BASIS\"\n  STR_PATROLLING: \"PATRULLÉIERT\"\n  STR_RETURNING_TO_BASE: \"FLITT ZERÉCK OP D'BASIS\"\n  STR_DESTINATION_UC_: \"ZIL: {0}\"\n  STR_BASE_UC: \"BASIS>{ALT}{0}\"\n  STR_SPEED_: \"GESCHW.>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"MAXIMAL GESCHW.>{ALT}{0}{ALT}\"\n  STR_FUEL: \"BENSIN>{ALT}{0}\"\n  STR_WEAPON_ONE: \"WAFF-1>{ALT}{0}\"\n  STR_NONE_UC: \"OUNI\"\n  STR_ROUNDS_: \"RONNEN>{ALT}{0}\"\n  STR_WEAPON_TWO: \"WAFF-2>{ALT}{0}\"\n  STR_BASE_: \"Basis>{0}\"\n  STR_NAME_UC: \"NUMM\"\n  STR_AMMO_: \"MUNITIOUN>{ALT}{0}\"\n  STR_CREW: \"CREW\"\n  STR_EQUIPMENT_UC: \"EQUIPEMENT\"\n  STR_ARMOR: \"RÜSTUNG\"\n  STR_MAX: \"MAX>{ALT}{0}\"\n  STR_COLONEL: \"Kommandant\"\n  STR_COMMANDER: \"Kapitän\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Wiel d'Ekipp fir {0}\"\n  STR_SORT_BY: \"SORTÉIREN NO...\"\n  STR_ORIGINAL_ORDER: \"UFANKSUEDER\"\n  STR_MISSIONS2: \"MISSIOUNEN\"\n  STR_KILLS2: \"EMBRUED\"\n  STR_WOUND_RECOVERY2: \"WONNENHEELUNG\"\n  STR_SPACE_AVAILABLE: \"PLAZ VERFÜGBAR>{ALT}{0}\"\n  STR_SPACE_USED: \"GEBRAUCHTE PLAZ>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"GEBRAUCHTE PLAZ\"\n  STR_RANK: \"RANG\"\n  STR_WOUNDED: \"VERLETZT\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Equipement fir {0}\"\n  STR_DEFENSE_VALUE: \"Verteidegungswert\"\n  STR_HIT_RATIO: \"Trefferquote\"\n  STR_BEGIN_MISSION: \"Missioun starten?\"\n  STR_SELECT_ARMAMENT: \"Rüstung wielen\"\n  STR_AMMUNITION_AVAILABLE: \"MUNITIOUN VERFÜGBAR\"\n  STR_ARMAMENT: \"BEWAFFNUNG\"\n  STR_NOT_AVAILABLE: \"-\"\n  STR_TYPE: \"TYP\"\n  STR_SELECT_ARMOR: \"Rüstung auswielen\"\n  STR_NORTH: \"NORDEN\"\n  STR_NORTH_EAST: \"NORDOSTEN\"\n  STR_EAST: \"OSTEN\"\n  STR_SOUTH_EAST: \"SÜD OST\"\n  STR_SOUTH: \"SÜD\"\n  STR_SOUTH_WEST: \"SÜDWEST\"\n  STR_WEST: \"WEST\"\n  STR_NORTH_WEST: \"NORDWEST\"\n  STR_SELECT_ACTION: \"AKTIOUN WIELEN\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"OFFÄNKMANÖVER WIEDERMAN\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"VERFOLGEN OUNI UGRËFF\"\n  STR_VERY_LARGE: \"GANZ GROUSS\"\n  STR_LARGE: \"GROUSS\"\n  STR_MEDIUM_UC: \"METTEL\"\n  STR_SMALL: \"KLENG\"\n  STR_VERY_SMALL: \"GANZ KLENG\"\n  STR_DETECTED: \"Entdeckt\"\n  STR_SIZE_UC: \"GREISST\"\n  STR_HEADING: \"RICHTUNG\"\n  STR_SPEED: \"GESCHWINDEGKEET\"\n  STR_TRACKING_LOST: \"ZIL VERLUER\"\n  STR_REDIRECT_CRAFT: \"FLIGER EMLEEDEN\"\n  STR_CRASH_SITE_: \"CRASH-PLAZ-{0}\"\n  STR_WAY_POINT_: \"WEEPUNKT-{0}\"\n  STR_TERROR_SITE: \"TERRORSITE-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}huet{NEWLINE}{1}erreecht\"\n  STR_NOW_PATROLLING: \"Patroulléiert\"\n  STR_ALIEN_ORIGINS: \"Alien Originen\"\n  STR_UFOPAEDIA: \"UFOpedia\"\n  STR_SELECT_ITEM: \"DEEL WIELEN\"\n  STR_ACCELERATION: \"BESCHLEUNIG.>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"BENSINSTANK>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"WAFFEBEHÄLTER>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"SCHUEDENSKAPAZITEIT>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"CARGORAUM>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Schued\"\n  STR_RANGE: \"Reechwäit\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Genauegkeet\"\n  STR_RE_LOAD_TIME: \"Nei-lued-Zäit\"\n  STR_SECONDS: \"{0}s\"\n  STR_DAMAGE_ARMOR_PIERCING: \"PANZERBRIECHEND\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"HÉIGEXPLOSIV\"\n  STR_DAMAGE_MELEE: \"NOKAMPF\"\n  STR_DAMAGE_ACID: \"SAIER\"\n  STR_DAMAGE_SMOKE: \"DAMP\"\n  STR_SHOT_TYPE: \"TYP\"\n  STR_ACCURACY_UC: \"GENAUEGKEET\"\n  STR_TIME_UNIT_COST: \"ZE KÄSCHTEN\"\n  STR_DAMAGE_UC: \"SCHUED\"\n  STR_AMMO: \"MUNITIOUN\"\n  STR_SHOT_TYPE_AUTO: \"Auto\"\n  STR_SHOT_TYPE_SNAP: \"Schnell\"\n  STR_SHOT_TYPE_AIMED: \"Gezilt\"\n  STR_CONSTRUCTION_TIME: \"Konstruktiounsdauer\"\n  STR_CONSTRUCTION_COST: \"Konstruktiounskäschten\"\n  STR_MAINTENANCE_COST: \"Ënnerhalungskäschten\"\n  STR_LOW: \"Niddreg\"\n  STR_MEDIUM: \"Mëttel\"\n  STR_HIGH: \"Héig\"\n  STR_WEAPON: \"Waff\"\n  STR_AMMUNITION: \"Munitioun\"\n  STR_EQUIPMENT: \"Equipement\"\n  STR_ALIEN_CORPSE: \"Alien Kierper\"\n  STR_PERSONAL_ARMOR: \"PERSOUNENPANZER\"\n  STR_RAW_MATERIALS: \"Réimaterial\"\n  STR_ALIEN: \"Alien\"\n  STR_ZOMBIE: \"Zombie\"\n  STR_LIVE_COMMANDER: \"Kommandant\"\n  STR_LIVE_NAVIGATOR: \"Navigator\"\n  STR_LIVE_MEDIC: \"Dokter\"\n  STR_LIVE_SOLDIER: \"Zaldot\"\n  STR_LIVE_TERRORIST: \"Terrorist\"\n  STR_EXAMINATION_ROOM: \"Analyseraum\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Neien Fighter-Transporter\"\n  STR_ARMOR_PIERCING: \"PANZERBRIECHEND\"\n  STR_SCIENTIST: \"Wëssenschaftler\"\n  STR_NORTH_ATLANTIC: \"Nord Atlantik\"\n  STR_SOUTH_ATLANTIC: \"Süd Atlantik\"\n  STR_INDIAN_OCEAN: \"Indeschen Ozean\"\n  STR_ARCTIC: \"Arktis\"\n  STR_NORTH_AMERICA: \"Nordamerika\"\n  STR_MAXIMUM_SPEED: \"Maximal Geschwindegkeet\"\n  STR_DAMAGE_CAPACITY: \"Schuedenskapazitéit\"\n  STR_WEAPON_POWER: \"Waffestäerkt\"\n  STR_WEAPON_RANGE: \"Waffereechwäit\"\n  STR_LABORATORY: \"Labo\"\n  STR_WORKSHOP: \"ATELIER\"\n  STR_GENERAL_STORES: \"Haptlager\"\n  STR_ALIEN_CONTAINMENT: \"Alien-Klimazell\"\n  STR_USA: \"USA\"\n  STR_CIVILIAN: \"Zivilist\"\n  STR_JAN: \"Jan\"\n  STR_FEB: \"Feb\"\n  STR_MAR: \"Mär\"\n  STR_APR: \"Abr\"\n  STR_MAY: \"Mee\"\n  STR_JUN: \"Jun\"\n  STR_JUL: \"Jul\"\n  STR_AUG: \"Aug\"\n  STR_SEP: \"Sep\"\n  STR_OCT: \"Okt\"\n  STR_NOV: \"Nov\"\n  STR_DEC: \"Dez\"\n  STR_INTERNATIONAL_RELATIONS: \"International Relatiounen\"\n  STR_COUNTRY: \"Land\"\n  STR_FUNDING: \"Finanzéirung\"\n  STR_CHANGE: \"Wiesselen\"\n  STR_WEAPON_SYSTEMS: \"WAFFENSYSTEMER\"\n  STR_DAMAGE_UC_: \"SCHUED>{ALT}{0}\"\n  STR_MAGNA_BLAST_GRENADE_UFOPEDIA: \"D'Standardausféierung vun der Granat huet e präzisen an sophistiquéierten Timer fir eng genau Kontroll.\"\n  STR_BATTLESHIP: \"Kampfschëff\"\n  MAP_XBASES: \"X-Com Basis\"\n  STR_RATING: \"RATING> {0}\"\n  STR_RATING_TERRIBLE: \"TERRIBEL!\"\n  STR_RATING_POOR: \"SCHWAACH!\"\n  STR_RATING_OK: \"OK\"\n  STR_RATING_GOOD: \"GUTT!\"\n  STR_RATING_EXCELLENT: \"EXZELLENT!\"\n  STR_SCORE: \"SCORE\"\n  STR_MONTH: \"Mount> {ALT}{0} {1}\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} sinn deels zefridde mat denger Aarbecht a bereet méi Gelder ze finanzéieren.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} an {1}\"\n  STR_KNOTS: \"{0} Kniet\"\n  STR_MONTHLY_RATING: \"Rating vum Mount> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Finanziell Ännerung> {ALT}{0}\"\n  STR_RACE: \"RASS\"\n  STR_MISSION: \"MISSIOUN\"\n  STR_ZONE: \"ZON\"\n  STR_ALLOCATE_RESEARCH: \"Forschung ufänken\"\n  STR_ALLOCATE_MANUFACTURE: \"Produktioun zoudeelen\"\n  STR_NEW_YORK: \"New York\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_MANILA: \"Manila\"\n  STR_HONG_KONG: \"Hong Kong\"\n  STR_SINGAPORE: \"Singapor\"\n  STR_BANGKOK: \"Bangkok\"\n  STR_BOMBAY: \"Bombay\"\n  STR_TOKYO: \"Tokyo\"\n  STR_SHANGHAI: \"Shanghai\"\n  STR_LONDON: \"London\"\n  STR_IN_TRAINING: \"Am{NEWLINE}Training?\"\n  STR_TARGETTED_BY: \"AM ZIL VUN:\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"huet kaum nach Bensin,{NEWLINE}flitt zeréck op d'Basis\"\n  STR_RANK_: \"RANG> {ALT}{0}\"\n  STR_MISSIONS: \"MISSIOUNEN> {ALT}{0}\"\n  STR_KILLS: \"KILLS> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"WONNENHEELUNG> {ALT}{0}\"\n  STR_TIME_UNITS: \"ZÄITEENHEETEN\"\n  STR_STAMINA: \"AUSDAUER\"\n  STR_HEALTH: \"LIEWEN\"\n  STR_BRAVERY: \"MUDD\"\n  STR_REACTIONS: \"REAKTIOUNEN\"\n  STR_FIRING_ACCURACY: \"SCHOSSGENAUEGKEET\"\n  STR_THROWING_ACCURACY: \"WORFGENAUEGKEET\"\n  STR_STRENGTH: \"STÄERKT\"\n  STR_NEW_RANK: \"NEIEN RANG\"\n  STR_PROMOTIONS: \"Promotiounen\"\n  STR_ALIEN_INFILTRATION: \"Alien Infiltratioun\"\n  STR_DISMANTLE: \"Demontéiren\"\n  STR_TRANSFER_ITEMS_TO: \"Géigestänn op {0} transferéiren\"\n  STR_AMOUNT_AT_DESTINATION: \"UNZUEL OP DER{NEWLINE}DESTINATIOUN\"\n  STR_ITEMS_ARRIVING: \"Deeler kommen un\"\n  STR_DESTINATION_UC: \"ZIL\"\n  STR_MEDI_KIT: \"1t-Hëllef-Kit\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Net genuch Equipement fir d'Ekipp voll ze equipéiren\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Du muss en{NEWLINE}{0}{NEWLINE} erforschen befier en {NEWLINE}{1}{NEWLINE}erforscht ka ginn\"\n  STR_STANDOFF: \"PATTSITUATIOUN\"\n  STR_CAUTIOUS_ATTACK: \"VIRSIICHTEG ATTACK\"\n  STR_STANDARD_ATTACK: \"STANDARDATTACK\"\n  STR_AGGRESSIVE_ATTACK: \"AGGRESSIV ATTACK\"\n  STR_DISENGAGING: \"ZERÉCKZÉIEN\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Nëmmen a Pattsituatioun minimiséieren\"\n  STR_STORES_UC: \"LAGER\"\n  STR_DIFFICULTY_LEVEL: \"Schwierëgkeetsgrad\"\n  STR_INTERCEPT: \"OFFENKEN\"\n  STR_BASES: \"BASEN\"\n  STR_GRAPHS: \"GRAFIKEN\"\n  STR_OPTIONS_UC: \"OPTIOUNEN\"\n  STR_FUNDING_UC: \"FINANZÉIRUNG\"\n  STR_5_SECONDS: \"5 Sek\"\n  STR_1_MINUTE: \"1 Min\"\n  STR_5_MINUTES: \"5 Mins\"\n  STR_30_MINUTES: \"30 Mins\"\n  STR_1_HOUR: \"1 Stonn\"\n  STR_1_DAY: \"1 Dag\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"X-Com Performance Tabell\"\n  STR_ENTER_NAME: \"Numm aginn\"\n  STR_PERFORMANCE_RATING: \"Performance Rating\"\n  STR_VICTORY_DATE: \"Triumphdatum\"\n  STR_MONTHLY_COSTS: \"Käschte pro Mount\"\n  STR_SALARIES: \"Paien\"\n  STR_BASE_MAINTENANCE: \"Basisennerhalt\"\n  STR_COST_PER_UNIT: \"Käschten pro Eenheet\"\n  STR_QUANTITY: \"Unzuel\"\n  STR_TOTAL: \"Total\"\n  STR_FRONT_ARMOR: \"Broschtpanzer\"\n  STR_LEFT_ARMOR: \"Panzerung lénks\"\n  STR_RIGHT_ARMOR: \"Panzerung riets\"\n  STR_REAR_ARMOR: \"Réckerüstung\"\n  STR_UNDER_ARMOR: \"Enner Rüstung\"\n  STR_UNIT: \"EENHEET> {0}\"\n  STR_ENERGY: \"ENERGIE\"\n  STR_MORALE: \"MORAL\"\n  STR_ARMOR_: \"PANZERUNG> {0}\"\n  STR_FRONT_ARMOR_UC: \"Viischt Panzerung\"\n  STR_LEFT_ARMOR_UC: \"LÉNKS RÜSTUNG\"\n  STR_RIGHT_ARMOR_UC: \"PANZERUNG RIETS\"\n  STR_REAR_ARMOR_UC: \"RÉCKERÜSTUNG\"\n  STR_SKILLS: \"FÄHEGKEETEN> {0}\"\n  STR_LEVEL: \"LEVEL> {0}\"\n  STR_HEAD: \"KAPP\"\n  STR_TORSO: \"TORSO\"\n  STR_RIGHT_ARM: \"RIETSEN ARM\"\n  STR_LEFT_ARM: \"LÉNKEN ARM\"\n  STR_RIGHT_LEG: \"RIETST BEEN\"\n  STR_LEFT_LEG: \"LENKST BEEN\"\n  STR_PAIN_KILLER: \"MËTTEL GÉINT PÉNG\"\n  STR_STIMULANT: \"STIMULANT\"\n  STR_HEAL: \"HEELUNG\"\n  STR_TIME_UNITS_SHORT: \"ZE>{ALT}{0}\"\n  STR_WEIGHT: \"Gewiicht>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"React>{ALT}{0}\"\n  STR_AMMO_ROUNDS_LEFT: \"MUNITIOUN:{NEWLINE}KUGELEN{NEWLINE}IWWREG={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Péng>{ALT}{0}{ALT}{NEWLINE}Opputsch>{ALT}{1}{ALT}{NEWLINE}Heelen>{ALT}{2}\"\n  STR_THROW: \"Werfen\"\n  STR_AUTO_SHOT: \"Autoschoss\"\n  STR_SNAP_SHOT: \"Schnellschoss\"\n  STR_AIMED_SHOT: \"Gezilte Schoss\"\n  STR_STUN: \"Betäuben\"\n  STR_PRIME_GRENADE: \"Granat scharf man\"\n  STR_USE_MEDI_KIT: \"1t-Hëllef benotzen\"\n  STR_ACCURACY_SHORT: \"Gen>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Net genuch Zäit-Eenheeten!\"\n  STR_NOT_ENOUGH_ENERGY: \"Net genuch Energie!\"\n  STR_NO_ROUNDS_LEFT: \"Keng Kugelen iwwreg!\"\n  STR_NO_AMMUNITION_LOADED: \"Keng Munitioun gelueden!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Falsch Munitioun fir des Waff!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"Waff ass schons gelueden!\"\n  STR_NO_LINE_OF_FIRE: \"Keng Schosslinn!\"\n  STR_GRENADE_IS_ACTIVATED: \"Granat ass aktivéiert!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Granat deaktivéiert!\"\n  STR_THERE_IS_NO_ONE_THERE: \"Do ass keen!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Kann d'Alien Artefakt net benotzen bis et erforscht gouf!\"\n  STR_OUT_OF_RANGE: \"Ausser Reechwäit!\"\n  STR_UNABLE_TO_THROW_HERE: \"Kann net dohin werfen!\"\n  STR_SET_TIMER: \"Timer setzen\"\n  STR_HIDDEN_MOVEMENT: \"VERSTOPPTE BEWEGUNG\"\n  STR_TURN: \"TUER> {0}\"\n  STR_SIDE: \"SÄIT> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Tast drécken fir weider ze maachen\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Moralesch Attack gelongen!\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}leeft Amok\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}leeft Amok\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}panikéiert\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}panikéiert\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Alien\"\n  STR_RIGHT_HAND: \"RIETS HAND\"\n  STR_LEFT_HAND: \"LENKS HAND\"\n  STR_RIGHT_SHOULDER: \"RIETS SCHELLER\"\n  STR_LEFT_SHOULDER: \"LÉNKS SCHËLLER\"\n  STR_BACK_PACK: \"RUCKSAK\"\n  STR_BELT: \"RIMM\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}ass bewosstlos ginn\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}ass bewosstlos ginn\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}as un enger fataler Wonn gestuerwen\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}as un enger fataler Wonn gestuerwen\"\n  STR_FATAL_WOUNDS: \"FATAL WONN\"\n  STR_UNDER_ARMOR_UC: \"PANZERUNG ËNNEN\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Zäiteenheeten fir Schnellschoss reservéiert\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Zäiteenheeten fir en Autoschoss reservéiert\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Zäiteenheete reservéiert fir gezilte Schoss\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Zäiteenheten fir ze knéien reservéiert\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"ZE reservéiert fir ze knéien a schéissen\"\n  STR_ABORT_MISSION_QUESTION: \"Missioun ofbriechen?\"\n  STR_CORPSE: \"Kierper\"\n  STR_UNLOAD_CRAFT: \"Entlueden\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}ass embrued ginn\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}ass embrued ginn\"\n  STR_HIT_MELEE: \"Treffer\"\n  STR_GROUND: \"BUEDEM\"\n  STR_LIVING_QUARTERS_PLURAL: \"Wunnräim\"\n  STR_LIST_ITEM: \"DEEL\"\n  STR_RESET: \"Reset\"\n  STR_MEMORIAL: \"Memorial\"\n  STR_DATE_UC: \"DATUM\"\n  STR_REMOVE_SELECTED: \"Ugewielten wechhuelen\"\n  STR_LIVE_ALIENS: \"Liëwegt{NEWLINE}Exemplar\"\n  STR_DEAD_ALIENS: \"Ofgeleent{NEWLINE}Exemplar\"\n  STR_UNDER_INTERROGATION: \"Gëtt{NEWLINE}studéiert\"\n  STR_CONTAINMENT_EXCEEDED: \"Alien-Klimazell Kapazitéit errecht.{SMALLLINE}Keng Plaz an der Alien-Klimazell zu {0}. Du muss e puer Alien aus der Klimazell eraushuelen (déi dann stierwen wäerten).\"\n  STR_MANAGE_CONTAINMENT: \"Alien-Klimazell verwalten\"\n  STR_STORAGE_EXCEEDED: \"LAGER IWWERFËLLT!{SMALLLINE}Net genuch Lagerplaz an der Basis {0}. Exzessiv Deeler musse verkaf ginn.\"\n  STR_GO_TO_BASE: \"Zur Basis goen\"\n  STR_MELEE_ACCURACY: \"NOKAMPFGENAUEGKEET\"\n  STR_SELL_PRODUCTION: \"VERKAFEN\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Béid Hänn mussen eidel sinn!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Net genuch Deeler fir den Template ze kopéieren\"\n  STR_UNLOAD_WEAPON: \"Waff entlueden\"\n  STR_ALL_ITEMS: \"All Deeler\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}KONTROLLZENTER ZERSTÉIERT{NEWLINE}Maach dech zeréck bei den Agang a briech of.\"\n  STR_PERSONNEL: \"Personal\"\n  STR_CRAFT_ARMAMENT: \"Fliger & Bewaffnung\"\n  STR_COMPONENTS: \"Komponenten\"\n  FEMALE_CIVILIAN: \"Zivilist, weiblech\"\n  MALE_CIVILIAN: \"Zivilist, männlech\"\n  ZOMBIE_WEAPON: \"Zombiewaff\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/lv.yml",
    "content": "lv:\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"Centrēt uz atrašanās vietu, laiks = 5 Sekundes\"\n  STR_CANCEL_UC: \"ATCELT\"\n  STR_NONE: \"Nekāds\"\n  STR_UNKNOWN: \"Nezināms\"\n  STR_POOR: \"Slikti\"\n  STR_AVERAGE: \"Vidēji\"\n  STR_GOOD: \"Labi\"\n  STR_EXCELLENT: \"Lieliski\"\n  STR_BUILD_NEW_BASE_UC: \"CELT JAUNU BĀZI\"\n  STR_BASE_INFORMATION: \"BĀZES INFORMĀCIJA\"\n  STR_BUILD_FACILITIES: \"CELT STRUKTŪRAS\"\n  STR_RESEARCH: \"IZPĒTE\"\n  STR_MANUFACTURE: \"RAŽOT\"\n  STR_TRANSFER_UC: \"PĀRVEST\"\n  STR_PURCHASE_RECRUIT: \"PIRKT/REKRUTĒT\"\n  STR_SACK: \"ATLAIST\"\n  STR_SELL_SACK_UC: \"PĀRDOT/ATLAIST\"\n  STR_GEOSCAPE_UC: \"Zemes ainava\"\n  STR_NAME: \"Vārds\"\n  STR_AREA: \"Zona\"\n  STR_BUILD_NEW_BASE: \"Uzcelt Jaunu Bāzi\"\n  STR_CANCEL: \"Atcelt\"\n  STR_COST_UC: \"CENA>\"\n  STR_CONSTRUCTION_TIME_UC: \"BŪVNIECĪBAS LAIKS>\"\n  STR_MAINTENANCE_UC: \"UZTURĒŠANA>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Instalācija\"\n  STR_CURRENT_RESEARCH: \"PAŠREIZĒJĀ IZPĒTE\"\n  STR_SCIENTISTS_AVAILABLE: \"Zinātnieki Pieejami>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Piešķirtie Zinātnieki>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Pieejamā Vieta Labaratorijā>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"IZPĒTES PROJEKTS\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"ZINĀTNIEKI PĒTNIECĪBĀ\"\n  STR_PROGRESS: \"PROGRESS\"\n  STR_NEW_PROJECT: \"Jauns projekts\"\n  STR_CANCEL_PROJECT: \"ATCELT PROJEKTU\"\n  STR_NEW_RESEARCH_PROJECTS: \"JAUNI IZPĒTES PROJEKTI\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"ZINĀTNIEKI PIEEJAMI>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"PIEEJAMĀ VIETA LABARATORIJĀ>{ALT}{0}\"\n  STR_INCREASE: \"Palielināt\"\n  STR_DECREASE: \"Samazināt\"\n  STR_START_PROJECT: \"SĀKT PROJEKTU\"\n  STR_CURRENT_PRODUCTION: \"PAŠREIZĒJĀ PRODUKCIJA\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Pieejamā Vieta Darbnīcā>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Pašreizējie Fondi>{ALT}{0}\"\n  STR_UNITS_PRODUCED: \"Vienības Saražotas\"\n  STR_COST__PER__UNIT: \"Izmaksas{NEWLINE}par{NEWLINE}Vienību\"\n  STR_DAYS_HOURS_LEFT: \"Dienas/stundas palikušas\"\n  STR_NEW_PRODUCTION: \"Jauna produkcija\"\n  STR_CATEGORY: \"KATEGORIJA\"\n  STR_START_PRODUCTION: \"SĀKT PRODUKCIJU\"\n  STR_COST_PER_UNIT_: \"Vienas vienības izmaksas>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"NEPIECIEŠAMI SPECIALIZĒTI MATERIĀLI\"\n  STR_UNITS_REQUIRED: \"VIENĪBAS VAJADZĪGAS\"\n  STR_UNITS_AVAILABLE: \"VIENĪBAS PIEEJAMAS\"\n  STR_STOP_PRODUCTION: \"PĀRTRAUKT IZGATAVOŠANU\"\n  STR_INCREASE_UC: \"Palielināt\"\n  STR_DECREASE_UC: \"SAMAZINĀT\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Pirkt/Algot Personālu\"\n  STR_COST_PER_UNIT_UC: \"IZMAKSA PAR VIENU VIENĪBU\"\n  STR_QUANTITY_UC: \"SKAITS\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"PIEEJAMAIS PERSONĀLS:PERSONĀLS KOPĀ>\"\n  STR_SCIENTISTS: \"Zinātnieki\"\n  STR_LIVING_QUARTERS: \"Dzīvojamās Telpas\"\n  STR_STORES: \"Noliktavas\"\n  STR_LABORATORIES: \"Laboratorijas\"\n  STR_WORK_SHOPS: \"Darbnīcas\"\n  STR_DEFENSE_STRENGTH: \"Aizsardzības spēks\"\n  STR_TRANSFERS_UC: \"PĀRSKAITĪJUMI\"\n  STR_ARRIVAL_TIME_HOURS: \"Ierašanās laiks (stundās)\"\n  STR_COST_: \"Izmaksa>{ALT}{0}\"\n  STR_AREA_: \"Zona>{ALT}{0}\"\n  STR_BASE_NAME: \"Bāzes Nosaukums?\"\n  STR_TRANSFER: \"Pārvest\"\n  STR_SELECT_DESTINATION_BASE: \"Norādiet bāzi galamērķim\"\n  STR_COST: \"Izmaksa\"\n  STR_TOTAL_UC: \"KOPSUMMA\"\n  STR_INCOME: \"Ienākums\"\n  STR_EXPENDITURE: \"Izdevumi\"\n  STR_MAINTENANCE: \"Uzturēšana\"\n  STR_BALANCE: \"Balanss\"\n  STR_FINANCE: \"Finanses\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Nepietiekami speciālo materiālu lai producētu{NEWLINE}{0}{NEWLINE}uz{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Nepietiekami naudas līdzekļu lai producētu{NEWLINE}{0}{NEWLINE}uz{NEWLINE}{1}\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"Būvniecība{NEWLINE}{0}{NEWLINE}uz{NEWLINE}{1}{NEWLINE}ir pabeigta\"\n  STR_OK_5_SECONDS: \"OK - 5 sekundes\"\n  STR_RESEARCH_COMPLETED: \"Pētījums pabeigts\"\n  STR_VIEW_REPORTS: \"APSKATĪT ZIŅOJUMUS\"\n  STR_WE_CAN_NOW_RESEARCH: \"Mēs tagad varam izpētīt\"\n  STR_WE_CAN_NOW_PRODUCE: \"Mēs tagad varam producēt\"\n  STR_SUNDAY: \"SVĒTDIENA\"\n  STR_MONDAY: \"PIRMDIENA\"\n  STR_TUESDAY: \"OTRDIENA\"\n  STR_WEDNESDAY: \"TREŠDIENA\"\n  STR_THURSDAY: \"CETURTDIENA\"\n  STR_FRIDAY: \"PIEKTDIENA\"\n  STR_SATURDAY: \"SESTDIENA\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Nepietiek {0}, lai uzpildītu degvielu {1} pie {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Nav pietiekami{0} lai apbruņot {1} uz {2}\"\n  STR_ALIENS_DEFEATED: \"Citplanētieši tika pieveikti\"\n  STR_BASE_IS_LOST: \"Bāze tika zaudēta\"\n  STR_BASE_IS_SAVED: \"Bāze ir pasargāta\"\n  STR_ALIENS_KILLED: \"CITPLANĒTIEŠI NOGALINĀTI\"\n  STR_ALIEN_CORPSES_RECOVERED: \"ATGŪTIE CITPLANĒTIEŠU LĪĶI\"\n  STR_LIVE_ALIENS_RECOVERED: \"DZĪVI CITPLANĒTIEŠI ATGŪTI\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"CITPLANĒTIEŠU ARTIFAKTI ATGŪTI\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"CITPLANĒTIEŠIEM NOGALINĀTIE CIVILIEDZĪVOTĀJI\"\n  STR_CIVILIANS_SAVED: \"CIVILIEDZĪVOTĀJI IZGLĀBTI \"\n  STR_BASE_UNDER_ATTACK: \"{0} under attack!\"\n  STR_FIRING: \"ŠAUJ\"\n  STR_HIT: \"TRĀPĪJUMS!\"\n  STR_FUNDS: \"NAUDAS LĪDZEKĻĪ> {ALT}{0}\"\n  STR_SELL_SACK: \"Pārdot/Atlaist\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"NEPIETIEKAMI DARBA VIETAS PIEEJAMS! {SMALLLINE} Uzbūvējiet jaunu darbnīcu vai samazināt darbu pie citiem projektiem.\"\n  STR_NOT_ENOUGH_MONEY: \"NEPIETIEKAMI NAUDAS!\"\n  STR_LAUNCH_INTERCEPTION: \"UZSĀKT IZSEKOŠANU\"\n  STR_BASE: \"BĀZE\"\n  STR_READY: \"GATAVS\"\n  STR_TARGET: \"MĒRĶIS: {0}\"\n  STR_YES: \"JĀ\"\n  STR_NO: \"NĒ\"\n  STR_SELECT_DESTINATION: \"IZVĒLATIES GALAPUNKTU\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"Izvēlēties vietu priekš jaunas bāzes\"\n  STR_RETURN_TO_BASE: \"ATGRIEZTIES UZ BĀZI\"\n  STR_SELECT_NEW_TARGET: \"IZVĒLIES JAUNU MĒRĶI\"\n  STR_MAXIMUM_SPEED_UC: \"MAKSIMĀLAIS ĀTRUMS>{ALT}{0}{ALT}\"\n  STR_WEAPON_ONE: \"IEROCIS-1>{ALT}{0}\"\n  STR_NONE_UC: \"NAV\"\n  STR_BASE_: \"Bāze>{0}\"\n  STR_NAME_UC: \"VĀRDS\"\n  STR_AMMO_: \"MUNĪCIJA>{ALT}{0}\"\n  STR_ARMOR: \"BRUŅAS\"\n  STR_SPACE_AVAILABLE: \"VIETA PIEEJAMA>{ALT}{0}\"\n  STR_WOUNDED: \"Ievainots\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Aprīkojums priekš {0}\"\n  STR_DEFENSE_VALUE: \"Aizsardzība\"\n  STR_SELECT_ARMAMENT: \"Izvēlaties Ekipējumu\"\n  STR_AMMUNITION_AVAILABLE: \"MUNĪCIJA PIEEJAMA\"\n  STR_ARMAMENT: \"BRUŅOJUMS\"\n  STR_SELECT_ARMOR: \"Izvēlaties Bruņas\"\n  STR_NORTH_EAST: \"ZIEMEĻAUSTRUMI\"\n  STR_EAST: \"AUSTRUMI\"\n  STR_SOUTH_EAST: \"DIENVIDAUSTRUMI\"\n  STR_SOUTH_WEST: \"Dienvidrietumi\"\n  STR_NORTH_WEST: \"ZIEMEĻRIETUMI\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"TURPINĀT TVARSTĪŠANU\"\n  STR_VERY_LARGE: \"ĻOTI LIELS\"\n  STR_MEDIUM_UC: \"VIDĒJI\"\n  STR_SMALL: \"MAZS\"\n  STR_DETECTED: \"Atklāts\"\n  STR_SIZE_UC: \"LIELUMS\"\n  STR_CRASH_SITE_: \"AVĀRIJAS NOTIKUMA VIETA-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}ir sasniedzis{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"Patrulē\"\n  STR_ALIEN_ORIGINS: \"Citplanētiešu izcelšanās\"\n  STR_SELECT_ITEM: \"IZVĒLĒTIES IERĪCI\"\n  STR_FUEL_CAPACITY: \"Degvielas tvertne>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"BOJĀJUMU JAUDA>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Bojājumi\"\n  STR_RANGE: \"Attālums\"\n  STR_KILOMETERS: \"{0} kilometri\"\n  STR_DAMAGE_SMOKE: \"DŪMI\"\n  STR_ACCURACY_UC: \"PRECIZITĀTE\"\n  STR_DAMAGE_UC: \"BOJĀJUMI\"\n  STR_AMMO: \"MUNĪCIJA\"\n  STR_CONSTRUCTION_COST: \"Celtniecības Izmaksas\"\n  STR_MAINTENANCE_COST: \"Uzturēšanas izmaksas\"\n  STR_LOW: \"Zema\"\n  STR_MEDIUM: \"Vidējs\"\n  STR_WEAPON: \"Ierocis\"\n  STR_AMMUNITION: \"Munīcija\"\n  STR_PERSONAL_ARMOR: \"Personālās Bruņas\"\n  STR_ALIEN: \"Svešzemis\"\n  STR_ZOMBIE: \"Zombijs\"\n  STR_LIVE_MEDIC: \"Ārsts\"\n  STR_LIVE_TERRORIST: \"Terorists\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Jauns Cīnītājs-Transportieris\"\n  STR_NORTH_ATLANTIC: \"Ziemeļatlantija\"\n  STR_SOUTH_ATLANTIC: \"Dienvidatlantija\"\n  STR_ARCTIC: \"Arktika\"\n  STR_NORTH_AMERICA: \"Ziemeļamerika\"\n  STR_DAMAGE_CAPACITY: \"Bojājumu kapacitāte\"\n  STR_WEAPON_POWER: \"Ieroča spēks\"\n  STR_LABORATORY: \"Labaratorija\"\n  STR_FEB: \"Feb.\"\n  STR_MAR: \"Mar.\"\n  STR_APR: \"Aprīlis\"\n  STR_MAY: \"Mai.\"\n  STR_JUN: \"Jūnijs\"\n  STR_JUL: \"Jūlijs\"\n  STR_OCT: \"Okt.\"\n  STR_COUNTRY: \"Valsts\"\n  STR_FUNDING: \"Finansējums\"\n  STR_CHANGE: \"Mainīt\"\n  STR_WEAPON_SYSTEMS: \"IEROČU SISTĒMAS\"\n  STR_DAMAGE_UC_: \"BOJĀJUMS>{ALT}{0}\"\n  STR_RATING: \"REITINGS> {0}\"\n  STR_RATING_POOR: \"SLIKTI!\"\n  STR_RATING_OK: \"OK\"\n  STR_COUNTRIES_AND: \"{0} un {1}\"\n  STR_KNOTS: \"{0} mezgli\"\n  STR_ZONE: \"ZONA\"\n  STR_ALLOCATE_RESEARCH: \"Pētniecība\"\n  STR_NEW_YORK: \"Ņujorka\"\n  STR_VANCOUVER: \"Vankūvera\"\n  STR_WELLINGTON: \"Velingtona\"\n  STR_HONG_KONG: \"Honkonga\"\n  STR_SINGAPORE: \"Singapūra\"\n  STR_BANGKOK: \"Bangkoka\"\n  STR_TOKYO: \"Tokija\"\n  STR_SHANGHAI: \"Šanhaja\"\n  STR_LONDON: \"Londona\"\n  STR_RANK_: \"RANGS> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"ATVESEĻOŠANĀS> {ALT}{0}\"\n  STR_STAMINA: \"IZTURĪBA\"\n  STR_REACTIONS: \"REAKCIJA\"\n  STR_FIRING_ACCURACY: \"ŠAUŠANAS PRECIZITĀTE\"\n  STR_THROWING_ACCURACY: \"MEŠANAS PRECIZITĀTE\"\n  STR_STRENGTH: \"SPĒKS\"\n  STR_NEW_RANK: \"JAUNS RANGS\"\n  STR_PROMOTIONS: \"Paaugstinājumi\"\n  STR_ALIEN_INFILTRATION: \"Citplanētiešu infiltrācija\"\n  STR_DISMANTLE: \"Demontēt\"\n  STR_TRANSFER_ITEMS_TO: \"Pārvest ekipējumu uz {0}\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Nepietiek ekipējuma, lai atkārtoti pilnībā aprīkotu komandu\"\n  STR_CAUTIOUS_ATTACK: \"PIESARDZĪGS UZBRUKUMS\"\n  STR_STANDARD_ATTACK: \"STANDARTA UZBRUKUMS\"\n  STR_AGGRESSIVE_ATTACK: \"AGRESĪVS UZBRUKUMS\"\n  STR_INTERCEPT: \"PĀRTVERT\"\n  STR_BASES: \"BĀZES\"\n  STR_OPTIONS_UC: \"IZVĒLES\"\n  STR_FUNDING_UC: \"FINANSĒJUMS\"\n  STR_1_MINUTE: \"1 min.\"\n  STR_30_MINUTES: \"30 min.\"\n  STR_1_HOUR: \"1 Stunda\"\n  STR_1_DAY: \"1 Diena\"\n  STR_ENTER_NAME: \"Ievadiet vārdu\"\n  STR_PERFORMANCE_RATING: \"Snieguma Reitings\"\n  STR_VICTORY_DATE: \"Uzvaras Datums\"\n  STR_SALARIES: \"Algas\"\n  STR_COST_PER_UNIT: \"Vienas vienības izmaksa\"\n  STR_QUANTITY: \"Skaits\"\n  STR_REAR_ARMOR: \"Aizmugures bruņas\"\n  STR_UNDER_ARMOR: \"Apakš Bruņas\"\n  STR_UNIT: \"VIENĪBA> {0}\"\n  STR_ENERGY: \"ENERGIJA\"\n  STR_MORALE: \"MORĀLE\"\n  STR_FRONT_ARMOR_UC: \"PRIEKŠAS BRUŅAS\"\n  STR_REAR_ARMOR_UC: \"MUGURAS BRUŅAS\"\n  STR_SKILLS: \"IEMAŅAS> {0}\"\n  STR_HEAD: \"GALVA\"\n  STR_TORSO: \"TORSS\"\n  STR_LEFT_ARM: \"KREISĀ ROKA\"\n  STR_LEFT_LEG: \"KREISĀ KĀJA\"\n  STR_PAIN_KILLER: \"PRETSĀPJU LĪDZEKLIS\"\n  STR_HEAL: \"VESEĻOT\"\n  STR_THROW: \"Mest\"\n  STR_AUTO_SHOT: \"Auto-šaušana\"\n  STR_STUN: \"Apdullināt\"\n  STR_USE_MEDI_KIT: \"Izmantot aptieciņu\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Nepietiek laika vienības!\"\n  STR_NO_AMMUNITION_LOADED: \"Munīcija nav ielādēta!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"Ierocis jau ir uzlādēts!\"\n  STR_GRENADE_IS_ACTIVATED: \"Granāta aktivizēta!\"\n  STR_THERE_IS_NO_ONE_THERE: \"Tur nav neviens!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Nevar izmantot citplanētiešu artefaktu kamēr tas nav izpētīts!\"\n  STR_OUT_OF_RANGE: \"Ārpus diapazonas!\"\n  STR_UNABLE_TO_THROW_HERE: \"Tur nevar mest!\"\n  STR_SET_TIMER: \"Uzlikt Taimeri\"\n  STR_HIDDEN_MOVEMENT: \"PASLĒPTĀ KUSTĪBA\"\n  STR_TURN: \"KĀRTA> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Nospiediet pogu lai turpinātu\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}kļuvis ļoti dusmīgs\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}kļuvis ļoti dusmīgs\"\n  STR_HAS_PANICKED_MALE: \"{0} {NEWLINE} ir panikā\"\n  STR_HAS_PANICKED_FEMALE: \"{0} {NEWLINE} ir panikā\"\n  STR_ALIENS: \"Citplanētieši\"\n  STR_RIGHT_HAND: \"LABĀ ROKA\"\n  STR_LEFT_HAND: \"KREISĀ ROKA\"\n  STR_RIGHT_SHOULDER: \"LABAIS PLECS\"\n  STR_BACK_PACK: \"MUGURSOMA\"\n  STR_BELT: \"JOSTA\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0} {NEWLINE} nomira no letālajām brūcēm\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0} {NEWLINE} nomira no letālajām brūcēm\"\n  STR_FATAL_WOUNDS: \"LETĀLIE IEVAINOJUMI\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Laika Vienības rezervētas priekš (snap shot)\"\n  STR_UNLOAD_CRAFT: \"Izkraut\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}tika nogalināts(a)\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}tika nogalināts(a)\"\n  STR_LIVING_QUARTERS_PLURAL: \"Dzīvojamās Telpas\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Abām rokām jābūt tukšām!\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/nl.yml",
    "content": "nl:\n  STR_AQUATOID_AUTOPSY: \"Aquatoid autopsie\"\n  STR_GILLMAN_AUTOPSY: \"Gillman autopsie\"\n  STR_LOBSTERMAN_AUTOPSY: \"Lobsterman autopsie\"\n  STR_TASOTH_AUTOPSY: \"Tasoth autopsie\"\n  STR_DEEP_ONE_AUTOPSY: \"Deep One autopsie\"\n  STR_BIODRONE_AUTOPSY: \"Bio-Drone autopsie\"\n  STR_TENTACULAT_AUTOPSY: \"Tentaculat autopsie\"\n  STR_CALCINITE_AUTOPSY: \"Calcinite autopsie\"\n  STR_TRISCENE_AUTOPSY: \"Triscene autopsie\"\n  STR_HALLUCINOID_AUTOPSY: \"Hallucinoid autopsie\"\n  STR_XARQUID_AUTOPSY: \"Xarquid autopsie\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"CENTREREN OP LOCATIE-TIJD=5 Sec\"\n  STR_CANCEL_UC: \"ANNULEREN\"\n  STR_NONE: \"Geen\"\n  STR_UNKNOWN: \"Onbekend\"\n  STR_POOR: \"Zwak\"\n  STR_AVERAGE: \"Gemiddeld\"\n  STR_GOOD: \"Goed\"\n  STR_EXCELLENT: \"Uitstekend\"\n  STR_BUILD_NEW_BASE_UC: \"NIEUWE BASIS BOUWEN\"\n  STR_BASE_INFORMATION: \"BASIS-INFORMATIE\"\n  STR_BUILD_FACILITIES: \"FACILITEITEN BOUWEN\"\n  STR_RESEARCH: \"ONDERZOEK\"\n  STR_MANUFACTURE: \"PRODUCTIE\"\n  STR_TRANSFER_UC: \"OVERPLAATSINGEN\"\n  STR_PURCHASE_RECRUIT: \"AANKOPEN/WERVEN\"\n  STR_SACK: \"ONTSLAAN\"\n  STR_SELL_SACK_UC: \"VERKOPEN/ONTSLAAN\"\n  STR_GEOSCAPE_UC: \"GLOBE\"\n  STR_NAME: \"Naam\"\n  STR_AREA: \"Gebied\"\n  STR_BUILD_NEW_BASE: \"Nieuwe Basis Bouwen\"\n  STR_CANCEL: \"Annuleren\"\n  STR_COST_UC: \"PRIJS>\"\n  STR_CONSTRUCTION_TIME_UC: \"BOUWTIJD>\"\n  STR_MAINTENANCE_UC: \"ONDERHOUD>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Installatie\"\n  STR_CURRENT_RESEARCH: \"HUIDIG ONDERZOEK\"\n  STR_SCIENTISTS_AVAILABLE: \"Onderzoekers Beschikbaar>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Onderzoekers Toegewezen>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Laboratorium Ruimte Beschikbaar>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"ONDERZOEKSPROJECT\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"TOEGEWEZEN WETENSCHAPPERS\"\n  STR_PROGRESS: \"VOORTGANG\"\n  STR_NEW_PROJECT: \"Nieuw Project\"\n  STR_CANCEL_PROJECT: \"PROJECT ANNULEREN\"\n  STR_NEW_RESEARCH_PROJECTS: \"NIEUWE ONDERZOEKSPROJECTEN\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"ONDERZOEKERS BESCHIKBAAR>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"LABORATORIUMRUIMTE BESCHIKBAAR>{ALT}{0}\"\n  STR_INCREASE: \"Verhogen\"\n  STR_DECREASE: \"Verlagen\"\n  STR_START_PROJECT: \"PROJECT STARTEN\"\n  STR_CURRENT_PRODUCTION: \"HUIDIGE PRODUCTIE\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Werkplaats Ruimte Beschikbaar>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Beschikbare Middelen>{ALT}{0}\"\n  STR_ITEM: \"ARTIKEL\"\n  STR_UNITS_PRODUCED: \"Eenheden Geproduceerd\"\n  STR_TOTAL_TO_PRODUCE: \"Totaal nog te produceren\"\n  STR_COST__PER__UNIT: \"Prijs{NEWLINE}per{NEWLINE}Eenheid\"\n  STR_DAYS_HOURS_LEFT: \"Resterende dagen/uren\"\n  STR_NEW_PRODUCTION: \"Nieuwe Productie\"\n  STR_PRODUCTION_ITEMS: \"Productie-artikelen\"\n  STR_CATEGORY: \"CATEGORIE\"\n  STR_START_PRODUCTION: \"START PRODUCTIE\"\n  STR_COST_PER_UNIT_: \"Kosten per eenheid>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Werkplaats nodig>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"SPECIALE MATERIALEN VEREIST\"\n  STR_ITEM_REQUIRED: \"ARTIKEL NODIG\"\n  STR_UNITS_REQUIRED: \"EENHEDEN NODIG\"\n  STR_UNITS_AVAILABLE: \"EENHEDEN BESCHIKBAAR\"\n  STR_STOP_PRODUCTION: \"STOP PRODUCTIE\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"WERKPLAATSRUIMTE BESCHIKBAAR>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"MAANDELIJKSE WINST>{ALT}{0}\"\n  STR_INCREASE_UC: \"VERHOOG\"\n  STR_DECREASE_UC: \"VERLAAG\"\n  STR_UNITS_TO_PRODUCE: \"Eenheden nog te produceren\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Aankoop/Werving van Personeel\"\n  STR_COST_OF_PURCHASES: \"Kosten van aankopen>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"PRIJS PER STUK\"\n  STR_QUANTITY_UC: \"AANTAL\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"BESCHIKBAAR PERSONEEL:TOTAAL PERSONEEL>\"\n  STR_SCIENTISTS: \"Wetenschappers\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"GEBRUIKTE RUIMTE:BESCHIKBARE RUIMTE>\"\n  STR_LIVING_QUARTERS: \"Leefruimtes\"\n  STR_STORES: \"Opslag\"\n  STR_LABORATORIES: \"Laboratoria\"\n  STR_WORK_SHOPS: \"Werkplaatsen\"\n  STR_DEFENSE_STRENGTH: \"Sterkte Defensie\"\n  STR_TRANSFERS_UC: \"OVERPLAATSINGEN\"\n  STR_TRANSFERS: \"Overplaatsingen\"\n  STR_ARRIVAL_TIME_HOURS: \"Aankomsttijd (uren)\"\n  STR_COST_: \"Kosten>{ALT}{0}\"\n  STR_AREA_: \"Gebied>{ALT}{0}\"\n  STR_BASE_NAME: \"Basisnaam?\"\n  STR_TRANSFER: \"Overplaatsen\"\n  STR_AMOUNT_TO_TRANSFER: \"HOEVEELHEID OVER TE PLAATSEN\"\n  STR_SELECT_DESTINATION_BASE: \"Selecteer Doelbasis\"\n  STR_COST: \"Kostprijs\"\n  STR_TOTAL_UC: \"TOTAAL\"\n  STR_INCOME: \"Inkomsten\"\n  STR_EXPENDITURE: \"Uitgaven\"\n  STR_MAINTENANCE: \"Onderhoud\"\n  STR_BALANCE: \"Balans\"\n  STR_FINANCE: \"Financiën\"\n  STR_DATE_FIRST: \"{0}ste\"\n  STR_DATE_SECOND: \"{0}de\"\n  STR_DATE_THIRD: \"{0}de\"\n  STR_DATE_FOURTH: \"{0}de\"\n  STR_FINANCE_THOUSANDS: \"$1000's\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Niet genoeg speciale materialen om{NEWLINE}{0}{NEWLINE}bij{NEWLINE}{1}te produceren\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Niet genoeg geld om{NEWLINE}{0}{NEWLINE}bij{NEWLINE}{1}te produceren\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"De productie van{NEWLINE}{0}{NEWLINE}bij{NEWLINE}{1}{NEWLINE}is compleet\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"De bouw van{NEWLINE}{0}{NEWLINE}op{NEWLINE}{1}{NEWLINE}is compleet\"\n  STR_OK_5_SECONDS: \"OK - 5 sec\"\n  STR_RESEARCH_COMPLETED: \"Onderzoek Voltooid\"\n  STR_VIEW_REPORTS: \"RAPPORT INZIEN\"\n  STR_WE_CAN_NOW_RESEARCH: \"Onderzoek mogelijk van\"\n  STR_WE_CAN_NOW_PRODUCE: \"Productie mogelijk van\"\n  STR_SUNDAY: \"ZONDAG\"\n  STR_MONDAY: \"MAANDAG\"\n  STR_TUESDAY: \"DINSDAG\"\n  STR_WEDNESDAY: \"WOENSDAG\"\n  STR_THURSDAY: \"DONDERDAG\"\n  STR_FRIDAY: \"VRIJDAG\"\n  STR_SATURDAY: \"ZATERDAG\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Niet genoeg {0} om {1} bijtetanken bij {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Niet genoeg {0} om {1} te herladen in {2}\"\n  STR_ALIENS_DEFEATED: \"Buitenaardsen verslagen\"\n  STR_BASE_IS_LOST: \"Basis is verloren\"\n  STR_BASE_IS_SAVED: \"Basis is gered\"\n  STR_ALIENS_KILLED: \"BUITENAARDSEN GEDOOD\"\n  STR_ALIEN_CORPSES_RECOVERED: \"TERRUGGEVONDEN BUITENAARDSE LICHAMEN\"\n  STR_LIVE_ALIENS_RECOVERED: \"LEVENDE BUITENAARDSEN TERUGGEVONDEN\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"BUITENAARDSE VOORWERPEN GEVONDEN\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"BURGERS GEDOOD DOOR BUITENAARDSEN\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"BURGERS GEDOOD DOOR X-COM AGENTEN\"\n  STR_CIVILIANS_SAVED: \"BURGERS GERED\"\n  STR_XCOM_OPERATIVES_KILLED: \"X-COM AGENTEN GEDOOD\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"X-COM AGENTEN VERMIST IN ACTIE\"\n  STR_BASE_UNDER_ATTACK: \"{0} wordt aangevallen!\"\n  STR_BASE_DEFENSES_INITIATED: \"BASISDEFENSIE GEACTIVEERD\"\n  STR_FIRING: \"VUURT\"\n  STR_HIT: \"RAAK!\"\n  STR_MISSED: \"MIS!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Verkoop/Ontslag van Personeel\"\n  STR_VALUE_OF_SALES: \"WAARDE VAN VERKOOP> {ALT}{0}\"\n  STR_FUNDS: \"GELDMIDDELEN> {ALT}{0}\"\n  STR_SELL_SACK: \"Verkopen/Ontslaan\"\n  STR_VALUE: \"Waarde\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_BASE_DEFENSE: \"VERDEDIGING BASIS\"\n  STR_BASE_UC_: \"BASIS> {0}\"\n  STR_ALIEN_ACTIVITY_DETECTED: \"BUITENAARDSE ACTIVITEIT GEDETECTEERD\"\n  STR_NO_FREE_ACCOMODATION: \"GEEN ACCOMODATIE BESCHIKBAAR!{SMALLLINE}De doelbasis heeft niet genoeg leefruimte.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"ONVOLDOENDE WERKPLAATS BESCHIKBAAR!{SMALLLINE}Bouw meer werkplaatsen of verminder werk op andere projecten.\"\n  STR_NOT_ENOUGH_MONEY: \"TE WEINIG GELD!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"NIET GENOEG OPSLAGRUIMTE!{SMALLLINE}Bouw nieuwe opslagruimte of maak ruimte vrij.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"NIET GENOEG LEEFRUIMTE!{SMALLLINE}Bouw nieuwe leefruimte of verplaats personeel naar andere basissen.\"\n  STR_LAUNCH_INTERCEPTION: \"ONDERSCHEPPING LANCEREN\"\n  STR_CRAFT: \"VAARTUIG\"\n  STR_STATUS: \"STATUS\"\n  STR_BASE: \"BASIS\"\n  STR_READY: \"GEREED\"\n  STR_OUT: \"ONDERWEG\"\n  STR_REPAIRS: \"REPARATIE\"\n  STR_REFUELLING: \"BIJTANKEN\"\n  STR_REARMING: \"BEWAPENEN\"\n  STR_TARGET: \"DOELWIT: {0}\"\n  STR_WAY_POINT: \"Veld Punt\"\n  STR_YES: \"JA\"\n  STR_NO: \"NEE\"\n  STR_SELECT_DESTINATION: \"SELECTEER BESTEMMING\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"KIES PLAATS VOOR NIEUWE BASIS\"\n  STR_RETURN_TO_BASE: \"TERUGKEREN NAAR BASIS\"\n  STR_SELECT_NEW_TARGET: \"NIEUW DOELWIT SELECTEREN\"\n  STR_PATROL: \"PATROUILLEREN\"\n  STR_STATUS_: \"STATUS>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"BESCHADIGD - KEERT TERUG NAAR BASIS\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"WEINIG BRANDSTOF - KEERT TERUG NAAR BASIS\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"MISSIE AFGEROND - ONDERWEG TERUG NAAR BASIS\"\n  STR_PATROLLING: \"PATROUILLEERT\"\n  STR_RETURNING_TO_BASE: \"KEERT TERUG NAAR BASIS\"\n  STR_DESTINATION_UC_: \"BESTEMMING: {0}\"\n  STR_BASE_UC: \"BASIS>{ALT}{0}\"\n  STR_SPEED_: \"SNELHEID>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"MAXIMUM SNELHEID>{ALT}{0}{ALT}\"\n  STR_FUEL: \"BRANDSTOF>{ALT}{0}\"\n  STR_WEAPON_ONE: \"WAPEN-1>{ALT}{0}\"\n  STR_NONE_UC: \"GEEN\"\n  STR_ROUNDS_: \"PATRONEN>{ALT}{0}\"\n  STR_WEAPON_TWO: \"WAPEN-2>{ALT}{0}\"\n  STR_BASE_: \"Basis>{0}\"\n  STR_NAME_UC: \"NAAM\"\n  STR_AMMO_: \"MUNITIE>{ALT}{0}\"\n  STR_CREW: \"BEZETTING\"\n  STR_EQUIPMENT_UC: \"UITRUSTING\"\n  STR_ARMOR: \"PANTSERS\"\n  STR_MAX: \"MAX>{ALT}{0}\"\n  STR_COLONEL: \"Commandeur\"\n  STR_COMMANDER: \"Kapitein\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Selecteer Squad voor {0}\"\n  STR_SORT_BY: \"SORTEER OP...\"\n  STR_ORIGINAL_ORDER: \"ORGINELE VOLGORDE\"\n  STR_MISSIONS2: \"MISSIES\"\n  STR_KILLS2: \"GEDOOD\"\n  STR_WOUND_RECOVERY2: \"WONDHERSTEL\"\n  STR_SPACE_AVAILABLE: \"RUIMTE BESCHIKBAAR>{ALT}{0}\"\n  STR_SPACE_USED: \"RUIMTE GEBRUIKT>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"RUIMTE IN GEBRUIK\"\n  STR_RANK: \"RANG\"\n  STR_WOUNDED: \"GEWOND\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Uitrusting voor {0}\"\n  STR_DEFENSE_VALUE: \"Defensieve Waarde\"\n  STR_HIT_RATIO: \"Verhouding Treffers\"\n  STR_BEGIN_MISSION: \"Missie Starten?\"\n  STR_SELECT_ARMAMENT: \"Bewapening Kiezen\"\n  STR_AMMUNITION_AVAILABLE: \"MUNITIE BESCHIKBAAR\"\n  STR_ARMAMENT: \"BEWAPENING\"\n  STR_NOT_AVAILABLE: \"NB\"\n  STR_TYPE: \"TYPE\"\n  STR_SELECT_ARMOR: \"Kies Pantser\"\n  STR_NORTH: \"NOORDEN\"\n  STR_NORTH_EAST: \"NOORD-OOSTEN\"\n  STR_EAST: \"OOSTEN\"\n  STR_SOUTH_EAST: \"ZUID-OOSTEN\"\n  STR_SOUTH: \"ZUIDEN\"\n  STR_SOUTH_WEST: \"ZUID-WESTEN\"\n  STR_WEST: \"WESTEN\"\n  STR_NORTH_WEST: \"NOORD-WESTEN\"\n  STR_SELECT_ACTION: \"KIES ACTIE\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"DOORGAAN MET ONDERSCHEPPINGSACHTERVOLGING\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"DOORGAAN ZONDER ONDERSCHEPPING\"\n  STR_VERY_LARGE: \"ZEER GROOT\"\n  STR_LARGE: \"GROOT\"\n  STR_MEDIUM_UC: \"MIDDELGROOT\"\n  STR_SMALL: \"KLEIN\"\n  STR_VERY_SMALL: \"ZEER KLEIN\"\n  STR_DETECTED: \"Gedetecteerd\"\n  STR_SIZE_UC: \"GROOTTE\"\n  STR_HEADING: \"RICHTING\"\n  STR_SPEED: \"SNELHEID\"\n  STR_TRACKING_LOST: \"SPOOR BIJSTER\"\n  STR_REDIRECT_CRAFT: \"VAARTUIG OMLEIDEN\"\n  STR_CRASH_SITE_: \"CRASH LOKATIE-{0}\"\n  STR_WAY_POINT_: \"RICHTINGSPUNT-{0}\"\n  STR_TERROR_SITE: \"TERRURU LOKATIE-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}heeft bereikt{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"Patrioulleert nu\"\n  STR_ALIEN_ORIGINS: \"Buitenaardse Oorsprong\"\n  STR_UFOPAEDIA: \"UFOpedie\"\n  STR_SELECT_ITEM: \"SELECTEER ONDERDEEL\"\n  STR_ACCELERATION: \"ACCELERATIE>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"BRANDSTOF CAPACITEIT>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"WAPEN PODS>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"SCHADE  CAPACITEIT>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"BERGRUIMTE>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Schade\"\n  STR_RANGE: \"Bereik\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Nauwkeurigheid\"\n  STR_RE_LOAD_TIME: \"Herlaadtijd\"\n  STR_SECONDS: \"{0}s\"\n  STR_DAMAGE_ARMOR_PIERCING: \"PANTSER PENETRATIE\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"ZWAAR EXPLOSIEF\"\n  STR_DAMAGE_MELEE: \"HANDGEVECHT\"\n  STR_DAMAGE_ACID: \"ZUUR\"\n  STR_DAMAGE_SMOKE: \"ROOK\"\n  STR_SHOT_TYPE: \"TYPE\"\n  STR_ACCURACY_UC: \"NAUWK.HEID\"\n  STR_TIME_UNIT_COST: \"AP KOSTEN\"\n  STR_DAMAGE_UC: \"SCHADE\"\n  STR_AMMO: \"MUNITIE\"\n  STR_SHOT_TYPE_AUTO: \"AUTOMATISCH VERSCHUIVEN\"\n  STR_SHOT_TYPE_SNAP: \"Snel\"\n  STR_SHOT_TYPE_AIMED: \"Gericht\"\n  STR_CONSTRUCTION_TIME: \"Constructietijd\"\n  STR_CONSTRUCTION_COST: \"Constructieprijs\"\n  STR_MAINTENANCE_COST: \"Onderhoudsprijs\"\n  STR_LOW: \"Laag\"\n  STR_MEDIUM: \"Gemiddels\"\n  STR_HIGH: \"Hoog\"\n  STR_WEAPON: \"Wapen\"\n  STR_AMMUNITION: \"Munitie\"\n  STR_EQUIPMENT: \"Uitrusting\"\n  STR_ALIEN_CORPSE: \"Dode Buitenaardsen\"\n  STR_PERSONAL_ARMOR: \"Persoonlijke Pantsers\"\n  STR_RAW_MATERIALS: \"Grondstoffen\"\n  STR_ALIEN: \"Buitenaardse\"\n  STR_ZOMBIE: \"Zombie\"\n  STR_LIVE_COMMANDER: \"Commandeur\"\n  STR_LIVE_NAVIGATOR: \"Navigator\"\n  STR_LIVE_MEDIC: \"Hospik\"\n  STR_LIVE_SOLDIER: \"Soldaat\"\n  STR_LIVE_TERRORIST: \"Terrorist\"\n  STR_EXAMINATION_ROOM: \"Onderzoekskamer\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Nieuw transport- en gevechtsvliegtuig\"\n  STR_ARMOR_PIERCING: \"PANTSER PENETRATIE\"\n  STR_SCIENTIST: \"Wetenschapper\"\n  STR_NORTH_ATLANTIC: \"Noord-Atlantische\"\n  STR_SOUTH_ATLANTIC: \"Zuid-Atlantische\"\n  STR_INDIAN_OCEAN: \"Indische Oceaan\"\n  STR_ARCTIC: \"Noordpool\"\n  STR_NORTH_AMERICA: \"Noord-Amerika\"\n  STR_MAXIMUM_SPEED: \"Maximumsnelheid\"\n  STR_DAMAGE_CAPACITY: \"Capaciteit voor Schade\"\n  STR_WEAPON_POWER: \"Wapenkracht\"\n  STR_WEAPON_RANGE: \"Wapenbereik\"\n  STR_LABORATORY: \"Laboratorium\"\n  STR_WORKSHOP: \"Werkplaats\"\n  STR_GENERAL_STORES: \"Opslagruimte\"\n  STR_ALIEN_CONTAINMENT: \"Buitenaardse Klimaatcel\"\n  STR_USA: \"VS\"\n  STR_CIVILIAN: \"Burger\"\n  STR_JAN: \"Jan\"\n  STR_FEB: \"Feb\"\n  STR_MAR: \"Maa\"\n  STR_APR: \"Apr\"\n  STR_MAY: \"Mei\"\n  STR_JUN: \"Jun\"\n  STR_JUL: \"Jul\"\n  STR_AUG: \"Aug\"\n  STR_SEP: \"Sep\"\n  STR_OCT: \"Okt\"\n  STR_NOV: \"Nov\"\n  STR_DEC: \"Dec\"\n  STR_INTERNATIONAL_RELATIONS: \"Internationale Betrekkingen\"\n  STR_COUNTRY: \"Land\"\n  STR_FUNDING: \"Steun\"\n  STR_CHANGE: \"Verandering\"\n  STR_WEAPON_SYSTEMS: \"WAPENSYSTEMEN\"\n  STR_DAMAGE_UC_: \"SCHADE>{ALT}{0}\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"Levende buitenaardse wezens hebben een speciale habitat nodig om ze bij te houden. Deze eenheden ondersteunen hun vitale functies en brengen hun vechtpotentieel tot nul. De klimaatcel kan tot 10 buitenaardse wezens huisvesten in onafhankelijke eenheden.\"\n  STR_MAGNA_BLAST_GRENADE_UFOPEDIA: \"Deze granaat uit de standaarduitrusting heeft een nauwkeurige en complexe timer voor precieze controle.\"\n  STR_BATTLESHIP: \"Slagschip\"\n  MAP_XBASES: \"X-Com Basis\"\n  STR_RATING: \"PRESTATIE> {0}\"\n  STR_RATING_TERRIBLE: \"TRIEST!\"\n  STR_RATING_POOR: \"ZWAK!\"\n  STR_RATING_OK: \"OK\"\n  STR_RATING_GOOD: \"GOED!\"\n  STR_RATING_EXCELLENT: \"UITSTEKEND!\"\n  STR_SCORE: \"SCORE\"\n  STR_MONTH: \"Maand> {ALT}{0} {1}\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} is bijzonder tevreden over je vermogen om de lokale dreiging het hoofd te bieden en heeft ermee ingestemd de financiering te verhogen.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} en {1}\"\n  STR_KNOTS: \"{0} knopen\"\n  STR_MONTHLY_RATING: \"Maandelijkse Beoordeling> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Financieringsaanpassing> {ALT}{0}\"\n  STR_RACE: \"RAS\"\n  STR_MISSION: \"MISSIE\"\n  STR_ZONE: \"GEBIED\"\n  STR_ALLOCATE_RESEARCH: \"Onderzoek Toewijzen\"\n  STR_ALLOCATE_MANUFACTURE: \"Productie Toewijzen\"\n  STR_NEW_YORK: \"New York\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_MANILA: \"Manilla\"\n  STR_HONG_KONG: \"Hongkong\"\n  STR_SINGAPORE: \"Singapore\"\n  STR_BANGKOK: \"Bangkok\"\n  STR_BOMBAY: \"Mumbai\"\n  STR_TOKYO: \"Tokio\"\n  STR_SHANGHAI: \"Sjanghai\"\n  STR_LONDON: \"Londen\"\n  STR_IN_TRAINING: \"Wordt{NEWLINE}Getraind?\"\n  STR_TARGETTED_BY: \"DOELWIT VAN:\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"heeft weinig brandstof,{NEWLINE}keert terug naar basis\"\n  STR_RANK_: \"RANG> {ALT}{0}\"\n  STR_MISSIONS: \"MISSIES> {ALT}{0}\"\n  STR_KILLS: \"GEDOOD> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"WOND HERSTEL> {ALT}{0}\"\n  STR_TIME_UNITS: \"ACTIEPUNTEN\"\n  STR_STAMINA: \"UITHOUDINGSVERMOGEN\"\n  STR_HEALTH: \"GEZONDHEIDSTOESTAND\"\n  STR_BRAVERY: \"MOED\"\n  STR_REACTIONS: \"REACTIES\"\n  STR_FIRING_ACCURACY: \"SCHIETNAUWKEURIGHEID\"\n  STR_THROWING_ACCURACY: \"GOOINAUWKEURIGHEID\"\n  STR_STRENGTH: \"KRACHT\"\n  STR_NEW_RANK: \"NIEUWE RANG\"\n  STR_PROMOTIONS: \"Promoties\"\n  STR_ALIEN_INFILTRATION: \"Buitenaardse Infiltratie\"\n  STR_DISMANTLE: \"Ontmantel\"\n  STR_TRANSFER_ITEMS_TO: \"Verplaats spullen naar {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"GEEN KLIMAATCEL OM NAAR OVER TE BRENGEN!{SMALLLINE}Levende buitenaardse wezens hebben een klimaatcel nodig om te kunnen overleven.\"\n  STR_AMOUNT_AT_DESTINATION: \"AANTAL OP{NEWLINE}BESTEMMING\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"Buitenaardse wezen sterft vanwege het ontbreken van een klimaatcel.\"\n  STR_ITEMS_ARRIVING: \"Aankomende Artikelen\"\n  STR_DESTINATION_UC: \"BESTEMMING\"\n  STR_MEDI_KIT: \"Medicijnkit\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Onvoldoende materieel om geweergroep volledig opnieuw uit te rusten.\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Doe onderzoek naar{NEWLINE}{0}{NEWLINE} voor de productie van{NEWLINE}{1}\"\n  STR_STANDOFF: \"HOU AFSTAND\"\n  STR_CAUTIOUS_ATTACK: \"VOORZICHTIGE AANVAL\"\n  STR_STANDARD_ATTACK: \"STANDAARDAANVAL\"\n  STR_AGGRESSIVE_ATTACK: \"AGGRESSIEVE AANVAL\"\n  STR_DISENGAGING: \"TREKT TERUG\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Minimaliseren Enkel op Veilige Afstand\"\n  STR_STORES_UC: \"OPSLAGRUIMTE\"\n  STR_DIFFICULTY_LEVEL: \"Moeilijkheidsgraad\"\n  STR_INTERCEPT: \"ONDERSCHEPPING\"\n  STR_BASES: \"BASISSEN\"\n  STR_GRAPHS: \"GRAFIEKEN\"\n  STR_OPTIONS_UC: \"OPTIES\"\n  STR_FUNDING_UC: \"FINANCIERING\"\n  STR_5_SECONDS: \"5 Sec\"\n  STR_1_MINUTE: \"1 Min\"\n  STR_5_MINUTES: \"5 Min\"\n  STR_30_MINUTES: \"30 Min\"\n  STR_1_HOUR: \"1 Uur\"\n  STR_1_DAY: \"1 Dag\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"X-Com prestatie Rooster\"\n  STR_ENTER_NAME: \"Naam Invoeren\"\n  STR_PERFORMANCE_RATING: \"Beoordeling van Prestatie\"\n  STR_VICTORY_DATE: \"Datum Overwinning\"\n  STR_MONTHLY_COSTS: \"Maandelijkse Kosten\"\n  STR_SALARIES: \"Salarissen\"\n  STR_BASE_MAINTENANCE: \"Onderhoud Basis\"\n  STR_COST_PER_UNIT: \"Kosten per eenheid\"\n  STR_QUANTITY: \"Aantal\"\n  STR_TOTAL: \"Totaal\"\n  STR_FRONT_ARMOR: \"Pantser Voor\"\n  STR_LEFT_ARMOR: \"Pantser Links\"\n  STR_RIGHT_ARMOR: \"Pantser Rechts\"\n  STR_REAR_ARMOR: \"Pantser Achter\"\n  STR_UNDER_ARMOR: \"Pantser Onder\"\n  STR_UNIT: \"EENHEID> {0}\"\n  STR_ENERGY: \"ENERGIE\"\n  STR_MORALE: \"MOREEL\"\n  STR_ARMOR_: \"PANTSER> {0}\"\n  STR_FRONT_ARMOR_UC: \"PANTSER VOOR\"\n  STR_LEFT_ARMOR_UC: \"PANTSER LINKS\"\n  STR_RIGHT_ARMOR_UC: \"PANTSER RECHTS\"\n  STR_REAR_ARMOR_UC: \"PANTSER ACHTER\"\n  STR_SKILLS: \"VAARDIGHEDEN> {0}\"\n  STR_LEVEL: \"NIVEAU> {0}\"\n  STR_HEAD: \"HOOFD\"\n  STR_TORSO: \"ROMP\"\n  STR_RIGHT_ARM: \"RECHTERARM\"\n  STR_LEFT_ARM: \"LINKERARM\"\n  STR_RIGHT_LEG: \"RECHTERBEEN\"\n  STR_LEFT_LEG: \"LINKERBEEN\"\n  STR_PAIN_KILLER: \"PIJNSTILLER\"\n  STR_STIMULANT: \"OPWEKKEND MIDDEL\"\n  STR_HEAL: \"GENEZEN\"\n  STR_TIME_UNITS_SHORT: \"AP>{ALT}{0}\"\n  STR_WEIGHT: \"Gewicht>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"React>{ALT}{0}\"\n  STR_AMMO_ROUNDS_LEFT: \"MUNITIE:{NEWLINE}KOGELS{NEWLINE}OVER={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Pijn>{ALT}{0}{ALT}{NEWLINE}Stim>{ALT}{1}{ALT}{NEWLINE}Helen>{ALT}{2}\"\n  STR_THROW: \"Werpen\"\n  STR_AUTO_SHOT: \"Autom. Schot\"\n  STR_SNAP_SHOT: \"Vlug Schot\"\n  STR_AIMED_SHOT: \"Gericht Schot\"\n  STR_STUN: \"Verdoven\"\n  STR_PRIME_GRENADE: \"Granaat Afstellen\"\n  STR_USE_MEDI_KIT: \"Gebruik Medicijnkit\"\n  STR_ACCURACY_SHORT: \"Acc>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Onvoldoende Actiepunten!\"\n  STR_NOT_ENOUGH_ENERGY: \"Onvoldoende Energie!\"\n  STR_NO_ROUNDS_LEFT: \"Geen Resterende Patronen!\"\n  STR_NO_AMMUNITION_LOADED: \"Wapen Niet geladen!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Vekeerde Munitie voor dit wapen!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"Wapen is reeds Geladen!\"\n  STR_NO_LINE_OF_FIRE: \"Obstructie in de Vuurlinie!\"\n  STR_GRENADE_IS_ACTIVATED: \"Granaat is Geactiveerd!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Granaat is  Gedeactiveert\"\n  STR_THERE_IS_NO_ONE_THERE: \"Daar staat niemand!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Kan buitenaards voorwerp niet gebruiken totdat het onderzocht is!\"\n  STR_OUT_OF_RANGE: \"Buiten Bereik!\"\n  STR_UNABLE_TO_THROW_HERE: \"Kan hier niet heen gooien!\"\n  STR_SET_TIMER: \"Tijd Instellen\"\n  STR_HIDDEN_MOVEMENT: \"VERBORGEN ACTIE\"\n  STR_TURN: \"BEURT>{0}\"\n  STR_SIDE: \"ZIJDE> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Druk een toets om verder te gaan\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Moreel Aanval Succesvol\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}is Dol geworden\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}is Dol geworden\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}is in paniek\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}is in paniek\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Buitenaardsen\"\n  STR_RIGHT_HAND: \"RECHTERHAND\"\n  STR_LEFT_HAND: \"LINKERHAND\"\n  STR_RIGHT_SHOULDER: \"RECHTERSCHOUDER\"\n  STR_LEFT_SHOULDER: \"LINKERSCHOUDER\"\n  STR_BACK_PACK: \"RUGZAK\"\n  STR_BELT: \"RIEM\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}is bewusteloos geraakt\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}is bewusteloos geraakt\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}is dood gegaan door een fatale wond\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}is dood gegaan door een fatale wond\"\n  STR_FATAL_WOUNDS: \"FATALE WONDEN\"\n  STR_UNDER_ARMOR_UC: \"PANTSER ONDER\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Actiepunten gereserveerd voor Vlug Schot\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Actiepunten gereserveerd voor Automatisch Schot\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Actiepunten gereserveerd voor Gericht Schot\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Actiepunten gereserveerd voor knielen\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"Actiepunten gereserveerd voor Knielen en Vuren\"\n  STR_ABORT_MISSION_QUESTION: \"Missie Afbreken ?\"\n  STR_CORPSE: \"Lichaam\"\n  STR_UNLOAD_CRAFT: \"Uitladen\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}is gedood\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}is gedood\"\n  STR_HIT_MELEE: \"Slag\"\n  STR_GROUND: \"GROND\"\n  STR_LIVING_QUARTERS_PLURAL: \"Leefruimtes\"\n  STR_LIST_ITEM: \"ARTIKEL\"\n  STR_RESET: \"Reset\"\n  STR_MEMORIAL: \"Herdenking\"\n  STR_DATE_UC: \"DATUM\"\n  STR_REMOVE_SELECTED: \"Verwijder Geselecteerd\"\n  STR_LIVE_ALIENS: \"Levend{NEWLINE}Exemplaar\"\n  STR_DEAD_ALIENS: \"Afgewezen{NEWLINE}Exemplaar\"\n  STR_UNDER_INTERROGATION: \"Wezen{NEWLINE}Bestudeerd\"\n  STR_CONTAINMENT_EXCEEDED: \"LIMIET BUITENAARDSE KLIMAATCEL OVERSCHREDEN!{SMALLLINE}Onvoldoende opslagruimte in {0}. Verwijder overtollige buitenaardse wezens van de klimaatcellen (zij zullen sterven).\"\n  STR_MANAGE_CONTAINMENT: \"Beheer Buitenaardse Klimaatcellen\"\n  STR_STORAGE_EXCEEDED: \"OPSLAGRUIMTE OVERSCHREDEN!{SMALLLINE}Onvoldoende opslagruimte voor {0}. U moet overtollige zaken verkopen.\"\n  STR_GO_TO_BASE: \"Ga naar Basis\"\n  STR_MELEE_ACCURACY: \"HANDGEVECHT NAUWKEURIGHEID\"\n  STR_SELL_PRODUCTION: \"VERKOOP\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Beide handen moeten leeg zijn!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Niet genoeg spullen om sjabloon te kopieren\"\n  STR_UNLOAD_WEAPON: \"Wapen ontladen\"\n  STR_ALL_ITEMS: \"Alle spullen\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}CONTROLE CENTRUM VERNIETIGD{NEWLINE}Ga naar de ingang en breek de missie af.\"\n  STR_PERSONNEL: \"Personeel\"\n  STR_CRAFT_ARMAMENT: \"Voertuigen & Bewapening\"\n  STR_COMPONENTS: \"Componenten\"\n  FEMALE_CIVILIAN: \"Burger, Vrouw\"\n  MALE_CIVILIAN: \"Burger, Man\"\n  HALLUCINOID_WEAPON: \"Hallucinoid Wapen\"\n  CALCINITE_WEAPON: \"Calcinite Wapen\"\n  DEEP_ONE_WEAPON: \"Deep One Wapen\"\n  STR_TRIBIO_SONIC_WEAPON: \"Buitenaards Sonisch Wapen\"\n  XARQUID_WEAPON: \"Xarquid Wapen\"\n  TENTACULAT_WEAPON: \"Tentaculat Wapen\"\n  ZOMBIE_WEAPON: \"Zombie Wapen\"\n  ALIEN_PSI_WEAPON: \"Buitenaards M.C. Wapen\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/no.yml",
    "content": "\"no\":\n  STR_AQUATOID_AUTOPSY: \"Obduksjon av Aquatoide\"\n  STR_LOBSTERMAN_AUTOPSY: \"Obduksjon av Hummermann\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"SENTRER PÅ STED - TID=5 Sek\"\n  STR_CANCEL_UC: \"AVBRYT\"\n  STR_NONE: \"Ingen\"\n  STR_UNKNOWN: \"Ukjent\"\n  STR_POOR: \"Dårlig\"\n  STR_AVERAGE: \"Middels\"\n  STR_GOOD: \"God\"\n  STR_EXCELLENT: \"Fantastisk\"\n  STR_BUILD_NEW_BASE_UC: \"BYGG NY BASE\"\n  STR_BASE_INFORMATION: \"BASE-INFORMASJON\"\n  STR_BUILD_FACILITIES: \"BYGG FASILITETER\"\n  STR_RESEARCH: \"FORSKNING\"\n  STR_MANUFACTURE: \"PRODUKSJON\"\n  STR_TRANSFER_UC: \"OVERFØR\"\n  STR_PURCHASE_RECRUIT: \"KJØP/ANSETT\"\n  STR_SACK: \"SPARK\"\n  STR_SELL_SACK_UC: \"SELG/SPARK\"\n  STR_GEOSCAPE_UC: \"JORDKLODE\"\n  STR_NAME: \"Navn\"\n  STR_AREA: \"Område\"\n  STR_BUILD_NEW_BASE: \"Bygg Ny Base\"\n  STR_CANCEL: \"Avbryt\"\n  STR_COST_UC: \"KOSTNAD>\"\n  STR_CONSTRUCTION_TIME_UC: \"BYGGE-PERIODE>\"\n  STR_MAINTENANCE_UC: \"VEDLIKEHOLD>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Installasjon\"\n  STR_CURRENT_RESEARCH: \"NÅVÆRENDE FORSKNING\"\n  STR_SCIENTISTS_AVAILABLE: \"Ledige Forskere>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Forskere i Arbeid>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Ledig Laboratorie-Plass>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"FORSKNINGS-PROSJEKT\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"FORSKERE I ARBEID\"\n  STR_PROGRESS: \"FREMGANG\"\n  STR_NEW_PROJECT: \"Nytt Prosjekt\"\n  STR_CANCEL_PROJECT: \"AVBRYT PROSJEKT\"\n  STR_NEW_RESEARCH_PROJECTS: \"NYE FORSKNINGS-PROSJEKTER\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"LEDIGE FORSKERE>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"LEDIG LABORATORIE-PLASS>{ALT}{0}\"\n  STR_INCREASE: \"Flere\"\n  STR_DECREASE: \"Færre\"\n  STR_START_PROJECT: \"START PROSJEKT\"\n  STR_CURRENT_PRODUCTION: \"NÅVÆRENDE PRODUKSJON\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Ledig Verksted-Plass>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Tilgjengelige Midler>{ALT}{0}\"\n  STR_ITEM: \"GJENSTAND\"\n  STR_UNITS_PRODUCED: \"Produserte Enheter\"\n  STR_TOTAL_TO_PRODUCE: \"Totalt å Produsere\"\n  STR_COST__PER__UNIT: \"Kostnad{NEWLINE}per{NEWLINE}Enhet\"\n  STR_DAYS_HOURS_LEFT: \"Dager/Timer Igjen\"\n  STR_NEW_PRODUCTION: \"Ny Produksjon\"\n  STR_CATEGORY: \"KATEGORI\"\n  STR_START_PRODUCTION: \"START PRODUKSJON\"\n  STR_COST_PER_UNIT_: \"Kostnad per enhet>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"SPESIELLE MATERIALER NØDVENDIG\"\n  STR_ITEM_REQUIRED: \"GJENSTAND PÅKREVD\"\n  STR_UNITS_REQUIRED: \"ENHETER PÅKREVD\"\n  STR_UNITS_AVAILABLE: \"ENHETER TILGJENGELIG\"\n  STR_STOP_PRODUCTION: \"STOPP PRODUKSJON\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"LEDIG VERKSTED-PLASS>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"MÅNEDLIG PROFITT>{ALT}{0}\"\n  STR_INCREASE_UC: \"FLERE\"\n  STR_DECREASE_UC: \"FÆRRE\"\n  STR_UNITS_TO_PRODUCE: \"Enheter å Produsere\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Kjøp/Ansett Personell\"\n  STR_COST_OF_PURCHASES: \"Kjøpesum>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"PRIS PR. ENHET\"\n  STR_QUANTITY_UC: \"ANTALL\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"LEDIG PERSONELL:TOTALT PERSONELL>\"\n  STR_SCIENTISTS: \"Forskere\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"BRUKT PLASS:TOTAL PLASS>\"\n  STR_LIVING_QUARTERS: \"Boliger\"\n  STR_STORES: \"Lager\"\n  STR_LABORATORIES: \"Laboratorier\"\n  STR_WORK_SHOPS: \"Verksted\"\n  STR_DEFENSE_STRENGTH: \"Forsvars Styrke\"\n  STR_TRANSFERS_UC: \"OVERFØRINGER\"\n  STR_TRANSFERS: \"Overføringer\"\n  STR_ARRIVAL_TIME_HOURS: \"Ankomsttid (timer)\"\n  STR_COST_: \"Kostnad>{ALT}{0}\"\n  STR_AREA_: \"Område>{ALT}{0}\"\n  STR_BASE_NAME: \"Basens Navn?\"\n  STR_TRANSFER: \"Overføre\"\n  STR_AMOUNT_TO_TRANSFER: \"ANTALL FOR OVERFØRING\"\n  STR_SELECT_DESTINATION_BASE: \"Velg Destinasjons Base\"\n  STR_COST: \"Kostnad\"\n  STR_TOTAL_UC: \"TOTALT\"\n  STR_INCOME: \"Inntekter\"\n  STR_EXPENDITURE: \"Utgifter\"\n  STR_MAINTENANCE: \"Vedlikehold\"\n  STR_BALANCE: \"Balanse\"\n  STR_FINANCE: \"Finanser\"\n  STR_DATE_FIRST: \"{0}.\"\n  STR_DATE_SECOND: \"{0}.\"\n  STR_DATE_THIRD: \"{0}.\"\n  STR_DATE_FOURTH: \"{0}.\"\n  STR_FINANCE_THOUSANDS: \"$1000's\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"Bygging av{NEWLINE}{0}{NEWLINE}i{NEWLINE}{1}{NEWLINE}er ferdig\"\n  STR_OK_5_SECONDS: \"OK - 5 sek\"\n  STR_RESEARCH_COMPLETED: \"Forskning Fullført\"\n  STR_VIEW_REPORTS: \"LES RAPPORTER\"\n  STR_WE_CAN_NOW_RESEARCH: \"Vi kan nå forske på\"\n  STR_WE_CAN_NOW_PRODUCE: \"Vi kan nå produsere\"\n  STR_SUNDAY: \"SØNDAG\"\n  STR_MONDAY: \"MANDAG\"\n  STR_TUESDAY: \"TIRSDAG\"\n  STR_WEDNESDAY: \"ONSDAG\"\n  STR_THURSDAY: \"TORSDAG\"\n  STR_FRIDAY: \"FREDAG\"\n  STR_SATURDAY: \"LØRDAG\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Ikke nok {0} til å tanke opp {1} ved {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Ikke nok {0} for å armere {1} ved {2}\"\n  STR_ALIENS_DEFEATED: \"Aliens overvunnet\"\n  STR_BASE_IS_LOST: \"Basen er tapt\"\n  STR_BASE_IS_SAVED: \"Basen er reddet\"\n  STR_ALIENS_KILLED: \"UTENOMJORDISKE DREPT\"\n  STR_ALIEN_CORPSES_RECOVERED: \"DØDE UTENOMJORDISKE FUNNET\"\n  STR_LIVE_ALIENS_RECOVERED: \"LEVENDE UTENOMJORDISKE FUNNET\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"UTENOMJORDISKE GJENSTANDER FUNNET\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"SIVILE DREPT AV ALIENS\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"SIVILE DREPT AV X-COM STYRKER\"\n  STR_CIVILIANS_SAVED: \"SIVILE REDDET\"\n  STR_XCOM_OPERATIVES_KILLED: \"X-COM STYRKER DREPT\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"X-COM STYRKER SAVNET I AKSJON\"\n  STR_BASE_UNDER_ATTACK: \"{0} under angrep!\"\n  STR_BASE_DEFENSES_INITIATED: \"BASEFORSVAR IGANGSATT\"\n  STR_FIRING: \"AVFYRER\"\n  STR_HIT: \"TREFF!\"\n  STR_MISSED: \"BOMMET!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Selg Gjenstander/Spark Personell\"\n  STR_VALUE_OF_SALES: \"SALGSVERDI> {ALT}{0}\"\n  STR_FUNDS: \"MIDLER> {ALT}{0}\"\n  STR_SELL_SACK: \"Selg/Spark\"\n  STR_VALUE: \"Verdi\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_BASE_DEFENSE: \"BASEFORSVAR\"\n  STR_BASE_UC_: \"BASE> {0}\"\n  STR_NOT_ENOUGH_MONEY: \"IKKE NOK MIDLER!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"IKKE NOK LAGERPLASS!{SMALLLINE}Bygg en ny lager fasilitet eller overfør eksisterende lagerbeholdninger til andre baser.\"\n  STR_LAUNCH_INTERCEPTION: \"START AVSKJÆRING\"\n  STR_CRAFT: \"FARTØY\"\n  STR_STATUS: \"STATUS\"\n  STR_BASE: \"BASE\"\n  STR_READY: \"KLAR\"\n  STR_OUT: \"UTE\"\n  STR_REPAIRS: \"REPARASJONER\"\n  STR_REFUELLING: \"TANKER OPP\"\n  STR_REARMING: \"OPPRUSTER\"\n  STR_TARGET: \"MÅL: {0}\"\n  STR_WAY_POINT: \"VEIPUNKT\"\n  STR_YES: \"JA\"\n  STR_NO: \"NEI\"\n  STR_SELECT_DESTINATION: \"VELG DESTINASJON\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"VELG STED FOR NY BASE\"\n  STR_RETURN_TO_BASE: \"RETURNER TIL BASEN\"\n  STR_SELECT_NEW_TARGET: \"VELG NYTT MÅL\"\n  STR_PATROL: \"PATRULJERE\"\n  STR_STATUS_: \"STATUS>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"SKADET - RETURNERER TIL BASEN\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"LITE DRIVSTOFF - RETURNERER TIL BASE\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"OPPDRAG UTFØRT - RETURNERER TIL BASE\"\n  STR_PATROLLING: \"PATRULJERER\"\n  STR_RETURNING_TO_BASE: \"RETURNERER TIL BASEN\"\n  STR_DESTINATION_UC_: \"DESTINASJON: {0}\"\n  STR_BASE_UC: \"BASE>{ALT}{0}\"\n  STR_SPEED_: \"HASTIGHET>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"TOPPFART>{ALT}{0}{ALT}\"\n  STR_FUEL: \"DRIVSTOFF>{ALT}{0}\"\n  STR_WEAPON_ONE: \"VÅPEN-1>{ALT}{0}\"\n  STR_NONE_UC: \"INGEN\"\n  STR_ROUNDS_: \"SKUDD>{ALT}{0}\"\n  STR_WEAPON_TWO: \"VÅPEN-2>{ALT}{0}\"\n  STR_BASE_: \"Base>{0}\"\n  STR_NAME_UC: \"NAVN\"\n  STR_AMMO_: \"AMMUNISJON>{ALT}{0}\"\n  STR_CREW: \"BESETNING\"\n  STR_EQUIPMENT_UC: \"UTRUSTNING\"\n  STR_ARMOR: \"RUSTNING\"\n  STR_MAX: \"MAX>{ALT}{0}\"\n  STR_COLONEL: \"Kommandør\"\n  STR_COMMANDER: \"Kaptein\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Velg Tropp for {0}\"\n  STR_SORT_BY: \"SORTER ETTER...\"\n  STR_ORIGINAL_ORDER: \"OPPRINNELIG ORDRE\"\n  STR_MISSIONS2: \"OPPDRAG\"\n  STR_SPACE_AVAILABLE: \"LEDIG PLASS>{ALT}{0}\"\n  STR_SPACE_USED: \"BRUKT PLASS>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"BRUKT PLASS\"\n  STR_RANK: \"GRAD\"\n  STR_WOUNDED: \"SKADET\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Utrustning for {0}\"\n  STR_DEFENSE_VALUE: \"Forsvars Verdi\"\n  STR_HIT_RATIO: \"Treffrate\"\n  STR_BEGIN_MISSION: \"Starte Oppdrag?\"\n  STR_SELECT_ARMAMENT: \"Velg Bevæpning\"\n  STR_AMMUNITION_AVAILABLE: \"TILGJENGELIG AMMUNISJON\"\n  STR_ARMAMENT: \"BEVÆPNING\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"VELG RUSTNING FOR{NEWLINE}{0}\"\n  STR_TYPE: \"TYPE\"\n  STR_PLASTIC_AQUA_ARMOR_UC: \"PLASTISK AQUA RUSTNING\"\n  STR_ION_ARMOR_UC: \"IONISK RUSTNING\"\n  STR_SELECT_ARMOR: \"Velg Rustning\"\n  STR_NORTH: \"NORD\"\n  STR_NORTH_EAST: \"NORDØST\"\n  STR_EAST: \"ØST\"\n  STR_SOUTH_EAST: \"SØRØST\"\n  STR_SOUTH: \"SØR\"\n  STR_SOUTH_WEST: \"SØRVEST\"\n  STR_WEST: \"VEST\"\n  STR_NORTH_WEST: \"NORDVEST\"\n  STR_SELECT_ACTION: \"VELG HANDLING\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"FORTSETT JAGER-FORFØLGELSEN\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"FORFØLGE MED AVSTAND\"\n  STR_VERY_LARGE: \"VELDIG STOR\"\n  STR_LARGE: \"STOR\"\n  STR_MEDIUM_UC: \"MELLOMSTOR\"\n  STR_SMALL: \"LITEN\"\n  STR_VERY_SMALL: \"VELDIG LITEN\"\n  STR_DETECTED: \"Oppdaget\"\n  STR_SIZE_UC: \"STØRRELSE\"\n  STR_HEADING: \"KURS\"\n  STR_SPEED: \"HASTIGHET\"\n  STR_TRACKING_LOST: \"SPORING FEILET\"\n  STR_REDIRECT_CRAFT: \"OMDIRIGER FARTØY\"\n  STR_CRASH_SITE_: \"HAVARI-STED-{0}\"\n  STR_WAY_POINT_: \"VEIPUNKT-{0}\"\n  STR_TERROR_SITE: \"TERROR OMRÅDE-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}har ankommet{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"Patruljerer\"\n  STR_ALIEN_ORIGINS: \"Utenomjordisk opphav\"\n  STR_THE_ULTIMATE_THREAT: \"Den Ultimate Trussel\"\n  STR_UFOPAEDIA: \"UFOpedia\"\n  STR_XCOM_CRAFT_ARMAMENT: \"X-COM FARTØY & VÅPEN\"\n  STR_ALIEN_RESEARCH_UC: \"ALIEN TEKNOLOGI\"\n  STR_SELECT_ITEM: \"VELG GJENSTAND\"\n  STR_ACCELERATION: \"AKSELERASJON>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"DRIVSTOFF-KAPASITET>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"VÅPEN-FESTER>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"PANSRING>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"LASTE-KAPASITET>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Skade\"\n  STR_RANGE: \"Rekkevidde\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Treffsikkerhet\"\n  STR_RE_LOAD_TIME: \"Omladningstid\"\n  STR_SECONDS: \"{0}s\"\n  STR_DAMAGE_ARMOR_PIERCING: \"PANSERBRYTENDE\"\n  STR_DAMAGE_INCENDIARY: \"FOSFOR\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"HØY-EKSPLOSIV\"\n  STR_DAMAGE_LASER_BEAM: \"GAUSS STRÅLE\"\n  STR_DAMAGE_PLASMA_BEAM: \"SONISK STRÅLE\"\n  STR_DAMAGE_STUN: \"FRYSE\"\n  STR_DAMAGE_MELEE: \"NÆRKAMP\"\n  STR_DAMAGE_ACID: \"SYRE\"\n  STR_DAMAGE_SMOKE: \"RØYK\"\n  STR_SHOT_TYPE: \"TYPE\"\n  STR_ACCURACY_UC: \"TREFFSIKKERHET\"\n  STR_TIME_UNIT_COST: \"TIDSENHETER\"\n  STR_DAMAGE_UC: \"SKADE\"\n  STR_AMMO: \"AMMUNISJON\"\n  STR_SHOT_TYPE_AUTO: \"Auto\"\n  STR_SHOT_TYPE_SNAP: \"Slengskudd\"\n  STR_SHOT_TYPE_AIMED: \"Siktet\"\n  STR_CONSTRUCTION_TIME: \"Bygge-Periode\"\n  STR_CONSTRUCTION_COST: \"Bygge-Kostnader\"\n  STR_MAINTENANCE_COST: \"Vedlikeholds-Kostnader\"\n  STR_LOW: \"Lav\"\n  STR_MEDIUM: \"Medium\"\n  STR_HIGH: \"Høy\"\n  STR_CRAFT_WEAPON: \"Ubåt Våpen\"\n  STR_CRAFT_AMMUNITION: \"Ubåt Ammunisjon\"\n  STR_WEAPON: \"Våpen\"\n  STR_AMMUNITION: \"Ammunisjon\"\n  STR_EQUIPMENT: \"Utrustning\"\n  STR_ALIEN_CORPSE: \"Alien-Kadaver\"\n  STR_PERSONAL_ARMOR: \"Personlig Rustning\"\n  STR_RAW_MATERIALS: \"Råmaterialer\"\n  STR_ALIEN: \"Romvesen\"\n  STR_AQUATOID: \"Aquatoide\"\n  STR_GILLMAN: \"Gjellemann\"\n  STR_LOBSTERMAN: \"Hummermann\"\n  STR_ZOMBIE: \"Zombie\"\n  STR_LIVE_COMMANDER: \"Kommandør\"\n  STR_LIVE_NAVIGATOR: \"Navigatør\"\n  STR_LIVE_MEDIC: \"Pleier\"\n  STR_LIVE_TECHNICIAN: \"Tekniker\"\n  STR_LIVE_SOLDIER: \"Soldat\"\n  STR_LIVE_TERRORIST: \"Terrorist\"\n  STR_AQUATOID_COMMANDER: \"Aquatoide Kommandør\"\n  STR_AQUATOID_NAVIGATOR: \"Aquatiode Navigatør\"\n  STR_AQUATOID_TECHNICIAN: \"Aquatoide Tekniker\"\n  STR_AQUATOID_SQUAD_LEADER: \"Aquatoide Troppsleder\"\n  STR_AQUATOID_SOLDIER: \"Aquatoide-Soldat\"\n  STR_EXAMINATION_ROOM: \"Undersøkelsesrom\"\n  STR_AQUA_PLASTICS: \"Aqua Plastikk\"\n  STR_GAUSS_TECH: \"Gauss Teknologi\"\n  STR_ARMOR_PIERCING: \"PANSERBRYTENDE\"\n  STR_SCIENTIST: \"Forsker\"\n  STR_ENGINEER: \"Tekniker\"\n  STR_NORTH_ATLANTIC: \"Nord-Atlanteren\"\n  STR_SOUTH_ATLANTIC: \"Sør-Atlanteren\"\n  STR_INDIAN_OCEAN: \"Indiahavet\"\n  STR_ARCTIC: \"Arktis\"\n  STR_NORTH_AMERICA: \"Nord-Amerika\"\n  STR_MAXIMUM_SPEED: \"Toppfart\"\n  STR_DAMAGE_CAPACITY: \"Pansring\"\n  STR_WEAPON_POWER: \"Våpen-Kraft\"\n  STR_WEAPON_RANGE: \"Våpen-Rekkevidde\"\n  STR_LABORATORY: \"Laboratorium\"\n  STR_WORKSHOP: \"Verksted\"\n  STR_GENERAL_STORES: \"Lager\"\n  STR_USA: \"USA\"\n  STR_CIVILIAN: \"Sivilperson\"\n  STR_JAN: \"Jan\"\n  STR_FEB: \"Feb\"\n  STR_MAR: \"Mar\"\n  STR_APR: \"Apr\"\n  STR_MAY: \"Mai\"\n  STR_JUN: \"Jun\"\n  STR_JUL: \"Jul\"\n  STR_AUG: \"Aug\"\n  STR_SEP: \"Sep\"\n  STR_OCT: \"Okt\"\n  STR_NOV: \"Nov\"\n  STR_DEC: \"Des\"\n  STR_INTERNATIONAL_RELATIONS: \"Internasjonale Forbindelser\"\n  STR_COUNTRY: \"Land\"\n  STR_FUNDING: \"Finansiering\"\n  STR_CHANGE: \"Endring\"\n  STR_WEAPON_SYSTEMS: \"VÅPEN- SYSTEMER\"\n  STR_DAMAGE_UC_: \"SKADE>{ALT}{0}\"\n  STR_BATTLESHIP: \"Slagskip\"\n  MAP_XBASES: \"X-Com Base\"\n  STR_RATING: \"VURDERING> {0}\"\n  STR_RATING_TERRIBLE: \"FORFERDELIG!\"\n  STR_RATING_POOR: \"DÅRLIG!\"\n  STR_RATING_OK: \"OK\"\n  STR_RATING_GOOD: \"BRA!\"\n  STR_RATING_EXCELLENT: \"FANTASTISK!\"\n  STR_SCORE: \"POENG\"\n  STR_MONTH: \"Måned> {ALT}{0} {1}\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} er spesielt fornøyd med din evne til å håndtere den lokaliserte trusselen og har sagt seg villig til å øke sin finansiering.\"\n  STR_COUNTRIES_AND: \"{0} og {1}\"\n  STR_KNOTS: \"{0} knop\"\n  STR_RACE: \"RASE\"\n  STR_MISSION: \"OPPDRAG\"\n  STR_ALLOCATE_RESEARCH: \"Tildel Forskning\"\n  STR_HONG_KONG: \"Hongkong\"\n  STR_BOMBAY: \"Mumbai\"\n  STR_RANK_: \"GRAD> {ALT}{0}\"\n  STR_MISSIONS: \"OPPDRAG> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"SYKEDAGER> {ALT}{0}\"\n  STR_TIME_UNITS: \"TIDS-ENHETER\"\n  STR_STAMINA: \"UTHOLDENHET\"\n  STR_HEALTH: \"HELSE\"\n  STR_BRAVERY: \"TAPPERHET\"\n  STR_REACTIONS: \"REAKSJONSEVNE\"\n  STR_FIRING_ACCURACY: \"SKYTE-FERDIGHETER\"\n  STR_THROWING_ACCURACY: \"KASTE-FERDIGHETER\"\n  STR_STRENGTH: \"STYRKE\"\n  STR_NEW_RANK: \"NY GRAD\"\n  STR_SOLDIERS_UC: \"AQUANAUTER\"\n  STR_ALIEN_INFILTRATION: \"Romvesen-Infiltrasjon\"\n  STR_DISMANTLE: \"Demontere\"\n  STR_DESTINATION_UC: \"DESTINASJON\"\n  STR_MEDI_KIT: \"Førstehjelpssett\"\n  STR_STANDOFF: \"HOLD AVSTAND\"\n  STR_CAUTIOUS_ATTACK: \"FORSIKTIG ANGREP\"\n  STR_STANDARD_ATTACK: \"STANDARD ANGREP\"\n  STR_AGGRESSIVE_ATTACK: \"AGGRESSIVT ANGREP\"\n  STR_DISENGAGING: \"FALL IFRA\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Minimer Kun Under Avstandholdelese\"\n  STR_STORES_UC: \"LAGER\"\n  STR_DIFFICULTY_LEVEL: \"Vanskelighetsgrad\"\n  STR_INTERCEPT: \"AVSKJÆRING\"\n  STR_BASES: \"BASER\"\n  STR_GRAPHS: \"GRAFER\"\n  STR_OPTIONS_UC: \"ALTERNATIVER\"\n  STR_FUNDING_UC: \"FINANSIERING\"\n  STR_5_SECONDS: \"5 Sek\"\n  STR_1_MINUTE: \"1 Min\"\n  STR_5_MINUTES: \"5 Min\"\n  STR_30_MINUTES: \"30 Min\"\n  STR_1_HOUR: \"1 Time\"\n  STR_1_DAY: \"1 Dag\"\n  STR_ENTER_NAME: \"Skriv Navn\"\n  STR_PERFORMANCE_RATING: \"Prestasjons Vurdering\"\n  STR_VICTORY_DATE: \"Seiers-dato\"\n  STR_MONTHLY_COSTS: \"Månedskostnader\"\n  STR_SALARIES: \"Lønninger\"\n  STR_BASE_MAINTENANCE: \"Base-Vedlikehold\"\n  STR_COST_PER_UNIT: \"Kostnad/stk.\"\n  STR_QUANTITY: \"Antall\"\n  STR_TOTAL: \"Totalt\"\n  STR_FRONT_ARMOR: \"Beskyttelse Front\"\n  STR_LEFT_ARMOR: \"Beskyttelse Venstre\"\n  STR_RIGHT_ARMOR: \"Beskyttelse Høyre\"\n  STR_REAR_ARMOR: \"Beskyttelse Bak\"\n  STR_UNDER_ARMOR: \"Beskyttelse Under\"\n  STR_UNIT: \"ENHET> {0}\"\n  STR_ENERGY: \"UTHOLDENHET\"\n  STR_MORALE: \"DISIPLIN\"\n  STR_ARMOR_: \"PANSER> {0}\"\n  STR_FRONT_ARMOR_UC: \"FREMRE PANSER\"\n  STR_LEFT_ARMOR_UC: \"VENSTRE PANSER\"\n  STR_RIGHT_ARMOR_UC: \"HØYRE PANSER\"\n  STR_REAR_ARMOR_UC: \"BAKRE PANSER\"\n  STR_SKILLS: \"FERDIGHETER> {0}\"\n  STR_LEVEL: \"NIVÅ> {0}\"\n  STR_HEAD: \"HODE\"\n  STR_TORSO: \"TORSO\"\n  STR_RIGHT_ARM: \"HØYRE ARM\"\n  STR_LEFT_ARM: \"VENSTRE ARM\"\n  STR_RIGHT_LEG: \"HØYRE BEN\"\n  STR_LEFT_LEG: \"VENSTRE BEN\"\n  STR_PAIN_KILLER: \"SMERTESTILLENDE\"\n  STR_STIMULANT: \"STIMULERENDE\"\n  STR_HEAL: \"HELBREDE\"\n  STR_TIME_UNITS_SHORT: \"TID>{ALT}{0}\"\n  STR_WEIGHT: \"Vekt>{ALT}{0}/{1}\"\n  STR_AMMO_ROUNDS_LEFT: \"AMMUNISJON:{NEWLINE}{ALT}{0} SKUDD{NEWLINE}IGJEN\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Bedøve>{ALT}{0}{ALT}{NEWLINE}Opplive>{ALT}{1}{ALT}{NEWLINE}Helbrede>{ALT}{2}\"\n  STR_THROW: \"Kast\"\n  STR_AUTO_SHOT: \"Skuddserie (3)\"\n  STR_SNAP_SHOT: \"Slengskudd\"\n  STR_AIMED_SHOT: \"Siktet Skudd\"\n  STR_STUN: \"Bedøve\"\n  STR_USE_MEDI_KIT: \"Bruk Førstehjelpssett\"\n  STR_ACCURACY_SHORT: \"Trf>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Ikke Nok Tid!\"\n  STR_NOT_ENOUGH_ENERGY: \"For Dårlig Kondisjon!\"\n  STR_NO_ROUNDS_LEFT: \"Tom for kuler!\"\n  STR_NO_AMMUNITION_LOADED: \"Ingen Ammunisjon Ladd!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Feil Ammunisjon for dette Våpenet!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"Våpenet er allerede ladd!\"\n  STR_NO_LINE_OF_FIRE: \"Ingen Skuddlinje!\"\n  STR_GRENADE_IS_ACTIVATED: \"Granat er Avsikret!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Granat er Sikret!\"\n  STR_THERE_IS_NO_ONE_THERE: \"Det er ingen der!\"\n  STR_OUT_OF_RANGE: \"Utenfor Rekkevidde!\"\n  STR_UNABLE_TO_THROW_HERE: \"Kan ikke kaste der!\"\n  STR_HIDDEN_MOVEMENT: \"SKJULT AKTIVITET\"\n  STR_TURN: \"RUNDE> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Trykk knapp for å fortsette\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Moralangrep Vellykket\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}har gått Berserk\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}har gått Berserk\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}har fått Panikk\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}har fått Panikk\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Romvesen\"\n  STR_RIGHT_HAND: \"HØYRE HÅND\"\n  STR_LEFT_HAND: \"VENSTRE HÅND\"\n  STR_RIGHT_SHOULDER: \"HØYRE SKULDER\"\n  STR_LEFT_SHOULDER: \"VENSTRE SKULDER\"\n  STR_BACK_PACK: \"RYGGSEKK\"\n  STR_BELT: \"BELTE\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}er blitt bevisstløs\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}er blitt bevisstløs\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}omkom av ett dødelig sår\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}omkom av ett dødelig sår\"\n  STR_FATAL_WOUNDS: \"DØDELIGE SÅR\"\n  STR_UNDER_ARMOR_UC: \"NEDRE PANSER\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Tid Reservert for Slengskudd\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Tid Reservert for Skuddserie (3)\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Tid Reservert for Siktet Skudd\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Tid Reservert for Kneling\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"Tid Reservert for Kneling og Skyting\"\n  STR_ABORT_MISSION_QUESTION: \"Avbryte Oppdrag?\"\n  STR_CORPSE: \"Kropp\"\n  STR_UNLOAD_CRAFT: \"Last Av\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}ble drept\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}ble drept\"\n  STR_HIT_MELEE: \"Treff\"\n  STR_GROUND: \"BAKKE\"\n  STR_LIVING_QUARTERS_PLURAL: \"Boliger\"\n  STR_LIST_ITEM: \"GJENSTAND\"\n  STR_RESET: \"Reset\"\n  STR_MEMORIAL: \"Minnetavle\"\n  STR_DATE_UC: \"DATO\"\n  STR_REMOVE_SELECTED: \"Fjern Valgte\"\n  STR_LIVE_ALIENS: \"Levende{NEWLINE}Eksemplarer\"\n  STR_DEAD_ALIENS: \"Forkastede{NEWLINE}Eksemplarer\"\n  STR_UNDER_INTERROGATION: \"Blir{NEWLINE}Studert\"\n  STR_GO_TO_BASE: \"Gå til Base\"\n  STR_MELEE_ACCURACY: \"NÆRKAMP-FERDIGHET\"\n  STR_SELL_PRODUCTION: \"SELG\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Begge hender må være tomhendt!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Ikke nok utstyr til å kopiere mal!\"\n  STR_UNLOAD_WEAPON: \"Ta av våpen\"\n  STR_ALL_ITEMS: \"Alle Gjenstander\"\n  STR_PERSONNEL: \"Personell\"\n  STR_CRAFT_ARMAMENT: \"Fartøy & Bevæpning\"\n  STR_COMPONENTS: \"Komponenter\"\n  FEMALE_CIVILIAN: \"Sivil, Kvinne\"\n  MALE_CIVILIAN: \"Sivil, Mann\"\n  ZOMBIE_WEAPON: \"Zombi Våpen\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/pl.yml",
    "content": "pl:\n  STR_LEVIATHAN_UFOPEDIA: \"TRANSPORTOWA I PRZECHWYTUJĄCA ŁÓDŹ LATAJĄCA O NIEOGRANICZONEJ GŁĘBOKOŚCI ZANURZENIA. TO WSPANIAŁE POŁĄCZENIE OBCEJ TECHNIKI Z LUDZKĄ, WYKORZYSTUJĄCE SYSTEMY NAPĘDU JONOWEGO I NAWIGACYJNE BLOKI MAGNETYCZNE.\"\n  STR_BARRACUDA_UFOPEDIA: \"PRODUKOWANA PRZEZ BRITISH HYDROSPACE ŁÓDŹ BARAKUDA JEST ZASILANA NADCIEPLNYMI SILNIKAMI LASEROWYMI. TO JEDNA Z NAJSZYBSZYCH ŁODZI PRZECHWYTUJĄCYCH NA ŚWIECIE, KTÓRA DZIAŁA ZARÓWNO POD WODĄ, JAK I W POWIETRZU. TO NASZA KLUCZOWA BROŃ W NADCHODZĄCEJ WALCE.\"\n  STR_HAMMERHEAD_UFOPEDIA: \"ŁÓDŹ TRANSPORTOWO-PRZECHWYTUJĄCA. ZASTOSOWANO W NIEJ SYSTEM BLOKÓW MAGNETYCZNYCH ZINTEGROWANY Z KADŁUBEM X-COMU. MIMO MAŁYCH ROZMIARÓW, TEN PROJEKT TO WSPANIAŁE OSIĄGNIĘCIE TECHNICZNE.\"\n  STR_TRITON_UFOPEDIA: \"TRYTON TO TRANSPORTOWIEC SZTURMOWY, WYPOSAŻONY W PEŁNY ZESTAW SILNIKÓW DO LOTÓW W POWIETRZU I PŁYWANIA POD WODĄ. JEGO DUŻA POJEMNOŚĆ I MOCNA KONSTRUKCJA CZYNIĄ ZEŃ PODSTAWĘ FLOTY X-COMU.\"\n  STR_MANTA_UFOPEDIA: \"MANTA TO SZYBKA, JEDNOOSOBOWA ŁÓDŹ PRZECHWYTUJĄCA, BĘDĄCA NIEMALŻE KOPIĄ STATKÓW OBCYCH ZASILANYCH NAPĘDEM JONOWYM. WYSOCE EFEKTYWNA JEDNOSTKA BOJOWA W NARASTAJĄCYM KONFLIKCIE.\"\n  STR_AJAX_UFOPEDIA: \"TORPEDA AJAKS JEST STANDARDOWĄ BRONIĄ W WALCE PODWODNEJ NA CAŁYM ŚWIECIE. WYKORZYSTYWANA JAKO ŚRODEK ODSTRASZAJĄCY ZE WZGLĘDU NA WYSOKĄ CELNOŚĆ I POTĘŻNĄ SIŁĘ.\"\n  STR_DUP_HEAD_UFOPEDIA: \"TECHNOLOGIA BRONI Z GŁOWICĄ Z KAPSUŁKAMI ZUBOŻONEGO URANU JEST STOSUNKOWO NOWA I JEST TO PIERWSZY KOMERCYJNY SYSTEM BRONI WODNEJ, W KTÓRYM ZNALAZŁA ONA PEŁNE ZASTOSOWANIE.\"\n  STR_CRAFT_GAS_CANNON_UFOPEDIA: \"SYSTEM DZIAŁEK ZASILANYCH SPRĘŻONYM GAZEM, STRZELAJĄCY POCISKAMI O WYSOKIEJ ZDOLNOŚCI PRZEBICIA PANCERZA\"\n  STR_PWT_CANNON_UFOPEDIA: \"TORPEDA IMPULSOWA WYKORZYSTUJE UKŁAD PRZEGRZANEGO PALIWA ORAZ EKSTREMALNIE GĘSTĄ GŁOWICĘ, KTÓRA MOŻE PRZEBIĆ WIĘKSZOŚĆ STOPÓW.\"\n  STR_GAUSS_CANNON_UFOPEDIA: \"BROŃ GAUSSA JEST JEDNYM Z NOWYCH OSIĄGNIĘĆ TECHNICZNYCH ORGANIZACJI X-COM. AKCELERATOR CZĄSTEK NAPĘDZANY JEST MAŁYM REAKTOREM FUZYJNYM, CHŁODZONYM CIEKŁYM AZOTEM.\"\n  STR_SONIC_OSCILLATOR_UFOPEDIA: \"POTĘŻNY OSCYLATOR DŹWIĘKOWY. WYTWARZA ON FALE SONICZNE O ODPOWIEDNIEJ CZĘSTOTLIWOŚCI REZONANSOWEJ I SILE, BY ZNISZCZYĆ CEL POPRZEZ ROZPAD WIĄZAŃ MOLEKULARNYCH.\"\n  STR_AQUATOID_UFOPEDIA: \"Akwatoidzi są starożytną rasą, która istniała tysiące lat przed pojawieniem się człowieka. Ich niewielkie rozmiary i krągłe kształty nasuwają skojarzenia z ich kosmicznymi kuzynami, sektoidami. Ich moc jest oparta na potężnej technologii 'kontroli molekularnej'. Akwatoidzi najwyraźniej starają się mnożyć pomimo bezpłodności dzięki genetycznym modyfikacjom, do których idealnie nadają się istoty ludzkie. Wynikami tych eksperymentów są liczne rasy hybrydowe.\"\n  STR_AQUATOID_AUTOPSY: \"Sekcja zwłok akwatoida\"\n  STR_AQUATOID_AUTOPSY_UFOPEDIA: \"Szczegółowa analiza tych istot pozwoliła nam poczynić pewne założenia. To sektoid, nasz dawny wróg, ale odmieniony przez chirurgięi i wszczepy, by stać się stworzeniem wodnym. Szczątkowe płuca pozwalają na oddychanie powietrzem i ograniczoną mobilność na powierzchni. W całym ciele znajdują się cybernetyczne implanty, wzmacniające siły zanikających członków i funkcje organów. Ponieważ wszyscy członkowie tej rasy są identyczni, możemy postawić hipotezę, że te stworzenia są klonami.\"\n  STR_GILLMAN_UFOPEDIA: \"Dziwne, niemal ludzkie stworzenie, które wydaje się być gadzim humanoidem, bardzo blisko spokrewnionym z człowiekiem. Jest ono nadzwyczaj silna i szybka w podwodnym świecie. Skrzelaki to pełnoprawna rasa, składająca się z męskich i żeńskich osobników w różnym wieku. Są niepodobni do większości podwodnych obcych, gdyż nie ma w nich śladów zmian genetycznych czy deformacji chirurgicznych. Możliwe, że patrzymy na jakiś starożytny odłam naszego własnego gatunku.\"\n  STR_GILLMAN_AUTOPSY: \"Sekcja zwłok skrzelaka\"\n  STR_GILLMAN_AUTOPSY_UFOPEDIA: \"Zaraz po rozpoczęciu operacji wyszło na jaw, że to nie żaden obcy, ale istota urodzona na ziemi; starożytna, prehistoryczna rasa, którą uważano za wymarłą od czasów, gdy ssaki objęły panowanie. W czasach wędrówek dinozaurów żyły skrzelaki - ziemnowodny gatunek, inteligentny i silny. Kataklizm, który zakończył panowanie jaszczurów na tej planecie, zmusił te istoty do relacji symbiotycznych z nowoprzybyłymi obcymi. W czaszkach tych istot umieszczono małe urządzenie elektroniczne.\"\n  STR_LOBSTERMAN_UFOPEDIA: \"To szokujące stworzenie, wyższe od człowieka, szczycące się sześcioma członkami, przypominające wręcz podwodnego demona. Podobieństwa pomiędzy tym stworzeniem a ziemskim homarem zapewniły mu wśród żołnierzy X-Comu przydomek 'homaroid'. Jest to behemot z głębin; starannie zaprojektowana istota bojowa o niezwykłej sile i praktycznie niewrażliwości na pociski. Same jej szczypce potrafią kruszyć stal.\"\n  STR_LOBSTERMAN_AUTOPSY: \"Sekcja zwłok homaroida\"\n  STR_LOBSTERMAN_AUTOPSY_UFOPEDIA: \"Pod praktycznie niezniszczalną skorupą stworzenie to stanowi niesamowitą konstrukcję. Silne mięśnie prężą się wokół tytanowego szkieletu, a wyrafinowany system celowniczy ze zdolnością skanowania wielopasmowego jest przytwierdzony bezpośrednio do mózgu stwora. Liczne oczy są chronione przez twardsze niż stal tworzywo sztuczne i jest jasne, że te istoty po wystawieniu do walki są nie do powstrzymania. Głęboko w ciele osadzone są urządzenia o nieznanej budowie i funkcji.\"\n  STR_TASOTH_UFOPEDIA: \"Ci zwinni i szybcy przeciwnicy są filarem armii obcych. Setki rodzą się w ogromnych kadziach hodowlanych, głęboko w sercu kolonii obcych. Znacznie bardziej potężny od człowieka tasot jest prawdziwym obcym, a jego zachowanie i drapieżna natura nie mają sobie równych na planecie. Tasot często staje na czele ataku obcych i jak się wydaje, nigdy nie uchyla się od walki, nawet w obliczu przeważających przeciwności. \"\n  STR_TASOTH_AUTOPSY: \"Sekcja zwłok tasota\"\n  STR_TASOTH_AUTOPSY_UFOPEDIA: \"Wnikliwa analiza ujawniła cybernetyczny organizm władający dziwnymi mocami. Wewnątrz jamy ciała znajduje się mała jednostka zasilająca, ale nie ma tam żadnych rozpoznawalnych organów. Moc przekazywana jest do całego ciała poprzez bioelektryczny system transmisyjny. Całe ciało jest pozbawione kości czy innych struktur podtrzymujących. Po śmierci energia zatrzymuje się i stworzenie staje się martwą kukłą, z której sączy się obca tkanka i płyny. Jedyną inną strukturą wewnętrzną jest para ogniw ceramicznych, które po naładowaniu na krótko ożywią stworzenie.\"\n  STR_DEEP_ONE_UFOPEDIA: \"Głębion jest biologicznym koszmarem, krzyżówką stworzoną przez niewyobrażalne eksperymenty akwatoidów. Napotkaliśmy kilka różnych odmian tych stworów. Po obszernych badaniach wywnioskowaliśmy, że produkowane są przez najeźdźców. Ich szeregi wzrastają w miarę porywania coraz to nowego materiału ludzkiego. Każdy z tych podludzi jest uzbrojony w miotacz energii elektrycznej, wystarczająco mocny, by zabić akwanautę.\"\n  STR_DEEP_ONE_AUTOPSY: \"Sekcja zwłok głębiona\"\n  STR_DEEP_ONE_AUTOPSY_UFOPEDIA: \"Stworzenie to jest szczepem człowieka i obcego organizmu. Ludzki mózg został przystosowany do połączenia z elektroniką sterującą i obcą korą mózgową. Jedyny ślad ludzkiego ciała, jaki się zachował, to oczy. Ślady operacji chirurgicznych wskazują, że obcy płód wzrasta pożerając ludzkiego nosiciela. Solidna skóra tego stworzenia wygląda na nieorganiczną, metalową siatkę, niezwykle silną i giętką. Wynikowa krzyżówka jest silna, szybka i całkowicie pod kontrolą obcych.\"\n  STR_BIODRONE_UFOPEDIA: \"Biodron jest wymysłem, który tylko obcy umysł mógł stworzyć. Jest to mózg (ludzki lub obcego) zawieszony w płynach owodniowych i podłączony do zasilanej jednostki bazowej, która może latać ponad lądem i pod wodą. Każdy biodron jest uzbrojony w potężny dysruptor audialny, po części będący maszyną, a po części organizmem. Niektórzy z naszych naukowców sugerują, że broń jest napędzana przez pierwotne struny głosowe organizmu nosiciela. Wysoce celne i wytrwałe, te superpsy obronne są szeroko stosowane przez obcych do ochrony cennych zasobów.\"\n  STR_BIODRONE_AUTOPSY: \"Sekcja zwłok biodrona\"\n  STR_BIODRONE_AUTOPSY_UFOPEDIA: \"Hipoteza, że dysruptor audialny jest urządzeniem biologicznym, jest prawdziwa. Ta nieszczęsna kreatura dosłownie zakrzykuje swoich wrogów na śmierć. Każdy okaz ma rozległe urazy od zabiegów chirurgicznych i poważne okaleczenia. Obcy wydają się zakatowywać mózg, by był im posłuszny. Większość z kory użytej w tych istotach jest obcego pochodzenia, ale nic nie da się porównać z koszmarem znalezienia jednostki opartej na człowieku. Biodrony są napędzane przez silnik jonowy i zawierają jakąś formę systemu zdalnego sterowania.\"\n  STR_TENTACULAT_UFOPEDIA: \"Nawet głębiny lovecraftowskiego horroru nie zdołałyby zrodzić tak nieopisanego stworzenia jak to. Nieporównywalny z żadnym żyjącym ziemskim zwierzęciem, musiał wykształcić się w środowisku, którego nie sposób sobie wyobrazić. Za pomocą długich macek paraliżuje swoje ofiary, przeobrażając je w bezmyślne twory. Potomstwo to może wywołać śmierć poprzez dotyk, przechodzący nawet przez zbroję. Mackonóg to najbardziej przeraźliwy obcy, jakiego dotąd napotkał X-Com.\"\n  STR_TENTACULAT_AUTOPSY: \"Sekcja zwłok mackonoga\"\n  STR_TENTACULAT_AUTOPSY_UFOPEDIA: \"Sekcja odkryła mnóstwo małych cyberwszczepów w dużym mózgu istoty. Narząd wzroku wykorzystuje światło widzialne i obrazowanie termiczne, więc potwór ten może nawigować z niezawodną dokładnością nawet w najczarniejszych głębinach oceanu. Organy wewnętrzne są dość szczątkowe i ledwo wystarczają mu do przeżycia. Do małego żołądka prowadzi zewnętrzne przyłącze, co pozwala zakładać, że istota jest karmiona przez bezpośrednie podawanie substancji pokarmowych.\"\n  STR_CALCINITE_UFOPEDIA: \"Jak skafandry zagubionych nurków, ci obcy grasują na dnie morza w oczekiwaniu na nieostrożnych. Rozjuszony zamach mocniejszych niż stal szczypiec stwora może wystarczyć, by posłać na dno najlepszego nurka. Za szybą hełmu można dostrzec przelewającą się, zieloną galaretę. Z często śmiertelnych spotkań z tymi istotami nie udało się niczego wywnioskować na temat ich natury.\"\n  STR_CALCINITE_AUTOPSY: \"Sekcja zwłok kalcynita\"\n  STR_CALCINITE_AUTOPSY_UFOPEDIA: \"Po zdjęciu skafandra kalcynit okazał się być ogromną, bezkształtną masą protoplazmy. Nie ma widocznego mózgu, kończyn ani narządów zmysłów, a głęboko w płynnym ciele znajduje się mały metalowy podzespół. Możemy tylko domyślać się natury martwej istoty. To niewytłumaczalna zagadka naszych obcych wrogów.\"\n  STR_TRISCENE_UFOPEDIA: \"Ten dwunożny gad jest powrotem do czasów dinozaurów. Wydaje się być typową istotą z okresu kredy, z wyjątkiem zdolności przetrwania w wodzie i na lądzie. Stworzeniom tym zakłada się mocowanie na broń, a szczęki mają wypełnione wielkimi, metalicznymi zębami. Często potwory te są rdzeniem sił obcych podczas ataków na lądzie. To silna i potężna broń, którą oficerowie tasotów stosują z zabójczą skutecznością.\"\n  STR_TRISCENE_AUTOPSY: \"Sekcja zwłok tryskona\"\n  STR_TRISCENE_AUTOPSY_UFOPEDIA: \"Pod nożem naukowców tryskon ujawnia, że jest starożytną istotą, uzupełnioną o cyberwszczepy i systemy broni. Jego bardzo mały mózg jest sprzężony z małym modułem komputerowym zamontowanym w uprzęży sterującej, którą noszą wszystkie te stworzenia. Mocna naturalna skóra i drapieżny instynkt wzmocniony dodatkowymi brońmi czynią go śmiertelnym przeciwnikiem w każdym otoczeniu.\"\n  STR_HALLUCINOID_UFOPEDIA: \"Korzystając z zasobów oceanu, obcy ukształtowali te wielkie ziemskie stworzenia jako broń. Nie daj się zwieść spokojnym ruchom tych podmorskich żeglarzy. Posługujący się lodowatym dotykiem parzydełek halucynoid jest groźnym przeciwnikiem.\"\n  STR_HALLUCINOID_AUTOPSY: \"Sekcja zwłok halucynoida\"\n  STR_HALLUCINOID_AUTOPSY_UFOPEDIA: \"Wśród wielu warstw galaretowego ciała tego organizmu mieści się potężny zamrażacz chemiczny, jego główna zdolność ofensywna. Miękka i prężna skóra halucynoida wydaje się podatna na ataki cieplne. Często mutant ten jest spotykany w towarzystwie swoich panów, akwatoidów.\"\n  STR_XARQUID_UFOPEDIA: \"Kolejny zmodyfikowany ziemski bezkręgowiec, ksarkuid, to piękne i niebezpieczne stworzenie. Szybko pływający gigant kryje niszczycielski arsenał broni, rozprysk duszącego atramentu i strumień zjonizowanych cząstek. Od naszych pierwszych spotkań z tymi potężnymi stworami mamy baczenie na ich moce oraz na ich władców, mściwych skrzelaków.\"\n  STR_XARQUID_AUTOPSY: \"Sekcja zwłok ksarkuida\"\n  STR_XARQUID_AUTOPSY_UFOPEDIA: \"Ten przerośnięty łodzik wyrósł na diecie z leków obcych i chirurgicznych modyfikacji. Gwałcąc prawa natury, skrzelaki dodały stworzeniu mechaniczne systemy kontroli, a więc naturalna forma tego stworzenia dziś już nie występuje. Stosowane jako organiczna platforma na broń, ksarkuidy ze swoją twardą skorupą i dobrą mobilnością stanowią wymagającego przeciwnika.\"\n  STR_ION_BEAM_ACCELERATORS_UFOPEDIA: \"Obce łodzie latające operują dzięki złożonym systemom siłowym, które nadają im niewiarygodne prędkości pod wodą. Podstawą ich działania jest dyslokator jonowy, który używa zrbitu jako katalizatora, dzięki czemu silniki wypierają swoją stukrotną objętość wody na sekundę. Ta ogromna moc daje obcym zdolność prześcignięcia niemal każdej ziemskiej jednostki pływającej. Możemy skopiować ten system napędowy używając akwaplastyku i zrbitowych ogniw zasilających.\"\n  STR_MAGNETIC_NAVIGATION_UFOPEDIA: \"Jednostki te generują kuliste wielowarstwowe pole magnetyczne, rzutowane przez bloki nawigacyjne na odległość do 1000 m wokół łodzi. Nawigatorzy obcych są bezpośrednio podłączeni do maszyn i dzięki nim wyczuwają niewidzialny świat ukryty pod falami. W interfejsie systemu zastosowano zmodyfikowane tkanki mózgowe obcych, które komunikują się bezpośrednio z mózgiem operatora poprzez łącze neuronowe.\"\n  STR_ALIEN_SUB_CONSTRUCTION_UFOPEDIA: \"Każda jednostka ma strukturę podobną do kameleona, starannie wzorowaną na morskich stworzeniach i zbudowaną z akwaplastyku. Każda łódź podwodna działa jak organizm: załoga i statek są w harmonii. Większość systemów możemy skopiować, a następnie rozwinąć technikę hybrydową, która pozwoli nam wspiąć się na ten sam poziom techniczny.\"\n  STR_ALIEN_CRYOGENICS_UFOPEDIA: \"Niezliczeni obcy, którzy spoczywają w ukryciu na Ziemi, pozostają w hibernacji, kriogenicznie zamrożeni. Wszystkie istoty są zapieczętowane w kapsułach, a temperatura ich ciała jest zredukowana do punktu, w którym funkcje życiowe są wtrzymane. Jak dotąd badania tych kapsuł pokazują, jak nieprawdopodobnie długo trwa hibernacja, niekiedy ponad 60 milionów lat.\"\n  STR_ALIEN_CLONING_UFOPEDIA: \"Wielu schwytanych obcych jest identycznych aż do ich DNA, to pod każdym względem kopie. Próbki komórek z banków zamrożonych genów obcych umieszczane są w specjalnych komorach. Niektóre jednostki zawierają ludzi lub ludzkie części. Możliwe, że innym zastosowaniem tych jednostek klonujących jest tworzenie jakiejś ludzko-obcej hybrydy.\"\n  STR_ALIEN_LEARNING_ARRAYS_UFOPEDIA: \"Za pomocą Implantów kontroli molekularnej w czaszkach obcych maszyny te ładują informację bezpośrednio do mózgu. Świeżo sklonowani obcy są dowożeni do tych jednostek, by do ich czystych umysłów wpłynęły wspomnienia ich rasy oraz wszelkie dane naukowe lub wojskowe.\"\n  STR_ALIEN_IMPLANTER_UFOPEDIA: \"Ta jednostka jest używana do wszczepiania obcym implantów kontroli molekularnej, zapładniania ras reproduktorów i umieszczania lub usuwania organów i elektroniki z dowolnej istoty. Sądziliśmy, że procedura ta jest przeprowadzana na znieczulonym pacjencie, ale jest on w pełni świadomy zabiegu i niestety ludzka anatomia wydaje się perfekcyjnie pasować do urządzenia.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"Mamy teraz dość danych, by ustalić, dlaczego obcy porywają ludzi. Nie są oni pożywieniem, nie wszczepia się im obcych płodów, ale stanowią bazę dla szeregu istot i systemów kontrolnych. Technika obcych opiera się na wspólnym umyśle, dzielonym intelekcie, a ludzki mózg jest idealnym ośrodkiem dla takich systemów. Ludzka tkanka mózgowa jest używana w większości obcych biologicznych systemów komputerowych przeznaczonych do przechowywania i pozyskiwania zasobów, a pozostałości znajdują zastosowanie w budowie i hodowli.\"\n  STR_AQUA_PLASTICS_UFOPEDIA: \"W obcych łodziach podwodnych i budowlach stosuje się niezwykle silny, giętki i odporny materiał do konstrukcji większości elementów. Akwaplastyk to złożone, wielowiązaniowe materiały katalizowane przez zrbit. Gęsta, lecz lekka substancja jest nawet mocniejsza niż tytan czy kewlar.\"\n  STR_ZRBITE_UFOPEDIA: \"Jest to stop obcego pochodzenia, po części złoto, po części materiał biologiczny. Gdy jest używany jako źródło energii, małe ilości generują więcej mocy niż 10 razy większa jednostka nuklearna. Skopiowanie tego materiału wykracza poza nasze możliwości techniczne, gdyż większość jego składników ma obce pochodzenie.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"Obcy atakują na całym świecie z bezlitosną skutecznością. Nie możemy przyszpilić ich źródła. Może to jakaś głębia oceaniczna, zbyt dla nas nieprzenikniona, by ich wykryć? Nie wszystkie organizmy, które napotkaliśmy, są obce; niektóre są bardzo stare, niektóre pochodzą ze ścieżek ewolucji, które uznawaliśmy za wymarłe. Mamy do czynienia z zagrożeniem, które było uśpione od tysiącleci, subtelną symbiozą człowieka i obcego. Głęboko w oceanach położone są starożytne miejsca używane przez obcych do kontaktów z ich gwiezdnymi kuzynami. Każde z tych dwunastu miejsc zawiera urządzenie synomium, potężny twór obcej techniki. Teraz, kiedy ich machina wojenna ruszyła, obcy reaktywowali te miejsca, by rozszerzyć sieć Kontroli Molekularnej, więc za wszelką cenę musimy je zniszczyć.\"\n  STR_THE_ULTIMATE_THREAT_UFOPEDIA: \"Sześćdziesiąt pięć milionów lat temu ogromny statek kolonialny został wysłany na ziemię z odległego świata obcych. Gdy przeogromny statek zbliżył się do niemowlęcej planety, masywny i gwałtowny rozbłysk słoneczny spowodował awarię systemów nawigacji. Okaleczona i niesprawna, gigantyczna bryła spadła gwałtownie przez stratosferę, wyłaniając się na kredowym niebie. Na ziemi niezliczone formy życia wytężyły wzrok ku niebu, gdy w ich planetę uderzył wróg. Rozległa chmura pyłu zatkała atmosferę i gdy ląd ostygł, dominująca forma życia, potężne dinozaury, wyginęła. Ale 400 miliardów ton T'leth nie zostało zniszczonych w wyniku zderzenia; zaawansowane superkomputery zainicjowały kriogeniczny cykl snu istot przetrzymywanych w swych trzewiach. Gdy minęły eony, komputery wybudziły oddziały obcych, by spróbowały skomunikować się ze swymi gwiezdnymi kuzynami, lecz na próżno; jądro obcej mocy nadal spało.\"\n  STR_TLETH_THE_ALIEN_CITY: \"T'leth, miasto obcych\"\n  STR_TLETH_THE_ALIEN_CITY_UFOPEDIA: \"T'leth, wielki kolonizacyjny statek obcych, zalega w głębinie Sigsbee w Zatoce Meksykańskiej. W sercu miasta znajduje się obcy koszmar, tak plugawy i tak potężny, że nawet śmierć go nie dosięga. W komorze z obcego metalu spoczywa śpiące ciało wielkiego marzyciela, Najwyższego Obcego. Podniesienie T'leth ponad fale rozpocznie w nim ożywczy cykl, a wówczas będzie niepowstrzymane. Wprawdzie nie jest żywy, choć też nie martwy, ale obcy umysł kontroluje armię najeźdźców. Dziwna technologia kontroli molekularnej łączy wszystkich obcych z Jednością oraz Jedność z wszystkimi obcymi. Genetycznie przeobrażone obco-ludzkie płody dostarczają obcemu umysłowi energii i tworzą więź pomiędzy rządzącym a jego podmiotami. Mit o Najwyższym Obcym istniał w sercach i umysłach ludzkości od wieków, a morza zawsze skrywały ostateczną prawdę.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"WSKAŻ MIEJSCE - CZAS: 5 sekund\"\n  STR_CANCEL_UC: \"ANULUJ\"\n  STR_NONE: \"Brak\"\n  STR_UNKNOWN: \"Nieznane\"\n  STR_POOR: \"Słabo\"\n  STR_AVERAGE: \"Średnio\"\n  STR_GOOD: \"Dobrze\"\n  STR_EXCELLENT: \"Znakomicie\"\n  STR_BUILD_NEW_BASE_UC: \"BUDUJ NOWĄ BAZĘ\"\n  STR_BASE_INFORMATION: \"INFORMACJE O BAZIE\"\n  STR_EQUIP_CRAFT: \"WYPOSAŻENIE STATKÓW\"\n  STR_BUILD_FACILITIES: \"BUDUJ INSTALACJĘ\"\n  STR_RESEARCH: \"BADANIA\"\n  STR_MANUFACTURE: \"PRODUKCJA\"\n  STR_TRANSFER_UC: \"TRANSFERUJ\"\n  STR_PURCHASE_RECRUIT: \"KUP/ZATRUDNIJ\"\n  STR_SACK: \"ZWOLNIJ\"\n  STR_SELL_SACK_UC: \"SPRZEDAJ/ZWOLNIJ\"\n  STR_GEOSCAPE_UC: \"EKRAN ZIEMI\"\n  STR_NAME: \"Nazwa\"\n  STR_AREA: \"Obszar\"\n  STR_BUILD_NEW_BASE: \"Buduj nową bazę\"\n  STR_CANCEL: \"Anuluj\"\n  STR_COST_UC: \"KOSZT>\"\n  STR_CONSTRUCTION_TIME_UC: \"CZAS BUDOWY>\"\n  STR_DAY:\n    one: \"{N} dzień\"\n    few: \"{N} dni\"\n    many: \"{N} dni\"\n    other: \"{N} dni\"\n  STR_HOUR:\n    one: \"{N} godzina\"\n    few: \"{N} godziny\"\n    many: \"{N} godzin\"\n    other: \"{N} godzin\"\n  STR_MAINTENANCE_UC: \"UTRZYMANIE>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Instalacja\"\n  STR_CURRENT_RESEARCH: \"AKTUALNE BADANIA\"\n  STR_SCIENTISTS_AVAILABLE: \"Dostępnych naukowców>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Wysłanych do badań>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Wolnych stanowisk badań>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"BADANY PROJEKT\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"WYSŁANYCH DO BADAŃ\"\n  STR_PROGRESS: \"POSTĘP\"\n  STR_NEW_PROJECT: \"Nowy projekt\"\n  STR_CANCEL_PROJECT: \"ANULUJ PROJEKT\"\n  STR_NEW_RESEARCH_PROJECTS: \"NOWE PROJEKTY NAUKOWE\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"DOSTĘPNYCH NAUKOWCÓW>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"WOLNYCH STANOWISK BADAŃ>{ALT}{0}\"\n  STR_INCREASE: \"Zwiększ\"\n  STR_DECREASE: \"Zmniejsz\"\n  STR_START_PROJECT: \"ROZPOCZNIJ PROJEKT\"\n  STR_CURRENT_PRODUCTION: \"AKTUALNA PRODUKCJA\"\n  STR_ENGINEERS_AVAILABLE: \"Dostępnych techników>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Wysłanych do pracy>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Wolnych stanowisk pracy>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Obecne środki>{ALT}{0}\"\n  STR_ITEM: \"PRZEDMIOT\"\n  STR_ENGINEERS__ALLOCATED: \"Wysłanych do pracy\"\n  STR_UNITS_PRODUCED: \"Wytworzono sztuk\"\n  STR_TOTAL_TO_PRODUCE: \"Sztuk do produkcji\"\n  STR_COST__PER__UNIT: \"Koszt{NEWLINE}za{NEWLINE}sztukę\"\n  STR_DAYS_HOURS_LEFT: \"Pozostało dni/godzin\"\n  STR_NEW_PRODUCTION: \"Nowa produkcja\"\n  STR_PRODUCTION_ITEMS: \"Przedmioty do produkcji\"\n  STR_CATEGORY: \"KATEGORIA\"\n  STR_START_PRODUCTION: \"ROZPOCZNIJ PRODUKCJĘ\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} roboczogodzin na jedną sztukę\"\n  STR_COST_PER_UNIT_: \"Koszt za sztukę>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Wymagana przestrzeń robocza>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"WYMAGANE SPECJALNE MATERIAŁY\"\n  STR_ITEM_REQUIRED: \"WYMAGANY PRZEDMIOT\"\n  STR_UNITS_REQUIRED: \"WYMAGANYCH SZTUK\"\n  STR_UNITS_AVAILABLE: \"DOSTĘPNYCH SZTUK\"\n  STR_STOP_PRODUCTION: \"PRZERWIJ PRODUKCJĘ\"\n  STR_ENGINEERS_AVAILABLE_UC: \"DOSTĘPNYCH TECHNIKÓW>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"WOLNA PRZESTRZEŃ ROBOCZA>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"ZYSK MIESIĘCZNY>{ALT}{0}\"\n  STR_INCREASE_UC: \"ZWIĘKSZ\"\n  STR_DECREASE_UC: \"ZMNIEJSZ\"\n  STR_UNITS_TO_PRODUCE: \"Sztuk do produkcji\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Kup przedmioty/Zatrudnij ludzi\"\n  STR_COST_OF_PURCHASES: \"Koszt transakcji>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"KOSZT ZA SZTUKĘ\"\n  STR_QUANTITY_UC: \"ILOŚĆ\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"DOSTĘPNY PERSONEL/CAŁY PERSONEL>\"\n  STR_SOLDIERS: \"Akwanauci\"\n  STR_SCIENTISTS: \"Naukowcy\"\n  STR_ENGINEERS: \"Technicy\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"UŻYWANA PRZESTRZEŃ/DOSTĘPNA PRZESTRZEŃ>\"\n  STR_LIVING_QUARTERS: \"Kwatery mieszkalne\"\n  STR_STORES: \"Magazyny\"\n  STR_LABORATORIES: \"Laboratoria\"\n  STR_WORK_SHOPS: \"Warsztaty\"\n  STR_HANGARS: \"Doki dla łodzi\"\n  STR_SHORT_RANGE_DETECTION: \"Sonar krótkiego zasięgu\"\n  STR_DEFENSE_STRENGTH: \"Siła obrony\"\n  STR_TRANSFERS_UC: \"TRANSFERY\"\n  STR_TRANSFERS: \"Transfery\"\n  STR_ARRIVAL_TIME_HOURS: \"Godzin do przybycia\"\n  STR_COST_: \"Koszt>{ALT}{0}\"\n  STR_AREA_: \"Teren>{ALT}{0}\"\n  STR_BASE_NAME: \"Nazwa bazy?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"WYBIERZ POŁOŻENIE ŚLUZY\"\n  STR_TRANSFER: \"Transfer\"\n  STR_AMOUNT_TO_TRANSFER: \"SZTUK DO TRANSFERU\"\n  STR_SELECT_DESTINATION_BASE: \"Wybierz bazę docelową\"\n  STR_COST: \"Koszt\"\n  STR_INTRO_1: \"Prawa autorskie: 1995 r., MicroProse\"\n  STR_INTRO_2: \"Mars: upadek Cydonii.\"\n  STR_INTRO_3: \"Po zniszczeniu serca obcej machiny wojennej, X-Com triumfalnie powraca do domu. Jednakże nie wszystko w zrujnowanej marsjańskiej bazie jest martwe.\"\n  STR_INTRO_4: \"Potężna wiązka tachionowa zostaje wystrzelona z gruzów cydońskiego centrum dowodzenia i pędzi przez pustkę. Jej cel...\"\n  STR_INTRO_5: \"Ziemia.\"\n  STR_INTRO_6: \"Wiązka uderza w długo uśpiony receptor w głębinach oceanu. Wielkie uśpione komputery zaczynają się wybudzać. W głębi, pozostając poza wzrokiem ludzi, wielkie komory obcych rozpoczynają swój długi cykl reanimacji.\"\n  STR_INTRO_7: \"Rok 2040: nieświadoma Ziemia. O koszmarze wojny obcych już zapomniano. Ale w zaginionych i ukrytych miejscach oceanu hordy obcych są gotowe - gotowe do obalenia ludzkości i zawładnięcia światem.\"\n  STR_INTRO_8: \"Obcy uderzają w ludzkość; szukają osobników dla swoich spaczonych eksperymentów; rabują cenne minerały i zasoby na całym świecie; łupią oceany. Następnie obcy kierują uwagę ponad poziom poziom morza.\"\n  STR_INTRO_9: \"Potężna latające łodzie dziwnej konstrukcji przemierzają oceany, - wypatrując, szukając, polując.........\"\n  STR_INTRO_10: \"Atakując znalezione ofiary.\"\n  STR_INTRO_11: \"Niesamowite nowe rodzaje broni zostają wysłane przeciw bezbronnemu światu. Jesteśmy całkowicie na łasce obcych.{NEWLINE}Tylko jedna organizacja może nas uratować; lecz odwróciliśmy się do nich plecami dawno temu......\"\n  STR_INTRO_12: \"Eksperymentalna podwodna placówka organizacji X-Com\"\n  STR_INTRO_13: \"'Mayday! mayday! Tu transatlantycki liniowiec Hyperion. Atakują nas! Mayday! Mayd...'\"\n  STR_INTRO_14: \"'Centrum Dowodzenia do Doku Jeden: Otworzyć drzwi oceaniczne', 'wypuścić Barakudę Zero Jeden. Mamy tu sytuację ataku obcych - stan Czerwony.'{NEWLINE}'Powtarzam: stan Czerwony'\"\n  STR_INTRO_15: \"Obcy są bezwzględni w swojej skuteczności....\"\n  STR_INTRO_16: \"...niezawodni w swojej celności\"\n  STR_INTRO_17: \"'Barakuda Zero Jeden do bazy' - 'zbliżamy się do szczątków Hyperionu'.\"\n  STR_INTRO_18: \"'Zwalniam'.{NEWLINE}'Dwa metry'{NEWLINE}'Jeden metr'{NEWLINE}'Wszyscy akwanauci przygotować się do natychmiastowej akcji.'\"\n  STR_INTRO_19: \"...........'Śluza zabezpieczona...'zbliżam się do wraku'.{NEWLINE}'O matko!'{NEWLINE}'Odbierasz te stwory z mojej kamery ze skafandra?'\"\n  STR_GAMEOVER_1: \"Zawiedliśmy, obcy unicestwili naszą ostatnią nadzieję na ocalenie.{NEWLINE}X-Com został zniszczony i Ziemia leży u stóp starożytnego wroga.\"\n  STR_GAMEOVER_2: \"T'leth grzmi wysoko w stratosferze i zaczyna się przemieszczać poprzez świat. Sieje śmierć i zbiera pozostałości rasy ludzkiej. Głęboko w jego wnętrzu zaczyna się budzić morderczy umysł obcego.\"\n  STR_GAMEOVER_3: \"W stolicach miast wszystkich narodów wykreśla się desperackie plany. Wszystko to spali na panewce, bez techniki użyczonej przez projekt badawczy X-Com nasze bronie są nieskuteczne.\"\n  STR_GAMEOVER_4: \"Obcy zakładają bazy na biegunach polarnych i zaczynają roztapiać lód, świat stanie się rozległym oceanem. Pozostałości ludzkiej rasy są spędzane jak bydło i używane w odrażających eksperymentach hodowlanych dla nieznanych, obcych celów. Niebo ciemnieje, a straszliwy pomór ogarnia ziemskie lądy.\"\n  STR_GAMEOVER_5: \"Nie możemy stawić oporu nowemu światowemu porządkowi, a tych, którzy spróbują, dosięga płomienna zagłada od niepojętych broni obcych. Dla reszty z nas nie ma takiego błogosławionego odpuszczenia, matka Ziemia stała się światem obcych, a ludzkość jest zgubiona pod pełzającym koszmarem.\"\n  STR_OUTRO_1: \"Grobowiec, spustoszony i zdziesiątkowany, bulgoczące ryki dobiegają z trumny w jego centrum.{NEWLINE}Głupcy, wszyscy zginiecie....................\"\n  STR_OUTRO_2: \".................nikt nie ucieknie.\"\n  STR_OUTRO_3: \"Wielka eksplozja tryska z grobowca i rozdziera całe miasto, gruz i dym wypełniają powietrze. Plany obcych zostały pokrzyżowane........\"\n  STR_OUTRO_4: \"Wynaturzony ogrom T'leth zaczyna pękać. Płomienie i ogień tańczą na lśniących iglicach i halach z adamantu.\"\n  STR_OUTRO_5: \"Potężne twierdza obcych wali się do morza, wycie miętolonego metalu i dusz wypełnia powietrze. Wielki Marzyciel nie będzie już śnił o podbijaniu świata.\"\n  STR_OUTRO_6: \"Jeszcze jeden przeraźliwy grzmot i T'leth rozpada się na części.{NEWLINE}Zagrożenie ze strony obcych minęło, Ziemia jest oczyszczona..................\"\n  STR_OUTRO_7: \"Senna, niebiesko-zielona planeta w odległym zakątku Galaktyki.\"\n  STR_OUTRO_8: \"Niedaleka przyszłość, bezpieczne miejsce do życia.\"\n  STR_OUTRO_9: \"Obce zagrożenie dla Ziemi zostało pokonane dawno temu.\"\n  STR_OUTRO_10: \"Rozległe metropolie mieszczą niezliczone miliardy ludzi.\"\n  STR_OUTRO_11: \"Dokonania X-Comu i wojny z obcymi stały się tematem historyjek dla dzieci.\"\n  STR_OUTRO_12: \"Ale legendy mają to do siebie, że zawierają ziarno prawdy............\"\n  STR_RISE_1: \"T'leth pojawia się w różnych legendach różnych krajów pod różnymi nazwami.\"\n  STR_RISE_2: \"Z wrzaskiem eksplozji, który rozbrzmiał na całym świecie, T'leth zaczął powstawać z dna morza.\"\n  STR_RISE_3: \"Wielka budowla wychynęła z wód Zatoki Meksykańskiej.\"\n  STR_RISE_4: \"400 miliardów ton obcego metalu, potężne miasto obcych, w którym spoczywa śpiące ciało Najwyższego Obcego. Uwięziony na ziemi od 65 milionów lat, ten potworny kosmiczny bóg zaczyna się poruszać.\"\n  STR_RISE_5: \"Wody gotują się i wzburzają, gdy grobowiec Wielkiego Marzyciela wyłania się w świetle dnia................\"\n  STR_RISE_6: \".........światło, które wkrótce zgaśnie, chyba że X-Com zdoła zniszczyć machinę wojenną obcych.\"\n  STR_YOU_HAVE_FAILED: \"Nie udało ci się zatrzymać machiny wojennej obcych. Finansujące organizacje, zawiedzione twoimi wynikami, próbują wynegocjować z obcymi niemilitarne rozwiązanie. Najeźdźcy mają zupełnie inne zamiary i wkrótce cały świat dowie się prawdy...\"\n  STR_TOTAL_UC: \"SUMA\"\n  STR_INCOME: \"Dochód\"\n  STR_EXPENDITURE: \"Wydatki\"\n  STR_MAINTENANCE: \"Utrzymanie\"\n  STR_BALANCE: \"Bilans\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"Aktywność obcych na morzach\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"Aktywność obcych w strefach\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"Aktywność X-Comu na morzach\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"Aktywność X-Comu w strefach\"\n  STR_FINANCE: \"Finanse\"\n  STR_DATE_FIRST: \"{0}.\"\n  STR_DATE_SECOND: \"{0}.\"\n  STR_DATE_THIRD: \"{0}.\"\n  STR_DATE_FOURTH: \"{0}.\"\n  STR_FINANCE_THOUSANDS: \"tys. $\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Brakuje materiałów specjalnych do produkcji{NEWLINE}{0}{NEWLINE}w bazie{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Brakuje pieniędzy do produkcji{NEWLINE}{0}{NEWLINE}w bazie{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"Produkcja {0}{NEWLINE}w bazie{NEWLINE}{1}{NEWLINE}została zakończona\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"Budowa {0}{NEWLINE}w bazie {1}{NEWLINE}została zakończona\"\n  STR_OK_5_SECONDS: \"OK - CZAS: 5 sekund\"\n  STR_RESEARCH_COMPLETED: \"Badania ukończone\"\n  STR_VIEW_REPORTS: \"ZOBACZ RAPORTY\"\n  STR_WE_CAN_NOW_RESEARCH: \"Możemy teraz badać\"\n  STR_WE_CAN_NOW_PRODUCE: \"Możemy teraz produkować\"\n  STR_SUNDAY: \"NIEDZIELA\"\n  STR_MONDAY: \"PONIEDZIAŁEK\"\n  STR_TUESDAY: \"WTOREK\"\n  STR_WEDNESDAY: \"ŚRODA\"\n  STR_THURSDAY: \"CZWARTEK\"\n  STR_FRIDAY: \"PIĄTEK\"\n  STR_SATURDAY: \"SOBOTA\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Brakuje {0}, by zatankować łódź {1} w bazie {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Brakuje {0}, by dozbroić łódź {1} w bazie {2}\"\n  STR_UFO_IS_NOT_RECOVERED: \"USO nie zostało odzyskane\"\n  STR_UFO_IS_RECOVERED: \"USO zostało odzyskane\"\n  STR_CRAFT_IS_LOST: \"Łódź latająca stracona\"\n  STR_TERROR_CONTINUES: \"Aktywność obcych trwa\"\n  STR_ALIENS_DEFEATED: \"Obcy pokonani\"\n  STR_BASE_IS_LOST: \"Baza stracona\"\n  STR_BASE_IS_SAVED: \"Baza uratowana\"\n  STR_ALIEN_BASE_STILL_INTACT: \"Kolonia obcych nadal istnieje\"\n  STR_ALIEN_BASE_DESTROYED: \"Kolonia obcych zniszczona\"\n  STR_ALIENS_KILLED: \"ZABICI OBCY\"\n  STR_ALIEN_CORPSES_RECOVERED: \"ZNALEZIONYCH ZWŁOK OBCYCH\"\n  STR_LIVE_ALIENS_RECOVERED: \"POJMANYCH ŻYWYCH OBCYCH\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"ZNALEZIONYCH ARTEFAKTÓW OBCYCH\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"ZNISZCZONO STEROWNIĘ OBCEJ KOLONII\"\n  STR_ALIEN_SYNOMIUM_DEVICE_DESTROYED: \"ZNISZCZONO SYNOMIUM OBCYCH\"\n  STR_ALIEN_SYNOMIUM_DEVICE_FAILED: \"NIE ZNISZCZONO SYNOMIUM OBCYCH\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"CYWILI ZABITYCH PRZEZ OBCYCH\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"CYWILI ZABITYCH PRZEZ AKWANAUTÓW X-COMU\"\n  STR_CIVILIANS_SAVED: \"URATOWANYCH CYWILI\"\n  STR_XCOM_OPERATIVES_KILLED: \"ZABITYCH AKWANAUTÓW X-COMU\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"ZAGINIONYCH W AKCJI AKWANAUTÓW X-COMU\"\n  STR_TANKS_DESTROYED: \"ZNISZCZONYCH PSB X-COMU\"\n  STR_XCOM_CRAFT_LOST: \"STRACONYCH ŁODZI X-COMU\"\n  STR_UFO_RECOVERY: \"PRZEJĘTE POZOSTAŁOŚCI USO\"\n  STR_ALIEN_BASE_RECOVERY: \"PRZEJĘTE POZOSTAŁOŚCI KOLONII OBCYCH\"\n  STR_BASE_UNDER_ATTACK: \"Baza '{0}' jest atakowana!\"\n  STR_BASE_DEFENSES_INITIATED: \"ZAINICJOWANO SYSTEMY OBRONNE BAZY\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"TARCZE ODPYCHAJĄ USO!\"\n  STR_FIRING: \"STRZELA\"\n  STR_HIT: \"TRAFIENIE!\"\n  STR_UFO_DESTROYED: \"USO ZNISZCZONE!\"\n  STR_MISSED: \"PUDŁO!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Sprzedaj produkty/Zwolnij ludzi\"\n  STR_VALUE_OF_SALES: \"WARTOŚĆ SPRZEDAŻY>{ALT}{0}\"\n  STR_FUNDS: \"FUNDUSZE>{ALT}{0}\"\n  STR_SELL_SACK: \"Sprzedaj/Zwolnij\"\n  STR_VALUE: \"Wartość\"\n  STR_CRAFT_: \"ŁÓDŹ LATAJĄCA>{ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"PRZEJĘCIE ROZBITEGO USO\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"ZACHOWAJ SZCZEGÓLNĄ OSTROŻNOŚĆ - w łodzi i jej okolicy będą obcy. Misja będzie ukończona, gdy wszystkie wrogie jednostki zostaną wyeliminowane lub zneutralizowane. Potem można rozpocząć odzyskiwanie pozostałości obcych łodzi, urządzeń technicznych i zwłok. Aby przerwać misję, zawróć akwanautów X-Comu do łodzi i kliknij ikonę 'Przerwij misję'.\"\n  STR_UFO_GROUND_ASSAULT: \"SZTURM NA USO\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"Zbadaj miejsce lądowania i, jeśli to możliwe, wejdź do USO. Misja zakończy się powodzeniem, gdy wszystkie jednostki wroga zostaną wyeliminowane lub zneutralizowane. Nastąpi wtedy przejęcie pozostałości USO, przedmiotów i martwych obcych. Aby przerwać misję, zawróć akwanautów X-Comu do łodzi i kliknij ikonę 'Przerwij misję'.\"\n  STR_BASE_DEFENSE: \"OBRONA BAZY X-COMU\"\n  STR_BASE_UC_: \"BAZA>{0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"W pobliżu wylądował statek obcych. Nasza baza jest w wielkim niebezpieczeństwie. Standardową procedurą w takiej sytuacji jest ewakuacja całego niewalczącego personelu wszystkimi dostępnymi łodziami X-Comu. Jednostki obcych mogły wejść do bazy przez śluzę lub windę dostępu. Obroń bazę i jej istotne instalacje za wszelką cenę. To jest walka na śmierć i życie. Jeśli klikniesz na ikonę 'Przerwij misję' i potwierdzisz wybór, poniesiesz klęskę i utracisz bazę.\"\n  STR_ALIEN_COLONY_ATTACK_MISSION: \"ATAK NA KOLONIĘ OBCYCH\"\n  STR_ALIEN_BASE_ASSAULT: \"KOLONIA OBCYCH: CZĘŚĆ PIERWSZA\"\n  STR_ALIEN_COLONY_P1_BRIEFING: \"Ta misja to atak na instalację kolonizacyjną obcych. Dzieli się ona na 2 poziomy; aby przejść dalej, zaprowadź wszystkich akwanautów do świecącego wyjścia w pierwszym kompleksie i kliknij ikonę 'Przerwij Misję'. Jakiekolwiek pozostawione wyposażenie pozostanie na dnie morza dopóki nie zakończysz części drugiej. Aby uciec, zawróć akwanautów X-Comu do łodzi i kliknij ikonę 'Przerwij misję'.\"\n  STR_ALIEN_COLONY_P2: \"KOLONIA OBCYCH: CZĘŚĆ DRUGA\"\n  STR_ALIEN_COLONY_P2_BRIEFING: \"Po pokonaniu pierwszego poziomu wkraczasz do serca kolonii. Twoją misją jest zniszczenie centrum kontroli, urządzenia synomium, lub wyeliminowanie wszystkich obcych. Aby przerwać misję, zbierz akwanautów w obszarze startowym i kliknij na ikonie 'Przerwij misję'. Całe możliwe do zebrania wyposażenie X-Comu wróci do bazy.\"\n  STR_ALIENS_LAUNCH_PORT_TERROR: \"OBCY ATAKUJĄ{NEWLINE}PORT W KRAJU\"\n  STR_PORT_TERROR: \"ATAK OBCYCH NA PORT\"\n  STR_PORT_TERROR_BRIEFING: \"Obcy rozpoczęli atak przeciwko obiektom na powierzchni. Port i jego ludność cywilna są zagrożone. Twój oddział musi wyeliminować wszystkich obcych i ocalić niewinne osoby postronne przed tą napaścią. Aby uciec, zawróć akwanautów X-Comu do łodzi i kliknij ikonę 'Przerwij misję'.\"\n  STR_ALIENS_LAUNCH_ISLAND_TERROR: \"OBCY ATAKUJĄ{NEWLINE}WYSPĘ W KRAJU\"\n  STR_ISLAND_TERROR: \"ATAK OBCYCH NA WYSPĘ\"\n  STR_ISLAND_TERROR_BRIEFING: \"Obcy rozpoczęli atak przeciwko obiektom na powierzchni. Wyspa i jej ludność cywilna są zagrożone. Twój oddział musi wyeliminować wszystkich obcych i ocalić niewinne osoby postronne przed tą napaścią. Aby uciec, zawróć akwanautów X-Comu do łodzi i kliknij ikonę 'Przerwij misję'.\"\n  STR_ALIENS_ATTACK_SHIPPING_ROUTE: \"OBCY ATAKUJĄ{NEWLINE}SZLAK WODNY\"\n  STR_CARGO_SHIP_P1: \"STATEK TOWAROWY: CZĘŚĆ PIERWSZA\"\n  STR_CARGO_SHIP_P2: \"STATEK TOWAROWY: CZĘŚĆ DRUGA\"\n  STR_CRUISE_SHIP_P1: \"STATEK WYCIECZKOWY: CZĘŚĆ PIERWSZA\"\n  STR_CRUISE_SHIP_P2: \"STATEK WYCIECZKOWY: CZĘŚĆ DRUGA\"\n  STR_SHIP_RESCUE_MISSION: \"MISJA RATOWANIA STATKU\"\n  STR_SHIP_RESCUE_P1_BRIEFING: \"Ta misja to polowanie na robaki, wyeliminuj wszystkich obcych znajdujących się na statku i chroń życie każdego cywila na pokładzie. Obcy rozproszyli się nad i pod pokładami, zabezpiecz wyższe pokłady przed zejściem na niższe. Aby wyjść, umieść akwanautów w latającej łodzi i kliknij na ikonie 'Przerwij Misję'.\"\n  STR_SHIP_RESCUE_P2_BRIEFING: \"Wyższy pokład jest teraz czysty, przejdź do niższych pokładów. Korzystając z windy towarowej możesz zejść do ładowni. Aby ukończyć tą misję twój oddział musi wyeliminować wszystkich Obcych na tym poziomie. Aby przerwać umieść wszystkich akwanautów w punkcie początku windy i kliknij na ikonie 'Przerwij Misję'.\"\n  STR_ALIEN_ACTIVITY_DETECTED: \"WYKRYTO AKTYWNOŚĆ OBCYCH\"\n  STR_ALIEN_CONTACT_SITE_MISSION: \"PUNKT KOMUNIKACYJNY OBCYCH\"\n  STR_ARTIFACT_SITE_P1: \"PUNKT KOMUNIKACYJNY OBCYCH: CZĘŚĆ PIERWSZA\"\n  STR_ARTIFACT_SITE_P1_BRIEFING: \"Ta misja to napad na niedawno aktywowane miejsce komunikacyjne Obcych. Są 2 poziomy tego miejsca, dno z piramidami Obcych i ukryty kompleks Obcych. Aby przejść dalej weź wszystkich akwanautów to wejścia do kompleksu i kliknij na ikonie 'Przerwij Misję'. Aby wyjść, umieść akwanautów w latającej łodzi i kliknij na ikonie 'Przerwij Misję'.\"\n  STR_ARTIFACT_SITE_P2: \"PUNKT KOMUNIKACYJNY OBCYCH: CZĘŚĆ DRUGA\"\n  STR_ARTIFACT_SITE_P2_BRIEFING: \"Poradziłeś sobie ze strukturami Obcych i wszedłeś do kompleksu, cele misji są jasne. Aby ukończyć misję przeniknij do serca placówki Obcych i zniszcz Urządzenie Kontroli Molekularnej Synomium. Aby przerwać umieść wszystkich akwanautów w punkcie początku wejścia windy i kliknij na ikonie 'Przerwij Misję'.\"\n  STR_SIGSBEE_DEEP_MISSION: \"GŁEBIA SIGSBEE{NEWLINE}MIASTO OBCYCH: POZIOM PIERWSZY\"\n  STR_TLETH_P1_BRIEFING: \"Wkraczamy w nieznane, odtąd wszystko może na nas czekać. Wiemy że są 2 dalsze poziomy przed miastem Obcych i twój oddział musi ścigać się do wyjścia na tym poziomie by wejść do następnego. Aby przejść dalej przemieść wszystkich akwanautów do wyjścia i kliknij na ikonie 'Przerwij Misję'. Przerwanie w każdym innym miejscu zakończy misję.\"\n  STR_TLETH_ATTACK_MISSION: \"ATAK NA T'LETH{NEWLINE}MIASTO OBCYCH: POZIOM DRUGI\"\n  STR_TLETH_P2_BRIEFING: \"Brnąc dalej w nieznane, odtąd możemy spodziewać się wszystkiego. Wiemy, że istnieje jeszcze kolejny poziom przed miastem obcych, a twój oddział musi jak najszybciej dotrzeć do wyjścia z tego poziomu, \\n by przejść do następnego. Aby kontynuować, przemieść wszystkich akwanautów do wyjścia i kliknij na ikonie 'Przerwij Misję'. Przerwanie w każdym innym miejscu zakończy misję.\"\n  STR_FINAL_TLETH_MISSION: \"OSTATNIA FAZA ATAKU NA T'LETH{NEWLINE}MIASTO OBCYCH: POZIOM TRZECI\"\n  STR_TLETH_P3_BRIEFING: \"Koniec jest w zasięgu wzroku, odtąd szukamy krypty Największego Obcego. Zniszcz 8 podajników mocy grobowca by zakończyć zagrożenie Obcych. Nie poddawaj się teraz! Przerwanie zakończy misję.\"\n  STR_TLETH_P1: \"MIASTO OBCYCH: POZIOM PIERWSZY\"\n  STR_TLETH_P2: \"MIASTO OBCYCH: POZIOM DRUGI\"\n  STR_TLETH_P3: \"MIASTO OBCYCH: POZIOM TRZECI\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"BRAKUJE WOLNEGO DOKU DLA PRODUKOWANEGO STATKU!{SMALLLINE}Każdy statek przydzielony w danej bazie, przenoszony do innej bazy, kupowany lub produkowany wymaga co najmniej jednego doku. Wybuduj nowy dok lub przenieś przynajmniej jeden statek do innej bazy.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"BRAKUJE WOLNEGO DOKU DLA KUPOWANEGO STATKU!{SMALLLINE}Każdy statek przydzielony w danej bazie, przenoszony do innej bazy, kupowany lub produkowany wymaga co najmniej jednego doku. Wybuduj nowy dok lub przenieś przynajmniej jeden statek do innej bazy.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"BRAKUJE WOLNEGO DOKU DLA PRZENOSZONEGO STATKU!{SMALLLINE}Każdy statek przydzielony w danej bazie, przenoszony do innej bazy, kupowany lub produkowany wymaga co najmniej jednego doku. Wybuduj nowy dok lub przenieś przynajmniej jeden statek do innej bazy.\"\n  STR_CANNOT_BUILD_HERE: \"NIE MOŻNA TU BUDOWAĆ!{SMALLLINE}Musisz budować obok kapsuły, która już istnieje.\"\n  STR_NO_FREE_ACCOMODATION: \"BRAK WOLNYCH KWATER!{SMALLLINE}Brak wolnych kwater w bazie docelowej.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"BRAKUJE WOLNEGO MIEJSCA W WARSZTACIE!{SMALLLINE}Wybuduj nowy warsztat lub ogranicz pracę nad co najmniej jednym projektem.\"\n  STR_NOT_ENOUGH_MONEY: \"NIEWYSTARCZAJĄCA ILOŚĆ PIENIĘDZY!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"BRAK MIEJSCA W MAGAZYNACH!{SMALLLINE}Wybuduj nowe magazyny lub przenieś część zapasów do innej bazy.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"BRAK WOLNYCH KWATER!{SMALLLINE}Wybuduj nowe kwatery lub przenieś część personelu do innej bazy.\"\n  STR_LAUNCH_INTERCEPTION: \"WYSYŁANIE ŁODZI\"\n  STR_CRAFT: \"ŁÓDŹ\"\n  STR_STATUS: \"STATUS\"\n  STR_BASE: \"BAZA\"\n  STR_READY: \"GOTOWA\"\n  STR_OUT: \"WYSŁANA\"\n  STR_REPAIRS: \"NAPRAWIANA\"\n  STR_REFUELLING: \"TANKOWANA\"\n  STR_REARMING: \"DOZBRAJANA\"\n  STR_TARGET: \"CEL: {0}\"\n  STR_WAY_POINT: \"PUNKT ORIENTACYJNY\"\n  STR_ARE_YOU_SURE_CYDONIA: \"Czy na pewno chcesz wysłać tę łódź na misję do T'leth?\"\n  STR_YES: \"TAK\"\n  STR_NO: \"NIE\"\n  STR_SELECT_DESTINATION: \"WYBIERZ CEL\"\n  STR_CYDONIA: \"T'LETH\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"WYBIERZ MIEJSCE NA NOWĄ BAZĘ\"\n  STR_RETURN_TO_BASE: \"POWRÓT DO BAZY\"\n  STR_SELECT_NEW_TARGET: \"WYBIERZ NOWY CEL\"\n  STR_PATROL: \"PATROL\"\n  STR_STATUS_: \"STATUS>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"USZKODZONY - WRACA DO BAZY\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"MAŁO PALIWA - WRACA DO BAZY\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"MISJA ZAKOŃCZONA - WRACA DO BAZY\"\n  STR_PATROLLING: \"PATROLUJE\"\n  STR_TAILING_UFO: \"ŚLEDZI USO\"\n  STR_INTERCEPTING_UFO: \"PRZECHWYTUJE USO-{0}\"\n  STR_RETURNING_TO_BASE: \"WRACA DO BAZY\"\n  STR_DESTINATION_UC_: \"CEL: {0}\"\n  STR_BASE_UC: \"BAZA>{ALT}{0}\"\n  STR_SPEED_: \"PRĘDKOŚĆ>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"PRĘDKOŚĆ MAKSYMALNA>{ALT}{0} w.{ALT}\"\n  STR_ALTITUDE_: \"GŁĘBOKOŚĆ>{ALT}{0}\"\n  STR_AIRBORNE: \"NAD LĄDEM\"\n  STR_VERY_LOW: \"PŁYTKO\"\n  STR_LOW_UC: \"NORMALNA\"\n  STR_HIGH_UC: \"GŁĘBOKO\"\n  STR_VERY_HIGH: \"BARDZO GŁĘBOKO\"\n  STR_FUEL: \"PALIWO>{ALT}{0}\"\n  STR_WEAPON_ONE: \"BROŃ L.>{ALT}{0}\"\n  STR_NONE_UC: \"BRAK\"\n  STR_ROUNDS_: \"NABOI>{ALT}{0}\"\n  STR_WEAPON_TWO: \"BROŃ P.>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"ŁÓDŹ\"\n  STR_BASE_: \"Baza>{0}\"\n  STR_NAME_UC: \"NAZWA\"\n  STR_AMMO_: \"AMUNICJA>{ALT}{0}\"\n  STR_CREW: \"ZAŁOGA\"\n  STR_EQUIPMENT_UC: \"SPRZĘT\"\n  STR_ARMOR: \"PANCERZ\"\n  STR_MAX: \"MAKS.>{ALT}{0}\"\n  STR_ROOKIE: \"Marynarz\"\n  STR_SQUADDIE: \"Starszy Marynarz\"\n  STR_SERGEANT: \"Chorąży\"\n  STR_CAPTAIN: \"Porucznik\"\n  STR_COLONEL: \"Komandor\"\n  STR_COMMANDER: \"Kapitan\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Wybierz skład dla: {0}\"\n  STR_SORT_BY: \"SORTUJ WG...\"\n  STR_ORIGINAL_ORDER: \"PIERWOTNA KOLEJNOŚĆ\"\n  STR_MISSIONS2: \"MISJE\"\n  STR_KILLS2: \"ZABITYCH\"\n  STR_WOUND_RECOVERY2: \"CZAS KURACJI\"\n  STR_SPACE_AVAILABLE: \"WOLNE MIEJSCA>{ALT}{0}\"\n  STR_SPACE_USED: \"ZAJĘTE MIEJSCA>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"ZAJĘTO\"\n  STR_RANK: \"RANGA\"\n  STR_WOUNDED: \"RANNY\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Wyposażenie dla: {0}\"\n  STR_DEFENSE_VALUE: \"Wartość obrony\"\n  STR_HIT_RATIO: \"Celność\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}w gotowości do{NEWLINE}lądowania przy:{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"Rozpocząć misję?\"\n  STR_SELECT_ARMAMENT: \"Wybierz uzbrojenie\"\n  STR_AMMUNITION_AVAILABLE: \"DOSTĘPNA AMUNICJA\"\n  STR_ARMAMENT: \"UZBROJENIE\"\n  STR_NOT_AVAILABLE: \"BRAK\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"WYBIERZ PANCERZ DLA{NEWLINE}{ALT}{0}\"\n  STR_TYPE: \"TYP\"\n  STR_PLASTIC_AQUA_ARMOR_UC: \"PANCERZ AKWAPLASTOWY\"\n  STR_ION_ARMOR_UC: \"PANCERZ JONOWY\"\n  STR_MAGNETIC_ION_ARMOR_UC: \"PANCERZ MAGNETYCZNO-JONOWY\"\n  STR_PLASTIC_AQUA_ARMOR_UFOPEDIA: \"Ta zbroja wykorzystuje nowo odkryty materiał obcych, akwaplastyk. Zapewnia ona naszym akwanautom szansę walki przeciwko najazdowi obcych.\"\n  STR_ION_ARMOR_UFOPEDIA: \"Potężna nowa ochrona dla akwanautów. Zbroja ta napędzana jest jonowym źródłem energii i znakomicie wzmacnia szybkość i siłę noszącego. Oferuje najlepszą jak dotąd ochronę dla naszych bojowników.\"\n  STR_MAGNETIC_ION_ARMOR_UFOPEDIA: \"Ulepszenie jonowego pancerza zawiera technologię Bloków Magnetycznych pozwalającą na pełną swobodę ruchu w środowisku wodnym.\"\n  STR_SELECT_ARMOR: \"Wybierz pancerz\"\n  STR_NORTH: \"PÓŁNOC\"\n  STR_NORTH_EAST: \"PÓŁNOCNY WSCHÓD\"\n  STR_EAST: \"WSCHÓD\"\n  STR_SOUTH_EAST: \"POŁUDNIOWY WSCHÓD\"\n  STR_SOUTH: \"POŁUDNIE\"\n  STR_SOUTH_WEST: \"POŁUDNIOWY ZACHÓD\"\n  STR_WEST: \"ZACHÓD\"\n  STR_NORTH_WEST: \"PÓŁNOCNY ZACHÓD\"\n  STR_SELECT_ACTION: \"WYBIERZ ZADANIE\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"KONTYNUUJ POŚCIG PRZECHWYTUJĄCY\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"ŚCIGAJ BEZ PRZECHWYTYWANIA\"\n  STR_VERY_LARGE: \"BARDZO DUŻE\"\n  STR_LARGE: \"DUŻE\"\n  STR_MEDIUM_UC: \"ŚREDNIE\"\n  STR_SMALL: \"MAŁE\"\n  STR_VERY_SMALL: \"BARDZO MAŁE\"\n  STR_GROUNDED: \"WYLĄDOWAŁ\"\n  STR_DETECTED: \"Wykryte\"\n  STR_SIZE_UC: \"ROZMIAR\"\n  STR_ALTITUDE: \"GŁĘBOKOŚĆ\"\n  STR_HEADING: \"KIERUNEK\"\n  STR_SPEED: \"PRĘDKOŚĆ\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"POKAŻ USO - CZAS: 5 sekund\"\n  STR_TRACKING_LOST: \"ZNIKNĘŁO Z SONARU\"\n  STR_REDIRECT_CRAFT: \"WYBIERZ NOWE ZADANIE\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"PŁYŃ/LEĆ DO OSTATNIEJ ZNANEJ POZYCJI USO\"\n  STR_UFO_: \"USO-{0}\"\n  STR_ALIEN_BASE_: \"KOLONIA OBCYCH-{0}\"\n  STR_CRASH_SITE_: \"ROZBITE USO-{0}\"\n  STR_LANDING_SITE_: \"MIEJSCE LĄDOWANIA USO-{0}\"\n  STR_WAY_POINT_: \"PUNKT DOCELOWY-{0}\"\n  STR_TERROR_SITE: \"MIEJSCE TERRORU-{0}\"\n  STR_ARTIFACT_SITE: \"MIEJSCE ARTEFAKTU-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}dotarł do{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"Teraz patroluje\"\n  STR_ALIEN_ORIGINS: \"Pochodzenie obcych\"\n  STR_THE_ULTIMATE_THREAT: \"Ostateczne zagrożenie\"\n  STR_TLETH_ALIEN_CITY: \"T'leth - miasto obcych\"\n  STR_UFOPAEDIA: \"USOpedia\"\n  STR_XCOM_CRAFT_ARMAMENT: \"ŁODZIE X-COMU I ICH UZBROJENIE\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"PODWODNE SYSTEMY BRONI\"\n  STR_WEAPONS_AND_EQUIPMENT: \"OGÓLNE WYPOSAŻENIE\"\n  STR_ALIEN_ARTIFACTS: \"ARTEFAKTY WODNE\"\n  STR_BASE_FACILITIES: \"INSTALACJE ORGANIZACJI X-COM\"\n  STR_ALIEN_LIFE_FORMS: \"STWORZENIA OBCYCH\"\n  STR_ALIEN_RESEARCH_UC: \"TECHNOLOGIA OBCYCH\"\n  STR_UFO_COMPONENTS: \"NOWE TECHNOLOGIE PODWODNE\"\n  STR_UFOS: \"RODZAJE USO\"\n  STR_SELECT_ITEM: \"WYBIERZ POZYCJĘ\"\n  STR_ACCELERATION: \"PRZYŚPIESZENIE>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"ILOŚĆ PALIWA>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"MOCOWAŃ NA BROŃ>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"WYTRZYMAŁOŚĆ>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"ŁADOWNOŚĆ>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"MAKS. LICZBA PSB-ów>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Siła rażenia\"\n  STR_RANGE: \"Zasięg\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Celność\"\n  STR_RE_LOAD_TIME: \"Czas przeładowania\"\n  STR_SECONDS: \"{0} sek.\"\n  STR_DAMAGE_ARMOR_PIERCING: \"PRZEBIJAJĄCE\"\n  STR_DAMAGE_INCENDIARY: \"FOSFOROWE\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"WYBUCHOWE\"\n  STR_DAMAGE_LASER_BEAM: \"WIĄZKA GAUSSA\"\n  STR_DAMAGE_PLASMA_BEAM: \"WIĄZKA DŹWIĘKOWA\"\n  STR_DAMAGE_STUN: \"ZAMRAŻAJĄCE\"\n  STR_DAMAGE_MELEE: \"WALKA WRĘCZ\"\n  STR_DAMAGE_ACID: \"KWAS\"\n  STR_DAMAGE_SMOKE: \"DYMNE\"\n  STR_SHOT_TYPE: \"TYP\"\n  STR_ACCURACY_UC: \"CELNOŚĆ\"\n  STR_TIME_UNIT_COST: \"KOSZT JC\"\n  STR_DAMAGE_UC: \"OBRAŻENIA\"\n  STR_AMMO: \"AMUNICJA\"\n  STR_SHOT_TYPE_AUTO: \"Ciągły\"\n  STR_SHOT_TYPE_SNAP: \"Szybki\"\n  STR_SHOT_TYPE_AIMED: \"Celowany\"\n  STR_CONSTRUCTION_TIME: \"Czas budowy\"\n  STR_CONSTRUCTION_COST: \"Koszt budowy\"\n  STR_MAINTENANCE_COST: \"Koszt utrzymania\"\n  STR_LOW: \"Niski\"\n  STR_MEDIUM: \"Średnie\"\n  STR_HIGH: \"Wysoki\"\n  STR_CRAFT_WEAPON: \"Broń łodzi\"\n  STR_CRAFT_AMMUNITION: \"Amunicja łodzi\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"System ciężkiej broni\"\n  STR_WEAPON: \"Broń\"\n  STR_AMMUNITION: \"Amunicja\"\n  STR_EQUIPMENT: \"Wyposażenie \"\n  STR_ALIEN_CORPSE: \"Zwłoki obcego\"\n  STR_UFO_COMPONENT: \"Komponent USO\"\n  STR_PERSONAL_ARMOR: \"Pancerz osobisty\"\n  STR_RAW_MATERIALS: \"Surowce\"\n  STR_HWP_SOLID_HARPOON_BOLTS: \"Bełty harpunowe\"\n  STR_ALIEN: \"Obcy\"\n  STR_AQUATOID: \"Akwatoid\"\n  STR_GILLMAN: \"Skrzelak\"\n  STR_LOBSTERMAN: \"Homaroid\"\n  STR_TASOTH: \"Tasot\"\n  STR_CALCINITE: \"Kalcynit\"\n  STR_DEEP_ONE: \"Głębion\"\n  STR_BIODRONE: \"Biodron\"\n  STR_TENTACULAT: \"Mackonóg\"\n  STR_TRISCENE: \"Tryskon\"\n  STR_HALLUCINOID: \"Halucynoid\"\n  STR_XARQUID: \"Ksarkuid\"\n  STR_ZOMBIE: \"Zombi\"\n  STR_LIVE_COMMANDER: \"Komandor\"\n  STR_LIVE_NAVIGATOR: \"Nawigator\"\n  STR_LIVE_MEDIC: \"Medyk\"\n  STR_LIVE_TECHNICIAN: \"Technik\"\n  STR_LIVE_SQUAD_LEADER: \"Dowódca drużyny\"\n  STR_LIVE_SOLDIER: \"Żołnierz\"\n  STR_LIVE_TERRORIST: \"Terrorysta\"\n  STR_AQUATOID_COMMANDER: \"Akwatoid komandor\"\n  STR_AQUATOID_NAVIGATOR: \"Akwatoid nawigator\"\n  STR_AQUATOID_MEDIC: \"Akwatoid medyk\"\n  STR_AQUATOID_TECHNICIAN: \"Akwatoid technik\"\n  STR_AQUATOID_SQUAD_LEADER: \"Akwatoid dowódca drużyny\"\n  STR_AQUATOID_SOLDIER: \"Akwatoid żołnierz\"\n  STR_GILLMAN_COMMANDER: \"Skrzelak komandor\"\n  STR_GILLMAN_TECHNICIAN: \"Skrzelak technik\"\n  STR_GILLMAN_SQUAD_LEADER: \"Skrzelak dowódca drużyny\"\n  STR_GILLMAN_SOLDIER: \"Skrzelak żołnierz\"\n  STR_LOBSTERMAN_COMMANDER: \"Homaroid komandor\"\n  STR_LOBSTERMAN_NAVIGATOR: \"Homaroid nawigator\"\n  STR_LOBSTERMAN_TECHNICIAN: \"Homaroid technik\"\n  STR_LOBSTERMAN_SQUAD_LEADER: \"Homaroid dowódca drużyny\"\n  STR_LOBSTERMAN_SOLDIER: \"Homaroid żołnierz\"\n  STR_TASOTH_SQUAD_LEADER: \"Tasoth dowódca drużyny\"\n  STR_TASOTH_SOLDIER: \"Tasoth żołnierz\"\n  STR_CALCINITE_TERRORIST: \"Kalcynit Terrorysta\"\n  STR_DEEP_ONE_TERRORIST: \"Głębion terrorysta\"\n  STR_BIODRONE_TERRORIST: \"Biodron terrorysta\"\n  STR_TENTACULAT_TERRORIST: \"Mackonóg terrorysta\"\n  STR_TRISCENE_TERRORIST: \"Tryskon terrorysta\"\n  STR_HALLUCINOID_TERRORIST: \"Halucynoid terrorysta\"\n  STR_XARQUID_TERRORIST: \"Ksarkuid terrorysta\"\n  STR_ION_BEAM_ACCELERATORS: \"Akceleratory wiązek jonowych\"\n  STR_MAGNETIC_NAVIGATION: \"Nawigacja magnetyczna\"\n  STR_ALIEN_SUB_CONSTRUCTION: \"Konstrukcja łodzi obcych\"\n  STR_ALIEN_CRYOGENICS: \"Kriogenika obcych\"\n  STR_ALIEN_CLONING: \"Maszyna klonująca obcych\"\n  STR_ALIEN_LEARNING_ARRAYS: \"Macierze uczące obcych\"\n  STR_ALIEN_IMPLANTER: \"Implatator obcych\"\n  STR_EXAMINATION_ROOM: \"Sala badawcza\"\n  STR_AQUA_PLASTICS: \"Akwaplastyk\"\n  STR_ALIEN_REANIMATION_ZONE: \"Strefa ożywiania obcych\"\n  STR_PLASTIC_AQUA_ARMOR: \"Pancerz z akwaplastyku\"\n  STR_ION_ARMOR: \"Pancerz jonowy\"\n  STR_MAGNETIC_ION_ARMOR: \"Magnetyczny pancerz jonowy\"\n  STR_HWP_AQUA_JET_MISSILES: \"Torpedy akwadżetowe\"\n  STR_HWP_DISPLACER_PWT: \"Torpeda impulsowa\"\n  STR_GAUSS_TECH: \"Technologia Gaussa\"\n  STR_NEW_FIGHTER_FLYING_SUB: \"Nowa latająca łódź przechwytująca\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Nowy Myśliwco-Transporter\"\n  STR_THE_LATEST_FLYING_SUB: \"Najnowsza Latająca Łódź\"\n  STR_ARMOR_PIERCING: \"PRZECIWPANCERNA\"\n  STR_COELACANTH_GAS_CANNON: \"Latimeria/Działko gazowe\"\n  STR_COELACANTH_AQUA_JET: \"Latimeria/Akwadżet\"\n  STR_COELACANTH_GAUSS: \"Latimeria/Gauss\"\n  STR_DISPLACER_SONIC: \"Dyslokator/Dźwięk\"\n  STR_DISPLACER_PWT: \"Dyslokator/Torpeda impulsowa\"\n  STR_AJAX_LAUNCHER: \"Wyrzutnia Ajaks\"\n  STR_DUP_HEAD_LAUNCHER: \"Wyrzutnia głowic z K.Z.U.\"\n  STR_CRAFT_GAS_CANNON: \"Pokładowe działo gazowe\"\n  STR_PWT_CANNON: \"Impulsowe działko torpedowe\"\n  STR_GAUSS_CANNON: \"Działko Gaussa\"\n  STR_GAUSS_CANNON_AMMO: \"Amunicja do działka Gaussa\"\n  STR_SONIC_OSCILLATOR: \"Oscylator dźwiękowy\"\n  STR_AJAX_TORPEDOES: \"Torpedy Ajaks\"\n  STR_DUP_HEAD_TORPEDOES: \"Torpedy z głowicą z K.Z.U\"\n  STR_CRAFT_GAS_CANNON_ROUNDS_X50: \"Naboje gazowe (x50)\"\n  STR_SONIC_WAVE: \"Fala dźwiękowa\"\n  STR_PULSE_WAVE_TORPEDOES: \"Amunicja impulsowego działka torpedowego\"\n  STR_SOLDIER: \"Akwanauta\"\n  STR_SCIENTIST: \"Naukowiec\"\n  STR_ENGINEER: \"Technik\"\n  STR_NORTH_ATLANTIC: \"Atlantyk Płn.\"\n  STR_SOUTH_ATLANTIC: \"Atlantyk Płd.\"\n  STR_NORTH_PACIFIC: \"Pacyfik Płn.\"\n  STR_SOUTH_PACIFIC: \"Pacyfik Płd.\"\n  STR_MEDITERRANEAN: \"Morze Śródziemne\"\n  STR_SOUTH_CHINA_SEA: \"Morze Południowochińskie\"\n  STR_INDIAN_OCEAN: \"Ocean Indyjski\"\n  STR_THE_EAST_SEA: \"Morze Japońskie\"\n  STR_NORTH_SEA: \"Morze Północne\"\n  STR_CARRIBEAN: \"Karaiby\"\n  STR_ANTARCTIC: \"Antarktyka\"\n  STR_ARCTIC: \"Arktyka\"\n  STR_EURASIA: \"Eurazja\"\n  STR_NORTH_AMERICA: \"Ameryka Płn.\"\n  STR_AFRICA: \"Afryka\"\n  STR_MAXIMUM_SPEED: \"Prędkość maksymalna\"\n  STR_TRANSMISSION_RESOLVER_UC: \"DEKODER TRANSMISJI\"\n  STR_TRITON: \"TRYTON\"\n  STR_HAMMERHEAD: \"GŁOWOMŁOT\"\n  STR_LEVIATHAN: \"LEWIATAN\"\n  STR_BARRACUDA: \"BARAKUDA\"\n  STR_MANTA: \"MANTA\"\n  STR_UFO: \"USO\"\n  STR_AJAX: \"AJAKS\"\n  STR_DUP_HEAD: \"GŁOWICA Z K.Z.U\"\n  STR_CRAFT_GAS_CANNON_UC: \"POKŁAD. DZIAŁO GAZOWE\"\n  STR_PWT_CANNON_UC: \"IMP. DZIAŁKO TORP.\"\n  STR_GAUSS_CANNON_UC: \"DZIAŁO GAUSSA\"\n  STR_SONIC_OSCILLATOR_UC: \"OSCYLATOR DŹWIĘKOWY\"\n  STR_DAMAGE_CAPACITY: \"Wytrzymałość\"\n  STR_WEAPON_POWER: \"Siła rażenia broni\"\n  STR_WEAPON_RANGE: \"Zasięg broni\"\n  STR_AIR_LOCK: \"Śluza\"\n  STR_LABORATORY: \"Laboratorium\"\n  STR_WORKSHOP: \"Warsztat\"\n  STR_STANDARD_SONAR: \"Standardowy sonar\"\n  STR_WIDE_ARRAY_SONAR: \"Sonar szerokopasmowy\"\n  STR_TORPEDO_DEFENSES: \"Obrona torpedowa\"\n  STR_GENERAL_STORES: \"Magazyny\"\n  STR_ALIEN_CONTAINMENT: \"Cele dla obcych\"\n  STR_GAUSS_DEFENSES: \"Obrona Gaussa\"\n  STR_SONIC_DEFENSES: \"Obrona dźwiękowa\"\n  STR_PWT_DEFENSES: \"Impulsowa obrona torpedowa\"\n  STR_BOMBARDMENT_SHIELD: \"Osłona przeciwbombowa\"\n  STR_MC_GENERATOR: \"Generator K.M.\"\n  STR_MC_LAB: \"Laboratorium K.M.\"\n  STR_TRANSMISSION_RESOLVER: \"Dekoder transmisji\"\n  STR_SUB_PEN: \"Doki\"\n  STR_USA: \"STANY ZJED.\"\n  STR_ALASKA: \"ALASKA\"\n  STR_EU_SYNDICATE: \"EUROSYNDYKAT\"\n  STR_ARABIAN_BLOC: \"BLOK ARABSKI\"\n  STR_EGYPTIAN_CARTEL: \"KARTEL EGIPSKI\"\n  STR_AFRICA_CORP: \"KORPORACJA AFRYKI\"\n  STR_BRAZILIAN_UNION: \"UNIA BRAZYLIJSKA\"\n  STR_NEW_MEXICO: \"NOWY MEKSYK\"\n  STR_ASIAN_COALITION: \"KOALICJA AZJATYCKA\"\n  STR_SCANDINAVIA: \"SKANDYNAWIA\"\n  STR_NEO_JAPAN: \"NEO-JAPONIA\"\n  STR_FREE_CHINA: \"WOLNE CHINY\"\n  STR_AUSTRALASIA: \"AUSTRALAZJA\"\n  STR_FED_KOREA: \"FEDERACJA KOREI\"\n  STR_EURASIA_UC: \"EURAZJA\"\n  STR_ICELANDIC_UNION: \"UNIA ISLANDZKA\"\n  STR_TANK: \"System broni podwodnej\"\n  STR_CIVILIAN: \"Cywil\"\n  STR_JAN: \"Sty\"\n  STR_FEB: \"Lut\"\n  STR_MAR: \"Mar\"\n  STR_APR: \"Kwi\"\n  STR_MAY: \"Maj\"\n  STR_JUN: \"Cze\"\n  STR_JUL: \"Lip\"\n  STR_AUG: \"Sie\"\n  STR_SEP: \"Wrz\"\n  STR_OCT: \"Paź\"\n  STR_NOV: \"Lis\"\n  STR_DEC: \"Gru\"\n  STR_INTERNATIONAL_RELATIONS: \"Stosunki międzynarodowe\"\n  STR_COUNTRY: \"Kraj\"\n  STR_FUNDING: \"Dotacje\"\n  STR_CHANGE: \"Zmiana\"\n  STR_WEAPON_SYSTEMS: \"SYSTEMY BRONI\"\n  STR_HWPS: \"PSB\"\n  STR_DAMAGE_UC_: \"USZKODZENIA>{ALT}{0}\"\n  STR_AIR_LOCK_UFOPEDIA: \"Śluza powietrzna pozwala wyposażeniu i personelowi przenosić się wewnątrz lub na zewnątrz podwodnej bazy. Jest to zawsze pierwsze pomieszczenie które musi być zbudowane na nowym miejscu. Obszar śluzy powietrznej jest podatny na wtargnięcia ze strony każdej wrogiej siły.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Każde miejsce mieszkalne obsługuje do 50 osób personelu. Placówki są raczej proste i funkcjonalne.\"\n  STR_LABORATORY_UFOPEDIA: \"Pięćdziesięciu naukowców może pracować w pojedynczym bloku laboratorium. Laboratoria są wyposażone w najnowszą technologię do badań nad materiałami, biochemią i bronią. X-Com ma dostęp do wszystkich najlepszych laboratoriów badawczych na świecie, zarówno cywilnych jak i wojskowych.\"\n  STR_WORKSHOP_UFOPEDIA: \"Warsztat zawiera każde niezbędne wyposażenie by produkować wyposażenie oparte na najnowszych projektach z laboratoriów naukowych. 50 Techników może zajmować jeden warsztat, przedmioty w budowie także zajmują miejsce.\"\n  STR_STANDARD_SONAR_UFOPEDIA: \"Standardowy system sonaru dla większości głębokości ma zasięg skuteczny ponad 450 kilometrów a w celu analizy powierzchni jest podłączony do siatki satelit geostacjonarnych. Każdy skaner ma 10% szansy wykrycia statku podwodnego lub powietrznego w 30 minutowym cyklu skanowania.\"\n  STR_WIDE_ARRAY_SONAR_UFOPEDIA: \"Sonar szerokopasmowy dla większości głębokości ma zasięg skuteczny ponad 700 kilometrów a w celu analizy powierzchni jest podłączony do siatki satelit geostacjonarnych. Każdy skaner ma 20% szansy wykrycia statku podwodnego lub powietrznego w 30 minutowym cyklu skanowania.\"\n  STR_TORPEDO_DEFENSES_UFOPEDIA: \"Torpedowy system obronny zapewnia ochronę przeciwko atakom wrogich statków podwodnych, które próbują zadokować w bazie.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"Każde wyposażenie, uzbrojenie, amunicja, odzyskiwane materiały i podwodne systemy broni są umieszczane w magazynach, włączając w to wyposażenie przypisane do statków w dokach.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"Aby móc przetrzymywać żywych obcych, wymagane są specjalne instalacje. Jednostki te podtrzymują ich systemy życiowe i ograniczają ich potencjał bojowy do zera. Placówka przechowująca może trzymać w zamknięciu 10 obcych form życia.\"\n  STR_GAUSS_DEFENSES_UFOPEDIA: \"Obrona Gaussa zapewnia najnowocześniejszą i najbardziej efektywną ochronę przed atakami wrogich łodzi podwodnych.\"\n  STR_SONIC_DEFENSES_UFOPEDIA: \"Oscylator dźwiękowy zapewnia potężną i efektywną obronę przeciwko agresorom.\"\n  STR_PWT_DEFENSES_UFOPEDIA: \"Torpedy Impulsowe zapewniają najbardziej efektywną obronę przed atakami Obcych. Rakiety te posiadają gęstą głowicę bojową, która potrafi przebić każdy znany pancerz. Fale magnetyczne produkowane przez torpedę wyłączają elektroniczne systemy obrony.\"\n  STR_BOMBARDMENT_SHIELD_UFOPEDIA: \"Ciśnieniowa osłona przeciwbombowa chroni bazę przed dokowaniem obcych łodzi podwodnych i emituje pole rezonansowe, które odpycha atakujące łodzie na dystans umożliwiający strzelanie z systemów obronnych. W efekcie podwaja to efektywność każdego zainstalowanego systemu obrony.\"\n  STR_MC_GENERATOR_UFOPEDIA: \"Odkąd łodzie Obcych aby wykryć obecność żywych istot używają Technologii Kontroli Molekularnej, użycie ujemnego emitera K.M. zasłoni bazę nieprzeniknioną osłoną mylącą Obcych i ukrywającą naszą obecność.\"\n  STR_MC_LAB_UFOPEDIA: \"Laboratorium Kontroli Molekularnej pozwoli wszczepiać i trenować do dziesięciu akwanautów w tym samym czasie. Implanty są chirurgicznie instalowane w czaszkach akwanautów. Kompleksowy trening pozwoli im używać swoich implantów. Zdolności implantu są używane w połączeniu z Urządzeniem Molekularnym i mogą być użyte jako ataki podczas walki.\"\n  STR_TRANSMISSION_RESOLVER_UFOPEDIA: \"Komunikacja obcych używa sieci implantów kontroli molekularnej, którą zbudowali obcy. Dekoder transmisji przechwytuje komunikaty łodzi obcych i odszyfrowuje informacje. Pozwala to określić typ statku obcych, rasę obcych i rodzaj działań, które właśnie są podejmowane.\"\n  STR_SUB_PEN_UFOPEDIA: \"Każdy dok może pomieścić jeden statek. Są to instalacje do obsługi, tankowania i naprawy floty statków X-Comu. Każda latająca łódź stacjonująca w bazie musi mieć przypisany wolny dok, który nie może być używany przez inną łódź, nawet jeżeli przypisana łódź jest na misji.\"\n  STR_DART_PISTOL_UFOPEDIA: \"Pistolet rzutkowy X-Comu jest małą, celną jednostką dużej mocy z magazynkiem na 12 drążonych rzutek. Rzutki są odpalane przy pomocy kartridża z gazem z zasobnika amunicji.\"\n  STR_JET_HARPOON_UFOPEDIA: \"Ten podwodny karabin jest celną i potężną bronią, strzelającą drążonymi stalowymi harpunami z 10-pociskowych magazynków. Każdy harpun ma własny zbiornik gazu.\"\n  STR_GAS_CANNON_UFOPEDIA: \"Waga ciężka rodziny technologii gazowej, działo te wystrzeliwuje lite bełty, niektóre z Wybuchowymi lub fosforowymi grotami. Ulubiona broń pośród doświadczonych akwanautów.\"\n  STR_HYDRO_JET_CANNON_UFOPEDIA: \"Działka hydroodrzutowe to system broni ciężkiej piechoty. Działko to strzela minitorpedami o napędzie magnezowym. Choć potężne, działko hydroodrzutowe jest topornym i nieporęcznym urządzeniem, odpowiednim tylko do użycia w wodzie.\"\n  STR_TORPEDO_LAUNCHER_UFOPEDIA: \"Prawdziwa waga ciężka, ta duża wyrzutnia wystrzeliwuje trzy typy torped, każdy ze swoim własną jednostką napędową. Niszczycielska broń, tylko z ręcznym ładowaniem będącym jej wadą. Dostępne typy amunicji włączają duże lub małe torpedy zakończone materiałami wybuchowymi lub fosforem, wszystkie tylko do użytku podwodnego.\"\n  STR_GAUSS_PISTOL_UFOPEDIA: \"Pistolet Gaussa używa technologi przyśpieszonych cząstek, nowy postęp w nowoczesnym uzbrojeniu. Jest szybki, celny i działa nad i pod wodą. Technologia Gaussa jest rozwinięciem technologi Plazmowej poznanej w poprzedniej wojnie.\"\n  STR_GAUSS_PISTOL_CLIP_UFOPEDIA: \"Pistolet Gaussa używa technologi przyśpieszonych cząstek, nowy postęp w nowoczesnym uzbrojeniu. Jest szybki, celny i działa nad i pod wodą. Technologia Gaussa jest rozwinięciem technologi Plazmowej poznanej z poprzedniej wojny.\"\n  STR_GAUSS_RIFLE_UFOPEDIA: \"Krok w przód od pistoletu Gaussa, karabin dający prawdziwego kopa swoimi podwójnymi akceleratorami cząstek. Zastępując Plazmowy system zasilany Elerium użyliśmy akceleratora mikro cząstek, które generują wiązkę anty-protonów.\"\n  STR_GAUSS_RIFLE_CLIP_UFOPEDIA: \"Krok w przód od pistoletu Gaussa, karabin dający prawdziwego kopa, ze swoimi podwójnymi akceleratorami cząstek. Zastępując Plazmowy system zasilany Elerium użyliśmy akcelerator mikro cząstek, które generują wiązkę anty-protonów.\"\n  STR_HEAVY_GAUSS_UFOPEDIA: \"Ciężki Gauss jest nieporęczny, ale ekstremalnie efektywny. Działa z 3 akceleratorami cząstek i praktycznie jest nie do zatrzymania. Wiązka anty-protonów jest zamknięta w środku skorupy z Arsenku Galu, która imploduje przy zderzeniu uwalniając antymaterię.\"\n  STR_HEAVY_GAUSS_CLIP_UFOPEDIA: \"Ciężki Gauss jest nieporęczny, ale ekstremalnie efektywny. Działa z 3 akceleratorami cząstek i praktycznie jest nie do zatrzymania. Wiązka anty-protonów jest ograniczona w środku skorupy z Arsenku Galu, która imploduje przy zderzeniu uwalniając antymaterię.\"\n  STR_MAGNA_BLAST_GRENADE_UFOPEDIA: \"Ten granaty normalnego przeznaczenia ma dokładny i skomplikowany zegar dla precyzyjnego sterowania.\"\n  STR_DYE_GRENADE_UFOPEDIA: \"Granaty barwiące mają podwójną rolę, użyteczne by zapewnić osłonę w sytuacjach ekspozycji. Działając zarówno w środowisku wodnym i lądowym, barwnik, jest wyrzucany jako chmura cząstek, tworzący w wodzie podobny do ośmiornicy rozprysk atramentu lub na lądzie gęstą lotną chmurę.\"\n  STR_PARTICLE_DISTURBANCE_GRENADE_UFOPEDIA: \"Granat zbliżeniowy, który może być rzucony jak zwykły granat ale gdy już został rozmieszczony jest uruchamiany bliskimi ruchami. Aby używać tych urządzeń poprawnie wymagane są umiejętności i trening.\"\n  STR_MAGNA_PACK_EXPLOSIVE_UFOPEDIA: \"Te ładunki wybuchowe powinny być używane tylko do wyburzania. Jednakże dawne doświadczenie pokazało, że te potężne ładunki wybuchowe są idealną bronią by wykurzyć Obcych. Promień rażenia jest duży, więc upewnij się, że żadni akwanauci nie są w minimalnej bezpiecznej odległości.\"\n  STR_PARTICLE_DISTURBANCE_SENSOR_UFOPEDIA: \"To nowe urządzenie używa różnorodnych detektorów i zaawansowanego systemu komputerowego, aby zidentyfikować poruszające się wrogie jednostki. Kliknij na ikonie czujnika zaburzeń cząstek na wyświetlaczu taktycznym. Z menu wybierz 'Użyj czujnika zaburzeń'. W centrum wyświetlacza sensor pokaże strzałkę, która wskazuje orientację akwanauty (północ jest na górze). Kropki pokazują jednostki, które niedawno się poruszały. Duże lub szybko poruszające się jednostki utworzą większe plamy. Nieruchome jednostki nie pojawią się.\"\n  STR_MEDI_KIT_UFOPEDIA: \"Aby tego użyć, stań naprzeciw rannego agenta X-Comu lub nad ciałem ogłuszonego akwanauty.{NEWLINE}LECZENIE> Czerwony oznacza rany. Wybierz część ciała i kliknij przycisk 'Lecz'. Zostanie wyleczona jedna śmiertelna rana oraz przywrócone zdrowie.{NEWLINE}STYMULANT> Przywraca energię i cuci ogłuszonych akwanautów. Aby ocucić nieprzytomnego akwanautę, musisz stanąć bezpośrednio nad ciałem.{NEWLINE}ŚRODKI PRZECIWBÓLOWE> Przywracają morale rannego akwanauty.\"\n  STR_MC_DISRUPTOR_UFOPEDIA: \"Ostateczna technologia K.M. Może być użyta tylko przez akwanautów z umiejętnościami K.M. Kliknij na zakłócaczu, wybierz typ ataku i kursorem wybierz cel. Są dwa typy ataku zakłócacza:{NEWLINE}ZAKŁÓĆ IMPLANT> Jeżeli się powiedzie, jednostka staje się zdezorientowana i może spanikować.{NEWLINE}KONTROLUJ IMPLANT> Jeżeli się powiedzie, zyskasz kontrolę nad wrogą jednostką.\"\n  STR_THERMAL_TAZER_UFOPEDIA: \"To urządzenie może być użyte tylko w walce wręcz, ale poprzez zamrożenie istoty ogłuszy żyjący organizm bez zabijania go.\"\n  STR_VIBRO_BLADE_UFOPEDIA: \"Wibroostrze jest długą, ostrą klingą z tytanu, która wiruje z prędkością 6000 obr./min. Urządzenie to może rozłupać nawet najtwardszą zbroję do nurkowania. Źródło mocy jest wynalazkiem obcych, a nasze wcześniejsze próby odtworzenia tego przedmiotu przyniosły srogą porażkę, gdyż nasze ostrza obracały się zbyt wolno lub eksplodowały pod naciskiem.\"\n  STR_THERMIC_LANCE_UFOPEDIA: \"Lanca termiczna jest logicznym rozszerzeniem technologii wibroostrza. Ostrze obraca się z wysoką prędkością, a zrbitowe źródło zasilania przegrzewa je, by cięło pancerz jak ciepły nóż masło.\"\n  STR_HEAVY_THERMIC_LANCE_UFOPEDIA: \"Ciężka lanca termiczna jest mocniejszą wersją LT. Podwojone źródło ciepła i ekstremalnie wysoka prędkość obrotowa sprawiają, że ciężka lanca termiczna jest praktycznie nie do zatrzymania dla jakiegokolwiek materiału.\"\n  STR_SONIC_CANNON_UFOPEDIA: \"Działko dźwiękowe jest najmocniejsze z rodziny broni dźwiękowych. Posiada audiooscylator o większym zakresie i większą komorę rewerberacyjną niż blasta. Działko posiada również system detonacji pulsowej, który zmienia modulację fali ultradźwiękowej tak, by wytworzyć bardziej efektywny wstrząs dźwiękowy.\"\n  STR_CANNON_POWER_CLIP_UFOPEDIA: \"Kompaktowe urządzenie używane jako amunicja do działka dźwiękowego. Zawiera małe ilości zrbitu.\"\n  STR_SONIC_BLASTA_RIFLE_UFOPEDIA: \"Mocniejsze urządzenie dźwiękowe. Nawet wysokowęglowa stal nie jest odporna na tę broń. Aby zwiększyć jej moc, zastosowano bardzo kompaktowy emiter fal, wspomagany przez wzmacniacz superprzewodnikowy.\"\n  STR_BLASTA_POWER_CLIP_UFOPEDIA: \"Ten mały obiekt jest użyty jako źródło mocy karabinu dźwiękowego, potężnej broni obcych. Zawiera małe ilości zrbitu.\"\n  STR_SONIC_PISTOL_UFOPEDIA: \"Pistolety dźwiękowe są bronią obcych opartą na falach ultradźwiękowych, które w sekundę zamienią kości w galaretę. Fale ultradźwiękowe pracują poza zakresem ludzkiego słuchu.\"\n  STR_PISTOL_POWER_CLIP_UFOPEDIA: \"Źródło mocy dla kompaktowego pistoletu dźwiękowego obcych. Zawiera zrbit - wszechstronne źródło mocy obcych.\"\n  STR_DISRUPTOR_PULSE_LAUNCHER_UFOPEDIA: \"Jest to obca broń samonaprowadzająca do użytku wyłącznie podwodnego, strzelająca samonapędzającymi 'pociskami rozrywającymi'. Gdy klikniesz, by wystrzelić, broń pozwoli ci postawić 'punkty nawigacyjne' dla pocisku, by ten nimi podążał. Gdy już umieścisz wystarczająco dużo punktów nawigacyjnych, kliknij na ikonie odpalenia.\"\n  STR_DISRUPTOR_AMMO_UFOPEDIA: \"Urządzenie to jest pociskiem pulsowym do rozrywacza, wyposażonym w pokładowy system naprowadzania komputerowego. Wystrzeliwane jest z wyrzutni rozrywającej.\"\n  STR_THERMAL_SHOK_LAUNCHER_UFOPEDIA: \"Mała wyrzutnia termoszokowa, która strzela chemicznymi bombami zamrażającymi. Bardzo przydatna do chwytania żywych obcych.\"\n  STR_THERMAL_SHOK_BOMB_UFOPEDIA: \"Bomba termoszokowa jest używana do chwytania żywych ludzi, ale może być także użyta przeciwko większości ras obcych. Wystrzeliwana jest z wyrzutni termoszokowej.\"\n  STR_SONIC_PULSER_UFOPEDIA: \"Te urządzenie działa w ten sam sposób, jak standardowy granat - poza tym, że jest wiele razy silniejsze. Granat stosuje pojedynczy podmuch fali dźwiękowej, który jest emitowany w każdym kierunku jednocześnie.\"\n  STR_MC_READER_UFOPEDIA: \"Wewnątrz ciał obcych znaleźliśmy chirurgicznie wszczepione małe jednostki. Są to implanty kontrolne, zaprojektowane przez akwatoidów, by umożliwić im stały dopływ informacji z pola bitwy, nawet na dużych odległościach. Czytnik kontroli molekularnej jest obcym urządzeniem komunikacyjnym, który służy do pobierania informacji bezpośrednio z implantów K.M. Jednostki X-Comu mogą używać tych urządzeń podczas walki, by wyświetlić charakterystyki obcego. Wybierz opcję 'użyj'. Potem kliknij kursorem na obcym.\"\n  STR_SURVEY_SHIP: \"Statek rozpoznawczy\"\n  STR_ESCORT: \"Statek eskortowy\"\n  STR_CRUISER: \"Krążownik\"\n  STR_HEAVY_CRUISER: \"Ciężki krążownik\"\n  STR_HUNTER: \"Łowca\"\n  STR_BATTLESHIP: \"Pancernik\"\n  STR_DREADNOUGHT: \"Postrach\"\n  STR_FLEET_SUPPLY_CRUISER: \"Krążownik zaopatrzenia floty\"\n  MAP_SEABED: \"Dno morskie\"\n  MAP_PIPES: \"Placówka badawcza\"\n  MAP_PLANE: \"Rozbity samolot\"\n  MAP_ATLAN: \"Atlantyda\"\n  MAP_MU: \"Świątynia Majów\"\n  MAP_GAL: \"Zatopiony galeon\"\n  MAP_MSUNK: \"Zatopiony liniowiec\"\n  MAP_VOLC: \"Wulkaniczny\"\n  MAP_CORAL: \"Rafa koralowa\"\n  MAP_PORT: \"Port\"\n  MAP_ISLAND: \"Wyspa\"\n  MAP_CARGO: \"Statek towarowy\"\n  MAP_LINERT: \"Statek wycieczkowy P1\"\n  MAP_LINERB: \"Statek wycieczkowy P2\"\n  MAP_ALART: \"Artefakt P1\"\n  MAP_GRUNGE: \"Artefakt P2\"\n  MAP_ENTRY: \"Kolonia P1\"\n  MAP_A_BASE: \"Kolonia P2\"\n  MAP_ALSHIP: \"T'leth P1\"\n  MAP_LEVEL: \"T'leth P2\"\n  MAP_CRYPT: \"T'leth P3\"\n  MAP_XBASES: \"Baza X-Comu\"\n  STR_MIXED_CREW: \"Mieszana załoga\"\n  STR_MIXED_CREW_2: \"Mieszana załoga 2\"\n  STR_RATING: \"OCENA> {0}\"\n  STR_RATING_TERRIBLE: \"FATALNIE!\"\n  STR_RATING_POOR: \"SŁABO!\"\n  STR_RATING_OK: \"OK\"\n  STR_RATING_GOOD: \"DOBRZE!\"\n  STR_RATING_EXCELLENT: \"ZNAKOMICIE!\"\n  STR_SCORE: \"PUNKTY\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"MIESIĘCZNY RAPORT X-COMU\"\n  STR_MONTH: \"Miesiąc> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"Komitet organizacji finansujących jak dotąd jest generalnie zadowolony z twoich postępów.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"Komitet organizacji finansujących jak dotąd jest bardzo zadowolony z twojego wspaniałego postępu. Tak trzymaj.\"\n  STR_COUNCIL_IS_DISSATISFIED: \"Komitet organizacji finansujących jest niezadowolony z twojej wydajności. Zwiększ swoją efektywność w zajmowaniu się zagrożeniem Obcymi albo ryzykujesz zakończenie finansowego wsparcia X-Comu.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"Nie odniosłeś sukcesu w zajmowaniu się inwazją Obcych i komitet organizacji finansujących niestety zdecydował by zakończyć finansowanie X-Comu. Każda organizacja powinna radzić sobie z problemem, tak jak to uważa za stosowne. Możemy mieć tylko nadzieję, że możemy dojść do jakiegoś porozumienia z tymi starożytnymi siłami i że generalnie ludność będzie się godzić na wodnych odwiedzających.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} jest szczególnie zadowolony z twoich zdolności zajmowania się miejscowym zagrożeniem i zgodził się zwiększyć swoje finansowanie.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} są szczególnie szczęśliwi z twoich zdolności zajmowania się miejscowymi napadami Obcych i zgodzili się zwiększyć swoje finansowanie.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} i {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} jest nieszczęśliwy z twoich zdolności zajmowania się aktywnością Obcych na ich Morzach i zdecydował się zmniejszyć swoje zaangażowanie finansowe.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} są nieszczęśliwi z twoich zdolności zajmowania się aktywnością Obcych na ich Morzu i zdecydowali się zmniejszyć swoje zaangażowanie finansowe.\"\n  STR_KNOTS: \"{0} węzły\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"Kraj {0} podpisał porozumienie o współpracy z obcymi siłami i wycofał swoje finansowanie X-Comu.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"Kraje {0} podpisały porozumienie o współpracy z obcymi siłami i wycofały swoje finansowanie X-Comu.\"\n  STR_MONTHLY_RATING: \"Ocena miesięczna> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Zmiana funduszy> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"Organizacja finansująca jest niezadowolona z twojej pozycji finansowej. Musisz zmniejszyć swój dług poniżej 1 miliona dolarów lub X-Com zostanie zamknięty.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"ZDEKODOWANO TRANSMISJĘ CZĄSTECZKOWĄ\"\n  STR_CRAFT_TYPE: \"TYP STATKU\"\n  STR_RACE: \"RASA\"\n  STR_MISSION: \"MISJA\"\n  STR_ZONE: \"REGION\"\n  STR_ALLOCATE_RESEARCH: \"Wyznacz badania\"\n  STR_ALLOCATE_MANUFACTURE: \"Wyznacz produkcję\"\n  STR_AZORES: \"Azory\"\n  STR_REYKJAVIK: \"Reykjavik\"\n  STR_BERMUDA: \"Bermudy\"\n  STR_NEW_YORK: \"Nowy Jork\"\n  STR_BOSTON: \"Boston\"\n  STR_FORT_SEVERN: \"Fort Severn\"\n  STR_DAKAR: \"Dakar\"\n  STR_RECIFE: \"Recife\"\n  STR_ACCRA: \"Akra\"\n  STR_ASCENSION_ISLAND: \"Wyspa Wniebowstąpienia\"\n  STR_TRINIDADE_ISLAND: \"Trynidad\"\n  STR_FALKLAND_ISLAND: \"Falklandy\"\n  STR_CANARY_ISLANDS: \"Wyspy Kanaryjskie\"\n  STR_ANCHORAGE: \"Anchorage\"\n  STR_ST_LAWRENCE_ISLAND: \"Wyspa Świętego Wawrzyńca\"\n  STR_SAN_FRANCISCO: \"San Francisco\"\n  STR_MIDWAY_ISLAND: \"Wyspa Midway\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_TASMANIA: \"Tasmania\"\n  STR_HAWAII: \"Hawaje\"\n  STR_FIJI: \"Fiji\"\n  STR_TONGA: \"Tonga\"\n  STR_EASTER_ISLAND: \"Wyspy wielkanocne\"\n  STR_GALAPAGOS_ISLAND: \"Wyspy Galapagos\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_SOLOMON_ISLAND: \"Wyspy Salomona\"\n  STR_CRETE: \"Kreta\"\n  STR_LISBON: \"Lisbona\"\n  STR_PORT_SAID: \"Port Said\"\n  STR_MARSEILLES: \"Marsylia\"\n  STR_TRIPOLI: \"Tripoli\"\n  STR_MANILA: \"Manila\"\n  STR_HONG_KONG: \"Hong Kong\"\n  STR_SINGAPORE: \"Singapur\"\n  STR_BANGKOK: \"Bangkok\"\n  STR_DARWIN: \"Darwin\"\n  STR_BOMBAY: \"Bombaj\"\n  STR_SAYCHELLES_ISLAND: \"Seszele\"\n  STR_MALDIVE_ISLAND: \"Malediwy\"\n  STR_SRI_LANKA: \"Sri Lanka\"\n  STR_MAURITIUS: \"Mauritius\"\n  STR_TOKYO: \"Tokio\"\n  STR_SHANGHAI: \"Szanghaj\"\n  STR_VLADIVOSTOK: \"Władywostok\"\n  STR_LONDON: \"Londyn\"\n  STR_FAEROE_ISLAND: \"Wyspy Owcze\"\n  STR_ABERDEEN: \"Aberdeen\"\n  STR_OSLO: \"Oslo\"\n  STR_JAMAICA: \"Jamajka\"\n  STR_PANAMA: \"Panama\"\n  STR_MIAMI: \"Miami\"\n  STR_PSI_TRAINING: \"Trening K.M.\"\n  STR_PSIONIC_TRAINING: \"TRENING KONTROLI MOLEKULARNEJ\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Pozostała pojemność K.M.> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"Siła{NEWLINE}K.M.\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"Zdolność K.M.{NEWLINE}/Zmiana\"\n  STR_IN_TRAINING: \"W{NEWLINE}treningu?\"\n  STR_TARGETTED_BY: \"CEL NAMIERZONY PRZEZ:\"\n  STR_WEAPONS_CREW_HWPS: \"SYSTEMY BRONI/{NEWLINE}I. ZAŁOGI/PSB-ów\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"ma mało paliwa,{NEWLINE}wraca do bazy.\"\n  STR_SOLDIER_LIST: \"Lista akwanautów\"\n  STR_RANK_: \"RANGA> {ALT}{0}\"\n  STR_MISSIONS: \"MISJI> {ALT}{0}\"\n  STR_KILLS: \"ZABITYCH> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"CZAS KURACJI> {ALT}{0}\"\n  STR_TIME_UNITS: \"JEDNOSTKI CZASU\"\n  STR_STAMINA: \"WYTRZYMAŁOŚĆ\"\n  STR_HEALTH: \"ZDROWIE\"\n  STR_BRAVERY: \"ODWAGA\"\n  STR_REACTIONS: \"REFLEKS\"\n  STR_FIRING_ACCURACY: \"CELNOŚĆ STRZAŁU\"\n  STR_THROWING_ACCURACY: \"CELNOŚĆ RZUTU\"\n  STR_STRENGTH: \"SIŁA\"\n  STR_PSIONIC_STRENGTH: \"SIŁA KONTROLI MOLEKULARNEJ\"\n  STR_PSIONIC_SKILL: \"ZDOLNOŚĆ KONTROLI MOLEKULARNEJ\"\n  STR_NEW_RANK: \"NOWA RANGA\"\n  STR_PROMOTIONS: \"Awanse\"\n  STR_SOLDIERS_UC: \"AKWANAUCI\"\n  STR_COELACANTH_GAS_CANNON_UFOPEDIA: \"Zautomatyzowane PSB mają wysoką manewrowość i wytrzymały pancerz. Stanowią silne wsparcie dla piechoty na każdej głębokości. PSB są uzbrajane automatycznie, jeśli masz wystarczającą ilość amunicji.\"\n  STR_COELACANTH_AQUA_JET_UFOPEDIA: \"Ten pojazd jest uzbrojony w torpedy akwadżetowe. Ten system broni działa tylko pod wodą. Upewnij się, że w magazynach leżą wystarczające zapasy tych torped.\"\n  STR_COELACANTH_GAUSS_UFOPEDIA: \"Technologia Gaussa pozwala na potężną broń dla PSB. W porównaniu z poprzednimi modelami oferuje dużą siłę ognia i używa autorskiej technologii X-Comu.\"\n  STR_DISPLACER_SONIC_UFOPEDIA: \"Technologia obcych ponownie zdefiniowała PSB. Zdolność do użycia dyslokatora jonowego oznacza, że PSB nie są już ograniczone do działań na lądzie/dnie. Broń dźwiękowa daje prawdziwą przewagę w bitwie.\"\n  STR_DISPLACER_PWT_UFOPEDIA: \"Ten PSB umożliwia użycie broni impulsowych pod wodą. Musisz produkować torpedy impulsowe, aby go uzbroić. Aby wystrzelić, wskaż kilka punktów kontrolnych i kliknij na ikonę wystrzału. \"\n  STR_ALIEN_PROBE_MISSION: \"Misja sondująca obcych\"\n  STR_ALIEN_INTERDICTION: \"Zabezpieczenie obcych\"\n  STR_ALIEN_RESOURCE_RAID: \"Rajd obcych po zasoby\"\n  STR_ALIEN_INFILTRATION: \"Infiltracja obcych\"\n  STR_ALIEN_BASE: \"Rozbudowa kolonii obcych\"\n  STR_ALIEN_SURFACE_ATTACK: \"Atak naziemny obcych\"\n  STR_ALIEN_RETALIATION: \"Atak na podwodną bazę\"\n  STR_ALIEN_SUPPLY: \"Misja zaopatrzenia kolonii\"\n  STR_ALIEN_PROBE_MISSION_UFOPEDIA: \"Misja sondująca obcych służy korelowaniu danych o dnie morskim, zasobach, dostawach i trasach lotów samolotów w obszarze. Łodzie obcych zaangażowane w te misje same w sobie nie są głównym zagrożeniem, ale pokazują obszary aktywności, które w każdym momencie mogą się zaognić.\"\n  STR_ALIEN_INTERDICTION_UFOPEDIA: \"Obcy mają politykę pilnowania obszarów, które ich interesują, wysyłając statek z wyraźnym rozkazem ich zabezpieczenia, zanim zaczną się bardziej intensywne misje. Wyląduje on w określonym miejscu, które mają zamiar napaść później, by zamknąć obszar i przygotować drogę pod następny poziom aktywności.\"\n  STR_ALIEN_RESOURCE_RAID_UFOPEDIA: \"Zatapianie statków i zestrzeliwanie samolotów są kluczowymi elementami strategii obcych. Pozyskiwanie materiałów jest jedną z wiodących aktywności obcych i jako takie powiązane z tymi jawnymi aktami agresji. Obcy napadają także na obszary aktywności geotermalnej, kopalnie i starożytne ruiny dla minerałów, oczyszczonych metali czy innych wyprodukowanych przez ludzi rzeczy.\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"Może to prowadzić do oficjalnych kontaktów najwyższego stopnia pomiędzy obcymi a korporacjami lub rządami. Kulminacja tych czynności cechuje się intensyfikacją aktywności obcych łodzi na wodach danej organizacji. Obcy będą próbować podpisać porozumienie z rządami lub organizacjami, oferując poznanie ich zaawansowanych technologii. Ta aktywność obcych reprezentuje główne zagrożenie dla X-Comu. Jeżeli korporacja czy rząd współpracuje z najeźdźcami, przestaje nas finansować.\"\n  STR_ALIEN_BASE_UFOPEDIA: \"Obcy budują tajne podwodne kolonie w odległych, niezaludnionych miejscach. Po kilku początkowych lotach zwiadowczych aktywność obcych łodzi wzrośnie w miarę budowy kolonii kolonii. Wiemy, że kolonie te zawierają laboratoria, centra klonowania, placówki chirurgiczne do eksperymentów na ludziach i obcych. Obecność obcych kolonii wygeneruje więcej aktywności obcych bez obecności łodzi obcych. Aby mieć szansę na zlokalizowania kolonii, łodzie X-Comu muszą patrolować dany obszar przez kilka godzin.\"\n  STR_ALIEN_SURFACE_ATTACK_UFOPEDIA: \"Kiedy Obcy potrzebują ludzi, terroryzują port, atakują wyspę lub napadają na statek. By zaspokoić odrażające potrzeby hodowlane obcych i ich paskudne eksperymenty, cywile będą bezpośrednio narażeni na atak.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"Jeśli łodzie X-Comu będą szczególnie często zestrzeliwać obce jednostki, wtedy obcy mogą podjąć akcję odwetową. Wynikiem tego może być bezpośredni atak na bazę X-Comu. Jednak obcy muszą ją najpierw znaleźć, by móc zaatakować, więc jeśli patrolujące łodzie będą trzymane z dala od bazy, wówczas prawdopodobieństwo ataku będzie minimalne.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"Kiedy kolonia obcych zostanie zbudowana, jest ona regularnie zaopatrywana przez specjalne transportowce. Jeżeli wykryjemy jeden z tych pojazdów podczas lądowania, wtedy jest pewne, że kolonia obcych jest w pobliżu.\"\n  STR_SURVEY_SHIP_UFOPEDIA: \"Mała łódź podwodna, używana do rozpoznania i misji wywiadowczych. Normalnie poprzedza większe pojazdy, stanowiąc forpocztę obcych sił zadaniowych.\"\n  STR_ESCORT_UFOPEDIA: \"Średniego rozmiaru pojazd eskortowy, który stanowi niewielkie zagrożenie sam w sobie. Ten statek poprzedza przybycie większych pojazdów i zwiększoną aktywność.\"\n  STR_CRUISER_UFOPEDIA: \"Krążownik jest statkiem ogólnego przeznaczenia, filarem floty obcych, używanym we wszystkich typach misji obcych i niebezpiecznym przeciwnikiem.\"\n  STR_HEAVY_CRUISER_UFOPEDIA: \"Ciężki krążownik jest mocniejszym statkiem niż krążownik, a większe bronie i systemy napędowe zwiększają jego moc. Ciężki krążownik jest używany w misjach surowcowych do zbierania dużej ilości minerałów i wyposażenia.\"\n  STR_HUNTER_UFOPEDIA: \"Statek ten jest wyposażony w laboratorium do dokonywania eksperymentów i operacji chirurgicznych na ludziach. Ofiary są poddawane najstraszniejszym torturom, a mózg często jest wyjmowany i zabezpieczany do dalszego przetwarzania.\"\n  STR_BATTLESHIP_UFOPEDIA: \"Pancernik jest najbardziej agresywnym statkiem, jaki posiadają obcy. Dysponuje on wszystkimi technologiami i systemami obcych, by działać jako baza operacyjna dla każdego rodzaju aktu agresji, którego obcy chcieliby dokonać. Przewozi szeroki wachlarz broni.\"\n  STR_DREADNOUGHT_UFOPEDIA: \"Drednot jest supertransportowcem, w pełni wyposażonym w technologię Obcych oraz ogromną pojemność. Drednot jest trudnym i groźnym przeciwnikiem.\"\n  STR_FLEET_SUPPLY_CRUISER_UFOPEDIA: \"Zaopatrzeniowiec jest używany podczas budowania kolonii obcych lub do zaopatrywania istniejących. Przewozi pożywkę dla obcych, DNA, płody i inne komponenty biologiczne.\"\n  STR_DISMANTLE: \"Rozbierz\"\n  STR_FACILITY_IN_USE: \"KAPSUŁA W UŻYCIU\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"NIE MOŻNA ZDEMONTOWAĆ KAPSUŁY!{SMALLLINE}Wszysktie kapsuły bazy muszą być podłączone do śluzy powietrznej.\"\n  STR_TRANSFER_ITEMS_TO: \"Cel transferu: {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"BRAK MIEJSC DO PRZECHOWYWANIA W PUNKCIE TRANSPORTOWYM!{SMALLLINE}Żywi Obcy by przeżyć potrzebują wyposażenia do przechowywania Obcych.\"\n  STR_AMOUNT_AT_DESTINATION: \"ILOŚĆ W{NEWLINE}MIEJSCU DOCELOWYM\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"Obcy zmarł, ponieważ nie zbudowano cel dla obcych\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"BRAK WOLNYCH KWATER!{SMALLLINE}Baza przeznaczenia nie ma wystarczającej ilości miejsca w kwaterach mieszkalnych dla załogi przypisanej do łodzi.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"BRAK MIEJSCA DO PRZECHOWYWANIA!{SMALLLINE}Baza przeznaczenia nie ma wystarczającej ilości miejsca do przechowywania dla wyposażenia przypisanego do łodzi.\"\n  STR_ITEMS_ARRIVING: \"Dostarczone przedmioty\"\n  STR_DESTINATION_UC: \"CEL\"\n  STR_DART_PISTOL: \"Pistolet rzutkowy\"\n  STR_DART_POD: \"Magazynek z rzutkami\"\n  STR_JET_HARPOON: \"Miotacz harpunów\"\n  STR_HARPOON_POD: \"Magazynek z harpunami\"\n  STR_GAS_CANNON: \"Działko gazowe\"\n  STR_GC_AP_AMMO: \"Bełty przeciwpancerne DG\"\n  STR_GC_HE_AMMO: \"Bełty wybuchowe DG\"\n  STR_GC_P_AMMO: \"Bełty fosforowe DG\"\n  STR_HYDRO_JET_CANNON: \"Działko hydroodrzutowe\"\n  STR_HJC_AP_AMMO: \"Amunicja przeciwpancerna DHO\"\n  STR_HJC_HE_AMMO: \"Amunicja wybuchowa DHO\"\n  STR_HJC_P_AMMO: \"Amunicja zapalająca DHO\"\n  STR_TORPEDO_LAUNCHER: \"Wyrzutnia torped\"\n  STR_SMALL_TORPEDO: \"Torpeda mała\"\n  STR_LARGE_TORPEDO: \"Torpeda duża\"\n  STR_PHOSPHOROUS_TORPEDO: \"Torpeda fosforowa\"\n  STR_MAGNA_BLAST_GRENADE: \"Magnowy granat wybuchowy\"\n  STR_DYE_GRENADE: \"Granat barwiący\"\n  STR_PARTICLE_DISTURBANCE_GRENADE: \"Granat sensoryczny\"\n  STR_MAGNA_PACK_EXPLOSIVE: \"Magnowy ładunek wybuchowy\"\n  STR_PARTICLE_DISTURBANCE_SENSOR: \"Czujnik zaburzeń cząstek\"\n  STR_MEDI_KIT: \"Apteczka\"\n  STR_MC_DISRUPTOR: \"Zakłócacz K.M.\"\n  STR_THERMAL_TAZER: \"Taser termiczny\"\n  STR_GAUSS_PISTOL: \"Pistolet Gaussa\"\n  STR_GAUSS_PISTOL_CLIP: \"Magazynek pistoletu Gaussa\"\n  STR_GAUSS_RIFLE: \"Karabin Gaussa\"\n  STR_GAUSS_RIFLE_CLIP: \"Magazynek karabinu Gaussa\"\n  STR_HEAVY_GAUSS: \"Ręczne działko Gaussa\"\n  STR_HEAVY_GAUSS_CLIP: \"Magazynek ciężkiego Gaussa\"\n  STR_SONIC_CANNON: \"Działko dźwiękowe\"\n  STR_CANNON_POWER_CLIP: \"Bateria działka dźwiękowego\"\n  STR_SONIC_BLASTA_RIFLE: \"Karabin blasta-dźwiękowy\"\n  STR_BLASTA_POWER_CLIP: \"Bateria blasta\"\n  STR_SONIC_PISTOL: \"Pistolet dźwiękowy\"\n  STR_PISTOL_POWER_CLIP: \"Bateria pistoletu\"\n  STR_DISRUPTOR_PULSE_LAUNCHER: \"Wyrzutnia rozrywająca\"\n  STR_DISRUPTOR_AMMO: \"Amunicja rozrywająca\"\n  STR_THERMAL_SHOK_LAUNCHER: \"Wyrzutnia termoszokowa\"\n  STR_THERMAL_SHOK_BOMB: \"Bomba termoszokowa\"\n  STR_SONIC_PULSER: \"Pulser dźwiękowy\"\n  STR_ZRBITE: \"Zrbit\"\n  STR_MC_READER: \"Czytnik K.M.\"\n  STR_VIBRO_BLADE: \"Wibroostrze\"\n  STR_THERMIC_LANCE: \"Lanca termiczna\"\n  STR_HEAVY_THERMIC_LANCE: \"Ciężka lanca termiczna\"\n  STR_AQUATOID_CORPSE: \"Zwłoki akwatoida\"\n  STR_GILLMAN_CORPSE: \"Zwłoki skrzelaka\"\n  STR_LOBSTERMAN_CORPSE: \"Zwłoki homaroida\"\n  STR_TASOTH_CORPSE: \"Zwłoki tasota\"\n  STR_CALCINITE_CORPSE: \"Zwłoki kalcynita\"\n  STR_DEEP_ONE_CORPSE: \"Zwłoki głębiona\"\n  STR_BIODRONE_CORPSE: \"Zwłoki biodrona\"\n  STR_TENTACULAT_CORPSE: \"Zwłoki mackonoga\"\n  STR_TRISCENE_CORPSE: \"Zwłoki tryskona\"\n  STR_HALLUCINOID_CORPSE: \"Zwłoki halucynoida\"\n  STR_XARQUID_CORPSE: \"Zwłoki ksarkuida\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"Za mało amunicji by uzbroić PSB{SMALLLINE}Każdy PSB wymaga {0} {1}.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Za mało sprzętu, aby w pełni uzbroić oddział.\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Musisz zbadać{NEWLINE}{0}{NEWLINE}by móc produkować:{NEWLINE}{1}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"Obcy zniszczyli niechronioną bazę '{0}'\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"Twoi szpiedzy zlokalizowali kolonię obcych w morzu: {0}\"\n  STR_STANDOFF: \"ŚLEDZENIE\"\n  STR_CAUTIOUS_ATTACK: \"ATAK OSTROŻNY\"\n  STR_STANDARD_ATTACK: \"ATAK STANDARDOWY\"\n  STR_AGGRESSIVE_ATTACK: \"ATAK AGRESYWNY\"\n  STR_DISENGAGING: \"ZAWRACANIE\"\n  STR_UFO_HIT: \"USO TRAFIONE!\"\n  STR_UFO_CRASH_LANDS: \"USO ZATOPIONE!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Minimalizuj tylko podczas śledzenia\"\n  STR_UFO_RETURN_FIRE: \"USO ODPOWIADA OGNIEM!\"\n  STR_INTERCEPTOR_DAMAGED: \">>> ŁÓDŹ USZKODZONA <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> ŁÓDŹ ZNISZCZONA <<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"USO UCIEKA ŁODZI!\"\n  STR_LONG_RANGE_DETECTION: \"Szerokie pasmo wykrycia\"\n  STR_STORES_UC: \"MAGAZYNY\"\n  STR_DIFFICULTY_LEVEL: \"Poziom trudności\"\n  STR_INTERCEPT: \"PRZECHWYTYWANIE\"\n  STR_BASES: \"BAZY\"\n  STR_GRAPHS: \"WYKRESY\"\n  STR_UFOPAEDIA_UC: \"USOPEDIA\"\n  STR_OPTIONS_UC: \"OPCJE\"\n  STR_FUNDING_UC: \"BUDŻET\"\n  STR_5_SECONDS: \"5 sek.\"\n  STR_1_MINUTE: \"1 min.\"\n  STR_5_MINUTES: \"5 min.\"\n  STR_30_MINUTES: \"30 min.\"\n  STR_1_HOUR: \"1 godz.\"\n  STR_1_DAY: \"1 dzień\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"Lista działaczy organizacji X-Com\"\n  STR_ENTER_NAME: \"Wprowadź nazwę\"\n  STR_PERFORMANCE_RATING: \"Ocena działalności\"\n  STR_VICTORY_DATE: \"Dzień zwycięstwa\"\n  STR_CHEMICAL_FLARE: \"Flara chemiczna\"\n  STR_CHEMICAL_FLARE_UFOPEDIA: \"To małe urządzenie po rzuceniu na lądzie lub pod wodą zaczyna emitować bardzo jaskrawe światło. Podczas misji nocnych może to spowodować oświetlenie jednostek wroga będących w pobliżu flary chemicznej, przez co staną się widoczne.\"\n  STR_MONTHLY_COSTS: \"KOSZTY MIESIĘCZNE\"\n  STR_CRAFT_RENTAL: \"Dzierżawa łodzi\"\n  STR_SALARIES: \"Wynagrodzenia\"\n  STR_BASE_MAINTENANCE: \"Utrzymanie bazy\"\n  STR_COST_PER_UNIT: \"Koszt za sztukę\"\n  STR_QUANTITY: \"Ilość\"\n  STR_TOTAL: \"Razem\"\n  STR_IN_PSIONIC_TRAINING: \"Na szkoleniu K.M.\"\n  STR_FRONT_ARMOR: \"Pancerz przedni\"\n  STR_LEFT_ARMOR: \"Pancerz lewy\"\n  STR_RIGHT_ARMOR: \"Pancerz prawy\"\n  STR_REAR_ARMOR: \"Pancerz tylny\"\n  STR_UNDER_ARMOR: \"Pancerz dolny\"\n  STR_ROUNDS: \"STRZAŁÓW\"\n  STR_UNIT: \"JEDNOSTKA> {0}\"\n  STR_ENERGY: \"ENERGIA\"\n  STR_MORALE: \"MORALE\"\n  STR_ARMOR_: \"PANCERZ> {0}\"\n  STR_FRONT_ARMOR_UC: \"PANCERZ PRZEDNI\"\n  STR_LEFT_ARMOR_UC: \"PANCERZ LEWY\"\n  STR_RIGHT_ARMOR_UC: \"PANCERZ PRAWY\"\n  STR_REAR_ARMOR_UC: \"PANCERZ TYLNY\"\n  STR_SKILLS: \"ZDOLNOŚCI> {0}\"\n  STR_LEVEL: \"POZIOM> {0}\"\n  STR_HEAD: \"GŁOWA\"\n  STR_TORSO: \"TUŁÓW\"\n  STR_RIGHT_ARM: \"PRAWA RĘKA\"\n  STR_LEFT_ARM: \"LEWA RĘKA\"\n  STR_RIGHT_LEG: \"PRAWA NOGA\"\n  STR_LEFT_LEG: \"LEWA NOGA\"\n  STR_PAIN_KILLER: \"ZNIECZULENIE\"\n  STR_STIMULANT: \"STYMULACJA\"\n  STR_HEAL: \"LECZENIE\"\n  STR_TIME_UNITS_SHORT: \"JC>{ALT}{0}\"\n  STR_WEIGHT: \"Waga>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"Refl.>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"Zd. M.>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"Sił. M.>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Artefakt obcych\"\n  STR_AMMO_ROUNDS_LEFT: \"AMUNICJA:{NEWLINE}ZOSTAŁO{NEWLINE}NABOI: {ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Znie.>{ALT}{0}{ALT}{NEWLINE}Stym.>{ALT}{1}{ALT}{NEWLINE}Lecz.>{ALT}{2}\"\n  STR_THROW: \"Rzuć\"\n  STR_AUTO_SHOT: \"Strzał ciągły\"\n  STR_SNAP_SHOT: \"Strzał szybki\"\n  STR_AIMED_SHOT: \"Strzał celowany\"\n  STR_STUN: \"Ogłusz\"\n  STR_PRIME_GRENADE: \"Odbezpiecz granat\"\n  STR_USE_SCANNER: \"Użyj czujnika zaburzeń\"\n  STR_USE_MEDI_KIT: \"Użyj apteczki\"\n  STR_LAUNCH_MISSILE: \"Odpal torpedę\"\n  STR_ACCURACY_SHORT: \"Cel.> {ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Za mało Jednostek Czasu!\"\n  STR_NOT_ENOUGH_ENERGY: \"Za mało energii!\"\n  STR_NO_ROUNDS_LEFT: \"Brak naboi!\"\n  STR_NO_AMMUNITION_LOADED: \"Nie załadowano amunicji!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Niewłaściwa amunicja do tej broni!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"Broń jest już załadowana!\"\n  STR_NO_LINE_OF_FIRE: \"Brak linii strzału!\"\n  STR_GRENADE_IS_ACTIVATED: \"Granat odbezpieczony!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Granat zabezpieczony!\"\n  STR_THERE_IS_NO_ONE_THERE: \"Nie ma tam nikogo!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Musimy zbadać ten artefakt obcych, by móc go używać!\"\n  STR_OUT_OF_RANGE: \"Poza zasięgiem!\"\n  STR_UNABLE_TO_THROW_HERE: \"Nie można tutaj rzucić!\"\n  STR_SET_TIMER: \"Ustaw stoper na\"\n  STR_HIDDEN_MOVEMENT: \"RUCH UKRYTY\"\n  STR_TURN: \"TURA> {0}\"\n  STR_SIDE: \"STRONA> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Naciśnij dowolny klawisz, by kontynuować\"\n  STR_MIND_CONTROL: \"Użyj kontroli molekularnej\"\n  STR_PANIC_UNIT: \"Wywołaj panikę\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Morale obcego skutecznie obniżone\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Kontrola implantu pomyślna\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}wpadł w szał\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}wpadła w szał\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}spanikował\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}spanikowała\"\n  STR_XCOM: \"X-COM\"\n  STR_ALIENS: \"Obcy\"\n  STR_RIGHT_HAND: \"PRAWA DŁOŃ\"\n  STR_LEFT_HAND: \"LEWA DŁOŃ\"\n  STR_RIGHT_SHOULDER: \"PRAWE RAMIĘ\"\n  STR_LEFT_SHOULDER: \"LEWE RAMIĘ\"\n  STR_BACK_PACK: \"PLECAK\"\n  STR_BELT: \"PAS\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}jest pod kontrolą molekularną\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}jest pod kontrolą molekularną\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}stracił przytomność.\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}straciła przytomność.\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}zmarł od ran śmiertelnych\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}zmarła od ran śmiertelnych\"\n  STR_USE_MIND_PROBE: \"Użyj czytnika K.M.\"\n  STR_FATAL_WOUNDS: \"RANY ŚMIERTELNE\"\n  STR_UNDER_ARMOR_UC: \"PANCERZ DOLNY\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"JC zarezerwowano na strzał szybki\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"JC zarezerwowano na strzał ciągły\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"JC zarezerwowano na strzał mierzony\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"JC zarezerwowano na klęknięcie\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"JC zarezerwowano na klęknięcie i ostrzał\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} jednostka w łodzi org. X-COM\"\n    few: \"{N} jednostki w łodzi X-Com\"\n    many: \"{N} jednostek w łodzi X-Com\"\n    other: \"{N} jednostek w łodzi X-Com\"\n  STR_UNITS_OUTSIDE:\n    one: \"{N} jednostka pozostawiona na zewnątrz\"\n    few: \"{N} jednostki pozostawione na zewnątrz\"\n    many: \"{N} jednostki zostawione na zewnątrz\"\n    other: \"{N} jednostek pozostawionych na zewnątrz\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} jednostka stojąca we wejściu\"\n    few: \"{N} jednostek stojących we wejściu\"\n    many: \"{N} jednostki stojące we wejściu\"\n    other: \"{N} jednostki stojące we wejściu\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} jednostka w docelowym wyjściu\"\n    few: \"{N} jednostek w docelowym wyjściu\"\n    many: \"{N} jednostki w docelowym wyjściu\"\n    other: \"{N} jednostki w docelowym wyjściu\"\n  STR_ABORT_MISSION_QUESTION: \"Przerwać misję?\"\n  STR_CORPSE: \"Zwłoki\"\n  STR_UNLOAD_CRAFT: \"Rozładuj\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}został zabity\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}została zabita\"\n  STR_HIT_MELEE: \"Cios\"\n  STR_GROUND: \"NA ZIEMI\"\n  STR_LIVING_QUARTERS_PLURAL: \"Kwatery mieszkalne\"\n  STR_LIST_ITEM: \"PRZEDMIOT\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"Wszyscy obcy zginęli, więc{NEWLINE}pozostałości przejęto automatycznie\"\n  STR_RESET: \"Resetuj\"\n  STR_MEMORIAL: \"Tablica poległych\"\n  STR_DATE_UC: \"DATA\"\n  STR_SOLDIERS_RECRUITED_UC: \"ZATRUDNIENI AKWANAUCI>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"UTRACENI AKWANAUCI>{ALT}{0}\"\n  STR_REMOVE_SELECTED: \"Usuń zaznaczone\"\n  STR_LIVE_ALIENS: \"Żywe{NEWLINE}osobniki\"\n  STR_DEAD_ALIENS: \"Odrzucone{NEWLINE}osobniki\"\n  STR_UNDER_INTERROGATION: \"W{NEWLINE}badaniach\"\n  STR_CONTAINMENT_EXCEEDED: \"LIMIT CEL DLA OBCYCH PRZEKROCZONY!{SMALLLINE}Brak miejsca w celi w bazie {0}. Musisz usunąć z cel nadmiar obcych, gdyż następni będą umierać.\"\n  STR_MANAGE_CONTAINMENT: \"Zarządzanie celami dla obcych\"\n  STR_STORAGE_EXCEEDED: \"PRZESTRZEŃ MAGAZYNOWA PRZEPEŁNIONA!{SMALLLINE}Niewystarczająca ilość miejsca w magazynach {0}. Musisz sprzedać nadwyżkę stanu magazynowego.\"\n  STR_GO_TO_BASE: \"Przejdź do bazy\"\n  STR_MELEE_ACCURACY: \"WALKA WRĘCZ\"\n  STR_SELL_PRODUCTION: \"SPRZEDAJ\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Obie dłonie muszą być wolne!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Za mało przedmiotów, aby skopiować szablon!\"\n  STR_UNLOAD_WEAPON: \"Rozładuj broń\"\n  STR_ALL_ITEMS: \"Wszystkie przedmioty\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"NIE MOŻNA MIEĆ WIĘCEJ WYPOSAŻENIA NA POKŁADZIE!{SMALLLINE}W tej łodzi możesz zabrać maksymalnie {N} przedmiot.\"\n    few: \"NIE MOŻNA MIEĆ WIĘCEJ WYPOSAŻENIA NA POKŁADZIE!{SMALLLINE}W tej łodzi możesz zabrać maksymalnie {N} przedmiotów.\"\n    many: \"NIE MOŻNA MIEĆ WIĘCEJ WYPOSAŻENIA NA POKŁADZIE!{SMALLLINE}W tej łodzi możesz zabrać maksymalnie {N} przedmiotów.\"\n    other: \"BRAK MIEJSCA NA WYPOSAŻENIE NA POKŁADZIE!{SMALLLINE}W tej łodzi możesz zabrać maksymalnie {N} przedmiotów.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}CENTRUM KONTROLI ZNISZCZONE{NEWLINE}Skieruj wszystkich akwanautów do wyjścia i kliknij przycisk 'Przerwij misję'.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"Bazy morskie X-Comu nie mogą być budowane na lądzie\"\n  STR_UNABLE_TO_ENGAGE_DEPTH: \"NIE MOŻNA ZAATAKOWAĆ{NEWLINE}WROGA NA TAKIEJ GŁĘBOKOŚCI\"\n  STR_UNABLE_TO_ENGAGE_AIRBORNE: \"NIE MOŻNA ZAATAKOWAĆ{NEWLINE}WROGA PODCZAS LOTU\"\n  STR_UNDERWATER_EQUIPMENT: \"To wyposażenie nie działa na powierzchni!\"\n  STR_LAND_EQUIPMENT: \"To wyposażenie nie działa pod wodą!\"\n  STR_LEVEL_SHORT: \"P{0}\"\n  STR_PERSONNEL: \"Personel\"\n  STR_CRAFT_ARMAMENT: \"Pojazdy i uzbrojenie\"\n  STR_COMPONENTS: \"Komponenty\"\n  STR_SOLDIERS_RECRUITED: \"Zatrudnieni akwanauci\"\n  STR_SOLDIERS_LOST: \"Utraceni akwanauci\"\n  STR_TOTAL_UFOS: \"Wykrytych łodzi latających\"\n  STR_TOTAL_ALIEN_BASES: \"Odkrytych kolonii obcych\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"SKM\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"ZKM\"\n  FEMALE_CIVILIAN: \"Cywil, kobieta\"\n  MALE_CIVILIAN: \"Cywil, mężczyzna\"\n  DOCKER_CIVILIAN: \"Cywil, robotnik\"\n  SAILOR_CIVILIAN: \"Cywil, marynarz\"\n  STR_BIODRONE_MELEE_WEAPON: \"Atak kontaktowy biodrona\"\n  HALLUCINOID_WEAPON: \"Atak halucynoida\"\n  STR_LOBSTERMAN_MELEE_WEAPON: \"Atak homaroida\"\n  CALCINITE_WEAPON: \"Atak kalcynita\"\n  DEEP_ONE_WEAPON: \"Atak głębiona\"\n  STR_TRISCENE_MELEE_WEAPON: \"Atak tryskona\"\n  STR_TRIBIO_SONIC_WEAPON: \"Obca broń dźwiękowa\"\n  XARQUID_WEAPON: \"Atak ksarkuida\"\n  TENTACULAT_WEAPON: \"Atak mackonoga\"\n  ZOMBIE_WEAPON: \"Atak zombiego\"\n  ALIEN_PSI_WEAPON: \"Obca broń K.M.\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/pt-BR.yml",
    "content": "pt-BR:\n  STR_LEVIATHAN_UFOPEDIA: \"AEROSUBMARINO DE TRANSPORTE E INTERCEPTAÇÃO, CAPAZ DE CHEGAR A UMA PROFUNDIDADE EXTREMA. UMA SÍNTESE FABULOSA DA TECNOLOGIA HUMANA E ALIENÍGENA, USANDO EM SISTEMAS DE PROPULSÃO IÔNICA E NAVEGAÇÃO DE MATRIZ MAGNÉTICA.\"\n  STR_BARRACUDA_UFOPEDIA: \"NAVE SUBMARINA BRITÂNICA BARRACUDA, MOVIDA POR MOTORES DE LASER SUPER AQUECIDOS, UMA DAS NAVES DE INTERCEPTAÇÃO MAIS VELOZES DO MUNDO, PODE SUBMERGIR E VOAR, UMA PEÇA CHAVE PARA A BATALHA QUE SE APROXIMA.\"\n  STR_HAMMERHEAD_UFOPEDIA: \"UMA NAVE DE TRANSPORTE E INTERCEPTAÇÃO. UMA RÉPLICA DOS SISTEMAS DE REDE MAGNÉTICA EM UMA NAVE X-COM. SEU DESENHO É UMA REALIZAÇÃO TÉCNICA ASSOMBROSA.\"\n  STR_TRITON_UFOPEDIA: \"O TRANPORTADOR DE TROPAS DE ASSALTO TRITÃO, EQUIPADO COM MOTORES PARA IMERSÃO E VOO. SUA ENORME CAPACIDADE E SUA CONSTRUÇÃO RESISTENTE FAZEM COM QUE ELE SEJA O SUPORTE PRINCIPAL DA FROTA X-COM.\"\n  STR_MANTA_UFOPEDIA: \"NAVE DE ALTA VELOCIDADE MANTA, UM AEROSUBMARINO DE INTERCEPTAÇÃO PARA APENAS UMA PESSOA, PARECIDO COM AS NAVES ALIENÍGENAS MOVIDAS POR ÍONS. MUITO EFICAZ NO CONFLITO QUE SE AGRAVA.\"\n  STR_AJAX_UFOPEDIA: \"O TORPEDO AJAX É A ARMA PADRÃO DO COMBATE SUBMARINO QUE SE ESTENDE POR TODO O MUNDO. SERVE COMO ELEMENTO DISSUASIVO POTENTE E PRECISO.\"\n  STR_DUP_HEAD_UFOPEDIA: \"A TECNOLOGIA DE ARMAS COM OGIVA DE URÂNIO EMPOBRECIDO É RELATIVAMENTE NOVA, E ESTA É A PRIMEIRA ARMA AQUÁTICA COMERCIAL QUE USA ESTA TECNOLOGIA.\"\n  STR_CRAFT_GAS_CANNON_UFOPEDIA: \"ESTE CANHÃO A GÁS COMPRIMIDO DISPARA PROJÉTEIS SÓLIDOS PERFURANTES, COM GRANDE CAPACIDADE DE PENETRAÇÃO.\"\n  STR_PWT_CANNON_UFOPEDIA: \"O TORPEDO DE ONDAS DE IMPULSOS UTILIZA UM SISTEMA DE COMBUSTÍVEL SUPER AQUECIDO E UMA OGIVA EXTREMAMENTE DENSA QUE PODE PERFURAR A MAIORIA DAS LIGAS.\"\n  STR_GAUSS_CANNON_UFOPEDIA: \"O CANHÃO GAUSS É A MAIS RECENTE TECNOLOGIA DE ARMAMENTO DESENVOLVIDA PELO PROJETO X-COM. O ACELERADOR DE PARTICULAS DESTA ARMA É ALIMENTADO POR UM PEQUENO REATOR DE FUSÃO REFRIGERADO COM NITROGÊNIO LÍQUIDO.\"\n  STR_SONIC_OSCILLATOR_UFOPEDIA: \"ESTE POTENTE OSCILADOR ACÚSTICO PRODUZ ONDAS SÔNICAS QUE DESTRUEM A ESTRUTURA MOLECULAR DO ALVO ATRAVÉS DE PODEROSAS VIBRAÇÕES.\"\n  STR_AQUATOID_UFOPEDIA: \"A raça Aquatoide forma uma sociedade ancestral que já existia antes do homem dar seus primeiros passos sobre a Terra. Seu aspecto compacto e suas características bulbosas supõem um retrocesso com respeito a seus irmãos os Sectoides, que também viajam pelo espaço. Seu poder se apoia na tecnologia do controle molecular. Os Aquatoides querem propagar sua raça estéril por meio da codificação genética e, para isso, fazem experiências com seres humanos, dando origem a numerosas raças híbridas.\"\n  STR_AQUATOID_AUTOPSY: \"Necrópsia de Aquatoide\"\n  STR_AQUATOID_AUTOPSY_UFOPEDIA: \"Um exame detalhado desta criatura nos permite chegar a umas suposições básicas. É um Sectoide, nosso antigo inimigo, mas foi modificado por métodos cirúrgicos e implante e agora é uma criatura aquática. O vestígio de pulmões que restaram lhe permite respirar e mover-se por terra, e implantes cibernéticos aumentam a força de seus membros atrofiados e melhoram o funcionamento de seus órgãos. Já que todos os membros desta raça são idênticos, supomos que sejam clones.\"\n  STR_GILLMAN_UFOPEDIA: \"Uma estranha criatura meio humana meio réptil, estreitamente relacionada com o homem e extraordinariamente forte e rápida sob a água. Os Homens-Brânquia são uma raça plenamente desenvolvida, com fêmeas e machos de distintas idades. Diferenciam-se da maioria dos alienígenas submarinos em que não apresentam nenhum sinal de alteração genética nem de deformação cirúrgica. Pode ser que estejamos diante de um grupo arcaico de nossa própria espécie.\"\n  STR_GILLMAN_AUTOPSY: \"Necrópsia de Homem-Brânquia\"\n  STR_GILLMAN_AUTOPSY_UFOPEDIA: \"Uma vez iniciada a intervenção cirúrgica, ficou claro que não era um alienígena, mas sim uma criatura da Terra, uma raça pré-histórica que se acreditava estar desaparecida desde que os mamíferos predominaram neste planeta. Os Homens-Brânquia, inteligentes e fortes, viveram na época dos dinossauros. O cataclismo que acabou com o predomínio dos répteis obrigou a estas criaturas a estabelecer uma relação simbiótica com os alienígenas recém chegados. Têm um dispositivo eletrônico no crânio.\"\n  STR_LOBSTERMAN_UFOPEDIA: \"Esta é uma criatura assombrosa, mais alta que um homem e tem seis pulmões. Se parece nada menos do que um demônio aquático. Sua semelhança com a lagosta terrestre o fez ganhar o apelido de Homem-Lagosta entre as tropas X-Com. Isto é um monstro das profundezas. Uma criatura de incrível força desenvolvida cuidadosamente para lutar, e virtualmente invulnerável ao fogo de projéteis. Suas pinças são suficientes para triturar aço.\"\n  STR_LOBSTERMAN_AUTOPSY: \"Necrópsia de Homem-Lagosta\"\n  STR_LOBSTERMAN_AUTOPSY_UFOPEDIA: \"Sob a carapaça virtualmente indestrutível, encontramos uma criatura construída de forma soberba. Os músculos poderosos são apoiados por um esqueleto de titânio e um sistema avançado de escaneamento múltiplo de alvos está ligado diretamente ao seu cérebro. Os seus olhos estão protegidos por lentes de plástico mais duras que o aço e o seu corpo contém ainda aparelhos cuja função desconhecemos. Com base nestes aspetos, concluímos que, quando usados estrategicamente em combate, estes seres são praticamente invencíveis.\"\n  STR_TASOTH_UFOPEDIA: \"Estes seres aquáticos constituem a base do exército invasor. São produzidos às centenas, em incubadoras enormes, localizadas no coração das colônias alienígenas. Com uma força e agilidade superiores às de um homem normal, os Tasoth são verdadeiros alienígenas, carnívoros e muito mais fortes que os homens. Ocupam regularmente a linha da frente dos ataques alienígenas e nunca parecem se amedrontar, inclusive quando levam clara desvantagem.\"\n  STR_TASOTH_AUTOPSY: \"Necrópsia de Tasoth\"\n  STR_TASOTH_AUTOPSY_UFOPEDIA: \"A autópsia revelou um organismo com base num estranho sistema cibernético. Encontramos somente uma pequena unidade energética dentro do corpo, sem nenhum órgão biológico identificável. A energia circula através de uma rede bioelétrica. Esta criatura não possuí esqueleto ou qualquer estrutura de apoio. Ao morrer, o fluxo de energia para, e o seu corpo torna-se uma pilha inerte de músculos e fluídos. O único elemento interno é o par de baterias de cerâmica, que revivem a criatura brevemente, se reenergizadas.\"\n  STR_DEEP_ONE_UFOPEDIA: \"Os Seres das Profundezas são verdadeiros horrores biológicos, produzidos através das experiências de cruzamento entre humanos e alienígenas, realizadas pelos Aquatoides. Após encontrarmos variações diferentes desta criatura, concluímos, depois de várias pesquisas, que estes seres são fabricados pelos invasores, reforçando o seu exército com seres humanos recentemente capturados. Cada Ser das Profundezas está armado com um feixe de energia suficientemente poderoso para matar um aquanauta.\"\n  STR_DEEP_ONE_AUTOPSY: \"Necrópsia de Ser das Profundezas\"\n  STR_DEEP_ONE_AUTOPSY_UFOPEDIA: \"Esta criatura é um misto entre ser humano e organismo alienígena. O cérebro humano foi alterado para acomodar circuitos de controle e partes do córtex alienígena. O resto do corpo, exceto os olhos, foi removido. A alteração cirúrgica é feita de forma a permitir a inserção de um feto alienígena que consome o hospedeiro humano à medida que cresce. O resultado é uma aberração de enorme força e destreza, sob pleno controle dos invasores. A sua pele é um filamento metálico flexível, não-orgânico e altamente resistente. \"\n  STR_BIODRONE_UFOPEDIA: \"O Biodrone é uma criação que só uma mente alienígena poderia conceber. Trata-se de um cérebro (humano ou alienígena) suspenso em fluídos amnióticos e ligado a uma unidade robótica que lhe permite voar e mergulhar na água. Cada Biodrone está armado com um disruptor de áudio, um aparelho biomecânico que alguns cientistas julgam operar com base nas cordas vocais do organismo original. Os alienígenas utilizam estas entidades como sentinelas de recursos valiosos devido à sua alta precisão e tenacidade.\"\n  STR_BIODRONE_AUTOPSY: \"Necrópsia de Biodrone\"\n  STR_BIODRONE_AUTOPSY_UFOPEDIA: \"A hipótese de que o disruptor sônico é uma arma biológica é verdadeira.  Esta criatura infeliz literalmente mata seus inimigos no grito.  Todos os exemplares tem cicatrizes massivas e estão severamente mutilados.  Os alienígenas aparentemente mutilam o cérebro para assegurar obediência.  A maioria dos espécimes possui encéfalos de origem alienígena, mas nada se compara ao horror de  encontrar um exemplar de proveniência humana. Os Biodrones são impulsionados por de um motor de íons e incorporam algum tipo de controle remoto.\"\n  STR_TENTACULAT_UFOPEDIA: \"Nem nos contos do escritor H.P. Lovecraft poderíamos encontrar uma criatura mais horrenda. O ambiente que deu origem a este monstro está além das nossas especulações, pois nenhum animal terrestre se parece com ele. Armado com longos tentáculos paralisantes, capazes de penetrar a melhor das armaduras, o Tentaculate é uma criatura mortífera que transforma as suas vítimas em zumbis errantes. Este é o alienígena mais terrível encontrado pelas forças X-Com.\"\n  STR_TENTACULAT_AUTOPSY: \"Necrópsia do Tentaculate\"\n  STR_TENTACULAT_AUTOPSY_UFOPEDIA: \"A necrópsia revelou a presença de vários implantes cibernéticos no cérebro desta criatura. O seu sistema visual é uma combinação complexa de captação de luz visível e imagens térmicas, permitindo a navegação nas profundezas mais escuras com enorme precisão. Este ser possui apenas órgãos residuais necessários para assegurar a sua sobrevivência, e o seu estômago está ligado a um conector externo, o que sugere dependência de injeções diretas de nutrientes por parte dos seus mestres.\"\n  STR_CALCINITE_UFOPEDIA: \"Estas criaturas similares aos trajes de mergulhadores perdidos espreitam as profundezas oceânicas em busca de vítimas. Um golpe das suas garras é suficiente para incapacitar os mergulhadores mais experientes. Além da massa gelatinosa observável através da viseira do escafandro, não conseguimos retirar outras conclusões sobre a natureza desta criatura com base nos encontros frequentemente letais que tivemos com ela.\"\n  STR_CALCINITE_AUTOPSY: \"Necrópsia de Calcinite\"\n  STR_CALCINITE_AUTOPSY_UFOPEDIA: \"Uma vez desprovido do traje blindado, o Calcinite é uma massa amorfa de protoplasma sem cérebro, membros ou órgãos sensoriais visíveis. No interior do corpo líquido há um pequeno elemento metálico. Uma vez morta, só podemos fazer conjeturas sobre a natureza desta criatura. É um enigma inexplicável dos nossos inimigos alienígenas.\"\n  STR_TRISCENE_UFOPEDIA: \"Este réptil bípede é um regresso à idade dos dinossauros. Tudo, exceto sua habilidade para viver na água e fora dela, indica que é uma criatura do período Cretáceo. Estas criaturas levam compartimentos de armas e têm uma mandíbula com enormes dentes de aço. Frequentemente, estes monstros têm estado no centro das forças de ataque alienígenas quando estas lançam um ataque terrestre. Constituem uma arma potente e pesada que os Tasoth de alta patente desdobram com uma eficácia mortal.\"\n  STR_TRISCENE_AUTOPSY: \"Necrópsia de Triscênio\"\n  STR_TRISCENE_AUTOPSY_UFOPEDIA: \"Uma vez submetidos ao bisturi do cientista, o Triscênio revela ser uma criatura pré-histórica modificada com implantes cibernéticos e sistemas de armas. Seu minúsculo cérebro foi suplementado por um pequeno módulo de computador acoplado ao arnês de controle que todas as criaturas vestem. Uma pele natural resistente e um instinto predatório realçado com armas fazem dele um oponente mortal em qualquer ambiente.\"\n  STR_HALLUCINOID_UFOPEDIA: \"Depois de explorar os oceanos, os alienígenas criaram esta enorme criatura terrestre e a utilizam como arma. Não se deixe enganar pelo falso aspecto inofensivo desta criatura marinha das profundezas. O Alucinoide é um inimigo mortal que ataca de longe com explosões congelantes e de perto com golpes cortantes como o gelo.\"\n  STR_HALLUCINOID_AUTOPSY: \"Necrópsia de Alucinoide\"\n  STR_HALLUCINOID_AUTOPSY_UFOPEDIA: \"Nas muitas camadas do corpo gelatinoso deste organismo há um potente químico congelante, seu principal meio de ataque. A pele suave e flexível do Alucinoide indica que é vulnerável a ataques baseados em calor. Este mutante é frequentemente visto em companhia de seus amos, os Aquatoides.\"\n  STR_XARQUID_UFOPEDIA: \"Outro invertebrado modificado da Terra, o Xarquídeo é uma criatura de grande beleza e perigo. A natação rápida e colossal esconde um arsenal devastador de armas, um spray de tinta sufocante e uma explosão de partícula ionizada. Desde os nossos primeiros encontros com esta criatura poderosa, temos sido cautelosos com seu poder e seus controladores, os vingativos Homens-Brânquias.\"\n  STR_XARQUID_AUTOPSY: \"Necrópsia de Xarquídeo\"\n  STR_XARQUID_AUTOPSY_UFOPEDIA: \"Este Náutilo gigantesco foi alterado através de cirurgia e drogas alienígenas, por forma a operar como uma enorme plataforma de armas orgânica. A sua natureza pacifica foi corrompida pelos Homens-Guelra através de sistemas de controlo mecânicos. A sua concha resistente e enorme mobilidade fazem do Xarquídeo um adversário formidável em combate.\"\n  STR_ION_BEAM_ACCELERATORS_UFOPEDIA: \"Os aerosubmarinos alienígenas utilizam motores complexos para navegar a velocidades incríveis nas profundezas. Esta tecnologia utiliza um DESLOCADOR DE ÍONS que, ao utilizar Zrbite como catalisador, permite aos motores deslocar até 100 vezes o seu próprio volume em água por segundo. Tal potência significa que os veículos alienígenas facilmente ultrapassam em velocidade a maioria dos submarinos da Terra. Podemos replicar este sistema de propulsão usando aquaplástico e baterias de Zrbite.\"\n  STR_MAGNETIC_NAVIGATION_UFOPEDIA: \"Este sistema projeta um campo magnético dividido em camadas esféricas, no raio de 1 km, em torno do OSNI. Os navegadores alienígenas estão ligados a estas máquinas, de maneira a \\\"sentirem\\\" o caminho através da escuridão dos oceanos. Esta interface utiliza matéria cerebral alienígena para comunicar diretamente com o cérebro do navegador, através de uma ligação nervosa.\"\n  STR_ALIEN_SUB_CONSTRUCTION_UFOPEDIA: \"A estrutura das naves é como a de um camaleão, imita características das criaturas marinhas e é feita de aquaplástico. Cada submarino funciona como um organismo: tripulação e nave em harmonia. A maioria de seus sistemas podem ser reproduzidos e é possível criar uma tecnologia híbrida que nos permita chegar ao mesmo nível tecnológico.\"\n  STR_ALIEN_CRYOGENICS_UFOPEDIA: \"Muitos alienígenas permanecem escondidos na Terra em estado de em animação suspensa, submetidos a um congelamento criogênico. Estas criaturas são guardadas em unidades com sua temperatura corporal reduzida até que suas funções vitais estejam a ponto de parar. Um exame destas unidades revelou que os corpos permaneceram suspensos por períodos incríveis, alguns com mais de 60 milhões de anos.\"\n  STR_ALIEN_CLONING_UFOPEDIA: \"Muitos dos Alienígenas que capturamos são geneticamente idênticos, cópias em tudo. Amostras celulares são colocadas nas unidades a partir dos bancos genéticos congelados dos Alienígenas. Algumas unidades contêm humanos ou partes de corpos.  É possível que sirvam também para criar um híbrido Alienígena-Humano.\"\n  STR_ALIEN_LEARNING_ARRAYS_UFOPEDIA: \"Graças aos implantes de Controle Molecular que há nos crânios de todos os alienígenas, estas máquinas injetam diretamente informação em seus cérebros. Os alienígenas recém clonados são levados até estas unidades para lhes introduzir lembranças de sua raça e informações científicas e bélicas em suas mentes vazias.\"\n  STR_ALIEN_IMPLANTER_UFOPEDIA: \"Esta unidade é utilizada para inserir implantes de controlo molecular nos crânios dos alienígenas, fertilizar espécies com capacidades reprodutoras, e colocar ou remover órgãos e aparelhos cibernéticos em qualquer criatura. Os pacientes são sujeitos ao processo em pleno estado de consciência e, infelizmente, descobrimos que o aparelho adapta-se perfeitamente à anatomia humana.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"Nós já temos evidências para descobrir por que os humanos são capturados pelos alienígenas. Eles não os usam como comida nem os fertilizam com seus próprios embriões, eles os usam como base de uma série de criaturas e sistemas de controle. Sua tecnologia é baseada em uma única mente, um intelecto compartilhado, e o cérebro humano é o receptáculo ideal para isso. O tecido do cérebro humano é utilizado na maioria dos computadores e sistemas de recuperação biológica, o resto serve para produzir e procriar.\"\n  STR_AQUA_PLASTICS_UFOPEDIA: \"Os veículos e estruturas alienígenas são construídos através de aquaplástico, um material estruturalmente complexo, com enorme durabilidade, resistência e flexibilidade. Esta substância catalisada através de Zrbite é altamente densa, mas extremamente leve.\"\n  STR_ZRBITE_UFOPEDIA: \"Esta liga de origem alienígena, é um composto híbrido entre ouro e matéria orgânica alienígena. Quando utilizada como combustível, pequenas quantidades desta substância são capazes de gerar mais energia que uma unidade de fusão nuclear. Infelizmente somos incapazes de reproduzir este material, devido à maioria dos seus componentes serem de origem extraterrestre.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"Os alienígenas atacam por todo o planeta com uma eficácia assustadora, mas nós não conseguimos localizar sua origem. Será que vêm de alguma profundeza oceânica impenetrável aos nossos sonares? Nem todos os organismos que encontramos são de origem alienígena. Alguns assemelham-se a espécies antigas e outros descendentes de cadeias evolucionárias que julgávamos extintas há muito tempo. Lidamos com uma ameaça dormente há milênios, uma sutil simbiose entre humanos e alienígenas. Nas profundezas dos oceanos, encontram-se estações antigas, usadas pelos alienígenas para contatar os seus parentes estelares. Cada uma destas doze estações contém um Dispositivo Synomium, uma poderosa peça de tecnologia alienígena. Agora, com as suas hostes em marcha, os alienígenas procuram reativar estas estações para expandirem a sua rede de Controle Molecular. Precisamos destruir estas estações a todo o custo.\"\n  STR_THE_ULTIMATE_THREAT_UFOPEDIA: \"Há sessenta e cinco milhões de anos atrás uma enorme nave colônia foi enviada à Terra de um mundo alienígena longínquo. À medida que a enorme embarcação se aproximava do jovem planeta, uma violenta erupção solar provocou uma falha nos sistemas da navegação. A enorme maça, inutilizada e avariada caiu pela estratosfera do céu do período cretáceo. Na Terra, numerosas espécies animais olharam para o céu e viram seu inimigo preparando o caminho no planeta. Uma vasta nuvem de poeira entupia a atmosfera e à medida que a terra esfriava, a vida dominante, os poderosos dinossauros, pereciam. Mas os 400 bilhões de toneladas de T'leth não foram destruídos no impacto, modernos super computadores iniciaram a hibernação criogênica das criaturas que haviam em seu interior. Depois éons, os computadores despertaram grupos de alienígenas para que tentassem se comunicar com seus primos estelares, mas foi em vão, pois o núcleo do poder alienígena continuava dormindo.\"\n  STR_TLETH_THE_ALIEN_CITY: \"T'leth, a Cidade Alienígena\"\n  STR_TLETH_THE_ALIEN_CITY_UFOPEDIA: \"T'leth, a enorme nave colônia alienígena, jaz no fundo da fossa \\\"Sigsbee Deep\\\", no Golfo do México. No coração da cidadela esconde-se um horror alienígena tão poderoso e tão vil que nem a morte pode lhe tocar. Dentro de uma enorme câmara de metal alienígena dorme a forma dormente do grande sonhador, o Supremo Alienígena. Quando T'leth se erguer acima das ondas, o seu ciclo de reanimação será iniciado, e se isso acontecer ele será imparável. Apesar de não estar vivo, mas de alguma maneira também não morto, a mente deste ser controla o exército alienígena. A estranha tecnologia de controle molecular liga todos os alienígenas à sua mente, e a sua mente à de todos os alienígenas. Milhares de fetos híbridos entre humanos e alienígenas proporcionam energia à Grande Mente alienígena, e formam o elo mental entre o mestre supremo e os seus súditos. O mito do Supremo Alienígena sempre existiu nos corações e nas mentes de todos os seres humanos durante séculos, mas a verdade sempre esteve escondida no fundo do mar.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"CENTRALIZAR NO LOCAL = 5 Segs\"\n  STR_CANCEL_UC: \"CANCELAR\"\n  STR_NONE: \"Nenhum\"\n  STR_UNKNOWN: \"Desconhecido\"\n  STR_POOR: \"Fraco\"\n  STR_AVERAGE: \"Médio\"\n  STR_GOOD: \"Bom\"\n  STR_EXCELLENT: \"Excelente\"\n  STR_BUILD_NEW_BASE_UC: \"CONSTRUIR NOVA BASE\"\n  STR_BASE_INFORMATION: \"INFORMAÇÕES DA BASE\"\n  STR_EQUIP_CRAFT: \"EQUIPAR SUBMARINO\"\n  STR_BUILD_FACILITIES: \"CONSTRUIR INSTALAÇÕES\"\n  STR_RESEARCH: \"PESQUISAR\"\n  STR_MANUFACTURE: \"PRODUZIR\"\n  STR_TRANSFER_UC: \"TRANSFERIR\"\n  STR_PURCHASE_RECRUIT: \"COMPRAR/RECRUTAR\"\n  STR_SACK: \"DISPENSAR\"\n  STR_SELL_SACK_UC: \"VENDER/DISPENSAR\"\n  STR_GEOSCAPE_UC: \"TELA GLOBAL\"\n  STR_NAME: \"Nome\"\n  STR_AREA: \"Área\"\n  STR_BUILD_NEW_BASE: \"Construir Nova Base\"\n  STR_CANCEL: \"Cancelar\"\n  STR_COST_UC: \"CUSTO>\"\n  STR_CONSTRUCTION_TIME_UC: \"TEMPO DE CONSTRUÇÃO>\"\n  STR_DAY:\n    one: \"{N} dia\"\n    many: \"{N} dias\"\n    other: \"{N} dias\"\n  STR_HOUR:\n    one: \"{N} hora\"\n    many: \"{N} horas\"\n    other: \"{N} horas\"\n  STR_MAINTENANCE_UC: \"MANUTENÇÃO>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Instalação\"\n  STR_CURRENT_RESEARCH: \"PESQUISAS ATUAIS\"\n  STR_SCIENTISTS_AVAILABLE: \"Cientistas Disponíveis>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Cientistas Alocados>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Espaço de Laboratório Disponível>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"PROJETO DE PESQUISA\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"CIENTISTAS ALOCADOS\"\n  STR_PROGRESS: \"PROGRESSO\"\n  STR_NEW_PROJECT: \"Novo Projeto\"\n  STR_CANCEL_PROJECT: \"CANCELAR PROJETO\"\n  STR_NEW_RESEARCH_PROJECTS: \"NOVOS PROJETOS DE PESQUISA\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"CIENTISTAS DISPONÍVEIS>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"ESPAÇO DE LABORATÓRIO DISPONÍVEL>{ALT}{0}\"\n  STR_INCREASE: \"Aumentar\"\n  STR_DECREASE: \"Diminuir\"\n  STR_START_PROJECT: \"INICIAR PROJETO\"\n  STR_CURRENT_PRODUCTION: \"PRODUÇÃO ATUAL\"\n  STR_ENGINEERS_AVAILABLE: \"Técnicos Disponíveis>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Técnicos Alocados>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Espaço Disponível na Oficina>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Fundos Atuais>{ALT}{0}\"\n  STR_ITEM: \"ITEM\"\n  STR_ENGINEERS__ALLOCATED: \"Técnicos Alocados\"\n  STR_UNITS_PRODUCED: \"Unidades Produzidas\"\n  STR_TOTAL_TO_PRODUCE: \"Total a Produzir\"\n  STR_COST__PER__UNIT: \"Custo{NEWLINE}por{NEWLINE}Unidade\"\n  STR_DAYS_HOURS_LEFT: \"Dias/Horas Restantes\"\n  STR_NEW_PRODUCTION: \"Nova Produção\"\n  STR_PRODUCTION_ITEMS: \"Itens para Produção\"\n  STR_CATEGORY: \"CATEGORIA\"\n  STR_START_PRODUCTION: \"INICIAR PRODUÇÃO\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} horas de Técnicos para produzir uma unidade.\"\n  STR_COST_PER_UNIT_: \"Custo por unid.>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Espaço de Trabalho Necessário>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"MATERIAIS ESPECIAIS NECESSÁRIOS\"\n  STR_ITEM_REQUIRED: \"ITEM NECESSÁRIO\"\n  STR_UNITS_REQUIRED: \"UNIDADES NECESSÁRIAS\"\n  STR_UNITS_AVAILABLE: \"UNIDADES DISPONÍVEIS\"\n  STR_STOP_PRODUCTION: \"PARAR PRODUÇÃO\"\n  STR_ENGINEERS_AVAILABLE_UC: \"TÉCNICOS DISPONÍVEIS>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"ESPAÇO DISPONÍVEL NA OFICINA>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"LUCRO MENSAL>{ALT}{0}\"\n  STR_INCREASE_UC: \"AUMENTAR\"\n  STR_DECREASE_UC: \"DIMINUIR\"\n  STR_UNITS_TO_PRODUCE: \"Unidades a Produzir\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Comprar/Recrutar Pessoal\"\n  STR_COST_OF_PURCHASES: \"Custo das Compras>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"CUSTO POR UNID.\"\n  STR_QUANTITY_UC: \"QUANTID.\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"PESSOAL DISPONÍVEL : PESSOAL TOTAL>\"\n  STR_SOLDIERS: \"Aquanautas\"\n  STR_SCIENTISTS: \"Cientistas\"\n  STR_ENGINEERS: \"Técnicos\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"ESPAÇO USADO : ESPAÇO DISPONÍVEL>\"\n  STR_LIVING_QUARTERS: \"Habitação\"\n  STR_STORES: \"Depósitos\"\n  STR_LABORATORIES: \"Laboratórios\"\n  STR_WORK_SHOPS: \"Oficinas\"\n  STR_HANGARS: \"Aerosubmarino\"\n  STR_SHORT_RANGE_DETECTION: \"Sonar de Curto Alcance\"\n  STR_DEFENSE_STRENGTH: \"Força Defensiva\"\n  STR_TRANSFERS_UC: \"Transferências\"\n  STR_TRANSFERS: \"Transferências\"\n  STR_ARRIVAL_TIME_HOURS: \"CHEGADA (EM HORAS)\"\n  STR_COST_: \"Custo>{ALT}{0}\"\n  STR_AREA_: \"Área>{ALT}{0}\"\n  STR_BASE_NAME: \"Nome da Base?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"SELECIONE A LOCALIZAÇÃO DA CÂMARA PRESSURIZADA\"\n  STR_TRANSFER: \"Transferir\"\n  STR_AMOUNT_TO_TRANSFER: \"QUANT. A TRANSF.\"\n  STR_SELECT_DESTINATION_BASE: \"Selecionar Base de Destino\"\n  STR_COST: \"Custo\"\n  STR_INTRO_1: \"© 1995 MicroProse - Todos os direitos reservados\"\n  STR_INTRO_2: \"Marte: A Queda de Cidônia\"\n  STR_INTRO_3: \"As forças X-Com regressam à Terra após uma triunfante batalha que culminou com a destruição da máquina de guerra alienígena. Entretanto, ainda há vida nas ruínas da base marciana.\"\n  STR_INTRO_4: \"Um poderoso raio de táquion flui dos escombros do centro de comando de Cidônia, a toda velocidade através do vazio. Seu destino............\"\n  STR_INTRO_5: \"A Terra.\"\n  STR_INTRO_6: \"Nas profundezas do oceano o feixe atinge um receptor há muito tempo inativo. Grandes computadores desligados, iniciam a sua atividade. Nas profundezas, longe dos olhares humanos, vastas câmaras com Alienígenas em criogenia começam seu longo ciclo de reanimação.\"\n  STR_INTRO_7: \"2040: Uma Terra ignorante. Os terrores da guerra Alienígena foram esquecidos. Mas, nos lugares perdidos e ocultos do oceano as hordas alienígenas estão preparadas e prontas para derrotar a humanidade e dominar o mundo.\"\n  STR_INTRO_8: \"Os Alienígenas atacaram a humanidade em busca de espécimes humanos para seus deturpados experimentos. Invadiram o mundo e saquearam os mares por seus valiosos minerais e recursos. Mas então, os Alienígenas fixaram seus olhos em terra firme.\"\n  STR_INTRO_9: \"Poderosos aerosubmarinos de estranho desenho riscam os oceanos - observando, procurando, caçando.........\"\n  STR_INTRO_10: \"Procurando presas para atacar.\"\n  STR_INTRO_11: \"Novas armas misteriosas ameaçam uma civilização indefesa. Estamos completamente à mercê das forças alienígenas.{NEWLINE} Só uma organização há muito esquecida pode nos salvar.\"\n  STR_INTRO_12: \"Instalação Subaquática Experimental da X-Com\"\n  STR_INTRO_13: \"'Mayday! Mayday!' 'Aqui é o transatlântico Hyperion'. 'Estamos sob ataque'. 'Mayday! Mayd............'\"\n  STR_INTRO_14: \"'Centro de Comando para Submarino Um: Abrir portas ao mar', 'posicionar Barracuda Zero Um. Temos uma situação de ataque alienígena - Alerta Vermelho'.{NEWLINE}'Repito: Alerta Vermelho'\"\n  STR_INTRO_15: \"Os alienígenas são implacáveis em sua eficiência...\"\n  STR_INTRO_16: \"...infalíveis em sua exatidão \"\n  STR_INTRO_17: \"'Barracuda Zero Um para base' - 'aproximando-se do que restou do Hyperion'.\"\n  STR_INTRO_18: \"'Desacelerando''.{NEWLINE}'Dois metros'{NEWLINE}'Um metro'{NEWLINE}'Todos os aquanautas preparem para desembarque imediato'.\"\n  STR_INTRO_19: \"...........'Escotilha de ar aberta'...'aproximando-me dos destroços'.{NEWLINE}'Mas que...!'{NEWLINE}'Estão gravando essas criaturas com a câmera de meu traje?'\"\n  STR_GAMEOVER_1: \"Nós falhamos. Os alienígenas destruíram a nossa última esperança de salvação.{NEWLINE}As forças X-Com foram vencidas e a Terra jaz agora aos pés do inimigo.\"\n  STR_GAMEOVER_2: \"T 'leth troveja alto na estratosfera e começa a se mover através da face do mundo.  Distribuindo morte e colhendo os restos da raça humana. Na profundidade de suas entranhas a assassina mente alienígena começa a despertar.\"\n  STR_GAMEOVER_3: \"Nas capitais de todas as nações, planos desesperados são elaborados. Tudo é em vão, sem a tecnologia oferecida pelo projeto de pesquisa X-Com nossas armas são ineficazes.\"\n  STR_GAMEOVER_4: \"Os Alienígenas estabeleceram bases nas calotas polares e começam a derreter o gelo, o mundo se converterá em um vasto oceano. Os restos da raça humana são capturados e utilizados em vis experimentos de procriação com fins desconhecidos. Os céus obscurecem e uma poderosa pestilência está sobre as terras do Mundo.\"\n  STR_GAMEOVER_5: \"Não podemos oferecer nenhuma resistência à nova ordem mundial, aqueles que o tentam se encontram com um destino ígneo nas mãos das incompreensíveis armas alienígenas. Para o restante de nós não há tal bendita libertação, a mãe terra se converte em um mundo alienígena e a humanidade se perde debaixo de um progressivo horror.\"\n  STR_OUTRO_1: \"A Tumba, desolada e dizimada, um rugido borbulhante vem do caixão, no seu centro.{NEWLINE}Tolos, vocês todos perecerão....................\"\n  STR_OUTRO_2: \".................ninguém pode escapar.\"\n  STR_OUTRO_3: \"Uma enorme explosão irrompe da tumba e atravessa a cidade, os escombros e a fumaça enchem o ar. Os planos dos alienígenas foram frustrados........\"\n  STR_OUTRO_4: \"A retorcida vastidão de T'leth começa a se romper. Chamas e fumaça são jogadas de suas torres reluzentes e salas de adamantium.\"\n  STR_OUTRO_5: \"A poderosa fortaleza Alienígena desaba em direção ao mar, os gritos de metal e almas torturadas enchem o ar. O Grande Sonhador já não sonhará conquistando o mundo.\"\n  STR_OUTRO_6: \"O som de um abalo final ensurdecedor despedaça T'leth.{NEWLINE}A ameaça alienígena se foi e a Terra é purificada..................\"\n  STR_OUTRO_7: \"Um planeta sonolento, azul e verde, num canto distante da galáxia.\"\n  STR_OUTRO_8: \"O futuro próximo, um lugar seguro para se estar.\"\n  STR_OUTRO_9: \"A ameaça Alienígena foi derrotada há muito tempo.\"\n  STR_OUTRO_10: \"Vastas metrópoles alojam biliões de humanos.\"\n  STR_OUTRO_11: \"Os feitos da guerra entre X-Com e Alienígenas fazem parte das histórias para crianças.\"\n  STR_OUTRO_12: \"Mas as lendas sempre tiveram o habito de conter um pingo de verdade..........\"\n  STR_RISE_1: \"T'leth, conhecida por muitos nomes, em várias lendas de muitas terras.\"\n  STR_RISE_2: \"Com um grito explosivo que reverbera em todo o mundo, T'leth começa a subir do solo oceânico.\"\n  STR_RISE_3: \"O enorme edifício surge das águas do Golfo do México.\"\n  STR_RISE_4: \"400 bilhões de toneladas de metal alienígena, a grande cidade alienígena onde se encontra o corpo dormente do alienígena definitivo. Preso na terra por 65 milhões, este vil deus do espaço começa a se mover.\"\n  STR_RISE_5: \"As águas fervem e se agitam enquanto o túmulo do Grande Sonhador emerge a luz................\"\n  STR_RISE_6: \".........uma luz que terá vida curta a não ser que X-Com possa destruir a máquina de guerra Alienígena.\"\n  STR_YOU_HAVE_FAILED: \"Você fracassou em deter a máquina de guerra alienígena. As organizações de financiamento, desiludidas com sua capacidade tentam negociar uma solução não militar com os alienígenas. Os invasores têm uma agenda muito diferente e logo o mundo inteiro fica ciente da verdade...\"\n  STR_TOTAL_UC: \"TOTAL\"\n  STR_INCOME: \"Renda\"\n  STR_EXPENDITURE: \"Gastos\"\n  STR_MAINTENANCE: \"Manutenção\"\n  STR_BALANCE: \"Saldo\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"Atividade Alienígena nos Mares\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"Atividade Alienígena por Áreas\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"Atividade X-Com nos Mares\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"Atividade X-Com por Áreas\"\n  STR_FINANCE: \"Finanças\"\n  STR_DATE_FIRST: \"{0}  de\"\n  STR_DATE_SECOND: \"{0}  de\"\n  STR_DATE_THIRD: \"{0}  de\"\n  STR_DATE_FOURTH: \"{0}  de\"\n  STR_FINANCE_THOUSANDS: \"$1000\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Não há materiais especiais suficientes para produzir{NEWLINE}{0}{NEWLINE}em{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Dinheiro insuficiente para produzir{NEWLINE}{0}{NEWLINE}em{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"Produção de{NEWLINE}{0}{NEWLINE}em{NEWLINE}{1}{NEWLINE}está completa\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"Construção de {NEWLINE}{0}{NEWLINE}em{NEWLINE}{1}{NEWLINE}completa\"\n  STR_OK_5_SECONDS: \"OK - 5 segs\"\n  STR_RESEARCH_COMPLETED: \"Pesquisa Completa\"\n  STR_VIEW_REPORTS: \"VER RELATÓRIOS\"\n  STR_WE_CAN_NOW_RESEARCH: \"Agora podemos pesquisar\"\n  STR_WE_CAN_NOW_PRODUCE: \"Agora podemos produzir\"\n  STR_SUNDAY: \"DOMINGO\"\n  STR_MONDAY: \"SEGUNDA\"\n  STR_TUESDAY: \"TERÇA\"\n  STR_WEDNESDAY: \"QUARTA\"\n  STR_THURSDAY: \"QUINTA\"\n  STR_FRIDAY: \"SEXTA\"\n  STR_SATURDAY: \"SÁBADO\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Não há {0} suficiente para reabastecer {1} em {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Não há {0} suficiente para rearmar {1} em {2}\"\n  STR_UFO_IS_NOT_RECOVERED: \"O OSNI não foi recuperado\"\n  STR_UFO_IS_RECOVERED: \"O OSNI foi recuperado\"\n  STR_CRAFT_IS_LOST: \"O Aerosubmarino foi perdido\"\n  STR_TERROR_CONTINUES: \"Atividade Alienígena continua\"\n  STR_ALIENS_DEFEATED: \"Alienígenas derrotados\"\n  STR_BASE_IS_LOST: \"A base foi perdida\"\n  STR_BASE_IS_SAVED: \"A base está salva\"\n  STR_ALIEN_BASE_STILL_INTACT: \"Colônia Alienígena permanece intacta\"\n  STR_ALIEN_BASE_DESTROYED: \"Colônia Alienígena destruída\"\n  STR_ALIENS_KILLED: \"ALIENÍGENAS MORTOS\"\n  STR_ALIEN_CORPSES_RECOVERED: \"CADÁVERES DE ALIENÍGENAS RECUPERADOS \"\n  STR_LIVE_ALIENS_RECOVERED: \"ALIENÍGENAS RECUPERADOS VIVOS\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"ARTEFATOS ALIENÍGENAS RECUPERADOS\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"COLÔNIA CONTROLADA POR ALIENÍGENAS DESTRUÍDA\"\n  STR_ALIEN_SYNOMIUM_DEVICE_DESTROYED: \"DISPOSITIVO ALIENÍGENA SYNOMIUM DESTRUÍDO\"\n  STR_ALIEN_SYNOMIUM_DEVICE_FAILED: \"FALHA EM DESTRUIR O DISPOSITIVO SYNOMIUM\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"CIVIS MORTOS POR ALIENÍGENAS\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"CIVIS MORTOS POR SOLDADOS X-COM\"\n  STR_CIVILIANS_SAVED: \"CIVIS SALVOS\"\n  STR_XCOM_OPERATIVES_KILLED: \"AGENTES X-COM MORTOS\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"AGENTES X-COM DESAPARECIDOS EM COMBATE\"\n  STR_TANKS_DESTROYED: \"PLATAFORMA DE ARMAS X-COM DESTRUÍDA\"\n  STR_XCOM_CRAFT_LOST: \"SUBMARINO X-COM PERDIDO\"\n  STR_UFO_RECOVERY: \"RECUPERAÇÃO DE OSNI\"\n  STR_ALIEN_BASE_RECOVERY: \"CAPTURADOS NA COLÔNIA ALIENÍGENA\"\n  STR_BASE_UNDER_ATTACK: \"{0} está sob ataque!\"\n  STR_BASE_DEFENSES_INITIATED: \"SISTEMAS DE DEFESA ATIVADOS\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"ESCUDOS AFASTARAM O OSNI!\"\n  STR_FIRING: \"ATIRANDO\"\n  STR_HIT: \"ALVO ATINGIDO!\"\n  STR_UFO_DESTROYED: \"OSNI DESTRUÍDO!\"\n  STR_MISSED: \"ERROU!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Vender Itens/Dispensar Pessoal\"\n  STR_VALUE_OF_SALES: \"VALOR DA VENDA> {ALT}{0}\"\n  STR_FUNDS: \"FUNDOS> {ALT}{0}\"\n  STR_SELL_SACK: \"Vender/Dispensar\"\n  STR_VALUE: \"Valor\"\n  STR_CRAFT_: \"AEROSUBMARINO> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"RECUPERAÇÃO DE OSNI AFUNDADO\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"EXTREMA CAUTELA - Podem haver Alienígenas no OSNI ou ao redor do local do acidente. A missão será bem sucedida quando todas as unidades inimigas forem eliminadas ou neutralizadas. A recuperação de destroços do OSNI, artefatos e cadáveres alienígenas podem então ser iniciados. Para abortar a missão, retorne os aquanautas X-Com para o submarino e clique no ícone 'Abortar Missão'.\"\n  STR_UFO_GROUND_ASSAULT: \"ASSALTO AO OSNI\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"Explore o local de aterrissagem e, se possível, entre no OSNI. A missão será bem-sucedida quando todas as unidades inimigas forem eliminadas ou neutralizadas. Só depois poderemos iniciar a recuperação dos destroços do OSNI, artefatos e cadáveres de alienígenas. Para abortar a missão, retorne os aquanautas X-Com ao submarino e clique no ícone \\\"Abortar Missão\\\".\"\n  STR_BASE_DEFENSE: \"DEFESA DE BASE\"\n  STR_BASE_UC_: \"BASE> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"Um submarino alienígena atracou nas proximidades. A nossa base está em sério perigo. Todos os submarinos X-Com e os não-militares foram evacuados conforme o protocolo. As tropas alienígenas entrarão na base através das docas ou da câmara pressurizada. Temos que defender a base e as suas instalações vitais a todo o custo, num combate até à morte. Se clicar no ícone \\\"Abortar Missão\\\" as nossas tropas se renderão e você perderá a base.\"\n  STR_ALIEN_COLONY_ATTACK_MISSION: \"ATAQUE A COLÔNIA ALIENÍGENA\"\n  STR_ALIEN_BASE_ASSAULT: \"COLÔNIA ALIENÍGENA - PARTE 1\"\n  STR_ALIEN_COLONY_P1_BRIEFING: \"Esta missão é um ataque à uma colônia alienígena.  Há 2 níveis, leve todos os aquanautas à saída luminosa no primeiro complexo e clique no ícone \\\"Abortar Missão\\\" para prosseguir.  Qualquer equipamento deixado para trás ficará no fundo do mar até que se resolva a segunda seção.  Para sair, coloque os aquanautas no submarino e clique no ícone \\\"Abortar Missão\\\".\"\n  STR_ALIEN_COLONY_P2: \"COLÔNIA ALIENÍGENA - PARTE 2\"\n  STR_ALIEN_COLONY_P2_BRIEFING: \"Tendo negociado o primeiro nível e entrado no núcleo da colônia, a missão agora é destruir o centro de controle ou o Dispositivo Synomium, ou eliminar todos os alienígenas. Para abortar coloque todos os aquanautas no ponto de partida e clique no ícone \\\"Abortar Missão\\\".  Todo o equipamento X-Com viável regressará à base.\"\n  STR_ALIENS_LAUNCH_PORT_TERROR: \"ALIENÍGENAS LANÇAM{NEWLINE}ATAQUE NO PORTO\"\n  STR_PORT_TERROR: \"ALIENÍGENAS LANÇAM ATAQUE NO PORTO DE\"\n  STR_PORT_TERROR_BRIEFING: \"Os alienígenas lançaram um ataque contra uma zona portuária. Todos os civis e infraestruturas encontram-se em sério risco. O nosso objetivo é eliminar as forças alienígenas e proteger todos os civis inocentes. Para sair, leve os aquanautas ao aerosubmarino e clique no ícone \\\"Abortar Missão\\\".\"\n  STR_ALIENS_LAUNCH_ISLAND_TERROR: \"ALIENÍGENAS LANÇAM{NEWLINE}ATAQUE NA ILHA\"\n  STR_ISLAND_TERROR: \"ALIENÍGENAS LANÇAM ATAQUE À ILHA\"\n  STR_ISLAND_TERROR_BRIEFING: \"Os alienígenas lançaram um ataque contra uma ilha. Toda a população civil encontra-se em risco. Seu esquadrão deve eliminar as forças alienígenas e proteger todos os civis inocentes dessa incursão alienígena. Para sair, leve os aquanautas ao aerosubmarino e clique no ícone \\\"Abortar Missão\\\".\"\n  STR_ALIENS_ATTACK_SHIPPING_ROUTE: \"ATAQUE ALIENÍGENA{NEWLINE}ROTA DE TRANSPORTE\"\n  STR_CARGO_SHIP_P1: \"NAVIO DE CARGA - PARTE 1\"\n  STR_CARGO_SHIP_P2: \"NAVIO DE CARGA - PARTE 2\"\n  STR_CRUISE_SHIP_P1: \"CRUZEIRO - PARTE 1\"\n  STR_CRUISE_SHIP_P2: \"CRUZEIRO - PARTE 2\"\n  STR_SHIP_RESCUE_MISSION: \"MISSÃO DE RESGATE DE NAVIO\"\n  STR_SHIP_RESCUE_P1_BRIEFING: \"Esta é uma missão de extermínio. O nosso objetivo é eliminar todas as forças alienígenas no navio e proteger quaisquer civis que encontremos a bordo. Os alienígenas estão espalhados por todo o navio e é essencial eliminar todas as unidades inimigas no convés antes de descermos aos níveis inferiores. Para sair, leve os aquanautas ao aerosubmarino e clique no ícone \\\"Abortar Missão\\\".\"\n  STR_SHIP_RESCUE_P2_BRIEFING: \"Após eliminarmos as forças inimigas no convés, podemos finalmente prosseguir para os pisos inferiores. As nossas tropas desceram até o porão através do elevador de carga. Temos que eliminar todos os alienígenas neste nível para concluirmos a missão com sucesso. Para abortar a missão, retorne os aquanautas ao elevador de acesso e clique no ícone \\\"Abortar missão\\\".\"\n  STR_ALIEN_ACTIVITY_DETECTED: \"ATIVIDADE ALIENÍGENA DETECTADA\"\n  STR_ALIEN_CONTACT_SITE_MISSION: \"LOCAL DE CONTATO ALIENÍGENA\"\n  STR_ARTIFACT_SITE_P1: \"ARTEFATO ALIENÍGENA - PARTE 1\"\n  STR_ARTIFACT_SITE_P1_BRIEFING: \"Essa missão é um ataque a uma estação de comunicação recém ativada.  Existem 2 níveis na estação, o fundo do mar com suas pirâmides alienígenas e um complexo alienígena escondido.  Leve todos os aquanautas à entrada do complexo e clique no ícone \\\"Abortar Missão\\\" para prosseguir.  Para sair, leve os aquanautas ao aerosubmarino e clique no ícone \\\"Abortar Missão\\\".\"\n  STR_ARTIFACT_SITE_P2: \"ARTEFATO ALIENÍGENA - PARTE 2\"\n  STR_ARTIFACT_SITE_P2_BRIEFING: \"Tendo negociado as estruturas alienígenas e entrado no complexo, os objetivos da missão são claros.  Penetrar no coração da instalação alienígena e destruir o Dispositivo de Controle Molecular Synomium para completar a missão.  Para abortar coloque todos os aquanautas no elevador de acesso e clique no ícone \\\"Abortar Missão\\\".\"\n  STR_SIGSBEE_DEEP_MISSION: \"MISSÃO SUBMARINA EM SIGSBEE{NEWLINE}CIDADE ALIENÍGENA NÍVEL UM\"\n  STR_TLETH_P1_BRIEFING: \"Estamos entrando no desconhecido, daqui em diante pode haver qualquer coisa esperando por nós.  Sabemos que há mais 2 níveis na cidade alienígena e seu esquadrão deve correr para a saída desse nível para entrar no próximo.  Leve todos os aquanautas à saída e clique no ícone \\\"Abortar Missão\\\" para avançar.  Abortar em outro lugar irá cancelar a missão.\"\n  STR_TLETH_ATTACK_MISSION: \"MISSÃO DE ATAQUE À T'LETH{NEWLINE}CIDADE ALIENÍGENA NÍVEL DOIS\"\n  STR_TLETH_P2_BRIEFING: \"Seguimos avançando no desconhecido, daqui em diante pode haver qualquer coisa esperando por nós.  Sabemos que há mais um nível na cidade alienígena e seu esquadrão deve correr para a saída desse nível para entrar no próximo.  Leve todos os aquanautas à saída e clique no ícone \\\"Abortar Missão\\\" para avançar.  Abortar em outro lugar irá cancelar a missão.\"\n  STR_FINAL_TLETH_MISSION: \"MISSÃO FINAL T'LETH{NEWLINE}CIDADE ALIENÍGENA NÍVEL TRÊS\"\n  STR_TLETH_P3_BRIEFING: \"O final está próximo, de agora em diante estamos buscando a cripta do Alienígena Supremo.  Destrua os 8 alimentadores de força da tumba para eliminar a ameaça alienígena.  Não desista agora!  Abortar irá encerrar a missão.\"\n  STR_TLETH_P1: \"CIDADE ALIENÍGENA NÍVEL UM\"\n  STR_TLETH_P2: \"CIDADE ALIENÍGENA NÍVEL DOIS\"\n  STR_TLETH_P3: \"CIDADE ALIENÍGENA NÍVEL TRÊS\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"NÃO HÁ DOCAS LIVRES PARA A PRODUÇÃO!{SMALLLINE}Cada aerosubmarino atribuído a uma base, transferido para uma base, comprado ou construído ocupa uma doca. Construa uma nova doca ou transfira um submarino para outra base.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"NÃO HÁ DOCAS LIVRES PARA EFETUAR A COMPRA!{SMALLLINE}Cada aerosubmarino atribuído a uma base, transferido para uma base, comprado ou construído ocupa uma doca. Construa uma nova doca ou transfira um submarino para outra base.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"NÃO HÁ DOCAS LIVRES PARA A TRANSFERÊNCIA!{SMALLLINE}Cada aerosubmarino atribuído a uma base, transferido para uma base, comprado ou construído ocupa uma doca. Construa uma nova doca ou transfira um submarino para outra base.\"\n  STR_CANNOT_BUILD_HERE: \"IMPOSSÍVEL CONSTRUIR AQUI!{SMALLLINE}Todas as construções devem ser feitas ao lado de uma instalação existente.\"\n  STR_NO_FREE_ACCOMODATION: \"SEM ACOMODAÇÕES DISPONÍVEIS!{SMALLLINE}A base de destino não tem espaço suficiente em alojamentos.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"NÃO HÁ ESPAÇO DE TRABALHO DISPONÍVEL!{SMALLLINE}Construa mais oficinas ou reduza outros projetos.\"\n  STR_NOT_ENOUGH_MONEY: \"DINHEIRO INSUFICIENTE!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"ESPAÇO DE ARMAZENAMENTO INSUFICIENTE!{SMALLLINE}Construa um novo depósito ou transfira equipamentos existentes para outras bases.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"NÃO HÁ HABITAÇÕES SUFICIENTES!{SMALLLINE}Construa novas habitações ou transfira pessoal para outras bases.\"\n  STR_LAUNCH_INTERCEPTION: \"LANÇAR INTERCEPTAÇÃO\"\n  STR_CRAFT: \"SUBMARINO\"\n  STR_STATUS: \"ESTADO\"\n  STR_BASE: \"BASE\"\n  STR_READY: \"PRONTO\"\n  STR_OUT: \"FORA\"\n  STR_REPAIRS: \"REPAROS\"\n  STR_REFUELLING: \"ABASTECENDO\"\n  STR_REARMING: \"REARMANDO\"\n  STR_TARGET: \"ALVO: {0}\"\n  STR_WAY_POINT: \"PONTO DE DESTINO\"\n  STR_ARE_YOU_SURE_CYDONIA: \"Tem a certeza de que deseja enviar este veículo em uma missão a T'leth?\"\n  STR_YES: \"SIM\"\n  STR_NO: \"NÃO\"\n  STR_SELECT_DESTINATION: \"SELECIONE O DESTINO\"\n  STR_CYDONIA: \"T'LETH\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"SELECIONE O LOCAL PARA A NOVA BASE\"\n  STR_RETURN_TO_BASE: \"VOLTAR PARA A BASE\"\n  STR_SELECT_NEW_TARGET: \"SELECIONAR O NOVO ALVO\"\n  STR_PATROL: \"PATRULHAR\"\n  STR_STATUS_: \"ESTADO>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"DANIFICADA - RETORNANDO À BASE\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"POUCO COMBUSTÍVEL - RETORNANDO À BASE\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"MISSÃO COMPLETA - RETORNANDO À BASE\"\n  STR_PATROLLING: \"PATRULHANDO\"\n  STR_TAILING_UFO: \"PERSEGUINDO OSNI\"\n  STR_INTERCEPTING_UFO: \"INTERCEPTANDO OSNI - {0}\"\n  STR_RETURNING_TO_BASE: \"RETORNANDO À BASE\"\n  STR_DESTINATION_UC_: \"DESTINO: {0}\"\n  STR_BASE_UC: \"BASE>{ALT}{0}\"\n  STR_SPEED_: \"VELOCIDADE>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"VELOCIDADE MÁXIMA>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"PROFUNDIDADE>{ALT}{0}\"\n  STR_AIRBORNE: \"TRANSPORTANDO PELO AR\"\n  STR_VERY_LOW: \"RASA\"\n  STR_LOW_UC: \"NORMAL\"\n  STR_HIGH_UC: \"PROFUNDA\"\n  STR_VERY_HIGH: \"MUITO PROFUNDA\"\n  STR_FUEL: \"COMBUSTÍVEL>{ALT}{0}\"\n  STR_WEAPON_ONE: \"ARMA-1>{ALT}{0}\"\n  STR_NONE_UC: \"NENHUMA\"\n  STR_ROUNDS_: \"MUNIÇÃO>{ALT}{0}\"\n  STR_WEAPON_TWO: \"ARMA-2>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"AEROSUBMARINO\"\n  STR_BASE_: \"Base>{0}\"\n  STR_NAME_UC: \"NOME\"\n  STR_AMMO_: \"MUNIÇÃO>{ALT}{0}\"\n  STR_CREW: \"TRIPULAÇÃO\"\n  STR_EQUIPMENT_UC: \"EQUIPAMENTO\"\n  STR_ARMOR: \"ARMADURA\"\n  STR_MAX: \"MÁX>{ALT}{0}\"\n  STR_ROOKIE: \"Marinheiro\"\n  STR_SQUADDIE: \"Marinheiro de Primeira Classe\"\n  STR_SERGEANT: \"Guarda-Marinha\"\n  STR_CAPTAIN: \"Tenente\"\n  STR_COLONEL: \"Comandante\"\n  STR_COMMANDER: \"Capitão\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Selecionar Esquadrão para {0}\"\n  STR_SORT_BY: \"CLASSIFICAR POR...\"\n  STR_ORIGINAL_ORDER: \"ORDEM ORIGINAL\"\n  STR_MISSIONS2: \"MISSÕES\"\n  STR_KILLS2: \"MORTES\"\n  STR_WOUND_RECOVERY2: \"RECUPERAÇÃO DE FERIMENTO\"\n  STR_SPACE_AVAILABLE: \"ESPAÇO DISPONÍVEL>{ALT}{0}\"\n  STR_SPACE_USED: \"ESPAÇO USADO>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"ESPAÇO USADO\"\n  STR_RANK: \"PATENTE\"\n  STR_WOUNDED: \"FERIDO\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Equipamento para {0}\"\n  STR_DEFENSE_VALUE: \"Pontos de Defesa\"\n  STR_HIT_RATIO: \"Taxa de Acerto\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}pronto para{NEWLINE}aterrissar próximo a{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"Começar Missão?\"\n  STR_SELECT_ARMAMENT: \"Selecionar Armamento\"\n  STR_AMMUNITION_AVAILABLE: \"MUNIÇÃO DISPONÍVEL\"\n  STR_ARMAMENT: \"ARMAMENTO\"\n  STR_NOT_AVAILABLE: \"N.D.\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"SELECIONAR ARMADURA PARA{NEWLINE}{ALT}{0}\"\n  STR_TYPE: \"TIPO\"\n  STR_PLASTIC_AQUA_ARMOR_UC: \"ARMADURA DE AQUAPLÁSTICO\"\n  STR_ION_ARMOR_UC: \"ARMADURA DE ÍONS\"\n  STR_MAGNETIC_ION_ARMOR_UC: \"ARMADURA MAGNÉTICA DE ÍONS\"\n  STR_PLASTIC_AQUA_ARMOR_UFOPEDIA: \"Fabricada através da nova substância alienígena, o aquaplástico, esta armadura melhora as hipóteses de sobrevivência dos nossos aquanautas contra os invasores alienígenas.\"\n  STR_ION_ARMOR_UFOPEDIA: \"Uma nova e poderosa proteção para Aquanautas, esta armadura é alimentada por uma fonte de energia ION e amplifica enormemente a velocidade e a força do usuário, oferecendo a melhor proteção para as tropas de combate.\"\n  STR_MAGNETIC_ION_ARMOR_UFOPEDIA: \"Esta versão melhorada da armadura de íons está equipada com um sistema de navegação magnético, que permite a liberdade total de movimento em meios aquáticos.\"\n  STR_SELECT_ARMOR: \"Selecionar Armadura\"\n  STR_NORTH: \"NORTE\"\n  STR_NORTH_EAST: \"NORDESTE\"\n  STR_EAST: \"LESTE\"\n  STR_SOUTH_EAST: \"SUDESTE\"\n  STR_SOUTH: \"SUL\"\n  STR_SOUTH_WEST: \"SUDOESTE\"\n  STR_WEST: \"OESTE\"\n  STR_NORTH_WEST: \"NOROESTE\"\n  STR_SELECT_ACTION: \"SELECIONAR AÇÃO\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"CONTINUAR PERSEGUIÇÃO E INTERCEPTAR\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"PERSEGUIR SEM INTERCEPTAR\"\n  STR_VERY_LARGE: \"MUITO GRANDE\"\n  STR_LARGE: \"GRANDE\"\n  STR_MEDIUM_UC: \"MÉDIO\"\n  STR_SMALL: \"PEQUENO\"\n  STR_VERY_SMALL: \"MUITO PEQUENO\"\n  STR_GROUNDED: \"NO FUNDO DO MAR\"\n  STR_DETECTED: \"Detectado\"\n  STR_SIZE_UC: \"TAMANHO\"\n  STR_ALTITUDE: \"PROFUNDIDADE\"\n  STR_HEADING: \"SENTIDO\"\n  STR_SPEED: \"VELOCIDADE\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"CENTRALIZAR NO OSNI - TEMPO = 5 Segs\"\n  STR_TRACKING_LOST: \"RASTRO PERDIDO\"\n  STR_REDIRECT_CRAFT: \"REDIRECIONAR NAVE\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"IR PARA ÚLTIMA POSIÇÃO CONHECIDA DO ALVO\"\n  STR_UFO_: \"OSNI - {0}\"\n  STR_ALIEN_BASE_: \"COLÔNIA ALIENÍGENA - {0}\"\n  STR_CRASH_SITE_: \"LOCAL DE NAUFRÁGIO - {0}\"\n  STR_LANDING_SITE_: \"LOCAL DE ATERRISSAGEM - {0}\"\n  STR_WAY_POINT_: \"PONTO DE DESTINO - {0}\"\n  STR_TERROR_SITE: \"LOCAL DE TERROR {0}\"\n  STR_ARTIFACT_SITE: \"LOCAL DE ARTEFATOS - {0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}chegou em{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"Patrulhando\"\n  STR_ALIEN_ORIGINS: \"Origens Alienígenas\"\n  STR_THE_ULTIMATE_THREAT: \"A Ameaça Final\"\n  STR_TLETH_ALIEN_CITY: \"T'leth, a Cidade Alienígena\"\n  STR_UFOPAEDIA: \"OSNIpédia\"\n  STR_XCOM_CRAFT_ARMAMENT: \"VEÍCULOS E ARMAMENTO X-COM\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"SISTEMAS DE ARMAMENTOS SUBMERSÍVEIS (SAS)\"\n  STR_WEAPONS_AND_EQUIPMENT: \"EQUIPAMENTO GERAL\"\n  STR_ALIEN_ARTIFACTS: \"ARTEFATOS AQUÁTICOS\"\n  STR_BASE_FACILITIES: \"INSTALAÇÕES X-COM\"\n  STR_ALIEN_LIFE_FORMS: \"CRIATURAS ALIENÍGENAS\"\n  STR_ALIEN_RESEARCH_UC: \"TECNOLOGIA ALIENÍGENA\"\n  STR_UFO_COMPONENTS: \"NOVAS TECNOLOGIAS SUBMERSÍVEIS\"\n  STR_UFOS: \"OSNIS\"\n  STR_SELECT_ITEM: \"SELECIONE O ITEM\"\n  STR_ACCELERATION: \"ACELERAÇÃO>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"COMBUSTÍVEL>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"SISTEMAS DE ARMAS>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"CAPACIDADE DE DANO>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"ESPAÇO DE CARGA>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"CAPACIDADE DE SAS>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Dano\"\n  STR_RANGE: \"Alcance\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Precisão\"\n  STR_RE_LOAD_TIME: \"Tempo de Recarga\"\n  STR_SECONDS: \"{0}s\"\n  STR_DAMAGE_ARMOR_PIERCING: \"PERFURANTE\"\n  STR_DAMAGE_INCENDIARY: \"FÓSFORO\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"EXPLOSIVO\"\n  STR_DAMAGE_LASER_BEAM: \"RAIO GAUSS\"\n  STR_DAMAGE_PLASMA_BEAM: \"RAIO SÔNICO\"\n  STR_DAMAGE_STUN: \"CONGELAR\"\n  STR_DAMAGE_MELEE: \"CORPO-A-CORPO\"\n  STR_DAMAGE_ACID: \"ÁCIDO\"\n  STR_DAMAGE_SMOKE: \"FUMAÇA\"\n  STR_SHOT_TYPE: \"TIPO\"\n  STR_ACCURACY_UC: \"PRECISÃO\"\n  STR_TIME_UNIT_COST: \"CUSTO UT\"\n  STR_DAMAGE_UC: \"DANO\"\n  STR_AMMO: \"MUNIÇÃO\"\n  STR_SHOT_TYPE_AUTO: \"Rajada\"\n  STR_SHOT_TYPE_SNAP: \"Simples\"\n  STR_SHOT_TYPE_AIMED: \"Preciso\"\n  STR_CONSTRUCTION_TIME: \"Tempo de Construção\"\n  STR_CONSTRUCTION_COST: \"Custo de Construção\"\n  STR_MAINTENANCE_COST: \"Custo de Manutenção\"\n  STR_LOW: \"Baixo\"\n  STR_MEDIUM: \"Médio\"\n  STR_HIGH: \"Alto\"\n  STR_CRAFT_WEAPON: \"Arma Submarina\"\n  STR_CRAFT_AMMUNITION: \"Munição Submarina\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Sistema de Armas Pesadas\"\n  STR_WEAPON: \"Armamento\"\n  STR_AMMUNITION: \"Munição\"\n  STR_EQUIPMENT: \"Equipamento\"\n  STR_ALIEN_CORPSE: \"Cadáver Alienígena\"\n  STR_UFO_COMPONENT: \"Componente do OSNI\"\n  STR_PERSONAL_ARMOR: \"Armadura de Aquaplástico\"\n  STR_RAW_MATERIALS: \"Matérias Primas\"\n  STR_HWP_SOLID_HARPOON_BOLTS: \"Parafusos Sólidos para Arpão\"\n  STR_ALIEN: \"Alienígena\"\n  STR_AQUATOID: \"Aquatoide\"\n  STR_GILLMAN: \"Homem-Brânquia\"\n  STR_LOBSTERMAN: \"Homem-Lagosta\"\n  STR_TASOTH: \"Tasoth\"\n  STR_CALCINITE: \"Calcinite\"\n  STR_DEEP_ONE: \"Ser das Profundezas\"\n  STR_BIODRONE: \"Biodrone\"\n  STR_TENTACULAT: \"Tentaculate\"\n  STR_TRISCENE: \"Triscênio\"\n  STR_HALLUCINOID: \"Alucinoide\"\n  STR_XARQUID: \"Xarquídeo\"\n  STR_ZOMBIE: \"Zumbi\"\n  STR_LIVE_COMMANDER: \"Comandante\"\n  STR_LIVE_NAVIGATOR: \"Navegador\"\n  STR_LIVE_MEDIC: \"Médico\"\n  STR_LIVE_TECHNICIAN: \"Técnico\"\n  STR_LIVE_SQUAD_LEADER: \"Líder de Esquadrão\"\n  STR_LIVE_SOLDIER: \"Soldado\"\n  STR_LIVE_TERRORIST: \"Terrorista\"\n  STR_AQUATOID_COMMANDER: \"Comandante Aquatoide\"\n  STR_AQUATOID_NAVIGATOR: \"Navegador Aquatoide\"\n  STR_AQUATOID_MEDIC: \"Médico Aquatoide\"\n  STR_AQUATOID_TECHNICIAN: \"Técnico Aquatoide\"\n  STR_AQUATOID_SQUAD_LEADER: \"Líder de Esquadrão Aquatoide\"\n  STR_AQUATOID_SOLDIER: \"Soldado Aquatoide\"\n  STR_GILLMAN_COMMANDER: \"Comandante Homem-Brânquia\"\n  STR_GILLMAN_TECHNICIAN: \"Técnico Homem-Brânquia\"\n  STR_GILLMAN_SQUAD_LEADER: \"Líder de Esquadrão Homem-Brânquia\"\n  STR_GILLMAN_SOLDIER: \"Soldado Homem-Brânquia\"\n  STR_LOBSTERMAN_COMMANDER: \"Comandante Homem-Lagosta\"\n  STR_LOBSTERMAN_NAVIGATOR: \"Navegador Homem-Lagosta\"\n  STR_LOBSTERMAN_TECHNICIAN: \"Técnico Homem-Lagosta\"\n  STR_LOBSTERMAN_SQUAD_LEADER: \"Líder de Esquadrão Homem-Lagosta\"\n  STR_LOBSTERMAN_SOLDIER: \"Soldado Homem-Lagosta\"\n  STR_TASOTH_SQUAD_LEADER: \"Líder de Esquadrão Tasoth\"\n  STR_TASOTH_SOLDIER: \"Soldado Tasoth\"\n  STR_CALCINITE_TERRORIST: \"Terrorista Calcinite\"\n  STR_DEEP_ONE_TERRORIST: \"Ser das Profundezas Terrorista\"\n  STR_BIODRONE_TERRORIST: \"Terrorista Biodrone\"\n  STR_TENTACULAT_TERRORIST: \"Terrorista Tentaculate\"\n  STR_TRISCENE_TERRORIST: \"Terrorista Triscênio\"\n  STR_HALLUCINOID_TERRORIST: \"Terrorista Alucinoide\"\n  STR_XARQUID_TERRORIST: \"Terrorista Xarquídeo\"\n  STR_ION_BEAM_ACCELERATORS: \"Aceleradores de Íons\"\n  STR_MAGNETIC_NAVIGATION: \"Sistema de Navegação Magnético\"\n  STR_ALIEN_SUB_CONSTRUCTION: \"Métodos de Construção OSNI\"\n  STR_ALIEN_CRYOGENICS: \"Criogenia Alienígena\"\n  STR_ALIEN_CLONING: \"Clonagem Alienígena\"\n  STR_ALIEN_LEARNING_ARRAYS: \"Matrizes de Aprendizagem Alienígena\"\n  STR_ALIEN_IMPLANTER: \"Implantador Alienígena\"\n  STR_EXAMINATION_ROOM: \"Sala de Exames\"\n  STR_AQUA_PLASTICS: \"Aquaplástico\"\n  STR_ALIEN_REANIMATION_ZONE: \"Área de Reanimação Alienígena\"\n  STR_PLASTIC_AQUA_ARMOR: \"Armadura de Aquaplástico\"\n  STR_ION_ARMOR: \"Armadura Íon\"\n  STR_MAGNETIC_ION_ARMOR: \"Armadura Mag. de Íons\"\n  STR_HWP_AQUA_JET_MISSILES: \"Torpedos Aquajato\"\n  STR_HWP_DISPLACER_PWT: \"Torpedo de Ondas de Impulsos\"\n  STR_GAUSS_TECH: \"Tecnologia Gauss\"\n  STR_NEW_FIGHTER_FLYING_SUB: \"Novo Caça Aerosubmarino\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Novo Caça-Transportador\"\n  STR_THE_LATEST_FLYING_SUB: \"O Último Aerosubmarino\"\n  STR_ARMOR_PIERCING: \"PERFURANTE\"\n  STR_COELACANTH_GAS_CANNON: \"Celacanto/Canhão de Gás\"\n  STR_COELACANTH_AQUA_JET: \"Celacanto/Aquajato\"\n  STR_COELACANTH_GAUSS: \"Celacanto/Gauss\"\n  STR_DISPLACER_SONIC: \"Deslocador/Canhão Sônico\"\n  STR_DISPLACER_PWT: \"Deslocador/T.O.I\"\n  STR_AJAX_LAUNCHER: \"Lançador Ajax\"\n  STR_DUP_HEAD_LAUNCHER: \"Lançador O.U.E.\"\n  STR_CRAFT_GAS_CANNON: \"Canhão de Gás Pesado\"\n  STR_PWT_CANNON: \"Canhão T.O.I\"\n  STR_GAUSS_CANNON: \"Canhão Gauss\"\n  STR_GAUSS_CANNON_AMMO: \"Munição para Canhão Gauss\"\n  STR_SONIC_OSCILLATOR: \"Oscilador Sônico\"\n  STR_AJAX_TORPEDOES: \"Torpedos Ajax\"\n  STR_DUP_HEAD_TORPEDOES: \"Torpedos de Urânio\"\n  STR_CRAFT_GAS_CANNON_ROUNDS_X50: \"Cartuchos de Gás(x50)\"\n  STR_SONIC_WAVE: \"Onda Sônica\"\n  STR_PULSE_WAVE_TORPEDOES: \"Munição T.O.I\"\n  STR_SOLDIER: \"Aquanauta\"\n  STR_SCIENTIST: \"Cientistas\"\n  STR_ENGINEER: \"Técnicos\"\n  STR_NORTH_ATLANTIC: \"Atlântico Norte\"\n  STR_SOUTH_ATLANTIC: \"Atlântico Sul\"\n  STR_NORTH_PACIFIC: \"Pacífico Norte\"\n  STR_SOUTH_PACIFIC: \"Pacífico Sul\"\n  STR_MEDITERRANEAN: \"Mediterrâneo\"\n  STR_SOUTH_CHINA_SEA: \"Mar do Sul da China\"\n  STR_INDIAN_OCEAN: \"Oceano Índico\"\n  STR_THE_EAST_SEA: \"Mar do Japão\"\n  STR_NORTH_SEA: \"Mar do Norte\"\n  STR_CARRIBEAN: \"Caribe\"\n  STR_ANTARCTIC: \"Antártico\"\n  STR_ARCTIC: \"Ártico\"\n  STR_EURASIA: \"Eurásia\"\n  STR_NORTH_AMERICA: \"América do Norte\"\n  STR_AFRICA: \"África\"\n  STR_MAXIMUM_SPEED: \"Velocidade Máxima\"\n  STR_TRANSMISSION_RESOLVER_UC: \"IDENTIFICADOR DE TRANSMISSÕES\"\n  STR_TRITON: \"TRITÃO\"\n  STR_HAMMERHEAD: \"HAMMERHEAD\"\n  STR_LEVIATHAN: \"LEVIATHAN\"\n  STR_BARRACUDA: \"BARRACUDA\"\n  STR_MANTA: \"MANTA\"\n  STR_UFO: \"OSNI\"\n  STR_AJAX: \"AJAX\"\n  STR_DUP_HEAD: \"TORPEDO DE URÂNIO\"\n  STR_CRAFT_GAS_CANNON_UC: \"CANHÃO DE GÁS PES.\"\n  STR_PWT_CANNON_UC: \"CANHÃO T.O.I\"\n  STR_GAUSS_CANNON_UC: \"CANHÃO GAUSS\"\n  STR_SONIC_OSCILLATOR_UC: \"OSCILADOR SÔNICO\"\n  STR_DAMAGE_CAPACITY: \"Capacidade de Dano\"\n  STR_WEAPON_POWER: \"Poder de Fogo\"\n  STR_WEAPON_RANGE: \"Alcance do Armamento\"\n  STR_AIR_LOCK: \"Câmara Pressurizada\"\n  STR_LABORATORY: \"Laboratório\"\n  STR_WORKSHOP: \"Oficina\"\n  STR_STANDARD_SONAR: \"Sonar Padrão\"\n  STR_WIDE_ARRAY_SONAR: \"Sonar de Longo Alcance\"\n  STR_TORPEDO_DEFENSES: \"Defesas de Torpedos\"\n  STR_GENERAL_STORES: \"Depósito\"\n  STR_ALIEN_CONTAINMENT: \"Contentor de Alienígena\"\n  STR_GAUSS_DEFENSES: \"Defesas de Gauss\"\n  STR_SONIC_DEFENSES: \"Defesas Sônicas\"\n  STR_PWT_DEFENSES: \"Defesas T.O.I\"\n  STR_BOMBARDMENT_SHIELD: \"Escudo de Bombardeamento\"\n  STR_MC_GENERATOR: \"Gerador de C.M.\"\n  STR_MC_LAB: \"Laboratório de C.M.\"\n  STR_TRANSMISSION_RESOLVER: \"Identificador de Transmissões\"\n  STR_SUB_PEN: \"Doca\"\n  STR_USA: \"EUA\"\n  STR_ALASKA: \"Alasca\"\n  STR_EU_SYNDICATE: \"Euro-Sindicato\"\n  STR_ARABIAN_BLOC: \"Bloco Árabe\"\n  STR_EGYPTIAN_CARTEL: \"Cartel Egípcio\"\n  STR_AFRICA_CORP: \"Corporação Africana\"\n  STR_BRAZILIAN_UNION: \"União Brasileira\"\n  STR_NEW_MEXICO: \"Novo México\"\n  STR_ASIAN_COALITION: \"Coalizão Asiática\"\n  STR_SCANDINAVIA: \"Escandinávia\"\n  STR_NEO_JAPAN: \"Novo Japão\"\n  STR_FREE_CHINA: \"China Livre\"\n  STR_AUSTRALASIA: \"Australásia\"\n  STR_FED_KOREA: \"Federação Coreana\"\n  STR_EURASIA_UC: \"Eurásia\"\n  STR_ICELANDIC_UNION: \"União Islandesa\"\n  STR_TANK: \"Sistema de Armas Submersíveis\"\n  STR_CIVILIAN: \"Civis\"\n  STR_JAN: \"Jan\"\n  STR_FEB: \"Fev\"\n  STR_MAR: \"Mar\"\n  STR_APR: \"Abr\"\n  STR_MAY: \"Mai\"\n  STR_JUN: \"Jun\"\n  STR_JUL: \"Jul\"\n  STR_AUG: \"Ago\"\n  STR_SEP: \"Set\"\n  STR_OCT: \"Out\"\n  STR_NOV: \"Nov\"\n  STR_DEC: \"Dez\"\n  STR_INTERNATIONAL_RELATIONS: \"Relações Internacionais\"\n  STR_COUNTRY: \"Organização\"\n  STR_FUNDING: \"Finanças\"\n  STR_CHANGE: \"Alteração\"\n  STR_WEAPON_SYSTEMS: \"SISTEMAS DE ARMAS\"\n  STR_HWPS: \"SAS\"\n  STR_DAMAGE_UC_: \"DANO>{ALT}{0}\"\n  STR_AIR_LOCK_UFOPEDIA: \"A câmara pressurizada permite a transferência de equipamento e pessoal para dentro ou para fora da base subaquática. É sempre a primeira instalação a ser construída em uma nova base. Este compartimento é vulnerável e pode ser invadido.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Cada bloco habitacional pode alojar o máximo de 50 pessoas. Estas instalações são básicas, mas funcionais.\"\n  STR_LABORATORY_UFOPEDIA: \"Estas instalações estão equipadas com a mais recente tecnologia para investigação de materiais, bioquímica e armamento, dispondo de acesso privilegiado às bases de dados dos melhores centros de investigação do planeta, tanto civis como militares. Cada laboratório possuí espaço de trabalho suficiente para 50 cientistas. \"\n  STR_WORKSHOP_UFOPEDIA: \"As oficinas dispõem de todo o equipamento necessário para fabricar produtos baseados nos projetos elaborados pelos laboratórios. Cada oficina possuí espaço de trabalho suficiente para 50 técnicos, mas os processos de fabricação de produtos podem também ocupar algum espaço adicional.\"\n  STR_STANDARD_SONAR_UFOPEDIA: \"Este sistema de detecção por sonar tem um alcance de 450 km a todas as profundidades e está ligado a uma rede de satélites geoestacionários para detecção à superfície. Cada sistema tem a probabilidade de 10% de detectar um veículo submerso ou à superfície por cada ciclo de 30 minutos.\"\n  STR_WIDE_ARRAY_SONAR_UFOPEDIA: \"Este sistema de detecção por sonar tem um alcance de 700 km a todas as profundidades e está ligado a uma rede de satélites geoestacionários para detecção à superfície. Cada sistema tem a probabilidade de 20% de detectar um veículo submerso ou à superfície por cada ciclo de 30 minutos.\"\n  STR_TORPEDO_DEFENSES_UFOPEDIA: \"Estes torpedos defensivos proporcionam alguma proteção contra incursões de submersíveis hostis que tentem ancorar perto da base.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"Todos os equipamentos, sistemas de armas, munições, material recuperado e Sistemas de Armas Submersíveis são guardados nos depósitos, incluindo o equipamento atribuído a submarinos na doca.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"É provável que alienígenas capturados com vida necessitem de ser mantidos em áreas de contenção especiais, a fim de preservar os seus sistemas vitais e eliminar quaisquer riscos possíveis. Estas instalações podem manter até dez formas de vida alienígena em unidades de contenção individuais.\"\n  STR_GAUSS_DEFENSES_UFOPEDIA: \"Estes sistemas de defesa Gauss proporcionam a proteção mais recente e eficaz contra incursões de naves inimigas. \"\n  STR_SONIC_DEFENSES_UFOPEDIA: \"Estes sistemas de defesa de oscilação sônica proporcionam uma proteção poderosa e eficiente contra forças hostis. \"\n  STR_PWT_DEFENSES_UFOPEDIA: \"Os torpedos de ondas de pulsão proporcionam o sistema de defesa mais eficaz contra ataques alienígenas. Estes projéteis subaquáticos geram ondas magnéticas capazes de desativar sistemas de defesa eletrônicos e possuem ogivas incrivelmente densas que penetram todos os tipos de blindagem. \"\n  STR_BOMBARDMENT_SHIELD_UFOPEDIA: \"O Escudo de Bombardeio de Pressão protege a base de submarinos alienígenas que tentem atracar e gera um campo de ressonância durante tempo suficiente para que os sistemas de defesa atirem repetidamente, duplicando a eficácia dos sistemas de defesa já instalados.\"\n  STR_MC_GENERATOR_UFOPEDIA: \"Como os submarinos alienígenas utilizam Tecnologia de Controle Molecular para detectar a presença de outros seres vivos, usar com um emissor de C.M. negativo protege uma base com um escudo impenetrável para confundir os alienígenas e ocultar a nossa presença. \"\n  STR_MC_LAB_UFOPEDIA: \"O laboratório de Controle Molecular pode implantar e treinar até dez aquanautas de cada vez. Implantes são inseridos cirurgicamente nos crânios dos aquanautas. Treinamento intensivo permitem o uso dos implantes em conjunto com um Dispositivo Molecular que podem ser usados para ataque em situações de combate.\"\n  STR_TRANSMISSION_RESOLVER_UFOPEDIA: \"Os sistemas de comunicação alienígenas utilizam redes de implantação molecular. Esta instalação intercepta transmissões feitas por OSNIs e descodifica a informação, o que permite identificar o tipo de OSNI, a espécie da tripulação e o tipo de missão a que se destina.\"\n  STR_SUB_PEN_UFOPEDIA: \"Cada doca pode abrigar um aerosubmarino, dispondo de instalações próprias para manutenção, abastecimento e reparação. Um aerosubmarino atribuído a uma base deverá dispor de uma doca exclusiva. Mesmo que um submarino esteja fora em missão, a sua doca não pode ser utilizada por outros submarinos.\"\n  STR_DART_PISTOL_UFOPEDIA: \"A pistola de dardos X-Com é uma unidade pequena, certeira e poderosa, com capacidade para 12 dardos ocos. Os dardos são disparados por um cartucho de gás alojado no cartucho de munição.\"\n  STR_JET_HARPOON_UFOPEDIA: \"Este rifle é uma arma precisa e mortífera, que dispara arpões de aço em carregadores de 10 unidades. Cada arpão possui um reservatório de gás individual.\"\n  STR_GAS_CANNON_UFOPEDIA: \"O peso pesado das armas de gás, este canhão dispara projéteis sólidos com a ponta altamente explosiva (AE) ou de fósforo; a preferida dos aquanautas.\"\n  STR_HYDRO_JET_CANNON_UFOPEDIA: \"Canhões de Hidrojato são um sistema de armamento pesado de infantaria.  O canhão dispara mini-torpedos abastecidos com magnésio.  Embora poderoso, o Canhão de Hidrojato é um dispositivo grande e desajeitado, adequado apenas para uso subaquático.\"\n  STR_TORPEDO_LAUNCHER_UFOPEDIA: \"Muito pesado, este lançador grande funciona com três tipos de torpedo, cada um equipado com sua própria unidade de propulsão.  É uma arma devastadora, mas sua desvantagem é o carregamento manual. Os tipos de munição disponíveis incluem projéteis explosivos de carga grande ou pequena, e um projétil incendiário com carga de fósforo, todos para uso exclusivo em ambientes submersos.\"\n  STR_GAUSS_PISTOL_UFOPEDIA: \"A pistola Gauss usa tecnologia de aceleração de partículas, um novo desenvolvimento no armamento moderno. É rápida, certeira, e funciona acima e abaixo da água. A tecnologia Gauss é um desenvolvimento das tecnologias Plasma estudadas na guerra anterior.\"\n  STR_GAUSS_PISTOL_CLIP_UFOPEDIA: \"A pistola Gauss usa tecnologia de aceleração de partículas, um novo desenvolvimento no armamento moderno. É rápida, certeira, e funciona acima e abaixo da água. A tecnologia Gauss é um desenvolvimento das tecnologias Plasma estudadas na guerra anterior.\"\n  STR_GAUSS_RIFLE_UFOPEDIA: \"Um passo além da pistola Gauss, o rifle causa bastante danos com seus aceleradores de partículas duplos. O sistema Plasma alimentado a Elério foi substituído por um micro acelerador de partículas que gera um fluxo de anti-prótons.\"\n  STR_GAUSS_RIFLE_CLIP_UFOPEDIA: \"Um passo além da pistola Gauss, o rifle causa bastante danos com seus aceleradores de partículas duplos. O sistema Plasma alimentado a Elério foi substituído por um micro acelerador de partículas que gera um fluxo de anti-prótons.\"\n  STR_HEAVY_GAUSS_UFOPEDIA: \"O Canhão Gauss Pesado é desajeitado, mas extremamente efetivo.  Ele opera com 3 aceleradores de partículas e é virtualmente impossível de parar.  O fluxo de anti-prótons é confinado dentro de um cartucho de Arsenieto de Gálio que implode no impacto liberando a anti-matéria.\"\n  STR_HEAVY_GAUSS_CLIP_UFOPEDIA: \"O Canhão Gauss Pesado é desajeitado, mas extremamente efetivo.  Ele opera com 3 aceleradores de partículas e é virtualmente impossível de parar.  O fluxo de anti-prótons é confinado dentro de um cartucho de Arsenieto de Gálio que implode no impacto liberando a anti-matéria.\"\n  STR_MAGNA_BLAST_GRENADE_UFOPEDIA: \"Esta granada padrão possuí um temporizador sofisticado que permite um controle preciso.\"\n  STR_DYE_GRENADE_UFOPEDIA: \"A granada de tinta é um dispositivo de suporte, utilizado para criar cobertura em áreas expostas durante situações de combate. A tinta é ejetada através de uma nuvem de partículas que produz um jato de tinta dentro d’água e uma cortina de fumaça na superfície.\"\n  STR_PARTICLE_DISTURBANCE_GRENADE_UFOPEDIA: \"Funciona como uma granada normal, mas é apenas detonada caso detecte movimento na área onde é lançada. Utilize com extremo cuidado.\"\n  STR_MAGNA_PACK_EXPLOSIVE_UFOPEDIA: \"Este explosivo foi originalmente concebido para demolições, mas experiências passadas revelaram que são armas ideais para desalojar alienígenas. Devido ao grande raio de explosão, garanta todos os aquanautas estejam a uma distância segura antes da detonação.\"\n  STR_PARTICLE_DISTURBANCE_SENSOR_UFOPEDIA: \"Este aparelho utiliza uma série de detectores e sistemas para identificar unidades inimigas em movimento. Clique no ícone do sensor de partículas no menu tático e selecione \\\"Usar Sensor\\\". O mostrador aparecerá na tela, indicando com uma seta ao centro a direção para a qual o aquanauta está virado (o norte corresponde à aresta superior). As manchas indicam unidades que se moveram recentemente. Criaturas maiores ou mais rápidas geram manchas mais largas. Unidades estáticas não serão detectadas.\"\n  STR_MEDI_KIT_UFOPEDIA: \"Para usar o kit médico, o agente deve estar virado de frente para a vítima a ser tratada ou posicionado sobre o corpo da mesma, caso esteja inconsciente. {NEWLINE}CURA> Selecione a parte do corpo a tratar e clique no botão \\\"Cura\\\". Um ferimento grave será curado por cada uso, e a vítima recuperará alguns pontos de vida.{NEWLINE}ESTIMULANTE> O uso de estimulantes recupera pontos de energia e reanima tropas inconscientes. Não se esqueça de posicionar o agente sobre o corpo da vítima caso esta esteja inconsciente.{NEWLINE} ANALGÉSICO> Os analgésicos recuperam a moral de agentes feridos.\"\n  STR_MC_DISRUPTOR_UFOPEDIA: \"O que há de melhor em tecnologia de Controle Molecular. Só pode ser usado por aquanautas com habilidades em C.M. Pressione no Disruptor, escolha um tipo de ataque e selecione um alvo com o cursor. Há 2 tipos de ataques:{NEWLINE}INTERFERIR IMPLANTE> Se o ataque tiver êxito, reduzirá a moral do alvo com a probabilidade de induzir pânico.{NEWLINE}CONTROLAR IMPLANTE> Se este ataque for bem sucedido, você ganha o controle da unidade inimiga.\"\n  STR_THERMAL_TAZER_UFOPEDIA: \"Esta arma térmica é capaz de neutralizar um inimigo de forma não letal, mas só pode ser utilizada em combate corpo a corpo.\"\n  STR_VIBRO_BLADE_UFOPEDIA: \"A Vibrolâmina é uma arma branca longa e afiada cuja lâmina é feita de titânio. Gira a mais de 600 rpm e pode perfurar até a blindagem mais dura. Sua fonte de poder é de invenção alienígena. Nossas tentativas de fabricar uma arma deste tipo, fracassaram: as lâminas giravam muito devagar ou explodiam com a pressão.\"\n  STR_THERMIC_LANCE_UFOPEDIA: \"A Lança Térmica é uma extensão lógica da tecnologia Vibrolâmina. A lâmina gira em alta velocidade e uma fonte de energia Zrbita superaquece a lâmina para cortar a armadura como uma faca quente na manteiga.\"\n  STR_HEAVY_THERMIC_LANCE_UFOPEDIA: \"A Lança Térmica Pesada é uma versão mais poderosa da lança térmica normal. Duas fontes de calor e uma assombrosa velocidade de rotação fazem com que esta lança atravesse qualquer tipo de material.\"\n  STR_SONIC_CANNON_UFOPEDIA: \"O Canhão Sônico é a arma mais poderosa do arsenal sônico. A sua câmara de reverberação é maior e o seu oscilador de áudio tem maior faixa que os da Espingarda Sônica. O Canhão também tem um sistema de pulso-detonação que altera as ondas ultrassônicas por modulação para produzir um Choque Sônico mais eficaz.\"\n  STR_CANNON_POWER_CLIP_UFOPEDIA: \"Este dispositivo compacto é utilizado como munição para o Canhão Sônico. Contém uma pequena quantidade de Zrbite. \"\n  STR_SONIC_BLASTA_RIFLE_UFOPEDIA: \"Um dispositivo Sônico mais poderoso.  Nem o aço de alto carbono é imune a esta arma.  O emissor de ondas altamente compacto foi aperfeiçoado com um amplificador supercondutor para aumentar o poder desta arma.\"\n  STR_BLASTA_POWER_CLIP_UFOPEDIA: \"Este pequeno objeto é utilizado como fonte de energia para o Rifle Sônico, uma poderosa arma alienígena, e contém uma pequena quantidade de Zrbite. \"\n  STR_SONIC_PISTOL_UFOPEDIA: \"Pistolas Sônicas são armas alienígenas que disparam ondas ultrassônicas capazes de amolecer ossos em segundos. Estas ondas estão em uma faixa além do limite da audição humana.\"\n  STR_PISTOL_POWER_CLIP_UFOPEDIA: \"Fonte de energia para a pistola sônica alienígena. Contém Zrbite, a fonte de toda a energia alienígena.\"\n  STR_DISRUPTOR_PULSE_LAUNCHER_UFOPEDIA: \"É uma arma alienígena aquática que lança 'Projéteis Disruptores' auto impulsionados e dirigíveis. Ao clicar para disparar a arma, aparecerão pontos no mapa que indicam o rumo do projétil. Quando tiver posicionado os pontos suficientes, clique no ícone de lançar projéteis.\"\n  STR_DISRUPTOR_AMMO_UFOPEDIA: \"Este dispositivo é um Projétil de Pulso Disruptor equipada com um computador de orientação interno. É disparado por um lançador de Pulso Disruptor.\"\n  STR_THERMAL_SHOK_LAUNCHER_UFOPEDIA: \"Pequeno Lançador de Choque Térmico que dispara bombas de congelamento. Muito útil para capturar Alienígenas vivos.\"\n  STR_THERMAL_SHOK_BOMB_UFOPEDIA: \"A bomba de Choque Térmico é usada para capturar humanos vivos, mas também pode ser usada contra a maioria das raças alienígenas. É disparado de um Lançador de Choque Térmico.\"\n  STR_SONIC_PULSER_UFOPEDIA: \"Este dispositivo funciona como uma granada comum - exceto por ser muitas vezes mais poderosa. A granada utiliza uma única detonação de pulso sônico que é emitida simultaneamente em todas as direções.\"\n  STR_MC_READER_UFOPEDIA: \"Dentro dos corpos dos Alienígenas nós encontramos pequenas unidades implantadas. São os Implante de Controle criados pelos Aquatoides, que permitem a provisão constante de informações do campo de batalha, inclusive a grandes distâncias. O Leitor de Controle Molecular é um aparelho de comunicações alienígena que extrai informação dos implantes pelo C.M.; as unidades X-Com podem usar este dispositivo em combate para ver as características de um alienígena. Selecione a opção 'Usar' e em seguida clique com o cursor em um alienígena.\"\n  STR_SURVEY_SHIP: \"Navio de Pesquisa\"\n  STR_ESCORT: \"Nave de Escolta\"\n  STR_CRUISER: \"Cruzador\"\n  STR_HEAVY_CRUISER: \"Cruzador Pesado\"\n  STR_HUNTER: \"Predador\"\n  STR_BATTLESHIP: \"Nave de Batalha\"\n  STR_DREADNOUGHT: \"Couraçado\"\n  STR_FLEET_SUPPLY_CRUISER: \"Cruzador de Abastecimento\"\n  MAP_SEABED: \"Fundo Marinho\"\n  MAP_PIPES: \"Estação Subaquática\"\n  MAP_PLANE: \"Avião Afundado\"\n  MAP_ATLAN: \"Atlântida\"\n  MAP_MU: \"Templo Maia\"\n  MAP_GAL: \"Galeão Afundado\"\n  MAP_MSUNK: \"Cruzeiro Afundado\"\n  MAP_VOLC: \"Vulcão Submarino\"\n  MAP_CORAL: \"Coral\"\n  MAP_PORT: \"Porto\"\n  MAP_ISLAND: \"Ilha\"\n  MAP_CARGO: \"Navio de Carga\"\n  MAP_LINERT: \"Navio de Cruzeiros - Parte 1\"\n  MAP_LINERB: \"Navio de Cruzeiros - Parte 2\"\n  MAP_ALART: \"Artefato P1\"\n  MAP_GRUNGE: \"Artefato P2\"\n  MAP_ENTRY: \"Colônia P1\"\n  MAP_A_BASE: \"Colônia P2\"\n  MAP_ALSHIP: \"T'leth P1\"\n  MAP_LEVEL: \"T'leth P2\"\n  MAP_CRYPT: \"T'leth P3\"\n  MAP_XBASES: \"Base X-Com\"\n  STR_MIXED_CREW: \"Tripulação Mista\"\n  STR_MIXED_CREW_2: \"Tripulação Mista 2\"\n  STR_RATING: \"AVALIAÇÃO> {0}\"\n  STR_RATING_TERRIBLE: \"TERRÍVEL!\"\n  STR_RATING_POOR: \"RUIM!\"\n  STR_RATING_OK: \"OK\"\n  STR_RATING_GOOD: \"BOM!\"\n  STR_RATING_EXCELLENT: \"EXCELENTE!\"\n  STR_SCORE: \"PONTOS\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"RELATÓRIO MENSAL DA X-COM\"\n  STR_MONTH: \"Mês> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"O comitê das organizações financiadoras está satisfeito com o seu progresso atual.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"O comitê das organizações financiadoras está muito satisfeito com os seus excelentes progressos. Continue o bom trabalho.\"\n  STR_COUNCIL_IS_DISSATISFIED: \"O comitê das organizações financiadoras está insatisfeito com os seus resultados. Melhore o seu desempenho em lidar com a ameaça alienígena ou o projeto X-Com será cancelado.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"Como não conseguiu lidar adequadamente com a invasão alienígena o concelho de nações financiadoras decidiu, a muito custo, terminar o projeto X-Com. Cada nação irá lidar com o problema do seu modo. Só nos resta esperar que cheguemos a um acordo com as forças hostis e que a população consiga aceitar os visitantes subaquáticos.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} está particularmente satisfeito com a sua capacidade de lidar com a ameaça localizada e concordou em aumentar o seu financiamento.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} estão particularmente contentes com os seus progressos em lidar com incursões alienígenas locais e concordaram em aumentar a sua contribuição financeira.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} e {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} está descontente com a maneira como lidou com a atividade alienígena na sua área marítima e decidiu diminuir a sua contribuição financeira.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} estão descontentes com a sua incapacidade em lidar com a atividade alienígena nas respectivas áreas marítimas e decidiram reduzir a sua contribuição financeira.\"\n  STR_KNOTS: \"{0} nós\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} assinou um acordo de cooperação com as forças alienígenas e decidiu se retirar do comitê de financiamento X-Com.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} assinaram um acordo de cooperação com as forças alienígenas e decidiram se retirar do comitê de financiamento X-Com.\"\n  STR_MONTHLY_RATING: \"Avaliação Mensal> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Mudanças no financiamento> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"O comitê de financiamento não está satisfeito com a sua posição financeira. Reduza a sua dívida para menos de 1 milhão ou o projeto será cancelado.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"TRANSMISSÃO DE SUB-PARTÍCULAS IDENTIFICADA\"\n  STR_CRAFT_TYPE: \"TIPO DE OSNI\"\n  STR_RACE: \"RAÇA\"\n  STR_MISSION: \"MISSÃO\"\n  STR_ZONE: \"ZONA\"\n  STR_ALLOCATE_RESEARCH: \"Alocar Pesquisa\"\n  STR_ALLOCATE_MANUFACTURE: \"Alocar Produção\"\n  STR_AZORES: \"Açores\"\n  STR_REYKJAVIK: \"Reiquejavique\"\n  STR_BERMUDA: \"Bermuda\"\n  STR_NEW_YORK: \"Nova Iorque\"\n  STR_BOSTON: \"Boston\"\n  STR_FORT_SEVERN: \"Fort Severn\"\n  STR_DAKAR: \"Dacar\"\n  STR_RECIFE: \"Recife\"\n  STR_ACCRA: \"Acra\"\n  STR_ASCENSION_ISLAND: \"Ilha de Ascensão\"\n  STR_TRINIDADE_ISLAND: \"Ilha Trindade\"\n  STR_FALKLAND_ISLAND: \"Ilhas Malvinas\"\n  STR_CANARY_ISLANDS: \"Ilhas Canárias\"\n  STR_ANCHORAGE: \"Anchorage\"\n  STR_ST_LAWRENCE_ISLAND: \"Ilha de São Lourenço\"\n  STR_SAN_FRANCISCO: \"São Francisco\"\n  STR_MIDWAY_ISLAND: \"Ilha de Midway\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_TASMANIA: \"Tasmânia\"\n  STR_HAWAII: \"Havaí\"\n  STR_FIJI: \"Fiji\"\n  STR_TONGA: \"Tonga\"\n  STR_EASTER_ISLAND: \"Ilha de Páscoa\"\n  STR_GALAPAGOS_ISLAND: \"Galápagos\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_SOLOMON_ISLAND: \"Ilhas Salomão\"\n  STR_CRETE: \"Creta\"\n  STR_LISBON: \"Lisboa\"\n  STR_PORT_SAID: \"Porto Said\"\n  STR_MARSEILLES: \"Marselha\"\n  STR_TRIPOLI: \"Trípoli\"\n  STR_MANILA: \"Manila\"\n  STR_HONG_KONG: \"Hong Kong\"\n  STR_SINGAPORE: \"Singapura\"\n  STR_BANGKOK: \"Bancoque\"\n  STR_DARWIN: \"Darwin\"\n  STR_BOMBAY: \"Mumbai\"\n  STR_SAYCHELLES_ISLAND: \"Ilhas Seicheles\"\n  STR_MALDIVE_ISLAND: \"Ilhas Maldivas\"\n  STR_SRI_LANKA: \"Sri Lanka\"\n  STR_MAURITIUS: \"Mauritius\"\n  STR_TOKYO: \"Tóquio\"\n  STR_SHANGHAI: \"Xangai\"\n  STR_VLADIVOSTOK: \"Vladivostok\"\n  STR_LONDON: \"Londres\"\n  STR_FAEROE_ISLAND: \"Ilhas Faroé\"\n  STR_ABERDEEN: \"Aberdeen\"\n  STR_OSLO: \"Oslo\"\n  STR_JAMAICA: \"Jamaica\"\n  STR_PANAMA: \"Panamá\"\n  STR_MIAMI: \"Miami\"\n  STR_PSI_TRAINING: \"Treinamento C.M.\"\n  STR_PSIONIC_TRAINING: \"TREINAMENTO DE CONTROLE MOLECULAR\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Capacidade Restante> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"Força{NEWLINE}C.M.\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"Habilidade C.M.{NEWLINE}/Melhoramento\"\n  STR_IN_TRAINING: \"Em{NEWLINE}Treinamento?\"\n  STR_TARGETTED_BY: \"FOCADO EM:\"\n  STR_WEAPONS_CREW_HWPS: \"ARMAS/{NEWLINE}TRIPULAÇÃO/SAS\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"tem pouco combustível.{NEWLINE}retornando a base\"\n  STR_SOLDIER_LIST: \"Lista de Aquanautas\"\n  STR_RANK_: \"PATENTE> {ALT}{0}\"\n  STR_MISSIONS: \"MISSÕES> {ALT}{0}\"\n  STR_KILLS: \"MORTES> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"RECUPERAÇÃO EM> {ALT}{0}\"\n  STR_TIME_UNITS: \"UNIDADES DE TEMPO\"\n  STR_STAMINA: \"VIGOR\"\n  STR_HEALTH: \"SAÚDE\"\n  STR_BRAVERY: \"BRAVURA\"\n  STR_REACTIONS: \"REAÇÕES\"\n  STR_FIRING_ACCURACY: \"PRECISÃO DE TIRO\"\n  STR_THROWING_ACCURACY: \"PRECISÃO DE ARREMESSO\"\n  STR_STRENGTH: \"FORÇA\"\n  STR_PSIONIC_STRENGTH: \"FORÇA EM C.M.\"\n  STR_PSIONIC_SKILL: \"HABILIDADE EM C.M.\"\n  STR_NEW_RANK: \"NOVA PATENTE\"\n  STR_PROMOTIONS: \"Promoções\"\n  STR_SOLDIERS_UC: \"AQUANAUTAS\"\n  STR_COELACANTH_GAS_CANNON_UFOPEDIA: \"SAS Autônomos têm grande capacidade de manobra e blindagem resistente.  Eles provêm suporte pesado para tropas a todas as profundidades. Os SAS são rearmados automaticamente se houver munição suficiente.\"\n  STR_COELACANTH_AQUA_JET_UFOPEDIA: \"Este submersível está armado com torpedos Aquajato que funcionam exclusivamente sob a água. Certifique-se de que os armazéns dispõe de torpedos suficientes.\"\n  STR_COELACANTH_GAUSS_UFOPEDIA: \"A tecnologia Gauss fornece um arsenal poderoso aos SASs.  Proporcionando poder de fogo pesado quando comparada com modelos anteriores, e usa tecnologia proprietária X-Com.\"\n  STR_DISPLACER_SONIC_UFOPEDIA: \"A tecnologia alienígena redefiniu o SAS. A capacidade de utilizar Deslocadores de Íons significa que os SASs não estão mais restritos à terra e ao leito marinho. O armamento sônico proporciona uma vantagem real em batalha.\"\n  STR_DISPLACER_PWT_UFOPEDIA: \"Este SAS está equipado com armas Ondas de Pulso para uso aquático. Para armar este SAS será necessário fabricar Torpedos de Ondas de Pulso. Para disparar, selecione vários \\\"pontos de referência\\\" e então clique no ícone \\\"Lançar Míssil\\\".\"\n  STR_ALIEN_PROBE_MISSION: \"Missão de Sonda Alienígena\"\n  STR_ALIEN_INTERDICTION: \"Interdição Alienígena\"\n  STR_ALIEN_RESOURCE_RAID: \"Incursão Alienígena para obter recursos\"\n  STR_ALIEN_INFILTRATION: \"Infiltração Alienígena\"\n  STR_ALIEN_BASE: \"Expansão Colonial Alienígena\"\n  STR_ALIEN_SURFACE_ATTACK: \"Ataques Alienígenas à Superfície\"\n  STR_ALIEN_RETALIATION: \"Ataque à Base Flutuante\"\n  STR_ALIEN_SUPPLY: \"Missões de Suprimento Colonial\"\n  STR_ALIEN_PROBE_MISSION_UFOPEDIA: \"A Missão de Sondagem Alienígena é usada para correlacionar dados sobre o leito marinho, recursos, e rotas marítimas e aéreas da área. Os submersíveis alienígenas envolvidos nestas missões não representam uma grande ameaça, mas indicam locais onde a atividade pode aumentar a qualquer momento.\"\n  STR_ALIEN_INTERDICTION_UFOPEDIA: \"Os Alienígenas têm a política de patrulhar áreas em que estão interessados, enviando submersíveis com o propósito de proteger a área antes do início de missões mais intensivas. Aterrissam em locais que querem atacar depois, para abrir caminho para o próximo nível de atividades.\"\n  STR_ALIEN_RESOURCE_RAID_UFOPEDIA: \"O afundamento de navios e a derrubada aviões são elementos chave da estratégia Alienígena. A aquisição de materiais é uma das atividades primárias dos Alienígenas, associada à agressividade notória destes atos. Os Alienígenas fazem incursões em áreas de atividade geotérmica, explorando estes locais para obter minerais e metais refinados, assim como outros itens produzidos pelos humanos.\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"Isso pode resultar em um contato oficial entre os alienígenas e os escalões mais altos do governo. O clímax dessa atividade é caracterizado por uma intensa movimentação de submarinos alienígenas nas águas das respectivas organizações. Os alienígenas tentarão assinar um acordo com uma nação ou organização da Terra oferecendo conhecimentos de sua tecnologia superior. Essa atividade alienígenas representa uma grande ameaças ao X-Com. Se uma organização ou governo aceitar cooperação com os alienígenas, seu patrocínio será retirado.\"\n  STR_ALIEN_BASE_UFOPEDIA: \"Os alienígenas vão construir colônias submarinas secretas em locais remotos. Depois de alguns voos iniciais de reconhecimento, uma intensa atividade de submarinos alienígenas enquanto ocorrer a construção da colônia. Estas colônias são conhecidas por conter laboratórios, centros de clonagem, instalações cirúrgicas para experiências com alienígenas e humanos. A presença de colônias alienígenas gerará mais atividade alienígena percebida sem a presença de submarinos alienígenas. Para localizar uma colônia, um submarino X-Com deve patrulhar uma área por algumas horas para ter alguma chance de detecção.\"\n  STR_ALIEN_SURFACE_ATTACK_UFOPEDIA: \"Quando precisam capturar seres humanos, os alienígenas aterrorizam zonas portuárias, atacam ilhas ou navios, ameaçando diretamente as vidas de civis para satisfazer as suas perversas necessidades reprodutivas e suas experiências hediondas.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"Se as missões de interceptação X-Com forem especialmente bem-sucedidas em afundar veículos alienígenas, é possível que as forças extraterrestres tomem medidas de retaliação agressiva, o que pode culminar num assalto direto às bases X-Com. No entanto, os alienígenas precisam antes encontrar uma base para poder atacá-la, é pouco provável que o ataque aconteça desde que os submarinos alienígenas sejam mantidos à distância. \"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"Assim que uma colônia alienígena é construída ela começa a receber suprimentos, trazidos por uma nave especial. Se uma destas naves for descoberta enquanto estiver aterrissando então com certeza existe uma colônia alienígena por perto.\"\n  STR_SURVEY_SHIP_UFOPEDIA: \"Este pequeno submarino é usado em missões de reconhecimento e pesquisa. Ele normalmente precede a chegada de naves maiores no início de uma missão alienígena.\"\n  STR_ESCORT_UFOPEDIA: \"Uma nave batedora de médio porte que não oferece por si só. Normalmente precede a vinda de naves maiores e outras atividades alienígenas.\"\n  STR_CRUISER_UFOPEDIA: \"O Cruzador é um veículo de propósito geral, a base da frota alienígena, usado para desempenhar todo o tipo de missões e é um adversário perigoso.\"\n  STR_HEAVY_CRUISER_UFOPEDIA: \"O cruzador pesado é uma nave mais poderosa do cruzador, equipado com armas maiores e sistemas de propulsão mais potentes. Este veículo é utilizado em missões de recursos para transportar grandes quantidades de minerais e equipamento. \"\n  STR_HUNTER_UFOPEDIA: \"Esta nave está equipada com uma sala de exames para a realização de experimentos e cirurgias em seres humanos. As vítimas passam por torturas abomináveis e o cérebro é frequentemente removido e armazenado para processamento no caminho.\"\n  STR_BATTLESHIP_UFOPEDIA: \"A nave de batalha é o veículo de combate mais agressivo da frota alienígena. Equipado com todos os sistemas, e tecnologias alienígenas para funcionar como uma base de operações para todo o tipo de missões ofensivas.  Carrega um grande conjunto de armas.\"\n  STR_DREADNOUGHT_UFOPEDIA: \"O couraçado é um enorme veículo de transporte de tropas, equipado com toda tecnologia alienígena e um vasto espaço de carga. Este submersível alienígena é resistente e é um adversário formidável.\"\n  STR_FLEET_SUPPLY_CRUISER_UFOPEDIA: \"A nave de suprimento é usada durante a construção de colônias alienígenas ou para o abastecimento de colônias existentes. Ela carrega nutrientes, amostras de ADN, fetos e outros componentes biológicos alienígenas.\"\n  STR_DISMANTLE: \"Demolir\"\n  STR_FACILITY_IN_USE: \"AQUAMÓDULO EM USO\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"NÃO É POSSÍVEL DESMONTAR ESTE AQUAMÓDULO!{SMALLLINE}Todas os módulos têm que estar ligadas à eclusa de ar.\"\n  STR_TRANSFER_ITEMS_TO: \"Transferir Itens para {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"NÃO HÁ ESPAÇO DE CONTENÇÃO ALIENÍGENA PARA A TRANSFERÊNCIA!{SMALLLINE}Alienígenas vivos necessitam de uma área de contenção alienígena para sobreviverem.\"\n  STR_AMOUNT_AT_DESTINATION: \"QUANT. NO{NEWLINE}DESTINO\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"Os alienígenas capturados morreram devido à falta de uma instalação de contenção alienígena\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"NÃO HÁ ACOMODAÇÕES LIVRES!{SMALLLINE}A base de destino não tem espaço de habitação suficiente para a tripulação deste submersível.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"ESPAÇO DE ARMAZENAGEM INSUFICIENTE!{SMALLLINE}A base de destino não dispõe de espaço de armazenagem suficiente para o equipamento atribuído ao submersível.\"\n  STR_ITEMS_ARRIVING: \"Chegada de Transporte\"\n  STR_DESTINATION_UC: \"DESTINO\"\n  STR_DART_PISTOL: \"Pistola de Dardos\"\n  STR_DART_POD: \"Carregador de Pistola de Dardos\"\n  STR_JET_HARPOON: \"Arpão-Jato\"\n  STR_HARPOON_POD: \"Carregador de Arpão-Jato\"\n  STR_GAS_CANNON: \"Canhão de Gás\"\n  STR_GC_AP_AMMO: \"Munição CG-P\"\n  STR_GC_HE_AMMO: \"Munição CG-E\"\n  STR_GC_P_AMMO: \"Munição CG-Fósforo\"\n  STR_HYDRO_JET_CANNON: \"Canhão de Hidrojato\"\n  STR_HJC_AP_AMMO: \"Munição HJ-P\"\n  STR_HJC_HE_AMMO: \"Munição HJ-E\"\n  STR_HJC_P_AMMO: \"Munição HJ-Fósforo\"\n  STR_TORPEDO_LAUNCHER: \"Lança-Torpedos\"\n  STR_SMALL_TORPEDO: \"Torpedo Pequeno\"\n  STR_LARGE_TORPEDO: \"Torpedo Grande\"\n  STR_PHOSPHOROUS_TORPEDO: \"Torpedo de Fósforo\"\n  STR_MAGNA_BLAST_GRENADE: \"Magnagranada\"\n  STR_DYE_GRENADE: \"Granada de Tinta\"\n  STR_PARTICLE_DISTURBANCE_GRENADE: \"Granada de Partículas\"\n  STR_MAGNA_PACK_EXPLOSIVE: \"Magnaexplosivo\"\n  STR_PARTICLE_DISTURBANCE_SENSOR: \"Sensor de Partículas\"\n  STR_MEDI_KIT: \"Kit Médico\"\n  STR_MC_DISRUPTOR: \"Disruptor C.M.\"\n  STR_THERMAL_TAZER: \"Bastão Térmico\"\n  STR_GAUSS_PISTOL: \"Pistola Gauss\"\n  STR_GAUSS_PISTOL_CLIP: \"Carregador de Pistola Gauss\"\n  STR_GAUSS_RIFLE: \"Rifle Gauss\"\n  STR_GAUSS_RIFLE_CLIP: \"Carregador de Rifle Gauss\"\n  STR_HEAVY_GAUSS: \"Canhão Gauss Pesado\"\n  STR_HEAVY_GAUSS_CLIP: \"Carreg. de Canhão Gauss Pesado\"\n  STR_SONIC_CANNON: \"Canhão Sônico\"\n  STR_CANNON_POWER_CLIP: \"Carregador de Canhão Sônico\"\n  STR_SONIC_BLASTA_RIFLE: \"Rifle Sônico\"\n  STR_BLASTA_POWER_CLIP: \"Carregador de Rifle Sônico\"\n  STR_SONIC_PISTOL: \"Pistola Sônica\"\n  STR_PISTOL_POWER_CLIP: \"Carregador de Pistola Sônica\"\n  STR_DISRUPTOR_PULSE_LAUNCHER: \"Lançador de Pulso Disruptor\"\n  STR_DISRUPTOR_AMMO: \"Munição de Disruptor\"\n  STR_THERMAL_SHOK_LAUNCHER: \"Lançador Térmico\"\n  STR_THERMAL_SHOK_BOMB: \"Bomba de Choque Térmico\"\n  STR_SONIC_PULSER: \"Granada Sônica\"\n  STR_ZRBITE: \"Zrbite\"\n  STR_MC_READER: \"Leitor de C.M.\"\n  STR_VIBRO_BLADE: \"Vibrolâmina\"\n  STR_THERMIC_LANCE: \"Lança Térmica\"\n  STR_HEAVY_THERMIC_LANCE: \"Lança Térmica Pesada\"\n  STR_AQUATOID_CORPSE: \"Cadáver de Aquatoide\"\n  STR_GILLMAN_CORPSE: \"Cadáver de Homem-Guelra\"\n  STR_LOBSTERMAN_CORPSE: \"Cadáver de Homem-Lagosta\"\n  STR_TASOTH_CORPSE: \"Cadáver de Tasoth\"\n  STR_CALCINITE_CORPSE: \"Cadáver de Calcinite\"\n  STR_DEEP_ONE_CORPSE: \"Cadáver de Ser das Profundezas\"\n  STR_BIODRONE_CORPSE: \"Destroços de Biodrone\"\n  STR_TENTACULAT_CORPSE: \"Cadáver de Tentaculate\"\n  STR_TRISCENE_CORPSE: \"Cadáver de Triscênio\"\n  STR_HALLUCINOID_CORPSE: \"Cadáver de Alucinoide\"\n  STR_XARQUID_CORPSE: \"Cadáver de Xarquídeo\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"Munição insuficiente para armar o SAS{SMALLLINE}Cada SAS necessita de {0} {1}.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Não há equipamento suficiente para reequipar o esquadrão\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Você necessitará pesquisar {NEWLINE}{0}{NEWLINE}para poder produzir {NEWLINE}{1}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"Os alienígenas destruíram a base desguarnecida: {0}\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"Patrulhas da X-Com localizaram uma colônia alienígena em {0}\"\n  STR_STANDOFF: \"DEFENSIVO\"\n  STR_CAUTIOUS_ATTACK: \"ATAQUE CAUTELOSO\"\n  STR_STANDARD_ATTACK: \"ATAQUE PADRÃO\"\n  STR_AGGRESSIVE_ATTACK: \"ATAQUE AGRESSIVO\"\n  STR_DISENGAGING: \"DESISTIR\"\n  STR_UFO_HIT: \"ACERTOU O OSNI!\"\n  STR_UFO_CRASH_LANDS: \"OSNI DERRUBADO!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Só Minimiza em Distância Segura\"\n  STR_UFO_RETURN_FIRE: \"O OSNI ABRIU FOGO!\"\n  STR_INTERCEPTOR_DAMAGED: \">>> AEROSUBMARINO DANIFICADO <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> AEROSUBMARINO DESTRUÍDO <<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"O OSNI ESCAPOU!\"\n  STR_LONG_RANGE_DETECTION: \"Sonar de Longo Alcance\"\n  STR_STORES_UC: \"Depósitos\"\n  STR_DIFFICULTY_LEVEL: \"Nível de Dificuldade\"\n  STR_INTERCEPT: \"INTERCEPTAR\"\n  STR_BASES: \"BASES\"\n  STR_GRAPHS: \"GRÁFICOS\"\n  STR_UFOPAEDIA_UC: \"OSNIPÉDIA\"\n  STR_OPTIONS_UC: \"OPÇÕES\"\n  STR_FUNDING_UC: \"FINANÇAS\"\n  STR_5_SECONDS: \"5 Segs\"\n  STR_1_MINUTE: \"1 Min\"\n  STR_5_MINUTES: \"5 Mins\"\n  STR_30_MINUTES: \"30 Mins\"\n  STR_1_HOUR: \"1 Hora\"\n  STR_1_DAY: \"1 Dia\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"Registo de Avaliação X-Com\"\n  STR_ENTER_NAME: \"Introduza o Nome\"\n  STR_PERFORMANCE_RATING: \"Classificação de Desempenho\"\n  STR_VICTORY_DATE: \"Data da Vitória\"\n  STR_CHEMICAL_FLARE: \"Sinalizador Químico\"\n  STR_CHEMICAL_FLARE_UFOPEDIA: \"Este dispositivo compacto produz uma luz brilhante que ilumina a área onde é lançado, dentro de água ou à superfície, revelando unidades inimigas durante missões noturnas ou a grande profundidade.\"\n  STR_MONTHLY_COSTS: \"Custos Mensais\"\n  STR_CRAFT_RENTAL: \"Aluguel de Aerosubmarinos\"\n  STR_SALARIES: \"Salários\"\n  STR_BASE_MAINTENANCE: \"Manutenção da Base\"\n  STR_COST_PER_UNIT: \"Custo por unid.\"\n  STR_QUANTITY: \"Quantidade\"\n  STR_TOTAL: \"Total\"\n  STR_IN_PSIONIC_TRAINING: \"Em implantação C.M.\"\n  STR_FRONT_ARMOR: \"Armadura Frontal\"\n  STR_LEFT_ARMOR: \"Armadura Esquerda\"\n  STR_RIGHT_ARMOR: \"Armadura Direita\"\n  STR_REAR_ARMOR: \"Armadura Traseira\"\n  STR_UNDER_ARMOR: \"Armadura Inferior\"\n  STR_ROUNDS: \"CARTUCHOS\"\n  STR_UNIT: \"UNIDADE> {0}\"\n  STR_ENERGY: \"ENERGIA\"\n  STR_MORALE: \"MORAL\"\n  STR_ARMOR_: \"ARMADURA> {0}\"\n  STR_FRONT_ARMOR_UC: \"ARMADURA FRONTAL\"\n  STR_LEFT_ARMOR_UC: \"ARMADURA ESQUERDA\"\n  STR_RIGHT_ARMOR_UC: \"ARMADURA DIREITA\"\n  STR_REAR_ARMOR_UC: \"ARMADURA TRASEIRA\"\n  STR_SKILLS: \"HABILIDADES> {0}\"\n  STR_LEVEL: \"NÍVEL> {0}\"\n  STR_HEAD: \"CABEÇA\"\n  STR_TORSO: \"TRONCO\"\n  STR_RIGHT_ARM: \"BRAÇO DIR.\"\n  STR_LEFT_ARM: \"BRAÇO ESQ.\"\n  STR_RIGHT_LEG: \"PERNA DIR.\"\n  STR_LEFT_LEG: \"PERNA ESQ.\"\n  STR_PAIN_KILLER: \"ANALGÉSICO\"\n  STR_STIMULANT: \"ESTIMULANTE\"\n  STR_HEAL: \"CURA\"\n  STR_TIME_UNITS_SHORT: \"UT>{ALT}{0}\"\n  STR_WEIGHT: \"Peso>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"Reaç>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"M.Skill>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"M.Str>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Artefato Alienígena\"\n  STR_AMMO_ROUNDS_LEFT: \"MUNIÇÃO:{NEWLINE}TIROS{NEWLINE}RESTANTES={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Analgésico>{ALT}{0}{ALT}{NEWLINE}Estimulante>{ALT}{1}{ALT}{NEWLINE}Cura>{ALT}{2}\"\n  STR_THROW: \"Arremessar\"\n  STR_AUTO_SHOT: \"Tiro Rajada\"\n  STR_SNAP_SHOT: \"Tiro Simples\"\n  STR_AIMED_SHOT: \"Tiro Preciso\"\n  STR_STUN: \"Atordoar\"\n  STR_PRIME_GRENADE: \"Ativar Granada\"\n  STR_USE_SCANNER: \"Usar Sensor\"\n  STR_USE_MEDI_KIT: \"Usar Kit Médico\"\n  STR_LAUNCH_MISSILE: \"Lançar Torpedo\"\n  STR_ACCURACY_SHORT: \"Prec>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Unidades de Tempo Insuficientes!\"\n  STR_NOT_ENOUGH_ENERGY: \"Energia Insuficiente!\"\n  STR_NO_ROUNDS_LEFT: \"Cartuchos esgotados!\"\n  STR_NO_AMMUNITION_LOADED: \"Sem Munição Carregada!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Munição Errada para esta Arma!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"A arma já está carregada!\"\n  STR_NO_LINE_OF_FIRE: \"Obstáculo na Linha de Fogo!\"\n  STR_GRENADE_IS_ACTIVATED: \"Granada Ativada!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Granada Desativada!\"\n  STR_THERE_IS_NO_ONE_THERE: \"Não há ninguém aqui!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Não pode usar artefato alienígena sem antes pesquisá-lo!\"\n  STR_OUT_OF_RANGE: \"Fora de Alcance!\"\n  STR_UNABLE_TO_THROW_HERE: \"Não é possível arremessar ali!\"\n  STR_SET_TIMER: \"Ajustar Temporizador\"\n  STR_HIDDEN_MOVEMENT: \"MOVIMENTO OCULTO\"\n  STR_TURN: \"TURNO> {0}\"\n  STR_SIDE: \"LADO> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Pressione o botão para continuar\"\n  STR_MIND_CONTROL: \"Controlar Implante\"\n  STR_PANIC_UNIT: \"Interferir Implante\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Ataque Moral Bem Sucedido\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Controlo de implante bem-sucedido\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}teve um frenesi de fúria\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}teve um frenesi de fúria\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}entrou em pânico\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}entrou em pânico\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Alienígenas\"\n  STR_RIGHT_HAND: \"MÃO DIR.\"\n  STR_LEFT_HAND: \"MÃO ESQ.\"\n  STR_RIGHT_SHOULDER: \"OMBRO DIR.\"\n  STR_LEFT_SHOULDER: \"OMBRO ESQ.\"\n  STR_BACK_PACK: \"MOCHILA\"\n  STR_BELT: \"CINTO\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}está sob controle molecular\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}está sob controle molecular\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}está inconsciente\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}está inconsciente\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}morreu vítima de ferimentos fatais.\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}morreu vítima de ferimentos fatais\"\n  STR_USE_MIND_PROBE: \"Usar Leitor de C.M.\"\n  STR_FATAL_WOUNDS: \"FERIMENTOS FATAIS\"\n  STR_UNDER_ARMOR_UC: \"ARMADURA INFERIOR\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Unidades de Tempo reservadas para Tiro Simples\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Unidades de Tempo reservadas para Tiro Rajada\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Unidades de Tempo reservadas para Tiro Preciso\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Unidades de Tempo reservadas para Ajoelhar\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"Unidades de Tempo reservadas para Ajoelhar e Disparar\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} unidade na nave X-Com\"\n    many: \"{N} unidades na nave X-Com\"\n    other: \"{N} unidades na nave X-Com\"\n  STR_UNITS_OUTSIDE:\n    one: \"Resta {N} unidade no exterior\"\n    many: \"Restam {N} unidades no exterior\"\n    other: \"Restam {N} unidades no exterior\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} unidade na entrada\"\n    many: \"{N} unidades na entrada\"\n    other: \"{N} unidades na entrada\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} unidade na área de saída\"\n    many: \"{N} unidades na área de saída\"\n    other: \"{N} unidades na área de saída\"\n  STR_ABORT_MISSION_QUESTION: \"Abortar Missão?\"\n  STR_CORPSE: \"Cadáver\"\n  STR_UNLOAD_CRAFT: \"Descarregar\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}foi morto\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}foi morta\"\n  STR_HIT_MELEE: \"Acerto\"\n  STR_GROUND: \"CHÃO\"\n  STR_LIVING_QUARTERS_PLURAL: \"Habitações\"\n  STR_LIST_ITEM: \"ITEM\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"Todos os alienígenas morreram no naufrágio.{NEWLINE}Recuperação de OSNI iniciada.\"\n  STR_RESET: \"Inicializar\"\n  STR_MEMORIAL: \"Memorial\"\n  STR_DATE_UC: \"DATA\"\n  STR_SOLDIERS_RECRUITED_UC: \"AQUANAUTAS RECRUTADOS>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"AQUANAUTAS PERDIDOS>{ALT}{0}\"\n  STR_REMOVE_SELECTED: \"Remover o Selecionado\"\n  STR_LIVE_ALIENS: \"Espécimes{NEWLINE}vivas\"\n  STR_DEAD_ALIENS: \"Espécimes{NEWLINE}mortas\"\n  STR_UNDER_INTERROGATION: \"Sendo{NEWLINE}examinada\"\n  STR_CONTAINMENT_EXCEEDED: \"LIMITES DO CONFINAMENTO ALIENÍGENA EXCEDIDO!{SMALLLINE}Espaço de contenção insuficiente em {0}. Você deve remover o excesso de alienígenas do confinamento (que morrerão, por consequência).\"\n  STR_MANAGE_CONTAINMENT: \"Gerenciar Contentor de Alienígena\"\n  STR_STORAGE_EXCEEDED: \"ESPAÇO DE ARMAZENAMENTO EXCEDIDO!{SMALLLINE}Espaço de armazenamento insuficiente em {0}. Você deve vender itens excedentes.\"\n  STR_GO_TO_BASE: \"Ir para Base\"\n  STR_MELEE_ACCURACY: \"PRECISÃO CORPO-A-CORPO\"\n  STR_SELL_PRODUCTION: \"VENDER\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Ambas as mãos necessitam estar vazias!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Itens insuficientes para copiar modelo!\"\n  STR_UNLOAD_WEAPON: \"Descarregar arma\"\n  STR_ALL_ITEMS: \"Todos os Itens\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"NÃO É PERMITIDO MAIS EQUIPAMENTO A BORDO!{SMALLLINE}Este veículo só pode transportar o limite máximo de {N} item.\"\n    many: \"NÃO É PERMITIDO MAIS EQUIPAMENTO A BORDO!{SMALLLINE}Este veículo só pode transportar o limite máximo de {N} itens.\"\n    other: \"NÃO É PERMITIDO MAIS EQUIPAMENTO A BORDO!{SMALLLINE}Este veículo só pode transportar o limite máximo de {N} itens.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}CENTRO DE COMANDO DESTRUÍDO{NEWLINE}Volte para a entrada e aborte a missão.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"A base X-Com não pode ser construída em terra.\"\n  STR_UNABLE_TO_ENGAGE_DEPTH: \"IMPOSSÍVEL ATACAR O VEÍCULO INIMIGO{NEWLINE}A ESTA PROFUNDIDADE\"\n  STR_UNABLE_TO_ENGAGE_AIRBORNE: \"IMPOSSÍVEL ATACAR O VEÍCULO INIMIGO{NEWLINE}NA SUPERFÍCIE\"\n  STR_UNDERWATER_EQUIPMENT: \"Este equipamento não funcionará na superfície!\"\n  STR_LAND_EQUIPMENT: \"Este equipamento não funciona na água!\"\n  STR_LEVEL_SHORT: \"N{0}\"\n  STR_PERSONNEL: \"Pessoal\"\n  STR_CRAFT_ARMAMENT: \"Veículos e armamento\"\n  STR_COMPONENTS: \"Componentes\"\n  STR_SOLDIERS_RECRUITED: \"Aquanautas recrutados\"\n  STR_SOLDIERS_LOST: \"Aquanautas perdidos\"\n  STR_TOTAL_UFOS: \"Aerosubmarinos detectados\"\n  STR_TOTAL_ALIEN_BASES: \"Bases alienígenas descobertas\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"FCM\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"HCM\"\n  FEMALE_CIVILIAN: \"Civil, Feminino\"\n  MALE_CIVILIAN: \"Civil, Masculino\"\n  DOCKER_CIVILIAN: \"Civil, Carregador\"\n  SAILOR_CIVILIAN: \"Civil, Marinheiro\"\n  STR_BIODRONE_MELEE_WEAPON: \"Biodrone desarmado\"\n  HALLUCINOID_WEAPON: \"Arma do Alucinoide\"\n  STR_LOBSTERMAN_MELEE_WEAPON: \"Homem-Lagosta Desarmado\"\n  CALCINITE_WEAPON: \"Arma do Calcinite\"\n  DEEP_ONE_WEAPON: \"Arma do Ser das Profundezas\"\n  STR_TRISCENE_MELEE_WEAPON: \"Triscênio Desarmado\"\n  STR_TRIBIO_SONIC_WEAPON: \"Arma Sônica Alienígena\"\n  XARQUID_WEAPON: \"Arma do Xarquídeo\"\n  TENTACULAT_WEAPON: \"Arma do Tentaculate\"\n  ZOMBIE_WEAPON: \"Arma do Zumbi\"\n  ALIEN_PSI_WEAPON: \"Arma de C.M. Alienígena\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/pt-PT.yml",
    "content": "pt-PT:\n  STR_LEVIATHAN_UFOPEDIA: \"O LEVIATHAN É UMA SÍNTESE PERFEITA ENTRE TECNOLOGIA ALIENÍGENA E TERRESTRE. ESTE NOVO VEÍCULO MISTO DE TRANSPORTE E INTERCEÇÃO UTILIZA SISTEMAS DE PROPULSÃO DE IÕES E SISTEMAS DE NAVEGAÇÃO MAGNÉTICOS, SENDO CAPAZ DE ATINGIR PROFUNDIDADES EXTREMAS.\"\n  STR_BARRACUDA_UFOPEDIA: \"CRIADO PELA BRITISH HYDROSPACE, ESTE AEROSUBMERSÍVEL MOVIDO POR MOTORES AQUECIDOS A LASER É UM DOS VEÍCULOS DE INTERCEÇÃO MAIS VELOZES DO PLANETA. O BARRACUDA É UMA PEÇA VALIOSA NA LUTA CONTRA OS ALIENÍGENAS, DEVIDO ÀS SUAS CAPACIDADES DE NAVEGAÇÃO SUBMERSA E VOO ATMOSFÉRICO.\"\n  STR_HAMMERHEAD_UFOPEDIA: \"NÃO OBSTANTE O SEU TAMANHO REDUZIDO, ESTE NOVO VEÍCULO DE TRANSPORTE E INTERCEÇÃO É UM DESENVOLVIMENTO TECNOLÓGICO INCRÍVEL, INCORPORANDO PERFEITAMENTE OS SISTEMAS DE NAVEGAÇÃO MAGNÉTICOS ALIENÍGENAS NUM MODELO DE AEROSUBMERSÍVEL X-COM.\"\n  STR_TRITON_UFOPEDIA: \"O TRANSPORTE DE TROPAS TRITON É UM VEÍCULO EQUIPADO COM MOTORES DE DESLOCAÇÃO AÉREA E SUBAQUÁTICA. A SUA CONSTRUÇÃO ROBUSTA E ESPAÇOSA FAZEM DESTE VEÍCULO UMA DAS PRINCIPAIS AQUISIÇÕES DA FROTA X-COM.\"\n  STR_MANTA_UFOPEDIA: \"O MANTA É UM AEROSUBMERSÍVEL MONOLUGAR DE ALTA VELOCIDADE, MOVIDO A MOTORES DE IÕES, TAL COMO AS NAVES ALIENÍGENAS. ESTE CAÇA DE COMBATE É UMA AQUISIÇÃO IMPORTANTE NA LUTA CONTRA OS INVASORES.\"\n  STR_AJAX_UFOPEDIA: \"O TORPEDO AJAX É ARMA DE GUERRA SUBAQUÁTICA MAIS UTILIZADA DO MUNDO, DEVIDO À SUA GRANDE PRECISÃO E PODER DE FOGO.\"\n  STR_DUP_HEAD_UFOPEDIA: \"ESTA É A PRIMEIRA ARMA SUBAQUÁTICA COMERCIALMENTE DISPONÍVEL QUE UTILIZA A NOVA TECNOLOGIA DE MUNIÇÕES À BASE DE URÂNIO EMPOBRECIDO.\"\n  STR_CRAFT_GAS_CANNON_UFOPEDIA: \"ESTE CANHÃO A GÁS COMPRIMIDO DISPARA PROJÉTEIS SÓLIDOS PERFURANTES, COM GRANDE CAPACIDADE DE PENETRAÇÃO.\"\n  STR_PWT_CANNON_UFOPEDIA: \"O TORPEDO DE ONDAS DE PULSÃO UTILIZA UM SISTEMA DE COMBUSTÍVEL SUPERAQUECIDO E UMA OGIVA CONSTRUÍDA ATRAVÉS DE UM MATERIAL ALTAMENTE DENSO, CAPAZ DE PENETRAR A MAIORIA DOS MATERIAIS.\"\n  STR_GAUSS_CANNON_UFOPEDIA: \"O CANHÃO GAUSS É A MAIS RECENTE TECNOLOGIA DE ARMAMENTO DESENVOLVIDA PELO PROJETO X-COM. O ACELERADOR DE PARTÍCULAS DESTA ARMA É ALIMENTADO POR UM PEQUENO REATOR DE FUSÃO ARREFECIDO A NITROGÉNIO LÍQUIDO.\"\n  STR_SONIC_OSCILLATOR_UFOPEDIA: \"ESTE OSCILADOR SONORO PRODUZ ONDAS SÓNICAS DE GRANDE POTÊNCIA, CAPAZES DE DESTRUIR A ESTRUTURA MOLECULAR DO ALVO ATRAVÉS DE PODEROSAS VIBRAÇÕES.\"\n  STR_AQUATOID_UFOPEDIA: \"Os Aquatóides são uma espécie antiga, cuja sociedade já existia milénios antes dos seres humanos darem os primeiros passos neste planeta. A sua fisionomia compacta e feições arredondadas evidenciam a sua ligação com a espécie extraterrestre dos Sectóides. Estas criaturas são estéreis por natureza, e procuram propagar a sua espécie através de modificação genética e hibridização com seres humanos. Em combate, fazem uso da poderosa tecnologia de controlo molecular.\"\n  STR_AQUATOID_AUTOPSY: \"Autópsia: Aquatóide\"\n  STR_AQUATOID_AUTOPSY_UFOPEDIA: \"Uma análise detalhada do cadáver permitiu-nos tirar várias conclusões: trata-se de um Sectóide, um dos nossos antigos inimigos, mas alterado através de cirurgia e implantes para se adaptar ao meio aquático. Pulmões residuais permitem respiração e movimento à superfície, mas de forma limitada. Encontrámos vários implantes espalhados pelo corpo destinados a melhorar o desempenho dos membros e órgãos atrofiados. Como todos os membros desta espécie são idênticos, é muito provável que estes seres sejam clonados.\"\n  STR_GILLMAN_UFOPEDIA: \"Estas estranhas criaturas assemelham-se a humanoides reptilianos, não muito distantes dos seres humanos, e são extremamente ágeis dentro de água. Os Homens-Guelra são uma espécie sexuada, com espécimes macho e fêmea, assim como indivíduos de várias idades. São diferentes da maioria das espécies de alienígenas subaquáticos que encontrámos até ao momento, pois não exibem traços de alteração genética. É possível que estejamos a lidar com um parente afastado da nossa própria espécie.\"\n  STR_GILLMAN_AUTOPSY: \"Autópsia: Homem-guelra\"\n  STR_GILLMAN_AUTOPSY_UFOPEDIA: \"Ao dar início à autopsia, concluímos imediatamente que este ser não é um alienígena, mas uma criatura terrestre; uma espécie pré-histórica que julgávamos extinta desde o início da era dos mamíferos. No tempo em que os dinossauros caminhavam pelo planeta, estes seres anfíbios, fortes e inteligentes, prosperaram. O cataclismo que pôs termo ao domínio dos répteis forçou estas criaturas a cooperar com os alienígenas recém-chegados. Possuem um pequeno aparelho eletrónico alojado no crânio.\"\n  STR_LOBSTERMAN_UFOPEDIA: \"Esta enorme criatura é um verdadeiro horror subaquático. Possui três pares de membros e é mais alta que um homem normal. As suas semelhanças com a lagosta terrestre atribuíram-lhe o nome de \\\"Homem-lagosta\\\" entre as tropas X-Com. Este monstro das profundezas é uma entidade criada especificamente para o combate, praticamente invulnerável a qualquer tipo projéteis e detentora de uma força sem precedentes. As suas pinças são capazes de esmagar aço.\"\n  STR_LOBSTERMAN_AUTOPSY: \"Autópsia: Homem-lagosta\"\n  STR_LOBSTERMAN_AUTOPSY_UFOPEDIA: \"Esta criatura possuí um organismo extraordinário protegido por uma carapaça quase indestrutível. Os seus músculos poderosos são apoiados por um esqueleto de titânio e um sistema avançado de aquisição múltipla de alvos está ligado diretamente ao seu cérebro. Os seus olhos estão protegidos por lentes feitas de um plástico mais duro que aço. Existem ainda vários aparelhos distribuídos pelo seu corpo cuja função desconhecemos. Com base nesta análise concluímos que, quando usados estrategicamente, estes seres são praticamente invencíveis em combate.\"\n  STR_TASOTH_UFOPEDIA: \"Estes seres aquáticos constituem a base do exército invasor. São produzidos às centenas, em incubadoras enormes, localizadas no coração das colónias alienígenas. Com uma força e agilidade superiores às de um homem normal, os Tasoth são criaturas verdadeiramente alienígenas, na medida em que a sua natureza carnívora e comportamento agressivo não encontram igual no nosso planeta. Ocupam regularmente a linha da frente nas incursões alienígenas e parecem nunca recuar face aos seus adversários.\"\n  STR_TASOTH_AUTOPSY: \"Autópsia: Tasoth\"\n  STR_TASOTH_AUTOPSY_UFOPEDIA: \"A autópsia revelou um organismo com base num estranho sistema cibernético. Encontrámos somente uma pequena unidade energética dentro do corpo, sem nenhum órgão biológico identificável. A energia circula através de uma rede bioelétrica. Esta criatura não possuí esqueleto ou qualquer estrutura de apoio. Ao morrer, o fluxo de energia para, e o seu corpo torna-se uma pilha inerte de músculos e fluídos. O único elemento interno é o par de baterias de cerâmica que revivem a criatura brevemente, se reenergizadas.\"\n  STR_DEEP_ONE_UFOPEDIA: \"Os Seres das profundezas são verdadeiros horrores biológicos, produzidos através de experiências de cruzamento entre humanos e alienígenas, realizadas pelos Aquatóides. Ao encontrarmos variações diferentes desta criatura, concluímos, após várias pesquisas, que estes seres são fabricados pelos invasores, reforçando o seu exército com seres humanos recentemente capturados. Cada Ser das profundezas está armado com um feixe de energia suficientemente poderoso para matar um aquanauta.\"\n  STR_DEEP_ONE_AUTOPSY: \"Autópsia: Ser das profundezas\"\n  STR_DEEP_ONE_AUTOPSY_UFOPEDIA: \"Esta criatura é um misto entre ser humano e organismo alienígena. O cérebro humano foi alterado para acomodar circuitos de controlo e partes do córtex alienígena. O resto do corpo, salvo os olhos, foi removido. A alteração cirúrgica é feita de forma a permitir a inserção de um feto alienígena que consome o hospedeiro humano à medida que cresce. O resultado é uma aberração de enorme força e destreza, sob pleno controlo dos invasores. A sua pele é um filamento metálico flexível, não-orgânico e altamente resistente. \"\n  STR_BIODRONE_UFOPEDIA: \"Esta entidade é mais uma das criações perversas dos alienígenas. O Biodisco consiste num cérebro humano ou alienígena suspenso em fluídos amnióticos e ligado e uma unidade de deslocação anti-gravidade, que permite movimento dentro ou fora de água. Cada Biodisco está equipado com um disruptor sonoro biomecânico. Alguns cientistas sugeriram que esta arma funciona com base nas cordas vocais do organismo original. Estas entidades especializam-se em funções de vigia e são utilizadas pelos alienígenas para guardar bens preciosos.\"\n  STR_BIODRONE_AUTOPSY: \"Autópsia: Biodisco\"\n  STR_BIODRONE_AUTOPSY_UFOPEDIA: \"Descobrimos que a arma sónica desta entidade é um aparelho biológico que emite gritos mortíferos. Os alienígenas mutilam o cérebro da vítima de maneira a assegurar obediência, pois todos os espécimes exibem cicatrizes que apontam para um processo cirúrgico extremo. A maioria dos espécimes possui encéfalos de origem alienígena, mas, para nosso horror, encontrámos vários exemplares de proveniência humana. Os Biodiscos deslocam-se através de um motor de iões e contém uma unidade de controlo remoto.\"\n  STR_TENTACULAT_UFOPEDIA: \"O ambiente que deu origem a este monstro está para além das nossas especulações, pois nenhum animal terrestre se lhe compara. Armado com longos tentáculos paralisantes, capazes de penetrar a melhor das armaduras, o Tentaculat é uma criatura mortífera que transforma as suas vítimas em zombies errantes. Este é o alienígena mais terrível alguma vez encontrado pelas forças X-Com.\"\n  STR_TENTACULAT_AUTOPSY: \"Autópsia: Tentaculat\"\n  STR_TENTACULAT_AUTOPSY_UFOPEDIA: \"A autópsia revelou a presença de vários implantes cibernéticos no cérebro desta criatura. O seu sistema visual é complexo, e permite-lhe navegar nas profundezas mais escuras com enorme precisão. Este ser possui apenas órgãos residuais necessários para assegurar a sua sobrevivência, e o seu estômago está ligado a um conector externo, o que sugere dependência de injeções diretas de nutrientes por parte dos seus mestres.\"\n  STR_CALCINITE_UFOPEDIA: \"Hóspedes de antigos fatos de mergulho abandonados, estes alienígenas perscrutam as profundezas oceânicas em busca de vítimas. Um golpe das suas garras é suficiente para incapacitar os mergulhadores mais experientes. Para além da massa gelatinosa observável através da viseira do escafandro, não conseguimos retirar outras conclusões sobre a natureza desta criatura com base em encontros anteriores.\"\n  STR_CALCINITE_AUTOPSY: \"Autópsia: Calcinite\"\n  STR_CALCINITE_AUTOPSY_UFOPEDIA: \"Após removermos o fato de mergulho, o Calcinite revelou ser pouco mais que uma massa disforme de protoplasma. Não encontrámos nenhum cérebro, membros, ou órgãos sensoriais. Apenas um pequeno componente metálico que reside no interior do seu corpo líquido. A natureza desta criatura permanece assim um mistério inexplicável dos nossos inimigos alienígenas.\"\n  STR_TRISCENE_UFOPEDIA: \"Salvo a sua capacidade para sobreviver debaixo de água, esta criatura bípede parece um descendente dos antigos dinossauros do período Cretáceo. O Triscénio está equipado com sistemas de armas avançados e as suas mandíbulas foram modificadas com dentes metálicos. Estes monstros são frequentemente utilizados pelos comandantes Tasoth como unidades de apoio pesado em ataques à superfície.\"\n  STR_TRISCENE_AUTOPSY: \"Autópsia: Triscénio\"\n  STR_TRISCENE_AUTOPSY_UFOPEDIA: \"O Triscénio é uma criatura primitiva equipada com implantes cibernéticos e vários sistemas de armas modernos. O seu cérebro minúsculo é suplementado por um módulo informático contido no seu arnês de controlo. A sua pele resistente e o seu instinto predatório naturais combinados com o armamento adicional, fazem desta criatura um oponente mortífero em todo o género de ambientes.\"\n  STR_HALLUCINOID_UFOPEDIA: \"Os alienígenas tornaram estas enormes alforrecas terrestres em armas biológicas mortíferas. Recomenda-se cuidado ao lidar com estas criaturas, pois por detrás da sua aparência inofensiva, os Halucinóides possuem um terrível ataque gelado corpo a corpo.\"\n  STR_HALLUCINOID_AUTOPSY: \"Autópsia: Alucinóide\"\n  STR_HALLUCINOID_AUTOPSY_UFOPEDIA: \"Este organismo aloja um poderoso químico congelante no seu corpo gelatinoso, que utiliza como principal arma ofensiva. A sua pele suave e flexível parece ser suscetível a ataques térmicos. Os Alucinóides são criaturas mutantes, e são frequentemente acompanhados pelos seus mestres, os Aquatóides.\"\n  STR_XARQUID_UFOPEDIA: \"O Xarquídeo é uma modificação de um invertebrado terrestre. Esta criatura ágil possui um arsenal devastador: um jato de tinta e um raio de partículas ionizadas. Desde os nossos primeiros encontros com esta criatura que os nossos soldados aprenderam a respeitar o seu poder e o dos seus mestres, os terríveis Homens-Guelra.\"\n  STR_XARQUID_AUTOPSY: \"Autópsia: Xarquídeo\"\n  STR_XARQUID_AUTOPSY_UFOPEDIA: \"Esta criatura é um náutilo gigantesco que foi alterado através de cirurgia e drogas alienígenas por forma a operar como uma enorme plataforma de armas orgânica. A sua natureza pacífica foi corrompida pelos Homens-guelra através de sistemas de controlo mecânicos. O Xarquídeo é um adversário formidável em combate, graças à sua concha altamente resistente e à sua excelente mobilidade subaquática.\"\n  STR_ION_BEAM_ACCELERATORS_UFOPEDIA: \"Os aerosubmersíveis alienígenas funcionam através de sistemas de energia complexos que permitem movimento subaquático a velocidades incríveis. O componente principal desta tecnologia é o deslocador de iões, um motor capaz de mover 100 vezes o seu volume em água por segundo que utiliza Zrbite como catalisador primário. Este enorme potencial energético significa que os veículos alienígenas facilmente superam os submersíveis terrestres. Felizmente somos capazes de reproduzir estes novos sistema de propulsão através de aquaplástico e células de Zrbite.\"\n  STR_MAGNETIC_NAVIGATION_UFOPEDIA: \"Este sistema projeta um campo magnético no raio de 1 km em torno do OSNI, dividido em camadas esféricas. Os navegadores alienígenas estão ligados a estas máquinas, e conseguem a \\\"sentir\\\" o caminho através da escuridão dos oceanos. Este interface utiliza matéria cerebral alienígena para comunicar diretamente com o cérebro do navegador através de uma ligação nervosa.\"\n  STR_ALIEN_SUB_CONSTRUCTION_UFOPEDIA: \"Todos os veículos alienígenas são construídos em aquaplástico e equipados com mecanismos de camuflagem. O seu funcionamento implica uma relação orgânica entre a tripulação e os sistemas de controlo. A fabricação da maioria destes sistemas está agora ao nosso alcance, o que nos permite desenvolver um modelo tecnológico híbrido que nos colocará ao mesmo ao nível dos alienígenas.\"\n  STR_ALIEN_CRYOGENICS_UFOPEDIA: \"As hostes alienígenas escondidas nas profundezas do nosso planeta encontram-se atualmente em modo de hipersono. Todas estas criaturas estão seladas em unidades de contenção que reduzem a sua temperatura corporal a um ponto em que todas as suas funções vitais são suspensas. Uma análise realizada a estas unidades revela que os alienígenas foram mantidos neste estado por mais de 60 milhões de anos.\"\n  STR_ALIEN_CLONING_UFOPEDIA: \"Muitos dos alienígenas que capturámos são geneticamente idênticos em todos os sentidos. As amostras celulares são colocadas nas unidades de clonagem, a partir dos bancos genéticos dos alienígenas. Encontrámos algumas unidades contendo humanos ou partes de cadáveres humanos. É possível que estas unidades sirvam para criar híbridos entre alienígenas e humanos.\"\n  STR_ALIEN_LEARNING_ARRAYS_UFOPEDIA: \"Estes aparelhos inserem informação no cérebro de todos os clones alienígenas recém-nascidos. Todas as suas memórias raciais, assim como todo o conhecimento científico e treino militar são carregados diretamente nas suas mentes vazias.\"\n  STR_ALIEN_IMPLANTER_UFOPEDIA: \"Esta unidade é utilizada para inserir implantes de controlo molecular nos crânios dos alienígenas, fertilizar espécies com capacidades reprodutoras, e colocar ou remover órgãos e aparelhos cibernéticos em qualquer criatura. Os pacientes são sujeitos ao processo em pleno estado de consciência e, infelizmente, descobrimos que o aparelho adapta-se perfeitamente à anatomia humana.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"Após reunirmos provas suficientes, finalmente compreendemos o motivo pelo qual os alienígenas capturam seres humanos. A tecnologia alienígena funciona com base numa estrutura mental partilhada, para a qual o cérebro humano é o recetáculo mais acessível. Os alienígenas utilizam tecido cerebral humano na fabricação de computadores e sistemas de controlo biológicos para esta rede, enquanto o material orgânico restante é aproveitado para fins de alimentação ou manipulação genética.\"\n  STR_AQUA_PLASTICS_UFOPEDIA: \"Os veículos e estruturas alienígenas são construídos através de aquaplástico, um material estruturalmente complexo, com enorme durabilidade, resistência e flexibilidade. Esta substância catalisada através de Zrbite é altamente densa, mas extremamente leve.\"\n  STR_ZRBITE_UFOPEDIA: \"Esta liga de origem alienígena é um composto híbrido entre ouro e matéria orgânica alienígena. Quando utilizada como combustível, pequenas quantidades desta substância são capazes de gerar mais energia que uma unidade fusão nuclear. Infelizmente somos incapazes de reproduzir este material, devido à maioria dos seus constituintes ser de origem extraterrestre.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"Os alienígenas atacam por todo o planeta com uma eficácia assustadora, mas nós não conseguimos localizar as origem dos seus ataques. É possível que surjam de profundezas oceânicas impenetráveis aos nossos sonares. Nem todos os organismos que encontrámos até à data são de origem alienígena. Alguns assemelham-se a espécies antigas, e outros a descendentes de cadeias evolucionárias que julgávamos extintas há muito. Lidamos com uma ameaça que esteve dormente durante milénios e vários indícios sugerem uma certa dependência na nossa espécie. Espalhados pelos oceanos, encontram-se várias estações antigas, usadas pelos alienígenas para contactar os seus parentes estelares. Cada uma destas doze estações contém um Sinónimo, uma poderosa peça de tecnologia alienígena. Com as suas hostes em marcha, os alienígenas procuram reativar estas estações para expandirem a sua rede de controlo molecular. Logo, é essencial destruir as estações alienígenas a todo o custo.\"\n  STR_THE_ULTIMATE_THREAT_UFOPEDIA: \"Há 65 milhões de anos, uma nave colossal vinda de um mundo distante foi enviada numa missão para colonizar o planeta Terra. Enquanto se aproximava da órbita terrestre, uma enorme tempestade solar provocou uma falha geral nos seus sistemas de navegação. À beira do colapso, a estrutura gigantesca precipitou-se na atmosfera, emergindo nos céus do Cretáceo. No solo, inúmeras espécies terrestres fixavam os seus olhares na destruição que se abatia sobre o planeta. Uma enorme nuvem de pó encobriu a atmosfera por completo. À medida que o planeta arrefecia, também as formas de vida dominantes, os dinossauros, caminhavam para a sua extinção. Mas T'leth, a enorme nave alienígena, não foi destruída pelo impacto. Encerrados na sua estrutura de 400 mil milhões de toneladas, inúmeros computadores sofisticados colocaram todos os tripulantes sobreviventes num estado de hipersono. Com o passar dos milénios, os sistemas acordaram grupos de alienígenas em tentativas vãs de restabelecer contacto com os seus congéneres estelares. O núcleo de energia alienígena permanecia dormente, e não parecia haver forma de o reativar.\"\n  STR_TLETH_THE_ALIEN_CITY: \"T'leth, a cidadela alienígena\"\n  STR_TLETH_THE_ALIEN_CITY_UFOPEDIA: \"T'leth, a enorme nave-colónia alienígena, jaz no fundo da depressão conhecida como fossa de Sigsbee, no Golfo do México. No coração da cidadela esconde-se um horror alienígena tão poderoso e tão vil, que nem a morte lhe toca. Dentro de uma enorme câmara de metal dorme o grande sonhador, o Derradeiro Alienígena. Quando T'leth se erguer acima das ondas, o seu ciclo de reanimação será iniciado. Se tal acontecer, os alienígenas serão imparáveis. Apesar de não estar vivo, mas sem, no entanto, estar morto, a mente deste ser controla o exército alienígena. A estranha tecnologia de controlo molecular liga todos os alienígenas à sua mente, e a sua mente à de todos os alienígenas. Milhares de fetos híbridos entre humanos e alienígenas proporcionam energia à grande mente alienígena, e formam o elo mental entre o supremo mestre e os seus súbditos. O mito do Derradeiro Alienígena sempre existiu algures nos corações e nas mentes de todos os seres humanos durante séculos, mas a verdade estava escondida no fundo dos oceanos.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"CENTRAR NO LOCAL-TEMPO=5 Segs\"\n  STR_CANCEL_UC: \"CANCELAR\"\n  STR_NONE: \"Nenhum\"\n  STR_UNKNOWN: \"Desconhecido\"\n  STR_POOR: \"Fraco\"\n  STR_AVERAGE: \"Médio\"\n  STR_GOOD: \"Bom\"\n  STR_EXCELLENT: \"Excelente\"\n  STR_BUILD_NEW_BASE_UC: \"CONSTRUIR NOVA BASE\"\n  STR_BASE_INFORMATION: \"INFORMAÇÕES DA BASE\"\n  STR_EQUIP_CRAFT: \"EQUIPAR SUBMERSÍVEL\"\n  STR_BUILD_FACILITIES: \"CONSTRUIR INSTALAÇÕES\"\n  STR_RESEARCH: \"PESQUISAS\"\n  STR_MANUFACTURE: \"MANUFATURAS\"\n  STR_TRANSFER_UC: \"TRANSFERÊNCIAS\"\n  STR_PURCHASE_RECRUIT: \"COMPRAR/CONTRATAR\"\n  STR_SACK: \"DEMITIR\"\n  STR_SELL_SACK_UC: \"VENDER/DEMITIR\"\n  STR_GEOSCAPE_UC: \"GLOBO\"\n  STR_NAME: \"Nome\"\n  STR_AREA: \"Área\"\n  STR_BUILD_NEW_BASE: \"Construir nova base\"\n  STR_CANCEL: \"Cancelar\"\n  STR_COST_UC: \"VALOR>\"\n  STR_CONSTRUCTION_TIME_UC: \"TEMPO DE CONSTRUÇÃO>\"\n  STR_DAY:\n    one: \"{N} dia\"\n    many: \"{N} dias\"\n    other: \"{N} dias\"\n  STR_HOUR:\n    one: \"{N} hora\"\n    many: \"{N} horas\"\n    other: \"{N} horas\"\n  STR_MAINTENANCE_UC: \"MANUTENÇÃO>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Instalação\"\n  STR_CURRENT_RESEARCH: \"PESQUISAS ATUAIS\"\n  STR_SCIENTISTS_AVAILABLE: \"Cientistas disponíveis>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Cientistas atribuídos>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Espaço de laboratório disponível>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"PROJETO DE INVESTIGAÇÃO\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"CIENTISTAS ATRIBUÍDOS\"\n  STR_PROGRESS: \"PROGRESSO\"\n  STR_NEW_PROJECT: \"Novo projeto\"\n  STR_CANCEL_PROJECT: \"CANCELAR PROJETO\"\n  STR_NEW_RESEARCH_PROJECTS: \"NOVOS PROJETOS DE INVESTIGAÇÃO\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"CIENTISTAS DISPONÍVEIS>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"ESPAÇO DE LABORATÓRIO DISPONÍVEL>{ALT}{0}\"\n  STR_INCREASE: \"Aumentar\"\n  STR_DECREASE: \"Diminuir\"\n  STR_START_PROJECT: \"INICIAR PROJETO\"\n  STR_CURRENT_PRODUCTION: \"PRODUÇÃO ATUAL\"\n  STR_ENGINEERS_AVAILABLE: \"Técnicos disponíveis>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Técnicos atribuídos>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Espaço de oficina disponível>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Fundos atuais>{ALT}{0}\"\n  STR_ITEM: \"ITEM\"\n  STR_ENGINEERS__ALLOCATED: \"Técnicos atribuídos\"\n  STR_UNITS_PRODUCED: \"Unidades produzidas\"\n  STR_TOTAL_TO_PRODUCE: \"Total a produzir\"\n  STR_COST__PER__UNIT: \"Custo{NEWLINE}por{NEWLINE}unidade\"\n  STR_DAYS_HOURS_LEFT: \"Dias/Horas restantes\"\n  STR_NEW_PRODUCTION: \"Nova produção\"\n  STR_PRODUCTION_ITEMS: \"Itens para produção\"\n  STR_CATEGORY: \"CATEGORIA\"\n  STR_START_PRODUCTION: \"INICIAR PRODUÇÃO\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} horas de trabalho para produzir uma unidade\"\n  STR_COST_PER_UNIT_: \"Valor da unidade>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Espaço de oficina necessário>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"MATERIAIS ESPECIAIS NECESSÁRIOS\"\n  STR_ITEM_REQUIRED: \"ITEM NECESSÁRIO\"\n  STR_UNITS_REQUIRED: \"UNIDADES NECESSÁRIAS\"\n  STR_UNITS_AVAILABLE: \"UNIDADES DISPONÍVEIS\"\n  STR_STOP_PRODUCTION: \"CANCELAR PRODUÇÃO\"\n  STR_ENGINEERS_AVAILABLE_UC: \"TÉCNICOS DISPONÍVEIS>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"ESPAÇO DE OFICINA DISPONÍVEL>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"LUCRO MENSAL>{ALT}[0}\"\n  STR_INCREASE_UC: \"AUMENTAR\"\n  STR_DECREASE_UC: \"DIMINUIR\"\n  STR_UNITS_TO_PRODUCE: \"Unidades a produzir\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Comprar/Contratar\"\n  STR_COST_OF_PURCHASES: \"Valor total>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"VALOR P/ UNIDADE\"\n  STR_QUANTITY_UC: \"QUANTIDADE\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"PESSOAL DISPONÍVEL:PESSOAL TOTAL>\"\n  STR_SOLDIERS: \"Aquanautas\"\n  STR_SCIENTISTS: \"Cientistas\"\n  STR_ENGINEERS: \"Técnicos\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"ESPAÇO USADO:ESPAÇO DISPONÍVEL>\"\n  STR_LIVING_QUARTERS: \"Bloco habitacional\"\n  STR_STORES: \"Armazéns\"\n  STR_LABORATORIES: \"Laboratórios\"\n  STR_WORK_SHOPS: \"Oficinas\"\n  STR_HANGARS: \"Docas\"\n  STR_SHORT_RANGE_DETECTION: \"Sonar de curto alcance\"\n  STR_DEFENSE_STRENGTH: \"Defesas\"\n  STR_TRANSFERS_UC: \"TRANSFERÊNCIAS\"\n  STR_TRANSFERS: \"Transferências\"\n  STR_ARRIVAL_TIME_HOURS: \"Hora de chegada\"\n  STR_COST_: \"Valor>{ALT}{0}\"\n  STR_AREA_: \"Área>{ALT}{0}\"\n  STR_BASE_NAME: \"Nome da base?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"SELECIONAR POSIÇÃO PARA A ECLUSA DE AR\"\n  STR_TRANSFER: \"Transferir\"\n  STR_AMOUNT_TO_TRANSFER: \"QUANTIDADE A TRANSFERIR\"\n  STR_SELECT_DESTINATION_BASE: \"Selecionar base de destino\"\n  STR_COST: \"Valor\"\n  STR_INTRO_1: \"© 1995 MicroProse - Todos os direitos reservados\"\n  STR_INTRO_2: \"Marte: a destruição de Cidónia.\"\n  STR_INTRO_3: \"As forças X-Com regressam à Terra após uma triunfante batalha que culminou com a destruição da máquina de guerra alienígena. No entanto, ainda há vida nas ruínas da base marciana.\"\n  STR_INTRO_4: \"Um poderoso feixe de taquiões surge por entre os destroços do centro de comando de Cidónia, cruzando o espaço com um único destino...\"\n  STR_INTRO_5: \"A Terra.\"\n  STR_INTRO_6: \"O feixe atinge um antigo recetor dormente no fundo do oceano. Imediatamente, inúmeros computadores iniciam a sua atividade. Bem longe dos olhares humanos, enormes câmaras, repletas de alienígenas em crioestase, começam um longo processo de reanimação.\"\n  STR_INTRO_7: \"2040: uma Terra ignorante. Os horrores da guerra alienígena foram há muito esquecidos. Mas no fundo do oceano, as hordas alienígenas estão prontas para derrubar a humanidade e assumir o controlo do planeta.\"\n  STR_INTRO_8: \"Os alienígenas atacam a humanidade, sequestrando seres humanos para as suas experiências, lançando incursões globais para obter minerais e recursos valiosos, e pilhando os mares das suas riquezas. Mas cedo os alienígenas apontam o olhar acima das ondas.\"\n  STR_INTRO_9: \"Aerosubmersíveis de origem alienígena perscrutam os oceanos à procura de presas...\"\n  STR_INTRO_10: \"Ao encontrarem o seu alvo, lançam-se ao ataque.\"\n  STR_INTRO_11: \"Novas armas misteriosas ameaçam uma civilização indefesa. Estamos completamente à mercê das forças alienígenas.{NEWLINE} Só uma organização há muito esquecida nos pode salvar.\"\n  STR_INTRO_12: \"Estação experimental subaquática X-COM\"\n  STR_INTRO_13: \"\\\"SOS! SOS! Daqui é o paquete transatlântico Hyperion. Estamos a ser atacados. SOS! SO-\\\"\"\n  STR_INTRO_14: \"\\\"Centro de controlo para doca um: abrir comportas para o oceano, enviar Barracuda 01. Temos uma situação de ataque alienígena - alerta vermelho\\\".{NEWLINE}\\\"Repito: alerta vermelho\\\"\"\n  STR_INTRO_15: \"Os alienígenas são impiedosos na sua eficácia...\"\n  STR_INTRO_16: \"... e infalíveis na sua precisão.\"\n  STR_INTRO_17: \"\\\"Barracuda 01 para base - em aproximação dos destroços do Hyperion.\\\"\"\n  STR_INTRO_18: \"\\\"A desacelerar\\\".{NEWLINE}\\\"Dois metros\\\"'{NEWLINE}\\\"Um metro\\\"{NEWLINE}\\\"Alerta a todos os aquanautas: preparem-se para desembarque imediato\\\".\"\n  STR_INTRO_19: \"\\\"Escotilha de ar aberta. A aproximar-me dos destroços.\\\"{NEWLINE}\\\"Que raio!\\\"{NEWLINE}\\\"Conseguem ver aquelas criaturas na minha câmara?\\\"\"\n  STR_GAMEOVER_1: \"Falhámos a nossa missão. Os alienígenas destruíram a nossa última esperança de salvação.{NEWLINE}As forças X-Com foram vencidas e Terra jaz agora aos pés do inimigo.\"\n  STR_GAMEOVER_2: \"A cidadela de T'leth ascende à estratosfera e inicia o seu percurso pela superfície terrestre, semeando a morte e a destruição enquanto recolhe os restos da espécie humana. Nas profundezas da fortaleza, a terrível mente alienígena começa a despertar.\"\n  STR_GAMEOVER_3: \"Nos centros de governo das várias nações terrestres, vários planos de emergência são criados em vão. Sem a tecnologia desenvolvida pelo projeto X-Com, as nossas armas são ineficazes.\"\n  STR_GAMEOVER_4: \"Os alienígenas constroem bases nas regiões polares e começam a derreter o gelo. Em breve o mundo será apenas um vasto oceano. Os restos da espécie humana são reunidos em campos de concentração e utilizados em experiências horríveis de reprodução. Os céus escurecem e uma enorme pestilência espalha-se sobre a Terra.\"\n  STR_GAMEOVER_5: \"É impossível resistir à tirania alienígena. Todos os que se revoltam acabam por perecer face ao enorme potencial bélico dos invasores. O resto da humanidade não tem tanta sorte. O nosso planeta é transformado num mundo alienígena e espécie humana é exterminada de forma horrenda.\"\n  STR_OUTRO_1: \"O túmulo é destruído e um enorme rugido emerge do sarcófago no centro.{NEWLINE}\\\"Criaturas loucas. Vão todos morrer...\\\"\"\n  STR_OUTRO_2: \"... ninguém pode escapar.\"\n  STR_OUTRO_3: \"Uma enorme explosão irrompe do túmulo e rasga as entranhas da cidadela. Os céus enchem-se de fumo e destroços. Os planos dos alienígenas foram arruinados...\"\n  STR_OUTRO_4: \"A enorme estrutura da T'leth entra em colapso. As suas torres reluzentes e os seus salões em adamântio vomitam agora fumo e chamas.\"\n  STR_OUTRO_5: \"A fortaleza alienígena precipita-se nos oceanos, acompanhada pelos gritos de toneladas de metal retorcido e dos milhares de almas no seu interior. Os sonhos de conquista do Grande Sonhador foram extintos de uma vez por todas.\"\n  STR_OUTRO_6: \"Com um último gemido avassalador, T'leth é completamente destruída.{NEWLINE}A ameaça alienígena desapareceu e a Terra está salva...\"\n  STR_OUTRO_7: \"Um belo e pacífico planeta azul, num canto distante da galáxia.\"\n  STR_OUTRO_8: \"O futuro próximo, um lugar seguro para viver.\"\n  STR_OUTRO_9: \"A ameaça alienígena que pairava sobre a Terra foi há muito vencida.\"\n  STR_OUTRO_10: \"Vastas metrópoles alojam populações de milhares de milhões.\"\n  STR_OUTRO_11: \"Os feitos da guerra entre as forças X-Com e os alienígenas fazem parte de histórias para crianças.\"\n  STR_OUTRO_12: \"Mas todas as lendas têm um fundo de verdade...\"\n  STR_RISE_1: \"T'leth, conhecida por muitos nomes, em várias lendas de todo o mundo.\"\n  STR_RISE_2: \"Com um ruído explosivo que ecoa através do planeta, T'leth começa a erguer-se lentamente do fundo do mar.\"\n  STR_RISE_3: \"A enorme estrutura emerge nas águas do golfo do México.\"\n  STR_RISE_4: \"Construída com mais de 400 mil milhões de toneladas de metal, esta é a enorme cidadela onde jaz o corpo do Derradeiro Alienígena, aprisionado no fundo do oceano por mais de 65 milhões de anos. Agora, esta terrível entidade espacial começa a dar sinais de vida.\"\n  STR_RISE_5: \"As águas espumam em turbilhões imensos, enquanto o sarcófago do Grande Sonhador emerge à luz do dia...\"\n  STR_RISE_6: \"...um dia que será curto, a menos que as forças X-Com consigam travar o exército alienígena.\"\n  STR_YOU_HAVE_FAILED: \"Falhámos a nossa missão ao não conseguirmos impedir as forças alienígenas. As organizações financiadoras, desiludidas com as nossas competências, tentam negociar uma solução não-militar com os alienígenas. Mas os invasores têm planos muito diferentes, e cedo o todo o mundo descobre a verdade...\"\n  STR_TOTAL_UC: \"TOTAL\"\n  STR_INCOME: \"Rendimento\"\n  STR_EXPENDITURE: \"Despesa\"\n  STR_MAINTENANCE: \"Manutenção\"\n  STR_BALANCE: \"Balanço\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"Atividade OSNI por mar\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"Atividade OSNI por zona\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"Atividade X-Com por mar\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"Atividade X-Com por zona\"\n  STR_FINANCE: \"Finanças\"\n  STR_DATE_FIRST: \"{0}\"\n  STR_DATE_SECOND: \"{0}\"\n  STR_DATE_THIRD: \"{0}\"\n  STR_DATE_FOURTH: \"{0}\"\n  STR_FINANCE_THOUSANDS: \"$1000\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Não há materiais especiais suficientes para produzir:{NEWLINE}{0}{NEWLINE}em{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Não há dinheiro suficiente para produzir:{NEWLINE}{0}{NEWLINE}em{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"A produção de:{NEWLINE}{0}{NEWLINE}em{NEWLINE}{1}{NEWLINE}está completa\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"A construção de:{NEWLINE}{0}{NEWLINE}em{NEWLINE}{1}{NEWLINE}está completa\"\n  STR_OK_5_SECONDS: \"OK - 5 segs\"\n  STR_RESEARCH_COMPLETED: \"Investigação completa\"\n  STR_VIEW_REPORTS: \"VER RELATÓRIOS\"\n  STR_WE_CAN_NOW_RESEARCH: \"Nova investigação disponível\"\n  STR_WE_CAN_NOW_PRODUCE: \"Nova produção disponível\"\n  STR_SUNDAY: \"DOMINGO\"\n  STR_MONDAY: \"SEGUNDA\"\n  STR_TUESDAY: \"TERÇA\"\n  STR_WEDNESDAY: \"QUARTA\"\n  STR_THURSDAY: \"QUINTA\"\n  STR_FRIDAY: \"SEXTA\"\n  STR_SATURDAY: \"SÁBADO\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Não há {0} suficiente para reabastecer {1} em {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Não há {0} para rearmar {1} em {2}\"\n  STR_UFO_IS_NOT_RECOVERED: \"O OSNI não foi recuperado.\"\n  STR_UFO_IS_RECOVERED: \"OSNI recuperado\"\n  STR_CRAFT_IS_LOST: \"Aerosubmersível perdido\"\n  STR_TERROR_CONTINUES: \"A atividade alienígena continua\"\n  STR_ALIENS_DEFEATED: \"Os alienígenas foram derrotados\"\n  STR_BASE_IS_LOST: \"Base destruída\"\n  STR_BASE_IS_SAVED: \"Base salva\"\n  STR_ALIEN_BASE_STILL_INTACT: \"A colónia continua operacional\"\n  STR_ALIEN_BASE_DESTROYED: \"Colónia alienígena destruída\"\n  STR_ALIENS_KILLED: \"ALIENÍGENAS MORTOS\"\n  STR_ALIEN_CORPSES_RECOVERED: \"CADÁVERES ALIENÍGENAS RECUPERADOS\"\n  STR_LIVE_ALIENS_RECOVERED: \"ALIENÍGENAS VIVOS CAPTURADOS\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"ARTEFACTOS ALIENÍGENAS RECUPERADOS\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"COMANDO DE COLÓNIA ALIENÍGENA DESTRUÍDO\"\n  STR_ALIEN_SYNOMIUM_DEVICE_DESTROYED: \"SINÓMIO ALIENÍGENA DESTRUÍDO\"\n  STR_ALIEN_SYNOMIUM_DEVICE_FAILED: \"SINÓMIO ALIENÍGENA INTACTO\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"CIVIS MORTOS POR ALIENÍGENAS\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"CIVIS MORTOS POR AGENTES X-COM\"\n  STR_CIVILIANS_SAVED: \"CIVIS RESGATADOS\"\n  STR_XCOM_OPERATIVES_KILLED: \"AGENTES X-COM MORTOS EM COMBATE\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"AGENTES X-COM DESAPARECIDOS EM COMBATE\"\n  STR_TANKS_DESTROYED: \"PLATAFORMA DE ARMAS X-COM DESTRUÍDA\"\n  STR_XCOM_CRAFT_LOST: \"SUBMERSÍVEL X-COM PERDIDO\"\n  STR_UFO_RECOVERY: \"RECUPERAÇÃO DE OSNI\"\n  STR_ALIEN_BASE_RECOVERY: \"RECUPERAÇÃO DE COLÓNIA ALIENÍGENA\"\n  STR_BASE_UNDER_ATTACK: \"{0} está sob ataque!\"\n  STR_BASE_DEFENSES_INITIATED: \"SISTEMAS DE DEFESA ATIVADOS\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"O ESCUDO REPELIU O OSNI!\"\n  STR_FIRING: \"A DISPARAR\"\n  STR_HIT: \"ALVO ATINGIDO!\"\n  STR_UFO_DESTROYED: \"OSNI DESTRUÍDO!\"\n  STR_MISSED: \"FALHOU!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Vender itens/Demitir pessoal\"\n  STR_VALUE_OF_SALES: \"VALOR DAS VENDAS> {ALT}{0}\"\n  STR_FUNDS: \"FUNDOS>{ALT}{0}\"\n  STR_SELL_SACK: \"Vender/Demitir\"\n  STR_VALUE: \"Valor\"\n  STR_CRAFT_: \"VEÍCULO> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"RECUPERAÇÃO DE OSNI AFUNDADO\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"PROCEDER COM CAUTELA - É altamente provável que hajam alienígenas no interior ou nas proximidades do OSNI. A missão será bem-sucedida quando todas as unidades inimigas forem eliminadas ou neutralizadas. Só depois poderemos iniciar a recuperação dos restos do OSNI, artefactos e cadáveres de alienígenas. Para abortar a missão, retorne os aquanautas X-Com ao veículo de transporte e clique no ícone \\\"Abortar missão\\\".\"\n  STR_UFO_GROUND_ASSAULT: \"ASSALTO A OSNI\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"O objetivo desta missão é explorar o local de ancoragem e, se possível, conseguir aceder ao OSNI. A missão será bem-sucedida quando todas as unidades inimigas forem eliminadas ou neutralizadas. Só depois poderemos iniciar a recuperação dos destroços do OSNI, artefactos e cadáveres de alienígenas. Para abortar a missão, retorne os agentes X-Com ao veículo de transporte e clique no ícone \\\"Abortar missão\\\".\"\n  STR_BASE_DEFENSE: \"DEFESA DE BASE\"\n  STR_BASE_UC_: \"BASE> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"Um submersível alienígena atracou nas proximidades. A nossa base está em sério perigo. Todos os submersíveis X-Com e o pessoal não-militar foram evacuados conforme o protocolo. As tropas alienígenas entrarão na base através das docas ou da eclusa de ar. Temos de defender a base e as suas instalações vitais a todo o custo, num combate até à morte. Se clicar no ícone \\\"Abortar missão\\\" as nossas tropas render-se-ão e a base será destruída.\"\n  STR_ALIEN_COLONY_ATTACK_MISSION: \"ASSALTO A COLÓNIA ALIENÍGENA\"\n  STR_ALIEN_BASE_ASSAULT: \"COLÓNIA ALIENÍGENA - PARTE 1\"\n  STR_ALIEN_COLONY_P1_BRIEFING: \"Esta missão é um ataque direto a uma colónia alienígena, uma instalação constituída por dois níveis. Para prosseguir para o piso inferior dirija todos os aquanatas para o elevador reluzente no primeiro complexo, e clique no ícone \\\"Abortar missão\\\". Todo o equipamento deixado para trás irá permanecer abandonado até o objetivo no segundo piso for cumprido. Para desistir da missão, coloque os aquanautas restantes no submarino e clique no ícone \\\"Abortar missão\\\".\"\n  STR_ALIEN_COLONY_P2: \"COLÓNIA ALIENÍGENA - PARTE 2\"\n  STR_ALIEN_COLONY_P2_BRIEFING: \"Após atravessarmos o primeiro piso, garantimos acesso ao interior da colónia alienígena. O nosso objetivo é localizar e destruir o Sinómio, um aparelho responsável pelo controlo do centro de comando, ou alternativamente eliminar todos os alienígenas na base. Para abortar a missão, dirija todos os aquanautas restantes ao ponto de início e clique no ícone \\\"Abortar missão\\\". Todo o equipamento X-Com funcional será retornado à base.\"\n  STR_ALIENS_LAUNCH_PORT_TERROR: \"FORÇAS ALIENÍGENAS{NEWLINE}ATACAM PORTO EM:\"\n  STR_PORT_TERROR: \"FORÇAS ALIENÍGENAS ATACAM PORTO\"\n  STR_PORT_TERROR_BRIEFING: \"Os alienígenas lançaram um ataque contra uma zona portuária. Todos os civis e infraestruturas da área encontram-se em sério risco. O nosso objetivo é eliminar as forças alienígenas e proteger todos os civis inocentes. Para cancelar a missão, retorne os aquanautas ao veículo de transporte e clique no ícone \\\"Abortar missão\\\".\"\n  STR_ALIENS_LAUNCH_ISLAND_TERROR: \"FORÇAS ALIENÍGENAS{NEWLINE}ATACAM ILHA EM:\"\n  STR_ISLAND_TERROR: \"FORÇAS ALIENÍGENAS ATACAM ILHA\"\n  STR_ISLAND_TERROR_BRIEFING: \"Os alienígenas lançaram um ataque contra uma ilha. Toda a população civil encontra-se em sério risco. O nosso objetivo é eliminar as forças alienígenas e proteger todos os civis inocentes. Para cancelar a missão, retorne os aquanautas ao veículo de transporte e clique no ícone \\\"Abortar missão\\\".\"\n  STR_ALIENS_ATTACK_SHIPPING_ROUTE: \"FORÇAS ALIENÍGENAS{NEWLINE}ATACAM ROTA MARÍTIMA\"\n  STR_CARGO_SHIP_P1: \"NAVIO DE CARGA - PARTE 1\"\n  STR_CARGO_SHIP_P2: \"NAVIO DE CARGA - PARTE 2\"\n  STR_CRUISE_SHIP_P1: \"CRUZEIRO - PARTE 1\"\n  STR_CRUISE_SHIP_P2: \"CRUZEIRO - PARTE 2\"\n  STR_SHIP_RESCUE_MISSION: \"RESGATE DE NAVIO\"\n  STR_SHIP_RESCUE_P1_BRIEFING: \"Esta é uma missão de extermínio. O nosso objetivo é eliminar todas as forças alienígenas no navio e proteger todos civis que encontrarmos a bordo. Os alienígenas estão dispersos por todos os pisos e é essencial eliminar todas as unidades inimigas no convés antes de descermos aos níveis inferiores. Para cancelar a missão, retorne os aquanautas ao veículo de transporte e clique no ícone \\\"Abortar missão\\\".\"\n  STR_SHIP_RESCUE_P2_BRIEFING: \"Após eliminarmos as forças inimigas no convés, podemos finalmente proceder aos pisos inferiores. As nossas tropas desceram até ao porão através do elevador de carga. Temos de eliminar todos os alienígenas neste nível para concluirmos a missão com sucesso. Para abortar a missão, retorne os aquanautas ao elevador de acesso e clique no ícone \\\"Abortar missão\\\".\"\n  STR_ALIEN_ACTIVITY_DETECTED: \"ATIVIDADE ALIENÍGENA DETETADA\"\n  STR_ALIEN_CONTACT_SITE_MISSION: \"LOCAL DE CONTACTO ALIENÍGENA\"\n  STR_ARTIFACT_SITE_P1: \"ARTEFACTO ALIENÍGENA - PARTE 1\"\n  STR_ARTIFACT_SITE_P1_BRIEFING: \"Esta missão é um ataque direto a uma base de comunicação alienígena recentemente ativada. Esta instalação é constituída por dois níveis: um aglomerado de pirâmides à superfície do leito oceânico e um complexo alienígena subterrâneo. Dirija todos os aquanautas para a entrada do complexo e clique no ícone \\\"Abortar missão\\\" para prosseguir ao nível seguinte. Para abandonar a missão, retorne todos os aquanautas ao veículo de transporte e clique no ícone \\\"Abortar missão\\\".\"\n  STR_ARTIFACT_SITE_P2: \"ARTEFACTO ALIENÍGENA - PARTE 2\"\n  STR_ARTIFACT_SITE_P2_BRIEFING: \"Após atravessarmos a rede de pirâmides e acedermos ao complexo, o nosso objetivo é claro: temos ganhar acesso ao centro da instalação alienígena e destruir o Sinómio de controlo molecular para completarmos a missão. Para abortar a missão retorne os aquanautas restantes ao elevador de acesso e clique no ícone \\\"Abortar missão\\\".\"\n  STR_SIGSBEE_DEEP_MISSION: \"MISSÃO NA FOSSA DE SIGSBEE{NEWLINE}CIDADELA ALIENÍGENA - NÍVEL 1\"\n  STR_TLETH_P1_BRIEFING: \"Estamos a entrar num nível desconhecido. A partir deste local não sabemos ao certo o que nos aguarda. As nossas informações apenas mencionam a existência de mais dois níveis na cidadela alienígena. Logo, o nosso objetivo é localizarmos a entrada para o próximo. Assim que encontrar este acesso, dirija todos os aquanautas para a zona de saída e clique no ícone \\\"Abortar missão\\\" para prosseguir. Se a missão for cancelada noutro local as nossas tropas serão derrotadas.\"\n  STR_TLETH_ATTACK_MISSION: \"ASSALTO A T'LETH{NEWLINE}CIDADELA ALIENÍGENA - NÍVEL 2\"\n  STR_TLETH_P2_BRIEFING: \"Mais uma vez não sabemos ao certo o que nos aguarda. Só há mais um nível na cidadela alienígena, e o nosso objetivo é localizarmos a entrada. Assim que encontrar este acesso, dirija todos os aquanautas para a zona de saída e clique no ícone \\\"Abortar missão\\\" para prosseguir. Se a missão for cancelada noutro local as nossas tropas serão derrotadas. \"\n  STR_FINAL_TLETH_MISSION: \"ASSALTO FINAL A T'LETH{NEWLINE}CIDADELA ALIENÍGENA - NÍVEL 3\"\n  STR_TLETH_P3_BRIEFING: \"Estamos muito próximos do nosso objetivo. A partir daqui a nossa missão é encontrar a cripta do Derradeiro Alienígena. Após encontrarmos o local, temos de destruir os oito geradores de energia ligados ao túmulo para finalmente pormos um fim à ameaça alienígena. Não podemos desistir agora! Se a missão for abortada os nossos esforços serão em vão.\"\n  STR_TLETH_P1: \"CIDADELA ALIENÍGENA - NÍVEL 1\"\n  STR_TLETH_P2: \"CIDADELA ALIENÍGENA - NÍVEL 2\"\n  STR_TLETH_P3: \"CIDADELA ALIENÍGENA - NÍVEL 3\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"NÃO HÁ DOCAS LIVRES PARA A PRODUÇÃO!{SMALLLINE}Cada submersível atribuído a uma base, transferido, comprado ou construído ocupa uma doca. Construa uma nova doca ou transfira um submersível para outra base.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"NÃO HÁ DOCAS LIVRES PARA EFETUAR A COMPRA!{SMALLLINE}Cada submersível atribuído a uma base, transferido, comprado ou construído ocupa uma doca. Construa uma nova doca ou transfira um submersível para outra base.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"NÃO HÁ DOCAS LIVRES PARA A TRANSFERÊNCIA!{SMALLLINE}Cada submersível atribuído a uma base, transferido, comprado ou construído ocupa uma doca. Construa uma nova doca ou transfira um submersível para outra base.\"\n  STR_CANNOT_BUILD_HERE: \"IMPOSSÍVEL CONSTRUIR AQUI!{SMALLLINE}Todas as construções devem ser feitas ao lado de uma instalação existente.\"\n  STR_NO_FREE_ACCOMODATION: \"NÃO HÁ HABITAÇÕES LIVRES!{SMALLLINE}A base de destino não tem espaço suficiente nos blocos habitacionais.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"NÃO HÁ ESPAÇO DE TRABALHO SUFICIENTE!{SMALLLINE}Construa uma nova oficina ou reduza o trabalho noutros projetos.\"\n  STR_NOT_ENOUGH_MONEY: \"NÃO TEM DINHEIRO SUFICIENTE!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"NÃO HÁ ESPAÇO EM ARMAZÉM SUFICIENTE!{SMALLLINE}Construa um novo armazém ou transfira equipamento para outras bases.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"NÃO HÁ HABITAÇÕES SUFICIENTES{SMALLLINE}Construa um novo bloco habitacional ou transfira pessoal para outras bases.\"\n  STR_LAUNCH_INTERCEPTION: \"LANÇAR INTERCEÇÃO\"\n  STR_CRAFT: \"SUBMERSÍVEL\"\n  STR_STATUS: \"ESTADO\"\n  STR_BASE: \"BASE\"\n  STR_READY: \"PRONTO\"\n  STR_OUT: \"FORA\"\n  STR_REPAIRS: \"A REPARAR\"\n  STR_REFUELLING: \"A REABASTECER\"\n  STR_REARMING: \"A REARMAR\"\n  STR_TARGET: \"ALVO: {0}\"\n  STR_WAY_POINT: \"PONTO DE REFERÊNCIA\"\n  STR_ARE_YOU_SURE_CYDONIA: \"Tem a certeza de que deseja enviar este veículo numa missão a T'leth?\"\n  STR_YES: \"SIM\"\n  STR_NO: \"NÃO\"\n  STR_SELECT_DESTINATION: \"SELECIONAR DESTINO\"\n  STR_CYDONIA: \"T'LETH\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"SELECIONAR LOCAL PARA A NOVA BASE\"\n  STR_RETURN_TO_BASE: \"REGRESSAR À BASE\"\n  STR_SELECT_NEW_TARGET: \"SELECIONAR NOVO ALVO\"\n  STR_PATROL: \"PATRULHAR\"\n  STR_STATUS_: \"ESTADO>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"DANIFICADO - A REGRESSAR À BASE\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"POUCO COMBUSTÍVEL - A REGRESSAR À BASE\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"MISSÃO COMPLETA - A REGRESSAR À BASE\"\n  STR_PATROLLING: \"EM PATRULHA\"\n  STR_TAILING_UFO: \"A PERSEGUIR OSNI\"\n  STR_INTERCEPTING_UFO: \"A INTERCETAR OSNI-{0}\"\n  STR_RETURNING_TO_BASE: \"A REGRESSAR À BASE\"\n  STR_DESTINATION_UC_: \"DESTINO: {0}\"\n  STR_BASE_UC: \"BASE>{ALT}{0}\"\n  STR_SPEED_: \"VELOCIDADE>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"VELOCIDADE MÁXIMA>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"PROFUNDIDADE> {ALT}{0}\"\n  STR_AIRBORNE: \"NO AR\"\n  STR_VERY_LOW: \"BAIXA\"\n  STR_LOW_UC: \"MÉDIA\"\n  STR_HIGH_UC: \"ALTA\"\n  STR_VERY_HIGH: \"MUITO ALTA\"\n  STR_FUEL: \"COMBUSTÍVEL>{ALT}{0}\"\n  STR_WEAPON_ONE: \"ARMA-1>{ALT}{0}\"\n  STR_NONE_UC: \"NENHUMA\"\n  STR_ROUNDS_: \"MUNIÇÃO>{ALT}{0}\"\n  STR_WEAPON_TWO: \"ARMA-2>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"VEÍCULO\"\n  STR_BASE_: \"Base>{0}\"\n  STR_NAME_UC: \"NOME\"\n  STR_AMMO_: \"MUNIÇÃO>{ALT}{0}\"\n  STR_CREW: \"TRIPULAÇÃO\"\n  STR_EQUIPMENT_UC: \"EQUIPAMENTO\"\n  STR_ARMOR: \"ARMADURA\"\n  STR_MAX: \"MÁX>{ALT}{0}\"\n  STR_ROOKIE: \"Grumete\"\n  STR_SQUADDIE: \"Marinheiro\"\n  STR_SERGEANT: \"Guarda-marinha\"\n  STR_CAPTAIN: \"Tenente\"\n  STR_COLONEL: \"Comandante\"\n  STR_COMMANDER: \"Capitão\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"{0}: selecionar tropas\"\n  STR_SORT_BY: \"ORDENAR POR...\"\n  STR_ORIGINAL_ORDER: \"ORDEM ORIGINAL\"\n  STR_MISSIONS2: \"MISSÕES\"\n  STR_KILLS2: \"MORTOS\"\n  STR_WOUND_RECOVERY2: \"EM RECUPERAÇÃO\"\n  STR_SPACE_AVAILABLE: \"ESPAÇO DISPONÍVEL>{ALT}{0}\"\n  STR_SPACE_USED: \"ESPAÇO UTILIZADO>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"ESPAÇO USADO\"\n  STR_RANK: \"POSTO\"\n  STR_WOUNDED: \"FERIDO\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Equipar {0}\"\n  STR_DEFENSE_VALUE: \"Pontos de defesa\"\n  STR_HIT_RATIO: \"Precisão de fogo\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}perto de{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"Iniciar missão?\"\n  STR_SELECT_ARMAMENT: \"Selecionar armamento\"\n  STR_AMMUNITION_AVAILABLE: \"MUNIÇÃO DISPONÍVEL\"\n  STR_ARMAMENT: \"ARMAMENTO\"\n  STR_NOT_AVAILABLE: \"N.D.\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"SELECIONAR ARMADURA PARA{NEWLINE}{ALT}{0}\"\n  STR_TYPE: \"TIPO\"\n  STR_PLASTIC_AQUA_ARMOR_UC: \"ARMADURA DE AQUAPLÁSTICO\"\n  STR_ION_ARMOR_UC: \"ARMADURA DE IÕES\"\n  STR_MAGNETIC_ION_ARMOR_UC: \"ARMADURA MAGNÉTICA\"\n  STR_PLASTIC_AQUA_ARMOR_UFOPEDIA: \"Fabricada através de aquaplástico, a nova substância alienígena, esta armadura melhora as hipóteses de sobrevivência dos nossos aquanautas contra forças hostis.\"\n  STR_ION_ARMOR_UFOPEDIA: \"A melhor proteção atualmente disponível para tropas em campo, esta poderosa armadura é movida por uma fonte de energia à base de iões e aumenta de forma extraordinária a força e destreza do utilizador.\"\n  STR_MAGNETIC_ION_ARMOR_UFOPEDIA: \"Esta versão melhorada da armadura de iões está equipada com um sistema de navegação magnético, que permite a liberdade total de movimento em meios subaquáticos.\"\n  STR_SELECT_ARMOR: \"Selecionar armadura\"\n  STR_NORTH: \"NORTE\"\n  STR_NORTH_EAST: \"NORDESTE\"\n  STR_EAST: \"ESTE\"\n  STR_SOUTH_EAST: \"SUDESTE\"\n  STR_SOUTH: \"SUL\"\n  STR_SOUTH_WEST: \"SUDOESTE\"\n  STR_WEST: \"OESTE\"\n  STR_NORTH_WEST: \"NOROESTE\"\n  STR_SELECT_ACTION: \"SELECIONAR AÇÃO\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"CONTINUAR PERSEGUIÇÃO E INTERCETAR\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"PERSEGUIR SEM INTERCEÇÃO\"\n  STR_VERY_LARGE: \"MUITO GRANDE\"\n  STR_LARGE: \"GRANDE\"\n  STR_MEDIUM_UC: \"MÉDIO\"\n  STR_SMALL: \"PEQUENO\"\n  STR_VERY_SMALL: \"MUITO PEQUENO\"\n  STR_GROUNDED: \"NO FUNDO DO MAR\"\n  STR_DETECTED: \"Detetado\"\n  STR_SIZE_UC: \"TAMANHO\"\n  STR_ALTITUDE: \"PROFUNDIDADE\"\n  STR_HEADING: \"DIREÇÃO\"\n  STR_SPEED: \"VELOCIDADE\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"CENTRAR EM OSNI-TEMPO=5 segs\"\n  STR_TRACKING_LOST: \"ALVO PERDIDO\"\n  STR_REDIRECT_CRAFT: \"REDIRECIONAR VEÍCULO\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"IR PARA A ÚLTIMA LOCALIZAÇÃO DO ALVO\"\n  STR_UFO_: \"OSNI-{0}\"\n  STR_ALIEN_BASE_: \"COLÓNIA ALIENÍGENA-{0}\"\n  STR_CRASH_SITE_: \"LOCAL DE NAUFRÁGIO-{0}\"\n  STR_LANDING_SITE_: \"LOCAL DE ANCORAGEM-{0}\"\n  STR_WAY_POINT_: \"PONTO DE REFERÊNCIA-{0}\"\n  STR_TERROR_SITE: \"LOCAL DE TERROR-{0}\"\n  STR_ARTIFACT_SITE: \"LOCAL DE ARTEFACTO-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}chegou a{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"A patrulhar\"\n  STR_ALIEN_ORIGINS: \"Origens alienígenas\"\n  STR_THE_ULTIMATE_THREAT: \"A derradeira ameaça\"\n  STR_TLETH_ALIEN_CITY: \"T'leth, a cidadela alienígena\"\n  STR_UFOPAEDIA: \"OSNIpédia\"\n  STR_XCOM_CRAFT_ARMAMENT: \"VEÍCULOS E ARMAMENTO X-COM\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"SISTEMAS DE ARMAS SUBMERSÍVEIS\"\n  STR_WEAPONS_AND_EQUIPMENT: \"ARMAS E EQUIPAMENTO\"\n  STR_ALIEN_ARTIFACTS: \"ARTEFACTOS AQUÁTICOS\"\n  STR_BASE_FACILITIES: \"INSTALAÇÕES X-COM\"\n  STR_ALIEN_LIFE_FORMS: \"CRIATURAS ALIENÍGENAS\"\n  STR_ALIEN_RESEARCH_UC: \"TECNOLOGIA ALIENÍGENA\"\n  STR_UFO_COMPONENTS: \"NOVAS TECNOLOGIAS SUBMERSÍVEIS\"\n  STR_UFOS: \"OSNIS\"\n  STR_SELECT_ITEM: \"SELECIONAR ITEM\"\n  STR_ACCELERATION: \"ACELERAÇÃO>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"COMBUSTÍVEL>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"SISTEMAS DE ARMAS>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"BLINDAGEM>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"ESPAÇO PARA CARGA>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"SUPORTE PARA SASs>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Dano\"\n  STR_RANGE: \"Alcance\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Precisão\"\n  STR_RE_LOAD_TIME: \"Intervalo de fogo\"\n  STR_SECONDS: \"{0}s\"\n  STR_DAMAGE_ARMOR_PIERCING: \"PERFURANTE\"\n  STR_DAMAGE_INCENDIARY: \"FÓSFORO\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"EXPLOSIVO\"\n  STR_DAMAGE_LASER_BEAM: \"FEIXE GAUSS\"\n  STR_DAMAGE_PLASMA_BEAM: \"ONDA SÓNICA\"\n  STR_DAMAGE_STUN: \"GELO\"\n  STR_DAMAGE_MELEE: \"CORPO A CORPO\"\n  STR_DAMAGE_ACID: \"ÁCIDO\"\n  STR_DAMAGE_SMOKE: \"FUMO\"\n  STR_SHOT_TYPE: \"TIPO\"\n  STR_ACCURACY_UC: \"PRECISÃO\"\n  STR_TIME_UNIT_COST: \"UTs\"\n  STR_DAMAGE_UC: \"TIPO DE DANO\"\n  STR_AMMO: \"MUNIÇÃO\"\n  STR_SHOT_TYPE_AUTO: \"Rajada\"\n  STR_SHOT_TYPE_SNAP: \"Simples\"\n  STR_SHOT_TYPE_AIMED: \"Preciso\"\n  STR_CONSTRUCTION_TIME: \"Tempo de construção\"\n  STR_CONSTRUCTION_COST: \"Valor de construção\"\n  STR_MAINTENANCE_COST: \"Custo de manutenção\"\n  STR_LOW: \"Baixo\"\n  STR_MEDIUM: \"Médio\"\n  STR_HIGH: \"Alto\"\n  STR_CRAFT_WEAPON: \"Armamento para submersível\"\n  STR_CRAFT_AMMUNITION: \"Munição para submersíveis\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Sistema de armas pesadas\"\n  STR_WEAPON: \"Arma\"\n  STR_AMMUNITION: \"Munição\"\n  STR_EQUIPMENT: \"Equipamento\"\n  STR_ALIEN_CORPSE: \"Cadáver alienígena\"\n  STR_UFO_COMPONENT: \"Componente OSNI\"\n  STR_PERSONAL_ARMOR: \"Armadura pessoal\"\n  STR_RAW_MATERIALS: \"Matéria-prima\"\n  STR_HWP_SOLID_HARPOON_BOLTS: \"Harpões SWS\"\n  STR_ALIEN: \"Alienígena\"\n  STR_AQUATOID: \"Aquatóide\"\n  STR_GILLMAN: \"Homem-guelra\"\n  STR_LOBSTERMAN: \"Homem-lagosta\"\n  STR_TASOTH: \"Tasoth\"\n  STR_CALCINITE: \"Calcinite\"\n  STR_DEEP_ONE: \"Ser das profundezas\"\n  STR_BIODRONE: \"Biodisco\"\n  STR_TENTACULAT: \"Tentaculat\"\n  STR_TRISCENE: \"Triscénio\"\n  STR_HALLUCINOID: \"Alucinóide\"\n  STR_XARQUID: \"Xarquídeo\"\n  STR_ZOMBIE: \"Zombie\"\n  STR_LIVE_COMMANDER: \"Comandante\"\n  STR_LIVE_NAVIGATOR: \"Navegador\"\n  STR_LIVE_MEDIC: \"Médico\"\n  STR_LIVE_TECHNICIAN: \"Técnico\"\n  STR_LIVE_SQUAD_LEADER: \"Sargento\"\n  STR_LIVE_SOLDIER: \"Soldado\"\n  STR_LIVE_TERRORIST: \"Agente terrorista\"\n  STR_AQUATOID_COMMANDER: \"Comandante Aquatóide\"\n  STR_AQUATOID_NAVIGATOR: \"Navegador Aquatóide\"\n  STR_AQUATOID_MEDIC: \"Médico Aquatóide\"\n  STR_AQUATOID_TECHNICIAN: \"Técnico Aquatóide\"\n  STR_AQUATOID_SQUAD_LEADER: \"Sargento Aquatóide\"\n  STR_AQUATOID_SOLDIER: \"Soldado Aquatóide\"\n  STR_GILLMAN_COMMANDER: \"Comandante Homem-guelra\"\n  STR_GILLMAN_TECHNICIAN: \"Técnico Homem-guelra\"\n  STR_GILLMAN_SQUAD_LEADER: \"Sargento Homem-guelra\"\n  STR_GILLMAN_SOLDIER: \"Soldado Homem-guelra\"\n  STR_LOBSTERMAN_COMMANDER: \"Comandante Homem-lagosta\"\n  STR_LOBSTERMAN_NAVIGATOR: \"Navegador Homem-lagosta\"\n  STR_LOBSTERMAN_TECHNICIAN: \"Técnico Homem-lagosta\"\n  STR_LOBSTERMAN_SQUAD_LEADER: \"Sargento Homem-lagosta\"\n  STR_LOBSTERMAN_SOLDIER: \"Soldado Homem-lagosta\"\n  STR_TASOTH_SQUAD_LEADER: \"Sargento Tasoth\"\n  STR_TASOTH_SOLDIER: \"Soldado Tasoth\"\n  STR_CALCINITE_TERRORIST: \"Calcinite - Terrorista\"\n  STR_DEEP_ONE_TERRORIST: \"Ser das Profundezas - Terrorista\"\n  STR_BIODRONE_TERRORIST: \"Biodisco - Terrorista\"\n  STR_TENTACULAT_TERRORIST: \"Tentaculat - Terrorista\"\n  STR_TRISCENE_TERRORIST: \"Triscénio - Terrorista\"\n  STR_HALLUCINOID_TERRORIST: \"Alucinóide - Terrorista\"\n  STR_XARQUID_TERRORIST: \"Xarquídeo - Terrorista\"\n  STR_ION_BEAM_ACCELERATORS: \"Aceleradores de iões\"\n  STR_MAGNETIC_NAVIGATION: \"Sistema de navegação magnético\"\n  STR_ALIEN_SUB_CONSTRUCTION: \"Métodos de construção OSNI\"\n  STR_ALIEN_CRYOGENICS: \"Criogenia alienígena\"\n  STR_ALIEN_CLONING: \"Clonagem alienígena\"\n  STR_ALIEN_LEARNING_ARRAYS: \"Matrizes de instrução alienígena\"\n  STR_ALIEN_IMPLANTER: \"Implantador alienígena\"\n  STR_EXAMINATION_ROOM: \"Sala de exames\"\n  STR_AQUA_PLASTICS: \"Aquaplástico\"\n  STR_ALIEN_REANIMATION_ZONE: \"Zona de reanimação alienígena\"\n  STR_PLASTIC_AQUA_ARMOR: \"Armadura de aquaplástico\"\n  STR_ION_ARMOR: \"Armadura de iões\"\n  STR_MAGNETIC_ION_ARMOR: \"Armadura magnética\"\n  STR_HWP_AQUA_JET_MISSILES: \"Torpedos aquajato\"\n  STR_HWP_DISPLACER_PWT: \"Torpedo de ondas de pulsão\"\n  STR_GAUSS_TECH: \"Tecnologia Gauss\"\n  STR_NEW_FIGHTER_FLYING_SUB: \"Novo caça aerosubmersível\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Novo caça-transportador\"\n  STR_THE_LATEST_FLYING_SUB: \"O Último Aerosubmersível\"\n  STR_ARMOR_PIERCING: \"PERFURANTE\"\n  STR_COELACANTH_GAS_CANNON: \"Celacanto/Canhão de gás\"\n  STR_COELACANTH_AQUA_JET: \"Celacanto/Aquajato\"\n  STR_COELACANTH_GAUSS: \"Celacanto/Gauss\"\n  STR_DISPLACER_SONIC: \"Deslocador/Canhão sónico\"\n  STR_DISPLACER_PWT: \"Deslocador/TOP\"\n  STR_AJAX_LAUNCHER: \"Lançador Ajax\"\n  STR_DUP_HEAD_LAUNCHER: \"Lançador TU\"\n  STR_CRAFT_GAS_CANNON: \"Canhão aquático\"\n  STR_PWT_CANNON: \"Canhão TOP\"\n  STR_GAUSS_CANNON: \"Canhão Gauss\"\n  STR_GAUSS_CANNON_AMMO: \"Munição de canhão Gauss\"\n  STR_SONIC_OSCILLATOR: \"Oscilador sónico\"\n  STR_AJAX_TORPEDOES: \"Torpedos Ajax\"\n  STR_DUP_HEAD_TORPEDOES: \"Torpedos de urânio\"\n  STR_CRAFT_GAS_CANNON_ROUNDS_X50: \"Cartuchos de gás(x50)\"\n  STR_SONIC_WAVE: \"Onda sónica\"\n  STR_PULSE_WAVE_TORPEDOES: \"Munição TOP\"\n  STR_SOLDIER: \"Aquanauta\"\n  STR_SCIENTIST: \"Cientista\"\n  STR_ENGINEER: \"Técnico\"\n  STR_NORTH_ATLANTIC: \"Atlântico Norte\"\n  STR_SOUTH_ATLANTIC: \"Atlântico Sul\"\n  STR_NORTH_PACIFIC: \"Pacífico Norte\"\n  STR_SOUTH_PACIFIC: \"Pacífico Sul\"\n  STR_MEDITERRANEAN: \"Mediterrâneo\"\n  STR_SOUTH_CHINA_SEA: \"Mar do sul da China\"\n  STR_INDIAN_OCEAN: \"Oceano Índico\"\n  STR_THE_EAST_SEA: \"Mar do Japão\"\n  STR_NORTH_SEA: \"Mar do Norte\"\n  STR_CARRIBEAN: \"Caraíbas\"\n  STR_ANTARCTIC: \"Antártico\"\n  STR_ARCTIC: \"Ártico\"\n  STR_EURASIA: \"Eurásia\"\n  STR_NORTH_AMERICA: \"América do Norte\"\n  STR_AFRICA: \"África\"\n  STR_MAXIMUM_SPEED: \"Velocidade máxima\"\n  STR_TRANSMISSION_RESOLVER_UC: \"IDENTIFICADOR DE TRANSMISSÕES\"\n  STR_TRITON: \"TRITON\"\n  STR_HAMMERHEAD: \"HAMMERHEAD\"\n  STR_LEVIATHAN: \"LEVIATHAN\"\n  STR_BARRACUDA: \"BARRACUDA\"\n  STR_MANTA: \"MANTA\"\n  STR_UFO: \"OSNI\"\n  STR_AJAX: \"AJAX\"\n  STR_DUP_HEAD: \"TORPEDO DE URÂNIO\"\n  STR_CRAFT_GAS_CANNON_UC: \"CANHÃO AQUÁTICO\"\n  STR_PWT_CANNON_UC: \"CANHÃO TOP\"\n  STR_GAUSS_CANNON_UC: \"CANHÃO GAUSS\"\n  STR_SONIC_OSCILLATOR_UC: \"OSCILADOR SÓNICO\"\n  STR_DAMAGE_CAPACITY: \"Blindagem\"\n  STR_WEAPON_POWER: \"Poder de fogo\"\n  STR_WEAPON_RANGE: \"Alcance de fogo\"\n  STR_AIR_LOCK: \"Eclusa de ar\"\n  STR_LABORATORY: \"Laboratório\"\n  STR_WORKSHOP: \"Oficina\"\n  STR_STANDARD_SONAR: \"Sonar\"\n  STR_WIDE_ARRAY_SONAR: \"Sonar de longo alcance\"\n  STR_TORPEDO_DEFENSES: \"Defesas torpedo\"\n  STR_GENERAL_STORES: \"Armazéns\"\n  STR_ALIEN_CONTAINMENT: \"Contenção alienígena\"\n  STR_GAUSS_DEFENSES: \"Defesas Gauss\"\n  STR_SONIC_DEFENSES: \"Defesas sónicas\"\n  STR_PWT_DEFENSES: \"Defesas TOP\"\n  STR_BOMBARDMENT_SHIELD: \"Escudo de pressão\"\n  STR_MC_GENERATOR: \"Gerador molecular\"\n  STR_MC_LAB: \"Laboratório molecular\"\n  STR_TRANSMISSION_RESOLVER: \"Identificador de transmissões\"\n  STR_SUB_PEN: \"Doca\"\n  STR_USA: \"EUA\"\n  STR_ALASKA: \"ALASCA\"\n  STR_EU_SYNDICATE: \"EUROCORPORAÇÃO\"\n  STR_ARABIAN_BLOC: \"BLOCO ÁRABE\"\n  STR_EGYPTIAN_CARTEL: \"CARTEL EGÍPCIO\"\n  STR_AFRICA_CORP: \"AFRICA CORP\"\n  STR_BRAZILIAN_UNION: \"UNIÃO BRASILEIRA\"\n  STR_NEW_MEXICO: \"NOVO MÉXICO\"\n  STR_ASIAN_COALITION: \"COLIGAÇÃO ASIÁTICA\"\n  STR_SCANDINAVIA: \"ESCANDINÁVIA\"\n  STR_NEO_JAPAN: \"NEOJAPÃO\"\n  STR_FREE_CHINA: \"CHINA LIVRE\"\n  STR_AUSTRALASIA: \"AUSTRALÁSIA\"\n  STR_FED_KOREA: \"FEDERAÇÃO COREANA\"\n  STR_EURASIA_UC: \"EURÁSIA\"\n  STR_ICELANDIC_UNION: \"UNIÃO ISLANDESA\"\n  STR_TANK: \"Sistema de armas submersível\"\n  STR_CIVILIAN: \"Civil\"\n  STR_JAN: \"Jan\"\n  STR_FEB: \"Fev\"\n  STR_MAR: \"Mar\"\n  STR_APR: \"Abr\"\n  STR_MAY: \"Mai\"\n  STR_JUN: \"Jun\"\n  STR_JUL: \"Jul\"\n  STR_AUG: \"Ago\"\n  STR_SEP: \"Set\"\n  STR_OCT: \"Out\"\n  STR_NOV: \"Nov\"\n  STR_DEC: \"Dez\"\n  STR_INTERNATIONAL_RELATIONS: \"Relações internacionais\"\n  STR_COUNTRY: \"País\"\n  STR_FUNDING: \"Fundos\"\n  STR_CHANGE: \"Alteração\"\n  STR_WEAPON_SYSTEMS: \"SISTEMAS DE ARMAS\"\n  STR_HWPS: \"SAS\"\n  STR_DAMAGE_UC_: \"DANO>{ALT}{0}\"\n  STR_AIR_LOCK_UFOPEDIA: \"A eclusa de ar permite a transferência de equipamento e pessoal para dentro ou para fora da base subaquática. É sempre a primeira instalação a ser construída numa nova base. A zona da eclusa de ar é vulnerável à intrusão por forças hostis.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Cada bloco habitacional pode alojar o máximo de 50 pessoas. Estas instalações são básicas, mas funcionais.\"\n  STR_LABORATORY_UFOPEDIA: \"Estas instalações estão equipadas com a mais recente tecnologia para investigação de materiais, bioquímica e armamento, dispondo de acesso privilegiado às bases de dados dos melhores centros de investigação do planeta, tanto civis como militares. Cada laboratório possuí espaço de trabalho suficiente para 50 cientistas. \"\n  STR_WORKSHOP_UFOPEDIA: \"As oficinas dispõem de todo o equipamento necessário para fabricar produtos baseados nos projetos elaborados pelos laboratórios. Cada oficina possuí espaço de trabalho suficiente para 50 técnicos, mas os processos de fabricação de produtos podem também ocupar algum espaço adicional.\"\n  STR_STANDARD_SONAR_UFOPEDIA: \"Este sistema de deteção por sonar tem um alcance de 450 km a todas as profundidades e está ligado a uma rede de satélites geoestacionários para deteção à superfície. Cada sistema tem a probabilidade de 10% de detetar um veículo submerso ou à superfície por cada ciclo de 30 minutos.\"\n  STR_WIDE_ARRAY_SONAR_UFOPEDIA: \"Este sistema de deteção por sonar tem um alcance de 700 km a todas as profundidades e está ligado a uma rede de satélites geoestacionários para deteção à superfície. Cada sistema tem a probabilidade de 20% de detetar um veículo submerso ou à superfície por cada ciclo de 30 minutos.\"\n  STR_TORPEDO_DEFENSES_UFOPEDIA: \"Estes torpedos defensivos proporcionam alguma proteção contra incursões de submersíveis hostis que tentem ancorar perto da base.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"Todos os equipamentos, sistemas de armas, munições, material recuperado e Sistemas de Armas Submersíveis são guardados nos armazéns, incluindo o equipamento atribuído a submarinos na doca.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"É provável que alienígenas capturados com vida necessitem de ser mantidos em áreas de contenção especiais, a fim de preservar os seus sistemas vitais e eliminar quaisquer riscos possíveis. Estas instalações podem manter até dez formas de vida alienígena em unidades de contenção individuais.\"\n  STR_GAUSS_DEFENSES_UFOPEDIA: \"Estes sistemas de defesa Gauss proporcionam a proteção mais recente e eficaz contra incursões de naves inimigas. \"\n  STR_SONIC_DEFENSES_UFOPEDIA: \"Estes sistemas de defesa de oscilação sónica proporcionam uma proteção poderosa e eficiente contra forças hostis.\"\n  STR_PWT_DEFENSES_UFOPEDIA: \"Os torpedos de ondas de pulsão proporcionam o sistema de defesa mais eficaz contra ataques alienígenas. Estes projéteis subaquáticos geram ondas magnéticas capazes de desativar sistemas de defesa eletrónicos e possuem ogivas incrivelmente densas que penetram todos os tipos de blindagem.\"\n  STR_BOMBARDMENT_SHIELD_UFOPEDIA: \"O escudo de pressão repele submersíveis alienígenas que tentem ancorar perto de uma base X-Com, e gera um campo de ressonância durante tempo suficiente para que os sistemas de defesa voltem a abrir fogo, duplicando a sua eficácia.\"\n  STR_MC_GENERATOR_UFOPEDIA: \"Como os alienígenas utilizam tecnologia de controlo molecular para detetar a presença de outros seres vivos, esta instalação está equipada com um emissor molecular negativo, de forma a proteger uma base X-Com e ocultar a nossa presença.\"\n  STR_MC_LAB_UFOPEDIA: \"Cada laboratório molecular tem a capacidade para implantar e treinar até dez aquanautas de cada vez. Numa primeira fase, os aquanautas eleitos recebem implantes inseridos cirurgicamente nos seus cérebros. Vários programas de treino intensivo permitem o uso dos implantes em conjunto com um disruptor molecular para fins ofensivos durante situações de combate.\"\n  STR_TRANSMISSION_RESOLVER_UFOPEDIA: \"Os sistemas de comunicação alienígenas utilizam redes de implantação molecular. Esta instalação interceta transmissões feitas por OSNIs e descodifica a informação, o que permite identificar o tipo de OSNI, a espécie da tripulação e o tipo de missão a que se destina.\"\n  STR_SUB_PEN_UFOPEDIA: \"Cada doca pode albergar um aerosubmersível X-Com, dispondo de instalações próprias para manutenção, abastecimento e reparação. Um veículo atribuído a uma base deverá dispor de uma doca exclusiva. Mesmo que um veículo esteja fora em missão, a sua doca não pode ser utilizada por outros, sem que este seja transferido em primeiro lugar.\"\n  STR_DART_PISTOL_UFOPEDIA: \"A pistola de dardos X-Com é uma unidade pequena e certeira de alta potência, com capacidade para 12 tiros. Os dardos são disparados por um cartucho de gás alojado no carregador.\"\n  STR_JET_HARPOON_UFOPEDIA: \"Esta espingarda é uma arma precisa e mortífera, que dispara arpões de aço em carregadores de dez unidades. Cada arpão possui um reservatório de gás individual.\"\n  STR_GAS_CANNON_UFOPEDIA: \"O canhão de gás funciona com projéteis perfurantes, explosivos ou de fósforo. Esta é uma arma favorita entre aquanautas experientes.\"\n  STR_HYDRO_JET_CANNON_UFOPEDIA: \"O canhão de hidrojato é uma arma de infantaria pesada que dispara pequenos torpedos movidos a magnésio, e que funciona exclusivamente debaixo de água. Apesar de possuir grande potencial destrutivo, esta é uma arma de difícil uso devido ao seu tamanho e complexidade.\"\n  STR_TORPEDO_LAUNCHER_UFOPEDIA: \"Este lançador é uma arma devastadora que funciona com três tipos de torpedo equipados com unidades de propulsão individuais, dependendo, no entanto, de carregamento manual. Os tipos de munição disponível incluem dois projéteis explosivos, de carga grande ou pequena, e um projétil incendiário à base de fósforo. Esta arma funciona exclusivamente em ambientes submersos.\"\n  STR_GAUSS_PISTOL_UFOPEDIA: \"A pistola Gauss utiliza a tecnologia de aceleração de partículas, um novo desenvolvimento no armamento moderno. Esta arma é rápida, precisa, e funciona tanto à superfície como debaixo de água. A tecnologia Gauss é uma derivação da tecnologia plasma estudada na anterior guerra alienígena.\"\n  STR_GAUSS_PISTOL_CLIP_UFOPEDIA: \"A pistola Gauss utiliza a tecnologia de aceleração de partículas, um novo desenvolvimento no armamento moderno. Esta arma é rápida, precisa, e funciona tanto à superfície como debaixo de água. A tecnologia Gauss é uma derivação da tecnologia plasma estudada na anterior guerra contra os alienígenas.\"\n  STR_GAUSS_RIFLE_UFOPEDIA: \"Uma evolução do modelo da pistola Gauss, esta espingarda utiliza aceleradores de partículas duplos para gerar um enorme poder de fogo. O sistema de plasma alimentado a elério foi substituído por um micro-acelerador de partículas que gera um fluxo de antiprotões.\"\n  STR_GAUSS_RIFLE_CLIP_UFOPEDIA: \"Uma evolução do modelo da pistola Gauss, esta espingarda utiliza aceleradores de partículas duplos para gerar um enorme poder de fogo. O sistema de plasma alimentado a elério foi substituído por um micro-acelerador de partículas que gera um fluxo de antiprotões.\"\n  STR_HEAVY_GAUSS_UFOPEDIA: \"O Gauss pesado é uma arma de  difícil manejo, mas extremamente eficaz. Funciona com base em três aceleradores de partículas e é virtualmente imparável. Um feixe de antiprotões é encapsulado num projétil de arsenieto de gálio que provoca uma explosão de antimatéria após o impacto.\"\n  STR_HEAVY_GAUSS_CLIP_UFOPEDIA: \"O Gauss pesado é uma arma de  difícil manejo, mas extremamente eficaz. Funciona com base em três aceleradores de partículas e é virtualmente imparável. Um feixe de antiprotões é encapsulado num projétil de arsenieto de gálio que provoca uma explosão de antimatéria após o impacto.\"\n  STR_MAGNA_BLAST_GRENADE_UFOPEDIA: \"Esta granada padrão possuí um temporizador sofisticado que permite um controlo preciso.\"\n  STR_DYE_GRENADE_UFOPEDIA: \"A granada de tinta é um dispositivo de suporte, utilizado para criar cobertura em zonas expostas durante situações de combate. O composto químico é ejetado através de uma nuvem de partículas que produz um jato de tinta dentro de água e uma cortina de fumo à superfície.\"\n  STR_PARTICLE_DISTURBANCE_GRENADE_UFOPEDIA: \"Este explosivo de proximidade funciona como uma granada normal, mas é apenas detonado caso detete movimento na zona onde é lançado. Utilizar com extremo cuidado.\"\n  STR_MAGNA_PACK_EXPLOSIVE_UFOPEDIA: \"Este explosivo foi originalmente concebido para demolições, mas experiências passadas revelaram que pode ser uma arma bastante eficaz para eliminar grupos de alienígenas. Devido ao enorme alcance de explosão deste aparelho, recomenda-se que todos os aquanautas sejam colocados a uma distância segura antes de utilizar.\"\n  STR_PARTICLE_DISTURBANCE_SENSOR_UFOPEDIA: \"Este aparelho utiliza uma série de detetores e sistemas para identificar unidades inimigas em movimento. Clique no ícone do sensor de partículas no menu tático e selecione \\\"Usar Sensor\\\". O mostrador aparecerá no ecrã, indicando com uma seta ao centro a direção para a qual o aquanauta está voltado (o norte corresponde à aresta superior). As manchas indicam unidades que se moveram recentemente. Criaturas maiores ou mais rápidas geram manchas mais largas. Unidades estáticas não serão detetadas.\"\n  STR_MEDI_KIT_UFOPEDIA: \"Para usar o medi-kit, o agente deve estar de frente para a vítima a ser tratada ou posicionado sobre o corpo da mesma, caso esteja inconsciente. {NEWLINE}CURAR> Selecione a parte do corpo a tratar e clique no botão \\\"Curar\\\". Um ferimento grave será curado por cada uso, e a vítima recuperará alguns pontos de vida.{NEWLINE}ESTIMULANTE> Recuperam pontos de energia e reanimam tropas inconscientes. Posicione o agente sobre o corpo da vítima caso esta esteja inconsciente.{NEWLINE}ANALGÉSICOS> Recuperam a moral de agentes feridos.\"\n  STR_MC_DISRUPTOR_UFOPEDIA: \"O disruptor molecular só pode ser usado por agentes com habilidades de CM. Clique no ícone do disruptor, escolha o tipo de ataque a executar e selecione o alvo com o cursor. Existem duas formas de ataque de CM:{NEWLINE}INTERFERÊNCIA> Se executado com sucesso este ataque reduz a moral da unidade-alvo para que esta entre em pânico. {NEWLINE}CONTROLO> Se bem-sucedido, este ataque garante controlo sobre uma unidade inimiga.\"\n  STR_THERMAL_TAZER_UFOPEDIA: \"Esta arma térmica é capaz de neutralizar um inimigo de forma não letal, mas só pode ser utilizada em combate corpo a corpo.\"\n  STR_VIBRO_BLADE_UFOPEDIA: \"A vibrolâmina consiste numa broca de titânio que gira a velocidades de 6000 rpm. Este aparelho é capaz de perfurar os materiais mais resistentes e funciona com base numa fonte de energia alienígena. Tentativas anteriores de criarmos uma arma similar com tecnologia terrestre falharam devido a rotação ou resistência insuficientes.\"\n  STR_THERMIC_LANCE_UFOPEDIA: \"A lança térmica é uma versão melhorada da vibrolâmina. A sua broca gira a uma velocidade enorme e é aquecida por uma fonte de energia à base de Zrbite. Este aparelho tem potência suficiente para perfurar facilmente qualquer tipo de blindagem.\"\n  STR_HEAVY_THERMIC_LANCE_UFOPEDIA: \"A lança térmica pesada é uma versão mais potente da lança térmica original. A broca gira a um nível de rotação extremamente elevado e é aquecida por duas fontes de energia, o que significa que este aparelho é praticamente imparável face a todos os tipos de material.\"\n  STR_SONIC_CANNON_UFOPEDIA: \"O canhão sónico é a arma de infantaria mais poderosa do arsenal sónico. A sua câmara de reverberação e o seu oscilador sonoro são mais potentes que os do modelo da espingarda sónica. Este canhão também possuí um sistema de pulso-detonação que altera as ondas ultrassónicas através de um processo de modulação, de maneira a produzir um choque sónico mais eficaz.\"\n  STR_CANNON_POWER_CLIP_UFOPEDIA: \"Este pequeno dispositivo é utilizado como fonte de energia para o canhão sónico. Contém uma pequena quantidade de Zrbite no seu interior. \"\n  STR_SONIC_BLASTA_RIFLE_UFOPEDIA: \"Esta espingarda sónica é capaz de penetrar os tipos mais fortes de aço. O emissor compacto de ondas sónicas é amplificado através de um supercondutor que aumenta a sua potência destrutiva.\"\n  STR_BLASTA_POWER_CLIP_UFOPEDIA: \"Este pequeno objeto é utilizado como fonte de energia para a espingarda sónica, uma arma alienígena, e contém uma pequena quantidade de Zrbite no seu interior. \"\n  STR_SONIC_PISTOL_UFOPEDIA: \"A pistola sónica é uma arma alienígena que dispara ondas ultra-sónicas capazes de desfazer ossos em segundos. Estas ondas estão para além do limite de frequência audível pelos seres humanos.\"\n  STR_PISTOL_POWER_CLIP_UFOPEDIA: \"Este objeto é um dispositivo de alimentação para a pistola sónica alienígena. Contém Zrbite, a fonte de energia alienígena.\"\n  STR_DISRUPTOR_PULSE_LAUNCHER_UFOPEDIA: \"Esta arma é uma espécie de lança-torpedos alienígena que dispara bombas de pulsão teleguiadas, e só pode ser usada debaixo de água. Ao ativar a arma pode colocar pontos de referência no terreno de maneira guiar mais eficazmente a bomba. Após definir pontos suficientes, clique no ícone especial \\\"Lançar Míssil\\\". \"\n  STR_DISRUPTOR_AMMO_UFOPEDIA: \"Este aparelho é uma bomba de ondas de pulsão equipada com um sistema de orientação interno. É disparado através de um lançador de ondas de pulsão.\"\n  STR_THERMAL_SHOK_LAUNCHER_UFOPEDIA: \"Este pequeno lançador dispara bombas de choque térmico, capazes de atordoar inimigos. Esta arma é bastante útil para capturar alienígenas vivos.\"\n  STR_THERMAL_SHOK_BOMB_UFOPEDIA: \"A bomba de choque térmico serve, originalmente, para capturar humanos vivos, mas também pode ser utilizada contra a maioria das espécies alienígenas. É disparada através de um lançador térmico.\"\n  STR_SONIC_PULSER_UFOPEDIA: \"Este dispositivo funciona de forma similar a uma granada comum, mas com um poder destrutivo superior. O seu mecanismo de ação consiste numa detonação sónica singular que é emitida simultaneamente em todas as direções.\"\n  STR_MC_READER_UFOPEDIA: \"Encontrámos pequenos dispositivos inseridos cirurgicamente nos cadáveres dos alienígenas. Tratam-se de implantes de controlo criados pelos Aquatóides, que transmitem informação a grandes distâncias. O leitor molecular é um aparelho de comunicação utilizado para extrair informação destes implantes. Os agentes X-Com podem utilizar este dispositivo em combate para saberem mais sobre as características de um alienígena. Após equipar, clique no ícone do leitor molecular e selecione a opção \\\"usar\\\". Em seguida, selecione o inimigo-alvo com o cursor.\"\n  STR_SURVEY_SHIP: \"Nave de reconhecimento\"\n  STR_ESCORT: \"Nave de escolta\"\n  STR_CRUISER: \"Cruzador\"\n  STR_HEAVY_CRUISER: \"Cruzador pesado\"\n  STR_HUNTER: \"Predador\"\n  STR_BATTLESHIP: \"Nave de batalha\"\n  STR_DREADNOUGHT: \"Couraçado\"\n  STR_FLEET_SUPPLY_CRUISER: \"Cruzador de abastecimento\"\n  MAP_SEABED: \"Fundo marinho\"\n  MAP_PIPES: \"Estação subaquática\"\n  MAP_PLANE: \"Avião afundado\"\n  MAP_ATLAN: \"Atlântida\"\n  MAP_MU: \"Templo maia\"\n  MAP_GAL: \"Galeão afundado\"\n  MAP_MSUNK: \"Cruzeiro afundado\"\n  MAP_VOLC: \"Vulcão sumarino\"\n  MAP_CORAL: \"Coral\"\n  MAP_PORT: \"Porto\"\n  MAP_ISLAND: \"Ilha\"\n  MAP_CARGO: \"Navio de carga\"\n  MAP_LINERT: \"Navio de cruzeiros - parte 1\"\n  MAP_LINERB: \"Navio de cruzeiros - parte 2\"\n  MAP_ALART: \"Artefacto P1\"\n  MAP_GRUNGE: \"Artefacto P2\"\n  MAP_ENTRY: \"Colónia P1\"\n  MAP_A_BASE: \"Colónia P2\"\n  MAP_ALSHIP: \"T'leth P1\"\n  MAP_LEVEL: \"T'leth P2\"\n  MAP_CRYPT: \"T'leth P3\"\n  MAP_XBASES: \"Base X-Com\"\n  STR_MIXED_CREW: \"Várias\"\n  STR_MIXED_CREW_2: \"Várias 2\"\n  STR_RATING: \"AVALIAÇÃO> {0}\"\n  STR_RATING_TERRIBLE: \"TERRÍVEL!\"\n  STR_RATING_POOR: \"FRACO!\"\n  STR_RATING_OK: \"OK\"\n  STR_RATING_GOOD: \"BOM!\"\n  STR_RATING_EXCELLENT: \"EXCELENTE!\"\n  STR_SCORE: \"PONTUAÇÃO\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"RELATÓRIO MENSAL X-COM\"\n  STR_MONTH: \"Mês> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"O comité de organizações financiadoras está satisfeito com o seu progresso atual.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"O comité de organizações financiadoras está muito satisfeito com os seus excelentes progressos. Continue o bom trabalho.\"\n  STR_COUNCIL_IS_DISSATISFIED: \"O comité de organizações financiadoras está insatisfeito com os seus resultados. Melhore o seu desempenho em lidar com a ameaça alienígena ou arrisca-se a que o projeto X-Com seja cancelado.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"Como não conseguiu lidar adequadamente com a invasão alienígena o concelho de nações financiadoras decidiu, a muito custo, terminar o projeto X-Com. Cada nação irá lidar com o problema à sua maneira. Só nos resta esperar que cheguemos a um acordo com as forças hostis e que a população consiga aceitar os visitantes subaquáticos.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} está especialmente contente pela maneira como lidou com a ameaça local e concordou em aumentar a sua contribuição financeira.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} estão particularmente contentes com os seus progressos em lidar com incursões alienígenas locais e concordaram em aumentar a sua contribuição financeira.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} e {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} está descontente com maneira como lidou com a atividade alienígena na sua zona marítima e decidiu diminuir a sua contribuição financeira.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} estão descontentes com a sua incapacidade em lidar com a atividade alienígena nas respetivas zonas marítimas e decidiram reduzir a sua contribuição financeira.\"\n  STR_KNOTS: \"{0} nós\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} assinou um acordo de cooperação com as forças alienígenas e decidiu retirar-se do comité de financiamento X-Com.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} assinaram um acordo de cooperação com as forças alienígenas e decidiram retirar-se do comité de financiamento X-Com.\"\n  STR_MONTHLY_RATING: \"Avaliação mensal> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Alteração de fundos> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"O comité de financiamento não está satisfeito com a sua posição financeira. Reduza a sua dívida abaixo de 1 milhão ou o projeto será cancelado.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"TRANSMISSÃO DE SUB-PARTÍCULAS IDENTIFICADA\"\n  STR_CRAFT_TYPE: \"TIPO DE OSNI\"\n  STR_RACE: \"ESPÉCIE\"\n  STR_MISSION: \"MISSÃO\"\n  STR_ZONE: \"ZONA\"\n  STR_ALLOCATE_RESEARCH: \"Novo projeto\"\n  STR_ALLOCATE_MANUFACTURE: \"Nova produção\"\n  STR_AZORES: \"Açores\"\n  STR_REYKJAVIK: \"Reiquiavique\"\n  STR_BERMUDA: \"Bermuda\"\n  STR_NEW_YORK: \"Nova Iorque\"\n  STR_BOSTON: \"Boston\"\n  STR_FORT_SEVERN: \"Fort Severn\"\n  STR_DAKAR: \"Dacar\"\n  STR_RECIFE: \"Recife\"\n  STR_ACCRA: \"Acra\"\n  STR_ASCENSION_ISLAND: \"Ilha de Ascenção\"\n  STR_TRINIDADE_ISLAND: \"Ilha da Trindade\"\n  STR_FALKLAND_ISLAND: \"Ilhas Falkland\"\n  STR_CANARY_ISLANDS: \"Canárias\"\n  STR_ANCHORAGE: \"Anchorage\"\n  STR_ST_LAWRENCE_ISLAND: \"Ilha de São Lourenço\"\n  STR_SAN_FRANCISCO: \"São Francisco\"\n  STR_MIDWAY_ISLAND: \"Ilha de Midway\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_TASMANIA: \"Tasmânia\"\n  STR_HAWAII: \"Havai\"\n  STR_FIJI: \"Fiji\"\n  STR_TONGA: \"Tonga\"\n  STR_EASTER_ISLAND: \"Ilha da Páscoa\"\n  STR_GALAPAGOS_ISLAND: \"Galápagos\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_SOLOMON_ISLAND: \"Ilhas Salomão\"\n  STR_CRETE: \"Creta\"\n  STR_LISBON: \"Lisboa\"\n  STR_PORT_SAID: \"Porto Said\"\n  STR_MARSEILLES: \"Marselha\"\n  STR_TRIPOLI: \"Tripoli\"\n  STR_MANILA: \"Manila\"\n  STR_HONG_KONG: \"Hong Kong\"\n  STR_SINGAPORE: \"Singapura\"\n  STR_BANGKOK: \"Banguecoque\"\n  STR_DARWIN: \"Darwin\"\n  STR_BOMBAY: \"Mumbai\"\n  STR_SAYCHELLES_ISLAND: \"Seicheles\"\n  STR_MALDIVE_ISLAND: \"Maldivas\"\n  STR_SRI_LANKA: \"Sri Lanka\"\n  STR_MAURITIUS: \"Maurícia\"\n  STR_TOKYO: \"Tóquio\"\n  STR_SHANGHAI: \"Xangai\"\n  STR_VLADIVOSTOK: \"Vladivostok\"\n  STR_LONDON: \"Londres\"\n  STR_FAEROE_ISLAND: \"Ilhas Faroé\"\n  STR_ABERDEEN: \"Aberdeen\"\n  STR_OSLO: \"Oslo\"\n  STR_JAMAICA: \"Jamaica\"\n  STR_PANAMA: \"Panamá\"\n  STR_MIAMI: \"Miami\"\n  STR_PSI_TRAINING: \"Treino CM\"\n  STR_PSIONIC_TRAINING: \"TREINO DE CONTROLO MOLECULAR\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Capacidade restante> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"Poder{NEWLINE}C.M\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"Habilidade C.M{NEWLINE}/Melhoramento\"\n  STR_IN_TRAINING: \"Em{NEWLINE}treino?\"\n  STR_TARGETTED_BY: \"ALVO DE:\"\n  STR_WEAPONS_CREW_HWPS: \"ARMAS/{NEWLINE}TRIPULAÇÃO/SASs\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"tem pouco combustível.{NEWLINE}A regressar à base\"\n  STR_SOLDIER_LIST: \"Lista de aquanautas\"\n  STR_RANK_: \"POSTO> {ALT}{0}\"\n  STR_MISSIONS: \"MISSÕES> {ALT}{0}\"\n  STR_KILLS: \"MORTOS> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"EM RECUPERAÇÃO> {ALT}{0}\"\n  STR_TIME_UNITS: \"UNIDADES DE TEMPO\"\n  STR_STAMINA: \"RESISTÊNCIA\"\n  STR_HEALTH: \"PONTOS DE VIDA\"\n  STR_BRAVERY: \"CORAGEM\"\n  STR_REACTIONS: \"REAÇÕES\"\n  STR_FIRING_ACCURACY: \"PRECISÃO DE FOGO\"\n  STR_THROWING_ACCURACY: \"PRECISÃO DE ARREMESSO\"\n  STR_STRENGTH: \"FORÇA\"\n  STR_PSIONIC_STRENGTH: \"PODER CM\"\n  STR_PSIONIC_SKILL: \"HABILIDADE CM\"\n  STR_NEW_RANK: \"Promoção\"\n  STR_PROMOTIONS: \"Promoções\"\n  STR_SOLDIERS_UC: \"AQUANAUTAS\"\n  STR_COELACANTH_GAS_CANNON_UFOPEDIA: \"Os SAS são plataformas de armas blindadas de controlo à distância com grande capacidade de manobra, projetadas para suporte de tropas a todas a profundidades. Os SAS são rearmados automaticamente após o combate.\"\n  STR_COELACANTH_AQUA_JET_UFOPEDIA: \"Este sistema de armas está armado com torpedos aquajato que funcionam exclusivamente debaixo de água. Certifique-se de que dispõe de torpedos suficientes nos armazéns para rearmamento após o combate.\"\n  STR_COELACANTH_GAUSS_UFOPEDIA: \"A nova tecnologia Gauss renovou o armamento dos SAS, proporcionando poder de fogo superior ao dos modelos anteriores e utilizando tecnologia proprietária X-Com.\"\n  STR_DISPLACER_SONIC_UFOPEDIA: \"A nova tecnologia alienígena revolucionou o funcionamento dos SAS. Equipado com deslocadores de iões, este novo modelo é capaz de flutuar à superfície e debaixo de água. Armado com tecnologia sónica, o deslocador é altamente eficaz em situações de combate.\"\n  STR_DISPLACER_PWT_UFOPEDIA: \"Este deslocador dispara poderosos explosivos para uso em ambientes subaquáticos. É necessário fabricar torpedos de ondas de pulsão para armar este SAS. Para lançar um torpedo coloque vários pontos de referência no terreno com o cursor e clique no ícone \\\"Lançar míssil\\\".\"\n  STR_ALIEN_PROBE_MISSION: \"Missão de sondagem alienígena\"\n  STR_ALIEN_INTERDICTION: \"Interdição alienígena\"\n  STR_ALIEN_RESOURCE_RAID: \"Incursão alienígena por recursos\"\n  STR_ALIEN_INFILTRATION: \"Infiltração alienígena\"\n  STR_ALIEN_BASE: \"Colónia alienígena\"\n  STR_ALIEN_SURFACE_ATTACK: \"Ataques alienígenas à superfície\"\n  STR_ALIEN_RETALIATION: \"Ataque a base flutuante\"\n  STR_ALIEN_SUPPLY: \"Abastecimento alienígena\"\n  STR_ALIEN_PROBE_MISSION_UFOPEDIA: \"As missões de sondagem são utilizadas para obter informações sobre o leito marinho, recursos, e rotas marítimas e aéreas da área. Os submersíveis alienígenas envolvidos nestas missões não representam uma grande ameaça por si sós, mas indicam locais onde a atividade pode aumentar a qualquer altura.\"\n  STR_ALIEN_INTERDICTION_UFOPEDIA: \"Os alienígenas patrulham regularmente áreas em que estão interessados, enviando submersíveis com o propósito de proteger a área antes do início de missões intensivas. Aterram em locais específicos para mais tarde lançar incursões e abrir caminho para futuras atividades.\"\n  STR_ALIEN_RESOURCE_RAID_UFOPEDIA: \"A estratégia alienígena possuí como elementos-chave o afundamento de navios e a destruição de aviões. A aquisição de materiais é uma das atividades primárias dos alienígenas, associada à agressividade notória destes atos. Os alienígenas fazem incursões em áreas de atividade geotérmica, explorando estes locais para obter minerais e metais refinados, assim como itens produzidos pelos humanos.\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"Os governos terrestres podem ser alvo de infiltração por parte de agentes alienígenas disfarçados de humanos. Isto pode resultar em contacto oficial entre alienígenas e entidades governamentais ao mais alto nível. Os picos deste género de atividade são caracterizados por atividade OSNI intensa nas zonas costeiras das respetivas regiões. Os alienígenas tentarão assinar um acordo com uma nação ou organização terrestre, oferecendo o seu conhecimento e tecnologia superiores. Em troca, o governo assinante permitirá aos alienígenas levarem a cabo as suas atividades sem impedimentos. Este género de missão representa a maior ameaça para o projeto X-Com, pois se um governo ou corporação entrar em cooperação com os alienígenas, irá cancelar o nosso financiamento. \"\n  STR_ALIEN_BASE_UFOPEDIA: \"Descobrimos que os alienígenas constroem colónias subaquáticas secretas em localizações remotas do nosso planeta. Após alguns voos de reconhecimento iniciais, a atividade OSNI intensifica-se enquanto a colónia está a ser construída. Sabemos que estas instalações contém laboratórios experimentais, centros de clonagem e instalações cirúrgicas para realizar experiências em seres humanos e alienígenas. A presença de uma colónia irá causar um aumento de atividade alienígena na zona sem que se registe a presença de OSNIs. Para localizar uma base é necessário patrulhar a área-alvo com um aerosubmersível X-Com durante algumas horas. \"\n  STR_ALIEN_SURFACE_ATTACK_UFOPEDIA: \"Quando surge a necessidade de capturar seres humanos, os alienígenas lançam incursões diretas a zonas portuárias, ilhas, ou navios, ameaçando diretamente as vidas de civis inocentes para satisfazer as suas necessidades reprodutivas e experiências hediondas.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"Se as missões de interceção X-Com forem especialmente bem-sucedidas em afundar submersíveis alienígenas, é possível que as forças extraterrestres tomem medidas de retaliação, o que pode culminar num assalto direto às bases X-Com. No entanto, como é necessário aos alienígenas encontrar uma base para lançar uma incursão, é pouco provável que tal suceda, desde que os OSNIs inimigos sejam mantidos à distância. \"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"Após a sua construção, as colónias alienígenas necessitam de abastecimento frequente executado por veículos próprios. Se uma destas naves for detetada no fundo do oceano é porque uma colónia alienígena se encontra nas proximidades.\"\n  STR_SURVEY_SHIP_UFOPEDIA: \"Este pequeno submersível é utilizado em missões de reconhecimento e pesquisa. Precede a chegada de naves maiores durante o início de uma incursão alienígena.\"\n  STR_ESCORT_UFOPEDIA: \"Um veículo de reconhecimento ligeiro que não é grande ameaça para as forças X-Com. Precede a vinda de OSNIs maiores e de outras atividades alienígenas.\"\n  STR_CRUISER_UFOPEDIA: \"O cruzador é veículo-base da frota alienígena, adaptado para desempenhar todo o tipo de missões. Este submersível pode ser um adversário perigoso em combate.\"\n  STR_HEAVY_CRUISER_UFOPEDIA: \"O cruzador pesado é uma versão mais poderosa do cruzador, equipado com armas e sistemas de propulsão mais potentes. Este veículo é utilizado em missões de recursos para recolher grandes quantidades de minerais e equipamento.\"\n  STR_HUNTER_UFOPEDIA: \"Este navio está equipado com uma sala de exames para executar experiências e cirurgia em cobaias humanas. As vítimas são sujeitas a torturas abomináveis e o seu cérebro é frequentemente removido e armazenado para processamento.\"\n  STR_BATTLESHIP_UFOPEDIA: \"A nave de batalha é o veículo de combate mais agressivo da frota alienígena. Este submersível está equipado com todos os sistemas, armas e tecnologias alienígenas, que lhe permitem funcionar como uma base de operações para todo o género de missões ofensivas.\"\n  STR_DREADNOUGHT_UFOPEDIA: \"O couraçado é um enorme veículo de transporte de tropas, equipado com a mais recente tecnologia alienígena e um vasto arsenal. Este submersível alienígena é um adversário formidável para qualquer veículo de interceção X-Com.\"\n  STR_FLEET_SUPPLY_CRUISER_UFOPEDIA: \"O navio de abastecimento é utilizado durante a construção de colónias alienígenas ou para o abastecimento das mesmas. Transporta contentores de nutrientes, amostras de ADN, fetos alienígenas e outros componentes biológicos. \"\n  STR_DISMANTLE: \"Demolir\"\n  STR_FACILITY_IN_USE: \"AQUAMÓDULO EM USO\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"NÃO É POSSÍVEL DEMOLIR ESTE AQUAMÓDULO!{SMALLLINE}Todas as instalações têm de estar ligadas à eclusa de ar.\"\n  STR_TRANSFER_ITEMS_TO: \"Transferir itens para {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"NÃO HÁ ESPAÇO DE CONTENÇÃO ALIENÍGENA PARA EFETUAR A TRANSFERÊNCIA!{SMALLLINE}Os alienígenas vivos necessitam de uma área de contenção alienígena para sobreviverem.\"\n  STR_AMOUNT_AT_DESTINATION: \"QUANTIDADE{NEWLINE}NA BASE DESTINO\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"Os alienígenas capturados morreram devido à falta de uma instalação de contenção alienígena\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"NÃO HÁ HABITAÇÕES LIVRES!{SMALLLINE}A base de destino não tem espaço de habitação suficiente para a tripulação deste submersível.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"NÃO HÁ ESPAÇO EM ARMAZÉM SUFICIENTE!{SMALLLINE}A base de destino não dispõe de espaço suficiente para armazenar o equipamento atribuído a este submersível.\"\n  STR_ITEMS_ARRIVING: \"Chegada de transporte\"\n  STR_DESTINATION_UC: \"DESTINO\"\n  STR_DART_PISTOL: \"Pistola de dardos\"\n  STR_DART_POD: \"Carregador de dardos\"\n  STR_JET_HARPOON: \"Arpão-jato\"\n  STR_HARPOON_POD: \"Carregador de arpão-jato\"\n  STR_GAS_CANNON: \"Canhão de gás\"\n  STR_GC_AP_AMMO: \"Munição CG-P\"\n  STR_GC_HE_AMMO: \"Munição CG-E\"\n  STR_GC_P_AMMO: \"Munição CG-F\"\n  STR_HYDRO_JET_CANNON: \"Canhão de hidrojato\"\n  STR_HJC_AP_AMMO: \"Munição HJ-P\"\n  STR_HJC_HE_AMMO: \"Munição HJ-E\"\n  STR_HJC_P_AMMO: \"Munição HJ-F\"\n  STR_TORPEDO_LAUNCHER: \"Lança-torpedos\"\n  STR_SMALL_TORPEDO: \"Torpedo pequeno\"\n  STR_LARGE_TORPEDO: \"Torpedo grande\"\n  STR_PHOSPHOROUS_TORPEDO: \"Torpedo de fósforo\"\n  STR_MAGNA_BLAST_GRENADE: \"Magnagranada\"\n  STR_DYE_GRENADE: \"Granada de tinta\"\n  STR_PARTICLE_DISTURBANCE_GRENADE: \"Granada de partículas\"\n  STR_MAGNA_PACK_EXPLOSIVE: \"Magnaexplosivo\"\n  STR_PARTICLE_DISTURBANCE_SENSOR: \"Sensor de partículas\"\n  STR_MEDI_KIT: \"Medi-kit\"\n  STR_MC_DISRUPTOR: \"Disruptor molecular\"\n  STR_THERMAL_TAZER: \"Bastão térmico\"\n  STR_GAUSS_PISTOL: \"Pistola Gauss\"\n  STR_GAUSS_PISTOL_CLIP: \"Carregador de pistola Gauss\"\n  STR_GAUSS_RIFLE: \"Espingarda Gauss\"\n  STR_GAUSS_RIFLE_CLIP: \"Carregador de espingarda Gauss\"\n  STR_HEAVY_GAUSS: \"Gauss pesado\"\n  STR_HEAVY_GAUSS_CLIP: \"Carregador de Gauss pesado\"\n  STR_SONIC_CANNON: \"Canhão sónico\"\n  STR_CANNON_POWER_CLIP: \"Carregador de canhão sónico\"\n  STR_SONIC_BLASTA_RIFLE: \"Espingarda sónica\"\n  STR_BLASTA_POWER_CLIP: \"Carregador de espingarda sónica\"\n  STR_SONIC_PISTOL: \"Pistola sónica\"\n  STR_PISTOL_POWER_CLIP: \"Carregador de pistola sónica\"\n  STR_DISRUPTOR_PULSE_LAUNCHER: \"Lançador de bombas de pulsão\"\n  STR_DISRUPTOR_AMMO: \"Bomba de ondas de pulsão\"\n  STR_THERMAL_SHOK_LAUNCHER: \"Lançador térmico\"\n  STR_THERMAL_SHOK_BOMB: \"Bomba de choque térmico\"\n  STR_SONIC_PULSER: \"Granada sónica\"\n  STR_ZRBITE: \"Zrbite\"\n  STR_MC_READER: \"Leitor molecular\"\n  STR_VIBRO_BLADE: \"Vibrolâmina\"\n  STR_THERMIC_LANCE: \"Lança térmica\"\n  STR_HEAVY_THERMIC_LANCE: \"Lança térmica pesada\"\n  STR_AQUATOID_CORPSE: \"Cadáver de Aquatóide\"\n  STR_GILLMAN_CORPSE: \"Cadáver de Homem-guelra\"\n  STR_LOBSTERMAN_CORPSE: \"Cadáver de Homem-lagosta\"\n  STR_TASOTH_CORPSE: \"Cadáver de Tasoth\"\n  STR_CALCINITE_CORPSE: \"Cadáver de Calcinite\"\n  STR_DEEP_ONE_CORPSE: \"Cadáver de Ser das profundezas\"\n  STR_BIODRONE_CORPSE: \"Fragmentos de Biodisco\"\n  STR_TENTACULAT_CORPSE: \"Cadáver de Tentaculat\"\n  STR_TRISCENE_CORPSE: \"Cadáver de Triscénio\"\n  STR_HALLUCINOID_CORPSE: \"Cadáver de Alucinóide\"\n  STR_XARQUID_CORPSE: \"Cadáver de Xarquídeo\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"Munição insuficiente para armar o SAS{SMALLLINE}Cada SAS necessita de {0} {1}.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Não há equipamento suficiente para reequipar o esquadrão\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Para produzir:{NEWLINE}{1}{NEWLINE}é necessário investigar:{NEWLINE}{0}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"Os alienígenas destruíram a base indefesa {0}\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"Detetámos uma colónia alienígena na seguinte localização: {0}\"\n  STR_STANDOFF: \"MODO DE PERSEGUIÇÃO\"\n  STR_CAUTIOUS_ATTACK: \"ATAQUE DE LONGO ALCANCE\"\n  STR_STANDARD_ATTACK: \"ATAQUE NORMAL\"\n  STR_AGGRESSIVE_ATTACK: \"ATAQUE AGRESSIVO\"\n  STR_DISENGAGING: \"A RETIRAR\"\n  STR_UFO_HIT: \"ALVO ATINGIDO!\"\n  STR_UFO_CRASH_LANDS: \"OSNI AFUNDADO!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Minimizar apenas em perseguição\"\n  STR_UFO_RETURN_FIRE: \"O OSNI ABRIU FOGO!\"\n  STR_INTERCEPTOR_DAMAGED: \">>> SUBMERSÍVEL DANIFICADO <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> SUBMERSÍVEL DESTRUÍDO <<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"O OSNI ESCAPOU!\"\n  STR_LONG_RANGE_DETECTION: \"Deteção de banda larga\"\n  STR_STORES_UC: \"ARMAZÉNS\"\n  STR_DIFFICULTY_LEVEL: \"Nível de dificuldade\"\n  STR_INTERCEPT: \"INTERCETAR\"\n  STR_BASES: \"BASES\"\n  STR_GRAPHS: \"ESTATÍSTICAS\"\n  STR_UFOPAEDIA_UC: \"OSNIPÉDIA\"\n  STR_OPTIONS_UC: \"OPÇÕES\"\n  STR_FUNDING_UC: \"ORÇAMENTO\"\n  STR_5_SECONDS: \"5 segs\"\n  STR_1_MINUTE: \"1 min\"\n  STR_5_MINUTES: \"5 mins\"\n  STR_30_MINUTES: \"30 mins\"\n  STR_1_HOUR: \"1 hora\"\n  STR_1_DAY: \"1 dia\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"Registo de avaliação X-Com\"\n  STR_ENTER_NAME: \"Introduzir nome\"\n  STR_PERFORMANCE_RATING: \"Classificação final\"\n  STR_VICTORY_DATE: \"Data de vitória\"\n  STR_CHEMICAL_FLARE: \"Sinalizador químico\"\n  STR_CHEMICAL_FLARE_UFOPEDIA: \"Este pequeno aparelho produz uma luz brilhante que ilumina a área onde é lançado, dentro de água ou à superfície, revelando unidades inimigas durante missões noturnas ou a grande profundidade.\"\n  STR_MONTHLY_COSTS: \"Despesas mensais\"\n  STR_CRAFT_RENTAL: \"Aluguer de submersíveis\"\n  STR_SALARIES: \"Salários\"\n  STR_BASE_MAINTENANCE: \"Manutenção da base\"\n  STR_COST_PER_UNIT: \"Custo por unidade\"\n  STR_QUANTITY: \"Quantidade\"\n  STR_TOTAL: \"Total\"\n  STR_IN_PSIONIC_TRAINING: \"Em implantação CM\"\n  STR_FRONT_ARMOR: \"Armadura frontal\"\n  STR_LEFT_ARMOR: \"Armadura esquerda\"\n  STR_RIGHT_ARMOR: \"Armadura direita\"\n  STR_REAR_ARMOR: \"Armadura traseira\"\n  STR_UNDER_ARMOR: \"Armadura inferior\"\n  STR_ROUNDS: \"TIROS\"\n  STR_UNIT: \"UNIDADE> {0}\"\n  STR_ENERGY: \"ENERGIA\"\n  STR_MORALE: \"MORAL\"\n  STR_ARMOR_: \"ARMADURA> {0}\"\n  STR_FRONT_ARMOR_UC: \"ARMADURA FRONTAL\"\n  STR_LEFT_ARMOR_UC: \"ARMADURA ESQUERDA\"\n  STR_RIGHT_ARMOR_UC: \"ARMADURA DIREITA\"\n  STR_REAR_ARMOR_UC: \"ARMADURA TRASEIRA\"\n  STR_SKILLS: \"HABILIDADES> {0}\"\n  STR_LEVEL: \"NÍVEL> {0}\"\n  STR_HEAD: \"CABEÇA\"\n  STR_TORSO: \"TRONCO\"\n  STR_RIGHT_ARM: \"BRAÇO DIR.\"\n  STR_LEFT_ARM: \"BRAÇO ESQ.\"\n  STR_RIGHT_LEG: \"PERNA DIR.\"\n  STR_LEFT_LEG: \"PERNA ESQ.\"\n  STR_PAIN_KILLER: \"ANALGÉSICO\"\n  STR_STIMULANT: \"ESTIMULANTE\"\n  STR_HEAL: \"CURAR\"\n  STR_TIME_UNITS_SHORT: \"UT>{ALT}{0}\"\n  STR_WEIGHT: \"Peso>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"Reaç>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"H.Mol>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"P.Mol>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Artefacto alienígena\"\n  STR_AMMO_ROUNDS_LEFT: \"MUNIÇÃO:{NEWLINE}TIROS{NEWLINE}RESTANTES={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Analgésico>{ALT}{0}{ALT}{NEWLINE}Estimulante>{ALT}{1}{ALT}{NEWLINE}Curar>{ALT}{2}\"\n  STR_THROW: \"Atirar\"\n  STR_AUTO_SHOT: \"Rajada\"\n  STR_SNAP_SHOT: \"Tiro simples\"\n  STR_AIMED_SHOT: \"Tiro preciso\"\n  STR_STUN: \"Atordoar\"\n  STR_PRIME_GRENADE: \"Programar explosivo\"\n  STR_USE_SCANNER: \"Usar sensor\"\n  STR_USE_MEDI_KIT: \"Usar medi-kit\"\n  STR_LAUNCH_MISSILE: \"Lançar torpedo\"\n  STR_ACCURACY_SHORT: \"Pr>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Sem unidades de tempo suficientes!\"\n  STR_NOT_ENOUGH_ENERGY: \"Sem energia suficiente!\"\n  STR_NO_ROUNDS_LEFT: \"Sem munição!\"\n  STR_NO_AMMUNITION_LOADED: \"Sem munição!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Munição errada para esta arma!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"A arma já está carregada!\"\n  STR_NO_LINE_OF_FIRE: \"Nenhuma linha de fogo!\"\n  STR_GRENADE_IS_ACTIVATED: \"Explosivo ativado!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Explosivo desativado!\"\n  STR_THERE_IS_NO_ONE_THERE: \"Não há ninguém aqui!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Impossível utilizar um artefacto alienígena sem ser investigado!\"\n  STR_OUT_OF_RANGE: \"Fora de alcance!\"\n  STR_UNABLE_TO_THROW_HERE: \"Não é possível atirar para aqui!\"\n  STR_SET_TIMER: \"Temporizador\"\n  STR_HIDDEN_MOVEMENT: \"MOVIMENTO OCULTO\"\n  STR_TURN: \"TURNO> {0}\"\n  STR_SIDE: \"LADO> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Pressione um botão para continuar\"\n  STR_MIND_CONTROL: \"Controlo molecular\"\n  STR_PANIC_UNIT: \"Interferência\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Ataque psíquico bem-sucedido\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Controlo de implante bem-sucedido\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}enlouqueceu\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}enlouqueceu\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}entrou em pânico\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}entrou em pânico\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Alienígenas\"\n  STR_RIGHT_HAND: \"MÃO DIR.\"\n  STR_LEFT_HAND: \"MÃO ESQ.\"\n  STR_RIGHT_SHOULDER: \"OMBRO DIR.\"\n  STR_LEFT_SHOULDER: \"OMBRO ESQ.\"\n  STR_BACK_PACK: \"MOCHILA\"\n  STR_BELT: \"CINTO\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}está sob controlo molecular\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}está sob controlo molecular\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}está inconsciente\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}está inconsciente\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}morreu vítima de ferimentos graves\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}morreu vítima de ferimentos graves\"\n  STR_USE_MIND_PROBE: \"Usar leitor\"\n  STR_FATAL_WOUNDS: \"FERIMENTOS GRAVES\"\n  STR_UNDER_ARMOR_UC: \"ARMADURA INFERIOR\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"UTs reservadas para Tiro rápido\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"UTs reservadas para Rajada\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"UTs reservadas para Tiro preciso\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"UTs reservadas para Ajoelhar\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"UTs reservadas para Ajoelhar e disparar\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} Unidade na nave X-Com\"\n    many: \"{N} unidades na nave X-Com\"\n    other: \"{N} unidades na nave X-Com\"\n  STR_UNITS_OUTSIDE:\n    one: \"Resta {N} unidade no exterior\"\n    many: \"Restam {N} unidades no exterior\"\n    other: \"Restam {N} unidades no exterior\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} Unidade na entrada\"\n    many: \"{N} unidades na entrada\"\n    other: \"{N} unidades na entrada\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} Unidade na saída-alvo\"\n    many: \"{N} unidades na saída-alvo\"\n    other: \"{N} unidades na saída-alvo\"\n  STR_ABORT_MISSION_QUESTION: \"Abortar missão?\"\n  STR_CORPSE: \"Cadáver\"\n  STR_UNLOAD_CRAFT: \"Remover todos\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}morreu em combate\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}morreu em combate\"\n  STR_HIT_MELEE: \"Atacar\"\n  STR_GROUND: \"SOLO\"\n  STR_LIVING_QUARTERS_PLURAL: \"Habitações\"\n  STR_LIST_ITEM: \"ITEM\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"Todos os alienígenas morreram no naufrágio.{NEWLINE}Recuperação de OSNI iniciada.\"\n  STR_RESET: \"Repor\"\n  STR_MEMORIAL: \"Memorial\"\n  STR_DATE_UC: \"DATA\"\n  STR_SOLDIERS_RECRUITED_UC: \"AQUANAUTAS RECRUTADOS>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"AQUANAUTAS PERDIDOS>{ALT}{0}\"\n  STR_REMOVE_SELECTED: \"Remover seleção\"\n  STR_LIVE_ALIENS: \"Espécimes{NEWLINE}vivos\"\n  STR_DEAD_ALIENS: \"Espécimes{NEWLINE}reijeitados\"\n  STR_UNDER_INTERROGATION: \"Em{NEWLINE}estudo\"\n  STR_CONTAINMENT_EXCEEDED: \"CONTENÇÃO ALIENÍGENA CHEIA!{SMALLLINE}Não há espaço de contenção suficiente em {0}. Remova os alienígenas em excesso. Todos os alienígenas removidos morrerão imediatamente.\"\n  STR_MANAGE_CONTAINMENT: \"Gerir contenção alienígena\"\n  STR_STORAGE_EXCEEDED: \"LIMITES DE ARMAZENAMENTO EXCEDIDOS!{SMALLLINE}Não há espaço em armazém suficiente em {0}. É necessário vender itens em excesso.\"\n  STR_GO_TO_BASE: \"Ver base\"\n  STR_MELEE_ACCURACY: \"PRECISÃO CORPO A CORPO\"\n  STR_SELL_PRODUCTION: \"VENDER\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Ambas as mãos devem estar vazias!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Não há itens necessários para copiar o modelo!\"\n  STR_UNLOAD_WEAPON: \"Descarregar arma\"\n  STR_ALL_ITEMS: \"Todos\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"NÃO É PERMITIDO MAIS EQUIPAMENTO A BORDO!{SMALLLINE}Este veículo só pode transportar o limite máximo de {N} item.\"\n    many: \"NÃO É PERMITIDO MAIS EQUIPAMENTO A BORDO!{SMALLLINE}Este veículo só pode transportar o limite máximo de {N} itens.\"\n    other: \"NÃO É PERMITIDO MAIS EQUIPAMENTO A BORDO!{SMALLLINE}Este veículo só pode transportar o limite máximo de {N} itens.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}CENTRO DE COMANDO DESTRUÍDO{NEWLINE}Regresse à entrada e aborte a missão.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"A base X-Com não pode ser construída em terra\"\n  STR_UNABLE_TO_ENGAGE_DEPTH: \"IMPOSSÍVEL ATACAR VEÍCULO INIMIGO{NEWLINE}A ESTA PROFUNDIDADE\"\n  STR_UNABLE_TO_ENGAGE_AIRBORNE: \"IMPOSSÍVEL ATACAR VEÍCULO INIMIGO{NEWLINE}À SUPERFÍCIE\"\n  STR_UNDERWATER_EQUIPMENT: \"Este equipamento não funciona à superfície!\"\n  STR_LAND_EQUIPMENT: \"Este equipamento não funciona debaixo de água!\"\n  STR_LEVEL_SHORT: \"N{0}\"\n  STR_PERSONNEL: \"Pessoal\"\n  STR_CRAFT_ARMAMENT: \"Veículos e armamento\"\n  STR_COMPONENTS: \"Componentes\"\n  STR_SOLDIERS_RECRUITED: \"Aquanautas recrutados\"\n  STR_SOLDIERS_LOST: \"Aquanautas perdidos\"\n  STR_TOTAL_UFOS: \"Aerosubmersíveis detetados\"\n  STR_TOTAL_ALIEN_BASES: \"Colónias alienígenas descobertas\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"PCM\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"HCM\"\n  FEMALE_CIVILIAN: \"Civil, Mulher\"\n  MALE_CIVILIAN: \"Civil, Homem\"\n  DOCKER_CIVILIAN: \"Civil, Estivador\"\n  SAILOR_CIVILIAN: \"Civil, Marinheiro\"\n  STR_BIODRONE_MELEE_WEAPON: \"Biodisco - Ataque corpo-a-corpo\"\n  HALLUCINOID_WEAPON: \"Arma de Halucinóide\"\n  STR_LOBSTERMAN_MELEE_WEAPON: \"Homem-lagosta - Ataque corpo-a-corpo\"\n  CALCINITE_WEAPON: \"Arma de Calcinite\"\n  DEEP_ONE_WEAPON: \"Arma de Ser das profundezas\"\n  STR_TRISCENE_MELEE_WEAPON: \"Triscénio - Ataque corpo-a-corpo\"\n  STR_TRIBIO_SONIC_WEAPON: \"Arma sónica alienígena\"\n  XARQUID_WEAPON: \"Arma de Xarquídeo\"\n  TENTACULAT_WEAPON: \"Arma de Tentaculat\"\n  ZOMBIE_WEAPON: \"Arma de Zombie\"\n  ALIEN_PSI_WEAPON: \"Arma de CM alienígena\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/ro.yml",
    "content": "ro:\n  STR_LEVIATHAN_UFOPEDIA: \"NAVĂ DE TRANSPORT ȘI INTERCEPȚIE, CAPABILĂ DE SCUFUNDĂRI LA ADANCIMI EXTRME. O SUPERBĂ COMBINAȚIE DE TEHNOLOGII EXTRATERESTRE ȘI UMANE, FOLOSIND PROPULSIE IONICĂ ȘI NAVIGAȚIE MAGNETICĂ.\"\n  STR_BARRACUDA_UFOPEDIA: \"UNA DINTRE CELE MAI RAPIDE NAVE DE INTERCEPȚIE DIN LUME, PROPULSATĂ DE MOTOARE LASER, CAPABILĂ DE SCUFUNDĂRI ȘI ZBOR ATMOSFERIC, O NAVĂ CHEIE ÎN BĂTĂLIA CE URMEAZĂ.\"\n  STR_HAMMERHEAD_UFOPEDIA: \"NAVĂ DE TRANSPORT ȘI INTERCEPȚIE. O REPLICARE A SISTEMELOR MAGNETICE ÎNTR-O NAVĂ X-COM. DEȘI ARE DIMENSIUNI MICI, DESIGNUL ESTE O REALIZARE TEHNICĂ ULUITOARE.\"\n  STR_TRITON_UFOPEDIA: \"TRANSPORTOR PENTRU TRUPELE DE ASALT, ECHIPAT CU MOTOARE DE ZBOR ATMOSFERIC ȘI SCUFUNDĂRI. CAPACITATEA MARE ȘI CONSTRUCȚIA ÎI ASIGURĂ LOCUL PROEMINENT ÎN FLOTA X-COM.\"\n  STR_MANTA_UFOPEDIA: \"NAVĂ INDIVIDUALĂ DE INTERCEPȚIE DE MARE VITEZĂ, ASEMENEA CU NAVELE EXTRATERESTRE CU PROPULSIE IONICĂ. O NAVĂ DE ATAC FOARTE EFICIENTĂ ÎN CONFLICTUL TOT MAI ESCALADAT.\"\n  STR_AJAX_UFOPEDIA: \"ARMA STANDARD ÎN RĂZBOIUL SUBACVATIC, FOLOSITĂ PE TOT GLOBUL CA UN MIJLOC DE INTIMIDARE PRECIS ȘI PUTERNIC.\"\n  STR_DUP_HEAD_UFOPEDIA: \"TEHNOLOGIA ALICELOR DE URANIU SĂRĂCIT ESTE RELATIV NOUĂ, IAR ACESTA ESTE PRIMUL SISTEM ACVATIC COMERCIAL CE O IMPLEMENTEAZĂ PE DEPLIN.\"\n  STR_CRAFT_GAS_CANNON_UFOPEDIA: \"ARTILERIE CU GAZ COMPRIMAT CE PROPULSEAZĂ BOLȚURI MASIVE CARE POT STRĂPUNGE BLINDAJUL.\"\n  STR_PWT_CANNON_UFOPEDIA: \"TORPILĂ CE FOLOSEȘTE UN SISTEM CU COMBUSTIBIL SUPRAÎNCĂLZIT ȘI UN FOCOS EXTREM DE DENS CE POATE STRĂPUNGE MAJORITATEA ALIAJELOR.\"\n  STR_GAUSS_CANNON_UFOPEDIA: \"O NOUĂ ARMĂ DEZVOLTATĂ CU TEHNOLOGIE X-COM. ACCELERATORUL DE PARTICULE AL SISTEMULUI ESTE ALIMENTAT DE UN REACTOR DE FUZIUNE COMPACT, RĂCIT CU AZOT LICHID.\"\n  STR_SONIC_OSCILLATOR_UFOPEDIA: \"UN PUTERNIC OSCILATOR AUDITIV CE CREAZĂ UNDE DE FORȚĂ SONICĂ, DISTRUGÂNDU-ȘI ȚINTA PRIN DESFACEREA LEGĂTURILOR MOLECULARE DATORATĂ VIBRAȚIILOR.\"\n  STR_AQUATOID_UFOPEDIA: \"Specia lor reprezintă o societate străveche, ce exista cu milenii înaintea primilor pași ai omului în această lume. Forma compactă și trăsăturile bulboase sunt vestigii ale fraților călători prin spațiu, Sectoizii. Forța lor se bazează pe tehnologia puternică a Controlului Molecular. Caută să își propage specia sterilă prin modificări genetice, subiectul ideal fiind ființele umane. Experimentele au dus la crearea a numeroase specii hibride.\"\n  STR_AQUATOID_AUTOPSY: \"Autopsie Aquatoid\"\n  STR_AQUATOID_AUTOPSY_UFOPEDIA: \"O analiză detaliată a acestei creaturi ne permite să facem câteva afirmații fundamentale. Este un Sectoid, vechiul nostru dușman, dar schimbat prin metode chirurgicale și implanturi pentru a fi o creatură acvatică. Plămânii vestigiali permit respirarea aerului și o mobilitate limitată la suprafață. Implanturi cibernetice se întâlnesc în tot corpul, acestea mărind forța membrelor și funcția organelor. Toți membri acestei rase sunt identici, ducând la ipoteza că aceste creaturi sunt clone.\"\n  STR_GILLMAN_UFOPEDIA: \"Aproape umană, această creatură ciudată ce pare să fie un umanoid reptilian, înrudit îndeaproape cu noi. Este extrem de puternic și rapid în lumea subacvatică. Sunt o rasa cu drepturi depline, existând masculi și femele de vârste diferite. Sunt diferiți de majoritatea extratereștrilor subacvatici, neprezentând semnele modificărilor genetice sau deformărilor chirurgicale. Există posibilitatea că privim o încrengătură străveche a propriei noastre specii.\"\n  STR_GILLMAN_AUTOPSY: \"Autopsie Gillman\"\n  STR_GILLMAN_AUTOPSY_UFOPEDIA: \"Odată începută operația a devenit clar faptul că această creatură nu este extraterestră, ci a fost născută pe Pământ, o rasă preistorică bănuit a fi distrusă când mamiferele au devenit dominante. Într-o vreme în care dinozaurii cutreierau pământul trăiau aceste creaturi - amfibii, inteligente și puternice. Cataclismul ce a pus capăt stăpânirii reptiliene asupra planetei a forțat creaturile într-o relație simbiotică cu nou-veniții extratereștri. Un mic dispozitiv electronic este plasat în craniul acestora.\"\n  STR_LOBSTERMAN_UFOPEDIA: \"O creatură amețitoare, mai înaltă decât un om și având șase membre, diferită de orice în afara unui demon acvatic. Numele i-a fost dat de către trupele X-Com ținând cont de similaritățile cu homarul pământean. Este un mastodont al adâncurilor. O creatură de luptă proiectată cu atenție având o forță incredibilă și practic invulnerabilă la rachete. De asemenea, cleștii săi pot zdrobi oțelul.\"\n  STR_LOBSTERMAN_AUTOPSY: \"Autopsie Lobsterman\"\n  STR_LOBSTERMAN_AUTOPSY_UFOPEDIA: \"Odată trecuți de carapacea aproape indestructibilă a creaturii descoperim o construcție incredibilă. Mușchi puternici acoperă un schelet de titaniu, iar un sistem sofisticat de țintire cu abilități de scanare în mai multe benzi este conectat direct la creierul creaturii. Ochii multiplii sunt protejați de plastici mai duri decât oțelul și este clar că, atunci când sunt desfășurațe corect de către stăpânii lor, aceste creaturi sunt de neoprit. Adânc în corpul său sunt dispozitive de o construcție și având funcții necunoscute.\"\n  STR_TASOTH_UFOPEDIA: \"Acești dușmani agili și rapizi reprezintă grosul armatei extraterestre. Sunt născuți cu sutele în cuve masive în inima coloniilor extraterestre. Mult mai puternici decât un om, sunt niște extratereștri adevărați, iar comportamentul și natura carnivoră sunt fără precedent pe planetă. Formează vârful de lance al atacului extraterestru și nu par a da înapoi în luptă de la nimic, chiar și în fața șanselor potrivnice.\"\n  STR_TASOTH_AUTOPSY: \"Autopsie Tasoth\"\n  STR_TASOTH_AUTOPSY_UFOPEDIA: \"Disecția a dezvăluit un organism cibernetic alimentat de o forță stranie. În cavitatea corpului se află o mică sursă de energie, organele identificabile lipsind. Forța se transmite în corp printr-un sistem bio-electric. Corpul nu prezintă oase sau orice altă structură de susținere. Odată ucisă, energia se oprește și creatura devine o păpușă de cârpă lipsită de viață mustind de lichide extraterestre. Singura construcție internă este o pereche de celule ceramice, care, dacă sunt energizate, reînvie pentru scurt timp creatura.\"\n  STR_DEEP_ONE_UFOPEDIA: \"Un coșmar biologic, o încrucișare de specii, produs al experimentelor inimaginabile ale Aquatoizilor. Am întâlnit mai multe variante ale acestei creaturi. După ample cercetări am concluzionat că sunt fabricați de către invadatori, numărul acestora crescând odată cu cel al oamenilor capturați. Fiecare dintre acești sub-oameni poate descărca energie electrică suficient de puternică pentru a omorî un soldat.\"\n  STR_DEEP_ONE_AUTOPSY: \"Autopsie Deep One\"\n  STR_DEEP_ONE_AUTOPSY_UFOPEDIA: \"Creatura este o combinație de organism uman și extraterestru. Creierul uman este modificat masiv pentru a găzdui echipamentele electronice de control și cortexul extraterestru. Toate vestigiile corpului uman sunt pierdute în afara unuia: ochii. Grefa chirurgicală permite fetusului extraterestru să consume gazda pe măsură ce crește. Pielea tare a creaturii pare o țesătură non-organică, metalică, extrem de puternică și flexibilă. Hibridul rezultat este puternic, rapid și sub controlul deplin al extratereștrilor.\"\n  STR_BIODRONE_UFOPEDIA: \"O creație ce numai o minte extraterestră putea concepe. Este un creier (uman sau extraterestru) suspendat în lichid amniotic și conectat la o unitate de bază ce poate zbura pe pământ sau sub apă. Este înarmată cu un perturbator auditiv puternic, parte mașină și parte organism. Unii dintre cercetători au sugerat că arma este operată de corzile vocale ale organismului original. Extrem de precise și tenace, aceste super-gărzi sunt folosite la scară largă pentru a proteja bunurile de preț ale extratereștrilor.\"\n  STR_BIODRONE_AUTOPSY: \"Autopsie Bio-drone\"\n  STR_BIODRONE_AUTOPSY_UFOPEDIA: \"Ipoteza că perturbatorul auditiv este un dispozitiv biologic este adevărată. Această creatură nefericită țipă la propriu la inamici până mor. Toate exemplarele prezintă cicatrici cirurgicale masive și mutilări severe. Extratereștrii par să măcelărească creierul până devine obedient. Majoritatea creierelor folosite sunt extraterestre, dar nimic nu se poate compara cu groaza găsirii unuia uman. Sunt alimentate de un motor ionic și conțin o formă de sistem de control la distanță.\"\n  STR_TENTACULAT_UFOPEDIA: \"Nici măcar adâncurile unui coșmar Lovecraftian nu puteau da naștere unei asemenea creaturi. Nu există nicio comparație cu vreun animal pământean, mediul ce a putut produce ceva asemenea este inimaginabil. Înarmat cu tentacule lungi, își paralizează victimele apoi le transmută în lucruri lipsite de rațiune. Aceste progenituri pot induce moartea prin atingere, chiar și prin armură. Este cel mai de temut extraterestru întâlnit până acum.\"\n  STR_TENTACULAT_AUTOPSY: \"Autopsie Tentaculat\"\n  STR_TENTACULAT_AUTOPSY_UFOPEDIA: \"Autopsia relevă mai multe implanturi cibernetice plasate în creierul uriaș al creaturii. Sistemul de vedere reprezintă o combinație complexă de lumină vizibilă și imagine termică. Chiar și în adâncurile negre ca smoala ale oceanelor acest monstru poate naviga cu precizie infailibilă. Prezintă organe vestigiale ce par asigura minimul pentru a supraviețui. Fiecare creatură prezintă un mic stomac cu un conector extern, sugerând că sunt hrănite direct cu nutrienți de către stăpâni.\"\n  STR_CALCINITE_UFOPEDIA: \"Precum costumele de scufundare ale marinarilor pierduți, acești extratereștri bântuie fundul oceanelor după cei nevigilenți. O lovitură cu ghearele mai puternice ca oțelul poate fi suficientă pentru a trimite cei mai buni scufundători la fund. O formă verde gelatinoasă poate fi observată răsucindu-se prin casca costumului. Din întâlnirile adesea letale pe care le-am avut nu există indicii asupra naturii reale a creaturilor din interior.\"\n  STR_CALCINITE_AUTOPSY: \"Autopsie Calcinite\"\n  STR_CALCINITE_AUTOPSY_UFOPEDIA: \"Odată îndepărtat costumul creatura dezvăluită este o uriașă formă amorfă de protoplasmă. Fără niciun creier vizibil, membre sau organe senzoriale, o mică componentă metalică se găsește adânc în corpul lichid. Odată moartă nu putem decât ghici natura creaturii. O enigmă inexplicabilă a dușmanilor noștri extratereștri.\"\n  STR_TRISCENE_UFOPEDIA: \"Această reptilă bipedă reprezintă o întoarcere în era dinozaurilor. Pare a fi de natură cretacică în toate privințele dacă nu ar exista abilitatea de a supraviețui și sub apă. Aceste creaturi sunt încărcate cu platforme armate și au maxilarul dotat cu dinți metalici. Au fost folosite adesea în prima linie a asalturilor extraterestre la sol. O armă de categorie grea și puternică, sunt desfășurați cu o eficiență letală de către rasa Tasoth.\"\n  STR_TRISCENE_AUTOPSY: \"Autopsie Triscene\"\n  STR_TRISCENE_AUTOPSY_UFOPEDIA: \"Odată supusă bisturiului, creatura străveche dezvăluie că este completată cu implanturi cibernetice și sisteme armate. Creierul minuscul este suplimentat de un mic modul de computer montat în harnașamentul purtat de toate creaturile. O piele naturală rezistentă și un instinct predatorial intensificat cu arme adiționale îl transformă într-un inamic letal în orice mediu. \"\n  STR_HALLUCINOID_UFOPEDIA: \"După ce au recoltat oceanele extratereștrii au crescut aceste creaturi pământene pe post de arme. Nu trebuie să fim atrași într-un fals sentiment de siguranță când întâlnim acești navigatori ai adâncurilor aparent inofensivi. Posedând un formidabil atac ce îngheață de aproape, această creatură este un adversar redutabil.\"\n  STR_HALLUCINOID_AUTOPSY: \"Autopsie Hallucinoid\"\n  STR_HALLUCINOID_AUTOPSY_UFOPEDIA: \"Îngropat în multele straturi ale corpului gelatinos ale acestui organism se află un puternic congelator chimic, principala armă ofensivă. Pielea moale și suplă pare a fi susceptibilă atacurilor bazate pe căldură. Adeseori, acest mutant se găsește în compania stăpânilor săi, Aquatoizii.\"\n  STR_XARQUID_UFOPEDIA: \"Altă nevertebrată pământeană modificată, Xarquid-ul este o creatură de o mare frumusețe și de un pericol la fel de mare. Înnotătorul rapid gigantic ascunde un arsenal devastator, un pulverizator sufocant de cerneală și un suflu de particule ionizate. De la primele întâlniri cu această puternică creatură am exercitat prudență față de ea și de stăpânii ei răzbunători din rasa Gillman.\"\n  STR_XARQUID_AUTOPSY: \"Autopsie Xarquid\"\n  STR_XARQUID_AUTOPSY_UFOPEDIA: \"Acest Nautilus supradimensionat a fost crescut printr-o dietă de droguri extraterestre și modificări chirurgicale. Pervertită dincolo de natura sa, rasa Gillman a adăugat creaturii sisteme de control mecanic și nimic din creatura originală nu mai există. Desfășurată ca o platformă organică armată, învelișul puternic și mobilitatea fac din ea un adversar formidabil.\"\n  STR_ION_BEAM_ACCELERATORS_UFOPEDIA: \"Navele extraterestre folosesc sisteme energetice complexe pentru a se deplasa la viteze incredibile prin adâncuri. Fundamentul tehnologiei este dislocarea ionică, folosind Zrbite drept catalist motoarele dislocă de 100 de ori pe secundă propriul volum în apă. Semnificația acestei enorme puteri este că extratereștrii sunt capabili să întreacă majoritatea navelor pământene. Putem replica acest sistem de propulsie folosind plastice extraterestre și Zrbite.\"\n  STR_MAGNETIC_NAVIGATION_UFOPEDIA: \"Acest ansamblu generează un câmp magnetic sferic multistrat, proiectat până la 1000m în jurul navei. Piloții extratereștri sunt direct legați de echipament, pur și simplu simțind lumea invizibilă de sub valuri. Interfața de sistem funcționează cu materie cerebrală extraterestră modificată ce comunică direct cu creierul utilizatorului printr-o rețea neurală.\"\n  STR_ALIEN_SUB_CONSTRUCTION_UFOPEDIA: \"Fiecare navă are o structură cameleonică, modelată după creaturi marine și realizată din plastice extraterestre. Fiecare din ele funcționează precum un organism: echipaj și navă în armonie. Majoritatea sistemelor pot fi replicate și o tehnologie hibridă poate fi dezvoltată pentru a ne permite să atingem același nivel de tehnologie.\"\n  STR_ALIEN_CRYOGENICS_UFOPEDIA: \"Nenumărații extratereștri ce au stat ascunși pe Pământ sunt ținuți în stază, înghețați criogenic. Toate creaturile sunt închise în capsule, cu temperatura corpului redusă până la un punct în care toate funcțiile sunt aproape oprite. Examinarea capsulelor de până acum dezvăluie perioadele de timp incredibile în care corpurile au fost ținute, unele pentru 60 de milioane de ani.\"\n  STR_ALIEN_CLONING_UFOPEDIA: \"Mulți dintre extratereștrii capturați sunt identici, chiar și la nivel de ADN, duplicați în toate privințele. Mostrele celulare păstrate în băncile de gene înghețate sunt plasate în capsule. Unele dintre acestea conțin oameni sau diverse părți din corp. Este posibil ca o altă utilizare a acestora să fie aceea de a crea un hibrid om-extraterestru.\"\n  STR_ALIEN_LEARNING_ARRAYS_UFOPEDIA: \"Aceste mașinării injectează informația direct în creier folosind implanturile de Control Molecular din craniul tuturor extratereștrilor. Proaspăt clonați, sunt aduși în aceste capsule și li se descarcă amintirile rasiale și informațiile științifice sau de luptă în mințile goale.\"\n  STR_ALIEN_IMPLANTER_UFOPEDIA: \"Această mașinărie este folosită pentru a monta implanturi de Control Molecular extratereștrilor, pentru a fecunda rasele reproducătoare și pentru a introduce sau îndepărta organe sau electronica din orice creatură. Se credea că procesul are loc fără știința subiectului dar acesta este pe deplin conștient și din păcate anatomia umană pare a se potrivi perfect mașinăriei.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"Am strâns dovezi suficiente pentru a ne da seama de ce extratereștrii răpesc oameni. Nu sunt pentru hrană și nici pentru a fi fecundați cu embrioni extratereștri ci formează baza unor serii de creaturi și sisteme de control. Tehnologia extraterestră se bazează pe o minte comună, o inteligență împărtășită, iar creierul uman este receptorul ideal pentru aceste sisteme. Țesutul cerebral uman este folosit pentru stocarea datelor și a sistemelor iar restul pentru construcție și înmulțire.\"\n  STR_AQUA_PLASTICS_UFOPEDIA: \"Navele și structurile extraterestre utilizează un material extrem de puternic, flexibil și durabil pentru majoritatea elementelor. Plasticele extraterestre sunt materiale omogene catalizate de Zrbite. Densă și totuși ușoară, substanța are o rezistență mai mare decât titaniul sau kevlarul.\"\n  STR_ZRBITE_UFOPEDIA: \"Acest aliaj de origine extraterestră conține aur și material biologic extraterestru. Utilizate ca sursă de energie, cantități mici generează mai multă energie decât o centrală nucleară de 10 ori mai mare. Replicarea acestui material este dincolo de abilitățile noastre tehnologice de vreme ce majoritatea elementelor sunt de natură extraterestră.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"Extratereștrii lovesc pe tot globul cu eficiență nemiloasă. Nu le putem identifica sursa. Poate fi în adâncul impenetrabil al unui ocean prea profund pentru a fi localizată de către noi? Nu toate organismele identificate sunt extraterestre, unele sunt arhaice sau de pe linii evolutive crezut dispărute. Avem de-a face cu o amenințare adormită de milenii, o subtilă simbioză între om și extraterestru. Adânc în oceane se găsesc zone antice folosite de extratereștri pentru a-și contacta verii stelari. Fiecare dintre aceste douăsprezece zone conțin un dispozitiv Synomium. Odată pornită mașinăria de război extraterestră, aceste zone sunt reactivate pentru a lărgi rețeaua de Control Molecular. Trebuie distruse cu orice preț.\"\n  STR_THE_ULTIMATE_THREAT_UFOPEDIA: \"Acum 65 de milioane de ani o enormă navă de colonizare a fost trimisă către Pământ dintr-o lume extraterestră îndepărtată. Când s-a apropiat de mica planetă o explozie solară violentă a defectat sistemele de navigație. Avariată, nava a străpuns stratosfera și s-a ivit pe cerul Cretacicului. Pe Pământ, numeroase viețuitoare și-au îndreptat privirea către cer în timp ce nenorocirea izbea planeta. Un vast nor de praf a înăbușit atmosfera și, pe măsură ce lumea s-a răcit, măreții dinozauri au pierit. Dar cele 400 de miliarde de tone ale T'leth nu s-au distrus în impact, computerele sofisticate inițiind o perioadă de somn criogenic creaturilor din echipaj. Odată cu trecerea erelor computerele au trezit grupuri de extratereștri pentru a încerca contactarea verilor stelari, însa totul a fost în zadar, nava dormind în continuare.\"\n  STR_TLETH_THE_ALIEN_CITY: \"T'leth, Orașul Extratereștrilor\"\n  STR_TLETH_THE_ALIEN_CITY_UFOPEDIA: \"T'leth, enorma navă de colonizare extraterestră, se află încastrată în Sigsbee Deep, în golful Mexic. În inima orașului se află o teroare atât de ticăloasă și puternică că nici moartea nu o poate lua. Înt-o cameră din metal extraterestru se află forma adormită a Marelui Visător, Extraterestrul Suprem. Ridicarea T'leth la suprafață va declanșa perioada de reanimare și odată cu ea acesta va fi de neoprit. Deși nu este viu și totuși nici mort, mintea extraterestră controlează armata. Ciudata tehnologie a controlului molecular unește toți extratereștrii cu mintea Supremă, iar ea îi controlează pe toți. Fetuși hibrid extraterestru/om furnizează minții energia și formează legătura dintre conducător și supuși. Mitul Extraterestrului Suprem a existat în inimile și mințile umanității timp de secole dar marea a ascuns dintotdeauna adevărul suprem.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"CENTRARE ZONĂ-TIMP=5 Sec\"\n  STR_CANCEL_UC: \"ANULARE\"\n  STR_NONE: \"Nimic\"\n  STR_UNKNOWN: \"Necunoscut\"\n  STR_POOR: \"Slab\"\n  STR_AVERAGE: \"Mediu\"\n  STR_GOOD: \"Bun\"\n  STR_EXCELLENT: \"Excelent\"\n  STR_BUILD_NEW_BASE_UC: \"CONSTRUIRE BAZĂ NOUĂ\"\n  STR_BASE_INFORMATION: \"INFORMAȚII BAZĂ\"\n  STR_EQUIP_CRAFT: \"DOTĂRI NAVĂ\"\n  STR_BUILD_FACILITIES: \"CONSTRUIRE STRUCTURI\"\n  STR_RESEARCH: \"CERCETARE\"\n  STR_MANUFACTURE: \"PRODUCȚIE\"\n  STR_TRANSFER_UC: \"TRANSFER\"\n  STR_PURCHASE_RECRUIT: \"ACHIZIȚII/RECRUTĂRI\"\n  STR_SACK: \"CONCEDIERE\"\n  STR_SELL_SACK_UC: \"VÂNZĂRI/CONCEDIERI\"\n  STR_GEOSCAPE_UC: \"GEOSFERĂ\"\n  STR_NAME: \"Nume\"\n  STR_AREA: \"Zonă\"\n  STR_BUILD_NEW_BASE: \"Construire Bază Nouă\"\n  STR_CANCEL: \"Anulare\"\n  STR_COST_UC: \"COST>\"\n  STR_CONSTRUCTION_TIME_UC: \"TIMP CONSTRUCȚIE>\"\n  STR_DAY:\n    one: \"{N} zi\"\n    few: \"{N} zile\"\n    other: \"{N} zile\"\n  STR_HOUR:\n    one: \"{N} oră\"\n    few: \"{N} ore\"\n    other: \"{N} ore\"\n  STR_MAINTENANCE_UC: \"ÎNTREȚINERE>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Structuri\"\n  STR_CURRENT_RESEARCH: \"CERCETARE CURENTĂ\"\n  STR_SCIENTISTS_AVAILABLE: \"Cercetători Disponibili>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Cercetători Alocați>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Spațiu Disponibil Laboratoare>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"PROIECT CERCETARE\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"CERCETĂTORI ALOCAȚI\"\n  STR_PROGRESS: \"EVOLUȚIE\"\n  STR_NEW_PROJECT: \"Proiect Nou\"\n  STR_CANCEL_PROJECT: \"ANULARE PROIECT\"\n  STR_NEW_RESEARCH_PROJECTS: \"NOI PROIECTE DE CERCETARE\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"CERCETĂTORI DISPONIBILI>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"SPAȚIU DISPONIBIL LABORATOARE>{ALT}{0}\"\n  STR_INCREASE: \"Creștere\"\n  STR_DECREASE: \"Scădere\"\n  STR_START_PROJECT: \"DEMARARE PROIECT\"\n  STR_CURRENT_PRODUCTION: \"PRODUCȚIE CURENTĂ\"\n  STR_ENGINEERS_AVAILABLE: \"Tehnicieni Disponibili>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Tehnicieni Alocați>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Spațiu Disponibil Ateliere>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Fonduri Curente>{ALT}{0}\"\n  STR_ITEM: \"ARTICOL\"\n  STR_ENGINEERS__ALLOCATED: \"Tehnicieni Alocați\"\n  STR_UNITS_PRODUCED: \"Unități Produse\"\n  STR_TOTAL_TO_PRODUCE: \"Total de Produs\"\n  STR_COST__PER__UNIT: \"Cost{NEWLINE}Unitar{NEWLINE}\"\n  STR_DAYS_HOURS_LEFT: \"Zile/Ore Rămase\"\n  STR_NEW_PRODUCTION: \"Producție Nouă\"\n  STR_PRODUCTION_ITEMS: \"Articole Producție\"\n  STR_CATEGORY: \"CATEGORIE\"\n  STR_START_PRODUCTION: \"PORNIRE PRODUCȚIE\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} ore pentru a produce un articol\"\n  STR_COST_PER_UNIT_: \"Cost unitar>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Spațiu de Lucru Necesar>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"MATERIALE SPECIALE NECESARE\"\n  STR_ITEM_REQUIRED: \"ARTICOL NECESAR\"\n  STR_UNITS_REQUIRED: \"UNITĂȚI NECESARE\"\n  STR_UNITS_AVAILABLE: \"UNITĂȚI DISPONIBILE\"\n  STR_STOP_PRODUCTION: \"OPRIRE PRODUCȚIE\"\n  STR_ENGINEERS_AVAILABLE_UC: \"TEHNICIENI DISPONIBILI>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"SPAȚIU DISPONIBIL ATELIERE>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"PROFIT LUNAR>{ALT}{0}\"\n  STR_INCREASE_UC: \"CREȘTERE\"\n  STR_DECREASE_UC: \"SCĂDERE\"\n  STR_UNITS_TO_PRODUCE: \"Unități de Produs\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Achiziții Articole/Recrutări Personal\"\n  STR_COST_OF_PURCHASES: \"Costul Achizițiilor>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"COST UNITAR\"\n  STR_QUANTITY_UC: \"CANTITATE\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"PERSONAL DISPONIBIL:TOTAL PERSONAL>\"\n  STR_SOLDIERS: \"Scafandrieri\"\n  STR_SCIENTISTS: \"Cercetători\"\n  STR_ENGINEERS: \"Tehnicieni\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"SPAȚIU UTILIZAT:SPAȚIU DISPONIBIL>\"\n  STR_LIVING_QUARTERS: \"Ansamblu Locuințe\"\n  STR_STORES: \"Depozite\"\n  STR_LABORATORIES: \"Laboratoare\"\n  STR_WORK_SHOPS: \"Ateliere\"\n  STR_HANGARS: \"Refugiu Nave\"\n  STR_SHORT_RANGE_DETECTION: \"Sonar cu Rază Scurtă\"\n  STR_DEFENSE_STRENGTH: \"Putere Sistem Defensiv\"\n  STR_TRANSFERS_UC: \"TRANSFERURI\"\n  STR_TRANSFERS: \"Transferuri\"\n  STR_ARRIVAL_TIME_HOURS: \"Timp Sosire (ore)\"\n  STR_COST_: \"Cost>{ALT}{0}\"\n  STR_AREA_: \"Zonă>{ALT}{0}\"\n  STR_BASE_NAME: \"Denumirea Bazei?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"ALEGERE POZIȚIE ECLUZĂ ACCES\"\n  STR_TRANSFER: \"Transfer\"\n  STR_AMOUNT_TO_TRANSFER: \"CANTITATE DE TRANSFERAT\"\n  STR_SELECT_DESTINATION_BASE: \"Alegere Bază Destinație\"\n  STR_COST: \"Cost\"\n  STR_INTRO_1: \"Copyright 1995 MicroProse\"\n  STR_INTRO_2: \"Marte: Căderea Cydoniei.\"\n  STR_INTRO_3: \"Echipa X-Com triumfătoare decolează spre casă după ce au distrus nucleul mașinăriei de război extraterestre. Totuși, în baza marțiană devastată mai mișcă ceva.\"\n  STR_INTRO_4: \"Un puternic fascicul tahionic emite din ruinele centrului Cydonian - străbătând în viteză vidul. Destinația sa............\"\n  STR_INTRO_5: \"Pământul.\"\n  STR_INTRO_6: \"În adâncurile oceanului fascicolul lovește un receptor inactiv. Computerele încep să se trezească. În adâncuri, dincolo de privirile oamenilor, camere vaste cu extratereștri dormind își încep lunga perioadă de reanimare.\"\n  STR_INTRO_7: \"2040: Un Pământ ignorant. Ororile războaielor extraterestre sunt de mult uitate. Dar, în locurile pierdute și ascunse ale oceanului, hoardele extraterestre sunt pregătite - pregătite să răstoarne umanitatea și să stăpânească lumea.\"\n  STR_INTRO_8: \"Extratereștrii lovesc împotriva umanității; căutând specimene pentru experimentele lor denaturate; sărăcind globul de resursele minerale și valoroase; prădând mările. Apoi, extratereștrii își îndreaptă atenția la suprafață.\"\n  STR_INTRO_9: \"Submarine puternice cu design ciudat străbat oceanele - inspectând, căutând, vânând.........\"\n  STR_INTRO_10: \"Descoperind prada, lovesc.\"\n  STR_INTRO_11: \"Arme noi și ciudate exercitate împotriva unei lumi lipsite de apărare. Suntem cu totul la mila amenințării extraterestre.{NEWLINE}Numai o singură organizație ne poate salva; dar, le-am întors spatele cu mult timp în urmă......\"\n  STR_INTRO_12: \"Structura Subacvatică Experimentală X-COM\"\n  STR_INTRO_13: \"'SOS! SOS!' 'Aici nava transatlantică de linie Hyperion'. 'Suntem atacați'. 'SOS! SO............'\"\n  STR_INTRO_14: \"'Centrul de Comandă către Hangarul Unu: Deschideți ușile către ocean', 'lansați Barracuda Zero Unu. Avem un atac extraterestru - grad Roșu'.{NEWLINE}'Repet: grad Roșu'\"\n  STR_INTRO_15: \"Extratereștrii au o eficacitate lipsită de milă....\"\n  STR_INTRO_16: \"...și o precizie infailibilă.\"\n  STR_INTRO_17: \"'Barracuda Zero Unu către bază' - 'ne apropiem de rămășițele navei Hyperion'.\"\n  STR_INTRO_18: \"'Decelerăm'.{NEWLINE}'Doi metri'{NEWLINE}'Un metru'{NEWLINE}'Toți scafandrierii să fie pregătiți de atac'.\"\n  STR_INTRO_19: \"...........'Am trecut de ecluză'...'ne apropiem de resturile vasului'.{NEWLINE}'Doamne!'{NEWLINE}'Vedeți acele creaturi pe camera costumului meu?'\"\n  STR_GAMEOVER_1: \"Am eșuat, extratereștrii ne-au nimicit ultimele speranțe de salvare.{NEWLINE}X-Com este distrusă și Pământul se află la picioarele dușmanului străvechi.\"\n  STR_GAMEOVER_2: \"T'leth se înalță în stratosferă și începe să se deplaseze pe suprafața lumii, împărțind moarte și recoltând rămășițele speciei umane. Adânc în măruntaiele sale, criminala minte extraterestră începe să se trezească.\"\n  STR_GAMEOVER_3: \"În orașele capitală ale tuturor națiunilor se fac planuri disperate. Totul este zadarnic, fără tehnologia acordată de către proiectul de cercetare X-Com armele noastre sunt ineficiente.\"\n  STR_GAMEOVER_4: \"Extratereștrii construiesc baze la calotele polare și încep topirea gheții, lumea devenind o mare vastă. Rămășițele rasei umane sunt adunate și folosite în experimente grotești de reproducere în scopuri necunoscute. Cerul se întunecă și o plagă puternică se abate asupra Pământului.\"\n  STR_GAMEOVER_5: \"Nu putem rezista împotriva noii ordini a lumii, cei ce încearcă au o soartă groaznică în mâinile armelor extraterestre de neînțeles. Restul nu au parte de o așa eliberare, Pământul devenind o lume extraterestră, iar umanitatea este pierdută sub o groază înfiorătoare.\"\n  STR_OUTRO_1: \"Mormântul, devastat și decimat, un răget bolborosit răsunând din cavou, în centrul său.{NEWLINE}Proștilor, veți pieri cu toții....................\"\n  STR_OUTRO_2: \".................nimeni nu poate scăpa.\"\n  STR_OUTRO_3: \"O explozie masivă erupe din mormânt și spintecă orașul, rămășițele și fumul umplu aerul. Planurile extratereștrilor sunt dejucate........\"\n  STR_OUTRO_4: \"Imensitatea orașului T'leth începe să se sfărâme. Flăcări și fum se revarsă din turnurile sale sclipitoare și sălile de adamantiu.\"\n  STR_OUTRO_5: \"Măreața fortăreață extraterestră se prăvălește în mare, țipătul metalului și sufletelor torturate umple aerul. Marele Visător nu va mai visa la cucerirea lumii.\"\n  STR_OUTRO_6: \"O ultimă zguduire asurzitoare și T'leth se destramă complet.{NEWLINE}Amenințarea extraterestră a dispărut, Pământul este curățit..................\"\n  STR_OUTRO_7: \"O planetă albastră-verde adormită, într-un colț îndepărtat al galaxiei.\"\n  STR_OUTRO_8: \"În viitorul apropiat, un loc sigur de locuit.\"\n  STR_OUTRO_9: \"Amenințarea extraterestră asupra Pământului a fost de mult învinsă.\"\n  STR_OUTRO_10: \"Orașe vaste, metropole adăpostind miliardele roditoare ale umanității.\"\n  STR_OUTRO_11: \"Isprăvile X-Com și războaiele extraterestre sunt povești din cărțile pentru copii.\"\n  STR_OUTRO_12: \"Dar legendele au avut întotdeauna obiceiul de a conține un sâmbure de adevăr............\"\n  STR_RISE_1: \"T'leth, numit în multe feluri în multe legende din multe ținuturi.\"\n  STR_RISE_2: \"Cu un răget exploziv ce reverberează pe tot globul T'leth începe să se ridice de pe fundul mării.\"\n  STR_RISE_3: \"Enormul edificiu tălăzuiește prin apele Golfului Mexic.\"\n  STR_RISE_4: \"400 de miliarde de tone de metal extraterestru, mărețul oraș extraterestru unde se găsește corpul Extraterestrului Suprem. Întemnițat pe Pământ timp de 65 de milioane de ani, acest ticălos Zeu spațial începe să se agite.\"\n  STR_RISE_5: \"Apele fierb și se agită pe măsură ce mormântul Marelui Visător iese la lumină................\"\n  STR_RISE_6: \".........o lumină ce va fi de scurtă durată dacă X-Com nu distruge mașina de război extraterestră.\"\n  STR_YOU_HAVE_FAILED: \"Ai eșuat în a opri mașina de război extraterestră. Organizațiile finanțatoare sunt dezamăgite de abilitatea ta de a negocia o soluție non-militară cu extratereștrii. Invadatorii au o agendă foarte diferită și în curând lumea întreagă își dă seama de adevăr...\"\n  STR_TOTAL_UC: \"TOTAL\"\n  STR_INCOME: \"Venit\"\n  STR_EXPENDITURE: \"Cheltuieli\"\n  STR_MAINTENANCE: \"Întreținere\"\n  STR_BALANCE: \"Balanță\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"Activități Extraterestre în Mări\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"Activități Extraterestre în Zone\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"Activități X-Com în Mări\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"Activități X-Com în Zone\"\n  STR_FINANCE: \"Finanțe\"\n  STR_DATE_FIRST: \"{0}\"\n  STR_DATE_SECOND: \"{0}\"\n  STR_DATE_THIRD: \"{0}\"\n  STR_DATE_FOURTH: \"{0}\"\n  STR_FINANCE_THOUSANDS: \"mii $\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Materiale speciale insuficiente pentru a produce{NEWLINE}{0}{NEWLINE}în{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Fonduri insuficiente pentru a produce{NEWLINE}{0}{NEWLINE}în{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"Producția de{NEWLINE}{0}{NEWLINE}de la{NEWLINE}{1}{NEWLINE}este completă\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"Lucrările pentru{NEWLINE}{0}{NEWLINE}din{NEWLINE}{1}{NEWLINE}s-au finalizat\"\n  STR_OK_5_SECONDS: \"OK - 5 sec\"\n  STR_RESEARCH_COMPLETED: \"Cercetare Completă\"\n  STR_VIEW_REPORTS: \"RAPORTARE\"\n  STR_WE_CAN_NOW_RESEARCH: \"Putem cerceta\"\n  STR_WE_CAN_NOW_PRODUCE: \"Putem produce\"\n  STR_SUNDAY: \"DUMINICĂ\"\n  STR_MONDAY: \"LUNI\"\n  STR_TUESDAY: \"MARȚI\"\n  STR_WEDNESDAY: \"MIERCURI\"\n  STR_THURSDAY: \"JOI\"\n  STR_FRIDAY: \"VINERI\"\n  STR_SATURDAY: \"SÂMBĂTĂ\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Insuficient {0} pentru realimentare {1} din {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Insuficient(e) {0} pentru re-înarmarea {1} din {2}\"\n  STR_UFO_IS_NOT_RECOVERED: \"OSN pierdut\"\n  STR_UFO_IS_RECOVERED: \"OSN recuperat\"\n  STR_CRAFT_IS_LOST: \"Navă pierdută\"\n  STR_TERROR_CONTINUES: \"Activitățile Extraterestre continuă\"\n  STR_ALIENS_DEFEATED: \"Extratereștrii sunt înfrânți\"\n  STR_BASE_IS_LOST: \"Bază pierdută\"\n  STR_BASE_IS_SAVED: \"Bază salvată\"\n  STR_ALIEN_BASE_STILL_INTACT: \"Colonie Extraterestră încă intactă\"\n  STR_ALIEN_BASE_DESTROYED: \"Colonie Extraterestră distrusă\"\n  STR_ALIENS_KILLED: \"EXTRATEREȘTRI UCIȘI\"\n  STR_ALIEN_CORPSES_RECOVERED: \"CADAVRE EXTRATERESTRE RECUPERATE\"\n  STR_LIVE_ALIENS_RECOVERED: \"EXTRATEREȘTRI CAPTURAȚi VII\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"ARTEFACTE EXTRATERESTRE RECUPERATE\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"CONTROLUL COLONIEI EXTRATERESTRE DISTRUS\"\n  STR_ALIEN_SYNOMIUM_DEVICE_DESTROYED: \"DISPOZITIVUL SYNOMIUM DISTRUS\"\n  STR_ALIEN_SYNOMIUM_DEVICE_FAILED: \"DISTRUGEREA DISPOZITIVULUI SYNOMIUM EȘUATĂ\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"CIVILI UCIȘI DE EXTRATEREȘTRII\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"CIVILI UCIȘI DE SOLDAȚI X-COM\"\n  STR_CIVILIANS_SAVED: \"CIVILI SALVAȚI\"\n  STR_XCOM_OPERATIVES_KILLED: \"SOLDAȚI X-COM UCIȘI\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"SOLDAȚI X-COM DISPĂRUȚI ÎN MISIUNE\"\n  STR_TANKS_DESTROYED: \"SISTEME SUBMERSIBILE ARMATE X-COM DISTRUSE\"\n  STR_XCOM_CRAFT_LOST: \"NAVĂ X-COM PIERDUTĂ\"\n  STR_UFO_RECOVERY: \"RECUPERARE OSN\"\n  STR_ALIEN_BASE_RECOVERY: \"RECUPERATE DIN COLONIA EXTRATERESTRĂ\"\n  STR_BASE_UNDER_ATTACK: \"{0} se află sub asediu!\"\n  STR_BASE_DEFENSES_INITIATED: \"APĂRAREA BAZEI INIȚIATĂ\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"SCUTURILE RESPING OSNul!\"\n  STR_FIRING: \"EXECUTĂ FOC\"\n  STR_HIT: \"LOVIT!\"\n  STR_UFO_DESTROYED: \"OSN DISTRUS!\"\n  STR_MISSED: \"RATAT!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Vânzări Articole/Concedieri Personal\"\n  STR_VALUE_OF_SALES: \"VALOARE VÂNZĂRI> {ALT}{0}\"\n  STR_FUNDS: \"FONDURI> {ALT}{0}\"\n  STR_SELL_SACK: \"Vânzări/Concedieri\"\n  STR_VALUE: \"Valoare\"\n  STR_CRAFT_: \"OSN> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"RECUPERARE OSN DOBORÂT\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"PRUDENȚĂ MAXIMĂ - Există inamici în OSN sau în zona unde s-a prăbușit acesta. Misiunea va avea succes numai atunci când toți inamicii au fost eliminați sau neutralizați. După aceea poate fi inițiată recuperarea resturilor de OSN, a artefactelor și cadavrelor extratereștrilor. Pentru a anula misiunea scafandrierii X-Com trebuie să se întoarcă în nava de transport după care se apasă pe butonul 'Abandonare Misiune'.\"\n  STR_UFO_GROUND_ASSAULT: \"ASALT SUBMARIN ASUPRA OSN\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"Echipa va explora zona și, dacă e posibil, va pătrunde în OSN. Misiunea va avea succes numai atunci când toți inamicii au fost eliminați sau neutralizați. După aceea poate fi inițiată recuperarea resturilor de OSN, a artefactelor și cadavrelor extratereștrilor. Pentru a anula misiunea scafandrierii X-Com trebuie să se întoarcă în nava de transport după care se apasă pe butonul 'Abandonare Misiune'.\"\n  STR_BASE_DEFENSE: \"APĂRAREA BAZEI\"\n  STR_BASE_UC_: \"BAZĂ> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"O navă extraterestră a aterizat în apropiere. Baza noastră este în pericol. Tot personalul necombatant a fost evacuat cu navele X-Com. Extratereștrii vor pătrunde în bază prin porțile hangarelor sau ecluza de acces. Apară baza și structurile vitale cu orice preț - aceasta este o luptă pe viață și pe moarte. Butonul 'Abandonare Misiune' declanșează capitularea și pierderea bazei.\"\n  STR_ALIEN_COLONY_ATTACK_MISSION: \"MISIUNE DE ATAC ASUPRA COLONIEI ET\"\n  STR_ALIEN_BASE_ASSAULT: \"COLONIE EXTRATERESTRĂ P1\"\n  STR_ALIEN_COLONY_P1_BRIEFING: \"Misiunea aceasta este un raid asupra unei colonii extraterestre. Această zonă are 2 nivele, toți scafandrierii trebuind să ajungă în zona de evacuare din primul complex după care se apasă pe butonul 'Abandonare Misiune'. Tot echipamentul lăsat în urmă va rămâne pe fundul mării până se rezolvă a 2-a secțiune. Pentru a anula misiunea scafandrierii trebuie să se întoarcă în nava de transport după care se apasă pe butonul 'Abandonare Misiune'.\"\n  STR_ALIEN_COLONY_P2: \"COLONIE EXTRATERESTRĂ P2\"\n  STR_ALIEN_COLONY_P2_BRIEFING: \"După curățirea primului nivel se intră în inima coloniei. Misiunea constă în distrugerea centrului de control, dispozitivul Synomium, sau eliminarea tuturor extratereștrilor. Pentru a anula misiunea scafandrierii trebuie să se întoarcă în punctul de plecare după care se apasă pe butonul 'Abandonare Misiune'. Tot echipamentul X-Com viabil va fi înapoiat în bază.\"\n  STR_ALIENS_LAUNCH_PORT_TERROR: \"EXTRATEREȘTRII{NEWLINE}ATACĂ PORTUL\"\n  STR_PORT_TERROR: \"ATAC EXTRATERESTRU PORTUAR\"\n  STR_PORT_TERROR_BRIEFING: \"Extratereștrii au lansat un atac împotriva zonelor de suprafață. Portul și populația civilă sunt în pericol. Echipa trebuie să elimine toți extratereștrii și să protejeze trecătorii nevinovați de incursiunea extraterestră. Pentru a anula misiunea scafandrierii trebuie să se întoarcă în nava de transport după care se apasă pe butonul 'Abandonare Misiune'.\"\n  STR_ALIENS_LAUNCH_ISLAND_TERROR: \"EXTRATEREȘTRII{NEWLINE}ATACĂ INSULA\"\n  STR_ISLAND_TERROR: \"ATAC EXTRATERESTRU INSULAR\"\n  STR_ISLAND_TERROR_BRIEFING: \"Extratereștrii au lansat un atac împotriva zonelor de suprafață. Insula și populația civilă sunt în pericol. Echipa trebuie să elimine toți extratereștrii și să protejeze trecătorii nevinovați de incursiunea extraterestră. Pentru a anula misiunea scafandrierii trebuie să se întoarcă în nava de transport după care se apasă pe butonul 'Abandonare Misiune'.\"\n  STR_ALIENS_ATTACK_SHIPPING_ROUTE: \"EXTRATEREȘTRII ATACĂ {NEWLINE}RUTA MARITIMĂ\"\n  STR_CARGO_SHIP_P1: \"CARGOBOT P1\"\n  STR_CARGO_SHIP_P2: \"CARGOBOT P2\"\n  STR_CRUISE_SHIP_P1: \"VAS DE CROAZIERĂ P1\"\n  STR_CRUISE_SHIP_P2: \"VAS DE CROAZIERĂ P2\"\n  STR_SHIP_RESCUE_MISSION: \"MISIUNE DE SALVARE VAS\"\n  STR_SHIP_RESCUE_P1_BRIEFING: \"Misiunea este una de vânătoare, de eliminare a tuturor extratereștrilor de pe navă și de a păstra în viață civili de la bord. Extratereștrii sunt dispersați pe punte și în cala navei, recomandată fiind curățarea punții superioare, după care se coboară la cele inferioare. Pentru a anula misiunea scafandrierii trebuie să se întoarcă în nava de transport după care se apasă pe butonul 'Abandonare Misiune'.\"\n  STR_SHIP_RESCUE_P2_BRIEFING: \"Acum că puntea superioară este liberă se continuă cu cele inferioare. Folosind liftul de marfă se coboară în cală. Echipa trebuie să elimine toți extratereștrii de la acest nivel pentru a încheia misiunea. Pentru a anula misiunea scafandrierii trebuie să se întoarcă în liftul de acces după care se apasă pe butonul 'Abandonare Misiune'.\"\n  STR_ALIEN_ACTIVITY_DETECTED: \"ACTIVITĂȚI ET DETECTATE\"\n  STR_ALIEN_CONTACT_SITE_MISSION: \"MISIUNE ÎN ZONA DE CONTACT ET\"\n  STR_ARTIFACT_SITE_P1: \"ZONA DE CONTACT ET P1\"\n  STR_ARTIFACT_SITE_P1_BRIEFING: \"Misiunea este un raid asupra unei zone de comunicație proaspăt activate. Zona are 2 niveluri, fundul mării cu piramidele extraterestre și un complex subteran ascuns. Echipa trebuie să ajungă la intrarea în complex după care se apasă pe butonul 'Abandonare Misiune'. Pentru a anula misiunea scafandrierii trebuie să se întoarcă în nava de transport după care se apasă pe butonul 'Abandonare Misiune'.\"\n  STR_ARTIFACT_SITE_P2: \"ZONA DE CONTACT ET P1\"\n  STR_ARTIFACT_SITE_P2_BRIEFING: \"După curățirea primului nivel și intrarea în complex, scopul misiunii este clar. Infiltrarea în inima structurii extraterestre și distrugerea dispozitivului Synomium de Control Molecular, sau eliminarea tuturor extratereștrilor. Pentru a anula misiunea scafandrierii trebuie să se întoarcă în liftul de acces după care se apasă pe butonul 'Abandonare Misiune'.\"\n  STR_SIGSBEE_DEEP_MISSION: \"MISIUNEA SIGSBEE DEEP{NEWLINE}ORAȘ ET NIVEL UNU\"\n  STR_TLETH_P1_BRIEFING: \"Pătrundem în necunoscut, de aici în colo ne putem aștepta la orice. Știm că orașul extraterestru mai are încă 2 nivele și că echipa trebuie sa ajungă la ieșirea din acest nivel pentru a intra în următorul. Pentru a avansa în misiune scafandrierii trebuie să ajungă la ieșire după care se apasă pe butonul 'Abandonare Misiune'. Orice altceva duce la eșecul misiunii.\"\n  STR_TLETH_ATTACK_MISSION: \"MISIUNEA DE ATAC T'LETH{NEWLINE}ORAȘ ET NIVEL DOI\"\n  STR_TLETH_P2_BRIEFING: \"Pătrundem și mai adânc în necunoscut, de aici în colo ne putem aștepta la orice. Știm că orașul extraterestru mai are încă un nivel și că echipa trebuie sa ajungă la ieșirea din acest nivel pentru a intra în următorul. Pentru a avansa în misiune scafandrierii trebuie să ajungă la ieșire după care se apasă pe butonul 'Abandonare Misiune'. Orice altceva duce la eșecul misiunii.\"\n  STR_FINAL_TLETH_MISSION: \"MISIUNEA FINALĂ T'LETH{NEWLINE}ORAȘ ET NIVEL TREI\"\n  STR_TLETH_P3_BRIEFING: \"Sfârșitul este aproape, de aici în colo căutăm mormântul Extraterestrului Suprem. Cele 8 alimentări cu energie ale cavoului trebuie distruse pentru a opri amenințarea extraterestră. Nu trebuie să ne dăm bătuți acum! Abandonul duce la eșecul misiunii.\"\n  STR_TLETH_P1: \"ORAȘ ET NIVEL UNU\"\n  STR_TLETH_P2: \"ORAȘ ET NIVEL DOI\"\n  STR_TLETH_P3: \"ORAȘ ET NIVEL TREI\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"NU EXISTĂ HANGARE LIBERE PENTRU A PRODUCE NAVA!{SMALLLINE}Fiecare navă desemnată unei baze, transferată, cumpărată sau construită foloseste un hangar. Construiește un hangar nou sau transferă o navă în altă bază.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"NU EXISTĂ HANGARE LIBERE PENTRU ACHIZIȚIE!{SMALLLINE}Fiecare navă desemnată unei baze, transferată, cumpărată sau construită foloseste un hangar. Construiește un hangar nou sau transferă o navă în altă bază.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"NU EXISTĂ HANGARE LIBERE PENTRU TRANSFER!{SMALLLINE}Fiecare navă desemnată unei baze, transferată, cumpărată sau construită foloseste un hangar. Construiește un hangar nou sau transferă o navă în altă bază.\"\n  STR_CANNOT_BUILD_HERE: \"NU SE POATE CONSTRUI AICI!{SMALLLINE}Trebuie amplasat lângă o structură existentă.\"\n  STR_NO_FREE_ACCOMODATION: \"NU EXISTĂ LOCURI LIBERE!{SMALLLINE}Baza destinată nu are locuri libere în locuințe.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"SPAȚIU INSUFICIENT ÎN ATELIER!{SMALLLINE}Construiește un atelier nou sau redu activitatea la alte proiecte.\"\n  STR_NOT_ENOUGH_MONEY: \"FONDURI INSUFICIENTE!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"SPAȚIU DE DEPOZITARE INSUFICIENT!{SMALLLINE}Construiește un depozit nou sau transferă articole existente către alte baze.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"LOCUINȚE INSUFICIENTE!{SMALLLINE}Construiește locuințe sau transferă personal către alte baze.\"\n  STR_LAUNCH_INTERCEPTION: \"LANSARE INTERCEPȚIE\"\n  STR_CRAFT: \"NAVĂ\"\n  STR_STATUS: \"STARE\"\n  STR_BASE: \"BAZĂ\"\n  STR_READY: \"PREGĂTIT\"\n  STR_OUT: \"ÎN MISIUNE\"\n  STR_REPAIRS: \"REPARAȚII\"\n  STR_REFUELLING: \"REALIMENTARE\"\n  STR_REARMING: \"REÎNARMARE\"\n  STR_TARGET: \"ȚINTĂ: {0}\"\n  STR_WAY_POINT: \"PUNCT RUTĂ\"\n  STR_ARE_YOU_SURE_CYDONIA: \"Sigur trimitem această navă în misiune către T'leth?\"\n  STR_YES: \"DA\"\n  STR_NO: \"NU\"\n  STR_SELECT_DESTINATION: \"ALEGERE DESTINAȚIE\"\n  STR_CYDONIA: \"T'LETH\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"ALEGERE LOCAȚIE BAZĂ NOUĂ\"\n  STR_RETURN_TO_BASE: \"REVENIRE LA BAZĂ\"\n  STR_SELECT_NEW_TARGET: \"ALEGERE ȚINTĂ NOUĂ\"\n  STR_PATROL: \"PATRULARE\"\n  STR_STATUS_: \"STARE>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"AVARIAT - REVENIRE LA BAZĂ\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"REZERVOR GOL - REVENIRE LA BAZĂ\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"MISIUNE COMPLETĂ - REVENIRE LA BAZĂ\"\n  STR_PATROLLING: \"PATRULEAZĂ\"\n  STR_TAILING_UFO: \"URMĂREȘTE OSN\"\n  STR_INTERCEPTING_UFO: \"INTERCEPTARE OSN-{0}\"\n  STR_RETURNING_TO_BASE: \"REVENIRE LA BAZĂ\"\n  STR_DESTINATION_UC_: \"DESTINAȚIE: {0}\"\n  STR_BASE_UC: \"BAZĂ>{ALT}{0}\"\n  STR_SPEED_: \"VITEZĂ>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"VITEZĂ MAXIMĂ>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"ADÂNCIME>{ALT}{0}\"\n  STR_AIRBORNE: \"ÎN AER\"\n  STR_VERY_LOW: \"SUPERFICIALĂ\"\n  STR_LOW_UC: \"NORMALĂ\"\n  STR_HIGH_UC: \"MARE\"\n  STR_VERY_HIGH: \"FOARTE MARE\"\n  STR_FUEL: \"COMBUSTIBIL>{ALT}{0}\"\n  STR_WEAPON_ONE: \"ARMA-1>{ALT}{0}\"\n  STR_NONE_UC: \"NIMIC\"\n  STR_ROUNDS_: \"SALVE>{ALT}{0}\"\n  STR_WEAPON_TWO: \"ARMA-2>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"NAVĂ INTERCEPȚIE\"\n  STR_BASE_: \"Bază>{0}\"\n  STR_NAME_UC: \"NUME\"\n  STR_AMMO_: \"MUNIȚIE>{ALT}{0}\"\n  STR_CREW: \"ECHIPAJ\"\n  STR_EQUIPMENT_UC: \"ECHIPAMENT\"\n  STR_ARMOR: \"ARMURĂ\"\n  STR_MAX: \"MAXIM>{ALT}{0}\"\n  STR_ROOKIE: \"Recrut\"\n  STR_SQUADDIE: \"Fruntaș\"\n  STR_SERGEANT: \"Sergent\"\n  STR_CAPTAIN: \"Locotenent\"\n  STR_COLONEL: \"Comandor\"\n  STR_COMMANDER: \"Amiral\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Alegere Echipă pentru {0}\"\n  STR_SORT_BY: \"SORTARE DUPĂ...\"\n  STR_ORIGINAL_ORDER: \"ORDINE IMPLICITĂ\"\n  STR_MISSIONS2: \"MISIUNI\"\n  STR_KILLS2: \"VICTIME\"\n  STR_WOUND_RECOVERY2: \"VINDECARE RĂNI\"\n  STR_SPACE_AVAILABLE: \"SPAȚIU DISPONIBIL>{ALT}{0}\"\n  STR_SPACE_USED: \"SPAȚIU UTILIZAT>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"SPAȚIU UTILIZAT\"\n  STR_RANK: \"RANG\"\n  STR_WOUNDED: \"RĂNIT\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Echipament pentru {0}\"\n  STR_DEFENSE_VALUE: \"Valoare Defensivă\"\n  STR_HIT_RATIO: \"Raport Lovire\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}pregătit de{NEWLINE}aterizare lângă{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"Începere Misiune?\"\n  STR_SELECT_ARMAMENT: \"Alegere Armament\"\n  STR_AMMUNITION_AVAILABLE: \"MUNIȚIE DISPONIBILĂ\"\n  STR_ARMAMENT: \"ARMAMENT\"\n  STR_NOT_AVAILABLE: \"N.A.\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"ALEGERE ARMURĂ PENTRU{NEWLINE}{ALT}{0}\"\n  STR_TYPE: \"TIP\"\n  STR_PLASTIC_AQUA_ARMOR_UC: \"ARMURĂ ACVA-PLASTICĂ\"\n  STR_ION_ARMOR_UC: \"ARMURĂ IONICĂ\"\n  STR_MAGNETIC_ION_ARMOR_UC: \"ARMURĂ MAGNETO-IONICĂ\"\n  STR_PLASTIC_AQUA_ARMOR_UFOPEDIA: \"Această armură folosește nou descoperitele Plastice Extraterestre, oferind scafandrierilor o șansă în lupta împotriva amenințării extraterestre.\"\n  STR_ION_ARMOR_UFOPEDIA: \"O nouă și puternică protecție pentru scafandrieri, această armură este alimentată de o sursă de energie ionică ce amplifică mult viteza și forța utilizatorului, oferind cea mai bună protecție de până acum pentru trupele luptătoare.\"\n  STR_MAGNETIC_ION_ARMOR_UFOPEDIA: \"O versiune îmbunătățită a Armurii Ionice, având incorporată tehnologie de navigație magnetică ce permite libertate totală de mișcare în mediul acvatic.\"\n  STR_SELECT_ARMOR: \"Alegere Armură\"\n  STR_NORTH: \"NORD\"\n  STR_NORTH_EAST: \"NORD-EST\"\n  STR_EAST: \"EST\"\n  STR_SOUTH_EAST: \"SUD-EST\"\n  STR_SOUTH: \"SUD\"\n  STR_SOUTH_WEST: \"SUD-VEST\"\n  STR_WEST: \"VEST\"\n  STR_NORTH_WEST: \"NORD-VEST\"\n  STR_SELECT_ACTION: \"ALEGERE ACȚIUNE\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"CONTINUARE URMĂRIRE ȘI INTERCEPTARE\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"URMĂRIRE FĂRĂ INTERCEPTARE\"\n  STR_VERY_LARGE: \"FOARTE MARE\"\n  STR_LARGE: \"MARE\"\n  STR_MEDIUM_UC: \"MEDIU\"\n  STR_SMALL: \"MIC\"\n  STR_VERY_SMALL: \"FOARTE MIC\"\n  STR_GROUNDED: \"LA SOL\"\n  STR_DETECTED: \"Detectat\"\n  STR_SIZE_UC: \"DIMENSIUNE\"\n  STR_ALTITUDE: \"ADÂNCIME\"\n  STR_HEADING: \"DIRECȚIE\"\n  STR_SPEED: \"VITEZĂ\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"CENTRARE OSN-TIMP=5 Sec\"\n  STR_TRACKING_LOST: \"SEMNAL PIERDUT\"\n  STR_REDIRECT_CRAFT: \"REDIRECȚIONARE NAVĂ\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"ULTIMA LOCAȚIE CUNOSCUTĂ\"\n  STR_UFO_: \"OSN-{0}\"\n  STR_ALIEN_BASE_: \"COLONIE EXTRATERESTRĂ-{0}\"\n  STR_CRASH_SITE_: \"OSN DOBORÂT-{0}\"\n  STR_LANDING_SITE_: \"OSN ATERIZAT-{0}\"\n  STR_WAY_POINT_: \"PUNCT RUTĂ-{0}\"\n  STR_TERROR_SITE: \"ZONĂ TERORIZATĂ-{0}\"\n  STR_ARTIFACT_SITE: \"ZONĂ ARTEFACT-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}a ajuns la{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"Patrulează\"\n  STR_ALIEN_ORIGINS: \"Originile Extratereștrilor\"\n  STR_THE_ULTIMATE_THREAT: \"Amenințarea Supremă\"\n  STR_TLETH_ALIEN_CITY: \"T'leth, Orașul Extratereștrilor\"\n  STR_UFOPAEDIA: \"UFOpedia\"\n  STR_XCOM_CRAFT_ARMAMENT: \"NAVE ȘI ARMAMENT X-COM\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"SISTEME SUBMERSIBILE ARMATE\"\n  STR_WEAPONS_AND_EQUIPMENT: \"ECHIPAMENT GENERAL\"\n  STR_ALIEN_ARTIFACTS: \"ARTEFACTE ACVATICE\"\n  STR_BASE_FACILITIES: \"CONSTRUCȚII BAZĂ\"\n  STR_ALIEN_LIFE_FORMS: \"CREATURI EXTRATERESTRE\"\n  STR_ALIEN_RESEARCH_UC: \"TEHNOLOGII EXTRATERESTRE\"\n  STR_UFO_COMPONENTS: \"NOI TEHNOLOGII OSN\"\n  STR_UFOS: \"OSNuri EXTRATERESTRE\"\n  STR_SELECT_ITEM: \"SELECTARE ARTICOL\"\n  STR_ACCELERATION: \"ACCELERAȚIE>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"VOLUM REZERVOR>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"SOCLURI ARMAMENT>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"REZISTENȚĂ AVARII>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"SPAȚIU ÎNCĂRCĂTURĂ>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"SPAȚIU SSAuri>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Putere Foc\"\n  STR_RANGE: \"Rază Acțiune\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Precizie Foc\"\n  STR_RE_LOAD_TIME: \"Timp Reîncărcare\"\n  STR_SECONDS: \"{0}s\"\n  STR_DAMAGE_ARMOR_PIERCING: \"PERCUTANT\"\n  STR_DAMAGE_INCENDIARY: \"FOSFOROS\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"EXPLOZIV\"\n  STR_DAMAGE_LASER_BEAM: \"FASCICUL GAUSS\"\n  STR_DAMAGE_PLASMA_BEAM: \"FASCICUL SONIC\"\n  STR_DAMAGE_STUN: \"ÎNGHEȚARE\"\n  STR_DAMAGE_MELEE: \"MELEU\"\n  STR_DAMAGE_ACID: \"ACID\"\n  STR_DAMAGE_SMOKE: \"FUMIGEN\"\n  STR_SHOT_TYPE: \"TIP\"\n  STR_ACCURACY_UC: \"PRECIZIE\"\n  STR_TIME_UNIT_COST: \"RĂSTIMP\"\n  STR_DAMAGE_UC: \"PUTERE\"\n  STR_AMMO: \"MUNIȚIE\"\n  STR_SHOT_TYPE_AUTO: \"Automat\"\n  STR_SHOT_TYPE_SNAP: \"Rapid\"\n  STR_SHOT_TYPE_AIMED: \"Ochit\"\n  STR_CONSTRUCTION_TIME: \"Timp Construcție\"\n  STR_CONSTRUCTION_COST: \"Cost Construcție\"\n  STR_MAINTENANCE_COST: \"Cost Întreținere\"\n  STR_LOW: \"Scăzut\"\n  STR_MEDIUM: \"Mediu\"\n  STR_HIGH: \"Mare\"\n  STR_CRAFT_WEAPON: \"Armă Nave\"\n  STR_CRAFT_AMMUNITION: \"Muniție Nave\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Tanc Automatizat\"\n  STR_WEAPON: \"Armă\"\n  STR_AMMUNITION: \"Muniție\"\n  STR_EQUIPMENT: \"Echipament\"\n  STR_ALIEN_CORPSE: \"Cadavru Extraterestru\"\n  STR_UFO_COMPONENT: \"Componentă OSN\"\n  STR_PERSONAL_ARMOR: \"Armură Personală\"\n  STR_RAW_MATERIALS: \"Materii Prime\"\n  STR_HWP_SOLID_HARPOON_BOLTS: \"Muniție Artilerie SSA\"\n  STR_ALIEN: \"Extraterestru\"\n  STR_AQUATOID: \"Aquatoid\"\n  STR_GILLMAN: \"Gill Man\"\n  STR_LOBSTERMAN: \"Lobster Man\"\n  STR_TASOTH: \"Tasoth\"\n  STR_CALCINITE: \"Calcinite\"\n  STR_DEEP_ONE: \"Deep One\"\n  STR_BIODRONE: \"Bio-drone\"\n  STR_TENTACULAT: \"Tentaculat\"\n  STR_TRISCENE: \"Triscene\"\n  STR_HALLUCINOID: \"Hallucinoid\"\n  STR_XARQUID: \"Xarquid\"\n  STR_ZOMBIE: \"Zombie\"\n  STR_LIVE_COMMANDER: \"Comandant\"\n  STR_LIVE_NAVIGATOR: \"Pilot\"\n  STR_LIVE_MEDIC: \"Medic\"\n  STR_LIVE_TECHNICIAN: \"Tehnician\"\n  STR_LIVE_SQUAD_LEADER: \"Lider\"\n  STR_LIVE_SOLDIER: \"Soldat\"\n  STR_LIVE_TERRORIST: \"Terorist\"\n  STR_AQUATOID_COMMANDER: \"Comandant Aquatoid\"\n  STR_AQUATOID_NAVIGATOR: \"Pilot Aquatoid\"\n  STR_AQUATOID_MEDIC: \"Medic Aquatoid\"\n  STR_AQUATOID_TECHNICIAN: \"Tehnician Aquatoid\"\n  STR_AQUATOID_SQUAD_LEADER: \"Lider Aquatoid\"\n  STR_AQUATOID_SOLDIER: \"Soldat Aquatoid\"\n  STR_GILLMAN_COMMANDER: \"Comandant Gill Man\"\n  STR_GILLMAN_TECHNICIAN: \"Tehnician Gill Man\"\n  STR_GILLMAN_SQUAD_LEADER: \"Lider Gill Man\"\n  STR_GILLMAN_SOLDIER: \"Soldat Gill Man\"\n  STR_LOBSTERMAN_COMMANDER: \"Comandant Lobster Man\"\n  STR_LOBSTERMAN_NAVIGATOR: \"Pilot Lobster Man\"\n  STR_LOBSTERMAN_TECHNICIAN: \"Tehnician Lobster Man\"\n  STR_LOBSTERMAN_SQUAD_LEADER: \"Lider Lobster Man\"\n  STR_LOBSTERMAN_SOLDIER: \"Soldat Lobster Man\"\n  STR_TASOTH_SQUAD_LEADER: \"Lider Tasoth\"\n  STR_TASOTH_SOLDIER: \"Soldat Tasoth\"\n  STR_CALCINITE_TERRORIST: \"Terorist Calcinite\"\n  STR_DEEP_ONE_TERRORIST: \"Terorist Deep One\"\n  STR_BIODRONE_TERRORIST: \"Terorist Bio-drone\"\n  STR_TENTACULAT_TERRORIST: \"Terorist Tentaculat\"\n  STR_TRISCENE_TERRORIST: \"Terorist Triscene\"\n  STR_HALLUCINOID_TERRORIST: \"Terorist Hallucinoid\"\n  STR_XARQUID_TERRORIST: \"Terorist Xarquid\"\n  STR_ION_BEAM_ACCELERATORS: \"Acceleratoare Undă Ionică\"\n  STR_MAGNETIC_NAVIGATION: \"Navigație Magnetică\"\n  STR_ALIEN_SUB_CONSTRUCTION: \"Construcție OSN\"\n  STR_ALIEN_CRYOGENICS: \"Criogenie Extraterestră\"\n  STR_ALIEN_CLONING: \"Clonare Extraterestră\"\n  STR_ALIEN_LEARNING_ARRAYS: \"Matrice de Învățare Extraterestră\"\n  STR_ALIEN_IMPLANTER: \"Implantări Extraterestre\"\n  STR_EXAMINATION_ROOM: \"Cameră Examinări\"\n  STR_AQUA_PLASTICS: \"Plastice Extraterestre\"\n  STR_ALIEN_REANIMATION_ZONE: \"Reanimare Extraterestră\"\n  STR_PLASTIC_AQUA_ARMOR: \"Armură Acva-Plastică\"\n  STR_ION_ARMOR: \"Armură Ionică\"\n  STR_MAGNETIC_ION_ARMOR: \"Armură Magneto-Ionică\"\n  STR_HWP_AQUA_JET_MISSILES: \"Torpile Acva-Jet\"\n  STR_HWP_DISPLACER_PWT: \"Torpilă U.P.\"\n  STR_GAUSS_TECH: \"Tehnologie Gauss\"\n  STR_NEW_FIGHTER_FLYING_SUB: \"Navă de Luptă Nouă\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Transportor de Luptă Nou\"\n  STR_THE_LATEST_FLYING_SUB: \"Nava Supremă\"\n  STR_ARMOR_PIERCING: \"PERCUTANT\"\n  STR_COELACANTH_GAS_CANNON: \"Coelacanth/Artilerie\"\n  STR_COELACANTH_AQUA_JET: \"Coelacanth/Acva-Jet\"\n  STR_COELACANTH_GAUSS: \"Coelacanth/Gauss\"\n  STR_DISPLACER_SONIC: \"Displacer/Sonic\"\n  STR_DISPLACER_PWT: \"Displacer/T.U.P.\"\n  STR_AJAX_LAUNCHER: \"Lansator Ajax\"\n  STR_DUP_HEAD_LAUNCHER: \"Lansator A.U.S.\"\n  STR_CRAFT_GAS_CANNON: \"Artilerie Navă\"\n  STR_PWT_CANNON: \"Artilerie T.U.P.\"\n  STR_GAUSS_CANNON: \"Artilerie Gauss\"\n  STR_GAUSS_CANNON_AMMO: \"Muniție Artilerie Gauss\"\n  STR_SONIC_OSCILLATOR: \"Oscilator Sonic\"\n  STR_AJAX_TORPEDOES: \"Torpile Ajax\"\n  STR_DUP_HEAD_TORPEDOES: \"Torpile A.U.S.\"\n  STR_CRAFT_GAS_CANNON_ROUNDS_X50: \"Salve Artilerie (x50)\"\n  STR_SONIC_WAVE: \"Undă Sonică\"\n  STR_PULSE_WAVE_TORPEDOES: \"Muniție T.U.P.\"\n  STR_SOLDIER: \"Scafandrier\"\n  STR_SCIENTIST: \"Cercetător\"\n  STR_ENGINEER: \"Tehnician\"\n  STR_NORTH_ATLANTIC: \"Atlanticul de Nord\"\n  STR_SOUTH_ATLANTIC: \"Atlanticul de Sud\"\n  STR_NORTH_PACIFIC: \"Pacificul de Nord\"\n  STR_SOUTH_PACIFIC: \"Pacificul de Sud\"\n  STR_MEDITERRANEAN: \"Mediterana\"\n  STR_SOUTH_CHINA_SEA: \"Marea Chinei de Sud\"\n  STR_INDIAN_OCEAN: \"Oceanul Indian\"\n  STR_THE_EAST_SEA: \"Marea Japoniei\"\n  STR_NORTH_SEA: \"Marea Nordului\"\n  STR_CARRIBEAN: \"Caraibe\"\n  STR_ANTARCTIC: \"Antarctica\"\n  STR_ARCTIC: \"Arctica\"\n  STR_EURASIA: \"Eurasia\"\n  STR_NORTH_AMERICA: \"America de Nord\"\n  STR_AFRICA: \"Africa\"\n  STR_MAXIMUM_SPEED: \"Viteză Maximă\"\n  STR_TRANSMISSION_RESOLVER_UC: \"DECODOR TRANSMISIUNI S-P\"\n  STR_TRITON: \"TRITON\"\n  STR_HAMMERHEAD: \"HAMMERHEAD\"\n  STR_LEVIATHAN: \"LEVIATHAN\"\n  STR_BARRACUDA: \"BARRACUDA\"\n  STR_MANTA: \"MANTA\"\n  STR_UFO: \"USO\"\n  STR_AJAX: \"AJAX\"\n  STR_DUP_HEAD: \"A.U.S.\"\n  STR_CRAFT_GAS_CANNON_UC: \"ARTILERIE NAVĂ\"\n  STR_PWT_CANNON_UC: \"ARTILERIE T.U.P.\"\n  STR_GAUSS_CANNON_UC: \"ARTILERIE GAUSS\"\n  STR_SONIC_OSCILLATOR_UC: \"OSCILATOR SONIC\"\n  STR_DAMAGE_CAPACITY: \"Rezistență Avarii\"\n  STR_WEAPON_POWER: \"Putere\"\n  STR_WEAPON_RANGE: \"Rază Acțiune\"\n  STR_AIR_LOCK: \"Ecluză Acces\"\n  STR_LABORATORY: \"Laborator\"\n  STR_WORKSHOP: \"Atelier\"\n  STR_STANDARD_SONAR: \"Sonar Standard\"\n  STR_WIDE_ARRAY_SONAR: \"Sonar cu Gamă Largă\"\n  STR_TORPEDO_DEFENSES: \"Defensivă Torpile\"\n  STR_GENERAL_STORES: \"Depozite Generale\"\n  STR_ALIEN_CONTAINMENT: \"Carantină Extratereștrii\"\n  STR_GAUSS_DEFENSES: \"Defensivă Gauss\"\n  STR_SONIC_DEFENSES: \"Defensivă Sonică\"\n  STR_PWT_DEFENSES: \"Defensivă P.W.T.\"\n  STR_BOMBARDMENT_SHIELD: \"Scut Bombardament\"\n  STR_MC_GENERATOR: \"Generator C.M.\"\n  STR_MC_LAB: \"Laborator C.M.\"\n  STR_TRANSMISSION_RESOLVER: \"Decodor Transmisiuni S-P\"\n  STR_SUB_PEN: \"Hangar\"\n  STR_USA: \"SUA\"\n  STR_ALASKA: \"ALASKA\"\n  STR_EU_SYNDICATE: \"SINDICATUL EUROPEAN\"\n  STR_ARABIAN_BLOC: \"BLOCUL ARAB\"\n  STR_EGYPTIAN_CARTEL: \"CARTELUL EGIPTEAN\"\n  STR_AFRICA_CORP: \"CORPORAȚIA AFRICANĂ\"\n  STR_BRAZILIAN_UNION: \"UNIUNEA BRAZILIANĂ\"\n  STR_NEW_MEXICO: \"NEW MEXICO\"\n  STR_ASIAN_COALITION: \"COALIȚIA ASIATICĂ\"\n  STR_SCANDINAVIA: \"SCANDINAVIA\"\n  STR_NEO_JAPAN: \"NEO-JAPONIA\"\n  STR_FREE_CHINA: \"CHINA LIBERĂ\"\n  STR_AUSTRALASIA: \"AUSTRALASIA\"\n  STR_FED_KOREA: \"FEDERAȚIA COREEANĂ\"\n  STR_EURASIA_UC: \"EURASIA\"\n  STR_ICELANDIC_UNION: \"UNIUNEA ISLANDEZĂ\"\n  STR_TANK: \"Sistem Submersibil Armat\"\n  STR_CIVILIAN: \"Civil\"\n  STR_JAN: \"Ian\"\n  STR_FEB: \"Feb\"\n  STR_MAR: \"Mar\"\n  STR_APR: \"Apr\"\n  STR_MAY: \"Mai\"\n  STR_JUN: \"Iun\"\n  STR_JUL: \"Iul\"\n  STR_AUG: \"Aug\"\n  STR_SEP: \"Sep\"\n  STR_OCT: \"Oct\"\n  STR_NOV: \"Noi\"\n  STR_DEC: \"Dec\"\n  STR_INTERNATIONAL_RELATIONS: \"Relații Internaționale\"\n  STR_COUNTRY: \"Țară\"\n  STR_FUNDING: \"Finanțare\"\n  STR_CHANGE: \"Variație\"\n  STR_WEAPON_SYSTEMS: \"ARMAMENT\"\n  STR_HWPS: \"SSAuri\"\n  STR_DAMAGE_UC_: \"AVARII>{ALT}{0}\"\n  STR_AIR_LOCK_UFOPEDIA: \"Ecluza de acces permite transferul echipamentului și personalului în și din baza subacvatică. Este întotdeauna prima structură construită în noua locație. Zona ecluzei este vulnerabilă intruziunii posibilelor forțe ostile.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Fiecare ansamblu de locuințe furnizează spațiu pentru maxim 50 de oameni. Este prevăzut cu facilități de bază și funcționale.\"\n  STR_LABORATORY_UFOPEDIA: \"Într-un laborator pot lucra până la 50 de cercetători. Laboratoarele sunt echipate cu cea mai nouă tehnologie pentru cercetarea materialelor, biochimiei și armelor. Cercetătorii X-Com au acces privilegiat la cele mai bune laboratoare din lume, atât civile cât și militare.\"\n  STR_WORKSHOP_UFOPEDIA: \"Atelierul conține toate echipamentele necesare producerii obiectelor bazate pe schițele venite de la laboratoare. Până la 50 de tehnicieni pot să lucreze în atelier, deși obiectele produse o să ocupe de asemenea spațiu.\"\n  STR_STANDARD_SONAR_UFOPEDIA: \"Un sistem standard de detecție cu o rază de acțiune efectivă de 450 de kilometri la majoritatea adâncimilor și legat la rețeaua de sateliți geostaționari pentru analiza la suprafață. Fiecare sistem are o șansă de 10% la fiecare 30 de minute de a detecta o navă submersibilă sau aeriană.\"\n  STR_WIDE_ARRAY_SONAR_UFOPEDIA: \"Un sistem extins de detecție cu o rază de acțiune efectivă de peste 700 de kilometri la orice adâncime și legat la rețeaua de sateliți geostaționari pentru analiza la suprafață. Fiecare sistem are o șansă de 20% la fiecare 30 de minute de a detecta o navă submersibilă sau aeriană.\"\n  STR_TORPEDO_DEFENSES_UFOPEDIA: \"Furnizează protecție împotriva incursiunilor navelor forțelor ostile care încearcă să andocheze la bază.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"Toate echipamentele, armele, munițiile, materialele recuperate și SSAurile sunt păstrate în depozite, inclusiv echipamentele atribuite navelor din hangare.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"Extratereștrii vii necesită un habitat special pentru a fi menținuți în viață și a li se neutraliza potențialul combativ. Structura poate păstra până la 10 forme de viață extraterestre în unități autonome.\"\n  STR_GAUSS_DEFENSES_UFOPEDIA: \"Furnizează cea mai nouă și eficientă protecție împotriva incursiunilor navelor inamice.\"\n  STR_SONIC_DEFENSES_UFOPEDIA: \"Furnizează o protecție puternică și eficientă împotriva incursiunilor navelor inamice.\"\n  STR_PWT_DEFENSES_UFOPEDIA: \"Furnizează cea mai eficientă defensivă împotriva atacurilor extraterestre. Torpilele au focoase super dense ce pot penetra toate blindajele cunoscute. Undele magnetice produse dezactivează sistemele electronice defensive.\"\n  STR_BOMBARDMENT_SHIELD_UFOPEDIA: \"Scutul protejează baza de navele extraterestre care încearcă să andocheze la bază și emite un câmp rezonant ce le respinge suficient de mult timp pentru ca sistemele defensive să mai tragă o dată. Practic, acest sistem dublează efectul oricărui sistem defensiv din bază.\"\n  STR_MC_GENERATOR_UFOPEDIA: \"Ținând cont că submarinele extraterestre folosesc Controlul Molecular pentru a detecta prezența vietăților, folosirea unui emițător C.M. negativ va ecrana baza cu un scut impenetrabil, derutând extratereștrii și mascându-ne prezența.\"\n  STR_MC_LAB_UFOPEDIA: \"Poate implanta și antrena până la zece scafandrieri în același timp. Implanturile sunt instalate chirurgical în craniu. Antrenamentul prelungit le permite oamenilor utilizarea acestora. Abilitățile sunt folosite împreună cu un dispozitiv de Control Molecular ce poate fi utilizat în luptă.\"\n  STR_TRANSMISSION_RESOLVER_UFOPEDIA: \"Comunicațiile extraterestre utilizează rețeaua implanturilor de Control Molecular construită de aceștia. Această structură interceptează trasmisiunile OSN, decodează informația și arată tipul OSNului, specia extraterestră și natura activității desfășurate.\"\n  STR_SUB_PEN_UFOPEDIA: \"Fiecare hangar poate găzdui o singură navă. Conține echipamente pentru întreținerea, alimentarea și repararea navelor X-Com. Fiecare navă alocată unei baze trebuie să aibă un hangar liber atribuit ce nu poate fi folosit de altă navă, chiar dacă nava atribuită se află într-o misiune.\"\n  STR_DART_PISTOL_UFOPEDIA: \"Pistolul X-Com este o armă mică și precisă, având un încărcător cu 12 bolțuri goale pe dinăuntru propulsate de gazul dintr-un rezervor alăturat.\"\n  STR_JET_HARPOON_UFOPEDIA: \"Această pușcă subacvatică este precisă și puternică, trăgând cu harpoane de oțel goale pe dinăuntru, dispuse în seturi de câte 10. Fiecare harpon are propriul rezervor de gaz.\"\n  STR_GAS_CANNON_UFOPEDIA: \"Categoria grea a armelor ce folosesc propulsia cu gaz, ce folosește bolțuri solide sau cu vârful exploziv ori fosforos. Arma favorită a scafandrierilor experimentați.\"\n  STR_HYDRO_JET_CANNON_UFOPEDIA: \"O armă grea de infanterie, artileria folosește mini-torpile propulsate de magneziu. Deși puternică, este o armă stângace și greoaie, potrivită folosirii exclusive în mediul acvatic.\"\n  STR_TORPEDO_LAUNCHER_UFOPEDIA: \"Cu adevărat de categorie grea, lansatorul folosește trei tipuri de torpile, fiecare cu propulsie proprie. O armă devastatoare, având ca singur neajuns încărcarea manuală. Tipurile de muniție disponibile sunt cele cu explozibil mic sau mare și cu vârf fosoros, toate destinate folosirii exclusive sub apă.\"\n  STR_GAUSS_PISTOL_UFOPEDIA: \"Pistolul Gauss folosește tehnologia pariculelor accelerate, o nouă evoluție a armelor moderne. Este rapid, precis și funcționează atât la suprafață cât și sub apă. Tehnologia Gauss este o rafinare a celei cu Plasmă cunoscută în războiul anterior.\"\n  STR_GAUSS_PISTOL_CLIP_UFOPEDIA: \"Pistolul Gauss folosește tehnologia pariculelor accelerate, o nouă evoluție a armelor moderne. Este rapid, precis și funcționează atât la suprafață cât și sub apă. Tehnologia Gauss este o rafinare a celei cu Plasmă cunoscută în războiul anterior.\"\n  STR_GAUSS_RIFLE_UFOPEDIA: \"Un pas înainte față de pistol, pușca Gauss este cu adevărat puternică având accelerator de particule dublu. Înlocuind sistemul cu Plasmă alimentat de Elerium cu un micro-accelerator de particule ce generează un flux de anti-protoni.\"\n  STR_GAUSS_RIFLE_CLIP_UFOPEDIA: \"Un pas înainte față de pistol, pușca Gauss este cu adevărat puternică având accelerator de particule dublu. Înlocuind sistemul cu Plasmă alimentat de Elerium cu un micro-accelerator de particule ce generează un flux de anti-protoni.\"\n  STR_HEAVY_GAUSS_UFOPEDIA: \"Deși voluminoasă artileria Gauss este extrem de eficace. Folosește trei acceleratoare de particule și e practic de neoprit. Fluxul de anti-protoni este constrâns într-un proiectil de arseniură de galiu ce implodează la impact eliberând anti-materia.\"\n  STR_HEAVY_GAUSS_CLIP_UFOPEDIA: \"Deși voluminoasă artileria Gauss este extrem de eficace. Folosește trei acceleratoare de particule și e practic de neoprit. Fluxul de anti-protoni este constrâns într-un proiectil de arseniură de galiu ce implodează la impact eliberând anti-materia.\"\n  STR_MAGNA_BLAST_GRENADE_UFOPEDIA: \"Această grenadă standard prezintă un cronometru sofisticat, pentru un control de precizie.\"\n  STR_DYE_GRENADE_UFOPEDIA: \"Grenadele cu vopsea au un rol dublu, fiind folositoare pentru asigurarea acoperirii în zonele expuse. Funcționând atât sub apă cât și la sol, vopseaua este evacuată sub forma unui nor de particule, acesta producând sub apă un efect asemenea jetului de cerneală al caracatițelor și un nor dens când este la sol.\"\n  STR_PARTICLE_DISTURBANCE_GRENADE_UFOPEDIA: \"O grenadă de proximitate poate fi aruncată precum o grenadă normală dar odată activată este declanșată de mișcările din apropiere. Pentru a folosi corect acest echipament sunt necesare abilități bune și antrenament.\"\n  STR_MAGNA_PACK_EXPLOSIVE_UFOPEDIA: \"Acest explozibil ar trebui folosit numai pentru demolări. Totuși experiențele anterioare au arătat că acești explozibili puternici sunt ideali pentru stârpirea extratereștrilor. Raza de acțiune este mare așa că scafandrierii trebuie să stea la o distanță sigură.\"\n  STR_PARTICLE_DISTURBANCE_SENSOR_UFOPEDIA: \"Acest dispozitiv sofisticat folosește o varietate de detectori și algoritmi avansați pentru a identifica unitățile aflate în apă. Apasă pe reprezentarea detectorului de perturbații de pe afișajul tactic. Alege 'Folosire Detector' din meniu. Afișajul detectorului arată o săgeată în mijloc - direcția în care se uită scafandrierul (nordul este în sus). Cercurile pulsatorii arată unitățile care s-au mișcat recent. Unitățile mari sau care se mișcă repede vor produce cercuri mai mari. Unitățile statice nu vor fi detectate.\"\n  STR_MEDI_KIT_UFOPEDIA: \"Pentru a folosi trusa trebuie să stai cu fața la scafandrierul care are nevoie de tratament. Apasă pe reprezentarea trusei și alege 'Folosire Trusă' din meniu.{NEWLINE}TRATAMENT> Zonele cu roșu sunt rănile grave. Apasă pe o zonă rănită, apoi pe butonul 'Vindecare'. O rană gravă va fi vindecată și o parte din sănătate refăcută.{NEWLINE}STIMULENT> Va restaura energia și resuscita scafandrierii inconștienți (paralizați). Pentru a resuscita un soldat incoștient trebuie să stai deasupra corpului acestuia.{NEWLINE}CALMANT> Va restaura moralul soldaților răniți până la un nivel echivalent cu sănătatea pierdută.\"\n  STR_MC_DISRUPTOR_UFOPEDIA: \"Tehnologia C.M. supremă. Poate fi folosit numai de către scafandrierii cu abilități C.M. În luptă, apasă pe Perturbator, alege tipul atacului și selectează o țintă. Sunt două tipuri de atac perturbator:{NEWLINE}BRUIAJ IMPLANT> Dacă atacul are succes va reduce moralul țintei, putând induce panica.{NEWLINE}CONTROL IMPLANT> Dacă are succes vei avea imediat control asupra unității inamice ca și cum ți-ar fi aparținut. Este mai dificil să ai succes cu acest tip de atac.\"\n  STR_THERMAL_TAZER_UFOPEDIA: \"Acest dispozitiv poate fi folosit numai în lupta corp la corp, dar va paraliza un organism viu fără a îl omorî, înghețând creatura.\"\n  STR_VIBRO_BLADE_UFOPEDIA: \"O lamă de titaniu lungă și ascuțită ce se rotește la peste 6000 rpm, putând străpunge chiar și cele mai puternice armuri. Sursa de energie este o invenție extraterestră, încercările noastre de a le construi fiind sortite eșecului, lamele rotindu-se prea încet ori dezintegrându-se sub presiunie.\"\n  STR_THERMIC_LANCE_UFOPEDIA: \"Lancea Termică este o evoluție naturală a tehnologiei Vibro-Lamei, se rotește la viteză mare iar o sursă de energie cu Zrbite o supraîncălzește pentru a putea străpunge armurile precum un cuțit cald străpunge untul.\"\n  STR_HEAVY_THERMIC_LANCE_UFOPEDIA: \"O versiune și mai puternică decât Lancea Termică. Două surse de căldură și o viteză de rotație mai mare duce la concluzia că Lancea Termică Grea este practic de neoprit, indiferent de materialul armurii.\"\n  STR_SONIC_CANNON_UFOPEDIA: \"Cea mai puternică armă cu tehnologie sonică. Dispune de un oscilator audio de gamă înaltă și o cameră de reverberație mai mare decât pușca. Folosește un sistem de detonare cu puls ce modifică unda ultrasonică pentru a produce un șoc sonic mai eficient.\"\n  STR_CANNON_POWER_CLIP_UFOPEDIA: \"Acest dispozitiv compact este folosit drept muniție pentru Artileria Sonică. Conține o cantitate mică de Zrbite.\"\n  STR_SONIC_BLASTA_RIFLE_UFOPEDIA: \"Un dispozitiv sonic și mai puternic. Nici măcar oțel-carbonul superior nu este imun la această armă. Emițătorul de unde extrem de compact este ajutat de un amplificator superconductor pentru a mări puterea armei.\"\n  STR_BLASTA_POWER_CLIP_UFOPEDIA: \"Acest mic dispozitiv este folosit drept sursă de energie pentru Pușca Sonică, o armă extraterestră puternică, și conține o cantitate mică de Zrbite.\"\n  STR_SONIC_PISTOL_UFOPEDIA: \"O armă extraterestră bazată pe unde audio ultrasonice ce pot lichefia oasele în câteva secunde. Aceste unde operează într-o gamă dincolo de limitele auzului uman.\"\n  STR_PISTOL_POWER_CLIP_UFOPEDIA: \"Sursa de energie pentru Pistolul Sonic extraterestru. Conține Zrbite - sursa de energie folosită de către extratereștri.\"\n  STR_DISRUPTOR_PULSE_LAUNCHER_UFOPEDIA: \"Acesta este un lansator care proiectează 'Pulsuri Perturbatoare' teleghidate. Când se trage cu arma, aceasta va genera 'puncte rută' pe care Pulsul le va traversa. După ce s-au trasat suficiente puncte se apasă pe butonul de lansare.\"\n  STR_DISRUPTOR_AMMO_UFOPEDIA: \"Acest dispozitiv conține Pulsurile Perturbatoare și este dotat cu un sistem de ghidare la bord. Este proiectată de un Lansator de Puls Perturbator.\"\n  STR_THERMAL_SHOK_LAUNCHER_UFOPEDIA: \"Un mic lansator care proiectează bombe cu șoc termal. Foarte folositor pentru capturarea extratereștrilor vii.\"\n  STR_THERMAL_SHOK_BOMB_UFOPEDIA: \"Bomba cu șoc termal este folosită pentru capturarea în viață a specimenelor umane, dar poate fi de asemenea utilizată împotriva majorității speciilor extraterestre. Este proiectată la țintă cu ajutorul unui Lansator de Șoc Termal.\"\n  STR_SONIC_PULSER_UFOPEDIA: \"Acest dispozitiv funcționează precum o grenadă normală - numai că este de multe ori mai puternică. Folosește un singur puls sonic ce este emis simultan în toate direcțiile.\"\n  STR_MC_READER_UFOPEDIA: \"În corpul extratereștrilor am găsit mici implanturi. Acestea sunt proiectate de către Aquatoizi pentru a permite furnizarea informațiilor de pe câmpul de luptă, chiar și la distanțe mari. Sonda C.M. este un dispozitiv extraterestru de comunicare care este folosit pentru a extrage informații direct din implanturile C.M. Scafandrierii X-Com pot folosi acest dispozitiv în luptă pentru a afișa caracteristicile extraterestrului. Apasă pe reprezentarea sondei și alege opțiunea 'Folosire Sondă C.M.' apoi selectează un extraterestru.\"\n  STR_SURVEY_SHIP: \"Navă Cercetare\"\n  STR_ESCORT: \"Navă Escortă\"\n  STR_CRUISER: \"Navă Crucișător\"\n  STR_HEAVY_CRUISER: \"Navă Crucișător Greu\"\n  STR_HUNTER: \"Navă Vânătoare\"\n  STR_BATTLESHIP: \"Navă Război\"\n  STR_DREADNOUGHT: \"Navă Cuirasat\"\n  STR_FLEET_SUPPLY_CRUISER: \"Navă Aprovizionare\"\n  MAP_SEABED: \"Fundul oceanului\"\n  MAP_PIPES: \"Centru de Cercetare\"\n  MAP_PLANE: \"Avion Prăbușit\"\n  MAP_ATLAN: \"Atlantida\"\n  MAP_MU: \"Templu Mayaș\"\n  MAP_GAL: \"Corabie Scufundată\"\n  MAP_MSUNK: \"Navă de Linie Scufundată\"\n  MAP_VOLC: \"Regiune Vulcanică\"\n  MAP_CORAL: \"Recif de Corali\"\n  MAP_PORT: \"Port\"\n  MAP_ISLAND: \"Insulă\"\n  MAP_CARGO: \"Cargobot\"\n  MAP_LINERT: \"Navă de Linie P1\"\n  MAP_LINERB: \"Navă de Linie P2\"\n  MAP_ALART: \"Artefact P1\"\n  MAP_GRUNGE: \"Artefact P2\"\n  MAP_ENTRY: \"Colonie P1\"\n  MAP_A_BASE: \"Colonie P2\"\n  MAP_ALSHIP: \"T'leth P1\"\n  MAP_LEVEL: \"T'leth P2\"\n  MAP_CRYPT: \"T'leth P3\"\n  MAP_XBASES: \"Bază X-Com\"\n  STR_MIXED_CREW: \"Echipaj Amestecat\"\n  STR_MIXED_CREW_2: \"Echipaj Amestecat 2\"\n  STR_RATING: \"EVALUARE> {0}\"\n  STR_RATING_TERRIBLE: \"GROAZNIC!\"\n  STR_RATING_POOR: \"SLAB!\"\n  STR_RATING_OK: \"OK\"\n  STR_RATING_GOOD: \"BUN!\"\n  STR_RATING_EXCELLENT: \"EXCELENT!\"\n  STR_SCORE: \"PUNCTAJ\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"RAPORT LUNAR PROIECT X-COM\"\n  STR_MONTH: \"Lună> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"Comitetul organizațiilor finanțatoare este în general mulțumit de progresul realizat.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"Comitetul organizațiilor finanțatoare este foarte mulțumit de progresul realizat. Continuă tot așa!\"\n  STR_COUNCIL_IS_DISSATISFIED: \"Comitetul organizațiilor finanțatoare este nemulțumit de performanța ta. Trebuie să îți mărești eficacitatea în lupta cu amenințarea extraterestră sau riști încheierea proiectului.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"Nu ai reușit să faci față amenințării extraterestre iar comitetul organizațiilor finanțatoare a decis cu regret închiderea proiectului. Fiecare organizație va trata problema așa cum crede de cuviință. Nu putem decât să sperăm că vom ajunge la un oarecare nivel de împăcare cu aceste forțe străvechi și că populația va ajunge la o întelegere cu vizitatorii extratereștri.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} este în mod special satisfăcută de competențele de care ai dat dovadă în lupta cu amenințarea locală și a decis să își mărească contribuția financiară.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} sunt în mod special fericite de progresul făcut în lupta împotriva incursiunilor locale ale extratereștrilor și au decis să își mărească contribuția financiară.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} și {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} este nemulțumită de abilitățile de care ai dat dovadă în lupta cu extratereștrii din apele ei și a decis să își reducă contribuția financiară.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} sunt nemulțumite de capacitatea ta de a face față activităților extratereștrilor din apele lor și au decis să își reducă contribuțiile financiare.\"\n  STR_KNOTS: \"{0} noduri\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} a semnat un acord de cooperare cu forțele extraterestre și a oprit finanțarea proiectului.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} au semnat un acord de cooperare cu forțele extraterestre și au oprit finanțarea proiectului.\"\n  STR_MONTHLY_RATING: \"Evaluare Lunară> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Variație Finanțe> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"Comitetul nu este mulțumit de situația ta financiară. Trebuie să îți micșorezi datoriile la o valoare de până în 1 milion $ sau proiectul va fi închis.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"TRANSMISIUNI SUB-PARTICULĂ DECODATE\"\n  STR_CRAFT_TYPE: \"TIP NAVĂ\"\n  STR_RACE: \"RASĂ\"\n  STR_MISSION: \"MISIUNE\"\n  STR_ZONE: \"ZONĂ\"\n  STR_ALLOCATE_RESEARCH: \"Alocare Cercetare\"\n  STR_ALLOCATE_MANUFACTURE: \"Alocare Producție\"\n  STR_AZORES: \"Azore\"\n  STR_REYKJAVIK: \"Reykjavik\"\n  STR_BERMUDA: \"Bermude\"\n  STR_NEW_YORK: \"New York\"\n  STR_BOSTON: \"Boston\"\n  STR_FORT_SEVERN: \"Fort Severn\"\n  STR_DAKAR: \"Dakar\"\n  STR_RECIFE: \"Recife\"\n  STR_ACCRA: \"Accra\"\n  STR_ASCENSION_ISLAND: \"Insula Ascension\"\n  STR_TRINIDADE_ISLAND: \"Insula Trinidad\"\n  STR_FALKLAND_ISLAND: \"Insulele Falkland\"\n  STR_CANARY_ISLANDS: \"Insulele Canare\"\n  STR_ANCHORAGE: \"Anchorage\"\n  STR_ST_LAWRENCE_ISLAND: \"Insula Sf. Laurențiu\"\n  STR_SAN_FRANCISCO: \"San Francisco\"\n  STR_MIDWAY_ISLAND: \"Insula Midway\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_TASMANIA: \"Tasmania\"\n  STR_HAWAII: \"Hawaii\"\n  STR_FIJI: \"Fiji\"\n  STR_TONGA: \"Tonga\"\n  STR_EASTER_ISLAND: \"Insula Paștelui\"\n  STR_GALAPAGOS_ISLAND: \"Insulele Galapagos\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_SOLOMON_ISLAND: \"Insula Solomon\"\n  STR_CRETE: \"Creta\"\n  STR_LISBON: \"Lisabona\"\n  STR_PORT_SAID: \"Port Said\"\n  STR_MARSEILLES: \"Marsilia\"\n  STR_TRIPOLI: \"Tripoli\"\n  STR_MANILA: \"Manila\"\n  STR_HONG_KONG: \"Hong Kong\"\n  STR_SINGAPORE: \"Singapore\"\n  STR_BANGKOK: \"Bangkok\"\n  STR_DARWIN: \"Darwin\"\n  STR_BOMBAY: \"Bombay\"\n  STR_SAYCHELLES_ISLAND: \"Insulele Seychelles\"\n  STR_MALDIVE_ISLAND: \"Insula Maldive\"\n  STR_SRI_LANKA: \"Sri Lanka\"\n  STR_MAURITIUS: \"Mauritius\"\n  STR_TOKYO: \"Tokio\"\n  STR_SHANGHAI: \"Shanghai\"\n  STR_VLADIVOSTOK: \"Vladivostok\"\n  STR_LONDON: \"Londra\"\n  STR_FAEROE_ISLAND: \"Insulele Feroe\"\n  STR_ABERDEEN: \"Aberdeen\"\n  STR_OSLO: \"Oslo\"\n  STR_JAMAICA: \"Jamaica\"\n  STR_PANAMA: \"Panama\"\n  STR_MIAMI: \"Miami\"\n  STR_PSI_TRAINING: \"Antrenament C.M.\"\n  STR_PSIONIC_TRAINING: \"ANTRENAMENT CONTROL MOLECULAR\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Spațiu liber Laborator C.M.> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"Rezistență{NEWLINE}C.M.\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"Abilități C.M.{NEWLINE}/Îmbunătățire\"\n  STR_IN_TRAINING: \"Sub{NEWLINE}Antrenament?\"\n  STR_TARGETTED_BY: \"ȚINTIT DE CĂTRE:\"\n  STR_WEAPONS_CREW_HWPS: \"ARME/ECHIPAJ/{NEWLINE}SSAuri\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"a terminat combustibilul{NEWLINE}și revine la bază\"\n  STR_SOLDIER_LIST: \"Listă Scafandrieri\"\n  STR_RANK_: \"RANG> {ALT}{0}\"\n  STR_MISSIONS: \"MISIUNI> {ALT}{0}\"\n  STR_KILLS: \"VICTIME> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"VINDECARE> {ALT}{0}\"\n  STR_TIME_UNITS: \"UNITĂȚI TIMP\"\n  STR_STAMINA: \"ENERGIE\"\n  STR_HEALTH: \"SĂNĂTATE\"\n  STR_BRAVERY: \"VITEJIE\"\n  STR_REACTIONS: \"REACȚII\"\n  STR_FIRING_ACCURACY: \"PRECIZIE FOC\"\n  STR_THROWING_ACCURACY: \"PRECIZIE ARUNCARE\"\n  STR_STRENGTH: \"FORȚĂ\"\n  STR_PSIONIC_STRENGTH: \"REZISTENȚĂ C.M.\"\n  STR_PSIONIC_SKILL: \"ABILITĂȚI C.M.\"\n  STR_NEW_RANK: \"RANG NOU\"\n  STR_PROMOTIONS: \"Promovări\"\n  STR_SOLDIERS_UC: \"SCAFANDRIERI\"\n  STR_COELACANTH_GAS_CANNON_UFOPEDIA: \"SSAurile automate au manevrabilitate mare și înveliș rezistent. Furnizează sprijin greu trupelor la orice adâncime. Dacă există muniție suficientă se rearmează automat.\"\n  STR_COELACANTH_AQUA_JET_UFOPEDIA: \"Acest SSA este înarmat cu Torpile Acva-Jet, funcționând numai sub apă. Necesită un stoc bine aprovizionat de Torpile Acva-Jet.\"\n  STR_COELACANTH_GAUSS_UFOPEDIA: \"Tehnologia Gauss asigură un sistem puternic pentru SSAuri. Oferă o mai mare putere de foc în comparație cu modelele precedente, folosind tehnologie proprie X-Com.\"\n  STR_DISPLACER_SONIC_UFOPEDIA: \"Tehnologia extraterestră a rafinat SSAurile. Abilitatea de a folosi dislocarea ionică înseamnă că SSAurile nu mai sunt limitate la deplasarea pe sol sau sub apă. Armele sonice sunt de un real avantaj în luptă.\"\n  STR_DISPLACER_PWT_UFOPEDIA: \"Acest SSA folosește arme T.U.P. pentru uz exclusiv acvatic. Pentru a le menține echipate trebuiesc produse Torpile U.P. suficiente. Când se trage cu arma, aceasta va genera 'puncte rută' după care se apasă pe butonul de lansare.\"\n  STR_ALIEN_PROBE_MISSION: \"Sondări Extraterestre\"\n  STR_ALIEN_INTERDICTION: \"Interdicții Extraterestre\"\n  STR_ALIEN_RESOURCE_RAID: \"Raiduri Extraterestre pentru Resurse\"\n  STR_ALIEN_INFILTRATION: \"Infiltrări Extraterestre\"\n  STR_ALIEN_BASE: \"Extindere Colonie Extraterestră\"\n  STR_ALIEN_SURFACE_ATTACK: \"Atacuri Extraterestre la Suprafață\"\n  STR_ALIEN_RETALIATION: \"Atac asupra Bazei Plutitoare\"\n  STR_ALIEN_SUPPLY: \"Aprovizionare Colonie Extraterestră\"\n  STR_ALIEN_PROBE_MISSION_UFOPEDIA: \"Misiunea de sondare a extratereștrilor este folosită pentru a colecta date despre mediu, resurse și rutele navelor și avioanelor dintr-o anumită zonă. Navele folosite în aceste misiuni nu sunt o amenințare foarte mare, dar prezența lor sugerează că activitatea în zonă poate spori în orice moment.\"\n  STR_ALIEN_INTERDICTION_UFOPEDIA: \"Extratereștrii au obiceiul de a controla zonele de care sunt interesați, trimițând nave cu scopul precis de a securiza zona înainte de a declanșa misiunile mai importante. Aterizează special în locurile ce vor fi prădate ulterior pentru a bloca zonele și pregăti calea pentru următorul nivel de activitate.\"\n  STR_ALIEN_RESOURCE_RAID_UFOPEDIA: \"Scufundarea și doborârea navelor sunt elementele cheie ale strategiei extraterestre. Dobândirea materialelor este principala activitate extraterestră și astfel este asociată cu aceste acte de agresiune. Extratereștrii prăduiesc zonele cu activitate geotermală, cele miniere sau antice pentru minerale și metale rare sau alte articole produse de oameni.\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"Aceste misiuni duc la întâlniri oficiale la cel mai înalt nivel între extratereștri și corporații sau guverne. Apogeul acestei activități este caracterizat de mișcări intense de nave în apele organizațiilor vizate. Extratereștrii vor încerca să semneze un pact cu guvernul sau organizația respectivă prin oferirea de tehnologii superioare. Aceste misiuni reprezintă o amenințare majoră pentru X-Com. Dacă o corporație sau un guvern cooperează cu dușmanul atunci aceasta nu va mai finanța proiectul.\"\n  STR_ALIEN_BASE_UFOPEDIA: \"Extratereștrii vor construi colonii submarine secrete în zone izolate. După zborurile de observare inițiale va urma o activitate OSN intensă pe masură ce baza este construită. Aceasta conține laboratoare, centre de clonare, structuri unde au loc experimentele chirurgicale pe oameni și extratereștri. Existența unei colonii extraterestre va genera o activitate intensă chiar și fără apariția OSNurilor. Pentru a localiza o colonie o navă X-Com trebuie să patruleze o zonă timp de câteva ore pentru a avea o șansă de detecție.\"\n  STR_ALIEN_SURFACE_ATTACK_UFOPEDIA: \"Când au nevoie de oameni extratereștrii terorizează un port, atacă o insulă sau prăduiesc o navă. Civilii vor fi în amenințați direct, pentru a îndeplini nevoile de reproducere ale extratereștrilor și experimentelor acestora.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"Dacă interceptoarele X-Com reușesc să doboare multe OSNuri atunci extratereștrii pot recurge la represalii. Acestea pot lua forma unui atac direct împotriva bazelor X-Com. Totuși, extratereștrii trebuie să găsească o bază X-Com pentru a o putea ataca, însă dacă OSNurile sunt îndepărtate atunci acest pericol a trebui să fie redus.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"Odată ce colonia extraterestră este construită, aceasta va fi aprovizionată în mod regulat de către o navă specială. Dacă una din aceste nave este detectată în timp ce aterizează atunci este sigur faptul că în apropiere se află o colonie extraterestră.\"\n  STR_SURVEY_SHIP_UFOPEDIA: \"Această navă minusculă este folosită pentru misiuni de recunoaștere și sondare. În mod normal precede navele mai mari de la începutul unei misiuni extraterestre.\"\n  STR_ESCORT_UFOPEDIA: \"O navă de escortă de dimensiune medie ce nu prezintă o amenințare puternică pe cont propriu. Precede navele mai mari și o intensificare a activităților.\"\n  STR_CRUISER_UFOPEDIA: \"Această navă cu scop general formează grosul flotei extraterestre, folosită în toate tipurile de misiuni extraterestre și un adversar de temut.\"\n  STR_HEAVY_CRUISER_UFOPEDIA: \"Această navă este mai puternică decât Crucișătorul, având arme mai mari și sisteme de propulsie mai bune. Este folosită în misiunile de colectare a resurselor pentru a aduna cantități mari de minerale și echipament.\"\n  STR_HUNTER_UFOPEDIA: \"Această navă prezintă o cameră de examinare în care au loc experimente groaznice pe subiecți umani. Victimele sunt supuse la cele mai oribile torturi, iar creierul este adesea eliminat și păstrat pentru procesare.\"\n  STR_BATTLESHIP_UFOPEDIA: \"Cea mai agresivă navă deținută de extratereștri, echipată cu cele mai noi tehnologii și sisteme, dispune de o gamă largă de arme și fucționează ca bază de operațiuni pentru orice act de agresiune conceput de extratereștri.\"\n  STR_DREADNOUGHT_UFOPEDIA: \"Această navă este un transportor de trupe echipat cu toate tehnologiile extraterestre și având o sarcină utilă mare. Este un adversar rezistent și formidabil.\"\n  STR_FLEET_SUPPLY_CRUISER_UFOPEDIA: \"Această navă este folosită în timpul construcției coloniilor extraterestre sau pentru aprovizionarea coloniilor existente. Transportă mâncare extraterestră, ADN, fetuși și alte componente biologice.\"\n  STR_DISMANTLE: \"Dezafectare\"\n  STR_FACILITY_IN_USE: \"STRUCTURĂ îNTREBUINȚATĂ\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"NU SE POATE DEZAFECTA!{SMALLLINE}Toate structurile trebuie să aibă legături către ecluza de acces.\"\n  STR_TRANSFER_ITEMS_TO: \"Transferă Articole la {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"NU EXISTĂ CARANTINĂ PENTRU TRANSFER!{SMALLLINE}Extratereștrii vii au nevoie de carantină pentru a supraviețui.\"\n  STR_AMOUNT_AT_DESTINATION: \"CANTITATE LA{NEWLINE}DESTINAȚIE\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"Extraterestrul moare pentru că nu există carantină\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"NU EXISTĂ LOCURI LIBERE!{SMALLLINE}Baza destinată nu are locuri libere în locuințe pentru echipajul alocat navei.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"SPAȚIU DEPOZITARE INSUFICIENT!{SMALLLINE}Baza destinație nu are spațiu suficient în depozite pentru echipamentul alocat navei.\"\n  STR_ITEMS_ARRIVING: \"Sosire Articole\"\n  STR_DESTINATION_UC: \"DESTINAȚIE\"\n  STR_DART_PISTOL: \"Pistol Bolțuri\"\n  STR_DART_POD: \"Muniție Bolțuri\"\n  STR_JET_HARPOON: \"Pușcă Harpon\"\n  STR_HARPOON_POD: \"Muniție Harpoane\"\n  STR_GAS_CANNON: \"Artilerie de Mână\"\n  STR_GC_AP_AMMO: \"Muniție AM-P\"\n  STR_GC_HE_AMMO: \"Muniție AM-E\"\n  STR_GC_P_AMMO: \"Muniție AM-F\"\n  STR_HYDRO_JET_CANNON: \"Artilerie Hidro-Jet\"\n  STR_HJC_AP_AMMO: \"Muniție HJ-P\"\n  STR_HJC_HE_AMMO: \"Muniție HJ-E\"\n  STR_HJC_P_AMMO: \"Muniție HJ-F\"\n  STR_TORPEDO_LAUNCHER: \"Lansator Torpile\"\n  STR_SMALL_TORPEDO: \"Torpilă Mică\"\n  STR_LARGE_TORPEDO: \"Torpilă Mare\"\n  STR_PHOSPHOROUS_TORPEDO: \"Torpilă Fosforoasă\"\n  STR_MAGNA_BLAST_GRENADE: \"Grenadă Magna-Blast\"\n  STR_DYE_GRENADE: \"Grenadă Vopsea\"\n  STR_PARTICLE_DISTURBANCE_GRENADE: \"Grenadă Perturbații Particule\"\n  STR_MAGNA_PACK_EXPLOSIVE: \"Explozibil Magna-Pack\"\n  STR_PARTICLE_DISTURBANCE_SENSOR: \"Detector Perturbații Particule\"\n  STR_MEDI_KIT: \"Trusă Medicală\"\n  STR_MC_DISRUPTOR: \"Perturbator C.M.\"\n  STR_THERMAL_TAZER: \"Baston Paralizant Termal\"\n  STR_GAUSS_PISTOL: \"Pistol Gauss\"\n  STR_GAUSS_PISTOL_CLIP: \"Muniție Pistol Gauss\"\n  STR_GAUSS_RIFLE: \"Pușcă Gauss\"\n  STR_GAUSS_RIFLE_CLIP: \"Muniție Pușcă Gauss\"\n  STR_HEAVY_GAUSS: \"Artilerie Gauss\"\n  STR_HEAVY_GAUSS_CLIP: \"Muniție Artilerie Gauss\"\n  STR_SONIC_CANNON: \"Artilerie Sonică\"\n  STR_CANNON_POWER_CLIP: \"Muniție Artilerie Sonică\"\n  STR_SONIC_BLASTA_RIFLE: \"Pușcă Sonică\"\n  STR_BLASTA_POWER_CLIP: \"Muniție Pușcă Sonică\"\n  STR_SONIC_PISTOL: \"Pistol Sonic\"\n  STR_PISTOL_POWER_CLIP: \"Muniție Pistol Sonic\"\n  STR_DISRUPTOR_PULSE_LAUNCHER: \"Lansator Puls Perturbator\"\n  STR_DISRUPTOR_AMMO: \"Muniție Perturbator\"\n  STR_THERMAL_SHOK_LAUNCHER: \"Lansator Șoc Termal\"\n  STR_THERMAL_SHOK_BOMB: \"Bombă Șoc Termal\"\n  STR_SONIC_PULSER: \"Grenadă Sonică\"\n  STR_ZRBITE: \"Zrbite\"\n  STR_MC_READER: \"Sondă C.M.\"\n  STR_VIBRO_BLADE: \"Vibro-Lamă\"\n  STR_THERMIC_LANCE: \"Lance Termică\"\n  STR_HEAVY_THERMIC_LANCE: \"Lance Termică Grea\"\n  STR_AQUATOID_CORPSE: \"Cadavru Aquatoid\"\n  STR_GILLMAN_CORPSE: \"Cadavru Gill Man\"\n  STR_LOBSTERMAN_CORPSE: \"Cadavru Lobster Man\"\n  STR_TASOTH_CORPSE: \"Cadavru Tasoth\"\n  STR_CALCINITE_CORPSE: \"Cadavru Calcinite\"\n  STR_DEEP_ONE_CORPSE: \"Cadavru Deep One\"\n  STR_BIODRONE_CORPSE: \"Cadavru Bio-Drone\"\n  STR_TENTACULAT_CORPSE: \"Cadavru Tentaculat\"\n  STR_TRISCENE_CORPSE: \"Cadavru Triscene\"\n  STR_HALLUCINOID_CORPSE: \"Cadavru Hallucinoid\"\n  STR_XARQUID_CORPSE: \"Cadavru Xarquid\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"Muniție insuficientă pentru înarmare SSA{SMALLLINE}Fiecare SSA necesită {0} {1}.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Echipamente insuficiente pentru utilarea trupelor\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Finalizare cercetare{NEWLINE}{0}{NEWLINE}pentru a produce{NEWLINE}{1}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"Extratereștrii au distrus baza lipsită de apărare {0}\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"Patrulele X-Com au localizat o colonie extraterestră în {0}\"\n  STR_STANDOFF: \"PĂSTREAZĂ DISTANȚA\"\n  STR_CAUTIOUS_ATTACK: \"ATAC PRECAUT\"\n  STR_STANDARD_ATTACK: \"ATAC STANDARD\"\n  STR_AGGRESSIVE_ATTACK: \"ATAC AGRESIV\"\n  STR_DISENGAGING: \"DEGAJARE\"\n  STR_UFO_HIT: \"OSN LOVIT!\"\n  STR_UFO_CRASH_LANDS: \"OSN DOBORÂT!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Minimizare Numai la Distanță\"\n  STR_UFO_RETURN_FIRE: \"OSN RIPOSTEAZĂ!\"\n  STR_INTERCEPTOR_DAMAGED: \">>> NAVĂ AVARIATĂ <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> NAVĂ DISTRUSĂ <<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"OSN DEVANSEAZĂ INTERCEPTORUL!\"\n  STR_LONG_RANGE_DETECTION: \"Detecție Bandă Largă\"\n  STR_STORES_UC: \"DEPOZITE\"\n  STR_DIFFICULTY_LEVEL: \"Nivel Dificultate\"\n  STR_INTERCEPT: \"INTERCEPTARE\"\n  STR_BASES: \"BAZE\"\n  STR_GRAPHS: \"GRAFICE\"\n  STR_UFOPAEDIA_UC: \"UFOPAEDIA\"\n  STR_OPTIONS_UC: \"OPȚIUNI\"\n  STR_FUNDING_UC: \"FINANȚARE\"\n  STR_5_SECONDS: \"5 Sec\"\n  STR_1_MINUTE: \"1 Min\"\n  STR_5_MINUTES: \"5 Min\"\n  STR_30_MINUTES: \"30 Min\"\n  STR_1_HOUR: \"1 Oră\"\n  STR_1_DAY: \"1 Zi\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"Listă Performanțe X-Com\"\n  STR_ENTER_NAME: \"Introducere Nume\"\n  STR_PERFORMANCE_RATING: \"Evaluare Performanță\"\n  STR_VICTORY_DATE: \"Data Victoriei\"\n  STR_CHEMICAL_FLARE: \"Semnal Luminos Chimic\"\n  STR_CHEMICAL_FLARE_UFOPEDIA: \"Acest dispozitiv compact produce o lumină puternică la orice adâncime sau la sol. În timpul misiunilor de noapte sau la adâncime mare va evidenția inamicii din proximitatea semnalului luminos.\"\n  STR_MONTHLY_COSTS: \"Costuri Lunare\"\n  STR_CRAFT_RENTAL: \"Chiria Navelor\"\n  STR_SALARIES: \"Salarii\"\n  STR_BASE_MAINTENANCE: \"Întreținerea Bazei\"\n  STR_COST_PER_UNIT: \"Cost unitar\"\n  STR_QUANTITY: \"Cantitate\"\n  STR_TOTAL: \"Total\"\n  STR_IN_PSIONIC_TRAINING: \"La Implantare C.M.\"\n  STR_FRONT_ARMOR: \"Armură Frontală\"\n  STR_LEFT_ARMOR: \"Armură Stânga\"\n  STR_RIGHT_ARMOR: \"Armură Dreapta\"\n  STR_REAR_ARMOR: \"Armură Spate\"\n  STR_UNDER_ARMOR: \"Armură Inferioară\"\n  STR_ROUNDS: \"MUNIȚIE\"\n  STR_UNIT: \"UNITATE> {0}\"\n  STR_ENERGY: \"ENERGIE\"\n  STR_MORALE: \"MORAL\"\n  STR_ARMOR_: \"ARMURĂ> {0}\"\n  STR_FRONT_ARMOR_UC: \"ARMURĂ FRONTALĂ\"\n  STR_LEFT_ARMOR_UC: \"ARMURĂ STÂNGA\"\n  STR_RIGHT_ARMOR_UC: \"ARMURĂ DREAPTA\"\n  STR_REAR_ARMOR_UC: \"ARMURĂ SPATE\"\n  STR_SKILLS: \"ABILITĂȚI> {0}\"\n  STR_LEVEL: \"NIVEL> {0}\"\n  STR_HEAD: \"CAP\"\n  STR_TORSO: \"TRUNCHI\"\n  STR_RIGHT_ARM: \"BRAȚ DREPT\"\n  STR_LEFT_ARM: \"BRAȚ STÂNG\"\n  STR_RIGHT_LEG: \"PICIOR DREPT\"\n  STR_LEFT_LEG: \"PICIOR STÂNG\"\n  STR_PAIN_KILLER: \"ANALGEZIC\"\n  STR_STIMULANT: \"STIMULENT\"\n  STR_HEAL: \"VINDECARE\"\n  STR_TIME_UNITS_SHORT: \"UT>{ALT}{0}\"\n  STR_WEIGHT: \"Greut>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"Reac>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"Abil.MC>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"Rez.MC>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Artefact Extraterestru\"\n  STR_AMMO_ROUNDS_LEFT: \"MUNIȚIE:{NEWLINE}SALVE{NEWLINE}RĂMASE={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Calm>{ALT}{0}{ALT}{NEWLINE}Stim>{ALT}{1}{ALT}{NEWLINE}Trat>{ALT}{2}\"\n  STR_THROW: \"Aruncare\"\n  STR_AUTO_SHOT: \"Foc Automat\"\n  STR_SNAP_SHOT: \"Foc Rapid\"\n  STR_AIMED_SHOT: \"Foc Ochit\"\n  STR_STUN: \"Paralizare\"\n  STR_PRIME_GRENADE: \"Amorsare\"\n  STR_USE_SCANNER: \"Folosire Detector\"\n  STR_USE_MEDI_KIT: \"Folosire Trusă\"\n  STR_LAUNCH_MISSILE: \"Lansare Torpilă\"\n  STR_ACCURACY_SHORT: \"Pre>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Unități Timp Insuficiente!\"\n  STR_NOT_ENOUGH_ENERGY: \"Energie Insuficientă!\"\n  STR_NO_ROUNDS_LEFT: \"Salve Terminate!\"\n  STR_NO_AMMUNITION_LOADED: \"Arma este Descărcată!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Muniție improprie pentru această Armă!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"Arma este deja încărcată!\"\n  STR_NO_LINE_OF_FIRE: \"Linie de Tragere Blocată!\"\n  STR_GRENADE_IS_ACTIVATED: \"Grenada este Amorsată!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Grenada este Dezamorsată!\"\n  STR_THERE_IS_NO_ONE_THERE: \"Nu este nimeni acolo!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Artefact inutilizabil până ce nu este cercetat!\"\n  STR_OUT_OF_RANGE: \"În Afara Razei De Acțiune!\"\n  STR_UNABLE_TO_THROW_HERE: \"Nu se poate arunca acolo!\"\n  STR_SET_TIMER: \"Setare Cronometru\"\n  STR_HIDDEN_MOVEMENT: \"MIȘCĂRI ASCUNSE\"\n  STR_TURN: \"RUNDA> {0}\"\n  STR_SIDE: \"FACȚIUNEA> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Apasă orice pentru a continua\"\n  STR_MIND_CONTROL: \"Control Molecular\"\n  STR_PANIC_UNIT: \"Blocare Implant\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Atac Moral Reușit\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Controlul Implantului Reușit\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}a Înnebunit\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}a Înnebunit\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}s-a Panicat\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}s-a Panicat\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Extratereștrii\"\n  STR_RIGHT_HAND: \"MÂNA DREAPTĂ\"\n  STR_LEFT_HAND: \"MÂNA STÂNGĂ\"\n  STR_RIGHT_SHOULDER: \"UMĂR DREPT\"\n  STR_LEFT_SHOULDER: \"UMĂR STÂNG\"\n  STR_BACK_PACK: \"RUCSAC\"\n  STR_BELT: \"CENTURĂ\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}se află sub Control Molecular\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}se află sub Control Molecular\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}și-a pierdut cunoștința\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}și-a pierdut cunoștința\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}a murit din cauza rănilor grave\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}a murit din cauza rănilor grave\"\n  STR_USE_MIND_PROBE: \"Folosire Sondă C.M.\"\n  STR_FATAL_WOUNDS: \"RĂNI GRAVE\"\n  STR_UNDER_ARMOR_UC: \"ARMURĂ INFERIOARĂ\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Unități Timp rezervate pentru Foc Rapid\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Unități Timp rezervate pentru Foc Automat\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Unități Timp rezervate pentru Foc Țintit\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Unități Timp rezervate pentru Îngenunchere\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"UT rezervate pentru Îngenunchere și Foc\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} Soldat în Nava X-Com\"\n    few: \"{N} Soldați în Nava X-Com\"\n    other: \"{N} Soldați în Nava X-Com\"\n  STR_UNITS_OUTSIDE:\n    one: \"{N} Soldat lăsat afară\"\n    few: \"{N} Soldați lăsați afară\"\n    other: \"{N} Soldați lăsați afară\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} Soldat în Zona de Intrare\"\n    few: \"{N} Soldați în Zona de Intrare\"\n    other: \"{N} Soldați în Zona de Intrare\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} Soldat în Zona de Evacuare\"\n    few: \"{N} Soldați în Zona de Evacuare\"\n    other: \"{N} Soldați în Zona de Evacuare\"\n  STR_ABORT_MISSION_QUESTION: \"Abandonare Misiune?\"\n  STR_CORPSE: \"Cadavru\"\n  STR_UNLOAD_CRAFT: \"Descărcare\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}a fost ucisă\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}a fost ucisă\"\n  STR_HIT_MELEE: \"Lovire\"\n  STR_GROUND: \"LA SOL\"\n  STR_LIVING_QUARTERS_PLURAL: \"Ansamblu Locuințe\"\n  STR_LIST_ITEM: \"ARTICOL\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"Toți extratereștrii morți în scufundare,{NEWLINE}se inițiază recuperarea automată\"\n  STR_RESET: \"Resetare\"\n  STR_MEMORIAL: \"Memorial\"\n  STR_DATE_UC: \"DATĂ\"\n  STR_SOLDIERS_RECRUITED_UC: \"SCAFANDRIERI RECRUTAȚI>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"SCAFANDRIERI PIERDUȚI>{ALT}{0}\"\n  STR_REMOVE_SELECTED: \"Eliminare Selecționați\"\n  STR_LIVE_ALIENS: \"Exemplare{NEWLINE}În Viață\"\n  STR_DEAD_ALIENS: \"Exemplare{NEWLINE}Respinse\"\n  STR_UNDER_INTERROGATION: \"Supuse{NEWLINE}Studiului\"\n  STR_CONTAINMENT_EXCEEDED: \"LIMITE DEPĂȘITE CARANTINĂ EXTRATEREȘTRII!{SMALLLINE}Spațiu insuficient în carantina din {0}. Trebuie eliminat excesul de extratereștrii din carantină (aceștia vor muri).\"\n  STR_MANAGE_CONTAINMENT: \"Gestionare Carantină Extratereștrii\"\n  STR_STORAGE_EXCEEDED: \"SPAȚIU DEPOZITARE DEPĂȘIT!{SMALLLINE}Spațiu insuficient pentru stocare în {0}. Trebuie vândut surplusul de articole.\"\n  STR_GO_TO_BASE: \"Afișare Bază\"\n  STR_MELEE_ACCURACY: \"PRECIZIE MELEU\"\n  STR_SELL_PRODUCTION: \"VÂNZARE\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Ambele mâini trebuie să fie goale!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Articole insuficiente pentru a copia șablonul!\"\n  STR_UNLOAD_WEAPON: \"Descărcare armă\"\n  STR_ALL_ITEMS: \"Toate Articolele\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"FĂRĂ ECHIPAMENT ÎN PLUS LA BORD!{SMALLLINE}Se poate lua la bord un număr maxim de {N} de articol pentru această navă.\"\n    few: \"FĂRĂ ECHIPAMENT ÎN PLUS LA BORD!{SMALLLINE}Se pot lua la bord un număr maxim de {N} de articole pentru această navă.\"\n    other: \"FĂRĂ ECHIPAMENT ÎN PLUS LA BORD!{SMALLLINE}Se pot lua la bord un număr maxim de {N} de articole pentru această navă.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}CENTRU DE CONTROL DISTRUS{NEWLINE}Continuați până la intrare și evacuați.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"Structurile X-Com subacvatice nu pot fi construite pe sol\"\n  STR_UNABLE_TO_ENGAGE_DEPTH: \"INAMICUL NU POATE FI INTERCEPTAT{NEWLINE}LA ACEASTĂ ADÂNCIME\"\n  STR_UNABLE_TO_ENGAGE_AIRBORNE: \"INAMICUL NU POATE FI INTERCEPTAT{NEWLINE}CÂND ESTE ÎN AER\"\n  STR_UNDERWATER_EQUIPMENT: \"Echipamentul nu poate funcționa la suprafață!\"\n  STR_LAND_EQUIPMENT: \"Echipamentul nu poate funcționa sub apă!\"\n  STR_LEVEL_SHORT: \"E{0}\"\n  STR_PERSONNEL: \"Personal\"\n  STR_CRAFT_ARMAMENT: \"Nave & Armament\"\n  STR_COMPONENTS: \"Componente\"\n  STR_SOLDIERS_RECRUITED: \"Scafandrieri recrutați\"\n  STR_SOLDIERS_LOST: \"Scafandrieri pierduți\"\n  STR_TOTAL_UFOS: \"OSNuri detectate\"\n  STR_TOTAL_ALIEN_BASES: \"Colonii Extraterestre descoperite\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"RCM\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"ACM\"\n  FEMALE_CIVILIAN: \"Civil, Femeie\"\n  MALE_CIVILIAN: \"Civil, Bărbat\"\n  DOCKER_CIVILIAN: \"Civil, Docher\"\n  SAILOR_CIVILIAN: \"Civil, Marinar\"\n  STR_BIODRONE_MELEE_WEAPON: \"Atac Mele Bio-drone\"\n  HALLUCINOID_WEAPON: \"Armă Hallucinoid\"\n  STR_LOBSTERMAN_MELEE_WEAPON: \"Atac Mele Lobsterman\"\n  CALCINITE_WEAPON: \"Armă Calcinite\"\n  DEEP_ONE_WEAPON: \"Armă Deep One\"\n  STR_TRISCENE_MELEE_WEAPON: \"Atac Mele Triscene\"\n  STR_TRIBIO_SONIC_WEAPON: \"Armă Sonică Extraterestră\"\n  XARQUID_WEAPON: \"Armă Xarquid\"\n  TENTACULAT_WEAPON: \"Armă Tentaculat\"\n  ZOMBIE_WEAPON: \"Armă Zombie\"\n  ALIEN_PSI_WEAPON: \"Armă M.C. Extraterestră\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/ru.yml",
    "content": "ru:\n  STR_LEVIATHAN_UFOPEDIA: \"СУБМАРИНА, ПРЕДНАЗНАЧЕННАЯ ДЛЯ ТРАНСПОРТИРОВКИ ВОЙСК И ПЕРЕХВАТА ПРОТИВНИКА, КОТОРОЙ ДОСТУПНЫ ЭКСТРЕМАЛЬНЫЕ ГЛУБИНЫ. ПРЕВОСХОДНЫЙ ОБРАЗЕЦ СИНТЕЗА ЗЕМНЫХ И ВНЕЗЕМНЫХ ТЕХНОЛОГИЙ, В КОТОРОМ ПРИМЕНЯЮТСЯ ИОННЫЕ СИЛОВЫЕ УСТАНОВКИ И МАГНИТНЫЕ НАВИГАЦИОННЫЕ АНТЕННЫ.\"\n  STR_BARRACUDA_UFOPEDIA: \"БРИТАНСКАЯ ГИДРОСФЕРНАЯ БАРРАКУДА ОСНАЩЕНА ПЕРЕГРЕВАЮЩИМИ ЛАЗЕРНЫМИ ДВИГАТЕЛЯМИ. ОДИН ИЗ САМЫХ БЫСТРЫХ В МИРЕ КОРАБЛЕЙ-ПЕРЕХВАТЧИКОВ, СПОСОБНЫХ ПЕРЕМЕЩАТЬСЯ КАК ПОД ВОДОЙ, ТАК И В АТМОСФЕРЕ. КЛЮЧЕВОЕ СУДНО В ПРЕДСТОЯЩЕЙ БИТВЕ.\"\n  STR_HAMMERHEAD_UFOPEDIA: \"СУДНО, ПРЕДНАЗНАЧЕННОЕ ДЛЯ ТРАНСПОРТИРОВКИ ВОЙСК И ПЕРЕХВАТА ПРОТИВНИКА. НА КОРАБЛЕ РАЗМЕЩЕН АНАЛОГ СИСТЕМЫ МАГНИТНЫХ МАССИВОВ. НЕСМОТРЯ НА СВОИ МАЛЫЕ РАЗМЕРЫ, ЭТОТ АППАРАТ ПРЕДСТАВЛЯЕТ СОБОЙ ПОТРЯСАЮЩЕЕ ТЕХНИЧЕСКОЕ ДОСТИЖЕНИЕ.\"\n  STR_TRITON_UFOPEDIA: \"\\\"ТРИТОН\\\" - ЭТО ТРАНСПОРТНО-ДЕСАНТНЫЙ КОРАБЛЬ, ОСНАЩЕННЫЙ ДВИГАТЕЛЯМИ, РАБОТАЮЩИМИ В АТМОСФЕРЕ И ПОД ВОДОЙ. БОЛЬШАЯ ГРУЗОПОДЪЕМНОСТЬ И НАДЕЖНАЯ КОНСТРУКЦИЯ ДЕЛАЮТ ЭТОТ КОРАБЛЬ ОПЛОТОМ ФЛОТА X-COM.\"\n  STR_MANTA_UFOPEDIA: \"\\\"МАНТА\\\" - ВЫСОКОСКОРОСТНОЕ СУДНО, ОДНОМЕСТНАЯ ЛЕТАЮЩАЯ ПОДЛОДКА-ПЕРЕХВАТЧИК ВЕСЬМА СХОЖА С КОРАБЛЯМИ ПРИШЕЛЬЦЕВ НА ИОННОЙ ТЯГЕ. ВЫСОКОЭФФЕКТИВНЫЙ УДАРНЫЙ АППАРАТ В УСЛОВИЯХ НАРАСТАЮЩЕГО КОНФЛИКТА.\"\n  STR_AJAX_UFOPEDIA: \"ТОРПЕДА \\\"АЯКС\\\" - ТИПОВОЕ ВООРУЖЕНИЕ ПОДВОДНЫХ СРАЖЕНИЙ ВО ВСЁМ МИРЕ. ИСПОЛЬЗУЕТСЯ КАК МЕТКОЕ И МОЩНОЕ СРЕДСТВО СДЕРЖИВАНИЯ.\"\n  STR_DUP_HEAD_UFOPEDIA: \"ТЕХНОЛОГИЯ БОЕПРИПАСОВ С СЕРДЕЧНИКОМ ИЗ ОБЕДНЕННОГО УРАНА РАЗРАБОТАНА ОТНОСИТЕЛЬНО НЕДАВНО, И ЭТО ПЕРВОЕ КОММЕРЧЕСКОЕ ВОПЛОЩЕНИЕ ПОДВОДНОГО ОРУЖЕЙНОГО КОМПЛЕКСА, В КОТОРОМ ОНИ ИСПОЛЬЗУЮТСЯ В ПОЛНОЙ МЕРЕ.\"\n  STR_CRAFT_GAS_CANNON_UFOPEDIA: \"ОРУДИЙНАЯ СИСТЕМА НА СЖАТОМ ГАЗЕ, СТРЕЛЯЮЩАЯ ЦЕЛЬНОКОРПУСНЫМИ СНАРЯДАМИ С ВЫСОКОЙ БРОНЕПРОБИВАЕМОСТЬЮ.\"\n  STR_PWT_CANNON_UFOPEDIA: \"ИМПУЛЬСНО-ВОЛНОВАЯ ТОРПЕДА ИСПОЛЬЗУЕТ СИСТЕМУ  ПЕРЕГРЕВА ТОПЛИВА И ОЧЕНЬ ПЛОТНУЮ БОЕГОЛОВКУ, КОТОРАЯ СПОСОБНА ПРОБИТЬ БОЛЬШИНСТВО СПЛАВОВ.\"\n  STR_GAUSS_CANNON_UFOPEDIA: \"ОРУЖИЕ ГАУССА - ЭТО НОВАЯ ТЕХНОЛОГИЯ, РАЗРАБОТАННАЯ СПЕЦИАЛИСТАМИ X-COM. УСКОРИТЕЛЬ ЧАСТИЦ ЭТОЙ СИСТЕМЫ РАБОТАЕТ НА КОМПАКТНОМ ТЕРМОЯДЕРНОМ РЕАКТОРЕ, ОХЛАЖДАЕМОМ ЖИДКИМ АЗОТОМ.\"\n  STR_SONIC_OSCILLATOR_UFOPEDIA: \"МОЩНЫЙ ЗВУКОВОЙ ОСЦИЛЛЯТОР СОЗДАЕТ АКУСТИЧЕСКИЕ ВОЛНЫ, УНИЧТОЖАЮЩИЕ ЦЕЛЬ ПОСРЕДСТВОМ КОЛЕБАНИЙ, РАЗРЫВАЮЩИХ МЕЖМОЛЕКУЛЯРНЫЕ СВЯЗИ.\"\n  STR_AQUATOID_UFOPEDIA: \"Раса акватоидов - это древняя цивилизация, процветавшая за много тыс. лет до того, как человек сделал первые шаги по земле. Их компактное телосложение и грушевидный череп напоминают об их космич. собратьях - сектоидах. Основа их мощи - эффективная технология молек. контроля. Размножение бесплодной расы акватоидов происходит путем генетических модификаций, идеальным объектом для которых являются человеческие индивиды. В результате экспериментов возникло множество гибр. рас.\"\n  STR_AQUATOID_AUTOPSY: \"Вскрытие акватоида\"\n  STR_AQUATOID_AUTOPSY_UFOPEDIA: \"Анализ этого существа позволяет нам сделать некоторые исходные предположения. Это сектоид, наш старый противник, но видоизменённый хирургическим путем и снабженный имплантами, позволяющими ему существовать под водой. Рудиментарные легкие позволяют ему дышать воздухом и ограниченно перемещаться на поверхности. В теле установлены киберимпланты, улучшающие функциональность атрофированных конечностей и органов. Все особи этой расы идентичны; мы предполагаем, что они клонированы.\"\n  STR_GILLMAN_UFOPEDIA: \"Это странное человекоподобное создание, очевидно, является гуманоидной рептилией, очень близкой к человеку. Это чрезвычайно сильное создание, способное быстро двигаться под водой. Гиллмены - полноценная раса, в которой есть особи двух полов и разных возрастов. Они отличаются от большинства подводных пришельцев, поскольку не несут следов генетических или хирургических вмешательств. Похоже, это некая древняя ветвь нашего вида.\"\n  STR_GILLMAN_AUTOPSY: \"Вскрытие гиллмена\"\n  STR_GILLMAN_AUTOPSY_UFOPEDIA: \"Уже в ходе вскрытия стало ясно, что это не пришелец, а какая-то доисторическая земная раса, которая жила на Земле во времена динозавров и, как считалось, погибла в начале эры млекопитающих. Гиллмены - умные и сильные амфибии. Доисторический катаклизм, положивший конец господству рептилий, вынудил их вступить в симбиотические отношения с появившимися на Земле пришельцами. В их черепа вживлено маленькое электронное устройство.\"\n  STR_LOBSTERMAN_UFOPEDIA: \"Это поразительное создание, выше человека и обладающее шестью конечностями, напоминает ничего иного, кроме как водяного демона. Сходство с земным лобстером принесло ему прозвище «Лобстермен» среди бойцов X-Com. Это чудище глубин. Тщательно спроектированная бойцовая тварь невероятной силы, практически неуязвимая для снарядного огня. Одни только клешни способны дробить сталь.\"\n  STR_LOBSTERMAN_AUTOPSY: \"Вскрытие лобстермена\"\n  STR_LOBSTERMAN_AUTOPSY_UFOPEDIA: \"Под практически неразрушимым панцирем оказалось существо удивительного строения. Мощные мышцы переплетаются вокруг титанового скелета, сложная система наведения с возможностью многодиапазонного сканирования подключена прямо к мозгу. Его фасеточные глаза защищены пластиком, тверже стали. Очевидно, что при умелом использовании своими хозяевами эти создания практически неостановимы. Глубоко внутри их тел скрыты устройства неизвестной конструкции и назначения.\"\n  STR_TASOTH_UFOPEDIA: \"Эти быстрые и проворные пришельцы - оплот инопланетной армии. Они сотнями выходят из огромных баков размножения, расположенных в сердце колоний пришельцев. Значительно более сильные, чем люди, тасоты - истинные пришельцы, и их манера поведения и плотоядная природа не имеет аналогов на планете. Тасоты часто идут в авангарде во время нападений пришельцев и никогда не уклоняются от боя, даже перед лицом значительно превосходящего их числом противника.\"\n  STR_TASOTH_AUTOPSY: \"Вскрытие тасота\"\n  STR_TASOTH_AUTOPSY_UFOPEDIA: \"Вскрытие показало, что это кибернетический организм, обладающий странной силой. Внутри полости тела находится малый источник энергии, но при этом не найдено опознаваемых органов. Энергия переносится по телу биоэлектрической системой. В теле нет ни костей, ни каркаса. Если пришелец умирает, подача энергии прекращается, а тело становится безжизненной куклой, из которой сочится жидкость и мышечная ткань. Кроме источника энергии, мы обнаружили пару керамических ячеек, которые оживляют организм в случае подачи на них энергии.\"\n  STR_DEEP_ONE_UFOPEDIA: \"Глубинный - это биологический кошмар, гибрид, порождённый опытами акватоидов, искажающими разум. Мы столкнулись с несколькими разновидностями этого существа. После проведения обширных исследований мы пришли к выводу, что они были изготовлены захватчиками. Их ряды пополняются по мере захвата свежих человеческих особей. Каждый из этих недочеловеков орудует электрическим разрядом, достаточно мощным, чтобы убить акванавта.\"\n  STR_DEEP_ONE_AUTOPSY: \"Вскрытие глубинного\"\n  STR_DEEP_ONE_AUTOPSY_UFOPEDIA: \"Это существо - результат трансплантации инопланетных тканей в организм человека. Человеческий мозг был сильно изменён для подключения электронного управления и трансплантации коры пришельца. Все человеческие органы, видимо, уничтожены - остались только глаза. Хирургические трансплантаты позволяют зародышу по мере роста поглощать носителя. Прочная кожа существа не содержит органики: это металлическая сеть, очень прочная и гибкая. Гибрид очень силен, быстр и полностью контролируется пришельцами.\"\n  STR_BIODRONE_UFOPEDIA: \"Биодрон - создание, которое мог придумать только пришелец. Это мозг (человека либо пришельца), погружённый в амниотическую жидкость и соединённый с энергетической платформой, способной летать над землёй или под водой. Каждый биодрон вооружён мощным звуковым разрушителем, частично механическим и частично живым. Учёные предположили, что это оружие управляется голосовыми связками организма хозяина. Будучи весьма меткими и крепкими, эти сторожевые псы используются пришельцами для защиты ценного имущества.\"\n  STR_BIODRONE_AUTOPSY: \"Вскрытие биодрона\"\n  STR_BIODRONE_AUTOPSY_UFOPEDIA: \"Гипотеза о биологической природе акустического разрушителя подтвердилась. Это несчастное создание буквально убивает врагов своим воплем. Каждый экземпляр имеет множество следов хирургических вмешательств и жестоко искалечен. Похоже, пришельцы безжалостно пытают мозг до достижения полной покорности. Обычно используется мозг пришельцев, но ужас при обнаружении человеческого мозга неизмеримо выше. Биодроны снабжены ионным двигателем и некой интегрированной системой дистанционного управления.\"\n  STR_TENTACULAT_UFOPEDIA: \"Даже в безднах лавкрафтовских кошмаров нет такого неописуемого создания. Среди земных организмов нет сколько-нибудь близких аналогов этому существу, и невозможно даже представить среду, способную породить ЭТО. Вооружённый длинными щупальцами, тентакулат парализует свои жертвы и превращает их в безмозглые куклы, которые способны убить одним прикосновением, даже сквозь броню. Тентакулат - самое зловещее существо из всех, с кем доводилось встречаться X-COM.\"\n  STR_TENTACULAT_AUTOPSY: \"Вскрытие тентакулата\"\n  STR_TENTACULAT_AUTOPSY_UFOPEDIA: \"При вскрытии этого огромного мозга были обнаружены небольшие киберимпланты. Зрительная система представляет собой сложный комплекс рецепторов излучения видимого и инфракрасного спектра. Даже в тёмных глубинах океана этот монстр может перемещаться с безошибочной точностью. Имеются рудиментарные органы, которые едва обеспечивают его существование. У каждого существа есть маленький желудок с внешним разъёмом. Видимо, это существо получает питательные вещества путем прямого их введения хозяевами.\"\n  STR_CALCINITE_UFOPEDIA: \"Похожие на водолазные костюмы пропавших моряков, эти пришельцы блуждают по морскому дну в поисках доверчивых жертв. Его удар, превосходящий по мощи створки стального капкана, способен утопить даже самых лучших дайверов. Вокруг лицевой маски можно заметить студенистое зеленое образование. Что за существо находится в скафандре, нам до сих пор понять не удалось, несмотря на неоднократные смертельно опасные встречи с ним.\"\n  STR_CALCINITE_AUTOPSY: \"Вскрытие кальцинита\"\n  STR_CALCINITE_AUTOPSY_UFOPEDIA: \"После снятия бронированного скафандра кальцинит предстал перед нами в виде огромной аморфной капли протоплазмы. Нет никаких видимых следов мозга, конечностей или органов чувств; в его жидком теле присутствует только небольшой металлический компонент. В результате исследования мертвого экземпляра мы можем только гадать, какова природа этого существа. Ещё одна неразрешимая загадка от наших инопланетных врагов.\"\n  STR_TRISCENE_UFOPEDIA: \"Эта двуногая рептилия - ожившее ископаемое эры динозавров. Видимо, это создание, представляя собой во всех отношениях экземпляр из мелового периода, сохранило способность существовать и в воде, и на суше. Эти создания оснащены оружейными подвесками и обладают челюстью с огромными металлическими зубами. Зачастую эти монстры становятся ядром ударных сил пришельцев при атаках на суше. Поистине тяжелое и мощное оружие, которое тасоты-командующие применяют со смертоносной эффективностью.\"\n  STR_TRISCENE_AUTOPSY: \"Вскрытие трисцена\"\n  STR_TRISCENE_AUTOPSY_UFOPEDIA: \"Скальпель учёного подтвердил, что трисцен - это древнее существо, оснащенное кибернетическими имплантами и оружейными системами. Его крошечный мозг дополнен маленьким компьютерным модулем, установленным в пучке управления, который несут все представители этого вида. Плотная натуральная кожа и инстинкт хищника, улучшенные с помощью дополнительного вооружения, делают его смертоносным противником в любой среде.\"\n  STR_HALLUCINOID_UFOPEDIA: \"Захватив океаны, пришельцы стали разводить этих огромных земных существ для применения в качестве оружия. Не позволяйте обмануть себя ложному чувству безопасности при встрече с этими безобидными на вид подводными парусниками. Ледяная атака, использующаяся в ближнем бою, делает галлюциноидов смертоносным противником.\"\n  STR_HALLUCINOID_AUTOPSY: \"Вскрытие галлюциноида\"\n  STR_HALLUCINOID_AUTOPSY_UFOPEDIA: \"Множество слоев студенистого тела этого организма скрывают мощный химический холодильник, основное оружие этого существа. Мягкая и гибкая оболочка галлюциноида, похоже, уязвима для тепловых атак. Зачастую этих мутантов можно встретить в компании с их хозяевами - акватоидами.\"\n  STR_XARQUID_UFOPEDIA: \"Ещё одно модифицированное земное беспозвоночное, ксарквид, - очень красивое и опасное создание. Этот стремительный водоплавающий гигант обладает разрушительным арсеналом: удушающими чернилами и взрывчаткой на основе ионизированных частиц. Уже с первых встреч с этим сильным созданием мы поняли, насколько опасно оно и контролирующие его мстительные гиллмены.\"\n  STR_XARQUID_AUTOPSY: \"Вскрытие ксарквида\"\n  STR_XARQUID_AUTOPSY_UFOPEDIA: \"Этот наутилус-переросток вырос до таких размеров благодаря внеземным препаратам и хирургическим изменениям. Извратив его изначальную природу, гиллмены встроили в него механическую систему управления, так что от изначальной природы существа ничего не осталось. Используемые в качестве органической боевой платформы, ксарквиды, благодаря прочной оболочке и хорошей мобильности, являются грозным противником.\"\n  STR_ION_BEAM_ACCELERATORS_UFOPEDIA: \"Летающие субмарины пришельцев используют сложные энергосистемы для перемещения по глубинам. Основа их технологии - ИОННЫЙ ВЫТЕСНИТЕЛЬ, который, используя зрбит в качестве катализатора, в секунду вытесняет стократный собственный объём. Эта огромная мощь говорит о том, что пришельцы быстрее большинства земных судов. Мы можем воспроизвести эту технологию с помощью аквапластика и ячеек питания на зрбите.\"\n  STR_MAGNETIC_NAVIGATION_UFOPEDIA: \"Эти устройства генерируют многослойное магнитное поле сферической формы, действующее в радиусе до 1000 метров вокруг субмарины. Навигаторы пришельцев напрямую подключены к этим аппаратам и при перемещении судна ощущают весь подводный мир вокруг. Интерфейс системы функционирует посредством использования измененной мозговой ткани пришельцев, взаимодействующей с головным мозгом оператора через нейронную связь.\"\n  STR_ALIEN_SUB_CONSTRUCTION_UFOPEDIA: \"Каждый корабль имеет мимикрирующую структуру из аквапластика, тщательно повторяющую форму морских созданий. Каждая субмарина функционирует как единый организм: экипаж и судно гармонично взаимодействуют. Большинство из этих систем можно скопировать. Дальнейшие исследования гибридной технологии позволят нам достичь такого же технологического уровня.\"\n  STR_ALIEN_CRYOGENICS_UFOPEDIA: \"Бесчисленные орды пришельцев, когда-то прибывших на Землю, находятся в состоянии криогенного сна. Все существа запечатаны в отдельных контейнерах, температура их тела понижена до точки, когда биологические функции практически остановлены. Анализ контейнеров показал, что тела хранятся на протяжении невероятного количества времени, которое составляет более 60 миллионов лет.\"\n  STR_ALIEN_CLONING_UFOPEDIA: \"Многие из пришельцев, которых мы захватили, являются копиями друг друга вплоть до ДНК. Образцы клеток извлекаются из замороженных банков ДНК пришельцев и помещаются в специальные блоки. В некоторых блоках содержатся человеческие тела, в других - только их части. Возможно, эти блоки клонирования предназначены также для создания гибрида человека и пришельца.\"\n  STR_ALIEN_LEARNING_ARRAYS_UFOPEDIA: \"Благодаря использованию имплантов молекулярного контроля, вживленных в черепа всех пришельцев, эти машины передают информацию непосредственно им в мозг. Только что клонированных пришельцев подключают к этим аппаратам, и в их чистый разум загружаются все необходимые боевые навыки, научная информация и видовая память.\"\n  STR_ALIEN_IMPLANTER_UFOPEDIA: \"Этот аппарат используется для вживления имплантов молекулярного контроля в мозг пришельцев, оплодотворения рас-репродуцентов и интеграции или удаления органов и электроники в теле любого живого существа. Предполагалось, что весь процесс происходит на полностью подконтрольных чужой воле пациентах, однако, как выясняется, субъект полностью осознает происходящее, и, к большому сожалению, человеческая анатомия идеально соответствует конструкции блока.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"Теперь у нас есть факты, позволяющие понять, зачем пришельцы захватывают людей. Люди для них не еда, не способ выносить эмбрионов пришельцев, а скорее основа для создания разных видов существ и систем контроля. Технологии пришельцев основаны на подключении к общему коллективному разуму, и человеческий мозг идеально для этого подходит. Мозговая ткань человека используется в большинстве поисковых систем и хранилищ данных биокомпьютеров пришельцев. Прочие ткани используются для строительства и размножения.\"\n  STR_AQUA_PLASTICS_UFOPEDIA: \"Субмарины и другие конструкции пришельцев созданы с использованием невероятно прочного, гибкого и надежного материала - аквапластика. Это сложный композитный материал, при создании которого в качестве катализатора применяется зрбит. Структура материала очень плотная, но при этом лёгкая и в то же время намного более прочная, чем у титана или кевлара.\"\n  STR_ZRBITE_UFOPEDIA: \"Это сплав внеземного происхождения, состоящий частично из золота, частично из биоматериала пришельцев. Небольшое количество этого вещества может обеспечить больше энергии, чем ядерная установка на порядок большего размера. Воссоздание этого материала лежит за пределами наших технических возможностей, поскольку большая часть его компонентов имеет внеземное происхождение.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"Пришельцы атакуют по всему земному шару эффективно и беспощадно. Мы не можем выявить, откуда исходят их нападения. Возможно, это место находится в непроглядной бездне океана? Не все виды, с которыми мы столкнулись, внеземного происхождения: некоторые из них очень древние, другие представляют те эволюционные ветви, которые мы полагали давно уничтоженными. Мы столкнулись с угрозой, которая спала многие тысячелетия, со сложным симбиозом человека и пришельца. В глубинах океана скрыты древние площадки, предназначенные для связи пришельцев с их звёздными собратьями. На каждой из этих двенадцати площадок установлено синомиумное устройство - могущественное технологическое изобретение пришельцев. И теперь, когда их военная машина заработала, пришельцы перезапускают эти устройства для расширения своей сети молекулярного контроля. Мы должны уничтожить эти площадки любой ценой.\"\n  STR_THE_ULTIMATE_THREAT_UFOPEDIA: \"Шестьдесят пять миллионов лет назад из отдалённого мира на Землю был послан огромный колониальный корабль. В тот момент, когда этот корабль приблизился к молодой планете, мощная солнечная вспышка повредила его навигационную систему. Поврежденный и неуправляемый, он своей громадиной обрушился сквозь стратосферу планеты, переживавшей меловой период. Бесчисленные земные создания наблюдали, как их погибель падала на планету. Огромное облако пыли заволокло всю атмосферу, земля стала охлаждаться, и доминирующая форма жизни - динозавры - исчезла. 400-миллиарднотонный Т'льех не разрушился от столкновения, и сложные суперкомпьютеры ввели всех летевших на этом корабле существ в криогенный сон. По прошествии веков компьютеры пробуждали небольшие группы пришельцев, чтобы они могли связаться со своими далекими собратьями, но тщетно. Основные силы пришельцев продолжали спать.\"\n  STR_TLETH_THE_ALIEN_CITY: \"Т'льех - город пришельцев\"\n  STR_TLETH_THE_ALIEN_CITY_UFOPEDIA: \"Т'льех - огромный колонизационный корабль пришельцев, зарытый на дне впадины Сигсби в Мексиканском заливе. В сердце города таится ужас, такой отвратительный и могущественный, что даже смерть страшится прийти за ним. В помещении из инопланетного металла спит великий сновидец - Верховный Пришелец. Когда Т'льех поднимется над водой, запустится реанимационный цикл, и когда Верховный проснётся, его нельзя будет остановить. Будучи не живым, но и не совсем мёртвым, инопланетный разум управляет армией пришельцев. Сверхъестественная технология молекулярного контроля соединяет всех пришельцев с сознанием Верховного, а сознание Верховного - со всеми пришельцами. Генетически модифицированные зародыши гибридов людей и инопланетян обеспечивают сознание Пришельца энергией и образуют связь между хозяином и подконтрольными ему существами. Миф о Верховном Пришельце существовал в сердцах и умах человечества на протяжении многих веков, но истина скрывалась в морской пучине.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"ФОКУС НА ТОЧКЕ, ВРЕМЯ=5 сек.\"\n  STR_CANCEL_UC: \"ОТМЕНА\"\n  STR_NONE: \"Отсутствует\"\n  STR_UNKNOWN: \"Неизвестно\"\n  STR_POOR: \"Плохо\"\n  STR_AVERAGE: \"Посредственно\"\n  STR_GOOD: \"Хорошо\"\n  STR_EXCELLENT: \"Превосходно\"\n  STR_BUILD_NEW_BASE_UC: \"СТРОИТЬ НОВУЮ БАЗУ\"\n  STR_BASE_INFORMATION: \"ИНФОРМАЦИЯ ПО БАЗЕ\"\n  STR_EQUIP_CRAFT: \"СНАРЯДИТЬ СУБМАРИНУ\"\n  STR_BUILD_FACILITIES: \"СТРОИТЬ МОДУЛИ\"\n  STR_RESEARCH: \"ИССЛЕДОВАНИЕ\"\n  STR_MANUFACTURE: \"ПРОИЗВОДСТВО\"\n  STR_TRANSFER_UC: \"ТРАНСПОРТИРОВКА\"\n  STR_PURCHASE_RECRUIT: \"ЗАКУПКА/ВЕРБОВКА\"\n  STR_SACK: \"УВОЛИТЬ\"\n  STR_SELL_SACK_UC: \"ПРОДАТЬ/УВОЛИТЬ\"\n  STR_GEOSCAPE_UC: \"ГЛОБУС\"\n  STR_NAME: \"Имя\"\n  STR_AREA: \"Регион\"\n  STR_BUILD_NEW_BASE: \"Строить новую базу\"\n  STR_CANCEL: \"Отмена\"\n  STR_COST_UC: \"СТОИМОСТЬ>\"\n  STR_CONSTRUCTION_TIME_UC: \"ВРЕМЯ СТРОИТЕЛЬСТВА>\"\n  STR_DAY:\n    one: \"{N} день\"\n    few: \"{N} дня\"\n    many: \"{N} дней\"\n    other: \"{N} дней\"\n  STR_HOUR:\n    one: \"{N} час\"\n    few: \"{N} часа\"\n    many: \"{N} часов\"\n    other: \"{N} часов\"\n  STR_MAINTENANCE_UC: \"ОБСЛУЖИВАНИЕ>\"\n  STR_OK: \"ОК\"\n  STR_INSTALLATION: \"Строить:\"\n  STR_CURRENT_RESEARCH: \"ТЕКУЩИЕ ИССЛЕДОВАНИЯ\"\n  STR_SCIENTISTS_AVAILABLE: \"Ученых доступно>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Ученых занято>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Места в лаборатории доступно>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"ИССЛЕДОВАТЬ ПРОЕКТ\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"УЧЕНЫХ ЗАНЯТО\"\n  STR_PROGRESS: \"ПРОГРЕСС\"\n  STR_NEW_PROJECT: \"Новый проект\"\n  STR_CANCEL_PROJECT: \"ОТМЕНА ПРОЕКТА\"\n  STR_NEW_RESEARCH_PROJECTS: \"НАЧАТЬ НОВЫЙ ПРОЕКТ\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"УЧЕНЫХ ДОСТУПНО>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"МЕСТА В ЛАБОРАТОРИЯХ ДОСТУПНО>{ALT}{0}\"\n  STR_INCREASE: \"Увеличить\"\n  STR_DECREASE: \"Уменьшить\"\n  STR_START_PROJECT: \"НАЧАТЬ ПРОЕКТ\"\n  STR_CURRENT_PRODUCTION: \"ТЕКУЩЕЕ ПРОИЗВОДСТВО\"\n  STR_ENGINEERS_AVAILABLE: \"Техников доступно>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Техников занято>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Места в мастерских доступно>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Текущий баланс>{ALT}{0}\"\n  STR_ITEM: \"ИЗДЕЛИЕ\"\n  STR_ENGINEERS__ALLOCATED: \"Техников занято\"\n  STR_UNITS_PRODUCED: \"Единиц произвед.\"\n  STR_TOTAL_TO_PRODUCE: \"Всего к произв.\"\n  STR_COST__PER__UNIT: \"Цена{NEWLINE}за ед.\"\n  STR_DAYS_HOURS_LEFT: \"Дней/часов осталось\"\n  STR_NEW_PRODUCTION: \"Новое производство\"\n  STR_PRODUCTION_ITEMS: \"Произвести изделие\"\n  STR_CATEGORY: \"КАТЕГОРИЯ\"\n  STR_START_PRODUCTION: \"НАЧАТЬ ПРОИЗВОДСТВО\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} человеко-часов на производство единицы\"\n  STR_COST_PER_UNIT_: \"Стоимость за ед.>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Требуется рабочих мест>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"ТРЕБУЮТСЯ СПЕЦИАЛЬНЫЕ МАТЕРИАЛЫ\"\n  STR_ITEM_REQUIRED: \"НЕОБХОДИМЫЕ МАТЕРИАЛЫ\"\n  STR_UNITS_REQUIRED: \"ТРЕБУЕТСЯ ЕДИНИЦ\"\n  STR_UNITS_AVAILABLE: \"ДОСТУПНО ЕДИНИЦ\"\n  STR_STOP_PRODUCTION: \"ОСТАНОВИТЬ ПРОИЗВОДСТВО\"\n  STR_ENGINEERS_AVAILABLE_UC: \"ТЕХНИКОВ ДОСТУПНО>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"МЕСТА В МАСТЕРСКИХ ДОСТУПНО>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"ДОХОД В МЕСЯЦ>{ALT}{0}\"\n  STR_INCREASE_UC: \"УВЕЛИЧИТЬ\"\n  STR_DECREASE_UC: \"УМЕНЬШИТЬ\"\n  STR_UNITS_TO_PRODUCE: \"Произвести\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Купить/Нанять\"\n  STR_COST_OF_PURCHASES: \"Стоимость покупки>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"ЦЕНА ЗА ЕД.\"\n  STR_QUANTITY_UC: \"КОЛ-ВО\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"ДОСТУПНО ЧЕЛОВЕК:ВСЕГО ЧЕЛОВЕК>\"\n  STR_SOLDIERS: \"Акванавты\"\n  STR_SCIENTISTS: \"Ученые\"\n  STR_ENGINEERS: \"Техники\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"МЕСТА ЗАНЯТО:МЕСТА ДОСТУПНО>\"\n  STR_LIVING_QUARTERS: \"Жилые модули\"\n  STR_STORES: \"Склады\"\n  STR_LABORATORIES: \"Лаборатории\"\n  STR_WORK_SHOPS: \"Мастерские\"\n  STR_HANGARS: \"Подводные доки\"\n  STR_SHORT_RANGE_DETECTION: \"Ближнее обнаружение\"\n  STR_DEFENSE_STRENGTH: \"Мощность обороны\"\n  STR_TRANSFERS_UC: \"ТРАНСПОРТИРОВКИ\"\n  STR_TRANSFERS: \"Транспортировки\"\n  STR_ARRIVAL_TIME_HOURS: \"Время прибытия (часов)\"\n  STR_COST_: \"Стоимость>{ALT}{0}\"\n  STR_AREA_: \"Регион>{ALT}{0}\"\n  STR_BASE_NAME: \"Название базы?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"ВЫБЕРИТЕ МЕСТО ДЛЯ ШЛЮЗОВОЙ КАМЕРЫ\"\n  STR_TRANSFER: \"Транспортировка\"\n  STR_AMOUNT_TO_TRANSFER: \"КОЛ-ВО ДЛЯ ОТПРАВКИ\"\n  STR_SELECT_DESTINATION_BASE: \"Выберите место назначения\"\n  STR_COST: \"Стоимость\"\n  STR_INTRO_1: \"Copyright 1995 MicroProse\"\n  STR_INTRO_2: \"Марс. Кидония пала.\"\n  STR_INTRO_3: \"Одержавшие триумфальную победу бойцы X-Com, уничтожив самое сердце боевой машины пришельцев, летят домой. Однако марсианская база была разрушена не до основания.\"\n  STR_INTRO_4: \"Мощный тахионный луч устремляется из развалин нервного узла Кидонии, проносясь сквозь пустоту. Его цель - ...\"\n  STR_INTRO_5: \"Земля.\"\n  STR_INTRO_6: \"В толще океанских вод сигнал луча пробудил веками неактивный приемник. Огромные спавшие компьютеры зашевелились. В глубине, за пределами человеческого взора, гигантские камеры со спящими пришельцами инициировали долгий цикл пробуждения.\"\n  STR_INTRO_7: \"Год 2040-й. Ничего не подозревающая Земля. Ужасы войны с пришельцами забыты. Но в затерянных, потаенных глубинах океана ждут новые орды пришельцев. Они ждут, чтобы повергнуть человечество в прах и захватить весь мир.\"\n  STR_INTRO_8: \"Пришельцы нападают на людей, ищут образцы для своих извращенных экспериментов, грабят ценные ископаемые и ресурсы, нападают из бездн вод. А затем они обращают свой взор на надводный мир.\"\n  STR_INTRO_9: \"Мощные летающие суда странного вида барражируют над океанами: наблюдают, ищут, преследуют...\"\n  STR_INTRO_10: \"Обнаружив добычу, они нападают.\"\n  STR_INTRO_11: \"Мир столкнулся с новыми жуткими видами вооружений, и теперь мы оказались абсолютно беззащитны перед пришельцами.{NEWLINE}Только одна организация может спасти нас, но мы отвернулись от нее давным-давно...\"\n  STR_INTRO_12: \"Экспериментальная подводная база X-COM\"\n  STR_INTRO_13: \"- SOS! SOS! Говорит трансатлантический лайнер «Гиперион». На нас напали! SOS! S...\"\n  STR_INTRO_14: \"Центр управления - Субмарине #1: - Открыть ворота шлюза. Запуск «Барракуды-01». Мы столкнулись с нападением пришельцев, статус - красный.{NEWLINE}Повторяю: статус - красный.\"\n  STR_INTRO_15: \"Пришельцы действуют с беспощадной эффективностью, ...\"\n  STR_INTRO_16: \"точность их ударов абсолютна.\"\n  STR_INTRO_17: \"Барракуда-01 - базе: - Приближаемся к останкам «Гипериона».\"\n  STR_INTRO_18: \"- Замедляем ход.{NEWLINE}- Два метра.{NEWLINE}- Один метр.{NEWLINE}- Всем акванавтам приготовиться к немедленной высадке!\"\n  STR_INTRO_19: \"- Шлюз открыт... Приближаемся к обломкам.{NEWLINE}- Господи боже!{NEWLINE}- Вы видите этих тварей на моей камере?\"\n  STR_GAMEOVER_1: \"Мы потерпели неудачу, пришельцы уничтожили нашу последнюю надежду на спасение.{NEWLINE}X-Com уничтожен, и Земля пала к ногам древнего врага.\"\n  STR_GAMEOVER_2: \"Т'льех поднимается в стратосферу и начинает свое шествие по планете, сея смерть и порабощая остатки человеческой расы. Глубоко в его недрах начинает пробуждаться кровожадный инопланетный разум.\"\n  STR_GAMEOVER_3: \"В столицах всех государств разрабатываются безнадежные планы. Все тщетно: без технологий, разработанных учеными X-Com, наше оружие бессильно.\"\n  STR_GAMEOVER_4: \"Пришельцы создали базы на полярных шапках и начали растапливать лед. Планета превратится в огромный океан. Остатки человеческой расы согнаны вместе и используются с неизвестной целью в ужасных экспериментах пришельцев по скрещиванию рас. Небеса потемнели, и страшный мор покрыл Землю.\"\n  STR_GAMEOVER_5: \"Мы не можем сопротивляться новому мировому порядку, а те, кто осмеливается, находят свою смерть от огня непостижимого оружия пришельцев. Выживших ждет куда более незавидная участь - планета Земля станет миром пришельцев, а человечество сгинет от ползучего ужаса.\"\n  STR_OUTRO_1: \"Из саркофага в центре разрушенной и разоренной гробницы вырываются пузырьки и раздается рев.{NEWLINE}«Глупцы, все вы сгинете...»\"\n  STR_OUTRO_2: \"...никому не спастись.\"\n  STR_OUTRO_3: \"Мощный взрыв сотрясает гробницу и проносится по городу, наполняя воздух обломками и дымом. Планы пришельцев сорваны...\"\n  STR_OUTRO_4: \"Вращающаяся громада Т'льеха начинает разваливаться на части. Огонь и дым вырываются из его сверкающих шпилей и адамантиновых залов.\"\n  STR_OUTRO_5: \"Могучая крепость пришельцев падает в море, наполняя воздух скрежетом искорёженного металла и воплями умирающих. Не доведется более Великому Сновидцу видеть снов о покорении мира.\"\n  STR_OUTRO_6: \"С последним оглушительным сотрясением Т'льех разрывает себя на части.{NEWLINE}Нет больше угрозы пришельцев, Земля очищена...\"\n  STR_OUTRO_7: \"Тихая сине-зеленая планета в отдаленном уголке галактики.\"\n  STR_OUTRO_8: \"Недалекое будущее, безопасный мир.\"\n  STR_OUTRO_9: \"Инопланетная угроза Земле давно уже ликвидирована.\"\n  STR_OUTRO_10: \"Многие миллиарды людей живут в огромных городах-метрополиях.\"\n  STR_OUTRO_11: \"Про подвиги X-Com и войны с пришельцами рассказывают лишь в детских сказках.\"\n  STR_OUTRO_12: \"Но в любых легендах всегда содержится зерно истины...\"\n  STR_RISE_1: \"Т'льех, имеющий множество названий во многих легендах разных народов.\"\n  STR_RISE_2: \"С чудовищным воплем, слышным даже в самых глухих уголках земного шара, Т'льех начал подниматься со дна океана.\"\n  STR_RISE_3: \"Огромное величественное сооружение восстало из вод Мексиканского залива.\"\n  STR_RISE_4: \"400 миллиардов тонн инопланетного металла, огромный город пришельцев, в котором покоится спящее тело Верховного Пришельца. Он был заточен на Земле на 65 миллионов лет, но теперь это жуткое космическое божество зашевелилось.\"\n  STR_RISE_5: \"Воды вскипели и вспенились, когда склеп Великого Сновидца открылся свету...\"\n  STR_RISE_6: \"...свету, существование которого будет недолгим, если X-Com не удастся уничтожить военную машину пришельцев.\"\n  STR_YOU_HAVE_FAILED: \"Вы не сумели остановить военную машину пришельцев. Финансирующие организации, разочарованные в ваших возможностях, пытаются договориться с пришельцами о мирном урегулировании. Но у захватчиков иные замыслы, и вскоре истина становится известна всему миру...\"\n  STR_TOTAL_UC: \"ВСЕГО\"\n  STR_INCOME: \"Доход\"\n  STR_EXPENDITURE: \"Расход\"\n  STR_MAINTENANCE: \"Обслуживание\"\n  STR_BALANCE: \"Баланс\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"Враж. активн. на морях\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"Враж. активн. в странах\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"Активн. X-Com на морях\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"Активн. X-Com в странах\"\n  STR_FINANCE: \"Финансы\"\n  STR_DATE_FIRST: \"{0}\"\n  STR_DATE_SECOND: \"{0}\"\n  STR_DATE_THIRD: \"{0}\"\n  STR_DATE_FOURTH: \"{0}\"\n  STR_FINANCE_THOUSANDS: \"тыс. $\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"{0}{NEWLINE}требует материалов для производства{NEWLINE}на базе{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"{0}{NEWLINE}требует денег для производства{NEWLINE}на базе{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"Производство{NEWLINE}{0}{NEWLINE}на базе{NEWLINE}{1}{NEWLINE}завершено\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"Строительство{NEWLINE}{0}{NEWLINE}на базе{NEWLINE}{1}{NEWLINE}завершено\"\n  STR_OK_5_SECONDS: \"ОК - 5 сек.\"\n  STR_RESEARCH_COMPLETED: \"Исследование завершено\"\n  STR_VIEW_REPORTS: \"ОТЧЕТ\"\n  STR_WE_CAN_NOW_RESEARCH: \"Теперь мы можем исследовать\"\n  STR_WE_CAN_NOW_PRODUCE: \"Теперь мы можем производить\"\n  STR_SUNDAY: \"ВОСКРЕСЕНЬЕ\"\n  STR_MONDAY: \"ПОНЕДЕЛЬНИК\"\n  STR_TUESDAY: \"ВТОРНИК\"\n  STR_WEDNESDAY: \"СРЕДА\"\n  STR_THURSDAY: \"ЧЕТВЕРГ\"\n  STR_FRIDAY: \"ПЯТНИЦА\"\n  STR_SATURDAY: \"СУББОТА\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Отсутствует {0}, чтобы заправить {1} на базе {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Отсутствует {0}, чтобы перевооружить {1} на базе {2}\"\n  STR_UFO_IS_NOT_RECOVERED: \"СУБМАРИНА не захвачена\"\n  STR_UFO_IS_RECOVERED: \"СУБМАРИНА захвачена\"\n  STR_CRAFT_IS_LOST: \"Субмарина потеряна\"\n  STR_TERROR_CONTINUES: \"Пришельцы продолжают действовать\"\n  STR_ALIENS_DEFEATED: \"Пришельцы побеждены\"\n  STR_BASE_IS_LOST: \"База потеряна\"\n  STR_BASE_IS_SAVED: \"База защищена\"\n  STR_ALIEN_BASE_STILL_INTACT: \"Колония пришельцев все еще действует\"\n  STR_ALIEN_BASE_DESTROYED: \"Колония пришельцев уничтожена\"\n  STR_ALIENS_KILLED: \"ПРИШЕЛЬЦЕВ УБИТО\"\n  STR_ALIEN_CORPSES_RECOVERED: \"ТРУПОВ ПРИШЕЛЬЦЕВ НАЙДЕНО\"\n  STR_LIVE_ALIENS_RECOVERED: \"ЖИВЫХ ПРИШЕЛЬЦЕВ НАЙДЕНО\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"ИНОПЛАНЕТНЫХ АРТЕФАКТОВ НАЙДЕНО\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"КОЛОНИЯ ПРИШЕЛЬЦЕВ УНИЧТОЖЕНА\"\n  STR_ALIEN_SYNOMIUM_DEVICE_DESTROYED: \"СИНОМИУМНОЕ УСТРОЙСТВО УНИЧТОЖЕНО\"\n  STR_ALIEN_SYNOMIUM_DEVICE_FAILED: \"СИНОМИУМНОЕ УСТРОЙСТВО НЕ УНИЧТОЖЕНО\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"ГРАЖДАНСКИХ УБИТО ПРИШЕЛЬЦАМИ\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"ГРАЖДАНСКИХ УБИТО БОЙЦАМИ X-COM\"\n  STR_CIVILIANS_SAVED: \"ГРАЖДАНСКИХ СПАСЕНО\"\n  STR_XCOM_OPERATIVES_KILLED: \"БОЙЦОВ X-COM УБИТО\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"БОЙЦОВ X-COM ПРОПАЛО БЕЗ ВЕСТИ\"\n  STR_TANKS_DESTROYED: \"ОРУЖЕЙНЫХ ПЛАТФОРМ X-COM УНИЧТОЖЕНО\"\n  STR_XCOM_CRAFT_LOST: \"СУБМАРИНА X-COM ПОТЕРЯНА\"\n  STR_UFO_RECOVERY: \"ДОБЫТО С КОРАБЛЯ ПРИШЕЛЬЦЕВ\"\n  STR_ALIEN_BASE_RECOVERY: \"ДОБЫТО В КОЛОНИИ ПРИШЕЛЬЦЕВ\"\n  STR_BASE_UNDER_ATTACK: \"База {0} атакована!\"\n  STR_BASE_DEFENSES_INITIATED: \"ЗАДЕЙСТВОВАНА ОБОРОНА БАЗЫ\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"ЩИТЫ ОТТАЛКИВАЮТ СУБМАРИНУ!\"\n  STR_FIRING: \"ВЫСТРЕЛ\"\n  STR_HIT: \"ПОПАДАНИЕ!\"\n  STR_UFO_DESTROYED: \"СУДНО ПРИШЕЛЬЦЕВ УНИЧТОЖЕНО!\"\n  STR_MISSED: \"ПРОМАХ!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Продать/Уволить\"\n  STR_VALUE_OF_SALES: \"СТОИМОСТЬ ПРОДАЖИ> {ALT}{0}\"\n  STR_FUNDS: \"БАЛАНС> {ALT}{0}\"\n  STR_SELL_SACK: \"Продать/Уволить\"\n  STR_VALUE: \"Цена\"\n  STR_CRAFT_: \"СУБМАРИНА> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"ЗАХВАТ ПОТОПЛЕННОГО СУДНА ПРИШЕЛЬЦЕВ\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"ОСОБЫЕ МЕРЫ ПРЕДОСТОРОЖНОСТИ - на субмарине и вокруг нее могут находиться пришельцы. Миссия будет успешно завершена, если все силы противника будут уничтожены или нейтрализованы. Обломки субмарины, артефакты и тела пришельцев можно впоследствии использовать. Чтобы прервать миссию, верните акванавтов X-Com в субмарину и нажмите кнопку \\\"Покинуть поле боя\\\".\"\n  STR_UFO_GROUND_ASSAULT: \"ШТУРМ СУБМАРИНЫ ПРИШЕЛЬЦЕВ\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"Исследуйте место высадки и постарайтесь проникнуть на судно пришельцев. Миссия будет успешно завершена, если все силы противника будут уничтожены или нейтрализованы. Обломки субмарины, артефакты и тела пришельцев можно впоследствии использовать. Чтобы прервать миссию, верните акванавтов X-Com в субмарину и нажмите кнопку \\\"Покинуть поле боя\\\".\"\n  STR_BASE_DEFENSE: \"ЗАЩИТА БАЗЫ\"\n  STR_BASE_UC_: \"БАЗА> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"Где-то неподалеку сел корабль пришельцев. Нашей базе грозит серьёзная опасность. В соответствии с инструкцией, гражданский персонал и субмарины X-Com были эвакуированы. Пришельцы могут проникнуть в помещения базы через подводные доки или шлюзовую камеру. Защищайте базу и все жизненно важные сооружения любой ценой - бой придется вести до последней капли крови. Если вы нажмете кнопку \\\"Покинуть поле боя\\\", это будет означать поражение и потерю базы.\"\n  STR_ALIEN_COLONY_ATTACK_MISSION: \"ШТУРМ КОЛОНИИ ПРИШЕЛЬЦЕВ\"\n  STR_ALIEN_BASE_ASSAULT: \"КОЛОНИЯ ПРИШЕЛЬЦЕВ ЧАСТЬ 1\"\n  STR_ALIEN_COLONY_P1_BRIEFING: \"Вы нападаете на колонию пришельцев. Задание состоит из двух частей; чтобы перейти на следующий уровень, подведите всех акванавтов к светящемуся выходу из первого комплекса и нажмите кнопку \\\"Покинуть поле боя\\\". Все брошенное снаряжение останется лежать на морском дне до победы на втором уровне. Чтобы выйти, верните акванавтов в субмарину и нажмите кнопку \\\"Покинуть поле боя\\\".\"\n  STR_ALIEN_COLONY_P2: \"КОЛОНИЯ ПРИШЕЛЬЦЕВ ЧАСТЬ 2\"\n  STR_ALIEN_COLONY_P2_BRIEFING: \"Преодолев первый уровень, вы вошли в ядро колонии. Цель задания: уничтожить центр управления - синомиумное устройство - или устранить всех пришельцев. Чтобы прервать задание, верните всех акванавтов в исходную точку и нажмите кнопку \\\"Покинуть поле боя\\\". Все пригодное оборудование X-Com будет возвращено на базу.\"\n  STR_ALIENS_LAUNCH_PORT_TERROR: \"ПРИШЕЛЬЦЫ НАПАЛИ{NEWLINE}НА ПОРТ\"\n  STR_PORT_TERROR: \"НАПАДЕНИЕ ПРИШЕЛЬЦЕВ НА ПОРТ\"\n  STR_PORT_TERROR_BRIEFING: \"Пришельцы напали на сооружения на суше. Порт и его гражданское население в опасности. Ваш взвод должен уничтожить всех пришельцев и защитить население от вторжения. Чтобы выйти, верните акванавтов в субмарину и нажмите кнопку \\\"Покинуть поле боя\\\".\"\n  STR_ALIENS_LAUNCH_ISLAND_TERROR: \"ПРИШЕЛЬЦЫ НАПАЛИ{NEWLINE}НА ОСТРОВ\"\n  STR_ISLAND_TERROR: \"НАПАДЕНИЕ ПРИШЕЛЬЦЕВ НА ОСТРОВ\"\n  STR_ISLAND_TERROR_BRIEFING: \"Пришельцы напали на сооружения на суше. Порт и его гражданское население в опасности. Ваш взвод должен уничтожить всех пришельцев и защитить население от вторжения. Чтобы выйти, верните акванавтов в субмарину и нажмите кнопку \\\"Покинуть поле боя\\\".\"\n  STR_ALIENS_ATTACK_SHIPPING_ROUTE: \"ПРИШЕЛЬЦЫ НАПАЛИ{NEWLINE}НА МОРСКИЕ ПУТИ\"\n  STR_CARGO_SHIP_P1: \"ГРУЗОВОЙ КОРАБЛЬ ЧАСТЬ 1\"\n  STR_CARGO_SHIP_P2: \"ГРУЗОВОЙ КОРАБЛЬ ЧАСТЬ 2\"\n  STR_CRUISE_SHIP_P1: \"КРУИЗНЫЙ ЛАЙНЕР ЧАСТЬ 1\"\n  STR_CRUISE_SHIP_P2: \"КРУИЗНЫЙ ЛАЙНЕР ЧАСТЬ 2\"\n  STR_SHIP_RESCUE_MISSION: \"МИССИЯ СПАСЕНИЯ КОРАБЛЯ\"\n  STR_SHIP_RESCUE_P1_BRIEFING: \"Ваше задание - охота на пришельцев. Необходимо устранить всех пришельцев и сохранить жизни гражданских, находящихся на борту. Пришельцы рассредоточены по верхним и нижним палубам. Перед спуском на нижние палубы необходимо очистить верхние. Чтобы выйти, верните акванавтов в субмарину и нажмите кнопку \\\"Покинуть поле боя\\\".\"\n  STR_SHIP_RESCUE_P2_BRIEFING: \"Теперь, когда верхняя палуба очищена,  спускайтесь на нижние. Через грузовой лифт вы попадете в трюм. Чтобы выполнить задание, ваш взвод должен уничтожить всех пришельцев на этом уровне. Чтобы прервать задание, верните всех акванавтов в лифт и нажмите кнопку \\\"Покинуть поле боя\\\".\"\n  STR_ALIEN_ACTIVITY_DETECTED: \"ОБНАРУЖЕНА АКТИВНОСТЬ ПРИШЕЛЬЦЕВ\"\n  STR_ALIEN_CONTACT_SITE_MISSION: \"ШТУРМ БАЗЫ СВЯЗИ\"\n  STR_ARTIFACT_SITE_P1: \"БАЗА СВЯЗИ ЧАСТЬ 1\"\n  STR_ARTIFACT_SITE_P1_BRIEFING: \"Ваше задание - штурм недавно запущенного коммуникационного комплекса пришельцев. Задание состоит из двух частей: морское дно с пирамидами и скрытая база пришельцев. Чтобы перейти на второй уровень, подведите всех акванавтов к входу в комплекс и нажмите кнопку \\\"Покинуть поле боя\\\". Чтобы прервать миссию, верните акванавтов в субмарину и нажмите кнопку \\\"Покинуть поле боя\\\".\"\n  STR_ARTIFACT_SITE_P2: \"БАЗА СВЯЗИ ЧАСТЬ 2\"\n  STR_ARTIFACT_SITE_P2_BRIEFING: \"Теперь, когда оборона пришельцев преодолена и мы вошли в комплекс, цели ясны. Чтобы выполнить задание, проникните в сердце комплекса и уничтожьте синомиумное устройство молекулярного контроля. Чтобы прервать задание, верните всех акванавтов во входной лифт и нажмите кнопку \\\"Покинуть поле боя\\\".\"\n  STR_SIGSBEE_DEEP_MISSION: \"МИССИЯ В СИГСБИ, ГЛУБОКО ПОД ВОДОЙ{NEWLINE}ГОРОД ПРИШЕЛЬЦЕВ УРОВЕНЬ ПЕРВЫЙ\"\n  STR_TLETH_P1_BRIEFING: \"Мы стоим перед лицом неизвестности. С этой минуты нас может ждать всё что угодно. Все, что нам известно: город пришельцев трехуровневый, и ваш взвод должен прорваться к выходу, чтобы перейти на следующий уровень. Подведите всех акванавтов к выходу и нажмите на кнопку \\\"Покинуть поле боя\\\". Выход из боя в любом другом месте равносилен поражению.\"\n  STR_TLETH_ATTACK_MISSION: \"ШТУРМ Т'ЛЬЕХА{NEWLINE}ГОРОД ПРИШЕЛЬЦЕВ УРОВЕНЬ ВТОРОЙ\"\n  STR_TLETH_P2_BRIEFING: \"Мы идем еще дальше в неизвестность и все так же не можем предположить развитие событий. Мы только знаем, что в городе пришельцев есть ещё один уровень, и ваш взвод должен прорваться к выходу, чтобы перейти на следующий уровень. Подведите всех акванавтов к выходу и после этого нажмите кнопку \\\"Покинуть поле боя\\\". Выход из боя в любом другом месте равносилен поражению.\"\n  STR_FINAL_TLETH_MISSION: \"ФИНАЛЬНАЯ МИССИЯ В Т'ЛЬЕХЕ{NEWLINE}ГОРОД ПРИШЕЛЬЦЕВ УРОВЕНЬ ТРЕТИЙ\"\n  STR_TLETH_P3_BRIEFING: \"Конец близок. С этого момента мы ищем склеп с Верховным Пришельцем. Уничтожьте все 8 питающих склеп модулей, чтобы ликвидировать инопланетную угрозу. Сдаваться нельзя! Выход из боя равносилен поражению.\"\n  STR_TLETH_P1: \"ПЕРВЫЙ УРОВЕНЬ ГОРОДА ПРИШЕЛЬЦЕВ\"\n  STR_TLETH_P2: \"ВТОРОЙ УРОВЕНЬ ГОРОДА ПРИШЕЛЬЦЕВ\"\n  STR_TLETH_P3: \"ТРЕТИЙ УРОВЕНЬ ГОРОДА ПРИШЕЛЬЦЕВ\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"НЕТ СВОБОДНОГО ДОКА ДЛЯ СТРОИТЕЛЬСТВА!{SMALLLINE}Каждая субмарина, приписанная к базе, транспортируемая на базу, приобретённая или строящаяся на базе, использует один док. Постройте новый док или переправьте судно на другую базу.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"НЕТ СВОБОДНОГО ДОКА ДЛЯ ПОКУПКИ!{SMALLLINE}Каждая субмарина, приписанная к базе, транспортируемая на базу, приобретённая или строящаяся на базе, использует один док. Постройте новый док или переправьте судно на другую базу.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"НЕТ СВОБОДНОГО ДОКА ДЛЯ ТРАНСПОРТИРОВКИ!{SMALLLINE}Каждая субмарина, приписанная к базе, транспортируемая на базу, приобретённая или строящаяся на базе, использует один док. Постройте новый док или переправьте судно на другую базу.\"\n  STR_CANNOT_BUILD_HERE: \"НЕЛЬЗЯ СТРОИТЬ ЗДЕСЬ!{SMALLLINE}Строительство возможно только рядом с уже существующим отсеком.\"\n  STR_NO_FREE_ACCOMODATION: \"НЕТ СВОБОДНОГО ЖИЛЬЯ!{SMALLLINE}На базе назначения не хватает мест в жилых модулях.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"НЕДОСТАТОЧНО РАБОЧЕГО ПРОСТРАНСТВА!{SMALLLINE}Постройте новую мастерскую или сократите работы над другими проектами.\"\n  STR_NOT_ENOUGH_MONEY: \"НЕ ХВАТАЕТ ДЕНЕГ!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"НЕДОСТАТОЧНО МЕСТА НА СКЛАДЕ!{SMALLLINE}Постройте новые склады или перевезите складируемое на другие базы.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"НЕ ХВАТАЕТ МЕСТ В ЖИЛЫХ МОДУЛЯХ!{SMALLLINE}Постройте жилые модули или переправьте персонал на другие базы.\"\n  STR_LAUNCH_INTERCEPTION: \"ЗАПУСТИТЬ ПЕРЕХВАТЧИК\"\n  STR_CRAFT: \"КОРАБЛЬ\"\n  STR_STATUS: \"СТАТУС\"\n  STR_BASE: \"БАЗА\"\n  STR_READY: \"ГОТОВ\"\n  STR_OUT: \"НА ЗАДАНИИ\"\n  STR_REPAIRS: \"РЕМОНТ\"\n  STR_REFUELLING: \"ЗАПРАВКА\"\n  STR_REARMING: \"ПЕРЕЗАРЯДКА\"\n  STR_TARGET: \"ЦЕЛЬ: {0}\"\n  STR_WAY_POINT: \"ПУТЕВАЯ ТОЧКА\"\n  STR_ARE_YOU_SURE_CYDONIA: \"Вы уверены, что хотите послать экспедицию в Т'льех?\"\n  STR_YES: \"ДА\"\n  STR_NO: \"НЕТ\"\n  STR_SELECT_DESTINATION: \"ВЫБЕРИТЕ ЦЕЛЬ\"\n  STR_CYDONIA: \"Т'ЛЬЕХ\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"ВЫБЕРИТЕ МЕСТО ДЛЯ НОВОЙ БАЗЫ\"\n  STR_RETURN_TO_BASE: \"ВЕРНУТЬСЯ НА БАЗУ\"\n  STR_SELECT_NEW_TARGET: \"ВЫБРАТЬ НОВУЮ ЦЕЛЬ\"\n  STR_PATROL: \"ПАТРУЛИРОВАТЬ\"\n  STR_STATUS_: \"СТАТУС>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"ПОВРЕЖДЕН - ВОЗВРАЩАЮСЬ НА БАЗУ\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"МАЛО ТОПЛИВА - ВОЗВРАЩАЮСЬ НА БАЗУ\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"МИССИЯ ВЫПОЛНЕНА - ВОЗВРАЩАЮСЬ НА БАЗУ\"\n  STR_PATROLLING: \"ПАТРУЛИРОВАНИЕ\"\n  STR_TAILING_UFO: \"ПРЕСЛЕДОВАНИЕ СУДНА ПРИШЕЛЬЦЕВ\"\n  STR_INTERCEPTING_UFO: \"ПЕРЕХВАТ СУДНА-{0}\"\n  STR_RETURNING_TO_BASE: \"ВОЗВРАЩЕНИЕ НА БАЗУ\"\n  STR_DESTINATION_UC_: \"ПУНКТ НАЗНАЧЕНИЯ: {0}\"\n  STR_BASE_UC: \"БАЗА>{ALT}{0}\"\n  STR_SPEED_: \"СКОРОСТЬ>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"МАКС. СКОРОСТЬ>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"ГЛУБИНА>{ALT}{0}\"\n  STR_AIRBORNE: \"В ВОЗДУХЕ\"\n  STR_VERY_LOW: \"МАЛ. ГЛУБИНА\"\n  STR_LOW_UC: \"ОБЫЧ. ГЛУБИНА\"\n  STR_HIGH_UC: \"ГЛУБОКО\"\n  STR_VERY_HIGH: \"ОЧ. ГЛУБОКО\"\n  STR_FUEL: \"ТОПЛИВО>{ALT}{0}\"\n  STR_WEAPON_ONE: \"ОРУЖИЕ-1>{ALT}{0}\"\n  STR_NONE_UC: \"НЕТ\"\n  STR_ROUNDS_: \"БОЕЗАПАС>{ALT}{0}\"\n  STR_WEAPON_TWO: \"ОРУЖИЕ-2>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"СУБМАРИНА\"\n  STR_BASE_: \"База>{0}\"\n  STR_NAME_UC: \"ИМЯ\"\n  STR_AMMO_: \"БОЕЗАПАС>{ALT}{0}\"\n  STR_CREW: \"ЭКИПАЖ\"\n  STR_EQUIPMENT_UC: \"СНАРЯЖЕНИЕ\"\n  STR_ARMOR: \"БРОНЯ\"\n  STR_MAX: \"МАКС>{ALT}{0}\"\n  STR_ROOKIE: \"Матрос\"\n  STR_SQUADDIE: \"Старший матрос\"\n  STR_SERGEANT: \"Мичман\"\n  STR_CAPTAIN: \"Лейтенант\"\n  STR_COLONEL: \"Командующий\"\n  STR_COMMANDER: \"Капитан\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"{0}: Экипаж и пассажиры\"\n  STR_SORT_BY: \"СОРТИРОВКА\"\n  STR_ORIGINAL_ORDER: \"ОБЫЧНЫЙ ПОРЯДОК\"\n  STR_MISSIONS2: \"МИССИИ\"\n  STR_KILLS2: \"УБИЙСТВ\"\n  STR_WOUND_RECOVERY2: \"ЛЕЧЕНИЕ\"\n  STR_SPACE_AVAILABLE: \"МЕСТА ДОСТУПНО>{ALT}{0}\"\n  STR_SPACE_USED: \"МЕСТА ЗАНЯТО>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"  МЕСТА\"\n  STR_RANK: \"ЗВАНИЕ\"\n  STR_WOUNDED: \"РАНЕНИЕ\"\n  STR_EQUIPMENT_FOR_CRAFT: \"{0}: Техника и снаряжение\"\n  STR_DEFENSE_VALUE: \"Степень защиты\"\n  STR_HIT_RATIO: \"Точность\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}готов{NEWLINE}высадить десант.{NEWLINE}Место:{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"Начать операцию?\"\n  STR_SELECT_ARMAMENT: \"Выберите оружие\"\n  STR_AMMUNITION_AVAILABLE: \"{NEWLINE}БОЕЗАПАС\"\n  STR_ARMAMENT: \"ОРУЖИЕ\"\n  STR_NOT_AVAILABLE: \"НЕТ\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"{0}{NEWLINE}ВЫБЕРИТЕ БРОНЮ\"\n  STR_TYPE: \"ТИП\"\n  STR_PLASTIC_AQUA_ARMOR_UC: \"ПЛАСТИКОВЫЙ СКАФАНДР\"\n  STR_ION_ARMOR_UC: \"ИОННЫЙ СКАФАНДР\"\n  STR_MAGNETIC_ION_ARMOR_UC: \"МАГН.-ИОННЫЙ СКАФАНДР\"\n  STR_PLASTIC_AQUA_ARMOR_UFOPEDIA: \"В этом скафандре применяется недавно открытое внеземное вещество - аквапластик. Он дарит нашим акванавтам шанс выжить в борьбе с пришельцами.\"\n  STR_ION_ARMOR_UFOPEDIA: \"Новая мощная защита для акванавтов. Эта броня оснащена ионным энергетическим источником, что позволяет значительно увеличить скорость и силу владельца. На настоящий момент она обеспечивает максимальную защиту бойцов.\"\n  STR_MAGNETIC_ION_ARMOR_UFOPEDIA: \"Улучшенная версия ионного скафандра, в которой используется технология магнитных массивов, что обеспечивает полную свободу передвижения в водной среде.\"\n  STR_SELECT_ARMOR: \"Выберите броню\"\n  STR_NORTH: \"СЕВЕР\"\n  STR_NORTH_EAST: \"СЕВ.-ВОСТ.\"\n  STR_EAST: \"ВОСТОК\"\n  STR_SOUTH_EAST: \"ЮГО-ВОСТ.\"\n  STR_SOUTH: \"ЮГ\"\n  STR_SOUTH_WEST: \"ЮГО-ЗАП.\"\n  STR_WEST: \"ЗАПАД\"\n  STR_NORTH_WEST: \"СЕВ.-ЗАП.\"\n  STR_SELECT_ACTION: \"ВЫБЕРИТЕ ДЕЙСТВИЕ\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"ПРОДОЛЖИТЬ ПРЕСЛЕДОВАНИЕ\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"ПРЕСЛЕДОВАТЬ БЕЗ ПЕРЕХВАТА\"\n  STR_VERY_LARGE: \"ОЧ. БОЛЬШ.\"\n  STR_LARGE: \"БОЛЬШОЙ\"\n  STR_MEDIUM_UC: \"СРЕДНИЙ\"\n  STR_SMALL: \"МАЛЕНЬКИЙ\"\n  STR_VERY_SMALL: \"ОЧ. МАЛ.\"\n  STR_GROUNDED: \"НА ДНЕ\"\n  STR_DETECTED: \"Обнаружено\"\n  STR_SIZE_UC: \"РАЗМЕР\"\n  STR_ALTITUDE: \"ГЛУБИНА\"\n  STR_HEADING: \"НАПРАВЛ.\"\n  STR_SPEED: \"СКОРОСТЬ\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"ФОКУС НА СУДНЕ, ВРЕМЯ=5 сек.\"\n  STR_TRACKING_LOST: \"ВНЕ ЗОНЫ РАДАРА\"\n  STR_REDIRECT_CRAFT: \"ПЕРЕНАПРАВИТЬ СУДНО\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"К ПОСЛЕДНЕЙ ИЗВЕСТНОЙ ПОЗИЦИИ СУДНА\"\n  STR_UFO_: \"ИНОПЛ. СУДНО-{0}\"\n  STR_ALIEN_BASE_: \"КОЛОНИЯ ПРИШЕЛЬЦЕВ-{0}\"\n  STR_CRASH_SITE_: \"МЕСТО КРУШЕНИЯ-{0}\"\n  STR_LANDING_SITE_: \"МЕСТО ПОСАДКИ-{0}\"\n  STR_WAY_POINT_: \"ПУТЕВАЯ ТОЧКА-{0}\"\n  STR_TERROR_SITE: \"МЕСТО ТЕРРОРА-{0}\"\n  STR_ARTIFACT_SITE: \"МЕСТО АРТЕФАКТА-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"Судно {0}{NEWLINE}достигло места{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"Патрулирует\"\n  STR_ALIEN_ORIGINS: \"Происхождение пришельцев\"\n  STR_THE_ULTIMATE_THREAT: \"Главная угроза\"\n  STR_TLETH_ALIEN_CITY: \"Т'льех, город пришельцев\"\n  STR_UFOPAEDIA: \"УФОпедия\"\n  STR_XCOM_CRAFT_ARMAMENT: \"КОРАБЛИ X-COM И ВООРУЖЕНИЕ\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"ПОДВОДНЫЕ СИСТЕМЫ ВООРУЖЕНИЯ\"\n  STR_WEAPONS_AND_EQUIPMENT: \"ОСНОВНОЕ СНАРЯЖЕНИЕ\"\n  STR_ALIEN_ARTIFACTS: \"ПОДВОДНЫЕ АРТЕФАКТЫ\"\n  STR_BASE_FACILITIES: \"МОДУЛИ X-COM\"\n  STR_ALIEN_LIFE_FORMS: \"ПРИШЕЛЬЦЫ\"\n  STR_ALIEN_RESEARCH_UC: \"ТЕХНОЛОГИИ ПРИШЕЛЬЦЕВ\"\n  STR_UFO_COMPONENTS: \"НОВЫЕ ПОДВОДНЫЕ ТЕХНОЛОГИИ\"\n  STR_UFOS: \"СУДА ПРИШЕЛЬЦЕВ\"\n  STR_SELECT_ITEM: \"ВЫБЕРИТЕ СТАТЬЮ\"\n  STR_ACCELERATION: \"УСКОРЕНИЕ>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"ЗАПАС ТОПЛИВА>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"ТОЧЕК ПОДВЕСКИ ОРУЖИЯ>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"ЗАПАС ПРОЧНОСТИ>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"ОБЪЕМ ГРУЗОВОГО ОТСЕКА>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"КОЛИЧЕСТВО ПБС>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Урон\"\n  STR_RANGE: \"Дальность\"\n  STR_KILOMETERS: \"{0} км\"\n  STR_ACCURACY: \"Точность\"\n  STR_RE_LOAD_TIME: \"Время перезарядки\"\n  STR_SECONDS: \"{0}с\"\n  STR_DAMAGE_ARMOR_PIERCING: \"БРОНЕБОЙНЫЙ\"\n  STR_DAMAGE_INCENDIARY: \"ФОСФОРНЫЙ\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"ФУГАСНЫЙ\"\n  STR_DAMAGE_LASER_BEAM: \"ПОТОК ГАУССА\"\n  STR_DAMAGE_PLASMA_BEAM: \"АКУСТ. ПОТОК\"\n  STR_DAMAGE_STUN: \"ЗАМОРОЗКА\"\n  STR_DAMAGE_MELEE: \"БЛИЖНИЙ БОЙ\"\n  STR_DAMAGE_ACID: \"КИСЛОТА\"\n  STR_DAMAGE_SMOKE: \"ДЫМ\"\n  STR_SHOT_TYPE: \"ТИП\"\n  STR_ACCURACY_UC: \"ТОЧНОСТЬ\"\n  STR_TIME_UNIT_COST: \"ЦЕНА ОД\"\n  STR_DAMAGE_UC: \"УРОН\"\n  STR_AMMO: \"БОЕЗАПАС\"\n  STR_SHOT_TYPE_AUTO: \"Очередь\"\n  STR_SHOT_TYPE_SNAP: \"Навскидку\"\n  STR_SHOT_TYPE_AIMED: \"Прицельный\"\n  STR_CONSTRUCTION_TIME: \"Время постройки\"\n  STR_CONSTRUCTION_COST: \"Стоимость постройки\"\n  STR_MAINTENANCE_COST: \"Стоимость содержания\"\n  STR_LOW: \"Низкая\"\n  STR_MEDIUM: \"Средняя\"\n  STR_HIGH: \"Высокая\"\n  STR_CRAFT_WEAPON: \"Корабельное оружие\"\n  STR_CRAFT_AMMUNITION: \"Корабельный боезапас\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Тяжелая боевая система\"\n  STR_WEAPON: \"Оружие\"\n  STR_AMMUNITION: \"Боеприпасы\"\n  STR_EQUIPMENT: \"Снаряжение\"\n  STR_ALIEN_CORPSE: \"Труп пришельца\"\n  STR_UFO_COMPONENT: \"Компонент СУДНА ПРИШЕЛЬЦЕВ\"\n  STR_PERSONAL_ARMOR: \"Персональная защита\"\n  STR_RAW_MATERIALS: \"Исходные материалы\"\n  STR_HWP_SOLID_HARPOON_BOLTS: \"Цельные гарпунные стрелы\"\n  STR_ALIEN: \"Пришелец\"\n  STR_AQUATOID: \"Акватоид\"\n  STR_GILLMAN: \"Гиллмен\"\n  STR_LOBSTERMAN: \"Лобстермен\"\n  STR_TASOTH: \"Тасот\"\n  STR_CALCINITE: \"Кальцинит\"\n  STR_DEEP_ONE: \"Глубинный\"\n  STR_BIODRONE: \"Биодрон\"\n  STR_TENTACULAT: \"Тентакулат\"\n  STR_TRISCENE: \"Трисцен\"\n  STR_HALLUCINOID: \"Галлюциноид\"\n  STR_XARQUID: \"Ксарквид\"\n  STR_ZOMBIE: \"Зомби\"\n  STR_LIVE_COMMANDER: \"Командующий\"\n  STR_LIVE_NAVIGATOR: \"Навигатор\"\n  STR_LIVE_MEDIC: \"Медик\"\n  STR_LIVE_TECHNICIAN: \"Техник\"\n  STR_LIVE_SQUAD_LEADER: \"Лидер\"\n  STR_LIVE_SOLDIER: \"Солдат\"\n  STR_LIVE_TERRORIST: \"Террорист\"\n  STR_AQUATOID_COMMANDER: \"Акватоид-командующий\"\n  STR_AQUATOID_NAVIGATOR: \"Акватоид-навигатор\"\n  STR_AQUATOID_MEDIC: \"Акватоид-медик\"\n  STR_AQUATOID_TECHNICIAN: \"Акватоид-техник\"\n  STR_AQUATOID_SQUAD_LEADER: \"Акватоид-лидер\"\n  STR_AQUATOID_SOLDIER: \"Акватоид-солдат\"\n  STR_GILLMAN_COMMANDER: \"Гиллмен-командующий\"\n  STR_GILLMAN_TECHNICIAN: \"Гиллмен-техник\"\n  STR_GILLMAN_SQUAD_LEADER: \"Гиллмен-лидер\"\n  STR_GILLMAN_SOLDIER: \"Гиллмен-солдат\"\n  STR_LOBSTERMAN_COMMANDER: \"Лобстермен-командующий\"\n  STR_LOBSTERMAN_NAVIGATOR: \"Лобстермен-навигатор\"\n  STR_LOBSTERMAN_TECHNICIAN: \"Лобстермен-техник\"\n  STR_LOBSTERMAN_SQUAD_LEADER: \"Лобстермен-лидер\"\n  STR_LOBSTERMAN_SOLDIER: \"Лобстермен-солдат\"\n  STR_TASOTH_SQUAD_LEADER: \"Тасот-лидер\"\n  STR_TASOTH_SOLDIER: \"Тасот-солдат\"\n  STR_CALCINITE_TERRORIST: \"Кальцинит-террорист\"\n  STR_DEEP_ONE_TERRORIST: \"Глубинный-террорист\"\n  STR_BIODRONE_TERRORIST: \"Биодрон-террорист\"\n  STR_TENTACULAT_TERRORIST: \"Тентакулат-террорист\"\n  STR_TRISCENE_TERRORIST: \"Трисцен-террорист\"\n  STR_HALLUCINOID_TERRORIST: \"Галлюциноид-террорист\"\n  STR_XARQUID_TERRORIST: \"Ксарквид-террорист\"\n  STR_ION_BEAM_ACCELERATORS: \"Ионно-лучевые ускорители\"\n  STR_MAGNETIC_NAVIGATION: \"Магнитная навигация\"\n  STR_ALIEN_SUB_CONSTRUCTION: \"Конструкция судна пришельцев\"\n  STR_ALIEN_CRYOGENICS: \"Криогеника пришельцев\"\n  STR_ALIEN_CLONING: \"Клонирование пришельцев\"\n  STR_ALIEN_LEARNING_ARRAYS: \"Обучающие матрицы пришельцев\"\n  STR_ALIEN_IMPLANTER: \"Имплантационная пришельцев\"\n  STR_EXAMINATION_ROOM: \"Комната допроса\"\n  STR_AQUA_PLASTICS: \"Аквапластик\"\n  STR_ALIEN_REANIMATION_ZONE: \"Зона реанимации пришельцев\"\n  STR_PLASTIC_AQUA_ARMOR: \"Пластиковый скафандр\"\n  STR_ION_ARMOR: \"Ионный скафандр\"\n  STR_MAGNETIC_ION_ARMOR: \"Маг.-ионный скафандр\"\n  STR_HWP_AQUA_JET_MISSILES: \"Гидрореактивные торпеды\"\n  STR_HWP_DISPLACER_PWT: \"И.-В. торпеда\"\n  STR_GAUSS_TECH: \"Технологии Гаусса\"\n  STR_NEW_FIGHTER_FLYING_SUB: \"Новое боевое судно\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Новое транспортно-боевое судно\"\n  STR_THE_LATEST_FLYING_SUB: \"Новейшая субмарина\"\n  STR_ARMOR_PIERCING: \"БРОНЕБОЙНЫЙ\"\n  STR_COELACANTH_GAS_CANNON: \"Целакант/Газ.пушка\"\n  STR_COELACANTH_AQUA_JET: \"Целакант/Торпедный\"\n  STR_COELACANTH_GAUSS: \"Целакант/Гаусс\"\n  STR_DISPLACER_SONIC: \"Вытеснитель/Акуст.\"\n  STR_DISPLACER_PWT: \"Вытеснитель/ИВТ\"\n  STR_AJAX_LAUNCHER: \"Пусковая установка \\\"Аякс\\\"\"\n  STR_DUP_HEAD_LAUNCHER: \"Пусковая установка СОУ\"\n  STR_CRAFT_GAS_CANNON: \"Корабельная газ. пушка\"\n  STR_PWT_CANNON: \"ИВТ-пушка\"\n  STR_GAUSS_CANNON: \"Пушка Гаусса\"\n  STR_GAUSS_CANNON_AMMO: \"Боеприпасы к пушке Гаусса\"\n  STR_SONIC_OSCILLATOR: \"Акустический осциллятор\"\n  STR_AJAX_TORPEDOES: \"Торпеды \\\"Аякс\\\"\"\n  STR_DUP_HEAD_TORPEDOES: \"Торпеды с боеголовкой СОУ\"\n  STR_CRAFT_GAS_CANNON_ROUNDS_X50: \"Газовые снаряды (x50)\"\n  STR_SONIC_WAVE: \"Акустическая волна\"\n  STR_PULSE_WAVE_TORPEDOES: \"И.-В. торпеды\"\n  STR_SOLDIER: \"Акванавт\"\n  STR_SCIENTIST: \"Ученый\"\n  STR_ENGINEER: \"Техник\"\n  STR_NORTH_ATLANTIC: \"Сев. Атлантика\"\n  STR_SOUTH_ATLANTIC: \"Южная Атлантика\"\n  STR_NORTH_PACIFIC: \"Север Тих. океана\"\n  STR_SOUTH_PACIFIC: \"Юг Тихого океана\"\n  STR_MEDITERRANEAN: \"Средизем. море\"\n  STR_SOUTH_CHINA_SEA: \"Южно-Кит. море\"\n  STR_INDIAN_OCEAN: \"Индийский океан\"\n  STR_THE_EAST_SEA: \"Японское море\"\n  STR_NORTH_SEA: \"Северное море\"\n  STR_CARRIBEAN: \"Карибы\"\n  STR_ANTARCTIC: \"Антарктика\"\n  STR_ARCTIC: \"Арктика\"\n  STR_EURASIA: \"Евразия\"\n  STR_NORTH_AMERICA: \"Северная Америка\"\n  STR_AFRICA: \"Африка\"\n  STR_MAXIMUM_SPEED: \"Макс. скорость\"\n  STR_TRANSMISSION_RESOLVER_UC: \"ДЕШИФРАТОР ПЕРЕДАЧ\"\n  STR_TRITON: \"ТРИТОН\"\n  STR_HAMMERHEAD: \"МОЛОТ\"\n  STR_LEVIATHAN: \"ЛЕВИАФАН\"\n  STR_BARRACUDA: \"БАРРАКУДА\"\n  STR_MANTA: \"МАНТА\"\n  STR_UFO: \"СУДНО ПРИШЕЛЬЦЕВ\"\n  STR_AJAX: \"АЯКС\"\n  STR_DUP_HEAD: \"БОЕГОЛОВКА СОУ\"\n  STR_CRAFT_GAS_CANNON_UC: \"КОРАБЕЛЬНАЯ ГАЗ. ПУШКА\"\n  STR_PWT_CANNON_UC: \"ИВТ-ПУШКА\"\n  STR_GAUSS_CANNON_UC: \"ПУШКА ГАУССА\"\n  STR_SONIC_OSCILLATOR_UC: \"АКУСТ. ОСЦИЛЛЯТОР\"\n  STR_DAMAGE_CAPACITY: \"Запас прочности\"\n  STR_WEAPON_POWER: \"Мощность\"\n  STR_WEAPON_RANGE: \"Дальность оружия\"\n  STR_AIR_LOCK: \"Шлюзовая камера\"\n  STR_LABORATORY: \"Лаборатория\"\n  STR_WORKSHOP: \"Мастерская\"\n  STR_STANDARD_SONAR: \"Стандартный сонар\"\n  STR_WIDE_ARRAY_SONAR: \"Широкополосный сонар\"\n  STR_TORPEDO_DEFENSES: \"Торпедная защита\"\n  STR_GENERAL_STORES: \"Склад\"\n  STR_ALIEN_CONTAINMENT: \"Изолятор пришельцев\"\n  STR_GAUSS_DEFENSES: \"Защита Гаусса\"\n  STR_SONIC_DEFENSES: \"Акустическая защита\"\n  STR_PWT_DEFENSES: \"ИВТ-защита\"\n  STR_BOMBARDMENT_SHIELD: \"Противобомбовый щит\"\n  STR_MC_GENERATOR: \"Генератор М.K.\"\n  STR_MC_LAB: \"Лаборатория М.К.\"\n  STR_TRANSMISSION_RESOLVER: \"Дешифратор передач\"\n  STR_SUB_PEN: \"Док\"\n  STR_USA: \"США\"\n  STR_ALASKA: \"АЛЯСКА\"\n  STR_EU_SYNDICATE: \"ЕВРОСИНДИКАТ\"\n  STR_ARABIAN_BLOC: \"АРАБСКИЙ БЛОК\"\n  STR_EGYPTIAN_CARTEL: \"ЕГИПЕТ. КАРТЕЛЬ\"\n  STR_AFRICA_CORP: \"АФРИК. КОРП.\"\n  STR_BRAZILIAN_UNION: \"БРАЗИЛЬСКИЙ СОЮЗ\"\n  STR_NEW_MEXICO: \"НЬЮ-МЕХИКО\"\n  STR_ASIAN_COALITION: \"АЗИАТ. КОАЛИЦИЯ\"\n  STR_SCANDINAVIA: \"СКАНДИНАВИЯ\"\n  STR_NEO_JAPAN: \"НЕО-ЯПОНИЯ\"\n  STR_FREE_CHINA: \"СВОБОДНЫЙ КИТАЙ\"\n  STR_AUSTRALASIA: \"АВСТРАЛАЗИЯ\"\n  STR_FED_KOREA: \"КОРЕЙСКАЯ ФЕД.\"\n  STR_EURASIA_UC: \"ЕВРАЗИЯ\"\n  STR_ICELANDIC_UNION: \"ИСЛАНДСКИЙ СОЮЗ\"\n  STR_TANK: \"Погружаемая боевая система\"\n  STR_CIVILIAN: \"Гражданский\"\n  STR_JAN: \"янв\"\n  STR_FEB: \"фев\"\n  STR_MAR: \"мар\"\n  STR_APR: \"апр\"\n  STR_MAY: \"мая\"\n  STR_JUN: \"июн\"\n  STR_JUL: \"июл\"\n  STR_AUG: \"авг\"\n  STR_SEP: \"сен\"\n  STR_OCT: \"окт\"\n  STR_NOV: \"ноя\"\n  STR_DEC: \"дек\"\n  STR_INTERNATIONAL_RELATIONS: \"Международные отношения\"\n  STR_COUNTRY: \"Страна\"\n  STR_FUNDING: \"Инвестиции\"\n  STR_CHANGE: \"Изменение\"\n  STR_WEAPON_SYSTEMS: \"СИСТЕМЫ ВООРУЖЕНИЯ\"\n  STR_HWPS: \"ПБС\"\n  STR_DAMAGE_UC_: \"ПОВРЕЖДЕНИЯ>{ALT}{0}\"\n  STR_AIR_LOCK_UFOPEDIA: \"Шлюзовая камера используется для доставки персонала и оборудования на подводную базу. Закладка нового комплекса начинается с постройки этого модуля. Шлюзовая камера уязвима для проникновения потенциального противника.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Каждая жилая область обеспечивает размещение до 50 человек. Эти модули представляют собой нечто вроде основного элемента работоспособной базы.\"\n  STR_LABORATORY_UFOPEDIA: \"В лабораторном блоке могут работать до 50 ученых. Лаборатории оснащены по последнему слову техники для проведения исследований в области материалов, биохимии и вооружений. X-Com имеет доступ к лучшим исследовательским центрам по всему миру, как военным, так и гражданским.\"\n  STR_WORKSHOP_UFOPEDIA: \"Мастерская оборудована всем необходимым для производства снаряжения и техники, разработанных в недрах лабораторий. В каждой мастерской могут одновременно работать до 50 техников, однако производимые единицы также будут занимать некоторое пространство.\"\n  STR_STANDARD_SONAR_UFOPEDIA: \"Стандартная сонарная система имеет эффективный радиус действия 450 километров и связана с геостационарной спутниковой сетью для анализа поверхности. Каждый сканер обнаруживает подводную или воздушную цель с вероятностью 10 % в течение 30 минут.\"\n  STR_WIDE_ARRAY_SONAR_UFOPEDIA: \"Широкополосная сонарная система имеет эффективный радиус действия 700 километров и связана с геостационарной спутниковой сетью для анализа поверхности. Каждый сканер обнаруживает подводную или воздушную цель с вероятностью 20 % в течение 30 минут.\"\n  STR_TORPEDO_DEFENSES_UFOPEDIA: \"Торпедная система обороны обеспечивает защиту против вражеских кораблей, пытающихся проникнуть на базу.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"Все снаряжение, оружейные системы, боеприпасы, добытые материалы и погружаемые боевые системы размещаются на складах, включая оборудование, предназначенное для субмарин.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"Для содержания живых пришельцев требуются тюремные модули. В них поддерживается подходящая для инопланетных существ среда. Кроме того, эти камеры сводят боевой потенциал пришельцев к нулю. В каждом модуле в отдельных камерах может содержаться до 10 пришельцев.\"\n  STR_GAUSS_DEFENSES_UFOPEDIA: \"Противолодочный комплекс Гаусса обеспечивает современную и максимально эффективную защиту от атак враждебных субмарин.\"\n  STR_SONIC_DEFENSES_UFOPEDIA: \"Система защиты на основе акустического осциллятора обеспечивает мощную и эффективную защиту от агрессоров.\"\n  STR_PWT_DEFENSES_UFOPEDIA: \"Импульсно-волновые торпеды обеспечивают наиболее эффективную защиту против атак пришельцев. Эти снаряды снабжены сверхплотными боеголовками, которые способны пробить любую известную броню, а магнитные волны выводят из строя электронную защиту цели.\"\n  STR_BOMBARDMENT_SHIELD_UFOPEDIA: \"Противобомбовый щит не даёт субмаринам пришельцев пришвартоваться к базе, создавая резонирующее поле, которое отталкивает атакующие судна, позволяя средствам защиты сделать повторный залп. На практике это означает удвоение эффективности систем защиты базы. \"\n  STR_MC_GENERATOR_UFOPEDIA: \"Поскольку субмарины пришельцев используют технологию молекулярного контроля для обнаружения присутствия живых существ, использование негативного М.К.-излучателя покроет базу непроницаемым щитом, который собьёт пришельцев с толку и скроет наше присутствие.\"\n  STR_MC_LAB_UFOPEDIA: \"Лаборатория молекулярного контроля может внедрять импланты и обучать до десяти акванавтов одновременно. Импланты хирургически внедряются в черепа акванавтов. Путем долгих тренировок они обучаются использовать их. Полученные навыки задействуются вместе с устройством молекулярного контроля и могут использоваться для проведения соответствующих атак в ходе боя.\"\n  STR_TRANSMISSION_RESOLVER_UFOPEDIA: \"Средства связи инопланетян основаны на использовании построенной пришельцами сети молекулярного контроля. Дешифратор позволяет осуществить перехват и расшифровку передач с субмарин пришельцев. Он отображает тип судна пришельцев, его расовую принадлежность и задание, которое он выполняет.\"\n  STR_SUB_PEN_UFOPEDIA: \"К каждому доку может быть приписана одна субмарина. Док оснащён оборудованием для обслуживания, дозаправки и ремонта подводного флота X-Com. Каждой субмарине, приписанной к базе, должен быть назначен свой док, который не может быть использован для размещения других субмарин, даже если приписанное судно в этот момент находится на задании.\"\n  STR_DART_PISTOL_UFOPEDIA: \"Дротикомёт X-Com - компактное, точное и мощное оружие, снаряжаемое магазином с 12 пустотелыми дротиками. Дротики выстреливаются с помощью газа, находящегося во встроенном в магазин отсеке.\"\n  STR_JET_HARPOON_UFOPEDIA: \"Высокоточное и мощное подводное ружьё, стреляющее пустотелыми стальными гарпунами. Каждый гарпун в 10-зарядной герметичном контейнере оснащён собственным резервуаром с газом.\"\n  STR_GAS_CANNON_UFOPEDIA: \"Эта пушка - настоящий тяжеловес среди всех видов газового оружия, заряжаемый цельнолитыми стержнями, которые также могут оснащаться фугасными или фосфорными боеголовками. Излюбленное оружие опытных акванавтов.\"\n  STR_HYDRO_JET_CANNON_UFOPEDIA: \"Гидрореактивные пушки предназначены для использования тяжелой пехотой. Пушка стреляет мини-торпедами на магниевом топливе. Несмотря на свою мощь, гидрореактивная пушка - неуклюжее и неудобное оружие, действующее только под водой.\"\n  STR_TORPEDO_LAUNCHER_UFOPEDIA: \"По-настоящему тяжелая, эта огромная установка позволяет запускать три типа торпед, каждая из которых имеет собственный двигатель. Это разрушительное оружие имеет только один недостаток - перезарядка осуществляется вручную. Боеприпасы включают торпеды, несущие малый или большой разрывной либо фосфорный заряд. Предназначена для использования только под водой.\"\n  STR_GAUSS_PISTOL_UFOPEDIA: \"В пистолете Гаусса используется новейшая разработка в области современных вооружений - технология ускорения частиц. Это скорострельное и точное оружие, способное вести огонь как над, так и под водой. Гаусс-технология является развитием плазменных технологий, изученных в ходе предыдущей войны.\"\n  STR_GAUSS_PISTOL_CLIP_UFOPEDIA: \"В пистолете Гаусса используется новейшая разработка в области современных вооружений - технология ускорения частиц. Это скорострельное и точное оружие, способное вести огонь как над, так и под водой. Гаусс-технология является развитием плазменных технологий, изученных в ходе предыдущей войны.\"\n  STR_GAUSS_RIFLE_UFOPEDIA: \"Следующий этап развития пистолета Гаусса. Это ружьё, имея сдвоенный ускоритель частиц, способно наносить серьёзный урон. Отказавшись от работающей на базе элерия плазменной системы, мы применили микроускоритель частиц, генерирующий поток антипротонов.\"\n  STR_GAUSS_RIFLE_CLIP_UFOPEDIA: \"Следующий этап развития пистолета Гаусса. Это ружьё, имея сдвоенный ускоритель частиц, способно наносить серьёзный урон. Отказавшись от работающей на базе элерия плазменной системы, мы применили микроускоритель частиц, генерирующий поток антипротонов.\"\n  STR_HEAVY_GAUSS_UFOPEDIA: \"Тяжёлый Гаусс довольно громоздок, но чрезвычайно эффективен. В нем установлено три ускорителя частиц, а потому выстрел из него практически невозможно остановить. Поток антипротонов удерживается внутри оболочки из арсенида галлия, которая при попадании разрушается, высвобождая антиматерию.\"\n  STR_HEAVY_GAUSS_CLIP_UFOPEDIA: \"Тяжёлый Гаусс довольно громоздок, но чрезвычайно эффективен. В нем установлено три ускорителя частиц, а потому выстрел из него практически невозможно остановить. Поток антипротонов удерживается внутри оболочки из арсенида галлия, которая при попадании разрушается, высвобождая антиматерию.\"\n  STR_MAGNA_BLAST_GRENADE_UFOPEDIA: \"Стандартная наступательная граната с точным таймером-взрывателем.\"\n  STR_DYE_GRENADE_UFOPEDIA: \"Чернильные гранаты - оружие двойного назначения, пригодное для обеспечения прикрытия на открытой местности. Граната может применяться как на суше, так и под водой: под водой при взрыве образуется взвесь, подобная чернильному облаку осьминога, а на суше в воздух поднимается плотное облако.\"\n  STR_PARTICLE_DISTURBANCE_GRENADE_UFOPEDIA: \"Сенсорную гранату бросают так же, как и обычную, но взрыв происходит, если рядом с ней было зафиксировано движение. Правильное применение требует особых навыков и тренировок.\"\n  STR_MAGNA_PACK_EXPLOSIVE_UFOPEDIA: \"Изначально эта взрывчатка должна была использоваться только для демонтажных работ. Однако опыт предыдущей войны показал, что подобные заряды мощной взрывчатки - идеальное оружие для уничтожения пришельцев. Радиус действия очень большой, поэтому перед применением удостоверьтесь, что акванавтов в пределах опасной зоны нет.\"\n  STR_PARTICLE_DISTURBANCE_SENSOR_UFOPEDIA: \"В этом новейшем устройстве используется множество детекторов и сложные компьютерные системы для обнаружения движущихся объектов. Нажмите на иконку сенсора на тактическом экране. Выберите пункт 'Сканировать'. Стрелка на экране устройства отображает направление взгляда акванавта (север находится наверху). Только что двигавшиеся объекты отображаются яркими точками, большие точки соответствуют быстродвижущимся или крупным объектам. Неподвижные объекты не отображаются.\"\n  STR_MEDI_KIT_UFOPEDIA: \"При использовании встаньте рядом или (если он без сознания) над пострадавшим акванавтом.{NEWLINE} ЛЕЧЕНИЕ> Ранения отмечены красным. Выберите ранение и нажмите на кнопку. Будет вылечена одна смертельная рана и восстановлено здоровье.{NEWLINE} СТИМУЛЯТОР> Восстанавливает энергию акванавта и выводит его из бессознательного состояния (для этого вы должны стоять над его телом).{NEWLINE} АНАЛЬГЕТИК> Восстанавливает моральное состояние раненного акванавта.\"\n  STR_MC_DISRUPTOR_UFOPEDIA: \"Вершина технологии М.К. Это устройство может использоваться только акванавтами с навыками М.К. Нажмите на разрушитель, выберите тип атаки и укажите цель курсором. Возможны два типа атаки:{NEWLINE} СБОЙ ИМПЛАНТА> В случае успеха противник теряется и может запаниковать.{NEWLINE} КОНТРОЛЬ ИМПЛАНТА> В случае успеха вы получите контроль над противником. \"\n  STR_THERMAL_TAZER_UFOPEDIA: \"Устройство предназначено для парализации заморозкой без летального исхода живого противника при непосредственном контакте.\"\n  STR_VIBRO_BLADE_UFOPEDIA: \"Виброклинок - длинный острый титановый бур, вращающийся со скоростью более 6000 об/мин и способный расколоть даже самую прочную броню. Источник энергии устройства изобретен пришельцами; все наши предыдущие попытки создать такое устройство были обречены на провал: буры вращались слишком медленно или разрывались под давлением.\"\n  STR_THERMIC_LANCE_UFOPEDIA: \"Тепловое копьё - логическое развитие технологии виброклинка: полотно вращается с более высокой скоростью, а источник энергии на зрбайте раскаляет лезвие до такой степени, что оно проходит через броню как горячий нож сквозь масло.\"\n  STR_HEAVY_THERMIC_LANCE_UFOPEDIA: \"Тяжёлое тепловое копьё - более мощная версия обычного теплового копья. Сдвоенный нагреватель и огромная скорость вращения означают, что тяжёлое тепловое копьё фактически невозможно остановить никаким материалом.\"\n  STR_SONIC_CANNON_UFOPEDIA: \"Акустическая пушка является самым мощным из всего семейства акустического оружия. По сравнению с ружьём она оборудована аудиогенератором более широкого диапазона и более крупным камерой реверберации. У пушки также есть система импульсной детонации, которая изменяет ультразвуковую волну путем модуляции для создания более эффективного акустич. удара.\"\n  STR_CANNON_POWER_CLIP_UFOPEDIA: \"Это компактное устройство используется в качестве боеприпаса для акустической пушки. Содержит небольшое количество зрбита.\"\n  STR_SONIC_BLASTA_RIFLE_UFOPEDIA: \"Более мощное акустическое устройство. Даже высокоуглеродистая сталь не выдерживает воздействия этого оружия. Сверхкомпактный волновой передатчик дополнен сверхпроводящим усилителем, увеличивающим мощность этого оружия.\"\n  STR_BLASTA_POWER_CLIP_UFOPEDIA: \"Это небольшое устройство используется в качестве источника энергии для акустического ружья - мощного оружия пришельцев. Содержит небольшое количество зрбита.\"\n  STR_SONIC_PISTOL_UFOPEDIA: \"Акустические пистолеты - оружие пришельцев, основанное на ультразвуковых волнах, которые за несколько секунд могут превратить человеческие кости в желе. Ультразвуковые волны находятся за границами слухового восприятия человека.\"\n  STR_PISTOL_POWER_CLIP_UFOPEDIA: \"Источник энергии для компактного акустического пистолета пришельцев. Содержит небольшое количество зрбита - источника энергии всех технологий пришельцев.\"\n  STR_DISRUPTOR_PULSE_LAUNCHER_UFOPEDIA: \"Эта подводное вооружение пришельцев с управляемым наведением стреляет самодвижущимися \\\"разрушительными зарядами\\\". При использовании этого оружия вы указываете точки траектории, по которым будет следовать заряд. После задания траектории нажмите специальную кнопку пуска.\"\n  STR_DISRUPTOR_AMMO_UFOPEDIA: \"Это устройство - заряд дисруптора, снабжённый бортовым компьютером для осуществления управляемого наведения. Используется для стрельбы из дисрупторной установки.\"\n  STR_THERMAL_SHOK_LAUNCHER_UFOPEDIA: \"Небольшая теплоударная установка, стреляющая химически замораживающими бомбами. Весьма полезна для захвата живых пришельцев.\"\n  STR_THERMAL_SHOK_BOMB_UFOPEDIA: \"Теплоударная бомба применяется для захвата живых людей, но может использоваться и против большинства видов пришельцев. Используется как боеприпас для теплоударной установки.\"\n  STR_SONIC_PULSER_UFOPEDIA: \"Это устройство действует аналогично обычной гранате, однако оно во много раз мощнее. Граната генерирует один мощный звуковой импульс, распространяющийся во все стороны одновременно.\"\n  STR_MC_READER_UFOPEDIA: \"Внутри тел пришельцев мы нашли небольшие, хирургически внедрённые, блоки. Эти управляющие импланты разработаны акватоидами с целью постоянного обеспечивания информацией с поля боя , даже на большом расстоянии. Считыватель молекулярного контроля - это устройство связи, используемое для получения информации прямо из имплантов М.К. X-COM могут использовать это устройство в бою для выяснения характеристик пришельцев. Нажмите на \\\"использовать\\\", а затем по врагу.\"\n  STR_SURVEY_SHIP: \"Корабль наблюдения\"\n  STR_ESCORT: \"Корабль сопровождения\"\n  STR_CRUISER: \"Крейсер\"\n  STR_HEAVY_CRUISER: \"Тяжелый крейсер\"\n  STR_HUNTER: \"Охотник\"\n  STR_BATTLESHIP: \"Линкор\"\n  STR_DREADNOUGHT: \"Дредноут\"\n  STR_FLEET_SUPPLY_CRUISER: \"Крейсер снабжения\"\n  MAP_SEABED: \"Океанское дно\"\n  MAP_PIPES: \"Подводная станция\"\n  MAP_PLANE: \"Разрушенный самолет\"\n  MAP_ATLAN: \"Атлантида\"\n  MAP_MU: \"Храм Майя\"\n  MAP_GAL: \"Затонувший галеон\"\n  MAP_MSUNK: \"Затонувший лайнер\"\n  MAP_VOLC: \"Вулканы\"\n  MAP_CORAL: \"Кораллы\"\n  MAP_PORT: \"Порт\"\n  MAP_ISLAND: \"Остров\"\n  MAP_CARGO: \"Грузовое судно\"\n  MAP_LINERT: \"Круизный лайнер ч.1\"\n  MAP_LINERB: \"Круизный лайнер ч.2\"\n  MAP_ALART: \"Артефакт ч.1\"\n  MAP_GRUNGE: \"Артефакт ч.2\"\n  MAP_ENTRY: \"Колония ч.1\"\n  MAP_A_BASE: \"Колония ч.2\"\n  MAP_ALSHIP: \"Т'льех ч.1\"\n  MAP_LEVEL: \"Т'льех ч.2\"\n  MAP_CRYPT: \"Т'льех ч.3\"\n  MAP_XBASES: \"База X-Com\"\n  STR_MIXED_CREW: \"Смешанная команда\"\n  STR_MIXED_CREW_2: \"Смешанная команда 2\"\n  STR_RATING: \"РЕЙТИНГ> {0}\"\n  STR_RATING_TERRIBLE: \"УЖАСНО!\"\n  STR_RATING_POOR: \"ПЛОХО!\"\n  STR_RATING_OK: \"ОК\"\n  STR_RATING_GOOD: \"ХОРОШО!\"\n  STR_RATING_EXCELLENT: \"ПРЕВОСХОДНО!\"\n  STR_SCORE: \"СЧЕТ\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"ОТЧЕТ X-COM ЗА МЕСЯЦ\"\n  STR_MONTH: \"Месяц> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"Комитет финансирующих организаций в целом удовлетворен вашими действиями.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"Комитет финансирующих организаций очень доволен вашими действиями. Продолжайте в том же духе.\"\n  STR_COUNCIL_IS_DISSATISFIED: \"Комитет финансирующих организаций не удовлетворен вашими результатами. Вы должны улучшить эффективность противодействия инопланетной угрозе, иначе финансовая поддержка проекта X-Com будет прекращена.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"Вам не удалось противостоять вторжению пришельцев, в связи с чем Комитет финансирующих организаций, к сожалению, принял решение о прекратить финансирование X-Com. Каждая организация отныне будет решать эту проблему самостоятельно. Мы можем только надеяться, что сможем как-то примириться с этими древними силами, и что население смирится с сосуществованием с пришельцами из глубин.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} выражает глубокое удовлетворение проведенной вами работой и соглашается увеличить финансирование.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} особенно довольны вашими успехами при отражении нападений пришельцев и договорились увеличить финансирование.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} и {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} выражает неудовлетворенность эффективностью ваших действий по пресечению активности пришельцев в своих территориальных водах, и сокращает финансирование.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} не удовлетворены эффективностью ваших действий по пресечению активности пришельцев в своих территориальных водах, и сокращают финансирование.\"\n  STR_KNOTS: \"{0} узлов\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} заключает соглашение о сотрудничестве с силами пришельцев и прекращает финансирование X-Com.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} заключили соглашение о сотрудничестве с силами пришельцев и прекращают финансирование X-Com.\"\n  STR_MONTHLY_RATING: \"Рейтинг за месяц> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Изменение в финансировании> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"Финансирующая организация недовольна состоянием ваших финансов. Вы должны снизить задолженность до 1 миллиона долл., иначе проект X-Com будет закрыт.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"СУБАТОМНОЕ СООБЩЕНИЕ РАСШИФРОВАНО\"\n  STR_CRAFT_TYPE: \"ТИП СУДНА\"\n  STR_RACE: \"РАСА\"\n  STR_MISSION: \"МИССИЯ\"\n  STR_ZONE: \"РЕГИОН\"\n  STR_ALLOCATE_RESEARCH: \"Новое исследование\"\n  STR_ALLOCATE_MANUFACTURE: \"Произвести\"\n  STR_AZORES: \"Азорские острова\"\n  STR_REYKJAVIK: \"Рейкьявик\"\n  STR_BERMUDA: \"Бермудские острова\"\n  STR_NEW_YORK: \"Нью-Йорк\"\n  STR_BOSTON: \"Бостон\"\n  STR_FORT_SEVERN: \"Порт Северн\"\n  STR_DAKAR: \"Дакар\"\n  STR_RECIFE: \"Ресифи\"\n  STR_ACCRA: \"Аккра\"\n  STR_ASCENSION_ISLAND: \"Остров Вознесения\"\n  STR_TRINIDADE_ISLAND: \"Триндади-э-Мартин-Вас\"\n  STR_FALKLAND_ISLAND: \"Фолкленды\"\n  STR_CANARY_ISLANDS: \"Канарские острова\"\n  STR_ANCHORAGE: \"Анкоридж\"\n  STR_ST_LAWRENCE_ISLAND: \"Остров Святого Лаврентия\"\n  STR_SAN_FRANCISCO: \"Сан-Франциско\"\n  STR_MIDWAY_ISLAND: \"Мидуэй\"\n  STR_VANCOUVER: \"Ванкувер\"\n  STR_TASMANIA: \"Тасмания\"\n  STR_HAWAII: \"Гавайи\"\n  STR_FIJI: \"Фиджи\"\n  STR_TONGA: \"Тонга\"\n  STR_EASTER_ISLAND: \"Остров Пасхи\"\n  STR_GALAPAGOS_ISLAND: \"Галапагосские острова\"\n  STR_WELLINGTON: \"Веллингтон\"\n  STR_SOLOMON_ISLAND: \"Соломоновы острова\"\n  STR_CRETE: \"Крит\"\n  STR_LISBON: \"Лиссабон\"\n  STR_PORT_SAID: \"Порт-Саид\"\n  STR_MARSEILLES: \"Марсель\"\n  STR_TRIPOLI: \"Триполи\"\n  STR_MANILA: \"Манила\"\n  STR_HONG_KONG: \"Гонконг\"\n  STR_SINGAPORE: \"Сингапур\"\n  STR_BANGKOK: \"Бангкок\"\n  STR_DARWIN: \"Дарвин\"\n  STR_BOMBAY: \"Бомбей\"\n  STR_SAYCHELLES_ISLAND: \"Сейшельские острова\"\n  STR_MALDIVE_ISLAND: \"Мальдивские острова\"\n  STR_SRI_LANKA: \"Шри-Ланка\"\n  STR_MAURITIUS: \"Маврикий\"\n  STR_TOKYO: \"Токио\"\n  STR_SHANGHAI: \"Шанхай\"\n  STR_VLADIVOSTOK: \"Владивосток\"\n  STR_LONDON: \"Лондон\"\n  STR_FAEROE_ISLAND: \"Фарерские острова\"\n  STR_ABERDEEN: \"Абердин\"\n  STR_OSLO: \"Осло\"\n  STR_JAMAICA: \"Ямайка\"\n  STR_PANAMA: \"Панама\"\n  STR_MIAMI: \"Майами\"\n  STR_PSI_TRAINING: \"Тренировка М.К.\"\n  STR_PSIONIC_TRAINING: \"ТРЕНИРОВКА МОЛЕКУЛЯРНОГО КОНТРОЛЯ\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Мест в лаборатории М.К.> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"Сила{NEWLINE}МК\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"Навык М.К.{NEWLINE}/Улучшение\"\n  STR_IN_TRAINING: \"Тренир.?{NEWLINE}\"\n  STR_TARGETTED_BY: \"ЦЕЛЬ ДЛЯ:\"\n  STR_WEAPONS_CREW_HWPS: \"ОРУЖИЕ/{NEWLINE}ЭКИПАЖ/БС\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"Топливо на исходе,{NEWLINE}возвращаюсь на базу\"\n  STR_SOLDIER_LIST: \"Список акванавтов\"\n  STR_RANK_: \"ЗВАНИЕ> {ALT}{0}\"\n  STR_MISSIONS: \"МИССИЙ> {ALT}{0}\"\n  STR_KILLS: \"УБИЙСТВ> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"ЛЕЧЕНИЕ> {ALT}{0}\"\n  STR_TIME_UNITS: \"ОЧКИ ДЕЙСТВИЯ\"\n  STR_STAMINA: \"ВЫНОСЛИВОСТЬ\"\n  STR_HEALTH: \"ЗДОРОВЬЕ\"\n  STR_BRAVERY: \"ХРАБРОСТЬ\"\n  STR_REACTIONS: \"РЕАКЦИЯ\"\n  STR_FIRING_ACCURACY: \"ТОЧНОСТЬ ВЫСТРЕЛА\"\n  STR_THROWING_ACCURACY: \"ТОЧНОСТЬ БРОСКА\"\n  STR_STRENGTH: \"СИЛА\"\n  STR_PSIONIC_STRENGTH: \"СИЛА М.К.\"\n  STR_PSIONIC_SKILL: \"НАВЫК М.К.\"\n  STR_NEW_RANK: \"НОВОЕ ЗВАНИЕ\"\n  STR_PROMOTIONS: \"Повышение\"\n  STR_SOLDIERS_UC: \"АКВАНАВТЫ\"\n  STR_COELACANTH_GAS_CANNON_UFOPEDIA: \"ПБС являются высокомобильными и прочными системами поддержки пехоты на любой глубине. Перезарядка ПБС выполняется автоматически при наличии достаточного боекомплекта.\"\n  STR_COELACANTH_AQUA_JET_UFOPEDIA: \"Эта платформа вооружена гидрореактивными торпедами. Она может работать только под водой. Следите, чтобы на складах было наличие гидрореактивных торпед.\"\n  STR_COELACANTH_GAUSS_UFOPEDIA: \"технология Гаусса позволяет создавать мощную оружейную систему для ПБС. Она дает высокую огневую мощь по сравнению с ранними моделями и основана на разработках X-Com.\"\n  STR_DISPLACER_SONIC_UFOPEDIA: \"Технологии пришельцев изменили ПБС. Ионный вытеснитель дал возможность перемещаться не только по дну или суше, но и плавать и летать. А акуст. оружие дает превосходство в бою.\"\n  STR_DISPLACER_PWT_UFOPEDIA: \"Данная ПБС использует подводное импульсно-волновое оружие. Убедитесь, что изготовили необходимое количество ИВТ. Для выстрела укажите точки траектории и нажмите запуск.\"\n  STR_ALIEN_PROBE_MISSION: \"Разведка\"\n  STR_ALIEN_INTERDICTION: \"Блокирование района\"\n  STR_ALIEN_RESOURCE_RAID: \"Поиск ресурсов\"\n  STR_ALIEN_INFILTRATION: \"Инфильтрация\"\n  STR_ALIEN_BASE: \"Расширение колонии\"\n  STR_ALIEN_SURFACE_ATTACK: \"Атаки на суше\"\n  STR_ALIEN_RETALIATION: \"Атака на базу X-Com\"\n  STR_ALIEN_SUPPLY: \"Снабжение колонии\"\n  STR_ALIEN_PROBE_MISSION_UFOPEDIA: \"Разведывательное задание используется для сбора данных относительно морского дна, ресурсов, маршрутов кораблей и самолетов. Участвующие в этих заданиях субмарины пришельцев сами по себе не несут большой угрозы, но они намекают на то, что в этой зоне разворачивается деятельность пришельцев, которая может вспыхнуть в любой момент.\"\n  STR_ALIEN_INTERDICTION_UFOPEDIA: \"Стратегия пришельцев предполагает патрулирование зон их интересов, и прежде чем развернуть более активные действия, они выпускают судно с целью обеспечения охраны этого района. Они прибывают в те места, куда позже предполагают совершить рейд, блокируют район и производят подготовку к следующему этапу их миссии.\"\n  STR_ALIEN_RESOURCE_RAID_UFOPEDIA: \"Затопление кораблей и сбивание самолетов - ключевые элементы стратегии пришельцев. Поиск ресурсов - один из главных их видов деятельности, и как таковой сродни другим откровенно агрессивным актам. Пришельцы также совершают рейды в места геотермической активности, в места залегания минералов и очищенных металлов, а также на древние затонувшие города в поисках предметов и материалов оставленных людьми.\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"Это может привести к налаживанию официального контакта между пришельцами и корпорациями или правительствами на самом высоком уровне. Кульминация этих действий выражается в значительной активности судов пришельцев в водах соответствующей организации. Пришельцы попытаются подписать договор с правительством или организацией, предложив взамен какие-то из своих передовых технологий. Деятельность пришельцев несет большую опасность X-COM. Если корпорация или правительство подписывает с захватчиками договор, она прекращает финансирование X-COM.\"\n  STR_ALIEN_BASE_UFOPEDIA: \"Пришельцы будут создавать секретные подводные колонии в отдалённых районах. После нескольких разведывательных рейсов по мере строительства колонии активность их субмарин заметно усиливается. Известно, что эти колонии содержат лаборатории, центры клонирования, хирургическое оборудование для экспериментов над людьми и пришельцами. Созданные колонии создают повышенную активность и при отсутствии субмарин пришельцев. Чтобы обнаружить колонию в таких местах, судно X-Com должно патрулировать над подозрительной зоной в течение несколько часов.\"\n  STR_ALIEN_SURFACE_ATTACK_UFOPEDIA: \"Когда у пришельцев возникает необходимость в людях, они терроризируют порт, атакуют остров или нападают на корабль. Пришельцы будут открыто нападать на гражданских, используя их для удовлетворения своей извращённой потребности в размножении и жутких экспериментах.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"В случае особо успешных действий перехватчиков X-Com, пришельцы будут предпринимать ответные меры, вплоть до прямой атаки баз X-Com. Однако перед атакой пришельцы сперва должны обнаружить базу, поэтому риск можно существенно снизить, если не подпускать судна пришельцев к базе.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"После окончания строительства колонии пришельцев начинается её регулярное снабжение специальным грузовым кораблем. Обнаружив совершивший высадку корабль, можно быть уверенным, что колония пришельцев расположена где-то неподалеку.\"\n  STR_SURVEY_SHIP_UFOPEDIA: \"Эта крошечная субмарина используется для разведки или наблюдений. Обычно она является предвестником начала миссий более крупных кораблей.\"\n  STR_ESCORT_UFOPEDIA: \"Средний по размеру корабль сопровождения сам по себе не представляет большой опасности. Это судно предшествует более крупным кораблям и повышенной активности пришельцев.\"\n  STR_CRUISER_UFOPEDIA: \"Крейсер - корабль общего назначения, основа флота пришельцев. Пришельцы используют их на заданиях любых типов. Довольно опасный противник.\"\n  STR_HEAVY_CRUISER_UFOPEDIA: \"Тяжелый крейсер - более мощный корабль, нежели обычный крейсер. Он имеет усиленное вооружение и более мощные силовые установки, дающие ему большую скорость. Тяжелый крейсер используется в заданиях поиска ресурсов для переноса большего количества минералов и оборудования.\"\n  STR_HUNTER_UFOPEDIA: \"Этот корабль оборудован исследовательской комнатой для проведения экспериментов и хирургических операций над людьми. Жертвы подвергаются чудовищным пыткам, мозг часто извлекается и сохраняется для последующей обработки.\"\n  STR_BATTLESHIP_UFOPEDIA: \"Линкор - наиболее агрессивный корабль пришельцев. Он оснащён всеми технологиями и системами для того, чтобы действовать как главная ударная сила при выполнении самых разных боевых миссий пришельцев. Он оборудован широким боевым арсеналом.\"\n  STR_DREADNOUGHT_UFOPEDIA: \"Дредноут - боевой супертранспорт, полностью оборудован всеми технологиями пришельцев и повышенной полезной нагрузкой. Дредноут - крепкий и грозный противник.\"\n  STR_FLEET_SUPPLY_CRUISER_UFOPEDIA: \"Корабль снабжения используется при строительстве новых колоний пришельцев а также для снабжения уже существующих. Он перевозит продукты питания, ДНК, эмбрионы и другие биологические компоненты.\"\n  STR_DISMANTLE: \"Демонтировать\"\n  STR_FACILITY_IN_USE: \"ОТСЕК ИСПОЛЬЗУЕТСЯ\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"НЕВОЗМОЖНО ДЕМОНТИРОВАТЬ ОТСЕК!{SMALLLINE}Все отсеки должны быть соединены со шлюзовой камерой.\"\n  STR_TRANSFER_ITEMS_TO: \"Перевозка на базу {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"НЕТ ИЗОЛЯТОРА ПРИШЕЛЬЦЕВ ДЛЯ ПЕРЕДАЧИ!{SMALLLINE}Для содержания живых пришельцев необходим специальный модуль.\"\n  STR_AMOUNT_AT_DESTINATION: \"В ПУНКТЕ{NEWLINE}НАЗНАЧЕНИЯ\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"Пришелец погиб, так как нет модуля для его содержания.\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"НЕДОСТАТОЧНО МЕСТ ДЛЯ РАЗМЕЩЕНИЯ!{SMALLLINE}На базе назначения не хватает мест в жилых модулях для экипажа, назначенного субмарине.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"НЕДОСТАТОЧНО МЕСТА НА СКЛАДЕ!{SMALLLINE}На складе базы назначения не хватает места для снаряжения, назначенного субмарине.\"\n  STR_ITEMS_ARRIVING: \"Прибытие\"\n  STR_DESTINATION_UC: \"ПУНКТ НАЗНАЧЕНИЯ\"\n  STR_DART_PISTOL: \"Дротикомет\"\n  STR_DART_POD: \"Магазин с дротиками\"\n  STR_JET_HARPOON: \"Реактивный гарпун\"\n  STR_HARPOON_POD: \"Магазин с гарпунами\"\n  STR_GAS_CANNON: \"Газовая пушка\"\n  STR_GC_AP_AMMO: \"ГП-ББ заряды\"\n  STR_GC_HE_AMMO: \"ГП-Р заряды\"\n  STR_GC_P_AMMO: \"ГП-Ф заряды\"\n  STR_HYDRO_JET_CANNON: \"Гидрореактивная пушка\"\n  STR_HJC_AP_AMMO: \"ГРП-ББ боеприпасы\"\n  STR_HJC_HE_AMMO: \"ГРП-Р боеприпасы\"\n  STR_HJC_P_AMMO: \"ГРП-Ф боеприпас\"\n  STR_TORPEDO_LAUNCHER: \"Торпедная установка\"\n  STR_SMALL_TORPEDO: \"Малая торпеда\"\n  STR_LARGE_TORPEDO: \"Большая торпеда\"\n  STR_PHOSPHOROUS_TORPEDO: \"Фосфорная торпеда\"\n  STR_MAGNA_BLAST_GRENADE: \"Магниевая граната\"\n  STR_DYE_GRENADE: \"Чернильная граната\"\n  STR_PARTICLE_DISTURBANCE_GRENADE: \"Сенсорная граната\"\n  STR_MAGNA_PACK_EXPLOSIVE: \"Магниевая взрывчатка\"\n  STR_PARTICLE_DISTURBANCE_SENSOR: \"Сенсор микроколебаний\"\n  STR_MEDI_KIT: \"Медкомплект\"\n  STR_MC_DISRUPTOR: \"Разрушитель М.К.\"\n  STR_THERMAL_TAZER: \"Тепловой жезл\"\n  STR_GAUSS_PISTOL: \"Пистолет Гаусса\"\n  STR_GAUSS_PISTOL_CLIP: \"Магазин к пистолету Гаусса\"\n  STR_GAUSS_RIFLE: \"Ружьё Гаусса\"\n  STR_GAUSS_RIFLE_CLIP: \"Магазин к ружью Гаусса\"\n  STR_HEAVY_GAUSS: \"Тяжёлый Гаусс\"\n  STR_HEAVY_GAUSS_CLIP: \"Магазин к тяжёлому Гауссу\"\n  STR_SONIC_CANNON: \"Акустическая пушка\"\n  STR_CANNON_POWER_CLIP: \"Магазин к акустической пушке\"\n  STR_SONIC_BLASTA_RIFLE: \"Акустическое ружьё\"\n  STR_BLASTA_POWER_CLIP: \"Магазин к акустическому ружью\"\n  STR_SONIC_PISTOL: \"Акустический пистолет\"\n  STR_PISTOL_POWER_CLIP: \"Магазин к акустическому пистолету\"\n  STR_DISRUPTOR_PULSE_LAUNCHER: \"Дисрупторная установка\"\n  STR_DISRUPTOR_AMMO: \"Заряд дисруптора\"\n  STR_THERMAL_SHOK_LAUNCHER: \"Теплоударная установка\"\n  STR_THERMAL_SHOK_BOMB: \"Теплоударная бомба\"\n  STR_SONIC_PULSER: \"Акустический импульсатор\"\n  STR_ZRBITE: \"Зрбит\"\n  STR_MC_READER: \"Считыватель М.К.\"\n  STR_VIBRO_BLADE: \"Виброклинок\"\n  STR_THERMIC_LANCE: \"Тепловое копьё\"\n  STR_HEAVY_THERMIC_LANCE: \"Тяжёлое тепловое копьё\"\n  STR_AQUATOID_CORPSE: \"Труп акватоида\"\n  STR_GILLMAN_CORPSE: \"Труп гиллмена\"\n  STR_LOBSTERMAN_CORPSE: \"Труп лобстермена\"\n  STR_TASOTH_CORPSE: \"Труп тасота\"\n  STR_CALCINITE_CORPSE: \"Труп кальцинита\"\n  STR_DEEP_ONE_CORPSE: \"Труп глубинного\"\n  STR_BIODRONE_CORPSE: \"Труп биодрона\"\n  STR_TENTACULAT_CORPSE: \"Труп тентакулата\"\n  STR_TRISCENE_CORPSE: \"Труп трисцена\"\n  STR_HALLUCINOID_CORPSE: \"Труп галлюциноида\"\n  STR_XARQUID_CORPSE: \"Труп ксарквида\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"Недостаточно боеприпасов для снаряжения ПБС{SMALLLINE}Для каждой ПБС необходимо {0} {1}.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Недостаточно снаряжения для экипировки подразделения\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Необходимо исследовать{NEWLINE}{0},{NEWLINE}чтобы производить{NEWLINE}{1}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"Пришельцы разрушили незащищенную базу {0}\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"Патрули X-Com обнаружили колонию пришельцев. Место: {0}\"\n  STR_STANDOFF: \"ОЖИДАНИЕ\"\n  STR_CAUTIOUS_ATTACK: \"ОСТОРОЖНАЯ АТАКА\"\n  STR_STANDARD_ATTACK: \"СТАНДАРТНАЯ АТАКА\"\n  STR_AGGRESSIVE_ATTACK: \"АГРЕССИВНАЯ АТАКА\"\n  STR_DISENGAGING: \"ВЫХОД ИЗ БОЯ\"\n  STR_UFO_HIT: \"ПОПАДАНИЕ!\"\n  STR_UFO_CRASH_LANDS: \"СУДНО ПРИШЕЛЬЦЕВ ЗАТОНУЛО!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Сворачивать только на безопасной дистанции\"\n  STR_UFO_RETURN_FIRE: \"СУДНО ПРИШЕЛЬЦЕВ СТРЕЛЯЕТ!\"\n  STR_INTERCEPTOR_DAMAGED: \">>> СУБМАРИНА X-COM ПОВРЕЖДЕНА <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> СУБМАРИНА X-COM УНИЧТОЖЕНА <<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"СУДНО ПРИШЕЛЬЦЕВ УХОДИТ!\"\n  STR_LONG_RANGE_DETECTION: \"Дальнее обнаружение\"\n  STR_STORES_UC: \"СКЛАД\"\n  STR_DIFFICULTY_LEVEL: \"Уровень сложности\"\n  STR_INTERCEPT: \"ПЕРЕХВАТ\"\n  STR_BASES: \"БАЗЫ\"\n  STR_GRAPHS: \"ГРАФИКИ\"\n  STR_UFOPAEDIA_UC: \"УФОПЕДИЯ\"\n  STR_OPTIONS_UC: \"НАСТРОЙКИ\"\n  STR_FUNDING_UC: \"ФИНАНСЫ\"\n  STR_5_SECONDS: \"5 сек\"\n  STR_1_MINUTE: \"1 мин\"\n  STR_5_MINUTES: \"5 мин\"\n  STR_30_MINUTES: \"30 мин\"\n  STR_1_HOUR: \"1 час\"\n  STR_1_DAY: \"1 день\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"Выполнение заданий X-Com\"\n  STR_ENTER_NAME: \"Введите имя\"\n  STR_PERFORMANCE_RATING: \"Рейтинг результативности\"\n  STR_VICTORY_DATE: \"День Победы\"\n  STR_CHEMICAL_FLARE: \"Химический осветитель\"\n  STR_CHEMICAL_FLARE_UFOPEDIA: \"Это компактное устройство излучает яркий свет на любой глубине, как и на суше. Оно освещает находящихся вблизи противников во время заданий глубоко под водой или в ночное время.\"\n  STR_MONTHLY_COSTS: \"Месячные затраты\"\n  STR_CRAFT_RENTAL: \"Аренда летающих субмарин\"\n  STR_SALARIES: \"Жалованье\"\n  STR_BASE_MAINTENANCE: \"Обслуживание базы\"\n  STR_COST_PER_UNIT: \"Стоимость за ед.\"\n  STR_QUANTITY: \"Кол-во\"\n  STR_TOTAL: \"Всего\"\n  STR_IN_PSIONIC_TRAINING: \"В лаборатории М.К.\"\n  STR_FRONT_ARMOR: \"Броня спереди\"\n  STR_LEFT_ARMOR: \"Броня слева\"\n  STR_RIGHT_ARMOR: \"Броня справа\"\n  STR_REAR_ARMOR: \"Броня сзади\"\n  STR_UNDER_ARMOR: \"Броня снизу\"\n  STR_ROUNDS: \"Боезапас\"\n  STR_UNIT: \"БОЕЦ> {0}\"\n  STR_ENERGY: \"ЭНЕРГИЯ\"\n  STR_MORALE: \"МОРАЛЬ\"\n  STR_ARMOR_: \"БРОНЯ> {0}\"\n  STR_FRONT_ARMOR_UC: \"БРОНЯ СПЕРЕДИ\"\n  STR_LEFT_ARMOR_UC: \"БРОНЯ СЛЕВА\"\n  STR_RIGHT_ARMOR_UC: \"БРОНЯ СПРАВА\"\n  STR_REAR_ARMOR_UC: \"БРОНЯ СЗАДИ\"\n  STR_SKILLS: \"НАВЫКИ> {0}\"\n  STR_LEVEL: \"УРОВЕНЬ> {0}\"\n  STR_HEAD: \"ГОЛОВА\"\n  STR_TORSO: \"ТОРС\"\n  STR_RIGHT_ARM: \"ПРАВАЯ РУКА\"\n  STR_LEFT_ARM: \"ЛЕВАЯ РУКА\"\n  STR_RIGHT_LEG: \"ПРАВАЯ НОГА\"\n  STR_LEFT_LEG: \"ЛЕВАЯ НОГА\"\n  STR_PAIN_KILLER: \"АНАЛЬГЕТИК\"\n  STR_STIMULANT: \"СТИМУЛЯТОР\"\n  STR_HEAL: \"ЛЕЧИТЬ\"\n  STR_TIME_UNITS_SHORT: \"ОД>{ALT}{0}\"\n  STR_WEIGHT: \"Вес>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"Реакц>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"М.Нав>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"М.Сила>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Артефакт пришельцев\"\n  STR_AMMO_ROUNDS_LEFT: \"ОРУЖИЕ:{NEWLINE}ИМЕЮЩИЙСЯ{NEWLINE}БОЕЗАПАС={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Болеут>{ALT}{0}{ALT}{NEWLINE}Стим>{ALT}{1}{ALT}{NEWLINE}Леч>{ALT}{2}\"\n  STR_THROW: \"Бросить\"\n  STR_AUTO_SHOT: \"Очередь\"\n  STR_SNAP_SHOT: \"Навскидку\"\n  STR_AIMED_SHOT: \"Прицельный\"\n  STR_STUN: \"Парализовать\"\n  STR_PRIME_GRENADE: \"Взвести гранату\"\n  STR_USE_SCANNER: \"Сканировать\"\n  STR_USE_MEDI_KIT: \"Использовать\"\n  STR_LAUNCH_MISSILE: \"Пуск торпеды\"\n  STR_ACCURACY_SHORT: \"Точ>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Не хватает очков действия!\"\n  STR_NOT_ENOUGH_ENERGY: \"Не хватает энергии!\"\n  STR_NO_ROUNDS_LEFT: \"Кончились боеприпасы!\"\n  STR_NO_AMMUNITION_LOADED: \"Оружие не заряжено!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Боеприпасы не от этого оружия!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"Оружие уже заряжено!\"\n  STR_NO_LINE_OF_FIRE: \"Нет линии огня!\"\n  STR_GRENADE_IS_ACTIVATED: \"Граната активирована!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Граната деактивирована!\"\n  STR_THERE_IS_NO_ONE_THERE: \"Там никого нет!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Невозможно использовать неисследованный артефакт!\"\n  STR_OUT_OF_RANGE: \"Вне зоны поражения!\"\n  STR_UNABLE_TO_THROW_HERE: \"Не могу бросить сюда!\"\n  STR_SET_TIMER: \"Установить таймер\"\n  STR_HIDDEN_MOVEMENT: \"СКРЫТЫЕ ПЕРЕМЕЩЕНИЯ\"\n  STR_TURN: \"ХОД> {0}\"\n  STR_SIDE: \"СТОРОНА> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Нажмите кнопку для продолжения\"\n  STR_MIND_CONTROL: \"Молекулярный контроль\"\n  STR_PANIC_UNIT: \"Сбой импланта\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Психическая атака удалась\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Контроль установлен\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}потерял рассудок\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}потеряла рассудок\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}запаниковал\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}запаниковала\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Пришельцы\"\n  STR_RIGHT_HAND: \"ПРАВАЯ РУКА\"\n  STR_LEFT_HAND: \"ЛЕВАЯ РУКА\"\n  STR_RIGHT_SHOULDER: \"ПРАВОЕ ПЛЕЧО\"\n  STR_LEFT_SHOULDER: \"ЛЕВОЕ ПЛЕЧО\"\n  STR_BACK_PACK: \"РЮКЗАК\"\n  STR_BELT: \"ПОЯС\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}под молекулярным контролем\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}под молекулярным контролем\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}потерял сознание\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}потеряла сознание\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}умер от смертельных ран\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}умерла от смертельных ран\"\n  STR_USE_MIND_PROBE: \"Использовать М.К. Считыватель\"\n  STR_FATAL_WOUNDS: \"СМЕРТЕЛЬНЫЕ РАНЫ\"\n  STR_UNDER_ARMOR_UC: \"БРОНЯ СНИЗУ\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Очки действия зарезервированы для выстрела навскидку\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Очки действия зарезервированы для стрельбы очередью\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Очки действия зарезервированы для прицельного выстрела\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Очки действия зарезервированы, чтобы присесть\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"ОД зарезервированы, чтобы присесть и выстрелить\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} боец на судне X-Com\"\n    few: \"{N} бойца на судне X-Com\"\n    many: \"{N} бойцов на судне X-Com\"\n    other: \"{N} бойцов на судне X-Com\"\n  STR_UNITS_OUTSIDE:\n    one: \"{N} боец остался снаружи\"\n    few: \"{N} бойца осталось снаружи\"\n    many: \"{N} бойцов осталось снаружи\"\n    other: \"{N} бойцов осталось снаружи\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} боец на входе\"\n    few: \"{N} бойца на входе\"\n    many: \"{N} бойцов на входе\"\n    other: \"{N} бойцов на входе\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} боец в зоне выхода\"\n    few: \"{N} бойца в зоне выхода\"\n    many: \"{N} бойцов в зоне выхода\"\n    other: \"{N} бойцов в зоне выхода\"\n  STR_ABORT_MISSION_QUESTION: \"Покинуть поле боя?\"\n  STR_CORPSE: \"Труп\"\n  STR_UNLOAD_CRAFT: \"Выгрузить\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}убит\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}убита\"\n  STR_HIT_MELEE: \"Ударить\"\n  STR_GROUND: \"НА ЗЕМЛЕ\"\n  STR_LIVING_QUARTERS_PLURAL: \"Жилые модули\"\n  STR_LIST_ITEM: \"ПРЕДМЕТ\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"Все пришельцы погибли при крушении.{NEWLINE}Автоматическая эвакуация НПО\"\n  STR_RESET: \"Сброс\"\n  STR_MEMORIAL: \"Мемориал\"\n  STR_DATE_UC: \"ДАТА\"\n  STR_SOLDIERS_RECRUITED_UC: \"АКВАНАВТОВ НАНЯТО>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"ПОТЕРИ>{ALT}{0}\"\n  STR_REMOVE_SELECTED: \"Убрать отобранных\"\n  STR_LIVE_ALIENS: \"Живые{NEWLINE}образцы\"\n  STR_DEAD_ALIENS: \"Негодные{NEWLINE}образцы\"\n  STR_UNDER_INTERROGATION: \"Изучаемые{NEWLINE}образцы\"\n  STR_CONTAINMENT_EXCEEDED: \"ИЗОЛЯТОР ПРИШЕЛЬЦЕВ ЗАПОЛНЕН!{SMALLLINE}на базе {0} не хватает мест в изоляторе. Вы должны избавиться от лишних пленных (которые не выживут).\"\n  STR_MANAGE_CONTAINMENT: \"Управление изолятором пришельцев\"\n  STR_STORAGE_EXCEEDED: \"СКЛАДЫ ПЕРЕПОЛНЕНЫ!{SMALLLINE}На базе {0} недостаточно свободного места. Необходимо продать часть складируемого.\"\n  STR_GO_TO_BASE: \"Перейти к базе\"\n  STR_MELEE_ACCURACY: \"ТОЧНОСТЬ БЛИЖНЕГО БОЯ\"\n  STR_SELL_PRODUCTION: \"ПРОДАТЬ\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Обе руки должны быть свободны!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Не хватает предметов для применения шаблона!\"\n  STR_UNLOAD_WEAPON: \"Разрядить оружие\"\n  STR_ALL_ITEMS: \"Все предметы\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"НЕТ МЕСТА НА БОРТУ!{SMALLLINE}Вы можете взять не больше {N} груза на эту субмарину.\"\n    few: \"НЕТ МЕСТА НА БОРТУ!{SMALLLINE}Вы можете взять не больше {N} грузов на эту субмарину.\"\n    many: \"НЕТ МЕСТА НА БОРТУ!{SMALLLINE}Вы можете взять не больше {N} грузов на эту субмарину.\"\n    other: \"НЕТ МЕСТА НА БОРТУ!{SMALLLINE}Вы можете взять не больше {N} грузов на эту субмарину.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}КОМАНДНЫЙ ЦЕНТР УНИЧТОЖЕН{NEWLINE}Доберитесь до входа и покиньте поле боя.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"Базу X-Com нельзя построить на суше\"\n  STR_UNABLE_TO_ENGAGE_DEPTH: \"НЕ МОГУ АТАКОВАТЬ ПРОТИВНИКА{NEWLINE}НА ТАКОЙ ГЛУБИНЕ\"\n  STR_UNABLE_TO_ENGAGE_AIRBORNE: \"НЕ МОГУ АТАКОВАТЬ ПРОТИВНИКА{NEWLINE}В ВОЗДУХЕ\"\n  STR_UNDERWATER_EQUIPMENT: \"Это оборудование не работает над водой!\"\n  STR_LAND_EQUIPMENT: \"Это оборудование не работает под водой!\"\n  STR_LEVEL_SHORT: \"L{0}\"\n  STR_PERSONNEL: \"Персонал\"\n  STR_CRAFT_ARMAMENT: \"Суда и вооружение\"\n  STR_COMPONENTS: \"Компоненты\"\n  STR_SOLDIERS_RECRUITED: \"Акванавтов нанято\"\n  STR_SOLDIERS_LOST: \"Акванавтов потеряно\"\n  STR_TOTAL_UFOS: \"Cубмарин обнаружено\"\n  STR_TOTAL_ALIEN_BASES: \"Колоний пришельцев обнаружено\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"МКС\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"МКН\"\n  FEMALE_CIVILIAN: \"Гражданский, женщина\"\n  MALE_CIVILIAN: \"Гражданский, мужчина\"\n  DOCKER_CIVILIAN: \"Гражданский, докер\"\n  SAILOR_CIVILIAN: \"Гражданский, моряк\"\n  STR_BIODRONE_MELEE_WEAPON: \"Холодное оружие биодрона\"\n  HALLUCINOID_WEAPON: \"Оружие галлюциноида\"\n  STR_LOBSTERMAN_MELEE_WEAPON: \"Холодное оружие лобстермена\"\n  CALCINITE_WEAPON: \"Оружие кальцинита\"\n  DEEP_ONE_WEAPON: \"Оружие глубинного\"\n  STR_TRISCENE_MELEE_WEAPON: \"Холодное оружие трисцена\"\n  STR_TRIBIO_SONIC_WEAPON: \"Акустическое оружие пришельцев\"\n  XARQUID_WEAPON: \"Оружие ксарквида\"\n  TENTACULAT_WEAPON: \"Оружие тентакулата\"\n  ZOMBIE_WEAPON: \"Оружие зомби\"\n  ALIEN_PSI_WEAPON: \"Оружие М.К. пришельцев\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/sk.yml",
    "content": "sk:\n  STR_LEVIATHAN_UFOPEDIA: \"TRANSPORTNÁ A STÍHACIA PONORKA SO SCHOPNOSŤOU PONORU DO EXTRÉMNYCH HĹBOK. VĎAKA POKROČILEJ SYNTÉZE POZEMSKEJ A MIMOZEMSKEJ TECHNOLÓGIE IÓNOVÉHO POHONU A NAVIGÁCII ZALOŽENEJ NA MAGNETICKÝCH POLIACH, ZVLÁDA PRENASLEDOVAŤ PROTIVNÍKA I VO VZDUCHU. \"\n  STR_BARRACUDA_UFOPEDIA: \"BRITSKÁ HYDROSPACE BARRACUDA JE POHÁŇANÁ SUPER-TEPELNÝMI LASEROVÝMI MOTORMI. JE TO JEDNO Z NAJRÝCHLEJŠÍCH STÍHACÍCH PLAVIDIEL NA SVETE, SCHOPNÉ PODMORSKÉHO I ATMOSFERICKÉHO LETU, KĽÚČOVÉ PLAVIDLO V NADCHÁDZAJÚCOM BOJI.\"\n  STR_HAMMERHEAD_UFOPEDIA: \"TRANSPORTNÉ A STÍHACIE PLAVIDLO. REPLIKÁCIA SYSTÉMU MAGNETICKÝCH POLÍ V X-COM LODI. I KEĎ MALÁ, JEJ DIZAJN JE STRHUJÚCIM TECHNICKÝM ÚSPECHOM.\"\n  STR_TRITON_UFOPEDIA: \"TRITON JE VOJENSKÝM TRANSPORTÉROM VYBAVENÝM ATMOSFERICKÝMI A PODMORSKÝMI MOTORMI. JEHO VEĽKÁ TRANSPORTNÁ KAPACITA A ROBUSTNÁ KONŠTRUKCIA MU ZABEZPEČUJE TRVALÉ MIESTO V X-COM FLOTILE.\"\n  STR_MANTA_UFOPEDIA: \"VYSOKORÝCHLOSTNÉ PLAVIDLO MANTA JE STÍHACÍM VZDUŠNO-PODMORSKÝM STROJOM, KTORÝ PRIPOMÍNA MIMOZEMSKÉ LODE S IÓNOVÝM POHONOM. VYSOKO EFEKTÍVNE ÚTOČNÉ PLAVIDLO V STUPŇUJÚCOM SA KONFLIKTU.\"\n  STR_AJAX_UFOPEDIA: \"TORPÉDO AJAX PATRÍ NA CELOM SVETE K ŠTANDARDNEJ VÝBAVE PRE PODMORSKÝ BOJ. JE VYUŽÍVANÉ PRE SVOJU PRESNOSŤ A ODSTRAŠUJÚCU SILU.\"\n  STR_DUP_HEAD_UFOPEDIA: \"TECHNOLÓGIA STRIEL S HLAVICOU Z OCHUDOBNENÉHO URÁNU JE RELATÍVNE NOVÁ. TENTO SYSTÉM JE PRVÝM KOMERČNE VYRÁBANÝM A VYUŽÍVANÝM PODMORSKÝM ZBRAŇOVÝM SYSTÉMOM.\"\n  STR_CRAFT_GAS_CANNON_UFOPEDIA: \"TECHNOLÓGIA TEJTO ZBRANE JE ZALOŽENÁ NA SYSTÉME STLAČENÉHO PLYNU, KTORÝ UMOŽŇUJE KANÓNU VYSTRELIŤ CELOPLÁŠŤOVÉ ŠÍPY S VYSOKOU PRIERAZNOSŤOU. \"\n  STR_PWT_CANNON_UFOPEDIA: \"TORPÉDO ZALOŽENÉ NA TECHNOLÓGII PULZNÝCH VĹN VYUŽÍVA SUPERTEPELNÝ PALIVOVÝ SYSTÉM A EXTRÉMNE TVRDENÉ BOJOVÉ HLAVICE, KTORÉ DOKÁŽU PRERAZIŤ VÄČŠINU ZNÁMYCH ZLIATIN. \"\n  STR_GAUSS_CANNON_UFOPEDIA: \"GAUSSOVA ZBRAŇ JE NOVOU TECHNOLÓGIOU VYVINUTOU V LABORATÓRIÁCH X-COM. SYSTÉM JE POSTAVENÝ NA ČASTICOVOM URÝCHĽOVAČI, KTORÝ JE NAPÁJANÝ KOMPAKTNÝM FÚZNYM REAKTOROM CHLADENÝM TEKUTÝM DUSÍKOM. \"\n  STR_SONIC_OSCILLATOR_UFOPEDIA: \"SILNÝ ZVUKOVÝ OSCILÁTOR VYTVÁRA VLNY SONICKEJ SILY, KTORÉ DOKÁŽU ZNIČIŤ SVOJ CIEĽ ROZVIBROVANÍM JEHO ŠTRUKTÚRY NA MOLEKULÁRNEJ ÚROVNI. \"\n  STR_AQUATOID_UFOPEDIA: \"Druh akvatoidov tvorí prastarú spoločnosť, ktorá existovala milénia predtým ako sa ľudstvo prvý raz objavilo na svete. Ich kompaktná forma a baňaté rysy pripomínajú ich vesmírnych príbuzných – Sectoidov. Ich vláda je založená na mocnej technológii molekulárnej kontroly. Akvatoidi sa snažia rozmnožovať, svoj inak sterilný druh, pomocou genetickej modifikácie – ideálnymi subjektmi ich experimentov sú práve ľudia. Vďaka nim dokázali vytvoriť početné hybridné druhy.\"\n  STR_AQUATOID_AUTOPSY: \"Pitva akvatoida\"\n  STR_AQUATOID_AUTOPSY_UFOPEDIA: \"Detailná analýza tohto stvorenia nám umožnila vysloviť niekoľko základných predpokladov. Je to sectoid, starý nepriateľ, avšak zmenený pomocou chirurgie a implantátov tak, aby z neho bolo vodné stvorenie. Zostatkové pľúca mu umožňujú dýchanie vzduchu a čiastočný pohyb po povrchu. Celé telo je pretkané kybernetickými implantátmi, ktoré zvyšujú efektívnosť jeho atrofických končatín a vnútorných orgánov. Keďže sú všetci členovia tohto druhu identickí, predpokladáme, že sú tieto stvorenia klony.\"\n  STR_GILLMAN_UFOPEDIA: \"Skoro človek. Podivný tvor, ktorý vyzerá ako plazovitý humanoid, veľmi blízky príbuzný človeka. Toto stvorenie je v podmorskom svete veľmi silné a rýchle. Gillmeni sú plne vyvinutý druh, nachádzame u nich samcov a samice rôznych vekových kategórií. Nie sú ako ostatní podmorský mimozemšťania, pretože nemajú žiadnu z ich genetických modifikácií či chirurgických deformácií. Je možné, že tu máme čo do činenia s vývojovou vetvou nášho vlastného druhu.\"\n  STR_GILLMAN_AUTOPSY: \"Pitva gillmana\"\n  STR_GILLMAN_AUTOPSY_UFOPEDIA: \"Už po začatí pitvy bolo zrejmé, že tu nemáme čo do činenia s mimozemšťanom, ale s na Zemi zrodeným tvorom. Prastarý prehistorický druh, o ktorom sme si mysleli, že vyhynul v momente kedy sa stali na planéte dominantné cicavce. Gillmeni – obojživelní, inteligentní a silní - tu žili v čase keď planétu obývali dinosaury. Katastrofa, ktorá zapríčinila vyhynutie plazov na tejto planéte ich vohnala do symbiotického vzťahu s cudzími prišelcami. V lebkách majú umiestnené malé elektronické zariadenie.\"\n  STR_LOBSTERMAN_UFOPEDIA: \"Tento ohromný tvor, vyšší ako človek s výraznými šiestimi končatinami, nepripomína nič menej ako vodného démona. Podobnosť tvora s pozemskými rakmi mu medzi X-Com vojakmi zabezpečila anglickú prezývku Lobsterman (Račí muž). Je to behemot morských hlbín. Je to precízne navrhnutá bojová kreatúra, s neuveriteľnou silou, prakticky nezraniteľná streľbou. Len jeho klepetá samotné dokážu rozdrviť oceľ.\"\n  STR_LOBSTERMAN_AUTOPSY: \"Pitva lobstermana\"\n  STR_LOBSTERMAN_AUTOPSY_UFOPEDIA: \"Pod takmer nezničiteľnou schránkou sa nachádza tvor neuveriteľnej konštrukcie. Silné svalstvo vinúce sa okolo titánovej kostry, sofistikovaný zameriavací systém s multipásmovou snímacou schopnosťou je pripojený priamo do mozgu tvora. Jeho niekoľko očí je chránených plastom, ktorý je silnejší ako oceľ. Je zrejmé, že tieto tvory boli stvorené tak, aby ich nikto nedokázal zastaviť. Hlboko v jeho tele sme našli zariadenia neznámej konštrukcie a funkcie.\"\n  STR_TASOTH_UFOPEDIA: \"Títo agilní a rýchli protivníci sú pilierom mimozemskej armády. Stovky sa rodia v masívnych kadiach kdesi hlboko v srdci kolónií mimozemšťanov. Výrazne silnejší ako človek, Tasoth je skutočný votrelec na Zemi – jeho správanie a mäsožravá nátura nemá na tejto planéte obdoby. Tvoria hlavnú útočnú silu mimozemšťanov a nikdy neutekajú z boja, ani za nepriaznivo sa vyvíjajúcej situácie na bojisku. \"\n  STR_TASOTH_AUTOPSY: \"Pitva tasotha\"\n  STR_TASOTH_AUTOPSY_UFOPEDIA: \"Pitva odhalila kybernetický organizmus so zvláštnou energiou. Vo vnútri telesnej schránky je malá energetické jednotka, avšak žiadne identifikovateľné orgány. Energia je prenášaná cez telo pomocou bio-elektrického prenosového systému. Telu chýbajú kosti a akékoľvek iné podporné orgány. Po zabití prúdenie energie ustáva a z tvora sa stáva neživá bábka plná slizkého mimozemského mäsa a tekutín. Druhou rozoznateľnou konštrukciou v tele je pár keramických batérií, ktoré keď sa nabijú energiou dokážu na moment tvora oživiť. \"\n  STR_DEEP_ONE_UFOPEDIA: \"Hĺbkomor je biologická nočná mora, kríženec, ktorý vzišiel z pokrútených experimentov akvatoidov. Narazili sme na niekoľko variantov týchto tvorov. Po rozsiahlom výskume sme došli k záveru, že tieto tvory sú vyrábané dobyvateľmi. Ich rady bujnejú vždy po tom ako mimozemšťania zajmú čerstvú dávku ľudí. Každý z týchto pod-ľudí je vyzbrojený energetickým výbojom, ktorý je schopný zabiť akvanauta.\"\n  STR_DEEP_ONE_AUTOPSY: \"Pitva hĺbkomora\"\n  STR_DEEP_ONE_AUTOPSY_UFOPEDIA: \"Tento tvor je štep človeka a mimozemského organizmu. Ľudský mozog bol výrazne pozmenený tak, aby dokázal prijať ovládaciu elektroniku a mimozemskú mozgovú kôru. Len veľmi ťažko by sme v tomto tvorovi hľadali známky ľudskej anatómie, okrem jednej časti: očí. Chirurgický štep umožňuje mimozemskému zárodku rásť konzumovaním ľudského hostiteľa. Tvrdá koža tvora sa zdá byť neorganická, kovové pletivo, ktoré je extrémne silné a pružné. Výsledný kríženec je silný, rýchly a úplne pod kontrolou mimozemšťanov.  \"\n  STR_BIODRONE_UFOPEDIA: \"Bio-dron je výtvor, ktorý mohla stvoriť jedine myseľ mimozemšťana. Je to mozog (ľudský alebo mimozemský) uložený v amniotickej tekutine a pripojený k napájanej základnej jednotke, ktorá dokáže lietať na zemi alebo pod vodou. Každý bio-dron je vyzbrojený so silným zvukovým distruptorom, z časti mechanickým a z časti organickým. Niektorý z našich vedcov sa domnievajú, že zbraň je riadená pôvodnými hlasivkami hostiteľského organizmu. Presné a húževnaté, tieto strážne super psy sú využívané mimozemšťanmi na stráženie hodnotných aktív.\"\n  STR_BIODRONE_AUTOPSY: \"Pitva bio-drona\"\n  STR_BIODRONE_AUTOPSY_UFOPEDIA: \"Hypotéza, že zvukový distruptor je biologické zariadenie sa nám potvrdila. Toto nešťastné stvorenie doslova ukričí svojich protivníkov k smrti. Každá vzorka je vážne znetvorená a má jazvy spôsobené masívnou chirurgickou traumou. Mimozemšťania doslova prinútili mozog k poslušnosti. Väčšina mozgovej kôry použitej v tvorovi je mimozemského pôvodu, avšak nič sa nemôže rovnať hrôze nájdenia ľudskej jednotky. Bio-drony sú poháňané iónovým motorom a obsahujú akúsi formu systému diaľkového ovládania. \"\n  STR_TENTACULAT_UFOPEDIA: \"Ani len najhlbšie lovercraftovské nočné mory by nemohli stvoriť takéto neopísateľné stvorenie. Na zemi nežije žiadne zviera, ktoré by sa mu rovnalo. Prostredie, ktoré by dokázalo vytvoriť tvora ako je tento je pre nás nepredstaviteľné. Jeho dlhé chápadlá dokážu svoju obeť paralyzovať a následne premeniť na zvláštnu, nemysliacu vec. Dotyk týchto potomkov môže znamenať smrť, a to dokonca i cez zbroj. Chápadlovec je najhrôzostrašnejší mimozemšťan na akého X-Com doteraz narazil.\"\n  STR_TENTACULAT_AUTOPSY: \"Pitva chápadlovca\"\n  STR_TENTACULAT_AUTOPSY_UFOPEDIA: \"Pitva odhalila malý kybernetický implantát uložený vo veľkom mozgu tohto tvora. Jeho orientačný systém je komplexnou kombináciou optického a tepelného obrazového vnímania. Dokonca i v tmavých hlbinách oceánu sa táto príšera dokáže orientovať s neomylnou presnosťou. Tých niekoľko zostatkových orgánov je vyvinutých len natoľko, aby stačili pre prežitie. Každý tvor ma malý žalúdok s externou prípojkou. Je pravdepodobné, že tento tvor bol vyživovaný priamo svojimi pánmi. \"\n  STR_CALCINITE_UFOPEDIA: \"Tak ako potápačské skafandre stratených námorníkov, číha tento tvor na morskom dne na neopatrných. Svojimi pazúrmi, tvrdšími než oceľ, dokáže úderom poslať k zemi i toho najschopnejšieho potápača. Pri pohľade do priezoru prilby vidíme hmotu zelenej farby, ktorá vyzerá ako želatína. Avšak aký tvor sa za skafandrom skrýva, to nedokážeme s častých smrteľných stretnutí s touto obludou vytušiť.\"\n  STR_CALCINITE_AUTOPSY: \"Pitva kalcinita\"\n  STR_CALCINITE_AUTOPSY_UFOPEDIA: \"Keď sme z kalcinita odstránili jeho pancierovaný oblek, ukázalo sa, že je to mohutná beztvará masa protoplazmy. Žiadna známka po viditeľnom mozgu, končatinách či zmyslových orgánoch, len hlboko v tekutom tele zostal malý kovový komponent. Po smrti tvora môžeme len odhadovať jeho prirodzenú formu. Je to jedna z nevysvetliteľných záhad našich mimozemských nepriateľov.\"\n  STR_TRISCENE_UFOPEDIA: \"Tento dvojnohý plaz je návratom do doby dinosaurov. Zdá sa, že túto príšeru z obdobia kriedy zachránila jej schopnosť prežiť ako vo vode tak na súši. K tvorovi je pripevnený nosič zbrani a jeho čeľuste sú vybavené silnými kovovými zubami. Tieto tvory sú často centrom mimozemských útočných formácií pri útokoch na súši. Sú ťažkotonážnou a schopnou zbraňou s vysokou efektivitou nasadzovanou Tasothmi veliteľmi.\"\n  STR_TRISCENE_AUTOPSY: \"Pitva triscena\"\n  STR_TRISCENE_AUTOPSY_UFOPEDIA: \"Chirurgické skúmanie Triscena odhalilo, že sa jedná o veľmi prastarého tvora, ktorý je posilnený kybernetickými implantátmi a zbraňovým systémom. Jeho mozog je podporovaný malým počítačovým modulom kontrolujúcim všetky jeho funkcie. Hrubá odolná koža, inštinkty predátora rozšírené o zbraňový systém z neho vytvárajú nebezpečného protivníka v každom prostredí. \"\n  STR_HALLUCINOID_UFOPEDIA: \"Hlboko v oceánoch chovajú mimozemšťania tieto obrovské pozemské tvory ako zbrane. Nenechajte sa v prítomnosti týchto neškodne sa tváriacich obyvateľov hlbín ukolísať falošným pocitom bezpečia. Halucinoid vybavený ľadovým útokom v boji na blízko, je smrteľne nebezpečný tvor.\"\n  STR_HALLUCINOID_AUTOPSY: \"Pitva halucinoida\"\n  STR_HALLUCINOID_AUTOPSY_UFOPEDIA: \"Pod mnohými vrstvami jeho želatínového tela nachádzame silný chemický zmrazovač tvoriaci jeho hlavnú ofenzívnu silu. Jemná a pružná koža Halucinoida sa zdá byť citlivá na útoky zbraňami, ktoré produkujú teplo. Tohto mutanta často nachádzame v spoločnosti jeho pánov – Akvatoidov.\"\n  STR_XARQUID_UFOPEDIA: \"Ďalší modifikovaný pozemský bezstavovec, Xarkid, je nádherný a nebezpečný tvor. Tento rýchlo plávajúci obor, skrýva v sebe ničivý arzenál zbraní: dusivý atramentový sprej a iónový časticový lúč. Od nášho prvého stretnutia s týmto mocným tvorom si musíme dávať pozor na jeho silu a jeho pánov, Gillmanov, ktorý ho dokážu ovládať. \"\n  STR_XARQUID_AUTOPSY: \"Pitva xarkida\"\n  STR_XARQUID_AUTOPSY_UFOPEDIA: \"Táto prerastená nautiloidea bola do tejto veľkosti vyšľachtená pomocou mimozemských drog a chirurgických zmien. Neprirodzene zvrhlá je i úprava tvora Gillmanmi tak, že pridali do jeho útrob mechanický kontrolný systém. Z tvora tak neostalo nič z jeho prirodzenej existencie. Využívaní ako organický zbraňový systém, robí z xarkidov, ich hrubého panciera a pohyblivosti, obávaných protivníkov.\"\n  STR_ION_BEAM_ACCELERATORS_UFOPEDIA: \"Mimozemské lietajúce ponorky sú založené na komplexnom energetickom systéme, ktorý ich poháňa neuveriteľnou rýchlosťou i pod morskou hladinou. Základ ich technológie tvorí IÓNOVÝ TLAKOVAČ využívajúci Zrbit ako katalyzátor. Motory vo vode tak pretlačia stonásobok svojho objemu za sekundu. Tento enormný výkon spôsobuje, že sú mimozemské ponorky schopné uniknúť väčšine pozemských ponoriek. Tento pohonný systém dokážeme replikovať za použitia Zrbitu a akvaplastov.\"\n  STR_MAGNETIC_NAVIGATION_UFOPEDIA: \"Tieto jednotky generujú sférické mnohovrstevné magnetické pole, ktoré sa rozšíri do oblasti 1000m okolo ponorky. Mimozemskí navigátori sú priamo napojení na tieto stroje a vnímajú tak cestu neviditeľným svetom pod hladinou. Riadiaci systém využíva modifikované mimozemské mozgové tkanivo, ktoré komunikuje priamo s navigátorovým mozgom cez neurónové spojenie.\"\n  STR_ALIEN_SUB_CONSTRUCTION_UFOPEDIA: \"Každé plavidlo má chameleónsku štruktúru starostlivo vymodelovanú podľa morských živočíchov, ktorá je postavená z akvapalstov. Každá ponorka pracuje ako živý organizmus: posádka a stroj sú zharmonizovaní. Väčšina týchto systémov môže byť replikovaná a je možné vytvoriť hybridnú technológiu, ktorá nám umožní dosiahnutie rovnakej technickej úrovne.\"\n  STR_ALIEN_CRYOGENICS_UFOPEDIA: \"Nespočetné množstvo mimozemšťanov, ktorí boli skrytý na Zemi, boli udržovaní v podchladenom stave – kryogenicky zmrazení. Všetky tvory sú umiestnené v boxoch, ich telesná teplota redukovaná až na bod, kedy sa všetky telesné pochody zastavia. Prieskum týchto jednotiek odhalil, že telá boli zmrazené neuveriteľne dlhú dobu, niektoré viac ako 60 miliónov rokov.\"\n  STR_ALIEN_CLONING_UFOPEDIA: \"Veľké množstvo zajatých mimozemšťanov je identických až na úroveň ich DNA, duplikáty na každej úrovni. Vzorky buniek sú umiestnené do týchto jednotiek zo zamrznutých génových bánk mimozemšťanov. Niektoré jednotky obsahujú ľudí alebo časti ľudských tiel. Je možné, že ďalším účelom týchto klonovacích jednotiek je vytvorenie mimozemsko-ľudského hybridu. \"\n  STR_ALIEN_LEARNING_ARRAYS_UFOPEDIA: \"Využívaním implantátov molekulárnej kontroly v lebkách mimozemšťanov, dokážu tieto prístroje vložiť informácie priamo do mozgu. K týmto jednotkám potom privedú čerstvé mimozemské klony a do ich prázdnych myslí stiahnu pamäť celého druhu a všetky vedecké alebo bojové vedomosti.\"\n  STR_ALIEN_IMPLANTER_UFOPEDIA: \"Táto jednotka je využívaná na vybavovanie mimozemšťanov implantátmi molekulárnej kontroly, oplodňovanie reprodukujúcich sa rás a vkladanie alebo vyberanie orgánov a elektroniky z akéhokoľvek živého tvora. Mysleli sme si, že proces bol vykonávaný na pacientoch v narkóze, avšak jedinec tento proces veľmi dobre vníma. Bohužiaľ, tento prístroj je perfektne prispôsobený ľudskej anatómii.  \"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"Konečne máme dôkazy na to, aby sme zistili prečo mimozemšťania zajímajú ľudí. Nie sú jedlom, nie sú oplodňovaní mimozemskými embryami, skôr sú základom pre celý rad stvorení a kontrolných systémov. Mimozemská technológia je založená na spoločnej mysli, zdieľanom intelekte a ľudský mozog je ideálnym materiálom pre tieto systémy. Ľudské mozgové tkanivo je využívané vo väčšine mimozemských biologických počítačových pamätiach a riadiacich systémoch. Zvyšky sú potom využívané na výstavbu a chov. \"\n  STR_AQUA_PLASTICS_UFOPEDIA: \"Ponorky mimozemšťanov a ich stavby využívajú tento neuveriteľné silný, pružný a odolný materiál vo väčšine svojich konštrukcií. Akvapalasty sú komplexné multizväzkové, zrbitom katalyzované materiály. Hustejšia, pritom však ľahšia, substancia je silnejšia než Titan alebo Kevlar.\"\n  STR_ZRBITE_UFOPEDIA: \"Je to zliatina mimozemského pôvodu, čiastočne zo zlata a čiastočne z biomateriálu mimozemšťanov. Pri použití ako energetického zdroja, dokáže malé množstvo vytvoriť viac energie ako 10 krát väčší nukleárny reaktor. Výroba tohto materiálu je mimo naše technické schopnosti, pretože väčšina jeho komponentov je mimozemského pôvodu.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"Mimozemšťania útočia po celej zemi s nemilosrdnou efektivitou. Nedokážeme však určiť zdroj týchto útokov. Mohlo by to byť nikede v hlbinách oceánu, ktoré sú pre nás zatiaľ nedostupné? Nie všetky organizmy, na ktoré sme narazili, sú mimozemského pôvodu, niektoré sú veľmi staré avšak pozemské. Dokonca z evolučných vetiev, o ktorých sme si mysleli, že dávno vyhynuli. Máme čo dočinenia s hrozbou, ktorá driemala po celé milénia - dômyselná symbióza mimozemského a ľudského. Hlboko v oceánoch sú pradávne mimozemské miesta, ktoré mimozemšťania využívali ku kontaktu so svojimi vesmírnymi bratrancami. Každé z týchto dvanástich miest obsahuje Synomium, výkonný kus mimozemskej technológie. Teraz, keď je ich vojnová mašinéria na pochode, sa mimozemšťania snažia tieto zariadenia reaktivovať. Ich reaktivovaním rozšíria sieť molekulárnej kontroly na Zemi. Musíme tieto zariadenia zničiť za každú cenu.\"\n  STR_THE_ULTIMATE_THREAT_UFOPEDIA: \"Pred 65 miliónmi rokov bola na Zem poslaná kolonizačná loď zo vzdialeného mimozemského sveta. Keď sa toto mohutné plavidlo priblížilo k mladej planéte, mohutná slnečná erupcia spôsobila zlyhanie navigačných systémov lode. Poškodený a zlyhávajúci stroj preletel stratosférou a vynoril sa oblohe obdobia kriedy. Na Zemi sledovali nespočetné druhy živočíchov ako sa ich Nemezis zarýva do povrchu planéty. Obrovský mrak prachu zaclonil oblohu a ako sa zem ochladzovala, tak dominantný živočíšny druh – veľkolepé dinosaury – pomaly mizol. Avšak 400 miliárd ton T'leth nebolo nárazom zničených. Sofistikované superpočítače zahájili kryogenický spánkový cyklus tvorov, ktoré prebývali v jeho hlbinách. Ako veky plynuli, počítače prebudili časť mimozemšťanov, aby sa pokúsili nadviazať spojenie so svojimi vesmírnymi bratrancami. Márne, pretože väčšina napájacích zdrojov bola vypnutá.\"\n  STR_TLETH_THE_ALIEN_CITY: \"Mesto mimozemšťanov T'leth\"\n  STR_TLETH_THE_ALIEN_CITY_UFOPEDIA: \"T'leth, mohutná mimozemská kolonizačná loď leží pripútaná na dne Sigsbeeho hlbiny, v Mexickom zálive. V centre tohto mesta drieme mimozemská hrôza. Najodpornejšia a tak mocná, že i smrť je na ňu krátka. V sieňach z mimozemských zliatin spí forma veľkého spáča – Všemocný mimozemšťan. Vyzdvihnutím T'leth nad morskú hladinu započne jeho oživovací cyklus. Ak sa prebudí, bude nezastaviteľný. I keď nie je mŕtvy, ale ani živý, ovláda jeho mozog celú mimozemskú armádu. Podivuhodná technológia molekulárnej kontroly spája všetkých mimozemšťanov k Jednej mysli a Jednu myseľ k všetkým mimozemšťanom. Geneticky upravené mimozemsko/ľudské zárodky dodávajú Jednému energiu a vytvárajú spojenie medzi vládcom a jeho poddanými. Mýtus o Všemocnom mimozemšťanovi existuje v mysliach ľudí po celé storočia. Hlbiny oceánu vždy skrývali skutočnú pravdu. \"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"VYCENTROVAŤ-ČAS=5 sek.\"\n  STR_CANCEL_UC: \"ZRUŠIŤ\"\n  STR_NONE: \"Prázdny\"\n  STR_UNKNOWN: \"Neznámy\"\n  STR_POOR: \"Slabé\"\n  STR_AVERAGE: \"Priemerný\"\n  STR_GOOD: \"Dobrý\"\n  STR_EXCELLENT: \"Výborne\"\n  STR_BUILD_NEW_BASE_UC: \"POSTAVIŤ NOVÚ ZÁKLADŇU\"\n  STR_BASE_INFORMATION: \"INFORMÁCIA O ZÁKLADNI\"\n  STR_EQUIP_CRAFT: \"VYZBROJIŤ PONORKU\"\n  STR_BUILD_FACILITIES: \"POSTAVIŤ ZARIADENIE\"\n  STR_RESEARCH: \"VÝSKUM\"\n  STR_MANUFACTURE: \"VÝROBA\"\n  STR_TRANSFER_UC: \"PRESUN\"\n  STR_PURCHASE_RECRUIT: \"NÁKUP/NÁBOR\"\n  STR_SACK: \"PREPUSTIŤ\"\n  STR_SELL_SACK_UC: \"PREDAŤ/PREPUSTIŤ\"\n  STR_GEOSCAPE_UC: \"GLÓBUS\"\n  STR_NAME: \"Meno\"\n  STR_AREA: \"Oblasť\"\n  STR_BUILD_NEW_BASE: \"PostavIť novú základňu\"\n  STR_CANCEL: \"Zrušiť\"\n  STR_COST_UC: \"CENA>\"\n  STR_CONSTRUCTION_TIME_UC: \"ČAS VÝSTAVBY>\"\n  STR_DAY:\n    one: \"{N} deň\"\n    few: \"{N} dni\"\n    many: \"{N} dní\"\n    other: \"{N} dní\"\n  STR_HOUR:\n    one: \"{N} hodina\"\n    few: \"{N} hodiny\"\n    many: \"{N} hodín\"\n    other: \"{N} hodín\"\n  STR_MAINTENANCE_UC: \"ÚDRŽBA>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Inštalácia\"\n  STR_CURRENT_RESEARCH: \"AKTUÁLNY VÝSKUM\"\n  STR_SCIENTISTS_AVAILABLE: \"Dostupní vedci>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Pridelených vedcov>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Voľné laboratórne miesto>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"VÝSKUMNÝ PROJEKT\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"PRIDELENÍ VEDCI\"\n  STR_PROGRESS: \"POSTUP\"\n  STR_NEW_PROJECT: \"Nový projekt\"\n  STR_CANCEL_PROJECT: \"ZRUŠIŤ PROJEKT\"\n  STR_NEW_RESEARCH_PROJECTS: \"NOVÉ VÝSKUMNÉ PROJEKTY\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"DOSTUPNÍ VEDCI>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"VOĽNÉ LABORATÓRNE MIESTO>{ALT}{0}\"\n  STR_INCREASE: \"Zvýšenie\"\n  STR_DECREASE: \"Znížiť\"\n  STR_START_PROJECT: \"SPUSTIŤ PROJEKT\"\n  STR_CURRENT_PRODUCTION: \"Aktuálna produkcia\"\n  STR_ENGINEERS_AVAILABLE: \"Dostupní technici>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Pridelení technici>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Dostupné miesto v dielni>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Dostupné financie>{ALT}{0}\"\n  STR_ITEM: \"POLOŽKA\"\n  STR_ENGINEERS__ALLOCATED: \"Pridelení technici\"\n  STR_UNITS_PRODUCED: \"Vyrobených kusov\"\n  STR_TOTAL_TO_PRODUCE: \"Celkovo vyrobiť\"\n  STR_COST__PER__UNIT: \"Cena{NEWLINE}za{NEWLINE}kus\"\n  STR_DAYS_HOURS_LEFT: \"Ostávajúce dni/hodiny\"\n  STR_NEW_PRODUCTION: \"Nová výroba\"\n  STR_PRODUCTION_ITEMS: \"Predmety k výrobe\"\n  STR_CATEGORY: \"KATEGÓRIA\"\n  STR_START_PRODUCTION: \"ZAČNI S VÝROBOU\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} Osobohodín potrebných na výrobu jedného kusu\"\n  STR_COST_PER_UNIT_: \"Jedn. cena>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Požadovaný pracovný priestor>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"VYŽADUJE ŠPECIÁLNE MATERIÁLY\"\n  STR_ITEM_REQUIRED: \"POTREBNÝ MATERIÁL\"\n  STR_UNITS_REQUIRED: \"POTREBNÝCH JEDNOTIEK\"\n  STR_UNITS_AVAILABLE: \"JEDNOTKY DOSTUPNÉ\"\n  STR_STOP_PRODUCTION: \"ZASTAVIŤ VÝROBU\"\n  STR_ENGINEERS_AVAILABLE_UC: \"DOSTUPNÍ TECHNICI>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"DOSTUPNÉ PRACOVNÉ MIESTO>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"MESAČNÝ ZISK>{ALT}{0}\"\n  STR_INCREASE_UC: \"ZVÝŠIŤ\"\n  STR_DECREASE_UC: \"ZNÍŽIŤ\"\n  STR_UNITS_TO_PRODUCE: \"Vyrobiť kusov\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Nákup/Nábor personálu\"\n  STR_COST_OF_PURCHASES: \"Cena za nákup>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"JEDN. CENA\"\n  STR_QUANTITY_UC: \"MNOŽSTVO\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"VOĽNÝCH MIEST:ZAMESTNANCOV CELKOM>\"\n  STR_SOLDIERS: \"Akvanauti\"\n  STR_SCIENTISTS: \"Vedci\"\n  STR_ENGINEERS: \"Technici\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"POUŽITÉ MIESTO:DOSTUPNÉ MIESTO>\"\n  STR_LIVING_QUARTERS: \"Ubytovne\"\n  STR_STORES: \"Sklady\"\n  STR_LABORATORIES: \"Laboratóriá\"\n  STR_WORK_SHOPS: \"Dielne\"\n  STR_HANGARS: \"Ponorkový dok\"\n  STR_SHORT_RANGE_DETECTION: \"Sonar krátkeho dosahu\"\n  STR_DEFENSE_STRENGTH: \"Účinnosť obrany\"\n  STR_TRANSFERS_UC: \"PRESUNY\"\n  STR_TRANSFERS: \"Presuny\"\n  STR_ARRIVAL_TIME_HOURS: \"Doba dodávky (hodiny)\"\n  STR_COST_: \"Cena>{ALT}{0}\"\n  STR_AREA_: \"Oblasť>{ALT}{0}\"\n  STR_BASE_NAME: \"Meno základne?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"URČI POZíCIU PRE PRETLAKOVÚ KOMORU\"\n  STR_TRANSFER: \"Presun\"\n  STR_AMOUNT_TO_TRANSFER: \"MNOŽSTVO NA PRESUN\"\n  STR_SELECT_DESTINATION_BASE: \"Označ cieľovú základňu\"\n  STR_COST: \"Cena\"\n  STR_INTRO_1: \"Copyright 1995 MicroProse\"\n  STR_INTRO_2: \"Mars: Pád Cydonie\"\n  STR_INTRO_3: \"Po tom ako jednotky X-Com zničili samotné centrum mimozemskej vojnovej mašinérie, vracajú sa triumfálne domov. Avšak nie všetko bolo v marťanskej základni mŕtve.\"\n  STR_INTRO_4: \"Silný tachyónový lúč začal prúdiť z ruín nervového centra Cydonie - svišiaci prázdnotou k svojmu cieľu............\"\n  STR_INTRO_5: \"Zemi.\"\n  STR_INTRO_6: \"Hlboko v pozemskom oceáne lúč zasiahne dlho neaktívny prijímač. Obrovské spiace počítače sa preberajú k životu. Hlboko, mimo dohľadu celého ľudstva, v obrovských komorách plných spiacich bytostí sa začína ich dlhý reanimačný cyklus.\"\n  STR_INTRO_7: \"2040: Zem zabúda. Hrôzy Prvej mimozemskej vojny sú dávno zabudnuté. Avšak, v stratených a skrytých miestach oceánu sú znova pripravené mimozemské hordy. Pripravené zvrhnúť ľudstvo a ovládnuť jeho planétu.\"\n  STR_INTRO_8: \"Mimozemšťania udreli proti ľudstvu; hľadajúc vzorky pre svoje zvrátené experimenty; pustošia planétu pre zdroje a vzácne minerály; útočia z hlbín morí. Potom obrátili svoj zrak nad vlny.\"\n  STR_INTRO_9: \"Silné vznášajúce sa ponorky podivných tvarov brázdia oceány - pozerajú, hľadajú, lovia...\"\n  STR_INTRO_10: \"Ak nájdu svoju korisť, zaútočia.\"\n  STR_INTRO_11: \"Používajú podivné nové zbrane, pred ktorými sa svet nevie brániť. Sme vydaní na milosť útočníkom.{NEWLINE}Je len jedna organizácia, ktorá nás dokáže zachrániť; ale my sme sa jej už dávno otočili chrbtom...\"\n  STR_INTRO_12: \"Experimentálna podmorská základňa X-COM\"\n  STR_INTRO_13: \"'Mayday! Mayday!' 'Toto je transatlantický parník Hyperion'. 'Útočia na nás'. 'Mayday! Mayd............'\"\n  STR_INTRO_14: \"'Veliteľské centru doku jedna: Otváram pretlakový uzáver', 'vypustite Barracuda Zero One. Máme hlásený útok mimozemšťanov - stav Červený'.{NEWLINE}'Opakujem: najvyššia pohotovosť'\"\n  STR_INTRO_15: \"Mimozemšťania sú vo svojej efektivite nemilosrdný....\"\n  STR_INTRO_16: \"...neomylní vo svojej presnosti\"\n  STR_INTRO_17: \"'Barracuda Zero One základni' - 'približujeme sa k zvyškom Hyperionu'.\"\n  STR_INTRO_18: \"'Spomaľujem'.{NEWLINE}'Dva metre’{NEWLINE}'Jeden meter'{NEWLINE}'Všetci akvanauti sa pripravia na výsadok'.\"\n  STR_INTRO_19: \"...........'Vzduchový uzáver voľný'...'približujem sa k vraku'.{NEWLINE}'Holy!'{NEWLINE}'Vidíte tie príšery cez moju kameru?'\"\n  STR_GAMEOVER_1: \"Zlyhali sme, mimozemšťania zlikvidovali našu poslednú nádej na spásu.{NEWLINE}X-Com bol zničený a Zem leží pri nohách svojho pradávneho nepriateľa.\"\n  STR_GAMEOVER_2: \"Vysoko v stratosfére sa ozýva hrmenie T'leth, ako sa mesto presúva po tvári sveta. Rozosieva smrť a žne posledné zvyšky ľudskej rasy. Hlboko v jeho útrobách sa k životu preberá vražedná mimozemská myseľ.\"\n  STR_GAMEOVER_3: \"V hlavných mestách všetkých národov sa snažia prísť z posledným zúfalým plánom. Avšak všetko zlyháva, bez technológie z výskumných projektov X-Com sú naše zbrane neefektívne.\"\n  STR_GAMEOVER_4: \"Mimozemšťania rozostavili svoje základne okolo polárnych čapičiek a začali s roztápaním ľadu, svet sa stane jedným nekonečným oceánom. Zvyšky ľudskej rasy sú zhromaždené na jedno miesto a využívané pre kruté chovné experimenty s neznámymi mimozemským cieľom. Obloha potemnela a nákaza zasiahla všetky krajiny Zeme.\"\n  STR_GAMEOVER_5: \"Nedokážeme odporovať novému svetovému poriadku, a tých ktorí sa o to pokúsili postihla rýchla smrť z rúk neuveriteľných mimozemských zbraní. Pre tých z nás, ktorých nepostihlo také vyslobodenie, sa matka Zem stala mimozemským svetom a ľudstvo bolo stratené pod tiažou približujúcej sa hrôzy. \"\n  STR_OUTRO_1: \"Hrobka, spustošená a zničená, bublajúci rev vychádza z urny uprostred.{NEWLINE}Hlupáci, všetci zahyniete....................\"\n  STR_OUTRO_2: \".................nikto neujde.\"\n  STR_OUTRO_3: \"Hrobkou otriasla masívna erupcia a prehnala sa celým mestom. Trosky a dym zaplnili ovzdušie. Plány mimozemšťanov sú zhatené........\"\n  STR_OUTRO_4: \"Pokrivená veľkosť mesta T'leth začína praskať. Jeho žiariace veže a adamantiové sieňe chŕlia len oheň a dym.\"\n  STR_OUTRO_5: \"Mocná mimozemská bašta sa rúti do mora, kvílenie krútiaceho sa kovu a duší sa šíri priestorom. Už nikdy viac nebude Veľký Spáč snívať o dobývaní sveta.\"\n  STR_OUTRO_6: \"Nakoniec v uši drásajúcom zvuku sa veľké mesto T'leth rozpadne na kusy.{NEWLINE}Mimozemská hrozba pominula, Zem je očistená..................\"\n  STR_OUTRO_7: \"Ospalá modro-zelená planéta kdesi vo vzdialenom kúte galaxie.\"\n  STR_OUTRO_8: \"Blízka budúcnosť je bezpečným miestom k životu.\"\n  STR_OUTRO_9: \"Mimozemská hrozba pre Zem už je dávno zažehnaná.\"\n  STR_OUTRO_10: \"Obrovské mestské metropole obývajú miliardy ľudských bytostí.\"\n  STR_OUTRO_11: \"Hrdinské činy X-Com vo vojnách s mimozemšťanmi sa stali súčasťou detských príbehov.\"\n  STR_OUTRO_12: \"Avšak každá legenda má vždy v sebe zrnko pravdy............\"\n  STR_RISE_1: \"T'leth, nazývané mnohými menami v mnohých legendách z rôznych krajín.\"\n  STR_RISE_2: \"S ohlušujúcim výkrikom, ktorý sa niesol po celom svete, začalo T'leth stúpať z morského dna.\"\n  STR_RISE_3: \"Jeho obrovská konštrukcia sa valí vodami Mexického zálivu.\"\n  STR_RISE_4: \"400 miliárd ton mimozemského kovu, veľkolepé mimozemské mesto, v ktorého hlbinách leží spiace telo Všemocného mimozemšťana. Uväzneného na zemi 65 miliónov rokov sa tento zákerný vesmírny Boh začína preberať k životu.\"\n  STR_RISE_5: \"Voda v oceáne sa varí a múti ako sa hrobka Veľkého spáča prediera na svetlo sveta................\"\n  STR_RISE_6: \".........svetlo, ktoré nebude mať dlhého trvania, ak sa X-Comu podarí zničiť mimozemskú vojnovú mašinériu.\"\n  STR_YOU_HAVE_FAILED: \"Zlyhal si, nepodarilo sa ti zastaviť mimozemskú vojnovú mašinériu. Výbor, zbavený ilúzií o tvojej schopnosti viesť boj z mimozemšťanmi, sa pokúsil o nevojenské riešenie. Avšak okupanti mali svoje vlastné plány a svet sa čoskoro dozvedel celú pravdu...\"\n  STR_TOTAL_UC: \"CELKOM\"\n  STR_INCOME: \"Príjmy\"\n  STR_EXPENDITURE: \"Výdavky\"\n  STR_MAINTENANCE: \"Údržba\"\n  STR_BALANCE: \"Zostatok\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"Mimozemská aktivita v moriach\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"Mimozemská aktivita v zónach\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"Aktivita X-Com v moriach\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"Aktivita X-Com v zónach\"\n  STR_FINANCE: \"Financie\"\n  STR_DATE_FIRST: \"{0}.\"\n  STR_DATE_SECOND: \"{0}.\"\n  STR_DATE_THIRD: \"{0}.\"\n  STR_DATE_FOURTH: \"{0}.\"\n  STR_FINANCE_THOUSANDS: \"$1000's\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Nemáme dostatok špeciálnych materiálov na výrobu{NEWLINE}{0}{NEWLINE}v{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Nemáme dosatok financií na výrobu{NEWLINE}{0}{NEWLINE}v{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"Dokončená výroba predmetu{NEWLINE}{0}{NEWLINE}na základni{NEWLINE}{1}{NEWLINE}\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"Výstavba{NEWLINE}{0}{NEWLINE}v{NEWLINE}{1}{NEWLINE}je ukončená\"\n  STR_OK_5_SECONDS: \"OK - 5 sek\"\n  STR_RESEARCH_COMPLETED: \"Výskum dokončený\"\n  STR_VIEW_REPORTS: \"PREZRIEŤ HLÁSENIA\"\n  STR_WE_CAN_NOW_RESEARCH: \"Teraz môžeme skúmať\"\n  STR_WE_CAN_NOW_PRODUCE: \"Môžeme vyrábať\"\n  STR_SUNDAY: \"NEDEĽA\"\n  STR_MONDAY: \"PONDELOK\"\n  STR_TUESDAY: \"UTOROK\"\n  STR_WEDNESDAY: \"STREDA\"\n  STR_THURSDAY: \"ŠTVRTOK\"\n  STR_FRIDAY: \"PIATOK\"\n  STR_SATURDAY: \"SOBOTA\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Nedostatok {0} na dotankovanie {1} v {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Nedostatok {0} na vzybrojenie {1} v {2}\"\n  STR_UFO_IS_NOT_RECOVERED: \"MIMOZEMSKÁ PONORKA nebola zaistená\"\n  STR_UFO_IS_RECOVERED: \"MIMOZEMSKÁ PONORKA bola vyzdvihnutá\"\n  STR_CRAFT_IS_LOST: \"Ponorka bola zničená\"\n  STR_TERROR_CONTINUES: \"Mimozemská aktivita v krajinách\"\n  STR_ALIENS_DEFEATED: \"Mimozemšťania boli porazení\"\n  STR_BASE_IS_LOST: \"Prišli sme o základňu\"\n  STR_BASE_IS_SAVED: \"Základňu sme ubránili\"\n  STR_ALIEN_BASE_STILL_INTACT: \"Kolónia mimozemšťanov je stále nepoškodená\"\n  STR_ALIEN_BASE_DESTROYED: \"Kolónia mimozemšťanov bola zničená\"\n  STR_ALIENS_KILLED: \"MIMOZEMŠŤANIA ZABITÍ\"\n  STR_ALIEN_CORPSES_RECOVERED: \"ZÍSKANÉ TELÁ MIMOZEMŠŤANOV\"\n  STR_LIVE_ALIENS_RECOVERED: \"ZAJATÝCH ŽIVÝCH MIMOZEMŠŤANOV\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"ZÍSKANÉ MIMOZEMSKÉ ARTEFAKTY\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"RIADENIE MIMOZEMSKEJ KOLÓNIE ZNIČENÉ\"\n  STR_ALIEN_SYNOMIUM_DEVICE_DESTROYED: \"SYNOMIUM BOLO ZNIČENÉ\"\n  STR_ALIEN_SYNOMIUM_DEVICE_FAILED: \"SYNOMIUM SA NEPODARILO ZNIČIŤ\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"CIVILISTI ZABITÍ MIMOZEMŠŤANMI\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"CIVILISTI ZABITÍ JEDNOTKAMI X-COM\"\n  STR_CIVILIANS_SAVED: \"ZACHRANENÍ CIVILISTI\"\n  STR_XCOM_OPERATIVES_KILLED: \"ZABITÍ AGENTI X-COM\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"AGENTI X-COM STRATENÍ V AKCII\"\n  STR_TANKS_DESTROYED: \"ZNIČENÉ ZBRAŇOVÉ SYSTÉMY X-COMu\"\n  STR_XCOM_CRAFT_LOST: \"PONORKA X-COM ZNIČENÁ\"\n  STR_UFO_RECOVERY: \"ZAISTENIE PONORKY MIMOZEMŠŤANOV\"\n  STR_ALIEN_BASE_RECOVERY: \"DOBÝVANIE KOLÓNIE MIMOZEMŠŤANOV\"\n  STR_BASE_UNDER_ATTACK: \"{0} pod paľbou!\"\n  STR_BASE_DEFENSES_INITIATED: \"OBRANA ZÁKLADNE INICIALIZOVANÁ\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"ŠTÍTY ODRÁŽAJÚ PONORKU!\"\n  STR_FIRING: \"STREĽBA\"\n  STR_HIT: \"ZÁSAH!\"\n  STR_UFO_DESTROYED: \"MIMOZEMSKÁ PONORKA ZNIČENÁ!\"\n  STR_MISSED: \"VEDĽA!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Predaj predmety/Prepusti personál\"\n  STR_VALUE_OF_SALES: \"HODNOTA PREDAJA> {ALT}{0}\"\n  STR_FUNDS: \"FINANCIE> {ALT}{0}\"\n  STR_SELL_SACK: \"Predať/Prepustiť\"\n  STR_VALUE: \"Cena\"\n  STR_CRAFT_: \"PONORKA> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"ZAISTENIE POTOPENEJ PONORKY\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"UPOZORNENIE - v ponorke alebo okolí miesta havárie sa stále môžu pohybovať živí mimozemšťania. Misia bude úspešná pokiaľ budú všetky opozičné jednotky eliminované či zneškodnené. Následne bude zahájený presun zvyškov mimozemskej ponorky, artefaktov a mŕtvol mimozemšťanov späť na základňu. Ak chcete predčasne ukončiť misiu, musia sa všetci akvanauti X-Com vrátiť do ponorky, inak budú zanechaní na mieste. Misiu zrušíte kliknutím na ikonu 'Zrušiť misiu'.\"\n  STR_UFO_GROUND_ASSAULT: \"ÚTOK NA MIMOZEMSKÚ PONORKU\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"Preskúmajte miesto pristátia, a pokiaľ možno, získajte vstup do ponorky. Misia bude úspešná pokiaľ budú všetky opozičné jednotky eliminované či zneškodnené. Následne bude zahájený presun častí ponorky, artefaktov a mŕtvol mimozemšťanov späť na základňu. Ak chcete predčasne ukončiť misiu, musia sa všetci akvanauti X-Com vrátiť do ponorky, inak budú zanechaní na mieste. Misiu zrušíte kliknutím na ikonu 'Zrušiť misiu'.\"\n  STR_BASE_DEFENSE: \"OBRANA ZÁKLADNE\"\n  STR_BASE_UC_: \"ZÁKLADŇA> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"Bolo detekované mimozemské plavidlo. Naša základňa je v nebezpečenstve. Podľa štandardných bezpečnostných protokolov všetok nebojový personál a plavidlá X-Com boli evakuované. Mimozemské jednotky sa pokúsia do základne preniknúť cez doky alebo vzduchový uzáver. Ochráňte základňu a jej kľúčové zariadenia za každú cenu - toto je boj na smrť. Kliknutie na 'opustiť misiu' bude znamenať okamžitú porážku a stratu základne.\"\n  STR_ALIEN_COLONY_ATTACK_MISSION: \"MISIA: ÚTOK NA MIMOZEMSKÚ KOLÓNIU\"\n  STR_ALIEN_BASE_ASSAULT: \"MIMOZEMSKÁ KOLÓNIA ČASŤ PRVÁ\"\n  STR_ALIEN_COLONY_P1_BRIEFING: \"Táto misia je prepadnutím kolónie mimozemšťanov. Misia sa skladá z dvoch častí. Vašou prvou úlohou je dostať všetkých akvanaoutov k hlavnému vchodu do podzemia a kliknúť na ikonu 'Zrušiť misiu', alebo zlikvidovať všetkých mimozemšťanov v oblasti. Všetko vybavenie ostane na morskom dne až do doby ukončenia misie v druhej časti kolónie. Ak chcete misiu ukončiť, premiestite všetkých akvanautov do ponorky a kliknite na ikonu 'Zrušiť misiu'.\"\n  STR_ALIEN_COLONY_P2: \"MIMOZEMSKÁ KOLÓNIA ČASŤ DRUHÁ\"\n  STR_ALIEN_COLONY_P2_BRIEFING: \"Podarilo sa vám preniknúť do útrob kolónie mimozemšťanov. Vašou úlohou teraz bude zničiť riadiace centrum, zariadenie Synomium alebo zneškodniť všetkých mimozemšťanov vo vnútri kolónie. Pre ukončenie misie umiestnite všetkých akvanautov do vstupnej oblasti a kliknite na ikonu 'Zrušiť misiu'. Všetko použiteľné vybavenie X-Comu bude vrátené späť na základňu.\"\n  STR_ALIENS_LAUNCH_PORT_TERROR: \"MIMOZEMŠŤANIA ÚTOČIA{NEWLINE}NA PRÍSTAV\"\n  STR_PORT_TERROR: \"MIMOZEMŠŤANIA ÚTOČIA NA PRÍSTAV\"\n  STR_PORT_TERROR_BRIEFING: \"Bol hlásený útok mimozemšťanov na súši. Prístav a jeho civilné osadenstvo je v nebezpečenstve. Vaša jednotka musí eliminovať všetkých votrelcov a ochrániť nevinných okolostojacich občanov. Pre ukončenie misie umiestnite všetkých akvanautov do ponorky a stlačte ikonu 'Zrušiť misiu'.\"\n  STR_ALIENS_LAUNCH_ISLAND_TERROR: \"MIMOZEMŠŤANIA ÚTOČIA{NEWLINE}NA OSTROV\"\n  STR_ISLAND_TERROR: \"MIMOZEMŠŤANIA ÚTOČIA NA OSTROV\"\n  STR_ISLAND_TERROR_BRIEFING: \"Bol hlásený útok mimozemšťanov na súši. Civilné obyvateľstvo ostrova je v nebezpečenstve. Vaša jednotka musí eliminovať všetkých votrelcov a ochrániť nevinných domorodcov i dovolenkujúcich občanov. Pre ukončenie misie umiestnite všetkých akvanautov do ponorky a stlačte ikonu 'Zrušiť misiu'.\"\n  STR_ALIENS_ATTACK_SHIPPING_ROUTE: \"MIMOZEMŠŤANIA ÚTOČIA{NEWLINE}NA OBCHODNÚ TRASU\"\n  STR_CARGO_SHIP_P1: \"NÁKLADNÁ LOĎ ČASŤ PRVÁ\"\n  STR_CARGO_SHIP_P2: \"NÁKLADNÁ LOĎ ČASŤ DRUHÁ\"\n  STR_CRUISE_SHIP_P1: \"VÝLETNÁ LOĎ ČASŤ PRVÁ\"\n  STR_CRUISE_SHIP_P2: \"VÝLETNÁ LOĎ ČASŤ DRUHÁ\"\n  STR_SHIP_RESCUE_MISSION: \"MISIA: ZÁCHRANA LODE\"\n  STR_SHIP_RESCUE_P1_BRIEFING: \"Deratizačná misia - musíte eliminovať všetkých mimozemšťanov na lodi a chrániť životy civilistov na palube. Mimozemšťania sa rozmiestnili po celej lodi – na povrchu ako i v podpalubí. Primárne je potrebné zabezpečiť palubu, potom je možné vstúpiť do podpalubia.  Pre ukončenie misie umiestnite všetkých akvanautov do ponorky a stlačte ikonu 'Zrušiť misiu'.\"\n  STR_SHIP_RESCUE_P2_BRIEFING: \"Po vyčistení hornej paluby môžete vstúpiť do podpalubia. Na zostup do podpalubia použijete nákladný výťah. Vaša jednotka musí eliminovať všetkých votrelcov na tejto úrovni. Pre ukončenie misie umiestnite všetkých akvanautov do vstupného výťahu a stlačte ikonu 'Zrušiť misiu'.\"\n  STR_ALIEN_ACTIVITY_DETECTED: \"ZACHYTENÁ MIMOZEMSKÁ AKTIVITA\"\n  STR_ALIEN_CONTACT_SITE_MISSION: \"MISIA: MIMOZEMSKÝ KONTAKT\"\n  STR_ARTIFACT_SITE_P1: \"MIMOZEMSKÝ KONTAKT ČASŤ PRVÁ\"\n  STR_ARTIFACT_SITE_P1_BRIEFING: \"Cieľom tejto misie je prepadnutie čerstvo aktivovaného mimozemského komunikačného uzla. Táto misia bude mať dve fázy. Na morskom dne sa nachádzajú pyramídy a pod nimi skrytá základňa mimozemšťanov. Vašou úlohou bude dostať akvanautov do vstupu do podzemného komplexu zariadenia. Dostaňte ich na toto miesto a stlačte ikonu 'Zrušiť misiu' pre pokračovanie do ďalšej časti. Ak chcete misiu ukončiť, premiestite všetkých akvanautov do ponorky a kliknite na ikonu 'Zrušiť misiu'.\"\n  STR_ARTIFACT_SITE_P2: \"MIMOZEMSKÝ KONTAKT ČASŤ DRUHÁ\"\n  STR_ARTIFACT_SITE_P2_BRIEFING: \"Podarilo sa vám preniknúť do útrob kolónie podzemného komplexu. Vašou úlohou teraz bude dostať sa do základne a zničiť Synomium - zariadenie molekulárnej kontroly. Pre ukončenie misie umiestnite všetkých akvanautov do vstupnej oblasti a kliknite na ikonu 'Zrušiť misiu'. \"\n  STR_SIGSBEE_DEEP_MISSION: \"SIGSBEEHO HLBINA{NEWLINE}MIMOZEMSKÉ MESTO PRVÁ ÚROVEŇ\"\n  STR_TLETH_P1_BRIEFING: \"Vstupujeme do neznáma. V týchto miestach nás môže čakať čokoľvek. Vieme, že sú pred nami dve ďalšie úrovne mimozemského mesta a vaša jednotka musí čo najrýchlejšie nájsť vstup do ďalšej úrovne mesta. Pre vstup do ďalšej úrovne mesta umiestnite všetkých akvanautov do výťahu a kliknite na ikonu 'Zrušiť misiu'. Zrušenie misie kdekoľvek inde bude mať za následok zlyhanie misie. \"\n  STR_TLETH_ATTACK_MISSION: \"ÚTOK NA T'LETH {NEWLINE}MIMOZEMSKÉ MESTO DRUHÁ ÚROVEŇ\"\n  STR_TLETH_P2_BRIEFING: \"Sme stále hlbšie v neznámom priestore, v týchto miestach môžeme očakávať nečakané. Vieme, že nás od nášho cieľa delí ešte jedna úroveň mimozemského mesta. Vaša jednotka sa musí čo najrýchlejšie dostať k vstupu do ďalšej úrovne mesta. Pre vstup do ďalšej úrovne mesta umiestnite všetkých akvanautov do výťahu a kliknite na ikonu 'Zrušiť misiu'. Zrušenie misie kdekoľvek inde bude mať za následok zlyhanie misie. \"\n  STR_FINAL_TLETH_MISSION: \"FINÁLNY ÚTOK NA T'LETH {NEWLINE}MIMOZEMSKÉ MESTO TRETIA ÚROVEŇ\"\n  STR_TLETH_P3_BRIEFING: \"Už nieto návratu – blížime sa k cieľu misie. Tu musia vaše jednotky prehľadať hrobku Všemocného mimozemšťana a zničiť všetkých 8 napájacích staníc, ktoré ju zásobujú energiou. Koniec mimozemskej hrozby je blízko. Nevzdávajte sa! Zrušenie misie bude mať za následok jej zlyhanie.\"\n  STR_TLETH_P1: \"MIMOZEMSKÉ MESTO PRVÁ ÚROVEŇ\"\n  STR_TLETH_P2: \"MIMOZEMSKÉ MESTO DRUHÁ ÚROVEŇ\"\n  STR_TLETH_P3: \"MIMOZEMSKÉ MESTO TRETIA ÚROVEŇ\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"NIE JE VOĽNÝ DOK PRE ZAČATIE VÝROBY PLAVIDLA!{SMALLLINE}Každé plavidlo pridelené na základňu, presunuté na základňu, kúpené alebo skonštruované využíva jeden dok. Postavte nový dok alebo presuňte plavidlo do inej základne. \"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"NIE JE VOĽNÝ DOK PRE KUPOVANÉ PLAVIDLO!{SMALLLINE}Každé plavidlo pridelené na základňu, presunuté na základňu, kúpené alebo skonštruované využíva jeden dok. Postavte nový dok alebo presuňte plavidlo do inej základne.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"NIE JE VOĽNÝ DOK PRE TRANSFER PLAVIDLA!{SMALLLINE}Každé plavidlo pridelené na základňu, presunuté na základňu, kúpené alebo skonštruované využíva jeden dok. Postavte nový dok alebo presuňte plavidlo do inej základne. \"\n  STR_CANNOT_BUILD_HERE: \"NA TOMTO MIESTE NIE JE MOŽNÉ STAVAŤ!{SMALLLINE}Nové zariadenie môžete postaviť len vedľa existujúceho zariadenia.\"\n  STR_NO_FREE_ACCOMODATION: \"K DISPOZÍCII NIE SÚ DOSTATOČNÉ UBYTOVACIE KAPACITY!{SMALLLINE}Cieľová základňa nemá dostatok miesta v ubytovniach.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"NEDOSTATOK VOĽNÉHO PRACOVNÉHO MIESTA!{SMALLLINE}Postavte novú dielňu, alebo znížte výrobu na iných projektoch.\"\n  STR_NOT_ENOUGH_MONEY: \"NEDOSTATOK FINANCIÍ!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"NEDOSTATOK MIESTA V SKLADOCH!{SMALLLINE}Postavte nové skladové priestory alebo presuňte existujúce zásoby do inej základne.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"NEDOSTATOČNÁ UBYTOVACIA KAPACITA!{SMALLLINE}Postav nové ubytovacie priestory alebo presuň personál na inú základňu.\"\n  STR_LAUNCH_INTERCEPTION: \"ZAHÁJIŤ STÍHANIE\"\n  STR_CRAFT: \"PLAVIDLO\"\n  STR_STATUS: \"STAV\"\n  STR_BASE: \"ZÁKLADŇA\"\n  STR_READY: \"PRIPRAVENÝ\"\n  STR_OUT: \"MIMO\"\n  STR_REPAIRS: \"OPRAVY\"\n  STR_REFUELLING: \"TANKUJE\"\n  STR_REARMING: \"ZBROJENIE\"\n  STR_TARGET: \"CIEĽ: {0}\"\n  STR_WAY_POINT: \"SÚRADNICE\"\n  STR_ARE_YOU_SURE_CYDONIA: \"Skutočne chceš vyslať toto plavidlo na misiu do T'leth?\"\n  STR_YES: \"ÁNO\"\n  STR_NO: \"NIE\"\n  STR_SELECT_DESTINATION: \"OZNAČ CIEĽOVÉ MIESTO\"\n  STR_CYDONIA: \"T'LETH\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"ZVOĽ MIESTO PRE NOVÚ ZÁKLADŇU\"\n  STR_RETURN_TO_BASE: \"NÁVRAT NA ZÁKLADŇU\"\n  STR_SELECT_NEW_TARGET: \"OZNAČ NOVÝ CIEĽ\"\n  STR_PATROL: \"HLIADKOVAŤ\"\n  STR_STATUS_: \"STAV>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"POŠKODENÉ - VRACIA SA NA ZÁKLADŇU\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"MÁLO PALIVA - VRACIA SA NA ZÁKLADŇU\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"MISIA ÚSPEŠNÁ - VRACIAME SA NA ZÁKLADŇU\"\n  STR_PATROLLING: \"HLIADKUJE\"\n  STR_TAILING_UFO: \"SLEDUJE PONORKU\"\n  STR_INTERCEPTING_UFO: \"PRENASLEDUJE PONORKU-{0}\"\n  STR_RETURNING_TO_BASE: \"VRACIA SA NA ZÁKLADŇU\"\n  STR_DESTINATION_UC_: \"MIESTO URČENIA: {0}\"\n  STR_BASE_UC: \"ZÁKLADŇA>{ALT}{0}\"\n  STR_SPEED_: \"RÝCHLOSŤ>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"MAXIMÁLNA RÝCHLOSŤ>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"HĹBKA>{ALT}{0}\"\n  STR_AIRBORNE: \"VO VZDUCHU\"\n  STR_VERY_LOW: \"PLYTKÁ\"\n  STR_LOW_UC: \"NORMÁLNA\"\n  STR_HIGH_UC: \"HLBOKÁ\"\n  STR_VERY_HIGH: \"VEĽMI HLBOKÁ\"\n  STR_FUEL: \"PALIVO>{ALT}{0}\"\n  STR_WEAPON_ONE: \"ZBRAŇ-1>{ALT}{0}\"\n  STR_NONE_UC: \"Prázdný\"\n  STR_ROUNDS_: \"NÁBOJE>{ALT}{0}\"\n  STR_WEAPON_TWO: \"ZBRAŇ-2>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"PONORKA\"\n  STR_BASE_: \"Základňa>{0}\"\n  STR_NAME_UC: \"MENO\"\n  STR_AMMO_: \"MUNÍCIA>{ALT}{0}\"\n  STR_CREW: \"POSÁDKA\"\n  STR_EQUIPMENT_UC: \"VYBAVENIE\"\n  STR_ARMOR: \"ZBROJ\"\n  STR_MAX: \"MAX>{ALT}{0}\"\n  STR_ROOKIE: \"Plavčík\"\n  STR_SQUADDIE: \"Námorník\"\n  STR_SERGEANT: \"Praporčík\"\n  STR_CAPTAIN: \"Poručík\"\n  STR_COLONEL: \"Komandér\"\n  STR_COMMANDER: \"Kapitán\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Vyberte bojový tím pre {0}\"\n  STR_SORT_BY: \"ZORADIŤ PODĽA...\"\n  STR_ORIGINAL_ORDER: \"PÔVODNÉ PORADIE\"\n  STR_MISSIONS2: \"POČET MISIÍ\"\n  STR_KILLS2: \"POČET ZABITÍ\"\n  STR_WOUND_RECOVERY2: \"DOBA ZOTAVENIA\"\n  STR_SPACE_AVAILABLE: \"DOSTUPNÉ MIESTO>{ALT}{0}\"\n  STR_SPACE_USED: \"POUŽITÉ MIESTO>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"POUŽITÉ MIESTO\"\n  STR_RANK: \"HODNOSŤ\"\n  STR_WOUNDED: \"ZRANENÝ\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Vybavenie pre {0}\"\n  STR_DEFENSE_VALUE: \"Hodnota obrany\"\n  STR_HIT_RATIO: \"Pravdepodobnosť zásahu\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}pripravený na{NEWLINE}dosadnutie v blízkosti{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"Začať misiu?\"\n  STR_SELECT_ARMAMENT: \"Vybrať výzbroj\"\n  STR_AMMUNITION_AVAILABLE: \"DOSTUPNÁ MUNÍCIA\"\n  STR_ARMAMENT: \"VÝZBROJ\"\n  STR_NOT_AVAILABLE: \"NIE JE\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"VYBRAŤ ZBROJ PRE {NEWLINE}{ALT}{0}\"\n  STR_TYPE: \"TYP\"\n  STR_PLASTIC_AQUA_ARMOR_UC: \"AKVAPLASTIK ZBROJ\"\n  STR_ION_ARMOR_UC: \"IÓNOVÁ ZBROJ\"\n  STR_MAGNETIC_ION_ARMOR_UC: \"MAGNETO-IÓNOVÁ ZBROJ\"\n  STR_PLASTIC_AQUA_ARMOR_UFOPEDIA: \"Táto zbroj je postavená na nedávno objavenej mimozemskej substancii - akvaplaste - zaistí, že naši akvanauti budú mať v boji s mimozemskou inváziou väčšiu šancu na prežitie. \"\n  STR_ION_ARMOR_UFOPEDIA: \"Nová výkonná zbroj pre akvanautov je napájaná z iónového generátora. Značne zosiľňuje rýchlosť a silu nositeľa a poskytuje zatiaľ najlepšiu ochranu pre naše jednotky.\"\n  STR_MAGNETIC_ION_ARMOR_UFOPEDIA: \"Vylepšená verzia iónovej zbroje obsahujúca technológiu magnetických polí, umožňujúca úplnu slobodu pohybu v podmorskom prostredí.\"\n  STR_SELECT_ARMOR: \"Vybrať zbroj\"\n  STR_NORTH: \"SEVER\"\n  STR_NORTH_EAST: \"SEVEROVÝCHOD\"\n  STR_EAST: \"VÝCHOD\"\n  STR_SOUTH_EAST: \"JUHOVÝCHOD\"\n  STR_SOUTH: \"JUH\"\n  STR_SOUTH_WEST: \"JUHOZÁPAD\"\n  STR_WEST: \"ZÁPAD\"\n  STR_NORTH_WEST: \"SEVEROZÁPAD\"\n  STR_SELECT_ACTION: \"VYBER AKCIU\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"POKRAČUJ V ÚTOKU\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"SLEDUJ BEZ STÍHANIA\"\n  STR_VERY_LARGE: \"VEĽMI VEĽKÁ\"\n  STR_LARGE: \"VEĽKÁ\"\n  STR_MEDIUM_UC: \"STREDNÁ\"\n  STR_SMALL: \"MALÁ\"\n  STR_VERY_SMALL: \"VEĽMI MALÁ\"\n  STR_GROUNDED: \"PRISTÁLA\"\n  STR_DETECTED: \"Zistená\"\n  STR_SIZE_UC: \"VEĽKOSŤ\"\n  STR_ALTITUDE: \"HĹBKA\"\n  STR_HEADING: \"SMER\"\n  STR_SPEED: \"RÝCHLOSŤ\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"VYCENTROVAŤ NA PONORKU-ČAS=5 sek\"\n  STR_TRACKING_LOST: \"STRATILI SME KONTAKT\"\n  STR_REDIRECT_CRAFT: \"PRESMEROVAŤ PLAVIDLO\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"ÍSŤ NA POSLEDNÚ ZNÁMU POZÍCIU PONORKY\"\n  STR_UFO_: \"PONORKA-{0}\"\n  STR_ALIEN_BASE_: \"MIMOZEMSKÁ KOLÓNIA-{0}\"\n  STR_CRASH_SITE_: \"MIESTO HAVÁRIE-{0}\"\n  STR_LANDING_SITE_: \"MIESTO PRISTÁTIA-{0}\"\n  STR_WAY_POINT_: \"SÚRADNICA-{0}\"\n  STR_TERROR_SITE: \"MIESTO TERORU-{0}\"\n  STR_ARTIFACT_SITE: \"MIMOZEMSKÝ ARTEFAKT-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}dorazil{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"Hliadkuje\"\n  STR_ALIEN_ORIGINS: \"Pôvod mimozemšťanov\"\n  STR_THE_ULTIMATE_THREAT: \"Definitívna hrozba\"\n  STR_TLETH_ALIEN_CITY: \"T'leth, mesto mimozemšťanov\"\n  STR_UFOPAEDIA: \"UFOpédia\"\n  STR_XCOM_CRAFT_ARMAMENT: \"VÝZBROJ A STROJE X-COMu\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"PODMORSKÉ ZBRAŇOVÉ SYSTÉMY\"\n  STR_WEAPONS_AND_EQUIPMENT: \"VYBAVENIE\"\n  STR_ALIEN_ARTIFACTS: \"PODMORSKÉ ARTEFAKTY\"\n  STR_BASE_FACILITIES: \"ZARIADENIA X-COM ZÁKLADNE\"\n  STR_ALIEN_LIFE_FORMS: \"MIMOZEMSKÉ TVORY\"\n  STR_ALIEN_RESEARCH_UC: \"MIMOZEMSKÉ TECHNOLÓGIE\"\n  STR_UFO_COMPONENTS: \"NOVÉ PODMORSKÉ TECHNOLÓGIE\"\n  STR_UFOS: \"MIMOZEMSKÉ PONORKY\"\n  STR_SELECT_ITEM: \"OZNAČ POLOŽKU\"\n  STR_ACCELERATION: \"AKCELERÁCIA>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"KAPACITA PALIVA>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"MIESTO PRE ZBRANE>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"PANCIEROVANIE>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"NÁKLADNÝ PRIESTOR>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"KAPACITA PZS>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Poškodenie\"\n  STR_RANGE: \"Dostrel\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Presnosť\"\n  STR_RE_LOAD_TIME: \"Dĺžka prebitia\"\n  STR_SECONDS: \"{0}s\"\n  STR_DAMAGE_ARMOR_PIERCING: \"PRIERAZNÉ\"\n  STR_DAMAGE_INCENDIARY: \"FOSFOROVÉ\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"SILNÁ VÝBUŠNINA\"\n  STR_DAMAGE_LASER_BEAM: \"GAUSSOV LÚČ\"\n  STR_DAMAGE_PLASMA_BEAM: \"SONICKÝ LÚČ\"\n  STR_DAMAGE_STUN: \"ZMRAZENIE\"\n  STR_DAMAGE_MELEE: \"BOJ Z BLÍZKA\"\n  STR_DAMAGE_ACID: \"KYSELINA\"\n  STR_DAMAGE_SMOKE: \"DYM\"\n  STR_SHOT_TYPE: \"TYP\"\n  STR_ACCURACY_UC: \"PRESNOSŤ\"\n  STR_TIME_UNIT_COST: \"CENA AB\"\n  STR_DAMAGE_UC: \"POŠKODENIE\"\n  STR_AMMO: \"MUNÍCIA\"\n  STR_SHOT_TYPE_AUTO: \"Automat\"\n  STR_SHOT_TYPE_SNAP: \"Rýchla\"\n  STR_SHOT_TYPE_AIMED: \"Mierená\"\n  STR_CONSTRUCTION_TIME: \"Čas výstavby\"\n  STR_CONSTRUCTION_COST: \"Cena výstavby\"\n  STR_MAINTENANCE_COST: \"Cena údržby\"\n  STR_LOW: \"Nízke\"\n  STR_MEDIUM: \"Stredné\"\n  STR_HIGH: \"Vysoko\"\n  STR_CRAFT_WEAPON: \"Palubná zbraň\"\n  STR_CRAFT_AMMUNITION: \"Munícia pre ponorky\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Ťažký zbraňový systém\"\n  STR_WEAPON: \"Zbraň\"\n  STR_AMMUNITION: \"Munícia\"\n  STR_EQUIPMENT: \"Výbava\"\n  STR_ALIEN_CORPSE: \"Mŕtvola mimozemšťana\"\n  STR_UFO_COMPONENT: \"komponent PONORKY\"\n  STR_PERSONAL_ARMOR: \"Osobná zbroj\"\n  STR_RAW_MATERIALS: \"Nespracované materiály\"\n  STR_HWP_SOLID_HARPOON_BOLTS: \"Tvrdené harpúnové šípy\"\n  STR_ALIEN: \"Mimozemšťan\"\n  STR_AQUATOID: \"Akvatoid\"\n  STR_GILLMAN: \"Gillman\"\n  STR_LOBSTERMAN: \"Lobsterman\"\n  STR_TASOTH: \"Tasoth\"\n  STR_CALCINITE: \"Kalcinit\"\n  STR_DEEP_ONE: \"Hĺbkomor\"\n  STR_BIODRONE: \"Bio-dron\"\n  STR_TENTACULAT: \"Chápadlovec\"\n  STR_TRISCENE: \"Triscen\"\n  STR_HALLUCINOID: \"Halucinoid\"\n  STR_XARQUID: \"Xarkid\"\n  STR_ZOMBIE: \"Zombie\"\n  STR_LIVE_COMMANDER: \"Komandér\"\n  STR_LIVE_NAVIGATOR: \"Navigátor\"\n  STR_LIVE_MEDIC: \"Medik\"\n  STR_LIVE_TECHNICIAN: \"Technik\"\n  STR_LIVE_SQUAD_LEADER: \"Veliteľ jednotky\"\n  STR_LIVE_SOLDIER: \"Vojak\"\n  STR_LIVE_TERRORIST: \"Terorista\"\n  STR_AQUATOID_COMMANDER: \"Akvatoid Komandér\"\n  STR_AQUATOID_NAVIGATOR: \"Akvatoid Navigátor\"\n  STR_AQUATOID_MEDIC: \"Akvatoid Medik\"\n  STR_AQUATOID_TECHNICIAN: \"Akvatoid Technik\"\n  STR_AQUATOID_SQUAD_LEADER: \"Akvatoid Veliteľ\"\n  STR_AQUATOID_SOLDIER: \"Akvatoid Vojak\"\n  STR_GILLMAN_COMMANDER: \"Gillman Komandér\"\n  STR_GILLMAN_TECHNICIAN: \"Gillman Technik\"\n  STR_GILLMAN_SQUAD_LEADER: \"Gillman Veliteľ\"\n  STR_GILLMAN_SOLDIER: \"Gillman Vojak\"\n  STR_LOBSTERMAN_COMMANDER: \"Lobsterman Komandér\"\n  STR_LOBSTERMAN_NAVIGATOR: \"Lobsterman Navigátor\"\n  STR_LOBSTERMAN_TECHNICIAN: \"Lobsterman Technik\"\n  STR_LOBSTERMAN_SQUAD_LEADER: \"Lobsterman Veliteľ\"\n  STR_LOBSTERMAN_SOLDIER: \"Lobsterman Vojak\"\n  STR_TASOTH_SQUAD_LEADER: \"Tasoth Veliteľ\"\n  STR_TASOTH_SOLDIER: \"Tasoth Vojak\"\n  STR_CALCINITE_TERRORIST: \"Kalcinit terorista\"\n  STR_DEEP_ONE_TERRORIST: \"Hĺbkomor terorista\"\n  STR_BIODRONE_TERRORIST: \"Bio-dron terorista\"\n  STR_TENTACULAT_TERRORIST: \"Chápadlovec terorista\"\n  STR_TRISCENE_TERRORIST: \"Trisen terorista\"\n  STR_HALLUCINOID_TERRORIST: \"Halucinoid terorista\"\n  STR_XARQUID_TERRORIST: \"Xarkid teorista\"\n  STR_ION_BEAM_ACCELERATORS: \"Iónový pohon\"\n  STR_MAGNETIC_NAVIGATION: \"Magnetická navigácia\"\n  STR_ALIEN_SUB_CONSTRUCTION: \"Konštrukcia mimozemských ponoriek\"\n  STR_ALIEN_CRYOGENICS: \"Mimozemská kryogenika\"\n  STR_ALIEN_CLONING: \"Mimozemské klonovanie\"\n  STR_ALIEN_LEARNING_ARRAYS: \"Mimozemské edukačné polia\"\n  STR_ALIEN_IMPLANTER: \"Mimozemský implantér\"\n  STR_EXAMINATION_ROOM: \"Vyšetrovacia miestnosť\"\n  STR_AQUA_PLASTICS: \"Akvaplasty\"\n  STR_ALIEN_REANIMATION_ZONE: \"Mimozemská oživovacia zóna\"\n  STR_PLASTIC_AQUA_ARMOR: \"Akvaplastová zbroj\"\n  STR_ION_ARMOR: \"Iónová zbroj\"\n  STR_MAGNETIC_ION_ARMOR: \"Mag. Iónová zbroj\"\n  STR_HWP_AQUA_JET_MISSILES: \"Akva-prúdové torpéda\"\n  STR_HWP_DISPLACER_PWT: \"Pulzné torpédo\"\n  STR_GAUSS_TECH: \"Gaussova technológia\"\n  STR_NEW_FIGHTER_FLYING_SUB: \"Nová bojová ponorka\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Nový stíhač-transportér\"\n  STR_THE_LATEST_FLYING_SUB: \"Najnovší typ ponorky\"\n  STR_ARMOR_PIERCING: \"PRIERAZNÉ\"\n  STR_COELACANTH_GAS_CANNON: \"Obojživelník/Plynový kanón\"\n  STR_COELACANTH_AQUA_JET: \"Obojživelník/Torpédomet\"\n  STR_COELACANTH_GAUSS: \"Obojživelník/Gaussov kanón\"\n  STR_DISPLACER_SONIC: \"Displacer/Sonický kanón\"\n  STR_DISPLACER_PWT: \"Displacer/Pulzné torpédo\"\n  STR_AJAX_LAUNCHER: \"Odpaľovač torpéd Ajax\"\n  STR_DUP_HEAD_LAUNCHER: \"S.O.U. torpédomet\"\n  STR_CRAFT_GAS_CANNON: \"Závesný plyn. kanón\"\n  STR_PWT_CANNON: \"P.T. Torpédomet\"\n  STR_GAUSS_CANNON: \"Gaussov kanón\"\n  STR_GAUSS_CANNON_AMMO: \"Munícia pre gauss kanón\"\n  STR_SONIC_OSCILLATOR: \"Sonický oscilátor\"\n  STR_AJAX_TORPEDOES: \"Torpéda Ajax\"\n  STR_DUP_HEAD_TORPEDOES: \"Torpéda s S.O.U. hlavicou\"\n  STR_CRAFT_GAS_CANNON_ROUNDS_X50: \"Plynové náboje(x50)\"\n  STR_SONIC_WAVE: \"Sonická vlna\"\n  STR_PULSE_WAVE_TORPEDOES: \"Pulzné torpédo\"\n  STR_SOLDIER: \"Akvanaut\"\n  STR_SCIENTIST: \"Vedec\"\n  STR_ENGINEER: \"Technik\"\n  STR_NORTH_ATLANTIC: \"Severný Atlantik\"\n  STR_SOUTH_ATLANTIC: \"Južný Atlantik\"\n  STR_NORTH_PACIFIC: \"Severný Pacifik\"\n  STR_SOUTH_PACIFIC: \"Južný Pacifik\"\n  STR_MEDITERRANEAN: \"Stredomorie\"\n  STR_SOUTH_CHINA_SEA: \"Južné Čínske more\"\n  STR_INDIAN_OCEAN: \"Indický oceán\"\n  STR_THE_EAST_SEA: \"Japonské more\"\n  STR_NORTH_SEA: \"Severné more\"\n  STR_CARRIBEAN: \"Karibik\"\n  STR_ANTARCTIC: \"Antarktída\"\n  STR_ARCTIC: \"Arktída\"\n  STR_EURASIA: \"Euroázia\"\n  STR_NORTH_AMERICA: \"Severná Amerika\"\n  STR_AFRICA: \"Afrika\"\n  STR_MAXIMUM_SPEED: \"Maximálna rýchlosť\"\n  STR_TRANSMISSION_RESOLVER_UC: \"DEKÓDOVAČ PRENOSU\"\n  STR_TRITON: \"TRITON\"\n  STR_HAMMERHEAD: \"HAMMERHEAD\"\n  STR_LEVIATHAN: \"LEVIATHAN\"\n  STR_BARRACUDA: \"BARRACUDA\"\n  STR_MANTA: \"MANTA\"\n  STR_UFO: \"MIMOZEMSKÁ PONORKA\"\n  STR_AJAX: \"AJAX\"\n  STR_DUP_HEAD: \"S.O.U. HLAVICA\"\n  STR_CRAFT_GAS_CANNON_UC: \"ZÁVESNÝ PLYN. KANÓN\"\n  STR_PWT_CANNON_UC: \"P.T. TORPÉDOMET\"\n  STR_GAUSS_CANNON_UC: \"GAUSSOV KANÓN\"\n  STR_SONIC_OSCILLATOR_UC: \"SONICKÝ OSCILÁTOR\"\n  STR_DAMAGE_CAPACITY: \"Pancierovanie\"\n  STR_WEAPON_POWER: \"Sila zbrane\"\n  STR_WEAPON_RANGE: \"Dosah zbrane\"\n  STR_AIR_LOCK: \"Vzduchový uzáver\"\n  STR_LABORATORY: \"Laboratórium\"\n  STR_WORKSHOP: \"Dielňa\"\n  STR_STANDARD_SONAR: \"Štandardný sonar\"\n  STR_WIDE_ARRAY_SONAR: \"Širokopásmový sonar\"\n  STR_TORPEDO_DEFENSES: \"Torpédová obrana\"\n  STR_GENERAL_STORES: \"Sklady\"\n  STR_ALIEN_CONTAINMENT: \"Zadržiavacia cela\"\n  STR_GAUSS_DEFENSES: \"Gaussova obrana\"\n  STR_SONIC_DEFENSES: \"Sonická obrana\"\n  STR_PWT_DEFENSES: \"P.T. OBRANA\"\n  STR_BOMBARDMENT_SHIELD: \"Bombardovací štít\"\n  STR_MC_GENERATOR: \"Generátor M.K.\"\n  STR_MC_LAB: \"Laboratórim M.K.\"\n  STR_TRANSMISSION_RESOLVER: \"Dekóder prenosu\"\n  STR_SUB_PEN: \"Dok\"\n  STR_USA: \"USA\"\n  STR_ALASKA: \"ALIAŠKA\"\n  STR_EU_SYNDICATE: \"EURO-SYNDIKÁT\"\n  STR_ARABIAN_BLOC: \"ARABSKÝ BLOK\"\n  STR_EGYPTIAN_CARTEL: \"EGYPTSKÝ KARTEL\"\n  STR_AFRICA_CORP: \"AFRICA CORP\"\n  STR_BRAZILIAN_UNION: \"BRAZÍLSKA ÚNIA\"\n  STR_NEW_MEXICO: \"NOVÉ MEXIKO\"\n  STR_ASIAN_COALITION: \"ÁZIJSKÁ KOALÍCIA\"\n  STR_SCANDINAVIA: \"ŠKANDINÁVIA\"\n  STR_NEO_JAPAN: \"NOVÉ JAPONSKO\"\n  STR_FREE_CHINA: \"SLOBODNÁ ČÍNA\"\n  STR_AUSTRALASIA: \"AUSTRALOÁZIA\"\n  STR_FED_KOREA: \"KÓREJSKÁ FEDERÁCIA\"\n  STR_EURASIA_UC: \"EUROÁZIA\"\n  STR_ICELANDIC_UNION: \"ISLANDSKÁ ÚNIA\"\n  STR_TANK: \"Podmorské zbraňové systémy\"\n  STR_CIVILIAN: \"Civilista\"\n  STR_JAN: \"Jan\"\n  STR_FEB: \"Feb\"\n  STR_MAR: \"Mar\"\n  STR_APR: \"Apr\"\n  STR_MAY: \"Máj\"\n  STR_JUN: \"Jún\"\n  STR_JUL: \"Júl\"\n  STR_AUG: \"Aug\"\n  STR_SEP: \"Sep\"\n  STR_OCT: \"Okt\"\n  STR_NOV: \"Nov\"\n  STR_DEC: \"Dec\"\n  STR_INTERNATIONAL_RELATIONS: \"Medzinárodné vzťahy\"\n  STR_COUNTRY: \"Krajina\"\n  STR_FUNDING: \"Financovanie\"\n  STR_CHANGE: \"Zmena\"\n  STR_WEAPON_SYSTEMS: \"ZBRAŇOVÉ SYSTÉMY\"\n  STR_HWPS: \"PZSy\"\n  STR_DAMAGE_UC_: \"POŠKODENIE>{ALT}{0}\"\n  STR_AIR_LOCK_UFOPEDIA: \"Vzduchový uzáver slúži na prepravu vybavenia a personálu do a z podzemnej základne. Je to vždy prvé zariadenie, ktoré musí byť postavené na novom mieste. Priestor uzáveru je zraniteľný na útok potencionálnych nepriateľských síl.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Každý ubytovací blok poskytuje miesto pre 50 osôb. Zariadenie poskytuje základné rekreačné, stravovacie a ubytovacie zariadenie.\"\n  STR_LABORATORY_UFOPEDIA: \"Kapacita laborátória je maximálne 50 vedcov. Laboratóriá sú vybavené najmodernejšími technológiami pre výskum materiálov, biochémie a zbraní. X-Com má prístup k najlepším výskumným laboratóriám po celom svete, vrátane vojenských zariadení.\"\n  STR_WORKSHOP_UFOPEDIA: \"Dielne obsahujú všetko potrebné vybavenie na realizáciu projektov, ktoré vyvinuli vedci vo vedeckých laboratóriách. Až 50 technikov dokáže pracovať v jednom bloku dielní, avšak treba počítať s tým, že i konštruované predmety zaberajú nejaké miesto.\"\n  STR_STANDARD_SONAR_UFOPEDIA: \"Štandardný sonar má efektivitu cez 450 km do hĺbky a je prepojený na satelitný systém pre analýzu povrchu. Každý takýto systém ma 10%-tnú šancu objaviť ponorený alebo vzdušný objekt každých 30 minút.\"\n  STR_WIDE_ARRAY_SONAR_UFOPEDIA: \"Širokopásmový sonar dokáže efektívne zachytiť objekty do hĺbky 700 km. Je prepojený s geostacionárnymi družicami, ktoré analyzujú povrch planéty. Detektor má 20% šancu zachytiť podmorský alebo vzdušný objekt každých 30 minút.\"\n  STR_TORPEDO_DEFENSES_UFOPEDIA: \"Torpédová obrana poskytuje ochranu proti útoku nepriateľských ponoriek, ktoré sa snažia zadokovať v základni. \"\n  STR_GENERAL_STORES_UFOPEDIA: \"Všetko vybavenie, zbraňové systémy, munícia, získaný materiál a ponorné zbraňové systémy sú uložené v skladových priestoroch, vrátane vybavenia prideleného do ponoriek v dokoch.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"Aby sme udržali pri živote živých mimozemšťanov je potrebné ich uzavrieť do špeciálnych zadržiavacích ciel. Tieto jednotky ich budú udržiavať pri živote, avšak ich bojové schopnosti budú nulové. Toto zadržiavacie zariadenie dokáže udržať pri živote až 10 mimozemských životných foriem v sebestačných jednotkách.\"\n  STR_GAUSS_DEFENSES_UFOPEDIA: \"Gaussov obranný systém je najmodernejšou a najefektívnejšou ochranou proti útoku nepriateľských ponoriek.\"\n  STR_SONIC_DEFENSES_UFOPEDIA: \"Obrana postavená na sonických oscilátoroch zabezpečuje silnú a efektívnu obranu proti agresorom.\"\n  STR_PWT_DEFENSES_UFOPEDIA: \"Pulzné torpéda predstavujú najefektívnejšiu obranu proti mimozemských útokom. Tieto rakety majú super tvrdé bojové hlavice, ktoré dokážu preraziť akýkoľvek nám známy pancier. Magnetické vlny, ktoré torpédo produkuje, zneškodnia každý elektronický systém.\"\n  STR_BOMBARDMENT_SHIELD_UFOPEDIA: \"Tlakový bombardovací štít chráni základňu proti zakotveniu mimozemských ponoriek. Vytvára okolo základne rezonančné pole, ktoré odráža útočiace ponorky dostatočne dlho na to, aby obranné systémy dokázali niekoľkokrát reagovať. V praxi tento systém zdvojnásobí efektivitu obranných systémov základne.\"\n  STR_MC_GENERATOR_UFOPEDIA: \"Keďže mimozemské ponorky využívajú na detekciu živých bytostí technológiu molekulárnej kontroly, použitie negatívneho M.K. vysielača vytvorí nepreniknuteľný štít, ktorý zmätie mimozemšťanov a zakryje pred nimi našu prítomnosť.\"\n  STR_MC_LAB_UFOPEDIA: \"V laboratóriu pre molekulárnu kontrolu dokážeme implantovať a trénovať naraz až desať akvanautov. Implantáty sú chirurgicky inštalované v lebkách akvanautov. Tvrdý tréning im umožní využiť implantáty. Tieto schopnosti sú využívané za pomoci molekulárneho zariadenia a možno ich použiť počas boja i na útočné akcie.\"\n  STR_TRANSMISSION_RESOLVER_UFOPEDIA: \"Mimozemská komunikácia využíva sieť implantátov molekulárnej kontroly, ktorú vybudovali mimozemšťania. Dekódovacie oddelenie zachytáva prenos ponoriek a dekóduje informácie. Takto odhalí typ ponorky, mimozemskú rasu a typ aktivity, ktorú ponorka robí.\"\n  STR_SUB_PEN_UFOPEDIA: \"V každom doku môže kotviť jedna ponorka. Toto zariadenie obsahuje zariadenie potrebné pre údržbu a opravy ponorkovej flotily X-Com. Každé plavidlo umiestnené na základni musí mať priradený vlastný dok, ktorý nemôže byť využívaný iným plavidlom, ani keď je priradená ponorka na misii.\"\n  STR_DART_PISTOL_UFOPEDIA: \"Šípovka X-Comu je malá pištoľ na šípky, je presná, výkonná so zásobníkom na 12 dutých šípiek. Šípky sú vystreľované vďaka plynovému kartridžu umiestnenému v základni nábojov.\"\n  STR_JET_HARPOON_UFOPEDIA: \"Táto akva-puška je presná a účinná, vystreľuje duté oceľové harpúny zo zapečatených balíkov po 10. Každá harpúna má svoj vlastný plynový rezervoár. \"\n  STR_GAS_CANNON_UFOPEDIA: \"Najväčší kaliber z rodiny plynovej zbraňovej technológie, tento kanón strieľa masívne šípy, ktoré môžu mať výbušné alebo fosforové špičky. Obľúbená zbraň medzi skúsenými akvanautami. \"\n  STR_HYDRO_JET_CANNON_UFOPEDIA: \"Hydro-prúdové kanóny sú ťažkou pechotnou zbraňou. Vystreľujú minitorpéda s magnéziovým pohonom. I keď je hydro-prúdový kanón na jednej strane veľmi výkonný, je to nešikovná a ťažkopádna zbraň. Zbraň je použiteľná iba pod vodnou hladinou. \"\n  STR_TORPEDO_LAUNCHER_UFOPEDIA: \"Skutočný ťažký kaliber, tento veľký torpédomet dokáže vystreliť tri druhy torpéd, každé s vlastnou pohonnou jednotkou. Jedinou nevýhodou tejto zničujúcej zbrane je manuálne nabíjanie. Torpéda môžu mať dve veľkosti - malé a veľké s výbušnou alebo fosforovou hlavicou. Použiteľné sú len vo vode.\"\n  STR_GAUSS_PISTOL_UFOPEDIA: \"Gaussova pištoľ využíva technológiu časticového urýchľovača, čo je nový smer vo vývoji moderných zbraní. Je rýchla, presná a použiteľná ako nad vodnou hladinou tak pod ňou. Vývojovo vychádza gaussova technológia z plazmovej technológie poznanej počas predchádzajúcej vojny.\"\n  STR_GAUSS_PISTOL_CLIP_UFOPEDIA: \"Gaussova pištoľ využíva technológiu časticového urýchľovača, čo je nový smer vo vývoji moderných zbraní. Je rýchla, presná a použiteľná ako nad vodnou hladinou tak pod ňou. Vývojovo vychádza gaussova technológia z plazmovej technológie poznanej počas predchádzajúcej vojny.\"\n  STR_GAUSS_RIFLE_UFOPEDIA: \"Krok pred gaussovou pištoľou je puška, ktorá má skutočnú silu, vďaka dvojitému časticovému urýchľovaču. Namiesto elériového systém plazmového napájania sme využili mikročasticový urýchľovač, ktorý generuje prúd anti-protónov. \"\n  STR_GAUSS_RIFLE_CLIP_UFOPEDIA: \"Krok pred gaussovou pištoľou je puška, ktorá má skutočnú silu, vďaka dvojitému časticovému urýchľovaču. Namiesto elériového systém plazmového napájania sme využili mikročasticový urýchľovač, ktorý generuje prúd anti-protónov. \"\n  STR_HEAVY_GAUSS_UFOPEDIA: \"Gaussov kanón je ťakopádny, ale extrémne efektívny. Pracuje s 3 časticovými urýchľovačmi a je prakticky nezastaviteľný. Prúd anti-protónov je udržiavaný vo vnútri gálium arzenidového obalu, ktorý pri náraze imploduje a vypustí antihmotu.\"\n  STR_HEAVY_GAUSS_CLIP_UFOPEDIA: \"Gaussov kanón je ťakopádny, ale extrémne efektívny. Pracuje s 3 časticovými urýchľovačmi a je prakticky nezastaviteľný. Prúd anti-protónov je udržiavaný vo vnútri gálium arzenidového obalu, ktorý pri náraze imploduje a vypustí antihmotu.\"\n  STR_MAGNA_BLAST_GRENADE_UFOPEDIA: \"Štandardný granát s presným a sofistikovaným systémom odistenia a časovania, ktorý umožňuje precíznu kontrolu odpalu.\"\n  STR_DYE_GRENADE_UFOPEDIA: \"Tieto dymovnice, ale farbiace granáty, poskytujú krytie vo vypätých situáciách. Fungujú ako pod vodou, tak i na súši. Vypustené farbivo vytvorí časticový mrak, ktorý produkuje chobotnici podobný atrament vo vodnom prostredí a hustý dym na súši.\"\n  STR_PARTICLE_DISTURBANCE_GRENADE_UFOPEDIA: \"Nástrahový granát môže byť odhodený ako bežný granát, avšak po dopade sa dá len do stavu pohotovosti. Explózia nastane až pri zaregistrovaní pohybu v jeho blízkosti. K správnemu použitiu je potrebná veľká zručnosť a opatrnosť.\"\n  STR_MAGNA_PACK_EXPLOSIVE_UFOPEDIA: \"Táto výbušnina by sa mala využívať len na demolačné účely. Avšak v minulosti sa ukázalo, že tieto silné výbušniny sú ideálnou zbraňou na vykorenenie mimozemšťanov. Detonačné pásmo je veľké, preto zabezpečte aby boli akvanauti aspoň v minimálnej bezpečnej vzdialenosti. \"\n  STR_PARTICLE_DISTURBANCE_SENSOR_UFOPEDIA: \"Toto nové zariadenie používa množstvo detektorov a počítačových systémov pre identifikáciu pohybujúcich sa nepriateľských jednotiek. Kliknite na ikonu senzoru na taktickej obrazovke. Zvoľte 'Použiť senzor' z príslušného menu. Šípka uprostred ukazuje smerovanie akvanauta (sever je hore). Blikajúce značky ukazujú jednotky, ktoré sa v poslednej dobe pohli. Veľké alebo rýchlo sa pohybujúce jednotky vytvárajú väčšie značky. Statické jednotky sa nezobrazujú.\"\n  STR_MEDI_KIT_UFOPEDIA: \"Ak je vojak v bezvedomí, musíte stáť nad jeho telom. {NEWLINE}LIEČENIE>Vylieči jedno smrteľné zranenie a trocha zdravia pacienta. Červenou farbou vyznačené časti tela znamenajú vážne zranenia.{NEWLINE}STIMULANT>Obnoví energiu vojaka a preberie vojaka v bezvedomí. Aby ste mohli oživiť vojaka v bezvedomí je potrebné stáť priamo nad jeho telom.{NEWLINE}SEDATÍVA>Podporia morálku vašich ranených vojakov až do ekvivalentu strateného zdravia vojaka.\"\n  STR_MC_DISRUPTOR_UFOPEDIA: \"Môže byť použitá len vojakmi, ktorí dokážu využívať M.K. Počas boja, kliknite na Rušičku, vyberte typ útoku a vyberte cieľovú jednotku. Poznáme dva druhy rušiacich útokov:{NEWLINE}SKRATOVAŤ IMPLANTÁT> Úspešný útok zníži morálku cieľa, čo môže spôsobiť, že jednotka spanikári.{NEWLINE}OVLÁDNUŤ IMPLANTÁT> Ak je ovládnutie úspešné, získate okamžitú kontrolu nad nepriateľskou jednotkou, akoby to bola vaša vlastná.\"\n  STR_THERMAL_TAZER_UFOPEDIA: \"Toto zariadenie môže byť použité len v boji na blízko, avšak omráči živý organizmus zmrazením bez toho aby tento zásah tvora zabil.\"\n  STR_VIBRO_BLADE_UFOPEDIA: \"Vibro čepeľ je dlhý titánový nôž, ktorý sa otáča rýchlosťou 6000 ot./min. Táto vŕtačka dokáže prevŕtať i ten najsilnejší potápačský skafander. Napájanie zariadenia je mimozemského pôvodu. Naše predchádzajúce pokusy s touto technológiou zlyhávali, buď čepele rotovali príliš pomaly alebo pod tlakom explodovali.\"\n  STR_THERMIC_LANCE_UFOPEDIA: \"Termický vrták je logickou evolúciou technológie vibro čepele. Vrták sa točí vysokou rýchlosťou a zdroj energie, využívajúci zrbit, zahrieva vrták tak, že sa prereže pancierom ako teplý nôž maslom.\"\n  STR_HEAVY_THERMIC_LANCE_UFOPEDIA: \"Ťažký termický vrták je účinnejšou verziou termického vrtáka. Dvojitý zdroj tepla a extrémne vysoká rýchlosť rotácie znamená, že sa vŕtačka prereže akýmkoľvek známym materiálom.\"\n  STR_SONIC_CANNON_UFOPEDIA: \"Sonický kanón je najsilnejší z rodiny sonických zbraní. Charakteristickým prvkom je zvýšený rozsah audio oscilátoru a väčšia rezonančná komora než má sonická puška. Je taktiež vybavený impulzným detonačným systémom, ktorý pomocou modulácie ultrazvukových vĺn zvyšuje efektivitu soncikého úderu. \"\n  STR_CANNON_POWER_CLIP_UFOPEDIA: \"Toto kompaktné zariadenie slúži ako munícia pre sonický kanón. Obsahuje malé množstvo zrbitu.\"\n  STR_SONIC_BLASTA_RIFLE_UFOPEDIA: \"Výkonnejšie sonické zariadenie. Dokonca ani vysoko legovaná oceľ nie je imúnna voči tejto zbrani. Kompaktný vlnový emitor je rozšírený o supravodivý zosilňovač, ktorý zvyšuje výkon tejto zbrane.\"\n  STR_BLASTA_POWER_CLIP_UFOPEDIA: \"Tento malý objekt je používaný ako zdroj energie pre sonickú pušku - stredne silnú mimozemskú zbraň. Obsahuje malé množstvo zrbitu.\"\n  STR_SONIC_PISTOL_UFOPEDIA: \"Sonické pištole sú mimozemskou zbraňou využívajúcou ultrazvuk, ktoré dokážu behom sekundy premeniť kosti na želatínu. Ultrazvukové vlny sú v rozsahu nad rámcom ľudského sluchu.\"\n  STR_PISTOL_POWER_CLIP_UFOPEDIA: \"Zdroj energie pre malú mimozemskú sonickú pištoľ. Obsahuje malé množstvo zrbitu - zdroja mimozemskej energie.\"\n  STR_DISRUPTOR_PULSE_LAUNCHER_UFOPEDIA: \"Toto je mimozemský odpaľovač navádzaných rakiet, ktorý vystreľuje autonómne poháňané torpéda tzv. 'disruptorové projektily'. Pred ich vystrelením je potrebné zadať cieľové body, ktoré určia trajektóriu strely a následne potvrdiť ikonou výstrelu. Zbraň je použiteľná len pod vodnou hladinou.\"\n  STR_DISRUPTOR_AMMO_UFOPEDIA: \"Toto zariadenie je osadené tzv. disruptorovým projektilom, vybavený inteligentným navádzacím systémom. Je odpaľované pomocou disruptora. \"\n  STR_THERMAL_SHOK_LAUNCHER_UFOPEDIA: \"Termálny odpaľovač slúži na vystreľovanie chemických omračujúcich bômb. Veľmi užitočný pri chytaní živých mimozemšťanov.\"\n  STR_THERMAL_SHOK_BOMB_UFOPEDIA: \"Termálna šoková bomba sa používa pri chytaní živých ľudských vzoriek, avšak rovnako môže byť použitá proti väčšine mimozemských druhov. Vystreľuje sa pomocou tzv. termálneho odpaľovača.\"\n  STR_SONIC_PULSER_UFOPEDIA: \"Toto zariadenie funguje rovnako ako naše štandardné granáty - akurát je niekoľko násobne účinnejšie. Granát generuje sonický impulz smerovaný do všetkých strán naraz. \"\n  STR_MC_READER_UFOPEDIA: \"V telách mimozemšťanov sme našli malé, chirurgicky implantované jednotky. Tieto kontrolné implantáty, vytvorené akvatoidmi, umožňujú stály prísun informácií z bojiska i na veľké vzdialenosti. Čítačka molekulárnej kontroly je mimozemské komunikačné zariadenie, ktoré si berie informácie priamo z M.K. implantátov. Agenti X-Com môžu tento systém využívať v boji na zobrazovanie charakteristík protivníka. Vyberte funkciu 'použiť' a potom kliknite s kurzorom na mimozemšťana.\"\n  STR_SURVEY_SHIP: \"Prieskumná loď\"\n  STR_ESCORT: \"Eskorta\"\n  STR_CRUISER: \"Krížnik\"\n  STR_HEAVY_CRUISER: \"Ťažký krížnik\"\n  STR_HUNTER: \"Lovec\"\n  STR_BATTLESHIP: \"Bojová loď\"\n  STR_DREADNOUGHT: \"Ťažká bojová loď\"\n  STR_FLEET_SUPPLY_CRUISER: \"Zásobovací krížnik\"\n  MAP_SEABED: \"Morské dno\"\n  MAP_PIPES: \"Výskumná stanica\"\n  MAP_PLANE: \"Havarované lietadlo\"\n  MAP_ATLAN: \"Atlantída\"\n  MAP_MU: \"Mayský chrám\"\n  MAP_GAL: \"Potopená galeóna\"\n  MAP_MSUNK: \"Potopený parník\"\n  MAP_VOLC: \"Vulkanická\"\n  MAP_CORAL: \"Koralová\"\n  MAP_PORT: \"Prístav\"\n  MAP_ISLAND: \"Ostrov\"\n  MAP_CARGO: \"Nákladná loď\"\n  MAP_LINERT: \"Výletná loď Č1\"\n  MAP_LINERB: \"Výletná loď Č2\"\n  MAP_ALART: \"Artefakt Č1\"\n  MAP_GRUNGE: \"Artefakt Č2\"\n  MAP_ENTRY: \"Kolónia Č1\"\n  MAP_A_BASE: \"Kolónia Č2\"\n  MAP_ALSHIP: \"T'leth Č1\"\n  MAP_LEVEL: \"T'leth Č2\"\n  MAP_CRYPT: \"T'leth Č3\"\n  MAP_XBASES: \"Základňa X-Com\"\n  STR_MIXED_CREW: \"Zmiešaná posádka\"\n  STR_MIXED_CREW_2: \"Zmiešaná posádka 2\"\n  STR_RATING: \"HODNOTENIE> {0}\"\n  STR_RATING_TERRIBLE: \"PRÍŠERNÉ!\"\n  STR_RATING_POOR: \"SLABÉ!\"\n  STR_RATING_OK: \"OK\"\n  STR_RATING_GOOD: \"DOBRÉ!\"\n  STR_RATING_EXCELLENT: \"VÝBORNÉ!\"\n  STR_SCORE: \"BODY\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"MESAČNÁ SPRÁVA PROJEKTU X-COM\"\n  STR_MONTH: \"Mesiac> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"Výbor organizácií financiujúcich projekt je zatiaľ spokojný s vašim napredovaním.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"Výbor organizácií financiujúcich projekt je veľmi spokojný s vašimi výbornými výsledkami. Pokračujte v dobre odvádzanej práci.\"\n  STR_COUNCIL_IS_DISSATISFIED: \"Výbor zaisťujúci financovanie projektu je nespokojný s vaším napredovaním. Musíte zvýšiť efektivitu akcií podnikaných proti mimozemskej hrozbe, inak riskujete okamžité ukončenie celého projektu.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"V boji s mimozemšťanmi si zlyhal. Výbor sa preto rozhodol ukončiť projekt X-Com. Každá organizácia sa teraz bude musieť vysporiadať so situáciou vlastnými prostriedkami. Môžeme len dúfať, že s týmito prastarými silami nájdeme spôsob akým spor urovnať, a že obyvateľstvo pristúpi na podmienky podmorských návštevníkov.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} je obzvlášť spokojné so schopnosťou vašej organizácie vysporiadať sa s mimozemskou hrozbou a súhlasili s navýšením financovania.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} sú čiastočne spokojné s vašim pokrokom s vysporiadaním sa s miestnymi vpádmi a rozhodli sa navýšiť svoje finančné príspevky.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} a {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} nie je spokojná s Vašou schopnosťou vysporiadať sa s mimozemskou aktivitou v jej vodách a preto sa rozhodli, že znížia svoje financovanie.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} nie sú spokojní s Vašou schopnosťou vysporiadať sa s mimozemskou aktivitou v jej vodách a preto sa rozhodli, že znížia svoje financovanie.\"\n  STR_KNOTS: \"{0} uzlov\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} podpísal kooperačnú dohodu s mimozemskými silami a odstúpil od projektu X-Com.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} podpísali kooperačnú dohodu s mimozemskými silami a odstúpili od projektu X-Com.\"\n  STR_MONTHLY_RATING: \"Mesačné hodnotenie> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Zmena financovania> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"Výbor zaisťujúci financovanie projektu nie je spokojný s vašou finančnou situáciou. Musíte redukovať dlhy pod $1 milión inak bude projekt ukončený.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"DEKÓDOVANÉ SUB-ČASTICOVÉ VYSIELANIE\"\n  STR_CRAFT_TYPE: \"TYP PONORKY\"\n  STR_RACE: \"DRUH\"\n  STR_MISSION: \"MISIA\"\n  STR_ZONE: \"ZÓNA\"\n  STR_ALLOCATE_RESEARCH: \"Rozvrhnúť výskum\"\n  STR_ALLOCATE_MANUFACTURE: \"Naplánovať výrobu\"\n  STR_AZORES: \"Azory\"\n  STR_REYKJAVIK: \"Reykjavik\"\n  STR_BERMUDA: \"Bermuda\"\n  STR_NEW_YORK: \"New York\"\n  STR_BOSTON: \"Boston\"\n  STR_FORT_SEVERN: \"Fort Severn\"\n  STR_DAKAR: \"Dakar\"\n  STR_RECIFE: \"Recife\"\n  STR_ACCRA: \"Accra\"\n  STR_ASCENSION_ISLAND: \"Ostrov Ascension\"\n  STR_TRINIDADE_ISLAND: \"Ostrov Trinidad\"\n  STR_FALKLAND_ISLAND: \"Falklandské ostrovy\"\n  STR_CANARY_ISLANDS: \"Kanárske ostrovy\"\n  STR_ANCHORAGE: \"Anchorage\"\n  STR_ST_LAWRENCE_ISLAND: \"Ostrov Sv. Vavrinca\"\n  STR_SAN_FRANCISCO: \"San Francisco\"\n  STR_MIDWAY_ISLAND: \"Ostrov Midway\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_TASMANIA: \"Tazmánia\"\n  STR_HAWAII: \"Hawaii\"\n  STR_FIJI: \"Fidži\"\n  STR_TONGA: \"Tonga\"\n  STR_EASTER_ISLAND: \"Veľkonočný ostrov\"\n  STR_GALAPAGOS_ISLAND: \"Galapágy\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_SOLOMON_ISLAND: \"Šalamúnové ostrovy\"\n  STR_CRETE: \"Kréta\"\n  STR_LISBON: \"Lisabon\"\n  STR_PORT_SAID: \"Port Said\"\n  STR_MARSEILLES: \"Marseilles\"\n  STR_TRIPOLI: \"Tripoli\"\n  STR_MANILA: \"Manila\"\n  STR_HONG_KONG: \"Hong Kong\"\n  STR_SINGAPORE: \"Singapúr\"\n  STR_BANGKOK: \"Bangkok\"\n  STR_DARWIN: \"Darwin\"\n  STR_BOMBAY: \"Bombay\"\n  STR_SAYCHELLES_ISLAND: \"Seychely\"\n  STR_MALDIVE_ISLAND: \"Maledivy\"\n  STR_SRI_LANKA: \"Sri Lanka\"\n  STR_MAURITIUS: \"Maurícius\"\n  STR_TOKYO: \"Tokio\"\n  STR_SHANGHAI: \"Šanghaj\"\n  STR_VLADIVOSTOK: \"Vladivostok\"\n  STR_LONDON: \"Londýn\"\n  STR_FAEROE_ISLAND: \"Faerské ostrovy\"\n  STR_ABERDEEN: \"Aberdeen\"\n  STR_OSLO: \"Oslo\"\n  STR_JAMAICA: \"Jamajka\"\n  STR_PANAMA: \"Panama\"\n  STR_MIAMI: \"Miami\"\n  STR_PSI_TRAINING: \"Tréning M.K.\"\n  STR_PSIONIC_TRAINING: \"TRÉNING MOLEKULÁRNEJ KONTROLY\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Ostávajúca kapacita M.K.> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"M.K.{NEWLINE}odolnosť\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"M.K. schopnosť{NEWLINE}/zlepšenie\"\n  STR_IN_TRAINING: \"Vo{NEWLINE}výcviku?\"\n  STR_TARGETTED_BY: \"ZACIEĽENÝ:\"\n  STR_WEAPONS_CREW_HWPS: \"ZBRANE/{NEWLINE}POSÁDKA/ŤZS\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"má málo paliva,{NEWLINE}sa vracia na základňu\"\n  STR_SOLDIER_LIST: \"Zoznam akvanautov\"\n  STR_RANK_: \"HODNOSŤ> {ALT}{0}\"\n  STR_MISSIONS: \"MISIE> {ALT}{0}\"\n  STR_KILLS: \"ZABITIA> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"ZOTAVENIE> {ALT}{0}\"\n  STR_TIME_UNITS: \"AKČNÉ BODY\"\n  STR_STAMINA: \"VÝDRŽ\"\n  STR_HEALTH: \"ZDRAVIE\"\n  STR_BRAVERY: \"UDATNOSŤ\"\n  STR_REACTIONS: \"REAKCIE\"\n  STR_FIRING_ACCURACY: \"PRESNOSŤ STREĽBY\"\n  STR_THROWING_ACCURACY: \"PRESNOSŤ VRHU\"\n  STR_STRENGTH: \"SILA\"\n  STR_PSIONIC_STRENGTH: \"M.K. ODOLNOSŤ\"\n  STR_PSIONIC_SKILL: \"M.K. SCHOPNOSŤ\"\n  STR_NEW_RANK: \"NOVÁ HODNOSŤ\"\n  STR_PROMOTIONS: \"Povýšenia\"\n  STR_SOLDIERS_UC: \"AKVANAUTI\"\n  STR_COELACANTH_GAS_CANNON_UFOPEDIA: \"Automatické PZS sú dobre manévrovateľné a majú odolný pancier. Sú výbornou podporu pre jednotky v hĺbkach. PZS sú vyzbrojované automaticky pokiaľ máte dostatok munície.\"\n  STR_COELACANTH_AQUA_JET_UFOPEDIA: \"Tento obojživelník je vyzbrojený akva-prúdovými torpédami. Tento zbraňový systém funguje len pod vodou. Zabezpečte, aby ste mali vždy na sklade dostatok príslušných torpéd.\"\n  STR_COELACANTH_GAUSS_UFOPEDIA: \"Gaussova technológia poskytuje pre naše PZS účinný zbraňový systém. Poskytuje naším PZS ťažkú palebnú silu, v rámci vlastnej X-Com technológie.\"\n  STR_DISPLACER_SONIC_UFOPEDIA: \"Mimozemská technológia redefinovala využitie a možnosti PZS. Iónový pohon neobmedzuje PZS len na pohyb po súši/morskom dne. Sonická výzbroj predstavuje výhodu v boji. \"\n  STR_DISPLACER_PWT_UFOPEDIA: \"Pulzné torpéda sú použiteľné len pod vodou. Musíte mať dostatok pulzných torpéd, aby bolo zariadenie stále plne nabité. Pred vystrelením zadajte cieľové body a potvrďte ikonou výstrelu.\"\n  STR_ALIEN_PROBE_MISSION: \"Prieskumná misia\"\n  STR_ALIEN_INTERDICTION: \"Mimozemská blokáda\"\n  STR_ALIEN_RESOURCE_RAID: \"Rabovanie surovín\"\n  STR_ALIEN_INFILTRATION: \"Mimozemská infiltrácia\"\n  STR_ALIEN_BASE: \"Rozširovanie kolónie\"\n  STR_ALIEN_SURFACE_ATTACK: \"Útok na povrchu\"\n  STR_ALIEN_RETALIATION: \"Útok na základňu\"\n  STR_ALIEN_SUPPLY: \"Zásobovanie kolónie\"\n  STR_ALIEN_PROBE_MISSION_UFOPEDIA: \"Mimozemské výskumné misie slúžia na získavanie údajov z určitej oblasti o morskom dne, prírodných zdrojoch, lodných a leteckých koridoroch. Mimozemské ponorky plniace tieto úlohy pre nás nepredstavujú hrozbu, sú však indikátorom budúcej mimozemskej aktivity.\"\n  STR_ALIEN_INTERDICTION_UFOPEDIA: \"Mimozemšťania majú vlastné postupy pri spravovaní oblastí, o ktoré majú záujem. Najprv vyšlú špeciálne plavidlo, ktorej úlohou je zabezpečiť oblasť skôr, než v nej začnú s intenzívnou činnosťou. Pristávajú na vytipovaných miestach, ktoré plánujú prepadnúť, aby zaistili oblasť a pripravili sa na ďalší stupeň aktivity.\"\n  STR_ALIEN_RESOURCE_RAID_UFOPEDIA: \"Kľúčovým prvkom stratégie mimozemšťanov je potápanie lodí a zostreľovanie lietadiel. Z nich potom získavajú materiály, ktoré sú pre ne kľúčové. Mimozemšťania tiež prepadávajú geotermálne miesta, ťažobné lokácie a prastaré miesta, kde hľadajú minerály, spracované kovy a ďalšie ľudské produkty.  \"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"Pozemská vláda môže byť infiltrovaná mimozemskými agentmi, ktorí vyzerajú ako ľudia. Toto môže mať za dôsledok oficiálny kontakt medzi mimozemšťanmi a korporáciami alebo vládou na najvyššej úrovni. Vyvrcholenie tejto aktivity má za následok zvýšenie mimozemskej aktivity vo vodách dotknutých organizácii. Mimozemšťania sa budú pokúšať podpísať dohodu s vládami alebo organizáciami ponúknutím poznatkov ich vysoko vyvinutej technológie. Tento typ mimozemskej aktivity predstavuje najväčšiu hrozbou pre X-Com. Ak vláda alebo korporácia pristúpi na dohodu, potom ukončí financovanie projektu X-Com.\"\n  STR_ALIEN_BASE_UFOPEDIA: \"Mimozemšťania budujú tajné podzemné kolónie v odľahlých lokalitách Zeme. Výstavba základne sa začína prieskumnými loďami, ktoré sú nasledované častejšou  aktivitou v momente keď mimozemšťania začnú s výstavbou. V týchto kolóniách sa nachádzajú laboratória, klonovacie centrá, chirurgické zariadenia slúžiace na ľudské experimenty. Prítomnosť kolónie generuje veľké množstvo hlásených aktivít mimozemšťanov bez prítomnosti ich ponoriek. Aby bol X-Com schopný detekovať kolóniu musí hliadkovacia ponorka niekoľko hodín skúmať príslušnú oblasť.\"\n  STR_ALIEN_SURFACE_ATTACK_UFOPEDIA: \"Keď mimozemšťania potrebujú ľudí, terorizujú prístav, zaútočia na ostrov alebo prepadnú loď. V takýchto prípadoch je priamo ohrozené civilné obyvateľstvo, ktoré bude slúžiť pre perverzné rozmnožovacie potreby mimozemšťanov a ich strašných experimentov.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"Ak sa stíhacím ponorkám X-Com darí úspešne potápať mimozemské ponorky, potom môžu mimozemšťania pristúpiť k odvetným akciám. To môže mať za následok priamy útok na základňu X-Com. Odhaleniu základne sa dá predísť promptnou reakciou na výskyt mimozemských ponoriek v okolí základne. V takom prípade je riziko útoku minimálne.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"Po tom ako mimozemšťania postavia na Zemi kolóniu je táto zásobovaná v pravidelných intervaloch pomocou špeciálnych zásobovacích lodí. Ak je jedna z takýchto lodí detekovaná pri pristávaní, je viac než isté, že sa v okolí nachádza kolónia mimozemšťanov.\"\n  STR_SURVEY_SHIP_UFOPEDIA: \"Táto malá ponorka je primárne určená na prieskumné misie. Táto loď je predvojom väčších lodí a pripravuje pôdu pre začiatok mimozemský útoky.\"\n  STR_ESCORT_UFOPEDIA: \"Stredne veľké eskortné plavidlo, ktoré nepredstavuje veľkú hrozbu pre pozemské sily. Obvykle predstavuje predvoj väčších mimozemských plavidiel a zvýšenie mimozemských aktivít v oblasti.\"\n  STR_CRUISER_UFOPEDIA: \"Krížnik je pilierom mimozemskej flotily, univerzálnym plavidlom využívaným na všetky druhy mimozemských misií. \"\n  STR_HEAVY_CRUISER_UFOPEDIA: \"Ťažký krížnik je silnejšou variantov krížnika. Jeho silu navyšujú väčšie zbraňové a pohonné systémy. Ťažký krížnik sa využíva na zhromažďovanie zdrojov, ťaženie a zbieranie veľkých kvánt minerálov a vybavenia.\"\n  STR_HUNTER_UFOPEDIA: \"Táto loď je vybavená vyšetrovacou miestnosťou, v ktorej sa vykonávajú chirurgické zákroky a experimenty na ľudských subjektoch. Obete sú podrobené najodpornejším mukám. Mozog je často odstránený a uložený a spracovaný počas cesty.\"\n  STR_BATTLESHIP_UFOPEDIA: \"Bojová loď je najagresívnejšou mimozemskou loďou. Je vybavená všetkou technológiou a systémami, ktoré mimozemšťania majú k dispozícii a slúži ako základňa pre mimozemské operácie. Je vyzbrojená širokou škálou zbraňových systémov.\"\n  STR_DREADNOUGHT_UFOPEDIA: \"Táto ťažká bojová loď alebo dreadnought je super transportérom, plne vybavený všetkými mimozemskými technológiami a plne vyzbrojený. Dreadnought je pre naše bojové ponorky veľmi húževnatým a impozantným protivníkom.\"\n  STR_FLEET_SUPPLY_CRUISER_UFOPEDIA: \"Zásobovacia loď je používaná počas budovania kolónií mimozemšťanov alebo ako prostriedok zásobovania existujúcich kolónií. Prepravuje potravu, DNA, zárodky a ďaľšie biologické komponenty.\"\n  STR_DISMANTLE: \"Rozobrať\"\n  STR_FACILITY_IN_USE: \"ZARIADENIE SA POUŽÍVA\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"ZARIADENIE NIE JE MOŽNÉ ROZOBRAŤ! {SMALLLINE}Všetky zariadenia v základni musia byť spojené s vzduchovým uzáverom.\"\n  STR_TRANSFER_ITEMS_TO: \"Presuň predmety do {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"CHÝBA ZADRŽIAVACIA CELA PRE MIMOZEMŠŤANOV!{SMALLLINE}Aby živí mimozemšťania prežili musia byť umiestnení v špeciálnej cele.\"\n  STR_AMOUNT_AT_DESTINATION: \"MNOŽSTVO{NEWLINE}V CIELI\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"Mimozemšťan zahynul, pretože nemáme zadržiavaciu celu pre mimozemšťanov\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"K DISPOZÍCII NIE SÚ DOSTATOČNÉ UBYTOVACIE KAPACITY!{SMALLLINE}Cieľová základňa nemá dostatok miesta v ubytovniach pre tím priradený k transportnému plavidlu.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"NEDOSTATOK MIESTA V SKLADOCH!{SMALLLINE}Cieľová základňa nemá dostatok skladových priestorov pre vybavenie, ktoré bolo pridelené tomuto plavidlu.\"\n  STR_ITEMS_ARRIVING: \"Dodané položky\"\n  STR_DESTINATION_UC: \"MIESTO URČENIA\"\n  STR_DART_PISTOL: \"Šípovka\"\n  STR_DART_POD: \"Zásobník šípov\"\n  STR_JET_HARPOON: \"Prúdová harpúna\"\n  STR_HARPOON_POD: \"Zásobník harpúny\"\n  STR_GAS_CANNON: \"Plynový kanón\"\n  STR_GC_AP_AMMO: \"PK-PR šípy\"\n  STR_GC_HE_AMMO: \"PK-EX šípy\"\n  STR_GC_P_AMMO: \"PK-FOS šípy\"\n  STR_HYDRO_JET_CANNON: \"Hydro-prúdový kanón\"\n  STR_HJC_AP_AMMO: \"HP-PR munícia\"\n  STR_HJC_HE_AMMO: \"HP-EX munícia\"\n  STR_HJC_P_AMMO: \"HP-FOS munícia\"\n  STR_TORPEDO_LAUNCHER: \"Torpédomet\"\n  STR_SMALL_TORPEDO: \"Malé torpédo\"\n  STR_LARGE_TORPEDO: \"Veľké torpédo\"\n  STR_PHOSPHOROUS_TORPEDO: \"Fosforové torpédo\"\n  STR_MAGNA_BLAST_GRENADE: \"Granát\"\n  STR_DYE_GRENADE: \"Dymovnica\"\n  STR_PARTICLE_DISTURBANCE_GRENADE: \"Časticový granát\"\n  STR_MAGNA_PACK_EXPLOSIVE: \"Demolačná výbušnina\"\n  STR_PARTICLE_DISTURBANCE_SENSOR: \"Senzor časticových porúch\"\n  STR_MEDI_KIT: \"Lekárnička\"\n  STR_MC_DISRUPTOR: \"Rušička M.K.\"\n  STR_THERMAL_TAZER: \"Tepelný omračovač\"\n  STR_GAUSS_PISTOL: \"Gaussova pištoľ\"\n  STR_GAUSS_PISTOL_CLIP: \"Zásobník gaussovej pištole\"\n  STR_GAUSS_RIFLE: \"Gaussova puška\"\n  STR_GAUSS_RIFLE_CLIP: \"Zásobník gaussovej pušky\"\n  STR_HEAVY_GAUSS: \"Ťažký gaussov kanón\"\n  STR_HEAVY_GAUSS_CLIP: \"Zásobník gaussovho kanóna\"\n  STR_SONIC_CANNON: \"Sonický kanón\"\n  STR_CANNON_POWER_CLIP: \"Zásobník sonického kanónu\"\n  STR_SONIC_BLASTA_RIFLE: \"Sonická puška\"\n  STR_BLASTA_POWER_CLIP: \"Zásobník sonickej pušky\"\n  STR_SONIC_PISTOL: \"Sonická pištoľ\"\n  STR_PISTOL_POWER_CLIP: \"Zásobník sonickej pištole\"\n  STR_DISRUPTOR_PULSE_LAUNCHER: \"Disruptor\"\n  STR_DISRUPTOR_AMMO: \"Munícia pre disruptor\"\n  STR_THERMAL_SHOK_LAUNCHER: \"Termálny odpaľovač\"\n  STR_THERMAL_SHOK_BOMB: \"Termálna bomba\"\n  STR_SONIC_PULSER: \"Sonický pulzér\"\n  STR_ZRBITE: \"Zrbit\"\n  STR_MC_READER: \"Čítačka M.K.\"\n  STR_VIBRO_BLADE: \"Vibro čepeľ\"\n  STR_THERMIC_LANCE: \"Termický vrták\"\n  STR_HEAVY_THERMIC_LANCE: \"Tažký termický vrták\"\n  STR_AQUATOID_CORPSE: \"Mŕtvola akvatoida\"\n  STR_GILLMAN_CORPSE: \"Mŕtvola gillmana\"\n  STR_LOBSTERMAN_CORPSE: \"Mŕtvola lobstermana\"\n  STR_TASOTH_CORPSE: \"Mŕtvola tasotha\"\n  STR_CALCINITE_CORPSE: \"Mŕtvola kalcinita\"\n  STR_DEEP_ONE_CORPSE: \"Mŕtvola hĺbkomora\"\n  STR_BIODRONE_CORPSE: \"Mŕtvola bio-drona\"\n  STR_TENTACULAT_CORPSE: \"Mŕtvola chápadlovca\"\n  STR_TRISCENE_CORPSE: \"Mŕtvola triscena\"\n  STR_HALLUCINOID_CORPSE: \"Mŕtvola halucinoida\"\n  STR_XARQUID_CORPSE: \"Mŕtvola xarkida\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"Nedostatok munície pre PZS{SMALLLINE}Každý PZS vyžaduje {0} {1}.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Nedostatok vybavenia pre plné prezbrojenie jednotky\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Najprv musíte vynájsť{NEWLINE}{0}{NEWLINE}aby ste moholi vyrobiť{NEWLINE}{1}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"Mimozemšťania zničili nechránenú základňu {0}\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"Hliadka X-Com objavila umiestnenie mimozemskej kolónie v {0}\"\n  STR_STANDOFF: \"ODSTUP\"\n  STR_CAUTIOUS_ATTACK: \"OPATRNÝ ÚTOK\"\n  STR_STANDARD_ATTACK: \"ŠTANDARDNÝ ÚTOK\"\n  STR_AGGRESSIVE_ATTACK: \"AGRESÍVNY ÚTOK\"\n  STR_DISENGAGING: \"RUŠÍM PRENASLEDOVANIE\"\n  STR_UFO_HIT: \"PONORKA ZASIAHNUTÁ!\"\n  STR_UFO_CRASH_LANDS: \"MIMOZEMSKÁ PONORKA POTOPENÁ!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Minimalizovať len pri odstupe\"\n  STR_UFO_RETURN_FIRE: \"PONORKA MIMOZEMŠŤANOV OPÄTUJE PAĽBU!\"\n  STR_INTERCEPTOR_DAMAGED: \">>> PONORKA POŠKODENÁ <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> PONORKA BOLA ZNIČENÁ <<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"MIMOZEMSKÁ PONORKA UNIKÁ!\"\n  STR_LONG_RANGE_DETECTION: \"Širokopásmová detekcia\"\n  STR_STORES_UC: \"SKLADY\"\n  STR_DIFFICULTY_LEVEL: \"Stupeň obtiažnosti\"\n  STR_INTERCEPT: \"STÍHANIE\"\n  STR_BASES: \"ZÁKLADNE\"\n  STR_GRAPHS: \"GRAFY\"\n  STR_UFOPAEDIA_UC: \"UFOPÉDIA\"\n  STR_OPTIONS_UC: \"NASTAVENIA\"\n  STR_FUNDING_UC: \"FINANCOVANIE\"\n  STR_5_SECONDS: \"5 sek\"\n  STR_1_MINUTE: \"1 min\"\n  STR_5_MINUTES: \"5 min\"\n  STR_30_MINUTES: \"30 min\"\n  STR_1_HOUR: \"1 hod\"\n  STR_1_DAY: \"1 deň\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"Rozpis výkonu X-Com\"\n  STR_ENTER_NAME: \"Vložte meno\"\n  STR_PERFORMANCE_RATING: \"Hodnotenie výkonu\"\n  STR_VICTORY_DATE: \"Dátum víťazstva\"\n  STR_CHEMICAL_FLARE: \"Chemická svetlica\"\n  STR_CHEMICAL_FLARE_UFOPEDIA: \"Po odhodení, toto kompaktné zariadenie produkuje silné, jasné svetlo, ktoré dokáže vo veľkých hĺbkach alebo počas nočných misií odhaliť nepriateľské jednotky v okolí svetlice. \"\n  STR_MONTHLY_COSTS: \"Mesačné náklady\"\n  STR_CRAFT_RENTAL: \"Prenájom doku\"\n  STR_SALARIES: \"Výplaty\"\n  STR_BASE_MAINTENANCE: \"Údržba základne\"\n  STR_COST_PER_UNIT: \"Jedn. cena\"\n  STR_QUANTITY: \"Množstvo\"\n  STR_TOTAL: \"Celkovo\"\n  STR_IN_PSIONIC_TRAINING: \"Prebieha M.K. implantácia\"\n  STR_FRONT_ARMOR: \"Predná zbroj\"\n  STR_LEFT_ARMOR: \"Ľavá zbroj\"\n  STR_RIGHT_ARMOR: \"Pravá zbroj\"\n  STR_REAR_ARMOR: \"Zadná zbroj\"\n  STR_UNDER_ARMOR: \"Spodná zbroj\"\n  STR_ROUNDS: \"NÁBOJE\"\n  STR_UNIT: \"JEDNOTKA> {0}\"\n  STR_ENERGY: \"ENERGIA\"\n  STR_MORALE: \"MORÁLKA\"\n  STR_ARMOR_: \"ZBROJ> {0}\"\n  STR_FRONT_ARMOR_UC: \"PREDNÁ ZBROJ\"\n  STR_LEFT_ARMOR_UC: \"ĽAVÁ ZBROJ\"\n  STR_RIGHT_ARMOR_UC: \"PRAVÁ ZBROJ\"\n  STR_REAR_ARMOR_UC: \"ZADNÁ ZBROJ\"\n  STR_SKILLS: \"SCHOPNOSTI> {0}\"\n  STR_LEVEL: \"ÚROVEŇ> {0}\"\n  STR_HEAD: \"HLAVA\"\n  STR_TORSO: \"TELO\"\n  STR_RIGHT_ARM: \"PRAVÁ PAŽA\"\n  STR_LEFT_ARM: \"ĽAVÉ RAMENO\"\n  STR_RIGHT_LEG: \"PRAVÁ NOHA\"\n  STR_LEFT_LEG: \"ĽAVÁ NOHA\"\n  STR_PAIN_KILLER: \"SEDATÍVA\"\n  STR_STIMULANT: \"STIMULANT\"\n  STR_HEAL: \"LIEČENIE\"\n  STR_TIME_UNITS_SHORT: \"AB>{ALT}{0}\"\n  STR_WEIGHT: \"Váha>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"REA>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"P.Schopnosť>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"P.Odol>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Mimozemský artefakt\"\n  STR_AMMO_ROUNDS_LEFT: \"NÁBOJE:{NEWLINE}OSTÁVA{NEWLINE}VÝSTRELOV={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Sedatíva>{ALT}{0}{ALT}{NEWLINE}Stimulant>{ALT}{1}{ALT}{NEWLINE}Liečenie>{ALT}{2}\"\n  STR_THROW: \"Hodiť\"\n  STR_AUTO_SHOT: \"Auto-streľba\"\n  STR_SNAP_SHOT: \"Bez mierenia\"\n  STR_AIMED_SHOT: \"Mierená strela\"\n  STR_STUN: \"Omráčiť\"\n  STR_PRIME_GRENADE: \"Odistiť granát\"\n  STR_USE_SCANNER: \"Použi senzor\"\n  STR_USE_MEDI_KIT: \"Použi lekárničku\"\n  STR_LAUNCH_MISSILE: \"Vypustiť torpédo\"\n  STR_ACCURACY_SHORT: \"PRE>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Nedostatok akčných bodov!\"\n  STR_NOT_ENOUGH_ENERGY: \"Nedostatok energie!\"\n  STR_NO_ROUNDS_LEFT: \"Chýba munícia!\"\n  STR_NO_AMMUNITION_LOADED: \"Nie je nabitá!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Munícia nevhodná pre túto zbraň!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"Zbraň je už nabitá!\"\n  STR_NO_LINE_OF_FIRE: \"Prekážka v dráhe strely!\"\n  STR_GRENADE_IS_ACTIVATED: \"Granát je odistený!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Granát zaistený!\"\n  STR_THERE_IS_NO_ONE_THERE: \"Nikto tam nie je!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Nie je možné používať mimozemský artefakt keď nie je preskúmaný našimi vedcami!\"\n  STR_OUT_OF_RANGE: \"Mimo dosah!\"\n  STR_UNABLE_TO_THROW_HERE: \"Nedá sa odhodiť!\"\n  STR_SET_TIMER: \"Nastav časovač\"\n  STR_HIDDEN_MOVEMENT: \"SKRYTÝ POHYB\"\n  STR_TURN: \"ŤAH> {0}\"\n  STR_SIDE: \"STRANA> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Stlač tlačidlo na pokračovanie\"\n  STR_MIND_CONTROL: \"Molekulárna kontrola\"\n  STR_PANIC_UNIT: \"Skratovať implantát\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Úspešný útok na morálku\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Skratovanie implantátu bolo úspešné\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}podľahol amoku\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}podlahla amoku\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE} spanikáril\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}spanikárila\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Mimozemšťania\"\n  STR_RIGHT_HAND: \"PRAVÁ RUKA\"\n  STR_LEFT_HAND: \"ĽAVÁ RUKA\"\n  STR_RIGHT_SHOULDER: \"PRAVÉ RAMENO\"\n  STR_LEFT_SHOULDER: \"ĽAVÉ RAMENO\"\n  STR_BACK_PACK: \"RUKSAK\"\n  STR_BELT: \"OPASOK\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}je ovládaný mimozemšťanmi\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}je ovládaná mimozemšťanmi\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}stratil vedomie\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}stratila vedomie\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}zomrel na smrteľné zranenia\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}zomrela na smrtelné zranenie\"\n  STR_USE_MIND_PROBE: \"Použi M.K. čítačku\"\n  STR_FATAL_WOUNDS: \"SMRTEĽNÉ ZRANENIA\"\n  STR_UNDER_ARMOR_UC: \"SPODNÁ ZBROJ\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Akčné body rezervované pre rýchly výstrel\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Akčné body rezervované pre auto-streľbu\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Akčné body rezervované pre mierenú strelu\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Akčné body rezervované pre pokľaknutie\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"AB rezervované pre pokľaknutie a streľbu\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} jednotka v X-Com transportéri\"\n    few: \"{N} jednotky v X-Com transportéri\"\n    many: \"{N} jednotiek v X-Com transportéri\"\n    other: \"{N} jednotiek v X-Com transportéri\"\n  STR_UNITS_OUTSIDE:\n    one: \"{N} jednotka ostala vonku\"\n    few: \"{N} jednotky ostali vonku\"\n    many: \"{N} jednotiek ostalo vonku\"\n    other: \"{N} jednotiek ostalo vonku\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} jednotka pri vstupe\"\n    few: \"{N} jednotky pri vstupe\"\n    many: \"{N} jednotiek pri vstupe\"\n    other: \"{N} jednotiek pri vstupe\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} jednotka v cieľovej oblasti\"\n    few: \"{N} jednotky v cieľovej oblasti\"\n    many: \"{N} jednotiek v cieľovej oblasti\"\n    other: \"{N} jednotiek v cieľovej oblasti\"\n  STR_ABORT_MISSION_QUESTION: \"Ukončiť misiu?\"\n  STR_CORPSE: \"Mŕtvola\"\n  STR_UNLOAD_CRAFT: \"Vyložiť\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}bol zabitý\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}bola zabitá.\"\n  STR_HIT_MELEE: \"Zásah\"\n  STR_GROUND: \"ZEM\"\n  STR_LIVING_QUARTERS_PLURAL: \"Ubytovne\"\n  STR_LIST_ITEM: \"POLOŽKA\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"Všetci mimozemšťania zahynuli pri havárii,{NEWLINE}Zahajujem automatické prehliadnutie miesta havárie.\"\n  STR_RESET: \"Reset\"\n  STR_MEMORIAL: \"Pamätník\"\n  STR_DATE_UC: \"DÁTUM\"\n  STR_SOLDIERS_RECRUITED_UC: \"NAVERBOVANÝCH AKVANAUTOV>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"VOJENSKÉ STRATY>{ALT}{0}\"\n  STR_REMOVE_SELECTED: \"Odstráň označené\"\n  STR_LIVE_ALIENS: \"Živí{NEWLINE}jedinci\"\n  STR_DEAD_ALIENS: \"Nepotrební{NEWLINE}jedinci\"\n  STR_UNDER_INTERROGATION: \"Vo{NEWLINE}výskume\"\n  STR_CONTAINMENT_EXCEEDED: \"LIMIT ZADRŽIAVACEJ CELY PRE MIMOZEMŠŤANOV BOL PREKROČENÝ!{SMALLLINE}Nedostatok miesta v {0}. Je potrebné odstrániť prevyšujúcich mimozemšťanov z cely (tí potom zahynú).\"\n  STR_MANAGE_CONTAINMENT: \"Správa zadržiavacej cely\"\n  STR_STORAGE_EXCEEDED: \"KAPACITA SKLADOV BOLA PREKROČENÁ!{SMALLLINE}Máme nedostatok miesta v {0}. Musíte predať nadbytočné predmety.\"\n  STR_GO_TO_BASE: \"Do základne\"\n  STR_MELEE_ACCURACY: \"BOJ Z BLÍZKA\"\n  STR_SELL_PRODUCTION: \"PREDAŤ\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Obe ruky musia byť voľné!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Nedostatok predmetov pre kopírovanie šablóny!\"\n  STR_UNLOAD_WEAPON: \"Vybiť zbraň\"\n  STR_ALL_ITEMS: \"Všetky predmety\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"NA PALUBU SA NEZMESTÍ VIAC VYBAVENIA!{SMALLLINE}Máte povolených maximálne {N} položku vybavenia na palube tohto stroja.\"\n    few: \"NA PALUBU SA NEZMESTÍ VIAC VYBAVENIA!{SMALLLINE}Máte povolených maximálne {N} položky vybavenia na palube tohto stroja.\"\n    many: \"NA PALUBU SA NEZMESTÍ VIAC VYBAVENIA!{SMALLLINE}Máte povolených maximálne {N} položiek vybavenia na palube tohto stroja.\"\n    other: \"NA PALUBU SA NEZMESTÍ VIAC VYBAVENIA!{SMALLLINE}Máte povolených maximálne {N} položiek vybavenia na palube tohto stroja.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}RIADIACE CENTRUM BOLO ZNIČENÉ{NEWLINE}Dostaňte sa do vstupnej oblasti a ukončite misiu.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"X-Com nemôže budovať podmorské základne na pevnine\"\n  STR_UNABLE_TO_ENGAGE_DEPTH: \"NEMÔŽE PRENASLEDOVAŤ PROTIVNíKA{NEWLINE}V TEJTO HĹBKE\"\n  STR_UNABLE_TO_ENGAGE_AIRBORNE: \"NEMÔŽE PRENASLEDOVAŤ PROTIVNíKA{NEWLINE}VO VZDUCHU\"\n  STR_UNDERWATER_EQUIPMENT: \"Toto vybavenie nebude fungovať na súši!\"\n  STR_LAND_EQUIPMENT: \"Toto vybavenie nebude fungovať pod vodou!\"\n  STR_LEVEL_SHORT: \"L{0}\"\n  STR_PERSONNEL: \"Personál\"\n  STR_CRAFT_ARMAMENT: \"Plavidlá a výzbroj\"\n  STR_COMPONENTS: \"Komponenty\"\n  STR_SOLDIERS_RECRUITED: \"Naverbovaných akvanautov\"\n  STR_SOLDIERS_LOST: \"Vojenské straty\"\n  STR_TOTAL_UFOS: \"Zistených ponoriek\"\n  STR_TOTAL_ALIEN_BASES: \"Objavených kolónii mimozemšťanov\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"MKO\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"MKS\"\n  FEMALE_CIVILIAN: \"Civilista, Žena\"\n  MALE_CIVILIAN: \"Civilista, Muž\"\n  DOCKER_CIVILIAN: \"Civilista, Robotník\"\n  SAILOR_CIVILIAN: \"Civilista, Námorník\"\n  STR_BIODRONE_MELEE_WEAPON: \"Bio-dron zblízka\"\n  HALLUCINOID_WEAPON: \"Zbraň halucinoida\"\n  STR_LOBSTERMAN_MELEE_WEAPON: \"Lobsterman zblízka\"\n  CALCINITE_WEAPON: \"Zbraň kalcinita\"\n  DEEP_ONE_WEAPON: \"Zbraň hĺbkomora\"\n  STR_TRISCENE_MELEE_WEAPON: \"Triscen zblízka\"\n  STR_TRIBIO_SONIC_WEAPON: \"Mimozemská sonická zbraň\"\n  XARQUID_WEAPON: \"Zbraň xarkida\"\n  TENTACULAT_WEAPON: \"Zbraň chápadlovca\"\n  ZOMBIE_WEAPON: \"Zbraň zombieho\"\n  ALIEN_PSI_WEAPON: \"Mimozemská M.K. zbraň\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/sv.yml",
    "content": "sv:\n  STR_LEVIATHAN_UFOPEDIA: \"TRANSPORT- OCH JAKTFARKOST MED BÅDE FLYG- OCH DJUPDYKNINGSFÖMÅGA. EN UTMÄRKT FUSION AV UTOMJORDISK OCH MÄNSKLIG TEKNOLOGI. ANVÄNDER ETT JONISKT DRIFTSYSTEM OCH ETT MAGNETISKT NAVIGATIONSSYSTEM.\"\n  STR_BARRACUDA_UFOPEDIA: \"DEN BRITTISKA BARRACUDAN DRIVS A SUPERVARMA LASERMOTORER. EN AV DE SNABBASTE JAKTFARKOSTERNA I VÄRLDEN SOM KAN BÅDE FLYGA OCH DYKA.\"\n  STR_HAMMERHEAD_UFOPEDIA: \"EN TRANSPORT- OCH JAKTFARKOST MED REKONSTRUERAT MAGNETNAVIGERINGSSYSTEM. EN LITEN KONTRUKTION MEN ETT TEKNISKT STORT FRAMSTEG.\"\n  STR_TRITON_UFOPEDIA: \"Triton, en trupp transport, utrustad med fulla atmosfäriska och akvatiska flygmotorer. Den stora kapaciteten och den robusta konstruktionen ser till att den är stöttepelaren i X-Com flottan.\"\n  STR_MANTA_UFOPEDIA: \"MANTA HÖGHASTIGHETSFARKOST. EN ENMANNAD, FLYGANDE UBÅT TILL JAKTFARKOST INSPIRERAD AV JON-DRIVNA UTOMJORDISKA SKEPP. ETT HÖGST EFFEKTIVT VAPEN I DEN ESKALERANDE KONFLIKTEN.\"\n  STR_AJAX_UFOPEDIA: \"Ajax torpeden är standard vapnet i undervattensstrid världen över. Används som ett pricksäkert och kraftfullt avskräckande medel.\"\n  STR_DUP_HEAD_UFOPEDIA: \"VAPENSYSTEM MED UTARMAT URAN I SPETSARNA ÄR RELATIVT NYTT. DETTA ÄR DET FÖRSTA KOMMERSIELLA UNDERVATTENSDESIGNADE VAPENSYSTEMET SOM UTNYTTJAR DETTA TILL FULLO.\"\n  STR_CRAFT_GAS_CANNON_UFOPEDIA: \"Ett komprimerad-gasdrivet kanonsystem som avfyrar fasta bultar med hög pansarbrytande förmåga.\"\n  STR_PWT_CANNON_UFOPEDIA: \"PULSVÅGSTORPEDEN KOMBINERAR ETT SUPERVARMT BRÄNSLESYSTEM MED EN EXTREMT TUNG STRIDSSPETS FÖR ATT SLÅ IGENOM DE FLESTA MATERIAL.\"\n  STR_GAUSS_CANNON_UFOPEDIA: \"GAUSS-VAPEN ÄR EN NYUTVECKLAD X-COM TEKNOLOGI. VAPNETS PARTIKELACCELERATORER DRIVS AV EN KOMPAKT FUSIONSREAKTOR SOM KYLS MED FLYTANDE KVÄVE.\"\n  STR_SONIC_OSCILLATOR_UFOPEDIA: \"EN KRAFTFULL LJUDOSCILLATOR SOM SKAPAR DÖDLIGA LJUDVÅGOR. FÖRSTÖR SITT MÅL GENOM ATT VIBRERA ISÄR SITT MÅLS MOLEKYLÄRA BYGGSTENAR.\"\n  STR_AQUATOID_UFOPEDIA: \"Akvatoiderna är uråldriga och fanns flera millennium innan människan tog sina första steg på jorden. Deras kompakta kroppar och runda anletsdrag visar släktskap med deras rymdburna bröder, Sectoiderna. Deras största styrka är den molekylära kontrollteknologin. Akvatoiderna är sterila och förökar sig genom genetisk modifikation, gärna på människor. Dessa experiment har gett upphov till flertalet hybrider.\"\n  STR_AQUATOID_AUTOPSY: \"Obduktion av Akvatoid\"\n  STR_AQUATOID_AUTOPSY_UFOPEDIA: \"En detaljerad analys av varelsen tillåter att dra vissa grunläggande slutsatser. Det är en Sectoid, våra tidigare fiender, men kirurgiskt förändrad för att göra den till en vattenlevande varelse. Rudimentära lungor tillåter inandning av luft och rörlighet på land. Cybernetiska implantat i kroppen förstärker kroppens försvagade lemmar och organ. Eftersom alla exemplar vi fått in är identiska misstänker vi att dessa varelser är kloner.\"\n  STR_GILLMAN_UFOPEDIA: \"Denna märkliga varelse ser ut som en reptilliknande människa, kanske närbesläktad med oss själva. Den är väldigt stark och kan röra sig snabbt under vatten. Gälmän är en fullt utvecklad ras eftersom det finns både män och kvinnor av varierande ålder. Till skillnad från de andra vattenbaserade utomjordingarna visar de inga tecken på genetiska eller kirurgiska förändringar. Det är möjligt att vi ser en uråldrig avgrening på vår egen art.\"\n  STR_GILLMAN_AUTOPSY: \"Gälman obduktion\"\n  STR_GILLMAN_AUTOPSY_UFOPEDIA: \"Så fort operation började blev det tydligt att detta inte var någon utomjording, utan en uråldrig, förhistorisk art som försvann när däggdjuren tog över. Redan när dinosaurierna levde fanns Gälmännen: amfibiska, intelligenta och starka. Katastrofen som dödade dinosaurierna tvingade dessa varelser till en symbiotiskt överenskommelse med de nyanlända utomjordingarna. En liten elektronisk apparat är införd i skallen på dessa varelser.\"\n  STR_LOBSTERMAN_UFOPEDIA: \"Det här är en häpnadsväckande varelse, högre än en människa och med sex lemmar, som mest liknar en vattenlevande demon. Likheterna mellan denna varelse och jordens hummer har gett den smeknamnet Hummerman bland X-Com-trupperna. Det här är ett havsmonster. En noggrant utformad stridsvarelse med otrolig styrka och praktiskt taget osårbar för missiler. Bara dess klor kan krossa stål.\"\n  STR_LOBSTERMAN_AUTOPSY: \"Obduktion av Hummerman\"\n  STR_LOBSTERMAN_AUTOPSY_UFOPEDIA: \"När man tagit sig igenom dess nästan ogenomträngliga skal är denna varelse en förundrande konstruktion. Kraftfulla muskler omfamnar ett skelett av titanium och ett sofistikerat målangivelsesystem med en flerkanalig skanningsförmåga är direkt inkopplad i hjärnan. Facettögonen är skyddade av en plast hårdare än stål och det är uppenbart att dessa varelser rätt använda är så gott som ostoppbara. Djupt i varelsens kropp är flera apparater av okänd konstruktion och funktion.\"\n  STR_TASOTH_UFOPEDIA: \"Dessa smidiga och snabba varelser utgör huvuddelen av utomjordingarnas arme. Hundratals föds upp i massiva avelskärl djupt i havets kolonier. Tasothen är starkare än en människa och har en blodtörst olikt något annat på vår planet. Tasotherna är ofta i fronten av fiendens attacker och verkar aldrig tveka ens mot överväldigande odds.\"\n  STR_TASOTH_AUTOPSY: \"Tasoth obduktion\"\n  STR_TASOTH_AUTOPSY_UFOPEDIA: \"Dissektionen visar en cybernetisk organism med märkliga krafter. Inuti kroppsöppningarna finns små kraftkällor, men inga direkta organ. Kraften sprids i kroppen genom ett bioelektriskt överföringssystem. När varelsen dör försvinner kraften och den blir en livlös trasdocka av löst, utomjordiskt kött och kroppsvätskor. Den andra interna delen är ett par keramiska celler, som när de tillförs ström återupplivar varelsen för ett ögonblick.\"\n  STR_DEEP_ONE_UFOPEDIA: \"Djuphavsvarelsen är en biologisk mardröm framtagen av de gränslösa Akvatoidernas experiment. Vi har haft kontakt med flera variationer av denna varelse. Efter undersökningar har vi konstaterat att det verkar vara genetiskt framtagna.\\nDe ökar i antal när inkräktarna fångat in levande människor.\\nVarje individuell varelse är beväpnad med en elektriskt laddad stöt som är kraftfull nog att döda en akvanaut.\"\n  STR_DEEP_ONE_AUTOPSY: \"Djuphavsvarelse obduktion\"\n  STR_DEEP_ONE_AUTOPSY_UFOPEDIA: \"Varelsen är en transplantation av en människa och en utomjordisk organism. Den mänskliga hjärnan ändras för att göra plats för kontrollmekanismer och en utomjordisk hjärnbark.\\nTransplantationen möjliggör att det utomjordiska fostret konsumerar den mänskliga värden när det växer. Skinnet är oorganiskt men extremt starkt och flexibelt.  \\nAlla spår av den mänskliga kroppen verkar i slutändan vara försvunna förutom två, ögonen.\"\n  STR_BIODRONE_UFOPEDIA: \"Bio-drönaren är en skapelse som bara ett omänskligt sinne kunnat konstruera. En hjärna (Mänsklig eller utomjordisk) placeras i en behållare med livmodersvätska vilken monteras på en plattform som kan sväva både på land och under vatten. Varje Bio-drönare är beväpnad med en kraftfull ljudkanon som är delvis mekanisk, delvis organisk. Våra forskare menar att vapnet drivs a hjärnorganismens stämband. Denna pricksäkra och envisa vakthund används för att skydda utomjordingarnas mest värdefulla tillgångar.\"\n  STR_BIODRONE_AUTOPSY: \"Bio-drönare obduktion\"\n  STR_BIODRONE_AUTOPSY_UFOPEDIA: \"Teorin om att ljudkanonen är biologisk är sann. Denna stackars varelse skriker bokstavligen ihjäl sina fiender. Varje exemplar har ärr från stora kirurgingrepp och saknar delar. Utomjordingarna verkar alltså stympa hjärnorna till lydnad. De flesta har utomjordisk hjärnbark, men inget är värre än att hitta ett mänskligt exemplar. Bio-drönaren drivs an en jonisk motor och har någon sorts system för fjärrstyrning.\"\n  STR_TENTACULAT_UFOPEDIA: \"Inte ens den djupaste av Lovecraftianska mardrömmar kunde ge upphov till denna obeskrivbara varelse. Den värld som skulle kunna naturligt forma denna varelse är bortom allt förstånd. Tentaculaten anfaller med sina långa tentakler som paralyserar dess offer och förvandlar det till ett själlöst ting. Denna avkomma kan döda vid beröring, även genom pansar. Tentaculaten är den mest skräckinjagande utomjording som påträffats av X-Com.\"\n  STR_TENTACULAT_AUTOPSY: \"Tentaculat obduktion\"\n  STR_TENTACULAT_AUTOPSY_UFOPEDIA: \"Obduktionen avslöjade små cybernetiska implantat införda i varelsens stora hjärna. Synen utgörs av en komplicerad kombination av synligt ljus och värmebildsupptagning. Även i de mörkaste vatten kan detta monster navigera med osviklig pricksäkerhet. Mindre organ verkar fylla ett minimum av funktion för att överleva. En mage med yttre mynning antyder att varelsen matas av sina ägare.\"\n  STR_CALCINITE_UFOPEDIA: \"Likt förlorade djuphavsdykare döljer sig dessa varelser på havets botten för lovligt byte. Ett slag från Calcinitens sylvassa stålklor kan fälla även den bäste dykaren.\\nI maskens fönster syns en grön gelatinliknande vätska virvla omkring. Vad som döljer sig under dräkten är en gåta.\"\n  STR_CALCINITE_AUTOPSY: \"Calcinite obduktion\"\n  STR_CALCINITE_AUTOPSY_UFOPEDIA: \"När dräkten väl tagits av visar sig Calciniten vara en stor, oformlig klump av protoplasma. Varken hjärna, lem eller sensoriska organ hittas. Bara en liten metallkomponent påträffas i klumpens mitt.\\nVi kan bara gissa oss till varelsens egentliga härkomst.\"\n  STR_TRISCENE_UFOPEDIA: \"Denna tvåbenta reptil är en rest från dinosaurietiden, Krita-perioden närmare bestämt. Den kan vistas både på land och i vatten och är beväpnad med skjutvapensystem och sylvassa metalltänder.\\nDessa varelser utgör ofta kärntruppen när utomjordingarna attackerar på land med sina tunga och dödliga vapen.\"\n  STR_TRISCENE_AUTOPSY: \"Triscene obduktion\"\n  STR_TRISCENE_AUTOPSY_UFOPEDIA: \"När vi obducerar Triscenen visar den sig vara en uråldrig varelse innehållandes cybernetiska implantat och vapensystem. Dess minimala hjärna kompletteras med en datormodul som monterats på kontrollanordningen varelsen bär. Triscenens hårda skinn, jaktinstinkt och vapensystem gör den till en livsfarlig fiende i alla miljöer.\"\n  STR_HALLUCINOID_UFOPEDIA: \"Inkräktarna verkar ha odlat dessa naturliga havsvarelser till biologiska vapen. Bli inte lurad av dess harmlösa utseende, tentaklerna kan döda med sitt isande gift.\"\n  STR_HALLUCINOID_AUTOPSY: \"Hallucinoid obduktion\"\n  STR_HALLUCINOID_AUTOPSY_UFOPEDIA: \"Inuti de många gelatinlagren hittar vi en kraftfull kemikalie med frysande egenskaper. Kroppens mjuka hölje verkar känsligt för värmebaserade attacker.\"\n  STR_XARQUID_UFOPEDIA: \"Xarquiden är ett vackert men farligt monster, genetiskt modifierat från Jordens egna varelser. Den snabbt simmande giganten innehar en arsenal bestående av siktskymmande bläckspruta och en joniserad partikelattack.\\nDe verkar främst strida tillsammans med Gällmännen. \"\n  STR_XARQUID_AUTOPSY: \"Xarquid obduktion\"\n  STR_XARQUID_AUTOPSY_UFOPEDIA: \"Denna gigantiska pärlbåtssnäcka har ändrats genom utomjordisk dopning och kirurgiska ingrepp. Gällmännen har installerat mekaniska kontrollsystem för att styra denna organiska vapenplattform. Dess hårda skal och simförmåga gör den till en dödlig fiende.\"\n  STR_ION_BEAM_ACCELERATORS_UFOPEDIA: \"Utomjordingarnas flygande ubåtar förlitar sig på komplexa energisystem för att driva dem i hög hastighet genom vattendjupen. Grundfunktionen är en jonförflyttare som använder Zrbite som en katalysator för att flytta vattenmassorna hundra gånger dess volym per sekund.\\nDenna enorma kraft gör att utomjordingarna utklassar de flesta av våra ubåtar fartmässigt. Vi kan replikera detta drivsystem med akvaplast och Zrbite-kristaller.\"\n  STR_MAGNETIC_NAVIGATION_UFOPEDIA: \"Den här anordningen genererar ett sfär-format magnetiskt fält med en radie på 1000 meter runt ubåten. Navigatören länkas direkt till maskinen igenom och \\\"känner\\\" sig igenom det ogenomträngliga djuphavet.\\nGränsnittet går genom modifierad utomjordisk hjärnsubstans som kommunicerar direkt med navigatörens hjärna via en neural länk.\"\n  STR_ALIEN_SUB_CONSTRUCTION_UFOPEDIA: \"Varje farkost har en kameleont-liknande struktur likt havsdjur och är konstruerade av akvaplast. Varje ubåt fungerar som en organism där besättningen och skeppet agerar i harmoni. Dessa system kan replikeras och vi kan utveckla en hybridteknik för att komma ikapp inkräktarna teknikmässigt.\"\n  STR_ALIEN_CRYOGENICS_UFOPEDIA: \"De oräkneliga utomjordingar som gömts på Jorden har hållits vid liv genom att frysas ner. De stängs in i individuella enheter som efter våra undersökningar kan vara så gamla som 60 miljoner år.\"\n  STR_ALIEN_CLONING_UFOPEDIA: \"Många av varelserna vi fångat är identiska ner till DNA-nivå. Celler från frusna genbanker placeras i kloningsenheten. Vissa enheter innehåller antingen människor eller delar av dem. Det är mycket möjligt att ändamålet är att skapa en mänsklig/utomjordisk hydrid.\"\n  STR_ALIEN_LEARNING_ARRAYS_UFOPEDIA: \"Med Molekylära Kontroll Implantat som finns i utomjordingarnas skallar kan information matas rakt in i hjärnan. Färskt klonade varelser förs till dessa maskiner för att få grundläggande kunskap om krig och vetenskap inpräntade i sina tomma sinnen.\"\n  STR_ALIEN_IMPLANTER_UFOPEDIA: \"Denna maskin används för att operera in Molekylära Kontroll Implantat, befrukta reproducerande varelser och ta bort samt lägga till organ och elektronik i alla sorters organismer.\\nVi trodde först att proceduren utfördes på sövda patienter men istället verkar offret högst medveten under operationen och tyvärr verkar maskinen perfekt anpassad till den mänskliga anatomin.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"Vi vet nu varför utomjordingarna kidnappar människor. Vi är inte mat eller gödning till deras embryon. Istället är vi basen för en mängdvarelser och kontrollsystem. Deras teknologi baseras på ett delat sinne och intellekt och den mänskliga hjärnan är ett idealiskt medium för detta system. Människans hjärnsubstans används i de flesta utomjordiska datorsystem för dataförvaring. Resten används för expansion och reproduktion.\"\n  STR_AQUA_PLASTICS_UFOPEDIA: \"Alienubåtar och strukturer använder ett otroligt starkt, flexibelt och hållbart material för den största delen av sin konstruktion. Akvaplast är komplexa multi-bindande och Zrbite-katalyserade material. Täta, men lätta, ämnet har styrka över även Titan eller Kevlar.\"\n  STR_ZRBITE_UFOPEDIA: \"Det här är en legering av utomjordiskt ursprung, delvis guld och delvis utomjordiskt biomaterial. När den används som kraftkälla, kommer små mängder att generera mer kraft än en kärnkraftsenhet som är 10 gånger så stor. Det är bortom vår tekniska förmåga att replikera detta material eftersom de flesta av dess beståndsdelar är av utomjordiskt ursprung.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"Utomjordingarna slår till jorden runt, med hänsynslös effektivitet. Vi har inte lyckats fastslå deras utgångspunkt. Kan den vara i något hav för djupt för oss att finna? Av de organismer vi påträffat är inte alla av utomjordisk härkomst, några är från evolutionsgrenar vi trott sedan länge utdöda. Vi har att göra med ett hot som legat i dvala i årtusenden, en subtil symbios mellan människa och det utomjordiska. Djupt i haven ligger uråldriga förläggningsplatser utomjordingarna använder för att kommunicera med sina avlägsna släktingar från stjärnorna. Var och en av dessa tolv platser huserar en Synomium-anordning, en kraftfull utomjordisk teknologi. Med deras krigsmaskineri nu på marsch håller utomjordingarna på att återaktivera dessa  förläggningar, för att vidga sitt molekylära kontrollnät, och vi måste förstöra dessa förläggningar till varje pris.\"\n  STR_THE_ULTIMATE_THREAT_UFOPEDIA: \"För sextiofem miljoner år sedan skickades ett väldigt koloniskepp till Jorden från en avlägsen utomjordisk värld. När det enorma skeppet närmade sig den unga planeten orsakade ett massivt och våldsamt solutbrott stora navigationsproblem för skeppet. Lamslaget och ur kontroll störtade den väldiga massan genom stratosfären och ner genom kritaperiodens himmel. På jordytan riktades ögonen från oräkneliga livsformer mot skyn medan deras domedag kraschade in i marken. Ett väldigt dammoln förmörkade atmosfären och i den efterföljande nedkylningen dukade dinosaurierna under. Men det fyra hundra miljarder ton tunga T'leth förstördes inte i nedslaget då sofistikerade superdatorer initierade en kryogenisk sömncykel för varelserna djupt i dess lastutrymmen. Och genom eonerna väckte datorerna då och då små grupper av utomjordingar, för att förska upprätta kommunikation med sina kusiner från stjärnorna - men förväges, då utomjordingarnas högsäte sov vidare.\"\n  STR_TLETH_THE_ALIEN_CITY: \"T'leth, utomjordingarnas stad\"\n  STR_TLETH_THE_ALIEN_CITY_UFOPEDIA: \"T'leth, det enorma utomjordiska koloniskeppet, ligger begravt i Sigsbee Deep i Mexikanska golfen. I hjärtat av staden finns en utomjordisk skräck, så avskyvärd och så mäktig att inte ens döden kan ta den. I en kammare av utomjordiskt metall ligger den store drömmaren, den ultimata utomjordingen, och sover. Att lyfta T'leth över vågorna kommer att starta hans återupplivningscykel, och när han väl har återuppstått kommer han att vara ostoppbar. Även om han inte är levande och på något sätt inte död, kontrollerar utomjordingen utomjordingsarmén. Den märkliga tekniken för molekylär kontroll förbinder alla utomjordingar med det enda sinnet och det enda sinnet med alla utomjordingar. Genetiskt muterade utomjordiska/mänskliga foster förser utomjordingen med energi och bildar länken mellan härskaren och hans undersåtar. Myten om den ultimata utomjordingen har funnits i människans hjärtan och sinnen i århundraden, men havet har alltid dolt den ultimata sanningen.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"CENTRERA PÅ PLATS-TID=5 s\"\n  STR_CANCEL_UC: \"AVBRYT\"\n  STR_NONE: \"Inga\"\n  STR_UNKNOWN: \"Okänd\"\n  STR_POOR: \"Dålig\"\n  STR_AVERAGE: \"Genomsnitt\"\n  STR_GOOD: \"Bra\"\n  STR_EXCELLENT: \"Utmärkt\"\n  STR_BUILD_NEW_BASE_UC: \"BYGG NY BAS\"\n  STR_BASE_INFORMATION: \"BASINFORMATION\"\n  STR_EQUIP_CRAFT: \"UTRUSTA U-BÅT\"\n  STR_BUILD_FACILITIES: \"BYGG ANLÄGGNINGAR\"\n  STR_RESEARCH: \"FORSKNING\"\n  STR_MANUFACTURE: \"TILLVERKNING\"\n  STR_TRANSFER_UC: \"ÖVERFÖR\"\n  STR_PURCHASE_RECRUIT: \"KÖP/ANSTÄLL\"\n  STR_SACK: \"AVSKEDA\"\n  STR_SELL_SACK_UC: \"SÄLJ/AVSKEDA\"\n  STR_GEOSCAPE_UC: \"GEOVY\"\n  STR_NAME: \"Namn\"\n  STR_AREA: \"Område\"\n  STR_BUILD_NEW_BASE: \"Bygg ny bas\"\n  STR_CANCEL: \"Avbryt\"\n  STR_COST_UC: \"KOSTNAD>\"\n  STR_CONSTRUCTION_TIME_UC: \"BYGGTID>\"\n  STR_DAY:\n    one: \"{N} dag\"\n    other: \"{N} dagar\"\n  STR_HOUR:\n    one: \"{N} timm\"\n    other: \"{N} timmar\"\n  STR_MAINTENANCE_UC: \"UNDERHÅLL>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Installation\"\n  STR_CURRENT_RESEARCH: \"NUVARANDE FORSKNING\"\n  STR_SCIENTISTS_AVAILABLE: \"Forskare Tillgängliga>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Forskare Tilldelade>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Laboratoriumutrymme Tillgängligt>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"FORSKNINGSPROJEKT\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"FORSKARE TILLDELADE\"\n  STR_PROGRESS: \"UTVECKLING\"\n  STR_NEW_PROJECT: \"Nytt projekt\"\n  STR_CANCEL_PROJECT: \"AVBRYT PROJEKT\"\n  STR_NEW_RESEARCH_PROJECTS: \"NYA FORSKNINGSPROJEKT\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"FORSKARE TILLGÄNGLIGA>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"LABORATORIEPLATSER TILLGÄNGLIGA>{ALT}{0}\"\n  STR_INCREASE: \"Öka\"\n  STR_DECREASE: \"Minska\"\n  STR_START_PROJECT: \"STARTA PROJEKT\"\n  STR_CURRENT_PRODUCTION: \"NUVARANDE PRODUKTION\"\n  STR_ENGINEERS_AVAILABLE: \"Tekniker tillgängliga>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Tekniker tilldelade>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Verkstadsutrymme tillgängligt>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Nuvarande tillgångar>{ALT}{0}\"\n  STR_ITEM: \"FÖREMÅL\"\n  STR_ENGINEERS__ALLOCATED: \"Tekniker tilldelade\"\n  STR_UNITS_PRODUCED: \"Enheter producerade\"\n  STR_TOTAL_TO_PRODUCE: \"Totalt att producera\"\n  STR_COST__PER__UNIT: \"Kostnad{NEWLINE}per{NEWLINE}enhet\"\n  STR_DAYS_HOURS_LEFT: \"Dagar/Timmar kvar\"\n  STR_NEW_PRODUCTION: \"Ny produktion\"\n  STR_PRODUCTION_ITEMS: \"Produktionsföremål\"\n  STR_CATEGORY: \"KATEGORI\"\n  STR_START_PRODUCTION: \"STARTA PRODUKTION\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} Teknikertimmar att producera en enhet\"\n  STR_COST_PER_UNIT_: \"Kostnad per enhet>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"VERKSTADSUTRYMME SOM KRÄVS>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"SPECIALMATERIEL KRÄVS\"\n  STR_ITEM_REQUIRED: \"FÖREMÅL KRÄVS\"\n  STR_UNITS_REQUIRED: \"ENHETSKRAV\"\n  STR_UNITS_AVAILABLE: \"ENHETER TILLGÄNGLIGA\"\n  STR_STOP_PRODUCTION: \"STOPPA PRODUKTION\"\n  STR_ENGINEERS_AVAILABLE_UC: \"TEKNIKER TILLGÄNGLIGA>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"VERKSTADSUTRYMME TILLGÄNGLIGT>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"MÅNATLIG VINST>{ALT}{0}\"\n  STR_INCREASE_UC: \"ÖKA\"\n  STR_DECREASE_UC: \"MINSKA\"\n  STR_UNITS_TO_PRODUCE: \"Enheter att producera\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Köp/Anställ Personal\"\n  STR_COST_OF_PURCHASES: \"Kostnad per köp>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"KOSTNAD PER ENHET\"\n  STR_QUANTITY_UC: \"KVANTITET\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"PERSONAL TILLGÄNGLIG:PERSONAL TOTAL>\"\n  STR_SOLDIERS: \"Akvanauter\"\n  STR_SCIENTISTS: \"Forskare\"\n  STR_ENGINEERS: \"Tekniker\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"UTRYMME ANVÄNT:UTRYMME TILLGÄNGLIGT>\"\n  STR_LIVING_QUARTERS: \"Logement\"\n  STR_STORES: \"Förråd\"\n  STR_LABORATORIES: \"Laboratorier\"\n  STR_WORK_SHOPS: \"Verkstäder\"\n  STR_HANGARS: \"Flygande ubåtsdocka\"\n  STR_SHORT_RANGE_DETECTION: \"Kortdistans Sonar\"\n  STR_DEFENSE_STRENGTH: \"Försvarstyrka\"\n  STR_TRANSFERS_UC: \"ÖVERFÖRINGAR\"\n  STR_TRANSFERS: \"Överföringar\"\n  STR_ARRIVAL_TIME_HOURS: \"Ankomsttid (timmar)\"\n  STR_COST_: \"Kostnad>{ALT}{0}\"\n  STR_AREA_: \"Område>{ALT}{0}\"\n  STR_BASE_NAME: \"Basens namn?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"VÄLJ POSITION FÖR LUFTSLUSS\"\n  STR_TRANSFER: \"Överför\"\n  STR_AMOUNT_TO_TRANSFER: \"ANTAL ATT ÖVERFÖRA\"\n  STR_SELECT_DESTINATION_BASE: \"Välj destinationsbas\"\n  STR_COST: \"Kostnad\"\n  STR_INTRO_1: \"Copyright 1995 MicroProse\"\n  STR_INTRO_2: \"Mars: Cydonias undergång\"\n  STR_INTRO_3: \"En segerrik X-Com, som har förstört kärnan av den Utomjordiska krigsmaskinen, åker hem. Dock, allt är inte dött i den förstörda Marsian basen.\"\n  STR_INTRO_4: \"En kraftfull takyonstråle strömmar från spillrorna av det Cydonianska nervcentrumet - rusande genom tomrummet. Destinationen............\"\n  STR_INTRO_5: \"Jorden.\"\n  STR_INTRO_6: \"Djupt nere i havet träffar strålen en mottagare som varit inaktiv under lång tid. Stora sovande datorer börjar vakna till liv. I djupet, utom synhåll för människor, påbörjar stora kamrar med sovande utomjordingar sin långa återupplivningscykel.\"\n  STR_INTRO_7: \"2040: En ignorant Jord. Terrorn från kriget med utomjordingarna är glömt. Men, i de förlorade och gömda platserna under havet är de utomjordiska horderna redo att störta mänskligheten och ta över världen.\"\n  STR_INTRO_8: \"Utomjordingarna attackerar mänskligheten, letar efter försökspersoner för sina sjukliga experiment, plundrar jorden på värdefulla mineraler och resurser och rövar från haven. Sedan riktar utomjordingarna blicken mot vågorna.\"\n  STR_INTRO_9: \"Kraftfulla flygande ubåtar med märklig design färdas över haven – letar, söker, jagar...\"\n  STR_INTRO_10: \"När de hittar ett byte attackerar de.\"\n  STR_INTRO_11: \"Konstiga nya vapen används mot en försvarslös värld. Vi är helt i händerna på det främmande hotet.{NEWLINE}Endast en organisation kan rädda oss, men vi vände dem ryggen för länge sedan......\"\n  STR_INTRO_12: \"X-COM:s experimentella undervattensanläggning\"\n  STR_INTRO_13: \"'Mayday! Mayday!' 'Det här är den transatlantiska fartygen Hyperion'. 'Vi blir anfallna'. 'Mayday! Mayd............'\"\n  STR_INTRO_14: \"”Kommandocentral till ubåt ett: Öppna dörrarna till havet”, ”sätt in Barracuda Zero One. Vi har en situation med utomjordisk attack – rött läge”.{NEWLINE}”Jag upprepar: rött läge”\"\n  STR_INTRO_15: \"Aliens är hänsynslösa i sin effektivitet...\"\n  STR_INTRO_16: \"...ofelbara i sin noggrannhet\"\n  STR_INTRO_17: \"”Barracuda Zero One till basen” – ”närmar sig det som återstår av Hyperion”.\"\n  STR_INTRO_18: \"”Saktar in”.{NEWLINE}”Två meter”.{NEWLINE}”En meter”.{NEWLINE}”Alla akvanauter, förbered er för omedelbar insats”.\"\n  STR_INTRO_19: \"...........’Luftslussen klar’...’närmar sig vraket’.{NEWLINE}’Herregud!’{NEWLINE}’Ser du de där varelserna på min dräktkamera?’\"\n  STR_GAMEOVER_1: \"Vi har misslyckats, utomjordingarna har krossat våra sista förhoppningar om räddning.{NEWLINE}X-Com är förstört och jorden ligger under den uråldriga fiendens fötter.\"\n  STR_GAMEOVER_2: \"T'leth dundrar högt upp i stratosfären och börjar röra sig över jordens yta. Den sprider död och skördar resterna av mänskligheten. Djupt inne i dess inre börjar det mordiska främmande sinnet vakna till liv.\"\n  STR_GAMEOVER_3: \"I alla nationers huvudstäder utarbetas desperata planer. Allt är förgäves, utan den teknik som X-Com-forskningsprojektet tillhandahåller är våra vapen verkningslösa.\"\n  STR_GAMEOVER_4: \"Utomjordingarna etablerar baser vid polarna och börjar smälta isen, världen kommer att förvandlas till ett stort hav. Resterna av mänskligheten samlas ihop och används i avskyvärda avelsexperiment för okända utomjordiska syften. Himlen mörknar och en mäktig pest drabbar jordens länder.\"\n  STR_GAMEOVER_5: \"Vi kan inte göra motstånd mot den nya världsordningen, och de som försöker möter ett våldsamt öde i händerna på obegripliga utomjordiska vapen. För resten av oss finns ingen sådan välsignad befrielse, moder jord blir en främmande värld och mänskligheten går under i en krypande skräck.\"\n  STR_OUTRO_1: \"Graven, ödelagd och förstörd, ett bubblande vrål kommer från kistan i dess centrum.{NEWLINE}Ni dårar kommer alla att förgås....................\"\n  STR_OUTRO_2: \".................ingen kan undkomma.\"\n  STR_OUTRO_3: \"En enorm explosion bryter ut från graven och skakar om staden, skräp och rök fyller luften. Utomjordingarnas planer går i stöpet...\"\n  STR_OUTRO_4: \"T'leths vindlande storhet börjar spricka. Flammor och rök sprutar ut från dess glänsande spiror och adamantiumhallar.\"\n  STR_OUTRO_5: \"Den mäktiga utomjordiska fästningen störtar mot havet, skriken från plågade metaller och själar fyller luften. Den store drömmaren kommer inte längre att drömma om att erövra världen.\"\n  STR_OUTRO_6: \"En sista öronbedövande ljudvåg och T'leth slits itu.{NEWLINE}Hotet från utomjordingarna är borta, Jorden är renad..................\"\n  STR_OUTRO_7: \"En sömnig blågrön planet, i ett avlägset hörn av galaxen.\"\n  STR_OUTRO_8: \"Den nära framtiden, en säker plats att vara på.\"\n  STR_OUTRO_9: \"Det utomjordiska hotet mot jorden har sedan länge besegrats.\"\n  STR_OUTRO_10: \"Stora metropoler som städer huserar miljarder människor.\"\n  STR_OUTRO_11: \"X-Coms bedrifter och kriget mot utomjordingarna är ämnen som hör hemma i barnböcker.\"\n  STR_OUTRO_12: \"Men legender har alltid haft en tendens att innehålla ett korn av sanning...\"\n  STR_RISE_1: \"T'leth, kallad många saker i många legender från många länder.\"\n  STR_RISE_2: \"Med ett explosivt skrik som ekar över hela världen börjar T'leth stiga upp från havsbotten.\"\n  STR_RISE_3: \"Den enorma byggnaden reser sig ur vattnet i Mexikanska golfen.\"\n  STR_RISE_4: \"400 miljarder ton utomjordisk metall, den mäktiga främmande staden där den ultimata främmande varelsens sovande kropp ligger. Fängslad på jorden i 65 miljoner år börjar denna avskyvärda rymdgud att röra på sig.\"\n  STR_RISE_5: \"Vattnet kokar och bubblar när den Store drömmarens grav träder fram i ljuset................\"\n  STR_RISE_6: \".........ett ljus som kommer att vara kortlivat om inte X-Com kan förstöra utomjordingarnas krigsmaskin.\"\n  STR_YOU_HAVE_FAILED: \"Du har misslyckats med att stoppa utomjordingarnas krigsmaskin. Finansieringsorganisationerna, som är desillusionerade över din förmåga, försöker förhandla fram en icke-militär lösning med utomjordingarna. Invasörerna har en helt annan agenda och snart är hela världen medveten om sanningen...\"\n  STR_TOTAL_UC: \"TOTAL\"\n  STR_INCOME: \"Inkomst\"\n  STR_EXPENDITURE: \"Utgifter\"\n  STR_MAINTENANCE: \"Underhåll\"\n  STR_BALANCE: \"Saldo\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"Utomjordisk aktivitet i hav\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"Utomjordisk aktivitet i zoner\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"X-Com-aktivitet i hav\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"X-Com-aktivitet i zoner\"\n  STR_FINANCE: \"Finans\"\n  STR_DATE_FIRST: \"{0}:a\"\n  STR_DATE_SECOND: \"{0}:a\"\n  STR_DATE_THIRD: \"{0}:e\"\n  STR_DATE_FOURTH: \"{0}:e\"\n  STR_FINANCE_THOUSANDS: \"$1000's\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Otillräckligt med specialmaterial för att producera{NEWLINE}{0}{NEWLINE}i{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Otillräckligt med pengar för att producera{NEWLINE}{0}{NEWLINE}i{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"Produktion av {NEWLINE}{0}{NEWLINE}på{NEWLINE}{1}{NEWLINE}är avklarad\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"Konstruktion av{NEWLINE}{0}{NEWLINE}på{NEWLINE}{1}{NEWLINE}är slutförd\"\n  STR_OK_5_SECONDS: \"OK - 5 s\"\n  STR_RESEARCH_COMPLETED: \"Forskning avslutad\"\n  STR_VIEW_REPORTS: \"GRANSKA RAPPORTER\"\n  STR_WE_CAN_NOW_RESEARCH: \"Vi kan nu undersöka\"\n  STR_WE_CAN_NOW_PRODUCE: \"Vi kan nu producera\"\n  STR_SUNDAY: \"SÖNDAG\"\n  STR_MONDAY: \"MÅNDAG\"\n  STR_TUESDAY: \"TISDAG\"\n  STR_WEDNESDAY: \"ONSDAG\"\n  STR_THURSDAY: \"TORSDAG\"\n  STR_FRIDAY: \"FREDAG\"\n  STR_SATURDAY: \"LÖRDAG\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Inte tillräckligt med {0} för att fylla på {1} i {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Inte tillräckligt med {0} för att rusta om {1} i {2}\"\n  STR_UFO_IS_NOT_RECOVERED: \"Utomjordisk u-båt inte inhämtat\"\n  STR_UFO_IS_RECOVERED: \"Utomjordisk u-båt inhämtat\"\n  STR_CRAFT_IS_LOST: \"Flygande u-båt förlorad\"\n  STR_TERROR_CONTINUES: \"Utomjordisk aktivitet fortsätter\"\n  STR_ALIENS_DEFEATED: \"Utomjordingar besegrade\"\n  STR_BASE_IS_LOST: \"Basen är förlorad\"\n  STR_BASE_IS_SAVED: \"Basen är räddad\"\n  STR_ALIEN_BASE_STILL_INTACT: \"Utomjordisk koloni fortfarande intakt\"\n  STR_ALIEN_BASE_DESTROYED: \"Utomjordisk koloni förstörd\"\n  STR_ALIENS_KILLED: \"UTOMJORDINGAR DÖDADE\"\n  STR_ALIEN_CORPSES_RECOVERED: \"UTOMJORDISKA KROPPAR INHÄMTADE\"\n  STR_LIVE_ALIENS_RECOVERED: \"LEVANDE UTOMJORDINGAR INFÅNGADE\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"UTOMJORDISKA FÖREMÅL BESLAGTAGNA\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"UTOMJORDINGSKOLONIENS KONTROLLENHET FÖRSTÖRD\"\n  STR_ALIEN_SYNOMIUM_DEVICE_DESTROYED: \"UTOMJORDISK SYNOMIUM APPARAT FÖRSTÖRD\"\n  STR_ALIEN_SYNOMIUM_DEVICE_FAILED: \"MISSLYCKADE ATT FÖRSTÖRA SYNOMIUM APPARAT\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"CIVILA DÖDADE AV UTOMJORDINGAR\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"CIVILA DÖDADE AV X-COM-AGENTER\"\n  STR_CIVILIANS_SAVED: \"CIVILA RÄDDADE\"\n  STR_XCOM_OPERATIVES_KILLED: \"X-COM-AGENTER DÖDADE\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"X-COM AGENTER SAKNADE I STRID\"\n  STR_TANKS_DESTROYED: \"X-COM VAPENPLATFORM FÖRSTÖRD\"\n  STR_XCOM_CRAFT_LOST: \"X-COM U-BÅT FÖRLORAD\"\n  STR_UFO_RECOVERY: \"BÄRGNING AV UTOMJORDISK UBÅT\"\n  STR_ALIEN_BASE_RECOVERY: \"UTVINNING AV UTOMJORDISK KOLONI\"\n  STR_BASE_UNDER_ATTACK: \"{0} är under attack!\"\n  STR_BASE_DEFENSES_INITIATED: \"BASFÖRSVAR INLETT\"\n  STR_FIRING: \"AVFYRAR\"\n  STR_HIT: \"TRÄFF!\"\n  STR_UFO_DESTROYED: \"UTOMJORDISK U-BÅT FÖRSTÖRD!\"\n  STR_MISSED: \"MISS!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Sälj Föremål/Avskeda Personal\"\n  STR_VALUE_OF_SALES: \"SÄLJVÄRDE>{ALT}{0}\"\n  STR_FUNDS: \"TILLGÅNGAR>{ALT}{0}\"\n  STR_SELL_SACK: \"Sälj/Avskeda\"\n  STR_VALUE: \"Värde\"\n  STR_CRAFT_: \"FLYGANDE UBÅT> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"BÄRGNING AV KRASCHAD UTOMJORDISK UBÅT\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"EXTREM FÖRSIKTIGHET - Det kommer att finnas utomjordingar i ubåten och runt om på platsen. Uppdraget är slutfört när alla fiendeenheter har eliminerats eller neutraliserats. Därefter kan återvinningen av ubåtens rester, teknik och utomjordiska lik påbörjas. För att avbryta uppdraget, återför X-Com-akvanauterna till ubåten och klicka på ikonen ”Avbryt uppdrag”.\"\n  STR_UFO_GROUND_ASSAULT: \"ATTACK MOT UTOMJORDISK UBÅT\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"Utforska nedslagsplatsen och försök om möjligt ta dig in i den utomjordiska ubåten. Uppdraget är lyckat när alla fiendeenheter har eliminerats eller neutraliserats. Därefter kan du påbörja bärgningen av den främmande ubåten, artefakterna och de främmande liken. För att avbryta uppdraget, återför X-Com-akvanauterna till ubåten och klicka på ikonen ”Avbryt uppdrag”.\"\n  STR_BASE_DEFENSE: \"BASFÖRSVAR\"\n  STR_BASE_UC_: \"BAS> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"En utomjordisk farkost som har landat i närheten. Vår bas är i allvarlig fara. Enligt standardförfarande har all icke-stridspersonal och fungerande X-Com-ubåtar evakuerats. Utomjordingar kommer att gå in i basen via ubåtsdockor eller luftslussar. Försvara basen och dess vitala installationer till varje pris - det här är en kamp till döden. Om du klickar på ikonen \\\"Överge Uppdrag?\\\" ger du upp och förlorar basen.\"\n  STR_ALIEN_COLONY_ATTACK_MISSION: \"ATTACKUPPDRAG MOT UTOMJORDISK KOLONI\"\n  STR_ALIEN_BASE_ASSAULT: \"UTOMJORDISK KOLONI DEL ETT\"\n  STR_ALIEN_COLONY_P1_BRIEFING: \"Det här uppdraget är en räd mot en utomjordisk koloni. Det finns två nivåer på platsen. Få alla akvanauter till den lysande utgången i den första anläggningen och klicka på ikonen ”Avbryt uppdrag” för att fortsätta. All utrustning som lämnas kvar kommer att ligga kvar på havsbotten tills den andra delen är klar. För att avsluta, placera akvanauterna i ubåten och klicka på ikonen ”Avbryt uppdrag”.\"\n  STR_ALIEN_COLONY_P2: \"UTOMJORDISK KOLONI DEL TVÅ\"\n  STR_ALIEN_COLONY_P2_BRIEFING: \"Efter att ha klarat den första nivån och kommit in i koloniens kärna är uppdraget nu att förstöra kontrollcentret, Synomium-enheten, eller eliminera alla utomjordingar. För att avbryta uppdraget placerar du alla akvanauter på startpunkten och klickar på ikonen ”Avbryt uppdrag”. All användbar X-Com-utrustning återförs till basen.\"\n  STR_ALIENS_LAUNCH_PORT_TERROR: \"UTOMJORDINGAR INLEDER{NEWLINE}HAMNATTACK PÅ\"\n  STR_PORT_TERROR: \"UTOMJORDINGAR INLEDER HAMNATTACK\"\n  STR_PORT_TERROR_BRIEFING: \"Utomjordingar har inlett en attack mot ytanläggningar. Hamnen och dess civila befolkning är i fara. Din trupp måste eliminera alla utomjordingar och skydda oskyldiga åskådare från denna utomjordiska invasion. För att avsluta, placera akvanauterna i den flygande ubåten och klicka på ikonen ”Avbryt uppdrag”.\"\n  STR_ALIENS_LAUNCH_ISLAND_TERROR: \"UTOMJORDINGAR INLEDER{NEWLINE}ATTACK MOT ÖN PÅ\"\n  STR_ISLAND_TERROR: \"UTOMJORDINGAR INLEDER ATTACK PÅ Ö\"\n  STR_ISLAND_TERROR_BRIEFING: \"Utomjordingar har inlett en attack mot ytanläggningar. Ön och dess civilbefolkning är i fara. Din trupp måste eliminera alla utomjordingar och skydda oskyldiga åskådare från denna utomjordiska invasion. För att avsluta, placera akvanauterna i den flygande ubåten och klicka på ikonen ”Avbryt uppdrag”.\"\n  STR_CARGO_SHIP_P1: \"LASTFARTYG DEL ETT\"\n  STR_CARGO_SHIP_P2: \"LASTFARTYG DEL TVÅ\"\n  STR_CRUISE_SHIP_P1: \"KRYSSNINGSFARTYG DEL ETT\"\n  STR_CRUISE_SHIP_P2: \"KRYSSNINGSFARTYG DEL TVÅ\"\n  STR_SHIP_RESCUE_MISSION: \"UPPDRAG FÖR SKEPPSRÄDDNING\"\n  STR_SHIP_RESCUE_P1_BRIEFING: \"Detta uppdrag är en jakt, eliminera alla utomjordiska enheter på skeppet och rädda livet på alla civila ombord. Utomjordingarna är utspridda över och under däck, säkra de övre däcken innan du går in på de nedre. För att avsluta, placera akvanauterna i den flygande ubåten och klicka på ikonen ”Avbryt uppdrag”.\"\n  STR_SHIP_RESCUE_P2_BRIEFING: \"Nu när det övre däcket är säkrat kan du fortsätta till de nedre däcken. Använd lasthissen för att ta dig ner till lastrummet. Din trupp måste eliminera alla utomjordingar på denna nivå för att slutföra uppdraget. För att avbryta uppdraget placerar du alla akvanauter på hissens startpunkt och klickar på ikonen ”Avbryt uppdrag”.\"\n  STR_ALIEN_ACTIVITY_DETECTED: \"UTOMJORDISK AKTIVITET UPPTÄCKT\"\n  STR_ALIEN_CONTACT_SITE_MISSION: \"UPPDRAG FÖR UTOMJORDISK KONTAKTPLATS\"\n  STR_ARTIFACT_SITE_P1: \"UTOMJORDISK KONTAKTPLATS DEL ETT\"\n  STR_ARTIFACT_SITE_P1_BRIEFING: \"Denna uppdrag är en räd mot en nyligen aktiverad utomjordisk kommunikationsstation. Stationen har två nivåer: havsbotten med utomjordiska pyramider och en dold utomjordisk anläggning. För alla akvanauter till ingången till anläggningen och klicka på ikonen ”Avbryt uppdrag” för att fortsätta. För att avsluta, placera akvanauterna i den flygande ubåten och klicka på ikonen ”Avbryt uppdrag”.\"\n  STR_ARTIFACT_SITE_P2: \"UTOMJORDISK KONTAKTPLATS DEL TVÅ\"\n  STR_ARTIFACT_SITE_P2_BRIEFING: \"Efter att ha förhandlat om de utomjordiska strukturerna och kommit in i komplexet är uppdragets mål tydliga. Träng in i hjärtat av den utomjordiska anläggningen och förstör Synomium Molecular Control Device för att slutföra uppdraget. För att avbryta uppdraget, placera alla akvanauter på startpunkten för hissarna och klicka på ikonen ”Avbryt uppdrag”.\"\n  STR_TLETH_P1_BRIEFING: \"Vi ger oss in i det okända, härifrån kan vad som helst vänta på oss. Vi vet att det finns ytterligare två nivåer i utomjordiska staden och din trupp måste skynda sig till utgången på denna nivå för att komma vidare till nästa. Placera alla akvanauter vid utgången och klicka på ikonen ”Avbryt uppdrag” för att gå vidare. Om du avbryter någon annanstans avslutas uppdraget.\"\n  STR_TLETH_P2_BRIEFING: \"Längre in i det okända, härifrån och framåt kan vad som helst vänta på oss. Vi vet att det finns en ytterligare nivå i utomjordiska staden och din trupp måste skynda sig till utgången på denna nivå för att komma vidare till nästa. Placera alla akvanauter vid utgången och klicka på ikonen ”Avbryt uppdrag” för att gå vidare. Om du avbryter någon annanstans avslutas uppdraget.\"\n  STR_TLETH_P3_BRIEFING: \"Slutet är i sikte, från och med nu letar vi efter den ultimata utomjordings krypta. Förstör de åtta strömkällorna till graven för att göra slut på utomjordingshotet. Ge inte upp nu! Om du avbryter uppdraget avslutas det.\"\n  STR_TLETH_P1: \"UTOMJORDISK STAD NIVÅ ETT\"\n  STR_TLETH_P2: \"UTOMJORDISK STAD NIVÅ TVÅ\"\n  STR_TLETH_P3: \"UTOMJORDISK STAD NIVÅ TRE\"\n  STR_CANNOT_BUILD_HERE: \"KAN INTE BYGGA HÄR!{SMALLLINE}Du måste bygga bredvid en redan byggd anläggning.\"\n  STR_NO_FREE_ACCOMODATION: \"INGA FRIA LOGIUTRYMMEN!{SMALLLINE}Destinationsbasen har inte tillräckligt med utrymme i sina logement.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"OTILLRÄCKLIGT MED ARBETSUTRYMME!{SMALLLINE}Bygg nya verkstäder eller minska arbetsstorleken på andra projekt.\"\n  STR_NOT_ENOUGH_MONEY: \"OTILLRÄCKLIGT MED PENGAR!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"OTILLRÄCKLIGT FÖRRÅDSUTRYMME!{SMALLLINE}Bygg nya förråd eller överför material till andra baser.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"OTILLRÄCKLIGT MED LOGIUTRYMMEN!{SMALLLINE}Bygg nya logement eller överför personal till andra baser.\"\n  STR_LAUNCH_INTERCEPTION: \"STARTA GENSKJUTNING\"\n  STR_CRAFT: \"FARKOST\"\n  STR_STATUS: \"STATUS\"\n  STR_BASE: \"BAS\"\n  STR_READY: \"REDO\"\n  STR_OUT: \"UT\"\n  STR_REPAIRS: \"REPARATIONER\"\n  STR_REFUELLING: \"TANKAR\"\n  STR_REARMING: \"OMRUSTAS\"\n  STR_TARGET: \"MÅL: {0}\"\n  STR_WAY_POINT: \"VÄGPUNKT\"\n  STR_ARE_YOU_SURE_CYDONIA: \"Är du säker på att du vill sända denna U-båt på uppdrag till T'leth?\"\n  STR_YES: \"JA\"\n  STR_NO: \"NEJ\"\n  STR_SELECT_DESTINATION: \"VÄLJ DESTINATION\"\n  STR_CYDONIA: \"T'LETH\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"VÄLJ PLATS FÖR NY BAS\"\n  STR_RETURN_TO_BASE: \"ÅTERVÄND TILL BASEN\"\n  STR_SELECT_NEW_TARGET: \"VÄLJ NYTT MÅL\"\n  STR_PATROL: \"PATRULLERA\"\n  STR_STATUS_: \"STATUS>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"SKADAD - ÅTERVÄNDER TILL BAS\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"LÅG BRÄNSLENIVÅ - ÅTERVÄNDER TILL BAS\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"UPPDRAG SLUTFÖRT - ÅTERVÄNDER TILL BAS\"\n  STR_PATROLLING: \"PATRULLERAR\"\n  STR_TAILING_UFO: \"FÖLJER UTOMJORDISK U-BÅT\"\n  STR_INTERCEPTING_UFO: \"GENSKJUTER UTOMJORDISK U-BÅT-{0}\"\n  STR_RETURNING_TO_BASE: \"ÅTERVÄNDER TILL BAS\"\n  STR_DESTINATION_UC_: \"DESTINATION: {0}\"\n  STR_BASE_UC: \"BAS>{ALT}{0}\"\n  STR_SPEED_: \"HASTIGHET>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"MAXHASTIGHET>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"DJUP>{ALT}{0}\"\n  STR_AIRBORNE: \"LUFTBUREN\"\n  STR_VERY_LOW: \"GRUND\"\n  STR_LOW_UC: \"NORMAL\"\n  STR_HIGH_UC: \"DJUP\"\n  STR_VERY_HIGH: \"VÄLDIGT DJUP\"\n  STR_FUEL: \"BRÄNSLE>{ALT}{0}\"\n  STR_WEAPON_ONE: \"VAPEN-1>{ALT}{0}\"\n  STR_NONE_UC: \"INGEN\"\n  STR_ROUNDS_: \"SKOTT>{ALT}{0}\"\n  STR_WEAPON_TWO: \"VAPEN-2>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"FLYGANDE UBÅT\"\n  STR_BASE_: \"Bas>{0}\"\n  STR_NAME_UC: \"NAMN\"\n  STR_AMMO_: \"AMMO>{ALT}{0}\"\n  STR_CREW: \"BESÄTTNING\"\n  STR_EQUIPMENT_UC: \"UTRUSTNING\"\n  STR_ARMOR: \"PANSAR\"\n  STR_MAX: \"MAX>{ALT}{0}\"\n  STR_ROOKIE: \"Sjöman\"\n  STR_SQUADDIE: \"Erfaren sjöman\"\n  STR_SERGEANT: \"Fänrik\"\n  STR_CAPTAIN: \"Löjtnant\"\n  STR_COLONEL: \"Kommendör\"\n  STR_COMMANDER: \"Kapten\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Välj Trupp för {0}\"\n  STR_SORT_BY: \"SORTERA EFTER...\"\n  STR_ORIGINAL_ORDER: \"ORIGINAL ORDNING\"\n  STR_MISSIONS2: \"UPPDRAG\"\n  STR_KILLS2: \"DÖDADE\"\n  STR_WOUND_RECOVERY2: \"SJUKDAGAR\"\n  STR_SPACE_AVAILABLE: \"UTRYMME TILLGÄNGLIGT>{ALT}{0}\"\n  STR_SPACE_USED: \"UTRYMME ANVÄNT>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"UTRYMME ANVÄNT\"\n  STR_RANK: \"GRAD\"\n  STR_WOUNDED: \"SKADAD\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Utrustning för {0}\"\n  STR_DEFENSE_VALUE: \"Försvarsvärde\"\n  STR_HIT_RATIO: \"Träffratio\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}redo att{NEWLINE}landa nära{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"Påbörja uppdrag?\"\n  STR_SELECT_ARMAMENT: \"Välj Bestyckning\"\n  STR_AMMUNITION_AVAILABLE: \"AMMUNITION TILLGÄNGLIG\"\n  STR_ARMAMENT: \"BESTYCKNING\"\n  STR_NOT_AVAILABLE: \"N.A.\"\n  STR_TYPE: \"TYP\"\n  STR_ION_ARMOR_UC: \"ION-KROPPSSKYDD\"\n  STR_MAGNETIC_ION_ARMOR_UC: \"MAGNETISKT ION-KROPPSSKYDD\"\n  STR_PLASTIC_AQUA_ARMOR_UFOPEDIA: \"Detta kroppsskydd använder det nyupptäckta utomjordiska ämnet akvaplast och säkerställer att våra akvanauter får en chans att bekämpa det utomjordiska angreppet.\"\n  STR_ION_ARMOR_UFOPEDIA: \"Detta kroppsskydd är ett kraftfullt nytt skydd för akvanauter. Den drivs av en ION-energikälla och förstärker bärarens hastighet och styrka avsevärt. Den erbjuder det bästa skyddet hittills för stridande trupper.\"\n  STR_MAGNETIC_ION_ARMOR_UFOPEDIA: \"En förbättring av ION-rustningen som införlivar Magnetic Array-tekniken för att möjliggöra full rörelsefrihet i vattenmiljön.\"\n  STR_SELECT_ARMOR: \"Välj Rustning\"\n  STR_NORTH: \"NORR\"\n  STR_NORTH_EAST: \"NORDÖST\"\n  STR_EAST: \"ÖST\"\n  STR_SOUTH_EAST: \"SYDÖST\"\n  STR_SOUTH: \"SYD\"\n  STR_SOUTH_WEST: \"SYDVÄST\"\n  STR_WEST: \"VÄST\"\n  STR_NORTH_WEST: \"NORDVÄST\"\n  STR_SELECT_ACTION: \"VÄLJ HANDLING\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"FORTSÄTT GENSKJUTNINGSJAKT\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"FÖLJ EFTER UTAN GENSKJUTNING\"\n  STR_VERY_LARGE: \"VÄLDIGT STOR\"\n  STR_LARGE: \"STOR\"\n  STR_MEDIUM_UC: \"MELLAN\"\n  STR_SMALL: \"LITEN\"\n  STR_VERY_SMALL: \"VÄLDIGT LITEN\"\n  STR_GROUNDED: \"LANDAT\"\n  STR_DETECTED: \"Upptäckt\"\n  STR_SIZE_UC: \"STORLEK\"\n  STR_ALTITUDE: \"DJUP\"\n  STR_HEADING: \"KURS\"\n  STR_SPEED: \"HASTIGHET\"\n  STR_TRACKING_LOST: \"SPÅR FÖRLORAT\"\n  STR_REDIRECT_CRAFT: \"OMDIRIGERA FARKOST\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"GÅ TILL SIST KÄNDA U-BÅT-POSITION\"\n  STR_UFO_: \"UTOMJORDISK U-BÅT-{0}\"\n  STR_ALIEN_BASE_: \"UTOMJORDISK KOLONI-{0}\"\n  STR_CRASH_SITE_: \"OLYCKSPLATS-{0}\"\n  STR_LANDING_SITE_: \"LANDNINGSPLATS-{0}\"\n  STR_WAY_POINT_: \"VÄGPUNKT-{0}\"\n  STR_TERROR_SITE: \"TERRORISERAD ORT-{0}\"\n  STR_ARTIFACT_SITE: \"ARTEFAKTPLATS-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}har anlänt till{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"Patrullerar\"\n  STR_ALIEN_ORIGINS: \"Utomjordingarnas Ursprung\"\n  STR_THE_ULTIMATE_THREAT: \"Det Ultimata Hotet\"\n  STR_TLETH_ALIEN_CITY: \"T'leth, Utomjordingarnas Stad\"\n  STR_UFOPAEDIA: \"UFOpedia\"\n  STR_XCOM_CRAFT_ARMAMENT: \"X-COM FARKOSTER & VAPEN\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"UNDERVATTENSVAPENSYSTEM\"\n  STR_WEAPONS_AND_EQUIPMENT: \"ALLMÄN UTRUSTNING\"\n  STR_ALIEN_ARTIFACTS: \"AKVATISKA ARTEFAKTER\"\n  STR_BASE_FACILITIES: \"X-COM-ANLÄGGNINGAR\"\n  STR_ALIEN_LIFE_FORMS: \"Utomjordiska Varelser\"\n  STR_ALIEN_RESEARCH_UC: \"Utomjordisk Teknologi\"\n  STR_UFO_COMPONENTS: \"NYA UNDERVATTENSTEKNOLOGIER\"\n  STR_UFOS: \"UTOMJORDISKA U-BÅTAR\"\n  STR_SELECT_ITEM: \"VÄLJ FÖREMÅL\"\n  STR_ACCELERATION: \"ACCELERATION>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"BRÄNSLEKAPACITET>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"VAPENSYSTEM>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"SKADEKAPACITET>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"LASTUTRYMME>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"SWS-KAPACITET>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Skada\"\n  STR_RANGE: \"Räckvidd\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"Träffsäkerhet\"\n  STR_RE_LOAD_TIME: \"Omladdningstid\"\n  STR_SECONDS: \"{0}s\"\n  STR_DAMAGE_ARMOR_PIERCING: \"PANSARBRYTANDE\"\n  STR_DAMAGE_INCENDIARY: \"FOSFOR\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"HÖGEXPLOSIVT\"\n  STR_DAMAGE_LASER_BEAM: \"GAUSS-STRÅLE\"\n  STR_DAMAGE_PLASMA_BEAM: \"SONISK STRÅLE\"\n  STR_DAMAGE_STUN: \"FRYS\"\n  STR_DAMAGE_MELEE: \"NÄRSTRID\"\n  STR_DAMAGE_ACID: \"SYRA\"\n  STR_DAMAGE_SMOKE: \"RÖK\"\n  STR_SHOT_TYPE: \"TYP\"\n  STR_ACCURACY_UC: \"TRÄFFSÄKERHET\"\n  STR_TIME_UNIT_COST: \"TE-KOST\"\n  STR_DAMAGE_UC: \"SKADA\"\n  STR_AMMO: \"AMMO\"\n  STR_SHOT_TYPE_AUTO: \"Auto\"\n  STR_SHOT_TYPE_SNAP: \"Fäst\"\n  STR_SHOT_TYPE_AIMED: \"Välriktat\"\n  STR_CONSTRUCTION_TIME: \"Byggtid\"\n  STR_CONSTRUCTION_COST: \"Byggkostnad\"\n  STR_MAINTENANCE_COST: \"Underhållskostnad\"\n  STR_LOW: \"Låg\"\n  STR_MEDIUM: \"Mellan\"\n  STR_HIGH: \"Hög\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Tunga vapensystem\"\n  STR_WEAPON: \"Vapen\"\n  STR_AMMUNITION: \"Ammunition\"\n  STR_EQUIPMENT: \"Utrustning\"\n  STR_ALIEN_CORPSE: \"Utomjordiskt lik\"\n  STR_PERSONAL_ARMOR: \"Personlig skyddsutrustning\"\n  STR_RAW_MATERIALS: \"Råmaterial\"\n  STR_ALIEN: \"Utomjording\"\n  STR_AQUATOID: \"Akvatoid\"\n  STR_GILLMAN: \"Gälman\"\n  STR_LOBSTERMAN: \"Hummerman\"\n  STR_TASOTH: \"Tasoth\"\n  STR_CALCINITE: \"Calcinite\"\n  STR_BIODRONE: \"Bio-drönare\"\n  STR_ZOMBIE: \"Zombie\"\n  STR_LIVE_COMMANDER: \"Kommendör\"\n  STR_LIVE_NAVIGATOR: \"Navigatör\"\n  STR_LIVE_MEDIC: \"Sjukvårdare\"\n  STR_LIVE_TECHNICIAN: \"Tekniker\"\n  STR_LIVE_SQUAD_LEADER: \"Gruppchef\"\n  STR_LIVE_SOLDIER: \"Soldat\"\n  STR_LIVE_TERRORIST: \"Terrorist\"\n  STR_AQUATOID_COMMANDER: \"Akvatoid Kommendör\"\n  STR_AQUATOID_NAVIGATOR: \"Akvatoid Navigatör\"\n  STR_AQUATOID_MEDIC: \"Akvatoid Sjukvårdare\"\n  STR_AQUATOID_TECHNICIAN: \"Akvatoid Tekniker\"\n  STR_AQUATOID_SQUAD_LEADER: \"Akvatoid gruppchef\"\n  STR_AQUATOID_SOLDIER: \"Akvatoid Soldat\"\n  STR_GILLMAN_SQUAD_LEADER: \"Gälman gruppchef\"\n  STR_LOBSTERMAN_NAVIGATOR: \"Hummerman navigatör\"\n  STR_LOBSTERMAN_TECHNICIAN: \"Hummerman tekniker\"\n  STR_LOBSTERMAN_SQUAD_LEADER: \"Hummerman gruppchef\"\n  STR_LOBSTERMAN_SOLDIER: \"Hummerman soldat\"\n  STR_TASOTH_SQUAD_LEADER: \"Tasoth gruppchef\"\n  STR_MAGNETIC_NAVIGATION: \"Magnetisk navigering\"\n  STR_ALIEN_SUB_CONSTRUCTION: \"Konstruktion av utomjordisk u-båt\"\n  STR_ALIEN_CLONING: \"Utomjordisk kloning\"\n  STR_EXAMINATION_ROOM: \"Undersökningsrum\"\n  STR_AQUA_PLASTICS: \"Akvaplast\"\n  STR_ION_ARMOR: \"Ion-kroppsskydd\"\n  STR_GAUSS_TECH: \"Gauss-teknologi\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Nytt Jaktplan-Trupptransportör\"\n  STR_THE_LATEST_FLYING_SUB: \"Den senaste flygande ubåten\"\n  STR_ARMOR_PIERCING: \"PANSARBRYTANDE\"\n  STR_GAUSS_CANNON: \"Gauss-kanon\"\n  STR_AJAX_TORPEDOES: \"Ajax Torpeder\"\n  STR_CRAFT_GAS_CANNON_ROUNDS_X50: \"Gas Skott(x50)\"\n  STR_SONIC_WAVE: \"Sonisk våg\"\n  STR_SOLDIER: \"Akvanaut\"\n  STR_SCIENTIST: \"Forskare\"\n  STR_ENGINEER: \"Tekniker\"\n  STR_NORTH_ATLANTIC: \"Nordatlanten\"\n  STR_SOUTH_ATLANTIC: \"Sydatlanten\"\n  STR_NORTH_PACIFIC: \"Norra Stilla havet\"\n  STR_SOUTH_PACIFIC: \"Södra Stilla havet\"\n  STR_MEDITERRANEAN: \"Medelhavet\"\n  STR_SOUTH_CHINA_SEA: \"Sydkinesiska havet\"\n  STR_INDIAN_OCEAN: \"Indiska Oceanen\"\n  STR_THE_EAST_SEA: \"Japanska havet\"\n  STR_NORTH_SEA: \"Nordsjön\"\n  STR_CARRIBEAN: \"Karibien\"\n  STR_ANTARCTIC: \"Antarktis\"\n  STR_ARCTIC: \"Arktisk\"\n  STR_EURASIA: \"Eurasien\"\n  STR_NORTH_AMERICA: \"Nordamerika\"\n  STR_AFRICA: \"Afrika\"\n  STR_MAXIMUM_SPEED: \"Maxfart\"\n  STR_TRITON: \"TRITON\"\n  STR_HAMMERHEAD: \"HAMMARHAJ\"\n  STR_LEVIATHAN: \"LEVIATAN\"\n  STR_BARRACUDA: \"BARRACUDA\"\n  STR_MANTA: \"MANTA\"\n  STR_UFO: \"UTOMJORDISK U-BÅT\"\n  STR_AJAX: \"AJAX\"\n  STR_GAUSS_CANNON_UC: \"GAUSS-KANON\"\n  STR_DAMAGE_CAPACITY: \"Skadekapacitet\"\n  STR_WEAPON_POWER: \"Vapenkraft\"\n  STR_WEAPON_RANGE: \"Vapenräckvidd\"\n  STR_AIR_LOCK: \"Luftsluss\"\n  STR_LABORATORY: \"Laboratorie\"\n  STR_WORKSHOP: \"Verkstad\"\n  STR_STANDARD_SONAR: \"Standard Sonar\"\n  STR_TORPEDO_DEFENSES: \"Torpedförsvar\"\n  STR_GENERAL_STORES: \"Lagerutrymme\"\n  STR_ALIEN_CONTAINMENT: \"Utomjordingsförvaring\"\n  STR_GAUSS_DEFENSES: \"Gaussförsvar\"\n  STR_BOMBARDMENT_SHIELD: \"Bombardemangssköld\"\n  STR_SUB_PEN: \"Ubåtsdocka\"\n  STR_USA: \"USA\"\n  STR_ALASKA: \"ALASKA\"\n  STR_EU_SYNDICATE: \"EURO-SYNDIKATET\"\n  STR_ARABIAN_BLOC: \"ARABISKA BLOCKET\"\n  STR_EGYPTIAN_CARTEL: \"EGYPTISKA KARTELLEN\"\n  STR_AFRICA_CORP: \"AFRICA CORP\"\n  STR_BRAZILIAN_UNION: \"BRASILIANSKA UNIONEN\"\n  STR_NEW_MEXICO: \"NYA MEXIKO\"\n  STR_ASIAN_COALITION: \"ASIATISKA KOALITIONEN\"\n  STR_SCANDINAVIA: \"SCANDINAVIEN\"\n  STR_NEO_JAPAN: \"NEO-JAPAN\"\n  STR_FREE_CHINA: \"FRIA KINA\"\n  STR_AUSTRALASIA: \"AUSTRALASIEN\"\n  STR_FED_KOREA: \"FED KOREA\"\n  STR_EURASIA_UC: \"EURASIEN\"\n  STR_ICELANDIC_UNION: \"ISLÄNDSKA UNIONEN\"\n  STR_TANK: \"Undervattensvapensystem\"\n  STR_CIVILIAN: \"Civilist\"\n  STR_JAN: \"Jan\"\n  STR_FEB: \"Feb\"\n  STR_MAR: \"Mar\"\n  STR_APR: \"Apr\"\n  STR_MAY: \"Maj\"\n  STR_JUN: \"Jun\"\n  STR_JUL: \"Jul\"\n  STR_AUG: \"Aug\"\n  STR_SEP: \"Sep\"\n  STR_OCT: \"Okt\"\n  STR_NOV: \"Nov\"\n  STR_DEC: \"Dec\"\n  STR_INTERNATIONAL_RELATIONS: \"Internationella Relationer\"\n  STR_COUNTRY: \"Land\"\n  STR_FUNDING: \"Finansiering\"\n  STR_CHANGE: \"Ändra\"\n  STR_WEAPON_SYSTEMS: \"VAPENSYSTEM\"\n  STR_HWPS: \"SWSer\"\n  STR_DAMAGE_UC_: \"SKADA>{ALT}{0}\"\n  STR_AIR_LOCK_UFOPEDIA: \"Luftslussen tillåter utrustning och personal att komma in eller ut från undervattensbasen. Det är alltid slussen som byggs först i en ny bas. Slussen är sårbar för intrång från potentiellt fientliga styrkor.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Varje logement får plats med 50 anställda. Anläggningen är något grundläggande och funktionell.\"\n  STR_LABORATORY_UFOPEDIA: \"Femtio forskare kan jobba i ett laboratorie. Laboratorier är utrustade med den senaste teknologin för forsking inom material, biokemi och vapen. X-Com har tillgång till de bästa forskningslabben över hela världen, både civila och militära.\"\n  STR_WORKSHOP_UFOPEDIA: \"En verkstad innehåller alla verktyg för att tillverka utrustning baserade på de senaste designritningar från forskningslabben. 50 tekniker kan arbeta i en verkstad, föremål under konstruktion kommer också ta upp plats.\"\n  STR_STANDARD_SONAR_UFOPEDIA: \"Ett sonarsystem har som standard en effektiv räckvidd på över 450 kilometer på de flesta djup och är kopplat till geostationära satellitnät för ytanalys. Varje skanner har 10% chans att upptäcka ett undervattensfarkost eller luftfarkost per 30 minuters skanningscykel.\"\n  STR_WIDE_ARRAY_SONAR_UFOPEDIA: \"Ett bredbandigt sonarsystem har en effektiv räckvidd på över 700 kilometer på alla djup och är kopplat till geostationära satellitnät för ytanalys. Varje skanner har 20% chans att upptäcka ett undervattensfarkost eller flygfarkost var 30:e minut under skanningscykeln.\"\n  STR_TORPEDO_DEFENSES_UFOPEDIA: \"Torpedförsvarssystem ger skydd mot attack av fientliga undervattensfarkoster som försöker docka vid basen.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"All utrustning, vapensystem, ammunition, återvunnet material och undervattensvapensystem placeras i förråd, inklusive utrustning som tilldelats ubåtar i dockor.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"Levande utomjordingar kräver särskilda isoleringsanläggningar för att hållas instängda. Dessa enheter upprätthåller deras livssystem och reducerar deras stridspotential till noll. Isoleringsanläggningen kan hålla 10 utomjordiska livsformer instängda i isoleringsceller.\"\n  STR_PWT_DEFENSES_UFOPEDIA: \"Pulsvågstorpedor är det mest effektiva försvaret mot utomjordiska attacker. Dessa missiler har supertäta stridsspetsar som kan penetrera alla kända pansar. De magnetiska vågorna de producerar inaktiverar elektroniska försvarssystem.\"\n  STR_BOMBARDMENT_SHIELD_UFOPEDIA: \"Tryckbombardemangsskölden skyddar basen från att utomjordiska undervattensfarkoster dockar och skapar ett resonansfält som stöter bort angripande ubåtar tillräckligt länge för att försvarssystemen ska hinna avfyras upprepade gånger. I praktiken fördubblar detta effektiviteten hos alla försvarssystem som redan är utplacerade.\"\n  STR_MC_GENERATOR_UFOPEDIA: \"Eftersom utomjordiska ubåtar använder molekylär kontrollteknik för att upptäcka närvaron av levande varelser, kommer användningen av en negativ M.C.-sändare att täcka basen med ett ogenomträngligt sköld som förvirrar utomjordingarna och döljer vår närvaro.\"\n  STR_MC_LAB_UFOPEDIA: \"Molekylkontrollaboratoriet kan implantera och träna upp till tio akvanauter samtidigt. Implantaten installeras kirurgiskt i akvanauternas skallar. Omfattande träning gör det möjligt för dem att använda sina implantat. Implantatfärdigheterna används tillsammans med en molekylär enhet och kan användas för attacker under strid.\"\n  STR_TRANSMISSION_RESOLVER_UFOPEDIA: \"Kommunikationen med utomjordingarna sker via det nätverk av molekylära kontrollimplantat som utomjordingarna har byggt upp. Överföringsresolveranläggningen fångar upp överföringar från utomjordiska ubåtar och avkodar informationen. Detta visar vilken typ av utomjordisk ubåt det rör sig om, vilken utomjordisk ras det är och vilken typ av aktivitet som pågår.\"\n  STR_SUB_PEN_UFOPEDIA: \"Varje docka rymmer en ubåt. Det finns anläggningar för underhåll, tankning och reparation av X-Com:s ubåtsflotta. Varje flygubåt som är stationerad vid en bas måste ha en ledig docka tilldelad sig som inte kan användas av andra ubåtar, även om den tilldelade ubåten är ute på uppdrag.\"\n  STR_DART_PISTOL_UFOPEDIA: \"X-Com-pilpistolen är en liten, precis och kraftfull enhet med ett magasin för 12 ihåliga pilar. Pilarna avfyras av en gaspatron i ammunitionsmagasinet.\"\n  STR_JET_HARPOON_UFOPEDIA: \"Detta vattengevär är träffsäkert, kraftfullt och avfyrar ihåliga stålharpuner från förseglade förpackningar om 10 stycken. Varje harpun har sin egen gasbehållare.\"\n  STR_GAS_CANNON_UFOPEDIA: \"Denna kanon är tungviktaren i gasteknikfamiljen och avfyrar solida bultar, vissa med HE- eller fosforspetsar. Ett favoritvapen bland erfarna akvanauter.\"\n  STR_TORPEDO_LAUNCHER_UFOPEDIA: \"Denna stora avfyrningsanordning är en riktig tungviktare som avfyrar tre typer av torpeder, var och en med sin egen drivningsenhet. Ett förödande vapen, vars enda nackdel är att det måste laddas manuellt. Tillgängliga ammunitionstyper inkluderar stora eller små högexplosiva torpeder och torpeder med fosforspets, alla endast avsedda för användning under vatten.\"\n  STR_GAUSS_PISTOL_UFOPEDIA: \"Gausspistolen använder accelererad partikelteknologi, en ny utveckling i moderna vapen. Den är snabb, precis och fungerar både ur och i vatten. Gaussteknologi är en utveckling utifrån Plasmateknologin lärt ifrån den förre kriget. \"\n  STR_GAUSS_PISTOL_CLIP_UFOPEDIA: \"Gausspistolen använder accelererad partikelteknologi, en ny utveckling i moderna vapen. Den är snabb, precis och fungerar både ur och i vatten. Gaussteknologi är en utveckling utifrån Plasmateknologin lärt ifrån den förra kriget. \"\n  STR_GAUSS_RIFLE_UFOPEDIA: \"Ett steg bortom Gauss-pistolen, geväret har en rejäl slagkraft med sina dubbla partikelacceleratorer. I stället för det Elerium-drivna plasmasystemet har vi använt en mikropartikelaccelerator som genererar en ström av antiprotoner.\"\n  STR_GAUSS_RIFLE_CLIP_UFOPEDIA: \"Ett steg bortom Gauss-pistolen, geväret har en rejäl slagkraft med sina dubbla partikelacceleratorer. I stället för det Elerium-drivna plasmasystemet har vi använt en mikropartikelaccelerator som genererar en ström av antiprotoner.\"\n  STR_HEAVY_GAUSS_UFOPEDIA: \"Den tunga Gauss är otymplig, men extremt effektiv. Den fungerar med tre partikelacceleratorer och är praktiskt taget omöjlig att stoppa. Antiprotonströmmen är innesluten i ett galliumarsenidskal som imploderar vid kollision och frigör antimateria.\"\n  STR_HEAVY_GAUSS_CLIP_UFOPEDIA: \"Den tunga Gauss är otymplig, men extremt effektiv. Den fungerar med tre partikelacceleratorer och är praktiskt taget omöjlig att stoppa. Antiprotonströmmen är innesluten i ett galliumarsenidskal som imploderar vid kollision och frigör antimateria.\"\n  STR_MAGNA_BLAST_GRENADE_UFOPEDIA: \"Denna standardgranat har en exakt och sofistikerad timer för precis kontroll.\"\n  STR_DYE_GRENADE_UFOPEDIA: \"Färggranater är föremål med dubbla funktioner, användbara för att ge skydd i utsatta situationer. De fungerar både i vatten och på land, och färgen sprutas ut som ett partikelmoln som bildar en bläckstråle liknande en bläckfisk i vatten eller ett tätt moln i luften på land.\"\n  STR_PARTICLE_DISTURBANCE_GRENADE_UFOPEDIA: \"En närhetsgranat som kan kastas som en vanlig granat men som utlöses av rörelser i närheten efter att den har placerats ut. Det krävs skicklighet och träning för att använda dessa enheter på rätt sätt.\"\n  STR_MAGNA_PACK_EXPLOSIVE_UFOPEDIA: \"Denna sprängämne ska endast användas för rivningsändamål. Tidigare erfarenheter har dock visat att dessa kraftfulla sprängämnen är perfekta vapen för att utrota utomjordingar. Sprängradien är stor, så se till att inga akvanauter befinner sig inom minsta säkerhetsavstånd.\"\n  STR_PARTICLE_DISTURBANCE_SENSOR_UFOPEDIA: \"Denna nya enhet använder en rad olika detektorer och avancerade datorsystem för att identifiera rörliga fiendeenheter. Klicka på ikonen Störningssensor på den taktiska skärmen. Välj ”Använd sensor” från menyn. Sensordisplayen visar en pil i mitten som anger den riktning som akvanauten är vänd mot (norr är uppåt). Blipsen visar enheter som har rört sig nyligen. Stora enheter eller snabbt rörliga enheter ger större blips. Statiska enheter visas inte.\"\n  STR_MEDI_KIT_UFOPEDIA: \"För att använda detta vänder du dig mot den skadade X-Com-agenten eller ställer dig över kroppen av en medvetslös akvanaut.{NEWLINE}HELA> Rött indikerar sår. Välj kroppsdel och klicka på knappen ”Hela”. Ett dödligt sår läks och hälsan återställs.{NEWLINE}STIMULANT> Återställer energi och återupplivar medvetslösa akvanauter. För att återuppliva en medvetslös akvanaut måste du stå direkt över kroppen.{NEWLINE}SMÄRTSTILLANDE> Återställer moralen hos skadade akvanauter.\"\n  STR_THERMAL_TAZER_UFOPEDIA: \"Denna anordning kan endast användas i närstrid, men kommer att bedöva en levande organism utan att döda den genom att frysa varelsen.\"\n  STR_VIBRO_BLADE_UFOPEDIA: \"Vibroblade är en lång, vass knivblad av titan som roterar med över 6000 varv per minut. Denna anordning kan krossa även den hårdaste dykarutrustningen. Kraftkällan är en utomjordisk uppfinning. Våra tidigare försök att bygga dessa föremål misslyckades totalt, eftersom våra blad roterade för långsamt eller exploderade under tryck.\"\n  STR_THERMIC_LANCE_UFOPEDIA: \"Den termiska lansen är en logisk vidareutveckling av Vibroblade-tekniken. Bladet roterar med hög hastighet och en Zrbite-kraftkälla överhettar bladet så att det skär igenom pansar som en varm kniv genom smör.\"\n  STR_HEAVY_THERMIC_LANCE_UFOPEDIA: \"Den tunga termiska lansen är en kraftfullare version av TL. Dubbla värmekällor och en extremt hög rotationshastighet gör att den tunga termiska lansen är praktiskt taget oövervinnlig mot alla material.\"\n  STR_SONIC_CANNON_UFOPEDIA: \"Den soniska kanonen är den mest kraftfulla av de soniska vapnen. Den har en ljudoscillator med högre räckvidd och en större efterklangskammare än Blasta. Kanonen har också ett pulsdetoneringssystem som förändrar ultraljudsvågen genom modulering för att producera en mer effektiv sonisk chockvåg.\"\n  STR_CANNON_POWER_CLIP_UFOPEDIA: \"Denna kompakta enhet används som ammunition för en sonisk kanon. Den innehåller en liten mängd Zrbite.\"\n  STR_SONIC_BLASTA_RIFLE_UFOPEDIA: \"En kraftfullare sonisk anordning. Inte ens högkolstål är immunt mot detta vapen. Den mycket kompakta vågsändaren förstärks av en superledande förstärkare för att öka vapnets kraft.\"\n  STR_BLASTA_POWER_CLIP_UFOPEDIA: \"Detta lilla föremål används som kraftkälla för ett soniskt gevär, ett kraftfullt utomjordiskt vapen, och innehåller en liten mängd Zrbite.\"\n  STR_SONIC_PISTOL_UFOPEDIA: \"Soniska pistoler är ett utomjordiskt vapen som baseras på ultraljudsvågor som kan omvandla ben till gelé på några sekunder. Ultraljudsvågorna ligger utanför det mänskliga hörselområdet.\"\n  STR_PISTOL_POWER_CLIP_UFOPEDIA: \"Kraftkälla för den kompakta utomjordiska soniska pistolen. Innehåller Zrbite – källan till all utomjordisk kraft.\"\n  STR_SONIC_PULSER_UFOPEDIA: \"Denna anordning fungerar på samma sätt som en vanlig granat – förutom att den är många gånger kraftfullare. Granaten använder en enda sonisk våg som avges i alla riktningar samtidigt.\"\n  STR_MC_READER_UFOPEDIA: \"Inuti kropparna på utomjordingarna har vi hittat små kirurgiskt implanterade enheter. Dessa är kontrollimplantat som har utformats av akvatoiderna för att möjliggöra en konstant informationsflöde från slagfältet, även på stora avstånd. Molekulär kontrolläsare är en utomjordisk kommunikationsenhet som används för att hämta information direkt från M.C.-implantat. X-Com-enheter kan använda denna enhet i strid för att visa en utomjordings egenskaper. Välj alternativet ”använd”. Klicka sedan på en utomjording med markören.\"\n  STR_SURVEY_SHIP: \"Undersökningsfartyg\"\n  STR_ESCORT: \"Eskort\"\n  STR_CRUISER: \"Kryssare\"\n  STR_HEAVY_CRUISER: \"Tungkryssare\"\n  STR_HUNTER: \"Jagare\"\n  STR_BATTLESHIP: \"Slagskepp\"\n  STR_DREADNOUGHT: \"Dreadnought\"\n  STR_FLEET_SUPPLY_CRUISER: \"Fartygsförsörjningskryssare\"\n  MAP_SEABED: \"Havsbotten\"\n  MAP_PIPES: \"Forskningsanläggning\"\n  MAP_PLANE: \"Kraschat plan\"\n  MAP_ATLAN: \"Atlantis\"\n  MAP_MU: \"Mayatempel\"\n  MAP_GAL: \"Sjunken galleon\"\n  MAP_VOLC: \"Vulkanisk\"\n  MAP_CORAL: \"Korall\"\n  MAP_PORT: \"Hamn\"\n  MAP_ISLAND: \"Ö\"\n  MAP_CARGO: \"Fraktskepp\"\n  MAP_LINERT: \"Kryssningsskepp P1\"\n  MAP_LINERB: \"Kryssningsskepp P2\"\n  MAP_ALART: \"Artefakt P1\"\n  MAP_GRUNGE: \"Artefakt P2\"\n  MAP_ENTRY: \"Koloni P1\"\n  MAP_A_BASE: \"Koloni P2\"\n  MAP_ALSHIP: \"T'leth P1\"\n  MAP_LEVEL: \"T'leth P2\"\n  MAP_CRYPT: \"T'leth P3\"\n  MAP_XBASES: \"X-COM Bas\"\n  STR_MIXED_CREW: \"Blandad besättning\"\n  STR_MIXED_CREW_2: \"Blandad besättning 2\"\n  STR_RATING: \"GRADERING> {0}\"\n  STR_RATING_TERRIBLE: \"FRUKTANSVÄRT!\"\n  STR_RATING_POOR: \"DÅLIG!\"\n  STR_RATING_OK: \"OK\"\n  STR_RATING_GOOD: \"BRA!\"\n  STR_RATING_EXCELLENT: \"UTMÄRKT!\"\n  STR_SCORE: \"POÄNG\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"MÅNADSRAPPORT FÖR X-COM\"\n  STR_MONTH: \"Månad> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"Finansieringsorganisationernas kommitté är generellt sett nöjd med dina framsteg hittills.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"Finansieringsorganisationernas kommitté är mycket nöjd med dina utmärkta framsteg. Fortsätt med det goda arbetet.\"\n  STR_COUNCIL_IS_DISSATISFIED: \"Finansieringsorganisationernas kommitté är missnöjd med dina prestationer. Du måste förbättra din effektivitet i hanteringen av utomjordingshotet, annars riskerar du att X-Com:s finansiella stöd dras in.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"Ni har inte lyckats hantera invasionen av utomjordingar och kommittén för finansieringsorganisationer har tyvärr beslutat att avsluta finansieringen av X-Com. Varje organisation ska hantera problemet på det sätt de finner lämpligt. Vi kan bara hoppas att vi kan komma överens med dessa uråldriga krafter och att allmänheten kommer att acceptera de vattenlevande besökarna.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} är väldigt nöjd med din förmåga att hantera hot inom nationens gränser och har beslutat att öka sitt anslag.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} är väldigt nöjd med din förmåga att hantera lokala intrång från utomjordingarna och har beslutat att öka sina anslag.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} och {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} är missnöjd med din förmåga att hantera utomjordisk aktivitet i dess hav och har beslutat att minska sitt ekonomiska engagemang.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} är missnöjda med din förmåga att hantera utomjordisk aktivitet i deras hav och har beslutat att minska sin finansiering.\"\n  STR_KNOTS: \"{0} knop\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} har undertecknat ett samarbetsavtal med de utomjordiska styrkorna och har dragit sig ur finansieringen av X-Com.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} har undertecknat ett samarbetsavtal med utomjordiska krafter och har dragit sig ur finansieringen av X-Com.\"\n  STR_MONTHLY_RATING: \"Månadsutvärdering> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Inkomständring> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"Finansieringsorganisationen är inte nöjd med din ekonomiska situation. Du måste minska dina skulder till under 1 miljon dollar, annars kommer X-Com att avslutas.\"\n  STR_CRAFT_TYPE: \"UBÅTSTYP\"\n  STR_RACE: \"ART\"\n  STR_MISSION: \"UPPDRAG\"\n  STR_ZONE: \"ZON\"\n  STR_ALLOCATE_RESEARCH: \"Fördela Forskning\"\n  STR_ALLOCATE_MANUFACTURE: \"Fördela Tillverkning\"\n  STR_AZORES: \"Azorerna\"\n  STR_REYKJAVIK: \"Reykjavik\"\n  STR_BERMUDA: \"Bermuda\"\n  STR_NEW_YORK: \"New York\"\n  STR_BOSTON: \"Boston\"\n  STR_FORT_SEVERN: \"Fort Severn\"\n  STR_DAKAR: \"Dakar\"\n  STR_RECIFE: \"Recife\"\n  STR_ACCRA: \"Accra\"\n  STR_ASCENSION_ISLAND: \"Ascensionön\"\n  STR_TRINIDADE_ISLAND: \"Trindadeön\"\n  STR_FALKLAND_ISLAND: \"Falklandsöarna\"\n  STR_CANARY_ISLANDS: \"Kanarieöarna\"\n  STR_ANCHORAGE: \"Anchorage\"\n  STR_ST_LAWRENCE_ISLAND: \"St Lawrence Island\"\n  STR_SAN_FRANCISCO: \"San Francisco\"\n  STR_MIDWAY_ISLAND: \"Midwayöarna\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_TASMANIA: \"Tasmanien\"\n  STR_HAWAII: \"Hawaii\"\n  STR_FIJI: \"Fiji\"\n  STR_TONGA: \"Tonga\"\n  STR_EASTER_ISLAND: \"Påskön\"\n  STR_GALAPAGOS_ISLAND: \"Galapagosöarna\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_SOLOMON_ISLAND: \"Solomonöarna\"\n  STR_CRETE: \"Kreta\"\n  STR_LISBON: \"Lissabon\"\n  STR_PORT_SAID: \"Port Said\"\n  STR_MARSEILLES: \"Marseilles\"\n  STR_TRIPOLI: \"Tripoli\"\n  STR_MANILA: \"Manila\"\n  STR_HONG_KONG: \"Hong Kong\"\n  STR_SINGAPORE: \"Singapore\"\n  STR_BANGKOK: \"Bangkok\"\n  STR_DARWIN: \"Darwin\"\n  STR_BOMBAY: \"Mumbai\"\n  STR_SAYCHELLES_ISLAND: \"Seychellerna\"\n  STR_MALDIVE_ISLAND: \"Maldiverna\"\n  STR_SRI_LANKA: \"Sri Lanka\"\n  STR_MAURITIUS: \"Mauritius\"\n  STR_TOKYO: \"Tokyo\"\n  STR_SHANGHAI: \"Shanghai\"\n  STR_VLADIVOSTOK: \"Vladivostok\"\n  STR_LONDON: \"London\"\n  STR_FAEROE_ISLAND: \"Färöarna\"\n  STR_ABERDEEN: \"Aberdeen\"\n  STR_OSLO: \"Oslo\"\n  STR_JAMAICA: \"Jamaica\"\n  STR_PANAMA: \"Panama\"\n  STR_MIAMI: \"Miami\"\n  STR_PSI_TRAINING: \"M.K.-träning\"\n  STR_PSIONIC_TRAINING: \"TRÄNING I MOLEKULÄR KONTROLL\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Återstående M.K.-kapacitet> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"M.K.{NEWLINE}Styrka\"\n  STR_IN_TRAINING: \"Genomgår{NEWLINE}Träning?\"\n  STR_TARGETTED_BY: \"MÅLINRIKTAD AV:\"\n  STR_WEAPONS_CREW_HWPS: \"VAPEN/{NEWLINE}BESÄTTNING/SWSer\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"har låg bränslenivå,{NEWLINE}återvänder till bas\"\n  STR_SOLDIER_LIST: \"Akvanautlista\"\n  STR_RANK_: \"GRAD> {ALT}{0}\"\n  STR_MISSIONS: \"UPPDRAG> {ALT}{0}\"\n  STR_KILLS: \"DÖDADE> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"SJUKDAGAR> {ALT}{0}\"\n  STR_TIME_UNITS: \"TIDSENHETER\"\n  STR_STAMINA: \"UTHÅLLIGHET\"\n  STR_HEALTH: \"HÄLSA\"\n  STR_BRAVERY: \"MOD\"\n  STR_REACTIONS: \"REAKTIONSFÖRMÅGA\"\n  STR_FIRING_ACCURACY: \"SKYTTEFÖRMÅGA\"\n  STR_THROWING_ACCURACY: \"KASTFÖRMÅGA\"\n  STR_STRENGTH: \"STYRKA\"\n  STR_PSIONIC_STRENGTH: \"M.K.-STYRKA\"\n  STR_PSIONIC_SKILL: \"M.K-FÄRDIGHET\"\n  STR_NEW_RANK: \"NY GRAD\"\n  STR_PROMOTIONS: \"Befordran\"\n  STR_SOLDIERS_UC: \"AKVANAUTER\"\n  STR_COELACANTH_GAS_CANNON_UFOPEDIA: \"Automatiserade SWS har hög manövrerbarhet och skrovstyrka. De ger tungt truppstöd på alla djup. SWS ombeväpnas automatiskt om du har tillräckligt med ammunition.\"\n  STR_COELACANTH_AQUA_JET_UFOPEDIA: \"Denna undervattensfarkost är beväpnad med Aqua-Jet-torpeder. Detta vapensystem fungerar endast under vatten. Se till att lagren är välfyllda med Aqua-Jet-torpeder.\"\n  STR_COELACANTH_GAUSS_UFOPEDIA: \"Gauss-tekniken ger SWS ett kraftfullt vapensystem. Den erbjuder större eldkraft jämfört med tidigare modeller och använder egenutvecklad X-Com-teknik.\"\n  STR_DISPLACER_SONIC_UFOPEDIA: \"Utomjordisk teknik har omdefinierat SWS. Förmågan att använda jonförskjutare innebär att SWS inte längre är begränsade till land/havsbotten. Soniska vapen ger en verklig fördel i strid.\"\n  STR_DISPLACER_PWT_UFOPEDIA: \"Denna SWS har pulsvågvapen för användning i vatten. Du måste tillverka PWT:er för att hålla dem fullt beväpnade. För att avfyra, välj ett antal ”vägpunkter” och klicka sedan på avfyrningsikonen.\"\n  STR_ALIEN_PROBE_MISSION: \"Utomjordiskt sonderingsuppdrag\"\n  STR_ALIEN_INTERDICTION: \"Utomjordiskt förbud\"\n  STR_ALIEN_INFILTRATION: \"Utomjordisk Infiltrering\"\n  STR_ALIEN_RETALIATION: \"Attack mot flytande bas\"\n  STR_ALIEN_SUPPLY: \"Försörjningsuppdrag för kolonier\"\n  STR_ALIEN_PROBE_MISSION_UFOPEDIA: \"Utomjordiska sonderingsuppdrag används för att korrelera data om havsbotten, resurser, sjöfart och flygvägar i ett område. De utomjordiska ubåtar som deltar i dessa uppdrag utgör inte någon större hot i sig, men de indikerar platser där aktivitet kan uppstå när som helst.\"\n  STR_ALIEN_INTERDICTION_UFOPEDIA: \"Utomjordingarna har som princip att övervaka områden som de är intresserade av och skickar ut farkoster med det uttryckliga syftet att säkra ett område innan mer intensiva uppdrag påbörjas. De landar på specifika platser som de avser att plundra senare för att spärra av områdena och förbereda för nästa steg i verksamheten.\"\n  STR_ALIEN_RESOURCE_RAID_UFOPEDIA: \"Att sänka fartyg och skjuta ner flygplan är viktiga delar av utomjordingarnas strategi. Att skaffa material är en av utomjordingarnas huvudsakliga aktiviteter och är därför kopplat till dessa öppet aggressiva handlingar. Utomjordingarna plundrar också områden med geotermisk aktivitet, gruvor och fornlämningar för att få tag på mineraler, raffinerade metaller och andra föremål som tillverkats av människor.\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"Detta kan resultera i officiella kontakter mellan utomjordingar och företag eller regeringar på högsta nivå. Klimaxet för denna aktivitet kännetecknas av intensiv utomjordisk aktivitet i vattnen kring den berörda organisationen. Utomjordingarna kommer att försöka ingå ett avtal med en regering eller organisation genom att erbjuda kunskap om sin överlägsna teknologi. Denna utomjordiska aktivitet utgör ett stort hot mot X-Com. Om ett företag eller en regering samarbetar med inkräktarna upphör dess finansiering.\"\n  STR_ALIEN_BASE_UFOPEDIA: \"Utomjordingarna kommer att bygga hemliga undervattenskolonier på avlägset belägna platser. Efter några inledande rekognoseringsflygningar kommer det att ske intensiv aktivitet från utomjordiska ubåtar medan kolonin byggs. Dessa kolonier är kända för att innehålla laboratorier, kloningscenter och kirurgiska anläggningar för experiment på människor och utomjordingar. Närvaron av utomjordiska kolonier kommer att generera mer utomjordisk aktivitet utan närvaron av utomjordiska ubåtar. För att lokalisera en koloni måste en X-Com-ubåt patrullera ett område i några timmar för att ha någon chans att upptäcka den.\"\n  STR_ALIEN_SURFACE_ATTACK_UFOPEDIA: \"När utomjordingarna behöver människor terroriserar de en hamn, attackerar en ö eller plundrar ett skepp. Civila kommer att hotas direkt för att tillfredsställa utomjordingarnas perversa avelsbehov och deras avskyvärda experiment.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"Om X-Com:s attackubåtar är särskilt framgångsrika i att sänka utomjordiska farkoster kan utomjordingarna vidta aggressiva motåtgärder. Detta kan resultera i en direkt attack mot en X-Com-anläggning. Utomjordingarna måste dock hitta en X-Com-bas för att kunna attackera den, och förutsatt att utomjordiska ubåtar hålls borta bör risken för en attack vara liten.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"När en utomjordisk koloni har byggts upp försörjs den regelbundet av ett särskilt försörjningsfartyg. Om ett av dessa fartyg upptäcks när det landar är det säkert att det finns en utomjordisk koloni i närheten.\"\n  STR_SURVEY_SHIP_UFOPEDIA: \"Denna lilla ubåt används för rekognoscering och kartläggningsuppdrag. Den går normalt före större fartyg i början av en utomjordisk insatsstyrka.\"\n  STR_ESCORT_UFOPEDIA: \"Ett medelstort eskortfartyg som i sig självt utgör ett minimalt hot. Detta fartyg föregår ankomsten av större fartyg och ökad aktivitet.\"\n  STR_CRUISER_UFOPEDIA: \"Kryssaren är ett allmänt fartyg, stöttepelaren i den främmande flottan. Den används i alla typer av främmande uppdrag och är en farlig motståndare.\"\n  STR_HEAVY_CRUISER_UFOPEDIA: \"Den tunga kryssaren är ett kraftfullare fartyg än kryssaren, med större vapen och framdrivningssystem som ökar dess kraft. Den tunga kryssaren används för resursuppdrag för att samla in stora mängder mineraler och utrustning.\"\n  STR_HUNTER_UFOPEDIA: \"Fartyget är utrustat med ett undersökningsrum för att utföra experiment och kirurgiska ingrepp på människor. Offren utsätts för de mest avskyvärda tortyrmetoder och hjärnan avlägsnas ofta och förvaras för bearbetning under resan.\"\n  STR_BATTLESHIP_UFOPEDIA: \"Slagskeppet är det mest aggressiva skeppet som utomjordingarna har. Det är utrustat med all utomjordisk teknik och alla utomjordiska system och fungerar som bas för alla former av aggressiva handlingar som utomjordingarna vill utföra. Det är utrustat med ett brett utbud av vapen.\"\n  STR_DREADNOUGHT_UFOPEDIA: \"Dreadnought är ett supertransportfartyg, fullt utrustat med all utomjordisk teknik och en enorm lastkapacitet. Dreadnought är en tuff och formidabel motståndare.\"\n  STR_FLEET_SUPPLY_CRUISER_UFOPEDIA: \"Försörjningsfartyget används under byggandet av utomjordiska kolonier eller för att försörja befintliga kolonier. Det transporterar utomjordiska näringsämnen, DNA, foster och andra biologiska komponenter.\"\n  STR_DISMANTLE: \"Demontera\"\n  STR_TRANSFER_ITEMS_TO: \"Överför Föremål till {0}\"\n  STR_AMOUNT_AT_DESTINATION: \"ANTAL VID{NEWLINE}DESTINATION\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"Utomjordingen avlider eftersom det inte finns någon anläggning för att hålla utomjordingar isolerade.\"\n  STR_ITEMS_ARRIVING: \"Föremål Ankommer\"\n  STR_DESTINATION_UC: \"DESTINATION\"\n  STR_JET_HARPOON: \"Jetharpun\"\n  STR_HARPOON_POD: \"Harpun\"\n  STR_GAS_CANNON: \"Gaskanon\"\n  STR_SMALL_TORPEDO: \"Liten torped\"\n  STR_LARGE_TORPEDO: \"Stor torped\"\n  STR_PHOSPHOROUS_TORPEDO: \"Fosfortorped\"\n  STR_MAGNA_BLAST_GRENADE: \"Magna-Blast-granat\"\n  STR_DYE_GRENADE: \"Färggranat\"\n  STR_PARTICLE_DISTURBANCE_GRENADE: \"Partikelstörningsgranat\"\n  STR_PARTICLE_DISTURBANCE_SENSOR: \"Partikelstörningssensor\"\n  STR_MEDI_KIT: \"Första-Hjälpen-verktyg\"\n  STR_GAUSS_PISTOL: \"Gauss-pistol\"\n  STR_GAUSS_RIFLE: \"Gauss-gevär\"\n  STR_THERMIC_LANCE: \"Termisk lans\"\n  STR_HEAVY_THERMIC_LANCE: \"Tung termisk lans\"\n  STR_AQUATOID_CORPSE: \"Akvatoid-kropp\"\n  STR_GILLMAN_CORPSE: \"Gälman Kropp\"\n  STR_LOBSTERMAN_CORPSE: \"Hummerman lik\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"Inte tillräckligt med ammunition för att beväpna SWS{SMALLLINE}Varje SWS kräver {0} {1}.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Otillräckligt med materiel för att fullt återbeväpna truppen\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Du måste undersöka {NEWLINE}{0}{NEWLINE}för att kunna tillverka{NEWLINE}{1}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"Utomjordingarna har förstört den oskyddade basen {0}\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"X-Com-patruller har lokaliserat en utomjordisk koloni i {0}.\"\n  STR_STANDOFF: \"DÖDLÄGE\"\n  STR_CAUTIOUS_ATTACK: \"FÖRSIKTIG ATTACK\"\n  STR_STANDARD_ATTACK: \"STANDARDATTACK\"\n  STR_AGGRESSIVE_ATTACK: \"AGGRESSIV ATTACK\"\n  STR_DISENGAGING: \"AVSTÅNDSTAGANDE\"\n  STR_UFO_HIT: \"UTOMJORDISK UBÅT TRÄFFAD!\"\n  STR_UFO_CRASH_LANDS: \"UTOMJORDISK UBÅT SÄNKT!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"MINIMERA VID DÖDLÄGESRÄCKVIDD ENDAST\"\n  STR_UFO_RETURN_FIRE: \"UTOMJORDISK UBÅT SKJUTER TILLBAKA!\"\n  STR_INTERCEPTOR_DAMAGED: \">>> FLYGANDE UBÅT SKADAD <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> FLYGANDE UBÅT FÖRSTÖRD <<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"UTOMJORDISK FLYGANDE UBÅT FLYR!\"\n  STR_LONG_RANGE_DETECTION: \"Bredbandsdetektering\"\n  STR_STORES_UC: \"FÖRRÅD\"\n  STR_DIFFICULTY_LEVEL: \"Svårighetsgrad\"\n  STR_INTERCEPT: \"GENSKJUT\"\n  STR_BASES: \"BASER\"\n  STR_GRAPHS: \"GRAFER\"\n  STR_UFOPAEDIA_UC: \"UFOPAEDIA\"\n  STR_OPTIONS_UC: \"ALTERNATIV\"\n  STR_FUNDING_UC: \"FINANSIERING\"\n  STR_5_SECONDS: \"5 s\"\n  STR_1_MINUTE: \"1 Min\"\n  STR_5_MINUTES: \"5 Minr\"\n  STR_30_MINUTES: \"30 Minr\"\n  STR_1_HOUR: \"1 Timm\"\n  STR_1_DAY: \"1 Dag\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"X-Com Prestationstabell\"\n  STR_ENTER_NAME: \"Skriv Namn\"\n  STR_PERFORMANCE_RATING: \"Framgångsvärdering\"\n  STR_VICTORY_DATE: \"Segerdatum\"\n  STR_CHEMICAL_FLARE: \"Kemisk fackla\"\n  STR_CHEMICAL_FLARE_UFOPEDIA: \"Denna kompakta enhet avger ett starkt ljussken på alla djup och på torra land. Detta belyser fiendens enheter i närheten av ljusskenet under djuphavs- eller nattuppdrag.\"\n  STR_MONTHLY_COSTS: \"Månadskostnader\"\n  STR_SALARIES: \"Löner\"\n  STR_BASE_MAINTENANCE: \"Basunderhåll\"\n  STR_COST_PER_UNIT: \"Kostnad per enhet\"\n  STR_QUANTITY: \"Kvantitet\"\n  STR_TOTAL: \"Total\"\n  STR_FRONT_ARMOR: \"Främre Pansar\"\n  STR_LEFT_ARMOR: \"Vänster Pansar\"\n  STR_RIGHT_ARMOR: \"Höger Pansar\"\n  STR_REAR_ARMOR: \"Bakre Pansar\"\n  STR_UNDER_ARMOR: \"Undre Pansar\"\n  STR_ROUNDS: \"SKOTT\"\n  STR_UNIT: \"ENHET>{0}\"\n  STR_ENERGY: \"ENERGI\"\n  STR_MORALE: \"MORAL\"\n  STR_ARMOR_: \"RUSTNING>{0}\"\n  STR_FRONT_ARMOR_UC: \"FRÄMRE PANSAR\"\n  STR_LEFT_ARMOR_UC: \"VÄNSTER PANSAR\"\n  STR_RIGHT_ARMOR_UC: \"HÖGER PANSAR\"\n  STR_REAR_ARMOR_UC: \"BAKRE PANSAR\"\n  STR_SKILLS: \"FÄRDIGHET> {0}\"\n  STR_LEVEL: \"NIVÅ> {0}\"\n  STR_HEAD: \"HUVUD\"\n  STR_TORSO: \"TORSO\"\n  STR_RIGHT_ARM: \"HÖGER ARM\"\n  STR_LEFT_ARM: \"VÄNSTER ARM\"\n  STR_RIGHT_LEG: \"HÖGER BEN\"\n  STR_LEFT_LEG: \"VÄNSTER BEN\"\n  STR_PAIN_KILLER: \"SMÄRTSTILLANDE\"\n  STR_STIMULANT: \"PSYKOSTIMULANTIA\"\n  STR_HEAL: \"LÄK\"\n  STR_TIME_UNITS_SHORT: \"TE>{ALT}{0}\"\n  STR_WEIGHT: \"Bärvikt>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"Reakt>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Utomjordisk artefakt\"\n  STR_AMMO_ROUNDS_LEFT: \"AMMO:{NEWLINE}SKOTT{NEWLINE}KVAR={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Smärt>{ALT}{0}{ALT}{NEWLINE}Stim>{ALT}{1}{ALT}{NEWLINE}Hela>{ALT}{2}\"\n  STR_THROW: \"Kasta\"\n  STR_AUTO_SHOT: \"Automateld\"\n  STR_SNAP_SHOT: \"Snabbskott\"\n  STR_AIMED_SHOT: \"Välriktat Skott\"\n  STR_STUN: \"Bedöva\"\n  STR_PRIME_GRENADE: \"Förbered granat\"\n  STR_USE_SCANNER: \"Använd avståndssensor\"\n  STR_USE_MEDI_KIT: \"Använd första hjälpen\"\n  STR_LAUNCH_MISSILE: \"Avfyra torped\"\n  STR_ACCURACY_SHORT: \"Trf>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Otillräckligt med TE!\"\n  STR_NOT_ENOUGH_ENERGY: \"Slut på energi!\"\n  STR_NO_ROUNDS_LEFT: \"Inga skott kvar!\"\n  STR_NO_AMMUNITION_LOADED: \"Ingen ammunition laddad!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Fel ammunition för detta vapen!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"Vapnet redan laddat!\"\n  STR_NO_LINE_OF_FIRE: \"Ingen skottlinje!\"\n  STR_GRENADE_IS_ACTIVATED: \"Granat aktiverad!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Granat inaktiverad!\"\n  STR_THERE_IS_NO_ONE_THERE: \"Det finns ingen där!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Omöjligt att använda utomjordiska artefakter innan de undersökts.\"\n  STR_OUT_OF_RANGE: \"Utom räckvidd!\"\n  STR_UNABLE_TO_THROW_HERE: \"Oförmögen att kasta där!\"\n  STR_SET_TIMER: \"Ställ in timer\"\n  STR_HIDDEN_MOVEMENT: \"DOLD FÖRFLYTTNING\"\n  STR_TURN: \"RUNDA> {0}\"\n  STR_SIDE: \"SIDA> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Tryck på knapp för att fortsätta\"\n  STR_MIND_CONTROL: \"Molekulär kontroll\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Moral Attack Framgångsrik\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}går bärsärkargång\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}går bärsärkargång\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}grips av panik\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}grips av panik\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Utomjordingar\"\n  STR_RIGHT_HAND: \"HÖGER HAND\"\n  STR_LEFT_HAND: \"VÄNSTER HAND\"\n  STR_RIGHT_SHOULDER: \"HÖGER AXEL\"\n  STR_LEFT_SHOULDER: \"VÄNSTER AXEL\"\n  STR_BACK_PACK: \"RYGGSÄCK\"\n  STR_BELT: \"BÄLTE\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}är under molekulär kontroll\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}är under molekulär kontroll\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}är medvetslös\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}är medvetslös\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}har avlidit från en dödlig skada\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}har avlidit från en dödlig skada\"\n  STR_FATAL_WOUNDS: \"DÖDLIGA SÅR\"\n  STR_UNDER_ARMOR_UC: \"UNDRE PANSAR\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"TE reserverade för snabbskott\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"TE reserverade för automateld\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"TE reserverade för välriktat skott\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"TE reserverade för knäställning\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"TE reserverade för knäställning och eld\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} enhet i X-Com-farkost\"\n    other: \"{N} enheter i X-Com-farkost\"\n  STR_UNITS_OUTSIDE:\n    one: \"{N} enhet kvar utanför\"\n    other: \"{N} enheter kvar utanför\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} enhet vid ingången\"\n    other: \"{N} enheter vid ingången\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} enhet vid målets utgång\"\n    other: \"{N} enheter vid målets utgång\"\n  STR_ABORT_MISSION_QUESTION: \"Överge Uppdrag?\"\n  STR_CORPSE: \"Kropp\"\n  STR_UNLOAD_CRAFT: \"Ladda ur\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}har avlidit\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}har avlidit\"\n  STR_HIT_MELEE: \"Träffa\"\n  STR_GROUND: \"MARK\"\n  STR_LIVING_QUARTERS_PLURAL: \"Logement\"\n  STR_LIST_ITEM: \"FÖREMÅL\"\n  STR_RESET: \"Återställ\"\n  STR_MEMORIAL: \"Minnesmärke\"\n  STR_DATE_UC: \"DATUM\"\n  STR_SOLDIERS_RECRUITED_UC: \"AKVANAUTER REKRYTERADE>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"AKVANAUTER FÖRLORADE>{ALT}{0}\"\n  STR_REMOVE_SELECTED: \"Ta bort markerade\"\n  STR_LIVE_ALIENS: \"Levande{NEWLINE}varelser\"\n  STR_DEAD_ALIENS: \"Avvisade{NEWLINE}varelser\"\n  STR_UNDER_INTERROGATION: \"Blir{NEWLINE}undersökta\"\n  STR_CONTAINMENT_EXCEEDED: \"UTOMJORDINGFÖRVARINGS GRÄNSVÄRDE ÖVERSKRIDEN!{SMALLLINE}Otillräcklig förvaringskapacitet i {0}. Du måste välja ut överskridande utomjordingar från förvaringen (Som sedermera avlider).\"\n  STR_MANAGE_CONTAINMENT: \"Hantera utomjordingsförvaring\"\n  STR_STORAGE_EXCEEDED: \"LAGERUTRYMME SLUT!{SMALLLINE}Otillräckligt lagerutrymme i {0}. Du måste sälja överskridande föremål.\"\n  STR_GO_TO_BASE: \"Gå till bas\"\n  STR_MELEE_ACCURACY: \"TRÄFFSÄKERHET FÖR NÄRKAMP\"\n  STR_SELL_PRODUCTION: \"SÄLJ\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Båda händerna måste vara tomma!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Otillräckligt med föremål för att kopiera mall!\"\n  STR_UNLOAD_WEAPON: \"Ladda ur vapen\"\n  STR_ALL_ITEMS: \"Alla föremål\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}KONTROLLCENTER FÖRSTÖRT{NEWLINE}Ta dig till entrén och avbryt.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"X-Com:s akvaanläggningar kan inte byggas på land\"\n  STR_UNDERWATER_EQUIPMENT: \"Denna utrustning fungerar inte ovanför vattenytan!\"\n  STR_LAND_EQUIPMENT: \"Denna utrustning fungerar inte under vattenytan!\"\n  STR_LEVEL_SHORT: \"L{0}\"\n  STR_PERSONNEL: \"Personal\"\n  STR_CRAFT_ARMAMENT: \"Farkost & Bestyckning\"\n  STR_COMPONENTS: \"Komponenter\"\n  STR_SOLDIERS_RECRUITED: \"Akvanauter rekryterade\"\n  STR_SOLDIERS_LOST: \"Akvanauter förlorade\"\n  STR_TOTAL_UFOS: \"Flygande ubåtar upptäcktes\"\n  STR_TOTAL_ALIEN_BASES: \"Utomjordiska kolonier upptäcktes\"\n  FEMALE_CIVILIAN: \"Civilist, Kvinna\"\n  MALE_CIVILIAN: \"Civilist, Man\"\n  DOCKER_CIVILIAN: \"Civil, hamnarbetare\"\n  SAILOR_CIVILIAN: \"Civil, sjöman\"\n  ZOMBIE_WEAPON: \"Zombie Vapen\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/tr.yml",
    "content": "tr:\n  STR_LEVIATHAN_UFOPEDIA: \"AŞIRI DERİNLİK KABİLİYETİ OLAN BİR İNTİKAL VE AVCI UÇARBOTU. İYON İTME SİSTEMLERİ VE MANYETİK SEYRÜSEFER MODÜLÜYLE, YABANCI VE İNSAN TEKNOLOJİLERİNİN MUHTEŞEM BİR SENTEZİ.\"\n  STR_BARRACUDA_UFOPEDIA: \"KIZGIN LAZER TAHRİKLİ MOTORLARLA DONATILMIŞ İNGİLİZ YAPIMI BARAKÜDA. DÜNYADAKİ EN HIZLI AVCI ARAÇLARI ARASINDA. SUALTI VE ATMOSFERİK UÇUŞ YETENEĞİ SAYESİNDE ANAHTAR KONUMUNDA BİR ARAÇ.\"\n  STR_HAMMERHEAD_UFOPEDIA: \"İNTİKAL VE AVCI ARACI. MANYETİK DİZE SİSTEMLERİNİN BİR X-COM GEMİSİNDE İLK KULLANIMI. KÜÇÜK BOYUTLARINA KARŞIN, TASARIMIYLA NEFES KESİCİ BİR TEKNİK BAŞARI.\"\n  STR_TRITON_UFOPEDIA: \"TRİTON, ATMOSFERİK VE SUALTI UÇUŞ MOTORLARIYLA DONATILMIŞ BİR TAARRUZ İNTİKAL ARACI. BÜYÜK HACMİ VE DAYANIKLI YAPISIYLA, X-COM DONANMASININ ÖNCÜSÜ.\"\n  STR_MANTA_UFOPEDIA: \"YÜKSEK HIZLI MANTA, İYON MOTORLU YABANCI GEMİLERİNİ ANDIRAN TEK KİŞİLİK BİR AVCI DENİZALTISI. KIZIŞAN ÇATIŞMALARDA OLDUKÇA ETKİLİ BİR SALDIRI ARACI.\"\n  STR_AJAX_UFOPEDIA: \"DÜNYA ÇAPINDA SUALTI SAVAŞLARININ STANDART SİLAHI AJAX TORPİDOSU. İSABETLİLİĞİ VE KUVVETİ SAYESİNDE CAYDIRICI BİR ETKEN.\"\n  STR_DUP_HEAD_UFOPEDIA: \"SEYRELTİLMİŞ URANYUM TANECİĞİ HARP BAŞLIĞI TEKNOLOJİSİNİN BİR SUALTI SİLAH SİSTEMİNDE İLK TİCARİ KULLANIMI.\"\n  STR_CRAFT_GAS_CANNON_UFOPEDIA: \"BASINÇLI GAZ GÜCÜYLE ÇELİK ZIPKINLAR FIRLATAN, YÜKSEK ZIRH DELİCİ KABİLİYETİNE SAHİP BİR TOP SİSTEMİ.\"\n  STR_PWT_CANNON_UFOPEDIA: \"KIZGIN YAKIT SİSTEMİ VE SON DERECE YOĞUNLAŞTIRILMIŞ BİR HARP BAŞLIĞI TAŞIYAN DARBE DALGA TORPİDOSU, BİLİNEN ALAŞIMLARIN ÇOĞUNU PARÇALAYABİLECEK GÜÇTE.\"\n  STR_GAUSS_CANNON_UFOPEDIA: \"GAUS SİLAH SİSTEMLERİ, YENİ GELİŞTİRİLMİŞ BİR X-COM TEKNOLOJİSİ. BU SİSTEMİN PARÇACIK HIZLANDIRICISI, GÜCÜNÜ SIVI NİTROJEN SOĞUTMALI KÜÇÜK BİR FÜZYON REAKTÖRÜNDEN ALIYOR.\"\n  STR_SONIC_OSCILLATOR_UFOPEDIA: \"SONİK GÜÇ DALGALARI ÜRETEN KUVVETLİ BİR SES OSİLATÖRÜ. HEDEFİNİN MOLEKÜLER BAĞLARINI KOPARTARAK PARÇALAYABİLECEK GÜÇTE TİTREŞİMLER OLUŞTURABİLİYOR.\"\n  STR_AQUATOID_UFOPEDIA: \"Akuatoid ırkı, daha insanlar dünya yüzeyinde ilk adımlarını atmaya başlarken bile binlerce yıldır varlıklarını sürdürmekte olan kadim bir topluluk. Küçük boyları ve yuvarlak hatları, uzay gezgini kuzenleri Sektoidleri andırıyor. Moleküler Kontrol teknolojisi, en büyük güçleri. Akuatoid ırkının başlıca hedefi, kısır olan soylarını genetik müdahalelerle yaygınlaştırmak. Bu yolda insanları ideal birer denek olarak görüyor ve sayısız melez ırkın oluşumunda rol oynuyorlar.\"\n  STR_AQUATOID_AUTOPSY: \"Akuatoid otopsisi\"\n  STR_AQUATOID_AUTOPSY_UFOPEDIA: \"Yaratığın detaylı bir analizi, bazı temel varsayımlarda bulunmamızı sağlıyor. Bu canlıların kökeni, önceki düşmanlarımız olan Sektoidler, ancak cerrahi müdahaleler ve implantlar sayesinde sualtı yaşamına uygun hale getirilmişler. Körelmiş ciğerleri, su dışında nefes almalarına ve yüzeyde kısıtlı hareket kabiliyetine sahip olmalarına yetiyor. Atrofiye uğramış uzuvlarını ve organlarını desteklemek için tüm bedenleri sibernetik implantlarla donatılmış. Irkın tüm üyeleri özdeş olduğundan, bu yaratıkların klonlanmış olduğunu tahmin ediyoruz.\"\n  STR_GILLMAN_UFOPEDIA: \"İnsan ırkıyla çok yakın akraba olduğu anlaşılan ve sürüngen özellikleri taşıyan tuhaf bir yaratık. Sualtı dünyasında son derece güçlü ve hızlı hareket edebiliyor. Farklı yaşlarda hem erkek hem de dişi örneklerle karşılaşmamız, tam anlamıyla gelişkin bir ırka mensup oldukları anlamına geliyor. Sualtı yabancılarının büyük çoğunluğunun aksine bu canlılar genetik müdahale ya da cerrahi deformasyon izleri taşımıyorlar. Kendi türümüzden çok uzun zaman önce ayrılarak farklı biçimde evrimleşmiş bir ırk oldukları bile düşünülebilir.\"\n  STR_GILLMAN_AUTOPSY: \"Solungaçadam otopsisi\"\n  STR_GILLMAN_AUTOPSY_UFOPEDIA: \"Otopsi sonucunda bu yaratığın bir uzaylı değil, tarih öncesi çağlarda ortaya çıkmış bir Dünya canlısı olduğu apaçık görülebiliyor. Dünyaya dinozorların hakim olduğu dönemden kalan bu güçlü amfibik canlıların, memelilerin egemenliği üstün gelmeye başladığında yeryüzünden silinmiş olmaları beklenirdi. Gezegende sürüngen hakimiyetini sonlandıran büyük felaketle birlikte, uzaydan gelen yabancılarla bir ortakyaşarlık durumuna zorlanmış olabilirler. Yaratıkların kafatasına küçük, elektronik bir cihaz yerleştirilmiş.\"\n  STR_LOBSTERMAN_UFOPEDIA: \"Denizden gelen bu iblis, insandan daha uzun boylu ve altı uzvu olan muazzam bir yaratık. Dünya ıstakozuna olan benzerliği nedeniyle X-Com askerleri arasında Istakozadam lakabıyla anılıyor. Kıskaçlarıyla çeliği bile parçalayabilecek kuvvete ve inanılmaz bir dayanıklılığa sahip bu yaratık, adeta özenle tasarlanmış bir savaş makinesi.\"\n  STR_LOBSTERMAN_AUTOPSY: \"Istakozadam otopsisi\"\n  STR_LOBSTERMAN_AUTOPSY_UFOPEDIA: \"Yaratığın son derece dayanıklı kabuğunun altında hayret verici bir yapı mevcut. Titanyum bir iskeletin etrafında kuvvetli kaslara ve doğrudan beyinle entegre çalışan gelişmiş bir hedefleme sistemine sahip. Çoklu gözleri, çelikten daha güçlü plastik bir mahfaza tarafından korunuyor. Efendileri tarafından doğru yönlendirildiklerinde bu yaratıkların neredeyse durdurulamaz bir güç oldukları anlaşılıyor. Bedenlerinde, yapısı ve işlevi bilinmeyen pek çok cihaz gömülü.\"\n  STR_TASOTH_UFOPEDIA: \"Bu atik ve hızlı yaratıklar, yabancı ordusunun ana unsuru. Yabancı kolonilerinin derinliklerindeki kuluçka makinelerinde yüzlercesi gözlerini açıyor. Bir insandan çok daha güçlü olan Tasot, katıksız bir yabancı ırkı. Davranışları ve etobur doğasıyla gezegende emsali bulunmayan bir tür. Tasot sıklıkla yabancı taarruzlarının en ön saflarında görev alıyor ve ümitsiz koşullar karşısında bile çarpışmaktan kaçınmıyor.\"\n  STR_TASOTH_AUTOPSY: \"Tasot otopsisi\"\n  STR_TASOTH_AUTOPSY_UFOPEDIA: \"Diseksiyon sonucunda, tuhaf bir güç tarafından kontrol edilen sibernetik bir organizma gün ışığına çıkıyor. Vücut boşluğu içinde tanınabilir bir organ yok ama küçük bir enerji kaynağı mevcut. Üretilen enerji, bir biyo-elektrik iletim sistemiyle tüm vücuda yayılıyor. Yaratığın vücudunda, iskelet ya da benzeri bir destekleyici yapı da bulunmuyor. Yaratık hayatını kaybettiğinde enerji dağılımı duruyor ve bedeni, içinden sıvılar sızan cansız bir bez bebek gibi yığılıp kalıyor. Tespit edilebilen tek diğer iç yapı, enerjiyle uyarıldığında yaratığı geçici olarak canlandıran bir çift seramik hücre.\"\n  STR_DEEP_ONE_UFOPEDIA: \"Diptengelen adını verdiğimiz biyolojik kabus, Akuatoid'lerin akıl almaz deneyler sonucunda ürettikleri melez bir tür. Bu yaratığın bir kaç varyasyonuyla karşılaştık. Uzun araştırmalar sonucunda istilacıların ele geçirdikleri insan bedenlerini kullanarak bu canlıları imal ettikleri sonucuna vardık. Bu insan altı yaratıkların her biri, akuanotlarımızı öldürmeye yetecek kadar güçlü bir elektrik yüküyle donatılıyor.\"\n  STR_DEEP_ONE_AUTOPSY: \"Diptengelen otopsisi\"\n  STR_DEEP_ONE_AUTOPSY_UFOPEDIA: \"Bu yaratık, insan ve yabancı organizmalarının çapraz aşılanmasıyla oluşturulmuş. Taşıdığı insan beynine, elektronik kumanda devrelerini ve yabancı korteksini entegre etmek için büyük müdahalelerde bulunulmuş. İnsan bedenine cerrahi yöntemle aşılanan yabancı fetüsün, büyüdükçe taşıyıcısını sarmalayıp yuttuğu bir sürecin izleri görülüyor. Yaratığın son derece kuvvetli ve esnek derisi, organik olmayan metalik bir doku gibi görünüyor. Bu melez canlı hem güçlü, hem hızlı, hem de yabancıların tam kontrolü altında.\"\n  STR_BIODRONE_UFOPEDIA: \"Biyodron, ancak yabancı bir zihnin tasarlayabileceği bir yaratık. Su altında ya da karada hareket edebilen bir modüle monte edilmiş bir fanusta, amniyotik sıvılar içinde yüzen bir beyinden (insan ya da yabancı) müteşekkil. Her bir biyodron, yarı mekanik yarı organik bir sonik parçalayıcı ile donatılmış. Bilim insanlarımızın bir kısmı, bu cihazın aktif kısmının, orijinal organizmanın ses telleri ile güçlendirildiğini düşünüyor. Son derece isabetli ve inatçı bu bekçi köpekleri, yabancılar tarafından kıymetli varlıkların korunmasında kullanılıyorlar.\"\n  STR_BIODRONE_AUTOPSY: \"Biyodron otopsisi\"\n  STR_BIODRONE_AUTOPSY_UFOPEDIA: \"Sonik parçalayıcının biyolojik bir cihaz olduğu tezi doğrulandı. Bu bahtsız yaratık, gerçekten de düşmanını kendi çığlıklarıyla öldürüyor. Karşılaştığımız her bir örnekte ileri derecede cerrahi travma ve sakatlık gözlemledik. Görünüşe göre yabancılar, beyinleri itaate zorlamak için kasap gibi biçiyorlar. Yaratıkların üretiminde kullanılan kortekslerin çoğunun kökeni yabancı, ancak insan tabanlı ünitelerle de karşılaşmış olmanın dehşeti hiç bir şeyle ölçülemez. Biyodronlar, bir iyon motoruyla güçlendirilmiş ve bir tür uzaktan kontrol sistemiyle yönetiliyorlar.\"\n  STR_TENTACULAT_UFOPEDIA: \"Bu tanımlanamaz yaratığı, Lovecraft'in en karanlık kabusları bile doğurmuş olamazdı. Dünyadaki canlıların hiç biriyle kıyas edilemeyen bu organizmaya ev sahipliği yapan ortamı hayal bile edemiyoruz. Tentakülat, uzun duyargalarıyla kavradığı kurbanını önce felç ediyor, sonra da akılsız yaratıklara dönüştürüyor. Bu yeni yaratıkların tek bir dokunuşu, en kalın zırhın üzerinden bile anında ölüme yol açabiliyor. Tentakülat, şu ana kadar X-Com'un karşılaştığı en dehşet verici yabancı ırkı.\"\n  STR_TENTACULAT_AUTOPSY: \"Tentakülat otopsisi\"\n  STR_TENTACULAT_AUTOPSY_UFOPEDIA: \"Otopsi sonucunda, yaratığın büyük beynine gömülü sibernetik implantlar tespit ettik. Yaratık, optik görüş ve termal imaj oluşturma özelliklerini bir araya getiren komplike bir görüş sistemine sahip. Bu canavar, okyanusun karanlık derinliklerinde bile yolunu hatasız biçimde bulabiliyor. Bazı organları, hayatta kalmak için gerekli asgari noktaya kadar körelmiş durumda. Her bir yaratığın, dış bir konnektöre bağlı küçük bir midesi olduğundan, efendileri tarafından besin maddeleriyle doğrudan beslendiklerini varsaymak mümkün.\"\n  STR_CALCINITE_UFOPEDIA: \"Bu yaratıklar, kayıp denizcilerin dalgıç kıyafetleri içinde, gafil avlayacakları kurbanlar arıyorlar. Yaratıkların çelikten daha güçlü pençeleri, en iyi dalgıçları bile dibe gömmeye yetecek kuvvette. Dalgıç maskelerinin vizöründen, içeride kıpırdaşan yeşil ve jelatinimsi bir form görülebiliyor. Kıyafetin altındaki yaratığın gerçek şekli daha fazla anlaşılmıyor.\"\n  STR_CALCINITE_AUTOPSY: \"Kalsinit otopsisi\"\n  STR_CALCINITE_AUTOPSY_UFOPEDIA: \"Kalsinit, zırhlı kıyafetinin altında aslında kocaman, şekilsiz bir protoplazma yığını. Görünürde beyni, uzuvları ya da duyu organlarını teşkil eden belirgin bir yapı yok. Akışkan bedenin derinliklerinde gömülü küçük metal bir bileşene rastlanıyor. Yaratığın cansız bedeni üzerinde yapılan incelemelerden net sonuç almak neredeyse imkansız. Bu yabancı düşman, çözümsüz bir bilmeceye benziyor.\"\n  STR_TRISCENE_UFOPEDIA: \"Bu iki ayaklı sürüngenin kökeni, dinozorlar çağına kadar uzanıyor. Hem suda hem de karada hayatta kalma yeteneği hariç tüm özellikleri, yaratığın Kretase dönemine ait olduğunu gösteriyor. Sırtlarına silah yuvaları yüklenmiş ve çeneleri kocaman metal dişlerle donatılmış. Bu yaratıkların çoğu zaman yabancıların kara saldırılarında taarruz gücünün merkezinde rol aldığını görüyoruz. Ağır sıklet bu yaratıklar, Tasot kumandanları tarafından ölümcül birer silah olarak görevlendiriliyorlar.\"\n  STR_TRISCENE_AUTOPSY: \"Trisen otopsisi\"\n  STR_TRISCENE_AUTOPSY_UFOPEDIA: \"Bıçak altında, Trisen'in gerçekten kadim bir yaratık olduğu ve sibernetik implantlar ve silah sistemleriyle daha da güçlendirilmiş bulunduğu anlaşılıyor. Tüm yaratıklara giydirlen uzaktan kumanda kemerinin içinde, ufacık beynini destekleyen küçük bir bilgisayar modülü mevcut. Derisinin doğal dayanıklığı ve ilave silahlarla daha da keskinleştirilmiş avcı içgüdüleri sayesinde bu yaratık, her tür çevresel koşulda ölümcül bir tehdit oluşturuyor.\"\n  STR_HALLUCINOID_UFOPEDIA: \"Yabancılar, okyanusun derinliklerinden topladıkları bu devasa Dünya canlılarını birer silah olarak yetiştirmişler. İlk bakışta zararsız görünen bu yüzücülerle karşılaştığınızda güvende olduğunuz yanılgısına düşmeyin. Yakın dövüşte kullandığı dondurucu bir saldırıya sahip Halüsinoid, gerçekte ölümcül bir düşman.\"\n  STR_HALLUCINOID_AUTOPSY: \"Halüsinoid otopsisi\"\n  STR_HALLUCINOID_AUTOPSY_UFOPEDIA: \"Jelatinimsi organızmasının kat kat dokularının altında, yaratığın asıl saldırı yeteneğini teşkil eden kuvvetli bir kimyasal dondurucu saklı. Halüsinoid'in yumuşak ve esnek derisi, yüksek sıcaklığa karşı dayanıklı değil. Bu mutant, genellikle efendileri olan Akuatoid'lerle birlikte görülüyor.\"\n  STR_XARQUID_UFOPEDIA: \"Dünya kökenli başkalaştırılmış bir omurgasız canlı olan Zarkid, hem güzellik hem de tehlike timsali. Hızlı bir yüzücü olan bu dev, boğucu bir tür mürekkep ve iyonlaştırılmış parçacık püskürtme yeteneğiyle gizli ve ölümcül bir silah gibi. Bu yaratıklarla ilk karşılaştığımızdan bu yana güçlerine ve efendileri olan Solungaçadamlara temkinle yaklaşıyoruz.\"\n  STR_XARQUID_AUTOPSY: \"Zarkid otopsisi\"\n  STR_XARQUID_AUTOPSY_UFOPEDIA: \"Bu aşırı gelişmiş kabuklu, Yabancıların tıbbi ve cerrahi müdahaleleri sonucunda bu büyüklüğe ulaşmış. Solungaçadamların eklediği mekanik kontrol sistemleri yüzünden, yaratığın doğal yapısından geriye hiç bir iz kalmamış. Organik bir silah platformu olarak cepheye sürülen Zarkidler, kalın kabukları ve yüksek hareket kabiliyetleriyle müthiş birer hasım.\"\n  STR_ION_BEAM_ACCELERATORS_UFOPEDIA: \"Yabancı uçar denizaltıları, derinliklerde müthiş hızlara ulaşmalarını sağlayan karmaşık enerji sistemleriyle donatılmış. Teknolojilerinin temelinde, katalizatör olarak Zerbit kullanan İyon Deplasörleri yatıyor. Bunlar, saniyede kendi hacimlerinin 100 katı sıvıyı itebilecek güçte cihazlar. Bu muazzam güç sayesinde yabancılar, hemen hemen tüm Dünya botlarını geride bırakacak hıza ulaşabiliyorlar. Akua-plastikler ve Zerbit enerji hücreleri kullanarak benzer bir itme sistemini biz de üretebiliriz.\"\n  STR_MAGNETIC_NAVIGATION_UFOPEDIA: \"Bu cihazlar, botun etrafında 1000 metreye kadar ulaşabilen çok katlı, küresel bir manyetik alan üretirler. Yabancı seyrüsefer görevlileri, doğrudan makinelere bağlanır ve dalgaların arasındaki göze görünmez dünyayı hissederek araçlarını yönetirler. Başkalaştırılmış beyin dokularından üretilmiş olan arabirim, operatörün beyniyle doğrudan bir sinirsel bağlantı kurabilecek şekilde tasarlanmıştır.\"\n  STR_ALIEN_SUB_CONSTRUCTION_UFOPEDIA: \"Her bir araç, deniz canlılarına benzetilerek, bukalemun gibi bir yapıyla tasarlanmış ve Akua-plastikler kullanılarak üretilmiş. Denizaltı ve mürettebatı, aynı organizmanın parçaları gibi birbirleriyle uyum içinde işlev görüyor. Kullanılan sistemlerin çoğunu kopyalamamız ve eşdeğer seviyede melez bir teknoloji geliştirmemiz mümkün.\"\n  STR_ALIEN_CRYOGENICS_UFOPEDIA: \"Dünyada gizlenen sayısız Yabancı, kriyojenik yolla dondurularak kış uykusunda muhafaza edilmişler. Yaratıklar, bu cihazların içine kapatıldıktan sonra vücut sıcaklıkları, neredeyse tüm bedensel faaliyetlerin durduğu bir noktaya kadar düşürülmüş. Cihazlar üzerindeki ilk incelemeler sonucunda inanılmaz bulgular elde ettik: bu canlıların 60 milyon yılı aşkın süredir uykuda oldukları anlaşılıyor.\"\n  STR_ALIEN_CLONING_UFOPEDIA: \"Ele geçirdiğimiz Yabancıların çoğunun, DNA'larına kadar özdeş olduklarını görüyoruz. Yabancıların klonlanması için hücre örneklerinin dondurularak gen bankalarında muhafaza edildiği anlaşılıyor. Bazı klonlama ünitelerinin insan bedenleri ya da organları içerdiği dikkat çekiyor. Bu klonlama cihazlarının bir diğer işlevinin de Yabancı-İnsan melezi yeni türler üretmek olduğundan şüpheleniyoruz.\"\n  STR_ALIEN_LEARNING_ARRAYS_UFOPEDIA: \"Yabancıların tümünün kafatasında bulunan Moleküler Kontrol implantlarıyla haberleşen bu makineler, her türlü bilgiyi doğrudan yaratıkların beynine enjekte etmekte kullanılıyor. Yeni klonlanmış tüm yabancılar bu cihazlara bağlanarak hem ırksal bellekleri oluşturuluyor, hem de boş zihinlerine tüm bilimsel ve muharebe bilgileri yükleniyor.\"\n  STR_ALIEN_IMPLANTER_UFOPEDIA: \"Bu makineler, Yabancıların kafatasına Moleküler Kontrol implantları yerleştirmek, eşeyli üreyen ırkları döllemek, vücuttan bazı organları kesip çıkartmak ve her tür canlı bedenine elektronik cihazlar eklemek için kullanılıyor. İlk başlarda bu cerrahi süreçlerin anestezi altında yürütüldüğü sanılıyordu ancak artık deneklerin tüm süreç boyunca bilinçlerinin açık olduğu anlaşılıyor. Asıl korkutucu olan, bu makinelerin insan anatomisine mükemmel uygunluğu.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"Yabancıların insanları gerçekte neden kaçırdığını açıklayan ipuçları elde ettik. Kaçırılan insanlar yiyecek olarak ya da Yabancı embriyolarıyla döllenmek için değil, çeşit çeşit yaratıkların ve kontrol sistemlerinin üretiminde hammadde olarak kullanılıyorlar. Yabancı teknolojisi, ortak bir zihin ve akıl üzerine kurulmuş sistemlerden oluşuyor ve insan beyni, bu sistemlerle en uyumlu alıcı niteliğinde. Beyin dokuları, Yabancıların biyolojik bilgisayar sistemlerinin hemen hepsinde kullanılıyor. Diğer dokular da üretim ve üreme süreçlerinde değerlendiriliyor.\"\n  STR_AQUA_PLASTICS_UFOPEDIA: \"Yabancı denizaltıları inanılmaz derecede güçlü, esnek ve dayanıklı bir malzemeden üretiliyorlar. Akua plastik adındaki bu materyal, katalizör olarak Zerbit kullanılan bir süreçle üretiliyor ve karmaşık  bir yapıya sahip. Hem yoğun hem de hafif olan bu maddenin dayanıklılığı, titanyum ve kevlar içeren materyalleri bile geride bırakıyor.\"\n  STR_ZRBITE_UFOPEDIA: \"Kısmen altın, kısmen de Yabancı biyo-materyal içeren bir alaşım. Enerji kaynağı olarak kullanıldığında, aynı ağırlıktaki nükleer maddelerden 10 kat daha fazla güç elde edilmesine olanak sağlıyor. Ne yazık ki elimizdeki teknik imkanlar, yapıtaşlarından pek çoğu Yabancı kökenli olan bu alaşımı üretebilmek için yeterli değil.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"Yabancılar, acımasız saldırılarını tüm yerküre sathında sürdürüyorlar ve merkez üslerini tespit edemiyoruz. Ulaşabileceğimizden çok daha derin denizlerden geliyor olabilirler mi? Karşılaştığımız canlıların bazıları gerçek anlamda Yabancı bile değil. Soyunun çoktan tükendiğini sandığımız dünya türlerinin neslinden gelen yaratıklarla da çarpışıyoruz. Binlerce yıldır dünyamızda uyumakta olan, insan ve Yabancı ırklarının karmaşık bir sembiyozuyla karşı karşıyayız. Okyanusların derinliklerinde, Yabancıların uzaylı akrabalarıyla temas kurmakta kullandıkları kadim üsler olduğunu öğrendik. Bu oniki üssün her birinde, Yabancı teknolojisinin güçlü birer örneği olan Sinomiyum cihazları bulunuyor. Dünyadaki savaş çarklarının yeniden dönmesiyle birlikte Yabancılar, Moleküler Kontrol ağlarını genişletmek için bu üsleri tekrar aktifleştirmeye çalışıyorlar. Her ne pahasına olursa olsun bu üsleri yok etmeliyiz.\"\n  STR_THE_ULTIMATE_THREAT_UFOPEDIA: \"Altmış beş milyon yıl önce dev bir koloni gemisi, uzak bir Yabancı gezegeninden dünyamıza gönderilmişti. Muazzam gemi bu genç gezegene yaklaşırken, büyük ve şiddetli bir güneş patlaması seyrüsefer sistemlerinin arıza yapmasına neden oldu. Sakatlanmış uzay aracı çaresizce tarih öncesi atmosfere doğru düşüşe geçtiğinde, dünyadaki sayısız ırk, gökyüzünden gelen kıyametlerini görebilmek için başını kaldırdı. Çarpışma sonrasında korkunç bir toz bulutu atmosferi kapladı ve gezegendeki egemen yaşam formu olan muazzam dinozorların sonu geldi. Ancak çarpışma, T'leth uzay aracının 400 milyar tonluk cüssesini yok etmeye yetmedi. Gelişmiş süper bilgisayarlar, aracın koynundaki binlerce yaratığı uzun ve derin bir uykuya yatırdı. Bilgisayarlar, çağlar boyunca zaman zaman uzaylı akrabalarıyla iletişim kurmayı denemeleri için yaratıkların bazılarını uyandırdı, ancak Yabancı gücünün çekirdeği uykuda olduğundan bu çabalar sonuçsuz kaldı.\"\n  STR_TLETH_THE_ALIEN_CITY: \"Yabancılar Şehri T'leth\"\n  STR_TLETH_THE_ALIEN_CITY_UFOPEDIA: \"Devasa Yabancı koloni gemisi T'leth, Meksika Körfezindeki Sigsbee Çukurluğunun dibindee gömülü. Şehrin kalbinde ise, ölümün bile sahiplenemeyeceği kadar korkunç ve güçlü bir Yabancı dehşeti gizlenmekte. Metalden yapılmış bir kraliyet odasında, baş Yabancı Ulu Uyuyan'ın bedeni yatıyor. T'leth su yüzüne çıkacak olursa, bu yaratık da uzun uykusundan uyanacak ve artık onu hiç bir kuvvet durduramayacak. Tam anlamıyla canlı olmamasına rağmen, bu yaratığın zihni tüm Yabancı ordusuna komuta ediyor. Moleküler Kontrol teknolojisi, tüm diğer Yabancılar ve Tek zihin arasında bağlantı sağlıyor. Genetiği değiştirilmiş Yabancı/insan fetüsleri de hükümdar ve tebası arasındaki bağlantıyı besleyen enerjiyi üretiyorlar. Yüzlerce yıldır insanlığın bilinç altında yer etmiş olan Baş Yabancı mitosu hakkındaki gerçekliğin, en başından beri denizler altında gizlendiğini anlamış bulunuyoruz.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"MEVKİYE ODAKLAN-SÜRE=5 Sn.\"\n  STR_CANCEL_UC: \"İPTAL\"\n  STR_NONE: \"Yok\"\n  STR_UNKNOWN: \"Bilinmiyor\"\n  STR_POOR: \"Zayıf\"\n  STR_AVERAGE: \"Ortalama\"\n  STR_GOOD: \"İyi\"\n  STR_EXCELLENT: \"Mükemmel\"\n  STR_BUILD_NEW_BASE_UC: \"YENİ ÜS KUR\"\n  STR_BASE_INFORMATION: \"ÜS BİLGİLERİ\"\n  STR_EQUIP_CRAFT: \"DENİZALTI DONATIM\"\n  STR_BUILD_FACILITIES: \"TESİS İNŞA ET\"\n  STR_RESEARCH: \"ARAŞTIRMA\"\n  STR_MANUFACTURE: \"ÜRETİM\"\n  STR_TRANSFER_UC: \"TRANSFER\"\n  STR_PURCHASE_RECRUIT: \"SATIN AL/İŞE AL\"\n  STR_SACK: \"KOV\"\n  STR_SELL_SACK_UC: \"SAT/KOV\"\n  STR_GEOSCAPE_UC: \"YERKÜRE\"\n  STR_NAME: \"İsim\"\n  STR_AREA: \"Bölge\"\n  STR_BUILD_NEW_BASE: \"Yeni Üs İnşa Et\"\n  STR_CANCEL: \"İptal\"\n  STR_COST_UC: \"MALİYET>\"\n  STR_CONSTRUCTION_TIME_UC: \"İNŞAAT SÜRESİ>\"\n  STR_DAY:\n    one: \"{N} gün\"\n    other: \"{N} gün\"\n  STR_HOUR:\n    one: \"{N} saat\"\n    other: \"{N} saat\"\n  STR_MAINTENANCE_UC: \"BAKIM>\"\n  STR_OK: \"TAMAM\"\n  STR_INSTALLATION: \"Tesisler\"\n  STR_CURRENT_RESEARCH: \"MEVCUT ARAŞTIRMA\"\n  STR_SCIENTISTS_AVAILABLE: \"Toplam Araştırma Personeli>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Görevli Araştırma Personeli>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Mevcut Laboratuvar Alanı>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"ARAŞTIRMA PROJESİ\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"GÖREVLİ PERSONEL\"\n  STR_PROGRESS: \"GİDİŞAT\"\n  STR_NEW_PROJECT: \"Yeni Proje\"\n  STR_CANCEL_PROJECT: \"PROJEYİ İPTAL ET\"\n  STR_NEW_RESEARCH_PROJECTS: \"YENİ ARAŞTIRMA PROJELERİ\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"TOPLAM ARAŞTIRMA PERSONELİ>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"MEVCUT LABORATUVAR KAPASİTESİ>{ALT}{0}\"\n  STR_INCREASE: \"Arttır\"\n  STR_DECREASE: \"Azalt\"\n  STR_START_PROJECT: \"PROJE BAŞLAT\"\n  STR_CURRENT_PRODUCTION: \"MEVCUT ÜRETİM\"\n  STR_ENGINEERS_AVAILABLE: \"Mevcut Teknisyenler>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Görevlendirilen Teknisyenler>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Mevcut Atölye Alanı>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Mevcut Ödenek>{ALT}{0}\"\n  STR_ITEM: \"MADDE\"\n  STR_ENGINEERS__ALLOCATED: \"Görevlendirilen Teknisyenler\"\n  STR_UNITS_PRODUCED: \"Üretilen Miktar\"\n  STR_TOTAL_TO_PRODUCE: \"Toplam Üretilecek\"\n  STR_COST__PER__UNIT: \"Birim{NEWLINE}başına{NEWLINE}Maliyet\"\n  STR_DAYS_HOURS_LEFT: \"Kalan Gün/Saat\"\n  STR_NEW_PRODUCTION: \"Yeni Üretim\"\n  STR_PRODUCTION_ITEMS: \"Üretim Kalemleri\"\n  STR_CATEGORY: \"KATEGORİ\"\n  STR_START_PRODUCTION: \"ÜRETİME BAŞLA\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"Bir birim üretmek için gerekli Teknisyen saati: {0}\"\n  STR_COST_PER_UNIT_: \"Birim başına maliyet>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Gerekli Atölye Alanı>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"ÜRETİM İÇİN GEREKLİ MATERYAL\"\n  STR_ITEM_REQUIRED: \"GEREKLİ MATERYAL\"\n  STR_UNITS_REQUIRED: \"GEREKLİ MİKTAR\"\n  STR_UNITS_AVAILABLE: \"MEVCUT MİKTAR\"\n  STR_STOP_PRODUCTION: \"ÜRETİMİ DURDUR\"\n  STR_ENGINEERS_AVAILABLE_UC: \"MEVCUT TEKNİSYENLER>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"MEVCUT ÇALIŞMA ALANI>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"AYLIK GELİR>{ALT}{0}\"\n  STR_INCREASE_UC: \"ARTTIR\"\n  STR_DECREASE_UC: \"AZALT\"\n  STR_UNITS_TO_PRODUCE: \"Üretilecek Miktar\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Satın Al / İşe Al\"\n  STR_COST_OF_PURCHASES: \"Toplam Fiyat>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"BİRİM BAŞINA MALİYET\"\n  STR_QUANTITY_UC: \"MİKTAR\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"MEVCUT PERSONEL:TOPLAM PERSONEL>\"\n  STR_SOLDIERS: \"Akuanotlar\"\n  STR_SCIENTISTS: \"Bilim İnsanları\"\n  STR_ENGINEERS: \"Teknisyenler\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"KULLANILAN ALAN:MEVCUT ALAN>\"\n  STR_LIVING_QUARTERS: \"Koğuş\"\n  STR_STORES: \"Depo\"\n  STR_LABORATORIES: \"Laboratuvarlar\"\n  STR_WORK_SHOPS: \"Atölyeler\"\n  STR_HANGARS: \"Uçar Bot Sığınakları\"\n  STR_SHORT_RANGE_DETECTION: \"Kısa Menzilli Sonar\"\n  STR_DEFENSE_STRENGTH: \"Savunma Kuvveti\"\n  STR_TRANSFERS_UC: \"TRANSFERLER\"\n  STR_TRANSFERS: \"Transferler\"\n  STR_ARRIVAL_TIME_HOURS: \"Varış Süresi (saat)\"\n  STR_COST_: \"Maliyet>{ALT}{0}\"\n  STR_AREA_: \"Bölge>{ALT}{0}\"\n  STR_BASE_NAME: \"Üs Adı?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"HAVA CEBİNİN KONUMUNU SEÇİN\"\n  STR_TRANSFER: \"Transfer\"\n  STR_AMOUNT_TO_TRANSFER: \"TRANSFER EDİLECEK MİKTAR\"\n  STR_SELECT_DESTINATION_BASE: \"Varış Üssünü Seç\"\n  STR_COST: \"Maliyet\"\n  STR_INTRO_1: \"Copyright 1995 MicroProse\"\n  STR_INTRO_2: \"Mars: Cydonia'nın Düşüşü.\"\n  STR_INTRO_3: \"Yabancı savaş makinesinin kalbini imha eden muzaffer X-Com, eve dönüyor. Ancak Mars üssü harap olmuş olsa da tamamen ölmüş değil.\"\n  STR_INTRO_4: \"Cydonia komuta merkezinden ateşlenen güçlü bir takyon hüzmesi, uzay boşluğunda son sürat ilerliyor. Hedefi............\"\n  STR_INTRO_5: \"Dünya.\"\n  STR_INTRO_6: \"Hüzme, okyanusun dibinde uzun süredir uykuda olan bir alıcıyla buluşuyor. Dev bilgisayarlar hareketleniyor. Derinliklerde, insan gözlerinden çok uzakta, Yabancılar uzun uykularından uyanmaya başlıyorlar.\"\n  STR_INTRO_7: \"2040: Her şeyden habersiz bir Dünya. Yabancı savaşlarının dehşeti çoktan unutulmuş. Ancak okyanusun kayıp ve gizli köşelerinde, Yabancı güruhları insanlığı yok edip dünyayı ele geçirmeye hazır.\"\n  STR_INTRO_8: \"Yabancılar insan türüne karşı saldırıya geçiyor. Sapkın deneyleri için örnek toplamaya, kıymetli hammaddeler için denizleri yağmalamaya başlıyorlar. Ardından, gözlerini denizin dışına çeviriyorlar.\"\n  STR_INTRO_9: \"Tuhaf görünümlü ve güçlü uçar botlar, okyanusları taramaya ve avlanmaya başlıyorlar.........\"\n  STR_INTRO_10: \"Av bulduklarında saldırıyorlar.\"\n  STR_INTRO_11: \"Savunmasız bir dünya, tuhaf ve yeni silahlarla burun buruna geliyor. İnsanlık, Yabancı tehdidinin insafına kalmış durumda.{NEWLINE}Bizi kurtarabilecek yalnızca bir örgüt var. Ne var ki, uzun zaman önce onlara sırtımızı çevirdik......\"\n  STR_INTRO_12: \"X-COM Deneysel Sualtı Tesisleri\"\n  STR_INTRO_13: \"'Mayday! Mayday!' 'Transatlantik yolcu gemisi Hyperion konuşuyor'. 'Saldırıya uğradık'. 'Mayday! Mayd............'\"\n  STR_INTRO_14: \"'Komuta Merkezinden Bot Sığınağı Bir'e: Okyanus kapılarını açın', 'Baraküda Sıfır Bir görev başına. Yabancı taarruz ihbarı aldık - Kırmızı alarm'.{NEWLINE}'Tekrar ediyorum: Kırmızı alarm'\"\n  STR_INTRO_15: \"Yabancı saldırıları etkin ve amansız....\"\n  STR_INTRO_16: \"...isabetli ve hatasız.\"\n  STR_INTRO_17: \"'Baraküda Sıfır Bir'den üsse' - 'Hyperion'dan geriye kalan enkaza yaklaşıyoruz'.\"\n  STR_INTRO_18: \"'Yavaşlıyorum'.{NEWLINE}'İki metre'{NEWLINE}'Bir metre'{NEWLINE}'Tüm akuanotlar acil mevzilenme için hazırlansın'.\"\n  STR_INTRO_19: \"...........'Hava cebi boşaltıldı'...'enkaza yaklaşıyorum'.{NEWLINE}'Tanrım!'{NEWLINE}'Miğfer kameramdan bu yaratıkları görebiliyor musunuz?'\"\n  STR_GAMEOVER_1: \"Başarısız olduk. Yabancılar, kurtuluşa dair son ümitlerimizi de yerle bir etti.{NEWLINE}X-Com yok edildi ve Dünya, kadim düşmanının ayaklarına serildi.\"\n  STR_GAMEOVER_2: \"T'leth, gürleyerek stratosfere yükseliyor; yeryüzü boyunca ölüm saçarak ve insan ırkından geriye kalanları hasat kaldırır gibi toplayarak ilerlemeye başlıyor. Derinliklerindeki kana susamış Yabancı zihni, uyanışa geçiyor.\"\n  STR_GAMEOVER_3: \"Tüm ulusların başkentlerinde ümitsiz planlar yapılıyor. Ne yazık ki bu son çırpınışlar nafile; X-Com araştırma projesiyle elde edilen teknolojinin yokluğunda, silahlarımız etkisiz kalıyor.\"\n  STR_GAMEOVER_4: \"Yabancılar, kutuplarda üsler kuruyor ve buzulları eritmeye, yeryüzünü dev bir denize çevirmeye başlıyorlar. İnsan ırkının kalıntıları sürü gibi toplanıyor ve amacı meçhul üreme deneylerinde kullanılıyor. Gökyüzü kararıyor ve Dünya, amansız bir belayla kuşatılıyor.\"\n  STR_GAMEOVER_5: \"Bu yeni dünya düzenine karşı gelmemiz imkansız; baş kaldıranlar akıl almaz Yabancı silahlarının namlusunda can veriyorlar. Geriye kalanlar içinse böyle şanslı bir kurtuluş söz konusu değil. Dünyamız, bir Yabancı gezegenine dönüşüyor ve insan ırkı bu vahşet altında yitip gidiyor.\"\n  STR_OUTRO_1: \"Mozolenin harap olmasıyla birlikte merkezdeki lahitten bir kükreme yükseliyor.{NEWLINE}Sersemler! Hepiniz yok olacaksınız....................\"\n  STR_OUTRO_2: \".................hiç biriniz kaçamayacaksınız.\"\n  STR_OUTRO_3: \"Lahitte başlayan müthiş patlama tüm şehri tahrip ederek yayılıyor ve her yeri moloz ve dumanla dolduruyor. Yabancıların tüm planları bir anda suya düşüyor........\"\n  STR_OUTRO_4: \"Girift ve devasa T'leth şehri parçalara ayrılmaya başlıyor. Işıltılı kulelerden ve adamantiyum koridorlardan alevler ve dumanlar yükseliyor.\"\n  STR_OUTRO_5: \"Muazzam Yabancı sığınağı, okyanusun sularına doğru yuvarlanıyor; hem metal yapıların hem de canlıların ızdırap dolu çığlıkları kulaklarda çınlıyor. Ulu Uyuyan'ın dünyayı ele geçirme rüyaları da böylece son buluyor.\"\n  STR_OUTRO_6: \"T'leth, kulak patlatan son bir çarpışma sesiyle paramparça oluyor.{NEWLINE}Dünya, Yabancı tehdidinden tam olarak arınıyor..................\"\n  STR_OUTRO_7: \"Galaksinin uzak bir köşesinde, miskin, mavi-yeşil bir gezegen.\"\n  STR_OUTRO_8: \"Yakın gelecek. Yaşamak için güvenli bir yer.\"\n  STR_OUTRO_9: \"Dünya karşısındaki Yabancı tehdidinin mağlup edilmesi üzerinden uzun zaman geçmiş.\"\n  STR_OUTRO_10: \"İnsanlık gelişip serpilmiş; muazzam metropollerde milyarlar yaşıyor.\"\n  STR_OUTRO_11: \"X-Com'un hizmetleri ve Yabancı savaşları artık sadece çocuk hikayelerinde ve efsanelerde geçiyor.\"\n  STR_OUTRO_12: \"Ama tüm efsanelerde her zaman bir gerçeklik payı olmuştur............\"\n  STR_RISE_1: \"Pek çok diyarda, farklı efsanelerde farklı isimlerle anılan T'leth,\"\n  STR_RISE_2: \"yeryüzü boyunca yankılanan korkunç bir çığlıkla deniz yatağından ayrılmaya başlıyor.\"\n  STR_RISE_3: \"Dev mabet, Meksika Körfezi'nin sularından yükseliyor.\"\n  STR_RISE_4: \"65 milyon yıldır dünyada mahsur kalmış Baş Yabancı, istirahat yeri olan 400 milyar ton ağırlığındaki metal Yabancı şehri ile birlikte uykusundan uyanmaya başlıyor.\"\n  STR_RISE_5: \"Ulu Uyuyan, çalkalanan ve kaynayan sular arasından güneş ışığına doğru yükseliyor................\"\n  STR_RISE_6: \".........eğer X-Com, Yabancı savaş makinesini yok edemeyecek olursa, bu güneş ışığının da günleri sayılı.\"\n  STR_YOU_HAVE_FAILED: \"Yabancı savaş makinesini durdurmakta başarısız oldunuz. Size güvenini kaybeden finsansör kurumlar, Yabancılarla müzakere masasına oturmaya karar verdiler. İşgalcilerin ise çok farklı planları vardı ve çok geçmeden tüm dünya asıl gerçeğin farkına vardı.\"\n  STR_TOTAL_UC: \"TOPLAM\"\n  STR_INCOME: \"Gelir\"\n  STR_EXPENDITURE: \"Harcama\"\n  STR_MAINTENANCE: \"Bakım\"\n  STR_BALANCE: \"Bakiye\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"Denizlere göre Yabancı Aktivitesi\"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"Bölgelere göre Yabancı Aktivitesi\"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"Denizlere göre X-Com Aktivitesi\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"Bölgelere göre X-Com Aktivitesi\"\n  STR_FINANCE: \"Finans\"\n  STR_DATE_FIRST: \"{0}\"\n  STR_DATE_SECOND: \"{0}\"\n  STR_DATE_THIRD: \"{0}\"\n  STR_DATE_FOURTH: \"{0}\"\n  STR_FINANCE_THOUSANDS: \"$1000\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"{1} üssünde{NEWLINE}{0} üretmek için yeterli özel malzeme yok\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"{1} üssündeki{NEWLINE}{0} üretimi için yeterli para yok\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"{1}{NEWLINE}üssünde{NEWLINE}{0}{NEWLINE}üretimi tamamlandı.\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"{1}{NEWLINE}üssünde{NEWLINE}{0}{NEWLINE}inşaatı tamamlandı.\"\n  STR_OK_5_SECONDS: \"TAMAM - 5 sn.\"\n  STR_RESEARCH_COMPLETED: \"Araştırma Sonuçlandı\"\n  STR_VIEW_REPORTS: \"SONUÇ RAPORU\"\n  STR_WE_CAN_NOW_RESEARCH: \"Yeni araştırma konusu:\"\n  STR_WE_CAN_NOW_PRODUCE: \"Yeni Üretim Kalemi:\"\n  STR_SUNDAY: \"PAZAR\"\n  STR_MONDAY: \"PAZARTESİ\"\n  STR_TUESDAY: \"SALI\"\n  STR_WEDNESDAY: \"ÇARŞAMBA\"\n  STR_THURSDAY: \"PERŞEMBE\"\n  STR_FRIDAY: \"CUMA\"\n  STR_SATURDAY: \"CUMARTESİ\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"{2} üssünde {1} için yakıt ikmaline yetecek kadar {0} yok\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"{2} üssünde {1} için yeterli {0} yok\"\n  STR_UFO_IS_NOT_RECOVERED: \"YABANCI BOTU ele geçirilemedi\"\n  STR_UFO_IS_RECOVERED: \"YABANCI BOTU ele geçirildi\"\n  STR_CRAFT_IS_LOST: \"Uçar Bot kaybedildi\"\n  STR_TERROR_CONTINUES: \"Yabancı Faaliyeti devam ediyor\"\n  STR_ALIENS_DEFEATED: \"Yabancılar yenilgiye uğratıldı\"\n  STR_BASE_IS_LOST: \"Üs hakimiyeti kaybedildi\"\n  STR_BASE_IS_SAVED: \"Üs kurtarıldı\"\n  STR_ALIEN_BASE_STILL_INTACT: \"Yabancı Kolonisi hala aktif\"\n  STR_ALIEN_BASE_DESTROYED: \"Yabancı Kolonisi imha edildi\"\n  STR_ALIENS_KILLED: \"ÖLDÜRÜLEN YABANCILAR\"\n  STR_ALIEN_CORPSES_RECOVERED: \"ÖLÜ ELE GEÇİRİLEN YABANCILAR\"\n  STR_LIVE_ALIENS_RECOVERED: \"CANLI ELE GEÇİRİLEN YABANCILAR\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"ELE GEÇİRİLEN YABANCI YAPITLARI\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"KOLONİ MERKEZİNİN İMHASI\"\n  STR_ALIEN_SYNOMIUM_DEVICE_DESTROYED: \"YABANCI SİNOMİYUM CİHAZI İMHA EDİLDİ\"\n  STR_ALIEN_SYNOMIUM_DEVICE_FAILED: \"SİNOMİYUM CİHAZI İMHA EDİLEMEDİ\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"YABANCILARIN ÖLDÜRDÜĞÜ SİVİLLER\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"X-COM TARAFINDAN ÖLDÜRÜLEN SİVİLLER\"\n  STR_CIVILIANS_SAVED: \"KURTARILAN SİVİLLER\"\n  STR_XCOM_OPERATIVES_KILLED: \"ÖLDÜRÜLEN X-COM PERSONELİ\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"MUHAREBEDE KAYBOLAN X-COM PERSONELİ\"\n  STR_TANKS_DESTROYED: \"X-COM SİLAH PLATFORMU YOK EDİLDİ\"\n  STR_XCOM_CRAFT_LOST: \"KAYBEDİLEN X-COM DENİZALTISI\"\n  STR_UFO_RECOVERY: \"YABANCI BOTUNU ELE GEÇİRME\"\n  STR_ALIEN_BASE_RECOVERY: \"YABANCI KOLONİSİNE TAARRUZ\"\n  STR_BASE_UNDER_ATTACK: \"{0} taarruz altında!\"\n  STR_BASE_DEFENSES_INITIATED: \"ÜS SAVUNMA SİLAHLARI AKTİF\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"KALKANLAR YABANCI BOTUNU PÜSKÜRTTÜ!\"\n  STR_FIRING: \"ATEŞ EDİYOR\"\n  STR_HIT: \"İSABET!\"\n  STR_UFO_DESTROYED: \"YABANCI BOTU YOK EDİLDİ!\"\n  STR_MISSED: \"ISKA!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Mal Sat / Personel Kov\"\n  STR_VALUE_OF_SALES: \"SATIŞ DEĞERİ> {ALT}{0}\"\n  STR_FUNDS: \"ÖDENEK> {ALT}{0}\"\n  STR_SELL_SACK: \"Sat/Kov\"\n  STR_VALUE: \"Değer\"\n  STR_CRAFT_: \"UÇAR BOT> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"ÇAKILAN YABANCI BOTUNU ELE GEÇİRME\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"DİKKATLİ OLUN - Yabancı denizaltısının içinde ya da civarında hala düşman personeli mevcut olabilir. Harekat, tüm düşman unsurları etkisiz hale getirildiğinde başarıya ulaşacaktır. Denizaltının, teçhizatın ve yabancı cesetlerinin ele geçirilmesine bundan sonra başlanabilir. Harekatı iptal etmek için, X-Com personelini intikal aracına geri döndürün ve 'Harekatı Bırak' butonuna basın.\"\n  STR_UFO_GROUND_ASSAULT: \"YABANCI DENİZALTISINA TAARRUZ\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"İniş bölgesini araştırın ve mümkünse yabancı denizaltısına giriş yapmaya çalışın. Harekat, tüm düşman unsurları etkisiz hale getirildiğinde başarıya ulaşacaktır. Denizaltının, teçhizatın ve yabancı cesetlerinin ele geçirilmesine bundan sonra başlanabilir. Harekatı iptal etmek için, tüm X-Com personelini intikal aracına geri döndürün ve 'Harekatı Bırak' butonuna basın.\"\n  STR_BASE_DEFENSE: \"ÜS SAVUNMASI\"\n  STR_BASE_UC_: \"ÜS> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"Bir yabancı denizaltısı, yakınlarda iniş yaptı. Üssümüz büyük tehlike altında. Standart prosedür gereği tüm sivil personel ve X-Com botları tahliye edildi. Düşman unsurlar, bot sığınaklarından ya da hava cebinden giriş yapacaklardır. Üssü ve içindeki hayati tesisleri her ne pahasına olursa olsun savunmalısınız - bu bir ölüm kalım savaşı. Eğer 'harekatı bırak' butonuna basarsanız yenilgiyi kabul etmiş olacaksınız ve üssü kaybedeceğiz.\"\n  STR_ALIEN_COLONY_ATTACK_MISSION: \"YABANCI KOLONİSİ TAARRUZ HAREKATI\"\n  STR_ALIEN_BASE_ASSAULT: \"YABANCI KOLONİSİ BİRİNCİ KISIM\"\n  STR_ALIEN_COLONY_P1_BRIEFING: \"Bu görev, bir Yabancı kolonisine taarruz harekatıdır. Koloni iki seviyeden oluşuyor. Tüm akuanotlarınızı ilk seviye içerisindeki ışıltılı çıkış bölgesine ulaştırıp 'Harekatı Bırak' butonuna basarak ikinci seviyeye geçmelisiniz. Geride bırakılan tüm teçhizat, ikinci seviye tamamlanana kadar deniz dibinde kalacaktır. Geri çekilmek için akuanotlarınızı Denizaltıya döndürün ve 'Harekatı Bırak' butonuna basın.\"\n  STR_ALIEN_COLONY_P2: \"YABANCI KOLONİSİ İKİNCİ KISIM\"\n  STR_ALIEN_COLONY_P2_BRIEFING: \"Harekatın ilk kısmı tamamlandı ve koloni merkezine ulaşıldı. Şimdiki göreviniz komuta merkezini ya da Sinomiyum Cihazını imha etmek veya tüm Yabancıları etkisiz hale getirmek. Geri çekilmek için tüm akuanotlarınızı başlangıç bölgesine geri döndürün ve 'Harekatı Bırak' butonuna basın. Kullanılabilir durumdaki tüm X-Com teçhizatı da üsse geri götürülecektir.\"\n  STR_ALIENS_LAUNCH_PORT_TERROR: \"LİMAN HEDEFİNE{NEWLINE}YABANCI SALDIRISI\"\n  STR_PORT_TERROR: \"YABANCILARIN LİMAN SALDIRISI\"\n  STR_PORT_TERROR_BRIEFING: \"Yabancılar karadaki bir hedefe saldırı düzenlediler. Liman tesisleri ve bölgedeki siviller tehlike altında. Takımınızın tüm Yabancıları bertaraf etmesi ve masum sivillerin güvenliğini sağlaması gerekiyor. Geri çekilmek için akuanotlarınızı uçar bota geri döndürün ve 'Harekatı Bırak' butonuna basın.\"\n  STR_ALIENS_LAUNCH_ISLAND_TERROR: \"ADA HEDEFİNE{NEWLINE}YABANCI SALDIRISI\"\n  STR_ISLAND_TERROR: \"YABANCILARIN ADA SALDIRISI\"\n  STR_ISLAND_TERROR_BRIEFING: \"Yabancılar karadaki bir hedefe saldırı düzenlediler. Adadaki sivil halk tehlike altında. Takımınızın tüm Yabancıları bertaraf etmesi ve masum sivillerin güvenliğini sağlaması gerekiyor. Geri çekilmek için akuanotlarınızı uçar bota geri döndürün ve 'Harekatı Bırak' butonuna basın.\"\n  STR_ALIENS_ATTACK_SHIPPING_ROUTE: \"GEMİ HEDEFİNE{NEWLINE}YABANCI SALDIRISI\"\n  STR_CARGO_SHIP_P1: \"KARGO GEMİSİ BİRİNCİ KISIM\"\n  STR_CARGO_SHIP_P2: \"KARGO GEMİSİ İKİNCİ KISIM\"\n  STR_CRUISE_SHIP_P1: \"YOLCU GEMİSİ BİRİNCİ KISIM\"\n  STR_CRUISE_SHIP_P2: \"YOLCU GEMİSİ İKİNCİ KISIM\"\n  STR_SHIP_RESCUE_MISSION: \"GEMİ KURTARMA HAREKATI\"\n  STR_SHIP_RESCUE_P1_BRIEFING: \"Bu görev, bir böcek avı. Gemideki tüm Yabancıları etkisiz hale getirin ve sivillerin can güvenliğini sağlamaya çalışın. Yabancılar üst ve alt güvertelere dağılmış durumdalar. Alt güvertelere inmeden önce üst güverteleri kontrol altına alın. Geri çekilmek için akuanotlarınızı uçar bota geri döndürün ve 'Harekatı Bırak' butonuna basın.\"\n  STR_SHIP_RESCUE_P2_BRIEFING: \"Üst güvertenin güvenliği sağlanmış durumda. Kargo asansörünü kullanarak alt güverte ambarına intikal edin. Takımınız, harekatı tamamlamak için bu seviyedeki tüm Yabancıları etkisiz hale getirmeli. Geri çekilmek için tüm akuanotlarınızı asansördeki başlangıç noktasına geri döndürün ve 'Harekatı Bırak' butonuna basın.\"\n  STR_ALIEN_ACTIVITY_DETECTED: \"YABANCI FALİYETİ TESPİT EDİLDİ\"\n  STR_ALIEN_CONTACT_SITE_MISSION: \"YABANCI TEMAS MEVKİİ HAREKATI\"\n  STR_ARTIFACT_SITE_P1: \"YABANCI TEMAS MEVKİİ BİRİNCİ KISIM\"\n  STR_ARTIFACT_SITE_P1_BRIEFING: \"Bu görev, faaliyete yeni başlayan bir Yabancı iletişim merkezine taarruz harekatıdır. Bölgede, deniz dibindeki Yabancı piramitleri ve bunların altındaki gizli Yabancı yerleşkesi olmak üzere iki seviye mevcut. İkinci seviyeye geçmek için tüm akuanotları yerleşke girişine ulaştırın ve 'Harekatı Bırak' butonuna basın. Geri çekilmek için ise akuanotlarınızı uçar bota geri döndürün ve 'Harekatı Bırak' butonuna basın.\"\n  STR_ARTIFACT_SITE_P2: \"YABANCI TEMAS MEVKİİ İKİNCİ KISIM\"\n  STR_ARTIFACT_SITE_P2_BRIEFING: \"Yabancı yapılarını aşıp ana yerleşkeye ulaşmanızla birlikte harekatın hedefi netlik kazanmış durumda. Görevi tamamlamak için Yabancı tesislerinin kalbine nüfuz etmeli ve Sinomiyum Moleküler Kontrol Cihazını imha etmelisiniz. Geri çekilmek için tüm akuanotlarınızı giriş asansörüne geri döndürün ve 'Harekatı Bırak' butonuna basın.\"\n  STR_SIGSBEE_DEEP_MISSION: \"SIGSBEE ÇUKURLUĞU HAREKATI{NEWLINE}YABANCI ŞEHRİ BİRİNCİ KISIM\"\n  STR_TLETH_P1_BRIEFING: \"Bilinmeyene adım atıyoruz - şu andan itibaren karşımıza her şey çıkabilir. Tek bildiğimiz, Yabancı şehrinin 2 seviyesi daha olduğu ve sonraki seviyeye geçebilmek için takımınızı hızla çıkışa ulaştırmanız gerektiği. Devam etmek için tüm akuanotları çıkış bölgesine yerleştirin ve 'Harekatı Bırak' butonuna basın. Harekatı başka bir yerdeyken bırakmak, tüm görevi sonlandıracaktır.\"\n  STR_TLETH_ATTACK_MISSION: \"T'LETH TAARRUZ HAREKATI{NEWLINE}YABANCI ŞEHRİ İKİNCİ KISIM\"\n  STR_TLETH_P2_BRIEFING: \"Bilinmeyenin derinliklerindeyiz - şu andan itibaren karşımıza ne çıkacağını kestiremiyoruz. Tek bildiğimiz Yabancı şehrinin bir seviyesi daha olduğu ve sonraki seviyeye geçebilmek için takımını hızla çıkışa ulaştırmanız gerektiği. Devam etmek için tüm akuanotları çıkış bölgesine yerleştirin ve 'Harekatı Bırak' butonuna basın. Harekatı başka bir yerdeyken bırakmak, tüm görevi sonlandıracaktır.\"\n  STR_FINAL_TLETH_MISSION: \"NİHAİ T'LETH HAREKATI{NEWLINE}YABANCI ŞEHRİ ÜÇÜNCÜ KISIM\"\n  STR_TLETH_P3_BRIEFING: \"Harekatın sonuna yaklaşıyoruz. Şimdi, Baş Yabancının mezarını bulmamız gerekiyor. Yabancı tehdidini sona erdirmek için bu mezarı besleyen 8 tane güç kaynağını imha etmelisiniz. Artık geri dönüş yok! Harekatı bırakmak tüm görevi sonlandıracaktır.\"\n  STR_TLETH_P1: \"YABANCI ŞEHRİ BİRİNCİ KISIM\"\n  STR_TLETH_P2: \"YABANCI ŞEHRİ İKİNCİ KISIM\"\n  STR_TLETH_P3: \"YABANCI ŞEHRİ ÜÇÜNCÜ KISIM\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"ÜRETİM İÇİN BOT SIĞINAĞI YOK!{SMALLLINE}Bir üsse tahsis edilen, transfer edilen, satın alınan ya da üretimine başlanan her bir Uçar Bot için bir bot sığınağı ayrılmalıdır. Yeni bir bot sığınağı inşa edin ya da mevcut botlardan birini başka bir üsse transfer edin.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"SATINALIM İÇİN BOT SIĞINAĞI YOK!{SMALLLINE}Bir üsse tahsis edilen, transfer edilen, satın alınan ya da üretimine başlanan her bir Uçar Bot için bir bot sığınağı ayrılmalıdır. Yeni bir bot sığınağı inşa edin ya da mevcut botlardan birini başka bir üsse transfer edin.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"TRANSFER İÇİN BOT SIĞINAĞI YOK!{SMALLLINE}Bir üsse tahsis edilen, transfer edilen, satın alınan ya da üretimine başlanan her bir Uçar Bot için bir bot sığınağı ayrılmalıdır. Yeni bir bot sığınağı inşa edin ya da mevcut botlardan birini başka bir üsse transfer edin.\"\n  STR_CANNOT_BUILD_HERE: \"BURADA İNŞA EDİLEMEZ!{SMALLLINE}Yeni tesis, mevcut bir tesise komşu olmak zorunda.\"\n  STR_NO_FREE_ACCOMODATION: \"YETERLİ YAŞAM ALANI YOK!{SMALLLINE}Varış üssü, personel için yeterli koğuş kapasitesine sahip değil.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"YETERLİ ÇALIŞMA ALANI YOK!{SMALLLINE}Ya yeni bir atölye inşa edin ya da diğer projelere ayrılan iş gücünü azaltın.\"\n  STR_NOT_ENOUGH_MONEY: \"YETERLİ PARA YOK!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"YETERLİ DEPO ALANI YOK!{SMALLLINE}Yeni bir depo inşa edin ya da mevcut stokları diğer üslere transfer edin.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"YETERLİ YAŞAM ALANI YOK!{SMALLLINE}Yeni koğuşlar inşa edin ya da mevcut personeli diğer üslere transfer edin.\"\n  STR_LAUNCH_INTERCEPTION: \"TAKİP BAŞLAT\"\n  STR_CRAFT: \"ARAÇ\"\n  STR_STATUS: \"DURUM\"\n  STR_BASE: \"ÜS\"\n  STR_READY: \"HAZIR\"\n  STR_OUT: \"DIŞARIDA\"\n  STR_REPAIRS: \"TAMİRAT\"\n  STR_REFUELLING: \"YAKIT İKMALİ\"\n  STR_REARMING: \"SİLAHLANMA\"\n  STR_TARGET: \"HEDEF: {0}\"\n  STR_WAY_POINT: \"ARA NOKTA\"\n  STR_ARE_YOU_SURE_CYDONIA: \"Bu botu T'leth harekatına göndermek istediğinize emin misiniz?\"\n  STR_YES: \"EVET\"\n  STR_NO: \"HAYIR\"\n  STR_SELECT_DESTINATION: \"HEDEFİ SEÇ\"\n  STR_CYDONIA: \"T'LETH\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"YENİ ÜS İÇİN KONUM BELİRLEYİN\"\n  STR_RETURN_TO_BASE: \"ÜSSE GERİ DÖN\"\n  STR_SELECT_NEW_TARGET: \"YENİ HEDEF SEÇ\"\n  STR_PATROL: \"DEVRİYE\"\n  STR_STATUS_: \"DURUM>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"HASARLI - ÜSSE DÖNÜYOR\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"YAKIT AZALDI - ÜSSE DÖNÜYOR\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"GÖREV TAMAMLANDI - ÜSSE DÖNÜYOR\"\n  STR_PATROLLING: \"DEVRİYE GEZİYOR\"\n  STR_TAILING_UFO: \"YABANCI BOTU TAKİBİ\"\n  STR_INTERCEPTING_UFO: \"YABANCI BOTU-{0} TAKİP EDİLİYOR\"\n  STR_RETURNING_TO_BASE: \"ÜSSE DÖNÜYOR\"\n  STR_DESTINATION_UC_: \"HEDEF: {0}\"\n  STR_BASE_UC: \"ÜS>{ALT}{0}\"\n  STR_SPEED_: \"SÜRAT>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"AZAMİ SÜRAT>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"DERİNLİK>{ALT}{0}\"\n  STR_AIRBORNE: \"HAVADA\"\n  STR_VERY_LOW: \"SIĞ\"\n  STR_LOW_UC: \"NORMAL\"\n  STR_HIGH_UC: \"DERİN\"\n  STR_VERY_HIGH: \"ÇOK DERİN\"\n  STR_FUEL: \"YAKIT>{ALT}{0}\"\n  STR_WEAPON_ONE: \"SİLAH-1>{ALT}{0}\"\n  STR_NONE_UC: \"YOK\"\n  STR_ROUNDS_: \"MERMİ>{ALT}{0}\"\n  STR_WEAPON_TWO: \"SİLAH-2>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"UÇAR BOT\"\n  STR_BASE_: \"Üs>{0}\"\n  STR_NAME_UC: \"İSİM\"\n  STR_AMMO_: \"CEPHANE>{ALT}{0}\"\n  STR_CREW: \"MÜRETTEBAT\"\n  STR_EQUIPMENT_UC: \"TEÇHİZAT\"\n  STR_ARMOR: \"ZIRH\"\n  STR_MAX: \"AZAMİ>{ALT}{0}\"\n  STR_ROOKIE: \"Deniz eri\"\n  STR_SQUADDIE: \"Çavuş\"\n  STR_SERGEANT: \"Asteğmen\"\n  STR_CAPTAIN: \"Teğmen\"\n  STR_COLONEL: \"Yarbay\"\n  STR_COMMANDER: \"Albay\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"{0} için Takım Seç\"\n  STR_SORT_BY: \"SIRALAMA...\"\n  STR_ORIGINAL_ORDER: \"ÖZGÜN SIRALAMA\"\n  STR_MISSIONS2: \"GÖREV SAYISI\"\n  STR_KILLS2: \"İMHA\"\n  STR_WOUND_RECOVERY2: \"MALÜLİYET SÜRESİ\"\n  STR_SPACE_AVAILABLE: \"BOŞ ALAN>{ALT}{0}\"\n  STR_SPACE_USED: \"KULLANILAN ALAN>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"KULLANILAN ALAN\"\n  STR_RANK: \"RÜTBE\"\n  STR_WOUNDED: \"YARALI\"\n  STR_EQUIPMENT_FOR_CRAFT: \"{0} için Teçhizat\"\n  STR_DEFENSE_VALUE: \"Savunma Değeri\"\n  STR_HIT_RATIO: \"İsabet Oranı\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}iniş yapmaya hazır.{NEWLINE}Hedef:{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"Göreve Başla?\"\n  STR_SELECT_ARMAMENT: \"Donatım Seç\"\n  STR_AMMUNITION_AVAILABLE: \"MEVCUT CEPHANE\"\n  STR_ARMAMENT: \"DONATIM\"\n  STR_NOT_AVAILABLE: \"-\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"{0}{NEWLINE}için zırh tahsis et\"\n  STR_TYPE: \"TİP\"\n  STR_PLASTIC_AQUA_ARMOR_UC: \"PLASTİK AKUAZIRH\"\n  STR_ION_ARMOR_UC: \"İYON ZIRH\"\n  STR_MAGNETIC_ION_ARMOR_UC: \"MANYETİK İYON ZIRH\"\n  STR_PLASTIC_AQUA_ARMOR_UFOPEDIA: \"Yabancılardan ele geçirilen Akua Plastik teknolojisiyle üretilen bu zırhlar, askerlerimize, Yabancı tehdidine karşı direnme şansı verecektir.\"\n  STR_ION_ARMOR_UFOPEDIA: \"Askerlerimiz için güçlü koruma sağlayan bu yeni zırh, İYON enerji kaynağıyla besleniyor ve kullanıcısının kuvvetini ve hızını önemli ölçüde arttırıyor. Bu zırh, harekat güçlerimiz için şu ana kadar geliştirilmiş en iyi korunma aracı.\"\n  STR_MAGNETIC_ION_ARMOR_UFOPEDIA: \"İYON zırhının daha gelişmiş ve Manyetik Dizi teknolojisiyle güçlendirilmiş versiyonu. Su altında sınırsız hareket kabiliyeti sağlıyor.\"\n  STR_SELECT_ARMOR: \"Zırh Seç\"\n  STR_NORTH: \"KUZEY\"\n  STR_NORTH_EAST: \"KUZEY DOĞU\"\n  STR_EAST: \"DOĞU\"\n  STR_SOUTH_EAST: \"GÜNEY DOĞU\"\n  STR_SOUTH: \"GÜNEY\"\n  STR_SOUTH_WEST: \"GÜNEY BATI\"\n  STR_WEST: \"BATI\"\n  STR_NORTH_WEST: \"KUZEY BATI\"\n  STR_SELECT_ACTION: \"AKSİYON SEÇ\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"TAKİBE DEVAM ET\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"TEMAS SAĞLAMADAN TAKİP\"\n  STR_VERY_LARGE: \"ÇOK BÜYÜK\"\n  STR_LARGE: \"BÜYÜK\"\n  STR_MEDIUM_UC: \"ORTA\"\n  STR_SMALL: \"KÜÇÜK\"\n  STR_VERY_SMALL: \"ÇOK KÜÇÜK\"\n  STR_GROUNDED: \"İNİŞ YAPMIŞ\"\n  STR_DETECTED: \"Tespit edildi\"\n  STR_SIZE_UC: \"BOYUT\"\n  STR_ALTITUDE: \"DERİNLİK\"\n  STR_HEADING: \"İSTİKAMET\"\n  STR_SPEED: \"SÜRAT\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"YABANCI BOTUNA ODAKLAN-SÜRE=5 Sn.\"\n  STR_TRACKING_LOST: \"BOT İZİNİ KAYBETTİRDİ\"\n  STR_REDIRECT_CRAFT: \"ARACI YENİDEN YÖNLENDİR\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"BİLİNEN SON BOT KONUMUNA GİT\"\n  STR_UFO_: \"YABANCI BOTU-{0}\"\n  STR_ALIEN_BASE_: \"YABANCI KOLONİSİ-{0}\"\n  STR_CRASH_SITE_: \"DÜŞÜŞ BÖLGESİ-{0}\"\n  STR_LANDING_SITE_: \"İNİŞ BÖLGESİ-{0}\"\n  STR_WAY_POINT_: \"ARA NOKTA-{0}\"\n  STR_TERROR_SITE: \"TERÖR MEVKİİ-{0}\"\n  STR_ARTIFACT_SITE: \"YAPIT MEVKİİ-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}{1}{NEWLINE}hedefine ulaştı\"\n  STR_NOW_PATROLLING: \"Devriye geziyor\"\n  STR_ALIEN_ORIGINS: \"Yabancı Kökenleri\"\n  STR_THE_ULTIMATE_THREAT: \"Nihai Tehdit\"\n  STR_TLETH_ALIEN_CITY: \"Yabancılar Şehri T'leth\"\n  STR_UFOPAEDIA: \"UFOpedi\"\n  STR_XCOM_CRAFT_ARMAMENT: \"X-COM ARAÇ VE SİLAHLARI\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"DENİZALTI SİLAH SİSTEMLERİ\"\n  STR_WEAPONS_AND_EQUIPMENT: \"GENEL TEÇHİZAT\"\n  STR_ALIEN_ARTIFACTS: \"DENİZ YAPITLARI\"\n  STR_BASE_FACILITIES: \"X-COM TESİSLERİ\"\n  STR_ALIEN_LIFE_FORMS: \"YABANCI YARATIKLAR\"\n  STR_ALIEN_RESEARCH_UC: \"YABANCI TEKNOLOJİSİ\"\n  STR_UFO_COMPONENTS: \"YENİ DENİZALTI TEKNOLOJİLERİ\"\n  STR_UFOS: \"YABANCI DENİZALTILARI\"\n  STR_SELECT_ITEM: \"KONU BAŞLIKLARI\"\n  STR_ACCELERATION: \"SÜRATLENME>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"YAKIT KAPASİTESİ>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"SİLAH YUVALARI>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"HASAR KAPASİTESİ>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"KARGO ALANI>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"DSS KAPASİTESİ>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Hasar\"\n  STR_RANGE: \"Menzil\"\n  STR_KILOMETERS: \"{0} km\"\n  STR_ACCURACY: \"İsabet\"\n  STR_RE_LOAD_TIME: \"Doldurma süresi\"\n  STR_SECONDS: \"{0}s\"\n  STR_DAMAGE_ARMOR_PIERCING: \"ZIRH DELİCİ\"\n  STR_DAMAGE_INCENDIARY: \"FOSFOR\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"PATLAYICI\"\n  STR_DAMAGE_LASER_BEAM: \"GAUS IŞINI\"\n  STR_DAMAGE_PLASMA_BEAM: \"SONİK HÜZME\"\n  STR_DAMAGE_STUN: \"DON\"\n  STR_DAMAGE_MELEE: \"YAKIN DÖVÜŞ\"\n  STR_DAMAGE_ACID: \"ASİT\"\n  STR_DAMAGE_SMOKE: \"DUMAN\"\n  STR_SHOT_TYPE: \"TİP\"\n  STR_ACCURACY_UC: \"İSABET\"\n  STR_TIME_UNIT_COST: \"ZÜ\"\n  STR_DAMAGE_UC: \"HASAR\"\n  STR_AMMO: \"MÜHİMMAT\"\n  STR_SHOT_TYPE_AUTO: \"Otomatik\"\n  STR_SHOT_TYPE_SNAP: \"Ani\"\n  STR_SHOT_TYPE_AIMED: \"Keskin\"\n  STR_CONSTRUCTION_TIME: \"İnşaat Süresi\"\n  STR_CONSTRUCTION_COST: \"İnşaat Maliyeti\"\n  STR_MAINTENANCE_COST: \"Bakım Maliyeti\"\n  STR_LOW: \"Düşük\"\n  STR_MEDIUM: \"Orta\"\n  STR_HIGH: \"Yüksek\"\n  STR_CRAFT_WEAPON: \"Bot Silahı\"\n  STR_CRAFT_AMMUNITION: \"Bot Mühimmatı\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Ağır Silah Sistemi\"\n  STR_WEAPON: \"Silah\"\n  STR_AMMUNITION: \"Mühimmat\"\n  STR_EQUIPMENT: \"Teçhizat\"\n  STR_ALIEN_CORPSE: \"Yabancı Cesedi\"\n  STR_UFO_COMPONENT: \"YABANCI BOTU bileşeni\"\n  STR_PERSONAL_ARMOR: \"Vücut Zırhı\"\n  STR_RAW_MATERIALS: \"Ham Madde\"\n  STR_HWP_SOLID_HARPOON_BOLTS: \"Çelik Zıpkın Okları\"\n  STR_ALIEN: \"Yabancı\"\n  STR_AQUATOID: \"Akuatoid\"\n  STR_GILLMAN: \"Solungaçadam\"\n  STR_LOBSTERMAN: \"Istakozadam\"\n  STR_TASOTH: \"Tasot\"\n  STR_CALCINITE: \"Kalsinit\"\n  STR_DEEP_ONE: \"Diptengelen\"\n  STR_BIODRONE: \"Biyodron\"\n  STR_TENTACULAT: \"Tentakülat\"\n  STR_TRISCENE: \"Trisen\"\n  STR_HALLUCINOID: \"Halüsinoid\"\n  STR_XARQUID: \"Zarkid\"\n  STR_ZOMBIE: \"Zombi\"\n  STR_LIVE_COMMANDER: \"Komutan\"\n  STR_LIVE_NAVIGATOR: \"Seyrüseferci\"\n  STR_LIVE_MEDIC: \"Sıhhiyeci\"\n  STR_LIVE_TECHNICIAN: \"Teknisyen\"\n  STR_LIVE_SQUAD_LEADER: \"Takım Komutanı\"\n  STR_LIVE_SOLDIER: \"Asker\"\n  STR_LIVE_TERRORIST: \"Terörist\"\n  STR_AQUATOID_COMMANDER: \"Komutan Akuatoid\"\n  STR_AQUATOID_NAVIGATOR: \"Seyrüseferci Akuatoid\"\n  STR_AQUATOID_MEDIC: \"Sıhhiyeci Akuatoid\"\n  STR_AQUATOID_TECHNICIAN: \"Teknisyen Akuatoid\"\n  STR_AQUATOID_SQUAD_LEADER: \"Takım Komutanı Akuatoid\"\n  STR_AQUATOID_SOLDIER: \"Asker Akuatoid\"\n  STR_GILLMAN_COMMANDER: \"Komutan Solungaçadam\"\n  STR_GILLMAN_TECHNICIAN: \"Teknisyen Solungaçadam\"\n  STR_GILLMAN_SQUAD_LEADER: \"Takım Komutanı Solungaçadam\"\n  STR_GILLMAN_SOLDIER: \"Asker Solungaçadam\"\n  STR_LOBSTERMAN_COMMANDER: \"Komutan Istakozadam\"\n  STR_LOBSTERMAN_NAVIGATOR: \"Seyrüseferci Istakozadam\"\n  STR_LOBSTERMAN_TECHNICIAN: \"Teknisyen Istakozadam\"\n  STR_LOBSTERMAN_SQUAD_LEADER: \"Takım Komutanı Istakozadam\"\n  STR_LOBSTERMAN_SOLDIER: \"Asker Istakozadam\"\n  STR_TASOTH_SQUAD_LEADER: \"Takım Komutanı Tasot\"\n  STR_TASOTH_SOLDIER: \"Asker Tasot\"\n  STR_CALCINITE_TERRORIST: \"Terörist Kalsinit\"\n  STR_DEEP_ONE_TERRORIST: \"Terörist Diptengelen\"\n  STR_BIODRONE_TERRORIST: \"Terörist Biyodron\"\n  STR_TENTACULAT_TERRORIST: \"Terörist Tentakülat\"\n  STR_TRISCENE_TERRORIST: \"Terörist Trisen\"\n  STR_HALLUCINOID_TERRORIST: \"Terörist Halüsinoid\"\n  STR_XARQUID_TERRORIST: \"Terörist Zarkid\"\n  STR_ION_BEAM_ACCELERATORS: \"İyon Hüzme Hızlandırıcıları\"\n  STR_MAGNETIC_NAVIGATION: \"Manyetik Seyrüsefer\"\n  STR_ALIEN_SUB_CONSTRUCTION: \"Yabancı Bot Konstrüksiyonu\"\n  STR_ALIEN_CRYOGENICS: \"Yabancı Kriyojenik Üniteleri\"\n  STR_ALIEN_CLONING: \"Yabancı Klonlayıcıları\"\n  STR_ALIEN_LEARNING_ARRAYS: \"Yabancı Öğrenim Dizeleri\"\n  STR_ALIEN_IMPLANTER: \"Yabancı İmplantasyon Üniteleri\"\n  STR_EXAMINATION_ROOM: \"Tetkik Odası\"\n  STR_AQUA_PLASTICS: \"Akua Plastik\"\n  STR_ALIEN_REANIMATION_ZONE: \"Yabancı Canlandırma Üniteleri\"\n  STR_PLASTIC_AQUA_ARMOR: \"Plastik Akua-Zırh\"\n  STR_ION_ARMOR: \"İyon Zırhı\"\n  STR_MAGNETIC_ION_ARMOR: \"Man. İyon Zırhı\"\n  STR_HWP_AQUA_JET_MISSILES: \"Akua Jet Torpidosu\"\n  STR_HWP_DISPLACER_PWT: \"D.D. Torpidosu\"\n  STR_GAUSS_TECH: \"Gaus Teknolojisi\"\n  STR_NEW_FIGHTER_FLYING_SUB: \"Yeni Avcı Uçar Bot\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Yeni Avcı-Taşıyıcı\"\n  STR_THE_LATEST_FLYING_SUB: \"Nihai Uçar Bot\"\n  STR_ARMOR_PIERCING: \"ZIRH DELİCİ\"\n  STR_COELACANTH_GAS_CANNON: \"Koelakant/G. Topu\"\n  STR_COELACANTH_AQUA_JET: \"Koelakant/Akua Jet\"\n  STR_COELACANTH_GAUSS: \"Koelakant/Gaus\"\n  STR_DISPLACER_SONIC: \"Deplasör/Sonik\"\n  STR_DISPLACER_PWT: \"Deplasör/D.D.T.\"\n  STR_AJAX_LAUNCHER: \"Ajax Roketatar\"\n  STR_DUP_HEAD_LAUNCHER: \"S.U.T. Başlıklı Roketatar\"\n  STR_CRAFT_GAS_CANNON: \"Taşıt Gaz Topu\"\n  STR_PWT_CANNON: \"D.D.T. Topu\"\n  STR_GAUSS_CANNON: \"Gaus Topu\"\n  STR_GAUSS_CANNON_AMMO: \"Gaus Top Mermisi\"\n  STR_SONIC_OSCILLATOR: \"Sonik Osilatör\"\n  STR_AJAX_TORPEDOES: \"Ajax Torpido\"\n  STR_DUP_HEAD_TORPEDOES: \"S.U.T Başlıklı Torpido\"\n  STR_CRAFT_GAS_CANNON_ROUNDS_X50: \"Gaz Mermisi(x50)\"\n  STR_SONIC_WAVE: \"Sonik Dalga\"\n  STR_PULSE_WAVE_TORPEDOES: \"D.D.T. Mühimmat\"\n  STR_SOLDIER: \"Akuanot\"\n  STR_SCIENTIST: \"Bilim İnsanı\"\n  STR_ENGINEER: \"Teknisyen\"\n  STR_NORTH_ATLANTIC: \"Kuzey Atlantik\"\n  STR_SOUTH_ATLANTIC: \"Güney Atlantik\"\n  STR_NORTH_PACIFIC: \"Kuzey Afrika\"\n  STR_SOUTH_PACIFIC: \"Pasifik\"\n  STR_MEDITERRANEAN: \"Akdeniz\"\n  STR_SOUTH_CHINA_SEA: \"Güney Çin Denizi\"\n  STR_INDIAN_OCEAN: \"Hint Okyanusu\"\n  STR_THE_EAST_SEA: \"Japon Denizi\"\n  STR_NORTH_SEA: \"Kuzey Denizi\"\n  STR_CARRIBEAN: \"Karayipler\"\n  STR_ANTARCTIC: \"Antarktika\"\n  STR_ARCTIC: \"Arktika\"\n  STR_EURASIA: \"Avrasya\"\n  STR_NORTH_AMERICA: \"Kuzey Amerika\"\n  STR_AFRICA: \"Afrika\"\n  STR_MAXIMUM_SPEED: \"Azami Sürat\"\n  STR_TRANSMISSION_RESOLVER_UC: \"İLETİ ÇÖZÜCÜ\"\n  STR_TRITON: \"TRİTON\"\n  STR_HAMMERHEAD: \"ÇEKİÇKAFA\"\n  STR_LEVIATHAN: \"LİVYATAN\"\n  STR_BARRACUDA: \"BARAKÜDA\"\n  STR_MANTA: \"MANTA\"\n  STR_UFO: \"YABANCI BOTU\"\n  STR_AJAX: \"AJAX\"\n  STR_DUP_HEAD: \"S.U.T. BAŞLIK\"\n  STR_CRAFT_GAS_CANNON_UC: \"TAŞIT GAZ TOPU\"\n  STR_PWT_CANNON_UC: \"D.D.T. TOPU\"\n  STR_GAUSS_CANNON_UC: \"GAUS TOPU\"\n  STR_SONIC_OSCILLATOR_UC: \"SONİK OSİLATÖR\"\n  STR_DAMAGE_CAPACITY: \"Hasar Kapasitesi\"\n  STR_WEAPON_POWER: \"Silah Gücü\"\n  STR_WEAPON_RANGE: \"Silah Menzili\"\n  STR_AIR_LOCK: \"Hava Cebi\"\n  STR_LABORATORY: \"Laboratuvar\"\n  STR_WORKSHOP: \"Atölye\"\n  STR_STANDARD_SONAR: \"Standart Sonar\"\n  STR_WIDE_ARRAY_SONAR: \"Geniş Bant Sonar\"\n  STR_TORPEDO_DEFENSES: \"Torpido Savunma\"\n  STR_GENERAL_STORES: \"Depo\"\n  STR_ALIEN_CONTAINMENT: \"Yabancı Karantinası\"\n  STR_GAUSS_DEFENSES: \"Gaus Savunma\"\n  STR_SONIC_DEFENSES: \"Sonik Savunma\"\n  STR_PWT_DEFENSES: \"D.D.T. Savunma\"\n  STR_BOMBARDMENT_SHIELD: \"Bombardıman Kalkanı\"\n  STR_MC_GENERATOR: \"M.K. Üreteci\"\n  STR_MC_LAB: \"M.K. Laboratuvarı\"\n  STR_TRANSMISSION_RESOLVER: \"İleti Çözücü\"\n  STR_SUB_PEN: \"Bot Sığınağı\"\n  STR_USA: \"ABD\"\n  STR_ALASKA: \"ALASKA\"\n  STR_EU_SYNDICATE: \"AVRO-KARTEL\"\n  STR_ARABIAN_BLOC: \"ARAP BLOKU\"\n  STR_EGYPTIAN_CARTEL: \"MISIR KARTELİ\"\n  STR_AFRICA_CORP: \"AFRİKA TOPLULUĞU\"\n  STR_BRAZILIAN_UNION: \"BREZİLYA BİRLİĞİ\"\n  STR_NEW_MEXICO: \"YENİ MEKSİKA\"\n  STR_ASIAN_COALITION: \"ASYA KOALİSYONU\"\n  STR_SCANDINAVIA: \"İSKANDİNAVYA\"\n  STR_NEO_JAPAN: \"NEO-JAPONYA\"\n  STR_FREE_CHINA: \"ÖZGÜR ÇİN\"\n  STR_AUSTRALASIA: \"AVUSTRALASYA\"\n  STR_FED_KOREA: \"KORE FEDERASYONU\"\n  STR_EURASIA_UC: \"AVRASYA\"\n  STR_ICELANDIC_UNION: \"İZLANDA BİRLİĞİ\"\n  STR_TANK: \"Denizaltı Silah Sistemi\"\n  STR_CIVILIAN: \"Sivil\"\n  STR_JAN: \"Oca\"\n  STR_FEB: \"Şub\"\n  STR_MAR: \"Mar\"\n  STR_APR: \"Nis\"\n  STR_MAY: \"May\"\n  STR_JUN: \"Haz\"\n  STR_JUL: \"Tem\"\n  STR_AUG: \"Ağu\"\n  STR_SEP: \"Eyl\"\n  STR_OCT: \"Eki\"\n  STR_NOV: \"Kas\"\n  STR_DEC: \"Ara\"\n  STR_INTERNATIONAL_RELATIONS: \"Uluslararası İlişkiler\"\n  STR_COUNTRY: \"Ülke\"\n  STR_FUNDING: \"Finansman\"\n  STR_CHANGE: \"Değişiklik\"\n  STR_WEAPON_SYSTEMS: \"SİLAH SİSTEMLERİ\"\n  STR_HWPS: \"DSSler\"\n  STR_DAMAGE_UC_: \"HASAR>{ALT}{0}\"\n  STR_AIR_LOCK_UFOPEDIA: \"Hava cebi, denizaltındaki üsse personel ve teçhizatın giriş çıkışını sağlar. Yeni inşa edilen bir üste ilk kurulan tesistir. Hava cebi bölgesi, olası bir düşman saldırısında hücuma maruz kalmaya meyillidir.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Her bir koğuş, azami 50 personele hizmet verebilir. Tesisler temel seviyede ve fonksiyoneldir.\"\n  STR_LABORATORY_UFOPEDIA: \"Tek bir laboratuvar, elli bilim insanı için çalışma ortamı teşkil eder. Laboratuvarlar, madde, biyokimya ve silah araştırmalarına yönelik en son teknolojilerle donatılmışlardır. X-Com, dünya genelinde hem sivil hem de askeri en gelişmiş araştırma laboratuvarlarına erişim yetkisine sahiptir.\"\n  STR_WORKSHOP_UFOPEDIA: \"Atölyeler, laboratuvarlarda geliştirilen en son tasarımların üretiminde gerekli olan her türlü ekipmanla donatılmıştır. Her bir atölye, 50 teknisyen kapasitesine sahiptir ancak üretilen malzemeler de bir miktar yer kaplayacaktır.\"\n  STR_STANDARD_SONAR_UFOPEDIA: \"Standart sonar sistemi, hemen her derinlikte 450 kilometreden fazla etkin menzile sahiptir ve yüzey analizi için de geosenkron uydu ağlarıyla bağlantı halindedir. Her bir tarayıcı, her 30 dakikalık tarama döngüsünde %10 ihtimalle havadaki ya da su altındaki bir aracı tespit edebilir.\"\n  STR_WIDE_ARRAY_SONAR_UFOPEDIA: \"Geniş bant sonar sistemi, her derinlikte 700 kilometreden fazla etkin menzile sahiptir ve yüzey analizi için de geosenkron uydu ağlarıyla bağlantı halindedir. Her bir tarayıcı, her 30 dakikalık tarama döngüsünde %20 ihtimalle havadaki ya da su altındaki bir aracı tespit edebilir.\"\n  STR_TORPEDO_DEFENSES_UFOPEDIA: \"Torpido savunma sistemleri, üsse nüfuz etmeye çalışan düşman denizaltılara karşı korunma sağlar.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"Sığınaklarda bekleyen denizaltılara tahsis edilmiş olanlar da dahil olmak üzere tüm silah sistemleri, teçhizat, cephane, ele geçirilmiş materyal ve Denizaltı Silah Sistemleri, bu depolarda saklanır.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"Canlı ele geçirilen yabancıların muhafazası için özel tesisler gereklidir. Bu tesisler, yaratıkların yaşamsal faaliyetleri için destek sağlar ve muharebe kabiliyetlerini sıfıra indirir. Her bir karantina tesisi, azami 10 yabancı yaşam formu için izole bölümler bulundurur.\"\n  STR_GAUSS_DEFENSES_UFOPEDIA: \"Gaus savunma modülleri, düşman denizaltılarına karşı en güncel ve etkin korunma sistemleridir.\"\n  STR_SONIC_DEFENSES_UFOPEDIA: \"Sonik Osilatör savunma sistemleri, düşmanlara karşı kuvvetli ve etkin korunma sağlar.\"\n  STR_PWT_DEFENSES_UFOPEDIA: \"Darbe Dalga Torpidoları, Yabancı saldırılarına karşı en etkin savunma araçlarıdır. Bu füzeler, bilinen tüm zırhları delebilecek güçte süper yoğun harp başlıklarıyla donatılmışlardır. Ürettikleri manyetik dalgalarla da, elektronik savunma sistemlerini devre dışı bırabilirler.\"\n  STR_BOMBARDMENT_SHIELD_UFOPEDIA: \"Basınçlı Bombardıman Kalkanı, üsse kilitlenmeye çalışan Yabancı denizaltılarına karşı savunma sağlar ve yaklaşan araçları geriye iterek, diğer savunma sistemlerine bir kez daha ateş etmeleri için zaman kazandırır. Pratikte bu, tüm savunma sistemlerinin etkinliğini iki katına çıkartmak anlamına gelir.\"\n  STR_MC_GENERATOR_UFOPEDIA: \"Yabancı botları, canlı yaratıkların varlığını tespit etmek için Moleküler Kontrol teknolojisinden faydalanıyorlar. Negatif M.K. emitörleri, üslerimizi aşılamaz bir kalkanla sararak varlığımızı Yabancılardan gizlemekte faydalı olacaktır.\"\n  STR_MC_LAB_UFOPEDIA: \"Her bir Moleküler Kontrol laboratuvarı, aynı anda on adet akuanotun implantasyonunu ve eğitimini yürütebilecek kapasitede. Implantlar, akuanotların kafatasına cerrahi müdahaleyle yerleştiriliyor ve etkin kullanım için yoğun bir eğitim süreci gerektiriyorlar. Çatışma anında implant yetenekleri, özel moleküler kontrol cihazları yardımıyla kullanılıyor.\"\n  STR_TRANSMISSION_RESOLVER_UFOPEDIA: \"Yabancılar iletişim kurmak için, ördükleri Moleküler Kontrol ağından faydalanıyorlar. İleti Çözücü sayesinde Yabancı botları arasında gidip gelen sinyaller yakalanıyor ve deşifre ediliyor. Böylelikle Yabancı botunun tipi, mürettebatı ve görevi hakkında bilgi edinebiliyoruz.\"\n  STR_SUB_PEN_UFOPEDIA: \"Her bir sığınak, tek bir denizaltıya ev sahipliği yapabilir. Sığınaklarda, X-Com denizaltı filosunun bakımı, ikmali ve tamiri için gerekli tüm tesisler mevcuttur. Bir üste konuşlanmış her bir Uçar Bot için ayrı bir sığınak tahsis edilmesi zorunludur. Bir denizaltı göreve çıkmış olsa bile, tahsis edilen sığınak başka bir Bot tarafından kullanılamaz.\"\n  STR_DART_PISTOL_UFOPEDIA: \"X-Com dart tabancası, 12 atışlık dart şarjörü ile kullanılan, küçük, isabetli ve tesirli bir silah. Ateşleme, cephane yuvasındaki basınçlı gaz kapsülü ile sağlanıyor.\"\n  STR_JET_HARPOON_UFOPEDIA: \"Hem isabetli hem de kuvvetli bu akua-tüfek, 10 atımlık mühürlü paketler halinde üretilen çelik zıpkın oklar fırlatıyor. Her bir ok, gaz haznesini kendi bünyesinde barındırıyor.\"\n  STR_GAS_CANNON_UFOPEDIA: \"Gaz teknoloji ailesinin ağır sıkleti olan bu top, standart, YP ya da fosfor uçlu çelik oklar fırlatabiliyor. Tecrübeli akuanotların gözdesi konumunda bir silah.\"\n  STR_HYDRO_JET_CANNON_UFOPEDIA: \"Bir ağır piyade silahı olan Hidro-Jet Topu, yakıt olarak magnezyum kullanan ufak torpidolar ateşliyor. Güçlü ve tesirli olduğu kadar ağır ve hantal bir silah. Bu nedenle ancak su altında kullanıma uygun.\"\n  STR_TORPEDO_LAUNCHER_UFOPEDIA: \"Gerçek bir ağırsıklet olan bu fırlatıcı, her biri kendi itme sistemiyle donatılmış üç tip torpido ateşleyebiliyor. Tek dezavantajı elle yükleme sistemi olan müthiş bir silah. Desteklediği mühimmat tipleri arasında küçük ve büyük ağır patlayıcılar ve fosfor uçlu torpidolar var. Bunların hepsi su altı kullanıma yönelik.\"\n  STR_GAUSS_PISTOL_UFOPEDIA: \"Gaus tabancası, yeni geliştirilen hızlandırılmış parçacık teknolojisinden faydalanıyor. Hızlı, isabetli ve hem karada hem de su altında çalışabilen bir silah. Gaus teknolojisi, bir önceki savaşta edindiğimiz Plazma teknolojisinin bir uzantısı niteliğinde.\"\n  STR_GAUSS_PISTOL_CLIP_UFOPEDIA: \"Gaus tabancası, yeni geliştirilen hızlandırılmış parçacık teknolojisinden faydalanıyor. Hızlı, isabetli ve hem karada hem de su altında çalışabilen bir silah. Gaus teknolojisi, bir önceki savaşta edindiğimiz Plazma teknolojisinin bir uzantısı niteliğinde.\"\n  STR_GAUSS_RIFLE_UFOPEDIA: \"Gaus tabancasının bir adım ötesindeki Gaus tüfeği, ikiz parçacık hızlandırıcılarıyla ciddi bir yıkım gücüne sahip. Eleryum'la çalışan Plazma sisteminin yerini alan yeni mikro parçacık hızlandırıcıların ürettiği anti-proton akımıyla çalışıyor.\"\n  STR_GAUSS_RIFLE_CLIP_UFOPEDIA: \"Gaus tabancasının bir adım ötesindeki Gaus tüfeği, ikiz parçacık hızlandırıcılarıyla ciddi bir yıkım gücüne sahip. Eleryum'la çalışan Plazma sisteminin yerini alan yeni mikro parçacık hızlandırıcıların ürettiği anti-proton akımıyla çalışıyor.\"\n  STR_HEAVY_GAUSS_UFOPEDIA: \"Ağır Gaus topu, hantal olmakla birlikte son derece etkili bir silah. 3 tane parçacık hızlandırıcıyla donatılmış bu silah neredeyse durdurulamaz güçte. Üretilen anti-proton akımı, bir Galyum Arsenit kabuk içine hapsediliyor ve çarpışma anında patlayarak anti-madde salınımı yapıyor.\"\n  STR_HEAVY_GAUSS_CLIP_UFOPEDIA: \"Ağır Gaus topu, hantal olmakla birlikte son derece etkili bir silah. 3 tane parçacık hızlandırıcıyla donatılmış bu silah neredeyse durdurulamaz güçte. Üretilen anti-proton akımı, bir Galyum Arsenit kabuk içine hapsediliyor ve çarpışma anında patlayarak anti-madde salınımı yapıyor.\"\n  STR_MAGNA_BLAST_GRENADE_UFOPEDIA: \"Bu standart el bombası, gelişmiş ve hassas bir zamanlayıcı içerir.\"\n  STR_DYE_GRENADE_UFOPEDIA: \"Boya bombası, açık arazi çatışmalarında çifte rol üstlenen bir teçhizat. Hem su altında hem de karada kullanılabilen bombalar, içerdiği boyalı maddeyi parçacıklar halinde püskürtebiliyor. Su altında ahtapot mürekkebi gibi yayılan boya, karada da yoğun bir bulut oluşturuyor.\"\n  STR_PARTICLE_DISTURBANCE_GRENADE_UFOPEDIA: \"Harekete duyarlı mayın, sıradan bir el bombası gibi fırlatılarak kullanılır ama tetikleme mekanizması, civarda hareket eden nesnelere duyarlıdır. Bu silahların doğru kullanımı için personelin yetenekli ve iyi eğitilmiş olması şarttır.\"\n  STR_MAGNA_PACK_EXPLOSIVE_UFOPEDIA: \"Normalde bu patlayıcıların sadece istimlak amacıyla kullanılması öneriliyor. Ancak geçmiş tecrübelerimiz, bu güçlü patlayıcıları, yabancıları yuvalandıkları yerlerden çıkartmak için de kullanabileceğimizi göstermiştir. Tesir alanı çok geniş olduğu için, tüm akuanotların güvenli bir mesafeye çekilmiş olduğundan emin olmalısınız.\"\n  STR_PARTICLE_DISTURBANCE_SENSOR_UFOPEDIA: \"Bu yeni cihaz, çeşitli dedektörler ve gelişmiş bilgisayar sistemleri kullanarak hareketli düşman birimlerini tespit etmekte kullanılıyor. Taktik ekranında Devinim Sensörü ikonuna tıklayın. Menüden 'Dev. Sensörü Kullan' komutunu seçin. Sensör ekranının ortasında, askerin yüzünün dönük olduğu istikameti gösteren bir ok göreceksiniz (yukarısı Kuzeyi gösterir). Yanıp sönen noktalar, yakın zamanda hareket etmiş olan birimleri temsil eder. Büyük boyutlu veya hızlı hareket eden birimlere ait noktalar daha büyük görüntülenir. Hareketsiz birimler tespit edilemeyecektir.\"\n  STR_MEDI_KIT_UFOPEDIA: \"Bunu kullanmak için, yüzünüzü tedaviye ihtiyaç duyan askere dönmeniz, eğer asker bilincini kaybetmişse, vücudunun üzerinde durmanız gerekir. {NEWLINE}TEDAVİ> Ağır yaralı organlar kırmızı renkte gösterilir. Yaralı bölgeye tıklayın ve 'Tedavi' butonuna basın. Hayati yaralardan bir tanesi iyileştirilecek ve askerin sağlığı bir miktar yerine gelecektir.{NEWLINE}UYARICI> Bu seçenek, kaybedilen enerjinin yeniden kazandırılması ve bilincini yitirmiş askerlerin uyandırılması için kullanılır. Baygın bir askere tedavi uygulamak için doğrudan vücudun üzerinde durmanız gerekir.{NEWLINE}AĞRI KESİCİ> Bu seçenek, yaralı askerlerin moralini yükseltmeye yarar.\"\n  STR_MC_DISRUPTOR_UFOPEDIA: \"M.K. teknolojisinin zirvesi olan bu cihaz, sadece M.K. eğitimi almış askerler tarafından kullanılabilir. Bozucu ikonuna tıklayın, saldırı tipini belirleyin ve imleci kullanarak hedefinizi seçin. İki farklı bozucu saldırısı mevcuttur:{NEWLINE}İMPLANT KİLİTLE> Bu saldırı başarılı olursa, hedef şaşkınlığa ve paniğe kapılabilir.{NEWLINE}MOLEKÜLER KONTROL> Bu saldırı başarılı olursa, düşman ünitesinin kontrolü size geçer.\"\n  STR_THERMAL_TAZER_UFOPEDIA: \"Göğüs göğüse çarpışma için tasarlanmış bu silah, canlı bir organizmayı dondurarak etkisiz hale getirmekte etkilidir.\"\n  STR_VIBRO_BLADE_UFOPEDIA: \"Vibrobıçak, dakikada 6000 devir üzerinde bir hızla dönen, titanyumdan yapılmış uzun ve keskin bir uca sahip. En sağlam dalış zırhını bile delebilecek kadar kuvvetli. Kullandığı güç kaynağı, bir Yabancı icadı. Benzer bir silah üretme çabalarımız şu ana kadar sonuçsuz kaldı. Ürettiğimiz bıçaklar ya çok yavaş dönüyor ya da basınç altında infilak ediyor.\"\n  STR_THERMIC_LANCE_UFOPEDIA: \"Termik Mızrak, Vibrobıçak teknolojisinin bir uzantısı niteliğinde. Zerbit güç kaynağı sayesinde çok yüksek hızla dönen ve aşırı derece ısıtılan bıçak, standart zırhları tereyağı gibi delebiliyor.\"\n  STR_HEAVY_THERMIC_LANCE_UFOPEDIA: \"Ağır Termik Mızrak, standart TM'nin daha güçlü bir versiyonu. Donanımındaki çifte ısı kaynağı ve son derece yüksek dönüş hızı, neredeyse tüm zırh materyalleri karşısında durdurulamaz bir güce sahip olmasını sağlıyor.\"\n  STR_SONIC_CANNON_UFOPEDIA: \"Sonik silah ailesinin en etkili üyesi olan Sonik Top, yüksek frekans aralığına sahip bir osilatörle ve geniş bir yankı odasıyla donatılmış. Ultrasonik dalga modülasyonu sayesinde çok daha güçlü bir sonik şok dalgası üretebiliyor.\"\n  STR_CANNON_POWER_CLIP_UFOPEDIA: \"Az miktarda Zerbit içeren bu ufak cihaz, Sonik Top için mühimmat olarak kullanılıyor.\"\n  STR_SONIC_BLASTA_RIFLE_UFOPEDIA: \"Daha kuvvetli bir Sonik cihaz olan bu silah, karbon çelik zırh karşısında bile etkili. Dalga yayıcı modülün süper iletken bir amplifikatör ile desteklenmesi, silahın gücünü daha da arttırıyor.\"\n  STR_BLASTA_POWER_CLIP_UFOPEDIA: \"Az miktarda Zerbit içeren bu küçük nesne, oldukça güçlü bir silah olan Sonik Tüfek için güç kaynağı işlevi görüyor.\"\n  STR_SONIC_PISTOL_UFOPEDIA: \"Sonik tabanca, ürettiği ultrasonik ses dalgalarıyla kemikleri bile saniyeler içinde eritebilecek güçte bir silah. Yaydığı ultrasonik dalgalar, insan kulağının işitemeyeceği bir frekans aralığında.\"\n  STR_PISTOL_POWER_CLIP_UFOPEDIA: \"Yabancı yapımı Sonik Tabanca için batarya. Yabancıların kullandığı tüm diğer güç kaynakları gibi Zerbit içeriyor.\"\n  STR_DISRUPTOR_PULSE_LAUNCHER_UFOPEDIA: \"Güdümlü 'Bozgun Roketleri'ni ateşlemekte kullanılan, sadece su altında çalışan bir Yabancı silahı. Tetiğe bastığınızda silah, roketin izleyeceği güzergahı belirleyen birden fazla ara nokta seçebilirsiniz. Yeterince ara nokta tanımladıktan sonra \\\"ateşle\\\" butonuna basın.\"\n  STR_DISRUPTOR_AMMO_UFOPEDIA: \"Kendi bilgisayarlı güdüm sistemine sahip olan Bozgun-Darbe Roketi. Ateşlemek için bir Bozgun-Darbe Roketatarı kullanmak gerekiyor.\"\n  STR_THERMAL_SHOK_LAUNCHER_UFOPEDIA: \"Kimyasal donducu bombaları ateşleyen küçük bir Termal Şok roketatarı. Yabancıları canlı ele geçirmek için çok kullanışlı.\"\n  STR_THERMAL_SHOK_BOMB_UFOPEDIA: \"Yabancılar, Termal Şok bombasını canlı insan ele geçirmek için kullanıyorlar ama bu silahı pek çok Yabancı ırkına karşı da kullanmamız mümkün. Ateşlemek için bir Termal Şok Roketatarı gerekiyor.\"\n  STR_SONIC_PULSER_UFOPEDIA: \"Standart bir el bombasıyla aynı şekilde kullanılan, ancak katbekat daha güçlü bir silah. Tetiklendiğinde, her yönde eş zamanlı yayılan bir sonik darbe üretiyor.\"\n  STR_MC_READER_UFOPEDIA: \"Yabancıların bedenlerinde cerrahi müdahaleyle yerleştirilmiş küçük cihazlar bulduk. Bunlar, Aquatoidler tarafından tasarlanmış Kontrol İmplantları. Savaş alanında, çok uzak mesafelerden bile sürekli olarak veri akışı sağlayabiliyorlar. Moleküler Kontrol Okuyucu, bu M.K. İmplantlarından direkt olarak bilgi çekebilen bir iletişim aracı. X-Com unsurları, çatışma anında bu aracı kullanarak herhangi bir Yabancı hakkında detaylı bilgi edinebilir. 'Kullan' seçeneğine tıkladıktan sonra imleci kullanarak hedefi seçmeniz yeterli.\"\n  STR_SURVEY_SHIP: \"Tetkik Gemisi\"\n  STR_ESCORT: \"Muhafız\"\n  STR_CRUISER: \"Kruvazör\"\n  STR_HEAVY_CRUISER: \"Ağır Kruvazör\"\n  STR_HUNTER: \"Avcı\"\n  STR_BATTLESHIP: \"Muharip\"\n  STR_DREADNOUGHT: \"Dretnot\"\n  STR_FLEET_SUPPLY_CRUISER: \"Filo İkmal Gemisi\"\n  MAP_SEABED: \"Deniz Tabanı\"\n  MAP_PIPES: \"Araştırma Tesisi\"\n  MAP_PLANE: \"Çakılmış Uçak\"\n  MAP_ATLAN: \"Atlantis\"\n  MAP_MU: \"Maya Tapınağı\"\n  MAP_GAL: \"Batık Kalyon\"\n  MAP_MSUNK: \"Batık Yolcu Gemisi\"\n  MAP_VOLC: \"Volkanik\"\n  MAP_CORAL: \"Mercan\"\n  MAP_PORT: \"Liman\"\n  MAP_ISLAND: \"Ada\"\n  MAP_CARGO: \"Kargo Gemisi\"\n  MAP_LINERT: \"Yolcu Gemisi K1\"\n  MAP_LINERB: \"Yolcu Gemisi K2\"\n  MAP_ALART: \"Yapıt K1\"\n  MAP_GRUNGE: \"Yapıt K2\"\n  MAP_ENTRY: \"Koloni K1\"\n  MAP_A_BASE: \"Koloni K2\"\n  MAP_ALSHIP: \"T'leth K1\"\n  MAP_LEVEL: \"T'leth K2\"\n  MAP_CRYPT: \"T'leth K3\"\n  MAP_XBASES: \"X-Com Üssü\"\n  STR_MIXED_CREW: \"Karışık Mürettebat\"\n  STR_MIXED_CREW_2: \"Karışık Mürettebat 2\"\n  STR_RATING: \"DEĞERLENDİRME> {0}\"\n  STR_RATING_TERRIBLE: \"REZALET!\"\n  STR_RATING_POOR: \"ZAYIF!\"\n  STR_RATING_OK: \"GEÇER\"\n  STR_RATING_GOOD: \"İYİ!\"\n  STR_RATING_EXCELLENT: \"MÜKEMMEL!\"\n  STR_SCORE: \"SKOR\"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"X-COM AYLIK RAPOR\"\n  STR_MONTH: \"Ay> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"Finansör kurumlar komitesi, genel olarak şu ana kadarki gidişatınızdan memnun.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"Finansör kurumlar komitesi, mükemmel gidişatınızdan son derece memnun. Aynen devam.\"\n  STR_COUNCIL_IS_DISSATISFIED: \"Finansör kurumlar komitesi, performansınızdan hoşnut değil. Yabancı tehdidiyle daha etkin bir mücadele yürütmeye başlamadığınız taktirde, projenin iptal edilmesi söz konusu olabilir.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"Ne yazık ki Yabancı istilasıyla mücadelede başarılı olamadınız ve finansör kurumlar komitesi X-Com projesinin finansmanını kesmeye karar verdi. Her bir kurum, sorunu kendi uygun gördüğü biçimde çözmeye çalışacak. Şimdi geride kalan tek umut, bu kadim güçlerle bir anlaşma sağlanması ve genel halkın denizden gelen ziyaretçilerle mutabakata varması.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} yerel tehditle mücadelede gösterdiğiniz başarıdan çok memnun ve finansal desteğini arttırma kararı aldı.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} yerel Yabancı istilasıyla mücadelede katettiğiniz yoldan çok memnun ve finansal desteklerini arttırma kararı aldılar.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} ve {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} denizlerindeki Yabancı faaliyetleriyle mücadelede yetersiz kaldığınız kanaatinde ve finansal desteğini azaltma kararı aldı.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} denizlerindeki Yabancı faaliyetleriyle mücadelenizden hoşnut değil ve finansal desteğini azaltma kararı aldı.\"\n  STR_KNOTS: \"{0} deniz mili\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} Yabancı güçleriyle dayanışma anlaşması imzaladı ve X-Com projesinden finansal desteğini çekti.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} Yabancı güçleriyle dayanışma anlaşması imzaladı ve X-Com projesinden finansal desteğini çekti.\"\n  STR_MONTHLY_RATING: \"Aylık Değerlendirme> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Finansman değişikliği> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"Finansör kurumlar, mali durumunuzdan hoşnut değil. Borçlarınızı $1 milyon seviyesinin altına çekemezseniz X-Com projesi sonlandırılacak.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"PARÇACIKALTI İLETİLER ÇÖZÜLDÜ\"\n  STR_CRAFT_TYPE: \"BOT TİPİ\"\n  STR_RACE: \"IRK\"\n  STR_MISSION: \"GÖREV\"\n  STR_ZONE: \"BÖLGE\"\n  STR_ALLOCATE_RESEARCH: \"Araştırma Başlat\"\n  STR_ALLOCATE_MANUFACTURE: \"Üretim Başlat\"\n  STR_AZORES: \"Azorlar\"\n  STR_REYKJAVIK: \"Reykjavik\"\n  STR_BERMUDA: \"Bermuda\"\n  STR_NEW_YORK: \"New York\"\n  STR_BOSTON: \"Boston\"\n  STR_FORT_SEVERN: \"Fort Severn\"\n  STR_DAKAR: \"Dakar\"\n  STR_RECIFE: \"Recife\"\n  STR_ACCRA: \"Akra\"\n  STR_ASCENSION_ISLAND: \"Ascension Adası\"\n  STR_TRINIDADE_ISLAND: \"Trinidad Adası\"\n  STR_FALKLAND_ISLAND: \"Falkland Adası\"\n  STR_CANARY_ISLANDS: \"Kanarya Adaları\"\n  STR_ANCHORAGE: \"Anchorage\"\n  STR_ST_LAWRENCE_ISLAND: \"St. Lawrence Adası\"\n  STR_SAN_FRANCISCO: \"San Francisco\"\n  STR_MIDWAY_ISLAND: \"Midway Adası\"\n  STR_VANCOUVER: \"Vancouver\"\n  STR_TASMANIA: \"Tasmanya\"\n  STR_HAWAII: \"Hawaii\"\n  STR_FIJI: \"Fiji\"\n  STR_TONGA: \"Tonga\"\n  STR_EASTER_ISLAND: \"Paskalya Adası\"\n  STR_GALAPAGOS_ISLAND: \"Galapagos Adası\"\n  STR_WELLINGTON: \"Wellington\"\n  STR_SOLOMON_ISLAND: \"Solomon Adası\"\n  STR_CRETE: \"Girit\"\n  STR_LISBON: \"Lizbon\"\n  STR_PORT_SAID: \"Port Said\"\n  STR_MARSEILLES: \"Marsilya\"\n  STR_TRIPOLI: \"Trablus\"\n  STR_MANILA: \"Manila\"\n  STR_HONG_KONG: \"Hong Kong\"\n  STR_SINGAPORE: \"Singapur\"\n  STR_BANGKOK: \"Bangkok\"\n  STR_DARWIN: \"Darwin\"\n  STR_BOMBAY: \"Mumbai\"\n  STR_SAYCHELLES_ISLAND: \"Seyşeller\"\n  STR_MALDIVE_ISLAND: \"Maldivler\"\n  STR_SRI_LANKA: \"Sri Lanka\"\n  STR_MAURITIUS: \"Mauritius\"\n  STR_TOKYO: \"Tokyo\"\n  STR_SHANGHAI: \"Şanghay\"\n  STR_VLADIVOSTOK: \"Vladivostok\"\n  STR_LONDON: \"Londra\"\n  STR_FAEROE_ISLAND: \"Faroe Adası\"\n  STR_ABERDEEN: \"Aberdeen\"\n  STR_OSLO: \"Oslo\"\n  STR_JAMAICA: \"Jamaika\"\n  STR_PANAMA: \"Panama\"\n  STR_MIAMI: \"Miami\"\n  STR_PSI_TRAINING: \"M.K. Eğitimi\"\n  STR_PSIONIC_TRAINING: \"MOLEKÜLER KONTROL EĞİTİMİ\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Kalan M.K. kapasitesi> {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"M.K.{NEWLINE}Direnci\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"M.K. Becerisi{NEWLINE}/Gelişim\"\n  STR_IN_TRAINING: \"Eğitimde?{NEWLINE}\"\n  STR_TARGETTED_BY: \"HEDEFLEYEN:\"\n  STR_WEAPONS_CREW_HWPS: \"SİLAHLAR/{NEWLINE}MÜRETTEBAT/DSSler\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"Yakıt azaldı,{NEWLINE}araç üsse dönüyor.\"\n  STR_SOLDIER_LIST: \"Akuanot Listesi\"\n  STR_RANK_: \"RÜTBE> {ALT}{0}\"\n  STR_MISSIONS: \"GÖREVLER> {ALT}{0}\"\n  STR_KILLS: \"İMHA> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"MALÜLİYET> {ALT}{0}\"\n  STR_TIME_UNITS: \"ZAMAN ÜNİTESİ\"\n  STR_STAMINA: \"DAYANIKLILIK\"\n  STR_HEALTH: \"SAĞLIK\"\n  STR_BRAVERY: \"CESARET\"\n  STR_REACTIONS: \"TEPKİ\"\n  STR_FIRING_ACCURACY: \"ATIŞ İSABETLİLİĞİ\"\n  STR_THROWING_ACCURACY: \"FIRLATMA İSABETLİLİĞİ\"\n  STR_STRENGTH: \"KUVVET\"\n  STR_PSIONIC_STRENGTH: \"M.K. DİRENCİ\"\n  STR_PSIONIC_SKILL: \"M.K. BECERİSİ\"\n  STR_NEW_RANK: \"YENİ RÜTBE\"\n  STR_PROMOTIONS: \"Terfiler\"\n  STR_SOLDIERS_UC: \"AKUANOTLAR\"\n  STR_COELACANTH_GAS_CANNON_UFOPEDIA: \"Otomatik DSS'ler yüksek manevra kabiliyetine ve güçlü zırha sahiptir. Her derinlikte ağır silah desteği sağlayabilirler. Stoklarınızda yeterli mühimmat olduğu sürece DSS'ler otomatik olarak yeniden doldurulur.\"\n  STR_COELACANTH_AQUA_JET_UFOPEDIA: \"Akua-Jet torpidolarıyla donatılmış bir denizaltı. Bu silah sistemi sadece su altında görev yapabilir. Stoklarınızda yeterli miktarda Akua-Jet torpido bulundurmaya dikkat edin.\"\n  STR_COELACANTH_GAUSS_UFOPEDIA: \"DSS'ler için Gaus teknolojisiyle üretilmiş güçlü bir silah sistemi. Tescilli X-Com teknolojileri sayesinde önceki modellere nazaran daha yüksek atış gücü sunuyor.\"\n  STR_DISPLACER_SONIC_UFOPEDIA: \"Yabancı teknolojisi, DSS kavramına yeni bir tanım getirdi. Ion Deplasörleri sayesinde DSS kullanımı artık sadece kara ve deniz zeminiyle kısıtlı değil. Sonik silahlar da çatışmada önemli bir üstünlük sağlıyor.\"\n  STR_DISPLACER_PWT_UFOPEDIA: \"Bu DSS, su altı kullanımına yönelik Darbe Dalga silahları taşıyor. Mühimmat olarak yeterince DDT ürettiğinize emin olun. Ateşlemek için yeterince 'ara nokta' tanımlayın ve ateşleme butonuna basın.\"\n  STR_ALIEN_PROBE_MISSION: \"Yabancı Keşif Harekatı\"\n  STR_ALIEN_INTERDICTION: \"Yabancı Tecrit Harekatı\"\n  STR_ALIEN_RESOURCE_RAID: \"Yabancı Yağmalama Harekatı\"\n  STR_ALIEN_INFILTRATION: \"Yabancı Sızma Harekatı\"\n  STR_ALIEN_BASE: \"Yabancı Koloni Yayılımı\"\n  STR_ALIEN_SURFACE_ATTACK: \"Yabancı Yüzey Taarruzları\"\n  STR_ALIEN_RETALIATION: \"Yüzer Üsse Taarruz\"\n  STR_ALIEN_SUPPLY: \"Koloni İkmal Görevleri\"\n  STR_ALIEN_PROBE_MISSION_UFOPEDIA: \"Yabancı Keşif Harekatı, bölgedeki deniz yatağı, kaynaklar, gemi ve uçak rotaları hakkında bilgi toplamaya yöneliktir. Bu harekatlarda görevlendirilen Yabancı Botları kendi başlarına büyük bir tehdit oluşturmazlar, ancak birden bire yoğun faaliyet görülecek bölgelere işaret ediyor olabilirler.\"\n  STR_ALIEN_INTERDICTION_UFOPEDIA: \"Yabancılar, prensip itibarıyla, gözlerini diktikleri bölgeleri denetim altında tutmak ve asıl görevlere başlamadan önce bu bölgelerin güvenliğini sağlamak için çalışmalarda bulunuyorlar. Daha sonra taarruz etmeyi planladıkları belli bölgelere iniş yapıyor ve bir sonraki faaliyetleri için zemin hazırlıyorlar.\"\n  STR_ALIEN_RESOURCE_RAID_UFOPEDIA: \"Yabancı stratejisinin anahtar öğelerinden biri de gemi batırmak ve uçak düşürmek. Üretim için gerekli materyallerin ele geçirilmesi, başlıca Yabancı faaliyetlerinden biri ve bu saldırgan hareketler de doğrudan bu amaca yönelik. Yabancılar aynı zamanda jeotermal ya da maden arama çalışmaları yürütülen bölgeleri de yağmalıyor ve mineraller, rafine metaller ya da insan eliyle üretilmiş diğer malzemeleri ele geçirmeye çalışıyorlar.\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"Bu faaliyetler, Yabancılarla, kuruluşlar ya da hükümetler arasında en üst düzeyde resmi temaslarla sonuçlanabilir. İlgili kurumun civarındaki sularda çok yoğun Yabancı Bot aktivitesi, bu harekatın doruk noktasına işaret eder. Yabancılar, sağlayacakları temaslar sonucunda, üstün teknoloji ve bilgi vaadlerinde bulunarak hükümet ya da kuruluşlarla anlaşma imzalamayı hedefleyeceklerdir. Bu tipte Yabancı faaliyetleri, X-Com için çok ciddi bir tehdit oluşturur. Eğer bir kuruluş ya da hükümet, Yabancılarla işbirliği içine girecek olursa, sağladıkları finansman da kesilecektir.\"\n  STR_ALIEN_BASE_UFOPEDIA: \"Yabancılar, medeniyete uzak noktalarda gizli su altı üsleri inşa edeceklerdir. Bir kaç keşif uçuşu ardından koloninin inşası başladığında bölgede yoğun Yabancı Botu faaliyeti gözlemlenebilir. Bu kolonilerin laboratuvarlar, klonlama merkezleri ve hem insanlar hem de Yabancılar üzerinde deneyler için donatılmış cerrahi tesisler içereceğini biliyoruz. Yabancı kolonilerinin bulunduğu bölgelerde Yabancı Botları olmasa da artan Yabancı aktivitesi göze çarpacaktır. Yerini tahmin ettiğiniz bir koloniyi tespit edebilmek için, X-Com botlarını bir kaç saat sürecek devriye uçuşlarıyla görevlendirmelisiniz.\"\n  STR_ALIEN_SURFACE_ATTACK_UFOPEDIA: \"Yabancılar, üreme amacıyla ya da korkunç deneylerinde kullanmak için insan bedenlerine ihtiyaç duyduklarında limanlara, adalara ya da yolcu gemilerine terör saldırılarında bulunuyorlar. Bu saldırılar, doğrudan sivillere yönelik bir tehdit oluşturuyor.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"X-Com avcı botları, Yabancı gemilerini batırmakta üstün başarı gösterdiklerinde Yabancılar missilleme olarak X-Com üslerine doğrudan saldırı düzenlemeye karar verebilirler. Ancak Yabancıların bir X-Com üssüne saldırabilmek için önce üssün yerini tespit etmeleri gereklidir ve düşman botlar üslerden uzak tutulduğu sürece saldırı tehlikesi düşük kalacaktır.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"Bir Yabancı kolonisi inşa edildiğinde, özel ikmal gemileri düzenli olarak ikmal uçuşları yapacaklardır. Bu denizaltılardan birinin iniş yaptığını tespit ettiğinizde, civarlarda bir Yabancı kolonisi olduğuna kesin gözüyle bakabilirsiniz.\"\n  STR_SURVEY_SHIP_UFOPEDIA: \"Bu küçük denizaltı, keşif ve araştırma için görevlendiriliyor. Bir yabancı harekatının başlangıcında, daha büyük gemilere öncülük ediyor.\"\n  STR_ESCORT_UFOPEDIA: \"Kendi başınayken fazla tehdit oluşturmayan, refakat amaçlı orta büyüklükte bir gemi. Daha büyük gemilerin ve yabancı faaliyetlerinde artışın öncüsü niteliğinde.\"\n  STR_CRUISER_UFOPEDIA: \"Yabancı filosunun ana unsuru olan Kruvazör, her tür Yabancı harekatında kullanılabilen tehlikeli bir gemi.\"\n  STR_HEAVY_CRUISER_UFOPEDIA: \"Ağır Kruvazör, normal kruvazörden çok daha güçlü, daha büyük silahlara ve itme sistemlerine sahip bir gemi. Ağır Kruvazör, büyük miktarlarda mineral ve teçhizat ele geçirmeye yönelik harekatlarda kullanılıyor.\"\n  STR_HUNTER_UFOPEDIA: \"Bu araç, insanlar üzerinde deney ve cerrahi uygulamalarında kullanılan bir ameliyat odası içeriyor. Kurbanlar bu odalarda en korkunç işkencelere maruz kalıyor. Deneklerin beyinleri işlenmek üzere çıkartılıp depolanıyor.\"\n  STR_BATTLESHIP_UFOPEDIA: \"Yabancıların elindeki en agresif gemi olan Muharip, mevcut tüm Yabancı teknolojilerini içeriyor. Her türlü taarruz harekatı için bir merkez üssü gibi davranacak tesislerle ve çok çeşitli silahlarla donatılmış.\"\n  STR_DREADNOUGHT_UFOPEDIA: \"Dretnot, her tür Yabancı teknolojisiyle ve korkunç bir ateş gücüyle donatılmış ileri düzeyde bir birlik nakliye aracı. Kuvvetli ve dayanıklı bir tehdit.\"\n  STR_FLEET_SUPPLY_CRUISER_UFOPEDIA: \"İkmal gemileri, yeni Yabancı kolonilerinin inşasında ve mevcut kolonilerin tedarik faaliyetlerinde görevlendirilir. Bu gemilerde, Yabancı besin konteynerleri, DNA örnekleri, fetüsler ve diğer biyolojik bileşenler bulunur.\"\n  STR_DISMANTLE: \"İstimlak\"\n  STR_FACILITY_IN_USE: \"AKUA-YUVA KULLANIMDA\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"BU AKUA-YUVA YIKILAMAZ!{SMALLLINE}Tüm üs yuvaları, hava cebiyle bağlantılı olmalıdır.\"\n  STR_TRANSFER_ITEMS_TO: \"{0} üssüne transferi onaylayın\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"TRANSFER İÇİN KARANTİNA ALANI YOK!{SMALLLINE}Canlı ele geçirilmiş Yabancıların hayatta tutulabilmesi için bir karantina tesisi zorunludur.\"\n  STR_AMOUNT_AT_DESTINATION: \"VARIŞ MERKEZİNDEKİ{NEWLINE}MİKTAR\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"Ele geçirilen Yabancı, karantina tesisi olmadığı için öldü\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"YETERLİ YAŞAM ALANI YOK!{SMALLLINE}Varış üssünde, araca tahsis edilmiş personeli ağırlayabilecek kapasitede yaşam alanı mevcut değil.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"YETERLİ DEPO ALANI YOK!{SMALLLINE}Varış üssünde, araca tahsis edilmiş levazımatı depolamaya yetecek kadar boş alan yok.\"\n  STR_ITEMS_ARRIVING: \"Teslimat\"\n  STR_DESTINATION_UC: \"HEDEF\"\n  STR_DART_PISTOL: \"Dart Tabancası\"\n  STR_DART_POD: \"Dart Şarjörü\"\n  STR_JET_HARPOON: \"Jet Zıpkını\"\n  STR_HARPOON_POD: \"Zıpkın Şarjörü\"\n  STR_GAS_CANNON: \"Gaz Topu\"\n  STR_GC_AP_AMMO: \"GT-ZD Oklar\"\n  STR_GC_HE_AMMO: \"GT-KP Oklar\"\n  STR_GC_P_AMMO: \"GT-Fosfor Okları\"\n  STR_HYDRO_JET_CANNON: \"Hidro-Jet Topu\"\n  STR_HJC_AP_AMMO: \"HJ-ZD Mühimmat\"\n  STR_HJC_HE_AMMO: \"HJ-KP Mühimmat\"\n  STR_HJC_P_AMMO: \"HJ-F Mühimmat\"\n  STR_TORPEDO_LAUNCHER: \"Torpido Tüpü\"\n  STR_SMALL_TORPEDO: \"Küçük Torpido\"\n  STR_LARGE_TORPEDO: \"Büyük Torpido\"\n  STR_PHOSPHOROUS_TORPEDO: \"Fosfor Torpidosu\"\n  STR_MAGNA_BLAST_GRENADE: \"Dev Yumruk El Bombası\"\n  STR_DYE_GRENADE: \"Boya Bombası\"\n  STR_PARTICLE_DISTURBANCE_GRENADE: \"Parçacık Devinim El Bombası\"\n  STR_MAGNA_PACK_EXPLOSIVE: \"Dev Yumruk Patlayıcı Paketi\"\n  STR_PARTICLE_DISTURBANCE_SENSOR: \"Parçacık Devinim Sensörü\"\n  STR_MEDI_KIT: \"İlk Yardım Çantası\"\n  STR_MC_DISRUPTOR: \"M.K. Bozucu\"\n  STR_THERMAL_TAZER: \"Termal Tazer\"\n  STR_GAUSS_PISTOL: \"Gaus Tabancası\"\n  STR_GAUSS_PISTOL_CLIP: \"Gaus Tabanca Şarjörü\"\n  STR_GAUSS_RIFLE: \"Gaus Tüfeği\"\n  STR_GAUSS_RIFLE_CLIP: \"Gaus Tüfek Şarjörü\"\n  STR_HEAVY_GAUSS: \"Ağır Gaus\"\n  STR_HEAVY_GAUSS_CLIP: \"Ağır Gaus Şarjörü\"\n  STR_SONIC_CANNON: \"Sonik Top\"\n  STR_CANNON_POWER_CLIP: \"Top Şarjörü\"\n  STR_SONIC_BLASTA_RIFLE: \"Sonik İnfilak Tüfeği\"\n  STR_BLASTA_POWER_CLIP: \"Sonik İnfilak Şarjörü\"\n  STR_SONIC_PISTOL: \"Sonik Tabanca\"\n  STR_PISTOL_POWER_CLIP: \"Sonik Tabanca Şarjörü\"\n  STR_DISRUPTOR_PULSE_LAUNCHER: \"Bozgun-Darbe Roketatarı\"\n  STR_DISRUPTOR_AMMO: \"Bozgun-Darbe Roketi\"\n  STR_THERMAL_SHOK_LAUNCHER: \"Termal Şok Fırlatıcı\"\n  STR_THERMAL_SHOK_BOMB: \"Termal Şok Bombası\"\n  STR_SONIC_PULSER: \"Sonik Bomba\"\n  STR_ZRBITE: \"Zerbit\"\n  STR_MC_READER: \"M.K. Okuyucu\"\n  STR_VIBRO_BLADE: \"Vibro Bıçak\"\n  STR_THERMIC_LANCE: \"Termik Mızrak\"\n  STR_HEAVY_THERMIC_LANCE: \"Ağır Termik Mızrak\"\n  STR_AQUATOID_CORPSE: \"Akuatoid Cesedi\"\n  STR_GILLMAN_CORPSE: \" Solungaçadam Cesedi\"\n  STR_LOBSTERMAN_CORPSE: \"Istakozadam Cesedi\"\n  STR_TASOTH_CORPSE: \"Tasot Cesedi\"\n  STR_CALCINITE_CORPSE: \"Kalsinit Cesedi\"\n  STR_DEEP_ONE_CORPSE: \"Diptengelen Cesedi\"\n  STR_BIODRONE_CORPSE: \"Biyodron Cesedi\"\n  STR_TENTACULAT_CORPSE: \"Tentakülat Cesedi\"\n  STR_TRISCENE_CORPSE: \"Trisen Cesedi\"\n  STR_HALLUCINOID_CORPSE: \"Halüsinoid Cesedi\"\n  STR_XARQUID_CORPSE: \"Zarkid Cesedi\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"DSS'yi donatmak için yeterli cephane yok{SMALLLINE}Her DSS {0} {1} gerektirir.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Takımı tamamen donatmak için yeterli teçhizat yok\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"{1}{NEWLINE}üretebilmek için öncelikle{NEWLINE}{0}{NEWLINE}araştırmasını tamamlamalısınız.\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"Yabancılar, savunmasız {0} üssünü imha etti\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"X-Com devriyeleri, {0} sınırları içinde bir Yabancı kolonisi tespit etti\"\n  STR_STANDOFF: \"TAKİP\"\n  STR_CAUTIOUS_ATTACK: \"TEMKİNLİ SALDIRI\"\n  STR_STANDARD_ATTACK: \"STANDART SALDIRI\"\n  STR_AGGRESSIVE_ATTACK: \"AGRESİF SALDIRI\"\n  STR_DISENGAGING: \"GERİ ÇEKİLME\"\n  STR_UFO_HIT: \"YABANCI BOTU İSABET ALDI!\"\n  STR_UFO_CRASH_LANDS: \"YABANCI BOTU DÜŞÜRÜLDÜ!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Sadece Takip Mesafesinde Küçült\"\n  STR_UFO_RETURN_FIRE: \"YABANCI BOTU KARŞI ATEŞ AÇTI!\"\n  STR_INTERCEPTOR_DAMAGED: \">>>UÇAR BOT HASAR GÖRDÜ<<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>>UÖAR BOT İMHA EDİLDİ<<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"YABANCI UÇAR BOTU KAÇIYOR!\"\n  STR_LONG_RANGE_DETECTION: \"Geniş bant Tarama\"\n  STR_STORES_UC: \"DEPO\"\n  STR_DIFFICULTY_LEVEL: \"Zorluk Seviyesi\"\n  STR_INTERCEPT: \"TAKİP\"\n  STR_BASES: \"ÜSLER\"\n  STR_GRAPHS: \"GRAFİKLER\"\n  STR_UFOPAEDIA_UC: \"UFOPEDİ\"\n  STR_OPTIONS_UC: \"AYARLAR\"\n  STR_FUNDING_UC: \"FİNANSMAN\"\n  STR_5_SECONDS: \"5 Sn.\"\n  STR_1_MINUTE: \"1 Dk.\"\n  STR_5_MINUTES: \"5 Dk.\"\n  STR_30_MINUTES: \"30 Dk.\"\n  STR_1_HOUR: \"1 Saat\"\n  STR_1_DAY: \"1 Gün\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"X-Com Performans Cetveli\"\n  STR_ENTER_NAME: \"İsim Girin\"\n  STR_PERFORMANCE_RATING: \"Performans Değerlendirmesi\"\n  STR_VICTORY_DATE: \"Zafer Tarihi\"\n  STR_CHEMICAL_FLARE: \"Kimyevi Fişek\"\n  STR_CHEMICAL_FLARE_UFOPEDIA: \"Bu küçük cihaz, hem karada hem de su altında parlak bir ışık saçar. Gece görevlerinde veya derin denizlerde, civardaki düşman unsurları tespit etmek için kullanabilirsiniz.\"\n  STR_MONTHLY_COSTS: \"Aylık Maliyet\"\n  STR_CRAFT_RENTAL: \"Uçar Bot Kirası\"\n  STR_SALARIES: \"Maaşlar\"\n  STR_BASE_MAINTENANCE: \"Üs bakımı\"\n  STR_COST_PER_UNIT: \"Maliyet/Birim\"\n  STR_QUANTITY: \"Miktar\"\n  STR_TOTAL: \"Toplam\"\n  STR_IN_PSIONIC_TRAINING: \"M.K. İmplantasyonunda\"\n  STR_FRONT_ARMOR: \"Ön Zırh\"\n  STR_LEFT_ARMOR: \"Sol Zırh\"\n  STR_RIGHT_ARMOR: \"Sağ Zırh\"\n  STR_REAR_ARMOR: \"Arka Zırh\"\n  STR_UNDER_ARMOR: \"Alt Zırh\"\n  STR_ROUNDS: \"MERMİ\"\n  STR_UNIT: \"ÜNİTE> {0}\"\n  STR_ENERGY: \"ENERJİ\"\n  STR_MORALE: \"MORAL\"\n  STR_ARMOR_: \"ZIRH> {0}\"\n  STR_FRONT_ARMOR_UC: \"ÖN ZIRH\"\n  STR_LEFT_ARMOR_UC: \"SOL ZIRH\"\n  STR_RIGHT_ARMOR_UC: \"SAĞ ZIRH\"\n  STR_REAR_ARMOR_UC: \"ARKA ZIRH\"\n  STR_SKILLS: \"YETENEK> {0}\"\n  STR_LEVEL: \"SEVİYE>{0}\"\n  STR_HEAD: \"BAŞ\"\n  STR_TORSO: \"GÖVDE\"\n  STR_RIGHT_ARM: \"SAĞ KOL\"\n  STR_LEFT_ARM: \"SOL KOL\"\n  STR_RIGHT_LEG: \"SAĞ BACAK\"\n  STR_LEFT_LEG: \"SOL BACAK\"\n  STR_PAIN_KILLER: \"AĞRI KESİCİ\"\n  STR_STIMULANT: \"UYARICI\"\n  STR_HEAL: \"TEDAVİ\"\n  STR_TIME_UNITS_SHORT: \"ZÜ>{ALT}{0}\"\n  STR_WEIGHT: \"Yük>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"Tep.>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"M.K.B>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"M.K.D.>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Yabancı Yapıtı\"\n  STR_AMMO_ROUNDS_LEFT: \"KALAN{NEWLINE}CEPHANE:{NEWLINE}{ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Ağrı Kesici>{ALT}{0}{ALT}{NEWLINE}Uyarıcı    >{ALT}{1}{ALT}{NEWLINE}Tedavi    >{ALT}{2}\"\n  STR_THROW: \"Fırlat\"\n  STR_AUTO_SHOT: \"Otomatik Atış\"\n  STR_SNAP_SHOT: \"Ani Atış\"\n  STR_AIMED_SHOT: \"Keskin Atış\"\n  STR_STUN: \"Dondur\"\n  STR_PRIME_GRENADE: \"El Bombasını Kur\"\n  STR_USE_SCANNER: \"Dev. Sensörü Kullan\"\n  STR_USE_MEDI_KIT: \"İlk Yardım Çantası Kullan\"\n  STR_LAUNCH_MISSILE: \"Torpido Ateşle\"\n  STR_ACCURACY_SHORT: \"İsb>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Zaman Ünitesi Yetersiz!\"\n  STR_NOT_ENOUGH_ENERGY: \"Yeterli Enerji Yok!\"\n  STR_NO_ROUNDS_LEFT: \"Cephane kalmadı!\"\n  STR_NO_AMMUNITION_LOADED: \"Silah Boş!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Bu cephane bu silah için değil!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"Silah zaten dolu!\"\n  STR_NO_LINE_OF_FIRE: \"Görüş Açısı Yok!\"\n  STR_GRENADE_IS_ACTIVATED: \"El Bombası Aktif!\"\n  STR_GRENADE_IS_DEACTIVATED: \"El bombası etkisiz hale getirildi!\"\n  STR_THERE_IS_NO_ONE_THERE: \"Orada hiç kimse yok!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Yabancı teçhizatı, araştırılmadan kullanılamaz!\"\n  STR_OUT_OF_RANGE: \"Menzil Dışı!\"\n  STR_UNABLE_TO_THROW_HERE: \"Buraya fırlatılamıyor!\"\n  STR_SET_TIMER: \"Zamanlayıcıyı Kur\"\n  STR_HIDDEN_MOVEMENT: \"GİZLİ MANEVRA\"\n  STR_TURN: \"TUR> {0}\"\n  STR_SIDE: \"TARAF> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Devam etmek için butona basın\"\n  STR_MIND_CONTROL: \"Moleküler Kontrol\"\n  STR_PANIC_UNIT: \"İmplant Kilitle\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Moral Saldırısı Başarılı\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"İmplant Kontrolü Başarılı\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}çıldırdı\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}çıldırdı\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}paniğe kapıldı\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}paniğe kapıldı\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"Yabancılar\"\n  STR_RIGHT_HAND: \"SAĞ EL\"\n  STR_LEFT_HAND: \"SOL EL\"\n  STR_RIGHT_SHOULDER: \"SAĞ OMUZ\"\n  STR_LEFT_SHOULDER: \"SOL OMUZ\"\n  STR_BACK_PACK: \"ÇANTA\"\n  STR_BELT: \"KEMER\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE} Moleküler Kontrol altında\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE} Moleküler Kontrol altında\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}bilincini yitirdi\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}bilincini yitirdi\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}ölümcül bir yara nedeniyle hayatını kaybetti\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}ölümcül bir yara nedeniyle hayatını kaybetti\"\n  STR_USE_MIND_PROBE: \"M.K. Okuyucu Kullan\"\n  STR_FATAL_WOUNDS: \"ÖLÜMCÜL YARALAR\"\n  STR_UNDER_ARMOR_UC: \"ALT ZIRH\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Zaman Üniteleri ani atış için ayrıldı\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Zaman Üniteleri otomatik atış için ayrıldı\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Zaman Üniteleri keskin atış için ayrıldı\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"Zaman Üniteleri diz çökmek için ayrıldı\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"ZÜ'leri diz çöküp ateş etmek için ayrıldı\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} Ünite X-Com aracında\"\n    other: \"{N} Ünite X-Com aracında\"\n  STR_UNITS_OUTSIDE:\n    one: \"{N} Ünite X-Com aracı dışında\"\n    other: \"{N} Ünite X-Com aracı dışında\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} Ünite giriş bölgesinde\"\n    other: \"{N} Ünite giriş bölgesinde\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} Ünite tahliye bölgesinde.\"\n    other: \"{N} Ünite tahliye bölgesinde.\"\n  STR_ABORT_MISSION_QUESTION: \"Harekat Yarıda Bırakılsın mı?\"\n  STR_CORPSE: \"Ceset\"\n  STR_UNLOAD_CRAFT: \"Aracı boşalt\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}öldürüldü\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}öldürüldü\"\n  STR_HIT_MELEE: \"Vur\"\n  STR_GROUND: \"ZEMİN\"\n  STR_LIVING_QUARTERS_PLURAL: \"Koğuş\"\n  STR_LIST_ITEM: \"MADDE\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"Düşüşte tüm yabancılar öldü,{NEWLINE}Ele geçirme çalışması başlatıldı\"\n  STR_RESET: \"Baştan Başla\"\n  STR_MEMORIAL: \"Anıt\"\n  STR_DATE_UC: \"TARİH\"\n  STR_SOLDIERS_RECRUITED_UC: \"ASKERE ALINANLAR>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"ŞEHİTLER>{ALT}{0}\"\n  STR_REMOVE_SELECTED: \"Seçilenleri Öldür\"\n  STR_LIVE_ALIENS: \"Canlı{NEWLINE}Numuneler\"\n  STR_DEAD_ALIENS: \"Iskarta{NEWLINE}Numuneler\"\n  STR_UNDER_INTERROGATION: \"İnceleme{NEWLINE}Altında\"\n  STR_CONTAINMENT_EXCEEDED: \"KARANTİNA LİMİTLERİ AŞILDI!{SMALLLINE}{0} üssünde karantina tesisi tamamen dolu. Muhafaza etmek istemediğiniz Yabancıları imha etmelisiniz.\"\n  STR_MANAGE_CONTAINMENT: \"Karantina Yönetimi\"\n  STR_STORAGE_EXCEEDED: \"DEPOLAMA KAPASİTESİ AŞILDI!{SMALLLINE}{0} üssünde yeterli depolama alanı kalmadı. İhtiyaç fazlası levazımatı satmalısınız.\"\n  STR_GO_TO_BASE: \"Üssü Görüntüle\"\n  STR_MELEE_ACCURACY: \"YAKIN DÖVÜŞ\"\n  STR_SELL_PRODUCTION: \"SAT\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Her iki el boş olmalıdır!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Mevcut teçhizat, envanter şablonu için yetersiz!\"\n  STR_UNLOAD_WEAPON: \"Silahı boşalt\"\n  STR_ALL_ITEMS: \"Tüm Kalemler\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"ARAÇTA TEÇHİZAT İÇİN YER YOK!{SMALLLINE}Bu denizaltıya, azami {N} parça teçhizat yükleyebilirsiniz.\"\n    other: \"ARAÇTA TEÇHİZAT İÇİN YER YOK!{SMALLLINE}Bu denizaltıya, azami {N} parça teçhizat yükleyebilirsiniz.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}KOMUTA MERKEZİ YOK EDİLDİ{NEWLINE}Girişe geri dönüp görevi iptal edin.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"X-Com Akua-tesisleri karada inşa edilemez\"\n  STR_UNABLE_TO_ENGAGE_DEPTH: \"BU DERİNLİKTE{NEWLINE}SICAK TEMAS SAĞLANAMAZ\"\n  STR_UNABLE_TO_ENGAGE_AIRBORNE: \"BOTLAR HAVADAYKEN{NEWLINE}SICAK TEMAS SAĞLANAMAZ\"\n  STR_UNDERWATER_EQUIPMENT: \"Bu teçhizat su dışında kullanılamaz!\"\n  STR_LAND_EQUIPMENT: \"Bu teçhizat su altında kullanılamaz!\"\n  STR_LEVEL_SHORT: \"K{0}\"\n  STR_PERSONNEL: \"Personel\"\n  STR_CRAFT_ARMAMENT: \"Araç ve Donatım\"\n  STR_COMPONENTS: \"Bileşenler\"\n  STR_SOLDIERS_RECRUITED: \"Askere alınanlar\"\n  STR_SOLDIERS_LOST: \"Şehitler\"\n  STR_TOTAL_UFOS: \"Tespit edilen uçar botlar\"\n  STR_TOTAL_ALIEN_BASES: \"Tespit edilen Yabancı kolonileri\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"MKD\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"MKB\"\n  FEMALE_CIVILIAN: \"Sivil, Kadın\"\n  MALE_CIVILIAN: \"Sivil, Erkek\"\n  DOCKER_CIVILIAN: \"Sivil, Liman İşçisi\"\n  SAILOR_CIVILIAN: \"Sivil, Denizci\"\n  STR_BIODRONE_MELEE_WEAPON: \"Biyodron Saldırısı\"\n  HALLUCINOID_WEAPON: \"Halüsinoid Silahı\"\n  STR_LOBSTERMAN_MELEE_WEAPON: \"Istakozadam Saldırısı\"\n  CALCINITE_WEAPON: \"Kalsinit Silahı\"\n  DEEP_ONE_WEAPON: \"Diptengelen Silahı\"\n  STR_TRISCENE_MELEE_WEAPON: \"Trisen Saldırısı\"\n  STR_TRIBIO_SONIC_WEAPON: \"Yabancı Sonik Silahı\"\n  XARQUID_WEAPON: \"Zarkid Silahı\"\n  TENTACULAT_WEAPON: \"Tentakülat Silahı\"\n  ZOMBIE_WEAPON: \"Zombi Silahı\"\n  ALIEN_PSI_WEAPON: \"Yabancı M.K. Silahı\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/uk.yml",
    "content": "uk:\n  STR_LEVIATHAN_UFOPEDIA: \"СУБМАРИНА ДЛЯ ТРАНСПОРТУВАННЯ ВІЙСЬК ТА ПЕРЕХОПЛЕННЯ ВОРОГА, З МОЖЛИВІСТЮ НАДГЛИБОКОГО ЗАНУРЕННЯ. ЧУДОВИЙ ЗРАЗОК ПОЄДНАННЯ ІНОПЛАНЕТНИХ ТА ЛЮДСЬКИХ ТЕХНОЛОГІЙ З ВПРОВАДЖЕННЯМ ІОННИХ ДВИГУНІВ ТА МАГНІТНОЇ НАВІГАЦІЇ.\"\n  STR_BARRACUDA_UFOPEDIA: \"БРИТАНСЬКА ГІДРОКОСМІЧНА БАРРАКУДА, ОСНАЩЕНА ДВИГУНАМИ, ЯКІ ПРАЦЮЮТЬ ЗА ПРИНЦИПОМ ПЕРЕГРІТИХ ЛАЗЕРІВ. ОДИН З НАЙШВИДШИХ ПЕРЕХОПЛЮВАЧІВ У СВІТІ, ЗДАТНИЙ ДО ПІДВОДНОГО ТА ПОВІТРЯНОГО БОЮ, КЛЮЧОВИЙ КОРАБЕЛЬ ДЛЯ МАЙБУТНІХ БИТВ.\"\n  STR_HAMMERHEAD_UFOPEDIA: \"КОРАБЕЛЬ ДЛЯ ТРАНСПОРТУВАННЯ ВІЙСЬК ТА ПЕРЕХОПЛЕННЯ ВОРОГА. НА БОРТУ ВСТАНОВЛЕНО АНАЛОГ СИСТЕМИ МАГНІТНИХ ПІДВІСОК. З ОГЛЯДУ НА МАЛІ РОЗМІРИ, ВТІЛЕННЯ ДАНОГО ПРОЕКТУ СТАЛО ПРОРИВНИМ ДОСЯГНЕННЯМ ДЛЯ СПЕЦІАЛІСТІВ.\"\n  STR_TRITON_UFOPEDIA: \"ТРИТОН - ДЕСАНТНО-ТРАНСПОРТНИЙ КОРАБЕЛЬ, ОСНАЩЕНИЙ ДВИГУНАМИ ДЛЯ ПЕРЕСУВАННЯ В ПОВІТРІ ТА ПІД ВОДОЮ. ВЕЛИКА МІСТКІСТЬ ТА НАДІЙНІСТЬ КОНСТРУКЦІЇ РОБЛЯТЬ ЙОГО ОСНОВОЮ ФЛОТУ X-COM.\"\n  STR_MANTA_UFOPEDIA: \"СКАТ - ВИСОКОШВИДКІСНА, ОДНОМІСНА ЛІТАЮЧА СУБМАРИНА-ПЕРЕХОПЛЮВАЧ З ІОННИМИ ДВИГУНАМИ, СХОЖИМИ НА ІНОПЛАНЕТНІ. ДУЖЕ ЕФЕКТИВНА В УМОВАХ НАРОСТАЮЧОГО КОНФЛІКТУ.\"\n  STR_AJAX_UFOPEDIA: \"ТОРПЕДА \\\"AJAX\\\" - СТАНДАРТНА ЗБРОЯ ДЛЯ ПІДВОДНИХ БОЇВ, ВИСТОСОВУЄТЬСЯ У ВОДАХ УСЬОГО СВІТУ. ЗАСТОСОВУЄТЬСЯ ЯК ТОЧНА ТА ПОТУЖНА ЗБРОЯ ЗАЛЯКУВАННЯ.\"\n  STR_DUP_HEAD_UFOPEDIA: \"ТЕХНОЛОГІЯ БОЄПРИПАСІВ, ЩО ВИКОРИСТОВУЮТЬ СЕРДЕЧНИКИ ІЗ ЗБІДНЕНОГО УРАНУ, Є ВІДНОСНО НОВОЮ. ЦЕ ПЕРШЕ, ПОВІНІСТЮ ВПРОВАДЖЕНЕ, КОМЕРЦІЙНЕ РІШЕННЯ ДЛЯ КОМПЛЕКСУ ПІДВОДНОЇ ЗБРОЇ. \"\n  STR_CRAFT_GAS_CANNON_UFOPEDIA: \"ПНЕВМАТИЧНИЙ ГАРМАТНИЙ КОМПЛЕКС. ВИСТРІЛЮЄ МОНОЛІТНИМИ СТРИЖНЯМИ, ЯКІ МАЮТЬ ВЕЛИКУ БРОНЕБІЙНІСТЬ.\"\n  STR_PWT_CANNON_UFOPEDIA: \"ІМПУЛЬСНО-ХВИЛЬОВА ТОРПЕДНА ГАРМАТА ВИКОРИСТОВУЄ СИСТЕМУ ПОДАЧІ ПЕРЕГРІТОГО ПАЛИВА ТА НАДЗВИЧАЙНО ЩІЛЬНУ БОЄГОЛОВКУ, ЯКА МОЖЕ ПРОБИВАТИ БІЛЬШІСТЬ СПЛАВІВ.\"\n  STR_GAUSS_CANNON_UFOPEDIA: \"ГАУСC-ЗБРОЯ - НЕЩОДАВНО РОЗРОБЛЕНА ТЕХНОЛОГІЯ X-COM. ПРИСКОРЮВАЧ ЧАСТИНОК ЦІЄЇ СИСТЕМИ ЖИВИТЬСЯ ВІД КОМПАКТНОГО ТЕРМОЯДЕРНОГО РЕАКТОРА, ЯКИЙ ОХОЛОДЖУЄТЬСЯ РІДКИМ АЗОТОМ.\"\n  STR_SONIC_OSCILLATOR_UFOPEDIA: \"ПОТУЖНИЙ АКУСТИЧНИЙ ВИПРОМІНЮВАЧ СТВОРЮЄ СИЛОВІ АКУСТИЧНІ ХВИЛІ. ЦІЛЬ ЗНИЩУЄТЬСЯ ЗА РАХУНОК РОЗРИВУ МІЖМОЛЕКУЛЯРНИХ ЗВ'ЯЗКІВ СИЛОЮ ВІБРАЦІЇ.\"\n  STR_AQUATOID_UFOPEDIA: \"Раса акватоїдів - це древня цивілізація, процвітаюча за багато тис. років до того, як люди зробили перші кроки по землі. Їх компактна тілобудова та грушеподібний череп нагадують про їхніх космічних братів - сектоїдів. Основа їхньої сили - ефективна технологія молекулярного контролю. Розмноження безплідної раси акватоїдів відбувається шляхом генетичних модифікацій, ідеальними об'єктами для яких є люди. Експерименти породили численні гібридні раси.\"\n  STR_AQUATOID_AUTOPSY: \"Розтин акватоїда\"\n  STR_AQUATOID_AUTOPSY_UFOPEDIA: \"Детальне дослідження цього створіння навело нас на декілька початкових припущень. Це, наш старий ворог - сектоїд, але змінений хірургічним шляхом і оснащений імплантами, позволяючими йому існувати під водою. Рудиментарні легені дозволяють йому дихати повітрям та обмежено пересуватись на поверхні. У тілі встановлені кібернетичні імпланти, що покращують функціонування атрофованих кінцівок та внутрішніх оргінів. Всі особи цієї раси ідентичні, ми припускаємо, що вони клоновані.\"\n  STR_GILLMAN_UFOPEDIA: \"Це дивне створіння, очевидно, є гуманоїдною рептилією, дуже близькою до людини. Воно дуже сильне та швидко рухається під водою. Зябролюди - повноцінна раса, в якій присутні особи двох статей та різного віку. Вони відрізняються від більшості підводних прибульців, адже не мають слідів хірургічних або генетичних втручань. Схоже на те, що це якась древня гілка нашого виду.\"\n  STR_GILLMAN_AUTOPSY: \"Розтин зябролюдини\"\n  STR_GILLMAN_AUTOPSY_UFOPEDIA: \"Під час розтину стало зрозуміло, що це не прибулець, а якась доісторична раса, котра жила на Землі в часи динозаврів, і, як вважалося, вимерла на початку ери ссавців. Зябролюди - розумні та сильні амфібії. Катаклізм, що поклав кінець ері рептилій, змусив їх до симбіотичних відносин з прибульціями, що з'явились на Землі. В черепа створінь вживлено маленький електронний пристрій.\"\n  STR_LOBSTERMAN_UFOPEDIA: \"Це приголомшливе створіння з шістьма кінцівками набагато більше за людину та схоже на справжнього морського демона. Завдяки зовнішній подібності до земного лобстера, це створіння отримало прізвисько \\\"Лобстеролюдина\\\" серед оперативників X-COM.  Бездоганно продумана бойова істота, що володіє неймовірною силою і майже невразлива для ракет -  справжнє чудовисько з глибин. Своїми клешнями воно здатне розривати сталь.\"\n  STR_LOBSTERMAN_AUTOPSY: \"Розтин лобстеролюдини\"\n  STR_LOBSTERMAN_AUTOPSY_UFOPEDIA: \"Під практично непробивним панцирем було виявлено істоту вражаючої конструкції. Титановий скелет овитий потужною мускулатурою. Складна система наведення з можливістю мультидіапазонного супроводу цілі підєднана безпосередньо до мозку створіння. Його фасеткові очі захищені пластиком, що міцніший за сталь. Очевидно, що при правильному бойовому використанні ці створіння будуть практично непереможними. Глибоко в їхніх тілах приховані пристрої невідомого призначення.\"\n  STR_TASOTH_UFOPEDIA: \"Ці спритні та швидкі істоти - основа армії прибульців. Вони сотнями виходять з величезних баків розмноження, розташованих в серці колонії прибульців. Набагато сильніші за людей, тасоти - істинні прибульці, їхня манера поведінки та кровожерна природа не моють аналогів на планеті. Тасоти часто йдуть в авангарді під час нападів прибульців і ніколи не ухиляються від бою, навіть перед значно переважаючими силами противника.\"\n  STR_TASOTH_AUTOPSY: \"Розтин тасота\"\n  STR_TASOTH_AUTOPSY_UFOPEDIA: \"Розтин показав, що це кібернетичний організм, володіючий дивною силою. Всередині порожнини тіла знажодиться невелике джерело енергії, але не знайдено органів, які б можливо було розпізнати. Енергія по тілу переноситься біо-електричною системою. У тілі немає ні кісток, ні каркасу. Якщо прибулець помирає, подача енергії припиняється, а тіло стає нерухомою лялькою, з якої сочаться рідини та плоть. Окрім джерела енергії, ми виявили декілька керамічних комірок, які оживляють створіння, якщо подати на них енергію.\"\n  STR_DEEP_ONE_UFOPEDIA: \"Глибинник являє собою біологічний жах: це гібрид, створений безумними експерементами Акватоїдів. Ми виявили декілька підвидів даної істоти. Після проведення багатьох досліджень ми дійшли до висновку, що вони були створені загарбниками. Їх кількість зростає по мірі захоплення людей. Кожна з цих людиноподібних істот озброєна електричним розрядником, потужності якого досить, щоб вбити акванавта.\"\n  STR_DEEP_ONE_AUTOPSY: \"Розтин глибинника\"\n  STR_DEEP_ONE_AUTOPSY_UFOPEDIA: \"Ця істота - результат трансплантації тканин прибульців в людський організм. Людський мозок був сильно видозмінений для встроювання електронного керування та трансплантації кори прибульця. Всі людські органи, очевидно, видалені - залишились тільки очі. Хірургічно вбудовані транспланти дають змогу зародку, по мірі росту, поглинати свого носія. Міцна шкіра істоти не містить органіки: це металева сітка, дуже міцна та гнучка. Гібрид дуже сильний, швидкий та повіністю контролюється прибульцями.\"\n  STR_BIODRONE_UFOPEDIA: \"Біо-дрон - створіння, яке міг вигадати тільки розум прибульця. Це мозок (людини або прибульця), занурений в амніотичну рідину і з'єднаний з енергетичною платформою, що може літати над землею обо під водою. Кожен біо-дрон озброєний потужним акустичним деструктором, який є частково механічним, а частково - живим організмом. Вчені припускають, що ця зброя керує голосовими зв'язками організма-господаря. Висока точність та живучість роблять цих істот хорошими стороживими \\\"псами\\\" для захисту цінного майна прибульців.\"\n  STR_BIODRONE_AUTOPSY: \"Розбір біо-дрона\"\n  STR_BIODRONE_AUTOPSY_UFOPEDIA: \"Гіпотеза про те, що акустичний деструктор є біологічним пристроєм, підтвердилася. Це нещасне створіння буквально вбиває ворогів своїм криком. Кожен екземпляр має багато слідів хірургічного втручання і сильно понівечений. Прибульці, схоже, безжально катують мозок, щоб змусити його підкорятися. Зазвичай використовується мозок прибульців, але ніщо не може зрівнятися із жахом від виявлення людського мозку. Біо-дрони оснащені іонним двигуном та деякою інтегрованою системою дистанційного керування.\"\n  STR_TENTACULAT_UFOPEDIA: \"Навіть безодні лавкрафтівського кошмару не могли породити таку невимовну істоту. Не існує жодного порівняння з будь-яким земним організмом, і неможливо навіть уявити середовище, яке могло б породити щось подібне. Озброєний довгими щупальцями, тентакулат паралізує своїх жертв, а потім перетворює їх на бездумних ляльок, які можуть вбити одним дотиком, навіть через броню. Тентакулат - найстрашніший прибулець, з яким коли-небудь стикався X-COM.\"\n  STR_TENTACULAT_AUTOPSY: \"Розтин тентакулата\"\n  STR_TENTACULAT_AUTOPSY_UFOPEDIA: \"Розтин показує, що у великому мозку істоти встановлені невеликі кібернетичні імпланти. Система зору - це складна комбінація видимого світла і тепловізійної обробки зображень. Навіть у чорнильних глибинах океану цей монстр може орієнтуватися з безпомилковою точністю. Існують рудиментарні органи, які здаються мінімально необхідними для виживання. Кожна істота має невеликий шлунок із зовнішнім роз'ємом, логічно припустити, що вона харчується за рахунок прямого надходження поживних речовин від своїх господарів.\"\n  STR_CALCINITE_UFOPEDIA: \"Схожі на водолазні костюми загиблих моряків, ці прибульці блукають по морському дні в пошуках довірливих жертв. Одного сильного удару міцних, як сталь, кігтів істоти може бути достатньо, щоб відправити на дно найкращих дайверів. У масці для обличчя видніється желатиноподібна зелена форма. Нам не вдалося з'ясувати, що за створіння знаходиться у скафандрі, незважаючи на неодноразові, смертельно небезпечні зустрічі з ним.\"\n  STR_CALCINITE_AUTOPSY: \"Розтин кальциніта\"\n  STR_CALCINITE_AUTOPSY_UFOPEDIA: \"Якщо зняти броньований скафандр, кальциніт являє собою величезний аморфний згусток протоплазми. У нього немає видимого мозку, кінцівок чи органів чуття, лише невеликий металевий компонент, що глибоко залягає в рідкому тілі. Після смерті ми можемо лише здогадуватися про природу цієї істоти. Незрозуміла загадка наших інопланетних ворогів.\"\n  STR_TRISCENE_UFOPEDIA: \"Ця двонога рептилія є поверненням до епохи динозаврів. Здається, це крейдяна істота в усіх сенсах, окрім здатності виживати у воді та на суші. Ці істоти обвішані капсулами зі зброєю і мають щелепу, викладену величезними металевими зубами. Часто ці монстри складають основу ударних сил прибульців, коли вони здійснюють напади на сушу. Це важка і потужна зброя, і командири тасотів застосовують її зі смертельною ефективністю.\"\n  STR_TRISCENE_AUTOPSY: \"Розтин трисцена\"\n  STR_TRISCENE_AUTOPSY_UFOPEDIA: \"Скальпель науковців показав, що трисцен - це древня істота, оснащена кібернетичними імплантами та системами озброєння. Його крихітний мозок доповнений невеликим комп'ютерним модулем, вмонтованим у керуючий нерв, який є у всіх представників даного виду. Міцна природна шкіра, інстинкт хижака та посилення додатковою зброєю, роблять його смертельним супротивником у будь-якому середовищі.\"\n  STR_HALLUCINOID_UFOPEDIA: \"Підкоривши океани, прибульці вивели цих величезних земних істот як зброю. Не піддавайтеся оманливому почуттю безпеки, зустрічаючись з цими нешкідливими на вигляд підводними корабликами. Володіючи крижаним ударом ближнього бою, галюциноїд є смертельним ворогом.\"\n  STR_HALLUCINOID_AUTOPSY: \"Розтин галюциноїда\"\n  STR_HALLUCINOID_AUTOPSY_UFOPEDIA: \"У багатьох шарах желатинового тіла цього організму захована потужна хімічна морозильна камера, його головна наступальна здатність. М'яка та еластична шкіра галюциноїда здається вразливою до теплових атак. Часто цей мутант зустрічається в компанії своїх господарів - акватоїдів.\"\n  STR_XARQUID_UFOPEDIA: \"Ще одне видозмінене земне безхребетне, ксарквід - істота надзвичайно красива і небезпечна. Цей швидкий плавучий гігант володіє руйнівним арсеналом: задушливим чорнилом та бомбами на основі іонізованих частинок. З перших зустрічей з цим могутнім створінням ми остерігаємося його сили та його контролерів - мстивих зябролюдей.\"\n  STR_XARQUID_AUTOPSY: \"Розтин ксарквіда\"\n  STR_XARQUID_AUTOPSY_UFOPEDIA: \"Цей наутилус-переросток виріс до таких розмірів завдяки позаземним препаратам і хірургічним змінам. Познущавшись над природою, зябролюди додали до нього механічні системи управління, і тепер від його первісної природи нічого не залишилося. Використовувані у якості органічної бойової платформи, ксарквіди, завдяки щільній оболонці та хорошій мобільності, являють собою грізних супротивників.\"\n  STR_ION_BEAM_ACCELERATORS_UFOPEDIA: \"Літаючі субмарини прибульців використовують складні енергетичні системи для переміщення крізь глибини. Основою їхньої технології є іонний витіснювач, що використовуючи зербіт як каталізатор, за секунду витісняють стократний власний об'єм. Ця величезна потужність означає, що інопланетяни здатні обігнати більшість земних суден. Ми можемо відтворити цю систему руху, використовуючи аквапластик та елементи живлення на основі зербіту.\"\n  STR_MAGNETIC_NAVIGATION_UFOPEDIA: \"Ці пристрої генерують багатошарове магнітне поле сферичної форми, діюче в радіусі до 1000 метрів навколо субмарини. Навігатори прибульців напряму підключені до цих машин і при переміщенні судна відчувають весь підводний світ довкола. Система інтерфейсу працює за допомогою модифікованої прибульцями мозкової тканини, яка взаємодії із мозком оператора через нейронний зв'язок.\"\n  STR_ALIEN_SUB_CONSTRUCTION_UFOPEDIA: \"Кожне судно має хамелеоноподібну структуру, ретельно змодельовану на основі морських істот і побудовану з аквапластику. Кожен підводний човен функціонує як єдиний організм: екіпаж та обладнання в гармонії. Більшість з цих систем можна відтворити і розробити гібридну технологію, яка дозволить нам піднятися на той самий технологічний рівень.\"\n  STR_ALIEN_CRYOGENICS_UFOPEDIA: \"Незліченна кількість прибульців, що зачаїлися на Землі, перебувають у стані анабіозу, у кріогенній заморозці. Всі істоти запечатані в окремих контейнерах, температура їхніх тіл знижена до такої міри, що функції організму майже зупинилися. Аналіз контейнерів показав, що тіла зберігаються на протязі неймовірної кількості часу, деяким із них - понад 60 мільйонів років.\"\n  STR_ALIEN_CLONING_UFOPEDIA: \"Чимало з упійманих нами прибульців ідентичні аж до ДНК - дублікати у всіх відношеннях. Зразки клітин витягують зі заморожених генних банків прибульців і поміщають у спеціальні блоки. Деякі з них містять людські тіла, інші - лише їх частини. Можливо, ці блоки клонування призначені також для створення гібриду людини і прибульця.\"\n  STR_ALIEN_LEARNING_ARRAYS_UFOPEDIA: \"Використовуючи імпланти МК в черепах усіх прибульців, ці машини вводять інформацію безпосередньо в мозок. До цих установок привозять щойно клонованих прибульців, які отримують расову пам'ять і всю наукову та бойову інформацію, завантажену в їхній чистий мозок.\"\n  STR_ALIEN_IMPLANTER_UFOPEDIA: \"Цей пристрій використовується для імплантації прибульцями імплантів молекулярного контролю, запліднення репродуктивних рас, а також для імплантації або видалення органів та електроніки з будь-якої істоти. Вважалося, що процес відбувається на підкорених пацієнтах, але піддослідні дуже добре обізнані із процесом, і, на жаль, людська анатомія, схоже, ідеально підходить для цього.\"\n  STR_EXAMINATION_ROOM_UFOPEDIA: \"Тепер у нас є факти, щоб зрозуміти, чому прибульці захоплюють людей. Вони не є їжею, і вони не запліднюються чужими ембріонами, скоріше, вони є основою для цілого ряду істот і систем управління. Технології прибульців засновані на колективному розумі, спільному інтелекті, а людський мозок є ідеальним вмістилищем для цих систем. Тканина людського мозку використовується в більшості біологічних комп'ютерних систем зберігання та пошуку інформації, а рештки використовуються для будівництва та розмноження.\"\n  STR_AQUA_PLASTICS_UFOPEDIA: \"Інопланетні підводні човни та споруди використовують неймовірно міцний, гнучкий та довговічний матеріал для більшості своїх конструкцій. Аквапластик - це складний багатозв'язний, зербіто-каталізований матеріал. Щільна, але легка речовина має міцність, вищу навіть за титан чи кевлар.\"\n  STR_ZRBITE_UFOPEDIA: \"Це сплав чужорідного походження, частково золото, частково чужорідний біоматеріал. Якщо його використовувати як джерело енергії, невелика кількість згенерує більше енергії, ніж ядерний блок у 10 разів більшого розміру. Ми не маємо технічної можливості відтворити цей матеріал, оскільки більшість його компонентів мають чужорідне походження.\"\n  STR_ALIEN_ORIGINS_UFOPEDIA: \"Прибульці наносять удари по всьому світу з безжальною ефективністю. Ми не можемо визначити їхнє джерело. Можливо, воно знаходиться в якомусь океані, надто глибокому і непроникному для нас? Не всі організми, з якими ми зіткнулися, є чужорідними, деякі з них дуже старі, деякі виникли еволюційно, які давно вважалися вимерлими. Ми маємо справу із загрозою, яка дрімала тисячоліттями, тонким симбіозом людини та прибульця. Глибоко в океанах лежать стародавні місця, які прибульці використовували для контакту зі своїми далекими родичами. Кожне з цих дванадцяти місць містить пристрій Синоміум, потужну технологію прибульців. Тепер, коли їхня військова машина активована, прибульці знову активують ці об'єкти, щоб розширити свою мережу молекулярного контролю. Ми повинні знищити ці об'єкти за будь-яку ціну.\"\n  STR_THE_ULTIMATE_THREAT_UFOPEDIA: \"Шістдесят п'ять мільйонів років тому з далекого світу прибульців на Землю був відправлений величезний колоніальний корабель. Коли він наближався до молодої планети, потужний сонячний спалах спричинив збій у навігаційних системах. Пошкоджений і дезорієнтований, величезний корабель пролетів крізь стратосферу і з'явився у осяяному небі. Незліченні види життя на Землі звели свої погляди в небо, коли їхній заклятий ворог врізався в планету. Величезна хмара пилу заполонила атмосферу, і в міру того, як земля охолоджувалася, домінуюче життя, могутні динозаври, загинули. Але 400 мільярдів тонн Т'льєта не були знищені в результаті зіткнення, складні суперкомп'ютери запустили цикл кріогенного сну для істот, що перебували глибоко в його трюмах. Минали ери, комп'ютери будили партії прибульців, щоб спробувати зв'язатися зі своїми далекими родичами, але все було марно, бо ядро сили прибульців міцно спало.\"\n  STR_TLETH_THE_ALIEN_CITY: \"Т'льєт - місто прибульців\"\n  STR_TLETH_THE_ALIEN_CITY_UFOPEDIA: \"Т'льєт - величезний корабель колонії прибульців лежить на дні Сігсбі в Мексиканській затоці. У самому серці міста знаходиться інопланетний жах, такий огидний і такий могутній, що навіть смерть не може його здолати. У камері з чужорідного металу спить великий сновида - Верховний прибулець. Якщо підняти Т'лета над хвилями, почнеться цикл його реанімації, і коли він підніметься, його вже не зупинити. Будучи не живим, але й не мертвим, Верховний прибулець контролює свою армію. Дивна технологія молекулярного контролю з'єднує всіх прибульців з Верховним, а Верховного - з усіма прибульцями. Генетично модифіковані зародки гібридів прибульців та людей постачають свідомість Верховного енергією і формують зв'язок між правителем і його підданими. Міф про Верховного прибульця існував у серцях і умах людства століттями, але істина була прихована морськими глибинами.\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"ЦЕНТР НА ДІЛЯНЦІ-ЧАС=5 Сек\"\n  STR_CANCEL_UC: \"СКАСУВАТИ\"\n  STR_NONE: \"Нічого\"\n  STR_UNKNOWN: \"Невідомо\"\n  STR_POOR: \"Погано\"\n  STR_AVERAGE: \"Посередньо\"\n  STR_GOOD: \"Добре\"\n  STR_EXCELLENT: \"Відмінно\"\n  STR_BUILD_NEW_BASE_UC: \"БУДУВАТИ НОВУ БАЗУ\"\n  STR_BASE_INFORMATION: \"ІНФОРМАЦІЯ ПРО БАЗУ\"\n  STR_EQUIP_CRAFT: \"СПОРЯДИТИ СУБМАРИНУ\"\n  STR_BUILD_FACILITIES: \"БУДУВАТИ МОДУЛІ\"\n  STR_RESEARCH: \"ДОСЛІДЖЕННЯ\"\n  STR_MANUFACTURE: \"ВИРОБНИЦТВО\"\n  STR_TRANSFER_UC: \"ТРАНСПОРТУВАННЯ\"\n  STR_PURCHASE_RECRUIT: \"ЗАКУПІВЛЯ/НАЙМ\"\n  STR_SACK: \"ЗВІЛЬНИТИ\"\n  STR_SELL_SACK_UC: \"ПРОДАЖ/ЗВІЛЬНЕННЯ\"\n  STR_GEOSCAPE_UC: \"ГЛОБУС\"\n  STR_NAME: \"Назва\"\n  STR_AREA: \"Регіон\"\n  STR_BUILD_NEW_BASE: \"Будувати нову базу\"\n  STR_CANCEL: \"Скасувати\"\n  STR_COST_UC: \"ЦІНА>\"\n  STR_CONSTRUCTION_TIME_UC: \"ЧАС БУДІВНИЦТВА>\"\n  STR_DAY:\n    one: \"{N} день\"\n    few: \"{N} днів\"\n    many: \"{N} днів\"\n    other: \"{N} днів\"\n  STR_HOUR:\n    one: \"{N} година\"\n    few: \"{N} годин\"\n    many: \"{N} годин\"\n    other: \"{N} годин\"\n  STR_MAINTENANCE_UC: \"ОБСЛУГОВУВАННЯ>\"\n  STR_OK: \"OK\"\n  STR_INSTALLATION: \"Встановлення\"\n  STR_CURRENT_RESEARCH: \"ПОТОЧНІ ДОСЛІДЖЕННЯ\"\n  STR_SCIENTISTS_AVAILABLE: \"Вчених вільно>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"Вчених зайнято>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"Вільних місць в лабораторіях>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"ПРОЕКТ ДОСЛІДЖЕНЬ\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"ВЧЕНИХ ЗАЙНЯТО\"\n  STR_PROGRESS: \"ПРОГРЕС\"\n  STR_NEW_PROJECT: \"Новий проект\"\n  STR_CANCEL_PROJECT: \"СКАСУВАТИ ПРОЕКТ\"\n  STR_NEW_RESEARCH_PROJECTS: \"НОВІ ПРОЕКТИ ДОСЛІДЖЕНЬ\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"ВЧЕНИХ ВІЛЬНО>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"ВІЛЬНИХ МІСЦЬ В ЛАБОРАТОРІЯХ>{ALT}{0}\"\n  STR_INCREASE: \"Збільшити\"\n  STR_DECREASE: \"Зменшити\"\n  STR_START_PROJECT: \"ПОЧАТИ ПРОЕКТ\"\n  STR_CURRENT_PRODUCTION: \"ПОТОЧНЕ ВИРОБНИЦТВО\"\n  STR_ENGINEERS_AVAILABLE: \"Інженерів вільно>{ALT}{0}\"\n  STR_ENGINEERS_ALLOCATED: \"Інженерів зайнято>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"Вільних місць в майстернях>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"Поточні фонди>{ALT}{0}\"\n  STR_ITEM: \"ПРЕДМЕТ\"\n  STR_ENGINEERS__ALLOCATED: \"Інженерів зайнято\"\n  STR_UNITS_PRODUCED: \"Одиниць виготовлено\"\n  STR_TOTAL_TO_PRODUCE: \"Всього до виготовлення\"\n  STR_COST__PER__UNIT: \" Ціна{NEWLINE}за{NEWLINE}одиницю\"\n  STR_DAYS_HOURS_LEFT: \"Днів/Годин залишилось\"\n  STR_NEW_PRODUCTION: \"Нове виробництво\"\n  STR_PRODUCTION_ITEMS: \"Виготовити виріб\"\n  STR_CATEGORY: \"КАТЕГОРІЯ\"\n  STR_START_PRODUCTION: \"ПОЧАТИ ВИРОБНИЦТВО\"\n  STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT: \"{0} Інженеро-годин на виготовлення одиниці\"\n  STR_COST_PER_UNIT_: \"Ціна за одиницю>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"Робочого місця необхідно>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"НЕОБХІДНІ СПЕЦІАЛЬНІ МАТЕРІАЛИ\"\n  STR_ITEM_REQUIRED: \"НЕОБХІДНИЙ ПРЕДМЕТ\"\n  STR_UNITS_REQUIRED: \"НЕОБХІДНО ОДИНИЦЬ\"\n  STR_UNITS_AVAILABLE: \"ДОСТУПНО ОДИНИЦЬ\"\n  STR_STOP_PRODUCTION: \"ЗУПИНИТИ ВИРОБНИЦТВО\"\n  STR_ENGINEERS_AVAILABLE_UC: \"ІНЖЕНЕРІВ ВІЛЬНО>{ALT}{0}\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"ВІЛЬНИХ МІСЦЬ В МАЙСТЕРНЯХ>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"МІСЯЧНИЙ ПРИБУТОК>{ALT}{0}\"\n  STR_INCREASE_UC: \"ЗБІЛЬШИТИ\"\n  STR_DECREASE_UC: \"ЗМЕНШИТИ\"\n  STR_UNITS_TO_PRODUCE: \"Одиниць для виготовлення\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"Закупівля/Найм персоналу\"\n  STR_COST_OF_PURCHASES: \"Ціна придбань>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"ЦІНА ЗА ОДИНИЦЮ\"\n  STR_QUANTITY_UC: \" КІЛЬКІСТЬ\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"ЧОЛ. ВІЛЬНО:ЧОЛ. ВСЬОГО>\"\n  STR_SOLDIERS: \"Акванавти\"\n  STR_SCIENTISTS: \"Вчені\"\n  STR_ENGINEERS: \"Інженери\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"МІСЦЯ ЗАЙНЯТО:МІСЦЯ ВІЛЬНО>\"\n  STR_LIVING_QUARTERS: \"Житловий модуль\"\n  STR_STORES: \"Склади\"\n  STR_LABORATORIES: \"Лабораторії \"\n  STR_WORK_SHOPS: \"Майстерні\"\n  STR_HANGARS: \"Субмарини\"\n  STR_SHORT_RANGE_DETECTION: \"Ближнє виявлення\"\n  STR_DEFENSE_STRENGTH: \"Сила ППО\"\n  STR_TRANSFERS_UC: \"ПЕРЕДАЧІ\"\n  STR_TRANSFERS: \"Передачі\"\n  STR_ARRIVAL_TIME_HOURS: \"Час прибуття (годин)\"\n  STR_COST_: \"Вартість>{ALT}{0}\"\n  STR_AREA_: \"Регіон>{ALT}{0}\"\n  STR_BASE_NAME: \"Назва бази?\"\n  STR_SELECT_POSITION_FOR_ACCESS_LIFT: \"ВИБЕРІТЬ МІСЦЕ ДЛЯ ШЛЮЗУ\"\n  STR_TRANSFER: \"Транспортування\"\n  STR_AMOUNT_TO_TRANSFER: \"КІЛЬКІСТЬ ДЛЯ ТРАНСПОРТУВАННЯ\"\n  STR_SELECT_DESTINATION_BASE: \"Виберіть базу призначення\"\n  STR_COST: \"Ціна \"\n  STR_INTRO_1: \"Авторське право 1995 MicroProse\"\n  STR_INTRO_2: \"Марс: падіння Кідонії\"\n  STR_INTRO_3: \"Тріумфуючий X-Com, знищивши саме ядро військової машини прибульців, вирушає додому. Однак не все так просто на зруйнованій марсіанській базі.\"\n  STR_INTRO_4: \"Потужний тахіонний промінь виходить з уламків нервового центру Кидонії - мчить крізь порожнечу. Його призначення............\"\n  STR_INTRO_5: \"Земля.\"\n  STR_INTRO_6: \"Глибоко в океані промінь потрапляє на рецептор, що довго спав. Величезні сплячі комп'ютери починають ворушитися. У глибині, поза людським зором, величезні камери сплячих прибульців починають свій довгий цикл реанімації.\"\n  STR_INTRO_7: \"2040: Спокійна Земля. Жахи війни з прибульцями забуті. Але в загублених і прихованих місцях океану орди прибульців готові - готові знищити людство і захопити світ.\"\n  STR_INTRO_8: \"Прибульці нападають на людство, шукаючи зразки для своїх збочених експериментів, здійснюючи набіги на земну поверхню в пошуках цінних мінералів і ресурсів, а також грабуючи морські простори. Потім прибульці піднімаються над хвилями.\"\n  STR_INTRO_9: \"Потужні літаючі підводні човни дивної конструкції борознять океани - дивляться, шукають, полюють.........\"\n  STR_INTRO_10: \"Знайшовши здобич, вони нападають.\"\n  STR_INTRO_11: \"Проти беззахисного світу застосовують нову дивну зброю. Ми повністю у владі інопланетної загрози.{NEWLINE}Тільки одна організація може врятувати нас, але ми давно відвернулися від них......\"\n  STR_INTRO_12: \"Експериментальний підводний комплекс X-COM\"\n  STR_INTRO_13: \"'Рятуйте! Рятуйте!' 'Це трансатлантичний лайнер Гіперіон'. 'Нас атакують'. 'Рятуйте! Ряту............'\"\n  STR_INTRO_14: \"'Командний центр - підводному човну Один: відкрити океанічні двері', 'розгорнути Барракуду Нуль Один. Ситуація з нападом прибульців - стан червоний'.{NEWLINE}'Повторюю: стан червоний'\"\n  STR_INTRO_15: \"Прибульці безжальні у своїй ефективності....\"\n  STR_INTRO_16: \"...безпомилкові у своїй точності\"\n  STR_INTRO_17: \"'Барракуда Нуль Один - базі' - 'наближаємося до того, що залишилося від Гіперіона'.\"\n  STR_INTRO_18: \"'Уповільнення'.{NEWLINE}'Два метри'.{NEWLINE}'Один метр'.{NEWLINE}'Усім акванавтам приготуватися до негайного розгортання'.\"\n  STR_INTRO_19: \"........... 'Шлюз очищено' ... 'наближаємося до уламків'. {NEWLINE} 'Боже!' {NEWLINE} 'Ти бачиш тих істот на камері мого скафандра?'\"\n  STR_GAMEOVER_1: \"Ми зазнали поразки, прибульці знищили нашу останню надію на порятунок. {NEWLINE} X-Com зруйновано, а Земля лежить під ногами давнього ворога.\"\n  STR_GAMEOVER_2: \"Т'льєт гримить високо в стратосфері і починає рухатися по всьому світу, сіючи смерть і збираючи залишки людської раси. Глибоко в його надрах починає прокидатися вбивчий інопланетний розум.\"\n  STR_GAMEOVER_3: \"У столицях усіх країн розробляються відчайдушні плани. Все марно, без технологій, які надавав дослідницький проект X-Com, наша зброя неефективна.\"\n  STR_GAMEOVER_4: \"Прибульці облаштовують бази на полярних шапках і починають плавити лід, світ перетвориться на величезне море. Залишки людської раси збирають і використовують у мерзенних селекційних експериментах для невідомих цілей прибульців. Небо темніє, і на землі Землі насувається могутня пошесть.\"\n  STR_GAMEOVER_5: \"Ми не можемо чинити опір новому світовому порядку, ті, хто намагається зустріти вогненну долю від рук незрозумілої зброї прибульців. Для решти з нас такого благословенного звільнення не буде, матінка-Земля стане світом прибульців, а людство загубиться під повзучим жахіттям.\"\n  STR_OUTRO_1: \"Гробниця, спустошена і знищена, з труни в її центрі лунає бурхливий рев.{NEWLINE}Дурні, ви всі загинете....................\"\n  STR_OUTRO_2: \"................. нікому не вдасться втекти.\"\n  STR_OUTRO_3: \"З гробниці лунає потужний вибух, який розриває місто, уламки і дим наповнюють повітря. Плани прибульців зірвані........\"\n  STR_OUTRO_4: \"Грізна велич Т'льєта починає розвалюватися. Полум'я і дим вивергаються з його блискучих шпилів і адамантових залів.\"\n  STR_OUTRO_5: \"Могутній корабель прибульців падає в море, крики катованого металу і душ наповнюють повітря. Більше Верховний прибулець не буде мріяти про підкорення світу.\"\n  STR_OUTRO_6: \"Останній, закладаючий вуха звук, і Т'льєт розриває себе на частини.{NEWLINE}Загроза інопланетян зникла, Земля очищена..................\"\n  STR_OUTRO_7: \"Сонна синьо-зелена планета в далекому куточку галактики.\"\n  STR_OUTRO_8: \"Найближче майбутнє - безпечне місце.\"\n  STR_OUTRO_9: \"Інопланетна загроза для Землі вже давно подолана.\"\n  STR_OUTRO_10: \"У величезних мегаполісах, схожих на міста, живуть мільярди людей.\"\n  STR_OUTRO_11: \"Подвиги X-Com та війни з прибульцями - це матеріал для дитячих казок.\"\n  STR_OUTRO_12: \"Але легенди завжди мали звичку містити зерно правди............\"\n  STR_RISE_1: \"Т'льєт, по-різному названий в багатьох легендах з багатьох країн.\"\n  STR_RISE_2: \"З вибуховим криком, що лунає по всьому світу, Т'льєт починає підніматися з морського дна.\"\n  STR_RISE_3: \"Величезна споруда здіймається над водами Мексиканської затоки.\"\n  STR_RISE_4: \"400 мільярдів тонн Чужого металу, могутнє Чуже місто, в якому лежить спляче тіло Останнього Чужого. Ув'язнений на Землі протягом 65 мільйонів років, цей мерзенний космічний Бог починає ворушитися.\"\n  STR_RISE_5: \"Води киплять і вирують, коли могила Верховного прибульця виходить на світло................\"\n  STR_RISE_6: \"......... світло, яке буде недовгим, якщо X-Com не зможе знищити військову машину прибульців.\"\n  STR_YOU_HAVE_FAILED: \"Вам не вдалося зупинити військову машину прибульців. Фінансуючі організації, розчарувавшись у ваших здібностях, намагаються домовитися з ними про невійськове вирішення проблеми. У Загарбників зовсім інші плани, і незабаром весь світ дізнається правду...\"\n  STR_TOTAL_UC: \"ВСЬОГО\"\n  STR_INCOME: \"Дохід\"\n  STR_EXPENDITURE: \"Витрати\"\n  STR_MAINTENANCE: \"Обслуговування\"\n  STR_BALANCE: \"Баланс\"\n  STR_UFO_ACTIVITY_IN_AREAS: \"Активність прибульців у морях \"\n  STR_UFO_ACTIVITY_IN_COUNTRIES: \"Активність прибульців в зонах \"\n  STR_XCOM_ACTIVITY_IN_AREAS: \"Активність X-COM у морях\"\n  STR_XCOM_ACTIVITY_IN_COUNTRIES: \"Активність X-COM в зонах\"\n  STR_FINANCE: \"Фінанси\"\n  STR_DATE_FIRST: \"{0}e\"\n  STR_DATE_SECOND: \"{0}е\"\n  STR_DATE_THIRD: \"{0}є\"\n  STR_DATE_FOURTH: \"{0}е\"\n  STR_FINANCE_THOUSANDS: \"тис. $\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"Бракує спеціальних матеріалів для виготовлення{NEWLINE}{0}{NEWLINE}на базі{NEWLINE}{1}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"Бракує грошей для виготовлення{NEWLINE}{0}{NEWLINE}на базі{NEWLINE}{1}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"Виготовлення{NEWLINE}{0}{NEWLINE}на базі{NEWLINE}{1}{NEWLINE}завершено\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"Виготовлення{NEWLINE}{0}{NEWLINE}на базі{NEWLINE}{1}{NEWLINE}завершено\"\n  STR_OK_5_SECONDS: \"OK - 5 сек\"\n  STR_RESEARCH_COMPLETED: \"Дослідження завершено\"\n  STR_VIEW_REPORTS: \"ЗВІТИ\"\n  STR_WE_CAN_NOW_RESEARCH: \"Ми тепер можемо досліджувати\"\n  STR_WE_CAN_NOW_PRODUCE: \"Ми тепер можемо виготовляти\"\n  STR_SUNDAY: \"НЕДІЛЯ\"\n  STR_MONDAY: \"ПОНЕДІЛОК\"\n  STR_TUESDAY: \"ВІВТОРОК \"\n  STR_WEDNESDAY: \"СЕРЕДА\"\n  STR_THURSDAY: \"ЧЕТВЕР\"\n  STR_FRIDAY: \"П'ЯТНИЦЯ\"\n  STR_SATURDAY: \"СУБОТА\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"Бракує {0} для заправки {1} в {2}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"Бракує {0} для перезарядки {1} на базі {2}\"\n  STR_UFO_IS_NOT_RECOVERED: \"НПО не захоплено\"\n  STR_UFO_IS_RECOVERED: \"НПО захоплено\"\n  STR_CRAFT_IS_LOST: \"Субмарину втрачено\"\n  STR_TERROR_CONTINUES: \"Активність прибульців триває\"\n  STR_ALIENS_DEFEATED: \"Прибульці переможені\"\n  STR_BASE_IS_LOST: \"Базу втрачено\"\n  STR_BASE_IS_SAVED: \"Базу збережено\"\n  STR_ALIEN_BASE_STILL_INTACT: \"Базу прибульців не знищено\"\n  STR_ALIEN_BASE_DESTROYED: \"Базу прибульців знищено\"\n  STR_ALIENS_KILLED: \"ПРИБУЛЬЦІВ ВБИТО\"\n  STR_ALIEN_CORPSES_RECOVERED: \"ТРУПІВ ПРИБУЛЬЦІВ ЗНАЙДЕНО\"\n  STR_LIVE_ALIENS_RECOVERED: \"ЖИВИХ ПРИБУЛЬЦІВ ЗНАЙДЕНО\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"АРТЕФАКТІВ ПРИБУЛЬЦІВ ЗНАЙДЕНО\"\n  STR_ALIEN_BASE_CONTROL_DESTROYED: \"БАЗУ ПРИБУЛЬЦІВ ЗНИЩЕНО\"\n  STR_ALIEN_SYNOMIUM_DEVICE_DESTROYED: \"ІНОПЛАНЕТНИЙ ПРИСТРІЙ СИНОМІУМ ЗНИЩЕНО\"\n  STR_ALIEN_SYNOMIUM_DEVICE_FAILED: \"НЕ ВДАЛОСЯ ЗНИЩИТИ ПРИСТРІЙ СИНОМІУМ\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"ЦИВІЛЬНИХ ВБИТО ПРИБУЛЬЦЯМИ\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"ЦИВІЛЬНИХ ВБИТО СОЛДАТАМИ X-COM\"\n  STR_CIVILIANS_SAVED: \"ЦИВІЛЬНИХ ВРЯТОВАНО\"\n  STR_XCOM_OPERATIVES_KILLED: \"СОЛДАТІВ X-COM ВБИТО\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"СОЛДАТІВ X-COM ЗНИКЛО БЕЗ ВІСТІ\"\n  STR_TANKS_DESTROYED: \"БОЙОВІ ПЛАТФОРМИ Х-СОМ ЗНИЩЕНО\"\n  STR_XCOM_CRAFT_LOST: \"Субмарина Х-СОМ ВТРАЧЕНО\"\n  STR_UFO_RECOVERY: \"НПО ЗНАЙДЕНО\"\n  STR_ALIEN_BASE_RECOVERY: \"БАЗУ ПРИБУЛЬЦІВ ЗНАЙДЕНО\"\n  STR_BASE_UNDER_ATTACK: \"{0} атаковано!\"\n  STR_BASE_DEFENSES_INITIATED: \"ЗАДІЯНО ЗАХИСТ БАЗИ\"\n  STR_GRAV_SHIELD_REPELS_UFO: \"ГРАВ. ЩИТ ВІДШТОВХНУВ НПО!\"\n  STR_FIRING: \"СТРІЛЯЄ\"\n  STR_HIT: \"ВЛУЧИВ!\"\n  STR_UFO_DESTROYED: \"НПО ЗНИЩЕНО\"\n  STR_MISSED: \"ПРОМАХНУВСЯ!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"Продаж/Звільнення персоналу\"\n  STR_VALUE_OF_SALES: \"ВАРТІСТЬ ПРОДАНОГО> {ALT}{0}\"\n  STR_FUNDS: \"ФОНДИ> {ALT}{0}\"\n  STR_SELL_SACK: \"Продати/Звільнити\"\n  STR_VALUE: \"Вартість\"\n  STR_CRAFT_: \"Субмарина> {ALT}{0}\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_UFO_CRASH_RECOVERY: \"ЗАХОПЛЕННЯ ЗБИТОГО НПО\"\n  STR_UFO_CRASH_RECOVERY_BRIEFING: \"Будьте обережні - прибульці можуть бути в НПО чи поблизу нього. Місія завершиться коли всі прибульці будуть вбиті або нейтралізовані. Після цього знайдені рештки НПО, тіла прибульців та їх спорядження будуть евакуйовані. Для припинення місії поверніть бійців в транспорт і натисніть кнопку \\\"Перервати Місію\\\".\"\n  STR_UFO_GROUND_ASSAULT: \"ШТУРМ СУБМАРИНИ ПРИБУЛЬЦІВ\"\n  STR_UFO_GROUND_ASSAULT_BRIEFING: \"Вивчіть місце посадки і, при можливості, отримайте доступ до НПО. Місія завершиться коли всі прибульці будуть вбиті або нейтралізовані. Після цього знайдені рештки НПО, тіла прибульців та їх спорядження будуть евакуйовані. Для припинення місії поверніть бійців в транспорт і натисніть кнопку \\\"Перервати Місію\\\".\"\n  STR_BASE_DEFENSE: \"ЗАХИСТ БАЗИ\"\n  STR_BASE_UC_: \"БАЗА> {0}\"\n  STR_BASE_DEFENSE_BRIEFING: \"Неподалік приземлилася субмарина прибульців. Наша база в серйозній небезпеці. Згідно зі стандартною процедурою, цивільний персонал та кораблі X-COM були евакуйовані. Прибульці будуть проникати на базу через доки та повітряний шлюз. Захищайте базу будь-якою ціною - це битва на смерть. В випадку відступу ви втратите базу.\"\n  STR_ALIEN_COLONY_ATTACK_MISSION: \"МІСІЯ НАПАДУ НА ІНОПЛАНЕТНУ КОЛОНІЮ\"\n  STR_ALIEN_BASE_ASSAULT: \"КОЛОНІЯ ПРИБУЛЬЦІВ ЧАСТИНА ПЕРША\"\n  STR_ALIEN_COLONY_P1_BRIEFING: \"Ця місія - рейд на територію колонії прибульців. На майданчику є 2 рівні, проведіть усіх акванавтів до виходу, що світиться, в першому комплексі і натисніть на кнопку \\\"Перервати місію\\\", щоб продовжити. Будь-яке обладнання, залишене позаду, залишиться на морському дні, поки не буде завершена 2-а секція. Щоб завершити гру, помістіть акванавтів у підводний човен і натисніть на кнопку \\\"Перервати місію\\\".\"\n  STR_ALIEN_COLONY_P2: \"КОЛОНІЯ ПРИБУЛЬЦІВ ЧАСТИНА ДРУГА\"\n  STR_ALIEN_COLONY_P2_BRIEFING: \"Пройдено перший рівень. Ми потрапили в ядро колонії. Тепер наша місія полягає в тому, щоб знищити центр управління, пристрій Синоміум, або ліквідувати всіх прибульців. Щоб перервати місію, розмістіть усіх акванавтів у точці старту і натисніть на кнопку \\\"Перервати місію\\\". Усе життєздатне обладнання X-Com буде повернуто на базу. \"\n  STR_ALIENS_LAUNCH_PORT_TERROR: \"ВТОРГНЕННЯ ПРИБУЛЬЦІВ{NEWLINE}ПОРТ АТАКОВАНО\"\n  STR_PORT_TERROR: \"ПРИБУЛЬЦІ РОЗПОЧАЛИ АТАКУ НА ПОРТ\"\n  STR_PORT_TERROR_BRIEFING: \"Інопланетяни розпочали атаку на наземні об'єкти. Порт і його цивільне населення опинилися під загрозою. Ваш загін повинен знищити всіх прибульців і захистити невинних перехожих від цього вторгнення. Щоб вийти з гри, помістіть акванавтів у літаючу субмарину і натисніть на кнопку \\\"Перервати місію\\\".\"\n  STR_ALIENS_LAUNCH_ISLAND_TERROR: \"ВТОРГНЕННЯ ПРИБУЛЬЦІВ{NEWLINE}ОСТРІВ АТАКОВАНО\"\n  STR_ISLAND_TERROR: \"ПРИБУЛЬЦІ РОЗПОЧАЛИ АТАКУ НА ОСТРІВ\"\n  STR_ISLAND_TERROR_BRIEFING: \"Інопланетяни розпочали атаку на наземні об'єкти. Острів та його цивільне населення опинилися під загрозою. Ваш загін повинен знищити всіх прибульців і захистити мирних мешканців від цього вторгнення. Щоб вийти з гри, помістіть акванавтів у літаючу субмарину і натисніть на кнопку \\\"Перервати місію\\\".\"\n  STR_ALIENS_ATTACK_SHIPPING_ROUTE: \"ВТОРГНЕННЯ ПРИБУЛЬЦІВ{NEWLINE}ТОРГІВЕЛЬНИЙ ШЛЯХ\"\n  STR_CARGO_SHIP_P1: \"ВАНТАЖНЕ СУДНО ЧАСТИНА ПЕРША\"\n  STR_CARGO_SHIP_P2: \"ВАНТАЖНЕ СУДНО ЧАСТИНА ДРУГА\"\n  STR_CRUISE_SHIP_P1: \"КРУЇЗНИЙ ЛАЙНЕР ЧАСТИНА ПЕРША\"\n  STR_CRUISE_SHIP_P2: \"КРУЇЗНИЙ ЛАЙНЕР ЧАСТИНА ДРУГА\"\n  STR_SHIP_RESCUE_MISSION: \"МІСІЯ З ПОРЯТУНКУ СУДНА\"\n  STR_SHIP_RESCUE_P1_BRIEFING: \"Суть цієї місії полягає у знищенні всіх підрозділів прибульців на кораблі та збереженні життя всіх цивільних на борту. Прибульці розосереджені на верхніх і нижніх палубах, зачистіть верхні палуби, перш ніж заходити на нижні. Щоб вийти з гри, помістіть акванавтів у літаючу субмарину і натисніть на кнопку \\\"Перервати місію\\\".\"\n  STR_SHIP_RESCUE_P2_BRIEFING: \"Тепер, коли верхня палуба вільна, переходимо до нижньої. Використовуючи вантажний ліфт, ми спускаємося в трюм. Щоб завершити місію, ваш загін повинен знищити всіх прибульців на цьому рівні. Щоб перервати місію, розмістіть усіх акванавтів у точці старту ліфта і натисніть на кнопку \\\"Перервати місію\\\".\"\n  STR_ALIEN_ACTIVITY_DETECTED: \"ПОМІЧЕНА АКТИВНІСТЬ ПРИБУЛЬЦІВ\"\n  STR_ALIEN_CONTACT_SITE_MISSION: \"МІСІЯ НА МІСЦІ КОНТАКТУ З ПРИБУЛЬЦЯМИ\"\n  STR_ARTIFACT_SITE_P1: \"МІСЦЕ КОНТАКТУ З ПРИБУЛЬЦЯМИ ЧАСТИНА ПЕРША\"\n  STR_ARTIFACT_SITE_P1_BRIEFING: \"Ця місія - рейд на щойно активовану базу зв'язку прибульців. На об'єкті є 2 рівні: морське дно з пірамідами прибульців і прихований комплекс прибульців. Доставте всіх акванавтів до входу в комплекс і натисніть на кнопку \\\"Перервати місію\\\", щоб продовжити. Щоб завершити гру, помістіть акванавтів у літаючу субмарину і натисніть на кнопку \\\"Перервати місію\\\".\"\n  STR_ARTIFACT_SITE_P2: \"МІСЦЕ КОНТАКТУ З ПРИБУЛЬЦЯМИ ЧАСТИНА ДРУГА\"\n  STR_ARTIFACT_SITE_P2_BRIEFING: \"Після \\\"переговорів\\\" із охороною прибульців та входу в комплекс ціль місії стала зрозумілою. Щоб завершити місію, проникніть у серце об'єкта прибульців і знищіть молекулярний контрольний пристрій Синоміум. Щоб перервати місію, розмістіть всіх акванавтів на стартовій точці підйомника і натисніть на кнопку \\\"Перервати місію\\\".\"\n  STR_SIGSBEE_DEEP_MISSION: \"ГЛИБИННА МІСІЯ У СІГЗБІ{NEWLINE}МІСТО ПРИБУЛЬЦІВ РІВЕНЬ ПЕРШИЙ\"\n  STR_TLETH_P1_BRIEFING: \"Ми входимо в невідоме, і далі на нас може чекати що завгодно. Ми знаємо, що до міста прибульців є ще 2 рівні, і ваш загін повинен дійти до виходу на цьому рівні, щоб потрапити на наступний. Розмістіть всіх акванавтів на виході і натисніть кнопку \\\"Перервати місію\\\", щоб продовжити. Переривання місії в іншому місці призведе до її завершення.\"\n  STR_TLETH_ATTACK_MISSION: \"НАПАД НА Т'ЛЬЄТ{NEWLINE}МІСТО ПРИБУЛЬЦІВ РІВЕНЬ ДРУГИЙ\"\n  STR_TLETH_P2_BRIEFING: \"Далі у невідомість, звідси на нас може чекати що завгодно. Ми знаємо, що в місті прибульців є ще один рівень, і ваш загін повинен дійти до виходу на цьому рівні, щоб потрапити на наступний. Розмістіть всіх акванавтів на виході і натисніть кнопку \\\"Перервати місію\\\", щоб продовжити. Переривання місії в іншому місці призведе до її завершення.\"\n  STR_FINAL_TLETH_MISSION: \"Т'ЛЬЄТ: ФІНАЛЬНА МІСІЯ{NEWLINE}МІСТО ПРИБУЛЬЦІВ РІВЕНЬ ТРЕТІЙ\"\n  STR_TLETH_P3_BRIEFING: \"Кінець наближається, відтепер ми шукаємо склеп останнього прибульця. Знищте 8 джерел живлення в гробниці, щоб покінчити із загрозою прибульців. Не здавайтеся! Переривання місії призведе до її завершення.\"\n  STR_TLETH_P1: \"ІНОПЛАНЕТНЕ МІСТО: РІВЕНЬ ПЕРШИЙ\"\n  STR_TLETH_P2: \"ІНОПЛАНЕТНЕ МІСТО: РІВЕНЬ ДРУГИЙ\"\n  STR_TLETH_P3: \"ІНОПЛАНЕТНЕ МІСТО: РІВЕНЬ ТРЕТІЙ\"\n  STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION: \"НЕМАЄ ВІЛЬНОГО ДОКУ ДЛЯ БУДІВНИЦТВА КОРАБЛЯ!{SMALLLINE}Кожний корабель приписаний до бази, транспортований на базу, придбаний або такий, який тільки будується, використовує один док. Збудуйте новий док або транспортуйте якийсь корабель на іншу базу.\"\n  STR_NO_FREE_HANGARS_FOR_PURCHASE: \"НЕМАЄ ВІЛЬНОГО ДОКУ ДЛЯ КУПІВЛІ КОРАБЛЯ!{SMALLLINE}Кожний корабель приписаний до бази, транспортований на базу, придбаний або такий, який тільки будується, використовує один док. Збудуйте новий док або транспортуйте якийсь корабель на іншу базу.\"\n  STR_NO_FREE_HANGARS_FOR_TRANSFER: \"НЕМАЄ ВІЛЬНОГО ДОКУ ДЛЯ ТРАНСПОРТУВАННЯ!{SMALLLINE}Кожний корабель приписаний до бази, транспортований на базу, придбаний або такий, який тільки будується, використовує один док. Збудуйте новий док або транспортуйте якийсь корабель на іншу базу.\"\n  STR_CANNOT_BUILD_HERE: \"НЕ МОЖНА БУДУВАТИ ТУТ!{SMALLLINE}Будівництво можливе лише поруч з уже наявним модулем.\"\n  STR_NO_FREE_ACCOMODATION: \"НЕДОСТАТНЬО ЖИТЛОВОЇ ПЛОЩІ!{SMALLLINE}База призначення не має достатньо вільних місць в житлових модулях.\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"НЕ ДОСТАТНЬО РОБОЧИХ МІСЦЬ!{SMALLLINE}Будуйте нову майстерню або зменшуйте роботу над іншими проектами.\"\n  STR_NOT_ENOUGH_MONEY: \"БРАКУЄ ГРОШЕЙ!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"НЕ ДОСТАТНЬО МІСЦЯ НА СКЛАДАХ!{SMALLLINE}Будуйте нові склади або транспортуйте наявні предмети на інші бази.\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"НЕДОСТАТНЬО ЖИТЛОВОЇ ПЛОЩІ!{SMALLLINE}Збудуйте житлові модулі або транспортуйте персонал на інші бази.\"\n  STR_LAUNCH_INTERCEPTION: \"ПОЧАТИ ПЕРЕХОПЛЕННЯ\"\n  STR_CRAFT: \"КОРАБЕЛЬ\"\n  STR_STATUS: \"СТАТУС\"\n  STR_BASE: \"БАЗА\"\n  STR_READY: \"ГОТОВИЙ\"\n  STR_OUT: \"НА ВИЛЬОТІ\"\n  STR_REPAIRS: \"НА РЕМОНТІ\"\n  STR_REFUELLING: \"ЗАПРАВЛЯЄТЬСЯ\"\n  STR_REARMING: \"ПЕРЕЗАРЯД.\"\n  STR_TARGET: \"ЦІЛЬ: {0}\"\n  STR_WAY_POINT: \"ТОЧКА ШЛЯХУ\"\n  STR_ARE_YOU_SURE_CYDONIA: \"Ви впевнені, що бажаєте відправити експедицію до Т'льєту?\"\n  STR_YES: \"ТАК\"\n  STR_NO: \"НІ\"\n  STR_SELECT_DESTINATION: \"ВИБЕРІТЬ ЦІЛЬ\"\n  STR_CYDONIA: \"T'ЛЬЄХ\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"ВИБЕРІТЬ МІСЦЕ ДЛЯ НОВОЇ БАЗИ\"\n  STR_RETURN_TO_BASE: \"ПОВЕРНУТИСЬ НА БАЗУ\"\n  STR_SELECT_NEW_TARGET: \"ОБЕРІТЬ НОВУ ЦІЛЬ \"\n  STR_PATROL: \"ПАТРУЛЮВАТИ\"\n  STR_STATUS_: \"СТАТУС>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"ПОШКОДЖЕНИЙ - ПОВЕРТАЄТЬСЯ НА БАЗУ\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"МАЛО ПАЛЬНОГО - ПОВЕРТАЄТЬСЯ НА БАЗУ\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"МІСІЮ ЗАВЕРШЕНО - ПОВЕРТАЄТЬСЯ НА БАЗУ\"\n  STR_PATROLLING: \"ПАТРУЛЮЄ\"\n  STR_TAILING_UFO: \"ПЕРЕСЛІДУЄ НПО\"\n  STR_INTERCEPTING_UFO: \"ПЕРЕХОПЛЮЄ НПО-{0}\"\n  STR_RETURNING_TO_BASE: \"ПОВЕРТАЄТЬСЯ НА БАЗУ\"\n  STR_DESTINATION_UC_: \"ПУНКТ ПРИЗНАЧЕННЯ:{0}\"\n  STR_BASE_UC: \"БАЗА>{ALT}{0}\"\n  STR_SPEED_: \"ШВИДКІСТЬ>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"МАКСИМАЛЬНА ШВИДКІСТЬ>{ALT}{0}{ALT}\"\n  STR_ALTITUDE_: \"ДЕТАЛІ> {ALT}{0}\"\n  STR_AIRBORNE: \"ДЕСАНТ\"\n  STR_VERY_LOW: \"МІЛИНА\"\n  STR_LOW_UC: \"НОРМАЛЬНО\"\n  STR_HIGH_UC: \"ГЛИБОКО\"\n  STR_VERY_HIGH: \"ДУЖЕ ГЛИБОКО\"\n  STR_FUEL: \"ПАЛЬНЕ>{ALT}{0}\"\n  STR_WEAPON_ONE: \"ЗБРОЯ-1>{ALT}{0}\"\n  STR_NONE_UC: \"НЕМАЄ\"\n  STR_ROUNDS_: \"БОЄЗАПАС>{ALT}{0}\"\n  STR_WEAPON_TWO: \"ЗБРОЯ-2>{ALT}{0}\"\n  STR_INTERCEPTION_CRAFT: \"Субмарина\"\n  STR_BASE_: \"База> {0}\"\n  STR_NAME_UC: \"ІМ'Я\"\n  STR_AMMO_: \"НАБОЇ>{ALT}{0}\"\n  STR_CREW: \"ЕКІПАЖ\"\n  STR_EQUIPMENT_UC: \"СПОРЯДЖЕННЯ\"\n  STR_ARMOR: \"БРОНЯ\"\n  STR_MAX: \"МАКС>{ALT}{0}\"\n  STR_ROOKIE: \"Матрос\"\n  STR_SQUADDIE: \"Старший матрос\"\n  STR_SERGEANT: \"Мічман\"\n  STR_CAPTAIN: \"Лейтинант\"\n  STR_COLONEL: \"Командир\"\n  STR_COMMANDER: \"Капітан\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"Виберіть екіпаж для {0}\"\n  STR_SORT_BY: \"ВІДСОРТУВАТИ ЗА...\"\n  STR_ORIGINAL_ORDER: \"ЗВИЧАЙНИЙ ПОРЯДОК\"\n  STR_MISSIONS2: \"МІСІЯ\"\n  STR_KILLS2: \"ВБИВСТВ\"\n  STR_WOUND_RECOVERY2: \"ЗАГОЄННЯ РАН\"\n  STR_SPACE_AVAILABLE: \"МІСЦЯ ВІЛЬНО>{ALT}{0}\"\n  STR_SPACE_USED: \"МІСЦЯ ЗАЙНЯТО>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"МІСЦЯ ЗАЙНЯТО\"\n  STR_RANK: \"ЗВАННЯ\"\n  STR_WOUNDED: \"ПОРАНЕНИЙ\"\n  STR_EQUIPMENT_FOR_CRAFT: \"Спорядження для {0}\"\n  STR_DEFENSE_VALUE: \"Ступінь Захисту\"\n  STR_HIT_RATIO: \"Точність\"\n  STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION: \"{0}{ALT}{NEWLINE}готовий до{NEWLINE}приземлення біля{NEWLINE}{ALT}{1}\"\n  STR_BEGIN_MISSION: \"Почати операцію?\"\n  STR_SELECT_ARMAMENT: \"Виберіть зброю\"\n  STR_AMMUNITION_AVAILABLE: \"БОЄПРИПАСІВ ДОСТУПНО\"\n  STR_ARMAMENT: \"ЗБРОЯ\"\n  STR_NOT_AVAILABLE: \"Н.Д.\"\n  STR_SELECT_ARMOR_FOR_SOLDIER: \"ОБЕРІТЬ БРОНЮ ДЛЯ{NEWLINE}{ALT}{0}\"\n  STR_TYPE: \"ТИП\"\n  STR_PLASTIC_AQUA_ARMOR_UC: \"АКВАПЛАСТИКОВА БРОНЯ\"\n  STR_ION_ARMOR_UC: \"ІОННА БРОНЯ\"\n  STR_MAGNETIC_ION_ARMOR_UC: \"МАГНІТНО-ІОННА БРОНЯ\"\n  STR_PLASTIC_AQUA_ARMOR_UFOPEDIA: \"Ця броня використовує нещодавно відкриту інопланетну речовину, аквапластик. Із нею наші акванавти мають шанс протистояти вторгненню прибульців.\"\n  STR_ION_ARMOR_UFOPEDIA: \"Потужний новий захист для акванавтів, ця броня живиться від джерела іонної енергії і значно посилює швидкість і силу власника, вона пропонує найкращий захист для бойових підрозділів.\"\n  STR_MAGNETIC_ION_ARMOR_UFOPEDIA: \"Удосконалення іонної броні, що включає технологію магнітної підвіски, яка забезпечує повну свободу пересування у водному середовищі.\"\n  STR_SELECT_ARMOR: \"Виберіть броню\"\n  STR_NORTH: \"ПІВНІЧ\"\n  STR_NORTH_EAST: \"ПІВНІЧНИЙ СХІД\"\n  STR_EAST: \"СХІД\"\n  STR_SOUTH_EAST: \"ПІВДЕННИЙ СХІД\"\n  STR_SOUTH: \"ПІВДЕНЬ\"\n  STR_SOUTH_WEST: \"ПІВДЕННИЙ ЗАХІД\"\n  STR_WEST: \"ЗАХІД\"\n  STR_NORTH_WEST: \"ПІВНІЧНИЙ ЗАХІД\"\n  STR_SELECT_ACTION: \"ВИБЕРІТЬ ЗАВДАННЯ\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"ПРОДОВЖИТИ ПЕРЕХОПЛЕННЯ\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"ПЕРЕСЛІДУВАТИ БЕЗ ПЕРЕХОПЛЕННЯ\"\n  STR_VERY_LARGE: \"ДУЖЕ ВЕЛИКИЙ\"\n  STR_LARGE: \"ВЕЛИКИЙ\"\n  STR_MEDIUM_UC: \"СЕРЕДНІЙ\"\n  STR_SMALL: \"МАЛИЙ\"\n  STR_VERY_SMALL: \"ДУЖЕ МАЛИЙ\"\n  STR_GROUNDED: \"ПРИЗЕМЛИВСЯ\"\n  STR_DETECTED: \"Виявлено\"\n  STR_SIZE_UC: \"РОЗМІР\"\n  STR_ALTITUDE: \"ГЛИБИНА\"\n  STR_HEADING: \"НАПРЯМ\"\n  STR_SPEED: \"ШВИДКІСТЬ\"\n  STR_CENTER_ON_UFO_TIME_5_SECONDS: \"ЦЕНТР НА ДІЛЯНЦІ-ЧАС=5 Сек\"\n  STR_TRACKING_LOST: \"ВТРАЧЕНО\"\n  STR_REDIRECT_CRAFT: \"ПЕРЕНАПРАВИТИ КОРАБЕЛЬ\"\n  STR_GO_TO_LAST_KNOWN_UFO_POSITION: \"ЛЕТІТИ ДО ОСТАННЬОЇ ВІДОМОЇ ПОЗИЦІЇ НПО\"\n  STR_UFO_: \"НПО-{0}\"\n  STR_ALIEN_BASE_: \"КОЛОНІЯ ПРИБУЛЬЦІВ-{0}\"\n  STR_CRASH_SITE_: \"МІСЦЕ ПАДІННЯ-{0}\"\n  STR_LANDING_SITE_: \"МІСЦЕ ПРИЗЕМЛЕННЯ-{0}\"\n  STR_WAY_POINT_: \"ТОЧКА ШЛЯХУ-{0}\"\n  STR_TERROR_SITE: \"МІСЦЕ ТЕРОРУ-{0}\"\n  STR_ARTIFACT_SITE: \"МІСЦЕ АРТЕФАКТУ-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}досяг{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"Патрулювання\"\n  STR_ALIEN_ORIGINS: \"Походження прибульців\"\n  STR_THE_ULTIMATE_THREAT: \"Основна загроза\"\n  STR_TLETH_ALIEN_CITY: \"Т'льєт, місто прибульців\"\n  STR_UFOPAEDIA: \"УФОПЕДІЯ\"\n  STR_XCOM_CRAFT_ARMAMENT: \"КОРАБЛІ X-COM ТА ЇХНЄ ОЗБРОЄННЯ\"\n  STR_HEAVY_WEAPONS_PLATFORMS: \"ПІДВОДНІ БОЙОВІ ПЛАТФОРМИ (ПБП)\"\n  STR_WEAPONS_AND_EQUIPMENT: \"ЗБРОЯ ТА СПОРЯДЖЕННЯ\"\n  STR_ALIEN_ARTIFACTS: \"ПІДВОДНІ АРТЕФАКТИ\"\n  STR_BASE_FACILITIES: \"МОДУЛІ БАЗИ\"\n  STR_ALIEN_LIFE_FORMS: \"ПОЗАЗЕМНІ ФОРМИ ЖИТТЯ\"\n  STR_ALIEN_RESEARCH_UC: \"ДІЯЛЬНІСТЬ ПРИБУЛЬЦІВ\"\n  STR_UFO_COMPONENTS: \"КОМПОНЕНТИ НПО\"\n  STR_UFOS: \"НПО\"\n  STR_SELECT_ITEM: \"ОБЕРІТЬ ПРЕДМЕТ\"\n  STR_ACCELERATION: \"ПРИСКОРЕННЯ>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"ЗАПАС ПАЛЬНОГО>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"ПІДВІСОК ДЛЯ ЗБРОЇ>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"ЗАПАС МІЦНОСТІ>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"ОБ'ЄМ ВАНТАЖНОГО ВІДСІКУ>{ALT}{0}{ALT}\"\n  STR_HWP_CAPACITY: \"МІСЦЬ ДЛЯ ПБП>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"Пошкодження\"\n  STR_RANGE: \"Радіус ураження\"\n  STR_KILOMETERS: \"{0} км\"\n  STR_ACCURACY: \"Точність\"\n  STR_RE_LOAD_TIME: \"Час перезарядки\"\n  STR_SECONDS: \"{0}с\"\n  STR_DAMAGE_ARMOR_PIERCING: \"БРОНЕБІЙНИЙ\"\n  STR_DAMAGE_INCENDIARY: \"ФОСФОРНИЙ\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"РОЗРИВНИЙ\"\n  STR_DAMAGE_LASER_BEAM: \"ГАУСС-ПРОМІНЬ\"\n  STR_DAMAGE_PLASMA_BEAM: \"АКУСТИЧНИЙ ПРОМІНЬ\"\n  STR_DAMAGE_STUN: \"ПАРАЛІЗАТОР\"\n  STR_DAMAGE_MELEE: \"БЛИЖНІЙ БІЙ\"\n  STR_DAMAGE_ACID: \"КИСЛОТА\"\n  STR_DAMAGE_SMOKE: \"ДИМ\"\n  STR_SHOT_TYPE: \"ТИП\"\n  STR_ACCURACY_UC: \"ТОЧНІСТЬ\"\n  STR_TIME_UNIT_COST: \"ОЧКИ ДІЙ\"\n  STR_DAMAGE_UC: \"ПОШКОДЖЕННЯ\"\n  STR_AMMO: \"ЗАРЯД\"\n  STR_SHOT_TYPE_AUTO: \"Черга\"\n  STR_SHOT_TYPE_SNAP: \"Навмання\"\n  STR_SHOT_TYPE_AIMED: \"Прицільно\"\n  STR_CONSTRUCTION_TIME: \"Час будівництва\"\n  STR_CONSTRUCTION_COST: \"Вартість будівництва\"\n  STR_MAINTENANCE_COST: \"Вартість утримання\"\n  STR_LOW: \"Низький \"\n  STR_MEDIUM: \"Середній\"\n  STR_HIGH: \"Високий\"\n  STR_CRAFT_WEAPON: \"Зброя для субмарин\"\n  STR_CRAFT_AMMUNITION: \"Боєприпаси для субмарин\"\n  STR_HEAVY_WEAPONS_PLATFORM: \"Системи важкого озброєння\"\n  STR_WEAPON: \"Зброя\"\n  STR_AMMUNITION: \"Боєприпаси\"\n  STR_EQUIPMENT: \"Спорядження\"\n  STR_ALIEN_CORPSE: \"Труп прибульця\"\n  STR_UFO_COMPONENT: \"Компонент Субмарин Прибульців\"\n  STR_PERSONAL_ARMOR: \"Бронекостюм\"\n  STR_RAW_MATERIALS: \"Вихідні матеріали\"\n  STR_HWP_SOLID_HARPOON_BOLTS: \"Масивні гарпуни\"\n  STR_ALIEN: \"Прибулець\"\n  STR_AQUATOID: \"Акватоїд\"\n  STR_GILLMAN: \"Зябролюдина\"\n  STR_LOBSTERMAN: \"Лобстеролюдина\"\n  STR_TASOTH: \"Тасот\"\n  STR_CALCINITE: \"Кальциніт\"\n  STR_DEEP_ONE: \"Глибинник\"\n  STR_BIODRONE: \"Біо-дрон\"\n  STR_TENTACULAT: \"Тентакулат\"\n  STR_TRISCENE: \"Трисцен\"\n  STR_HALLUCINOID: \"Галюциноїд\"\n  STR_XARQUID: \"Ксарквід\"\n  STR_ZOMBIE: \"Зомбі\"\n  STR_LIVE_COMMANDER: \"Командир\"\n  STR_LIVE_NAVIGATOR: \"Навігатор\"\n  STR_LIVE_MEDIC: \"Медик\"\n  STR_LIVE_TECHNICIAN: \"Інженер\"\n  STR_LIVE_SQUAD_LEADER: \"Командир загону\"\n  STR_LIVE_SOLDIER: \"Солдат\"\n  STR_LIVE_TERRORIST: \"Терорист \"\n  STR_AQUATOID_COMMANDER: \"Командир акватоїдів\"\n  STR_AQUATOID_NAVIGATOR: \"Акватоїд-навігатор\"\n  STR_AQUATOID_MEDIC: \"Акватоїд-медик\"\n  STR_AQUATOID_TECHNICIAN: \"Акватоїд-інженер\"\n  STR_AQUATOID_SQUAD_LEADER: \"Акватоїд-лідер \"\n  STR_AQUATOID_SOLDIER: \"Акватоїд-солдат\"\n  STR_GILLMAN_COMMANDER: \"Зябролюдина-командир\"\n  STR_GILLMAN_TECHNICIAN: \"Зябролюдина-інженер\"\n  STR_GILLMAN_SQUAD_LEADER: \"Зябролюдина-лідер\"\n  STR_GILLMAN_SOLDIER: \"Зябролюдина-солдат\"\n  STR_LOBSTERMAN_COMMANDER: \"Командир лобстеролюдей\"\n  STR_LOBSTERMAN_NAVIGATOR: \"Лобстеролюдина-навігатор\"\n  STR_LOBSTERMAN_TECHNICIAN: \"Лобстеролюдина-інженер\"\n  STR_LOBSTERMAN_SQUAD_LEADER: \"Командир загону лобстеролюдей\"\n  STR_LOBSTERMAN_SOLDIER: \"Лобстеролюдина-солдат \"\n  STR_TASOTH_SQUAD_LEADER: \"Командир загону тасотів\"\n  STR_TASOTH_SOLDIER: \"Тасот-солдат\"\n  STR_CALCINITE_TERRORIST: \"Кальциніт-терорист\"\n  STR_DEEP_ONE_TERRORIST: \"Глибинник-терорист\"\n  STR_BIODRONE_TERRORIST: \"Біодрон-терорист\"\n  STR_TENTACULAT_TERRORIST: \"Тентакулат-терорист\"\n  STR_TRISCENE_TERRORIST: \"Трисцен-терорист\"\n  STR_HALLUCINOID_TERRORIST: \"Галюциноїд-терорист\"\n  STR_XARQUID_TERRORIST: \"Ксарвід-терорист\"\n  STR_ION_BEAM_ACCELERATORS: \"Іонно-променеві прискорювачі\"\n  STR_MAGNETIC_NAVIGATION: \"Магнітна навігація\"\n  STR_ALIEN_SUB_CONSTRUCTION: \"Конструкція субмарини прибульців\"\n  STR_ALIEN_CRYOGENICS: \"Кріогеніка прибульців\"\n  STR_ALIEN_CLONING: \"Клонування прибульців\"\n  STR_ALIEN_LEARNING_ARRAYS: \"Навчальні архіви прибульців\"\n  STR_ALIEN_IMPLANTER: \"Імплантатор прибульців\"\n  STR_EXAMINATION_ROOM: \"Кімната допитів\"\n  STR_AQUA_PLASTICS: \"Аквапластик\"\n  STR_ALIEN_REANIMATION_ZONE: \"Зона реанімації прибульців\"\n  STR_PLASTIC_AQUA_ARMOR: \"Аквапластикова броня\"\n  STR_ION_ARMOR: \"Іонна броня\"\n  STR_MAGNETIC_ION_ARMOR: \"Магнітна іонна броня\"\n  STR_HWP_AQUA_JET_MISSILES: \"Гідрореактивні торпеди\"\n  STR_HWP_DISPLACER_PWT: \"Боєприпаси до І.Х.Т.\"\n  STR_GAUSS_TECH: \"Гаус-Технологія\"\n  STR_NEW_FIGHTER_FLYING_SUB: \"Нова літаюча бойова субмарина\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"Новий винищувач-транспорт\"\n  STR_THE_LATEST_FLYING_SUB: \"Новітня літаюча субмарина\"\n  STR_ARMOR_PIERCING: \"БРОНЕБІЙНИЙ\"\n  STR_COELACANTH_GAS_CANNON: \"Целакант/Газова гармата\"\n  STR_COELACANTH_AQUA_JET: \"Целакант/Торпеда\"\n  STR_COELACANTH_GAUSS: \"Целакант/Гаусс\"\n  STR_DISPLACER_SONIC: \"Витіснювач/Акуст. гармата\"\n  STR_DISPLACER_PWT: \"Витіснювач/І.Х.Т.\"\n  STR_AJAX_LAUNCHER: \"Ajax-гармата\"\n  STR_DUP_HEAD_LAUNCHER: \"СЗУ-гармата\"\n  STR_CRAFT_GAS_CANNON: \"Корабельна газова гармата\"\n  STR_PWT_CANNON: \"І.Х.Т. Гармата\"\n  STR_GAUSS_CANNON: \"Гаус-гармата\"\n  STR_GAUSS_CANNON_AMMO: \"Боєприпаси до гаус-гармати\"\n  STR_SONIC_OSCILLATOR: \"Акустичний випромінювач\"\n  STR_AJAX_TORPEDOES: \"Ajax-торпеда\"\n  STR_DUP_HEAD_TORPEDOES: \"СЗУ-торпеда\"\n  STR_CRAFT_GAS_CANNON_ROUNDS_X50: \"Газові патрони (x50)\"\n  STR_SONIC_WAVE: \"Акустична хвиля\"\n  STR_PULSE_WAVE_TORPEDOES: \"І.Х.Т. Боєприпаси\"\n  STR_SOLDIER: \"Акванавт\"\n  STR_SCIENTIST: \"Вчений\"\n  STR_ENGINEER: \"Інженер\"\n  STR_NORTH_ATLANTIC: \"Північна Атлантика \"\n  STR_SOUTH_ATLANTIC: \"Півд. Атлантика\"\n  STR_NORTH_PACIFIC: \"Пн. Тихого океану\"\n  STR_SOUTH_PACIFIC: \"Пд. Тихого океану\"\n  STR_MEDITERRANEAN: \"Середземномор'я\"\n  STR_SOUTH_CHINA_SEA: \"Південнокит. море\"\n  STR_INDIAN_OCEAN: \"Індійський Океан\"\n  STR_THE_EAST_SEA: \"Японське море\"\n  STR_NORTH_SEA: \"Північне море\"\n  STR_CARRIBEAN: \"Карибський басейн\"\n  STR_ANTARCTIC: \"Антарктика\"\n  STR_ARCTIC: \"Арктика\"\n  STR_EURASIA: \"Євразія\"\n  STR_NORTH_AMERICA: \"Північна Америка\"\n  STR_AFRICA: \"Африка\"\n  STR_MAXIMUM_SPEED: \"Макс. швидкість\"\n  STR_TRANSMISSION_RESOLVER_UC: \"РОЗДІЛЬНИК ПЕРЕДАЧІ\"\n  STR_TRITON: \"ТРИТОН\"\n  STR_HAMMERHEAD: \"РИБА-МОЛОТ\"\n  STR_LEVIATHAN: \"ЛЕВІАТАН\"\n  STR_BARRACUDA: \"БАРРАКУДА\"\n  STR_MANTA: \"СКАТ\"\n  STR_UFO: \"СУБМАРИНА ПРИБУЛЬЦІВ\"\n  STR_AJAX: \"ТОРПЕДА \\\"AJAX\\\"\"\n  STR_DUP_HEAD: \"ТОРПЕДА С.З.У.\"\n  STR_CRAFT_GAS_CANNON_UC: \"КОРАБЕЛЬНА ГАЗОВА ГАРМАТА\"\n  STR_PWT_CANNON_UC: \"І.Х.Т. ГАРМАТА\"\n  STR_GAUSS_CANNON_UC: \"ГАУС-ГАРМАТА\"\n  STR_SONIC_OSCILLATOR_UC: \"АКУСТИЧНИЙ ВИПРОМІНЮВАЧ\"\n  STR_DAMAGE_CAPACITY: \"Запас міцності\"\n  STR_WEAPON_POWER: \"Потужність зброї\"\n  STR_WEAPON_RANGE: \"Дальність зброї\"\n  STR_AIR_LOCK: \"Повітряний шлюз\"\n  STR_LABORATORY: \"Лабораторія\"\n  STR_WORKSHOP: \"Майстерня\"\n  STR_STANDARD_SONAR: \"Стандартний гідролокатор\"\n  STR_WIDE_ARRAY_SONAR: \"Широкосмуговий гідролокатор\"\n  STR_TORPEDO_DEFENSES: \"Торпедний захист\"\n  STR_GENERAL_STORES: \"Склад\"\n  STR_ALIEN_CONTAINMENT: \"Ізолятор прибульців\"\n  STR_GAUSS_DEFENSES: \"Гаусс-захист\"\n  STR_SONIC_DEFENSES: \"Акустичний захист\"\n  STR_PWT_DEFENSES: \"ІХТ-захист\"\n  STR_BOMBARDMENT_SHIELD: \"Антибомбардувальний щит\"\n  STR_MC_GENERATOR: \"МК-генератор\"\n  STR_MC_LAB: \"МК-лабораторія\"\n  STR_TRANSMISSION_RESOLVER: \"Дешифратор сигналів\"\n  STR_SUB_PEN: \"Субмаринний док\"\n  STR_USA: \"США\"\n  STR_ALASKA: \"АЛЯСКА\"\n  STR_EU_SYNDICATE: \"ЄВРОСИНДИКАТ\"\n  STR_ARABIAN_BLOC: \"АРАБСЬКИЙ БЛОК\"\n  STR_EGYPTIAN_CARTEL: \"ЄГИПЕТ. КАРТЕЛЬ\"\n  STR_AFRICA_CORP: \"АФРИК. КОРПОРАЦІЯ\"\n  STR_BRAZILIAN_UNION: \"БРАЗИЛЬСЬКИЙ СОЮЗ\"\n  STR_NEW_MEXICO: \"НОВА МЕКСИКА\"\n  STR_ASIAN_COALITION: \"АЗІЙСЬКА КОАЛІЦІЯ\"\n  STR_SCANDINAVIA: \"СКАНДИНАВІЯ\"\n  STR_NEO_JAPAN: \"НЕО-ЯПОНІЯ\"\n  STR_FREE_CHINA: \"ВІЛЬНИЙ КИТАЙ\"\n  STR_AUSTRALASIA: \"АВСТРАЛАЗІЯ\"\n  STR_FED_KOREA: \"ФЕДЕРАЦІЯ КОРЕЯ\"\n  STR_EURASIA_UC: \"ЄВРАЗІЯ\"\n  STR_ICELANDIC_UNION: \"ІСЛАНДСЬКИЙ СОЮЗ\"\n  STR_TANK: \"Система підводного озброєння\"\n  STR_CIVILIAN: \"Цивільний\"\n  STR_JAN: \"Січ\"\n  STR_FEB: \"Лют\"\n  STR_MAR: \"Бер\"\n  STR_APR: \"Кві\"\n  STR_MAY: \"Тра\"\n  STR_JUN: \"Чер\"\n  STR_JUL: \"Лип\"\n  STR_AUG: \"Сер\"\n  STR_SEP: \"Вер\"\n  STR_OCT: \"Жов\"\n  STR_NOV: \"Лис\"\n  STR_DEC: \"Гру\"\n  STR_INTERNATIONAL_RELATIONS: \"МІЖНАРОДНІ ВІДНОСИНИ\"\n  STR_COUNTRY: \"Країна\"\n  STR_FUNDING: \"Фінансування\"\n  STR_CHANGE: \"Зміна\"\n  STR_WEAPON_SYSTEMS: \"СИСТЕМИ ОЗБРОЄННЯ\"\n  STR_HWPS: \"ПБП'ми\"\n  STR_DAMAGE_UC_: \"ПОШКОДЖЕННЯ>{ALT}{0}\"\n  STR_AIR_LOCK_UFOPEDIA: \"Повітряний шлюз дозволяє переміщувати обладнання та персонал на підводну базу або з неї. Це завжди перший об'єкт, який будується на новому місці. Зона повітряного шлюзу є вразливою до вторгнення будь-якої потенційної ворожої сили.\"\n  STR_LIVING_QUARTERS_UFOPEDIA: \"Кожен житловий модуль розрахований на 50 осіб. Ці модулі є основними елементами функціонування бази.\"\n  STR_LABORATORY_UFOPEDIA: \"В одному лабораторному блоці можуть працювати п'ятдесят вчених. Лабораторії обладнані за останнім словом техніки для дослідження матеріалів, біохімії та озброєння. X-Com має доступ до всіх найкращих дослідницьких лабораторій по всьому світу, як цивільних, так і військових.\"\n  STR_WORKSHOP_UFOPEDIA: \"Майстерня містить усе необхідне для виробництва обладнання на основі найновіших розробок наукових лабораторій. 50 інженерів можуть працювати в одній майстерні, об'єкти, що перебувають на стадії розробки, також займатимуть місце.\"\n  STR_STANDARD_SONAR_UFOPEDIA: \"Стандартна гідролокаційна система має ефективну дальність дії понад 450 кілометрів на найбільших глибинах і пов'язана з геостаціонарними супутниковими мережами для аналізу надводної обстановки. Кожен сканер має 10% ймовірність виявлення підводного або повітряного судна за 30-хвилинний цикл сканування.\"\n  STR_WIDE_ARRAY_SONAR_UFOPEDIA: \"Широкосмугова гідролокаційна система має ефективний радіус дії понад 700 кілометрів на всіх глибинах і пов'язана з геостаціонарними супутниковими мережами для аналізу надводної обстановки. Кожен сканер має 20% ймовірність виявлення підводного або повітряного судна за кожний 30-хвилинний цикл сканування.\"\n  STR_TORPEDO_DEFENSES_UFOPEDIA: \"Системи торпедного захисту забезпечують захист від нападу ворожих субмарин, які намагаються пришвартуватися до бази.\"\n  STR_GENERAL_STORES_UFOPEDIA: \"Все обладнання, системи озброєння, боєприпаси, знайдені артефакти та ПБП розміщуються на складах, включаючи обладнання, призначене для субмарин.\"\n  STR_ALIEN_CONTAINMENT_UFOPEDIA: \"Для утримання живих прибульців потрібні спеціальні тюремні мобулі. В них підтримуються підходящі для них умови, а також зводиться нанівець увесь їхній бойовий потенціал. Ізолятор може містити до 10 прибульців.\"\n  STR_GAUSS_DEFENSES_UFOPEDIA: \"Гауссові гармати забезпечують новіший та ефективніший захист бази від нападу ворожих субмарин.\"\n  STR_SONIC_DEFENSES_UFOPEDIA: \"Система захисту на основі акустичних випромінювачів забезпечує потужний та ефективний захист від агресорів.\"\n  STR_PWT_DEFENSES_UFOPEDIA: \"Імпульсно-хвильові торпеди забезпечують найефективніший захист від атак прибульців. Ці торпеди мають надщільні боєголовки, які можуть пробити будь-яку відому броню. Магнітні хвилі, які вони випромінюють, виводять з ладу електронний захист.\"\n  STR_BOMBARDMENT_SHIELD_UFOPEDIA: \"Антибомбардувальний щит захищає базу від причалювання ворожих субмарин, створюючи резонансне поле, яке відштовхує атакуючі субмарини на час, достатній для того, щоб оборонні системи могли відкрити вогонь повторно. По суті, це подвоює ефективність будь-яких вже встановлених захисних систем.\"\n  STR_MC_GENERATOR_UFOPEDIA: \"Оскільки субмарини прибульців використовують технологію молекулярного контролю для виявлення присутності живих істот, використання негативного МК-випромінювача покриє базу непроникним щитом, щоб збити прибульців з пантелику і замаскувати нашу присутність.\"\n  STR_MC_LAB_UFOPEDIA: \"Лабораторія молекулярного контролю може імплантувати та тренувати до десяти акванавтів одночасно. Імпланти хірургічним шляхом встановлюються в черепи акванавтів. Шляхом інтенсивних тренуань вони вчаться їх використовувати. Отримані навички задіюються разом із пристроєм МК і можуть бути використані для відповідних атак під час бою.\"\n  STR_TRANSMISSION_RESOLVER_UFOPEDIA: \"Системи зв'язку прибульців основані на використанні побудованих мереж молекулярного контролю. Розшифровувач сигналів перехоплює сигнали субмарини прибульців та розшифровує інформацію. Він відображає тип субмарини, расу прибульців і завдання, яке вони виконують.\"\n  STR_SUB_PEN_UFOPEDIA: \"Кожен док може вмістити одну субмарину. На ньому є приміщення для обслуговування, дозаправки та ремонту підводного флоту X-Com. Кожна літаюча субмарина, що знаходиться на базі, повинна мати вільний док, який не може бути використаний іншими субмаринами, навіть якщо призначена субмарина перебуває на завданні.\"\n  STR_DART_PISTOL_UFOPEDIA: \"Дротикомет X-Com - це невеликий, точний, потужний пристрій з магазином на 12 порожнистих дротиків. Стрільба дротиками здійснюється за допомогою газового балона в обоймі.\"\n  STR_JET_HARPOON_UFOPEDIA: \"Ця аква-гвинтівка точна і потужна, стріляє порожнистими сталевими гарпунами з герметичних упаковок по 10 штук. Кожен гарпун має власний резервуар для газу.\"\n  STR_GAS_CANNON_UFOPEDIA: \"Будучи справжнім важковаговиком у сімействі газового озброєння, ця гармата стріляє цільними стрижнями, які можуть оснащуватися розривними або фосфорними наконечниками. Улюблена зброя досвідчених акванавтів.\"\n  STR_HYDRO_JET_CANNON_UFOPEDIA: \"Гідрореактивні гармати призначені для використання важкою піхотою. Гармата стріляє міні-торпедами на магнієвому паливі. Незважаючи на свою потужність, гідрореактивна гармата є незграбною та громіздкою зброєю, придатною до використання лише у воді.\"\n  STR_TORPEDO_LAUNCHER_UFOPEDIA: \"Справжній важковаговик, ця велика гармата стріляє трьома типами торпед, кожна з яких має власну рушійну систему. Руйнівна зброя, єдиним недоліком якої є лише ручне заряджання. Доступні типи боєприпасів включають великі або малі осколково-фугасні та фосфорні торпеди з люмінофорним наконечником, призначені лише для підводного використання.\"\n  STR_GAUSS_PISTOL_UFOPEDIA: \"Гаусс-пістолет використовує найновішу розробку в галузі сучасних озброєнь - технологія прискорення частинок. Він швидкий, точний і працює як над, так і під водою. Технологія Гаусса є розвитком плазмових технологій, отриманих під час попередньої війни.\"\n  STR_GAUSS_PISTOL_CLIP_UFOPEDIA: \"Цей невеликий об'єкт - магазин до гаусс-пістолета. Він вміщає в себе 20 набоїв.\"\n  STR_GAUSS_RIFLE_UFOPEDIA: \"Гаусс-гвинтівка - наступний етап розвитку гаусс-пістолета, Ця гвинтівка, маючи здвоєний прискорювач частинок, здатна наносити серйозні пошкодження. Відмовившись від працюючої на елерії плазмової системи, ми застосували мікроприскорювач частинок, який генерує потік антипротонів.\"\n  STR_GAUSS_RIFLE_CLIP_UFOPEDIA: \"Цей невеликий об'єкт - магазин до гаусс-гвинтівки. Він вміщає в себе 15 набоїв.\"\n  STR_HEAVY_GAUSS_UFOPEDIA: \"Гаусс-гармата є громіздкою, але надзвичайно ефективною. Вона працює зі строєним мікроприскорювачем частинок і її практично неможливо зупинити. Потік антипротонів утримується всередині оболонки з арсеніду галію, яка при зіткненні вибухає, вивільняючи антиречовину.\"\n  STR_HEAVY_GAUSS_CLIP_UFOPEDIA: \"Цей невеликий об'єкт - магазин до гаусс-гармати. Він вміщає в себе 10 набоїв.\"\n  STR_MAGNA_BLAST_GRENADE_UFOPEDIA: \"Стандартна осколкова граната з точним таймером для запалу.\"\n  STR_DYE_GRENADE_UFOPEDIA: \"Чорнильні гранати мають подвійне призначення, вони корисні для забезпечення укриття на відкритій місцевості. При вибуху на суші утворюється щільна хмара, яка переноситься вітром, а у воді утворюється темна завіса, що нагадує чорнильну хмару восьминога.\"\n  STR_PARTICLE_DISTURBANCE_GRENADE_UFOPEDIA: \"Сенсорна граната, яку можна кинути як звичайну гранату, але після встановлення вона спрацьовує від руху поблизу. Для правильного використання цих пристроїв потрібні навички та підготовка.\"\n  STR_MAGNA_PACK_EXPLOSIVE_UFOPEDIA: \"Цю вибухівку слід використовувати лише для знесення будівель. Однак минулий досвід показав, що ці потужні вибухові пакети є ідеальною зброєю для знищення прибульців. Радіус вибуху великий, тому переконайтеся, що жоден акванавт не перебуває в межах небезпечної зони.\"\n  STR_PARTICLE_DISTURBANCE_SENSOR_UFOPEDIA: \"Цей новий пристрій використовує різноманітні детектори та передові комп'ютерні системи для виявлення рухомих ворожих одиниць. Натисніть на піктограму сенсора руху на тактичному дисплеї. Виберіть \\\"Використати сенсор\\\" з меню. На дисплеї сенсора з'явиться стрілка в центрі, яка вказує напрямок, куди дивиться акванавт (північ вгорі). Блимання показують об'єкти, які нещодавно перемістилися. Великі об'єкти або об'єкти, що швидко рухаються, даватимуть більші сплески. Нерухомі об'єкти не відображатимуться.\"\n  STR_MEDI_KIT_UFOPEDIA: \"Для використання вам потрібно стати обличчям до пораненого агента X-Com або стати над тілом оглушеного акванавта.{NEWLINE}ЛІКУВАННЯ> Червоним кольором позначені смертельні рани. Виберіть частину тіла і натисніть на кнопку \\\"Лікування\\\". Одна смертельна рана буде зцілена, а здоров'я відновлено.{NEWLINE}СТИМУЛЯТОР> Відновлює енергію і оживляє оглушених акванавтів. Щоб оживити непритомного акванавта, ви повинні стояти безпосередньо над його тілом.{NEWLINE}ЗНЕБОЛЮЮЧЕ> Відновлює бойовий дух поранених акванавтів.\"\n  STR_MC_DISRUPTOR_UFOPEDIA: \"Вершина технології М.К. Цей пристрій може використовуватися лише акванавтами із вміннями М.К. Натисніть на пристрій, виберіть тип атаки і вкажіть ціль курсором. Доступні два типи атаки:{NEWLINE}ЗБІЙ ІМПЛАНТУ> У разі успіху ворог буде збитий з пантелику і може запанікувати.{NEWLINE}КОНТРОЛЬ ІМПЛАНТУ> У разі успіху ви отримаєте контроль над ворогом.\"\n  STR_THERMAL_TAZER_UFOPEDIA: \"Цей пристрій можна використовувати лише в ближньому бою. Він приголомшить живий організм, не вбиваючи його, паралізувавши істоту.\"\n  STR_VIBRO_BLADE_UFOPEDIA: \"Вібро-бур - це пристрій, гостре титанове лезо якого обертається зі швидкістю понад 6000 об/хв. Він може розбити навіть найміцнішу водолазну броню. Це винахід прибульців, наші спроби створити подібні предмети раніше зазнавали невдачі, наші леза оберталися надто повільно або вибухали під тиском.\"\n  STR_THERMIC_LANCE_UFOPEDIA: \"Термо-бур - це логічне продовження технології вібро-буру. Лезо обертається на високій швидкості, а зербітове джерело живлення нагріває лезо до такої міри, що воно проходить через броню, як теплий ніж крізь масло.\"\n  STR_HEAVY_THERMIC_LANCE_UFOPEDIA: \"Важкий термо-бур - це більш потужна версія ТБ. Подвійне джерело тепла і надзвичайно висока швидкість обертання означають, що важкий термічний наконечник практично не зупиняється при роботі з будь-якими матеріалами.\"\n  STR_SONIC_CANNON_UFOPEDIA: \"Акустична гармата - найпотужніша з сімейства акустичної зброї. Вона оснащена аудіогенератором більшого діапазону та більшою ревербераційною камерою. Гармата також має імпульсну систему детонації, яка змінює ультразвукову хвилю шляхом модуляції для створення більш ефективного акустичного удару.\"\n  STR_CANNON_POWER_CLIP_UFOPEDIA: \"Цей компактний пристрій використовується як боєприпас для акустичної гармати. Він містить невелику кількість зербіту.\"\n  STR_SONIC_BLASTA_RIFLE_UFOPEDIA: \"Більш потужний акустична пристрій. Навіть високовуглецева сталь не захищена від цієї зброї. Оснащена компактним випромінювачем хвиль, який посилений надпровідниковим підсилювачем, що збільшує її потужність.\"\n  STR_BLASTA_POWER_CLIP_UFOPEDIA: \"Цей невеликий об'єкт використовується як джерело енергії для акустичної гвинтівки - потужної зброї прибульців, і містить невелику кількість зербіту.\"\n  STR_SONIC_PISTOL_UFOPEDIA: \"Акустичні пістолети - це зброя прибульців, заснована на ультразвукових хвилях, які здатні за лічені секунди роз'їдати кістки. Ультразвукові хвилі поширюються в діапазоні за межами людського слуху.\"\n  STR_PISTOL_POWER_CLIP_UFOPEDIA: \"Джерело живлення для компактного акустичного пістолета прибульців. Містить зербіт - джерело всієї їхньої сили.\"\n  STR_DISRUPTOR_PULSE_LAUNCHER_UFOPEDIA: \"Це інопланетна керована зброя, що стріляє самохідними бомбами, призначена лише для використання у воді. Коли ви використовуєте зброю, вона генерує точки маршруту, за яким буде рухатися снаряд. Коли ви встановите достатню кількість точок, натисніть на кнопку запуску.\"\n  STR_DISRUPTOR_AMMO_UFOPEDIA: \"Цей пристрій являє собою імпульсну руйнівну бомбу, оснащений бортовою комп'ютерною системою наведення. Він випускається з установки дезінтегратора.\"\n  STR_THERMAL_SHOK_LAUNCHER_UFOPEDIA: \"Невелика установка, яка стріляє хімічними бомбами, що заморожують. Дуже корисна для захоплення живих прибульців.\"\n  STR_THERMAL_SHOK_BOMB_UFOPEDIA: \"Термально-шокова бомба використовується для захоплення живих людей, але також може бути використана проти більшості рас прибульців. Вона запускається з термально-шокової установки.\"\n  STR_SONIC_PULSER_UFOPEDIA: \"Цей пристрій працює так само, як і звичайна бойова граната - за винятком того, що він у багато разів потужніший. Граната використовує один імпульс акустичного вибуху, який випромінюється в усіх напрямках одночасно.\"\n  STR_MC_READER_UFOPEDIA: \"У тілах прибульців ми знайшли невеликі хірургічно імплантовані пристрої. Це імпланти управління, розроблені акватоїдами, щоб забезпечити постійне постачання інформації з поля бою, навіть на великих відстанях. Зчитувач молекулярного контролю - це пристрій зв'язку прибульців, який використовується для зчитування інформації безпосередньо з імплантів МК. Підрозділи X-Com можуть використовувати цей пристрій у бою для відображення характеристик прибульця. Виберіть опцію \\\"Викор. зчитувач МК\\\". Потім клацніть курсором на прибульця.\"\n  STR_SURVEY_SHIP: \"Корабель спортереження\"\n  STR_ESCORT: \"Корабель супроводу\"\n  STR_CRUISER: \"Крейсер\"\n  STR_HEAVY_CRUISER: \"Важкий крейсер\"\n  STR_HUNTER: \"Мисливець\"\n  STR_BATTLESHIP: \"Лінкор\"\n  STR_DREADNOUGHT: \"Дредноут\"\n  STR_FLEET_SUPPLY_CRUISER: \"Крейсер забезпечення\"\n  MAP_SEABED: \"Морське дно\"\n  MAP_PIPES: \"Дослідницький центр\"\n  MAP_PLANE: \"Розбитий літак\"\n  MAP_ATLAN: \"Атлантида\"\n  MAP_MU: \"Храм Майя\"\n  MAP_GAL: \"Затонулий галеон\"\n  MAP_MSUNK: \"Затонулий лайнер\"\n  MAP_VOLC: \"Вулканічний\"\n  MAP_CORAL: \"Кораловий\"\n  MAP_PORT: \"Порт\"\n  MAP_ISLAND: \"Острів\"\n  MAP_CARGO: \"Вантажний корабель\"\n  MAP_LINERT: \"Круїзний лайнер Р1\"\n  MAP_LINERB: \"Круїзний лайнер Р2\"\n  MAP_ALART: \"Артефакт Р1\"\n  MAP_GRUNGE: \"Артефакт Р2\"\n  MAP_ENTRY: \"Колонія Р1\"\n  MAP_A_BASE: \"Колонія Р2\"\n  MAP_ALSHIP: \"Т'льєт Р1\"\n  MAP_LEVEL: \"Т'льєт Р2\"\n  MAP_CRYPT: \"Т'льєт Р3\"\n  MAP_XBASES: \"База X-Com\"\n  STR_MIXED_CREW: \"Змішаний екіпаж\"\n  STR_MIXED_CREW_2: \"Змішаний екіпаж 2\"\n  STR_RATING: \"РЕЙТИНГ> {0}\"\n  STR_RATING_TERRIBLE: \"ЖАХЛИВО!\"\n  STR_RATING_POOR: \"ПОГАНО!\"\n  STR_RATING_OK: \"ОК\"\n  STR_RATING_GOOD: \"ДОБРЕ!\"\n  STR_RATING_EXCELLENT: \"ПРЕКРАСНО!\"\n  STR_SCORE: \"РАХУНОК \"\n  STR_XCOM_PROJECT_MONTHLY_REPORT: \"ЩОМІСЯЧНИЙ ЗВІТ X-COM\"\n  STR_MONTH: \"Місяць> {ALT}{0} {1}\"\n  STR_COUNCIL_IS_GENERALLY_SATISFIED: \"Комітет фінансуючих організацій в цілому задоволений вашим прогресом.\"\n  STR_COUNCIL_IS_VERY_PLEASED: \"Комітет фінансуючих організацій дуже задоволений вашим чудовим прогресом. Продовжуйте в тому ж дусі.\"\n  STR_COUNCIL_IS_DISSATISFIED: \"Комітет фінансуючих організацій незадоволений вашою роботою. Ви повинні підвищити свою ефективність у боротьбі з інопланетною загрозою або ризикуєте припинити фінансову підтримку X-Com.\"\n  STR_YOU_HAVE_NOT_SUCCEEDED: \"Вам не вдалося впоратися з вторгненням прибульців, і комітет фінансуючих організацій, на жаль, вирішив припинити фінансування X-Com. Кожна організація буде вирішувати цю проблему так, як вважає за потрібне. Ми можемо лише сподіватися, що зможемо домовитися з цими древніми силами, і що населення змириться з водними візитерами.\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0} особливо задоволена Вашими успіхами в боротьбі з загрозою на її території та погодилась збільшити фінансування.\"\n  STR_COUNTRIES_ARE_PARTICULARLY_HAPPY: \"{0} особливо задоволені вашим прогресом у боротьбі з місцевим вторгненням прибульців і погодилися збільшити своє фінансування.\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0} та {1}\"\n  STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY: \"{0} незадоволена вашою здатністю боротися з активністю прибульців у своїх морях і вирішила зменшити свої фінансові зобов'язання.\"\n  STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY: \"{0} незадоволені вашою здатністю боротися з активністю прибульців у їхньому морі і вирішили зменшити своє фінансування.\"\n  STR_KNOTS: \"{0} вузлів\"\n  STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT: \"{0} підписав угоду про співпрацю з інопланетними силами і відмовився від фінансування X-Com.\"\n  STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT: \"{0} підписали угоду про співпрацю з силами прибульців і відмовилися від фінансування X-Com.\"\n  STR_MONTHLY_RATING: \"Рейтинг за місяць> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"Зміна фінансування> {ALT}{0}\"\n  STR_COUNCIL_REDUCE_DEBTS: \"Фінансуюча організація не задоволена вашим фінансовим становищем. Ви повинні зменшити свої борги до рівня нижче 1 мільйона доларів, інакше X-Com буде припинено.\"\n  STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED: \"ПЕРЕДАЧУ СУБЧАСТИНОК РОЗШИФРОВАНО\"\n  STR_CRAFT_TYPE: \"ТИП СУБМАРИНИ\"\n  STR_RACE: \"РАСА\"\n  STR_MISSION: \"ЗАВДАННЯ\"\n  STR_ZONE: \"ЗОНА\"\n  STR_ALLOCATE_RESEARCH: \"Почати дослідження\"\n  STR_ALLOCATE_MANUFACTURE: \"Почати виробництво\"\n  STR_AZORES: \"Азорські острови\"\n  STR_REYKJAVIK: \"Рейк'явік\"\n  STR_BERMUDA: \"Бермудські острови\"\n  STR_NEW_YORK: \"Нью-Йорк\"\n  STR_BOSTON: \"Бостон \"\n  STR_FORT_SEVERN: \"Форт Північ\"\n  STR_DAKAR: \"Дакар\"\n  STR_RECIFE: \"Ресіфі\"\n  STR_ACCRA: \"Аккра\"\n  STR_ASCENSION_ISLAND: \"Острів Вознесіння\"\n  STR_TRINIDADE_ISLAND: \"Острів Тріндаде\"\n  STR_FALKLAND_ISLAND: \"Фолклендські острови\"\n  STR_CANARY_ISLANDS: \"Канарські острови\"\n  STR_ANCHORAGE: \"Якірна стоянка\"\n  STR_ST_LAWRENCE_ISLAND: \"Острів Святого Лаврентія\"\n  STR_SAN_FRANCISCO: \"Сан-Франциско\"\n  STR_MIDWAY_ISLAND: \"Острів Мідвей\"\n  STR_VANCOUVER: \"Ванкувер\"\n  STR_TASMANIA: \"Острів Тасманія\"\n  STR_HAWAII: \"Гавайські острови\"\n  STR_FIJI: \"Фіджі\"\n  STR_TONGA: \"Тонга\"\n  STR_EASTER_ISLAND: \"Острів Пасхи\"\n  STR_GALAPAGOS_ISLAND: \"Галапагоські острови\"\n  STR_WELLINGTON: \"Веллінгтон\"\n  STR_SOLOMON_ISLAND: \"Соломонові острови\"\n  STR_CRETE: \"Критський півострів\"\n  STR_LISBON: \"Лісабон\"\n  STR_PORT_SAID: \"Порт Саїд\"\n  STR_MARSEILLES: \"Марсель \"\n  STR_TRIPOLI: \"Тріполі\"\n  STR_MANILA: \"Маніла\"\n  STR_HONG_KONG: \"Гонконг\"\n  STR_SINGAPORE: \"Сінгапур\"\n  STR_BANGKOK: \"Бангкок\"\n  STR_DARWIN: \"Дарвін\"\n  STR_BOMBAY: \"Бомбей\"\n  STR_SAYCHELLES_ISLAND: \"Сейшельські острови\"\n  STR_MALDIVE_ISLAND: \"Мальдівські острови\"\n  STR_SRI_LANKA: \"Шрі-Ланка\"\n  STR_MAURITIUS: \"Маврикій\"\n  STR_TOKYO: \"Токіо\"\n  STR_SHANGHAI: \"Шанхай\"\n  STR_VLADIVOSTOK: \"Владивосток\"\n  STR_LONDON: \"Лондон\"\n  STR_FAEROE_ISLAND: \"Острів Фаеро\"\n  STR_ABERDEEN: \"Абердін\"\n  STR_OSLO: \"Осло\"\n  STR_JAMAICA: \"Ямайка \"\n  STR_PANAMA: \"Панама \"\n  STR_MIAMI: \"Маямі\"\n  STR_PSI_TRAINING: \"Тренування М.К.\"\n  STR_PSIONIC_TRAINING: \"НАВЧАННЯ МОЛЕКУЛЯРНОМУ КОНТРОЛЮ\"\n  STR_REMAINING_PSI_LAB_CAPACITY: \"Залишок значення М.К. > {ALT}{0}\"\n  STR_PSIONIC__STRENGTH: \"М.К.{NEWLINE}Сила\"\n  STR_PSIONIC_SKILL_IMPROVEMENT: \"Вміння М.К.{NEWLINE}/Покращення\"\n  STR_IN_TRAINING: \"На{NEWLINE}Тренув.?\"\n  STR_TARGETTED_BY: \"ЦІЛЬ ДЛЯ:\"\n  STR_WEAPONS_CREW_HWPS: \"ЗБРОЯ/{NEWLINE}ЕКІПАЖ/ПБП\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"закінчується пальне,{NEWLINE}повертаюсь на базу\"\n  STR_SOLDIER_LIST: \"Список акванавтів\"\n  STR_RANK_: \"ЗВАННЯ> {ALT}{0}\"\n  STR_MISSIONS: \"МІСІЙ> {ALT}{0}\"\n  STR_KILLS: \"ВБИВСТВ> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"ЛІКУВАННЯ РАН> {ALT}{0}\"\n  STR_TIME_UNITS: \"ОДИНИЦІ ДІЙ\"\n  STR_STAMINA: \"ВИТРИВАЛІСТЬ\"\n  STR_HEALTH: \"ЗДОРОВ'Я\"\n  STR_BRAVERY: \"ХОРОБРІСТЬ\"\n  STR_REACTIONS: \"РЕАКЦІЯ\"\n  STR_FIRING_ACCURACY: \"ТОЧНІСТЬ СТРІЛЬБИ\"\n  STR_THROWING_ACCURACY: \"ТОЧНІСТЬ КИДАННЯ\"\n  STR_STRENGTH: \"СИЛА\"\n  STR_PSIONIC_STRENGTH: \"СИЛА М.К.\"\n  STR_PSIONIC_SKILL: \"ВМІННЯ М.К.\"\n  STR_NEW_RANK: \"НОВЕ ЗВАННЯ\"\n  STR_PROMOTIONS: \"Присвоєні звання:\"\n  STR_SOLDIERS_UC: \"АКВАНАВТИ\"\n  STR_COELACANTH_GAS_CANNON_UFOPEDIA: \"Автоматизовані підводні бойові платформи мають міцний корпус та високу маневреність. Вони забезпечують підтримку важкого десанту на будь-якій глибині. ПБП автоматично переозброюються, якщо у вас достатньо боєприпасів.\"\n  STR_COELACANTH_AQUA_JET_UFOPEDIA: \"Цей підводний апарат озброєний торпедами, які працюють лише під водою. Переконайтеся, що у вас на складах достатня кількість торпед.\"\n  STR_COELACANTH_GAUSS_UFOPEDIA: \"Технологія Гаусса забезпечує потужну систему озброєння для ПБП, пропонуючи велику вогневу міць у порівнянні з попередніми моделями. Вона використовує запатентовану технологію X-Com.\"\n  STR_DISPLACER_SONIC_UFOPEDIA: \"Інопланетна технологія переосмислила ПБП. Здатність використовувати іонні витіснювачі означає, що ПБП більше не обмежуються сушею/морським дном. Акустична зброя дає значну перевагу в бою.\"\n  STR_DISPLACER_PWT_UFOPEDIA: \"У цій ПБП використовується імпульсно-хвильова зброя. Ви повинні виготовити боєприпаси до ІХТ, щоб тримати їх повністю озброєними. Щоб відкрити вогонь, виберіть кілька \\\"маршрутних точок\\\", а потім натисніть на кнопку запуску.\"\n  STR_ALIEN_PROBE_MISSION: \"Інопланетне зондування\"\n  STR_ALIEN_INTERDICTION: \"Блокування регіону\"\n  STR_ALIEN_RESOURCE_RAID: \"Рейд на ресурси\"\n  STR_ALIEN_INFILTRATION: \"Проникнення\"\n  STR_ALIEN_BASE: \"Розширення колонії\"\n  STR_ALIEN_SURFACE_ATTACK: \"Атаки на суходіл\"\n  STR_ALIEN_RETALIATION: \"Атака плавучої бази\"\n  STR_ALIEN_SUPPLY: \"Постачання колонії\"\n  STR_ALIEN_PROBE_MISSION_UFOPEDIA: \"Місія інопланетного зондування використовується для зіставлення даних про морське дно, ресурси, судноплавство і траєкторії польотів літаків у певній місцевості. Підводні апарати прибульців, що беруть участь у цих місіях, самі по собі не становлять великої загрози, але вони вказують на місця активності, які можуть спалахнути в будь-який момент.\"\n  STR_ALIEN_INTERDICTION_UFOPEDIA: \"Стратегія прибульців передбачає патрулювання регіонів які їх цікавлять, і перш ніж розпочати більш активні дії, вони посилають судна з метою забезпечення охорони цих територій. Вони прибувають у місця, куди пізніше планують здійснити набіг, блокують регіон і проводять підготовку до наступного етапу їхньої місії.\"\n  STR_ALIEN_RESOURCE_RAID_UFOPEDIA: \"Потоплення кораблів і збиття літаків є ключовими елементами стратегії прибульців. Здобуття матеріалів є одним з основних видів їх діяльності і, як таке, пов'язане з цими відверто агресивними діями. Прибульці також здійснюють набіги на зони геотермальної активності, місця видобутку корисних копалин і стародавні пам'ятки у пошуках мінералів, дорогоцінних металів та інших предметів, створених людиною.\"\n  STR_ALIEN_INFILTRATION_UFOPEDIA: \"Даний вид діяльності прибульців може призвести до офіційних контактів між ними та корпораціями або урядами на найвищому рівні. Кульмінація цієї активності характеризується інтенсивною діяльністю субмарин прибульців у акваторії відповідної організації. Прибульці намагатимуться підписати угоду з урядом або організацією, пропонуючи знання про свої передові технології. Ця діяльність прибульців становить серйозну загрозу для X-Com. Якщо корпорація або уряд співпрацює із загарбниками, її фінансування припиняється.\"\n  STR_ALIEN_BASE_UFOPEDIA: \"Прибульці будуватимуть таємні підводні колонії у віддалених місцях. Після кількох початкових розвідувальних польотів почнеться інтенсивна діяльність інопланетних субмарин, які будуватимуть колонію. Відомо, що ці колонії містять лабораторії, центри клонування, хірургічні кабінети для експериментів над людьми та прибульцями. Присутність колоній прибульців призведе до збільшення активності прибульців без виявлення субмарин прибульців. Щоб знайти колонію, субмарина X-Com повинна патрулювати місцевість протягом декількох годин, щоб мати шанс на успішне виявлення.\"\n  STR_ALIEN_SURFACE_ATTACK_UFOPEDIA: \"Коли прибульцям потрібні люди, вони тероризують порт, нападають на острів або здійснюють набіги на кораблі. Прибульці будуть відкрито нападати на цивільних, використовуючи їх для задоволення своїх збочених потреб в розмноженні та жахливих експерементах.\"\n  STR_ALIEN_RETALIATION_UFOPEDIA: \"Якщо підводні човни-перехоплювачі X-Com будуть особливо успішними у потопленні кораблів прибульців, то вони можуть вжити агресивних дій у відповідь. Це може призвести до прямої атаки на об'єкт X-Com. Однак, щоб атакувати базу, прибульці повинні знайти її, і якщо ворожі субмарини будуть триматися подалі, то небезпека нападу буде невеликою.\"\n  STR_ALIEN_SUPPLY_UFOPEDIA: \"Після того, як колонія прибульців побудована, вона регулярно забезпечується спеціальним кораблем постачання. Якщо один з цих кораблів буде виявлено під час приземлення, це означає, що колонія прибульців знаходиться поблизу.\"\n  STR_SURVEY_SHIP_UFOPEDIA: \"Ця крихітна субмарина використовується для розвідувальних та оглядових місій. Зазвичай вона передує більшим суднам на початку операцій прибульців.\"\n  STR_ESCORT_UFOPEDIA: \"Корабель супроводу середнього розміру, саме по собі він становить незначну загрозу. Це судно передує прибуттю більших суден і активізації діяльності прибульців.\"\n  STR_CRUISER_UFOPEDIA: \"Крейсер - корабель загального призначення, основа флоту прибульців, він використовується у всіх типах ворожих місій і є небезпечним супротивником.\"\n  STR_HEAVY_CRUISER_UFOPEDIA: \"Важкий крейсер - потужніший корабель, ніж крейсер. Його потужність збільшується за рахунок більшого озброєння та силових установок. Важкий крейсер використовується для ресурсних місій для збору великої кількості мінералів та обладнання.\"\n  STR_HUNTER_UFOPEDIA: \"Це судно обладнане оглядовим кабінетом для проведення експериментів і хірургічних операцій на людях. Жертв піддають найжорстокішим тортурам, а мозок часто видаляють і зберігають для обробки по дорозі.\"\n  STR_BATTLESHIP_UFOPEDIA: \"Лінкор - найагресивніший корабель прибульців, він оснащений усіма передовими технологіями та системами, щоб слугувати базою для будь-яких агресивних дій, які вороги можуть замислити, і має на озброєнні широкий спектр озброєнь.\"\n  STR_DREADNOUGHT_UFOPEDIA: \"Дредноут - це супердесантний корабель, повністю оснащений усіма технологіями прибульців і має величезне підйомне навантаження. Дредноут - сильний і грізний супротивник.\"\n  STR_FLEET_SUPPLY_CRUISER_UFOPEDIA: \"Крейсер постачання використовується під час будівництва колоній прибульців або для постачання вже існуючих колоній. Він перевозить поживні речовини, ДНК, зародки та інші біологічні компоненти прибульців.\"\n  STR_DISMANTLE: \"Демонтувати\"\n  STR_FACILITY_IN_USE: \"ПОВІТРЯНИЙ ШЛЮЗ ВИКОРИСТОВУЄТЬСЯ\"\n  STR_CANNOT_DISMANTLE_FACILITY: \"НЕ МОЖНА ДЕМОНТУВАТИ ПОВІТРЯНИЙ ШЛЮЗ!{SMALLLINE} Усі базові капсули мають бути з'єднані з повітряним шлюзом.\"\n  STR_TRANSFER_ITEMS_TO: \"Переслати на базу {0}\"\n  STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER: \"НЕ МОЖНА ТРАНСПОРТУВАТИ ПРИБУЛЬЦІВ!{SMALLINE}Для виживання живим прибульцям потрібне обладнання для їх утримання.\"\n  STR_AMOUNT_AT_DESTINATION: \"НА МІСЦІ{NEWLINE}ПРИЗНАЧЕННЯ\"\n  STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY: \"Прибулець помирає, оскільки немає камери для його утримання\"\n  STR_NO_FREE_ACCOMODATION_CREW: \"НЕДОСТАТНЬО ЖИТЛОВОЇ ПЛОЩІ!{SMALLLINE}На базі призначення не вистачає місця в житлових приміщеннях для екіпажу, призначеного на підводний човен.\"\n  STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT: \"НЕДОСТАТНЬО МІСЦЯ ДЛЯ ЗБЕРІГАННЯ! {SMALLLINE}На базі призначення не вистачає місця для зберігання обладнання, призначеного для підводного човна.\"\n  STR_ITEMS_ARRIVING: \"Прибуття\"\n  STR_DESTINATION_UC: \"ПУНКТ ПРИЗНАЧЕННЯ\"\n  STR_DART_PISTOL: \"Дротикомет\"\n  STR_DART_POD: \"Магазин дротикомету\"\n  STR_JET_HARPOON: \"Аква-гвинтівка\"\n  STR_HARPOON_POD: \"Магазин аква-гвинтівки\"\n  STR_GAS_CANNON: \"Газова гармата\"\n  STR_GC_AP_AMMO: \"Бронебійний стрижень\"\n  STR_GC_HE_AMMO: \"Розривний стрижень\"\n  STR_GC_P_AMMO: \"Фосфорний стрижень\"\n  STR_HYDRO_JET_CANNON: \"Гідрореактивна гармата\"\n  STR_HJC_AP_AMMO: \"Бронебійна міні-торпеда\"\n  STR_HJC_HE_AMMO: \"Вибухова міні-торпеда\"\n  STR_HJC_P_AMMO: \"Фосфорна міні-торпеда\"\n  STR_TORPEDO_LAUNCHER: \"Торпедна гармата\"\n  STR_SMALL_TORPEDO: \"Мала торпеда\"\n  STR_LARGE_TORPEDO: \"Велика торпеда\"\n  STR_PHOSPHOROUS_TORPEDO: \"Фосфорна торпеда\"\n  STR_MAGNA_BLAST_GRENADE: \"Магнієва граната\"\n  STR_DYE_GRENADE: \"Чорнильна граната\"\n  STR_PARTICLE_DISTURBANCE_GRENADE: \"Сенсорна граната\"\n  STR_MAGNA_PACK_EXPLOSIVE: \"Магнієва вибухівка\"\n  STR_PARTICLE_DISTURBANCE_SENSOR: \"Сенсор збурення частинок\"\n  STR_MEDI_KIT: \"Мед-комплект\"\n  STR_MC_DISRUPTOR: \"Руйнівник М.К.\"\n  STR_THERMAL_TAZER: \"Паралізуючий жезл\"\n  STR_GAUSS_PISTOL: \"Гаусс-пістолет\"\n  STR_GAUSS_PISTOL_CLIP: \"Магазин гаусс-пістолета\"\n  STR_GAUSS_RIFLE: \"Гаусс-гвинтівка\"\n  STR_GAUSS_RIFLE_CLIP: \"Магазин гаусс-гвинтівки\"\n  STR_HEAVY_GAUSS: \"Гаусс-гармата\"\n  STR_HEAVY_GAUSS_CLIP: \"Магзин гаусс-гармати\"\n  STR_SONIC_CANNON: \"Акустична гармата\"\n  STR_CANNON_POWER_CLIP: \"Магазин акустичної гармати\"\n  STR_SONIC_BLASTA_RIFLE: \"Акустична гвинтівка\"\n  STR_BLASTA_POWER_CLIP: \"Магазин акустичної гвинтівки\"\n  STR_SONIC_PISTOL: \"Акустичний пістолет\"\n  STR_PISTOL_POWER_CLIP: \"Магазин акустичного пістолета\"\n  STR_DISRUPTOR_PULSE_LAUNCHER: \"Установка дезінтегратора\"\n  STR_DISRUPTOR_AMMO: \"Бомба дезінтегратора\"\n  STR_THERMAL_SHOK_LAUNCHER: \"Термально-шокова установка\"\n  STR_THERMAL_SHOK_BOMB: \"Термально-шокова бомба\"\n  STR_SONIC_PULSER: \"Акустична граната\"\n  STR_ZRBITE: \"Зербіт\"\n  STR_MC_READER: \"Зчитувач М.К.\"\n  STR_VIBRO_BLADE: \"Вібро-бур\"\n  STR_THERMIC_LANCE: \"Термо-бур\"\n  STR_HEAVY_THERMIC_LANCE: \"Важкий термо-бур\"\n  STR_AQUATOID_CORPSE: \"Труп акватоїда\"\n  STR_GILLMAN_CORPSE: \"Труп зябролюдини\"\n  STR_LOBSTERMAN_CORPSE: \"Труп лобстеролюдини\"\n  STR_TASOTH_CORPSE: \"Труп тасота\"\n  STR_CALCINITE_CORPSE: \"Труп кальциніта\"\n  STR_DEEP_ONE_CORPSE: \"Труп глибинника\"\n  STR_BIODRONE_CORPSE: \"Обломки біо-дрона\"\n  STR_TENTACULAT_CORPSE: \"Труп тентакулата\"\n  STR_TRISCENE_CORPSE: \"Труп трисцена\"\n  STR_HALLUCINOID_CORPSE: \"Труп галюциноїда\"\n  STR_XARQUID_CORPSE: \"Труп ксарквіда\"\n  STR_NOT_ENOUGH_AMMO_TO_ARM_HWP: \"Недостатньо боєприпасів для озброєння ПБП{SMALLLINE}Для кожного ПБП потрібно {0} {1}.\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"Недостатньо спорядження для екіпірування загону\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"Вам потрібно вивчити{NEWLINE}{0}{NEWLINE}для виготовлення{NEWLINE}{1}\"\n  STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE: \"Прибульці знищили незахищену базу {0}\"\n  STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION: \"Патрулі X-Com виявили колонію прибульців у {0}\"\n  STR_STANDOFF: \"НА БЕЗПЕЧНІЙ ВІДСТАНІ\"\n  STR_CAUTIOUS_ATTACK: \"ОБЕРЕЖНА АТАКА\"\n  STR_STANDARD_ATTACK: \"ЗВИЧАЙНА АТАКА\"\n  STR_AGGRESSIVE_ATTACK: \"АГРЕСИВНА АТАКА\"\n  STR_DISENGAGING: \"ВІДДАЛЕННЯ\"\n  STR_UFO_HIT: \"ІНОПЛАНЕТНУ СУБМ. УРАЖЕНО!\"\n  STR_UFO_CRASH_LANDS: \"ІНОПЛАНЕТНУ СУБМАРИНУ ПІДБИТО!\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"Переслідувати на безпечній дистанції\"\n  STR_UFO_RETURN_FIRE: \"ІНОПЛАНЕТНА СУБМАРИНА ВІДКРИЛА ВОГОНЬ!\"\n  STR_INTERCEPTOR_DAMAGED: \">>> ЛІТАЮЧУ СУБМАРИНУ УРАЖЕНО <<<\"\n  STR_INTERCEPTOR_DESTROYED: \">>> ЛІТАЮЧУ СУБМАРИНУ ЗНИЩЕНО <<<\"\n  STR_UFO_OUTRUNNING_INTERCEPTOR: \"СУБМАРИНА ПРИБУЛЬЦІВ ВТІКАЄ!\"\n  STR_LONG_RANGE_DETECTION: \"Широкосмугове виявлення\"\n  STR_STORES_UC: \"СКЛАДИ\"\n  STR_DIFFICULTY_LEVEL: \"Рівень складності\"\n  STR_INTERCEPT: \"ПЕРЕХОПЛЕННЯ\"\n  STR_BASES: \"БАЗИ\"\n  STR_GRAPHS: \"ГРАФІКИ\"\n  STR_UFOPAEDIA_UC: \"УФОПЕДІЯ\"\n  STR_OPTIONS_UC: \"НАЛАШТУВАННЯ\"\n  STR_FUNDING_UC: \"ФІНАНСИ\"\n  STR_5_SECONDS: \"5 сек\"\n  STR_1_MINUTE: \"1 хв\"\n  STR_5_MINUTES: \"5 хв\"\n  STR_30_MINUTES: \"30 хв\"\n  STR_1_HOUR: \"1 год\"\n  STR_1_DAY: \"1 день\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"Виконання завдань X-COM\"\n  STR_ENTER_NAME: \"Введіть ім'я\"\n  STR_PERFORMANCE_RATING: \"Оцінка виконання\"\n  STR_VICTORY_DATE: \"День Перемоги\"\n  STR_CHEMICAL_FLARE: \"Хімічний освітлювач\"\n  STR_CHEMICAL_FLARE_UFOPEDIA: \"Цей компактний пристрій створює яскравий світловий спалах на будь-якій глибині або на суші. Під час глибоководних або нічних місій він висвітлює ворожі підрозділи, що знаходяться поблизу спалаху.\"\n  STR_MONTHLY_COSTS: \"ЩОМІСЯЧНІ ВИТРАТИ\"\n  STR_CRAFT_RENTAL: \"Оренда літаючої субмарини\"\n  STR_SALARIES: \"Зарплати\"\n  STR_BASE_MAINTENANCE: \"Обслуговування бази\"\n  STR_COST_PER_UNIT: \"Ціна одиниці\"\n  STR_QUANTITY: \"Кільк.\"\n  STR_TOTAL: \"Всього\"\n  STR_IN_PSIONIC_TRAINING: \"В імплантації М.К.\"\n  STR_FRONT_ARMOR: \"Передня броня\"\n  STR_LEFT_ARMOR: \"Ліва броня\"\n  STR_RIGHT_ARMOR: \"Права броня\"\n  STR_REAR_ARMOR: \"Задня броня\"\n  STR_UNDER_ARMOR: \"Нижня броня\"\n  STR_ROUNDS: \"ПОСТРІЛИ\"\n  STR_UNIT: \"ОДИНИЦЯ> {0}\"\n  STR_ENERGY: \"ЕНЕРГІЯ\"\n  STR_MORALE: \"МОРАЛЬ\"\n  STR_ARMOR_: \"БРОНЯ>{0}\"\n  STR_FRONT_ARMOR_UC: \"ПЕРЕДНЯ БРОНЯ\"\n  STR_LEFT_ARMOR_UC: \"ЛІВА БРОНЯ\"\n  STR_RIGHT_ARMOR_UC: \"ПРАВА БРОНЯ\"\n  STR_REAR_ARMOR_UC: \"ЗАДНЯ БРОНЯ\"\n  STR_SKILLS: \"ВМІННЯ> {0}\"\n  STR_LEVEL: \"РІВЕНЬ> {0}\"\n  STR_HEAD: \"ГОЛОВА\"\n  STR_TORSO: \"ТУЛУБ\"\n  STR_RIGHT_ARM: \"ПРАВА РУКА\"\n  STR_LEFT_ARM: \"ЛІВА РУКА\"\n  STR_RIGHT_LEG: \"ПРАВА НОГА\"\n  STR_LEFT_LEG: \"ЛІВА НОГА\"\n  STR_PAIN_KILLER: \"ЗНЕБОЛЮЮЧЕ\"\n  STR_STIMULANT: \"СТИМУЛЯТОР\"\n  STR_HEAL: \"ЛІКУВАННЯ\"\n  STR_TIME_UNITS_SHORT: \"ОД>{ALT}{0}\"\n  STR_WEIGHT: \"Вага>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"Реакц>{ALT}{0}\"\n  STR_PSIONIC_SKILL_SHORT: \"М.Вміння>{ALT}{0}\"\n  STR_PSIONIC_STRENGTH_SHORT: \"M.Сила>{ALT}{0}\"\n  STR_ALIEN_ARTIFACT: \"Артефакт прибульців\"\n  STR_AMMO_ROUNDS_LEFT: \"БОЄПРИПАСИ:{NEWLINE}ЗАРЯДІВ{NEWLINE}ЗАЛИШИЛОСЬ={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"Знеб>{ALT}{0}{ALT}{NEWLINE}Стим>{ALT}{1}{ALT}{NEWLINE}Ліку>{ALT}{2}\"\n  STR_THROW: \"Кинути\"\n  STR_AUTO_SHOT: \"Черга \"\n  STR_SNAP_SHOT: \"Навмання\"\n  STR_AIMED_SHOT: \"Прицільно\"\n  STR_STUN: \"Паралізувати\"\n  STR_PRIME_GRENADE: \"Активувати\"\n  STR_USE_SCANNER: \"Використати сенсор\"\n  STR_USE_MEDI_KIT: \"Використати\"\n  STR_LAUNCH_MISSILE: \"Запустити торпеду\"\n  STR_ACCURACY_SHORT: \"Точ>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"Не достатньо ОД!\"\n  STR_NOT_ENOUGH_ENERGY: \"Не достатньо енергії!\"\n  STR_NO_ROUNDS_LEFT: \"Немає боєприпасів!\"\n  STR_NO_AMMUNITION_LOADED: \"Зброя не заряджена!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"Боєприпаси від іншої зброї!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"Зброя вже заряджена!\"\n  STR_NO_LINE_OF_FIRE: \"Немає лінії вогню!\"\n  STR_GRENADE_IS_ACTIVATED: \"Граната активована!\"\n  STR_GRENADE_IS_DEACTIVATED: \"Граната деактивована!\"\n  STR_THERE_IS_NO_ONE_THERE: \"Там нікого немає!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"Не досліджений артефакт прибульців!\"\n  STR_OUT_OF_RANGE: \"Надто далеко!\"\n  STR_UNABLE_TO_THROW_HERE: \"Не можу кинути сюди!\"\n  STR_SET_TIMER: \"Виставити Таймер\"\n  STR_HIDDEN_MOVEMENT: \"ПРИХОВАНІ ПЕРЕМІЩЕННЯ\"\n  STR_TURN: \"ХІД> {0}\"\n  STR_SIDE: \"СТОРОНА> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"Натисніть будь-яку кнопку...\"\n  STR_MIND_CONTROL: \"Молекулярний контроль\"\n  STR_PANIC_UNIT: \"Паніка\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"Атака на мораль вдалась\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"Успішний контроль{NEWLINE}імпланту\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}оскаженів\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}оскаженіла\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}запанікував\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}запанікувала\"\n  STR_XCOM: \"X-COM\"\n  STR_ALIENS: \"Прибульці\"\n  STR_RIGHT_HAND: \"ПРАВА РУКА\"\n  STR_LEFT_HAND: \"ЛІВА РУКА\"\n  STR_RIGHT_SHOULDER: \"ПРАВЕ ПЛЕЧЕ\"\n  STR_LEFT_SHOULDER: \"ЛІВЕ ПЛЕЧЕ\"\n  STR_BACK_PACK: \"РАНЕЦЬ\"\n  STR_BELT: \"ПОЯС\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}під молекулярним контролем\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}під молекулярним контролем\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}втратила свідомість\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}втратила свідомість\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}померла від смертельної рани\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}померла від смертельної рани\"\n  STR_USE_MIND_PROBE: \"Викор. зчитувач МК\"\n  STR_FATAL_WOUNDS: \"СМЕРТЕЛЬНІ РАНИ\"\n  STR_UNDER_ARMOR_UC: \"НИЖНЯ БРОНЯ\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"Одиниці дій зекономлено для пострілу навмання\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"Одиниці дій зекономлено для стрільби чергою\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"Одиниці дій зекономлено для прицільного пострілу\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"ОД зарезервовано для вставання на коліна\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"ОД зарезервовано для вставання на коліна і стрільби\"\n  STR_UNITS_IN_CRAFT:\n    one: \"{N} боєць в кораблі X-Com\"\n    few: \"{N} бійців у кораблі X-Com\"\n    many: \"{N} бійців у кораблі X-Com\"\n    other: \"{N} бійців у кораблі X-Com\"\n  STR_UNITS_OUTSIDE:\n    one: \"{N} боєць поза Зоною Виходу\"\n    few: \"{N} бійців поза Зоною Виходу\"\n    many: \"{N} бійців поза Зоною Виходу\"\n    other: \"{N} бійців поза Зоною Виходу\"\n  STR_UNITS_IN_ENTRANCE:\n    one: \"{N} боєць на вході\"\n    few: \"{N} бійців на вході\"\n    many: \"{N} бійців на вході\"\n    other: \"{N} бійців на вході\"\n  STR_UNITS_IN_EXIT:\n    one: \"{N} боєць на виході\"\n    few: \"{N} бійців на виході\"\n    many: \"{N} бійців на виході\"\n    other: \"{N} бійців на виході\"\n  STR_ABORT_MISSION_QUESTION: \"Перервати місію?\"\n  STR_CORPSE: \"Труп\"\n  STR_UNLOAD_CRAFT: \"Розрядити\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}була вбита\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}була вбита\"\n  STR_HIT_MELEE: \"Вдарити\"\n  STR_GROUND: \"НА ЗЕМЛІ\"\n  STR_LIVING_QUARTERS_PLURAL: \"Житлові модулі\"\n  STR_LIST_ITEM: \"ПРЕДМЕТ\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"Всі прибульці загинули в авіакатастрофі, {NEWLINE}Розпочато автоматичне відновлення\"\n  STR_RESET: \"Скинути\"\n  STR_MEMORIAL: \"Меморіал\"\n  STR_DATE_UC: \"ДАТА\"\n  STR_SOLDIERS_RECRUITED_UC: \"АКВАНАВТІВ НАЙНЯТО>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"АКВАНАВТІВ ВТРАЧЕНО>{ALT}{0}\"\n  STR_REMOVE_SELECTED: \"Видалити обране\"\n  STR_LIVE_ALIENS: \"Живі{NEWLINE}особини\"\n  STR_DEAD_ALIENS: \"Мертві{NEWLINE}особини\"\n  STR_UNDER_INTERROGATION: \"В процесі{NEWLINE}допиту\"\n  STR_CONTAINMENT_EXCEEDED: \"ПЕРЕВИЩЕНО ЛІМІТ ТЮРМИ ДЛЯ ПРИБУЛЬЦІВ!{SMALLLINE}Недостатньо місця в тюрмі на базі {0}. Ви мусите видалити зайвих прибульців з тюрми (вони від цього загинуть).\"\n  STR_MANAGE_CONTAINMENT: \"Управління Тюрмою для Прибульців\"\n  STR_STORAGE_EXCEEDED: \"МІСЦЕ НА СКЛАДАХ ВИЧЕРПАЛОСЬ!{SMALLLINE}Недостатньо місця на складах бази {0}. Ви мусите продати зайві речі.\"\n  STR_GO_TO_BASE: \"Перейти до бази\"\n  STR_MELEE_ACCURACY: \"ТОЧНІСТЬ БЛИЖНЬОГО БОЮ\"\n  STR_SELL_PRODUCTION: \"ПРОДАЖ\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"Обидві руки повинні бути порожніми \"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"Не достатньо предметів для копіювання шаблону!\"\n  STR_UNLOAD_WEAPON: \"Розрядити зброю\"\n  STR_ALL_ITEMS: \"Усі предмети\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    one: \"НЕДОСТАТНЬО МІСЦЯ НА БОРТУ!{SMALLLINE}Ви можете взяти не більше ніж {N} предмет спорядження на цей транспорт.\"\n    few: \"НЕДОСТАТНЬО МІСЦЯ НА БОРТУ!{SMALLLINE}Ви можете взяти не більше {N} предметів спорядження на цей транспорт.\"\n    many: \"НЕДОСТАТНЬО МІСЦЯ НА БОРТУ!{SMALLLINE}Ви можете взяти не більше {N} предметів спорядження на цей транспорт.\"\n    other: \"НЕДОСТАТНЬО МІСЦЯ НА БОРТУ!{SMALLLINE}Ви можете взяти не більше {N} предметів спорядження на цей транспорт.\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}ЦЕНТР КЕРУВАННЯ ЗНИЩЕНО{NEWLINE}Прямуйте до входу та тікайте.\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"Підводні бази X-Com не можуть бути побудовані на суші\"\n  STR_UNABLE_TO_ENGAGE_DEPTH: \"НЕ В ЗМОЗІ АТАКУВАТИ ВОРОГА{NEWLINE} НА ТАКІЙ ГЛИБИНІ\"\n  STR_UNABLE_TO_ENGAGE_AIRBORNE: \"НЕ В ЗМОЗІ ВСТУПИТИ В БІЙ З ВОРОГОМ,{NEWLINE}КОЛИ ПЕРЕБУВАЄ В ПОВІТРІ\"\n  STR_UNDERWATER_EQUIPMENT: \"Це обладнання не працюватиме над водою!\"\n  STR_LAND_EQUIPMENT: \"Це обладнання не працюватиме під водою!\"\n  STR_LEVEL_SHORT: \"L{0}\"\n  STR_PERSONNEL: \"Персонал\"\n  STR_CRAFT_ARMAMENT: \"Літаки та Озброєння\"\n  STR_COMPONENTS: \"Складові\"\n  STR_SOLDIERS_RECRUITED: \"Акванавтів набрано\"\n  STR_SOLDIERS_LOST: \"Акванавтів втрачено\"\n  STR_TOTAL_UFOS: \"Виявлено літаючі субмарини\"\n  STR_TOTAL_ALIEN_BASES: \"Виявлено колонії прибульців\"\n  STR_PSIONIC_STRENGTH_ABBREVIATION: \"С.МК\"\n  STR_PSIONIC_SKILL_ABBREVIATION: \"В.МК\"\n  FEMALE_CIVILIAN: \"Цивільний, жінка\"\n  MALE_CIVILIAN: \"Цивільний, чоловік\"\n  DOCKER_CIVILIAN: \"Цивільний, важтажник\"\n  SAILOR_CIVILIAN: \"Цивільний, моряк\"\n  STR_BIODRONE_MELEE_WEAPON: \"Ближній бій з біо-дроном\"\n  HALLUCINOID_WEAPON: \"Галюциноїдова зброя\"\n  STR_LOBSTERMAN_MELEE_WEAPON: \"Лобстеролюдина - ближній бій\"\n  CALCINITE_WEAPON: \"Кальцинітова зброя\"\n  DEEP_ONE_WEAPON: \"Зброя глибинника\"\n  STR_TRISCENE_MELEE_WEAPON: \"Ближній бій з трисценом\"\n  STR_TRIBIO_SONIC_WEAPON: \"Акустична зброя прибульців\"\n  XARQUID_WEAPON: \"Зброя ксарквіда\"\n  TENTACULAT_WEAPON: \"Зброя тентакулата\"\n  ZOMBIE_WEAPON: \"Зброя зомбі\"\n  ALIEN_PSI_WEAPON: \"Зброя прибульців М.К.\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/zh-CN.yml",
    "content": "zh-CN:\n  STR_DUP_HEAD_UFOPEDIA: \"贫铀武器相对而言还很新，这是第一种完全应用该技术的商业化水下武器系统。\"\n  STR_CRAFT_GAS_CANNON_UFOPEDIA: \"该武器使用压缩气体来发射动穿甲弹丸，具有很强的穿甲能力。\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"以现场为中心 - TIME=5 Secs\"\n  STR_CANCEL_UC: \"取消项目\"\n  STR_NONE: \"无\"\n  STR_UNKNOWN: \"未知\"\n  STR_POOR: \"优秀\"\n  STR_AVERAGE: \"平均\"\n  STR_GOOD: \"好\"\n  STR_EXCELLENT: \"优秀\"\n  STR_BUILD_NEW_BASE_UC: \"建造新基地\"\n  STR_BASE_INFORMATION: \"基地情报\"\n  STR_BUILD_FACILITIES: \"修建设施\"\n  STR_RESEARCH: \"研究\"\n  STR_MANUFACTURE: \"制造\"\n  STR_TRANSFER_UC: \"转移\"\n  STR_PURCHASE_RECRUIT: \"购买/雇用\"\n  STR_SACK: \"解雇\"\n  STR_SELL_SACK_UC: \"卖掉\"\n  STR_GEOSCAPE_UC: \"全球视图\"\n  STR_NAME: \"名字\"\n  STR_AREA: \"地区\"\n  STR_BUILD_NEW_BASE: \"建造新基地\"\n  STR_CANCEL: \"取消\"\n  STR_CONSTRUCTION_TIME_UC: \"建造时间>\"\n  STR_MAINTENANCE_UC: \"维护费用\"\n  STR_OK: \"OK\"\n  STR_CURRENT_RESEARCH: \"当前研究\"\n  STR_SCIENTISTS_AVAILABLE: \"可用科学家>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"可用实验室空间>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"研究项目\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"分配科学家\"\n  STR_PROGRESS: \"进展\"\n  STR_NEW_PROJECT: \"新的项目\"\n  STR_CANCEL_PROJECT: \"取消项目\"\n  STR_NEW_RESEARCH_PROJECTS: \"新的研究计划\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"可用科学家>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"实验室空间剩余>{ALT}{0}\"\n  STR_INCREASE: \"增加\"\n  STR_DECREASE: \"降低\"\n  STR_START_PROJECT: \"开始项目\"\n  STR_CURRENT_PRODUCTION: \"当前制造\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"可用工作室空间>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"当前资金>{ALT}{0}\"\n  STR_ITEM: \"物品\"\n  STR_UNITS_PRODUCED: \"生产数量\"\n  STR_DAYS_HOURS_LEFT: \"日/小时剩下\"\n  STR_NEW_PRODUCTION: \"新制造计划\"\n  STR_PRODUCTION_ITEMS: \"生产项目\"\n  STR_CATEGORY: \"类别\"\n  STR_START_PRODUCTION: \"开始生产\"\n  STR_COST_PER_UNIT_: \"每单位成本>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"需要工作空间>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"需要特殊材料\"\n  STR_ITEM_REQUIRED: \"所需材料\"\n  STR_UNITS_REQUIRED: \"所需数量\"\n  STR_UNITS_AVAILABLE: \"可用单位\"\n  STR_STOP_PRODUCTION: \"停止制造\"\n  STR_MONTHLY_PROFIT: \"每月收益>{ALT}{0}\"\n  STR_INCREASE_UC: \"增加\"\n  STR_DECREASE_UC: \"减少\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"雇佣人员\"\n  STR_COST_OF_PURCHASES: \"交易花费>{ALT}{0}\"\n  STR_QUANTITY_UC: \"数量\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"待命人员：PERSONNEL TOTAL>\"\n  STR_SCIENTISTS: \"科学家\"\n  STR_LIVING_QUARTERS: \"生活区\"\n  STR_STORES: \"通用仓库\"\n  STR_LABORATORIES: \"实验室\"\n  STR_WORK_SHOPS: \"工作间\"\n  STR_DEFENSE_STRENGTH: \"防御力量\"\n  STR_TRANSFERS_UC: \"传输\"\n  STR_TRANSFERS: \"运送物品到{0}\"\n  STR_ARRIVAL_TIME_HOURS: \"到达所需时间（小时）\"\n  STR_AREA_: \"区域>{ALT}{0}\"\n  STR_BASE_NAME: \"基地名称\"\n  STR_TRANSFER: \"调\"\n  STR_SELECT_DESTINATION_BASE: \"选择目的地基地\"\n  STR_INCOME: \"收入\"\n  STR_EXPENDITURE: \"花费\"\n  STR_MAINTENANCE: \"维护费用\"\n  STR_BALANCE: \"预算平衡\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"在{NEWLINE}{1}{NEWLINE}建设的{NEWLINE}{0}{NEWLINE}已经完成\"\n  STR_OK_5_SECONDS: \"好-五秒钟\"\n  STR_RESEARCH_COMPLETED: \"研究完成\"\n  STR_VIEW_REPORTS: \"查看报告\"\n  STR_WE_CAN_NOW_RESEARCH: \"我们现在可以研究\"\n  STR_WE_CAN_NOW_PRODUCE: \"现在我们可以制造\"\n  STR_SUNDAY: \"周日\"\n  STR_MONDAY: \"周一\"\n  STR_TUESDAY: \"周二\"\n  STR_WEDNESDAY: \"周三\"\n  STR_THURSDAY: \"周四\"\n  STR_FRIDAY: \"周五\"\n  STR_SATURDAY: \"周六\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"没有足够的{0}用来补充位于{2}的{1}\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"没有足够的{0}来补充位于{2}的{1}\"\n  STR_ALIENS_DEFEATED: \"外星人被击败\"\n  STR_BASE_IS_LOST: \"X-COM基地陷落\"\n  STR_ALIENS_KILLED: \"杀死外星人\"\n  STR_ALIEN_CORPSES_RECOVERED: \"俘获外星人\"\n  STR_LIVE_ALIENS_RECOVERED: \"俘获外星人\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"外星制品\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"平民被外星人击毙\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"被X-COM人员杀死的平民\"\n  STR_CIVILIANS_SAVED: \"拯救平民数\"\n  STR_FIRING: \"射击\"\n  STR_HIT: \"命中！\"\n  STR_VALUE_OF_SALES: \"出售物品价值>{ALT}{0}\"\n  STR_FUNDS: \"资金>{ALT}{0}\"\n  STR_SELL_SACK: \"出售\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_BASE_DEFENSE: \"基地防御\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"工作空间不足！{SMALLLINE}新建一个工场或者减少其他项目的工作空间占用。\"\n  STR_NOT_ENOUGH_MONEY: \"资金不足！\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"没有足够居住空间！{SMALLLINE}建造新的员工居住区或者将人员转移到其他基地。\"\n  STR_BASE: \"基地\"\n  STR_READY: \"就绪\"\n  STR_REPAIRS: \"修理中\"\n  STR_REFUELLING: \"补充燃料中\"\n  STR_WAY_POINT: \"导航点\"\n  STR_RETURN_TO_BASE: \"返回基地\"\n  STR_SELECT_NEW_TARGET: \"选择新目标\"\n  STR_PATROL: \"巡逻\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"受损——返回基地\"\n  STR_RETURNING_TO_BASE: \"返回基地\"\n  STR_MAXIMUM_SPEED_UC: \"最大速度>{ALT}{0}{ALT}\"\n  STR_WEAPON_ONE: \"武器-1>{ALT}{0}\"\n  STR_NONE_UC: \"没有任何事物\"\n  STR_BASE_: \"基地>{0}\"\n  STR_NAME_UC: \"名字\"\n  STR_AMMO_: \"弹药>{ALT}{0}\"\n  STR_CREW: \"乘员数\"\n  STR_EQUIPMENT_UC: \"装备\"\n  STR_ARMOR: \"装甲\"\n  STR_COLONEL: \"指挥官\"\n  STR_COMMANDER: \"上尉\"\n  STR_MISSIONS2: \"任务\"\n  STR_SPACE_AVAILABLE: \"剩余空间>{ALT}{0}\"\n  STR_WOUNDED: \"受伤\"\n  STR_EQUIPMENT_FOR_CRAFT: \"装备到 {0}\"\n  STR_DEFENSE_VALUE: \"防御力量\"\n  STR_HIT_RATIO: \"命中率\"\n  STR_BEGIN_MISSION: \"任务开始？\"\n  STR_SELECT_ARMAMENT: \"选择武器装备\"\n  STR_AMMUNITION_AVAILABLE: \"可用弹药\"\n  STR_ARMAMENT: \"武器配置\"\n  STR_NOT_AVAILABLE: \"不可用\"\n  STR_SELECT_ARMOR: \"选择装甲\"\n  STR_NORTH: \"北\"\n  STR_NORTH_EAST: \"东北\"\n  STR_EAST: \"东\"\n  STR_SOUTH_EAST: \"东南\"\n  STR_SOUTH: \"南\"\n  STR_SOUTH_WEST: \"西南方\"\n  STR_WEST: \"西\"\n  STR_NORTH_WEST: \"北 西\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"继续追踪拦截\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"跟踪但不开火\"\n  STR_VERY_LARGE: \"很大\"\n  STR_LARGE: \"大型\"\n  STR_MEDIUM_UC: \"中型\"\n  STR_SMALL: \"小\"\n  STR_VERY_SMALL: \"超小型\"\n  STR_SIZE_UC: \"大小\"\n  STR_SPEED: \"速度\"\n  STR_TRACKING_LOST: \"丢失目标\"\n  STR_REDIRECT_CRAFT: \"为战机重新制定目标\"\n  STR_CRASH_SITE_: \"坠毁地点-{0}\"\n  STR_WAY_POINT_: \"路径点-{0}\"\n  STR_TERROR_SITE: \"袭击地点-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}已经抵达了{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"正在巡逻\"\n  STR_ALIEN_ORIGINS: \"外星人起源\"\n  STR_FUEL_CAPACITY: \"燃料剩余>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"武器舱>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"伤害能力>{ALT}{0}{ALT}\"\n  STR_RANGE: \"射程\"\n  STR_KILOMETERS: \"{0} 公里\"\n  STR_ACCURACY: \"精度\"\n  STR_SECONDS: \"{0}秒\"\n  STR_DAMAGE_INCENDIARY: \"磷\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"高爆炸药\"\n  STR_DAMAGE_SMOKE: \"烟雾\"\n  STR_ACCURACY_UC: \"精度\"\n  STR_DAMAGE_UC: \"伤害\"\n  STR_AMMO: \"弹药\"\n  STR_SHOT_TYPE_AUTO: \"自动\"\n  STR_CONSTRUCTION_TIME: \"建造时间>\"\n  STR_CONSTRUCTION_COST: \"工程费用\"\n  STR_MAINTENANCE_COST: \"维护花费\"\n  STR_LOW: \"低\"\n  STR_MEDIUM: \"中\"\n  STR_HIGH: \"高\"\n  STR_WEAPON: \"武器\"\n  STR_AMMUNITION: \"弹药\"\n  STR_EQUIPMENT: \"設備\"\n  STR_ALIEN_CORPSE: \"外星人尸体\"\n  STR_PERSONAL_ARMOR: \"个人护甲\"\n  STR_ALIEN: \"异形\"\n  STR_LOBSTERMAN: \"龙虾人\"\n  STR_DEEP_ONE: \"深海人\"\n  STR_ZOMBIE: \"僵尸\"\n  STR_LIVE_COMMANDER: \"指挥官\"\n  STR_LIVE_NAVIGATOR: \"领航员\"\n  STR_LIVE_MEDIC: \"医疗兵\"\n  STR_LIVE_SOLDIER: \"士兵\"\n  STR_LIVE_TERRORIST: \"恐怖单位\"\n  STR_EXAMINATION_ROOM: \"检查室\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"新型战斗运输机\"\n  STR_SCIENTIST: \"科学家\"\n  STR_NORTH_ATLANTIC: \"北大西洋\"\n  STR_SOUTH_ATLANTIC: \"南大西洋\"\n  STR_INDIAN_OCEAN: \"印度洋\"\n  STR_ARCTIC: \"北极\"\n  STR_EURASIA: \"欧亚洲\"\n  STR_NORTH_AMERICA: \"北美\"\n  STR_AFRICA: \"非洲\"\n  STR_WEAPON_POWER: \"武器伤害\"\n  STR_WEAPON_RANGE: \"武器射程\"\n  STR_LABORATORY: \"实验室\"\n  STR_GENERAL_STORES: \"通用仓库\"\n  STR_ALIEN_CONTAINMENT: \"异形收容设施\"\n  STR_USA: \"美国\"\n  STR_BRAZILIAN_UNION: \"巴西盟\"\n  STR_NEW_MEXICO: \"新墨西哥\"\n  STR_CIVILIAN: \"平民\"\n  STR_JAN: \"一月\"\n  STR_FEB: \"二月\"\n  STR_MAR: \"三月\"\n  STR_APR: \"四月\"\n  STR_MAY: \"五月\"\n  STR_JUN: \"六月\"\n  STR_JUL: \"七月\"\n  STR_AUG: \"八月\"\n  STR_SEP: \"九月\"\n  STR_OCT: \"十月\"\n  STR_NOV: \"十一月\"\n  STR_DEC: \"十二月\"\n  STR_INTERNATIONAL_RELATIONS: \"国际关系\"\n  STR_COUNTRY: \"国家\"\n  STR_FUNDING: \"资金\"\n  STR_CHANGE: \"更改值\"\n  STR_WEAPON_SYSTEMS: \"武器系统\"\n  STR_DAMAGE_UC_: \"伤害>{ALT}{0}\"\n  STR_BATTLESHIP: \"战列舰\"\n  MAP_ISLAND: \"岛\"\n  STR_RATING: \"评分> {0}\"\n  STR_RATING_POOR: \"糟糕！\"\n  STR_RATING_OK: \"OK\"\n  STR_RATING_GOOD: \"好！\"\n  STR_RATING_EXCELLENT: \"优秀\"\n  STR_COUNTRIES_AND: \"{0} 和 {1}\"\n  STR_MISSION: \"任务\"\n  STR_REYKJAVIK: \"雷克雅維克\"\n  STR_BERMUDA: \"百慕大\"\n  STR_NEW_YORK: \"纽约\"\n  STR_BOSTON: \"波士顿\"\n  STR_VANCOUVER: \"温哥华\"\n  STR_HAWAII: \"夏威夷\"\n  STR_FIJI: \"斐濟\"\n  STR_WELLINGTON: \"惠灵顿\"\n  STR_HONG_KONG: \"香港\"\n  STR_SINGAPORE: \"新加坡\"\n  STR_BANGKOK: \"曼谷\"\n  STR_TOKYO: \"东京\"\n  STR_SHANGHAI: \"上海\"\n  STR_LONDON: \"伦敦\"\n  STR_WOUND_RECOVERY: \"创伤复原> {ALT}{0}\"\n  STR_TIME_UNITS: \"时间\"\n  STR_STAMINA: \"体力\"\n  STR_HEALTH: \"生命值\"\n  STR_BRAVERY: \"勇气\"\n  STR_REACTIONS: \"反应\"\n  STR_FIRING_ACCURACY: \"射击精度\"\n  STR_THROWING_ACCURACY: \"投掷精度\"\n  STR_STRENGTH: \"力量\"\n  STR_NEW_RANK: \"晋升军衔\"\n  STR_PROMOTIONS: \"晋级\"\n  STR_ALIEN_INFILTRATION: \"异形渗透任务\"\n  STR_DISMANTLE: \"拆除\"\n  STR_TRANSFER_ITEMS_TO: \"运送物品到{0}\"\n  STR_DESTINATION_UC: \"目的地\"\n  STR_MEDI_KIT: \"医疗包\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"没有足够的物资来完全补充战斗分队\"\n  STR_CAUTIOUS_ATTACK: \"谨慎的攻击\"\n  STR_STANDARD_ATTACK: \"标准攻击\"\n  STR_AGGRESSIVE_ATTACK: \"主动攻击\"\n  STR_DIFFICULTY_LEVEL: \"难度\"\n  STR_INTERCEPT: \"拦截\"\n  STR_BASES: \"基地\"\n  STR_OPTIONS_UC: \"选项\"\n  STR_FUNDING_UC: \"资金\"\n  STR_5_SECONDS: \"五秒\"\n  STR_1_MINUTE: \"一分钟\"\n  STR_5_MINUTES: \"5分钟\"\n  STR_30_MINUTES: \"三十分钟\"\n  STR_1_HOUR: \"一小时\"\n  STR_ENTER_NAME: \"输入名称\"\n  STR_PERFORMANCE_RATING: \"表现评价\"\n  STR_VICTORY_DATE: \"胜利日\"\n  STR_SALARIES: \"薪水\"\n  STR_BASE_MAINTENANCE: \"基地维护\"\n  STR_COST_PER_UNIT: \"每单位成本\"\n  STR_QUANTITY: \"数量\"\n  STR_REAR_ARMOR: \"侧向护甲\"\n  STR_UNDER_ARMOR: \"底部装甲\"\n  STR_UNIT: \"数量>{0}\"\n  STR_MORALE: \"士气\"\n  STR_FRONT_ARMOR_UC: \"前装甲\"\n  STR_LEFT_ARMOR_UC: \"左侧装甲\"\n  STR_REAR_ARMOR_UC: \"侧向护甲\"\n  STR_SKILLS: \"技能>{0}\"\n  STR_TORSO: \"躯干\"\n  STR_RIGHT_ARM: \"右臂\"\n  STR_LEFT_ARM: \"左臂\"\n  STR_RIGHT_LEG: \"右腿\"\n  STR_LEFT_LEG: \"左腿\"\n  STR_PAIN_KILLER: \"止痛药\"\n  STR_THROW: \"丢弃\"\n  STR_AUTO_SHOT: \"全自动射击\"\n  STR_SNAP_SHOT: \"速射\"\n  STR_PRIME_GRENADE: \"感应手榴弹\"\n  STR_USE_MEDI_KIT: \"使用医疗包\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"单位没有足够的时间！\"\n  STR_NO_AMMUNITION_LOADED: \"未装填弹药！\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"武器已经装填！\"\n  STR_NO_LINE_OF_FIRE: \"没有射界！\"\n  STR_GRENADE_IS_ACTIVATED: \"手榴弹已被激活！\"\n  STR_GRENADE_IS_DEACTIVATED: \"手榴弹已被关闭！\"\n  STR_THERE_IS_NO_ONE_THERE: \"这里空无一人！\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"研究完成前无法使用该异形物品！\"\n  STR_OUT_OF_RANGE: \"超出射程！\"\n  STR_UNABLE_TO_THROW_HERE: \"无能在这里扔！\"\n  STR_SET_TIMER: \"设置定时器\"\n  STR_HIDDEN_MOVEMENT: \"隐蔽移动\"\n  STR_TURN: \"回合> {0}\"\n  STR_SIDE: \"侧面>{0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"按任意键继续\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"士气攻击成功\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}已经进入狂暴\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}已经进入狂暴\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}感到十分惊恐\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}感到十分惊恐\"\n  STR_ALIENS: \"外星人\"\n  STR_RIGHT_HAND: \"右手\"\n  STR_LEFT_HAND: \"左手\"\n  STR_RIGHT_SHOULDER: \"右肩\"\n  STR_LEFT_SHOULDER: \"左肩\"\n  STR_BACK_PACK: \"背包\"\n  STR_BELT: \"腰带\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}已经伤重死亡\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}已经伤重死亡\"\n  STR_FATAL_WOUNDS: \"致命伤\"\n  STR_UNDER_ARMOR_UC: \"底部装甲\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"预留速射时间\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"预留扫射时间\"\n  STR_ABORT_MISSION_QUESTION: \"放弃任务？\"\n  STR_CORPSE: \"尸体\"\n  STR_UNLOAD_CRAFT: \"卸载\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}已被杀害\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}已被杀害\"\n  STR_HIT_MELEE: \"命中\"\n  STR_GROUND: \"着陆\"\n  STR_LIVING_QUARTERS_PLURAL: \"生活区\"\n  STR_LIST_ITEM: \"物品\"\n  STR_REMOVE_SELECTED: \"移除所选\"\n  STR_CONTAINMENT_EXCEEDED: \"外星人收容设施容量已满！{SMALLLINE}位于{0}的收容设施容量用尽。你必须把多出来的外星人从收容设施移出，被移出的外星人将会死亡。\"\n  STR_MANAGE_CONTAINMENT: \"管理异形收容设施\"\n  STR_STORAGE_EXCEEDED: \"物品数量达到上限{SMALLLINE} {0}的存储空间不足。你必须将多余的物品售出。\"\n  STR_GO_TO_BASE: \"前往总部\"\n  STR_MELEE_ACCURACY: \"近战精度\"\n  STR_SELL_PRODUCTION: \"卖出\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"两只手都必须是空的！\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"模板中部分物品数量不足，无法复制。\"\n  STR_UNLOAD_WEAPON: \"武器退弹\"\n  STR_ALL_ITEMS: \"全部物品\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}控制中心已被摧毁{NEWLINE}请前往基地入口撤离。\"\n  STR_PERSONNEL: \"人员\"\n  STR_CRAFT_ARMAMENT: \"战机和武器\"\n  STR_COMPONENTS: \"附件\"\n  FEMALE_CIVILIAN: \"平民，女性\"\n  MALE_CIVILIAN: \"平民，男性\"\n  ZOMBIE_WEAPON: \"僵尸武器\"\n"
  },
  {
    "path": "bin/standard/xcom2/Language/zh-TW.yml",
    "content": "zh-TW:\n  STR_AQUATOID_UFOPEDIA: \"水中灰人族是一個比人類還老數千年的遠古社會， 它們矮小的身軀和圓滑的體態和它們在太空的灰人兄弟極為相似。它們的力量源於強大的分子控制技術。水中灰人因不育而需要靠基因改造來繁殖，它們偏好用人類來做實驗對象。其實驗製造了數個混種異族。\"\n  STR_AQUATOID_AUTOPSY: \"驗屍水中灰人\"\n  STR_GILLMAN_AUTOPSY: \"驗屍海底人\"\n  STR_LOBSTERMAN_AUTOPSY: \"驗屍龍蝦人\"\n  STR_TASOTH_AUTOPSY: \"驗屍魚蜥人\"\n  STR_DEEP_ONE_AUTOPSY: \"驗屍深海異形\"\n  STR_BIODRONE_AUTOPSY: \"驗屍生質機械\"\n  STR_TENTACULAT_AUTOPSY: \"驗屍觸手人\"\n  STR_CALCINITE_AUTOPSY: \"驗屍方解石族\"\n  STR_CENTER_ON_SITE_TIME_5_SECONDS: \"置中該地-時間流逝=5 秒\"\n  STR_CANCEL_UC: \"取消\"\n  STR_NONE: \"無\"\n  STR_UNKNOWN: \"未知\"\n  STR_POOR: \"差\"\n  STR_AVERAGE: \"普\"\n  STR_GOOD: \"良\"\n  STR_EXCELLENT: \"優\"\n  STR_BUILD_NEW_BASE_UC: \"建設新基地\"\n  STR_BASE_INFORMATION: \"基地資訊\"\n  STR_BUILD_FACILITIES: \"增建設施\"\n  STR_RESEARCH: \"研究\"\n  STR_MANUFACTURE: \"生產\"\n  STR_TRANSFER_UC: \"運輸\"\n  STR_PURCHASE_RECRUIT: \"購買/招募\"\n  STR_SACK: \"解雇\"\n  STR_SELL_SACK_UC: \"賣出/解雇 \"\n  STR_GEOSCAPE_UC: \"全球介面\"\n  STR_NAME: \"名稱\"\n  STR_AREA: \"地區\"\n  STR_BUILD_NEW_BASE: \"建設新基地\"\n  STR_CANCEL: \"取消\"\n  STR_COST_UC: \"成本>\"\n  STR_CONSTRUCTION_TIME_UC: \"建造需時>\"\n  STR_MAINTENANCE_UC: \"維修>\"\n  STR_OK: \"尚可\"\n  STR_INSTALLATION: \"安裝\"\n  STR_CURRENT_RESEARCH: \"當前研究\"\n  STR_SCIENTISTS_AVAILABLE: \"可用的科學家>{ALT}{0}\"\n  STR_SCIENTISTS_ALLOCATED: \"已配置的科學家>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE: \"可用的實驗室空間>{ALT}{0}\"\n  STR_RESEARCH_PROJECT: \"研究專案\"\n  STR_SCIENTISTS_ALLOCATED_UC: \"已配置的科學家\"\n  STR_PROGRESS: \"進展\"\n  STR_NEW_PROJECT: \"新專案\"\n  STR_CANCEL_PROJECT: \"取消專案\"\n  STR_NEW_RESEARCH_PROJECTS: \"新研究專案\"\n  STR_SCIENTISTS_AVAILABLE_UC: \"可用的科學家>{ALT}{0}\"\n  STR_LABORATORY_SPACE_AVAILABLE_UC: \"可用的實驗室空間>{ALT}{0}\"\n  STR_INCREASE: \"增加\"\n  STR_DECREASE: \"減少\"\n  STR_START_PROJECT: \"開始專案\"\n  STR_CURRENT_PRODUCTION: \"生產中的項目\"\n  STR_WORKSHOP_SPACE_AVAILABLE: \"可用的工作室空間>{ALT}{0}\"\n  STR_CURRENT_FUNDS: \"現有資金>{ALT}{0}\"\n  STR_ITEM: \"道具\"\n  STR_UNITS_PRODUCED: \"已生產單位\"\n  STR_TOTAL_TO_PRODUCE: \"生產總數\"\n  STR_COST__PER__UNIT: \"每單位{NEWLINE}成本{NEWLINE}\"\n  STR_DAYS_HOURS_LEFT: \"尚餘日/小時\"\n  STR_NEW_PRODUCTION: \"新生產\"\n  STR_PRODUCTION_ITEMS: \"生產物品\"\n  STR_CATEGORY: \"類別\"\n  STR_START_PRODUCTION: \"開始新產\"\n  STR_COST_PER_UNIT_: \"每單位成本>{ALT}{0}\"\n  STR_WORK_SPACE_REQUIRED: \"所需工作空間>{ALT}{0}\"\n  STR_SPECIAL_MATERIALS_REQUIRED: \"所需特別材料\"\n  STR_ITEM_REQUIRED: \"所需物品\"\n  STR_UNITS_REQUIRED: \"所需單位\"\n  STR_UNITS_AVAILABLE: \"可用單位\"\n  STR_STOP_PRODUCTION: \"停止生產\"\n  STR_WORKSHOP_SPACE_AVAILABLE_UC: \"可用的工作室空間>{ALT}{0}\"\n  STR_MONTHLY_PROFIT: \"月利潤>{ALT}{0}\"\n  STR_INCREASE_UC: \"增加\"\n  STR_DECREASE_UC: \"減少\"\n  STR_UNITS_TO_PRODUCE: \"要製造的單位\"\n  STR_PURCHASE_HIRE_PERSONNEL: \"購買/招募人員\"\n  STR_COST_OF_PURCHASES: \"購買成本>{ALT}{0}\"\n  STR_COST_PER_UNIT_UC: \"每單位成本\"\n  STR_QUANTITY_UC: \"數量\"\n  STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL: \"可用人員:人員總數>\"\n  STR_SCIENTISTS: \"科學家\"\n  STR_SPACE_USED_SPACE_AVAILABLE: \"已使用空間:總可用空間>\"\n  STR_LIVING_QUARTERS: \"起居室\"\n  STR_STORES: \"倉庫\"\n  STR_LABORATORIES: \"實驗室\"\n  STR_WORK_SHOPS: \"工作室\"\n  STR_DEFENSE_STRENGTH: \"防禦力\"\n  STR_TRANSFERS_UC: \"運輸\"\n  STR_TRANSFERS: \"運輸\"\n  STR_ARRIVAL_TIME_HOURS: \"送達時間 (小時)\"\n  STR_COST_: \"成本>{ALT}{0}\"\n  STR_AREA_: \"地區>{ALT}{0}\"\n  STR_BASE_NAME: \"基地名稱?\"\n  STR_TRANSFER: \"運輸\"\n  STR_AMOUNT_TO_TRANSFER: \"轉移量\"\n  STR_SELECT_DESTINATION_BASE: \"選擇目的基地\"\n  STR_COST: \"成本\"\n  STR_TOTAL_UC: \"總數\"\n  STR_INCOME: \"收入\"\n  STR_EXPENDITURE: \"支出\"\n  STR_MAINTENANCE: \"維修\"\n  STR_BALANCE: \"結餘\"\n  STR_FINANCE: \"財務狀況\"\n  STR_DATE_FIRST: \"第{0}\"\n  STR_DATE_SECOND: \"第{0}\"\n  STR_DATE_THIRD: \"第{0}\"\n  STR_DATE_FOURTH: \"第{0}\"\n  STR_FINANCE_THOUSANDS: \"$1000的\"\n  STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE: \"要生產{NEWLINE}{1}的特殊物質不足{NEWLINE}{0}{NEWLINE}\"\n  STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE: \"要生產{NEWLINE}{1}的金錢不足{NEWLINE}{0}{NEWLINE}\"\n  STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE: \"已完成{NEWLINE}{0}{NEWLINE}在{NEWLINE}{1}{NEWLINE}的生產\"\n  STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE: \"已完成{NEWLINE}{0}{NEWLINE}在{NEWLINE}{1}{NEWLINE}的建設\"\n  STR_OK_5_SECONDS: \"OK - 5 秒\"\n  STR_RESEARCH_COMPLETED: \"研究完成\"\n  STR_VIEW_REPORTS: \"觀看報告\"\n  STR_WE_CAN_NOW_RESEARCH: \"我們可以開始研究\"\n  STR_WE_CAN_NOW_PRODUCE: \"我們可以開始生產\"\n  STR_SUNDAY: \"星期日\"\n  STR_MONDAY: \"星期一\"\n  STR_TUESDAY: \"星期二\"\n  STR_WEDNESDAY: \"星期三\"\n  STR_THURSDAY: \"星期四\"\n  STR_FRIDAY: \"星期五\"\n  STR_SATURDAY: \"星期六\"\n  STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE: \"{0}不足以將位於{2}的{1}裝滿油\"\n  STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE: \"{2}沒有足夠{0}去裝備{1}\"\n  STR_ALIENS_DEFEATED: \"外星人被擊敗\"\n  STR_BASE_IS_LOST: \"失去基地\"\n  STR_BASE_IS_SAVED: \"成功守護基地\"\n  STR_ALIENS_KILLED: \"被殺死的外星人\"\n  STR_ALIEN_CORPSES_RECOVERED: \"回收的異形屍體\"\n  STR_LIVE_ALIENS_RECOVERED: \"活捉的異形\"\n  STR_ALIEN_ARTIFACTS_RECOVERED: \"外星物品回收\"\n  STR_CIVILIANS_KILLED_BY_ALIENS: \"被異形殺死的平民\"\n  STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES: \"X-COM作業人員誤殺的平民\"\n  STR_CIVILIANS_SAVED: \"被救出的平民\"\n  STR_XCOM_OPERATIVES_KILLED: \"被殺的X-COM作業人員\"\n  STR_XCOM_OPERATIVES_MISSING_IN_ACTION: \"失蹤的X-COM作業人員\"\n  STR_BASE_UNDER_ATTACK: \"{0} 遭襲!\"\n  STR_BASE_DEFENSES_INITIATED: \"啟動基地防衛設置\"\n  STR_FIRING: \"開火中\"\n  STR_HIT: \"擊中!\"\n  STR_MISSED: \"沒有命中!\"\n  STR_SELL_ITEMS_SACK_PERSONNEL: \"賣出物件/裁員\"\n  STR_VALUE_OF_SALES: \"出售價值>{ALT}{0}\"\n  STR_FUNDS: \"基金>{ALT}{0}\"\n  STR_SELL_SACK: \"出售/解雇\"\n  STR_VALUE: \"價值\"\n  STR_CRAFTNAME: \"{0}-{1}\"\n  STR_BASE_DEFENSE: \"基地防禦\"\n  STR_BASE_UC_: \"基地> {0}\"\n  STR_NO_FREE_ACCOMODATION: \"沒有額外的居住空間!{SMALLLINE}目的地居住區沒有足夠空間。\"\n  STR_NOT_ENOUGH_WORK_SPACE: \"沒有額外的工作空間 !{SMALLLINE}建造一間新工作室或減少其他方案的工作量。\"\n  STR_NOT_ENOUGH_MONEY: \"資金不足!\"\n  STR_NOT_ENOUGH_STORE_SPACE: \"儲物空間不足!{SMALLLINE}建造新的儲物設施或將這裏的物資轉移至其他基地。\"\n  STR_NOT_ENOUGH_LIVING_SPACE: \"居住空間不足!{SMALLLINE}建造新住宅區或將人員調往其他基地。\"\n  STR_LAUNCH_INTERCEPTION: \"派機截擊\"\n  STR_CRAFT: \"載具\"\n  STR_STATUS: \"狀況\"\n  STR_BASE: \"基地\"\n  STR_READY: \"可用\"\n  STR_OUT: \"不在\"\n  STR_REPAIRS: \"維修中\"\n  STR_REFUELLING: \"補給燃料中\"\n  STR_REARMING: \"武器裝填中\"\n  STR_TARGET: \"目標: {0}\"\n  STR_WAY_POINT: \"導航點\"\n  STR_YES: \"是\"\n  STR_NO: \"否\"\n  STR_SELECT_DESTINATION: \"選擇目的地\"\n  STR_SELECT_SITE_FOR_NEW_BASE: \"選擇建造新基地的地點\"\n  STR_RETURN_TO_BASE: \"回基地\"\n  STR_SELECT_NEW_TARGET: \"選擇新目標\"\n  STR_PATROL: \"巡邏\"\n  STR_STATUS_: \"狀況>{ALT}{0}\"\n  STR_DAMAGED_RETURNING_TO_BASE: \"受損  - 正返回基地\"\n  STR_LOW_FUEL_RETURNING_TO_BASE: \"燃料將用盡 - 正返回基地\"\n  STR_MISSION_COMPLETE_RETURNING_TO_BASE: \"任務完成 - 正返回基地\"\n  STR_PATROLLING: \"巡邏中\"\n  STR_RETURNING_TO_BASE: \"正返回基地\"\n  STR_DESTINATION_UC_: \"目標: {0}\"\n  STR_BASE_UC: \"基地>{ALT}{0}\"\n  STR_SPEED_: \"速度>{ALT}{0}\"\n  STR_MAXIMUM_SPEED_UC: \"最高速度>{ALT}{0}{ALT}\"\n  STR_FUEL: \"燃料>{ALT}{0}\"\n  STR_WEAPON_ONE: \"武器-1>{ALT}{0}\"\n  STR_NONE_UC: \"無\"\n  STR_ROUNDS_: \"子彈量>{ALT}{0}\"\n  STR_WEAPON_TWO: \"武器-2>{ALT}{0}\"\n  STR_BASE_: \"基地>{0}\"\n  STR_NAME_UC: \"名稱\"\n  STR_AMMO_: \"彈藥>{ALT}{0}\"\n  STR_CREW: \"人員\"\n  STR_EQUIPMENT_UC: \"設備\"\n  STR_ARMOR: \"裝甲\"\n  STR_MAX: \"最大>{ALT}{0}\"\n  STR_COLONEL: \" 指揮官\"\n  STR_COMMANDER: \"上尉\"\n  STR_SELECT_SQUAD_FOR_CRAFT: \"選擇 {0} 的小隊\"\n  STR_SORT_BY: \"排序依據的項目\"\n  STR_ORIGINAL_ORDER: \"原始排序\"\n  STR_MISSIONS2: \"任務\"\n  STR_KILLS2: \"撃殺\"\n  STR_WOUND_RECOVERY2: \"康復需時\"\n  STR_SPACE_AVAILABLE: \"尚餘機位>{ALT}{0}\"\n  STR_SPACE_USED: \"已佔機位>{ALT}{0}\"\n  STR_SPACE_USED_UC: \"已佔機位\"\n  STR_RANK: \"軍階\"\n  STR_WOUNDED: \"受傷\"\n  STR_EQUIPMENT_FOR_CRAFT: \"{0} 的裝備\"\n  STR_DEFENSE_VALUE: \"防禦值\"\n  STR_HIT_RATIO: \"命中比例\"\n  STR_BEGIN_MISSION: \"開始任務？\"\n  STR_SELECT_ARMAMENT: \"選擇艦載武器\"\n  STR_AMMUNITION_AVAILABLE: \"可用彈藥\"\n  STR_ARMAMENT: \"艦載武器\"\n  STR_NOT_AVAILABLE: \"用完\"\n  STR_TYPE: \"型號\"\n  STR_SELECT_ARMOR: \"選擇護甲\"\n  STR_NORTH: \"北\"\n  STR_NORTH_EAST: \"東北\"\n  STR_EAST: \"東\"\n  STR_SOUTH_EAST: \"東南\"\n  STR_SOUTH: \"南\"\n  STR_SOUTH_WEST: \"西南\"\n  STR_WEST: \"西\"\n  STR_NORTH_WEST: \"西北\"\n  STR_SELECT_ACTION: \"行動選擇\"\n  STR_CONTINUE_INTERCEPTION_PURSUIT: \"繼續追蹤並攔截\"\n  STR_PURSUE_WITHOUT_INTERCEPTION: \"只追蹤但不攔截\"\n  STR_VERY_LARGE: \"非常巨大\"\n  STR_LARGE: \"大\"\n  STR_MEDIUM_UC: \"中\"\n  STR_SMALL: \"小\"\n  STR_VERY_SMALL: \"很小\"\n  STR_DETECTED: \"被探測到\"\n  STR_SIZE_UC: \"大小\"\n  STR_HEADING: \"航向\"\n  STR_SPEED: \"速度\"\n  STR_TRACKING_LOST: \"失去蹤影\"\n  STR_REDIRECT_CRAFT: \"重新指示載機航向\"\n  STR_CRASH_SITE_: \"墜毀地點-{0}\"\n  STR_WAY_POINT_: \"導航點-{0}\"\n  STR_TERROR_SITE: \"恐怖襲擊地點-{0}\"\n  STR_CRAFT_HAS_REACHED_DESTINATION: \"{0}{NEWLINE}已達{NEWLINE}{1}\"\n  STR_NOW_PATROLLING: \"正在巡邏\"\n  STR_ALIEN_ORIGINS: \"異形起源\"\n  STR_UFOPAEDIA: \"UFO 百科全書\"\n  STR_SELECT_ITEM: \"選擇物品\"\n  STR_ACCELERATION: \"加速度>{ALT}{0}{ALT}\"\n  STR_FUEL_CAPACITY: \"燃料容量>{ALT}{0}{ALT}\"\n  STR_WEAPON_PODS: \"武器架>{ALT}{0}{ALT}\"\n  STR_DAMAGE_CAPACITY_UC: \"裝甲防禦力>{ALT}{0}{ALT}\"\n  STR_CARGO_SPACE: \"可載人員>{ALT}{0}{ALT}\"\n  STR_DAMAGE: \"破壞力\"\n  STR_RANGE: \"射程\"\n  STR_KILOMETERS: \"{0} 公里\"\n  STR_ACCURACY: \"精準度\"\n  STR_RE_LOAD_TIME: \"裝填需時\"\n  STR_SECONDS: \"{0}們\"\n  STR_DAMAGE_ARMOR_PIERCING: \"穿甲性\"\n  STR_DAMAGE_HIGH_EXPLOSIVE: \"高爆性火藥\"\n  STR_DAMAGE_MELEE: \"肉搏\"\n  STR_DAMAGE_ACID: \"酸性\"\n  STR_DAMAGE_SMOKE: \"煙霧\"\n  STR_SHOT_TYPE: \"型號\"\n  STR_ACCURACY_UC: \"命中率\"\n  STR_TIME_UNIT_COST: \"花費TU\"\n  STR_DAMAGE_UC: \"破壞力\"\n  STR_AMMO: \"彈藥\"\n  STR_SHOT_TYPE_AUTO: \"自動\"\n  STR_SHOT_TYPE_SNAP: \"快速\"\n  STR_SHOT_TYPE_AIMED: \"精準\"\n  STR_CONSTRUCTION_TIME: \"建造需時\"\n  STR_CONSTRUCTION_COST: \"建造成本\"\n  STR_MAINTENANCE_COST: \"維修成本\"\n  STR_LOW: \"低\"\n  STR_MEDIUM: \"中\"\n  STR_HIGH: \"高\"\n  STR_WEAPON: \"武器\"\n  STR_AMMUNITION: \"彈藥\"\n  STR_EQUIPMENT: \"設備\"\n  STR_ALIEN_CORPSE: \"外星人屍體\"\n  STR_PERSONAL_ARMOR: \"個人護甲\"\n  STR_RAW_MATERIALS: \"原料\"\n  STR_ALIEN: \"外星人\"\n  STR_LOBSTERMAN: \"龙虾人\"\n  STR_DEEP_ONE: \"深海人\"\n  STR_ZOMBIE: \"殭屍\"\n  STR_LIVE_COMMANDER: \" 指揮官\"\n  STR_LIVE_NAVIGATOR: \" 領航員\"\n  STR_LIVE_MEDIC: \" 軍醫\"\n  STR_LIVE_SOLDIER: \"士兵\"\n  STR_LIVE_TERRORIST: \" 執行恐襲單位\"\n  STR_EXAMINATION_ROOM: \"檢查室\"\n  STR_NEW_FIGHTER_TRANSPORTER: \"新型戰鬥運兵機\"\n  STR_ARMOR_PIERCING: \"穿甲性\"\n  STR_SCIENTIST: \"科學家\"\n  STR_NORTH_ATLANTIC: \"北大西洋\"\n  STR_SOUTH_ATLANTIC: \"南大西洋\"\n  STR_INDIAN_OCEAN: \"印度洋\"\n  STR_ARCTIC: \"北極圈\"\n  STR_NORTH_AMERICA: \"北美\"\n  STR_AFRICA: \"非洲\"\n  STR_MAXIMUM_SPEED: \"最高速度\"\n  STR_DAMAGE_CAPACITY: \"裝甲防禦力\"\n  STR_WEAPON_POWER: \"武器威力\"\n  STR_WEAPON_RANGE: \"武器射程\"\n  STR_LABORATORY: \"實驗室\"\n  STR_WORKSHOP: \"工作室\"\n  STR_GENERAL_STORES: \"通用儲物倉\"\n  STR_ALIEN_CONTAINMENT: \"外星人監禁倉\"\n  STR_USA: \"美國\"\n  STR_CIVILIAN: \"平民\"\n  STR_JAN: \"一月\"\n  STR_FEB: \"二月\"\n  STR_MAR: \"三月\"\n  STR_APR: \"四月\"\n  STR_MAY: \"五月\"\n  STR_JUN: \"六月\"\n  STR_JUL: \"七月\"\n  STR_AUG: \"八月\"\n  STR_SEP: \"九月\"\n  STR_OCT: \"十月\"\n  STR_NOV: \"十一月\"\n  STR_DEC: \"十二月\"\n  STR_INTERNATIONAL_RELATIONS: \"國際關系\"\n  STR_COUNTRY: \"國家\"\n  STR_FUNDING: \"資金\"\n  STR_CHANGE: \"改變\"\n  STR_WEAPON_SYSTEMS: \"武器系統\"\n  STR_DAMAGE_UC_: \"裝甲防禦力>{ALT}{0}\"\n  STR_MAGNA_BLAST_GRENADE_UFOPEDIA: \"這常規用的手榴彈內有準確精密的計時器，可精確控制爆炸時間。\"\n  STR_BATTLESHIP: \"戰鬥艦\"\n  MAP_XBASES: \"X-Com基地\"\n  STR_RATING: \"評價> {0}\"\n  STR_RATING_TERRIBLE: \"一團糟!\"\n  STR_RATING_POOR: \"差強人意!\"\n  STR_RATING_OK: \"尚可\"\n  STR_RATING_GOOD: \"良好!\"\n  STR_RATING_EXCELLENT: \"非常出色!\"\n  STR_SCORE: \"評分\"\n  STR_MONTH: \"月> {ALT}{0} {1}\"\n  STR_COUNTRY_IS_PARTICULARLY_PLEASED: \"{0}特別滿意你處理當地威脅的能力，因此願意投入更多資金。\"\n  STR_COUNTRIES_COMMA: \"{0}, {1}\"\n  STR_COUNTRIES_AND: \"{0}和{1}\"\n  STR_KNOTS: \"{0}海哩\"\n  STR_MONTHLY_RATING: \"每月評價> {ALT}{0}{ALT} {1}\"\n  STR_FUNDING_CHANGE: \"資金增減> {ALT}{0}\"\n  STR_RACE: \"種族\"\n  STR_MISSION: \"任務\"\n  STR_ZONE: \"地帶\"\n  STR_ALLOCATE_RESEARCH: \"分配研究資源\"\n  STR_ALLOCATE_MANUFACTURE: \"分配生產資源\"\n  STR_AZORES: \"亞速群島\"\n  STR_REYKJAVIK: \"雷克雅維克\"\n  STR_BERMUDA: \"百慕大\"\n  STR_NEW_YORK: \"紐約\"\n  STR_BOSTON: \"波士顿\"\n  STR_DAKAR: \"達喀爾\"\n  STR_RECIFE: \"累西腓\"\n  STR_ACCRA: \"阿克拉\"\n  STR_ASCENSION_ISLAND: \"阿森松岛\"\n  STR_TRINIDADE_ISLAND: \"特林达德岛\"\n  STR_FALKLAND_ISLAND: \"福克兰岛\"\n  STR_CANARY_ISLANDS: \"加那利群岛\"\n  STR_ANCHORAGE: \"安克拉治\"\n  STR_ST_LAWRENCE_ISLAND: \"聖勞倫斯島\"\n  STR_SAN_FRANCISCO: \"舊金山\"\n  STR_MIDWAY_ISLAND: \"中途島\"\n  STR_VANCOUVER: \"溫哥華\"\n  STR_TASMANIA: \"塔斯馬尼亞州\"\n  STR_HAWAII: \"夏威夷\"\n  STR_FIJI: \"斐濟\"\n  STR_TONGA: \"湯加\"\n  STR_EASTER_ISLAND: \"復活節島\"\n  STR_WELLINGTON: \"威靈頓\"\n  STR_CRETE: \"克里特島\"\n  STR_LISBON: \"里斯本\"\n  STR_PORT_SAID: \"塞得港\"\n  STR_MARSEILLES: \"马赛\"\n  STR_TRIPOLI: \"的黎波里\"\n  STR_MANILA: \"馬尼拉\"\n  STR_HONG_KONG: \"香港\"\n  STR_SINGAPORE: \"新加坡\"\n  STR_BANGKOK: \"曼谷\"\n  STR_DARWIN: \"达尔文\"\n  STR_BOMBAY: \"孟買\"\n  STR_SAYCHELLES_ISLAND: \"塞舌尔\"\n  STR_SRI_LANKA: \"斯里蘭卡\"\n  STR_MAURITIUS: \"模里西斯\"\n  STR_TOKYO: \"東京\"\n  STR_SHANGHAI: \"上海\"\n  STR_VLADIVOSTOK: \"海參崴\"\n  STR_LONDON: \"倫敦\"\n  STR_OSLO: \"奥斯陆\"\n  STR_JAMAICA: \"牙买加\"\n  STR_PANAMA: \"巴拿馬\"\n  STR_MIAMI: \"迈阿密\"\n  STR_IN_TRAINING: \"正在{NEWLINE}訓練中?\"\n  STR_TARGETTED_BY: \"負責追截:\"\n  STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE: \"燃料不足，{NEWLINE}正返回基地\"\n  STR_RANK_: \"官階> {ALT}{0}\"\n  STR_MISSIONS: \"任務次數> {ALT}{0}\"\n  STR_KILLS: \"殺敵數> {ALT}{0}\"\n  STR_WOUND_RECOVERY: \"康復需時> {ALT}{0}\"\n  STR_TIME_UNITS: \"時間單位\"\n  STR_STAMINA: \"體力\"\n  STR_HEALTH: \"健康狀態\"\n  STR_BRAVERY: \"勇氣\"\n  STR_REACTIONS: \"反應度\"\n  STR_FIRING_ACCURACY: \"射擊能力\"\n  STR_THROWING_ACCURACY: \"投擲能力\"\n  STR_STRENGTH: \"筋力\"\n  STR_NEW_RANK: \"新官階\"\n  STR_PROMOTIONS: \"晉升\"\n  STR_SOLDIERS_UC: \"潛水伕\"\n  STR_ALIEN_INFILTRATION: \"外星滲透行動\"\n  STR_DISMANTLE: \"拆卸\"\n  STR_TRANSFER_ITEMS_TO: \"轉移物品至\"\n  STR_AMOUNT_AT_DESTINATION: \"目的地{NEWLINE}存量\"\n  STR_ITEMS_ARRIVING: \"轉移中的物品\"\n  STR_DESTINATION_UC: \"目的地\"\n  STR_MEDI_KIT: \"醫療工具箱\"\n  STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD: \"沒有足夠裝備去完全補給小隊\"\n  STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM: \"您需要研究一個{NEWLINE}{0}{NEWLINE}以製造{NEWLINE}{1}\"\n  STR_STANDOFF: \"對峙\"\n  STR_CAUTIOUS_ATTACK: \"謹慎攻擊\"\n  STR_STANDARD_ATTACK: \"普通攻擊\"\n  STR_AGGRESSIVE_ATTACK: \"進取攻擊\"\n  STR_DISENGAGING: \"脫離戰線\"\n  STR_MINIMISE_AT_STANDOFF_RANGE_ONLY: \"維持對峙距離並最小化視窗\"\n  STR_STORES_UC: \"儲物倉\"\n  STR_DIFFICULTY_LEVEL: \"難易度\"\n  STR_INTERCEPT: \"截擊\"\n  STR_BASES: \"基地\"\n  STR_GRAPHS: \"圖表\"\n  STR_OPTIONS_UC: \"選項\"\n  STR_FUNDING_UC: \"資金\"\n  STR_5_SECONDS: \"5 秒鐘\"\n  STR_1_MINUTE: \"1 分鐘\"\n  STR_5_MINUTES: \"5 分鐘\"\n  STR_30_MINUTES: \"30 分鐘\"\n  STR_1_HOUR: \"1 小時\"\n  STR_1_DAY: \"1 整日\"\n  STR_XCOM_PERFORMANCE_ROSTER: \"Ｘ-ＣＯＭ 績效名冊\"\n  STR_ENTER_NAME: \"輸入名稱\"\n  STR_PERFORMANCE_RATING: \"表現評核\"\n  STR_VICTORY_DATE: \"勝利日\"\n  STR_MONTHLY_COSTS: \"每月成本\"\n  STR_SALARIES: \"人工\"\n  STR_BASE_MAINTENANCE: \"基地維修\"\n  STR_COST_PER_UNIT: \"每單位成本\"\n  STR_QUANTITY: \"數量\"\n  STR_TOTAL: \"總數\"\n  STR_FRONT_ARMOR: \"前護甲\"\n  STR_LEFT_ARMOR: \"左護甲\"\n  STR_RIGHT_ARMOR: \"右護甲\"\n  STR_REAR_ARMOR: \"背護甲\"\n  STR_UNDER_ARMOR: \"下護甲\"\n  STR_UNIT: \"單位> {0}\"\n  STR_ENERGY: \"體力\"\n  STR_MORALE: \"士氣\"\n  STR_ARMOR_: \"護甲> {0}\"\n  STR_FRONT_ARMOR_UC: \"前護甲\"\n  STR_LEFT_ARMOR_UC: \"左護甲\"\n  STR_RIGHT_ARMOR_UC: \"右護甲\"\n  STR_REAR_ARMOR_UC: \"背護甲\"\n  STR_SKILLS: \"技能> {0}\"\n  STR_LEVEL: \"等級> {0}\"\n  STR_HEAD: \"頭部\"\n  STR_TORSO: \"軀幹\"\n  STR_RIGHT_ARM: \"右臂\"\n  STR_LEFT_ARM: \"左臂\"\n  STR_RIGHT_LEG: \"右腿\"\n  STR_LEFT_LEG: \"左腿\"\n  STR_PAIN_KILLER: \"止痛劑\"\n  STR_STIMULANT: \"激勵藥\"\n  STR_HEAL: \"治療\"\n  STR_TIME_UNITS_SHORT: \"TU>{ALT}{0}\"\n  STR_WEIGHT: \"負重>{ALT}{0}/{1}\"\n  STR_REACTIONS_SHORT: \"反應>{ALT}{0}\"\n  STR_AMMO_ROUNDS_LEFT: \"彈藥:{NEWLINE}尚餘{NEWLINE}彈量={ALT}{0}\"\n  STR_MEDI_KIT_QUANTITIES_LEFT: \"疼痛>{ALT}{0}{ALT}{NEWLINE}戰鬥藥劑>{ALT}{1}{ALT}{NEWLINE}治療>{ALT}{2}\"\n  STR_THROW: \"投擲\"\n  STR_AUTO_SHOT: \"自動射擊\"\n  STR_SNAP_SHOT: \"快速射擊\"\n  STR_AIMED_SHOT: \"精準射擊\"\n  STR_STUN: \"令其眩暈\"\n  STR_PRIME_GRENADE: \"較手榴彈\"\n  STR_USE_MEDI_KIT: \"使用醫療包\"\n  STR_LAUNCH_MISSILE: \"發射魚雷\"\n  STR_ACCURACY_SHORT: \"命中率>{ALT}{0}\"\n  STR_NOT_ENOUGH_TIME_UNITS: \"沒有足夠的TU!\"\n  STR_NOT_ENOUGH_ENERGY: \"沒有足夠的精力!\"\n  STR_NO_ROUNDS_LEFT: \"子彈用盡!\"\n  STR_NO_AMMUNITION_LOADED: \"無上膛的彈藥!\"\n  STR_WRONG_AMMUNITION_FOR_THIS_WEAPON: \"此彈藥不適用此武器!\"\n  STR_WEAPON_IS_ALREADY_LOADED: \"武器已上膛!\"\n  STR_NO_LINE_OF_FIRE: \"不在火線!\"\n  STR_GRENADE_IS_ACTIVATED: \"手榴彈已拔除插銷!\"\n  STR_GRENADE_IS_DEACTIVATED: \"手榴彈已重新插銷!\"\n  STR_THERE_IS_NO_ONE_THERE: \"那裏沒有生物!\"\n  STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED: \"無法使用尚未研發的異形聖物!\"\n  STR_OUT_OF_RANGE: \"射程外!\"\n  STR_UNABLE_TO_THROW_HERE: \"無法拋擲到那裡!\"\n  STR_SET_TIMER: \"設定計時器\"\n  STR_HIDDEN_MOVEMENT: \"匿蹤移動\"\n  STR_TURN: \"回合>{0}\"\n  STR_SIDE: \"一方> {0}\"\n  STR_PRESS_BUTTON_TO_CONTINUE: \"按下按鈕以繼續\"\n  STR_MIND_CONTROL: \"分子控制\"\n  STR_MORALE_ATTACK_SUCCESSFUL: \"士氣攻擊成功\"\n  STR_MIND_CONTROL_SUCCESSFUL: \"植入控制成功\"\n  STR_HAS_GONE_BERSERK_MALE: \"{0}{NEWLINE}暴走中\"\n  STR_HAS_GONE_BERSERK_FEMALE: \"{0}{NEWLINE}暴走中\"\n  STR_HAS_PANICKED_MALE: \"{0}{NEWLINE}恐慌中\"\n  STR_HAS_PANICKED_FEMALE: \"{0}{NEWLINE}恐慌中\"\n  STR_XCOM: \"X-Com\"\n  STR_ALIENS: \"異形\"\n  STR_RIGHT_HAND: \"右手\"\n  STR_LEFT_HAND: \"左手\"\n  STR_RIGHT_SHOULDER: \"右肩\"\n  STR_LEFT_SHOULDER: \"左肩\"\n  STR_BACK_PACK: \"背包\"\n  STR_BELT: \"腰帶\"\n  STR_IS_UNDER_ALIEN_CONTROL_MALE: \"{0}{NEWLINE}被分子控制中\"\n  STR_IS_UNDER_ALIEN_CONTROL_FEMALE: \"{0}{NEWLINE}被分子控制中\"\n  STR_HAS_BECOME_UNCONSCIOUS_MALE: \"{0}{NEWLINE}已昏迷\"\n  STR_HAS_BECOME_UNCONSCIOUS_FEMALE: \"{0}{NEWLINE}已昏迷\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_MALE: \"{0}{NEWLINE}因傷重致死\"\n  STR_HAS_DIED_FROM_A_FATAL_WOUND_FEMALE: \"{0}{NEWLINE}因傷重致死\"\n  STR_USE_MIND_PROBE: \"使用M.C.雷達\"\n  STR_FATAL_WOUNDS: \"重傷\"\n  STR_UNDER_ARMOR_UC: \"下護甲\"\n  STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT: \"保留給速射的TU\"\n  STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT: \"保留給自動射擊的TU\"\n  STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT: \"保留給精密射擊的TU\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING: \"保留給跪姿的TU\"\n  STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING: \"保留給跪姿開火的TU\"\n  STR_UNITS_IN_CRAFT:\n    other: \"{N}名單位在X-Com載具\"\n  STR_UNITS_OUTSIDE:\n    other: \"{N}名單位在戶外\"\n  STR_UNITS_IN_ENTRANCE:\n    other: \"{N}名單位在入口\"\n  STR_UNITS_IN_EXIT:\n    other: \"{N}名單位在目標出口\"\n  STR_ABORT_MISSION_QUESTION: \"放棄任務?\"\n  STR_CORPSE: \"屍體\"\n  STR_UNLOAD_CRAFT: \"卸載\"\n  STR_HAS_BEEN_KILLED_MALE: \"{0}{NEWLINE}已被擊殺\"\n  STR_HAS_BEEN_KILLED_FEMALE: \"{0}{NEWLINE}已被擊殺\"\n  STR_HIT_MELEE: \"打擊\"\n  STR_GROUND: \"落地\"\n  STR_LIVING_QUARTERS_PLURAL: \"起居室\"\n  STR_LIST_ITEM: \"道具\"\n  STR_ALL_ALIENS_KILLED_IN_CRASH: \"所有的異形均因潛艇遭毀而死。{NEWLINE}初始化自動回復\"\n  STR_RESET: \"重置\"\n  STR_MEMORIAL: \"緬念\"\n  STR_DATE_UC: \"日期\"\n  STR_SOLDIERS_RECRUITED_UC: \"已招募的潛水夫>{ALT}{0}\"\n  STR_SOLDIERS_LOST_UC: \"已失蹤的潛水夫>{ALT}{0}\"\n  STR_REMOVE_SELECTED: \"移除已選擇\"\n  STR_LIVE_ALIENS: \"活體{NEWLINE}樣本\"\n  STR_DEAD_ALIENS: \"被拒絕的{NEWLINE}樣本\"\n  STR_UNDER_INTERROGATION: \"已被{NEWLINE}研讀\"\n  STR_CONTAINMENT_EXCEEDED: \"異形容器超載{SMALLLINE}在{0}的容器空間不足。您必須從容器中移除多餘的異形(然後它們會死掉)。\"\n  STR_MANAGE_CONTAINMENT: \"管理異形容器\"\n  STR_STORAGE_EXCEEDED: \"儲存空間超載{SMALLLINE}在{0}的儲存空間不足。您必須賣掉多餘的物品。\"\n  STR_GO_TO_BASE: \"移動至基地\"\n  STR_MELEE_ACCURACY: \"肉搏命中率\"\n  STR_SELL_PRODUCTION: \"販售\"\n  STR_BOTH_HANDS_MUST_BE_EMPTY: \"雙手不得持物!\"\n  STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE: \"物品不足以複製範本!\"\n  STR_UNLOAD_WEAPON: \"卸載武器\"\n  STR_ALL_ITEMS: \"所有道具\"\n  STR_NO_MORE_EQUIPMENT_ALLOWED:\n    other: \"無法再乘載更多裝備{SMALLLINE}您最多只能在此潛艇裝承仔最多{N}件物品。\"\n  STR_CONTROL_CENTER_DESTROYED: \"{SMALLLINE}控制中心被摧毀{NEWLINE}請移動至入口並離開。\"\n  STR_XCOM_BASE_CANNOT_BE_BUILT: \"X-Com水中設施無法在地面上建築\"\n  STR_UNABLE_TO_ENGAGE_DEPTH: \"在此深度{NEWLINE}無法與敵接近戰\"\n  STR_UNABLE_TO_ENGAGE_AIRBORNE: \"在空中{NEWLINE}無法與敵接近戰\"\n  STR_UNDERWATER_EQUIPMENT: \"此設備無法離水使用!\"\n  STR_LEVEL_SHORT: \"L{0}\"\n  STR_PERSONNEL: \"人員\"\n  STR_CRAFT_ARMAMENT: \"載具和火力\"\n  STR_COMPONENTS: \"元件\"\n  STR_SOLDIERS_RECRUITED: \"已招募潛水伕\"\n  STR_SOLDIERS_LOST: \"已失蹤潛水伕\"\n  STR_TOTAL_UFOS: \"已偵測飛空潛艇\"\n  STR_TOTAL_ALIEN_BASES: \"已發現異形殖民地\"\n  FEMALE_CIVILIAN: \"城市居民, 女性\"\n  MALE_CIVILIAN: \"城市居民, 男性\"\n  ZOMBIE_WEAPON: \"殭屍武器\"\n"
  },
  {
    "path": "bin/standard/xcom2/Resources/Extended/Touch/license.txt",
    "content": "Artwork (c) Riccardo Gasperi\n\nThis artwork is licensed under a\nCreative Commons Attribution-ShareAlike 4.0 International License.\n\nYou should have received a copy of the license along with this\nwork.  If not, see <http://creativecommons.org/licenses/by-sa/4.0/>."
  },
  {
    "path": "bin/standard/xcom2/Resources/Weapons/license.txt",
    "content": "Artwork (c) Riccardo Gasperi\n\nThis artwork is licensed under a\nCreative Commons Attribution-ShareAlike 4.0 International License.\n\nYou should have received a copy of the license along with this\nwork.  If not, see <http://creativecommons.org/licenses/by-sa/4.0/>."
  },
  {
    "path": "bin/standard/xcom2/alienDeployments.rul",
    "content": "alienDeployments: #done\n  - type: STR_CRAFT_DEPLOYMENT_PREVIEW\n    isHidden: true\n    width: 10\n    length: 10\n    height: 8\n    terrains:\n      - SEABED\n    script: STR_CRAFT_DEPLOYMENT_PREVIEW\n  - type: STR_SURVEY_SHIP\n    data:\n      - alienRank: 5\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n    width: 50\n    length: 50\n    height: 4\n    briefing:\n      palette: 4\n      music: GMISPOSH\n  - type: STR_ESCORT\n    data:\n      - alienRank: 5\n        lowQty: 2\n        highQty: 4\n        dQty: 2\n        percentageOutsideUfo: 60\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n      - alienRank: 4\n        lowQty: 1\n        highQty: 2\n        dQty: 1\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n    width: 50\n    length: 50\n    height: 4\n    briefing:\n      palette: 4\n      music: GMISPOSH\n  - type: STR_CRUISER\n    data:\n      - alienRank: 5\n        lowQty: 1\n        highQty: 3\n        dQty: 5\n        percentageOutsideUfo: 65\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n      - alienRank: 4\n        lowQty: 1\n        highQty: 1\n        dQty: 1\n        percentageOutsideUfo: 25\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n      - alienRank: 2\n        lowQty: 1\n        highQty: 2\n        dQty: 1\n        percentageOutsideUfo: 35\n        itemSets:\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_VIBRO_BLADE\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n    width: 60\n    length: 60\n    height: 4\n    briefing:\n      palette: 4\n      music: GMISPOSH\n  - type: STR_HEAVY_CRUISER\n    data:\n      - alienRank: 5\n        lowQty: 5\n        highQty: 9\n        dQty: 4\n        percentageOutsideUfo: 70\n        itemSets:\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n      - alienRank: 4\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n      - alienRank: 3\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_SONIC_PULSER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_SONIC_PULSER\n          -\n            - STR_DISRUPTOR_PULSE_LAUNCHER\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n            - STR_SONIC_PULSER\n      - alienRank: 2\n        lowQty: 2\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 30\n        itemSets:\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n          -\n            - STR_DISRUPTOR_PULSE_LAUNCHER\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n          -\n            - STR_THERMIC_LANCE\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n      - alienRank: 1\n        lowQty: 1\n        highQty: 1\n        dQty: 1\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n          -\n            - STR_DISRUPTOR_PULSE_LAUNCHER\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n            - STR_SONIC_PULSER\n    width: 60\n    length: 60\n    height: 4\n    briefing:\n      palette: 4\n      music: GMISPOSH\n  - type: STR_HUNTER\n    data:\n      - alienRank: 5\n        lowQty: 3\n        highQty: 5\n        dQty: 4\n        percentageOutsideUfo: 70\n        itemSets:\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_SONIC_PULSER\n          -\n            - STR_DISRUPTOR_PULSE_LAUNCHER\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n            - STR_SONIC_PULSER\n      - alienRank: 4\n        lowQty: 1\n        highQty: 1\n        dQty: 1\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n          -\n            - STR_DISRUPTOR_PULSE_LAUNCHER\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n            - STR_SONIC_PULSER\n      - alienRank: 3\n        lowQty: 2\n        highQty: 4\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n      - alienRank: 2\n        lowQty: 2\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 30\n        itemSets:\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n          -\n            - STR_HEAVY_THERMIC_LANCE\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n      - alienRank: 1\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n          -\n            - STR_DISRUPTOR_PULSE_LAUNCHER\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n    width: 60\n    length: 60\n    height: 4\n    briefing:\n      palette: 4\n      music: GMISPOSH\n  - type: STR_BATTLESHIP\n    data:\n      - alienRank: 5\n        lowQty: 4\n        highQty: 6\n        dQty: 1\n        percentageOutsideUfo: 70\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n      - alienRank: 4\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_MC_READER\n      - alienRank: 3\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_MC_READER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_SONIC_PULSER\n      - alienRank: 2\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_THERMIC_LANCE\n          -\n            - STR_HEAVY_THERMIC_LANCE\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n      - alienRank: 1\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 6\n        lowQty: 1\n        highQty: 3\n        dQty: 2\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 7\n        lowQty: 1\n        highQty: 3\n        dQty: 2\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n    width: 60\n    length: 60\n    height: 4\n    briefing:\n      palette: 4\n      music: GMISPOSH\n  - type: STR_DREADNOUGHT\n    data:\n      - alienRank: 5\n        lowQty: 4\n        highQty: 8\n        dQty: 4\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n      - alienRank: 4\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n      - alienRank: 3\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n          -\n            - STR_DISRUPTOR_PULSE_LAUNCHER\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n      - alienRank: 2\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_THERMIC_LANCE\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n          -\n            - STR_HEAVY_THERMIC_LANCE\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n      - alienRank: 1\n        lowQty: 1\n        highQty: 3\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_CANNON_POWER_CLIP\n          -\n            - STR_DISRUPTOR_PULSE_LAUNCHER\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n      - alienRank: 0\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n      - alienRank: 6\n        lowQty: 0\n        highQty: 2\n        dQty: 1\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 7\n        lowQty: 0\n        highQty: 2\n        dQty: 1\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n    width: 60\n    length: 60\n    height: 4\n    briefing:\n      palette: 4\n      music: GMISPOSH\n  - type: STR_FLEET_SUPPLY_CRUISER\n    data:\n      - alienRank: 5\n        lowQty: 5\n        highQty: 7\n        dQty: 6\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n      - alienRank: 4\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_CANNON_POWER_CLIP\n      - alienRank: 3\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_SONIC_PULSER\n      - alienRank: 2\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n          -\n            - STR_THERMIC_LANCE\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n          -\n            - STR_DISRUPTOR_PULSE_LAUNCHER\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n      - alienRank: 1\n        lowQty: 1\n        highQty: 1\n        dQty: 1\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_HEAVY_THERMIC_LANCE\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n    width: 60\n    length: 60\n    height: 4\n    briefing:\n      palette: 4\n      music: GMISPOSH\n  - type: STR_PORT_TERROR\n    data:\n      - alienRank: 5\n        lowQty: 4\n        highQty: 6\n        dQty: 1\n        percentageOutsideUfo: 70\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n      - alienRank: 4\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_MC_READER\n      - alienRank: 3\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_MC_READER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_SONIC_PULSER\n      - alienRank: 2\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_THERMIC_LANCE\n          -\n            - STR_HEAVY_THERMIC_LANCE\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n      - alienRank: 1\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 6\n        lowQty: 1\n        highQty: 3\n        dQty: 2\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 7\n        lowQty: 1\n        highQty: 3\n        dQty: 2\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n    width: 50\n    length: 50\n    height: 4\n    civilians: 16\n    terrains:\n      - PORT\n    script: PORT_TERROR\n    briefing:\n      palette: 4\n      music: GMISPOSH\n    alert: STR_ALIENS_LAUNCH_PORT_TERROR\n    alertBackground: BACK03.SCR\n    markerName: STR_TERROR_SITE\n    duration: [4, 10]\n    despawnPenalty: 1000\n  - type: STR_ISLAND_TERROR\n    data:\n      - alienRank: 5\n        lowQty: 4\n        highQty: 6\n        dQty: 1\n        percentageOutsideUfo: 70\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n      - alienRank: 4\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_MC_READER\n      - alienRank: 3\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_MC_READER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_SONIC_PULSER\n      - alienRank: 2\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_THERMIC_LANCE\n          -\n            - STR_HEAVY_THERMIC_LANCE\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n      - alienRank: 1\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 6\n        lowQty: 1\n        highQty: 3\n        dQty: 2\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 7\n        lowQty: 1\n        highQty: 3\n        dQty: 2\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n    width: 50\n    length: 50\n    height: 4\n    civilians: 16\n    terrains:\n      - ISLAND\n    script: ISLAND_TERROR\n    briefing:\n      palette: 4\n      music: GMISPOSH\n    alert: STR_ALIENS_LAUNCH_ISLAND_TERROR\n    alertBackground: BACK03.SCR\n    markerName: STR_TERROR_SITE\n    duration: [4, 10]\n    despawnPenalty: 1000\n  - type: STR_CARGO_SHIP_P1\n    data:\n      - alienRank: 5\n        lowQty: 4\n        highQty: 6\n        dQty: 1\n        percentageOutsideUfo: 70\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n      - alienRank: 4\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_MC_READER\n      - alienRank: 3\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_MC_READER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_SONIC_PULSER\n      - alienRank: 2\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_VIBRO_BLADE\n          -\n            - STR_THERMIC_LANCE\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n      - alienRank: 1\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 6\n        lowQty: 1\n        highQty: 3\n        dQty: 2\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 7\n        lowQty: 1\n        highQty: 3\n        dQty: 2\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n    width: 30\n    length: 70\n    height: 4\n    civilians: 16\n    script: SHIP_P1\n    terrains:\n      - CARGO\n    nextStage: STR_CARGO_SHIP_P2\n    briefing:\n      title: STR_SHIP_RESCUE_MISSION\n      desc: STR_SHIP_RESCUE_P1_BRIEFING\n      palette: 4\n      music: GMISPOSH\n    alert: STR_ALIENS_ATTACK_SHIPPING_ROUTE\n    alertBackground: BACK03.SCR\n    markerName: STR_TERROR_SITE\n    duration: [4, 10]\n    despawnPenalty: 1000\n  - type: STR_CARGO_SHIP_P2\n    data:\n      - alienRank: 5\n        lowQty: 4\n        highQty: 6\n        dQty: 1\n        percentageOutsideUfo: 70\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n      - alienRank: 4\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_MC_READER\n      - alienRank: 3\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_MC_READER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_SONIC_PULSER\n      - alienRank: 2\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_VIBRO_BLADE\n          -\n            - STR_THERMIC_LANCE\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n      - alienRank: 1\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 6\n        lowQty: 1\n        highQty: 3\n        dQty: 2\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 7\n        lowQty: 1\n        highQty: 3\n        dQty: 2\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n    width: 30\n    length: 70\n    height: 4\n    civilians: 16\n    script: SHIP_P2\n    terrains:\n      - CARGO\n    shade: 0\n    briefing:\n      title: STR_SHIP_RESCUE_MISSION\n      desc: STR_SHIP_RESCUE_P2_BRIEFING\n      palette: 4\n      music: GMISPOSH\n      background: BACK01.SCR\n    markerName: STR_TERROR_SITE\n  - type: STR_CRUISE_SHIP_P1\n    data:\n      - alienRank: 5\n        lowQty: 4\n        highQty: 6\n        dQty: 1\n        percentageOutsideUfo: 70\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n      - alienRank: 4\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_MC_READER\n      - alienRank: 3\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_MC_READER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_SONIC_PULSER\n      - alienRank: 2\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_THERMIC_LANCE\n          -\n            - STR_HEAVY_THERMIC_LANCE\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n      - alienRank: 1\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 6\n        lowQty: 1\n        highQty: 3\n        dQty: 2\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 7\n        lowQty: 1\n        highQty: 3\n        dQty: 2\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n    width: 30\n    length: 70\n    height: 4\n    civilians: 16\n    script: SHIP_P1\n    terrains:\n      - LINERT\n    nextStage: STR_CRUISE_SHIP_P2\n    briefing:\n      title: STR_SHIP_RESCUE_MISSION\n      desc: STR_SHIP_RESCUE_P1_BRIEFING\n      palette: 4\n      music: GMISPOSH\n    alert: STR_ALIENS_ATTACK_SHIPPING_ROUTE\n    alertBackground: BACK03.SCR\n    markerName: STR_TERROR_SITE\n    duration: [4, 10]\n    despawnPenalty: 1000\n  - type: STR_CRUISE_SHIP_P2\n    data:\n      - alienRank: 5\n        lowQty: 4\n        highQty: 6\n        dQty: 1\n        percentageOutsideUfo: 70\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n      - alienRank: 4\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_MC_READER\n      - alienRank: 3\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_MC_READER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_SONIC_PULSER\n      - alienRank: 2\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_VIBRO_BLADE\n          -\n            - STR_THERMIC_LANCE\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n      - alienRank: 1\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 6\n        lowQty: 1\n        highQty: 3\n        dQty: 2\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 7\n        lowQty: 1\n        highQty: 3\n        dQty: 2\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n    width: 30\n    length: 70\n    height: 4\n    civilians: 16\n    script: SHIP_P2\n    terrains:\n      - LINERB\n    shade: 0\n    briefing:\n      title: STR_SHIP_RESCUE_MISSION\n      desc: STR_SHIP_RESCUE_P2_BRIEFING\n      palette: 4\n      music: GMISPOSH\n      background: BACK01.SCR\n    markerName: STR_TERROR_SITE\n  - type: STR_ARTIFACT_SITE_P1\n    data:\n      - alienRank: 5\n        lowQty: 4\n        highQty: 6\n        dQty: 1\n        extraQty: 2\n        percentageOutsideUfo: 70\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n      - alienRank: 4\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        extraQty: 2\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_MC_READER\n      - alienRank: 3\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        extraQty: 2\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_MC_READER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_SONIC_PULSER\n      - alienRank: 2\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        extraQty: 2\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_THERMIC_LANCE\n          -\n            - STR_HEAVY_THERMIC_LANCE\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n      - alienRank: 1\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        extraQty: 2\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 6\n        lowQty: 1\n        highQty: 3\n        dQty: 2\n        extraQty: 2\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 7\n        lowQty: 1\n        highQty: 3\n        dQty: 2\n        extraQty: 2\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n    width: 50\n    length: 50\n    height: 4\n    terrains:\n      - ALART\n    script: ARTIFACT_P1\n    nextStage: STR_ARTIFACT_SITE_P2\n    briefing:\n      title: STR_ALIEN_CONTACT_SITE_MISSION\n      palette: 4\n      music: GMATTBAS\n    alert: STR_ALIEN_ACTIVITY_DETECTED\n    alertBackground: BACK03.SCR\n    markerName: STR_ARTIFACT_SITE\n    duration: [4, 10]\n    despawnPenalty: 2000\n    objectiveFailed: [STR_ALIEN_SYNOMIUM_DEVICE_FAILED, -750]\n  - type: STR_ARTIFACT_SITE_P2\n    data:\n      - alienRank: 5\n        lowQty: 4\n        highQty: 6\n        dQty: 1\n        extraQty: 2\n        percentageOutsideUfo: 70\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n      - alienRank: 4\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        extraQty: 2\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_MC_READER\n      - alienRank: 3\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        extraQty: 2\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_MC_READER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_SONIC_PULSER\n      - alienRank: 2\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        extraQty: 2\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_THERMIC_LANCE\n          -\n            - STR_HEAVY_THERMIC_LANCE\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n      - alienRank: 1\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        extraQty: 2\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 6\n        lowQty: 1\n        highQty: 3\n        dQty: 2\n        extraQty: 2\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 7\n        lowQty: 1\n        highQty: 3\n        dQty: 2\n        extraQty: 2\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n    width: 40\n    length: 40\n    height: 4\n    terrains:\n      - GRUNGE\n    shade: 15\n    depth: [3, 3]\n    script: ARTIFACT_P2\n    briefing:\n      title: STR_ALIEN_CONTACT_SITE_MISSION\n      palette: 4\n      music: GMATTBAS\n      background: BACK01.SCR\n    markerName: STR_ARTIFACT_SITE\n    objectiveType: 3\n    objectivesRequired: 1\n    objectiveComplete: [STR_ALIEN_SYNOMIUM_DEVICE_DESTROYED, 750]\n    objectiveFailed: [STR_ALIEN_SYNOMIUM_DEVICE_FAILED, -750]\n    objectivePopup: STR_CONTROL_CENTER_DESTROYED\n  - type: STR_ALIEN_BASE_ASSAULT\n    data:\n      - alienRank: 6\n        lowQty: 2\n        highQty: 4\n        dQty: 1\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 7\n        lowQty: 1\n        highQty: 3\n        dQty: 1\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 5\n        lowQty: 7\n        highQty: 9\n        dQty: 5\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_DISRUPTOR_PULSE_LAUNCHER\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n      - alienRank: 4\n        lowQty: 3\n        highQty: 4\n        dQty: 2\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_HEAVY_THERMIC_LANCE\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_MC_READER\n      - alienRank: 3\n        lowQty: 2\n        highQty: 2\n        dQty: 1\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n          -\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_MC_READER\n          -\n            - STR_DISRUPTOR_PULSE_LAUNCHER\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n            - STR_MC_READER\n      - alienRank: 2\n        lowQty: 2\n        highQty: 3\n        dQty: 1\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_DISRUPTOR_PULSE_LAUNCHER\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n      - alienRank: 1\n        lowQty: 2\n        highQty: 4\n        dQty: 1\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n          -\n            - STR_DISRUPTOR_PULSE_LAUNCHER\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n      - alienRank: 0\n        lowQty: 1\n        highQty: 2\n        dQty: 1\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n    width: 60\n    length: 60\n    height: 4\n    terrains:\n      - ENTRY\n    shade: 15\n    depth: [3, 3]\n    race: STR_MIXED_CREW\n    markerName: STR_ALIEN_BASE\n    markerIcon: 7\n    genMission:\n      STR_ALIEN_SUPPLY: 100\n    genMissionFreq: 6\n    script: ALIEN_COLONY_P1\n    alienBase: true    # this is only to tell new battle mode what to do with this deployment\n    nextStage: STR_ALIEN_COLONY_P2\n    briefing:\n      title: STR_ALIEN_COLONY_ATTACK_MISSION\n      desc: STR_ALIEN_COLONY_P1_BRIEFING\n      palette: 4\n      music: GMATTBAS\n      background: BACK01.SCR\n    points: 5\n  - type: STR_ALIEN_COLONY_P2\n    data:\n      - alienRank: 6\n        lowQty: 2\n        highQty: 4\n        dQty: 1\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 7\n        lowQty: 1\n        highQty: 3\n        dQty: 1\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 5\n        lowQty: 7\n        highQty: 9\n        dQty: 5\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_DISRUPTOR_PULSE_LAUNCHER\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n      - alienRank: 4\n        lowQty: 3\n        highQty: 4\n        dQty: 2\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_THERMIC_LANCE\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_MC_READER\n      - alienRank: 3\n        lowQty: 2\n        highQty: 2\n        dQty: 1\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n          -\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_MC_READER\n          -\n            - STR_DISRUPTOR_PULSE_LAUNCHER\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n            - STR_MC_READER\n      - alienRank: 2\n        lowQty: 2\n        highQty: 3\n        dQty: 1\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_DISRUPTOR_PULSE_LAUNCHER\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n      - alienRank: 1\n        lowQty: 2\n        highQty: 4\n        dQty: 1\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n          -\n            - STR_DISRUPTOR_PULSE_LAUNCHER\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n      - alienRank: 0\n        lowQty: 1\n        highQty: 2\n        dQty: 1\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n    width: 60\n    length: 60\n    height: 4\n    shade: 0\n    depth: [3, 3]\n    terrains:\n      - A_BASE\n    race: STR_LOBSTERMAN\n    markerName: STR_ALIEN_BASE\n    script: ALIEN_COLONY_P2\n    briefing:\n      title: STR_ALIEN_COLONY_ATTACK_MISSION\n      palette: 4\n      music: GMATTBAS\n      background: BACK01.SCR\n    objectiveType: 3\n    alienBase: true    # this is only to tell new battle mode what to do with this deployment\n    objectiveComplete: [STR_ALIEN_BASE_CONTROL_DESTROYED, 500]\n    objectivePopup: STR_CONTROL_CENTER_DESTROYED\n  - type: STR_BASE_DEFENSE # use of this name is hard coded. this is because of REASONS.\n    data:\n      - alienRank: 5\n        lowQty: 4\n        highQty: 8\n        dQty: 4\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n      - alienRank: 4\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_PISTOL\n            - STR_PISTOL_POWER_CLIP\n            - STR_PISTOL_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n      - alienRank: 3\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n          -\n            - STR_DISRUPTOR_PULSE_LAUNCHER\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n      - alienRank: 2\n        lowQty: 1\n        highQty: 2\n        dQty: 0\n        percentageOutsideUfo: 20\n        itemSets:\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_VIBRO_BLADE\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n          -\n            - STR_THERMIC_LANCE\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n      - alienRank: 1\n        lowQty: 1\n        highQty: 3\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_CANNON_POWER_CLIP\n          -\n            - STR_DISRUPTOR_PULSE_LAUNCHER\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n      - alienRank: 0\n        lowQty: 1\n        highQty: 1\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n      - alienRank: 6\n        lowQty: 0\n        highQty: 2\n        dQty: 1\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 7\n        lowQty: 0\n        highQty: 2\n        dQty: 1\n        percentageOutsideUfo: 50\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n    width: 60\n    length: 60\n    height: 4\n    terrains:\n      - XBASES\n    shade: 8\n    script: BASE_DRILL\n    briefing:\n      palette: 4\n      music: GMDEFBAS\n      background: BACK01.SCR\n  - type: STR_TLETH_P1\n    data:\n      - alienRank: 5\n        lowQty: 4\n        highQty: 6\n        dQty: 0\n        percentageOutsideUfo: 60\n        itemSets:\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n          -\n            - STR_DISRUPTOR_PULSE_LAUNCHER\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n      - alienRank: 1\n        lowQty: 3\n        highQty: 5\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n          -\n            - STR_DISRUPTOR_PULSE_LAUNCHER\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n      - alienRank: 0\n        lowQty: 3\n        highQty: 5\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n          -\n            - STR_DISRUPTOR_PULSE_LAUNCHER\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n      - alienRank: 6\n        lowQty: 2\n        highQty: 4\n        dQty: 0\n        percentageOutsideUfo: 100\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n    width: 60\n    length: 60\n    height: 2\n    terrains:\n      - ALSHIP\n    shade: 15\n    depth: [3, 3]\n    race: STR_AQUATOID\n    nextStage: STR_TLETH_P2\n    finalDestination: true\n    script: TLETH_P1\n    loseCutscene: loseGame\n    abortCutscene: loseGame\n    briefing:\n      title: STR_SIGSBEE_DEEP_MISSION\n      desc: STR_TLETH_P1_BRIEFING\n      palette: 5\n      music: GMBIGMAR\n      background: BACK05.SCR\n      showTarget: false\n      cutscene: tleth\n  - type: STR_TLETH_P2\n    data:\n      - alienRank: 0\n        lowQty: 2\n        highQty: 4\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 1\n        lowQty: 1\n        highQty: 3\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 7\n        lowQty: 3\n        highQty: 5\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 3\n        lowQty: 3\n        highQty: 5\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n      - alienRank: 4\n        lowQty: 3\n        highQty: 5\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n      - alienRank: 5\n        lowQty: 3\n        highQty: 5\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n          -\n            - STR_DISRUPTOR_PULSE_LAUNCHER\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n      - alienRank: 6\n        lowQty: 1\n        highQty: 4\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n    width: 60\n    length: 60\n    height: 2\n    terrains:\n      - LEVEL\n    shade: 15\n    depth: [3, 3]\n    race: STR_MIXED_CREW_2\n    nextStage: STR_TLETH_P3\n    script: TLETH_P2_P3\n    loseCutscene: loseGame\n    abortCutscene: loseGame\n    briefing:\n      title: STR_TLETH_ATTACK_MISSION\n      desc: STR_TLETH_P2_BRIEFING\n      palette: 4\n      music: GMBIGMAR\n      background: BACK01.SCR\n      showTarget: false\n      showCraft: false\n  - type: STR_TLETH_P3\n    data:\n      - alienRank: 0\n        lowQty: 2\n        highQty: 4\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 1\n        lowQty: 1\n        highQty: 3\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 7\n        lowQty: 3\n        highQty: 5\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n      - alienRank: 3\n        lowQty: 3\n        highQty: 5\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n      - alienRank: 4\n        lowQty: 3\n        highQty: 5\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n          -\n            - STR_THERMAL_SHOK_LAUNCHER\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n            - STR_THERMAL_SHOK_BOMB\n      - alienRank: 5\n        lowQty: 3\n        highQty: 5\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            - STR_SONIC_BLASTA_RIFLE\n            - STR_BLASTA_POWER_CLIP\n            - STR_BLASTA_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n          -\n            - STR_SONIC_CANNON\n            - STR_CANNON_POWER_CLIP\n            - STR_CANNON_POWER_CLIP\n            - STR_SONIC_PULSER\n            - STR_SONIC_PULSER\n          -\n            - STR_DISRUPTOR_PULSE_LAUNCHER\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n            - STR_DISRUPTOR_AMMO\n      - alienRank: 6\n        lowQty: 1\n        highQty: 4\n        dQty: 0\n        percentageOutsideUfo: 0\n        itemSets:\n          -\n            []\n          -\n            []\n          -\n            []\n    width: 60\n    length: 60\n    height: 2\n    terrains:\n      - CRYPT\n    shade: 15\n    depth: [3, 3]\n    race: STR_MIXED_CREW_2\n    script: TLETH_P2_P3\n    winCutscene: winGame\n    loseCutscene: loseGame\n    abortCutscene: loseGame\n    briefing:\n      title: STR_FINAL_TLETH_MISSION\n      desc: STR_TLETH_P3_BRIEFING\n      palette: 4\n      music: GMBIGMAR\n      background: BACK01.SCR\n      showTarget: false\n      showCraft: false\n    objectiveType: 14\n    objectivesRequired: 8\n"
  },
  {
    "path": "bin/standard/xcom2/alienItemLevels.rul",
    "content": "alienItemLevels: #done\n  - [0, 0, 0, 0, 0, 0, 0, 1, 1, 2]\n  - [0, 0, 0, 0, 0, 1, 1, 1, 2, 2]\n  - [0, 0, 0, 1, 1, 1, 1, 2, 2, 2]\n  - [0, 0, 1, 1, 1, 1, 2, 2, 2, 2]\n  - [0, 0, 1, 1, 1, 2, 2, 2, 2, 2]\n  - [0, 1, 1, 1, 2, 2, 2, 2, 2, 2]\n  - [1, 1, 1, 2, 2, 2, 2, 2, 2, 2]\n  - [1, 1, 1, 2, 2, 2, 2, 2, 2, 2]\n  - [1, 1, 2, 2, 2, 2, 2, 2, 2, 2]\n  - [2, 2, 2, 2, 2, 2, 2, 2, 2, 2]\n"
  },
  {
    "path": "bin/standard/xcom2/alienMissions.rul",
    "content": "alienMissions: #done\n  - type: STR_ALIEN_PROBE_MISSION\n    points: 0\n    raceWeights:\n      0:\n          STR_AQUATOID: 70\n          STR_GILLMAN: 30\n      1:\n          STR_AQUATOID: 60\n          STR_GILLMAN: 30\n          STR_LOBSTERMAN: 10\n      3:\n          STR_AQUATOID: 30\n          STR_GILLMAN: 40\n          STR_LOBSTERMAN: 30\n      6:\n          STR_AQUATOID: 20\n          STR_GILLMAN: 10\n          STR_LOBSTERMAN: 40\n          STR_TASOTH: 30\n      9:\n          STR_AQUATOID: 20\n          STR_GILLMAN: 20\n          STR_LOBSTERMAN: 20\n          STR_TASOTH: 40\n    waves:\n      - ufo: STR_SURVEY_SHIP\n        count: 1\n        trajectory: P0\n        timer: 9000\n      - ufo: STR_ESCORT\n        count: 1\n        trajectory: P2\n        timer: 7800\n      - ufo: STR_CRUISER\n        count: 2\n        trajectory: P4\n        timer: 9000\n  - type: STR_ALIEN_INTERDICTION\n    points: 30\n    raceWeights:\n      0:\n          STR_AQUATOID: 50\n          STR_GILLMAN: 50\n      1:\n          STR_AQUATOID: 50\n          STR_GILLMAN: 50\n      3:\n          STR_AQUATOID: 30\n          STR_GILLMAN: 50\n          STR_LOBSTERMAN: 20\n      6:\n          STR_AQUATOID: 10\n          STR_LOBSTERMAN: 40\n          STR_TASOTH: 50\n      9:\n          STR_AQUATOID: 30\n          STR_LOBSTERMAN: 30\n          STR_TASOTH: 40\n    waves:\n      - ufo: STR_SURVEY_SHIP\n        count: 1\n        trajectory: P0\n        timer: 7800\n      - ufo: STR_SURVEY_SHIP\n        count: 1\n        trajectory: P2\n        timer: 7800\n      - ufo: STR_ESCORT\n        count: 1\n        trajectory: P2\n        timer: 6000\n      - ufo: STR_CRUISER\n        count: 1\n        trajectory: P0\n        timer: 7800\n      - ufo: STR_CRUISER\n        count: 1\n        trajectory: P3\n        timer: 9000\n      - ufo: STR_HUNTER\n        count: 1\n        trajectory: P4\n        timer: 3000\n      - ufo: STR_HUNTER\n        count: 1\n        trajectory: P4\n        timer: 750\n      - ufo: STR_DREADNOUGHT\n        count: 1\n        trajectory: P2\n        timer: 1500\n  - type: STR_ALIEN_RESOURCE_RAID\n    points: 50\n    raceWeights:\n      0:\n          STR_AQUATOID: 60\n          STR_GILLMAN: 40\n      1:\n          STR_AQUATOID: 40\n          STR_GILLMAN: 60\n      3:\n          STR_AQUATOID: 50\n          STR_GILLMAN: 50\n      6:\n          STR_AQUATOID: 30\n          STR_TASOTH: 70\n      9:\n          STR_AQUATOID: 50\n          STR_TASOTH: 50\n    waves:\n      - ufo: STR_SURVEY_SHIP\n        count: 1\n        trajectory: P0\n        timer: 15000\n      - ufo: STR_ESCORT\n        count: 1\n        trajectory: P1\n        timer: 18000\n      - ufo: STR_CRUISER\n        count: 1\n        trajectory: P3\n        timer: 9000\n      - ufo: STR_HEAVY_CRUISER\n        count: 1\n        trajectory: P3\n        timer: 9000\n      - ufo: STR_HEAVY_CRUISER\n        count: 2\n        trajectory: P4\n        timer: 60\n  - type: STR_ALIEN_INFILTRATION\n    points: 150 #Pact score only awarded on month end\n    objective: 1\n    siteType: STR_ALIEN_BASE_ASSAULT\n    spawnZone: 4 #Mission zone for alien bases\n    raceWeights:\n      0:\n          STR_AQUATOID: 60\n          STR_GILLMAN: 40\n      1:\n          STR_AQUATOID: 50\n          STR_GILLMAN: 30\n          STR_LOBSTERMAN: 20\n      3:\n          STR_AQUATOID: 20\n          STR_GILLMAN: 50\n          STR_LOBSTERMAN: 30\n      6:\n          STR_AQUATOID: 10\n          STR_GILLMAN: 30\n          STR_LOBSTERMAN: 20\n          STR_TASOTH: 40\n      9:\n          STR_AQUATOID: 30\n          STR_GILLMAN: 10\n          STR_LOBSTERMAN: 50\n          STR_TASOTH: 10\n    waves:\n      - ufo: STR_SURVEY_SHIP\n        count: 1\n        trajectory: P0\n        timer: 16500\n      - ufo: STR_ESCORT\n        count: 1\n        trajectory: P1\n        timer: 15000\n      - ufo: STR_ESCORT\n        count: 1\n        trajectory: P6\n        timer: 13800\n      - ufo: STR_CRUISER\n        count: 1\n        trajectory: P7\n        timer: 9000\n      - ufo: STR_CRUISER\n        count: 1\n        trajectory: P7\n        timer: 60\n      - ufo: STR_BATTLESHIP\n        count: 1\n        trajectory: P7\n        timer: 60\n      - ufo: STR_FLEET_SUPPLY_CRUISER\n        count: 1\n        trajectory: P7\n        timer: 60\n      - ufo: STR_DREADNOUGHT\n        count: 2\n        trajectory: P7\n        timer: 60\n  - type: STR_ALIEN_BASE\n    points: 50\n    objective: 2\n    siteType: STR_ALIEN_BASE_ASSAULT\n    spawnZone: 4 #Mission zone for alien bases\n    raceWeights:\n      0:\n          STR_AQUATOID: 30\n          STR_GILLMAN: 70\n      1:\n          STR_AQUATOID: 40\n          STR_GILLMAN: 40\n          STR_LOBSTERMAN: 20\n      3:\n          STR_AQUATOID: 10\n          STR_GILLMAN: 30\n          STR_LOBSTERMAN: 60\n      6:\n          STR_AQUATOID: 10\n          STR_GILLMAN: 40\n          STR_LOBSTERMAN: 30\n          STR_TASOTH: 20\n      9:\n          STR_AQUATOID: 10\n          STR_GILLMAN: 20\n          STR_LOBSTERMAN: 60\n          STR_TASOTH: 10\n    waves:\n      - ufo: STR_SURVEY_SHIP\n        count: 1\n        trajectory: P1\n        timer: 13500\n      - ufo: STR_ESCORT\n        count: 1\n        trajectory: P5\n        timer: 15000\n      - ufo: STR_CRUISER\n        count: 1\n        trajectory: P5\n        timer: 60\n      - ufo: STR_FLEET_SUPPLY_CRUISER\n        count: 2\n        trajectory: P5\n        timer: 60\n      - ufo: STR_DREADNOUGHT\n        count: 1\n        trajectory: P6\n        timer: 60\n  - type: STR_ALIEN_SURFACE_ATTACK\n    points: 10\n    objective: 3\n    spawnZone: 3 #Mission zone for terror missions\n    raceWeights:\n      0:\n          STR_GILLMAN: 100\n      1:\n          STR_AQUATOID: 20\n          STR_GILLMAN: 80\n      3:\n          STR_AQUATOID: 20\n          STR_GILLMAN: 30\n          STR_LOBSTERMAN: 50\n      6:\n          STR_AQUATOID: 10\n          STR_GILLMAN: 30\n          STR_LOBSTERMAN: 20\n          STR_TASOTH: 20\n          STR_MIXED_CREW: 20\n      9:\n          STR_AQUATOID: 20\n          STR_GILLMAN: 20\n          STR_LOBSTERMAN: 20\n          STR_TASOTH: 10\n          STR_MIXED_CREW: 30\n    waves:\n      - ufo: STR_ESCORT\n        count: 1\n        trajectory: P1\n        timer: 15000\n      - ufo: STR_CRUISER\n        count: 1\n        trajectory: P1\n        timer: 9600\n      - ufo: STR_BATTLESHIP\n        count: 1\n        trajectory: P0\n        timer: 12000\n      - ufo: STR_BATTLESHIP\n        count: 1\n        trajectory: P7\n        timer: 9000\n        objective: true\n  - type: STR_ALIEN_SHIP_ATTACK\n    points: 0\n    objective: 3\n    spawnZone: 0 #Mission zone for terror missions\n    raceWeights:\n      0:\n        STR_AQUATOID: 10\n        STR_GILLMAN: 30\n        STR_MIXED_CREW: 20\n        STR_LOBSTERMAN: 20\n        STR_TASOTH: 20\n    waves:\n      - ufo: dummy #don't spawn a ufo, we only want the site\n        count: 1\n        trajectory: P10\n        timer: 0\n        objective: true\n  - type: STR_ALIEN_RETALIATION\n    points: 0\n    objective: 4\n    spawnUfo: STR_DREADNOUGHT #Spawned for the final retaliation run\n    raceWeights:\n      0:\n        STR_AQUATOID: 20\n        STR_GILLMAN: 20\n        STR_TASOTH: 20\n        STR_LOBSTERMAN: 20\n    waves:\n      - ufo: STR_SURVEY_SHIP\n        count: 1\n        trajectory: P8\n        timer: 3000\n      - ufo: STR_ESCORT\n        count: 2\n        trajectory: P8\n        timer: 3000\n      - ufo: STR_CRUISER\n        count: 3\n        trajectory: P8\n        timer: 3000\n      - ufo: STR_DREADNOUGHT\n        count: 2\n        trajectory: P8\n        timer: 3000\n  - type: STR_ALIEN_SUPPLY\n    points: 0\n    objective: 5\n    raceWeights: {} #Special case, race comes from base.\n    waves:\n      - ufo: STR_FLEET_SUPPLY_CRUISER\n        count: 1\n        trajectory: P9\n        timer: 6000\n        objective: true\n  - type: STR_ALIEN_ARTIFACT\n    points: 0\n    objective: 3\n    spawnZone: 0 #Mission zone for terror missions\n    raceWeights:\n      0:\n        STR_MIXED_CREW: 100\n    waves:\n      - ufo: STR_ARTIFACT_SITE_P1 # spawn this site directly\n        count: 1\n        trajectory: P10\n        timer: 0\n        objective: true\n"
  },
  {
    "path": "bin/standard/xcom2/alienRaces.rul",
    "content": "alienRaces: #done\n  - id: STR_AQUATOID\n    members:\n      - STR_AQUATOID_COMMANDER\n      - STR_AQUATOID_NAVIGATOR\n      - STR_AQUATOID_MEDIC\n      - STR_AQUATOID_TECHNICIAN\n      - STR_AQUATOID_SQUAD_LEADER\n      - STR_AQUATOID_SOLDIER\n      - STR_CALCINITE_TERRORIST\n      - STR_CALCINITE_TERRORIST\n  - id: STR_AQUATOID_UNDERWATER\n    members:\n      - STR_AQUATOID_COMMANDER\n      - STR_AQUATOID_NAVIGATOR\n      - STR_AQUATOID_MEDIC\n      - STR_AQUATOID_TECHNICIAN\n      - STR_AQUATOID_SQUAD_LEADER\n      - STR_AQUATOID_SOLDIER\n      - STR_HALLUCINOID_TERRORIST\n      - STR_HALLUCINOID_TERRORIST\n  - id: STR_GILLMAN\n    members:\n      - STR_GILLMAN_COMMANDER\n      - STR_GILLMAN_TECHNICIAN\n      - STR_GILLMAN_SQUAD_LEADER\n      - STR_GILLMAN_SQUAD_LEADER\n      - STR_GILLMAN_SOLDIER\n      - STR_GILLMAN_SOLDIER\n      - STR_DEEP_ONE_TERRORIST\n      - STR_DEEP_ONE_TERRORIST\n  - id: STR_GILLMAN_UNDERWATER\n    members:\n      - STR_GILLMAN_COMMANDER\n      - STR_GILLMAN_TECHNICIAN\n      - STR_GILLMAN_SQUAD_LEADER\n      - STR_GILLMAN_SQUAD_LEADER\n      - STR_GILLMAN_SOLDIER\n      - STR_GILLMAN_SOLDIER\n      - STR_XARQUID_TERRORIST\n      - STR_XARQUID_TERRORIST\n  - id: STR_LOBSTERMAN\n    members:\n      - STR_LOBSTERMAN_COMMANDER\n      - STR_LOBSTERMAN_NAVIGATOR\n      - STR_LOBSTERMAN_TECHNICIAN\n      - STR_LOBSTERMAN_SQUAD_LEADER\n      - STR_LOBSTERMAN_TECHNICIAN\n      - STR_LOBSTERMAN_SOLDIER\n      - STR_BIODRONE_TERRORIST\n      - STR_BIODRONE_TERRORIST\n  - id: STR_LOBSTERMAN_UNDERWATER\n    members:\n      - STR_LOBSTERMAN_COMMANDER\n      - STR_LOBSTERMAN_NAVIGATOR\n      - STR_LOBSTERMAN_TECHNICIAN\n      - STR_LOBSTERMAN_SQUAD_LEADER\n      - STR_LOBSTERMAN_TECHNICIAN\n      - STR_LOBSTERMAN_SOLDIER\n      - STR_TENTACULAT_TERRORIST\n      - STR_TENTACULAT_TERRORIST\n# Small departure from vanilla here: we've applied the same 50% upgrade\n# of biodrones to triscenes as was the case with mixed race 1.\n# This was done in order to reduce the ridiculous rarity of their appearance.\n  - id: STR_TASOTH\n    members:\n      - STR_TASOTH_SQUAD_LEADER\n      - STR_TASOTH_SQUAD_LEADER\n      - STR_TASOTH_SOLDIER\n      - STR_TASOTH_SQUAD_LEADER\n      - STR_TASOTH_SQUAD_LEADER\n      - STR_TASOTH_SOLDIER\n      - STR_BIODRONE_TERRORIST\n      - STR_TRISCENE_TERRORIST\n  - id: STR_TASOTH_UNDERWATER\n    members:\n      - STR_TASOTH_SQUAD_LEADER\n      - STR_TASOTH_SQUAD_LEADER\n      - STR_TASOTH_SOLDIER\n      - STR_TASOTH_SQUAD_LEADER\n      - STR_TASOTH_SQUAD_LEADER\n      - STR_TASOTH_SOLDIER\n      - STR_TENTACULAT_TERRORIST\n      - STR_TENTACULAT_TERRORIST\n# Vanilla has a 50% chance for each biodrone that spawns on a mixed crew\n# to be \"upgraded\" to a Triscene on land missions.\n# This unfortunately also upgrades 50% of the calcinites to xarquids,\n# which is very likely unintended.\n# The method to re-implement that should be fairly obvious.\n  - id: STR_MIXED_CREW\n    members:\n      - STR_CALCINITE_TERRORIST\n      - STR_CALCINITE_TERRORIST\n      - STR_AQUATOID_SQUAD_LEADER\n      - STR_AQUATOID_SOLDIER\n      - STR_TASOTH_SQUAD_LEADER\n      - STR_TASOTH_SOLDIER\n      - STR_BIODRONE_TERRORIST\n      - STR_TRISCENE_TERRORIST\n  - id: STR_MIXED_CREW_UNDERWATER\n    members:\n      - STR_HALLUCINOID_TERRORIST\n      - STR_HALLUCINOID_TERRORIST\n      - STR_AQUATOID_SQUAD_LEADER\n      - STR_AQUATOID_SOLDIER\n      - STR_TASOTH_SQUAD_LEADER\n      - STR_TASOTH_SOLDIER\n      - STR_TENTACULAT_TERRORIST\n      - STR_TENTACULAT_TERRORIST\n  - id: STR_MIXED_CREW_2\n    members:\n      - STR_TENTACULAT_TERRORIST\n      - STR_DEEP_ONE_TERRORIST\n      - STR_BIODRONE_TERRORIST\n      - STR_AQUATOID_SOLDIER\n      - STR_LOBSTERMAN_SQUAD_LEADER\n      - STR_LOBSTERMAN_SOLDIER\n      - STR_BIODRONE_TERRORIST\n      - STR_CALCINITE_TERRORIST\n  - id: STR_MIXED_CREW_2_UNDERWATER\n    members:\n      - STR_DEEP_ONE_TERRORIST\n      - STR_XARQUID_TERRORIST\n      - STR_TENTACULAT_TERRORIST\n      - STR_AQUATOID_SOLDIER\n      - STR_LOBSTERMAN_SQUAD_LEADER\n      - STR_LOBSTERMAN_SOLDIER\n      - STR_TENTACULAT_TERRORIST\n      - STR_HALLUCINOID_TERRORIST\n"
  },
  {
    "path": "bin/standard/xcom2/armors.rul",
    "content": "armors: #done\n  - type: STR_NONE_UC\n    spriteSheet: TDXCOM_0.PCK\n    spriteInv: MAN_0\n    storeItem: STR_NONE\n    corpseItem: STR_CORPSE\n    frontArmor: 12\n    sideArmor: 8\n    rearArmor: 5\n    underArmor: 2\n    damageModifier:\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.6\n      - 1.5\n      - 1.0\n    loftemps: 3\n    drawingRoutine: 13\n    drawBubbles: true\n    spriteFaceGroup: 14\n    spriteFaceColor: [160, 160, 64, 160, 160, 64, 160, 160] #M0 F0 M1 F1 M2 F2 M3 F3\n    spriteHairGroup: 4\n    spriteHairColor: [130, 160, 201, 130, 64, 198, 160, 64] #M0 F0 M1 F1 M2 F2 M3 F3\n  - type: STR_PLASTIC_AQUA_ARMOR_UC\n    spriteSheet: TDXCOM_1.PCK\n    spriteInv: MAN_1\n    corpseItem: STR_CORPSE_ARMOR\n    storeItem: STR_PLASTIC_AQUA_ARMOR\n    frontArmor: 60\n    sideArmor: 35\n    rearArmor: 30\n    underArmor: 25\n    damageModifier:\n      - 1.0\n      - 0.9\n      - 0.8\n      - 1.0\n      - 0.8\n      - 1.0\n      - 1.0\n      - 1.2\n      - 1.1\n      - 1.0\n    loftemps: 3\n    drawingRoutine: 13\n    drawBubbles: true\n    spriteFaceGroup: 14\n    spriteFaceColor: [160, 160, 64, 160, 160, 64, 160, 160] #M0 F0 M1 F1 M2 F2 M3 F3\n    spriteHairGroup: 4\n    spriteHairColor: [130, 160, 201, 130, 64, 198, 160, 64] #M0 F0 M1 F1 M2 F2 M3 F3\n  - type: STR_ION_ARMOR_UC\n    spriteSheet: TDXCOM_2.PCK\n    spriteInv: MAN_2\n    corpseItem: STR_CORPSE_ION\n    storeItem: STR_ION_ARMOR\n    frontArmor: 132\n    sideArmor: 70\n    rearArmor: 100\n    underArmor: 55\n    damageModifier:\n      - 1.0\n      - 0.8\n      - 0.0\n      - 0.8\n      - 0.7\n      - 0.9\n      - 1.0\n      - 1.1\n      - 1.0\n      - 0.0\n    loftemps: 3\n    drawingRoutine: 13\n    drawBubbles: true\n    forcedTorso: 1\n    spriteFaceGroup: 14\n    spriteFaceColor: [160, 160, 64, 160, 160, 64, 160, 160] #M0 F0 M1 F1 M2 F2 M3 F3\n    spriteHairGroup: 4\n    spriteHairColor: [130, 160, 201, 130, 64, 198, 160, 64] #M0 F0 M1 F1 M2 F2 M3 F3\n  - type: STR_MAGNETIC_ION_ARMOR_UC\n    spriteSheet: TDXCOM_2.PCK\n    spriteInv: MAN_3\n    corpseItem: STR_CORPSE_ION\n    storeItem: STR_MAGNETIC_ION_ARMOR\n    frontArmor: 142\n    sideArmor: 80\n    rearArmor: 110\n    underArmor: 65\n    movementType: 3\n    damageModifier:\n      - 1.0\n      - 0.8\n      - 0.0\n      - 0.8\n      - 0.7\n      - 0.9\n      - 1.0\n      - 1.1\n      - 1.0\n      - 0.0\n    loftemps: 3\n    drawingRoutine: 13\n    drawBubbles: true\n    forcedTorso: 2\n    spriteFaceGroup: 14\n    spriteFaceColor: [160, 160, 64, 160, 160, 64, 160, 160] #M0 F0 M1 F1 M2 F2 M3 F3\n    spriteHairGroup: 4\n    spriteHairColor: [130, 160, 201, 130, 64, 198, 160, 64] #M0 F0 M1 F1 M2 F2 M3 F3\n  - type: AQUATOID_ARMOR0\n    spriteSheet: AQUA.PCK\n    corpseItem: STR_AQUATOID_CORPSE\n    frontArmor: 4\n    sideArmor: 3\n    rearArmor: 2\n    underArmor: 2\n    damageModifier:\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.6\n      - 1.5\n      - 1.0\n    loftemps: 2\n    drawingRoutine: 15\n  - type: DEEP_ONE_ARMOR0\n    spriteSheet: DEEPONE.PCK\n    allowInv: false\n    corpseItem: STR_DEEP_ONE_CORPSE\n    frontArmor: 8\n    sideArmor: 6\n    rearArmor: 4\n    underArmor: 12\n    damageModifier:\n      - 1.0\n      - 0.9\n      - 0.9\n      - 0.8\n      - 0.9\n      - 1.1\n      - 1.0\n      - 1.2\n      - 0.0\n      - 1.0\n    loftemps: 3\n    drawingRoutine: 14\n    drawBubbles: true\n  - type: GILLMAN_ARMOR0\n    spriteSheet: GILLMAN.PCK\n    corpseItem: STR_GILLMAN_CORPSE\n    frontArmor: 15\n    sideArmor: 12\n    rearArmor: 14\n    underArmor: 12\n    damageModifier:\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.1\n      - 1.0\n      - 1.2\n      - 0.0\n      - 1.0\n    loftemps: 3\n    drawingRoutine: 14\n    drawBubbles: true\n  - type: TASOTH_ARMOR0\n    spriteSheet: TASOTHS.PCK\n    corpseItem: STR_TASOTH_CORPSE\n    frontArmor: 20\n    sideArmor: 20\n    rearArmor: 20\n    underArmor: 10\n    damageModifier:\n      - 1.0\n      - 0.8\n      - 0.4\n      - 0.9\n      - 0.7\n      - 1.2\n      - 1.1\n      - 0.9\n      - 0.0\n      - 1.1\n    loftemps: 3\n    drawingRoutine: 14\n    drawBubbles: true\n  - type: CALCINITE_ARMOR0\n    spriteSheet: CALCIN.PCK\n    allowInv: false\n    corpseItem: STR_CALCINITE_CORPSE\n    frontArmor: 35\n    sideArmor: 35\n    rearArmor: 35\n    underArmor: 10\n    damageModifier:\n      - 1.0\n      - 1.0\n      - 0.9\n      - 1.0\n      - 0.9\n      - 1.1\n      - 1.0\n      - 0.8\n      - 0.0\n      - 1.0\n    loftemps: 3\n    drawingRoutine: 14\n    drawBubbles: true\n  - type: TENTACULAT_ARMOR0\n    spriteSheet: TENTAC.PCK\n    allowInv: false\n    corpseItem: STR_TENTACULAT_CORPSE\n    frontArmor: 45\n    sideArmor: 25\n    rearArmor: 15\n    underArmor: 5\n    movementType: 1\n    damageModifier:\n      - 1.0\n      - 0.8\n      - 1.0\n      - 1.5\n      - 0.9\n      - 1.1\n      - 1.1\n      - 1.1\n      - 0.0\n      - 1.1\n    loftemps: 2\n    drawingRoutine: 19\n  - type: LOBSTERMAN_ARMOR0\n    spriteSheet: LOBSTER.PCK\n    corpseItem: STR_LOBSTERMAN_CORPSE\n    frontArmor: 20\n    sideArmor: 20\n    rearArmor: 15\n    underArmor: 10\n    damageModifier:\n      - 1.0\n      - 0.2\n      - 0.3\n      - 0.3\n      - 0.3\n      - 0.5\n      - 1.1\n      - 2.0\n      - 0.0\n      - 1.1\n    loftemps: 4\n    drawingRoutine: 14\n    drawBubbles: true\n  - type: LOBSTERMAN_ARMOR1\n    spriteSheet: LOBSTER.PCK\n    corpseItem: STR_LOBSTERMAN_CORPSE\n    frontArmor: 20\n    sideArmor: 20\n    rearArmor: 18\n    underArmor: 10\n    damageModifier:\n      - 1.0\n      - 0.2\n      - 0.3\n      - 0.3\n      - 0.3\n      - 0.5\n      - 1.1\n      - 2.0\n      - 0.0\n      - 1.1\n    loftemps: 4\n    drawingRoutine: 14\n    drawBubbles: true\n  - type: LOBSTERMAN_ARMOR2\n    spriteSheet: LOBSTER.PCK\n    corpseItem: STR_LOBSTERMAN_CORPSE\n    frontArmor: 22\n    sideArmor: 22\n    rearArmor: 20\n    underArmor: 12\n    damageModifier:\n      - 1.0\n      - 0.2\n      - 0.3\n      - 0.3\n      - 0.3\n      - 0.5\n      - 1.1\n      - 2.0\n      - 0.0\n      - 1.1\n    loftemps: 4\n    drawingRoutine: 14\n    drawBubbles: true\n  - type: XARQUID_ARMOR0\n    spriteSheet: XARQUID.PCK\n    allowInv: false\n    corpseGeo: STR_XARQUID_CORPSE\n    corpseBattle:\n      - XARQUID_CORPSE_1\n      - XARQUID_CORPSE_2\n      - XARQUID_CORPSE_3\n      - XARQUID_CORPSE_4\n    frontArmor: 50\n    sideArmor: 50\n    rearArmor: 50\n    underArmor: 5\n    movementType: 1\n    size: 2\n    damageModifier:\n      - 1.0\n      - 1.0\n      - 0.6\n      - 0.6\n      - 0.7\n      - 0.9\n      - 0.9\n      - 1.45\n      - 0.0\n      - 0.9\n    loftempsSet: [ 92, 89, 90, 91 ]\n    drawingRoutine: 21\n    constantAnimation: true\n  - type: BIODRONE_ARMOR0\n    spriteSheet: BIODRON.PCK\n    allowInv: false\n    corpseItem: STR_BIODRONE_CORPSE\n    frontArmor: 25\n    sideArmor: 15\n    rearArmor: 10\n    underArmor: 5\n    movementType: 1\n    damageModifier:\n      - 1.0\n      - 1.0\n      - 0.6\n      - 0.6\n      - 0.7\n      - 0.9\n      - 0.9\n      - 1.45\n      - 0.0\n      - 0.9\n    loftemps: 2\n    drawingRoutine: 16\n    constantAnimation: true\n  - type: HALLUCINOID_ARMOR0\n    spriteSheet: HALLUCIN.PCK\n    allowInv: false\n    corpseGeo: STR_HALLUCINOID_CORPSE\n    corpseBattle:\n      - HALLUCINOID_CORPSE_1\n      - HALLUCINOID_CORPSE_2\n      - HALLUCINOID_CORPSE_3\n      - HALLUCINOID_CORPSE_4\n    frontArmor: 35\n    sideArmor: 35\n    rearArmor: 35\n    underArmor: 25\n    size: 2\n    movementType: 1\n    damageModifier:\n      - 1.0\n      - 0.6\n      - 1.7\n      - 0.7\n      - 0.8\n      - 1.0\n      - 1.0\n      - 0.6\n      - 0.0\n      - 1.0\n    loftempsSet: [ 92, 89, 90, 91 ]\n    drawingRoutine: 12\n    constantAnimation: true\n  - type: TRISCENE_ARMOR0\n    spriteSheet: TRISCEN.PCK\n    allowInv: false\n    corpseGeo: STR_TRISCENE_CORPSE\n    corpseBattle:\n      - TRISCENE_CORPSE_1\n      - TRISCENE_CORPSE_2\n      - TRISCENE_CORPSE_3\n      - TRISCENE_CORPSE_4\n    frontArmor: 120\n    sideArmor: 110\n    rearArmor: 110\n    underArmor: 8\n    size: 2\n    damageModifier:\n      - 1.0\n      - 0.9\n      - 0.9\n      - 0.9\n      - 0.8\n      - 0.9\n      - 0.9\n      - 1.1\n      - 0.0\n      - 0.9\n    loftempsSet: [ 92, 89, 90, 91 ]\n    drawingRoutine: 20\n  - type: COELACANTH_ARMOR\n    spriteSheet: TANK01.PCK\n    allowInv: false\n    corpseBattle:\n      - COELACANTH_CORPSE_1\n      - COELACANTH_CORPSE_2\n      - COELACANTH_CORPSE_3\n      - COELACANTH_CORPSE_4\n    frontArmor: 90\n    sideArmor: 75\n    rearArmor: 60\n    underArmor: 60\n    size: 2\n    damageModifier:\n      - 1.0\n      - 0.95\n      - 0.4\n      - 0.8\n      - 0.6\n      - 1.0\n      - 0.0\n      - 0.8\n      - 1.2\n      - 0.0\n    loftempsSet: [ 92, 89, 90, 91 ]\n    drawingRoutine: 11\n  - type: DISPLACER_ARMOR\n    spriteSheet: TANK01.PCK\n    allowInv: false\n    corpseBattle:\n      - DISPLACER_CORPSE_1\n      - DISPLACER_CORPSE_2\n      - DISPLACER_CORPSE_3\n      - DISPLACER_CORPSE_4\n    frontArmor: 130\n    sideArmor: 130\n    rearArmor: 130\n    underArmor: 100\n    movementType: 1\n    size: 2\n    damageModifier:\n      - 1.0\n      - 0.95\n      - 0.4\n      - 0.8\n      - 0.6\n      - 1.0\n      - 0.0\n      - 0.8\n      - 1.2\n      - 0.0\n    loftempsSet: [ 92, 89, 90, 91 ]\n    drawingRoutine: 11\n    constantAnimation: true\n  - type: DOCKER_ARMOR\n    spriteSheet: CIVIL_1.PCK\n    corpseItem: CIVM_CORPSE\n    frontArmor: 0\n    sideArmor: 0\n    rearArmor: 0\n    underArmor: 0\n    damageModifier:\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.6\n      - 1.5\n      - 1.0\n    loftemps: 3\n    drawingRoutine: 17\n  - type: SURFER_ARMOR\n    spriteSheet: CIVIL_1.PCK\n    corpseItem: CIVF_CORPSE\n    frontArmor: 0\n    sideArmor: 0\n    rearArmor: 0\n    underArmor: 0\n    damageModifier:\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.6\n      - 1.5\n      - 1.0\n    loftemps: 3\n    drawingRoutine: 18\n  - type: SAILOR_ARMOR\n    spriteSheet: CIVIL_2.PCK\n    corpseItem: CIVM_CORPSE\n    frontArmor: 0\n    sideArmor: 0\n    rearArmor: 0\n    underArmor: 0\n    damageModifier:\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.6\n      - 1.5\n      - 1.0\n    loftemps: 3\n    drawingRoutine: 17\n  - type: BIKINI_GIRL_ARMOR\n    spriteSheet: CIVIL_2.PCK\n    corpseItem: CIVF_CORPSE\n    frontArmor: 0\n    sideArmor: 0\n    rearArmor: 0\n    underArmor: 0\n    damageModifier:\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.0\n      - 1.6\n      - 1.5\n      - 1.0\n    loftemps: 3\n    drawingRoutine: 18\n  - type: ZOMBIE_ARMOR\n    spriteSheet: ZOMBIE.PCK\n    allowInv: false\n    corpseItem: STR_TENTACULAT_CORPSE\n    frontArmor: 4\n    sideArmor: 4\n    rearArmor: 4\n    underArmor: 4\n    damageModifier:\n      - 1.0\n      - 0.9\n      - 0.9\n      - 0.9\n      - 0.8\n      - 0.9\n      - 0.9\n      - 1.1\n      - 0.0\n      - 0.9\n    loftemps: 2\n    drawingRoutine: 17\n"
  },
  {
    "path": "bin/standard/xcom2/converter.rul",
    "content": "# Here be dragons\nconverter:\n  offsets:\n    BASE.DAT_FACILITIES: 0xDA\n    BASE.DAT_ENGINEERS: 0x122\n    BASE.DAT_SCIENTISTS: 0x123\n    BASE.DAT_ITEMS: 0x10\n    CRAFT.DAT_LEFT_WEAPON: 0x01\n    CRAFT.DAT_LEFT_AMMO: 0x02\n    CRAFT.DAT_FLIGHT: 0x04\n    CRAFT.DAT_RIGHT_WEAPON: 0x05\n    CRAFT.DAT_RIGHT_AMMO: 0x3E\n    CRAFT.DAT_DAMAGE: 0x42\n    CRAFT.DAT_ALTITUDE: 0x44\n    CRAFT.DAT_SPEED: 0x46\n    CRAFT.DAT_DESTINATION: 0x48\n    CRAFT.DAT_DEST_LON: 0x4C\n    CRAFT.DAT_DEST_LAT: 0x4E\n    CRAFT.DAT_FUEL: 0x50\n    CRAFT.DAT_BASE: 0x52\n    CRAFT.DAT_MISSION: 0x54\n    CRAFT.DAT_REGION: 0x56\n    CRAFT.DAT_TRAJECTORY: 0x5A\n    CRAFT.DAT_TRAJECTORY_POINT: 0x58\n    CRAFT.DAT_RACE: 0x5C\n    CRAFT.DAT_STATUS: 0x62\n    CRAFT.DAT_ITEMS: 0x06\n    CRAFT.DAT_STATE: 0x64\n    SOLDIER.DAT_RANK: 0x0A\n    SOLDIER.DAT_BASE: 0x06\n    SOLDIER.DAT_CRAFT: 0x08\n    SOLDIER.DAT_MISSIONS: 0x12\n    SOLDIER.DAT_KILLS: 0x0E\n    SOLDIER.DAT_RECOVERY: 0x10\n    SOLDIER.DAT_NAME: 0x23\n    SOLDIER.DAT_INITIAL_TU: 0x1A\n    SOLDIER.DAT_INITIAL_HE: 0x1B\n    SOLDIER.DAT_INITIAL_STA: 0x1C\n    SOLDIER.DAT_INITIAL_RE: 0x45\n    SOLDIER.DAT_INITIAL_STR: 0x22\n    SOLDIER.DAT_INITIAL_FA: 0x21\n    SOLDIER.DAT_INITIAL_TA: 0x1D\n    SOLDIER.DAT_INITIAL_ME: 0x44\n    SOLDIER.DAT_INITIAL_PST: 0x43\n    SOLDIER.DAT_INITIAL_PSK: 0x41\n    SOLDIER.DAT_INITIAL_BR: 0x40\n    SOLDIER.DAT_IMPROVED_TU: 0x01\n    SOLDIER.DAT_IMPROVED_HE: 0x04\n    SOLDIER.DAT_IMPROVED_STA: 0x17\n    SOLDIER.DAT_IMPROVED_RE: 0x18\n    SOLDIER.DAT_IMPROVED_STR: 0x05\n    SOLDIER.DAT_IMPROVED_FA: 0x19\n    SOLDIER.DAT_IMPROVED_TA: 0x3F\n    SOLDIER.DAT_IMPROVED_ME: 0x42\n    SOLDIER.DAT_IMPROVED_BR: 0x3E\n    SOLDIER.DAT_ARMOR: 0x1E\n    SOLDIER.DAT_PSI: 0x00\n    SOLDIER.DAT_PSILAB: 0x02\n    SOLDIER.DAT_GENDER: 0x1F\n    SOLDIER.DAT_LOOK: 0x20\n  markers:\n    - STR_UFO\n    - STR_TERROR_SITE\n    - STR_ALIEN_BASE\n    - STR_LANDING_SITE\n    - STR_CRASH_SITE\n    - STR_WAYPOINT\n    - STR_TRITON\n    - STR_BARRACUDA\n    - STR_MANTA\n    - STR_HAMMERHEAD\n    - STR_LEVIATHAN\n  countries:\n    - STR_USA\n    - STR_ALASKA\n    - STR_EU_SYNDICATE\n    - STR_ARABIAN_BLOC\n    - STR_EGYPTIAN_CARTEL\n    - STR_AFRICA_CORP\n    - STR_BRAZILIAN_UNION\n    - STR_NEW_MEXICO\n    - STR_ASIAN_COALITION\n    - STR_SCANDINAVIA\n    - STR_NEO_JAPAN\n    - STR_FREE_CHINA\n    - STR_AUSTRALASIA\n    - STR_FED_KOREA\n    - STR_EURASIA_UC\n    - STR_ICELANDIC_UNION\n  regions:\n    - STR_NORTH_ATLANTIC\n    - STR_SOUTH_ATLANTIC\n    - STR_NORTH_PACIFIC\n    - STR_SOUTH_PACIFIC\n    - STR_MEDITERRANEAN\n    - STR_SOUTH_CHINA_SEA\n    - STR_INDIAN_OCEAN\n    - STR_THE_EAST_SEA\n    - STR_NORTH_SEA\n    - STR_CARRIBEAN\n    - STR_ANTARCTIC\n    - STR_ARCTIC\n    - STR_EURASIA\n    - STR_NORTH_AMERICA\n    - STR_AFRICA\n  facilities:\n    - STR_AIR_LOCK\n    - STR_LIVING_QUARTERS\n    - STR_LABORATORY\n    - STR_WORKSHOP\n    - STR_STANDARD_SONAR\n    - STR_WIDE_ARRAY_SONAR\n    - STR_TORPEDO_DEFENSES\n    - STR_GENERAL_STORES\n    - STR_ALIEN_CONTAINMENT\n    - STR_GAUSS_DEFENSES\n    - STR_SONIC_DEFENSES\n    - STR_PWT_DEFENSES\n    - STR_BOMBARDMENT_SHIELD\n    - STR_MC_GENERATOR\n    - STR_MC_LAB\n    - STR_TRANSMISSION_RESOLVER\n    - STR_SUB_PEN\n  items:\n    - STR_AJAX_LAUNCHER\n    - STR_DUP_HEAD_LAUNCHER\n    - STR_CRAFT_GAS_CANNON\n    - STR_PWT_CANNON\n    - STR_GAUSS_CANNON\n    - STR_SONIC_OSCILLATOR\n    - STR_AJAX_TORPEDOES\n    - STR_DUP_HEAD_TORPEDOES\n    - STR_CRAFT_GAS_CANNON_ROUNDS_X50\n    - STR_PULSE_WAVE_TORPEDOES\n    - STR_COELACANTH_GAS_CANNON\n    - STR_COELACANTH_AQUA_JET\n    - STR_COELACANTH_GAUSS\n    - STR_DISPLACER_SONIC\n    - STR_DISPLACER_PWT\n    - STR_DART_PISTOL\n    - STR_DART_POD\n    - STR_JET_HARPOON\n    - STR_HARPOON_POD\n    - STR_GAS_CANNON\n    - STR_GC_AP_AMMO\n    - STR_GC_HE_AMMO\n    - STR_GC_P_AMMO\n    - STR_HYDRO_JET_CANNON\n    - STR_HJC_AP_AMMO\n    - STR_HJC_HE_AMMO\n    - STR_HJC_P_AMMO\n    - STR_TORPEDO_LAUNCHER\n    - STR_SMALL_TORPEDO\n    - STR_LARGE_TORPEDO\n    - STR_PHOSPHOROUS_TORPEDO\n    - STR_GAUSS_PISTOL\n    - STR_GAUSS_RIFLE\n    - STR_HEAVY_GAUSS\n    - STR_MAGNA_BLAST_GRENADE\n    - STR_DYE_GRENADE\n    - STR_PARTICLE_DISTURBANCE_GRENADE\n    - STR_MAGNA_PACK_EXPLOSIVE\n    - STR_PARTICLE_DISTURBANCE_SENSOR\n    - STR_MEDI_KIT\n    - STR_MC_DISRUPTOR\n    - STR_THERMAL_TAZER\n    - STR_CHEMICAL_FLARE\n    - STR_VIBRO_BLADE\n    - STR_THERMIC_LANCE\n    - STR_HEAVY_THERMIC_LANCE\n    - \"\"\n    - \"\"\n    - \"\"\n    - STR_SONIC_CANNON\n    - STR_CANNON_POWER_CLIP\n    - STR_SONIC_BLASTA_RIFLE\n    - STR_BLASTA_POWER_CLIP\n    - STR_SONIC_PISTOL\n    - STR_PISTOL_POWER_CLIP\n    - STR_DISRUPTOR_PULSE_LAUNCHER\n    - STR_DISRUPTOR_AMMO\n    - STR_THERMAL_SHOK_LAUNCHER\n    - STR_THERMAL_SHOK_BOMB\n    - STR_SONIC_PULSER\n    - STR_ZRBITE\n    - STR_MC_READER\n    - STR_GAUSS_PISTOL_CLIP\n    - STR_GAUSS_RIFLE_CLIP\n    - STR_HEAVY_GAUSS_CLIP\n    - STR_AQUATOID_CORPSE\n    - STR_GILLMAN_CORPSE\n    - STR_LOBSTERMAN_CORPSE\n    - STR_TASOTH_CORPSE\n    - STR_CALCINITE_CORPSE\n    - STR_DEEP_ONE_CORPSE\n    - STR_BIODRONE_CORPSE\n    - STR_TENTACULAT_CORPSE\n    - STR_TRISCENE_CORPSE\n    - STR_HALLUCINOID_CORPSE\n    - STR_XARQUID_CORPSE\n    - \"\"\n    - \"\"\n    - \"\"\n    - \"\"\n    - STR_ION_BEAM_ACCELERATORS\n    - STR_MAGNETIC_NAVIGATION\n    - STR_ALIEN_SUB_CONSTRUCTION\n    - STR_ALIEN_CRYOGENICS\n    - STR_ALIEN_CLONING\n    - STR_ALIEN_LEARNING_ARRAYS\n    - STR_ALIEN_IMPLANTER\n    - STR_EXAMINATION_ROOM\n    - STR_AQUA_PLASTICS\n    - STR_ALIEN_REANIMATION_ZONE\n    - STR_PLASTIC_AQUA_ARMOR\n    - STR_ION_ARMOR\n    - STR_MAGNETIC_ION_ARMOR\n    - STR_HWP_SOLID_HARPOON_BOLTS\n    - STR_HWP_AQUA_JET_MISSILES\n    - STR_HWP_DISPLACER_PWT\n    - STR_GAUSS_CANNON_AMMO\n  crews:\n    - STR_AQUATOID\n    - STR_GILLMAN\n    - STR_LOBSTERMAN\n    - STR_TASOTH\n    - STR_MIXED_CREW\n    - STR_MIXED_CREW_2\n  crafts:\n    - STR_TRITON\n    - STR_HAMMERHEAD\n    - STR_LEVIATHAN\n    - STR_BARRACUDA\n    - STR_MANTA\n  ufos:\n    - STR_SURVEY_SHIP\n    - STR_ESCORT\n    - STR_CRUISER\n    - STR_HEAVY_CRUISER\n    - STR_HUNTER\n    - STR_BATTLESHIP\n    - STR_DREADNOUGHT\n    - STR_FLEET_SUPPLY_CRUISER\n  craftWeapons:\n    - STR_AJAX\n    - STR_DUP_HEAD\n    - STR_CRAFT_GAS_CANNON_UC\n    - STR_PWT_CANNON_UC\n    - STR_GAUSS_CANNON_UC\n    - STR_SONIC_OSCILLATOR_UC\n  missions:\n    - STR_ALIEN_PROBE_MISSION\n    - STR_ALIEN_INTERDICTION\n    - STR_ALIEN_RESOURCE_RAID\n    - STR_ALIEN_INFILTRATION\n    - STR_ALIEN_BASE\n    - STR_ALIEN_SURFACE_ATTACK\n#    - STR_ALIEN_SHIP_ATTACK\n    - STR_ALIEN_RETALIATION\n    - STR_ALIEN_SUPPLY\n#    - STR_ALIEN_ARTIFACT\n  armor:\n    - STR_NONE_UC\n    - STR_PLASTIC_AQUA_ARMOR_UC\n    - STR_ION_ARMOR_UC\n    - STR_MAGNETIC_ION_ARMOR_UC\n  alienRaces:\n    - \"\"\n    - STR_AQUATOID\n    - STR_GILLMAN\n    - STR_LOBSTERMAN\n    - STR_TASOTH\n    - STR_CALCINITE\n    - STR_DEEP_ONE\n    - STR_BIODRONE\n    - STR_TENTACULAT\n    - STR_TRISCENE\n    - STR_HALLUCINOID\n    - STR_XARQUID\n  alienRanks:\n    - \"\"\n    - _COMMANDER\n    - _NAVIGATOR\n    - _MEDIC\n    - _TECHNICIAN\n    - _SQUAD_LEADER\n    - _SOLDIER\n    - _TERRORIST\n  research:\n    - STR_GAUSS_TECH\n    - STR_PARTICLE_DISTURBANCE_SENSOR\n    - STR_MEDI_KIT\n    - STR_MC_DISRUPTOR\n    - STR_SONIC_CANNON\n    - STR_CANNON_POWER_CLIP\n    - STR_SONIC_BLASTA_RIFLE\n    - STR_BLASTA_POWER_CLIP\n    - STR_SONIC_PISTOL\n    - STR_PISTOL_POWER_CLIP\n    - STR_DISRUPTOR_PULSE_LAUNCHER\n    - STR_DISRUPTOR_AMMO\n    - STR_THERMAL_SHOK_LAUNCHER\n    - STR_THERMAL_SHOK_BOMB\n    - STR_SONIC_PULSER\n    - STR_ZRBITE\n    - STR_MC_READER\n    - STR_ION_BEAM_ACCELERATORS\n    - STR_MAGNETIC_NAVIGATION\n    - STR_ALIEN_SUB_CONSTRUCTION\n    - STR_ALIEN_CRYOGENICS\n    - STR_ALIEN_CLONING\n    - STR_ALIEN_LEARNING_ARRAYS\n    - STR_ALIEN_IMPLANTER\n    - STR_EXAMINATION_ROOM\n    - STR_AQUA_PLASTICS\n    - STR_NEW_FIGHTER_FLYING_SUB\n    - STR_NEW_FIGHTER_TRANSPORTER\n    - STR_THE_LATEST_FLYING_SUB\n    - STR_GAUSS_PISTOL\n    - STR_GAUSS_RIFLE\n    - STR_HEAVY_GAUSS\n    - STR_GAUSS_CANNON\n    - STR_SONIC_OSCILLATOR\n    - STR_PWT_CANNON\n    - STR_GAUSS_DEFENSES\n    - STR_SONIC_DEFENSES\n    - STR_PWT_DEFENSES\n    - STR_BOMBARDMENT_SHIELD\n    - STR_MC_GENERATOR\n    - STR_MC_LAB\n    - STR_TRANSMISSION_RESOLVER\n    - \"\"\n    - \"\"\n    - \"\"\n    - STR_AQUATOID_CORPSE\n    - STR_GILLMAN_CORPSE\n    - STR_LOBSTERMAN_CORPSE\n    - STR_TASOTH_CORPSE\n    - STR_CALCINITE_CORPSE\n    - STR_DEEP_ONE_CORPSE\n    - STR_BIODRONE_CORPSE\n    - STR_TENTACULAT_CORPSE\n    - STR_TRISCENE_CORPSE\n    - STR_HALLUCINOID_CORPSE\n    - STR_XARQUID_CORPSE\n    - STR_ALIEN_ORIGINS\n    - STR_THE_ULTIMATE_THREAT\n    - STR_TLETH_ALIEN_CITY\n    - STR_PLASTIC_AQUA_ARMOR\n    - STR_ION_ARMOR\n    - STR_MAGNETIC_ION_ARMOR\n    - STR_GAUSS_PISTOL_CLIP\n    - STR_GAUSS_RIFLE_CLIP\n    - STR_HEAVY_GAUSS_CLIP\n    - \"\"\n    - STR_VIBRO_BLADE\n    - STR_THERMIC_LANCE\n    - STR_HEAVY_THERMIC_LANCE\n    - STR_AQUATOID_COMMANDER\n    - STR_AQUATOID_NAVIGATOR\n    - STR_AQUATOID_MEDIC\n    - STR_AQUATOID_TECHNICIAN\n    - STR_AQUATOID_SQUAD_LEADER\n    - STR_AQUATOID_SOLDIER\n    - STR_GILLMAN_COMMANDER\n    - STR_GILLMAN_TECHNICIAN\n    - STR_GILLMAN_SQUAD_LEADER\n    - STR_GILLMAN_SOLDIER\n    - STR_LOBSTERMAN_COMMANDER\n    - STR_LOBSTERMAN_NAVIGATOR\n    - STR_LOBSTERMAN_TECHNICIAN\n    - STR_LOBSTERMAN_SQUAD_LEADER\n    - STR_LOBSTERMAN_SOLDIER\n    - STR_TASOTH_SQUAD_LEADER\n    - STR_TASOTH_SOLDIER\n    - STR_CALCINITE_TERRORIST\n    - STR_DEEP_ONE_TERRORIST\n    - STR_BIODRONE_TERRORIST\n    - STR_TENTACULAT_TERRORIST\n    - STR_TRISCENE_TERRORIST\n    - STR_HALLUCINOID_TERRORIST\n    - STR_XARQUID_TERRORIST\n    - \"\"\n  manufacture:\n    - STR_PWT_CANNON\n    - STR_GAUSS_CANNON\n    - STR_SONIC_OSCILLATOR\n    - STR_PULSE_WAVE_TORPEDOES\n    - STR_COELACANTH_GAUSS\n    - STR_DISPLACER_SONIC\n    - STR_DISPLACER_PWT\n    - STR_HWP_DISPLACER_PWT\n    - STR_GAUSS_PISTOL\n    - STR_GAUSS_RIFLE\n    - STR_HEAVY_GAUSS\n    - STR_PARTICLE_DISTURBANCE_SENSOR\n    - STR_MEDI_KIT\n    - STR_MC_DISRUPTOR\n    - STR_SONIC_CANNON\n    - STR_CANNON_POWER_CLIP\n    - STR_SONIC_BLASTA_RIFLE\n    - STR_BLASTA_POWER_CLIP\n    - STR_SONIC_PISTOL\n    - STR_PISTOL_POWER_CLIP\n    - STR_DISRUPTOR_PULSE_LAUNCHER\n    - STR_DISRUPTOR_AMMO\n    - STR_THERMAL_SHOK_LAUNCHER\n    - STR_THERMAL_SHOK_BOMB\n    - STR_SONIC_PULSER\n    - STR_MC_READER\n    - STR_PLASTIC_AQUA_ARMOR\n    - STR_ION_ARMOR\n    - STR_MAGNETIC_ION_ARMOR\n    - STR_AQUA_PLASTICS\n    - STR_ION_BEAM_ACCELERATORS\n    - STR_MAGNETIC_NAVIGATION\n    - STR_MANTA\n    - STR_HAMMERHEAD\n    - STR_LEVIATHAN\n    - STR_GAUSS_PISTOL_CLIP\n    - STR_GAUSS_RIFLE_CLIP\n    - STR_HEAVY_GAUSS_CLIP\n    - STR_VIBRO_BLADE\n    - STR_THERMIC_LANCE\n    - STR_HEAVY_THERMIC_LANCE\n    - STR_GAUSS_CANNON_AMMO\n    - \"\"\n  ufopaedia:\n    - STR_TRITON\n    - STR_HAMMERHEAD\n    - STR_LEVIATHAN\n    - STR_BARRACUDA\n    - STR_MANTA\n    - STR_AJAX\n    - STR_DUP_HEAD\n    - STR_CRAFT_GAS_CANNON_UC\n    - STR_PWT_CANNON_UC\n    - STR_GAUSS_CANNON_UC\n    - STR_SONIC_OSCILLATOR_UC\n    - STR_COELACANTH_GAS_CANNON\n    - STR_COELACANTH_AQUA_JET\n    - STR_COELACANTH_GAUSS\n    - STR_DISPLACER_SONIC\n    - STR_DISPLACER_PWT\n    - STR_PLASTIC_AQUA_ARMOR_UC\n    - STR_ION_ARMOR_UC\n    - STR_MAGNETIC_ION_ARMOR_UC\n    - STR_DART_PISTOL\n    - STR_JET_HARPOON\n    - STR_GAS_CANNON\n    - STR_HYDRO_JET_CANNON\n    - STR_TORPEDO_LAUNCHER\n    - STR_GAUSS_PISTOL\n    - STR_GAUSS_PISTOL_CLIP\n    - STR_GAUSS_RIFLE\n    - STR_GAUSS_RIFLE_CLIP\n    - STR_HEAVY_GAUSS\n    - STR_HEAVY_GAUSS_CLIP\n    - STR_MAGNA_BLAST_GRENADE\n    - STR_DYE_GRENADE\n    - STR_PARTICLE_DISTURBANCE_GRENADE\n    - STR_MAGNA_PACK_EXPLOSIVE\n    - STR_PARTICLE_DISTURBANCE_SENSOR\n    - STR_MEDI_KIT\n    - STR_MC_DISRUPTOR\n    - STR_THERMAL_TAZER\n    - STR_CHEMICAL_FLARE\n    - STR_VIBRO_BLADE\n    - STR_THERMIC_LANCE\n    - STR_HEAVY_THERMIC_LANCE\n    - STR_SONIC_CANNON\n    - STR_CANNON_POWER_CLIP\n    - STR_SONIC_BLASTA_RIFLE\n    - STR_BLASTA_POWER_CLIP\n    - STR_SONIC_PISTOL\n    - STR_PISTOL_POWER_CLIP\n    - STR_DISRUPTOR_PULSE_LAUNCHER\n    - STR_DISRUPTOR_AMMO\n    - STR_THERMAL_SHOK_LAUNCHER\n    - STR_THERMAL_SHOK_BOMB\n    - STR_SONIC_PULSER\n    - STR_ZRBITE\n    - STR_MC_READER\n    - STR_AIR_LOCK\n    - STR_LIVING_QUARTERS\n    - STR_LABORATORY\n    - STR_WORKSHOP\n    - STR_STANDARD_SONAR\n    - STR_WIDE_ARRAY_SONAR\n    - STR_TORPEDO_DEFENSES\n    - STR_GENERAL_STORES\n    - STR_ALIEN_CONTAINMENT\n    - STR_GAUSS_DEFENSES\n    - STR_SONIC_DEFENSES\n    - STR_PWT_DEFENSES\n    - STR_BOMBARDMENT_SHIELD\n    - STR_MC_GENERATOR\n    - STR_MC_LAB\n    - STR_TRANSMISSION_RESOLVER\n    - STR_SUB_PEN\n    - STR_AQUATOID\n    - STR_AQUATOID_AUTOPSY\n    - STR_GILLMAN\n    - STR_GILLMAN_AUTOPSY\n    - STR_LOBSTERMAN\n    - STR_LOBSTERMAN_AUTOPSY\n    - STR_TASOTH\n    - STR_TASOTH_AUTOPSY\n    - STR_CALCINITE\n    - STR_CALCINITE_AUTOPSY\n    - STR_DEEP_ONE\n    - STR_DEEP_ONE_AUTOPSY\n    - STR_BIODRONE\n    - STR_BIODRONE_AUTOPSY\n    - STR_TENTACULAT\n    - STR_TENTACULAT_AUTOPSY\n    - STR_TRISCENE\n    - STR_TRISCENE_AUTOPSY\n    - STR_HALLUCINOID\n    - STR_HALLUCINOID_AUTOPSY\n    - STR_XARQUID\n    - STR_XARQUID_AUTOPSY\n    - STR_ALIEN_ORIGINS\n    - STR_THE_ULTIMATE_THREAT\n    - STR_TLETH_THE_ALIEN_CITY\n    - STR_ALIEN_PROBE_MISSION\n    - STR_ALIEN_INTERDICTION\n    - STR_ALIEN_RESOURCE_RAID\n    - STR_ALIEN_INFILTRATION\n    - STR_ALIEN_BASE\n    - STR_ALIEN_SURFACE_ATTACK\n    - STR_ALIEN_RETALIATION\n    - STR_ALIEN_SUPPLY\n    - STR_ION_BEAM_ACCELERATORS\n    - STR_MAGNETIC_NAVIGATION\n    - STR_ALIEN_SUB_CONSTRUCTION\n    - STR_ALIEN_CRYOGENICS\n    - STR_ALIEN_CLONING\n    - STR_ALIEN_LEARNING_ARRAYS\n    - STR_ALIEN_IMPLANTER\n    - STR_EXAMINATION_ROOM\n    - STR_AQUA_PLASTICS\n    - STR_SURVEY_SHIP\n    - STR_ESCORT\n    - STR_CRUISER\n    - STR_HEAVY_CRUISER\n    - STR_HUNTER\n    - STR_BATTLESHIP\n    - STR_DREADNOUGHT\n    - STR_FLEET_SUPPLY_CRUISER"
  },
  {
    "path": "bin/standard/xcom2/countries.rul",
    "content": "countries: #done\n  - type: STR_USA\n    fundingBase: 600\n    fundingCap: 10000\n    labelLon: 257\n    labelLat: -45\n    areas:   # lonMin lonMax latMin latMax\n      - [266, 83, -63.5, -57]\n      - [297, 39.5, -57, -44]\n      - [217.5, 239, -51, -30]\n  - type: STR_ALASKA\n    fundingBase: 230\n    fundingCap: 8000\n    labelLon: 193.25\n    labelLat: -68.75\n    areas:\n      - [180, 197, -75, -57.5]\n      - [197, 237, -75, -70]\n  - type: STR_EU_SYNDICATE\n    fundingBase: 240\n    fundingCap: 7000\n    labelLon: 355\n    labelLat: -45\n    areas:\n      - [343, 354.5, -61, -43]\n      - [337, 349, -43, -28.5]\n      - [1, 21.5, -45, -36.5]\n  - type: STR_ARABIAN_BLOC\n    fundingBase: 320\n    fundingCap: 8000\n    labelLon: 45\n    labelLat: -5\n    areas:\n      - [21.5, 36.5, -38, -31]\n      - [60, 73, -24, -12.5]\n      - [52, 73, -12.5, -0.5]\n  - type: STR_EGYPTIAN_CARTEL\n    fundingBase: 250\n    fundingCap: 9000\n    labelLon: 18.75\n    labelLat: -26.75\n    areas:\n      - [325, 347, -28.5, -3]\n      - [323, 11, -3, 4]\n      - [1, 21.5, -36.5, -31]\n  - type: STR_AFRICA_CORP\n    fundingBase: 160\n    fundingCap: 6000\n    labelLon: 16.75\n    labelLat: 31.75\n    areas:\n      - [3.5, 18, 4, 42.5]\n      - [18, 38, 34.5, 42.5]\n      - [38, 52, -0.5, 42.5]\n  - type: STR_BRAZILIAN_UNION\n    fundingBase: 140\n    fundingCap: 5000\n    labelLon: 290\n    labelLat: 30\n    areas:\n      - [273, 290, 18, 57]\n      - [296, 310, 30.5, 57]\n      - [310, 323, 23, 40]\n      - [323, 341, 4, 23]\n  - type: STR_NEW_MEXICO\n    fundingBase: 245\n    fundingCap: 7000\n    labelLon: 265\n    labelLat: -10.75\n    areas:\n      - [228, 251, -30, -14]\n      - [245, 273, -14, 7]\n      - [267, 297.5, -30, -17.5]\n  - type: STR_ASIAN_COALITION\n    fundingBase: 400\n    fundingCap: 10000\n    labelLon: 81.25\n    labelLat: -15.25\n    areas:\n      - [72.5, 97, -24, 2]\n  - type: STR_SCANDINAVIA\n    fundingBase: 150\n    fundingCap: 5000\n    labelLon: 20\n    labelLat: -60\n    areas:\n      - [354.5, 5, -67, -57]\n      - [5, 15, -75, -65]\n      - [18, 27, -65, -55]\n  - type: STR_NEO_JAPAN\n    fundingBase: 300\n    fundingCap: 4000\n    labelLon: 142.5\n    labelLat: -41.25\n    areas:\n      - [118.5, 142, -44, -30]\n  - type: STR_FREE_CHINA\n    fundingBase: 280\n    fundingCap: 5000\n    labelLon: 126\n    labelLat: -18\n    areas:\n      - [118.5, 135, -30, -12.5]\n  - type: STR_AUSTRALASIA\n    fundingBase: 180\n    fundingCap: 2000\n    labelLon: 146.25\n    labelLat: 25\n    areas:\n      - [119, 142, 2, 13]\n      - [119, 153, 37, 47]\n      - [153, 170.5, 2, 42]\n  - type: STR_FED_KOREA\n    fundingBase: 310\n    fundingCap: 3000\n    labelLon: 118.75\n    labelLat: -36\n    areas:\n      - [111, 118.5, -24, -3]\n  - type: STR_EURASIA_UC\n    fundingBase: 160\n    fundingCap: 2000\n    labelLon: 60\n    labelLat: -60.75\n    areas:\n      - [135, 168, -62, -44]\n      - [31, 168, -75, -68]\n  - type: STR_ICELANDIC_UNION\n    fundingBase: 110\n    fundingCap: 4000\n    labelLon: 323\n    labelLat: -72\n    areas:\n      - [323, 340, -67, -56]\n      - [340, 250, -74, -65]\n"
  },
  {
    "path": "bin/standard/xcom2/craftWeapons.rul",
    "content": "craftWeapons: #done\n  - type: STR_AJAX\n    sprite: 0\n    sound: 6\n    damage: 60\n    range: 32\n    accuracy: 70\n    reloadCautious: 64\n    reloadStandard: 48\n    reloadAggressive: 32\n    ammoMax: 6\n    launcher: STR_AJAX_LAUNCHER\n    clip: STR_AJAX_TORPEDOES\n    projectileType: 0\n    projectileSpeed: 8\n    underwaterOnly: true\n  - type: STR_DUP_HEAD\n    sprite: 1\n    sound: 7\n    damage: 110\n    range: 50\n    accuracy: 80\n    reloadCautious: 96\n    reloadStandard: 72\n    reloadAggressive: 48\n    ammoMax: 3\n    launcher: STR_DUP_HEAD_LAUNCHER\n    clip: STR_DUP_HEAD_TORPEDOES\n    projectileType: 1\n    projectileSpeed: 8\n    underwaterOnly: true\n  - type: STR_CRAFT_GAS_CANNON_UC\n    sprite: 2\n    sound: 8\n    damage: 15\n    range: 8\n    accuracy: 25\n    reloadCautious: 4\n    reloadStandard: 4\n    reloadAggressive: 4\n    ammoMax: 200\n    rearmRate: 50\n    launcher: STR_CRAFT_GAS_CANNON\n    clip: STR_CRAFT_GAS_CANNON_ROUNDS_X50\n    projectileType: 2\n    projectileSpeed: 8\n    underwaterOnly: true\n  - type: STR_PWT_CANNON_UC\n    sprite: 3\n    sound: 9\n    damage: 200\n    range: 60\n    accuracy: 100\n    reloadCautious: 64\n    reloadStandard: 48\n    reloadAggressive: 32\n    ammoMax: 2\n    launcher: STR_PWT_CANNON\n    clip: STR_PULSE_WAVE_TORPEDOES\n    projectileType: 3\n    projectileSpeed: 8\n    underwaterOnly: true\n  - type: STR_GAUSS_CANNON_UC\n    sprite: 4\n    sound: 10\n    damage: 90\n    range: 20\n    accuracy: 35\n    reloadCautious: 24\n    reloadStandard: 24\n    reloadAggressive: 24\n    ammoMax: 50\n    rearmRate: 50\n    launcher: STR_GAUSS_CANNON\n    clip: STR_GAUSS_CANNON_AMMO\n    projectileType: 4\n    underwaterOnly: true\n  - type: STR_SONIC_OSCILLATOR_UC\n    sprite: 5\n    sound: 11\n    damage: 150\n    range: 55\n    accuracy: 50\n    reloadCautious: 24\n    reloadStandard: 24\n    reloadAggressive: 24\n    ammoMax: 100\n    rearmRate: 100\n    launcher: STR_SONIC_OSCILLATOR\n    projectileType: 5\n    underwaterOnly: true\n"
  },
  {
    "path": "bin/standard/xcom2/crafts.rul",
    "content": "crafts: #done\n  - type: STR_TRITON\n    sprite: 0\n    fuelMax: 1400\n    damageMax: 160\n    speedMax: 790\n    accel: 2\n    soldiers: 14\n    vehicles: 3\n    costBuy: 500000\n    costRent: 500000\n    forceShowInMonthlyCosts: true\n    refuelRate: 50\n    transferTime: 72\n    score: 200\n    maxAltitude: 4\n    battlescapeTerrainData:\n      name: TRITON\n      mapDataSets:\n        - BLANKS\n        - TRITON\n      mapBlocks:\n        - name: TRITON\n          width: 10\n          length: 20\n    deployment:\n      - [5, 7, 0, 4]\n      - [4, 7, 0, 4]\n      - [5, 6, 0, 4]\n      - [4, 6, 0, 4]\n      - [5, 5, 0, 4]\n      - [4, 5, 0, 4]\n      - [5, 4, 0, 4]\n      - [4, 4, 0, 4]\n      - [5, 3, 0, 4]\n      - [4, 3, 0, 4]\n      - [5, 2, 0, 4]\n      - [4, 2, 0, 4]\n      - [3, 7, 0, 4]\n      - [3, 6, 0, 4]\n  - type: STR_BARRACUDA\n    sprite: 3\n    fuelMax: 800\n    damageMax: 120\n    speedMax: 2400\n    accel: 3\n    weapons: 2\n    costRent: 600000\n    forceShowInMonthlyCosts: true\n    costBuy: 600000\n    refuelRate: 50\n    transferTime: 96\n    score: 250\n    maxAltitude: 3\n  - type: STR_MANTA\n    sprite: 4\n    fuelMax: 30\n    damageMax: 400\n    speedMax: 4600\n    accel: 10\n    weapons: 2\n    refuelItem: STR_ZRBITE\n    refuelRate: 5\n    score: 250\n    maxAltitude: 4\n  - type: STR_HAMMERHEAD\n    sprite: 1\n    fuelMax: 60\n    damageMax: 960\n    speedMax: 4030\n    accel: 9\n    weapons: 1\n    soldiers: 12\n    refuelItem: STR_ZRBITE\n    refuelRate: 5\n    score: 300\n    maxAltitude: 4\n    battlescapeTerrainData:\n      name: HAMMER\n      mapDataSets:\n        - BLANKS\n        - HAMMER\n      mapBlocks:\n        - name: HAMMER\n          width: 10\n          length: 10\n    deployment:\n      - [5, 7, 0, 4]\n      - [4, 7, 0, 4]\n      - [3, 7, 0, 4]\n      - [5, 6, 0, 4]\n      - [4, 6, 0, 4]\n      - [3, 6, 0, 4]\n      - [5, 5, 0, 4]\n      - [4, 5, 0, 4]\n      - [3, 5, 0, 4]\n      - [5, 4, 0, 4]\n      - [4, 4, 0, 4]\n      - [3, 4, 0, 4]\n  - type: STR_LEVIATHAN\n    sprite: 2\n    fuelMax: 50\n    damageMax: 1250\n    speedMax: 5800\n    accel: 9\n    weapons: 2\n    soldiers: 26\n    vehicles: 4\n    refuelItem: STR_ZRBITE\n    spacecraft: true\n    refuelRate: 5\n    score: 400\n    maxAltitude: 4\n    battlescapeTerrainData:\n      name: LEVIATH\n      mapDataSets:\n        - BLANKS\n        - LEVIATH\n      mapBlocks:\n        - name: LEVIATH\n          width: 10\n          length: 20\n    deployment:\n      - [5, 10, 0, 4]\n      - [4, 10, 0, 4]\n      - [5, 9, 0, 4]\n      - [4, 9, 0, 4]\n      - [5, 8, 0, 4]\n      - [4, 8, 0, 4]\n      - [5, 7, 0, 4]\n      - [4, 7, 0, 4]\n      - [5, 6, 0, 4]\n      - [4, 6, 0, 4]\n      - [5, 5, 0, 4]\n      - [4, 5, 0, 4]\n      - [5, 4, 0, 4]\n      - [4, 4, 0, 4]\n      - [5, 3, 0, 4]\n      - [4, 3, 0, 4]\n      - [6, 8, 0, 4]\n      - [3, 8, 0, 4]\n      - [6, 7, 0, 4]\n      - [3, 7, 0, 4]\n      - [6, 6, 0, 4]\n      - [3, 6, 0, 4]\n      - [6, 5, 0, 4]\n      - [3, 5, 0, 4]\n      - [6, 4, 0, 4]\n      - [3, 4, 0, 4]\n"
  },
  {
    "path": "bin/standard/xcom2/cutscenes.rul",
    "content": "cutscenes: #done\n  - type: intro\n    videos:\n      - ANIMS/LOGO.VID\n      - ANIMS/INTRO.VID\n    slideshow:\n      musicId: GMNEWINT\n      slides:\n        - imagePath: FLOP_INT/INT00.LBM\n          transitionSeconds: 5\n          caption: STR_INTRO_1\n          captionSize: [320, 10]\n          captionPos: [0, 190]\n          captionColor: 249\n          captionAlign: 1\n        - imagePath: FLOP_INT/INT01.LBM\n          transitionSeconds: 5\n          caption: STR_INTRO_2\n          captionSize: [320, 48]\n          captionPos: [0, 152]\n          captionColor: 249\n        - imagePath: FLOP_INT/INT02.LBM\n          transitionSeconds: 10\n          caption: STR_INTRO_3\n          captionSize: [320, 48]\n          captionPos: [0, 152]\n          captionColor: 249\n        - imagePath: FLOP_INT/INT03.LBM\n          transitionSeconds: 5\n          caption: STR_INTRO_4\n          captionSize: [320, 48]\n          captionPos: [0, 152]\n          captionColor: 249\n        - imagePath: FLOP_INT/INT04.LBM\n          transitionSeconds: 5\n          caption: STR_INTRO_5\n          captionSize: [320, 48]\n          captionPos: [0, 152]\n          captionColor: 249\n        - imagePath: FLOP_INT/INT05.LBM\n          transitionSeconds: 10\n          caption: STR_INTRO_6\n          captionSize: [320, 48]\n          captionPos: [0, 152]\n          captionColor: 249\n        - imagePath: FLOP_INT/INT06.LBM\n          transitionSeconds: 10\n          caption: STR_INTRO_7\n          captionSize: [320, 48]\n          captionPos: [0, 152]\n          captionColor: 249\n        - imagePath: FLOP_INT/INT07.LBM\n          transitionSeconds: 10\n          caption: STR_INTRO_8\n          captionSize: [320, 48]\n          captionPos: [0, 152]\n          captionColor: 249\n        - imagePath: FLOP_INT/INT08.LBM\n          transitionSeconds: 5\n          caption: STR_INTRO_9\n          captionSize: [320, 48]\n          captionPos: [0, 152]\n          captionColor: 249\n        - imagePath: FLOP_INT/INT09.LBM\n          transitionSeconds: 5\n          caption: STR_INTRO_10\n          captionSize: [320, 48]\n          captionPos: [0, 152]\n          captionColor: 249\n        - imagePath: FLOP_INT/INT10.LBM\n          transitionSeconds: 10\n          caption: STR_INTRO_11\n          captionSize: [320, 48]\n          captionPos: [0, 152]\n          captionColor: 249\n        - imagePath: FLOP_INT/INT11.LBM\n          transitionSeconds: 5\n          caption: STR_INTRO_12\n          captionSize: [320, 48]\n          captionPos: [0, 152]\n          captionColor: 249\n        - imagePath: FLOP_INT/INT12.LBM\n          transitionSeconds: 5\n          caption: STR_INTRO_13\n          captionSize: [320, 48]\n          captionPos: [0, 152]\n          captionColor: 249\n        - imagePath: FLOP_INT/INT13.LBM\n          transitionSeconds: 10\n          caption: STR_INTRO_14\n          captionSize: [320, 48]\n          captionPos: [0, 152]\n          captionColor: 249\n        - imagePath: FLOP_INT/INT14.LBM\n          transitionSeconds: 5\n          caption: STR_INTRO_15\n          captionSize: [320, 48]\n          captionPos: [0, 152]\n          captionColor: 249\n        - imagePath: FLOP_INT/INT15.LBM\n          transitionSeconds: 5\n          caption: STR_INTRO_16\n          captionSize: [320, 48]\n          captionPos: [0, 152]\n          captionColor: 249\n        - imagePath: FLOP_INT/INT16.LBM\n          transitionSeconds: 5\n          caption: STR_INTRO_17\n          captionSize: [320, 48]\n          captionPos: [0, 152]\n          captionColor: 249\n        - imagePath: FLOP_INT/INT17.LBM\n          transitionSeconds: 5\n          caption: STR_INTRO_18\n          captionSize: [320, 48]\n          captionPos: [0, 152]\n          captionColor: 249\n        - imagePath: FLOP_INT/INT18.LBM\n          transitionSeconds: 5\n          caption: STR_INTRO_19\n          captionSize: [320, 48]\n          captionPos: [0, 152]\n          captionColor: 249\n        - imagePath: FLOP_INT/INT19.LBM\n          transitionSeconds: 5\n          captionSize: [320, 48]\n          captionPos: [0, 152]\n          captionColor: 249\n        - imagePath: FLOP_INT/INT20.LBM\n          transitionSeconds: 5\n          captionSize: [320, 48]\n          captionPos: [0, 152]\n          captionColor: 249\n  - type: tleth\n    videos:\n      - ANIMS/RISE.VID\n    slideshow:\n      musicId: GMSIG\n      slides:\n        - imagePath: FLOP_INT/TWE01.LBM\n          transitionSeconds: 10\n          caption: STR_RISE_1\n          captionSize: [320, 48]\n          captionPos: [0, 152]\n          captionColor: 249\n        - imagePath: FLOP_INT/TWE02.LBM\n          transitionSeconds: 10\n          caption: STR_RISE_2\n          captionSize: [320, 48]\n          captionPos: [0, 152]\n          captionColor: 249\n        - imagePath: FLOP_INT/TWE03.LBM\n          transitionSeconds: 10\n          caption: STR_RISE_3\n          captionSize: [320, 48]\n          captionPos: [0, 152]\n          captionColor: 249\n        - imagePath: FLOP_INT/TWE04.LBM\n          transitionSeconds: 10\n          caption: STR_RISE_4\n          captionSize: [320, 48]\n          captionPos: [0, 152]\n          captionColor: 249\n        - imagePath: FLOP_INT/TWE05.LBM\n          transitionSeconds: 10\n          caption: STR_RISE_5\n          captionSize: [320, 48]\n          captionPos: [0, 152]\n          captionColor: 249\n        - imagePath: FLOP_INT/TWE06.LBM\n          transitionSeconds: 10\n          caption: STR_RISE_6\n          captionSize: [320, 48]\n          captionPos: [0, 152]\n          captionColor: 249\n  - type: winGame\n    winGame: true\n    videos:\n      - ANIMS/OUTRO.VID\n    slideshow:\n      musicId: GMWIN\n      slides:\n        - imagePath: FLOP_INT/OUT01.LBM\n          transitionSeconds: 10\n          caption: STR_OUTRO_1\n          captionSize: [320, 48]\n          captionPos: [0, 152]\n          captionColor: 249\n        - imagePath: FLOP_INT/OUT02.LBM\n          transitionSeconds: 10\n          caption: STR_OUTRO_2\n          captionSize: [320, 48]\n          captionPos: [0, 152]\n          captionColor: 249\n        - imagePath: FLOP_INT/OUT03.LBM\n          transitionSeconds: 10\n          caption: STR_OUTRO_3\n          captionSize: [320, 48]\n          captionPos: [0, 152]\n          captionColor: 249\n        - imagePath: FLOP_INT/OUT04.LBM\n          transitionSeconds: 10\n          caption: STR_OUTRO_4\n          captionSize: [320, 48]\n          captionPos: [0, 152]\n          captionColor: 249\n        - imagePath: FLOP_INT/OUT05.LBM\n          transitionSeconds: 10\n          caption: STR_OUTRO_5\n          captionSize: [320, 48]\n          captionPos: [0, 152]\n          captionColor: 249\n        - imagePath: FLOP_INT/OUT06.LBM\n          transitionSeconds: 10\n          caption: STR_OUTRO_6\n          captionSize: [320, 48]\n          captionPos: [0, 152]\n          captionColor: 249\n        - imagePath: FLOP_INT/OUT07.LBM\n          transitionSeconds: 10\n          caption: STR_OUTRO_7\n          captionSize: [320, 48]\n          captionPos: [0, 152]\n          captionColor: 249\n        - imagePath: FLOP_INT/OUT08.LBM\n          transitionSeconds: 10\n          caption: STR_OUTRO_8\n          captionSize: [320, 48]\n          captionPos: [0, 152]\n          captionColor: 249\n        - imagePath: FLOP_INT/OUT09.LBM\n          transitionSeconds: 10\n          caption: STR_OUTRO_9\n          captionSize: [320, 48]\n          captionPos: [0, 152]\n          captionColor: 249\n        - imagePath: FLOP_INT/OUT10.LBM\n          transitionSeconds: 10\n          caption: STR_OUTRO_10\n          captionSize: [320, 48]\n          captionPos: [0, 152]\n          captionColor: 249\n        - imagePath: FLOP_INT/OUT11.LBM\n          transitionSeconds: 10\n          caption: STR_OUTRO_11\n          captionSize: [320, 48]\n          captionPos: [0, 152]\n          captionColor: 249\n        - imagePath: FLOP_INT/OUT12.LBM\n          transitionSeconds: 10\n          caption: STR_OUTRO_12\n          captionSize: [320, 48]\n          captionPos: [0, 152]\n          captionColor: 249\n  - type: loseGame\n    loseGame: true\n    videos:\n      - ANIMS/GAMEOVER.VID\n    slideshow:\n      musicId: GMLOSE\n      slides:\n        - imagePath: FLOP_INT/GAO01.LBM\n          transitionSeconds: 10\n          caption: STR_GAMEOVER_1\n          captionSize: [320, 48]\n          captionPos: [0, 152]\n          captionColor: 249\n        - imagePath: FLOP_INT/GAO02.LBM\n          transitionSeconds: 10\n          caption: STR_GAMEOVER_2\n          captionSize: [320, 48]\n          captionPos: [0, 152]\n          captionColor: 249\n        - imagePath: FLOP_INT/GAO03.LBM\n          transitionSeconds: 10\n          caption: STR_GAMEOVER_3\n          captionSize: [320, 48]\n          captionPos: [0, 152]\n          captionColor: 249\n        - imagePath: FLOP_INT/GAO04.LBM\n          transitionSeconds: 10\n          caption: STR_GAMEOVER_4\n          captionSize: [320, 48]\n          captionPos: [0, 152]\n          captionColor: 249\n        - imagePath: FLOP_INT/GAO05.LBM\n          transitionSeconds: 10\n          caption: STR_GAMEOVER_5\n          captionSize: [320, 48]\n          captionPos: [0, 152]\n          captionColor: 249\n"
  },
  {
    "path": "bin/standard/xcom2/difficulty.rul",
    "content": "difficultyCoefficient: [0, 1, 2, 4, 6]\naimAndArmorMultipliers: [0.4, 0.7, 1.0, 1.1, 1.2]\nstatGrowthMultipliers:\n  tu: 8\n  stamina: 8\n  health: 0\n  bravery: 0\n  reactions: 6\n  firing: 6\n  throwing: 0\n  strength: 4\n  psiStrength: 4\n  psiSkill: 4\n  melee: 8\n# for more information on what these numbers mean, see\n# http://ufopaedia.org/index.php?title=Alien_Stats_(TFTD)#Calculating_Statistics\n# statGrowthMultipliers are the increments\n# difficultyCoefficients are MultiplierA\n# aimAndArmorMultipliers are MultiplierB\nturnAIUseGrenade: 2\nturnAIUseBlaster: 2\ndefeatScore: -900\ndefeatFunds: -1000000\nconstants:\n  - damageRange: 50\n  - explosiveDamageRange: 50\n  - fireDamageRange: [5, 10]"
  },
  {
    "path": "bin/standard/xcom2/extraSprites.rul",
    "content": "extraSprites: #done\n  - type: Touch\n    width: 64\n    height: 120\n    subX: 32\n    subY: 24\n    files:\n      0: Resources/Extended/Touch/Touch_TFTD.png\n  - type: oxceLinks\n    width: 32\n    height: 16\n    singleImage: true\n    files:\n      0: Resources/Extended/oxceLinks.png\n  - type: oxceLinksInv\n    width: 23\n    height: 22\n    singleImage: true\n    files:\n      0: Resources/Extended/oxceLinksInv.png\n  - type: TinyRanks\n    width: 42\n    height: 7\n    subX: 7\n    subY: 7\n    files:\n      0: Resources/Extended/TinyRanks.png\n  - type: BACK08.SCR-InfoButton\n    width: 320\n    height: 200\n    singleImage: true\n    files:\n      0: Resources/Extended/Pedia/info-button-tftd.png\n  - type: Pathfinding\n    files:\n      0: Resources/Pathfinding/Pathfinding.png\n    width: 384\n    height: 80\n    subX: 32\n    subY: 40\n  - type: Projectiles\n    width: 105\n    height: 33\n    subX: 3\n    subY: 3\n    files:\n      0: Resources/BulletSprites/TFTD-LAND.png\n  - type: UnderwaterProjectiles\n    width: 105\n    height: 33\n    subX: 3\n    subY: 3\n    files:\n      0: Resources/BulletSprites/TFTD-UNDERWATER.png\n  - type: InvCopy\n    width: 32\n    height: 22\n    singleImage: true\n    files:\n      0: Resources/UI/invcopy_TFTD.png\n  - type: InvCopyActive\n    width: 32\n    height: 22\n    singleImage: true\n    files:\n      0: Resources/UI/invcopy_active_TFTD.png\n  - type: InvPaste\n    width: 32\n    height: 22\n    singleImage: true\n    files:\n      0: Resources/UI/invpaste_TFTD.png\n  - type: InvPasteEmpty\n    width: 32\n    height: 22\n    singleImage: true\n    files:\n      0: Resources/UI/invpaste_empty_TFTD.png\n  - type: GlobeMarkers\n    width: 27\n    height: 3\n    subX: 3\n    subY: 3\n    files:\n      0: Resources/UI/globe_tftd.png\n  - type: BIGOBS.PCK\n    width: 288\n    height: 48\n    subX: 32\n    subY: 48\n    files:\n      66: Resources/Weapons/Terror.png\n  - type: TDXCOM_2.PCK\n    files:\n      233: Resources/Sprite/missing_arm.png\n  - type: WpnActive\n    width: 36\n    height: 52\n    singleImage: true\n    files:\n      0: Resources/UI/WpnActive.png\n"
  },
  {
    "path": "bin/standard/xcom2/facilities.rul",
    "content": "facilities: #done\n  - type: STR_AIR_LOCK\n    spriteShape: 2\n    spriteFacility: 17\n    lift: true\n    buildCost: 300000\n    buildTime: 1\n    monthlyCost: 4000\n    mapName: XBASES00\n  - type: STR_LIVING_QUARTERS\n    spriteShape: 1\n    spriteFacility: 18\n    buildCost: 400000\n    buildTime: 16\n    monthlyCost: 10000\n    personnel: 50\n    mapName: XBASES01\n  - type: STR_LABORATORY\n    spriteShape: 1\n    spriteFacility: 19\n    buildCost: 750000\n    buildTime: 26\n    monthlyCost: 30000\n    labs: 50\n    mapName: XBASES02\n  - type: STR_WORKSHOP\n    spriteShape: 1\n    spriteFacility: 20\n    buildCost: 800000\n    buildTime: 32\n    monthlyCost: 35000\n    workshops: 50\n    mapName: XBASES03\n  - type: STR_STANDARD_SONAR\n    spriteShape: 2\n    spriteFacility: 21\n    buildCost: 500000\n    buildTime: 12\n    monthlyCost: 10000\n    radarRange: 1695\n    radarChance: 10\n    mapName: XBASES04\n  - type: STR_WIDE_ARRAY_SONAR\n    spriteShape: 1\n    spriteFacility: 22\n    buildCost: 800000\n    buildTime: 25\n    monthlyCost: 15000\n    radarRange: 2577\n    radarChance: 20\n    mapName: XBASES05\n  - type: STR_TORPEDO_DEFENSES\n    spriteShape: 2\n    spriteFacility: 23\n    buildCost: 200000\n    buildTime: 16\n    monthlyCost: 5000\n    defense: 500\n    hitRatio: 50\n    fireSound: 12\n    hitSound: 10\n    mapName: XBASES06\n  - type: STR_GENERAL_STORES\n    spriteShape: 1\n    spriteFacility: 24\n    buildCost: 150000\n    buildTime: 10\n    monthlyCost: 5000\n    storage: 50\n    mapName: XBASES07\n  - type: STR_ALIEN_CONTAINMENT\n    spriteShape: 1\n    spriteFacility: 25\n    buildCost: 400000\n    buildTime: 18\n    monthlyCost: 15000\n    aliens: 10\n    mapName: XBASES08\n  - type: STR_GAUSS_DEFENSES\n    requires:\n      - STR_GAUSS_DEFENSES\n    spriteShape: 3\n    spriteFacility: 26\n    buildCost: 400000\n    buildTime: 24\n    monthlyCost: 10000\n    defense: 600\n    hitRatio: 60\n    fireSound: 13\n    hitSound: 10\n    mapName: XBASES09\n  - type: STR_SONIC_DEFENSES\n    requires:\n      - STR_SONIC_DEFENSES\n    spriteShape: 3\n    spriteFacility: 27\n    buildCost: 600000\n    buildTime: 34\n    monthlyCost: 12000\n    defense: 900\n    hitRatio: 70\n    fireSound: 14\n    hitSound: 10\n    mapName: XBASES10\n  - type: STR_PWT_DEFENSES\n    requires:\n      - STR_PWT_DEFENSES\n    spriteShape: 3\n    spriteFacility: 28\n    buildCost: 800000\n    buildTime: 34\n    monthlyCost: 14000\n    defense: 1200\n    hitRatio: 80\n    fireSound: 15\n    hitSound: 10\n    mapName: XBASES11\n  - type: STR_BOMBARDMENT_SHIELD\n    requires:\n      - STR_BOMBARDMENT_SHIELD\n    grav: true\n    spriteShape: 2\n    spriteFacility: 29\n    buildCost: 1200000\n    buildTime: 38\n    monthlyCost: 15000\n    mapName: XBASES12\n  - type: STR_MC_GENERATOR\n    requires:\n      - STR_MC_GENERATOR\n    mind: true\n    spriteShape: 2\n    spriteFacility: 30\n    buildCost: 1300000\n    buildTime: 33\n    monthlyCost: 5000\n    mapName: XBASES13\n  - type: STR_MC_LAB\n    requires:\n      - STR_MC_LAB\n    spriteShape: 1\n    spriteFacility: 31\n    buildCost: 750000\n    buildTime: 24\n    monthlyCost: 16000\n    psiLabs: 10\n    mapName: XBASES14\n  - type: STR_TRANSMISSION_RESOLVER\n    requires:\n      - STR_TRANSMISSION_RESOLVER\n    hyper: true\n    spriteShape: 2\n    spriteFacility: 32\n    buildCost: 1400000\n    buildTime: 26\n    monthlyCost: 30000\n    radarRange: 2759\n    radarChance: 100\n    mapName: XBASES15\n  - type: STR_SUB_PEN\n    spriteShape: 9\n    spriteFacility: 9\n    size: 2\n    buildCost: 200000\n    buildTime: 25\n    monthlyCost: 25000\n    crafts: 1\n    storage: 5 #OXCE bonus because of change in handling craft storage\n    storageTiles: [[-1, -1, -1]]\n    mapName: XBASES16\n"
  },
  {
    "path": "bin/standard/xcom2/globe.rul",
    "content": "globe: #done\n  data: GEODATA/WORLD.DAT\n  oceanPalette: 1\n  countryColor: 245\n  cityColor: 239\n  baseColor: 239\n  lineColor: 111\n  polylines:\n    - [28, -30.375, 29, -27, 29, -24, 31, -21, 30.625, -19, 30.625, -16, 33, -18, 34, -15, 32, -11, 31, -8, 31, -3]\n    - [34, -15, 36, -9, 39, -8, 39, -5, 35, -4]\n    - [308.625, 0, 306, 4, 303, 6, 300, 6.5, 296, 8, 292, 7.5]\n    - [306, 4, 306, 6]\n    - [300, 6.5, 299, 9]\n    - [270, -30, 266, -33, 267, -35, 267, -37, 265, -40]\n    - [266, -33, 264, -35]\n    - [267, -37, 269, -38, 269.5, -41]\n    - [66.25, -24, 67, -26, 69, -29, 74, -31, 77, -34, 76.625, -35, 77, -39]\n    - [72, -20, 74, -23, 74.5, -26, 75, -29, 74, -31, 77, -34, 80, -35, 82, -37]\n    - [28.375, -42, 27, -42.5, 26, -41.5, 24, -41, 22, -41, 20, -42, 19, -42]\n    - [20, -42, 19, -43]\n    - [2.25, -4, 9, -7, 8, -9.625, 8, -11, 6, -13, 4, -14, 1, -14.5, 358, -13, 357, -11]\n    - [9, -7, 11, -9, 13, -10, 15, -9.5]\n    - [40.625, -39, 43, -39, 46, -38.625, 49, -38, 51, -39, 53, -39, 55, -40, 58, -41, 60, -43, 63, -44]\n    - [49, -38, 51, -37, 53, -34]\n    - [120, -36, 118, -35, 116, -34, 115, -33, 113, -32.5, 112, -33, 111, -34, 110, -36, 109.5, -38, 108.5, -38.625, 107, -39, 105, -38.5, 104.5, -38.5, 104.5, -38, 104, -36]\n    - [129.75, 15.125, 131, 16, 132, 16.25, 132.25, 17, 132, 18, 131, 19, 130, 19.125, 128, 18.5, 126.5, 19, 126, 20]\n    - [132, 31, 133, 30, 135, 29.5, 137, 30, 139, 29.625, 140, 29, 140.5, 28, 141, 26]\n  textures:\n    - id: 0\n      terrain:\n        - name: SEABED\n          weight: 75\n        - name: CORAL\n          weight: 25\n    - id: 1\n      terrain:\n        - name: PIPES\n          weight: 50\n        - name: SEABED\n          weight: 25\n        - name: CORAL\n          weight: 25\n    - id: 2\n      terrain:\n        - name: PLANE\n          weight: 50\n        - name: SEABED\n          weight: 25\n        - name: CORAL\n          weight: 25\n    - id: 3\n      terrain:\n        - name: ATLAN\n          weight: 50\n        - name: SEABED\n          weight: 25\n        - name: CORAL\n          weight: 25\n    - id: 4\n      terrain:\n        - name: MU\n          weight: 50\n        - name: SEABED\n          weight: 25\n        - name: CORAL\n          weight: 25\n    - id: 5\n      terrain:\n        - name: GAL\n          weight: 50\n        - name: SEABED\n          weight: 25\n        - name: CORAL\n          weight: 25\n    - id: 6\n      terrain:\n        - name: MSUNK\n          weight: 50\n        - name: SEABED\n          weight: 25\n        - name: CORAL\n          weight: 25\n    - id: 7\n      terrain:\n        - name: VOLC\n          weight: 50\n        - name: SEABED\n          weight: 25\n        - name: CORAL\n          weight: 25\n    - id: 8\n      terrain:\n        - name: CORAL\n          weight: 75\n        - name: SEABED\n          weight: 25\n    - id: 9\n      terrain:\n        - name: VOLC\n          weight: 50\n        - name: SEABED\n          weight: 25\n        - name: CORAL\n          weight: 25\n    - id: 10\n      terrain:\n        - name: MSUNK\n          weight: 50\n        - name: SEABED\n          weight: 25\n        - name: CORAL\n          weight: 25\n    - id: 11\n      terrain:\n        - name: PIPES\n          weight: 50\n        - name: SEABED\n          weight: 25\n        - name: CORAL\n          weight: 25\n    - id: 12\n      terrain:\n        - name: MU\n          weight: 50\n        - name: SEABED\n          weight: 25\n        - name: CORAL\n          weight: 25\n    - id: -1\n      deployments:\n        STR_PORT_TERROR: 100\n    - id: -2\n      deployments:\n        STR_ISLAND_TERROR: 100\n    - id: -3\n      deployments:\n        STR_ARTIFACT_SITE_P1: 100\n    - id: -4\n      deployments:\n        STR_CARGO_SHIP_P1: 50\n        STR_CRUISE_SHIP_P1: 50\n\n"
  },
  {
    "path": "bin/standard/xcom2/interfaces.rul",
    "content": "interfaces: #done\n  - type: mainMenu\n    backgroundImage: BACK01.SCR\n    music: GMWAITLO\n    elements:\n      - id: palette\n        color: 4\n      - id: window\n        color: 1\n      - id: text\n        color: 1\n      - id: button\n        color: 1\n      - id: battlescapeTheme\n        color: 48\n        color2: 48\n        border: 48\n  - type: tests\n    backgroundImage: BACK05.SCR\n    elements:\n      - id: palette\n        color: 6\n      - id: window\n        color: 1\n      - id: heading\n        color: 1\n      - id: text\n        color: 239\n      - id: frames\n        color: 239\n      - id: button1\n        color: 1\n      - id: button2\n        color: 1\n  - type: newBattleMenu\n    backgroundImage: BACK01.SCR\n    elements:\n      - id: palette\n        color: 6\n      - id: window\n        color: 1\n      - id: heading\n        color: 1\n      - id: text\n        color: 239\n      - id: frames\n        color: 239\n      - id: button1\n        color: 1\n      - id: button2\n        color: 1\n      - id: list\n        color: 1\n        color2: 239\n        border: 1\n  - type: newGameMenu\n    backgroundImage: BACK01.SCR\n    elements:\n      - id: palette\n        color: 4\n      - id: window\n        color: 1\n      - id: text\n        color: 1\n      - id: ironman\n        color: 239\n      - id: button\n        color: 1\n  - type: endGameStatistics\n    backgroundImage: BACK01.SCR\n    elements:\n      - id: palette\n        color: 4\n      - id: window\n        color: 1\n      - id: text\n        color: 1\n        color2: 239\n      - id: list\n        color: 1\n        color2: 239\n        border: 1\n      - id: button\n        color: 1\n  - type: optionsMenu\n    backgroundImage: BACK01.SCR\n    elements:\n      - id: palette\n        color: 6\n      - id: window\n        color: 1\n      - id: tooltip\n        color: 239\n        color2: 244\n      - id: button\n        color: 1\n      - id: confirmDefaults\n        color: 1\n      - id: confirmVideo\n        color: 1\n  - type: videoMenu\n    elements:\n      - id: text\n        color: 239\n      - id: resolution\n        color: 1\n      - id: button\n        color: 1\n  - type: audioMenu\n    elements:\n      - id: text\n        color: 239\n      - id: button\n        color: 1\n  - type: controlsMenu\n    elements:\n      - id: button\n        color: 1\n      - id: optionLists\n        color: 1\n        color2: 239\n        border: 239\n  - type: geoscapeMenu\n    elements:\n      - id: text\n        color: 239\n      - id: button\n        color: 1\n  - type: battlescapeMenu\n    elements:\n      - id: text\n        color: 239\n      - id: button\n        color: 1\n  - type: advancedMenu\n    elements:\n      - id: button\n        color: 1\n      - id: optionLists\n        color: 1\n        color2: 239\n        border: 239\n      - id: disabledUserOption\n        color: 3\n  - type: foldersMenu\n    elements:\n      - id: text1\n        color: 239\n      - id: text2\n        color: 1\n  - type: modsMenu\n    backgroundImage: BACK01.SCR\n    elements:\n      - id: palette\n        color: 6\n      - id: window\n        color: 1\n      - id: optionLists\n        color: 1\n        border: 239\n      - id: text\n        color: 239\n      - id: tooltip\n        color: 239\n      - id: button1\n        color: 1\n      - id: button2\n        color: 1\n  - type: modsWindow\n    elements:\n      - id: palette\n        color: 6\n      - id: window\n        color: 239\n      - id: heading\n        color: 239\n      - id: text\n        color: 239\n      - id: button1\n        color: 1\n      - id: button2\n        color: 1\n  - type: saveMenus\n    backgroundImage: BACK01.SCR\n    elements:\n      - id: palette\n        color: 4\n      - id: window\n        color: 1\n      - id: text\n        color: 1\n        color2: 239\n      - id: list\n        color: 1\n        color2: 239\n        border: 1\n      - id: button\n        color: 1\n      - id: confirmLoad\n        color: 1\n      - id: confirmDelete\n        color: 1\n  - type: pauseMenu\n    backgroundImage: BACK01.SCR\n    elements:\n      - id: palette\n        color: 4\n      - id: window\n        color: 1\n      - id: text\n        color: 1\n      - id: button\n        color: 1\n  - type: noteMenu\n    backgroundImage: BACK01.SCR\n    elements:\n      - id: palette\n        color: 4\n      - id: window\n        color: 1\n      - id: text\n        color: 1\n        color2: 239\n      - id: list\n        color: 1\n        color2: 239\n        border: 1\n      - id: button\n        color: 1\n  - type: errorMessages\n    elements:\n      - id: geoscapePalette\n        color: 6\n      - id: battlescapePalette\n        color: -1\n      - id: geoscapeColor\n        color: 1\n      - id: battlescapeColor\n        color: 0\n  - type: geoCraft\n    backgroundImage: BACK12.SCR\n    elements:\n      - id: palette\n        color: 1\n        color2: 6    # oxide\n      - id: window\n        color: 1\n      - id: text1\n        color: 1\n        color2: 244\n        border: 1\n      - id: text2\n        color: 1\n        color2: 244\n        border: 133  # minty green\n      - id: text3\n        color: 1\n        color2: 244\n        border: 239  # bright green\n      - id: list\n        color: 1\n        color2: 239\n        border: 1\n      - id: button\n        color: 1\n  - type: selectMusicTrack\n    backgroundImage: BACK01.SCR\n    elements:\n      - id: palette\n        color: 4\n      - id: window\n        color: 1\n      - id: text\n        color: 1\n      - id: list\n        color: 1\n        color2: 239\n        border: 1\n      - id: button\n        color: 1\n  - type: dogfightExperience\n    backgroundImage: BACK01.SCR\n    elements:\n      - id: palette\n        color: 4     # green\n      - id: window\n        color: 1\n      - id: text1\n        color: 1\n        color2: 244\n        border: 1\n      - id: text2\n        color: 1\n        color2: 244\n        border: 133  # minty green\n      - id: list\n        color: 1\n        color2: 239\n        border: 1\n      - id: button\n        color: 1\n  - type: intercept\n    backgroundImage: BACK12.SCR\n    elements:\n      - id: palette\n        color: 1\n        color2: 6    # oxide\n      - id: window\n        color: 1\n      - id: text1\n        color: 1\n        color2: 244\n        border: 1\n      - id: text2\n        color: 1\n        color2: 244\n        border: 133  # minty green\n      - id: list\n        color: 1\n        color2: 239\n        border: 1\n      - id: disabled\n        color: 3\n      - id: button\n        color: 1\n  - type: ufoTracker\n    backgroundImage: BACK12.SCR\n    elements:\n      - id: palette\n        color: 1\n        color2: 6    # oxide\n      - id: window\n        color: 1\n      - id: text1\n        color: 1\n        color2: 244\n        border: 1\n      - id: text2\n        color: 1\n        color2: 244\n        border: 133  # minty green\n      - id: list\n        color: 1\n        color2: 239\n        border: 1\n      - id: button\n        color: 1\n  - type: craftPatrol\n    backgroundImage: BACK12.SCR\n    elements:\n      - id: palette\n        color: 1\n        color2: 6    # oxide\n      - id: window\n        color: 1\n      - id: text1\n        color: 1\n        color2: 244\n        border: 1\n      - id: button\n        color: 1\n  - type: craftError\n    backgroundImage: BACK12.SCR\n    elements:\n      - id: palette\n        color: 1\n        color2: 6    # oxide\n      - id: window\n        color: 1\n      - id: text1\n        color: 1\n        color2: 244\n        border: 1\n      - id: button\n        color: 1\n  - type: craftPilotError\n    backgroundImage: BACK12.SCR\n    elements:\n      - id: palette\n        color: 1\n        color2: 6    # oxide\n      - id: window\n        color: 1\n      - id: text1\n        color: 1\n        color2: 244\n        border: 1\n      - id: button\n        color: 1\n  - type: targetInfo\n    backgroundImage: BACK01.SCR\n    elements:\n      - id: palette\n        color: 1     # brown\n      - id: window\n        color: 1   # yellow\n      - id: text1\n        color: 1   # bright green\n      - id: text2\n        color: 1  # yellow\n      - id: button\n        color: 1   # minty green\n  - type: confirmDestination\n    backgroundImage: BACK12.SCR\n    elements:\n      - id: palette\n        color: 1     # aqua\n        color2: 1    # oxide\n      - id: window\n        color: 1   # bright green\n      - id: text\n        color: 1   # bright green\n        color2: 1  # yellow\n        border: 1  # minty green\n      - id: button\n        color: 1   # minty green\n  - type: confirmCydonia\n    backgroundImage: BACK12.SCR\n    elements:\n      - id: palette\n        color: 2     # red\n      - id: window\n        color: 1   # minty green\n      - id: button\n        color: 1   # minty green\n      - id: text\n        color: 1   # yellow\n  - type: confirmLanding\n    backgroundImage: BACK15.SCR\n    elements:\n      - id: palette\n        color: 1\n      - id: window\n        color: 1\n      - id: text\n        color: 1\n        color2: 1\n      - id: button\n        color: 1\n  - type: lowFuel\n    backgroundImage: BACK12.SCR\n    elements:\n      - id: palette\n        color: 1\n      - id: text\n        color: 1\n      - id: window\n        color: 1\n      - id: button\n        color: 1\n  - type: UFOInfo\n    backgroundImage: BACK15.SCR\n    elements:\n      - id: palette\n        color: 1     # aqua\n        color2: 1    # aqua\n      - id: window\n        color: 1     # white\n      - id: text\n        color: 1     # white\n        color2: 244  # minty green\n      - id: button\n        color: 1     # white\n        color2: 1    # white\n  - type: UFOLost\n    backgroundImage: BACK15.SCR\n    elements:\n      - id: palette\n        color: 1     # aqua\n        color2: 1    # aqua\n      - id: window\n        color: 1     # white\n      - id: text\n        color: 1     # white\n        color2: 244  # minty green\n      - id: button\n        color: 1     # white\n        color2: 1    # white\n  - type: multipleTargets\n    backgroundImage: BACK15.SCR\n    elements:\n      - id: palette\n        color: 1     # aqua\n        color2: 1    # aqua\n      - id: window\n        color: 1     # white\n      - id: text\n        color: 1     # white\n        color2: 244  # minty green\n      - id: button\n        color: 1     # white\n        color2: 1    # white\n  - type: baseDestroyed\n    backgroundImage: BACK15.SCR\n    elements:\n      - id: palette\n        color: 1     # aqua\n        color2: 1    # aqua\n      - id: window\n        color: 1     # white\n      - id: text\n        color: 1     # white\n        color2: 244  # minty green\n      - id: button\n        color: 1     # white\n        color2: 1    # white\n  - type: dogfightInfo\n    backgroundImage: BACK15.SCR\n    elements:\n      - id: palette\n        color: 4\n      - id: window\n        color: 1\n      - id: text\n        color: 1\n      - id: button\n        color: 1\n  - type: baseDefense\n    backgroundImage: BACK04.SCR\n#    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 2     # red/orange\n      - id: window\n        color: 1   # purple\n      - id: text\n        color: 1   # blue\n      - id: button\n        color: 1   # blue\n  - type: baseDefense_geo\n    backgroundImage: BACK04.SCR\n    elements:\n      - id: palette\n        color: 2\n      - id: window\n        color: 1\n      - id: text\n        color: 1\n        color2: 239\n      - id: button\n        color: 1\n  - type: terrorSite\n    elements:\n      - id: palette\n        color: 7     # pink\n      - id: window\n        color: 1   # minty green\n      - id: text\n        color: 1   # minty green\n      - id: button\n        color: 1   # minty green\n  - type: alienBase\n    backgroundImage: BACK13.SCR\n    elements:\n      - id: palette\n        color: 1     # pink\n      - id: window\n        color: 1   # bright green\n      - id: text\n        color: 1   # minty green\n      - id: button\n        color: 1   # yellow\n  - type: itemsArriving\n    backgroundImage: BACK13.SCR\n    elements:\n      - id: palette\n        color: 3     # yellow\n      - id: window\n        color: 1   # minty green\n      - id: text1\n        color: 1   # minty green\n      - id: text2\n        color: 244   # yellow\n        border: 1  # minty green\n      - id: button\n        color: 1   # minty green\n  - type: geoResearch\n    backgroundImage: BACK05.SCR\n    elements:\n      - id: palette\n        color: 0     # green\n      - id: window\n        color: 1   # bright green\n      - id: text1\n        color: 1   # bright green\n      - id: text2\n        color: 1   # yellow\n      - id: button\n        color: 1   # minty green\n  - type: geoResearchComplete\n    backgroundImage: BACK05.SCR\n    elements:\n      - id: palette\n        color: 0     # green\n      - id: window\n        color: 1   # bright green\n      - id: text1\n        color: 1   # bright green\n      - id: text2\n        color: 1   # yellow\n      - id: button\n        color: 1   # minty green\n  - type: geoResearchRequired\n    backgroundImage: BACK05.SCR\n    elements:\n      - id: palette\n        color: 0     # green\n      - id: window\n        color: 1   # bright green\n      - id: text1\n        color: 1   # bright green\n      - id: text2\n        color: 1   # yellow\n      - id: button\n        color: 1   # minty green\n  - type: trainingFinished\n    backgroundImage: BACK02.SCR\n    elements:\n      - id: palette\n        color: 2     # oxide\n      - id: window\n        color: 1   # bright green\n      - id: text1\n        color: 1   # bright green\n      - id: text2\n        color: 1   # yellow\n      - id: button\n        color: 1   # minty green\n  - type: geoNewCraft\n    backgroundImage: BACK13.SCR\n    elements:\n      - id: palette\n        color: 2     # oxide\n      - id: window\n        color: 1   # bright green\n      - id: text1\n        color: 1   # bright green\n      - id: text2\n        color: 1   # yellow\n      - id: button\n        color: 1   # minty green\n  - type: geoNewFacility\n    backgroundImage: BACK13.SCR\n    elements:\n      - id: palette\n        color: 2     # oxide\n      - id: window\n        color: 1   # bright green\n      - id: text1\n        color: 1   # bright green\n      - id: text2\n        color: 1   # yellow\n      - id: button\n        color: 1   # minty green\n  - type: geoNewItem\n    backgroundImage: BACK13.SCR\n    elements:\n      - id: palette\n        color: 2     # oxide\n      - id: window\n        color: 1   # bright green\n      - id: text1\n        color: 1   # bright green\n      - id: text2\n        color: 1   # yellow\n      - id: button\n        color: 1   # minty green\n  - type: geoManufacture\n    backgroundImage: BACK17.SCR\n    elements:\n      - id: palette\n        color: 2     # oxide\n      - id: window\n        color: 1   # bright green\n      - id: text1\n        color: 1   # bright green\n      - id: text2\n        color: 1   # yellow\n      - id: button\n        color: 1   # minty green\n  - type: geoManufactureComplete\n    backgroundImage: BACK17.SCR\n    elements:\n      - id: palette\n        color: 2     # oxide\n      - id: window\n        color: 1   # bright green\n      - id: text1\n        color: 1   # bright green\n      - id: text2\n        color: 1   # yellow\n      - id: button\n        color: 1   # minty green\n      - id: list\n        color: 239\n        color2: 1\n        border: 1\n  - type: dogfight\n    elements:\n      - id: button1\n        color: 1\n        TFTDMode: true\n      - id: minimizeButtonDummy\n        color: 1\n        TFTDMode: true\n      - id: standoffButton\n        color: 1\n        pos: [84, 4]\n        size: [35, 14]\n        TFTDMode: true\n      - id: cautiousButton\n        color: 1\n        pos: [121, 4]\n        size: [35, 14]\n        TFTDMode: true\n      - id: standardButton\n        color: 1\n        pos: [84, 20]\n        size: [35, 14]\n        TFTDMode: true\n      - id: aggressiveButton\n        color: 1\n        pos: [121, 20]\n        size: [35, 14]\n        TFTDMode: true\n      - id: disengageButton\n        color: 1\n        pos: [121, 36]\n        size: [35, 14]\n        TFTDMode: true\n      - id: ufoButton\n        color: 1\n        pos: [121, 52]\n        size: [35, 14]\n        TFTDMode: true\n      - id: text\n        color: 1\n      - id: numbers\n        color: 244\n      - id: distance\n        color: 244\n        pos: [123, 73]\n      - id: oceanIndicator\n        color: 239\n        pos: [151, 73]\n      - id: minimizedNumber\n        color: 80\n      - id: radarDetail\n        color: 160\n        color2: 124\n      - id: craftRange\n        color: 1\n        color2: 8\n      - id: radarRange\n        color: 160\n        color2: 176\n      - id: damageRange\n        color: 125\n        color2: 126\n      - id: disabledWeapon\n        color: 32\n        color2: 2\n      - id: disabledAmmo\n        color: 20\n      - id: shieldRange\n        color: 224\n        color2: 229\n      - id: previewTop\n        pos: [0, 96]\n        size: [160, 17]\n      - id: previewBot\n        pos: [0, 113]\n        size: [160, 21]\n      - id: previewMid\n        pos: [0, 134]\n        size: [160, 58]\n  - type: baseNaming\n    backgroundImage: BACK01.SCR\n    elements:\n      - id: palette\n        color: 4\n      - id: window\n        color: 1\n      - id: text\n        color: 1\n      - id: button\n        color: 1\n  - type: monthlyReport\n    backgroundImage: BACK13.SCR\n    elements:\n      - id: palette\n        color: 3\n      - id: window\n        color: 1   # bright green\n        color2: 1  # yellow\n      - id: text1\n        color: 1   # bright green\n        color2: 239  # yellow\n      - id: text2\n        color: 239   # yellow\n      - id: button\n        color: 1   # bright green\n  - type: psiTraining\n    backgroundImage: BACK01.SCR\n    palette: PAL_GEOSCAPE\n    elements:\n      - id: palette\n        color: 4     # violet\n      - id: window\n        color: 1   # purple\n      - id: text\n        color: 1   # light blue\n      - id: button1\n        color: 1   # purple\n      - id: button2\n        color: 1   # light blue\n  - type: martialTraining\n    backgroundImage: BACK02.SCR\n    palette: PAL_GEOSCAPE\n    elements:\n      - id: palette\n        color: 4     # violet\n      - id: window\n        color: 1   # purple\n      - id: text\n        color: 1   # light blue\n      - id: button1\n        color: 1   # purple\n      - id: button2\n        color: 1   # light blue\n  - type: allocatePsi\n    backgroundImage: BACK01.SCR\n    palette: PAL_GEOSCAPE\n    elements:\n      - id: palette\n        color: 4     # violet\n      - id: window\n        color: 1   # blue\n      - id: text\n        color: 1   # blue\n        color2: 1  # white\n      - id: list\n        color: 239   # purple\n        color2: 239  # yellow\n        border: 1  # blue\n      - id: button\n        color: 1   # blue\n  - type: allocateMartial\n    backgroundImage: BACK02.SCR\n    palette: PAL_GEOSCAPE\n    elements:\n      - id: palette\n        color: 4     # violet\n      - id: window\n        color: 1   # blue\n      - id: text\n        color: 1   # blue\n        color2: 1  # white\n      - id: list\n        color: 239   # purple\n        color2: 239  # yellow\n        border: 1  # blue\n      - id: button\n        color: 1   # blue\n  - type: fundingWindow\n    backgroundImage: BACK13.SCR\n    elements:\n      - id: palette\n        color: 3\n      - id: window\n        color: 1\n      - id: text1\n        color: 1\n      - id: text2\n        color: 1\n      - id: list\n        color: 244\n        color2: 244\n      - id: button\n        color: 1\n  - type: oxceLinks\n    backgroundImage: BACK01.SCR\n    elements:\n      - id: palette\n        color: 4\n      - id: window\n        color: 1\n      - id: text\n        color: 1\n      - id: button\n        color: 1\n  - type: geoscapeEvent\n    elements:\n      - id: palette\n        color: 1\n      - id: window\n        color: 1\n      - id: text1\n        color: 244\n        color2: 1\n      - id: text2\n        color: 1\n        color2: 239\n      - id: list\n        color: 239\n        color2: 244\n        border: 1\n      - id: button\n        color: 1\n  - type: graphs\n    palette: PAL_GRAPHS\n    elements:\n      - id: text\n        color: 1     # white\n      - id: scale\n        color: 103   # minty green\n      - id: graph\n        color: 160   # green\n      - id: button\n        color: 2   # grey\n        TFTDMode: true\n      - id: regionTotal\n        color: 133    # salmon (inverted button offset)\n        color2: 136  # also salmon (the line itself)\n      - id: countryTotal\n        color: 141    # magenta (inverted button offset)\n        color2: 144  # also magenta (the line itself)\n  - type: ufopaedia\n    backgroundImage: BACK01.SCR\n    elements:\n      - id: palette\n        color: 4\n      - id: window\n        color: 1\n      - id: text\n        color: 1\n      - id: list\n        color: 1\n        color2: 239\n        border: 1\n      - id: listExtended\n        color: 156\n        color2: 244\n        border: 1\n      - id: button1\n        color: 1\n      - id: button2\n        color: 1\n  - type: promotions\n    backgroundImage: BACK01.SCR\n    elements:\n      - id: palette\n        color: 4     # green\n      - id: window\n        color: 1   # bright green\n      - id: heading\n        color: 1   # minty green\n      - id: text\n        color: 1   # bright green\n      - id: list\n        color: 239   # yellow\n      - id: button\n        color: 1   # bright green\n  - type: cannotReequip\n    backgroundImage: BACK01.SCR\n    elements:\n      - id: palette\n        color: 4     # green\n      - id: window\n        color: 1   # bright green\n      - id: heading\n        color: 1   # minty green\n      - id: text\n        color: 1   # bright green\n      - id: list\n        color: 239   # yellow\n      - id: button\n        color: 1   # bright green\n  - type: debriefing\n    backgroundImage: BACK01.SCR\n    elements:\n      - id: palette\n        color: 4     # green\n      - id: window\n        color: 1     # white\n      - id: heading\n        color: 1     # white\n      - id: text\n        color: 1     # white\n      - id: list\n        color: 1     # white\n        color2: 1    # white\n        custom: 254\n      - id: totals\n        color: 1     # white\n      - id: button\n        color: 1     # white\n      - id: errorPalette\n        color: 1     # brown\n      - id: errorMessage\n        color: 1     # white\n  - type: commendations\n    backgroundImage: BACK01.SCR\n    elements:\n      - id: palette\n        color: 4     # green\n      - id: window\n        color: 1   # bright green\n      - id: heading\n        color: 1   # minty green\n      - id: list\n        color: 1   # bright green\n        color2: 239   # yellow\n      - id: button\n        color: 1   # bright green\n  - type: commendationsLate\n    backgroundImage: BACK02.SCR\n    music: GMDEBPOR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 1     # violet\n      - id: window\n        color: 1     # blue\n      - id: text\n        color: 1   # blue\n        color2: 244  # white\n      - id: list\n        color: 244   # purple\n        color2: 1    # blue\n        border: 1  # blue\n      - id: button\n        color: 1   # blue\n  - type: geoscape\n    backgroundImage: BACK01.SCR\n    elements:\n      - id: palette\n        color: 4     # brown\n        color2: 4\n      - id: textLoad\n        color: 239   # minty green\n      - id: button\n        color: 2   # light blue\n        color2: 1  # slightly lighter blue\n        TFTDMode: true\n      - id: text\n        color: 1   # even lighter blue\n      - id: slackingIndicator\n        color: 1     # white\n        color2: 239  # light blue\n        custom: -12  # above Intercept button\n      - id: trainingIndicator\n        color: 1     # white\n        color2: 239  # light blue\n        custom: 4  # below standard visible area\n      - id: genericWindow\n        color: 1\n      - id: genericText\n        color: 1\n        color2: 239  # yellow\n        border: 1  # minty green\n      - id: genericButton1\n        color: 1   # minty green\n      - id: genericButton2\n        color: 1   # bright green\n      - id: errorPalette\n        color: 6     # brown\n      - id: errorMessage\n        color: 1   # even lighter blue\n  - type: sellMenu\n    backgroundImage: BACK13.SCR\n    palette: PAL_GEOSCAPE\n    elements:\n      - id: palette\n        color: 6\n      - id: window\n        color: 1\n      - id: text\n        color: 1\n        color2: 244\n      - id: list\n        color: 244\n        color2: 239\n        border: 1\n      - id: ammoColor\n        color: 1\n      - id: button\n        color: 1\n      - id: button2\n        color: 244\n      - id: touchButton\n        color: 244\n  - type: dependencyTree\n    backgroundImage: BACK13.SCR\n    palette: PAL_GEOSCAPE\n    elements:\n      - id: palette\n        color: 6\n      - id: window\n        color: 1\n      - id: text\n        color: 1\n        color2: 244\n      - id: list\n        color: 244\n        color2: 239\n        border: 1\n      - id: button\n        color: 1\n  - type: itemLocations\n    backgroundImage: BACK13.SCR\n    palette: PAL_GEOSCAPE\n    elements:\n      - id: palette\n        color: 6\n      - id: window\n        color: 1\n      - id: text\n        color: 1\n        color2: 244\n      - id: list\n        color: 244\n        color2: 239\n        border: 1\n      - id: button\n        color: 1\n  - type: buyMenu\n    backgroundImage: BACK13.SCR\n    elements:\n      - id: palette\n        color: 6     # blue\n      - id: window\n        color: 1   # blue\n      - id: text\n        color: 1   # blue\n        color2: 244  # white\n      - id: list\n        color: 244   # blue\n        color2: 239   # purple\n        border: 1\n      - id: ammoColor\n        color: 1  # white\n      - id: button\n        color: 1   # blue\n      - id: button2\n        color: 244\n      - id: touchButton\n        color: 244\n      - id: errorPalette\n        color: 6     # brown\n      - id: errorMessage\n        color: 1   # pink\n        color2: 244\n  - type: manageContainment\n    backgroundImage: BACK05.SCR\n    elements:\n      - id: palette\n        color: 0     # burgundy\n      - id: window\n        color: 1   # blue\n      - id: text\n        color: 1   # blue\n        color2: 239  # white\n      - id: list\n        color: 1   # white\n        color2: 239  # blue\n        border: 1  # blue\n      - id: button\n        color: 1   # blue\n      - id: button2\n        color: 244\n      - id: touchButton\n        color: 244\n      - id: errorPalette\n        color: 6     # oxide\n      - id: errorMessage\n        color: 1   # pink\n  - type: globalContainmentMenu\n    backgroundImage: BACK05.SCR\n    elements:\n      - id: palette\n        color: 0\n      - id: window\n        color: 1\n      - id: text\n        color: 1\n        color2: 239\n      - id: list\n        color: 239\n        color2: 1\n        border: 1\n      - id: button\n        color: 1\n  - type: transferBaseSelect\n    backgroundImage: BACK13.SCR\n    elements:\n      - id: palette\n        color: 6     # blue\n      - id: window\n        color: 1   # gold\n      - id: button\n        color: 1   # gold\n      - id: text\n        color: 1   # gold\n        color2: 239  # white\n      - id: list\n        color: 244   # pink\n        color2: 244  # gold\n        border: 1\n  - type: transferMenu\n    backgroundImage: BACK13.SCR\n    elements:\n      - id: palette\n        color: 6     # brown\n      - id: window\n        color: 1   # blue\n      - id: text\n        color: 1   # blue\n      - id: list\n        color: 244   # blue\n        color2: 1  # white\n        border: 1\n      - id: ammoColor\n        color: 239   # purple\n      - id: button\n        color: 1   # purple\n      - id: button2\n        color: 244\n      - id: touchButton\n        color: 244\n      - id: errorPalette\n        color: 6     # brown\n      - id: errorMessage\n        color: 1   # pink\n  - type: transferConfirm\n    backgroundImage: BACK13.SCR\n    elements:\n      - id: palette\n        color: 6     # oxide\n      - id: window\n        color: 1   # gold\n      - id: button\n        color: 1   # purple\n      - id: text\n        color: 1   # blue\n        color2: 1  # pink\n  - type: transferInfo\n    backgroundImage: BACK13.SCR\n    elements:\n      - id: palette\n        color: 6\n      - id: window\n        color: 1\n      - id: button\n        color: 1\n      - id: text\n        color: 1\n      - id: list\n        color: 244\n        border: 1\n  - type: selectFacility\n    backgroundImage: BACK05.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 0\n      - id: window\n        color: 1\n      - id: button\n        color: 1\n      - id: text\n        color: 1\n      - id: list\n        color: 1\n        color2: 244\n  - type: placeFacility\n    backgroundImage: BACK01.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 0\n      - id: window\n        color: 1\n      - id: button\n        color: 1\n      - id: text\n        color: 1\n      - id: numbers\n        color: 244\n      - id: errorPalette\n        color: 0\n      - id: errorMessage\n        color: 1\n  - type: dismantleFacility\n    backgroundImage: BACK13.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 6     # oxide\n      - id: window\n        color: 1\n      - id: button\n        color: 1\n      - id: text\n        color: 1\n        color2: 81\n  - type: manufactureMenu\n    backgroundImage: BACK17.SCR\n    elements:\n      - id: palette\n        color: 2     # oxide\n      - id: window\n        color: 1   # purple\n      - id: text1\n        color: 1   # purple\n        color2: 244  # white\n      - id: text2\n        color: 1   # pink\n      - id: list\n        color: 244   # blue\n        border: 1  # purple\n      - id: button\n        color: 1   # blue\n  - type: globalManufactureMenu\n    backgroundImage: BACK17.SCR\n    elements:\n      - id: palette\n        color: 2\n      - id: window\n        color: 1\n      - id: text1\n        color: 1\n        color2: 244\n      - id: text2\n        color: 1\n      - id: list\n        color: 244\n        color2: 1\n        border: 1\n      - id: button\n        color: 1\n  - type: selectNewManufacture\n    backgroundImage: BACK17.SCR\n    parent: manufactureMenu\n    elements:\n      - id: window\n        color: 1   # pink\n      - id: text\n        color: 1   # pink\n      - id: list\n        color: 1\n        color2: 239\n        border: 1  # pink\n      - id: listExtended\n        color: 156\n        color2: 244\n      - id: button\n        color: 1   # blue\n      - id: button2\n        color: 244\n      - id: touchButton\n        color: 244\n      - id: catBox\n        color: 1   # pink\n  - type: allocateManufacture\n    backgroundImage: BACK17.SCR\n    parent: manufactureMenu\n    elements:\n      - id: window\n        color: 1   # blue\n      - id: text\n        color: 1   # blue\n        color2: 244  # white\n      - id: list\n        color: 1   # blue\n        color2: 244  # white\n      - id: button\n        color: 1   # blue\n  - type: manufactureInfo\n    backgroundImage: BACK17.SCR\n    parent: manufactureMenu\n    elements:\n      - id: window\n        color: 1   # pink\n      - id: text\n        color: 1   # pink\n        color2: 244  # white\n      - id: list\n        color: 1   # blue\n        color2: 244  # white\n      - id: button1\n        color: 1   # pink\n      - id: button2\n        color: 1   # purple\n  - type: researchMenu\n    backgroundImage: BACK05.SCR\n    elements:\n      - id: palette\n        color: 0     # green\n      - id: window\n        color: 1     # blue\n      - id: text\n        color: 1   # blue\n        color2: 239  # white\n      - id: list\n        color: 239   # purple\n        border: 1  # blue\n      - id: button\n        color: 1   # purple\n  - type: globalResearchMenu\n    backgroundImage: BACK05.SCR\n    elements:\n      - id: palette\n        color: 0\n      - id: window\n        color: 1\n      - id: text\n        color: 1\n        color2: 239\n      - id: list\n        color: 239\n        color2: 1\n        border: 1\n      - id: button\n        color: 1\n  - type: globalResearchDiary\n    backgroundImage: BACK05.SCR\n    elements:\n      - id: palette\n        color: 0\n      - id: window\n        color: 1\n      - id: text\n        color: 1\n        color2: 239\n      - id: list\n        color: 239\n        color2: 1\n        border: 1\n      - id: button\n        color: 1\n  - type: selectNewResearch\n    backgroundImage: BACK05.SCR\n    parent: researchMenu\n    elements:\n      - id: window\n        color: 1   # blue\n      - id: text\n        color: 1   # blue\n      - id: list\n        color: 1   # white\n        color2: 239\n        border: 1  # blue\n      - id: listExtended\n        color: 156\n        color2: 244\n      - id: button\n        color: 1   # purple\n      - id: button2\n        color: 244\n      - id: touchButton\n        color: 244\n  - type: allocateResearch\n    backgroundImage: BACK05.SCR\n    parent: researchMenu\n    elements:\n      - id: window\n        color: 1   # gold\n      - id: text\n        color: 1   # gold\n        color2: 1  # white\n      - id: button1\n        color: 1   # gold\n      - id: button2\n        color: 1   # blue\n  - type: techTreeViewer\n    backgroundImage: BACK05.SCR\n    elements:\n      - id: palette\n        color: 0     # green\n      - id: window\n        color: 1     # blue\n      - id: text\n        color: 1   # blue\n        color2: 244  # white\n      - id: list\n        color: 3     # purple -> grey\n        color2: 239  # pink   -> light blue\n        border: 1    # blue   -> white\n      - id: listExtended\n        color: 244   # white  -> light green\n        color2: 146  # gold   -> gold\n        border: 8    # grey   -> bright red\n      - id: button\n        color: 1   # purple\n  - type: techTreeSelect\n    backgroundImage: BACK05.SCR\n    parent: techTreeViewer\n    elements:\n      - id: window\n        color: 1   # gold\n      - id: text\n        color: 1   # gold\n        color2: 1  # white\n      - id: list\n        color: 3\n        color2: 239\n        border: 1  # blue\n      - id: button\n        color: 1   # blue\n  - type: baseInfo\n    elements:\n      - id: palette\n      - id: text1\n        color: 1\n      - id: text2\n        color: 1\n      - id: numbers\n        color: 244\n      - id: button\n        color: 1\n      - id: personnelBars\n        color: 123\n        border: 124\n      - id: facilityBars\n        color: 157\n        border: 158\n      - id: defenceBar\n        color: 10\n        border: 12\n      - id: detectionBars\n        color: 128\n        border: 129\n  - type: storesInfo\n    backgroundImage: BACK13.SCR\n    elements:\n      - id: palette\n        color: 6\n      - id: window\n        color: 1\n      - id: text\n        color: 1\n      - id: list\n        color: 244\n        border: 1\n      - id: button\n        color: 1\n  - type: costsInfo\n    backgroundImage: BACK13.SCR\n    elements:\n      - id: palette\n        color: 3\n      - id: window\n        color: 1\n      - id: text1\n        color: 1\n        color2: 1\n      - id: text2\n        color: 1\n      - id: list\n        color: 244\n        color2: 1\n      - id: button\n        color: 1\n  - type: soldierList\n    backgroundImage: BACK02.SCR\n    elements:\n      - id: palette\n        color: 2\n      - id: window\n        color: 1\n      - id: text1\n        color: 1\n      - id: text2\n        color: 1\n      - id: list\n        color: 244\n        color2: 239\n        border: 1\n      - id: button\n        color: 1\n  - type: soldierInfo\n    elements:\n      - id: palette\n      - id: text1\n        color: 1     # blue\n        color2: 244  # white\n      - id: text2\n        color: 1   # pink\n      - id: numbers\n        color: 244   # white\n        color2: 244   # white\n      - id: button\n        color: 1   # purple\n      - id: barTUs\n        color: 144\n        color2: 148\n        border: 151\n      - id: barEnergy\n        color: 111\n        color2: 115\n        border: 116\n      - id: barHealth\n        color: 5\n        color2: 9\n        border: 12\n      - id: barBravery\n        color: 254\n        color2: 2\n        border: 4\n      - id: barReactions\n        color: 35\n        color2: 39\n        border: 40\n      - id: barFiring\n        color: 12\n        color2: 16\n        border: 24\n      - id: barThrowing\n        color: 241\n        color2: 245\n        border: 248\n      - id: barMelee\n        color: 111\n        color2: 115\n        border: 116\n      - id: barStrength\n        color: 254\n        color2: 2\n        border: 4\n      - id: barMana\n        color: 240\n        color2: 241\n        border: 243\n      - id: barPsiStrength\n        color: 1\n        color2: 2\n        border: 4\n      - id: barPsiSkill\n        color: 1\n        color2: 2\n        border: 4\n      - id: errorPalette\n        color: 0     # brown\n      - id: errorMessage\n        color: 1   # pink\n  - type: sackSoldier\n    backgroundImage: BACK13.SCR\n    elements:\n      - id: palette\n        color: 6     # oxide\n      - id: window\n        color: 1   # pink\n      - id: text\n        color: 1   # blue\n      - id: button\n        color: 1   # purple\n  - type: soldierArmor\n    backgroundImage: BACK14.SCR\n    elements:\n      - id: palette\n        color: 4     # green\n      - id: window\n        color: 1     # white\n      - id: text\n        color: 1     # white\n        color2: 239  # blue\n      - id: list\n        color: 1   # white\n        border: 1  # white\n      - id: button\n        color: 1   # white\n  - type: soldierTransform\n    backgroundImage: BACK14.SCR\n    elements:\n      - id: palette\n        color: 4     # green\n      - id: window\n        color: 1     # white\n      - id: text\n        color: 1     # white\n        color2: 239  # blue\n      - id: list\n        color: 1   # white\n        border: 1  # white\n      - id: button\n        color: 1   # white\n  - type: soldierRank\n    backgroundImage: BACK14.SCR\n    elements:\n      - id: palette\n        color: 4     # green\n      - id: window\n        color: 1     # white\n      - id: text\n        color: 1     # white\n      - id: list\n        color: 1     # white\n        color2: 244  # green\n        border: 1    # white\n      - id: button\n        color: 1     # white\n  - type: soldierAvatar\n    backgroundImage: BACK14.SCR\n    elements:\n      - id: palette\n        color: 4     # green\n      - id: window\n        color: 1     # white\n      - id: text\n        color: 1     # white\n        color2: 239  # blue\n      - id: list\n        color: 1   # white\n        border: 1  # white\n      - id: button\n        color: 1   # white\n  - type: soldierDiaryLight\n    backgroundImage: BACK14.SCR\n    elements:\n      - id: palette\n        color: 4     # green\n      - id: window\n        color: 1     # white\n      - id: text\n        color: 1     # white\n        color2: 239  # blue\n      - id: list\n        color: 1   # white\n        border: 1  # white\n      - id: button\n        color: 1   # white\n  - type: soldierBonus\n    backgroundImage: BACK14.SCR\n    elements:\n      - id: palette\n        color: 4     # green\n      - id: window\n        color: 1     # white\n      - id: text\n        color: 1     # white\n        color2: 239  # blue\n      - id: list\n        color: 1   # white\n        border: 1  # white\n      - id: button\n        color: 1   # white\n  - type: soldierMemorial\n    backgroundImage: BACK02.SCR\n    music: GMDEBPOR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 1     # violet\n      - id: window\n        color: 1     # blue\n      - id: text\n        color: 1   # blue\n        color2: 244  # white\n      - id: list\n        color: 244   # purple\n        color2: 1    # blue\n        border: 1  # blue\n      - id: button\n        color: 1   # blue\n  - type: soldierDiary\n    backgroundImage: BACK02.SCR\n    elements:\n      - id: palette\n        color: 6\n      - id: window\n        color: 1\n      - id: text1\n        color: 1\n      - id: text2\n        color: 1\n        color2: 244\n      - id: text3\n        color: 244\n      - id: list\n        color: 244\n        color2: 1\n        border: 1\n      - id: button\n        color: 1\n  - type: soldierDiaryPerformance\n    backgroundImage: BACK02.SCR\n    elements:\n      - id: palette\n        color: 6\n      - id: window\n        color: 1\n      - id: text1\n        color: 1\n      - id: text2\n        color: 1\n        color2: 244\n      - id: list\n        color: 244\n        color2: 1\n        border: 1\n      - id: button\n        color: 1\n  - type: soldierDiaryMission\n    backgroundImage: BACK16.SCR\n    elements:\n      - id: palette\n        color: 4     # burgundy\n      - id: window\n        color: 1   # blue\n      - id: text\n        color: 1   # gold\n        color2: 239  # white\n      - id: list\n        color: 239   # white\n        border: 1  # gold\n      - id: button\n        color: 1   # gold\n  - type: craftEquipment\n    backgroundImage: BACK04.SCR\n    elements:\n      - id: palette\n        color: 2\n      - id: window\n        color: 1\n      - id: text\n        color: 1\n        color2: 244\n      - id: button\n        color: 1\n      - id: button2\n        color: 244\n      - id: touchButton\n        color: 244\n      - id: list\n        color: 244\n        color2: 239\n        border: 1\n      - id: ammoColor\n        color: 1\n      - id: errorPalette\n        color: 2\n      - id: errorMessage\n        color: 1\n  - type: craftEquipmentSave\n    backgroundImage: BACK04.SCR\n    parent: craftEquipment\n    elements:\n      - id: window\n        color: 1\n      - id: text\n        color: 1\n        color2: 244\n      - id: button\n        color: 1\n      - id: list\n        color: 244\n        color2: 239\n        border: 1\n  - type: craftEquipmentLoad\n    backgroundImage: BACK04.SCR\n    parent: craftEquipment\n    elements:\n      - id: window\n        color: 1\n      - id: text\n        color: 1\n        color2: 244\n      - id: button\n        color: 1\n      - id: list\n        color: 244\n        color2: 239\n        border: 1\n  - type: craftArmor\n    backgroundImage: BACK14.SCR\n    elements:\n      - id: palette\n        color: 4     # aqua\n      - id: window\n        color: 1     # blue\n      - id: text\n        color: 1     # blue\n      - id: button\n        color: 1     # blue\n      - id: button2\n        color: 244\n      - id: touchButton\n        color: 244\n      - id: list\n        color: 1     # white\n        color2: 239  # blue\n      - id: otherCraft\n        color: 239   # blue\n  - type: craftInfo\n    backgroundImage: BACK14.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 4\n      - id: window\n        color: 1\n      - id: text1\n        color: 1\n        color2: 244\n      - id: text2\n        color: 1\n      - id: text3\n        color: 1\n        color2: 244\n      - id: button\n        color: 1\n  - type: craftWeapons\n    backgroundImage: BACK14.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 4\n      - id: window\n        color: 1\n      - id: text\n        color: 1\n        color2: 244\n      - id: list\n        color: 244\n      - id: button\n        color: 1\n      - id: errorPalette\n        color: 4\n      - id: errorMessage\n        color: 1\n  - type: craftSoldiers\n    backgroundImage: BACK02.SCR\n    elements:\n      - id: palette\n        color: 2\n      - id: window\n        color: 1\n      - id: text\n        color: 1\n        color2: 239\n      - id: otherCraft\n        color: 244\n      - id: list\n        color: 244\n        color2: 239\n        border: 1\n      - id: button\n        color: 1\n      - id: button2\n        color: 244\n      - id: touchButton\n        color: 244\n  - type: craftPilots\n    backgroundImage: BACK02.SCR\n    elements:\n      - id: palette\n        color: 3\n      - id: window\n        color: 1\n      - id: text1\n        color: 1\n        color2: 1\n      - id: text2\n        color: 1\n      - id: list\n        color: 244\n        color2: 1\n      - id: button\n        color: 1\n  - type: craftPilotsSelect\n    backgroundImage: BACK02.SCR\n    parent: craftPilots\n    elements:\n      - id: window\n        color: 1\n      - id: text1\n        color: 1\n        color2: 1\n      - id: text2\n        color: 1\n      - id: list\n        color: 244\n        color2: 1\n      - id: button\n        color: 1\n  - type: craftSelect\n    backgroundImage: BACK14.SCR\n    palette: PAL_BASESCAPE\n    elements:\n      - id: palette\n        color: 4\n      - id: window\n        color: 1\n      - id: text\n        color: 1\n        color2: 244\n      - id: list\n        color: 244\n        border: 1\n      - id: button\n        color: 1\n      - id: errorPalette\n        color: 6     # oxide\n      - id: errorMessage\n        color: 1\n  - type: basescape\n    palette: PAL_BASESCAPE\n    elements:\n      - id: button\n        color: 1\n      - id: text1\n        color: 244\n      - id: text2\n        color: 244\n      - id: text3\n        color: 164\n      - id: textTooltip\n        color: 1\n      - id: baseView\n        color: 213   # gold   (time remaining)\n        color2: 16   # orange (selector color)\n      - id: trafficLights\n        color: 8     # red\n        color2: 163  # yellow\n        border: 81   # green\n        TFTDMode: true\n      - id: errorPalette\n        color: 6     # oxide\n      - id: errorMessage\n        color: 1\n      - id: miniBase\n        color: 8\n        color2: 80\n        border: 159\n  - type: battlescape\n    palette: PAL_BATTLESCAPE\n    elements:\n      - id: buttonUnitUp\n        pos: [50, 1]\n        size: [28, 13]\n        TFTDMode: true\n      - id: buttonUnitDown\n        pos: [50, 17]\n        size: [28, 13]\n        TFTDMode: true\n      - id: buttonMapUp\n        pos: [82, 1]\n        size: [28, 13]\n        TFTDMode: true\n      - id: buttonMapDown\n        pos: [82, 17]\n        size: [28, 13]\n        TFTDMode: true\n      - id: buttonShowMap\n        pos: [114, 1]\n        size: [28, 13]\n        TFTDMode: true\n      - id: buttonKneel\n        pos: [114, 17]\n        size: [28, 13]\n        TFTDMode: true\n      - id: buttonInventory\n        pos: [146, 1]\n        size: [28, 13]\n        TFTDMode: true\n      - id: buttonCenter\n        pos: [146, 17]\n        size: [28, 13]\n        TFTDMode: true\n      - id: buttonNextSoldier\n        pos: [178, 1]\n        size: [28, 13]\n        TFTDMode: true\n      - id: buttonNextStop\n        pos: [178, 17]\n        size: [28, 13]\n        TFTDMode: true\n      - id: buttonShowLayers\n        pos: [210, 1]\n        size: [28, 13]\n        TFTDMode: true\n      - id: numLayers\n        pos: [229, 5]\n        TFTDMode: true\n        color: 15\n      - id: buttonHelp\n        pos: [210, 17]\n        size: [28, 13]\n        TFTDMode: true\n      - id: buttonEndTurn\n        pos: [242, 1]\n        size: [28, 13]\n        TFTDMode: true\n      - id: buttonAbort\n        pos: [242, 17]\n        size: [28, 13]\n        TFTDMode: true\n      - id: textName\n        pos: [134, 32]\n        color: 48\n      - id: numTUs\n        color: 1\n      - id: numEnergy\n        color: 1\n      - id: numHealth\n        color: 1\n      - id: numMorale\n        color: 1\n      - id: barTUs\n        color: 148\n        border: 151\n      - id: barEnergy\n        color: 160\n        border: 176\n      - id: barHealth\n        color: 9\n        color2: 4\n        border: 11\n      - id: barMorale\n        color: 157\n        border: 158\n      - id: barMana\n        color: 244\n        border: 248\n      - id: buttonReserveNone\n        pos: [54, 33]\n        size: [20, 11]\n        TFTDMode: true\n      - id: buttonReserveSnap\n        pos: [75, 33]\n        size: [21, 11]\n        TFTDMode: true\n      - id: buttonReserveAimed\n        pos: [54, 45]\n        size: [20, 11]\n        TFTDMode: true\n      - id: buttonReserveAuto\n        pos: [75, 45]\n        size: [21, 11]\n        TFTDMode: true\n      - id: buttonReserveKneel\n        pos: [97, 33]\n        size: [10, 23]\n        TFTDMode: true\n      - id: buttonZeroTUs\n        pos: [43, 33]\n        size: [10, 23]\n        TFTDMode: true\n      - id: numAmmoLeft\n        color: 1\n      - id: numAmmoRight\n        color: 1\n      - id: textTooltip\n        color: 48\n      - id: infoBoxOK\n        color: 47\n        color2: 63\n        border: 57\n      - id: infoBoxOKButton\n        color: 47\n      - id: infoBox\n        color: 47\n        color2: 63\n        border: 54\n      - id: infoBoxText\n        color: 47\n        color2: 80\n        border: 54\n      - id: grenadeMenu\n        color: 47\n        color2: 63\n        border: 57\n      - id: pathfinding\n        color: 6\n        color2: 2\n        border: 12\n      - id: messageWindowButtons\n        color: 47\n        color2: 47\n      - id: messageWindowBorder\n        color: -1\n      # The usage of the following is hard-coded, these ones MUST be defined\n      - id: visibleUnits\n        pos: [300, -16]\n        color: 1\n      - id: squadsightUnits\n        color: 86\n      - id: woundedUnits\n        color: 246\n      - id: passingOutUnits\n        color: 158\n      - id: icons\n        size: [320, 56]\n        TFTDMode: true\n      - id: messageWindows\n        color: 47\n        color2: 60\n        border: 51\n      - id: thinkingProgressBar\n        color: 177\n        color2: 81\n        border: 1\n      - id: warning\n        size: [232, 24]\n        pos: [44, 32]\n        color: 48\n        color2: 32\n      - id: actionMenu\n        color: 47\n        color2: 61\n        border: 51\n        TFTDMode: true\n      - id: grenadeBackground\n        color: 59\n        color2: 63\n        border: 55\n      - id: textLoad\n        color: 80\n      - id: optionLists\n        color: 48\n        color2: 80\n        border: 48\n      - id: disabledUserOption\n        color: 240\n      - id: medikitRed\n        color: 11\n      - id: medikitGreen\n        color: 5\n      - id: medikitBlue\n        color: 15\n      - id: medikitOrange\n        color: 8\n      - id: twoHandedRed\n        color: 9\n      - id: twoHandedGreen\n        color: 83\n  - type: briefing\n    elements:\n      - id: window\n        color: 1\n      - id: button\n        color: 1\n        color2: 1\n      - id: text\n        color: 1\n  - type: inventory\n    elements:\n      - id: textSlot\n        color: 48\n        color2: 16\n        pos: [65, 95]\n        size: [70, 9]\n      - id: textName\n        color: 48\n      - id: textTUs\n        color: 48\n        color2: 16\n      - id: textWeight\n        color: 48\n        color2: 16\n      - id: textStatLine1\n        custom: 1\n        color: 48\n        color2: 16\n      - id: textStatLine2\n        custom: 2\n        color: 48\n        color2: 16\n      - id: textStatLine3\n        custom: 3\n        color: 48\n        color2: 16\n      - id: textStatLine4\n        custom: 4\n        color: 48\n        color2: 16\n      - id: textItem\n        color: 192\n        color2: 16\n      - id: textAmmo\n        color: 48\n        color2: 16\n      - id: buttonOK\n        TFTDMode: true\n      - id: buttonPrev\n        TFTDMode: true\n      - id: buttonNext\n        TFTDMode: true\n      - id: buttonUnload\n        TFTDMode: true\n      - id: buttonGround\n        TFTDMode: true\n      - id: buttonCreate\n        TFTDMode: true\n      - id: buttonApply\n        TFTDMode: true\n      - id: buttonLinks\n        TFTDMode: true\n      # required\n      - id: textSlots\n        color: 48\n      - id: grid\n        color: 5\n      - id: weight\n        color: 16     # gold (acceptable)\n        color2: 176    # red (overweight)\n      - id: numStack\n        color: 82\n        color2: 0\n  - type: stats\n    elements:\n      - id: numMaxHealth\n        color: 96\n        pos: [278, 0]    # only X counts, Y is ignored (because it's dynamic)\n        custom: 2        # 0 + 1(=show also when current hp is equal to max hp) + 2(=show '/' prefix)\n      - id: textName\n        color: 48\n      - id: barTUs\n        color: 148\n        border: 151\n      - id: barEnergy\n        color: 160\n        border: 176\n      - id: barHealth\n        color: 9\n        color2: 4\n        border: 11\n      - id: barWounds\n        color: 32\n      - id: barBravery\n        color: 192\n      - id: barMorale\n        color: 157\n        border: 158\n      - id: barReactions\n        color: 16\n      - id: barFiring\n        color: 128\n      - id: barThrowing\n        color: 96\n      - id: barMelee\n        color: 3\n        border: 4\n      - id: barStrength\n        color: 48\n      - id: barMana\n        color: 243\n      - id: barPsiStrength\n        color: 192\n      - id: barPsiSkill\n        color: 192\n      - id: barFrontArmor\n        color: 80\n      - id: barLeftArmor\n        color: 80\n      - id: barRightArmor\n        color: 80\n      - id: barRearArmor\n        color: 80\n      - id: barUnderArmor\n        color: 80\n      # required\n      - id: text\n        color: 48\n        color2: 96\n  - type: minimap\n    elements:\n      - id: buttonUp\n        pos: [280, 98]\n        size: [24, 12]\n        TFTDMode: true\n      - id: buttonDown\n        pos: [280, 115]\n        size: [24, 12]\n        TFTDMode: true\n      - id: buttonOK\n        pos: [280, 144]\n        size: [24, 12]\n        TFTDMode: true\n      # required\n      - id: textLevel\n        pos: [282, 28]\n        color: 80\n        TFTDMode: true\n      - id: emptySpace\n        color: 180\n  - type: medikit\n    elements:\n      - id: textPK\n        pos: [151, 33]\n      - id: textStim\n        pos: [151, 69]\n      - id: textHeal\n        pos: [151, 105]\n      - id: buttonPK\n        pos: [186, 44]\n        size: [21, 21]\n      - id: buttonStim\n        pos: [186, 80]\n        size: [21, 21]\n      - id: buttonHeal\n        pos: [186, 116]\n        size: [21, 21]\n      - id: numPK\n        pos: [215, 48]\n        color: 16\n      - id: numStim\n        pos: [215, 84]\n        color: 16\n      - id: numHeal\n        pos: [215, 120]\n        color: 16\n      - id: textPart\n        pos: [82, 116]\n        color: 32\n      - id: numWounds\n        pos: [145, 116]\n        color: 32\n      - id: buttonEnd\n        pos: [292, 46]\n        size: [28, 86]\n      # required\n      - id: body\n        pos: [90, 55]\n        color: 6\n        color2: 12\n  - type: systemMenu\n    elements:\n      - id: text\n        color: 239\n      - id: button\n        color: 1\n  - type: articleTFTD\n    palette: PAL_BASESCAPE\n    backgroundImage: BACK08.SCR\n    elements:\n      - id: button\n        color: 2       # light grey\n      - id: text\n        color: 2       # light grey\n        color2: 244    # blue\n      - id: list\n        color: 2       # light grey\n        color2: 244    # blue\n  - type: articleCraftTFTD\n    palette: PAL_BASESCAPE\n    backgroundImage: BACK08.SCR\n    elements:\n      - id: button\n        color: 2       # light grey\n      - id: text\n        color: 2       # light grey\n        color2: 244    # blue\n      - id: list\n        color: 2       # light grey\n        color2: 244    # blue\n  - type: articleCraftWeaponTFTD\n    palette: PAL_BASESCAPE\n    backgroundImage: BACK08.SCR\n    elements:\n      - id: button\n        color: 2       # light grey\n      - id: text\n        color: 2       # light grey\n        color2: 244    # blue\n      - id: list\n        color: 2       # light grey\n        color2: 244    # blue\n  - type: articleVehicleTFTD\n    palette: PAL_BASESCAPE\n    backgroundImage: BACK08.SCR\n    elements:\n      - id: button\n        color: 2       # light grey\n      - id: text\n        color: 2       # light grey\n        color2: 244    # blue\n      - id: list\n        color: 2       # light grey\n        color2: 244    # blue\n  - type: articleItemTFTD\n    palette: PAL_BASESCAPE\n    backgroundImage: BACK08.SCR\n    elements:\n      - id: button\n        color: 2       # light grey\n      - id: text\n        color: 2       # light grey\n        color2: 244    # blue\n      - id: list\n        color: 2       # light grey\n        color2: 244    # blue\n      - id: ammoColor\n        color: 54      # green\n  - type: articleArmorTFTD\n    palette: PAL_BASESCAPE\n    backgroundImage: BACK08.SCR\n    elements:\n      - id: button\n        color: 2       # light grey\n      - id: text\n        color: 2       # light grey\n        color2: 244    # blue\n      - id: list\n        color: 2       # light grey\n        color2: 244    # blue\n  - type: articleBaseFacilityTFTD\n    palette: PAL_BASESCAPE\n    backgroundImage: BACK08.SCR\n    elements:\n      - id: button\n        color: 2       # light grey\n      - id: text\n        color: 2       # light grey\n        color2: 244    # blue\n      - id: list\n        color: 2       # light grey\n        color2: 244    # blue\n  - type: articleUsoTFTD\n    palette: PAL_BASESCAPE\n    backgroundImage: BACK08.SCR\n    elements:\n      - id: button\n        color: 2       # light grey\n      - id: text\n        color: 2       # light grey\n        color2: 244    # blue\n      - id: list\n        color: 2       # light grey\n        color2: 244    # blue\n  - type: statsForNerds\n    backgroundImage: BACK05.SCR\n    elements:\n      - id: palette\n        color: 0\n      - id: window\n        color: 1\n      - id: text\n        color: 1\n        color2: 244\n      - id: list\n        color: 1     # xcom1 purple (property name, property default value)\n        color2: 239  # xcom1 pink (property value)\n        border: 1    # xcom1 blue (header)\n      - id: listExtended\n        color: 244   # xcom1 white (section label)\n        color2: 244  # xcom1 gold (resource paths)\n      - id: button\n        color: 1\n      - id: comboBox\n        color: 239\n  - type: soldierTransformation\n    backgroundImage: BACK02.SCR\n    elements:\n      - id: palette\n        color: 2\n      - id: window\n        color: 1\n      - id: text\n        color: 1\n        color2: 244\n      - id: list1\n        color: 239\n        color2: 244\n        border: 1\n      - id: list2\n        color: 1\n        color2: 244\n        border: 1\n      - id: button\n        color: 1\n  - type: transformationList\n    backgroundImage: BACK02.SCR\n    elements:\n      - id: palette\n        color: 2\n      - id: window\n        color: 1\n      - id: text1\n        color: 1\n      - id: text2\n        color: 1\n      - id: list\n        color: 239\n        border: 1\n      - id: button\n        color: 1\n      - id: button2\n        color: 1\n"
  },
  {
    "path": "bin/standard/xcom2/inventories.rul",
    "content": "invs:\n  - id: STR_GROUND\n    x: 0\n    y: 152\n    type: 2\n    costs:\n      STR_BACK_PACK: 20\n      STR_BELT: 12\n      STR_LEFT_HAND: 8\n      STR_LEFT_LEG: 10\n      STR_LEFT_SHOULDER: 12\n      STR_RIGHT_HAND: 8\n      STR_RIGHT_LEG: 10\n      STR_RIGHT_SHOULDER: 12\n  - id: STR_RIGHT_HAND\n    x: 0\n    y: 63\n    type: 1\n    costs:\n      STR_BACK_PACK: 14\n      STR_BELT: 8\n      STR_GROUND: 2\n      STR_LEFT_HAND: 4\n      STR_LEFT_LEG: 10\n      STR_LEFT_SHOULDER: 10\n      STR_RIGHT_LEG: 8\n      STR_RIGHT_SHOULDER: 10\n  - id: STR_LEFT_HAND\n    x: 128\n    y: 63\n    type: 1\n    costs:\n      STR_BACK_PACK: 14\n      STR_BELT: 8\n      STR_GROUND: 2\n      STR_LEFT_LEG: 8\n      STR_LEFT_SHOULDER: 10\n      STR_RIGHT_HAND: 4\n      STR_RIGHT_LEG: 10\n      STR_RIGHT_SHOULDER: 10\n  - id: STR_BELT\n    x: 192\n    y: 104\n    slots:\n      - [0, 0]\n      - [1, 0]\n      - [2, 0]\n      - [3, 0]\n      - [0, 1]\n      - [3, 1]\n    costs:\n      STR_BACK_PACK: 16\n      STR_GROUND: 6\n      STR_LEFT_HAND: 4\n      STR_LEFT_LEG: 10\n      STR_LEFT_SHOULDER: 12\n      STR_RIGHT_HAND: 4\n      STR_RIGHT_LEG: 10\n      STR_RIGHT_SHOULDER: 12\n  - id: STR_RIGHT_LEG\n    x: 0\n    y: 120\n    slots:\n      - [0, 0]\n      - [1, 0]\n    costs:\n      STR_BACK_PACK: 18\n      STR_BELT: 10\n      STR_GROUND: 6\n      STR_LEFT_HAND: 6\n      STR_LEFT_LEG: 10\n      STR_LEFT_SHOULDER: 10\n      STR_RIGHT_HAND: 4\n      STR_RIGHT_SHOULDER: 10\n  - id: STR_LEFT_LEG\n    x: 128\n    y: 120\n    slots:\n      - [0, 0]\n      - [1, 0]\n    costs:\n      STR_BACK_PACK: 18\n      STR_BELT: 10\n      STR_GROUND: 6\n      STR_LEFT_HAND: 4\n      STR_LEFT_SHOULDER: 10\n      STR_RIGHT_HAND: 6\n      STR_RIGHT_LEG: 10\n      STR_RIGHT_SHOULDER: 10\n  - id: STR_RIGHT_SHOULDER\n    x: 16\n    y: 37\n    slots:\n      - [0, 0]\n      - [1, 0]\n    costs:\n      STR_BACK_PACK: 16\n      STR_BELT: 10\n      STR_GROUND: 4\n      STR_LEFT_HAND: 3\n      STR_LEFT_LEG: 12\n      STR_LEFT_SHOULDER: 8\n      STR_RIGHT_HAND: 3\n      STR_RIGHT_LEG: 12\n  - id: STR_LEFT_SHOULDER\n    x: 112\n    y: 37\n    slots:\n      - [0, 0]\n      - [1, 0]\n    costs:\n      STR_BACK_PACK: 16\n      STR_BELT: 10\n      STR_GROUND: 4\n      STR_LEFT_HAND: 3\n      STR_LEFT_LEG: 12\n      STR_RIGHT_HAND: 3\n      STR_RIGHT_LEG: 12\n      STR_RIGHT_SHOULDER: 8\n  - id: STR_BACK_PACK\n    x: 192\n    y: 37\n    slots:\n      - [0, 0]\n      - [1, 0]\n      - [2, 0]\n      - [0, 1]\n      - [1, 1]\n      - [2, 1]\n      - [0, 2]\n      - [1, 2]\n      - [2, 2]\n    costs:\n      STR_BELT: 12\n      STR_GROUND: 10\n      STR_LEFT_HAND: 8\n      STR_LEFT_LEG: 16\n      STR_LEFT_SHOULDER: 14\n      STR_RIGHT_HAND: 8\n      STR_RIGHT_LEG: 16\n      STR_RIGHT_SHOULDER: 14"
  },
  {
    "path": "bin/standard/xcom2/items.rul",
    "content": "items: #done\n  - type: STR_AJAX_LAUNCHER\n    size: 0.8\n    costBuy: 16000\n    costSell: 12000\n    transferTime: 48\n  - type: STR_AJAX_TORPEDOES\n    size: 0.4\n    costBuy: 3000\n    costSell: 2400\n    transferTime: 48\n    clipSize: 1\n  - type: STR_DUP_HEAD_LAUNCHER\n    size: 1\n    costBuy: 17000\n    costSell: 12750\n    transferTime: 48\n  - type: STR_DUP_HEAD_TORPEDOES\n    size: 1.5\n    costBuy: 9000\n    costSell: 7200\n    transferTime: 48\n    clipSize: 1\n  - type: STR_CRAFT_GAS_CANNON\n    size: 1.5\n    costBuy: 30000\n    costSell: 22500\n    transferTime: 48\n  - type: STR_CRAFT_GAS_CANNON_ROUNDS_X50\n    size: 0.1 # changed from vanilla - these took up no space at all in the original, and so have been given the minimum size.\n    costBuy: 1240\n    costSell: 1012\n    transferTime: 96\n    clipSize: 50\n  - type: STR_GAUSS_CANNON\n    size: 2.0\n    costSell: 211000\n    transferTime: 48\n  - type: STR_GAUSS_CANNON_AMMO\n    size: 0.1\n    clipSize: 1\n    costSell: 200\n    transferTime: 48\n    battleType: 2\n    bulletSprite: 6\n    hitSound: 31\n    hitAnimation: 46\n    power: 110\n    damageType: 4\n    vaporColor: 2\n    vaporDensity: 10\n  - type: STR_SONIC_OSCILLATOR\n    size: 1.2\n    costSell: 267300\n    transferTime: 48\n  - type: STR_PWT_CANNON\n    size: 2.0\n    costSell: 281000\n    transferTime: 48\n  - type: STR_PULSE_WAVE_TORPEDOES\n    size: 0.6\n    costSell: 53300\n    transferTime: 48\n    clipSize: 1\n  - type: STR_COELACANTH_GAS_CANNON\n    size: 6\n    costBuy: 420000\n    costSell: 340000\n    transferTime: 96\n    weight: 1\n    bigSprite: 40\n    floorSprite: 0\n    handSprite: 0\n    bulletSprite: 4\n    fireSound: 24\n    compatibleAmmo:\n      - STR_HWP_SOLID_HARPOON_BOLTS\n    accuracySnap: 60\n    accuracyAimed: 90\n    tuSnap: 30\n    tuAimed: 80\n    battleType: 1\n    fixedWeapon: true\n    invWidth: 2\n    invHeight: 3\n    turretType: 0\n  - type: STR_HWP_SOLID_HARPOON_BOLTS\n    size: 0.1\n    costBuy: 200\n    costSell: 100\n    transferTime: 48\n    weight: 1\n    hitSound: 21\n    hitAnimation: 26\n    power: 60\n    damageType: 1\n    clipSize: 30\n    battleType: 2\n    invWidth: 2\n    invHeight: 1\n    vaporColor: 0\n    vaporDensity: 15\n  - type: STR_COELACANTH_AQUA_JET\n    size: 6\n    costBuy: 480000\n    costSell: 360000\n    transferTime: 96\n    bigSprite: 42\n    fireSound: 23\n    bulletSprite: 0\n    compatibleAmmo:\n      - STR_HWP_AQUA_JET_MISSILES\n    accuracySnap: 55\n    accuracyAimed: 115\n    tuSnap: 45\n    tuAimed: 75\n    battleType: 1\n    fixedWeapon: true\n    invWidth: 2\n    invHeight: 3\n    turretType: 1\n    underwaterOnly: true\n  - type: STR_HWP_AQUA_JET_MISSILES\n    size: 0.6\n    costBuy: 3000\n    costSell: 2250\n    transferTime: 48\n    power: 85\n    damageType: 3\n    clipSize: 8\n    battleType: 2\n    hitAnimation: 8\n    vaporColor: 1\n    vaporDensity: 20\n  - type: STR_COELACANTH_GAUSS\n    size: 6\n    costSell: 594000\n    transferTime: 96\n    bigSprite: 40\n    fireSound: 34\n    accuracySnap: 50\n    accuracyAimed: 85\n    tuSnap: 33\n    tuAimed: 75\n    fixedWeapon: true\n    invWidth: 2\n    invHeight: 3\n    turretType: 2\n    battleType: 1\n    # special behaviour here: for a HWP with compatible ammo, setting a clipSize\n    # defines the max ammo for the HWP, and the clipSize on the weapon dictates\n    # how many rounds it adds.\n    compatibleAmmo:\n      - STR_GAUSS_CANNON_AMMO\n    clipSize: 50\n  - type: STR_DISPLACER_SONIC\n    size: 6\n    costSell: 980000\n    transferTime: 96\n    bigSprite: 54\n    bulletSprite: 8\n    fireSound: 36\n    hitSound: 31\n    power: 110\n    damageType: 5\n    hitAnimation: 46\n    accuracySnap: 86\n    accuracyAimed: 100\n    tuSnap: 30\n    tuAimed: 60\n    battleType: 1\n    fixedWeapon: true\n    clipSize: 100\n    isAmmoRechargeable: true\n    invWidth: 2\n    invHeight: 3\n    turretType: 3\n    vaporColor: 3\n    vaporDensity: 30\n  - type: STR_DISPLACER_PWT\n    size: 6\n    costSell: 1043000\n    transferTime: 96\n    bigSprite: 43\n    bulletSprite: 10\n    fireSound: 26\n    compatibleAmmo:\n      - STR_HWP_DISPLACER_PWT\n    accuracyAimed: 60\n    tuAimed: 66\n    battleType: 1\n    fixedWeapon: true\n    waypoints: 9\n    invWidth: 2\n    invHeight: 3\n    turretType: 4\n    underwaterOnly: true\n  - type: STR_HWP_DISPLACER_PWT\n    size: 0.6\n    costSell: 31500\n    transferTime: 48\n    power: 140\n    damageType: 3\n    clipSize: 8\n    battleType: 2\n    blastRadius: 11\n    hitAnimation: 8\n    vaporColor: 1\n    vaporDensity: 15\n  - type: STR_DART_PISTOL\n    size: 0.1\n    costBuy: 800\n    costSell: 600\n    weight: 5\n    bigSprite: 3\n    floorSprite: 3\n    handSprite: 96\n    bulletSprite: 1\n    fireSound: 20\n    compatibleAmmo:\n      - STR_DART_POD\n    accuracySnap: 40\n    accuracyAimed: 80\n    tuSnap: 20\n    tuAimed: 50\n    battleType: 1\n    invWidth: 1\n    invHeight: 2\n  - type: STR_DART_POD\n    size: 0.1\n    costBuy: 70\n    costSell: 52\n    weight: 2\n    bigSprite: 4\n    floorSprite: 4\n    handSprite: 240\n    hitSound: 21\n    hitAnimation: 26\n    power: 16\n    damageType: 1\n    clipSize: 12\n    battleType: 2\n    vaporColor: 0\n    vaporDensity: 5\n  - type: STR_JET_HARPOON\n    size: 0.2\n    costBuy: 3000\n    costSell: 2250\n    weight: 8\n    bigSprite: 1\n    floorSprite: 1\n    handSprite: 0\n    bulletSprite: 2\n    fireSound: 19\n    compatibleAmmo:\n      - STR_HARPOON_POD\n    accuracyAuto: 40\n    accuracySnap: 60\n    accuracyAimed: 90\n    tuAuto: 40\n    tuSnap: 35\n    tuAimed: 70\n    battleType: 1\n    twoHanded: true\n    invWidth: 1\n    invHeight: 3\n  - type: STR_HARPOON_POD\n    size: 0.1\n    costBuy: 200\n    costSell: 150\n    weight: 2\n    bigSprite: 2\n    floorSprite: 2\n    handSprite: 248\n    hitSound: 16\n    hitAnimation: 26\n    power: 32\n    damageType: 1\n    clipSize: 10\n    battleType: 2\n    vaporColor: 0\n    vaporDensity: 10\n  - type: STR_GAS_CANNON\n    size: 0.3\n    costBuy: 6400\n    costSell: 4800\n    weight: 17\n    bigSprite: 11\n    floorSprite: 11\n    handSprite: 24\n    bulletSprite: 4\n    fireSound: 24\n    compatibleAmmo:\n      - STR_GC_AP_AMMO\n      - STR_GC_HE_AMMO\n      - STR_GC_P_AMMO\n    accuracySnap: 60\n    accuracyAimed: 90\n    tuSnap: 40\n    tuAimed: 75\n    battleType: 1\n    twoHanded: true\n    invWidth: 2\n    invHeight: 3\n  - type: STR_GC_AP_AMMO\n    size: 0.1\n    costBuy: 300\n    costSell: 225\n    weight: 5\n    bigSprite: 12\n    floorSprite: 8\n    handSprite: 272\n    hitSound: 21\n    hitAnimation: 26\n    power: 60\n    damageType: 1\n    clipSize: 8\n    battleType: 2\n    invWidth: 2\n    invHeight: 1\n    armor: 50\n    attraction: 1\n    vaporColor: 0\n    vaporDensity: 15\n  - type: STR_GC_HE_AMMO\n    size: 0.1\n    costBuy: 500\n    costSell: 275\n    weight: 6\n    bigSprite: 13\n    floorSprite: 9\n    handSprite: 256\n    hitSound: 0\n    hitAnimation: 8\n    power: 65\n    damageType: 3\n    clipSize: 8\n    battleType: 2\n    invWidth: 2\n    invHeight: 1\n    armor: 50\n    attraction: 1\n    vaporColor: 0\n    vaporDensity: 15\n  - type: STR_GC_P_AMMO\n    size: 0.1\n    costBuy: 400\n    costSell: 300\n    weight: 6\n    bigSprite: 14\n    floorSprite: 10\n    handSprite: 264\n    hitSound: 0\n    hitAnimation: 8\n    power: 60\n    damageType: 2\n    clipSize: 8\n    battleType: 2\n    invWidth: 2\n    invHeight: 1\n    armor: 50\n    attraction: 1\n    vaporColor: 0\n    vaporDensity: 15\n  - type: STR_HYDRO_JET_CANNON\n    size: 0.3\n    costBuy: 13500\n    costSell: 10125\n    weight: 19\n    bigSprite: 7\n    floorSprite: 7\n    handSprite: 32\n    bulletSprite: 3\n    fireSound: 23\n    compatibleAmmo:\n      - STR_HJC_AP_AMMO\n      - STR_HJC_HE_AMMO\n      - STR_HJC_P_AMMO\n    accuracyAuto: 40\n    accuracySnap: 50\n    accuracyAimed: 80\n    tuAuto: 40\n    tuSnap: 35\n    tuAimed: 80\n    battleType: 1\n    twoHanded: true\n    invWidth: 2\n    invHeight: 3\n    underwaterOnly: true\n  - type: STR_HJC_AP_AMMO\n    size: 0.1\n    costBuy: 500\n    costSell: 400\n    weight: 5\n    bigSprite: 8\n    floorSprite: 13\n    handSprite: 296\n    hitSound: 21\n    hitAnimation: 26\n    power: 40\n    damageType: 1\n    clipSize: 14\n    battleType: 2\n    invWidth: 2\n    invHeight: 1\n    armor: 40\n    vaporColor: 0\n    vaporDensity: 10\n  - type: STR_HJC_HE_AMMO\n    size: 0.1\n    costBuy: 700\n    costSell: 560\n    weight: 5\n    bigSprite: 9\n    floorSprite: 14\n    handSprite: 280\n    hitSound: 0\n    hitAnimation: 8\n    power: 50\n    damageType: 3\n    clipSize: 14\n    battleType: 2\n    invWidth: 2\n    invHeight: 1\n    armor: 40\n    vaporColor: 0\n    vaporDensity: 10\n  - type: STR_HJC_P_AMMO\n    size: 0.1\n    costBuy: 650\n    costSell: 520\n    weight: 5\n    bigSprite: 10\n    floorSprite: 12\n    handSprite: 288\n    hitSound: 0\n    hitAnimation: 8\n    power: 40\n    damageType: 2\n    clipSize: 14\n    battleType: 2\n    invWidth: 2\n    invHeight: 1\n    armor: 40\n    attraction: 1\n    vaporColor: 0\n    vaporDensity: 10\n  - type: STR_TORPEDO_LAUNCHER\n    size: 0.4\n    costBuy: 4000\n    costSell: 3000\n    weight: 10\n    bigSprite: 15\n    floorSprite: 15\n    handSprite: 72\n    bulletSprite: 0\n    fireSound: 23\n    compatibleAmmo:\n      - STR_SMALL_TORPEDO\n      - STR_LARGE_TORPEDO\n      - STR_PHOSPHOROUS_TORPEDO\n    accuracySnap: 50\n    accuracyAimed: 110\n    tuSnap: 40\n    tuAimed: 80\n    battleType: 1\n    twoHanded: true\n    invWidth: 2\n    invHeight: 3\n    underwaterOnly: true\n  - type: STR_SMALL_TORPEDO\n    size: 0.2\n    costBuy: 600\n    costSell: 480\n    weight: 5\n    bigSprite: 16\n    floorSprite: 16\n    handSprite: 304\n    hitSound: 0\n    hitAnimation: 8\n    power: 80\n    damageType: 3\n    clipSize: 1\n    battleType: 2\n    invWidth: 1\n    invHeight: 3\n    armor: 50\n    vaporColor: 1\n    vaporDensity: 20\n  - type: STR_LARGE_TORPEDO\n    size: 0.2\n    costBuy: 900\n    costSell: 720\n    weight: 8\n    bigSprite: 17\n    floorSprite: 17\n    handSprite: 312\n    hitSound: 0\n    hitAnimation: 8\n    power: 90\n    damageType: 3\n    clipSize: 1\n    battleType: 2\n    invWidth: 1\n    invHeight: 3\n    armor: 50\n    vaporColor: 1\n    vaporDensity: 20\n  - type: STR_PHOSPHOROUS_TORPEDO\n    size: 0.2\n    costBuy: 1200\n    costSell: 960\n    weight: 8\n    bigSprite: 18\n    floorSprite: 18\n    handSprite: 320\n    hitSound: 0\n    hitAnimation: 8\n    power: 80\n    damageType: 2\n    clipSize: 1\n    battleType: 2\n    invWidth: 1\n    invHeight: 3\n    armor: 40\n    vaporColor: 1\n    vaporDensity: 20\n  - type: STR_GAUSS_PISTOL\n    size: 0.1\n    costSell: 20000\n    weight: 7\n    bigSprite: 5\n    floorSprite: 5\n    handSprite: 128\n    bulletSprite: 5\n    fireSound: 35\n    accuracyAuto: 30\n    accuracySnap: 40\n    accuracyAimed: 70\n    tuAuto: 30\n    tuSnap: 25\n    tuAimed: 50\n    compatibleAmmo:\n      - STR_GAUSS_PISTOL_CLIP\n    battleType: 1\n    invWidth: 1\n    invHeight: 2\n  - type: STR_GAUSS_PISTOL_CLIP\n    size: 0.2\n    costSell: 1050\n    weight: 2\n    bigSprite: 57\n    floorSprite: 78\n    handSprite: 216\n    hitSound: 31\n    hitAnimation: 46\n    power: 45\n    damageType: 4\n    clipSize: 20\n    battleType: 2\n    invWidth: 1\n    invHeight: 1\n    armor: 70\n    vaporColor: 2\n    vaporDensity: 5\n  - type: STR_GAUSS_RIFLE\n    size: 0.2\n    costSell: 36900\n    weight: 8\n    bigSprite: 0\n    floorSprite: 0\n    handSprite: 8\n    bulletSprite: 6\n    fireSound: 34\n    accuracyAuto: 50\n    accuracySnap: 65\n    accuracyAimed: 100\n    tuAuto: 40\n    tuSnap: 30\n    tuAimed: 60\n    compatibleAmmo:\n      - STR_GAUSS_RIFLE_CLIP\n    battleType: 1\n    twoHanded: true\n    invWidth: 1\n    invHeight: 3\n  - type: STR_GAUSS_RIFLE_CLIP\n    size: 0.2\n    costSell: 1950\n    weight: 3\n    bigSprite: 61\n    floorSprite: 78\n    handSprite: 224\n    hitSound: 31\n    hitAnimation: 46\n    power: 60\n    damageType: 4\n    clipSize: 15\n    battleType: 2\n    invWidth: 1\n    invHeight: 1\n    armor: 70\n    vaporColor: 2\n    vaporDensity: 10\n  - type: STR_HEAVY_GAUSS\n    size: 0.3\n    costSell: 61000\n    weight: 18\n    bigSprite: 6\n    floorSprite: 6\n    handSprite: 16\n    bulletSprite: 7\n    fireSound: 33\n    accuracySnap: 50\n    accuracyAimed: 90\n    tuSnap: 40\n    tuAimed: 80\n    compatibleAmmo:\n      - STR_HEAVY_GAUSS_CLIP\n    battleType: 1\n    twoHanded: true\n    invWidth: 2\n    invHeight: 3\n  - type: STR_HEAVY_GAUSS_CLIP\n    size: 0.2\n    costSell: 3220\n    weight: 4\n    bigSprite: 62\n    floorSprite: 78\n    handSprite: 232\n    hitSound: 31\n    hitAnimation: 46\n    power: 75\n    damageType: 4\n    clipSize: 10\n    battleType: 2\n    invWidth: 1\n    invHeight: 1\n    armor: 70\n    vaporColor: 2\n    vaporDensity: 15\n  - type: STR_MAGNA_BLAST_GRENADE\n    size: 0.1\n    costBuy: 300\n    costSell: 240\n    weight: 3\n    bigSprite: 19\n    floorSprite: 19\n    handSprite: 120\n    power: 50\n    damageType: 3\n    battleType: 4\n    armor: 150\n    blastRadius: 5\n    hitAnimation: 8\n  - type: STR_DYE_GRENADE\n    size: 0.1\n    costBuy: 150\n    costSell: 120\n    weight: 3\n    bigSprite: 20\n    floorSprite: 19\n    handSprite: 120\n    # Applying Zombie's patch here, because I happen to agree with him.\n    power: 60\n    damageType: 9\n    battleType: 4\n    armor: 110\n    blastRadius: 5\n    hitAnimation: 8\n  - type: STR_PARTICLE_DISTURBANCE_GRENADE\n    size: 0.1\n    costBuy: 500\n    costSell: 400\n    weight: 3\n    bigSprite: 21\n    floorSprite: 21\n    handSprite: 120\n    power: 70\n    damageType: 3\n    battleType: 5\n    armor: 90\n    blastRadius: 5\n    hitAnimation: 8\n  - type: STR_MAGNA_PACK_EXPLOSIVE\n    size: 0.25\n    costBuy: 1500\n    costSell: 1200\n    weight: 6\n    bigSprite: 22\n    floorSprite: 22\n    handSprite: 352\n    power: 100\n    damageType: 3\n    battleType: 4\n    invWidth: 2\n    invHeight: 1\n    armor: 140\n    blastRadius: 5\n    hitAnimation: 8\n  - type: STR_PARTICLE_DISTURBANCE_SENSOR\n    size: 0.1\n    costSell: 45600\n    weight: 3\n    bigSprite: 23\n    floorSprite: 23\n    handSprite: 192\n    battleType: 7\n    tuUse: 25\n  - type: STR_MEDI_KIT\n    size: 0.1\n    costSell: 46500\n    weight: 5\n    bigSprite: 24\n    floorSprite: 24\n    handSprite: 208\n    battleType: 6\n    invWidth: 1\n    invHeight: 2\n    painKiller: 10\n    heal: 10\n    stimulant: 10\n    woundRecovery: 1\n    healthRecovery: 3\n    stunRecovery: 4\n    energyRecovery: 10\n    tuUse: 10\n    flatRate: true\n  - type: STR_MC_DISRUPTOR\n    requires:\n      - STR_MC_DISRUPTOR\n    size: 0.1\n    costSell: 194700\n    weight: 8\n    bigSprite: 33\n    floorSprite: 28\n    handSprite: 384\n    hitSound: 43\n    battleType: 9\n    twoHanded: true\n    invWidth: 1\n    invHeight: 3\n    tuUse: 25\n    flatRate: true\n  - type: STR_THERMAL_TAZER\n    size: 0.1\n    costBuy: 1260\n    costSell: 945\n    weight: 6\n    bigSprite: 26\n    floorSprite: 26\n    handSprite: 152\n    meleeSound: 60\n    power: 80\n    damageType: 6\n    accuracyMelee: 100\n    skillApplied: false\n    tuMelee: 40\n    battleType: 3\n    twoHanded: true\n    invWidth: 1\n    invHeight: 3\n    clipSize: -1\n  - type: STR_CHEMICAL_FLARE\n    size: 0.1\n    costBuy: 60\n    costSell: 40\n    weight: 3\n    bigSprite: 55\n    floorSprite: 72\n    handSprite: 360\n    power: 15\n    battleType: 10\n    armor: 40\n  - type: STR_CORPSE\n    weight: 35\n    bigSprite: 28\n    floorSprite: 39\n    invWidth: 2\n    invHeight: 3\n    armor: 0\n    battleType: 11\n    recover: false\n  - type: STR_CORPSE_ARMOR\n    name: STR_CORPSE\n    weight: 35\n    bigSprite: 44\n    floorSprite: 40\n    invWidth: 2\n    invHeight: 3\n    armor: 0\n    battleType: 11\n    recover: false\n  - type: STR_CORPSE_ION\n    name: STR_CORPSE\n    weight: 40\n    bigSprite: 45\n    floorSprite: 41\n    invWidth: 2\n    invHeight: 3\n    armor: 0\n    battleType: 11\n    recover: false\n  - type: STR_SONIC_CANNON\n    requires:\n      - STR_SONIC_CANNON\n    size: 0.2\n    costSell: 171600\n    weight: 8\n    bigSprite: 30\n    floorSprite: 29\n    handSprite: 40\n    bulletSprite: 8\n    fireSound: 37\n    compatibleAmmo:\n      - STR_CANNON_POWER_CLIP\n    accuracySnap: 80\n    accuracyAimed: 115\n    tuSnap: 50\n    tuAimed: 70\n    battleType: 1\n    twoHanded: true\n    invWidth: 2\n    invHeight: 3\n    recoveryPoints: 5\n    armor: 50\n    attraction: 1\n  - type: STR_CANNON_POWER_CLIP\n    requires:\n      - STR_CANNON_POWER_CLIP\n    size: 0.3\n    costSell: 9590\n    weight: 3\n    bigSprite: 25\n    floorSprite: 33\n    handSprite: 200\n    hitSound: 31\n    hitAnimation: 46\n    power: 130\n    damageType: 5\n    clipSize: 10\n    battleType: 2\n    recoveryPoints: 1\n    armor: 50\n    attraction: 1\n    vaporColor: 3\n    vaporDensity: 30\n  - type: STR_SONIC_BLASTA_RIFLE\n    requires:\n      - STR_SONIC_BLASTA_RIFLE\n    size: 0.2\n    costSell: 126500\n    weight: 5\n    bigSprite: 31\n    floorSprite: 30\n    handSprite: 48\n    bulletSprite: 8\n    fireSound: 36\n    compatibleAmmo:\n      - STR_BLASTA_POWER_CLIP\n    accuracySnap: 75\n    accuracyAimed: 110\n    tuSnap: 40\n    tuAimed: 60\n    battleType: 1\n    twoHanded: true\n    invWidth: 1\n    invHeight: 3\n    recoveryPoints: 4\n    armor: 50\n    attraction: 1\n  - type: STR_BLASTA_POWER_CLIP\n    requires:\n      - STR_BLASTA_POWER_CLIP\n    size: 0.1\n    costSell: 6290\n    weight: 3\n    bigSprite: 41\n    floorSprite: 33\n    handSprite: 432\n    hitSound: 31\n    hitAnimation: 46\n    power: 95\n    damageType: 5\n    clipSize: 15\n    battleType: 2\n    recoveryPoints: 1\n    armor: 50\n    attraction: 1\n    vaporColor: 3\n    vaporDensity: 30\n  - type: STR_SONIC_PISTOL\n    requires:\n      - STR_SONIC_PISTOL\n    size: 0.1\n    costSell: 84000\n    weight: 3\n    bigSprite: 32\n    floorSprite: 31\n    handSprite: 104\n    bulletSprite: 8\n    fireSound: 38\n    compatibleAmmo:\n      - STR_PISTOL_POWER_CLIP\n    accuracySnap: 65\n    accuracyAimed: 85\n    tuSnap: 30\n    tuAimed: 50\n    battleType: 1\n    invWidth: 1\n    invHeight: 2\n    recoveryPoints: 3\n    armor: 45\n    attraction: 1\n  - type: STR_PISTOL_POWER_CLIP\n    requires:\n      - STR_PISTOL_POWER_CLIP\n    size: 0.1\n    costSell: 4440\n    weight: 3\n    bigSprite: 34\n    floorSprite: 33\n    handSprite: 424\n    hitSound: 31\n    hitAnimation: 46\n    power: 80\n    damageType: 5\n    clipSize: 20\n    battleType: 2\n    recoveryPoints: 1\n    armor: 50\n    attraction: 1\n    vaporColor: 3\n    vaporDensity: 30\n  - type: STR_DISRUPTOR_PULSE_LAUNCHER\n    requires:\n      - STR_DISRUPTOR_PULSE_LAUNCHER\n    size: 0.3\n    costSell: 144000\n    weight: 12\n    bigSprite: 35\n    floorSprite: 34\n    handSprite: 56\n    bulletSprite: 10\n    fireSound: 26\n    compatibleAmmo:\n      - STR_DISRUPTOR_AMMO\n    accuracyAimed: 120\n    tuAimed: 66\n    battleType: 1\n    twoHanded: true\n    waypoints: 9\n    invWidth: 2\n    invHeight: 3\n    recoveryPoints: 5\n    armor: 40\n    attraction: 1\n    underwaterOnly: true\n  - type: STR_DISRUPTOR_AMMO\n    requires:\n      - STR_DISRUPTOR_AMMO\n    size: 0.2\n    costSell: 17028\n    weight: 4\n    bigSprite: 36\n    floorSprite: 35\n    handSprite: 328\n    hitSound: 0\n    hitAnimation: 8\n    power: 210\n    damageType: 3\n    clipSize: 1\n    battleType: 2\n    invWidth: 1\n    invHeight: 2\n    recoveryPoints: 1\n    armor: 60\n    blastRadius: 11\n    attraction: 1\n    vaporColor: 1\n    vaporDensity: 15\n  - type: STR_THERMAL_SHOK_LAUNCHER\n    requires:\n      - STR_THERMAL_SHOK_LAUNCHER\n    size: 0.2\n    costSell: 120000\n    weight: 8\n    bigSprite: 37\n    floorSprite: 36\n    handSprite: 64\n    bulletSprite: 9\n    fireSound: 41\n    compatibleAmmo:\n      - STR_THERMAL_SHOK_BOMB\n    accuracySnap: 70\n    accuracyAimed: 120\n    tuSnap: 50\n    tuAimed: 70\n    battleType: 1\n    twoHanded: true\n    invWidth: 2\n    invHeight: 2\n    recoveryPoints: 4\n    attraction: 1\n  - type: STR_THERMAL_SHOK_BOMB\n    requires:\n      - STR_THERMAL_SHOK_BOMB\n    size: 0.1\n    costSell: 15200\n    weight: 3\n    bigSprite: 38\n    floorSprite: 81\n    handSprite: 368\n    hitSound: 0\n    hitAnimation: 8\n    power: 120\n    damageType: 6\n    clipSize: 1\n    battleType: 2\n    recoveryPoints: 1\n    armor: 60\n    attraction: 1\n    vaporColor: 1\n    vaporDensity: 10\n  - type: STR_SONIC_PULSER\n    requires:\n      - STR_SONIC_PULSER\n    size: 0.1\n    costSell: 14850\n    weight: 3\n    bigSprite: 39\n    floorSprite: 38\n    handSprite: 368\n    power: 120\n    damageType: 3\n    battleType: 4\n    recoveryPoints: 1\n    armor: 150\n    blastRadius: 5\n    attraction: 1\n    hitAnimation: 8\n  - type: STR_ZRBITE\n    size: 0.1\n    costSell: 5000\n    weight: 3\n    bigSprite: 56\n    floorSprite: 79\n    invWidth: 2\n    invHeight: 1\n    attraction: 4\n    recoveryPoints: 5\n  - type: STR_MC_READER\n    requires:\n      - STR_MC_READER\n    size: 0.1\n    costSell: 304000\n    weight: 7\n    bigSprite: 29\n    floorSprite: 77\n    handSprite: 376\n    hitSound: 43\n    battleType: 8\n    invWidth: 2\n    invHeight: 2\n    tuUse: 50\n    recoveryPoints: 1\n    attraction: 1\n  - type: STR_VIBRO_BLADE\n    requires:\n      - STR_VIBRO_BLADE\n    size: 0.3\n    costSell: 1500\n    transferTime: 48\n    weight: 10\n    bigSprite: 60\n    floorSprite: 75\n    handSprite: 168\n    meleeSound: 60\n    hitAnimation: 0\n    accuracyMelee: 150\n    tuMelee: 10\n    power: 80\n    damageType: 7\n    clipSize: -1\n    battleType: 3\n    invWidth: 2\n    invHeight: 3\n  - type: STR_THERMIC_LANCE\n    requires:\n      - STR_THERMIC_LANCE\n    size: 0.3\n    costSell: 1800\n    transferTime: 48\n    weight: 10\n    bigSprite: 59\n    floorSprite: 74\n    handSprite: 176\n    meleeSound: 60\n    hitAnimation: 0\n    accuracyMelee: 160\n    tuMelee: 15\n    power: 110\n    damageType: 7\n    clipSize: -1\n    battleType: 3\n    invWidth: 2\n    invHeight: 3\n  - type: STR_HEAVY_THERMIC_LANCE\n    requires:\n      - STR_HEAVY_THERMIC_LANCE\n    size: 0.3\n    costSell: 2000\n    transferTime: 48\n    weight: 15\n    bigSprite: 58\n    floorSprite: 73\n    handSprite: 184\n    meleeSound: 60\n    hitAnimation: 0\n    accuracyMelee: 160\n    tuMelee: 20\n    power: 150\n    damageType: 7\n    clipSize: -1\n    battleType: 3\n    invWidth: 2\n    invHeight: 3\n  - type: STR_AQUATOID_CORPSE\n    size: 0.4\n    costSell: 20000\n    weight: 30\n    bigSprite: 46\n    floorSprite: 42\n    invWidth: 2\n    invHeight: 3\n    recoveryPoints: 5\n    battleType: 11\n    armor: 26\n  - type: STR_DEEP_ONE_CORPSE\n    size: 0.4\n    costSell: 20000\n    weight: 35\n    bigSprite: 47\n    floorSprite: 43\n    invWidth: 2\n    invHeight: 3\n    recoveryPoints: 5\n    battleType: 11\n    armor: 26\n  - type: STR_GILLMAN_CORPSE\n    size: 0.4\n    costSell: 20000\n    weight: 40\n    bigSprite: 50\n    floorSprite: 46\n    invWidth: 2\n    invHeight: 3\n    recoveryPoints: 5\n    battleType: 11\n    armor: 26\n  - type: STR_TASOTH_CORPSE\n    size: 0.4\n    costSell: 20000\n    weight: 40\n    bigSprite: 48\n    floorSprite: 44\n    invWidth: 2\n    invHeight: 3\n    recoveryPoints: 5\n    battleType: 11\n    armor: 26\n  - type: STR_CALCINITE_CORPSE\n    size: 0.4\n    costSell: 20000\n    weight: 30\n    bigSprite: 52\n    floorSprite: 48\n    invWidth: 2\n    invHeight: 3\n    recoveryPoints: 5\n    battleType: 11\n    armor: 26\n  - type: STR_TENTACULAT_CORPSE\n    size: 0.4\n    costSell: 20000\n    weight: 40\n    bigSprite: 53\n    floorSprite: 49\n    invWidth: 2\n    invHeight: 3\n    recoveryPoints: 3\n    battleType: 11\n    armor: 26\n  - type: STR_LOBSTERMAN_CORPSE\n    size: 0.4\n    costSell: 20000\n    weight: 45\n    bigSprite: 49\n    floorSprite: 45\n    invWidth: 2\n    invHeight: 3\n    recoveryPoints: 3\n    battleType: 11\n    armor: 26\n  - type: STR_BIODRONE_CORPSE\n    size: 0.4\n    costSell: 20000\n    weight: 30\n    bigSprite: 51\n    floorSprite: 47\n    invWidth: 2\n    invHeight: 3\n    recoveryPoints: 3\n    battleType: 11\n    armor: 26\n    power: 120\n    blastRadius: 6\n  - type: STR_XARQUID_CORPSE\n    size: 1\n    costSell: 20000\n    battleType: 11\n  - type: XARQUID_CORPSE_1\n    name: STR_XARQUID_CORPSE\n    floorSprite: 56\n    invWidth: 0\n    invHeight: 0\n    battleType: 11\n    recoveryPoints: 3\n  - type: XARQUID_CORPSE_2\n    floorSprite: 57\n    invWidth: 0\n    invHeight: 0\n    battleType: 11\n    recover: false\n  - type: XARQUID_CORPSE_3\n    floorSprite: 58\n    invWidth: 0\n    invHeight: 0\n    battleType: 11\n    recover: false\n  - type: XARQUID_CORPSE_4\n    floorSprite: 59\n    invWidth: 0\n    invHeight: 0\n    battleType: 11\n    recover: false\n  - type: STR_HALLUCINOID_CORPSE\n    size: 1\n    costSell: 20000\n    battleType: 11\n  - type: HALLUCINOID_CORPSE_1\n    name: STR_HALLUCINOID_CORPSE\n    floorSprite: 60\n    invWidth: 0\n    invHeight: 0\n    battleType: 11\n    recoveryPoints: 3\n  - type: HALLUCINOID_CORPSE_2\n    floorSprite: 61\n    invWidth: 0\n    invHeight: 0\n    battleType: 11\n    recover: false\n  - type: HALLUCINOID_CORPSE_3\n    floorSprite: 62\n    invWidth: 0\n    invHeight: 0\n    battleType: 11\n    recover: false\n  - type: HALLUCINOID_CORPSE_4\n    floorSprite: 63\n    invWidth: 0\n    invHeight: 0\n    battleType: 11\n    recover: false\n  - type: STR_TRISCENE_CORPSE\n    size: 1\n    costSell: 20000\n    battleType: 11\n  - type: TRISCENE_CORPSE_1\n    name: STR_TRISCENE_CORPSE\n    floorSprite: 52\n    invWidth: 0\n    invHeight: 0\n    battleType: 11\n    recoveryPoints: 3\n  - type: TRISCENE_CORPSE_2\n    floorSprite: 55\n    invWidth: 0\n    invHeight: 0\n    battleType: 11\n    recover: false\n  - type: TRISCENE_CORPSE_3\n    floorSprite: 54\n    invWidth: 0\n    invHeight: 0\n    battleType: 11\n    recover: false\n  - type: TRISCENE_CORPSE_4\n    floorSprite: 53\n    invWidth: 0\n    invHeight: 0\n    battleType: 11\n    recover: false\n  - type: DISPLACER_CORPSE_1\n    floorSprite: 64\n    invWidth: 0\n    invHeight: 0\n    battleType: 11\n    recover: false\n  - type: DISPLACER_CORPSE_2\n    floorSprite: 65\n    invWidth: 0\n    invHeight: 0\n    battleType: 11\n    recover: false\n  - type: DISPLACER_CORPSE_3\n    floorSprite: 66\n    invWidth: 0\n    invHeight: 0\n    battleType: 11\n    recover: false\n  - type: DISPLACER_CORPSE_4\n    floorSprite: 67\n    invWidth: 0\n    invHeight: 0\n    battleType: 11\n    recover: false\n  - type: COELACANTH_CORPSE_1\n    floorSprite: 68\n    invWidth: 0\n    invHeight: 0\n    battleType: 11\n    recover: false\n  - type: COELACANTH_CORPSE_2\n    floorSprite: 69\n    invWidth: 0\n    invHeight: 0\n    battleType: 11\n    recover: false\n  - type: COELACANTH_CORPSE_3\n    floorSprite: 70\n    invWidth: 0\n    invHeight: 0\n    battleType: 11\n    recover: false\n  - type: COELACANTH_CORPSE_4\n    floorSprite: 71\n    invWidth: 0\n    invHeight: 0\n    battleType: 11\n    recover: false\n  - type: CIVM_CORPSE\n    name: STR_CORPSE\n    weight: 30\n    floorSprite: 50\n    invWidth: 0\n    invHeight: 0\n    armor: 12\n    battleType: 11\n    recover: false\n  - type: CIVF_CORPSE\n    name: STR_CORPSE\n    weight: 50\n    floorSprite: 51\n    invWidth: 0\n    invHeight: 0\n    armor: 12\n    battleType: 11\n    recover: false\n  - type: STR_ION_BEAM_ACCELERATORS\n    size: 0.7\n    costSell: 250000\n    specialType: 2\n    recoveryPoints: 20\n  - type: STR_MAGNETIC_NAVIGATION\n    size: 0.2\n    costSell: 80000\n    specialType: 3\n    recoveryPoints: 5\n  - type: STR_ALIEN_SUB_CONSTRUCTION\n    size: 0.1\n    costSell: 20000\n    specialType: 4\n    recoveryPoints: 2\n  - type: STR_ALIEN_CRYOGENICS\n    size: 0.2\n    costSell: 5000\n    specialType: 5\n    recoveryPoints: 2\n  - type: STR_ALIEN_CLONING\n    size: 0.2\n    costSell: 40000\n    specialType: 6\n    recoveryPoints: 2\n  - type: STR_ALIEN_LEARNING_ARRAYS\n    size: 0.2\n    costSell: 20000\n    specialType: 7\n    recoveryPoints: 2\n  - type: STR_ALIEN_IMPLANTER\n    size: 0.2\n    costSell: 38000\n    specialType: 8\n    recoveryPoints: 2\n  - type: STR_EXAMINATION_ROOM\n    size: 0.2\n    costSell: 9000\n    specialType: 9\n    recoveryPoints: 2\n  - type: STR_ALIEN_REANIMATION_ZONE\n    size: 0.1\n    costSell: 100\n    specialType: 11\n    recoveryPoints: 1\n  - type: STR_AQUA_PLASTICS\n    size: 0.1\n    costSell: 6500\n    specialType: 10\n    recoveryPoints: 1\n    recoveryDividers:\n      STR_UFO: 10\n      STR_OTHER: 150\n  - type: STR_PLASTIC_AQUA_ARMOR\n    size: 0.8\n    costSell: 54000\n  - type: STR_ION_ARMOR\n    size: 0.8\n    costSell: 85000\n  - type: STR_MAGNETIC_ION_ARMOR\n    size: 0.8\n    costSell: 115000\n  - type: STR_BIODRONE_MELEE_WEAPON\n    bigSprite: 73\n    meleeSound: 26\n    strengthApplied: true\n    damageType: 7\n    accuracyMelee: 100\n    tuMelee: 15\n    battleType: 3\n    fixedWeapon: true\n    invWidth: 2\n    invHeight: 3\n    clipSize: -1\n    recover: false\n  - type: HALLUCINOID_WEAPON\n    bigSprite: 68\n    meleeSound: 26\n    strengthApplied: true\n    damageType: 7\n    accuracyMelee: 100\n    tuMelee: 15\n    battleType: 3\n    fixedWeapon: true\n    invWidth: 2\n    invHeight: 3\n    clipSize: -1\n    recover: false\n  - type: STR_LOBSTERMAN_MELEE_WEAPON\n    specialUseEmptyHand: true\n    specialUseEmptyHandShow: true\n    bigSprite: 70\n    meleeSound: 42\n    strengthApplied: true\n    damageType: 7\n    accuracyMelee: 100\n    tuMelee: 15\n    battleType: 3\n    fixedWeapon: true\n    invWidth: 2\n    invHeight: 3\n    clipSize: -1\n    recover: false\n  - type: CALCINITE_WEAPON\n    bigSprite: 66\n    meleeSound: 16\n    strengthApplied: true\n    damageType: 7\n    accuracyMelee: 100\n    tuMelee: 15\n    battleType: 3\n    fixedWeapon: true\n    invWidth: 2\n    invHeight: 3\n    clipSize: -1\n    recover: false\n  - type: DEEP_ONE_WEAPON\n    bigSprite: 72\n    bulletSprite: 8\n    fireSound: 40\n    hitSound: 41\n    power: 100\n    damageType: 8\n    accuracyAuto: 50\n    accuracySnap: 75\n    accuracyAimed: 110\n    tuAuto: 35\n    tuSnap: 30\n    tuAimed: 60\n    battleType: 1\n    fixedWeapon: true\n    invWidth: 2\n    invHeight: 3\n    clipSize: -1\n    recover: false\n    arcingShot: true\n    hitAnimation: -1\n  - type: STR_TRISCENE_MELEE_WEAPON\n    bigSprite: 69\n    handSprite: 41\n    meleeSound: 44\n    strengthApplied: true\n    damageType: 7\n    accuracyMelee: 100\n    tuMelee: 15\n    battleType: 3\n    fixedWeapon: true\n    invWidth: 2\n    invHeight: 3\n    clipSize: -1\n    recover: false\n  - type: STR_TRIBIO_SONIC_WEAPON\n    weight: 3\n    bigSprite: 67\n    floorSprite: 29\n    handSprite: 40\n    fireSound: 36\n    hitSound: 31\n    hitAnimation: 46\n    power: 110\n    damageType: 5\n    accuracySnap: 86\n    accuracyAimed: 100\n    tuSnap: 30\n    tuAimed: 60\n    battleType: 1\n    fixedWeapon: true\n    invWidth: 2\n    invHeight: 3\n    clipSize: -1\n    bulletSprite: 8\n    recover: false\n    vaporColor: 3\n    vaporDensity: 30\n  - type: XARQUID_WEAPON\n    weight: 3\n    bigSprite: 67\n    floorSprite: 29\n    handSprite: 40\n    fireSound: 37\n    hitSound: 31\n    hitAnimation: 46\n    power: 130\n    damageType: 5\n    accuracySnap: 75\n    accuracyAimed: 100\n    tuSnap: 30\n    tuAimed: 60\n    battleType: 1\n    fixedWeapon: true\n    invWidth: 2\n    invHeight: 3\n    clipSize: -1\n    bulletSprite: 8\n    recover: false\n    vaporColor: 3\n    vaporDensity: 30\n  - type: TENTACULAT_WEAPON\n    bigSprite: 71\n    meleeSound: 42\n    strengthApplied: true\n    damageType: 7\n    accuracyMelee: 100\n    tuMelee: 15\n    battleType: 3\n    fixedWeapon: true\n    invWidth: 2\n    invHeight: 3\n    clipSize: -1\n    recover: false\n    zombieUnit: STR_ZOMBIE\n  - type: ZOMBIE_WEAPON\n    bigSprite: 74\n    meleeSound: 42\n    strengthApplied: true\n    damageType: 7\n    accuracyMelee: 100\n    tuMelee: 15\n    battleType: 3\n    fixedWeapon: true\n    invWidth: 2\n    invHeight: 3\n    clipSize: -1\n    recover: false\n  - type: STR_AQUATOID_SOLDIER\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 40000\n  - type: STR_AQUATOID_SQUAD_LEADER\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 60000\n  - type: STR_AQUATOID_TECHNICIAN\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 60000\n  - type: STR_AQUATOID_MEDIC\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 60000\n  - type: STR_AQUATOID_NAVIGATOR\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 60000\n  - type: STR_AQUATOID_COMMANDER\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 60000\n  - type: STR_HALLUCINOID_TERRORIST\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 80000\n  - type: STR_CALCINITE_TERRORIST\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 60000\n  - type: STR_GILLMAN_SOLDIER\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 40000\n  - type: STR_GILLMAN_SQUAD_LEADER\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 60000\n  - type: STR_GILLMAN_TECHNICIAN\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 60000\n  - type: STR_GILLMAN_COMMANDER\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 60000\n  - type: STR_DEEP_ONE_TERRORIST\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 60000\n  - type: STR_XARQUID_TERRORIST\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 40000\n  - type: STR_TASOTH_SOLDIER\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 40000\n  - type: STR_TASOTH_SQUAD_LEADER\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 60000\n  - type: STR_TRISCENE_TERRORIST\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 60000\n  - type: STR_BIODRONE_TERRORIST\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 60000\n  - type: STR_TENTACULAT_TERRORIST\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 60000\n  - type: STR_LOBSTERMAN_SOLDIER\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 60000\n  - type: STR_LOBSTERMAN_SQUAD_LEADER\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 40000\n  - type: STR_LOBSTERMAN_TECHNICIAN\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 60000\n  - type: STR_LOBSTERMAN_NAVIGATOR\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 60000\n  - type: STR_LOBSTERMAN_COMMANDER\n    size: 0.0\n    recover: true\n    liveAlien: true\n    costSell: 60000\n# Special Psi Weapon for Aliens.\n# Usage of this is hard-coded.\n# DO NOT DELETE!\n  - type: ALIEN_PSI_WEAPON\n    hitSound: 43\n    battleType: 9\n    tuUse: 25\n    flatRate: true\n    recover: false\n"
  },
  {
    "path": "bin/standard/xcom2/manufacture.rul",
    "content": "manufacture: # done\n  - name: STR_PWT_CANNON    #P.W.T. Cannon #\n    category: STR_CRAFT_WEAPON\n    requires:\n     - STR_PWT_CANNON\n    space: 6\n    time: 400\n    cost: 242000\n  - name: STR_PULSE_WAVE_TORPEDOES    #P.W.T Ammo #\n    category: STR_CRAFT_AMMUNITION\n    requires:\n     - STR_PWT_CANNON\n    space: 6\n    time: 600\n    cost: 28000\n    requiredItems:\n      STR_ZRBITE: 4\n  - name: STR_GAUSS_CANNON    #Gauss Cannon #\n    category: STR_CRAFT_WEAPON\n    requires:\n     - STR_GAUSS_CANNON\n    space: 6\n    time: 300\n    cost: 182000\n  - name: STR_GAUSS_CANNON_AMMO    #Gauss Cannon Ammo #\n    category: STR_AMMUNITION\n    requires:\n     - STR_GAUSS_CANNON\n    space: 2\n    time: 5\n    cost: 200\n  - name: STR_SONIC_OSCILLATOR    #Sonic Oscillator #\n    category: STR_CRAFT_WEAPON\n    requires:\n     - STR_SONIC_OSCILLATOR\n    space: 8\n    time: 500\n    cost: 226000\n    requiredItems:\n      STR_ZRBITE: 15\n  - name: STR_COELACANTH_GAUSS    #Coelacanth/Gauss #\n    category: STR_HEAVY_WEAPONS_PLATFORM\n    requires:\n     - STR_GAUSS_CANNON\n     - STR_NEW_FIGHTER_FLYING_SUB\n    space: 25\n    time: 1200\n    cost: 500000\n  - name: STR_DISPLACER_SONIC    #Displacer /Sonic #\n    category: STR_HEAVY_WEAPONS_PLATFORM\n    requires:\n     - STR_SONIC_OSCILLATOR\n     - STR_NEW_FIGHTER_FLYING_SUB\n    space: 30\n    time: 1200\n    cost: 850000\n    requiredItems:\n      STR_ZRBITE: 30\n      STR_AQUA_PLASTICS: 5\n  - name: STR_DISPLACER_PWT    #Displacer /P. W. T. #\n    category: STR_HEAVY_WEAPONS_PLATFORM\n    requires:\n     - STR_PWT_CANNON\n     - STR_NEW_FIGHTER_FLYING_SUB\n    space: 30\n    time: 1400\n    cost: 900000\n    requiredItems:\n      STR_ZRBITE: 25\n      STR_AQUA_PLASTICS: 8\n  - name: STR_HWP_DISPLACER_PWT    #P.W. Torpedo #\n    category: STR_AMMUNITION\n    requires:\n     - STR_PWT_CANNON\n     - STR_NEW_FIGHTER_FLYING_SUB\n    space: 25\n    time: 400\n    cost: 15000\n    requiredItems:\n      STR_ZRBITE: 5\n      STR_AQUA_PLASTICS: 8\n  - name: STR_GAUSS_PISTOL    #Gauss Pistol #\n    category: STR_WEAPON\n    requires:\n     - STR_GAUSS_PISTOL\n    space: 2\n    time: 300\n    cost: 8000\n  - name: STR_GAUSS_PISTOL_CLIP    #Gauss Pistol Clip #\n    category: STR_AMMUNITION\n    requires:\n     - STR_GAUSS_PISTOL_CLIP\n    space: 2\n    time: 20\n    cost: 1000\n  - name: STR_GAUSS_RIFLE    #Gauss Rifle #\n    category: STR_WEAPON\n    requires:\n     - STR_GAUSS_RIFLE\n    space: 3\n    time: 400\n    cost: 20000\n  - name: STR_GAUSS_RIFLE_CLIP    #Gauss Rifle Clip #\n    category: STR_AMMUNITION\n    requires:\n     - STR_GAUSS_RIFLE_CLIP\n    space: 4\n    time: 45\n    cost: 2000\n  - name: STR_HEAVY_GAUSS    #Heavy Gauss #\n    category: STR_WEAPON\n    requires:\n     - STR_HEAVY_GAUSS\n    space: 4\n    time: 700\n    cost: 32000\n  - name: STR_HEAVY_GAUSS_CLIP    #Heavy Gauss Clip #\n    category: STR_AMMUNITION\n    requires:\n     - STR_HEAVY_GAUSS_CLIP\n    space: 4\n    time: 70\n    cost: 4000\n  - name: STR_PARTICLE_DISTURBANCE_SENSOR    #Particle Disturbance Sensor #\n    category: STR_EQUIPMENT\n    requires:\n     - STR_PARTICLE_DISTURBANCE_SENSOR\n    space: 4\n    time: 220\n    cost: 34000\n  - name: STR_MEDI_KIT    #Medi-Kit #\n    category: STR_EQUIPMENT\n    requires:\n     - STR_MEDI_KIT\n    space: 4\n    time: 420\n    cost: 28000\n  - name: STR_MC_DISRUPTOR    #M.C. Disruptor #\n    category: STR_EQUIPMENT\n    requires:\n     - STR_MC_DISRUPTOR\n    space: 4\n    time: 500\n    cost: 160000\n    requiredItems:\n      STR_ZRBITE: 2\n      STR_AQUA_PLASTICS: 1\n  - name: STR_SONIC_CANNON    #Sonic Cannon #\n    category: STR_WEAPON\n    requires:\n     - STR_SONIC_CANNON\n     - STR_CANNON_POWER_CLIP\n    space: 4\n    time: 1000\n    cost: 122000\n    requiredItems:\n      STR_AQUA_PLASTICS: 1\n  - name: STR_CANNON_POWER_CLIP    #Cannon Power Clip #\n    category: STR_AMMUNITION\n    requires:\n     - STR_SONIC_CANNON\n     - STR_CANNON_POWER_CLIP\n    space: 4\n    time: 80\n    cost: 6000\n    requiredItems:\n      STR_ZRBITE: 3\n  - name: STR_SONIC_BLASTA_RIFLE    #Sonic-Blasta Rifle #\n    category: STR_WEAPON\n    requires:\n     - STR_SONIC_BLASTA_RIFLE\n     - STR_BLASTA_POWER_CLIP\n    space: 4\n    time: 820\n    cost: 88000\n    requiredItems:\n      STR_AQUA_PLASTICS: 1\n  - name: STR_BLASTA_POWER_CLIP    #Blasta Power Clip #\n    category: STR_AMMUNITION\n    requires:\n     - STR_SONIC_BLASTA_RIFLE\n     - STR_BLASTA_POWER_CLIP\n    space: 4\n    time: 80\n    cost: 3000\n    requiredItems:\n      STR_ZRBITE: 1\n  - name: STR_SONIC_PISTOL    #Sonic Pistol #\n    category: STR_WEAPON\n    requires:\n     - STR_SONIC_PISTOL\n     - STR_PISTOL_POWER_CLIP\n    space: 3\n    time: 600\n    cost: 56000\n    requiredItems:\n      STR_AQUA_PLASTICS: 1\n  - name: STR_PISTOL_POWER_CLIP    #Pistol Power Clip #\n    category: STR_AMMUNITION\n    requires:\n     - STR_SONIC_PISTOL\n     - STR_PISTOL_POWER_CLIP\n    space: 4\n    time: 60\n    cost: 2000\n    requiredItems:\n      STR_ZRBITE: 1\n  - name: STR_DISRUPTOR_PULSE_LAUNCHER    #Disruptor Pulse Launcher #\n    category: STR_WEAPON\n    requires:\n     - STR_DISRUPTOR_PULSE_LAUNCHER\n     - STR_DISRUPTOR_AMMO\n    space: 5\n    time: 1200\n    cost: 90000\n    requiredItems:\n      STR_AQUA_PLASTICS: 1\n  - name: STR_DISRUPTOR_AMMO    #Disruptor Ammo #\n    category: STR_AMMUNITION\n    requires:\n     - STR_DISRUPTOR_PULSE_LAUNCHER\n     - STR_DISRUPTOR_AMMO\n    space: 3\n    time: 220\n    cost: 8000\n    requiredItems:\n      STR_ZRBITE: 3\n  - name: STR_THERMAL_SHOK_LAUNCHER    #Thermal Shok Launcher #\n    category: STR_WEAPON\n    requires:\n     - STR_THERMAL_SHOK_LAUNCHER\n     - STR_THERMAL_SHOK_BOMB\n    space: 3\n    time: 900\n    cost: 78000\n    requiredItems:\n      STR_AQUA_PLASTICS: 1\n  - name: STR_THERMAL_SHOK_BOMB    #Thermal Shok Bomb #\n    category: STR_AMMUNITION\n    requires:\n     - STR_THERMAL_SHOK_LAUNCHER\n     - STR_THERMAL_SHOK_BOMB\n    space: 2\n    time: 200\n    cost: 7000\n    requiredItems:\n      STR_ZRBITE: 1\n  - name: STR_SONIC_PULSER    #Sonic Pulser #\n    category: STR_WEAPON\n    requires:\n     - STR_SONIC_PULSER\n    space: 2\n    time: 200\n    cost: 6700\n    requiredItems:\n      STR_ZRBITE: 2\n  - name: STR_MC_READER    #M.C. Reader #\n    category: STR_EQUIPMENT\n    requires:\n     - STR_MC_READER\n    space: 4\n    time: 1200\n    cost: 262000\n    requiredItems:\n      STR_ZRBITE: 1\n  - name: STR_PLASTIC_AQUA_ARMOR    #Plastic Aqua-Armour #\n    category: STR_PERSONAL_ARMOR\n    requires:\n     - STR_PLASTIC_AQUA_ARMOR\n    space: 12\n    time: 800\n    cost: 22000\n    requiredItems:\n      STR_AQUA_PLASTICS: 4\n  - name: STR_ION_ARMOR    #Ion Armour #\n    category: STR_PERSONAL_ARMOR\n    requires:\n     - STR_ION_ARMOR\n    space: 16\n    time: 1000\n    cost: 42000\n    requiredItems:\n      STR_AQUA_PLASTICS: 5\n      STR_ZRBITE: 5\n  - name: STR_MAGNETIC_ION_ARMOR    #Mag. Ion Armour #\n    category: STR_PERSONAL_ARMOR\n    requires:\n     - STR_MAGNETIC_ION_ARMOR\n    space: 16\n    time: 1400\n    cost: 58000\n    requiredItems:\n      STR_AQUA_PLASTICS: 5\n      STR_ZRBITE: 16\n  - name: STR_AQUA_PLASTICS    #Aqua Plastics\n    category: STR_UFO_COMPONENT\n    requires:\n     - STR_AQUA_PLASTICS\n    space: 10\n    time: 100\n    cost: 3000\n  - name: STR_ION_BEAM_ACCELERATORS    #Ion-Beam Accelerators #\n    category: STR_UFO_COMPONENT\n    requires:\n     - STR_ION_BEAM_ACCELERATORS\n    space: 22\n    time: 1400\n    cost: 130000\n    requiredItems:\n      STR_AQUA_PLASTICS: 5\n      STR_ZRBITE: 16\n  - name: STR_MAGNETIC_NAVIGATION    #Magnetic Navigation #\n    category: STR_UFO_COMPONENT\n    requires:\n     - STR_MAGNETIC_NAVIGATION\n    space: 18\n    time: 1600\n    cost: 150000\n    requiredItems:\n      STR_AQUA_PLASTICS: 3\n  - name: STR_MANTA    #MANTA #\n    category: STR_CRAFT\n    requires:\n     - STR_NEW_FIGHTER_FLYING_SUB\n    space: 30\n    time: 14000\n    cost: 400000\n    requiredItems:\n      STR_AQUA_PLASTICS: 65\n      STR_ION_BEAM_ACCELERATORS: 1\n      STR_MAGNETIC_NAVIGATION: 1\n  - name: STR_HAMMERHEAD    #HAMMERHEAD #\n    category: STR_CRAFT\n    requires:\n     - STR_NEW_FIGHTER_TRANSPORTER\n    space: 34\n    time: 18000\n    cost: 600000\n    requiredItems:\n      STR_AQUA_PLASTICS: 85\n      STR_ION_BEAM_ACCELERATORS: 1\n      STR_MAGNETIC_NAVIGATION: 1\n  - name: STR_LEVIATHAN    #LEVIATHAN #\n    category: STR_CRAFT\n    requires:\n     - STR_THE_LATEST_FLYING_SUB\n    space: 36\n    time: 34000\n    cost: 900000\n    requiredItems:\n      STR_AQUA_PLASTICS: 120\n      STR_ION_BEAM_ACCELERATORS: 2\n      STR_MAGNETIC_NAVIGATION: 1\n  - name: STR_VIBRO_BLADE    #Vibro Blade #\n    category: STR_WEAPON\n    requires:\n     - STR_VIBRO_BLADE\n    space: 3\n    time: 150\n    cost: 7000\n    requiredItems:\n      STR_ZRBITE: 1\n  - name: STR_THERMIC_LANCE    #Thermic Lance #\n    category: STR_WEAPON\n    requires:\n     - STR_THERMIC_LANCE\n    space: 3\n    time: 220\n    cost: 12000\n    requiredItems:\n      STR_ZRBITE: 2\n  - name: STR_HEAVY_THERMIC_LANCE    #Heavy Thermic Lance #\n    category: STR_WEAPON\n    requires:\n     - STR_HEAVY_THERMIC_LANCE\n    space: 3\n    time: 300\n    cost: 20000\n    requiredItems:\n      STR_ZRBITE: 2\n"
  },
  {
    "path": "bin/standard/xcom2/mapScripts.rul",
    "content": "mapScripts: #done\n  - type: STR_CRAFT_DEPLOYMENT_PREVIEW\n    commands:\n    - type: addCraft\n    - type: fillArea\n  - type: DEFAULT #ATLAN_MU_GAL_VOLCANO\n    commands:\n    - type: addUFO\n    - type: addCraft\n    - type: addBlock\n      size: 2\n      executions: 2\n    - type: fillArea\n  - type: THREEBIG #SEABED_PIPES_MSUNK_CORAL\n    commands:\n    - type: addUFO\n    - type: addCraft\n    - type: addBlock\n      size: 2\n      executions: 3\n    - type: fillArea\n  - type: PLANE\n    commands:\n    - type: resize\n      size: 5\n    - type: addUFO\n    - type: addCraft\n    - type: addBlock\n      blocks: [13, 14]\n      rects:\n        - [2, 0, 2, 2]\n    - type: addBlock\n      blocks: [17, 18]\n      rects:\n        - [3, 0, 1, 1]\n    - type: addBlock\n      blocks: [15, 16]\n      rects:\n        - [2, 3, 2, 2]\n    - type: addBlock\n      blocks: [19, 20]\n      rects:\n        - [3, 3, 1, 1]\n    - type: addBlock\n      blocks: 12\n      rects:\n        - [0, 0, 1, 5]\n    - type: addBlock\n      blocks: [8, 9, 10, 11]\n      rects:\n        - [1, 0, 1, 5]\n    - type: addBlock\n      blocks: [8, 9, 10, 11]\n      rects:\n        - [2, 0, 1, 5]\n    - type: addBlock\n      blocks: [6, 7]\n      rects:\n        - [3, 0, 1, 5]\n    - type: addBlock\n      blocks: [4, 5]\n      rects:\n        - [4, 0, 1, 5]\n    - type: fillArea\n      blocks: [1, 2, 3]\n  - type: SHIP_P1\n    commands:\n    - type: addCraft\n      rects:\n        - [1,0,1,1]\n      label: 1\n    - type: addCraft\n      rects:\n        - [1,0,1,2]\n      conditionals: [-1]\n    - type: addBlock\n      size: [3,7]\n    - type: addBlock\n      size: [3,2]\n      rects:\n        - [0,5,3,2]\n    - type: addBlock\n      size: [3,5]\n  - type: SHIP_P2\n    commands:\n    - type: addBlock\n      size: [3,2]\n      rects:\n        - [0,5,3,2]\n    - type: addBlock\n      size: [3,5]\n  - type: ARTIFACT_P1\n    commands:\n    - type: addBlock\n      groups: 6\n      size: 2\n    - type: addCraft\n    - type: addBlock\n      size: 2\n      executions: 2\n    - type: fillArea\n  - type: ARTIFACT_P2\n    commands:\n    - type: addBlock\n      groups: 7\n      size: 2\n    - type: addBlock\n      groups: 6\n      executions: 2\n    - type: addBlock\n      size: 2\n      executions: 2\n    - type: fillArea\n    - type: digTunnel\n      direction: both\n      tunnelData:\n        level: 0\n  - type: BASE_DRILL\n    commands:\n    - type: digTunnel\n      direction: both\n      tunnelData:\n        level: 1\n    - type: fillArea\n      groups: 1\n  - type: ALIEN_COLONY_P1\n    commands:\n    - type: addCraft\n      rects:\n       - [1,0,1,2]\n       - [4,0,1,2]\n       - [1,4,1,2]\n       - [4,4,1,2]\n    - type: addBlock\n      size: 2\n      groups: 2\n      rects:\n        - [0,0,2,2]\n    - type: addBlock\n      size: 2\n      groups: 3\n      rects:\n        - [2,0,2,2]\n    - type: addBlock\n      size: 2\n      groups: 4\n      rects:\n        - [4,0,2,2]\n    - type: addBlock\n      size: 2\n      groups: 5\n      rects:\n        - [0,2,2,2]\n    - type: addBlock\n      size: 2\n      groups: 6\n      rects:\n        - [2,2,2,2]\n    - type: addBlock\n      size: 2\n      groups: 7\n      rects:\n        - [4,2,2,2]\n    - type: addBlock\n      size: 2\n      groups: 8\n      rects:\n        - [0,4,2,2]\n    - type: addBlock\n      size: 2\n      groups: 9\n      rects:\n        - [2,4,2,2]\n    - type: addBlock\n      size: 2\n      groups: 10\n      rects:\n        - [4,4,2,2]\n  - type: ALIEN_COLONY_P2\n    commands:\n    - type: addBlock\n      size: 2\n      groups: 1\n    - type: addBlock\n      executions: 2\n      groups: 2\n    - type: addBlock\n      size: 2\n      executions: 4\n      groups: 3\n    - type: fillArea\n      groups: [3, 4]\n      freqs: [3, 2]\n    - type: digTunnel\n      direction: both\n      tunnelData:\n        level: 0\n    - type: digTunnel\n      direction: both\n      tunnelData:\n        level: 1\n    - type: digTunnel\n      direction: both\n      tunnelData:\n        level: 2\n  - type: PORT_TERROR\n    commands:\n    - type: addBlock\n      rects:\n        - [0,0,4,2]\n      blocks: 20\n    - type: addBlock\n      rects:\n        - [4,0,1,5]\n      executions: 5\n      blocks: [2, 3, 4, 5, 6, 7, 8, 9]\n      maxUses: [1, 1, 1, 1, 1, 1, 1, 1]\n    - type: addCraft\n    - type: addBlock\n      size: 2\n      executions: 2\n    - type: fillArea\n  - type: ISLAND_TERROR\n    commands:\n    - type: addBlock\n      size: 2\n      groups: 2\n      rects:\n        - [0,3,5,2]\n    - type: addBlock\n      size: 2\n      groups: 3\n      rects:\n        - [0,3,5,2]\n    - type: addBlock\n      groups: 4\n      rects:\n        - [0,4,5,1]\n    - type: addCraft\n    - type: addBlock\n      size: 2\n      executions: 4\n    - type: fillArea\n  - type: TLETH_P1\n    commands:\n    - type: fillArea\n      groups: 3\n      rects:\n        - [0,0,1,1]\n        - [5,0,1,1]\n        - [0,5,1,1]\n        - [5,5,1,1]\n    - type: addBlock\n      groups: 2\n      rects:\n        - [1,5,4,1]\n    - type: addBlock\n      blocks: 1\n      rects:\n        - [1,0,4,1]\n    - type: addBlock\n      blocks: 2\n      rects:\n        - [0,0,5,1]\n    - type: addBlock\n      size: 2\n      executions: 3\n    - type: fillArea\n    - type: digTunnel\n      direction: both\n      tunnelData:\n        level: 0\n  - type: TLETH_P2_P3\n    commands:\n    - type: addBlock\n      blocks: 0\n      rects:\n        - [0,0,2,2]\n    - type: addBlock\n      blocks: 1\n      rects:\n        - [2,0,2,2]\n    - type: addBlock\n      blocks: 2\n      rects:\n        - [4,0,2,2]\n    - type: addBlock\n      blocks: 3\n      rects:\n        - [0,2,2,2]\n    - type: addBlock\n      blocks: 4\n      rects:\n        - [2,2,2,2]\n    - type: addBlock\n      blocks: 5\n      rects:\n        - [4,2,2,2]\n    - type: addBlock\n      blocks: 6\n      rects:\n        - [0,4,2,2]\n    - type: addBlock\n      blocks: 7\n      rects:\n        - [2,4,2,2]\n    - type: addBlock\n      blocks: 8\n      rects:\n        - [4,4,2,2]\n"
  },
  {
    "path": "bin/standard/xcom2/mcdPatches.rul",
    "content": "MCDPatches: #will never be done\n# pathFinding Hacks.\n# bigWall 1 = regular bigwall, no movement allowed.\n# bigWall 2 = can walk by north-east/south-west |\n# bigWall 3 = can walk by north-west/south-east -\n# bigWall 4 = acts as west wall\n# bigWall 5 = acts as north wall\n# bigWall 6 = acts as east wall\n# bigWall 7 = acts as south wall\n# bigWall 8 = acts as east and south wall\n# bigWall 9 = acts as west and north wall\n  - type: ENTRY\n    data:\n      - MCDIndex: 6\n        deathTile: 7\n  - type: ATLANTIS\n    data:\n      - MCDIndex: 47\n        LOFTS: [4,4,4,4,5,5,63,63,63,6,6,6]\n      - MCDIndex: 48\n        LOFTS: [4,4,4,4,5,5,5,63,63,6,6,6]\n      - MCDIndex: 62\n        TUWalk: 4\n        TUFly: 4\n        TUSlide: 4\n      - MCDIndex: 63\n        TUWalk: 4\n        TUFly: 4\n        TUSlide: 4\n  - type: ASUNK\n    data:\n      - MCDIndex: 31\n        bigWall: 0\n  - type: ISLAND1\n    data:\n      - MCDIndex: 30\n        TUWalk: 0\n        TUFly: 0\n        TUSlide: 0\n  - type: CARGO1\n    data:\n      - MCDIndex: 10\n        bigWall: 6\n      - MCDIndex: 12\n        bigWall: 2\n      - MCDIndex: 13\n        bigWall: 6\n      - MCDIndex: 14\n        LOFTS: [44,0,43,42,0,14,0,0,0,0,0,0]\n      - MCDIndex: 15\n        LOFTS: [0,0,0,0,0,0,44,0,43,42,0,14]\n      - MCDIndex: 20\n        LOFTS: [47,0,46,45,0,13,0,0,0,0,0,0]\n      - MCDIndex: 21\n        LOFTS: [0,0,0,0,0,0,47,0,46,45,0,13]\n      - MCDIndex: 31\n        bigWall: 2\n  - type: CARGO3\n    data:\n      - MCDIndex: 0\n        LOFTS: [0,0,0,0,0,0,47,0,46,45,0,13]\n      - MCDIndex: 1\n        LOFTS: [47,0,46,45,0,13,0,0,0,0,0,0]\n      - MCDIndex: 2\n        LOFTS: [0,0,0,0,0,0,44,0,43,42,0,14]\n      - MCDIndex: 3\n        LOFTS: [44,0,43,42,0,14,0,0,0,0,0,0]\n  - type: CRYPT1\n    data:\n      - MCDIndex: 12\n        bigWall: 9\n  - type: GRUNGE1\n    data:\n      - MCDIndex: 9\n        bigWall: 2\n      - MCDIndex: 11\n        bigWall: 9\n      - MCDIndex: 12\n        bigWall: 3\n      - MCDIndex: 14\n        bigWall: 3\n      - MCDIndex: 15\n        bigWall: 2\n  - type: GRUNGE3\n    data:\n      - MCDIndex: 3\n        bigWall: 2\n  - type: GRUNGE4\n    data:\n      - MCDIndex: 27\n        stopLOS: true\n        bigWall: 1\n      - MCDIndex: 28\n        bigWall: 2\n      - MCDIndex: 29\n        bigWall: 3\n      - MCDIndex: 30\n        bigWall: 3\n      - MCDIndex: 31\n        bigWall: 2\n  - type: HAMMER\n    data:\n      - MCDIndex: 2\n        bigWall: 0\n        stopLOS: false\n        footstepSound: -1\n      - MCDIndex: 5\n        bigWall: 0\n        stopLOS: false\n        footstepSound: -1\n      - MCDIndex: 8\n        bigWall: 6\n      - MCDIndex: 10\n        TUWalk: 4\n        TUFly: 4\n        TUSlide: 4\n        terrainHeight: -16\n      - MCDIndex: 11\n        TUWalk: 4\n        TUFly: 4\n        TUSlide: 4\n        terrainHeight: -16\n      - MCDIndex: 12\n        TUWalk: 4\n        TUFly: 4\n        TUSlide: 4\n        terrainHeight: -16\n      - MCDIndex: 13\n        TUWalk: 4\n        TUFly: 4\n        TUSlide: 4\n        terrainHeight: -16\n      - MCDIndex: 14\n        bigWall: 7\n        terrainHeight: 0\n        LOFTS: [44,44,44,44,44,44,0,0,0,0,0,0]\n      - MCDIndex: 25\n        TUWalk: 4\n        TUFly: 4\n        TUSlide: 4\n        terrainHeight: -20\n      - MCDIndex: 26\n        bigWall: 7\n      - MCDIndex: 27\n        TUWalk: 4\n        TUFly: 4\n        TUSlide: 4\n        terrainHeight: -20\n      - MCDIndex: 29\n        TUWalk: 4\n        TUFly: 4\n        TUSlide: 4\n        terrainHeight: -20\n      - MCDIndex: 31\n        TUWalk: 4\n        TUFly: 4\n        TUSlide: 4\n        terrainHeight: -16\n      - MCDIndex: 32\n        bigWall: 7\n      - MCDIndex: 33\n        TUWalk: 4\n        TUFly: 4\n        TUSlide: 4\n        terrainHeight: -16\n      - MCDIndex: 34\n        TUWalk: 4\n        TUFly: 4\n        TUSlide: 4\n        terrainHeight: -16\n      - MCDIndex: 35\n        TUWalk: 4\n        TUFly: 4\n        TUSlide: 4\n        terrainHeight: -16\n  - type: LEVIATH\n    data:\n      - MCDIndex: 2\n        bigWall: 0\n        TUWalk: 0\n        TUFly: 0\n        TUSlide: 0\n        stopLOS: false\n        footstepSound: -1\n      - MCDIndex: 3\n        bigWall: 2\n      - MCDIndex: 9\n        bigWall: 3\n      - MCDIndex: 10\n        bigWall: 0\n        TUWalk: 0\n        TUFly: 0\n        TUSlide: 0\n        stopLOS: false\n        footstepSound: -1\n      - MCDIndex: 11\n        bigWall: 6\n      - MCDIndex: 13\n        TUWalk: 0\n        TUFly: 0\n        TUSlide: 0\n      - MCDIndex: 14\n        TUWalk: 0\n        TUFly: 0\n        TUSlide: 0\n      - MCDIndex: 15\n        TUWalk: 0\n        TUFly: 0\n        TUSlide: 0\n      - MCDIndex: 16\n        TUWalk: 0\n        TUFly: 0\n        TUSlide: 0\n      - MCDIndex: 22\n        TUWalk: 4\n        TUFly: 4\n        TUSlide: 4\n      - MCDIndex: 23\n        TUWalk: 4\n        TUFly: 4\n        TUSlide: 4\n      - MCDIndex: 24\n        TUWalk: 4\n        TUFly: 4\n        TUSlide: 4\n      - MCDIndex: 25\n        TUWalk: 4\n        TUFly: 4\n        TUSlide: 4\n      - MCDIndex: 28\n        stopLOS: false\n        TUWalk: 4\n        TUFly: 4\n        TUSlide: 4\n      - MCDIndex: 29\n        stopLOS: false\n        TUWalk: 4\n        TUFly: 4\n        TUSlide: 4\n      - MCDIndex: 30\n        TUWalk: 4\n        TUFly: 4\n        TUSlide: 4\n        terrainHeight: -18\n      - MCDIndex: 32\n        stopLOS: false\n        TUWalk: 4\n        TUFly: 4\n        TUSlide: 4\n      - MCDIndex: 34\n        stopLOS: false\n        TUWalk: 4\n        TUFly: 4\n        TUSlide: 4\n        terrainHeight: -10\n      - MCDIndex: 35\n        stopLOS: false\n        TUWalk: 4\n        TUFly: 4\n        TUSlide: 4\n        terrainHeight: -10\n      - MCDIndex: 36\n        stopLOS: false\n        bigWall: 0\n      - MCDIndex: 38\n        stopLOS: false\n        bigWall: 0\n      - MCDIndex: 39\n        stopLOS: false\n      - MCDIndex: 40\n        stopLOS: false\n        bigWall: 0\n        TUWalk: 4\n        TUFly: 4\n        TUSlide: 4\n        terrainHeight: -10\n      - MCDIndex: 41\n        stopLOS: false\n        bigWall: 0\n        TUWalk: 4\n        TUFly: 4\n        TUSlide: 4\n        terrainHeight: -10\n      - MCDIndex: 42\n        stopLOS: false\n        terrainHeight: -10\n      - MCDIndex: 45\n        stopLOS: false\n        terrainHeight: -10\n      - MCDIndex: 46\n        stopLOS: false\n        TUWalk: 4\n        TUFly: 4\n        TUSlide: 4\n        terrainHeight: -10\n  - type: LINERA\n    data:\n      - MCDIndex: 14\n        LOFTS: [44,0,43,42,0,14,0,0,0,0,0,0]\n      - MCDIndex: 15\n        LOFTS: [0,0,0,0,0,0,44,0,43,42,0,14]\n      - MCDIndex: 20\n        LOFTS: [47,0,46,45,0,13,0,0,0,0,0,0]\n      - MCDIndex: 21\n        LOFTS: [0,0,0,0,0,0,47,0,46,45,0,13]\n      - MCDIndex: 30\n        bigWall: 3\n      - MCDIndex: 31\n        bigWall: 2\n      - MCDIndex: 32\n        bigWall: 3\n      - MCDIndex: 33\n        bigWall: 3\n      - MCDIndex: 34\n        bigWall: 2\n      - MCDIndex: 35\n        bigWall: 2\n      - MCDIndex: 37\n        stopLOS: false\n        bigWall: 0\n      - MCDIndex: 41\n        bigWall: 0\n      - MCDIndex: 46\n        footstepSound: -1\n      - MCDIndex: 47\n        footstepSound: -1\n      - MCDIndex: 48\n        footstepSound: -1\n      - MCDIndex: 65\n        bigWall: 6\n      - MCDIndex: 66\n        bigWall: 6\n      - MCDIndex: 78\n        footstepSound: -1\n      - MCDIndex: 79\n        footstepSound: -1\n      - MCDIndex: 80\n        footstepSound: -1\n      - MCDIndex: 92\n        footstepSound: -1\n  - type: LINERB\n    data:\n      - MCDIndex: 1\n        noFloor: false\n        TUFly: 4\n        terrainHeight: 0\n      - MCDIndex: 8\n        bigWall: 2\n      - MCDIndex: 21\n        noFloor: true\n        TUWalk: 4\n        TUSlide: 4\n        TUFly: 4\n  - type: MSUNK2\n    data:\n      - MCDIndex: 2\n        bigWall: 6\n      - MCDIndex: 5\n        bigWall: 2\n      - MCDIndex: 6\n        bigWall: 2\n      - MCDIndex: 8\n        bigWall: 6\n      - MCDIndex: 9\n        bigWall: 6\n      - MCDIndex: 10\n        bigWall: 3\n  - type: ORGANIC1\n    data:\n      - MCDIndex: 33\n        bigWall: 2\n      - MCDIndex: 34\n        bigWall: 3\n      - MCDIndex: 36\n        bigWall: 3\n      - MCDIndex: 73\n        bigWall: 2\n      - MCDIndex: 74\n        bigWall: 2\n      - MCDIndex: 75\n        bigWall: 3\n      - MCDIndex: 76\n        bigWall: 3\n      - MCDIndex: 77\n        bigWall: 3\n  - type: ORGANIC2\n    data:\n      - MCDIndex: 6\n        deathTile: 7\n  - type: PIPES\n    data:\n      - MCDIndex: 32\n        LOFTS: [44,0,43,42,0,14,0,0,0,0,0,0]\n      - MCDIndex: 33\n        LOFTS: [109,109,109,109,109,109,44,0,43,42,0,14]\n      - MCDIndex: 34\n        LOFTS: [109,109,109,109,109,109,109,67,0,94,0,14]\n      - MCDIndex: 36\n        LOFTS: [109,109,109,109,109,109,47,0,46,45,0,13]\n      - MCDIndex: 37\n        LOFTS: [47,0,46,45,0,13,0,0,0,0,0,0]\n      - MCDIndex: 38\n        LOFTS: [109,109,109,109,109,109,109,97,0,93,66,13]\n      - MCDIndex: 51\n        bigWall: 4\n      - MCDIndex: 52\n        bigWall: 4\n      - MCDIndex: 53\n        bigWall: 5\n      - MCDIndex: 54\n        bigWall: 5\n  - type: PLANE\n    data:\n      - MCDIndex: 11\n        LOFTS: [44,44,44,43,43,43,42,42,42,14,14,14]\n      - MCDIndex: 12\n        LOFTS: [44,44,44,43,75,75,42,42,41,41,41,14]\n      - MCDIndex: 17\n        LOFTS: [23,23,106,106,106,23,23,23,23,23,23,23]\n      - MCDIndex: 20\n        LOFTS: [10,10,113,113,113,113,10,10,10,10,10,10]\n      - MCDIndex: 24\n        LOFTS: [83,0,0,0,0,0,0,0]\n      - MCDIndex: 25\n        LOFTS: [23,23,44,43,43,69,69,42,42,14,12,12]\n      - MCDIndex: 26\n        LOFTS: [44,105,105,75,75,75,71,71,102,94,94,12]\n      - MCDIndex: 28\n        LOFTS: [12,12,94,94,0,75,75,71,105,106,44,44]\n  - type: PORT01\n    data:\n      - MCDIndex: 19\n        TUWalk: 4\n        TUFly: 4\n        objectType: 0\n      - MCDIndex: 50\n        LOFTS: [88,0,88,0,88,0,88,0,88,0,88,0]\n      - MCDIndex: 51\n        LOFTS: [87,0,87,0,87,0,87,0,87,0,87,0]\n      - MCDIndex: 62\n        LOFTS: [44,38,43,42,38,14,0,0,0,0,0,0]\n      - MCDIndex: 64\n        LOFTS: [85,85,85,85,85,85,44,48,43,42,38,14]\n      - MCDIndex: 67\n        LOFTS: [85,85,85,85,85,85,47,37,46,45,37,13]\n      - MCDIndex: 69\n        LOFTS: [47,37,46,45,37,13,0,0,0,0,0,0]\n  - type: TRITON\n    data:\n      - MCDIndex: 0\n        bigWall: 6\n      - MCDIndex: 1\n        bigWall: 7\n      - MCDIndex: 3\n        TUWalk: 4\n        TUFly: 4\n        TUSlide: 4\n        terrainHeight: -18\n      - MCDIndex: 7\n        bigWall: 7\n        terrainHeight: 0\n        LOFTS: [44,44,44,44,44,44,0,0,0,0,0,0]\n      - MCDIndex: 13\n        LOFTS: [6,6,6,6,6,6,6,6,6,78,78,0]\n      - MCDIndex: 18\n        bigWall: 4\n        LOFTS: [13,13,13,13,13,0,0,0,0,0,0,0]\n      - MCDIndex: 19\n        bigWall: 0\n        TUWalk: 4\n        TUFly: 4\n        TUSlide: 4\n        terrainHeight: -10\n      - MCDIndex: 20\n        TUWalk: 4\n        TUFly: 4\n        TUSlide: 4\n        terrainHeight: -16\n      - MCDIndex: 21\n        bigWall: 0\n        terrainHeight: -12\n      - MCDIndex: 22\n        bigWall: 0\n      - MCDIndex: 24\n        bigWall: 6\n        LOFTS: [26,26,26,26,26,0,0,0,0,0,0,0]\n      - MCDIndex: 25\n        TUWalk: 4\n        TUFly: 4\n        TUSlide: 4\n        terrainHeight: -10\n      - MCDIndex: 26\n        TUWalk: 4\n        TUFly: 4\n        TUSlide: 4\n        terrainHeight: -16\n      - MCDIndex: 27\n        TUWalk: 4\n        TUFly: 4\n        TUSlide: 4\n        LOFTS: [6,6,6,6,6,6,19,17,15,13,11,9]\n      - MCDIndex: 28\n        TUWalk: 4\n        TUFly: 4\n        TUSlide: 4\n      - MCDIndex: 29\n        TUWalk: 4\n        TUFly: 4\n        TUSlide: 4\n      - MCDIndex: 30\n        TUWalk: 4\n        TUFly: 4\n        TUSlide: 4\n      - MCDIndex: 31\n        bigWall: 7\n        terrainHeight: 0\n  - type: UEXT3\n    data:\n      - MCDIndex: 0\n        bigWall: 5\n      - MCDIndex: 1\n        bigWall: 2\n      - MCDIndex: 2\n        bigWall: 4\n      - MCDIndex: 3\n        footstepSound: -1\n      - MCDIndex: 4\n        footstepSound: -1\n      - MCDIndex: 6\n        bigWall: 3\n      - MCDIndex: 7\n        bigWall: 3\n      - MCDIndex: 8\n        bigWall: 5\n      - MCDIndex: 9\n        bigWall: 2\n      - MCDIndex: 10\n        bigWall: 4\n      - MCDIndex: 12\n        bigWall: 2\n      - MCDIndex: 14\n        bigWall: 5\n      - MCDIndex: 15\n        bigWall: 2\n      - MCDIndex: 16\n        bigWall: 4\n      - MCDIndex: 19\n        bigWall: 5\n      - MCDIndex: 20\n        bigWall: 2\n      - MCDIndex: 21\n        bigWall: 4\n  - type: UINT1\n    data:\n      - MCDIndex: 17\n        bigWall: 2\n      - MCDIndex: 19\n        bigWall: 3\n      - MCDIndex: 20\n        bigWall: 0\n      - MCDIndex: 21\n        bigWall: 3\n      - MCDIndex: 29\n        bigWall: 0\n      - MCDIndex: 32\n        bigWall: 0\n  - type: UINT3\n    data:\n      - MCDIndex: 9\n        bigWall: 0\n        footstepSound: -1\n      - MCDIndex: 10\n        bigWall: 0\n        footstepSound: -1\n      - MCDIndex: 11\n        bigWall: 0\n        footstepSound: -1\n      - MCDIndex: 12\n        bigWall: 0\n        footstepSound: -1\n  - type: XBASES01\n    data:\n      - MCDIndex: 0\n        bigWall: 4\n      - MCDIndex: 6\n        bigWall: 6\n      - MCDIndex: 9\n        bigWall: 6\n  - type: XBASES02\n    data:\n      - MCDIndex: 8\n        bigWall: 9\n      - MCDIndex: 9\n        bigWall: 9\n  - type: MU\n    data:\n      - MCDIndex: 7\n        bigWall: 0\n      - MCDIndex: 8\n        bigWall: 0\n  - type: CORAL\n    data:\n      - MCDIndex: 9\n        bigWall: 0\n      - MCDIndex: 10\n        bigWall: 0\n      - MCDIndex: 11\n        bigWall: 0\n      - MCDIndex: 12\n        bigWall: 0\n      - MCDIndex: 13\n        bigWall: 0\n      - MCDIndex: 14\n        bigWall: 0\n"
  },
  {
    "path": "bin/standard/xcom2/metadata.yml",
    "content": "#\n# metadata.yaml for XCOM2\n\nname: \"X-Com: Terror From the Deep\"\nversion: 8.6.0\ndescription: \"The original X-Com: Terror From the Deep\"\nauthor: Microprose\nid: xcom2\n\nisMaster: true\nresourceConfig: vars.rul\nloadResources:\n  - TFTD\n"
  },
  {
    "path": "bin/standard/xcom2/missionScripts.rul",
    "content": "#  - type: example                       # the type/name is used for overwriting or deleting purposes.\n#    firstMonth: 0                       # months this command runs on, 0 runs on startup of a new game (default 0)\n#    lastMonth: 0                        # don't run after this month. in this context we mean \"run once\". -1 denotes no limit (default -1)\n#    label: 1                            # label, used for conditionals (default 0)\n#    conditionals: [1, -2]               # conditional list, just like mapscripts (default none)\n#    missionWeights:                     # the type of mission to spawn (omit to pick one from the mission table) (default none)\n#      0:                                # these are split into monthly chunks, and can contain multiple entries,\n#        STR_ALIEN_PROBE_MISSION: 20     # including weighted odds, but there is a caveat here:\n#        STR_ALIEN_INTERDICTION: 30      # you cannot mix and match missions with mission site objectives (ie: terror) with regular missions,\n#        STR_ALIEN_OUTERDICTION: 30      # they are generated too differently. using executionOdds and conditionals instead can achieve\n#        STR_WHALE_WATCHING: 20          # exactly the same thing. similarly, terror missions should not appear in regional mission weights (regions.rul)\n#    executionOdds: 100                  # % chances of this command executing (default 100)\n#    targetBaseOdds: 75                  # % chances of this mission targeting a region containing an xcom base instead of random (default 0)\n#    startDelay: 120                     # number of minutes to delay the start of the mission (rounded down to the nearest 30, 0 to use the wave timer from the mission itself) (default 0)\n#    raceWeights:                        # can override established monthly race weights here if desired (default empty)\n#      0:\n#        STR_AQUATOID: 100               # in this case we want an aquatoid mission, so they get 100%\n#    regionWeights:                      # again, this can override the defined mission region weights (default empty)\n#      0:                                # this won't come into play here unless the mission doesn't target an xcom base, as described above.\n#        STR_SAMPLE_REGION1: 20          # IF OMITTED:\n#        STR_SAMPLE_REGION2: 30          # for a terror type mission, all regions that meet the criteria will be weighed equally.\n#        STR_SAMPLE_REGION3: 50          # for regular missions the normal regional distribution weights will be applied.\n#    minDifficulty: 0                    # this command only applies to difficulty levels of this or above (default 0)\n#    researchTriggers:                   # a list of research topics that can influence the execution of this mission (default empty)\n#      STR_THE_ULTIMATE_THREAT: true     # in this case, the mission would only run if the player has the ultimate threat\n#      STR_TLETH_TH_ALIEN_CITY: false    # and does NOT have T'Leth\n#    maxRuns: 12                         # this mission type can only execute this number of times, -1 for infinite (default -1)\n#    avoidRepeats: 12                    # this means \"store an array of the 12 previous coordinates, and don't use them again\" (default 0)\n#    varName: researching                # this is an internal variable name, used for tracking maxruns and avoidRepeats (default none)\n#    useTable: false                     # check this mission type appears in the mission tables, and remove it if it does? (default true)\n\nmissionScripts: #done\n  - type: gameStart\n    missionWeights:\n      0:\n        STR_ALIEN_PROBE_MISSION: 100\n    lastMonth: 0\n    targetBaseOdds: 100\n    raceWeights:\n      0:\n        STR_AQUATOID: 100\n    startDelay: 120\n\n\n  - type: artifacts\n    label: 1\n    missionWeights:\n      # 0 is just for safety\n      0:\n        STR_ALIEN_ARTIFACT: 100\n    regionWeights:\n      0:\n        ARTIFACT_SITES: 100\n    avoidRepeats: 12\n    maxRuns: 12\n    varName: artifacts\n    useTable: false\n    firstMonth: 6\n    executionOdds: 50\n    startDelay: 0\n\n\n\n  - type: shipTerror\n    conditionals: [-1]\n    label: 2\n    missionWeights:\n      # 0 is just for safety\n      0:\n        STR_ALIEN_SHIP_ATTACK: 100\n    regionWeights:\n      0:\n        SHIPPING_LANES: 100\n    avoidRepeats: 5\n    varName: shippingLanes\n    useTable: false\n    firstMonth: 3\n    executionOdds: 60\n    startDelay: 0\n\n\n  - type: recurringTerror\n    conditionals: [-1, -2]\n    missionWeights:\n      0:\n        STR_ALIEN_SURFACE_ATTACK: 100\n    regionWeights:\n      0:\n        STR_NORTH_ATLANTIC: 10\n        STR_SOUTH_ATLANTIC: 10\n        STR_NORTH_PACIFIC: 10\n        STR_SOUTH_PACIFIC: 10\n        STR_MEDITERRANEAN: 10\n        STR_SOUTH_CHINA_SEA: 10\n        STR_INDIAN_OCEAN: 10\n        STR_THE_EAST_SEA: 10\n        STR_NORTH_SEA: 10\n        STR_CARRIBEAN: 10\n    useTable: false\n    startDelay: 150\n\n\n\n\n\n\n  - type: recon\n    firstMonth: 1\n  - type: invasion\n    firstMonth: 6\n  - type: researchRetaliation\n    missionWeights:\n      0:\n        STR_ALIEN_RETALIATION: 100\n    researchTriggers:\n      STR_THE_ULTIMATE_THREAT: true\n    startDelay: 150\n    targetBaseOdds: 100\n    useTable: false\n    label: 3\n  - type: beginnerRetaliation\n    missionWeights:\n      0:\n        STR_ALIEN_RETALIATION: 100\n    firstMonth: 14\n    targetBaseOdds: 100\n    useTable: false\n    conditionals: [-3]\n    label: 4\n    startDelay: 150\n  - type: experiencedRetaliation\n    minDifficulty: 1\n    missionWeights:\n      0:\n        STR_ALIEN_RETALIATION: 100\n    firstMonth: 13\n    targetBaseOdds: 100\n    useTable: false\n    conditionals: [-3, -4]\n    label: 5\n    startDelay: 150\n  - type: veteranRetaliation\n    minDifficulty: 2\n    missionWeights:\n      0:\n        STR_ALIEN_RETALIATION: 100\n    firstMonth: 12\n    targetBaseOdds: 100\n    useTable: false\n    conditionals: [-3, -4, -5]\n    label: 6\n    startDelay: 150\n  - type: geniusRetaliation\n    minDifficulty: 3\n    missionWeights:\n      0:\n        STR_ALIEN_RETALIATION: 100\n    firstMonth: 10\n    targetBaseOdds: 100\n    useTable: false\n    conditionals: [-3, -4, -5, -6]\n    label: 7\n    startDelay: 150\n  - type: superhumanRetaliation\n    minDifficulty: 4\n    missionWeights:\n      0:\n        STR_ALIEN_RETALIATION: 100\n    firstMonth: 8\n    targetBaseOdds: 100\n    useTable: false\n    conditionals: [-3, -4, -5, -6, -7]\n    startDelay: 150\n"
  },
  {
    "path": "bin/standard/xcom2/music.rul",
    "content": "musics: #done\n  - type: GMNEWINT #intro\n    catPos: 0\n  - type: GMSIG #tleth cutscene\n    catPos: 1\n  - type: GMWAITLO #main menu\n    catPos: 2\n  - type: GMGEO1\n    catPos: 3\n  - type: GMGEO2\n    catPos: 4\n  - type: GMGEO3\n    catPos: 5\n  - type: GMGEO4\n    catPos: 6\n  - type: GMGEO5\n    catPos: 7\n  - type: GMGEO6\n    catPos: 8\n  - type: GMINTER1\n    catPos: 9\n  - type: GMINTER2\n    catPos: 10\n  - type: GMINTER3\n    catPos: 11\n  - type: GMISPOSH #ufo / terror\n    catPos: 12\n  - type: GMINTER0 #ufo / terror\n    name: GMISPOSH\n    catPos: 12\n  - type: GMBIGMAR #tleth\n    catPos: 13\n  - type: GMDEFBAS #base defense\n    catPos: 14\n  - type: GMATTBAS #alien base\n    catPos: 15\n  - type: GMDEBGOO #debriefing good\n    catPos: 16\n  - type: GMDEBPOR #debriefing poor\n    catPos: 17\n  - type: GMTACWET #tactical water\n    catPos: 18\n  - type: GMTACDRY #tactical land\n    catPos: 19\n  - type: GMWIN #doesn't have a midi\n    catPos: 20\n  - type: GMLOSE #doesn't have a midi\n    catPos: 21\n"
  },
  {
    "path": "bin/standard/xcom2/regions.rul",
    "content": "regions: #done\n  - type: ARTIFACT_SITES\n    missionZones:\n      -\n        - [14, 14, -40, -40, -3]\n        - [294, 294, -18, -18, -3]\n        - [279, 279, -61.5, -61.5, -3]\n        - [356, 356, -59, -59, -3]\n        - [151, 151, -3.5, -3.5, -3]\n        - [329, 329, -37, -37, -3]\n        - [27, 27, -32, -32, -3]\n        - [278, 278, 23, 23, -3]\n        - [189, 189, 39, 39, -3]\n        - [306, 306, 45, 45, -3]\n        - [132.5, 132.5, 39, 39, -3]\n        - [164.5, 164.5, -53, -53, -3]\n        - [134, 134, -15, -15, -3]\n        - [10, 10, 12, 12, -3]\n        - [302.5, 302.5, -68, -68, -3]\n        - [42, 42, -69, -69, -3]\n        - [66, 66, -11, -11, -3]\n        - [72, 72, 29, 29, -3]\n        - [84, 84, 55, 55, -3]\n        - [40, 40, 64, 64, -3]\n        - [329, 329, 62.5, 62.5, -3]\n        - [226, 226, 56, 56, -3]\n        - [139, 139, 62, 62, -3]\n        - [188, 188, -68.5, -68.5, -3]\n        - [205, 205, -36, -36, -3]\n        - [172, 172, -11, -11, -3]\n        - [197, 197, -15.5, -15.5, -3]\n        - [242.5, 242.5, 27, 27, -3]\n        - [265, 265, -14, -14, -3]\n        - [325, 325, 39, 39, -3]\n        - [31, 31, 49, 49, -3]\n        - [214, 214, -55, -55, -3]\n        - [164, 164, 17, 17, -3]\n        - [309, 309, -44, -44, -3]\n        - [316, 316, -11, -11, -3]\n        - [0, 0, -72, -72, -3]\n  - type: SHIPPING_LANES\n    missionZones:\n      -\n        - [296.5, 296.5, -42, -42, -4]\n        - [318, 318, -47, -47, -4]\n        - [326, 326, -48, -48, -4]\n        - [337, 337, -48.5, -48.5, -4]\n        - [344, 344, 49.5, 49.5, -4]\n        - [351, 351, -50, -50, -4]\n        - [291, 291, -39, -39, -4]\n        - [310, 310, -34, -34, -4]\n        - [318.5, 318.5, -30, -30, -4]\n        - [329, 329, -28, -28, -4]\n        - [338, 338, -24, -24, -4]\n        - [337, 337, 12, 12, -4]\n        - [347, 347, 17, 17, -4]\n        - [355, 355, 21, 21, -4]\n        - [5, 5, 26, 26, -4]\n        - [9, 9, -30, -30, -4]\n        - [149, 149, -44, -44, -4]\n        - [159, 159, -44.5, -44.5, -4]\n        - [172, 172, -45, -45, -4]\n        - [184, 184, -46, -46, -4]\n        - [197, 197, -46.5, -46.5, -4]\n        - [209, 209, -47, -47, -4]\n        - [223, 223, -48, -48, -4]\n        - [163, 163, 10, 10, -4]\n        - [173, 173, 3, 3, -4]\n        - [185, 185, -5, -5, -4]\n        - [193, 193, -9.5, -9.5, -4]\n        - [213, 213, -22, -22, -4]\n        - [221, 221, -29, -29, -4]\n        - [228, 228, -33, -33, -4]\n        - [172, 172, 20, 20, -4]\n        - [193, 193, 20, 20, -4]\n        - [211, 211, 20, 20, -4]\n        - [223, 223, 20, 20, -4]\n        - [240, 240, 20, 20, -4]\n        - [256, 256, 20, 20, -4]\n        - [283, 283, 20, 20, -4]\n        - [39, 39, 35, 35, -4]\n        - [52, 52, 34.5, 34.5, -4]\n        - [64.5, 64.5, 34, 34, -4]\n        - [78.5, 78.5, 33, 33, -4]\n        - [92, 92, 33, 33, -4]\n        - [105.5, 105.5, 32.5, 32.5, -4]\n        - [87, 87, -3, -3, -4]\n        - [93, 93, 5, 5, -4]\n        - [98, 98, 12, 12, -4]\n        - [104.5, 104.5, 19, 19, -4]\n        - [109, 109, 25, 25, -4]\n  - type: STR_NORTH_ATLANTIC\n    cost: 800000\n    areas:\n      - [266, 292, -70, -50]\n      - [291, 349, -66, -30]\n      - [279.5, 292, -43.5, -30]\n      - [349, 355, -42, -30]\n    regionWeight: 18\n    missionWeights:\n      STR_ALIEN_PROBE_MISSION: 14\n      STR_ALIEN_INTERDICTION: 16\n      STR_ALIEN_RESOURCE_RAID: 20\n      STR_ALIEN_INFILTRATION: 20\n      STR_ALIEN_BASE: 20\n    missionZones:  # lonMin lonMax latMin latMax\n      -\n        - [300, 301, -58, -57]\n        - [306, 307, -53, -52]\n        - [320, 321, -58, -57]\n        - [347, 347.5, -40, -39]\n        - [347, 348, -59, -58]\n        - [318, 318.5, -45, -43.25]\n        - [347, 349.75, -30, -28.875]\n        - [305, 306.25, -32, -31.125]\n        - [325, 326.75, -25, -23.625]\n        - [340, 340.875, -55, -53.75]\n      -\n        - [265.75, 266.25, -62, -61.5]\n        - [281, 281.75, -66, -65.25]\n        - [282, 283.5, -63, -61.25]\n        - [288, 289.5, -37, -35.875]\n        - [337, 338.625, -62, -59.5]\n        - [298, 299.5, -48, -46.125]\n        - [313, 314.5, -54, -51.5]\n        - [310, 310.875, -33, -31.125]\n        - [331, 332.5, -31, -28]\n        - [345, 346.25, -40, -39.375]\n      -\n        - [274.5, 277.625, -57.5, -54]\n        - [283, 283.25, -30, -29.375]\n        - [297, 298, -37, -35.125]\n        - [325, 330.25, -44, -37]\n        - [331, 333.75, -53, -50.375]\n        - [335, 336.75, -65, -63.625]\n        - [322, 324.75, -40, -38.875]\n        - [320, 321.5, -55.625, -54.875]\n      -\n        - [336, 336, -37, -37, -2, STR_AZORES]\n        - [337, 337, -61.25, -61.25, -1, STR_REYKJAVIK]\n        - [295.125, 295.125, -34.5, -34.5, -2, STR_BERMUDA]\n        - [286.875, 286.875, -38.25, -38.25, -1, STR_NEW_YORK]\n        - [290.25, 290.25, -41.25, -41.25, -1, STR_BOSTON]\n        - [271.25, 271.25, -50.875, -50.875, -1, STR_FORT_SEVERN]\n      -\n        - [281.5, 282.375, -57, -55.125]\n        - [323, 327.25, -51, -44.125]\n        - [282, 283.5, -63, -61.25]\n        - [288, 289.5, -37, -35.875]\n        - [337, 338.625, -62, -59.5]\n        - [298, 299.5, -48, -46.125]\n        - [325, 326.75, -25, -23.625]\n        - [347, 349.75, -30, -28.875]\n      -\n        - [303, 304, -66, -65]\n        - [347, 348, 53.5, 54.5]\n        - [354, 355.5, -64, -59.625]\n        - [79.5, 81.5, -16, -13.625]\n        - [330, 333.5, 33, 35.25]\n        - [350, 352.375, -70, -68.5]\n        - [70, 71.125, -70, -68.125]\n        - [4, 5.5, -38, -35.5]\n        - [273, 274.5, -23, -21.25]\n  - type: STR_SOUTH_ATLANTIC\n    cost: 950000\n    areas:\n      - [300, 347.5, -30, -3]\n      - [317.5, 11, -4, 22]\n      - [297, 11, 22, 40]\n      - [305, 320, -3, 5]\n    regionWeight: 4\n    missionWeights:\n      STR_ALIEN_PROBE_MISSION: 25\n      STR_ALIEN_INTERDICTION: 22\n      STR_ALIEN_RESOURCE_RAID: 12\n      STR_ALIEN_INFILTRATION: 20\n      STR_ALIEN_BASE: 25\n    missionZones:  # lonMin lonMax latMin latMax\n      -\n        - [303, 305.75, 51, 55]\n        - [325, 330, 6, 13.125]\n        - [328, 330.75, -22, -17.625]\n        - [351, 352.5, 28, 34.25]\n        - [9, 10.5, 35, 40.75]\n        - [325, 326.75, 11, 11.625]\n        - [5, 5.625, 11, 12.125]\n        - [343, 344.875, 35, 37.625]\n        - [330, 331.375, 0, 1]\n        - [318, 319.25, 30, 30.625]\n      -\n        - [296, 296.875, 42, 42.875]\n        - [339, 343, 17, 19.125]\n        - [4, 4.625, 2.5, 3.25]\n        - [303, 304.5, 51, 52.25]\n        - [9, 10, 35, 36.125]\n        - [340, 341.25, 20, 22.5]\n        - [340, 341.125, 30, 31.5]\n        - [310, 310.5, -22, -20.125]\n        - [5, 6.75, 40, 42.875]\n        - [325, 327.5, 0, 2.5]\n      -\n        - [295, 295.875, 56, 58.125]\n        - [303, 304.875, -24, -20.875]\n        - [9, 10, 23, 23.75]\n        - [332, 333, 27, 29]\n        - [345, 346.25, 20, 22.5]\n        - [4, 4.625, 2.5, 3.25]\n        - [320, 321.25, 3, 4.25]\n        - [340, 341.25, 3, 4.25]\n        - [325, 327.5, 0, 2.5]\n      -\n        - [343.75, 343.75, -14.75, -14.75, -1, STR_DAKAR]\n        - [319.375, 319.375, 8.625, 8.625, -1, STR_RECIFE]\n        - [359.75, 359.75, -4.25, -4.25, -2, STR_ACCRA]\n        - [345, 345, 8, 8, -1, STR_ASCENSION_ISLAND]\n        - [330, 330, 20.5, 20.5, -2, STR_TRINIDADE_ISLAND]\n        - [301, 301, 51, 51, -2, STR_FALKLAND_ISLAND]\n        - [339, 339, -26, -26, -2, STR_CANARY_ISLANDS]\n      -\n        - [305, 307.125, -9, -6.875]\n        - [350, 354, 12, 17.875]\n        - [5, 5.625, 11, 12.125]\n        - [343, 344.875, 35, 37.625]\n        - [330, 331.375, 0, 1]\n        - [318, 319.25, 30, 30.625]\n        - [303, 304.875, -24, -20.875]\n        - [4, 4.625, 2.5, 3.25]\n      -\n        - [79.5, 81.5, -16, -13.625]\n        - [330, 333.5, 33, 35.25]\n        - [273, 274.5, -23, -21.25]\n        - [350, 352.375, -70, -68.5]\n        - [303.125, 304.125, -66, -65]\n        - [347, 348, 53.5, 54.5]\n        - [70, 71.125, -70, -68.125]\n        - [70, 73.125, 60, 61.75]\n        - [0, 6.875, 60, 65.25]\n  - type: STR_NORTH_PACIFIC\n    cost: 900000\n    areas:\n      - [142, 230, -70, -20]\n      - [230, 243, -57, -30]\n    regionWeight: 4\n    missionWeights:\n      STR_ALIEN_PROBE_MISSION: 25\n      STR_ALIEN_INTERDICTION: 16\n      STR_ALIEN_RESOURCE_RAID: 21\n      STR_ALIEN_INFILTRATION: 18\n      STR_ALIEN_BASE: 18\n    missionZones:  # lonMin lonMax latMin latMax\n      -\n        - [154, 157.125, -30, -26.125]\n        - [164, 166.75, -53, -47.375]\n        - [210, 215, -29, -24.875]\n        - [232, 238.375, -45, -39.5]\n        - [170, 172.75, -43.5, -41.375]\n        - [155, 156.75, -29, -27.5]\n      -\n        - [143, 143.625, -57, -56]\n        - [147, 148, -41, -40.625]\n        - [173, 174.625, -33, -30.25]\n        - [200, 202.75, -42, -38.875]\n        - [211, 211.5, -56, -55]\n        - [220, 223.125, -45, -41.125]\n        - [223, 223.25, -56, -55.25]\n        - [233, 234.875, -33, -28.75]\n      -\n        - [156, 156.625, -47, -46]\n        - [157, 158, -59, -58.625]\n        - [191, 193.875, -59, -54.375]\n        - [195, 197, -25, -19.625]\n        - [218, 221.75, -51, -44.625]\n      -\n        - [210.125, 210.125, -57.75, -57.75, -1, STR_ANCHORAGE]\n        - [190, 190, -59.75, -59.75, -2, STR_ST_LAWRENCE_ISLAND]\n        - [238, 238, -37, -37, -1, STR_SAN_FRANCISCO]\n        - [182, 182, -28, -28, -2, STR_MIDWAY_ISLAND]\n        - [237.75, 237.75, -49, -49, -1, STR_VANCOUVER]\n      -\n        - [150, 150.25, -51, -49.875]\n        - [187, 188.875, -50, -46.125]\n        - [191, 193.875, -59, -54.375]\n        - [195, 197, -25, -19.625]\n        - [218, 221.75, -51, -44.625]\n        - [233, 234.875, -33, -28.75]\n        - [154, 157.125, -30, -26.125]\n        - [164, 166.75, -53, -47.375]\n      -\n        - [184, 187.125, -63, -60.875]\n        - [145, 146.625, -22, -20]\n        - [165, 166.5, -70, -68.25]\n        - [235, 236.625, -70, -68]\n        - [273, 274.5, -23, -21.25]\n        - [163.5, 166.125, -10, -7.625]\n        - [187, 188.5, 24, 27.875]\n        - [132, 134.625, 5, 7.375]\n        - [124.25, 125.875, -24, -21.625]\n  - type: STR_SOUTH_PACIFIC\n    cost: 600000\n    areas:\n      - [142, 230, -20, 8]\n      - [230, 266, -30, 8]\n      - [142, 292, 8, 65]\n    regionWeight: 10\n    missionWeights:\n      STR_ALIEN_PROBE_MISSION: 10\n      STR_ALIEN_INTERDICTION: 24\n      STR_ALIEN_RESOURCE_RAID: 12\n      STR_ALIEN_INFILTRATION: 18\n      STR_ALIEN_BASE: 20\n    missionZones:\n      -\n        - [159, 161.25, -12, -10]\n        - [142.5, 143.5, 46.5, 47.375]\n        - [165, 165.75, 56, 58]\n        - [187, 188.5, -4, -0.625]\n        - [203, 205.375, 34, 37.125]\n        - [217, 219.375, 31, 33.25]\n        - [245, 247.125, 30, 31.875]\n        - [238.5, 241.25, -18, -13.5]\n        - [270, 271.5, 53, 55.75]\n      -\n        - [148, 148.25, 41, 41.5]\n        - [169, 172, -5, -2.5]\n        - [174, 174.375, 45, 46.5]\n        - [197, 198, -52, -49.25]\n        - [208, 210, -4, -1.875]\n        - [234, 235.25, -44, -41]\n        - [270, 271.5, 53, 55.75]\n        - [174, 176.25, 34, 37]\n      -\n        - [150, 150.5, 46, 47.875]\n        - [160, 162.875, 35, 37.875]\n        - [174, 176.25, 34, 37]\n        - [231, 234.125, 2, 7.625]\n        - [268, 269.625, 17, 20]\n      -\n        - [147.5, 147.5, 40.75, 40.75, -1, STR_TASMANIA]\n        - [204.5, 204.5, -20.25, -20.25, -2, STR_HAWAII]\n        - [178, 178, 17, 17, -2, STR_FIJI]\n        - [189, 189, 19, 19, -2, STR_TONGA]\n        - [241, 241, 26.5, 26.5, -2, STR_EASTER_ISLAND]\n        - [269, 269, 1, 1, -2, STR_GALAPAGOS_ISLAND]\n        - [175, 175, 40.25, 40.25, -1, STR_WELLINGTON]\n        - [161.25, 161.25, 9, 9, -2, STR_SOLOMON_ISLAND]\n      -\n        - [212, 214.75, 17, 21.375]\n        - [273, 276.625, 29, 33.5]\n        - [174, 176.25, 34, 37]\n        - [231, 234.125, 2, 7.625]\n        - [268, 269.625, 17, 20]\n        - [148, 148.25, 41, 41.5]\n        - [169, 172, -5, -2.5]\n      -\n        - [163.5, 166.125, -10, -7.625]\n        - [187, 188.5, 24, 27.875]\n        - [184, 187.125, -63, -60.875]\n        - [145, 146.625, -22, -20]\n        - [120, 124.25, 60, 66.5]\n        - [132, 134.625, 5, 7.375]\n        - [124.25, 125.875, -24, -21.75]\n        - [273, 274.5, -23, -21.25]\n  - type: STR_MEDITERRANEAN\n    cost: 1000000\n    areas:\n      - [1, 40, -48, -30]\n      - [353, 1, -41, -32]\n    regionWeight: 16\n    missionWeights:\n      STR_ALIEN_PROBE_MISSION: 10\n      STR_ALIEN_INTERDICTION: 10\n      STR_ALIEN_RESOURCE_RAID: 15\n      STR_ALIEN_INFILTRATION: 20\n      STR_ALIEN_BASE: 6\n    missionZones:  # lonMin lonMax latMin latMax\n      -\n        - [27, 28.75, -38, -36]\n        - [28, 29.375, -32, -25.125]\n      -\n        - [13, 16.75, -42, -40.875]\n        - [37, 39.25, -41, -37]\n      -\n        - [15, 18, -31, -28.5]\n      -\n        - [25, 25, -35.125, -35.125, -2, STR_CRETE]\n        - [352.5, 352.5, -36.25, -36.25, -1, STR_LISBON]\n        - [32, 32, -30, -30, -1, STR_PORT_SAID]\n        - [5, 5, -40, -40, -1, STR_MARSEILLES]\n        - [13, 13, -29.375, -29.375, -1, STR_TRIPOLI]\n      -\n        - [10, 11.375, -42.75, -40.25]\n        - [15, 18, -32.25, -29.75]\n        - [13, 16.75, -42, -40.875]\n        - [37, 39.25, -41, -37]\n      -\n        - [4, 5.5, -38, -35.5]\n        - [354, 355.5, -64, -59.625]\n        - [303.125, 304.125, -66, -65]\n        - [347, 348, 53.5, 54.5]\n        - [350, 352.375, -70, -68.5]\n        - [70, 71.125, -70, -68.125]\n        - [79.5, 81.5, -16, -13.625]\n        - [273, 274.5, -23, -21.25]\n        - [163.5, 166.125, -10, -7.625]\n  - type: STR_SOUTH_CHINA_SEA\n    cost: 650000\n    areas:\n      - [101, 142, -24, 30]\n      - [96, 101, -3, 30]\n    regionWeight: 12\n    missionWeights:\n      STR_ALIEN_PROBE_MISSION: 8\n      STR_ALIEN_INTERDICTION: 8\n      STR_ALIEN_RESOURCE_RAID: 8\n      STR_ALIEN_INFILTRATION: 8\n      STR_ALIEN_BASE: 19\n    missionZones:\n      -\n        - [141, 144.5, 11, 13.875]\n        - [111, 114.625, -18, -15.625]\n        - [108, 111, 10, 13.625]\n      -\n        - [118, 121.125, -9, -4.75]\n        - [126, 128.375, -17, -13]\n        - [124, 126.75, -4, -0.125]\n        - [124, 125.75, 7, 9.75]\n      -\n        - [116, 117.25, 12, 15.625]\n        - [139, 142, -18, -15.875]\n        - [140, 143.375, -4, -2.125]\n      -\n        - [121, 121, -14.5, -14.5, -1, STR_MANILA]\n        - [114, 114, -23, -23, -1, STR_HONG_KONG]\n        - [102.625, 102.625, -1.25, -1.25, -1, STR_SINGAPORE]\n        - [100.5, 100.5, -12.5, -12.5, -1, STR_BANGKOK]\n        - [131, 131, 13.25, 13.25, -1, STR_DARWIN]\n      -\n        - [110, 112.625, 5, 6.75]\n        - [126, 128.375, -17, -13]\n        - [115.25, 118, -4, -0.125]\n        - [124, 125.75, 7, 9.75]\n      -\n        - [132, 134.625, 5, 7.375]\n        - [124.25, 125.875, -24, -21.625]\n        - [184, 187.125, -63, -60.875]\n        - [145, 146.625, -22, -20]\n        - [163.5, 166.125, -10, -7.625]\n        - [187, 188.5, 24, 27.875]\n        - [165, 166.5, -70, -68.25]\n        - [235, 236.625, -70, -68]\n        - [72, 74.5, 50, 52.875]\n        - [100, 101.625, 40, 41.75]\n  - type: STR_INDIAN_OCEAN\n    cost: 550000\n    areas:\n      - [54.5, 78, -24, 40.5]\n      - [78, 101, -24, -3]\n      - [78, 96, -3, 40]\n    regionWeight: 8\n    missionWeights:\n      STR_ALIEN_PROBE_MISSION: 7\n      STR_ALIEN_INTERDICTION: 8\n      STR_ALIEN_RESOURCE_RAID: 8\n      STR_ALIEN_INFILTRATION: 8\n      STR_ALIEN_BASE: 9\n    missionZones:\n      -\n        - [56, 57.25, -16, -14.25]\n        - [72, 74.5, 21, 23.375]\n        - [64, 65.625, 1, 2.625]\n        - [93, 94.5, 23, 26.875]\n        - [80, 81.125, 0, 1.5]\n        - [89, 90.75, -11, -9]\n      -\n        - [57, 60.125, 40, 42.75]\n        - [72, 74.75, 40, 43.25]\n        - [64, 65.625, 1, 4.125]\n        - [79, 81, 22, 24]\n        - [83, 84.125, 11, 13.125]\n        - [84, 85.375, -4, -1.125]\n        - [86, 87.5, -18, -16.125]\n      -\n        - [55, 58.875, 11, 13.5]\n        - [64, 65, 30, 31.5]\n        - [74, 77.25, 20, 23.625]\n        - [72, 74.5, -4, -1.5]\n        - [66, 66.375, -18, -16.25]\n      -\n        - [73, 73, -19, -19, -1, STR_BOMBAY]\n        - [56, 56, 4.5, 4.5, -2, STR_SAYCHELLES_ISLAND]\n        - [73, 73, -6.5, -6.5, -2, STR_MALDIVE_ISLAND]\n        - [79.75, 79.75, -7, -7, -2, STR_SRI_LANKA]\n        - [53, 53, 20.5, 20.5, -2, STR_MAURITIUS]\n      -\n        - [72, 74.375, 8, 11.125]\n        - [89, 91.375, -9, -7.375]\n        - [55, 58.875, 11, 13.5]\n        - [64, 65, 30, 31.5]\n      -\n        - [72, 74.5, 50, 52.875]\n        - [100, 101.625, 40, 41.75]\n        - [70, 73.125, 60, 61.75]\n        - [0, 6.875, 60, 65.25]\n        - [132, 134.625, 5, 7.375]\n        - [124.25, 125.875, -24, -21.625]\n        - [79.5, 81.5, -16, -13.625]\n        - [330, 336, 33, 35.25]\n  - type: STR_THE_EAST_SEA\n    cost: 500000\n    areas:\n      - [112, 142, -47.5, -24]\n      - [133, 142, -50, -47.5]\n    regionWeight: 12\n    missionWeights:\n      STR_ALIEN_PROBE_MISSION: 5\n      STR_ALIEN_INTERDICTION: 5\n      STR_ALIEN_RESOURCE_RAID: 6\n      STR_ALIEN_INFILTRATION: 10\n      STR_ALIEN_BASE: 8\n    missionZones:\n      -\n        - [116, 117.25, -38, -36.5]\n        - [140, 142.75, -39.25, -35.25]\n        - [140, 142.625, -23, -18.625]\n      -\n        - [125, 127.5, -27, -23.375]\n        - [127, 128.125, -2, 0.25]\n        - [132, 133.5, -21, -18.25]\n      -\n        - [142, 144.125, -34, -31.125]\n        - [132, 133.5, -28, -25.625]\n        - [139, 141.625, -38, -34.75]\n      -\n        - [140, 140, -36, -36, -1, STR_TOKYO]\n        - [120.75, 120.75, -32, -32, -1, STR_SHANGHAI]\n        - [137, 137, -44.75, -44.75, -1, STR_VLADIVOSTOK]\n      -\n        - [123.25, 124.25, -28, -27.5]\n        - [140, 142.25, -37, -33.625]\n        - [132, 133.5, -21, -18.25]\n        - [120.75, 122, -38, -36.5]\n      -\n        - [124.25, 125.875, -24, -21.625]\n        - [132, 134.625, 5, 7.375]\n        - [184, 187.125, -63, -60.875]\n        - [145, 146.625, -22, -20]\n        - [163.5, 166.125, -10, -7.625]\n        - [187, 188.5, 24, 27.875]\n        - [165, 166.5, -70, -68.25]\n        - [235, 236.5, -70, -68.25]\n        - [235, 236.625, -70, -68]\n  - type: STR_NORTH_SEA\n    cost: 750000\n    areas:\n      - [349, 27, -66, -50]\n      - [349, 5, -50, -41]\n    regionWeight: 15\n    missionWeights:\n      STR_ALIEN_PROBE_MISSION: 8\n      STR_ALIEN_INTERDICTION: 13\n      STR_ALIEN_RESOURCE_RAID: 21\n      STR_ALIEN_INFILTRATION: 13\n      STR_ALIEN_BASE: 8\n    missionZones:\n      -\n        - [354, 356.625, -50, -48.25]\n        - [22, 22.75, -59, -57.75]\n        - [352, 353.25, -59, -57.375]\n        - [8, 9.25, 66, 66.625]\n      -\n        - [1, 4.375, -64, -58.625]\n        - [21, 22.5, -63, -61.875]\n        - [16, 17.25, 55, 56.125]\n        - [4, 5.75, 53, 55]\n      -\n        - [353, 354.625, -59, -57.5]\n        - [11, 12.125, -65, -63.5]\n        - [350, 351.25, -66, -65.375]\n        - [3, 4.25, -53.125, -52.375]\n        - [355, 355.625, -48, -47.375]\n        - [349, 349.625, -54, -53.5]\n      -\n        - [0, 0, -48.75, -48.75, -1, STR_LONDON]\n        - [353, 353, -58.25, -58.25, -2, STR_FAEROE_ISLAND]\n        - [356.25, 356.25, -53.75, -53.75, -1, STR_ABERDEEN]\n        - [10, 10, -58.125, -58.125, -1, STR_OSLO]\n      -\n        - [4, 6.25, -67, -64.375]\n        - [352, 353.5, -53, -50.625]\n        - [1, 4.375, -64, -58.625]\n        - [349, 349.625, -54, -53.5]\n      -\n        - [354, 355.5, -64, -59.625]\n        - [303.125, 304.125, -66, -65]\n        - [347, 348, 53.5, 54.5]\n        - [79.5, 81.5, -16, -13.625]\n        - [330, 333.5, 33, 35.25]\n        - [4, 5.5, -38, -35.5]\n        - [350, 352.375, -70, -68.5]\n        - [70, 71.125, -70, -68.125]\n        - [273, 274.5, -23, -21.25]\n  - type: STR_CARRIBEAN\n    cost: 800000\n    areas:\n      - [266, 301, -30, 8]\n    regionWeight: 10\n    missionWeights:\n      STR_ALIEN_PROBE_MISSION: 6\n      STR_ALIEN_RESOURCE_RAID: 4\n      STR_ALIEN_BASE: 9\n    missionZones:\n      -\n        - [282, 283.5, 11, 13.875]\n        - [296, 297.875, -25, -21.125]\n      -\n        - [287, 288.5, -18, -16.25]\n        - [283, 286.875, -25, -22.25]\n      -\n        - [294, 295.875, -22, -20]\n      -\n        - [287, 287, -17, -17, -1, STR_JAMAICA]\n        - [279.75, 279.75, -9, -9, -1, STR_PANAMA]\n        - [278.5, 278.5, -27, -27, -1, STR_MIAMI]\n      -\n        - [296, 298.375, -17, -13.75]\n        - [287, 288.5, -18, -16.25]\n        - [283, 286.875, -25, -22.25]\n        - [296, 297.875, -25, -21.125]\n      -\n        - [273, 274.5, -23, -21.25]\n        - [303.125, 304.125, -66, -65]\n        - [347, 348, 53.5, 54.5]\n        - [163.5, 166.125, -10, -7.625]\n        - [187, 188.5, 24, 27.875]\n        - [79.5, 81.5, -16, -13.625]\n        - [330, 333.5, 33, 35.25]\n        - [4, 5.5, -38, -35.5]\n        - [354, 355.5, -64, -59.625]\n  - type: STR_ANTARCTIC\n    cost: 750000\n    areas:\n      - [292, 142, 40, 80]\n      - [96, 142, 30, 40]\n      - [142, 212, 64, 80]\n      - [212, 292, 64, 80]\n    regionWeight: 10\n    missionWeights:\n      STR_ALIEN_PROBE_MISSION: 15\n      STR_ALIEN_BASE: 22\n    missionZones:\n      -\n        - [350, 353.25, 50, 54.125]\n        - [295, 300, 50, 53.125]\n        - [140, 142.625, 42, 48.25]\n        - [110, 113.125, 47, 51.625]\n        - [70, 72, 53, 58.25]\n      -\n        - [20, 22.625, 42, 46.375]\n        - [320, 322.5, 61, 66.25]\n        - [35, 38.375, 60, 62.875]\n        - [119, 121, 60, 65.25]\n        - [100, 102.875, 55.5, 60.625]\n      -\n        - [20, 22.625, 42, 46.375]\n        - [320, 322.5, 61, 66.25]\n        - [35, 38.375, 60, 62.875]\n        - [119, 121, 60, 65.25]\n        - [100, 102.875, 55.5, 60.625]\n      -\n        - [300, 303.75, 49, 51.5]\n        - [50, 52.875, 60, 62.375]\n      -\n        - [20, 22.625, 42, 46.375]\n        - [320, 322.5, 61, 66.25]\n        - [35, 38.375, 60, 62.875]\n        - [119, 121, 60, 65.25]\n        - [100, 102.875, 55.5, 60.625]\n      -\n        - [70, 73.125, 60, 61.75]\n        - [0, 3.125, 60, 65.25]\n        - [120, 123, 60, 66.5]\n        - [72, 74.5, 50, 52.875]\n        - [100, 101.625, 40, 41.75]\n        - [79.5, 81.5, -16, -13.625]\n        - [330, 333.5, 33, 35.25]\n        - [163.5, 166.125, -10, -7.625]\n        - [187, 188.5, 24, 27.875]\n        - [132, 134.625, 5, 7.375]\n  - type: STR_ARCTIC\n    cost: 600000\n    areas:\n      - [0, 360, -80, -70]\n      - [292, 40, -70, -66]\n      - [27, 40, -68.25, -58]\n    regionWeight: 5\n    missionWeights:\n      STR_ALIEN_PROBE_MISSION: 15\n      STR_ALIEN_BASE: 28\n    missionZones:\n      -\n        - [30, 32.375, -78, -76.5]\n        - [60, 62.625, -76, -74.375]\n        - [180, 183, -79, -77.75]\n        - [220, 221.75, -75, -73]\n      -\n        - [20, 21.75, -70, -68.875]\n        - [75, 76.5, -72, -70.5]\n        - [160, 161.5, -73, -71.25]\n        - [210, 211.625, -70, -68.375]\n      -\n        - [20, 21.75, -70, -68.875]\n        - [75, 76.5, -72, -70.5]\n        - [180, 183, -79, -77.75]\n        - [220, 221.75, -75, -73]\n      -\n        - [10, 12.625, 75, 77.375]\n        - [173, 174.25, 75, 79]\n      -\n        - [20, 21.75, -70, -68.875]\n        - [75, 76.5, -72, -70.5]\n        - [180, 183, -79, -77.75]\n        - [220, 221.75, -75, -73]\n      -\n        - [350, 352.375, -70, -68.5]\n        - [70, 71.125, -70, -68.125]\n        - [165, 166.5, -70, -68.25]\n        - [235, 236.625, -70, -68]\n        - [184, 187.125, -63, -60.875]\n        - [145, 146.625, -22, -20]\n        - [303.125, 304.125, -66, -65]\n        - [347, 348, 53.5, 54.5]\n        - [354, 355.5, -64, -59.625]\n        - [79.5, 81.5, -16, -13.625]\n  - type: STR_EURASIA\n    cost: 500000\n    missionRegion: STR_ARCTIC\n    areas:\n      - [40, 118, -70, -24]\n      - [118, 142, -70, -50]\n  - type: STR_NORTH_AMERICA\n    cost: 500000\n    missionRegion: STR_NORTH_ATLANTIC\n    areas:\n      - [230, 266, -70, -57]\n      - [240.5, 279.5, -57, -30]\n  - type: STR_AFRICA\n    cost: 500000\n    missionRegion: STR_SOUTH_ATLANTIC\n    areas:\n      - [347.5, 11, -30, -3]\n      - [11, 40, -30, 40]\n      - [40, 55, -24, 40]\n"
  },
  {
    "path": "bin/standard/xcom2/research.rul",
    "content": "research: #done: double check scores and times.\n  - name: STR_VIBRO_BLADE\n    cost: 500\n    points: 10\n    dependencies:\n      - STR_CALCINITE_CORPSE\n  - name: STR_THERMIC_LANCE\n    cost: 500\n    points: 10\n    dependencies:\n      - STR_VIBRO_BLADE\n      - STR_GILLMAN_CORPSE\n  - name: STR_HEAVY_THERMIC_LANCE\n    cost: 600\n    points: 10\n    dependencies:\n      - STR_THERMIC_LANCE\n  - name: STR_GAUSS_TECH\n    cost: 50\n    points: 10\n  - name: STR_GAUSS_PISTOL\n    cost: 100\n    points: 10\n    dependencies:\n      - STR_GAUSS_TECH\n  - name: STR_GAUSS_PISTOL_CLIP\n    cost: 60\n    points: 10\n    dependencies:\n      - STR_GAUSS_PISTOL\n  - name: STR_GAUSS_RIFLE\n    cost: 300\n    points: 10\n    dependencies:\n      - STR_GAUSS_PISTOL\n  - name: STR_GAUSS_RIFLE_CLIP\n    cost: 150\n    points: 10\n    dependencies:\n      - STR_GAUSS_RIFLE\n  - name: STR_HEAVY_GAUSS\n    cost: 460\n    points: 10\n    dependencies:\n      - STR_GAUSS_RIFLE\n  - name: STR_HEAVY_GAUSS_CLIP\n    cost: 230\n    points: 10\n    dependencies:\n      - STR_HEAVY_GAUSS\n  - name: STR_GAUSS_CANNON\n    cost: 420\n    points: 15\n    dependencies:\n      - STR_HEAVY_GAUSS_CLIP\n  - name: STR_GAUSS_DEFENSES\n    cost: 510\n    points: 15\n    dependencies:\n      - STR_GAUSS_CANNON\n  - name: STR_PARTICLE_DISTURBANCE_SENSOR\n    cost: 180\n    points: 20\n  - name: STR_MEDI_KIT\n    cost: 210\n    points: 20\n  - name: STR_AQUA_PLASTICS\n    cost: 400\n    points: 30\n    needItem: true\n    dependencies:\n      - STR_DEEP_ONE_CORPSE\n  - name: STR_ALIEN_CRYOGENICS\n    cost: 150\n    points: 30\n    needItem: true\n  - name: STR_ALIEN_CLONING\n    cost: 150\n    points: 30\n    needItem: true\n  - name: STR_ALIEN_LEARNING_ARRAYS\n    cost: 150\n    points: 30\n    needItem: true\n  - name: STR_ALIEN_IMPLANTER\n    cost: 150\n    points: 30\n    needItem: true\n  - name: STR_EXAMINATION_ROOM\n    cost: 150\n    points: 30\n    needItem: true\n  - name: STR_SONIC_PULSER\n    cost: 200\n    points: 20\n    needItem: true\n  - name: STR_MC_READER\n    cost: 600\n    points: 25\n    needItem: true\n    dependencies:\n      - STR_MC_LAB\n  - name: STR_ALIEN_ORIGINS\n    cost: 300\n    points: 60\n    dependencies:\n      - STR_AQUATOID_COMMANDER\n      - STR_AQUATOID_NAVIGATOR\n      - STR_AQUATOID_TECHNICIAN\n      - STR_AQUATOID_MEDIC\n      - STR_AQUATOID_SQUAD_LEADER\n      - STR_AQUATOID_SOLDIER\n      - STR_CALCINITE_TERRORIST\n      - STR_HALLUCINOID_TERRORIST\n      - STR_GILLMAN_COMMANDER\n      - STR_GILLMAN_TECHNICIAN\n      - STR_GILLMAN_SQUAD_LEADER\n      - STR_GILLMAN_SOLDIER\n      - STR_DEEP_ONE_TERRORIST\n      - STR_XARQUID_TERRORIST\n      - STR_TASOTH_SQUAD_LEADER\n      - STR_TASOTH_SOLDIER\n      - STR_TENTACULAT_TERRORIST\n      - STR_BIODRONE_TERRORIST\n      - STR_TRISCENE_TERRORIST\n      - STR_LOBSTERMAN_COMMANDER\n      - STR_LOBSTERMAN_NAVIGATOR\n      - STR_LOBSTERMAN_TECHNICIAN\n      - STR_LOBSTERMAN_SQUAD_LEADER\n      - STR_LOBSTERMAN_SOLDIER\n  - name: STR_DISRUPTOR_PULSE_LAUNCHER\n    cost: 900\n    points: 10\n    needItem: true\n    dependencies:\n      - STR_ZRBITE\n  - name: STR_DISRUPTOR_AMMO\n    cost: 300\n    points: 10\n    needItem: true\n    dependencies:\n      - STR_ZRBITE\n  - name: STR_PWT_CANNON\n    cost: 880\n    points: 25\n    dependencies:\n      - STR_DISRUPTOR_PULSE_LAUNCHER\n      - STR_DISRUPTOR_AMMO\n  - name: STR_PWT_DEFENSES\n    cost: 800\n    points: 25\n    dependencies:\n      - STR_PWT_CANNON\n  - name: STR_TLETH_ALIEN_CITY\n    cost: 600\n    points: 60\n    unlockFinalMission: true\n    dependencies:\n      - STR_COMMANDER_PLUS\n  - name: STR_COMMANDER_PLUS\n    cost: 0\n    points: 0\n    unlocks:\n      - STR_TLETH_ALIEN_CITY\n    requires:\n      - STR_THE_ULTIMATE_THREAT\n    dependencies:\n      - STR_LOBSTERMAN_COMMANDER\n  - name: STR_ZRBITE\n    cost: 450\n    points: 60\n    needItem: true\n  - name: STR_BOMBARDMENT_SHIELD\n    cost: 930\n    points: 25\n    dependencies:\n      - STR_THE_LATEST_FLYING_SUB\n  - name: STR_SONIC_PISTOL\n    cost: 600\n    points: 20\n    needItem: true\n  - name: STR_PISTOL_POWER_CLIP\n    cost: 400\n    points: 5\n    needItem: true\n  - name: STR_SONIC_BLASTA_RIFLE\n    cost: 700\n    points: 25\n    needItem: true\n  - name: STR_BLASTA_POWER_CLIP\n    cost: 400\n    points: 6\n    needItem: true\n  - name: STR_SONIC_CANNON\n    cost: 800\n    points: 30\n    needItem: true\n  - name: STR_CANNON_POWER_CLIP\n    cost: 400\n    points: 7\n    needItem: true\n  - name: STR_SONIC_OSCILLATOR\n    cost: 660\n    points: 25\n    dependencies:\n      - STR_SONIC_OSCILLATOR_DEP1\n      - STR_SONIC_OSCILLATOR_DEP2\n      - STR_SONIC_OSCILLATOR_DEP3\n  - name: STR_SONIC_DEFENSES\n    cost: 620\n    points: 25\n    dependencies:\n      - STR_SONIC_OSCILLATOR\n  - name: STR_SONIC_OSCILLATOR_DEP1\n    cost: 0\n    dependencies:\n      - STR_SONIC_PISTOL\n      - STR_PISTOL_POWER_CLIP\n  - name: STR_SONIC_OSCILLATOR_DEP2\n    cost: 0\n    dependencies:\n      - STR_SONIC_BLASTA_RIFLE\n      - STR_BLASTA_POWER_CLIP\n  - name: STR_SONIC_OSCILLATOR_DEP3\n    cost: 0\n    dependencies:\n      - STR_SONIC_CANNON\n      - STR_CANNON_POWER_CLIP\n  - name: STR_TRANSMISSION_RESOLVER\n    cost: 670\n    points: 25\n    dependencies:\n      - STR_MAGNETIC_NAVIGATION\n  - name: STR_NEW_FIGHTER_FLYING_SUB\n    cost: 600\n    points: 30\n    dependencies:\n      - STR_ALIEN_SUB_CONSTRUCTION\n      - STR_MAGNETIC_ION_ARMOR\n  - name: STR_NEW_FIGHTER_TRANSPORTER\n    cost: 700\n    points: 30\n    dependencies:\n      - STR_NEW_FIGHTER_FLYING_SUB\n  - name: STR_PLASTIC_AQUA_ARMOR\n    cost: 180\n    points: 20\n    dependencies:\n      - STR_AQUA_PLASTICS\n  - name: STR_ION_ARMOR\n    cost: 205\n    points: 20\n    dependencies:\n      - STR_ION_BEAM_ACCELERATORS\n      - STR_PLASTIC_AQUA_ARMOR\n      - STR_DEEP_ONE_TERRORIST\n  - name: STR_MAGNETIC_ION_ARMOR\n    cost: 330\n    points: 20\n    dependencies:\n      - STR_ION_ARMOR\n      - STR_MAGNETIC_NAVIGATION\n  - name: STR_MC_LAB\n    cost: 420\n    points: 25\n    dependencies:\n      - STR_CALCINITE_TERRORIST\n      - STR_HALLUCINOID_TERRORIST\n      - STR_DEEP_ONE_TERRORIST\n      - STR_XARQUID_TERRORIST\n      - STR_TENTACULAT_TERRORIST\n      - STR_BIODRONE_TERRORIST\n      - STR_TRISCENE_TERRORIST\n  - name: STR_MC_DISRUPTOR\n    cost: 500\n    points: 20\n    dependencies:\n      - STR_MC_READER\n      - STR_MC_DISRUPTOR_DEP\n  - name: STR_MC_DISRUPTOR_DEP\n    cost: 0\n    dependencies:\n      - STR_TASOTH_SOLDIER\n      - STR_TASOTH_SQUAD_LEADER\n  - name: STR_MC_GENERATOR\n    cost: 360\n    points: 25\n    dependencies:\n      - STR_MC_DISRUPTOR\n  - name: STR_THERMAL_SHOK_LAUNCHER\n    cost: 550\n    points: 30\n    needItem: true\n  - name: STR_THERMAL_SHOK_BOMB\n    cost: 180\n    points: 10\n    needItem: true\n  - name: STR_THE_ULTIMATE_THREAT\n    cost: 500\n    points: 60\n    dependencies:\n      - STR_ALIEN_ORIGINS\n      - STR_LEADER_PLUS\n  - name: STR_LEADER_PLUS\n    cost: 0\n    requires:\n      - STR_ALIEN_ORIGINS\n    dependencies:\n      - STR_LOBSTERMAN_COMMANDER\n      - STR_LOBSTERMAN_NAVIGATOR\n      - STR_GILLMAN_COMMANDER\n  - name: STR_ALIEN_SUB_CONSTRUCTION\n    cost: 450\n    points: 30\n    needItem: true\n    dependencies:\n      - STR_TRANSMISSION_RESOLVER\n      - STR_ZRBITE\n  - name: STR_MAGNETIC_NAVIGATION\n    cost: 450\n    points: 30\n    needItem: true\n  - name: STR_ION_BEAM_ACCELERATORS\n    cost: 450\n    points: 30\n    needItem: true\n  - name: STR_THE_LATEST_FLYING_SUB\n    cost: 900\n    points: 30\n    dependencies:\n      - STR_NEW_FIGHTER_TRANSPORTER\n      - STR_LOBSTERMAN_COMMANDER\n  - name: STR_AQUATOID_CORPSE\n    cost: 180\n    points: 50\n    lookup: STR_AQUATOID_AUTOPSY\n    needItem: true\n  - name: STR_LOBSTERMAN_CORPSE\n    cost: 180\n    points: 50\n    lookup: STR_LOBSTERMAN_AUTOPSY\n    needItem: true\n  - name: STR_TASOTH_CORPSE\n    cost: 180\n    points: 50\n    lookup: STR_TASOTH_AUTOPSY\n    needItem: true\n  - name: STR_BIODRONE_CORPSE\n    cost: 180\n    points: 50\n    lookup: STR_BIODRONE_AUTOPSY\n    needItem: true\n  - name: STR_TENTACULAT_CORPSE\n    cost: 180\n    points: 50\n    lookup: STR_TENTACULAT_AUTOPSY\n    needItem: true\n  - name: STR_TRISCENE_CORPSE\n    cost: 180\n    points: 50\n    lookup: STR_TRISCENE_AUTOPSY\n    needItem: true\n  - name: STR_HALLUCINOID_CORPSE\n    cost: 180\n    points: 50\n    lookup: STR_HALLUCINOID_AUTOPSY\n    needItem: true\n  - name: STR_XARQUID_CORPSE\n    cost: 180\n    points: 50\n    lookup: STR_XARQUID_AUTOPSY\n    needItem: true\n  - name: STR_CALCINITE_CORPSE\n    cost: 180\n    points: 50\n    lookup: STR_CALCINITE_AUTOPSY\n    needItem: true\n    unlocks:\n      - STR_VIBRO_BLADE\n  - name: STR_GILLMAN_CORPSE\n    cost: 180\n    points: 50\n    lookup: STR_GILLMAN_AUTOPSY\n    needItem: true\n  - name: STR_DEEP_ONE_CORPSE\n    cost: 180\n    points: 50\n    lookup: STR_DEEP_ONE_AUTOPSY\n    needItem: true\n    unlocks:\n      - STR_AQUA_PLASTICS\n  - name: STR_AQUATOID_SOLDIER\n    cost: 192\n    points: 50\n    lookup: STR_AQUATOID\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_ALIEN_ORIGINS\n  - name: STR_AQUATOID_SQUAD_LEADER\n    cost: 192\n    points: 50\n    lookup: STR_AQUATOID\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_ALIEN_ORIGINS\n    getOneFree:\n      - STR_ALIEN_PROBE_MISSION\n      - STR_ALIEN_INTERDICTION\n      - STR_ALIEN_RESOURCE_RAID\n      - STR_ALIEN_INFILTRATION\n      - STR_ALIEN_BASE\n      - STR_ALIEN_SURFACE_ATTACK\n      - STR_ALIEN_RETALIATION\n      - STR_ALIEN_SUPPLY\n  - name: STR_AQUATOID_MEDIC\n    cost: 192\n    points: 50\n    lookup: STR_AQUATOID\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_ALIEN_ORIGINS\n    getOneFree:\n      - STR_CALCINITE\n      - STR_HALLUCINOID\n      - STR_GILLMAN\n      - STR_DEEP_ONE\n      - STR_XARQUID\n      - STR_TASOTH\n      - STR_TENTACULAT\n      - STR_BIODRONE\n      - STR_TRISCENE\n      - STR_LOBSTERMAN\n      - STR_CALCINITE_AUTOPSY\n      - STR_HALLUCINOID_AUTOPSY\n      - STR_GILLMAN_AUTOPSY\n      - STR_DEEP_ONE_AUTOPSY\n      - STR_XARQUID_AUTOPSY\n      - STR_TASOTH_AUTOPSY\n      - STR_TENTACULAT_AUTOPSY\n      - STR_BIODRONE_AUTOPSY\n      - STR_TRISCENE_AUTOPSY\n      - STR_LOBSTERMAN_AUTOPSY\n  - name: STR_AQUATOID_TECHNICIAN\n    cost: 192\n    points: 50\n    lookup: STR_AQUATOID\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_ALIEN_ORIGINS\n    getOneFree:\n      - STR_SURVEY_SHIP\n      - STR_ESCORT\n      - STR_CRUISER\n      - STR_HEAVY_CRUISER\n      - STR_HUNTER\n      - STR_BATTLESHIP\n      - STR_DREADNOUGHT\n      - STR_FLEET_SUPPLY_CRUISER\n  - name: STR_AQUATOID_NAVIGATOR\n    cost: 192\n    points: 50\n    lookup: STR_AQUATOID\n    unlocks:\n      - STR_ALIEN_ORIGINS\n    needItem: true\n    destroyItem: true\n  - name: STR_AQUATOID_COMMANDER\n    cost: 192\n    points: 50\n    lookup: STR_AQUATOID\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_ALIEN_ORIGINS\n  - name: STR_GILLMAN_SOLDIER\n    cost: 192\n    points: 50\n    lookup: STR_GILLMAN\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_ALIEN_ORIGINS\n  - name: STR_GILLMAN_SQUAD_LEADER\n    cost: 192\n    points: 50\n    lookup: STR_GILLMAN\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_ALIEN_ORIGINS\n    getOneFree:\n      - STR_ALIEN_PROBE_MISSION\n      - STR_ALIEN_INTERDICTION\n      - STR_ALIEN_RESOURCE_RAID\n      - STR_ALIEN_INFILTRATION\n      - STR_ALIEN_BASE\n      - STR_ALIEN_SURFACE_ATTACK\n      - STR_ALIEN_RETALIATION\n      - STR_ALIEN_SUPPLY\n  - name: STR_GILLMAN_TECHNICIAN\n    cost: 192\n    points: 50\n    lookup: STR_GILLMAN\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_ALIEN_ORIGINS\n    getOneFree:\n      - STR_SURVEY_SHIP\n      - STR_ESCORT\n      - STR_CRUISER\n      - STR_HEAVY_CRUISER\n      - STR_HUNTER\n      - STR_BATTLESHIP\n      - STR_DREADNOUGHT\n      - STR_FLEET_SUPPLY_CRUISER\n  - name: STR_GILLMAN_COMMANDER\n    cost: 192\n    points: 50\n    lookup: STR_GILLMAN\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_LEADER_PLUS\n      - STR_ALIEN_ORIGINS\n  - name: STR_LOBSTERMAN_SOLDIER\n    cost: 192\n    points: 50\n    lookup: STR_LOBSTERMAN\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_ALIEN_ORIGINS\n  - name: STR_LOBSTERMAN_SQUAD_LEADER\n    cost: 192\n    points: 50\n    lookup: STR_LOBSTERMAN\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_ALIEN_ORIGINS\n    getOneFree:\n      - STR_ALIEN_PROBE_MISSION\n      - STR_ALIEN_INTERDICTION\n      - STR_ALIEN_RESOURCE_RAID\n      - STR_ALIEN_INFILTRATION\n      - STR_ALIEN_BASE\n      - STR_ALIEN_SURFACE_ATTACK\n      - STR_ALIEN_RETALIATION\n      - STR_ALIEN_SUPPLY\n  - name: STR_LOBSTERMAN_TECHNICIAN\n    cost: 192\n    points: 50\n    lookup: STR_LOBSTERMAN\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_ALIEN_ORIGINS\n    getOneFree:\n      - STR_SURVEY_SHIP\n      - STR_ESCORT\n      - STR_CRUISER\n      - STR_HEAVY_CRUISER\n      - STR_HUNTER\n      - STR_BATTLESHIP\n      - STR_DREADNOUGHT\n      - STR_FLEET_SUPPLY_CRUISER\n  - name: STR_LOBSTERMAN_NAVIGATOR\n    cost: 192\n    points: 50\n    lookup: STR_LOBSTERMAN\n    unlocks:\n      - STR_LEADER_PLUS\n      - STR_ALIEN_ORIGINS\n    needItem: true\n    destroyItem: true\n  - name: STR_LOBSTERMAN_COMMANDER\n    cost: 192\n    points: 50\n    lookup: STR_LOBSTERMAN\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_LEADER_PLUS\n      - STR_COMMANDER_PLUS\n      - STR_ALIEN_ORIGINS\n  - name: STR_TASOTH_SOLDIER\n    cost: 192\n    points: 50\n    lookup: STR_TASOTH\n    unlocks:\n      - STR_ALIEN_ORIGINS\n      - STR_MC_DISRUPTOR_DEP\n    needItem: true\n    destroyItem: true\n  - name: STR_TASOTH_SQUAD_LEADER\n    cost: 192\n    points: 50\n    lookup: STR_TASOTH\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_ALIEN_ORIGINS\n      - STR_MC_DISRUPTOR_DEP\n    getOneFree:\n      - STR_ALIEN_PROBE_MISSION\n      - STR_ALIEN_INTERDICTION\n      - STR_ALIEN_RESOURCE_RAID\n      - STR_ALIEN_INFILTRATION\n      - STR_ALIEN_BASE\n      - STR_ALIEN_SURFACE_ATTACK\n      - STR_ALIEN_RETALIATION\n      - STR_ALIEN_SUPPLY\n  - name: STR_AQUATOID\n    cost: 0\n    points: 50\n    needItem: true\n  - name: STR_LOBSTERMAN\n    cost: 0\n    points: 50\n    needItem: true\n  - name: STR_TASOTH\n    cost: 0\n    points: 50\n    needItem: true\n  - name: STR_BIODRONE\n    cost: 0\n    points: 50\n    needItem: true\n  - name: STR_TENTACULAT\n    cost: 0\n    points: 50\n    needItem: true\n  - name: STR_TRISCENE\n    cost: 0\n    points: 50\n    needItem: true\n  - name: STR_HALLUCINOID\n    cost: 0\n    points: 50\n    needItem: true\n  - name: STR_XARQUID\n    cost: 0\n    points: 50\n    needItem: true\n  - name: STR_DEEP_ONE\n    cost: 0\n    points: 50\n    needItem: true\n  - name: STR_GILLMAN\n    cost: 0\n    points: 50\n    needItem: true\n  - name: STR_CALCINITE\n    cost: 0\n    points: 50\n    needItem: true\n\n\n  - name: STR_BIODRONE_TERRORIST\n    cost: 170\n    points: 50\n    lookup: STR_BIODRONE\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_ALIEN_ORIGINS\n      - STR_MC_LAB\n  - name: STR_CALCINITE_TERRORIST\n    cost: 170\n    points: 50\n    lookup: STR_CALCINITE\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_ALIEN_ORIGINS\n      - STR_MC_LAB\n  - name: STR_DEEP_ONE_TERRORIST\n    cost: 170\n    points: 50\n    lookup: STR_DEEP_ONE\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_ALIEN_ORIGINS\n      - STR_MC_LAB\n  - name: STR_HALLUCINOID_TERRORIST\n    cost: 170\n    points: 50\n    lookup: STR_HALLUCINOID\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_ALIEN_ORIGINS\n      - STR_MC_LAB\n  - name: STR_TENTACULAT_TERRORIST\n    cost: 170\n    points: 50\n    lookup: STR_TENTACULAT\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_ALIEN_ORIGINS\n      - STR_MC_LAB\n  - name: STR_TRISCENE_TERRORIST\n    cost: 170\n    points: 50\n    lookup: STR_TRISCENE\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_ALIEN_ORIGINS\n      - STR_MC_LAB\n  - name: STR_XARQUID_TERRORIST\n    cost: 170\n    points: 50\n    lookup: STR_XARQUID\n    needItem: true\n    destroyItem: true\n    unlocks:\n      - STR_ALIEN_ORIGINS\n      - STR_MC_LAB\n  - name: STR_ALIEN_PROBE_MISSION\n    cost: 0\n    points: 50\n    needItem: true\n  - name: STR_ALIEN_INTERDICTION\n    cost: 0\n    points: 50\n    needItem: true\n  - name: STR_ALIEN_RESOURCE_RAID\n    cost: 0\n    points: 50\n    needItem: true\n  - name: STR_ALIEN_INFILTRATION\n    cost: 0\n    points: 50\n    needItem: true\n  - name: STR_ALIEN_BASE\n    cost: 0\n    points: 50\n    needItem: true\n  - name: STR_ALIEN_SURFACE_ATTACK\n    cost: 0\n    points: 50\n    needItem: true\n  - name: STR_ALIEN_RETALIATION\n    cost: 0\n    points: 50\n    needItem: true\n  - name: STR_ALIEN_SUPPLY\n    cost: 0\n    points: 50\n    needItem: true\n  - name: STR_SURVEY_SHIP\n    cost: 0\n    points: 50\n    needItem: true\n  - name: STR_ESCORT\n    cost: 0\n    points: 50\n    needItem: true\n  - name: STR_CRUISER\n    cost: 0\n    points: 50\n    needItem: true\n  - name: STR_HEAVY_CRUISER\n    cost: 0\n    points: 50\n    needItem: true\n  - name: STR_HUNTER\n    cost: 0\n    points: 50\n    needItem: true\n  - name: STR_BATTLESHIP\n    cost: 0\n    points: 50\n    needItem: true\n  - name: STR_DREADNOUGHT\n    cost: 0\n    points: 50\n    needItem: true\n  - name: STR_FLEET_SUPPLY_CRUISER\n    cost: 0\n    points: 50\n    needItem: true\n  - name: STR_AQUATOID_AUTOPSY\n    cost: 0\n    points: 50\n    needItem: true\n  - name: STR_LOBSTERMAN_AUTOPSY\n    cost: 0\n    points: 50\n    needItem: true\n  - name: STR_TASOTH_AUTOPSY\n    cost: 0\n    points: 50\n    needItem: true\n  - name: STR_BIODRONE_AUTOPSY\n    cost: 0\n    points: 50\n    needItem: true\n  - name: STR_TENTACULAT_AUTOPSY\n    cost: 0\n    points: 50\n    needItem: true\n  - name: STR_TRISCENE_AUTOPSY\n    cost: 0\n    points: 50\n    needItem: true\n  - name: STR_HALLUCINOID_AUTOPSY\n    cost: 0\n    points: 50\n    needItem: true\n  - name: STR_XARQUID_AUTOPSY\n    cost: 0\n    points: 50\n    needItem: true\n  - name: STR_CALCINITE_AUTOPSY\n    cost: 0\n    points: 50\n    needItem: true\n  - name: STR_GILLMAN_AUTOPSY\n    cost: 0\n    points: 50\n    needItem: true\n  - name: STR_DEEP_ONE_AUTOPSY\n    cost: 0\n    points: 50\n    needItem: true\n"
  },
  {
    "path": "bin/standard/xcom2/soldiers.rul",
    "content": "soldiers: #done\n  - type: STR_SOLDIER\n    costBuy: 40000\n    costSalary: 20000\n    minStats:\n      tu: 50\n      stamina: 40\n      health: 25\n      bravery: 10\n      reactions: 30\n      firing: 40\n      throwing: 50\n      strength: 20\n      psiStrength: 0\n# psiSkill here is treated as the initial stat\n      psiSkill: 0\n      melee: 20\n    maxStats:\n      tu: 60\n      stamina: 70\n      health: 40\n      bravery: 60\n      reactions: 60\n      firing: 70\n      throwing: 80\n      strength: 40\n      psiStrength: 100\n# psiSkill here is treated as the minimum value for the initial month of training using\n# a random number between (this) and (150% of this)\n      psiSkill: 16\n      melee: 40\n# Note: caps are not absolute, it IS possible to go one or two points over (at most)\n# this is NOT a bug, it is a design choice, for variety's sake.\n# bravery is ALWAYS treated in multiples of 10, and cannot go above the cap. 101 will be treated as 110\n# psi strength is NEVER increased.\n    statCaps:\n      tu: 80\n      stamina: 100\n      health: 60\n      bravery: 100\n      reactions: 100\n      firing: 120\n      throwing: 120\n      strength: 70\n      psiStrength: 100\n      psiSkill: 100\n      melee: 120\n    armor: STR_NONE_UC\n    standHeight: 22\n    kneelHeight: 14\n    femaleFrequency: 25\n    soldierNames:\n      - SoldierName/\n    deathMale: 48\n    deathFemale: 48\n"
  },
  {
    "path": "bin/standard/xcom2/startingBase.rul",
    "content": "startingBase: #done\n  facilities:\n    - type: STR_AIR_LOCK\n      x: 2\n      y: 2\n    - type: STR_SUB_PEN\n      x: 2\n      y: 0\n    - type: STR_SUB_PEN\n      x: 0\n      y: 4\n    - type: STR_SUB_PEN\n      x: 4\n      y: 4\n    - type: STR_LIVING_QUARTERS\n      x: 3\n      y: 2\n    - type: STR_GENERAL_STORES\n      x: 2\n      y: 3\n    - type: STR_LABORATORY\n      x: 3\n      y: 3\n    - type: STR_WORKSHOP\n      x: 4\n      y: 3\n    - type: STR_STANDARD_SONAR\n      x: 1\n      y: 3\n  randomSoldiers: 8\n  crafts:\n    - lon: 0.0\n      lat: 0.0\n      speedLon: 0\n      speedLat: 0\n      speedRadian: 0\n      speed: 0\n      type: STR_TRITON\n      id: 1\n      fuel: 1400\n      damage: 0\n      weapons:\n        []\n      items:\n        STR_MAGNA_BLAST_GRENADE: 8\n        STR_GC_AP_AMMO: 2\n        STR_GC_HE_AMMO: 2\n        STR_GAS_CANNON: 1\n        STR_DART_PISTOL: 3\n        STR_DART_POD: 5\n        STR_JET_HARPOON: 6\n        STR_HARPOON_POD: 12\n      vehicles:\n        []\n      status: STR_READY\n      lowFuel: false\n      inBattlescape: false\n      inDogfight: false\n      interceptionOrder: 0\n    - lon: 0.0\n      lat: 0.0\n      speedLon: 0\n      speedLat: 0\n      speedRadian: 0\n      speed: 0\n      type: STR_BARRACUDA\n      id: 1\n      fuel: 800\n      damage: 0\n      weapons:\n        - type: STR_AJAX\n          ammo: 6\n          rearming: false\n        - type: STR_CRAFT_GAS_CANNON_UC\n          ammo: 200\n          rearming: false\n      items:\n        {}\n      vehicles:\n        []\n      status: STR_READY\n      lowFuel: false\n      inBattlescape: false\n      inDogfight: false\n      interceptionOrder: 0\n    - lon: 0.0\n      lat: 0.0\n      speedLon: 0\n      speedLat: 0\n      speedRadian: 0\n      speed: 0\n      type: STR_BARRACUDA\n      id: 2\n      fuel: 800\n      damage: 0\n      weapons:\n        - type: STR_AJAX\n          ammo: 6\n          rearming: false\n        - type: STR_CRAFT_GAS_CANNON_UC\n          ammo: 200\n          rearming: false\n      items:\n        {}\n      vehicles:\n        []\n      status: STR_READY\n      lowFuel: false\n      inBattlescape: false\n      inDogfight: false\n      interceptionOrder: 0\n  items:\n    STR_HJC_AP_AMMO: 6\n    STR_HYDRO_JET_CANNON: 1\n    STR_DUP_HEAD_LAUNCHER: 1\n    STR_DUP_HEAD_TORPEDOES: 10\n    STR_CRAFT_GAS_CANNON: 2\n    STR_CRAFT_GAS_CANNON_ROUNDS_X50: 1\n    STR_MAGNA_BLAST_GRENADE: 5\n    STR_GC_AP_AMMO: 6\n    STR_GAS_CANNON: 1\n    STR_DART_PISTOL: 2\n    STR_DART_POD: 8\n    STR_JET_HARPOON: 2\n    STR_HARPOON_POD: 8\n    STR_TORPEDO_LAUNCHER: 1\n    STR_SMALL_TORPEDO: 4\n    STR_DYE_GRENADE: 5\n    STR_AJAX_LAUNCHER: 1\n    STR_AJAX_TORPEDOES: 25\n  scientists: 10\n  engineers: 10\n"
  },
  {
    "path": "bin/standard/xcom2/terrains.rul",
    "content": "terrains: #done\n  - name: SEABED\n    music:\n      - GMTACWET\n    mapDataSets:\n      - BLANKS\n      - SAND\n      - ROCKS\n      - WEEDS\n      - DEBRIS\n      - UFOBITS\n    depth: [1, 2]\n    ambience: 67\n    script: THREEBIG\n    mapBlocks:\n      - name: SEABED00\n        width: 10\n        length: 10\n        groups: 1\n      - name: SEABED01\n        width: 10\n        length: 10\n        groups: 1\n      - name: SEABED02\n        width: 10\n        length: 10\n      - name: SEABED03\n        width: 10\n        length: 10\n      - name: SEABED04\n        width: 10\n        length: 10\n      - name: SEABED05\n        width: 10\n        length: 10\n      - name: SEABED06\n        width: 10\n        length: 10\n      - name: SEABED07\n        width: 10\n        length: 10\n      - name: SEABED08\n        width: 10\n        length: 10\n      - name: SEABED09\n        width: 10\n        length: 10\n      - name: SEABED10\n        width: 20\n        length: 20\n      - name: SEABED11\n        width: 20\n        length: 20\n      - name: SEABED12\n        width: 20\n        length: 20\n  - name: PIPES\n    music:\n      - GMTACWET\n    mapDataSets:\n      - BLANKS\n      - SAND\n      - PIPES\n      - UFOBITS\n    depth: [1, 2]\n    ambience: 67\n    script: THREEBIG\n    mapBlocks:\n      - name: PIPES00\n        width: 10\n        length: 10\n        groups: 1\n      - name: PIPES01\n        width: 10\n        length: 10\n      - name: PIPES02\n        width: 10\n        length: 10\n      - name: PIPES03\n        width: 10\n        length: 10\n      - name: PIPES04\n        width: 10\n        length: 10\n      - name: PIPES05\n        width: 10\n        length: 10\n      - name: PIPES06\n        width: 10\n        length: 10\n      - name: PIPES07\n        width: 10\n        length: 10\n      - name: PIPES08\n        width: 20\n        length: 20\n      - name: PIPES09\n        width: 20\n        length: 20\n      - name: PIPES10\n        width: 20\n        length: 20\n      - name: PIPES11\n        width: 20\n        length: 20\n  - name: PLANE\n    music:\n      - GMTACWET\n    mapDataSets:\n      - BLANKS\n      - SAND\n      - PLANE\n      - UFOBITS\n    depth: [1, 2]\n    ambience: 67\n    script: PLANE\n    mapBlocks:\n      - name: PLANE00\n        width: 10\n        length: 10\n        groups: 1\n      - name: PLANE01\n        width: 10\n        length: 10\n      - name: PLANE02\n        width: 10\n        length: 10\n      - name: PLANE03\n        width: 10\n        length: 10\n      - name: PLANE04\n        width: 10\n        length: 10\n      - name: PLANE05\n        width: 10\n        length: 10\n      - name: PLANE06\n        width: 10\n        length: 10\n      - name: PLANE07\n        width: 10\n        length: 10\n      - name: PLANE08\n        width: 10\n        length: 10\n      - name: PLANE09\n        width: 10\n        length: 10\n      - name: PLANE10\n        width: 10\n        length: 10\n      - name: PLANE11\n        width: 10\n        length: 10\n      - name: PLANE12\n        width: 10\n        length: 10\n      - name: PLANE13\n        width: 20\n        length: 20\n      - name: PLANE14\n        width: 20\n        length: 20\n      - name: PLANE15\n        width: 20\n        length: 20\n      - name: PLANE16\n        width: 20\n        length: 20\n      - name: PLANE17\n        width: 10\n        length: 10\n      - name: PLANE18\n        width: 10\n        length: 10\n      - name: PLANE19\n        width: 10\n        length: 10\n      - name: PLANE20\n        width: 10\n        length: 10\n  - name: ATLAN\n    music:\n      - GMTACWET\n    mapDataSets:\n      - BLANKS\n      - SAND\n      - ATLANTIS\n      - UFOBITS\n    depth: [1, 2]\n    ambience: 67\n    mapBlocks:\n      - name: ATLAN00\n        width: 10\n        length: 10\n        groups: 1\n      - name: ATLAN01\n        width: 10\n        length: 10\n      - name: ATLAN02\n        width: 10\n        length: 10\n      - name: ATLAN03\n        width: 10\n        length: 10\n      - name: ATLAN04\n        width: 10\n        length: 10\n      - name: ATLAN05\n        width: 10\n        length: 10\n      - name: ATLAN06\n        width: 10\n        length: 10\n      - name: ATLAN07\n        width: 10\n        length: 10\n      - name: ATLAN08\n        width: 10\n        length: 10\n      - name: ATLAN09\n        width: 10\n        length: 10\n      - name: ATLAN10\n        width: 20\n        length: 20\n      - name: ATLAN11\n        width: 20\n        length: 20\n  - name: MU\n    music:\n      - GMTACWET\n    mapDataSets:\n      - BLANKS\n      - SAND\n      - MU\n      - UFOBITS\n    depth: [1, 2]\n    ambience: 67\n    mapBlocks:\n      - name: MU00\n        width: 10\n        length: 10\n        groups: 1\n      - name: MU01\n        width: 10\n        length: 10\n      - name: MU02\n        width: 10\n        length: 10\n      - name: MU03\n        width: 10\n        length: 10\n      - name: MU04\n        width: 10\n        length: 10\n      - name: MU05\n        width: 10\n        length: 10\n      - name: MU06\n        width: 10\n        length: 10\n      - name: MU07\n        width: 10\n        length: 10\n      - name: MU08\n        width: 10\n        length: 10\n      - name: MU09\n        width: 20\n        length: 20\n      - name: MU10\n        width: 20\n        length: 20\n      - name: MU11\n        width: 20\n        length: 20\n  - name: GAL\n    music:\n      - GMTACWET\n    mapDataSets:\n      - BLANKS\n      - SAND\n      - ROCKS\n      - ASUNK\n      - UFOBITS\n    depth: [1, 2]\n    ambience: 67\n    mapBlocks:\n      - name: GAL01\n        width: 20\n        length: 20\n      - name: GAL02\n        width: 20\n        length: 20\n      - name: GAL03\n        width: 20\n        length: 20\n      - name: GAL04\n        width: 10\n        length: 10\n      - name: GAL05\n        width: 10\n        length: 10\n      - name: GAL06\n        width: 10\n        length: 10\n      - name: GAL07\n        width: 10\n        length: 10\n      - name: GAL08\n        width: 10\n        length: 10\n      - name: GAL09\n        width: 10\n        length: 10\n      - name: GAL10\n        width: 10\n        length: 10\n      - name: GAL11\n        width: 10\n        length: 10\n      - name: GAL12\n        width: 10\n        length: 10\n      - name: GAL13\n        width: 10\n        length: 10\n        groups: 1\n      - name: GAL14\n        width: 10\n        length: 10\n        groups: 1\n      - name: GAL15\n        width: 10\n        length: 10\n        groups: 1\n      - name: GAL16\n        width: 10\n        length: 10\n        groups: 1\n  - name: MSUNK\n    music:\n      - GMTACWET\n    mapDataSets:\n      - BLANKS\n      - SAND\n      - MSUNK1\n      - MSUNK2\n      - UFOBITS\n    depth: [1, 2]\n    ambience: 67\n    script: THREEBIG\n    mapBlocks:\n      - name: MSUNK00\n        width: 10\n        length: 10\n        groups: 1\n      - name: MSUNK01\n        width: 10\n        length: 10\n        groups: 1\n      - name: MSUNK02\n        width: 20\n        length: 20\n      - name: MSUNK03\n        width: 20\n        length: 20\n      - name: MSUNK04\n        width: 20\n        length: 20\n      - name: MSUNK05\n        width: 20\n        length: 20\n      - name: MSUNK06\n        width: 20\n        length: 20\n      - name: MSUNK07\n        width: 10\n        length: 10\n      - name: MSUNK08\n        width: 10\n        length: 10\n      - name: MSUNK09\n        width: 10\n        length: 10\n      - name: MSUNK10\n        width: 10\n        length: 10\n      - name: MSUNK11\n        width: 10\n        length: 10\n      - name: MSUNK12\n        width: 10\n        length: 10\n      - name: MSUNK13\n        width: 10\n        length: 10\n  - name: VOLC\n    music:\n      - GMTACWET\n    mapDataSets:\n      - BLANKS\n      - SAND\n      - VOLC\n      - UFOBITS\n    depth: [1, 2]\n    ambience: 67\n    mapBlocks:\n      - name: VOLC00\n        width: 10\n        length: 10\n        groups: 1\n      - name: VOLC01\n        width: 10\n        length: 10\n      - name: VOLC02\n        width: 10\n        length: 10\n      - name: VOLC03\n        width: 10\n        length: 10\n      - name: VOLC04\n        width: 10\n        length: 10\n      - name: VOLC05\n        width: 10\n        length: 10\n      - name: VOLC06\n        width: 10\n        length: 10\n      - name: VOLC07\n        width: 10\n        length: 10\n      - name: VOLC08\n        width: 10\n        length: 10\n      - name: VOLC09\n        width: 20\n        length: 20\n      - name: VOLC10\n        width: 20\n        length: 20\n      - name: VOLC11\n        width: 20\n        length: 20\n  - name: CORAL\n    music:\n      - GMTACWET\n    mapDataSets:\n      - BLANKS\n      - SAND\n      - WEEDS\n      - CORAL\n      - ROCKS\n    depth: [1, 2]\n    ambience: 67\n    script: THREEBIG\n    mapBlocks:\n      - name: CORAL00\n        width: 10\n        length: 10\n        groups: 1\n      - name: CORAL01\n        width: 10\n        length: 10\n      - name: CORAL02\n        width: 10\n        length: 10\n      - name: CORAL03\n        width: 10\n        length: 10\n      - name: CORAL04\n        width: 10\n        length: 10\n      - name: CORAL05\n        width: 10\n        length: 10\n      - name: CORAL06\n        width: 10\n        length: 10\n      - name: CORAL07\n        width: 10\n        length: 10\n      - name: CORAL08\n        width: 10\n        length: 10\n      - name: CORAL09\n        width: 20\n        length: 20\n      - name: CORAL10\n        width: 20\n        length: 20\n      - name: CORAL11\n        width: 20\n        length: 20\n  - name: ALART\n    music:\n      - GMTACWET\n    mapDataSets:\n      - BLANKS\n      - SAND\n      - ROCKS\n      - WEEDS\n      - PYRAMID\n      - UFOBITS\n    depth: [1, 2]\n    ambience: 67\n    mapBlocks:\n      - name: ALART00\n        width: 10\n        length: 10\n        groups: 1\n      - name: ALART01\n        width: 10\n        length: 10\n      - name: ALART02\n        width: 10\n        length: 10\n      - name: ALART03\n        width: 10\n        length: 10\n      - name: ALART04\n        width: 10\n        length: 10\n      - name: ALART05\n        width: 10\n        length: 10\n      - name: ALART06\n        width: 10\n        length: 10\n      - name: ALART07\n        width: 10\n        length: 10\n      - name: ALART08\n        width: 10\n        length: 10\n      - name: ALART09\n        width: 20\n        length: 20\n        groups: 6\n      - name: ALART10\n        width: 20\n        length: 20\n      - name: ALART11\n        width: 20\n        length: 20\n  - name: PORT\n    music:\n      - GMTACDRY\n    mapDataSets:\n      - BLANKS\n      - SEA\n      - PORT01\n      - PORT02\n    ambience: 67\n    ambientVolume: 0.25\n    civilianTypes:\n      - SAILOR_CIVILIAN\n      - DOCKER_CIVILIAN\n    mapBlocks:\n      - name: PORT00\n        width: 10\n        length: 10\n        groups: 1\n      - name: PORT01\n        width: 10\n        length: 10\n        groups: 1\n      - name: PORT02\n        width: 10\n        length: 10\n        groups: 3\n      - name: PORT03\n        width: 10\n        length: 10\n        groups: 3\n      - name: PORT04\n        width: 10\n        length: 10\n        groups: 3\n      - name: PORT05\n        width: 10\n        length: 10\n        groups: 3\n      - name: PORT06\n        width: 10\n        length: 10\n        groups: 3\n      - name: PORT07\n        width: 10\n        length: 10\n        groups: 3\n      - name: PORT08\n        width: 10\n        length: 10\n        groups: 3\n      - name: PORT09\n        width: 10\n        length: 10\n        groups: 3\n      - name: PORT10\n        width: 10\n        length: 10\n      - name: PORT11\n        width: 10\n        length: 10\n      - name: PORT12\n        width: 10\n        length: 10\n      - name: PORT13\n        width: 10\n        length: 10\n      - name: PORT14\n        width: 10\n        length: 10\n      - name: PORT15\n        width: 10\n        length: 10\n      - name: PORT16\n        width: 10\n        length: 10\n      - name: PORT17\n        width: 20\n        length: 20\n      - name: PORT18\n        width: 20\n        length: 20\n      - name: PORT19\n        width: 20\n        length: 20\n      - name: PORT20\n        width: 20\n        length: 20\n        groups: 5\n  - name: ISLAND\n    music:\n      - GMTACDRY\n    mapDataSets:\n      - BLANKS\n      - SEA\n      - ISLAND1\n      - ISLAND2\n      - ISLAND3\n    ambience: 67\n    ambientVolume: 0.25\n    mapBlocks:\n      - name: ISLAND00\n        width: 10\n        length: 10\n        groups: 1\n      - name: ISLAND01\n        width: 10\n        length: 10\n        groups: 1\n      - name: ISLAND02\n        width: 20\n        length: 20\n      - name: ISLAND03\n        width: 20\n        length: 20\n      - name: ISLAND04\n        width: 20\n        length: 20\n        groups: 2\n      - name: ISLAND05\n        width: 20\n        length: 20\n        groups: 3\n      - name: ISLAND06\n        width: 20\n        length: 20\n      - name: ISLAND07\n        width: 10\n        length: 10\n        groups: 4\n      - name: ISLAND08\n        width: 10\n        length: 10\n      - name: ISLAND09\n        width: 10\n        length: 10\n      - name: ISLAND10\n        width: 10\n        length: 10\n      - name: ISLAND11\n        width: 10\n        length: 10\n      - name: ISLAND12\n        width: 10\n        length: 10\n      - name: ISLAND13\n        width: 10\n        length: 10\n      - name: ISLAND14\n        width: 10\n        length: 10\n  - name: CARGO\n    music:\n      - GMTACDRY\n    ambience: 67\n    ambientVolume: 0.25\n    mapDataSets:\n      - BLANKS\n      - SEA\n      - CARGO1\n      - CARGO2\n      - XBITS\n      - CARGO3\n    civilianTypes:\n      - SAILOR_CIVILIAN\n      - DOCKER_CIVILIAN\n    mapBlocks:\n      - name: CARGO00\n        width: 30\n        length: 70\n      - name: CARGO01\n        width: 30\n        length: 50\n      - name: CARGO02\n        width: 30\n        length: 20\n  - name: XBASES\n    music:\n      - GMTACDRY\n    ambience: 67\n    ambientVolume: 0.25\n    mapDataSets:\n      - BLANKS\n      - XBASES01\n      - XBASES02\n      - XBASES03\n      - XBASES04\n      - XBASES05\n      - XBITS\n    mapBlocks:\n      - name: XBASES00\n        width: 10\n        length: 10\n      - name: XBASES01\n        width: 10\n        length: 10\n      - name: XBASES02\n        width: 10\n        length: 10\n      - name: XBASES03\n        width: 10\n        length: 10\n      - name: XBASES04\n        width: 10\n        length: 10\n      - name: XBASES05\n        width: 10\n        length: 10\n      - name: XBASES06\n        width: 10\n        length: 10\n      - name: XBASES07\n        width: 10\n        length: 10\n      - name: XBASES08\n        width: 10\n        length: 10\n      - name: XBASES09\n        width: 10\n        length: 10\n      - name: XBASES10\n        width: 10\n        length: 10\n      - name: XBASES11\n        width: 10\n        length: 10\n      - name: XBASES12\n        width: 10\n        length: 10\n      - name: XBASES13\n        width: 10\n        length: 10\n      - name: XBASES14\n        width: 10\n        length: 10\n      - name: XBASES15\n        width: 10\n        length: 10\n      - name: XBASES16\n        width: 10\n        length: 10\n      - name: XBASES17\n        width: 10\n        length: 10\n      - name: XBASES18\n        width: 10\n        length: 10\n      - name: XBASES19\n        width: 10\n        length: 10\n      - name: XBASES20\n        width: 10\n        length: 10\n        groups: 1\n  - name: ENTRY\n    music:\n      - GMTACWET\n    depth: [2, 3]\n    ambience: 67\n    mapDataSets:\n      - BLANKS\n      - SAND\n      - UEXT2\n      - UEXT3\n      - ORGANIC1\n      - ENTRY\n    mapBlocks:\n      - name: ENTRY00\n        width: 20\n        length: 20\n        groups: 2\n      - name: ENTRY01\n        width: 20\n        length: 20\n        groups: 3\n      - name: ENTRY02\n        width: 20\n        length: 20\n        groups: 4\n      - name: ENTRY03\n        width: 20\n        length: 20\n        groups: 5\n      - name: ENTRY04\n        width: 20\n        length: 20\n        groups: 6\n      - name: ENTRY05\n        width: 20\n        length: 20\n        groups: 7\n      - name: ENTRY06\n        width: 20\n        length: 20\n        groups: 8\n      - name: ENTRY07\n        width: 20\n        length: 20\n        groups: 9\n      - name: ENTRY08\n        width: 20\n        length: 20\n        groups: 10\n  - name: GRUNGE\n    music:\n      - GMTACWET\n    depth: [3, 3]\n    ambience: 67\n    ambientVolume: 0.25\n    mapDataSets:\n      - BLANKS\n      - GRUNGE1\n      - GRUNGE2\n      - GRUNGE3\n      - GRUNGE4\n      - GRUNGE5\n      - UFOBITS\n    mapBlocks:\n      - name: GRUNGE00\n        width: 10\n        length: 10\n        groups: 1\n      - name: GRUNGE01\n        width: 10\n        length: 10\n        groups: 1\n      - name: GRUNGE02\n        width: 10\n        length: 10\n        groups: 1\n      - name: GRUNGE03\n        width: 10\n        length: 10\n        groups: 1\n      - name: GRUNGE04\n        width: 10\n        length: 10\n        groups: 6\n        revealedFloors: 3\n      - name: GRUNGE05\n        width: 10\n        length: 10\n      - name: GRUNGE06\n        width: 10\n        length: 10\n      - name: GRUNGE07\n        width: 10\n        length: 10\n      - name: GRUNGE08\n        width: 10\n        length: 10\n      - name: GRUNGE09\n        width: 10\n        length: 10\n      - name: GRUNGE10\n        width: 10\n        length: 10\n      - name: GRUNGE11\n        width: 20\n        length: 20\n      - name: GRUNGE12\n        width: 20\n        length: 20\n      - name: GRUNGE13\n        width: 20\n        length: 20\n      - name: GRUNGE14\n        width: 20\n        length: 20\n      - name: GRUNGE15\n        width: 20\n        length: 20\n        groups: 7\n    #  - name: GRUNGE16\n    #    width: 20\n    #    length: 20\n  - name: LINERT\n    music:\n      - GMTACDRY\n    ambience: 67\n    ambientVolume: 0.25\n    mapDataSets:\n      - BLANKS\n      - DECKC\n      - LINERA\n      - LINERB\n      - LINERC\n      - LINERD\n    mapBlocks:\n      - name: LINERT00\n        width: 30\n        length: 20\n      - name: LINERT01\n        width: 30\n        length: 50\n      - name: LINERT02\n        width: 30\n        length: 50\n        groups: 2 #this block is unused\n  - name: LINERB\n    music:\n      - GMTACDRY\n    ambience: 67\n    ambientVolume: 0.25\n    mapDataSets:\n      - BLANKS\n      - SEA\n      - LINERA\n      - LINERB\n      - LINERC\n      - LINERD\n      - DECKC\n    mapBlocks:\n      - name: LINERB02\n        width: 30\n        length: 50\n      - name: LINERB03\n        width: 30\n        length: 20\n  - name: A_BASE\n    music:\n      - GMTACWET\n    depth: [1, 1]\n    ambience: 67\n    mapDataSets:\n      - BLANKS\n      - ORGANIC1\n      - ORGANIC2\n      - ORGANIC3\n      - PSYNOM\n    mapBlocks:\n      - name: A_BASE00\n        width: 10\n        length: 10\n        groups: 2\n        revealedFloors: 2\n      - name: A_BASE07\n        width: 10\n        length: 10\n        groups: 4\n      - name: A_BASE08\n        width: 10\n        length: 10\n        groups: 3\n      - name: A_BASE09\n        width: 10\n        length: 10\n        groups: 3\n      - name: A_BASE11\n        width: 20\n        length: 20\n        groups: 3\n      - name: A_BASE12\n        width: 20\n        length: 20\n        groups: 3\n      - name: A_BASE13\n        width: 20\n        length: 20\n        groups: 3\n      - name: A_BASE14\n        width: 20\n        length: 20\n        groups: 3\n      - name: A_BASE15\n        width: 20\n        length: 20\n        groups: 1\n        items:\n          STR_ZRBITE:\n            - [14, 14, 2]\n            - [4, 10, 2]\n  - name: ALSHIP\n    music:\n      - GMTACWET\n    depth: [1, 3]\n    ambience: 67\n    mapDataSets:\n      - BLANKS\n      - GRUNGE1\n      - GRUNGE2\n      - GRUNGE3\n      - GRUNGE4\n      - UFOBITS\n    mapBlocks:\n      - name: ALSHIP00\n        width: 10\n        length: 10\n        groups: 3\n      - name: ALSHIP01\n        width: 10\n        length: 10\n        groups: 1\n        revealedFloors: 1\n      - name: ALSHIP02\n        width: 10\n        length: 10\n        groups: 1\n        revealedFloors: 1\n      - name: ALSHIP03\n        width: 10\n        length: 10\n        groups: 2\n      - name: ALSHIP04\n        width: 10\n        length: 10\n      - name: ALSHIP05\n        width: 10\n        length: 10\n      - name: ALSHIP06\n        width: 10\n        length: 10\n      - name: ALSHIP07\n        width: 10\n        length: 10\n      - name: ALSHIP08\n        width: 10\n        length: 10\n      - name: ALSHIP09\n        width: 10\n        length: 10\n      - name: ALSHIP10\n        width: 10\n        length: 10\n      - name: ALSHIP11\n        width: 20\n        length: 20\n      - name: ALSHIP12\n        width: 20\n        length: 20\n      - name: ALSHIP13\n        width: 20\n        length: 20\n      - name: ALSHIP14\n        width: 20\n        length: 20\n      - name: ALSHIP15\n        width: 20\n        length: 20\n      - name: ALSHIP16\n        width: 20\n        length: 20\n      - name: ALSHIP17\n        width: 20\n        length: 20\n  - name: LEVEL\n    music:\n      - GMTACWET\n    depth: [1, 3]\n    ambience: 67\n    mapDataSets:\n      - BLANKS\n      - ORGANIC1\n      - ORGANIC2\n      - ORGANIC3\n      - PSYNOM\n    mapBlocks:\n      - name: LEVEL01\n        width: 20\n        length: 20\n      - name: LEVEL02\n        width: 20\n        length: 20\n      - name: LEVEL03\n        width: 20\n        length: 20\n      - name: LEVEL04\n        width: 20\n        length: 20\n      - name: LEVEL05\n        width: 20\n        length: 20\n      - name: LEVEL06\n        width: 20\n        length: 20\n      - name: LEVEL07\n        width: 20\n        length: 20\n      - name: LEVEL08\n        width: 20\n        length: 20\n      - name: LEVEL09\n        width: 20\n        length: 20\n  - name: CRYPT\n    music:\n      - GMTACWET\n    depth: [3, 3]\n    ambience: 67\n    mapDataSets:\n      - BLANKS\n      - CRYPT1\n      - CRYPT2\n      - CRYPT3\n      - CRYPT4\n      - UFOBITS\n    mapBlocks:\n      - name: CRYPT01\n        width: 20\n        length: 20\n      - name: CRYPT02\n        width: 20\n        length: 20\n      - name: CRYPT03\n        width: 20\n        length: 20\n      - name: CRYPT04\n        width: 20\n        length: 20\n      - name: CRYPT05\n        width: 20\n        length: 20\n      - name: CRYPT06\n        width: 20\n        length: 20\n      - name: CRYPT07\n        width: 20\n        length: 20\n      - name: CRYPT08\n        width: 20\n        length: 20\n      - name: CRYPT09\n        width: 20\n        length: 20\n"
  },
  {
    "path": "bin/standard/xcom2/ufoTrajectories.rul",
    "content": "ufoTrajectories: #done\n  - id: P0\n    groundTimer: 3000\n    waypoints:\n      - [5, 4, 100]\n      - [0, 3, 74]\n      - [0, 1, 28]\n      - [1, 1, 47]\n      - [5, 2, 100]\n  - id: P1\n    groundTimer: 4000\n    waypoints:\n      - [5, 4, 100]\n      - [0, 2, 76]\n      - [0, 2, 20]\n      - [1, 1, 44]\n      - [0, 0, 20]\n      - [0, 2, 32]\n      - [2, 1, 65]\n      - [5, 0, 100]\n  - id: P2\n    groundTimer: 5000\n    waypoints:\n      - [5, 4, 100]\n      - [0, 3, 57]\n      - [0, 2, 26]\n      - [1, 1, 50]\n      - [5, 0, 100]\n  - id: P3\n    groundTimer: 6000\n    waypoints:\n      - [5, 4, 100]\n      - [0, 3, 30]\n      - [0, 2, 25]\n      - [2, 1, 20]\n      - [5, 0, 100]\n  - id: P4\n    groundTimer: 7000\n    waypoints:\n      - [5, 4, 100]\n      - [0, 2, 67]\n      - [0, 2, 52]\n      - [2, 1, 40]\n      - [0, 0, 30]\n      - [0, 2, 20]\n      - [2, 1, 30]\n      - [5, 0, 100]\n  - id: P5\n    groundTimer: 4000\n    waypoints:\n      - [5, 4, 100]\n      - [0, 2, 50]\n      - [0, 2, 20]\n      - [4, 1, 15]\n      - [0, 0, 20]\n      - [0, 2, 29]\n      - [4, 1, 42]\n      - [5, 0, 90]\n  - id: P6\n    groundTimer: 5000\n    waypoints:\n      - [5, 4, 100]\n      - [0, 3, 50]\n      - [0, 2, 25]\n      - [4, 1, 16]\n      - [5, 0, 100]\n  - id: P7\n    groundTimer: 9000\n    waypoints:\n      - [5, 4, 100]\n      - [0, 3, 60]\n      - [0, 2, 30]\n      - [3, 1, 20]\n      - [5, 0, 100]\n  - id: P8\n    groundTimer: 6000\n    waypoints:\n      - [5, 4, 100]\n      - [1, 1, 60]\n      - [2, 1, 20]\n      - [3, 1, 30]\n      - [4, 1, 20]\n      - [0, 1, 42]\n      - [2, 1, 56]\n      - [5, 4, 100]\n  - id: P9\n    groundTimer: 2000\n    waypoints:\n      - [5, 4, 80]\n      - [5, 0, 100]\n  - id: __RETALIATION_ASSAULT_RUN\n    groundTimer: 1000\n    waypoints:\n      - [5, 4, 100] #This should always be 5, 4, 100\n      - [5, 0, 100] #only the 0 altitude matters\n  - id: P10\n    groundTimer: 0\n    waypoints:\n      - [0, 0, 0]\n"
  },
  {
    "path": "bin/standard/xcom2/ufopaedia.rul",
    "content": "ufopaedia: #done\n  - id: STR_TRITON\n    type_id: 11\n    section: STR_XCOM_CRAFT_ARMAMENT\n    image_id: UP001.BDY\n    text: STR_TRITON_UFOPEDIA\n  - id: STR_HAMMERHEAD\n    type_id: 11\n    section: STR_XCOM_CRAFT_ARMAMENT\n    requires:\n      - STR_NEW_FIGHTER_TRANSPORTER\n    image_id: UP005.BDY\n    text: STR_HAMMERHEAD_UFOPEDIA\n  - id: STR_LEVIATHAN\n    type_id: 11\n    section: STR_XCOM_CRAFT_ARMAMENT\n    requires:\n      - STR_THE_LATEST_FLYING_SUB\n    image_id: UP003.BDY\n    text: STR_LEVIATHAN_UFOPEDIA\n  - id: STR_BARRACUDA\n    type_id: 11\n    section: STR_XCOM_CRAFT_ARMAMENT\n    image_id: UP004.BDY\n    text: STR_BARRACUDA_UFOPEDIA\n  - id: STR_MANTA\n    type_id: 11\n    section: STR_XCOM_CRAFT_ARMAMENT\n    requires:\n      - STR_NEW_FIGHTER_FLYING_SUB\n    image_id: UP002.BDY\n    text: STR_MANTA_UFOPEDIA\n  - id: STR_AJAX\n    type_id: 12\n    section: STR_XCOM_CRAFT_ARMAMENT\n    image_id: UP054.BDY\n    text: STR_AJAX_UFOPEDIA\n  - id: STR_DUP_HEAD\n    type_id: 12\n    section: STR_XCOM_CRAFT_ARMAMENT\n    image_id: UP055.BDY\n    text: STR_DUP_HEAD_UFOPEDIA\n  - id: STR_CRAFT_GAS_CANNON_UC\n    type_id: 12\n    section: STR_XCOM_CRAFT_ARMAMENT\n    image_id: UP056.BDY\n    text: STR_CRAFT_GAS_CANNON_UFOPEDIA\n  - id: STR_PWT_CANNON_UC\n    type_id: 12\n    section: STR_XCOM_CRAFT_ARMAMENT\n    requires:\n      - STR_PWT_CANNON\n    image_id: UP074.BDY\n    text: STR_PWT_CANNON_UFOPEDIA\n  - id: STR_GAUSS_CANNON_UC\n    type_id: 12\n    section: STR_XCOM_CRAFT_ARMAMENT\n    requires:\n      - STR_GAUSS_CANNON\n    image_id: UP073.BDY\n    text: STR_GAUSS_CANNON_UFOPEDIA\n  - id: STR_SONIC_OSCILLATOR_UC\n    type_id: 12\n    section: STR_XCOM_CRAFT_ARMAMENT\n    requires:\n      - STR_SONIC_OSCILLATOR\n    image_id: UP075.BDY\n    text: STR_SONIC_OSCILLATOR_UFOPEDIA\n  - id: STR_COELACANTH_GAS_CANNON\n    type_id: 13\n    section: STR_HEAVY_WEAPONS_PLATFORMS\n    text: STR_COELACANTH_GAS_CANNON_UFOPEDIA\n    weapon: STR_DAMAGE_ARMOR_PIERCING\n    image_id: UP027.BDY\n  - id: STR_COELACANTH_AQUA_JET\n    type_id: 13\n    section: STR_HEAVY_WEAPONS_PLATFORMS\n    text: STR_COELACANTH_AQUA_JET_UFOPEDIA\n    weapon: STR_TORPEDO_LAUNCHER\n    image_id: UP057.BDY\n  - id: STR_COELACANTH_GAUSS\n    type_id: 13\n    section: STR_HEAVY_WEAPONS_PLATFORMS\n    weapon: STR_DAMAGE_LASER_BEAM\n    image_id: UP068.BDY\n    requires:\n      - STR_GAUSS_CANNON\n      - STR_NEW_FIGHTER_FLYING_SUB\n    text: STR_COELACANTH_GAUSS_UFOPEDIA\n  - id: STR_DISPLACER_SONIC\n    type_id: 13\n    section: STR_HEAVY_WEAPONS_PLATFORMS\n    weapon: STR_DAMAGE_PLASMA_BEAM\n    requires:\n      - STR_SONIC_OSCILLATOR\n      - STR_NEW_FIGHTER_FLYING_SUB\n    text: STR_DISPLACER_SONIC_UFOPEDIA\n    image_id: UP028.BDY\n  - id: STR_DISPLACER_PWT\n    type_id: 13\n    section: STR_HEAVY_WEAPONS_PLATFORMS\n    weapon: STR_PWT_CANNON\n    requires:\n      - STR_PWT_CANNON\n      - STR_NEW_FIGHTER_FLYING_SUB\n    text: STR_DISPLACER_PWT_UFOPEDIA\n    image_id: UP058.BDY\n  - id: STR_PLASTIC_AQUA_ARMOR_UC\n    type_id: 15\n    section: STR_WEAPONS_AND_EQUIPMENT\n    requires:\n      - STR_PLASTIC_AQUA_ARMOR\n    text: STR_PLASTIC_AQUA_ARMOR_UFOPEDIA\n    image_id: UP023.BDY\n  - id: STR_ION_ARMOR_UC\n    type_id: 15\n    section: STR_WEAPONS_AND_EQUIPMENT\n    requires:\n      - STR_ION_ARMOR\n    text: STR_ION_ARMOR_UFOPEDIA\n    image_id: UP024.BDY\n  - id: STR_MAGNETIC_ION_ARMOR_UC\n    type_id: 15\n    section: STR_WEAPONS_AND_EQUIPMENT\n    requires:\n      - STR_MAGNETIC_ION_ARMOR\n    text: STR_MAGNETIC_ION_ARMOR_UFOPEDIA\n    image_id: UP022.BDY\n  - id: STR_DART_PISTOL\n    type_id: 14\n    section: STR_WEAPONS_AND_EQUIPMENT\n    image_id: UP034.BDY\n    text: STR_DART_PISTOL_UFOPEDIA\n  - id: STR_DART_POD\n    type_id: 14\n    section: STR_NOT_AVAILABLE\n  - id: STR_JET_HARPOON\n    type_id: 14\n    section: STR_WEAPONS_AND_EQUIPMENT\n    text: STR_JET_HARPOON_UFOPEDIA\n    image_id: UP035.BDY\n  - id: STR_HARPOON_POD\n    type_id: 14\n    section: STR_NOT_AVAILABLE\n  - id: STR_GAS_CANNON\n    type_id: 14\n    section: STR_WEAPONS_AND_EQUIPMENT\n    text: STR_GAS_CANNON_UFOPEDIA\n    image_id: UP036.BDY\n  - id: STR_GC_AP_AMMO\n    type_id: 14\n    section: STR_NOT_AVAILABLE\n  - id: STR_GC_HE_AMMO\n    type_id: 14\n    section: STR_NOT_AVAILABLE\n  - id: STR_GC_P_AMMO\n    type_id: 14\n    section: STR_NOT_AVAILABLE\n  - id: STR_HYDRO_JET_CANNON\n    type_id: 14\n    section: STR_WEAPONS_AND_EQUIPMENT\n    text: STR_HYDRO_JET_CANNON_UFOPEDIA\n    image_id: UP037.BDY\n  - id: STR_HJC_AP_AMMO\n    type_id: 14\n    section: STR_NOT_AVAILABLE\n  - id: STR_HJC_HE_AMMO\n    type_id: 14\n    section: STR_NOT_AVAILABLE\n  - id: STR_HJC_P_AMMO\n    type_id: 14\n    section: STR_NOT_AVAILABLE\n  - id: STR_TORPEDO_LAUNCHER\n    type_id: 14\n    section: STR_WEAPONS_AND_EQUIPMENT\n    text: STR_TORPEDO_LAUNCHER_UFOPEDIA\n    image_id: UP038.BDY\n  - id: STR_SMALL_TORPEDO\n    type_id: 14\n    section: STR_NOT_AVAILABLE\n  - id: STR_LARGE_TORPEDO\n    type_id: 14\n    section: STR_NOT_AVAILABLE\n  - id: STR_PHOSPHOROUS_TORPEDO\n    type_id: 14\n    section: STR_NOT_AVAILABLE\n  - id: STR_GAUSS_PISTOL\n    type_id: 14\n    section: STR_WEAPONS_AND_EQUIPMENT\n    image_id: UP031.BDY\n    requires:\n      - STR_GAUSS_PISTOL\n    text: STR_GAUSS_PISTOL_UFOPEDIA\n  - id: STR_GAUSS_PISTOL_CLIP\n    type_id: 14\n    section: STR_WEAPONS_AND_EQUIPMENT\n    requires:\n      - STR_GAUSS_PISTOL_CLIP\n    text: STR_GAUSS_PISTOL_CLIP_UFOPEDIA\n    image_id: UP110.BDY\n  - id: STR_GAUSS_RIFLE\n    type_id: 14\n    section: STR_WEAPONS_AND_EQUIPMENT\n    image_id: UP032.BDY\n    requires:\n      - STR_GAUSS_RIFLE\n    text: STR_GAUSS_RIFLE_UFOPEDIA\n  - id: STR_GAUSS_RIFLE_CLIP\n    type_id: 14\n    section: STR_WEAPONS_AND_EQUIPMENT\n    requires:\n      - STR_GAUSS_RIFLE_CLIP\n    text: STR_GAUSS_RIFLE_CLIP_UFOPEDIA\n    image_id: UP111.BDY\n  - id: STR_HEAVY_GAUSS\n    type_id: 14\n    section: STR_WEAPONS_AND_EQUIPMENT\n    image_id: UP033.BDY\n    requires:\n      - STR_HEAVY_GAUSS\n    text: STR_HEAVY_GAUSS_UFOPEDIA\n  - id: STR_HEAVY_GAUSS_CLIP\n    type_id: 14\n    section: STR_WEAPONS_AND_EQUIPMENT\n    requires:\n      - STR_HEAVY_GAUSS_CLIP\n    text: STR_HEAVY_GAUSS_CLIP_UFOPEDIA\n    image_id: UP112.BDY\n  - id: STR_MAGNA_BLAST_GRENADE\n    type_id: 14\n    section: STR_WEAPONS_AND_EQUIPMENT\n    text: STR_MAGNA_BLAST_GRENADE_UFOPEDIA\n    image_id: UP039.BDY\n  - id: STR_DYE_GRENADE\n    type_id: 14\n    section: STR_WEAPONS_AND_EQUIPMENT\n    text: STR_DYE_GRENADE_UFOPEDIA\n    image_id: UP040.BDY\n  - id: STR_PARTICLE_DISTURBANCE_GRENADE\n    type_id: 14\n    section: STR_WEAPONS_AND_EQUIPMENT\n    text: STR_PARTICLE_DISTURBANCE_GRENADE_UFOPEDIA\n    image_id: UP041.BDY\n  - id: STR_MAGNA_PACK_EXPLOSIVE\n    type_id: 14\n    section: STR_WEAPONS_AND_EQUIPMENT\n    text: STR_MAGNA_PACK_EXPLOSIVE_UFOPEDIA\n    image_id: UP042.BDY\n  - id: STR_PARTICLE_DISTURBANCE_SENSOR\n    type_id: 14\n    section: STR_WEAPONS_AND_EQUIPMENT\n    image_id: UP030.BDY\n    requires:\n      - STR_PARTICLE_DISTURBANCE_SENSOR\n    text: STR_PARTICLE_DISTURBANCE_SENSOR_UFOPEDIA\n  - id: STR_MEDI_KIT\n    type_id: 14\n    section: STR_WEAPONS_AND_EQUIPMENT\n    requires:\n      - STR_MEDI_KIT\n    text: STR_MEDI_KIT_UFOPEDIA\n    image_id: UP052.BDY\n  - id: STR_MC_DISRUPTOR\n    type_id: 14\n    section: STR_WEAPONS_AND_EQUIPMENT\n    requires:\n      - STR_MC_DISRUPTOR\n    text: STR_MC_DISRUPTOR_UFOPEDIA\n    image_id: UP106.BDY\n  - id: STR_THERMAL_TAZER\n    type_id: 14\n    section: STR_WEAPONS_AND_EQUIPMENT\n    text: STR_THERMAL_TAZER_UFOPEDIA\n    image_id: UP044.BDY\n  - id: STR_CHEMICAL_FLARE\n    type_id: 14\n    section: STR_WEAPONS_AND_EQUIPMENT\n    text: STR_CHEMICAL_FLARE_UFOPEDIA\n    image_id: UP043.BDY\n  - id: STR_VIBRO_BLADE\n    type_id: 14\n    section: STR_ALIEN_ARTIFACTS\n    text: STR_VIBRO_BLADE_UFOPEDIA\n    image_id: UP107.BDY\n    requires:\n      - STR_VIBRO_BLADE\n  - id: STR_THERMIC_LANCE\n    type_id: 14\n    section: STR_ALIEN_ARTIFACTS\n    text: STR_THERMIC_LANCE_UFOPEDIA\n    image_id: UP108.BDY\n    requires:\n      - STR_THERMIC_LANCE\n  - id: STR_HEAVY_THERMIC_LANCE\n    type_id: 14\n    section: STR_ALIEN_ARTIFACTS\n    text: STR_HEAVY_THERMIC_LANCE_UFOPEDIA\n    image_id: UP109.BDY\n    requires:\n      - STR_HEAVY_THERMIC_LANCE\n  - id: STR_SONIC_CANNON\n    type_id: 14\n    section: STR_ALIEN_ARTIFACTS\n    requires:\n      - STR_SONIC_CANNON\n    text: STR_SONIC_CANNON_UFOPEDIA\n    image_id: UP051.BDY\n  - id: STR_CANNON_POWER_CLIP\n    type_id: 14\n    section: STR_ALIEN_ARTIFACTS\n    requires:\n      - STR_CANNON_POWER_CLIP\n    text: STR_CANNON_POWER_CLIP_UFOPEDIA\n    image_id: UP104.BDY\n  - id: STR_SONIC_BLASTA_RIFLE\n    type_id: 14\n    section: STR_ALIEN_ARTIFACTS\n    requires:\n      - STR_SONIC_BLASTA_RIFLE\n    text: STR_SONIC_BLASTA_RIFLE_UFOPEDIA\n    image_id: UP050.BDY\n  - id: STR_BLASTA_POWER_CLIP\n    type_id: 14\n    section: STR_ALIEN_ARTIFACTS\n    requires:\n      - STR_BLASTA_POWER_CLIP\n    text: STR_BLASTA_POWER_CLIP_UFOPEDIA\n    image_id: UP103.BDY\n  - id: STR_SONIC_PISTOL\n    type_id: 14\n    section: STR_ALIEN_ARTIFACTS\n    requires:\n      - STR_SONIC_PISTOL\n    text: STR_SONIC_PISTOL_UFOPEDIA\n    image_id: UP049.BDY\n  - id: STR_PISTOL_POWER_CLIP\n    type_id: 14\n    section: STR_ALIEN_ARTIFACTS\n    image_id: UP102.BDY\n    requires:\n      - STR_PISTOL_POWER_CLIP\n    text: STR_PISTOL_POWER_CLIP_UFOPEDIA\n  - id: STR_DISRUPTOR_PULSE_LAUNCHER\n    type_id: 14\n    section: STR_ALIEN_ARTIFACTS\n    requires:\n      - STR_DISRUPTOR_PULSE_LAUNCHER\n    text: STR_DISRUPTOR_PULSE_LAUNCHER_UFOPEDIA\n    image_id: UP047.BDY\n  - id: STR_DISRUPTOR_AMMO\n    type_id: 14\n    section: STR_ALIEN_ARTIFACTS\n    requires:\n      - STR_DISRUPTOR_AMMO\n    text: STR_DISRUPTOR_AMMO_UFOPEDIA\n    image_id: UP072.BDY\n  - id: STR_THERMAL_SHOK_LAUNCHER\n    type_id: 14\n    section: STR_ALIEN_ARTIFACTS\n    requires:\n      - STR_THERMAL_SHOK_LAUNCHER\n    text: STR_THERMAL_SHOK_LAUNCHER_UFOPEDIA\n    image_id: UP048.BDY\n  - id: STR_THERMAL_SHOK_BOMB\n    type_id: 14\n    section: STR_ALIEN_ARTIFACTS\n    requires:\n      - STR_THERMAL_SHOK_BOMB\n    text: STR_THERMAL_SHOK_BOMB_UFOPEDIA\n    image_id: UP101.BDY\n  - id: STR_SONIC_PULSER\n    type_id: 14\n    section: STR_ALIEN_ARTIFACTS\n    requires:\n      - STR_SONIC_PULSER\n    text: STR_SONIC_PULSER_UFOPEDIA\n    image_id: UP045.BDY\n  - id: STR_ZRBITE\n    type_id: 14\n    section: STR_ALIEN_ARTIFACTS\n    requires:\n      - STR_ZRBITE\n    text: STR_ZRBITE_UFOPEDIA\n    image_id: UP067.BDY\n  - id: STR_MC_READER\n    type_id: 14\n    section: STR_ALIEN_ARTIFACTS\n    text: STR_MC_READER_UFOPEDIA\n    requires:\n      - STR_MC_READER\n    image_id: UP046.BDY\n  - id: STR_AIR_LOCK\n    type_id: 16\n    section: STR_BASE_FACILITIES\n    text: STR_AIR_LOCK_UFOPEDIA\n    image_id: UP078.BDY\n  - id: STR_LIVING_QUARTERS\n    type_id: 16\n    section: STR_BASE_FACILITIES\n    text: STR_LIVING_QUARTERS_UFOPEDIA\n    image_id: UP076.BDY\n  - id: STR_LABORATORY\n    type_id: 16\n    section: STR_BASE_FACILITIES\n    text: STR_LABORATORY_UFOPEDIA\n    image_id: UP084.BDY\n  - id: STR_WORKSHOP\n    type_id: 16\n    section: STR_BASE_FACILITIES\n    text: STR_WORKSHOP_UFOPEDIA\n    image_id: UP087.BDY\n  - id: STR_STANDARD_SONAR\n    type_id: 16\n    section: STR_BASE_FACILITIES\n    text: STR_STANDARD_SONAR_UFOPEDIA\n    image_id: UP077.BDY\n  - id: STR_WIDE_ARRAY_SONAR\n    type_id: 16\n    section: STR_BASE_FACILITIES\n    text: STR_WIDE_ARRAY_SONAR_UFOPEDIA\n    image_id: UP079.BDY\n  - id: STR_TORPEDO_DEFENSES\n    type_id: 16\n    section: STR_BASE_FACILITIES\n    text: STR_TORPEDO_DEFENSES_UFOPEDIA\n    image_id: UP082.BDY\n  - id: STR_GENERAL_STORES\n    type_id: 16\n    section: STR_BASE_FACILITIES\n    text: STR_GENERAL_STORES_UFOPEDIA\n    image_id: UP081.BDY\n  - id: STR_ALIEN_CONTAINMENT\n    type_id: 16\n    section: STR_BASE_FACILITIES\n    text: STR_ALIEN_CONTAINMENT_UFOPEDIA\n    image_id: UP080.BDY\n  - id: STR_GAUSS_DEFENSES\n    type_id: 16\n    section: STR_BASE_FACILITIES\n    requires:\n      - STR_GAUSS_DEFENSES\n    text: STR_GAUSS_DEFENSES_UFOPEDIA\n    image_id: UP083.BDY\n  - id: STR_SONIC_DEFENSES\n    type_id: 16\n    section: STR_BASE_FACILITIES\n    requires:\n      - STR_SONIC_DEFENSES\n    text: STR_SONIC_DEFENSES_UFOPEDIA\n    image_id: UP085.BDY\n  - id: STR_PWT_DEFENSES\n    type_id: 16\n    section: STR_BASE_FACILITIES\n    text: STR_PWT_DEFENSES_UFOPEDIA\n    requires:\n      - STR_PWT_DEFENSES\n    image_id: UP086.BDY\n  - id: STR_BOMBARDMENT_SHIELD\n    type_id: 16\n    section: STR_BASE_FACILITIES\n    requires:\n      - STR_BOMBARDMENT_SHIELD\n    text: STR_BOMBARDMENT_SHIELD_UFOPEDIA\n    image_id: UP090.BDY\n  - id: STR_MC_GENERATOR\n    type_id: 16\n    section: STR_BASE_FACILITIES\n    requires:\n      - STR_MC_GENERATOR\n    text: STR_MC_GENERATOR_UFOPEDIA\n    image_id: UP092.BDY\n  - id: STR_MC_LAB\n    type_id: 16\n    section: STR_BASE_FACILITIES\n    requires:\n      - STR_MC_LAB\n    text: STR_MC_LAB_UFOPEDIA\n    image_id: UP088.BDY\n  - id: STR_TRANSMISSION_RESOLVER\n    type_id: 16\n    section: STR_BASE_FACILITIES\n    requires:\n      - STR_TRANSMISSION_RESOLVER\n    text: STR_TRANSMISSION_RESOLVER_UFOPEDIA\n    image_id: UP091.BDY\n  - id: STR_SUB_PEN\n    type_id: 16\n    section: STR_BASE_FACILITIES\n    text: STR_SUB_PEN_UFOPEDIA\n    image_id: UP089.BDY\n  - id: STR_AQUATOID\n    type_id: 10\n    section: STR_ALIEN_LIFE_FORMS\n    requires:\n      - STR_AQUATOID\n    image_id: UP006.BDY\n    text: STR_AQUATOID_UFOPEDIA\n  - id: STR_AQUATOID_AUTOPSY\n    type_id: 10\n    section: STR_ALIEN_LIFE_FORMS\n    image_id: UP007.BDY\n    text: STR_AQUATOID_AUTOPSY_UFOPEDIA\n    requires:\n      - STR_AQUATOID_AUTOPSY\n  - id: STR_GILLMAN\n    type_id: 10\n    section: STR_ALIEN_LIFE_FORMS\n    requires:\n      - STR_GILLMAN\n    image_id: UP008.BDY\n    text: STR_GILLMAN_UFOPEDIA\n  - id: STR_GILLMAN_AUTOPSY\n    type_id: 10\n    section: STR_ALIEN_LIFE_FORMS\n    requires:\n      - STR_GILLMAN_AUTOPSY\n    image_id: UP009.BDY\n    text: STR_GILLMAN_AUTOPSY_UFOPEDIA\n  - id: STR_LOBSTERMAN\n    type_id: 10\n    section: STR_ALIEN_LIFE_FORMS\n    requires:\n      - STR_LOBSTERMAN\n    image_id: UP010.BDY\n    text: STR_LOBSTERMAN_UFOPEDIA\n  - id: STR_LOBSTERMAN_AUTOPSY\n    type_id: 10\n    section: STR_ALIEN_LIFE_FORMS\n    requires:\n      - STR_LOBSTERMAN_AUTOPSY\n    image_id: UP011.BDY\n    text: STR_LOBSTERMAN_AUTOPSY_UFOPEDIA\n  - id: STR_TASOTH\n    type_id: 10\n    section: STR_ALIEN_LIFE_FORMS\n    requires:\n      - STR_TASOTH\n    image_id: UP012.BDY\n    text: STR_TASOTH_UFOPEDIA\n  - id: STR_TASOTH_AUTOPSY\n    type_id: 10\n    section: STR_ALIEN_LIFE_FORMS\n    requires:\n      - STR_TASOTH_AUTOPSY\n    image_id: UP053.BDY\n    text: STR_TASOTH_AUTOPSY_UFOPEDIA\n  - id: STR_CALCINITE\n    type_id: 10\n    section: STR_ALIEN_LIFE_FORMS\n    requires:\n      - STR_CALCINITE\n    image_id: UP025.BDY\n    text: STR_CALCINITE_UFOPEDIA\n  - id: STR_CALCINITE_AUTOPSY\n    type_id: 10\n    section: STR_ALIEN_LIFE_FORMS\n    requires:\n      - STR_CALCINITE_AUTOPSY\n    image_id: UP026.BDY\n    text: STR_CALCINITE_AUTOPSY_UFOPEDIA\n  - id: STR_DEEP_ONE\n    type_id: 10\n    section: STR_ALIEN_LIFE_FORMS\n    requires:\n      - STR_DEEP_ONE\n    image_id: UP013.BDY\n    text: STR_DEEP_ONE_UFOPEDIA\n  - id: STR_DEEP_ONE_AUTOPSY\n    type_id: 10\n    section: STR_ALIEN_LIFE_FORMS\n    requires:\n      - STR_DEEP_ONE_AUTOPSY\n    image_id: UP014.BDY\n    text: STR_DEEP_ONE_AUTOPSY_UFOPEDIA\n  - id: STR_BIODRONE\n    type_id: 10\n    section: STR_ALIEN_LIFE_FORMS\n    requires:\n      - STR_BIODRONE\n    image_id: UP070.BDY\n    text: STR_BIODRONE_UFOPEDIA\n  - id: STR_BIODRONE_AUTOPSY\n    type_id: 10\n    section: STR_ALIEN_LIFE_FORMS\n    requires:\n      - STR_BIODRONE_AUTOPSY\n    image_id: UP071.BDY\n    text: STR_BIODRONE_AUTOPSY_UFOPEDIA\n  - id: STR_TENTACULAT\n    type_id: 10\n    section: STR_ALIEN_LIFE_FORMS\n    requires:\n      - STR_TENTACULAT\n    image_id: UP015.BDY\n    text: STR_TENTACULAT_UFOPEDIA\n  - id: STR_TENTACULAT_AUTOPSY\n    type_id: 10\n    section: STR_ALIEN_LIFE_FORMS\n    requires:\n      - STR_TENTACULAT_AUTOPSY\n    image_id: UP016.BDY\n    text: STR_TENTACULAT_AUTOPSY_UFOPEDIA\n  - id: STR_TRISCENE\n    type_id: 10\n    section: STR_ALIEN_LIFE_FORMS\n    requires:\n      - STR_TRISCENE\n    image_id: UP017.BDY\n    text: STR_TRISCENE_UFOPEDIA\n  - id: STR_TRISCENE_AUTOPSY\n    type_id: 10\n    section: STR_ALIEN_LIFE_FORMS\n    requires:\n      - STR_TRISCENE_AUTOPSY\n    image_id: UP029.BDY\n    text: STR_TRISCENE_AUTOPSY_UFOPEDIA\n  - id: STR_HALLUCINOID\n    type_id: 10\n    section: STR_ALIEN_LIFE_FORMS\n    requires:\n      - STR_HALLUCINOID\n    image_id: UP018.BDY\n    text: STR_HALLUCINOID_UFOPEDIA\n  - id: STR_HALLUCINOID_AUTOPSY\n    type_id: 10\n    section: STR_ALIEN_LIFE_FORMS\n    requires:\n      - STR_HALLUCINOID_AUTOPSY\n    image_id: UP019.BDY\n    text: STR_HALLUCINOID_AUTOPSY_UFOPEDIA\n  - id: STR_XARQUID\n    type_id: 10\n    section: STR_ALIEN_LIFE_FORMS\n    requires:\n      - STR_XARQUID\n    image_id: UP020.BDY\n    text: STR_XARQUID_UFOPEDIA\n  - id: STR_XARQUID_AUTOPSY\n    type_id: 10\n    section: STR_ALIEN_LIFE_FORMS\n    requires:\n      - STR_XARQUID_AUTOPSY\n    image_id: UP021.BDY\n    text: STR_XARQUID_AUTOPSY_UFOPEDIA\n  - id: STR_ALIEN_ORIGINS\n    type_id: 10\n    section: STR_ALIEN_RESEARCH_UC\n    requires:\n      - STR_ALIEN_ORIGINS\n    text: STR_ALIEN_ORIGINS_UFOPEDIA\n    image_id: UP105.BDY\n    text_width: 308\n  - id: STR_THE_ULTIMATE_THREAT\n    type_id: 10\n    section: STR_ALIEN_RESEARCH_UC\n    requires:\n      - STR_THE_ULTIMATE_THREAT\n    text: STR_THE_ULTIMATE_THREAT_UFOPEDIA\n    image_id: UP105.BDY\n    text_width: 308\n  - id: STR_TLETH_THE_ALIEN_CITY\n    type_id: 10\n    section: STR_ALIEN_RESEARCH_UC\n    requires:\n      - STR_TLETH_ALIEN_CITY\n    text: STR_TLETH_THE_ALIEN_CITY_UFOPEDIA\n    image_id: UP105.BDY\n    text_width: 308\n  - id: STR_ALIEN_PROBE_MISSION\n    type_id: 10\n    section: STR_ALIEN_RESEARCH_UC\n    requires:\n      - STR_ALIEN_PROBE_MISSION\n    text: STR_ALIEN_PROBE_MISSION_UFOPEDIA\n    image_id: UP105.BDY\n    text_width: 308\n  - id: STR_ALIEN_INTERDICTION\n    type_id: 10\n    section: STR_ALIEN_RESEARCH_UC\n    requires:\n      - STR_ALIEN_INTERDICTION\n    text: STR_ALIEN_INTERDICTION_UFOPEDIA\n    image_id: UP105.BDY\n    text_width: 308\n  - id: STR_ALIEN_RESOURCE_RAID\n    type_id: 10\n    section: STR_ALIEN_RESEARCH_UC\n    requires:\n      - STR_ALIEN_RESOURCE_RAID\n    text: STR_ALIEN_RESOURCE_RAID_UFOPEDIA\n    image_id: UP105.BDY\n    text_width: 308\n  - id: STR_ALIEN_INFILTRATION\n    type_id: 10\n    section: STR_ALIEN_RESEARCH_UC\n    requires:\n      - STR_ALIEN_INFILTRATION\n    text: STR_ALIEN_INFILTRATION_UFOPEDIA\n    image_id: UP105.BDY\n    text_width: 308\n  - id: STR_ALIEN_BASE\n    type_id: 10\n    section: STR_ALIEN_RESEARCH_UC\n    requires:\n      - STR_ALIEN_BASE\n    text: STR_ALIEN_BASE_UFOPEDIA\n    image_id: UP105.BDY\n    text_width: 308\n  - id: STR_ALIEN_SURFACE_ATTACK\n    type_id: 10\n    section: STR_ALIEN_RESEARCH_UC\n    requires:\n      - STR_ALIEN_SURFACE_ATTACK\n    text: STR_ALIEN_SURFACE_ATTACK_UFOPEDIA\n    image_id: UP105.BDY\n    text_width: 308\n  - id: STR_ALIEN_RETALIATION\n    type_id: 10\n    section: STR_ALIEN_RESEARCH_UC\n    requires:\n      - STR_ALIEN_RETALIATION\n    text: STR_ALIEN_RETALIATION_UFOPEDIA\n    image_id: UP105.BDY\n    text_width: 308\n  - id: STR_ALIEN_SUPPLY\n    type_id: 10\n    section: STR_ALIEN_RESEARCH_UC\n    requires:\n      - STR_ALIEN_SUPPLY\n    text: STR_ALIEN_SUPPLY_UFOPEDIA\n    image_id: UP105.BDY\n    text_width: 308\n  - id: STR_ION_BEAM_ACCELERATORS\n    type_id: 10\n    section: STR_UFO_COMPONENTS\n    requires:\n      - STR_ION_BEAM_ACCELERATORS\n    image_id: UP059.BDY\n    text: STR_ION_BEAM_ACCELERATORS_UFOPEDIA\n  - id: STR_MAGNETIC_NAVIGATION\n    type_id: 10\n    section: STR_UFO_COMPONENTS\n    requires:\n      - STR_MAGNETIC_NAVIGATION\n    image_id: UP060.BDY\n    text: STR_MAGNETIC_NAVIGATION_UFOPEDIA\n  - id: STR_ALIEN_SUB_CONSTRUCTION\n    type_id: 10\n    section: STR_UFO_COMPONENTS\n    requires:\n      - STR_ALIEN_SUB_CONSTRUCTION\n    image_id: UP069.BDY\n    text: STR_ALIEN_SUB_CONSTRUCTION_UFOPEDIA\n  - id: STR_ALIEN_CRYOGENICS\n    type_id: 10\n    section: STR_UFO_COMPONENTS\n    requires:\n      - STR_ALIEN_CRYOGENICS\n    image_id: UP061.BDY\n    text: STR_ALIEN_CRYOGENICS_UFOPEDIA\n  - id: STR_ALIEN_CLONING\n    type_id: 10\n    section: STR_UFO_COMPONENTS\n    requires:\n      - STR_ALIEN_CLONING\n    image_id: UP062.BDY\n    text: STR_ALIEN_CLONING_UFOPEDIA\n  - id: STR_ALIEN_LEARNING_ARRAYS\n    type_id: 10\n    section: STR_UFO_COMPONENTS\n    requires:\n      - STR_ALIEN_LEARNING_ARRAYS\n    image_id: UP063.BDY\n    text: STR_ALIEN_LEARNING_ARRAYS_UFOPEDIA\n  - id: STR_ALIEN_IMPLANTER\n    type_id: 10\n    section: STR_UFO_COMPONENTS\n    requires:\n      - STR_ALIEN_IMPLANTER\n    image_id: UP064.BDY\n    text: STR_ALIEN_IMPLANTER_UFOPEDIA\n  - id: STR_EXAMINATION_ROOM\n    type_id: 10\n    section: STR_UFO_COMPONENTS\n    requires:\n      - STR_EXAMINATION_ROOM\n    image_id: UP065.BDY\n    text: STR_EXAMINATION_ROOM_UFOPEDIA\n  - id: STR_AQUA_PLASTICS\n    type_id: 10\n    section: STR_UFO_COMPONENTS\n    requires:\n      - STR_AQUA_PLASTICS\n    image_id: UP066.BDY\n    text: STR_AQUA_PLASTICS_UFOPEDIA\n  - id: STR_SURVEY_SHIP\n    type_id: 17\n    section: STR_UFOS\n    requires:\n      - STR_SURVEY_SHIP\n    text: STR_SURVEY_SHIP_UFOPEDIA\n    image_id: UP093.BDY\n  - id: STR_ESCORT\n    type_id: 17\n    section: STR_UFOS\n    requires:\n      - STR_ESCORT\n    text: STR_ESCORT_UFOPEDIA\n    image_id: UP094.BDY\n  - id: STR_CRUISER\n    type_id: 17\n    section: STR_UFOS\n    requires:\n      - STR_CRUISER\n    text: STR_CRUISER_UFOPEDIA\n    image_id: UP095.BDY\n  - id: STR_HEAVY_CRUISER\n    type_id: 17\n    section: STR_UFOS\n    requires:\n      - STR_HEAVY_CRUISER\n    text: STR_HEAVY_CRUISER_UFOPEDIA\n    image_id: UP096.BDY\n  - id: STR_HUNTER\n    type_id: 17\n    section: STR_UFOS\n    requires:\n      - STR_HUNTER\n    text: STR_HUNTER_UFOPEDIA\n    image_id: UP097.BDY\n  - id: STR_BATTLESHIP\n    type_id: 17\n    section: STR_UFOS\n    requires:\n      - STR_BATTLESHIP\n    text: STR_BATTLESHIP_UFOPEDIA\n    image_id: UP098.BDY\n  - id: STR_DREADNOUGHT\n    type_id: 17\n    section: STR_UFOS\n    requires:\n      - STR_DREADNOUGHT\n    text: STR_DREADNOUGHT_UFOPEDIA\n    image_id: UP099.BDY\n  - id: STR_FLEET_SUPPLY_CRUISER\n    type_id: 17\n    section: STR_UFOS\n    requires:\n      - STR_FLEET_SUPPLY_CRUISER\n    text: STR_FLEET_SUPPLY_CRUISER_UFOPEDIA\n    image_id: UP100.BDY\n"
  },
  {
    "path": "bin/standard/xcom2/ufos.rul",
    "content": "ufos: #done\n  - type: STR_SURVEY_SHIP\n    size: STR_VERY_SMALL\n    sprite: 0\n    damageMax: 60\n    speedMax: 2000\n    power: 0\n    range: 0\n    score: 50\n    reload: 56\n    breakOffTime: 200\n    battlescapeTerrainData:\n      name: UFO01\n      mapDataSets:\n        - BLANKS\n        - UEXT2\n        - UEXT3\n        - UINT1\n        - UINT2\n        - UINT3\n      mapBlocks:\n        - name: UFO01\n          width: 10\n          length: 10\n  - type: STR_ESCORT\n    size: STR_SMALL\n    sprite: 1\n    damageMax: 300\n    speedMax: 2800\n    power: 30\n    range: 13\n    score: 75\n    reload: 56\n    breakOffTime: 250\n    battlescapeTerrainData:\n      name: UFO02\n      mapDataSets:\n        - BLANKS\n        - UEXT2\n        - UEXT3\n        - UINT1\n        - UINT2\n        - UINT3\n      mapBlocks:\n        - name: UFO02\n          width: 10\n          length: 10\n          items:\n            STR_ZRBITE:\n              - [2, 2, 0]\n  - type: STR_CRUISER\n    size: STR_SMALL\n    sprite: 2\n    damageMax: 300\n    speedMax: 2600\n    power: 25\n    range: 35\n    score: 125\n    reload: 48\n    breakOffTime: 300\n    battlescapeTerrainData:\n      name: UFO03\n      mapDataSets:\n        - BLANKS\n        - UEXT2\n        - UEXT3\n        - UINT1\n        - UINT2\n        - UINT3\n      mapBlocks:\n        - name: UFO03\n          width: 20\n          length: 20\n          items:\n            STR_ZRBITE:\n              - [10, 3, 0]\n  - type: STR_HEAVY_CRUISER\n    size: STR_MEDIUM_UC\n    sprite: 3\n    damageMax: 450\n    speedMax: 3800\n    power: 60\n    range: 20\n    score: 250\n    reload: 48\n    breakOffTime: 500\n    battlescapeTerrainData:\n      name: UFO04\n      mapDataSets:\n        - BLANKS\n        - UEXT2\n        - UEXT3\n        - UINT1\n        - UINT2\n        - UINT3\n      mapBlocks:\n        - name: UFO04\n          width: 20\n          length: 20\n          items:\n            STR_ZRBITE:\n              - [5, 8, 0]\n              - [3, 8, 0]\n  - type: STR_HUNTER\n    size: STR_MEDIUM_UC\n    sprite: 4\n    damageMax: 500\n    speedMax: 4500\n    power: 50\n    range: 18\n    score: 250\n    reload: 32\n    breakOffTime: 500\n    battlescapeTerrainData:\n      name: UFO05\n      mapDataSets:\n        - BLANKS\n        - UEXT2\n        - UEXT3\n        - UINT1\n        - UINT2\n        - UINT3\n      mapBlocks:\n        - name: UFO05\n          width: 20\n          length: 20\n          items:\n            STR_ZRBITE:\n              - [9, 3, 1]\n              - [10, 3, 1]\n  - type: STR_BATTLESHIP\n    size: STR_LARGE\n    sprite: 7\n    damageMax: 1400\n    speedMax: 4200\n    power: 120\n    range: 50\n    score: 500\n    reload: 24\n    breakOffTime: 2000\n    battlescapeTerrainData:\n      name: UFO06\n      mapDataSets:\n        - BLANKS\n        - UEXT2\n        - UEXT3\n        - UINT1\n        - UINT2\n        - UINT3\n      mapBlocks:\n        - name: UFO06\n          width: 20\n          length: 30\n          items:\n            STR_ZRBITE:\n              - [8, 12, 0]\n              - [9, 14, 0]\n              - [6, 14, 1]\n              - [5, 15, 1]\n  - type: STR_DREADNOUGHT\n    size: STR_VERY_LARGE\n    sprite: 6\n    damageMax: 3400\n    speedMax: 4800\n    power: 140\n    range: 60\n    score: 700\n    reload: 24\n    breakOffTime: 4000\n    battlescapeTerrainData:\n      name: UFO07\n      mapDataSets:\n        - BLANKS\n        - UEXT2\n        - UEXT3\n        - UINT1\n        - UINT2\n        - UINT3\n      mapBlocks:\n        - name: UFO07\n          width: 30\n          length: 30\n          items:\n            STR_ZRBITE:\n              - [17, 2, 0]\n              - [16, 3, 0]\n              - [3, 12, 0]\n              - [26, 12, 0]\n  - type: STR_FLEET_SUPPLY_CRUISER\n    size: STR_LARGE\n    sprite: 5\n    damageMax: 2000\n    speedMax: 3400\n    power: 70\n    range: 38\n    score: 400\n    reload: 24\n    breakOffTime: 3000\n    battlescapeTerrainData:\n      name: UFO08\n      mapDataSets:\n        - BLANKS\n        - UEXT2\n        - UEXT3\n        - UINT1\n        - UINT2\n        - UINT3\n      mapBlocks:\n        - name: UFO08\n          width: 20\n          length: 30\n          items:\n            STR_ZRBITE:\n              - [11, 2, 0]\n              - [10, 3, 0]\n              - [8, 2, 0]\n"
  },
  {
    "path": "bin/standard/xcom2/units.rul",
    "content": "units: #done\n  - type: STR_AQUATOID_SOLDIER\n    race: STR_AQUATOID\n    rank: STR_LIVE_SOLDIER\n    stats:\n      tu: 54\n      stamina: 90\n      health: 30\n      bravery: 80\n      reactions: 63\n      firing: 52\n      throwing: 58\n      strength: 30\n      psiStrength: 35\n      psiSkill: 0\n      melee: 76\n    armor: AQUATOID_ARMOR0\n    standHeight: 16\n    kneelHeight: 12\n    value: 10\n    deathSound: 50\n    intelligence: 3\n    aggression: 2\n  - type: STR_AQUATOID_SQUAD_LEADER\n    race: STR_AQUATOID\n    rank: STR_LIVE_SQUAD_LEADER\n    stats:\n      tu: 54\n      stamina: 90\n      health: 35\n      bravery: 80\n      reactions: 63\n      firing: 52\n      throwing: 58\n      strength: 30\n      psiStrength: 35\n      psiSkill: 0\n      melee: 76\n    armor: AQUATOID_ARMOR0\n    standHeight: 16\n    kneelHeight: 12\n    value: 10\n    deathSound: 50\n    intelligence: 4\n    aggression: 2\n  - type: STR_AQUATOID_TECHNICIAN\n    race: STR_AQUATOID\n    rank: STR_LIVE_TECHNICIAN\n    stats:\n      tu: 54\n      stamina: 90\n      health: 35\n      bravery: 80\n      reactions: 63\n      firing: 52\n      throwing: 58\n      strength: 30\n      psiStrength: 40\n      psiSkill: 25\n      melee: 76\n    armor: AQUATOID_ARMOR0\n    standHeight: 16\n    kneelHeight: 12\n    value: 10\n    deathSound: 50\n    intelligence: 5\n    aggression: 2\n  - type: STR_AQUATOID_MEDIC\n    race: STR_AQUATOID\n    rank: STR_LIVE_MEDIC\n    stats:\n      tu: 54\n      stamina: 90\n      health: 35\n      bravery: 80\n      reactions: 63\n      firing: 52\n      throwing: 58\n      strength: 35\n      psiStrength: 40\n      psiSkill: 0\n      melee: 76\n    armor: AQUATOID_ARMOR0\n    standHeight: 16\n    kneelHeight: 12\n    value: 10\n    deathSound: 50\n    intelligence: 6\n    aggression: 2\n  - type: STR_AQUATOID_NAVIGATOR\n    race: STR_AQUATOID\n    rank: STR_LIVE_NAVIGATOR\n    stats:\n      tu: 54\n      stamina: 100\n      health: 35\n      bravery: 80\n      reactions: 63\n      firing: 52\n      throwing: 58\n      strength: 40\n      psiStrength: 40\n      psiSkill: 30\n      melee: 76\n    armor: AQUATOID_ARMOR0\n    standHeight: 16\n    kneelHeight: 12\n    value: 10\n    deathSound: 50\n    intelligence: 7\n    aggression: 1\n  - type: STR_AQUATOID_COMMANDER\n    race: STR_AQUATOID\n    rank: STR_LIVE_COMMANDER\n    stats:\n      tu: 54\n      stamina: 100\n      health: 35\n      bravery: 80\n      reactions: 63\n      firing: 52\n      throwing: 58\n      strength: 40\n      psiStrength: 50\n      psiSkill: 50\n      melee: 76\n    armor: AQUATOID_ARMOR0\n    standHeight: 16\n    kneelHeight: 12\n    value: 10\n    deathSound: 50\n    intelligence: 8\n    aggression: 0\n  - type: STR_GILLMAN_SOLDIER\n    race: STR_GILLMAN\n    rank: STR_LIVE_SOLDIER\n    stats:\n      tu: 40\n      stamina: 80\n      health: 45\n      bravery: 90\n      reactions: 45\n      firing: 45\n      throwing: 50\n      strength: 47\n      psiStrength: 30\n      psiSkill: 0\n      melee: 54\n    armor: GILLMAN_ARMOR0\n    standHeight: 20\n    kneelHeight: 12\n    value: 15\n    deathSound: 51\n    intelligence: 2\n    aggression: 2\n  - type: STR_GILLMAN_SQUAD_LEADER\n    race: STR_GILLMAN\n    rank: STR_LIVE_SQUAD_LEADER\n    stats:\n      tu: 45\n      stamina: 80\n      health: 50\n      bravery: 80\n      reactions: 45\n      firing: 49\n      throwing: 54\n      strength: 47\n      psiStrength: 30\n      psiSkill: 0\n      melee: 54\n    armor: GILLMAN_ARMOR0\n    standHeight: 20\n    kneelHeight: 12\n    value: 17\n    deathSound: 51\n    intelligence: 2\n    aggression: 2\n  - type: STR_GILLMAN_TECHNICIAN\n    race: STR_GILLMAN\n    rank: STR_LIVE_TECHNICIAN\n    stats:\n      tu: 45\n      stamina: 80\n      health: 55\n      bravery: 80\n      reactions: 50\n      firing: 54\n      throwing: 58\n      strength: 50\n      psiStrength: 30\n      psiSkill: 0\n      melee: 54\n    armor: GILLMAN_ARMOR0\n    standHeight: 20\n    kneelHeight: 12\n    value: 20\n    deathSound: 51\n    intelligence: 3\n    aggression: 2\n  - type: STR_GILLMAN_COMMANDER\n    race: STR_GILLMAN\n    rank: STR_LIVE_COMMANDER\n    stats:\n      tu: 50\n      stamina: 80\n      health: 60\n      bravery: 80\n      reactions: 53\n      firing: 58\n      throwing: 65\n      strength: 52\n      psiStrength: 35\n      psiSkill: 50\n      melee: 54\n    armor: GILLMAN_ARMOR0\n    standHeight: 20\n    kneelHeight: 12\n    value: 20\n    deathSound: 51\n    intelligence: 4\n    aggression: 1\n  - type: STR_TASOTH_SOLDIER\n    race: STR_TASOTH\n    rank: STR_LIVE_SOLDIER\n    stats:\n      tu: 56\n      stamina: 100\n      health: 125\n      bravery: 60\n      reactions: 80\n      firing: 54\n      throwing: 62\n      strength: 70\n      psiStrength: 30\n      psiSkill: 0\n      melee: 78\n    armor: TASOTH_ARMOR0\n    standHeight: 22\n    kneelHeight: 14\n    value: 18\n    deathSound: 54\n    intelligence: 4\n    aggression: 2\n  - type: STR_TASOTH_SQUAD_LEADER\n    race: STR_TASOTH\n    rank: STR_LIVE_SQUAD_LEADER\n    stats:\n      tu: 66\n      stamina: 100\n      health: 135\n      bravery: 80\n      reactions: 80\n      firing: 65\n      throwing: 62\n      strength: 70\n      psiStrength: 50\n      psiSkill: 40\n      melee: 78\n    armor: TASOTH_ARMOR0\n    standHeight: 22\n    kneelHeight: 14\n    value: 22\n    deathSound: 54\n    intelligence: 8\n    aggression: 2\n  - type: STR_LOBSTERMAN_SOLDIER\n    race: STR_LOBSTERMAN\n    rank: STR_LIVE_SOLDIER\n    stats:\n      tu: 56\n      stamina: 90\n      health: 90\n      bravery: 90\n      reactions: 60\n      firing: 54\n      throwing: 62\n      strength: 70\n      psiStrength: 35\n      psiSkill: 0\n      melee: 78\n    armor: LOBSTERMAN_ARMOR0\n    standHeight: 22\n    kneelHeight: 14\n    value: 20\n    deathSound: 53\n    intelligence: 2\n    aggression: 2\n    meleeWeapon: STR_LOBSTERMAN_MELEE_WEAPON\n    moveSound: 63\n  - type: STR_LOBSTERMAN_SQUAD_LEADER\n    race: STR_LOBSTERMAN\n    rank: STR_LIVE_SQUAD_LEADER\n    stats:\n      tu: 66\n      stamina: 90\n      health: 110\n      bravery: 80\n      reactions: 65\n      firing: 54\n      throwing: 62\n      strength: 70\n      psiStrength: 35\n      psiSkill: 0\n      melee: 78\n    armor: LOBSTERMAN_ARMOR0\n    standHeight: 22\n    kneelHeight: 14\n    value: 25\n    deathSound: 53\n    intelligence: 3\n    aggression: 2\n    meleeWeapon: STR_LOBSTERMAN_MELEE_WEAPON\n    moveSound: 63\n  - type: STR_LOBSTERMAN_TECHNICIAN\n    race: STR_LOBSTERMAN\n    rank: STR_LIVE_TECHNICIAN\n    stats:\n      tu: 70\n      stamina: 95\n      health: 115\n      bravery: 80\n      reactions: 70\n      firing: 54\n      throwing: 62\n      strength: 70\n      psiStrength: 35\n      psiSkill: 0\n      melee: 78\n    armor: LOBSTERMAN_ARMOR1\n    standHeight: 22\n    kneelHeight: 14\n    value: 30\n    deathSound: 53\n    intelligence: 4\n    aggression: 2\n    meleeWeapon: STR_LOBSTERMAN_MELEE_WEAPON\n    moveSound: 63\n  - type: STR_LOBSTERMAN_NAVIGATOR\n    race: STR_LOBSTERMAN\n    rank: STR_LIVE_NAVIGATOR\n    stats:\n      tu: 74\n      stamina: 95\n      health: 120\n      bravery: 80\n      reactions: 75\n      firing: 54\n      throwing: 62\n      strength: 70\n      psiStrength: 40\n      psiSkill: 0\n      melee: 78\n    armor: LOBSTERMAN_ARMOR1\n    standHeight: 22\n    kneelHeight: 14\n    value: 35\n    deathSound: 53\n    intelligence: 6\n    aggression: 1\n    meleeWeapon: STR_LOBSTERMAN_MELEE_WEAPON\n    moveSound: 63\n  - type: STR_LOBSTERMAN_COMMANDER\n    race: STR_LOBSTERMAN\n    rank: STR_LIVE_COMMANDER\n    stats:\n      tu: 76\n      stamina: 100\n      health: 125\n      bravery: 80\n      reactions: 80\n      firing: 54\n      throwing: 62\n      strength: 70\n      psiStrength: 50\n      psiSkill: 0\n      melee: 78\n    armor: LOBSTERMAN_ARMOR2\n    standHeight: 22\n    kneelHeight: 14\n    value: 40\n    deathSound: 53\n    intelligence: 8\n    aggression: 1\n    meleeWeapon: STR_LOBSTERMAN_MELEE_WEAPON\n    moveSound: 63\n  - type: STR_DEEP_ONE_TERRORIST\n    race: STR_DEEP_ONE\n    rank: STR_LIVE_TERRORIST\n    stats:\n      tu: 50\n      stamina: 90\n      health: 35\n      bravery: 90\n      reactions: 55\n      firing: 50\n      throwing: 58\n      strength: 40\n      psiStrength: 50\n      psiSkill: 0\n      melee: 70\n    armor: DEEP_ONE_ARMOR0\n    standHeight: 21\n    kneelHeight: 16\n    value: 12\n    deathSound: 56\n    intelligence: 4\n    aggression: 2\n    livingWeapon: true\n  - type: STR_TRISCENE_TERRORIST\n    race: STR_TRISCENE\n    rank: STR_LIVE_TERRORIST\n    stats:\n      tu: 72\n      stamina: 90\n      health: 158\n      bravery: 90\n      reactions: 69\n      firing: 80\n      throwing: 80\n      strength: 120\n      psiStrength: 100\n      psiSkill: 0\n      melee: 80\n    armor: TRISCENE_ARMOR0\n    standHeight: 23\n    kneelHeight: 16\n    value: 25\n    deathSound: 58\n    intelligence: 3\n    aggression: 2\n    livingWeapon: true\n    builtInWeapons:\n      - STR_TRISCENE_MELEE_WEAPON\n      - STR_TRIBIO_SONIC_WEAPON\n    moveSound: 62\n  - type: STR_XARQUID_TERRORIST\n    race: STR_XARQUID\n    rank: STR_LIVE_TERRORIST\n    stats:\n      tu: 40\n      stamina: 80\n      health: 114\n      bravery: 90\n      reactions: 50\n      firing: 65\n      throwing: 50\n      strength: 70\n      psiStrength: 100\n      psiSkill: 0\n      melee: 50\n    armor: XARQUID_ARMOR0\n    standHeight: 23\n    floatHeight: 2\n    kneelHeight: 13\n    value: 30\n    deathSound: 60\n    intelligence: 4\n    aggression: 2\n    livingWeapon: true\n    moveSound: 65\n  - type: STR_CALCINITE_TERRORIST\n    race: STR_CALCINITE\n    rank: STR_LIVE_TERRORIST\n    stats:\n      tu: 68\n      stamina: 96\n      health: 55\n      bravery: 90\n      reactions: 75\n      firing: 74\n      throwing: 80\n      strength: 110\n      psiStrength: 90\n      psiSkill: 0\n      melee: 85\n    armor: CALCINITE_ARMOR0\n    standHeight: 20\n    kneelHeight: 15\n    value: 20\n    deathSound: 55\n    intelligence: 5\n    aggression: 2\n    livingWeapon: true\n  - type: STR_TENTACULAT_TERRORIST\n    race: STR_TENTACULAT\n    rank: STR_LIVE_TERRORIST\n    stats:\n      tu: 99\n      stamina: 140\n      health: 96\n      bravery: 110\n      reactions: 90\n      firing: 50\n      throwing: 50\n      strength: 100\n      psiStrength: 100\n      psiSkill: 0\n      melee: 80\n    armor: TENTACULAT_ARMOR0\n    standHeight: 22\n    floatHeight: 2\n    kneelHeight: 18\n    value: 25\n    deathSound: 52\n    intelligence: 8\n    aggression: 2\n    zombieUnit: STR_ZOMBIE\n    livingWeapon: true\n    moveSound: 64\n  - type: STR_HALLUCINOID_TERRORIST\n    race: STR_HALLUCINOID\n    rank: STR_LIVE_TERRORIST\n    stats:\n      tu: 62\n      stamina: 90\n      health: 120\n      bravery: 100\n      reactions: 90\n      firing: 80\n      throwing: 80\n      strength: 90\n      psiStrength: 90\n      psiSkill: 0\n      melee: 90\n    armor: HALLUCINOID_ARMOR0\n    standHeight: 23\n    floatHeight: 2\n    kneelHeight: 18\n    value: 35\n    deathSound: 59\n    intelligence: 7\n    aggression: 2\n    livingWeapon: true\n    moveSound: 65\n  - type: STR_BIODRONE_TERRORIST\n    race: STR_BIODRONE\n    rank: STR_LIVE_TERRORIST\n    stats:\n      tu: 80\n      stamina: 120\n      health: 140\n      bravery: 100\n      reactions: 40\n      firing: 90\n      throwing: 0\n      strength: 120\n      psiStrength: 90\n      psiSkill: 0\n      melee: 1 # vanilla TFTD had this value as 0, but it would still have a 0.89999% chance to hit with an attack.\n    armor: BIODRONE_ARMOR0\n    standHeight: 17\n    floatHeight: 2\n    kneelHeight: 12\n    value: 25\n    deathSound: 57\n    intelligence: 7\n    aggression: 2\n    specab: 3\n    livingWeapon: true\n    builtInWeapons:\n      - STR_BIODRONE_MELEE_WEAPON\n      - STR_TRIBIO_SONIC_WEAPON\n    moveSound: 66\n  - type: STR_ZOMBIE\n    race: STR_ZOMBIE\n    rank: STR_LIVE_TERRORIST\n    stats:\n      tu: 40\n      stamina: 110\n      health: 84\n      bravery: 110\n      reactions: 40\n      firing: 0\n      throwing: 0\n      strength: 120\n      psiStrength: 90\n      psiSkill: 0\n      melee: 80\n    armor: ZOMBIE_ARMOR\n    standHeight: 18\n    kneelHeight: 18\n    value: 18\n    # Zombies are silent on death, no deathSound\n    intelligence: 3\n    aggression: 2\n    spawnUnit: STR_TENTACULAT_TERRORIST\n    livingWeapon: true\n    # needs more civilian types.\n  - type: MALE_CIVILIAN\n    race: STR_CIVILIAN\n    stats:\n      tu: 35\n      stamina: 65\n      health: 30\n      bravery: 80\n      reactions: 30\n      firing: 30\n      throwing: 50\n      strength: 20\n      psiStrength: 5\n      psiSkill: 0\n      melee: 50\n    armor: SURFER_ARMOR\n    standHeight: 22\n    kneelHeight: 14\n    value: 30\n    intelligence: 1\n    deathSound: 48\n  - type: SAILOR_CIVILIAN\n    race: STR_CIVILIAN\n    stats:\n      tu: 35\n      stamina: 65\n      health: 30\n      bravery: 80\n      reactions: 30\n      firing: 30\n      throwing: 50\n      strength: 20\n      psiStrength: 5\n      psiSkill: 0\n      melee: 50\n    armor: SAILOR_ARMOR\n    standHeight: 22\n    kneelHeight: 14\n    value: 30\n    intelligence: 1\n    deathSound: 48\n  - type: DOCKER_CIVILIAN\n    race: STR_CIVILIAN\n    stats:\n      tu: 35\n      stamina: 65\n      health: 30\n      bravery: 80\n      reactions: 30\n      firing: 30\n      throwing: 50\n      strength: 20\n      psiStrength: 5\n      psiSkill: 0\n      melee: 50\n    armor: DOCKER_ARMOR\n    standHeight: 22\n    kneelHeight: 14\n    value: 30\n    intelligence: 1\n    deathSound: 48\n  - type: FEMALE_CIVILIAN\n    race: STR_CIVILIAN\n    stats:\n      tu: 35\n      stamina: 65\n      health: 30\n      bravery: 80\n      reactions: 30\n      firing: 30\n      throwing: 50\n      strength: 20\n      psiStrength: 5\n      psiSkill: 0\n      melee: 50\n    armor: BIKINI_GIRL_ARMOR\n    standHeight: 22\n    kneelHeight: 14\n    value: 30\n    intelligence: 1\n    deathSound: 48\n  - type: STR_COELACANTH_GAS_CANNON\n    race: STR_COELACANTH_GAS_CANNON\n    stats:\n      tu: 70\n      stamina: 100\n      health: 90\n      bravery: 110\n      reactions: 20\n      firing: 60\n      throwing: 0\n      strength: 60\n      psiStrength: 100\n      psiSkill: 0\n    armor: COELACANTH_ARMOR\n    standHeight: 16\n    kneelHeight: 16\n    value: 20\n    deathSound: 57\n    moveSound: 12\n    energyRecovery: 50\n  - type: STR_COELACANTH_AQUA_JET\n    race: STR_COELACANTH_AQUA_JET\n    stats:\n      tu: 70\n      stamina: 100\n      health: 90\n      bravery: 110\n      reactions: 20\n      firing: 60\n      throwing: 0\n      strength: 60\n      psiStrength: 100\n      psiSkill: 0\n    armor: COELACANTH_ARMOR\n    standHeight: 16\n    kneelHeight: 16\n    value: 20\n    deathSound: 57\n    moveSound: 12\n    energyRecovery: 50\n  - type: STR_COELACANTH_GAUSS\n    race: STR_COELACANTH_GAUSS\n    stats:\n      tu: 70\n      stamina: 100\n      health: 90\n      bravery: 110\n      reactions: 20\n      firing: 60\n      throwing: 0\n      strength: 60\n      psiStrength: 100\n      psiSkill: 0\n    armor: COELACANTH_ARMOR\n    standHeight: 16\n    kneelHeight: 16\n    value: 20\n    deathSound: 57\n    moveSound: 12\n    energyRecovery: 50\n  - type: STR_DISPLACER_SONIC\n    race: STR_DISPLACER_SONIC\n    stats:\n      tu: 100\n      stamina: 100\n      health: 90\n      bravery: 110\n      reactions: 30\n      firing: 60\n      throwing: 0\n      strength: 60\n      psiStrength: 100\n      psiSkill: 0\n    armor: DISPLACER_ARMOR\n    standHeight: 16\n    kneelHeight: 16\n    value: 20\n    deathSound: 57\n    moveSound: 66\n    energyRecovery: 50\n  - type: STR_DISPLACER_PWT\n    race: STR_DISPLACER_PWT\n    stats:\n      tu: 100\n      stamina: 100\n      health: 90\n      bravery: 110\n      reactions: 30\n      firing: 60\n      throwing: 0\n      strength: 60\n      psiStrength: 100\n      psiSkill: 0\n    armor: DISPLACER_ARMOR\n    standHeight: 16\n    kneelHeight: 16\n    value: 20\n    moveSound: 66\n    deathSound: 57\n    energyRecovery: 50\n"
  },
  {
    "path": "bin/standard/xcom2/vars.rul",
    "content": "# X-COM 2 (Terror From The Deep) ruleset\n# For documentation on these values, see http://ufopaedia.org/index.php?title=Rulesets_(OpenXcom)\n\nstartingTime: #done\n  second: 0\n  minute: 0\n  hour: 12\n  weekday: 1\n  day: 1\n  month: 1\n  year: 2040\n\ncostEngineer: 25000\ncostScientist: 30000\ntimePersonnel: 72\ninitialFunding: 6000\nalienFuel: [STR_ZRBITE, 50]\nfontName: Font.dat\n\nconstants: #done\n  doorSound: 47\n  slidingDoorSound: 46\n  slidingDoorClose: -1\n  smallExplosion: 30\n  largeExplosion: 29\n  itemDrop: 44\n  itemThrow: 42\n  itemReload: 45\n  walkOffset: 0\n  flyingSound: 66\n  buttonPress: 0\n  windowPopup: [1, 1, 1]\n  ufoFire: 5\n  ufoHit: 4\n  ufoExplode: 3\n  ufoCrash: 2\n  interceptorHit: 2\n  interceptorExplode: 2\n  explosionOffset: 8\n  smokeOffset: 56\n  underwaterSmokeOffset: 8\n  basescapeCursor: 42\n  graphsCursor: 144\n  goodDebriefingMusic: GMDEBGOO\n  badDebriefingMusic: GMDEBPOR\n\nsoundDefs: #done: double check explosions.\n  - type: GEO.CAT\n    file: SAMPLE.CAT\n    sounds:\n    # UI sounds: press and popup\n      - 120\n      - 98\n    # ufo hit interceptor/ufo crash/interceptor crash, ufo explode, interceptor hit ufo, ufo fire\n      - 27\n      - 28\n      - 31\n      - 37\n    # craft weapon sounds: ajax, dup, cannon, pwt, gauss, plasma\n      - 14\n      - 15\n      - 33\n      - 97\n      - 37\n      - 18\n    # base defenses: torpedo, gauss, sonic, pwt\n      - 13\n      - 14\n      - 15\n      - 24\n  - type: BATTLE.CAT\n    file: SAMPLE.CAT\n    soundRanges:\n      - [49, 96]\n      - [99, 117]\n    sounds: [122]\n  - type: BATTLE2.CAT\n    file: SAMPLE.CAT\n    soundRanges:\n      - [0, 47]\n      - [99, 117]\n    sounds: [48]\n\ntransparencyLUTs: #done\n  - colors:\n      - [  8,  8, 12, 2 ] # \"white\"\n      - [ 16,  8,  0, 2 ] # orange\n      - [  0, 12, 12, 2 ] # cyan\n      - [  4, 16,  4, 2 ] # green\n"
  },
  {
    "path": "cmake/modules/BuildType.cmake",
    "content": "# From https://raw.githubusercontent.com/OpenChemistry/tomviz/master/cmake/BuildType.cmake\n# Their project license is BSDL 3-Clause\n# Found via https://blog.kitware.com/cmake-and-the-default-build-type/\n#\n# Set a default build type if none was specified\nset(default_build_type \"Release\")\n\nif(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)\n  message(STATUS \"Setting build type to '${default_build_type}' as none was specified.\")\n  set(CMAKE_BUILD_TYPE \"${default_build_type}\" CACHE\n      STRING \"Choose the type of build.\" FORCE)\n  # Set the possible values of build type for cmake-gui\n  set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS \"Debug\" \"Release\"\n    \"MinSizeRel\" \"RelWithDebInfo\")\nendif()\n"
  },
  {
    "path": "cmake/modules/Description.txt",
    "content": "OpenXcom is an open-source clone of the popular UFO: Enemy Unknown (X-COM: UFO\nDefense in USA) turn-based strategy game by MicroProse. It is written in\nC++/SDL and licensed under the GPL3. OpenXcom requires game resources from the\noriginal game (DOS, Windows or Steam version).\n"
  },
  {
    "path": "cmake/modules/NSIS.template.in",
    "content": "; CPack install script designed for a nmake build\n\n;--------------------------------\n; You must define these values\n\n  !define VERSION \"@CPACK_PACKAGE_VERSION@\"\n  !define PATCH  \"@CPACK_PACKAGE_VERSION_PATCH@\"\n  !define INST_DIR \"@CPACK_TEMPORARY_DIRECTORY@\"\n\n;--------------------------------\n;Variables\n\n  Var MUI_TEMP\n  Var STARTMENU_FOLDER\n  Var SV_ALLUSERS\n  Var START_MENU\n  Var DO_NOT_ADD_TO_PATH\n  Var ADD_TO_PATH_ALL_USERS\n  Var ADD_TO_PATH_CURRENT_USER\n  Var INSTALL_DESKTOP\n  Var IS_DEFAULT_INSTALLDIR\n  Var UFODIR\n;--------------------------------\n;Include Modern UI\n\n  !include \"MUI.nsh\"\n  !include \"FileFunc.nsh\"\n\n  ;Default installation folder\n  InstallDir \"@CPACK_NSIS_INSTALL_ROOT@\\@CPACK_PACKAGE_INSTALL_DIRECTORY@\"\n\n;--------------------------------\n;General\n\n  ;Name and file\n  Name \"@CPACK_NSIS_PACKAGE_NAME@\"\n  !define GAME_NAME \"@CPACK_NSIS_PACKAGE_NAME@\"\n  OutFile \"@CPACK_TOPLEVEL_DIRECTORY@/@CPACK_OUTPUT_FILE_NAME@\"\n\n  ;Set compression\n  SetCompressor @CPACK_NSIS_COMPRESSOR@\n\n@CPACK_NSIS_DEFINES@\n\n  !include Sections.nsh\n\n;--- Component support macros: ---\n; The code for the add/remove functionality is from:\n;   http://nsis.sourceforge.net/Add/Remove_Functionality\n; It has been modified slightly and extended to provide\n; inter-component dependencies.\nVar AR_SecFlags\nVar AR_RegFlags\n@CPACK_NSIS_SECTION_SELECTED_VARS@\n\n; Loads the \"selected\" flag for the section named SecName into the\n; variable VarName.\n!macro LoadSectionSelectedIntoVar SecName VarName\n SectionGetFlags ${${SecName}} $${VarName}\n IntOp $${VarName} $${VarName} & ${SF_SELECTED}  ;Turn off all other bits\n!macroend\n\n; Loads the value of a variable... can we get around this?\n!macro LoadVar VarName\n  IntOp $R0 0 + $${VarName}\n!macroend\n\n; Sets the value of a variable\n!macro StoreVar VarName IntValue\n  IntOp $${VarName} 0 + ${IntValue}\n!macroend\n\n!macro InitSection SecName\n  ;  This macro reads component installed flag from the registry and\n  ;changes checked state of the section on the components page.\n  ;Input: section index constant name specified in Section command.\n\n  ClearErrors\n  ;Reading component status from registry\n  ReadRegDWORD $AR_RegFlags HKLM \"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@\\Components\\${SecName}\" \"Installed\"\n  IfErrors \"default_${SecName}\"\n    ;Status will stay default if registry value not found\n    ;(component was never installed)\n  IntOp $AR_RegFlags $AR_RegFlags & ${SF_SELECTED} ;Turn off all other bits\n  SectionGetFlags ${${SecName}} $AR_SecFlags  ;Reading default section flags\n  IntOp $AR_SecFlags $AR_SecFlags & 0xFFFE  ;Turn lowest (enabled) bit off\n  IntOp $AR_SecFlags $AR_RegFlags | $AR_SecFlags      ;Change lowest bit\n\n  ; Note whether this component was installed before\n  !insertmacro StoreVar ${SecName}_was_installed $AR_RegFlags\n  IntOp $R0 $AR_RegFlags & $AR_RegFlags\n\n  ;Writing modified flags\n  SectionSetFlags ${${SecName}} $AR_SecFlags\n\n \"default_${SecName}:\"\n !insertmacro LoadSectionSelectedIntoVar ${SecName} ${SecName}_selected\n!macroend\n\n!macro FinishSection SecName\n  ;  This macro reads section flag set by user and removes the section\n  ;if it is not selected.\n  ;Then it writes component installed flag to registry\n  ;Input: section index constant name specified in Section command.\n\n  SectionGetFlags ${${SecName}} $AR_SecFlags  ;Reading section flags\n  ;Checking lowest bit:\n  IntOp $AR_SecFlags $AR_SecFlags & ${SF_SELECTED}\n  IntCmp $AR_SecFlags 1 \"leave_${SecName}\"\n    ;Section is not selected:\n    ;Calling Section uninstall macro and writing zero installed flag\n    !insertmacro \"Remove_${${SecName}}\"\n    WriteRegDWORD HKLM \"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@\\Components\\${SecName}\" \\\n  \"Installed\" 0\n    Goto \"exit_${SecName}\"\n\n \"leave_${SecName}:\"\n    ;Section is selected:\n    WriteRegDWORD HKLM \"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@\\Components\\${SecName}\" \\\n  \"Installed\" 1\n\n \"exit_${SecName}:\"\n!macroend\n\n!macro RemoveSection SecName\n  ;  This macro is used to call section's Remove_... macro\n  ;from the uninstaller.\n  ;Input: section index constant name specified in Section command.\n\n  !insertmacro \"Remove_${${SecName}}\"\n!macroend\n\n; Determine whether the selection of SecName changed\n!macro MaybeSelectionChanged SecName\n  !insertmacro LoadVar ${SecName}_selected\n  SectionGetFlags ${${SecName}} $R1\n  IntOp $R1 $R1 & ${SF_SELECTED} ;Turn off all other bits\n\n  ; See if the status has changed:\n  IntCmp $R0 $R1 \"${SecName}_unchanged\"\n  !insertmacro LoadSectionSelectedIntoVar ${SecName} ${SecName}_selected\n\n  IntCmp $R1 ${SF_SELECTED} \"${SecName}_was_selected\"\n  !insertmacro \"Deselect_required_by_${SecName}\"\n  goto \"${SecName}_unchanged\"\n\n  \"${SecName}_was_selected:\"\n  !insertmacro \"Select_${SecName}_depends\"\n\n  \"${SecName}_unchanged:\"\n!macroend\n;--- End of Add/Remove macros ---\n\n;--------------------------------\n;Interface Settings\n\n  !define MUI_HEADERIMAGE\n  !define MUI_ABORTWARNING\n\n;--------------------------------\n; path functions\n\n!verbose 3\n!include \"WinMessages.NSH\"\n!verbose 4\n\n;----------------------------------------\n; based upon a script of \"Written by KiCHiK 2003-01-18 05:57:02\"\n;----------------------------------------\n!verbose 3\n!include \"WinMessages.NSH\"\n!verbose 4\n;====================================================\n; get_NT_environment\n;     Returns: the selected environment\n;     Output : head of the stack\n;====================================================\n!macro select_NT_profile UN\nFunction ${UN}select_NT_profile\n   StrCmp $ADD_TO_PATH_ALL_USERS \"1\" 0 environment_single\n      DetailPrint \"Selected environment for all users\"\n      Push \"all\"\n      Return\n   environment_single:\n      DetailPrint \"Selected environment for current user only.\"\n      Push \"current\"\n      Return\nFunctionEnd\n!macroend\n!insertmacro select_NT_profile \"\"\n!insertmacro select_NT_profile \"un.\"\n;----------------------------------------------------\n!define NT_current_env 'HKCU \"Environment\"'\n!define NT_all_env     'HKLM \"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment\"'\n\n!ifndef WriteEnvStr_RegKey\n  !ifdef ALL_USERS\n    !define WriteEnvStr_RegKey \\\n       'HKLM \"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment\"'\n  !else\n    !define WriteEnvStr_RegKey 'HKCU \"Environment\"'\n  !endif\n!endif\n\n; AddToPath - Adds the given dir to the search path.\n;        Input - head of the stack\n;        Note - Win9x systems requires reboot\n\nFunction AddToPath\n  Exch $0\n  Push $1\n  Push $2\n  Push $3\n\n  # don't add if the path doesn't exist\n  IfFileExists \"$0\\*.*\" \"\" AddToPath_done\n\n  ReadEnvStr $1 PATH\n  ; if the path is too long for a NSIS variable NSIS will return a 0\n  ; length string.  If we find that, then warn and skip any path\n  ; modification as it will trash the existing path.\n  StrLen $2 $1\n  IntCmp $2 0 CheckPathLength_ShowPathWarning CheckPathLength_Done CheckPathLength_Done\n    CheckPathLength_ShowPathWarning:\n    Messagebox MB_OK|MB_ICONEXCLAMATION \"Warning! PATH too long installer unable to modify PATH!\"\n    Goto AddToPath_done\n  CheckPathLength_Done:\n  Push \"$1;\"\n  Push \"$0;\"\n  Call StrStr\n  Pop $2\n  StrCmp $2 \"\" \"\" AddToPath_done\n  Push \"$1;\"\n  Push \"$0\\;\"\n  Call StrStr\n  Pop $2\n  StrCmp $2 \"\" \"\" AddToPath_done\n  GetFullPathName /SHORT $3 $0\n  Push \"$1;\"\n  Push \"$3;\"\n  Call StrStr\n  Pop $2\n  StrCmp $2 \"\" \"\" AddToPath_done\n  Push \"$1;\"\n  Push \"$3\\;\"\n  Call StrStr\n  Pop $2\n  StrCmp $2 \"\" \"\" AddToPath_done\n\n  Call IsNT\n  Pop $1\n  StrCmp $1 1 AddToPath_NT\n    ; Not on NT\n    StrCpy $1 $WINDIR 2\n    FileOpen $1 \"$1\\autoexec.bat\" a\n    FileSeek $1 -1 END\n    FileReadByte $1 $2\n    IntCmp $2 26 0 +2 +2 # DOS EOF\n      FileSeek $1 -1 END # write over EOF\n    FileWrite $1 \"$\\r$\\nSET PATH=%PATH%;$3$\\r$\\n\"\n    FileClose $1\n    SetRebootFlag true\n    Goto AddToPath_done\n\n  AddToPath_NT:\n    StrCmp $ADD_TO_PATH_ALL_USERS \"1\" ReadAllKey\n      ReadRegStr $1 ${NT_current_env} \"PATH\"\n      Goto DoTrim\n    ReadAllKey:\n      ReadRegStr $1 ${NT_all_env} \"PATH\"\n    DoTrim:\n    StrCmp $1 \"\" AddToPath_NTdoIt\n      Push $1\n      Call Trim\n      Pop $1\n      StrCpy $0 \"$1;$0\"\n    AddToPath_NTdoIt:\n      StrCmp $ADD_TO_PATH_ALL_USERS \"1\" WriteAllKey\n        WriteRegExpandStr ${NT_current_env} \"PATH\" $0\n        Goto DoSend\n      WriteAllKey:\n        WriteRegExpandStr ${NT_all_env} \"PATH\" $0\n      DoSend:\n      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 \"STR:Environment\" /TIMEOUT=5000\n\n  AddToPath_done:\n    Pop $3\n    Pop $2\n    Pop $1\n    Pop $0\nFunctionEnd\n\n\n; RemoveFromPath - Remove a given dir from the path\n;     Input: head of the stack\n\nFunction un.RemoveFromPath\n  Exch $0\n  Push $1\n  Push $2\n  Push $3\n  Push $4\n  Push $5\n  Push $6\n\n  IntFmt $6 \"%c\" 26 # DOS EOF\n\n  Call un.IsNT\n  Pop $1\n  StrCmp $1 1 unRemoveFromPath_NT\n    ; Not on NT\n    StrCpy $1 $WINDIR 2\n    FileOpen $1 \"$1\\autoexec.bat\" r\n    GetTempFileName $4\n    FileOpen $2 $4 w\n    GetFullPathName /SHORT $0 $0\n    StrCpy $0 \"SET PATH=%PATH%;$0\"\n    Goto unRemoveFromPath_dosLoop\n\n    unRemoveFromPath_dosLoop:\n      FileRead $1 $3\n      StrCpy $5 $3 1 -1 # read last char\n      StrCmp $5 $6 0 +2 # if DOS EOF\n        StrCpy $3 $3 -1 # remove DOS EOF so we can compare\n      StrCmp $3 \"$0$\\r$\\n\" unRemoveFromPath_dosLoopRemoveLine\n      StrCmp $3 \"$0$\\n\" unRemoveFromPath_dosLoopRemoveLine\n      StrCmp $3 \"$0\" unRemoveFromPath_dosLoopRemoveLine\n      StrCmp $3 \"\" unRemoveFromPath_dosLoopEnd\n      FileWrite $2 $3\n      Goto unRemoveFromPath_dosLoop\n      unRemoveFromPath_dosLoopRemoveLine:\n        SetRebootFlag true\n        Goto unRemoveFromPath_dosLoop\n\n    unRemoveFromPath_dosLoopEnd:\n      FileClose $2\n      FileClose $1\n      StrCpy $1 $WINDIR 2\n      Delete \"$1\\autoexec.bat\"\n      CopyFiles /SILENT $4 \"$1\\autoexec.bat\"\n      Delete $4\n      Goto unRemoveFromPath_done\n\n  unRemoveFromPath_NT:\n    StrCmp $ADD_TO_PATH_ALL_USERS \"1\" unReadAllKey\n      ReadRegStr $1 ${NT_current_env} \"PATH\"\n      Goto unDoTrim\n    unReadAllKey:\n      ReadRegStr $1 ${NT_all_env} \"PATH\"\n    unDoTrim:\n    StrCpy $5 $1 1 -1 # copy last char\n    StrCmp $5 \";\" +2 # if last char != ;\n      StrCpy $1 \"$1;\" # append ;\n    Push $1\n    Push \"$0;\"\n    Call un.StrStr ; Find `$0;` in $1\n    Pop $2 ; pos of our dir\n    StrCmp $2 \"\" unRemoveFromPath_done\n      ; else, it is in path\n      # $0 - path to add\n      # $1 - path var\n      StrLen $3 \"$0;\"\n      StrLen $4 $2\n      StrCpy $5 $1 -$4 # $5 is now the part before the path to remove\n      StrCpy $6 $2 \"\" $3 # $6 is now the part after the path to remove\n      StrCpy $3 $5$6\n\n      StrCpy $5 $3 1 -1 # copy last char\n      StrCmp $5 \";\" 0 +2 # if last char == ;\n        StrCpy $3 $3 -1 # remove last char\n\n      StrCmp $ADD_TO_PATH_ALL_USERS \"1\" unWriteAllKey\n        WriteRegExpandStr ${NT_current_env} \"PATH\" $3\n        Goto unDoSend\n      unWriteAllKey:\n        WriteRegExpandStr ${NT_all_env} \"PATH\" $3\n      unDoSend:\n      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 \"STR:Environment\" /TIMEOUT=5000\n\n  unRemoveFromPath_done:\n    Pop $6\n    Pop $5\n    Pop $4\n    Pop $3\n    Pop $2\n    Pop $1\n    Pop $0\nFunctionEnd\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n; Uninstall sutff\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n###########################################\n#            Utility Functions            #\n###########################################\n\n;====================================================\n; IsNT - Returns 1 if the current system is NT, 0\n;        otherwise.\n;     Output: head of the stack\n;====================================================\n; IsNT\n; no input\n; output, top of the stack = 1 if NT or 0 if not\n;\n; Usage:\n;   Call IsNT\n;   Pop $R0\n;  ($R0 at this point is 1 or 0)\n\n!macro IsNT un\nFunction ${un}IsNT\n  Push $0\n  ReadRegStr $0 HKLM \"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\" CurrentVersion\n  StrCmp $0 \"\" 0 IsNT_yes\n  ; we are not NT.\n  Pop $0\n  Push 0\n  Return\n\n  IsNT_yes:\n    ; NT!!!\n    Pop $0\n    Push 1\nFunctionEnd\n!macroend\n!insertmacro IsNT \"\"\n!insertmacro IsNT \"un.\"\n\n; StrStr\n; input, top of stack = string to search for\n;        top of stack-1 = string to search in\n; output, top of stack (replaces with the portion of the string remaining)\n; modifies no other variables.\n;\n; Usage:\n;   Push \"this is a long ass string\"\n;   Push \"ass\"\n;   Call StrStr\n;   Pop $R0\n;  ($R0 at this point is \"ass string\")\n\n!macro StrStr un\nFunction ${un}StrStr\nExch $R1 ; st=haystack,old$R1, $R1=needle\n  Exch    ; st=old$R1,haystack\n  Exch $R2 ; st=old$R1,old$R2, $R2=haystack\n  Push $R3\n  Push $R4\n  Push $R5\n  StrLen $R3 $R1\n  StrCpy $R4 0\n  ; $R1=needle\n  ; $R2=haystack\n  ; $R3=len(needle)\n  ; $R4=cnt\n  ; $R5=tmp\n  loop:\n    StrCpy $R5 $R2 $R3 $R4\n    StrCmp $R5 $R1 done\n    StrCmp $R5 \"\" done\n    IntOp $R4 $R4 + 1\n    Goto loop\ndone:\n  StrCpy $R1 $R2 \"\" $R4\n  Pop $R5\n  Pop $R4\n  Pop $R3\n  Pop $R2\n  Exch $R1\nFunctionEnd\n!macroend\n!insertmacro StrStr \"\"\n!insertmacro StrStr \"un.\"\n\nFunction Trim ; Added by Pelaca\n\tExch $R1\n\tPush $R2\nLoop:\n\tStrCpy $R2 \"$R1\" 1 -1\n\tStrCmp \"$R2\" \" \" RTrim\n\tStrCmp \"$R2\" \"$\\n\" RTrim\n\tStrCmp \"$R2\" \"$\\r\" RTrim\n\tStrCmp \"$R2\" \";\" RTrim\n\tGoTo Done\nRTrim:\n\tStrCpy $R1 \"$R1\" -1\n\tGoto Loop\nDone:\n\tPop $R2\n\tExch $R1\nFunctionEnd\n\nFunction ConditionalAddToRegisty\n  Pop $0\n  Pop $1\n  StrCmp \"$0\" \"\" ConditionalAddToRegisty_EmptyString\n    WriteRegStr SHCTX \"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@\" \\\n    \"$1\" \"$0\"\n    ;MessageBox MB_OK \"Set Registry: '$1' to '$0'\"\n    DetailPrint \"Set install registry entry: '$1' to '$0'\"\n  ConditionalAddToRegisty_EmptyString:\nFunctionEnd\n\n;--------------------------------\n\n!ifdef CPACK_USES_DOWNLOAD\nFunction DownloadFile\n    IfFileExists $INSTDIR\\* +2\n    CreateDirectory $INSTDIR\n    Pop $0\n\n    ; Skip if already downloaded\n    IfFileExists $INSTDIR\\$0 0 +2\n    Return\n\n    StrCpy $1 \"@CPACK_DOWNLOAD_SITE@\"\n\n  try_again:\n    NSISdl::download \"$1/$0\" \"$INSTDIR\\$0\"\n\n    Pop $1\n    StrCmp $1 \"success\" success\n    StrCmp $1 \"Cancelled\" cancel\n    MessageBox MB_OK \"Download failed: $1\"\n  cancel:\n    Return\n  success:\nFunctionEnd\n!endif\n\n;--------------------------------\n; Installation types\n@CPACK_NSIS_INSTALLATION_TYPES@\n\n;--------------------------------\n; Component sections\n@CPACK_NSIS_COMPONENT_SECTIONS@\n\n;--------------------------------\n; Define some macro setting for the gui\n@CPACK_NSIS_INSTALLER_MUI_ICON_CODE@\n@CPACK_NSIS_INSTALLER_ICON_CODE@\n@CPACK_NSIS_INSTALLER_MUI_COMPONENTS_DESC@\n@CPACK_NSIS_INSTALLER_MUI_FINISHPAGE_RUN_CODE@\n\n;--------------------------------\n;Pages\n  ;Language strings\n  LangString PAGE_UfoFolder ${LANG_ENGLISH} \"${GAME_NAME} requires a copy of UFO: Enemy Unknown / X-Com: UFO Defense. You can skip this step if you're upgrading an existing installation.$\\n$\\nSetup will copy the required files from the following folder. To copy from a different folder, click Browse and select another folder. Click Next to continue.\"\n  LangString PAGE_UfoFolder_TITLE ${LANG_ENGLISH} \"Choose UFO Location\"\n  LangString PAGE_UfoFolder_SUBTITLE ${LANG_ENGLISH} \"Choose the folder where you have UFO installed.\"\n  LangString DEST_UfoFolder ${LANG_ENGLISH} \"UFO Folder\"\n\n  !insertmacro MUI_PAGE_WELCOME\n\n  !insertmacro MUI_PAGE_LICENSE \"@CPACK_RESOURCE_FILE_LICENSE@\"\n  Page custom InstallOptionsPage\n  ; UFO Folder Page Configuration\n  !define MUI_PAGE_HEADER_TEXT $(PAGE_UfoFolder_TITLE)\n  !define MUI_PAGE_HEADER_SUBTEXT $(PAGE_UfoFolder_SUBTITLE)\n  !define MUI_DIRECTORYPAGE_TEXT_TOP $(PAGE_UfoFolder)\n  !define MUI_DIRECTORYPAGE_TEXT_DESTINATION $(DEST_UfoFolder)\n  !define MUI_DIRECTORYPAGE_VARIABLE $UFODIR\n  !define MUI_DIRECTORYPAGE_VERIFYONLEAVE\n\n  !insertmacro MUI_PAGE_DIRECTORY\n\n  ;Start Menu Folder Page Configuration\n  !define MUI_STARTMENUPAGE_REGISTRY_ROOT \"SHCTX\"\n  !define MUI_STARTMENUPAGE_REGISTRY_KEY \"Software\\@CPACK_PACKAGE_VENDOR@\\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@\"\n  !define MUI_STARTMENUPAGE_REGISTRY_VALUENAME \"Start Menu Folder\"\n  !insertmacro MUI_PAGE_STARTMENU Application $STARTMENU_FOLDER\n\n  @CPACK_NSIS_PAGE_COMPONENTS@\n\n  !insertmacro MUI_PAGE_INSTFILES\n  !insertmacro MUI_PAGE_FINISH\n\n  !insertmacro MUI_UNPAGE_CONFIRM\n  !insertmacro MUI_UNPAGE_INSTFILES\n\n;--------------------------------\n;Languages\n\n  !insertmacro MUI_LANGUAGE \"English\" ;first language is the default language\n\n\n;--------------------------------\n;Reserve Files\n\n  ;These files should be inserted before other files in the data block\n  ;Keep these lines before any File command\n  ;Only for solid compression (by default, solid compression is enabled for BZIP2 and LZMA)\n\n  ReserveFile \"NSIS.InstallOptions.ini\"\n  !insertmacro MUI_RESERVEFILE_INSTALLOPTIONS\n\n;--------------------------------\n;Installer Sections\n\nSection \"-Core installation\"\n  ;Use the entire tree produced by the INSTALL target.  Keep the\n  ;list of directories here in sync with the RMDir commands below.\n  SetOutPath \"$INSTDIR\"\n  @CPACK_NSIS_FULL_INSTALL@\n\n  ;Copy UFO files\n  ${DirState} $UFODIR $R1\n  IntCmp $R1 -1 ufo_no\n\n  CreateDirectory \"$INSTDIR\\bin\\UFO\\GEODATA\"\n  CopyFiles /SILENT \"$UFODIR\\GEODATA\\*.*\" \"$INSTDIR\\bin\\UFO\\GEODATA\"\n  CreateDirectory \"$INSTDIR\\bin\\UFO\\GEOGRAPH\"\n  CopyFiles /SILENT \"$UFODIR\\GEOGRAPH\\*.*\" \"$INSTDIR\\bin\\UFO\\GEOGRAPH\"\n  CreateDirectory \"$INSTDIR\\bin\\UFO\\MAPS\"\n  CopyFiles /SILENT \"$UFODIR\\MAPS\\*.*\" \"$INSTDIR\\bin\\UFO\\MAPS\"\n  CreateDirectory \"$INSTDIR\\bin\\UFO\\ROUTES\"\n  CopyFiles /SILENT \"$UFODIR\\ROUTES\\*.*\" \"$INSTDIR\\bin\\UFO\\ROUTES\"\n  CreateDirectory \"$INSTDIR\\bin\\UFO\\SOUND\"\n  CopyFiles /SILENT \"$UFODIR\\SOUND\\*.*\" \"$INSTDIR\\bin\\UFO\\SOUND\"\n  CreateDirectory \"$INSTDIR\\bin\\UFO\\TERRAIN\"\n  CopyFiles /SILENT \"$UFODIR\\TERRAIN\\*.*\" \"$INSTDIR\\bin\\UFO\\TERRAIN\"\n  CreateDirectory \"$INSTDIR\\bin\\UFO\\UFOGRAPH\"\n  CopyFiles /SILENT \"$UFODIR\\UFOGRAPH\\*.*\" \"$INSTDIR\\bin\\UFO\\UFOGRAPH\"\n  CreateDirectory \"$INSTDIR\\bin\\UFO\\UFOINTRO\"\n  CopyFiles /SILENT \"$UFODIR\\UFOINTRO\\*.*\" \"$INSTDIR\\bin\\UFO\\UFOINTRO\"\n  CreateDirectory \"$INSTDIR\\bin\\UFO\\UNITS\"\n  CopyFiles /SILENT \"$UFODIR\\UNITS\\*.*\" \"$INSTDIR\\bin\\UFO\\UNITS\"\n\n  ufo_no:\n\n  ;Store installation folder\n  WriteRegStr SHCTX \"Software\\@CPACK_PACKAGE_VENDOR@\\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@\" \"\" $INSTDIR\n\n  ;Create uninstaller\n  WriteUninstaller \"$INSTDIR\\Uninstall.exe\"\n  Push \"DisplayName\"\n  Push \"@CPACK_NSIS_DISPLAY_NAME@\"\n  Call ConditionalAddToRegisty\n  Push \"DisplayVersion\"\n  Push \"@CPACK_PACKAGE_VERSION@\"\n  Call ConditionalAddToRegisty\n  Push \"Publisher\"\n  Push \"@CPACK_PACKAGE_VENDOR@\"\n  Call ConditionalAddToRegisty\n  Push \"UninstallString\"\n  Push \"$INSTDIR\\Uninstall.exe\"\n  Call ConditionalAddToRegisty\n  Push \"NoRepair\"\n  Push \"1\"\n  Call ConditionalAddToRegisty\n\n  !ifdef CPACK_NSIS_ADD_REMOVE\n  ;Create add/remove functionality\n  Push \"ModifyPath\"\n  Push \"$INSTDIR\\AddRemove.exe\"\n  Call ConditionalAddToRegisty\n  !else\n  Push \"NoModify\"\n  Push \"1\"\n  Call ConditionalAddToRegisty\n  !endif\n\n  ; Optional registration\n  Push \"DisplayIcon\"\n  Push \"$INSTDIR\\@CPACK_NSIS_INSTALLED_ICON_NAME@\"\n  Call ConditionalAddToRegisty\n  Push \"HelpLink\"\n  Push \"@CPACK_NSIS_HELP_LINK@\"\n  Call ConditionalAddToRegisty\n  Push \"URLInfoAbout\"\n  Push \"@CPACK_NSIS_URL_INFO_ABOUT@\"\n  Call ConditionalAddToRegisty\n  Push \"Contact\"\n  Push \"@CPACK_NSIS_CONTACT@\"\n  Call ConditionalAddToRegisty\n  !insertmacro MUI_INSTALLOPTIONS_READ $INSTALL_DESKTOP \"NSIS.InstallOptions.ini\" \"Field 5\" \"State\"\n  !insertmacro MUI_STARTMENU_WRITE_BEGIN Application\n\n  ;Create shortcuts\n  CreateDirectory \"$SMPROGRAMS\\$STARTMENU_FOLDER\"\n@CPACK_NSIS_CREATE_ICONS@\n@CPACK_NSIS_CREATE_ICONS_EXTRA@\n  CreateShortCut \"$SMPROGRAMS\\$STARTMENU_FOLDER\\Uninstall.lnk\" \"$INSTDIR\\Uninstall.exe\"\n\n  ;Read a value from an InstallOptions INI file\n  !insertmacro MUI_INSTALLOPTIONS_READ $DO_NOT_ADD_TO_PATH \"NSIS.InstallOptions.ini\" \"Field 2\" \"State\"\n  !insertmacro MUI_INSTALLOPTIONS_READ $ADD_TO_PATH_ALL_USERS \"NSIS.InstallOptions.ini\" \"Field 3\" \"State\"\n  !insertmacro MUI_INSTALLOPTIONS_READ $ADD_TO_PATH_CURRENT_USER \"NSIS.InstallOptions.ini\" \"Field 4\" \"State\"\n\n  ; Write special uninstall registry entries\n  Push \"StartMenu\"\n  Push \"$STARTMENU_FOLDER\"\n  Call ConditionalAddToRegisty\n  Push \"DoNotAddToPath\"\n  Push \"$DO_NOT_ADD_TO_PATH\"\n  Call ConditionalAddToRegisty\n  Push \"AddToPathAllUsers\"\n  Push \"$ADD_TO_PATH_ALL_USERS\"\n  Call ConditionalAddToRegisty\n  Push \"AddToPathCurrentUser\"\n  Push \"$ADD_TO_PATH_CURRENT_USER\"\n  Call ConditionalAddToRegisty\n  Push \"InstallToDesktop\"\n  Push \"$INSTALL_DESKTOP\"\n  Call ConditionalAddToRegisty\n\n  !insertmacro MUI_STARTMENU_WRITE_END\n\n@CPACK_NSIS_EXTRA_INSTALL_COMMANDS@\n\nSectionEnd\n\nSection \"-Add to path\"\n  Push $INSTDIR\\bin\n  StrCmp \"@CPACK_NSIS_MODIFY_PATH@\" \"ON\" 0 doNotAddToPath\n  StrCmp $DO_NOT_ADD_TO_PATH \"1\" doNotAddToPath 0\n    Call AddToPath\n  doNotAddToPath:\nSectionEnd\n\n;--------------------------------\n; Create custom pages\nFunction InstallOptionsPage\n  !insertmacro MUI_HEADER_TEXT \"Install Options\" \"Choose options for installing @CPACK_NSIS_PACKAGE_NAME@\"\n  !insertmacro MUI_INSTALLOPTIONS_DISPLAY \"NSIS.InstallOptions.ini\"\n\nFunctionEnd\n\n;--------------------------------\n; determine admin versus local install\nFunction un.onInit\n\n  ClearErrors\n  UserInfo::GetName\n  IfErrors noLM\n  Pop $0\n  UserInfo::GetAccountType\n  Pop $1\n  StrCmp $1 \"Admin\" 0 +3\n    SetShellVarContext all\n    ;MessageBox MB_OK 'User \"$0\" is in the Admin group'\n    Goto done\n  StrCmp $1 \"Power\" 0 +3\n    SetShellVarContext all\n    ;MessageBox MB_OK 'User \"$0\" is in the Power Users group'\n    Goto done\n\n  noLM:\n    ;Get installation folder from registry if available\n\n  done:\n\nFunctionEnd\n\n;--- Add/Remove callback functions: ---\n!macro SectionList MacroName\n  ;This macro used to perform operation on multiple sections.\n  ;List all of your components in following manner here.\n@CPACK_NSIS_COMPONENT_SECTION_LIST@\n!macroend\n\nSection -FinishComponents\n  ;Removes unselected components and writes component status to registry\n  !insertmacro SectionList \"FinishSection\"\n\n!ifdef CPACK_NSIS_ADD_REMOVE\n  ; Get the name of the installer executable\n  System::Call 'kernel32::GetModuleFileNameA(i 0, t .R0, i 1024) i r1'\n  StrCpy $R3 $R0\n\n  ; Strip off the last 13 characters, to see if we have AddRemove.exe\n  StrLen $R1 $R0\n  IntOp $R1 $R0 - 13\n  StrCpy $R2 $R0 13 $R1\n  StrCmp $R2 \"AddRemove.exe\" addremove_installed\n\n  ; We're not running AddRemove.exe, so install it\n  CopyFiles $R3 $INSTDIR\\AddRemove.exe\n\n  addremove_installed:\n!endif\nSectionEnd\n;--- End of Add/Remove callback functions ---\n\n;--------------------------------\n; Component dependencies\nFunction .onSelChange\n  !insertmacro SectionList MaybeSelectionChanged\nFunctionEnd\n\n;--------------------------------\n;Uninstaller Section\n\nSection \"Uninstall\"\n  ReadRegStr $START_MENU SHCTX \\\n   \"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@\" \"StartMenu\"\n  ;MessageBox MB_OK \"Start menu is in: $START_MENU\"\n  ReadRegStr $DO_NOT_ADD_TO_PATH SHCTX \\\n    \"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@\" \"DoNotAddToPath\"\n  ReadRegStr $ADD_TO_PATH_ALL_USERS SHCTX \\\n    \"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@\" \"AddToPathAllUsers\"\n  ReadRegStr $ADD_TO_PATH_CURRENT_USER SHCTX \\\n    \"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@\" \"AddToPathCurrentUser\"\n  ;MessageBox MB_OK \"Add to path: $DO_NOT_ADD_TO_PATH all users: $ADD_TO_PATH_ALL_USERS\"\n  ReadRegStr $INSTALL_DESKTOP SHCTX \\\n    \"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@\" \"InstallToDesktop\"\n  ;MessageBox MB_OK \"Install to desktop: $INSTALL_DESKTOP \"\n\n@CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS@\n\n  RMDir /r \"$INSTDIR\\bin\\UFO\\GEODATA\"\n  RMDir /r \"$INSTDIR\\bin\\UFO\\GEOGRAPH\"\n  RMDir /r \"$INSTDIR\\bin\\UFO\\MAPS\"\n  RMDir /r \"$INSTDIR\\bin\\UFO\\ROUTES\"\n  RMDir /r \"$INSTDIR\\bin\\UFO\\SOUND\"\n  RMDir /r \"$INSTDIR\\bin\\UFO\\TERRAIN\"\n  RMDir /r \"$INSTDIR\\bin\\UFO\\UFOGRAPH\"\n  RMDir /r \"$INSTDIR\\bin\\UFO\\UFOINTRO\"\n  RMDir /r \"$INSTDIR\\bin\\UFO\\UNITS\"\n\n  ;Remove files we installed.\n  ;Keep the list of directories here in sync with the File commands above.\n@CPACK_NSIS_DELETE_FILES@\n@CPACK_NSIS_DELETE_DIRECTORIES@\n\n!ifdef CPACK_NSIS_ADD_REMOVE\n  ;Remove the add/remove program\n  Delete \"$INSTDIR\\AddRemove.exe\"\n!endif\n\n  ;Remove the uninstaller itself.\n  Delete \"$INSTDIR\\Uninstall.exe\"\n  DeleteRegKey SHCTX \"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@\"\n\n  ;Remove the installation directory if it is empty.\n  RMDir \"$INSTDIR\"\n\n  ; Remove the registry entries.\n  DeleteRegKey SHCTX \"Software\\@CPACK_PACKAGE_VENDOR@\\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@\"\n\n  ; Removes all optional components\n  !insertmacro SectionList \"RemoveSection\"\n\n  !insertmacro MUI_STARTMENU_GETFOLDER Application $MUI_TEMP\n\n  Delete \"$SMPROGRAMS\\$MUI_TEMP\\Uninstall.lnk\"\n@CPACK_NSIS_DELETE_ICONS@\n@CPACK_NSIS_DELETE_ICONS_EXTRA@\n\n  ;Delete empty start menu parent diretories\n  StrCpy $MUI_TEMP \"$SMPROGRAMS\\$MUI_TEMP\"\n\n  startMenuDeleteLoop:\n    ClearErrors\n    RMDir $MUI_TEMP\n    GetFullPathName $MUI_TEMP \"$MUI_TEMP\\..\"\n\n    IfErrors startMenuDeleteLoopDone\n\n    StrCmp \"$MUI_TEMP\" \"$SMPROGRAMS\" startMenuDeleteLoopDone startMenuDeleteLoop\n  startMenuDeleteLoopDone:\n\n  ; If the user changed the shortcut, then untinstall may not work. This should\n  ; try to fix it.\n  StrCpy $MUI_TEMP \"$START_MENU\"\n  Delete \"$SMPROGRAMS\\$MUI_TEMP\\Uninstall.lnk\"\n@CPACK_NSIS_DELETE_ICONS_EXTRA@\n\n  ;Delete empty start menu parent diretories\n  StrCpy $MUI_TEMP \"$SMPROGRAMS\\$MUI_TEMP\"\n\n  secondStartMenuDeleteLoop:\n    ClearErrors\n    RMDir $MUI_TEMP\n    GetFullPathName $MUI_TEMP \"$MUI_TEMP\\..\"\n\n    IfErrors secondStartMenuDeleteLoopDone\n\n    StrCmp \"$MUI_TEMP\" \"$SMPROGRAMS\" secondStartMenuDeleteLoopDone secondStartMenuDeleteLoop\n  secondStartMenuDeleteLoopDone:\n\n  DeleteRegKey /ifempty SHCTX \"Software\\@CPACK_PACKAGE_VENDOR@\\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@\"\n\n  Push $INSTDIR\\bin\n  StrCmp $DO_NOT_ADD_TO_PATH_ \"1\" doNotRemoveFromPath 0\n    Call un.RemoveFromPath\n  doNotRemoveFromPath:\nSectionEnd\n\n;--------------------------------\n; determine admin versus local install\n; Is install for \"AllUsers\" or \"JustMe\"?\n; Default to \"JustMe\" - set to \"AllUsers\" if admin or on Win9x\n; This function is used for the very first \"custom page\" of the installer.\n; This custom page does not show up visibly, but it executes prior to the\n; first visible page and sets up $INSTDIR properly...\n; Choose different default installation folder based on SV_ALLUSERS...\n; \"Program Files\" for AllUsers, \"My Documents\" for JustMe...\n\nFunction .onInit\n  ; Reads components status for registry\n  !insertmacro SectionList \"InitSection\"\n\n  ; check to see if /D has been used to change\n  ; the install directory by comparing it to the\n  ; install directory that is expected to be the\n  ; default\n  StrCpy $IS_DEFAULT_INSTALLDIR 0\n  StrCmp \"$INSTDIR\" \"@CPACK_NSIS_INSTALL_ROOT@\\@CPACK_PACKAGE_INSTALL_DIRECTORY@\" 0 +2\n    StrCpy $IS_DEFAULT_INSTALLDIR 1\n\n  StrCpy $SV_ALLUSERS \"JustMe\"\n  ; if default install dir then change the default\n  ; if it is installed for JustMe\n  StrCmp \"$IS_DEFAULT_INSTALLDIR\" \"1\" 0 +2\n    StrCpy $INSTDIR \"$DOCUMENTS\\@CPACK_PACKAGE_INSTALL_DIRECTORY@\"\n\n  ClearErrors\n  UserInfo::GetName\n  IfErrors noLM\n  Pop $0\n  UserInfo::GetAccountType\n  Pop $1\n  StrCmp $1 \"Admin\" 0 +3\n    SetShellVarContext all\n    ;MessageBox MB_OK 'User \"$0\" is in the Admin group'\n    StrCpy $SV_ALLUSERS \"AllUsers\"\n    Goto done\n  StrCmp $1 \"Power\" 0 +3\n    SetShellVarContext all\n    ;MessageBox MB_OK 'User \"$0\" is in the Power Users group'\n    StrCpy $SV_ALLUSERS \"AllUsers\"\n    Goto done\n\n  noLM:\n    StrCpy $SV_ALLUSERS \"AllUsers\"\n    ;Get installation folder from registry if available\n\n  done:\n  StrCmp $SV_ALLUSERS \"AllUsers\" 0 +3\n    StrCmp \"$IS_DEFAULT_INSTALLDIR\" \"1\" 0 +2\n      StrCpy $INSTDIR \"@CPACK_NSIS_INSTALL_ROOT@\\@CPACK_PACKAGE_INSTALL_DIRECTORY@\"\n\n  StrCmp \"@CPACK_NSIS_MODIFY_PATH@\" \"ON\" 0 noOptionsPage\n    !insertmacro MUI_INSTALLOPTIONS_EXTRACT \"NSIS.InstallOptions.ini\"\n\n  noOptionsPage:\n  StrCpy $UFODIR \"\"\n  ReadRegStr $R0 HKLM \"Software\\Valve\\Steam\" \"InstallPath\"\n  IfErrors ufo_no\n  StrCpy $R0 \"$R0\\steamapps\\common\\xcom ufo defense\\XCOM\"\n  ${DirState} $R0 $R1\n  IntCmp $R1 -1 ufo_no\n  StrCpy $UFODIR $R0\n  ufo_no:\nFunctionEnd\n"
  },
  {
    "path": "cmake/modules/PostprocessBundle.cmake",
    "content": "# Adapted from the Dolphin project: https://dolphin-emu.org/\n\n# This module can be used in two different ways.\n#\n# When invoked as `cmake -P PostprocessBundle.cmake`, it fixes up an\n# application folder to be standalone. It bundles all required libraries from\n# the system and fixes up library IDs. Any additional shared libraries, like\n# plugins, that are found under Contents/MacOS/ will be made standalone as well.\n#\n# When called with `include(PostprocessBundle)`, it defines a helper\n# function `postprocess_bundle` that sets up the command form of the\n# module as a post-build step.\n\nif(CMAKE_GENERATOR)\n\t# Being called as include(PostprocessBundle), so define a helper function.\n\tset(_POSTPROCESS_BUNDLE_MODULE_LOCATION \"${CMAKE_CURRENT_LIST_FILE}\")\n\tfunction(postprocess_bundle target path)\n\t\tadd_custom_command(TARGET ${target}\n\t\t\tPOST_BUILD\n\t\t\tCOMMAND ${CMAKE_COMMAND} -D \"BUNDLE_PATH=${path}\"\n\t\t\t\t-P \"${_POSTPROCESS_BUNDLE_MODULE_LOCATION}\"\n\t\t\t\tVERBATIM\n\t\t)\n\tendfunction()\n\treturn()\nendif()\n\nget_filename_component(BUNDLE_PATH \"${BUNDLE_PATH}\" ABSOLUTE)\nmessage(STATUS \"Fixing up application bundle: ${BUNDLE_PATH}\")\n\n# Make sure to fix up any additional shared libraries (like plugins) that are\n# needed.\nfile(GLOB_RECURSE extra_libs \"${BUNDLE_PATH}/Contents/MacOS/*.dylib\")\n\n# BundleUtilities doesn't support DYLD_FALLBACK_LIBRARY_PATH behavior, which\n# makes it sometimes break on libraries that do weird things with @rpath. Specify\n# equivalent search directories until https://gitlab.kitware.com/cmake/cmake/issues/16625\n# is fixed and in our minimum CMake version.\nset(extra_dirs \"/opt/homebrew/lib\" \"/usr/local/lib\" \"/lib\" \"/usr/lib\")\n\n# BundleUtilities is overly verbose, so disable most of its messages\nfunction(message)\n\tif(NOT ARGV MATCHES \"^STATUS;\")\n\t\t_message(${ARGV})\n\tendif()\nendfunction()\n\ninclude(BundleUtilities)\nset(BU_CHMOD_BUNDLE_ITEMS ON)\nfixup_bundle(\"${BUNDLE_PATH}\" \"${extra_libs}\" \"${extra_dirs}\")\n"
  },
  {
    "path": "deps/dummy.txt",
    "content": "Needed for github actions."
  },
  {
    "path": "deps/include/SDL/SDL.h",
    "content": "/*\n    SDL - Simple DirectMedia Layer\n    Copyright (C) 1997-2012 Sam Lantinga\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Lesser General Public\n    License as published by the Free Software Foundation; either\n    version 2.1 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public\n    License along with this library; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n\n    Sam Lantinga\n    slouken@libsdl.org\n*/\n\n/** @file SDL.h\n *  Main include header for the SDL library\n */\n\n#ifndef _SDL_H\n#define _SDL_H\n\n#include \"SDL_main.h\"\n#include \"SDL_stdinc.h\"\n#include \"SDL_audio.h\"\n#include \"SDL_cdrom.h\"\n#include \"SDL_cpuinfo.h\"\n#include \"SDL_endian.h\"\n#include \"SDL_error.h\"\n#include \"SDL_events.h\"\n#include \"SDL_loadso.h\"\n#include \"SDL_mutex.h\"\n#include \"SDL_rwops.h\"\n#include \"SDL_thread.h\"\n#include \"SDL_timer.h\"\n#include \"SDL_video.h\"\n#include \"SDL_version.h\"\n\n#include \"begin_code.h\"\n/* Set up for C function definitions, even when using C++ */\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/** @file SDL.h\n *  @note As of version 0.5, SDL is loaded dynamically into the application\n */\n\n/** @name SDL_INIT Flags\n *  These are the flags which may be passed to SDL_Init() -- you should\n *  specify the subsystems which you will be using in your application.\n */\n/*@{*/\n#define\tSDL_INIT_TIMER\t\t0x00000001\n#define SDL_INIT_AUDIO\t\t0x00000010\n#define SDL_INIT_VIDEO\t\t0x00000020\n#define SDL_INIT_CDROM\t\t0x00000100\n#define SDL_INIT_JOYSTICK\t0x00000200\n#define SDL_INIT_NOPARACHUTE\t0x00100000\t/**< Don't catch fatal signals */\n#define SDL_INIT_EVENTTHREAD\t0x01000000\t/**< Not supported on all OS's */\n#define SDL_INIT_EVERYTHING\t0x0000FFFF\n/*@}*/\n\n/** This function loads the SDL dynamically linked library and initializes \n *  the subsystems specified by 'flags' (and those satisfying dependencies)\n *  Unless the SDL_INIT_NOPARACHUTE flag is set, it will install cleanup\n *  signal handlers for some commonly ignored fatal signals (like SIGSEGV)\n */\nextern DECLSPEC int SDLCALL SDL_Init(Uint32 flags);\n\n/** This function initializes specific SDL subsystems */\nextern DECLSPEC int SDLCALL SDL_InitSubSystem(Uint32 flags);\n\n/** This function cleans up specific SDL subsystems */\nextern DECLSPEC void SDLCALL SDL_QuitSubSystem(Uint32 flags);\n\n/** This function returns mask of the specified subsystems which have\n *  been initialized.\n *  If 'flags' is 0, it returns a mask of all initialized subsystems.\n */\nextern DECLSPEC Uint32 SDLCALL SDL_WasInit(Uint32 flags);\n\n/** This function cleans up all initialized subsystems and unloads the\n *  dynamically linked library.  You should call it upon all exit conditions.\n */\nextern DECLSPEC void SDLCALL SDL_Quit(void);\n\n/* Ends C function definitions when using C++ */\n#ifdef __cplusplus\n}\n#endif\n#include \"close_code.h\"\n\n#endif /* _SDL_H */\n"
  },
  {
    "path": "deps/include/SDL/SDL_active.h",
    "content": "/*\n    SDL - Simple DirectMedia Layer\n    Copyright (C) 1997-2012 Sam Lantinga\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Lesser General Public\n    License as published by the Free Software Foundation; either\n    version 2.1 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public\n    License along with this library; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n\n    Sam Lantinga\n    slouken@libsdl.org\n*/\n\n/**\n *  @file SDL_active.h\n *  Include file for SDL application focus event handling \n */\n\n#ifndef _SDL_active_h\n#define _SDL_active_h\n\n#include \"SDL_stdinc.h\"\n#include \"SDL_error.h\"\n\n#include \"begin_code.h\"\n/* Set up for C function definitions, even when using C++ */\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/** @name The available application states */\n/*@{*/\n#define SDL_APPMOUSEFOCUS\t0x01\t\t/**< The app has mouse coverage */\n#define SDL_APPINPUTFOCUS\t0x02\t\t/**< The app has input focus */\n#define SDL_APPACTIVE\t\t0x04\t\t/**< The application is active */\n/*@}*/\n\n/* Function prototypes */\n/** \n * This function returns the current state of the application, which is a\n * bitwise combination of SDL_APPMOUSEFOCUS, SDL_APPINPUTFOCUS, and\n * SDL_APPACTIVE.  If SDL_APPACTIVE is set, then the user is able to\n * see your application, otherwise it has been iconified or disabled.\n */\nextern DECLSPEC Uint8 SDLCALL SDL_GetAppState(void);\n\n\n/* Ends C function definitions when using C++ */\n#ifdef __cplusplus\n}\n#endif\n#include \"close_code.h\"\n\n#endif /* _SDL_active_h */\n"
  },
  {
    "path": "deps/include/SDL/SDL_audio.h",
    "content": "/*\n    SDL - Simple DirectMedia Layer\n    Copyright (C) 1997-2012 Sam Lantinga\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Lesser General Public\n    License as published by the Free Software Foundation; either\n    version 2.1 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public\n    License along with this library; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n\n    Sam Lantinga\n    slouken@libsdl.org\n*/\n\n/**\n *  @file SDL_audio.h\n *  Access to the raw audio mixing buffer for the SDL library\n */\n\n#ifndef _SDL_audio_h\n#define _SDL_audio_h\n\n#include \"SDL_stdinc.h\"\n#include \"SDL_error.h\"\n#include \"SDL_endian.h\"\n#include \"SDL_mutex.h\"\n#include \"SDL_thread.h\"\n#include \"SDL_rwops.h\"\n\n#include \"begin_code.h\"\n/* Set up for C function definitions, even when using C++ */\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * When filling in the desired audio spec structure,\n * - 'desired->freq' should be the desired audio frequency in samples-per-second.\n * - 'desired->format' should be the desired audio format.\n * - 'desired->samples' is the desired size of the audio buffer, in samples.\n *     This number should be a power of two, and may be adjusted by the audio\n *     driver to a value more suitable for the hardware.  Good values seem to\n *     range between 512 and 8096 inclusive, depending on the application and\n *     CPU speed.  Smaller values yield faster response time, but can lead\n *     to underflow if the application is doing heavy processing and cannot\n *     fill the audio buffer in time.  A stereo sample consists of both right\n *     and left channels in LR ordering.\n *     Note that the number of samples is directly related to time by the\n *     following formula:  ms = (samples*1000)/freq\n * - 'desired->size' is the size in bytes of the audio buffer, and is\n *     calculated by SDL_OpenAudio().\n * - 'desired->silence' is the value used to set the buffer to silence,\n *     and is calculated by SDL_OpenAudio().\n * - 'desired->callback' should be set to a function that will be called\n *     when the audio device is ready for more data.  It is passed a pointer\n *     to the audio buffer, and the length in bytes of the audio buffer.\n *     This function usually runs in a separate thread, and so you should\n *     protect data structures that it accesses by calling SDL_LockAudio()\n *     and SDL_UnlockAudio() in your code.\n * - 'desired->userdata' is passed as the first parameter to your callback\n *     function.\n *\n * @note The calculated values in this structure are calculated by SDL_OpenAudio()\n *\n */\ntypedef struct SDL_AudioSpec {\n\tint freq;\t\t/**< DSP frequency -- samples per second */\n\tUint16 format;\t\t/**< Audio data format */\n\tUint8  channels;\t/**< Number of channels: 1 mono, 2 stereo */\n\tUint8  silence;\t\t/**< Audio buffer silence value (calculated) */\n\tUint16 samples;\t\t/**< Audio buffer size in samples (power of 2) */\n\tUint16 padding;\t\t/**< Necessary for some compile environments */\n\tUint32 size;\t\t/**< Audio buffer size in bytes (calculated) */\n\t/**\n\t *  This function is called when the audio device needs more data.\n\t *\n\t *  @param[out] stream\tA pointer to the audio data buffer\n\t *  @param[in]  len\tThe length of the audio buffer in bytes.\n\t *\n\t *  Once the callback returns, the buffer will no longer be valid.\n\t *  Stereo samples are stored in a LRLRLR ordering.\n\t */\n\tvoid (SDLCALL *callback)(void *userdata, Uint8 *stream, int len);\n\tvoid  *userdata;\n} SDL_AudioSpec;\n\n/**\n *  @name Audio format flags\n *  defaults to LSB byte order\n */\n/*@{*/\n#define AUDIO_U8\t0x0008\t/**< Unsigned 8-bit samples */\n#define AUDIO_S8\t0x8008\t/**< Signed 8-bit samples */\n#define AUDIO_U16LSB\t0x0010\t/**< Unsigned 16-bit samples */\n#define AUDIO_S16LSB\t0x8010\t/**< Signed 16-bit samples */\n#define AUDIO_U16MSB\t0x1010\t/**< As above, but big-endian byte order */\n#define AUDIO_S16MSB\t0x9010\t/**< As above, but big-endian byte order */\n#define AUDIO_U16\tAUDIO_U16LSB\n#define AUDIO_S16\tAUDIO_S16LSB\n\n/**\n *  @name Native audio byte ordering\n */\n/*@{*/\n#if SDL_BYTEORDER == SDL_LIL_ENDIAN\n#define AUDIO_U16SYS\tAUDIO_U16LSB\n#define AUDIO_S16SYS\tAUDIO_S16LSB\n#else\n#define AUDIO_U16SYS\tAUDIO_U16MSB\n#define AUDIO_S16SYS\tAUDIO_S16MSB\n#endif\n/*@}*/\n\n/*@}*/\n\n\n/** A structure to hold a set of audio conversion filters and buffers */\ntypedef struct SDL_AudioCVT {\n\tint needed;\t\t\t/**< Set to 1 if conversion possible */\n\tUint16 src_format;\t\t/**< Source audio format */\n\tUint16 dst_format;\t\t/**< Target audio format */\n\tdouble rate_incr;\t\t/**< Rate conversion increment */\n\tUint8 *buf;\t\t\t/**< Buffer to hold entire audio data */\n\tint    len;\t\t\t/**< Length of original audio buffer */\n\tint    len_cvt;\t\t\t/**< Length of converted audio buffer */\n\tint    len_mult;\t\t/**< buffer must be len*len_mult big */\n\tdouble len_ratio; \t/**< Given len, final size is len*len_ratio */\n\tvoid (SDLCALL *filters[10])(struct SDL_AudioCVT *cvt, Uint16 format);\n\tint filter_index;\t\t/**< Current audio conversion function */\n} SDL_AudioCVT;\n\n\n/* Function prototypes */\n\n/**\n * @name Audio Init and Quit\n * These functions are used internally, and should not be used unless you\n * have a specific need to specify the audio driver you want to use.\n * You should normally use SDL_Init() or SDL_InitSubSystem().\n */\n/*@{*/\nextern DECLSPEC int SDLCALL SDL_AudioInit(const char *driver_name);\nextern DECLSPEC void SDLCALL SDL_AudioQuit(void);\n/*@}*/\n\n/**\n * This function fills the given character buffer with the name of the\n * current audio driver, and returns a pointer to it if the audio driver has\n * been initialized.  It returns NULL if no driver has been initialized.\n */\nextern DECLSPEC char * SDLCALL SDL_AudioDriverName(char *namebuf, int maxlen);\n\n/**\n * This function opens the audio device with the desired parameters, and\n * returns 0 if successful, placing the actual hardware parameters in the\n * structure pointed to by 'obtained'.  If 'obtained' is NULL, the audio\n * data passed to the callback function will be guaranteed to be in the\n * requested format, and will be automatically converted to the hardware\n * audio format if necessary.  This function returns -1 if it failed \n * to open the audio device, or couldn't set up the audio thread.\n *\n * The audio device starts out playing silence when it's opened, and should\n * be enabled for playing by calling SDL_PauseAudio(0) when you are ready\n * for your audio callback function to be called.  Since the audio driver\n * may modify the requested size of the audio buffer, you should allocate\n * any local mixing buffers after you open the audio device.\n *\n * @sa SDL_AudioSpec\n */\nextern DECLSPEC int SDLCALL SDL_OpenAudio(SDL_AudioSpec *desired, SDL_AudioSpec *obtained);\n\ntypedef enum {\n\tSDL_AUDIO_STOPPED = 0,\n\tSDL_AUDIO_PLAYING,\n\tSDL_AUDIO_PAUSED\n} SDL_audiostatus;\n\n/** Get the current audio state */\nextern DECLSPEC SDL_audiostatus SDLCALL SDL_GetAudioStatus(void);\n\n/**\n * This function pauses and unpauses the audio callback processing.\n * It should be called with a parameter of 0 after opening the audio\n * device to start playing sound.  This is so you can safely initialize\n * data for your callback function after opening the audio device.\n * Silence will be written to the audio device during the pause.\n */\nextern DECLSPEC void SDLCALL SDL_PauseAudio(int pause_on);\n\n/**\n * This function loads a WAVE from the data source, automatically freeing\n * that source if 'freesrc' is non-zero.  For example, to load a WAVE file,\n * you could do:\n *\t@code SDL_LoadWAV_RW(SDL_RWFromFile(\"sample.wav\", \"rb\"), 1, ...); @endcode\n *\n * If this function succeeds, it returns the given SDL_AudioSpec,\n * filled with the audio data format of the wave data, and sets\n * 'audio_buf' to a malloc()'d buffer containing the audio data,\n * and sets 'audio_len' to the length of that audio buffer, in bytes.\n * You need to free the audio buffer with SDL_FreeWAV() when you are \n * done with it.\n *\n * This function returns NULL and sets the SDL error message if the \n * wave file cannot be opened, uses an unknown data format, or is \n * corrupt.  Currently raw and MS-ADPCM WAVE files are supported.\n */\nextern DECLSPEC SDL_AudioSpec * SDLCALL SDL_LoadWAV_RW(SDL_RWops *src, int freesrc, SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len);\n\n/** Compatibility convenience function -- loads a WAV from a file */\n#define SDL_LoadWAV(file, spec, audio_buf, audio_len) \\\n\tSDL_LoadWAV_RW(SDL_RWFromFile(file, \"rb\"),1, spec,audio_buf,audio_len)\n\n/**\n * This function frees data previously allocated with SDL_LoadWAV_RW()\n */\nextern DECLSPEC void SDLCALL SDL_FreeWAV(Uint8 *audio_buf);\n\n/**\n * This function takes a source format and rate and a destination format\n * and rate, and initializes the 'cvt' structure with information needed\n * by SDL_ConvertAudio() to convert a buffer of audio data from one format\n * to the other.\n *\n * @return This function returns 0, or -1 if there was an error.\n */\nextern DECLSPEC int SDLCALL SDL_BuildAudioCVT(SDL_AudioCVT *cvt,\n\t\tUint16 src_format, Uint8 src_channels, int src_rate,\n\t\tUint16 dst_format, Uint8 dst_channels, int dst_rate);\n\n/**\n * Once you have initialized the 'cvt' structure using SDL_BuildAudioCVT(),\n * created an audio buffer cvt->buf, and filled it with cvt->len bytes of\n * audio data in the source format, this function will convert it in-place\n * to the desired format.\n * The data conversion may expand the size of the audio data, so the buffer\n * cvt->buf should be allocated after the cvt structure is initialized by\n * SDL_BuildAudioCVT(), and should be cvt->len*cvt->len_mult bytes long.\n */\nextern DECLSPEC int SDLCALL SDL_ConvertAudio(SDL_AudioCVT *cvt);\n\n\n#define SDL_MIX_MAXVOLUME 128\n/**\n * This takes two audio buffers of the playing audio format and mixes\n * them, performing addition, volume adjustment, and overflow clipping.\n * The volume ranges from 0 - 128, and should be set to SDL_MIX_MAXVOLUME\n * for full audio volume.  Note this does not change hardware volume.\n * This is provided for convenience -- you can mix your own audio data.\n */\nextern DECLSPEC void SDLCALL SDL_MixAudio(Uint8 *dst, const Uint8 *src, Uint32 len, int volume);\n\n/**\n * @name Audio Locks\n * The lock manipulated by these functions protects the callback function.\n * During a LockAudio/UnlockAudio pair, you can be guaranteed that the\n * callback function is not running.  Do not call these from the callback\n * function or you will cause deadlock.\n */\n/*@{*/\nextern DECLSPEC void SDLCALL SDL_LockAudio(void);\nextern DECLSPEC void SDLCALL SDL_UnlockAudio(void);\n/*@}*/\n\n/**\n * This function shuts down audio processing and closes the audio device.\n */\nextern DECLSPEC void SDLCALL SDL_CloseAudio(void);\n\n\n/* Ends C function definitions when using C++ */\n#ifdef __cplusplus\n}\n#endif\n#include \"close_code.h\"\n\n#endif /* _SDL_audio_h */\n"
  },
  {
    "path": "deps/include/SDL/SDL_byteorder.h",
    "content": "/*\n    SDL - Simple DirectMedia Layer\n    Copyright (C) 1997-2012 Sam Lantinga\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Lesser General Public\n    License as published by the Free Software Foundation; either\n    version 2.1 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public\n    License along with this library; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n\n    Sam Lantinga\n    slouken@libsdl.org\n*/\n\n/**\n *  @file SDL_byteorder.h\n *  @deprecated Use SDL_endian.h instead\n */\n\n/* DEPRECATED */\n#include \"SDL_endian.h\"\n"
  },
  {
    "path": "deps/include/SDL/SDL_cdrom.h",
    "content": "/*\n    SDL - Simple DirectMedia Layer\n    Copyright (C) 1997-2012 Sam Lantinga\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Lesser General Public\n    License as published by the Free Software Foundation; either\n    version 2.1 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public\n    License along with this library; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n\n    Sam Lantinga\n    slouken@libsdl.org\n*/\n\n/**\n *  @file SDL_cdrom.h\n *  This is the CD-audio control API for Simple DirectMedia Layer\n */\n\n#ifndef _SDL_cdrom_h\n#define _SDL_cdrom_h\n\n#include \"SDL_stdinc.h\"\n#include \"SDL_error.h\"\n\n#include \"begin_code.h\"\n/* Set up for C function definitions, even when using C++ */\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n *  @file SDL_cdrom.h\n *  In order to use these functions, SDL_Init() must have been called\n *  with the SDL_INIT_CDROM flag.  This causes SDL to scan the system\n *  for CD-ROM drives, and load appropriate drivers.\n */\n\n/** The maximum number of CD-ROM tracks on a disk */\n#define SDL_MAX_TRACKS\t99\n\n/** @name Track Types\n *  The types of CD-ROM track possible\n */\n/*@{*/\n#define SDL_AUDIO_TRACK\t0x00\n#define SDL_DATA_TRACK\t0x04\n/*@}*/\n\n/** The possible states which a CD-ROM drive can be in. */\ntypedef enum {\n\tCD_TRAYEMPTY,\n\tCD_STOPPED,\n\tCD_PLAYING,\n\tCD_PAUSED,\n\tCD_ERROR = -1\n} CDstatus;\n\n/** Given a status, returns true if there's a disk in the drive */\n#define CD_INDRIVE(status)\t((int)(status) > 0)\n\ntypedef struct SDL_CDtrack {\n\tUint8 id;\t\t/**< Track number */\n\tUint8 type;\t\t/**< Data or audio track */\n\tUint16 unused;\n\tUint32 length;\t\t/**< Length, in frames, of this track */\n\tUint32 offset;\t\t/**< Offset, in frames, from start of disk */\n} SDL_CDtrack;\n\n/** This structure is only current as of the last call to SDL_CDStatus() */\ntypedef struct SDL_CD {\n\tint id;\t\t\t/**< Private drive identifier */\n\tCDstatus status;\t/**< Current drive status */\n\n\t/** The rest of this structure is only valid if there's a CD in drive */\n        /*@{*/\n\tint numtracks;\t\t/**< Number of tracks on disk */\n\tint cur_track;\t\t/**< Current track position */\n\tint cur_frame;\t\t/**< Current frame offset within current track */\n\tSDL_CDtrack track[SDL_MAX_TRACKS+1];\n        /*@}*/\n} SDL_CD;\n\n/** @name Frames / MSF Conversion Functions\n *  Conversion functions from frames to Minute/Second/Frames and vice versa\n */\n/*@{*/\n#define CD_FPS\t75\n#define FRAMES_TO_MSF(f, M,S,F)\t{\t\t\t\t\t\\\n\tint value = f;\t\t\t\t\t\t\t\\\n\t*(F) = value%CD_FPS;\t\t\t\t\t\t\\\n\tvalue /= CD_FPS;\t\t\t\t\t\t\\\n\t*(S) = value%60;\t\t\t\t\t\t\\\n\tvalue /= 60;\t\t\t\t\t\t\t\\\n\t*(M) = value;\t\t\t\t\t\t\t\\\n}\n#define MSF_TO_FRAMES(M, S, F)\t((M)*60*CD_FPS+(S)*CD_FPS+(F))\n/*@}*/\n\n/* CD-audio API functions: */\n\n/**\n *  Returns the number of CD-ROM drives on the system, or -1 if\n *  SDL_Init() has not been called with the SDL_INIT_CDROM flag.\n */\nextern DECLSPEC int SDLCALL SDL_CDNumDrives(void);\n\n/**\n *  Returns a human-readable, system-dependent identifier for the CD-ROM.\n *  Example:\n *   - \"/dev/cdrom\"\n *   - \"E:\"\n *   - \"/dev/disk/ide/1/master\"\n */\nextern DECLSPEC const char * SDLCALL SDL_CDName(int drive);\n\n/**\n *  Opens a CD-ROM drive for access.  It returns a drive handle on success,\n *  or NULL if the drive was invalid or busy.  This newly opened CD-ROM\n *  becomes the default CD used when other CD functions are passed a NULL\n *  CD-ROM handle.\n *  Drives are numbered starting with 0.  Drive 0 is the system default CD-ROM.\n */\nextern DECLSPEC SDL_CD * SDLCALL SDL_CDOpen(int drive);\n\n/**\n *  This function returns the current status of the given drive.\n *  If the drive has a CD in it, the table of contents of the CD and current\n *  play position of the CD will be stored in the SDL_CD structure.\n */\nextern DECLSPEC CDstatus SDLCALL SDL_CDStatus(SDL_CD *cdrom);\n\n/**\n *  Play the given CD starting at 'start_track' and 'start_frame' for 'ntracks'\n *  tracks and 'nframes' frames.  If both 'ntrack' and 'nframe' are 0, play \n *  until the end of the CD.  This function will skip data tracks.\n *  This function should only be called after calling SDL_CDStatus() to \n *  get track information about the CD.\n *  For example:\n *      @code\n *\t// Play entire CD:\n *\tif ( CD_INDRIVE(SDL_CDStatus(cdrom)) )\n *\t\tSDL_CDPlayTracks(cdrom, 0, 0, 0, 0);\n *\t// Play last track:\n *\tif ( CD_INDRIVE(SDL_CDStatus(cdrom)) ) {\n *\t\tSDL_CDPlayTracks(cdrom, cdrom->numtracks-1, 0, 0, 0);\n *\t}\n *\t// Play first and second track and 10 seconds of third track:\n *\tif ( CD_INDRIVE(SDL_CDStatus(cdrom)) )\n *\t\tSDL_CDPlayTracks(cdrom, 0, 0, 2, 10);\n *      @endcode\n *\n *  @return This function returns 0, or -1 if there was an error.\n */\nextern DECLSPEC int SDLCALL SDL_CDPlayTracks(SDL_CD *cdrom,\n\t\tint start_track, int start_frame, int ntracks, int nframes);\n\n/**\n *  Play the given CD starting at 'start' frame for 'length' frames.\n *  @return It returns 0, or -1 if there was an error.\n */\nextern DECLSPEC int SDLCALL SDL_CDPlay(SDL_CD *cdrom, int start, int length);\n\n/** Pause play\n *  @return returns 0, or -1 on error\n */\nextern DECLSPEC int SDLCALL SDL_CDPause(SDL_CD *cdrom);\n\n/** Resume play\n *  @return returns 0, or -1 on error\n */\nextern DECLSPEC int SDLCALL SDL_CDResume(SDL_CD *cdrom);\n\n/** Stop play\n *  @return returns 0, or -1 on error\n */\nextern DECLSPEC int SDLCALL SDL_CDStop(SDL_CD *cdrom);\n\n/** Eject CD-ROM\n *  @return returns 0, or -1 on error\n */\nextern DECLSPEC int SDLCALL SDL_CDEject(SDL_CD *cdrom);\n\n/** Closes the handle for the CD-ROM drive */\nextern DECLSPEC void SDLCALL SDL_CDClose(SDL_CD *cdrom);\n\n\n/* Ends C function definitions when using C++ */\n#ifdef __cplusplus\n}\n#endif\n#include \"close_code.h\"\n\n#endif /* _SDL_video_h */\n"
  },
  {
    "path": "deps/include/SDL/SDL_config.h",
    "content": "/*\n    SDL - Simple DirectMedia Layer\n    Copyright (C) 1997-2012 Sam Lantinga\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Lesser General Public\n    License as published by the Free Software Foundation; either\n    version 2.1 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public\n    License along with this library; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n\n    Sam Lantinga\n    slouken@libsdl.org\n*/\n\n#ifndef _SDL_config_h\n#define _SDL_config_h\n\n#include \"SDL_platform.h\"\n\n/* Add any platform that doesn't build using the configure system */\n#if defined(__DREAMCAST__)\n#include \"SDL_config_dreamcast.h\"\n#elif defined(__MACOS__)\n#include \"SDL_config_macos.h\"\n#elif defined(__MACOSX__)\n#include \"SDL_config_macosx.h\"\n#elif defined(__SYMBIAN32__)\n#include \"SDL_config_symbian.h\"  /* must be before win32! */\n#elif defined(__WIN32__)\n#include \"SDL_config_win32.h\"\n#elif defined(__OS2__)\n#include \"SDL_config_os2.h\"\n#else\n#include \"SDL_config_minimal.h\"\n#endif /* platform config */\n\n#endif /* _SDL_config_h */\n"
  },
  {
    "path": "deps/include/SDL/SDL_config.h.in",
    "content": "/*\n    SDL - Simple DirectMedia Layer\n    Copyright (C) 1997-2012 Sam Lantinga\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Lesser General Public\n    License as published by the Free Software Foundation; either\n    version 2.1 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public\n    License along with this library; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n\n    Sam Lantinga\n    slouken@libsdl.org\n*/\n\n#ifndef _SDL_config_h\n#define _SDL_config_h\n\n/* This is a set of defines to configure the SDL features */\n\n/* General platform specific identifiers */\n#include \"SDL_platform.h\"\n\n/* Make sure that this isn't included by Visual C++ */\n#ifdef _MSC_VER\n#error You should copy include/SDL_config.h.default to include/SDL_config.h\n#endif\n\n/* C language features */\n#undef const\n#undef inline\n#undef volatile\n\n/* C datatypes */\n#undef size_t\n#undef int8_t\n#undef uint8_t\n#undef int16_t\n#undef uint16_t\n#undef int32_t\n#undef uint32_t\n#undef int64_t\n#undef uint64_t\n#undef uintptr_t\n#undef SDL_HAS_64BIT_TYPE\n\n/* Endianness */\n#undef SDL_BYTEORDER\n\n/* Comment this if you want to build without any C library requirements */\n#undef HAVE_LIBC\n#if HAVE_LIBC\n\n/* Useful headers */\n#undef HAVE_ALLOCA_H\n#undef HAVE_SYS_TYPES_H\n#undef HAVE_STDIO_H\n#undef STDC_HEADERS\n#undef HAVE_STDLIB_H\n#undef HAVE_STDARG_H\n#undef HAVE_MALLOC_H\n#undef HAVE_MEMORY_H\n#undef HAVE_STRING_H\n#undef HAVE_STRINGS_H\n#undef HAVE_INTTYPES_H\n#undef HAVE_STDINT_H\n#undef HAVE_CTYPE_H\n#undef HAVE_MATH_H\n#undef HAVE_ICONV_H\n#undef HAVE_SIGNAL_H\n#undef HAVE_ALTIVEC_H\n#undef HAVE_SYS_IO_H\n\n/* C library functions */\n#undef HAVE_MALLOC\n#undef HAVE_CALLOC\n#undef HAVE_REALLOC\n#undef HAVE_FREE\n#undef HAVE_ALLOCA\n#ifndef _WIN32 /* Don't use C runtime versions of these on Windows */\n#undef HAVE_GETENV\n#undef HAVE_PUTENV\n#undef HAVE_UNSETENV\n#endif\n#undef HAVE_QSORT\n#undef HAVE_ABS\n#undef HAVE_BCOPY\n#undef HAVE_MEMSET\n#undef HAVE_MEMCPY\n#undef HAVE_MEMMOVE\n#undef HAVE_MEMCMP\n#undef HAVE_STRLEN\n#undef HAVE_STRLCPY\n#undef HAVE_STRLCAT\n#undef HAVE_STRDUP\n#undef HAVE__STRREV\n#undef HAVE__STRUPR\n#undef HAVE__STRLWR\n#undef HAVE_INDEX\n#undef HAVE_RINDEX\n#undef HAVE_STRCHR\n#undef HAVE_STRRCHR\n#undef HAVE_STRSTR\n#undef HAVE_ITOA\n#undef HAVE__LTOA\n#undef HAVE__UITOA\n#undef HAVE__ULTOA\n#undef HAVE_STRTOL\n#undef HAVE_STRTOUL\n#undef HAVE__I64TOA\n#undef HAVE__UI64TOA\n#undef HAVE_STRTOLL\n#undef HAVE_STRTOULL\n#undef HAVE__STRTOI64\n#undef HAVE__STRTOUI64\n#undef HAVE_STRTOD\n#undef HAVE_ATOI\n#undef HAVE_ATOF\n#undef HAVE_STRCMP\n#undef HAVE_STRNCMP\n#undef HAVE__STRICMP\n#undef HAVE_STRCASECMP\n#undef HAVE__STRNICMP\n#undef HAVE_STRNCASECMP\n#undef HAVE_SSCANF\n#undef HAVE_SNPRINTF\n#undef HAVE_VSNPRINTF\n#undef HAVE_ICONV\n#undef HAVE_SIGACTION\n#undef HAVE_SA_SIGACTION\n#undef HAVE_SETJMP\n#undef HAVE_NANOSLEEP\n#undef HAVE_CLOCK_GETTIME\n#undef HAVE_GETPAGESIZE\n#undef HAVE_MPROTECT\n#undef HAVE_SEM_TIMEDWAIT\n#undef HAVE_GETAUXVAL\n#undef HAVE_ELF_AUX_INFO\n\n#else\n/* We may need some replacement for stdarg.h here */\n#include <stdarg.h>\n#endif /* HAVE_LIBC */\n\n/* Allow disabling of core subsystems */\n#undef SDL_AUDIO_DISABLED\n#undef SDL_CDROM_DISABLED\n#undef SDL_CPUINFO_DISABLED\n#undef SDL_EVENTS_DISABLED\n#undef SDL_FILE_DISABLED\n#undef SDL_JOYSTICK_DISABLED\n#undef SDL_LOADSO_DISABLED\n#undef SDL_THREADS_DISABLED\n#undef SDL_TIMERS_DISABLED\n#undef SDL_VIDEO_DISABLED\n\n/* Enable various audio drivers */\n#undef SDL_AUDIO_DRIVER_ALSA\n#undef SDL_AUDIO_DRIVER_ALSA_DYNAMIC\n#undef SDL_AUDIO_DRIVER_ARTS\n#undef SDL_AUDIO_DRIVER_ARTS_DYNAMIC\n#undef SDL_AUDIO_DRIVER_BAUDIO\n#undef SDL_AUDIO_DRIVER_BSD\n#undef SDL_AUDIO_DRIVER_COREAUDIO\n#undef SDL_AUDIO_DRIVER_DART\n#undef SDL_AUDIO_DRIVER_DC\n#undef SDL_AUDIO_DRIVER_DISK\n#undef SDL_AUDIO_DRIVER_DUMMY\n#undef SDL_AUDIO_DRIVER_DMEDIA\n#undef SDL_AUDIO_DRIVER_DSOUND\n#undef SDL_AUDIO_DRIVER_PULSE\n#undef SDL_AUDIO_DRIVER_PULSE_DYNAMIC\n#undef SDL_AUDIO_DRIVER_ESD\n#undef SDL_AUDIO_DRIVER_ESD_DYNAMIC\n#undef SDL_AUDIO_DRIVER_MINT\n#undef SDL_AUDIO_DRIVER_MMEAUDIO\n#undef SDL_AUDIO_DRIVER_NAS\n#undef SDL_AUDIO_DRIVER_NAS_DYNAMIC\n#undef SDL_AUDIO_DRIVER_OSS\n#undef SDL_AUDIO_DRIVER_OSS_SOUNDCARD_H\n#undef SDL_AUDIO_DRIVER_PAUD\n#undef SDL_AUDIO_DRIVER_QNXNTO\n#undef SDL_AUDIO_DRIVER_SNDIO\n#undef SDL_AUDIO_DRIVER_SNDMGR\n#undef SDL_AUDIO_DRIVER_SUNAUDIO\n#undef SDL_AUDIO_DRIVER_WAVEOUT\n\n/* Enable various cdrom drivers */\n#undef SDL_CDROM_AIX\n#undef SDL_CDROM_BEOS\n#undef SDL_CDROM_BSDI\n#undef SDL_CDROM_DC\n#undef SDL_CDROM_DUMMY\n#undef SDL_CDROM_FREEBSD\n#undef SDL_CDROM_LINUX\n#undef SDL_CDROM_MACOS\n#undef SDL_CDROM_MACOSX\n#undef SDL_CDROM_MINT\n#undef SDL_CDROM_OPENBSD\n#undef SDL_CDROM_OS2\n#undef SDL_CDROM_OSF\n#undef SDL_CDROM_QNX\n#undef SDL_CDROM_WIN32\n\n/* Enable various input drivers */\n#undef SDL_INPUT_LINUXEV\n#undef SDL_INPUT_TSLIB\n#undef SDL_JOYSTICK_BEOS\n#undef SDL_JOYSTICK_DC\n#undef SDL_JOYSTICK_DUMMY\n#undef SDL_JOYSTICK_IOKIT\n#undef SDL_JOYSTICK_LINUX\n#undef SDL_JOYSTICK_MACOS\n#undef SDL_JOYSTICK_MINT\n#undef SDL_JOYSTICK_OS2\n#undef SDL_JOYSTICK_RISCOS\n#undef SDL_JOYSTICK_WINMM\n#undef SDL_JOYSTICK_USBHID\n#undef SDL_HAVE_MACHINE_JOYSTICK_H\n\n/* Enable various shared object loading systems */\n#undef SDL_LOADSO_BEOS\n#undef SDL_LOADSO_DLCOMPAT\n#undef SDL_LOADSO_DLOPEN\n#undef SDL_LOADSO_DUMMY\n#undef SDL_LOADSO_LDG\n#undef SDL_LOADSO_MACOS\n#undef SDL_LOADSO_OS2\n#undef SDL_LOADSO_WIN32\n\n/* Enable various threading systems */\n#undef SDL_THREAD_BEOS\n#undef SDL_THREAD_DC\n#undef SDL_THREAD_OS2\n#undef SDL_THREAD_PTH\n#undef SDL_THREAD_PTHREAD\n#undef SDL_THREAD_PTHREAD_RECURSIVE_MUTEX\n#undef SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP\n#undef SDL_THREAD_SPROC\n#undef SDL_THREAD_WIN32\n\n/* Enable various timer systems */\n#undef SDL_TIMER_BEOS\n#undef SDL_TIMER_DC\n#undef SDL_TIMER_DUMMY\n#undef SDL_TIMER_MACOS\n#undef SDL_TIMER_MINT\n#undef SDL_TIMER_OS2\n#undef SDL_TIMER_RISCOS\n#undef SDL_TIMER_UNIX\n#undef SDL_TIMER_WIN32\n#undef SDL_TIMER_WINCE\n\n/* Enable various video drivers */\n#undef SDL_VIDEO_DRIVER_AALIB\n#undef SDL_VIDEO_DRIVER_BWINDOW\n#undef SDL_VIDEO_DRIVER_CACA\n#undef SDL_VIDEO_DRIVER_DC\n#undef SDL_VIDEO_DRIVER_DDRAW\n#undef SDL_VIDEO_DRIVER_DGA\n#undef SDL_VIDEO_DRIVER_DIRECTFB\n#undef SDL_VIDEO_DRIVER_DRAWSPROCKET\n#undef SDL_VIDEO_DRIVER_DUMMY\n#undef SDL_VIDEO_DRIVER_FBCON\n#undef SDL_VIDEO_DRIVER_GAPI\n#undef SDL_VIDEO_DRIVER_GEM\n#undef SDL_VIDEO_DRIVER_GGI\n#undef SDL_VIDEO_DRIVER_IPOD\n#undef SDL_VIDEO_DRIVER_NANOX\n#undef SDL_VIDEO_DRIVER_OS2GROP\n#undef SDL_VIDEO_DRIVER_OS2FS\n#undef SDL_VIDEO_DRIVER_PHOTON\n#undef SDL_VIDEO_DRIVER_PICOGUI\n#undef SDL_VIDEO_DRIVER_PS2GS\n#undef SDL_VIDEO_DRIVER_PS3\n#undef SDL_VIDEO_DRIVER_QTOPIA\n#undef SDL_VIDEO_DRIVER_QUARTZ\n#undef SDL_VIDEO_DRIVER_RISCOS\n#undef SDL_VIDEO_DRIVER_SVGALIB\n#undef SDL_VIDEO_DRIVER_TOOLBOX\n#undef SDL_VIDEO_DRIVER_VGL\n#undef SDL_VIDEO_DRIVER_WINDIB\n#undef SDL_VIDEO_DRIVER_WSCONS\n#undef SDL_VIDEO_DRIVER_X11\n#undef SDL_VIDEO_DRIVER_X11_CONST_PARAM_XDATA32\n#undef SDL_VIDEO_DRIVER_X11_DGAMOUSE\n#undef SDL_VIDEO_DRIVER_X11_DYNAMIC\n#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT\n#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR\n#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XRENDER\n#undef SDL_VIDEO_DRIVER_X11_VIDMODE\n#undef SDL_VIDEO_DRIVER_X11_XINERAMA\n#undef SDL_VIDEO_DRIVER_X11_XME\n#undef SDL_VIDEO_DRIVER_X11_XRANDR\n#undef SDL_VIDEO_DRIVER_X11_XV\n#undef SDL_VIDEO_DRIVER_XBIOS\n\n/* Enable OpenGL support */\n#undef SDL_VIDEO_OPENGL\n#undef SDL_VIDEO_OPENGL_GLX\n#undef SDL_VIDEO_OPENGL_WGL\n#undef SDL_VIDEO_OPENGL_OSMESA\n#undef SDL_VIDEO_OPENGL_OSMESA_DYNAMIC\n\n/* Disable screensaver */\n#undef SDL_VIDEO_DISABLE_SCREENSAVER\n\n/* Enable assembly routines */\n#undef SDL_ASSEMBLY_ROUTINES\n#undef SDL_HERMES_BLITTERS\n#undef SDL_ALTIVEC_BLITTERS\n#undef SDL_ARM_SIMD_BLITTERS\n#undef SDL_ARM_NEON_BLITTERS\n\n#endif /* _SDL_config_h */\n"
  },
  {
    "path": "deps/include/SDL/SDL_config_dreamcast.h",
    "content": "/*\n    SDL - Simple DirectMedia Layer\n    Copyright (C) 1997-2012 Sam Lantinga\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Lesser General Public\n    License as published by the Free Software Foundation; either\n    version 2.1 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public\n    License along with this library; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n\n    Sam Lantinga\n    slouken@libsdl.org\n*/\n\n#ifndef _SDL_config_dreamcast_h\n#define _SDL_config_dreamcast_h\n\n#include \"SDL_platform.h\"\n\n/* This is a set of defines to configure the SDL features */\n\ntypedef signed char int8_t;\ntypedef unsigned char uint8_t;\ntypedef signed short int16_t;\ntypedef unsigned short uint16_t;\ntypedef signed int int32_t;\ntypedef unsigned int uint32_t;\ntypedef signed long long int64_t;\ntypedef unsigned long long uint64_t;\ntypedef unsigned long uintptr_t;\n#define SDL_HAS_64BIT_TYPE\t1\n\n/* Useful headers */\n#define HAVE_SYS_TYPES_H\t1\n#define HAVE_STDIO_H\t1\n#define STDC_HEADERS\t1\n#define HAVE_STRING_H\t1\n#define HAVE_CTYPE_H\t1\n\n/* C library functions */\n#define HAVE_MALLOC\t1\n#define HAVE_CALLOC\t1\n#define HAVE_REALLOC\t1\n#define HAVE_FREE\t1\n#define HAVE_ALLOCA\t1\n#define HAVE_GETENV\t1\n#define HAVE_PUTENV\t1\n#define HAVE_QSORT\t1\n#define HAVE_ABS\t1\n#define HAVE_BCOPY\t1\n#define HAVE_MEMSET\t1\n#define HAVE_MEMCPY\t1\n#define HAVE_MEMMOVE\t1\n#define HAVE_MEMCMP\t1\n#define HAVE_STRLEN\t1\n#define HAVE_STRDUP\t1\n#define HAVE_INDEX\t1\n#define HAVE_RINDEX\t1\n#define HAVE_STRCHR\t1\n#define HAVE_STRRCHR\t1\n#define HAVE_STRSTR\t1\n#define HAVE_STRTOL\t1\n#define HAVE_STRTOD\t1\n#define HAVE_ATOI\t1\n#define HAVE_ATOF\t1\n#define HAVE_STRCMP\t1\n#define HAVE_STRNCMP\t1\n#define HAVE_STRICMP\t1\n#define HAVE_STRCASECMP\t1\n#define HAVE_SSCANF\t1\n#define HAVE_SNPRINTF\t1\n#define HAVE_VSNPRINTF\t1\n\n/* Enable various audio drivers */\n#define SDL_AUDIO_DRIVER_DC\t1\n#define SDL_AUDIO_DRIVER_DISK\t1\n#define SDL_AUDIO_DRIVER_DUMMY\t1\n\n/* Enable various cdrom drivers */\n#define SDL_CDROM_DC\t1\n\n/* Enable various input drivers */\n#define SDL_JOYSTICK_DC\t1\n\n/* Enable various shared object loading systems */\n#define SDL_LOADSO_DUMMY\t1\n\n/* Enable various threading systems */\n#define SDL_THREAD_DC\t1\n\n/* Enable various timer systems */\n#define SDL_TIMER_DC\t1\n\n/* Enable various video drivers */\n#define SDL_VIDEO_DRIVER_DC\t1\n#define SDL_VIDEO_DRIVER_DUMMY\t1\n\n#endif /* _SDL_config_dreamcast_h */\n"
  },
  {
    "path": "deps/include/SDL/SDL_config_macos.h",
    "content": "/*\n    SDL - Simple DirectMedia Layer\n    Copyright (C) 1997-2012 Sam Lantinga\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Lesser General Public\n    License as published by the Free Software Foundation; either\n    version 2.1 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public\n    License along with this library; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n\n    Sam Lantinga\n    slouken@libsdl.org\n*/\n\n#ifndef _SDL_config_macos_h\n#define _SDL_config_macos_h\n\n#include \"SDL_platform.h\"\n\n/* This is a set of defines to configure the SDL features */\n\n#include <MacTypes.h>\n\ntypedef SInt8\tint8_t;\ntypedef UInt8\tuint8_t;\ntypedef SInt16\tint16_t;\ntypedef UInt16\tuint16_t;\ntypedef SInt32\tint32_t;\ntypedef UInt32\tuint32_t;\ntypedef SInt64\tint64_t;\ntypedef UInt64\tuint64_t;\ntypedef unsigned long\tuintptr_t;\n\n#define SDL_HAS_64BIT_TYPE\t1\n\n/* Useful headers */\n#define HAVE_STDIO_H\t1\n#define STDC_HEADERS\t1\n#define HAVE_STRING_H\t1\n#define HAVE_CTYPE_H\t1\n#define HAVE_MATH_H\t1\n#define HAVE_SIGNAL_H\t1\n\n/* C library functions */\n#define HAVE_MALLOC\t1\n#define HAVE_CALLOC\t1\n#define HAVE_REALLOC\t1\n#define HAVE_FREE\t1\n#define HAVE_ALLOCA\t1\n#define HAVE_ABS\t1\n#define HAVE_MEMSET\t1\n#define HAVE_MEMCPY\t1\n#define HAVE_MEMMOVE\t1\n#define HAVE_MEMCMP\t1\n#define HAVE_STRLEN\t1\n#define HAVE_STRCHR\t1\n#define HAVE_STRRCHR\t1\n#define HAVE_STRSTR\t1\n#define HAVE_ITOA\t1\n#define HAVE_STRTOL\t1\n#define HAVE_STRTOD\t1\n#define HAVE_ATOI\t1\n#define HAVE_ATOF\t1\n#define HAVE_STRCMP\t1\n#define HAVE_STRNCMP\t1\n#define HAVE_SSCANF\t1\n\n/* Enable various audio drivers */\n#define SDL_AUDIO_DRIVER_SNDMGR\t1\n#define SDL_AUDIO_DRIVER_DISK\t1\n#define SDL_AUDIO_DRIVER_DUMMY\t1\n\n/* Enable various cdrom drivers */\n#if TARGET_API_MAC_CARBON\n#define SDL_CDROM_DUMMY\t\t1\n#else\n#define SDL_CDROM_MACOS\t\t1\n#endif\n\n/* Enable various input drivers */\n#if TARGET_API_MAC_CARBON\n#define SDL_JOYSTICK_DUMMY\t1\n#else\n#define SDL_JOYSTICK_MACOS\t1\n#endif\n\n/* Enable various shared object loading systems */\n#define SDL_LOADSO_MACOS\t1\n\n/* Enable various threading systems */\n#define SDL_THREADS_DISABLED\t1\n\n/* Enable various timer systems */\n#define SDL_TIMER_MACOS\t1\n\n/* Enable various video drivers */\n#define SDL_VIDEO_DRIVER_DUMMY\t1\n#define SDL_VIDEO_DRIVER_DRAWSPROCKET\t1\n#define SDL_VIDEO_DRIVER_TOOLBOX\t1\n\n/* Enable OpenGL support */\n#define SDL_VIDEO_OPENGL\t1\n\n#endif /* _SDL_config_macos_h */\n"
  },
  {
    "path": "deps/include/SDL/SDL_config_macosx.h",
    "content": "/*\n    SDL - Simple DirectMedia Layer\n    Copyright (C) 1997-2012 Sam Lantinga\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Lesser General Public\n    License as published by the Free Software Foundation; either\n    version 2.1 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public\n    License along with this library; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n\n    Sam Lantinga\n    slouken@libsdl.org\n*/\n\n#ifndef _SDL_config_macosx_h\n#define _SDL_config_macosx_h\n\n#include \"SDL_platform.h\"\n\n/* This gets us MAC_OS_X_VERSION_MIN_REQUIRED... */\n#include <AvailabilityMacros.h>\n\n/* This is a set of defines to configure the SDL features */\n\n#define SDL_HAS_64BIT_TYPE\t1\n\n/* Useful headers */\n/* If we specified an SDK or have a post-PowerPC chip, then alloca.h exists. */\n#if ( (MAC_OS_X_VERSION_MIN_REQUIRED >= 1030) || (!defined(__POWERPC__)) )\n#define HAVE_ALLOCA_H\t\t1\n#endif\n#define HAVE_SYS_TYPES_H\t1\n#define HAVE_STDIO_H\t1\n#define STDC_HEADERS\t1\n#define HAVE_STRING_H\t1\n#define HAVE_INTTYPES_H\t1\n#define HAVE_STDINT_H\t1\n#define HAVE_CTYPE_H\t1\n#define HAVE_MATH_H\t1\n#define HAVE_SIGNAL_H\t1\n\n/* C library functions */\n#define HAVE_MALLOC\t1\n#define HAVE_CALLOC\t1\n#define HAVE_REALLOC\t1\n#define HAVE_FREE\t1\n#define HAVE_ALLOCA\t1\n#define HAVE_GETENV\t1\n#define HAVE_PUTENV\t1\n#define HAVE_UNSETENV\t1\n#define HAVE_QSORT\t1\n#define HAVE_ABS\t1\n#define HAVE_BCOPY\t1\n#define HAVE_MEMSET\t1\n#define HAVE_MEMCPY\t1\n#define HAVE_MEMMOVE\t1\n#define HAVE_MEMCMP\t1\n#define HAVE_STRLEN\t1\n#define HAVE_STRLCPY\t1\n#define HAVE_STRLCAT\t1\n#define HAVE_STRDUP\t1\n#define HAVE_STRCHR\t1\n#define HAVE_STRRCHR\t1\n#define HAVE_STRSTR\t1\n#define HAVE_STRTOL\t1\n#define HAVE_STRTOUL\t1\n#define HAVE_STRTOLL\t1\n#define HAVE_STRTOULL\t1\n#define HAVE_STRTOD\t1\n#define HAVE_ATOI\t1\n#define HAVE_ATOF\t1\n#define HAVE_STRCMP\t1\n#define HAVE_STRNCMP\t1\n#define HAVE_STRCASECMP\t1\n#define HAVE_STRNCASECMP 1\n#define HAVE_SSCANF\t1\n#define HAVE_SNPRINTF\t1\n#define HAVE_VSNPRINTF\t1\n#define HAVE_SIGACTION\t1\n#define HAVE_SETJMP\t1\n#define HAVE_NANOSLEEP\t1\n\n/* Enable various audio drivers */\n#define SDL_AUDIO_DRIVER_COREAUDIO\t1\n#define SDL_AUDIO_DRIVER_DISK\t1\n#define SDL_AUDIO_DRIVER_DUMMY\t1\n\n/* Enable various cdrom drivers */\n#define SDL_CDROM_MACOSX\t1\n\n/* Enable various input drivers */\n#define SDL_JOYSTICK_IOKIT\t1\n\n/* Enable various shared object loading systems */\n#ifdef __ppc__\n/* For Mac OS X 10.2 compatibility */\n#define SDL_LOADSO_DLCOMPAT\t1\n#else\n#define SDL_LOADSO_DLOPEN\t1\n#endif\n\n/* Enable various threading systems */\n#define SDL_THREAD_PTHREAD\t1\n#define SDL_THREAD_PTHREAD_RECURSIVE_MUTEX\t1\n\n/* Enable various timer systems */\n#define SDL_TIMER_UNIX\t1\n\n/* Enable various video drivers */\n#define SDL_VIDEO_DRIVER_DUMMY\t1\n#if ((defined TARGET_API_MAC_CARBON) && (TARGET_API_MAC_CARBON))\n#define SDL_VIDEO_DRIVER_TOOLBOX\t1\n#else\n#define SDL_VIDEO_DRIVER_QUARTZ\t1\n#endif\n#define SDL_VIDEO_DRIVER_DGA 1\n#define SDL_VIDEO_DRIVER_X11 1\n#define SDL_VIDEO_DRIVER_X11_DGAMOUSE 1\n#define SDL_VIDEO_DRIVER_X11_DYNAMIC \"/usr/X11R6/lib/libX11.6.dylib\"\n#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT \"/usr/X11R6/lib/libXext.6.dylib\"\n#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR \"/usr/X11R6/lib/libXrandr.2.dylib\"\n#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XRENDER \"/usr/X11R6/lib/libXrender.1.dylib\"\n#define SDL_VIDEO_DRIVER_X11_VIDMODE 1\n#define SDL_VIDEO_DRIVER_X11_XINERAMA 1\n#define SDL_VIDEO_DRIVER_X11_XME 1\n#define SDL_VIDEO_DRIVER_X11_XRANDR 1\n#define SDL_VIDEO_DRIVER_X11_XV 1\n#define SDL_VIDEO_DRIVER_X11_CONST_PARAM_XDATA32 1\n\n/* Enable OpenGL support */\n#define SDL_VIDEO_OPENGL\t1\n#define SDL_VIDEO_OPENGL_GLX 1\n\n/* Disable screensaver */\n#define SDL_VIDEO_DISABLE_SCREENSAVER\t1\n\n/* Enable assembly routines */\n#define SDL_ASSEMBLY_ROUTINES\t1\n#ifdef __ppc__\n#define SDL_ALTIVEC_BLITTERS\t1\n#endif\n\n#endif /* _SDL_config_macosx_h */\n"
  },
  {
    "path": "deps/include/SDL/SDL_config_minimal.h",
    "content": "/*\n    SDL - Simple DirectMedia Layer\n    Copyright (C) 1997-2012 Sam Lantinga\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Lesser General Public\n    License as published by the Free Software Foundation; either\n    version 2.1 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public\n    License along with this library; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n\n    Sam Lantinga\n    slouken@libsdl.org\n*/\n\n#ifndef _SDL_config_minimal_h\n#define _SDL_config_minimal_h\n\n#include \"SDL_platform.h\"\n\n/* This is the minimal configuration that can be used to build SDL */\n\n#include <stdarg.h>\n\ntypedef signed char int8_t;\ntypedef unsigned char uint8_t;\ntypedef signed short int16_t;\ntypedef unsigned short uint16_t;\ntypedef signed int int32_t;\ntypedef unsigned int uint32_t;\ntypedef unsigned int size_t;\ntypedef unsigned long uintptr_t;\n\n/* Enable the dummy audio driver (src/audio/dummy/\\*.c) */\n#define SDL_AUDIO_DRIVER_DUMMY\t1\n\n/* Enable the stub cdrom driver (src/cdrom/dummy/\\*.c) */\n#define SDL_CDROM_DISABLED\t1\n\n/* Enable the stub joystick driver (src/joystick/dummy/\\*.c) */\n#define SDL_JOYSTICK_DISABLED\t1\n\n/* Enable the stub shared object loader (src/loadso/dummy/\\*.c) */\n#define SDL_LOADSO_DISABLED\t1\n\n/* Enable the stub thread support (src/thread/generic/\\*.c) */\n#define SDL_THREADS_DISABLED\t1\n\n/* Enable the stub timer support (src/timer/dummy/\\*.c) */\n#define SDL_TIMERS_DISABLED\t1\n\n/* Enable the dummy video driver (src/video/dummy/\\*.c) */\n#define SDL_VIDEO_DRIVER_DUMMY\t1\n\n#endif /* _SDL_config_minimal_h */\n"
  },
  {
    "path": "deps/include/SDL/SDL_config_nds.h",
    "content": "/*\n    SDL - Simple DirectMedia Layer\n    Copyright (C) 1997-2012 Sam Lantinga\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Lesser General Public\n    License as published by the Free Software Foundation; either\n    version 2.1 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public\n    License along with this library; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n\n    Sam Lantinga\n    slouken@libsdl.org\n*/\n\n#ifndef _SDL_config_nds_h\n#define _SDL_config_nds_h\n\n#include \"SDL_platform.h\"\n\n/* This is a set of defines to configure the SDL features */\n\n/* General platform specific identifiers */\n#include \"SDL_platform.h\"\n\n/* C datatypes */\n#define SDL_HAS_64BIT_TYPE 1\n\n/* Endianness */\n#define SDL_BYTEORDER 1234\n\n/* Useful headers */\n#define HAVE_ALLOCA_H 1\n#define HAVE_SYS_TYPES_H 1\n#define HAVE_STDIO_H 1\n#define STDC_HEADERS 1\n#define HAVE_STDLIB_H 1\n#define HAVE_STDARG_H 1\n#define HAVE_MALLOC_H 1\n#define HAVE_STRING_H 1\n#define HAVE_INTTYPES_H 1\n#define HAVE_STDINT_H 1\n#define HAVE_CTYPE_H 1\n#define HAVE_MATH_H 1\n#define HAVE_ICONV_H 1\n#define HAVE_SIGNAL_H 1\n\n/* C library functions */\n#define HAVE_MALLOC 1\n#define HAVE_CALLOC 1\n#define HAVE_REALLOC 1\n#define HAVE_FREE 1\n#define HAVE_ALLOCA 1\n#define HAVE_GETENV 1\n#define HAVE_PUTENV 1\n#define HAVE_UNSETENV 1\n#define HAVE_QSORT 1\n#define HAVE_ABS 1\n#define HAVE_BCOPY 1\n#define HAVE_MEMSET 1\n#define HAVE_MEMCPY 1\n#define HAVE_MEMMOVE 1\n#define HAVE_STRLEN 1\n#define HAVE_STRLCPY 1\n#define HAVE_STRLCAT 1\n#define HAVE_STRDUP 1\n#define HAVE_STRCHR 1\n#define HAVE_STRRCHR 1\n#define HAVE_STRSTR 1\n#define HAVE_STRTOL 1\n#define HAVE_STRTOUL 1\n#define HAVE_STRTOLL 1\n#define HAVE_STRTOULL 1\n#define HAVE_ATOI 1\n#define HAVE_ATOF 1\n#define HAVE_STRCMP 1\n#define HAVE_STRNCMP 1\n#define HAVE_STRCASECMP 1\n#define HAVE_STRNCASECMP 1\n#define HAVE_SSCANF 1\n#define HAVE_SNPRINTF 1\n#define HAVE_VSNPRINTF 1\n#define HAVE_SETJMP 1\n\n/* Enable various audio drivers */\n#define SDL_AUDIO_DRIVER_NDS\t1\n#define SDL_AUDIO_DRIVER_DUMMY\t1\n\n/* Enable the stub cdrom driver (src/cdrom/dummy/\\*.c) */\n#define SDL_CDROM_DISABLED\t1\n\n/* Enable various input drivers */\n#define SDL_JOYSTICK_NDS\t1\n\n/* Enable the stub shared object loader (src/loadso/dummy/\\*.c) */\n#define SDL_LOADSO_DISABLED\t1\n\n/* Enable the stub thread support (src/thread/generic/\\*.c) */\n#define SDL_THREADS_DISABLED\t1\n\n/* Enable various timer systems */\n#define SDL_TIMER_NDS\t1\n\n/* Enable various video drivers */\n#define SDL_VIDEO_DRIVER_NDS\t1\n#define SDL_VIDEO_DRIVER_DUMMY\t1\n\n#endif /* _SDL_config_nds_h */\n"
  },
  {
    "path": "deps/include/SDL/SDL_config_os2.h",
    "content": "/*\n    SDL - Simple DirectMedia Layer\n    Copyright (C) 1997-2012 Sam Lantinga\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Lesser General Public\n    License as published by the Free Software Foundation; either\n    version 2.1 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public\n    License along with this library; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n\n    Sam Lantinga\n    slouken@libsdl.org\n*/\n\n#ifndef _SDL_config_os2_h\n#define _SDL_config_os2_h\n\n#include \"SDL_platform.h\"\n\n/* This is a set of defines to configure the SDL features */\n\n#define SDL_HAS_64BIT_TYPE\t1\n\n/* Use Watcom's LIBC */\n#define HAVE_LIBC 1\n\n/* Useful headers */\n#define HAVE_SYS_TYPES_H 1\n#define HAVE_STDIO_H 1\n#define STDC_HEADERS 1\n#define HAVE_STDLIB_H 1\n#define HAVE_STDARG_H 1\n#define HAVE_MALLOC_H 1\n#define HAVE_MEMORY_H 1\n#define HAVE_STRING_H 1\n#define HAVE_STRINGS_H 1\n#define HAVE_INTTYPES_H 1\n#define HAVE_STDINT_H 1\n#define HAVE_CTYPE_H 1\n#define HAVE_MATH_H 1\n#define HAVE_SIGNAL_H 1\n\n/* C library functions */\n#define HAVE_MALLOC 1\n#define HAVE_CALLOC 1\n#define HAVE_REALLOC 1\n#define HAVE_FREE 1\n#define HAVE_ALLOCA 1\n#define HAVE_GETENV 1\n#define HAVE_PUTENV 1\n#define HAVE_QSORT 1\n#define HAVE_ABS 1\n#define HAVE_BCOPY 1\n#define HAVE_MEMSET 1\n#define HAVE_MEMCPY 1\n#define HAVE_MEMMOVE 1\n#define HAVE_MEMCMP 1\n#define HAVE_STRLEN 1\n#define HAVE_STRLCPY 1\n#define HAVE_STRLCAT 1\n#define HAVE_STRDUP 1\n#define HAVE__STRREV 1\n#define HAVE__STRUPR 1\n#define HAVE__STRLWR 1\n/* #undef HAVE_INDEX */\n/* #undef HAVE_RINDEX */\n#define HAVE_STRCHR 1\n#define HAVE_STRRCHR 1\n#define HAVE_STRSTR 1\n#define HAVE_ITOA 1\n#define HAVE__LTOA 1\n#define HAVE__ULTOA 1\n#define HAVE_STRTOL 1\n#define HAVE_STRTOUL 1\n#define HAVE__I64TOA 1\n#define HAVE__UI64TOA 1\n#define HAVE_STRTOLL 1\n#define HAVE_STRTOULL 1\n#define HAVE_STRTOD 1\n#define HAVE_ATOI 1\n#define HAVE_ATOF 1\n#define HAVE_STRCMP 1\n#define HAVE_STRNCMP 1\n#define HAVE_STRICMP 1\n#define HAVE_STRCASECMP 1\n#define HAVE_STRNCASECMP 1\n#define HAVE_SSCANF 1\n#define HAVE_SNPRINTF 1\n#define HAVE_VSNPRINTF 1\n#define HAVE_SETJMP 1\n\n/* Enable various audio drivers */\n#define SDL_AUDIO_DRIVER_DART\t1\n#define SDL_AUDIO_DRIVER_DISK\t1\n#define SDL_AUDIO_DRIVER_DUMMY\t1\n\n/* Enable various cdrom drivers */\n#define SDL_CDROM_OS2\t1\n\n/* Enable various input drivers */\n#define SDL_JOYSTICK_OS2\t1\n\n/* Enable various shared object loading systems */\n#define SDL_LOADSO_OS2\t1\n\n/* Enable various threading systems */\n#define SDL_THREAD_OS2\t1\n\n/* Enable various timer systems */\n#define SDL_TIMER_OS2\t1\n\n/* Enable various video drivers */\n#define SDL_VIDEO_DRIVER_DUMMY\t1\n#define SDL_VIDEO_DRIVER_OS2GROP\t1\n/* #undef SDL_VIDEO_DRIVER_OS2FS */\n\n/* Enable OpenGL support */\n/* #undef SDL_VIDEO_OPENGL */\n\n/* Enable assembly routines where available */\n#define SDL_ASSEMBLY_ROUTINES\t1\n\n#endif /* _SDL_config_os2_h */\n"
  },
  {
    "path": "deps/include/SDL/SDL_config_symbian.h",
    "content": "/*\n    SDL - Simple DirectMedia Layer\n    Copyright (C) 1997-2012 Sam Lantinga\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Lesser General Public\n    License as published by the Free Software Foundation; either\n    version 2.1 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public\n    License along with this library; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n\n    Sam Lantinga\n    slouken@libsdl.org\n*/\n\n/*\n\nSymbian version Markus Mertama\n\n*/\n\n\n#ifndef _SDL_CONFIG_SYMBIAN_H\n#define _SDL_CONFIG_SYMBIAN_H\n\n#include \"SDL_platform.h\"\n\n/* This is the minimal configuration that can be used to build SDL */\n\n\n#include <stdarg.h>\n#include <stddef.h>\n\n\n#ifdef __GCCE__\n#define SYMBIAN32_GCCE\n#endif\n\n#ifndef _SIZE_T_DEFINED\ntypedef unsigned int size_t;\n#endif\n\n#ifndef _INTPTR_T_DECLARED\ntypedef unsigned int uintptr_t;\n#endif \n\n#ifndef _INT8_T_DECLARED\ntypedef signed char int8_t;\n#endif \n\n#ifndef _UINT8_T_DECLARED\ntypedef unsigned char uint8_t;\n#endif\n\n#ifndef _INT16_T_DECLARED\ntypedef signed short int16_t;\n#endif\n\n#ifndef _UINT16_T_DECLARED\ntypedef unsigned short uint16_t;\n#endif\n\n#ifndef _INT32_T_DECLARED\ntypedef signed int int32_t;\n#endif\n\n#ifndef _UINT32_T_DECLARED\ntypedef unsigned int uint32_t;\n#endif\n\n#ifndef _INT64_T_DECLARED\ntypedef signed long long int64_t;\n#endif\n\n#ifndef _UINT64_T_DECLARED\ntypedef unsigned long long uint64_t;\n#endif\n\n#define SDL_AUDIO_DRIVER_EPOCAUDIO\t1\n\n\n/* Enable the stub cdrom driver (src/cdrom/dummy/\\*.c) */\n#define SDL_CDROM_DISABLED\t1\n\n/* Enable the stub joystick driver (src/joystick/dummy/\\*.c) */\n#define SDL_JOYSTICK_DISABLED\t1\n\n/* Enable the stub shared object loader (src/loadso/dummy/\\*.c) */\n#define SDL_LOADSO_DISABLED\t1\n\n#define SDL_THREAD_SYMBIAN 1\n\n#define SDL_VIDEO_DRIVER_EPOC    1\n\n#define SDL_VIDEO_OPENGL 0\n\n#define SDL_HAS_64BIT_TYPE\t1\n\n#define HAVE_LIBC\t1\n#define HAVE_STDIO_H 1\n#define STDC_HEADERS 1\n#define HAVE_STRING_H 1\n#define HAVE_CTYPE_H 1\n#define HAVE_MATH_H 1\n\n#define HAVE_MALLOC 1\n#define HAVE_CALLOC 1\n#define HAVE_REALLOC 1\n#define HAVE_FREE 1\n/*#define HAVE_ALLOCA 1*/\n#define HAVE_QSORT 1\n#define HAVE_ABS 1\n#define HAVE_MEMSET 1\n#define HAVE_MEMCPY 1\n#define HAVE_MEMMOVE 1\n#define HAVE_MEMCMP 1\n#define HAVE_STRLEN 1\n#define HAVE__STRUPR 1\n#define HAVE_STRCHR 1\n#define HAVE_STRRCHR 1\n#define HAVE_STRSTR 1\n#define HAVE_ITOA 1\n#define HAVE_STRTOL 1\n#define HAVE_STRTOUL 1\n#define HAVE_STRTOLL 1\n#define HAVE_STRTOD 1\n#define HAVE_ATOI 1\n#define HAVE_ATOF 1\n#define HAVE_STRCMP 1\n#define HAVE_STRNCMP 1\n/*#define HAVE__STRICMP 1*/\n#define HAVE__STRNICMP 1\n#define HAVE_SSCANF 1\n#define HAVE_STDARG_H\t1\n#define HAVE_STDDEF_H\t1\n\n\n\n#endif /* _SDL_CONFIG_SYMBIAN_H */\n"
  },
  {
    "path": "deps/include/SDL/SDL_config_win32.h",
    "content": "/*\n    SDL - Simple DirectMedia Layer\n    Copyright (C) 1997-2012 Sam Lantinga\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Lesser General Public\n    License as published by the Free Software Foundation; either\n    version 2.1 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public\n    License along with this library; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n\n    Sam Lantinga\n    slouken@libsdl.org\n*/\n\n#ifndef _SDL_config_win32_h\n#define _SDL_config_win32_h\n\n#include \"SDL_platform.h\"\n\n/* This is a set of defines to configure the SDL features */\n\n#if defined(__GNUC__) || defined(__DMC__) || defined(__WATCOMC__)\n#define HAVE_STDINT_H\t1\n#elif defined(_MSC_VER)\ntypedef signed __int8\t\tint8_t;\ntypedef unsigned __int8\t\tuint8_t;\ntypedef signed __int16\t\tint16_t;\ntypedef unsigned __int16\tuint16_t;\ntypedef signed __int32\t\tint32_t;\ntypedef unsigned __int32\tuint32_t;\ntypedef signed __int64\t\tint64_t;\ntypedef unsigned __int64\tuint64_t;\n#ifndef _UINTPTR_T_DEFINED\n#ifdef  _WIN64\ntypedef unsigned __int64    uintptr_t;\n#else\ntypedef unsigned int   uintptr_t;\n#endif\n#define _UINTPTR_T_DEFINED\n#endif\n/* Older Visual C++ headers don't have the Win64-compatible typedefs... */\n#if ((_MSC_VER <= 1200) && (!defined(DWORD_PTR)))\n#define DWORD_PTR DWORD\n#endif\n#if ((_MSC_VER <= 1200) && (!defined(LONG_PTR)))\n#define LONG_PTR LONG\n#endif\n#else\t/* !__GNUC__ && !_MSC_VER */\ntypedef signed char int8_t;\ntypedef unsigned char uint8_t;\ntypedef signed short int16_t;\ntypedef unsigned short uint16_t;\ntypedef signed int int32_t;\ntypedef unsigned int uint32_t;\ntypedef signed long long int64_t;\ntypedef unsigned long long uint64_t;\n#ifndef _SIZE_T_DEFINED_\n#define _SIZE_T_DEFINED_\ntypedef unsigned int size_t;\n#endif\ntypedef unsigned int uintptr_t;\n#endif /* __GNUC__ || _MSC_VER */\n#define SDL_HAS_64BIT_TYPE\t1\n\n/* Enabled for SDL 1.2 (binary compatibility) */\n#define HAVE_LIBC\t1\n#ifdef HAVE_LIBC\n/* Useful headers */\n#define HAVE_STDIO_H 1\n#define STDC_HEADERS 1\n#define HAVE_STRING_H 1\n#define HAVE_CTYPE_H 1\n#define HAVE_MATH_H 1\n#ifndef _WIN32_WCE\n#define HAVE_SIGNAL_H 1\n#endif\n\n/* C library functions */\n#define HAVE_MALLOC 1\n#define HAVE_CALLOC 1\n#define HAVE_REALLOC 1\n#define HAVE_FREE 1\n#define HAVE_ALLOCA 1\n#define HAVE_QSORT 1\n#define HAVE_ABS 1\n#define HAVE_MEMSET 1\n#define HAVE_MEMCPY 1\n#define HAVE_MEMMOVE 1\n#define HAVE_MEMCMP 1\n#define HAVE_STRLEN 1\n#define HAVE_STRDUP 1\n#define HAVE__STRREV 1\n#define HAVE__STRUPR 1\n#define HAVE__STRLWR 1\n#define HAVE_STRCHR 1\n#define HAVE_STRRCHR 1\n#define HAVE_STRSTR 1\n#define HAVE_ITOA 1\n#define HAVE__LTOA 1\n#define HAVE__ULTOA 1\n#define HAVE__I64TOA 1\n#define HAVE__UI64TOA 1\n#define HAVE_STRTOL 1\n#define HAVE_STRTOUL 1\n#if defined(__MINGW32__) || defined(__WATCOMC__)\n#define HAVE_STRTOLL 1\n#define HAVE_STRTOULL 1\n#endif\n#if defined(__WATCOMC__) || (defined(_MSC_VER) && (_MSC_VER >= 1300)) || defined(_WIN64)\n#define HAVE__STRTOI64 1\n#define HAVE__STRTOUI64 1\n#endif\n#define HAVE_STRTOD 1\n#define HAVE_ATOI 1\n#define HAVE_ATOF 1\n#define HAVE_STRCMP 1\n#define HAVE_STRNCMP 1\n#define HAVE__STRICMP 1\n#define HAVE__STRNICMP 1\n#define HAVE_SSCANF 1\n#else\n#define HAVE_STDARG_H\t1\n#define HAVE_STDDEF_H\t1\n#endif\n\n/* Windows CE can support only _strdup() */\n#if defined(_WIN32_WCE) && defined(HAVE_STRDUP)\n#undef strdup\n#define strdup\t_strdup\n#endif\n\n/* Enable various audio drivers */\n#ifndef _WIN32_WCE\n#define SDL_AUDIO_DRIVER_DSOUND\t1\n#endif\n#define SDL_AUDIO_DRIVER_WAVEOUT\t1\n#define SDL_AUDIO_DRIVER_DISK\t1\n#define SDL_AUDIO_DRIVER_DUMMY\t1\n\n/* Enable various cdrom drivers */\n#ifdef _WIN32_WCE\n#define SDL_CDROM_DISABLED      1\n#else\n#define SDL_CDROM_WIN32\t\t1\n#endif\n\n/* Enable various input drivers */\n#ifdef _WIN32_WCE\n#define SDL_JOYSTICK_DISABLED   1\n#else\n#define SDL_JOYSTICK_WINMM\t1\n#endif\n\n/* Enable various shared object loading systems */\n#define SDL_LOADSO_WIN32\t1\n\n/* Enable various threading systems */\n#define SDL_THREAD_WIN32\t1\n\n/* Enable various timer systems */\n#ifdef _WIN32_WCE\n#define SDL_TIMER_WINCE\t1\n#else\n#define SDL_TIMER_WIN32\t1\n#endif\n\n/* Enable various video drivers */\n#ifdef _WIN32_WCE\n#define SDL_VIDEO_DRIVER_GAPI\t1\n#endif\n#ifndef _WIN32_WCE\n#define SDL_VIDEO_DRIVER_DDRAW\t1\n#endif\n#define SDL_VIDEO_DRIVER_DUMMY\t1\n#define SDL_VIDEO_DRIVER_WINDIB\t1\n\n/* Enable OpenGL support */\n#ifndef _WIN32_WCE\n#define SDL_VIDEO_OPENGL\t1\n#define SDL_VIDEO_OPENGL_WGL\t1\n#endif\n\n/* Disable screensaver */\n#define SDL_VIDEO_DISABLE_SCREENSAVER\t1\n\n/* Enable assembly routines (Win64 doesn't have inline asm) */\n#ifndef _WIN64\n#define SDL_ASSEMBLY_ROUTINES\t1\n#endif\n\n#endif /* _SDL_config_win32_h */\n"
  },
  {
    "path": "deps/include/SDL/SDL_copying.h",
    "content": "/*\n    SDL - Simple DirectMedia Layer\n    Copyright (C) 1997-2012 Sam Lantinga\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Lesser General Public\n    License as published by the Free Software Foundation; either\n    version 2.1 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public\n    License along with this library; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n\n    Sam Lantinga\n    slouken@libsdl.org\n*/\n\n"
  },
  {
    "path": "deps/include/SDL/SDL_cpuinfo.h",
    "content": "/*\n    SDL - Simple DirectMedia Layer\n    Copyright (C) 1997-2012 Sam Lantinga\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Lesser General Public\n    License as published by the Free Software Foundation; either\n    version 2.1 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public\n    License along with this library; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n\n    Sam Lantinga\n    slouken@libsdl.org\n*/\n\n/**\n *  @file SDL_cpuinfo.h\n *  CPU feature detection for SDL\n */\n\n#ifndef _SDL_cpuinfo_h\n#define _SDL_cpuinfo_h\n\n#include \"SDL_stdinc.h\"\n\n#include \"begin_code.h\"\n/* Set up for C function definitions, even when using C++ */\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/** This function returns true if the CPU has the RDTSC instruction */\nextern DECLSPEC SDL_bool SDLCALL SDL_HasRDTSC(void);\n\n/** This function returns true if the CPU has MMX features */\nextern DECLSPEC SDL_bool SDLCALL SDL_HasMMX(void);\n\n/** This function returns true if the CPU has MMX Ext. features */\nextern DECLSPEC SDL_bool SDLCALL SDL_HasMMXExt(void);\n\n/** This function returns true if the CPU has 3DNow features */\nextern DECLSPEC SDL_bool SDLCALL SDL_Has3DNow(void);\n\n/** This function returns true if the CPU has 3DNow! Ext. features */\nextern DECLSPEC SDL_bool SDLCALL SDL_Has3DNowExt(void);\n\n/** This function returns true if the CPU has SSE features */\nextern DECLSPEC SDL_bool SDLCALL SDL_HasSSE(void);\n\n/** This function returns true if the CPU has SSE2 features */\nextern DECLSPEC SDL_bool SDLCALL SDL_HasSSE2(void);\n\n/** This function returns true if the CPU has AltiVec features */\nextern DECLSPEC SDL_bool SDLCALL SDL_HasAltiVec(void);\n\n/* Ends C function definitions when using C++ */\n#ifdef __cplusplus\n}\n#endif\n#include \"close_code.h\"\n\n#endif /* _SDL_cpuinfo_h */\n"
  },
  {
    "path": "deps/include/SDL/SDL_endian.h",
    "content": "/*\n    SDL - Simple DirectMedia Layer\n    Copyright (C) 1997-2012 Sam Lantinga\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Lesser General Public\n    License as published by the Free Software Foundation; either\n    version 2.1 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public\n    License along with this library; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n\n    Sam Lantinga\n    slouken@libsdl.org\n*/\n\n/**\n *  @file SDL_endian.h\n *  Functions for reading and writing endian-specific values\n */\n\n#ifndef _SDL_endian_h\n#define _SDL_endian_h\n\n#include \"SDL_stdinc.h\"\n\n/** @name SDL_ENDIANs\n *  The two types of endianness\n */\n/*@{*/\n#define SDL_LIL_ENDIAN\t1234\n#define SDL_BIG_ENDIAN\t4321\n/*@}*/\n\n#ifndef SDL_BYTEORDER\t/* Not defined in SDL_config.h? */\n#ifdef __linux__\n#include <endian.h>\n#define SDL_BYTEORDER  __BYTE_ORDER\n#elif defined(__OpenBSD__) || defined(__DragonFly__)\n#include <endian.h>\n#define SDL_BYTEORDER  BYTE_ORDER\n#elif defined(__FreeBSD__) || defined(__NetBSD__)\n#include <sys/endian.h>\n#define SDL_BYTEORDER  BYTE_ORDER\n/* predefs from newer gcc and clang versions: */\n#elif defined(__ORDER_LITTLE_ENDIAN__) && defined(__ORDER_BIG_ENDIAN__) && defined(__BYTE_ORDER__)\n#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)\n#define SDL_BYTEORDER   SDL_LIL_ENDIAN\n#elif (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)\n#define SDL_BYTEORDER   SDL_BIG_ENDIAN\n#else\n#error Unsupported endianness\n#endif /**/\n#else\n#if defined(__hppa__) || \\\n    defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || \\\n    (defined(__MIPS__) && defined(__MIPSEB__)) || \\\n    defined(__ppc__) || defined(__POWERPC__) || defined(__powerpc__) || defined(__PPC__) || \\\n    defined(__sparc__)\n#define SDL_BYTEORDER\tSDL_BIG_ENDIAN\n#else\n#define SDL_BYTEORDER\tSDL_LIL_ENDIAN\n#endif\n#endif /* __linux__ */\n#endif /* !SDL_BYTEORDER */\n\n\n#include \"begin_code.h\"\n/* Set up for C function definitions, even when using C++ */\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n *  @name SDL_Swap Functions\n *  Use inline functions for compilers that support them, and static\n *  functions for those that do not.  Because these functions become\n *  static for compilers that do not support inline functions, this\n *  header should only be included in files that actually use them.\n */\n/*@{*/\n#if defined(__GNUC__) && defined(__i386__) && \\\n   !(__GNUC__ == 2 && __GNUC_MINOR__ <= 95 /* broken gcc version */)\nstatic __inline__ Uint16 SDL_Swap16(Uint16 x)\n{\n\t__asm__(\"xchgb %b0,%h0\" : \"=q\" (x) :  \"0\" (x));\n\treturn x;\n}\n#elif defined(__GNUC__) && defined(__x86_64__)\nstatic __inline__ Uint16 SDL_Swap16(Uint16 x)\n{\n\t__asm__(\"xchgb %b0,%h0\" : \"=Q\" (x) :  \"0\" (x));\n\treturn x;\n}\n#elif defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__))\nstatic __inline__ Uint16 SDL_Swap16(Uint16 x)\n{\n\tint result;\n\n\t__asm__(\"rlwimi %0,%2,8,16,23\" : \"=&r\" (result) : \"0\" (x >> 8), \"r\" (x));\n\treturn (Uint16)result;\n}\n#elif defined(__GNUC__) && defined(__aarch64__)\nstatic __inline__ Uint16 SDL_Swap16(Uint16 x)\n{\n\treturn __builtin_bswap16(x);\n}\n#elif defined(__GNUC__) && (defined(__m68k__) && !defined(__mcoldfire__))\nstatic __inline__ Uint16 SDL_Swap16(Uint16 x)\n{\n\t__asm__(\"rorw #8,%0\" : \"=d\" (x) :  \"0\" (x) : \"cc\");\n\treturn x;\n}\n#elif defined(__WATCOMC__) && defined(__386__)\nextern __inline Uint16 SDL_Swap16(Uint16);\n#pragma aux SDL_Swap16 = \\\n\t\"xchg al, ah\" \\\n\tparm   [ax]   \\\n\tmodify [ax];\n#else\nstatic __inline__ Uint16 SDL_Swap16(Uint16 x) {\n\treturn SDL_static_cast(Uint16, ((x<<8)|(x>>8)));\n}\n#endif\n\n#if defined(__GNUC__) && defined(__i386__) && \\\n   !(__GNUC__ == 2 && __GNUC_MINOR__ <= 95 /* broken gcc version */)\nstatic __inline__ Uint32 SDL_Swap32(Uint32 x)\n{\n\t__asm__(\"bswap %0\" : \"=r\" (x) : \"0\" (x));\n\treturn x;\n}\n#elif defined(__GNUC__) && defined(__x86_64__)\nstatic __inline__ Uint32 SDL_Swap32(Uint32 x)\n{\n\t__asm__(\"bswapl %0\" : \"=r\" (x) : \"0\" (x));\n\treturn x;\n}\n#elif defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__))\nstatic __inline__ Uint32 SDL_Swap32(Uint32 x)\n{\n\tUint32 result;\n\n\t__asm__(\"rlwimi %0,%2,24,16,23\" : \"=&r\" (result) : \"0\" (x>>24),  \"r\" (x));\n\t__asm__(\"rlwimi %0,%2,8,8,15\"   : \"=&r\" (result) : \"0\" (result), \"r\" (x));\n\t__asm__(\"rlwimi %0,%2,24,0,7\"   : \"=&r\" (result) : \"0\" (result), \"r\" (x));\n\treturn result;\n}\n#elif defined(__GNUC__) && defined(__aarch64__)\nstatic __inline__ Uint32 SDL_Swap32(Uint32 x)\n{\n\treturn __builtin_bswap32(x);\n}\n#elif defined(__GNUC__) && (defined(__m68k__) && !defined(__mcoldfire__))\nstatic __inline__ Uint32 SDL_Swap32(Uint32 x)\n{\n\t__asm__(\"rorw #8,%0\\n\\tswap %0\\n\\trorw #8,%0\" : \"=d\" (x) :  \"0\" (x) : \"cc\");\n\treturn x;\n}\n#elif defined(__WATCOMC__) && defined(__386__)\nextern __inline Uint32 SDL_Swap32(Uint32);\n#pragma aux SDL_Swap32 = \\\n\t\"bswap eax\"  \\\n\tparm   [eax] \\\n\tmodify [eax];\n#else\nstatic __inline__ Uint32 SDL_Swap32(Uint32 x) {\n\treturn SDL_static_cast(Uint32, ((x<<24)|((x<<8)&0x00FF0000)|((x>>8)&0x0000FF00)|(x>>24)));\n}\n#endif\n\n#ifdef SDL_HAS_64BIT_TYPE /**/\n#if defined(__GNUC__) && defined(__i386__) && \\\n   !(__GNUC__ == 2 && __GNUC_MINOR__ <= 95 /* broken gcc version */)\nstatic __inline__ Uint64 SDL_Swap64(Uint64 x)\n{\n\tunion {\n\t\tstruct { Uint32 a,b; } s;\n\t\tUint64 u;\n\t} v;\n\tv.u = x;\n\t__asm__(\"bswapl %0 ; bswapl %1 ; xchgl %0,%1\"\n\t        : \"=r\" (v.s.a), \"=r\" (v.s.b)\n\t        : \"0\"  (v.s.a),  \"1\" (v.s.b));\n\treturn v.u;\n}\n#elif defined(__GNUC__) && defined(__aarch64__)\nstatic __inline__ Uint64 SDL_Swap64(Uint64 x)\n{\n\treturn __builtin_bswap64(x);\n}\n#elif defined(__GNUC__) && defined(__x86_64__)\nstatic __inline__ Uint64 SDL_Swap64(Uint64 x)\n{\n\t__asm__(\"bswapq %0\" : \"=r\" (x) : \"0\" (x));\n\treturn x;\n}\n#elif defined(__WATCOMC__) && defined(__386__)\nextern __inline Uint64 SDL_Swap64(Uint64);\n#pragma aux SDL_Swap64 = \\\n\t\"bswap eax\"     \\\n\t\"bswap edx\"     \\\n\t\"xchg eax,edx\"  \\\n\tparm [eax edx]  \\\n\tmodify [eax edx];\n#else\nstatic __inline__ Uint64 SDL_Swap64(Uint64 x)\n{\n\tUint32 hi, lo;\n\n\t/* Separate into high and low 32-bit values and swap them */\n\tlo = SDL_static_cast(Uint32, x & 0xFFFFFFFF);\n\tx >>= 32;\n\thi = SDL_static_cast(Uint32, x & 0xFFFFFFFF);\n\tx = SDL_Swap32(lo);\n\tx <<= 32;\n\tx |= SDL_Swap32(hi);\n\treturn (x);\n}\n#endif\n#else  /* SDL_HAS_64BIT_TYPE */\n/* This is mainly to keep compilers from complaining in SDL code.\n * If there is no real 64-bit datatype, then compilers will complain about\n * the fake 64-bit datatype that SDL provides when it compiles user code.\n */\n#define SDL_Swap64(X)\t(X)\n#endif /* SDL_HAS_64BIT_TYPE */\n/*@}*/\n\n/**\n *  @name SDL_SwapLE and SDL_SwapBE Functions\n *  Byteswap item from the specified endianness to the native endianness\n */\n/*@{*/\n#if SDL_BYTEORDER == SDL_LIL_ENDIAN\n#define SDL_SwapLE16(X)\t(X)\n#define SDL_SwapLE32(X)\t(X)\n#define SDL_SwapLE64(X)\t(X)\n#define SDL_SwapBE16(X)\tSDL_Swap16(X)\n#define SDL_SwapBE32(X)\tSDL_Swap32(X)\n#define SDL_SwapBE64(X)\tSDL_Swap64(X)\n#else\n#define SDL_SwapLE16(X)\tSDL_Swap16(X)\n#define SDL_SwapLE32(X)\tSDL_Swap32(X)\n#define SDL_SwapLE64(X)\tSDL_Swap64(X)\n#define SDL_SwapBE16(X)\t(X)\n#define SDL_SwapBE32(X)\t(X)\n#define SDL_SwapBE64(X)\t(X)\n#endif\n/*@}*/\n\n/* Ends C function definitions when using C++ */\n#ifdef __cplusplus\n}\n#endif\n#include \"close_code.h\"\n\n#endif /* _SDL_endian_h */\n"
  },
  {
    "path": "deps/include/SDL/SDL_error.h",
    "content": "/*\n    SDL - Simple DirectMedia Layer\n    Copyright (C) 1997-2012 Sam Lantinga\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Lesser General Public\n    License as published by the Free Software Foundation; either\n    version 2.1 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public\n    License along with this library; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n\n    Sam Lantinga\n    slouken@libsdl.org\n*/\n\n/**\n *  @file SDL_error.h\n *  Simple error message routines for SDL\n */\n\n#ifndef _SDL_error_h\n#define _SDL_error_h\n\n#include \"SDL_stdinc.h\"\n\n#include \"begin_code.h\"\n/* Set up for C function definitions, even when using C++ */\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/** \n *  @name Public functions\n */\n/*@{*/\nextern DECLSPEC void SDLCALL SDL_SetError(const char *fmt, ...);\nextern DECLSPEC char * SDLCALL SDL_GetError(void);\nextern DECLSPEC void SDLCALL SDL_ClearError(void);\n/*@}*/\n\n/**\n *  @name Private functions\n *  @internal Private error message function - used internally\n */\n/*@{*/\n#define SDL_OutOfMemory()\tSDL_Error(SDL_ENOMEM)\n#define SDL_Unsupported()\tSDL_Error(SDL_UNSUPPORTED)\ntypedef enum {\n\tSDL_ENOMEM,\n\tSDL_EFREAD,\n\tSDL_EFWRITE,\n\tSDL_EFSEEK,\n\tSDL_UNSUPPORTED,\n\tSDL_LASTERROR\n} SDL_errorcode;\nextern DECLSPEC void SDLCALL SDL_Error(SDL_errorcode code);\n/*@}*/\n\n/* Ends C function definitions when using C++ */\n#ifdef __cplusplus\n}\n#endif\n#include \"close_code.h\"\n\n#endif /* _SDL_error_h */\n"
  },
  {
    "path": "deps/include/SDL/SDL_events.h",
    "content": "/*\n    SDL - Simple DirectMedia Layer\n    Copyright (C) 1997-2012 Sam Lantinga\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Lesser General Public\n    License as published by the Free Software Foundation; either\n    version 2.1 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public\n    License along with this library; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n\n    Sam Lantinga\n    slouken@libsdl.org\n*/\n\n/**\n *  @file SDL_events.h\n *  Include file for SDL event handling\n */\n\n#ifndef _SDL_events_h\n#define _SDL_events_h\n\n#include \"SDL_stdinc.h\"\n#include \"SDL_error.h\"\n#include \"SDL_active.h\"\n#include \"SDL_keyboard.h\"\n#include \"SDL_mouse.h\"\n#include \"SDL_joystick.h\"\n#include \"SDL_quit.h\"\n\n#include \"begin_code.h\"\n/* Set up for C function definitions, even when using C++ */\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/** @name General keyboard/mouse state definitions */\n/*@{*/\n#define SDL_RELEASED\t0\n#define SDL_PRESSED\t1\n/*@}*/\n\n/** Event enumerations */\ntypedef enum {\n       SDL_NOEVENT = 0,\t\t\t/**< Unused (do not remove) */\n       SDL_ACTIVEEVENT,\t\t\t/**< Application loses/gains visibility */\n       SDL_KEYDOWN,\t\t\t/**< Keys pressed */\n       SDL_KEYUP,\t\t\t/**< Keys released */\n       SDL_MOUSEMOTION,\t\t\t/**< Mouse moved */\n       SDL_MOUSEBUTTONDOWN,\t\t/**< Mouse button pressed */\n       SDL_MOUSEBUTTONUP,\t\t/**< Mouse button released */\n       SDL_JOYAXISMOTION,\t\t/**< Joystick axis motion */\n       SDL_JOYBALLMOTION,\t\t/**< Joystick trackball motion */\n       SDL_JOYHATMOTION,\t\t/**< Joystick hat position change */\n       SDL_JOYBUTTONDOWN,\t\t/**< Joystick button pressed */\n       SDL_JOYBUTTONUP,\t\t\t/**< Joystick button released */\n       SDL_QUIT,\t\t\t/**< User-requested quit */\n       SDL_SYSWMEVENT,\t\t\t/**< System specific event */\n       SDL_EVENT_RESERVEDA,\t\t/**< Reserved for future use.. */\n       SDL_EVENT_RESERVEDB,\t\t/**< Reserved for future use.. */\n       SDL_VIDEORESIZE,\t\t\t/**< User resized video mode */\n       SDL_VIDEOEXPOSE,\t\t\t/**< Screen needs to be redrawn */\n       SDL_EVENT_RESERVED2,\t\t/**< Reserved for future use.. */\n       SDL_EVENT_RESERVED3,\t\t/**< Reserved for future use.. */\n       SDL_EVENT_RESERVED4,\t\t/**< Reserved for future use.. */\n       SDL_EVENT_RESERVED5,\t\t/**< Reserved for future use.. */\n       SDL_EVENT_RESERVED6,\t\t/**< Reserved for future use.. */\n       SDL_EVENT_RESERVED7,\t\t/**< Reserved for future use.. */\n       /** Events SDL_USEREVENT through SDL_MAXEVENTS-1 are for your use */\n       SDL_USEREVENT = 24,\n       /** This last event is only for bounding internal arrays\n\t*  It is the number of bits in the event mask datatype -- Uint32\n        */\n       SDL_NUMEVENTS = 32\n} SDL_EventType;\n\n/** @name Predefined event masks */\n/*@{*/\n#define SDL_EVENTMASK(X)\t(1<<(X))\ntypedef enum {\n\tSDL_ACTIVEEVENTMASK\t= SDL_EVENTMASK(SDL_ACTIVEEVENT),\n\tSDL_KEYDOWNMASK\t\t= SDL_EVENTMASK(SDL_KEYDOWN),\n\tSDL_KEYUPMASK\t\t= SDL_EVENTMASK(SDL_KEYUP),\n\tSDL_KEYEVENTMASK\t= SDL_EVENTMASK(SDL_KEYDOWN)|\n\t                          SDL_EVENTMASK(SDL_KEYUP),\n\tSDL_MOUSEMOTIONMASK\t= SDL_EVENTMASK(SDL_MOUSEMOTION),\n\tSDL_MOUSEBUTTONDOWNMASK\t= SDL_EVENTMASK(SDL_MOUSEBUTTONDOWN),\n\tSDL_MOUSEBUTTONUPMASK\t= SDL_EVENTMASK(SDL_MOUSEBUTTONUP),\n\tSDL_MOUSEEVENTMASK\t= SDL_EVENTMASK(SDL_MOUSEMOTION)|\n\t                          SDL_EVENTMASK(SDL_MOUSEBUTTONDOWN)|\n\t                          SDL_EVENTMASK(SDL_MOUSEBUTTONUP),\n\tSDL_JOYAXISMOTIONMASK\t= SDL_EVENTMASK(SDL_JOYAXISMOTION),\n\tSDL_JOYBALLMOTIONMASK\t= SDL_EVENTMASK(SDL_JOYBALLMOTION),\n\tSDL_JOYHATMOTIONMASK\t= SDL_EVENTMASK(SDL_JOYHATMOTION),\n\tSDL_JOYBUTTONDOWNMASK\t= SDL_EVENTMASK(SDL_JOYBUTTONDOWN),\n\tSDL_JOYBUTTONUPMASK\t= SDL_EVENTMASK(SDL_JOYBUTTONUP),\n\tSDL_JOYEVENTMASK\t= SDL_EVENTMASK(SDL_JOYAXISMOTION)|\n\t                          SDL_EVENTMASK(SDL_JOYBALLMOTION)|\n\t                          SDL_EVENTMASK(SDL_JOYHATMOTION)|\n\t                          SDL_EVENTMASK(SDL_JOYBUTTONDOWN)|\n\t                          SDL_EVENTMASK(SDL_JOYBUTTONUP),\n\tSDL_VIDEORESIZEMASK\t= SDL_EVENTMASK(SDL_VIDEORESIZE),\n\tSDL_VIDEOEXPOSEMASK\t= SDL_EVENTMASK(SDL_VIDEOEXPOSE),\n\tSDL_QUITMASK\t\t= SDL_EVENTMASK(SDL_QUIT),\n\tSDL_SYSWMEVENTMASK\t= SDL_EVENTMASK(SDL_SYSWMEVENT)\n} SDL_EventMask ;\n#define SDL_ALLEVENTS\t\t0xFFFFFFFF\n/*@}*/\n\n/** Application visibility event structure */\ntypedef struct SDL_ActiveEvent {\n\tUint8 type;\t/**< SDL_ACTIVEEVENT */\n\tUint8 gain;\t/**< Whether given states were gained or lost (1/0) */\n\tUint8 state;\t/**< A mask of the focus states */\n} SDL_ActiveEvent;\n\n/** Keyboard event structure */\ntypedef struct SDL_KeyboardEvent {\n\tUint8 type;\t/**< SDL_KEYDOWN or SDL_KEYUP */\n\tUint8 which;\t/**< The keyboard device index */\n\tUint8 state;\t/**< SDL_PRESSED or SDL_RELEASED */\n\tSDL_keysym keysym;\n} SDL_KeyboardEvent;\n\n/** Mouse motion event structure */\ntypedef struct SDL_MouseMotionEvent {\n\tUint8 type;\t/**< SDL_MOUSEMOTION */\n\tUint8 which;\t/**< The mouse device index */\n\tUint8 state;\t/**< The current button state */\n\tUint16 x, y;\t/**< The X/Y coordinates of the mouse */\n\tSint16 xrel;\t/**< The relative motion in the X direction */\n\tSint16 yrel;\t/**< The relative motion in the Y direction */\n} SDL_MouseMotionEvent;\n\n/** Mouse button event structure */\ntypedef struct SDL_MouseButtonEvent {\n\tUint8 type;\t/**< SDL_MOUSEBUTTONDOWN or SDL_MOUSEBUTTONUP */\n\tUint8 which;\t/**< The mouse device index */\n\tUint8 button;\t/**< The mouse button index */\n\tUint8 state;\t/**< SDL_PRESSED or SDL_RELEASED */\n\tUint16 x, y;\t/**< The X/Y coordinates of the mouse at press time */\n} SDL_MouseButtonEvent;\n\n/** Joystick axis motion event structure */\ntypedef struct SDL_JoyAxisEvent {\n\tUint8 type;\t/**< SDL_JOYAXISMOTION */\n\tUint8 which;\t/**< The joystick device index */\n\tUint8 axis;\t/**< The joystick axis index */\n\tSint16 value;\t/**< The axis value (range: -32768 to 32767) */\n} SDL_JoyAxisEvent;\n\n/** Joystick trackball motion event structure */\ntypedef struct SDL_JoyBallEvent {\n\tUint8 type;\t/**< SDL_JOYBALLMOTION */\n\tUint8 which;\t/**< The joystick device index */\n\tUint8 ball;\t/**< The joystick trackball index */\n\tSint16 xrel;\t/**< The relative motion in the X direction */\n\tSint16 yrel;\t/**< The relative motion in the Y direction */\n} SDL_JoyBallEvent;\n\n/** Joystick hat position change event structure */\ntypedef struct SDL_JoyHatEvent {\n\tUint8 type;\t/**< SDL_JOYHATMOTION */\n\tUint8 which;\t/**< The joystick device index */\n\tUint8 hat;\t/**< The joystick hat index */\n\tUint8 value;\t/**< The hat position value:\n\t\t\t *   SDL_HAT_LEFTUP   SDL_HAT_UP       SDL_HAT_RIGHTUP\n\t\t\t *   SDL_HAT_LEFT     SDL_HAT_CENTERED SDL_HAT_RIGHT\n\t\t\t *   SDL_HAT_LEFTDOWN SDL_HAT_DOWN     SDL_HAT_RIGHTDOWN\n\t\t\t *  Note that zero means the POV is centered.\n\t\t\t */\n} SDL_JoyHatEvent;\n\n/** Joystick button event structure */\ntypedef struct SDL_JoyButtonEvent {\n\tUint8 type;\t/**< SDL_JOYBUTTONDOWN or SDL_JOYBUTTONUP */\n\tUint8 which;\t/**< The joystick device index */\n\tUint8 button;\t/**< The joystick button index */\n\tUint8 state;\t/**< SDL_PRESSED or SDL_RELEASED */\n} SDL_JoyButtonEvent;\n\n/** The \"window resized\" event\n *  When you get this event, you are responsible for setting a new video\n *  mode with the new width and height.\n */\ntypedef struct SDL_ResizeEvent {\n\tUint8 type;\t/**< SDL_VIDEORESIZE */\n\tint w;\t\t/**< New width */\n\tint h;\t\t/**< New height */\n} SDL_ResizeEvent;\n\n/** The \"screen redraw\" event */\ntypedef struct SDL_ExposeEvent {\n\tUint8 type;\t/**< SDL_VIDEOEXPOSE */\n} SDL_ExposeEvent;\n\n/** The \"quit requested\" event */\ntypedef struct SDL_QuitEvent {\n\tUint8 type;\t/**< SDL_QUIT */\n} SDL_QuitEvent;\n\n/** A user-defined event type */\ntypedef struct SDL_UserEvent {\n\tUint8 type;\t/**< SDL_USEREVENT through SDL_NUMEVENTS-1 */\n\tint code;\t/**< User defined event code */\n\tvoid *data1;\t/**< User defined data pointer */\n\tvoid *data2;\t/**< User defined data pointer */\n} SDL_UserEvent;\n\n/** If you want to use this event, you should include SDL_syswm.h */\nstruct SDL_SysWMmsg;\ntypedef struct SDL_SysWMmsg SDL_SysWMmsg;\ntypedef struct SDL_SysWMEvent {\n\tUint8 type;\n\tSDL_SysWMmsg *msg;\n} SDL_SysWMEvent;\n\n/** General event structure */\ntypedef union SDL_Event {\n\tUint8 type;\n\tSDL_ActiveEvent active;\n\tSDL_KeyboardEvent key;\n\tSDL_MouseMotionEvent motion;\n\tSDL_MouseButtonEvent button;\n\tSDL_JoyAxisEvent jaxis;\n\tSDL_JoyBallEvent jball;\n\tSDL_JoyHatEvent jhat;\n\tSDL_JoyButtonEvent jbutton;\n\tSDL_ResizeEvent resize;\n\tSDL_ExposeEvent expose;\n\tSDL_QuitEvent quit;\n\tSDL_UserEvent user;\n\tSDL_SysWMEvent syswm;\n} SDL_Event;\n\n\n/* Function prototypes */\n\n/** Pumps the event loop, gathering events from the input devices.\n *  This function updates the event queue and internal input device state.\n *  This should only be run in the thread that sets the video mode.\n */\nextern DECLSPEC void SDLCALL SDL_PumpEvents(void);\n\ntypedef enum {\n\tSDL_ADDEVENT,\n\tSDL_PEEKEVENT,\n\tSDL_GETEVENT\n} SDL_eventaction;\n\n/**\n *  Checks the event queue for messages and optionally returns them.\n *\n *  If 'action' is SDL_ADDEVENT, up to 'numevents' events will be added to\n *  the back of the event queue.\n *  If 'action' is SDL_PEEKEVENT, up to 'numevents' events at the front\n *  of the event queue, matching 'mask', will be returned and will not\n *  be removed from the queue.\n *  If 'action' is SDL_GETEVENT, up to 'numevents' events at the front \n *  of the event queue, matching 'mask', will be returned and will be\n *  removed from the queue.\n *\n *  @return\n *  This function returns the number of events actually stored, or -1\n *  if there was an error.\n *\n *  This function is thread-safe.\n */\nextern DECLSPEC int SDLCALL SDL_PeepEvents(SDL_Event *events, int numevents,\n\t\t\t\tSDL_eventaction action, Uint32 mask);\n\n/** Polls for currently pending events, and returns 1 if there are any pending\n *  events, or 0 if there are none available.  If 'event' is not NULL, the next\n *  event is removed from the queue and stored in that area.\n */\nextern DECLSPEC int SDLCALL SDL_PollEvent(SDL_Event *event);\n\n/** Waits indefinitely for the next available event, returning 1, or 0 if there\n *  was an error while waiting for events.  If 'event' is not NULL, the next\n *  event is removed from the queue and stored in that area.\n */\nextern DECLSPEC int SDLCALL SDL_WaitEvent(SDL_Event *event);\n\n/** Add an event to the event queue.\n *  This function returns 0 on success, or -1 if the event queue was full\n *  or there was some other error.\n */\nextern DECLSPEC int SDLCALL SDL_PushEvent(SDL_Event *event);\n\n/** @name Event Filtering */\n/*@{*/\ntypedef int (SDLCALL *SDL_EventFilter)(const SDL_Event *event);\n/**\n *  This function sets up a filter to process all events before they\n *  change internal state and are posted to the internal event queue.\n *\n *  The filter is protypted as:\n *      @code typedef int (SDLCALL *SDL_EventFilter)(const SDL_Event *event); @endcode\n *\n * If the filter returns 1, then the event will be added to the internal queue.\n * If it returns 0, then the event will be dropped from the queue, but the \n * internal state will still be updated.  This allows selective filtering of\n * dynamically arriving events.\n *\n * @warning  Be very careful of what you do in the event filter function, as \n *           it may run in a different thread!\n *\n * There is one caveat when dealing with the SDL_QUITEVENT event type.  The\n * event filter is only called when the window manager desires to close the\n * application window.  If the event filter returns 1, then the window will\n * be closed, otherwise the window will remain open if possible.\n * If the quit event is generated by an interrupt signal, it will bypass the\n * internal queue and be delivered to the application at the next event poll.\n */\nextern DECLSPEC void SDLCALL SDL_SetEventFilter(SDL_EventFilter filter);\n\n/**\n *  Return the current event filter - can be used to \"chain\" filters.\n *  If there is no event filter set, this function returns NULL.\n */\nextern DECLSPEC SDL_EventFilter SDLCALL SDL_GetEventFilter(void);\n/*@}*/\n\n/** @name Event State */\n/*@{*/\n#define SDL_QUERY\t-1\n#define SDL_IGNORE\t 0\n#define SDL_DISABLE\t 0\n#define SDL_ENABLE\t 1\n/*@}*/\n\n/**\n* This function allows you to set the state of processing certain events.\n* If 'state' is set to SDL_IGNORE, that event will be automatically dropped\n* from the event queue and will not event be filtered.\n* If 'state' is set to SDL_ENABLE, that event will be processed normally.\n* If 'state' is set to SDL_QUERY, SDL_EventState() will return the \n* current processing state of the specified event.\n*/\nextern DECLSPEC Uint8 SDLCALL SDL_EventState(Uint8 type, int state);\n\n/* Ends C function definitions when using C++ */\n#ifdef __cplusplus\n}\n#endif\n#include \"close_code.h\"\n\n#endif /* _SDL_events_h */\n"
  },
  {
    "path": "deps/include/SDL/SDL_framerate.h",
    "content": "/*\n\nSDL_framerate.h: framerate manager\n\nCopyright (C) 2001-2012  Andreas Schiffler\n\nThis software is provided 'as-is', without any express or implied\nwarranty. In no event will the authors be held liable for any damages\narising from the use of this software.\n\nPermission is granted to anyone to use this software for any purpose,\nincluding commercial applications, and to alter it and redistribute it\nfreely, subject to the following restrictions:\n\n1. The origin of this software must not be misrepresented; you must not\nclaim that you wrote the original software. If you use this software\nin a product, an acknowledgment in the product documentation would be\nappreciated but is not required.\n\n2. Altered source versions must be plainly marked as such, and must not be\nmisrepresented as being the original software.\n\n3. This notice may not be removed or altered from any source\ndistribution.\n\nAndreas Schiffler -- aschiffler at ferzkopp dot net\n\n*/\n\n#ifndef _SDL_framerate_h\n#define _SDL_framerate_h\n\n/* Set up for C function definitions, even when using C++ */\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n\t/* --- */\n\n#include <SDL.h>\n\n\t/* --------- Definitions */\n\n\t/*!\n\t\\brief Highest possible rate supported by framerate controller in Hz (1/s).\n\t*/\n#define FPS_UPPER_LIMIT\t\t200\n\n\t/*!\n\t\\brief Lowest possible rate supported by framerate controller in Hz (1/s).\n\t*/\n#define FPS_LOWER_LIMIT\t\t1\n\n\t/*!\n\t\\brief Default rate of framerate controller in Hz (1/s).\n\t*/\n#define FPS_DEFAULT\t\t30\n\n\t/*! \n\t\\brief Structure holding the state and timing information of the framerate controller. \n\t*/\n\ttypedef struct {\n\t\tUint32 framecount;\n\t\tfloat rateticks;\n\t\tUint32 baseticks;\n\t\tUint32 lastticks;\n\t\tUint32 rate;\n\t} FPSmanager;\n\n\t/* ---- Function Prototypes */\n\n#ifdef _MSC_VER\n#  if defined(DLL_EXPORT) && !defined(LIBSDL_GFX_DLL_IMPORT)\n#    define SDL_FRAMERATE_SCOPE __declspec(dllexport)\n#  else\n#    ifdef LIBSDL_GFX_DLL_IMPORT\n#      define SDL_FRAMERATE_SCOPE __declspec(dllimport)\n#    endif\n#  endif\n#endif\n#ifndef SDL_FRAMERATE_SCOPE\n#  define SDL_FRAMERATE_SCOPE extern\n#endif\n\n\t/* Functions return 0 or value for sucess and -1 for error */\n\n\tSDL_FRAMERATE_SCOPE void SDL_initFramerate(FPSmanager * manager);\n\tSDL_FRAMERATE_SCOPE int SDL_setFramerate(FPSmanager * manager, Uint32 rate);\n\tSDL_FRAMERATE_SCOPE int SDL_getFramerate(FPSmanager * manager);\n\tSDL_FRAMERATE_SCOPE int SDL_getFramecount(FPSmanager * manager);\n\tSDL_FRAMERATE_SCOPE Uint32 SDL_framerateDelay(FPSmanager * manager);\n\n\t/* --- */\n\n\t/* Ends C function definitions when using C++ */\n#ifdef __cplusplus\n}\n#endif\n\n#endif\t\t\t\t/* _SDL_framerate_h */\n"
  },
  {
    "path": "deps/include/SDL/SDL_getenv.h",
    "content": "/*\n    SDL - Simple DirectMedia Layer\n    Copyright (C) 1997-2012 Sam Lantinga\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Lesser General Public\n    License as published by the Free Software Foundation; either\n    version 2.1 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public\n    License along with this library; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n\n    Sam Lantinga\n    slouken@libsdl.org\n*/\n\n/** @file SDL_getenv.h\n *  @deprecated Use SDL_stdinc.h instead\n */\n\n/* DEPRECATED */\n#include \"SDL_stdinc.h\"\n"
  },
  {
    "path": "deps/include/SDL/SDL_gfxBlitFunc.h",
    "content": "/* \n\nSDL_gfxBlitFunc.h: custom blitters\n\nCopyright (C) 2001-2012  Andreas Schiffler\n\nThis software is provided 'as-is', without any express or implied\nwarranty. In no event will the authors be held liable for any damages\narising from the use of this software.\n\nPermission is granted to anyone to use this software for any purpose,\nincluding commercial applications, and to alter it and redistribute it\nfreely, subject to the following restrictions:\n\n1. The origin of this software must not be misrepresented; you must not\nclaim that you wrote the original software. If you use this software\nin a product, an acknowledgment in the product documentation would be\nappreciated but is not required.\n\n2. Altered source versions must be plainly marked as such, and must not be\nmisrepresented as being the original software.\n\n3. This notice may not be removed or altered from any source\ndistribution.\n\nAndreas Schiffler -- aschiffler at ferzkopp dot net\n\n*/\n\n#ifndef _SDL_gfxBlitFunc_h\n#define _SDL_gfxBlitFunc_h\n\n/* Set up for C function definitions, even when using C++ */\n#ifdef __cplusplus\nextern    \"C\" {\n#endif\n\n#include <stdio.h>\n#include <stdlib.h>\n\n#include <SDL.h>\n#include <SDL_video.h>\n\n\n\textern const unsigned int GFX_ALPHA_ADJUST_ARRAY[256];\n\n\t/* ---- Function Prototypes */\n\n#ifdef _MSC_VER\n#  if defined(DLL_EXPORT) && !defined(LIBSDL_GFX_DLL_IMPORT)\n#    define SDL_GFXBLITFUNC_SCOPE __declspec(dllexport)\n#  else\n#    ifdef LIBSDL_GFX_DLL_IMPORT\n#      define SDL_GFXBLITFUNC_SCOPE __declspec(dllimport)\n#    endif\n#  endif\n#endif\n#ifndef SDL_GFXBLITFUNC_SCOPE\n#  define SDL_GFXBLITFUNC_SCOPE extern\n#endif\n\n\n\tSDL_GFXBLITFUNC_SCOPE int SDL_gfxBlitRGBA(SDL_Surface * src, SDL_Rect * srcrect, SDL_Surface * dst, SDL_Rect * dstrect);\n\n\tSDL_GFXBLITFUNC_SCOPE int SDL_gfxSetAlpha(SDL_Surface * src, Uint8 a);\n\n\tSDL_GFXBLITFUNC_SCOPE int SDL_gfxMultiplyAlpha(SDL_Surface * src, Uint8 a);\n\n\t/* -------- Macros */\n\n\t/* Define SDL macros locally as a substitute for an #include \"SDL_blit.h\", */\n\t/* which doesn't work since the include file doesn't get installed.       */\n\n\t/*!\n\t\\brief The structure passed to the low level blit functions.\n\t*/\n\ttypedef struct {\n\t\tUint8    *s_pixels;\n\t\tint       s_width;\n\t\tint       s_height;\n\t\tint       s_skip;\n\t\tUint8    *d_pixels;\n\t\tint       d_width;\n\t\tint       d_height;\n\t\tint       d_skip;\n\t\tvoid     *aux_data;\n\t\tSDL_PixelFormat *src;\n\t\tUint8    *table;\n\t\tSDL_PixelFormat *dst;\n\t} SDL_gfxBlitInfo;\n\n\t/*!\n\t\\brief Unwrap RGBA values from a pixel using mask, shift and loss for surface.\n\t*/\n#define GFX_RGBA_FROM_PIXEL(pixel, fmt, r, g, b, a)\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\\\n\tr = ((pixel&fmt->Rmask)>>fmt->Rshift)<<fmt->Rloss; \t\t\\\n\tg = ((pixel&fmt->Gmask)>>fmt->Gshift)<<fmt->Gloss; \t\t\\\n\tb = ((pixel&fmt->Bmask)>>fmt->Bshift)<<fmt->Bloss; \t\t\\\n\ta = ((pixel&fmt->Amask)>>fmt->Ashift)<<fmt->Aloss;\t \t\\\n\t}\n\n\t/*!\n\t\\brief Disassemble buffer pointer into a pixel and separate RGBA values.\n\t*/\n#define GFX_DISASSEMBLE_RGBA(buf, bpp, fmt, pixel, r, g, b, a)\t\t\t   \\\n\tdo {\t\t\t\t\t\t\t\t\t   \\\n\tpixel = *((Uint32 *)(buf));\t\t\t   \t\t   \\\n\tGFX_RGBA_FROM_PIXEL(pixel, fmt, r, g, b, a);\t\t\t   \\\n\tpixel &= ~fmt->Amask;\t\t\t\t\t\t   \\\n\t} while(0)\n\n\t/*!\n\t\\brief Wrap a pixel from RGBA values using mask, shift and loss for surface.\n\t*/\n#define GFX_PIXEL_FROM_RGBA(pixel, fmt, r, g, b, a)\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\\\n\tpixel = ((r>>fmt->Rloss)<<fmt->Rshift)|\t\t\t\t\\\n\t((g>>fmt->Gloss)<<fmt->Gshift)|\t\t\t\t\\\n\t((b>>fmt->Bloss)<<fmt->Bshift)|\t\t\t\t\\\n\t((a<<fmt->Aloss)<<fmt->Ashift);\t\t\t\t\\\n\t}\n\n\t/*!\n\t\\brief Assemble pixel into buffer pointer from separate RGBA values.\n\t*/\n#define GFX_ASSEMBLE_RGBA(buf, bpp, fmt, r, g, b, a)\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\\\n\tUint32 pixel;\t\t\t\t\t\\\n\t\\\n\tGFX_PIXEL_FROM_RGBA(pixel, fmt, r, g, b, a);\t\\\n\t*((Uint32 *)(buf)) = pixel;\t\t\t\\\n\t}\n\n\t/*!\n\t\\brief Blend the RGB values of two pixels based on a source alpha value.\n\t*/\n#define GFX_ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB)\t\\\n\tdo {\t\t\t\t\t\t\\\n\tdR = (((sR-dR)*(A))/255)+dR;\t\t\\\n\tdG = (((sG-dG)*(A))/255)+dG;\t\t\\\n\tdB = (((sB-dB)*(A))/255)+dB;\t\t\\\n\t} while(0)\n\n\t/*!\n\t\\brief 4-times unrolled DUFFs loop.\n\n\tThis is a very useful loop for optimizing blitters.\n\t*/\n#define GFX_DUFFS_LOOP4(pixel_copy_increment, width)\t\t\t\\\n\t{ int n = (width+3)/4;\t\t\t\t\t\t\t\\\n\tswitch (width & 3) {\t\t\t\t\t\t\\\n\tcase 0: do {\tpixel_copy_increment;\t\t\t\t\\\n\tcase 3:\t\tpixel_copy_increment;\t\t\t\t\\\n\tcase 2:\t\tpixel_copy_increment;\t\t\t\t\\\n\tcase 1:\t\tpixel_copy_increment;\t\t\t\t\\\n\t} while ( --n > 0 );\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\t}\n\n\n\n\t/* Ends C function definitions when using C++ */\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* _SDL_gfxBlitFunc_h */\n"
  },
  {
    "path": "deps/include/SDL/SDL_gfxPrimitives.h",
    "content": "/* \n\nSDL_gfxPrimitives.h: graphics primitives for SDL\n\nCopyright (C) 2001-2013  Andreas Schiffler\n\nThis software is provided 'as-is', without any express or implied\nwarranty. In no event will the authors be held liable for any damages\narising from the use of this software.\n\nPermission is granted to anyone to use this software for any purpose,\nincluding commercial applications, and to alter it and redistribute it\nfreely, subject to the following restrictions:\n\n1. The origin of this software must not be misrepresented; you must not\nclaim that you wrote the original software. If you use this software\nin a product, an acknowledgment in the product documentation would be\nappreciated but is not required.\n\n2. Altered source versions must be plainly marked as such, and must not be\nmisrepresented as being the original software.\n\n3. This notice may not be removed or altered from any source\ndistribution.\n\nAndreas Schiffler -- aschiffler at ferzkopp dot net\n\n*/\n\n#ifndef _SDL_gfxPrimitives_h\n#define _SDL_gfxPrimitives_h\n\n#include <math.h>\n#ifndef M_PI\n#define M_PI\t3.1415926535897932384626433832795\n#endif\n\n#include <SDL.h>\n\n/* Set up for C function definitions, even when using C++ */\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n\t/* ----- Versioning */\n\n#define SDL_GFXPRIMITIVES_MAJOR\t2\n#define SDL_GFXPRIMITIVES_MINOR\t0\n#define SDL_GFXPRIMITIVES_MICRO\t26\n\n\n\t/* ---- Function Prototypes */\n\n#ifdef _MSC_VER\n#  if defined(DLL_EXPORT) && !defined(LIBSDL_GFX_DLL_IMPORT)\n#    define SDL_GFXPRIMITIVES_SCOPE __declspec(dllexport)\n#  else\n#    ifdef LIBSDL_GFX_DLL_IMPORT\n#      define SDL_GFXPRIMITIVES_SCOPE __declspec(dllimport)\n#    endif\n#  endif\n#endif\n#ifndef SDL_GFXPRIMITIVES_SCOPE\n#  define SDL_GFXPRIMITIVES_SCOPE extern\n#endif\n\n\t/* Note: all ___Color routines expect the color to be in format 0xRRGGBBAA */\n\n\t/* Pixel */\n\n\tSDL_GFXPRIMITIVES_SCOPE int pixelColor(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color);\n\tSDL_GFXPRIMITIVES_SCOPE int pixelRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a);\n\n\t/* Horizontal line */\n\n\tSDL_GFXPRIMITIVES_SCOPE int hlineColor(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color);\n\tSDL_GFXPRIMITIVES_SCOPE int hlineRGBA(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a);\n\n\t/* Vertical line */\n\n\tSDL_GFXPRIMITIVES_SCOPE int vlineColor(SDL_Surface * dst, Sint16 x, Sint16 y1, Sint16 y2, Uint32 color);\n\tSDL_GFXPRIMITIVES_SCOPE int vlineRGBA(SDL_Surface * dst, Sint16 x, Sint16 y1, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a);\n\n\t/* Rectangle */\n\n\tSDL_GFXPRIMITIVES_SCOPE int rectangleColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color);\n\tSDL_GFXPRIMITIVES_SCOPE int rectangleRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1,\n\t\tSint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a);\n\n\t/* Rounded-Corner Rectangle */\n\n\tSDL_GFXPRIMITIVES_SCOPE int roundedRectangleColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 rad, Uint32 color);\n\tSDL_GFXPRIMITIVES_SCOPE int roundedRectangleRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1,\n\t\tSint16 x2, Sint16 y2, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a);\n\n\t/* Filled rectangle (Box) */\n\n\tSDL_GFXPRIMITIVES_SCOPE int boxColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color);\n\tSDL_GFXPRIMITIVES_SCOPE int boxRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2,\n\t\tSint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a);\n\n\t/* Rounded-Corner Filled rectangle (Box) */\n\n\tSDL_GFXPRIMITIVES_SCOPE int roundedBoxColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 rad, Uint32 color);\n\tSDL_GFXPRIMITIVES_SCOPE int roundedBoxRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2,\n\t\tSint16 y2, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a);\n\n\t/* Line */\n\n\tSDL_GFXPRIMITIVES_SCOPE int lineColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color);\n\tSDL_GFXPRIMITIVES_SCOPE int lineRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1,\n\t\tSint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a);\n\n\t/* AA Line */\n\n\tSDL_GFXPRIMITIVES_SCOPE int aalineColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color);\n\tSDL_GFXPRIMITIVES_SCOPE int aalineRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1,\n\t\tSint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a);\n\n\t/* Thick Line */\n\tSDL_GFXPRIMITIVES_SCOPE int thickLineColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, \n\t\tUint8 width, Uint32 color);\n\tSDL_GFXPRIMITIVES_SCOPE int thickLineRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, \n\t\tUint8 width, Uint8 r, Uint8 g, Uint8 b, Uint8 a);\n\n\t/* Circle */\n\n\tSDL_GFXPRIMITIVES_SCOPE int circleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint32 color);\n\tSDL_GFXPRIMITIVES_SCOPE int circleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a);\n\n\t/* Arc */\n\n\tSDL_GFXPRIMITIVES_SCOPE int arcColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color);\n\tSDL_GFXPRIMITIVES_SCOPE int arcRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, \n\t\tUint8 r, Uint8 g, Uint8 b, Uint8 a);\n\n\t/* AA Circle */\n\n\tSDL_GFXPRIMITIVES_SCOPE int aacircleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint32 color);\n\tSDL_GFXPRIMITIVES_SCOPE int aacircleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y,\n\t\tSint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a);\n\n\t/* Filled Circle */\n\n\tSDL_GFXPRIMITIVES_SCOPE int filledCircleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 r, Uint32 color);\n\tSDL_GFXPRIMITIVES_SCOPE int filledCircleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y,\n\t\tSint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a);\n\n\t/* Ellipse */\n\n\tSDL_GFXPRIMITIVES_SCOPE int ellipseColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color);\n\tSDL_GFXPRIMITIVES_SCOPE int ellipseRGBA(SDL_Surface * dst, Sint16 x, Sint16 y,\n\t\tSint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a);\n\n\t/* AA Ellipse */\n\n\tSDL_GFXPRIMITIVES_SCOPE int aaellipseColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color);\n\tSDL_GFXPRIMITIVES_SCOPE int aaellipseRGBA(SDL_Surface * dst, Sint16 x, Sint16 y,\n\t\tSint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a);\n\n\t/* Filled Ellipse */\n\n\tSDL_GFXPRIMITIVES_SCOPE int filledEllipseColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color);\n\tSDL_GFXPRIMITIVES_SCOPE int filledEllipseRGBA(SDL_Surface * dst, Sint16 x, Sint16 y,\n\t\tSint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a);\n\n\t/* Pie */\n\n\tSDL_GFXPRIMITIVES_SCOPE int pieColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad,\n\t\tSint16 start, Sint16 end, Uint32 color);\n\tSDL_GFXPRIMITIVES_SCOPE int pieRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad,\n\t\tSint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a);\n\n\t/* Filled Pie */\n\n\tSDL_GFXPRIMITIVES_SCOPE int filledPieColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad,\n\t\tSint16 start, Sint16 end, Uint32 color);\n\tSDL_GFXPRIMITIVES_SCOPE int filledPieRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad,\n\t\tSint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a);\n\n\t/* Trigon */\n\n\tSDL_GFXPRIMITIVES_SCOPE int trigonColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color);\n\tSDL_GFXPRIMITIVES_SCOPE int trigonRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,\n\t\tUint8 r, Uint8 g, Uint8 b, Uint8 a);\n\n\t/* AA-Trigon */\n\n\tSDL_GFXPRIMITIVES_SCOPE int aatrigonColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color);\n\tSDL_GFXPRIMITIVES_SCOPE int aatrigonRGBA(SDL_Surface * dst,  Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,\n\t\tUint8 r, Uint8 g, Uint8 b, Uint8 a);\n\n\t/* Filled Trigon */\n\n\tSDL_GFXPRIMITIVES_SCOPE int filledTrigonColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color);\n\tSDL_GFXPRIMITIVES_SCOPE int filledTrigonRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,\n\t\tUint8 r, Uint8 g, Uint8 b, Uint8 a);\n\n\t/* Polygon */\n\n\tSDL_GFXPRIMITIVES_SCOPE int polygonColor(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color);\n\tSDL_GFXPRIMITIVES_SCOPE int polygonRGBA(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy,\n\t\tint n, Uint8 r, Uint8 g, Uint8 b, Uint8 a);\n\n\t/* AA-Polygon */\n\n\tSDL_GFXPRIMITIVES_SCOPE int aapolygonColor(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color);\n\tSDL_GFXPRIMITIVES_SCOPE int aapolygonRGBA(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy,\n\t\tint n, Uint8 r, Uint8 g, Uint8 b, Uint8 a);\n\n\t/* Filled Polygon */\n\n\tSDL_GFXPRIMITIVES_SCOPE int filledPolygonColor(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color);\n\tSDL_GFXPRIMITIVES_SCOPE int filledPolygonRGBA(SDL_Surface * dst, const Sint16 * vx,\n\t\tconst Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a);\n\tSDL_GFXPRIMITIVES_SCOPE int texturedPolygon(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, SDL_Surface * texture,int texture_dx,int texture_dy);\n\n\t/* (Note: These MT versions are required for multi-threaded operation.) */\n\n\tSDL_GFXPRIMITIVES_SCOPE int filledPolygonColorMT(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color, int **polyInts, int *polyAllocated);\n\tSDL_GFXPRIMITIVES_SCOPE int filledPolygonRGBAMT(SDL_Surface * dst, const Sint16 * vx,\n\t\tconst Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a,\n\t\tint **polyInts, int *polyAllocated);\n\tSDL_GFXPRIMITIVES_SCOPE int texturedPolygonMT(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, SDL_Surface * texture,int texture_dx,int texture_dy, int **polyInts, int *polyAllocated);\n\n\t/* Bezier */\n\n\tSDL_GFXPRIMITIVES_SCOPE int bezierColor(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, int s, Uint32 color);\n\tSDL_GFXPRIMITIVES_SCOPE int bezierRGBA(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy,\n\t\tint n, int s, Uint8 r, Uint8 g, Uint8 b, Uint8 a);\n\n\t/* Characters/Strings */\n\n\tSDL_GFXPRIMITIVES_SCOPE void gfxPrimitivesSetFont(const void *fontdata, Uint32 cw, Uint32 ch);\n\tSDL_GFXPRIMITIVES_SCOPE void gfxPrimitivesSetFontRotation(Uint32 rotation);\n\tSDL_GFXPRIMITIVES_SCOPE int characterColor(SDL_Surface * dst, Sint16 x, Sint16 y, char c, Uint32 color);\n\tSDL_GFXPRIMITIVES_SCOPE int characterRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, char c, Uint8 r, Uint8 g, Uint8 b, Uint8 a);\n\tSDL_GFXPRIMITIVES_SCOPE int stringColor(SDL_Surface * dst, Sint16 x, Sint16 y, const char *s, Uint32 color);\n\tSDL_GFXPRIMITIVES_SCOPE int stringRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, const char *s, Uint8 r, Uint8 g, Uint8 b, Uint8 a);\n\n\t/* Ends C function definitions when using C++ */\n#ifdef __cplusplus\n}\n#endif\n\n#endif\t\t\t\t/* _SDL_gfxPrimitives_h */\n"
  },
  {
    "path": "deps/include/SDL/SDL_gfxPrimitives_font.h",
    "content": "\n/* ---- 8x8 font definition ---- */\n\n/*  ZLIB (c) A. Schiffler 2001-2012 */\n\n#define GFX_FONTDATAMAX (8*256)\n\nstatic unsigned char gfxPrimitivesFontdata[GFX_FONTDATAMAX] = {\n\n\t/*\n\t* 0 0x00 '^@' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 1 0x01 '^A' \n\t*/\n\t0x7e,\t\t\t/* 01111110 */\n\t0x81,\t\t\t/* 10000001 */\n\t0xa5,\t\t\t/* 10100101 */\n\t0x81,\t\t\t/* 10000001 */\n\t0xbd,\t\t\t/* 10111101 */\n\t0x99,\t\t\t/* 10011001 */\n\t0x81,\t\t\t/* 10000001 */\n\t0x7e,\t\t\t/* 01111110 */\n\n\t/*\n\t* 2 0x02 '^B' \n\t*/\n\t0x7e,\t\t\t/* 01111110 */\n\t0xff,\t\t\t/* 11111111 */\n\t0xdb,\t\t\t/* 11011011 */\n\t0xff,\t\t\t/* 11111111 */\n\t0xc3,\t\t\t/* 11000011 */\n\t0xe7,\t\t\t/* 11100111 */\n\t0xff,\t\t\t/* 11111111 */\n\t0x7e,\t\t\t/* 01111110 */\n\n\t/*\n\t* 3 0x03 '^C' \n\t*/\n\t0x6c,\t\t\t/* 01101100 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0x38,\t\t\t/* 00111000 */\n\t0x10,\t\t\t/* 00010000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 4 0x04 '^D' \n\t*/\n\t0x10,\t\t\t/* 00010000 */\n\t0x38,\t\t\t/* 00111000 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0x38,\t\t\t/* 00111000 */\n\t0x10,\t\t\t/* 00010000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 5 0x05 '^E' \n\t*/\n\t0x38,\t\t\t/* 00111000 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0x38,\t\t\t/* 00111000 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0xd6,\t\t\t/* 11010110 */\n\t0x10,\t\t\t/* 00010000 */\n\t0x38,\t\t\t/* 00111000 */\n\n\t/*\n\t* 6 0x06 '^F' \n\t*/\n\t0x10,\t\t\t/* 00010000 */\n\t0x38,\t\t\t/* 00111000 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0x10,\t\t\t/* 00010000 */\n\t0x38,\t\t\t/* 00111000 */\n\n\t/*\n\t* 7 0x07 '^G' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 8 0x08 '^H' \n\t*/\n\t0xff,\t\t\t/* 11111111 */\n\t0xff,\t\t\t/* 11111111 */\n\t0xe7,\t\t\t/* 11100111 */\n\t0xc3,\t\t\t/* 11000011 */\n\t0xc3,\t\t\t/* 11000011 */\n\t0xe7,\t\t\t/* 11100111 */\n\t0xff,\t\t\t/* 11111111 */\n\t0xff,\t\t\t/* 11111111 */\n\n\t/*\n\t* 9 0x09 '^I' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x42,\t\t\t/* 01000010 */\n\t0x42,\t\t\t/* 01000010 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 10 0x0a '^J' \n\t*/\n\t0xff,\t\t\t/* 11111111 */\n\t0xc3,\t\t\t/* 11000011 */\n\t0x99,\t\t\t/* 10011001 */\n\t0xbd,\t\t\t/* 10111101 */\n\t0xbd,\t\t\t/* 10111101 */\n\t0x99,\t\t\t/* 10011001 */\n\t0xc3,\t\t\t/* 11000011 */\n\t0xff,\t\t\t/* 11111111 */\n\n\t/*\n\t* 11 0x0b '^K' \n\t*/\n\t0x0f,\t\t\t/* 00001111 */\n\t0x07,\t\t\t/* 00000111 */\n\t0x0f,\t\t\t/* 00001111 */\n\t0x7d,\t\t\t/* 01111101 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0x78,\t\t\t/* 01111000 */\n\n\t/*\n\t* 12 0x0c '^L' \n\t*/\n\t0x3c,\t\t\t/* 00111100 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0x18,\t\t\t/* 00011000 */\n\n\t/*\n\t* 13 0x0d '^M' \n\t*/\n\t0x3f,\t\t\t/* 00111111 */\n\t0x33,\t\t\t/* 00110011 */\n\t0x3f,\t\t\t/* 00111111 */\n\t0x30,\t\t\t/* 00110000 */\n\t0x30,\t\t\t/* 00110000 */\n\t0x70,\t\t\t/* 01110000 */\n\t0xf0,\t\t\t/* 11110000 */\n\t0xe0,\t\t\t/* 11100000 */\n\n\t/*\n\t* 14 0x0e '^N' \n\t*/\n\t0x7f,\t\t\t/* 01111111 */\n\t0x63,\t\t\t/* 01100011 */\n\t0x7f,\t\t\t/* 01111111 */\n\t0x63,\t\t\t/* 01100011 */\n\t0x63,\t\t\t/* 01100011 */\n\t0x67,\t\t\t/* 01100111 */\n\t0xe6,\t\t\t/* 11100110 */\n\t0xc0,\t\t\t/* 11000000 */\n\n\t/*\n\t* 15 0x0f '^O' \n\t*/\n\t0x18,\t\t\t/* 00011000 */\n\t0xdb,\t\t\t/* 11011011 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0xe7,\t\t\t/* 11100111 */\n\t0xe7,\t\t\t/* 11100111 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0xdb,\t\t\t/* 11011011 */\n\t0x18,\t\t\t/* 00011000 */\n\n\t/*\n\t* 16 0x10 '^P' \n\t*/\n\t0x80,\t\t\t/* 10000000 */\n\t0xe0,\t\t\t/* 11100000 */\n\t0xf8,\t\t\t/* 11111000 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0xf8,\t\t\t/* 11111000 */\n\t0xe0,\t\t\t/* 11100000 */\n\t0x80,\t\t\t/* 10000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 17 0x11 '^Q' \n\t*/\n\t0x02,\t\t\t/* 00000010 */\n\t0x0e,\t\t\t/* 00001110 */\n\t0x3e,\t\t\t/* 00111110 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0x3e,\t\t\t/* 00111110 */\n\t0x0e,\t\t\t/* 00001110 */\n\t0x02,\t\t\t/* 00000010 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 18 0x12 '^R' \n\t*/\n\t0x18,\t\t\t/* 00011000 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x18,\t\t\t/* 00011000 */\n\n\t/*\n\t* 19 0x13 '^S' \n\t*/\n\t0x66,\t\t\t/* 01100110 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 20 0x14 '^T' \n\t*/\n\t0x7f,\t\t\t/* 01111111 */\n\t0xdb,\t\t\t/* 11011011 */\n\t0xdb,\t\t\t/* 11011011 */\n\t0x7b,\t\t\t/* 01111011 */\n\t0x1b,\t\t\t/* 00011011 */\n\t0x1b,\t\t\t/* 00011011 */\n\t0x1b,\t\t\t/* 00011011 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 21 0x15 '^U' \n\t*/\n\t0x3e,\t\t\t/* 00111110 */\n\t0x61,\t\t\t/* 01100001 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x86,\t\t\t/* 10000110 */\n\t0x7c,\t\t\t/* 01111100 */\n\n\t/*\n\t* 22 0x16 '^V' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 23 0x17 '^W' \n\t*/\n\t0x18,\t\t\t/* 00011000 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x18,\t\t\t/* 00011000 */\n\t0xff,\t\t\t/* 11111111 */\n\n\t/*\n\t* 24 0x18 '^X' \n\t*/\n\t0x18,\t\t\t/* 00011000 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 25 0x19 '^Y' \n\t*/\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 26 0x1a '^Z' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x0c,\t\t\t/* 00001100 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0x0c,\t\t\t/* 00001100 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 27 0x1b '^[' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x30,\t\t\t/* 00110000 */\n\t0x60,\t\t\t/* 01100000 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0x60,\t\t\t/* 01100000 */\n\t0x30,\t\t\t/* 00110000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 28 0x1c '^\\' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0xc0,\t\t\t/* 11000000 */\n\t0xc0,\t\t\t/* 11000000 */\n\t0xc0,\t\t\t/* 11000000 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 29 0x1d '^]' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x24,\t\t\t/* 00100100 */\n\t0x66,\t\t\t/* 01100110 */\n\t0xff,\t\t\t/* 11111111 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x24,\t\t\t/* 00100100 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 30 0x1e '^^' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0xff,\t\t\t/* 11111111 */\n\t0xff,\t\t\t/* 11111111 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 31 0x1f '^_' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0xff,\t\t\t/* 11111111 */\n\t0xff,\t\t\t/* 11111111 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 32 0x20 ' ' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 33 0x21 '!' \n\t*/\n\t0x18,\t\t\t/* 00011000 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 34 0x22 '\"' \n\t*/\n\t0x66,\t\t\t/* 01100110 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x24,\t\t\t/* 00100100 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 35 0x23 '#' \n\t*/\n\t0x6c,\t\t\t/* 01101100 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 36 0x24 '$' \n\t*/\n\t0x18,\t\t\t/* 00011000 */\n\t0x3e,\t\t\t/* 00111110 */\n\t0x60,\t\t\t/* 01100000 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x06,\t\t\t/* 00000110 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 37 0x25 '%' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x30,\t\t\t/* 00110000 */\n\t0x66,\t\t\t/* 01100110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 38 0x26 '&' \n\t*/\n\t0x38,\t\t\t/* 00111000 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0x38,\t\t\t/* 00111000 */\n\t0x76,\t\t\t/* 01110110 */\n\t0xdc,\t\t\t/* 11011100 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0x76,\t\t\t/* 01110110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 39 0x27 ''' \n\t*/\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x30,\t\t\t/* 00110000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 40 0x28 '(' \n\t*/\n\t0x0c,\t\t\t/* 00001100 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x30,\t\t\t/* 00110000 */\n\t0x30,\t\t\t/* 00110000 */\n\t0x30,\t\t\t/* 00110000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x0c,\t\t\t/* 00001100 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 41 0x29 ')' \n\t*/\n\t0x30,\t\t\t/* 00110000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x0c,\t\t\t/* 00001100 */\n\t0x0c,\t\t\t/* 00001100 */\n\t0x0c,\t\t\t/* 00001100 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x30,\t\t\t/* 00110000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 42 0x2a '*' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0xff,\t\t\t/* 11111111 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 43 0x2b '+' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 44 0x2c ',' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x30,\t\t\t/* 00110000 */\n\n\t/*\n\t* 45 0x2d '-' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 46 0x2e '.' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 47 0x2f '/' \n\t*/\n\t0x06,\t\t\t/* 00000110 */\n\t0x0c,\t\t\t/* 00001100 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x30,\t\t\t/* 00110000 */\n\t0x60,\t\t\t/* 01100000 */\n\t0xc0,\t\t\t/* 11000000 */\n\t0x80,\t\t\t/* 10000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 48 0x30 '0' \n\t*/\n\t0x38,\t\t\t/* 00111000 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xd6,\t\t\t/* 11010110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0x38,\t\t\t/* 00111000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 49 0x31 '1' \n\t*/\n\t0x18,\t\t\t/* 00011000 */\n\t0x38,\t\t\t/* 00111000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 50 0x32 '2' \n\t*/\n\t0x7c,\t\t\t/* 01111100 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0x06,\t\t\t/* 00000110 */\n\t0x1c,\t\t\t/* 00011100 */\n\t0x30,\t\t\t/* 00110000 */\n\t0x66,\t\t\t/* 01100110 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 51 0x33 '3' \n\t*/\n\t0x7c,\t\t\t/* 01111100 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0x06,\t\t\t/* 00000110 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x06,\t\t\t/* 00000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 52 0x34 '4' \n\t*/\n\t0x1c,\t\t\t/* 00011100 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0x0c,\t\t\t/* 00001100 */\n\t0x1e,\t\t\t/* 00011110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 53 0x35 '5' \n\t*/\n\t0xfe,\t\t\t/* 11111110 */\n\t0xc0,\t\t\t/* 11000000 */\n\t0xc0,\t\t\t/* 11000000 */\n\t0xfc,\t\t\t/* 11111100 */\n\t0x06,\t\t\t/* 00000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 54 0x36 '6' \n\t*/\n\t0x38,\t\t\t/* 00111000 */\n\t0x60,\t\t\t/* 01100000 */\n\t0xc0,\t\t\t/* 11000000 */\n\t0xfc,\t\t\t/* 11111100 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 55 0x37 '7' \n\t*/\n\t0xfe,\t\t\t/* 11111110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0x0c,\t\t\t/* 00001100 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x30,\t\t\t/* 00110000 */\n\t0x30,\t\t\t/* 00110000 */\n\t0x30,\t\t\t/* 00110000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 56 0x38 '8' \n\t*/\n\t0x7c,\t\t\t/* 01111100 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 57 0x39 '9' \n\t*/\n\t0x7c,\t\t\t/* 01111100 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0x06,\t\t\t/* 00000110 */\n\t0x0c,\t\t\t/* 00001100 */\n\t0x78,\t\t\t/* 01111000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 58 0x3a ':' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 59 0x3b ';' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x30,\t\t\t/* 00110000 */\n\n\t/*\n\t* 60 0x3c '<' \n\t*/\n\t0x06,\t\t\t/* 00000110 */\n\t0x0c,\t\t\t/* 00001100 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x30,\t\t\t/* 00110000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x0c,\t\t\t/* 00001100 */\n\t0x06,\t\t\t/* 00000110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 61 0x3d '=' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 62 0x3e '>' \n\t*/\n\t0x60,\t\t\t/* 01100000 */\n\t0x30,\t\t\t/* 00110000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x0c,\t\t\t/* 00001100 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x30,\t\t\t/* 00110000 */\n\t0x60,\t\t\t/* 01100000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 63 0x3f '?' \n\t*/\n\t0x7c,\t\t\t/* 01111100 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0x0c,\t\t\t/* 00001100 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 64 0x40 '@' \n\t*/\n\t0x7c,\t\t\t/* 01111100 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xde,\t\t\t/* 11011110 */\n\t0xde,\t\t\t/* 11011110 */\n\t0xde,\t\t\t/* 11011110 */\n\t0xc0,\t\t\t/* 11000000 */\n\t0x78,\t\t\t/* 01111000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 65 0x41 'A' \n\t*/\n\t0x38,\t\t\t/* 00111000 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 66 0x42 'B' \n\t*/\n\t0xfc,\t\t\t/* 11111100 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x66,\t\t\t/* 01100110 */\n\t0xfc,\t\t\t/* 11111100 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 67 0x43 'C' \n\t*/\n\t0x3c,\t\t\t/* 00111100 */\n\t0x66,\t\t\t/* 01100110 */\n\t0xc0,\t\t\t/* 11000000 */\n\t0xc0,\t\t\t/* 11000000 */\n\t0xc0,\t\t\t/* 11000000 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 68 0x44 'D' \n\t*/\n\t0xf8,\t\t\t/* 11111000 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0xf8,\t\t\t/* 11111000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 69 0x45 'E' \n\t*/\n\t0xfe,\t\t\t/* 11111110 */\n\t0x62,\t\t\t/* 01100010 */\n\t0x68,\t\t\t/* 01101000 */\n\t0x78,\t\t\t/* 01111000 */\n\t0x68,\t\t\t/* 01101000 */\n\t0x62,\t\t\t/* 01100010 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 70 0x46 'F' \n\t*/\n\t0xfe,\t\t\t/* 11111110 */\n\t0x62,\t\t\t/* 01100010 */\n\t0x68,\t\t\t/* 01101000 */\n\t0x78,\t\t\t/* 01111000 */\n\t0x68,\t\t\t/* 01101000 */\n\t0x60,\t\t\t/* 01100000 */\n\t0xf0,\t\t\t/* 11110000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 71 0x47 'G' \n\t*/\n\t0x3c,\t\t\t/* 00111100 */\n\t0x66,\t\t\t/* 01100110 */\n\t0xc0,\t\t\t/* 11000000 */\n\t0xc0,\t\t\t/* 11000000 */\n\t0xce,\t\t\t/* 11001110 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x3a,\t\t\t/* 00111010 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 72 0x48 'H' \n\t*/\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 73 0x49 'I' \n\t*/\n\t0x3c,\t\t\t/* 00111100 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 74 0x4a 'J' \n\t*/\n\t0x1e,\t\t\t/* 00011110 */\n\t0x0c,\t\t\t/* 00001100 */\n\t0x0c,\t\t\t/* 00001100 */\n\t0x0c,\t\t\t/* 00001100 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0x78,\t\t\t/* 01111000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 75 0x4b 'K' \n\t*/\n\t0xe6,\t\t\t/* 11100110 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0x78,\t\t\t/* 01111000 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0x66,\t\t\t/* 01100110 */\n\t0xe6,\t\t\t/* 11100110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 76 0x4c 'L' \n\t*/\n\t0xf0,\t\t\t/* 11110000 */\n\t0x60,\t\t\t/* 01100000 */\n\t0x60,\t\t\t/* 01100000 */\n\t0x60,\t\t\t/* 01100000 */\n\t0x62,\t\t\t/* 01100010 */\n\t0x66,\t\t\t/* 01100110 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 77 0x4d 'M' \n\t*/\n\t0xc6,\t\t\t/* 11000110 */\n\t0xee,\t\t\t/* 11101110 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0xd6,\t\t\t/* 11010110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 78 0x4e 'N' \n\t*/\n\t0xc6,\t\t\t/* 11000110 */\n\t0xe6,\t\t\t/* 11100110 */\n\t0xf6,\t\t\t/* 11110110 */\n\t0xde,\t\t\t/* 11011110 */\n\t0xce,\t\t\t/* 11001110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 79 0x4f 'O' \n\t*/\n\t0x7c,\t\t\t/* 01111100 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 80 0x50 'P' \n\t*/\n\t0xfc,\t\t\t/* 11111100 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0x60,\t\t\t/* 01100000 */\n\t0x60,\t\t\t/* 01100000 */\n\t0xf0,\t\t\t/* 11110000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 81 0x51 'Q' \n\t*/\n\t0x7c,\t\t\t/* 01111100 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xce,\t\t\t/* 11001110 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0x0e,\t\t\t/* 00001110 */\n\n\t/*\n\t* 82 0x52 'R' \n\t*/\n\t0xfc,\t\t\t/* 11111100 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0x66,\t\t\t/* 01100110 */\n\t0xe6,\t\t\t/* 11100110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 83 0x53 'S' \n\t*/\n\t0x3c,\t\t\t/* 00111100 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x30,\t\t\t/* 00110000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x0c,\t\t\t/* 00001100 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 84 0x54 'T' \n\t*/\n\t0x7e,\t\t\t/* 01111110 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0x5a,\t\t\t/* 01011010 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 85 0x55 'U' \n\t*/\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 86 0x56 'V' \n\t*/\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0x38,\t\t\t/* 00111000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 87 0x57 'W' \n\t*/\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xd6,\t\t\t/* 11010110 */\n\t0xd6,\t\t\t/* 11010110 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 88 0x58 'X' \n\t*/\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0x38,\t\t\t/* 00111000 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 89 0x59 'Y' \n\t*/\n\t0x66,\t\t\t/* 01100110 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 90 0x5a 'Z' \n\t*/\n\t0xfe,\t\t\t/* 11111110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0x8c,\t\t\t/* 10001100 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x32,\t\t\t/* 00110010 */\n\t0x66,\t\t\t/* 01100110 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 91 0x5b '[' \n\t*/\n\t0x3c,\t\t\t/* 00111100 */\n\t0x30,\t\t\t/* 00110000 */\n\t0x30,\t\t\t/* 00110000 */\n\t0x30,\t\t\t/* 00110000 */\n\t0x30,\t\t\t/* 00110000 */\n\t0x30,\t\t\t/* 00110000 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 92 0x5c '\\' \n\t*/\n\t0xc0,\t\t\t/* 11000000 */\n\t0x60,\t\t\t/* 01100000 */\n\t0x30,\t\t\t/* 00110000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x0c,\t\t\t/* 00001100 */\n\t0x06,\t\t\t/* 00000110 */\n\t0x02,\t\t\t/* 00000010 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 93 0x5d ']' \n\t*/\n\t0x3c,\t\t\t/* 00111100 */\n\t0x0c,\t\t\t/* 00001100 */\n\t0x0c,\t\t\t/* 00001100 */\n\t0x0c,\t\t\t/* 00001100 */\n\t0x0c,\t\t\t/* 00001100 */\n\t0x0c,\t\t\t/* 00001100 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 94 0x5e '^' \n\t*/\n\t0x10,\t\t\t/* 00010000 */\n\t0x38,\t\t\t/* 00111000 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 95 0x5f '_' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0xff,\t\t\t/* 11111111 */\n\n\t/*\n\t* 96 0x60 '`' \n\t*/\n\t0x30,\t\t\t/* 00110000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x0c,\t\t\t/* 00001100 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 97 0x61 'a' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x78,\t\t\t/* 01111000 */\n\t0x0c,\t\t\t/* 00001100 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0x76,\t\t\t/* 01110110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 98 0x62 'b' \n\t*/\n\t0xe0,\t\t\t/* 11100000 */\n\t0x60,\t\t\t/* 01100000 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x66,\t\t\t/* 01100110 */\n\t0xdc,\t\t\t/* 11011100 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 99 0x63 'c' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc0,\t\t\t/* 11000000 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 100 0x64 'd' \n\t*/\n\t0x1c,\t\t\t/* 00011100 */\n\t0x0c,\t\t\t/* 00001100 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0x76,\t\t\t/* 01110110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 101 0x65 'e' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0xc0,\t\t\t/* 11000000 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 102 0x66 'f' \n\t*/\n\t0x3c,\t\t\t/* 00111100 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x60,\t\t\t/* 01100000 */\n\t0xf8,\t\t\t/* 11111000 */\n\t0x60,\t\t\t/* 01100000 */\n\t0x60,\t\t\t/* 01100000 */\n\t0xf0,\t\t\t/* 11110000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 103 0x67 'g' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x76,\t\t\t/* 01110110 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0x0c,\t\t\t/* 00001100 */\n\t0xf8,\t\t\t/* 11111000 */\n\n\t/*\n\t* 104 0x68 'h' \n\t*/\n\t0xe0,\t\t\t/* 11100000 */\n\t0x60,\t\t\t/* 01100000 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0x76,\t\t\t/* 01110110 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x66,\t\t\t/* 01100110 */\n\t0xe6,\t\t\t/* 11100110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 105 0x69 'i' \n\t*/\n\t0x18,\t\t\t/* 00011000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x38,\t\t\t/* 00111000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 106 0x6a 'j' \n\t*/\n\t0x06,\t\t\t/* 00000110 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x06,\t\t\t/* 00000110 */\n\t0x06,\t\t\t/* 00000110 */\n\t0x06,\t\t\t/* 00000110 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x3c,\t\t\t/* 00111100 */\n\n\t/*\n\t* 107 0x6b 'k' \n\t*/\n\t0xe0,\t\t\t/* 11100000 */\n\t0x60,\t\t\t/* 01100000 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0x78,\t\t\t/* 01111000 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0xe6,\t\t\t/* 11100110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 108 0x6c 'l' \n\t*/\n\t0x38,\t\t\t/* 00111000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 109 0x6d 'm' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0xec,\t\t\t/* 11101100 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0xd6,\t\t\t/* 11010110 */\n\t0xd6,\t\t\t/* 11010110 */\n\t0xd6,\t\t\t/* 11010110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 110 0x6e 'n' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0xdc,\t\t\t/* 11011100 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 111 0x6f 'o' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 112 0x70 'p' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0xdc,\t\t\t/* 11011100 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0x60,\t\t\t/* 01100000 */\n\t0xf0,\t\t\t/* 11110000 */\n\n\t/*\n\t* 113 0x71 'q' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x76,\t\t\t/* 01110110 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0x0c,\t\t\t/* 00001100 */\n\t0x1e,\t\t\t/* 00011110 */\n\n\t/*\n\t* 114 0x72 'r' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0xdc,\t\t\t/* 11011100 */\n\t0x76,\t\t\t/* 01110110 */\n\t0x60,\t\t\t/* 01100000 */\n\t0x60,\t\t\t/* 01100000 */\n\t0xf0,\t\t\t/* 11110000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 115 0x73 's' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0xc0,\t\t\t/* 11000000 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0x06,\t\t\t/* 00000110 */\n\t0xfc,\t\t\t/* 11111100 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 116 0x74 't' \n\t*/\n\t0x30,\t\t\t/* 00110000 */\n\t0x30,\t\t\t/* 00110000 */\n\t0xfc,\t\t\t/* 11111100 */\n\t0x30,\t\t\t/* 00110000 */\n\t0x30,\t\t\t/* 00110000 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x1c,\t\t\t/* 00011100 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 117 0x75 'u' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0x76,\t\t\t/* 01110110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 118 0x76 'v' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0x38,\t\t\t/* 00111000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 119 0x77 'w' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xd6,\t\t\t/* 11010110 */\n\t0xd6,\t\t\t/* 11010110 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 120 0x78 'x' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0x38,\t\t\t/* 00111000 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 121 0x79 'y' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0x06,\t\t\t/* 00000110 */\n\t0xfc,\t\t\t/* 11111100 */\n\n\t/*\n\t* 122 0x7a 'z' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0x4c,\t\t\t/* 01001100 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x32,\t\t\t/* 00110010 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 123 0x7b '{' \n\t*/\n\t0x0e,\t\t\t/* 00001110 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x70,\t\t\t/* 01110000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x0e,\t\t\t/* 00001110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 124 0x7c '|' \n\t*/\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 125 0x7d '}' \n\t*/\n\t0x70,\t\t\t/* 01110000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x0e,\t\t\t/* 00001110 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x70,\t\t\t/* 01110000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 126 0x7e '~' \n\t*/\n\t0x76,\t\t\t/* 01110110 */\n\t0xdc,\t\t\t/* 11011100 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 127 0x7f '' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x10,\t\t\t/* 00010000 */\n\t0x38,\t\t\t/* 00111000 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 128 0x80 '' \n\t*/\n\t0x7c,\t\t\t/* 01111100 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc0,\t\t\t/* 11000000 */\n\t0xc0,\t\t\t/* 11000000 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0x0c,\t\t\t/* 00001100 */\n\t0x78,\t\t\t/* 01111000 */\n\n\t/*\n\t* 129 0x81 '' \n\t*/\n\t0xcc,\t\t\t/* 11001100 */\n\t0x00,\t\t\t/* 00000000 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0x76,\t\t\t/* 01110110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 130 0x82 '' \n\t*/\n\t0x0c,\t\t\t/* 00001100 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0xc0,\t\t\t/* 11000000 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 131 0x83 '' \n\t*/\n\t0x7c,\t\t\t/* 01111100 */\n\t0x82,\t\t\t/* 10000010 */\n\t0x78,\t\t\t/* 01111000 */\n\t0x0c,\t\t\t/* 00001100 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0x76,\t\t\t/* 01110110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 132 0x84 '' \n\t*/\n\t0xc6,\t\t\t/* 11000110 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x78,\t\t\t/* 01111000 */\n\t0x0c,\t\t\t/* 00001100 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0x76,\t\t\t/* 01110110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 133 0x85 '' \n\t*/\n\t0x30,\t\t\t/* 00110000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x78,\t\t\t/* 01111000 */\n\t0x0c,\t\t\t/* 00001100 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0x76,\t\t\t/* 01110110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 134 0x86 '' \n\t*/\n\t0x30,\t\t\t/* 00110000 */\n\t0x30,\t\t\t/* 00110000 */\n\t0x78,\t\t\t/* 01111000 */\n\t0x0c,\t\t\t/* 00001100 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0x76,\t\t\t/* 01110110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 135 0x87 '' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0xc0,\t\t\t/* 11000000 */\n\t0xc0,\t\t\t/* 11000000 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0x0c,\t\t\t/* 00001100 */\n\t0x38,\t\t\t/* 00111000 */\n\n\t/*\n\t* 136 0x88 '' \n\t*/\n\t0x7c,\t\t\t/* 01111100 */\n\t0x82,\t\t\t/* 10000010 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0xc0,\t\t\t/* 11000000 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 137 0x89 '' \n\t*/\n\t0xc6,\t\t\t/* 11000110 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0xc0,\t\t\t/* 11000000 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 138 0x8a '' \n\t*/\n\t0x30,\t\t\t/* 00110000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0xc0,\t\t\t/* 11000000 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 139 0x8b '' \n\t*/\n\t0x66,\t\t\t/* 01100110 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x38,\t\t\t/* 00111000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 140 0x8c '' \n\t*/\n\t0x7c,\t\t\t/* 01111100 */\n\t0x82,\t\t\t/* 10000010 */\n\t0x38,\t\t\t/* 00111000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 141 0x8d '' \n\t*/\n\t0x30,\t\t\t/* 00110000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x38,\t\t\t/* 00111000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 142 0x8e '' \n\t*/\n\t0xc6,\t\t\t/* 11000110 */\n\t0x38,\t\t\t/* 00111000 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 143 0x8f '' \n\t*/\n\t0x38,\t\t\t/* 00111000 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 144 0x90 '' \n\t*/\n\t0x18,\t\t\t/* 00011000 */\n\t0x30,\t\t\t/* 00110000 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0xc0,\t\t\t/* 11000000 */\n\t0xf8,\t\t\t/* 11111000 */\n\t0xc0,\t\t\t/* 11000000 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 145 0x91 '' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0xd8,\t\t\t/* 11011000 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 146 0x92 '' \n\t*/\n\t0x3e,\t\t\t/* 00111110 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0xce,\t\t\t/* 11001110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 147 0x93 '' \n\t*/\n\t0x7c,\t\t\t/* 01111100 */\n\t0x82,\t\t\t/* 10000010 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 148 0x94 '' \n\t*/\n\t0xc6,\t\t\t/* 11000110 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 149 0x95 '' \n\t*/\n\t0x30,\t\t\t/* 00110000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 150 0x96 '' \n\t*/\n\t0x78,\t\t\t/* 01111000 */\n\t0x84,\t\t\t/* 10000100 */\n\t0x00,\t\t\t/* 00000000 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0x76,\t\t\t/* 01110110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 151 0x97 '' \n\t*/\n\t0x60,\t\t\t/* 01100000 */\n\t0x30,\t\t\t/* 00110000 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0x76,\t\t\t/* 01110110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 152 0x98 '' \n\t*/\n\t0xc6,\t\t\t/* 11000110 */\n\t0x00,\t\t\t/* 00000000 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0x06,\t\t\t/* 00000110 */\n\t0xfc,\t\t\t/* 11111100 */\n\n\t/*\n\t* 153 0x99 '' \n\t*/\n\t0xc6,\t\t\t/* 11000110 */\n\t0x38,\t\t\t/* 00111000 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0x38,\t\t\t/* 00111000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 154 0x9a '' \n\t*/\n\t0xc6,\t\t\t/* 11000110 */\n\t0x00,\t\t\t/* 00000000 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 155 0x9b '' \n\t*/\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0xc0,\t\t\t/* 11000000 */\n\t0xc0,\t\t\t/* 11000000 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\n\t/*\n\t* 156 0x9c '' \n\t*/\n\t0x38,\t\t\t/* 00111000 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0x64,\t\t\t/* 01100100 */\n\t0xf0,\t\t\t/* 11110000 */\n\t0x60,\t\t\t/* 01100000 */\n\t0x66,\t\t\t/* 01100110 */\n\t0xfc,\t\t\t/* 11111100 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 157 0x9d '' \n\t*/\n\t0x66,\t\t\t/* 01100110 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\n\t/*\n\t* 158 0x9e '' \n\t*/\n\t0xf8,\t\t\t/* 11111000 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0xfa,\t\t\t/* 11111010 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xcf,\t\t\t/* 11001111 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc7,\t\t\t/* 11000111 */\n\n\t/*\n\t* 159 0x9f '' \n\t*/\n\t0x0e,\t\t\t/* 00001110 */\n\t0x1b,\t\t\t/* 00011011 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x18,\t\t\t/* 00011000 */\n\t0xd8,\t\t\t/* 11011000 */\n\t0x70,\t\t\t/* 01110000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 160 0xa0 '' \n\t*/\n\t0x18,\t\t\t/* 00011000 */\n\t0x30,\t\t\t/* 00110000 */\n\t0x78,\t\t\t/* 01111000 */\n\t0x0c,\t\t\t/* 00001100 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0x76,\t\t\t/* 01110110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 161 0xa1 '' \n\t*/\n\t0x0c,\t\t\t/* 00001100 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x38,\t\t\t/* 00111000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 162 0xa2 '' \n\t*/\n\t0x0c,\t\t\t/* 00001100 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 163 0xa3 '' \n\t*/\n\t0x18,\t\t\t/* 00011000 */\n\t0x30,\t\t\t/* 00110000 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0x76,\t\t\t/* 01110110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 164 0xa4 '' \n\t*/\n\t0x76,\t\t\t/* 01110110 */\n\t0xdc,\t\t\t/* 11011100 */\n\t0x00,\t\t\t/* 00000000 */\n\t0xdc,\t\t\t/* 11011100 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 165 0xa5 '' \n\t*/\n\t0x76,\t\t\t/* 01110110 */\n\t0xdc,\t\t\t/* 11011100 */\n\t0x00,\t\t\t/* 00000000 */\n\t0xe6,\t\t\t/* 11100110 */\n\t0xf6,\t\t\t/* 11110110 */\n\t0xde,\t\t\t/* 11011110 */\n\t0xce,\t\t\t/* 11001110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 166 0xa6 '' \n\t*/\n\t0x3c,\t\t\t/* 00111100 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0x3e,\t\t\t/* 00111110 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 167 0xa7 '' \n\t*/\n\t0x38,\t\t\t/* 00111000 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0x38,\t\t\t/* 00111000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 168 0xa8 '' \n\t*/\n\t0x18,\t\t\t/* 00011000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x30,\t\t\t/* 00110000 */\n\t0x63,\t\t\t/* 01100011 */\n\t0x3e,\t\t\t/* 00111110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 169 0xa9 '' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0xc0,\t\t\t/* 11000000 */\n\t0xc0,\t\t\t/* 11000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 170 0xaa '' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0x06,\t\t\t/* 00000110 */\n\t0x06,\t\t\t/* 00000110 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 171 0xab '' \n\t*/\n\t0x63,\t\t\t/* 01100011 */\n\t0xe6,\t\t\t/* 11100110 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0x33,\t\t\t/* 00110011 */\n\t0x66,\t\t\t/* 01100110 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0x0f,\t\t\t/* 00001111 */\n\n\t/*\n\t* 172 0xac '' \n\t*/\n\t0x63,\t\t\t/* 01100011 */\n\t0xe6,\t\t\t/* 11100110 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0x7a,\t\t\t/* 01111010 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x6a,\t\t\t/* 01101010 */\n\t0xdf,\t\t\t/* 11011111 */\n\t0x06,\t\t\t/* 00000110 */\n\n\t/*\n\t* 173 0xad '' \n\t*/\n\t0x18,\t\t\t/* 00011000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 174 0xae '' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x33,\t\t\t/* 00110011 */\n\t0x66,\t\t\t/* 01100110 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x33,\t\t\t/* 00110011 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 175 0xaf '' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x33,\t\t\t/* 00110011 */\n\t0x66,\t\t\t/* 01100110 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 176 0xb0 '' \n\t*/\n\t0x22,\t\t\t/* 00100010 */\n\t0x88,\t\t\t/* 10001000 */\n\t0x22,\t\t\t/* 00100010 */\n\t0x88,\t\t\t/* 10001000 */\n\t0x22,\t\t\t/* 00100010 */\n\t0x88,\t\t\t/* 10001000 */\n\t0x22,\t\t\t/* 00100010 */\n\t0x88,\t\t\t/* 10001000 */\n\n\t/*\n\t* 177 0xb1 '' \n\t*/\n\t0x55,\t\t\t/* 01010101 */\n\t0xaa,\t\t\t/* 10101010 */\n\t0x55,\t\t\t/* 01010101 */\n\t0xaa,\t\t\t/* 10101010 */\n\t0x55,\t\t\t/* 01010101 */\n\t0xaa,\t\t\t/* 10101010 */\n\t0x55,\t\t\t/* 01010101 */\n\t0xaa,\t\t\t/* 10101010 */\n\n\t/*\n\t* 178 0xb2 '' \n\t*/\n\t0x77,\t\t\t/* 01110111 */\n\t0xdd,\t\t\t/* 11011101 */\n\t0x77,\t\t\t/* 01110111 */\n\t0xdd,\t\t\t/* 11011101 */\n\t0x77,\t\t\t/* 01110111 */\n\t0xdd,\t\t\t/* 11011101 */\n\t0x77,\t\t\t/* 01110111 */\n\t0xdd,\t\t\t/* 11011101 */\n\n\t/*\n\t* 179 0xb3 '' \n\t*/\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\n\t/*\n\t* 180 0xb4 '' \n\t*/\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0xf8,\t\t\t/* 11111000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\n\t/*\n\t* 181 0xb5 '' \n\t*/\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0xf8,\t\t\t/* 11111000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0xf8,\t\t\t/* 11111000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\n\t/*\n\t* 182 0xb6 '' \n\t*/\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0xf6,\t\t\t/* 11110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\n\t/*\n\t* 183 0xb7 '' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\n\t/*\n\t* 184 0xb8 '' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0xf8,\t\t\t/* 11111000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0xf8,\t\t\t/* 11111000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\n\t/*\n\t* 185 0xb9 '' \n\t*/\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0xf6,\t\t\t/* 11110110 */\n\t0x06,\t\t\t/* 00000110 */\n\t0xf6,\t\t\t/* 11110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\n\t/*\n\t* 186 0xba '' \n\t*/\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\n\t/*\n\t* 187 0xbb '' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0x06,\t\t\t/* 00000110 */\n\t0xf6,\t\t\t/* 11110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\n\t/*\n\t* 188 0xbc '' \n\t*/\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0xf6,\t\t\t/* 11110110 */\n\t0x06,\t\t\t/* 00000110 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 189 0xbd '' \n\t*/\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 190 0xbe '' \n\t*/\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0xf8,\t\t\t/* 11111000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0xf8,\t\t\t/* 11111000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 191 0xbf '' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0xf8,\t\t\t/* 11111000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\n\t/*\n\t* 192 0xc0 '' \n\t*/\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x1f,\t\t\t/* 00011111 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 193 0xc1 '' \n\t*/\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0xff,\t\t\t/* 11111111 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 194 0xc2 '' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0xff,\t\t\t/* 11111111 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\n\t/*\n\t* 195 0xc3 '' \n\t*/\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x1f,\t\t\t/* 00011111 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\n\t/*\n\t* 196 0xc4 '' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0xff,\t\t\t/* 11111111 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 197 0xc5 '' \n\t*/\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0xff,\t\t\t/* 11111111 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\n\t/*\n\t* 198 0xc6 '' \n\t*/\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x1f,\t\t\t/* 00011111 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x1f,\t\t\t/* 00011111 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\n\t/*\n\t* 199 0xc7 '' \n\t*/\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x37,\t\t\t/* 00110111 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\n\t/*\n\t* 200 0xc8 '' \n\t*/\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x37,\t\t\t/* 00110111 */\n\t0x30,\t\t\t/* 00110000 */\n\t0x3f,\t\t\t/* 00111111 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 201 0xc9 '' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x3f,\t\t\t/* 00111111 */\n\t0x30,\t\t\t/* 00110000 */\n\t0x37,\t\t\t/* 00110111 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\n\t/*\n\t* 202 0xca '' \n\t*/\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0xf7,\t\t\t/* 11110111 */\n\t0x00,\t\t\t/* 00000000 */\n\t0xff,\t\t\t/* 11111111 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 203 0xcb '' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0xff,\t\t\t/* 11111111 */\n\t0x00,\t\t\t/* 00000000 */\n\t0xf7,\t\t\t/* 11110111 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\n\t/*\n\t* 204 0xcc '' \n\t*/\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x37,\t\t\t/* 00110111 */\n\t0x30,\t\t\t/* 00110000 */\n\t0x37,\t\t\t/* 00110111 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\n\t/*\n\t* 205 0xcd '' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0xff,\t\t\t/* 11111111 */\n\t0x00,\t\t\t/* 00000000 */\n\t0xff,\t\t\t/* 11111111 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 206 0xce '' \n\t*/\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0xf7,\t\t\t/* 11110111 */\n\t0x00,\t\t\t/* 00000000 */\n\t0xf7,\t\t\t/* 11110111 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\n\t/*\n\t* 207 0xcf '' \n\t*/\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0xff,\t\t\t/* 11111111 */\n\t0x00,\t\t\t/* 00000000 */\n\t0xff,\t\t\t/* 11111111 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 208 0xd0 '' \n\t*/\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0xff,\t\t\t/* 11111111 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 209 0xd1 '' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0xff,\t\t\t/* 11111111 */\n\t0x00,\t\t\t/* 00000000 */\n\t0xff,\t\t\t/* 11111111 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\n\t/*\n\t* 210 0xd2 '' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0xff,\t\t\t/* 11111111 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\n\t/*\n\t* 211 0xd3 '' \n\t*/\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x3f,\t\t\t/* 00111111 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 212 0xd4 '' \n\t*/\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x1f,\t\t\t/* 00011111 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x1f,\t\t\t/* 00011111 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 213 0xd5 '' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x1f,\t\t\t/* 00011111 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x1f,\t\t\t/* 00011111 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\n\t/*\n\t* 214 0xd6 '' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x3f,\t\t\t/* 00111111 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\n\t/*\n\t* 215 0xd7 '' \n\t*/\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0xff,\t\t\t/* 11111111 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\n\t/*\n\t* 216 0xd8 '' \n\t*/\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0xff,\t\t\t/* 11111111 */\n\t0x18,\t\t\t/* 00011000 */\n\t0xff,\t\t\t/* 11111111 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\n\t/*\n\t* 217 0xd9 '' \n\t*/\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0xf8,\t\t\t/* 11111000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 218 0xda '' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x1f,\t\t\t/* 00011111 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\n\t/*\n\t* 219 0xdb '' \n\t*/\n\t0xff,\t\t\t/* 11111111 */\n\t0xff,\t\t\t/* 11111111 */\n\t0xff,\t\t\t/* 11111111 */\n\t0xff,\t\t\t/* 11111111 */\n\t0xff,\t\t\t/* 11111111 */\n\t0xff,\t\t\t/* 11111111 */\n\t0xff,\t\t\t/* 11111111 */\n\t0xff,\t\t\t/* 11111111 */\n\n\t/*\n\t* 220 0xdc '' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0xff,\t\t\t/* 11111111 */\n\t0xff,\t\t\t/* 11111111 */\n\t0xff,\t\t\t/* 11111111 */\n\t0xff,\t\t\t/* 11111111 */\n\n\t/*\n\t* 221 0xdd '' \n\t*/\n\t0xf0,\t\t\t/* 11110000 */\n\t0xf0,\t\t\t/* 11110000 */\n\t0xf0,\t\t\t/* 11110000 */\n\t0xf0,\t\t\t/* 11110000 */\n\t0xf0,\t\t\t/* 11110000 */\n\t0xf0,\t\t\t/* 11110000 */\n\t0xf0,\t\t\t/* 11110000 */\n\t0xf0,\t\t\t/* 11110000 */\n\n\t/*\n\t* 222 0xde '' \n\t*/\n\t0x0f,\t\t\t/* 00001111 */\n\t0x0f,\t\t\t/* 00001111 */\n\t0x0f,\t\t\t/* 00001111 */\n\t0x0f,\t\t\t/* 00001111 */\n\t0x0f,\t\t\t/* 00001111 */\n\t0x0f,\t\t\t/* 00001111 */\n\t0x0f,\t\t\t/* 00001111 */\n\t0x0f,\t\t\t/* 00001111 */\n\n\t/*\n\t* 223 0xdf '' \n\t*/\n\t0xff,\t\t\t/* 11111111 */\n\t0xff,\t\t\t/* 11111111 */\n\t0xff,\t\t\t/* 11111111 */\n\t0xff,\t\t\t/* 11111111 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 224 0xe0 '' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x76,\t\t\t/* 01110110 */\n\t0xdc,\t\t\t/* 11011100 */\n\t0xc8,\t\t\t/* 11001000 */\n\t0xdc,\t\t\t/* 11011100 */\n\t0x76,\t\t\t/* 01110110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 225 0xe1 '' \n\t*/\n\t0x78,\t\t\t/* 01111000 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0xd8,\t\t\t/* 11011000 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xcc,\t\t\t/* 11001100 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 226 0xe2 '' \n\t*/\n\t0xfe,\t\t\t/* 11111110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc0,\t\t\t/* 11000000 */\n\t0xc0,\t\t\t/* 11000000 */\n\t0xc0,\t\t\t/* 11000000 */\n\t0xc0,\t\t\t/* 11000000 */\n\t0xc0,\t\t\t/* 11000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 227 0xe3 '' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 228 0xe4 '' \n\t*/\n\t0xfe,\t\t\t/* 11111110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0x60,\t\t\t/* 01100000 */\n\t0x30,\t\t\t/* 00110000 */\n\t0x60,\t\t\t/* 01100000 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 229 0xe5 '' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0xd8,\t\t\t/* 11011000 */\n\t0xd8,\t\t\t/* 11011000 */\n\t0xd8,\t\t\t/* 11011000 */\n\t0x70,\t\t\t/* 01110000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 230 0xe6 '' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0xc0,\t\t\t/* 11000000 */\n\n\t/*\n\t* 231 0xe7 '' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x76,\t\t\t/* 01110110 */\n\t0xdc,\t\t\t/* 11011100 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 232 0xe8 '' \n\t*/\n\t0x7e,\t\t\t/* 01111110 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x7e,\t\t\t/* 01111110 */\n\n\t/*\n\t* 233 0xe9 '' \n\t*/\n\t0x38,\t\t\t/* 00111000 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0x38,\t\t\t/* 00111000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 234 0xea '' \n\t*/\n\t0x38,\t\t\t/* 00111000 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0xee,\t\t\t/* 11101110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 235 0xeb '' \n\t*/\n\t0x0e,\t\t\t/* 00001110 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x0c,\t\t\t/* 00001100 */\n\t0x3e,\t\t\t/* 00111110 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x66,\t\t\t/* 01100110 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 236 0xec '' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0xdb,\t\t\t/* 11011011 */\n\t0xdb,\t\t\t/* 11011011 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 237 0xed '' \n\t*/\n\t0x06,\t\t\t/* 00000110 */\n\t0x0c,\t\t\t/* 00001100 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0xdb,\t\t\t/* 11011011 */\n\t0xdb,\t\t\t/* 11011011 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0x60,\t\t\t/* 01100000 */\n\t0xc0,\t\t\t/* 11000000 */\n\n\t/*\n\t* 238 0xee '' \n\t*/\n\t0x1e,\t\t\t/* 00011110 */\n\t0x30,\t\t\t/* 00110000 */\n\t0x60,\t\t\t/* 01100000 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0x60,\t\t\t/* 01100000 */\n\t0x30,\t\t\t/* 00110000 */\n\t0x1e,\t\t\t/* 00011110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 239 0xef '' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0xc6,\t\t\t/* 11000110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 240 0xf0 '' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0x00,\t\t\t/* 00000000 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0x00,\t\t\t/* 00000000 */\n\t0xfe,\t\t\t/* 11111110 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 241 0xf1 '' \n\t*/\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 242 0xf2 '' \n\t*/\n\t0x30,\t\t\t/* 00110000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x0c,\t\t\t/* 00001100 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x30,\t\t\t/* 00110000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 243 0xf3 '' \n\t*/\n\t0x0c,\t\t\t/* 00001100 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x30,\t\t\t/* 00110000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x0c,\t\t\t/* 00001100 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 244 0xf4 '' \n\t*/\n\t0x0e,\t\t\t/* 00001110 */\n\t0x1b,\t\t\t/* 00011011 */\n\t0x1b,\t\t\t/* 00011011 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\n\t/*\n\t* 245 0xf5 '' \n\t*/\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0xd8,\t\t\t/* 11011000 */\n\t0xd8,\t\t\t/* 11011000 */\n\t0x70,\t\t\t/* 01110000 */\n\n\t/*\n\t* 246 0xf6 '' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x7e,\t\t\t/* 01111110 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 247 0xf7 '' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x76,\t\t\t/* 01110110 */\n\t0xdc,\t\t\t/* 11011100 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x76,\t\t\t/* 01110110 */\n\t0xdc,\t\t\t/* 11011100 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 248 0xf8 '' \n\t*/\n\t0x38,\t\t\t/* 00111000 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0x38,\t\t\t/* 00111000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 249 0xf9 '' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 250 0xfa '' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 251 0xfb '' \n\t*/\n\t0x0f,\t\t\t/* 00001111 */\n\t0x0c,\t\t\t/* 00001100 */\n\t0x0c,\t\t\t/* 00001100 */\n\t0x0c,\t\t\t/* 00001100 */\n\t0xec,\t\t\t/* 11101100 */\n\t0x6c,\t\t\t/* 01101100 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x1c,\t\t\t/* 00011100 */\n\n\t/*\n\t* 252 0xfc '' \n\t*/\n\t0x6c,\t\t\t/* 01101100 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x36,\t\t\t/* 00110110 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 253 0xfd '' \n\t*/\n\t0x78,\t\t\t/* 01111000 */\n\t0x0c,\t\t\t/* 00001100 */\n\t0x18,\t\t\t/* 00011000 */\n\t0x30,\t\t\t/* 00110000 */\n\t0x7c,\t\t\t/* 01111100 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 254 0xfe '' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x3c,\t\t\t/* 00111100 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n\t/*\n\t* 255 0xff ' ' \n\t*/\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\t0x00,\t\t\t/* 00000000 */\n\n};\n"
  },
  {
    "path": "deps/include/SDL/SDL_image.h",
    "content": "/*\n  SDL_image:  An example image loading library for use with SDL\n  Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>\n\n  This software is provided 'as-is', without any express or implied\n  warranty.  In no event will the authors be held liable for any damages\n  arising from the use of this software.\n\n  Permission is granted to anyone to use this software for any purpose,\n  including commercial applications, and to alter it and redistribute it\n  freely, subject to the following restrictions:\n\n  1. The origin of this software must not be misrepresented; you must not\n     claim that you wrote the original software. If you use this software\n     in a product, an acknowledgment in the product documentation would be\n     appreciated but is not required.\n  2. Altered source versions must be plainly marked as such, and must not be\n     misrepresented as being the original software.\n  3. This notice may not be removed or altered from any source distribution.\n*/\n\n/* A simple library to load images of various formats as SDL surfaces */\n\n#ifndef _SDL_IMAGE_H\n#define _SDL_IMAGE_H\n\n#include \"SDL.h\"\n#include \"SDL_version.h\"\n#include \"begin_code.h\"\n\n/* Set up for C function definitions, even when using C++ */\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* Printable format: \"%d.%d.%d\", MAJOR, MINOR, PATCHLEVEL\n*/\n#define SDL_IMAGE_MAJOR_VERSION\t1\n#define SDL_IMAGE_MINOR_VERSION\t2\n#define SDL_IMAGE_PATCHLEVEL\t13\n\n/* This macro can be used to fill a version structure with the compile-time\n * version of the SDL_image library.\n */\n#define SDL_IMAGE_VERSION(X)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t(X)->major = SDL_IMAGE_MAJOR_VERSION;\t\t\t\t\\\n\t(X)->minor = SDL_IMAGE_MINOR_VERSION;\t\t\t\t\\\n\t(X)->patch = SDL_IMAGE_PATCHLEVEL;\t\t\t\t\\\n}\n\n/* This function gets the version of the dynamically linked SDL_image library.\n   it should NOT be used to fill a version structure, instead you should\n   use the SDL_IMAGE_VERSION() macro.\n */\nextern DECLSPEC const SDL_version * SDLCALL IMG_Linked_Version(void);\n\ntypedef enum\n{\n    IMG_INIT_JPG = 0x00000001,\n    IMG_INIT_PNG = 0x00000002,\n    IMG_INIT_TIF = 0x00000004,\n    IMG_INIT_WEBP = 0x00000008\n} IMG_InitFlags;\n\n/* Loads dynamic libraries and prepares them for use.  Flags should be\n   one or more flags from IMG_InitFlags OR'd together.\n   It returns the flags successfully initialized, or 0 on failure.\n */\nextern DECLSPEC int SDLCALL IMG_Init(int flags);\n\n/* Unloads libraries loaded with IMG_Init */\nextern DECLSPEC void SDLCALL IMG_Quit(void);\n\n/* Load an image from an SDL data source.\n   The 'type' may be one of: \"BMP\", \"GIF\", \"PNG\", etc.\n\n   If the image format supports a transparent pixel, SDL will set the\n   colorkey for the surface.  You can enable RLE acceleration on the\n   surface afterwards by calling:\n\tSDL_SetColorKey(image, SDL_RLEACCEL, image->format->colorkey);\n */\nextern DECLSPEC SDL_Surface * SDLCALL IMG_LoadTyped_RW(SDL_RWops *src, int freesrc, char *type);\n/* Convenience functions */\nextern DECLSPEC SDL_Surface * SDLCALL IMG_Load(const char *file);\nextern DECLSPEC SDL_Surface * SDLCALL IMG_Load_RW(SDL_RWops *src, int freesrc);\n\n/* Invert the alpha of a surface for use with OpenGL\n   This function is now a no-op, and only provided for backwards compatibility.\n*/\nextern DECLSPEC int SDLCALL IMG_InvertAlpha(int on);\n\n/* Functions to detect a file type, given a seekable source */\nextern DECLSPEC int SDLCALL IMG_isICO(SDL_RWops *src);\nextern DECLSPEC int SDLCALL IMG_isCUR(SDL_RWops *src);\nextern DECLSPEC int SDLCALL IMG_isBMP(SDL_RWops *src);\nextern DECLSPEC int SDLCALL IMG_isGIF(SDL_RWops *src);\nextern DECLSPEC int SDLCALL IMG_isJPG(SDL_RWops *src);\nextern DECLSPEC int SDLCALL IMG_isLBM(SDL_RWops *src);\nextern DECLSPEC int SDLCALL IMG_isPCX(SDL_RWops *src);\nextern DECLSPEC int SDLCALL IMG_isPNG(SDL_RWops *src);\nextern DECLSPEC int SDLCALL IMG_isPNM(SDL_RWops *src);\nextern DECLSPEC int SDLCALL IMG_isTIF(SDL_RWops *src);\nextern DECLSPEC int SDLCALL IMG_isXCF(SDL_RWops *src);\nextern DECLSPEC int SDLCALL IMG_isXPM(SDL_RWops *src);\nextern DECLSPEC int SDLCALL IMG_isXV(SDL_RWops *src);\nextern DECLSPEC int SDLCALL IMG_isWEBP(SDL_RWops *src);\n\n/* Individual loading functions */\nextern DECLSPEC SDL_Surface * SDLCALL IMG_LoadICO_RW(SDL_RWops *src);\nextern DECLSPEC SDL_Surface * SDLCALL IMG_LoadCUR_RW(SDL_RWops *src);\nextern DECLSPEC SDL_Surface * SDLCALL IMG_LoadBMP_RW(SDL_RWops *src);\nextern DECLSPEC SDL_Surface * SDLCALL IMG_LoadGIF_RW(SDL_RWops *src);\nextern DECLSPEC SDL_Surface * SDLCALL IMG_LoadJPG_RW(SDL_RWops *src);\nextern DECLSPEC SDL_Surface * SDLCALL IMG_LoadLBM_RW(SDL_RWops *src);\nextern DECLSPEC SDL_Surface * SDLCALL IMG_LoadPCX_RW(SDL_RWops *src);\nextern DECLSPEC SDL_Surface * SDLCALL IMG_LoadPNG_RW(SDL_RWops *src);\nextern DECLSPEC SDL_Surface * SDLCALL IMG_LoadPNM_RW(SDL_RWops *src);\nextern DECLSPEC SDL_Surface * SDLCALL IMG_LoadTGA_RW(SDL_RWops *src);\nextern DECLSPEC SDL_Surface * SDLCALL IMG_LoadTIF_RW(SDL_RWops *src);\nextern DECLSPEC SDL_Surface * SDLCALL IMG_LoadXCF_RW(SDL_RWops *src);\nextern DECLSPEC SDL_Surface * SDLCALL IMG_LoadXPM_RW(SDL_RWops *src);\nextern DECLSPEC SDL_Surface * SDLCALL IMG_LoadXV_RW(SDL_RWops *src);\nextern DECLSPEC SDL_Surface * SDLCALL IMG_LoadWEBP_RW(SDL_RWops *src);\n\nextern DECLSPEC SDL_Surface * SDLCALL IMG_ReadXPMFromArray(char **xpm);\n\n/* We'll use SDL for reporting errors */\n#define IMG_SetError\tSDL_SetError\n#define IMG_GetError\tSDL_GetError\n\n/* Ends C function definitions when using C++ */\n#ifdef __cplusplus\n}\n#endif\n#include \"close_code.h\"\n\n#endif /* _SDL_IMAGE_H */\n"
  },
  {
    "path": "deps/include/SDL/SDL_imageFilter.h",
    "content": "/*\n\nSDL_imageFilter.h: byte-image \"filter\" routines \n\nCopyright (C) 2001-2012  Andreas Schiffler\n\nThis software is provided 'as-is', without any express or implied\nwarranty. In no event will the authors be held liable for any damages\narising from the use of this software.\n\nPermission is granted to anyone to use this software for any purpose,\nincluding commercial applications, and to alter it and redistribute it\nfreely, subject to the following restrictions:\n\n1. The origin of this software must not be misrepresented; you must not\nclaim that you wrote the original software. If you use this software\nin a product, an acknowledgment in the product documentation would be\nappreciated but is not required.\n\n2. Altered source versions must be plainly marked as such, and must not be\nmisrepresented as being the original software.\n\n3. This notice may not be removed or altered from any source\ndistribution.\n\nAndreas Schiffler -- aschiffler at ferzkopp dot net\n\n*/\n\n#ifndef _SDL_imageFilter_h\n#define _SDL_imageFilter_h\n\n/* Set up for C function definitions, even when using C++ */\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n\t/* ---- Function Prototypes */\n\n#ifdef _MSC_VER\n#  if defined(DLL_EXPORT) && !defined(LIBSDL_GFX_DLL_IMPORT)\n#    define SDL_IMAGEFILTER_SCOPE __declspec(dllexport)\n#  else\n#    ifdef LIBSDL_GFX_DLL_IMPORT\n#      define SDL_IMAGEFILTER_SCOPE __declspec(dllimport)\n#    endif\n#  endif\n#endif\n#ifndef SDL_IMAGEFILTER_SCOPE\n#  define SDL_IMAGEFILTER_SCOPE extern\n#endif\n\n\t/* Comments:                                                                           */\n\t/*  1.) MMX functions work best if all data blocks are aligned on a 32 bytes boundary. */\n\t/*  2.) Data that is not within an 8 byte boundary is processed using the C routine.   */\n\t/*  3.) Convolution routines do not have C routines at this time.                      */\n\n\t// Detect MMX capability in CPU\n\tSDL_IMAGEFILTER_SCOPE int SDL_imageFilterMMXdetect(void);\n\n\t// Force use of MMX off (or turn possible use back on)\n\tSDL_IMAGEFILTER_SCOPE void SDL_imageFilterMMXoff(void);\n\tSDL_IMAGEFILTER_SCOPE void SDL_imageFilterMMXon(void);\n\n\t//\n\t// All routines return:\n\t//   0   OK\n\t//  -1   Error (internal error, parameter error)\n\t//\n\n\t//  SDL_imageFilterAdd: D = saturation255(S1 + S2)\n\tSDL_IMAGEFILTER_SCOPE int SDL_imageFilterAdd(unsigned char *Src1, unsigned char *Src2, unsigned char *Dest, unsigned int length);\n\n\t//  SDL_imageFilterMean: D = S1/2 + S2/2\n\tSDL_IMAGEFILTER_SCOPE int SDL_imageFilterMean(unsigned char *Src1, unsigned char *Src2, unsigned char *Dest, unsigned int length);\n\n\t//  SDL_imageFilterSub: D = saturation0(S1 - S2)\n\tSDL_IMAGEFILTER_SCOPE int SDL_imageFilterSub(unsigned char *Src1, unsigned char *Src2, unsigned char *Dest, unsigned int length);\n\n\t//  SDL_imageFilterAbsDiff: D = | S1 - S2 |\n\tSDL_IMAGEFILTER_SCOPE int SDL_imageFilterAbsDiff(unsigned char *Src1, unsigned char *Src2, unsigned char *Dest, unsigned int length);\n\n\t//  SDL_imageFilterMult: D = saturation(S1 * S2)\n\tSDL_IMAGEFILTER_SCOPE int SDL_imageFilterMult(unsigned char *Src1, unsigned char *Src2, unsigned char *Dest, unsigned int length);\n\n\t//  SDL_imageFilterMultNor: D = S1 * S2   (non-MMX)\n\tSDL_IMAGEFILTER_SCOPE int SDL_imageFilterMultNor(unsigned char *Src1, unsigned char *Src2, unsigned char *Dest, unsigned int length);\n\n\t//  SDL_imageFilterMultDivby2: D = saturation255(S1/2 * S2)\n\tSDL_IMAGEFILTER_SCOPE int SDL_imageFilterMultDivby2(unsigned char *Src1, unsigned char *Src2, unsigned char *Dest,\n\t\tunsigned int length);\n\n\t//  SDL_imageFilterMultDivby4: D = saturation255(S1/2 * S2/2)\n\tSDL_IMAGEFILTER_SCOPE int SDL_imageFilterMultDivby4(unsigned char *Src1, unsigned char *Src2, unsigned char *Dest,\n\t\tunsigned int length);\n\n\t//  SDL_imageFilterBitAnd: D = S1 & S2\n\tSDL_IMAGEFILTER_SCOPE int SDL_imageFilterBitAnd(unsigned char *Src1, unsigned char *Src2, unsigned char *Dest, unsigned int length);\n\n\t//  SDL_imageFilterBitOr: D = S1 | S2\n\tSDL_IMAGEFILTER_SCOPE int SDL_imageFilterBitOr(unsigned char *Src1, unsigned char *Src2, unsigned char *Dest, unsigned int length);\n\n\t//  SDL_imageFilterDiv: D = S1 / S2   (non-MMX)\n\tSDL_IMAGEFILTER_SCOPE int SDL_imageFilterDiv(unsigned char *Src1, unsigned char *Src2, unsigned char *Dest, unsigned int length);\n\n\t//  SDL_imageFilterBitNegation: D = !S\n\tSDL_IMAGEFILTER_SCOPE int SDL_imageFilterBitNegation(unsigned char *Src1, unsigned char *Dest, unsigned int length);\n\n\t//  SDL_imageFilterAddByte: D = saturation255(S + C)\n\tSDL_IMAGEFILTER_SCOPE int SDL_imageFilterAddByte(unsigned char *Src1, unsigned char *Dest, unsigned int length, unsigned char C);\n\n\t//  SDL_imageFilterAddUint: D = saturation255(S + (uint)C)\n\tSDL_IMAGEFILTER_SCOPE int SDL_imageFilterAddUint(unsigned char *Src1, unsigned char *Dest, unsigned int length, unsigned int C);\n\n\t//  SDL_imageFilterAddByteToHalf: D = saturation255(S/2 + C)\n\tSDL_IMAGEFILTER_SCOPE int SDL_imageFilterAddByteToHalf(unsigned char *Src1, unsigned char *Dest, unsigned int length,\n\t\tunsigned char C);\n\n\t//  SDL_imageFilterSubByte: D = saturation0(S - C)\n\tSDL_IMAGEFILTER_SCOPE int SDL_imageFilterSubByte(unsigned char *Src1, unsigned char *Dest, unsigned int length, unsigned char C);\n\n\t//  SDL_imageFilterSubUint: D = saturation0(S - (uint)C)\n\tSDL_IMAGEFILTER_SCOPE int SDL_imageFilterSubUint(unsigned char *Src1, unsigned char *Dest, unsigned int length, unsigned int C);\n\n\t//  SDL_imageFilterShiftRight: D = saturation0(S >> N)\n\tSDL_IMAGEFILTER_SCOPE int SDL_imageFilterShiftRight(unsigned char *Src1, unsigned char *Dest, unsigned int length, unsigned char N);\n\n\t//  SDL_imageFilterShiftRightUint: D = saturation0((uint)S >> N)\n\tSDL_IMAGEFILTER_SCOPE int SDL_imageFilterShiftRightUint(unsigned char *Src1, unsigned char *Dest, unsigned int length, unsigned char N);\n\n\t//  SDL_imageFilterMultByByte: D = saturation255(S * C)\n\tSDL_IMAGEFILTER_SCOPE int SDL_imageFilterMultByByte(unsigned char *Src1, unsigned char *Dest, unsigned int length, unsigned char C);\n\n\t//  SDL_imageFilterShiftRightAndMultByByte: D = saturation255((S >> N) * C)\n\tSDL_IMAGEFILTER_SCOPE int SDL_imageFilterShiftRightAndMultByByte(unsigned char *Src1, unsigned char *Dest, unsigned int length,\n\t\tunsigned char N, unsigned char C);\n\n\t//  SDL_imageFilterShiftLeftByte: D = (S << N)\n\tSDL_IMAGEFILTER_SCOPE int SDL_imageFilterShiftLeftByte(unsigned char *Src1, unsigned char *Dest, unsigned int length,\n\t\tunsigned char N);\n\n\t//  SDL_imageFilterShiftLeftUint: D = ((uint)S << N)\n\tSDL_IMAGEFILTER_SCOPE int SDL_imageFilterShiftLeftUint(unsigned char *Src1, unsigned char *Dest, unsigned int length,\n\t\tunsigned char N);\n\n\t//  SDL_imageFilterShiftLeft: D = saturation255(S << N)\n\tSDL_IMAGEFILTER_SCOPE int SDL_imageFilterShiftLeft(unsigned char *Src1, unsigned char *Dest, unsigned int length, unsigned char N);\n\n\t//  SDL_imageFilterBinarizeUsingThreshold: D = S >= T ? 255:0\n\tSDL_IMAGEFILTER_SCOPE int SDL_imageFilterBinarizeUsingThreshold(unsigned char *Src1, unsigned char *Dest, unsigned int length,\n\t\tunsigned char T);\n\n\t//  SDL_imageFilterClipToRange: D = (S >= Tmin) & (S <= Tmax) 255:0\n\tSDL_IMAGEFILTER_SCOPE int SDL_imageFilterClipToRange(unsigned char *Src1, unsigned char *Dest, unsigned int length,\n\t\tunsigned char Tmin, unsigned char Tmax);\n\n\t//  SDL_imageFilterNormalizeLinear: D = saturation255((Nmax - Nmin)/(Cmax - Cmin)*(S - Cmin) + Nmin)\n\tSDL_IMAGEFILTER_SCOPE int SDL_imageFilterNormalizeLinear(unsigned char *Src, unsigned char *Dest, unsigned int length, int Cmin,\n\t\tint Cmax, int Nmin, int Nmax);\n\n\t/* !!! NO C-ROUTINE FOR THESE FUNCTIONS YET !!! */\n\n\t//  SDL_imageFilterConvolveKernel3x3Divide: Dij = saturation0and255( ... )\n\tSDL_IMAGEFILTER_SCOPE int SDL_imageFilterConvolveKernel3x3Divide(unsigned char *Src, unsigned char *Dest, int rows,\n\t\tint columns, signed short *Kernel, unsigned char Divisor);\n\n\t//  SDL_imageFilterConvolveKernel5x5Divide: Dij = saturation0and255( ... )\n\tSDL_IMAGEFILTER_SCOPE int SDL_imageFilterConvolveKernel5x5Divide(unsigned char *Src, unsigned char *Dest, int rows,\n\t\tint columns, signed short *Kernel, unsigned char Divisor);\n\n\t//  SDL_imageFilterConvolveKernel7x7Divide: Dij = saturation0and255( ... )\n\tSDL_IMAGEFILTER_SCOPE int SDL_imageFilterConvolveKernel7x7Divide(unsigned char *Src, unsigned char *Dest, int rows,\n\t\tint columns, signed short *Kernel, unsigned char Divisor);\n\n\t//  SDL_imageFilterConvolveKernel9x9Divide: Dij = saturation0and255( ... )\n\tSDL_IMAGEFILTER_SCOPE int SDL_imageFilterConvolveKernel9x9Divide(unsigned char *Src, unsigned char *Dest, int rows,\n\t\tint columns, signed short *Kernel, unsigned char Divisor);\n\n\t//  SDL_imageFilterConvolveKernel3x3ShiftRight: Dij = saturation0and255( ... )\n\tSDL_IMAGEFILTER_SCOPE int SDL_imageFilterConvolveKernel3x3ShiftRight(unsigned char *Src, unsigned char *Dest, int rows,\n\t\tint columns, signed short *Kernel,\n\t\tunsigned char NRightShift);\n\n\t//  SDL_imageFilterConvolveKernel5x5ShiftRight: Dij = saturation0and255( ... )\n\tSDL_IMAGEFILTER_SCOPE int SDL_imageFilterConvolveKernel5x5ShiftRight(unsigned char *Src, unsigned char *Dest, int rows,\n\t\tint columns, signed short *Kernel,\n\t\tunsigned char NRightShift);\n\n\t//  SDL_imageFilterConvolveKernel7x7ShiftRight: Dij = saturation0and255( ... )\n\tSDL_IMAGEFILTER_SCOPE int SDL_imageFilterConvolveKernel7x7ShiftRight(unsigned char *Src, unsigned char *Dest, int rows,\n\t\tint columns, signed short *Kernel,\n\t\tunsigned char NRightShift);\n\n\t//  SDL_imageFilterConvolveKernel9x9ShiftRight: Dij = saturation0and255( ... )\n\tSDL_IMAGEFILTER_SCOPE int SDL_imageFilterConvolveKernel9x9ShiftRight(unsigned char *Src, unsigned char *Dest, int rows,\n\t\tint columns, signed short *Kernel,\n\t\tunsigned char NRightShift);\n\n\t//  SDL_imageFilterSobelX: Dij = saturation255( ... )\n\tSDL_IMAGEFILTER_SCOPE int SDL_imageFilterSobelX(unsigned char *Src, unsigned char *Dest, int rows, int columns);\n\n\t//  SDL_imageFilterSobelXShiftRight: Dij = saturation255( ... )\n\tSDL_IMAGEFILTER_SCOPE int SDL_imageFilterSobelXShiftRight(unsigned char *Src, unsigned char *Dest, int rows, int columns,\n\t\tunsigned char NRightShift);\n\n\t// Align/restore stack to 32 byte boundary -- Functionality untested! --\n\tSDL_IMAGEFILTER_SCOPE void SDL_imageFilterAlignStack(void);\n\tSDL_IMAGEFILTER_SCOPE void SDL_imageFilterRestoreStack(void);\n\n\t/* Ends C function definitions when using C++ */\n#ifdef __cplusplus\n}\n#endif\n\n#endif\t\t\t\t/* _SDL_imageFilter_h */\n"
  },
  {
    "path": "deps/include/SDL/SDL_joystick.h",
    "content": "/*\n    SDL - Simple DirectMedia Layer\n    Copyright (C) 1997-2012 Sam Lantinga\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Lesser General Public\n    License as published by the Free Software Foundation; either\n    version 2.1 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public\n    License along with this library; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n\n    Sam Lantinga\n    slouken@libsdl.org\n*/\n\n/** @file SDL_joystick.h\n *  Include file for SDL joystick event handling\n */\n\n#ifndef _SDL_joystick_h\n#define _SDL_joystick_h\n\n#include \"SDL_stdinc.h\"\n#include \"SDL_error.h\"\n\n#include \"begin_code.h\"\n/* Set up for C function definitions, even when using C++ */\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/** @file SDL_joystick.h\n *  @note In order to use these functions, SDL_Init() must have been called\n *        with the SDL_INIT_JOYSTICK flag.  This causes SDL to scan the system\n *        for joysticks, and load appropriate drivers.\n */\n\n/** The joystick structure used to identify an SDL joystick */\nstruct _SDL_Joystick;\ntypedef struct _SDL_Joystick SDL_Joystick;\n\n/* Function prototypes */\n/**\n * Count the number of joysticks attached to the system\n */\nextern DECLSPEC int SDLCALL SDL_NumJoysticks(void);\n\n/**\n * Get the implementation dependent name of a joystick.\n *\n * This can be called before any joysticks are opened.\n * If no name can be found, this function returns NULL.\n */\nextern DECLSPEC const char * SDLCALL SDL_JoystickName(int device_index);\n\n/**\n * Open a joystick for use.\n *\n * @param[in] device_index\n * The index passed as an argument refers to\n * the N'th joystick on the system.  This index is the value which will\n * identify this joystick in future joystick events.\n *\n * @return This function returns a joystick identifier, or NULL if an error occurred.\n */\nextern DECLSPEC SDL_Joystick * SDLCALL SDL_JoystickOpen(int device_index);\n\n/**\n * Returns 1 if the joystick has been opened, or 0 if it has not.\n */\nextern DECLSPEC int SDLCALL SDL_JoystickOpened(int device_index);\n\n/**\n * Get the device index of an opened joystick.\n */\nextern DECLSPEC int SDLCALL SDL_JoystickIndex(SDL_Joystick *joystick);\n\n/**\n * Get the number of general axis controls on a joystick\n */\nextern DECLSPEC int SDLCALL SDL_JoystickNumAxes(SDL_Joystick *joystick);\n\n/**\n * Get the number of trackballs on a joystick\n *\n * Joystick trackballs have only relative motion events associated\n * with them and their state cannot be polled.\n */\nextern DECLSPEC int SDLCALL SDL_JoystickNumBalls(SDL_Joystick *joystick);\n\n/**\n * Get the number of POV hats on a joystick\n */\nextern DECLSPEC int SDLCALL SDL_JoystickNumHats(SDL_Joystick *joystick);\n\n/**\n * Get the number of buttons on a joystick\n */\nextern DECLSPEC int SDLCALL SDL_JoystickNumButtons(SDL_Joystick *joystick);\n\n/**\n * Update the current state of the open joysticks.\n *\n * This is called automatically by the event loop if any joystick\n * events are enabled.\n */\nextern DECLSPEC void SDLCALL SDL_JoystickUpdate(void);\n\n/**\n * Enable/disable joystick event polling.\n *\n * If joystick events are disabled, you must call SDL_JoystickUpdate()\n * yourself and check the state of the joystick when you want joystick\n * information.\n *\n * @param[in] state The state can be one of SDL_QUERY, SDL_ENABLE or SDL_IGNORE.\n */\nextern DECLSPEC int SDLCALL SDL_JoystickEventState(int state);\n\n/**\n * Get the current state of an axis control on a joystick\n *\n * @param[in] axis The axis indices start at index 0.\n *\n * @return The state is a value ranging from -32768 to 32767.\n */\nextern DECLSPEC Sint16 SDLCALL SDL_JoystickGetAxis(SDL_Joystick *joystick, int axis);\n\n/**\n *  @name Hat Positions\n *  The return value of SDL_JoystickGetHat() is one of the following positions:\n */\n/*@{*/\n#define SDL_HAT_CENTERED\t0x00\n#define SDL_HAT_UP\t\t0x01\n#define SDL_HAT_RIGHT\t\t0x02\n#define SDL_HAT_DOWN\t\t0x04\n#define SDL_HAT_LEFT\t\t0x08\n#define SDL_HAT_RIGHTUP\t\t(SDL_HAT_RIGHT|SDL_HAT_UP)\n#define SDL_HAT_RIGHTDOWN\t(SDL_HAT_RIGHT|SDL_HAT_DOWN)\n#define SDL_HAT_LEFTUP\t\t(SDL_HAT_LEFT|SDL_HAT_UP)\n#define SDL_HAT_LEFTDOWN\t(SDL_HAT_LEFT|SDL_HAT_DOWN)\n/*@}*/\n\n/** \n *  Get the current state of a POV hat on a joystick\n *\n *  @param[in] hat The hat indices start at index 0.\n */\nextern DECLSPEC Uint8 SDLCALL SDL_JoystickGetHat(SDL_Joystick *joystick, int hat);\n\n/**\n * Get the ball axis change since the last poll\n *\n * @param[in] ball The ball indices start at index 0.\n *\n * @return This returns 0, or -1 if you passed it invalid parameters.\n */\nextern DECLSPEC int SDLCALL SDL_JoystickGetBall(SDL_Joystick *joystick, int ball, int *dx, int *dy);\n\n/**\n * Get the current state of a button on a joystick\n *\n * @param[in] button The button indices start at index 0.\n */\nextern DECLSPEC Uint8 SDLCALL SDL_JoystickGetButton(SDL_Joystick *joystick, int button);\n\n/**\n * Close a joystick previously opened with SDL_JoystickOpen()\n */\nextern DECLSPEC void SDLCALL SDL_JoystickClose(SDL_Joystick *joystick);\n\n\n/* Ends C function definitions when using C++ */\n#ifdef __cplusplus\n}\n#endif\n#include \"close_code.h\"\n\n#endif /* _SDL_joystick_h */\n"
  },
  {
    "path": "deps/include/SDL/SDL_keyboard.h",
    "content": "/*\n    SDL - Simple DirectMedia Layer\n    Copyright (C) 1997-2012 Sam Lantinga\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Lesser General Public\n    License as published by the Free Software Foundation; either\n    version 2.1 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public\n    License along with this library; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n\n    Sam Lantinga\n    slouken@libsdl.org\n*/\n\n/** @file SDL_keyboard.h\n *  Include file for SDL keyboard event handling\n */\n\n#ifndef _SDL_keyboard_h\n#define _SDL_keyboard_h\n\n#include \"SDL_stdinc.h\"\n#include \"SDL_error.h\"\n#include \"SDL_keysym.h\"\n\n#include \"begin_code.h\"\n/* Set up for C function definitions, even when using C++ */\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/** Keysym structure\n *\n *  - The scancode is hardware dependent, and should not be used by general\n *    applications.  If no hardware scancode is available, it will be 0.\n *\n *  - The 'unicode' translated character is only available when character\n *    translation is enabled by the SDL_EnableUNICODE() API.  If non-zero,\n *    this is a UNICODE character corresponding to the keypress.  If the\n *    high 9 bits of the character are 0, then this maps to the equivalent\n *    ASCII character:\n *      @code\n *\tchar ch;\n *\tif ( (keysym.unicode & 0xFF80) == 0 ) {\n *\t\tch = keysym.unicode & 0x7F;\n *\t} else {\n *\t\tAn international character..\n *\t}\n *      @endcode\n */\ntypedef struct SDL_keysym {\n\tUint8 scancode;\t\t\t/**< hardware specific scancode */\n\tSDLKey sym;\t\t\t/**< SDL virtual keysym */\n\tSDLMod mod;\t\t\t/**< current key modifiers */\n\tUint16 unicode;\t\t\t/**< translated character */\n} SDL_keysym;\n\n/** This is the mask which refers to all hotkey bindings */\n#define SDL_ALL_HOTKEYS\t\t0xFFFFFFFF\n\n/* Function prototypes */\n/**\n * Enable/Disable UNICODE translation of keyboard input.\n *\n * This translation has some overhead, so translation defaults off.\n *\n * @param[in] enable\n * If 'enable' is 1, translation is enabled.\n * If 'enable' is 0, translation is disabled.\n * If 'enable' is -1, the translation state is not changed.\n *\n * @return It returns the previous state of keyboard translation.\n */\nextern DECLSPEC int SDLCALL SDL_EnableUNICODE(int enable);\n\n#define SDL_DEFAULT_REPEAT_DELAY\t500\n#define SDL_DEFAULT_REPEAT_INTERVAL\t30\n/**\n * Enable/Disable keyboard repeat.  Keyboard repeat defaults to off.\n *\n *  @param[in] delay\n *  'delay' is the initial delay in ms between the time when a key is\n *  pressed, and keyboard repeat begins.\n *\n *  @param[in] interval\n *  'interval' is the time in ms between keyboard repeat events.\n *\n *  If 'delay' is set to 0, keyboard repeat is disabled.\n */\nextern DECLSPEC int SDLCALL SDL_EnableKeyRepeat(int delay, int interval);\nextern DECLSPEC void SDLCALL SDL_GetKeyRepeat(int *delay, int *interval);\n\n/**\n * Get a snapshot of the current state of the keyboard.\n * Returns an array of keystates, indexed by the SDLK_* syms.\n * Usage:\n *\t@code\n * \tUint8 *keystate = SDL_GetKeyState(NULL);\n *\tif ( keystate[SDLK_RETURN] ) //... \\<RETURN> is pressed.\n *\t@endcode\n */\nextern DECLSPEC Uint8 * SDLCALL SDL_GetKeyState(int *numkeys);\n\n/**\n * Get the current key modifier state\n */\nextern DECLSPEC SDLMod SDLCALL SDL_GetModState(void);\n\n/**\n * Set the current key modifier state.\n * This does not change the keyboard state, only the key modifier flags.\n */\nextern DECLSPEC void SDLCALL SDL_SetModState(SDLMod modstate);\n\n/**\n * Get the name of an SDL virtual keysym\n */\nextern DECLSPEC char * SDLCALL SDL_GetKeyName(SDLKey key);\n\n\n/* Ends C function definitions when using C++ */\n#ifdef __cplusplus\n}\n#endif\n#include \"close_code.h\"\n\n#endif /* _SDL_keyboard_h */\n"
  },
  {
    "path": "deps/include/SDL/SDL_keysym.h",
    "content": "/*\n    SDL - Simple DirectMedia Layer\n    Copyright (C) 1997-2012 Sam Lantinga\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Lesser General Public\n    License as published by the Free Software Foundation; either\n    version 2.1 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public\n    License along with this library; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n\n    Sam Lantinga\n    slouken@libsdl.org\n*/\n\n#ifndef _SDL_keysym_h\n#define _SDL_keysym_h\n\n/** What we really want is a mapping of every raw key on the keyboard.\n *  To support international keyboards, we use the range 0xA1 - 0xFF\n *  as international virtual keycodes.  We'll follow in the footsteps of X11...\n *  @brief The names of the keys\n */\ntypedef enum {\n        /** @name ASCII mapped keysyms\n         *  The keyboard syms have been cleverly chosen to map to ASCII\n         */\n        /*@{*/\n\tSDLK_UNKNOWN\t\t= 0,\n\tSDLK_FIRST\t\t= 0,\n\tSDLK_BACKSPACE\t\t= 8,\n\tSDLK_TAB\t\t= 9,\n\tSDLK_CLEAR\t\t= 12,\n\tSDLK_RETURN\t\t= 13,\n\tSDLK_PAUSE\t\t= 19,\n\tSDLK_ESCAPE\t\t= 27,\n\tSDLK_SPACE\t\t= 32,\n\tSDLK_EXCLAIM\t\t= 33,\n\tSDLK_QUOTEDBL\t\t= 34,\n\tSDLK_HASH\t\t= 35,\n\tSDLK_DOLLAR\t\t= 36,\n\tSDLK_AMPERSAND\t\t= 38,\n\tSDLK_QUOTE\t\t= 39,\n\tSDLK_LEFTPAREN\t\t= 40,\n\tSDLK_RIGHTPAREN\t\t= 41,\n\tSDLK_ASTERISK\t\t= 42,\n\tSDLK_PLUS\t\t= 43,\n\tSDLK_COMMA\t\t= 44,\n\tSDLK_MINUS\t\t= 45,\n\tSDLK_PERIOD\t\t= 46,\n\tSDLK_SLASH\t\t= 47,\n\tSDLK_0\t\t\t= 48,\n\tSDLK_1\t\t\t= 49,\n\tSDLK_2\t\t\t= 50,\n\tSDLK_3\t\t\t= 51,\n\tSDLK_4\t\t\t= 52,\n\tSDLK_5\t\t\t= 53,\n\tSDLK_6\t\t\t= 54,\n\tSDLK_7\t\t\t= 55,\n\tSDLK_8\t\t\t= 56,\n\tSDLK_9\t\t\t= 57,\n\tSDLK_COLON\t\t= 58,\n\tSDLK_SEMICOLON\t\t= 59,\n\tSDLK_LESS\t\t= 60,\n\tSDLK_EQUALS\t\t= 61,\n\tSDLK_GREATER\t\t= 62,\n\tSDLK_QUESTION\t\t= 63,\n\tSDLK_AT\t\t\t= 64,\n\t/* \n\t   Skip uppercase letters\n\t */\n\tSDLK_LEFTBRACKET\t= 91,\n\tSDLK_BACKSLASH\t\t= 92,\n\tSDLK_RIGHTBRACKET\t= 93,\n\tSDLK_CARET\t\t= 94,\n\tSDLK_UNDERSCORE\t\t= 95,\n\tSDLK_BACKQUOTE\t\t= 96,\n\tSDLK_a\t\t\t= 97,\n\tSDLK_b\t\t\t= 98,\n\tSDLK_c\t\t\t= 99,\n\tSDLK_d\t\t\t= 100,\n\tSDLK_e\t\t\t= 101,\n\tSDLK_f\t\t\t= 102,\n\tSDLK_g\t\t\t= 103,\n\tSDLK_h\t\t\t= 104,\n\tSDLK_i\t\t\t= 105,\n\tSDLK_j\t\t\t= 106,\n\tSDLK_k\t\t\t= 107,\n\tSDLK_l\t\t\t= 108,\n\tSDLK_m\t\t\t= 109,\n\tSDLK_n\t\t\t= 110,\n\tSDLK_o\t\t\t= 111,\n\tSDLK_p\t\t\t= 112,\n\tSDLK_q\t\t\t= 113,\n\tSDLK_r\t\t\t= 114,\n\tSDLK_s\t\t\t= 115,\n\tSDLK_t\t\t\t= 116,\n\tSDLK_u\t\t\t= 117,\n\tSDLK_v\t\t\t= 118,\n\tSDLK_w\t\t\t= 119,\n\tSDLK_x\t\t\t= 120,\n\tSDLK_y\t\t\t= 121,\n\tSDLK_z\t\t\t= 122,\n\tSDLK_DELETE\t\t= 127,\n\t/* End of ASCII mapped keysyms */\n        /*@}*/\n\n\t/** @name International keyboard syms */\n        /*@{*/\n\tSDLK_WORLD_0\t\t= 160,\t\t/* 0xA0 */\n\tSDLK_WORLD_1\t\t= 161,\n\tSDLK_WORLD_2\t\t= 162,\n\tSDLK_WORLD_3\t\t= 163,\n\tSDLK_WORLD_4\t\t= 164,\n\tSDLK_WORLD_5\t\t= 165,\n\tSDLK_WORLD_6\t\t= 166,\n\tSDLK_WORLD_7\t\t= 167,\n\tSDLK_WORLD_8\t\t= 168,\n\tSDLK_WORLD_9\t\t= 169,\n\tSDLK_WORLD_10\t\t= 170,\n\tSDLK_WORLD_11\t\t= 171,\n\tSDLK_WORLD_12\t\t= 172,\n\tSDLK_WORLD_13\t\t= 173,\n\tSDLK_WORLD_14\t\t= 174,\n\tSDLK_WORLD_15\t\t= 175,\n\tSDLK_WORLD_16\t\t= 176,\n\tSDLK_WORLD_17\t\t= 177,\n\tSDLK_WORLD_18\t\t= 178,\n\tSDLK_WORLD_19\t\t= 179,\n\tSDLK_WORLD_20\t\t= 180,\n\tSDLK_WORLD_21\t\t= 181,\n\tSDLK_WORLD_22\t\t= 182,\n\tSDLK_WORLD_23\t\t= 183,\n\tSDLK_WORLD_24\t\t= 184,\n\tSDLK_WORLD_25\t\t= 185,\n\tSDLK_WORLD_26\t\t= 186,\n\tSDLK_WORLD_27\t\t= 187,\n\tSDLK_WORLD_28\t\t= 188,\n\tSDLK_WORLD_29\t\t= 189,\n\tSDLK_WORLD_30\t\t= 190,\n\tSDLK_WORLD_31\t\t= 191,\n\tSDLK_WORLD_32\t\t= 192,\n\tSDLK_WORLD_33\t\t= 193,\n\tSDLK_WORLD_34\t\t= 194,\n\tSDLK_WORLD_35\t\t= 195,\n\tSDLK_WORLD_36\t\t= 196,\n\tSDLK_WORLD_37\t\t= 197,\n\tSDLK_WORLD_38\t\t= 198,\n\tSDLK_WORLD_39\t\t= 199,\n\tSDLK_WORLD_40\t\t= 200,\n\tSDLK_WORLD_41\t\t= 201,\n\tSDLK_WORLD_42\t\t= 202,\n\tSDLK_WORLD_43\t\t= 203,\n\tSDLK_WORLD_44\t\t= 204,\n\tSDLK_WORLD_45\t\t= 205,\n\tSDLK_WORLD_46\t\t= 206,\n\tSDLK_WORLD_47\t\t= 207,\n\tSDLK_WORLD_48\t\t= 208,\n\tSDLK_WORLD_49\t\t= 209,\n\tSDLK_WORLD_50\t\t= 210,\n\tSDLK_WORLD_51\t\t= 211,\n\tSDLK_WORLD_52\t\t= 212,\n\tSDLK_WORLD_53\t\t= 213,\n\tSDLK_WORLD_54\t\t= 214,\n\tSDLK_WORLD_55\t\t= 215,\n\tSDLK_WORLD_56\t\t= 216,\n\tSDLK_WORLD_57\t\t= 217,\n\tSDLK_WORLD_58\t\t= 218,\n\tSDLK_WORLD_59\t\t= 219,\n\tSDLK_WORLD_60\t\t= 220,\n\tSDLK_WORLD_61\t\t= 221,\n\tSDLK_WORLD_62\t\t= 222,\n\tSDLK_WORLD_63\t\t= 223,\n\tSDLK_WORLD_64\t\t= 224,\n\tSDLK_WORLD_65\t\t= 225,\n\tSDLK_WORLD_66\t\t= 226,\n\tSDLK_WORLD_67\t\t= 227,\n\tSDLK_WORLD_68\t\t= 228,\n\tSDLK_WORLD_69\t\t= 229,\n\tSDLK_WORLD_70\t\t= 230,\n\tSDLK_WORLD_71\t\t= 231,\n\tSDLK_WORLD_72\t\t= 232,\n\tSDLK_WORLD_73\t\t= 233,\n\tSDLK_WORLD_74\t\t= 234,\n\tSDLK_WORLD_75\t\t= 235,\n\tSDLK_WORLD_76\t\t= 236,\n\tSDLK_WORLD_77\t\t= 237,\n\tSDLK_WORLD_78\t\t= 238,\n\tSDLK_WORLD_79\t\t= 239,\n\tSDLK_WORLD_80\t\t= 240,\n\tSDLK_WORLD_81\t\t= 241,\n\tSDLK_WORLD_82\t\t= 242,\n\tSDLK_WORLD_83\t\t= 243,\n\tSDLK_WORLD_84\t\t= 244,\n\tSDLK_WORLD_85\t\t= 245,\n\tSDLK_WORLD_86\t\t= 246,\n\tSDLK_WORLD_87\t\t= 247,\n\tSDLK_WORLD_88\t\t= 248,\n\tSDLK_WORLD_89\t\t= 249,\n\tSDLK_WORLD_90\t\t= 250,\n\tSDLK_WORLD_91\t\t= 251,\n\tSDLK_WORLD_92\t\t= 252,\n\tSDLK_WORLD_93\t\t= 253,\n\tSDLK_WORLD_94\t\t= 254,\n\tSDLK_WORLD_95\t\t= 255,\t\t/* 0xFF */\n        /*@}*/\n\n\t/** @name Numeric keypad */\n        /*@{*/\n\tSDLK_KP0\t\t= 256,\n\tSDLK_KP1\t\t= 257,\n\tSDLK_KP2\t\t= 258,\n\tSDLK_KP3\t\t= 259,\n\tSDLK_KP4\t\t= 260,\n\tSDLK_KP5\t\t= 261,\n\tSDLK_KP6\t\t= 262,\n\tSDLK_KP7\t\t= 263,\n\tSDLK_KP8\t\t= 264,\n\tSDLK_KP9\t\t= 265,\n\tSDLK_KP_PERIOD\t\t= 266,\n\tSDLK_KP_DIVIDE\t\t= 267,\n\tSDLK_KP_MULTIPLY\t= 268,\n\tSDLK_KP_MINUS\t\t= 269,\n\tSDLK_KP_PLUS\t\t= 270,\n\tSDLK_KP_ENTER\t\t= 271,\n\tSDLK_KP_EQUALS\t\t= 272,\n        /*@}*/\n\n\t/** @name Arrows + Home/End pad */\n        /*@{*/\n\tSDLK_UP\t\t\t= 273,\n\tSDLK_DOWN\t\t= 274,\n\tSDLK_RIGHT\t\t= 275,\n\tSDLK_LEFT\t\t= 276,\n\tSDLK_INSERT\t\t= 277,\n\tSDLK_HOME\t\t= 278,\n\tSDLK_END\t\t= 279,\n\tSDLK_PAGEUP\t\t= 280,\n\tSDLK_PAGEDOWN\t\t= 281,\n        /*@}*/\n\n\t/** @name Function keys */\n        /*@{*/\n\tSDLK_F1\t\t\t= 282,\n\tSDLK_F2\t\t\t= 283,\n\tSDLK_F3\t\t\t= 284,\n\tSDLK_F4\t\t\t= 285,\n\tSDLK_F5\t\t\t= 286,\n\tSDLK_F6\t\t\t= 287,\n\tSDLK_F7\t\t\t= 288,\n\tSDLK_F8\t\t\t= 289,\n\tSDLK_F9\t\t\t= 290,\n\tSDLK_F10\t\t= 291,\n\tSDLK_F11\t\t= 292,\n\tSDLK_F12\t\t= 293,\n\tSDLK_F13\t\t= 294,\n\tSDLK_F14\t\t= 295,\n\tSDLK_F15\t\t= 296,\n        /*@}*/\n\n\t/** @name Key state modifier keys */\n        /*@{*/\n\tSDLK_NUMLOCK\t\t= 300,\n\tSDLK_CAPSLOCK\t\t= 301,\n\tSDLK_SCROLLOCK\t\t= 302,\n\tSDLK_RSHIFT\t\t= 303,\n\tSDLK_LSHIFT\t\t= 304,\n\tSDLK_RCTRL\t\t= 305,\n\tSDLK_LCTRL\t\t= 306,\n\tSDLK_RALT\t\t= 307,\n\tSDLK_LALT\t\t= 308,\n\tSDLK_RMETA\t\t= 309,\n\tSDLK_LMETA\t\t= 310,\n\tSDLK_LSUPER\t\t= 311,\t\t/**< Left \"Windows\" key */\n\tSDLK_RSUPER\t\t= 312,\t\t/**< Right \"Windows\" key */\n\tSDLK_MODE\t\t= 313,\t\t/**< \"Alt Gr\" key */\n\tSDLK_COMPOSE\t\t= 314,\t\t/**< Multi-key compose key */\n        /*@}*/\n\n\t/** @name Miscellaneous function keys */\n        /*@{*/\n\tSDLK_HELP\t\t= 315,\n\tSDLK_PRINT\t\t= 316,\n\tSDLK_SYSREQ\t\t= 317,\n\tSDLK_BREAK\t\t= 318,\n\tSDLK_MENU\t\t= 319,\n\tSDLK_POWER\t\t= 320,\t\t/**< Power Macintosh power key */\n\tSDLK_EURO\t\t= 321,\t\t/**< Some european keyboards */\n\tSDLK_UNDO\t\t= 322,\t\t/**< Atari keyboard has Undo */\n        /*@}*/\n\n\t/* Add any other keys here */\n\n\tSDLK_LAST\n} SDLKey;\n\n/** Enumeration of valid key mods (possibly OR'd together) */\ntypedef enum {\n\tKMOD_NONE  = 0x0000,\n\tKMOD_LSHIFT= 0x0001,\n\tKMOD_RSHIFT= 0x0002,\n\tKMOD_LCTRL = 0x0040,\n\tKMOD_RCTRL = 0x0080,\n\tKMOD_LALT  = 0x0100,\n\tKMOD_RALT  = 0x0200,\n\tKMOD_LMETA = 0x0400,\n\tKMOD_RMETA = 0x0800,\n\tKMOD_NUM   = 0x1000,\n\tKMOD_CAPS  = 0x2000,\n\tKMOD_MODE  = 0x4000,\n\tKMOD_RESERVED = 0x8000\n} SDLMod;\n\n#define KMOD_CTRL\t(KMOD_LCTRL|KMOD_RCTRL)\n#define KMOD_SHIFT\t(KMOD_LSHIFT|KMOD_RSHIFT)\n#define KMOD_ALT\t(KMOD_LALT|KMOD_RALT)\n#define KMOD_META\t(KMOD_LMETA|KMOD_RMETA)\n\n#endif /* _SDL_keysym_h */\n"
  },
  {
    "path": "deps/include/SDL/SDL_loadso.h",
    "content": "/*\n    SDL - Simple DirectMedia Layer\n    Copyright (C) 1997-2012 Sam Lantinga\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Lesser General Public\n    License as published by the Free Software Foundation; either\n    version 2.1 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public\n    License along with this library; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n\n    Sam Lantinga\n    slouken@libsdl.org\n*/\n\n/** @file SDL_loadso.h\n *  System dependent library loading routines\n */\n\n/** @file SDL_loadso.h\n *  Some things to keep in mind:                                        \n *  - These functions only work on C function names.  Other languages may\n *    have name mangling and intrinsic language support that varies from\n *    compiler to compiler.\n *  - Make sure you declare your function pointers with the same calling\n *    convention as the actual library function.  Your code will crash\n *    mysteriously if you do not do this.\n *  - Avoid namespace collisions.  If you load a symbol from the library,\n *    it is not defined whether or not it goes into the global symbol\n *    namespace for the application.  If it does and it conflicts with\n *    symbols in your code or other shared libraries, you will not get\n *    the results you expect. :)\n */\n\n\n#ifndef _SDL_loadso_h\n#define _SDL_loadso_h\n\n#include \"SDL_stdinc.h\"\n#include \"SDL_error.h\"\n\n#include \"begin_code.h\"\n/* Set up for C function definitions, even when using C++ */\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * This function dynamically loads a shared object and returns a pointer\n * to the object handle (or NULL if there was an error).\n * The 'sofile' parameter is a system dependent name of the object file.\n */\nextern DECLSPEC void * SDLCALL SDL_LoadObject(const char *sofile);\n\n/**\n * Given an object handle, this function looks up the address of the\n * named function in the shared object and returns it.  This address\n * is no longer valid after calling SDL_UnloadObject().\n */\nextern DECLSPEC void * SDLCALL SDL_LoadFunction(void *handle, const char *name);\n\n/** Unload a shared object from memory */\nextern DECLSPEC void SDLCALL SDL_UnloadObject(void *handle);\n\n/* Ends C function definitions when using C++ */\n#ifdef __cplusplus\n}\n#endif\n#include \"close_code.h\"\n\n#endif /* _SDL_loadso_h */\n"
  },
  {
    "path": "deps/include/SDL/SDL_main.h",
    "content": "/*\n    SDL - Simple DirectMedia Layer\n    Copyright (C) 1997-2012 Sam Lantinga\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Lesser General Public\n    License as published by the Free Software Foundation; either\n    version 2.1 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public\n    License along with this library; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n\n    Sam Lantinga\n    slouken@libsdl.org\n*/\n\n#ifndef _SDL_main_h\n#define _SDL_main_h\n\n#include \"SDL_stdinc.h\"\n\n/** @file SDL_main.h\n *  Redefine main() on Win32 and MacOS so that it is called by winmain.c\n */\n\n#if defined(__WIN32__) || \\\n    (defined(__MWERKS__) && !defined(__BEOS__)) || \\\n    defined(__MACOS__) || defined(__MACOSX__) || \\\n    defined(__SYMBIAN32__) || defined(QWS)\n\n#ifdef __cplusplus\n#define C_LINKAGE\t\"C\"\n#else\n#define C_LINKAGE\n#endif /* __cplusplus */\n\n/** The application's main() function must be called with C linkage,\n *  and should be declared like this:\n *      @code\n *      #ifdef __cplusplus\n *      extern \"C\"\n *      #endif\n *\tint main(int argc, char *argv[])\n *\t{\n *\t}\n *      @endcode\n */\n#define main\tSDL_main\n\n/** The prototype for the application's main() function */\nextern C_LINKAGE int SDL_main(int argc, char *argv[]);\n\n\n/** @name From the SDL library code -- needed for registering the app on Win32 */\n/*@{*/\n#ifdef __WIN32__\n\n#include \"begin_code.h\"\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/** This should be called from your WinMain() function, if any */\nextern DECLSPEC void SDLCALL SDL_SetModuleHandle(void *hInst);\n/** This can also be called, but is no longer necessary */\nextern DECLSPEC int SDLCALL SDL_RegisterApp(char *name, Uint32 style, void *hInst);\n/** This can also be called, but is no longer necessary (SDL_Quit calls it) */\nextern DECLSPEC void SDLCALL SDL_UnregisterApp(void);\n#ifdef __cplusplus\n}\n#endif\n#include \"close_code.h\"\n#endif\n/*@}*/\n\n/** @name From the SDL library code -- needed for registering QuickDraw on MacOS */\n/*@{*/\n#if defined(__MACOS__)\n\n#include \"begin_code.h\"\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/** Forward declaration so we don't need to include QuickDraw.h */\nstruct QDGlobals;\n\n/** This should be called from your main() function, if any */\nextern DECLSPEC void SDLCALL SDL_InitQuickDraw(struct QDGlobals *the_qd);\n\n#ifdef __cplusplus\n}\n#endif\n#include \"close_code.h\"\n#endif\n/*@}*/\n\n#endif /* Need to redefine main()? */\n\n#endif /* _SDL_main_h */\n"
  },
  {
    "path": "deps/include/SDL/SDL_mixer.h",
    "content": "/*\n  SDL_mixer:  An audio mixer library based on the SDL library\n  Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>\n\n  This software is provided 'as-is', without any express or implied\n  warranty.  In no event will the authors be held liable for any damages\n  arising from the use of this software.\n\n  Permission is granted to anyone to use this software for any purpose,\n  including commercial applications, and to alter it and redistribute it\n  freely, subject to the following restrictions:\n\n  1. The origin of this software must not be misrepresented; you must not\n     claim that you wrote the original software. If you use this software\n     in a product, an acknowledgment in the product documentation would be\n     appreciated but is not required.\n  2. Altered source versions must be plainly marked as such, and must not be\n     misrepresented as being the original software.\n  3. This notice may not be removed or altered from any source distribution.\n*/\n\n/* $Id$ */\n\n#ifndef _SDL_MIXER_H\n#define _SDL_MIXER_H\n\n#include \"SDL_types.h\"\n#include \"SDL_rwops.h\"\n#include \"SDL_audio.h\"\n#include \"SDL_endian.h\"\n#include \"SDL_version.h\"\n#include \"begin_code.h\"\n\n/* Set up for C function definitions, even when using C++ */\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* Printable format: \"%d.%d.%d\", MAJOR, MINOR, PATCHLEVEL\n*/\n#define SDL_MIXER_MAJOR_VERSION\t1\n#define SDL_MIXER_MINOR_VERSION\t2\n#define SDL_MIXER_PATCHLEVEL    13\n\n/* This macro can be used to fill a version structure with the compile-time\n * version of the SDL_mixer library.\n */\n#define SDL_MIXER_VERSION(X)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t(X)->major = SDL_MIXER_MAJOR_VERSION;\t\t\t\t\\\n\t(X)->minor = SDL_MIXER_MINOR_VERSION;\t\t\t\t\\\n\t(X)->patch = SDL_MIXER_PATCHLEVEL;\t\t\t\t\\\n}\n\n/* Backwards compatibility */\n#define MIX_MAJOR_VERSION\tSDL_MIXER_MAJOR_VERSION\n#define MIX_MINOR_VERSION\tSDL_MIXER_MINOR_VERSION\n#define MIX_PATCHLEVEL\t\tSDL_MIXER_PATCHLEVEL\n#define MIX_VERSION(X)\t\tSDL_MIXER_VERSION(X)\n\n/* This function gets the version of the dynamically linked SDL_mixer library.\n   it should NOT be used to fill a version structure, instead you should\n   use the SDL_MIXER_VERSION() macro.\n */\nextern DECLSPEC const SDL_version * SDLCALL Mix_Linked_Version(void);\n\ntypedef enum\n{\n    MIX_INIT_FLAC        = 0x00000001,\n    MIX_INIT_MOD         = 0x00000002,\n    MIX_INIT_MP3         = 0x00000004,\n    MIX_INIT_OGG         = 0x00000008,\n    MIX_INIT_FLUIDSYNTH  = 0x00000010\n} MIX_InitFlags;\n\n/* Loads dynamic libraries and prepares them for use.  Flags should be\n   one or more flags from MIX_InitFlags OR'd together.\n   It returns the flags successfully initialized, or 0 on failure.\n */\nextern DECLSPEC int SDLCALL Mix_Init(int flags);\n\n/* Unloads libraries loaded with Mix_Init */\nextern DECLSPEC void SDLCALL Mix_Quit(void);\n\n\n/* The default mixer has 8 simultaneous mixing channels */\n#ifndef MIX_CHANNELS\n#define MIX_CHANNELS\t8\n#endif\n\n/* Good default values for a PC soundcard */\n#define MIX_DEFAULT_FREQUENCY\t22050\n#if SDL_BYTEORDER == SDL_LIL_ENDIAN\n#define MIX_DEFAULT_FORMAT\tAUDIO_S16LSB\n#else\n#define MIX_DEFAULT_FORMAT\tAUDIO_S16MSB\n#endif\n#define MIX_DEFAULT_CHANNELS\t2\n#define MIX_MAX_VOLUME\t\t128\t/* Volume of a chunk */\n\n/* The internal format for an audio chunk */\ntypedef struct Mix_Chunk {\n\tint allocated;\n\tUint8 *abuf;\n\tUint32 alen;\n\tUint8 volume;\t\t/* Per-sample volume, 0-128 */\n} Mix_Chunk;\n\n/* The different fading types supported */\ntypedef enum {\n\tMIX_NO_FADING,\n\tMIX_FADING_OUT,\n\tMIX_FADING_IN\n} Mix_Fading;\n\ntypedef enum {\n\tMUS_NONE,\n\tMUS_CMD,\n\tMUS_WAV,\n\tMUS_MOD,\n\tMUS_MID,\n\tMUS_OGG,\n\tMUS_MP3,\n\tMUS_MP3_MAD,\n\tMUS_FLAC,\n\tMUS_MODPLUG\n} Mix_MusicType;\n\n/* The internal format for a music chunk interpreted via mikmod */\ntypedef struct _Mix_Music Mix_Music;\n\n/* Open the mixer with a certain audio format */\nextern DECLSPEC int SDLCALL Mix_OpenAudio(int frequency, Uint16 format, int channels,\n\t\t\t\t\t\t\tint chunksize);\n\n/* Dynamically change the number of channels managed by the mixer.\n   If decreasing the number of channels, the upper channels are\n   stopped.\n   This function returns the new number of allocated channels.\n */\nextern DECLSPEC int SDLCALL Mix_AllocateChannels(int numchans);\n\n/* Find out what the actual audio device parameters are.\n   This function returns 1 if the audio has been opened, 0 otherwise.\n */\nextern DECLSPEC int SDLCALL Mix_QuerySpec(int *frequency,Uint16 *format,int *channels);\n\n/* Load a wave file or a music (.mod .s3m .it .xm) file */\nextern DECLSPEC Mix_Chunk * SDLCALL Mix_LoadWAV_RW(SDL_RWops *src, int freesrc);\n#define Mix_LoadWAV(file)\tMix_LoadWAV_RW(SDL_RWFromFile(file, \"rb\"), 1)\nextern DECLSPEC Mix_Music * SDLCALL Mix_LoadMUS(const char *file);\n\n/* Load a music file from an SDL_RWop object (Ogg and MikMod specific currently)\n   Matt Campbell (matt@campbellhome.dhs.org) April 2000 */\nextern DECLSPEC Mix_Music * SDLCALL Mix_LoadMUS_RW(SDL_RWops *rw);\n\n/* Load a music file from an SDL_RWop object assuming a specific format */\nextern DECLSPEC Mix_Music * SDLCALL Mix_LoadMUSType_RW(SDL_RWops *rw, Mix_MusicType type, int freesrc);\n\n/* Load a wave file of the mixer format from a memory buffer */\nextern DECLSPEC Mix_Chunk * SDLCALL Mix_QuickLoad_WAV(Uint8 *mem);\n\n/* Load raw audio data of the mixer format from a memory buffer */\nextern DECLSPEC Mix_Chunk * SDLCALL Mix_QuickLoad_RAW(Uint8 *mem, Uint32 len);\n\n/* Free an audio chunk previously loaded */\nextern DECLSPEC void SDLCALL Mix_FreeChunk(Mix_Chunk *chunk);\nextern DECLSPEC void SDLCALL Mix_FreeMusic(Mix_Music *music);\n\n/* Get a list of chunk/music decoders that this build of SDL_mixer provides.\n   This list can change between builds AND runs of the program, if external\n   libraries that add functionality become available.\n   You must successfully call Mix_OpenAudio() before calling these functions.\n   This API is only available in SDL_mixer 1.2.9 and later.\n\n   // usage...\n   int i;\n   const int total = Mix_GetNumChunkDecoders();\n   for (i = 0; i < total; i++)\n       printf(\"Supported chunk decoder: [%s]\\n\", Mix_GetChunkDecoder(i));\n\n   Appearing in this list doesn't promise your specific audio file will\n   decode...but it's handy to know if you have, say, a functioning Timidity\n   install.\n\n   These return values are static, read-only data; do not modify or free it.\n   The pointers remain valid until you call Mix_CloseAudio().\n*/\nextern DECLSPEC int SDLCALL Mix_GetNumChunkDecoders(void);\nextern DECLSPEC const char * SDLCALL Mix_GetChunkDecoder(int index);\nextern DECLSPEC int SDLCALL Mix_GetNumMusicDecoders(void);\nextern DECLSPEC const char * SDLCALL Mix_GetMusicDecoder(int index);\n\n/* Find out the music format of a mixer music, or the currently playing\n   music, if 'music' is NULL.\n*/\nextern DECLSPEC Mix_MusicType SDLCALL Mix_GetMusicType(const Mix_Music *music);\n\n/* Set a function that is called after all mixing is performed.\n   This can be used to provide real-time visual display of the audio stream\n   or add a custom mixer filter for the stream data.\n*/\nextern DECLSPEC void SDLCALL Mix_SetPostMix(void (SDLCALL *mix_func)\n                             (void *udata, Uint8 *stream, int len), void *arg);\n\n/* Add your own music player or additional mixer function.\n   If 'mix_func' is NULL, the default music player is re-enabled.\n */\nextern DECLSPEC void SDLCALL Mix_HookMusic(void (SDLCALL *mix_func)\n                          (void *udata, Uint8 *stream, int len), void *arg);\n\n/* Add your own callback when the music has finished playing.\n   This callback is only called if the music finishes naturally.\n */\nextern DECLSPEC void SDLCALL Mix_HookMusicFinished(void (SDLCALL *music_finished)(void));\n\n/* Get a pointer to the user data for the current music hook */\nextern DECLSPEC void * SDLCALL Mix_GetMusicHookData(void);\n\n/*\n * Add your own callback when a channel has finished playing. NULL\n *  to disable callback. The callback may be called from the mixer's audio \n *  callback or it could be called as a result of Mix_HaltChannel(), etc.\n *  do not call SDL_LockAudio() from this callback; you will either be \n *  inside the audio callback, or SDL_mixer will explicitly lock the audio\n *  before calling your callback.\n */\nextern DECLSPEC void SDLCALL Mix_ChannelFinished(void (SDLCALL *channel_finished)(int channel));\n\n\n/* Special Effects API by ryan c. gordon. (icculus@icculus.org) */\n\n#define MIX_CHANNEL_POST  -2\n\n/* This is the format of a special effect callback:\n *\n *   myeffect(int chan, void *stream, int len, void *udata);\n *\n * (chan) is the channel number that your effect is affecting. (stream) is\n *  the buffer of data to work upon. (len) is the size of (stream), and\n *  (udata) is a user-defined bit of data, which you pass as the last arg of\n *  Mix_RegisterEffect(), and is passed back unmolested to your callback.\n *  Your effect changes the contents of (stream) based on whatever parameters\n *  are significant, or just leaves it be, if you prefer. You can do whatever\n *  you like to the buffer, though, and it will continue in its changed state\n *  down the mixing pipeline, through any other effect functions, then finally\n *  to be mixed with the rest of the channels and music for the final output\n *  stream.\n *\n * DO NOT EVER call SDL_LockAudio() from your callback function!\n */\ntypedef void (SDLCALL *Mix_EffectFunc_t)(int chan, void *stream, int len, void *udata);\n\n/*\n * This is a callback that signifies that a channel has finished all its\n *  loops and has completed playback. This gets called if the buffer\n *  plays out normally, or if you call Mix_HaltChannel(), implicitly stop\n *  a channel via Mix_AllocateChannels(), or unregister a callback while\n *  it's still playing.\n *\n * DO NOT EVER call SDL_LockAudio() from your callback function!\n */\ntypedef void (SDLCALL *Mix_EffectDone_t)(int chan, void *udata);\n\n\n/* Register a special effect function. At mixing time, the channel data is\n *  copied into a buffer and passed through each registered effect function.\n *  After it passes through all the functions, it is mixed into the final\n *  output stream. The copy to buffer is performed once, then each effect\n *  function performs on the output of the previous effect. Understand that\n *  this extra copy to a buffer is not performed if there are no effects\n *  registered for a given chunk, which saves CPU cycles, and any given\n *  effect will be extra cycles, too, so it is crucial that your code run\n *  fast. Also note that the data that your function is given is in the\n *  format of the sound device, and not the format you gave to Mix_OpenAudio(),\n *  although they may in reality be the same. This is an unfortunate but\n *  necessary speed concern. Use Mix_QuerySpec() to determine if you can\n *  handle the data before you register your effect, and take appropriate\n *  actions.\n * You may also specify a callback (Mix_EffectDone_t) that is called when\n *  the channel finishes playing. This gives you a more fine-grained control\n *  than Mix_ChannelFinished(), in case you need to free effect-specific\n *  resources, etc. If you don't need this, you can specify NULL.\n * You may set the callbacks before or after calling Mix_PlayChannel().\n * Things like Mix_SetPanning() are just internal special effect functions,\n *  so if you are using that, you've already incurred the overhead of a copy\n *  to a separate buffer, and that these effects will be in the queue with\n *  any functions you've registered. The list of registered effects for a\n *  channel is reset when a chunk finishes playing, so you need to explicitly\n *  set them with each call to Mix_PlayChannel*().\n * You may also register a special effect function that is to be run after\n *  final mixing occurs. The rules for these callbacks are identical to those\n *  in Mix_RegisterEffect, but they are run after all the channels and the\n *  music have been mixed into a single stream, whereas channel-specific\n *  effects run on a given channel before any other mixing occurs. These\n *  global effect callbacks are call \"posteffects\". Posteffects only have\n *  their Mix_EffectDone_t function called when they are unregistered (since\n *  the main output stream is never \"done\" in the same sense as a channel).\n *  You must unregister them manually when you've had enough. Your callback\n *  will be told that the channel being mixed is (MIX_CHANNEL_POST) if the\n *  processing is considered a posteffect.\n *\n * After all these effects have finished processing, the callback registered\n *  through Mix_SetPostMix() runs, and then the stream goes to the audio\n *  device. \n *\n * DO NOT EVER call SDL_LockAudio() from your callback function!\n *\n * returns zero if error (no such channel), nonzero if added.\n *  Error messages can be retrieved from Mix_GetError().\n */\nextern DECLSPEC int SDLCALL Mix_RegisterEffect(int chan, Mix_EffectFunc_t f,\n\t\t\t\t\tMix_EffectDone_t d, void *arg);\n\n\n/* You may not need to call this explicitly, unless you need to stop an\n *  effect from processing in the middle of a chunk's playback.\n * Posteffects are never implicitly unregistered as they are for channels,\n *  but they may be explicitly unregistered through this function by\n *  specifying MIX_CHANNEL_POST for a channel.\n * returns zero if error (no such channel or effect), nonzero if removed.\n *  Error messages can be retrieved from Mix_GetError().\n */\nextern DECLSPEC int SDLCALL Mix_UnregisterEffect(int channel, Mix_EffectFunc_t f);\n\n\n/* You may not need to call this explicitly, unless you need to stop all\n *  effects from processing in the middle of a chunk's playback. Note that\n *  this will also shut off some internal effect processing, since\n *  Mix_SetPanning() and others may use this API under the hood. This is\n *  called internally when a channel completes playback.\n * Posteffects are never implicitly unregistered as they are for channels,\n *  but they may be explicitly unregistered through this function by\n *  specifying MIX_CHANNEL_POST for a channel.\n * returns zero if error (no such channel), nonzero if all effects removed.\n *  Error messages can be retrieved from Mix_GetError().\n */\nextern DECLSPEC int SDLCALL Mix_UnregisterAllEffects(int channel);\n\n\n#define MIX_EFFECTSMAXSPEED  \"MIX_EFFECTSMAXSPEED\"\n\n/*\n * These are the internally-defined mixing effects. They use the same API that\n *  effects defined in the application use, but are provided here as a\n *  convenience. Some effects can reduce their quality or use more memory in\n *  the name of speed; to enable this, make sure the environment variable\n *  MIX_EFFECTSMAXSPEED (see above) is defined before you call\n *  Mix_OpenAudio().\n */\n\n\n/* Set the panning of a channel. The left and right channels are specified\n *  as integers between 0 and 255, quietest to loudest, respectively.\n *\n * Technically, this is just individual volume control for a sample with\n *  two (stereo) channels, so it can be used for more than just panning.\n *  If you want real panning, call it like this:\n *\n *   Mix_SetPanning(channel, left, 255 - left);\n *\n * ...which isn't so hard.\n *\n * Setting (channel) to MIX_CHANNEL_POST registers this as a posteffect, and\n *  the panning will be done to the final mixed stream before passing it on\n *  to the audio device.\n *\n * This uses the Mix_RegisterEffect() API internally, and returns without\n *  registering the effect function if the audio device is not configured\n *  for stereo output. Setting both (left) and (right) to 255 causes this\n *  effect to be unregistered, since that is the data's normal state.\n *\n * returns zero if error (no such channel or Mix_RegisterEffect() fails),\n *  nonzero if panning effect enabled. Note that an audio device in mono\n *  mode is a no-op, but this call will return successful in that case.\n *  Error messages can be retrieved from Mix_GetError().\n */\nextern DECLSPEC int SDLCALL Mix_SetPanning(int channel, Uint8 left, Uint8 right);\n\n\n/* Set the position of a channel. (angle) is an integer from 0 to 360, that\n *  specifies the location of the sound in relation to the listener. (angle)\n *  will be reduced as neccesary (540 becomes 180 degrees, -100 becomes 260).\n *  Angle 0 is due north, and rotates clockwise as the value increases.\n *  For efficiency, the precision of this effect may be limited (angles 1\n *  through 7 might all produce the same effect, 8 through 15 are equal, etc).\n *  (distance) is an integer between 0 and 255 that specifies the space\n *  between the sound and the listener. The larger the number, the further\n *  away the sound is. Using 255 does not guarantee that the channel will be\n *  culled from the mixing process or be completely silent. For efficiency,\n *  the precision of this effect may be limited (distance 0 through 5 might\n *  all produce the same effect, 6 through 10 are equal, etc). Setting (angle)\n *  and (distance) to 0 unregisters this effect, since the data would be\n *  unchanged.\n *\n * If you need more precise positional audio, consider using OpenAL for\n *  spatialized effects instead of SDL_mixer. This is only meant to be a\n *  basic effect for simple \"3D\" games.\n *\n * If the audio device is configured for mono output, then you won't get\n *  any effectiveness from the angle; however, distance attenuation on the\n *  channel will still occur. While this effect will function with stereo\n *  voices, it makes more sense to use voices with only one channel of sound,\n *  so when they are mixed through this effect, the positioning will sound\n *  correct. You can convert them to mono through SDL before giving them to\n *  the mixer in the first place if you like.\n *\n * Setting (channel) to MIX_CHANNEL_POST registers this as a posteffect, and\n *  the positioning will be done to the final mixed stream before passing it\n *  on to the audio device.\n *\n * This is a convenience wrapper over Mix_SetDistance() and Mix_SetPanning().\n *\n * returns zero if error (no such channel or Mix_RegisterEffect() fails),\n *  nonzero if position effect is enabled.\n *  Error messages can be retrieved from Mix_GetError().\n */\nextern DECLSPEC int SDLCALL Mix_SetPosition(int channel, Sint16 angle, Uint8 distance);\n\n\n/* Set the \"distance\" of a channel. (distance) is an integer from 0 to 255\n *  that specifies the location of the sound in relation to the listener.\n *  Distance 0 is overlapping the listener, and 255 is as far away as possible\n *  A distance of 255 does not guarantee silence; in such a case, you might\n *  want to try changing the chunk's volume, or just cull the sample from the\n *  mixing process with Mix_HaltChannel().\n * For efficiency, the precision of this effect may be limited (distances 1\n *  through 7 might all produce the same effect, 8 through 15 are equal, etc).\n *  (distance) is an integer between 0 and 255 that specifies the space\n *  between the sound and the listener. The larger the number, the further\n *  away the sound is.\n * Setting (distance) to 0 unregisters this effect, since the data would be\n *  unchanged.\n * If you need more precise positional audio, consider using OpenAL for\n *  spatialized effects instead of SDL_mixer. This is only meant to be a\n *  basic effect for simple \"3D\" games.\n *\n * Setting (channel) to MIX_CHANNEL_POST registers this as a posteffect, and\n *  the distance attenuation will be done to the final mixed stream before\n *  passing it on to the audio device.\n *\n * This uses the Mix_RegisterEffect() API internally.\n *\n * returns zero if error (no such channel or Mix_RegisterEffect() fails),\n *  nonzero if position effect is enabled.\n *  Error messages can be retrieved from Mix_GetError().\n */\nextern DECLSPEC int SDLCALL Mix_SetDistance(int channel, Uint8 distance);\n\n\n/*\n * !!! FIXME : Haven't implemented, since the effect goes past the\n *              end of the sound buffer. Will have to think about this.\n *               --ryan.\n */\n#if 0\n/* Causes an echo effect to be mixed into a sound. (echo) is the amount\n *  of echo to mix. 0 is no echo, 255 is infinite (and probably not\n *  what you want).\n *\n * Setting (channel) to MIX_CHANNEL_POST registers this as a posteffect, and\n *  the reverbing will be done to the final mixed stream before passing it on\n *  to the audio device.\n *\n * This uses the Mix_RegisterEffect() API internally. If you specify an echo\n *  of zero, the effect is unregistered, as the data is already in that state.\n *\n * returns zero if error (no such channel or Mix_RegisterEffect() fails),\n *  nonzero if reversing effect is enabled.\n *  Error messages can be retrieved from Mix_GetError().\n */\nextern no_parse_DECLSPEC int SDLCALL Mix_SetReverb(int channel, Uint8 echo);\n#endif\n\n/* Causes a channel to reverse its stereo. This is handy if the user has his\n *  speakers hooked up backwards, or you would like to have a minor bit of\n *  psychedelia in your sound code.  :)  Calling this function with (flip)\n *  set to non-zero reverses the chunks's usual channels. If (flip) is zero,\n *  the effect is unregistered.\n *\n * This uses the Mix_RegisterEffect() API internally, and thus is probably\n *  more CPU intensive than having the user just plug in his speakers\n *  correctly. Mix_SetReverseStereo() returns without registering the effect\n *  function if the audio device is not configured for stereo output.\n *\n * If you specify MIX_CHANNEL_POST for (channel), then this the effect is used\n *  on the final mixed stream before sending it on to the audio device (a\n *  posteffect).\n *\n * returns zero if error (no such channel or Mix_RegisterEffect() fails),\n *  nonzero if reversing effect is enabled. Note that an audio device in mono\n *  mode is a no-op, but this call will return successful in that case.\n *  Error messages can be retrieved from Mix_GetError().\n */\nextern DECLSPEC int SDLCALL Mix_SetReverseStereo(int channel, int flip);\n\n/* end of effects API. --ryan. */\n\n\n/* Reserve the first channels (0 -> n-1) for the application, i.e. don't allocate\n   them dynamically to the next sample if requested with a -1 value below.\n   Returns the number of reserved channels.\n */\nextern DECLSPEC int SDLCALL Mix_ReserveChannels(int num);\n\n/* Channel grouping functions */\n\n/* Attach a tag to a channel. A tag can be assigned to several mixer\n   channels, to form groups of channels.\n   If 'tag' is -1, the tag is removed (actually -1 is the tag used to\n   represent the group of all the channels).\n   Returns true if everything was OK.\n */\nextern DECLSPEC int SDLCALL Mix_GroupChannel(int which, int tag);\n/* Assign several consecutive channels to a group */\nextern DECLSPEC int SDLCALL Mix_GroupChannels(int from, int to, int tag);\n/* Finds the first available channel in a group of channels,\n   returning -1 if none are available.\n */\nextern DECLSPEC int SDLCALL Mix_GroupAvailable(int tag);\n/* Returns the number of channels in a group. This is also a subtle\n   way to get the total number of channels when 'tag' is -1\n */\nextern DECLSPEC int SDLCALL Mix_GroupCount(int tag);\n/* Finds the \"oldest\" sample playing in a group of channels */\nextern DECLSPEC int SDLCALL Mix_GroupOldest(int tag);\n/* Finds the \"most recent\" (i.e. last) sample playing in a group of channels */\nextern DECLSPEC int SDLCALL Mix_GroupNewer(int tag);\n\n/* Play an audio chunk on a specific channel.\n   If the specified channel is -1, play on the first free channel.\n   If 'loops' is greater than zero, loop the sound that many times.\n   If 'loops' is -1, loop inifinitely (~65000 times).\n   Returns which channel was used to play the sound.\n*/\n#define Mix_PlayChannel(channel,chunk,loops) Mix_PlayChannelTimed(channel,chunk,loops,-1)\n/* The same as above, but the sound is played at most 'ticks' milliseconds */\nextern DECLSPEC int SDLCALL Mix_PlayChannelTimed(int channel, Mix_Chunk *chunk, int loops, int ticks);\nextern DECLSPEC int SDLCALL Mix_PlayMusic(Mix_Music *music, int loops);\n\n/* Fade in music or a channel over \"ms\" milliseconds, same semantics as the \"Play\" functions */\nextern DECLSPEC int SDLCALL Mix_FadeInMusic(Mix_Music *music, int loops, int ms);\nextern DECLSPEC int SDLCALL Mix_FadeInMusicPos(Mix_Music *music, int loops, int ms, double position);\n#define Mix_FadeInChannel(channel,chunk,loops,ms) Mix_FadeInChannelTimed(channel,chunk,loops,ms,-1)\nextern DECLSPEC int SDLCALL Mix_FadeInChannelTimed(int channel, Mix_Chunk *chunk, int loops, int ms, int ticks);\n\n/* Set the volume in the range of 0-128 of a specific channel or chunk.\n   If the specified channel is -1, set volume for all channels.\n   Returns the original volume.\n   If the specified volume is -1, just return the current volume.\n*/\nextern DECLSPEC int SDLCALL Mix_Volume(int channel, int volume);\nextern DECLSPEC int SDLCALL Mix_VolumeChunk(Mix_Chunk *chunk, int volume);\nextern DECLSPEC int SDLCALL Mix_VolumeMusic(int volume);\n\n/* Halt playing of a particular channel */\nextern DECLSPEC int SDLCALL Mix_HaltChannel(int channel);\nextern DECLSPEC int SDLCALL Mix_HaltGroup(int tag);\nextern DECLSPEC int SDLCALL Mix_HaltMusic(void);\n\n/* Change the expiration delay for a particular channel.\n   The sample will stop playing after the 'ticks' milliseconds have elapsed,\n   or remove the expiration if 'ticks' is -1\n*/\nextern DECLSPEC int SDLCALL Mix_ExpireChannel(int channel, int ticks);\n\n/* Halt a channel, fading it out progressively till it's silent\n   The ms parameter indicates the number of milliseconds the fading\n   will take.\n */\nextern DECLSPEC int SDLCALL Mix_FadeOutChannel(int which, int ms);\nextern DECLSPEC int SDLCALL Mix_FadeOutGroup(int tag, int ms);\nextern DECLSPEC int SDLCALL Mix_FadeOutMusic(int ms);\n\n/* Query the fading status of a channel */\nextern DECLSPEC Mix_Fading SDLCALL Mix_FadingMusic(void);\nextern DECLSPEC Mix_Fading SDLCALL Mix_FadingChannel(int which);\n\n/* Pause/Resume a particular channel */\nextern DECLSPEC void SDLCALL Mix_Pause(int channel);\nextern DECLSPEC void SDLCALL Mix_Resume(int channel);\nextern DECLSPEC int SDLCALL Mix_Paused(int channel);\n\n/* Pause/Resume the music stream */\nextern DECLSPEC void SDLCALL Mix_PauseMusic(void);\nextern DECLSPEC void SDLCALL Mix_ResumeMusic(void);\nextern DECLSPEC void SDLCALL Mix_RewindMusic(void);\nextern DECLSPEC int SDLCALL Mix_PausedMusic(void);\n\n/* Set the current position in the music stream.\n   This returns 0 if successful, or -1 if it failed or isn't implemented.\n   This function is only implemented for MOD music formats (set pattern\n   order number) and for OGG, FLAC, MP3_MAD, and MODPLUG music (set \n   position in seconds), at the moment.\n*/\nextern DECLSPEC int SDLCALL Mix_SetMusicPosition(double position);\n\n/* Check the status of a specific channel.\n   If the specified channel is -1, check all channels.\n*/\nextern DECLSPEC int SDLCALL Mix_Playing(int channel);\nextern DECLSPEC int SDLCALL Mix_PlayingMusic(void);\n\n/* Stop music and set external music playback command */\nextern DECLSPEC int SDLCALL Mix_SetMusicCMD(const char *command);\n\n/* Synchro value is set by MikMod from modules while playing */\nextern DECLSPEC int SDLCALL Mix_SetSynchroValue(int value);\nextern DECLSPEC int SDLCALL Mix_GetSynchroValue(void);\n\n/* Set/Get/Iterate SoundFonts paths to use by supported MIDI backends */\nextern DECLSPEC int SDLCALL Mix_SetSoundFonts(const char *paths);\nextern DECLSPEC const char* SDLCALL Mix_GetSoundFonts(void);\nextern DECLSPEC int SDLCALL Mix_EachSoundFont(int (SDLCALL *function)(const char*, void*), void *data);\n\n/* Get the Mix_Chunk currently associated with a mixer channel\n    Returns NULL if it's an invalid channel, or there's no chunk associated.\n*/\nextern DECLSPEC Mix_Chunk * SDLCALL Mix_GetChunk(int channel);\n\n/* Close the mixer, halting all playing audio */\nextern DECLSPEC void SDLCALL Mix_CloseAudio(void);\n\n/* We'll use SDL for reporting errors */\n#define Mix_SetError\tSDL_SetError\n#define Mix_GetError\tSDL_GetError\n\n/* Ends C function definitions when using C++ */\n#ifdef __cplusplus\n}\n#endif\n#include \"close_code.h\"\n\n#endif /* _SDL_MIXER_H */\n"
  },
  {
    "path": "deps/include/SDL/SDL_mouse.h",
    "content": "/*\n    SDL - Simple DirectMedia Layer\n    Copyright (C) 1997-2012 Sam Lantinga\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Lesser General Public\n    License as published by the Free Software Foundation; either\n    version 2.1 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public\n    License along with this library; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n\n    Sam Lantinga\n    slouken@libsdl.org\n*/\n\n/** @file SDL_mouse.h\n *  Include file for SDL mouse event handling\n */\n\n#ifndef _SDL_mouse_h\n#define _SDL_mouse_h\n\n#include \"SDL_stdinc.h\"\n#include \"SDL_error.h\"\n#include \"SDL_video.h\"\n\n#include \"begin_code.h\"\n/* Set up for C function definitions, even when using C++ */\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\ntypedef struct WMcursor WMcursor;\t/**< Implementation dependent */\ntypedef struct SDL_Cursor {\n\tSDL_Rect area;\t\t\t/**< The area of the mouse cursor */\n\tSint16 hot_x, hot_y;\t\t/**< The \"tip\" of the cursor */\n\tUint8 *data;\t\t\t/**< B/W cursor data */\n\tUint8 *mask;\t\t\t/**< B/W cursor mask */\n\tUint8 *save[2];\t\t\t/**< Place to save cursor area */\n\tWMcursor *wm_cursor;\t\t/**< Window-manager cursor */\n} SDL_Cursor;\n\n/* Function prototypes */\n/**\n * Retrieve the current state of the mouse.\n * The current button state is returned as a button bitmask, which can\n * be tested using the SDL_BUTTON(X) macros, and x and y are set to the\n * current mouse cursor position.  You can pass NULL for either x or y.\n */\nextern DECLSPEC Uint8 SDLCALL SDL_GetMouseState(int *x, int *y);\n\n/**\n * Retrieve the current state of the mouse.\n * The current button state is returned as a button bitmask, which can\n * be tested using the SDL_BUTTON(X) macros, and x and y are set to the\n * mouse deltas since the last call to SDL_GetRelativeMouseState().\n */\nextern DECLSPEC Uint8 SDLCALL SDL_GetRelativeMouseState(int *x, int *y);\n\n/**\n * Set the position of the mouse cursor (generates a mouse motion event)\n */\nextern DECLSPEC void SDLCALL SDL_WarpMouse(Uint16 x, Uint16 y);\n\n/**\n * Create a cursor using the specified data and mask (in MSB format).\n * The cursor width must be a multiple of 8 bits.\n *\n * The cursor is created in black and white according to the following:\n * data  mask    resulting pixel on screen\n *  0     1       White\n *  1     1       Black\n *  0     0       Transparent\n *  1     0       Inverted color if possible, black if not.\n *\n * Cursors created with this function must be freed with SDL_FreeCursor().\n */\nextern DECLSPEC SDL_Cursor * SDLCALL SDL_CreateCursor\n\t\t(Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y);\n\n/**\n * Set the currently active cursor to the specified one.\n * If the cursor is currently visible, the change will be immediately \n * represented on the display.\n */\nextern DECLSPEC void SDLCALL SDL_SetCursor(SDL_Cursor *cursor);\n\n/**\n * Returns the currently active cursor.\n */\nextern DECLSPEC SDL_Cursor * SDLCALL SDL_GetCursor(void);\n\n/**\n * Deallocates a cursor created with SDL_CreateCursor().\n */\nextern DECLSPEC void SDLCALL SDL_FreeCursor(SDL_Cursor *cursor);\n\n/**\n * Toggle whether or not the cursor is shown on the screen.\n * The cursor start off displayed, but can be turned off.\n * SDL_ShowCursor() returns 1 if the cursor was being displayed\n * before the call, or 0 if it was not.  You can query the current\n * state by passing a 'toggle' value of -1.\n */\nextern DECLSPEC int SDLCALL SDL_ShowCursor(int toggle);\n\n/*@{*/\n/** Used as a mask when testing buttons in buttonstate\n *  Button 1:\tLeft mouse button\n *  Button 2:\tMiddle mouse button\n *  Button 3:\tRight mouse button\n *  Button 4:\tMouse wheel up\t (may also be a real button)\n *  Button 5:\tMouse wheel down (may also be a real button)\n */\n#define SDL_BUTTON(X)\t\t(1 << ((X)-1))\n#define SDL_BUTTON_LEFT\t\t1\n#define SDL_BUTTON_MIDDLE\t2\n#define SDL_BUTTON_RIGHT\t3\n#define SDL_BUTTON_WHEELUP\t4\n#define SDL_BUTTON_WHEELDOWN\t5\n#define SDL_BUTTON_X1\t\t6\n#define SDL_BUTTON_X2\t\t7\n#define SDL_BUTTON_LMASK\tSDL_BUTTON(SDL_BUTTON_LEFT)\n#define SDL_BUTTON_MMASK\tSDL_BUTTON(SDL_BUTTON_MIDDLE)\n#define SDL_BUTTON_RMASK\tSDL_BUTTON(SDL_BUTTON_RIGHT)\n#define SDL_BUTTON_X1MASK\tSDL_BUTTON(SDL_BUTTON_X1)\n#define SDL_BUTTON_X2MASK\tSDL_BUTTON(SDL_BUTTON_X2)\n/*@}*/\n\n/* Ends C function definitions when using C++ */\n#ifdef __cplusplus\n}\n#endif\n#include \"close_code.h\"\n\n#endif /* _SDL_mouse_h */\n"
  },
  {
    "path": "deps/include/SDL/SDL_mutex.h",
    "content": "/*\n    SDL - Simple DirectMedia Layer\n    Copyright (C) 1997-2012 Sam Lantinga\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Lesser General Public\n    License as published by the Free Software Foundation; either\n    version 2.1 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public\n    License along with this library; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n\n    Sam Lantinga\n    slouken@libsdl.org\n*/\n\n#ifndef _SDL_mutex_h\n#define _SDL_mutex_h\n\n/** @file SDL_mutex.h\n *  Functions to provide thread synchronization primitives\n *\n *  @note These are independent of the other SDL routines.\n */\n\n#include \"SDL_stdinc.h\"\n#include \"SDL_error.h\"\n\n#include \"begin_code.h\"\n/* Set up for C function definitions, even when using C++ */\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/** Synchronization functions which can time out return this value\n *  if they time out.\n */\n#define SDL_MUTEX_TIMEDOUT\t1\n\n/** This is the timeout value which corresponds to never time out */\n#define SDL_MUTEX_MAXWAIT\t(~(Uint32)0)\n\n\n/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */\n/** @name Mutex functions                                        */ /*@{*/\n/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */\n\n/** The SDL mutex structure, defined in SDL_mutex.c */\nstruct SDL_mutex;\ntypedef struct SDL_mutex SDL_mutex;\n\n/** Create a mutex, initialized unlocked */\nextern DECLSPEC SDL_mutex * SDLCALL SDL_CreateMutex(void);\n\n#define SDL_LockMutex(m)\tSDL_mutexP(m)\n/** Lock the mutex\n *  @return 0, or -1 on error\n */\nextern DECLSPEC int SDLCALL SDL_mutexP(SDL_mutex *mutex);\n\n#define SDL_UnlockMutex(m)\tSDL_mutexV(m)\n/** Unlock the mutex\n *  @return 0, or -1 on error\n *\n *  It is an error to unlock a mutex that has not been locked by\n *  the current thread, and doing so results in undefined behavior.\n */\nextern DECLSPEC int SDLCALL SDL_mutexV(SDL_mutex *mutex);\n\n/** Destroy a mutex */\nextern DECLSPEC void SDLCALL SDL_DestroyMutex(SDL_mutex *mutex);\n\n/*@}*/\n\n/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */\n/** @name Semaphore functions                                    */ /*@{*/\n/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */\n\n/** The SDL semaphore structure, defined in SDL_sem.c */\nstruct SDL_semaphore;\ntypedef struct SDL_semaphore SDL_sem;\n\n/** Create a semaphore, initialized with value, returns NULL on failure. */\nextern DECLSPEC SDL_sem * SDLCALL SDL_CreateSemaphore(Uint32 initial_value);\n\n/** Destroy a semaphore */\nextern DECLSPEC void SDLCALL SDL_DestroySemaphore(SDL_sem *sem);\n\n/**\n * This function suspends the calling thread until the semaphore pointed \n * to by sem has a positive count. It then atomically decreases the semaphore\n * count.\n */\nextern DECLSPEC int SDLCALL SDL_SemWait(SDL_sem *sem);\n\n/** Non-blocking variant of SDL_SemWait().\n *  @return 0 if the wait succeeds,\n *  SDL_MUTEX_TIMEDOUT if the wait would block, and -1 on error.\n */\nextern DECLSPEC int SDLCALL SDL_SemTryWait(SDL_sem *sem);\n\n/** Variant of SDL_SemWait() with a timeout in milliseconds, returns 0 if\n *  the wait succeeds, SDL_MUTEX_TIMEDOUT if the wait does not succeed in\n *  the allotted time, and -1 on error.\n *\n *  On some platforms this function is implemented by looping with a delay\n *  of 1 ms, and so should be avoided if possible.\n */\nextern DECLSPEC int SDLCALL SDL_SemWaitTimeout(SDL_sem *sem, Uint32 ms);\n\n/** Atomically increases the semaphore's count (not blocking).\n *  @return 0, or -1 on error.\n */\nextern DECLSPEC int SDLCALL SDL_SemPost(SDL_sem *sem);\n\n/** Returns the current count of the semaphore */\nextern DECLSPEC Uint32 SDLCALL SDL_SemValue(SDL_sem *sem);\n\n/*@}*/\n\n/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */\n/** @name Condition_variable_functions                           */ /*@{*/\n/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */\n\n/*@{*/\n/** The SDL condition variable structure, defined in SDL_cond.c */\nstruct SDL_cond;\ntypedef struct SDL_cond SDL_cond;\n/*@}*/\n\n/** Create a condition variable */\nextern DECLSPEC SDL_cond * SDLCALL SDL_CreateCond(void);\n\n/** Destroy a condition variable */\nextern DECLSPEC void SDLCALL SDL_DestroyCond(SDL_cond *cond);\n\n/** Restart one of the threads that are waiting on the condition variable,\n *  @return 0 or -1 on error.\n */\nextern DECLSPEC int SDLCALL SDL_CondSignal(SDL_cond *cond);\n\n/** Restart all threads that are waiting on the condition variable,\n *  @return 0 or -1 on error.\n */\nextern DECLSPEC int SDLCALL SDL_CondBroadcast(SDL_cond *cond);\n\n/** Wait on the condition variable, unlocking the provided mutex.\n *  The mutex must be locked before entering this function!\n *  The mutex is re-locked once the condition variable is signaled.\n *  @return 0 when it is signaled, or -1 on error.\n */\nextern DECLSPEC int SDLCALL SDL_CondWait(SDL_cond *cond, SDL_mutex *mut);\n\n/** Waits for at most 'ms' milliseconds, and returns 0 if the condition\n *  variable is signaled, SDL_MUTEX_TIMEDOUT if the condition is not\n *  signaled in the allotted time, and -1 on error.\n *  On some platforms this function is implemented by looping with a delay\n *  of 1 ms, and so should be avoided if possible.\n */\nextern DECLSPEC int SDLCALL SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms);\n\n/*@}*/\n\n/* Ends C function definitions when using C++ */\n#ifdef __cplusplus\n}\n#endif\n#include \"close_code.h\"\n\n#endif /* _SDL_mutex_h */\n\n"
  },
  {
    "path": "deps/include/SDL/SDL_name.h",
    "content": "\n#ifndef _SDLname_h_\n#define _SDLname_h_\n\n#if defined(__STDC__) || defined(__cplusplus)\n#define NeedFunctionPrototypes 1\n#endif\n\n#define SDL_NAME(X)\tSDL_##X\n\n#endif /* _SDLname_h_ */\n"
  },
  {
    "path": "deps/include/SDL/SDL_opengl.h",
    "content": "/*\n  Simple DirectMedia Layer\n  Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>\n\n  This software is provided 'as-is', without any express or implied\n  warranty.  In no event will the authors be held liable for any damages\n  arising from the use of this software.\n\n  Permission is granted to anyone to use this software for any purpose,\n  including commercial applications, and to alter it and redistribute it\n  freely, subject to the following restrictions:\n\n  1. The origin of this software must not be misrepresented; you must not\n     claim that you wrote the original software. If you use this software\n     in a product, an acknowledgment in the product documentation would be\n     appreciated but is not required.\n  2. Altered source versions must be plainly marked as such, and must not be\n     misrepresented as being the original software.\n  3. This notice may not be removed or altered from any source distribution.\n*/\n\n/* This is a simple file to encapsulate the OpenGL API headers */\n\n#include \"SDL_config.h\"\n\n#ifdef __WIN32__\n#ifndef WIN32_LEAN_AND_MEAN\n#define WIN32_LEAN_AND_MEAN\n#endif\n#ifndef NOMINMAX\n#define NOMINMAX        /* Don't define min() and max() */\n#endif\n#include <windows.h>\n#endif\n#ifndef NO_SDL_GLEXT\n#define __glext_h_      /* Don't let gl.h include glext.h */\n#define __gl_glext_h_   /* Don't let gl.h include glext.h */\n#endif\n#if defined(__MACOSX__)\n#include <OpenGL/gl.h>  /* Header File For The OpenGL Library */\n#include <OpenGL/glu.h> /* Header File For The GLU Library */\n#elif defined(__MACOS__)\n#include <gl.h>         /* Header File For The OpenGL Library */\n#include <glu.h>        /* Header File For The GLU Library */\n#else\n#include <GL/gl.h>      /* Header File For The OpenGL Library */\n#include <GL/glu.h>     /* Header File For The GLU Library */\n#endif\n#ifndef NO_SDL_GLEXT\n#undef __glext_h_\n#undef __gl_glext_h_\n#endif\n\n/** glext.h\n *  This is included here because glext.h is not available on some systems.\n *  If you don't want this version included, simply define \"NO_SDL_GLEXT\"\n */\n#ifndef NO_SDL_GLEXT\n#if !(defined(__glext_h_) || defined(__gl_glext_h_)) && !defined(GL_GLEXT_LEGACY)\n#define __glext_h_\n#define __gl_glext_h_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*\n** Copyright (c) 2007 The Khronos Group Inc.\n** \n** Permission is hereby granted, free of charge, to any person obtaining a\n** copy of this software and/or associated documentation files (the\n** \"Materials\"), to deal in the Materials without restriction, including\n** without limitation the rights to use, copy, modify, merge, publish,\n** distribute, sublicense, and/or sell copies of the Materials, and to\n** permit persons to whom the Materials are furnished to do so, subject to\n** the following conditions:\n** \n** The above copyright notice and this permission notice shall be included\n** in all copies or substantial portions of the Materials.\n** \n** THE MATERIALS ARE PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.\n*/\n\n#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)\n#define WIN32_LEAN_AND_MEAN 1\n#include <windows.h>\n#endif\n\n#ifndef APIENTRY\n#define APIENTRY\n#endif\n#ifndef APIENTRYP\n#define APIENTRYP APIENTRY *\n#endif\n#ifndef GLAPI\n#define GLAPI extern\n#endif\n\n/*************************************************************/\n\n/* Header file version number, required by OpenGL ABI for Linux */\n/* glext.h last updated 2008/03/24 */\n/* Current version at http://www.opengl.org/registry/ */\n#define GL_GLEXT_VERSION 40\n\n#ifndef GL_VERSION_1_2\n#define GL_UNSIGNED_BYTE_3_3_2            0x8032\n#define GL_UNSIGNED_SHORT_4_4_4_4         0x8033\n#define GL_UNSIGNED_SHORT_5_5_5_1         0x8034\n#define GL_UNSIGNED_INT_8_8_8_8           0x8035\n#define GL_UNSIGNED_INT_10_10_10_2        0x8036\n#define GL_RESCALE_NORMAL                 0x803A\n#define GL_TEXTURE_BINDING_3D             0x806A\n#define GL_PACK_SKIP_IMAGES               0x806B\n#define GL_PACK_IMAGE_HEIGHT              0x806C\n#define GL_UNPACK_SKIP_IMAGES             0x806D\n#define GL_UNPACK_IMAGE_HEIGHT            0x806E\n#define GL_TEXTURE_3D                     0x806F\n#define GL_PROXY_TEXTURE_3D               0x8070\n#define GL_TEXTURE_DEPTH                  0x8071\n#define GL_TEXTURE_WRAP_R                 0x8072\n#define GL_MAX_3D_TEXTURE_SIZE            0x8073\n#define GL_UNSIGNED_BYTE_2_3_3_REV        0x8362\n#define GL_UNSIGNED_SHORT_5_6_5           0x8363\n#define GL_UNSIGNED_SHORT_5_6_5_REV       0x8364\n#define GL_UNSIGNED_SHORT_4_4_4_4_REV     0x8365\n#define GL_UNSIGNED_SHORT_1_5_5_5_REV     0x8366\n#define GL_UNSIGNED_INT_8_8_8_8_REV       0x8367\n#define GL_UNSIGNED_INT_2_10_10_10_REV    0x8368\n#define GL_BGR                            0x80E0\n#define GL_BGRA                           0x80E1\n#define GL_MAX_ELEMENTS_VERTICES          0x80E8\n#define GL_MAX_ELEMENTS_INDICES           0x80E9\n#define GL_CLAMP_TO_EDGE                  0x812F\n#define GL_TEXTURE_MIN_LOD                0x813A\n#define GL_TEXTURE_MAX_LOD                0x813B\n#define GL_TEXTURE_BASE_LEVEL             0x813C\n#define GL_TEXTURE_MAX_LEVEL              0x813D\n#define GL_LIGHT_MODEL_COLOR_CONTROL      0x81F8\n#define GL_SINGLE_COLOR                   0x81F9\n#define GL_SEPARATE_SPECULAR_COLOR        0x81FA\n#define GL_SMOOTH_POINT_SIZE_RANGE        0x0B12\n#define GL_SMOOTH_POINT_SIZE_GRANULARITY  0x0B13\n#define GL_SMOOTH_LINE_WIDTH_RANGE        0x0B22\n#define GL_SMOOTH_LINE_WIDTH_GRANULARITY  0x0B23\n#define GL_ALIASED_POINT_SIZE_RANGE       0x846D\n#define GL_ALIASED_LINE_WIDTH_RANGE       0x846E\n#endif\n\n#ifndef GL_ARB_imaging\n#define GL_CONSTANT_COLOR                 0x8001\n#define GL_ONE_MINUS_CONSTANT_COLOR       0x8002\n#define GL_CONSTANT_ALPHA                 0x8003\n#define GL_ONE_MINUS_CONSTANT_ALPHA       0x8004\n#define GL_BLEND_COLOR                    0x8005\n#define GL_FUNC_ADD                       0x8006\n#define GL_MIN                            0x8007\n#define GL_MAX                            0x8008\n#define GL_BLEND_EQUATION                 0x8009\n#define GL_FUNC_SUBTRACT                  0x800A\n#define GL_FUNC_REVERSE_SUBTRACT          0x800B\n#define GL_CONVOLUTION_1D                 0x8010\n#define GL_CONVOLUTION_2D                 0x8011\n#define GL_SEPARABLE_2D                   0x8012\n#define GL_CONVOLUTION_BORDER_MODE        0x8013\n#define GL_CONVOLUTION_FILTER_SCALE       0x8014\n#define GL_CONVOLUTION_FILTER_BIAS        0x8015\n#define GL_REDUCE                         0x8016\n#define GL_CONVOLUTION_FORMAT             0x8017\n#define GL_CONVOLUTION_WIDTH              0x8018\n#define GL_CONVOLUTION_HEIGHT             0x8019\n#define GL_MAX_CONVOLUTION_WIDTH          0x801A\n#define GL_MAX_CONVOLUTION_HEIGHT         0x801B\n#define GL_POST_CONVOLUTION_RED_SCALE     0x801C\n#define GL_POST_CONVOLUTION_GREEN_SCALE   0x801D\n#define GL_POST_CONVOLUTION_BLUE_SCALE    0x801E\n#define GL_POST_CONVOLUTION_ALPHA_SCALE   0x801F\n#define GL_POST_CONVOLUTION_RED_BIAS      0x8020\n#define GL_POST_CONVOLUTION_GREEN_BIAS    0x8021\n#define GL_POST_CONVOLUTION_BLUE_BIAS     0x8022\n#define GL_POST_CONVOLUTION_ALPHA_BIAS    0x8023\n#define GL_HISTOGRAM                      0x8024\n#define GL_PROXY_HISTOGRAM                0x8025\n#define GL_HISTOGRAM_WIDTH                0x8026\n#define GL_HISTOGRAM_FORMAT               0x8027\n#define GL_HISTOGRAM_RED_SIZE             0x8028\n#define GL_HISTOGRAM_GREEN_SIZE           0x8029\n#define GL_HISTOGRAM_BLUE_SIZE            0x802A\n#define GL_HISTOGRAM_ALPHA_SIZE           0x802B\n#define GL_HISTOGRAM_LUMINANCE_SIZE       0x802C\n#define GL_HISTOGRAM_SINK                 0x802D\n#define GL_MINMAX                         0x802E\n#define GL_MINMAX_FORMAT                  0x802F\n#define GL_MINMAX_SINK                    0x8030\n#define GL_TABLE_TOO_LARGE                0x8031\n#define GL_COLOR_MATRIX                   0x80B1\n#define GL_COLOR_MATRIX_STACK_DEPTH       0x80B2\n#define GL_MAX_COLOR_MATRIX_STACK_DEPTH   0x80B3\n#define GL_POST_COLOR_MATRIX_RED_SCALE    0x80B4\n#define GL_POST_COLOR_MATRIX_GREEN_SCALE  0x80B5\n#define GL_POST_COLOR_MATRIX_BLUE_SCALE   0x80B6\n#define GL_POST_COLOR_MATRIX_ALPHA_SCALE  0x80B7\n#define GL_POST_COLOR_MATRIX_RED_BIAS     0x80B8\n#define GL_POST_COLOR_MATRIX_GREEN_BIAS   0x80B9\n#define GL_POST_COLOR_MATRIX_BLUE_BIAS    0x80BA\n#define GL_POST_COLOR_MATRIX_ALPHA_BIAS   0x80BB\n#define GL_COLOR_TABLE                    0x80D0\n#define GL_POST_CONVOLUTION_COLOR_TABLE   0x80D1\n#define GL_POST_COLOR_MATRIX_COLOR_TABLE  0x80D2\n#define GL_PROXY_COLOR_TABLE              0x80D3\n#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE 0x80D4\n#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE 0x80D5\n#define GL_COLOR_TABLE_SCALE              0x80D6\n#define GL_COLOR_TABLE_BIAS               0x80D7\n#define GL_COLOR_TABLE_FORMAT             0x80D8\n#define GL_COLOR_TABLE_WIDTH              0x80D9\n#define GL_COLOR_TABLE_RED_SIZE           0x80DA\n#define GL_COLOR_TABLE_GREEN_SIZE         0x80DB\n#define GL_COLOR_TABLE_BLUE_SIZE          0x80DC\n#define GL_COLOR_TABLE_ALPHA_SIZE         0x80DD\n#define GL_COLOR_TABLE_LUMINANCE_SIZE     0x80DE\n#define GL_COLOR_TABLE_INTENSITY_SIZE     0x80DF\n#define GL_CONSTANT_BORDER                0x8151\n#define GL_REPLICATE_BORDER               0x8153\n#define GL_CONVOLUTION_BORDER_COLOR       0x8154\n#endif\n\n#ifndef GL_VERSION_1_3\n#define GL_TEXTURE0                       0x84C0\n#define GL_TEXTURE1                       0x84C1\n#define GL_TEXTURE2                       0x84C2\n#define GL_TEXTURE3                       0x84C3\n#define GL_TEXTURE4                       0x84C4\n#define GL_TEXTURE5                       0x84C5\n#define GL_TEXTURE6                       0x84C6\n#define GL_TEXTURE7                       0x84C7\n#define GL_TEXTURE8                       0x84C8\n#define GL_TEXTURE9                       0x84C9\n#define GL_TEXTURE10                      0x84CA\n#define GL_TEXTURE11                      0x84CB\n#define GL_TEXTURE12                      0x84CC\n#define GL_TEXTURE13                      0x84CD\n#define GL_TEXTURE14                      0x84CE\n#define GL_TEXTURE15                      0x84CF\n#define GL_TEXTURE16                      0x84D0\n#define GL_TEXTURE17                      0x84D1\n#define GL_TEXTURE18                      0x84D2\n#define GL_TEXTURE19                      0x84D3\n#define GL_TEXTURE20                      0x84D4\n#define GL_TEXTURE21                      0x84D5\n#define GL_TEXTURE22                      0x84D6\n#define GL_TEXTURE23                      0x84D7\n#define GL_TEXTURE24                      0x84D8\n#define GL_TEXTURE25                      0x84D9\n#define GL_TEXTURE26                      0x84DA\n#define GL_TEXTURE27                      0x84DB\n#define GL_TEXTURE28                      0x84DC\n#define GL_TEXTURE29                      0x84DD\n#define GL_TEXTURE30                      0x84DE\n#define GL_TEXTURE31                      0x84DF\n#define GL_ACTIVE_TEXTURE                 0x84E0\n#define GL_CLIENT_ACTIVE_TEXTURE          0x84E1\n#define GL_MAX_TEXTURE_UNITS              0x84E2\n#define GL_TRANSPOSE_MODELVIEW_MATRIX     0x84E3\n#define GL_TRANSPOSE_PROJECTION_MATRIX    0x84E4\n#define GL_TRANSPOSE_TEXTURE_MATRIX       0x84E5\n#define GL_TRANSPOSE_COLOR_MATRIX         0x84E6\n#define GL_MULTISAMPLE                    0x809D\n#define GL_SAMPLE_ALPHA_TO_COVERAGE       0x809E\n#define GL_SAMPLE_ALPHA_TO_ONE            0x809F\n#define GL_SAMPLE_COVERAGE                0x80A0\n#define GL_SAMPLE_BUFFERS                 0x80A8\n#define GL_SAMPLES                        0x80A9\n#define GL_SAMPLE_COVERAGE_VALUE          0x80AA\n#define GL_SAMPLE_COVERAGE_INVERT         0x80AB\n#define GL_MULTISAMPLE_BIT                0x20000000\n#define GL_NORMAL_MAP                     0x8511\n#define GL_REFLECTION_MAP                 0x8512\n#define GL_TEXTURE_CUBE_MAP               0x8513\n#define GL_TEXTURE_BINDING_CUBE_MAP       0x8514\n#define GL_TEXTURE_CUBE_MAP_POSITIVE_X    0x8515\n#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X    0x8516\n#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y    0x8517\n#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y    0x8518\n#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z    0x8519\n#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z    0x851A\n#define GL_PROXY_TEXTURE_CUBE_MAP         0x851B\n#define GL_MAX_CUBE_MAP_TEXTURE_SIZE      0x851C\n#define GL_COMPRESSED_ALPHA               0x84E9\n#define GL_COMPRESSED_LUMINANCE           0x84EA\n#define GL_COMPRESSED_LUMINANCE_ALPHA     0x84EB\n#define GL_COMPRESSED_INTENSITY           0x84EC\n#define GL_COMPRESSED_RGB                 0x84ED\n#define GL_COMPRESSED_RGBA                0x84EE\n#define GL_TEXTURE_COMPRESSION_HINT       0x84EF\n#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE  0x86A0\n#define GL_TEXTURE_COMPRESSED             0x86A1\n#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2\n#define GL_COMPRESSED_TEXTURE_FORMATS     0x86A3\n#define GL_CLAMP_TO_BORDER                0x812D\n#define GL_COMBINE                        0x8570\n#define GL_COMBINE_RGB                    0x8571\n#define GL_COMBINE_ALPHA                  0x8572\n#define GL_SOURCE0_RGB                    0x8580\n#define GL_SOURCE1_RGB                    0x8581\n#define GL_SOURCE2_RGB                    0x8582\n#define GL_SOURCE0_ALPHA                  0x8588\n#define GL_SOURCE1_ALPHA                  0x8589\n#define GL_SOURCE2_ALPHA                  0x858A\n#define GL_OPERAND0_RGB                   0x8590\n#define GL_OPERAND1_RGB                   0x8591\n#define GL_OPERAND2_RGB                   0x8592\n#define GL_OPERAND0_ALPHA                 0x8598\n#define GL_OPERAND1_ALPHA                 0x8599\n#define GL_OPERAND2_ALPHA                 0x859A\n#define GL_RGB_SCALE                      0x8573\n#define GL_ADD_SIGNED                     0x8574\n#define GL_INTERPOLATE                    0x8575\n#define GL_SUBTRACT                       0x84E7\n#define GL_CONSTANT                       0x8576\n#define GL_PRIMARY_COLOR                  0x8577\n#define GL_PREVIOUS                       0x8578\n#define GL_DOT3_RGB                       0x86AE\n#define GL_DOT3_RGBA                      0x86AF\n#endif\n\n#ifndef GL_VERSION_1_4\n#define GL_BLEND_DST_RGB                  0x80C8\n#define GL_BLEND_SRC_RGB                  0x80C9\n#define GL_BLEND_DST_ALPHA                0x80CA\n#define GL_BLEND_SRC_ALPHA                0x80CB\n#define GL_POINT_SIZE_MIN                 0x8126\n#define GL_POINT_SIZE_MAX                 0x8127\n#define GL_POINT_FADE_THRESHOLD_SIZE      0x8128\n#define GL_POINT_DISTANCE_ATTENUATION     0x8129\n#define GL_GENERATE_MIPMAP                0x8191\n#define GL_GENERATE_MIPMAP_HINT           0x8192\n#define GL_DEPTH_COMPONENT16              0x81A5\n#define GL_DEPTH_COMPONENT24              0x81A6\n#define GL_DEPTH_COMPONENT32              0x81A7\n#define GL_MIRRORED_REPEAT                0x8370\n#define GL_FOG_COORDINATE_SOURCE          0x8450\n#define GL_FOG_COORDINATE                 0x8451\n#define GL_FRAGMENT_DEPTH                 0x8452\n#define GL_CURRENT_FOG_COORDINATE         0x8453\n#define GL_FOG_COORDINATE_ARRAY_TYPE      0x8454\n#define GL_FOG_COORDINATE_ARRAY_STRIDE    0x8455\n#define GL_FOG_COORDINATE_ARRAY_POINTER   0x8456\n#define GL_FOG_COORDINATE_ARRAY           0x8457\n#define GL_COLOR_SUM                      0x8458\n#define GL_CURRENT_SECONDARY_COLOR        0x8459\n#define GL_SECONDARY_COLOR_ARRAY_SIZE     0x845A\n#define GL_SECONDARY_COLOR_ARRAY_TYPE     0x845B\n#define GL_SECONDARY_COLOR_ARRAY_STRIDE   0x845C\n#define GL_SECONDARY_COLOR_ARRAY_POINTER  0x845D\n#define GL_SECONDARY_COLOR_ARRAY          0x845E\n#define GL_MAX_TEXTURE_LOD_BIAS           0x84FD\n#define GL_TEXTURE_FILTER_CONTROL         0x8500\n#define GL_TEXTURE_LOD_BIAS               0x8501\n#define GL_INCR_WRAP                      0x8507\n#define GL_DECR_WRAP                      0x8508\n#define GL_TEXTURE_DEPTH_SIZE             0x884A\n#define GL_DEPTH_TEXTURE_MODE             0x884B\n#define GL_TEXTURE_COMPARE_MODE           0x884C\n#define GL_TEXTURE_COMPARE_FUNC           0x884D\n#define GL_COMPARE_R_TO_TEXTURE           0x884E\n#endif\n\n#ifndef GL_VERSION_1_5\n#define GL_BUFFER_SIZE                    0x8764\n#define GL_BUFFER_USAGE                   0x8765\n#define GL_QUERY_COUNTER_BITS             0x8864\n#define GL_CURRENT_QUERY                  0x8865\n#define GL_QUERY_RESULT                   0x8866\n#define GL_QUERY_RESULT_AVAILABLE         0x8867\n#define GL_ARRAY_BUFFER                   0x8892\n#define GL_ELEMENT_ARRAY_BUFFER           0x8893\n#define GL_ARRAY_BUFFER_BINDING           0x8894\n#define GL_ELEMENT_ARRAY_BUFFER_BINDING   0x8895\n#define GL_VERTEX_ARRAY_BUFFER_BINDING    0x8896\n#define GL_NORMAL_ARRAY_BUFFER_BINDING    0x8897\n#define GL_COLOR_ARRAY_BUFFER_BINDING     0x8898\n#define GL_INDEX_ARRAY_BUFFER_BINDING     0x8899\n#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A\n#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING 0x889B\n#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING 0x889C\n#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING 0x889D\n#define GL_WEIGHT_ARRAY_BUFFER_BINDING    0x889E\n#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F\n#define GL_READ_ONLY                      0x88B8\n#define GL_WRITE_ONLY                     0x88B9\n#define GL_READ_WRITE                     0x88BA\n#define GL_BUFFER_ACCESS                  0x88BB\n#define GL_BUFFER_MAPPED                  0x88BC\n#define GL_BUFFER_MAP_POINTER             0x88BD\n#define GL_STREAM_DRAW                    0x88E0\n#define GL_STREAM_READ                    0x88E1\n#define GL_STREAM_COPY                    0x88E2\n#define GL_STATIC_DRAW                    0x88E4\n#define GL_STATIC_READ                    0x88E5\n#define GL_STATIC_COPY                    0x88E6\n#define GL_DYNAMIC_DRAW                   0x88E8\n#define GL_DYNAMIC_READ                   0x88E9\n#define GL_DYNAMIC_COPY                   0x88EA\n#define GL_SAMPLES_PASSED                 0x8914\n#define GL_FOG_COORD_SRC                  GL_FOG_COORDINATE_SOURCE\n#define GL_FOG_COORD                      GL_FOG_COORDINATE\n#define GL_CURRENT_FOG_COORD              GL_CURRENT_FOG_COORDINATE\n#define GL_FOG_COORD_ARRAY_TYPE           GL_FOG_COORDINATE_ARRAY_TYPE\n#define GL_FOG_COORD_ARRAY_STRIDE         GL_FOG_COORDINATE_ARRAY_STRIDE\n#define GL_FOG_COORD_ARRAY_POINTER        GL_FOG_COORDINATE_ARRAY_POINTER\n#define GL_FOG_COORD_ARRAY                GL_FOG_COORDINATE_ARRAY\n#define GL_FOG_COORD_ARRAY_BUFFER_BINDING GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING\n#define GL_SRC0_RGB                       GL_SOURCE0_RGB\n#define GL_SRC1_RGB                       GL_SOURCE1_RGB\n#define GL_SRC2_RGB                       GL_SOURCE2_RGB\n#define GL_SRC0_ALPHA                     GL_SOURCE0_ALPHA\n#define GL_SRC1_ALPHA                     GL_SOURCE1_ALPHA\n#define GL_SRC2_ALPHA                     GL_SOURCE2_ALPHA\n#endif\n\n#ifndef GL_VERSION_2_0\n#define GL_BLEND_EQUATION_RGB             GL_BLEND_EQUATION\n#define GL_VERTEX_ATTRIB_ARRAY_ENABLED    0x8622\n#define GL_VERTEX_ATTRIB_ARRAY_SIZE       0x8623\n#define GL_VERTEX_ATTRIB_ARRAY_STRIDE     0x8624\n#define GL_VERTEX_ATTRIB_ARRAY_TYPE       0x8625\n#define GL_CURRENT_VERTEX_ATTRIB          0x8626\n#define GL_VERTEX_PROGRAM_POINT_SIZE      0x8642\n#define GL_VERTEX_PROGRAM_TWO_SIDE        0x8643\n#define GL_VERTEX_ATTRIB_ARRAY_POINTER    0x8645\n#define GL_STENCIL_BACK_FUNC              0x8800\n#define GL_STENCIL_BACK_FAIL              0x8801\n#define GL_STENCIL_BACK_PASS_DEPTH_FAIL   0x8802\n#define GL_STENCIL_BACK_PASS_DEPTH_PASS   0x8803\n#define GL_MAX_DRAW_BUFFERS               0x8824\n#define GL_DRAW_BUFFER0                   0x8825\n#define GL_DRAW_BUFFER1                   0x8826\n#define GL_DRAW_BUFFER2                   0x8827\n#define GL_DRAW_BUFFER3                   0x8828\n#define GL_DRAW_BUFFER4                   0x8829\n#define GL_DRAW_BUFFER5                   0x882A\n#define GL_DRAW_BUFFER6                   0x882B\n#define GL_DRAW_BUFFER7                   0x882C\n#define GL_DRAW_BUFFER8                   0x882D\n#define GL_DRAW_BUFFER9                   0x882E\n#define GL_DRAW_BUFFER10                  0x882F\n#define GL_DRAW_BUFFER11                  0x8830\n#define GL_DRAW_BUFFER12                  0x8831\n#define GL_DRAW_BUFFER13                  0x8832\n#define GL_DRAW_BUFFER14                  0x8833\n#define GL_DRAW_BUFFER15                  0x8834\n#define GL_BLEND_EQUATION_ALPHA           0x883D\n#define GL_POINT_SPRITE                   0x8861\n#define GL_COORD_REPLACE                  0x8862\n#define GL_MAX_VERTEX_ATTRIBS             0x8869\n#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A\n#define GL_MAX_TEXTURE_COORDS             0x8871\n#define GL_MAX_TEXTURE_IMAGE_UNITS        0x8872\n#define GL_FRAGMENT_SHADER                0x8B30\n#define GL_VERTEX_SHADER                  0x8B31\n#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49\n#define GL_MAX_VERTEX_UNIFORM_COMPONENTS  0x8B4A\n#define GL_MAX_VARYING_FLOATS             0x8B4B\n#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C\n#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D\n#define GL_SHADER_TYPE                    0x8B4F\n#define GL_FLOAT_VEC2                     0x8B50\n#define GL_FLOAT_VEC3                     0x8B51\n#define GL_FLOAT_VEC4                     0x8B52\n#define GL_INT_VEC2                       0x8B53\n#define GL_INT_VEC3                       0x8B54\n#define GL_INT_VEC4                       0x8B55\n#define GL_BOOL                           0x8B56\n#define GL_BOOL_VEC2                      0x8B57\n#define GL_BOOL_VEC3                      0x8B58\n#define GL_BOOL_VEC4                      0x8B59\n#define GL_FLOAT_MAT2                     0x8B5A\n#define GL_FLOAT_MAT3                     0x8B5B\n#define GL_FLOAT_MAT4                     0x8B5C\n#define GL_SAMPLER_1D                     0x8B5D\n#define GL_SAMPLER_2D                     0x8B5E\n#define GL_SAMPLER_3D                     0x8B5F\n#define GL_SAMPLER_CUBE                   0x8B60\n#define GL_SAMPLER_1D_SHADOW              0x8B61\n#define GL_SAMPLER_2D_SHADOW              0x8B62\n#define GL_DELETE_STATUS                  0x8B80\n#define GL_COMPILE_STATUS                 0x8B81\n#define GL_LINK_STATUS                    0x8B82\n#define GL_VALIDATE_STATUS                0x8B83\n#define GL_INFO_LOG_LENGTH                0x8B84\n#define GL_ATTACHED_SHADERS               0x8B85\n#define GL_ACTIVE_UNIFORMS                0x8B86\n#define GL_ACTIVE_UNIFORM_MAX_LENGTH      0x8B87\n#define GL_SHADER_SOURCE_LENGTH           0x8B88\n#define GL_ACTIVE_ATTRIBUTES              0x8B89\n#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH    0x8B8A\n#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B\n#define GL_SHADING_LANGUAGE_VERSION       0x8B8C\n#define GL_CURRENT_PROGRAM                0x8B8D\n#define GL_POINT_SPRITE_COORD_ORIGIN      0x8CA0\n#define GL_LOWER_LEFT                     0x8CA1\n#define GL_UPPER_LEFT                     0x8CA2\n#define GL_STENCIL_BACK_REF               0x8CA3\n#define GL_STENCIL_BACK_VALUE_MASK        0x8CA4\n#define GL_STENCIL_BACK_WRITEMASK         0x8CA5\n#endif\n\n#ifndef GL_VERSION_2_1\n#define GL_CURRENT_RASTER_SECONDARY_COLOR 0x845F\n#define GL_PIXEL_PACK_BUFFER              0x88EB\n#define GL_PIXEL_UNPACK_BUFFER            0x88EC\n#define GL_PIXEL_PACK_BUFFER_BINDING      0x88ED\n#define GL_PIXEL_UNPACK_BUFFER_BINDING    0x88EF\n#define GL_FLOAT_MAT2x3                   0x8B65\n#define GL_FLOAT_MAT2x4                   0x8B66\n#define GL_FLOAT_MAT3x2                   0x8B67\n#define GL_FLOAT_MAT3x4                   0x8B68\n#define GL_FLOAT_MAT4x2                   0x8B69\n#define GL_FLOAT_MAT4x3                   0x8B6A\n#define GL_SRGB                           0x8C40\n#define GL_SRGB8                          0x8C41\n#define GL_SRGB_ALPHA                     0x8C42\n#define GL_SRGB8_ALPHA8                   0x8C43\n#define GL_SLUMINANCE_ALPHA               0x8C44\n#define GL_SLUMINANCE8_ALPHA8             0x8C45\n#define GL_SLUMINANCE                     0x8C46\n#define GL_SLUMINANCE8                    0x8C47\n#define GL_COMPRESSED_SRGB                0x8C48\n#define GL_COMPRESSED_SRGB_ALPHA          0x8C49\n#define GL_COMPRESSED_SLUMINANCE          0x8C4A\n#define GL_COMPRESSED_SLUMINANCE_ALPHA    0x8C4B\n#endif\n\n#ifndef GL_ARB_multitexture\n#define GL_TEXTURE0_ARB                   0x84C0\n#define GL_TEXTURE1_ARB                   0x84C1\n#define GL_TEXTURE2_ARB                   0x84C2\n#define GL_TEXTURE3_ARB                   0x84C3\n#define GL_TEXTURE4_ARB                   0x84C4\n#define GL_TEXTURE5_ARB                   0x84C5\n#define GL_TEXTURE6_ARB                   0x84C6\n#define GL_TEXTURE7_ARB                   0x84C7\n#define GL_TEXTURE8_ARB                   0x84C8\n#define GL_TEXTURE9_ARB                   0x84C9\n#define GL_TEXTURE10_ARB                  0x84CA\n#define GL_TEXTURE11_ARB                  0x84CB\n#define GL_TEXTURE12_ARB                  0x84CC\n#define GL_TEXTURE13_ARB                  0x84CD\n#define GL_TEXTURE14_ARB                  0x84CE\n#define GL_TEXTURE15_ARB                  0x84CF\n#define GL_TEXTURE16_ARB                  0x84D0\n#define GL_TEXTURE17_ARB                  0x84D1\n#define GL_TEXTURE18_ARB                  0x84D2\n#define GL_TEXTURE19_ARB                  0x84D3\n#define GL_TEXTURE20_ARB                  0x84D4\n#define GL_TEXTURE21_ARB                  0x84D5\n#define GL_TEXTURE22_ARB                  0x84D6\n#define GL_TEXTURE23_ARB                  0x84D7\n#define GL_TEXTURE24_ARB                  0x84D8\n#define GL_TEXTURE25_ARB                  0x84D9\n#define GL_TEXTURE26_ARB                  0x84DA\n#define GL_TEXTURE27_ARB                  0x84DB\n#define GL_TEXTURE28_ARB                  0x84DC\n#define GL_TEXTURE29_ARB                  0x84DD\n#define GL_TEXTURE30_ARB                  0x84DE\n#define GL_TEXTURE31_ARB                  0x84DF\n#define GL_ACTIVE_TEXTURE_ARB             0x84E0\n#define GL_CLIENT_ACTIVE_TEXTURE_ARB      0x84E1\n#define GL_MAX_TEXTURE_UNITS_ARB          0x84E2\n#endif\n\n#ifndef GL_ARB_transpose_matrix\n#define GL_TRANSPOSE_MODELVIEW_MATRIX_ARB 0x84E3\n#define GL_TRANSPOSE_PROJECTION_MATRIX_ARB 0x84E4\n#define GL_TRANSPOSE_TEXTURE_MATRIX_ARB   0x84E5\n#define GL_TRANSPOSE_COLOR_MATRIX_ARB     0x84E6\n#endif\n\n#ifndef GL_ARB_multisample\n#define GL_MULTISAMPLE_ARB                0x809D\n#define GL_SAMPLE_ALPHA_TO_COVERAGE_ARB   0x809E\n#define GL_SAMPLE_ALPHA_TO_ONE_ARB        0x809F\n#define GL_SAMPLE_COVERAGE_ARB            0x80A0\n#define GL_SAMPLE_BUFFERS_ARB             0x80A8\n#define GL_SAMPLES_ARB                    0x80A9\n#define GL_SAMPLE_COVERAGE_VALUE_ARB      0x80AA\n#define GL_SAMPLE_COVERAGE_INVERT_ARB     0x80AB\n#define GL_MULTISAMPLE_BIT_ARB            0x20000000\n#endif\n\n#ifndef GL_ARB_texture_env_add\n#endif\n\n#ifndef GL_ARB_texture_cube_map\n#define GL_NORMAL_MAP_ARB                 0x8511\n#define GL_REFLECTION_MAP_ARB             0x8512\n#define GL_TEXTURE_CUBE_MAP_ARB           0x8513\n#define GL_TEXTURE_BINDING_CUBE_MAP_ARB   0x8514\n#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x8515\n#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x8516\n#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x8517\n#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x8518\n#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x8519\n#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x851A\n#define GL_PROXY_TEXTURE_CUBE_MAP_ARB     0x851B\n#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB  0x851C\n#endif\n\n#ifndef GL_ARB_texture_compression\n#define GL_COMPRESSED_ALPHA_ARB           0x84E9\n#define GL_COMPRESSED_LUMINANCE_ARB       0x84EA\n#define GL_COMPRESSED_LUMINANCE_ALPHA_ARB 0x84EB\n#define GL_COMPRESSED_INTENSITY_ARB       0x84EC\n#define GL_COMPRESSED_RGB_ARB             0x84ED\n#define GL_COMPRESSED_RGBA_ARB            0x84EE\n#define GL_TEXTURE_COMPRESSION_HINT_ARB   0x84EF\n#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB 0x86A0\n#define GL_TEXTURE_COMPRESSED_ARB         0x86A1\n#define GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A2\n#define GL_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A3\n#endif\n\n#ifndef GL_ARB_texture_border_clamp\n#define GL_CLAMP_TO_BORDER_ARB            0x812D\n#endif\n\n#ifndef GL_ARB_point_parameters\n#define GL_POINT_SIZE_MIN_ARB             0x8126\n#define GL_POINT_SIZE_MAX_ARB             0x8127\n#define GL_POINT_FADE_THRESHOLD_SIZE_ARB  0x8128\n#define GL_POINT_DISTANCE_ATTENUATION_ARB 0x8129\n#endif\n\n#ifndef GL_ARB_vertex_blend\n#define GL_MAX_VERTEX_UNITS_ARB           0x86A4\n#define GL_ACTIVE_VERTEX_UNITS_ARB        0x86A5\n#define GL_WEIGHT_SUM_UNITY_ARB           0x86A6\n#define GL_VERTEX_BLEND_ARB               0x86A7\n#define GL_CURRENT_WEIGHT_ARB             0x86A8\n#define GL_WEIGHT_ARRAY_TYPE_ARB          0x86A9\n#define GL_WEIGHT_ARRAY_STRIDE_ARB        0x86AA\n#define GL_WEIGHT_ARRAY_SIZE_ARB          0x86AB\n#define GL_WEIGHT_ARRAY_POINTER_ARB       0x86AC\n#define GL_WEIGHT_ARRAY_ARB               0x86AD\n#define GL_MODELVIEW0_ARB                 0x1700\n#define GL_MODELVIEW1_ARB                 0x850A\n#define GL_MODELVIEW2_ARB                 0x8722\n#define GL_MODELVIEW3_ARB                 0x8723\n#define GL_MODELVIEW4_ARB                 0x8724\n#define GL_MODELVIEW5_ARB                 0x8725\n#define GL_MODELVIEW6_ARB                 0x8726\n#define GL_MODELVIEW7_ARB                 0x8727\n#define GL_MODELVIEW8_ARB                 0x8728\n#define GL_MODELVIEW9_ARB                 0x8729\n#define GL_MODELVIEW10_ARB                0x872A\n#define GL_MODELVIEW11_ARB                0x872B\n#define GL_MODELVIEW12_ARB                0x872C\n#define GL_MODELVIEW13_ARB                0x872D\n#define GL_MODELVIEW14_ARB                0x872E\n#define GL_MODELVIEW15_ARB                0x872F\n#define GL_MODELVIEW16_ARB                0x8730\n#define GL_MODELVIEW17_ARB                0x8731\n#define GL_MODELVIEW18_ARB                0x8732\n#define GL_MODELVIEW19_ARB                0x8733\n#define GL_MODELVIEW20_ARB                0x8734\n#define GL_MODELVIEW21_ARB                0x8735\n#define GL_MODELVIEW22_ARB                0x8736\n#define GL_MODELVIEW23_ARB                0x8737\n#define GL_MODELVIEW24_ARB                0x8738\n#define GL_MODELVIEW25_ARB                0x8739\n#define GL_MODELVIEW26_ARB                0x873A\n#define GL_MODELVIEW27_ARB                0x873B\n#define GL_MODELVIEW28_ARB                0x873C\n#define GL_MODELVIEW29_ARB                0x873D\n#define GL_MODELVIEW30_ARB                0x873E\n#define GL_MODELVIEW31_ARB                0x873F\n#endif\n\n#ifndef GL_ARB_matrix_palette\n#define GL_MATRIX_PALETTE_ARB             0x8840\n#define GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB 0x8841\n#define GL_MAX_PALETTE_MATRICES_ARB       0x8842\n#define GL_CURRENT_PALETTE_MATRIX_ARB     0x8843\n#define GL_MATRIX_INDEX_ARRAY_ARB         0x8844\n#define GL_CURRENT_MATRIX_INDEX_ARB       0x8845\n#define GL_MATRIX_INDEX_ARRAY_SIZE_ARB    0x8846\n#define GL_MATRIX_INDEX_ARRAY_TYPE_ARB    0x8847\n#define GL_MATRIX_INDEX_ARRAY_STRIDE_ARB  0x8848\n#define GL_MATRIX_INDEX_ARRAY_POINTER_ARB 0x8849\n#endif\n\n#ifndef GL_ARB_texture_env_combine\n#define GL_COMBINE_ARB                    0x8570\n#define GL_COMBINE_RGB_ARB                0x8571\n#define GL_COMBINE_ALPHA_ARB              0x8572\n#define GL_SOURCE0_RGB_ARB                0x8580\n#define GL_SOURCE1_RGB_ARB                0x8581\n#define GL_SOURCE2_RGB_ARB                0x8582\n#define GL_SOURCE0_ALPHA_ARB              0x8588\n#define GL_SOURCE1_ALPHA_ARB              0x8589\n#define GL_SOURCE2_ALPHA_ARB              0x858A\n#define GL_OPERAND0_RGB_ARB               0x8590\n#define GL_OPERAND1_RGB_ARB               0x8591\n#define GL_OPERAND2_RGB_ARB               0x8592\n#define GL_OPERAND0_ALPHA_ARB             0x8598\n#define GL_OPERAND1_ALPHA_ARB             0x8599\n#define GL_OPERAND2_ALPHA_ARB             0x859A\n#define GL_RGB_SCALE_ARB                  0x8573\n#define GL_ADD_SIGNED_ARB                 0x8574\n#define GL_INTERPOLATE_ARB                0x8575\n#define GL_SUBTRACT_ARB                   0x84E7\n#define GL_CONSTANT_ARB                   0x8576\n#define GL_PRIMARY_COLOR_ARB              0x8577\n#define GL_PREVIOUS_ARB                   0x8578\n#endif\n\n#ifndef GL_ARB_texture_env_crossbar\n#endif\n\n#ifndef GL_ARB_texture_env_dot3\n#define GL_DOT3_RGB_ARB                   0x86AE\n#define GL_DOT3_RGBA_ARB                  0x86AF\n#endif\n\n#ifndef GL_ARB_texture_mirrored_repeat\n#define GL_MIRRORED_REPEAT_ARB            0x8370\n#endif\n\n#ifndef GL_ARB_depth_texture\n#define GL_DEPTH_COMPONENT16_ARB          0x81A5\n#define GL_DEPTH_COMPONENT24_ARB          0x81A6\n#define GL_DEPTH_COMPONENT32_ARB          0x81A7\n#define GL_TEXTURE_DEPTH_SIZE_ARB         0x884A\n#define GL_DEPTH_TEXTURE_MODE_ARB         0x884B\n#endif\n\n#ifndef GL_ARB_shadow\n#define GL_TEXTURE_COMPARE_MODE_ARB       0x884C\n#define GL_TEXTURE_COMPARE_FUNC_ARB       0x884D\n#define GL_COMPARE_R_TO_TEXTURE_ARB       0x884E\n#endif\n\n#ifndef GL_ARB_shadow_ambient\n#define GL_TEXTURE_COMPARE_FAIL_VALUE_ARB 0x80BF\n#endif\n\n#ifndef GL_ARB_window_pos\n#endif\n\n#ifndef GL_ARB_vertex_program\n#define GL_COLOR_SUM_ARB                  0x8458\n#define GL_VERTEX_PROGRAM_ARB             0x8620\n#define GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB 0x8622\n#define GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB   0x8623\n#define GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB 0x8624\n#define GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB   0x8625\n#define GL_CURRENT_VERTEX_ATTRIB_ARB      0x8626\n#define GL_PROGRAM_LENGTH_ARB             0x8627\n#define GL_PROGRAM_STRING_ARB             0x8628\n#define GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB 0x862E\n#define GL_MAX_PROGRAM_MATRICES_ARB       0x862F\n#define GL_CURRENT_MATRIX_STACK_DEPTH_ARB 0x8640\n#define GL_CURRENT_MATRIX_ARB             0x8641\n#define GL_VERTEX_PROGRAM_POINT_SIZE_ARB  0x8642\n#define GL_VERTEX_PROGRAM_TWO_SIDE_ARB    0x8643\n#define GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB 0x8645\n#define GL_PROGRAM_ERROR_POSITION_ARB     0x864B\n#define GL_PROGRAM_BINDING_ARB            0x8677\n#define GL_MAX_VERTEX_ATTRIBS_ARB         0x8869\n#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB 0x886A\n#define GL_PROGRAM_ERROR_STRING_ARB       0x8874\n#define GL_PROGRAM_FORMAT_ASCII_ARB       0x8875\n#define GL_PROGRAM_FORMAT_ARB             0x8876\n#define GL_PROGRAM_INSTRUCTIONS_ARB       0x88A0\n#define GL_MAX_PROGRAM_INSTRUCTIONS_ARB   0x88A1\n#define GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A2\n#define GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A3\n#define GL_PROGRAM_TEMPORARIES_ARB        0x88A4\n#define GL_MAX_PROGRAM_TEMPORARIES_ARB    0x88A5\n#define GL_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A6\n#define GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A7\n#define GL_PROGRAM_PARAMETERS_ARB         0x88A8\n#define GL_MAX_PROGRAM_PARAMETERS_ARB     0x88A9\n#define GL_PROGRAM_NATIVE_PARAMETERS_ARB  0x88AA\n#define GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AB\n#define GL_PROGRAM_ATTRIBS_ARB            0x88AC\n#define GL_MAX_PROGRAM_ATTRIBS_ARB        0x88AD\n#define GL_PROGRAM_NATIVE_ATTRIBS_ARB     0x88AE\n#define GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AF\n#define GL_PROGRAM_ADDRESS_REGISTERS_ARB  0x88B0\n#define GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B1\n#define GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B2\n#define GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B3\n#define GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB 0x88B4\n#define GL_MAX_PROGRAM_ENV_PARAMETERS_ARB 0x88B5\n#define GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB 0x88B6\n#define GL_TRANSPOSE_CURRENT_MATRIX_ARB   0x88B7\n#define GL_MATRIX0_ARB                    0x88C0\n#define GL_MATRIX1_ARB                    0x88C1\n#define GL_MATRIX2_ARB                    0x88C2\n#define GL_MATRIX3_ARB                    0x88C3\n#define GL_MATRIX4_ARB                    0x88C4\n#define GL_MATRIX5_ARB                    0x88C5\n#define GL_MATRIX6_ARB                    0x88C6\n#define GL_MATRIX7_ARB                    0x88C7\n#define GL_MATRIX8_ARB                    0x88C8\n#define GL_MATRIX9_ARB                    0x88C9\n#define GL_MATRIX10_ARB                   0x88CA\n#define GL_MATRIX11_ARB                   0x88CB\n#define GL_MATRIX12_ARB                   0x88CC\n#define GL_MATRIX13_ARB                   0x88CD\n#define GL_MATRIX14_ARB                   0x88CE\n#define GL_MATRIX15_ARB                   0x88CF\n#define GL_MATRIX16_ARB                   0x88D0\n#define GL_MATRIX17_ARB                   0x88D1\n#define GL_MATRIX18_ARB                   0x88D2\n#define GL_MATRIX19_ARB                   0x88D3\n#define GL_MATRIX20_ARB                   0x88D4\n#define GL_MATRIX21_ARB                   0x88D5\n#define GL_MATRIX22_ARB                   0x88D6\n#define GL_MATRIX23_ARB                   0x88D7\n#define GL_MATRIX24_ARB                   0x88D8\n#define GL_MATRIX25_ARB                   0x88D9\n#define GL_MATRIX26_ARB                   0x88DA\n#define GL_MATRIX27_ARB                   0x88DB\n#define GL_MATRIX28_ARB                   0x88DC\n#define GL_MATRIX29_ARB                   0x88DD\n#define GL_MATRIX30_ARB                   0x88DE\n#define GL_MATRIX31_ARB                   0x88DF\n#endif\n\n#ifndef GL_ARB_fragment_program\n#define GL_FRAGMENT_PROGRAM_ARB           0x8804\n#define GL_PROGRAM_ALU_INSTRUCTIONS_ARB   0x8805\n#define GL_PROGRAM_TEX_INSTRUCTIONS_ARB   0x8806\n#define GL_PROGRAM_TEX_INDIRECTIONS_ARB   0x8807\n#define GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x8808\n#define GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x8809\n#define GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x880A\n#define GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB 0x880B\n#define GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB 0x880C\n#define GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB 0x880D\n#define GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x880E\n#define GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x880F\n#define GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x8810\n#define GL_MAX_TEXTURE_COORDS_ARB         0x8871\n#define GL_MAX_TEXTURE_IMAGE_UNITS_ARB    0x8872\n#endif\n\n#ifndef GL_ARB_vertex_buffer_object\n#define GL_BUFFER_SIZE_ARB                0x8764\n#define GL_BUFFER_USAGE_ARB               0x8765\n#define GL_ARRAY_BUFFER_ARB               0x8892\n#define GL_ELEMENT_ARRAY_BUFFER_ARB       0x8893\n#define GL_ARRAY_BUFFER_BINDING_ARB       0x8894\n#define GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB 0x8895\n#define GL_VERTEX_ARRAY_BUFFER_BINDING_ARB 0x8896\n#define GL_NORMAL_ARRAY_BUFFER_BINDING_ARB 0x8897\n#define GL_COLOR_ARRAY_BUFFER_BINDING_ARB 0x8898\n#define GL_INDEX_ARRAY_BUFFER_BINDING_ARB 0x8899\n#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB 0x889A\n#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB 0x889B\n#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB 0x889C\n#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB 0x889D\n#define GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB 0x889E\n#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB 0x889F\n#define GL_READ_ONLY_ARB                  0x88B8\n#define GL_WRITE_ONLY_ARB                 0x88B9\n#define GL_READ_WRITE_ARB                 0x88BA\n#define GL_BUFFER_ACCESS_ARB              0x88BB\n#define GL_BUFFER_MAPPED_ARB              0x88BC\n#define GL_BUFFER_MAP_POINTER_ARB         0x88BD\n#define GL_STREAM_DRAW_ARB                0x88E0\n#define GL_STREAM_READ_ARB                0x88E1\n#define GL_STREAM_COPY_ARB                0x88E2\n#define GL_STATIC_DRAW_ARB                0x88E4\n#define GL_STATIC_READ_ARB                0x88E5\n#define GL_STATIC_COPY_ARB                0x88E6\n#define GL_DYNAMIC_DRAW_ARB               0x88E8\n#define GL_DYNAMIC_READ_ARB               0x88E9\n#define GL_DYNAMIC_COPY_ARB               0x88EA\n#endif\n\n#ifndef GL_ARB_occlusion_query\n#define GL_QUERY_COUNTER_BITS_ARB         0x8864\n#define GL_CURRENT_QUERY_ARB              0x8865\n#define GL_QUERY_RESULT_ARB               0x8866\n#define GL_QUERY_RESULT_AVAILABLE_ARB     0x8867\n#define GL_SAMPLES_PASSED_ARB             0x8914\n#endif\n\n#ifndef GL_ARB_shader_objects\n#define GL_PROGRAM_OBJECT_ARB             0x8B40\n#define GL_SHADER_OBJECT_ARB              0x8B48\n#define GL_OBJECT_TYPE_ARB                0x8B4E\n#define GL_OBJECT_SUBTYPE_ARB             0x8B4F\n#define GL_FLOAT_VEC2_ARB                 0x8B50\n#define GL_FLOAT_VEC3_ARB                 0x8B51\n#define GL_FLOAT_VEC4_ARB                 0x8B52\n#define GL_INT_VEC2_ARB                   0x8B53\n#define GL_INT_VEC3_ARB                   0x8B54\n#define GL_INT_VEC4_ARB                   0x8B55\n#define GL_BOOL_ARB                       0x8B56\n#define GL_BOOL_VEC2_ARB                  0x8B57\n#define GL_BOOL_VEC3_ARB                  0x8B58\n#define GL_BOOL_VEC4_ARB                  0x8B59\n#define GL_FLOAT_MAT2_ARB                 0x8B5A\n#define GL_FLOAT_MAT3_ARB                 0x8B5B\n#define GL_FLOAT_MAT4_ARB                 0x8B5C\n#define GL_SAMPLER_1D_ARB                 0x8B5D\n#define GL_SAMPLER_2D_ARB                 0x8B5E\n#define GL_SAMPLER_3D_ARB                 0x8B5F\n#define GL_SAMPLER_CUBE_ARB               0x8B60\n#define GL_SAMPLER_1D_SHADOW_ARB          0x8B61\n#define GL_SAMPLER_2D_SHADOW_ARB          0x8B62\n#define GL_SAMPLER_2D_RECT_ARB            0x8B63\n#define GL_SAMPLER_2D_RECT_SHADOW_ARB     0x8B64\n#define GL_OBJECT_DELETE_STATUS_ARB       0x8B80\n#define GL_OBJECT_COMPILE_STATUS_ARB      0x8B81\n#define GL_OBJECT_LINK_STATUS_ARB         0x8B82\n#define GL_OBJECT_VALIDATE_STATUS_ARB     0x8B83\n#define GL_OBJECT_INFO_LOG_LENGTH_ARB     0x8B84\n#define GL_OBJECT_ATTACHED_OBJECTS_ARB    0x8B85\n#define GL_OBJECT_ACTIVE_UNIFORMS_ARB     0x8B86\n#define GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB 0x8B87\n#define GL_OBJECT_SHADER_SOURCE_LENGTH_ARB 0x8B88\n#endif\n\n#ifndef GL_ARB_vertex_shader\n#define GL_VERTEX_SHADER_ARB              0x8B31\n#define GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB 0x8B4A\n#define GL_MAX_VARYING_FLOATS_ARB         0x8B4B\n#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB 0x8B4C\n#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB 0x8B4D\n#define GL_OBJECT_ACTIVE_ATTRIBUTES_ARB   0x8B89\n#define GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB 0x8B8A\n#endif\n\n#ifndef GL_ARB_fragment_shader\n#define GL_FRAGMENT_SHADER_ARB            0x8B30\n#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB 0x8B49\n#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB 0x8B8B\n#endif\n\n#ifndef GL_ARB_shading_language_100\n#define GL_SHADING_LANGUAGE_VERSION_ARB   0x8B8C\n#endif\n\n#ifndef GL_ARB_texture_non_power_of_two\n#endif\n\n#ifndef GL_ARB_point_sprite\n#define GL_POINT_SPRITE_ARB               0x8861\n#define GL_COORD_REPLACE_ARB              0x8862\n#endif\n\n#ifndef GL_ARB_fragment_program_shadow\n#endif\n\n#ifndef GL_ARB_draw_buffers\n#define GL_MAX_DRAW_BUFFERS_ARB           0x8824\n#define GL_DRAW_BUFFER0_ARB               0x8825\n#define GL_DRAW_BUFFER1_ARB               0x8826\n#define GL_DRAW_BUFFER2_ARB               0x8827\n#define GL_DRAW_BUFFER3_ARB               0x8828\n#define GL_DRAW_BUFFER4_ARB               0x8829\n#define GL_DRAW_BUFFER5_ARB               0x882A\n#define GL_DRAW_BUFFER6_ARB               0x882B\n#define GL_DRAW_BUFFER7_ARB               0x882C\n#define GL_DRAW_BUFFER8_ARB               0x882D\n#define GL_DRAW_BUFFER9_ARB               0x882E\n#define GL_DRAW_BUFFER10_ARB              0x882F\n#define GL_DRAW_BUFFER11_ARB              0x8830\n#define GL_DRAW_BUFFER12_ARB              0x8831\n#define GL_DRAW_BUFFER13_ARB              0x8832\n#define GL_DRAW_BUFFER14_ARB              0x8833\n#define GL_DRAW_BUFFER15_ARB              0x8834\n#endif\n\n#ifndef GL_ARB_texture_rectangle\n#define GL_TEXTURE_RECTANGLE_ARB          0x84F5\n#define GL_TEXTURE_BINDING_RECTANGLE_ARB  0x84F6\n#define GL_PROXY_TEXTURE_RECTANGLE_ARB    0x84F7\n#define GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB 0x84F8\n#endif\n\n#ifndef GL_ARB_color_buffer_float\n#define GL_RGBA_FLOAT_MODE_ARB            0x8820\n#define GL_CLAMP_VERTEX_COLOR_ARB         0x891A\n#define GL_CLAMP_FRAGMENT_COLOR_ARB       0x891B\n#define GL_CLAMP_READ_COLOR_ARB           0x891C\n#define GL_FIXED_ONLY_ARB                 0x891D\n#endif\n\n#ifndef GL_ARB_half_float_pixel\n#define GL_HALF_FLOAT_ARB                 0x140B\n#endif\n\n#ifndef GL_ARB_texture_float\n#define GL_TEXTURE_RED_TYPE_ARB           0x8C10\n#define GL_TEXTURE_GREEN_TYPE_ARB         0x8C11\n#define GL_TEXTURE_BLUE_TYPE_ARB          0x8C12\n#define GL_TEXTURE_ALPHA_TYPE_ARB         0x8C13\n#define GL_TEXTURE_LUMINANCE_TYPE_ARB     0x8C14\n#define GL_TEXTURE_INTENSITY_TYPE_ARB     0x8C15\n#define GL_TEXTURE_DEPTH_TYPE_ARB         0x8C16\n#define GL_UNSIGNED_NORMALIZED_ARB        0x8C17\n#define GL_RGBA32F_ARB                    0x8814\n#define GL_RGB32F_ARB                     0x8815\n#define GL_ALPHA32F_ARB                   0x8816\n#define GL_INTENSITY32F_ARB               0x8817\n#define GL_LUMINANCE32F_ARB               0x8818\n#define GL_LUMINANCE_ALPHA32F_ARB         0x8819\n#define GL_RGBA16F_ARB                    0x881A\n#define GL_RGB16F_ARB                     0x881B\n#define GL_ALPHA16F_ARB                   0x881C\n#define GL_INTENSITY16F_ARB               0x881D\n#define GL_LUMINANCE16F_ARB               0x881E\n#define GL_LUMINANCE_ALPHA16F_ARB         0x881F\n#endif\n\n#ifndef GL_ARB_pixel_buffer_object\n#define GL_PIXEL_PACK_BUFFER_ARB          0x88EB\n#define GL_PIXEL_UNPACK_BUFFER_ARB        0x88EC\n#define GL_PIXEL_PACK_BUFFER_BINDING_ARB  0x88ED\n#define GL_PIXEL_UNPACK_BUFFER_BINDING_ARB 0x88EF\n#endif\n\n#ifndef GL_EXT_abgr\n#define GL_ABGR_EXT                       0x8000\n#endif\n\n#ifndef GL_EXT_blend_color\n#define GL_CONSTANT_COLOR_EXT             0x8001\n#define GL_ONE_MINUS_CONSTANT_COLOR_EXT   0x8002\n#define GL_CONSTANT_ALPHA_EXT             0x8003\n#define GL_ONE_MINUS_CONSTANT_ALPHA_EXT   0x8004\n#define GL_BLEND_COLOR_EXT                0x8005\n#endif\n\n#ifndef GL_EXT_polygon_offset\n#define GL_POLYGON_OFFSET_EXT             0x8037\n#define GL_POLYGON_OFFSET_FACTOR_EXT      0x8038\n#define GL_POLYGON_OFFSET_BIAS_EXT        0x8039\n#endif\n\n#ifndef GL_EXT_texture\n#define GL_ALPHA4_EXT                     0x803B\n#define GL_ALPHA8_EXT                     0x803C\n#define GL_ALPHA12_EXT                    0x803D\n#define GL_ALPHA16_EXT                    0x803E\n#define GL_LUMINANCE4_EXT                 0x803F\n#define GL_LUMINANCE8_EXT                 0x8040\n#define GL_LUMINANCE12_EXT                0x8041\n#define GL_LUMINANCE16_EXT                0x8042\n#define GL_LUMINANCE4_ALPHA4_EXT          0x8043\n#define GL_LUMINANCE6_ALPHA2_EXT          0x8044\n#define GL_LUMINANCE8_ALPHA8_EXT          0x8045\n#define GL_LUMINANCE12_ALPHA4_EXT         0x8046\n#define GL_LUMINANCE12_ALPHA12_EXT        0x8047\n#define GL_LUMINANCE16_ALPHA16_EXT        0x8048\n#define GL_INTENSITY_EXT                  0x8049\n#define GL_INTENSITY4_EXT                 0x804A\n#define GL_INTENSITY8_EXT                 0x804B\n#define GL_INTENSITY12_EXT                0x804C\n#define GL_INTENSITY16_EXT                0x804D\n#define GL_RGB2_EXT                       0x804E\n#define GL_RGB4_EXT                       0x804F\n#define GL_RGB5_EXT                       0x8050\n#define GL_RGB8_EXT                       0x8051\n#define GL_RGB10_EXT                      0x8052\n#define GL_RGB12_EXT                      0x8053\n#define GL_RGB16_EXT                      0x8054\n#define GL_RGBA2_EXT                      0x8055\n#define GL_RGBA4_EXT                      0x8056\n#define GL_RGB5_A1_EXT                    0x8057\n#define GL_RGBA8_EXT                      0x8058\n#define GL_RGB10_A2_EXT                   0x8059\n#define GL_RGBA12_EXT                     0x805A\n#define GL_RGBA16_EXT                     0x805B\n#define GL_TEXTURE_RED_SIZE_EXT           0x805C\n#define GL_TEXTURE_GREEN_SIZE_EXT         0x805D\n#define GL_TEXTURE_BLUE_SIZE_EXT          0x805E\n#define GL_TEXTURE_ALPHA_SIZE_EXT         0x805F\n#define GL_TEXTURE_LUMINANCE_SIZE_EXT     0x8060\n#define GL_TEXTURE_INTENSITY_SIZE_EXT     0x8061\n#define GL_REPLACE_EXT                    0x8062\n#define GL_PROXY_TEXTURE_1D_EXT           0x8063\n#define GL_PROXY_TEXTURE_2D_EXT           0x8064\n#define GL_TEXTURE_TOO_LARGE_EXT          0x8065\n#endif\n\n#ifndef GL_EXT_texture3D\n#define GL_PACK_SKIP_IMAGES_EXT           0x806B\n#define GL_PACK_IMAGE_HEIGHT_EXT          0x806C\n#define GL_UNPACK_SKIP_IMAGES_EXT         0x806D\n#define GL_UNPACK_IMAGE_HEIGHT_EXT        0x806E\n#define GL_TEXTURE_3D_EXT                 0x806F\n#define GL_PROXY_TEXTURE_3D_EXT           0x8070\n#define GL_TEXTURE_DEPTH_EXT              0x8071\n#define GL_TEXTURE_WRAP_R_EXT             0x8072\n#define GL_MAX_3D_TEXTURE_SIZE_EXT        0x8073\n#endif\n\n#ifndef GL_SGIS_texture_filter4\n#define GL_FILTER4_SGIS                   0x8146\n#define GL_TEXTURE_FILTER4_SIZE_SGIS      0x8147\n#endif\n\n#ifndef GL_EXT_subtexture\n#endif\n\n#ifndef GL_EXT_copy_texture\n#endif\n\n#ifndef GL_EXT_histogram\n#define GL_HISTOGRAM_EXT                  0x8024\n#define GL_PROXY_HISTOGRAM_EXT            0x8025\n#define GL_HISTOGRAM_WIDTH_EXT            0x8026\n#define GL_HISTOGRAM_FORMAT_EXT           0x8027\n#define GL_HISTOGRAM_RED_SIZE_EXT         0x8028\n#define GL_HISTOGRAM_GREEN_SIZE_EXT       0x8029\n#define GL_HISTOGRAM_BLUE_SIZE_EXT        0x802A\n#define GL_HISTOGRAM_ALPHA_SIZE_EXT       0x802B\n#define GL_HISTOGRAM_LUMINANCE_SIZE_EXT   0x802C\n#define GL_HISTOGRAM_SINK_EXT             0x802D\n#define GL_MINMAX_EXT                     0x802E\n#define GL_MINMAX_FORMAT_EXT              0x802F\n#define GL_MINMAX_SINK_EXT                0x8030\n#define GL_TABLE_TOO_LARGE_EXT            0x8031\n#endif\n\n#ifndef GL_EXT_convolution\n#define GL_CONVOLUTION_1D_EXT             0x8010\n#define GL_CONVOLUTION_2D_EXT             0x8011\n#define GL_SEPARABLE_2D_EXT               0x8012\n#define GL_CONVOLUTION_BORDER_MODE_EXT    0x8013\n#define GL_CONVOLUTION_FILTER_SCALE_EXT   0x8014\n#define GL_CONVOLUTION_FILTER_BIAS_EXT    0x8015\n#define GL_REDUCE_EXT                     0x8016\n#define GL_CONVOLUTION_FORMAT_EXT         0x8017\n#define GL_CONVOLUTION_WIDTH_EXT          0x8018\n#define GL_CONVOLUTION_HEIGHT_EXT         0x8019\n#define GL_MAX_CONVOLUTION_WIDTH_EXT      0x801A\n#define GL_MAX_CONVOLUTION_HEIGHT_EXT     0x801B\n#define GL_POST_CONVOLUTION_RED_SCALE_EXT 0x801C\n#define GL_POST_CONVOLUTION_GREEN_SCALE_EXT 0x801D\n#define GL_POST_CONVOLUTION_BLUE_SCALE_EXT 0x801E\n#define GL_POST_CONVOLUTION_ALPHA_SCALE_EXT 0x801F\n#define GL_POST_CONVOLUTION_RED_BIAS_EXT  0x8020\n#define GL_POST_CONVOLUTION_GREEN_BIAS_EXT 0x8021\n#define GL_POST_CONVOLUTION_BLUE_BIAS_EXT 0x8022\n#define GL_POST_CONVOLUTION_ALPHA_BIAS_EXT 0x8023\n#endif\n\n#ifndef GL_SGI_color_matrix\n#define GL_COLOR_MATRIX_SGI               0x80B1\n#define GL_COLOR_MATRIX_STACK_DEPTH_SGI   0x80B2\n#define GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B3\n#define GL_POST_COLOR_MATRIX_RED_SCALE_SGI 0x80B4\n#define GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI 0x80B5\n#define GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI 0x80B6\n#define GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI 0x80B7\n#define GL_POST_COLOR_MATRIX_RED_BIAS_SGI 0x80B8\n#define GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI 0x80B9\n#define GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI 0x80BA\n#define GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI 0x80BB\n#endif\n\n#ifndef GL_SGI_color_table\n#define GL_COLOR_TABLE_SGI                0x80D0\n#define GL_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D1\n#define GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D2\n#define GL_PROXY_COLOR_TABLE_SGI          0x80D3\n#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D4\n#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D5\n#define GL_COLOR_TABLE_SCALE_SGI          0x80D6\n#define GL_COLOR_TABLE_BIAS_SGI           0x80D7\n#define GL_COLOR_TABLE_FORMAT_SGI         0x80D8\n#define GL_COLOR_TABLE_WIDTH_SGI          0x80D9\n#define GL_COLOR_TABLE_RED_SIZE_SGI       0x80DA\n#define GL_COLOR_TABLE_GREEN_SIZE_SGI     0x80DB\n#define GL_COLOR_TABLE_BLUE_SIZE_SGI      0x80DC\n#define GL_COLOR_TABLE_ALPHA_SIZE_SGI     0x80DD\n#define GL_COLOR_TABLE_LUMINANCE_SIZE_SGI 0x80DE\n#define GL_COLOR_TABLE_INTENSITY_SIZE_SGI 0x80DF\n#endif\n\n#ifndef GL_SGIS_pixel_texture\n#define GL_PIXEL_TEXTURE_SGIS             0x8353\n#define GL_PIXEL_FRAGMENT_RGB_SOURCE_SGIS 0x8354\n#define GL_PIXEL_FRAGMENT_ALPHA_SOURCE_SGIS 0x8355\n#define GL_PIXEL_GROUP_COLOR_SGIS         0x8356\n#endif\n\n#ifndef GL_SGIX_pixel_texture\n#define GL_PIXEL_TEX_GEN_SGIX             0x8139\n#define GL_PIXEL_TEX_GEN_MODE_SGIX        0x832B\n#endif\n\n#ifndef GL_SGIS_texture4D\n#define GL_PACK_SKIP_VOLUMES_SGIS         0x8130\n#define GL_PACK_IMAGE_DEPTH_SGIS          0x8131\n#define GL_UNPACK_SKIP_VOLUMES_SGIS       0x8132\n#define GL_UNPACK_IMAGE_DEPTH_SGIS        0x8133\n#define GL_TEXTURE_4D_SGIS                0x8134\n#define GL_PROXY_TEXTURE_4D_SGIS          0x8135\n#define GL_TEXTURE_4DSIZE_SGIS            0x8136\n#define GL_TEXTURE_WRAP_Q_SGIS            0x8137\n#define GL_MAX_4D_TEXTURE_SIZE_SGIS       0x8138\n#define GL_TEXTURE_4D_BINDING_SGIS        0x814F\n#endif\n\n#ifndef GL_SGI_texture_color_table\n#define GL_TEXTURE_COLOR_TABLE_SGI        0x80BC\n#define GL_PROXY_TEXTURE_COLOR_TABLE_SGI  0x80BD\n#endif\n\n#ifndef GL_EXT_cmyka\n#define GL_CMYK_EXT                       0x800C\n#define GL_CMYKA_EXT                      0x800D\n#define GL_PACK_CMYK_HINT_EXT             0x800E\n#define GL_UNPACK_CMYK_HINT_EXT           0x800F\n#endif\n\n#ifndef GL_EXT_texture_object\n#define GL_TEXTURE_PRIORITY_EXT           0x8066\n#define GL_TEXTURE_RESIDENT_EXT           0x8067\n#define GL_TEXTURE_1D_BINDING_EXT         0x8068\n#define GL_TEXTURE_2D_BINDING_EXT         0x8069\n#define GL_TEXTURE_3D_BINDING_EXT         0x806A\n#endif\n\n#ifndef GL_SGIS_detail_texture\n#define GL_DETAIL_TEXTURE_2D_SGIS         0x8095\n#define GL_DETAIL_TEXTURE_2D_BINDING_SGIS 0x8096\n#define GL_LINEAR_DETAIL_SGIS             0x8097\n#define GL_LINEAR_DETAIL_ALPHA_SGIS       0x8098\n#define GL_LINEAR_DETAIL_COLOR_SGIS       0x8099\n#define GL_DETAIL_TEXTURE_LEVEL_SGIS      0x809A\n#define GL_DETAIL_TEXTURE_MODE_SGIS       0x809B\n#define GL_DETAIL_TEXTURE_FUNC_POINTS_SGIS 0x809C\n#endif\n\n#ifndef GL_SGIS_sharpen_texture\n#define GL_LINEAR_SHARPEN_SGIS            0x80AD\n#define GL_LINEAR_SHARPEN_ALPHA_SGIS      0x80AE\n#define GL_LINEAR_SHARPEN_COLOR_SGIS      0x80AF\n#define GL_SHARPEN_TEXTURE_FUNC_POINTS_SGIS 0x80B0\n#endif\n\n#ifndef GL_EXT_packed_pixels\n#define GL_UNSIGNED_BYTE_3_3_2_EXT        0x8032\n#define GL_UNSIGNED_SHORT_4_4_4_4_EXT     0x8033\n#define GL_UNSIGNED_SHORT_5_5_5_1_EXT     0x8034\n#define GL_UNSIGNED_INT_8_8_8_8_EXT       0x8035\n#define GL_UNSIGNED_INT_10_10_10_2_EXT    0x8036\n#endif\n\n#ifndef GL_SGIS_texture_lod\n#define GL_TEXTURE_MIN_LOD_SGIS           0x813A\n#define GL_TEXTURE_MAX_LOD_SGIS           0x813B\n#define GL_TEXTURE_BASE_LEVEL_SGIS        0x813C\n#define GL_TEXTURE_MAX_LEVEL_SGIS         0x813D\n#endif\n\n#ifndef GL_SGIS_multisample\n#define GL_MULTISAMPLE_SGIS               0x809D\n#define GL_SAMPLE_ALPHA_TO_MASK_SGIS      0x809E\n#define GL_SAMPLE_ALPHA_TO_ONE_SGIS       0x809F\n#define GL_SAMPLE_MASK_SGIS               0x80A0\n#define GL_1PASS_SGIS                     0x80A1\n#define GL_2PASS_0_SGIS                   0x80A2\n#define GL_2PASS_1_SGIS                   0x80A3\n#define GL_4PASS_0_SGIS                   0x80A4\n#define GL_4PASS_1_SGIS                   0x80A5\n#define GL_4PASS_2_SGIS                   0x80A6\n#define GL_4PASS_3_SGIS                   0x80A7\n#define GL_SAMPLE_BUFFERS_SGIS            0x80A8\n#define GL_SAMPLES_SGIS                   0x80A9\n#define GL_SAMPLE_MASK_VALUE_SGIS         0x80AA\n#define GL_SAMPLE_MASK_INVERT_SGIS        0x80AB\n#define GL_SAMPLE_PATTERN_SGIS            0x80AC\n#endif\n\n#ifndef GL_EXT_rescale_normal\n#define GL_RESCALE_NORMAL_EXT             0x803A\n#endif\n\n#ifndef GL_EXT_vertex_array\n#define GL_VERTEX_ARRAY_EXT               0x8074\n#define GL_NORMAL_ARRAY_EXT               0x8075\n#define GL_COLOR_ARRAY_EXT                0x8076\n#define GL_INDEX_ARRAY_EXT                0x8077\n#define GL_TEXTURE_COORD_ARRAY_EXT        0x8078\n#define GL_EDGE_FLAG_ARRAY_EXT            0x8079\n#define GL_VERTEX_ARRAY_SIZE_EXT          0x807A\n#define GL_VERTEX_ARRAY_TYPE_EXT          0x807B\n#define GL_VERTEX_ARRAY_STRIDE_EXT        0x807C\n#define GL_VERTEX_ARRAY_COUNT_EXT         0x807D\n#define GL_NORMAL_ARRAY_TYPE_EXT          0x807E\n#define GL_NORMAL_ARRAY_STRIDE_EXT        0x807F\n#define GL_NORMAL_ARRAY_COUNT_EXT         0x8080\n#define GL_COLOR_ARRAY_SIZE_EXT           0x8081\n#define GL_COLOR_ARRAY_TYPE_EXT           0x8082\n#define GL_COLOR_ARRAY_STRIDE_EXT         0x8083\n#define GL_COLOR_ARRAY_COUNT_EXT          0x8084\n#define GL_INDEX_ARRAY_TYPE_EXT           0x8085\n#define GL_INDEX_ARRAY_STRIDE_EXT         0x8086\n#define GL_INDEX_ARRAY_COUNT_EXT          0x8087\n#define GL_TEXTURE_COORD_ARRAY_SIZE_EXT   0x8088\n#define GL_TEXTURE_COORD_ARRAY_TYPE_EXT   0x8089\n#define GL_TEXTURE_COORD_ARRAY_STRIDE_EXT 0x808A\n#define GL_TEXTURE_COORD_ARRAY_COUNT_EXT  0x808B\n#define GL_EDGE_FLAG_ARRAY_STRIDE_EXT     0x808C\n#define GL_EDGE_FLAG_ARRAY_COUNT_EXT      0x808D\n#define GL_VERTEX_ARRAY_POINTER_EXT       0x808E\n#define GL_NORMAL_ARRAY_POINTER_EXT       0x808F\n#define GL_COLOR_ARRAY_POINTER_EXT        0x8090\n#define GL_INDEX_ARRAY_POINTER_EXT        0x8091\n#define GL_TEXTURE_COORD_ARRAY_POINTER_EXT 0x8092\n#define GL_EDGE_FLAG_ARRAY_POINTER_EXT    0x8093\n#endif\n\n#ifndef GL_EXT_misc_attribute\n#endif\n\n#ifndef GL_SGIS_generate_mipmap\n#define GL_GENERATE_MIPMAP_SGIS           0x8191\n#define GL_GENERATE_MIPMAP_HINT_SGIS      0x8192\n#endif\n\n#ifndef GL_SGIX_clipmap\n#define GL_LINEAR_CLIPMAP_LINEAR_SGIX     0x8170\n#define GL_TEXTURE_CLIPMAP_CENTER_SGIX    0x8171\n#define GL_TEXTURE_CLIPMAP_FRAME_SGIX     0x8172\n#define GL_TEXTURE_CLIPMAP_OFFSET_SGIX    0x8173\n#define GL_TEXTURE_CLIPMAP_VIRTUAL_DEPTH_SGIX 0x8174\n#define GL_TEXTURE_CLIPMAP_LOD_OFFSET_SGIX 0x8175\n#define GL_TEXTURE_CLIPMAP_DEPTH_SGIX     0x8176\n#define GL_MAX_CLIPMAP_DEPTH_SGIX         0x8177\n#define GL_MAX_CLIPMAP_VIRTUAL_DEPTH_SGIX 0x8178\n#define GL_NEAREST_CLIPMAP_NEAREST_SGIX   0x844D\n#define GL_NEAREST_CLIPMAP_LINEAR_SGIX    0x844E\n#define GL_LINEAR_CLIPMAP_NEAREST_SGIX    0x844F\n#endif\n\n#ifndef GL_SGIX_shadow\n#define GL_TEXTURE_COMPARE_SGIX           0x819A\n#define GL_TEXTURE_COMPARE_OPERATOR_SGIX  0x819B\n#define GL_TEXTURE_LEQUAL_R_SGIX          0x819C\n#define GL_TEXTURE_GEQUAL_R_SGIX          0x819D\n#endif\n\n#ifndef GL_SGIS_texture_edge_clamp\n#define GL_CLAMP_TO_EDGE_SGIS             0x812F\n#endif\n\n#ifndef GL_SGIS_texture_border_clamp\n#define GL_CLAMP_TO_BORDER_SGIS           0x812D\n#endif\n\n#ifndef GL_EXT_blend_minmax\n#define GL_FUNC_ADD_EXT                   0x8006\n#define GL_MIN_EXT                        0x8007\n#define GL_MAX_EXT                        0x8008\n#define GL_BLEND_EQUATION_EXT             0x8009\n#endif\n\n#ifndef GL_EXT_blend_subtract\n#define GL_FUNC_SUBTRACT_EXT              0x800A\n#define GL_FUNC_REVERSE_SUBTRACT_EXT      0x800B\n#endif\n\n#ifndef GL_EXT_blend_logic_op\n#endif\n\n#ifndef GL_SGIX_interlace\n#define GL_INTERLACE_SGIX                 0x8094\n#endif\n\n#ifndef GL_SGIX_pixel_tiles\n#define GL_PIXEL_TILE_BEST_ALIGNMENT_SGIX 0x813E\n#define GL_PIXEL_TILE_CACHE_INCREMENT_SGIX 0x813F\n#define GL_PIXEL_TILE_WIDTH_SGIX          0x8140\n#define GL_PIXEL_TILE_HEIGHT_SGIX         0x8141\n#define GL_PIXEL_TILE_GRID_WIDTH_SGIX     0x8142\n#define GL_PIXEL_TILE_GRID_HEIGHT_SGIX    0x8143\n#define GL_PIXEL_TILE_GRID_DEPTH_SGIX     0x8144\n#define GL_PIXEL_TILE_CACHE_SIZE_SGIX     0x8145\n#endif\n\n#ifndef GL_SGIS_texture_select\n#define GL_DUAL_ALPHA4_SGIS               0x8110\n#define GL_DUAL_ALPHA8_SGIS               0x8111\n#define GL_DUAL_ALPHA12_SGIS              0x8112\n#define GL_DUAL_ALPHA16_SGIS              0x8113\n#define GL_DUAL_LUMINANCE4_SGIS           0x8114\n#define GL_DUAL_LUMINANCE8_SGIS           0x8115\n#define GL_DUAL_LUMINANCE12_SGIS          0x8116\n#define GL_DUAL_LUMINANCE16_SGIS          0x8117\n#define GL_DUAL_INTENSITY4_SGIS           0x8118\n#define GL_DUAL_INTENSITY8_SGIS           0x8119\n#define GL_DUAL_INTENSITY12_SGIS          0x811A\n#define GL_DUAL_INTENSITY16_SGIS          0x811B\n#define GL_DUAL_LUMINANCE_ALPHA4_SGIS     0x811C\n#define GL_DUAL_LUMINANCE_ALPHA8_SGIS     0x811D\n#define GL_QUAD_ALPHA4_SGIS               0x811E\n#define GL_QUAD_ALPHA8_SGIS               0x811F\n#define GL_QUAD_LUMINANCE4_SGIS           0x8120\n#define GL_QUAD_LUMINANCE8_SGIS           0x8121\n#define GL_QUAD_INTENSITY4_SGIS           0x8122\n#define GL_QUAD_INTENSITY8_SGIS           0x8123\n#define GL_DUAL_TEXTURE_SELECT_SGIS       0x8124\n#define GL_QUAD_TEXTURE_SELECT_SGIS       0x8125\n#endif\n\n#ifndef GL_SGIX_sprite\n#define GL_SPRITE_SGIX                    0x8148\n#define GL_SPRITE_MODE_SGIX               0x8149\n#define GL_SPRITE_AXIS_SGIX               0x814A\n#define GL_SPRITE_TRANSLATION_SGIX        0x814B\n#define GL_SPRITE_AXIAL_SGIX              0x814C\n#define GL_SPRITE_OBJECT_ALIGNED_SGIX     0x814D\n#define GL_SPRITE_EYE_ALIGNED_SGIX        0x814E\n#endif\n\n#ifndef GL_SGIX_texture_multi_buffer\n#define GL_TEXTURE_MULTI_BUFFER_HINT_SGIX 0x812E\n#endif\n\n#ifndef GL_EXT_point_parameters\n#define GL_POINT_SIZE_MIN_EXT             0x8126\n#define GL_POINT_SIZE_MAX_EXT             0x8127\n#define GL_POINT_FADE_THRESHOLD_SIZE_EXT  0x8128\n#define GL_DISTANCE_ATTENUATION_EXT       0x8129\n#endif\n\n#ifndef GL_SGIS_point_parameters\n#define GL_POINT_SIZE_MIN_SGIS            0x8126\n#define GL_POINT_SIZE_MAX_SGIS            0x8127\n#define GL_POINT_FADE_THRESHOLD_SIZE_SGIS 0x8128\n#define GL_DISTANCE_ATTENUATION_SGIS      0x8129\n#endif\n\n#ifndef GL_SGIX_instruments\n#define GL_INSTRUMENT_BUFFER_POINTER_SGIX 0x8180\n#define GL_INSTRUMENT_MEASUREMENTS_SGIX   0x8181\n#endif\n\n#ifndef GL_SGIX_texture_scale_bias\n#define GL_POST_TEXTURE_FILTER_BIAS_SGIX  0x8179\n#define GL_POST_TEXTURE_FILTER_SCALE_SGIX 0x817A\n#define GL_POST_TEXTURE_FILTER_BIAS_RANGE_SGIX 0x817B\n#define GL_POST_TEXTURE_FILTER_SCALE_RANGE_SGIX 0x817C\n#endif\n\n#ifndef GL_SGIX_framezoom\n#define GL_FRAMEZOOM_SGIX                 0x818B\n#define GL_FRAMEZOOM_FACTOR_SGIX          0x818C\n#define GL_MAX_FRAMEZOOM_FACTOR_SGIX      0x818D\n#endif\n\n#ifndef GL_SGIX_tag_sample_buffer\n#endif\n\n#ifndef GL_FfdMaskSGIX\n#define GL_TEXTURE_DEFORMATION_BIT_SGIX   0x00000001\n#define GL_GEOMETRY_DEFORMATION_BIT_SGIX  0x00000002\n#endif\n\n#ifndef GL_SGIX_polynomial_ffd\n#define GL_GEOMETRY_DEFORMATION_SGIX      0x8194\n#define GL_TEXTURE_DEFORMATION_SGIX       0x8195\n#define GL_DEFORMATIONS_MASK_SGIX         0x8196\n#define GL_MAX_DEFORMATION_ORDER_SGIX     0x8197\n#endif\n\n#ifndef GL_SGIX_reference_plane\n#define GL_REFERENCE_PLANE_SGIX           0x817D\n#define GL_REFERENCE_PLANE_EQUATION_SGIX  0x817E\n#endif\n\n#ifndef GL_SGIX_flush_raster\n#endif\n\n#ifndef GL_SGIX_depth_texture\n#define GL_DEPTH_COMPONENT16_SGIX         0x81A5\n#define GL_DEPTH_COMPONENT24_SGIX         0x81A6\n#define GL_DEPTH_COMPONENT32_SGIX         0x81A7\n#endif\n\n#ifndef GL_SGIS_fog_function\n#define GL_FOG_FUNC_SGIS                  0x812A\n#define GL_FOG_FUNC_POINTS_SGIS           0x812B\n#define GL_MAX_FOG_FUNC_POINTS_SGIS       0x812C\n#endif\n\n#ifndef GL_SGIX_fog_offset\n#define GL_FOG_OFFSET_SGIX                0x8198\n#define GL_FOG_OFFSET_VALUE_SGIX          0x8199\n#endif\n\n#ifndef GL_HP_image_transform\n#define GL_IMAGE_SCALE_X_HP               0x8155\n#define GL_IMAGE_SCALE_Y_HP               0x8156\n#define GL_IMAGE_TRANSLATE_X_HP           0x8157\n#define GL_IMAGE_TRANSLATE_Y_HP           0x8158\n#define GL_IMAGE_ROTATE_ANGLE_HP          0x8159\n#define GL_IMAGE_ROTATE_ORIGIN_X_HP       0x815A\n#define GL_IMAGE_ROTATE_ORIGIN_Y_HP       0x815B\n#define GL_IMAGE_MAG_FILTER_HP            0x815C\n#define GL_IMAGE_MIN_FILTER_HP            0x815D\n#define GL_IMAGE_CUBIC_WEIGHT_HP          0x815E\n#define GL_CUBIC_HP                       0x815F\n#define GL_AVERAGE_HP                     0x8160\n#define GL_IMAGE_TRANSFORM_2D_HP          0x8161\n#define GL_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP 0x8162\n#define GL_PROXY_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP 0x8163\n#endif\n\n#ifndef GL_HP_convolution_border_modes\n#define GL_IGNORE_BORDER_HP               0x8150\n#define GL_CONSTANT_BORDER_HP             0x8151\n#define GL_REPLICATE_BORDER_HP            0x8153\n#define GL_CONVOLUTION_BORDER_COLOR_HP    0x8154\n#endif\n\n#ifndef GL_INGR_palette_buffer\n#endif\n\n#ifndef GL_SGIX_texture_add_env\n#define GL_TEXTURE_ENV_BIAS_SGIX          0x80BE\n#endif\n\n#ifndef GL_EXT_color_subtable\n#endif\n\n#ifndef GL_PGI_vertex_hints\n#define GL_VERTEX_DATA_HINT_PGI           0x1A22A\n#define GL_VERTEX_CONSISTENT_HINT_PGI     0x1A22B\n#define GL_MATERIAL_SIDE_HINT_PGI         0x1A22C\n#define GL_MAX_VERTEX_HINT_PGI            0x1A22D\n#define GL_COLOR3_BIT_PGI                 0x00010000\n#define GL_COLOR4_BIT_PGI                 0x00020000\n#define GL_EDGEFLAG_BIT_PGI               0x00040000\n#define GL_INDEX_BIT_PGI                  0x00080000\n#define GL_MAT_AMBIENT_BIT_PGI            0x00100000\n#define GL_MAT_AMBIENT_AND_DIFFUSE_BIT_PGI 0x00200000\n#define GL_MAT_DIFFUSE_BIT_PGI            0x00400000\n#define GL_MAT_EMISSION_BIT_PGI           0x00800000\n#define GL_MAT_COLOR_INDEXES_BIT_PGI      0x01000000\n#define GL_MAT_SHININESS_BIT_PGI          0x02000000\n#define GL_MAT_SPECULAR_BIT_PGI           0x04000000\n#define GL_NORMAL_BIT_PGI                 0x08000000\n#define GL_TEXCOORD1_BIT_PGI              0x10000000\n#define GL_TEXCOORD2_BIT_PGI              0x20000000\n#define GL_TEXCOORD3_BIT_PGI              0x40000000\n#define GL_TEXCOORD4_BIT_PGI              0x80000000\n#define GL_VERTEX23_BIT_PGI               0x00000004\n#define GL_VERTEX4_BIT_PGI                0x00000008\n#endif\n\n#ifndef GL_PGI_misc_hints\n#define GL_PREFER_DOUBLEBUFFER_HINT_PGI   0x1A1F8\n#define GL_CONSERVE_MEMORY_HINT_PGI       0x1A1FD\n#define GL_RECLAIM_MEMORY_HINT_PGI        0x1A1FE\n#define GL_NATIVE_GRAPHICS_HANDLE_PGI     0x1A202\n#define GL_NATIVE_GRAPHICS_BEGIN_HINT_PGI 0x1A203\n#define GL_NATIVE_GRAPHICS_END_HINT_PGI   0x1A204\n#define GL_ALWAYS_FAST_HINT_PGI           0x1A20C\n#define GL_ALWAYS_SOFT_HINT_PGI           0x1A20D\n#define GL_ALLOW_DRAW_OBJ_HINT_PGI        0x1A20E\n#define GL_ALLOW_DRAW_WIN_HINT_PGI        0x1A20F\n#define GL_ALLOW_DRAW_FRG_HINT_PGI        0x1A210\n#define GL_ALLOW_DRAW_MEM_HINT_PGI        0x1A211\n#define GL_STRICT_DEPTHFUNC_HINT_PGI      0x1A216\n#define GL_STRICT_LIGHTING_HINT_PGI       0x1A217\n#define GL_STRICT_SCISSOR_HINT_PGI        0x1A218\n#define GL_FULL_STIPPLE_HINT_PGI          0x1A219\n#define GL_CLIP_NEAR_HINT_PGI             0x1A220\n#define GL_CLIP_FAR_HINT_PGI              0x1A221\n#define GL_WIDE_LINE_HINT_PGI             0x1A222\n#define GL_BACK_NORMALS_HINT_PGI          0x1A223\n#endif\n\n#ifndef GL_EXT_paletted_texture\n#define GL_COLOR_INDEX1_EXT               0x80E2\n#define GL_COLOR_INDEX2_EXT               0x80E3\n#define GL_COLOR_INDEX4_EXT               0x80E4\n#define GL_COLOR_INDEX8_EXT               0x80E5\n#define GL_COLOR_INDEX12_EXT              0x80E6\n#define GL_COLOR_INDEX16_EXT              0x80E7\n#define GL_TEXTURE_INDEX_SIZE_EXT         0x80ED\n#endif\n\n#ifndef GL_EXT_clip_volume_hint\n#define GL_CLIP_VOLUME_CLIPPING_HINT_EXT  0x80F0\n#endif\n\n#ifndef GL_SGIX_list_priority\n#define GL_LIST_PRIORITY_SGIX             0x8182\n#endif\n\n#ifndef GL_SGIX_ir_instrument1\n#define GL_IR_INSTRUMENT1_SGIX            0x817F\n#endif\n\n#ifndef GL_SGIX_calligraphic_fragment\n#define GL_CALLIGRAPHIC_FRAGMENT_SGIX     0x8183\n#endif\n\n#ifndef GL_SGIX_texture_lod_bias\n#define GL_TEXTURE_LOD_BIAS_S_SGIX        0x818E\n#define GL_TEXTURE_LOD_BIAS_T_SGIX        0x818F\n#define GL_TEXTURE_LOD_BIAS_R_SGIX        0x8190\n#endif\n\n#ifndef GL_SGIX_shadow_ambient\n#define GL_SHADOW_AMBIENT_SGIX            0x80BF\n#endif\n\n#ifndef GL_EXT_index_texture\n#endif\n\n#ifndef GL_EXT_index_material\n#define GL_INDEX_MATERIAL_EXT             0x81B8\n#define GL_INDEX_MATERIAL_PARAMETER_EXT   0x81B9\n#define GL_INDEX_MATERIAL_FACE_EXT        0x81BA\n#endif\n\n#ifndef GL_EXT_index_func\n#define GL_INDEX_TEST_EXT                 0x81B5\n#define GL_INDEX_TEST_FUNC_EXT            0x81B6\n#define GL_INDEX_TEST_REF_EXT             0x81B7\n#endif\n\n#ifndef GL_EXT_index_array_formats\n#define GL_IUI_V2F_EXT                    0x81AD\n#define GL_IUI_V3F_EXT                    0x81AE\n#define GL_IUI_N3F_V2F_EXT                0x81AF\n#define GL_IUI_N3F_V3F_EXT                0x81B0\n#define GL_T2F_IUI_V2F_EXT                0x81B1\n#define GL_T2F_IUI_V3F_EXT                0x81B2\n#define GL_T2F_IUI_N3F_V2F_EXT            0x81B3\n#define GL_T2F_IUI_N3F_V3F_EXT            0x81B4\n#endif\n\n#ifndef GL_EXT_compiled_vertex_array\n#define GL_ARRAY_ELEMENT_LOCK_FIRST_EXT   0x81A8\n#define GL_ARRAY_ELEMENT_LOCK_COUNT_EXT   0x81A9\n#endif\n\n#ifndef GL_EXT_cull_vertex\n#define GL_CULL_VERTEX_EXT                0x81AA\n#define GL_CULL_VERTEX_EYE_POSITION_EXT   0x81AB\n#define GL_CULL_VERTEX_OBJECT_POSITION_EXT 0x81AC\n#endif\n\n#ifndef GL_SGIX_ycrcb\n#define GL_YCRCB_422_SGIX                 0x81BB\n#define GL_YCRCB_444_SGIX                 0x81BC\n#endif\n\n#ifndef GL_SGIX_fragment_lighting\n#define GL_FRAGMENT_LIGHTING_SGIX         0x8400\n#define GL_FRAGMENT_COLOR_MATERIAL_SGIX   0x8401\n#define GL_FRAGMENT_COLOR_MATERIAL_FACE_SGIX 0x8402\n#define GL_FRAGMENT_COLOR_MATERIAL_PARAMETER_SGIX 0x8403\n#define GL_MAX_FRAGMENT_LIGHTS_SGIX       0x8404\n#define GL_MAX_ACTIVE_LIGHTS_SGIX         0x8405\n#define GL_CURRENT_RASTER_NORMAL_SGIX     0x8406\n#define GL_LIGHT_ENV_MODE_SGIX            0x8407\n#define GL_FRAGMENT_LIGHT_MODEL_LOCAL_VIEWER_SGIX 0x8408\n#define GL_FRAGMENT_LIGHT_MODEL_TWO_SIDE_SGIX 0x8409\n#define GL_FRAGMENT_LIGHT_MODEL_AMBIENT_SGIX 0x840A\n#define GL_FRAGMENT_LIGHT_MODEL_NORMAL_INTERPOLATION_SGIX 0x840B\n#define GL_FRAGMENT_LIGHT0_SGIX           0x840C\n#define GL_FRAGMENT_LIGHT1_SGIX           0x840D\n#define GL_FRAGMENT_LIGHT2_SGIX           0x840E\n#define GL_FRAGMENT_LIGHT3_SGIX           0x840F\n#define GL_FRAGMENT_LIGHT4_SGIX           0x8410\n#define GL_FRAGMENT_LIGHT5_SGIX           0x8411\n#define GL_FRAGMENT_LIGHT6_SGIX           0x8412\n#define GL_FRAGMENT_LIGHT7_SGIX           0x8413\n#endif\n\n#ifndef GL_IBM_rasterpos_clip\n#define GL_RASTER_POSITION_UNCLIPPED_IBM  0x19262\n#endif\n\n#ifndef GL_HP_texture_lighting\n#define GL_TEXTURE_LIGHTING_MODE_HP       0x8167\n#define GL_TEXTURE_POST_SPECULAR_HP       0x8168\n#define GL_TEXTURE_PRE_SPECULAR_HP        0x8169\n#endif\n\n#ifndef GL_EXT_draw_range_elements\n#define GL_MAX_ELEMENTS_VERTICES_EXT      0x80E8\n#define GL_MAX_ELEMENTS_INDICES_EXT       0x80E9\n#endif\n\n#ifndef GL_WIN_phong_shading\n#define GL_PHONG_WIN                      0x80EA\n#define GL_PHONG_HINT_WIN                 0x80EB\n#endif\n\n#ifndef GL_WIN_specular_fog\n#define GL_FOG_SPECULAR_TEXTURE_WIN       0x80EC\n#endif\n\n#ifndef GL_EXT_light_texture\n#define GL_FRAGMENT_MATERIAL_EXT          0x8349\n#define GL_FRAGMENT_NORMAL_EXT            0x834A\n#define GL_FRAGMENT_COLOR_EXT             0x834C\n#define GL_ATTENUATION_EXT                0x834D\n#define GL_SHADOW_ATTENUATION_EXT         0x834E\n#define GL_TEXTURE_APPLICATION_MODE_EXT   0x834F\n#define GL_TEXTURE_LIGHT_EXT              0x8350\n#define GL_TEXTURE_MATERIAL_FACE_EXT      0x8351\n#define GL_TEXTURE_MATERIAL_PARAMETER_EXT 0x8352\n/* reuse GL_FRAGMENT_DEPTH_EXT */\n#endif\n\n#ifndef GL_SGIX_blend_alpha_minmax\n#define GL_ALPHA_MIN_SGIX                 0x8320\n#define GL_ALPHA_MAX_SGIX                 0x8321\n#endif\n\n#ifndef GL_SGIX_impact_pixel_texture\n#define GL_PIXEL_TEX_GEN_Q_CEILING_SGIX   0x8184\n#define GL_PIXEL_TEX_GEN_Q_ROUND_SGIX     0x8185\n#define GL_PIXEL_TEX_GEN_Q_FLOOR_SGIX     0x8186\n#define GL_PIXEL_TEX_GEN_ALPHA_REPLACE_SGIX 0x8187\n#define GL_PIXEL_TEX_GEN_ALPHA_NO_REPLACE_SGIX 0x8188\n#define GL_PIXEL_TEX_GEN_ALPHA_LS_SGIX    0x8189\n#define GL_PIXEL_TEX_GEN_ALPHA_MS_SGIX    0x818A\n#endif\n\n#ifndef GL_EXT_bgra\n#define GL_BGR_EXT                        0x80E0\n#define GL_BGRA_EXT                       0x80E1\n#endif\n\n#ifndef GL_SGIX_async\n#define GL_ASYNC_MARKER_SGIX              0x8329\n#endif\n\n#ifndef GL_SGIX_async_pixel\n#define GL_ASYNC_TEX_IMAGE_SGIX           0x835C\n#define GL_ASYNC_DRAW_PIXELS_SGIX         0x835D\n#define GL_ASYNC_READ_PIXELS_SGIX         0x835E\n#define GL_MAX_ASYNC_TEX_IMAGE_SGIX       0x835F\n#define GL_MAX_ASYNC_DRAW_PIXELS_SGIX     0x8360\n#define GL_MAX_ASYNC_READ_PIXELS_SGIX     0x8361\n#endif\n\n#ifndef GL_SGIX_async_histogram\n#define GL_ASYNC_HISTOGRAM_SGIX           0x832C\n#define GL_MAX_ASYNC_HISTOGRAM_SGIX       0x832D\n#endif\n\n#ifndef GL_INTEL_texture_scissor\n#endif\n\n#ifndef GL_INTEL_parallel_arrays\n#define GL_PARALLEL_ARRAYS_INTEL          0x83F4\n#define GL_VERTEX_ARRAY_PARALLEL_POINTERS_INTEL 0x83F5\n#define GL_NORMAL_ARRAY_PARALLEL_POINTERS_INTEL 0x83F6\n#define GL_COLOR_ARRAY_PARALLEL_POINTERS_INTEL 0x83F7\n#define GL_TEXTURE_COORD_ARRAY_PARALLEL_POINTERS_INTEL 0x83F8\n#endif\n\n#ifndef GL_HP_occlusion_test\n#define GL_OCCLUSION_TEST_HP              0x8165\n#define GL_OCCLUSION_TEST_RESULT_HP       0x8166\n#endif\n\n#ifndef GL_EXT_pixel_transform\n#define GL_PIXEL_TRANSFORM_2D_EXT         0x8330\n#define GL_PIXEL_MAG_FILTER_EXT           0x8331\n#define GL_PIXEL_MIN_FILTER_EXT           0x8332\n#define GL_PIXEL_CUBIC_WEIGHT_EXT         0x8333\n#define GL_CUBIC_EXT                      0x8334\n#define GL_AVERAGE_EXT                    0x8335\n#define GL_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8336\n#define GL_MAX_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8337\n#define GL_PIXEL_TRANSFORM_2D_MATRIX_EXT  0x8338\n#endif\n\n#ifndef GL_EXT_pixel_transform_color_table\n#endif\n\n#ifndef GL_EXT_shared_texture_palette\n#define GL_SHARED_TEXTURE_PALETTE_EXT     0x81FB\n#endif\n\n#ifndef GL_EXT_separate_specular_color\n#define GL_LIGHT_MODEL_COLOR_CONTROL_EXT  0x81F8\n#define GL_SINGLE_COLOR_EXT               0x81F9\n#define GL_SEPARATE_SPECULAR_COLOR_EXT    0x81FA\n#endif\n\n#ifndef GL_EXT_secondary_color\n#define GL_COLOR_SUM_EXT                  0x8458\n#define GL_CURRENT_SECONDARY_COLOR_EXT    0x8459\n#define GL_SECONDARY_COLOR_ARRAY_SIZE_EXT 0x845A\n#define GL_SECONDARY_COLOR_ARRAY_TYPE_EXT 0x845B\n#define GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT 0x845C\n#define GL_SECONDARY_COLOR_ARRAY_POINTER_EXT 0x845D\n#define GL_SECONDARY_COLOR_ARRAY_EXT      0x845E\n#endif\n\n#ifndef GL_EXT_texture_perturb_normal\n#define GL_PERTURB_EXT                    0x85AE\n#define GL_TEXTURE_NORMAL_EXT             0x85AF\n#endif\n\n#ifndef GL_EXT_multi_draw_arrays\n#endif\n\n#ifndef GL_EXT_fog_coord\n#define GL_FOG_COORDINATE_SOURCE_EXT      0x8450\n#define GL_FOG_COORDINATE_EXT             0x8451\n#define GL_FRAGMENT_DEPTH_EXT             0x8452\n#define GL_CURRENT_FOG_COORDINATE_EXT     0x8453\n#define GL_FOG_COORDINATE_ARRAY_TYPE_EXT  0x8454\n#define GL_FOG_COORDINATE_ARRAY_STRIDE_EXT 0x8455\n#define GL_FOG_COORDINATE_ARRAY_POINTER_EXT 0x8456\n#define GL_FOG_COORDINATE_ARRAY_EXT       0x8457\n#endif\n\n#ifndef GL_REND_screen_coordinates\n#define GL_SCREEN_COORDINATES_REND        0x8490\n#define GL_INVERTED_SCREEN_W_REND         0x8491\n#endif\n\n#ifndef GL_EXT_coordinate_frame\n#define GL_TANGENT_ARRAY_EXT              0x8439\n#define GL_BINORMAL_ARRAY_EXT             0x843A\n#define GL_CURRENT_TANGENT_EXT            0x843B\n#define GL_CURRENT_BINORMAL_EXT           0x843C\n#define GL_TANGENT_ARRAY_TYPE_EXT         0x843E\n#define GL_TANGENT_ARRAY_STRIDE_EXT       0x843F\n#define GL_BINORMAL_ARRAY_TYPE_EXT        0x8440\n#define GL_BINORMAL_ARRAY_STRIDE_EXT      0x8441\n#define GL_TANGENT_ARRAY_POINTER_EXT      0x8442\n#define GL_BINORMAL_ARRAY_POINTER_EXT     0x8443\n#define GL_MAP1_TANGENT_EXT               0x8444\n#define GL_MAP2_TANGENT_EXT               0x8445\n#define GL_MAP1_BINORMAL_EXT              0x8446\n#define GL_MAP2_BINORMAL_EXT              0x8447\n#endif\n\n#ifndef GL_EXT_texture_env_combine\n#define GL_COMBINE_EXT                    0x8570\n#define GL_COMBINE_RGB_EXT                0x8571\n#define GL_COMBINE_ALPHA_EXT              0x8572\n#define GL_RGB_SCALE_EXT                  0x8573\n#define GL_ADD_SIGNED_EXT                 0x8574\n#define GL_INTERPOLATE_EXT                0x8575\n#define GL_CONSTANT_EXT                   0x8576\n#define GL_PRIMARY_COLOR_EXT              0x8577\n#define GL_PREVIOUS_EXT                   0x8578\n#define GL_SOURCE0_RGB_EXT                0x8580\n#define GL_SOURCE1_RGB_EXT                0x8581\n#define GL_SOURCE2_RGB_EXT                0x8582\n#define GL_SOURCE0_ALPHA_EXT              0x8588\n#define GL_SOURCE1_ALPHA_EXT              0x8589\n#define GL_SOURCE2_ALPHA_EXT              0x858A\n#define GL_OPERAND0_RGB_EXT               0x8590\n#define GL_OPERAND1_RGB_EXT               0x8591\n#define GL_OPERAND2_RGB_EXT               0x8592\n#define GL_OPERAND0_ALPHA_EXT             0x8598\n#define GL_OPERAND1_ALPHA_EXT             0x8599\n#define GL_OPERAND2_ALPHA_EXT             0x859A\n#endif\n\n#ifndef GL_APPLE_specular_vector\n#define GL_LIGHT_MODEL_SPECULAR_VECTOR_APPLE 0x85B0\n#endif\n\n#ifndef GL_APPLE_transform_hint\n#define GL_TRANSFORM_HINT_APPLE           0x85B1\n#endif\n\n#ifndef GL_SGIX_fog_scale\n#define GL_FOG_SCALE_SGIX                 0x81FC\n#define GL_FOG_SCALE_VALUE_SGIX           0x81FD\n#endif\n\n#ifndef GL_SUNX_constant_data\n#define GL_UNPACK_CONSTANT_DATA_SUNX      0x81D5\n#define GL_TEXTURE_CONSTANT_DATA_SUNX     0x81D6\n#endif\n\n#ifndef GL_SUN_global_alpha\n#define GL_GLOBAL_ALPHA_SUN               0x81D9\n#define GL_GLOBAL_ALPHA_FACTOR_SUN        0x81DA\n#endif\n\n#ifndef GL_SUN_triangle_list\n#define GL_RESTART_SUN                    0x0001\n#define GL_REPLACE_MIDDLE_SUN             0x0002\n#define GL_REPLACE_OLDEST_SUN             0x0003\n#define GL_TRIANGLE_LIST_SUN              0x81D7\n#define GL_REPLACEMENT_CODE_SUN           0x81D8\n#define GL_REPLACEMENT_CODE_ARRAY_SUN     0x85C0\n#define GL_REPLACEMENT_CODE_ARRAY_TYPE_SUN 0x85C1\n#define GL_REPLACEMENT_CODE_ARRAY_STRIDE_SUN 0x85C2\n#define GL_REPLACEMENT_CODE_ARRAY_POINTER_SUN 0x85C3\n#define GL_R1UI_V3F_SUN                   0x85C4\n#define GL_R1UI_C4UB_V3F_SUN              0x85C5\n#define GL_R1UI_C3F_V3F_SUN               0x85C6\n#define GL_R1UI_N3F_V3F_SUN               0x85C7\n#define GL_R1UI_C4F_N3F_V3F_SUN           0x85C8\n#define GL_R1UI_T2F_V3F_SUN               0x85C9\n#define GL_R1UI_T2F_N3F_V3F_SUN           0x85CA\n#define GL_R1UI_T2F_C4F_N3F_V3F_SUN       0x85CB\n#endif\n\n#ifndef GL_SUN_vertex\n#endif\n\n#ifndef GL_EXT_blend_func_separate\n#define GL_BLEND_DST_RGB_EXT              0x80C8\n#define GL_BLEND_SRC_RGB_EXT              0x80C9\n#define GL_BLEND_DST_ALPHA_EXT            0x80CA\n#define GL_BLEND_SRC_ALPHA_EXT            0x80CB\n#endif\n\n#ifndef GL_INGR_color_clamp\n#define GL_RED_MIN_CLAMP_INGR             0x8560\n#define GL_GREEN_MIN_CLAMP_INGR           0x8561\n#define GL_BLUE_MIN_CLAMP_INGR            0x8562\n#define GL_ALPHA_MIN_CLAMP_INGR           0x8563\n#define GL_RED_MAX_CLAMP_INGR             0x8564\n#define GL_GREEN_MAX_CLAMP_INGR           0x8565\n#define GL_BLUE_MAX_CLAMP_INGR            0x8566\n#define GL_ALPHA_MAX_CLAMP_INGR           0x8567\n#endif\n\n#ifndef GL_INGR_interlace_read\n#define GL_INTERLACE_READ_INGR            0x8568\n#endif\n\n#ifndef GL_EXT_stencil_wrap\n#define GL_INCR_WRAP_EXT                  0x8507\n#define GL_DECR_WRAP_EXT                  0x8508\n#endif\n\n#ifndef GL_EXT_422_pixels\n#define GL_422_EXT                        0x80CC\n#define GL_422_REV_EXT                    0x80CD\n#define GL_422_AVERAGE_EXT                0x80CE\n#define GL_422_REV_AVERAGE_EXT            0x80CF\n#endif\n\n#ifndef GL_NV_texgen_reflection\n#define GL_NORMAL_MAP_NV                  0x8511\n#define GL_REFLECTION_MAP_NV              0x8512\n#endif\n\n#ifndef GL_EXT_texture_cube_map\n#define GL_NORMAL_MAP_EXT                 0x8511\n#define GL_REFLECTION_MAP_EXT             0x8512\n#define GL_TEXTURE_CUBE_MAP_EXT           0x8513\n#define GL_TEXTURE_BINDING_CUBE_MAP_EXT   0x8514\n#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT 0x8515\n#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT 0x8516\n#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT 0x8517\n#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT 0x8518\n#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT 0x8519\n#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT 0x851A\n#define GL_PROXY_TEXTURE_CUBE_MAP_EXT     0x851B\n#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_EXT  0x851C\n#endif\n\n#ifndef GL_SUN_convolution_border_modes\n#define GL_WRAP_BORDER_SUN                0x81D4\n#endif\n\n#ifndef GL_EXT_texture_env_add\n#endif\n\n#ifndef GL_EXT_texture_lod_bias\n#define GL_MAX_TEXTURE_LOD_BIAS_EXT       0x84FD\n#define GL_TEXTURE_FILTER_CONTROL_EXT     0x8500\n#define GL_TEXTURE_LOD_BIAS_EXT           0x8501\n#endif\n\n#ifndef GL_EXT_texture_filter_anisotropic\n#define GL_TEXTURE_MAX_ANISOTROPY_EXT     0x84FE\n#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF\n#endif\n\n#ifndef GL_EXT_vertex_weighting\n#define GL_MODELVIEW0_STACK_DEPTH_EXT     GL_MODELVIEW_STACK_DEPTH\n#define GL_MODELVIEW1_STACK_DEPTH_EXT     0x8502\n#define GL_MODELVIEW0_MATRIX_EXT          GL_MODELVIEW_MATRIX\n#define GL_MODELVIEW1_MATRIX_EXT          0x8506\n#define GL_VERTEX_WEIGHTING_EXT           0x8509\n#define GL_MODELVIEW0_EXT                 GL_MODELVIEW\n#define GL_MODELVIEW1_EXT                 0x850A\n#define GL_CURRENT_VERTEX_WEIGHT_EXT      0x850B\n#define GL_VERTEX_WEIGHT_ARRAY_EXT        0x850C\n#define GL_VERTEX_WEIGHT_ARRAY_SIZE_EXT   0x850D\n#define GL_VERTEX_WEIGHT_ARRAY_TYPE_EXT   0x850E\n#define GL_VERTEX_WEIGHT_ARRAY_STRIDE_EXT 0x850F\n#define GL_VERTEX_WEIGHT_ARRAY_POINTER_EXT 0x8510\n#endif\n\n#ifndef GL_NV_light_max_exponent\n#define GL_MAX_SHININESS_NV               0x8504\n#define GL_MAX_SPOT_EXPONENT_NV           0x8505\n#endif\n\n#ifndef GL_NV_vertex_array_range\n#define GL_VERTEX_ARRAY_RANGE_NV          0x851D\n#define GL_VERTEX_ARRAY_RANGE_LENGTH_NV   0x851E\n#define GL_VERTEX_ARRAY_RANGE_VALID_NV    0x851F\n#define GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_NV 0x8520\n#define GL_VERTEX_ARRAY_RANGE_POINTER_NV  0x8521\n#endif\n\n#ifndef GL_NV_register_combiners\n#define GL_REGISTER_COMBINERS_NV          0x8522\n#define GL_VARIABLE_A_NV                  0x8523\n#define GL_VARIABLE_B_NV                  0x8524\n#define GL_VARIABLE_C_NV                  0x8525\n#define GL_VARIABLE_D_NV                  0x8526\n#define GL_VARIABLE_E_NV                  0x8527\n#define GL_VARIABLE_F_NV                  0x8528\n#define GL_VARIABLE_G_NV                  0x8529\n#define GL_CONSTANT_COLOR0_NV             0x852A\n#define GL_CONSTANT_COLOR1_NV             0x852B\n#define GL_PRIMARY_COLOR_NV               0x852C\n#define GL_SECONDARY_COLOR_NV             0x852D\n#define GL_SPARE0_NV                      0x852E\n#define GL_SPARE1_NV                      0x852F\n#define GL_DISCARD_NV                     0x8530\n#define GL_E_TIMES_F_NV                   0x8531\n#define GL_SPARE0_PLUS_SECONDARY_COLOR_NV 0x8532\n#define GL_UNSIGNED_IDENTITY_NV           0x8536\n#define GL_UNSIGNED_INVERT_NV             0x8537\n#define GL_EXPAND_NORMAL_NV               0x8538\n#define GL_EXPAND_NEGATE_NV               0x8539\n#define GL_HALF_BIAS_NORMAL_NV            0x853A\n#define GL_HALF_BIAS_NEGATE_NV            0x853B\n#define GL_SIGNED_IDENTITY_NV             0x853C\n#define GL_SIGNED_NEGATE_NV               0x853D\n#define GL_SCALE_BY_TWO_NV                0x853E\n#define GL_SCALE_BY_FOUR_NV               0x853F\n#define GL_SCALE_BY_ONE_HALF_NV           0x8540\n#define GL_BIAS_BY_NEGATIVE_ONE_HALF_NV   0x8541\n#define GL_COMBINER_INPUT_NV              0x8542\n#define GL_COMBINER_MAPPING_NV            0x8543\n#define GL_COMBINER_COMPONENT_USAGE_NV    0x8544\n#define GL_COMBINER_AB_DOT_PRODUCT_NV     0x8545\n#define GL_COMBINER_CD_DOT_PRODUCT_NV     0x8546\n#define GL_COMBINER_MUX_SUM_NV            0x8547\n#define GL_COMBINER_SCALE_NV              0x8548\n#define GL_COMBINER_BIAS_NV               0x8549\n#define GL_COMBINER_AB_OUTPUT_NV          0x854A\n#define GL_COMBINER_CD_OUTPUT_NV          0x854B\n#define GL_COMBINER_SUM_OUTPUT_NV         0x854C\n#define GL_MAX_GENERAL_COMBINERS_NV       0x854D\n#define GL_NUM_GENERAL_COMBINERS_NV       0x854E\n#define GL_COLOR_SUM_CLAMP_NV             0x854F\n#define GL_COMBINER0_NV                   0x8550\n#define GL_COMBINER1_NV                   0x8551\n#define GL_COMBINER2_NV                   0x8552\n#define GL_COMBINER3_NV                   0x8553\n#define GL_COMBINER4_NV                   0x8554\n#define GL_COMBINER5_NV                   0x8555\n#define GL_COMBINER6_NV                   0x8556\n#define GL_COMBINER7_NV                   0x8557\n/* reuse GL_TEXTURE0_ARB */\n/* reuse GL_TEXTURE1_ARB */\n/* reuse GL_ZERO */\n/* reuse GL_NONE */\n/* reuse GL_FOG */\n#endif\n\n#ifndef GL_NV_fog_distance\n#define GL_FOG_DISTANCE_MODE_NV           0x855A\n#define GL_EYE_RADIAL_NV                  0x855B\n#define GL_EYE_PLANE_ABSOLUTE_NV          0x855C\n/* reuse GL_EYE_PLANE */\n#endif\n\n#ifndef GL_NV_texgen_emboss\n#define GL_EMBOSS_LIGHT_NV                0x855D\n#define GL_EMBOSS_CONSTANT_NV             0x855E\n#define GL_EMBOSS_MAP_NV                  0x855F\n#endif\n\n#ifndef GL_NV_blend_square\n#endif\n\n#ifndef GL_NV_texture_env_combine4\n#define GL_COMBINE4_NV                    0x8503\n#define GL_SOURCE3_RGB_NV                 0x8583\n#define GL_SOURCE3_ALPHA_NV               0x858B\n#define GL_OPERAND3_RGB_NV                0x8593\n#define GL_OPERAND3_ALPHA_NV              0x859B\n#endif\n\n#ifndef GL_MESA_resize_buffers\n#endif\n\n#ifndef GL_MESA_window_pos\n#endif\n\n#ifndef GL_EXT_texture_compression_s3tc\n#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT   0x83F0\n#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT  0x83F1\n#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT  0x83F2\n#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT  0x83F3\n#endif\n\n#ifndef GL_IBM_cull_vertex\n#define GL_CULL_VERTEX_IBM                103050\n#endif\n\n#ifndef GL_IBM_multimode_draw_arrays\n#endif\n\n#ifndef GL_IBM_vertex_array_lists\n#define GL_VERTEX_ARRAY_LIST_IBM          103070\n#define GL_NORMAL_ARRAY_LIST_IBM          103071\n#define GL_COLOR_ARRAY_LIST_IBM           103072\n#define GL_INDEX_ARRAY_LIST_IBM           103073\n#define GL_TEXTURE_COORD_ARRAY_LIST_IBM   103074\n#define GL_EDGE_FLAG_ARRAY_LIST_IBM       103075\n#define GL_FOG_COORDINATE_ARRAY_LIST_IBM  103076\n#define GL_SECONDARY_COLOR_ARRAY_LIST_IBM 103077\n#define GL_VERTEX_ARRAY_LIST_STRIDE_IBM   103080\n#define GL_NORMAL_ARRAY_LIST_STRIDE_IBM   103081\n#define GL_COLOR_ARRAY_LIST_STRIDE_IBM    103082\n#define GL_INDEX_ARRAY_LIST_STRIDE_IBM    103083\n#define GL_TEXTURE_COORD_ARRAY_LIST_STRIDE_IBM 103084\n#define GL_EDGE_FLAG_ARRAY_LIST_STRIDE_IBM 103085\n#define GL_FOG_COORDINATE_ARRAY_LIST_STRIDE_IBM 103086\n#define GL_SECONDARY_COLOR_ARRAY_LIST_STRIDE_IBM 103087\n#endif\n\n#ifndef GL_SGIX_subsample\n#define GL_PACK_SUBSAMPLE_RATE_SGIX       0x85A0\n#define GL_UNPACK_SUBSAMPLE_RATE_SGIX     0x85A1\n#define GL_PIXEL_SUBSAMPLE_4444_SGIX      0x85A2\n#define GL_PIXEL_SUBSAMPLE_2424_SGIX      0x85A3\n#define GL_PIXEL_SUBSAMPLE_4242_SGIX      0x85A4\n#endif\n\n#ifndef GL_SGIX_ycrcb_subsample\n#endif\n\n#ifndef GL_SGIX_ycrcba\n#define GL_YCRCB_SGIX                     0x8318\n#define GL_YCRCBA_SGIX                    0x8319\n#endif\n\n#ifndef GL_SGI_depth_pass_instrument\n#define GL_DEPTH_PASS_INSTRUMENT_SGIX     0x8310\n#define GL_DEPTH_PASS_INSTRUMENT_COUNTERS_SGIX 0x8311\n#define GL_DEPTH_PASS_INSTRUMENT_MAX_SGIX 0x8312\n#endif\n\n#ifndef GL_3DFX_texture_compression_FXT1\n#define GL_COMPRESSED_RGB_FXT1_3DFX       0x86B0\n#define GL_COMPRESSED_RGBA_FXT1_3DFX      0x86B1\n#endif\n\n#ifndef GL_3DFX_multisample\n#define GL_MULTISAMPLE_3DFX               0x86B2\n#define GL_SAMPLE_BUFFERS_3DFX            0x86B3\n#define GL_SAMPLES_3DFX                   0x86B4\n#define GL_MULTISAMPLE_BIT_3DFX           0x20000000\n#endif\n\n#ifndef GL_3DFX_tbuffer\n#endif\n\n#ifndef GL_EXT_multisample\n#define GL_MULTISAMPLE_EXT                0x809D\n#define GL_SAMPLE_ALPHA_TO_MASK_EXT       0x809E\n#define GL_SAMPLE_ALPHA_TO_ONE_EXT        0x809F\n#define GL_SAMPLE_MASK_EXT                0x80A0\n#define GL_1PASS_EXT                      0x80A1\n#define GL_2PASS_0_EXT                    0x80A2\n#define GL_2PASS_1_EXT                    0x80A3\n#define GL_4PASS_0_EXT                    0x80A4\n#define GL_4PASS_1_EXT                    0x80A5\n#define GL_4PASS_2_EXT                    0x80A6\n#define GL_4PASS_3_EXT                    0x80A7\n#define GL_SAMPLE_BUFFERS_EXT             0x80A8\n#define GL_SAMPLES_EXT                    0x80A9\n#define GL_SAMPLE_MASK_VALUE_EXT          0x80AA\n#define GL_SAMPLE_MASK_INVERT_EXT         0x80AB\n#define GL_SAMPLE_PATTERN_EXT             0x80AC\n#define GL_MULTISAMPLE_BIT_EXT            0x20000000\n#endif\n\n#ifndef GL_SGIX_vertex_preclip\n#define GL_VERTEX_PRECLIP_SGIX            0x83EE\n#define GL_VERTEX_PRECLIP_HINT_SGIX       0x83EF\n#endif\n\n#ifndef GL_SGIX_convolution_accuracy\n#define GL_CONVOLUTION_HINT_SGIX          0x8316\n#endif\n\n#ifndef GL_SGIX_resample\n#define GL_PACK_RESAMPLE_SGIX             0x842C\n#define GL_UNPACK_RESAMPLE_SGIX           0x842D\n#define GL_RESAMPLE_REPLICATE_SGIX        0x842E\n#define GL_RESAMPLE_ZERO_FILL_SGIX        0x842F\n#define GL_RESAMPLE_DECIMATE_SGIX         0x8430\n#endif\n\n#ifndef GL_SGIS_point_line_texgen\n#define GL_EYE_DISTANCE_TO_POINT_SGIS     0x81F0\n#define GL_OBJECT_DISTANCE_TO_POINT_SGIS  0x81F1\n#define GL_EYE_DISTANCE_TO_LINE_SGIS      0x81F2\n#define GL_OBJECT_DISTANCE_TO_LINE_SGIS   0x81F3\n#define GL_EYE_POINT_SGIS                 0x81F4\n#define GL_OBJECT_POINT_SGIS              0x81F5\n#define GL_EYE_LINE_SGIS                  0x81F6\n#define GL_OBJECT_LINE_SGIS               0x81F7\n#endif\n\n#ifndef GL_SGIS_texture_color_mask\n#define GL_TEXTURE_COLOR_WRITEMASK_SGIS   0x81EF\n#endif\n\n#ifndef GL_EXT_texture_env_dot3\n#define GL_DOT3_RGB_EXT                   0x8740\n#define GL_DOT3_RGBA_EXT                  0x8741\n#endif\n\n#ifndef GL_ATI_texture_mirror_once\n#define GL_MIRROR_CLAMP_ATI               0x8742\n#define GL_MIRROR_CLAMP_TO_EDGE_ATI       0x8743\n#endif\n\n#ifndef GL_NV_fence\n#define GL_ALL_COMPLETED_NV               0x84F2\n#define GL_FENCE_STATUS_NV                0x84F3\n#define GL_FENCE_CONDITION_NV             0x84F4\n#endif\n\n#ifndef GL_IBM_texture_mirrored_repeat\n#define GL_MIRRORED_REPEAT_IBM            0x8370\n#endif\n\n#ifndef GL_NV_evaluators\n#define GL_EVAL_2D_NV                     0x86C0\n#define GL_EVAL_TRIANGULAR_2D_NV          0x86C1\n#define GL_MAP_TESSELLATION_NV            0x86C2\n#define GL_MAP_ATTRIB_U_ORDER_NV          0x86C3\n#define GL_MAP_ATTRIB_V_ORDER_NV          0x86C4\n#define GL_EVAL_FRACTIONAL_TESSELLATION_NV 0x86C5\n#define GL_EVAL_VERTEX_ATTRIB0_NV         0x86C6\n#define GL_EVAL_VERTEX_ATTRIB1_NV         0x86C7\n#define GL_EVAL_VERTEX_ATTRIB2_NV         0x86C8\n#define GL_EVAL_VERTEX_ATTRIB3_NV         0x86C9\n#define GL_EVAL_VERTEX_ATTRIB4_NV         0x86CA\n#define GL_EVAL_VERTEX_ATTRIB5_NV         0x86CB\n#define GL_EVAL_VERTEX_ATTRIB6_NV         0x86CC\n#define GL_EVAL_VERTEX_ATTRIB7_NV         0x86CD\n#define GL_EVAL_VERTEX_ATTRIB8_NV         0x86CE\n#define GL_EVAL_VERTEX_ATTRIB9_NV         0x86CF\n#define GL_EVAL_VERTEX_ATTRIB10_NV        0x86D0\n#define GL_EVAL_VERTEX_ATTRIB11_NV        0x86D1\n#define GL_EVAL_VERTEX_ATTRIB12_NV        0x86D2\n#define GL_EVAL_VERTEX_ATTRIB13_NV        0x86D3\n#define GL_EVAL_VERTEX_ATTRIB14_NV        0x86D4\n#define GL_EVAL_VERTEX_ATTRIB15_NV        0x86D5\n#define GL_MAX_MAP_TESSELLATION_NV        0x86D6\n#define GL_MAX_RATIONAL_EVAL_ORDER_NV     0x86D7\n#endif\n\n#ifndef GL_NV_packed_depth_stencil\n#define GL_DEPTH_STENCIL_NV               0x84F9\n#define GL_UNSIGNED_INT_24_8_NV           0x84FA\n#endif\n\n#ifndef GL_NV_register_combiners2\n#define GL_PER_STAGE_CONSTANTS_NV         0x8535\n#endif\n\n#ifndef GL_NV_texture_compression_vtc\n#endif\n\n#ifndef GL_NV_texture_rectangle\n#define GL_TEXTURE_RECTANGLE_NV           0x84F5\n#define GL_TEXTURE_BINDING_RECTANGLE_NV   0x84F6\n#define GL_PROXY_TEXTURE_RECTANGLE_NV     0x84F7\n#define GL_MAX_RECTANGLE_TEXTURE_SIZE_NV  0x84F8\n#endif\n\n#ifndef GL_NV_texture_shader\n#define GL_OFFSET_TEXTURE_RECTANGLE_NV    0x864C\n#define GL_OFFSET_TEXTURE_RECTANGLE_SCALE_NV 0x864D\n#define GL_DOT_PRODUCT_TEXTURE_RECTANGLE_NV 0x864E\n#define GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV 0x86D9\n#define GL_UNSIGNED_INT_S8_S8_8_8_NV      0x86DA\n#define GL_UNSIGNED_INT_8_8_S8_S8_REV_NV  0x86DB\n#define GL_DSDT_MAG_INTENSITY_NV          0x86DC\n#define GL_SHADER_CONSISTENT_NV           0x86DD\n#define GL_TEXTURE_SHADER_NV              0x86DE\n#define GL_SHADER_OPERATION_NV            0x86DF\n#define GL_CULL_MODES_NV                  0x86E0\n#define GL_OFFSET_TEXTURE_MATRIX_NV       0x86E1\n#define GL_OFFSET_TEXTURE_SCALE_NV        0x86E2\n#define GL_OFFSET_TEXTURE_BIAS_NV         0x86E3\n#define GL_OFFSET_TEXTURE_2D_MATRIX_NV    GL_OFFSET_TEXTURE_MATRIX_NV\n#define GL_OFFSET_TEXTURE_2D_SCALE_NV     GL_OFFSET_TEXTURE_SCALE_NV\n#define GL_OFFSET_TEXTURE_2D_BIAS_NV      GL_OFFSET_TEXTURE_BIAS_NV\n#define GL_PREVIOUS_TEXTURE_INPUT_NV      0x86E4\n#define GL_CONST_EYE_NV                   0x86E5\n#define GL_PASS_THROUGH_NV                0x86E6\n#define GL_CULL_FRAGMENT_NV               0x86E7\n#define GL_OFFSET_TEXTURE_2D_NV           0x86E8\n#define GL_DEPENDENT_AR_TEXTURE_2D_NV     0x86E9\n#define GL_DEPENDENT_GB_TEXTURE_2D_NV     0x86EA\n#define GL_DOT_PRODUCT_NV                 0x86EC\n#define GL_DOT_PRODUCT_DEPTH_REPLACE_NV   0x86ED\n#define GL_DOT_PRODUCT_TEXTURE_2D_NV      0x86EE\n#define GL_DOT_PRODUCT_TEXTURE_CUBE_MAP_NV 0x86F0\n#define GL_DOT_PRODUCT_DIFFUSE_CUBE_MAP_NV 0x86F1\n#define GL_DOT_PRODUCT_REFLECT_CUBE_MAP_NV 0x86F2\n#define GL_DOT_PRODUCT_CONST_EYE_REFLECT_CUBE_MAP_NV 0x86F3\n#define GL_HILO_NV                        0x86F4\n#define GL_DSDT_NV                        0x86F5\n#define GL_DSDT_MAG_NV                    0x86F6\n#define GL_DSDT_MAG_VIB_NV                0x86F7\n#define GL_HILO16_NV                      0x86F8\n#define GL_SIGNED_HILO_NV                 0x86F9\n#define GL_SIGNED_HILO16_NV               0x86FA\n#define GL_SIGNED_RGBA_NV                 0x86FB\n#define GL_SIGNED_RGBA8_NV                0x86FC\n#define GL_SIGNED_RGB_NV                  0x86FE\n#define GL_SIGNED_RGB8_NV                 0x86FF\n#define GL_SIGNED_LUMINANCE_NV            0x8701\n#define GL_SIGNED_LUMINANCE8_NV           0x8702\n#define GL_SIGNED_LUMINANCE_ALPHA_NV      0x8703\n#define GL_SIGNED_LUMINANCE8_ALPHA8_NV    0x8704\n#define GL_SIGNED_ALPHA_NV                0x8705\n#define GL_SIGNED_ALPHA8_NV               0x8706\n#define GL_SIGNED_INTENSITY_NV            0x8707\n#define GL_SIGNED_INTENSITY8_NV           0x8708\n#define GL_DSDT8_NV                       0x8709\n#define GL_DSDT8_MAG8_NV                  0x870A\n#define GL_DSDT8_MAG8_INTENSITY8_NV       0x870B\n#define GL_SIGNED_RGB_UNSIGNED_ALPHA_NV   0x870C\n#define GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV 0x870D\n#define GL_HI_SCALE_NV                    0x870E\n#define GL_LO_SCALE_NV                    0x870F\n#define GL_DS_SCALE_NV                    0x8710\n#define GL_DT_SCALE_NV                    0x8711\n#define GL_MAGNITUDE_SCALE_NV             0x8712\n#define GL_VIBRANCE_SCALE_NV              0x8713\n#define GL_HI_BIAS_NV                     0x8714\n#define GL_LO_BIAS_NV                     0x8715\n#define GL_DS_BIAS_NV                     0x8716\n#define GL_DT_BIAS_NV                     0x8717\n#define GL_MAGNITUDE_BIAS_NV              0x8718\n#define GL_VIBRANCE_BIAS_NV               0x8719\n#define GL_TEXTURE_BORDER_VALUES_NV       0x871A\n#define GL_TEXTURE_HI_SIZE_NV             0x871B\n#define GL_TEXTURE_LO_SIZE_NV             0x871C\n#define GL_TEXTURE_DS_SIZE_NV             0x871D\n#define GL_TEXTURE_DT_SIZE_NV             0x871E\n#define GL_TEXTURE_MAG_SIZE_NV            0x871F\n#endif\n\n#ifndef GL_NV_texture_shader2\n#define GL_DOT_PRODUCT_TEXTURE_3D_NV      0x86EF\n#endif\n\n#ifndef GL_NV_vertex_array_range2\n#define GL_VERTEX_ARRAY_RANGE_WITHOUT_FLUSH_NV 0x8533\n#endif\n\n#ifndef GL_NV_vertex_program\n#define GL_VERTEX_PROGRAM_NV              0x8620\n#define GL_VERTEX_STATE_PROGRAM_NV        0x8621\n#define GL_ATTRIB_ARRAY_SIZE_NV           0x8623\n#define GL_ATTRIB_ARRAY_STRIDE_NV         0x8624\n#define GL_ATTRIB_ARRAY_TYPE_NV           0x8625\n#define GL_CURRENT_ATTRIB_NV              0x8626\n#define GL_PROGRAM_LENGTH_NV              0x8627\n#define GL_PROGRAM_STRING_NV              0x8628\n#define GL_MODELVIEW_PROJECTION_NV        0x8629\n#define GL_IDENTITY_NV                    0x862A\n#define GL_INVERSE_NV                     0x862B\n#define GL_TRANSPOSE_NV                   0x862C\n#define GL_INVERSE_TRANSPOSE_NV           0x862D\n#define GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV 0x862E\n#define GL_MAX_TRACK_MATRICES_NV          0x862F\n#define GL_MATRIX0_NV                     0x8630\n#define GL_MATRIX1_NV                     0x8631\n#define GL_MATRIX2_NV                     0x8632\n#define GL_MATRIX3_NV                     0x8633\n#define GL_MATRIX4_NV                     0x8634\n#define GL_MATRIX5_NV                     0x8635\n#define GL_MATRIX6_NV                     0x8636\n#define GL_MATRIX7_NV                     0x8637\n#define GL_CURRENT_MATRIX_STACK_DEPTH_NV  0x8640\n#define GL_CURRENT_MATRIX_NV              0x8641\n#define GL_VERTEX_PROGRAM_POINT_SIZE_NV   0x8642\n#define GL_VERTEX_PROGRAM_TWO_SIDE_NV     0x8643\n#define GL_PROGRAM_PARAMETER_NV           0x8644\n#define GL_ATTRIB_ARRAY_POINTER_NV        0x8645\n#define GL_PROGRAM_TARGET_NV              0x8646\n#define GL_PROGRAM_RESIDENT_NV            0x8647\n#define GL_TRACK_MATRIX_NV                0x8648\n#define GL_TRACK_MATRIX_TRANSFORM_NV      0x8649\n#define GL_VERTEX_PROGRAM_BINDING_NV      0x864A\n#define GL_PROGRAM_ERROR_POSITION_NV      0x864B\n#define GL_VERTEX_ATTRIB_ARRAY0_NV        0x8650\n#define GL_VERTEX_ATTRIB_ARRAY1_NV        0x8651\n#define GL_VERTEX_ATTRIB_ARRAY2_NV        0x8652\n#define GL_VERTEX_ATTRIB_ARRAY3_NV        0x8653\n#define GL_VERTEX_ATTRIB_ARRAY4_NV        0x8654\n#define GL_VERTEX_ATTRIB_ARRAY5_NV        0x8655\n#define GL_VERTEX_ATTRIB_ARRAY6_NV        0x8656\n#define GL_VERTEX_ATTRIB_ARRAY7_NV        0x8657\n#define GL_VERTEX_ATTRIB_ARRAY8_NV        0x8658\n#define GL_VERTEX_ATTRIB_ARRAY9_NV        0x8659\n#define GL_VERTEX_ATTRIB_ARRAY10_NV       0x865A\n#define GL_VERTEX_ATTRIB_ARRAY11_NV       0x865B\n#define GL_VERTEX_ATTRIB_ARRAY12_NV       0x865C\n#define GL_VERTEX_ATTRIB_ARRAY13_NV       0x865D\n#define GL_VERTEX_ATTRIB_ARRAY14_NV       0x865E\n#define GL_VERTEX_ATTRIB_ARRAY15_NV       0x865F\n#define GL_MAP1_VERTEX_ATTRIB0_4_NV       0x8660\n#define GL_MAP1_VERTEX_ATTRIB1_4_NV       0x8661\n#define GL_MAP1_VERTEX_ATTRIB2_4_NV       0x8662\n#define GL_MAP1_VERTEX_ATTRIB3_4_NV       0x8663\n#define GL_MAP1_VERTEX_ATTRIB4_4_NV       0x8664\n#define GL_MAP1_VERTEX_ATTRIB5_4_NV       0x8665\n#define GL_MAP1_VERTEX_ATTRIB6_4_NV       0x8666\n#define GL_MAP1_VERTEX_ATTRIB7_4_NV       0x8667\n#define GL_MAP1_VERTEX_ATTRIB8_4_NV       0x8668\n#define GL_MAP1_VERTEX_ATTRIB9_4_NV       0x8669\n#define GL_MAP1_VERTEX_ATTRIB10_4_NV      0x866A\n#define GL_MAP1_VERTEX_ATTRIB11_4_NV      0x866B\n#define GL_MAP1_VERTEX_ATTRIB12_4_NV      0x866C\n#define GL_MAP1_VERTEX_ATTRIB13_4_NV      0x866D\n#define GL_MAP1_VERTEX_ATTRIB14_4_NV      0x866E\n#define GL_MAP1_VERTEX_ATTRIB15_4_NV      0x866F\n#define GL_MAP2_VERTEX_ATTRIB0_4_NV       0x8670\n#define GL_MAP2_VERTEX_ATTRIB1_4_NV       0x8671\n#define GL_MAP2_VERTEX_ATTRIB2_4_NV       0x8672\n#define GL_MAP2_VERTEX_ATTRIB3_4_NV       0x8673\n#define GL_MAP2_VERTEX_ATTRIB4_4_NV       0x8674\n#define GL_MAP2_VERTEX_ATTRIB5_4_NV       0x8675\n#define GL_MAP2_VERTEX_ATTRIB6_4_NV       0x8676\n#define GL_MAP2_VERTEX_ATTRIB7_4_NV       0x8677\n#define GL_MAP2_VERTEX_ATTRIB8_4_NV       0x8678\n#define GL_MAP2_VERTEX_ATTRIB9_4_NV       0x8679\n#define GL_MAP2_VERTEX_ATTRIB10_4_NV      0x867A\n#define GL_MAP2_VERTEX_ATTRIB11_4_NV      0x867B\n#define GL_MAP2_VERTEX_ATTRIB12_4_NV      0x867C\n#define GL_MAP2_VERTEX_ATTRIB13_4_NV      0x867D\n#define GL_MAP2_VERTEX_ATTRIB14_4_NV      0x867E\n#define GL_MAP2_VERTEX_ATTRIB15_4_NV      0x867F\n#endif\n\n#ifndef GL_SGIX_texture_coordinate_clamp\n#define GL_TEXTURE_MAX_CLAMP_S_SGIX       0x8369\n#define GL_TEXTURE_MAX_CLAMP_T_SGIX       0x836A\n#define GL_TEXTURE_MAX_CLAMP_R_SGIX       0x836B\n#endif\n\n#ifndef GL_SGIX_scalebias_hint\n#define GL_SCALEBIAS_HINT_SGIX            0x8322\n#endif\n\n#ifndef GL_OML_interlace\n#define GL_INTERLACE_OML                  0x8980\n#define GL_INTERLACE_READ_OML             0x8981\n#endif\n\n#ifndef GL_OML_subsample\n#define GL_FORMAT_SUBSAMPLE_24_24_OML     0x8982\n#define GL_FORMAT_SUBSAMPLE_244_244_OML   0x8983\n#endif\n\n#ifndef GL_OML_resample\n#define GL_PACK_RESAMPLE_OML              0x8984\n#define GL_UNPACK_RESAMPLE_OML            0x8985\n#define GL_RESAMPLE_REPLICATE_OML         0x8986\n#define GL_RESAMPLE_ZERO_FILL_OML         0x8987\n#define GL_RESAMPLE_AVERAGE_OML           0x8988\n#define GL_RESAMPLE_DECIMATE_OML          0x8989\n#endif\n\n#ifndef GL_NV_copy_depth_to_color\n#define GL_DEPTH_STENCIL_TO_RGBA_NV       0x886E\n#define GL_DEPTH_STENCIL_TO_BGRA_NV       0x886F\n#endif\n\n#ifndef GL_ATI_envmap_bumpmap\n#define GL_BUMP_ROT_MATRIX_ATI            0x8775\n#define GL_BUMP_ROT_MATRIX_SIZE_ATI       0x8776\n#define GL_BUMP_NUM_TEX_UNITS_ATI         0x8777\n#define GL_BUMP_TEX_UNITS_ATI             0x8778\n#define GL_DUDV_ATI                       0x8779\n#define GL_DU8DV8_ATI                     0x877A\n#define GL_BUMP_ENVMAP_ATI                0x877B\n#define GL_BUMP_TARGET_ATI                0x877C\n#endif\n\n#ifndef GL_ATI_fragment_shader\n#define GL_FRAGMENT_SHADER_ATI            0x8920\n#define GL_REG_0_ATI                      0x8921\n#define GL_REG_1_ATI                      0x8922\n#define GL_REG_2_ATI                      0x8923\n#define GL_REG_3_ATI                      0x8924\n#define GL_REG_4_ATI                      0x8925\n#define GL_REG_5_ATI                      0x8926\n#define GL_REG_6_ATI                      0x8927\n#define GL_REG_7_ATI                      0x8928\n#define GL_REG_8_ATI                      0x8929\n#define GL_REG_9_ATI                      0x892A\n#define GL_REG_10_ATI                     0x892B\n#define GL_REG_11_ATI                     0x892C\n#define GL_REG_12_ATI                     0x892D\n#define GL_REG_13_ATI                     0x892E\n#define GL_REG_14_ATI                     0x892F\n#define GL_REG_15_ATI                     0x8930\n#define GL_REG_16_ATI                     0x8931\n#define GL_REG_17_ATI                     0x8932\n#define GL_REG_18_ATI                     0x8933\n#define GL_REG_19_ATI                     0x8934\n#define GL_REG_20_ATI                     0x8935\n#define GL_REG_21_ATI                     0x8936\n#define GL_REG_22_ATI                     0x8937\n#define GL_REG_23_ATI                     0x8938\n#define GL_REG_24_ATI                     0x8939\n#define GL_REG_25_ATI                     0x893A\n#define GL_REG_26_ATI                     0x893B\n#define GL_REG_27_ATI                     0x893C\n#define GL_REG_28_ATI                     0x893D\n#define GL_REG_29_ATI                     0x893E\n#define GL_REG_30_ATI                     0x893F\n#define GL_REG_31_ATI                     0x8940\n#define GL_CON_0_ATI                      0x8941\n#define GL_CON_1_ATI                      0x8942\n#define GL_CON_2_ATI                      0x8943\n#define GL_CON_3_ATI                      0x8944\n#define GL_CON_4_ATI                      0x8945\n#define GL_CON_5_ATI                      0x8946\n#define GL_CON_6_ATI                      0x8947\n#define GL_CON_7_ATI                      0x8948\n#define GL_CON_8_ATI                      0x8949\n#define GL_CON_9_ATI                      0x894A\n#define GL_CON_10_ATI                     0x894B\n#define GL_CON_11_ATI                     0x894C\n#define GL_CON_12_ATI                     0x894D\n#define GL_CON_13_ATI                     0x894E\n#define GL_CON_14_ATI                     0x894F\n#define GL_CON_15_ATI                     0x8950\n#define GL_CON_16_ATI                     0x8951\n#define GL_CON_17_ATI                     0x8952\n#define GL_CON_18_ATI                     0x8953\n#define GL_CON_19_ATI                     0x8954\n#define GL_CON_20_ATI                     0x8955\n#define GL_CON_21_ATI                     0x8956\n#define GL_CON_22_ATI                     0x8957\n#define GL_CON_23_ATI                     0x8958\n#define GL_CON_24_ATI                     0x8959\n#define GL_CON_25_ATI                     0x895A\n#define GL_CON_26_ATI                     0x895B\n#define GL_CON_27_ATI                     0x895C\n#define GL_CON_28_ATI                     0x895D\n#define GL_CON_29_ATI                     0x895E\n#define GL_CON_30_ATI                     0x895F\n#define GL_CON_31_ATI                     0x8960\n#define GL_MOV_ATI                        0x8961\n#define GL_ADD_ATI                        0x8963\n#define GL_MUL_ATI                        0x8964\n#define GL_SUB_ATI                        0x8965\n#define GL_DOT3_ATI                       0x8966\n#define GL_DOT4_ATI                       0x8967\n#define GL_MAD_ATI                        0x8968\n#define GL_LERP_ATI                       0x8969\n#define GL_CND_ATI                        0x896A\n#define GL_CND0_ATI                       0x896B\n#define GL_DOT2_ADD_ATI                   0x896C\n#define GL_SECONDARY_INTERPOLATOR_ATI     0x896D\n#define GL_NUM_FRAGMENT_REGISTERS_ATI     0x896E\n#define GL_NUM_FRAGMENT_CONSTANTS_ATI     0x896F\n#define GL_NUM_PASSES_ATI                 0x8970\n#define GL_NUM_INSTRUCTIONS_PER_PASS_ATI  0x8971\n#define GL_NUM_INSTRUCTIONS_TOTAL_ATI     0x8972\n#define GL_NUM_INPUT_INTERPOLATOR_COMPONENTS_ATI 0x8973\n#define GL_NUM_LOOPBACK_COMPONENTS_ATI    0x8974\n#define GL_COLOR_ALPHA_PAIRING_ATI        0x8975\n#define GL_SWIZZLE_STR_ATI                0x8976\n#define GL_SWIZZLE_STQ_ATI                0x8977\n#define GL_SWIZZLE_STR_DR_ATI             0x8978\n#define GL_SWIZZLE_STQ_DQ_ATI             0x8979\n#define GL_SWIZZLE_STRQ_ATI               0x897A\n#define GL_SWIZZLE_STRQ_DQ_ATI            0x897B\n#define GL_RED_BIT_ATI                    0x00000001\n#define GL_GREEN_BIT_ATI                  0x00000002\n#define GL_BLUE_BIT_ATI                   0x00000004\n#define GL_2X_BIT_ATI                     0x00000001\n#define GL_4X_BIT_ATI                     0x00000002\n#define GL_8X_BIT_ATI                     0x00000004\n#define GL_HALF_BIT_ATI                   0x00000008\n#define GL_QUARTER_BIT_ATI                0x00000010\n#define GL_EIGHTH_BIT_ATI                 0x00000020\n#define GL_SATURATE_BIT_ATI               0x00000040\n#define GL_COMP_BIT_ATI                   0x00000002\n#define GL_NEGATE_BIT_ATI                 0x00000004\n#define GL_BIAS_BIT_ATI                   0x00000008\n#endif\n\n#ifndef GL_ATI_pn_triangles\n#define GL_PN_TRIANGLES_ATI               0x87F0\n#define GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F1\n#define GL_PN_TRIANGLES_POINT_MODE_ATI    0x87F2\n#define GL_PN_TRIANGLES_NORMAL_MODE_ATI   0x87F3\n#define GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F4\n#define GL_PN_TRIANGLES_POINT_MODE_LINEAR_ATI 0x87F5\n#define GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI 0x87F6\n#define GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI 0x87F7\n#define GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI 0x87F8\n#endif\n\n#ifndef GL_ATI_vertex_array_object\n#define GL_STATIC_ATI                     0x8760\n#define GL_DYNAMIC_ATI                    0x8761\n#define GL_PRESERVE_ATI                   0x8762\n#define GL_DISCARD_ATI                    0x8763\n#define GL_OBJECT_BUFFER_SIZE_ATI         0x8764\n#define GL_OBJECT_BUFFER_USAGE_ATI        0x8765\n#define GL_ARRAY_OBJECT_BUFFER_ATI        0x8766\n#define GL_ARRAY_OBJECT_OFFSET_ATI        0x8767\n#endif\n\n#ifndef GL_EXT_vertex_shader\n#define GL_VERTEX_SHADER_EXT              0x8780\n#define GL_VERTEX_SHADER_BINDING_EXT      0x8781\n#define GL_OP_INDEX_EXT                   0x8782\n#define GL_OP_NEGATE_EXT                  0x8783\n#define GL_OP_DOT3_EXT                    0x8784\n#define GL_OP_DOT4_EXT                    0x8785\n#define GL_OP_MUL_EXT                     0x8786\n#define GL_OP_ADD_EXT                     0x8787\n#define GL_OP_MADD_EXT                    0x8788\n#define GL_OP_FRAC_EXT                    0x8789\n#define GL_OP_MAX_EXT                     0x878A\n#define GL_OP_MIN_EXT                     0x878B\n#define GL_OP_SET_GE_EXT                  0x878C\n#define GL_OP_SET_LT_EXT                  0x878D\n#define GL_OP_CLAMP_EXT                   0x878E\n#define GL_OP_FLOOR_EXT                   0x878F\n#define GL_OP_ROUND_EXT                   0x8790\n#define GL_OP_EXP_BASE_2_EXT              0x8791\n#define GL_OP_LOG_BASE_2_EXT              0x8792\n#define GL_OP_POWER_EXT                   0x8793\n#define GL_OP_RECIP_EXT                   0x8794\n#define GL_OP_RECIP_SQRT_EXT              0x8795\n#define GL_OP_SUB_EXT                     0x8796\n#define GL_OP_CROSS_PRODUCT_EXT           0x8797\n#define GL_OP_MULTIPLY_MATRIX_EXT         0x8798\n#define GL_OP_MOV_EXT                     0x8799\n#define GL_OUTPUT_VERTEX_EXT              0x879A\n#define GL_OUTPUT_COLOR0_EXT              0x879B\n#define GL_OUTPUT_COLOR1_EXT              0x879C\n#define GL_OUTPUT_TEXTURE_COORD0_EXT      0x879D\n#define GL_OUTPUT_TEXTURE_COORD1_EXT      0x879E\n#define GL_OUTPUT_TEXTURE_COORD2_EXT      0x879F\n#define GL_OUTPUT_TEXTURE_COORD3_EXT      0x87A0\n#define GL_OUTPUT_TEXTURE_COORD4_EXT      0x87A1\n#define GL_OUTPUT_TEXTURE_COORD5_EXT      0x87A2\n#define GL_OUTPUT_TEXTURE_COORD6_EXT      0x87A3\n#define GL_OUTPUT_TEXTURE_COORD7_EXT      0x87A4\n#define GL_OUTPUT_TEXTURE_COORD8_EXT      0x87A5\n#define GL_OUTPUT_TEXTURE_COORD9_EXT      0x87A6\n#define GL_OUTPUT_TEXTURE_COORD10_EXT     0x87A7\n#define GL_OUTPUT_TEXTURE_COORD11_EXT     0x87A8\n#define GL_OUTPUT_TEXTURE_COORD12_EXT     0x87A9\n#define GL_OUTPUT_TEXTURE_COORD13_EXT     0x87AA\n#define GL_OUTPUT_TEXTURE_COORD14_EXT     0x87AB\n#define GL_OUTPUT_TEXTURE_COORD15_EXT     0x87AC\n#define GL_OUTPUT_TEXTURE_COORD16_EXT     0x87AD\n#define GL_OUTPUT_TEXTURE_COORD17_EXT     0x87AE\n#define GL_OUTPUT_TEXTURE_COORD18_EXT     0x87AF\n#define GL_OUTPUT_TEXTURE_COORD19_EXT     0x87B0\n#define GL_OUTPUT_TEXTURE_COORD20_EXT     0x87B1\n#define GL_OUTPUT_TEXTURE_COORD21_EXT     0x87B2\n#define GL_OUTPUT_TEXTURE_COORD22_EXT     0x87B3\n#define GL_OUTPUT_TEXTURE_COORD23_EXT     0x87B4\n#define GL_OUTPUT_TEXTURE_COORD24_EXT     0x87B5\n#define GL_OUTPUT_TEXTURE_COORD25_EXT     0x87B6\n#define GL_OUTPUT_TEXTURE_COORD26_EXT     0x87B7\n#define GL_OUTPUT_TEXTURE_COORD27_EXT     0x87B8\n#define GL_OUTPUT_TEXTURE_COORD28_EXT     0x87B9\n#define GL_OUTPUT_TEXTURE_COORD29_EXT     0x87BA\n#define GL_OUTPUT_TEXTURE_COORD30_EXT     0x87BB\n#define GL_OUTPUT_TEXTURE_COORD31_EXT     0x87BC\n#define GL_OUTPUT_FOG_EXT                 0x87BD\n#define GL_SCALAR_EXT                     0x87BE\n#define GL_VECTOR_EXT                     0x87BF\n#define GL_MATRIX_EXT                     0x87C0\n#define GL_VARIANT_EXT                    0x87C1\n#define GL_INVARIANT_EXT                  0x87C2\n#define GL_LOCAL_CONSTANT_EXT             0x87C3\n#define GL_LOCAL_EXT                      0x87C4\n#define GL_MAX_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87C5\n#define GL_MAX_VERTEX_SHADER_VARIANTS_EXT 0x87C6\n#define GL_MAX_VERTEX_SHADER_INVARIANTS_EXT 0x87C7\n#define GL_MAX_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87C8\n#define GL_MAX_VERTEX_SHADER_LOCALS_EXT   0x87C9\n#define GL_MAX_OPTIMIZED_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CA\n#define GL_MAX_OPTIMIZED_VERTEX_SHADER_VARIANTS_EXT 0x87CB\n#define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87CC\n#define GL_MAX_OPTIMIZED_VERTEX_SHADER_INVARIANTS_EXT 0x87CD\n#define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCALS_EXT 0x87CE\n#define GL_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CF\n#define GL_VERTEX_SHADER_VARIANTS_EXT     0x87D0\n#define GL_VERTEX_SHADER_INVARIANTS_EXT   0x87D1\n#define GL_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87D2\n#define GL_VERTEX_SHADER_LOCALS_EXT       0x87D3\n#define GL_VERTEX_SHADER_OPTIMIZED_EXT    0x87D4\n#define GL_X_EXT                          0x87D5\n#define GL_Y_EXT                          0x87D6\n#define GL_Z_EXT                          0x87D7\n#define GL_W_EXT                          0x87D8\n#define GL_NEGATIVE_X_EXT                 0x87D9\n#define GL_NEGATIVE_Y_EXT                 0x87DA\n#define GL_NEGATIVE_Z_EXT                 0x87DB\n#define GL_NEGATIVE_W_EXT                 0x87DC\n#define GL_ZERO_EXT                       0x87DD\n#define GL_ONE_EXT                        0x87DE\n#define GL_NEGATIVE_ONE_EXT               0x87DF\n#define GL_NORMALIZED_RANGE_EXT           0x87E0\n#define GL_FULL_RANGE_EXT                 0x87E1\n#define GL_CURRENT_VERTEX_EXT             0x87E2\n#define GL_MVP_MATRIX_EXT                 0x87E3\n#define GL_VARIANT_VALUE_EXT              0x87E4\n#define GL_VARIANT_DATATYPE_EXT           0x87E5\n#define GL_VARIANT_ARRAY_STRIDE_EXT       0x87E6\n#define GL_VARIANT_ARRAY_TYPE_EXT         0x87E7\n#define GL_VARIANT_ARRAY_EXT              0x87E8\n#define GL_VARIANT_ARRAY_POINTER_EXT      0x87E9\n#define GL_INVARIANT_VALUE_EXT            0x87EA\n#define GL_INVARIANT_DATATYPE_EXT         0x87EB\n#define GL_LOCAL_CONSTANT_VALUE_EXT       0x87EC\n#define GL_LOCAL_CONSTANT_DATATYPE_EXT    0x87ED\n#endif\n\n#ifndef GL_ATI_vertex_streams\n#define GL_MAX_VERTEX_STREAMS_ATI         0x876B\n#define GL_VERTEX_STREAM0_ATI             0x876C\n#define GL_VERTEX_STREAM1_ATI             0x876D\n#define GL_VERTEX_STREAM2_ATI             0x876E\n#define GL_VERTEX_STREAM3_ATI             0x876F\n#define GL_VERTEX_STREAM4_ATI             0x8770\n#define GL_VERTEX_STREAM5_ATI             0x8771\n#define GL_VERTEX_STREAM6_ATI             0x8772\n#define GL_VERTEX_STREAM7_ATI             0x8773\n#define GL_VERTEX_SOURCE_ATI              0x8774\n#endif\n\n#ifndef GL_ATI_element_array\n#define GL_ELEMENT_ARRAY_ATI              0x8768\n#define GL_ELEMENT_ARRAY_TYPE_ATI         0x8769\n#define GL_ELEMENT_ARRAY_POINTER_ATI      0x876A\n#endif\n\n#ifndef GL_SUN_mesh_array\n#define GL_QUAD_MESH_SUN                  0x8614\n#define GL_TRIANGLE_MESH_SUN              0x8615\n#endif\n\n#ifndef GL_SUN_slice_accum\n#define GL_SLICE_ACCUM_SUN                0x85CC\n#endif\n\n#ifndef GL_NV_multisample_filter_hint\n#define GL_MULTISAMPLE_FILTER_HINT_NV     0x8534\n#endif\n\n#ifndef GL_NV_depth_clamp\n#define GL_DEPTH_CLAMP_NV                 0x864F\n#endif\n\n#ifndef GL_NV_occlusion_query\n#define GL_PIXEL_COUNTER_BITS_NV          0x8864\n#define GL_CURRENT_OCCLUSION_QUERY_ID_NV  0x8865\n#define GL_PIXEL_COUNT_NV                 0x8866\n#define GL_PIXEL_COUNT_AVAILABLE_NV       0x8867\n#endif\n\n#ifndef GL_NV_point_sprite\n#define GL_POINT_SPRITE_NV                0x8861\n#define GL_COORD_REPLACE_NV               0x8862\n#define GL_POINT_SPRITE_R_MODE_NV         0x8863\n#endif\n\n#ifndef GL_NV_texture_shader3\n#define GL_OFFSET_PROJECTIVE_TEXTURE_2D_NV 0x8850\n#define GL_OFFSET_PROJECTIVE_TEXTURE_2D_SCALE_NV 0x8851\n#define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8852\n#define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_SCALE_NV 0x8853\n#define GL_OFFSET_HILO_TEXTURE_2D_NV      0x8854\n#define GL_OFFSET_HILO_TEXTURE_RECTANGLE_NV 0x8855\n#define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_2D_NV 0x8856\n#define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8857\n#define GL_DEPENDENT_HILO_TEXTURE_2D_NV   0x8858\n#define GL_DEPENDENT_RGB_TEXTURE_3D_NV    0x8859\n#define GL_DEPENDENT_RGB_TEXTURE_CUBE_MAP_NV 0x885A\n#define GL_DOT_PRODUCT_PASS_THROUGH_NV    0x885B\n#define GL_DOT_PRODUCT_TEXTURE_1D_NV      0x885C\n#define GL_DOT_PRODUCT_AFFINE_DEPTH_REPLACE_NV 0x885D\n#define GL_HILO8_NV                       0x885E\n#define GL_SIGNED_HILO8_NV                0x885F\n#define GL_FORCE_BLUE_TO_ONE_NV           0x8860\n#endif\n\n#ifndef GL_NV_vertex_program1_1\n#endif\n\n#ifndef GL_EXT_shadow_funcs\n#endif\n\n#ifndef GL_EXT_stencil_two_side\n#define GL_STENCIL_TEST_TWO_SIDE_EXT      0x8910\n#define GL_ACTIVE_STENCIL_FACE_EXT        0x8911\n#endif\n\n#ifndef GL_ATI_text_fragment_shader\n#define GL_TEXT_FRAGMENT_SHADER_ATI       0x8200\n#endif\n\n#ifndef GL_APPLE_client_storage\n#define GL_UNPACK_CLIENT_STORAGE_APPLE    0x85B2\n#endif\n\n#ifndef GL_APPLE_element_array\n#define GL_ELEMENT_ARRAY_APPLE            0x8768\n#define GL_ELEMENT_ARRAY_TYPE_APPLE       0x8769\n#define GL_ELEMENT_ARRAY_POINTER_APPLE    0x876A\n#endif\n\n#ifndef GL_APPLE_fence\n#define GL_DRAW_PIXELS_APPLE              0x8A0A\n#define GL_FENCE_APPLE                    0x8A0B\n#endif\n\n#ifndef GL_APPLE_vertex_array_object\n#define GL_VERTEX_ARRAY_BINDING_APPLE     0x85B5\n#endif\n\n#ifndef GL_APPLE_vertex_array_range\n#define GL_VERTEX_ARRAY_RANGE_APPLE       0x851D\n#define GL_VERTEX_ARRAY_RANGE_LENGTH_APPLE 0x851E\n#define GL_VERTEX_ARRAY_STORAGE_HINT_APPLE 0x851F\n#define GL_VERTEX_ARRAY_RANGE_POINTER_APPLE 0x8521\n#define GL_STORAGE_CACHED_APPLE           0x85BE\n#define GL_STORAGE_SHARED_APPLE           0x85BF\n#endif\n\n#ifndef GL_APPLE_ycbcr_422\n#define GL_YCBCR_422_APPLE                0x85B9\n#define GL_UNSIGNED_SHORT_8_8_APPLE       0x85BA\n#define GL_UNSIGNED_SHORT_8_8_REV_APPLE   0x85BB\n#endif\n\n#ifndef GL_S3_s3tc\n#define GL_RGB_S3TC                       0x83A0\n#define GL_RGB4_S3TC                      0x83A1\n#define GL_RGBA_S3TC                      0x83A2\n#define GL_RGBA4_S3TC                     0x83A3\n#endif\n\n#ifndef GL_ATI_draw_buffers\n#define GL_MAX_DRAW_BUFFERS_ATI           0x8824\n#define GL_DRAW_BUFFER0_ATI               0x8825\n#define GL_DRAW_BUFFER1_ATI               0x8826\n#define GL_DRAW_BUFFER2_ATI               0x8827\n#define GL_DRAW_BUFFER3_ATI               0x8828\n#define GL_DRAW_BUFFER4_ATI               0x8829\n#define GL_DRAW_BUFFER5_ATI               0x882A\n#define GL_DRAW_BUFFER6_ATI               0x882B\n#define GL_DRAW_BUFFER7_ATI               0x882C\n#define GL_DRAW_BUFFER8_ATI               0x882D\n#define GL_DRAW_BUFFER9_ATI               0x882E\n#define GL_DRAW_BUFFER10_ATI              0x882F\n#define GL_DRAW_BUFFER11_ATI              0x8830\n#define GL_DRAW_BUFFER12_ATI              0x8831\n#define GL_DRAW_BUFFER13_ATI              0x8832\n#define GL_DRAW_BUFFER14_ATI              0x8833\n#define GL_DRAW_BUFFER15_ATI              0x8834\n#endif\n\n#ifndef GL_ATI_pixel_format_float\n#define GL_TYPE_RGBA_FLOAT_ATI            0x8820\n#define GL_COLOR_CLEAR_UNCLAMPED_VALUE_ATI 0x8835\n#endif\n\n#ifndef GL_ATI_texture_env_combine3\n#define GL_MODULATE_ADD_ATI               0x8744\n#define GL_MODULATE_SIGNED_ADD_ATI        0x8745\n#define GL_MODULATE_SUBTRACT_ATI          0x8746\n#endif\n\n#ifndef GL_ATI_texture_float\n#define GL_RGBA_FLOAT32_ATI               0x8814\n#define GL_RGB_FLOAT32_ATI                0x8815\n#define GL_ALPHA_FLOAT32_ATI              0x8816\n#define GL_INTENSITY_FLOAT32_ATI          0x8817\n#define GL_LUMINANCE_FLOAT32_ATI          0x8818\n#define GL_LUMINANCE_ALPHA_FLOAT32_ATI    0x8819\n#define GL_RGBA_FLOAT16_ATI               0x881A\n#define GL_RGB_FLOAT16_ATI                0x881B\n#define GL_ALPHA_FLOAT16_ATI              0x881C\n#define GL_INTENSITY_FLOAT16_ATI          0x881D\n#define GL_LUMINANCE_FLOAT16_ATI          0x881E\n#define GL_LUMINANCE_ALPHA_FLOAT16_ATI    0x881F\n#endif\n\n#ifndef GL_NV_float_buffer\n#define GL_FLOAT_R_NV                     0x8880\n#define GL_FLOAT_RG_NV                    0x8881\n#define GL_FLOAT_RGB_NV                   0x8882\n#define GL_FLOAT_RGBA_NV                  0x8883\n#define GL_FLOAT_R16_NV                   0x8884\n#define GL_FLOAT_R32_NV                   0x8885\n#define GL_FLOAT_RG16_NV                  0x8886\n#define GL_FLOAT_RG32_NV                  0x8887\n#define GL_FLOAT_RGB16_NV                 0x8888\n#define GL_FLOAT_RGB32_NV                 0x8889\n#define GL_FLOAT_RGBA16_NV                0x888A\n#define GL_FLOAT_RGBA32_NV                0x888B\n#define GL_TEXTURE_FLOAT_COMPONENTS_NV    0x888C\n#define GL_FLOAT_CLEAR_COLOR_VALUE_NV     0x888D\n#define GL_FLOAT_RGBA_MODE_NV             0x888E\n#endif\n\n#ifndef GL_NV_fragment_program\n#define GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV 0x8868\n#define GL_FRAGMENT_PROGRAM_NV            0x8870\n#define GL_MAX_TEXTURE_COORDS_NV          0x8871\n#define GL_MAX_TEXTURE_IMAGE_UNITS_NV     0x8872\n#define GL_FRAGMENT_PROGRAM_BINDING_NV    0x8873\n#define GL_PROGRAM_ERROR_STRING_NV        0x8874\n#endif\n\n#ifndef GL_NV_half_float\n#define GL_HALF_FLOAT_NV                  0x140B\n#endif\n\n#ifndef GL_NV_pixel_data_range\n#define GL_WRITE_PIXEL_DATA_RANGE_NV      0x8878\n#define GL_READ_PIXEL_DATA_RANGE_NV       0x8879\n#define GL_WRITE_PIXEL_DATA_RANGE_LENGTH_NV 0x887A\n#define GL_READ_PIXEL_DATA_RANGE_LENGTH_NV 0x887B\n#define GL_WRITE_PIXEL_DATA_RANGE_POINTER_NV 0x887C\n#define GL_READ_PIXEL_DATA_RANGE_POINTER_NV 0x887D\n#endif\n\n#ifndef GL_NV_primitive_restart\n#define GL_PRIMITIVE_RESTART_NV           0x8558\n#define GL_PRIMITIVE_RESTART_INDEX_NV     0x8559\n#endif\n\n#ifndef GL_NV_texture_expand_normal\n#define GL_TEXTURE_UNSIGNED_REMAP_MODE_NV 0x888F\n#endif\n\n#ifndef GL_NV_vertex_program2\n#endif\n\n#ifndef GL_ATI_map_object_buffer\n#endif\n\n#ifndef GL_ATI_separate_stencil\n#define GL_STENCIL_BACK_FUNC_ATI          0x8800\n#define GL_STENCIL_BACK_FAIL_ATI          0x8801\n#define GL_STENCIL_BACK_PASS_DEPTH_FAIL_ATI 0x8802\n#define GL_STENCIL_BACK_PASS_DEPTH_PASS_ATI 0x8803\n#endif\n\n#ifndef GL_ATI_vertex_attrib_array_object\n#endif\n\n#ifndef GL_OES_read_format\n#define GL_IMPLEMENTATION_COLOR_READ_TYPE_OES 0x8B9A\n#define GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES 0x8B9B\n#endif\n\n#ifndef GL_EXT_depth_bounds_test\n#define GL_DEPTH_BOUNDS_TEST_EXT          0x8890\n#define GL_DEPTH_BOUNDS_EXT               0x8891\n#endif\n\n#ifndef GL_EXT_texture_mirror_clamp\n#define GL_MIRROR_CLAMP_EXT               0x8742\n#define GL_MIRROR_CLAMP_TO_EDGE_EXT       0x8743\n#define GL_MIRROR_CLAMP_TO_BORDER_EXT     0x8912\n#endif\n\n#ifndef GL_EXT_blend_equation_separate\n#define GL_BLEND_EQUATION_RGB_EXT         GL_BLEND_EQUATION\n#define GL_BLEND_EQUATION_ALPHA_EXT       0x883D\n#endif\n\n#ifndef GL_MESA_pack_invert\n#define GL_PACK_INVERT_MESA               0x8758\n#endif\n\n#ifndef GL_MESA_ycbcr_texture\n#define GL_UNSIGNED_SHORT_8_8_MESA        0x85BA\n#define GL_UNSIGNED_SHORT_8_8_REV_MESA    0x85BB\n#define GL_YCBCR_MESA                     0x8757\n#endif\n\n#ifndef GL_EXT_pixel_buffer_object\n#define GL_PIXEL_PACK_BUFFER_EXT          0x88EB\n#define GL_PIXEL_UNPACK_BUFFER_EXT        0x88EC\n#define GL_PIXEL_PACK_BUFFER_BINDING_EXT  0x88ED\n#define GL_PIXEL_UNPACK_BUFFER_BINDING_EXT 0x88EF\n#endif\n\n#ifndef GL_NV_fragment_program_option\n#endif\n\n#ifndef GL_NV_fragment_program2\n#define GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV 0x88F4\n#define GL_MAX_PROGRAM_CALL_DEPTH_NV      0x88F5\n#define GL_MAX_PROGRAM_IF_DEPTH_NV        0x88F6\n#define GL_MAX_PROGRAM_LOOP_DEPTH_NV      0x88F7\n#define GL_MAX_PROGRAM_LOOP_COUNT_NV      0x88F8\n#endif\n\n#ifndef GL_NV_vertex_program2_option\n/* reuse GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV */\n/* reuse GL_MAX_PROGRAM_CALL_DEPTH_NV */\n#endif\n\n#ifndef GL_NV_vertex_program3\n/* reuse GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB */\n#endif\n\n#ifndef GL_EXT_framebuffer_object\n#define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506\n#define GL_MAX_RENDERBUFFER_SIZE_EXT      0x84E8\n#define GL_FRAMEBUFFER_BINDING_EXT        0x8CA6\n#define GL_RENDERBUFFER_BINDING_EXT       0x8CA7\n#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT 0x8CD0\n#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT 0x8CD1\n#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT 0x8CD2\n#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT 0x8CD3\n#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4\n#define GL_FRAMEBUFFER_COMPLETE_EXT       0x8CD5\n#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6\n#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7\n#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT 0x8CD9\n#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT 0x8CDA\n#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB\n#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC\n#define GL_FRAMEBUFFER_UNSUPPORTED_EXT    0x8CDD\n#define GL_MAX_COLOR_ATTACHMENTS_EXT      0x8CDF\n#define GL_COLOR_ATTACHMENT0_EXT          0x8CE0\n#define GL_COLOR_ATTACHMENT1_EXT          0x8CE1\n#define GL_COLOR_ATTACHMENT2_EXT          0x8CE2\n#define GL_COLOR_ATTACHMENT3_EXT          0x8CE3\n#define GL_COLOR_ATTACHMENT4_EXT          0x8CE4\n#define GL_COLOR_ATTACHMENT5_EXT          0x8CE5\n#define GL_COLOR_ATTACHMENT6_EXT          0x8CE6\n#define GL_COLOR_ATTACHMENT7_EXT          0x8CE7\n#define GL_COLOR_ATTACHMENT8_EXT          0x8CE8\n#define GL_COLOR_ATTACHMENT9_EXT          0x8CE9\n#define GL_COLOR_ATTACHMENT10_EXT         0x8CEA\n#define GL_COLOR_ATTACHMENT11_EXT         0x8CEB\n#define GL_COLOR_ATTACHMENT12_EXT         0x8CEC\n#define GL_COLOR_ATTACHMENT13_EXT         0x8CED\n#define GL_COLOR_ATTACHMENT14_EXT         0x8CEE\n#define GL_COLOR_ATTACHMENT15_EXT         0x8CEF\n#define GL_DEPTH_ATTACHMENT_EXT           0x8D00\n#define GL_STENCIL_ATTACHMENT_EXT         0x8D20\n#define GL_FRAMEBUFFER_EXT                0x8D40\n#define GL_RENDERBUFFER_EXT               0x8D41\n#define GL_RENDERBUFFER_WIDTH_EXT         0x8D42\n#define GL_RENDERBUFFER_HEIGHT_EXT        0x8D43\n#define GL_RENDERBUFFER_INTERNAL_FORMAT_EXT 0x8D44\n#define GL_STENCIL_INDEX1_EXT             0x8D46\n#define GL_STENCIL_INDEX4_EXT             0x8D47\n#define GL_STENCIL_INDEX8_EXT             0x8D48\n#define GL_STENCIL_INDEX16_EXT            0x8D49\n#define GL_RENDERBUFFER_RED_SIZE_EXT      0x8D50\n#define GL_RENDERBUFFER_GREEN_SIZE_EXT    0x8D51\n#define GL_RENDERBUFFER_BLUE_SIZE_EXT     0x8D52\n#define GL_RENDERBUFFER_ALPHA_SIZE_EXT    0x8D53\n#define GL_RENDERBUFFER_DEPTH_SIZE_EXT    0x8D54\n#define GL_RENDERBUFFER_STENCIL_SIZE_EXT  0x8D55\n#endif\n\n#ifndef GL_GREMEDY_string_marker\n#endif\n\n#ifndef GL_EXT_packed_depth_stencil\n#define GL_DEPTH_STENCIL_EXT              0x84F9\n#define GL_UNSIGNED_INT_24_8_EXT          0x84FA\n#define GL_DEPTH24_STENCIL8_EXT           0x88F0\n#define GL_TEXTURE_STENCIL_SIZE_EXT       0x88F1\n#endif\n\n#ifndef GL_EXT_stencil_clear_tag\n#define GL_STENCIL_TAG_BITS_EXT           0x88F2\n#define GL_STENCIL_CLEAR_TAG_VALUE_EXT    0x88F3\n#endif\n\n#ifndef GL_EXT_texture_sRGB\n#define GL_SRGB_EXT                       0x8C40\n#define GL_SRGB8_EXT                      0x8C41\n#define GL_SRGB_ALPHA_EXT                 0x8C42\n#define GL_SRGB8_ALPHA8_EXT               0x8C43\n#define GL_SLUMINANCE_ALPHA_EXT           0x8C44\n#define GL_SLUMINANCE8_ALPHA8_EXT         0x8C45\n#define GL_SLUMINANCE_EXT                 0x8C46\n#define GL_SLUMINANCE8_EXT                0x8C47\n#define GL_COMPRESSED_SRGB_EXT            0x8C48\n#define GL_COMPRESSED_SRGB_ALPHA_EXT      0x8C49\n#define GL_COMPRESSED_SLUMINANCE_EXT      0x8C4A\n#define GL_COMPRESSED_SLUMINANCE_ALPHA_EXT 0x8C4B\n#define GL_COMPRESSED_SRGB_S3TC_DXT1_EXT  0x8C4C\n#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT 0x8C4D\n#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT 0x8C4E\n#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F\n#endif\n\n#ifndef GL_EXT_framebuffer_blit\n#define GL_READ_FRAMEBUFFER_EXT           0x8CA8\n#define GL_DRAW_FRAMEBUFFER_EXT           0x8CA9\n#define GL_DRAW_FRAMEBUFFER_BINDING_EXT   GL_FRAMEBUFFER_BINDING_EXT\n#define GL_READ_FRAMEBUFFER_BINDING_EXT   0x8CAA\n#endif\n\n#ifndef GL_EXT_framebuffer_multisample\n#define GL_RENDERBUFFER_SAMPLES_EXT       0x8CAB\n#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56\n#define GL_MAX_SAMPLES_EXT                0x8D57\n#endif\n\n#ifndef GL_MESAX_texture_stack\n#define GL_TEXTURE_1D_STACK_MESAX         0x8759\n#define GL_TEXTURE_2D_STACK_MESAX         0x875A\n#define GL_PROXY_TEXTURE_1D_STACK_MESAX   0x875B\n#define GL_PROXY_TEXTURE_2D_STACK_MESAX   0x875C\n#define GL_TEXTURE_1D_STACK_BINDING_MESAX 0x875D\n#define GL_TEXTURE_2D_STACK_BINDING_MESAX 0x875E\n#endif\n\n#ifndef GL_EXT_timer_query\n#define GL_TIME_ELAPSED_EXT               0x88BF\n#endif\n\n#ifndef GL_EXT_gpu_program_parameters\n#endif\n\n#ifndef GL_APPLE_flush_buffer_range\n#define GL_BUFFER_SERIALIZED_MODIFY_APPLE 0x8A12\n#define GL_BUFFER_FLUSHING_UNMAP_APPLE    0x8A13\n#endif\n\n#ifndef GL_NV_gpu_program4\n#define GL_MIN_PROGRAM_TEXEL_OFFSET_NV    0x8904\n#define GL_MAX_PROGRAM_TEXEL_OFFSET_NV    0x8905\n#define GL_PROGRAM_ATTRIB_COMPONENTS_NV   0x8906\n#define GL_PROGRAM_RESULT_COMPONENTS_NV   0x8907\n#define GL_MAX_PROGRAM_ATTRIB_COMPONENTS_NV 0x8908\n#define GL_MAX_PROGRAM_RESULT_COMPONENTS_NV 0x8909\n#define GL_MAX_PROGRAM_GENERIC_ATTRIBS_NV 0x8DA5\n#define GL_MAX_PROGRAM_GENERIC_RESULTS_NV 0x8DA6\n#endif\n\n#ifndef GL_NV_geometry_program4\n#define GL_LINES_ADJACENCY_EXT            0x000A\n#define GL_LINE_STRIP_ADJACENCY_EXT       0x000B\n#define GL_TRIANGLES_ADJACENCY_EXT        0x000C\n#define GL_TRIANGLE_STRIP_ADJACENCY_EXT   0x000D\n#define GL_GEOMETRY_PROGRAM_NV            0x8C26\n#define GL_MAX_PROGRAM_OUTPUT_VERTICES_NV 0x8C27\n#define GL_MAX_PROGRAM_TOTAL_OUTPUT_COMPONENTS_NV 0x8C28\n#define GL_GEOMETRY_VERTICES_OUT_EXT      0x8DDA\n#define GL_GEOMETRY_INPUT_TYPE_EXT        0x8DDB\n#define GL_GEOMETRY_OUTPUT_TYPE_EXT       0x8DDC\n#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT 0x8C29\n#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT 0x8DA7\n#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT 0x8DA8\n#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT 0x8DA9\n#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT 0x8CD4\n#define GL_PROGRAM_POINT_SIZE_EXT         0x8642\n#endif\n\n#ifndef GL_EXT_geometry_shader4\n#define GL_GEOMETRY_SHADER_EXT            0x8DD9\n/* reuse GL_GEOMETRY_VERTICES_OUT_EXT */\n/* reuse GL_GEOMETRY_INPUT_TYPE_EXT */\n/* reuse GL_GEOMETRY_OUTPUT_TYPE_EXT */\n/* reuse GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT */\n#define GL_MAX_GEOMETRY_VARYING_COMPONENTS_EXT 0x8DDD\n#define GL_MAX_VERTEX_VARYING_COMPONENTS_EXT 0x8DDE\n#define GL_MAX_VARYING_COMPONENTS_EXT     0x8B4B\n#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT 0x8DDF\n#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT 0x8DE0\n#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT 0x8DE1\n/* reuse GL_LINES_ADJACENCY_EXT */\n/* reuse GL_LINE_STRIP_ADJACENCY_EXT */\n/* reuse GL_TRIANGLES_ADJACENCY_EXT */\n/* reuse GL_TRIANGLE_STRIP_ADJACENCY_EXT */\n/* reuse GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT */\n/* reuse GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT */\n/* reuse GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT */\n/* reuse GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT */\n/* reuse GL_PROGRAM_POINT_SIZE_EXT */\n#endif\n\n#ifndef GL_NV_vertex_program4\n#define GL_VERTEX_ATTRIB_ARRAY_INTEGER_NV 0x88FD\n#endif\n\n#ifndef GL_EXT_gpu_shader4\n#define GL_SAMPLER_1D_ARRAY_EXT           0x8DC0\n#define GL_SAMPLER_2D_ARRAY_EXT           0x8DC1\n#define GL_SAMPLER_BUFFER_EXT             0x8DC2\n#define GL_SAMPLER_1D_ARRAY_SHADOW_EXT    0x8DC3\n#define GL_SAMPLER_2D_ARRAY_SHADOW_EXT    0x8DC4\n#define GL_SAMPLER_CUBE_SHADOW_EXT        0x8DC5\n#define GL_UNSIGNED_INT_VEC2_EXT          0x8DC6\n#define GL_UNSIGNED_INT_VEC3_EXT          0x8DC7\n#define GL_UNSIGNED_INT_VEC4_EXT          0x8DC8\n#define GL_INT_SAMPLER_1D_EXT             0x8DC9\n#define GL_INT_SAMPLER_2D_EXT             0x8DCA\n#define GL_INT_SAMPLER_3D_EXT             0x8DCB\n#define GL_INT_SAMPLER_CUBE_EXT           0x8DCC\n#define GL_INT_SAMPLER_2D_RECT_EXT        0x8DCD\n#define GL_INT_SAMPLER_1D_ARRAY_EXT       0x8DCE\n#define GL_INT_SAMPLER_2D_ARRAY_EXT       0x8DCF\n#define GL_INT_SAMPLER_BUFFER_EXT         0x8DD0\n#define GL_UNSIGNED_INT_SAMPLER_1D_EXT    0x8DD1\n#define GL_UNSIGNED_INT_SAMPLER_2D_EXT    0x8DD2\n#define GL_UNSIGNED_INT_SAMPLER_3D_EXT    0x8DD3\n#define GL_UNSIGNED_INT_SAMPLER_CUBE_EXT  0x8DD4\n#define GL_UNSIGNED_INT_SAMPLER_2D_RECT_EXT 0x8DD5\n#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY_EXT 0x8DD6\n#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY_EXT 0x8DD7\n#define GL_UNSIGNED_INT_SAMPLER_BUFFER_EXT 0x8DD8\n#endif\n\n#ifndef GL_EXT_draw_instanced\n#endif\n\n#ifndef GL_EXT_packed_float\n#define GL_R11F_G11F_B10F_EXT             0x8C3A\n#define GL_UNSIGNED_INT_10F_11F_11F_REV_EXT 0x8C3B\n#define GL_RGBA_SIGNED_COMPONENTS_EXT     0x8C3C\n#endif\n\n#ifndef GL_EXT_texture_array\n#define GL_TEXTURE_1D_ARRAY_EXT           0x8C18\n#define GL_PROXY_TEXTURE_1D_ARRAY_EXT     0x8C19\n#define GL_TEXTURE_2D_ARRAY_EXT           0x8C1A\n#define GL_PROXY_TEXTURE_2D_ARRAY_EXT     0x8C1B\n#define GL_TEXTURE_BINDING_1D_ARRAY_EXT   0x8C1C\n#define GL_TEXTURE_BINDING_2D_ARRAY_EXT   0x8C1D\n#define GL_MAX_ARRAY_TEXTURE_LAYERS_EXT   0x88FF\n#define GL_COMPARE_REF_DEPTH_TO_TEXTURE_EXT 0x884E\n/* reuse GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT */\n#endif\n\n#ifndef GL_EXT_texture_buffer_object\n#define GL_TEXTURE_BUFFER_EXT             0x8C2A\n#define GL_MAX_TEXTURE_BUFFER_SIZE_EXT    0x8C2B\n#define GL_TEXTURE_BINDING_BUFFER_EXT     0x8C2C\n#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_EXT 0x8C2D\n#define GL_TEXTURE_BUFFER_FORMAT_EXT      0x8C2E\n#endif\n\n#ifndef GL_EXT_texture_compression_latc\n#define GL_COMPRESSED_LUMINANCE_LATC1_EXT 0x8C70\n#define GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT 0x8C71\n#define GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT 0x8C72\n#define GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT 0x8C73\n#endif\n\n#ifndef GL_EXT_texture_compression_rgtc\n#define GL_COMPRESSED_RED_RGTC1_EXT       0x8DBB\n#define GL_COMPRESSED_SIGNED_RED_RGTC1_EXT 0x8DBC\n#define GL_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD\n#define GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE\n#endif\n\n#ifndef GL_EXT_texture_shared_exponent\n#define GL_RGB9_E5_EXT                    0x8C3D\n#define GL_UNSIGNED_INT_5_9_9_9_REV_EXT   0x8C3E\n#define GL_TEXTURE_SHARED_SIZE_EXT        0x8C3F\n#endif\n\n#ifndef GL_NV_depth_buffer_float\n#define GL_DEPTH_COMPONENT32F_NV          0x8DAB\n#define GL_DEPTH32F_STENCIL8_NV           0x8DAC\n#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV_NV 0x8DAD\n#define GL_DEPTH_BUFFER_FLOAT_MODE_NV     0x8DAF\n#endif\n\n#ifndef GL_NV_fragment_program4\n#endif\n\n#ifndef GL_NV_framebuffer_multisample_coverage\n#define GL_RENDERBUFFER_COVERAGE_SAMPLES_NV 0x8CAB\n#define GL_RENDERBUFFER_COLOR_SAMPLES_NV  0x8E10\n#define GL_MAX_MULTISAMPLE_COVERAGE_MODES_NV 0x8E11\n#define GL_MULTISAMPLE_COVERAGE_MODES_NV  0x8E12\n#endif\n\n#ifndef GL_EXT_framebuffer_sRGB\n#define GL_FRAMEBUFFER_SRGB_EXT           0x8DB9\n#define GL_FRAMEBUFFER_SRGB_CAPABLE_EXT   0x8DBA\n#endif\n\n#ifndef GL_NV_geometry_shader4\n#endif\n\n#ifndef GL_NV_parameter_buffer_object\n#define GL_MAX_PROGRAM_PARAMETER_BUFFER_BINDINGS_NV 0x8DA0\n#define GL_MAX_PROGRAM_PARAMETER_BUFFER_SIZE_NV 0x8DA1\n#define GL_VERTEX_PROGRAM_PARAMETER_BUFFER_NV 0x8DA2\n#define GL_GEOMETRY_PROGRAM_PARAMETER_BUFFER_NV 0x8DA3\n#define GL_FRAGMENT_PROGRAM_PARAMETER_BUFFER_NV 0x8DA4\n#endif\n\n#ifndef GL_EXT_draw_buffers2\n#endif\n\n#ifndef GL_NV_transform_feedback\n#define GL_BACK_PRIMARY_COLOR_NV          0x8C77\n#define GL_BACK_SECONDARY_COLOR_NV        0x8C78\n#define GL_TEXTURE_COORD_NV               0x8C79\n#define GL_CLIP_DISTANCE_NV               0x8C7A\n#define GL_VERTEX_ID_NV                   0x8C7B\n#define GL_PRIMITIVE_ID_NV                0x8C7C\n#define GL_GENERIC_ATTRIB_NV              0x8C7D\n#define GL_TRANSFORM_FEEDBACK_ATTRIBS_NV  0x8C7E\n#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE_NV 0x8C7F\n#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_NV 0x8C80\n#define GL_ACTIVE_VARYINGS_NV             0x8C81\n#define GL_ACTIVE_VARYING_MAX_LENGTH_NV   0x8C82\n#define GL_TRANSFORM_FEEDBACK_VARYINGS_NV 0x8C83\n#define GL_TRANSFORM_FEEDBACK_BUFFER_START_NV 0x8C84\n#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE_NV 0x8C85\n#define GL_TRANSFORM_FEEDBACK_RECORD_NV   0x8C86\n#define GL_PRIMITIVES_GENERATED_NV        0x8C87\n#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_NV 0x8C88\n#define GL_RASTERIZER_DISCARD_NV          0x8C89\n#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_ATTRIBS_NV 0x8C8A\n#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_NV 0x8C8B\n#define GL_INTERLEAVED_ATTRIBS_NV         0x8C8C\n#define GL_SEPARATE_ATTRIBS_NV            0x8C8D\n#define GL_TRANSFORM_FEEDBACK_BUFFER_NV   0x8C8E\n#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_NV 0x8C8F\n#endif\n\n#ifndef GL_EXT_bindable_uniform\n#define GL_MAX_VERTEX_BINDABLE_UNIFORMS_EXT 0x8DE2\n#define GL_MAX_FRAGMENT_BINDABLE_UNIFORMS_EXT 0x8DE3\n#define GL_MAX_GEOMETRY_BINDABLE_UNIFORMS_EXT 0x8DE4\n#define GL_MAX_BINDABLE_UNIFORM_SIZE_EXT  0x8DED\n#define GL_UNIFORM_BUFFER_EXT             0x8DEE\n#define GL_UNIFORM_BUFFER_BINDING_EXT     0x8DEF\n#endif\n\n#ifndef GL_EXT_texture_integer\n#define GL_RGBA32UI_EXT                   0x8D70\n#define GL_RGB32UI_EXT                    0x8D71\n#define GL_ALPHA32UI_EXT                  0x8D72\n#define GL_INTENSITY32UI_EXT              0x8D73\n#define GL_LUMINANCE32UI_EXT              0x8D74\n#define GL_LUMINANCE_ALPHA32UI_EXT        0x8D75\n#define GL_RGBA16UI_EXT                   0x8D76\n#define GL_RGB16UI_EXT                    0x8D77\n#define GL_ALPHA16UI_EXT                  0x8D78\n#define GL_INTENSITY16UI_EXT              0x8D79\n#define GL_LUMINANCE16UI_EXT              0x8D7A\n#define GL_LUMINANCE_ALPHA16UI_EXT        0x8D7B\n#define GL_RGBA8UI_EXT                    0x8D7C\n#define GL_RGB8UI_EXT                     0x8D7D\n#define GL_ALPHA8UI_EXT                   0x8D7E\n#define GL_INTENSITY8UI_EXT               0x8D7F\n#define GL_LUMINANCE8UI_EXT               0x8D80\n#define GL_LUMINANCE_ALPHA8UI_EXT         0x8D81\n#define GL_RGBA32I_EXT                    0x8D82\n#define GL_RGB32I_EXT                     0x8D83\n#define GL_ALPHA32I_EXT                   0x8D84\n#define GL_INTENSITY32I_EXT               0x8D85\n#define GL_LUMINANCE32I_EXT               0x8D86\n#define GL_LUMINANCE_ALPHA32I_EXT         0x8D87\n#define GL_RGBA16I_EXT                    0x8D88\n#define GL_RGB16I_EXT                     0x8D89\n#define GL_ALPHA16I_EXT                   0x8D8A\n#define GL_INTENSITY16I_EXT               0x8D8B\n#define GL_LUMINANCE16I_EXT               0x8D8C\n#define GL_LUMINANCE_ALPHA16I_EXT         0x8D8D\n#define GL_RGBA8I_EXT                     0x8D8E\n#define GL_RGB8I_EXT                      0x8D8F\n#define GL_ALPHA8I_EXT                    0x8D90\n#define GL_INTENSITY8I_EXT                0x8D91\n#define GL_LUMINANCE8I_EXT                0x8D92\n#define GL_LUMINANCE_ALPHA8I_EXT          0x8D93\n#define GL_RED_INTEGER_EXT                0x8D94\n#define GL_GREEN_INTEGER_EXT              0x8D95\n#define GL_BLUE_INTEGER_EXT               0x8D96\n#define GL_ALPHA_INTEGER_EXT              0x8D97\n#define GL_RGB_INTEGER_EXT                0x8D98\n#define GL_RGBA_INTEGER_EXT               0x8D99\n#define GL_BGR_INTEGER_EXT                0x8D9A\n#define GL_BGRA_INTEGER_EXT               0x8D9B\n#define GL_LUMINANCE_INTEGER_EXT          0x8D9C\n#define GL_LUMINANCE_ALPHA_INTEGER_EXT    0x8D9D\n#define GL_RGBA_INTEGER_MODE_EXT          0x8D9E\n#endif\n\n#ifndef GL_GREMEDY_frame_terminator\n#endif\n\n\n/*************************************************************/\n\n#include <stddef.h>\n#ifndef GL_VERSION_2_0\n/* GL type for program/shader text */\ntypedef char GLchar;\t\t\t/* native character */\n#endif\n\n#ifndef GL_VERSION_1_5\n/* GL types for handling large vertex buffer objects */\n#ifdef __APPLE__\ntypedef long GLintptr;\ntypedef long GLsizeiptr;\n#else\ntypedef ptrdiff_t GLintptr;\ntypedef ptrdiff_t GLsizeiptr;\n#endif\n#endif\n\n#ifndef GL_ARB_vertex_buffer_object\n/* GL types for handling large vertex buffer objects */\n#ifdef __APPLE__\ntypedef long GLintptrARB;\ntypedef long GLsizeiptrARB;\n#else\ntypedef ptrdiff_t GLintptrARB;\ntypedef ptrdiff_t GLsizeiptrARB;\n#endif\n#endif\n\n#ifndef GL_ARB_shader_objects\n/* GL types for handling shader object handles and program/shader text */\ntypedef char GLcharARB;\t\t/* native character */\n#if defined(__APPLE__)\ntypedef void *GLhandleARB;\t/* shader object handle */\n#else\ntypedef unsigned int GLhandleARB;\t/* shader object handle */\n#endif\n#endif\n\n/* GL types for \"half\" precision (s10e5) float data in host memory */\n#ifndef GL_ARB_half_float_pixel\ntypedef unsigned short GLhalfARB;\n#endif\n\n#ifndef GL_NV_half_float\ntypedef unsigned short GLhalfNV;\n#endif\n\n#ifndef GLEXT_64_TYPES_DEFINED\n/* This code block is duplicated in glxext.h, so must be protected */\n#define GLEXT_64_TYPES_DEFINED\n/* Define int32_t, int64_t, and uint64_t types for UST/MSC */\n/* (as used in the GL_EXT_timer_query extension). */\n#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L\n#include <inttypes.h>\n#elif defined(__sun__) || defined(__digital__)\n#include <inttypes.h>\n#if defined(__STDC__)\n#if defined(__arch64__) || defined(_LP64)\ntypedef long int int64_t;\ntypedef unsigned long int uint64_t;\n#else\ntypedef long long int int64_t;\ntypedef unsigned long long int uint64_t;\n#endif /* __arch64__ */\n#endif /* __STDC__ */\n#elif defined( __VMS ) || defined(__sgi)\n#include <inttypes.h>\n#elif defined(__SCO__) || defined(__USLC__)\n#include <stdint.h>\n#elif defined(__UNIXOS2__) || defined(__SOL64__)\ntypedef long int int32_t;\ntypedef long long int int64_t;\ntypedef unsigned long long int uint64_t;\n#elif defined(_WIN32) && (defined(__GNUC__)||defined(__WATCOMC__))\n#include <stdint.h>\n#elif defined(_WIN32)\n#if 0 /* handled by SDL_config_windows.h */\ntypedef __int32 int32_t;\ntypedef __int64 int64_t;\ntypedef unsigned __int64 uint64_t;\n#endif /* */\n#elif defined(__MACOS__)  /* handled by SDL_config_macos.h */\n#else\n#include <inttypes.h>     /* Fallback option */\n#endif\n#endif\n\n#ifndef GL_EXT_timer_query\ntypedef int64_t GLint64EXT;\ntypedef uint64_t GLuint64EXT;\n#endif\n\n#ifndef GL_VERSION_1_2\n#define GL_VERSION_1_2 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glBlendColor (GLclampf, GLclampf, GLclampf, GLclampf);\nGLAPI void APIENTRY glBlendEquation (GLenum);\nGLAPI void APIENTRY glDrawRangeElements (GLenum, GLuint, GLuint, GLsizei, GLenum, const GLvoid *);\nGLAPI void APIENTRY glColorTable (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *);\nGLAPI void APIENTRY glColorTableParameterfv (GLenum, GLenum, const GLfloat *);\nGLAPI void APIENTRY glColorTableParameteriv (GLenum, GLenum, const GLint *);\nGLAPI void APIENTRY glCopyColorTable (GLenum, GLenum, GLint, GLint, GLsizei);\nGLAPI void APIENTRY glGetColorTable (GLenum, GLenum, GLenum, GLvoid *);\nGLAPI void APIENTRY glGetColorTableParameterfv (GLenum, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetColorTableParameteriv (GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glColorSubTable (GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);\nGLAPI void APIENTRY glCopyColorSubTable (GLenum, GLsizei, GLint, GLint, GLsizei);\nGLAPI void APIENTRY glConvolutionFilter1D (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *);\nGLAPI void APIENTRY glConvolutionFilter2D (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);\nGLAPI void APIENTRY glConvolutionParameterf (GLenum, GLenum, GLfloat);\nGLAPI void APIENTRY glConvolutionParameterfv (GLenum, GLenum, const GLfloat *);\nGLAPI void APIENTRY glConvolutionParameteri (GLenum, GLenum, GLint);\nGLAPI void APIENTRY glConvolutionParameteriv (GLenum, GLenum, const GLint *);\nGLAPI void APIENTRY glCopyConvolutionFilter1D (GLenum, GLenum, GLint, GLint, GLsizei);\nGLAPI void APIENTRY glCopyConvolutionFilter2D (GLenum, GLenum, GLint, GLint, GLsizei, GLsizei);\nGLAPI void APIENTRY glGetConvolutionFilter (GLenum, GLenum, GLenum, GLvoid *);\nGLAPI void APIENTRY glGetConvolutionParameterfv (GLenum, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetConvolutionParameteriv (GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glGetSeparableFilter (GLenum, GLenum, GLenum, GLvoid *, GLvoid *, GLvoid *);\nGLAPI void APIENTRY glSeparableFilter2D (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *, const GLvoid *);\nGLAPI void APIENTRY glGetHistogram (GLenum, GLboolean, GLenum, GLenum, GLvoid *);\nGLAPI void APIENTRY glGetHistogramParameterfv (GLenum, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetHistogramParameteriv (GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glGetMinmax (GLenum, GLboolean, GLenum, GLenum, GLvoid *);\nGLAPI void APIENTRY glGetMinmaxParameterfv (GLenum, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetMinmaxParameteriv (GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glHistogram (GLenum, GLsizei, GLenum, GLboolean);\nGLAPI void APIENTRY glMinmax (GLenum, GLenum, GLboolean);\nGLAPI void APIENTRY glResetHistogram (GLenum);\nGLAPI void APIENTRY glResetMinmax (GLenum);\nGLAPI void APIENTRY glTexImage3D (GLenum, GLint, GLint, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *);\nGLAPI void APIENTRY glTexSubImage3D (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);\nGLAPI void APIENTRY glCopyTexSubImage3D (GLenum, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLBLENDCOLORPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);\ntypedef void (APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode);\ntypedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices);\ntypedef void (APIENTRYP PFNGLCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table);\ntypedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params);\ntypedef void (APIENTRYP PFNGLCOPYCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);\ntypedef void (APIENTRYP PFNGLGETCOLORTABLEPROC) (GLenum target, GLenum format, GLenum type, GLvoid *table);\ntypedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data);\ntypedef void (APIENTRYP PFNGLCOPYCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width);\ntypedef void (APIENTRYP PFNGLCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image);\ntypedef void (APIENTRYP PFNGLCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image);\ntypedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat params);\ntypedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIPROC) (GLenum target, GLenum pname, GLint params);\ntypedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params);\ntypedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);\ntypedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height);\ntypedef void (APIENTRYP PFNGLGETCONVOLUTIONFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *image);\ntypedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETSEPARABLEFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span);\ntypedef void (APIENTRYP PFNGLSEPARABLEFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column);\ntypedef void (APIENTRYP PFNGLGETHISTOGRAMPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values);\ntypedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETMINMAXPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values);\ntypedef void (APIENTRYP PFNGLGETMINMAXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETMINMAXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLHISTOGRAMPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink);\ntypedef void (APIENTRYP PFNGLMINMAXPROC) (GLenum target, GLenum internalformat, GLboolean sink);\ntypedef void (APIENTRYP PFNGLRESETHISTOGRAMPROC) (GLenum target);\ntypedef void (APIENTRYP PFNGLRESETMINMAXPROC) (GLenum target);\ntypedef void (APIENTRYP PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);\ntypedef void (APIENTRYP PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);\ntypedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);\n#endif\n\n#ifndef GL_VERSION_1_3\n#define GL_VERSION_1_3 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glActiveTexture (GLenum);\nGLAPI void APIENTRY glClientActiveTexture (GLenum);\nGLAPI void APIENTRY glMultiTexCoord1d (GLenum, GLdouble);\nGLAPI void APIENTRY glMultiTexCoord1dv (GLenum, const GLdouble *);\nGLAPI void APIENTRY glMultiTexCoord1f (GLenum, GLfloat);\nGLAPI void APIENTRY glMultiTexCoord1fv (GLenum, const GLfloat *);\nGLAPI void APIENTRY glMultiTexCoord1i (GLenum, GLint);\nGLAPI void APIENTRY glMultiTexCoord1iv (GLenum, const GLint *);\nGLAPI void APIENTRY glMultiTexCoord1s (GLenum, GLshort);\nGLAPI void APIENTRY glMultiTexCoord1sv (GLenum, const GLshort *);\nGLAPI void APIENTRY glMultiTexCoord2d (GLenum, GLdouble, GLdouble);\nGLAPI void APIENTRY glMultiTexCoord2dv (GLenum, const GLdouble *);\nGLAPI void APIENTRY glMultiTexCoord2f (GLenum, GLfloat, GLfloat);\nGLAPI void APIENTRY glMultiTexCoord2fv (GLenum, const GLfloat *);\nGLAPI void APIENTRY glMultiTexCoord2i (GLenum, GLint, GLint);\nGLAPI void APIENTRY glMultiTexCoord2iv (GLenum, const GLint *);\nGLAPI void APIENTRY glMultiTexCoord2s (GLenum, GLshort, GLshort);\nGLAPI void APIENTRY glMultiTexCoord2sv (GLenum, const GLshort *);\nGLAPI void APIENTRY glMultiTexCoord3d (GLenum, GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glMultiTexCoord3dv (GLenum, const GLdouble *);\nGLAPI void APIENTRY glMultiTexCoord3f (GLenum, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glMultiTexCoord3fv (GLenum, const GLfloat *);\nGLAPI void APIENTRY glMultiTexCoord3i (GLenum, GLint, GLint, GLint);\nGLAPI void APIENTRY glMultiTexCoord3iv (GLenum, const GLint *);\nGLAPI void APIENTRY glMultiTexCoord3s (GLenum, GLshort, GLshort, GLshort);\nGLAPI void APIENTRY glMultiTexCoord3sv (GLenum, const GLshort *);\nGLAPI void APIENTRY glMultiTexCoord4d (GLenum, GLdouble, GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glMultiTexCoord4dv (GLenum, const GLdouble *);\nGLAPI void APIENTRY glMultiTexCoord4f (GLenum, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glMultiTexCoord4fv (GLenum, const GLfloat *);\nGLAPI void APIENTRY glMultiTexCoord4i (GLenum, GLint, GLint, GLint, GLint);\nGLAPI void APIENTRY glMultiTexCoord4iv (GLenum, const GLint *);\nGLAPI void APIENTRY glMultiTexCoord4s (GLenum, GLshort, GLshort, GLshort, GLshort);\nGLAPI void APIENTRY glMultiTexCoord4sv (GLenum, const GLshort *);\nGLAPI void APIENTRY glLoadTransposeMatrixf (const GLfloat *);\nGLAPI void APIENTRY glLoadTransposeMatrixd (const GLdouble *);\nGLAPI void APIENTRY glMultTransposeMatrixf (const GLfloat *);\nGLAPI void APIENTRY glMultTransposeMatrixd (const GLdouble *);\nGLAPI void APIENTRY glSampleCoverage (GLclampf, GLboolean);\nGLAPI void APIENTRY glCompressedTexImage3D (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glCompressedTexImage2D (GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glCompressedTexImage1D (GLenum, GLint, GLenum, GLsizei, GLint, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glCompressedTexSubImage3D (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glCompressedTexSubImage2D (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glCompressedTexSubImage1D (GLenum, GLint, GLint, GLsizei, GLenum, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glGetCompressedTexImage (GLenum, GLint, GLvoid *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);\ntypedef void (APIENTRYP PFNGLCLIENTACTIVETEXTUREPROC) (GLenum texture);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD1DPROC) (GLenum target, GLdouble s);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD1DVPROC) (GLenum target, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD1FPROC) (GLenum target, GLfloat s);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD1FVPROC) (GLenum target, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD1IPROC) (GLenum target, GLint s);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD1IVPROC) (GLenum target, const GLint *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD1SPROC) (GLenum target, GLshort s);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD1SVPROC) (GLenum target, const GLshort *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD2DPROC) (GLenum target, GLdouble s, GLdouble t);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD2DVPROC) (GLenum target, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD2FPROC) (GLenum target, GLfloat s, GLfloat t);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD2FVPROC) (GLenum target, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD2IPROC) (GLenum target, GLint s, GLint t);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD2IVPROC) (GLenum target, const GLint *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD2SPROC) (GLenum target, GLshort s, GLshort t);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD2SVPROC) (GLenum target, const GLshort *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD3DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD3DVPROC) (GLenum target, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD3FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD3FVPROC) (GLenum target, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD3IPROC) (GLenum target, GLint s, GLint t, GLint r);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD3IVPROC) (GLenum target, const GLint *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD3SPROC) (GLenum target, GLshort s, GLshort t, GLshort r);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD3SVPROC) (GLenum target, const GLshort *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD4DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD4DVPROC) (GLenum target, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD4FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD4FVPROC) (GLenum target, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD4IPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD4IVPROC) (GLenum target, const GLint *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD4SPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD4SVPROC) (GLenum target, const GLshort *v);\ntypedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXFPROC) (const GLfloat *m);\ntypedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXDPROC) (const GLdouble *m);\ntypedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXFPROC) (const GLfloat *m);\ntypedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXDPROC) (const GLdouble *m);\ntypedef void (APIENTRYP PFNGLSAMPLECOVERAGEPROC) (GLclampf value, GLboolean invert);\ntypedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data);\ntypedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);\ntypedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE1DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data);\ntypedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data);\ntypedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data);\ntypedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data);\ntypedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXIMAGEPROC) (GLenum target, GLint level, GLvoid *img);\n#endif\n\n#ifndef GL_VERSION_1_4\n#define GL_VERSION_1_4 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glBlendFuncSeparate (GLenum, GLenum, GLenum, GLenum);\nGLAPI void APIENTRY glFogCoordf (GLfloat);\nGLAPI void APIENTRY glFogCoordfv (const GLfloat *);\nGLAPI void APIENTRY glFogCoordd (GLdouble);\nGLAPI void APIENTRY glFogCoorddv (const GLdouble *);\nGLAPI void APIENTRY glFogCoordPointer (GLenum, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glMultiDrawArrays (GLenum, GLint *, GLsizei *, GLsizei);\nGLAPI void APIENTRY glMultiDrawElements (GLenum, const GLsizei *, GLenum, const GLvoid* *, GLsizei);\nGLAPI void APIENTRY glPointParameterf (GLenum, GLfloat);\nGLAPI void APIENTRY glPointParameterfv (GLenum, const GLfloat *);\nGLAPI void APIENTRY glPointParameteri (GLenum, GLint);\nGLAPI void APIENTRY glPointParameteriv (GLenum, const GLint *);\nGLAPI void APIENTRY glSecondaryColor3b (GLbyte, GLbyte, GLbyte);\nGLAPI void APIENTRY glSecondaryColor3bv (const GLbyte *);\nGLAPI void APIENTRY glSecondaryColor3d (GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glSecondaryColor3dv (const GLdouble *);\nGLAPI void APIENTRY glSecondaryColor3f (GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glSecondaryColor3fv (const GLfloat *);\nGLAPI void APIENTRY glSecondaryColor3i (GLint, GLint, GLint);\nGLAPI void APIENTRY glSecondaryColor3iv (const GLint *);\nGLAPI void APIENTRY glSecondaryColor3s (GLshort, GLshort, GLshort);\nGLAPI void APIENTRY glSecondaryColor3sv (const GLshort *);\nGLAPI void APIENTRY glSecondaryColor3ub (GLubyte, GLubyte, GLubyte);\nGLAPI void APIENTRY glSecondaryColor3ubv (const GLubyte *);\nGLAPI void APIENTRY glSecondaryColor3ui (GLuint, GLuint, GLuint);\nGLAPI void APIENTRY glSecondaryColor3uiv (const GLuint *);\nGLAPI void APIENTRY glSecondaryColor3us (GLushort, GLushort, GLushort);\nGLAPI void APIENTRY glSecondaryColor3usv (const GLushort *);\nGLAPI void APIENTRY glSecondaryColorPointer (GLint, GLenum, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glWindowPos2d (GLdouble, GLdouble);\nGLAPI void APIENTRY glWindowPos2dv (const GLdouble *);\nGLAPI void APIENTRY glWindowPos2f (GLfloat, GLfloat);\nGLAPI void APIENTRY glWindowPos2fv (const GLfloat *);\nGLAPI void APIENTRY glWindowPos2i (GLint, GLint);\nGLAPI void APIENTRY glWindowPos2iv (const GLint *);\nGLAPI void APIENTRY glWindowPos2s (GLshort, GLshort);\nGLAPI void APIENTRY glWindowPos2sv (const GLshort *);\nGLAPI void APIENTRY glWindowPos3d (GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glWindowPos3dv (const GLdouble *);\nGLAPI void APIENTRY glWindowPos3f (GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glWindowPos3fv (const GLfloat *);\nGLAPI void APIENTRY glWindowPos3i (GLint, GLint, GLint);\nGLAPI void APIENTRY glWindowPos3iv (const GLint *);\nGLAPI void APIENTRY glWindowPos3s (GLshort, GLshort, GLshort);\nGLAPI void APIENTRY glWindowPos3sv (const GLshort *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);\ntypedef void (APIENTRYP PFNGLFOGCOORDFPROC) (GLfloat coord);\ntypedef void (APIENTRYP PFNGLFOGCOORDFVPROC) (const GLfloat *coord);\ntypedef void (APIENTRYP PFNGLFOGCOORDDPROC) (GLdouble coord);\ntypedef void (APIENTRYP PFNGLFOGCOORDDVPROC) (const GLdouble *coord);\ntypedef void (APIENTRYP PFNGLFOGCOORDPOINTERPROC) (GLenum type, GLsizei stride, const GLvoid *pointer);\ntypedef void (APIENTRYP PFNGLMULTIDRAWARRAYSPROC) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount);\ntypedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount);\ntypedef void (APIENTRYP PFNGLPOINTPARAMETERFPROC) (GLenum pname, GLfloat param);\ntypedef void (APIENTRYP PFNGLPOINTPARAMETERFVPROC) (GLenum pname, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLPOINTPARAMETERIPROC) (GLenum pname, GLint param);\ntypedef void (APIENTRYP PFNGLPOINTPARAMETERIVPROC) (GLenum pname, const GLint *params);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3BPROC) (GLbyte red, GLbyte green, GLbyte blue);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3BVPROC) (const GLbyte *v);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3DPROC) (GLdouble red, GLdouble green, GLdouble blue);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3DVPROC) (const GLdouble *v);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3FPROC) (GLfloat red, GLfloat green, GLfloat blue);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3FVPROC) (const GLfloat *v);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3IPROC) (GLint red, GLint green, GLint blue);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3IVPROC) (const GLint *v);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3SPROC) (GLshort red, GLshort green, GLshort blue);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3SVPROC) (const GLshort *v);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBPROC) (GLubyte red, GLubyte green, GLubyte blue);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBVPROC) (const GLubyte *v);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIPROC) (GLuint red, GLuint green, GLuint blue);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIVPROC) (const GLuint *v);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3USPROC) (GLushort red, GLushort green, GLushort blue);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3USVPROC) (const GLushort *v);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLORPOINTERPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);\ntypedef void (APIENTRYP PFNGLWINDOWPOS2DPROC) (GLdouble x, GLdouble y);\ntypedef void (APIENTRYP PFNGLWINDOWPOS2DVPROC) (const GLdouble *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS2FPROC) (GLfloat x, GLfloat y);\ntypedef void (APIENTRYP PFNGLWINDOWPOS2FVPROC) (const GLfloat *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS2IPROC) (GLint x, GLint y);\ntypedef void (APIENTRYP PFNGLWINDOWPOS2IVPROC) (const GLint *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS2SPROC) (GLshort x, GLshort y);\ntypedef void (APIENTRYP PFNGLWINDOWPOS2SVPROC) (const GLshort *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3DPROC) (GLdouble x, GLdouble y, GLdouble z);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3DVPROC) (const GLdouble *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3FPROC) (GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3FVPROC) (const GLfloat *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3IPROC) (GLint x, GLint y, GLint z);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3IVPROC) (const GLint *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3SPROC) (GLshort x, GLshort y, GLshort z);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3SVPROC) (const GLshort *v);\n#endif\n\n#ifndef GL_VERSION_1_5\n#define GL_VERSION_1_5 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glGenQueries (GLsizei, GLuint *);\nGLAPI void APIENTRY glDeleteQueries (GLsizei, const GLuint *);\nGLAPI GLboolean APIENTRY glIsQuery (GLuint);\nGLAPI void APIENTRY glBeginQuery (GLenum, GLuint);\nGLAPI void APIENTRY glEndQuery (GLenum);\nGLAPI void APIENTRY glGetQueryiv (GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glGetQueryObjectiv (GLuint, GLenum, GLint *);\nGLAPI void APIENTRY glGetQueryObjectuiv (GLuint, GLenum, GLuint *);\nGLAPI void APIENTRY glBindBuffer (GLenum, GLuint);\nGLAPI void APIENTRY glDeleteBuffers (GLsizei, const GLuint *);\nGLAPI void APIENTRY glGenBuffers (GLsizei, GLuint *);\nGLAPI GLboolean APIENTRY glIsBuffer (GLuint);\nGLAPI void APIENTRY glBufferData (GLenum, GLsizeiptr, const GLvoid *, GLenum);\nGLAPI void APIENTRY glBufferSubData (GLenum, GLintptr, GLsizeiptr, const GLvoid *);\nGLAPI void APIENTRY glGetBufferSubData (GLenum, GLintptr, GLsizeiptr, GLvoid *);\nGLAPI GLvoid* APIENTRY glMapBuffer (GLenum, GLenum);\nGLAPI GLboolean APIENTRY glUnmapBuffer (GLenum);\nGLAPI void APIENTRY glGetBufferParameteriv (GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glGetBufferPointerv (GLenum, GLenum, GLvoid* *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLGENQUERIESPROC) (GLsizei n, GLuint *ids);\ntypedef void (APIENTRYP PFNGLDELETEQUERIESPROC) (GLsizei n, const GLuint *ids);\ntypedef GLboolean (APIENTRYP PFNGLISQUERYPROC) (GLuint id);\ntypedef void (APIENTRYP PFNGLBEGINQUERYPROC) (GLenum target, GLuint id);\ntypedef void (APIENTRYP PFNGLENDQUERYPROC) (GLenum target);\ntypedef void (APIENTRYP PFNGLGETQUERYIVPROC) (GLenum target, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETQUERYOBJECTIVPROC) (GLuint id, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint *params);\ntypedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);\ntypedef void (APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers);\ntypedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);\ntypedef GLboolean (APIENTRYP PFNGLISBUFFERPROC) (GLuint buffer);\ntypedef void (APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage);\ntypedef void (APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data);\ntypedef void (APIENTRYP PFNGLGETBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data);\ntypedef GLvoid* (APIENTRYP PFNGLMAPBUFFERPROC) (GLenum target, GLenum access);\ntypedef GLboolean (APIENTRYP PFNGLUNMAPBUFFERPROC) (GLenum target);\ntypedef void (APIENTRYP PFNGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETBUFFERPOINTERVPROC) (GLenum target, GLenum pname, GLvoid* *params);\n#endif\n\n#ifndef GL_VERSION_2_0\n#define GL_VERSION_2_0 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glBlendEquationSeparate (GLenum, GLenum);\nGLAPI void APIENTRY glDrawBuffers (GLsizei, const GLenum *);\nGLAPI void APIENTRY glStencilOpSeparate (GLenum, GLenum, GLenum, GLenum);\nGLAPI void APIENTRY glStencilFuncSeparate (GLenum, GLenum, GLint, GLuint);\nGLAPI void APIENTRY glStencilMaskSeparate (GLenum, GLuint);\nGLAPI void APIENTRY glAttachShader (GLuint, GLuint);\nGLAPI void APIENTRY glBindAttribLocation (GLuint, GLuint, const GLchar *);\nGLAPI void APIENTRY glCompileShader (GLuint);\nGLAPI GLuint APIENTRY glCreateProgram (void);\nGLAPI GLuint APIENTRY glCreateShader (GLenum);\nGLAPI void APIENTRY glDeleteProgram (GLuint);\nGLAPI void APIENTRY glDeleteShader (GLuint);\nGLAPI void APIENTRY glDetachShader (GLuint, GLuint);\nGLAPI void APIENTRY glDisableVertexAttribArray (GLuint);\nGLAPI void APIENTRY glEnableVertexAttribArray (GLuint);\nGLAPI void APIENTRY glGetActiveAttrib (GLuint, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLchar *);\nGLAPI void APIENTRY glGetActiveUniform (GLuint, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLchar *);\nGLAPI void APIENTRY glGetAttachedShaders (GLuint, GLsizei, GLsizei *, GLuint *);\nGLAPI GLint APIENTRY glGetAttribLocation (GLuint, const GLchar *);\nGLAPI void APIENTRY glGetProgramiv (GLuint, GLenum, GLint *);\nGLAPI void APIENTRY glGetProgramInfoLog (GLuint, GLsizei, GLsizei *, GLchar *);\nGLAPI void APIENTRY glGetShaderiv (GLuint, GLenum, GLint *);\nGLAPI void APIENTRY glGetShaderInfoLog (GLuint, GLsizei, GLsizei *, GLchar *);\nGLAPI void APIENTRY glGetShaderSource (GLuint, GLsizei, GLsizei *, GLchar *);\nGLAPI GLint APIENTRY glGetUniformLocation (GLuint, const GLchar *);\nGLAPI void APIENTRY glGetUniformfv (GLuint, GLint, GLfloat *);\nGLAPI void APIENTRY glGetUniformiv (GLuint, GLint, GLint *);\nGLAPI void APIENTRY glGetVertexAttribdv (GLuint, GLenum, GLdouble *);\nGLAPI void APIENTRY glGetVertexAttribfv (GLuint, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetVertexAttribiv (GLuint, GLenum, GLint *);\nGLAPI void APIENTRY glGetVertexAttribPointerv (GLuint, GLenum, GLvoid* *);\nGLAPI GLboolean APIENTRY glIsProgram (GLuint);\nGLAPI GLboolean APIENTRY glIsShader (GLuint);\nGLAPI void APIENTRY glLinkProgram (GLuint);\nGLAPI void APIENTRY glShaderSource (GLuint, GLsizei, const GLchar* *, const GLint *);\nGLAPI void APIENTRY glUseProgram (GLuint);\nGLAPI void APIENTRY glUniform1f (GLint, GLfloat);\nGLAPI void APIENTRY glUniform2f (GLint, GLfloat, GLfloat);\nGLAPI void APIENTRY glUniform3f (GLint, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glUniform4f (GLint, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glUniform1i (GLint, GLint);\nGLAPI void APIENTRY glUniform2i (GLint, GLint, GLint);\nGLAPI void APIENTRY glUniform3i (GLint, GLint, GLint, GLint);\nGLAPI void APIENTRY glUniform4i (GLint, GLint, GLint, GLint, GLint);\nGLAPI void APIENTRY glUniform1fv (GLint, GLsizei, const GLfloat *);\nGLAPI void APIENTRY glUniform2fv (GLint, GLsizei, const GLfloat *);\nGLAPI void APIENTRY glUniform3fv (GLint, GLsizei, const GLfloat *);\nGLAPI void APIENTRY glUniform4fv (GLint, GLsizei, const GLfloat *);\nGLAPI void APIENTRY glUniform1iv (GLint, GLsizei, const GLint *);\nGLAPI void APIENTRY glUniform2iv (GLint, GLsizei, const GLint *);\nGLAPI void APIENTRY glUniform3iv (GLint, GLsizei, const GLint *);\nGLAPI void APIENTRY glUniform4iv (GLint, GLsizei, const GLint *);\nGLAPI void APIENTRY glUniformMatrix2fv (GLint, GLsizei, GLboolean, const GLfloat *);\nGLAPI void APIENTRY glUniformMatrix3fv (GLint, GLsizei, GLboolean, const GLfloat *);\nGLAPI void APIENTRY glUniformMatrix4fv (GLint, GLsizei, GLboolean, const GLfloat *);\nGLAPI void APIENTRY glValidateProgram (GLuint);\nGLAPI void APIENTRY glVertexAttrib1d (GLuint, GLdouble);\nGLAPI void APIENTRY glVertexAttrib1dv (GLuint, const GLdouble *);\nGLAPI void APIENTRY glVertexAttrib1f (GLuint, GLfloat);\nGLAPI void APIENTRY glVertexAttrib1fv (GLuint, const GLfloat *);\nGLAPI void APIENTRY glVertexAttrib1s (GLuint, GLshort);\nGLAPI void APIENTRY glVertexAttrib1sv (GLuint, const GLshort *);\nGLAPI void APIENTRY glVertexAttrib2d (GLuint, GLdouble, GLdouble);\nGLAPI void APIENTRY glVertexAttrib2dv (GLuint, const GLdouble *);\nGLAPI void APIENTRY glVertexAttrib2f (GLuint, GLfloat, GLfloat);\nGLAPI void APIENTRY glVertexAttrib2fv (GLuint, const GLfloat *);\nGLAPI void APIENTRY glVertexAttrib2s (GLuint, GLshort, GLshort);\nGLAPI void APIENTRY glVertexAttrib2sv (GLuint, const GLshort *);\nGLAPI void APIENTRY glVertexAttrib3d (GLuint, GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glVertexAttrib3dv (GLuint, const GLdouble *);\nGLAPI void APIENTRY glVertexAttrib3f (GLuint, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glVertexAttrib3fv (GLuint, const GLfloat *);\nGLAPI void APIENTRY glVertexAttrib3s (GLuint, GLshort, GLshort, GLshort);\nGLAPI void APIENTRY glVertexAttrib3sv (GLuint, const GLshort *);\nGLAPI void APIENTRY glVertexAttrib4Nbv (GLuint, const GLbyte *);\nGLAPI void APIENTRY glVertexAttrib4Niv (GLuint, const GLint *);\nGLAPI void APIENTRY glVertexAttrib4Nsv (GLuint, const GLshort *);\nGLAPI void APIENTRY glVertexAttrib4Nub (GLuint, GLubyte, GLubyte, GLubyte, GLubyte);\nGLAPI void APIENTRY glVertexAttrib4Nubv (GLuint, const GLubyte *);\nGLAPI void APIENTRY glVertexAttrib4Nuiv (GLuint, const GLuint *);\nGLAPI void APIENTRY glVertexAttrib4Nusv (GLuint, const GLushort *);\nGLAPI void APIENTRY glVertexAttrib4bv (GLuint, const GLbyte *);\nGLAPI void APIENTRY glVertexAttrib4d (GLuint, GLdouble, GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glVertexAttrib4dv (GLuint, const GLdouble *);\nGLAPI void APIENTRY glVertexAttrib4f (GLuint, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glVertexAttrib4fv (GLuint, const GLfloat *);\nGLAPI void APIENTRY glVertexAttrib4iv (GLuint, const GLint *);\nGLAPI void APIENTRY glVertexAttrib4s (GLuint, GLshort, GLshort, GLshort, GLshort);\nGLAPI void APIENTRY glVertexAttrib4sv (GLuint, const GLshort *);\nGLAPI void APIENTRY glVertexAttrib4ubv (GLuint, const GLubyte *);\nGLAPI void APIENTRY glVertexAttrib4uiv (GLuint, const GLuint *);\nGLAPI void APIENTRY glVertexAttrib4usv (GLuint, const GLushort *);\nGLAPI void APIENTRY glVertexAttribPointer (GLuint, GLint, GLenum, GLboolean, GLsizei, const GLvoid *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha);\ntypedef void (APIENTRYP PFNGLDRAWBUFFERSPROC) (GLsizei n, const GLenum *bufs);\ntypedef void (APIENTRYP PFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);\ntypedef void (APIENTRYP PFNGLSTENCILFUNCSEPARATEPROC) (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask);\ntypedef void (APIENTRYP PFNGLSTENCILMASKSEPARATEPROC) (GLenum face, GLuint mask);\ntypedef void (APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);\ntypedef void (APIENTRYP PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar *name);\ntypedef void (APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader);\ntypedef GLuint (APIENTRYP PFNGLCREATEPROGRAMPROC) (void);\ntypedef GLuint (APIENTRYP PFNGLCREATESHADERPROC) (GLenum type);\ntypedef void (APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program);\ntypedef void (APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader);\ntypedef void (APIENTRYP PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader);\ntypedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index);\ntypedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index);\ntypedef void (APIENTRYP PFNGLGETACTIVEATTRIBPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);\ntypedef void (APIENTRYP PFNGLGETACTIVEUNIFORMPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);\ntypedef void (APIENTRYP PFNGLGETATTACHEDSHADERSPROC) (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *obj);\ntypedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name);\ntypedef void (APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);\ntypedef void (APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);\ntypedef void (APIENTRYP PFNGLGETSHADERSOURCEPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);\ntypedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name);\ntypedef void (APIENTRYP PFNGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint *params);\ntypedef void (APIENTRYP PFNGLGETVERTEXATTRIBDVPROC) (GLuint index, GLenum pname, GLdouble *params);\ntypedef void (APIENTRYP PFNGLGETVERTEXATTRIBFVPROC) (GLuint index, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVPROC) (GLuint index, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum pname, GLvoid* *pointer);\ntypedef GLboolean (APIENTRYP PFNGLISPROGRAMPROC) (GLuint program);\ntypedef GLboolean (APIENTRYP PFNGLISSHADERPROC) (GLuint shader);\ntypedef void (APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program);\ntypedef void (APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar* *string, const GLint *length);\ntypedef void (APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program);\ntypedef void (APIENTRYP PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0);\ntypedef void (APIENTRYP PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1);\ntypedef void (APIENTRYP PFNGLUNIFORM3FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);\ntypedef void (APIENTRYP PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);\ntypedef void (APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0);\ntypedef void (APIENTRYP PFNGLUNIFORM2IPROC) (GLint location, GLint v0, GLint v1);\ntypedef void (APIENTRYP PFNGLUNIFORM3IPROC) (GLint location, GLint v0, GLint v1, GLint v2);\ntypedef void (APIENTRYP PFNGLUNIFORM4IPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);\ntypedef void (APIENTRYP PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint *value);\ntypedef void (APIENTRYP PFNGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint *value);\ntypedef void (APIENTRYP PFNGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint *value);\ntypedef void (APIENTRYP PFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint *value);\ntypedef void (APIENTRYP PFNGLUNIFORMMATRIX2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLVALIDATEPROGRAMPROC) (GLuint program);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB1DPROC) (GLuint index, GLdouble x);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB1DVPROC) (GLuint index, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB1FPROC) (GLuint index, GLfloat x);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB1FVPROC) (GLuint index, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB1SPROC) (GLuint index, GLshort x);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB1SVPROC) (GLuint index, const GLshort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB2DPROC) (GLuint index, GLdouble x, GLdouble y);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB2DVPROC) (GLuint index, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB2FPROC) (GLuint index, GLfloat x, GLfloat y);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB2FVPROC) (GLuint index, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB2SPROC) (GLuint index, GLshort x, GLshort y);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB2SVPROC) (GLuint index, const GLshort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB3DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB3DVPROC) (GLuint index, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB3FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB3FVPROC) (GLuint index, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB3SPROC) (GLuint index, GLshort x, GLshort y, GLshort z);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB3SVPROC) (GLuint index, const GLshort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4NBVPROC) (GLuint index, const GLbyte *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4NIVPROC) (GLuint index, const GLint *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4NSVPROC) (GLuint index, const GLshort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBVPROC) (GLuint index, const GLubyte *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4NUIVPROC) (GLuint index, const GLuint *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4NUSVPROC) (GLuint index, const GLushort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4BVPROC) (GLuint index, const GLbyte *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4DVPROC) (GLuint index, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4IVPROC) (GLuint index, const GLint *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4SPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4SVPROC) (GLuint index, const GLshort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4UBVPROC) (GLuint index, const GLubyte *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4UIVPROC) (GLuint index, const GLuint *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4USVPROC) (GLuint index, const GLushort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer);\n#endif\n\n#ifndef GL_VERSION_2_1\n#define GL_VERSION_2_1 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glUniformMatrix2x3fv (GLint, GLsizei, GLboolean, const GLfloat *);\nGLAPI void APIENTRY glUniformMatrix3x2fv (GLint, GLsizei, GLboolean, const GLfloat *);\nGLAPI void APIENTRY glUniformMatrix2x4fv (GLint, GLsizei, GLboolean, const GLfloat *);\nGLAPI void APIENTRY glUniformMatrix4x2fv (GLint, GLsizei, GLboolean, const GLfloat *);\nGLAPI void APIENTRY glUniformMatrix3x4fv (GLint, GLsizei, GLboolean, const GLfloat *);\nGLAPI void APIENTRY glUniformMatrix4x3fv (GLint, GLsizei, GLboolean, const GLfloat *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLUNIFORMMATRIX2X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLUNIFORMMATRIX3X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLUNIFORMMATRIX2X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLUNIFORMMATRIX4X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLUNIFORMMATRIX3X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLUNIFORMMATRIX4X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);\n#endif\n\n#ifndef GL_ARB_multitexture\n#define GL_ARB_multitexture 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glActiveTextureARB (GLenum);\nGLAPI void APIENTRY glClientActiveTextureARB (GLenum);\nGLAPI void APIENTRY glMultiTexCoord1dARB (GLenum, GLdouble);\nGLAPI void APIENTRY glMultiTexCoord1dvARB (GLenum, const GLdouble *);\nGLAPI void APIENTRY glMultiTexCoord1fARB (GLenum, GLfloat);\nGLAPI void APIENTRY glMultiTexCoord1fvARB (GLenum, const GLfloat *);\nGLAPI void APIENTRY glMultiTexCoord1iARB (GLenum, GLint);\nGLAPI void APIENTRY glMultiTexCoord1ivARB (GLenum, const GLint *);\nGLAPI void APIENTRY glMultiTexCoord1sARB (GLenum, GLshort);\nGLAPI void APIENTRY glMultiTexCoord1svARB (GLenum, const GLshort *);\nGLAPI void APIENTRY glMultiTexCoord2dARB (GLenum, GLdouble, GLdouble);\nGLAPI void APIENTRY glMultiTexCoord2dvARB (GLenum, const GLdouble *);\nGLAPI void APIENTRY glMultiTexCoord2fARB (GLenum, GLfloat, GLfloat);\nGLAPI void APIENTRY glMultiTexCoord2fvARB (GLenum, const GLfloat *);\nGLAPI void APIENTRY glMultiTexCoord2iARB (GLenum, GLint, GLint);\nGLAPI void APIENTRY glMultiTexCoord2ivARB (GLenum, const GLint *);\nGLAPI void APIENTRY glMultiTexCoord2sARB (GLenum, GLshort, GLshort);\nGLAPI void APIENTRY glMultiTexCoord2svARB (GLenum, const GLshort *);\nGLAPI void APIENTRY glMultiTexCoord3dARB (GLenum, GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glMultiTexCoord3dvARB (GLenum, const GLdouble *);\nGLAPI void APIENTRY glMultiTexCoord3fARB (GLenum, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glMultiTexCoord3fvARB (GLenum, const GLfloat *);\nGLAPI void APIENTRY glMultiTexCoord3iARB (GLenum, GLint, GLint, GLint);\nGLAPI void APIENTRY glMultiTexCoord3ivARB (GLenum, const GLint *);\nGLAPI void APIENTRY glMultiTexCoord3sARB (GLenum, GLshort, GLshort, GLshort);\nGLAPI void APIENTRY glMultiTexCoord3svARB (GLenum, const GLshort *);\nGLAPI void APIENTRY glMultiTexCoord4dARB (GLenum, GLdouble, GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glMultiTexCoord4dvARB (GLenum, const GLdouble *);\nGLAPI void APIENTRY glMultiTexCoord4fARB (GLenum, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glMultiTexCoord4fvARB (GLenum, const GLfloat *);\nGLAPI void APIENTRY glMultiTexCoord4iARB (GLenum, GLint, GLint, GLint, GLint);\nGLAPI void APIENTRY glMultiTexCoord4ivARB (GLenum, const GLint *);\nGLAPI void APIENTRY glMultiTexCoord4sARB (GLenum, GLshort, GLshort, GLshort, GLshort);\nGLAPI void APIENTRY glMultiTexCoord4svARB (GLenum, const GLshort *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLACTIVETEXTUREARBPROC) (GLenum texture);\ntypedef void (APIENTRYP PFNGLCLIENTACTIVETEXTUREARBPROC) (GLenum texture);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD1DARBPROC) (GLenum target, GLdouble s);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD1DVARBPROC) (GLenum target, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD1FARBPROC) (GLenum target, GLfloat s);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD1FVARBPROC) (GLenum target, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD1IARBPROC) (GLenum target, GLint s);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD1IVARBPROC) (GLenum target, const GLint *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD1SARBPROC) (GLenum target, GLshort s);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD1SVARBPROC) (GLenum target, const GLshort *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD2DARBPROC) (GLenum target, GLdouble s, GLdouble t);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD2DVARBPROC) (GLenum target, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD2FARBPROC) (GLenum target, GLfloat s, GLfloat t);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD2FVARBPROC) (GLenum target, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD2IARBPROC) (GLenum target, GLint s, GLint t);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD2IVARBPROC) (GLenum target, const GLint *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD2SARBPROC) (GLenum target, GLshort s, GLshort t);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD2SVARBPROC) (GLenum target, const GLshort *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD3DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD3DVARBPROC) (GLenum target, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD3FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD3FVARBPROC) (GLenum target, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD3IARBPROC) (GLenum target, GLint s, GLint t, GLint r);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD3IVARBPROC) (GLenum target, const GLint *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD3SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD3SVARBPROC) (GLenum target, const GLshort *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD4DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD4DVARBPROC) (GLenum target, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD4FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD4FVARBPROC) (GLenum target, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD4IARBPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD4IVARBPROC) (GLenum target, const GLint *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD4SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD4SVARBPROC) (GLenum target, const GLshort *v);\n#endif\n\n#ifndef GL_ARB_transpose_matrix\n#define GL_ARB_transpose_matrix 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glLoadTransposeMatrixfARB (const GLfloat *);\nGLAPI void APIENTRY glLoadTransposeMatrixdARB (const GLdouble *);\nGLAPI void APIENTRY glMultTransposeMatrixfARB (const GLfloat *);\nGLAPI void APIENTRY glMultTransposeMatrixdARB (const GLdouble *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXFARBPROC) (const GLfloat *m);\ntypedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXDARBPROC) (const GLdouble *m);\ntypedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXFARBPROC) (const GLfloat *m);\ntypedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXDARBPROC) (const GLdouble *m);\n#endif\n\n#ifndef GL_ARB_multisample\n#define GL_ARB_multisample 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glSampleCoverageARB (GLclampf, GLboolean);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLSAMPLECOVERAGEARBPROC) (GLclampf value, GLboolean invert);\n#endif\n\n#ifndef GL_ARB_texture_env_add\n#define GL_ARB_texture_env_add 1\n#endif\n\n#ifndef GL_ARB_texture_cube_map\n#define GL_ARB_texture_cube_map 1\n#endif\n\n#ifndef GL_ARB_texture_compression\n#define GL_ARB_texture_compression 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glCompressedTexImage3DARB (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glCompressedTexImage2DARB (GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glCompressedTexImage1DARB (GLenum, GLint, GLenum, GLsizei, GLint, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glCompressedTexSubImage3DARB (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glCompressedTexSubImage2DARB (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glCompressedTexSubImage1DARB (GLenum, GLint, GLint, GLsizei, GLenum, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glGetCompressedTexImageARB (GLenum, GLint, GLvoid *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data);\ntypedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);\ntypedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE1DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data);\ntypedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data);\ntypedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data);\ntypedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data);\ntypedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint level, GLvoid *img);\n#endif\n\n#ifndef GL_ARB_texture_border_clamp\n#define GL_ARB_texture_border_clamp 1\n#endif\n\n#ifndef GL_ARB_point_parameters\n#define GL_ARB_point_parameters 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glPointParameterfARB (GLenum, GLfloat);\nGLAPI void APIENTRY glPointParameterfvARB (GLenum, const GLfloat *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLPOINTPARAMETERFARBPROC) (GLenum pname, GLfloat param);\ntypedef void (APIENTRYP PFNGLPOINTPARAMETERFVARBPROC) (GLenum pname, const GLfloat *params);\n#endif\n\n#ifndef GL_ARB_vertex_blend\n#define GL_ARB_vertex_blend 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glWeightbvARB (GLint, const GLbyte *);\nGLAPI void APIENTRY glWeightsvARB (GLint, const GLshort *);\nGLAPI void APIENTRY glWeightivARB (GLint, const GLint *);\nGLAPI void APIENTRY glWeightfvARB (GLint, const GLfloat *);\nGLAPI void APIENTRY glWeightdvARB (GLint, const GLdouble *);\nGLAPI void APIENTRY glWeightubvARB (GLint, const GLubyte *);\nGLAPI void APIENTRY glWeightusvARB (GLint, const GLushort *);\nGLAPI void APIENTRY glWeightuivARB (GLint, const GLuint *);\nGLAPI void APIENTRY glWeightPointerARB (GLint, GLenum, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glVertexBlendARB (GLint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLWEIGHTBVARBPROC) (GLint size, const GLbyte *weights);\ntypedef void (APIENTRYP PFNGLWEIGHTSVARBPROC) (GLint size, const GLshort *weights);\ntypedef void (APIENTRYP PFNGLWEIGHTIVARBPROC) (GLint size, const GLint *weights);\ntypedef void (APIENTRYP PFNGLWEIGHTFVARBPROC) (GLint size, const GLfloat *weights);\ntypedef void (APIENTRYP PFNGLWEIGHTDVARBPROC) (GLint size, const GLdouble *weights);\ntypedef void (APIENTRYP PFNGLWEIGHTUBVARBPROC) (GLint size, const GLubyte *weights);\ntypedef void (APIENTRYP PFNGLWEIGHTUSVARBPROC) (GLint size, const GLushort *weights);\ntypedef void (APIENTRYP PFNGLWEIGHTUIVARBPROC) (GLint size, const GLuint *weights);\ntypedef void (APIENTRYP PFNGLWEIGHTPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);\ntypedef void (APIENTRYP PFNGLVERTEXBLENDARBPROC) (GLint count);\n#endif\n\n#ifndef GL_ARB_matrix_palette\n#define GL_ARB_matrix_palette 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glCurrentPaletteMatrixARB (GLint);\nGLAPI void APIENTRY glMatrixIndexubvARB (GLint, const GLubyte *);\nGLAPI void APIENTRY glMatrixIndexusvARB (GLint, const GLushort *);\nGLAPI void APIENTRY glMatrixIndexuivARB (GLint, const GLuint *);\nGLAPI void APIENTRY glMatrixIndexPointerARB (GLint, GLenum, GLsizei, const GLvoid *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLCURRENTPALETTEMATRIXARBPROC) (GLint index);\ntypedef void (APIENTRYP PFNGLMATRIXINDEXUBVARBPROC) (GLint size, const GLubyte *indices);\ntypedef void (APIENTRYP PFNGLMATRIXINDEXUSVARBPROC) (GLint size, const GLushort *indices);\ntypedef void (APIENTRYP PFNGLMATRIXINDEXUIVARBPROC) (GLint size, const GLuint *indices);\ntypedef void (APIENTRYP PFNGLMATRIXINDEXPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);\n#endif\n\n#ifndef GL_ARB_texture_env_combine\n#define GL_ARB_texture_env_combine 1\n#endif\n\n#ifndef GL_ARB_texture_env_crossbar\n#define GL_ARB_texture_env_crossbar 1\n#endif\n\n#ifndef GL_ARB_texture_env_dot3\n#define GL_ARB_texture_env_dot3 1\n#endif\n\n#ifndef GL_ARB_texture_mirrored_repeat\n#define GL_ARB_texture_mirrored_repeat 1\n#endif\n\n#ifndef GL_ARB_depth_texture\n#define GL_ARB_depth_texture 1\n#endif\n\n#ifndef GL_ARB_shadow\n#define GL_ARB_shadow 1\n#endif\n\n#ifndef GL_ARB_shadow_ambient\n#define GL_ARB_shadow_ambient 1\n#endif\n\n#ifndef GL_ARB_window_pos\n#define GL_ARB_window_pos 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glWindowPos2dARB (GLdouble, GLdouble);\nGLAPI void APIENTRY glWindowPos2dvARB (const GLdouble *);\nGLAPI void APIENTRY glWindowPos2fARB (GLfloat, GLfloat);\nGLAPI void APIENTRY glWindowPos2fvARB (const GLfloat *);\nGLAPI void APIENTRY glWindowPos2iARB (GLint, GLint);\nGLAPI void APIENTRY glWindowPos2ivARB (const GLint *);\nGLAPI void APIENTRY glWindowPos2sARB (GLshort, GLshort);\nGLAPI void APIENTRY glWindowPos2svARB (const GLshort *);\nGLAPI void APIENTRY glWindowPos3dARB (GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glWindowPos3dvARB (const GLdouble *);\nGLAPI void APIENTRY glWindowPos3fARB (GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glWindowPos3fvARB (const GLfloat *);\nGLAPI void APIENTRY glWindowPos3iARB (GLint, GLint, GLint);\nGLAPI void APIENTRY glWindowPos3ivARB (const GLint *);\nGLAPI void APIENTRY glWindowPos3sARB (GLshort, GLshort, GLshort);\nGLAPI void APIENTRY glWindowPos3svARB (const GLshort *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLWINDOWPOS2DARBPROC) (GLdouble x, GLdouble y);\ntypedef void (APIENTRYP PFNGLWINDOWPOS2DVARBPROC) (const GLdouble *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS2FARBPROC) (GLfloat x, GLfloat y);\ntypedef void (APIENTRYP PFNGLWINDOWPOS2FVARBPROC) (const GLfloat *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS2IARBPROC) (GLint x, GLint y);\ntypedef void (APIENTRYP PFNGLWINDOWPOS2IVARBPROC) (const GLint *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS2SARBPROC) (GLshort x, GLshort y);\ntypedef void (APIENTRYP PFNGLWINDOWPOS2SVARBPROC) (const GLshort *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3DARBPROC) (GLdouble x, GLdouble y, GLdouble z);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3DVARBPROC) (const GLdouble *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3FARBPROC) (GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3FVARBPROC) (const GLfloat *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3IARBPROC) (GLint x, GLint y, GLint z);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3IVARBPROC) (const GLint *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3SARBPROC) (GLshort x, GLshort y, GLshort z);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3SVARBPROC) (const GLshort *v);\n#endif\n\n#ifndef GL_ARB_vertex_program\n#define GL_ARB_vertex_program 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glVertexAttrib1dARB (GLuint, GLdouble);\nGLAPI void APIENTRY glVertexAttrib1dvARB (GLuint, const GLdouble *);\nGLAPI void APIENTRY glVertexAttrib1fARB (GLuint, GLfloat);\nGLAPI void APIENTRY glVertexAttrib1fvARB (GLuint, const GLfloat *);\nGLAPI void APIENTRY glVertexAttrib1sARB (GLuint, GLshort);\nGLAPI void APIENTRY glVertexAttrib1svARB (GLuint, const GLshort *);\nGLAPI void APIENTRY glVertexAttrib2dARB (GLuint, GLdouble, GLdouble);\nGLAPI void APIENTRY glVertexAttrib2dvARB (GLuint, const GLdouble *);\nGLAPI void APIENTRY glVertexAttrib2fARB (GLuint, GLfloat, GLfloat);\nGLAPI void APIENTRY glVertexAttrib2fvARB (GLuint, const GLfloat *);\nGLAPI void APIENTRY glVertexAttrib2sARB (GLuint, GLshort, GLshort);\nGLAPI void APIENTRY glVertexAttrib2svARB (GLuint, const GLshort *);\nGLAPI void APIENTRY glVertexAttrib3dARB (GLuint, GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glVertexAttrib3dvARB (GLuint, const GLdouble *);\nGLAPI void APIENTRY glVertexAttrib3fARB (GLuint, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glVertexAttrib3fvARB (GLuint, const GLfloat *);\nGLAPI void APIENTRY glVertexAttrib3sARB (GLuint, GLshort, GLshort, GLshort);\nGLAPI void APIENTRY glVertexAttrib3svARB (GLuint, const GLshort *);\nGLAPI void APIENTRY glVertexAttrib4NbvARB (GLuint, const GLbyte *);\nGLAPI void APIENTRY glVertexAttrib4NivARB (GLuint, const GLint *);\nGLAPI void APIENTRY glVertexAttrib4NsvARB (GLuint, const GLshort *);\nGLAPI void APIENTRY glVertexAttrib4NubARB (GLuint, GLubyte, GLubyte, GLubyte, GLubyte);\nGLAPI void APIENTRY glVertexAttrib4NubvARB (GLuint, const GLubyte *);\nGLAPI void APIENTRY glVertexAttrib4NuivARB (GLuint, const GLuint *);\nGLAPI void APIENTRY glVertexAttrib4NusvARB (GLuint, const GLushort *);\nGLAPI void APIENTRY glVertexAttrib4bvARB (GLuint, const GLbyte *);\nGLAPI void APIENTRY glVertexAttrib4dARB (GLuint, GLdouble, GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glVertexAttrib4dvARB (GLuint, const GLdouble *);\nGLAPI void APIENTRY glVertexAttrib4fARB (GLuint, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glVertexAttrib4fvARB (GLuint, const GLfloat *);\nGLAPI void APIENTRY glVertexAttrib4ivARB (GLuint, const GLint *);\nGLAPI void APIENTRY glVertexAttrib4sARB (GLuint, GLshort, GLshort, GLshort, GLshort);\nGLAPI void APIENTRY glVertexAttrib4svARB (GLuint, const GLshort *);\nGLAPI void APIENTRY glVertexAttrib4ubvARB (GLuint, const GLubyte *);\nGLAPI void APIENTRY glVertexAttrib4uivARB (GLuint, const GLuint *);\nGLAPI void APIENTRY glVertexAttrib4usvARB (GLuint, const GLushort *);\nGLAPI void APIENTRY glVertexAttribPointerARB (GLuint, GLint, GLenum, GLboolean, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glEnableVertexAttribArrayARB (GLuint);\nGLAPI void APIENTRY glDisableVertexAttribArrayARB (GLuint);\nGLAPI void APIENTRY glProgramStringARB (GLenum, GLenum, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glBindProgramARB (GLenum, GLuint);\nGLAPI void APIENTRY glDeleteProgramsARB (GLsizei, const GLuint *);\nGLAPI void APIENTRY glGenProgramsARB (GLsizei, GLuint *);\nGLAPI void APIENTRY glProgramEnvParameter4dARB (GLenum, GLuint, GLdouble, GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glProgramEnvParameter4dvARB (GLenum, GLuint, const GLdouble *);\nGLAPI void APIENTRY glProgramEnvParameter4fARB (GLenum, GLuint, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glProgramEnvParameter4fvARB (GLenum, GLuint, const GLfloat *);\nGLAPI void APIENTRY glProgramLocalParameter4dARB (GLenum, GLuint, GLdouble, GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glProgramLocalParameter4dvARB (GLenum, GLuint, const GLdouble *);\nGLAPI void APIENTRY glProgramLocalParameter4fARB (GLenum, GLuint, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glProgramLocalParameter4fvARB (GLenum, GLuint, const GLfloat *);\nGLAPI void APIENTRY glGetProgramEnvParameterdvARB (GLenum, GLuint, GLdouble *);\nGLAPI void APIENTRY glGetProgramEnvParameterfvARB (GLenum, GLuint, GLfloat *);\nGLAPI void APIENTRY glGetProgramLocalParameterdvARB (GLenum, GLuint, GLdouble *);\nGLAPI void APIENTRY glGetProgramLocalParameterfvARB (GLenum, GLuint, GLfloat *);\nGLAPI void APIENTRY glGetProgramivARB (GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glGetProgramStringARB (GLenum, GLenum, GLvoid *);\nGLAPI void APIENTRY glGetVertexAttribdvARB (GLuint, GLenum, GLdouble *);\nGLAPI void APIENTRY glGetVertexAttribfvARB (GLuint, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetVertexAttribivARB (GLuint, GLenum, GLint *);\nGLAPI void APIENTRY glGetVertexAttribPointervARB (GLuint, GLenum, GLvoid* *);\nGLAPI GLboolean APIENTRY glIsProgramARB (GLuint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB1DARBPROC) (GLuint index, GLdouble x);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB1DVARBPROC) (GLuint index, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB1FARBPROC) (GLuint index, GLfloat x);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB1FVARBPROC) (GLuint index, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB1SARBPROC) (GLuint index, GLshort x);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB1SVARBPROC) (GLuint index, const GLshort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB2DARBPROC) (GLuint index, GLdouble x, GLdouble y);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB2DVARBPROC) (GLuint index, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB2FARBPROC) (GLuint index, GLfloat x, GLfloat y);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB2FVARBPROC) (GLuint index, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB2SARBPROC) (GLuint index, GLshort x, GLshort y);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB2SVARBPROC) (GLuint index, const GLshort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB3DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB3DVARBPROC) (GLuint index, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB3FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB3FVARBPROC) (GLuint index, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB3SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB3SVARBPROC) (GLuint index, const GLshort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4NBVARBPROC) (GLuint index, const GLbyte *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4NIVARBPROC) (GLuint index, const GLint *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4NSVARBPROC) (GLuint index, const GLshort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBARBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBVARBPROC) (GLuint index, const GLubyte *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4NUIVARBPROC) (GLuint index, const GLuint *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4NUSVARBPROC) (GLuint index, const GLushort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4BVARBPROC) (GLuint index, const GLbyte *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4DVARBPROC) (GLuint index, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4FVARBPROC) (GLuint index, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4IVARBPROC) (GLuint index, const GLint *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4SVARBPROC) (GLuint index, const GLshort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4UBVARBPROC) (GLuint index, const GLubyte *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4UIVARBPROC) (GLuint index, const GLuint *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4USVARBPROC) (GLuint index, const GLushort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERARBPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer);\ntypedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYARBPROC) (GLuint index);\ntypedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) (GLuint index);\ntypedef void (APIENTRYP PFNGLPROGRAMSTRINGARBPROC) (GLenum target, GLenum format, GLsizei len, const GLvoid *string);\ntypedef void (APIENTRYP PFNGLBINDPROGRAMARBPROC) (GLenum target, GLuint program);\ntypedef void (APIENTRYP PFNGLDELETEPROGRAMSARBPROC) (GLsizei n, const GLuint *programs);\ntypedef void (APIENTRYP PFNGLGENPROGRAMSARBPROC) (GLsizei n, GLuint *programs);\ntypedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);\ntypedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble *params);\ntypedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);\ntypedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);\ntypedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble *params);\ntypedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);\ntypedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETPROGRAMENVPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble *params);\ntypedef void (APIENTRYP PFNGLGETPROGRAMENVPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble *params);\ntypedef void (APIENTRYP PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETPROGRAMIVARBPROC) (GLenum target, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETPROGRAMSTRINGARBPROC) (GLenum target, GLenum pname, GLvoid *string);\ntypedef void (APIENTRYP PFNGLGETVERTEXATTRIBDVARBPROC) (GLuint index, GLenum pname, GLdouble *params);\ntypedef void (APIENTRYP PFNGLGETVERTEXATTRIBFVARBPROC) (GLuint index, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVARBPROC) (GLuint index, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVARBPROC) (GLuint index, GLenum pname, GLvoid* *pointer);\ntypedef GLboolean (APIENTRYP PFNGLISPROGRAMARBPROC) (GLuint program);\n#endif\n\n#ifndef GL_ARB_fragment_program\n#define GL_ARB_fragment_program 1\n/* All ARB_fragment_program entry points are shared with ARB_vertex_program. */\n#endif\n\n#ifndef GL_ARB_vertex_buffer_object\n#define GL_ARB_vertex_buffer_object 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glBindBufferARB (GLenum, GLuint);\nGLAPI void APIENTRY glDeleteBuffersARB (GLsizei, const GLuint *);\nGLAPI void APIENTRY glGenBuffersARB (GLsizei, GLuint *);\nGLAPI GLboolean APIENTRY glIsBufferARB (GLuint);\nGLAPI void APIENTRY glBufferDataARB (GLenum, GLsizeiptrARB, const GLvoid *, GLenum);\nGLAPI void APIENTRY glBufferSubDataARB (GLenum, GLintptrARB, GLsizeiptrARB, const GLvoid *);\nGLAPI void APIENTRY glGetBufferSubDataARB (GLenum, GLintptrARB, GLsizeiptrARB, GLvoid *);\nGLAPI GLvoid* APIENTRY glMapBufferARB (GLenum, GLenum);\nGLAPI GLboolean APIENTRY glUnmapBufferARB (GLenum);\nGLAPI void APIENTRY glGetBufferParameterivARB (GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glGetBufferPointervARB (GLenum, GLenum, GLvoid* *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLBINDBUFFERARBPROC) (GLenum target, GLuint buffer);\ntypedef void (APIENTRYP PFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint *buffers);\ntypedef void (APIENTRYP PFNGLGENBUFFERSARBPROC) (GLsizei n, GLuint *buffers);\ntypedef GLboolean (APIENTRYP PFNGLISBUFFERARBPROC) (GLuint buffer);\ntypedef void (APIENTRYP PFNGLBUFFERDATAARBPROC) (GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage);\ntypedef void (APIENTRYP PFNGLBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid *data);\ntypedef void (APIENTRYP PFNGLGETBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid *data);\ntypedef GLvoid* (APIENTRYP PFNGLMAPBUFFERARBPROC) (GLenum target, GLenum access);\ntypedef GLboolean (APIENTRYP PFNGLUNMAPBUFFERARBPROC) (GLenum target);\ntypedef void (APIENTRYP PFNGLGETBUFFERPARAMETERIVARBPROC) (GLenum target, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETBUFFERPOINTERVARBPROC) (GLenum target, GLenum pname, GLvoid* *params);\n#endif\n\n#ifndef GL_ARB_occlusion_query\n#define GL_ARB_occlusion_query 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glGenQueriesARB (GLsizei, GLuint *);\nGLAPI void APIENTRY glDeleteQueriesARB (GLsizei, const GLuint *);\nGLAPI GLboolean APIENTRY glIsQueryARB (GLuint);\nGLAPI void APIENTRY glBeginQueryARB (GLenum, GLuint);\nGLAPI void APIENTRY glEndQueryARB (GLenum);\nGLAPI void APIENTRY glGetQueryivARB (GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glGetQueryObjectivARB (GLuint, GLenum, GLint *);\nGLAPI void APIENTRY glGetQueryObjectuivARB (GLuint, GLenum, GLuint *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLGENQUERIESARBPROC) (GLsizei n, GLuint *ids);\ntypedef void (APIENTRYP PFNGLDELETEQUERIESARBPROC) (GLsizei n, const GLuint *ids);\ntypedef GLboolean (APIENTRYP PFNGLISQUERYARBPROC) (GLuint id);\ntypedef void (APIENTRYP PFNGLBEGINQUERYARBPROC) (GLenum target, GLuint id);\ntypedef void (APIENTRYP PFNGLENDQUERYARBPROC) (GLenum target);\ntypedef void (APIENTRYP PFNGLGETQUERYIVARBPROC) (GLenum target, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETQUERYOBJECTIVARBPROC) (GLuint id, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETQUERYOBJECTUIVARBPROC) (GLuint id, GLenum pname, GLuint *params);\n#endif\n\n#ifndef GL_ARB_shader_objects\n#define GL_ARB_shader_objects 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glDeleteObjectARB (GLhandleARB);\nGLAPI GLhandleARB APIENTRY glGetHandleARB (GLenum);\nGLAPI void APIENTRY glDetachObjectARB (GLhandleARB, GLhandleARB);\nGLAPI GLhandleARB APIENTRY glCreateShaderObjectARB (GLenum);\nGLAPI void APIENTRY glShaderSourceARB (GLhandleARB, GLsizei, const GLcharARB* *, const GLint *);\nGLAPI void APIENTRY glCompileShaderARB (GLhandleARB);\nGLAPI GLhandleARB APIENTRY glCreateProgramObjectARB (void);\nGLAPI void APIENTRY glAttachObjectARB (GLhandleARB, GLhandleARB);\nGLAPI void APIENTRY glLinkProgramARB (GLhandleARB);\nGLAPI void APIENTRY glUseProgramObjectARB (GLhandleARB);\nGLAPI void APIENTRY glValidateProgramARB (GLhandleARB);\nGLAPI void APIENTRY glUniform1fARB (GLint, GLfloat);\nGLAPI void APIENTRY glUniform2fARB (GLint, GLfloat, GLfloat);\nGLAPI void APIENTRY glUniform3fARB (GLint, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glUniform4fARB (GLint, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glUniform1iARB (GLint, GLint);\nGLAPI void APIENTRY glUniform2iARB (GLint, GLint, GLint);\nGLAPI void APIENTRY glUniform3iARB (GLint, GLint, GLint, GLint);\nGLAPI void APIENTRY glUniform4iARB (GLint, GLint, GLint, GLint, GLint);\nGLAPI void APIENTRY glUniform1fvARB (GLint, GLsizei, const GLfloat *);\nGLAPI void APIENTRY glUniform2fvARB (GLint, GLsizei, const GLfloat *);\nGLAPI void APIENTRY glUniform3fvARB (GLint, GLsizei, const GLfloat *);\nGLAPI void APIENTRY glUniform4fvARB (GLint, GLsizei, const GLfloat *);\nGLAPI void APIENTRY glUniform1ivARB (GLint, GLsizei, const GLint *);\nGLAPI void APIENTRY glUniform2ivARB (GLint, GLsizei, const GLint *);\nGLAPI void APIENTRY glUniform3ivARB (GLint, GLsizei, const GLint *);\nGLAPI void APIENTRY glUniform4ivARB (GLint, GLsizei, const GLint *);\nGLAPI void APIENTRY glUniformMatrix2fvARB (GLint, GLsizei, GLboolean, const GLfloat *);\nGLAPI void APIENTRY glUniformMatrix3fvARB (GLint, GLsizei, GLboolean, const GLfloat *);\nGLAPI void APIENTRY glUniformMatrix4fvARB (GLint, GLsizei, GLboolean, const GLfloat *);\nGLAPI void APIENTRY glGetObjectParameterfvARB (GLhandleARB, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetObjectParameterivARB (GLhandleARB, GLenum, GLint *);\nGLAPI void APIENTRY glGetInfoLogARB (GLhandleARB, GLsizei, GLsizei *, GLcharARB *);\nGLAPI void APIENTRY glGetAttachedObjectsARB (GLhandleARB, GLsizei, GLsizei *, GLhandleARB *);\nGLAPI GLint APIENTRY glGetUniformLocationARB (GLhandleARB, const GLcharARB *);\nGLAPI void APIENTRY glGetActiveUniformARB (GLhandleARB, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLcharARB *);\nGLAPI void APIENTRY glGetUniformfvARB (GLhandleARB, GLint, GLfloat *);\nGLAPI void APIENTRY glGetUniformivARB (GLhandleARB, GLint, GLint *);\nGLAPI void APIENTRY glGetShaderSourceARB (GLhandleARB, GLsizei, GLsizei *, GLcharARB *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLDELETEOBJECTARBPROC) (GLhandleARB obj);\ntypedef GLhandleARB (APIENTRYP PFNGLGETHANDLEARBPROC) (GLenum pname);\ntypedef void (APIENTRYP PFNGLDETACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB attachedObj);\ntypedef GLhandleARB (APIENTRYP PFNGLCREATESHADEROBJECTARBPROC) (GLenum shaderType);\ntypedef void (APIENTRYP PFNGLSHADERSOURCEARBPROC) (GLhandleARB shaderObj, GLsizei count, const GLcharARB* *string, const GLint *length);\ntypedef void (APIENTRYP PFNGLCOMPILESHADERARBPROC) (GLhandleARB shaderObj);\ntypedef GLhandleARB (APIENTRYP PFNGLCREATEPROGRAMOBJECTARBPROC) (void);\ntypedef void (APIENTRYP PFNGLATTACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB obj);\ntypedef void (APIENTRYP PFNGLLINKPROGRAMARBPROC) (GLhandleARB programObj);\ntypedef void (APIENTRYP PFNGLUSEPROGRAMOBJECTARBPROC) (GLhandleARB programObj);\ntypedef void (APIENTRYP PFNGLVALIDATEPROGRAMARBPROC) (GLhandleARB programObj);\ntypedef void (APIENTRYP PFNGLUNIFORM1FARBPROC) (GLint location, GLfloat v0);\ntypedef void (APIENTRYP PFNGLUNIFORM2FARBPROC) (GLint location, GLfloat v0, GLfloat v1);\ntypedef void (APIENTRYP PFNGLUNIFORM3FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);\ntypedef void (APIENTRYP PFNGLUNIFORM4FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);\ntypedef void (APIENTRYP PFNGLUNIFORM1IARBPROC) (GLint location, GLint v0);\ntypedef void (APIENTRYP PFNGLUNIFORM2IARBPROC) (GLint location, GLint v0, GLint v1);\ntypedef void (APIENTRYP PFNGLUNIFORM3IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2);\ntypedef void (APIENTRYP PFNGLUNIFORM4IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);\ntypedef void (APIENTRYP PFNGLUNIFORM1FVARBPROC) (GLint location, GLsizei count, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLUNIFORM2FVARBPROC) (GLint location, GLsizei count, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLUNIFORM3FVARBPROC) (GLint location, GLsizei count, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLUNIFORM4FVARBPROC) (GLint location, GLsizei count, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLUNIFORM1IVARBPROC) (GLint location, GLsizei count, const GLint *value);\ntypedef void (APIENTRYP PFNGLUNIFORM2IVARBPROC) (GLint location, GLsizei count, const GLint *value);\ntypedef void (APIENTRYP PFNGLUNIFORM3IVARBPROC) (GLint location, GLsizei count, const GLint *value);\ntypedef void (APIENTRYP PFNGLUNIFORM4IVARBPROC) (GLint location, GLsizei count, const GLint *value);\ntypedef void (APIENTRYP PFNGLUNIFORMMATRIX2FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLUNIFORMMATRIX3FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);\ntypedef void (APIENTRYP PFNGLGETOBJECTPARAMETERFVARBPROC) (GLhandleARB obj, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETOBJECTPARAMETERIVARBPROC) (GLhandleARB obj, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETINFOLOGARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *infoLog);\ntypedef void (APIENTRYP PFNGLGETATTACHEDOBJECTSARBPROC) (GLhandleARB containerObj, GLsizei maxCount, GLsizei *count, GLhandleARB *obj);\ntypedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB *name);\ntypedef void (APIENTRYP PFNGLGETACTIVEUNIFORMARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name);\ntypedef void (APIENTRYP PFNGLGETUNIFORMFVARBPROC) (GLhandleARB programObj, GLint location, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETUNIFORMIVARBPROC) (GLhandleARB programObj, GLint location, GLint *params);\ntypedef void (APIENTRYP PFNGLGETSHADERSOURCEARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *source);\n#endif\n\n#ifndef GL_ARB_vertex_shader\n#define GL_ARB_vertex_shader 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glBindAttribLocationARB (GLhandleARB, GLuint, const GLcharARB *);\nGLAPI void APIENTRY glGetActiveAttribARB (GLhandleARB, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLcharARB *);\nGLAPI GLint APIENTRY glGetAttribLocationARB (GLhandleARB, const GLcharARB *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLBINDATTRIBLOCATIONARBPROC) (GLhandleARB programObj, GLuint index, const GLcharARB *name);\ntypedef void (APIENTRYP PFNGLGETACTIVEATTRIBARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name);\ntypedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB *name);\n#endif\n\n#ifndef GL_ARB_fragment_shader\n#define GL_ARB_fragment_shader 1\n#endif\n\n#ifndef GL_ARB_shading_language_100\n#define GL_ARB_shading_language_100 1\n#endif\n\n#ifndef GL_ARB_texture_non_power_of_two\n#define GL_ARB_texture_non_power_of_two 1\n#endif\n\n#ifndef GL_ARB_point_sprite\n#define GL_ARB_point_sprite 1\n#endif\n\n#ifndef GL_ARB_fragment_program_shadow\n#define GL_ARB_fragment_program_shadow 1\n#endif\n\n#ifndef GL_ARB_draw_buffers\n#define GL_ARB_draw_buffers 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glDrawBuffersARB (GLsizei, const GLenum *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLDRAWBUFFERSARBPROC) (GLsizei n, const GLenum *bufs);\n#endif\n\n#ifndef GL_ARB_texture_rectangle\n#define GL_ARB_texture_rectangle 1\n#endif\n\n#ifndef GL_ARB_color_buffer_float\n#define GL_ARB_color_buffer_float 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glClampColorARB (GLenum, GLenum);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLCLAMPCOLORARBPROC) (GLenum target, GLenum clamp);\n#endif\n\n#ifndef GL_ARB_half_float_pixel\n#define GL_ARB_half_float_pixel 1\n#endif\n\n#ifndef GL_ARB_texture_float\n#define GL_ARB_texture_float 1\n#endif\n\n#ifndef GL_ARB_pixel_buffer_object\n#define GL_ARB_pixel_buffer_object 1\n#endif\n\n#ifndef GL_EXT_abgr\n#define GL_EXT_abgr 1\n#endif\n\n#ifndef GL_EXT_blend_color\n#define GL_EXT_blend_color 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glBlendColorEXT (GLclampf, GLclampf, GLclampf, GLclampf);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLBLENDCOLOREXTPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);\n#endif\n\n#ifndef GL_EXT_polygon_offset\n#define GL_EXT_polygon_offset 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glPolygonOffsetEXT (GLfloat, GLfloat);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLPOLYGONOFFSETEXTPROC) (GLfloat factor, GLfloat bias);\n#endif\n\n#ifndef GL_EXT_texture\n#define GL_EXT_texture 1\n#endif\n\n#ifndef GL_EXT_texture3D\n#define GL_EXT_texture3D 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glTexImage3DEXT (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *);\nGLAPI void APIENTRY glTexSubImage3DEXT (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLTEXIMAGE3DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);\ntypedef void (APIENTRYP PFNGLTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);\n#endif\n\n#ifndef GL_SGIS_texture_filter4\n#define GL_SGIS_texture_filter4 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glGetTexFilterFuncSGIS (GLenum, GLenum, GLfloat *);\nGLAPI void APIENTRY glTexFilterFuncSGIS (GLenum, GLenum, GLsizei, const GLfloat *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLGETTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLfloat *weights);\ntypedef void (APIENTRYP PFNGLTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLsizei n, const GLfloat *weights);\n#endif\n\n#ifndef GL_EXT_subtexture\n#define GL_EXT_subtexture 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glTexSubImage1DEXT (GLenum, GLint, GLint, GLsizei, GLenum, GLenum, const GLvoid *);\nGLAPI void APIENTRY glTexSubImage2DEXT (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);\ntypedef void (APIENTRYP PFNGLTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);\n#endif\n\n#ifndef GL_EXT_copy_texture\n#define GL_EXT_copy_texture 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glCopyTexImage1DEXT (GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLint);\nGLAPI void APIENTRY glCopyTexImage2DEXT (GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLsizei, GLint);\nGLAPI void APIENTRY glCopyTexSubImage1DEXT (GLenum, GLint, GLint, GLint, GLint, GLsizei);\nGLAPI void APIENTRY glCopyTexSubImage2DEXT (GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei);\nGLAPI void APIENTRY glCopyTexSubImage3DEXT (GLenum, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLCOPYTEXIMAGE1DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);\ntypedef void (APIENTRYP PFNGLCOPYTEXIMAGE2DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);\ntypedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);\ntypedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);\ntypedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);\n#endif\n\n#ifndef GL_EXT_histogram\n#define GL_EXT_histogram 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glGetHistogramEXT (GLenum, GLboolean, GLenum, GLenum, GLvoid *);\nGLAPI void APIENTRY glGetHistogramParameterfvEXT (GLenum, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetHistogramParameterivEXT (GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glGetMinmaxEXT (GLenum, GLboolean, GLenum, GLenum, GLvoid *);\nGLAPI void APIENTRY glGetMinmaxParameterfvEXT (GLenum, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetMinmaxParameterivEXT (GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glHistogramEXT (GLenum, GLsizei, GLenum, GLboolean);\nGLAPI void APIENTRY glMinmaxEXT (GLenum, GLenum, GLboolean);\nGLAPI void APIENTRY glResetHistogramEXT (GLenum);\nGLAPI void APIENTRY glResetMinmaxEXT (GLenum);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLGETHISTOGRAMEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values);\ntypedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETMINMAXEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values);\ntypedef void (APIENTRYP PFNGLGETMINMAXPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETMINMAXPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLHISTOGRAMEXTPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink);\ntypedef void (APIENTRYP PFNGLMINMAXEXTPROC) (GLenum target, GLenum internalformat, GLboolean sink);\ntypedef void (APIENTRYP PFNGLRESETHISTOGRAMEXTPROC) (GLenum target);\ntypedef void (APIENTRYP PFNGLRESETMINMAXEXTPROC) (GLenum target);\n#endif\n\n#ifndef GL_EXT_convolution\n#define GL_EXT_convolution 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glConvolutionFilter1DEXT (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *);\nGLAPI void APIENTRY glConvolutionFilter2DEXT (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);\nGLAPI void APIENTRY glConvolutionParameterfEXT (GLenum, GLenum, GLfloat);\nGLAPI void APIENTRY glConvolutionParameterfvEXT (GLenum, GLenum, const GLfloat *);\nGLAPI void APIENTRY glConvolutionParameteriEXT (GLenum, GLenum, GLint);\nGLAPI void APIENTRY glConvolutionParameterivEXT (GLenum, GLenum, const GLint *);\nGLAPI void APIENTRY glCopyConvolutionFilter1DEXT (GLenum, GLenum, GLint, GLint, GLsizei);\nGLAPI void APIENTRY glCopyConvolutionFilter2DEXT (GLenum, GLenum, GLint, GLint, GLsizei, GLsizei);\nGLAPI void APIENTRY glGetConvolutionFilterEXT (GLenum, GLenum, GLenum, GLvoid *);\nGLAPI void APIENTRY glGetConvolutionParameterfvEXT (GLenum, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetConvolutionParameterivEXT (GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glGetSeparableFilterEXT (GLenum, GLenum, GLenum, GLvoid *, GLvoid *, GLvoid *);\nGLAPI void APIENTRY glSeparableFilter2DEXT (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *, const GLvoid *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image);\ntypedef void (APIENTRYP PFNGLCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image);\ntypedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFEXTPROC) (GLenum target, GLenum pname, GLfloat params);\ntypedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIEXTPROC) (GLenum target, GLenum pname, GLint params);\ntypedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint *params);\ntypedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);\ntypedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height);\ntypedef void (APIENTRYP PFNGLGETCONVOLUTIONFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *image);\ntypedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETSEPARABLEFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span);\ntypedef void (APIENTRYP PFNGLSEPARABLEFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column);\n#endif\n\n#ifndef GL_SGI_color_matrix\n#define GL_SGI_color_matrix 1\n#endif\n\n#ifndef GL_SGI_color_table\n#define GL_SGI_color_table 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glColorTableSGI (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *);\nGLAPI void APIENTRY glColorTableParameterfvSGI (GLenum, GLenum, const GLfloat *);\nGLAPI void APIENTRY glColorTableParameterivSGI (GLenum, GLenum, const GLint *);\nGLAPI void APIENTRY glCopyColorTableSGI (GLenum, GLenum, GLint, GLint, GLsizei);\nGLAPI void APIENTRY glGetColorTableSGI (GLenum, GLenum, GLenum, GLvoid *);\nGLAPI void APIENTRY glGetColorTableParameterfvSGI (GLenum, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetColorTableParameterivSGI (GLenum, GLenum, GLint *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table);\ntypedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, const GLint *params);\ntypedef void (APIENTRYP PFNGLCOPYCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);\ntypedef void (APIENTRYP PFNGLGETCOLORTABLESGIPROC) (GLenum target, GLenum format, GLenum type, GLvoid *table);\ntypedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, GLint *params);\n#endif\n\n#ifndef GL_SGIX_pixel_texture\n#define GL_SGIX_pixel_texture 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glPixelTexGenSGIX (GLenum);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLPIXELTEXGENSGIXPROC) (GLenum mode);\n#endif\n\n#ifndef GL_SGIS_pixel_texture\n#define GL_SGIS_pixel_texture 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glPixelTexGenParameteriSGIS (GLenum, GLint);\nGLAPI void APIENTRY glPixelTexGenParameterivSGIS (GLenum, const GLint *);\nGLAPI void APIENTRY glPixelTexGenParameterfSGIS (GLenum, GLfloat);\nGLAPI void APIENTRY glPixelTexGenParameterfvSGIS (GLenum, const GLfloat *);\nGLAPI void APIENTRY glGetPixelTexGenParameterivSGIS (GLenum, GLint *);\nGLAPI void APIENTRY glGetPixelTexGenParameterfvSGIS (GLenum, GLfloat *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERISGISPROC) (GLenum pname, GLint param);\ntypedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERIVSGISPROC) (GLenum pname, const GLint *params);\ntypedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERFSGISPROC) (GLenum pname, GLfloat param);\ntypedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERFVSGISPROC) (GLenum pname, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETPIXELTEXGENPARAMETERIVSGISPROC) (GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETPIXELTEXGENPARAMETERFVSGISPROC) (GLenum pname, GLfloat *params);\n#endif\n\n#ifndef GL_SGIS_texture4D\n#define GL_SGIS_texture4D 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glTexImage4DSGIS (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *);\nGLAPI void APIENTRY glTexSubImage4DSGIS (GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLTEXIMAGE4DSGISPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLint border, GLenum format, GLenum type, const GLvoid *pixels);\ntypedef void (APIENTRYP PFNGLTEXSUBIMAGE4DSGISPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint woffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLenum format, GLenum type, const GLvoid *pixels);\n#endif\n\n#ifndef GL_SGI_texture_color_table\n#define GL_SGI_texture_color_table 1\n#endif\n\n#ifndef GL_EXT_cmyka\n#define GL_EXT_cmyka 1\n#endif\n\n#ifndef GL_EXT_texture_object\n#define GL_EXT_texture_object 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI GLboolean APIENTRY glAreTexturesResidentEXT (GLsizei, const GLuint *, GLboolean *);\nGLAPI void APIENTRY glBindTextureEXT (GLenum, GLuint);\nGLAPI void APIENTRY glDeleteTexturesEXT (GLsizei, const GLuint *);\nGLAPI void APIENTRY glGenTexturesEXT (GLsizei, GLuint *);\nGLAPI GLboolean APIENTRY glIsTextureEXT (GLuint);\nGLAPI void APIENTRY glPrioritizeTexturesEXT (GLsizei, const GLuint *, const GLclampf *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef GLboolean (APIENTRYP PFNGLARETEXTURESRESIDENTEXTPROC) (GLsizei n, const GLuint *textures, GLboolean *residences);\ntypedef void (APIENTRYP PFNGLBINDTEXTUREEXTPROC) (GLenum target, GLuint texture);\ntypedef void (APIENTRYP PFNGLDELETETEXTURESEXTPROC) (GLsizei n, const GLuint *textures);\ntypedef void (APIENTRYP PFNGLGENTEXTURESEXTPROC) (GLsizei n, GLuint *textures);\ntypedef GLboolean (APIENTRYP PFNGLISTEXTUREEXTPROC) (GLuint texture);\ntypedef void (APIENTRYP PFNGLPRIORITIZETEXTURESEXTPROC) (GLsizei n, const GLuint *textures, const GLclampf *priorities);\n#endif\n\n#ifndef GL_SGIS_detail_texture\n#define GL_SGIS_detail_texture 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glDetailTexFuncSGIS (GLenum, GLsizei, const GLfloat *);\nGLAPI void APIENTRY glGetDetailTexFuncSGIS (GLenum, GLfloat *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLDETAILTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat *points);\ntypedef void (APIENTRYP PFNGLGETDETAILTEXFUNCSGISPROC) (GLenum target, GLfloat *points);\n#endif\n\n#ifndef GL_SGIS_sharpen_texture\n#define GL_SGIS_sharpen_texture 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glSharpenTexFuncSGIS (GLenum, GLsizei, const GLfloat *);\nGLAPI void APIENTRY glGetSharpenTexFuncSGIS (GLenum, GLfloat *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLSHARPENTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat *points);\ntypedef void (APIENTRYP PFNGLGETSHARPENTEXFUNCSGISPROC) (GLenum target, GLfloat *points);\n#endif\n\n#ifndef GL_EXT_packed_pixels\n#define GL_EXT_packed_pixels 1\n#endif\n\n#ifndef GL_SGIS_texture_lod\n#define GL_SGIS_texture_lod 1\n#endif\n\n#ifndef GL_SGIS_multisample\n#define GL_SGIS_multisample 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glSampleMaskSGIS (GLclampf, GLboolean);\nGLAPI void APIENTRY glSamplePatternSGIS (GLenum);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLSAMPLEMASKSGISPROC) (GLclampf value, GLboolean invert);\ntypedef void (APIENTRYP PFNGLSAMPLEPATTERNSGISPROC) (GLenum pattern);\n#endif\n\n#ifndef GL_EXT_rescale_normal\n#define GL_EXT_rescale_normal 1\n#endif\n\n#ifndef GL_EXT_vertex_array\n#define GL_EXT_vertex_array 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glArrayElementEXT (GLint);\nGLAPI void APIENTRY glColorPointerEXT (GLint, GLenum, GLsizei, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glDrawArraysEXT (GLenum, GLint, GLsizei);\nGLAPI void APIENTRY glEdgeFlagPointerEXT (GLsizei, GLsizei, const GLboolean *);\nGLAPI void APIENTRY glGetPointervEXT (GLenum, GLvoid* *);\nGLAPI void APIENTRY glIndexPointerEXT (GLenum, GLsizei, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glNormalPointerEXT (GLenum, GLsizei, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glTexCoordPointerEXT (GLint, GLenum, GLsizei, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glVertexPointerEXT (GLint, GLenum, GLsizei, GLsizei, const GLvoid *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLARRAYELEMENTEXTPROC) (GLint i);\ntypedef void (APIENTRYP PFNGLCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);\ntypedef void (APIENTRYP PFNGLDRAWARRAYSEXTPROC) (GLenum mode, GLint first, GLsizei count);\ntypedef void (APIENTRYP PFNGLEDGEFLAGPOINTEREXTPROC) (GLsizei stride, GLsizei count, const GLboolean *pointer);\ntypedef void (APIENTRYP PFNGLGETPOINTERVEXTPROC) (GLenum pname, GLvoid* *params);\ntypedef void (APIENTRYP PFNGLINDEXPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);\ntypedef void (APIENTRYP PFNGLNORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);\ntypedef void (APIENTRYP PFNGLTEXCOORDPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);\ntypedef void (APIENTRYP PFNGLVERTEXPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);\n#endif\n\n#ifndef GL_EXT_misc_attribute\n#define GL_EXT_misc_attribute 1\n#endif\n\n#ifndef GL_SGIS_generate_mipmap\n#define GL_SGIS_generate_mipmap 1\n#endif\n\n#ifndef GL_SGIX_clipmap\n#define GL_SGIX_clipmap 1\n#endif\n\n#ifndef GL_SGIX_shadow\n#define GL_SGIX_shadow 1\n#endif\n\n#ifndef GL_SGIS_texture_edge_clamp\n#define GL_SGIS_texture_edge_clamp 1\n#endif\n\n#ifndef GL_SGIS_texture_border_clamp\n#define GL_SGIS_texture_border_clamp 1\n#endif\n\n#ifndef GL_EXT_blend_minmax\n#define GL_EXT_blend_minmax 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glBlendEquationEXT (GLenum);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLBLENDEQUATIONEXTPROC) (GLenum mode);\n#endif\n\n#ifndef GL_EXT_blend_subtract\n#define GL_EXT_blend_subtract 1\n#endif\n\n#ifndef GL_EXT_blend_logic_op\n#define GL_EXT_blend_logic_op 1\n#endif\n\n#ifndef GL_SGIX_interlace\n#define GL_SGIX_interlace 1\n#endif\n\n#ifndef GL_SGIX_pixel_tiles\n#define GL_SGIX_pixel_tiles 1\n#endif\n\n#ifndef GL_SGIX_texture_select\n#define GL_SGIX_texture_select 1\n#endif\n\n#ifndef GL_SGIX_sprite\n#define GL_SGIX_sprite 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glSpriteParameterfSGIX (GLenum, GLfloat);\nGLAPI void APIENTRY glSpriteParameterfvSGIX (GLenum, const GLfloat *);\nGLAPI void APIENTRY glSpriteParameteriSGIX (GLenum, GLint);\nGLAPI void APIENTRY glSpriteParameterivSGIX (GLenum, const GLint *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLSPRITEPARAMETERFSGIXPROC) (GLenum pname, GLfloat param);\ntypedef void (APIENTRYP PFNGLSPRITEPARAMETERFVSGIXPROC) (GLenum pname, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLSPRITEPARAMETERISGIXPROC) (GLenum pname, GLint param);\ntypedef void (APIENTRYP PFNGLSPRITEPARAMETERIVSGIXPROC) (GLenum pname, const GLint *params);\n#endif\n\n#ifndef GL_SGIX_texture_multi_buffer\n#define GL_SGIX_texture_multi_buffer 1\n#endif\n\n#ifndef GL_EXT_point_parameters\n#define GL_EXT_point_parameters 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glPointParameterfEXT (GLenum, GLfloat);\nGLAPI void APIENTRY glPointParameterfvEXT (GLenum, const GLfloat *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLPOINTPARAMETERFEXTPROC) (GLenum pname, GLfloat param);\ntypedef void (APIENTRYP PFNGLPOINTPARAMETERFVEXTPROC) (GLenum pname, const GLfloat *params);\n#endif\n\n#ifndef GL_SGIS_point_parameters\n#define GL_SGIS_point_parameters 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glPointParameterfSGIS (GLenum, GLfloat);\nGLAPI void APIENTRY glPointParameterfvSGIS (GLenum, const GLfloat *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLPOINTPARAMETERFSGISPROC) (GLenum pname, GLfloat param);\ntypedef void (APIENTRYP PFNGLPOINTPARAMETERFVSGISPROC) (GLenum pname, const GLfloat *params);\n#endif\n\n#ifndef GL_SGIX_instruments\n#define GL_SGIX_instruments 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI GLint APIENTRY glGetInstrumentsSGIX (void);\nGLAPI void APIENTRY glInstrumentsBufferSGIX (GLsizei, GLint *);\nGLAPI GLint APIENTRY glPollInstrumentsSGIX (GLint *);\nGLAPI void APIENTRY glReadInstrumentsSGIX (GLint);\nGLAPI void APIENTRY glStartInstrumentsSGIX (void);\nGLAPI void APIENTRY glStopInstrumentsSGIX (GLint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef GLint (APIENTRYP PFNGLGETINSTRUMENTSSGIXPROC) (void);\ntypedef void (APIENTRYP PFNGLINSTRUMENTSBUFFERSGIXPROC) (GLsizei size, GLint *buffer);\ntypedef GLint (APIENTRYP PFNGLPOLLINSTRUMENTSSGIXPROC) (GLint *marker_p);\ntypedef void (APIENTRYP PFNGLREADINSTRUMENTSSGIXPROC) (GLint marker);\ntypedef void (APIENTRYP PFNGLSTARTINSTRUMENTSSGIXPROC) (void);\ntypedef void (APIENTRYP PFNGLSTOPINSTRUMENTSSGIXPROC) (GLint marker);\n#endif\n\n#ifndef GL_SGIX_texture_scale_bias\n#define GL_SGIX_texture_scale_bias 1\n#endif\n\n#ifndef GL_SGIX_framezoom\n#define GL_SGIX_framezoom 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glFrameZoomSGIX (GLint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLFRAMEZOOMSGIXPROC) (GLint factor);\n#endif\n\n#ifndef GL_SGIX_tag_sample_buffer\n#define GL_SGIX_tag_sample_buffer 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glTagSampleBufferSGIX (void);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLTAGSAMPLEBUFFERSGIXPROC) (void);\n#endif\n\n#ifndef GL_SGIX_polynomial_ffd\n#define GL_SGIX_polynomial_ffd 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glDeformationMap3dSGIX (GLenum, GLdouble, GLdouble, GLint, GLint, GLdouble, GLdouble, GLint, GLint, GLdouble, GLdouble, GLint, GLint, const GLdouble *);\nGLAPI void APIENTRY glDeformationMap3fSGIX (GLenum, GLfloat, GLfloat, GLint, GLint, GLfloat, GLfloat, GLint, GLint, GLfloat, GLfloat, GLint, GLint, const GLfloat *);\nGLAPI void APIENTRY glDeformSGIX (GLbitfield);\nGLAPI void APIENTRY glLoadIdentityDeformationMapSGIX (GLbitfield);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLDEFORMATIONMAP3DSGIXPROC) (GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, GLdouble w1, GLdouble w2, GLint wstride, GLint worder, const GLdouble *points);\ntypedef void (APIENTRYP PFNGLDEFORMATIONMAP3FSGIXPROC) (GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, GLfloat w1, GLfloat w2, GLint wstride, GLint worder, const GLfloat *points);\ntypedef void (APIENTRYP PFNGLDEFORMSGIXPROC) (GLbitfield mask);\ntypedef void (APIENTRYP PFNGLLOADIDENTITYDEFORMATIONMAPSGIXPROC) (GLbitfield mask);\n#endif\n\n#ifndef GL_SGIX_reference_plane\n#define GL_SGIX_reference_plane 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glReferencePlaneSGIX (const GLdouble *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLREFERENCEPLANESGIXPROC) (const GLdouble *equation);\n#endif\n\n#ifndef GL_SGIX_flush_raster\n#define GL_SGIX_flush_raster 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glFlushRasterSGIX (void);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLFLUSHRASTERSGIXPROC) (void);\n#endif\n\n#ifndef GL_SGIX_depth_texture\n#define GL_SGIX_depth_texture 1\n#endif\n\n#ifndef GL_SGIS_fog_function\n#define GL_SGIS_fog_function 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glFogFuncSGIS (GLsizei, const GLfloat *);\nGLAPI void APIENTRY glGetFogFuncSGIS (GLfloat *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLFOGFUNCSGISPROC) (GLsizei n, const GLfloat *points);\ntypedef void (APIENTRYP PFNGLGETFOGFUNCSGISPROC) (GLfloat *points);\n#endif\n\n#ifndef GL_SGIX_fog_offset\n#define GL_SGIX_fog_offset 1\n#endif\n\n#ifndef GL_HP_image_transform\n#define GL_HP_image_transform 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glImageTransformParameteriHP (GLenum, GLenum, GLint);\nGLAPI void APIENTRY glImageTransformParameterfHP (GLenum, GLenum, GLfloat);\nGLAPI void APIENTRY glImageTransformParameterivHP (GLenum, GLenum, const GLint *);\nGLAPI void APIENTRY glImageTransformParameterfvHP (GLenum, GLenum, const GLfloat *);\nGLAPI void APIENTRY glGetImageTransformParameterivHP (GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glGetImageTransformParameterfvHP (GLenum, GLenum, GLfloat *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERIHPPROC) (GLenum target, GLenum pname, GLint param);\ntypedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERFHPPROC) (GLenum target, GLenum pname, GLfloat param);\ntypedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, const GLint *params);\ntypedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, GLfloat *params);\n#endif\n\n#ifndef GL_HP_convolution_border_modes\n#define GL_HP_convolution_border_modes 1\n#endif\n\n#ifndef GL_SGIX_texture_add_env\n#define GL_SGIX_texture_add_env 1\n#endif\n\n#ifndef GL_EXT_color_subtable\n#define GL_EXT_color_subtable 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glColorSubTableEXT (GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);\nGLAPI void APIENTRY glCopyColorSubTableEXT (GLenum, GLsizei, GLint, GLint, GLsizei);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data);\ntypedef void (APIENTRYP PFNGLCOPYCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width);\n#endif\n\n#ifndef GL_PGI_vertex_hints\n#define GL_PGI_vertex_hints 1\n#endif\n\n#ifndef GL_PGI_misc_hints\n#define GL_PGI_misc_hints 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glHintPGI (GLenum, GLint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLHINTPGIPROC) (GLenum target, GLint mode);\n#endif\n\n#ifndef GL_EXT_paletted_texture\n#define GL_EXT_paletted_texture 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glColorTableEXT (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *);\nGLAPI void APIENTRY glGetColorTableEXT (GLenum, GLenum, GLenum, GLvoid *);\nGLAPI void APIENTRY glGetColorTableParameterivEXT (GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glGetColorTableParameterfvEXT (GLenum, GLenum, GLfloat *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid *table);\ntypedef void (APIENTRYP PFNGLGETCOLORTABLEEXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *data);\ntypedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params);\n#endif\n\n#ifndef GL_EXT_clip_volume_hint\n#define GL_EXT_clip_volume_hint 1\n#endif\n\n#ifndef GL_SGIX_list_priority\n#define GL_SGIX_list_priority 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glGetListParameterfvSGIX (GLuint, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetListParameterivSGIX (GLuint, GLenum, GLint *);\nGLAPI void APIENTRY glListParameterfSGIX (GLuint, GLenum, GLfloat);\nGLAPI void APIENTRY glListParameterfvSGIX (GLuint, GLenum, const GLfloat *);\nGLAPI void APIENTRY glListParameteriSGIX (GLuint, GLenum, GLint);\nGLAPI void APIENTRY glListParameterivSGIX (GLuint, GLenum, const GLint *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLGETLISTPARAMETERFVSGIXPROC) (GLuint list, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETLISTPARAMETERIVSGIXPROC) (GLuint list, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLLISTPARAMETERFSGIXPROC) (GLuint list, GLenum pname, GLfloat param);\ntypedef void (APIENTRYP PFNGLLISTPARAMETERFVSGIXPROC) (GLuint list, GLenum pname, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLLISTPARAMETERISGIXPROC) (GLuint list, GLenum pname, GLint param);\ntypedef void (APIENTRYP PFNGLLISTPARAMETERIVSGIXPROC) (GLuint list, GLenum pname, const GLint *params);\n#endif\n\n#ifndef GL_SGIX_ir_instrument1\n#define GL_SGIX_ir_instrument1 1\n#endif\n\n#ifndef GL_SGIX_calligraphic_fragment\n#define GL_SGIX_calligraphic_fragment 1\n#endif\n\n#ifndef GL_SGIX_texture_lod_bias\n#define GL_SGIX_texture_lod_bias 1\n#endif\n\n#ifndef GL_SGIX_shadow_ambient\n#define GL_SGIX_shadow_ambient 1\n#endif\n\n#ifndef GL_EXT_index_texture\n#define GL_EXT_index_texture 1\n#endif\n\n#ifndef GL_EXT_index_material\n#define GL_EXT_index_material 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glIndexMaterialEXT (GLenum, GLenum);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLINDEXMATERIALEXTPROC) (GLenum face, GLenum mode);\n#endif\n\n#ifndef GL_EXT_index_func\n#define GL_EXT_index_func 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glIndexFuncEXT (GLenum, GLclampf);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLINDEXFUNCEXTPROC) (GLenum func, GLclampf ref);\n#endif\n\n#ifndef GL_EXT_index_array_formats\n#define GL_EXT_index_array_formats 1\n#endif\n\n#ifndef GL_EXT_compiled_vertex_array\n#define GL_EXT_compiled_vertex_array 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glLockArraysEXT (GLint, GLsizei);\nGLAPI void APIENTRY glUnlockArraysEXT (void);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLLOCKARRAYSEXTPROC) (GLint first, GLsizei count);\ntypedef void (APIENTRYP PFNGLUNLOCKARRAYSEXTPROC) (void);\n#endif\n\n#ifndef GL_EXT_cull_vertex\n#define GL_EXT_cull_vertex 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glCullParameterdvEXT (GLenum, GLdouble *);\nGLAPI void APIENTRY glCullParameterfvEXT (GLenum, GLfloat *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLCULLPARAMETERDVEXTPROC) (GLenum pname, GLdouble *params);\ntypedef void (APIENTRYP PFNGLCULLPARAMETERFVEXTPROC) (GLenum pname, GLfloat *params);\n#endif\n\n#ifndef GL_SGIX_ycrcb\n#define GL_SGIX_ycrcb 1\n#endif\n\n#ifndef GL_SGIX_fragment_lighting\n#define GL_SGIX_fragment_lighting 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glFragmentColorMaterialSGIX (GLenum, GLenum);\nGLAPI void APIENTRY glFragmentLightfSGIX (GLenum, GLenum, GLfloat);\nGLAPI void APIENTRY glFragmentLightfvSGIX (GLenum, GLenum, const GLfloat *);\nGLAPI void APIENTRY glFragmentLightiSGIX (GLenum, GLenum, GLint);\nGLAPI void APIENTRY glFragmentLightivSGIX (GLenum, GLenum, const GLint *);\nGLAPI void APIENTRY glFragmentLightModelfSGIX (GLenum, GLfloat);\nGLAPI void APIENTRY glFragmentLightModelfvSGIX (GLenum, const GLfloat *);\nGLAPI void APIENTRY glFragmentLightModeliSGIX (GLenum, GLint);\nGLAPI void APIENTRY glFragmentLightModelivSGIX (GLenum, const GLint *);\nGLAPI void APIENTRY glFragmentMaterialfSGIX (GLenum, GLenum, GLfloat);\nGLAPI void APIENTRY glFragmentMaterialfvSGIX (GLenum, GLenum, const GLfloat *);\nGLAPI void APIENTRY glFragmentMaterialiSGIX (GLenum, GLenum, GLint);\nGLAPI void APIENTRY glFragmentMaterialivSGIX (GLenum, GLenum, const GLint *);\nGLAPI void APIENTRY glGetFragmentLightfvSGIX (GLenum, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetFragmentLightivSGIX (GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glGetFragmentMaterialfvSGIX (GLenum, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetFragmentMaterialivSGIX (GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glLightEnviSGIX (GLenum, GLint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLFRAGMENTCOLORMATERIALSGIXPROC) (GLenum face, GLenum mode);\ntypedef void (APIENTRYP PFNGLFRAGMENTLIGHTFSGIXPROC) (GLenum light, GLenum pname, GLfloat param);\ntypedef void (APIENTRYP PFNGLFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum pname, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLFRAGMENTLIGHTISGIXPROC) (GLenum light, GLenum pname, GLint param);\ntypedef void (APIENTRYP PFNGLFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum pname, const GLint *params);\ntypedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELFSGIXPROC) (GLenum pname, GLfloat param);\ntypedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELFVSGIXPROC) (GLenum pname, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELISGIXPROC) (GLenum pname, GLint param);\ntypedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELIVSGIXPROC) (GLenum pname, const GLint *params);\ntypedef void (APIENTRYP PFNGLFRAGMENTMATERIALFSGIXPROC) (GLenum face, GLenum pname, GLfloat param);\ntypedef void (APIENTRYP PFNGLFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLFRAGMENTMATERIALISGIXPROC) (GLenum face, GLenum pname, GLint param);\ntypedef void (APIENTRYP PFNGLFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, const GLint *params);\ntypedef void (APIENTRYP PFNGLGETFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLLIGHTENVISGIXPROC) (GLenum pname, GLint param);\n#endif\n\n#ifndef GL_IBM_rasterpos_clip\n#define GL_IBM_rasterpos_clip 1\n#endif\n\n#ifndef GL_HP_texture_lighting\n#define GL_HP_texture_lighting 1\n#endif\n\n#ifndef GL_EXT_draw_range_elements\n#define GL_EXT_draw_range_elements 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glDrawRangeElementsEXT (GLenum, GLuint, GLuint, GLsizei, GLenum, const GLvoid *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSEXTPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices);\n#endif\n\n#ifndef GL_WIN_phong_shading\n#define GL_WIN_phong_shading 1\n#endif\n\n#ifndef GL_WIN_specular_fog\n#define GL_WIN_specular_fog 1\n#endif\n\n#ifndef GL_EXT_light_texture\n#define GL_EXT_light_texture 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glApplyTextureEXT (GLenum);\nGLAPI void APIENTRY glTextureLightEXT (GLenum);\nGLAPI void APIENTRY glTextureMaterialEXT (GLenum, GLenum);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLAPPLYTEXTUREEXTPROC) (GLenum mode);\ntypedef void (APIENTRYP PFNGLTEXTURELIGHTEXTPROC) (GLenum pname);\ntypedef void (APIENTRYP PFNGLTEXTUREMATERIALEXTPROC) (GLenum face, GLenum mode);\n#endif\n\n#ifndef GL_SGIX_blend_alpha_minmax\n#define GL_SGIX_blend_alpha_minmax 1\n#endif\n\n#ifndef GL_EXT_bgra\n#define GL_EXT_bgra 1\n#endif\n\n#ifndef GL_SGIX_async\n#define GL_SGIX_async 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glAsyncMarkerSGIX (GLuint);\nGLAPI GLint APIENTRY glFinishAsyncSGIX (GLuint *);\nGLAPI GLint APIENTRY glPollAsyncSGIX (GLuint *);\nGLAPI GLuint APIENTRY glGenAsyncMarkersSGIX (GLsizei);\nGLAPI void APIENTRY glDeleteAsyncMarkersSGIX (GLuint, GLsizei);\nGLAPI GLboolean APIENTRY glIsAsyncMarkerSGIX (GLuint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLASYNCMARKERSGIXPROC) (GLuint marker);\ntypedef GLint (APIENTRYP PFNGLFINISHASYNCSGIXPROC) (GLuint *markerp);\ntypedef GLint (APIENTRYP PFNGLPOLLASYNCSGIXPROC) (GLuint *markerp);\ntypedef GLuint (APIENTRYP PFNGLGENASYNCMARKERSSGIXPROC) (GLsizei range);\ntypedef void (APIENTRYP PFNGLDELETEASYNCMARKERSSGIXPROC) (GLuint marker, GLsizei range);\ntypedef GLboolean (APIENTRYP PFNGLISASYNCMARKERSGIXPROC) (GLuint marker);\n#endif\n\n#ifndef GL_SGIX_async_pixel\n#define GL_SGIX_async_pixel 1\n#endif\n\n#ifndef GL_SGIX_async_histogram\n#define GL_SGIX_async_histogram 1\n#endif\n\n#ifndef GL_INTEL_parallel_arrays\n#define GL_INTEL_parallel_arrays 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glVertexPointervINTEL (GLint, GLenum, const GLvoid* *);\nGLAPI void APIENTRY glNormalPointervINTEL (GLenum, const GLvoid* *);\nGLAPI void APIENTRY glColorPointervINTEL (GLint, GLenum, const GLvoid* *);\nGLAPI void APIENTRY glTexCoordPointervINTEL (GLint, GLenum, const GLvoid* *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLVERTEXPOINTERVINTELPROC) (GLint size, GLenum type, const GLvoid* *pointer);\ntypedef void (APIENTRYP PFNGLNORMALPOINTERVINTELPROC) (GLenum type, const GLvoid* *pointer);\ntypedef void (APIENTRYP PFNGLCOLORPOINTERVINTELPROC) (GLint size, GLenum type, const GLvoid* *pointer);\ntypedef void (APIENTRYP PFNGLTEXCOORDPOINTERVINTELPROC) (GLint size, GLenum type, const GLvoid* *pointer);\n#endif\n\n#ifndef GL_HP_occlusion_test\n#define GL_HP_occlusion_test 1\n#endif\n\n#ifndef GL_EXT_pixel_transform\n#define GL_EXT_pixel_transform 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glPixelTransformParameteriEXT (GLenum, GLenum, GLint);\nGLAPI void APIENTRY glPixelTransformParameterfEXT (GLenum, GLenum, GLfloat);\nGLAPI void APIENTRY glPixelTransformParameterivEXT (GLenum, GLenum, const GLint *);\nGLAPI void APIENTRY glPixelTransformParameterfvEXT (GLenum, GLenum, const GLfloat *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERIEXTPROC) (GLenum target, GLenum pname, GLint param);\ntypedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERFEXTPROC) (GLenum target, GLenum pname, GLfloat param);\ntypedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint *params);\ntypedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat *params);\n#endif\n\n#ifndef GL_EXT_pixel_transform_color_table\n#define GL_EXT_pixel_transform_color_table 1\n#endif\n\n#ifndef GL_EXT_shared_texture_palette\n#define GL_EXT_shared_texture_palette 1\n#endif\n\n#ifndef GL_EXT_separate_specular_color\n#define GL_EXT_separate_specular_color 1\n#endif\n\n#ifndef GL_EXT_secondary_color\n#define GL_EXT_secondary_color 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glSecondaryColor3bEXT (GLbyte, GLbyte, GLbyte);\nGLAPI void APIENTRY glSecondaryColor3bvEXT (const GLbyte *);\nGLAPI void APIENTRY glSecondaryColor3dEXT (GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glSecondaryColor3dvEXT (const GLdouble *);\nGLAPI void APIENTRY glSecondaryColor3fEXT (GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glSecondaryColor3fvEXT (const GLfloat *);\nGLAPI void APIENTRY glSecondaryColor3iEXT (GLint, GLint, GLint);\nGLAPI void APIENTRY glSecondaryColor3ivEXT (const GLint *);\nGLAPI void APIENTRY glSecondaryColor3sEXT (GLshort, GLshort, GLshort);\nGLAPI void APIENTRY glSecondaryColor3svEXT (const GLshort *);\nGLAPI void APIENTRY glSecondaryColor3ubEXT (GLubyte, GLubyte, GLubyte);\nGLAPI void APIENTRY glSecondaryColor3ubvEXT (const GLubyte *);\nGLAPI void APIENTRY glSecondaryColor3uiEXT (GLuint, GLuint, GLuint);\nGLAPI void APIENTRY glSecondaryColor3uivEXT (const GLuint *);\nGLAPI void APIENTRY glSecondaryColor3usEXT (GLushort, GLushort, GLushort);\nGLAPI void APIENTRY glSecondaryColor3usvEXT (const GLushort *);\nGLAPI void APIENTRY glSecondaryColorPointerEXT (GLint, GLenum, GLsizei, const GLvoid *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3BEXTPROC) (GLbyte red, GLbyte green, GLbyte blue);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3BVEXTPROC) (const GLbyte *v);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3DEXTPROC) (GLdouble red, GLdouble green, GLdouble blue);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3DVEXTPROC) (const GLdouble *v);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3FEXTPROC) (GLfloat red, GLfloat green, GLfloat blue);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3FVEXTPROC) (const GLfloat *v);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3IEXTPROC) (GLint red, GLint green, GLint blue);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3IVEXTPROC) (const GLint *v);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3SEXTPROC) (GLshort red, GLshort green, GLshort blue);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3SVEXTPROC) (const GLshort *v);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBEXTPROC) (GLubyte red, GLubyte green, GLubyte blue);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBVEXTPROC) (const GLubyte *v);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIEXTPROC) (GLuint red, GLuint green, GLuint blue);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIVEXTPROC) (const GLuint *v);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3USEXTPROC) (GLushort red, GLushort green, GLushort blue);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3USVEXTPROC) (const GLushort *v);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);\n#endif\n\n#ifndef GL_EXT_texture_perturb_normal\n#define GL_EXT_texture_perturb_normal 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glTextureNormalEXT (GLenum);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLTEXTURENORMALEXTPROC) (GLenum mode);\n#endif\n\n#ifndef GL_EXT_multi_draw_arrays\n#define GL_EXT_multi_draw_arrays 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glMultiDrawArraysEXT (GLenum, GLint *, GLsizei *, GLsizei);\nGLAPI void APIENTRY glMultiDrawElementsEXT (GLenum, const GLsizei *, GLenum, const GLvoid* *, GLsizei);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount);\ntypedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount);\n#endif\n\n#ifndef GL_EXT_fog_coord\n#define GL_EXT_fog_coord 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glFogCoordfEXT (GLfloat);\nGLAPI void APIENTRY glFogCoordfvEXT (const GLfloat *);\nGLAPI void APIENTRY glFogCoorddEXT (GLdouble);\nGLAPI void APIENTRY glFogCoorddvEXT (const GLdouble *);\nGLAPI void APIENTRY glFogCoordPointerEXT (GLenum, GLsizei, const GLvoid *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLFOGCOORDFEXTPROC) (GLfloat coord);\ntypedef void (APIENTRYP PFNGLFOGCOORDFVEXTPROC) (const GLfloat *coord);\ntypedef void (APIENTRYP PFNGLFOGCOORDDEXTPROC) (GLdouble coord);\ntypedef void (APIENTRYP PFNGLFOGCOORDDVEXTPROC) (const GLdouble *coord);\ntypedef void (APIENTRYP PFNGLFOGCOORDPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer);\n#endif\n\n#ifndef GL_REND_screen_coordinates\n#define GL_REND_screen_coordinates 1\n#endif\n\n#ifndef GL_EXT_coordinate_frame\n#define GL_EXT_coordinate_frame 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glTangent3bEXT (GLbyte, GLbyte, GLbyte);\nGLAPI void APIENTRY glTangent3bvEXT (const GLbyte *);\nGLAPI void APIENTRY glTangent3dEXT (GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glTangent3dvEXT (const GLdouble *);\nGLAPI void APIENTRY glTangent3fEXT (GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glTangent3fvEXT (const GLfloat *);\nGLAPI void APIENTRY glTangent3iEXT (GLint, GLint, GLint);\nGLAPI void APIENTRY glTangent3ivEXT (const GLint *);\nGLAPI void APIENTRY glTangent3sEXT (GLshort, GLshort, GLshort);\nGLAPI void APIENTRY glTangent3svEXT (const GLshort *);\nGLAPI void APIENTRY glBinormal3bEXT (GLbyte, GLbyte, GLbyte);\nGLAPI void APIENTRY glBinormal3bvEXT (const GLbyte *);\nGLAPI void APIENTRY glBinormal3dEXT (GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glBinormal3dvEXT (const GLdouble *);\nGLAPI void APIENTRY glBinormal3fEXT (GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glBinormal3fvEXT (const GLfloat *);\nGLAPI void APIENTRY glBinormal3iEXT (GLint, GLint, GLint);\nGLAPI void APIENTRY glBinormal3ivEXT (const GLint *);\nGLAPI void APIENTRY glBinormal3sEXT (GLshort, GLshort, GLshort);\nGLAPI void APIENTRY glBinormal3svEXT (const GLshort *);\nGLAPI void APIENTRY glTangentPointerEXT (GLenum, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glBinormalPointerEXT (GLenum, GLsizei, const GLvoid *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLTANGENT3BEXTPROC) (GLbyte tx, GLbyte ty, GLbyte tz);\ntypedef void (APIENTRYP PFNGLTANGENT3BVEXTPROC) (const GLbyte *v);\ntypedef void (APIENTRYP PFNGLTANGENT3DEXTPROC) (GLdouble tx, GLdouble ty, GLdouble tz);\ntypedef void (APIENTRYP PFNGLTANGENT3DVEXTPROC) (const GLdouble *v);\ntypedef void (APIENTRYP PFNGLTANGENT3FEXTPROC) (GLfloat tx, GLfloat ty, GLfloat tz);\ntypedef void (APIENTRYP PFNGLTANGENT3FVEXTPROC) (const GLfloat *v);\ntypedef void (APIENTRYP PFNGLTANGENT3IEXTPROC) (GLint tx, GLint ty, GLint tz);\ntypedef void (APIENTRYP PFNGLTANGENT3IVEXTPROC) (const GLint *v);\ntypedef void (APIENTRYP PFNGLTANGENT3SEXTPROC) (GLshort tx, GLshort ty, GLshort tz);\ntypedef void (APIENTRYP PFNGLTANGENT3SVEXTPROC) (const GLshort *v);\ntypedef void (APIENTRYP PFNGLBINORMAL3BEXTPROC) (GLbyte bx, GLbyte by, GLbyte bz);\ntypedef void (APIENTRYP PFNGLBINORMAL3BVEXTPROC) (const GLbyte *v);\ntypedef void (APIENTRYP PFNGLBINORMAL3DEXTPROC) (GLdouble bx, GLdouble by, GLdouble bz);\ntypedef void (APIENTRYP PFNGLBINORMAL3DVEXTPROC) (const GLdouble *v);\ntypedef void (APIENTRYP PFNGLBINORMAL3FEXTPROC) (GLfloat bx, GLfloat by, GLfloat bz);\ntypedef void (APIENTRYP PFNGLBINORMAL3FVEXTPROC) (const GLfloat *v);\ntypedef void (APIENTRYP PFNGLBINORMAL3IEXTPROC) (GLint bx, GLint by, GLint bz);\ntypedef void (APIENTRYP PFNGLBINORMAL3IVEXTPROC) (const GLint *v);\ntypedef void (APIENTRYP PFNGLBINORMAL3SEXTPROC) (GLshort bx, GLshort by, GLshort bz);\ntypedef void (APIENTRYP PFNGLBINORMAL3SVEXTPROC) (const GLshort *v);\ntypedef void (APIENTRYP PFNGLTANGENTPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer);\ntypedef void (APIENTRYP PFNGLBINORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer);\n#endif\n\n#ifndef GL_EXT_texture_env_combine\n#define GL_EXT_texture_env_combine 1\n#endif\n\n#ifndef GL_APPLE_specular_vector\n#define GL_APPLE_specular_vector 1\n#endif\n\n#ifndef GL_APPLE_transform_hint\n#define GL_APPLE_transform_hint 1\n#endif\n\n#ifndef GL_SGIX_fog_scale\n#define GL_SGIX_fog_scale 1\n#endif\n\n#ifndef GL_SUNX_constant_data\n#define GL_SUNX_constant_data 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glFinishTextureSUNX (void);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLFINISHTEXTURESUNXPROC) (void);\n#endif\n\n#ifndef GL_SUN_global_alpha\n#define GL_SUN_global_alpha 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glGlobalAlphaFactorbSUN (GLbyte);\nGLAPI void APIENTRY glGlobalAlphaFactorsSUN (GLshort);\nGLAPI void APIENTRY glGlobalAlphaFactoriSUN (GLint);\nGLAPI void APIENTRY glGlobalAlphaFactorfSUN (GLfloat);\nGLAPI void APIENTRY glGlobalAlphaFactordSUN (GLdouble);\nGLAPI void APIENTRY glGlobalAlphaFactorubSUN (GLubyte);\nGLAPI void APIENTRY glGlobalAlphaFactorusSUN (GLushort);\nGLAPI void APIENTRY glGlobalAlphaFactoruiSUN (GLuint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLGLOBALALPHAFACTORBSUNPROC) (GLbyte factor);\ntypedef void (APIENTRYP PFNGLGLOBALALPHAFACTORSSUNPROC) (GLshort factor);\ntypedef void (APIENTRYP PFNGLGLOBALALPHAFACTORISUNPROC) (GLint factor);\ntypedef void (APIENTRYP PFNGLGLOBALALPHAFACTORFSUNPROC) (GLfloat factor);\ntypedef void (APIENTRYP PFNGLGLOBALALPHAFACTORDSUNPROC) (GLdouble factor);\ntypedef void (APIENTRYP PFNGLGLOBALALPHAFACTORUBSUNPROC) (GLubyte factor);\ntypedef void (APIENTRYP PFNGLGLOBALALPHAFACTORUSSUNPROC) (GLushort factor);\ntypedef void (APIENTRYP PFNGLGLOBALALPHAFACTORUISUNPROC) (GLuint factor);\n#endif\n\n#ifndef GL_SUN_triangle_list\n#define GL_SUN_triangle_list 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glReplacementCodeuiSUN (GLuint);\nGLAPI void APIENTRY glReplacementCodeusSUN (GLushort);\nGLAPI void APIENTRY glReplacementCodeubSUN (GLubyte);\nGLAPI void APIENTRY glReplacementCodeuivSUN (const GLuint *);\nGLAPI void APIENTRY glReplacementCodeusvSUN (const GLushort *);\nGLAPI void APIENTRY glReplacementCodeubvSUN (const GLubyte *);\nGLAPI void APIENTRY glReplacementCodePointerSUN (GLenum, GLsizei, const GLvoid* *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEUISUNPROC) (GLuint code);\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEUSSUNPROC) (GLushort code);\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEUBSUNPROC) (GLubyte code);\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEUIVSUNPROC) (const GLuint *code);\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEUSVSUNPROC) (const GLushort *code);\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEUBVSUNPROC) (const GLubyte *code);\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEPOINTERSUNPROC) (GLenum type, GLsizei stride, const GLvoid* *pointer);\n#endif\n\n#ifndef GL_SUN_vertex\n#define GL_SUN_vertex 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glColor4ubVertex2fSUN (GLubyte, GLubyte, GLubyte, GLubyte, GLfloat, GLfloat);\nGLAPI void APIENTRY glColor4ubVertex2fvSUN (const GLubyte *, const GLfloat *);\nGLAPI void APIENTRY glColor4ubVertex3fSUN (GLubyte, GLubyte, GLubyte, GLubyte, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glColor4ubVertex3fvSUN (const GLubyte *, const GLfloat *);\nGLAPI void APIENTRY glColor3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glColor3fVertex3fvSUN (const GLfloat *, const GLfloat *);\nGLAPI void APIENTRY glNormal3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glNormal3fVertex3fvSUN (const GLfloat *, const GLfloat *);\nGLAPI void APIENTRY glColor4fNormal3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glColor4fNormal3fVertex3fvSUN (const GLfloat *, const GLfloat *, const GLfloat *);\nGLAPI void APIENTRY glTexCoord2fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glTexCoord2fVertex3fvSUN (const GLfloat *, const GLfloat *);\nGLAPI void APIENTRY glTexCoord4fVertex4fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glTexCoord4fVertex4fvSUN (const GLfloat *, const GLfloat *);\nGLAPI void APIENTRY glTexCoord2fColor4ubVertex3fSUN (GLfloat, GLfloat, GLubyte, GLubyte, GLubyte, GLubyte, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glTexCoord2fColor4ubVertex3fvSUN (const GLfloat *, const GLubyte *, const GLfloat *);\nGLAPI void APIENTRY glTexCoord2fColor3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glTexCoord2fColor3fVertex3fvSUN (const GLfloat *, const GLfloat *, const GLfloat *);\nGLAPI void APIENTRY glTexCoord2fNormal3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glTexCoord2fNormal3fVertex3fvSUN (const GLfloat *, const GLfloat *, const GLfloat *);\nGLAPI void APIENTRY glTexCoord2fColor4fNormal3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glTexCoord2fColor4fNormal3fVertex3fvSUN (const GLfloat *, const GLfloat *, const GLfloat *, const GLfloat *);\nGLAPI void APIENTRY glTexCoord4fColor4fNormal3fVertex4fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glTexCoord4fColor4fNormal3fVertex4fvSUN (const GLfloat *, const GLfloat *, const GLfloat *, const GLfloat *);\nGLAPI void APIENTRY glReplacementCodeuiVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glReplacementCodeuiVertex3fvSUN (const GLuint *, const GLfloat *);\nGLAPI void APIENTRY glReplacementCodeuiColor4ubVertex3fSUN (GLuint, GLubyte, GLubyte, GLubyte, GLubyte, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glReplacementCodeuiColor4ubVertex3fvSUN (const GLuint *, const GLubyte *, const GLfloat *);\nGLAPI void APIENTRY glReplacementCodeuiColor3fVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glReplacementCodeuiColor3fVertex3fvSUN (const GLuint *, const GLfloat *, const GLfloat *);\nGLAPI void APIENTRY glReplacementCodeuiNormal3fVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glReplacementCodeuiNormal3fVertex3fvSUN (const GLuint *, const GLfloat *, const GLfloat *);\nGLAPI void APIENTRY glReplacementCodeuiColor4fNormal3fVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glReplacementCodeuiColor4fNormal3fVertex3fvSUN (const GLuint *, const GLfloat *, const GLfloat *, const GLfloat *);\nGLAPI void APIENTRY glReplacementCodeuiTexCoord2fVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glReplacementCodeuiTexCoord2fVertex3fvSUN (const GLuint *, const GLfloat *, const GLfloat *);\nGLAPI void APIENTRY glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN (const GLuint *, const GLfloat *, const GLfloat *, const GLfloat *);\nGLAPI void APIENTRY glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN (const GLuint *, const GLfloat *, const GLfloat *, const GLfloat *, const GLfloat *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLCOLOR4UBVERTEX2FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y);\ntypedef void (APIENTRYP PFNGLCOLOR4UBVERTEX2FVSUNPROC) (const GLubyte *c, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLCOLOR4UBVERTEX3FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLCOLOR4UBVERTEX3FVSUNPROC) (const GLubyte *c, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLCOLOR3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLCOLOR3FVERTEX3FVSUNPROC) (const GLfloat *c, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLNORMAL3FVERTEX3FSUNPROC) (GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *n, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *c, const GLfloat *n, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLTEXCOORD2FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLTEXCOORD2FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLTEXCOORD4FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat x, GLfloat y, GLfloat z, GLfloat w);\ntypedef void (APIENTRYP PFNGLTEXCOORD4FVERTEX4FVSUNPROC) (const GLfloat *tc, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC) (const GLfloat *tc, const GLubyte *c, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *n, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z, GLfloat w);\ntypedef void (APIENTRYP PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC) (GLuint rc, GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC) (GLuint rc, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC) (const GLuint *rc, const GLubyte *c, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *c, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *n, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *c, const GLfloat *n, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *tc, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *tc, const GLfloat *n, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v);\n#endif\n\n#ifndef GL_EXT_blend_func_separate\n#define GL_EXT_blend_func_separate 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glBlendFuncSeparateEXT (GLenum, GLenum, GLenum, GLenum);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEEXTPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);\n#endif\n\n#ifndef GL_INGR_blend_func_separate\n#define GL_INGR_blend_func_separate 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glBlendFuncSeparateINGR (GLenum, GLenum, GLenum, GLenum);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEINGRPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);\n#endif\n\n#ifndef GL_INGR_color_clamp\n#define GL_INGR_color_clamp 1\n#endif\n\n#ifndef GL_INGR_interlace_read\n#define GL_INGR_interlace_read 1\n#endif\n\n#ifndef GL_EXT_stencil_wrap\n#define GL_EXT_stencil_wrap 1\n#endif\n\n#ifndef GL_EXT_422_pixels\n#define GL_EXT_422_pixels 1\n#endif\n\n#ifndef GL_NV_texgen_reflection\n#define GL_NV_texgen_reflection 1\n#endif\n\n#ifndef GL_SUN_convolution_border_modes\n#define GL_SUN_convolution_border_modes 1\n#endif\n\n#ifndef GL_EXT_texture_env_add\n#define GL_EXT_texture_env_add 1\n#endif\n\n#ifndef GL_EXT_texture_lod_bias\n#define GL_EXT_texture_lod_bias 1\n#endif\n\n#ifndef GL_EXT_texture_filter_anisotropic\n#define GL_EXT_texture_filter_anisotropic 1\n#endif\n\n#ifndef GL_EXT_vertex_weighting\n#define GL_EXT_vertex_weighting 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glVertexWeightfEXT (GLfloat);\nGLAPI void APIENTRY glVertexWeightfvEXT (const GLfloat *);\nGLAPI void APIENTRY glVertexWeightPointerEXT (GLsizei, GLenum, GLsizei, const GLvoid *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLVERTEXWEIGHTFEXTPROC) (GLfloat weight);\ntypedef void (APIENTRYP PFNGLVERTEXWEIGHTFVEXTPROC) (const GLfloat *weight);\ntypedef void (APIENTRYP PFNGLVERTEXWEIGHTPOINTEREXTPROC) (GLsizei size, GLenum type, GLsizei stride, const GLvoid *pointer);\n#endif\n\n#ifndef GL_NV_light_max_exponent\n#define GL_NV_light_max_exponent 1\n#endif\n\n#ifndef GL_NV_vertex_array_range\n#define GL_NV_vertex_array_range 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glFlushVertexArrayRangeNV (void);\nGLAPI void APIENTRY glVertexArrayRangeNV (GLsizei, const GLvoid *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLFLUSHVERTEXARRAYRANGENVPROC) (void);\ntypedef void (APIENTRYP PFNGLVERTEXARRAYRANGENVPROC) (GLsizei length, const GLvoid *pointer);\n#endif\n\n#ifndef GL_NV_register_combiners\n#define GL_NV_register_combiners 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glCombinerParameterfvNV (GLenum, const GLfloat *);\nGLAPI void APIENTRY glCombinerParameterfNV (GLenum, GLfloat);\nGLAPI void APIENTRY glCombinerParameterivNV (GLenum, const GLint *);\nGLAPI void APIENTRY glCombinerParameteriNV (GLenum, GLint);\nGLAPI void APIENTRY glCombinerInputNV (GLenum, GLenum, GLenum, GLenum, GLenum, GLenum);\nGLAPI void APIENTRY glCombinerOutputNV (GLenum, GLenum, GLenum, GLenum, GLenum, GLenum, GLenum, GLboolean, GLboolean, GLboolean);\nGLAPI void APIENTRY glFinalCombinerInputNV (GLenum, GLenum, GLenum, GLenum);\nGLAPI void APIENTRY glGetCombinerInputParameterfvNV (GLenum, GLenum, GLenum, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetCombinerInputParameterivNV (GLenum, GLenum, GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glGetCombinerOutputParameterfvNV (GLenum, GLenum, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetCombinerOutputParameterivNV (GLenum, GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glGetFinalCombinerInputParameterfvNV (GLenum, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetFinalCombinerInputParameterivNV (GLenum, GLenum, GLint *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLCOMBINERPARAMETERFVNVPROC) (GLenum pname, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLCOMBINERPARAMETERFNVPROC) (GLenum pname, GLfloat param);\ntypedef void (APIENTRYP PFNGLCOMBINERPARAMETERIVNVPROC) (GLenum pname, const GLint *params);\ntypedef void (APIENTRYP PFNGLCOMBINERPARAMETERINVPROC) (GLenum pname, GLint param);\ntypedef void (APIENTRYP PFNGLCOMBINERINPUTNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage);\ntypedef void (APIENTRYP PFNGLCOMBINEROUTPUTNVPROC) (GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum);\ntypedef void (APIENTRYP PFNGLFINALCOMBINERINPUTNVPROC) (GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage);\ntypedef void (APIENTRYP PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC) (GLenum variable, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC) (GLenum variable, GLenum pname, GLint *params);\n#endif\n\n#ifndef GL_NV_fog_distance\n#define GL_NV_fog_distance 1\n#endif\n\n#ifndef GL_NV_texgen_emboss\n#define GL_NV_texgen_emboss 1\n#endif\n\n#ifndef GL_NV_blend_square\n#define GL_NV_blend_square 1\n#endif\n\n#ifndef GL_NV_texture_env_combine4\n#define GL_NV_texture_env_combine4 1\n#endif\n\n#ifndef GL_MESA_resize_buffers\n#define GL_MESA_resize_buffers 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glResizeBuffersMESA (void);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLRESIZEBUFFERSMESAPROC) (void);\n#endif\n\n#ifndef GL_MESA_window_pos\n#define GL_MESA_window_pos 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glWindowPos2dMESA (GLdouble, GLdouble);\nGLAPI void APIENTRY glWindowPos2dvMESA (const GLdouble *);\nGLAPI void APIENTRY glWindowPos2fMESA (GLfloat, GLfloat);\nGLAPI void APIENTRY glWindowPos2fvMESA (const GLfloat *);\nGLAPI void APIENTRY glWindowPos2iMESA (GLint, GLint);\nGLAPI void APIENTRY glWindowPos2ivMESA (const GLint *);\nGLAPI void APIENTRY glWindowPos2sMESA (GLshort, GLshort);\nGLAPI void APIENTRY glWindowPos2svMESA (const GLshort *);\nGLAPI void APIENTRY glWindowPos3dMESA (GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glWindowPos3dvMESA (const GLdouble *);\nGLAPI void APIENTRY glWindowPos3fMESA (GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glWindowPos3fvMESA (const GLfloat *);\nGLAPI void APIENTRY glWindowPos3iMESA (GLint, GLint, GLint);\nGLAPI void APIENTRY glWindowPos3ivMESA (const GLint *);\nGLAPI void APIENTRY glWindowPos3sMESA (GLshort, GLshort, GLshort);\nGLAPI void APIENTRY glWindowPos3svMESA (const GLshort *);\nGLAPI void APIENTRY glWindowPos4dMESA (GLdouble, GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glWindowPos4dvMESA (const GLdouble *);\nGLAPI void APIENTRY glWindowPos4fMESA (GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glWindowPos4fvMESA (const GLfloat *);\nGLAPI void APIENTRY glWindowPos4iMESA (GLint, GLint, GLint, GLint);\nGLAPI void APIENTRY glWindowPos4ivMESA (const GLint *);\nGLAPI void APIENTRY glWindowPos4sMESA (GLshort, GLshort, GLshort, GLshort);\nGLAPI void APIENTRY glWindowPos4svMESA (const GLshort *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLWINDOWPOS2DMESAPROC) (GLdouble x, GLdouble y);\ntypedef void (APIENTRYP PFNGLWINDOWPOS2DVMESAPROC) (const GLdouble *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS2FMESAPROC) (GLfloat x, GLfloat y);\ntypedef void (APIENTRYP PFNGLWINDOWPOS2FVMESAPROC) (const GLfloat *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS2IMESAPROC) (GLint x, GLint y);\ntypedef void (APIENTRYP PFNGLWINDOWPOS2IVMESAPROC) (const GLint *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS2SMESAPROC) (GLshort x, GLshort y);\ntypedef void (APIENTRYP PFNGLWINDOWPOS2SVMESAPROC) (const GLshort *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3DMESAPROC) (GLdouble x, GLdouble y, GLdouble z);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3DVMESAPROC) (const GLdouble *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3FMESAPROC) (GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3FVMESAPROC) (const GLfloat *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3IMESAPROC) (GLint x, GLint y, GLint z);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3IVMESAPROC) (const GLint *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3SMESAPROC) (GLshort x, GLshort y, GLshort z);\ntypedef void (APIENTRYP PFNGLWINDOWPOS3SVMESAPROC) (const GLshort *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS4DMESAPROC) (GLdouble x, GLdouble y, GLdouble z, GLdouble w);\ntypedef void (APIENTRYP PFNGLWINDOWPOS4DVMESAPROC) (const GLdouble *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS4FMESAPROC) (GLfloat x, GLfloat y, GLfloat z, GLfloat w);\ntypedef void (APIENTRYP PFNGLWINDOWPOS4FVMESAPROC) (const GLfloat *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS4IMESAPROC) (GLint x, GLint y, GLint z, GLint w);\ntypedef void (APIENTRYP PFNGLWINDOWPOS4IVMESAPROC) (const GLint *v);\ntypedef void (APIENTRYP PFNGLWINDOWPOS4SMESAPROC) (GLshort x, GLshort y, GLshort z, GLshort w);\ntypedef void (APIENTRYP PFNGLWINDOWPOS4SVMESAPROC) (const GLshort *v);\n#endif\n\n#ifndef GL_IBM_cull_vertex\n#define GL_IBM_cull_vertex 1\n#endif\n\n#ifndef GL_IBM_multimode_draw_arrays\n#define GL_IBM_multimode_draw_arrays 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glMultiModeDrawArraysIBM (const GLenum *, const GLint *, const GLsizei *, GLsizei, GLint);\nGLAPI void APIENTRY glMultiModeDrawElementsIBM (const GLenum *, const GLsizei *, GLenum, const GLvoid* const *, GLsizei, GLint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLMULTIMODEDRAWARRAYSIBMPROC) (const GLenum *mode, const GLint *first, const GLsizei *count, GLsizei primcount, GLint modestride);\ntypedef void (APIENTRYP PFNGLMULTIMODEDRAWELEMENTSIBMPROC) (const GLenum *mode, const GLsizei *count, GLenum type, const GLvoid* const *indices, GLsizei primcount, GLint modestride);\n#endif\n\n#ifndef GL_IBM_vertex_array_lists\n#define GL_IBM_vertex_array_lists 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glColorPointerListIBM (GLint, GLenum, GLint, const GLvoid* *, GLint);\nGLAPI void APIENTRY glSecondaryColorPointerListIBM (GLint, GLenum, GLint, const GLvoid* *, GLint);\nGLAPI void APIENTRY glEdgeFlagPointerListIBM (GLint, const GLboolean* *, GLint);\nGLAPI void APIENTRY glFogCoordPointerListIBM (GLenum, GLint, const GLvoid* *, GLint);\nGLAPI void APIENTRY glIndexPointerListIBM (GLenum, GLint, const GLvoid* *, GLint);\nGLAPI void APIENTRY glNormalPointerListIBM (GLenum, GLint, const GLvoid* *, GLint);\nGLAPI void APIENTRY glTexCoordPointerListIBM (GLint, GLenum, GLint, const GLvoid* *, GLint);\nGLAPI void APIENTRY glVertexPointerListIBM (GLint, GLenum, GLint, const GLvoid* *, GLint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride);\ntypedef void (APIENTRYP PFNGLEDGEFLAGPOINTERLISTIBMPROC) (GLint stride, const GLboolean* *pointer, GLint ptrstride);\ntypedef void (APIENTRYP PFNGLFOGCOORDPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride);\ntypedef void (APIENTRYP PFNGLINDEXPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride);\ntypedef void (APIENTRYP PFNGLNORMALPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride);\ntypedef void (APIENTRYP PFNGLTEXCOORDPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride);\ntypedef void (APIENTRYP PFNGLVERTEXPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride);\n#endif\n\n#ifndef GL_SGIX_subsample\n#define GL_SGIX_subsample 1\n#endif\n\n#ifndef GL_SGIX_ycrcba\n#define GL_SGIX_ycrcba 1\n#endif\n\n#ifndef GL_SGIX_ycrcb_subsample\n#define GL_SGIX_ycrcb_subsample 1\n#endif\n\n#ifndef GL_SGIX_depth_pass_instrument\n#define GL_SGIX_depth_pass_instrument 1\n#endif\n\n#ifndef GL_3DFX_texture_compression_FXT1\n#define GL_3DFX_texture_compression_FXT1 1\n#endif\n\n#ifndef GL_3DFX_multisample\n#define GL_3DFX_multisample 1\n#endif\n\n#ifndef GL_3DFX_tbuffer\n#define GL_3DFX_tbuffer 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glTbufferMask3DFX (GLuint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLTBUFFERMASK3DFXPROC) (GLuint mask);\n#endif\n\n#ifndef GL_EXT_multisample\n#define GL_EXT_multisample 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glSampleMaskEXT (GLclampf, GLboolean);\nGLAPI void APIENTRY glSamplePatternEXT (GLenum);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLSAMPLEMASKEXTPROC) (GLclampf value, GLboolean invert);\ntypedef void (APIENTRYP PFNGLSAMPLEPATTERNEXTPROC) (GLenum pattern);\n#endif\n\n#ifndef GL_SGIX_vertex_preclip\n#define GL_SGIX_vertex_preclip 1\n#endif\n\n#ifndef GL_SGIX_convolution_accuracy\n#define GL_SGIX_convolution_accuracy 1\n#endif\n\n#ifndef GL_SGIX_resample\n#define GL_SGIX_resample 1\n#endif\n\n#ifndef GL_SGIS_point_line_texgen\n#define GL_SGIS_point_line_texgen 1\n#endif\n\n#ifndef GL_SGIS_texture_color_mask\n#define GL_SGIS_texture_color_mask 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glTextureColorMaskSGIS (GLboolean, GLboolean, GLboolean, GLboolean);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLTEXTURECOLORMASKSGISPROC) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);\n#endif\n\n#ifndef GL_SGIX_igloo_interface\n#define GL_SGIX_igloo_interface 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glIglooInterfaceSGIX (GLenum, const GLvoid *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLIGLOOINTERFACESGIXPROC) (GLenum pname, const GLvoid *params);\n#endif\n\n#ifndef GL_EXT_texture_env_dot3\n#define GL_EXT_texture_env_dot3 1\n#endif\n\n#ifndef GL_ATI_texture_mirror_once\n#define GL_ATI_texture_mirror_once 1\n#endif\n\n#ifndef GL_NV_fence\n#define GL_NV_fence 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glDeleteFencesNV (GLsizei, const GLuint *);\nGLAPI void APIENTRY glGenFencesNV (GLsizei, GLuint *);\nGLAPI GLboolean APIENTRY glIsFenceNV (GLuint);\nGLAPI GLboolean APIENTRY glTestFenceNV (GLuint);\nGLAPI void APIENTRY glGetFenceivNV (GLuint, GLenum, GLint *);\nGLAPI void APIENTRY glFinishFenceNV (GLuint);\nGLAPI void APIENTRY glSetFenceNV (GLuint, GLenum);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint *fences);\ntypedef void (APIENTRYP PFNGLGENFENCESNVPROC) (GLsizei n, GLuint *fences);\ntypedef GLboolean (APIENTRYP PFNGLISFENCENVPROC) (GLuint fence);\ntypedef GLboolean (APIENTRYP PFNGLTESTFENCENVPROC) (GLuint fence);\ntypedef void (APIENTRYP PFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLFINISHFENCENVPROC) (GLuint fence);\ntypedef void (APIENTRYP PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition);\n#endif\n\n#ifndef GL_NV_evaluators\n#define GL_NV_evaluators 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glMapControlPointsNV (GLenum, GLuint, GLenum, GLsizei, GLsizei, GLint, GLint, GLboolean, const GLvoid *);\nGLAPI void APIENTRY glMapParameterivNV (GLenum, GLenum, const GLint *);\nGLAPI void APIENTRY glMapParameterfvNV (GLenum, GLenum, const GLfloat *);\nGLAPI void APIENTRY glGetMapControlPointsNV (GLenum, GLuint, GLenum, GLsizei, GLsizei, GLboolean, GLvoid *);\nGLAPI void APIENTRY glGetMapParameterivNV (GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glGetMapParameterfvNV (GLenum, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetMapAttribParameterivNV (GLenum, GLuint, GLenum, GLint *);\nGLAPI void APIENTRY glGetMapAttribParameterfvNV (GLenum, GLuint, GLenum, GLfloat *);\nGLAPI void APIENTRY glEvalMapsNV (GLenum, GLenum);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLint uorder, GLint vorder, GLboolean packed, const GLvoid *points);\ntypedef void (APIENTRYP PFNGLMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, const GLint *params);\ntypedef void (APIENTRYP PFNGLMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLboolean packed, GLvoid *points);\ntypedef void (APIENTRYP PFNGLGETMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETMAPATTRIBPARAMETERIVNVPROC) (GLenum target, GLuint index, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETMAPATTRIBPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLEVALMAPSNVPROC) (GLenum target, GLenum mode);\n#endif\n\n#ifndef GL_NV_packed_depth_stencil\n#define GL_NV_packed_depth_stencil 1\n#endif\n\n#ifndef GL_NV_register_combiners2\n#define GL_NV_register_combiners2 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glCombinerStageParameterfvNV (GLenum, GLenum, const GLfloat *);\nGLAPI void APIENTRY glGetCombinerStageParameterfvNV (GLenum, GLenum, GLfloat *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, GLfloat *params);\n#endif\n\n#ifndef GL_NV_texture_compression_vtc\n#define GL_NV_texture_compression_vtc 1\n#endif\n\n#ifndef GL_NV_texture_rectangle\n#define GL_NV_texture_rectangle 1\n#endif\n\n#ifndef GL_NV_texture_shader\n#define GL_NV_texture_shader 1\n#endif\n\n#ifndef GL_NV_texture_shader2\n#define GL_NV_texture_shader2 1\n#endif\n\n#ifndef GL_NV_vertex_array_range2\n#define GL_NV_vertex_array_range2 1\n#endif\n\n#ifndef GL_NV_vertex_program\n#define GL_NV_vertex_program 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI GLboolean APIENTRY glAreProgramsResidentNV (GLsizei, const GLuint *, GLboolean *);\nGLAPI void APIENTRY glBindProgramNV (GLenum, GLuint);\nGLAPI void APIENTRY glDeleteProgramsNV (GLsizei, const GLuint *);\nGLAPI void APIENTRY glExecuteProgramNV (GLenum, GLuint, const GLfloat *);\nGLAPI void APIENTRY glGenProgramsNV (GLsizei, GLuint *);\nGLAPI void APIENTRY glGetProgramParameterdvNV (GLenum, GLuint, GLenum, GLdouble *);\nGLAPI void APIENTRY glGetProgramParameterfvNV (GLenum, GLuint, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetProgramivNV (GLuint, GLenum, GLint *);\nGLAPI void APIENTRY glGetProgramStringNV (GLuint, GLenum, GLubyte *);\nGLAPI void APIENTRY glGetTrackMatrixivNV (GLenum, GLuint, GLenum, GLint *);\nGLAPI void APIENTRY glGetVertexAttribdvNV (GLuint, GLenum, GLdouble *);\nGLAPI void APIENTRY glGetVertexAttribfvNV (GLuint, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetVertexAttribivNV (GLuint, GLenum, GLint *);\nGLAPI void APIENTRY glGetVertexAttribPointervNV (GLuint, GLenum, GLvoid* *);\nGLAPI GLboolean APIENTRY glIsProgramNV (GLuint);\nGLAPI void APIENTRY glLoadProgramNV (GLenum, GLuint, GLsizei, const GLubyte *);\nGLAPI void APIENTRY glProgramParameter4dNV (GLenum, GLuint, GLdouble, GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glProgramParameter4dvNV (GLenum, GLuint, const GLdouble *);\nGLAPI void APIENTRY glProgramParameter4fNV (GLenum, GLuint, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glProgramParameter4fvNV (GLenum, GLuint, const GLfloat *);\nGLAPI void APIENTRY glProgramParameters4dvNV (GLenum, GLuint, GLuint, const GLdouble *);\nGLAPI void APIENTRY glProgramParameters4fvNV (GLenum, GLuint, GLuint, const GLfloat *);\nGLAPI void APIENTRY glRequestResidentProgramsNV (GLsizei, const GLuint *);\nGLAPI void APIENTRY glTrackMatrixNV (GLenum, GLuint, GLenum, GLenum);\nGLAPI void APIENTRY glVertexAttribPointerNV (GLuint, GLint, GLenum, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glVertexAttrib1dNV (GLuint, GLdouble);\nGLAPI void APIENTRY glVertexAttrib1dvNV (GLuint, const GLdouble *);\nGLAPI void APIENTRY glVertexAttrib1fNV (GLuint, GLfloat);\nGLAPI void APIENTRY glVertexAttrib1fvNV (GLuint, const GLfloat *);\nGLAPI void APIENTRY glVertexAttrib1sNV (GLuint, GLshort);\nGLAPI void APIENTRY glVertexAttrib1svNV (GLuint, const GLshort *);\nGLAPI void APIENTRY glVertexAttrib2dNV (GLuint, GLdouble, GLdouble);\nGLAPI void APIENTRY glVertexAttrib2dvNV (GLuint, const GLdouble *);\nGLAPI void APIENTRY glVertexAttrib2fNV (GLuint, GLfloat, GLfloat);\nGLAPI void APIENTRY glVertexAttrib2fvNV (GLuint, const GLfloat *);\nGLAPI void APIENTRY glVertexAttrib2sNV (GLuint, GLshort, GLshort);\nGLAPI void APIENTRY glVertexAttrib2svNV (GLuint, const GLshort *);\nGLAPI void APIENTRY glVertexAttrib3dNV (GLuint, GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glVertexAttrib3dvNV (GLuint, const GLdouble *);\nGLAPI void APIENTRY glVertexAttrib3fNV (GLuint, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glVertexAttrib3fvNV (GLuint, const GLfloat *);\nGLAPI void APIENTRY glVertexAttrib3sNV (GLuint, GLshort, GLshort, GLshort);\nGLAPI void APIENTRY glVertexAttrib3svNV (GLuint, const GLshort *);\nGLAPI void APIENTRY glVertexAttrib4dNV (GLuint, GLdouble, GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glVertexAttrib4dvNV (GLuint, const GLdouble *);\nGLAPI void APIENTRY glVertexAttrib4fNV (GLuint, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glVertexAttrib4fvNV (GLuint, const GLfloat *);\nGLAPI void APIENTRY glVertexAttrib4sNV (GLuint, GLshort, GLshort, GLshort, GLshort);\nGLAPI void APIENTRY glVertexAttrib4svNV (GLuint, const GLshort *);\nGLAPI void APIENTRY glVertexAttrib4ubNV (GLuint, GLubyte, GLubyte, GLubyte, GLubyte);\nGLAPI void APIENTRY glVertexAttrib4ubvNV (GLuint, const GLubyte *);\nGLAPI void APIENTRY glVertexAttribs1dvNV (GLuint, GLsizei, const GLdouble *);\nGLAPI void APIENTRY glVertexAttribs1fvNV (GLuint, GLsizei, const GLfloat *);\nGLAPI void APIENTRY glVertexAttribs1svNV (GLuint, GLsizei, const GLshort *);\nGLAPI void APIENTRY glVertexAttribs2dvNV (GLuint, GLsizei, const GLdouble *);\nGLAPI void APIENTRY glVertexAttribs2fvNV (GLuint, GLsizei, const GLfloat *);\nGLAPI void APIENTRY glVertexAttribs2svNV (GLuint, GLsizei, const GLshort *);\nGLAPI void APIENTRY glVertexAttribs3dvNV (GLuint, GLsizei, const GLdouble *);\nGLAPI void APIENTRY glVertexAttribs3fvNV (GLuint, GLsizei, const GLfloat *);\nGLAPI void APIENTRY glVertexAttribs3svNV (GLuint, GLsizei, const GLshort *);\nGLAPI void APIENTRY glVertexAttribs4dvNV (GLuint, GLsizei, const GLdouble *);\nGLAPI void APIENTRY glVertexAttribs4fvNV (GLuint, GLsizei, const GLfloat *);\nGLAPI void APIENTRY glVertexAttribs4svNV (GLuint, GLsizei, const GLshort *);\nGLAPI void APIENTRY glVertexAttribs4ubvNV (GLuint, GLsizei, const GLubyte *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef GLboolean (APIENTRYP PFNGLAREPROGRAMSRESIDENTNVPROC) (GLsizei n, const GLuint *programs, GLboolean *residences);\ntypedef void (APIENTRYP PFNGLBINDPROGRAMNVPROC) (GLenum target, GLuint id);\ntypedef void (APIENTRYP PFNGLDELETEPROGRAMSNVPROC) (GLsizei n, const GLuint *programs);\ntypedef void (APIENTRYP PFNGLEXECUTEPROGRAMNVPROC) (GLenum target, GLuint id, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLGENPROGRAMSNVPROC) (GLsizei n, GLuint *programs);\ntypedef void (APIENTRYP PFNGLGETPROGRAMPARAMETERDVNVPROC) (GLenum target, GLuint index, GLenum pname, GLdouble *params);\ntypedef void (APIENTRYP PFNGLGETPROGRAMPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETPROGRAMIVNVPROC) (GLuint id, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETPROGRAMSTRINGNVPROC) (GLuint id, GLenum pname, GLubyte *program);\ntypedef void (APIENTRYP PFNGLGETTRACKMATRIXIVNVPROC) (GLenum target, GLuint address, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETVERTEXATTRIBDVNVPROC) (GLuint index, GLenum pname, GLdouble *params);\ntypedef void (APIENTRYP PFNGLGETVERTEXATTRIBFVNVPROC) (GLuint index, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVNVPROC) (GLuint index, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVNVPROC) (GLuint index, GLenum pname, GLvoid* *pointer);\ntypedef GLboolean (APIENTRYP PFNGLISPROGRAMNVPROC) (GLuint id);\ntypedef void (APIENTRYP PFNGLLOADPROGRAMNVPROC) (GLenum target, GLuint id, GLsizei len, const GLubyte *program);\ntypedef void (APIENTRYP PFNGLPROGRAMPARAMETER4DNVPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);\ntypedef void (APIENTRYP PFNGLPROGRAMPARAMETER4DVNVPROC) (GLenum target, GLuint index, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLPROGRAMPARAMETER4FNVPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);\ntypedef void (APIENTRYP PFNGLPROGRAMPARAMETER4FVNVPROC) (GLenum target, GLuint index, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLPROGRAMPARAMETERS4DVNVPROC) (GLenum target, GLuint index, GLuint count, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLPROGRAMPARAMETERS4FVNVPROC) (GLenum target, GLuint index, GLuint count, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLREQUESTRESIDENTPROGRAMSNVPROC) (GLsizei n, const GLuint *programs);\ntypedef void (APIENTRYP PFNGLTRACKMATRIXNVPROC) (GLenum target, GLuint address, GLenum matrix, GLenum transform);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERNVPROC) (GLuint index, GLint fsize, GLenum type, GLsizei stride, const GLvoid *pointer);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB1DNVPROC) (GLuint index, GLdouble x);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB1DVNVPROC) (GLuint index, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB1FNVPROC) (GLuint index, GLfloat x);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB1FVNVPROC) (GLuint index, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB1SNVPROC) (GLuint index, GLshort x);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB1SVNVPROC) (GLuint index, const GLshort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB2DNVPROC) (GLuint index, GLdouble x, GLdouble y);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB2DVNVPROC) (GLuint index, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB2FNVPROC) (GLuint index, GLfloat x, GLfloat y);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB2FVNVPROC) (GLuint index, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB2SNVPROC) (GLuint index, GLshort x, GLshort y);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB2SVNVPROC) (GLuint index, const GLshort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB3DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB3DVNVPROC) (GLuint index, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB3FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB3FVNVPROC) (GLuint index, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB3SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB3SVNVPROC) (GLuint index, const GLshort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4DVNVPROC) (GLuint index, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4FVNVPROC) (GLuint index, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4SVNVPROC) (GLuint index, const GLshort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4UBNVPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4UBVNVPROC) (GLuint index, const GLubyte *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBS1DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBS1FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBS1SVNVPROC) (GLuint index, GLsizei count, const GLshort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBS2DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBS2FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBS2SVNVPROC) (GLuint index, GLsizei count, const GLshort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBS3DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBS3FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBS3SVNVPROC) (GLuint index, GLsizei count, const GLshort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBS4DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBS4FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBS4SVNVPROC) (GLuint index, GLsizei count, const GLshort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBS4UBVNVPROC) (GLuint index, GLsizei count, const GLubyte *v);\n#endif\n\n#ifndef GL_SGIX_texture_coordinate_clamp\n#define GL_SGIX_texture_coordinate_clamp 1\n#endif\n\n#ifndef GL_SGIX_scalebias_hint\n#define GL_SGIX_scalebias_hint 1\n#endif\n\n#ifndef GL_OML_interlace\n#define GL_OML_interlace 1\n#endif\n\n#ifndef GL_OML_subsample\n#define GL_OML_subsample 1\n#endif\n\n#ifndef GL_OML_resample\n#define GL_OML_resample 1\n#endif\n\n#ifndef GL_NV_copy_depth_to_color\n#define GL_NV_copy_depth_to_color 1\n#endif\n\n#ifndef GL_ATI_envmap_bumpmap\n#define GL_ATI_envmap_bumpmap 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glTexBumpParameterivATI (GLenum, const GLint *);\nGLAPI void APIENTRY glTexBumpParameterfvATI (GLenum, const GLfloat *);\nGLAPI void APIENTRY glGetTexBumpParameterivATI (GLenum, GLint *);\nGLAPI void APIENTRY glGetTexBumpParameterfvATI (GLenum, GLfloat *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLTEXBUMPPARAMETERIVATIPROC) (GLenum pname, const GLint *param);\ntypedef void (APIENTRYP PFNGLTEXBUMPPARAMETERFVATIPROC) (GLenum pname, const GLfloat *param);\ntypedef void (APIENTRYP PFNGLGETTEXBUMPPARAMETERIVATIPROC) (GLenum pname, GLint *param);\ntypedef void (APIENTRYP PFNGLGETTEXBUMPPARAMETERFVATIPROC) (GLenum pname, GLfloat *param);\n#endif\n\n#ifndef GL_ATI_fragment_shader\n#define GL_ATI_fragment_shader 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI GLuint APIENTRY glGenFragmentShadersATI (GLuint);\nGLAPI void APIENTRY glBindFragmentShaderATI (GLuint);\nGLAPI void APIENTRY glDeleteFragmentShaderATI (GLuint);\nGLAPI void APIENTRY glBeginFragmentShaderATI (void);\nGLAPI void APIENTRY glEndFragmentShaderATI (void);\nGLAPI void APIENTRY glPassTexCoordATI (GLuint, GLuint, GLenum);\nGLAPI void APIENTRY glSampleMapATI (GLuint, GLuint, GLenum);\nGLAPI void APIENTRY glColorFragmentOp1ATI (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint);\nGLAPI void APIENTRY glColorFragmentOp2ATI (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint);\nGLAPI void APIENTRY glColorFragmentOp3ATI (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint);\nGLAPI void APIENTRY glAlphaFragmentOp1ATI (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint);\nGLAPI void APIENTRY glAlphaFragmentOp2ATI (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint);\nGLAPI void APIENTRY glAlphaFragmentOp3ATI (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint);\nGLAPI void APIENTRY glSetFragmentShaderConstantATI (GLuint, const GLfloat *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef GLuint (APIENTRYP PFNGLGENFRAGMENTSHADERSATIPROC) (GLuint range);\ntypedef void (APIENTRYP PFNGLBINDFRAGMENTSHADERATIPROC) (GLuint id);\ntypedef void (APIENTRYP PFNGLDELETEFRAGMENTSHADERATIPROC) (GLuint id);\ntypedef void (APIENTRYP PFNGLBEGINFRAGMENTSHADERATIPROC) (void);\ntypedef void (APIENTRYP PFNGLENDFRAGMENTSHADERATIPROC) (void);\ntypedef void (APIENTRYP PFNGLPASSTEXCOORDATIPROC) (GLuint dst, GLuint coord, GLenum swizzle);\ntypedef void (APIENTRYP PFNGLSAMPLEMAPATIPROC) (GLuint dst, GLuint interp, GLenum swizzle);\ntypedef void (APIENTRYP PFNGLCOLORFRAGMENTOP1ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod);\ntypedef void (APIENTRYP PFNGLCOLORFRAGMENTOP2ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod);\ntypedef void (APIENTRYP PFNGLCOLORFRAGMENTOP3ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod);\ntypedef void (APIENTRYP PFNGLALPHAFRAGMENTOP1ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod);\ntypedef void (APIENTRYP PFNGLALPHAFRAGMENTOP2ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod);\ntypedef void (APIENTRYP PFNGLALPHAFRAGMENTOP3ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod);\ntypedef void (APIENTRYP PFNGLSETFRAGMENTSHADERCONSTANTATIPROC) (GLuint dst, const GLfloat *value);\n#endif\n\n#ifndef GL_ATI_pn_triangles\n#define GL_ATI_pn_triangles 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glPNTrianglesiATI (GLenum, GLint);\nGLAPI void APIENTRY glPNTrianglesfATI (GLenum, GLfloat);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLPNTRIANGLESIATIPROC) (GLenum pname, GLint param);\ntypedef void (APIENTRYP PFNGLPNTRIANGLESFATIPROC) (GLenum pname, GLfloat param);\n#endif\n\n#ifndef GL_ATI_vertex_array_object\n#define GL_ATI_vertex_array_object 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI GLuint APIENTRY glNewObjectBufferATI (GLsizei, const GLvoid *, GLenum);\nGLAPI GLboolean APIENTRY glIsObjectBufferATI (GLuint);\nGLAPI void APIENTRY glUpdateObjectBufferATI (GLuint, GLuint, GLsizei, const GLvoid *, GLenum);\nGLAPI void APIENTRY glGetObjectBufferfvATI (GLuint, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetObjectBufferivATI (GLuint, GLenum, GLint *);\nGLAPI void APIENTRY glFreeObjectBufferATI (GLuint);\nGLAPI void APIENTRY glArrayObjectATI (GLenum, GLint, GLenum, GLsizei, GLuint, GLuint);\nGLAPI void APIENTRY glGetArrayObjectfvATI (GLenum, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetArrayObjectivATI (GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glVariantArrayObjectATI (GLuint, GLenum, GLsizei, GLuint, GLuint);\nGLAPI void APIENTRY glGetVariantArrayObjectfvATI (GLuint, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetVariantArrayObjectivATI (GLuint, GLenum, GLint *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef GLuint (APIENTRYP PFNGLNEWOBJECTBUFFERATIPROC) (GLsizei size, const GLvoid *pointer, GLenum usage);\ntypedef GLboolean (APIENTRYP PFNGLISOBJECTBUFFERATIPROC) (GLuint buffer);\ntypedef void (APIENTRYP PFNGLUPDATEOBJECTBUFFERATIPROC) (GLuint buffer, GLuint offset, GLsizei size, const GLvoid *pointer, GLenum preserve);\ntypedef void (APIENTRYP PFNGLGETOBJECTBUFFERFVATIPROC) (GLuint buffer, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETOBJECTBUFFERIVATIPROC) (GLuint buffer, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLFREEOBJECTBUFFERATIPROC) (GLuint buffer);\ntypedef void (APIENTRYP PFNGLARRAYOBJECTATIPROC) (GLenum array, GLint size, GLenum type, GLsizei stride, GLuint buffer, GLuint offset);\ntypedef void (APIENTRYP PFNGLGETARRAYOBJECTFVATIPROC) (GLenum array, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETARRAYOBJECTIVATIPROC) (GLenum array, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLVARIANTARRAYOBJECTATIPROC) (GLuint id, GLenum type, GLsizei stride, GLuint buffer, GLuint offset);\ntypedef void (APIENTRYP PFNGLGETVARIANTARRAYOBJECTFVATIPROC) (GLuint id, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETVARIANTARRAYOBJECTIVATIPROC) (GLuint id, GLenum pname, GLint *params);\n#endif\n\n#ifndef GL_EXT_vertex_shader\n#define GL_EXT_vertex_shader 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glBeginVertexShaderEXT (void);\nGLAPI void APIENTRY glEndVertexShaderEXT (void);\nGLAPI void APIENTRY glBindVertexShaderEXT (GLuint);\nGLAPI GLuint APIENTRY glGenVertexShadersEXT (GLuint);\nGLAPI void APIENTRY glDeleteVertexShaderEXT (GLuint);\nGLAPI void APIENTRY glShaderOp1EXT (GLenum, GLuint, GLuint);\nGLAPI void APIENTRY glShaderOp2EXT (GLenum, GLuint, GLuint, GLuint);\nGLAPI void APIENTRY glShaderOp3EXT (GLenum, GLuint, GLuint, GLuint, GLuint);\nGLAPI void APIENTRY glSwizzleEXT (GLuint, GLuint, GLenum, GLenum, GLenum, GLenum);\nGLAPI void APIENTRY glWriteMaskEXT (GLuint, GLuint, GLenum, GLenum, GLenum, GLenum);\nGLAPI void APIENTRY glInsertComponentEXT (GLuint, GLuint, GLuint);\nGLAPI void APIENTRY glExtractComponentEXT (GLuint, GLuint, GLuint);\nGLAPI GLuint APIENTRY glGenSymbolsEXT (GLenum, GLenum, GLenum, GLuint);\nGLAPI void APIENTRY glSetInvariantEXT (GLuint, GLenum, const GLvoid *);\nGLAPI void APIENTRY glSetLocalConstantEXT (GLuint, GLenum, const GLvoid *);\nGLAPI void APIENTRY glVariantbvEXT (GLuint, const GLbyte *);\nGLAPI void APIENTRY glVariantsvEXT (GLuint, const GLshort *);\nGLAPI void APIENTRY glVariantivEXT (GLuint, const GLint *);\nGLAPI void APIENTRY glVariantfvEXT (GLuint, const GLfloat *);\nGLAPI void APIENTRY glVariantdvEXT (GLuint, const GLdouble *);\nGLAPI void APIENTRY glVariantubvEXT (GLuint, const GLubyte *);\nGLAPI void APIENTRY glVariantusvEXT (GLuint, const GLushort *);\nGLAPI void APIENTRY glVariantuivEXT (GLuint, const GLuint *);\nGLAPI void APIENTRY glVariantPointerEXT (GLuint, GLenum, GLuint, const GLvoid *);\nGLAPI void APIENTRY glEnableVariantClientStateEXT (GLuint);\nGLAPI void APIENTRY glDisableVariantClientStateEXT (GLuint);\nGLAPI GLuint APIENTRY glBindLightParameterEXT (GLenum, GLenum);\nGLAPI GLuint APIENTRY glBindMaterialParameterEXT (GLenum, GLenum);\nGLAPI GLuint APIENTRY glBindTexGenParameterEXT (GLenum, GLenum, GLenum);\nGLAPI GLuint APIENTRY glBindTextureUnitParameterEXT (GLenum, GLenum);\nGLAPI GLuint APIENTRY glBindParameterEXT (GLenum);\nGLAPI GLboolean APIENTRY glIsVariantEnabledEXT (GLuint, GLenum);\nGLAPI void APIENTRY glGetVariantBooleanvEXT (GLuint, GLenum, GLboolean *);\nGLAPI void APIENTRY glGetVariantIntegervEXT (GLuint, GLenum, GLint *);\nGLAPI void APIENTRY glGetVariantFloatvEXT (GLuint, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetVariantPointervEXT (GLuint, GLenum, GLvoid* *);\nGLAPI void APIENTRY glGetInvariantBooleanvEXT (GLuint, GLenum, GLboolean *);\nGLAPI void APIENTRY glGetInvariantIntegervEXT (GLuint, GLenum, GLint *);\nGLAPI void APIENTRY glGetInvariantFloatvEXT (GLuint, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetLocalConstantBooleanvEXT (GLuint, GLenum, GLboolean *);\nGLAPI void APIENTRY glGetLocalConstantIntegervEXT (GLuint, GLenum, GLint *);\nGLAPI void APIENTRY glGetLocalConstantFloatvEXT (GLuint, GLenum, GLfloat *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLBEGINVERTEXSHADEREXTPROC) (void);\ntypedef void (APIENTRYP PFNGLENDVERTEXSHADEREXTPROC) (void);\ntypedef void (APIENTRYP PFNGLBINDVERTEXSHADEREXTPROC) (GLuint id);\ntypedef GLuint (APIENTRYP PFNGLGENVERTEXSHADERSEXTPROC) (GLuint range);\ntypedef void (APIENTRYP PFNGLDELETEVERTEXSHADEREXTPROC) (GLuint id);\ntypedef void (APIENTRYP PFNGLSHADEROP1EXTPROC) (GLenum op, GLuint res, GLuint arg1);\ntypedef void (APIENTRYP PFNGLSHADEROP2EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2);\ntypedef void (APIENTRYP PFNGLSHADEROP3EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2, GLuint arg3);\ntypedef void (APIENTRYP PFNGLSWIZZLEEXTPROC) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW);\ntypedef void (APIENTRYP PFNGLWRITEMASKEXTPROC) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW);\ntypedef void (APIENTRYP PFNGLINSERTCOMPONENTEXTPROC) (GLuint res, GLuint src, GLuint num);\ntypedef void (APIENTRYP PFNGLEXTRACTCOMPONENTEXTPROC) (GLuint res, GLuint src, GLuint num);\ntypedef GLuint (APIENTRYP PFNGLGENSYMBOLSEXTPROC) (GLenum datatype, GLenum storagetype, GLenum range, GLuint components);\ntypedef void (APIENTRYP PFNGLSETINVARIANTEXTPROC) (GLuint id, GLenum type, const GLvoid *addr);\ntypedef void (APIENTRYP PFNGLSETLOCALCONSTANTEXTPROC) (GLuint id, GLenum type, const GLvoid *addr);\ntypedef void (APIENTRYP PFNGLVARIANTBVEXTPROC) (GLuint id, const GLbyte *addr);\ntypedef void (APIENTRYP PFNGLVARIANTSVEXTPROC) (GLuint id, const GLshort *addr);\ntypedef void (APIENTRYP PFNGLVARIANTIVEXTPROC) (GLuint id, const GLint *addr);\ntypedef void (APIENTRYP PFNGLVARIANTFVEXTPROC) (GLuint id, const GLfloat *addr);\ntypedef void (APIENTRYP PFNGLVARIANTDVEXTPROC) (GLuint id, const GLdouble *addr);\ntypedef void (APIENTRYP PFNGLVARIANTUBVEXTPROC) (GLuint id, const GLubyte *addr);\ntypedef void (APIENTRYP PFNGLVARIANTUSVEXTPROC) (GLuint id, const GLushort *addr);\ntypedef void (APIENTRYP PFNGLVARIANTUIVEXTPROC) (GLuint id, const GLuint *addr);\ntypedef void (APIENTRYP PFNGLVARIANTPOINTEREXTPROC) (GLuint id, GLenum type, GLuint stride, const GLvoid *addr);\ntypedef void (APIENTRYP PFNGLENABLEVARIANTCLIENTSTATEEXTPROC) (GLuint id);\ntypedef void (APIENTRYP PFNGLDISABLEVARIANTCLIENTSTATEEXTPROC) (GLuint id);\ntypedef GLuint (APIENTRYP PFNGLBINDLIGHTPARAMETEREXTPROC) (GLenum light, GLenum value);\ntypedef GLuint (APIENTRYP PFNGLBINDMATERIALPARAMETEREXTPROC) (GLenum face, GLenum value);\ntypedef GLuint (APIENTRYP PFNGLBINDTEXGENPARAMETEREXTPROC) (GLenum unit, GLenum coord, GLenum value);\ntypedef GLuint (APIENTRYP PFNGLBINDTEXTUREUNITPARAMETEREXTPROC) (GLenum unit, GLenum value);\ntypedef GLuint (APIENTRYP PFNGLBINDPARAMETEREXTPROC) (GLenum value);\ntypedef GLboolean (APIENTRYP PFNGLISVARIANTENABLEDEXTPROC) (GLuint id, GLenum cap);\ntypedef void (APIENTRYP PFNGLGETVARIANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data);\ntypedef void (APIENTRYP PFNGLGETVARIANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data);\ntypedef void (APIENTRYP PFNGLGETVARIANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data);\ntypedef void (APIENTRYP PFNGLGETVARIANTPOINTERVEXTPROC) (GLuint id, GLenum value, GLvoid* *data);\ntypedef void (APIENTRYP PFNGLGETINVARIANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data);\ntypedef void (APIENTRYP PFNGLGETINVARIANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data);\ntypedef void (APIENTRYP PFNGLGETINVARIANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data);\ntypedef void (APIENTRYP PFNGLGETLOCALCONSTANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data);\ntypedef void (APIENTRYP PFNGLGETLOCALCONSTANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data);\ntypedef void (APIENTRYP PFNGLGETLOCALCONSTANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data);\n#endif\n\n#ifndef GL_ATI_vertex_streams\n#define GL_ATI_vertex_streams 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glVertexStream1sATI (GLenum, GLshort);\nGLAPI void APIENTRY glVertexStream1svATI (GLenum, const GLshort *);\nGLAPI void APIENTRY glVertexStream1iATI (GLenum, GLint);\nGLAPI void APIENTRY glVertexStream1ivATI (GLenum, const GLint *);\nGLAPI void APIENTRY glVertexStream1fATI (GLenum, GLfloat);\nGLAPI void APIENTRY glVertexStream1fvATI (GLenum, const GLfloat *);\nGLAPI void APIENTRY glVertexStream1dATI (GLenum, GLdouble);\nGLAPI void APIENTRY glVertexStream1dvATI (GLenum, const GLdouble *);\nGLAPI void APIENTRY glVertexStream2sATI (GLenum, GLshort, GLshort);\nGLAPI void APIENTRY glVertexStream2svATI (GLenum, const GLshort *);\nGLAPI void APIENTRY glVertexStream2iATI (GLenum, GLint, GLint);\nGLAPI void APIENTRY glVertexStream2ivATI (GLenum, const GLint *);\nGLAPI void APIENTRY glVertexStream2fATI (GLenum, GLfloat, GLfloat);\nGLAPI void APIENTRY glVertexStream2fvATI (GLenum, const GLfloat *);\nGLAPI void APIENTRY glVertexStream2dATI (GLenum, GLdouble, GLdouble);\nGLAPI void APIENTRY glVertexStream2dvATI (GLenum, const GLdouble *);\nGLAPI void APIENTRY glVertexStream3sATI (GLenum, GLshort, GLshort, GLshort);\nGLAPI void APIENTRY glVertexStream3svATI (GLenum, const GLshort *);\nGLAPI void APIENTRY glVertexStream3iATI (GLenum, GLint, GLint, GLint);\nGLAPI void APIENTRY glVertexStream3ivATI (GLenum, const GLint *);\nGLAPI void APIENTRY glVertexStream3fATI (GLenum, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glVertexStream3fvATI (GLenum, const GLfloat *);\nGLAPI void APIENTRY glVertexStream3dATI (GLenum, GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glVertexStream3dvATI (GLenum, const GLdouble *);\nGLAPI void APIENTRY glVertexStream4sATI (GLenum, GLshort, GLshort, GLshort, GLshort);\nGLAPI void APIENTRY glVertexStream4svATI (GLenum, const GLshort *);\nGLAPI void APIENTRY glVertexStream4iATI (GLenum, GLint, GLint, GLint, GLint);\nGLAPI void APIENTRY glVertexStream4ivATI (GLenum, const GLint *);\nGLAPI void APIENTRY glVertexStream4fATI (GLenum, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glVertexStream4fvATI (GLenum, const GLfloat *);\nGLAPI void APIENTRY glVertexStream4dATI (GLenum, GLdouble, GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glVertexStream4dvATI (GLenum, const GLdouble *);\nGLAPI void APIENTRY glNormalStream3bATI (GLenum, GLbyte, GLbyte, GLbyte);\nGLAPI void APIENTRY glNormalStream3bvATI (GLenum, const GLbyte *);\nGLAPI void APIENTRY glNormalStream3sATI (GLenum, GLshort, GLshort, GLshort);\nGLAPI void APIENTRY glNormalStream3svATI (GLenum, const GLshort *);\nGLAPI void APIENTRY glNormalStream3iATI (GLenum, GLint, GLint, GLint);\nGLAPI void APIENTRY glNormalStream3ivATI (GLenum, const GLint *);\nGLAPI void APIENTRY glNormalStream3fATI (GLenum, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glNormalStream3fvATI (GLenum, const GLfloat *);\nGLAPI void APIENTRY glNormalStream3dATI (GLenum, GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glNormalStream3dvATI (GLenum, const GLdouble *);\nGLAPI void APIENTRY glClientActiveVertexStreamATI (GLenum);\nGLAPI void APIENTRY glVertexBlendEnviATI (GLenum, GLint);\nGLAPI void APIENTRY glVertexBlendEnvfATI (GLenum, GLfloat);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM1SATIPROC) (GLenum stream, GLshort x);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM1SVATIPROC) (GLenum stream, const GLshort *coords);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM1IATIPROC) (GLenum stream, GLint x);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM1IVATIPROC) (GLenum stream, const GLint *coords);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM1FATIPROC) (GLenum stream, GLfloat x);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM1FVATIPROC) (GLenum stream, const GLfloat *coords);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM1DATIPROC) (GLenum stream, GLdouble x);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM1DVATIPROC) (GLenum stream, const GLdouble *coords);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM2SATIPROC) (GLenum stream, GLshort x, GLshort y);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM2SVATIPROC) (GLenum stream, const GLshort *coords);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM2IATIPROC) (GLenum stream, GLint x, GLint y);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM2IVATIPROC) (GLenum stream, const GLint *coords);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM2FATIPROC) (GLenum stream, GLfloat x, GLfloat y);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM2FVATIPROC) (GLenum stream, const GLfloat *coords);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM2DATIPROC) (GLenum stream, GLdouble x, GLdouble y);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM2DVATIPROC) (GLenum stream, const GLdouble *coords);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM3SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM3SVATIPROC) (GLenum stream, const GLshort *coords);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM3IATIPROC) (GLenum stream, GLint x, GLint y, GLint z);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM3IVATIPROC) (GLenum stream, const GLint *coords);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM3FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM3FVATIPROC) (GLenum stream, const GLfloat *coords);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM3DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM3DVATIPROC) (GLenum stream, const GLdouble *coords);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM4SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z, GLshort w);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM4SVATIPROC) (GLenum stream, const GLshort *coords);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM4IATIPROC) (GLenum stream, GLint x, GLint y, GLint z, GLint w);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM4IVATIPROC) (GLenum stream, const GLint *coords);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM4FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z, GLfloat w);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM4FVATIPROC) (GLenum stream, const GLfloat *coords);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM4DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z, GLdouble w);\ntypedef void (APIENTRYP PFNGLVERTEXSTREAM4DVATIPROC) (GLenum stream, const GLdouble *coords);\ntypedef void (APIENTRYP PFNGLNORMALSTREAM3BATIPROC) (GLenum stream, GLbyte nx, GLbyte ny, GLbyte nz);\ntypedef void (APIENTRYP PFNGLNORMALSTREAM3BVATIPROC) (GLenum stream, const GLbyte *coords);\ntypedef void (APIENTRYP PFNGLNORMALSTREAM3SATIPROC) (GLenum stream, GLshort nx, GLshort ny, GLshort nz);\ntypedef void (APIENTRYP PFNGLNORMALSTREAM3SVATIPROC) (GLenum stream, const GLshort *coords);\ntypedef void (APIENTRYP PFNGLNORMALSTREAM3IATIPROC) (GLenum stream, GLint nx, GLint ny, GLint nz);\ntypedef void (APIENTRYP PFNGLNORMALSTREAM3IVATIPROC) (GLenum stream, const GLint *coords);\ntypedef void (APIENTRYP PFNGLNORMALSTREAM3FATIPROC) (GLenum stream, GLfloat nx, GLfloat ny, GLfloat nz);\ntypedef void (APIENTRYP PFNGLNORMALSTREAM3FVATIPROC) (GLenum stream, const GLfloat *coords);\ntypedef void (APIENTRYP PFNGLNORMALSTREAM3DATIPROC) (GLenum stream, GLdouble nx, GLdouble ny, GLdouble nz);\ntypedef void (APIENTRYP PFNGLNORMALSTREAM3DVATIPROC) (GLenum stream, const GLdouble *coords);\ntypedef void (APIENTRYP PFNGLCLIENTACTIVEVERTEXSTREAMATIPROC) (GLenum stream);\ntypedef void (APIENTRYP PFNGLVERTEXBLENDENVIATIPROC) (GLenum pname, GLint param);\ntypedef void (APIENTRYP PFNGLVERTEXBLENDENVFATIPROC) (GLenum pname, GLfloat param);\n#endif\n\n#ifndef GL_ATI_element_array\n#define GL_ATI_element_array 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glElementPointerATI (GLenum, const GLvoid *);\nGLAPI void APIENTRY glDrawElementArrayATI (GLenum, GLsizei);\nGLAPI void APIENTRY glDrawRangeElementArrayATI (GLenum, GLuint, GLuint, GLsizei);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLELEMENTPOINTERATIPROC) (GLenum type, const GLvoid *pointer);\ntypedef void (APIENTRYP PFNGLDRAWELEMENTARRAYATIPROC) (GLenum mode, GLsizei count);\ntypedef void (APIENTRYP PFNGLDRAWRANGEELEMENTARRAYATIPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count);\n#endif\n\n#ifndef GL_SUN_mesh_array\n#define GL_SUN_mesh_array 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glDrawMeshArraysSUN (GLenum, GLint, GLsizei, GLsizei);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLDRAWMESHARRAYSSUNPROC) (GLenum mode, GLint first, GLsizei count, GLsizei width);\n#endif\n\n#ifndef GL_SUN_slice_accum\n#define GL_SUN_slice_accum 1\n#endif\n\n#ifndef GL_NV_multisample_filter_hint\n#define GL_NV_multisample_filter_hint 1\n#endif\n\n#ifndef GL_NV_depth_clamp\n#define GL_NV_depth_clamp 1\n#endif\n\n#ifndef GL_NV_occlusion_query\n#define GL_NV_occlusion_query 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glGenOcclusionQueriesNV (GLsizei, GLuint *);\nGLAPI void APIENTRY glDeleteOcclusionQueriesNV (GLsizei, const GLuint *);\nGLAPI GLboolean APIENTRY glIsOcclusionQueryNV (GLuint);\nGLAPI void APIENTRY glBeginOcclusionQueryNV (GLuint);\nGLAPI void APIENTRY glEndOcclusionQueryNV (void);\nGLAPI void APIENTRY glGetOcclusionQueryivNV (GLuint, GLenum, GLint *);\nGLAPI void APIENTRY glGetOcclusionQueryuivNV (GLuint, GLenum, GLuint *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLGENOCCLUSIONQUERIESNVPROC) (GLsizei n, GLuint *ids);\ntypedef void (APIENTRYP PFNGLDELETEOCCLUSIONQUERIESNVPROC) (GLsizei n, const GLuint *ids);\ntypedef GLboolean (APIENTRYP PFNGLISOCCLUSIONQUERYNVPROC) (GLuint id);\ntypedef void (APIENTRYP PFNGLBEGINOCCLUSIONQUERYNVPROC) (GLuint id);\ntypedef void (APIENTRYP PFNGLENDOCCLUSIONQUERYNVPROC) (void);\ntypedef void (APIENTRYP PFNGLGETOCCLUSIONQUERYIVNVPROC) (GLuint id, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETOCCLUSIONQUERYUIVNVPROC) (GLuint id, GLenum pname, GLuint *params);\n#endif\n\n#ifndef GL_NV_point_sprite\n#define GL_NV_point_sprite 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glPointParameteriNV (GLenum, GLint);\nGLAPI void APIENTRY glPointParameterivNV (GLenum, const GLint *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLPOINTPARAMETERINVPROC) (GLenum pname, GLint param);\ntypedef void (APIENTRYP PFNGLPOINTPARAMETERIVNVPROC) (GLenum pname, const GLint *params);\n#endif\n\n#ifndef GL_NV_texture_shader3\n#define GL_NV_texture_shader3 1\n#endif\n\n#ifndef GL_NV_vertex_program1_1\n#define GL_NV_vertex_program1_1 1\n#endif\n\n#ifndef GL_EXT_shadow_funcs\n#define GL_EXT_shadow_funcs 1\n#endif\n\n#ifndef GL_EXT_stencil_two_side\n#define GL_EXT_stencil_two_side 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glActiveStencilFaceEXT (GLenum);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLACTIVESTENCILFACEEXTPROC) (GLenum face);\n#endif\n\n#ifndef GL_ATI_text_fragment_shader\n#define GL_ATI_text_fragment_shader 1\n#endif\n\n#ifndef GL_APPLE_client_storage\n#define GL_APPLE_client_storage 1\n#endif\n\n#ifndef GL_APPLE_element_array\n#define GL_APPLE_element_array 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glElementPointerAPPLE (GLenum, const GLvoid *);\nGLAPI void APIENTRY glDrawElementArrayAPPLE (GLenum, GLint, GLsizei);\nGLAPI void APIENTRY glDrawRangeElementArrayAPPLE (GLenum, GLuint, GLuint, GLint, GLsizei);\nGLAPI void APIENTRY glMultiDrawElementArrayAPPLE (GLenum, const GLint *, const GLsizei *, GLsizei);\nGLAPI void APIENTRY glMultiDrawRangeElementArrayAPPLE (GLenum, GLuint, GLuint, const GLint *, const GLsizei *, GLsizei);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLELEMENTPOINTERAPPLEPROC) (GLenum type, const GLvoid *pointer);\ntypedef void (APIENTRYP PFNGLDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, GLint first, GLsizei count);\ntypedef void (APIENTRYP PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, GLint first, GLsizei count);\ntypedef void (APIENTRYP PFNGLMULTIDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);\ntypedef void (APIENTRYP PFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, const GLint *first, const GLsizei *count, GLsizei primcount);\n#endif\n\n#ifndef GL_APPLE_fence\n#define GL_APPLE_fence 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glGenFencesAPPLE (GLsizei, GLuint *);\nGLAPI void APIENTRY glDeleteFencesAPPLE (GLsizei, const GLuint *);\nGLAPI void APIENTRY glSetFenceAPPLE (GLuint);\nGLAPI GLboolean APIENTRY glIsFenceAPPLE (GLuint);\nGLAPI GLboolean APIENTRY glTestFenceAPPLE (GLuint);\nGLAPI void APIENTRY glFinishFenceAPPLE (GLuint);\nGLAPI GLboolean APIENTRY glTestObjectAPPLE (GLenum, GLuint);\nGLAPI void APIENTRY glFinishObjectAPPLE (GLenum, GLint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLGENFENCESAPPLEPROC) (GLsizei n, GLuint *fences);\ntypedef void (APIENTRYP PFNGLDELETEFENCESAPPLEPROC) (GLsizei n, const GLuint *fences);\ntypedef void (APIENTRYP PFNGLSETFENCEAPPLEPROC) (GLuint fence);\ntypedef GLboolean (APIENTRYP PFNGLISFENCEAPPLEPROC) (GLuint fence);\ntypedef GLboolean (APIENTRYP PFNGLTESTFENCEAPPLEPROC) (GLuint fence);\ntypedef void (APIENTRYP PFNGLFINISHFENCEAPPLEPROC) (GLuint fence);\ntypedef GLboolean (APIENTRYP PFNGLTESTOBJECTAPPLEPROC) (GLenum object, GLuint name);\ntypedef void (APIENTRYP PFNGLFINISHOBJECTAPPLEPROC) (GLenum object, GLint name);\n#endif\n\n#ifndef GL_APPLE_vertex_array_object\n#define GL_APPLE_vertex_array_object 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glBindVertexArrayAPPLE (GLuint);\nGLAPI void APIENTRY glDeleteVertexArraysAPPLE (GLsizei, const GLuint *);\nGLAPI void APIENTRY glGenVertexArraysAPPLE (GLsizei, GLuint *);\nGLAPI GLboolean APIENTRY glIsVertexArrayAPPLE (GLuint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLBINDVERTEXARRAYAPPLEPROC) (GLuint array);\ntypedef void (APIENTRYP PFNGLDELETEVERTEXARRAYSAPPLEPROC) (GLsizei n, const GLuint *arrays);\ntypedef void (APIENTRYP PFNGLGENVERTEXARRAYSAPPLEPROC) (GLsizei n, GLuint *arrays);\ntypedef GLboolean (APIENTRYP PFNGLISVERTEXARRAYAPPLEPROC) (GLuint array);\n#endif\n\n#ifndef GL_APPLE_vertex_array_range\n#define GL_APPLE_vertex_array_range 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glVertexArrayRangeAPPLE (GLsizei, GLvoid *);\nGLAPI void APIENTRY glFlushVertexArrayRangeAPPLE (GLsizei, GLvoid *);\nGLAPI void APIENTRY glVertexArrayParameteriAPPLE (GLenum, GLint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, GLvoid *pointer);\ntypedef void (APIENTRYP PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, GLvoid *pointer);\ntypedef void (APIENTRYP PFNGLVERTEXARRAYPARAMETERIAPPLEPROC) (GLenum pname, GLint param);\n#endif\n\n#ifndef GL_APPLE_ycbcr_422\n#define GL_APPLE_ycbcr_422 1\n#endif\n\n#ifndef GL_S3_s3tc\n#define GL_S3_s3tc 1\n#endif\n\n#ifndef GL_ATI_draw_buffers\n#define GL_ATI_draw_buffers 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glDrawBuffersATI (GLsizei, const GLenum *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLDRAWBUFFERSATIPROC) (GLsizei n, const GLenum *bufs);\n#endif\n\n#ifndef GL_ATI_pixel_format_float\n#define GL_ATI_pixel_format_float 1\n/* This is really a WGL extension, but defines some associated GL enums.\n * ATI does not export \"GL_ATI_pixel_format_float\" in the GL_EXTENSIONS string.\n */\n#endif\n\n#ifndef GL_ATI_texture_env_combine3\n#define GL_ATI_texture_env_combine3 1\n#endif\n\n#ifndef GL_ATI_texture_float\n#define GL_ATI_texture_float 1\n#endif\n\n#ifndef GL_NV_float_buffer\n#define GL_NV_float_buffer 1\n#endif\n\n#ifndef GL_NV_fragment_program\n#define GL_NV_fragment_program 1\n/* Some NV_fragment_program entry points are shared with ARB_vertex_program. */\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glProgramNamedParameter4fNV (GLuint, GLsizei, const GLubyte *, GLfloat, GLfloat, GLfloat, GLfloat);\nGLAPI void APIENTRY glProgramNamedParameter4dNV (GLuint, GLsizei, const GLubyte *, GLdouble, GLdouble, GLdouble, GLdouble);\nGLAPI void APIENTRY glProgramNamedParameter4fvNV (GLuint, GLsizei, const GLubyte *, const GLfloat *);\nGLAPI void APIENTRY glProgramNamedParameter4dvNV (GLuint, GLsizei, const GLubyte *, const GLdouble *);\nGLAPI void APIENTRY glGetProgramNamedParameterfvNV (GLuint, GLsizei, const GLubyte *, GLfloat *);\nGLAPI void APIENTRY glGetProgramNamedParameterdvNV (GLuint, GLsizei, const GLubyte *, GLdouble *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4FNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w);\ntypedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4DNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLdouble x, GLdouble y, GLdouble z, GLdouble w);\ntypedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4FVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, const GLfloat *v);\ntypedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4DVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, const GLdouble *v);\ntypedef void (APIENTRYP PFNGLGETPROGRAMNAMEDPARAMETERFVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETPROGRAMNAMEDPARAMETERDVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLdouble *params);\n#endif\n\n#ifndef GL_NV_half_float\n#define GL_NV_half_float 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glVertex2hNV (GLhalfNV, GLhalfNV);\nGLAPI void APIENTRY glVertex2hvNV (const GLhalfNV *);\nGLAPI void APIENTRY glVertex3hNV (GLhalfNV, GLhalfNV, GLhalfNV);\nGLAPI void APIENTRY glVertex3hvNV (const GLhalfNV *);\nGLAPI void APIENTRY glVertex4hNV (GLhalfNV, GLhalfNV, GLhalfNV, GLhalfNV);\nGLAPI void APIENTRY glVertex4hvNV (const GLhalfNV *);\nGLAPI void APIENTRY glNormal3hNV (GLhalfNV, GLhalfNV, GLhalfNV);\nGLAPI void APIENTRY glNormal3hvNV (const GLhalfNV *);\nGLAPI void APIENTRY glColor3hNV (GLhalfNV, GLhalfNV, GLhalfNV);\nGLAPI void APIENTRY glColor3hvNV (const GLhalfNV *);\nGLAPI void APIENTRY glColor4hNV (GLhalfNV, GLhalfNV, GLhalfNV, GLhalfNV);\nGLAPI void APIENTRY glColor4hvNV (const GLhalfNV *);\nGLAPI void APIENTRY glTexCoord1hNV (GLhalfNV);\nGLAPI void APIENTRY glTexCoord1hvNV (const GLhalfNV *);\nGLAPI void APIENTRY glTexCoord2hNV (GLhalfNV, GLhalfNV);\nGLAPI void APIENTRY glTexCoord2hvNV (const GLhalfNV *);\nGLAPI void APIENTRY glTexCoord3hNV (GLhalfNV, GLhalfNV, GLhalfNV);\nGLAPI void APIENTRY glTexCoord3hvNV (const GLhalfNV *);\nGLAPI void APIENTRY glTexCoord4hNV (GLhalfNV, GLhalfNV, GLhalfNV, GLhalfNV);\nGLAPI void APIENTRY glTexCoord4hvNV (const GLhalfNV *);\nGLAPI void APIENTRY glMultiTexCoord1hNV (GLenum, GLhalfNV);\nGLAPI void APIENTRY glMultiTexCoord1hvNV (GLenum, const GLhalfNV *);\nGLAPI void APIENTRY glMultiTexCoord2hNV (GLenum, GLhalfNV, GLhalfNV);\nGLAPI void APIENTRY glMultiTexCoord2hvNV (GLenum, const GLhalfNV *);\nGLAPI void APIENTRY glMultiTexCoord3hNV (GLenum, GLhalfNV, GLhalfNV, GLhalfNV);\nGLAPI void APIENTRY glMultiTexCoord3hvNV (GLenum, const GLhalfNV *);\nGLAPI void APIENTRY glMultiTexCoord4hNV (GLenum, GLhalfNV, GLhalfNV, GLhalfNV, GLhalfNV);\nGLAPI void APIENTRY glMultiTexCoord4hvNV (GLenum, const GLhalfNV *);\nGLAPI void APIENTRY glFogCoordhNV (GLhalfNV);\nGLAPI void APIENTRY glFogCoordhvNV (const GLhalfNV *);\nGLAPI void APIENTRY glSecondaryColor3hNV (GLhalfNV, GLhalfNV, GLhalfNV);\nGLAPI void APIENTRY glSecondaryColor3hvNV (const GLhalfNV *);\nGLAPI void APIENTRY glVertexWeighthNV (GLhalfNV);\nGLAPI void APIENTRY glVertexWeighthvNV (const GLhalfNV *);\nGLAPI void APIENTRY glVertexAttrib1hNV (GLuint, GLhalfNV);\nGLAPI void APIENTRY glVertexAttrib1hvNV (GLuint, const GLhalfNV *);\nGLAPI void APIENTRY glVertexAttrib2hNV (GLuint, GLhalfNV, GLhalfNV);\nGLAPI void APIENTRY glVertexAttrib2hvNV (GLuint, const GLhalfNV *);\nGLAPI void APIENTRY glVertexAttrib3hNV (GLuint, GLhalfNV, GLhalfNV, GLhalfNV);\nGLAPI void APIENTRY glVertexAttrib3hvNV (GLuint, const GLhalfNV *);\nGLAPI void APIENTRY glVertexAttrib4hNV (GLuint, GLhalfNV, GLhalfNV, GLhalfNV, GLhalfNV);\nGLAPI void APIENTRY glVertexAttrib4hvNV (GLuint, const GLhalfNV *);\nGLAPI void APIENTRY glVertexAttribs1hvNV (GLuint, GLsizei, const GLhalfNV *);\nGLAPI void APIENTRY glVertexAttribs2hvNV (GLuint, GLsizei, const GLhalfNV *);\nGLAPI void APIENTRY glVertexAttribs3hvNV (GLuint, GLsizei, const GLhalfNV *);\nGLAPI void APIENTRY glVertexAttribs4hvNV (GLuint, GLsizei, const GLhalfNV *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLVERTEX2HNVPROC) (GLhalfNV x, GLhalfNV y);\ntypedef void (APIENTRYP PFNGLVERTEX2HVNVPROC) (const GLhalfNV *v);\ntypedef void (APIENTRYP PFNGLVERTEX3HNVPROC) (GLhalfNV x, GLhalfNV y, GLhalfNV z);\ntypedef void (APIENTRYP PFNGLVERTEX3HVNVPROC) (const GLhalfNV *v);\ntypedef void (APIENTRYP PFNGLVERTEX4HNVPROC) (GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w);\ntypedef void (APIENTRYP PFNGLVERTEX4HVNVPROC) (const GLhalfNV *v);\ntypedef void (APIENTRYP PFNGLNORMAL3HNVPROC) (GLhalfNV nx, GLhalfNV ny, GLhalfNV nz);\ntypedef void (APIENTRYP PFNGLNORMAL3HVNVPROC) (const GLhalfNV *v);\ntypedef void (APIENTRYP PFNGLCOLOR3HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue);\ntypedef void (APIENTRYP PFNGLCOLOR3HVNVPROC) (const GLhalfNV *v);\ntypedef void (APIENTRYP PFNGLCOLOR4HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue, GLhalfNV alpha);\ntypedef void (APIENTRYP PFNGLCOLOR4HVNVPROC) (const GLhalfNV *v);\ntypedef void (APIENTRYP PFNGLTEXCOORD1HNVPROC) (GLhalfNV s);\ntypedef void (APIENTRYP PFNGLTEXCOORD1HVNVPROC) (const GLhalfNV *v);\ntypedef void (APIENTRYP PFNGLTEXCOORD2HNVPROC) (GLhalfNV s, GLhalfNV t);\ntypedef void (APIENTRYP PFNGLTEXCOORD2HVNVPROC) (const GLhalfNV *v);\ntypedef void (APIENTRYP PFNGLTEXCOORD3HNVPROC) (GLhalfNV s, GLhalfNV t, GLhalfNV r);\ntypedef void (APIENTRYP PFNGLTEXCOORD3HVNVPROC) (const GLhalfNV *v);\ntypedef void (APIENTRYP PFNGLTEXCOORD4HNVPROC) (GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q);\ntypedef void (APIENTRYP PFNGLTEXCOORD4HVNVPROC) (const GLhalfNV *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD1HNVPROC) (GLenum target, GLhalfNV s);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD1HVNVPROC) (GLenum target, const GLhalfNV *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD2HNVPROC) (GLenum target, GLhalfNV s, GLhalfNV t);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD2HVNVPROC) (GLenum target, const GLhalfNV *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD3HNVPROC) (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD3HVNVPROC) (GLenum target, const GLhalfNV *v);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD4HNVPROC) (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q);\ntypedef void (APIENTRYP PFNGLMULTITEXCOORD4HVNVPROC) (GLenum target, const GLhalfNV *v);\ntypedef void (APIENTRYP PFNGLFOGCOORDHNVPROC) (GLhalfNV fog);\ntypedef void (APIENTRYP PFNGLFOGCOORDHVNVPROC) (const GLhalfNV *fog);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue);\ntypedef void (APIENTRYP PFNGLSECONDARYCOLOR3HVNVPROC) (const GLhalfNV *v);\ntypedef void (APIENTRYP PFNGLVERTEXWEIGHTHNVPROC) (GLhalfNV weight);\ntypedef void (APIENTRYP PFNGLVERTEXWEIGHTHVNVPROC) (const GLhalfNV *weight);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB1HNVPROC) (GLuint index, GLhalfNV x);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB1HVNVPROC) (GLuint index, const GLhalfNV *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB2HNVPROC) (GLuint index, GLhalfNV x, GLhalfNV y);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB2HVNVPROC) (GLuint index, const GLhalfNV *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB3HNVPROC) (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB3HVNVPROC) (GLuint index, const GLhalfNV *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4HNVPROC) (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIB4HVNVPROC) (GLuint index, const GLhalfNV *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBS1HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBS2HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBS3HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBS4HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v);\n#endif\n\n#ifndef GL_NV_pixel_data_range\n#define GL_NV_pixel_data_range 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glPixelDataRangeNV (GLenum, GLsizei, GLvoid *);\nGLAPI void APIENTRY glFlushPixelDataRangeNV (GLenum);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLPIXELDATARANGENVPROC) (GLenum target, GLsizei length, GLvoid *pointer);\ntypedef void (APIENTRYP PFNGLFLUSHPIXELDATARANGENVPROC) (GLenum target);\n#endif\n\n#ifndef GL_NV_primitive_restart\n#define GL_NV_primitive_restart 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glPrimitiveRestartNV (void);\nGLAPI void APIENTRY glPrimitiveRestartIndexNV (GLuint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLPRIMITIVERESTARTNVPROC) (void);\ntypedef void (APIENTRYP PFNGLPRIMITIVERESTARTINDEXNVPROC) (GLuint index);\n#endif\n\n#ifndef GL_NV_texture_expand_normal\n#define GL_NV_texture_expand_normal 1\n#endif\n\n#ifndef GL_NV_vertex_program2\n#define GL_NV_vertex_program2 1\n#endif\n\n#ifndef GL_ATI_map_object_buffer\n#define GL_ATI_map_object_buffer 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI GLvoid* APIENTRY glMapObjectBufferATI (GLuint);\nGLAPI void APIENTRY glUnmapObjectBufferATI (GLuint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef GLvoid* (APIENTRYP PFNGLMAPOBJECTBUFFERATIPROC) (GLuint buffer);\ntypedef void (APIENTRYP PFNGLUNMAPOBJECTBUFFERATIPROC) (GLuint buffer);\n#endif\n\n#ifndef GL_ATI_separate_stencil\n#define GL_ATI_separate_stencil 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glStencilOpSeparateATI (GLenum, GLenum, GLenum, GLenum);\nGLAPI void APIENTRY glStencilFuncSeparateATI (GLenum, GLenum, GLint, GLuint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLSTENCILOPSEPARATEATIPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);\ntypedef void (APIENTRYP PFNGLSTENCILFUNCSEPARATEATIPROC) (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask);\n#endif\n\n#ifndef GL_ATI_vertex_attrib_array_object\n#define GL_ATI_vertex_attrib_array_object 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glVertexAttribArrayObjectATI (GLuint, GLint, GLenum, GLboolean, GLsizei, GLuint, GLuint);\nGLAPI void APIENTRY glGetVertexAttribArrayObjectfvATI (GLuint, GLenum, GLfloat *);\nGLAPI void APIENTRY glGetVertexAttribArrayObjectivATI (GLuint, GLenum, GLint *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBARRAYOBJECTATIPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLuint buffer, GLuint offset);\ntypedef void (APIENTRYP PFNGLGETVERTEXATTRIBARRAYOBJECTFVATIPROC) (GLuint index, GLenum pname, GLfloat *params);\ntypedef void (APIENTRYP PFNGLGETVERTEXATTRIBARRAYOBJECTIVATIPROC) (GLuint index, GLenum pname, GLint *params);\n#endif\n\n#ifndef GL_OES_read_format\n#define GL_OES_read_format 1\n#endif\n\n#ifndef GL_EXT_depth_bounds_test\n#define GL_EXT_depth_bounds_test 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glDepthBoundsEXT (GLclampd, GLclampd);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLDEPTHBOUNDSEXTPROC) (GLclampd zmin, GLclampd zmax);\n#endif\n\n#ifndef GL_EXT_texture_mirror_clamp\n#define GL_EXT_texture_mirror_clamp 1\n#endif\n\n#ifndef GL_EXT_blend_equation_separate\n#define GL_EXT_blend_equation_separate 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glBlendEquationSeparateEXT (GLenum, GLenum);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEEXTPROC) (GLenum modeRGB, GLenum modeAlpha);\n#endif\n\n#ifndef GL_MESA_pack_invert\n#define GL_MESA_pack_invert 1\n#endif\n\n#ifndef GL_MESA_ycbcr_texture\n#define GL_MESA_ycbcr_texture 1\n#endif\n\n#ifndef GL_EXT_pixel_buffer_object\n#define GL_EXT_pixel_buffer_object 1\n#endif\n\n#ifndef GL_NV_fragment_program_option\n#define GL_NV_fragment_program_option 1\n#endif\n\n#ifndef GL_NV_fragment_program2\n#define GL_NV_fragment_program2 1\n#endif\n\n#ifndef GL_NV_vertex_program2_option\n#define GL_NV_vertex_program2_option 1\n#endif\n\n#ifndef GL_NV_vertex_program3\n#define GL_NV_vertex_program3 1\n#endif\n\n#ifndef GL_EXT_framebuffer_object\n#define GL_EXT_framebuffer_object 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI GLboolean APIENTRY glIsRenderbufferEXT (GLuint);\nGLAPI void APIENTRY glBindRenderbufferEXT (GLenum, GLuint);\nGLAPI void APIENTRY glDeleteRenderbuffersEXT (GLsizei, const GLuint *);\nGLAPI void APIENTRY glGenRenderbuffersEXT (GLsizei, GLuint *);\nGLAPI void APIENTRY glRenderbufferStorageEXT (GLenum, GLenum, GLsizei, GLsizei);\nGLAPI void APIENTRY glGetRenderbufferParameterivEXT (GLenum, GLenum, GLint *);\nGLAPI GLboolean APIENTRY glIsFramebufferEXT (GLuint);\nGLAPI void APIENTRY glBindFramebufferEXT (GLenum, GLuint);\nGLAPI void APIENTRY glDeleteFramebuffersEXT (GLsizei, const GLuint *);\nGLAPI void APIENTRY glGenFramebuffersEXT (GLsizei, GLuint *);\nGLAPI GLenum APIENTRY glCheckFramebufferStatusEXT (GLenum);\nGLAPI void APIENTRY glFramebufferTexture1DEXT (GLenum, GLenum, GLenum, GLuint, GLint);\nGLAPI void APIENTRY glFramebufferTexture2DEXT (GLenum, GLenum, GLenum, GLuint, GLint);\nGLAPI void APIENTRY glFramebufferTexture3DEXT (GLenum, GLenum, GLenum, GLuint, GLint, GLint);\nGLAPI void APIENTRY glFramebufferRenderbufferEXT (GLenum, GLenum, GLenum, GLuint);\nGLAPI void APIENTRY glGetFramebufferAttachmentParameterivEXT (GLenum, GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glGenerateMipmapEXT (GLenum);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef GLboolean (APIENTRYP PFNGLISRENDERBUFFEREXTPROC) (GLuint renderbuffer);\ntypedef void (APIENTRYP PFNGLBINDRENDERBUFFEREXTPROC) (GLenum target, GLuint renderbuffer);\ntypedef void (APIENTRYP PFNGLDELETERENDERBUFFERSEXTPROC) (GLsizei n, const GLuint *renderbuffers);\ntypedef void (APIENTRYP PFNGLGENRENDERBUFFERSEXTPROC) (GLsizei n, GLuint *renderbuffers);\ntypedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);\ntypedef void (APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);\ntypedef GLboolean (APIENTRYP PFNGLISFRAMEBUFFEREXTPROC) (GLuint framebuffer);\ntypedef void (APIENTRYP PFNGLBINDFRAMEBUFFEREXTPROC) (GLenum target, GLuint framebuffer);\ntypedef void (APIENTRYP PFNGLDELETEFRAMEBUFFERSEXTPROC) (GLsizei n, const GLuint *framebuffers);\ntypedef void (APIENTRYP PFNGLGENFRAMEBUFFERSEXTPROC) (GLsizei n, GLuint *framebuffers);\ntypedef GLenum (APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) (GLenum target);\ntypedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE1DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);\ntypedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);\ntypedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);\ntypedef void (APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);\ntypedef void (APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) (GLenum target, GLenum attachment, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGENERATEMIPMAPEXTPROC) (GLenum target);\n#endif\n\n#ifndef GL_GREMEDY_string_marker\n#define GL_GREMEDY_string_marker 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glStringMarkerGREMEDY (GLsizei, const GLvoid *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLSTRINGMARKERGREMEDYPROC) (GLsizei len, const GLvoid *string);\n#endif\n\n#ifndef GL_EXT_packed_depth_stencil\n#define GL_EXT_packed_depth_stencil 1\n#endif\n\n#ifndef GL_EXT_stencil_clear_tag\n#define GL_EXT_stencil_clear_tag 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glStencilClearTagEXT (GLsizei, GLuint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLSTENCILCLEARTAGEXTPROC) (GLsizei stencilTagBits, GLuint stencilClearTag);\n#endif\n\n#ifndef GL_EXT_texture_sRGB\n#define GL_EXT_texture_sRGB 1\n#endif\n\n#ifndef GL_EXT_framebuffer_blit\n#define GL_EXT_framebuffer_blit 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glBlitFramebufferEXT (GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLbitfield, GLenum);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLBLITFRAMEBUFFEREXTPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);\n#endif\n\n#ifndef GL_EXT_framebuffer_multisample\n#define GL_EXT_framebuffer_multisample 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glRenderbufferStorageMultisampleEXT (GLenum, GLsizei, GLenum, GLsizei, GLsizei);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);\n#endif\n\n#ifndef GL_MESAX_texture_stack\n#define GL_MESAX_texture_stack 1\n#endif\n\n#ifndef GL_EXT_timer_query\n#define GL_EXT_timer_query 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glGetQueryObjecti64vEXT (GLuint, GLenum, GLint64EXT *);\nGLAPI void APIENTRY glGetQueryObjectui64vEXT (GLuint, GLenum, GLuint64EXT *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLGETQUERYOBJECTI64VEXTPROC) (GLuint id, GLenum pname, GLint64EXT *params);\ntypedef void (APIENTRYP PFNGLGETQUERYOBJECTUI64VEXTPROC) (GLuint id, GLenum pname, GLuint64EXT *params);\n#endif\n\n#ifndef GL_EXT_gpu_program_parameters\n#define GL_EXT_gpu_program_parameters 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glProgramEnvParameters4fvEXT (GLenum, GLuint, GLsizei, const GLfloat *);\nGLAPI void APIENTRY glProgramLocalParameters4fvEXT (GLenum, GLuint, GLsizei, const GLfloat *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERS4FVEXTPROC) (GLenum target, GLuint index, GLsizei count, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERS4FVEXTPROC) (GLenum target, GLuint index, GLsizei count, const GLfloat *params);\n#endif\n\n#ifndef GL_APPLE_flush_buffer_range\n#define GL_APPLE_flush_buffer_range 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glBufferParameteriAPPLE (GLenum, GLenum, GLint);\nGLAPI void APIENTRY glFlushMappedBufferRangeAPPLE (GLenum, GLintptr, GLsizeiptr);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLBUFFERPARAMETERIAPPLEPROC) (GLenum target, GLenum pname, GLint param);\ntypedef void (APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC) (GLenum target, GLintptr offset, GLsizeiptr size);\n#endif\n\n#ifndef GL_NV_gpu_program4\n#define GL_NV_gpu_program4 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glProgramLocalParameterI4iNV (GLenum, GLuint, GLint, GLint, GLint, GLint);\nGLAPI void APIENTRY glProgramLocalParameterI4ivNV (GLenum, GLuint, const GLint *);\nGLAPI void APIENTRY glProgramLocalParametersI4ivNV (GLenum, GLuint, GLsizei, const GLint *);\nGLAPI void APIENTRY glProgramLocalParameterI4uiNV (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint);\nGLAPI void APIENTRY glProgramLocalParameterI4uivNV (GLenum, GLuint, const GLuint *);\nGLAPI void APIENTRY glProgramLocalParametersI4uivNV (GLenum, GLuint, GLsizei, const GLuint *);\nGLAPI void APIENTRY glProgramEnvParameterI4iNV (GLenum, GLuint, GLint, GLint, GLint, GLint);\nGLAPI void APIENTRY glProgramEnvParameterI4ivNV (GLenum, GLuint, const GLint *);\nGLAPI void APIENTRY glProgramEnvParametersI4ivNV (GLenum, GLuint, GLsizei, const GLint *);\nGLAPI void APIENTRY glProgramEnvParameterI4uiNV (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint);\nGLAPI void APIENTRY glProgramEnvParameterI4uivNV (GLenum, GLuint, const GLuint *);\nGLAPI void APIENTRY glProgramEnvParametersI4uivNV (GLenum, GLuint, GLsizei, const GLuint *);\nGLAPI void APIENTRY glGetProgramLocalParameterIivNV (GLenum, GLuint, GLint *);\nGLAPI void APIENTRY glGetProgramLocalParameterIuivNV (GLenum, GLuint, GLuint *);\nGLAPI void APIENTRY glGetProgramEnvParameterIivNV (GLenum, GLuint, GLint *);\nGLAPI void APIENTRY glGetProgramEnvParameterIuivNV (GLenum, GLuint, GLuint *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERI4INVPROC) (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w);\ntypedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERI4IVNVPROC) (GLenum target, GLuint index, const GLint *params);\ntypedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERSI4IVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLint *params);\ntypedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERI4UINVPROC) (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);\ntypedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERI4UIVNVPROC) (GLenum target, GLuint index, const GLuint *params);\ntypedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERSI4UIVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLuint *params);\ntypedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERI4INVPROC) (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w);\ntypedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERI4IVNVPROC) (GLenum target, GLuint index, const GLint *params);\ntypedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERSI4IVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLint *params);\ntypedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERI4UINVPROC) (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);\ntypedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERI4UIVNVPROC) (GLenum target, GLuint index, const GLuint *params);\ntypedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERSI4UIVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLuint *params);\ntypedef void (APIENTRYP PFNGLGETPROGRAMLOCALPARAMETERIIVNVPROC) (GLenum target, GLuint index, GLint *params);\ntypedef void (APIENTRYP PFNGLGETPROGRAMLOCALPARAMETERIUIVNVPROC) (GLenum target, GLuint index, GLuint *params);\ntypedef void (APIENTRYP PFNGLGETPROGRAMENVPARAMETERIIVNVPROC) (GLenum target, GLuint index, GLint *params);\ntypedef void (APIENTRYP PFNGLGETPROGRAMENVPARAMETERIUIVNVPROC) (GLenum target, GLuint index, GLuint *params);\n#endif\n\n#ifndef GL_NV_geometry_program4\n#define GL_NV_geometry_program4 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glProgramVertexLimitNV (GLenum, GLint);\nGLAPI void APIENTRY glFramebufferTextureEXT (GLenum, GLenum, GLuint, GLint);\nGLAPI void APIENTRY glFramebufferTextureLayerEXT (GLenum, GLenum, GLuint, GLint, GLint);\nGLAPI void APIENTRY glFramebufferTextureFaceEXT (GLenum, GLenum, GLuint, GLint, GLenum);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLPROGRAMVERTEXLIMITNVPROC) (GLenum target, GLint limit);\ntypedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREEXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level);\ntypedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);\ntypedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREFACEEXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face);\n#endif\n\n#ifndef GL_EXT_geometry_shader4\n#define GL_EXT_geometry_shader4 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glProgramParameteriEXT (GLuint, GLenum, GLint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLPROGRAMPARAMETERIEXTPROC) (GLuint program, GLenum pname, GLint value);\n#endif\n\n#ifndef GL_NV_vertex_program4\n#define GL_NV_vertex_program4 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glVertexAttribI1iEXT (GLuint, GLint);\nGLAPI void APIENTRY glVertexAttribI2iEXT (GLuint, GLint, GLint);\nGLAPI void APIENTRY glVertexAttribI3iEXT (GLuint, GLint, GLint, GLint);\nGLAPI void APIENTRY glVertexAttribI4iEXT (GLuint, GLint, GLint, GLint, GLint);\nGLAPI void APIENTRY glVertexAttribI1uiEXT (GLuint, GLuint);\nGLAPI void APIENTRY glVertexAttribI2uiEXT (GLuint, GLuint, GLuint);\nGLAPI void APIENTRY glVertexAttribI3uiEXT (GLuint, GLuint, GLuint, GLuint);\nGLAPI void APIENTRY glVertexAttribI4uiEXT (GLuint, GLuint, GLuint, GLuint, GLuint);\nGLAPI void APIENTRY glVertexAttribI1ivEXT (GLuint, const GLint *);\nGLAPI void APIENTRY glVertexAttribI2ivEXT (GLuint, const GLint *);\nGLAPI void APIENTRY glVertexAttribI3ivEXT (GLuint, const GLint *);\nGLAPI void APIENTRY glVertexAttribI4ivEXT (GLuint, const GLint *);\nGLAPI void APIENTRY glVertexAttribI1uivEXT (GLuint, const GLuint *);\nGLAPI void APIENTRY glVertexAttribI2uivEXT (GLuint, const GLuint *);\nGLAPI void APIENTRY glVertexAttribI3uivEXT (GLuint, const GLuint *);\nGLAPI void APIENTRY glVertexAttribI4uivEXT (GLuint, const GLuint *);\nGLAPI void APIENTRY glVertexAttribI4bvEXT (GLuint, const GLbyte *);\nGLAPI void APIENTRY glVertexAttribI4svEXT (GLuint, const GLshort *);\nGLAPI void APIENTRY glVertexAttribI4ubvEXT (GLuint, const GLubyte *);\nGLAPI void APIENTRY glVertexAttribI4usvEXT (GLuint, const GLushort *);\nGLAPI void APIENTRY glVertexAttribIPointerEXT (GLuint, GLint, GLenum, GLsizei, const GLvoid *);\nGLAPI void APIENTRY glGetVertexAttribIivEXT (GLuint, GLenum, GLint *);\nGLAPI void APIENTRY glGetVertexAttribIuivEXT (GLuint, GLenum, GLuint *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI1IEXTPROC) (GLuint index, GLint x);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI2IEXTPROC) (GLuint index, GLint x, GLint y);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI3IEXTPROC) (GLuint index, GLint x, GLint y, GLint z);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI4IEXTPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIEXTPROC) (GLuint index, GLuint x);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIEXTPROC) (GLuint index, GLuint x, GLuint y);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIEXTPROC) (GLuint index, GLuint x, GLuint y, GLuint z);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIEXTPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI1IVEXTPROC) (GLuint index, const GLint *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI2IVEXTPROC) (GLuint index, const GLint *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI3IVEXTPROC) (GLuint index, const GLint *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI4IVEXTPROC) (GLuint index, const GLint *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIVEXTPROC) (GLuint index, const GLuint *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIVEXTPROC) (GLuint index, const GLuint *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIVEXTPROC) (GLuint index, const GLuint *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIVEXTPROC) (GLuint index, const GLuint *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI4BVEXTPROC) (GLuint index, const GLbyte *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI4SVEXTPROC) (GLuint index, const GLshort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI4UBVEXTPROC) (GLuint index, const GLubyte *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBI4USVEXTPROC) (GLuint index, const GLushort *v);\ntypedef void (APIENTRYP PFNGLVERTEXATTRIBIPOINTEREXTPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);\ntypedef void (APIENTRYP PFNGLGETVERTEXATTRIBIIVEXTPROC) (GLuint index, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETVERTEXATTRIBIUIVEXTPROC) (GLuint index, GLenum pname, GLuint *params);\n#endif\n\n#ifndef GL_EXT_gpu_shader4\n#define GL_EXT_gpu_shader4 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glGetUniformuivEXT (GLuint, GLint, GLuint *);\nGLAPI void APIENTRY glBindFragDataLocationEXT (GLuint, GLuint, const GLchar *);\nGLAPI GLint APIENTRY glGetFragDataLocationEXT (GLuint, const GLchar *);\nGLAPI void APIENTRY glUniform1uiEXT (GLint, GLuint);\nGLAPI void APIENTRY glUniform2uiEXT (GLint, GLuint, GLuint);\nGLAPI void APIENTRY glUniform3uiEXT (GLint, GLuint, GLuint, GLuint);\nGLAPI void APIENTRY glUniform4uiEXT (GLint, GLuint, GLuint, GLuint, GLuint);\nGLAPI void APIENTRY glUniform1uivEXT (GLint, GLsizei, const GLuint *);\nGLAPI void APIENTRY glUniform2uivEXT (GLint, GLsizei, const GLuint *);\nGLAPI void APIENTRY glUniform3uivEXT (GLint, GLsizei, const GLuint *);\nGLAPI void APIENTRY glUniform4uivEXT (GLint, GLsizei, const GLuint *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLGETUNIFORMUIVEXTPROC) (GLuint program, GLint location, GLuint *params);\ntypedef void (APIENTRYP PFNGLBINDFRAGDATALOCATIONEXTPROC) (GLuint program, GLuint color, const GLchar *name);\ntypedef GLint (APIENTRYP PFNGLGETFRAGDATALOCATIONEXTPROC) (GLuint program, const GLchar *name);\ntypedef void (APIENTRYP PFNGLUNIFORM1UIEXTPROC) (GLint location, GLuint v0);\ntypedef void (APIENTRYP PFNGLUNIFORM2UIEXTPROC) (GLint location, GLuint v0, GLuint v1);\ntypedef void (APIENTRYP PFNGLUNIFORM3UIEXTPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2);\ntypedef void (APIENTRYP PFNGLUNIFORM4UIEXTPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);\ntypedef void (APIENTRYP PFNGLUNIFORM1UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value);\ntypedef void (APIENTRYP PFNGLUNIFORM2UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value);\ntypedef void (APIENTRYP PFNGLUNIFORM3UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value);\ntypedef void (APIENTRYP PFNGLUNIFORM4UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value);\n#endif\n\n#ifndef GL_EXT_draw_instanced\n#define GL_EXT_draw_instanced 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glDrawArraysInstancedEXT (GLenum, GLint, GLsizei, GLsizei);\nGLAPI void APIENTRY glDrawElementsInstancedEXT (GLenum, GLsizei, GLenum, const GLvoid *, GLsizei);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDEXTPROC) (GLenum mode, GLint start, GLsizei count, GLsizei primcount);\ntypedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDEXTPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount);\n#endif\n\n#ifndef GL_EXT_packed_float\n#define GL_EXT_packed_float 1\n#endif\n\n#ifndef GL_EXT_texture_array\n#define GL_EXT_texture_array 1\n#endif\n\n#ifndef GL_EXT_texture_buffer_object\n#define GL_EXT_texture_buffer_object 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glTexBufferEXT (GLenum, GLenum, GLuint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLTEXBUFFEREXTPROC) (GLenum target, GLenum internalformat, GLuint buffer);\n#endif\n\n#ifndef GL_EXT_texture_compression_latc\n#define GL_EXT_texture_compression_latc 1\n#endif\n\n#ifndef GL_EXT_texture_compression_rgtc\n#define GL_EXT_texture_compression_rgtc 1\n#endif\n\n#ifndef GL_EXT_texture_shared_exponent\n#define GL_EXT_texture_shared_exponent 1\n#endif\n\n#ifndef GL_NV_depth_buffer_float\n#define GL_NV_depth_buffer_float 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glDepthRangedNV (GLdouble, GLdouble);\nGLAPI void APIENTRY glClearDepthdNV (GLdouble);\nGLAPI void APIENTRY glDepthBoundsdNV (GLdouble, GLdouble);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLDEPTHRANGEDNVPROC) (GLdouble zNear, GLdouble zFar);\ntypedef void (APIENTRYP PFNGLCLEARDEPTHDNVPROC) (GLdouble depth);\ntypedef void (APIENTRYP PFNGLDEPTHBOUNDSDNVPROC) (GLdouble zmin, GLdouble zmax);\n#endif\n\n#ifndef GL_NV_fragment_program4\n#define GL_NV_fragment_program4 1\n#endif\n\n#ifndef GL_NV_framebuffer_multisample_coverage\n#define GL_NV_framebuffer_multisample_coverage 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glRenderbufferStorageMultisampleCoverageNV (GLenum, GLsizei, GLsizei, GLenum, GLsizei, GLsizei);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLECOVERAGENVPROC) (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height);\n#endif\n\n#ifndef GL_EXT_framebuffer_sRGB\n#define GL_EXT_framebuffer_sRGB 1\n#endif\n\n#ifndef GL_NV_geometry_shader4\n#define GL_NV_geometry_shader4 1\n#endif\n\n#ifndef GL_NV_parameter_buffer_object\n#define GL_NV_parameter_buffer_object 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glProgramBufferParametersfvNV (GLenum, GLuint, GLuint, GLsizei, const GLfloat *);\nGLAPI void APIENTRY glProgramBufferParametersIivNV (GLenum, GLuint, GLuint, GLsizei, const GLint *);\nGLAPI void APIENTRY glProgramBufferParametersIuivNV (GLenum, GLuint, GLuint, GLsizei, const GLuint *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLPROGRAMBUFFERPARAMETERSFVNVPROC) (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLfloat *params);\ntypedef void (APIENTRYP PFNGLPROGRAMBUFFERPARAMETERSIIVNVPROC) (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLint *params);\ntypedef void (APIENTRYP PFNGLPROGRAMBUFFERPARAMETERSIUIVNVPROC) (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLuint *params);\n#endif\n\n#ifndef GL_EXT_draw_buffers2\n#define GL_EXT_draw_buffers2 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glColorMaskIndexedEXT (GLuint, GLboolean, GLboolean, GLboolean, GLboolean);\nGLAPI void APIENTRY glGetBooleanIndexedvEXT (GLenum, GLuint, GLboolean *);\nGLAPI void APIENTRY glGetIntegerIndexedvEXT (GLenum, GLuint, GLint *);\nGLAPI void APIENTRY glEnableIndexedEXT (GLenum, GLuint);\nGLAPI void APIENTRY glDisableIndexedEXT (GLenum, GLuint);\nGLAPI GLboolean APIENTRY glIsEnabledIndexedEXT (GLenum, GLuint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLCOLORMASKINDEXEDEXTPROC) (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);\ntypedef void (APIENTRYP PFNGLGETBOOLEANINDEXEDVEXTPROC) (GLenum target, GLuint index, GLboolean *data);\ntypedef void (APIENTRYP PFNGLGETINTEGERINDEXEDVEXTPROC) (GLenum target, GLuint index, GLint *data);\ntypedef void (APIENTRYP PFNGLENABLEINDEXEDEXTPROC) (GLenum target, GLuint index);\ntypedef void (APIENTRYP PFNGLDISABLEINDEXEDEXTPROC) (GLenum target, GLuint index);\ntypedef GLboolean (APIENTRYP PFNGLISENABLEDINDEXEDEXTPROC) (GLenum target, GLuint index);\n#endif\n\n#ifndef GL_NV_transform_feedback\n#define GL_NV_transform_feedback 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glBeginTransformFeedbackNV (GLenum);\nGLAPI void APIENTRY glEndTransformFeedbackNV (void);\nGLAPI void APIENTRY glTransformFeedbackAttribsNV (GLuint, const GLint *, GLenum);\nGLAPI void APIENTRY glBindBufferRangeNV (GLenum, GLuint, GLuint, GLintptr, GLsizeiptr);\nGLAPI void APIENTRY glBindBufferOffsetNV (GLenum, GLuint, GLuint, GLintptr);\nGLAPI void APIENTRY glBindBufferBaseNV (GLenum, GLuint, GLuint);\nGLAPI void APIENTRY glTransformFeedbackVaryingsNV (GLuint, GLsizei, const GLint *, GLenum);\nGLAPI void APIENTRY glActiveVaryingNV (GLuint, const GLchar *);\nGLAPI GLint APIENTRY glGetVaryingLocationNV (GLuint, const GLchar *);\nGLAPI void APIENTRY glGetActiveVaryingNV (GLuint, GLuint, GLsizei, GLsizei *, GLsizei *, GLenum *, GLchar *);\nGLAPI void APIENTRY glGetTransformFeedbackVaryingNV (GLuint, GLuint, GLint *);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLBEGINTRANSFORMFEEDBACKNVPROC) (GLenum primitiveMode);\ntypedef void (APIENTRYP PFNGLENDTRANSFORMFEEDBACKNVPROC) (void);\ntypedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKATTRIBSNVPROC) (GLuint count, const GLint *attribs, GLenum bufferMode);\ntypedef void (APIENTRYP PFNGLBINDBUFFERRANGENVPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);\ntypedef void (APIENTRYP PFNGLBINDBUFFEROFFSETNVPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset);\ntypedef void (APIENTRYP PFNGLBINDBUFFERBASENVPROC) (GLenum target, GLuint index, GLuint buffer);\ntypedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSNVPROC) (GLuint program, GLsizei count, const GLint *locations, GLenum bufferMode);\ntypedef void (APIENTRYP PFNGLACTIVEVARYINGNVPROC) (GLuint program, const GLchar *name);\ntypedef GLint (APIENTRYP PFNGLGETVARYINGLOCATIONNVPROC) (GLuint program, const GLchar *name);\ntypedef void (APIENTRYP PFNGLGETACTIVEVARYINGNVPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);\ntypedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKVARYINGNVPROC) (GLuint program, GLuint index, GLint *location);\n#endif\n\n#ifndef GL_EXT_bindable_uniform\n#define GL_EXT_bindable_uniform 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glUniformBufferEXT (GLuint, GLint, GLuint);\nGLAPI GLint APIENTRY glGetUniformBufferSizeEXT (GLuint, GLint);\nGLAPI GLintptr APIENTRY glGetUniformOffsetEXT (GLuint, GLint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLUNIFORMBUFFEREXTPROC) (GLuint program, GLint location, GLuint buffer);\ntypedef GLint (APIENTRYP PFNGLGETUNIFORMBUFFERSIZEEXTPROC) (GLuint program, GLint location);\ntypedef GLintptr (APIENTRYP PFNGLGETUNIFORMOFFSETEXTPROC) (GLuint program, GLint location);\n#endif\n\n#ifndef GL_EXT_texture_integer\n#define GL_EXT_texture_integer 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glTexParameterIivEXT (GLenum, GLenum, const GLint *);\nGLAPI void APIENTRY glTexParameterIuivEXT (GLenum, GLenum, const GLuint *);\nGLAPI void APIENTRY glGetTexParameterIivEXT (GLenum, GLenum, GLint *);\nGLAPI void APIENTRY glGetTexParameterIuivEXT (GLenum, GLenum, GLuint *);\nGLAPI void APIENTRY glClearColorIiEXT (GLint, GLint, GLint, GLint);\nGLAPI void APIENTRY glClearColorIuiEXT (GLuint, GLuint, GLuint, GLuint);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, const GLint *params);\ntypedef void (APIENTRYP PFNGLTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, const GLuint *params);\ntypedef void (APIENTRYP PFNGLGETTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, GLint *params);\ntypedef void (APIENTRYP PFNGLGETTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, GLuint *params);\ntypedef void (APIENTRYP PFNGLCLEARCOLORIIEXTPROC) (GLint red, GLint green, GLint blue, GLint alpha);\ntypedef void (APIENTRYP PFNGLCLEARCOLORIUIEXTPROC) (GLuint red, GLuint green, GLuint blue, GLuint alpha);\n#endif\n\n#ifndef GL_GREMEDY_frame_terminator\n#define GL_GREMEDY_frame_terminator 1\n#ifdef GL_GLEXT_PROTOTYPES\nGLAPI void APIENTRY glFrameTerminatorGREMEDY (void);\n#endif /* GL_GLEXT_PROTOTYPES */\ntypedef void (APIENTRYP PFNGLFRAMETERMINATORGREMEDYPROC) (void);\n#endif\n\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* GL_GLEXT_LEGACY */\n#endif /* NO_SDL_GLEXT */\n"
  },
  {
    "path": "deps/include/SDL/SDL_platform.h",
    "content": "/*\n    SDL - Simple DirectMedia Layer\n    Copyright (C) 1997-2012 Sam Lantinga\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Lesser General Public\n    License as published by the Free Software Foundation; either\n    version 2.1 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public\n    License along with this library; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n\n    Sam Lantinga\n    slouken@libsdl.org\n*/\n\n/** @file SDL_platform.h\n *  Try to get a standard set of platform defines\n */\n\n#ifndef _SDL_platform_h\n#define _SDL_platform_h\n\n#if defined(_AIX)\n#undef __AIX__\n#define __AIX__\t\t1\n#endif\n#if defined(__BEOS__)\n#undef __BEOS__\n#define __BEOS__\t1\n#endif\n#if defined(__HAIKU__)\n#undef __HAIKU__\n#define __HAIKU__ 1\n#endif\n#if defined(bsdi) || defined(__bsdi) || defined(__bsdi__)\n#undef __BSDI__\n#define __BSDI__\t1\n#endif\n#if defined(_arch_dreamcast)\n#undef __DREAMCAST__\n#define __DREAMCAST__\t1\n#endif\n#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)\n#undef __FREEBSD__\n#define __FREEBSD__\t1\n#endif\n#if defined(__HAIKU__)\n#undef __HAIKU__\n#define __HAIKU__\t1\n#endif\n#if defined(hpux) || defined(__hpux) || defined(__hpux__)\n#undef __HPUX__\n#define __HPUX__\t1\n#endif\n#if defined(sgi) || defined(__sgi) || defined(__sgi__) || defined(_SGI_SOURCE)\n#undef __IRIX__\n#define __IRIX__\t1\n#endif\n#if defined(linux) || defined(__linux) || defined(__linux__)\n#undef __LINUX__\n#define __LINUX__\t1\n#endif\n#if defined(__APPLE__)\n#undef __MACOSX__\n#define __MACOSX__\t1\n#elif defined(macintosh)\n#undef __MACOS__\n#define __MACOS__\t1\n#endif\n#if defined(__NetBSD__)\n#undef __NETBSD__\n#define __NETBSD__\t1\n#endif\n#if defined(__OpenBSD__)\n#undef __OPENBSD__\n#define __OPENBSD__\t1\n#endif\n#if defined(__OS2__) || defined(__EMX__)\n#undef __OS2__\n#define __OS2__\t\t1\n#endif\n#if defined(osf) || defined(__osf) || defined(__osf__) || defined(_OSF_SOURCE)\n#undef __OSF__\n#define __OSF__\t\t1\n#endif\n#if defined(__QNXNTO__)\n#undef __QNXNTO__\n#define __QNXNTO__\t1\n#endif\n#if defined(riscos) || defined(__riscos) || defined(__riscos__)\n#undef __RISCOS__\n#define __RISCOS__\t1\n#endif\n#if defined(__SVR4)\n#undef __SOLARIS__\n#define __SOLARIS__\t1\n#endif\n#if defined(WIN32) || defined(_WIN32)\n#undef __WIN32__\n#define __WIN32__\t1\n#endif\n\n#endif /* _SDL_platform_h */\n"
  },
  {
    "path": "deps/include/SDL/SDL_quit.h",
    "content": "/*\n    SDL - Simple DirectMedia Layer\n    Copyright (C) 1997-2012 Sam Lantinga\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Lesser General Public\n    License as published by the Free Software Foundation; either\n    version 2.1 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public\n    License along with this library; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n\n    Sam Lantinga\n    slouken@libsdl.org\n*/\n\n/** @file SDL_quit.h\n *  Include file for SDL quit event handling\n */\n\n#ifndef _SDL_quit_h\n#define _SDL_quit_h\n\n#include \"SDL_stdinc.h\"\n#include \"SDL_error.h\"\n\n/** @file SDL_quit.h\n *  An SDL_QUITEVENT is generated when the user tries to close the application\n *  window.  If it is ignored or filtered out, the window will remain open.\n *  If it is not ignored or filtered, it is queued normally and the window\n *  is allowed to close.  When the window is closed, screen updates will \n *  complete, but have no effect.\n *\n *  SDL_Init() installs signal handlers for SIGINT (keyboard interrupt)\n *  and SIGTERM (system termination request), if handlers do not already\n *  exist, that generate SDL_QUITEVENT events as well.  There is no way\n *  to determine the cause of an SDL_QUITEVENT, but setting a signal\n *  handler in your application will override the default generation of\n *  quit events for that signal.\n */\n\n/** @file SDL_quit.h\n *  There are no functions directly affecting the quit event \n */\n\n#define SDL_QuitRequested() \\\n        (SDL_PumpEvents(), SDL_PeepEvents(NULL,0,SDL_PEEKEVENT,SDL_QUITMASK))\n\n#endif /* _SDL_quit_h */\n"
  },
  {
    "path": "deps/include/SDL/SDL_rotozoom.h",
    "content": "/*  \n\nSDL_rotozoom.c: rotozoomer, zoomer and shrinker for 32bit or 8bit surfaces\n\nCopyright (C) 2001-2012  Andreas Schiffler\n\nThis software is provided 'as-is', without any express or implied\nwarranty. In no event will the authors be held liable for any damages\narising from the use of this software.\n\nPermission is granted to anyone to use this software for any purpose,\nincluding commercial applications, and to alter it and redistribute it\nfreely, subject to the following restrictions:\n\n1. The origin of this software must not be misrepresented; you must not\nclaim that you wrote the original software. If you use this software\nin a product, an acknowledgment in the product documentation would be\nappreciated but is not required.\n\n2. Altered source versions must be plainly marked as such, and must not be\nmisrepresented as being the original software.\n\n3. This notice may not be removed or altered from any source\ndistribution.\n\nAndreas Schiffler -- aschiffler at ferzkopp dot net\n\n*/\n\n#ifndef _SDL_rotozoom_h\n#define _SDL_rotozoom_h\n\n#include <math.h>\n\n/* Set up for C function definitions, even when using C++ */\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#ifndef M_PI\n#define M_PI\t3.141592654\n#endif\n\n#include <SDL.h>\n\n\t/* ---- Defines */\n\n\t/*!\n\t\\brief Disable anti-aliasing (no smoothing).\n\t*/\n#define SMOOTHING_OFF\t\t0\n\n\t/*!\n\t\\brief Enable anti-aliasing (smoothing).\n\t*/\n#define SMOOTHING_ON\t\t1\n\n\t/* ---- Function Prototypes */\n\n#ifdef _MSC_VER\n#  if defined(DLL_EXPORT) && !defined(LIBSDL_GFX_DLL_IMPORT)\n#    define SDL_ROTOZOOM_SCOPE __declspec(dllexport)\n#  else\n#    ifdef LIBSDL_GFX_DLL_IMPORT\n#      define SDL_ROTOZOOM_SCOPE __declspec(dllimport)\n#    endif\n#  endif\n#endif\n#ifndef SDL_ROTOZOOM_SCOPE\n#  define SDL_ROTOZOOM_SCOPE extern\n#endif\n\n\t/* \n\n\tRotozoom functions\n\n\t*/\n\n\tSDL_ROTOZOOM_SCOPE SDL_Surface *rotozoomSurface(SDL_Surface * src, double angle, double zoom, int smooth);\n\n\tSDL_ROTOZOOM_SCOPE SDL_Surface *rotozoomSurfaceXY\n\t\t(SDL_Surface * src, double angle, double zoomx, double zoomy, int smooth);\n\n\n\tSDL_ROTOZOOM_SCOPE void rotozoomSurfaceSize(int width, int height, double angle, double zoom, int *dstwidth,\n\t\tint *dstheight);\n\n\tSDL_ROTOZOOM_SCOPE void rotozoomSurfaceSizeXY\n\t\t(int width, int height, double angle, double zoomx, double zoomy, \n\t\tint *dstwidth, int *dstheight);\n\n\t/* \n\n\tZooming functions\n\n\t*/\n\n\tSDL_ROTOZOOM_SCOPE SDL_Surface *zoomSurface(SDL_Surface * src, double zoomx, double zoomy, int smooth);\n\n\tSDL_ROTOZOOM_SCOPE void zoomSurfaceSize(int width, int height, double zoomx, double zoomy, int *dstwidth, int *dstheight);\n\n\t/* \n\n\tShrinking functions\n\n\t*/     \n\n\tSDL_ROTOZOOM_SCOPE SDL_Surface *shrinkSurface(SDL_Surface * src, int factorx, int factory);\n\n\t/* \n\n\tSpecialized rotation functions\n\n\t*/\n\n\tSDL_ROTOZOOM_SCOPE SDL_Surface* rotateSurface90Degrees(SDL_Surface* src, int numClockwiseTurns);\n\n\t/* Ends C function definitions when using C++ */\n#ifdef __cplusplus\n}\n#endif\n\n#endif\t\t\t\t/* _SDL_rotozoom_h */\n"
  },
  {
    "path": "deps/include/SDL/SDL_rwops.h",
    "content": "/*\n    SDL - Simple DirectMedia Layer\n    Copyright (C) 1997-2012 Sam Lantinga\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Lesser General Public\n    License as published by the Free Software Foundation; either\n    version 2.1 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public\n    License along with this library; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n\n    Sam Lantinga\n    slouken@libsdl.org\n*/\n\n/** @file SDL_rwops.h\n *  This file provides a general interface for SDL to read and write\n *  data sources.  It can easily be extended to files, memory, etc.\n */\n\n#ifndef _SDL_rwops_h\n#define _SDL_rwops_h\n\n#include \"SDL_stdinc.h\"\n#include \"SDL_error.h\"\n\n#include \"begin_code.h\"\n/* Set up for C function definitions, even when using C++ */\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/** This is the read/write operation structure -- very basic */\n\ntypedef struct SDL_RWops {\n\t/** Seek to 'offset' relative to whence, one of stdio's whence values:\n\t *\tSEEK_SET, SEEK_CUR, SEEK_END\n\t *  Returns the final offset in the data source.\n\t */\n\tint (SDLCALL *seek)(struct SDL_RWops *context, int offset, int whence);\n\n\t/** Read up to 'maxnum' objects each of size 'size' from the data\n\t *  source to the area pointed at by 'ptr'.\n\t *  Returns the number of objects read, or -1 if the read failed.\n\t */\n\tint (SDLCALL *read)(struct SDL_RWops *context, void *ptr, int size, int maxnum);\n\n\t/** Write exactly 'num' objects each of size 'objsize' from the area\n\t *  pointed at by 'ptr' to data source.\n\t *  Returns 'num', or -1 if the write failed.\n\t */\n\tint (SDLCALL *write)(struct SDL_RWops *context, const void *ptr, int size, int num);\n\n\t/** Close and free an allocated SDL_FSops structure */\n\tint (SDLCALL *close)(struct SDL_RWops *context);\n\n\tUint32 type;\n\tunion {\n#if defined(__WIN32__) && !defined(__SYMBIAN32__)\n\t    struct {\n\t\tint   append;\n\t\tvoid *h;\n\t\tstruct {\n\t\t    void *data;\n\t\t    int size;\n\t\t    int left;\n\t\t} buffer;\n\t    } win32io;\n#endif\n#ifdef HAVE_STDIO_H \n\t    struct {\n\t\tint autoclose;\n\t \tFILE *fp;\n\t    } stdio;\n#endif\n\t    struct {\n\t\tUint8 *base;\n\t \tUint8 *here;\n\t\tUint8 *stop;\n\t    } mem;\n\t    struct {\n\t\tvoid *data1;\n\t    } unknown;\n\t} hidden;\n\n} SDL_RWops;\n\n\n/** @name Functions to create SDL_RWops structures from various data sources */\n/*@{*/\n\nextern DECLSPEC SDL_RWops * SDLCALL SDL_RWFromFile(const char *file, const char *mode);\n\n#ifdef HAVE_STDIO_H\nextern DECLSPEC SDL_RWops * SDLCALL SDL_RWFromFP(FILE *fp, int autoclose);\n#endif\n\nextern DECLSPEC SDL_RWops * SDLCALL SDL_RWFromMem(void *mem, int size);\nextern DECLSPEC SDL_RWops * SDLCALL SDL_RWFromConstMem(const void *mem, int size);\n\nextern DECLSPEC SDL_RWops * SDLCALL SDL_AllocRW(void);\nextern DECLSPEC void SDLCALL SDL_FreeRW(SDL_RWops *area);\n\n/*@}*/\n\n/** @name Seek Reference Points */\n/*@{*/\n#define RW_SEEK_SET\t0\t/**< Seek from the beginning of data */\n#define RW_SEEK_CUR\t1\t/**< Seek relative to current read point */\n#define RW_SEEK_END\t2\t/**< Seek relative to the end of data */\n/*@}*/\n\n/** @name Macros to easily read and write from an SDL_RWops structure */\n/*@{*/\n#define SDL_RWseek(ctx, offset, whence)\t(ctx)->seek(ctx, offset, whence)\n#define SDL_RWtell(ctx)\t\t\t(ctx)->seek(ctx, 0, RW_SEEK_CUR)\n#define SDL_RWread(ctx, ptr, size, n)\t(ctx)->read(ctx, ptr, size, n)\n#define SDL_RWwrite(ctx, ptr, size, n)\t(ctx)->write(ctx, ptr, size, n)\n#define SDL_RWclose(ctx)\t\t(ctx)->close(ctx)\n/*@}*/\n\n/** @name Read an item of the specified endianness and return in native format */\n/*@{*/\nextern DECLSPEC Uint16 SDLCALL SDL_ReadLE16(SDL_RWops *src);\nextern DECLSPEC Uint16 SDLCALL SDL_ReadBE16(SDL_RWops *src);\nextern DECLSPEC Uint32 SDLCALL SDL_ReadLE32(SDL_RWops *src);\nextern DECLSPEC Uint32 SDLCALL SDL_ReadBE32(SDL_RWops *src);\nextern DECLSPEC Uint64 SDLCALL SDL_ReadLE64(SDL_RWops *src);\nextern DECLSPEC Uint64 SDLCALL SDL_ReadBE64(SDL_RWops *src);\n/*@}*/\n\n/** @name Write an item of native format to the specified endianness */\n/*@{*/\nextern DECLSPEC int SDLCALL SDL_WriteLE16(SDL_RWops *dst, Uint16 value);\nextern DECLSPEC int SDLCALL SDL_WriteBE16(SDL_RWops *dst, Uint16 value);\nextern DECLSPEC int SDLCALL SDL_WriteLE32(SDL_RWops *dst, Uint32 value);\nextern DECLSPEC int SDLCALL SDL_WriteBE32(SDL_RWops *dst, Uint32 value);\nextern DECLSPEC int SDLCALL SDL_WriteLE64(SDL_RWops *dst, Uint64 value);\nextern DECLSPEC int SDLCALL SDL_WriteBE64(SDL_RWops *dst, Uint64 value);\n/*@}*/\n\n/* Ends C function definitions when using C++ */\n#ifdef __cplusplus\n}\n#endif\n#include \"close_code.h\"\n\n#endif /* _SDL_rwops_h */\n"
  },
  {
    "path": "deps/include/SDL/SDL_stdinc.h",
    "content": "/*\n    SDL - Simple DirectMedia Layer\n    Copyright (C) 1997-2012 Sam Lantinga\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Lesser General Public\n    License as published by the Free Software Foundation; either\n    version 2.1 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public\n    License along with this library; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n\n    Sam Lantinga\n    slouken@libsdl.org\n*/\n\n/** @file SDL_stdinc.h\n *  This is a general header that includes C language support\n */\n\n#ifndef _SDL_stdinc_h\n#define _SDL_stdinc_h\n\n#include \"SDL_config.h\"\n\n\n#ifdef HAVE_SYS_TYPES_H\n#include <sys/types.h>\n#endif\n#ifdef HAVE_STDIO_H\n#include <stdio.h>\n#endif\n#if defined(STDC_HEADERS)\n# include <stdlib.h>\n# include <stddef.h>\n# include <stdarg.h>\n#else\n# if defined(HAVE_STDLIB_H)\n#  include <stdlib.h>\n# elif defined(HAVE_MALLOC_H)\n#  include <malloc.h>\n# endif\n# if defined(HAVE_STDDEF_H)\n#  include <stddef.h>\n# endif\n# if defined(HAVE_STDARG_H)\n#  include <stdarg.h>\n# endif\n#endif\n#ifdef HAVE_STRING_H\n# if !defined(STDC_HEADERS) && defined(HAVE_MEMORY_H)\n#  include <memory.h>\n# endif\n# include <string.h>\n#endif\n#ifdef HAVE_STRINGS_H\n# include <strings.h>\n#endif\n#if defined(HAVE_INTTYPES_H)\n# include <inttypes.h>\n#elif defined(HAVE_STDINT_H)\n# include <stdint.h>\n#endif\n#ifdef HAVE_CTYPE_H\n# include <ctype.h>\n#endif\n#if defined(HAVE_ICONV) && defined(HAVE_ICONV_H)\n# include <iconv.h>\n#endif\n#if defined(HAVE_ALLOCA) && !defined(alloca)\n# if defined(HAVE_ALLOCA_H)\n#  include <alloca.h>\n# elif defined(__GNUC__)\n#  define alloca __builtin_alloca\n# elif defined(_MSC_VER)\n#  include <malloc.h>\n#  define alloca _alloca\n# elif defined(__WATCOMC__)\n#  include <malloc.h>\n# elif defined(__BORLANDC__)\n#  include <malloc.h>\n# elif defined(__DMC__)\n#  include <stdlib.h>\n# elif defined(__AIX__)\n  #pragma alloca\n# elif defined(__MRC__)\n   void *alloca (unsigned);\n# else\n   char *alloca ();\n# endif\n#endif\n\n/** The number of elements in an array */\n#define SDL_arraysize(array)\t(sizeof(array)/sizeof(array[0]))\n#define SDL_TABLESIZE(table)\tSDL_arraysize(table)\n\n/* Use proper C++ casts when compiled as C++ to be compatible with the option\n -Wold-style-cast of GCC (and -Werror=old-style-cast in GCC 4.2 and above. */\n#ifdef __cplusplus\n#define SDL_reinterpret_cast(type, expression) reinterpret_cast<type>(expression)\n#define SDL_static_cast(type, expression) static_cast<type>(expression)\n#else\n#define SDL_reinterpret_cast(type, expression) ((type)(expression))\n#define SDL_static_cast(type, expression) ((type)(expression))\n#endif\n\n/** @name Basic data types */\n/*@{*/\ntypedef enum {\n\tSDL_FALSE = 0,\n\tSDL_TRUE  = 1\n} SDL_bool;\n\ntypedef int8_t\t\tSint8;\ntypedef uint8_t\t\tUint8;\ntypedef int16_t\t\tSint16;\ntypedef uint16_t\tUint16;\ntypedef int32_t\t\tSint32;\ntypedef uint32_t\tUint32;\n\n#ifdef SDL_HAS_64BIT_TYPE\ntypedef int64_t\t\tSint64;\n#ifndef SYMBIAN32_GCCE\ntypedef uint64_t\tUint64;\n#endif\n#else\n/* This is really just a hack to prevent the compiler from complaining */\ntypedef struct {\n\tUint32 hi;\n\tUint32 lo;\n} Uint64, Sint64;\n#endif\n\n/*@}*/\n\n/** @name Make sure the types really have the right sizes */\n/*@{*/\n#define SDL_COMPILE_TIME_ASSERT(name, x)               \\\n       typedef int SDL_dummy_ ## name[(x) * 2 - 1]\n\nSDL_COMPILE_TIME_ASSERT(uint8, sizeof(Uint8) == 1);\nSDL_COMPILE_TIME_ASSERT(sint8, sizeof(Sint8) == 1);\nSDL_COMPILE_TIME_ASSERT(uint16, sizeof(Uint16) == 2);\nSDL_COMPILE_TIME_ASSERT(sint16, sizeof(Sint16) == 2);\nSDL_COMPILE_TIME_ASSERT(uint32, sizeof(Uint32) == 4);\nSDL_COMPILE_TIME_ASSERT(sint32, sizeof(Sint32) == 4);\nSDL_COMPILE_TIME_ASSERT(uint64, sizeof(Uint64) == 8);\nSDL_COMPILE_TIME_ASSERT(sint64, sizeof(Sint64) == 8);\n/*@}*/\n\n/** @name Enum Size Check\n *  Check to make sure enums are the size of ints, for structure packing.\n *  For both Watcom C/C++ and Borland C/C++ the compiler option that makes\n *  enums having the size of an int must be enabled.\n *  This is \"-b\" for Borland C/C++ and \"-ei\" for Watcom C/C++ (v11).\n */\n/* Enable enums always int in CodeWarrior (for MPW use \"-enum int\") */\n#ifdef __MWERKS__\n#pragma enumsalwaysint on\n#endif\n\ntypedef enum {\n\tDUMMY_ENUM_VALUE\n} SDL_DUMMY_ENUM;\n\n#ifndef __NDS__\nSDL_COMPILE_TIME_ASSERT(enum, sizeof(SDL_DUMMY_ENUM) == sizeof(int));\n#endif\n/*@}*/\n\n#include \"begin_code.h\"\n/* Set up for C function definitions, even when using C++ */\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#ifdef HAVE_MALLOC\n#define SDL_malloc\tmalloc\n#else\nextern DECLSPEC void * SDLCALL SDL_malloc(size_t size);\n#endif\n\n#ifdef HAVE_CALLOC\n#define SDL_calloc\tcalloc\n#else\nextern DECLSPEC void * SDLCALL SDL_calloc(size_t nmemb, size_t size);\n#endif\n\n#ifdef HAVE_REALLOC\n#define SDL_realloc\trealloc\n#else\nextern DECLSPEC void * SDLCALL SDL_realloc(void *mem, size_t size);\n#endif\n\n#ifdef HAVE_FREE\n#define SDL_free\tfree\n#else\nextern DECLSPEC void SDLCALL SDL_free(void *mem);\n#endif\n\n#ifdef HAVE_ALLOCA\n#define SDL_stack_alloc(type, count)    (type*)alloca(sizeof(type)*(count))\n#define SDL_stack_free(data)\n#else\n#define SDL_stack_alloc(type, count)    (type*)SDL_malloc(sizeof(type)*(count))\n#define SDL_stack_free(data)            SDL_free(data)\n#endif\n\n#ifdef HAVE_GETENV\n#define SDL_getenv\tgetenv\n#else\nextern DECLSPEC char * SDLCALL SDL_getenv(const char *name);\n#endif\n\n#ifdef HAVE_PUTENV\n#define SDL_putenv\tputenv\n#else\nextern DECLSPEC int SDLCALL SDL_putenv(const char *variable);\n#endif\n\n#ifdef HAVE_QSORT\n#define SDL_qsort\tqsort\n#else\nextern DECLSPEC void SDLCALL SDL_qsort(void *base, size_t nmemb, size_t size,\n           int (*compare)(const void *, const void *));\n#endif\n\n#ifdef HAVE_ABS\n#define SDL_abs\t\tabs\n#else\n#define SDL_abs(X)\t((X) < 0 ? -(X) : (X))\n#endif\n\n#define SDL_min(x, y)\t(((x) < (y)) ? (x) : (y))\n#define SDL_max(x, y)\t(((x) > (y)) ? (x) : (y))\n\n#ifdef HAVE_CTYPE_H\n#define SDL_isdigit(X)  isdigit(X)\n#define SDL_isspace(X)  isspace(X)\n#define SDL_toupper(X)  toupper(X)\n#define SDL_tolower(X)  tolower(X)\n#else\n#define SDL_isdigit(X)  (((X) >= '0') && ((X) <= '9'))\n#define SDL_isspace(X)  (((X) == ' ') || ((X) == '\\t') || ((X) == '\\r') || ((X) == '\\n'))\n#define SDL_toupper(X)  (((X) >= 'a') && ((X) <= 'z') ? ('A'+((X)-'a')) : (X))\n#define SDL_tolower(X)  (((X) >= 'A') && ((X) <= 'Z') ? ('a'+((X)-'A')) : (X))\n#endif\n\n#ifdef HAVE_MEMSET\n#define SDL_memset      memset\n#else\nextern DECLSPEC void * SDLCALL SDL_memset(void *dst, int c, size_t len);\n#endif\n\n#if defined(__GNUC__) && defined(__i386__)\n#define SDL_memset4(dst, val, len)\t\t\t\t\\\ndo {\t\t\t\t\t\t\t\t\\\n\tint u0, u1, u2;\t\t\t\t\t\t\\\n\t__asm__ __volatile__ (\t\t\t\t\t\\\n\t\t\"cld\\n\\t\"\t\t\t\t\t\\\n\t\t\"rep ; stosl\\n\\t\"\t\t\t\t\\\n\t\t: \"=&D\" (u0), \"=&a\" (u1), \"=&c\" (u2)\t\t\\\n\t\t: \"0\" (dst), \"1\" (val), \"2\" (SDL_static_cast(Uint32, len))\t\\\n\t\t: \"memory\" );\t\t\t\t\t\\\n} while(0)\n#endif\n#ifndef SDL_memset4\n#define SDL_memset4(dst, val, len)\t\t\\\ndo {\t\t\t\t\t\t\\\n\tunsigned _count = (len);\t\t\\\n\tunsigned _n = (_count + 3) / 4;\t\t\\\n\tUint32 *_p = SDL_static_cast(Uint32 *, dst);\t\\\n\tUint32 _val = (val);\t\t\t\\\n\tif (len == 0) break;\t\t\t\\\n        switch (_count % 4) {\t\t\t\\\n        case 0: do {    *_p++ = _val;\t\t\\\n        case 3:         *_p++ = _val;\t\t\\\n        case 2:         *_p++ = _val;\t\t\\\n        case 1:         *_p++ = _val;\t\t\\\n\t\t} while ( --_n );\t\t\\\n\t}\t\t\t\t\t\\\n} while(0)\n#endif\n\n/* We can count on memcpy existing on Mac OS X and being well-tuned. */\n#if defined(__MACH__) && defined(__APPLE__)\n#define SDL_memcpy(dst, src, len) memcpy(dst, src, len)\n#elif defined(__GNUC__) && defined(__i386__)\n#define SDL_memcpy(dst, src, len)\t\t\t\t\t  \\\ndo {\t\t\t\t\t\t\t\t\t  \\\n\tint u0, u1, u2;\t\t\t\t\t\t  \t  \\\n\t__asm__ __volatile__ (\t\t\t\t\t\t  \\\n\t\t\"cld\\n\\t\"\t\t\t\t\t\t  \\\n\t\t\"rep ; movsl\\n\\t\"\t\t\t\t\t  \\\n\t\t\"testb $2,%b4\\n\\t\"\t\t\t\t\t  \\\n\t\t\"je 1f\\n\\t\"\t\t\t\t\t\t  \\\n\t\t\"movsw\\n\"\t\t\t\t\t\t  \\\n\t\t\"1:\\ttestb $1,%b4\\n\\t\"\t\t\t\t\t  \\\n\t\t\"je 2f\\n\\t\"\t\t\t\t\t\t  \\\n\t\t\"movsb\\n\"\t\t\t\t\t\t  \\\n\t\t\"2:\"\t\t\t\t\t\t\t  \\\n\t\t: \"=&c\" (u0), \"=&D\" (u1), \"=&S\" (u2)\t\t\t  \\\n\t\t: \"0\" (SDL_static_cast(unsigned, len)/4), \"q\" (len), \"1\" (dst),\"2\" (src) \\\n\t\t: \"memory\" );\t\t\t\t\t\t  \\\n} while(0)\n#endif\n#ifndef SDL_memcpy\n#ifdef HAVE_MEMCPY\n#define SDL_memcpy      memcpy\n#elif defined(HAVE_BCOPY)\n#define SDL_memcpy(d, s, n)\tbcopy((s), (d), (n))\n#else\nextern DECLSPEC void * SDLCALL SDL_memcpy(void *dst, const void *src, size_t len);\n#endif\n#endif\n\n/* We can count on memcpy existing on Mac OS X and being well-tuned. */\n#if defined(__MACH__) && defined(__APPLE__)\n#define SDL_memcpy4(dst, src, len) memcpy(dst, src, (len)*4)\n#elif defined(__GNUC__) && defined(__i386__)\n#define SDL_memcpy4(dst, src, len)\t\t\t\t\\\ndo {\t\t\t\t\t\t\t\t\\\n\tint ecx, edi, esi;\t\t\t\t\t\\\n\t__asm__ __volatile__ (\t\t\t\t\t\\\n\t\t\"cld\\n\\t\"\t\t\t\t\t\\\n\t\t\"rep ; movsl\"\t\t\t\t\t\\\n\t\t: \"=&c\" (ecx), \"=&D\" (edi), \"=&S\" (esi)\t\t\\\n\t\t: \"0\" (SDL_static_cast(unsigned, len)), \"1\" (dst), \"2\" (src)\t\\\n\t\t: \"memory\" );\t\t\t\t\t\\\n} while(0)\n#endif\n#ifndef SDL_memcpy4\n#define SDL_memcpy4(dst, src, len)\tSDL_memcpy(dst, src, (len) << 2)\n#endif\n\n#if defined(__GNUC__) && defined(__i386__)\n#define SDL_revcpy(dst, src, len)\t\t\t\\\ndo {\t\t\t\t\t\t\t\\\n\tint u0, u1, u2;\t\t\t\t\t\\\n\tchar *dstp = SDL_static_cast(char *, dst);\t\\\n\tchar *srcp = SDL_static_cast(char *, src);\t\\\n\tint n = (len);\t\t\t\t\t\\\n\tif ( n >= 4 ) {\t\t\t\t\t\\\n\t__asm__ __volatile__ (\t\t\t\t\\\n\t\t\"std\\n\\t\"\t\t\t\t\\\n\t\t\"rep ; movsl\\n\\t\"\t\t\t\\\n\t\t\"cld\\n\\t\"\t\t\t\t\\\n\t\t: \"=&c\" (u0), \"=&D\" (u1), \"=&S\" (u2)\t\\\n\t\t: \"0\" (n >> 2),\t\t\t\t\\\n\t\t  \"1\" (dstp+(n-4)), \"2\" (srcp+(n-4))\t\\\n\t\t: \"memory\" );\t\t\t\t\\\n\t}\t\t\t\t\t\t\\\n\tswitch (n & 3) {\t\t\t\t\\\n\t\tcase 3: dstp[2] = srcp[2];\t\t\\\n\t\tcase 2: dstp[1] = srcp[1];\t\t\\\n\t\tcase 1: dstp[0] = srcp[0];\t\t\\\n\t\t\tbreak;\t\t\t\t\\\n\t\tdefault:\t\t\t\t\\\n\t\t\tbreak;\t\t\t\t\\\n\t}\t\t\t\t\t\t\\\n} while(0)\n#endif\n#ifndef SDL_revcpy\nextern DECLSPEC void * SDLCALL SDL_revcpy(void *dst, const void *src, size_t len);\n#endif\n\n#ifdef HAVE_MEMMOVE\n#define SDL_memmove     memmove\n#elif defined(HAVE_BCOPY)\n#define SDL_memmove(d, s, n)\tbcopy((s), (d), (n))\n#else\n#define SDL_memmove(dst, src, len)\t\t\t\\\ndo {\t\t\t\t\t\t\t\\\n\tif ( dst < src ) {\t\t\t\t\\\n\t\tSDL_memcpy(dst, src, len);\t\t\\\n\t} else {\t\t\t\t\t\\\n\t\tSDL_revcpy(dst, src, len);\t\t\\\n\t}\t\t\t\t\t\t\\\n} while(0)\n#endif\n\n#ifdef HAVE_MEMCMP\n#define SDL_memcmp      memcmp\n#else\nextern DECLSPEC int SDLCALL SDL_memcmp(const void *s1, const void *s2, size_t len);\n#endif\n\n#ifdef HAVE_STRLEN\n#define SDL_strlen      strlen\n#else\nextern DECLSPEC size_t SDLCALL SDL_strlen(const char *string);\n#endif\n\n#ifdef HAVE_STRLCPY\n#define SDL_strlcpy     strlcpy\n#else\nextern DECLSPEC size_t SDLCALL SDL_strlcpy(char *dst, const char *src, size_t maxlen);\n#endif\n\n#ifdef HAVE_STRLCAT\n#define SDL_strlcat    strlcat\n#else\nextern DECLSPEC size_t SDLCALL SDL_strlcat(char *dst, const char *src, size_t maxlen);\n#endif\n\n#ifdef HAVE_STRDUP\n#define SDL_strdup     strdup\n#else\nextern DECLSPEC char * SDLCALL SDL_strdup(const char *string);\n#endif\n\n#ifdef HAVE__STRREV\n#define SDL_strrev      _strrev\n#else\nextern DECLSPEC char * SDLCALL SDL_strrev(char *string);\n#endif\n\n#ifdef HAVE__STRUPR\n#define SDL_strupr      _strupr\n#else\nextern DECLSPEC char * SDLCALL SDL_strupr(char *string);\n#endif\n\n#ifdef HAVE__STRLWR\n#define SDL_strlwr      _strlwr\n#else\nextern DECLSPEC char * SDLCALL SDL_strlwr(char *string);\n#endif\n\n#ifdef HAVE_STRCHR\n#define SDL_strchr      strchr\n#elif defined(HAVE_INDEX)\n#define SDL_strchr      index\n#else\nextern DECLSPEC char * SDLCALL SDL_strchr(const char *string, int c);\n#endif\n\n#ifdef HAVE_STRRCHR\n#define SDL_strrchr     strrchr\n#elif defined(HAVE_RINDEX)\n#define SDL_strrchr     rindex\n#else\nextern DECLSPEC char * SDLCALL SDL_strrchr(const char *string, int c);\n#endif\n\n#ifdef HAVE_STRSTR\n#define SDL_strstr      strstr\n#else\nextern DECLSPEC char * SDLCALL SDL_strstr(const char *haystack, const char *needle);\n#endif\n\n#ifdef HAVE_ITOA\n#define SDL_itoa        itoa\n#else\n#define SDL_itoa(value, string, radix)\tSDL_ltoa((long)value, string, radix)\n#endif\n\n#ifdef HAVE__LTOA\n#define SDL_ltoa        _ltoa\n#else\nextern DECLSPEC char * SDLCALL SDL_ltoa(long value, char *string, int radix);\n#endif\n\n#ifdef HAVE__UITOA\n#define SDL_uitoa       _uitoa\n#else\n#define SDL_uitoa(value, string, radix)\tSDL_ultoa((long)value, string, radix)\n#endif\n\n#ifdef HAVE__ULTOA\n#define SDL_ultoa       _ultoa\n#else\nextern DECLSPEC char * SDLCALL SDL_ultoa(unsigned long value, char *string, int radix);\n#endif\n\n#ifdef HAVE_STRTOL\n#define SDL_strtol      strtol\n#else\nextern DECLSPEC long SDLCALL SDL_strtol(const char *string, char **endp, int base);\n#endif\n\n#ifdef HAVE_STRTOUL\n#define SDL_strtoul      strtoul\n#else\nextern DECLSPEC unsigned long SDLCALL SDL_strtoul(const char *string, char **endp, int base);\n#endif\n\n#ifdef SDL_HAS_64BIT_TYPE\n\n#ifdef HAVE__I64TOA\n#define SDL_lltoa       _i64toa\n#else\nextern DECLSPEC char* SDLCALL SDL_lltoa(Sint64 value, char *string, int radix);\n#endif\n\n#ifdef HAVE__UI64TOA\n#define SDL_ulltoa      _ui64toa\n#else\nextern DECLSPEC char* SDLCALL SDL_ulltoa(Uint64 value, char *string, int radix);\n#endif\n\n#ifdef HAVE__STRTOI64\n#define SDL_strtoll    _strtoi64\n#elif defined(HAVE_STRTOLL)\n#define SDL_strtoll     strtoll\n#else\nextern DECLSPEC Sint64 SDLCALL SDL_strtoll(const char *string, char **endp, int base);\n#endif\n\n#ifdef HAVE__STRTOUI64\n#define SDL_strtoull    _strtoui64\n#elif defined(HAVE_STRTOULL)\n#define SDL_strtoull     strtoull\n#else\nextern DECLSPEC Uint64 SDLCALL SDL_strtoull(const char *string, char **endp, int base);\n#endif\n\n#endif /* SDL_HAS_64BIT_TYPE */\n\n#ifdef HAVE_STRTOD\n#define SDL_strtod      strtod\n#else\nextern DECLSPEC double SDLCALL SDL_strtod(const char *string, char **endp);\n#endif\n\n#ifdef HAVE_ATOI\n#define SDL_atoi        atoi\n#else\n#define SDL_atoi(X)     SDL_strtol(X, NULL, 10)\n#endif\n\n#ifdef HAVE_ATOF\n#define SDL_atof        atof\n#else\n#define SDL_atof(X)     SDL_strtod(X, NULL)\n#endif\n\n#ifdef HAVE_STRCMP\n#define SDL_strcmp      strcmp\n#else\nextern DECLSPEC int SDLCALL SDL_strcmp(const char *str1, const char *str2);\n#endif\n\n#ifdef HAVE_STRNCMP\n#define SDL_strncmp     strncmp\n#else\nextern DECLSPEC int SDLCALL SDL_strncmp(const char *str1, const char *str2, size_t maxlen);\n#endif\n\n#if defined(HAVE__STRICMP)\n#define SDL_strcasecmp  _stricmp\n#elif defined(HAVE_STRCASECMP)\n#define SDL_strcasecmp  strcasecmp\n#else\nextern DECLSPEC int SDLCALL SDL_strcasecmp(const char *str1, const char *str2);\n#endif\n\n#if defined(HAVE__STRNICMP)\n#define SDL_strncasecmp _strnicmp\n#elif defined(HAVE_STRNCASECMP)\n#define SDL_strncasecmp strncasecmp\n#else\nextern DECLSPEC int SDLCALL SDL_strncasecmp(const char *str1, const char *str2, size_t maxlen);\n#endif\n\n#ifdef HAVE_SSCANF\n#define SDL_sscanf      sscanf\n#else\nextern DECLSPEC int SDLCALL SDL_sscanf(const char *text, const char *fmt, ...);\n#endif\n\n#if defined(HAVE_SNPRINTF) && !(defined(__WATCOMC__) || defined(_WIN32))\n#define SDL_snprintf    snprintf\n#else\nextern DECLSPEC int SDLCALL SDL_snprintf(char *text, size_t maxlen, const char *fmt, ...);\n#endif\n\n#if defined(HAVE_VSNPRINTF) && !(defined(__WATCOMC__) || defined(_WIN32))\n#define SDL_vsnprintf   vsnprintf\n#else\nextern DECLSPEC int SDLCALL SDL_vsnprintf(char *text, size_t maxlen, const char *fmt, va_list ap);\n#endif\n\n/** @name SDL_ICONV Error Codes\n *  The SDL implementation of iconv() returns these error codes \n */\n/*@{*/\n#define SDL_ICONV_ERROR\t\t(size_t)-1\n#define SDL_ICONV_E2BIG\t\t(size_t)-2\n#define SDL_ICONV_EILSEQ\t(size_t)-3\n#define SDL_ICONV_EINVAL\t(size_t)-4\n/*@}*/\n\n#if defined(HAVE_ICONV) && defined(HAVE_ICONV_H)\n#define SDL_iconv_t     iconv_t\n#define SDL_iconv_open  iconv_open\n#define SDL_iconv_close iconv_close\n#else\ntypedef struct _SDL_iconv_t *SDL_iconv_t;\nextern DECLSPEC SDL_iconv_t SDLCALL SDL_iconv_open(const char *tocode, const char *fromcode);\nextern DECLSPEC int SDLCALL SDL_iconv_close(SDL_iconv_t cd);\n#endif\nextern DECLSPEC size_t SDLCALL SDL_iconv(SDL_iconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft);\n/** This function converts a string between encodings in one pass, returning a\n *  string that must be freed with SDL_free() or NULL on error.\n */\nextern DECLSPEC char * SDLCALL SDL_iconv_string(const char *tocode, const char *fromcode, const char *inbuf, size_t inbytesleft);\n#define SDL_iconv_utf8_locale(S)\tSDL_iconv_string(\"\", \"UTF-8\", S, SDL_strlen(S)+1)\n#define SDL_iconv_utf8_ucs2(S)\t\t(Uint16 *)SDL_iconv_string(\"UCS-2\", \"UTF-8\", S, SDL_strlen(S)+1)\n#define SDL_iconv_utf8_ucs4(S)\t\t(Uint32 *)SDL_iconv_string(\"UCS-4\", \"UTF-8\", S, SDL_strlen(S)+1)\n\n/* Ends C function definitions when using C++ */\n#ifdef __cplusplus\n}\n#endif\n#include \"close_code.h\"\n\n#endif /* _SDL_stdinc_h */\n"
  },
  {
    "path": "deps/include/SDL/SDL_syswm.h",
    "content": "/*\n    SDL - Simple DirectMedia Layer\n    Copyright (C) 1997-2012 Sam Lantinga\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Lesser General Public\n    License as published by the Free Software Foundation; either\n    version 2.1 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public\n    License along with this library; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n\n    Sam Lantinga\n    slouken@libsdl.org\n*/\n\n/** @file SDL_syswm.h\n *  Include file for SDL custom system window manager hooks\n */\n\n#ifndef _SDL_syswm_h\n#define _SDL_syswm_h\n\n#include \"SDL_stdinc.h\"\n#include \"SDL_error.h\"\n#include \"SDL_version.h\"\n\n#ifndef SDL_PROTOTYPES_ONLY\n# if defined(SDL_VIDEO_DRIVER_X11)\n#  if defined(__APPLE__) && defined(__MACH__)\n#   define Cursor X11Cursor /* conflicts with Quickdraw.h */\n#  endif\n#  include <X11/Xlib.h>\n#  include <X11/Xatom.h>\n#  if defined(__APPLE__) && defined(__MACH__)\n#   undef Cursor\n#  endif\n# elif defined(SDL_VIDEO_DRIVER_NANOX)\n#  include <microwin/nano-X.h>\n# elif defined(SDL_VIDEO_DRIVER_WINDIB) || defined(SDL_VIDEO_DRIVER_DDRAW) || defined(SDL_VIDEO_DRIVER_GAPI)\n#  ifndef WIN32_LEAN_AND_MEAN\n#  define WIN32_LEAN_AND_MEAN\n#  endif\n#  include <windows.h>\n# elif defined(SDL_VIDEO_DRIVER_PHOTON)\n#  include <sys/neutrino.h>\n#  include <Ph.h>\n# endif\n#endif\n\n#include \"begin_code.h\"\n/* Set up for C function definitions, even when using C++ */\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/** @file SDL_syswm.h\n *  Your application has access to a special type of event 'SDL_SYSWMEVENT',\n *  which contains window-manager specific information and arrives whenever\n *  an unhandled window event occurs.  This event is ignored by default, but\n *  you can enable it with SDL_EventState()\n */\nstruct SDL_SysWMinfo;\ntypedef struct SDL_SysWMinfo SDL_SysWMinfo;\n\n#ifndef SDL_PROTOTYPES_ONLY\n\n/* This is the structure for custom window manager events */\n#if defined(SDL_VIDEO_DRIVER_X11)\n\n/** These are the various supported subsystems under UNIX */\ntypedef enum {\n\tSDL_SYSWM_X11\n} SDL_SYSWM_TYPE;\n\n/** The UNIX custom event structure */\nstruct SDL_SysWMmsg {\n\tSDL_version version;\n\tSDL_SYSWM_TYPE subsystem;\n\tunion {\n\t    XEvent xevent;\n\t} event;\n};\n\n/** The UNIX custom window manager information structure.\n *  When this structure is returned, it holds information about which\n *  low level system it is using, and will be one of SDL_SYSWM_TYPE.\n */\nstruct SDL_SysWMinfo {\n\tSDL_version version;\n\tSDL_SYSWM_TYPE subsystem;\n\tunion {\n\t    struct {\n\t    \tDisplay *display;\t/**< The X11 display */\n\t    \tWindow window;\t\t/**< The X11 display window */\n\t\t/** These locking functions should be called around\n                 *  any X11 functions using the display variable, \n                 *  but not the gfxdisplay variable.\n                 *  They lock the event thread, so should not be\n\t\t *  called around event functions or from event filters.\n\t\t */\n                /*@{*/\n\t\tvoid (*lock_func)(void);\n\t\tvoid (*unlock_func)(void);\n                /*@}*/\n\n\t\t/** @name Introduced in SDL 1.0.2 */\n                /*@{*/\n\t    \tWindow fswindow;\t/**< The X11 fullscreen window */\n\t    \tWindow wmwindow;\t/**< The X11 managed input window */\n                /*@}*/\n\n\t\t/** @name Introduced in SDL 1.2.12 */\n                /*@{*/\n\t\tDisplay *gfxdisplay;\t/**< The X11 display to which rendering is done */\n                /*@}*/\n\t    } x11;\n\t} info;\n};\n\n#elif defined(SDL_VIDEO_DRIVER_NANOX)\n\n/** The generic custom event structure */\nstruct SDL_SysWMmsg {\n\tSDL_version version;\n\tint data;\n};\n\n/** The windows custom window manager information structure */\nstruct SDL_SysWMinfo {\n\tSDL_version version ;\n\tGR_WINDOW_ID window ;\t/* The display window */\n};\n\n#elif defined(SDL_VIDEO_DRIVER_WINDIB) || defined(SDL_VIDEO_DRIVER_DDRAW) || defined(SDL_VIDEO_DRIVER_GAPI)\n\n/** The windows custom event structure */\nstruct SDL_SysWMmsg {\n\tSDL_version version;\n\tHWND hwnd;\t\t\t/**< The window for the message */\n\tUINT msg;\t\t\t/**< The type of message */\n\tWPARAM wParam;\t\t\t/**< WORD message parameter */\n\tLPARAM lParam;\t\t\t/**< LONG message parameter */\n};\n\n/** The windows custom window manager information structure */\nstruct SDL_SysWMinfo {\n\tSDL_version version;\n\tHWND window;\t\t\t/**< The Win32 display window */\n\tHGLRC hglrc;\t\t\t/**< The OpenGL context, if any */\n};\n\n#elif defined(SDL_VIDEO_DRIVER_RISCOS)\n\n/** RISC OS custom event structure */\nstruct SDL_SysWMmsg {\n\tSDL_version version;\n\tint eventCode;\t\t/**< The window for the message */\n\tint pollBlock[64];\n};\n\n/** The RISC OS custom window manager information structure */\nstruct SDL_SysWMinfo {\n\tSDL_version version;\n\tint wimpVersion;    /**< Wimp version running under */\n\tint taskHandle;     /**< The RISC OS task handle */\n\tint window;\t\t/**< The RISC OS display window */\n};\n\n#elif defined(SDL_VIDEO_DRIVER_PHOTON)\n\n/** The QNX custom event structure */\nstruct SDL_SysWMmsg {\n\tSDL_version version;\n\tint data;\n};\n\n/** The QNX custom window manager information structure */\nstruct SDL_SysWMinfo {\n\tSDL_version version;\n\tint data;\n};\n\n#else\n\n/** The generic custom event structure */\nstruct SDL_SysWMmsg {\n\tSDL_version version;\n\tint data;\n};\n\n/** The generic custom window manager information structure */\nstruct SDL_SysWMinfo {\n\tSDL_version version;\n\tint data;\n};\n\n#endif /* video driver type */\n\n#endif /* SDL_PROTOTYPES_ONLY */\n\n/* Function prototypes */\n/**\n * This function gives you custom hooks into the window manager information.\n * It fills the structure pointed to by 'info' with custom information and\n * returns 0 if the function is not implemented, 1 if the function is \n * implemented and no error occurred, and -1 if the version member of\n * the 'info' structure is not filled in or not supported.\n *\n * You typically use this function like this:\n * @code\n * SDL_SysWMinfo info;\n * SDL_VERSION(&info.version);\n * if ( SDL_GetWMInfo(&info) ) { ... }\n * @endcode\n */\nextern DECLSPEC int SDLCALL SDL_GetWMInfo(SDL_SysWMinfo *info);\n\n\n/* Ends C function definitions when using C++ */\n#ifdef __cplusplus\n}\n#endif\n#include \"close_code.h\"\n\n#endif /* _SDL_syswm_h */\n"
  },
  {
    "path": "deps/include/SDL/SDL_thread.h",
    "content": "/*\n    SDL - Simple DirectMedia Layer\n    Copyright (C) 1997-2012 Sam Lantinga\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Lesser General Public\n    License as published by the Free Software Foundation; either\n    version 2.1 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public\n    License along with this library; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n\n    Sam Lantinga\n    slouken@libsdl.org\n*/\n\n#ifndef _SDL_thread_h\n#define _SDL_thread_h\n\n/** @file SDL_thread.h\n *  Header for the SDL thread management routines \n *\n *  @note These are independent of the other SDL routines.\n */\n\n#include \"SDL_stdinc.h\"\n#include \"SDL_error.h\"\n\n/* Thread synchronization primitives */\n#include \"SDL_mutex.h\"\n\n#include \"begin_code.h\"\n/* Set up for C function definitions, even when using C++ */\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/** The SDL thread structure, defined in SDL_thread.c */\nstruct SDL_Thread;\ntypedef struct SDL_Thread SDL_Thread;\n\n/** Create a thread */\n#if ((defined(__WIN32__) && !defined(HAVE_LIBC)) || defined(__OS2__)) &&  !defined(__SYMBIAN32__)\n/**\n *  We compile SDL into a DLL on OS/2. This means, that it's the DLL which\n *  creates a new thread for the calling process with the SDL_CreateThread()\n *  API. There is a problem with this, that only the RTL of the SDL.DLL will\n *  be initialized for those threads, and not the RTL of the calling application!\n *  To solve this, we make a little hack here.\n *  We'll always use the caller's _beginthread() and _endthread() APIs to\n *  start a new thread. This way, if it's the SDL.DLL which uses this API,\n *  then the RTL of SDL.DLL will be used to create the new thread, and if it's\n *  the application, then the RTL of the application will be used.\n *  So, in short:\n *  Always use the _beginthread() and _endthread() of the calling runtime library!\n */\n#define SDL_PASSED_BEGINTHREAD_ENDTHREAD\n#ifndef _WIN32_WCE\n#include <process.h> /* This has _beginthread() and _endthread() defined! */\n#endif\n#ifdef __EMX__\n#include <stdlib.h>\n#endif\n\n#ifdef __OS2__\ntypedef int (*pfnSDL_CurrentBeginThread)(void (*func)(void *), void *, unsigned, void *arg); \ntypedef void (*pfnSDL_CurrentEndThread)(void);\n#else\ntypedef uintptr_t (__cdecl *pfnSDL_CurrentBeginThread) (void *, unsigned,\n        unsigned (__stdcall *func)(void *), void *arg, \n        unsigned, unsigned *threadID);\ntypedef void (__cdecl *pfnSDL_CurrentEndThread)(unsigned code);\n#endif\n\nextern DECLSPEC SDL_Thread * SDLCALL SDL_CreateThread(int (SDLCALL *fn)(void *), void *data, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread);\n\n#ifdef __OS2__\n#define SDL_CreateThread(fn, data) SDL_CreateThread(fn, data, _beginthread, _endthread)\n#elif defined(_WIN32_WCE)\n#define SDL_CreateThread(fn, data) SDL_CreateThread(fn, data, NULL, NULL)\n#else\n#define SDL_CreateThread(fn, data) SDL_CreateThread(fn, data, _beginthreadex, _endthreadex)\n#endif\n#else\nextern DECLSPEC SDL_Thread * SDLCALL SDL_CreateThread(int (SDLCALL *fn)(void *), void *data);\n#endif\n\n/** Get the 32-bit thread identifier for the current thread */\nextern DECLSPEC Uint32 SDLCALL SDL_ThreadID(void);\n\n/** Get the 32-bit thread identifier for the specified thread,\n *  equivalent to SDL_ThreadID() if the specified thread is NULL.\n */\nextern DECLSPEC Uint32 SDLCALL SDL_GetThreadID(SDL_Thread *thread);\n\n/** Wait for a thread to finish.\n *  The return code for the thread function is placed in the area\n *  pointed to by 'status', if 'status' is not NULL.\n */\nextern DECLSPEC void SDLCALL SDL_WaitThread(SDL_Thread *thread, int *status);\n\n/** Forcefully kill a thread without worrying about its state */\nextern DECLSPEC void SDLCALL SDL_KillThread(SDL_Thread *thread);\n\n\n/* Ends C function definitions when using C++ */\n#ifdef __cplusplus\n}\n#endif\n#include \"close_code.h\"\n\n#endif /* _SDL_thread_h */\n"
  },
  {
    "path": "deps/include/SDL/SDL_timer.h",
    "content": "/*\n    SDL - Simple DirectMedia Layer\n    Copyright (C) 1997-2012 Sam Lantinga\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Lesser General Public\n    License as published by the Free Software Foundation; either\n    version 2.1 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public\n    License along with this library; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n\n    Sam Lantinga\n    slouken@libsdl.org\n*/\n\n#ifndef _SDL_timer_h\n#define _SDL_timer_h\n\n/** @file SDL_timer.h\n *  Header for the SDL time management routines\n */\n\n#include \"SDL_stdinc.h\"\n#include \"SDL_error.h\"\n\n#include \"begin_code.h\"\n/* Set up for C function definitions, even when using C++ */\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/** This is the OS scheduler timeslice, in milliseconds */\n#define SDL_TIMESLICE\t\t10\n\n/** This is the maximum resolution of the SDL timer on all platforms */\n#define TIMER_RESOLUTION\t10\t/**< Experimentally determined */\n\n/**\n * Get the number of milliseconds since the SDL library initialization.\n * Note that this value wraps if the program runs for more than ~49 days.\n */ \nextern DECLSPEC Uint32 SDLCALL SDL_GetTicks(void);\n\n/** Wait a specified number of milliseconds before returning */\nextern DECLSPEC void SDLCALL SDL_Delay(Uint32 ms);\n\n/** Function prototype for the timer callback function */\ntypedef Uint32 (SDLCALL *SDL_TimerCallback)(Uint32 interval);\n\n/**\n * Set a callback to run after the specified number of milliseconds has\n * elapsed. The callback function is passed the current timer interval\n * and returns the next timer interval.  If the returned value is the \n * same as the one passed in, the periodic alarm continues, otherwise a\n * new alarm is scheduled.  If the callback returns 0, the periodic alarm\n * is cancelled.\n *\n * To cancel a currently running timer, call SDL_SetTimer(0, NULL);\n *\n * The timer callback function may run in a different thread than your\n * main code, and so shouldn't call any functions from within itself.\n *\n * The maximum resolution of this timer is 10 ms, which means that if\n * you request a 16 ms timer, your callback will run approximately 20 ms\n * later on an unloaded system.  If you wanted to set a flag signaling\n * a frame update at 30 frames per second (every 33 ms), you might set a \n * timer for 30 ms:\n *   @code SDL_SetTimer((33/10)*10, flag_update); @endcode\n *\n * If you use this function, you need to pass SDL_INIT_TIMER to SDL_Init().\n *\n * Under UNIX, you should not use raise or use SIGALRM and this function\n * in the same program, as it is implemented using setitimer().  You also\n * should not use this function in multi-threaded applications as signals\n * to multi-threaded apps have undefined behavior in some implementations.\n *\n * This function returns 0 if successful, or -1 if there was an error.\n */\nextern DECLSPEC int SDLCALL SDL_SetTimer(Uint32 interval, SDL_TimerCallback callback);\n\n/** @name New timer API\n * New timer API, supports multiple timers\n * Written by Stephane Peter <megastep@lokigames.com>\n */\n/*@{*/\n\n/**\n * Function prototype for the new timer callback function.\n * The callback function is passed the current timer interval and returns\n * the next timer interval.  If the returned value is the same as the one\n * passed in, the periodic alarm continues, otherwise a new alarm is\n * scheduled.  If the callback returns 0, the periodic alarm is cancelled.\n */\ntypedef Uint32 (SDLCALL *SDL_NewTimerCallback)(Uint32 interval, void *param);\n\n/** Definition of the timer ID type */\ntypedef struct _SDL_TimerID *SDL_TimerID;\n\n/** Add a new timer to the pool of timers already running.\n *  Returns a timer ID, or NULL when an error occurs.\n */\nextern DECLSPEC SDL_TimerID SDLCALL SDL_AddTimer(Uint32 interval, SDL_NewTimerCallback callback, void *param);\n\n/**\n * Remove one of the multiple timers knowing its ID.\n * Returns a boolean value indicating success.\n */\nextern DECLSPEC SDL_bool SDLCALL SDL_RemoveTimer(SDL_TimerID t);\n\n/*@}*/\n\n/* Ends C function definitions when using C++ */\n#ifdef __cplusplus\n}\n#endif\n#include \"close_code.h\"\n\n#endif /* _SDL_timer_h */\n"
  },
  {
    "path": "deps/include/SDL/SDL_types.h",
    "content": "/*\n    SDL - Simple DirectMedia Layer\n    Copyright (C) 1997-2012 Sam Lantinga\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Lesser General Public\n    License as published by the Free Software Foundation; either\n    version 2.1 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public\n    License along with this library; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n\n    Sam Lantinga\n    slouken@libsdl.org\n*/\n\n/** @file SDL_types.h\n *  @deprecated Use SDL_stdinc.h instead.\n */\n\n/* DEPRECATED */\n#include \"SDL_stdinc.h\"\n"
  },
  {
    "path": "deps/include/SDL/SDL_version.h",
    "content": "/*\n    SDL - Simple DirectMedia Layer\n    Copyright (C) 1997-2012 Sam Lantinga\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Lesser General Public\n    License as published by the Free Software Foundation; either\n    version 2.1 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public\n    License along with this library; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n\n    Sam Lantinga\n    slouken@libsdl.org\n*/\n\n/** @file SDL_version.h\n *  This header defines the current SDL version\n */\n\n#ifndef _SDL_version_h\n#define _SDL_version_h\n\n#include \"SDL_stdinc.h\"\n\n#include \"begin_code.h\"\n/* Set up for C function definitions, even when using C++ */\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/** @name Version Number\n *  Printable format: \"%d.%d.%d\", MAJOR, MINOR, PATCHLEVEL\n */\n/*@{*/\n#define SDL_MAJOR_VERSION\t1\n#define SDL_MINOR_VERSION\t2\n#define SDL_PATCHLEVEL\t\t16\n/*@}*/\n\ntypedef struct SDL_version {\n\tUint8 major;\n\tUint8 minor;\n\tUint8 patch;\n} SDL_version;\n\n/**\n * This macro can be used to fill a version structure with the compile-time\n * version of the SDL library.\n */\n#define SDL_VERSION(X)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t(X)->major = SDL_MAJOR_VERSION;\t\t\t\t\t\\\n\t(X)->minor = SDL_MINOR_VERSION;\t\t\t\t\t\\\n\t(X)->patch = SDL_PATCHLEVEL;\t\t\t\t\t\\\n}\n\n/** This macro turns the version numbers into a numeric value:\n *  (1,2,3) -> (1203)\n *  This assumes that there will never be more than 100 patchlevels\n */\n#define SDL_VERSIONNUM(X, Y, Z)\t\t\t\t\t\t\\\n\t((X)*1000 + (Y)*100 + (Z))\n\n/** This is the version number macro for the current SDL version */\n#define SDL_COMPILEDVERSION \\\n\tSDL_VERSIONNUM(SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL)\n\n/** This macro will evaluate to true if compiled with SDL at least X.Y.Z */\n#define SDL_VERSION_ATLEAST(X, Y, Z) \\\n\t(SDL_COMPILEDVERSION >= SDL_VERSIONNUM(X, Y, Z))\n\n/** This function gets the version of the dynamically linked SDL library.\n *  it should NOT be used to fill a version structure, instead you should\n *  use the SDL_Version() macro.\n */\nextern DECLSPEC const SDL_version * SDLCALL SDL_Linked_Version(void);\n\n/* Ends C function definitions when using C++ */\n#ifdef __cplusplus\n}\n#endif\n#include \"close_code.h\"\n\n#endif /* _SDL_version_h */\n"
  },
  {
    "path": "deps/include/SDL/SDL_video.h",
    "content": "/*\n    SDL - Simple DirectMedia Layer\n    Copyright (C) 1997-2012 Sam Lantinga\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Lesser General Public\n    License as published by the Free Software Foundation; either\n    version 2.1 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public\n    License along with this library; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n\n    Sam Lantinga\n    slouken@libsdl.org\n*/\n\n/** @file SDL_video.h\n *  Header file for access to the SDL raw framebuffer window\n */\n\n#ifndef _SDL_video_h\n#define _SDL_video_h\n\n#include \"SDL_stdinc.h\"\n#include \"SDL_error.h\"\n#include \"SDL_rwops.h\"\n\n#include \"begin_code.h\"\n/* Set up for C function definitions, even when using C++ */\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/** @name Transparency definitions\n *  These define alpha as the opacity of a surface\n */\n/*@{*/\n#define SDL_ALPHA_OPAQUE 255\n#define SDL_ALPHA_TRANSPARENT 0\n/*@}*/\n\n/** @name Useful data types */\n/*@{*/\ntypedef struct SDL_Rect {\n\tSint16 x, y;\n\tUint16 w, h;\n} SDL_Rect;\n\ntypedef struct SDL_Color {\n\tUint8 r;\n\tUint8 g;\n\tUint8 b;\n\tUint8 unused;\n} SDL_Color;\n#define SDL_Colour SDL_Color\n\ntypedef struct SDL_Palette {\n\tint       ncolors;\n\tSDL_Color *colors;\n} SDL_Palette;\n/*@}*/\n\n/** Everything in the pixel format structure is read-only */\ntypedef struct SDL_PixelFormat {\n\tSDL_Palette *palette;\n\tUint8  BitsPerPixel;\n\tUint8  BytesPerPixel;\n\tUint8  Rloss;\n\tUint8  Gloss;\n\tUint8  Bloss;\n\tUint8  Aloss;\n\tUint8  Rshift;\n\tUint8  Gshift;\n\tUint8  Bshift;\n\tUint8  Ashift;\n\tUint32 Rmask;\n\tUint32 Gmask;\n\tUint32 Bmask;\n\tUint32 Amask;\n\n\t/** RGB color key information */\n\tUint32 colorkey;\n\t/** Alpha value information (per-surface alpha) */\n\tUint8  alpha;\n} SDL_PixelFormat;\n\n/** This structure should be treated as read-only, except for 'pixels',\n *  which, if not NULL, contains the raw pixel data for the surface.\n */\ntypedef struct SDL_Surface {\n\tUint32 flags;\t\t\t\t/**< Read-only */\n\tSDL_PixelFormat *format;\t\t/**< Read-only */\n\tint w, h;\t\t\t\t/**< Read-only */\n\tUint16 pitch;\t\t\t\t/**< Read-only */\n\tvoid *pixels;\t\t\t\t/**< Read-write */\n\tint offset;\t\t\t\t/**< Private */\n\n\t/** Hardware-specific surface info */\n\tstruct private_hwdata *hwdata;\n\n\t/** clipping information */\n\tSDL_Rect clip_rect;\t\t\t/**< Read-only */\n\tUint32 unused1;\t\t\t\t/**< for binary compatibility */\n\n\t/** Allow recursive locks */\n\tUint32 locked;\t\t\t\t/**< Private */\n\n\t/** info for fast blit mapping to other surfaces */\n\tstruct SDL_BlitMap *map;\t\t/**< Private */\n\n\t/** format version, bumped at every change to invalidate blit maps */\n\tunsigned int format_version;\t\t/**< Private */\n\n\t/** Reference count -- used when freeing surface */\n\tint refcount;\t\t\t\t/**< Read-mostly */\n} SDL_Surface;\n\n/** @name SDL_Surface Flags\n *  These are the currently supported flags for the SDL_surface\n */\n/*@{*/\n\n/** Available for SDL_CreateRGBSurface() or SDL_SetVideoMode() */\n/*@{*/\n#define SDL_SWSURFACE\t0x00000000\t/**< Surface is in system memory */\n#define SDL_HWSURFACE\t0x00000001\t/**< Surface is in video memory */\n#define SDL_ASYNCBLIT\t0x00000004\t/**< Use asynchronous blits if possible */\n/*@}*/\n\n/** Available for SDL_SetVideoMode() */\n/*@{*/\n#define SDL_ANYFORMAT\t0x10000000\t/**< Allow any video depth/pixel-format */\n#define SDL_HWPALETTE\t0x20000000\t/**< Surface has exclusive palette */\n#define SDL_DOUBLEBUF\t0x40000000\t/**< Set up double-buffered video mode */\n#define SDL_TRIPLEBUF\t0x40000100\t/**< Set up triple-buffered video mode */\n#define SDL_FULLSCREEN\t0x80000000\t/**< Surface is a full screen display */\n#define SDL_OPENGL      0x00000002      /**< Create an OpenGL rendering context */\n#define SDL_OPENGLBLIT\t0x0000000A\t/**< Create an OpenGL rendering context and use it for blitting */\n#define SDL_RESIZABLE\t0x00000010\t/**< This video mode may be resized */\n#define SDL_NOFRAME\t0x00000020\t/**< No window caption or edge frame */\n/*@}*/\n\n/** Used internally (read-only) */\n/*@{*/\n#define SDL_HWACCEL\t0x00000100\t/**< Blit uses hardware acceleration */\n#define SDL_SRCCOLORKEY\t0x00001000\t/**< Blit uses a source color key */\n#define SDL_RLEACCELOK\t0x00002000\t/**< Private flag */\n#define SDL_RLEACCEL\t0x00004000\t/**< Surface is RLE encoded */\n#define SDL_SRCALPHA\t0x00010000\t/**< Blit uses source alpha blending */\n#define SDL_PREALLOC\t0x01000000\t/**< Surface uses preallocated memory */\n/*@}*/\n\n/*@}*/\n\n/** Evaluates to true if the surface needs to be locked before access */\n#define SDL_MUSTLOCK(surface)\t\\\n  (surface->offset ||\t\t\\\n  ((surface->flags & (SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_RLEACCEL)) != 0))\n\n/** typedef for private surface blitting functions */\ntypedef int (*SDL_blit)(struct SDL_Surface *src, SDL_Rect *srcrect,\n\t\t\tstruct SDL_Surface *dst, SDL_Rect *dstrect);\n\n\n/** Useful for determining the video hardware capabilities */\ntypedef struct SDL_VideoInfo {\n\tUint32 hw_available :1;\t/**< Flag: Can you create hardware surfaces? */\n\tUint32 wm_available :1;\t/**< Flag: Can you talk to a window manager? */\n\tUint32 UnusedBits1  :6;\n\tUint32 UnusedBits2  :1;\n\tUint32 blit_hw      :1;\t/**< Flag: Accelerated blits HW --> HW */\n\tUint32 blit_hw_CC   :1;\t/**< Flag: Accelerated blits with Colorkey */\n\tUint32 blit_hw_A    :1;\t/**< Flag: Accelerated blits with Alpha */\n\tUint32 blit_sw      :1;\t/**< Flag: Accelerated blits SW --> HW */\n\tUint32 blit_sw_CC   :1;\t/**< Flag: Accelerated blits with Colorkey */\n\tUint32 blit_sw_A    :1;\t/**< Flag: Accelerated blits with Alpha */\n\tUint32 blit_fill    :1;\t/**< Flag: Accelerated color fill */\n\tUint32 UnusedBits3  :16;\n\tUint32 video_mem;\t/**< The total amount of video memory (in K) */\n\tSDL_PixelFormat *vfmt;\t/**< Value: The format of the video surface */\n\tint    current_w;\t/**< Value: The current video mode width */\n\tint    current_h;\t/**< Value: The current video mode height */\n} SDL_VideoInfo;\n\n\n/** @name Overlay Formats\n *  The most common video overlay formats.\n *  For an explanation of these pixel formats, see:\n *\thttp://www.webartz.com/fourcc/indexyuv.htm\n *\n *  For information on the relationship between color spaces, see:\n *  http://www.neuro.sfc.keio.ac.jp/~aly/polygon/info/color-space-faq.html\n */\n/*@{*/\n#define SDL_YV12_OVERLAY  0x32315659\t/**< Planar mode: Y + V + U  (3 planes) */\n#define SDL_IYUV_OVERLAY  0x56555949\t/**< Planar mode: Y + U + V  (3 planes) */\n#define SDL_YUY2_OVERLAY  0x32595559\t/**< Packed mode: Y0+U0+Y1+V0 (1 plane) */\n#define SDL_UYVY_OVERLAY  0x59565955\t/**< Packed mode: U0+Y0+V0+Y1 (1 plane) */\n#define SDL_YVYU_OVERLAY  0x55595659\t/**< Packed mode: Y0+V0+Y1+U0 (1 plane) */\n/*@}*/\n\n/** The YUV hardware video overlay */\ntypedef struct SDL_Overlay {\n\tUint32 format;\t\t\t\t/**< Read-only */\n\tint w, h;\t\t\t\t/**< Read-only */\n\tint planes;\t\t\t\t/**< Read-only */\n\tUint16 *pitches;\t\t\t/**< Read-only */\n\tUint8 **pixels;\t\t\t\t/**< Read-write */\n\n\t/** @name Hardware-specific surface info */\n        /*@{*/\n\tstruct private_yuvhwfuncs *hwfuncs;\n\tstruct private_yuvhwdata *hwdata;\n        /*@{*/\n\n\t/** @name Special flags */\n        /*@{*/\n\tUint32 hw_overlay :1;\t/**< Flag: This overlay hardware accelerated? */\n\tUint32 UnusedBits :31;\n        /*@}*/\n} SDL_Overlay;\n\n\n/** Public enumeration for setting the OpenGL window attributes. */\ntypedef enum {\n    SDL_GL_RED_SIZE,\n    SDL_GL_GREEN_SIZE,\n    SDL_GL_BLUE_SIZE,\n    SDL_GL_ALPHA_SIZE,\n    SDL_GL_BUFFER_SIZE,\n    SDL_GL_DOUBLEBUFFER,\n    SDL_GL_DEPTH_SIZE,\n    SDL_GL_STENCIL_SIZE,\n    SDL_GL_ACCUM_RED_SIZE,\n    SDL_GL_ACCUM_GREEN_SIZE,\n    SDL_GL_ACCUM_BLUE_SIZE,\n    SDL_GL_ACCUM_ALPHA_SIZE,\n    SDL_GL_STEREO,\n    SDL_GL_MULTISAMPLEBUFFERS,\n    SDL_GL_MULTISAMPLESAMPLES,\n    SDL_GL_ACCELERATED_VISUAL,\n    SDL_GL_SWAP_CONTROL\n} SDL_GLattr;\n\n/** @name flags for SDL_SetPalette() */\n/*@{*/\n#define SDL_LOGPAL 0x01\n#define SDL_PHYSPAL 0x02\n/*@}*/\n\n/* Function prototypes */\n\n/**\n * @name Video Init and Quit\n * These functions are used internally, and should not be used unless you\n * have a specific need to specify the video driver you want to use.\n * You should normally use SDL_Init() or SDL_InitSubSystem().\n */\n/*@{*/\n/**\n * Initializes the video subsystem. Sets up a connection\n * to the window manager, etc, and determines the current video mode and\n * pixel format, but does not initialize a window or graphics mode.\n * Note that event handling is activated by this routine.\n *\n * If you use both sound and video in your application, you need to call\n * SDL_Init() before opening the sound device, otherwise under Win32 DirectX,\n * you won't be able to set full-screen display modes.\n */\nextern DECLSPEC int SDLCALL SDL_VideoInit(const char *driver_name, Uint32 flags);\nextern DECLSPEC void SDLCALL SDL_VideoQuit(void);\n/*@}*/\n\n/**\n * This function fills the given character buffer with the name of the\n * video driver, and returns a pointer to it if the video driver has\n * been initialized.  It returns NULL if no driver has been initialized.\n */\nextern DECLSPEC char * SDLCALL SDL_VideoDriverName(char *namebuf, int maxlen);\n\n/**\n * This function returns a pointer to the current display surface.\n * If SDL is doing format conversion on the display surface, this\n * function returns the publicly visible surface, not the real video\n * surface.\n */\nextern DECLSPEC SDL_Surface * SDLCALL SDL_GetVideoSurface(void);\n\n/**\n * This function returns a read-only pointer to information about the\n * video hardware.  If this is called before SDL_SetVideoMode(), the 'vfmt'\n * member of the returned structure will contain the pixel format of the\n * \"best\" video mode.\n */\nextern DECLSPEC const SDL_VideoInfo * SDLCALL SDL_GetVideoInfo(void);\n\n/**\n * Check to see if a particular video mode is supported.\n * It returns 0 if the requested mode is not supported under any bit depth,\n * or returns the bits-per-pixel of the closest available mode with the\n * given width and height.  If this bits-per-pixel is different from the\n * one used when setting the video mode, SDL_SetVideoMode() will succeed,\n * but will emulate the requested bits-per-pixel with a shadow surface.\n *\n * The arguments to SDL_VideoModeOK() are the same ones you would pass to\n * SDL_SetVideoMode()\n */\nextern DECLSPEC int SDLCALL SDL_VideoModeOK(int width, int height, int bpp, Uint32 flags);\n\n/**\n * Return a pointer to an array of available screen dimensions for the\n * given format and video flags, sorted largest to smallest.  Returns \n * NULL if there are no dimensions available for a particular format, \n * or (SDL_Rect **)-1 if any dimension is okay for the given format.\n *\n * If 'format' is NULL, the mode list will be for the format given \n * by SDL_GetVideoInfo()->vfmt\n */\nextern DECLSPEC SDL_Rect ** SDLCALL SDL_ListModes(SDL_PixelFormat *format, Uint32 flags);\n\n/**\n * Set up a video mode with the specified width, height and bits-per-pixel.\n *\n * If 'bpp' is 0, it is treated as the current display bits per pixel.\n *\n * If SDL_ANYFORMAT is set in 'flags', the SDL library will try to set the\n * requested bits-per-pixel, but will return whatever video pixel format is\n * available.  The default is to emulate the requested pixel format if it\n * is not natively available.\n *\n * If SDL_HWSURFACE is set in 'flags', the video surface will be placed in\n * video memory, if possible, and you may have to call SDL_LockSurface()\n * in order to access the raw framebuffer.  Otherwise, the video surface\n * will be created in system memory.\n *\n * If SDL_ASYNCBLIT is set in 'flags', SDL will try to perform rectangle\n * updates asynchronously, but you must always lock before accessing pixels.\n * SDL will wait for updates to complete before returning from the lock.\n *\n * If SDL_HWPALETTE is set in 'flags', the SDL library will guarantee\n * that the colors set by SDL_SetColors() will be the colors you get.\n * Otherwise, in 8-bit mode, SDL_SetColors() may not be able to set all\n * of the colors exactly the way they are requested, and you should look\n * at the video surface structure to determine the actual palette.\n * If SDL cannot guarantee that the colors you request can be set, \n * i.e. if the colormap is shared, then the video surface may be created\n * under emulation in system memory, overriding the SDL_HWSURFACE flag.\n *\n * If SDL_FULLSCREEN is set in 'flags', the SDL library will try to set\n * a fullscreen video mode.  The default is to create a windowed mode\n * if the current graphics system has a window manager.\n * If the SDL library is able to set a fullscreen video mode, this flag \n * will be set in the surface that is returned.\n *\n * If SDL_DOUBLEBUF is set in 'flags', the SDL library will try to set up\n * two surfaces in video memory and swap between them when you call \n * SDL_Flip().  This is usually slower than the normal single-buffering\n * scheme, but prevents \"tearing\" artifacts caused by modifying video \n * memory while the monitor is refreshing.  It should only be used by \n * applications that redraw the entire screen on every update.\n *\n * If SDL_RESIZABLE is set in 'flags', the SDL library will allow the\n * window manager, if any, to resize the window at runtime.  When this\n * occurs, SDL will send a SDL_VIDEORESIZE event to you application,\n * and you must respond to the event by re-calling SDL_SetVideoMode()\n * with the requested size (or another size that suits the application).\n *\n * If SDL_NOFRAME is set in 'flags', the SDL library will create a window\n * without any title bar or frame decoration.  Fullscreen video modes have\n * this flag set automatically.\n *\n * This function returns the video framebuffer surface, or NULL if it fails.\n *\n * If you rely on functionality provided by certain video flags, check the\n * flags of the returned surface to make sure that functionality is available.\n * SDL will fall back to reduced functionality if the exact flags you wanted\n * are not available.\n */\nextern DECLSPEC SDL_Surface * SDLCALL SDL_SetVideoMode\n\t\t\t(int width, int height, int bpp, Uint32 flags);\n\n/** @name SDL_Update Functions\n * These functions should not be called while 'screen' is locked.\n */\n/*@{*/\n/**\n * Makes sure the given list of rectangles is updated on the given screen.\n */\nextern DECLSPEC void SDLCALL SDL_UpdateRects\n\t\t(SDL_Surface *screen, int numrects, SDL_Rect *rects);\n/**\n * If 'x', 'y', 'w' and 'h' are all 0, SDL_UpdateRect will update the entire\n * screen.\n */\nextern DECLSPEC void SDLCALL SDL_UpdateRect\n\t\t(SDL_Surface *screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h);\n/*@}*/\n\n/**\n * On hardware that supports double-buffering, this function sets up a flip\n * and returns.  The hardware will wait for vertical retrace, and then swap\n * video buffers before the next video surface blit or lock will return.\n * On hardware that doesn not support double-buffering, this is equivalent\n * to calling SDL_UpdateRect(screen, 0, 0, 0, 0);\n * The SDL_DOUBLEBUF flag must have been passed to SDL_SetVideoMode() when\n * setting the video mode for this function to perform hardware flipping.\n * This function returns 0 if successful, or -1 if there was an error.\n */\nextern DECLSPEC int SDLCALL SDL_Flip(SDL_Surface *screen);\n\n/**\n * Set the gamma correction for each of the color channels.\n * The gamma values range (approximately) between 0.1 and 10.0\n * \n * If this function isn't supported directly by the hardware, it will\n * be emulated using gamma ramps, if available.  If successful, this\n * function returns 0, otherwise it returns -1.\n */\nextern DECLSPEC int SDLCALL SDL_SetGamma(float red, float green, float blue);\n\n/**\n * Set the gamma translation table for the red, green, and blue channels\n * of the video hardware.  Each table is an array of 256 16-bit quantities,\n * representing a mapping between the input and output for that channel.\n * The input is the index into the array, and the output is the 16-bit\n * gamma value at that index, scaled to the output color precision.\n * \n * You may pass NULL for any of the channels to leave it unchanged.\n * If the call succeeds, it will return 0.  If the display driver or\n * hardware does not support gamma translation, or otherwise fails,\n * this function will return -1.\n */\nextern DECLSPEC int SDLCALL SDL_SetGammaRamp(const Uint16 *red, const Uint16 *green, const Uint16 *blue);\n\n/**\n * Retrieve the current values of the gamma translation tables.\n * \n * You must pass in valid pointers to arrays of 256 16-bit quantities.\n * Any of the pointers may be NULL to ignore that channel.\n * If the call succeeds, it will return 0.  If the display driver or\n * hardware does not support gamma translation, or otherwise fails,\n * this function will return -1.\n */\nextern DECLSPEC int SDLCALL SDL_GetGammaRamp(Uint16 *red, Uint16 *green, Uint16 *blue);\n\n/**\n * Sets a portion of the colormap for the given 8-bit surface.  If 'surface'\n * is not a palettized surface, this function does nothing, returning 0.\n * If all of the colors were set as passed to SDL_SetColors(), it will\n * return 1.  If not all the color entries were set exactly as given,\n * it will return 0, and you should look at the surface palette to\n * determine the actual color palette.\n *\n * When 'surface' is the surface associated with the current display, the\n * display colormap will be updated with the requested colors.  If \n * SDL_HWPALETTE was set in SDL_SetVideoMode() flags, SDL_SetColors()\n * will always return 1, and the palette is guaranteed to be set the way\n * you desire, even if the window colormap has to be warped or run under\n * emulation.\n */\nextern DECLSPEC int SDLCALL SDL_SetColors(SDL_Surface *surface, \n\t\t\tSDL_Color *colors, int firstcolor, int ncolors);\n\n/**\n * Sets a portion of the colormap for a given 8-bit surface.\n * 'flags' is one or both of:\n * SDL_LOGPAL  -- set logical palette, which controls how blits are mapped\n *                to/from the surface,\n * SDL_PHYSPAL -- set physical palette, which controls how pixels look on\n *                the screen\n * Only screens have physical palettes. Separate change of physical/logical\n * palettes is only possible if the screen has SDL_HWPALETTE set.\n *\n * The return value is 1 if all colours could be set as requested, and 0\n * otherwise.\n *\n * SDL_SetColors() is equivalent to calling this function with\n *     flags = (SDL_LOGPAL|SDL_PHYSPAL).\n */\nextern DECLSPEC int SDLCALL SDL_SetPalette(SDL_Surface *surface, int flags,\n\t\t\t\t   SDL_Color *colors, int firstcolor,\n\t\t\t\t   int ncolors);\n\n/**\n * Maps an RGB triple to an opaque pixel value for a given pixel format\n */\nextern DECLSPEC Uint32 SDLCALL SDL_MapRGB\n(const SDL_PixelFormat * const format,\n const Uint8 r, const Uint8 g, const Uint8 b);\n\n/**\n * Maps an RGBA quadruple to a pixel value for a given pixel format\n */\nextern DECLSPEC Uint32 SDLCALL SDL_MapRGBA\n(const SDL_PixelFormat * const format,\n const Uint8 r, const Uint8 g, const Uint8 b, const Uint8 a);\n\n/**\n * Maps a pixel value into the RGB components for a given pixel format\n */\nextern DECLSPEC void SDLCALL SDL_GetRGB(Uint32 pixel,\n\t\t\t\tconst SDL_PixelFormat * const fmt,\n\t\t\t\tUint8 *r, Uint8 *g, Uint8 *b);\n\n/**\n * Maps a pixel value into the RGBA components for a given pixel format\n */\nextern DECLSPEC void SDLCALL SDL_GetRGBA(Uint32 pixel,\n\t\t\t\tconst SDL_PixelFormat * const fmt,\n\t\t\t\tUint8 *r, Uint8 *g, Uint8 *b, Uint8 *a);\n\n/** @sa SDL_CreateRGBSurface */\n#define SDL_AllocSurface    SDL_CreateRGBSurface\n/**\n * Allocate and free an RGB surface (must be called after SDL_SetVideoMode)\n * If the depth is 4 or 8 bits, an empty palette is allocated for the surface.\n * If the depth is greater than 8 bits, the pixel format is set using the\n * flags '[RGB]mask'.\n * If the function runs out of memory, it will return NULL.\n *\n * The 'flags' tell what kind of surface to create.\n * SDL_SWSURFACE means that the surface should be created in system memory.\n * SDL_HWSURFACE means that the surface should be created in video memory,\n * with the same format as the display surface.  This is useful for surfaces\n * that will not change much, to take advantage of hardware acceleration\n * when being blitted to the display surface.\n * SDL_ASYNCBLIT means that SDL will try to perform asynchronous blits with\n * this surface, but you must always lock it before accessing the pixels.\n * SDL will wait for current blits to finish before returning from the lock.\n * SDL_SRCCOLORKEY indicates that the surface will be used for colorkey blits.\n * If the hardware supports acceleration of colorkey blits between\n * two surfaces in video memory, SDL will try to place the surface in\n * video memory. If this isn't possible or if there is no hardware\n * acceleration available, the surface will be placed in system memory.\n * SDL_SRCALPHA means that the surface will be used for alpha blits and \n * if the hardware supports hardware acceleration of alpha blits between\n * two surfaces in video memory, to place the surface in video memory\n * if possible, otherwise it will be placed in system memory.\n * If the surface is created in video memory, blits will be _much_ faster,\n * but the surface format must be identical to the video surface format,\n * and the only way to access the pixels member of the surface is to use\n * the SDL_LockSurface() and SDL_UnlockSurface() calls.\n * If the requested surface actually resides in video memory, SDL_HWSURFACE\n * will be set in the flags member of the returned surface.  If for some\n * reason the surface could not be placed in video memory, it will not have\n * the SDL_HWSURFACE flag set, and will be created in system memory instead.\n */\nextern DECLSPEC SDL_Surface * SDLCALL SDL_CreateRGBSurface\n\t\t\t(Uint32 flags, int width, int height, int depth, \n\t\t\tUint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask);\n/** @sa SDL_CreateRGBSurface */\nextern DECLSPEC SDL_Surface * SDLCALL SDL_CreateRGBSurfaceFrom(void *pixels,\n\t\t\tint width, int height, int depth, int pitch,\n\t\t\tUint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask);\nextern DECLSPEC void SDLCALL SDL_FreeSurface(SDL_Surface *surface);\n\n/**\n * SDL_LockSurface() sets up a surface for directly accessing the pixels.\n * Between calls to SDL_LockSurface()/SDL_UnlockSurface(), you can write\n * to and read from 'surface->pixels', using the pixel format stored in \n * 'surface->format'.  Once you are done accessing the surface, you should \n * use SDL_UnlockSurface() to release it.\n *\n * Not all surfaces require locking.  If SDL_MUSTLOCK(surface) evaluates\n * to 0, then you can read and write to the surface at any time, and the\n * pixel format of the surface will not change.  In particular, if the\n * SDL_HWSURFACE flag is not given when calling SDL_SetVideoMode(), you\n * will not need to lock the display surface before accessing it.\n * \n * No operating system or library calls should be made between lock/unlock\n * pairs, as critical system locks may be held during this time.\n *\n * SDL_LockSurface() returns 0, or -1 if the surface couldn't be locked.\n */\nextern DECLSPEC int SDLCALL SDL_LockSurface(SDL_Surface *surface);\nextern DECLSPEC void SDLCALL SDL_UnlockSurface(SDL_Surface *surface);\n\n/**\n * Load a surface from a seekable SDL data source (memory or file.)\n * If 'freesrc' is non-zero, the source will be closed after being read.\n * Returns the new surface, or NULL if there was an error.\n * The new surface should be freed with SDL_FreeSurface().\n */\nextern DECLSPEC SDL_Surface * SDLCALL SDL_LoadBMP_RW(SDL_RWops *src, int freesrc);\n\n/** Convenience macro -- load a surface from a file */\n#define SDL_LoadBMP(file)\tSDL_LoadBMP_RW(SDL_RWFromFile(file, \"rb\"), 1)\n\n/**\n * Save a surface to a seekable SDL data source (memory or file.)\n * If 'freedst' is non-zero, the source will be closed after being written.\n * Returns 0 if successful or -1 if there was an error.\n */\nextern DECLSPEC int SDLCALL SDL_SaveBMP_RW\n\t\t(SDL_Surface *surface, SDL_RWops *dst, int freedst);\n\n/** Convenience macro -- save a surface to a file */\n#define SDL_SaveBMP(surface, file) \\\n\t\tSDL_SaveBMP_RW(surface, SDL_RWFromFile(file, \"wb\"), 1)\n\n/**\n * Sets the color key (transparent pixel) in a blittable surface.\n * If 'flag' is SDL_SRCCOLORKEY (optionally OR'd with SDL_RLEACCEL), \n * 'key' will be the transparent pixel in the source image of a blit.\n * SDL_RLEACCEL requests RLE acceleration for the surface if present,\n * and removes RLE acceleration if absent.\n * If 'flag' is 0, this function clears any current color key.\n * This function returns 0, or -1 if there was an error.\n */\nextern DECLSPEC int SDLCALL SDL_SetColorKey\n\t\t\t(SDL_Surface *surface, Uint32 flag, Uint32 key);\n\n/**\n * This function sets the alpha value for the entire surface, as opposed to\n * using the alpha component of each pixel. This value measures the range\n * of transparency of the surface, 0 being completely transparent to 255\n * being completely opaque. An 'alpha' value of 255 causes blits to be\n * opaque, the source pixels copied to the destination (the default). Note\n * that per-surface alpha can be combined with colorkey transparency.\n *\n * If 'flag' is 0, alpha blending is disabled for the surface.\n * If 'flag' is SDL_SRCALPHA, alpha blending is enabled for the surface.\n * OR:ing the flag with SDL_RLEACCEL requests RLE acceleration for the\n * surface; if SDL_RLEACCEL is not specified, the RLE accel will be removed.\n *\n * The 'alpha' parameter is ignored for surfaces that have an alpha channel.\n */\nextern DECLSPEC int SDLCALL SDL_SetAlpha(SDL_Surface *surface, Uint32 flag, Uint8 alpha);\n\n/**\n * Sets the clipping rectangle for the destination surface in a blit.\n *\n * If the clip rectangle is NULL, clipping will be disabled.\n * If the clip rectangle doesn't intersect the surface, the function will\n * return SDL_FALSE and blits will be completely clipped.  Otherwise the\n * function returns SDL_TRUE and blits to the surface will be clipped to\n * the intersection of the surface area and the clipping rectangle.\n *\n * Note that blits are automatically clipped to the edges of the source\n * and destination surfaces.\n */\nextern DECLSPEC SDL_bool SDLCALL SDL_SetClipRect(SDL_Surface *surface, const SDL_Rect *rect);\n\n/**\n * Gets the clipping rectangle for the destination surface in a blit.\n * 'rect' must be a pointer to a valid rectangle which will be filled\n * with the correct values.\n */\nextern DECLSPEC void SDLCALL SDL_GetClipRect(SDL_Surface *surface, SDL_Rect *rect);\n\n/**\n * Creates a new surface of the specified format, and then copies and maps \n * the given surface to it so the blit of the converted surface will be as \n * fast as possible.  If this function fails, it returns NULL.\n *\n * The 'flags' parameter is passed to SDL_CreateRGBSurface() and has those \n * semantics.  You can also pass SDL_RLEACCEL in the flags parameter and\n * SDL will try to RLE accelerate colorkey and alpha blits in the resulting\n * surface.\n *\n * This function is used internally by SDL_DisplayFormat().\n */\nextern DECLSPEC SDL_Surface * SDLCALL SDL_ConvertSurface\n\t\t\t(SDL_Surface *src, SDL_PixelFormat *fmt, Uint32 flags);\n\n/**\n * This performs a fast blit from the source surface to the destination\n * surface.  It assumes that the source and destination rectangles are\n * the same size.  If either 'srcrect' or 'dstrect' are NULL, the entire\n * surface (src or dst) is copied.  The final blit rectangles are saved\n * in 'srcrect' and 'dstrect' after all clipping is performed.\n * If the blit is successful, it returns 0, otherwise it returns -1.\n *\n * The blit function should not be called on a locked surface.\n *\n * The blit semantics for surfaces with and without alpha and colorkey\n * are defined as follows:\n *\n * RGBA->RGB:\n *     SDL_SRCALPHA set:\n * \talpha-blend (using alpha-channel).\n * \tSDL_SRCCOLORKEY ignored.\n *     SDL_SRCALPHA not set:\n * \tcopy RGB.\n * \tif SDL_SRCCOLORKEY set, only copy the pixels matching the\n * \tRGB values of the source colour key, ignoring alpha in the\n * \tcomparison.\n * \n * RGB->RGBA:\n *     SDL_SRCALPHA set:\n * \talpha-blend (using the source per-surface alpha value);\n * \tset destination alpha to opaque.\n *     SDL_SRCALPHA not set:\n * \tcopy RGB, set destination alpha to source per-surface alpha value.\n *     both:\n * \tif SDL_SRCCOLORKEY set, only copy the pixels matching the\n * \tsource colour key.\n * \n * RGBA->RGBA:\n *     SDL_SRCALPHA set:\n * \talpha-blend (using the source alpha channel) the RGB values;\n * \tleave destination alpha untouched. [Note: is this correct?]\n * \tSDL_SRCCOLORKEY ignored.\n *     SDL_SRCALPHA not set:\n * \tcopy all of RGBA to the destination.\n * \tif SDL_SRCCOLORKEY set, only copy the pixels matching the\n * \tRGB values of the source colour key, ignoring alpha in the\n * \tcomparison.\n * \n * RGB->RGB: \n *     SDL_SRCALPHA set:\n * \talpha-blend (using the source per-surface alpha value).\n *     SDL_SRCALPHA not set:\n * \tcopy RGB.\n *     both:\n * \tif SDL_SRCCOLORKEY set, only copy the pixels matching the\n * \tsource colour key.\n *\n * If either of the surfaces were in video memory, and the blit returns -2,\n * the video memory was lost, so it should be reloaded with artwork and \n * re-blitted:\n * @code\n *\twhile ( SDL_BlitSurface(image, imgrect, screen, dstrect) == -2 ) {\n *\t\twhile ( SDL_LockSurface(image) < 0 )\n *\t\t\tSleep(10);\n *\t\t-- Write image pixels to image->pixels --\n *\t\tSDL_UnlockSurface(image);\n *\t}\n * @endcode\n *\n * This happens under DirectX 5.0 when the system switches away from your\n * fullscreen application.  The lock will also fail until you have access\n * to the video memory again.\n *\n * You should call SDL_BlitSurface() unless you know exactly how SDL\n * blitting works internally and how to use the other blit functions.\n */\n#define SDL_BlitSurface SDL_UpperBlit\n\n/** This is the public blit function, SDL_BlitSurface(), and it performs\n *  rectangle validation and clipping before passing it to SDL_LowerBlit()\n */\nextern DECLSPEC int SDLCALL SDL_UpperBlit\n\t\t\t(SDL_Surface *src, SDL_Rect *srcrect,\n\t\t\t SDL_Surface *dst, SDL_Rect *dstrect);\n/** This is a semi-private blit function and it performs low-level surface\n *  blitting only.\n */\nextern DECLSPEC int SDLCALL SDL_LowerBlit\n\t\t\t(SDL_Surface *src, SDL_Rect *srcrect,\n\t\t\t SDL_Surface *dst, SDL_Rect *dstrect);\n\n/**\n * This function performs a fast fill of the given rectangle with 'color'\n * The given rectangle is clipped to the destination surface clip area\n * and the final fill rectangle is saved in the passed in pointer.\n * If 'dstrect' is NULL, the whole surface will be filled with 'color'\n * The color should be a pixel of the format used by the surface, and \n * can be generated by the SDL_MapRGB() function.\n * This function returns 0 on success, or -1 on error.\n */\nextern DECLSPEC int SDLCALL SDL_FillRect\n\t\t(SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color);\n\n/**\n * This function takes a surface and copies it to a new surface of the\n * pixel format and colors of the video framebuffer, suitable for fast\n * blitting onto the display surface.  It calls SDL_ConvertSurface()\n *\n * If you want to take advantage of hardware colorkey or alpha blit\n * acceleration, you should set the colorkey and alpha value before\n * calling this function.\n *\n * If the conversion fails or runs out of memory, it returns NULL\n */\nextern DECLSPEC SDL_Surface * SDLCALL SDL_DisplayFormat(SDL_Surface *surface);\n\n/**\n * This function takes a surface and copies it to a new surface of the\n * pixel format and colors of the video framebuffer (if possible),\n * suitable for fast alpha blitting onto the display surface.\n * The new surface will always have an alpha channel.\n *\n * If you want to take advantage of hardware colorkey or alpha blit\n * acceleration, you should set the colorkey and alpha value before\n * calling this function.\n *\n * If the conversion fails or runs out of memory, it returns NULL\n */\nextern DECLSPEC SDL_Surface * SDLCALL SDL_DisplayFormatAlpha(SDL_Surface *surface);\n\n\n/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */\n/** @name YUV video surface overlay functions                                */ /*@{*/\n/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */\n\n/** This function creates a video output overlay\n *  Calling the returned surface an overlay is something of a misnomer because\n *  the contents of the display surface underneath the area where the overlay\n *  is shown is undefined - it may be overwritten with the converted YUV data.\n */\nextern DECLSPEC SDL_Overlay * SDLCALL SDL_CreateYUVOverlay(int width, int height,\n\t\t\t\tUint32 format, SDL_Surface *display);\n\n/** Lock an overlay for direct access, and unlock it when you are done */\nextern DECLSPEC int SDLCALL SDL_LockYUVOverlay(SDL_Overlay *overlay);\nextern DECLSPEC void SDLCALL SDL_UnlockYUVOverlay(SDL_Overlay *overlay);\n\n/** Blit a video overlay to the display surface.\n *  The contents of the video surface underneath the blit destination are\n *  not defined.  \n *  The width and height of the destination rectangle may be different from\n *  that of the overlay, but currently only 2x scaling is supported.\n */\nextern DECLSPEC int SDLCALL SDL_DisplayYUVOverlay(SDL_Overlay *overlay, SDL_Rect *dstrect);\n\n/** Free a video overlay */\nextern DECLSPEC void SDLCALL SDL_FreeYUVOverlay(SDL_Overlay *overlay);\n\n/*@}*/\n\n/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */\n/** @name OpenGL support functions.                                          */ /*@{*/\n/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */\n\n/**\n * Dynamically load an OpenGL library, or the default one if path is NULL\n *\n * If you do this, you need to retrieve all of the GL functions used in\n * your program from the dynamic library using SDL_GL_GetProcAddress().\n */\nextern DECLSPEC int SDLCALL SDL_GL_LoadLibrary(const char *path);\n\n/**\n * Get the address of a GL function\n */\nextern DECLSPEC void * SDLCALL SDL_GL_GetProcAddress(const char* proc);\n\n/**\n * Set an attribute of the OpenGL subsystem before intialization.\n */\nextern DECLSPEC int SDLCALL SDL_GL_SetAttribute(SDL_GLattr attr, int value);\n\n/**\n * Get an attribute of the OpenGL subsystem from the windowing\n * interface, such as glX. This is of course different from getting\n * the values from SDL's internal OpenGL subsystem, which only\n * stores the values you request before initialization.\n *\n * Developers should track the values they pass into SDL_GL_SetAttribute\n * themselves if they want to retrieve these values.\n */\nextern DECLSPEC int SDLCALL SDL_GL_GetAttribute(SDL_GLattr attr, int* value);\n\n/**\n * Swap the OpenGL buffers, if double-buffering is supported.\n */\nextern DECLSPEC void SDLCALL SDL_GL_SwapBuffers(void);\n\n/** @name OpenGL Internal Functions\n * Internal functions that should not be called unless you have read\n * and understood the source code for these functions.\n */\n/*@{*/\nextern DECLSPEC void SDLCALL SDL_GL_UpdateRects(int numrects, SDL_Rect* rects);\nextern DECLSPEC void SDLCALL SDL_GL_Lock(void);\nextern DECLSPEC void SDLCALL SDL_GL_Unlock(void);\n/*@}*/\n\n/*@}*/\n\n/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */\n/** @name Window Manager Functions                                           */\n/** These functions allow interaction with the window manager, if any.       */ /*@{*/\n/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */\n\n/**\n * Sets the title and icon text of the display window (UTF-8 encoded)\n */\nextern DECLSPEC void SDLCALL SDL_WM_SetCaption(const char *title, const char *icon);\n/**\n * Gets the title and icon text of the display window (UTF-8 encoded)\n */\nextern DECLSPEC void SDLCALL SDL_WM_GetCaption(char **title, char **icon);\n\n/**\n * Sets the icon for the display window.\n * This function must be called before the first call to SDL_SetVideoMode().\n * It takes an icon surface, and a mask in MSB format.\n * If 'mask' is NULL, the entire icon surface will be used as the icon.\n */\nextern DECLSPEC void SDLCALL SDL_WM_SetIcon(SDL_Surface *icon, Uint8 *mask);\n\n/**\n * This function iconifies the window, and returns 1 if it succeeded.\n * If the function succeeds, it generates an SDL_APPACTIVE loss event.\n * This function is a noop and returns 0 in non-windowed environments.\n */\nextern DECLSPEC int SDLCALL SDL_WM_IconifyWindow(void);\n\n/**\n * Toggle fullscreen mode without changing the contents of the screen.\n * If the display surface does not require locking before accessing\n * the pixel information, then the memory pointers will not change.\n *\n * If this function was able to toggle fullscreen mode (change from \n * running in a window to fullscreen, or vice-versa), it will return 1.\n * If it is not implemented, or fails, it returns 0.\n *\n * The next call to SDL_SetVideoMode() will set the mode fullscreen\n * attribute based on the flags parameter - if SDL_FULLSCREEN is not\n * set, then the display will be windowed by default where supported.\n *\n * This is currently only implemented in the X11 video driver.\n */\nextern DECLSPEC int SDLCALL SDL_WM_ToggleFullScreen(SDL_Surface *surface);\n\ntypedef enum {\n\tSDL_GRAB_QUERY = -1,\n\tSDL_GRAB_OFF = 0,\n\tSDL_GRAB_ON = 1,\n\tSDL_GRAB_FULLSCREEN\t/**< Used internally */\n} SDL_GrabMode;\n/**\n * This function allows you to set and query the input grab state of\n * the application.  It returns the new input grab state.\n *\n * Grabbing means that the mouse is confined to the application window,\n * and nearly all keyboard input is passed directly to the application,\n * and not interpreted by a window manager, if any.\n */\nextern DECLSPEC SDL_GrabMode SDLCALL SDL_WM_GrabInput(SDL_GrabMode mode);\n\n/*@}*/\n\n/** @internal Not in public API at the moment - do not use! */\nextern DECLSPEC int SDLCALL SDL_SoftStretch(SDL_Surface *src, SDL_Rect *srcrect,\n                                    SDL_Surface *dst, SDL_Rect *dstrect);\n                    \n/* Ends C function definitions when using C++ */\n#ifdef __cplusplus\n}\n#endif\n#include \"close_code.h\"\n\n#endif /* _SDL_video_h */\n"
  },
  {
    "path": "deps/include/SDL/begin_code.h",
    "content": "/*\n    SDL - Simple DirectMedia Layer\n    Copyright (C) 1997-2012 Sam Lantinga\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Library General Public\n    License as published by the Free Software Foundation; either\n    version 2 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Library General Public License for more details.\n\n    You should have received a copy of the GNU Library General Public\n    License along with this library; if not, write to the Free\n    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n\n    Sam Lantinga\n    slouken@libsdl.org\n*/\n\n/** \n *  @file begin_code.h\n *  This file sets things up for C dynamic library function definitions,\n *  static inlined functions, and structures aligned at 4-byte alignment.\n *  If you don't like ugly C preprocessor code, don't look at this file. :)\n */\n\n/** \n *  @file begin_code.h\n *  This shouldn't be nested -- included it around code only.\n */\n#ifdef _begin_code_h\n#error Nested inclusion of begin_code.h\n#endif\n#define _begin_code_h\n\n/** \n *  @def DECLSPEC\n *  Some compilers use a special export keyword\n */\n#ifndef DECLSPEC\n# if defined(__BEOS__) || defined(__HAIKU__)\n#  if defined(__GNUC__)\n#   define DECLSPEC\n#  else\n#   define DECLSPEC\t__declspec(export)\n#  endif\n# elif defined(__WIN32__)\n#  ifdef __BORLANDC__\n#   ifdef BUILD_SDL\n#    define DECLSPEC \n#   else\n#    define DECLSPEC\t__declspec(dllimport)\n#   endif\n#  else\n#   define DECLSPEC\t__declspec(dllexport)\n#  endif\n# elif defined(__OS2__)\n#   ifdef BUILD_SDL\n#    define DECLSPEC\t__declspec(dllexport)\n#   else\n#    define DECLSPEC\n#   endif\n# else\n#  if defined(__GNUC__) && __GNUC__ >= 4\n#   define DECLSPEC\t__attribute__ ((visibility(\"default\")))\n#  else\n#   define DECLSPEC\n#  endif\n# endif\n#endif\n\n/** \n *  @def SDLCALL\n *  By default SDL uses the C calling convention\n */\n#ifndef SDLCALL\n# if defined(__WIN32__) && !defined(__GNUC__)\n#  define SDLCALL __cdecl\n# elif defined(__OS2__)\n   /* But on OS/2, we use the _System calling convention */\n   /* to be compatible with every compiler */\n#  if defined (__GNUC__) && !defined(_System)\n#   define _System /* For compatibility with old GCC/EMX */\n#  endif\n#  define SDLCALL _System\n# else\n#  define SDLCALL\n# endif\n#endif /* SDLCALL */\n\n#ifdef __SYMBIAN32__ \n#ifndef EKA2 \n#undef DECLSPEC\n#define DECLSPEC\n#elif !defined(__WINS__)\n#undef DECLSPEC\n#define DECLSPEC __declspec(dllexport)\n#endif /* !EKA2 */\n#endif /* __SYMBIAN32__ */\n\n/**\n *  @file begin_code.h\n *  Force structure packing at 4 byte alignment.\n *  This is necessary if the header is included in code which has structure\n *  packing set to an alternate value, say for loading structures from disk.\n *  The packing is reset to the previous value in close_code.h \n */\n#if defined(_MSC_VER) || defined(__MWERKS__) || defined(__BORLANDC__)\n#ifdef _MSC_VER\n#pragma warning(disable: 4103)\n#endif\n#ifdef __BORLANDC__\n#pragma nopackwarning\n#endif\n#ifdef _M_X64\n/* Use 8-byte alignment on 64-bit architectures, so pointers are aligned */\n#pragma pack(push,8)\n#else\n#pragma pack(push,4)\n#endif\n#elif (defined(__MWERKS__) && defined(__MACOS__))\n#pragma options align=mac68k4byte\n#pragma enumsalwaysint on\n#endif /* Compiler needs structure packing set */\n\n/**\n *  @def SDL_INLINE_OKAY\n *  Set up compiler-specific options for inlining functions\n */\n#ifndef SDL_INLINE_OKAY\n#ifdef __GNUC__\n#define SDL_INLINE_OKAY\n#else\n/* Add any special compiler-specific cases here */\n#if defined(_MSC_VER) || defined(__BORLANDC__) || \\\n    defined(__DMC__) || defined(__SC__) || \\\n    defined(__WATCOMC__) || defined(__LCC__) || \\\n    defined(__DECC) || defined(__EABI__)\n#ifndef __inline__\n#define __inline__\t__inline\n#endif\n#define SDL_INLINE_OKAY\n#else\n#if !defined(__MRC__) && !defined(_SGI_SOURCE)\n#ifndef __inline__\n#define __inline__ inline\n#endif\n#define SDL_INLINE_OKAY\n#endif /* Not a funky compiler */\n#endif /* Visual C++ */\n#endif /* GNU C */\n#endif /* SDL_INLINE_OKAY */\n\n/**\n *  @def __inline__\n *  If inlining isn't supported, remove \"__inline__\", turning static\n *  inlined functions into static functions (resulting in code bloat\n *  in all files which include the offending header files)\n */\n#ifndef SDL_INLINE_OKAY\n#define __inline__\n#endif\n\n/**\n *  @def NULL\n *  Apparently this is needed by several Windows compilers\n */\n#if !defined(__MACH__)\n#ifndef NULL\n#ifdef __cplusplus\n#define NULL 0\n#else\n#define NULL ((void *)0)\n#endif\n#endif /* NULL */\n#endif /* ! Mac OS X - breaks precompiled headers */\n"
  },
  {
    "path": "deps/include/SDL/close_code.h",
    "content": "/*\n    SDL - Simple DirectMedia Layer\n    Copyright (C) 1997-2012 Sam Lantinga\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Library General Public\n    License as published by the Free Software Foundation; either\n    version 2 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Library General Public License for more details.\n\n    You should have received a copy of the GNU Library General Public\n    License along with this library; if not, write to the Free\n    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n\n    Sam Lantinga\n    slouken@libsdl.org\n*/\n\n/**\n *  @file close_code.h\n *  This file reverses the effects of begin_code.h and should be included\n *  after you finish any function and structure declarations in your headers\n */\n\n#ifndef _begin_code_h\n#error close_code.h included without matching begin_code.h\n#endif\n#undef _begin_code_h\n\n/* Reset structure packing at previous byte alignment */\n#if defined(_MSC_VER) || defined(__MWERKS__) || defined(__BORLANDC__)\n#ifdef __BORLANDC__\n#pragma nopackwarning\n#endif\n#if (defined(__MWERKS__) && defined(__MACOS__))\n#pragma options align=reset\n#pragma enumsalwaysint reset\n#else\n#pragma pack(pop)\n#endif\n#endif /* Compiler needs structure packing set */\n"
  },
  {
    "path": "docs/CMakeLists.txt",
    "content": "include(GNUInstallDirs)\n\nfind_program ( DOXYGEN_EXECUTABLE\n  NAMES doxygen\n  DOC \"Doxygen program\" )\n\nif ( NOT ( DOXYGEN_EXECUTABLE MATCHES \"NOTFOUND\" ) )\n  message ( STATUS \"doxygen: ${DOXYGEN_EXECUTABLE}\" )\n  set ( top_srcdir \"${CMAKE_SOURCE_DIR}\" )\n  configure_file (\n\t    \"${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in\"\n\t    \"${CMAKE_CURRENT_BINARY_DIR}/Doxyfile\"\n  )\n\n  file ( READ\n  \"${CMAKE_CURRENT_BINARY_DIR}/Doxyfile\"\n    cmake_doxyfile )\n\n  if ( NOT (\"${CPACK_PACKAGE_VERSION_PATCH}\" STREQUAL \"\" ) )\n    set ( VERSION_EXTRA \".${CPACK_PACKAGE_VERSION_PATCH}\" )\n  endif ()\n\n  string ( REGEX REPLACE\n    \"PROJECT_NUMBER         = [0-9].[0-9]\"\n    \"PROJECT_NUMBER         = ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}${VERSION_EXTRA}\"\n    cmake_doxyfile\n    \"${cmake_doxyfile}\" )\n\n  file ( WRITE\n    \"${CMAKE_CURRENT_BINARY_DIR}/Doxyfile_cmake\"\n    \"${cmake_doxyfile}\" )\n\n  add_custom_target ( doxygen\n    COMMAND ${DOXYGEN_EXECUTABLE} \"${CMAKE_CURRENT_BINARY_DIR}/Doxyfile_cmake\"\n    WORKING_DIRECTORY \"${CMAKE_CURRENT_BINARY_DIR}\"\n    COMMENT \"Generating doxygen documentation\" )\nelse ()\n  message ( WARNING \"Doxygen not found. API documentation generation disabled.\" )\nendif ()\n\n# Only useful for make install/package under *nix OSes, but not macOS.\nif ( UNIX AND NOT APPLE )\n    INSTALL(FILES openxcom.6 DESTINATION ${CMAKE_INSTALL_MANDIR}/man6)\nendif ()\n"
  },
  {
    "path": "docs/Doxyfile.in",
    "content": "# Doxyfile 1.8.7\n\n# This file describes the settings to be used by the documentation system\n# doxygen (www.doxygen.org) for a project.\n#\n# All text after a double hash (##) is considered a comment and is placed in\n# front of the TAG it is preceding.\n#\n# All text after a single hash (#) is considered a comment and will be ignored.\n# The format is:\n# TAG = value [value, ...]\n# For lists, items can also be appended using:\n# TAG += value [value, ...]\n# Values that contain spaces should be placed between quotes (\\\" \\\").\n\n#---------------------------------------------------------------------------\n# Project related configuration options\n#---------------------------------------------------------------------------\n\n# This tag specifies the encoding used for all characters in the config file\n# that follow. The default is UTF-8 which is also the encoding used for all text\n# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv\n# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv\n# for the list of possible encodings.\n# The default value is: UTF-8.\n\nDOXYFILE_ENCODING      = UTF-8\n\n# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by\n# double-quotes, unless you are using Doxywizard) that should identify the\n# project for which the documentation is generated. This name is used in the\n# title of most generated pages and in a few other places.\n# The default value is: My Project.\n\nPROJECT_NAME           = OpenXcom\n\n# The PROJECT_NUMBER tag can be used to enter a project or revision number. This\n# could be handy for archiving the generated documentation or if some version\n# control system is used.\n\nPROJECT_NUMBER         = 1.0\n\n# Using the PROJECT_BRIEF tag one can provide an optional one line description\n# for a project that appears at the top of each page and should give viewer a\n# quick idea about the purpose of the project. Keep the description short.\n\nPROJECT_BRIEF          = \"Open-source clone of the original X-Com\"\n\n# With the PROJECT_LOGO tag one can specify an logo or icon that is included in\n# the documentation. The maximum height of the logo should not exceed 55 pixels\n# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo\n# to the output directory.\n\nPROJECT_LOGO           = @top_srcdir@/res/openxcom_wide.png\n\n# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path\n# into which the generated documentation will be written. If a relative path is\n# entered, it will be relative to the location where doxygen was started. If\n# left blank the current directory will be used.\n\nOUTPUT_DIRECTORY       = .\n\n# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub-\n# directories (in 2 levels) under the output directory of each output format and\n# will distribute the generated files over these directories. Enabling this\n# option can be useful when feeding doxygen a huge amount of source files, where\n# putting all generated files in the same directory would otherwise causes\n# performance problems for the file system.\n# The default value is: NO.\n\nCREATE_SUBDIRS         = NO\n\n# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII\n# characters to appear in the names of generated files. If set to NO, non-ASCII\n# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode\n# U+3044.\n# The default value is: NO.\n\nALLOW_UNICODE_NAMES    = NO\n\n# The OUTPUT_LANGUAGE tag is used to specify the language in which all\n# documentation generated by doxygen is written. Doxygen will use this\n# information to generate all constant output in the proper language.\n# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,\n# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),\n# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,\n# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),\n# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,\n# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,\n# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,\n# Ukrainian and Vietnamese.\n# The default value is: English.\n\nOUTPUT_LANGUAGE        = English\n\n# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member\n# descriptions after the members that are listed in the file and class\n# documentation (similar to Javadoc). Set to NO to disable this.\n# The default value is: YES.\n\nBRIEF_MEMBER_DESC      = YES\n\n# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief\n# description of a member or function before the detailed description\n#\n# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the\n# brief descriptions will be completely suppressed.\n# The default value is: YES.\n\nREPEAT_BRIEF           = YES\n\n# This tag implements a quasi-intelligent brief description abbreviator that is\n# used to form the text in various listings. Each string in this list, if found\n# as the leading text of the brief description, will be stripped from the text\n# and the result, after processing the whole list, is used as the annotated\n# text. Otherwise, the brief description is used as-is. If left blank, the\n# following values are used ($name is automatically replaced with the name of\n# the entity):The $name class, The $name widget, The $name file, is, provides,\n# specifies, contains, represents, a, an and the.\n\nABBREVIATE_BRIEF       = \"The $name class\" \\\n                         \"The $name widget\" \\\n                         \"The $name file\" \\\n                         is \\\n                         provides \\\n                         specifies \\\n                         contains \\\n                         represents \\\n                         a \\\n                         an \\\n                         the\n\n# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then\n# doxygen will generate a detailed section even if there is only a brief\n# description.\n# The default value is: NO.\n\nALWAYS_DETAILED_SEC    = NO\n\n# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all\n# inherited members of a class in the documentation of that class as if those\n# members were ordinary class members. Constructors, destructors and assignment\n# operators of the base classes will not be shown.\n# The default value is: NO.\n\nINLINE_INHERITED_MEMB  = NO\n\n# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path\n# before files name in the file list and in the header files. If set to NO the\n# shortest path that makes the file name unique will be used\n# The default value is: YES.\n\nFULL_PATH_NAMES        = NO\n\n# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.\n# Stripping is only done if one of the specified strings matches the left-hand\n# part of the path. The tag can be used to show relative paths in the file list.\n# If left blank the directory from which doxygen is run is used as the path to\n# strip.\n#\n# Note that you can specify absolute paths here, but also relative paths, which\n# will be relative from the directory where doxygen is started.\n# This tag requires that the tag FULL_PATH_NAMES is set to YES.\n\nSTRIP_FROM_PATH        =\n\n# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the\n# path mentioned in the documentation of a class, which tells the reader which\n# header file to include in order to use a class. If left blank only the name of\n# the header file containing the class definition is used. Otherwise one should\n# specify the list of include paths that are normally passed to the compiler\n# using the -I flag.\n\nSTRIP_FROM_INC_PATH    =\n\n# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but\n# less readable) file names. This can be useful is your file systems doesn't\n# support long names like on DOS, Mac, or CD-ROM.\n# The default value is: NO.\n\nSHORT_NAMES            = NO\n\n# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the\n# first line (until the first dot) of a Javadoc-style comment as the brief\n# description. If set to NO, the Javadoc-style will behave just like regular Qt-\n# style comments (thus requiring an explicit @brief command for a brief\n# description.)\n# The default value is: NO.\n\nJAVADOC_AUTOBRIEF      = YES\n\n# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first\n# line (until the first dot) of a Qt-style comment as the brief description. If\n# set to NO, the Qt-style will behave just like regular Qt-style comments (thus\n# requiring an explicit \\brief command for a brief description.)\n# The default value is: NO.\n\nQT_AUTOBRIEF           = NO\n\n# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a\n# multi-line C++ special comment block (i.e. a block of //! or /// comments) as\n# a brief description. This used to be the default behavior. The new default is\n# to treat a multi-line C++ comment block as a detailed description. Set this\n# tag to YES if you prefer the old behavior instead.\n#\n# Note that setting this tag to YES also means that rational rose comments are\n# not recognized any more.\n# The default value is: NO.\n\nMULTILINE_CPP_IS_BRIEF = YES\n\n# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the\n# documentation from any documented member that it re-implements.\n# The default value is: YES.\n\nINHERIT_DOCS           = YES\n\n# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a\n# new page for each member. If set to NO, the documentation of a member will be\n# part of the file/class/namespace that contains it.\n# The default value is: NO.\n\nSEPARATE_MEMBER_PAGES  = NO\n\n# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen\n# uses this value to replace tabs by spaces in code fragments.\n# Minimum value: 1, maximum value: 16, default value: 4.\n\nTAB_SIZE               = 4\n\n# This tag can be used to specify a number of aliases that act as commands in\n# the documentation. An alias has the form:\n# name=value\n# For example adding\n# \"sideeffect=@par Side Effects:\\n\"\n# will allow you to put the command \\sideeffect (or @sideeffect) in the\n# documentation, which will result in a user-defined paragraph with heading\n# \"Side Effects:\". You can put \\n's in the value part of an alias to insert\n# newlines.\n\nALIASES                =\n\n# This tag can be used to specify a number of word-keyword mappings (TCL only).\n# A mapping has the form \"name=value\". For example adding \"class=itcl::class\"\n# will allow you to use the command class in the itcl::class meaning.\n\nTCL_SUBST              =\n\n# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources\n# only. Doxygen will then generate output that is more tailored for C. For\n# instance, some of the names that are used will be different. The list of all\n# members will be omitted, etc.\n# The default value is: NO.\n\nOPTIMIZE_OUTPUT_FOR_C  = NO\n\n# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or\n# Python sources only. Doxygen will then generate output that is more tailored\n# for that language. For instance, namespaces will be presented as packages,\n# qualified scopes will look different, etc.\n# The default value is: NO.\n\nOPTIMIZE_OUTPUT_JAVA   = NO\n\n# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran\n# sources. Doxygen will then generate output that is tailored for Fortran.\n# The default value is: NO.\n\nOPTIMIZE_FOR_FORTRAN   = NO\n\n# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL\n# sources. Doxygen will then generate output that is tailored for VHDL.\n# The default value is: NO.\n\nOPTIMIZE_OUTPUT_VHDL   = NO\n\n# Doxygen selects the parser to use depending on the extension of the files it\n# parses. With this tag you can assign which parser to use for a given\n# extension. Doxygen has a built-in mapping, but you can override or extend it\n# using this tag. The format is ext=language, where ext is a file extension, and\n# language is one of the parsers supported by doxygen: IDL, Java, Javascript,\n# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:\n# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:\n# Fortran. In the later case the parser tries to guess whether the code is fixed\n# or free formatted code, this is the default for Fortran type files), VHDL. For\n# instance to make doxygen treat .inc files as Fortran files (default is PHP),\n# and .f files as C (default is Fortran), use: inc=Fortran f=C.\n#\n# Note For files without extension you can use no_extension as a placeholder.\n#\n# Note that for custom extensions you also need to set FILE_PATTERNS otherwise\n# the files are not read by doxygen.\n\nEXTENSION_MAPPING      =\n\n# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments\n# according to the Markdown format, which allows for more readable\n# documentation. See http://daringfireball.net/projects/markdown/ for details.\n# The output of markdown processing is further processed by doxygen, so you can\n# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in\n# case of backward compatibilities issues.\n# The default value is: YES.\n\nMARKDOWN_SUPPORT       = YES\n\n# When enabled doxygen tries to link words that correspond to documented\n# classes, or namespaces to their corresponding documentation. Such a link can\n# be prevented in individual cases by by putting a % sign in front of the word\n# or globally by setting AUTOLINK_SUPPORT to NO.\n# The default value is: YES.\n\nAUTOLINK_SUPPORT       = YES\n\n# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want\n# to include (a tag file for) the STL sources as input, then you should set this\n# tag to YES in order to let doxygen match functions declarations and\n# definitions whose arguments contain STL classes (e.g. func(std::string);\n# versus func(std::string) {}). This also make the inheritance and collaboration\n# diagrams that involve STL classes more complete and accurate.\n# The default value is: NO.\n\nBUILTIN_STL_SUPPORT    = NO\n\n# If you use Microsoft's C++/CLI language, you should set this option to YES to\n# enable parsing support.\n# The default value is: NO.\n\nCPP_CLI_SUPPORT        = NO\n\n# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:\n# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen\n# will parse them like normal C++ but will assume all classes use public instead\n# of private inheritance when no explicit protection keyword is present.\n# The default value is: NO.\n\nSIP_SUPPORT            = NO\n\n# For Microsoft's IDL there are propget and propput attributes to indicate\n# getter and setter methods for a property. Setting this option to YES will make\n# doxygen to replace the get and set methods by a property in the documentation.\n# This will only work if the methods are indeed getting or setting a simple\n# type. If this is not the case, or you want to show the methods anyway, you\n# should set this option to NO.\n# The default value is: YES.\n\nIDL_PROPERTY_SUPPORT   = YES\n\n# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC\n# tag is set to YES, then doxygen will reuse the documentation of the first\n# member in the group (if any) for the other members of the group. By default\n# all members of a group must be documented explicitly.\n# The default value is: NO.\n\nDISTRIBUTE_GROUP_DOC   = NO\n\n# Set the SUBGROUPING tag to YES to allow class member groups of the same type\n# (for instance a group of public functions) to be put as a subgroup of that\n# type (e.g. under the Public Functions section). Set it to NO to prevent\n# subgrouping. Alternatively, this can be done per class using the\n# \\nosubgrouping command.\n# The default value is: YES.\n\nSUBGROUPING            = YES\n\n# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions\n# are shown inside the group in which they are included (e.g. using \\ingroup)\n# instead of on a separate page (for HTML and Man pages) or section (for LaTeX\n# and RTF).\n#\n# Note that this feature does not work in combination with\n# SEPARATE_MEMBER_PAGES.\n# The default value is: NO.\n\nINLINE_GROUPED_CLASSES = NO\n\n# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions\n# with only public data fields or simple typedef fields will be shown inline in\n# the documentation of the scope in which they are defined (i.e. file,\n# namespace, or group documentation), provided this scope is documented. If set\n# to NO, structs, classes, and unions are shown on a separate page (for HTML and\n# Man pages) or section (for LaTeX and RTF).\n# The default value is: NO.\n\nINLINE_SIMPLE_STRUCTS  = NO\n\n# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or\n# enum is documented as struct, union, or enum with the name of the typedef. So\n# typedef struct TypeS {} TypeT, will appear in the documentation as a struct\n# with name TypeT. When disabled the typedef will appear as a member of a file,\n# namespace, or class. And the struct will be named TypeS. This can typically be\n# useful for C code in case the coding convention dictates that all compound\n# types are typedef'ed and only the typedef is referenced, never the tag name.\n# The default value is: NO.\n\nTYPEDEF_HIDES_STRUCT   = NO\n\n# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This\n# cache is used to resolve symbols given their name and scope. Since this can be\n# an expensive process and often the same symbol appears multiple times in the\n# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small\n# doxygen will become slower. If the cache is too large, memory is wasted. The\n# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range\n# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536\n# symbols. At the end of a run doxygen will report the cache usage and suggest\n# the optimal cache size from a speed point of view.\n# Minimum value: 0, maximum value: 9, default value: 0.\n\nLOOKUP_CACHE_SIZE      = 0\n\n#---------------------------------------------------------------------------\n# Build related configuration options\n#---------------------------------------------------------------------------\n\n# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in\n# documentation are documented, even if no documentation was available. Private\n# class members and static file members will be hidden unless the\n# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.\n# Note: This will also disable the warnings about undocumented members that are\n# normally produced when WARNINGS is set to YES.\n# The default value is: NO.\n\nEXTRACT_ALL            = NO\n\n# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will\n# be included in the documentation.\n# The default value is: NO.\n\nEXTRACT_PRIVATE        = NO\n\n# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal\n# scope will be included in the documentation.\n# The default value is: NO.\n\nEXTRACT_PACKAGE        = NO\n\n# If the EXTRACT_STATIC tag is set to YES all static members of a file will be\n# included in the documentation.\n# The default value is: NO.\n\nEXTRACT_STATIC         = NO\n\n# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined\n# locally in source files will be included in the documentation. If set to NO\n# only classes defined in header files are included. Does not have any effect\n# for Java sources.\n# The default value is: YES.\n\nEXTRACT_LOCAL_CLASSES  = YES\n\n# This flag is only useful for Objective-C code. When set to YES local methods,\n# which are defined in the implementation section but not in the interface are\n# included in the documentation. If set to NO only methods in the interface are\n# included.\n# The default value is: NO.\n\nEXTRACT_LOCAL_METHODS  = NO\n\n# If this flag is set to YES, the members of anonymous namespaces will be\n# extracted and appear in the documentation as a namespace called\n# 'anonymous_namespace{file}', where file will be replaced with the base name of\n# the file that contains the anonymous namespace. By default anonymous namespace\n# are hidden.\n# The default value is: NO.\n\nEXTRACT_ANON_NSPACES   = NO\n\n# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all\n# undocumented members inside documented classes or files. If set to NO these\n# members will be included in the various overviews, but no documentation\n# section is generated. This option has no effect if EXTRACT_ALL is enabled.\n# The default value is: NO.\n\nHIDE_UNDOC_MEMBERS     = YES\n\n# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all\n# undocumented classes that are normally visible in the class hierarchy. If set\n# to NO these classes will be included in the various overviews. This option has\n# no effect if EXTRACT_ALL is enabled.\n# The default value is: NO.\n\nHIDE_UNDOC_CLASSES     = NO\n\n# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend\n# (class|struct|union) declarations. If set to NO these declarations will be\n# included in the documentation.\n# The default value is: NO.\n\nHIDE_FRIEND_COMPOUNDS  = NO\n\n# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any\n# documentation blocks found inside the body of a function. If set to NO these\n# blocks will be appended to the function's detailed documentation block.\n# The default value is: NO.\n\nHIDE_IN_BODY_DOCS      = NO\n\n# The INTERNAL_DOCS tag determines if documentation that is typed after a\n# \\internal command is included. If the tag is set to NO then the documentation\n# will be excluded. Set it to YES to include the internal documentation.\n# The default value is: NO.\n\nINTERNAL_DOCS          = NO\n\n# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file\n# names in lower-case letters. If set to YES upper-case letters are also\n# allowed. This is useful if you have classes or files whose names only differ\n# in case and if your file system supports case sensitive file names. Windows\n# and Mac users are advised to set this option to NO.\n# The default value is: system dependent.\n\nCASE_SENSE_NAMES       = NO\n\n# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with\n# their full class and namespace scopes in the documentation. If set to YES the\n# scope will be hidden.\n# The default value is: NO.\n\nHIDE_SCOPE_NAMES       = NO\n\n# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of\n# the files that are included by a file in the documentation of that file.\n# The default value is: YES.\n\nSHOW_INCLUDE_FILES     = YES\n\n# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each\n# grouped member an include statement to the documentation, telling the reader\n# which file to include in order to use the member.\n# The default value is: NO.\n\nSHOW_GROUPED_MEMB_INC  = NO\n\n# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include\n# files with double quotes in the documentation rather than with sharp brackets.\n# The default value is: NO.\n\nFORCE_LOCAL_INCLUDES   = NO\n\n# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the\n# documentation for inline members.\n# The default value is: YES.\n\nINLINE_INFO            = YES\n\n# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the\n# (detailed) documentation of file and class members alphabetically by member\n# name. If set to NO the members will appear in declaration order.\n# The default value is: YES.\n\nSORT_MEMBER_DOCS       = YES\n\n# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief\n# descriptions of file, namespace and class members alphabetically by member\n# name. If set to NO the members will appear in declaration order. Note that\n# this will also influence the order of the classes in the class list.\n# The default value is: NO.\n\nSORT_BRIEF_DOCS        = NO\n\n# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the\n# (brief and detailed) documentation of class members so that constructors and\n# destructors are listed first. If set to NO the constructors will appear in the\n# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.\n# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief\n# member documentation.\n# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting\n# detailed member documentation.\n# The default value is: NO.\n\nSORT_MEMBERS_CTORS_1ST = NO\n\n# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy\n# of group names into alphabetical order. If set to NO the group names will\n# appear in their defined order.\n# The default value is: NO.\n\nSORT_GROUP_NAMES       = NO\n\n# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by\n# fully-qualified names, including namespaces. If set to NO, the class list will\n# be sorted only by class name, not including the namespace part.\n# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.\n# Note: This option applies only to the class list, not to the alphabetical\n# list.\n# The default value is: NO.\n\nSORT_BY_SCOPE_NAME     = NO\n\n# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper\n# type resolution of all parameters of a function it will reject a match between\n# the prototype and the implementation of a member function even if there is\n# only one candidate or it is obvious which candidate to choose by doing a\n# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still\n# accept a match between prototype and implementation in such cases.\n# The default value is: NO.\n\nSTRICT_PROTO_MATCHING  = NO\n\n# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the\n# todo list. This list is created by putting \\todo commands in the\n# documentation.\n# The default value is: YES.\n\nGENERATE_TODOLIST      = YES\n\n# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the\n# test list. This list is created by putting \\test commands in the\n# documentation.\n# The default value is: YES.\n\nGENERATE_TESTLIST      = YES\n\n# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug\n# list. This list is created by putting \\bug commands in the documentation.\n# The default value is: YES.\n\nGENERATE_BUGLIST       = YES\n\n# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO)\n# the deprecated list. This list is created by putting \\deprecated commands in\n# the documentation.\n# The default value is: YES.\n\nGENERATE_DEPRECATEDLIST= YES\n\n# The ENABLED_SECTIONS tag can be used to enable conditional documentation\n# sections, marked by \\if <section_label> ... \\endif and \\cond <section_label>\n# ... \\endcond blocks.\n\nENABLED_SECTIONS       =\n\n# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the\n# initial value of a variable or macro / define can have for it to appear in the\n# documentation. If the initializer consists of more lines than specified here\n# it will be hidden. Use a value of 0 to hide initializers completely. The\n# appearance of the value of individual variables and macros / defines can be\n# controlled using \\showinitializer or \\hideinitializer command in the\n# documentation regardless of this setting.\n# Minimum value: 0, maximum value: 10000, default value: 30.\n\nMAX_INITIALIZER_LINES  = 30\n\n# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at\n# the bottom of the documentation of classes and structs. If set to YES the list\n# will mention the files that were used to generate the documentation.\n# The default value is: YES.\n\nSHOW_USED_FILES        = YES\n\n# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This\n# will remove the Files entry from the Quick Index and from the Folder Tree View\n# (if specified).\n# The default value is: YES.\n\nSHOW_FILES             = YES\n\n# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces\n# page. This will remove the Namespaces entry from the Quick Index and from the\n# Folder Tree View (if specified).\n# The default value is: YES.\n\nSHOW_NAMESPACES        = YES\n\n# The FILE_VERSION_FILTER tag can be used to specify a program or script that\n# doxygen should invoke to get the current version for each file (typically from\n# the version control system). Doxygen will invoke the program by executing (via\n# popen()) the command command input-file, where command is the value of the\n# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided\n# by doxygen. Whatever the program writes to standard output is used as the file\n# version. For an example see the documentation.\n\nFILE_VERSION_FILTER    =\n\n# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed\n# by doxygen. The layout file controls the global structure of the generated\n# output files in an output format independent way. To create the layout file\n# that represents doxygen's defaults, run doxygen with the -l option. You can\n# optionally specify a file name after the option, if omitted DoxygenLayout.xml\n# will be used as the name of the layout file.\n#\n# Note that if you run doxygen from a directory containing a file called\n# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE\n# tag is left empty.\n\nLAYOUT_FILE            =\n\n# The CITE_BIB_FILES tag can be used to specify one or more bib files containing\n# the reference definitions. This must be a list of .bib files. The .bib\n# extension is automatically appended if omitted. This requires the bibtex tool\n# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.\n# For LaTeX the style of the bibliography can be controlled using\n# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the\n# search path. Do not use file names with spaces, bibtex cannot handle them. See\n# also \\cite for info how to create references.\n\nCITE_BIB_FILES         =\n\n#---------------------------------------------------------------------------\n# Configuration options related to warning and progress messages\n#---------------------------------------------------------------------------\n\n# The QUIET tag can be used to turn on/off the messages that are generated to\n# standard output by doxygen. If QUIET is set to YES this implies that the\n# messages are off.\n# The default value is: NO.\n\nQUIET                  = NO\n\n# The WARNINGS tag can be used to turn on/off the warning messages that are\n# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES\n# this implies that the warnings are on.\n#\n# Tip: Turn warnings on while writing the documentation.\n# The default value is: YES.\n\nWARNINGS               = YES\n\n# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate\n# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag\n# will automatically be disabled.\n# The default value is: YES.\n\nWARN_IF_UNDOCUMENTED   = YES\n\n# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for\n# potential errors in the documentation, such as not documenting some parameters\n# in a documented function, or documenting parameters that don't exist or using\n# markup commands wrongly.\n# The default value is: YES.\n\nWARN_IF_DOC_ERROR      = YES\n\n# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that\n# are documented, but have no documentation for their parameters or return\n# value. If set to NO doxygen will only warn about wrong or incomplete parameter\n# documentation, but not about the absence of documentation.\n# The default value is: NO.\n\nWARN_NO_PARAMDOC       = YES\n\n# The WARN_FORMAT tag determines the format of the warning messages that doxygen\n# can produce. The string should contain the $file, $line, and $text tags, which\n# will be replaced by the file and line number from which the warning originated\n# and the warning text. Optionally the format may contain $version, which will\n# be replaced by the version of the file (if it could be obtained via\n# FILE_VERSION_FILTER)\n# The default value is: $file:$line: $text.\n\nWARN_FORMAT            = \"$file:$line: $text\"\n\n# The WARN_LOGFILE tag can be used to specify a file to which warning and error\n# messages should be written. If left blank the output is written to standard\n# error (stderr).\n\nWARN_LOGFILE           =\n\n#---------------------------------------------------------------------------\n# Configuration options related to the input files\n#---------------------------------------------------------------------------\n\n# The INPUT tag is used to specify the files and/or directories that contain\n# documented source files. You may enter file names like myfile.cpp or\n# directories like /usr/src/myproject. Separate the files or directories with\n# spaces.\n# Note: If this tag is empty the current directory is searched.\n\nINPUT                  = @top_srcdir@/src\n\n# This tag can be used to specify the character encoding of the source files\n# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses\n# libiconv (or the iconv built into libc) for the transcoding. See the libiconv\n# documentation (see: http://www.gnu.org/software/libiconv) for the list of\n# possible encodings.\n# The default value is: UTF-8.\n\nINPUT_ENCODING         = UTF-8\n\n# If the value of the INPUT tag contains directories, you can use the\n# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and\n# *.h) to filter out the source-files in the directories. If left blank the\n# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,\n# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,\n# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,\n# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,\n# *.qsf, *.as and *.js.\n\nFILE_PATTERNS          = *.c \\\n                         *.cc \\\n                         *.cxx \\\n                         *.cpp \\\n                         *.c++ \\\n                         *.inl \\\n                         *.h \\\n                         *.hh \\\n                         *.hxx \\\n                         *.hpp \\\n                         *.h++ \\\n                         *.inc\n\n# The RECURSIVE tag can be used to specify whether or not subdirectories should\n# be searched for input files as well.\n# The default value is: NO.\n\nRECURSIVE              = YES\n\n# The EXCLUDE tag can be used to specify files and/or directories that should be\n# excluded from the INPUT source files. This way you can easily exclude a\n# subdirectory from a directory tree whose root is specified with the INPUT tag.\n#\n# Note that relative paths are relative to the directory from which doxygen is\n# run.\n\nEXCLUDE                = resource.h \\\n                         ipch \\\n                         dirent.h \\\n                         lodepng.cpp \\\n                         lodepng.h\n\n# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or\n# directories that are symbolic links (a Unix file system feature) are excluded\n# from the input.\n# The default value is: NO.\n\nEXCLUDE_SYMLINKS       = NO\n\n# If the value of the INPUT tag contains directories, you can use the\n# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude\n# certain files from those directories.\n#\n# Note that the wildcards are matched against the file with absolute path, so to\n# exclude all test directories for example use the pattern */test/*\n\nEXCLUDE_PATTERNS       = */ipch/* \\\n                         resource.h \\\n                         dirent.h \\\n                         lodepng.cpp \\\n                         lodepng.h\n\n# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names\n# (namespaces, classes, functions, etc.) that should be excluded from the\n# output. The symbol name can be a fully qualified name, a word, or if the\n# wildcard * is used, a substring. Examples: ANamespace, AClass,\n# AClass::ANamespace, ANamespace::*Test\n#\n# Note that the wildcards are matched against the file with absolute path, so to\n# exclude all test directories use the pattern */test/*\n\nEXCLUDE_SYMBOLS        =\n\n# The EXAMPLE_PATH tag can be used to specify one or more files or directories\n# that contain example code fragments that are included (see the \\include\n# command).\n\nEXAMPLE_PATH           =\n\n# If the value of the EXAMPLE_PATH tag contains directories, you can use the\n# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and\n# *.h) to filter out the source-files in the directories. If left blank all\n# files are included.\n\nEXAMPLE_PATTERNS       = *\n\n# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be\n# searched for input files to be used with the \\include or \\dontinclude commands\n# irrespective of the value of the RECURSIVE tag.\n# The default value is: NO.\n\nEXAMPLE_RECURSIVE      = NO\n\n# The IMAGE_PATH tag can be used to specify one or more files or directories\n# that contain images that are to be included in the documentation (see the\n# \\image command).\n\nIMAGE_PATH             =\n\n# The INPUT_FILTER tag can be used to specify a program that doxygen should\n# invoke to filter for each input file. Doxygen will invoke the filter program\n# by executing (via popen()) the command:\n#\n# <filter> <input-file>\n#\n# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the\n# name of an input file. Doxygen will then use the output that the filter\n# program writes to standard output. If FILTER_PATTERNS is specified, this tag\n# will be ignored.\n#\n# Note that the filter must not add or remove lines; it is applied before the\n# code is scanned, but not when the output code is generated. If lines are added\n# or removed, the anchors will not be placed correctly.\n\nINPUT_FILTER           =\n\n# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern\n# basis. Doxygen will compare the file name with each pattern and apply the\n# filter if there is a match. The filters are a list of the form: pattern=filter\n# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how\n# filters are used. If the FILTER_PATTERNS tag is empty or if none of the\n# patterns match the file name, INPUT_FILTER is applied.\n\nFILTER_PATTERNS        =\n\n# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using\n# INPUT_FILTER ) will also be used to filter the input files that are used for\n# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).\n# The default value is: NO.\n\nFILTER_SOURCE_FILES    = NO\n\n# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file\n# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and\n# it is also possible to disable source filtering for a specific pattern using\n# *.ext= (so without naming a filter).\n# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.\n\nFILTER_SOURCE_PATTERNS =\n\n# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that\n# is part of the input, its contents will be placed on the main page\n# (index.html). This can be useful if you have a project on for instance GitHub\n# and want to reuse the introduction page also for the doxygen output.\n\nUSE_MDFILE_AS_MAINPAGE =\n\n#---------------------------------------------------------------------------\n# Configuration options related to source browsing\n#---------------------------------------------------------------------------\n\n# If the SOURCE_BROWSER tag is set to YES then a list of source files will be\n# generated. Documented entities will be cross-referenced with these sources.\n#\n# Note: To get rid of all source code in the generated output, make sure that\n# also VERBATIM_HEADERS is set to NO.\n# The default value is: NO.\n\nSOURCE_BROWSER         = NO\n\n# Setting the INLINE_SOURCES tag to YES will include the body of functions,\n# classes and enums directly into the documentation.\n# The default value is: NO.\n\nINLINE_SOURCES         = NO\n\n# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any\n# special comment blocks from generated source code fragments. Normal C, C++ and\n# Fortran comments will always remain visible.\n# The default value is: YES.\n\nSTRIP_CODE_COMMENTS    = YES\n\n# If the REFERENCED_BY_RELATION tag is set to YES then for each documented\n# function all documented functions referencing it will be listed.\n# The default value is: NO.\n\nREFERENCED_BY_RELATION = NO\n\n# If the REFERENCES_RELATION tag is set to YES then for each documented function\n# all documented entities called/used by that function will be listed.\n# The default value is: NO.\n\nREFERENCES_RELATION    = NO\n\n# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set\n# to YES, then the hyperlinks from functions in REFERENCES_RELATION and\n# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will\n# link to the documentation.\n# The default value is: YES.\n\nREFERENCES_LINK_SOURCE = YES\n\n# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the\n# source code will show a tooltip with additional information such as prototype,\n# brief description and links to the definition and documentation. Since this\n# will make the HTML file larger and loading of large files a bit slower, you\n# can opt to disable this feature.\n# The default value is: YES.\n# This tag requires that the tag SOURCE_BROWSER is set to YES.\n\nSOURCE_TOOLTIPS        = YES\n\n# If the USE_HTAGS tag is set to YES then the references to source code will\n# point to the HTML generated by the htags(1) tool instead of doxygen built-in\n# source browser. The htags tool is part of GNU's global source tagging system\n# (see http://www.gnu.org/software/global/global.html). You will need version\n# 4.8.6 or higher.\n#\n# To use it do the following:\n# - Install the latest version of global\n# - Enable SOURCE_BROWSER and USE_HTAGS in the config file\n# - Make sure the INPUT points to the root of the source tree\n# - Run doxygen as normal\n#\n# Doxygen will invoke htags (and that will in turn invoke gtags), so these\n# tools must be available from the command line (i.e. in the search path).\n#\n# The result: instead of the source browser generated by doxygen, the links to\n# source code will now point to the output of htags.\n# The default value is: NO.\n# This tag requires that the tag SOURCE_BROWSER is set to YES.\n\nUSE_HTAGS              = NO\n\n# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a\n# verbatim copy of the header file for each class for which an include is\n# specified. Set to NO to disable this.\n# See also: Section \\class.\n# The default value is: YES.\n\nVERBATIM_HEADERS       = YES\n\n# If the CLANG_ASSISTED_PARSING tag is set to YES, then doxygen will use the\n# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the\n# cost of reduced performance. This can be particularly helpful with template\n# rich C++ code for which doxygen's built-in parser lacks the necessary type\n# information.\n# Note: The availability of this option depends on whether or not doxygen was\n# compiled with the --with-libclang option.\n# The default value is: NO.\n\nCLANG_ASSISTED_PARSING = NO\n\n# If clang assisted parsing is enabled you can provide the compiler with command\n# line options that you would normally use when invoking the compiler. Note that\n# the include paths will already be set by doxygen for the files and directories\n# specified with INPUT and INCLUDE_PATH.\n# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.\n\nCLANG_OPTIONS          =\n\n#---------------------------------------------------------------------------\n# Configuration options related to the alphabetical class index\n#---------------------------------------------------------------------------\n\n# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all\n# compounds will be generated. Enable this if the project contains a lot of\n# classes, structs, unions or interfaces.\n# The default value is: YES.\n\nALPHABETICAL_INDEX     = YES\n\n# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in\n# which the alphabetical index list will be split.\n# Minimum value: 1, maximum value: 20, default value: 5.\n# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.\n\nCOLS_IN_ALPHA_INDEX    = 5\n\n# In case all classes in a project start with a common prefix, all classes will\n# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag\n# can be used to specify a prefix (or a list of prefixes) that should be ignored\n# while generating the index headers.\n# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.\n\nIGNORE_PREFIX          =\n\n#---------------------------------------------------------------------------\n# Configuration options related to the HTML output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output\n# The default value is: YES.\n\nGENERATE_HTML          = YES\n\n# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a\n# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of\n# it.\n# The default directory is: html.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_OUTPUT            = html\n\n# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each\n# generated HTML page (for example: .htm, .php, .asp).\n# The default value is: .html.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_FILE_EXTENSION    = .html\n\n# The HTML_HEADER tag can be used to specify a user-defined HTML header file for\n# each generated HTML page. If the tag is left blank doxygen will generate a\n# standard header.\n#\n# To get valid HTML the header file that includes any scripts and style sheets\n# that doxygen needs, which is dependent on the configuration options used (e.g.\n# the setting GENERATE_TREEVIEW). It is highly recommended to start with a\n# default header using\n# doxygen -w html new_header.html new_footer.html new_stylesheet.css\n# YourConfigFile\n# and then modify the file new_header.html. See also section \"Doxygen usage\"\n# for information on how to generate the default header that doxygen normally\n# uses.\n# Note: The header is subject to change so you typically have to regenerate the\n# default header when upgrading to a newer version of doxygen. For a description\n# of the possible markers and block names see the documentation.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_HEADER            =\n\n# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each\n# generated HTML page. If the tag is left blank doxygen will generate a standard\n# footer. See HTML_HEADER for more information on how to generate a default\n# footer and what special commands can be used inside the footer. See also\n# section \"Doxygen usage\" for information on how to generate the default footer\n# that doxygen normally uses.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_FOOTER            =\n\n# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style\n# sheet that is used by each HTML page. It can be used to fine-tune the look of\n# the HTML output. If left blank doxygen will generate a default style sheet.\n# See also section \"Doxygen usage\" for information on how to generate the style\n# sheet that doxygen normally uses.\n# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as\n# it is more robust and this tag (HTML_STYLESHEET) will in the future become\n# obsolete.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_STYLESHEET        =\n\n# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user-\n# defined cascading style sheet that is included after the standard style sheets\n# created by doxygen. Using this option one can overrule certain style aspects.\n# This is preferred over using HTML_STYLESHEET since it does not replace the\n# standard style sheet and is therefor more robust against future updates.\n# Doxygen will copy the style sheet file to the output directory. For an example\n# see the documentation.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_EXTRA_STYLESHEET  =\n\n# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or\n# other source files which should be copied to the HTML output directory. Note\n# that these files will be copied to the base HTML output directory. Use the\n# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these\n# files. In the HTML_STYLESHEET file, use the file name only. Also note that the\n# files will be copied as-is; there are no commands or markers available.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_EXTRA_FILES       =\n\n# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen\n# will adjust the colors in the stylesheet and background images according to\n# this color. Hue is specified as an angle on a colorwheel, see\n# http://en.wikipedia.org/wiki/Hue for more information. For instance the value\n# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300\n# purple, and 360 is red again.\n# Minimum value: 0, maximum value: 359, default value: 220.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_COLORSTYLE_HUE    = 220\n\n# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors\n# in the HTML output. For a value of 0 the output will use grayscales only. A\n# value of 255 will produce the most vivid colors.\n# Minimum value: 0, maximum value: 255, default value: 100.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_COLORSTYLE_SAT    = 100\n\n# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the\n# luminance component of the colors in the HTML output. Values below 100\n# gradually make the output lighter, whereas values above 100 make the output\n# darker. The value divided by 100 is the actual gamma applied, so 80 represents\n# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not\n# change the gamma.\n# Minimum value: 40, maximum value: 240, default value: 80.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_COLORSTYLE_GAMMA  = 80\n\n# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML\n# page will contain the date and time when the page was generated. Setting this\n# to NO can help when comparing the output of multiple runs.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_TIMESTAMP         = YES\n\n# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML\n# documentation will contain sections that can be hidden and shown after the\n# page has loaded.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_DYNAMIC_SECTIONS  = NO\n\n# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries\n# shown in the various tree structured indices initially; the user can expand\n# and collapse entries dynamically later on. Doxygen will expand the tree to\n# such a level that at most the specified number of entries are visible (unless\n# a fully collapsed tree already exceeds this amount). So setting the number of\n# entries 1 will produce a full collapsed tree by default. 0 is a special value\n# representing an infinite number of entries and will result in a full expanded\n# tree by default.\n# Minimum value: 0, maximum value: 9999, default value: 100.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_INDEX_NUM_ENTRIES = 100\n\n# If the GENERATE_DOCSET tag is set to YES, additional index files will be\n# generated that can be used as input for Apple's Xcode 3 integrated development\n# environment (see: http://developer.apple.com/tools/xcode/), introduced with\n# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a\n# Makefile in the HTML output directory. Running make will produce the docset in\n# that directory and running make install will install the docset in\n# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at\n# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html\n# for more information.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nGENERATE_DOCSET        = NO\n\n# This tag determines the name of the docset feed. A documentation feed provides\n# an umbrella under which multiple documentation sets from a single provider\n# (such as a company or product suite) can be grouped.\n# The default value is: Doxygen generated docs.\n# This tag requires that the tag GENERATE_DOCSET is set to YES.\n\nDOCSET_FEEDNAME        = \"Doxygen generated docs\"\n\n# This tag specifies a string that should uniquely identify the documentation\n# set bundle. This should be a reverse domain-name style string, e.g.\n# com.mycompany.MyDocSet. Doxygen will append .docset to the name.\n# The default value is: org.doxygen.Project.\n# This tag requires that the tag GENERATE_DOCSET is set to YES.\n\nDOCSET_BUNDLE_ID       = org.doxygen.Project\n\n# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify\n# the documentation publisher. This should be a reverse domain-name style\n# string, e.g. com.mycompany.MyDocSet.documentation.\n# The default value is: org.doxygen.Publisher.\n# This tag requires that the tag GENERATE_DOCSET is set to YES.\n\nDOCSET_PUBLISHER_ID    = org.doxygen.Publisher\n\n# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.\n# The default value is: Publisher.\n# This tag requires that the tag GENERATE_DOCSET is set to YES.\n\nDOCSET_PUBLISHER_NAME  = Publisher\n\n# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three\n# additional HTML index files: index.hhp, index.hhc, and index.hhk. The\n# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop\n# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on\n# Windows.\n#\n# The HTML Help Workshop contains a compiler that can convert all HTML output\n# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML\n# files are now used as the Windows 98 help format, and will replace the old\n# Windows help format (.hlp) on all Windows platforms in the future. Compressed\n# HTML files also contain an index, a table of contents, and you can search for\n# words in the documentation. The HTML workshop also contains a viewer for\n# compressed HTML files.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nGENERATE_HTMLHELP      = NO\n\n# The CHM_FILE tag can be used to specify the file name of the resulting .chm\n# file. You can add a path in front of the file if the result should not be\n# written to the html output directory.\n# This tag requires that the tag GENERATE_HTMLHELP is set to YES.\n\nCHM_FILE               =\n\n# The HHC_LOCATION tag can be used to specify the location (absolute path\n# including file name) of the HTML help compiler ( hhc.exe). If non-empty\n# doxygen will try to run the HTML help compiler on the generated index.hhp.\n# The file has to be specified with full path.\n# This tag requires that the tag GENERATE_HTMLHELP is set to YES.\n\nHHC_LOCATION           =\n\n# The GENERATE_CHI flag controls if a separate .chi index file is generated (\n# YES) or that it should be included in the master .chm file ( NO).\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTMLHELP is set to YES.\n\nGENERATE_CHI           = NO\n\n# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc)\n# and project file content.\n# This tag requires that the tag GENERATE_HTMLHELP is set to YES.\n\nCHM_INDEX_ENCODING     =\n\n# The BINARY_TOC flag controls whether a binary table of contents is generated (\n# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it\n# enables the Previous and Next buttons.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTMLHELP is set to YES.\n\nBINARY_TOC             = NO\n\n# The TOC_EXPAND flag can be set to YES to add extra items for group members to\n# the table of contents of the HTML help documentation and to the tree view.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTMLHELP is set to YES.\n\nTOC_EXPAND             = NO\n\n# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and\n# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that\n# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help\n# (.qch) of the generated HTML documentation.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nGENERATE_QHP           = NO\n\n# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify\n# the file name of the resulting .qch file. The path specified is relative to\n# the HTML output folder.\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQCH_FILE               =\n\n# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help\n# Project output. For more information please see Qt Help Project / Namespace\n# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).\n# The default value is: org.doxygen.Project.\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHP_NAMESPACE          = org.doxygen.Project\n\n# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt\n# Help Project output. For more information please see Qt Help Project / Virtual\n# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-\n# folders).\n# The default value is: doc.\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHP_VIRTUAL_FOLDER     = doc\n\n# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom\n# filter to add. For more information please see Qt Help Project / Custom\n# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-\n# filters).\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHP_CUST_FILTER_NAME   =\n\n# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the\n# custom filter to add. For more information please see Qt Help Project / Custom\n# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-\n# filters).\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHP_CUST_FILTER_ATTRS  =\n\n# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this\n# project's filter section matches. Qt Help Project / Filter Attributes (see:\n# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHP_SECT_FILTER_ATTRS  =\n\n# The QHG_LOCATION tag can be used to specify the location of Qt's\n# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the\n# generated .qhp file.\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHG_LOCATION           =\n\n# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be\n# generated, together with the HTML files, they form an Eclipse help plugin. To\n# install this plugin and make it available under the help contents menu in\n# Eclipse, the contents of the directory containing the HTML and XML files needs\n# to be copied into the plugins directory of eclipse. The name of the directory\n# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.\n# After copying Eclipse needs to be restarted before the help appears.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nGENERATE_ECLIPSEHELP   = NO\n\n# A unique identifier for the Eclipse help plugin. When installing the plugin\n# the directory name containing the HTML and XML files should also have this\n# name. Each documentation set should have its own identifier.\n# The default value is: org.doxygen.Project.\n# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.\n\nECLIPSE_DOC_ID         = org.doxygen.Project\n\n# If you want full control over the layout of the generated HTML pages it might\n# be necessary to disable the index and replace it with your own. The\n# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top\n# of each HTML page. A value of NO enables the index and the value YES disables\n# it. Since the tabs in the index contain the same information as the navigation\n# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nDISABLE_INDEX          = NO\n\n# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index\n# structure should be generated to display hierarchical information. If the tag\n# value is set to YES, a side panel will be generated containing a tree-like\n# index structure (just like the one that is generated for HTML Help). For this\n# to work a browser that supports JavaScript, DHTML, CSS and frames is required\n# (i.e. any modern browser). Windows users are probably better off using the\n# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can\n# further fine-tune the look of the index. As an example, the default style\n# sheet generated by doxygen has an example that shows how to put an image at\n# the root of the tree instead of the PROJECT_NAME. Since the tree basically has\n# the same information as the tab index, you could consider setting\n# DISABLE_INDEX to YES when enabling this option.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nGENERATE_TREEVIEW      = NO\n\n# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that\n# doxygen will group on one line in the generated HTML documentation.\n#\n# Note that a value of 0 will completely suppress the enum values from appearing\n# in the overview section.\n# Minimum value: 0, maximum value: 20, default value: 4.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nENUM_VALUES_PER_LINE   = 4\n\n# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used\n# to set the initial width (in pixels) of the frame in which the tree is shown.\n# Minimum value: 0, maximum value: 1500, default value: 250.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nTREEVIEW_WIDTH         = 250\n\n# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to\n# external symbols imported via tag files in a separate window.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nEXT_LINKS_IN_WINDOW    = NO\n\n# Use this tag to change the font size of LaTeX formulas included as images in\n# the HTML documentation. When you change the font size after a successful\n# doxygen run you need to manually remove any form_*.png images from the HTML\n# output directory to force them to be regenerated.\n# Minimum value: 8, maximum value: 50, default value: 10.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nFORMULA_FONTSIZE       = 10\n\n# Use the FORMULA_TRANPARENT tag to determine whether or not the images\n# generated for formulas are transparent PNGs. Transparent PNGs are not\n# supported properly for IE 6.0, but are supported on all modern browsers.\n#\n# Note that when changing this option you need to delete any form_*.png files in\n# the HTML output directory before the changes have effect.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nFORMULA_TRANSPARENT    = YES\n\n# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see\n# http://www.mathjax.org) which uses client side Javascript for the rendering\n# instead of using prerendered bitmaps. Use this if you do not have LaTeX\n# installed or if you want to formulas look prettier in the HTML output. When\n# enabled you may also need to install MathJax separately and configure the path\n# to it using the MATHJAX_RELPATH option.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nUSE_MATHJAX            = NO\n\n# When MathJax is enabled you can set the default output format to be used for\n# the MathJax output. See the MathJax site (see:\n# http://docs.mathjax.org/en/latest/output.html) for more details.\n# Possible values are: HTML-CSS (which is slower, but has the best\n# compatibility), NativeMML (i.e. MathML) and SVG.\n# The default value is: HTML-CSS.\n# This tag requires that the tag USE_MATHJAX is set to YES.\n\nMATHJAX_FORMAT         = HTML-CSS\n\n# When MathJax is enabled you need to specify the location relative to the HTML\n# output directory using the MATHJAX_RELPATH option. The destination directory\n# should contain the MathJax.js script. For instance, if the mathjax directory\n# is located at the same level as the HTML output directory, then\n# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax\n# Content Delivery Network so you can quickly see the result without installing\n# MathJax. However, it is strongly recommended to install a local copy of\n# MathJax from http://www.mathjax.org before deployment.\n# The default value is: http://cdn.mathjax.org/mathjax/latest.\n# This tag requires that the tag USE_MATHJAX is set to YES.\n\nMATHJAX_RELPATH        = http://cdn.mathjax.org/mathjax/latest\n\n# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax\n# extension names that should be enabled during MathJax rendering. For example\n# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols\n# This tag requires that the tag USE_MATHJAX is set to YES.\n\nMATHJAX_EXTENSIONS     =\n\n# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces\n# of code that will be used on startup of the MathJax code. See the MathJax site\n# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an\n# example see the documentation.\n# This tag requires that the tag USE_MATHJAX is set to YES.\n\nMATHJAX_CODEFILE       =\n\n# When the SEARCHENGINE tag is enabled doxygen will generate a search box for\n# the HTML output. The underlying search engine uses javascript and DHTML and\n# should work on any modern browser. Note that when using HTML help\n# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)\n# there is already a search function so this one should typically be disabled.\n# For large projects the javascript based search engine can be slow, then\n# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to\n# search using the keyboard; to jump to the search box use <access key> + S\n# (what the <access key> is depends on the OS and browser, but it is typically\n# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down\n# key> to jump into the search results window, the results can be navigated\n# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel\n# the search. The filter options can be selected when the cursor is inside the\n# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>\n# to select a filter and <Enter> or <escape> to activate or cancel the filter\n# option.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nSEARCHENGINE           = YES\n\n# When the SERVER_BASED_SEARCH tag is enabled the search engine will be\n# implemented using a web server instead of a web client using Javascript. There\n# are two flavors of web server based searching depending on the EXTERNAL_SEARCH\n# setting. When disabled, doxygen will generate a PHP script for searching and\n# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing\n# and searching needs to be provided by external tools. See the section\n# \"External Indexing and Searching\" for details.\n# The default value is: NO.\n# This tag requires that the tag SEARCHENGINE is set to YES.\n\nSERVER_BASED_SEARCH    = NO\n\n# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP\n# script for searching. Instead the search results are written to an XML file\n# which needs to be processed by an external indexer. Doxygen will invoke an\n# external search engine pointed to by the SEARCHENGINE_URL option to obtain the\n# search results.\n#\n# Doxygen ships with an example indexer ( doxyindexer) and search engine\n# (doxysearch.cgi) which are based on the open source search engine library\n# Xapian (see: http://xapian.org/).\n#\n# See the section \"External Indexing and Searching\" for details.\n# The default value is: NO.\n# This tag requires that the tag SEARCHENGINE is set to YES.\n\nEXTERNAL_SEARCH        = NO\n\n# The SEARCHENGINE_URL should point to a search engine hosted by a web server\n# which will return the search results when EXTERNAL_SEARCH is enabled.\n#\n# Doxygen ships with an example indexer ( doxyindexer) and search engine\n# (doxysearch.cgi) which are based on the open source search engine library\n# Xapian (see: http://xapian.org/). See the section \"External Indexing and\n# Searching\" for details.\n# This tag requires that the tag SEARCHENGINE is set to YES.\n\nSEARCHENGINE_URL       =\n\n# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed\n# search data is written to a file for indexing by an external tool. With the\n# SEARCHDATA_FILE tag the name of this file can be specified.\n# The default file is: searchdata.xml.\n# This tag requires that the tag SEARCHENGINE is set to YES.\n\nSEARCHDATA_FILE        = searchdata.xml\n\n# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the\n# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is\n# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple\n# projects and redirect the results back to the right project.\n# This tag requires that the tag SEARCHENGINE is set to YES.\n\nEXTERNAL_SEARCH_ID     =\n\n# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen\n# projects other than the one defined by this configuration file, but that are\n# all added to the same external search index. Each project needs to have a\n# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of\n# to a relative location where the documentation can be found. The format is:\n# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...\n# This tag requires that the tag SEARCHENGINE is set to YES.\n\nEXTRA_SEARCH_MAPPINGS  =\n\n#---------------------------------------------------------------------------\n# Configuration options related to the LaTeX output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.\n# The default value is: YES.\n\nGENERATE_LATEX         = NO\n\n# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a\n# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of\n# it.\n# The default directory is: latex.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_OUTPUT           = latex\n\n# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be\n# invoked.\n#\n# Note that when enabling USE_PDFLATEX this option is only used for generating\n# bitmaps for formulas in the HTML output, but not in the Makefile that is\n# written to the output directory.\n# The default file is: latex.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_CMD_NAME         = latex\n\n# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate\n# index for LaTeX.\n# The default file is: makeindex.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nMAKEINDEX_CMD_NAME     = makeindex\n\n# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX\n# documents. This may be useful for small projects and may help to save some\n# trees in general.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nCOMPACT_LATEX          = NO\n\n# The PAPER_TYPE tag can be used to set the paper type that is used by the\n# printer.\n# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x\n# 14 inches) and executive (7.25 x 10.5 inches).\n# The default value is: a4.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nPAPER_TYPE             = a4\n\n# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names\n# that should be included in the LaTeX output. To get the times font for\n# instance you can specify\n# EXTRA_PACKAGES=times\n# If left blank no extra packages will be included.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nEXTRA_PACKAGES         =\n\n# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the\n# generated LaTeX document. The header should contain everything until the first\n# chapter. If it is left blank doxygen will generate a standard header. See\n# section \"Doxygen usage\" for information on how to let doxygen write the\n# default header to a separate file.\n#\n# Note: Only use a user-defined header if you know what you are doing! The\n# following commands have a special meaning inside the header: $title,\n# $datetime, $date, $doxygenversion, $projectname, $projectnumber. Doxygen will\n# replace them by respectively the title of the page, the current date and time,\n# only the current date, the version number of doxygen, the project name (see\n# PROJECT_NAME), or the project number (see PROJECT_NUMBER).\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_HEADER           =\n\n# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the\n# generated LaTeX document. The footer should contain everything after the last\n# chapter. If it is left blank doxygen will generate a standard footer.\n#\n# Note: Only use a user-defined footer if you know what you are doing!\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_FOOTER           =\n\n# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or\n# other source files which should be copied to the LATEX_OUTPUT output\n# directory. Note that the files will be copied as-is; there are no commands or\n# markers available.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_EXTRA_FILES      =\n\n# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is\n# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will\n# contain links (just like the HTML output) instead of page references. This\n# makes the output suitable for online browsing using a PDF viewer.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nPDF_HYPERLINKS         = YES\n\n# If the LATEX_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate\n# the PDF file directly from the LaTeX files. Set this option to YES to get a\n# higher quality PDF documentation.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nUSE_PDFLATEX           = YES\n\n# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode\n# command to the generated LaTeX files. This will instruct LaTeX to keep running\n# if errors occur, instead of asking the user for help. This option is also used\n# when generating formulas in HTML.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_BATCHMODE        = NO\n\n# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the\n# index chapters (such as File Index, Compound Index, etc.) in the output.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_HIDE_INDICES     = NO\n\n# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source\n# code with syntax highlighting in the LaTeX output.\n#\n# Note that which sources are shown also depends on other settings such as\n# SOURCE_BROWSER.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_SOURCE_CODE      = NO\n\n# The LATEX_BIB_STYLE tag can be used to specify the style to use for the\n# bibliography, e.g. plainnat, or ieeetr. See\n# http://en.wikipedia.org/wiki/BibTeX and \\cite for more info.\n# The default value is: plain.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_BIB_STYLE        = plain\n\n#---------------------------------------------------------------------------\n# Configuration options related to the RTF output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The\n# RTF output is optimized for Word 97 and may not look too pretty with other RTF\n# readers/editors.\n# The default value is: NO.\n\nGENERATE_RTF           = NO\n\n# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a\n# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of\n# it.\n# The default directory is: rtf.\n# This tag requires that the tag GENERATE_RTF is set to YES.\n\nRTF_OUTPUT             = rtf\n\n# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF\n# documents. This may be useful for small projects and may help to save some\n# trees in general.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_RTF is set to YES.\n\nCOMPACT_RTF            = NO\n\n# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will\n# contain hyperlink fields. The RTF file will contain links (just like the HTML\n# output) instead of page references. This makes the output suitable for online\n# browsing using Word or some other Word compatible readers that support those\n# fields.\n#\n# Note: WordPad (write) and others do not support links.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_RTF is set to YES.\n\nRTF_HYPERLINKS         = NO\n\n# Load stylesheet definitions from file. Syntax is similar to doxygen's config\n# file, i.e. a series of assignments. You only have to provide replacements,\n# missing definitions are set to their default value.\n#\n# See also section \"Doxygen usage\" for information on how to generate the\n# default style sheet that doxygen normally uses.\n# This tag requires that the tag GENERATE_RTF is set to YES.\n\nRTF_STYLESHEET_FILE    =\n\n# Set optional variables used in the generation of an RTF document. Syntax is\n# similar to doxygen's config file. A template extensions file can be generated\n# using doxygen -e rtf extensionFile.\n# This tag requires that the tag GENERATE_RTF is set to YES.\n\nRTF_EXTENSIONS_FILE    =\n\n#---------------------------------------------------------------------------\n# Configuration options related to the man page output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for\n# classes and files.\n# The default value is: NO.\n\nGENERATE_MAN           = NO\n\n# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a\n# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of\n# it. A directory man3 will be created inside the directory specified by\n# MAN_OUTPUT.\n# The default directory is: man.\n# This tag requires that the tag GENERATE_MAN is set to YES.\n\nMAN_OUTPUT             = man\n\n# The MAN_EXTENSION tag determines the extension that is added to the generated\n# man pages. In case the manual section does not start with a number, the number\n# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is\n# optional.\n# The default value is: .3.\n# This tag requires that the tag GENERATE_MAN is set to YES.\n\nMAN_EXTENSION          = .3\n\n# The MAN_SUBDIR tag determines the name of the directory created within\n# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by\n# MAN_EXTENSION with the initial . removed.\n# This tag requires that the tag GENERATE_MAN is set to YES.\n\nMAN_SUBDIR             =\n\n# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it\n# will generate one additional man file for each entity documented in the real\n# man page(s). These additional files only source the real man page, but without\n# them the man command would be unable to find the correct page.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_MAN is set to YES.\n\nMAN_LINKS              = NO\n\n#---------------------------------------------------------------------------\n# Configuration options related to the XML output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that\n# captures the structure of the code including all documentation.\n# The default value is: NO.\n\nGENERATE_XML           = NO\n\n# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a\n# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of\n# it.\n# The default directory is: xml.\n# This tag requires that the tag GENERATE_XML is set to YES.\n\nXML_OUTPUT             = xml\n\n# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program\n# listings (including syntax highlighting and cross-referencing information) to\n# the XML output. Note that enabling this will significantly increase the size\n# of the XML output.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_XML is set to YES.\n\nXML_PROGRAMLISTING     = YES\n\n#---------------------------------------------------------------------------\n# Configuration options related to the DOCBOOK output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files\n# that can be used to generate PDF.\n# The default value is: NO.\n\nGENERATE_DOCBOOK       = NO\n\n# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.\n# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in\n# front of it.\n# The default directory is: docbook.\n# This tag requires that the tag GENERATE_DOCBOOK is set to YES.\n\nDOCBOOK_OUTPUT         = docbook\n\n#---------------------------------------------------------------------------\n# Configuration options for the AutoGen Definitions output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen\n# Definitions (see http://autogen.sf.net) file that captures the structure of\n# the code including all documentation. Note that this feature is still\n# experimental and incomplete at the moment.\n# The default value is: NO.\n\nGENERATE_AUTOGEN_DEF   = NO\n\n#---------------------------------------------------------------------------\n# Configuration options related to the Perl module output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module\n# file that captures the structure of the code including all documentation.\n#\n# Note that this feature is still experimental and incomplete at the moment.\n# The default value is: NO.\n\nGENERATE_PERLMOD       = NO\n\n# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary\n# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI\n# output from the Perl module output.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_PERLMOD is set to YES.\n\nPERLMOD_LATEX          = NO\n\n# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely\n# formatted so it can be parsed by a human reader. This is useful if you want to\n# understand what is going on. On the other hand, if this tag is set to NO the\n# size of the Perl module output will be much smaller and Perl will parse it\n# just the same.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_PERLMOD is set to YES.\n\nPERLMOD_PRETTY         = YES\n\n# The names of the make variables in the generated doxyrules.make file are\n# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful\n# so different doxyrules.make files included by the same Makefile don't\n# overwrite each other's variables.\n# This tag requires that the tag GENERATE_PERLMOD is set to YES.\n\nPERLMOD_MAKEVAR_PREFIX =\n\n#---------------------------------------------------------------------------\n# Configuration options related to the preprocessor\n#---------------------------------------------------------------------------\n\n# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all\n# C-preprocessor directives found in the sources and include files.\n# The default value is: YES.\n\nENABLE_PREPROCESSING   = YES\n\n# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names\n# in the source code. If set to NO only conditional compilation will be\n# performed. Macro expansion can be done in a controlled way by setting\n# EXPAND_ONLY_PREDEF to YES.\n# The default value is: NO.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nMACRO_EXPANSION        = NO\n\n# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then\n# the macro expansion is limited to the macros specified with the PREDEFINED and\n# EXPAND_AS_DEFINED tags.\n# The default value is: NO.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nEXPAND_ONLY_PREDEF     = NO\n\n# If the SEARCH_INCLUDES tag is set to YES the includes files in the\n# INCLUDE_PATH will be searched if a #include is found.\n# The default value is: YES.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nSEARCH_INCLUDES        = YES\n\n# The INCLUDE_PATH tag can be used to specify one or more directories that\n# contain include files that are not input files but should be processed by the\n# preprocessor.\n# This tag requires that the tag SEARCH_INCLUDES is set to YES.\n\nINCLUDE_PATH           =\n\n# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard\n# patterns (like *.h and *.hpp) to filter out the header-files in the\n# directories. If left blank, the patterns specified with FILE_PATTERNS will be\n# used.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nINCLUDE_FILE_PATTERNS  =\n\n# The PREDEFINED tag can be used to specify one or more macro names that are\n# defined before the preprocessor is started (similar to the -D option of e.g.\n# gcc). The argument of the tag is a list of macros of the form: name or\n# name=definition (no spaces). If the definition and the \"=\" are omitted, \"=1\"\n# is assumed. To prevent a macro definition from being undefined via #undef or\n# recursively expanded use the := operator instead of the = operator.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nPREDEFINED             =\n\n# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this\n# tag can be used to specify a list of macro names that should be expanded. The\n# macro definition that is found in the sources will be used. Use the PREDEFINED\n# tag if you want to use a different macro definition that overrules the\n# definition found in the source code.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nEXPAND_AS_DEFINED      =\n\n# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will\n# remove all references to function-like macros that are alone on a line, have\n# an all uppercase name, and do not end with a semicolon. Such function macros\n# are typically used for boiler-plate code, and will confuse the parser if not\n# removed.\n# The default value is: YES.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nSKIP_FUNCTION_MACROS   = YES\n\n#---------------------------------------------------------------------------\n# Configuration options related to external references\n#---------------------------------------------------------------------------\n\n# The TAGFILES tag can be used to specify one or more tag files. For each tag\n# file the location of the external documentation should be added. The format of\n# a tag file without this location is as follows:\n# TAGFILES = file1 file2 ...\n# Adding location for the tag files is done as follows:\n# TAGFILES = file1=loc1 \"file2 = loc2\" ...\n# where loc1 and loc2 can be relative or absolute paths or URLs. See the\n# section \"Linking to external documentation\" for more information about the use\n# of tag files.\n# Note: Each tag file must have a unique name (where the name does NOT include\n# the path). If a tag file is not located in the directory in which doxygen is\n# run, you must also specify the path to the tagfile here.\n\nTAGFILES               =\n\n# When a file name is specified after GENERATE_TAGFILE, doxygen will create a\n# tag file that is based on the input files it reads. See section \"Linking to\n# external documentation\" for more information about the usage of tag files.\n\nGENERATE_TAGFILE       =\n\n# If the ALLEXTERNALS tag is set to YES all external class will be listed in the\n# class index. If set to NO only the inherited external classes will be listed.\n# The default value is: NO.\n\nALLEXTERNALS           = NO\n\n# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in\n# the modules index. If set to NO, only the current project's groups will be\n# listed.\n# The default value is: YES.\n\nEXTERNAL_GROUPS        = YES\n\n# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in\n# the related pages index. If set to NO, only the current project's pages will\n# be listed.\n# The default value is: YES.\n\nEXTERNAL_PAGES         = YES\n\n# The PERL_PATH should be the absolute path and name of the perl script\n# interpreter (i.e. the result of 'which perl').\n# The default file (with absolute path) is: /usr/bin/perl.\n\nPERL_PATH              = /usr/bin/perl\n\n#---------------------------------------------------------------------------\n# Configuration options related to the dot tool\n#---------------------------------------------------------------------------\n\n# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram\n# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to\n# NO turns the diagrams off. Note that this option also works with HAVE_DOT\n# disabled, but it is recommended to install and use dot, since it yields more\n# powerful graphs.\n# The default value is: YES.\n\nCLASS_DIAGRAMS         = YES\n\n# You can define message sequence charts within doxygen comments using the \\msc\n# command. Doxygen will then run the mscgen tool (see:\n# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the\n# documentation. The MSCGEN_PATH tag allows you to specify the directory where\n# the mscgen tool resides. If left empty the tool is assumed to be found in the\n# default search path.\n\nMSCGEN_PATH            =\n\n# You can include diagrams made with dia in doxygen documentation. Doxygen will\n# then run dia to produce the diagram and insert it in the documentation. The\n# DIA_PATH tag allows you to specify the directory where the dia binary resides.\n# If left empty dia is assumed to be found in the default search path.\n\nDIA_PATH               =\n\n# If set to YES, the inheritance and collaboration graphs will hide inheritance\n# and usage relations if the target is undocumented or is not a class.\n# The default value is: YES.\n\nHIDE_UNDOC_RELATIONS   = YES\n\n# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is\n# available from the path. This tool is part of Graphviz (see:\n# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent\n# Bell Labs. The other options in this section have no effect if this option is\n# set to NO\n# The default value is: NO.\n\nHAVE_DOT               = NO\n\n# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed\n# to run in parallel. When set to 0 doxygen will base this on the number of\n# processors available in the system. You can set it explicitly to a value\n# larger than 0 to get control over the balance between CPU load and processing\n# speed.\n# Minimum value: 0, maximum value: 32, default value: 0.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_NUM_THREADS        = 0\n\n# When you want a differently looking font n the dot files that doxygen\n# generates you can specify the font name using DOT_FONTNAME. You need to make\n# sure dot is able to find the font, which can be done by putting it in a\n# standard location or by setting the DOTFONTPATH environment variable or by\n# setting DOT_FONTPATH to the directory containing the font.\n# The default value is: Helvetica.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_FONTNAME           = Helvetica\n\n# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of\n# dot graphs.\n# Minimum value: 4, maximum value: 24, default value: 10.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_FONTSIZE           = 10\n\n# By default doxygen will tell dot to use the default font as specified with\n# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set\n# the path where dot can find it using this tag.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_FONTPATH           =\n\n# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for\n# each documented class showing the direct and indirect inheritance relations.\n# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nCLASS_GRAPH            = YES\n\n# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a\n# graph for each documented class showing the direct and indirect implementation\n# dependencies (inheritance, containment, and class references variables) of the\n# class with other documented classes.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nCOLLABORATION_GRAPH    = YES\n\n# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for\n# groups, showing the direct groups dependencies.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nGROUP_GRAPHS           = YES\n\n# If the UML_LOOK tag is set to YES doxygen will generate inheritance and\n# collaboration diagrams in a style similar to the OMG's Unified Modeling\n# Language.\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nUML_LOOK               = NO\n\n# If the UML_LOOK tag is enabled, the fields and methods are shown inside the\n# class node. If there are many fields or methods and many nodes the graph may\n# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the\n# number of items for each type to make the size more manageable. Set this to 0\n# for no limit. Note that the threshold may be exceeded by 50% before the limit\n# is enforced. So when you set the threshold to 10, up to 15 fields may appear,\n# but if the number exceeds 15, the total amount of fields shown is limited to\n# 10.\n# Minimum value: 0, maximum value: 100, default value: 10.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nUML_LIMIT_NUM_FIELDS   = 10\n\n# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and\n# collaboration graphs will show the relations between templates and their\n# instances.\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nTEMPLATE_RELATIONS     = NO\n\n# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to\n# YES then doxygen will generate a graph for each documented file showing the\n# direct and indirect include dependencies of the file with other documented\n# files.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nINCLUDE_GRAPH          = YES\n\n# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are\n# set to YES then doxygen will generate a graph for each documented file showing\n# the direct and indirect include dependencies of the file with other documented\n# files.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nINCLUDED_BY_GRAPH      = YES\n\n# If the CALL_GRAPH tag is set to YES then doxygen will generate a call\n# dependency graph for every global function or class method.\n#\n# Note that enabling this option will significantly increase the time of a run.\n# So in most cases it will be better to enable call graphs for selected\n# functions only using the \\callgraph command.\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nCALL_GRAPH             = NO\n\n# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller\n# dependency graph for every global function or class method.\n#\n# Note that enabling this option will significantly increase the time of a run.\n# So in most cases it will be better to enable caller graphs for selected\n# functions only using the \\callergraph command.\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nCALLER_GRAPH           = NO\n\n# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical\n# hierarchy of all classes instead of a textual one.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nGRAPHICAL_HIERARCHY    = YES\n\n# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the\n# dependencies a directory has on other directories in a graphical way. The\n# dependency relations are determined by the #include relations between the\n# files in the directories.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDIRECTORY_GRAPH        = YES\n\n# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images\n# generated by dot.\n# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order\n# to make the SVG files visible in IE 9+ (other browsers do not have this\n# requirement).\n# Possible values are: png, jpg, gif and svg.\n# The default value is: png.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_IMAGE_FORMAT       = png\n\n# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to\n# enable generation of interactive SVG images that allow zooming and panning.\n#\n# Note that this requires a modern browser other than Internet Explorer. Tested\n# and working are Firefox, Chrome, Safari, and Opera.\n# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make\n# the SVG files visible. Older versions of IE do not have SVG support.\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nINTERACTIVE_SVG        = NO\n\n# The DOT_PATH tag can be used to specify the path where the dot tool can be\n# found. If left blank, it is assumed the dot tool can be found in the path.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_PATH               =\n\n# The DOTFILE_DIRS tag can be used to specify one or more directories that\n# contain dot files that are included in the documentation (see the \\dotfile\n# command).\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOTFILE_DIRS           =\n\n# The MSCFILE_DIRS tag can be used to specify one or more directories that\n# contain msc files that are included in the documentation (see the \\mscfile\n# command).\n\nMSCFILE_DIRS           =\n\n# The DIAFILE_DIRS tag can be used to specify one or more directories that\n# contain dia files that are included in the documentation (see the \\diafile\n# command).\n\nDIAFILE_DIRS           =\n\n# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes\n# that will be shown in the graph. If the number of nodes in a graph becomes\n# larger than this value, doxygen will truncate the graph, which is visualized\n# by representing a node as a red box. Note that doxygen if the number of direct\n# children of the root node in a graph is already larger than\n# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that\n# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.\n# Minimum value: 0, maximum value: 10000, default value: 50.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_GRAPH_MAX_NODES    = 50\n\n# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs\n# generated by dot. A depth value of 3 means that only nodes reachable from the\n# root by following a path via at most 3 edges will be shown. Nodes that lay\n# further from the root node will be omitted. Note that setting this option to 1\n# or 2 may greatly reduce the computation time needed for large code bases. Also\n# note that the size of a graph can be further restricted by\n# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.\n# Minimum value: 0, maximum value: 1000, default value: 0.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nMAX_DOT_GRAPH_DEPTH    = 0\n\n# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent\n# background. This is disabled by default, because dot on Windows does not seem\n# to support this out of the box.\n#\n# Warning: Depending on the platform used, enabling this option may lead to\n# badly anti-aliased labels on the edges of a graph (i.e. they become hard to\n# read).\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_TRANSPARENT        = NO\n\n# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output\n# files in one run (i.e. multiple -o and -T options on the command line). This\n# makes dot run faster, but since only newer versions of dot (>1.8.10) support\n# this, this feature is disabled by default.\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_MULTI_TARGETS      = NO\n\n# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page\n# explaining the meaning of the various boxes and arrows in the dot generated\n# graphs.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nGENERATE_LEGEND        = YES\n\n# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot\n# files that are used to generate the various graphs.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_CLEANUP            = YES\n"
  },
  {
    "path": "docs/openxcom.6",
    "content": ".Dd 2014-06-12\n.Dt OPENXCOM 6\n.Os\n.Sh NAME\n.Nm openxcom\n.Nd An open-source reimplementation of the original\n.Dq UFO: Enemy Unknown\ngame\n.Sh SYNOPSIS\n.Nm\n.Op Fl ? | help\n.Op Fl data Ar path\n.Op Fl user Ar path\n.Op Fl cfg Ar path\n.Op Fl master Ar mod\n.Op Fl KEY Ar VALUE\n.Sh DESCRIPTION\n.Nm openxcom\nis an open-source reimplementation of the popular\n.Dq UFO: Enemy Unknown\ngame also known as\n.Dq X-COM: UFO Defense\nin North America, and its sequel\n.Dq X-COM: Terror from the Deep\nby publisher\n.An MicroProse .\nIt is licensed under the GPL and written in C++ / SDL.\n.Pp\nThe options are as follows:\n.Bl -tag -width Ds\n.It Fl ?, Fl help\nshow command-line help\n.It Fl data Ar path\nuse\n.Ar path\nas the default Data Folder instead of auto-detecting\n.It Fl user Ar path\nuse\n.Ar path\nas the default User Folder instead of auto-detecting\n.It Fl cfg Ar path\nuse\n.Ar path\nas the default Config Folder instead of auto-detecting\n.It Fl master Ar mod\nset\n.Ar mod\nthe current master mod (eg.\\&\n.Fl master\n.Ar xcom2 )\n.It Fl KEY Ar VALUE\nset option\n.Ar KEY\nto\n.Ar VALUE\ninstead of default/loaded value (eg\\&.\n.Fl displayWidth\n.Ar 640\n).\nSee\n.Pa src/Engine/Options.cpp\nfor a list of all potential options.\n.El\n.Sh INSTALLATION\n.Nm OpenXcom\nrequires a vanilla copy of the X-COM resources \\(em from either or both of the original games.\nPlease refer to the\n.Pa README.md\nfor the default search paths and the exact directory layout, as well as information on the Mod support.\n.Sh SEE ALSO\n.Lk https://openxcom.org ,\n.Lk https://ufopaedia.org/index.php?title=OpenXcom\n.Sh HISTORY\n.An MicroProse\nreleases\n.Dq UFO: Enemy Unknown\nin 1994, followed by\n.Dq X-COM: Terror from the Deep\nin 1995 with various sequels following.\nThe\n.Nm OpenXcom\nproject sees the light of day in 2010.\n.Sh COPYRIGHT\nCopyright \\(co 2020 OpenXcom Developers\n.Sh AUTHORS\n.An OpenXcom Developers\n"
  },
  {
    "path": "install/debian/changelog",
    "content": "openxcom (1.0-2) unstable; urgency=low\n\n  * Added translations\n\n -- Krzysztof Knapik <knapsu@gmail.com>  Fri, 27 Jun 2014 22:03:26 +0200\n\nopenxcom (1.0-1) unstable; urgency=medium\n\n  * Release of version 1.0\n\n -- Krzysztof Knapik <knapsu@gmail.com>  Wed, 18 Jun 2014 23:33:18 +0200\n"
  },
  {
    "path": "install/debian/compat",
    "content": "9\n"
  },
  {
    "path": "install/debian/control",
    "content": "Source: openxcom\nSection: games\nPriority: extra\nMaintainer: Krzysztof Knapik <knapsu@gmail.com>\nBuild-Depends:\n\tdebhelper (>=9),\n\tcmake,\n\tlibsdl1.2-dev,\n\tlibsdl-mixer1.2-dev,\n\tlibsdl-gfx1.2-dev,\n\tlibsdl-image1.2-dev,\n\tlibyaml-cpp-dev (>= 0.5.3),\n\tlibboost-dev\nStandards-Version: 3.9.6\nHomepage: https://openxcom.org/\nVcs-Git: git://github.com/OpenXcom/OpenXcom.git\nVcs-Browser: https://github.com/OpenXcom/OpenXcom\n\nPackage: openxcom\nArchitecture: any\nDepends: ${shlibs:Depends}, ${misc:Depends}\nDescription: Open-source clone of UFO: Enemy Unknown\n OpenXcom is an open-source clone of the popular UFO: Enemy Unknown (X-COM: UFO Defense in USA)\n turn-based strategy game by MicroProse. It is written in C++ / SDL and licensed under the GPL.\n OpenXcom requires game resources from the original game (DOS, Windows or Steam version).\n"
  },
  {
    "path": "install/debian/copyright",
    "content": "Format: http://dep.debian.net/deps/dep5\nUpstream-Name: openxcom\nSource: https://openxcom.org/\n\nFiles: *\nCopyright: 2009 Daniel Filipe \"SupSuper\" <openxcom@gmail.com>\n           2009 Others\nLicense: GPL-3.0+\n\nFiles: debian/*\nCopyright: 2012 Krzysztof Knapik \"Knapsu\" <knapsu@gmail.com>\nLicense: GPL-3.0+\n\nLicense: GPL-3.0+\n This program is free software: you can redistribute it and/or modify\n it under the terms of the GNU General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n .\n This package is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n GNU General Public License for more details.\n .\n You should have received a copy of the GNU General Public License\n along with this program. If not, see <http://www.gnu.org/licenses/>.\n .\n On Debian systems, the complete text of the GNU General\n Public License version 3 can be found in \"/usr/share/common-licenses/GPL-3\".\n"
  },
  {
    "path": "install/debian/docs",
    "content": "CHANGELOG.txt\nLICENSE.txt\nREADME.md\n"
  },
  {
    "path": "install/debian/install",
    "content": "translations/openxcom.openxcom/* usr/share/games/openxcom/common/Language/\ntranslations/openxcom.x-com-1/* usr/share/games/openxcom/standard/xcom1/Language/\ntranslations/openxcom.x-com-2/* usr/share/games/openxcom/standard/xcom2/Language/\n"
  },
  {
    "path": "install/debian/rules",
    "content": "#!/usr/bin/make -f\n\n#export DH_VERBOSE=1\n\n%:\n\tdh $@ --buildsystem=cmake --parallel\n\noverride_dh_auto_configure:\n\tdh_auto_configure -- \\\n\t\t-DCMAKE_BUILD_TYPE:STRING=Release \\\n\t\t-DCMAKE_INSTALL_BINDIR=\"/usr/games\" \\\n\t\t-DCMAKE_INSTALL_DATADIR=\"/usr/share/games\" \\\n\t\t-DBUILD_PACKAGE=OFF\n"
  },
  {
    "path": "install/debian/source/format",
    "content": "3.0 (quilt)\n"
  },
  {
    "path": "install/debian/source/options",
    "content": "compression = \"xz\"\ncompression-level = 6\n"
  },
  {
    "path": "install/gentoo/openxcom-9999.ebuild",
    "content": "# Copyright 1999-2013 Gentoo Foundation\n# Distributed under the terms of the GNU General Public License v2\n# $Header: $\n\nEAPI=5\n\nEGIT_REPO_URI=\"https://github.com/OpenXcom/OpenXcom.git\"\n\ninherit git-2 cmake-utils\n\nDESCRIPTION=\"OpenXcom is an open-source clone of the popular UFO: Enemy Unknown\"\nHOMEPAGE=\"https://openxcom.org/\"\nSRC_URI=\"\"\n\nLICENSE=\"GPL-3\"\nSLOT=\"0\"\nKEYWORDS=\"\"\nIUSE=\"clang\"\n\nDEPEND=\"\n\tdev-cpp/yaml-cpp\n\tmedia-libs/libsdl\n\tmedia-libs/sdl-mixer\n\tmedia-libs/sdl-gfx\n\tmedia-libs/sdl-image\n\tvirtual/opengl\n\"\nRDEPEND=\"${DEPEND}\"\n\nsrc_configure() {\n\tif use clang; then\n\t\texport CC=clang\n\t\texport CXX=clang++\n\tfi\n\tcmake-utils_src_configure\n}\n\npkg_postinst() {\n    einfo \"You will need to manually the original XCOM game data files to:\"\n    einfo \"/usr/share/openxcom/UFO/ and/or /usr/share/openxcom/TFTD/\"\n\teinfo \"see http://ufopaedia.org/index.php?title=Installing_(OpenXcom)\"\n\teinfo \"for more info.\"\n}\n"
  },
  {
    "path": "install/opensuse/openxcom.changes",
    "content": "-------------------------------------------------------------------\nSat May 11 09:54:33 UTC 2013 - Angelos Tzotsos <tzotsos@opensuse.org>\n\n- restrict yaml-cpp to versions under 0.5.0\n\n-------------------------------------------------------------------\nThu May  9 09:41:45 UTC 2013 - slavb18@gmail.com\n\n- moved installation to /usr istead of /usr/local\n\n-------------------------------------------------------------------\nTue May  7 10:09:36 UTC 2013 - Angelos Tzotsos <tzotsos@opensuse.org>\n\n- update to version 0.9.0\n\n-------------------------------------------------------------------\nTue Nov  6 13:48:28 UTC 2012 - Angelos Tzotsos <tzotsos@opensuse.org>\n\n- update to version 0.4.5\n\n-------------------------------------------------------------------\nFri Oct  5 18:39:59 UTC 2012 - Angelos Tzotsos <tzotsos@opensuse.org>\n\n- initial OBS build (0.4)\n\n"
  },
  {
    "path": "install/opensuse/openxcom.spec",
    "content": "#\n# spec file for package openxcom\n#\n# Copyright (c) 2012 Angelos Tzotsos <tzotsos@opensuse.org>\n#\n# This file and all modifications and additions to the openxcom\n# package are licensed under the GPL license.\n\n# Please submit bugfixes or comments via http://bugs.opensuse.org/\n#\n\n# norootforbuild\n\nName:           openxcom\nVersion:        1.0.0\nRelease:        0\nGroup:          Amusements/Games/Strategy/Turn Based\nLicense:        GPL-3.0\nBuildRoot:      %{_tmppath}/%{name}-%{version}-build\nURL:            https://openxcom.org/\nSource0:        %{name}-%{version}.tar.gz\nSummary:        Open-source clone of UFO: Enemy Unknown\nBuildRequires:  cmake\nBuildRequires:  gcc-c++\nBuildRequires:  gcc\nBuildRequires:  fdupes\nBuildRequires:\tpkg-config\nBuildRequires:\tlibSDL-devel\nBuildRequires:\tlibSDL_mixer-devel\nBuildRequires:\tlibSDL_image-devel\nBuildRequires:\tlibSDL_gfx-devel >= 2.0.21\nBuildRequires:\tyaml-cpp-devel >= 0.5.0\n\n%description\nOpenXcom is an open-source clone of the popular UFO: Enemy Unknown (X-COM: UFO Defense in USA) turn-based strategy game by MicroProse. It is written in C++ / SDL and licensed under the GPL. OpenXcom requires game resources from the original game (DOS, Windows or Steam version).\n\n%prep\n%setup -q\n\n%build\ncd ..\nmkdir temp\ncd temp\ncmake  -DBUILD_PACKAGE:BOOL=ON \\\n       -DDEV_BUILD:BOOL=OFF \\\n       -DCMAKE_INSTALL_PREFIX:PATH=/usr \\\n       -DCMAKE_BUILD_TYPE:STRING=\"Release\" ../%{name}-%{version}/\n\nmake VERBOSE=1 %{?_smp_mflags}\n\n%install\ncd ../temp\nmake install DESTDIR=%{buildroot}\n\n%fdupes %{buildroot}\n\n%clean\nrm -rf %{buildroot}\n\n%post -p /sbin/ldconfig\n\n%postun -p /sbin/ldconfig\n\n%files\n%defattr(-,root,root,-)\n%dir /usr/share/openxcom\n/usr/share/openxcom/*\n/usr/bin/openxcom\n\n%changelog\n"
  },
  {
    "path": "install/win/Language/Bulgarian.nsh",
    "content": "!insertmacro LANGFILE_EXT \"Bulgarian\"\n${LangFileString} SETUP_XCOM_FOLDER_TITLE \"Изберете директорията на X-Com\"\n${LangFileString} SETUP_XCOM_FOLDER_SUBTITLE \"Изберете директориите, където е инсталиран X-COM.\"\n${LangFileString} SETUP_XCOM_FOLDER \"${GAME_NAME} ${GAME_VERSION} изисква копие на една от следните X-COM игри. Може да пропуснете тази стъпка ако надграждате вече съществуваща инсталиация.$\\n$\\nПроцесът на инсталация ще копира необходимите файлове от следните директории. Ако желаете да копирате от друга директория, натиснете ... и изберете друга директория. Натиснете Напред за да продължите.\"\n${LangFileString} SETUP_UFO_FOLDER \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n${LangFileString} SETUP_TFTD_FOLDER \"X-COM: Terror From The Deep\"\n${LangFileString} SETUP_GAME \"Файлове на играта\"\n${LangFileString} SETUP_GAME_DESC \"Файлове необходими за ${GAME_NAME}.\"\n${LangFileString} SETUP_PORTABLE \"Преносима инсталация\"\n${LangFileString} SETUP_PORTABLE_DESC \"${GAME_NAME} ще складира данните за потребителя в инсталационната директория. Потребителят трябва да може да пише в тази директория.\"\n${LangFileString} SETUP_DESKTOP \"Препратка към работния плот.\"\n${LangFileString} SETUP_DESKTOP_DESC \"Създава препратка на работния стол към играта ${GAME_NAME}.\"\n${LangFileString} SETUP_UNDATA \"Изтриване на X-COM данните\"\n${LangFileString} SETUP_UNDATA_DESC \"Изтрива всички данни на ${GAME_NAME}, включително ресурсите на X-COM. Препоръчително за напълно нова инсталация.\"\n${LangFileString} SETUP_UNUSER \"Изтриване на данните на потребителя\"\n${LangFileString} SETUP_UNUSER_DESC \"Изтрива всички данни на потребителя за ${GAME_NAME}, включително модификации, запазени игри, снимки на екрана и настройки. Използвайте само в случай на напълно изтриване.\"\n${LangFileString} SETUP_SHORTCUT_CHANGELOG \"Списък с промените\"\n${LangFileString} SETUP_SHORTCUT_README \"Прочети ме\"\n${LangFileString} SETUP_SHORTCUT_USER \"Потребителска директория\"\n${LangFileString} SETUP_SHORTCUT_UNINSTALL \"Деинсталация\"\n${LangFileString} SETUP_WARNING_UFO \"X-COM 1 не беше открит в тази директория. ${GAME_NAME} изисква инсталация на X-COM за да работи правилно. Продължи?\"\n${LangFileString} SETUP_WARNING_TFTD \"X-COM 2 не беше открит в тази директория. ${GAME_NAME} изисква инсталация на X-COM за да работи правилно. Продължи?\"\n${LangFileString} SETUP_WARNING_XCU \"Открит е XcomUtil. ${GAME_NAME} не е съвместим с XcomUtil и няма да работи правилно. Продължи?\"\n${LangFileString} SETUP_ERROR_PORTABLE \"Инсталационната директория не поддържа преносима инсталация.\"\n"
  },
  {
    "path": "install/win/Language/Catalan.nsh",
    "content": "!insertmacro LANGFILE_EXT \"Catalan\"\n${LangFileString} SETUP_XCOM_FOLDER_TITLE \"Selecciona l'ubicació de X-COM\"\n${LangFileString} SETUP_XCOM_FOLDER_SUBTITLE \"Seleccioni les carpetes on has instal·lat X-COM\"\n${LangFileString} SETUP_XCOM_FOLDER \"${GAME_NAME} ${GAME_VERSION} necessita una còpia d'un dels jocs X-COM següents. Pots saltar aquest pas si ets actualitzant una instal·lació existent.$\\n$\\nLa instal·lació copiarà els fitxers necessaris de les carpetes següents. Per copiar els fitxers d'una carpeta diferent, clica ... i selecciona un altre carpeta.  Clica Següent per continuar.\"\n${LangFileString} SETUP_UFO_FOLDER \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n${LangFileString} SETUP_TFTD_FOLDER \"X-COM: Terror From The Deep\"\n${LangFileString} SETUP_GAME \"Fitxers de joc\"\n${LangFileString} SETUP_GAME_DESC \"Fitxers necessaris per jugar a ${GAME_NAME}.\"\n${LangFileString} SETUP_PORTABLE \"Instal·lació portable\"\n${LangFileString} SETUP_PORTABLE_DESC \"${GAME_NAME} salvarà tota l'informació d'usuari en la carpeta d'instal·lació. La carpeta ha de tenir drets d'escriptura per l'usuari.\"\n${LangFileString} SETUP_DESKTOP \"Accès directe a l'escriptori\"\n${LangFileString} SETUP_DESKTOP_DESC \"Crea un accès directe a l'escriptori per jugar a ${GAME_NAME}.\"\n${LangFileString} SETUP_UNDATA \"Elimina les dades de X-COM\"\n${LangFileString} SETUP_UNDATA_DESC \"Borra tota les dades d'instal·lació de ${GAME_NAME}, incloent les dades de X-COM. Recomanat per fer una reinstal·lació neta del joc.  \"\n${LangFileString} SETUP_UNUSER \"Elimina les dades de l'usuari\"\n${LangFileString} SETUP_UNUSER_DESC \"Elimina totes les dades d'usuari de ${GAME_NAME}, incloent modificacions, partides desades, captures de pantalla i opcions. Només utilitzar per una eliminació completa.\"\n${LangFileString} SETUP_SHORTCUT_CHANGELOG \"Registre de canvis\"\n${LangFileString} SETUP_SHORTCUT_README \"Readme\"\n${LangFileString} SETUP_SHORTCUT_USER \"Carpeta d'usuari\"\n${LangFileString} SETUP_SHORTCUT_UNINSTALL \"Desinstal·lar\"\n${LangFileString} SETUP_WARNING_UFO \"X-COM 1 no s'ha trobat dins la carpeta. ${GAME_NAME} necessita una instal·lació vàlida de X-COM per funcionar. Continuar?\"\n${LangFileString} SETUP_WARNING_TFTD \"X-COM 2 no s'ha trobat dins la carpeta. ${GAME_NAME} necessita una instal·lació valida de X-COM per funcionar. Continuar?\"\n${LangFileString} SETUP_WARNING_XCU \"XcomUtil detectat. ${GAME_NAME} es incompatible amb XcomUtil i pot no funcionar correctament. Continuar?\"\n${LangFileString} SETUP_ERROR_PORTABLE \"La carpeta d'instalació no es pot moure\"\n"
  },
  {
    "path": "install/win/Language/Croatian.nsh",
    "content": "!insertmacro LANGFILE_EXT \"Croatian\"\n${LangFileString} SETUP_XCOM_FOLDER_TITLE \"Izaberi X-COM Lokaciju\"\n${LangFileString} SETUP_XCOM_FOLDER_SUBTITLE \"Izaberi mapu gdje je instaliran X-COM\"\n${LangFileString} SETUP_XCOM_FOLDER \"${GAME_NAME} ${GAME_VERSION} zahtijeva kopiju od jedne od slijedećih X-COM igara. Možeš preskočiti ovaj korak ako nadograđuješ postojeću instalaciju igre.$\\n$\\nPodešavanje će kopirati potrebne datoteke sa slijedećih mapa. Za kopiranje iz drugačije mape, klikni ... i obilježi drugu mapu. Klikni Dalje za nastavak\"\n${LangFileString} SETUP_UFO_FOLDER \"NLO: Neprijatelj Nepoznat / X-COM: NLO Obrana\"\n${LangFileString} SETUP_TFTD_FOLDER \"X-COM: Teror Iz Dubina\"\n${LangFileString} SETUP_GAME \"Datoteke Igre\"\n${LangFileString} SETUP_GAME_DESC \"Datoteke nužne za pokretanje ${GAME_NAME}.\"\n${LangFileString} SETUP_PORTABLE \"Prijenosna Instalacija\"\n${LangFileString} SETUP_PORTABLE_DESC \"${GAME_NAME} će pohraniti korisničke podatke u instalacijsku mapu. Mapa mora imati omogućeno zapisivanje od strane korisnika.\"\n${LangFileString} SETUP_DESKTOP \"Prečac za Radnu površinu\"\n${LangFileString} SETUP_DESKTOP_DESC \"Stvara prečac za igranje na radnoj površini ${GAME_NAME}.\"\n${LangFileString} SETUP_UNDATA \"Izbriši X-COM Podatke\"\n${LangFileString} SETUP_UNDATA_DESC \"Briše sve ${GAME_NAME} instalacijske podatke, uključujući X-COM resurse. Preporuča se za čistu ponovnu instalaciju.\"\n${LangFileString} SETUP_UNUSER \"Pobriši Korisničke Podatke\"\n${LangFileString} SETUP_UNUSER_DESC \"Briše sve ${GAME_NAME} korisničke podatke, uključujući modifikacije, spremljene igre, snimke zaslona i opcije. Koristite ovo samo za potpuno brisanje.\"\n${LangFileString} SETUP_SHORTCUT_CHANGELOG \"Dnevnik promjena\"\n${LangFileString} SETUP_SHORTCUT_README \"PročitajMe\"\n${LangFileString} SETUP_SHORTCUT_USER \"Korisnička Mapa\"\n${LangFileString} SETUP_SHORTCUT_UNINSTALL \"Deinstaliraj\"\n${LangFileString} SETUP_WARNING_UFO \"X-COM 1 nije pronađen u mapi. ${GAME_NAME} zahtijeva važeću instalaciju X-COM za pokretanje. Nastaviti?\"\n${LangFileString} SETUP_WARNING_TFTD \"X-COM 2 nije pronađen u mapi. ${GAME_NAME} zahtijeva važeću instalaciju X-COM za pokretanje. Nastaviti?\"\n${LangFileString} SETUP_WARNING_XCU \"XcomUtil otkriven. ${GAME_NAME} nije kompatibilna s XcomUtilom i možda neće raditi ispravno. Nastaviti?\"\n${LangFileString} SETUP_ERROR_PORTABLE \"Instalacijska mapa ne podržava prijenosnu instalaciju.\"\n"
  },
  {
    "path": "install/win/Language/Czech.nsh",
    "content": "!insertmacro LANGFILE_EXT \"Czech\"\n${LangFileString} SETUP_XCOM_FOLDER_TITLE \"Vyberte umístění X-COM\"\n${LangFileString} SETUP_XCOM_FOLDER_SUBTITLE \"Vyberte složky, kde máte nainstalovaný X-COM.\"\n${LangFileString} SETUP_XCOM_FOLDER \"${GAME_NAME} ${GAME_VERSION} vyžaduje kopii jedné z následujících her X-COM. Tento krok můžete přeskočit, pokud upgradujete již existující instalaci.$\\n$\\nSetup zkopíruje potřebné soubory z následujících složek. Chcete-li vybrat jinou složku, klikněte na ... a vyberte ji. Kliknutím na Další budete pokračovat.\"\n${LangFileString} SETUP_UFO_FOLDER \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n${LangFileString} SETUP_TFTD_FOLDER \"X-COM: Terror From The Deep\"\n${LangFileString} SETUP_GAME \"Herní soubory\"\n${LangFileString} SETUP_GAME_DESC \"Soubory potřebné ke spuštění ${GAME_NAME}.\"\n${LangFileString} SETUP_PORTABLE \"Přenositelná instalace\"\n${LangFileString} SETUP_PORTABLE_DESC \"${GAME_NAME} bude ukládat uživatelská data do složky instalace. Uživatel musí mít na tuto složku právo zápisu.\"\n${LangFileString} SETUP_DESKTOP \"Zástupce na ploše\"\n${LangFileString} SETUP_DESKTOP_DESC \"Vytvoří zástupce na ploše, který umožní spustit ${GAME_NAME}.\"\n${LangFileString} SETUP_UNDATA \"Vymazat data X-COM\"\n${LangFileString} SETUP_UNDATA_DESC \"Smaže všechna data ${GAME_NAME} včetně X-COM zdrojových souborů. Doporučeno, pokud provádíte čistou instalaci.\"\n${LangFileString} SETUP_UNUSER \"Vymazat data uživatele\"\n${LangFileString} SETUP_UNUSER_DESC \"Smaže všechna data ${GAME_NAME} vytvořená uživatelem, včetně modů, uložených her a nastavení. Použijte pouze při kompletní přeinstalaci.\"\n${LangFileString} SETUP_SHORTCUT_CHANGELOG \"Changelog\"\n${LangFileString} SETUP_SHORTCUT_README \"Přečti si\"\n${LangFileString} SETUP_SHORTCUT_USER \"Složka uživatele\"\n${LangFileString} SETUP_SHORTCUT_UNINSTALL \"Odinstalovat\"\n${LangFileString} SETUP_WARNING_UFO \"X-COM 1 nebylo nalezeno v zadané složce. ${GAME_NAME} ke spuštění potřebuje úplnou instalaci X-COM. Pokračovat?\"\n${LangFileString} SETUP_WARNING_TFTD \"X-COM 2 nebylo nalezeno v zadané složce. ${GAME_NAME} ke spuštění potřebuje úplnou instalaci X-COM. Pokračovat?\"\n${LangFileString} SETUP_WARNING_XCU \"Detekováno rozšíření XcomUtil. ${GAME_NAME} je s XcomUtil nekompatibilní a nemusí pracovat správně. Pokračovat?\"\n${LangFileString} SETUP_ERROR_PORTABLE \"Instalační složka není přenositelná.\"\n"
  },
  {
    "path": "install/win/Language/Danish.nsh",
    "content": "!insertmacro LANGFILE_EXT \"Danish\"\n${LangFileString} SETUP_XCOM_FOLDER_TITLE \"Vælg X-COM-placering\"\n${LangFileString} SETUP_XCOM_FOLDER_SUBTITLE \"Vælg mapperne hvor du har X-COM installeret.\"\n${LangFileString} SETUP_XCOM_FOLDER \"${GAME_NAME} ${GAME_VERSION} kræver en kopi af et af de følgende X-COM-spil. Du kan udelade dette trin, hvis du opgraderer en eksisterende installation.$\\n$\\nInstallationen vil kopiere de krævede filer fra de følgende mapper. For at kopiere fra en anden mappe, klik ... og vælg en anden mappe. Klik næste for at fortsætte.\"\n${LangFileString} SETUP_UFO_FOLDER \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n${LangFileString} SETUP_TFTD_FOLDER \"X-COM: Terror From The Deep\"\n${LangFileString} SETUP_GAME \"Spilfiler\"\n${LangFileString} SETUP_GAME_DESC \"Filer krævet for at afvikle ${GAME_NAME}.\"\n${LangFileString} SETUP_PORTABLE \"Flytbar installation\"\n${LangFileString} SETUP_PORTABLE_DESC \"${GAME_NAME} vil lagre brugerdata i installationsmappen. Der skal kunne skrives til mappen af brugeren.\"\n${LangFileString} SETUP_DESKTOP \"Skrivebordsgenvej\"\n${LangFileString} SETUP_DESKTOP_DESC \"Opretter en genvej på skrivebordet til at spille ${GAME_NAME}.\"\n${LangFileString} SETUP_UNDATA \"Slet X-COM-data\"\n${LangFileString} SETUP_UNDATA_DESC \"Sletter alle ${GAME_NAME}-installationsdata, inklusive X-COM-ressourcer. Anbefalet for en ren geninstallation.\"\n${LangFileString} SETUP_UNUSER \"Slet brugerdata\"\n${LangFileString} SETUP_UNUSER_DESC \"Sletter alla ${GAME_NAME}-brugerdata, inklusive mod'er, gemte spil, skærmbilleder og indstillinger. Brug kun denne for en fuldstændig sletning.\"\n${LangFileString} SETUP_SHORTCUT_CHANGELOG \"Ændringslog\"\n${LangFileString} SETUP_SHORTCUT_README \"Læsmig\"\n${LangFileString} SETUP_SHORTCUT_USER \"Brugermappe\"\n${LangFileString} SETUP_SHORTCUT_UNINSTALL \"Afinstaller\"\n${LangFileString} SETUP_WARNING_UFO \"X-COM 1 blev ikke fundet i mappen. ${GAME_NAME} kræver en gyldig installation af X-COM for at blive afviklet. Fortsæt?\"\n${LangFileString} SETUP_WARNING_TFTD \"X-COM 2 blev ikke fundet i mappen. ${GAME_NAME} kræver en gyldig installation af X-COM for at blive afviklet. Fortsæt?\"\n${LangFileString} SETUP_WARNING_XCU \"XcomUtil detekteret. ${GAME_NAME} er ikke kompatibel med XcomUtil og fungerer måske ikke korrekt. Ønsker du at fortsætte?\"\n${LangFileString} SETUP_ERROR_PORTABLE \"Installationsmappen understøtter ikke flytbar installation.\"\n"
  },
  {
    "path": "install/win/Language/Dutch.nsh",
    "content": "!insertmacro LANGFILE_EXT \"Dutch\"\n${LangFileString} SETUP_XCOM_FOLDER_TITLE \"Kies X-COM Locatie\"\n${LangFileString} SETUP_XCOM_FOLDER_SUBTITLE \"Kies de mappen waar je X-COM hebt geïnstalleerd.\"\n${LangFileString} SETUP_XCOM_FOLDER \"${GAME_NAME} ${GAME_VERSION} vergt een kopie van een van de volgende X-COM spellen. Je kan deze stap overslaan als je een bestaande versie vernieuwt. $\\n$\\nSetup zal de nodige bestanden van de volgende mappen kopiëren. Om te kopiëren van een andere map, klik ... en selecteer een andere map. Klik Volgende om door te gaan.\"\n${LangFileString} SETUP_UFO_FOLDER \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n${LangFileString} SETUP_TFTD_FOLDER \"X-COM: Terror From The Deep\"\n${LangFileString} SETUP_GAME \"Spelbestanden\"\n${LangFileString} SETUP_GAME_DESC \"Bestanden nodig om ${GAME_NAME} uit te voeren.\"\n${LangFileString} SETUP_PORTABLE \"Draagbare Installatie\"\n${LangFileString} SETUP_PORTABLE_DESC \"${GAME_NAME} zal gebruikerdata in de installatiemap opslaan. De map moet gebruiker-schrijfbaar zijn.\"\n${LangFileString} SETUP_DESKTOP \"Bureaublad snelkoppeling\"\n${LangFileString} SETUP_DESKTOP_DESC \"Creëert een snelkoppeling op het bureaublad om ${GAME_NAME} te spelen.\"\n${LangFileString} SETUP_UNDATA \"Verwijder X-COM Data\"\n${LangFileString} SETUP_UNDATA_DESC \"Verwijdert alle ${GAME_NAME} installatiedata, inclusief X-COM bronnen. Aanbevolen voor een schone herinstallatie.\"\n${LangFileString} SETUP_UNUSER \"Verwijder Gebruikersdata\"\n${LangFileString} SETUP_UNUSER_DESC \"Verwijdert alle ${GAME_NAME} gebruikersdata, inclusief mods, opgeslagen spellen, schermafbeeldingen en opties. Alleen te gebruiken voor een volledige verwijdering.\"\n${LangFileString} SETUP_SHORTCUT_CHANGELOG \"Veranderingslogboek\"\n${LangFileString} SETUP_SHORTCUT_README \"Leesmij\"\n${LangFileString} SETUP_SHORTCUT_USER \"Gebruikersmap\"\n${LangFileString} SETUP_SHORTCUT_UNINSTALL \"Deïnstalleren\"\n${LangFileString} SETUP_WARNING_UFO \"X-COM 1 was niet in de map gevonden. ${GAME_NAME} vergt een geldige installatie van X-COM om uit te voeren. Doorgaan?\"\n${LangFileString} SETUP_WARNING_TFTD \"X-COM 2 was niet in de map gevonden. ${GAME_NAME} vergt een geldige installatie van X-COM om uit te voeren. Doorgaan?\"\n${LangFileString} SETUP_WARNING_XCU \"XcomUtil gedetecteerd. ${GAME_NAME} is niet compatibel met XcomUtil en zou niet correct kunnen werken. Doorgaan?\"\n${LangFileString} SETUP_ERROR_PORTABLE \"De installatie map bevindt zich in een beschermde locatie. \\nDit wordt niet ondersteund voor draagbare installaties.\"\n"
  },
  {
    "path": "install/win/Language/English.nsh",
    "content": ";NSIS OpenXcom Windows Installer Language\n\n!insertmacro LANGFILE_EXT \"English\" ; Must be the lang name define by NSIS\n\n;--------------------------------\n;Pages\n\n${LangFileString} SETUP_XCOM_FOLDER_TITLE \"Choose X-COM Location\"\n${LangFileString} SETUP_XCOM_FOLDER_SUBTITLE \"Choose the folders where you have X-COM installed.\"\n${LangFileString} SETUP_XCOM_FOLDER \"${GAME_NAME} ${GAME_VERSION} requires a copy of one of the following X-COM games. You can skip this step if you're upgrading an existing installation.$\\n$\\nSetup will copy the required files from the following folders. To copy from a different folder, click ... and select another folder. Click Next to continue.\"\n${LangFileString} SETUP_UFO_FOLDER \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n${LangFileString} SETUP_TFTD_FOLDER \"X-COM: Terror From The Deep\"\n\n;--------------------------------\n;Installer Sections\n\n${LangFileString} SETUP_GAME \"Game Files\"\n${LangFileString} SETUP_GAME_DESC \"Files required to run ${GAME_NAME}.\"\n${LangFileString} SETUP_PORTABLE \"Portable Installation\"\n${LangFileString} SETUP_PORTABLE_DESC \"${GAME_NAME} will store user data in the installation folder. The folder must be user-writable.\"\n${LangFileString} SETUP_DESKTOP \"Desktop Shortcut\"\n${LangFileString} SETUP_DESKTOP_DESC \"Creates a shortcut in the desktop to play ${GAME_NAME}.\"\n\n;--------------------------------\n;Uninstaller Descriptions\n\n${LangFileString} SETUP_UNDATA \"Delete X-COM Data\"\n${LangFileString} SETUP_UNDATA_DESC \"Deletes all ${GAME_NAME} install data, including X-COM resources. Recommended for a clean reinstall.\"\n${LangFileString} SETUP_UNUSER \"Delete User Data\"\n${LangFileString} SETUP_UNUSER_DESC \"Deletes all ${GAME_NAME} user data, including mods, savegames, screenshots and options. Only use this for a complete wipe.\"\n\n;--------------------------------\n;Shortcuts\n\n${LangFileString} SETUP_SHORTCUT_CHANGELOG \"Changelog\"\n${LangFileString} SETUP_SHORTCUT_README \"Readme\"\n${LangFileString} SETUP_SHORTCUT_USER \"User Folder\"\n${LangFileString} SETUP_SHORTCUT_UNINSTALL \"Uninstall\"\n\n;--------------------------------\n;Warnings\n\n${LangFileString} SETUP_WARNING_UFO \"X-COM 1 wasn't found in the folder. ${GAME_NAME} requires a valid installation of X-COM to run. Continue?\"\n${LangFileString} SETUP_WARNING_TFTD \"X-COM 2 wasn't found in the folder. ${GAME_NAME} requires a valid installation of X-COM to run. Continue?\"\n${LangFileString} SETUP_WARNING_XCU \"XcomUtil detected. ${GAME_NAME} is incompatible with XcomUtil and may not work correctly. Continue?\"\n${LangFileString} SETUP_ERROR_PORTABLE \"Installation folder is not portable.\""
  },
  {
    "path": "install/win/Language/Estonian.nsh",
    "content": "!insertmacro LANGFILE_EXT \"Estonian\"\n${LangFileString} SETUP_XCOM_FOLDER_TITLE \"Vali X-COMi asukoht\"\n${LangFileString} SETUP_XCOM_FOLDER_SUBTITLE \"Vali kataloogid kuhu oled X-COMi installinud.\"\n${LangFileString} SETUP_XCOM_FOLDER \"${GAME_NAME} ${GAME_VERSION} vajab ühte järgnevatest X-COMi mängudest. Võid loobuda sellest osast kui uuendad eksisteerivat installatsiooni.$\\n$\\nSetup kopeerib vajalikud failid järgnevaist kataloogidest. Et kopeerida teisest kataloogist, vajuta ... ja vali teine kataloog. Vajuta Järgmine jätkamiseks.\"\n${LangFileString} SETUP_UFO_FOLDER \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n${LangFileString} SETUP_TFTD_FOLDER \"X-COM: Terror From The Deep\"\n${LangFileString} SETUP_GAME \"Mängu failid\"\n${LangFileString} SETUP_GAME_DESC \"Failid mida on vaja mängu jooksutamiseks ${GAME_NAME}.\"\n${LangFileString} SETUP_PORTABLE \"Teisaldatav installatsioon\"\n${LangFileString} SETUP_PORTABLE_DESC \"${GAME_NAME} salvestab kasutaja andmed installikataloogi. Kataloog ei tohi olla kirjutuskaitstud.\"\n${LangFileString} SETUP_DESKTOP \"Otsetee desktopile \"\n${LangFileString} SETUP_DESKTOP_DESC \"Teeb desktopile otsetee ${GAME_NAME}st.\"\n${LangFileString} SETUP_UNDATA \"Kustuta X-COM.\"\n${LangFileString} SETUP_UNDATA_DESC \"Kustutab kõik ${GAME_NAME} failid, kaasaarvatud X-COMi ressursid. Soovitatav puhta reinstalli jaoks.\"\n${LangFileString} SETUP_UNUSER \"Kustuta kasutaja andmed.\"\n${LangFileString} SETUP_UNUSER_DESC \"Kustutab kõik ${GAME_NAME} kasutaja andmed, kaasaarvatud modid, salvestused, pildid ja valikud. Kasuta seda ainult täielikuks mängu eemaldamiseks.\"\n${LangFileString} SETUP_SHORTCUT_CHANGELOG \"Muutused.\"\n${LangFileString} SETUP_SHORTCUT_README \"LoeMind\"\n${LangFileString} SETUP_SHORTCUT_USER \"User Folder\"\n${LangFileString} SETUP_SHORTCUT_UNINSTALL \"Uninstalli\"\n${LangFileString} SETUP_WARNING_UFO \"X-COM 1 puudub kataloogist. ${GAME_NAME} vajab töötamiseks originaal X-COMi. Jätka?\"\n${LangFileString} SETUP_WARNING_TFTD \"X-COM 2 puudub kataloogist. ${GAME_NAME} vajab töötamiseks originaal X-COMi. Jätka?\"\n${LangFileString} SETUP_WARNING_XCU \"XcomUtil leitud. ${GAME_NAME} ei ühildu XcomUtiliga ning ei pruugi korrektselt töödata. Jätka?\"\n${LangFileString} SETUP_ERROR_PORTABLE \"Installikaust ei toeta kaasaskantavat installimist.\"\n"
  },
  {
    "path": "install/win/Language/Finnish.nsh",
    "content": "!insertmacro LANGFILE_EXT \"Finnish\"\n${LangFileString} SETUP_XCOM_FOLDER_TITLE \"Määritä X-COM:n sijainti\"\n${LangFileString} SETUP_XCOM_FOLDER_SUBTITLE \"Määritä kansiot, joihin X-COM on asennettu.\"\n${LangFileString} SETUP_XCOM_FOLDER \"${GAME_NAME} ${GAME_VERSION} edellyttää alkuperäiskappaleen omistamista yhdestä seuraavista X-COM-peleistä. Voit ohittaa tämän vaiheen, jos olet päivittämässä aiempaa asennusta.$\\n$\\nAsennus kopioi tarvittavat tiedostot seuraavista kansioista. Kopioidaksesi toisesta kansiosta napsauta ... ja valitse toinen kansio. Napsauta Seuraava jatkaaksesi.\"\n${LangFileString} SETUP_UFO_FOLDER \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n${LangFileString} SETUP_TFTD_FOLDER \"X-COM: Terror From The Deep\"\n${LangFileString} SETUP_GAME \"Pelin tiedostot\"\n${LangFileString} SETUP_GAME_DESC \"Tarvittavat tiedostot ohjelman ${GAME_NAME} ajamiseksi.\"\n${LangFileString} SETUP_PORTABLE \"Siirrettävä asennus\"\n${LangFileString} SETUP_PORTABLE_DESC \"${GAME_NAME} tallentaa käyttäjätiedot asennuskansioon. Käyttäjällä on oltava kansioon kirjoitusoikeus.\"\n${LangFileString} SETUP_DESKTOP \"Työpöydän pikakuvake\"\n${LangFileString} SETUP_DESKTOP_DESC \"Luo työpöydälle pikakuvakkeen pelin ${GAME_NAME} pelaamiseksi.\"\n${LangFileString} SETUP_UNDATA \"Poista X-COM:n tiedot\"\n${LangFileString} SETUP_UNDATA_DESC \"Poistaa kaikki pelin ${GAME_NAME} asennustiedot, mukaan lukien X-COM-resurssit. Suositellaan puhtaan uudelleenasennuksen yhteydessä.\"\n${LangFileString} SETUP_UNUSER \"Poista käyttäjätiedot\"\n${LangFileString} SETUP_UNUSER_DESC \"Poistaa kaikki pelin ${GAME_NAME} käyttäjätiedot, mukaan lukien modit, tallennetut pelit, kuvakaappaukset ja asetukset. Käytä tätä vaihtoehtoa ainoastaan täydellisen poiston yhteydessä.\"\n${LangFileString} SETUP_SHORTCUT_CHANGELOG \"Muutosloki\"\n${LangFileString} SETUP_SHORTCUT_README \"Lueminut\"\n${LangFileString} SETUP_SHORTCUT_USER \"Käyttäjäkansio\"\n${LangFileString} SETUP_SHORTCUT_UNINSTALL \"Poista\"\n${LangFileString} SETUP_WARNING_UFO \"X-COM 1 ei löytynyt kansiosta. ${GAME_NAME} vaatii kelvollisen asennuksen X-COM:sta toimiakseen. Jatketaanko?\"\n${LangFileString} SETUP_WARNING_TFTD \"X-COM 2 ei löytynyt kansiosta. ${GAME_NAME} vaatii kelvollisen asennuksen X-COM:sta toimiakseen. Jatketaanko?\"\n${LangFileString} SETUP_WARNING_XCU \"XcomUtil havaittu. ${GAME_NAME} ei ole yhteensopiva XcomUtilin kanssa eikä välttämättä toimi oikein. Jatketaanko?\"\n${LangFileString} SETUP_ERROR_PORTABLE \"Asennuskansio ei tue siirrettävää asennusta.\"\n"
  },
  {
    "path": "install/win/Language/French.nsh",
    "content": "!insertmacro LANGFILE_EXT \"French\"\n${LangFileString} SETUP_XCOM_FOLDER_TITLE \"Choisissez l'emplacement X-COM\"\n${LangFileString} SETUP_XCOM_FOLDER_SUBTITLE \"Choisissez le dossier d'installation de X-COM. \"\n${LangFileString} SETUP_XCOM_FOLDER \"${GAME_NAME} ${GAME_VERSION} requiert une copie de l'un des jeux X-COM suivants. Vous pouvez sauter cette étape si vous mettez à jour une installation existante.$\\n$\\nL'installation va copier les fichiers requis depuis les dossiers suivants. Pour copier depuis un dossier différent, cliquez sur ... et sélectionnez un autre dossier. Cliquez sur Suivant pour continuer.\"\n${LangFileString} SETUP_UFO_FOLDER \"UFO : Enemy Unknown / X-COM : UFO Defense\"\n${LangFileString} SETUP_TFTD_FOLDER \"X-COM : Terror From The Deep\"\n${LangFileString} SETUP_GAME \"Fichiers du jeu\"\n${LangFileString} SETUP_GAME_DESC \"Fichiers requis pour lancer ${GAME_NAME}.\"\n${LangFileString} SETUP_PORTABLE \"Installation portable\"\n${LangFileString} SETUP_PORTABLE_DESC \"${GAME_NAME} stockera les données d'utilisateur dans le dossier d'installation. Le dossier doit être modifiable.\"\n${LangFileString} SETUP_DESKTOP \"Raccourci sur le bureau\"\n${LangFileString} SETUP_DESKTOP_DESC \"Crée un raccourci sur le bureau pour lancer ${GAME_NAME}.\"\n${LangFileString} SETUP_UNDATA \"Détruit les données X-COM\"\n${LangFileString} SETUP_UNDATA_DESC \"Supprime toutes les données d'installation ${GAME_NAME} , y compris les ressources d'X-Com. Recommandé pour une réinstallation complète.\"\n${LangFileString} SETUP_UNUSER \"Effacer les données utilisateur\"\n${LangFileString} SETUP_UNUSER_DESC \"Effacer toutes les données utilisateur ${GAME_NAME}, y-compris les mods, parties sauvées, captures d'écrans et options. Utiliser uniquement pour une suppression complète.\"\n${LangFileString} SETUP_SHORTCUT_CHANGELOG \"Journal des changements\"\n${LangFileString} SETUP_SHORTCUT_README \"Lisez-moi\"\n${LangFileString} SETUP_SHORTCUT_USER \"Dossier utilisateur\"\n${LangFileString} SETUP_SHORTCUT_UNINSTALL \"Désinstaller\"\n${LangFileString} SETUP_WARNING_UFO \"X-COM 1 n'a pas été trouvé dans le dossier. ${GAME_NAME} requiert une installation valide de X-COM pour s'exécuter. Continuer ?\"\n${LangFileString} SETUP_WARNING_TFTD \"X-COM 2 n'a pas été trouvé dans le dossier. ${GAME_NAME} requiert une installation valide de X-COM pour s'exécuter. Continuer ?\"\n${LangFileString} SETUP_WARNING_XCU \"XcomUtil détecté. ${GAME_NAME} est incompatible avec XcomUtil et ne devrait pas fonctionner correctement. Continuer ?\"\n${LangFileString} SETUP_ERROR_PORTABLE \"Le dossier d'installation n'est pas portable.\"\n"
  },
  {
    "path": "install/win/Language/German.nsh",
    "content": "!insertmacro LANGFILE_EXT \"German\"\n${LangFileString} SETUP_XCOM_FOLDER_TITLE \"X-COM Standort auswählen\"\n${LangFileString} SETUP_XCOM_FOLDER_SUBTITLE \"Wählen Sie den Ordner, in dem Sie X-COM installiert haben.\"\n${LangFileString} SETUP_XCOM_FOLDER \"${GAME_NAME} ${GAME_VERSION} benötigt eines der folgenden X-COM Spiele. Falls diese Installation als Upgrade für eine bestehende Installation ausgeführt wird kann dieser Schritt übersprungen werden.$\\n$\\n$\\nSetup wird die benötigten Dateien aus den folgenden Ordnern kopieren. Um die Dateien aus einem anderen Ordner heraus zu kopieren bitte ... anklicken und den Ordner auswählen. Klicke auf 'Weiter' um fortzufahren. \"\n${LangFileString} SETUP_UFO_FOLDER \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n${LangFileString} SETUP_TFTD_FOLDER \"X-COM: Terror From The Deep\"\n${LangFileString} SETUP_GAME \"Spieledateien\"\n${LangFileString} SETUP_GAME_DESC \"Benötigte ${GAME_NAME}-Dateien.\"\n${LangFileString} SETUP_PORTABLE \"Portable Installation\"\n${LangFileString} SETUP_PORTABLE_DESC \"${GAME_NAME} speichert Benutzerdaten im Installationsordner.{NEWLINE}Der Ordner muss vom Anwender beschreibbar sein.\"\n${LangFileString} SETUP_DESKTOP \"Verknüpfung auf dem Desktop\"\n${LangFileString} SETUP_DESKTOP_DESC \"Erstellt eine ${GAME_NAME}-Verknüpfung auf dem Desktop.\"\n${LangFileString} SETUP_UNDATA \"X-COM Daten Löschen\"\n${LangFileString} SETUP_UNDATA_DESC \"Löscht alle ${GAME_NAME} Installationsdaten, einschließlich X-COM-Ressourcen. Empfohlen für eine saubere Neuinstallation.\"\n${LangFileString} SETUP_UNUSER \"Lösche Benutzerdaten\"\n${LangFileString} SETUP_UNUSER_DESC \"Löscht alle ${GAME_NAME} Benutzerdaten, einschließlich mods, Savegames, Screenshots und Optionen.\"\n${LangFileString} SETUP_SHORTCUT_CHANGELOG \"Changelog\"\n${LangFileString} SETUP_SHORTCUT_README \"Liesmich\"\n${LangFileString} SETUP_SHORTCUT_USER \"Benutzerverzeichnis\"\n${LangFileString} SETUP_SHORTCUT_UNINSTALL \"Deinstallieren\"\n${LangFileString} SETUP_WARNING_UFO \"X-COM 1 wurde im angegebenen Ordner nicht gefunden. ${GAME_NAME} benötigt eine gültige Installation von X-COM 1 um Starten zu können. Dennoch fortfahren?\"\n${LangFileString} SETUP_WARNING_TFTD \"X-COM 2 wurde im angegebenen Ordner nicht gefunden. ${GAME_NAME} benötigt eine gültige Installation von X-COM 2 um Starten zu können. Dennoch fortfahren?\"\n${LangFileString} SETUP_WARNING_XCU \"XcomUtil wurde erkannt. ${GAME_NAME} ist mit XcomUtil nicht kompatibel und könnte nicht richtig funktionieren. Dennoch fortfahren?\"\n${LangFileString} SETUP_ERROR_PORTABLE \"Der Installationsordner ist nicht portabel.\"\n"
  },
  {
    "path": "install/win/Language/Greek.nsh",
    "content": "!insertmacro LANGFILE_EXT \"Greek\"\n${LangFileString} SETUP_XCOM_FOLDER_TITLE \"Επιλέξτε θέση για εγκατάσταση του X-COM\"\n${LangFileString} SETUP_XCOM_FOLDER_SUBTITLE \"Διαλέξτε τον φάκελο που έχετε εγκαταστημένο το X-COM.\"\n${LangFileString} SETUP_XCOM_FOLDER \"${GAME_NAME} ${GAME_VERSION} χρειάζεται μία κόπια ενός από τα ακόλουθα X-COM παιχνίδια. Μπορείτε να παραλήψετε αυτό το βήμα αν κάνετε αναβάθμηση της τρέχουσας εγκατάστατης..$\\n$\\nΗ εγκατάσταση θα αντιγράψει τα απετούμετα αρχεία από τους φακέλους που ακολουθούν. Για να αντιγράψετε απο διαφορετικό φάκελο, πατήστε ... και διαλέξτε διαφορετκό φάκελο. Πατήστε επόμενο για να συνεχίσετε.\"\n${LangFileString} SETUP_UFO_FOLDER \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n${LangFileString} SETUP_TFTD_FOLDER \"X-COM: Terror From The Deep\"\n${LangFileString} SETUP_GAME \"Αρχεία από Παιχνίδι\"\n${LangFileString} SETUP_GAME_DESC \"Αρχεία που απαιτούνται για την εκτέλεση του ${GAME_NAME}.\"\n${LangFileString} SETUP_PORTABLE \"Φορητή Εγκατάσταση\"\n${LangFileString} SETUP_PORTABLE_DESC \"Το ${GAME_NAME} θα αποθηκεύσει τα δεδομένα χρήστη στο φάκελο εγκατάστασης. Ο φάκελος πρέπει να μπορεί να εγγραφεί από τον χρήστη.\"\n${LangFileString} SETUP_DESKTOP \"Συντόμευση Επιφάνειας Εργασίας\"\n${LangFileString} SETUP_DESKTOP_DESC \"Δημιουργεί μια συντόμευση στην επιφάνεια εργασίας για να παίξετε ${GAME_NAME}.\"\n${LangFileString} SETUP_UNDATA \"Διαγραφή Δεδομένων X-COM\"\n${LangFileString} SETUP_UNDATA_DESC \"Διαγράφει όλα τα δεδομένα εγκατάστασης του ${GAME_NAME}, συμπεριλαμβανομένων των πόρων του X-COM. Συνιστάται για καθαρή επανεγκατάσταση.\"\n${LangFileString} SETUP_UNUSER \"Διαγραφή Dεδομένων Xρήστη\"\n${LangFileString} SETUP_UNUSER_DESC \"Διαγράφει όλα τα δεδομένα χρήστη ${GAME_NAME}, συμπεριλαμβανομένων των mods, savegames, στιγμιότυπων οθόνης και επιλογών. Χρησιμοποιήστε το μόνο για μία πλήρες διαγραφή.\"\n${LangFileString} SETUP_SHORTCUT_CHANGELOG \"Καταγραφή αλλαγών\"\n${LangFileString} SETUP_SHORTCUT_README \"Διαβασέ με\"\n${LangFileString} SETUP_SHORTCUT_USER \"Φάκελος Xρήστη\"\n${LangFileString} SETUP_SHORTCUT_UNINSTALL \"Απεγκατάσταση\"\n${LangFileString} SETUP_WARNING_UFO \"Το X-COM 1 δεν βρέθηκε στο φάκελο. Το ${GAME_NAME} απαιτεί έγκυρη εγκατάσταση του X-COM για να εκτελεστεί. Θέλετε να συνεχίσετε?\"\n${LangFileString} SETUP_WARNING_TFTD \"Το X-COM 2 δεν βρέθηκε στο φάκελο. Το ${GAME_NAME} απαιτεί έγκυρη εγκατάσταση του X-COM για να εκτελεστεί. Θέλετε να συνεχίσετε?\"\n${LangFileString} SETUP_WARNING_XCU \"Το XcomUtil εντοπίστηκε. Το ${GAME_NAME} δεν είναι συμβατό με το XcomUtil και ενδέχεται να μην λειτουργεί σωστά. Θέλετε να συνεχίσετε?\"\n${LangFileString} SETUP_ERROR_PORTABLE \"Ο φάκελος εγκατάστασης δεν είναι φορητός.\"\n"
  },
  {
    "path": "install/win/Language/Hungarian.nsh",
    "content": "!insertmacro LANGFILE_EXT \"Hungarian\"\n${LangFileString} SETUP_XCOM_FOLDER_TITLE \"Válaszd ki az X-COM helyét\"\n${LangFileString} SETUP_XCOM_FOLDER_SUBTITLE \"Válaszd ki a mappát/mappákat, ahová telepítetted az X-COM-ot.\"\n${LangFileString} SETUP_XCOM_FOLDER \"${GAME_NAME} ${GAME_VERSION} -nak szüksége van egy másolatra a soron következő valamelyik X-COM játékok közül. Átugorhatod ezt a lépést, ha már egy meglévő telepítést frissítesz.$\\n$\\nA telepítő másolni fogja a szükséges fájlokat a következő mappából/mappákból. Ahhoz, hogy másik mappából másoljon, kattints a ... -ra és válassz egy másik mappát. Kattints a Következő gombra a folytatáshoz.\"\n${LangFileString} SETUP_UFO_FOLDER \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n${LangFileString} SETUP_TFTD_FOLDER \"X-COM: Terror From The Deep\"\n${LangFileString} SETUP_GAME \"Játék Fájlok\"\n${LangFileString} SETUP_GAME_DESC \"Fájlok szükségesek az ${GAME_NAME} futtatásához.\"\n${LangFileString} SETUP_PORTABLE \"Hordozható Verzió\"\n${LangFileString} SETUP_PORTABLE_DESC \"Az ${GAME_NAME} az adatokat a telepítési mappában fogja tárolni. A mappának a felhasználó által írhatónak kell lennie.\"\n${LangFileString} SETUP_DESKTOP \"Asztali Parancsikon\"\n${LangFileString} SETUP_DESKTOP_DESC \"Egy parancsikont hoz létre az asztalon, ahhoz, hogy következő játékkal játszani tudj: ${GAME_NAME}.\"\n${LangFileString} SETUP_UNDATA \"X-COM Adatainak Törlése.\"\n${LangFileString} SETUP_UNDATA_DESC \"Törli az ${GAME_NAME} összes telepítési adatát, beleértve az X-COM adatokat. Ajánlott egy tiszta újratelepítéshez.\"\n${LangFileString} SETUP_UNUSER \"Felhasználói Adatok Törlése\"\n${LangFileString} SETUP_UNUSER_DESC \"Törli az ${GAME_NAME} összes felhasználói adatát, beleértve a mod-okat, mentett játékállásokat, képernyőmentéseket és beállításokat. Csak teljes törlésre használd!\"\n${LangFileString} SETUP_SHORTCUT_CHANGELOG \"Változásnapló \"\n${LangFileString} SETUP_SHORTCUT_README \"Olvass el!\"\n${LangFileString} SETUP_SHORTCUT_USER \"Felhasználó Mappa\"\n${LangFileString} SETUP_SHORTCUT_UNINSTALL \"Törlés\"\n${LangFileString} SETUP_WARNING_UFO \"Az X-COM 1 nem található a mappában. Az ${GAME_NAME}-nak szüksége van egy érvényes/működő X-COM telepítésre a futtatáshoz. Folytatod?\"\n${LangFileString} SETUP_WARNING_TFTD \"Az X-COM 2 nem található a mappában. Az ${GAME_NAME}-nak szüksége van egy érvényes/működő X-COM telepítésre a futtatáshoz. Folytatod?\"\n${LangFileString} SETUP_WARNING_XCU \"XcomUtil észlelve. Az ${GAME_NAME} NEM kompatibilis az XcomUtil-lal és előfordulhat, hogy nem fog megfelelően működni. Folytatod?\"\n${LangFileString} SETUP_ERROR_PORTABLE \"A telepítési mappa nem támogatja a hordozható telepítést.\"\n"
  },
  {
    "path": "install/win/Language/Icelandic.nsh",
    "content": "!insertmacro LANGFILE_EXT \"Icelandic\"\n${LangFileString} SETUP_XCOM_FOLDER_TITLE \"Veldu X-COM staðsetningu\"\n${LangFileString} SETUP_XCOM_FOLDER_SUBTITLE \"Veldu möppuna þar sem þú hefur X-COM uppsettan.\"\n${LangFileString} SETUP_XCOM_FOLDER \"${GAME_NAME} ${GAME_VERSION} þarf eintak af einum af eftirfarandi X-COM leikjunum. Þú getur sleppt þessu stigi ef þú ert að uppfæra fyrirfram uppsettan leik.$\\n$\\nUppsetninging mun afrita gögn úr eftirfarandi möppum. Til að afrita úr anarri möppu, smelltu á ... og veldu á aðra möppu. Smelltu á Næst til að halda áfram.\"\n${LangFileString} SETUP_UFO_FOLDER \"FFH: Óþekktur Óvinur/X-COM: FFH Vörn\"\n${LangFileString} SETUP_TFTD_FOLDER \"X-COM: Ógn Úr Hyldýpinu\"\n${LangFileString} SETUP_GAME \"Leikja skrár\"\n${LangFileString} SETUP_GAME_DESC \"Skrár nauðsynlegar til að virkja ${GAME_NAME}.\"\n${LangFileString} SETUP_PORTABLE \"Færanleg Uppsetning\"\n${LangFileString} SETUP_PORTABLE_DESC \"${GAME_NAME} mun geyma notendagögn í uppsetri möppu. Mappan verður að vera aðgengileg fyrir breytingum frá notenda.\"\n${LangFileString} SETUP_DESKTOP \"Flýtileið á Skjáborð\"\n${LangFileString} SETUP_DESKTOP_DESC \"Býr til flýtileið á skjáborðið til að spila ${GAME_NAME}.\"\n${LangFileString} SETUP_UNDATA \"Eyða X-COM Gögnum\"\n${LangFileString} SETUP_UNDATA_DESC \"Eyðir öllum uppsettum gögnum frá ${GAME_NAME}. Mælt með fyrir fulla enduruppsetningu.\"\n${LangFileString} SETUP_UNUSER \"Eyða Notendagögnum\"\n${LangFileString} SETUP_UNUSER_DESC \"Eyðir öllum notendagögnum úr ${GAME_NAME}, þar á meðal breytipakka, vistaða leiki, skjáskot og valmöguleika. Notaðu þetta aðeins fyrir algera gagnahreinsun.\"\n${LangFileString} SETUP_SHORTCUT_CHANGELOG \"Breytingaskrá\"\n${LangFileString} SETUP_SHORTCUT_README \"Lestumig\"\n${LangFileString} SETUP_SHORTCUT_USER \"Notendamappa\"\n${LangFileString} SETUP_SHORTCUT_UNINSTALL \"Fjarlægja Leik\"\n${LangFileString} SETUP_WARNING_UFO \"X-COM 1 fannst ekki í möppunni. ${GAME_NAME} þarfnast lögmætrar uppsettningar X-COM til að virka. Halda áfram?\"\n${LangFileString} SETUP_WARNING_TFTD \"X-COM 2 fannst ekki í möppunni. ${GAME_NAME} þarfnast lögmætrar uppsettningar X-COM til að virka. Halda áfram?\"\n${LangFileString} SETUP_WARNING_XCU \"XcomUtil fannst. ${GAME_NAME} er ósamrýnanlegur XcomUtil og gæti ekki virkað rétt. Halda áfram?\"\n${LangFileString} SETUP_ERROR_PORTABLE \"Uppsetningarmappan styður ekki færanlega uppsetningu.\"\n"
  },
  {
    "path": "install/win/Language/Italian.nsh",
    "content": "!insertmacro LANGFILE_EXT \"Italian\"\n${LangFileString} SETUP_XCOM_FOLDER_TITLE \"Seleziona la Posizione di X-COM\"\n${LangFileString} SETUP_XCOM_FOLDER_SUBTITLE \"Seleziona le cartelle dove è installato X-COM.\"\n${LangFileString} SETUP_XCOM_FOLDER \"${GAME_NAME} ${GAME_VERSION} richiede una copia di uno dei seguenti giochi di X-COM. Puoi saltare questo passaggio se stai aggiornando un'installazione preesistente.$\\n$\\nL'installazione copierà i file richiesti da queste cartelle. Per copiarli da una cartella diversa, clicca ... e seleziona un'altra cartella. Premi Successivo per continuare.\"\n${LangFileString} SETUP_UFO_FOLDER \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n${LangFileString} SETUP_TFTD_FOLDER \"X-COM: Terror From The Deep\"\n${LangFileString} SETUP_GAME \"File di Gioco\"\n${LangFileString} SETUP_GAME_DESC \"File richiesti per eseguire ${GAME_NAME}.\"\n${LangFileString} SETUP_PORTABLE \"Installazione Portatile\"\n${LangFileString} SETUP_PORTABLE_DESC \"${GAME_NAME} salverà i dati utente nella cartella di installazione. La cartella deve essere scrivibile.\"\n${LangFileString} SETUP_DESKTOP \"Scorciatoia sul Desktop\"\n${LangFileString} SETUP_DESKTOP_DESC \"Crea una scorciatoia sul desktop per giocare a ${GAME_NAME}.\"\n${LangFileString} SETUP_UNDATA \"Cancella dati di X-COM\"\n${LangFileString} SETUP_UNDATA_DESC \"Cancella tutti ${GAME_NAME} di installazione, incluse le risorse X-COM. Raccomandato per una installazione pulita.\"\n${LangFileString} SETUP_UNUSER \"Cancella Dati Utente\"\n${LangFileString} SETUP_UNUSER_DESC \"Cancella tutti i dati utente di ${GAME_NAME}, incluse le mod, i salvataggi, gli screenshot e le opzioni. Utilizza quest'opzione solo per una disinstallazione completa.\"\n${LangFileString} SETUP_SHORTCUT_CHANGELOG \"Changelog\"\n${LangFileString} SETUP_SHORTCUT_README \"Leggimi\"\n${LangFileString} SETUP_SHORTCUT_USER \"Cartella Utente\"\n${LangFileString} SETUP_SHORTCUT_UNINSTALL \"Disinstalla\"\n${LangFileString} SETUP_WARNING_UFO \"X-COM 1 non è stato trovato nella cartella. ${GAME_NAME} richiede un'installazione valida di X-COM per funzionare. Continuare?\"\n${LangFileString} SETUP_WARNING_TFTD \"X-COM 2 non è stato trovato nella cartella. ${GAME_NAME} richiede un'installazione valida di X-COM per funzionare. Continuare?\"\n${LangFileString} SETUP_WARNING_XCU \"Rilevato XComUtil. ${GAME_NAME} è incompatibile con XComUtil e potrebbe non funzionare correttamente. Continuare?\"\n${LangFileString} SETUP_ERROR_PORTABLE \"La cartella per l'installazione non è portatile\"\n"
  },
  {
    "path": "install/win/Language/Japanese.nsh",
    "content": "!insertmacro LANGFILE_EXT \"Japanese\"\n${LangFileString} SETUP_XCOM_FOLDER_TITLE \"XComのインストール場所を選択\"\n${LangFileString} SETUP_XCOM_FOLDER_SUBTITLE \"X-Comがインストールされている場所を指定してください\"\n${LangFileString} SETUP_XCOM_FOLDER \"${GAME_NAME}の ${GAME_VERSION} バージョンが必要です。アップデートの場合はこの作業はスキップできます。$\\n$\\nセットアップに必要なファイルをオリジナルのX-Comフォルダからコピーします。他のフォルダからする場合はそれを選んで'次へ'をクリックしてください。\"\n${LangFileString} SETUP_UFO_FOLDER \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n${LangFileString} SETUP_TFTD_FOLDER \"X-COM: Terror From The Deep\"\n${LangFileString} SETUP_GAME \"ゲームのファイル\"\n${LangFileString} SETUP_GAME_DESC \"${GAME_NAME}.を起動するのに必要なファイル\"\n${LangFileString} SETUP_PORTABLE \"ポータブル版インストール\"\n${LangFileString} SETUP_PORTABLE_DESC \"${GAME_NAME} はユーザーのデータをインストール先のフォルダに保持します。フォルダを書き込み可能の状態にしてください。\"\n${LangFileString} SETUP_DESKTOP \"デスクトップ・ショートカット\"\n${LangFileString} SETUP_DESKTOP_DESC \"${GAME_NAME}.のデスクトップ・ショートカットを作成します\"\n${LangFileString} SETUP_UNDATA \"X-COMのデータを消去する\"\n${LangFileString} SETUP_UNDATA_DESC \"全ての ${GAME_NAME} のインストールデータを消去します。この処理にはオリジナルのX-COMのデータも含まれます。クリーンインストールを行いたい場合に推奨されるオプションです。\"\n${LangFileString} SETUP_UNUSER \"ユーザーデータの消去\"\n${LangFileString} SETUP_UNUSER_DESC \"${GAME_NAME}.のセーブデータ、MOD、スクリーンショットやオプション設定をWindowsのユーザーライブラリから消去します\"\n${LangFileString} SETUP_SHORTCUT_CHANGELOG \"変更点\"\n${LangFileString} SETUP_SHORTCUT_README \"Readme\"\n${LangFileString} SETUP_SHORTCUT_USER \"ユーザーフォルダ\"\n${LangFileString} SETUP_SHORTCUT_UNINSTALL \"アンインストール\"\n${LangFileString} SETUP_WARNING_UFO \"X-COM 1 が指定先に見つかりません。${GAME_NAME}のインストールには正常なオリジナル版X-COMのインストール済みフォルダが必要です。続けますか？\"\n${LangFileString} SETUP_WARNING_TFTD \"X-COM 2 が指定先に見つかりません。${GAME_NAME}のインストールには正常なオリジナル版X-COMのインストール済みフォルダが必要です。続けますか？\"\n${LangFileString} SETUP_WARNING_XCU \"XcomUtilがインストｰルされています。${GAME_NAME}はXcomUtilと互換性がなく、不具合が発生するかもしれません。続けますか?\"\n${LangFileString} SETUP_ERROR_PORTABLE \"インストールフォルダはポータブルには対応しません\"\n"
  },
  {
    "path": "install/win/Language/Korean.nsh",
    "content": "!insertmacro LANGFILE_EXT \"Korean\"\n${LangFileString} SETUP_XCOM_FOLDER_TITLE \"X-COM 위치 선택\"\n${LangFileString} SETUP_XCOM_FOLDER_SUBTITLE \"당신이 X-COM을 설치했던 폴더를 선택하라\"\n${LangFileString} SETUP_XCOM_FOLDER \"${GAME_NAME} ${GAME_VERSION}은 아래의 X-COM 게임들 중 하나의 사본을 요구합니다. 만약 당신이 기존 설치를 업그레이드하고 있다면 이 단계를 건너뛸 수 있습니다.$\\n$\\n설치 프로그램은 아래의 폴더에서 요구되는 파일을 복사할 것입니다. 다른 폴더로부터 복사하려면, ...를 누르고 또 다른 폴더를 선택하세요. 계속하려면 다음 을 누르세요.\"\n${LangFileString} SETUP_UFO_FOLDER \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n${LangFileString} SETUP_TFTD_FOLDER \"X-COM: Terror From The Deep\"\n${LangFileString} SETUP_GAME \"게임 파일\"\n${LangFileString} SETUP_GAME_DESC \"${GAME_NAME}을 실행하기 위해 요구되는 파일입니다.\"\n${LangFileString} SETUP_PORTABLE \"이동식 설치\"\n${LangFileString} SETUP_PORTABLE_DESC \"${GAME_NAME}은 설치 폴더에 사용자 자료를 저장할 것입니다. 이 폴더는 반드시 사용자가 편집할 수 있어야 합니다.\"\n${LangFileString} SETUP_DESKTOP \"바탕화면 바로가기\"\n${LangFileString} SETUP_DESKTOP_DESC \"${GAME_NAME}을 실행하기 위해 바탕 화면에 바로가기를 만듭니다.\"\n${LangFileString} SETUP_UNDATA \"X-COM 데이터 삭제\"\n${LangFileString} SETUP_UNDATA_DESC \"X-COM 자료를 포함해, 모든 ${GAME_NAME} 설치 데이터를 삭제합니다. 새롭게 다시 설치할 경우 추천됩니다.\"\n${LangFileString} SETUP_UNUSER \"사용자 자료 삭제\"\n${LangFileString} SETUP_UNUSER_DESC \"모드, 세이브, 스크린샷과 옵션 설정을 포함해, 모든 ${GAME_NAME}의 사용자 자료를 삭제합니다. 오직 완전히 삭제할 때만 사용하세요.\"\n${LangFileString} SETUP_SHORTCUT_CHANGELOG \"변경 기록\"\n${LangFileString} SETUP_SHORTCUT_README \"읽어보기\"\n${LangFileString} SETUP_SHORTCUT_USER \"사용자 폴더\"\n${LangFileString} SETUP_SHORTCUT_UNINSTALL \"삭제\"\n${LangFileString} SETUP_WARNING_UFO \"X-COM 1을 이 폴더에서 찾지 못했습니다. ${GAME_NAME}은 유효한 X-COM 설치본을 실행 시 요구합니다. 계속 하시겠습니까?\"\n${LangFileString} SETUP_WARNING_TFTD \"X-COM 1을 이 폴더에서 찾지 못했습니다. ${GAME_NAME}은 유효한 X-COM 설치본을 실행 시 요구합니다. 계속 하시겠습니까?\"\n${LangFileString} SETUP_WARNING_XCU \"XcomUtil을 탐지했습니다. ${GAME_NAME}은 XcomUtil과 호환되지 않으며 올바르게 동작하지 않을 지 모릅니다. 계속 하시겠습니까?\"\n${LangFileString} SETUP_ERROR_PORTABLE \"이 설치 폴더는 사용자 편집할 수 없습니다.\"\n"
  },
  {
    "path": "install/win/Language/Luxembourgish.nsh",
    "content": "!insertmacro LANGFILE_EXT \"Luxembourgish\"\n${LangFileString} SETUP_XCOM_FOLDER_TITLE \"Wiel den X-COM Dossier aus\"\n${LangFileString} SETUP_XCOM_FOLDER_SUBTITLE \"Wiel d'Dossieren aus wou's du X-COM installéiert hues.\"\n${LangFileString} SETUP_XCOM_FOLDER \"${GAME_NAME} ${GAME_VERSION} brauch eng Installatioun/Kopie vu folgenden X-COM Spiller. Dësen Deel kann iwwerspronge ginn, wann een just upgrade.$\\n$\\nDe Setup kopéiert d'Daten déi gebraucht ginn aus de folgenden Dossieren. Fir aus engem aneren Dossier ze kopéiren, klick ... an wiel en aneren Dossier aus. Klick Weider fir weider ze man.\"\n${LangFileString} SETUP_UFO_FOLDER \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n${LangFileString} SETUP_TFTD_FOLDER \"X-COM: Terror From The Deep\"\n${LangFileString} SETUP_GAME \"Spill-Dateien\"\n${LangFileString} SETUP_GAME_DESC \"Spill-Dateie gi gebraucht fir ${GAME_NAME} ze starten.\"\n${LangFileString} SETUP_PORTABLE \"Portabel Installatioun\"\n${LangFileString} SETUP_PORTABLE_DESC \"${GAME_NAME} schreiwt Benotzerdateien an den Installatiounsdossier. Den Dossier muss beschreiwbar sinn vum Benotzer.\"\n${LangFileString} SETUP_DESKTOP \"Desktop Shortcut\"\n${LangFileString} SETUP_DESKTOP_DESC \"Setzt e Shortcut op den Desktop fir ${GAME_NAME} ze spillen.\"\n${LangFileString} SETUP_UNDATA \"X-COM Date läschen\"\n${LangFileString} SETUP_UNDATA_DESC \"Läsch all ${GAME_NAME} Installatiounsdateien, inklusiv X-COM Ressourcen. Recommandéiert fir eng propper Neiinstallatioun.\"\n${LangFileString} SETUP_UNUSER \"User Date läschen\"\n${LangFileString} SETUP_UNUSER_DESC \"Läscht all ${GAME_NAME} User Daten, inklusiv Mods, Späicherstänn, Screenshots an Optiounen. Nëmme benotzen fir alles komplett ze läschen.\"\n${LangFileString} SETUP_SHORTCUT_CHANGELOG \"Changelog\"\n${LangFileString} SETUP_SHORTCUT_README \"Readme\"\n${LangFileString} SETUP_SHORTCUT_USER \"User Dossier\"\n${LangFileString} SETUP_SHORTCUT_UNINSTALL \"Deinstalléiren\"\n${LangFileString} SETUP_WARNING_UFO \"X-COM 1 gouf net am Dossier fonnt. ${GAME_NAME} brauch eng fonctionéirend X-COM Versioun fir ze lafen. Weider man ?\"\n${LangFileString} SETUP_WARNING_TFTD \"X-COM 2 gouf net am Dossier fonnt. ${GAME_NAME} brauch eng fonktionéirend X-COM Versioun fir ze lafen. Weider man ?\"\n${LangFileString} SETUP_WARNING_XCU \"XcomUtil fonnt. ${GAME_NAME} ass net kompatibel mat XcomUtil an kinnt net richteg fonktionéiren. Weider man?\"\n${LangFileString} SETUP_ERROR_PORTABLE \"Installatiounsdossier ass net portabel.\"\n"
  },
  {
    "path": "install/win/Language/Polish.nsh",
    "content": "!insertmacro LANGFILE_EXT \"Polish\"\n${LangFileString} SETUP_XCOM_FOLDER_TITLE \"Wybierz lokalizację gier UFO: Nieznany wróg i X-Com: Koszmar z głębin\"\n${LangFileString} SETUP_XCOM_FOLDER_SUBTITLE \"Wybierz foldery, w których gry „UFO: Nieznany wróg” i „X-Com: Koszmar z głębin” są zainstalowane.\"\n${LangFileString} SETUP_XCOM_FOLDER \"„${GAME_NAME}” w wersji ${GAME_VERSION} wymaga oryginalnej kopii gry. Możesz pominąć ten krok, jeśli zamierzasz tylko zaktualizować istniejącą instalację.$\\n$\\nInstalator skopiuje wymagane pliki z następujących folderów. Aby skopiować z innego folderu, kliknij „...” i wybierz inny folder. Kliknij „Dalej”, by kontynuować.\"\n${LangFileString} SETUP_UFO_FOLDER \"UFO: Nieznany wróg\"\n${LangFileString} SETUP_TFTD_FOLDER \"X-Com: Koszmar z głębin\"\n${LangFileString} SETUP_GAME \"Pliki gry\"\n${LangFileString} SETUP_GAME_DESC \"Wymagane pliki do uruchomienia gry „${GAME_NAME}”.\"\n${LangFileString} SETUP_PORTABLE \"Instalacja przenośna\"\n${LangFileString} SETUP_PORTABLE_DESC \"${GAME_NAME} będzie przechowywać pliki użytkownika w folderze instalacyjnym. Folder musi być zapisywalny przez użytkownika.\"\n${LangFileString} SETUP_DESKTOP \"Skrót na pulpicie\"\n${LangFileString} SETUP_DESKTOP_DESC \"Tworzy skrót na pulpicie, co umożliwia zagranie w „${GAME_NAME}”.\"\n${LangFileString} SETUP_UNDATA \"Usuń dane gier UFO: Nieznany wróg i X-Com: Koszmar z głębin\"\n${LangFileString} SETUP_UNDATA_DESC \"Kasuje wszystkie dane instalacyjne ${GAME_NAME}, włącznie z plikami X-Com. Zalecane przy czystej reinstalacji.\"\n${LangFileString} SETUP_UNUSER \"Usuń dane użytkownika\"\n${LangFileString} SETUP_UNUSER_DESC \"Usuwa wszystkie dane użytkownika gry „${GAME_NAME}”, wliczając w to modyfikacje, zapisane stany gry, zrzuty ekranu i opcje. Użyj tej opcji tylko dla pełnego wyczyszczenia danych.\"\n${LangFileString} SETUP_SHORTCUT_CHANGELOG \"Dziennik zmian\"\n${LangFileString} SETUP_SHORTCUT_README \"Informacje\"\n${LangFileString} SETUP_SHORTCUT_USER \"Folder użytkownika\"\n${LangFileString} SETUP_SHORTCUT_UNINSTALL \"Odinstaluj\"\n${LangFileString} SETUP_WARNING_UFO \"Gra „UFO: Nieznany wróg” nie została znaleziona w tym folderze. Wymaga ona poprawnej instalacji, by móc ją uruchomić. Kontynuować?\"\n${LangFileString} SETUP_WARNING_TFTD \"Gra „X-Com: Koszmar z głębin” nie została znaleziona w tym folderze. Wymaga ona poprawnej instalacji, by móc ją uruchomić. Kontynuować?\"\n${LangFileString} SETUP_WARNING_XCU \"Wykryto XcomUtil. ${GAME_NAME} nie jest kompatybilne z XcomUtil i może nie działać poprawnie. Kontynuować?\"\n${LangFileString} SETUP_ERROR_PORTABLE \"Folder instalacyjny nie jest przenośny.\"\n"
  },
  {
    "path": "install/win/Language/Portuguese.nsh",
    "content": "!insertmacro LANGFILE_EXT \"Portuguese\"\n${LangFileString} SETUP_XCOM_FOLDER_TITLE \"Escolher localização X-COM\"\n${LangFileString} SETUP_XCOM_FOLDER_SUBTITLE \"Escolher a pasta onde instalou X-COM.\"\n${LangFileString} SETUP_XCOM_FOLDER \"${GAME_NAME} ${GAME_VERSION} necessita de uma cópia de um dos seguintes jogos X-COM. Pode saltar este passo se está a atualizar uma instalação existente.\\n\\nA instalação copiará todos os ficheiros necessários das seguintes pastas. Para copiar de uma pasta diferente, clique ... e escolha outra pasta. Clique Seguinte para continuar.\"\n${LangFileString} SETUP_UFO_FOLDER \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n${LangFileString} SETUP_TFTD_FOLDER \"X-COM: Terror From The Deep\"\n${LangFileString} SETUP_GAME \"Ficheiros do jogo\"\n${LangFileString} SETUP_GAME_DESC \"Ficheiros necessários para correr ${GAME_NAME}.\"\n${LangFileString} SETUP_PORTABLE \"Instalação portável\"\n${LangFileString} SETUP_PORTABLE_DESC \"${GAME_NAME} irá guardar dados de utilizador na pasta de instalação. A pasta tem ser ser gravável.\"\n${LangFileString} SETUP_DESKTOP \"Atalho no ambiente de trabalho\"\n${LangFileString} SETUP_DESKTOP_DESC \"Cria atalho no ambiente de trabalho para jogar ${GAME_NAME}.\"\n${LangFileString} SETUP_UNDATA \"Remover ficheiros X-COM\"\n${LangFileString} SETUP_UNDATA_DESC \"Elimina todos os dados de ${GAME_NAME}, incluindo os recursos do X-COM. Recomendável para uma reinstalação limpa.\"\n${LangFileString} SETUP_UNUSER \"Remover dados do utilizador\"\n${LangFileString} SETUP_UNUSER_DESC \"Remove todos os dados de ${GAME_NAME}, incluindo mods, partidas gravadas, capturas de ecrã e opções. Usar apenas para uma limpeza completa.\"\n${LangFileString} SETUP_SHORTCUT_CHANGELOG \"Lista de mudanças\"\n${LangFileString} SETUP_SHORTCUT_README \"Leia-me\"\n${LangFileString} SETUP_SHORTCUT_USER \"Pasta do utilizador\"\n${LangFileString} SETUP_SHORTCUT_UNINSTALL \"Desinstalar\"\n${LangFileString} SETUP_WARNING_UFO \"X-COM 1 não foi encontrado na pasta. ${GAME_NAME} necessita de uma instalação válida de X-COM para correr. Continuar?\"\n${LangFileString} SETUP_WARNING_TFTD \"X-COM 2 não foi encontrado na pasta. ${GAME_NAME} necessita de uma instalação válida de X-COM para correr. Continuar?\"\n${LangFileString} SETUP_WARNING_XCU \"XcomUtil foi detetado. ${GAME_NAME} é incompatível com XcomUtil e poderá não funcionar corretamente. Continuar?\"\n${LangFileString} SETUP_ERROR_PORTABLE \"A pasta de instalação não é portável.\"\n"
  },
  {
    "path": "install/win/Language/PortugueseBR.nsh",
    "content": "!insertmacro LANGFILE_EXT \"PortugueseBR\"\n${LangFileString} SETUP_XCOM_FOLDER_TITLE \"Escolher Localização X-COM\"\n${LangFileString} SETUP_XCOM_FOLDER_SUBTITLE \"Escolha as pastas onde o X-COM está instalado.\"\n${LangFileString} SETUP_XCOM_FOLDER \"${GAME_NAME} ${GAME_VERSION} requer uma cópia de um dos seguintes jogos X-COM. Pode saltar este passo se estiver atualizando uma instalação existente.$\\n$\\nA instalação copiará todos os arquivos necessários das seguintes pastas. Para copiar de uma pasta diferente, clique ... e escolha outra pasta. Clique Próximo para continuar.\"\n${LangFileString} SETUP_UFO_FOLDER \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n${LangFileString} SETUP_TFTD_FOLDER \"X-COM: Terror From The Deep\"\n${LangFileString} SETUP_GAME \"Arquivos do Jogo\"\n${LangFileString} SETUP_GAME_DESC \"Arquivos necessários para executar o ${GAME_NAME}.\"\n${LangFileString} SETUP_PORTABLE \"Instalação portátil\"\n${LangFileString} SETUP_PORTABLE_DESC \"${GAME_NAME} irá armazenar dados de usuário na pasta de instalação. A pasta deve ter permissão de escrita pelo usuário.\"\n${LangFileString} SETUP_DESKTOP \"Atalho na Área de Trabalho\"\n${LangFileString} SETUP_DESKTOP_DESC \"Cria atalho na Área de Trabalho para jogar o ${GAME_NAME}.\"\n${LangFileString} SETUP_UNDATA \"Remover Dados do X-COM\"\n${LangFileString} SETUP_UNDATA_DESC \"Exclui todos os dados de instalação do ${GAME_NAME}, incluindo os recursos X-COM. Recomendado para uma reinstalação limpa.\"\n${LangFileString} SETUP_UNUSER \"Remover Dados do Usuário\"\n${LangFileString} SETUP_UNUSER_DESC \"Remove todos os dados do ${GAME_NAME}, incluindo mods, partidas salvas, capturas de tela e opções. Usar apenas para uma limpeza completa.\"\n${LangFileString} SETUP_SHORTCUT_CHANGELOG \"Lista de Alterações\"\n${LangFileString} SETUP_SHORTCUT_README \"Leia-me\"\n${LangFileString} SETUP_SHORTCUT_USER \"Pasta do Usuário\"\n${LangFileString} SETUP_SHORTCUT_UNINSTALL \"Desinstalar\"\n${LangFileString} SETUP_WARNING_UFO \"X-COM 1 não foi encontrado na pasta. ${GAME_NAME} requer uma instalação válida de X-COM para rodar. Continuar?\"\n${LangFileString} SETUP_WARNING_TFTD \"X-COM 2 não foi encontrado na pasta. ${GAME_NAME} requer uma instalação válida de X-COM para rodar. Continuar?\"\n${LangFileString} SETUP_WARNING_XCU \"XcomUtil foi detectado. ${GAME_NAME} não é compatível com o XcomUtil e poderá não funcionar corretamente. Continuar?\"\n${LangFileString} SETUP_ERROR_PORTABLE \"A pasta de instalação não é portátil.\"\n"
  },
  {
    "path": "install/win/Language/Romanian.nsh",
    "content": "!insertmacro LANGFILE_EXT \"Romanian\"\n${LangFileString} SETUP_XCOM_FOLDER_TITLE \"Alegeți Locația X-COM\"\n${LangFileString} SETUP_XCOM_FOLDER_SUBTITLE \"Alegeți dosarele unde aveți instalat X-COM.\"\n${LangFileString} SETUP_XCOM_FOLDER \"${GAME_NAME} ${GAME_VERSION} necesită o copie a unuia din următoarele jocuri X-COM. Dacă se face o actualizare a unei instalări existente se poate trece peste acest pas.$\\n$\\nInstalarea va copia fișierele necesare din următorul dosar. Pentru a copia din alt dosar, apăsați pe ... și selectați altă locație. Apăsați pe Înainte pentru a continua.\"\n${LangFileString} SETUP_UFO_FOLDER \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n${LangFileString} SETUP_TFTD_FOLDER \"X-COM: Terror From The Deep\"\n${LangFileString} SETUP_GAME \"Fișierele Jocului\"\n${LangFileString} SETUP_GAME_DESC \"Fișierele necesare pentru a rula ${GAME_NAME}.\"\n${LangFileString} SETUP_PORTABLE \"Instalare Portabilă\"\n${LangFileString} SETUP_PORTABLE_DESC \"${GAME_NAME} va păstra datele personalizate în dosarul de instalare. Dosarul trebuie să permită scrierea.\"\n${LangFileString} SETUP_DESKTOP \"Scurtătură Desktop\"\n${LangFileString} SETUP_DESKTOP_DESC \"Crează o scurtătură pe ecran pentru a juca ${GAME_NAME}.\"\n${LangFileString} SETUP_UNDATA \"Ștergere Date X-COM\"\n${LangFileString} SETUP_UNDATA_DESC \"Șterge toate datele ${GAME_NAME}, inclusiv resursele X-COM. Recomandat pentru o reinstalare curată.\"\n${LangFileString} SETUP_UNUSER \"Ștergere Date Utilizator\"\n${LangFileString} SETUP_UNUSER_DESC \"Șterge toate datele de utilizator pentru ${GAME_NAME}, inclusiv modificările, salvările, capturile de ecran și opțiunile. Recomandat numai pentru o ștergere completă.\"\n${LangFileString} SETUP_SHORTCUT_CHANGELOG \"Jurnal Modificări\"\n${LangFileString} SETUP_SHORTCUT_README \"Citește\"\n${LangFileString} SETUP_SHORTCUT_USER \"Dosar Utilizator\"\n${LangFileString} SETUP_SHORTCUT_UNINSTALL \"Dezinstalare\"\n${LangFileString} SETUP_WARNING_UFO \"X-COM 1 nu s-a găsit în acest dosar. ${GAME_NAME} necesită o instalare X-COM validă pentru a rula. Continuați?\"\n${LangFileString} SETUP_WARNING_TFTD \"X-COM 2 nu s-a găsit în acest dosar. ${GAME_NAME} necesită o instalare X-COM validă pentru a rula. Continuați?\"\n${LangFileString} SETUP_WARNING_XCU \"XcomUtil detectat. ${GAME_NAME} este incompatibil cu XcomUtil și este posibil să funcționeze incorect. Continuați?\"\n${LangFileString} SETUP_ERROR_PORTABLE \"Folderul de instalat nu este portabil.\"\n"
  },
  {
    "path": "install/win/Language/Russian.nsh",
    "content": "!insertmacro LANGFILE_EXT \"Russian\"\n${LangFileString} SETUP_XCOM_FOLDER_TITLE \"Укажите директорию X-COM\"\n${LangFileString} SETUP_XCOM_FOLDER_SUBTITLE \"Укажите каталог, в который установлена копия X-COM.\"\n${LangFileString} SETUP_XCOM_FOLDER \"Для ${GAME_NAME} ${GAME_VERSION} необходима копия одной из следующих игр. Если вы обновляете установленную игру, этот шаг можно пропустить.$\\n$\\nВо время установки необходимые файлы будут скопированы в следующий каталог. Если вы хотите скопировать их в другой каталог, нажмите кнопку «...» и укажите его. Нажмите «Далее» для продолжения.\"\n${LangFileString} SETUP_UFO_FOLDER \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n${LangFileString} SETUP_TFTD_FOLDER \"X-COM: Terror From The Deep\"\n${LangFileString} SETUP_GAME \"Файлы игры\"\n${LangFileString} SETUP_GAME_DESC \"Файлы, необходимые для запуска ${GAME_NAME}.\"\n${LangFileString} SETUP_PORTABLE \"Портативная (переносная) установка\"\n${LangFileString} SETUP_PORTABLE_DESC \"${GAME_NAME} будет хранить пользовательские данные в каталоге установки. Этот каталог должен быть доступен пользователю для записи.\"\n${LangFileString} SETUP_DESKTOP \"Ярлык на рабочем столе\"\n${LangFileString} SETUP_DESKTOP_DESC \"Создает ярлык ${GAME_NAME} на рабочем столе.\"\n${LangFileString} SETUP_UNDATA \"Удалить ассеты X-COM\"\n${LangFileString} SETUP_UNDATA_DESC \"Удалить все установленные файлы ${GAME_NAME}, включая ассеты X-COM. Рекомендуется при установке начисто.\"\n${LangFileString} SETUP_UNUSER \"Удалить пользовательские файлы\"\n${LangFileString} SETUP_UNUSER_DESC \"Удалить все пользовательские файлы ${GAME_NAME}, включая модификации, сохранения, снимки экрана и настройки игры. Рекомендуется только при полном удалении.\"\n${LangFileString} SETUP_SHORTCUT_CHANGELOG \"История изменений\"\n${LangFileString} SETUP_SHORTCUT_README \"Readme\"\n${LangFileString} SETUP_SHORTCUT_USER \"Пользовательский каталог\"\n${LangFileString} SETUP_SHORTCUT_UNINSTALL \"Удалить\"\n${LangFileString} SETUP_WARNING_UFO \"В каталоге не найдены ассеты X-COM 1. Для запуска ${GAME_NAME} необходимы файлы X-COM. Продолжить?\"\n${LangFileString} SETUP_WARNING_TFTD \"В каталоге не найдены ассеты X-COM 2. Для запуска ${GAME_NAME} необходимы файлы X-COM. Продолжить?\"\n${LangFileString} SETUP_WARNING_XCU \"Обнаружена утилита XcomUtil. ${GAME_NAME} несовместима с XcomUtil и может работать некорректно. Продолжить?\"\n${LangFileString} SETUP_ERROR_PORTABLE \"Директорию установки невозможно перенести.\"\n"
  },
  {
    "path": "install/win/Language/SimpChinese.nsh",
    "content": "!insertmacro LANGFILE_EXT \"SimpChinese\"\n${LangFileString} SETUP_XCOM_FOLDER_TITLE \"选择X-COM的安装目录\"\n${LangFileString} SETUP_XCOM_FOLDER_SUBTITLE \"选择你已经安装好的X-COM所在目录\"\n${LangFileString} SETUP_XCOM_FOLDER \"${GAME_NAME} ${GAME_VERSION} 需要任意一份如下X-COM游戏的副本。如果你是在升级，则可以跳过这一步。$\\n$\\n安装程序将会从以下目录复制文件，如果要从其他目录复制文件，点击“...”并选择目录。按“下一步”继续。\"\n${LangFileString} SETUP_UFO_FOLDER \"X-COM：飞碟防御\"\n${LangFileString} SETUP_TFTD_FOLDER \"X-COM：深海出击\"\n${LangFileString} SETUP_GAME \"游戏文件\"\n${LangFileString} SETUP_GAME_DESC \"运行${GAME_NAME}所需的文件。\"\n${LangFileString} SETUP_PORTABLE \"可移动设备\"\n${LangFileString} SETUP_PORTABLE_DESC \"${GAME_NAME}将会在安装文件夹中保存用户数据文件。请确保该文件夹拥有读写权限。\"\n${LangFileString} SETUP_DESKTOP \"桌面快捷方式\"\n${LangFileString} SETUP_DESKTOP_DESC \"在桌面上创建${GAME_NAME}的快捷方式。\"\n${LangFileString} SETUP_UNDATA \"删除X-COM数据\"\n${LangFileString} SETUP_UNDATA_DESC \"删除全部${GAME_NAME}安装数据，包括全部X-COM资源文件。推荐重新安装原始版本。\"\n${LangFileString} SETUP_UNUSER \"删除用户数据\"\n${LangFileString} SETUP_UNUSER_DESC \"删除所有${GAME_NAME}所有的用户数据，包括模组，存档，截图以及选项设置。卸载时请选中该项。\"\n${LangFileString} SETUP_SHORTCUT_CHANGELOG \"更新列表\"\n${LangFileString} SETUP_SHORTCUT_README \"说明\"\n${LangFileString} SETUP_SHORTCUT_USER \"用户文件夹\"\n${LangFileString} SETUP_SHORTCUT_UNINSTALL \"卸载\"\n${LangFileString} SETUP_WARNING_UFO \"没有找到原版X-COM1的位置。${GAME_NAME}需要一份有效的原版X-COM才能运行。继续吗？\"\n${LangFileString} SETUP_WARNING_TFTD \"没有找到原版X-COM2的位置。${GAME_NAME}需要一份有效的原版X-COM2才能运行。继续吗？\"\n${LangFileString} SETUP_WARNING_XCU \"检测到XcomUtil已经安装。${GAME_NAME}与它不兼容，可能会出现问题。继续吗？\"\n${LangFileString} SETUP_ERROR_PORTABLE \"安装文件夹不支持移动安装。\"\n"
  },
  {
    "path": "install/win/Language/Slovak.nsh",
    "content": "!insertmacro LANGFILE_EXT \"Slovak\"\n${LangFileString} SETUP_XCOM_FOLDER_TITLE \"Vyberte umiestnenie X-COM\"\n${LangFileString} SETUP_XCOM_FOLDER_SUBTITLE \"Vyberte priečinky, v ktorých máte nainštalovaný X-COM.\"\n${LangFileString} SETUP_XCOM_FOLDER \"${GAME_NAME} ${GAME_VERSION} vyžaduje kópiu jednej z nasledujúcich X-COM hier. Tento krok môžete preskočiť pokiaľ aktualizujete existujúcu inštaláciu.$\\n$\\nSetup skopíruje vyžadované súbory z nasledujúcich priečinkov. Pre kopírovanie z iného priečinku kliknite ... a vyberte iný priečinok. Pre pokračovanie kliknite na ďalej.\"\n${LangFileString} SETUP_UFO_FOLDER \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n${LangFileString} SETUP_TFTD_FOLDER \"X-COM: Terror From The Deep\"\n${LangFileString} SETUP_GAME \"Súbory hry\"\n${LangFileString} SETUP_GAME_DESC \"Súbory potrebné pre spustenie ${GAME_NAME}.\"\n${LangFileString} SETUP_PORTABLE \"Prenosná inštalácia\"\n${LangFileString} SETUP_PORTABLE_DESC \"${GAME_NAME} uloží aj všetky používateľské súbory do inštalačného priečinku. Priečinok nesmie byť chránený voči zapisovaniu.\"\n${LangFileString} SETUP_DESKTOP \"Ikona na ploche\"\n${LangFileString} SETUP_DESKTOP_DESC \"Vytvorí ikonu na ploche pre spustenie hry ${GAME_NAME}.\"\n${LangFileString} SETUP_UNDATA \"Vymazať X-COM dáta\"\n${LangFileString} SETUP_UNDATA_DESC \"Vymaže všetky nainštalované dáta hry ${GAME_NAME}, vrátane pôvodných súborov. Odporúča sa pre čistú reinštaláciu.\"\n${LangFileString} SETUP_UNUSER \"Vymazať používateľské dáta\"\n${LangFileString} SETUP_UNUSER_DESC \"Vymaže všetky užívateľské dáta hry ${GAME_NAME}, vrátane modov, uložených pozícii, screenshotov a nastavení. Odporúča sa iba pre kompletné vymazanie hry.\"\n${LangFileString} SETUP_SHORTCUT_CHANGELOG \"Changelog\"\n${LangFileString} SETUP_SHORTCUT_README \"Readme\"\n${LangFileString} SETUP_SHORTCUT_USER \"Používateľský priečinok\"\n${LangFileString} SETUP_SHORTCUT_UNINSTALL \"Odinštalovať\"\n${LangFileString} SETUP_WARNING_UFO \"X-COM 1 sa nenašla vo vybranom priečinku. ${GAME_NAME} vyžaduje platnú inštaláciu X-COMu, aby mohla fungovať. Pokračovať?\"\n${LangFileString} SETUP_WARNING_TFTD \"X-COM 2 sa nenašla vo vybranom priečinku. ${GAME_NAME} vyžaduje platnú inštaláciu X-COMu, aby mohla fungovať. Pokračovať?\"\n${LangFileString} SETUP_WARNING_XCU \"Bol nájdený XcomUtil. ${GAME_NAME} nie je kompatibilná s XComUtil a môže fungovať nesprávne. Pokračovať?\"\n${LangFileString} SETUP_ERROR_PORTABLE \"Inštalačný priečinok nepodporuje prenosnú inštaláciu.\"\n"
  },
  {
    "path": "install/win/Language/Spanish.nsh",
    "content": "!insertmacro LANGFILE_EXT \"Spanish\"\n${LangFileString} SETUP_XCOM_FOLDER_TITLE \"Elige ubicación de X-COM\"\n${LangFileString} SETUP_XCOM_FOLDER_SUBTITLE \"Elige la carpeta donde tienes X-COM instalado.\"\n${LangFileString} SETUP_XCOM_FOLDER \"${GAME_NAME} ${GAME_VERSION} requiere una copia de uno de los siguientes juegos de X-COM. Puede omitir este paso si va a actualizar una instalación existente.$\\n$\\nEl programa de instalación copiará los archivos necesarios de las siguientes carpetas. Para copiar desde una carpeta diferente, haga clic... y seleccione otra carpeta. Haga clic en Siguiente para continuar.\"\n${LangFileString} SETUP_UFO_FOLDER \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n${LangFileString} SETUP_TFTD_FOLDER \"X-COM: Terror From The Deep\"\n${LangFileString} SETUP_GAME \"Archivos del juego\"\n${LangFileString} SETUP_GAME_DESC \"Archivos necesarios para ejecutar ${GAME_NAME}.\"\n${LangFileString} SETUP_PORTABLE \"Instalación portable\"\n${LangFileString} SETUP_PORTABLE_DESC \"${GAME_NAME} guardará los datos de usuario en la carpeta de instalación. Asegúrate que la carpeta pueda ser escrita por el usuario.\"\n${LangFileString} SETUP_DESKTOP \"Acceso Directo en el Escritorio\"\n${LangFileString} SETUP_DESKTOP_DESC \"Crea un acceso directo en el escritorio para jugar ${GAME_NAME}.\"\n${LangFileString} SETUP_UNDATA \"Eliminar Datos de X-COM\"\n${LangFileString} SETUP_UNDATA_DESC \"Elimina todos los datos en la carpeta de instalación ${GAME_NAME}, incluyendo los archivos de X-COM. Acción recomendada para una instalación limpia.\"\n${LangFileString} SETUP_UNUSER \"Eliminar Datos del Usuario\"\n${LangFileString} SETUP_UNUSER_DESC \"Elimina todos los datos de usuario de ${GAME_NAME}, incluyendo mods, partidas guardadas, capturas de pantalla y opciones. Sólo la usamos para una limpieza completa.\"\n${LangFileString} SETUP_SHORTCUT_CHANGELOG \"Historial \"\n${LangFileString} SETUP_SHORTCUT_README \"Léeme\"\n${LangFileString} SETUP_SHORTCUT_USER \"Carpeta de usuario\"\n${LangFileString} SETUP_SHORTCUT_UNINSTALL \"Desinstalar\"\n${LangFileString} SETUP_WARNING_UFO \"X-COM 1 no se encontró en la carpeta. ${GAME_NAME} requiere una instalación válida de X-COM para funcionar. Continuar?\"\n${LangFileString} SETUP_WARNING_TFTD \"X-COM 2 no se encontró en la carpeta. ${GAME_NAME} requiere una instalación válida de X-COM para funcionar. Continuar?\"\n${LangFileString} SETUP_WARNING_XCU \"XcomUtil detectado. ${GAME_NAME} es incompatible con XcomUtil y podría no funcionar correctamente. Continuar?\"\n${LangFileString} SETUP_ERROR_PORTABLE \"La carpeta de instalación no es portátil.\"\n"
  },
  {
    "path": "install/win/Language/SpanishInternational.nsh",
    "content": "!insertmacro LANGFILE_EXT \"SpanishInternational\"\n${LangFileString} SETUP_XCOM_FOLDER_TITLE \"Elija ubicación de X-COM \"\n${LangFileString} SETUP_XCOM_FOLDER_SUBTITLE \"Elija los archivos donde tienes X-COM instalado.\"\n${LangFileString} SETUP_XCOM_FOLDER \"${GAME_NAME} ${GAME_VERSION} requiere una copia de uno de los siguientes juegos de X-COM. Puede omitir este paso si va a actualizar una instalación existente. $\\n$\\nEl programa de instalación copiará los archivos necesarios de las siguientes carpetas. Para copiar desde una carpeta diferente, presione... y seleccione otra carpeta. Presione en Siguiente para continuar.\"\n${LangFileString} SETUP_UFO_FOLDER \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n${LangFileString} SETUP_TFTD_FOLDER \"X-COM: Terror From The Deep\"\n${LangFileString} SETUP_GAME \"Archivos del Juego\"\n${LangFileString} SETUP_GAME_DESC \"Archivos necesarios para ejecutar ${GAME_NAME}.\"\n${LangFileString} SETUP_PORTABLE \"Instalación Portable\"\n${LangFileString} SETUP_PORTABLE_DESC \"${GAME_NAME} guardara data de usuario en el folder de instalación. Este folder debe poder ser escribible por el usuario\"\n${LangFileString} SETUP_DESKTOP \"Acceso Directo del Escritorio\"\n${LangFileString} SETUP_DESKTOP_DESC \"Crea un acceso directo en el escritorio para jugar ${GAME_NAME}.\"\n${LangFileString} SETUP_UNDATA \"Eliminar Datos de X-COM\"\n${LangFileString} SETUP_UNDATA_DESC \"Borata toda la data de instalación de ${GAME_NAME}, incluyendo recursos X-Com. Recomendado para una reinstalación limpia\"\n${LangFileString} SETUP_UNUSER \"Eliminar Datos del Usuario\"\n${LangFileString} SETUP_UNUSER_DESC \"Elimina todos los datos de usuario de ${GAME_NAME}, incluyendo mods, partidas guardadas, capturas de pantalla y opciones. Sólo la usamos para una limpieza completa.\"\n${LangFileString} SETUP_SHORTCUT_CHANGELOG \"Historial de Cambios\"\n${LangFileString} SETUP_SHORTCUT_README \"Léeme\"\n${LangFileString} SETUP_SHORTCUT_USER \"Carpeta de Usuario\"\n${LangFileString} SETUP_SHORTCUT_UNINSTALL \"Desinstalar\"\n${LangFileString} SETUP_WARNING_UFO \"X-COM 1 no se encontró en la carpeta. ${GAME_NAME} requiere una instalación válida de X-COM para funcionar. Continuar?\"\n${LangFileString} SETUP_WARNING_TFTD \"X-COM 2 no se encontró en la carpeta. ${GAME_NAME} requiere una instalación válida de X-COM para funcionar. Continuar?\"\n${LangFileString} SETUP_WARNING_XCU \"XcomUtil detectado. ${GAME_NAME} es incompatible con XcomUtil y podría no funcionar correctamente. ¿Continuar?\"\n${LangFileString} SETUP_ERROR_PORTABLE \"La carpeta de instalación no es portátil.\"\n"
  },
  {
    "path": "install/win/Language/Swedish.nsh",
    "content": "!insertmacro LANGFILE_EXT \"Swedish\"\n${LangFileString} SETUP_XCOM_FOLDER_TITLE \"Välj X-COM-plats\"\n${LangFileString} SETUP_XCOM_FOLDER_SUBTITLE \"Välj mapp där du har X-COM installerat.\"\n${LangFileString} SETUP_XCOM_FOLDER \"${GAME_NAME} ${GAME_VERSION} behöver ett exemplar av ett av följande X-COM-spel. Du kan ignorera detta steg om du uppgraderar en tidigare installation.\\n\\nInstallationsprogrammet kommer att kopiera de nödvändiga filerna från följande mappar. För att välja en annan mapp klicka på ... och välj en annan plats. Klicka Nästa för att fortsätta.\"\n${LangFileString} SETUP_UFO_FOLDER \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n${LangFileString} SETUP_TFTD_FOLDER \"X-COM: Terror From The Deep\"\n${LangFileString} SETUP_GAME \"Spelfiler\"\n${LangFileString} SETUP_GAME_DESC \"Filer som behövs för att köra ${GAME_NAME}.\"\n${LangFileString} SETUP_PORTABLE \"Portabel installation\"\n${LangFileString} SETUP_PORTABLE_DESC \"${GAME_NAME} kommer att lagra användardata i installationsmappen. Mappen måste vara skrivbar.\"\n${LangFileString} SETUP_DESKTOP \"Skrivbordsgenväg\"\n${LangFileString} SETUP_DESKTOP_DESC \"Skapar en genväg på skrivbordet för att spela ${GAME_NAME}.\"\n${LangFileString} SETUP_UNDATA \"Ta bort X-COM-data\"\n${LangFileString} SETUP_UNDATA_DESC \"Tar bort allt installerat ${GAME_NAME}-data inklusive X-Com-filer. Rekommenderas för en ren ominstallation.\"\n${LangFileString} SETUP_UNUSER \"Ta bort användardata\"\n${LangFileString} SETUP_UNUSER_DESC \"Tar bort allt ${GAME_NAME}-användardata, inklusive moddar, sparfiler, skärmdumpar och inställningar. Bör användas enbart vid total avinstallation.\"\n${LangFileString} SETUP_SHORTCUT_CHANGELOG \"Ändringslogg\"\n${LangFileString} SETUP_SHORTCUT_README \"Readme\"\n${LangFileString} SETUP_SHORTCUT_USER \"Användarmapp\"\n${LangFileString} SETUP_SHORTCUT_UNINSTALL \"Avinstallation\"\n${LangFileString} SETUP_WARNING_UFO \"X-COM 1 hittades inte i mappen. ${GAME_NAME} kräver en giltig installation av X-COM för att kunna köras. Fortsätt ändå?\"\n${LangFileString} SETUP_WARNING_TFTD \"X-COM 2 hittades inte i mappen. ${GAME_NAME} kräver en giltig installation av X-COM för att kunna köras. Fortsätt ändå?\"\n${LangFileString} SETUP_WARNING_XCU \"XcomUtil hittades. ${GAME_NAME} är okompatibelt med XcomUtil och kanske inte kommer fungera korrekt. Fortsätt ändå?\"\n${LangFileString} SETUP_ERROR_PORTABLE \"Installationsmappen är inte portabel.\"\n"
  },
  {
    "path": "install/win/Language/TradChinese.nsh",
    "content": "!insertmacro LANGFILE_EXT \"TradChinese\"\n${LangFileString} SETUP_XCOM_FOLDER_TITLE \"選擇 X-COM 安裝路徑\"\n${LangFileString} SETUP_XCOM_FOLDER_SUBTITLE \"選擇您已安裝 X-COM 的資料夾\"\n${LangFileString} SETUP_XCOM_FOLDER \"${GAME_NAME} ${GAME_VERSION} 需要以下的 X-COM 遊戲。若您要更新已存在的安裝，可略過此步驟。$\\n$\\n安裝程式將複製必須檔案至下列資料夾。欲複製到其他資料夾，點擊...以選擇其他資料夾。點擊下一步以繼續。\"\n${LangFileString} SETUP_UFO_FOLDER \"UFO: 未知敵人 / X-COM: UFO入侵\"\n${LangFileString} SETUP_TFTD_FOLDER \"X-COM: 深海幽浮\"\n${LangFileString} SETUP_GAME \"遊戲檔案\"\n${LangFileString} SETUP_GAME_DESC \"執行${GAME_NAME}的必須檔案。\"\n${LangFileString} SETUP_PORTABLE \"可攜式安裝\"\n${LangFileString} SETUP_PORTABLE_DESC \"${GAME_NAME}將會使用者資料儲存在安裝資料夾中。請確保該資料夾擁有讀寫權限。\"\n${LangFileString} SETUP_DESKTOP \"桌面捷徑\"\n${LangFileString} SETUP_DESKTOP_DESC \"在桌面建立一個玩 ${GAME_NAME}的捷徑。\"\n${LangFileString} SETUP_UNDATA \"刪除X-COM資料\"\n${LangFileString} SETUP_UNDATA_DESC \"刪除全部${GAME_NAME}安裝數據，包含全部X-COM資源檔。推薦重新安裝原始版本。\"\n${LangFileString} SETUP_UNUSER \"刪除使用者資料\"\n${LangFileString} SETUP_UNUSER_DESC \"刪除所有的${GAME_NAME}使用者資料，包括MOD、存檔、截圖和選項。僅於完全移除時使用。\"\n${LangFileString} SETUP_SHORTCUT_CHANGELOG \"更新紀錄\"\n${LangFileString} SETUP_SHORTCUT_README \"讀我\"\n${LangFileString} SETUP_SHORTCUT_USER \"使用者資料夾\"\n${LangFileString} SETUP_SHORTCUT_UNINSTALL \"移除\"\n${LangFileString} SETUP_WARNING_UFO \"未在資料夾尋獲X-COM 1。${GAME_NAME}需要一份有效的X-COM才能執行。是否繼續？\"\n${LangFileString} SETUP_WARNING_TFTD \"未在資料夾尋獲X-COM 2。${GAME_NAME}需要一份有效的X-COM才能執行。是否繼續？\"\n${LangFileString} SETUP_WARNING_XCU \"偵測到XcomUtil。${GAME_NAME}與該軟體不相容，可能會產生問題。是否繼續？\"\n${LangFileString} SETUP_ERROR_PORTABLE \"安裝文件夾不支援可攜式安裝。\"\n"
  },
  {
    "path": "install/win/Language/Turkish.nsh",
    "content": "!insertmacro LANGFILE_EXT \"Turkish\"\n${LangFileString} SETUP_XCOM_FOLDER_TITLE \"X-COM'un Konumunu Seç\"\n${LangFileString} SETUP_XCOM_FOLDER_SUBTITLE \"X-COM'un kurulu olduğu dizinlerin seçimi.\"\n${LangFileString} SETUP_XCOM_FOLDER \"${GAME_NAME} ${GAME_VERSION}, aşağıdaki X-COM oyunlarından birini gerektirir. Eğer mevcut bir kurulumu güncelliyorsanız, bu adımı atlayabilirsiniz.$\\n$\\nKurulum, gerekli dosyaları aşağıdaki dizinlerden kopyalayacak. Farklı bir dizinden kopyalamak için ... butonuna basın ve bir dizin seçin. Sonraki butonuna basarak devam edebilirsiniz.\"\n${LangFileString} SETUP_UFO_FOLDER \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n${LangFileString} SETUP_TFTD_FOLDER \"X-COM: Terror From The Deep\"\n${LangFileString} SETUP_GAME \"Oyun Dosyaları\"\n${LangFileString} SETUP_GAME_DESC \"${GAME_NAME} çalıştırmak için gerekli dosyalar.\"\n${LangFileString} SETUP_PORTABLE \"Taşınabilir Kurulum\"\n${LangFileString} SETUP_PORTABLE_DESC \"${GAME_NAME} kullanıcı bilgilerini kurulum dizininde tutar. Kullanıcının dizine yazma hakkı olmalıdır.\"\n${LangFileString} SETUP_DESKTOP \"Masaüstü Kısayolu\"\n${LangFileString} SETUP_DESKTOP_DESC \"Masaüstünde ${GAME_NAME} için kısayol oluşturur.\"\n${LangFileString} SETUP_UNDATA \"X-COM Verilerini Sil\"\n${LangFileString} SETUP_UNDATA_DESC \"X-COM kaynak dosyaları da dahil olmak üzere tüm ${GAME_NAME} verilerini siler. Temiz bir kurulum için tavsiye edilir.\"\n${LangFileString} SETUP_UNUSER \"Kullanıcı Verilerini Sil\"\n${LangFileString} SETUP_UNUSER_DESC \"Modlar, kayıtlı oyunlar, ekran görüntüleri ve ayarlar dahil olmak üzere tüm ${GAME_NAME}  kullanıcı verilerini siler. Sadece tam bir temizlik için tavsiye edilir.\"\n${LangFileString} SETUP_SHORTCUT_CHANGELOG \"Güncellemeler\"\n${LangFileString} SETUP_SHORTCUT_README \"Okubeni\"\n${LangFileString} SETUP_SHORTCUT_USER \"Kullanıcı Dizini\"\n${LangFileString} SETUP_SHORTCUT_UNINSTALL \"Kaldır\"\n${LangFileString} SETUP_WARNING_UFO \"X-COM 1 bulunamadı. ${GAME_NAME}, geçerli bir X-COM kurulumu gerektirir. Devam?\"\n${LangFileString} SETUP_WARNING_TFTD \"X-COM 2 bulunamadı. ${GAME_NAME}, geçerli bir X-COM kurulumu gerektirir. Devam?\"\n${LangFileString} SETUP_WARNING_XCU \"XcomUtil tespit edildi. ${GAME_NAME}, XcomUtil ile uyumlu olmadığından beklenmeyen durumlarla karşılaşabilirsiniz. Devam?\"\n${LangFileString} SETUP_ERROR_PORTABLE \"Kurulum dizini taşınabilir değil.\"\n"
  },
  {
    "path": "install/win/Language/Ukrainian.nsh",
    "content": "!insertmacro LANGFILE_EXT \"Ukrainian\"\n${LangFileString} SETUP_XCOM_FOLDER_TITLE \"Вкажіть розташування X-COM\"\n${LangFileString} SETUP_XCOM_FOLDER_SUBTITLE \"Оберіть каталог з встановленим X-COM.\"\n${LangFileString} SETUP_XCOM_FOLDER \"Для ${GAME_NAME} ${GAME_VERSION} необхідна копія однієї з наступних ігор серії  X-COM. Якщо ви оновлюєте вже встановлену гру цей крок можна пропустити.$\\n$\\nПід час встановлення необхдні файли будуть скопійовані з наступного каталогу. Для копіювання з іншого каталогу натисніть ... та оберіть необхідний каталог. Натисніть Далі для продовження.\"\n${LangFileString} SETUP_UFO_FOLDER \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n${LangFileString} SETUP_TFTD_FOLDER \"X-COM: Terror From The Deep\"\n${LangFileString} SETUP_GAME \"Файли гри\"\n${LangFileString} SETUP_GAME_DESC \"Файли, необхідні для запуску ${GAME_NAME}.\"\n${LangFileString} SETUP_PORTABLE \"Портативне Встановлення \"\n${LangFileString} SETUP_PORTABLE_DESC \"${GAME_NAME} буде зберігати ресурси користувача в каталозі встановлення. Каталог має бути доступним для запису файлів користувачем. \"\n${LangFileString} SETUP_DESKTOP \"Ярлик на Робочому столі\"\n${LangFileString} SETUP_DESKTOP_DESC \"Створити ярлик ${GAME_NAME} на Робочому столі\"\n${LangFileString} SETUP_UNDATA \"Видалити X-COM\"\n${LangFileString} SETUP_UNDATA_DESC \"Видалити всі встановлені дані ${GAME_NAME}, включно з ресурсами X-COM. Рекомендовано для чистого перевстановлення.\"\n${LangFileString} SETUP_UNUSER \"Видалити дані користувача\"\n${LangFileString} SETUP_UNUSER_DESC \"Видалити всі дані користувача ${GAME_NAME} включно з МОДифікаціями, збереженнями, знімками екрану та налаштуваннями. Рекомендовано тільки при повному видаленні.\"\n${LangFileString} SETUP_SHORTCUT_CHANGELOG \"Перелік змін\"\n${LangFileString} SETUP_SHORTCUT_README \"Readme\"\n${LangFileString} SETUP_SHORTCUT_USER \"Каталог користувача\"\n${LangFileString} SETUP_SHORTCUT_UNINSTALL \"Видалити\"\n${LangFileString} SETUP_WARNING_UFO \"Ресурси X-COM 1 не знайдені в каталозі. Для запуску ${GAME_NAME} потребує оригінальні файли X-COM. Продовжити?\"\n${LangFileString} SETUP_WARNING_TFTD \"Ресурси X-COM 2 не знайдені в каталозі. Для запуску ${GAME_NAME} потребує оригінальні файли X-COM. Продовжити?\"\n${LangFileString} SETUP_WARNING_XCU \"Виявлений XcomUtil. Можлива некоректна робота ${GAME_NAME} через несумісність з XcomUtil. Продовжити?\"\n${LangFileString} SETUP_ERROR_PORTABLE \"Теку з інсталяцією не можна переносити.\"\n"
  },
  {
    "path": "install/win/Language/bg.yml",
    "content": "bg:\n  SETUP_XCOM_FOLDER_TITLE: \"Изберете директорията на X-Com\"\n  SETUP_XCOM_FOLDER_SUBTITLE: \"Изберете директориите, където е инсталиран X-COM.\"\n  SETUP_XCOM_FOLDER: \"${GAME_NAME} ${GAME_VERSION} изисква копие на една от следните X-COM игри. Може да пропуснете тази стъпка ако надграждате вече съществуваща инсталиация.$\\n$\\nПроцесът на инсталация ще копира необходимите файлове от следните директории. Ако желаете да копирате от друга директория, натиснете ... и изберете друга директория. Натиснете Напред за да продължите.\"\n  SETUP_UFO_FOLDER: \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n  SETUP_TFTD_FOLDER: \"X-COM: Terror From The Deep\"\n  SETUP_GAME: \"Файлове на играта\"\n  SETUP_GAME_DESC: \"Файлове необходими за ${GAME_NAME}.\"\n  SETUP_PORTABLE: \"Преносима инсталация\"\n  SETUP_PORTABLE_DESC: \"${GAME_NAME} ще складира данните за потребителя в инсталационната директория. Потребителят трябва да може да пише в тази директория.\"\n  SETUP_DESKTOP: \"Препратка към работния плот.\"\n  SETUP_DESKTOP_DESC: \"Създава препратка на работния стол към играта ${GAME_NAME}.\"\n  SETUP_UNDATA: \"Изтриване на X-COM данните\"\n  SETUP_UNDATA_DESC: \"Изтрива всички данни на ${GAME_NAME}, включително ресурсите на X-COM. Препоръчително за напълно нова инсталация.\"\n  SETUP_UNUSER: \"Изтриване на данните на потребителя\"\n  SETUP_UNUSER_DESC: \"Изтрива всички данни на потребителя за ${GAME_NAME}, включително модификации, запазени игри, снимки на екрана и настройки. Използвайте само в случай на напълно изтриване.\"\n  SETUP_SHORTCUT_CHANGELOG: \"Списък с промените\"\n  SETUP_SHORTCUT_README: \"Прочети ме\"\n  SETUP_SHORTCUT_USER: \"Потребителска директория\"\n  SETUP_SHORTCUT_UNINSTALL: \"Деинсталация\"\n  SETUP_WARNING_UFO: \"X-COM 1 не беше открит в тази директория. ${GAME_NAME} изисква инсталация на X-COM за да работи правилно. Продължи?\"\n  SETUP_WARNING_TFTD: \"X-COM 2 не беше открит в тази директория. ${GAME_NAME} изисква инсталация на X-COM за да работи правилно. Продължи?\"\n  SETUP_WARNING_XCU: \"Открит е XcomUtil. ${GAME_NAME} не е съвместим с XcomUtil и няма да работи правилно. Продължи?\"\n  SETUP_ERROR_PORTABLE: \"Инсталационната директория не поддържа преносима инсталация.\"\n"
  },
  {
    "path": "install/win/Language/ca-ES.yml",
    "content": "ca-ES:\n  SETUP_XCOM_FOLDER_TITLE: \"Selecciona l'ubicació de X-COM\"\n  SETUP_XCOM_FOLDER_SUBTITLE: \"Seleccioni les carpetes on has instal·lat X-COM\"\n  SETUP_XCOM_FOLDER: \"${GAME_NAME} ${GAME_VERSION} necessita una còpia d'un dels jocs X-COM següents. Pots saltar aquest pas si ets actualitzant una instal·lació existent.$\\n$\\nLa instal·lació copiarà els fitxers necessaris de les carpetes següents. Per copiar els fitxers d'una carpeta diferent, clica ... i selecciona un altre carpeta.  Clica Següent per continuar.\"\n  SETUP_UFO_FOLDER: \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n  SETUP_TFTD_FOLDER: \"X-COM: Terror From The Deep\"\n  SETUP_GAME: \"Fitxers de joc\"\n  SETUP_GAME_DESC: \"Fitxers necessaris per jugar a ${GAME_NAME}.\"\n  SETUP_PORTABLE: \"Instal·lació portable\"\n  SETUP_PORTABLE_DESC: \"${GAME_NAME} salvarà tota l'informació d'usuari en la carpeta d'instal·lació. La carpeta ha de tenir drets d'escriptura per l'usuari.\"\n  SETUP_DESKTOP: \"Accès directe a l'escriptori\"\n  SETUP_DESKTOP_DESC: \"Crea un accès directe a l'escriptori per jugar a ${GAME_NAME}.\"\n  SETUP_UNDATA: \"Elimina les dades de X-COM\"\n  SETUP_UNDATA_DESC: \"Borra tota les dades d'instal·lació de ${GAME_NAME}, incloent les dades de X-COM. Recomanat per fer una reinstal·lació neta del joc.  \"\n  SETUP_UNUSER: \"Elimina les dades de l'usuari\"\n  SETUP_UNUSER_DESC: \"Elimina totes les dades d'usuari de ${GAME_NAME}, incloent modificacions, partides desades, captures de pantalla i opcions. Només utilitzar per una eliminació completa.\"\n  SETUP_SHORTCUT_CHANGELOG: \"Registre de canvis\"\n  SETUP_SHORTCUT_README: \"Readme\"\n  SETUP_SHORTCUT_USER: \"Carpeta d'usuari\"\n  SETUP_SHORTCUT_UNINSTALL: \"Desinstal·lar\"\n  SETUP_WARNING_UFO: \"X-COM 1 no s'ha trobat dins la carpeta. ${GAME_NAME} necessita una instal·lació vàlida de X-COM per funcionar. Continuar?\"\n  SETUP_WARNING_TFTD: \"X-COM 2 no s'ha trobat dins la carpeta. ${GAME_NAME} necessita una instal·lació valida de X-COM per funcionar. Continuar?\"\n  SETUP_WARNING_XCU: \"XcomUtil detectat. ${GAME_NAME} es incompatible amb XcomUtil i pot no funcionar correctament. Continuar?\"\n  SETUP_ERROR_PORTABLE: \"La carpeta d'instalació no es pot moure\"\n"
  },
  {
    "path": "install/win/Language/cs.yml",
    "content": "cs:\n  SETUP_XCOM_FOLDER_TITLE: \"Vyberte umístění X-COM\"\n  SETUP_XCOM_FOLDER_SUBTITLE: \"Vyberte složky, kde máte nainstalovaný X-COM.\"\n  SETUP_XCOM_FOLDER: \"${GAME_NAME} ${GAME_VERSION} vyžaduje kopii jedné z následujících her X-COM. Tento krok můžete přeskočit, pokud upgradujete již existující instalaci.$\\n$\\nSetup zkopíruje potřebné soubory z následujících složek. Chcete-li vybrat jinou složku, klikněte na ... a vyberte ji. Kliknutím na Další budete pokračovat.\"\n  SETUP_UFO_FOLDER: \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n  SETUP_TFTD_FOLDER: \"X-COM: Terror From The Deep\"\n  SETUP_GAME: \"Herní soubory\"\n  SETUP_GAME_DESC: \"Soubory potřebné ke spuštění ${GAME_NAME}.\"\n  SETUP_PORTABLE: \"Přenositelná instalace\"\n  SETUP_PORTABLE_DESC: \"${GAME_NAME} bude ukládat uživatelská data do složky instalace. Uživatel musí mít na tuto složku právo zápisu.\"\n  SETUP_DESKTOP: \"Zástupce na ploše\"\n  SETUP_DESKTOP_DESC: \"Vytvoří zástupce na ploše, který umožní spustit ${GAME_NAME}.\"\n  SETUP_UNDATA: \"Vymazat data X-COM\"\n  SETUP_UNDATA_DESC: \"Smaže všechna data ${GAME_NAME} včetně X-COM zdrojových souborů. Doporučeno, pokud provádíte čistou instalaci.\"\n  SETUP_UNUSER: \"Vymazat data uživatele\"\n  SETUP_UNUSER_DESC: \"Smaže všechna data ${GAME_NAME} vytvořená uživatelem, včetně modů, uložených her a nastavení. Použijte pouze při kompletní přeinstalaci.\"\n  SETUP_SHORTCUT_CHANGELOG: \"Changelog\"\n  SETUP_SHORTCUT_README: \"Přečti si\"\n  SETUP_SHORTCUT_USER: \"Složka uživatele\"\n  SETUP_SHORTCUT_UNINSTALL: \"Odinstalovat\"\n  SETUP_WARNING_UFO: \"X-COM 1 nebylo nalezeno v zadané složce. ${GAME_NAME} ke spuštění potřebuje úplnou instalaci X-COM. Pokračovat?\"\n  SETUP_WARNING_TFTD: \"X-COM 2 nebylo nalezeno v zadané složce. ${GAME_NAME} ke spuštění potřebuje úplnou instalaci X-COM. Pokračovat?\"\n  SETUP_WARNING_XCU: \"Detekováno rozšíření XcomUtil. ${GAME_NAME} je s XcomUtil nekompatibilní a nemusí pracovat správně. Pokračovat?\"\n  SETUP_ERROR_PORTABLE: \"Instalační složka není přenositelná.\"\n"
  },
  {
    "path": "install/win/Language/da.yml",
    "content": "da:\n  SETUP_XCOM_FOLDER_TITLE: \"Vælg X-COM-placering\"\n  SETUP_XCOM_FOLDER_SUBTITLE: \"Vælg mapperne hvor du har X-COM installeret.\"\n  SETUP_XCOM_FOLDER: \"${GAME_NAME} ${GAME_VERSION} kræver en kopi af et af de følgende X-COM-spil. Du kan udelade dette trin, hvis du opgraderer en eksisterende installation.$\\n$\\nInstallationen vil kopiere de krævede filer fra de følgende mapper. For at kopiere fra en anden mappe, klik ... og vælg en anden mappe. Klik næste for at fortsætte.\"\n  SETUP_UFO_FOLDER: \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n  SETUP_TFTD_FOLDER: \"X-COM: Terror From The Deep\"\n  SETUP_GAME: \"Spilfiler\"\n  SETUP_GAME_DESC: \"Filer krævet for at afvikle ${GAME_NAME}.\"\n  SETUP_PORTABLE: \"Flytbar installation\"\n  SETUP_PORTABLE_DESC: \"${GAME_NAME} vil lagre brugerdata i installationsmappen. Der skal kunne skrives til mappen af brugeren.\"\n  SETUP_DESKTOP: \"Skrivebordsgenvej\"\n  SETUP_DESKTOP_DESC: \"Opretter en genvej på skrivebordet til at spille ${GAME_NAME}.\"\n  SETUP_UNDATA: \"Slet X-COM-data\"\n  SETUP_UNDATA_DESC: \"Sletter alle ${GAME_NAME}-installationsdata, inklusive X-COM-ressourcer. Anbefalet for en ren geninstallation.\"\n  SETUP_UNUSER: \"Slet brugerdata\"\n  SETUP_UNUSER_DESC: \"Sletter alla ${GAME_NAME}-brugerdata, inklusive mod'er, gemte spil, skærmbilleder og indstillinger. Brug kun denne for en fuldstændig sletning.\"\n  SETUP_SHORTCUT_CHANGELOG: \"Ændringslog\"\n  SETUP_SHORTCUT_README: \"Læsmig\"\n  SETUP_SHORTCUT_USER: \"Brugermappe\"\n  SETUP_SHORTCUT_UNINSTALL: \"Afinstaller\"\n  SETUP_WARNING_UFO: \"X-COM 1 blev ikke fundet i mappen. ${GAME_NAME} kræver en gyldig installation af X-COM for at blive afviklet. Fortsæt?\"\n  SETUP_WARNING_TFTD: \"X-COM 2 blev ikke fundet i mappen. ${GAME_NAME} kræver en gyldig installation af X-COM for at blive afviklet. Fortsæt?\"\n  SETUP_WARNING_XCU: \"XcomUtil detekteret. ${GAME_NAME} er ikke kompatibel med XcomUtil og fungerer måske ikke korrekt. Ønsker du at fortsætte?\"\n  SETUP_ERROR_PORTABLE: \"Installationsmappen understøtter ikke flytbar installation.\"\n"
  },
  {
    "path": "install/win/Language/de.yml",
    "content": "de:\n  SETUP_XCOM_FOLDER_TITLE: \"X-COM Standort auswählen\"\n  SETUP_XCOM_FOLDER_SUBTITLE: \"Wählen Sie den Ordner, in dem Sie X-COM installiert haben.\"\n  SETUP_XCOM_FOLDER: \"${GAME_NAME} ${GAME_VERSION} benötigt eines der folgenden X-COM Spiele. Falls diese Installation als Upgrade für eine bestehende Installation ausgeführt wird kann dieser Schritt übersprungen werden.$\\n$\\n$\\nSetup wird die benötigten Dateien aus den folgenden Ordnern kopieren. Um die Dateien aus einem anderen Ordner heraus zu kopieren bitte ... anklicken und den Ordner auswählen. Klicke auf 'Weiter' um fortzufahren. \"\n  SETUP_UFO_FOLDER: \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n  SETUP_TFTD_FOLDER: \"X-COM: Terror From The Deep\"\n  SETUP_GAME: \"Spieledateien\"\n  SETUP_GAME_DESC: \"Benötigte ${GAME_NAME}-Dateien.\"\n  SETUP_PORTABLE: \"Portable Installation\"\n  SETUP_PORTABLE_DESC: \"${GAME_NAME} speichert Benutzerdaten im Installationsordner.{NEWLINE}Der Ordner muss vom Anwender beschreibbar sein.\"\n  SETUP_DESKTOP: \"Verknüpfung auf dem Desktop\"\n  SETUP_DESKTOP_DESC: \"Erstellt eine ${GAME_NAME}-Verknüpfung auf dem Desktop.\"\n  SETUP_UNDATA: \"X-COM Daten Löschen\"\n  SETUP_UNDATA_DESC: \"Löscht alle ${GAME_NAME} Installationsdaten, einschließlich X-COM-Ressourcen. Empfohlen für eine saubere Neuinstallation.\"\n  SETUP_UNUSER: \"Lösche Benutzerdaten\"\n  SETUP_UNUSER_DESC: \"Löscht alle ${GAME_NAME} Benutzerdaten, einschließlich mods, Savegames, Screenshots und Optionen.\"\n  SETUP_SHORTCUT_CHANGELOG: \"Changelog\"\n  SETUP_SHORTCUT_README: \"Liesmich\"\n  SETUP_SHORTCUT_USER: \"Benutzerverzeichnis\"\n  SETUP_SHORTCUT_UNINSTALL: \"Deinstallieren\"\n  SETUP_WARNING_UFO: \"X-COM 1 wurde im angegebenen Ordner nicht gefunden. ${GAME_NAME} benötigt eine gültige Installation von X-COM 1 um Starten zu können. Dennoch fortfahren?\"\n  SETUP_WARNING_TFTD: \"X-COM 2 wurde im angegebenen Ordner nicht gefunden. ${GAME_NAME} benötigt eine gültige Installation von X-COM 2 um Starten zu können. Dennoch fortfahren?\"\n  SETUP_WARNING_XCU: \"XcomUtil wurde erkannt. ${GAME_NAME} ist mit XcomUtil nicht kompatibel und könnte nicht richtig funktionieren. Dennoch fortfahren?\"\n  SETUP_ERROR_PORTABLE: \"Der Installationsordner ist nicht portabel.\"\n"
  },
  {
    "path": "install/win/Language/el.yml",
    "content": "el:\n  SETUP_XCOM_FOLDER_TITLE: \"Επιλέξτε θέση για εγκατάσταση του X-COM\"\n  SETUP_XCOM_FOLDER_SUBTITLE: \"Διαλέξτε τον φάκελο που έχετε εγκαταστημένο το X-COM.\"\n  SETUP_XCOM_FOLDER: \"${GAME_NAME} ${GAME_VERSION} χρειάζεται μία κόπια ενός από τα ακόλουθα X-COM παιχνίδια. Μπορείτε να παραλήψετε αυτό το βήμα αν κάνετε αναβάθμηση της τρέχουσας εγκατάστατης..$\\n$\\nΗ εγκατάσταση θα αντιγράψει τα απετούμετα αρχεία από τους φακέλους που ακολουθούν. Για να αντιγράψετε απο διαφορετικό φάκελο, πατήστε ... και διαλέξτε διαφορετκό φάκελο. Πατήστε επόμενο για να συνεχίσετε.\"\n  SETUP_UFO_FOLDER: \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n  SETUP_TFTD_FOLDER: \"X-COM: Terror From The Deep\"\n  SETUP_GAME: \"Αρχεία από Παιχνίδι\"\n  SETUP_GAME_DESC: \"Αρχεία που απαιτούνται για την εκτέλεση του ${GAME_NAME}.\"\n  SETUP_PORTABLE: \"Φορητή Εγκατάσταση\"\n  SETUP_PORTABLE_DESC: \"Το ${GAME_NAME} θα αποθηκεύσει τα δεδομένα χρήστη στο φάκελο εγκατάστασης. Ο φάκελος πρέπει να μπορεί να εγγραφεί από τον χρήστη.\"\n  SETUP_DESKTOP: \"Συντόμευση Επιφάνειας Εργασίας\"\n  SETUP_DESKTOP_DESC: \"Δημιουργεί μια συντόμευση στην επιφάνεια εργασίας για να παίξετε ${GAME_NAME}.\"\n  SETUP_UNDATA: \"Διαγραφή Δεδομένων X-COM\"\n  SETUP_UNDATA_DESC: \"Διαγράφει όλα τα δεδομένα εγκατάστασης του ${GAME_NAME}, συμπεριλαμβανομένων των πόρων του X-COM. Συνιστάται για καθαρή επανεγκατάσταση.\"\n  SETUP_UNUSER: \"Διαγραφή Dεδομένων Xρήστη\"\n  SETUP_UNUSER_DESC: \"Διαγράφει όλα τα δεδομένα χρήστη ${GAME_NAME}, συμπεριλαμβανομένων των mods, savegames, στιγμιότυπων οθόνης και επιλογών. Χρησιμοποιήστε το μόνο για μία πλήρες διαγραφή.\"\n  SETUP_SHORTCUT_CHANGELOG: \"Καταγραφή αλλαγών\"\n  SETUP_SHORTCUT_README: \"Διαβασέ με\"\n  SETUP_SHORTCUT_USER: \"Φάκελος Xρήστη\"\n  SETUP_SHORTCUT_UNINSTALL: \"Απεγκατάσταση\"\n  SETUP_WARNING_UFO: \"Το X-COM 1 δεν βρέθηκε στο φάκελο. Το ${GAME_NAME} απαιτεί έγκυρη εγκατάσταση του X-COM για να εκτελεστεί. Θέλετε να συνεχίσετε?\"\n  SETUP_WARNING_TFTD: \"Το X-COM 2 δεν βρέθηκε στο φάκελο. Το ${GAME_NAME} απαιτεί έγκυρη εγκατάσταση του X-COM για να εκτελεστεί. Θέλετε να συνεχίσετε?\"\n  SETUP_WARNING_XCU: \"Το XcomUtil εντοπίστηκε. Το ${GAME_NAME} δεν είναι συμβατό με το XcomUtil και ενδέχεται να μην λειτουργεί σωστά. Θέλετε να συνεχίσετε?\"\n  SETUP_ERROR_PORTABLE: \"Ο φάκελος εγκατάστασης δεν είναι φορητός.\"\n"
  },
  {
    "path": "install/win/Language/en-US.yml",
    "content": "en-US:\n  SETUP_XCOM_FOLDER_TITLE: \"Choose X-COM Location\"\n  SETUP_XCOM_FOLDER_SUBTITLE: \"Choose the folders where you have X-COM installed.\"\n  SETUP_XCOM_FOLDER: \"${GAME_NAME} ${GAME_VERSION} requires a copy of one of the following X-COM games. You can skip this step if you're upgrading an existing installation.$\\n$\\nSetup will copy the required files from the following folders. To copy from a different folder, click ... and select another folder. Click Next to continue.\"\n  SETUP_UFO_FOLDER: \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n  SETUP_TFTD_FOLDER: \"X-COM: Terror From The Deep\"\n  SETUP_GAME: \"Game Files\"\n  SETUP_GAME_DESC: \"Files required to run ${GAME_NAME}.\"\n  SETUP_PORTABLE: \"Portable Installation\"\n  SETUP_PORTABLE_DESC: \"${GAME_NAME} will store user data in the installation folder. The folder must be user-writable.\"\n  SETUP_DESKTOP: \"Desktop Shortcut\"\n  SETUP_DESKTOP_DESC: \"Creates a shortcut in the desktop to play ${GAME_NAME}.\"\n  SETUP_UNDATA: \"Delete X-COM Data\"\n  SETUP_UNDATA_DESC: \"Deletes all ${GAME_NAME} install data, including X-COM resources. Recommended for a clean reinstall.\"\n  SETUP_UNUSER: \"Delete User Data\"\n  SETUP_UNUSER_DESC: \"Deletes all ${GAME_NAME} user data, including mods, savegames, screenshots and options. Only use this for a complete wipe.\"\n  SETUP_SHORTCUT_CHANGELOG: \"Changelog\"\n  SETUP_SHORTCUT_README: \"Readme\"\n  SETUP_SHORTCUT_USER: \"User Folder\"\n  SETUP_SHORTCUT_UNINSTALL: \"Uninstall\"\n  SETUP_WARNING_UFO: \"X-COM 1 wasn't found in the folder. ${GAME_NAME} requires a valid installation of X-COM to run. Continue?\"\n  SETUP_WARNING_TFTD: \"X-COM 2 wasn't found in the folder. ${GAME_NAME} requires a valid installation of X-COM to run. Continue?\"\n  SETUP_WARNING_XCU: \"XcomUtil detected. ${GAME_NAME} is incompatible with XcomUtil and may not work correctly. Continue?\"\n  SETUP_ERROR_PORTABLE: \"Installation folder is not portable.\""
  },
  {
    "path": "install/win/Language/es-419.yml",
    "content": "es-419:\n  SETUP_XCOM_FOLDER_TITLE: \"Elija ubicación de X-COM \"\n  SETUP_XCOM_FOLDER_SUBTITLE: \"Elija los archivos donde tienes X-COM instalado.\"\n  SETUP_XCOM_FOLDER: \"${GAME_NAME} ${GAME_VERSION} requiere una copia de uno de los siguientes juegos de X-COM. Puede omitir este paso si va a actualizar una instalación existente. $\\n$\\nEl programa de instalación copiará los archivos necesarios de las siguientes carpetas. Para copiar desde una carpeta diferente, presione... y seleccione otra carpeta. Presione en Siguiente para continuar.\"\n  SETUP_UFO_FOLDER: \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n  SETUP_TFTD_FOLDER: \"X-COM: Terror From The Deep\"\n  SETUP_GAME: \"Archivos del Juego\"\n  SETUP_GAME_DESC: \"Archivos necesarios para ejecutar ${GAME_NAME}.\"\n  SETUP_PORTABLE: \"Instalación Portable\"\n  SETUP_PORTABLE_DESC: \"${GAME_NAME} guardara data de usuario en el folder de instalación. Este folder debe poder ser escribible por el usuario\"\n  SETUP_DESKTOP: \"Acceso Directo del Escritorio\"\n  SETUP_DESKTOP_DESC: \"Crea un acceso directo en el escritorio para jugar ${GAME_NAME}.\"\n  SETUP_UNDATA: \"Eliminar Datos de X-COM\"\n  SETUP_UNDATA_DESC: \"Borata toda la data de instalación de ${GAME_NAME}, incluyendo recursos X-Com. Recomendado para una reinstalación limpia\"\n  SETUP_UNUSER: \"Eliminar Datos del Usuario\"\n  SETUP_UNUSER_DESC: \"Elimina todos los datos de usuario de ${GAME_NAME}, incluyendo mods, partidas guardadas, capturas de pantalla y opciones. Sólo la usamos para una limpieza completa.\"\n  SETUP_SHORTCUT_CHANGELOG: \"Historial de Cambios\"\n  SETUP_SHORTCUT_README: \"Léeme\"\n  SETUP_SHORTCUT_USER: \"Carpeta de Usuario\"\n  SETUP_SHORTCUT_UNINSTALL: \"Desinstalar\"\n  SETUP_WARNING_UFO: \"X-COM 1 no se encontró en la carpeta. ${GAME_NAME} requiere una instalación válida de X-COM para funcionar. Continuar?\"\n  SETUP_WARNING_TFTD: \"X-COM 2 no se encontró en la carpeta. ${GAME_NAME} requiere una instalación válida de X-COM para funcionar. Continuar?\"\n  SETUP_WARNING_XCU: \"XcomUtil detectado. ${GAME_NAME} es incompatible con XcomUtil y podría no funcionar correctamente. ¿Continuar?\"\n  SETUP_ERROR_PORTABLE: \"La carpeta de instalación no es portátil.\"\n"
  },
  {
    "path": "install/win/Language/es-ES.yml",
    "content": "es-ES:\n  SETUP_XCOM_FOLDER_TITLE: \"Elige ubicación de X-COM\"\n  SETUP_XCOM_FOLDER_SUBTITLE: \"Elige la carpeta donde tienes X-COM instalado.\"\n  SETUP_XCOM_FOLDER: \"${GAME_NAME} ${GAME_VERSION} requiere una copia de uno de los siguientes juegos de X-COM. Puede omitir este paso si va a actualizar una instalación existente.$\\n$\\nEl programa de instalación copiará los archivos necesarios de las siguientes carpetas. Para copiar desde una carpeta diferente, haga clic... y seleccione otra carpeta. Haga clic en Siguiente para continuar.\"\n  SETUP_UFO_FOLDER: \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n  SETUP_TFTD_FOLDER: \"X-COM: Terror From The Deep\"\n  SETUP_GAME: \"Archivos del juego\"\n  SETUP_GAME_DESC: \"Archivos necesarios para ejecutar ${GAME_NAME}.\"\n  SETUP_PORTABLE: \"Instalación portable\"\n  SETUP_PORTABLE_DESC: \"${GAME_NAME} guardará los datos de usuario en la carpeta de instalación. Asegúrate que la carpeta pueda ser escrita por el usuario.\"\n  SETUP_DESKTOP: \"Acceso Directo en el Escritorio\"\n  SETUP_DESKTOP_DESC: \"Crea un acceso directo en el escritorio para jugar ${GAME_NAME}.\"\n  SETUP_UNDATA: \"Eliminar Datos de X-COM\"\n  SETUP_UNDATA_DESC: \"Elimina todos los datos en la carpeta de instalación ${GAME_NAME}, incluyendo los archivos de X-COM. Acción recomendada para una instalación limpia.\"\n  SETUP_UNUSER: \"Eliminar Datos del Usuario\"\n  SETUP_UNUSER_DESC: \"Elimina todos los datos de usuario de ${GAME_NAME}, incluyendo mods, partidas guardadas, capturas de pantalla y opciones. Sólo la usamos para una limpieza completa.\"\n  SETUP_SHORTCUT_CHANGELOG: \"Historial \"\n  SETUP_SHORTCUT_README: \"Léeme\"\n  SETUP_SHORTCUT_USER: \"Carpeta de usuario\"\n  SETUP_SHORTCUT_UNINSTALL: \"Desinstalar\"\n  SETUP_WARNING_UFO: \"X-COM 1 no se encontró en la carpeta. ${GAME_NAME} requiere una instalación válida de X-COM para funcionar. Continuar?\"\n  SETUP_WARNING_TFTD: \"X-COM 2 no se encontró en la carpeta. ${GAME_NAME} requiere una instalación válida de X-COM para funcionar. Continuar?\"\n  SETUP_WARNING_XCU: \"XcomUtil detectado. ${GAME_NAME} es incompatible con XcomUtil y podría no funcionar correctamente. Continuar?\"\n  SETUP_ERROR_PORTABLE: \"La carpeta de instalación no es portátil.\"\n"
  },
  {
    "path": "install/win/Language/et.yml",
    "content": "et:\n  SETUP_XCOM_FOLDER_TITLE: \"Vali X-COMi asukoht\"\n  SETUP_XCOM_FOLDER_SUBTITLE: \"Vali kataloogid kuhu oled X-COMi installinud.\"\n  SETUP_XCOM_FOLDER: \"${GAME_NAME} ${GAME_VERSION} vajab ühte järgnevatest X-COMi mängudest. Võid loobuda sellest osast kui uuendad eksisteerivat installatsiooni.$\\n$\\nSetup kopeerib vajalikud failid järgnevaist kataloogidest. Et kopeerida teisest kataloogist, vajuta ... ja vali teine kataloog. Vajuta Järgmine jätkamiseks.\"\n  SETUP_UFO_FOLDER: \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n  SETUP_TFTD_FOLDER: \"X-COM: Terror From The Deep\"\n  SETUP_GAME: \"Mängu failid\"\n  SETUP_GAME_DESC: \"Failid mida on vaja mängu jooksutamiseks ${GAME_NAME}.\"\n  SETUP_PORTABLE: \"Teisaldatav installatsioon\"\n  SETUP_PORTABLE_DESC: \"${GAME_NAME} salvestab kasutaja andmed installikataloogi. Kataloog ei tohi olla kirjutuskaitstud.\"\n  SETUP_DESKTOP: \"Otsetee desktopile \"\n  SETUP_DESKTOP_DESC: \"Teeb desktopile otsetee ${GAME_NAME}st.\"\n  SETUP_UNDATA: \"Kustuta X-COM.\"\n  SETUP_UNDATA_DESC: \"Kustutab kõik ${GAME_NAME} failid, kaasaarvatud X-COMi ressursid. Soovitatav puhta reinstalli jaoks.\"\n  SETUP_UNUSER: \"Kustuta kasutaja andmed.\"\n  SETUP_UNUSER_DESC: \"Kustutab kõik ${GAME_NAME} kasutaja andmed, kaasaarvatud modid, salvestused, pildid ja valikud. Kasuta seda ainult täielikuks mängu eemaldamiseks.\"\n  SETUP_SHORTCUT_CHANGELOG: \"Muutused.\"\n  SETUP_SHORTCUT_README: \"LoeMind\"\n  SETUP_SHORTCUT_USER: \"User Folder\"\n  SETUP_SHORTCUT_UNINSTALL: \"Uninstalli\"\n  SETUP_WARNING_UFO: \"X-COM 1 puudub kataloogist. ${GAME_NAME} vajab töötamiseks originaal X-COMi. Jätka?\"\n  SETUP_WARNING_TFTD: \"X-COM 2 puudub kataloogist. ${GAME_NAME} vajab töötamiseks originaal X-COMi. Jätka?\"\n  SETUP_WARNING_XCU: \"XcomUtil leitud. ${GAME_NAME} ei ühildu XcomUtiliga ning ei pruugi korrektselt töödata. Jätka?\"\n  SETUP_ERROR_PORTABLE: \"Installikaust ei toeta kaasaskantavat installimist.\"\n"
  },
  {
    "path": "install/win/Language/fi.yml",
    "content": "fi:\n  SETUP_XCOM_FOLDER_TITLE: \"Määritä X-COM:n sijainti\"\n  SETUP_XCOM_FOLDER_SUBTITLE: \"Määritä kansiot, joihin X-COM on asennettu.\"\n  SETUP_XCOM_FOLDER: \"${GAME_NAME} ${GAME_VERSION} edellyttää alkuperäiskappaleen omistamista yhdestä seuraavista X-COM-peleistä. Voit ohittaa tämän vaiheen, jos olet päivittämässä aiempaa asennusta.$\\n$\\nAsennus kopioi tarvittavat tiedostot seuraavista kansioista. Kopioidaksesi toisesta kansiosta napsauta ... ja valitse toinen kansio. Napsauta Seuraava jatkaaksesi.\"\n  SETUP_UFO_FOLDER: \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n  SETUP_TFTD_FOLDER: \"X-COM: Terror From The Deep\"\n  SETUP_GAME: \"Pelin tiedostot\"\n  SETUP_GAME_DESC: \"Tarvittavat tiedostot ohjelman ${GAME_NAME} ajamiseksi.\"\n  SETUP_PORTABLE: \"Siirrettävä asennus\"\n  SETUP_PORTABLE_DESC: \"${GAME_NAME} tallentaa käyttäjätiedot asennuskansioon. Käyttäjällä on oltava kansioon kirjoitusoikeus.\"\n  SETUP_DESKTOP: \"Työpöydän pikakuvake\"\n  SETUP_DESKTOP_DESC: \"Luo työpöydälle pikakuvakkeen pelin ${GAME_NAME} pelaamiseksi.\"\n  SETUP_UNDATA: \"Poista X-COM:n tiedot\"\n  SETUP_UNDATA_DESC: \"Poistaa kaikki pelin ${GAME_NAME} asennustiedot, mukaan lukien X-COM-resurssit. Suositellaan puhtaan uudelleenasennuksen yhteydessä.\"\n  SETUP_UNUSER: \"Poista käyttäjätiedot\"\n  SETUP_UNUSER_DESC: \"Poistaa kaikki pelin ${GAME_NAME} käyttäjätiedot, mukaan lukien modit, tallennetut pelit, kuvakaappaukset ja asetukset. Käytä tätä vaihtoehtoa ainoastaan täydellisen poiston yhteydessä.\"\n  SETUP_SHORTCUT_CHANGELOG: \"Muutosloki\"\n  SETUP_SHORTCUT_README: \"Lueminut\"\n  SETUP_SHORTCUT_USER: \"Käyttäjäkansio\"\n  SETUP_SHORTCUT_UNINSTALL: \"Poista\"\n  SETUP_WARNING_UFO: \"X-COM 1 ei löytynyt kansiosta. ${GAME_NAME} vaatii kelvollisen asennuksen X-COM:sta toimiakseen. Jatketaanko?\"\n  SETUP_WARNING_TFTD: \"X-COM 2 ei löytynyt kansiosta. ${GAME_NAME} vaatii kelvollisen asennuksen X-COM:sta toimiakseen. Jatketaanko?\"\n  SETUP_WARNING_XCU: \"XcomUtil havaittu. ${GAME_NAME} ei ole yhteensopiva XcomUtilin kanssa eikä välttämättä toimi oikein. Jatketaanko?\"\n  SETUP_ERROR_PORTABLE: \"Asennuskansio ei tue siirrettävää asennusta.\"\n"
  },
  {
    "path": "install/win/Language/fr.yml",
    "content": "fr:\n  SETUP_XCOM_FOLDER_TITLE: \"Choisissez l'emplacement X-COM\"\n  SETUP_XCOM_FOLDER_SUBTITLE: \"Choisissez le dossier d'installation de X-COM. \"\n  SETUP_XCOM_FOLDER: \"${GAME_NAME} ${GAME_VERSION} requiert une copie de l'un des jeux X-COM suivants. Vous pouvez sauter cette étape si vous mettez à jour une installation existante.$\\n$\\nL'installation va copier les fichiers requis depuis les dossiers suivants. Pour copier depuis un dossier différent, cliquez sur ... et sélectionnez un autre dossier. Cliquez sur Suivant pour continuer.\"\n  SETUP_UFO_FOLDER: \"UFO : Enemy Unknown / X-COM : UFO Defense\"\n  SETUP_TFTD_FOLDER: \"X-COM : Terror From The Deep\"\n  SETUP_GAME: \"Fichiers du jeu\"\n  SETUP_GAME_DESC: \"Fichiers requis pour lancer ${GAME_NAME}.\"\n  SETUP_PORTABLE: \"Installation portable\"\n  SETUP_PORTABLE_DESC: \"${GAME_NAME} stockera les données d'utilisateur dans le dossier d'installation. Le dossier doit être modifiable.\"\n  SETUP_DESKTOP: \"Raccourci sur le bureau\"\n  SETUP_DESKTOP_DESC: \"Crée un raccourci sur le bureau pour lancer ${GAME_NAME}.\"\n  SETUP_UNDATA: \"Détruit les données X-COM\"\n  SETUP_UNDATA_DESC: \"Supprime toutes les données d'installation ${GAME_NAME} , y compris les ressources d'X-Com. Recommandé pour une réinstallation complète.\"\n  SETUP_UNUSER: \"Effacer les données utilisateur\"\n  SETUP_UNUSER_DESC: \"Effacer toutes les données utilisateur ${GAME_NAME}, y-compris les mods, parties sauvées, captures d'écrans et options. Utiliser uniquement pour une suppression complète.\"\n  SETUP_SHORTCUT_CHANGELOG: \"Journal des changements\"\n  SETUP_SHORTCUT_README: \"Lisez-moi\"\n  SETUP_SHORTCUT_USER: \"Dossier utilisateur\"\n  SETUP_SHORTCUT_UNINSTALL: \"Désinstaller\"\n  SETUP_WARNING_UFO: \"X-COM 1 n'a pas été trouvé dans le dossier. ${GAME_NAME} requiert une installation valide de X-COM pour s'exécuter. Continuer ?\"\n  SETUP_WARNING_TFTD: \"X-COM 2 n'a pas été trouvé dans le dossier. ${GAME_NAME} requiert une installation valide de X-COM pour s'exécuter. Continuer ?\"\n  SETUP_WARNING_XCU: \"XcomUtil détecté. ${GAME_NAME} est incompatible avec XcomUtil et ne devrait pas fonctionner correctement. Continuer ?\"\n  SETUP_ERROR_PORTABLE: \"Le dossier d'installation n'est pas portable.\"\n"
  },
  {
    "path": "install/win/Language/hr.yml",
    "content": "hr:\n  SETUP_XCOM_FOLDER_TITLE: \"Izaberi X-COM Lokaciju\"\n  SETUP_XCOM_FOLDER_SUBTITLE: \"Izaberi mapu gdje je instaliran X-COM\"\n  SETUP_XCOM_FOLDER: \"${GAME_NAME} ${GAME_VERSION} zahtijeva kopiju od jedne od slijedećih X-COM igara. Možeš preskočiti ovaj korak ako nadograđuješ postojeću instalaciju igre.$\\n$\\nPodešavanje će kopirati potrebne datoteke sa slijedećih mapa. Za kopiranje iz drugačije mape, klikni ... i obilježi drugu mapu. Klikni Dalje za nastavak\"\n  SETUP_UFO_FOLDER: \"NLO: Neprijatelj Nepoznat / X-COM: NLO Obrana\"\n  SETUP_TFTD_FOLDER: \"X-COM: Teror Iz Dubina\"\n  SETUP_GAME: \"Datoteke Igre\"\n  SETUP_GAME_DESC: \"Datoteke nužne za pokretanje ${GAME_NAME}.\"\n  SETUP_PORTABLE: \"Prijenosna Instalacija\"\n  SETUP_PORTABLE_DESC: \"${GAME_NAME} će pohraniti korisničke podatke u instalacijsku mapu. Mapa mora imati omogućeno zapisivanje od strane korisnika.\"\n  SETUP_DESKTOP: \"Prečac za Radnu površinu\"\n  SETUP_DESKTOP_DESC: \"Stvara prečac za igranje na radnoj površini ${GAME_NAME}.\"\n  SETUP_UNDATA: \"Izbriši X-COM Podatke\"\n  SETUP_UNDATA_DESC: \"Briše sve ${GAME_NAME} instalacijske podatke, uključujući X-COM resurse. Preporuča se za čistu ponovnu instalaciju.\"\n  SETUP_UNUSER: \"Pobriši Korisničke Podatke\"\n  SETUP_UNUSER_DESC: \"Briše sve ${GAME_NAME} korisničke podatke, uključujući modifikacije, spremljene igre, snimke zaslona i opcije. Koristite ovo samo za potpuno brisanje.\"\n  SETUP_SHORTCUT_CHANGELOG: \"Dnevnik promjena\"\n  SETUP_SHORTCUT_README: \"PročitajMe\"\n  SETUP_SHORTCUT_USER: \"Korisnička Mapa\"\n  SETUP_SHORTCUT_UNINSTALL: \"Deinstaliraj\"\n  SETUP_WARNING_UFO: \"X-COM 1 nije pronađen u mapi. ${GAME_NAME} zahtijeva važeću instalaciju X-COM za pokretanje. Nastaviti?\"\n  SETUP_WARNING_TFTD: \"X-COM 2 nije pronađen u mapi. ${GAME_NAME} zahtijeva važeću instalaciju X-COM za pokretanje. Nastaviti?\"\n  SETUP_WARNING_XCU: \"XcomUtil otkriven. ${GAME_NAME} nije kompatibilna s XcomUtilom i možda neće raditi ispravno. Nastaviti?\"\n  SETUP_ERROR_PORTABLE: \"Instalacijska mapa ne podržava prijenosnu instalaciju.\"\n"
  },
  {
    "path": "install/win/Language/hu.yml",
    "content": "hu:\n  SETUP_XCOM_FOLDER_TITLE: \"Válaszd ki az X-COM helyét\"\n  SETUP_XCOM_FOLDER_SUBTITLE: \"Válaszd ki a mappát/mappákat, ahová telepítetted az X-COM-ot.\"\n  SETUP_XCOM_FOLDER: \"${GAME_NAME} ${GAME_VERSION} -nak szüksége van egy másolatra a soron következő valamelyik X-COM játékok közül. Átugorhatod ezt a lépést, ha már egy meglévő telepítést frissítesz.$\\n$\\nA telepítő másolni fogja a szükséges fájlokat a következő mappából/mappákból. Ahhoz, hogy másik mappából másoljon, kattints a ... -ra és válassz egy másik mappát. Kattints a Következő gombra a folytatáshoz.\"\n  SETUP_UFO_FOLDER: \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n  SETUP_TFTD_FOLDER: \"X-COM: Terror From The Deep\"\n  SETUP_GAME: \"Játék Fájlok\"\n  SETUP_GAME_DESC: \"Fájlok szükségesek az ${GAME_NAME} futtatásához.\"\n  SETUP_PORTABLE: \"Hordozható Verzió\"\n  SETUP_PORTABLE_DESC: \"Az ${GAME_NAME} az adatokat a telepítési mappában fogja tárolni. A mappának a felhasználó által írhatónak kell lennie.\"\n  SETUP_DESKTOP: \"Asztali Parancsikon\"\n  SETUP_DESKTOP_DESC: \"Egy parancsikont hoz létre az asztalon, ahhoz, hogy következő játékkal játszani tudj: ${GAME_NAME}.\"\n  SETUP_UNDATA: \"X-COM Adatainak Törlése.\"\n  SETUP_UNDATA_DESC: \"Törli az ${GAME_NAME} összes telepítési adatát, beleértve az X-COM adatokat. Ajánlott egy tiszta újratelepítéshez.\"\n  SETUP_UNUSER: \"Felhasználói Adatok Törlése\"\n  SETUP_UNUSER_DESC: \"Törli az ${GAME_NAME} összes felhasználói adatát, beleértve a mod-okat, mentett játékállásokat, képernyőmentéseket és beállításokat. Csak teljes törlésre használd!\"\n  SETUP_SHORTCUT_CHANGELOG: \"Változásnapló \"\n  SETUP_SHORTCUT_README: \"Olvass el!\"\n  SETUP_SHORTCUT_USER: \"Felhasználó Mappa\"\n  SETUP_SHORTCUT_UNINSTALL: \"Törlés\"\n  SETUP_WARNING_UFO: \"Az X-COM 1 nem található a mappában. Az ${GAME_NAME}-nak szüksége van egy érvényes/működő X-COM telepítésre a futtatáshoz. Folytatod?\"\n  SETUP_WARNING_TFTD: \"Az X-COM 2 nem található a mappában. Az ${GAME_NAME}-nak szüksége van egy érvényes/működő X-COM telepítésre a futtatáshoz. Folytatod?\"\n  SETUP_WARNING_XCU: \"XcomUtil észlelve. Az ${GAME_NAME} NEM kompatibilis az XcomUtil-lal és előfordulhat, hogy nem fog megfelelően működni. Folytatod?\"\n  SETUP_ERROR_PORTABLE: \"A telepítési mappa nem támogatja a hordozható telepítést.\"\n"
  },
  {
    "path": "install/win/Language/is.yml",
    "content": "is:\n  SETUP_XCOM_FOLDER_TITLE: \"Veldu X-COM staðsetningu\"\n  SETUP_XCOM_FOLDER_SUBTITLE: \"Veldu möppuna þar sem þú hefur X-COM uppsettan.\"\n  SETUP_XCOM_FOLDER: \"${GAME_NAME} ${GAME_VERSION} þarf eintak af einum af eftirfarandi X-COM leikjunum. Þú getur sleppt þessu stigi ef þú ert að uppfæra fyrirfram uppsettan leik.$\\n$\\nUppsetninging mun afrita gögn úr eftirfarandi möppum. Til að afrita úr anarri möppu, smelltu á ... og veldu á aðra möppu. Smelltu á Næst til að halda áfram.\"\n  SETUP_UFO_FOLDER: \"FFH: Óþekktur Óvinur/X-COM: FFH Vörn\"\n  SETUP_TFTD_FOLDER: \"X-COM: Ógn Úr Hyldýpinu\"\n  SETUP_GAME: \"Leikja skrár\"\n  SETUP_GAME_DESC: \"Skrár nauðsynlegar til að virkja ${GAME_NAME}.\"\n  SETUP_PORTABLE: \"Færanleg Uppsetning\"\n  SETUP_PORTABLE_DESC: \"${GAME_NAME} mun geyma notendagögn í uppsetri möppu. Mappan verður að vera aðgengileg fyrir breytingum frá notenda.\"\n  SETUP_DESKTOP: \"Flýtileið á Skjáborð\"\n  SETUP_DESKTOP_DESC: \"Býr til flýtileið á skjáborðið til að spila ${GAME_NAME}.\"\n  SETUP_UNDATA: \"Eyða X-COM Gögnum\"\n  SETUP_UNDATA_DESC: \"Eyðir öllum uppsettum gögnum frá ${GAME_NAME}. Mælt með fyrir fulla enduruppsetningu.\"\n  SETUP_UNUSER: \"Eyða Notendagögnum\"\n  SETUP_UNUSER_DESC: \"Eyðir öllum notendagögnum úr ${GAME_NAME}, þar á meðal breytipakka, vistaða leiki, skjáskot og valmöguleika. Notaðu þetta aðeins fyrir algera gagnahreinsun.\"\n  SETUP_SHORTCUT_CHANGELOG: \"Breytingaskrá\"\n  SETUP_SHORTCUT_README: \"Lestumig\"\n  SETUP_SHORTCUT_USER: \"Notendamappa\"\n  SETUP_SHORTCUT_UNINSTALL: \"Fjarlægja Leik\"\n  SETUP_WARNING_UFO: \"X-COM 1 fannst ekki í möppunni. ${GAME_NAME} þarfnast lögmætrar uppsettningar X-COM til að virka. Halda áfram?\"\n  SETUP_WARNING_TFTD: \"X-COM 2 fannst ekki í möppunni. ${GAME_NAME} þarfnast lögmætrar uppsettningar X-COM til að virka. Halda áfram?\"\n  SETUP_WARNING_XCU: \"XcomUtil fannst. ${GAME_NAME} er ósamrýnanlegur XcomUtil og gæti ekki virkað rétt. Halda áfram?\"\n  SETUP_ERROR_PORTABLE: \"Uppsetningarmappan styður ekki færanlega uppsetningu.\"\n"
  },
  {
    "path": "install/win/Language/it.yml",
    "content": "it:\n  SETUP_XCOM_FOLDER_TITLE: \"Seleziona la Posizione di X-COM\"\n  SETUP_XCOM_FOLDER_SUBTITLE: \"Seleziona le cartelle dove è installato X-COM.\"\n  SETUP_XCOM_FOLDER: \"${GAME_NAME} ${GAME_VERSION} richiede una copia di uno dei seguenti giochi di X-COM. Puoi saltare questo passaggio se stai aggiornando un'installazione preesistente.$\\n$\\nL'installazione copierà i file richiesti da queste cartelle. Per copiarli da una cartella diversa, clicca ... e seleziona un'altra cartella. Premi Successivo per continuare.\"\n  SETUP_UFO_FOLDER: \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n  SETUP_TFTD_FOLDER: \"X-COM: Terror From The Deep\"\n  SETUP_GAME: \"File di Gioco\"\n  SETUP_GAME_DESC: \"File richiesti per eseguire ${GAME_NAME}.\"\n  SETUP_PORTABLE: \"Installazione Portatile\"\n  SETUP_PORTABLE_DESC: \"${GAME_NAME} salverà i dati utente nella cartella di installazione. La cartella deve essere scrivibile.\"\n  SETUP_DESKTOP: \"Scorciatoia sul Desktop\"\n  SETUP_DESKTOP_DESC: \"Crea una scorciatoia sul desktop per giocare a ${GAME_NAME}.\"\n  SETUP_UNDATA: \"Cancella dati di X-COM\"\n  SETUP_UNDATA_DESC: \"Cancella tutti ${GAME_NAME} di installazione, incluse le risorse X-COM. Raccomandato per una installazione pulita.\"\n  SETUP_UNUSER: \"Cancella Dati Utente\"\n  SETUP_UNUSER_DESC: \"Cancella tutti i dati utente di ${GAME_NAME}, incluse le mod, i salvataggi, gli screenshot e le opzioni. Utilizza quest'opzione solo per una disinstallazione completa.\"\n  SETUP_SHORTCUT_CHANGELOG: \"Changelog\"\n  SETUP_SHORTCUT_README: \"Leggimi\"\n  SETUP_SHORTCUT_USER: \"Cartella Utente\"\n  SETUP_SHORTCUT_UNINSTALL: \"Disinstalla\"\n  SETUP_WARNING_UFO: \"X-COM 1 non è stato trovato nella cartella. ${GAME_NAME} richiede un'installazione valida di X-COM per funzionare. Continuare?\"\n  SETUP_WARNING_TFTD: \"X-COM 2 non è stato trovato nella cartella. ${GAME_NAME} richiede un'installazione valida di X-COM per funzionare. Continuare?\"\n  SETUP_WARNING_XCU: \"Rilevato XComUtil. ${GAME_NAME} è incompatibile con XComUtil e potrebbe non funzionare correttamente. Continuare?\"\n  SETUP_ERROR_PORTABLE: \"La cartella per l'installazione non è portatile\"\n"
  },
  {
    "path": "install/win/Language/ja.yml",
    "content": "ja:\n  SETUP_XCOM_FOLDER_TITLE: \"XComのインストール場所を選択\"\n  SETUP_XCOM_FOLDER_SUBTITLE: \"X-Comがインストールされている場所を指定してください\"\n  SETUP_XCOM_FOLDER: \"${GAME_NAME}の ${GAME_VERSION} バージョンが必要です。アップデートの場合はこの作業はスキップできます。$\\n$\\nセットアップに必要なファイルをオリジナルのX-Comフォルダからコピーします。他のフォルダからする場合はそれを選んで'次へ'をクリックしてください。\"\n  SETUP_UFO_FOLDER: \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n  SETUP_TFTD_FOLDER: \"X-COM: Terror From The Deep\"\n  SETUP_GAME: \"ゲームのファイル\"\n  SETUP_GAME_DESC: \"${GAME_NAME}.を起動するのに必要なファイル\"\n  SETUP_PORTABLE: \"ポータブル版インストール\"\n  SETUP_PORTABLE_DESC: \"${GAME_NAME} はユーザーのデータをインストール先のフォルダに保持します。フォルダを書き込み可能の状態にしてください。\"\n  SETUP_DESKTOP: \"デスクトップ・ショートカット\"\n  SETUP_DESKTOP_DESC: \"${GAME_NAME}.のデスクトップ・ショートカットを作成します\"\n  SETUP_UNDATA: \"X-COMのデータを消去する\"\n  SETUP_UNDATA_DESC: \"全ての ${GAME_NAME} のインストールデータを消去します。この処理にはオリジナルのX-COMのデータも含まれます。クリーンインストールを行いたい場合に推奨されるオプションです。\"\n  SETUP_UNUSER: \"ユーザーデータの消去\"\n  SETUP_UNUSER_DESC: \"${GAME_NAME}.のセーブデータ、MOD、スクリーンショットやオプション設定をWindowsのユーザーライブラリから消去します\"\n  SETUP_SHORTCUT_CHANGELOG: \"変更点\"\n  SETUP_SHORTCUT_README: \"Readme\"\n  SETUP_SHORTCUT_USER: \"ユーザーフォルダ\"\n  SETUP_SHORTCUT_UNINSTALL: \"アンインストール\"\n  SETUP_WARNING_UFO: \"X-COM 1 が指定先に見つかりません。${GAME_NAME}のインストールには正常なオリジナル版X-COMのインストール済みフォルダが必要です。続けますか？\"\n  SETUP_WARNING_TFTD: \"X-COM 2 が指定先に見つかりません。${GAME_NAME}のインストールには正常なオリジナル版X-COMのインストール済みフォルダが必要です。続けますか？\"\n  SETUP_WARNING_XCU: \"XcomUtilがインストｰルされています。${GAME_NAME}はXcomUtilと互換性がなく、不具合が発生するかもしれません。続けますか?\"\n  SETUP_ERROR_PORTABLE: \"インストールフォルダはポータブルには対応しません\"\n"
  },
  {
    "path": "install/win/Language/ko.yml",
    "content": "ko:\n  SETUP_XCOM_FOLDER_TITLE: \"X-COM 위치 선택\"\n  SETUP_XCOM_FOLDER_SUBTITLE: \"당신이 X-COM을 설치했던 폴더를 선택하라\"\n  SETUP_XCOM_FOLDER: \"${GAME_NAME} ${GAME_VERSION}은 아래의 X-COM 게임들 중 하나의 사본을 요구합니다. 만약 당신이 기존 설치를 업그레이드하고 있다면 이 단계를 건너뛸 수 있습니다.$\\n$\\n설치 프로그램은 아래의 폴더에서 요구되는 파일을 복사할 것입니다. 다른 폴더로부터 복사하려면, ...를 누르고 또 다른 폴더를 선택하세요. 계속하려면 다음 을 누르세요.\"\n  SETUP_UFO_FOLDER: \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n  SETUP_TFTD_FOLDER: \"X-COM: Terror From The Deep\"\n  SETUP_GAME: \"게임 파일\"\n  SETUP_GAME_DESC: \"${GAME_NAME}을 실행하기 위해 요구되는 파일입니다.\"\n  SETUP_PORTABLE: \"이동식 설치\"\n  SETUP_PORTABLE_DESC: \"${GAME_NAME}은 설치 폴더에 사용자 자료를 저장할 것입니다. 이 폴더는 반드시 사용자가 편집할 수 있어야 합니다.\"\n  SETUP_DESKTOP: \"바탕화면 바로가기\"\n  SETUP_DESKTOP_DESC: \"${GAME_NAME}을 실행하기 위해 바탕 화면에 바로가기를 만듭니다.\"\n  SETUP_UNDATA: \"X-COM 데이터 삭제\"\n  SETUP_UNDATA_DESC: \"X-COM 자료를 포함해, 모든 ${GAME_NAME} 설치 데이터를 삭제합니다. 새롭게 다시 설치할 경우 추천됩니다.\"\n  SETUP_UNUSER: \"사용자 자료 삭제\"\n  SETUP_UNUSER_DESC: \"모드, 세이브, 스크린샷과 옵션 설정을 포함해, 모든 ${GAME_NAME}의 사용자 자료를 삭제합니다. 오직 완전히 삭제할 때만 사용하세요.\"\n  SETUP_SHORTCUT_CHANGELOG: \"변경 기록\"\n  SETUP_SHORTCUT_README: \"읽어보기\"\n  SETUP_SHORTCUT_USER: \"사용자 폴더\"\n  SETUP_SHORTCUT_UNINSTALL: \"삭제\"\n  SETUP_WARNING_UFO: \"X-COM 1을 이 폴더에서 찾지 못했습니다. ${GAME_NAME}은 유효한 X-COM 설치본을 실행 시 요구합니다. 계속 하시겠습니까?\"\n  SETUP_WARNING_TFTD: \"X-COM 1을 이 폴더에서 찾지 못했습니다. ${GAME_NAME}은 유효한 X-COM 설치본을 실행 시 요구합니다. 계속 하시겠습니까?\"\n  SETUP_WARNING_XCU: \"XcomUtil을 탐지했습니다. ${GAME_NAME}은 XcomUtil과 호환되지 않으며 올바르게 동작하지 않을 지 모릅니다. 계속 하시겠습니까?\"\n  SETUP_ERROR_PORTABLE: \"이 설치 폴더는 사용자 편집할 수 없습니다.\"\n"
  },
  {
    "path": "install/win/Language/lb.yml",
    "content": "lb:\n  SETUP_XCOM_FOLDER_TITLE: \"Wiel den X-COM Dossier aus\"\n  SETUP_XCOM_FOLDER_SUBTITLE: \"Wiel d'Dossieren aus wou's du X-COM installéiert hues.\"\n  SETUP_XCOM_FOLDER: \"${GAME_NAME} ${GAME_VERSION} brauch eng Installatioun/Kopie vu folgenden X-COM Spiller. Dësen Deel kann iwwerspronge ginn, wann een just upgrade.$\\n$\\nDe Setup kopéiert d'Daten déi gebraucht ginn aus de folgenden Dossieren. Fir aus engem aneren Dossier ze kopéiren, klick ... an wiel en aneren Dossier aus. Klick Weider fir weider ze man.\"\n  SETUP_UFO_FOLDER: \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n  SETUP_TFTD_FOLDER: \"X-COM: Terror From The Deep\"\n  SETUP_GAME: \"Spill-Dateien\"\n  SETUP_GAME_DESC: \"Spill-Dateie gi gebraucht fir ${GAME_NAME} ze starten.\"\n  SETUP_PORTABLE: \"Portabel Installatioun\"\n  SETUP_PORTABLE_DESC: \"${GAME_NAME} schreiwt Benotzerdateien an den Installatiounsdossier. Den Dossier muss beschreiwbar sinn vum Benotzer.\"\n  SETUP_DESKTOP: \"Desktop Shortcut\"\n  SETUP_DESKTOP_DESC: \"Setzt e Shortcut op den Desktop fir ${GAME_NAME} ze spillen.\"\n  SETUP_UNDATA: \"X-COM Date läschen\"\n  SETUP_UNDATA_DESC: \"Läsch all ${GAME_NAME} Installatiounsdateien, inklusiv X-COM Ressourcen. Recommandéiert fir eng propper Neiinstallatioun.\"\n  SETUP_UNUSER: \"User Date läschen\"\n  SETUP_UNUSER_DESC: \"Läscht all ${GAME_NAME} User Daten, inklusiv Mods, Späicherstänn, Screenshots an Optiounen. Nëmme benotzen fir alles komplett ze läschen.\"\n  SETUP_SHORTCUT_CHANGELOG: \"Changelog\"\n  SETUP_SHORTCUT_README: \"Readme\"\n  SETUP_SHORTCUT_USER: \"User Dossier\"\n  SETUP_SHORTCUT_UNINSTALL: \"Deinstalléiren\"\n  SETUP_WARNING_UFO: \"X-COM 1 gouf net am Dossier fonnt. ${GAME_NAME} brauch eng fonctionéirend X-COM Versioun fir ze lafen. Weider man ?\"\n  SETUP_WARNING_TFTD: \"X-COM 2 gouf net am Dossier fonnt. ${GAME_NAME} brauch eng fonktionéirend X-COM Versioun fir ze lafen. Weider man ?\"\n  SETUP_WARNING_XCU: \"XcomUtil fonnt. ${GAME_NAME} ass net kompatibel mat XcomUtil an kinnt net richteg fonktionéiren. Weider man?\"\n  SETUP_ERROR_PORTABLE: \"Installatiounsdossier ass net portabel.\"\n"
  },
  {
    "path": "install/win/Language/nl.yml",
    "content": "nl:\n  SETUP_XCOM_FOLDER_TITLE: \"Kies X-COM Locatie\"\n  SETUP_XCOM_FOLDER_SUBTITLE: \"Kies de mappen waar je X-COM hebt geïnstalleerd.\"\n  SETUP_XCOM_FOLDER: \"${GAME_NAME} ${GAME_VERSION} vergt een kopie van een van de volgende X-COM spellen. Je kan deze stap overslaan als je een bestaande versie vernieuwt. $\\n$\\nSetup zal de nodige bestanden van de volgende mappen kopiëren. Om te kopiëren van een andere map, klik ... en selecteer een andere map. Klik Volgende om door te gaan.\"\n  SETUP_UFO_FOLDER: \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n  SETUP_TFTD_FOLDER: \"X-COM: Terror From The Deep\"\n  SETUP_GAME: \"Spelbestanden\"\n  SETUP_GAME_DESC: \"Bestanden nodig om ${GAME_NAME} uit te voeren.\"\n  SETUP_PORTABLE: \"Draagbare Installatie\"\n  SETUP_PORTABLE_DESC: \"${GAME_NAME} zal gebruikerdata in de installatiemap opslaan. De map moet gebruiker-schrijfbaar zijn.\"\n  SETUP_DESKTOP: \"Bureaublad snelkoppeling\"\n  SETUP_DESKTOP_DESC: \"Creëert een snelkoppeling op het bureaublad om ${GAME_NAME} te spelen.\"\n  SETUP_UNDATA: \"Verwijder X-COM Data\"\n  SETUP_UNDATA_DESC: \"Verwijdert alle ${GAME_NAME} installatiedata, inclusief X-COM bronnen. Aanbevolen voor een schone herinstallatie.\"\n  SETUP_UNUSER: \"Verwijder Gebruikersdata\"\n  SETUP_UNUSER_DESC: \"Verwijdert alle ${GAME_NAME} gebruikersdata, inclusief mods, opgeslagen spellen, schermafbeeldingen en opties. Alleen te gebruiken voor een volledige verwijdering.\"\n  SETUP_SHORTCUT_CHANGELOG: \"Veranderingslogboek\"\n  SETUP_SHORTCUT_README: \"Leesmij\"\n  SETUP_SHORTCUT_USER: \"Gebruikersmap\"\n  SETUP_SHORTCUT_UNINSTALL: \"Deïnstalleren\"\n  SETUP_WARNING_UFO: \"X-COM 1 was niet in de map gevonden. ${GAME_NAME} vergt een geldige installatie van X-COM om uit te voeren. Doorgaan?\"\n  SETUP_WARNING_TFTD: \"X-COM 2 was niet in de map gevonden. ${GAME_NAME} vergt een geldige installatie van X-COM om uit te voeren. Doorgaan?\"\n  SETUP_WARNING_XCU: \"XcomUtil gedetecteerd. ${GAME_NAME} is niet compatibel met XcomUtil en zou niet correct kunnen werken. Doorgaan?\"\n  SETUP_ERROR_PORTABLE: \"De installatie map bevindt zich in een beschermde locatie. \\nDit wordt niet ondersteund voor draagbare installaties.\"\n"
  },
  {
    "path": "install/win/Language/no.yml",
    "content": "\"no\":\n  SETUP_XCOM_FOLDER_TITLE: \"Velg X-COM Mappe\"\n  SETUP_XCOM_FOLDER_SUBTITLE: \"Velg de mappene hvor X-COM er installert.\"\n  SETUP_XCOM_FOLDER: \"${GAME_NAME} ${GAME_VERSION} krever en kopi av en av de følgende X-COM spillene. Du kan hoppe over dette punktet om du bare skal oppgradere en eksisterende installasjon.$\\n$\\nInstalleringsprogrammet vil kopiere de nødvendige filene fra de følgende mappene. For å kopiere fra en annen mappe, klikk ... og velg en annen mappe. Klikk Neste for å forsette.\"\n  SETUP_UFO_FOLDER: \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n  SETUP_TFTD_FOLDER: \"X-COM: Terror From The Deep\"\n  SETUP_GAME: \"Spillfiler\"\n  SETUP_GAME_DESC: \"Filer som kreves for å kjøre ${GAME_NAME}.\"\n  SETUP_PORTABLE: \"Flyttbar Installasjon\"\n  SETUP_DESKTOP: \"Skrivebordikon\"\n  SETUP_DESKTOP_DESC: \"Oppretter ett skrivebordikon for ${GAME_NAME}.\"\n  SETUP_UNDATA: \"Slett X-COM Data\"\n  SETUP_UNUSER: \"Slett Brukerdata\"\n  SETUP_UNUSER_DESC: \"Sletter alle ${GAME_NAME} brukerdata, inkludert modifikasjoner, lagrede spillomganger, skjermbilder og innstillinger Benyttes kun for komplett fjerning.\"\n  SETUP_SHORTCUT_CHANGELOG: \"Endrings-logg\"\n  SETUP_SHORTCUT_README: \"LesMeg\"\n  SETUP_SHORTCUT_USER: \"Brukermappe\"\n  SETUP_SHORTCUT_UNINSTALL: \"Avinstaller\"\n  SETUP_WARNING_UFO: \"X-COM 1 ble ikke funnet i mappen. ${GAME_NAME} krever en  gyldig installasjon av X-COM for å kunne kjøres. Forsette?\"\n  SETUP_WARNING_TFTD: \"X-COM 2 ble ikke funnet i mappen. ${GAME_NAME} krever en gyldig installasjon av X-COM for å kunne kjøres. Forsette?\"\n  SETUP_WARNING_XCU: \"XcomUtil oppdaget at. ${GAME_NAME} ikke er kompatibel med XcomUtil og det kan føre til at det ikke fungerer som det skal. Forsette?\"\n"
  },
  {
    "path": "install/win/Language/pl.yml",
    "content": "pl:\n  SETUP_XCOM_FOLDER_TITLE: \"Wybierz lokalizację gier UFO: Nieznany wróg i X-Com: Koszmar z głębin\"\n  SETUP_XCOM_FOLDER_SUBTITLE: \"Wybierz foldery, w których gry „UFO: Nieznany wróg” i „X-Com: Koszmar z głębin” są zainstalowane.\"\n  SETUP_XCOM_FOLDER: \"„${GAME_NAME}” w wersji ${GAME_VERSION} wymaga oryginalnej kopii gry. Możesz pominąć ten krok, jeśli zamierzasz tylko zaktualizować istniejącą instalację.$\\n$\\nInstalator skopiuje wymagane pliki z następujących folderów. Aby skopiować z innego folderu, kliknij „...” i wybierz inny folder. Kliknij „Dalej”, by kontynuować.\"\n  SETUP_UFO_FOLDER: \"UFO: Nieznany wróg\"\n  SETUP_TFTD_FOLDER: \"X-Com: Koszmar z głębin\"\n  SETUP_GAME: \"Pliki gry\"\n  SETUP_GAME_DESC: \"Wymagane pliki do uruchomienia gry „${GAME_NAME}”.\"\n  SETUP_PORTABLE: \"Instalacja przenośna\"\n  SETUP_PORTABLE_DESC: \"${GAME_NAME} będzie przechowywać pliki użytkownika w folderze instalacyjnym. Folder musi być zapisywalny przez użytkownika.\"\n  SETUP_DESKTOP: \"Skrót na pulpicie\"\n  SETUP_DESKTOP_DESC: \"Tworzy skrót na pulpicie, co umożliwia zagranie w „${GAME_NAME}”.\"\n  SETUP_UNDATA: \"Usuń dane gier UFO: Nieznany wróg i X-Com: Koszmar z głębin\"\n  SETUP_UNDATA_DESC: \"Kasuje wszystkie dane instalacyjne ${GAME_NAME}, włącznie z plikami X-Com. Zalecane przy czystej reinstalacji.\"\n  SETUP_UNUSER: \"Usuń dane użytkownika\"\n  SETUP_UNUSER_DESC: \"Usuwa wszystkie dane użytkownika gry „${GAME_NAME}”, wliczając w to modyfikacje, zapisane stany gry, zrzuty ekranu i opcje. Użyj tej opcji tylko dla pełnego wyczyszczenia danych.\"\n  SETUP_SHORTCUT_CHANGELOG: \"Dziennik zmian\"\n  SETUP_SHORTCUT_README: \"Informacje\"\n  SETUP_SHORTCUT_USER: \"Folder użytkownika\"\n  SETUP_SHORTCUT_UNINSTALL: \"Odinstaluj\"\n  SETUP_WARNING_UFO: \"Gra „UFO: Nieznany wróg” nie została znaleziona w tym folderze. Wymaga ona poprawnej instalacji, by móc ją uruchomić. Kontynuować?\"\n  SETUP_WARNING_TFTD: \"Gra „X-Com: Koszmar z głębin” nie została znaleziona w tym folderze. Wymaga ona poprawnej instalacji, by móc ją uruchomić. Kontynuować?\"\n  SETUP_WARNING_XCU: \"Wykryto XcomUtil. ${GAME_NAME} nie jest kompatybilne z XcomUtil i może nie działać poprawnie. Kontynuować?\"\n  SETUP_ERROR_PORTABLE: \"Folder instalacyjny nie jest przenośny.\"\n"
  },
  {
    "path": "install/win/Language/pt-BR.yml",
    "content": "pt-BR:\n  SETUP_XCOM_FOLDER_TITLE: \"Escolher Localização X-COM\"\n  SETUP_XCOM_FOLDER_SUBTITLE: \"Escolha as pastas onde o X-COM está instalado.\"\n  SETUP_XCOM_FOLDER: \"${GAME_NAME} ${GAME_VERSION} requer uma cópia de um dos seguintes jogos X-COM. Pode saltar este passo se estiver atualizando uma instalação existente.$\\n$\\nA instalação copiará todos os arquivos necessários das seguintes pastas. Para copiar de uma pasta diferente, clique ... e escolha outra pasta. Clique \\\"Próximo\\\" para continuar.\"\n  SETUP_UFO_FOLDER: \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n  SETUP_TFTD_FOLDER: \"X-COM: Terror From The Deep\"\n  SETUP_GAME: \"Arquivos do Jogo\"\n  SETUP_GAME_DESC: \"Arquivos necessários para executar o ${GAME_NAME}.\"\n  SETUP_PORTABLE: \"Instalação portátil\"\n  SETUP_PORTABLE_DESC: \"${GAME_NAME} irá armazenar dados de usuário na pasta de instalação. A pasta deve ter permissão de escrita pelo usuário.\"\n  SETUP_DESKTOP: \"Atalho na Área de Trabalho\"\n  SETUP_DESKTOP_DESC: \"Cria atalho na Área de Trabalho para jogar o ${GAME_NAME}.\"\n  SETUP_UNDATA: \"Remover Dados do X-COM\"\n  SETUP_UNDATA_DESC: \"Exclui todos os dados de instalação do ${GAME_NAME}, incluindo os recursos X-COM. Recomendado para uma reinstalação limpa.\"\n  SETUP_UNUSER: \"Remover Dados do Usuário\"\n  SETUP_UNUSER_DESC: \"Remove todos os dados do ${GAME_NAME}, incluindo mods, partidas salvas, capturas de tela e opções. Usar apenas para uma limpeza completa.\"\n  SETUP_SHORTCUT_CHANGELOG: \"Lista de Alterações\"\n  SETUP_SHORTCUT_README: \"Leia-me\"\n  SETUP_SHORTCUT_USER: \"Pasta do Usuário\"\n  SETUP_SHORTCUT_UNINSTALL: \"Desinstalar\"\n  SETUP_WARNING_UFO: \"X-COM 1 não foi encontrado na pasta. ${GAME_NAME} requer uma instalação válida de X-COM para rodar. Continuar?\"\n  SETUP_WARNING_TFTD: \"X-COM 2 não foi encontrado na pasta. ${GAME_NAME} requer uma instalação válida de X-COM para rodar. Continuar?\"\n  SETUP_WARNING_XCU: \"XcomUtil foi detectado. ${GAME_NAME} não é compatível com o XcomUtil e poderá não funcionar corretamente. Continuar?\"\n  SETUP_ERROR_PORTABLE: \"A pasta de instalação não é portátil.\"\n"
  },
  {
    "path": "install/win/Language/pt-PT.yml",
    "content": "pt-PT:\n  SETUP_XCOM_FOLDER_TITLE: \"Escolher localização X-COM\"\n  SETUP_XCOM_FOLDER_SUBTITLE: \"Escolher a pasta onde instalou X-COM.\"\n  SETUP_XCOM_FOLDER: \"${GAME_NAME} ${GAME_VERSION} necessita de uma cópia de um dos seguintes jogos X-COM. Pode saltar este passo se está a atualizar uma instalação existente.\\n\\nA instalação copiará todos os ficheiros necessários das seguintes pastas. Para copiar de uma pasta diferente, clique ... e escolha outra pasta. Clique \\\"Seguinte\\\" para continuar.\"\n  SETUP_UFO_FOLDER: \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n  SETUP_TFTD_FOLDER: \"X-COM: Terror From The Deep\"\n  SETUP_GAME: \"Ficheiros do jogo\"\n  SETUP_GAME_DESC: \"Ficheiros necessários para correr ${GAME_NAME}.\"\n  SETUP_PORTABLE: \"Instalação portável\"\n  SETUP_PORTABLE_DESC: \"${GAME_NAME} irá guardar dados de utilizador na pasta de instalação. A pasta tem ser ser gravável.\"\n  SETUP_DESKTOP: \"Atalho no ambiente de trabalho\"\n  SETUP_DESKTOP_DESC: \"Cria atalho no ambiente de trabalho para jogar ${GAME_NAME}.\"\n  SETUP_UNDATA: \"Remover ficheiros X-COM\"\n  SETUP_UNDATA_DESC: \"Elimina todos os dados de ${GAME_NAME}, incluindo os recursos do X-COM. Recomendável para uma reinstalação limpa.\"\n  SETUP_UNUSER: \"Remover dados do utilizador\"\n  SETUP_UNUSER_DESC: \"Remove todos os dados de ${GAME_NAME}, incluindo mods, partidas gravadas, capturas de ecrã e opções. Usar apenas para uma limpeza completa.\"\n  SETUP_SHORTCUT_CHANGELOG: \"Lista de mudanças\"\n  SETUP_SHORTCUT_README: \"Leia-me\"\n  SETUP_SHORTCUT_USER: \"Pasta do utilizador\"\n  SETUP_SHORTCUT_UNINSTALL: \"Desinstalar\"\n  SETUP_WARNING_UFO: \"X-COM 1 não foi encontrado na pasta. ${GAME_NAME} necessita de uma instalação válida de X-COM para correr. Continuar?\"\n  SETUP_WARNING_TFTD: \"X-COM 2 não foi encontrado na pasta. ${GAME_NAME} necessita de uma instalação válida de X-COM para correr. Continuar?\"\n  SETUP_WARNING_XCU: \"XcomUtil foi detetado. ${GAME_NAME} é incompatível com XcomUtil e poderá não funcionar corretamente. Continuar?\"\n  SETUP_ERROR_PORTABLE: \"A pasta de instalação não é portável.\"\n"
  },
  {
    "path": "install/win/Language/ro.yml",
    "content": "ro:\n  SETUP_XCOM_FOLDER_TITLE: \"Alegeți Locația X-COM\"\n  SETUP_XCOM_FOLDER_SUBTITLE: \"Alegeți dosarele unde aveți instalat X-COM.\"\n  SETUP_XCOM_FOLDER: \"${GAME_NAME} ${GAME_VERSION} necesită o copie a unuia din următoarele jocuri X-COM. Dacă se face o actualizare a unei instalări existente se poate trece peste acest pas.$\\n$\\nInstalarea va copia fișierele necesare din următorul dosar. Pentru a copia din alt dosar, apăsați pe ... și selectați altă locație. Apăsați pe Înainte pentru a continua.\"\n  SETUP_UFO_FOLDER: \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n  SETUP_TFTD_FOLDER: \"X-COM: Terror From The Deep\"\n  SETUP_GAME: \"Fișierele Jocului\"\n  SETUP_GAME_DESC: \"Fișierele necesare pentru a rula ${GAME_NAME}.\"\n  SETUP_PORTABLE: \"Instalare Portabilă\"\n  SETUP_PORTABLE_DESC: \"${GAME_NAME} va păstra datele personalizate în dosarul de instalare. Dosarul trebuie să permită scrierea.\"\n  SETUP_DESKTOP: \"Scurtătură Desktop\"\n  SETUP_DESKTOP_DESC: \"Crează o scurtătură pe ecran pentru a juca ${GAME_NAME}.\"\n  SETUP_UNDATA: \"Ștergere Date X-COM\"\n  SETUP_UNDATA_DESC: \"Șterge toate datele ${GAME_NAME}, inclusiv resursele X-COM. Recomandat pentru o reinstalare curată.\"\n  SETUP_UNUSER: \"Ștergere Date Utilizator\"\n  SETUP_UNUSER_DESC: \"Șterge toate datele de utilizator pentru ${GAME_NAME}, inclusiv modificările, salvările, capturile de ecran și opțiunile. Recomandat numai pentru o ștergere completă.\"\n  SETUP_SHORTCUT_CHANGELOG: \"Jurnal Modificări\"\n  SETUP_SHORTCUT_README: \"Citește\"\n  SETUP_SHORTCUT_USER: \"Dosar Utilizator\"\n  SETUP_SHORTCUT_UNINSTALL: \"Dezinstalare\"\n  SETUP_WARNING_UFO: \"X-COM 1 nu s-a găsit în acest dosar. ${GAME_NAME} necesită o instalare X-COM validă pentru a rula. Continuați?\"\n  SETUP_WARNING_TFTD: \"X-COM 2 nu s-a găsit în acest dosar. ${GAME_NAME} necesită o instalare X-COM validă pentru a rula. Continuați?\"\n  SETUP_WARNING_XCU: \"XcomUtil detectat. ${GAME_NAME} este incompatibil cu XcomUtil și este posibil să funcționeze incorect. Continuați?\"\n  SETUP_ERROR_PORTABLE: \"Folderul de instalat nu este portabil.\"\n"
  },
  {
    "path": "install/win/Language/ru.yml",
    "content": "ru:\n  SETUP_XCOM_FOLDER_TITLE: \"Укажите директорию X-COM\"\n  SETUP_XCOM_FOLDER_SUBTITLE: \"Укажите каталог, в который установлена копия X-COM.\"\n  SETUP_XCOM_FOLDER: \"Для ${GAME_NAME} ${GAME_VERSION} необходима копия одной из следующих игр. Если вы обновляете установленную игру, этот шаг можно пропустить.$\\n$\\nВо время установки необходимые файлы будут скопированы в следующий каталог. Если вы хотите скопировать их в другой каталог, нажмите кнопку «...» и укажите его. Нажмите «Далее» для продолжения.\"\n  SETUP_UFO_FOLDER: \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n  SETUP_TFTD_FOLDER: \"X-COM: Terror From The Deep\"\n  SETUP_GAME: \"Файлы игры\"\n  SETUP_GAME_DESC: \"Файлы, необходимые для запуска ${GAME_NAME}.\"\n  SETUP_PORTABLE: \"Портативная (переносная) установка\"\n  SETUP_PORTABLE_DESC: \"${GAME_NAME} будет хранить пользовательские данные в каталоге установки. Этот каталог должен быть доступен пользователю для записи.\"\n  SETUP_DESKTOP: \"Ярлык на рабочем столе\"\n  SETUP_DESKTOP_DESC: \"Создает ярлык ${GAME_NAME} на рабочем столе.\"\n  SETUP_UNDATA: \"Удалить ассеты X-COM\"\n  SETUP_UNDATA_DESC: \"Удалить все установленные файлы ${GAME_NAME}, включая ассеты X-COM. Рекомендуется при установке начисто.\"\n  SETUP_UNUSER: \"Удалить пользовательские файлы\"\n  SETUP_UNUSER_DESC: \"Удалить все пользовательские файлы ${GAME_NAME}, включая модификации, сохранения, снимки экрана и настройки игры. Рекомендуется только при полном удалении.\"\n  SETUP_SHORTCUT_CHANGELOG: \"История изменений\"\n  SETUP_SHORTCUT_README: \"Readme\"\n  SETUP_SHORTCUT_USER: \"Пользовательский каталог\"\n  SETUP_SHORTCUT_UNINSTALL: \"Удалить\"\n  SETUP_WARNING_UFO: \"В каталоге не найдены ассеты X-COM 1. Для запуска ${GAME_NAME} необходимы файлы X-COM. Продолжить?\"\n  SETUP_WARNING_TFTD: \"В каталоге не найдены ассеты X-COM 2. Для запуска ${GAME_NAME} необходимы файлы X-COM. Продолжить?\"\n  SETUP_WARNING_XCU: \"Обнаружена утилита XcomUtil. ${GAME_NAME} несовместима с XcomUtil и может работать некорректно. Продолжить?\"\n  SETUP_ERROR_PORTABLE: \"Директорию установки невозможно перенести.\"\n"
  },
  {
    "path": "install/win/Language/sk.yml",
    "content": "sk:\n  SETUP_XCOM_FOLDER_TITLE: \"Vyberte umiestnenie X-COM\"\n  SETUP_XCOM_FOLDER_SUBTITLE: \"Vyberte priečinky, v ktorých máte nainštalovaný X-COM.\"\n  SETUP_XCOM_FOLDER: \"${GAME_NAME} ${GAME_VERSION} vyžaduje kópiu jednej z nasledujúcich X-COM hier. Tento krok môžete preskočiť pokiaľ aktualizujete existujúcu inštaláciu.$\\n$\\nSetup skopíruje vyžadované súbory z nasledujúcich priečinkov. Pre kopírovanie z iného priečinku kliknite ... a vyberte iný priečinok. Pre pokračovanie kliknite na ďalej.\"\n  SETUP_UFO_FOLDER: \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n  SETUP_TFTD_FOLDER: \"X-COM: Terror From The Deep\"\n  SETUP_GAME: \"Súbory hry\"\n  SETUP_GAME_DESC: \"Súbory potrebné pre spustenie ${GAME_NAME}.\"\n  SETUP_PORTABLE: \"Prenosná inštalácia\"\n  SETUP_PORTABLE_DESC: \"${GAME_NAME} uloží aj všetky používateľské súbory do inštalačného priečinku. Priečinok nesmie byť chránený voči zapisovaniu.\"\n  SETUP_DESKTOP: \"Ikona na ploche\"\n  SETUP_DESKTOP_DESC: \"Vytvorí ikonu na ploche pre spustenie hry ${GAME_NAME}.\"\n  SETUP_UNDATA: \"Vymazať X-COM dáta\"\n  SETUP_UNDATA_DESC: \"Vymaže všetky nainštalované dáta hry ${GAME_NAME}, vrátane pôvodných súborov. Odporúča sa pre čistú reinštaláciu.\"\n  SETUP_UNUSER: \"Vymazať používateľské dáta\"\n  SETUP_UNUSER_DESC: \"Vymaže všetky užívateľské dáta hry ${GAME_NAME}, vrátane modov, uložených pozícii, screenshotov a nastavení. Odporúča sa iba pre kompletné vymazanie hry.\"\n  SETUP_SHORTCUT_CHANGELOG: \"Changelog\"\n  SETUP_SHORTCUT_README: \"Readme\"\n  SETUP_SHORTCUT_USER: \"Používateľský priečinok\"\n  SETUP_SHORTCUT_UNINSTALL: \"Odinštalovať\"\n  SETUP_WARNING_UFO: \"X-COM 1 sa nenašla vo vybranom priečinku. ${GAME_NAME} vyžaduje platnú inštaláciu X-COMu, aby mohla fungovať. Pokračovať?\"\n  SETUP_WARNING_TFTD: \"X-COM 2 sa nenašla vo vybranom priečinku. ${GAME_NAME} vyžaduje platnú inštaláciu X-COMu, aby mohla fungovať. Pokračovať?\"\n  SETUP_WARNING_XCU: \"Bol nájdený XcomUtil. ${GAME_NAME} nie je kompatibilná s XComUtil a môže fungovať nesprávne. Pokračovať?\"\n  SETUP_ERROR_PORTABLE: \"Inštalačný priečinok nepodporuje prenosnú inštaláciu.\"\n"
  },
  {
    "path": "install/win/Language/sv.yml",
    "content": "sv:\n  SETUP_XCOM_FOLDER_TITLE: \"Välj X-COM-plats\"\n  SETUP_XCOM_FOLDER_SUBTITLE: \"Välj mapp där du har X-COM installerat.\"\n  SETUP_XCOM_FOLDER: \"${GAME_NAME} ${GAME_VERSION} behöver ett exemplar av ett av följande X-COM-spel. Du kan ignorera detta steg om du uppgraderar en tidigare installation.\\n\\nInstallationsprogrammet kommer att kopiera de nödvändiga filerna från följande mappar. För att välja en annan mapp klicka på ... och välj en annan plats. Klicka Nästa för att fortsätta.\"\n  SETUP_UFO_FOLDER: \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n  SETUP_TFTD_FOLDER: \"X-COM: Terror From The Deep\"\n  SETUP_GAME: \"Spelfiler\"\n  SETUP_GAME_DESC: \"Filer som behövs för att köra ${GAME_NAME}.\"\n  SETUP_PORTABLE: \"Portabel installation\"\n  SETUP_PORTABLE_DESC: \"${GAME_NAME} kommer att lagra användardata i installationsmappen. Mappen måste vara skrivbar.\"\n  SETUP_DESKTOP: \"Skrivbordsgenväg\"\n  SETUP_DESKTOP_DESC: \"Skapar en genväg på skrivbordet för att spela ${GAME_NAME}.\"\n  SETUP_UNDATA: \"Ta bort X-COM-data\"\n  SETUP_UNDATA_DESC: \"Tar bort allt installerat ${GAME_NAME}-data inklusive X-Com-filer. Rekommenderas för en ren ominstallation.\"\n  SETUP_UNUSER: \"Ta bort användardata\"\n  SETUP_UNUSER_DESC: \"Tar bort allt ${GAME_NAME}-användardata, inklusive moddar, sparfiler, skärmdumpar och inställningar. Bör användas enbart vid total avinstallation.\"\n  SETUP_SHORTCUT_CHANGELOG: \"Ändringslogg\"\n  SETUP_SHORTCUT_README: \"Readme\"\n  SETUP_SHORTCUT_USER: \"Användarmapp\"\n  SETUP_SHORTCUT_UNINSTALL: \"Avinstallation\"\n  SETUP_WARNING_UFO: \"X-COM 1 hittades inte i mappen. ${GAME_NAME} kräver en giltig installation av X-COM för att kunna köras. Fortsätt ändå?\"\n  SETUP_WARNING_TFTD: \"X-COM 2 hittades inte i mappen. ${GAME_NAME} kräver en giltig installation av X-COM för att kunna köras. Fortsätt ändå?\"\n  SETUP_WARNING_XCU: \"XcomUtil hittades. ${GAME_NAME} är okompatibelt med XcomUtil och kanske inte kommer fungera korrekt. Fortsätt ändå?\"\n  SETUP_ERROR_PORTABLE: \"Installationsmappen är inte portabel.\"\n"
  },
  {
    "path": "install/win/Language/tr.yml",
    "content": "tr:\n  SETUP_XCOM_FOLDER_TITLE: \"X-COM'un Konumunu Seç\"\n  SETUP_XCOM_FOLDER_SUBTITLE: \"X-COM'un kurulu olduğu dizinlerin seçimi.\"\n  SETUP_XCOM_FOLDER: \"${GAME_NAME} ${GAME_VERSION}, aşağıdaki X-COM oyunlarından birini gerektirir. Eğer mevcut bir kurulumu güncelliyorsanız, bu adımı atlayabilirsiniz.$\\n$\\nKurulum, gerekli dosyaları aşağıdaki dizinlerden kopyalayacak. Farklı bir dizinden kopyalamak için ... butonuna basın ve bir dizin seçin. Sonraki butonuna basarak devam edebilirsiniz.\"\n  SETUP_UFO_FOLDER: \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n  SETUP_TFTD_FOLDER: \"X-COM: Terror From The Deep\"\n  SETUP_GAME: \"Oyun Dosyaları\"\n  SETUP_GAME_DESC: \"${GAME_NAME} çalıştırmak için gerekli dosyalar.\"\n  SETUP_PORTABLE: \"Taşınabilir Kurulum\"\n  SETUP_PORTABLE_DESC: \"${GAME_NAME} kullanıcı bilgilerini kurulum dizininde tutar. Kullanıcının dizine yazma hakkı olmalıdır.\"\n  SETUP_DESKTOP: \"Masaüstü Kısayolu\"\n  SETUP_DESKTOP_DESC: \"Masaüstünde ${GAME_NAME} için kısayol oluşturur.\"\n  SETUP_UNDATA: \"X-COM Verilerini Sil\"\n  SETUP_UNDATA_DESC: \"X-COM kaynak dosyaları da dahil olmak üzere tüm ${GAME_NAME} verilerini siler. Temiz bir kurulum için tavsiye edilir.\"\n  SETUP_UNUSER: \"Kullanıcı Verilerini Sil\"\n  SETUP_UNUSER_DESC: \"Modlar, kayıtlı oyunlar, ekran görüntüleri ve ayarlar dahil olmak üzere tüm ${GAME_NAME}  kullanıcı verilerini siler. Sadece tam bir temizlik için tavsiye edilir.\"\n  SETUP_SHORTCUT_CHANGELOG: \"Güncellemeler\"\n  SETUP_SHORTCUT_README: \"Okubeni\"\n  SETUP_SHORTCUT_USER: \"Kullanıcı Dizini\"\n  SETUP_SHORTCUT_UNINSTALL: \"Kaldır\"\n  SETUP_WARNING_UFO: \"X-COM 1 bulunamadı. ${GAME_NAME}, geçerli bir X-COM kurulumu gerektirir. Devam?\"\n  SETUP_WARNING_TFTD: \"X-COM 2 bulunamadı. ${GAME_NAME}, geçerli bir X-COM kurulumu gerektirir. Devam?\"\n  SETUP_WARNING_XCU: \"XcomUtil tespit edildi. ${GAME_NAME}, XcomUtil ile uyumlu olmadığından beklenmeyen durumlarla karşılaşabilirsiniz. Devam?\"\n  SETUP_ERROR_PORTABLE: \"Kurulum dizini taşınabilir değil.\"\n"
  },
  {
    "path": "install/win/Language/uk.yml",
    "content": "uk:\n  SETUP_XCOM_FOLDER_TITLE: \"Вкажіть розташування X-COM\"\n  SETUP_XCOM_FOLDER_SUBTITLE: \"Оберіть каталог з встановленим X-COM.\"\n  SETUP_XCOM_FOLDER: \"Для ${GAME_NAME} ${GAME_VERSION} необхідна копія однієї з наступних ігор серії  X-COM. Якщо ви оновлюєте вже встановлену гру цей крок можна пропустити.$\\n$\\nПід час встановлення необхдні файли будуть скопійовані з наступного каталогу. Для копіювання з іншого каталогу натисніть ... та оберіть необхідний каталог. Натисніть Далі для продовження.\"\n  SETUP_UFO_FOLDER: \"UFO: Enemy Unknown / X-COM: UFO Defense\"\n  SETUP_TFTD_FOLDER: \"X-COM: Terror From The Deep\"\n  SETUP_GAME: \"Файли гри\"\n  SETUP_GAME_DESC: \"Файли, необхідні для запуску ${GAME_NAME}.\"\n  SETUP_PORTABLE: \"Портативне Встановлення \"\n  SETUP_PORTABLE_DESC: \"${GAME_NAME} буде зберігати ресурси користувача в каталозі встановлення. Каталог має бути доступним для запису файлів користувачем. \"\n  SETUP_DESKTOP: \"Ярлик на Робочому столі\"\n  SETUP_DESKTOP_DESC: \"Створити ярлик ${GAME_NAME} на Робочому столі\"\n  SETUP_UNDATA: \"Видалити X-COM\"\n  SETUP_UNDATA_DESC: \"Видалити всі встановлені дані ${GAME_NAME}, включно з ресурсами X-COM. Рекомендовано для чистого перевстановлення.\"\n  SETUP_UNUSER: \"Видалити дані користувача\"\n  SETUP_UNUSER_DESC: \"Видалити всі дані користувача ${GAME_NAME} включно з МОДифікаціями, збереженнями, знімками екрану та налаштуваннями. Рекомендовано тільки при повному видаленні.\"\n  SETUP_SHORTCUT_CHANGELOG: \"Перелік змін\"\n  SETUP_SHORTCUT_README: \"Readme\"\n  SETUP_SHORTCUT_USER: \"Каталог користувача\"\n  SETUP_SHORTCUT_UNINSTALL: \"Видалити\"\n  SETUP_WARNING_UFO: \"Ресурси X-COM 1 не знайдені в каталозі. Для запуску ${GAME_NAME} потребує оригінальні файли X-COM. Продовжити?\"\n  SETUP_WARNING_TFTD: \"Ресурси X-COM 2 не знайдені в каталозі. Для запуску ${GAME_NAME} потребує оригінальні файли X-COM. Продовжити?\"\n  SETUP_WARNING_XCU: \"Виявлений XcomUtil. Можлива некоректна робота ${GAME_NAME} через несумісність з XcomUtil. Продовжити?\"\n  SETUP_ERROR_PORTABLE: \"Теку з інсталяцією не можна переносити.\"\n"
  },
  {
    "path": "install/win/Language/zh-CN.yml",
    "content": "zh-CN:\n  SETUP_XCOM_FOLDER_TITLE: \"选择X-COM的安装目录\"\n  SETUP_XCOM_FOLDER_SUBTITLE: \"选择你已经安装好的X-COM所在目录\"\n  SETUP_XCOM_FOLDER: \"${GAME_NAME} ${GAME_VERSION} 需要任意一份如下X-COM游戏的副本。如果你是在升级，则可以跳过这一步。$\\n$\\n安装程序将会从以下目录复制文件，如果要从其他目录复制文件，点击“...”并选择目录。按“下一步”继续。\"\n  SETUP_UFO_FOLDER: \"X-COM：飞碟防御\"\n  SETUP_TFTD_FOLDER: \"X-COM：深海出击\"\n  SETUP_GAME: \"游戏文件\"\n  SETUP_GAME_DESC: \"运行${GAME_NAME}所需的文件。\"\n  SETUP_PORTABLE: \"可移动设备\"\n  SETUP_PORTABLE_DESC: \"${GAME_NAME}将会在安装文件夹中保存用户数据文件。请确保该文件夹拥有读写权限。\"\n  SETUP_DESKTOP: \"桌面快捷方式\"\n  SETUP_DESKTOP_DESC: \"在桌面上创建${GAME_NAME}的快捷方式。\"\n  SETUP_UNDATA: \"删除X-COM数据\"\n  SETUP_UNDATA_DESC: \"删除全部${GAME_NAME}安装数据，包括全部X-COM资源文件。推荐重新安装原始版本。\"\n  SETUP_UNUSER: \"删除用户数据\"\n  SETUP_UNUSER_DESC: \"删除所有${GAME_NAME}所有的用户数据，包括模组，存档，截图以及选项设置。卸载时请选中该项。\"\n  SETUP_SHORTCUT_CHANGELOG: \"更新列表\"\n  SETUP_SHORTCUT_README: \"说明\"\n  SETUP_SHORTCUT_USER: \"用户文件夹\"\n  SETUP_SHORTCUT_UNINSTALL: \"卸载\"\n  SETUP_WARNING_UFO: \"没有找到原版X-COM1的位置。${GAME_NAME}需要一份有效的原版X-COM才能运行。继续吗？\"\n  SETUP_WARNING_TFTD: \"没有找到原版X-COM2的位置。${GAME_NAME}需要一份有效的原版X-COM2才能运行。继续吗？\"\n  SETUP_WARNING_XCU: \"检测到XcomUtil已经安装。${GAME_NAME}与它不兼容，可能会出现问题。继续吗？\"\n  SETUP_ERROR_PORTABLE: \"安装文件夹不支持移动安装。\"\n"
  },
  {
    "path": "install/win/Language/zh-TW.yml",
    "content": "zh-TW:\n  SETUP_XCOM_FOLDER_TITLE: \"選擇 X-COM 安裝路徑\"\n  SETUP_XCOM_FOLDER_SUBTITLE: \"選擇您已安裝 X-COM 的資料夾\"\n  SETUP_XCOM_FOLDER: \"${GAME_NAME} ${GAME_VERSION} 需要以下的 X-COM 遊戲。若您要更新已存在的安裝，可略過此步驟。$\\n$\\n安裝程式將複製必須檔案至下列資料夾。欲複製到其他資料夾，點擊...以選擇其他資料夾。點擊下一步以繼續。\"\n  SETUP_UFO_FOLDER: \"UFO: 未知敵人 / X-COM: UFO入侵\"\n  SETUP_TFTD_FOLDER: \"X-COM: 深海幽浮\"\n  SETUP_GAME: \"遊戲檔案\"\n  SETUP_GAME_DESC: \"執行${GAME_NAME}的必須檔案。\"\n  SETUP_PORTABLE: \"可攜式安裝\"\n  SETUP_PORTABLE_DESC: \"${GAME_NAME}將會使用者資料儲存在安裝資料夾中。請確保該資料夾擁有讀寫權限。\"\n  SETUP_DESKTOP: \"桌面捷徑\"\n  SETUP_DESKTOP_DESC: \"在桌面建立一個玩 ${GAME_NAME}的捷徑。\"\n  SETUP_UNDATA: \"刪除X-COM資料\"\n  SETUP_UNDATA_DESC: \"刪除全部${GAME_NAME}安裝數據，包含全部X-COM資源檔。推薦重新安裝原始版本。\"\n  SETUP_UNUSER: \"刪除使用者資料\"\n  SETUP_UNUSER_DESC: \"刪除所有的${GAME_NAME}使用者資料，包括MOD、存檔、截圖和選項。僅於完全移除時使用。\"\n  SETUP_SHORTCUT_CHANGELOG: \"更新紀錄\"\n  SETUP_SHORTCUT_README: \"讀我\"\n  SETUP_SHORTCUT_USER: \"使用者資料夾\"\n  SETUP_SHORTCUT_UNINSTALL: \"移除\"\n  SETUP_WARNING_UFO: \"未在資料夾尋獲X-COM 1。${GAME_NAME}需要一份有效的X-COM才能執行。是否繼續？\"\n  SETUP_WARNING_TFTD: \"未在資料夾尋獲X-COM 2。${GAME_NAME}需要一份有效的X-COM才能執行。是否繼續？\"\n  SETUP_WARNING_XCU: \"偵測到XcomUtil。${GAME_NAME}與該軟體不相容，可能會產生問題。是否繼續？\"\n  SETUP_ERROR_PORTABLE: \"安裝文件夾不支援可攜式安裝。\"\n"
  },
  {
    "path": "install/win/convert_lang.py",
    "content": "import glob\n\n# Convert YAML language files to NSIS format\nLANGS = {\n\t\"bg\": \"Bulgarian\",\n\t\"ca-ES\": \"Catalan\",\n\t\"cs\": \"Czech\",\n\t\"cy\": \"Welsh\",\n\t\"da\": \"Danish\",\n\t\"de\": \"German\",\n\t\"el\": \"Greek\",\n\t\"et\": \"Estonian\",\n\t\"es-ES\": \"Spanish\",\n\t\"es-419\": \"SpanishInternational\",\n\t\"fr\": \"French\",\n\t\"fi\": \"Finnish\",\n\t\"ga\": \"Galician\",\n\t\"hr\": \"Croatian\",\n\t\"hu\": \"Hungarian\",\n\t\"it\": \"Italian\",\n\t\"is\": \"Icelandic\",\n\t\"ja\": \"Japanese\",\n\t\"ko\": \"Korean\",\n\t\"lb\": \"Luxembourgish\",\n\t\"lv\": \"Latvian\",\n\t\"nl\": \"Dutch\",\n\t\"no\": \"Norweigan\",\n\t\"pl\": \"Polish\",\n\t\"pt-BR\": \"PortugueseBR\",\n\t\"pt-PT\": \"Portuguese\",\n\t\"ro\": \"Romanian\",\n\t\"ru\": \"Russian\",\n\t\"sk\": \"Slovak\",\n\t\"sl\": \"Slovenian\",\n\t\"sv\": \"Swedish\",\n\t\"tr\": \"Turkish\",\n\t\"uk\": \"Ukrainian\",\n\t\"vi\": \"Vietnamese\",\n\t\"zh-CN\": \"SimpChinese\",\n\t\"zh-TW\": \"TradChinese\",\n}\n\nlangs = []\nfor yamlPath in glob.glob(\"Language/*.yml\"):\n    nshLines = []\n    nshLang = \"\"\n    with open(yamlPath, \"r\", encoding=\"utf-8\") as yamlFile:\n        for line in yamlFile:\n            # First line is the language ID\n            if '\"' not in line:\n                lang = line.strip(\":\\n\")\n                if lang in LANGS:\n                    nshLang = LANGS[lang]\n                    nshLines.append(f'!insertmacro LANGFILE_EXT \"{nshLang}\"\\n')\n                    langs.append(nshLang)\n                else:\n                    break\n            else:\n                string = line.strip().replace(': \"', ' \"').replace(\"\\\\\\\"\", \"\")\n                nshLine = \"${LangFileString} \" + string + \"\\n\"\n                nshLines.append(nshLine)\n\n    if nshLang != \"\":\n        nshPath = \"Language/\" + nshLang + \".nsh\"\n        with open(nshPath, \"w\", encoding=\"utf-8\") as nshFile:\n            nshFile.writelines(nshLines)\n\nwith open(\"language.nsh\", \"w\", encoding=\"utf-8\") as nshInclude:\n    nshInclude.write('!insertmacro MUI_LANGUAGE \"English\"\\n')\n    nshInclude.write('!insertmacro LANGFILE_INCLUDE \"Language\\\\English.nsh\"\\n')\n    for lang in langs:\n        nshInclude.write(f'!insertmacro MUI_LANGUAGE \"{lang}\"\\n')\n        nshInclude.write(f'!insertmacro LANGFILE_INCLUDE \"Language\\\\{lang}.nsh\"\\n')"
  },
  {
    "path": "install/win/installer.nsi",
    "content": ";NSIS OpenXcom Windows Installer\n\n;--------------------------------\n;Special\n\n\t;Enable support for Unicode\n\tUnicode true\n\n\t;Compress the hell out of it\n\tSetCompressor /SOLID lzma\n\t\n\t!addplugindir /x86-ansi \".\\plugins\\x86-ansi\"\n\t!addplugindir /x86-unicode \".\\plugins\\x86-unicode\"\n\n;--------------------------------\n;Includes\n\n\t!include \"MUI2.nsh\"\n\t!include \"nsDialogs.nsh\"\n\t!include \"x64.nsh\"\n\t!include \"Sections.nsh\"\n\t!include \"LangFile.nsh\"\n\t!include \"StrFunc.nsh\"\n\n;--------------------------------\n;Defines\n\n\t!define GAME_NAME \"OpenXcom Extended\"\n\t!define GAME_VERSION \"8.6.0\"\n\t!define GAME_AUTHOR \"OpenXcom Developers\"\n\t!include \"version.nsh\"\n\n;--------------------------------\n;General\n\n\t;Name and file\n\tName \"${GAME_NAME} ${GAME_VERSION}\"\n\tOutFile \"openxcom_extended_v${GAME_VERSION}-win64.exe\"\n\n\t;Default installation folder\n\tInstallDir \"$PROGRAMFILES\\${GAME_NAME}\"\n\n\t;Get installation folder from registry if available\n\tInstallDirRegKey HKLM \"Software\\${GAME_NAME}\" \"\"\n\n\t;Request application privileges for Windows Vista\n\tRequestExecutionLevel admin\n\n;--------------------------------\n;Variables\n\n\tVar XDialog\n\tVar XLabelHeader\n\tVar XLabelDirUFO\n\tVar XDirUFO\n\tVar XBrowseUFO\n\tVar XLabelDirTFTD\n\tVar XDirTFTD\n\tVar XBrowseTFTD\n\n\tVar StartMenuFolder\n\tVar UFO_DIR\n\tVar TFTD_DIR\n\tVar PortableMode\n\n;--------------------------------\n;Interface Settings\n\n\t!define MUI_HEADERIMAGE\n\t!define MUI_HEADERIMAGE_BITMAP logo.bmp\n\t!define MUI_WELCOMEFINISHPAGE_BITMAP side.bmp\n\t\n\t;Show all languages, despite user's codepage\n\t!define MUI_LANGDLL_ALLLANGUAGES\n\t!define MUI_LANGDLL_ALWAYSSHOW\n\n;--------------------------------\n;Language Selection Dialog Settings\n\n\t;Remember the installer language\n\t!define MUI_LANGDLL_REGISTRY_ROOT \"HKLM\"\n\t!define MUI_LANGDLL_REGISTRY_KEY \"Software\\${GAME_NAME}\"\n\t!define MUI_LANGDLL_REGISTRY_VALUENAME \"Installer Language\"\n\n;--------------------------------\n;Pages\n\n\t!insertmacro MUI_PAGE_WELCOME\n\t!insertmacro MUI_PAGE_COMPONENTS\n\t!define MUI_PAGE_CUSTOMFUNCTION_PRE PreDirectory\n\t!define MUI_PAGE_CUSTOMFUNCTION_LEAVE PostDirectory\n\t!insertmacro MUI_PAGE_DIRECTORY\n\n\tPage custom XcomFolder ValidateXcom\n\n\t;Start Menu Folder Page Configuration\n\t!define MUI_STARTMENUPAGE_REGISTRY_ROOT \"HKLM\"\n\t!define MUI_STARTMENUPAGE_REGISTRY_KEY \"Software\\${GAME_NAME}\"\n\t!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME \"Start Menu Folder\"\n\n\t!insertmacro MUI_PAGE_STARTMENU Application $StartMenuFolder\n\n\t!insertmacro MUI_PAGE_INSTFILES\n\n\t;Finish Page Configuration\n\t!define MUI_FINISHPAGE_RUN\n\t!define MUI_FINISHPAGE_RUN_FUNCTION RunAsUser\n\t!define MUI_FINISHPAGE_NOREBOOTSUPPORT\n\n\t!insertmacro MUI_PAGE_FINISH\n\n\t!insertmacro MUI_UNPAGE_COMPONENTS\n\t!insertmacro MUI_UNPAGE_CONFIRM\n\t!insertmacro MUI_UNPAGE_INSTFILES\n\t\nFunction RunAsUser\n\tShellExecAsUser::ShellExecAsUser \"open\" \"$INSTDIR\\OpenXcomEx.exe\"\nFunctionEnd\n\nFunction XcomFolder\n\n\t!insertmacro MUI_HEADER_TEXT $(SETUP_XCOM_FOLDER_TITLE) $(SETUP_XCOM_FOLDER_SUBTITLE)\n\n\tnsDialogs::Create 1018\n\tPop $XDialog\n\n\t${If} $XDialog == error\n\t\tAbort\n\t${EndIf}\n\n\t${NSD_CreateLabel} 0 0 100% 50% $(SETUP_XCOM_FOLDER)\n\tPop $XLabelHeader\n\n\t${NSD_CreateLabel} 0 -67u 100% 10u $(SETUP_UFO_FOLDER)\n\tPop $XLabelDirUFO\n\n\t${NSD_CreateDirRequest} 0 -56u 95% 12u $UFO_DIR\n\tPop $XDirUFO\n\t${NSD_OnChange} $XDirUFO XcomFolderOnChange\n\n\t${NSD_CreateBrowseButton} -14u -56u 14u 12u \"...\"\n\tPop $XBrowseUFO\n\t${NSD_OnClick} $XBrowseUFO XcomFolderOnBrowse\n\n\t${NSD_CreateLabel} 0 -31u 95% 10u $(SETUP_TFTD_FOLDER)\n\tPop $XLabelDirTFTD\n\n\t${NSD_CreateDirRequest} 0 -20u 95% 12u $TFTD_DIR\n\tPop $XDirTFTD\n\t${NSD_OnChange} $XDirTFTD XcomFolderOnChange\n\n\t${NSD_CreateBrowseButton} -14u -20u 14u 12u \"...\"\n\tPop $XBrowseTFTD\n\t${NSD_OnClick} $XBrowseTFTD XcomFolderOnBrowse\n\n\tnsDialogs::Show\n\nFunctionEnd\n\nFunction XcomFolderOnChange\n\n\tPop $0\n\n\t${If} $0 == $XDirUFO\n\t\t${NSD_GetText} $0 $UFO_DIR\n\t${EndIf}\n\n\t${If} $0 == $XDirTFTD\n\t\t${NSD_GetText} $0 $TFTD_DIR\n\t${EndIf}\n\nFunctionEnd\n\nFunction XcomFolderOnBrowse\n\n\tPop $0\n\n\t${If} $0 == $XBrowseUFO\n\t\tnsDialogs::SelectFolderDialog $(SETUP_UFO_FOLDER) $UFO_DIR\n\t\tPop $1\n\t\t${If} $1 == error\n\t\t\tReturn\n\t\t${EndIf}\n\t\tStrCpy $UFO_DIR $1\n\t\t${NSD_SetText} $XDirUFO $UFO_DIR\n\t${EndIf}\n\n\t${If} $0 == $XBrowseTFTD\n\t\tnsDialogs::SelectFolderDialog $(SETUP_TFTD_FOLDER) $TFTD_DIR\n\t\tPop $1\n\t\t${If} $1 == error\n\t\t\tReturn\n\t\t${EndIf}\n\t\tStrCpy $TFTD_DIR $1\n\t\t${NSD_SetText} $XDirTFTD $TFTD_DIR\n\t${EndIf}\n\nFunctionEnd\n\n;--------------------------------\n;Languages\n\n\t!include \"language.nsh\"\n\n;--------------------------------\n;Reserve Files\n\n\t;If you are using solid compression, files that are required before\n\t;the actual installation should be stored first in the data block,\n\t;because this will make your installer start faster.\n\n\t!insertmacro MUI_RESERVEFILE_LANGDLL\n\n;--------------------------------\n;Installer Sections\n\nSection \"$(SETUP_GAME)\" SecMain\n\n\tSectionIn RO\n\n\tSetOutPath \"$INSTDIR\"\n\n\tFile \"OpenXcomEx.exe\"\n\t;File \"..\\..\\LICENSE.txt\"\n\t;File \"..\\..\\CHANGELOG.txt\"\n\t;File /oname=README.txt \"..\\..\\README.md\"\n\n\t;Copy UFO files\n\tSetOutPath \"$INSTDIR\\UFO\"\n\n\tStrCmp $UFO_DIR \"\" install_ufo_no 0\n\tIfFileExists \"$UFO_DIR\\*.*\" 0 install_ufo_no\n\n\tCreateDirectory \"$INSTDIR\\UFO\\GEODATA\"\n\tCopyFiles /SILENT \"$UFO_DIR\\GEODATA\\*.*\" \"$INSTDIR\\UFO\\GEODATA\"\n\tCreateDirectory \"$INSTDIR\\UFO\\GEOGRAPH\"\n\tCopyFiles /SILENT \"$UFO_DIR\\GEOGRAPH\\*.*\" \"$INSTDIR\\UFO\\GEOGRAPH\"\n\tCreateDirectory \"$INSTDIR\\UFO\\MAPS\"\n\tCopyFiles /SILENT \"$UFO_DIR\\MAPS\\*.*\" \"$INSTDIR\\UFO\\MAPS\"\n\tCreateDirectory \"$INSTDIR\\UFO\\ROUTES\"\n\tCopyFiles /SILENT \"$UFO_DIR\\ROUTES\\*.*\" \"$INSTDIR\\UFO\\ROUTES\"\n\tCreateDirectory \"$INSTDIR\\UFO\\SOUND\"\n\tCopyFiles /SILENT \"$UFO_DIR\\SOUND\\*.*\" \"$INSTDIR\\UFO\\SOUND\"\n\tCreateDirectory \"$INSTDIR\\UFO\\TERRAIN\"\n\tCopyFiles /SILENT \"$UFO_DIR\\TERRAIN\\*.*\" \"$INSTDIR\\UFO\\TERRAIN\"\n\tCreateDirectory \"$INSTDIR\\UFO\\UFOGRAPH\"\n\tCopyFiles /SILENT \"$UFO_DIR\\UFOGRAPH\\*.*\" \"$INSTDIR\\UFO\\UFOGRAPH\"\n\tCreateDirectory \"$INSTDIR\\UFO\\UFOINTRO\"\n\tCopyFiles /SILENT \"$UFO_DIR\\UFOINTRO\\*.*\" \"$INSTDIR\\UFO\\UFOINTRO\"\n\tCreateDirectory \"$INSTDIR\\UFO\\UNITS\"\n\tCopyFiles /SILENT \"$UFO_DIR\\UNITS\\*.*\" \"$INSTDIR\\UFO\\UNITS\"\n\n\tinstall_ufo_no:\n\tFile \"..\\..\\bin\\UFO\\README.txt\"\n\n\t;Copy TFTD files\n\tSetOutPath \"$INSTDIR\\TFTD\"\n\n\tStrCmp $TFTD_DIR \"\" install_tftd_no 0\n\tIfFileExists \"$TFTD_DIR\\*.*\" 0 install_tftd_no\n\n\tCreateDirectory \"$INSTDIR\\TFTD\\ANIMS\"\n\tCopyFiles /SILENT \"$TFTD_DIR\\ANIMS\\*.*\" \"$INSTDIR\\TFTD\\ANIMS\"\n\tCreateDirectory \"$INSTDIR\\TFTD\\FLOP_INT\"\n\tCopyFiles /SILENT \"$TFTD_DIR\\FLOP_INT\\*.*\" \"$INSTDIR\\TFTD\\FLOP_INT\"\n\tCreateDirectory \"$INSTDIR\\TFTD\\GEODATA\"\n\tCopyFiles /SILENT \"$TFTD_DIR\\GEODATA\\*.*\" \"$INSTDIR\\TFTD\\GEODATA\"\n\tCreateDirectory \"$INSTDIR\\TFTD\\GEOGRAPH\"\n\tCopyFiles /SILENT \"$TFTD_DIR\\GEOGRAPH\\*.*\" \"$INSTDIR\\TFTD\\GEOGRAPH\"\n\tCreateDirectory \"$INSTDIR\\TFTD\\MAPS\"\n\tCopyFiles /SILENT \"$TFTD_DIR\\MAPS\\*.*\" \"$INSTDIR\\TFTD\\MAPS\"\n\tCreateDirectory \"$INSTDIR\\TFTD\\ROUTES\"\n\tCopyFiles /SILENT \"$TFTD_DIR\\ROUTES\\*.*\" \"$INSTDIR\\TFTD\\ROUTES\"\n\tCreateDirectory \"$INSTDIR\\TFTD\\SOUND\"\n\tCopyFiles /SILENT \"$TFTD_DIR\\SOUND\\*.*\" \"$INSTDIR\\TFTD\\SOUND\"\n\tCreateDirectory \"$INSTDIR\\TFTD\\TERRAIN\"\n\tCopyFiles /SILENT \"$TFTD_DIR\\TERRAIN\\*.*\" \"$INSTDIR\\TFTD\\TERRAIN\"\n\tCreateDirectory \"$INSTDIR\\TFTD\\UFOGRAPH\"\n\tCopyFiles /SILENT \"$TFTD_DIR\\UFOGRAPH\\*.*\" \"$INSTDIR\\TFTD\\UFOGRAPH\"\n\tCreateDirectory \"$INSTDIR\\TFTD\\UNITS\"\n\tCopyFiles /SILENT \"$TFTD_DIR\\UNITS\\*.*\" \"$INSTDIR\\TFTD\\UNITS\"\n\n\tinstall_tftd_no:\n\tFile \"..\\..\\bin\\TFTD\\README.txt\"\n\n\tSetOutPath \"$INSTDIR\"\n\n\tFile /r \"..\\..\\bin\\common\"\n\tFile /r \"..\\..\\bin\\standard\"\n\n${If} $PortableMode == ${SF_SELECTED}\n\tCreateDirectory \"$INSTDIR\\user\"\n${EndIf}\n\n\t;Store installation folder\n\tWriteRegStr HKLM \"Software\\${GAME_NAME}\" \"\" $INSTDIR\n\n\t;Write the uninstall keys for Windows\n\tWriteRegStr HKLM \"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\${GAME_NAME}\" \"DisplayName\" \"${GAME_NAME} ${GAME_VERSION}\"\n\tWriteRegStr HKLM \"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\${GAME_NAME}\" \"DisplayIcon\" '\"$INSTDIR\\OpenXcomEx.exe\",0'\n\tWriteRegStr HKLM \"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\${GAME_NAME}\" \"DisplayVersion\" \"${GAME_VERSION}.0\"\n\tWriteRegStr HKLM \"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\${GAME_NAME}\" \"InstallLocation\" \"$INSTDIR\"\n\tWriteRegStr HKLM \"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\${GAME_NAME}\" \"Publisher\" \"${GAME_AUTHOR}\"\n\tWriteRegStr HKLM \"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\${GAME_NAME}\" \"UninstallString\" '\"$INSTDIR\\Uninstall.exe\"'\n\tWriteRegStr HKLM \"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\${GAME_NAME}\" \"URLInfoAbout\" \"https://openxcom.org\"\n\tWriteRegDWORD HKLM \"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\${GAME_NAME}\" \"NoModify\" 1\n\tWriteRegDWORD HKLM \"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\${GAME_NAME}\" \"NoRepair\" 1\n\n\t;Create uninstaller\n\tWriteUninstaller \"$INSTDIR\\Uninstall.exe\"\n\n\t;Create shortcuts\n\tSetOutPath \"$INSTDIR\"\n\n\t!insertmacro MUI_STARTMENU_WRITE_BEGIN Application\n\n\t\tCreateDirectory \"$SMPROGRAMS\\$StartMenuFolder\"\n\t\tCreateShortCut \"$SMPROGRAMS\\$StartMenuFolder\\${GAME_NAME}.lnk\" \"$INSTDIR\\OpenXcomEx.exe\"\n\t\t;CreateShortCut \"$SMPROGRAMS\\$StartMenuFolder\\$(SETUP_SHORTCUT_CHANGELOG).lnk\" \"$INSTDIR\\CHANGELOG.txt\"\n\t\t;CreateShortCut \"$SMPROGRAMS\\$StartMenuFolder\\$(SETUP_SHORTCUT_README).lnk\" \"$INSTDIR\\README.txt\"\n${If} $PortableMode == ${SF_SELECTED}\n\t\tCreateShortCut \"$SMPROGRAMS\\$StartMenuFolder\\$(SETUP_SHORTCUT_USER).lnk\" \"$INSTDIR\\user\"\n${Else}\n\t\tCreateShortCut \"$SMPROGRAMS\\$StartMenuFolder\\$(SETUP_SHORTCUT_USER).lnk\" \"$DOCUMENTS\\OpenXcom\"\n${EndIf}\n\t\tCreateShortCut \"$SMPROGRAMS\\$StartMenuFolder\\$(SETUP_SHORTCUT_UNINSTALL).lnk\" \"$INSTDIR\\Uninstall.exe\"\n\n\t!insertmacro MUI_STARTMENU_WRITE_END\n\nSectionEnd\n\nSection /o \"$(SETUP_PORTABLE)\" SecPortable\n\n\tCreateDirectory \"$INSTDIR\\user\"\n\nSectionEnd\n\nSection /o \"$(SETUP_DESKTOP)\" SecDesktop\n\n\tSetOutPath \"$INSTDIR\"\n\n\tCreateShortCut \"$DESKTOP\\${GAME_NAME}.lnk\" \"$INSTDIR\\OpenXcomEx.exe\"\n\nSectionEnd\n\n;--------------------------------\n;Descriptions\n\n\t;Assign language strings to sections\n\t!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN\n\t\t!insertmacro MUI_DESCRIPTION_TEXT ${SecMain} $(SETUP_GAME_DESC)\n\t\t!insertmacro MUI_DESCRIPTION_TEXT ${SecPortable} $(SETUP_PORTABLE_DESC)\n\t\t!insertmacro MUI_DESCRIPTION_TEXT ${SecDesktop} $(SETUP_DESKTOP_DESC)\n\t!insertmacro MUI_FUNCTION_DESCRIPTION_END\n\n;--------------------------------\n;Installer functions\n\nFunction .onInit\n\n\tStrCpy $StartMenuFolder \"${GAME_NAME}\"\n\tStrCpy $PortableMode 0\n\n\t; Check for existing X-COM installs\n\tStrCpy $UFO_DIR \"\"\n\tStrCpy $TFTD_DIR \"\"\n\n\tCall ScanSteam\n\tCall ScanGOG\n\n\t!insertmacro MUI_LANGDLL_DISPLAY\n\nFunctionEnd\n\nFunction PreDirectory\n\n\tStrCpy $1 \"${SecPortable}\"\n    SectionGetFlags $1 $0\n    IntOp $PortableMode $0 & ${SF_SELECTED}\n\t\n!ifdef NSIS_WIN32_MAKENSIS\n${If} ${RunningX64}\n\tStrCpy $INSTDIR \"$PROGRAMFILES64\\${GAME_NAME}\"\n${Else}\n\tStrCpy $INSTDIR \"$PROGRAMFILES32\\${GAME_NAME}\"\n${EndIf}\n!endif\n${If} $PortableMode == ${SF_SELECTED}\n\tStrCpy $INSTDIR \"C:\\${GAME_NAME}\"\n${EndIf}\n\nFunctionEnd\n\n${StrStr}\nFunction PostDirectory\n\n${If} $PortableMode == ${SF_SELECTED}\n\t;Don't allow Portable Mode in Program Files\n\t${StrStr} $0 $INSTDIR $PROGRAMFILES32\n\tStrCmp $0 \"\" 0 portable_no\n\t${StrStr} $0 $INSTDIR $PROGRAMFILES64\n\tStrCmp $0 \"\" portable_yes portable_no\n\n\tportable_no:\n\tMessageBox MB_ICONSTOP|MB_OK $(SETUP_ERROR_PORTABLE)\n\tAbort\n\n\tportable_yes:\n${EndIf}\n\nFunctionEnd\n\n;--------------------------------\n;Scan Steam for X-COM installations\n${StrLoc}\n${StrTok}\n${StrRep}\n\nFunction ScanSteam\n\n\tReadRegStr $R1 HKLM \"Software\\Valve\\Steam\" \"InstallPath\"\n\tIfErrors steam_done\n\tCall ScanSteamLibrary\n\n\tClearErrors\n\tFileOpen $0 \"$R1\\config\\libraryfolders.vdf\" r\n\tIfErrors steam_read_done\n\tsteam_read_loop:\n\tFileRead $0 $1\n\tIfErrors steam_read_done\n\t${StrLoc} $2 $1 \"path\" \">\"\n\tStrCmp $2 \"\" steam_read_next 0\n\t${StrTok} $R1 $1 '\"' \"3\" \"1\"\n\t${StrRep} $R1 $R1 \"\\\\\" \"\\\"\n\tCall ScanSteamLibrary\n\tsteam_read_next:\n\tGoto steam_read_loop\n\tsteam_read_done:\n\tFileClose $0\n\n\tsteam_done:\n\nFunctionEnd\n\n;--------------------------------\n;Scan a specific Steam Library\n\nFunction ScanSteamLibrary\n\n\tStrCpy $R0 \"$R1\\steamapps\\common\\XCom UFO Defense\\XCOM\"\n\tIfFileExists \"$R0\\*.*\" steam_ufo_yes steam_ufo_no\n\tsteam_ufo_yes:\n\tStrCpy $UFO_DIR $R0\n\tsteam_ufo_no:\n\n\tStrCpy $R0 \"$R1\\steamapps\\common\\X-COM Terror from the Deep\\TFD\"\n\tIfFileExists \"$R0\\*.*\" steam_tftd_yes steam_tftd_no\n\tsteam_tftd_yes:\n\tStrCpy $TFTD_DIR $R0\n\tsteam_tftd_no:\n\nFunctionEnd\n\n;--------------------------------\n;Scan GOG for X-COM installations\n\nFunction ScanGOG\n\n\tReadRegStr $R0 HKLM \"Software\\GOG.com\\Games\\1445250340\" \"PATH\"\n\tIfErrors gog_ufo_no\n\tIfFileExists \"$R0\\*.*\" gog_ufo_yes gog_ufo_no\n\tgog_ufo_yes:\n\tStrCpy $UFO_DIR $R0\n\tgog_ufo_no:\n\n\tReadRegStr $R0 HKLM \"Software\\GOG.com\\Games\\1445249983\" \"PATH\"\n\tIfErrors gog_tftd_no\n\tIfFileExists \"$R0\\*.*\" gog_tftd_yes gog_tftd_no\n\tgog_tftd_yes:\n\tStrCpy $TFTD_DIR $R0\n\tgog_tftd_no:\n\nFunctionEnd\n\n;--------------------------------\n;Validate X-COM folders\n\nFunction ValidateXcom\n\n\t; UFO\n\tStrCmp $UFO_DIR \"\" validate_ufo_yes\n\tIfFileExists \"$UFO_DIR\\GEODATA\\*.*\" 0 confirm_ufo\n\tIfFileExists \"$UFO_DIR\\GEOGRAPH\\*.*\" 0 confirm_ufo\n\tIfFileExists \"$UFO_DIR\\MAPS\\*.*\" 0 confirm_ufo\n\tIfFileExists \"$UFO_DIR\\ROUTES\\*.*\" 0 confirm_ufo\n\tIfFileExists \"$UFO_DIR\\SOUND\\*.*\" 0 confirm_ufo\n\tIfFileExists \"$UFO_DIR\\TERRAIN\\*.*\" 0 confirm_ufo\n\tIfFileExists \"$UFO_DIR\\UFOGRAPH\\*.*\" 0 confirm_ufo\n\tIfFileExists \"$UFO_DIR\\UNITS\\*.*\" 0 confirm_ufo\n\tIfFileExists \"$UFO_DIR\\GEOGRAPH\\UP001.SPK\" 0 confirm_ufo ; unique file\n\tIfFileExists \"$UFO_DIR\\XcuSetup.bat\" confirm_ufo_xcu\n\tGoto validate_ufo_yes\n\tconfirm_ufo:\n\tMessageBox MB_ICONEXCLAMATION|MB_YESNO $(SETUP_WARNING_UFO) /SD IDYES IDYES validate_ufo_yes IDNO validate_ufo_no\n\tconfirm_ufo_xcu:\n\tMessageBox MB_ICONEXCLAMATION|MB_YESNO $(SETUP_WARNING_XCU) /SD IDYES IDYES validate_ufo_yes IDNO validate_ufo_no\n\tvalidate_ufo_no:\n\tAbort\n\tvalidate_ufo_yes:\n\n\t; TFTD\n\tStrCmp $TFTD_DIR \"\" validate_tftd_yes\n\tIfFileExists \"$TFTD_DIR\\GEODATA\\*.*\" 0 confirm_tftd\n\tIfFileExists \"$TFTD_DIR\\GEOGRAPH\\*.*\" 0 confirm_tftd\n\tIfFileExists \"$TFTD_DIR\\MAPS\\*.*\" 0 confirm_tftd\n\tIfFileExists \"$TFTD_DIR\\ROUTES\\*.*\" 0 confirm_tftd\n\tIfFileExists \"$TFTD_DIR\\SOUND\\*.*\" 0 confirm_tftd\n\tIfFileExists \"$TFTD_DIR\\TERRAIN\\*.*\" 0 confirm_tftd\n\tIfFileExists \"$TFTD_DIR\\UFOGRAPH\\*.*\" 0 confirm_tftd\n\tIfFileExists \"$TFTD_DIR\\UNITS\\*.*\" 0 confirm_tftd\n\tIfFileExists \"$TFTD_DIR\\GEOGRAPH\\UP001.BDY\" 0 confirm_tftd ; unique file\n\tIfFileExists \"$TFTD_DIR\\XcuSetup.bat\" confirm_tftd_xcu\n\tGoto validate_tftd_yes\n\tconfirm_tftd:\n\tMessageBox MB_ICONEXCLAMATION|MB_YESNO $(SETUP_WARNING_TFTD) /SD IDYES IDYES validate_tftd_yes IDNO validate_tftd_no\n\tconfirm_tftd_xcu:\n\tMessageBox MB_ICONEXCLAMATION|MB_YESNO $(SETUP_WARNING_XCU) /SD IDYES IDYES validate_tftd_yes IDNO validate_tftd_no\n\tvalidate_tftd_no:\n\tAbort\n\tvalidate_tftd_yes:\n\nFunctionEnd\n\n;--------------------------------\n;Uninstaller Functions\n\nFunction un.onInit\n\n\t!insertmacro MUI_UNGETLANGUAGE\n\nFunctionEnd\n\n;--------------------------------\n;Uninstaller Sections\n\nSection \"un.$(SETUP_UNDATA)\" UnData\n\tRMDir /r \"$INSTDIR\\TFTD\"\n\tRMDir /r \"$INSTDIR\\UFO\"\nSectionEnd\n\nSection /o \"un.$(SETUP_UNUSER)\" UnUser\n\tRMDir /r \"$INSTDIR\\user\"\n\tRMDir /r \"$DOCUMENTS\\OpenXcom\"\nSectionEnd\n\nSection \"-un.Main\"\n\n\tSetOutPath \"$TEMP\"\n\n\tDelete \"$INSTDIR\\OpenXcomEx.exe\"\n\tDelete \"$INSTDIR\\*.dll\"\n\tDelete \"$INSTDIR\\*.txt\"\n\tDelete \"$INSTDIR\\*.md\"\n\n\tRMDir /r \"$INSTDIR\\common\"\n\tRMDir /r \"$INSTDIR\\standard\"\n\n\tDelete \"$INSTDIR\\Uninstall.exe\"\n\tRMDir \"$INSTDIR\"\n\n\t!insertmacro MUI_STARTMENU_GETFOLDER Application $StartMenuFolder\n\n\tDelete \"$SMPROGRAMS\\$StartMenuFolder\\*.*\"\n\tRMDir \"$SMPROGRAMS\\$StartMenuFolder\"\n\n\tDelete \"$DESKTOP\\${GAME_NAME}.lnk\"\n\n\tDeleteRegKey HKLM \"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\${GAME_NAME}\"\n\tDeleteRegKey /ifempty HKLM \"Software\\${GAME_NAME}\"\n\nSectionEnd\n\n;--------------------------------\n;Uninstaller Descriptions\n\n\t;Assign language strings to sections\n\t!insertmacro MUI_UNFUNCTION_DESCRIPTION_BEGIN\n\t\t!insertmacro MUI_DESCRIPTION_TEXT ${UnData} $(SETUP_UNDATA_DESC)\n\t\t!insertmacro MUI_DESCRIPTION_TEXT ${UnUser} $(SETUP_UNUSER_DESC)\n\t!insertmacro MUI_UNFUNCTION_DESCRIPTION_END\n\n;--------------------------------\n;Version Information\n\n\tVIProductVersion \"${GAME_VERSION}.0\"\n\tVIAddVersionKey /LANG=${LANG_ENGLISH} \"ProductName\" \"${GAME_NAME} Installer\"\n\tVIAddVersionKey /LANG=${LANG_ENGLISH} \"ProductVersion\" \"${GAME_VERSION}.0\"\n\tVIAddVersionKey /LANG=${LANG_ENGLISH} \"CompanyName\" \"${GAME_AUTHOR}\"\n\tVIAddVersionKey /LANG=${LANG_ENGLISH} \"LegalCopyright\" \"Copyright 2010-2025 ${GAME_AUTHOR}\"\n\tVIAddVersionKey /LANG=${LANG_ENGLISH} \"FileDescription\" \"${GAME_NAME} Installer\"\n\tVIAddVersionKey /LANG=${LANG_ENGLISH} \"FileVersion\" \"${GAME_VERSION}.0\"\n"
  },
  {
    "path": "install/win/language.nsh",
    "content": "!insertmacro MUI_LANGUAGE \"English\"\n!insertmacro LANGFILE_INCLUDE \"Language\\English.nsh\"\n!insertmacro MUI_LANGUAGE \"Bulgarian\"\n!insertmacro LANGFILE_INCLUDE \"Language\\Bulgarian.nsh\"\n!insertmacro MUI_LANGUAGE \"Catalan\"\n!insertmacro LANGFILE_INCLUDE \"Language\\Catalan.nsh\"\n!insertmacro MUI_LANGUAGE \"Czech\"\n!insertmacro LANGFILE_INCLUDE \"Language\\Czech.nsh\"\n!insertmacro MUI_LANGUAGE \"Danish\"\n!insertmacro LANGFILE_INCLUDE \"Language\\Danish.nsh\"\n!insertmacro MUI_LANGUAGE \"German\"\n!insertmacro LANGFILE_INCLUDE \"Language\\German.nsh\"\n!insertmacro MUI_LANGUAGE \"Greek\"\n!insertmacro LANGFILE_INCLUDE \"Language\\Greek.nsh\"\n!insertmacro MUI_LANGUAGE \"SpanishInternational\"\n!insertmacro LANGFILE_INCLUDE \"Language\\SpanishInternational.nsh\"\n!insertmacro MUI_LANGUAGE \"Spanish\"\n!insertmacro LANGFILE_INCLUDE \"Language\\Spanish.nsh\"\n!insertmacro MUI_LANGUAGE \"Estonian\"\n!insertmacro LANGFILE_INCLUDE \"Language\\Estonian.nsh\"\n!insertmacro MUI_LANGUAGE \"Finnish\"\n!insertmacro LANGFILE_INCLUDE \"Language\\Finnish.nsh\"\n!insertmacro MUI_LANGUAGE \"French\"\n!insertmacro LANGFILE_INCLUDE \"Language\\French.nsh\"\n!insertmacro MUI_LANGUAGE \"Croatian\"\n!insertmacro LANGFILE_INCLUDE \"Language\\Croatian.nsh\"\n!insertmacro MUI_LANGUAGE \"Hungarian\"\n!insertmacro LANGFILE_INCLUDE \"Language\\Hungarian.nsh\"\n!insertmacro MUI_LANGUAGE \"Icelandic\"\n!insertmacro LANGFILE_INCLUDE \"Language\\Icelandic.nsh\"\n!insertmacro MUI_LANGUAGE \"Italian\"\n!insertmacro LANGFILE_INCLUDE \"Language\\Italian.nsh\"\n!insertmacro MUI_LANGUAGE \"Japanese\"\n!insertmacro LANGFILE_INCLUDE \"Language\\Japanese.nsh\"\n!insertmacro MUI_LANGUAGE \"Korean\"\n!insertmacro LANGFILE_INCLUDE \"Language\\Korean.nsh\"\n!insertmacro MUI_LANGUAGE \"Luxembourgish\"\n!insertmacro LANGFILE_INCLUDE \"Language\\Luxembourgish.nsh\"\n!insertmacro MUI_LANGUAGE \"Dutch\"\n!insertmacro LANGFILE_INCLUDE \"Language\\Dutch.nsh\"\n!insertmacro MUI_LANGUAGE \"Polish\"\n!insertmacro LANGFILE_INCLUDE \"Language\\Polish.nsh\"\n!insertmacro MUI_LANGUAGE \"PortugueseBR\"\n!insertmacro LANGFILE_INCLUDE \"Language\\PortugueseBR.nsh\"\n!insertmacro MUI_LANGUAGE \"Portuguese\"\n!insertmacro LANGFILE_INCLUDE \"Language\\Portuguese.nsh\"\n!insertmacro MUI_LANGUAGE \"Romanian\"\n!insertmacro LANGFILE_INCLUDE \"Language\\Romanian.nsh\"\n!insertmacro MUI_LANGUAGE \"Russian\"\n!insertmacro LANGFILE_INCLUDE \"Language\\Russian.nsh\"\n!insertmacro MUI_LANGUAGE \"Slovak\"\n!insertmacro LANGFILE_INCLUDE \"Language\\Slovak.nsh\"\n!insertmacro MUI_LANGUAGE \"Swedish\"\n!insertmacro LANGFILE_INCLUDE \"Language\\Swedish.nsh\"\n!insertmacro MUI_LANGUAGE \"Turkish\"\n!insertmacro LANGFILE_INCLUDE \"Language\\Turkish.nsh\"\n!insertmacro MUI_LANGUAGE \"Ukrainian\"\n!insertmacro LANGFILE_INCLUDE \"Language\\Ukrainian.nsh\"\n!insertmacro MUI_LANGUAGE \"SimpChinese\"\n!insertmacro LANGFILE_INCLUDE \"Language\\SimpChinese.nsh\"\n!insertmacro MUI_LANGUAGE \"TradChinese\"\n!insertmacro LANGFILE_INCLUDE \"Language\\TradChinese.nsh\"\n"
  },
  {
    "path": "install/win/version.nsh",
    "content": "!define GAME_VERSION_GIT \"\"\n!define GAME_DATE_GIT \"\""
  },
  {
    "path": "libs/miniz/ChangeLog.md",
    "content": "## Changelog\n\n### 2.0.8\n\n - Remove unimplemented functions (mz_zip_locate_file and mz_zip_locate_file_v2)\n - Add license, changelog, readme and example files to release zip\n - Fix heap overflow to user buffer in tinfl_status tinfl_decompress\n - Fix corrupt archive if uncompressed file smaller than 4 byte and file is added by mz_zip_writer_add_mem*\n\n### 2.0.7\n\n - Removed need in C++ compiler in cmake build\n - Fixed loads of uninitilized value errors found with Valgrind by memsetting m_dict to 0 in tdefl_init.\n - Fix resource leak in mz_zip_reader_init_file_v2\n - Fix assert with mz_zip_writer_add_mem* w/MZ_DEFAULT_COMPRESSION\n - cmake build: install library and headers\n - Remove _LARGEFILE64_SOURCE requirement from apple defines for large files\n\n### 2.0.6\n\n - Improve MZ_ZIP_FLAG_WRITE_ZIP64 documentation\n - Remove check for cur_archive_file_ofs > UINT_MAX, because cur_archive_file_ofs is not used after this point\n - Add cmake debug configuration\n - Fix PNG height when creating png files\n - Add \"iterative\" file extraction method based on mz_zip_reader_extract_to_callback.\n - Option to use memcpy for unaligned data access\n - Define processor/arch macros as zero if not set to one\n\n### 2.0.4/2.0.5\n\n - Fix compilation with the various omission compile definitions\n\n### 2.0.3\n\n- Fix GCC/clang compile warnings\n- Added callback for periodic flushes (for ZIP file streaming)\n- Use UTF-8 for file names in ZIP files per default\n\n### 2.0.2\n\n- Fix source backwards compatibility with 1.x\n- Fix a ZIP bit not being set correctly\n\n### 2.0.1\n\n- Added some tests\n- Added CI\n- Make source code ANSI C compatible\n\n### 2.0.0 beta\n\n- Matthew Sitton merged to vogl ZIP64 changes. Miniz is now licensed as MIT since the vogl code base is MIT licensed\n- Miniz is now split into several files\n- Miniz does now not seek backwards when creating ZIP files. That is the ZIP files can be streamed\n- Miniz automatically switches to the ZIP64 format the created ZIP files goes over ZIP file limits\n- Similar to [SQLite](https://www.sqlite.org/amalgamation.html) the Miniz source code is amalgamated into one miniz.c/miniz.h pair in a build step (amalgamate.sh). Please use miniz.c/miniz.h in your projects\n\n### v1.16 BETA Oct 19, 2013\n\nStill testing, this release is downloadable from [here](http://www.tenacioussoftware.com/miniz_v116_beta_r1.7z). Two key inflator-only robustness and streaming related changes. Also merged in tdefl_compressor_alloc(), tdefl_compressor_free() helpers to make script bindings easier for rustyzip. I would greatly appreciate any help with testing or any feedback.\n\nThe inflator in raw (non-zlib) mode is now usable on gzip or similar streams that have a bunch of bytes following the raw deflate data (problem discovered by rustyzip author williamw520). This version should never read beyond the last byte of the raw deflate data independent of how many bytes you pass into the input buffer.\n\nThe inflator now has a new failure status TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS (-4). Previously, if the inflator was starved of bytes and could not make progress (because the input buffer was empty and the caller did not set the TINFL_FLAG_HAS_MORE_INPUT flag - say on truncated or corrupted compressed data stream) it would append all 0's to the input and try to soldier on. This is scary behavior if the caller didn't know when to stop accepting output (because it didn't know how much uncompressed data was expected, or didn't enforce a sane maximum). v1.16 will instead return TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS immediately if it needs 1 or more bytes to make progress, the input buf is empty, and the caller has indicated that no more input is available. This is a \"soft\" failure, so you can call the inflator again with more input and it will try to continue, or you can give up and fail. This could be very useful in network streaming scenarios.\n\n- The inflator coroutine func. is subtle and complex so I'm being cautious about this release. I would greatly appreciate any help with testing or any feedback.\n         I feel good about these changes, and they've been through several hours of automated testing, but they will probably not fix anything for the majority of prev. users so I'm\n         going to mark this release as beta for a few weeks and continue testing it at work/home on various things.\n- The inflator in raw (non-zlib) mode is now usable on gzip or similiar data streams that have a bunch of bytes following the raw deflate data (problem discovered by rustyzip author williamw520).\n         This version should *never* read beyond the last byte of the raw deflate data independent of how many bytes you pass into the input buffer. This issue was caused by the various Huffman bitbuffer lookahead optimizations, and\n         would not be an issue if the caller knew and enforced the precise size of the raw compressed data *or* if the compressed data was in zlib format (i.e. always followed by the byte aligned zlib adler32).\n         So in other words, you can now call the inflator on deflate streams that are followed by arbitrary amounts of data and it's guaranteed that decompression will stop exactly on the last byte.\n- The inflator now has a new failure status: TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS (-4). Previously, if the inflator was starved of bytes and could not make progress (because the input buffer was empty and the\n         caller did not set the TINFL_FLAG_HAS_MORE_INPUT flag - say on truncated or corrupted compressed data stream) it would append all 0's to the input and try to soldier on.\n         This is scary, because in the worst case, I believe it was possible for the prev. inflator to start outputting large amounts of literal data. If the caller didn't know when to stop accepting output\n         (because it didn't know how much uncompressed data was expected, or didn't enforce a sane maximum) it could continue forever. v1.16 cannot fall into this failure mode, instead it'll return\n         TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS immediately if it needs 1 or more bytes to make progress, the input buf is empty, and the caller has indicated that no more input is available. This is a \"soft\"\n         failure, so you can call the inflator again with more input and it will try to continue, or you can give up and fail. This could be very useful in network streaming scenarios.\n- Added documentation to all the tinfl return status codes, fixed miniz_tester so it accepts double minus params for Linux, tweaked example1.c, added a simple \"follower bytes\" test to miniz_tester.cpp.\n### v1.15 r4 STABLE - Oct 13, 2013\n\nMerged over a few very minor bug fixes that I fixed in the zip64 branch. This is downloadable from [here](http://code.google.com/p/miniz/downloads/list) and also in SVN head (as of 10/19/13).\n\n\n### v1.15 - Oct. 13, 2013\n\nInterim bugfix release while I work on the next major release with zip64 and streaming compression/decompression support. Fixed the MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY bug (thanks kahmyong.moon@hp.com), which could cause the locate files func to not find files when this flag was specified. Also fixed a bug in mz_zip_reader_extract_to_mem_no_alloc() with user provided read buffers (thanks kymoon). I also merged lots of compiler fixes from various github repo branches and Google Code issue reports. I finally added cmake support (only tested under for Linux so far), compiled and tested with clang v3.3 and gcc 4.6 (under Linux), added defl_write_image_to_png_file_in_memory_ex() (supports Y flipping for OpenGL use, real-time compression), added a new PNG example (example6.c - Mandelbrot), and I added 64-bit file I/O support (stat64(), etc.) for glibc.\n\n- Critical fix for the MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY bug (thanks kahmyong.moon@hp.com) which could cause locate files to not find files. This bug\n        would only have occured in earlier versions if you explicitly used this flag, OR if you used mz_zip_extract_archive_file_to_heap() or mz_zip_add_mem_to_archive_file_in_place()\n        (which used this flag). If you can't switch to v1.15 but want to fix this bug, just remove the uses of this flag from both helper funcs (and of course don't use the flag).\n- Bugfix in mz_zip_reader_extract_to_mem_no_alloc() from kymoon when pUser_read_buf is not NULL and compressed size is > uncompressed size\n- Fixing mz_zip_reader_extract_*() funcs so they don't try to extract compressed data from directory entries, to account for weird zipfiles which contain zero-size compressed data on dir entries.\n         Hopefully this fix won't cause any issues on weird zip archives, because it assumes the low 16-bits of zip external attributes are DOS attributes (which I believe they always are in practice).\n- Fixing mz_zip_reader_is_file_a_directory() so it doesn't check the internal attributes, just the filename and external attributes\n- mz_zip_reader_init_file() - missing MZ_FCLOSE() call if the seek failed\n- Added cmake support for Linux builds which builds all the examples, tested with clang v3.3 and gcc v4.6.\n- Clang fix for tdefl_write_image_to_png_file_in_memory() from toffaletti\n- Merged MZ_FORCEINLINE fix from hdeanclark\n- Fix <time.h> include before config #ifdef, thanks emil.brink\n- Added tdefl_write_image_to_png_file_in_memory_ex(): supports Y flipping (super useful for OpenGL apps), and explicit control over the compression level (so you can\n        set it to 1 for real-time compression).\n- Merged in some compiler fixes from paulharris's github repro.\n- Retested this build under Windows (VS 2010, including static analysis), tcc  0.9.26, gcc v4.6 and clang v3.3.\n- Added example6.c, which dumps an image of the mandelbrot set to a PNG file.\n- Modified example2 to help test the MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY flag more.\n- In r3: Bugfix to mz_zip_writer_add_file() found during merge: Fix possible src file fclose() leak if alignment bytes+local header file write faiiled\n- In r4: Minor bugfix to mz_zip_writer_add_from_zip_reader(): Was pushing the wrong central dir header offset, appears harmless in this release, but it became a problem in the zip64 branch\n\n### v1.14 - May 20, 2012\n\n(SVN Only) Minor tweaks to get miniz.c compiling with the Tiny C Compiler, added #ifndef MINIZ_NO_TIME guards around utime.h includes. Adding mz_free() function, so the caller can free heap blocks returned by miniz using whatever heap functions it has been configured to use, MSVC specific fixes to use \"safe\" variants of several functions (localtime_s, fopen_s, freopen_s).\n\nMinGW32/64 GCC 4.6.1 compiler fixes: added MZ_FORCEINLINE, #include <time.h> (thanks fermtect).\n\nCompiler specific fixes, some from fermtect. I upgraded to TDM GCC 4.6.1 and now static __forceinline is giving it fits, so I'm changing all usage of __forceinline to MZ_FORCEINLINE and forcing gcc to use __attribute__((__always_inline__)) (and MSVC to use __forceinline). Also various fixes from fermtect for MinGW32: added #include , 64-bit ftell/fseek fixes.\n\n### v1.13 - May 19, 2012\n\nFrom jason@cornsyrup.org and kelwert@mtu.edu - Most importantly, fixed mz_crc32() so it doesn't compute the wrong CRC-32's when mz_ulong is 64-bits. Temporarily/locally slammed in \"typedef unsigned long mz_ulong\" and re-ran a randomized regression test on ~500k files. Other stuff:\n\nEliminated a bunch of warnings when compiling with GCC 32-bit/64. Ran all examples, miniz.c, and tinfl.c through MSVC 2008's /analyze (static analysis) option and fixed all warnings (except for the silly \"Use of the comma-operator in a tested expression..\" analysis warning, which I purposely use to work around a MSVC compiler warning).\n\nCreated 32-bit and 64-bit Codeblocks projects/workspace. Built and tested Linux executables. The codeblocks workspace is compatible with Linux+Win32/x64. Added miniz_tester solution/project, which is a useful little app derived from LZHAM's tester app that I use as part of the regression test. Ran miniz.c and tinfl.c through another series of regression testing on ~500,000 files and archives. Modified example5.c so it purposely disables a bunch of high-level functionality (MINIZ_NO_STDIO, etc.). (Thanks to corysama for the MINIZ_NO_STDIO bug report.)\n\nFix ftell() usage in a few of the examples so they exit with an error on files which are too large (a limitation of the examples, not miniz itself). Fix fail logic handling in mz_zip_add_mem_to_archive_file_in_place() so it always calls mz_zip_writer_finalize_archive() and mz_zip_writer_end(), even if the file add fails.\n\n- From jason@cornsyrup.org and kelwert@mtu.edu - Fix mz_crc32() so it doesn't compute the wrong CRC-32's when mz_ulong is 64-bit.\n- Temporarily/locally slammed in \"typedef unsigned long mz_ulong\" and re-ran a randomized regression test on ~500k files.\n- Eliminated a bunch of warnings when compiling with GCC 32-bit/64.\n- Ran all examples, miniz.c, and tinfl.c through MSVC 2008's /analyze (static analysis) option and fixed all warnings (except for the silly\n\"Use of the comma-operator in a tested expression..\" analysis warning, which I purposely use to work around a MSVC compiler warning).\n- Created 32-bit and 64-bit Codeblocks projects/workspace. Built and tested Linux executables. The codeblocks workspace is compatible with Linux+Win32/x64.\n- Added miniz_tester solution/project, which is a useful little app derived from LZHAM's tester app that I use as part of the regression test.\n- Ran miniz.c and tinfl.c through another series of regression testing on ~500,000 files and archives.\n- Modified example5.c so it purposely disables a bunch of high-level functionality (MINIZ_NO_STDIO, etc.). (Thanks to corysama for the MINIZ_NO_STDIO bug report.)\n- Fix ftell() usage in examples so they exit with an error on files which are too large (a limitation of the examples, not miniz itself).\n\n### v1.12 - 4/12/12\n\nMore comments, added low-level example5.c, fixed a couple minor level_and_flags issues in the archive API's.\nlevel_and_flags can now be set to MZ_DEFAULT_COMPRESSION. Thanks to Bruce Dawson <bruced@valvesoftware.com> for the feedback/bug report.\n\n### v1.11 - 5/28/11\n\nAdded statement from unlicense.org\n\n### v1.10 - 5/27/11\n\n- Substantial compressor optimizations:\n- Level 1 is now ~4x faster than before. The L1 compressor's throughput now varies between 70-110MB/sec. on a Core i7 (actual throughput varies depending on the type of data, and x64 vs. x86).\n- Improved baseline L2-L9 compression perf. Also, greatly improved compression perf. issues on some file types.\n- Refactored the compression code for better readability and maintainability.\n- Added level 10 compression level (L10 has slightly better ratio than level 9, but could have a potentially large drop in throughput on some files).\n\n### v1.09 - 5/15/11\n\nInitial stable release.\n\n\n"
  },
  {
    "path": "libs/miniz/LICENSE",
    "content": "Copyright 2013-2014 RAD Game Tools and Valve Software\nCopyright 2010-2014 Rich Geldreich and Tenacious Software LLC\n\nAll Rights Reserved.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "libs/miniz/miniz.c",
    "content": "/**************************************************************************\n *\n * Copyright 2013-2014 RAD Game Tools and Valve Software\n * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC\n * All Rights Reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n **************************************************************************/\n\n#include  \"miniz.h\"\n\ntypedef unsigned char mz_validate_uint16[sizeof(mz_uint16) == 2 ? 1 : -1];\ntypedef unsigned char mz_validate_uint32[sizeof(mz_uint32) == 4 ? 1 : -1];\ntypedef unsigned char mz_validate_uint64[sizeof(mz_uint64) == 8 ? 1 : -1];\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* ------------------- zlib-style API's */\n\nmz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len)\n{\n    mz_uint32 i, s1 = (mz_uint32)(adler & 0xffff), s2 = (mz_uint32)(adler >> 16);\n    size_t block_len = buf_len % 5552;\n    if (!ptr)\n        return MZ_ADLER32_INIT;\n    while (buf_len)\n    {\n        for (i = 0; i + 7 < block_len; i += 8, ptr += 8)\n        {\n            s1 += ptr[0], s2 += s1;\n            s1 += ptr[1], s2 += s1;\n            s1 += ptr[2], s2 += s1;\n            s1 += ptr[3], s2 += s1;\n            s1 += ptr[4], s2 += s1;\n            s1 += ptr[5], s2 += s1;\n            s1 += ptr[6], s2 += s1;\n            s1 += ptr[7], s2 += s1;\n        }\n        for (; i < block_len; ++i)\n            s1 += *ptr++, s2 += s1;\n        s1 %= 65521U, s2 %= 65521U;\n        buf_len -= block_len;\n        block_len = 5552;\n    }\n    return (s2 << 16) + s1;\n}\n\n/* Karl Malbrain's compact CRC-32. See \"A compact CCITT crc16 and crc32 C implementation that balances processor cache usage against speed\": http://www.geocities.com/malbrain/ */\n#if 0\n    mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len)\n    {\n        static const mz_uint32 s_crc32[16] = { 0, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,\n                                               0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c };\n        mz_uint32 crcu32 = (mz_uint32)crc;\n        if (!ptr)\n            return MZ_CRC32_INIT;\n        crcu32 = ~crcu32;\n        while (buf_len--)\n        {\n            mz_uint8 b = *ptr++;\n            crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b & 0xF)];\n            crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b >> 4)];\n        }\n        return ~crcu32;\n    }\n#else\n/* Faster, but larger CPU cache footprint.\n */\nmz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len)\n{\n    static const mz_uint32 s_crc_table[256] =\n        {\n          0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535,\n          0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD,\n          0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D,\n          0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,\n          0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4,\n          0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,\n          0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC,\n          0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,\n          0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB,\n          0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F,\n          0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB,\n          0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,\n          0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA,\n          0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE,\n          0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A,\n          0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,\n          0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409,\n          0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,\n          0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739,\n          0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,\n          0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268,\n          0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0,\n          0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8,\n          0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,\n          0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF,\n          0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703,\n          0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7,\n          0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,\n          0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE,\n          0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,\n          0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6,\n          0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,\n          0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D,\n          0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5,\n          0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605,\n          0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,\n          0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D\n        };\n\n    mz_uint32 crc32 = (mz_uint32)crc ^ 0xFFFFFFFF;\n    const mz_uint8 *pByte_buf = (const mz_uint8 *)ptr;\n\n    while (buf_len >= 4)\n    {\n        crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[0]) & 0xFF];\n        crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[1]) & 0xFF];\n        crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[2]) & 0xFF];\n        crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[3]) & 0xFF];\n        pByte_buf += 4;\n        buf_len -= 4;\n    }\n\n    while (buf_len)\n    {\n        crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[0]) & 0xFF];\n        ++pByte_buf;\n        --buf_len;\n    }\n\n    return ~crc32;\n}\n#endif\n\nvoid mz_free(void *p)\n{\n    MZ_FREE(p);\n}\n\nvoid *miniz_def_alloc_func(void *opaque, size_t items, size_t size)\n{\n    (void)opaque, (void)items, (void)size;\n    return MZ_MALLOC(items * size);\n}\nvoid miniz_def_free_func(void *opaque, void *address)\n{\n    (void)opaque, (void)address;\n    MZ_FREE(address);\n}\nvoid *miniz_def_realloc_func(void *opaque, void *address, size_t items, size_t size)\n{\n    (void)opaque, (void)address, (void)items, (void)size;\n    return MZ_REALLOC(address, items * size);\n}\n\nconst char *mz_version(void)\n{\n    return MZ_VERSION;\n}\n\n#ifndef MINIZ_NO_ZLIB_APIS\n\nint mz_deflateInit(mz_streamp pStream, int level)\n{\n    return mz_deflateInit2(pStream, level, MZ_DEFLATED, MZ_DEFAULT_WINDOW_BITS, 9, MZ_DEFAULT_STRATEGY);\n}\n\nint mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy)\n{\n    tdefl_compressor *pComp;\n    mz_uint comp_flags = TDEFL_COMPUTE_ADLER32 | tdefl_create_comp_flags_from_zip_params(level, window_bits, strategy);\n\n    if (!pStream)\n        return MZ_STREAM_ERROR;\n    if ((method != MZ_DEFLATED) || ((mem_level < 1) || (mem_level > 9)) || ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS)))\n        return MZ_PARAM_ERROR;\n\n    pStream->data_type = 0;\n    pStream->adler = MZ_ADLER32_INIT;\n    pStream->msg = NULL;\n    pStream->reserved = 0;\n    pStream->total_in = 0;\n    pStream->total_out = 0;\n    if (!pStream->zalloc)\n        pStream->zalloc = miniz_def_alloc_func;\n    if (!pStream->zfree)\n        pStream->zfree = miniz_def_free_func;\n\n    pComp = (tdefl_compressor *)pStream->zalloc(pStream->opaque, 1, sizeof(tdefl_compressor));\n    if (!pComp)\n        return MZ_MEM_ERROR;\n\n    pStream->state = (struct mz_internal_state *)pComp;\n\n    if (tdefl_init(pComp, NULL, NULL, comp_flags) != TDEFL_STATUS_OKAY)\n    {\n        mz_deflateEnd(pStream);\n        return MZ_PARAM_ERROR;\n    }\n\n    return MZ_OK;\n}\n\nint mz_deflateReset(mz_streamp pStream)\n{\n    if ((!pStream) || (!pStream->state) || (!pStream->zalloc) || (!pStream->zfree))\n        return MZ_STREAM_ERROR;\n    pStream->total_in = pStream->total_out = 0;\n    tdefl_init((tdefl_compressor *)pStream->state, NULL, NULL, ((tdefl_compressor *)pStream->state)->m_flags);\n    return MZ_OK;\n}\n\nint mz_deflate(mz_streamp pStream, int flush)\n{\n    size_t in_bytes, out_bytes;\n    mz_ulong orig_total_in, orig_total_out;\n    int mz_status = MZ_OK;\n\n    if ((!pStream) || (!pStream->state) || (flush < 0) || (flush > MZ_FINISH) || (!pStream->next_out))\n        return MZ_STREAM_ERROR;\n    if (!pStream->avail_out)\n        return MZ_BUF_ERROR;\n\n    if (flush == MZ_PARTIAL_FLUSH)\n        flush = MZ_SYNC_FLUSH;\n\n    if (((tdefl_compressor *)pStream->state)->m_prev_return_status == TDEFL_STATUS_DONE)\n        return (flush == MZ_FINISH) ? MZ_STREAM_END : MZ_BUF_ERROR;\n\n    orig_total_in = pStream->total_in;\n    orig_total_out = pStream->total_out;\n    for (;;)\n    {\n        tdefl_status defl_status;\n        in_bytes = pStream->avail_in;\n        out_bytes = pStream->avail_out;\n\n        defl_status = tdefl_compress((tdefl_compressor *)pStream->state, pStream->next_in, &in_bytes, pStream->next_out, &out_bytes, (tdefl_flush)flush);\n        pStream->next_in += (mz_uint)in_bytes;\n        pStream->avail_in -= (mz_uint)in_bytes;\n        pStream->total_in += (mz_uint)in_bytes;\n        pStream->adler = tdefl_get_adler32((tdefl_compressor *)pStream->state);\n\n        pStream->next_out += (mz_uint)out_bytes;\n        pStream->avail_out -= (mz_uint)out_bytes;\n        pStream->total_out += (mz_uint)out_bytes;\n\n        if (defl_status < 0)\n        {\n            mz_status = MZ_STREAM_ERROR;\n            break;\n        }\n        else if (defl_status == TDEFL_STATUS_DONE)\n        {\n            mz_status = MZ_STREAM_END;\n            break;\n        }\n        else if (!pStream->avail_out)\n            break;\n        else if ((!pStream->avail_in) && (flush != MZ_FINISH))\n        {\n            if ((flush) || (pStream->total_in != orig_total_in) || (pStream->total_out != orig_total_out))\n                break;\n            return MZ_BUF_ERROR; /* Can't make forward progress without some input.\n */\n        }\n    }\n    return mz_status;\n}\n\nint mz_deflateEnd(mz_streamp pStream)\n{\n    if (!pStream)\n        return MZ_STREAM_ERROR;\n    if (pStream->state)\n    {\n        pStream->zfree(pStream->opaque, pStream->state);\n        pStream->state = NULL;\n    }\n    return MZ_OK;\n}\n\nmz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len)\n{\n    (void)pStream;\n    /* This is really over conservative. (And lame, but it's actually pretty tricky to compute a true upper bound given the way tdefl's blocking works.) */\n    return MZ_MAX(128 + (source_len * 110) / 100, 128 + source_len + ((source_len / (31 * 1024)) + 1) * 5);\n}\n\nint mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level)\n{\n    int status;\n    mz_stream stream;\n    memset(&stream, 0, sizeof(stream));\n\n    /* In case mz_ulong is 64-bits (argh I hate longs). */\n    if ((source_len | *pDest_len) > 0xFFFFFFFFU)\n        return MZ_PARAM_ERROR;\n\n    stream.next_in = pSource;\n    stream.avail_in = (mz_uint32)source_len;\n    stream.next_out = pDest;\n    stream.avail_out = (mz_uint32)*pDest_len;\n\n    status = mz_deflateInit(&stream, level);\n    if (status != MZ_OK)\n        return status;\n\n    status = mz_deflate(&stream, MZ_FINISH);\n    if (status != MZ_STREAM_END)\n    {\n        mz_deflateEnd(&stream);\n        return (status == MZ_OK) ? MZ_BUF_ERROR : status;\n    }\n\n    *pDest_len = stream.total_out;\n    return mz_deflateEnd(&stream);\n}\n\nint mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len)\n{\n    return mz_compress2(pDest, pDest_len, pSource, source_len, MZ_DEFAULT_COMPRESSION);\n}\n\nmz_ulong mz_compressBound(mz_ulong source_len)\n{\n    return mz_deflateBound(NULL, source_len);\n}\n\ntypedef struct\n{\n    tinfl_decompressor m_decomp;\n    mz_uint m_dict_ofs, m_dict_avail, m_first_call, m_has_flushed;\n    int m_window_bits;\n    mz_uint8 m_dict[TINFL_LZ_DICT_SIZE];\n    tinfl_status m_last_status;\n} inflate_state;\n\nint mz_inflateInit2(mz_streamp pStream, int window_bits)\n{\n    inflate_state *pDecomp;\n    if (!pStream)\n        return MZ_STREAM_ERROR;\n    if ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS))\n        return MZ_PARAM_ERROR;\n\n    pStream->data_type = 0;\n    pStream->adler = 0;\n    pStream->msg = NULL;\n    pStream->total_in = 0;\n    pStream->total_out = 0;\n    pStream->reserved = 0;\n    if (!pStream->zalloc)\n        pStream->zalloc = miniz_def_alloc_func;\n    if (!pStream->zfree)\n        pStream->zfree = miniz_def_free_func;\n\n    pDecomp = (inflate_state *)pStream->zalloc(pStream->opaque, 1, sizeof(inflate_state));\n    if (!pDecomp)\n        return MZ_MEM_ERROR;\n\n    pStream->state = (struct mz_internal_state *)pDecomp;\n\n    tinfl_init(&pDecomp->m_decomp);\n    pDecomp->m_dict_ofs = 0;\n    pDecomp->m_dict_avail = 0;\n    pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT;\n    pDecomp->m_first_call = 1;\n    pDecomp->m_has_flushed = 0;\n    pDecomp->m_window_bits = window_bits;\n\n    return MZ_OK;\n}\n\nint mz_inflateInit(mz_streamp pStream)\n{\n    return mz_inflateInit2(pStream, MZ_DEFAULT_WINDOW_BITS);\n}\n\nint mz_inflate(mz_streamp pStream, int flush)\n{\n    inflate_state *pState;\n    mz_uint n, first_call, decomp_flags = TINFL_FLAG_COMPUTE_ADLER32;\n    size_t in_bytes, out_bytes, orig_avail_in;\n    tinfl_status status;\n\n    if ((!pStream) || (!pStream->state))\n        return MZ_STREAM_ERROR;\n    if (flush == MZ_PARTIAL_FLUSH)\n        flush = MZ_SYNC_FLUSH;\n    if ((flush) && (flush != MZ_SYNC_FLUSH) && (flush != MZ_FINISH))\n        return MZ_STREAM_ERROR;\n\n    pState = (inflate_state *)pStream->state;\n    if (pState->m_window_bits > 0)\n        decomp_flags |= TINFL_FLAG_PARSE_ZLIB_HEADER;\n    orig_avail_in = pStream->avail_in;\n\n    first_call = pState->m_first_call;\n    pState->m_first_call = 0;\n    if (pState->m_last_status < 0)\n        return MZ_DATA_ERROR;\n\n    if (pState->m_has_flushed && (flush != MZ_FINISH))\n        return MZ_STREAM_ERROR;\n    pState->m_has_flushed |= (flush == MZ_FINISH);\n\n    if ((flush == MZ_FINISH) && (first_call))\n    {\n        /* MZ_FINISH on the first call implies that the input and output buffers are large enough to hold the entire compressed/decompressed file. */\n        decomp_flags |= TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF;\n        in_bytes = pStream->avail_in;\n        out_bytes = pStream->avail_out;\n        status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pStream->next_out, pStream->next_out, &out_bytes, decomp_flags);\n        pState->m_last_status = status;\n        pStream->next_in += (mz_uint)in_bytes;\n        pStream->avail_in -= (mz_uint)in_bytes;\n        pStream->total_in += (mz_uint)in_bytes;\n        pStream->adler = tinfl_get_adler32(&pState->m_decomp);\n        pStream->next_out += (mz_uint)out_bytes;\n        pStream->avail_out -= (mz_uint)out_bytes;\n        pStream->total_out += (mz_uint)out_bytes;\n\n        if (status < 0)\n            return MZ_DATA_ERROR;\n        else if (status != TINFL_STATUS_DONE)\n        {\n            pState->m_last_status = TINFL_STATUS_FAILED;\n            return MZ_BUF_ERROR;\n        }\n        return MZ_STREAM_END;\n    }\n    /* flush != MZ_FINISH then we must assume there's more input. */\n    if (flush != MZ_FINISH)\n        decomp_flags |= TINFL_FLAG_HAS_MORE_INPUT;\n\n    if (pState->m_dict_avail)\n    {\n        n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);\n        memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);\n        pStream->next_out += n;\n        pStream->avail_out -= n;\n        pStream->total_out += n;\n        pState->m_dict_avail -= n;\n        pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);\n        return ((pState->m_last_status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK;\n    }\n\n    for (;;)\n    {\n        in_bytes = pStream->avail_in;\n        out_bytes = TINFL_LZ_DICT_SIZE - pState->m_dict_ofs;\n\n        status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pState->m_dict, pState->m_dict + pState->m_dict_ofs, &out_bytes, decomp_flags);\n        pState->m_last_status = status;\n\n        pStream->next_in += (mz_uint)in_bytes;\n        pStream->avail_in -= (mz_uint)in_bytes;\n        pStream->total_in += (mz_uint)in_bytes;\n        pStream->adler = tinfl_get_adler32(&pState->m_decomp);\n\n        pState->m_dict_avail = (mz_uint)out_bytes;\n\n        n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);\n        memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);\n        pStream->next_out += n;\n        pStream->avail_out -= n;\n        pStream->total_out += n;\n        pState->m_dict_avail -= n;\n        pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);\n\n        if (status < 0)\n            return MZ_DATA_ERROR; /* Stream is corrupted (there could be some uncompressed data left in the output dictionary - oh well). */\n        else if ((status == TINFL_STATUS_NEEDS_MORE_INPUT) && (!orig_avail_in))\n            return MZ_BUF_ERROR; /* Signal caller that we can't make forward progress without supplying more input or by setting flush to MZ_FINISH. */\n        else if (flush == MZ_FINISH)\n        {\n            /* The output buffer MUST be large to hold the remaining uncompressed data when flush==MZ_FINISH. */\n            if (status == TINFL_STATUS_DONE)\n                return pState->m_dict_avail ? MZ_BUF_ERROR : MZ_STREAM_END;\n            /* status here must be TINFL_STATUS_HAS_MORE_OUTPUT, which means there's at least 1 more byte on the way. If there's no more room left in the output buffer then something is wrong. */\n            else if (!pStream->avail_out)\n                return MZ_BUF_ERROR;\n        }\n        else if ((status == TINFL_STATUS_DONE) || (!pStream->avail_in) || (!pStream->avail_out) || (pState->m_dict_avail))\n            break;\n    }\n\n    return ((status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK;\n}\n\nint mz_inflateEnd(mz_streamp pStream)\n{\n    if (!pStream)\n        return MZ_STREAM_ERROR;\n    if (pStream->state)\n    {\n        pStream->zfree(pStream->opaque, pStream->state);\n        pStream->state = NULL;\n    }\n    return MZ_OK;\n}\n\nint mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len)\n{\n    mz_stream stream;\n    int status;\n    memset(&stream, 0, sizeof(stream));\n\n    /* In case mz_ulong is 64-bits (argh I hate longs). */\n    if ((source_len | *pDest_len) > 0xFFFFFFFFU)\n        return MZ_PARAM_ERROR;\n\n    stream.next_in = pSource;\n    stream.avail_in = (mz_uint32)source_len;\n    stream.next_out = pDest;\n    stream.avail_out = (mz_uint32)*pDest_len;\n\n    status = mz_inflateInit(&stream);\n    if (status != MZ_OK)\n        return status;\n\n    status = mz_inflate(&stream, MZ_FINISH);\n    if (status != MZ_STREAM_END)\n    {\n        mz_inflateEnd(&stream);\n        return ((status == MZ_BUF_ERROR) && (!stream.avail_in)) ? MZ_DATA_ERROR : status;\n    }\n    *pDest_len = stream.total_out;\n\n    return mz_inflateEnd(&stream);\n}\n\nconst char *mz_error(int err)\n{\n    static struct\n    {\n        int m_err;\n        const char *m_pDesc;\n    } s_error_descs[] =\n        {\n          { MZ_OK, \"\" }, { MZ_STREAM_END, \"stream end\" }, { MZ_NEED_DICT, \"need dictionary\" }, { MZ_ERRNO, \"file error\" }, { MZ_STREAM_ERROR, \"stream error\" }, { MZ_DATA_ERROR, \"data error\" }, { MZ_MEM_ERROR, \"out of memory\" }, { MZ_BUF_ERROR, \"buf error\" }, { MZ_VERSION_ERROR, \"version error\" }, { MZ_PARAM_ERROR, \"parameter error\" }\n        };\n    mz_uint i;\n    for (i = 0; i < sizeof(s_error_descs) / sizeof(s_error_descs[0]); ++i)\n        if (s_error_descs[i].m_err == err)\n            return s_error_descs[i].m_pDesc;\n    return NULL;\n}\n\n#endif /*MINIZ_NO_ZLIB_APIS */\n\n#ifdef __cplusplus\n}\n#endif\n\n/*\n  This is free and unencumbered software released into the public domain.\n\n  Anyone is free to copy, modify, publish, use, compile, sell, or\n  distribute this software, either in source code form or as a compiled\n  binary, for any purpose, commercial or non-commercial, and by any\n  means.\n\n  In jurisdictions that recognize copyright laws, the author or authors\n  of this software dedicate any and all copyright interest in the\n  software to the public domain. We make this dedication for the benefit\n  of the public at large and to the detriment of our heirs and\n  successors. We intend this dedication to be an overt act of\n  relinquishment in perpetuity of all present and future rights to this\n  software under copyright law.\n\n  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR\n  OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n  ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n  OTHER DEALINGS IN THE SOFTWARE.\n\n  For more information, please refer to <http://unlicense.org/>\n*/\n/**************************************************************************\n *\n * Copyright 2013-2014 RAD Game Tools and Valve Software\n * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC\n * All Rights Reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n **************************************************************************/\n\n\n\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* ------------------- Low-level Compression (independent from all decompression API's) */\n\n/* Purposely making these tables static for faster init and thread safety. */\nstatic const mz_uint16 s_tdefl_len_sym[256] =\n    {\n      257, 258, 259, 260, 261, 262, 263, 264, 265, 265, 266, 266, 267, 267, 268, 268, 269, 269, 269, 269, 270, 270, 270, 270, 271, 271, 271, 271, 272, 272, 272, 272,\n      273, 273, 273, 273, 273, 273, 273, 273, 274, 274, 274, 274, 274, 274, 274, 274, 275, 275, 275, 275, 275, 275, 275, 275, 276, 276, 276, 276, 276, 276, 276, 276,\n      277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278,\n      279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280,\n      281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,\n      282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282,\n      283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283,\n      284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 285\n    };\n\nstatic const mz_uint8 s_tdefl_len_extra[256] =\n    {\n      0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,\n      4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,\n      5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,\n      5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0\n    };\n\nstatic const mz_uint8 s_tdefl_small_dist_sym[512] =\n    {\n      0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11,\n      11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13,\n      13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,\n      14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,\n      14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,\n      15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,\n      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,\n      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,\n      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,\n      17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,\n      17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,\n      17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17\n    };\n\nstatic const mz_uint8 s_tdefl_small_dist_extra[512] =\n    {\n      0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,\n      5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,\n      6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,\n      6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,\n      7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,\n      7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,\n      7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,\n      7, 7, 7, 7, 7, 7, 7, 7\n    };\n\nstatic const mz_uint8 s_tdefl_large_dist_sym[128] =\n    {\n      0, 0, 18, 19, 20, 20, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n      26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,\n      28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29\n    };\n\nstatic const mz_uint8 s_tdefl_large_dist_extra[128] =\n    {\n      0, 0, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,\n      12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,\n      13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13\n    };\n\n/* Radix sorts tdefl_sym_freq[] array by 16-bit key m_key. Returns ptr to sorted values. */\ntypedef struct\n{\n    mz_uint16 m_key, m_sym_index;\n} tdefl_sym_freq;\nstatic tdefl_sym_freq *tdefl_radix_sort_syms(mz_uint num_syms, tdefl_sym_freq *pSyms0, tdefl_sym_freq *pSyms1)\n{\n    mz_uint32 total_passes = 2, pass_shift, pass, i, hist[256 * 2];\n    tdefl_sym_freq *pCur_syms = pSyms0, *pNew_syms = pSyms1;\n    MZ_CLEAR_OBJ(hist);\n    for (i = 0; i < num_syms; i++)\n    {\n        mz_uint freq = pSyms0[i].m_key;\n        hist[freq & 0xFF]++;\n        hist[256 + ((freq >> 8) & 0xFF)]++;\n    }\n    while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256]))\n        total_passes--;\n    for (pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8)\n    {\n        const mz_uint32 *pHist = &hist[pass << 8];\n        mz_uint offsets[256], cur_ofs = 0;\n        for (i = 0; i < 256; i++)\n        {\n            offsets[i] = cur_ofs;\n            cur_ofs += pHist[i];\n        }\n        for (i = 0; i < num_syms; i++)\n            pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] = pCur_syms[i];\n        {\n            tdefl_sym_freq *t = pCur_syms;\n            pCur_syms = pNew_syms;\n            pNew_syms = t;\n        }\n    }\n    return pCur_syms;\n}\n\n/* tdefl_calculate_minimum_redundancy() originally written by: Alistair Moffat, alistair@cs.mu.oz.au, Jyrki Katajainen, jyrki@diku.dk, November 1996. */\nstatic void tdefl_calculate_minimum_redundancy(tdefl_sym_freq *A, int n)\n{\n    int root, leaf, next, avbl, used, dpth;\n    if (n == 0)\n        return;\n    else if (n == 1)\n    {\n        A[0].m_key = 1;\n        return;\n    }\n    A[0].m_key += A[1].m_key;\n    root = 0;\n    leaf = 2;\n    for (next = 1; next < n - 1; next++)\n    {\n        if (leaf >= n || A[root].m_key < A[leaf].m_key)\n        {\n            A[next].m_key = A[root].m_key;\n            A[root++].m_key = (mz_uint16)next;\n        }\n        else\n            A[next].m_key = A[leaf++].m_key;\n        if (leaf >= n || (root < next && A[root].m_key < A[leaf].m_key))\n        {\n            A[next].m_key = (mz_uint16)(A[next].m_key + A[root].m_key);\n            A[root++].m_key = (mz_uint16)next;\n        }\n        else\n            A[next].m_key = (mz_uint16)(A[next].m_key + A[leaf++].m_key);\n    }\n    A[n - 2].m_key = 0;\n    for (next = n - 3; next >= 0; next--)\n        A[next].m_key = A[A[next].m_key].m_key + 1;\n    avbl = 1;\n    used = dpth = 0;\n    root = n - 2;\n    next = n - 1;\n    while (avbl > 0)\n    {\n        while (root >= 0 && (int)A[root].m_key == dpth)\n        {\n            used++;\n            root--;\n        }\n        while (avbl > used)\n        {\n            A[next--].m_key = (mz_uint16)(dpth);\n            avbl--;\n        }\n        avbl = 2 * used;\n        dpth++;\n        used = 0;\n    }\n}\n\n/* Limits canonical Huffman code table's max code size. */\nenum\n{\n    TDEFL_MAX_SUPPORTED_HUFF_CODESIZE = 32\n};\nstatic void tdefl_huffman_enforce_max_code_size(int *pNum_codes, int code_list_len, int max_code_size)\n{\n    int i;\n    mz_uint32 total = 0;\n    if (code_list_len <= 1)\n        return;\n    for (i = max_code_size + 1; i <= TDEFL_MAX_SUPPORTED_HUFF_CODESIZE; i++)\n        pNum_codes[max_code_size] += pNum_codes[i];\n    for (i = max_code_size; i > 0; i--)\n        total += (((mz_uint32)pNum_codes[i]) << (max_code_size - i));\n    while (total != (1UL << max_code_size))\n    {\n        pNum_codes[max_code_size]--;\n        for (i = max_code_size - 1; i > 0; i--)\n            if (pNum_codes[i])\n            {\n                pNum_codes[i]--;\n                pNum_codes[i + 1] += 2;\n                break;\n            }\n        total--;\n    }\n}\n\nstatic void tdefl_optimize_huffman_table(tdefl_compressor *d, int table_num, int table_len, int code_size_limit, int static_table)\n{\n    int i, j, l, num_codes[1 + TDEFL_MAX_SUPPORTED_HUFF_CODESIZE];\n    mz_uint next_code[TDEFL_MAX_SUPPORTED_HUFF_CODESIZE + 1];\n    MZ_CLEAR_OBJ(num_codes);\n    if (static_table)\n    {\n        for (i = 0; i < table_len; i++)\n            num_codes[d->m_huff_code_sizes[table_num][i]]++;\n    }\n    else\n    {\n        tdefl_sym_freq syms0[TDEFL_MAX_HUFF_SYMBOLS], syms1[TDEFL_MAX_HUFF_SYMBOLS], *pSyms;\n        int num_used_syms = 0;\n        const mz_uint16 *pSym_count = &d->m_huff_count[table_num][0];\n        for (i = 0; i < table_len; i++)\n            if (pSym_count[i])\n            {\n                syms0[num_used_syms].m_key = (mz_uint16)pSym_count[i];\n                syms0[num_used_syms++].m_sym_index = (mz_uint16)i;\n            }\n\n        pSyms = tdefl_radix_sort_syms(num_used_syms, syms0, syms1);\n        tdefl_calculate_minimum_redundancy(pSyms, num_used_syms);\n\n        for (i = 0; i < num_used_syms; i++)\n            num_codes[pSyms[i].m_key]++;\n\n        tdefl_huffman_enforce_max_code_size(num_codes, num_used_syms, code_size_limit);\n\n        MZ_CLEAR_OBJ(d->m_huff_code_sizes[table_num]);\n        MZ_CLEAR_OBJ(d->m_huff_codes[table_num]);\n        for (i = 1, j = num_used_syms; i <= code_size_limit; i++)\n            for (l = num_codes[i]; l > 0; l--)\n                d->m_huff_code_sizes[table_num][pSyms[--j].m_sym_index] = (mz_uint8)(i);\n    }\n\n    next_code[1] = 0;\n    for (j = 0, i = 2; i <= code_size_limit; i++)\n        next_code[i] = j = ((j + num_codes[i - 1]) << 1);\n\n    for (i = 0; i < table_len; i++)\n    {\n        mz_uint rev_code = 0, code, code_size;\n        if ((code_size = d->m_huff_code_sizes[table_num][i]) == 0)\n            continue;\n        code = next_code[code_size]++;\n        for (l = code_size; l > 0; l--, code >>= 1)\n            rev_code = (rev_code << 1) | (code & 1);\n        d->m_huff_codes[table_num][i] = (mz_uint16)rev_code;\n    }\n}\n\n#define TDEFL_PUT_BITS(b, l)                                       \\\n    do                                                             \\\n    {                                                              \\\n        mz_uint bits = b;                                          \\\n        mz_uint len = l;                                           \\\n        MZ_ASSERT(bits <= ((1U << len) - 1U));                     \\\n        d->m_bit_buffer |= (bits << d->m_bits_in);                 \\\n        d->m_bits_in += len;                                       \\\n        while (d->m_bits_in >= 8)                                  \\\n        {                                                          \\\n            if (d->m_pOutput_buf < d->m_pOutput_buf_end)           \\\n                *d->m_pOutput_buf++ = (mz_uint8)(d->m_bit_buffer); \\\n            d->m_bit_buffer >>= 8;                                 \\\n            d->m_bits_in -= 8;                                     \\\n        }                                                          \\\n    }                                                              \\\n    MZ_MACRO_END\n\n#define TDEFL_RLE_PREV_CODE_SIZE()                                                                                       \\\n    {                                                                                                                    \\\n        if (rle_repeat_count)                                                                                            \\\n        {                                                                                                                \\\n            if (rle_repeat_count < 3)                                                                                    \\\n            {                                                                                                            \\\n                d->m_huff_count[2][prev_code_size] = (mz_uint16)(d->m_huff_count[2][prev_code_size] + rle_repeat_count); \\\n                while (rle_repeat_count--)                                                                               \\\n                    packed_code_sizes[num_packed_code_sizes++] = prev_code_size;                                         \\\n            }                                                                                                            \\\n            else                                                                                                         \\\n            {                                                                                                            \\\n                d->m_huff_count[2][16] = (mz_uint16)(d->m_huff_count[2][16] + 1);                                        \\\n                packed_code_sizes[num_packed_code_sizes++] = 16;                                                         \\\n                packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_repeat_count - 3);                           \\\n            }                                                                                                            \\\n            rle_repeat_count = 0;                                                                                        \\\n        }                                                                                                                \\\n    }\n\n#define TDEFL_RLE_ZERO_CODE_SIZE()                                                         \\\n    {                                                                                      \\\n        if (rle_z_count)                                                                   \\\n        {                                                                                  \\\n            if (rle_z_count < 3)                                                           \\\n            {                                                                              \\\n                d->m_huff_count[2][0] = (mz_uint16)(d->m_huff_count[2][0] + rle_z_count);  \\\n                while (rle_z_count--)                                                      \\\n                    packed_code_sizes[num_packed_code_sizes++] = 0;                        \\\n            }                                                                              \\\n            else if (rle_z_count <= 10)                                                    \\\n            {                                                                              \\\n                d->m_huff_count[2][17] = (mz_uint16)(d->m_huff_count[2][17] + 1);          \\\n                packed_code_sizes[num_packed_code_sizes++] = 17;                           \\\n                packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 3);  \\\n            }                                                                              \\\n            else                                                                           \\\n            {                                                                              \\\n                d->m_huff_count[2][18] = (mz_uint16)(d->m_huff_count[2][18] + 1);          \\\n                packed_code_sizes[num_packed_code_sizes++] = 18;                           \\\n                packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 11); \\\n            }                                                                              \\\n            rle_z_count = 0;                                                               \\\n        }                                                                                  \\\n    }\n\nstatic mz_uint8 s_tdefl_packed_code_size_syms_swizzle[] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };\n\nstatic void tdefl_start_dynamic_block(tdefl_compressor *d)\n{\n    int num_lit_codes, num_dist_codes, num_bit_lengths;\n    mz_uint i, total_code_sizes_to_pack, num_packed_code_sizes, rle_z_count, rle_repeat_count, packed_code_sizes_index;\n    mz_uint8 code_sizes_to_pack[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], packed_code_sizes[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], prev_code_size = 0xFF;\n\n    d->m_huff_count[0][256] = 1;\n\n    tdefl_optimize_huffman_table(d, 0, TDEFL_MAX_HUFF_SYMBOLS_0, 15, MZ_FALSE);\n    tdefl_optimize_huffman_table(d, 1, TDEFL_MAX_HUFF_SYMBOLS_1, 15, MZ_FALSE);\n\n    for (num_lit_codes = 286; num_lit_codes > 257; num_lit_codes--)\n        if (d->m_huff_code_sizes[0][num_lit_codes - 1])\n            break;\n    for (num_dist_codes = 30; num_dist_codes > 1; num_dist_codes--)\n        if (d->m_huff_code_sizes[1][num_dist_codes - 1])\n            break;\n\n    memcpy(code_sizes_to_pack, &d->m_huff_code_sizes[0][0], num_lit_codes);\n    memcpy(code_sizes_to_pack + num_lit_codes, &d->m_huff_code_sizes[1][0], num_dist_codes);\n    total_code_sizes_to_pack = num_lit_codes + num_dist_codes;\n    num_packed_code_sizes = 0;\n    rle_z_count = 0;\n    rle_repeat_count = 0;\n\n    memset(&d->m_huff_count[2][0], 0, sizeof(d->m_huff_count[2][0]) * TDEFL_MAX_HUFF_SYMBOLS_2);\n    for (i = 0; i < total_code_sizes_to_pack; i++)\n    {\n        mz_uint8 code_size = code_sizes_to_pack[i];\n        if (!code_size)\n        {\n            TDEFL_RLE_PREV_CODE_SIZE();\n            if (++rle_z_count == 138)\n            {\n                TDEFL_RLE_ZERO_CODE_SIZE();\n            }\n        }\n        else\n        {\n            TDEFL_RLE_ZERO_CODE_SIZE();\n            if (code_size != prev_code_size)\n            {\n                TDEFL_RLE_PREV_CODE_SIZE();\n                d->m_huff_count[2][code_size] = (mz_uint16)(d->m_huff_count[2][code_size] + 1);\n                packed_code_sizes[num_packed_code_sizes++] = code_size;\n            }\n            else if (++rle_repeat_count == 6)\n            {\n                TDEFL_RLE_PREV_CODE_SIZE();\n            }\n        }\n        prev_code_size = code_size;\n    }\n    if (rle_repeat_count)\n    {\n        TDEFL_RLE_PREV_CODE_SIZE();\n    }\n    else\n    {\n        TDEFL_RLE_ZERO_CODE_SIZE();\n    }\n\n    tdefl_optimize_huffman_table(d, 2, TDEFL_MAX_HUFF_SYMBOLS_2, 7, MZ_FALSE);\n\n    TDEFL_PUT_BITS(2, 2);\n\n    TDEFL_PUT_BITS(num_lit_codes - 257, 5);\n    TDEFL_PUT_BITS(num_dist_codes - 1, 5);\n\n    for (num_bit_lengths = 18; num_bit_lengths >= 0; num_bit_lengths--)\n        if (d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[num_bit_lengths]])\n            break;\n    num_bit_lengths = MZ_MAX(4, (num_bit_lengths + 1));\n    TDEFL_PUT_BITS(num_bit_lengths - 4, 4);\n    for (i = 0; (int)i < num_bit_lengths; i++)\n        TDEFL_PUT_BITS(d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[i]], 3);\n\n    for (packed_code_sizes_index = 0; packed_code_sizes_index < num_packed_code_sizes;)\n    {\n        mz_uint code = packed_code_sizes[packed_code_sizes_index++];\n        MZ_ASSERT(code < TDEFL_MAX_HUFF_SYMBOLS_2);\n        TDEFL_PUT_BITS(d->m_huff_codes[2][code], d->m_huff_code_sizes[2][code]);\n        if (code >= 16)\n            TDEFL_PUT_BITS(packed_code_sizes[packed_code_sizes_index++], \"\\02\\03\\07\"[code - 16]);\n    }\n}\n\nstatic void tdefl_start_static_block(tdefl_compressor *d)\n{\n    mz_uint i;\n    mz_uint8 *p = &d->m_huff_code_sizes[0][0];\n\n    for (i = 0; i <= 143; ++i)\n        *p++ = 8;\n    for (; i <= 255; ++i)\n        *p++ = 9;\n    for (; i <= 279; ++i)\n        *p++ = 7;\n    for (; i <= 287; ++i)\n        *p++ = 8;\n\n    memset(d->m_huff_code_sizes[1], 5, 32);\n\n    tdefl_optimize_huffman_table(d, 0, 288, 15, MZ_TRUE);\n    tdefl_optimize_huffman_table(d, 1, 32, 15, MZ_TRUE);\n\n    TDEFL_PUT_BITS(1, 2);\n}\n\nstatic const mz_uint mz_bitmasks[17] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };\n\n#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS\nstatic mz_bool tdefl_compress_lz_codes(tdefl_compressor *d)\n{\n    mz_uint flags;\n    mz_uint8 *pLZ_codes;\n    mz_uint8 *pOutput_buf = d->m_pOutput_buf;\n    mz_uint8 *pLZ_code_buf_end = d->m_pLZ_code_buf;\n    mz_uint64 bit_buffer = d->m_bit_buffer;\n    mz_uint bits_in = d->m_bits_in;\n\n#define TDEFL_PUT_BITS_FAST(b, l)                    \\\n    {                                                \\\n        bit_buffer |= (((mz_uint64)(b)) << bits_in); \\\n        bits_in += (l);                              \\\n    }\n\n    flags = 1;\n    for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < pLZ_code_buf_end; flags >>= 1)\n    {\n        if (flags == 1)\n            flags = *pLZ_codes++ | 0x100;\n\n        if (flags & 1)\n        {\n            mz_uint s0, s1, n0, n1, sym, num_extra_bits;\n            mz_uint match_len = pLZ_codes[0], match_dist = *(const mz_uint16 *)(pLZ_codes + 1);\n            pLZ_codes += 3;\n\n            MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);\n            TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);\n            TDEFL_PUT_BITS_FAST(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]);\n\n            /* This sequence coaxes MSVC into using cmov's vs. jmp's. */\n            s0 = s_tdefl_small_dist_sym[match_dist & 511];\n            n0 = s_tdefl_small_dist_extra[match_dist & 511];\n            s1 = s_tdefl_large_dist_sym[match_dist >> 8];\n            n1 = s_tdefl_large_dist_extra[match_dist >> 8];\n            sym = (match_dist < 512) ? s0 : s1;\n            num_extra_bits = (match_dist < 512) ? n0 : n1;\n\n            MZ_ASSERT(d->m_huff_code_sizes[1][sym]);\n            TDEFL_PUT_BITS_FAST(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]);\n            TDEFL_PUT_BITS_FAST(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);\n        }\n        else\n        {\n            mz_uint lit = *pLZ_codes++;\n            MZ_ASSERT(d->m_huff_code_sizes[0][lit]);\n            TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);\n\n            if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end))\n            {\n                flags >>= 1;\n                lit = *pLZ_codes++;\n                MZ_ASSERT(d->m_huff_code_sizes[0][lit]);\n                TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);\n\n                if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end))\n                {\n                    flags >>= 1;\n                    lit = *pLZ_codes++;\n                    MZ_ASSERT(d->m_huff_code_sizes[0][lit]);\n                    TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);\n                }\n            }\n        }\n\n        if (pOutput_buf >= d->m_pOutput_buf_end)\n            return MZ_FALSE;\n\n        *(mz_uint64 *)pOutput_buf = bit_buffer;\n        pOutput_buf += (bits_in >> 3);\n        bit_buffer >>= (bits_in & ~7);\n        bits_in &= 7;\n    }\n\n#undef TDEFL_PUT_BITS_FAST\n\n    d->m_pOutput_buf = pOutput_buf;\n    d->m_bits_in = 0;\n    d->m_bit_buffer = 0;\n\n    while (bits_in)\n    {\n        mz_uint32 n = MZ_MIN(bits_in, 16);\n        TDEFL_PUT_BITS((mz_uint)bit_buffer & mz_bitmasks[n], n);\n        bit_buffer >>= n;\n        bits_in -= n;\n    }\n\n    TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);\n\n    return (d->m_pOutput_buf < d->m_pOutput_buf_end);\n}\n#else\nstatic mz_bool tdefl_compress_lz_codes(tdefl_compressor *d)\n{\n    mz_uint flags;\n    mz_uint8 *pLZ_codes;\n\n    flags = 1;\n    for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < d->m_pLZ_code_buf; flags >>= 1)\n    {\n        if (flags == 1)\n            flags = *pLZ_codes++ | 0x100;\n        if (flags & 1)\n        {\n            mz_uint sym, num_extra_bits;\n            mz_uint match_len = pLZ_codes[0], match_dist = (pLZ_codes[1] | (pLZ_codes[2] << 8));\n            pLZ_codes += 3;\n\n            MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);\n            TDEFL_PUT_BITS(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);\n            TDEFL_PUT_BITS(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]);\n\n            if (match_dist < 512)\n            {\n                sym = s_tdefl_small_dist_sym[match_dist];\n                num_extra_bits = s_tdefl_small_dist_extra[match_dist];\n            }\n            else\n            {\n                sym = s_tdefl_large_dist_sym[match_dist >> 8];\n                num_extra_bits = s_tdefl_large_dist_extra[match_dist >> 8];\n            }\n            MZ_ASSERT(d->m_huff_code_sizes[1][sym]);\n            TDEFL_PUT_BITS(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]);\n            TDEFL_PUT_BITS(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);\n        }\n        else\n        {\n            mz_uint lit = *pLZ_codes++;\n            MZ_ASSERT(d->m_huff_code_sizes[0][lit]);\n            TDEFL_PUT_BITS(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);\n        }\n    }\n\n    TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);\n\n    return (d->m_pOutput_buf < d->m_pOutput_buf_end);\n}\n#endif /* MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS */\n\nstatic mz_bool tdefl_compress_block(tdefl_compressor *d, mz_bool static_block)\n{\n    if (static_block)\n        tdefl_start_static_block(d);\n    else\n        tdefl_start_dynamic_block(d);\n    return tdefl_compress_lz_codes(d);\n}\n\nstatic int tdefl_flush_block(tdefl_compressor *d, int flush)\n{\n    mz_uint saved_bit_buf, saved_bits_in;\n    mz_uint8 *pSaved_output_buf;\n    mz_bool comp_block_succeeded = MZ_FALSE;\n    int n, use_raw_block = ((d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS) != 0) && (d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size;\n    mz_uint8 *pOutput_buf_start = ((d->m_pPut_buf_func == NULL) && ((*d->m_pOut_buf_size - d->m_out_buf_ofs) >= TDEFL_OUT_BUF_SIZE)) ? ((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs) : d->m_output_buf;\n\n    d->m_pOutput_buf = pOutput_buf_start;\n    d->m_pOutput_buf_end = d->m_pOutput_buf + TDEFL_OUT_BUF_SIZE - 16;\n\n    MZ_ASSERT(!d->m_output_flush_remaining);\n    d->m_output_flush_ofs = 0;\n    d->m_output_flush_remaining = 0;\n\n    *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> d->m_num_flags_left);\n    d->m_pLZ_code_buf -= (d->m_num_flags_left == 8);\n\n    if ((d->m_flags & TDEFL_WRITE_ZLIB_HEADER) && (!d->m_block_index))\n    {\n        TDEFL_PUT_BITS(0x78, 8);\n        TDEFL_PUT_BITS(0x01, 8);\n    }\n\n    TDEFL_PUT_BITS(flush == TDEFL_FINISH, 1);\n\n    pSaved_output_buf = d->m_pOutput_buf;\n    saved_bit_buf = d->m_bit_buffer;\n    saved_bits_in = d->m_bits_in;\n\n    if (!use_raw_block)\n        comp_block_succeeded = tdefl_compress_block(d, (d->m_flags & TDEFL_FORCE_ALL_STATIC_BLOCKS) || (d->m_total_lz_bytes < 48));\n\n    /* If the block gets expanded, forget the current contents of the output buffer and send a raw block instead. */\n    if (((use_raw_block) || ((d->m_total_lz_bytes) && ((d->m_pOutput_buf - pSaved_output_buf + 1U) >= d->m_total_lz_bytes))) &&\n        ((d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size))\n    {\n        mz_uint i;\n        d->m_pOutput_buf = pSaved_output_buf;\n        d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;\n        TDEFL_PUT_BITS(0, 2);\n        if (d->m_bits_in)\n        {\n            TDEFL_PUT_BITS(0, 8 - d->m_bits_in);\n        }\n        for (i = 2; i; --i, d->m_total_lz_bytes ^= 0xFFFF)\n        {\n            TDEFL_PUT_BITS(d->m_total_lz_bytes & 0xFFFF, 16);\n        }\n        for (i = 0; i < d->m_total_lz_bytes; ++i)\n        {\n            TDEFL_PUT_BITS(d->m_dict[(d->m_lz_code_buf_dict_pos + i) & TDEFL_LZ_DICT_SIZE_MASK], 8);\n        }\n    }\n    /* Check for the extremely unlikely (if not impossible) case of the compressed block not fitting into the output buffer when using dynamic codes. */\n    else if (!comp_block_succeeded)\n    {\n        d->m_pOutput_buf = pSaved_output_buf;\n        d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;\n        tdefl_compress_block(d, MZ_TRUE);\n    }\n\n    if (flush)\n    {\n        if (flush == TDEFL_FINISH)\n        {\n            if (d->m_bits_in)\n            {\n                TDEFL_PUT_BITS(0, 8 - d->m_bits_in);\n            }\n            if (d->m_flags & TDEFL_WRITE_ZLIB_HEADER)\n            {\n                mz_uint i, a = d->m_adler32;\n                for (i = 0; i < 4; i++)\n                {\n                    TDEFL_PUT_BITS((a >> 24) & 0xFF, 8);\n                    a <<= 8;\n                }\n            }\n        }\n        else\n        {\n            mz_uint i, z = 0;\n            TDEFL_PUT_BITS(0, 3);\n            if (d->m_bits_in)\n            {\n                TDEFL_PUT_BITS(0, 8 - d->m_bits_in);\n            }\n            for (i = 2; i; --i, z ^= 0xFFFF)\n            {\n                TDEFL_PUT_BITS(z & 0xFFFF, 16);\n            }\n        }\n    }\n\n    MZ_ASSERT(d->m_pOutput_buf < d->m_pOutput_buf_end);\n\n    memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);\n    memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);\n\n    d->m_pLZ_code_buf = d->m_lz_code_buf + 1;\n    d->m_pLZ_flags = d->m_lz_code_buf;\n    d->m_num_flags_left = 8;\n    d->m_lz_code_buf_dict_pos += d->m_total_lz_bytes;\n    d->m_total_lz_bytes = 0;\n    d->m_block_index++;\n\n    if ((n = (int)(d->m_pOutput_buf - pOutput_buf_start)) != 0)\n    {\n        if (d->m_pPut_buf_func)\n        {\n            *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;\n            if (!(*d->m_pPut_buf_func)(d->m_output_buf, n, d->m_pPut_buf_user))\n                return (d->m_prev_return_status = TDEFL_STATUS_PUT_BUF_FAILED);\n        }\n        else if (pOutput_buf_start == d->m_output_buf)\n        {\n            int bytes_to_copy = (int)MZ_MIN((size_t)n, (size_t)(*d->m_pOut_buf_size - d->m_out_buf_ofs));\n            memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf, bytes_to_copy);\n            d->m_out_buf_ofs += bytes_to_copy;\n            if ((n -= bytes_to_copy) != 0)\n            {\n                d->m_output_flush_ofs = bytes_to_copy;\n                d->m_output_flush_remaining = n;\n            }\n        }\n        else\n        {\n            d->m_out_buf_ofs += n;\n        }\n    }\n\n    return d->m_output_flush_remaining;\n}\n\n#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES\n#ifdef MINIZ_UNALIGNED_USE_MEMCPY\nstatic inline mz_uint16 TDEFL_READ_UNALIGNED_WORD(const mz_uint8* p)\n{\n\tmz_uint16 ret;\n\tmemcpy(&ret, p, sizeof(mz_uint16));\n\treturn ret;\n}\nstatic inline mz_uint16 TDEFL_READ_UNALIGNED_WORD2(const mz_uint16* p)\n{\n\tmz_uint16 ret;\n\tmemcpy(&ret, p, sizeof(mz_uint16));\n\treturn ret;\n}\n#else\n#define TDEFL_READ_UNALIGNED_WORD(p) *(const mz_uint16 *)(p)\n#define TDEFL_READ_UNALIGNED_WORD2(p) *(const mz_uint16 *)(p)\n#endif\nstatic MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len)\n{\n    mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len;\n    mz_uint num_probes_left = d->m_max_probes[match_len >= 32];\n    const mz_uint16 *s = (const mz_uint16 *)(d->m_dict + pos), *p, *q;\n    mz_uint16 c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]), s01 = TDEFL_READ_UNALIGNED_WORD2(s);\n    MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN);\n    if (max_match_len <= match_len)\n        return;\n    for (;;)\n    {\n        for (;;)\n        {\n            if (--num_probes_left == 0)\n                return;\n#define TDEFL_PROBE                                                                             \\\n    next_probe_pos = d->m_next[probe_pos];                                                      \\\n    if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) \\\n        return;                                                                                 \\\n    probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK;                                       \\\n    if (TDEFL_READ_UNALIGNED_WORD(&d->m_dict[probe_pos + match_len - 1]) == c01)                \\\n        break;\n            TDEFL_PROBE;\n            TDEFL_PROBE;\n            TDEFL_PROBE;\n        }\n        if (!dist)\n            break;\n        q = (const mz_uint16 *)(d->m_dict + probe_pos);\n        if (TDEFL_READ_UNALIGNED_WORD2(q) != s01)\n            continue;\n        p = s;\n        probe_len = 32;\n        do\n        {\n        } while ((TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) &&\n                 (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (--probe_len > 0));\n        if (!probe_len)\n        {\n            *pMatch_dist = dist;\n            *pMatch_len = MZ_MIN(max_match_len, (mz_uint)TDEFL_MAX_MATCH_LEN);\n            break;\n        }\n        else if ((probe_len = ((mz_uint)(p - s) * 2) + (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q)) > match_len)\n        {\n            *pMatch_dist = dist;\n            if ((*pMatch_len = match_len = MZ_MIN(max_match_len, probe_len)) == max_match_len)\n                break;\n            c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]);\n        }\n    }\n}\n#else\nstatic MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len)\n{\n    mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len;\n    mz_uint num_probes_left = d->m_max_probes[match_len >= 32];\n    const mz_uint8 *s = d->m_dict + pos, *p, *q;\n    mz_uint8 c0 = d->m_dict[pos + match_len], c1 = d->m_dict[pos + match_len - 1];\n    MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN);\n    if (max_match_len <= match_len)\n        return;\n    for (;;)\n    {\n        for (;;)\n        {\n            if (--num_probes_left == 0)\n                return;\n#define TDEFL_PROBE                                                                               \\\n    next_probe_pos = d->m_next[probe_pos];                                                        \\\n    if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist))   \\\n        return;                                                                                   \\\n    probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK;                                         \\\n    if ((d->m_dict[probe_pos + match_len] == c0) && (d->m_dict[probe_pos + match_len - 1] == c1)) \\\n        break;\n            TDEFL_PROBE;\n            TDEFL_PROBE;\n            TDEFL_PROBE;\n        }\n        if (!dist)\n            break;\n        p = s;\n        q = d->m_dict + probe_pos;\n        for (probe_len = 0; probe_len < max_match_len; probe_len++)\n            if (*p++ != *q++)\n                break;\n        if (probe_len > match_len)\n        {\n            *pMatch_dist = dist;\n            if ((*pMatch_len = match_len = probe_len) == max_match_len)\n                return;\n            c0 = d->m_dict[pos + match_len];\n            c1 = d->m_dict[pos + match_len - 1];\n        }\n    }\n}\n#endif /* #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES */\n\n#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN\nstatic mz_bool tdefl_compress_fast(tdefl_compressor *d)\n{\n    /* Faster, minimally featured LZRW1-style match+parse loop with better register utilization. Intended for applications where raw throughput is valued more highly than ratio. */\n    mz_uint lookahead_pos = d->m_lookahead_pos, lookahead_size = d->m_lookahead_size, dict_size = d->m_dict_size, total_lz_bytes = d->m_total_lz_bytes, num_flags_left = d->m_num_flags_left;\n    mz_uint8 *pLZ_code_buf = d->m_pLZ_code_buf, *pLZ_flags = d->m_pLZ_flags;\n    mz_uint cur_pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;\n\n    while ((d->m_src_buf_left) || ((d->m_flush) && (lookahead_size)))\n    {\n        const mz_uint TDEFL_COMP_FAST_LOOKAHEAD_SIZE = 4096;\n        mz_uint dst_pos = (lookahead_pos + lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK;\n        mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(d->m_src_buf_left, TDEFL_COMP_FAST_LOOKAHEAD_SIZE - lookahead_size);\n        d->m_src_buf_left -= num_bytes_to_process;\n        lookahead_size += num_bytes_to_process;\n\n        while (num_bytes_to_process)\n        {\n            mz_uint32 n = MZ_MIN(TDEFL_LZ_DICT_SIZE - dst_pos, num_bytes_to_process);\n            memcpy(d->m_dict + dst_pos, d->m_pSrc, n);\n            if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))\n                memcpy(d->m_dict + TDEFL_LZ_DICT_SIZE + dst_pos, d->m_pSrc, MZ_MIN(n, (TDEFL_MAX_MATCH_LEN - 1) - dst_pos));\n            d->m_pSrc += n;\n            dst_pos = (dst_pos + n) & TDEFL_LZ_DICT_SIZE_MASK;\n            num_bytes_to_process -= n;\n        }\n\n        dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - lookahead_size, dict_size);\n        if ((!d->m_flush) && (lookahead_size < TDEFL_COMP_FAST_LOOKAHEAD_SIZE))\n            break;\n\n        while (lookahead_size >= 4)\n        {\n            mz_uint cur_match_dist, cur_match_len = 1;\n            mz_uint8 *pCur_dict = d->m_dict + cur_pos;\n            mz_uint first_trigram = (*(const mz_uint32 *)pCur_dict) & 0xFFFFFF;\n            mz_uint hash = (first_trigram ^ (first_trigram >> (24 - (TDEFL_LZ_HASH_BITS - 8)))) & TDEFL_LEVEL1_HASH_SIZE_MASK;\n            mz_uint probe_pos = d->m_hash[hash];\n            d->m_hash[hash] = (mz_uint16)lookahead_pos;\n\n            if (((cur_match_dist = (mz_uint16)(lookahead_pos - probe_pos)) <= dict_size) && ((*(const mz_uint32 *)(d->m_dict + (probe_pos &= TDEFL_LZ_DICT_SIZE_MASK)) & 0xFFFFFF) == first_trigram))\n            {\n                const mz_uint16 *p = (const mz_uint16 *)pCur_dict;\n                const mz_uint16 *q = (const mz_uint16 *)(d->m_dict + probe_pos);\n                mz_uint32 probe_len = 32;\n                do\n                {\n                } while ((TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) &&\n                         (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (--probe_len > 0));\n                cur_match_len = ((mz_uint)(p - (const mz_uint16 *)pCur_dict) * 2) + (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q);\n                if (!probe_len)\n                    cur_match_len = cur_match_dist ? TDEFL_MAX_MATCH_LEN : 0;\n\n                if ((cur_match_len < TDEFL_MIN_MATCH_LEN) || ((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U * 1024U)))\n                {\n                    cur_match_len = 1;\n                    *pLZ_code_buf++ = (mz_uint8)first_trigram;\n                    *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);\n                    d->m_huff_count[0][(mz_uint8)first_trigram]++;\n                }\n                else\n                {\n                    mz_uint32 s0, s1;\n                    cur_match_len = MZ_MIN(cur_match_len, lookahead_size);\n\n                    MZ_ASSERT((cur_match_len >= TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 1) && (cur_match_dist <= TDEFL_LZ_DICT_SIZE));\n\n                    cur_match_dist--;\n\n                    pLZ_code_buf[0] = (mz_uint8)(cur_match_len - TDEFL_MIN_MATCH_LEN);\n                    *(mz_uint16 *)(&pLZ_code_buf[1]) = (mz_uint16)cur_match_dist;\n                    pLZ_code_buf += 3;\n                    *pLZ_flags = (mz_uint8)((*pLZ_flags >> 1) | 0x80);\n\n                    s0 = s_tdefl_small_dist_sym[cur_match_dist & 511];\n                    s1 = s_tdefl_large_dist_sym[cur_match_dist >> 8];\n                    d->m_huff_count[1][(cur_match_dist < 512) ? s0 : s1]++;\n\n                    d->m_huff_count[0][s_tdefl_len_sym[cur_match_len - TDEFL_MIN_MATCH_LEN]]++;\n                }\n            }\n            else\n            {\n                *pLZ_code_buf++ = (mz_uint8)first_trigram;\n                *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);\n                d->m_huff_count[0][(mz_uint8)first_trigram]++;\n            }\n\n            if (--num_flags_left == 0)\n            {\n                num_flags_left = 8;\n                pLZ_flags = pLZ_code_buf++;\n            }\n\n            total_lz_bytes += cur_match_len;\n            lookahead_pos += cur_match_len;\n            dict_size = MZ_MIN(dict_size + cur_match_len, (mz_uint)TDEFL_LZ_DICT_SIZE);\n            cur_pos = (cur_pos + cur_match_len) & TDEFL_LZ_DICT_SIZE_MASK;\n            MZ_ASSERT(lookahead_size >= cur_match_len);\n            lookahead_size -= cur_match_len;\n\n            if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8])\n            {\n                int n;\n                d->m_lookahead_pos = lookahead_pos;\n                d->m_lookahead_size = lookahead_size;\n                d->m_dict_size = dict_size;\n                d->m_total_lz_bytes = total_lz_bytes;\n                d->m_pLZ_code_buf = pLZ_code_buf;\n                d->m_pLZ_flags = pLZ_flags;\n                d->m_num_flags_left = num_flags_left;\n                if ((n = tdefl_flush_block(d, 0)) != 0)\n                    return (n < 0) ? MZ_FALSE : MZ_TRUE;\n                total_lz_bytes = d->m_total_lz_bytes;\n                pLZ_code_buf = d->m_pLZ_code_buf;\n                pLZ_flags = d->m_pLZ_flags;\n                num_flags_left = d->m_num_flags_left;\n            }\n        }\n\n        while (lookahead_size)\n        {\n            mz_uint8 lit = d->m_dict[cur_pos];\n\n            total_lz_bytes++;\n            *pLZ_code_buf++ = lit;\n            *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);\n            if (--num_flags_left == 0)\n            {\n                num_flags_left = 8;\n                pLZ_flags = pLZ_code_buf++;\n            }\n\n            d->m_huff_count[0][lit]++;\n\n            lookahead_pos++;\n            dict_size = MZ_MIN(dict_size + 1, (mz_uint)TDEFL_LZ_DICT_SIZE);\n            cur_pos = (cur_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK;\n            lookahead_size--;\n\n            if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8])\n            {\n                int n;\n                d->m_lookahead_pos = lookahead_pos;\n                d->m_lookahead_size = lookahead_size;\n                d->m_dict_size = dict_size;\n                d->m_total_lz_bytes = total_lz_bytes;\n                d->m_pLZ_code_buf = pLZ_code_buf;\n                d->m_pLZ_flags = pLZ_flags;\n                d->m_num_flags_left = num_flags_left;\n                if ((n = tdefl_flush_block(d, 0)) != 0)\n                    return (n < 0) ? MZ_FALSE : MZ_TRUE;\n                total_lz_bytes = d->m_total_lz_bytes;\n                pLZ_code_buf = d->m_pLZ_code_buf;\n                pLZ_flags = d->m_pLZ_flags;\n                num_flags_left = d->m_num_flags_left;\n            }\n        }\n    }\n\n    d->m_lookahead_pos = lookahead_pos;\n    d->m_lookahead_size = lookahead_size;\n    d->m_dict_size = dict_size;\n    d->m_total_lz_bytes = total_lz_bytes;\n    d->m_pLZ_code_buf = pLZ_code_buf;\n    d->m_pLZ_flags = pLZ_flags;\n    d->m_num_flags_left = num_flags_left;\n    return MZ_TRUE;\n}\n#endif /* MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN */\n\nstatic MZ_FORCEINLINE void tdefl_record_literal(tdefl_compressor *d, mz_uint8 lit)\n{\n    d->m_total_lz_bytes++;\n    *d->m_pLZ_code_buf++ = lit;\n    *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> 1);\n    if (--d->m_num_flags_left == 0)\n    {\n        d->m_num_flags_left = 8;\n        d->m_pLZ_flags = d->m_pLZ_code_buf++;\n    }\n    d->m_huff_count[0][lit]++;\n}\n\nstatic MZ_FORCEINLINE void tdefl_record_match(tdefl_compressor *d, mz_uint match_len, mz_uint match_dist)\n{\n    mz_uint32 s0, s1;\n\n    MZ_ASSERT((match_len >= TDEFL_MIN_MATCH_LEN) && (match_dist >= 1) && (match_dist <= TDEFL_LZ_DICT_SIZE));\n\n    d->m_total_lz_bytes += match_len;\n\n    d->m_pLZ_code_buf[0] = (mz_uint8)(match_len - TDEFL_MIN_MATCH_LEN);\n\n    match_dist -= 1;\n    d->m_pLZ_code_buf[1] = (mz_uint8)(match_dist & 0xFF);\n    d->m_pLZ_code_buf[2] = (mz_uint8)(match_dist >> 8);\n    d->m_pLZ_code_buf += 3;\n\n    *d->m_pLZ_flags = (mz_uint8)((*d->m_pLZ_flags >> 1) | 0x80);\n    if (--d->m_num_flags_left == 0)\n    {\n        d->m_num_flags_left = 8;\n        d->m_pLZ_flags = d->m_pLZ_code_buf++;\n    }\n\n    s0 = s_tdefl_small_dist_sym[match_dist & 511];\n    s1 = s_tdefl_large_dist_sym[(match_dist >> 8) & 127];\n    d->m_huff_count[1][(match_dist < 512) ? s0 : s1]++;\n\n    if (match_len >= TDEFL_MIN_MATCH_LEN)\n        d->m_huff_count[0][s_tdefl_len_sym[match_len - TDEFL_MIN_MATCH_LEN]]++;\n}\n\nstatic mz_bool tdefl_compress_normal(tdefl_compressor *d)\n{\n    const mz_uint8 *pSrc = d->m_pSrc;\n    size_t src_buf_left = d->m_src_buf_left;\n    tdefl_flush flush = d->m_flush;\n\n    while ((src_buf_left) || ((flush) && (d->m_lookahead_size)))\n    {\n        mz_uint len_to_move, cur_match_dist, cur_match_len, cur_pos;\n        /* Update dictionary and hash chains. Keeps the lookahead size equal to TDEFL_MAX_MATCH_LEN. */\n        if ((d->m_lookahead_size + d->m_dict_size) >= (TDEFL_MIN_MATCH_LEN - 1))\n        {\n            mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK, ins_pos = d->m_lookahead_pos + d->m_lookahead_size - 2;\n            mz_uint hash = (d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK];\n            mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(src_buf_left, TDEFL_MAX_MATCH_LEN - d->m_lookahead_size);\n            const mz_uint8 *pSrc_end = pSrc + num_bytes_to_process;\n            src_buf_left -= num_bytes_to_process;\n            d->m_lookahead_size += num_bytes_to_process;\n            while (pSrc != pSrc_end)\n            {\n                mz_uint8 c = *pSrc++;\n                d->m_dict[dst_pos] = c;\n                if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))\n                    d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;\n                hash = ((hash << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1);\n                d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash];\n                d->m_hash[hash] = (mz_uint16)(ins_pos);\n                dst_pos = (dst_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK;\n                ins_pos++;\n            }\n        }\n        else\n        {\n            while ((src_buf_left) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN))\n            {\n                mz_uint8 c = *pSrc++;\n                mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK;\n                src_buf_left--;\n                d->m_dict[dst_pos] = c;\n                if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))\n                    d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;\n                if ((++d->m_lookahead_size + d->m_dict_size) >= TDEFL_MIN_MATCH_LEN)\n                {\n                    mz_uint ins_pos = d->m_lookahead_pos + (d->m_lookahead_size - 1) - 2;\n                    mz_uint hash = ((d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << (TDEFL_LZ_HASH_SHIFT * 2)) ^ (d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1);\n                    d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash];\n                    d->m_hash[hash] = (mz_uint16)(ins_pos);\n                }\n            }\n        }\n        d->m_dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - d->m_lookahead_size, d->m_dict_size);\n        if ((!flush) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN))\n            break;\n\n        /* Simple lazy/greedy parsing state machine. */\n        len_to_move = 1;\n        cur_match_dist = 0;\n        cur_match_len = d->m_saved_match_len ? d->m_saved_match_len : (TDEFL_MIN_MATCH_LEN - 1);\n        cur_pos = d->m_lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;\n        if (d->m_flags & (TDEFL_RLE_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS))\n        {\n            if ((d->m_dict_size) && (!(d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS)))\n            {\n                mz_uint8 c = d->m_dict[(cur_pos - 1) & TDEFL_LZ_DICT_SIZE_MASK];\n                cur_match_len = 0;\n                while (cur_match_len < d->m_lookahead_size)\n                {\n                    if (d->m_dict[cur_pos + cur_match_len] != c)\n                        break;\n                    cur_match_len++;\n                }\n                if (cur_match_len < TDEFL_MIN_MATCH_LEN)\n                    cur_match_len = 0;\n                else\n                    cur_match_dist = 1;\n            }\n        }\n        else\n        {\n            tdefl_find_match(d, d->m_lookahead_pos, d->m_dict_size, d->m_lookahead_size, &cur_match_dist, &cur_match_len);\n        }\n        if (((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U * 1024U)) || (cur_pos == cur_match_dist) || ((d->m_flags & TDEFL_FILTER_MATCHES) && (cur_match_len <= 5)))\n        {\n            cur_match_dist = cur_match_len = 0;\n        }\n        if (d->m_saved_match_len)\n        {\n            if (cur_match_len > d->m_saved_match_len)\n            {\n                tdefl_record_literal(d, (mz_uint8)d->m_saved_lit);\n                if (cur_match_len >= 128)\n                {\n                    tdefl_record_match(d, cur_match_len, cur_match_dist);\n                    d->m_saved_match_len = 0;\n                    len_to_move = cur_match_len;\n                }\n                else\n                {\n                    d->m_saved_lit = d->m_dict[cur_pos];\n                    d->m_saved_match_dist = cur_match_dist;\n                    d->m_saved_match_len = cur_match_len;\n                }\n            }\n            else\n            {\n                tdefl_record_match(d, d->m_saved_match_len, d->m_saved_match_dist);\n                len_to_move = d->m_saved_match_len - 1;\n                d->m_saved_match_len = 0;\n            }\n        }\n        else if (!cur_match_dist)\n            tdefl_record_literal(d, d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]);\n        else if ((d->m_greedy_parsing) || (d->m_flags & TDEFL_RLE_MATCHES) || (cur_match_len >= 128))\n        {\n            tdefl_record_match(d, cur_match_len, cur_match_dist);\n            len_to_move = cur_match_len;\n        }\n        else\n        {\n            d->m_saved_lit = d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)];\n            d->m_saved_match_dist = cur_match_dist;\n            d->m_saved_match_len = cur_match_len;\n        }\n        /* Move the lookahead forward by len_to_move bytes. */\n        d->m_lookahead_pos += len_to_move;\n        MZ_ASSERT(d->m_lookahead_size >= len_to_move);\n        d->m_lookahead_size -= len_to_move;\n        d->m_dict_size = MZ_MIN(d->m_dict_size + len_to_move, (mz_uint)TDEFL_LZ_DICT_SIZE);\n        /* Check if it's time to flush the current LZ codes to the internal output buffer. */\n        if ((d->m_pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) ||\n            ((d->m_total_lz_bytes > 31 * 1024) && (((((mz_uint)(d->m_pLZ_code_buf - d->m_lz_code_buf) * 115) >> 7) >= d->m_total_lz_bytes) || (d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS))))\n        {\n            int n;\n            d->m_pSrc = pSrc;\n            d->m_src_buf_left = src_buf_left;\n            if ((n = tdefl_flush_block(d, 0)) != 0)\n                return (n < 0) ? MZ_FALSE : MZ_TRUE;\n        }\n    }\n\n    d->m_pSrc = pSrc;\n    d->m_src_buf_left = src_buf_left;\n    return MZ_TRUE;\n}\n\nstatic tdefl_status tdefl_flush_output_buffer(tdefl_compressor *d)\n{\n    if (d->m_pIn_buf_size)\n    {\n        *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;\n    }\n\n    if (d->m_pOut_buf_size)\n    {\n        size_t n = MZ_MIN(*d->m_pOut_buf_size - d->m_out_buf_ofs, d->m_output_flush_remaining);\n        memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf + d->m_output_flush_ofs, n);\n        d->m_output_flush_ofs += (mz_uint)n;\n        d->m_output_flush_remaining -= (mz_uint)n;\n        d->m_out_buf_ofs += n;\n\n        *d->m_pOut_buf_size = d->m_out_buf_ofs;\n    }\n\n    return (d->m_finished && !d->m_output_flush_remaining) ? TDEFL_STATUS_DONE : TDEFL_STATUS_OKAY;\n}\n\ntdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush)\n{\n    if (!d)\n    {\n        if (pIn_buf_size)\n            *pIn_buf_size = 0;\n        if (pOut_buf_size)\n            *pOut_buf_size = 0;\n        return TDEFL_STATUS_BAD_PARAM;\n    }\n\n    d->m_pIn_buf = pIn_buf;\n    d->m_pIn_buf_size = pIn_buf_size;\n    d->m_pOut_buf = pOut_buf;\n    d->m_pOut_buf_size = pOut_buf_size;\n    d->m_pSrc = (const mz_uint8 *)(pIn_buf);\n    d->m_src_buf_left = pIn_buf_size ? *pIn_buf_size : 0;\n    d->m_out_buf_ofs = 0;\n    d->m_flush = flush;\n\n    if (((d->m_pPut_buf_func != NULL) == ((pOut_buf != NULL) || (pOut_buf_size != NULL))) || (d->m_prev_return_status != TDEFL_STATUS_OKAY) ||\n        (d->m_wants_to_finish && (flush != TDEFL_FINISH)) || (pIn_buf_size && *pIn_buf_size && !pIn_buf) || (pOut_buf_size && *pOut_buf_size && !pOut_buf))\n    {\n        if (pIn_buf_size)\n            *pIn_buf_size = 0;\n        if (pOut_buf_size)\n            *pOut_buf_size = 0;\n        return (d->m_prev_return_status = TDEFL_STATUS_BAD_PARAM);\n    }\n    d->m_wants_to_finish |= (flush == TDEFL_FINISH);\n\n    if ((d->m_output_flush_remaining) || (d->m_finished))\n        return (d->m_prev_return_status = tdefl_flush_output_buffer(d));\n\n#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN\n    if (((d->m_flags & TDEFL_MAX_PROBES_MASK) == 1) &&\n        ((d->m_flags & TDEFL_GREEDY_PARSING_FLAG) != 0) &&\n        ((d->m_flags & (TDEFL_FILTER_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS | TDEFL_RLE_MATCHES)) == 0))\n    {\n        if (!tdefl_compress_fast(d))\n            return d->m_prev_return_status;\n    }\n    else\n#endif /* #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN */\n    {\n        if (!tdefl_compress_normal(d))\n            return d->m_prev_return_status;\n    }\n\n    if ((d->m_flags & (TDEFL_WRITE_ZLIB_HEADER | TDEFL_COMPUTE_ADLER32)) && (pIn_buf))\n        d->m_adler32 = (mz_uint32)mz_adler32(d->m_adler32, (const mz_uint8 *)pIn_buf, d->m_pSrc - (const mz_uint8 *)pIn_buf);\n\n    if ((flush) && (!d->m_lookahead_size) && (!d->m_src_buf_left) && (!d->m_output_flush_remaining))\n    {\n        if (tdefl_flush_block(d, flush) < 0)\n            return d->m_prev_return_status;\n        d->m_finished = (flush == TDEFL_FINISH);\n        if (flush == TDEFL_FULL_FLUSH)\n        {\n            MZ_CLEAR_OBJ(d->m_hash);\n            MZ_CLEAR_OBJ(d->m_next);\n            d->m_dict_size = 0;\n        }\n    }\n\n    return (d->m_prev_return_status = tdefl_flush_output_buffer(d));\n}\n\ntdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush)\n{\n    MZ_ASSERT(d->m_pPut_buf_func);\n    return tdefl_compress(d, pIn_buf, &in_buf_size, NULL, NULL, flush);\n}\n\ntdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)\n{\n    d->m_pPut_buf_func = pPut_buf_func;\n    d->m_pPut_buf_user = pPut_buf_user;\n    d->m_flags = (mz_uint)(flags);\n    d->m_max_probes[0] = 1 + ((flags & 0xFFF) + 2) / 3;\n    d->m_greedy_parsing = (flags & TDEFL_GREEDY_PARSING_FLAG) != 0;\n    d->m_max_probes[1] = 1 + (((flags & 0xFFF) >> 2) + 2) / 3;\n    if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG))\n        MZ_CLEAR_OBJ(d->m_hash);\n    d->m_lookahead_pos = d->m_lookahead_size = d->m_dict_size = d->m_total_lz_bytes = d->m_lz_code_buf_dict_pos = d->m_bits_in = 0;\n    d->m_output_flush_ofs = d->m_output_flush_remaining = d->m_finished = d->m_block_index = d->m_bit_buffer = d->m_wants_to_finish = 0;\n    d->m_pLZ_code_buf = d->m_lz_code_buf + 1;\n    d->m_pLZ_flags = d->m_lz_code_buf;\n    d->m_num_flags_left = 8;\n    d->m_pOutput_buf = d->m_output_buf;\n    d->m_pOutput_buf_end = d->m_output_buf;\n    d->m_prev_return_status = TDEFL_STATUS_OKAY;\n    d->m_saved_match_dist = d->m_saved_match_len = d->m_saved_lit = 0;\n    d->m_adler32 = 1;\n    d->m_pIn_buf = NULL;\n    d->m_pOut_buf = NULL;\n    d->m_pIn_buf_size = NULL;\n    d->m_pOut_buf_size = NULL;\n    d->m_flush = TDEFL_NO_FLUSH;\n    d->m_pSrc = NULL;\n    d->m_src_buf_left = 0;\n    d->m_out_buf_ofs = 0;\n    if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG))\n        MZ_CLEAR_OBJ(d->m_dict);\n    memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);\n    memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);\n    return TDEFL_STATUS_OKAY;\n}\n\ntdefl_status tdefl_get_prev_return_status(tdefl_compressor *d)\n{\n    return d->m_prev_return_status;\n}\n\nmz_uint32 tdefl_get_adler32(tdefl_compressor *d)\n{\n    return d->m_adler32;\n}\n\nmz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)\n{\n    tdefl_compressor *pComp;\n    mz_bool succeeded;\n    if (((buf_len) && (!pBuf)) || (!pPut_buf_func))\n        return MZ_FALSE;\n    pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor));\n    if (!pComp)\n        return MZ_FALSE;\n    succeeded = (tdefl_init(pComp, pPut_buf_func, pPut_buf_user, flags) == TDEFL_STATUS_OKAY);\n    succeeded = succeeded && (tdefl_compress_buffer(pComp, pBuf, buf_len, TDEFL_FINISH) == TDEFL_STATUS_DONE);\n    MZ_FREE(pComp);\n    return succeeded;\n}\n\ntypedef struct\n{\n    size_t m_size, m_capacity;\n    mz_uint8 *m_pBuf;\n    mz_bool m_expandable;\n} tdefl_output_buffer;\n\nstatic mz_bool tdefl_output_buffer_putter(const void *pBuf, int len, void *pUser)\n{\n    tdefl_output_buffer *p = (tdefl_output_buffer *)pUser;\n    size_t new_size = p->m_size + len;\n    if (new_size > p->m_capacity)\n    {\n        size_t new_capacity = p->m_capacity;\n        mz_uint8 *pNew_buf;\n        if (!p->m_expandable)\n            return MZ_FALSE;\n        do\n        {\n            new_capacity = MZ_MAX(128U, new_capacity << 1U);\n        } while (new_size > new_capacity);\n        pNew_buf = (mz_uint8 *)MZ_REALLOC(p->m_pBuf, new_capacity);\n        if (!pNew_buf)\n            return MZ_FALSE;\n        p->m_pBuf = pNew_buf;\n        p->m_capacity = new_capacity;\n    }\n    memcpy((mz_uint8 *)p->m_pBuf + p->m_size, pBuf, len);\n    p->m_size = new_size;\n    return MZ_TRUE;\n}\n\nvoid *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags)\n{\n    tdefl_output_buffer out_buf;\n    MZ_CLEAR_OBJ(out_buf);\n    if (!pOut_len)\n        return MZ_FALSE;\n    else\n        *pOut_len = 0;\n    out_buf.m_expandable = MZ_TRUE;\n    if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags))\n        return NULL;\n    *pOut_len = out_buf.m_size;\n    return out_buf.m_pBuf;\n}\n\nsize_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags)\n{\n    tdefl_output_buffer out_buf;\n    MZ_CLEAR_OBJ(out_buf);\n    if (!pOut_buf)\n        return 0;\n    out_buf.m_pBuf = (mz_uint8 *)pOut_buf;\n    out_buf.m_capacity = out_buf_len;\n    if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags))\n        return 0;\n    return out_buf.m_size;\n}\n\nstatic const mz_uint s_tdefl_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 };\n\n/* level may actually range from [0,10] (10 is a \"hidden\" max level, where we want a bit more compression and it's fine if throughput to fall off a cliff on some files). */\nmz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy)\n{\n    mz_uint comp_flags = s_tdefl_num_probes[(level >= 0) ? MZ_MIN(10, level) : MZ_DEFAULT_LEVEL] | ((level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0);\n    if (window_bits > 0)\n        comp_flags |= TDEFL_WRITE_ZLIB_HEADER;\n\n    if (!level)\n        comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS;\n    else if (strategy == MZ_FILTERED)\n        comp_flags |= TDEFL_FILTER_MATCHES;\n    else if (strategy == MZ_HUFFMAN_ONLY)\n        comp_flags &= ~TDEFL_MAX_PROBES_MASK;\n    else if (strategy == MZ_FIXED)\n        comp_flags |= TDEFL_FORCE_ALL_STATIC_BLOCKS;\n    else if (strategy == MZ_RLE)\n        comp_flags |= TDEFL_RLE_MATCHES;\n\n    return comp_flags;\n}\n\n#ifdef _MSC_VER\n#pragma warning(push)\n#pragma warning(disable : 4204) /* nonstandard extension used : non-constant aggregate initializer (also supported by GNU C and C99, so no big deal) */\n#endif\n\n/* Simple PNG writer function by Alex Evans, 2011. Released into the public domain: https://gist.github.com/908299, more context at\n http://altdevblogaday.org/2011/04/06/a-smaller-jpg-encoder/.\n This is actually a modification of Alex's original code so PNG files generated by this function pass pngcheck. */\nvoid *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, size_t *pLen_out, mz_uint level, mz_bool flip)\n{\n    /* Using a local copy of this array here in case MINIZ_NO_ZLIB_APIS was defined. */\n    static const mz_uint s_tdefl_png_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 };\n    tdefl_compressor *pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor));\n    tdefl_output_buffer out_buf;\n    int i, bpl = w * num_chans, y, z;\n    mz_uint32 c;\n    *pLen_out = 0;\n    if (!pComp)\n        return NULL;\n    MZ_CLEAR_OBJ(out_buf);\n    out_buf.m_expandable = MZ_TRUE;\n    out_buf.m_capacity = 57 + MZ_MAX(64, (1 + bpl) * h);\n    if (NULL == (out_buf.m_pBuf = (mz_uint8 *)MZ_MALLOC(out_buf.m_capacity)))\n    {\n        MZ_FREE(pComp);\n        return NULL;\n    }\n    /* write dummy header */\n    for (z = 41; z; --z)\n        tdefl_output_buffer_putter(&z, 1, &out_buf);\n    /* compress image data */\n    tdefl_init(pComp, tdefl_output_buffer_putter, &out_buf, s_tdefl_png_num_probes[MZ_MIN(10, level)] | TDEFL_WRITE_ZLIB_HEADER);\n    for (y = 0; y < h; ++y)\n    {\n        tdefl_compress_buffer(pComp, &z, 1, TDEFL_NO_FLUSH);\n        tdefl_compress_buffer(pComp, (mz_uint8 *)pImage + (flip ? (h - 1 - y) : y) * bpl, bpl, TDEFL_NO_FLUSH);\n    }\n    if (tdefl_compress_buffer(pComp, NULL, 0, TDEFL_FINISH) != TDEFL_STATUS_DONE)\n    {\n        MZ_FREE(pComp);\n        MZ_FREE(out_buf.m_pBuf);\n        return NULL;\n    }\n    /* write real header */\n    *pLen_out = out_buf.m_size - 41;\n    {\n        static const mz_uint8 chans[] = { 0x00, 0x00, 0x04, 0x02, 0x06 };\n        mz_uint8 pnghdr[41] = { 0x89, 0x50, 0x4e, 0x47, 0x0d,\n                                0x0a, 0x1a, 0x0a, 0x00, 0x00,\n                                0x00, 0x0d, 0x49, 0x48, 0x44,\n                                0x52, 0x00, 0x00, 0x00, 0x00,\n                                0x00, 0x00, 0x00, 0x00, 0x08,\n                                0x00, 0x00, 0x00, 0x00, 0x00,\n                                0x00, 0x00, 0x00, 0x00, 0x00,\n                                0x00, 0x00, 0x49, 0x44, 0x41,\n                                0x54 };\n        pnghdr[18] = (mz_uint8)(w >> 8);\n        pnghdr[19] = (mz_uint8)w;\n        pnghdr[22] = (mz_uint8)(h >> 8);\n        pnghdr[23] = (mz_uint8)h;\n        pnghdr[25] = chans[num_chans];\n        pnghdr[33] = (mz_uint8)(*pLen_out >> 24);\n        pnghdr[34] = (mz_uint8)(*pLen_out >> 16);\n        pnghdr[35] = (mz_uint8)(*pLen_out >> 8);\n        pnghdr[36] = (mz_uint8)*pLen_out;\n        c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, pnghdr + 12, 17);\n        for (i = 0; i < 4; ++i, c <<= 8)\n            ((mz_uint8 *)(pnghdr + 29))[i] = (mz_uint8)(c >> 24);\n        memcpy(out_buf.m_pBuf, pnghdr, 41);\n    }\n    /* write footer (IDAT CRC-32, followed by IEND chunk) */\n    if (!tdefl_output_buffer_putter(\"\\0\\0\\0\\0\\0\\0\\0\\0\\x49\\x45\\x4e\\x44\\xae\\x42\\x60\\x82\", 16, &out_buf))\n    {\n        *pLen_out = 0;\n        MZ_FREE(pComp);\n        MZ_FREE(out_buf.m_pBuf);\n        return NULL;\n    }\n    c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, out_buf.m_pBuf + 41 - 4, *pLen_out + 4);\n    for (i = 0; i < 4; ++i, c <<= 8)\n        (out_buf.m_pBuf + out_buf.m_size - 16)[i] = (mz_uint8)(c >> 24);\n    /* compute final size of file, grab compressed data buffer and return */\n    *pLen_out += 57;\n    MZ_FREE(pComp);\n    return out_buf.m_pBuf;\n}\nvoid *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out)\n{\n    /* Level 6 corresponds to TDEFL_DEFAULT_MAX_PROBES or MZ_DEFAULT_LEVEL (but we can't depend on MZ_DEFAULT_LEVEL being available in case the zlib API's where #defined out) */\n    return tdefl_write_image_to_png_file_in_memory_ex(pImage, w, h, num_chans, pLen_out, 6, MZ_FALSE);\n}\n\n/* Allocate the tdefl_compressor and tinfl_decompressor structures in C so that */\n/* non-C language bindings to tdefL_ and tinfl_ API don't need to worry about */\n/* structure size and allocation mechanism. */\ntdefl_compressor *tdefl_compressor_alloc()\n{\n    return (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor));\n}\n\nvoid tdefl_compressor_free(tdefl_compressor *pComp)\n{\n    MZ_FREE(pComp);\n}\n\n#ifdef _MSC_VER\n#pragma warning(pop)\n#endif\n\n#ifdef __cplusplus\n}\n#endif\n/**************************************************************************\n *\n * Copyright 2013-2014 RAD Game Tools and Valve Software\n * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC\n * All Rights Reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n **************************************************************************/\n\n\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* ------------------- Low-level Decompression (completely independent from all compression API's) */\n\n#define TINFL_MEMCPY(d, s, l) memcpy(d, s, l)\n#define TINFL_MEMSET(p, c, l) memset(p, c, l)\n\n#define TINFL_CR_BEGIN  \\\n    switch (r->m_state) \\\n    {                   \\\n        case 0:\n#define TINFL_CR_RETURN(state_index, result) \\\n    do                                       \\\n    {                                        \\\n        status = result;                     \\\n        r->m_state = state_index;            \\\n        goto common_exit;                    \\\n        case state_index:;                   \\\n    }                                        \\\n    MZ_MACRO_END\n#define TINFL_CR_RETURN_FOREVER(state_index, result) \\\n    do                                               \\\n    {                                                \\\n        for (;;)                                     \\\n        {                                            \\\n            TINFL_CR_RETURN(state_index, result);    \\\n        }                                            \\\n    }                                                \\\n    MZ_MACRO_END\n#define TINFL_CR_FINISH }\n\n#define TINFL_GET_BYTE(state_index, c)                                                                                                                           \\\n    do                                                                                                                                                           \\\n    {                                                                                                                                                            \\\n        while (pIn_buf_cur >= pIn_buf_end)                                                                                                                       \\\n        {                                                                                                                                                        \\\n            TINFL_CR_RETURN(state_index, (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) ? TINFL_STATUS_NEEDS_MORE_INPUT : TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS); \\\n        }                                                                                                                                                        \\\n        c = *pIn_buf_cur++;                                                                                                                                      \\\n    }                                                                                                                                                            \\\n    MZ_MACRO_END\n\n#define TINFL_NEED_BITS(state_index, n)                \\\n    do                                                 \\\n    {                                                  \\\n        mz_uint c;                                     \\\n        TINFL_GET_BYTE(state_index, c);                \\\n        bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); \\\n        num_bits += 8;                                 \\\n    } while (num_bits < (mz_uint)(n))\n#define TINFL_SKIP_BITS(state_index, n)      \\\n    do                                       \\\n    {                                        \\\n        if (num_bits < (mz_uint)(n))         \\\n        {                                    \\\n            TINFL_NEED_BITS(state_index, n); \\\n        }                                    \\\n        bit_buf >>= (n);                     \\\n        num_bits -= (n);                     \\\n    }                                        \\\n    MZ_MACRO_END\n#define TINFL_GET_BITS(state_index, b, n)    \\\n    do                                       \\\n    {                                        \\\n        if (num_bits < (mz_uint)(n))         \\\n        {                                    \\\n            TINFL_NEED_BITS(state_index, n); \\\n        }                                    \\\n        b = bit_buf & ((1 << (n)) - 1);      \\\n        bit_buf >>= (n);                     \\\n        num_bits -= (n);                     \\\n    }                                        \\\n    MZ_MACRO_END\n\n/* TINFL_HUFF_BITBUF_FILL() is only used rarely, when the number of bytes remaining in the input buffer falls below 2. */\n/* It reads just enough bytes from the input stream that are needed to decode the next Huffman code (and absolutely no more). It works by trying to fully decode a */\n/* Huffman code by using whatever bits are currently present in the bit buffer. If this fails, it reads another byte, and tries again until it succeeds or until the */\n/* bit buffer contains >=15 bits (deflate's max. Huffman code size). */\n#define TINFL_HUFF_BITBUF_FILL(state_index, pHuff)                             \\\n    do                                                                         \\\n    {                                                                          \\\n        temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)];     \\\n        if (temp >= 0)                                                         \\\n        {                                                                      \\\n            code_len = temp >> 9;                                              \\\n            if ((code_len) && (num_bits >= code_len))                          \\\n                break;                                                         \\\n        }                                                                      \\\n        else if (num_bits > TINFL_FAST_LOOKUP_BITS)                            \\\n        {                                                                      \\\n            code_len = TINFL_FAST_LOOKUP_BITS;                                 \\\n            do                                                                 \\\n            {                                                                  \\\n                temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \\\n            } while ((temp < 0) && (num_bits >= (code_len + 1)));              \\\n            if (temp >= 0)                                                     \\\n                break;                                                         \\\n        }                                                                      \\\n        TINFL_GET_BYTE(state_index, c);                                        \\\n        bit_buf |= (((tinfl_bit_buf_t)c) << num_bits);                         \\\n        num_bits += 8;                                                         \\\n    } while (num_bits < 15);\n\n/* TINFL_HUFF_DECODE() decodes the next Huffman coded symbol. It's more complex than you would initially expect because the zlib API expects the decompressor to never read */\n/* beyond the final byte of the deflate stream. (In other words, when this macro wants to read another byte from the input, it REALLY needs another byte in order to fully */\n/* decode the next Huffman code.) Handling this properly is particularly important on raw deflate (non-zlib) streams, which aren't followed by a byte aligned adler-32. */\n/* The slow path is only executed at the very end of the input buffer. */\n/* v1.16: The original macro handled the case at the very end of the passed-in input buffer, but we also need to handle the case where the user passes in 1+zillion bytes */\n/* following the deflate data and our non-conservative read-ahead path won't kick in here on this code. This is much trickier. */\n#define TINFL_HUFF_DECODE(state_index, sym, pHuff)                                                                                  \\\n    do                                                                                                                              \\\n    {                                                                                                                               \\\n        int temp;                                                                                                                   \\\n        mz_uint code_len, c;                                                                                                        \\\n        if (num_bits < 15)                                                                                                          \\\n        {                                                                                                                           \\\n            if ((pIn_buf_end - pIn_buf_cur) < 2)                                                                                    \\\n            {                                                                                                                       \\\n                TINFL_HUFF_BITBUF_FILL(state_index, pHuff);                                                                         \\\n            }                                                                                                                       \\\n            else                                                                                                                    \\\n            {                                                                                                                       \\\n                bit_buf |= (((tinfl_bit_buf_t)pIn_buf_cur[0]) << num_bits) | (((tinfl_bit_buf_t)pIn_buf_cur[1]) << (num_bits + 8)); \\\n                pIn_buf_cur += 2;                                                                                                   \\\n                num_bits += 16;                                                                                                     \\\n            }                                                                                                                       \\\n        }                                                                                                                           \\\n        if ((temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)                                               \\\n            code_len = temp >> 9, temp &= 511;                                                                                      \\\n        else                                                                                                                        \\\n        {                                                                                                                           \\\n            code_len = TINFL_FAST_LOOKUP_BITS;                                                                                      \\\n            do                                                                                                                      \\\n            {                                                                                                                       \\\n                temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)];                                                      \\\n            } while (temp < 0);                                                                                                     \\\n        }                                                                                                                           \\\n        sym = temp;                                                                                                                 \\\n        bit_buf >>= code_len;                                                                                                       \\\n        num_bits -= code_len;                                                                                                       \\\n    }                                                                                                                               \\\n    MZ_MACRO_END\n\ntinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags)\n{\n    static const int s_length_base[31] = { 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 };\n    static const int s_length_extra[31] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 0, 0 };\n    static const int s_dist_base[32] = { 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 0, 0 };\n    static const int s_dist_extra[32] = { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 };\n    static const mz_uint8 s_length_dezigzag[19] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };\n    static const int s_min_table_sizes[3] = { 257, 1, 4 };\n\n    tinfl_status status = TINFL_STATUS_FAILED;\n    mz_uint32 num_bits, dist, counter, num_extra;\n    tinfl_bit_buf_t bit_buf;\n    const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end = pIn_buf_next + *pIn_buf_size;\n    mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end = pOut_buf_next + *pOut_buf_size;\n    size_t out_buf_size_mask = (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF) ? (size_t)-1 : ((pOut_buf_next - pOut_buf_start) + *pOut_buf_size) - 1, dist_from_out_buf_start;\n\n    /* Ensure the output buffer's size is a power of 2, unless the output buffer is large enough to hold the entire output file (in which case it doesn't matter). */\n    if (((out_buf_size_mask + 1) & out_buf_size_mask) || (pOut_buf_next < pOut_buf_start))\n    {\n        *pIn_buf_size = *pOut_buf_size = 0;\n        return TINFL_STATUS_BAD_PARAM;\n    }\n\n    num_bits = r->m_num_bits;\n    bit_buf = r->m_bit_buf;\n    dist = r->m_dist;\n    counter = r->m_counter;\n    num_extra = r->m_num_extra;\n    dist_from_out_buf_start = r->m_dist_from_out_buf_start;\n    TINFL_CR_BEGIN\n\n    bit_buf = num_bits = dist = counter = num_extra = r->m_zhdr0 = r->m_zhdr1 = 0;\n    r->m_z_adler32 = r->m_check_adler32 = 1;\n    if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)\n    {\n        TINFL_GET_BYTE(1, r->m_zhdr0);\n        TINFL_GET_BYTE(2, r->m_zhdr1);\n        counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) || (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8));\n        if (!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))\n            counter |= (((1U << (8U + (r->m_zhdr0 >> 4))) > 32768U) || ((out_buf_size_mask + 1) < (size_t)(1U << (8U + (r->m_zhdr0 >> 4)))));\n        if (counter)\n        {\n            TINFL_CR_RETURN_FOREVER(36, TINFL_STATUS_FAILED);\n        }\n    }\n\n    do\n    {\n        TINFL_GET_BITS(3, r->m_final, 3);\n        r->m_type = r->m_final >> 1;\n        if (r->m_type == 0)\n        {\n            TINFL_SKIP_BITS(5, num_bits & 7);\n            for (counter = 0; counter < 4; ++counter)\n            {\n                if (num_bits)\n                    TINFL_GET_BITS(6, r->m_raw_header[counter], 8);\n                else\n                    TINFL_GET_BYTE(7, r->m_raw_header[counter]);\n            }\n            if ((counter = (r->m_raw_header[0] | (r->m_raw_header[1] << 8))) != (mz_uint)(0xFFFF ^ (r->m_raw_header[2] | (r->m_raw_header[3] << 8))))\n            {\n                TINFL_CR_RETURN_FOREVER(39, TINFL_STATUS_FAILED);\n            }\n            while ((counter) && (num_bits))\n            {\n                TINFL_GET_BITS(51, dist, 8);\n                while (pOut_buf_cur >= pOut_buf_end)\n                {\n                    TINFL_CR_RETURN(52, TINFL_STATUS_HAS_MORE_OUTPUT);\n                }\n                *pOut_buf_cur++ = (mz_uint8)dist;\n                counter--;\n            }\n            while (counter)\n            {\n                size_t n;\n                while (pOut_buf_cur >= pOut_buf_end)\n                {\n                    TINFL_CR_RETURN(9, TINFL_STATUS_HAS_MORE_OUTPUT);\n                }\n                while (pIn_buf_cur >= pIn_buf_end)\n                {\n                    TINFL_CR_RETURN(38, (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) ? TINFL_STATUS_NEEDS_MORE_INPUT : TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS);\n                }\n                n = MZ_MIN(MZ_MIN((size_t)(pOut_buf_end - pOut_buf_cur), (size_t)(pIn_buf_end - pIn_buf_cur)), counter);\n                TINFL_MEMCPY(pOut_buf_cur, pIn_buf_cur, n);\n                pIn_buf_cur += n;\n                pOut_buf_cur += n;\n                counter -= (mz_uint)n;\n            }\n        }\n        else if (r->m_type == 3)\n        {\n            TINFL_CR_RETURN_FOREVER(10, TINFL_STATUS_FAILED);\n        }\n        else\n        {\n            if (r->m_type == 1)\n            {\n                mz_uint8 *p = r->m_tables[0].m_code_size;\n                mz_uint i;\n                r->m_table_sizes[0] = 288;\n                r->m_table_sizes[1] = 32;\n                TINFL_MEMSET(r->m_tables[1].m_code_size, 5, 32);\n                for (i = 0; i <= 143; ++i)\n                    *p++ = 8;\n                for (; i <= 255; ++i)\n                    *p++ = 9;\n                for (; i <= 279; ++i)\n                    *p++ = 7;\n                for (; i <= 287; ++i)\n                    *p++ = 8;\n            }\n            else\n            {\n                for (counter = 0; counter < 3; counter++)\n                {\n                    TINFL_GET_BITS(11, r->m_table_sizes[counter], \"\\05\\05\\04\"[counter]);\n                    r->m_table_sizes[counter] += s_min_table_sizes[counter];\n                }\n                MZ_CLEAR_OBJ(r->m_tables[2].m_code_size);\n                for (counter = 0; counter < r->m_table_sizes[2]; counter++)\n                {\n                    mz_uint s;\n                    TINFL_GET_BITS(14, s, 3);\n                    r->m_tables[2].m_code_size[s_length_dezigzag[counter]] = (mz_uint8)s;\n                }\n                r->m_table_sizes[2] = 19;\n            }\n            for (; (int)r->m_type >= 0; r->m_type--)\n            {\n                int tree_next, tree_cur;\n                tinfl_huff_table *pTable;\n                mz_uint i, j, used_syms, total, sym_index, next_code[17], total_syms[16];\n                pTable = &r->m_tables[r->m_type];\n                MZ_CLEAR_OBJ(total_syms);\n                MZ_CLEAR_OBJ(pTable->m_look_up);\n                MZ_CLEAR_OBJ(pTable->m_tree);\n                for (i = 0; i < r->m_table_sizes[r->m_type]; ++i)\n                    total_syms[pTable->m_code_size[i]]++;\n                used_syms = 0, total = 0;\n                next_code[0] = next_code[1] = 0;\n                for (i = 1; i <= 15; ++i)\n                {\n                    used_syms += total_syms[i];\n                    next_code[i + 1] = (total = ((total + total_syms[i]) << 1));\n                }\n                if ((65536 != total) && (used_syms > 1))\n                {\n                    TINFL_CR_RETURN_FOREVER(35, TINFL_STATUS_FAILED);\n                }\n                for (tree_next = -1, sym_index = 0; sym_index < r->m_table_sizes[r->m_type]; ++sym_index)\n                {\n                    mz_uint rev_code = 0, l, cur_code, code_size = pTable->m_code_size[sym_index];\n                    if (!code_size)\n                        continue;\n                    cur_code = next_code[code_size]++;\n                    for (l = code_size; l > 0; l--, cur_code >>= 1)\n                        rev_code = (rev_code << 1) | (cur_code & 1);\n                    if (code_size <= TINFL_FAST_LOOKUP_BITS)\n                    {\n                        mz_int16 k = (mz_int16)((code_size << 9) | sym_index);\n                        while (rev_code < TINFL_FAST_LOOKUP_SIZE)\n                        {\n                            pTable->m_look_up[rev_code] = k;\n                            rev_code += (1 << code_size);\n                        }\n                        continue;\n                    }\n                    if (0 == (tree_cur = pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)]))\n                    {\n                        pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)] = (mz_int16)tree_next;\n                        tree_cur = tree_next;\n                        tree_next -= 2;\n                    }\n                    rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1);\n                    for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--)\n                    {\n                        tree_cur -= ((rev_code >>= 1) & 1);\n                        if (!pTable->m_tree[-tree_cur - 1])\n                        {\n                            pTable->m_tree[-tree_cur - 1] = (mz_int16)tree_next;\n                            tree_cur = tree_next;\n                            tree_next -= 2;\n                        }\n                        else\n                            tree_cur = pTable->m_tree[-tree_cur - 1];\n                    }\n                    tree_cur -= ((rev_code >>= 1) & 1);\n                    pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index;\n                }\n                if (r->m_type == 2)\n                {\n                    for (counter = 0; counter < (r->m_table_sizes[0] + r->m_table_sizes[1]);)\n                    {\n                        mz_uint s;\n                        TINFL_HUFF_DECODE(16, dist, &r->m_tables[2]);\n                        if (dist < 16)\n                        {\n                            r->m_len_codes[counter++] = (mz_uint8)dist;\n                            continue;\n                        }\n                        if ((dist == 16) && (!counter))\n                        {\n                            TINFL_CR_RETURN_FOREVER(17, TINFL_STATUS_FAILED);\n                        }\n                        num_extra = \"\\02\\03\\07\"[dist - 16];\n                        TINFL_GET_BITS(18, s, num_extra);\n                        s += \"\\03\\03\\013\"[dist - 16];\n                        TINFL_MEMSET(r->m_len_codes + counter, (dist == 16) ? r->m_len_codes[counter - 1] : 0, s);\n                        counter += s;\n                    }\n                    if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter)\n                    {\n                        TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED);\n                    }\n                    TINFL_MEMCPY(r->m_tables[0].m_code_size, r->m_len_codes, r->m_table_sizes[0]);\n                    TINFL_MEMCPY(r->m_tables[1].m_code_size, r->m_len_codes + r->m_table_sizes[0], r->m_table_sizes[1]);\n                }\n            }\n            for (;;)\n            {\n                mz_uint8 *pSrc;\n                for (;;)\n                {\n                    if (((pIn_buf_end - pIn_buf_cur) < 4) || ((pOut_buf_end - pOut_buf_cur) < 2))\n                    {\n                        TINFL_HUFF_DECODE(23, counter, &r->m_tables[0]);\n                        if (counter >= 256)\n                            break;\n                        while (pOut_buf_cur >= pOut_buf_end)\n                        {\n                            TINFL_CR_RETURN(24, TINFL_STATUS_HAS_MORE_OUTPUT);\n                        }\n                        *pOut_buf_cur++ = (mz_uint8)counter;\n                    }\n                    else\n                    {\n                        int sym2;\n                        mz_uint code_len;\n#if TINFL_USE_64BIT_BITBUF\n                        if (num_bits < 30)\n                        {\n                            bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE32(pIn_buf_cur)) << num_bits);\n                            pIn_buf_cur += 4;\n                            num_bits += 32;\n                        }\n#else\n                        if (num_bits < 15)\n                        {\n                            bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits);\n                            pIn_buf_cur += 2;\n                            num_bits += 16;\n                        }\n#endif\n                        if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)\n                            code_len = sym2 >> 9;\n                        else\n                        {\n                            code_len = TINFL_FAST_LOOKUP_BITS;\n                            do\n                            {\n                                sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)];\n                            } while (sym2 < 0);\n                        }\n                        counter = sym2;\n                        bit_buf >>= code_len;\n                        num_bits -= code_len;\n                        if (counter & 256)\n                            break;\n\n#if !TINFL_USE_64BIT_BITBUF\n                        if (num_bits < 15)\n                        {\n                            bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits);\n                            pIn_buf_cur += 2;\n                            num_bits += 16;\n                        }\n#endif\n                        if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)\n                            code_len = sym2 >> 9;\n                        else\n                        {\n                            code_len = TINFL_FAST_LOOKUP_BITS;\n                            do\n                            {\n                                sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)];\n                            } while (sym2 < 0);\n                        }\n                        bit_buf >>= code_len;\n                        num_bits -= code_len;\n\n                        pOut_buf_cur[0] = (mz_uint8)counter;\n                        if (sym2 & 256)\n                        {\n                            pOut_buf_cur++;\n                            counter = sym2;\n                            break;\n                        }\n                        pOut_buf_cur[1] = (mz_uint8)sym2;\n                        pOut_buf_cur += 2;\n                    }\n                }\n                if ((counter &= 511) == 256)\n                    break;\n\n                num_extra = s_length_extra[counter - 257];\n                counter = s_length_base[counter - 257];\n                if (num_extra)\n                {\n                    mz_uint extra_bits;\n                    TINFL_GET_BITS(25, extra_bits, num_extra);\n                    counter += extra_bits;\n                }\n\n                TINFL_HUFF_DECODE(26, dist, &r->m_tables[1]);\n                num_extra = s_dist_extra[dist];\n                dist = s_dist_base[dist];\n                if (num_extra)\n                {\n                    mz_uint extra_bits;\n                    TINFL_GET_BITS(27, extra_bits, num_extra);\n                    dist += extra_bits;\n                }\n\n                dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start;\n                if ((dist > dist_from_out_buf_start) && (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))\n                {\n                    TINFL_CR_RETURN_FOREVER(37, TINFL_STATUS_FAILED);\n                }\n\n                pSrc = pOut_buf_start + ((dist_from_out_buf_start - dist) & out_buf_size_mask);\n\n                if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end)\n                {\n                    while (counter--)\n                    {\n                        while (pOut_buf_cur >= pOut_buf_end)\n                        {\n                            TINFL_CR_RETURN(53, TINFL_STATUS_HAS_MORE_OUTPUT);\n                        }\n                        *pOut_buf_cur++ = pOut_buf_start[(dist_from_out_buf_start++ - dist) & out_buf_size_mask];\n                    }\n                    continue;\n                }\n#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES\n                else if ((counter >= 9) && (counter <= dist))\n                {\n                    const mz_uint8 *pSrc_end = pSrc + (counter & ~7);\n                    do\n                    {\n                        ((mz_uint32 *)pOut_buf_cur)[0] = ((const mz_uint32 *)pSrc)[0];\n                        ((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1];\n                        pOut_buf_cur += 8;\n                    } while ((pSrc += 8) < pSrc_end);\n                    if ((counter &= 7) < 3)\n                    {\n                        if (counter)\n                        {\n                            pOut_buf_cur[0] = pSrc[0];\n                            if (counter > 1)\n                                pOut_buf_cur[1] = pSrc[1];\n                            pOut_buf_cur += counter;\n                        }\n                        continue;\n                    }\n                }\n#endif\n                while(counter>2)\n                {\n                    pOut_buf_cur[0] = pSrc[0];\n                    pOut_buf_cur[1] = pSrc[1];\n                    pOut_buf_cur[2] = pSrc[2];\n                    pOut_buf_cur += 3;\n                    pSrc += 3;\n\t\t\t\t\tcounter -= 3;\n                }\n                if (counter > 0)\n                {\n                    pOut_buf_cur[0] = pSrc[0];\n                    if (counter > 1)\n                        pOut_buf_cur[1] = pSrc[1];\n                    pOut_buf_cur += counter;\n                }\n            }\n        }\n    } while (!(r->m_final & 1));\n\n    /* Ensure byte alignment and put back any bytes from the bitbuf if we've looked ahead too far on gzip, or other Deflate streams followed by arbitrary data. */\n    /* I'm being super conservative here. A number of simplifications can be made to the byte alignment part, and the Adler32 check shouldn't ever need to worry about reading from the bitbuf now. */\n    TINFL_SKIP_BITS(32, num_bits & 7);\n    while ((pIn_buf_cur > pIn_buf_next) && (num_bits >= 8))\n    {\n        --pIn_buf_cur;\n        num_bits -= 8;\n    }\n    bit_buf &= (tinfl_bit_buf_t)((((mz_uint64)1) << num_bits) - (mz_uint64)1);\n    MZ_ASSERT(!num_bits); /* if this assert fires then we've read beyond the end of non-deflate/zlib streams with following data (such as gzip streams). */\n\n    if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)\n    {\n        for (counter = 0; counter < 4; ++counter)\n        {\n            mz_uint s;\n            if (num_bits)\n                TINFL_GET_BITS(41, s, 8);\n            else\n                TINFL_GET_BYTE(42, s);\n            r->m_z_adler32 = (r->m_z_adler32 << 8) | s;\n        }\n    }\n    TINFL_CR_RETURN_FOREVER(34, TINFL_STATUS_DONE);\n\n    TINFL_CR_FINISH\n\ncommon_exit:\n    /* As long as we aren't telling the caller that we NEED more input to make forward progress: */\n    /* Put back any bytes from the bitbuf in case we've looked ahead too far on gzip, or other Deflate streams followed by arbitrary data. */\n    /* We need to be very careful here to NOT push back any bytes we definitely know we need to make forward progress, though, or we'll lock the caller up into an inf loop. */\n    if ((status != TINFL_STATUS_NEEDS_MORE_INPUT) && (status != TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS))\n    {\n        while ((pIn_buf_cur > pIn_buf_next) && (num_bits >= 8))\n        {\n            --pIn_buf_cur;\n            num_bits -= 8;\n        }\n    }\n    r->m_num_bits = num_bits;\n    r->m_bit_buf = bit_buf & (tinfl_bit_buf_t)((((mz_uint64)1) << num_bits) - (mz_uint64)1);\n    r->m_dist = dist;\n    r->m_counter = counter;\n    r->m_num_extra = num_extra;\n    r->m_dist_from_out_buf_start = dist_from_out_buf_start;\n    *pIn_buf_size = pIn_buf_cur - pIn_buf_next;\n    *pOut_buf_size = pOut_buf_cur - pOut_buf_next;\n    if ((decomp_flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) && (status >= 0))\n    {\n        const mz_uint8 *ptr = pOut_buf_next;\n        size_t buf_len = *pOut_buf_size;\n        mz_uint32 i, s1 = r->m_check_adler32 & 0xffff, s2 = r->m_check_adler32 >> 16;\n        size_t block_len = buf_len % 5552;\n        while (buf_len)\n        {\n            for (i = 0; i + 7 < block_len; i += 8, ptr += 8)\n            {\n                s1 += ptr[0], s2 += s1;\n                s1 += ptr[1], s2 += s1;\n                s1 += ptr[2], s2 += s1;\n                s1 += ptr[3], s2 += s1;\n                s1 += ptr[4], s2 += s1;\n                s1 += ptr[5], s2 += s1;\n                s1 += ptr[6], s2 += s1;\n                s1 += ptr[7], s2 += s1;\n            }\n            for (; i < block_len; ++i)\n                s1 += *ptr++, s2 += s1;\n            s1 %= 65521U, s2 %= 65521U;\n            buf_len -= block_len;\n            block_len = 5552;\n        }\n        r->m_check_adler32 = (s2 << 16) + s1;\n        if ((status == TINFL_STATUS_DONE) && (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) && (r->m_check_adler32 != r->m_z_adler32))\n            status = TINFL_STATUS_ADLER32_MISMATCH;\n    }\n    return status;\n}\n\n/* Higher level helper functions. */\nvoid *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags)\n{\n    tinfl_decompressor decomp;\n    void *pBuf = NULL, *pNew_buf;\n    size_t src_buf_ofs = 0, out_buf_capacity = 0;\n    *pOut_len = 0;\n    tinfl_init(&decomp);\n    for (;;)\n    {\n        size_t src_buf_size = src_buf_len - src_buf_ofs, dst_buf_size = out_buf_capacity - *pOut_len, new_out_buf_capacity;\n        tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8 *)pSrc_buf + src_buf_ofs, &src_buf_size, (mz_uint8 *)pBuf, pBuf ? (mz_uint8 *)pBuf + *pOut_len : NULL, &dst_buf_size,\n                                               (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);\n        if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT))\n        {\n            MZ_FREE(pBuf);\n            *pOut_len = 0;\n            return NULL;\n        }\n        src_buf_ofs += src_buf_size;\n        *pOut_len += dst_buf_size;\n        if (status == TINFL_STATUS_DONE)\n            break;\n        new_out_buf_capacity = out_buf_capacity * 2;\n        if (new_out_buf_capacity < 128)\n            new_out_buf_capacity = 128;\n        pNew_buf = MZ_REALLOC(pBuf, new_out_buf_capacity);\n        if (!pNew_buf)\n        {\n            MZ_FREE(pBuf);\n            *pOut_len = 0;\n            return NULL;\n        }\n        pBuf = pNew_buf;\n        out_buf_capacity = new_out_buf_capacity;\n    }\n    return pBuf;\n}\n\nsize_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags)\n{\n    tinfl_decompressor decomp;\n    tinfl_status status;\n    tinfl_init(&decomp);\n    status = tinfl_decompress(&decomp, (const mz_uint8 *)pSrc_buf, &src_buf_len, (mz_uint8 *)pOut_buf, (mz_uint8 *)pOut_buf, &out_buf_len, (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);\n    return (status != TINFL_STATUS_DONE) ? TINFL_DECOMPRESS_MEM_TO_MEM_FAILED : out_buf_len;\n}\n\nint tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)\n{\n    int result = 0;\n    tinfl_decompressor decomp;\n    mz_uint8 *pDict = (mz_uint8 *)MZ_MALLOC(TINFL_LZ_DICT_SIZE);\n    size_t in_buf_ofs = 0, dict_ofs = 0;\n    if (!pDict)\n        return TINFL_STATUS_FAILED;\n    tinfl_init(&decomp);\n    for (;;)\n    {\n        size_t in_buf_size = *pIn_buf_size - in_buf_ofs, dst_buf_size = TINFL_LZ_DICT_SIZE - dict_ofs;\n        tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8 *)pIn_buf + in_buf_ofs, &in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size,\n                                               (flags & ~(TINFL_FLAG_HAS_MORE_INPUT | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)));\n        in_buf_ofs += in_buf_size;\n        if ((dst_buf_size) && (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user)))\n            break;\n        if (status != TINFL_STATUS_HAS_MORE_OUTPUT)\n        {\n            result = (status == TINFL_STATUS_DONE);\n            break;\n        }\n        dict_ofs = (dict_ofs + dst_buf_size) & (TINFL_LZ_DICT_SIZE - 1);\n    }\n    MZ_FREE(pDict);\n    *pIn_buf_size = in_buf_ofs;\n    return result;\n}\n\ntinfl_decompressor *tinfl_decompressor_alloc()\n{\n    tinfl_decompressor *pDecomp = (tinfl_decompressor *)MZ_MALLOC(sizeof(tinfl_decompressor));\n    if (pDecomp)\n        tinfl_init(pDecomp);\n    return pDecomp;\n}\n\nvoid tinfl_decompressor_free(tinfl_decompressor *pDecomp)\n{\n    MZ_FREE(pDecomp);\n}\n\n#ifdef __cplusplus\n}\n#endif\n/**************************************************************************\n *\n * Copyright 2013-2014 RAD Game Tools and Valve Software\n * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC\n * Copyright 2016 Martin Raiber\n * All Rights Reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n **************************************************************************/\n\n\n#ifndef MINIZ_NO_ARCHIVE_APIS\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* ------------------- .ZIP archive reading */\n\n#ifdef MINIZ_NO_STDIO\n#define MZ_FILE void *\n#else\n#include <sys/stat.h>\n\n#if defined(_MSC_VER) || defined(__MINGW64__)\nstatic FILE *mz_fopen(const char *pFilename, const char *pMode)\n{\n    FILE *pFile = NULL;\n    fopen_s(&pFile, pFilename, pMode);\n    return pFile;\n}\nstatic FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream)\n{\n    FILE *pFile = NULL;\n    if (freopen_s(&pFile, pPath, pMode, pStream))\n        return NULL;\n    return pFile;\n}\n#ifndef MINIZ_NO_TIME\n#include <sys/utime.h>\n#endif\n#define MZ_FOPEN mz_fopen\n#define MZ_FCLOSE fclose\n#define MZ_FREAD fread\n#define MZ_FWRITE fwrite\n#define MZ_FTELL64 _ftelli64\n#define MZ_FSEEK64 _fseeki64\n#define MZ_FILE_STAT_STRUCT _stat\n#define MZ_FILE_STAT _stat\n#define MZ_FFLUSH fflush\n#define MZ_FREOPEN mz_freopen\n#define MZ_DELETE_FILE remove\n#elif defined(__MINGW32__)\n#ifndef MINIZ_NO_TIME\n#include <sys/utime.h>\n#endif\n#define MZ_FOPEN(f, m) fopen(f, m)\n#define MZ_FCLOSE fclose\n#define MZ_FREAD fread\n#define MZ_FWRITE fwrite\n#define MZ_FTELL64 ftello64\n#define MZ_FSEEK64 fseeko64\n#define MZ_FILE_STAT_STRUCT _stat\n#define MZ_FILE_STAT _stat\n#define MZ_FFLUSH fflush\n#define MZ_FREOPEN(f, m, s) freopen(f, m, s)\n#define MZ_DELETE_FILE remove\n#elif defined(__TINYC__)\n#ifndef MINIZ_NO_TIME\n#include <sys/utime.h>\n#endif\n#define MZ_FOPEN(f, m) fopen(f, m)\n#define MZ_FCLOSE fclose\n#define MZ_FREAD fread\n#define MZ_FWRITE fwrite\n#define MZ_FTELL64 ftell\n#define MZ_FSEEK64 fseek\n#define MZ_FILE_STAT_STRUCT stat\n#define MZ_FILE_STAT stat\n#define MZ_FFLUSH fflush\n#define MZ_FREOPEN(f, m, s) freopen(f, m, s)\n#define MZ_DELETE_FILE remove\n#elif defined(__GNUC__) && _LARGEFILE64_SOURCE\n#ifndef MINIZ_NO_TIME\n#include <utime.h>\n#endif\n#define MZ_FOPEN(f, m) fopen64(f, m)\n#define MZ_FCLOSE fclose\n#define MZ_FREAD fread\n#define MZ_FWRITE fwrite\n#define MZ_FTELL64 ftello64\n#define MZ_FSEEK64 fseeko64\n#define MZ_FILE_STAT_STRUCT stat64\n#define MZ_FILE_STAT stat64\n#define MZ_FFLUSH fflush\n#define MZ_FREOPEN(p, m, s) freopen64(p, m, s)\n#define MZ_DELETE_FILE remove\n#elif defined(__APPLE__)\n#ifndef MINIZ_NO_TIME\n#include <utime.h>\n#endif\n#define MZ_FOPEN(f, m) fopen(f, m)\n#define MZ_FCLOSE fclose\n#define MZ_FREAD fread\n#define MZ_FWRITE fwrite\n#define MZ_FTELL64 ftello\n#define MZ_FSEEK64 fseeko\n#define MZ_FILE_STAT_STRUCT stat\n#define MZ_FILE_STAT stat\n#define MZ_FFLUSH fflush\n#define MZ_FREOPEN(p, m, s) freopen(p, m, s)\n#define MZ_DELETE_FILE remove\n\n#else\n#pragma message(\"Using fopen, ftello, fseeko, stat() etc. path for file I/O - this path may not support large files.\")\n#ifndef MINIZ_NO_TIME\n#include <utime.h>\n#endif\n#define MZ_FOPEN(f, m) fopen(f, m)\n#define MZ_FCLOSE fclose\n#define MZ_FREAD fread\n#define MZ_FWRITE fwrite\n#ifdef __STRICT_ANSI__\n#define MZ_FTELL64 ftell\n#define MZ_FSEEK64 fseek\n#else\n#define MZ_FTELL64 ftello\n#define MZ_FSEEK64 fseeko\n#endif\n#define MZ_FILE_STAT_STRUCT stat\n#define MZ_FILE_STAT stat\n#define MZ_FFLUSH fflush\n#define MZ_FREOPEN(f, m, s) freopen(f, m, s)\n#define MZ_DELETE_FILE remove\n#endif /* #ifdef _MSC_VER */\n#endif /* #ifdef MINIZ_NO_STDIO */\n\n#define MZ_TOLOWER(c) ((((c) >= 'A') && ((c) <= 'Z')) ? ((c) - 'A' + 'a') : (c))\n\n/* Various ZIP archive enums. To completely avoid cross platform compiler alignment and platform endian issues, miniz.c doesn't use structs for any of this stuff. */\nenum\n{\n    /* ZIP archive identifiers and record sizes */\n    MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06054b50,\n    MZ_ZIP_CENTRAL_DIR_HEADER_SIG = 0x02014b50,\n    MZ_ZIP_LOCAL_DIR_HEADER_SIG = 0x04034b50,\n    MZ_ZIP_LOCAL_DIR_HEADER_SIZE = 30,\n    MZ_ZIP_CENTRAL_DIR_HEADER_SIZE = 46,\n    MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE = 22,\n\n    /* ZIP64 archive identifier and record sizes */\n    MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06064b50,\n    MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG = 0x07064b50,\n    MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE = 56,\n    MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE = 20,\n    MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID = 0x0001,\n    MZ_ZIP_DATA_DESCRIPTOR_ID = 0x08074b50,\n    MZ_ZIP_DATA_DESCRIPTER_SIZE64 = 24,\n    MZ_ZIP_DATA_DESCRIPTER_SIZE32 = 16,\n\n    /* Central directory header record offsets */\n    MZ_ZIP_CDH_SIG_OFS = 0,\n    MZ_ZIP_CDH_VERSION_MADE_BY_OFS = 4,\n    MZ_ZIP_CDH_VERSION_NEEDED_OFS = 6,\n    MZ_ZIP_CDH_BIT_FLAG_OFS = 8,\n    MZ_ZIP_CDH_METHOD_OFS = 10,\n    MZ_ZIP_CDH_FILE_TIME_OFS = 12,\n    MZ_ZIP_CDH_FILE_DATE_OFS = 14,\n    MZ_ZIP_CDH_CRC32_OFS = 16,\n    MZ_ZIP_CDH_COMPRESSED_SIZE_OFS = 20,\n    MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS = 24,\n    MZ_ZIP_CDH_FILENAME_LEN_OFS = 28,\n    MZ_ZIP_CDH_EXTRA_LEN_OFS = 30,\n    MZ_ZIP_CDH_COMMENT_LEN_OFS = 32,\n    MZ_ZIP_CDH_DISK_START_OFS = 34,\n    MZ_ZIP_CDH_INTERNAL_ATTR_OFS = 36,\n    MZ_ZIP_CDH_EXTERNAL_ATTR_OFS = 38,\n    MZ_ZIP_CDH_LOCAL_HEADER_OFS = 42,\n\n    /* Local directory header offsets */\n    MZ_ZIP_LDH_SIG_OFS = 0,\n    MZ_ZIP_LDH_VERSION_NEEDED_OFS = 4,\n    MZ_ZIP_LDH_BIT_FLAG_OFS = 6,\n    MZ_ZIP_LDH_METHOD_OFS = 8,\n    MZ_ZIP_LDH_FILE_TIME_OFS = 10,\n    MZ_ZIP_LDH_FILE_DATE_OFS = 12,\n    MZ_ZIP_LDH_CRC32_OFS = 14,\n    MZ_ZIP_LDH_COMPRESSED_SIZE_OFS = 18,\n    MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS = 22,\n    MZ_ZIP_LDH_FILENAME_LEN_OFS = 26,\n    MZ_ZIP_LDH_EXTRA_LEN_OFS = 28,\n    MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR = 1 << 3,\n\n    /* End of central directory offsets */\n    MZ_ZIP_ECDH_SIG_OFS = 0,\n    MZ_ZIP_ECDH_NUM_THIS_DISK_OFS = 4,\n    MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS = 6,\n    MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 8,\n    MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS = 10,\n    MZ_ZIP_ECDH_CDIR_SIZE_OFS = 12,\n    MZ_ZIP_ECDH_CDIR_OFS_OFS = 16,\n    MZ_ZIP_ECDH_COMMENT_SIZE_OFS = 20,\n\n    /* ZIP64 End of central directory locator offsets */\n    MZ_ZIP64_ECDL_SIG_OFS = 0,                    /* 4 bytes */\n    MZ_ZIP64_ECDL_NUM_DISK_CDIR_OFS = 4,          /* 4 bytes */\n    MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS = 8,  /* 8 bytes */\n    MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS = 16, /* 4 bytes */\n\n    /* ZIP64 End of central directory header offsets */\n    MZ_ZIP64_ECDH_SIG_OFS = 0,                       /* 4 bytes */\n    MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS = 4,            /* 8 bytes */\n    MZ_ZIP64_ECDH_VERSION_MADE_BY_OFS = 12,          /* 2 bytes */\n    MZ_ZIP64_ECDH_VERSION_NEEDED_OFS = 14,           /* 2 bytes */\n    MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS = 16,            /* 4 bytes */\n    MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS = 20,            /* 4 bytes */\n    MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 24, /* 8 bytes */\n    MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS = 32,       /* 8 bytes */\n    MZ_ZIP64_ECDH_CDIR_SIZE_OFS = 40,                /* 8 bytes */\n    MZ_ZIP64_ECDH_CDIR_OFS_OFS = 48,                 /* 8 bytes */\n    MZ_ZIP_VERSION_MADE_BY_DOS_FILESYSTEM_ID = 0,\n    MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG = 0x10,\n    MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED = 1,\n    MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG = 32,\n    MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION = 64,\n    MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED = 8192,\n    MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8 = 1 << 11\n};\n\ntypedef struct\n{\n    void *m_p;\n    size_t m_size, m_capacity;\n    mz_uint m_element_size;\n} mz_zip_array;\n\nstruct mz_zip_internal_state_tag\n{\n    mz_zip_array m_central_dir;\n    mz_zip_array m_central_dir_offsets;\n    mz_zip_array m_sorted_central_dir_offsets;\n\n    /* The flags passed in when the archive is initially opened. */\n    uint32_t m_init_flags;\n\n    /* MZ_TRUE if the archive has a zip64 end of central directory headers, etc. */\n    mz_bool m_zip64;\n\n    /* MZ_TRUE if we found zip64 extended info in the central directory (m_zip64 will also be slammed to true too, even if we didn't find a zip64 end of central dir header, etc.) */\n    mz_bool m_zip64_has_extended_info_fields;\n\n    /* These fields are used by the file, FILE, memory, and memory/heap read/write helpers. */\n    MZ_FILE *m_pFile;\n    mz_uint64 m_file_archive_start_ofs;\n\n    void *m_pMem;\n    size_t m_mem_size;\n    size_t m_mem_capacity;\n};\n\n#define MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(array_ptr, element_size) (array_ptr)->m_element_size = element_size\n\n#if defined(DEBUG) || defined(_DEBUG) || defined(NDEBUG)\nstatic MZ_FORCEINLINE mz_uint mz_zip_array_range_check(const mz_zip_array *pArray, mz_uint index)\n{\n    MZ_ASSERT(index < pArray->m_size);\n    return index;\n}\n#define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) ((element_type *)((array_ptr)->m_p))[mz_zip_array_range_check(array_ptr, index)]\n#else\n#define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) ((element_type *)((array_ptr)->m_p))[index]\n#endif\n\nstatic MZ_FORCEINLINE void mz_zip_array_init(mz_zip_array *pArray, mz_uint32 element_size)\n{\n    memset(pArray, 0, sizeof(mz_zip_array));\n    pArray->m_element_size = element_size;\n}\n\nstatic MZ_FORCEINLINE void mz_zip_array_clear(mz_zip_archive *pZip, mz_zip_array *pArray)\n{\n    pZip->m_pFree(pZip->m_pAlloc_opaque, pArray->m_p);\n    memset(pArray, 0, sizeof(mz_zip_array));\n}\n\nstatic mz_bool mz_zip_array_ensure_capacity(mz_zip_archive *pZip, mz_zip_array *pArray, size_t min_new_capacity, mz_uint growing)\n{\n    void *pNew_p;\n    size_t new_capacity = min_new_capacity;\n    MZ_ASSERT(pArray->m_element_size);\n    if (pArray->m_capacity >= min_new_capacity)\n        return MZ_TRUE;\n    if (growing)\n    {\n        new_capacity = MZ_MAX(1, pArray->m_capacity);\n        while (new_capacity < min_new_capacity)\n            new_capacity *= 2;\n    }\n    if (NULL == (pNew_p = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pArray->m_p, pArray->m_element_size, new_capacity)))\n        return MZ_FALSE;\n    pArray->m_p = pNew_p;\n    pArray->m_capacity = new_capacity;\n    return MZ_TRUE;\n}\n\nstatic MZ_FORCEINLINE mz_bool mz_zip_array_reserve(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_capacity, mz_uint growing)\n{\n    if (new_capacity > pArray->m_capacity)\n    {\n        if (!mz_zip_array_ensure_capacity(pZip, pArray, new_capacity, growing))\n            return MZ_FALSE;\n    }\n    return MZ_TRUE;\n}\n\nstatic MZ_FORCEINLINE mz_bool mz_zip_array_resize(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_size, mz_uint growing)\n{\n    if (new_size > pArray->m_capacity)\n    {\n        if (!mz_zip_array_ensure_capacity(pZip, pArray, new_size, growing))\n            return MZ_FALSE;\n    }\n    pArray->m_size = new_size;\n    return MZ_TRUE;\n}\n\nstatic MZ_FORCEINLINE mz_bool mz_zip_array_ensure_room(mz_zip_archive *pZip, mz_zip_array *pArray, size_t n)\n{\n    return mz_zip_array_reserve(pZip, pArray, pArray->m_size + n, MZ_TRUE);\n}\n\nstatic MZ_FORCEINLINE mz_bool mz_zip_array_push_back(mz_zip_archive *pZip, mz_zip_array *pArray, const void *pElements, size_t n)\n{\n    size_t orig_size = pArray->m_size;\n    if (!mz_zip_array_resize(pZip, pArray, orig_size + n, MZ_TRUE))\n        return MZ_FALSE;\n    memcpy((mz_uint8 *)pArray->m_p + orig_size * pArray->m_element_size, pElements, n * pArray->m_element_size);\n    return MZ_TRUE;\n}\n\n#ifndef MINIZ_NO_TIME\nstatic MZ_TIME_T mz_zip_dos_to_time_t(int dos_time, int dos_date)\n{\n    struct tm tm;\n    memset(&tm, 0, sizeof(tm));\n    tm.tm_isdst = -1;\n    tm.tm_year = ((dos_date >> 9) & 127) + 1980 - 1900;\n    tm.tm_mon = ((dos_date >> 5) & 15) - 1;\n    tm.tm_mday = dos_date & 31;\n    tm.tm_hour = (dos_time >> 11) & 31;\n    tm.tm_min = (dos_time >> 5) & 63;\n    tm.tm_sec = (dos_time << 1) & 62;\n    return mktime(&tm);\n}\n\n#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS\nstatic void mz_zip_time_t_to_dos_time(MZ_TIME_T time, mz_uint16 *pDOS_time, mz_uint16 *pDOS_date)\n{\n#ifdef _MSC_VER\n    struct tm tm_struct;\n    struct tm *tm = &tm_struct;\n    errno_t err = localtime_s(tm, &time);\n    if (err)\n    {\n        *pDOS_date = 0;\n        *pDOS_time = 0;\n        return;\n    }\n#else\n    struct tm *tm = localtime(&time);\n#endif /* #ifdef _MSC_VER */\n\n    *pDOS_time = (mz_uint16)(((tm->tm_hour) << 11) + ((tm->tm_min) << 5) + ((tm->tm_sec) >> 1));\n    *pDOS_date = (mz_uint16)(((tm->tm_year + 1900 - 1980) << 9) + ((tm->tm_mon + 1) << 5) + tm->tm_mday);\n}\n#endif /* MINIZ_NO_ARCHIVE_WRITING_APIS */\n\n#ifndef MINIZ_NO_STDIO\n#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS\nstatic mz_bool mz_zip_get_file_modified_time(const char *pFilename, MZ_TIME_T *pTime)\n{\n    struct MZ_FILE_STAT_STRUCT file_stat;\n\n    /* On Linux with x86 glibc, this call will fail on large files (I think >= 0x80000000 bytes) unless you compiled with _LARGEFILE64_SOURCE. Argh. */\n    if (MZ_FILE_STAT(pFilename, &file_stat) != 0)\n        return MZ_FALSE;\n\n    *pTime = file_stat.st_mtime;\n\n    return MZ_TRUE;\n}\n#endif /* #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS*/\n\nstatic mz_bool mz_zip_set_file_times(const char *pFilename, MZ_TIME_T access_time, MZ_TIME_T modified_time)\n{\n    struct utimbuf t;\n\n    memset(&t, 0, sizeof(t));\n    t.actime = access_time;\n    t.modtime = modified_time;\n\n    return !utime(pFilename, &t);\n}\n#endif /* #ifndef MINIZ_NO_STDIO */\n#endif /* #ifndef MINIZ_NO_TIME */\n\nstatic MZ_FORCEINLINE mz_bool mz_zip_set_error(mz_zip_archive *pZip, mz_zip_error err_num)\n{\n    if (pZip)\n        pZip->m_last_error = err_num;\n    return MZ_FALSE;\n}\n\nstatic mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip, mz_uint flags)\n{\n    (void)flags;\n    if ((!pZip) || (pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))\n        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);\n\n    if (!pZip->m_pAlloc)\n        pZip->m_pAlloc = miniz_def_alloc_func;\n    if (!pZip->m_pFree)\n        pZip->m_pFree = miniz_def_free_func;\n    if (!pZip->m_pRealloc)\n        pZip->m_pRealloc = miniz_def_realloc_func;\n\n    pZip->m_archive_size = 0;\n    pZip->m_central_directory_file_ofs = 0;\n    pZip->m_total_files = 0;\n    pZip->m_last_error = MZ_ZIP_NO_ERROR;\n\n    if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))\n        return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);\n\n    memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));\n    MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8));\n    MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32));\n    MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32));\n    pZip->m_pState->m_init_flags = flags;\n    pZip->m_pState->m_zip64 = MZ_FALSE;\n    pZip->m_pState->m_zip64_has_extended_info_fields = MZ_FALSE;\n\n    pZip->m_zip_mode = MZ_ZIP_MODE_READING;\n\n    return MZ_TRUE;\n}\n\nstatic MZ_FORCEINLINE mz_bool mz_zip_reader_filename_less(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, mz_uint r_index)\n{\n    const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE;\n    const mz_uint8 *pR = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, r_index));\n    mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS), r_len = MZ_READ_LE16(pR + MZ_ZIP_CDH_FILENAME_LEN_OFS);\n    mz_uint8 l = 0, r = 0;\n    pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;\n    pR += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;\n    pE = pL + MZ_MIN(l_len, r_len);\n    while (pL < pE)\n    {\n        if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))\n            break;\n        pL++;\n        pR++;\n    }\n    return (pL == pE) ? (l_len < r_len) : (l < r);\n}\n\n#define MZ_SWAP_UINT32(a, b) \\\n    do                       \\\n    {                        \\\n        mz_uint32 t = a;     \\\n        a = b;               \\\n        b = t;               \\\n    }                        \\\n    MZ_MACRO_END\n\n/* Heap sort of lowercased filenames, used to help accelerate plain central directory searches by mz_zip_reader_locate_file(). (Could also use qsort(), but it could allocate memory.) */\nstatic void mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive *pZip)\n{\n    mz_zip_internal_state *pState = pZip->m_pState;\n    const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;\n    const mz_zip_array *pCentral_dir = &pState->m_central_dir;\n    mz_uint32 *pIndices;\n    mz_uint32 start, end;\n    const mz_uint32 size = pZip->m_total_files;\n\n    if (size <= 1U)\n        return;\n\n    pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0);\n\n    start = (size - 2U) >> 1U;\n    for (;;)\n    {\n        mz_uint64 child, root = start;\n        for (;;)\n        {\n            if ((child = (root << 1U) + 1U) >= size)\n                break;\n            child += (((child + 1U) < size) && (mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1U])));\n            if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child]))\n                break;\n            MZ_SWAP_UINT32(pIndices[root], pIndices[child]);\n            root = child;\n        }\n        if (!start)\n            break;\n        start--;\n    }\n\n    end = size - 1;\n    while (end > 0)\n    {\n        mz_uint64 child, root = 0;\n        MZ_SWAP_UINT32(pIndices[end], pIndices[0]);\n        for (;;)\n        {\n            if ((child = (root << 1U) + 1U) >= end)\n                break;\n            child += (((child + 1U) < end) && mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1U]));\n            if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child]))\n                break;\n            MZ_SWAP_UINT32(pIndices[root], pIndices[child]);\n            root = child;\n        }\n        end--;\n    }\n}\n\nstatic mz_bool mz_zip_reader_locate_header_sig(mz_zip_archive *pZip, mz_uint32 record_sig, mz_uint32 record_size, mz_int64 *pOfs)\n{\n    mz_int64 cur_file_ofs;\n    mz_uint32 buf_u32[4096 / sizeof(mz_uint32)];\n    mz_uint8 *pBuf = (mz_uint8 *)buf_u32;\n\n    /* Basic sanity checks - reject files which are too small */\n    if (pZip->m_archive_size < record_size)\n        return MZ_FALSE;\n\n    /* Find the record by scanning the file from the end towards the beginning. */\n    cur_file_ofs = MZ_MAX((mz_int64)pZip->m_archive_size - (mz_int64)sizeof(buf_u32), 0);\n    for (;;)\n    {\n        int i, n = (int)MZ_MIN(sizeof(buf_u32), pZip->m_archive_size - cur_file_ofs);\n\n        if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n)\n            return MZ_FALSE;\n\n        for (i = n - 4; i >= 0; --i)\n        {\n            mz_uint s = MZ_READ_LE32(pBuf + i);\n            if (s == record_sig)\n            {\n                if ((pZip->m_archive_size - (cur_file_ofs + i)) >= record_size)\n                    break;\n            }\n        }\n\n        if (i >= 0)\n        {\n            cur_file_ofs += i;\n            break;\n        }\n\n        /* Give up if we've searched the entire file, or we've gone back \"too far\" (~64kb) */\n        if ((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >= (MZ_UINT16_MAX + record_size)))\n            return MZ_FALSE;\n\n        cur_file_ofs = MZ_MAX(cur_file_ofs - (sizeof(buf_u32) - 3), 0);\n    }\n\n    *pOfs = cur_file_ofs;\n    return MZ_TRUE;\n}\n\nstatic mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, mz_uint flags)\n{\n    mz_uint cdir_size = 0, cdir_entries_on_this_disk = 0, num_this_disk = 0, cdir_disk_index = 0;\n    mz_uint64 cdir_ofs = 0;\n    mz_int64 cur_file_ofs = 0;\n    const mz_uint8 *p;\n\n    mz_uint32 buf_u32[4096 / sizeof(mz_uint32)];\n    mz_uint8 *pBuf = (mz_uint8 *)buf_u32;\n    mz_bool sort_central_dir = ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0);\n    mz_uint32 zip64_end_of_central_dir_locator_u32[(MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];\n    mz_uint8 *pZip64_locator = (mz_uint8 *)zip64_end_of_central_dir_locator_u32;\n\n    mz_uint32 zip64_end_of_central_dir_header_u32[(MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];\n    mz_uint8 *pZip64_end_of_central_dir = (mz_uint8 *)zip64_end_of_central_dir_header_u32;\n\n    mz_uint64 zip64_end_of_central_dir_ofs = 0;\n\n    /* Basic sanity checks - reject files which are too small, and check the first 4 bytes of the file to make sure a local header is there. */\n    if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)\n        return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);\n\n    if (!mz_zip_reader_locate_header_sig(pZip, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE, &cur_file_ofs))\n        return mz_zip_set_error(pZip, MZ_ZIP_FAILED_FINDING_CENTRAL_DIR);\n\n    /* Read and verify the end of central directory record. */\n    if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)\n        return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);\n\n    if (MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG)\n        return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);\n\n    if (cur_file_ofs >= (MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE + MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE))\n    {\n        if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs - MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE, pZip64_locator, MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) == MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE)\n        {\n            if (MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_SIG_OFS) == MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG)\n            {\n                zip64_end_of_central_dir_ofs = MZ_READ_LE64(pZip64_locator + MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS);\n                if (zip64_end_of_central_dir_ofs > (pZip->m_archive_size - MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE))\n                    return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);\n\n                if (pZip->m_pRead(pZip->m_pIO_opaque, zip64_end_of_central_dir_ofs, pZip64_end_of_central_dir, MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) == MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE)\n                {\n                    if (MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_SIG_OFS) == MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG)\n                    {\n                        pZip->m_pState->m_zip64 = MZ_TRUE;\n                    }\n                }\n            }\n        }\n    }\n\n    pZip->m_total_files = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS);\n    cdir_entries_on_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS);\n    num_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS);\n    cdir_disk_index = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS);\n    cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS);\n    cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS);\n\n    if (pZip->m_pState->m_zip64)\n    {\n        mz_uint32 zip64_total_num_of_disks = MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS);\n        mz_uint64 zip64_cdir_total_entries = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS);\n        mz_uint64 zip64_cdir_total_entries_on_this_disk = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS);\n        mz_uint64 zip64_size_of_end_of_central_dir_record = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS);\n        mz_uint64 zip64_size_of_central_directory = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_SIZE_OFS);\n\n        if (zip64_size_of_end_of_central_dir_record < (MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE - 12))\n            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);\n\n        if (zip64_total_num_of_disks != 1U)\n            return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);\n\n        /* Check for miniz's practical limits */\n        if (zip64_cdir_total_entries > MZ_UINT32_MAX)\n            return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);\n\n        pZip->m_total_files = (mz_uint32)zip64_cdir_total_entries;\n\n        if (zip64_cdir_total_entries_on_this_disk > MZ_UINT32_MAX)\n            return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);\n\n        cdir_entries_on_this_disk = (mz_uint32)zip64_cdir_total_entries_on_this_disk;\n\n        /* Check for miniz's current practical limits (sorry, this should be enough for millions of files) */\n        if (zip64_size_of_central_directory > MZ_UINT32_MAX)\n            return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);\n\n        cdir_size = (mz_uint32)zip64_size_of_central_directory;\n\n        num_this_disk = MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS);\n\n        cdir_disk_index = MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS);\n\n        cdir_ofs = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_OFS_OFS);\n    }\n\n    if (pZip->m_total_files != cdir_entries_on_this_disk)\n        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);\n\n    if (((num_this_disk | cdir_disk_index) != 0) && ((num_this_disk != 1) || (cdir_disk_index != 1)))\n        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);\n\n    if (cdir_size < pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)\n        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);\n\n    if ((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size)\n        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);\n\n    pZip->m_central_directory_file_ofs = cdir_ofs;\n\n    if (pZip->m_total_files)\n    {\n        mz_uint i, n;\n        /* Read the entire central directory into a heap block, and allocate another heap block to hold the unsorted central dir file record offsets, and possibly another to hold the sorted indices. */\n        if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size, MZ_FALSE)) ||\n            (!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir_offsets, pZip->m_total_files, MZ_FALSE)))\n            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);\n\n        if (sort_central_dir)\n        {\n            if (!mz_zip_array_resize(pZip, &pZip->m_pState->m_sorted_central_dir_offsets, pZip->m_total_files, MZ_FALSE))\n                return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);\n        }\n\n        if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs, pZip->m_pState->m_central_dir.m_p, cdir_size) != cdir_size)\n            return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);\n\n        /* Now create an index into the central directory file records, do some basic sanity checking on each record */\n        p = (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p;\n        for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i)\n        {\n            mz_uint total_header_size, disk_index, bit_flags, filename_size, ext_data_size;\n            mz_uint64 comp_size, decomp_size, local_header_ofs;\n\n            if ((n < MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) || (MZ_READ_LE32(p) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG))\n                return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);\n\n            MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, i) = (mz_uint32)(p - (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p);\n\n            if (sort_central_dir)\n                MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_sorted_central_dir_offsets, mz_uint32, i) = i;\n\n            comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);\n            decomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);\n            local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);\n            filename_size = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);\n            ext_data_size = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS);\n\n            if ((!pZip->m_pState->m_zip64_has_extended_info_fields) &&\n                (ext_data_size) &&\n                (MZ_MAX(MZ_MAX(comp_size, decomp_size), local_header_ofs) == MZ_UINT32_MAX))\n            {\n                /* Attempt to find zip64 extended information field in the entry's extra data */\n                mz_uint32 extra_size_remaining = ext_data_size;\n\n                if (extra_size_remaining)\n                {\n                    const mz_uint8 *pExtra_data = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size;\n\n                    do\n                    {\n                        mz_uint32 field_id;\n                        mz_uint32 field_data_size;\n\n                        if (extra_size_remaining < (sizeof(mz_uint16) * 2))\n                            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);\n\n                        field_id = MZ_READ_LE16(pExtra_data);\n                        field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));\n\n                        if ((field_data_size + sizeof(mz_uint16) * 2) > extra_size_remaining)\n                            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);\n\n                        if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)\n                        {\n                            /* Ok, the archive didn't have any zip64 headers but it uses a zip64 extended information field so mark it as zip64 anyway (this can occur with infozip's zip util when it reads compresses files from stdin). */\n                            pZip->m_pState->m_zip64 = MZ_TRUE;\n                            pZip->m_pState->m_zip64_has_extended_info_fields = MZ_TRUE;\n                            break;\n                        }\n\n                        pExtra_data += sizeof(mz_uint16) * 2 + field_data_size;\n                        extra_size_remaining = extra_size_remaining - sizeof(mz_uint16) * 2 - field_data_size;\n                    } while (extra_size_remaining);\n                }\n            }\n\n            /* I've seen archives that aren't marked as zip64 that uses zip64 ext data, argh */\n            if ((comp_size != MZ_UINT32_MAX) && (decomp_size != MZ_UINT32_MAX))\n            {\n                if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) && (decomp_size != comp_size)) || (decomp_size && !comp_size))\n                    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);\n            }\n\n            disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS);\n            if ((disk_index == MZ_UINT16_MAX) || ((disk_index != num_this_disk) && (disk_index != 1)))\n                return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);\n\n            if (comp_size != MZ_UINT32_MAX)\n            {\n                if (((mz_uint64)MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS) + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + comp_size) > pZip->m_archive_size)\n                    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);\n            }\n\n            bit_flags = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);\n            if (bit_flags & MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED)\n                return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);\n\n            if ((total_header_size = MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS)) > n)\n                return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);\n\n            n -= total_header_size;\n            p += total_header_size;\n        }\n    }\n\n    if (sort_central_dir)\n        mz_zip_reader_sort_central_dir_offsets_by_filename(pZip);\n\n    return MZ_TRUE;\n}\n\nvoid mz_zip_zero_struct(mz_zip_archive *pZip)\n{\n    if (pZip)\n        MZ_CLEAR_OBJ(*pZip);\n}\n\nstatic mz_bool mz_zip_reader_end_internal(mz_zip_archive *pZip, mz_bool set_last_error)\n{\n    mz_bool status = MZ_TRUE;\n\n    if (!pZip)\n        return MZ_FALSE;\n\n    if ((!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))\n    {\n        if (set_last_error)\n            pZip->m_last_error = MZ_ZIP_INVALID_PARAMETER;\n\n        return MZ_FALSE;\n    }\n\n    if (pZip->m_pState)\n    {\n        mz_zip_internal_state *pState = pZip->m_pState;\n        pZip->m_pState = NULL;\n\n        mz_zip_array_clear(pZip, &pState->m_central_dir);\n        mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);\n        mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);\n\n#ifndef MINIZ_NO_STDIO\n        if (pState->m_pFile)\n        {\n            if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE)\n            {\n                if (MZ_FCLOSE(pState->m_pFile) == EOF)\n                {\n                    if (set_last_error)\n                        pZip->m_last_error = MZ_ZIP_FILE_CLOSE_FAILED;\n                    status = MZ_FALSE;\n                }\n            }\n            pState->m_pFile = NULL;\n        }\n#endif /* #ifndef MINIZ_NO_STDIO */\n\n        pZip->m_pFree(pZip->m_pAlloc_opaque, pState);\n    }\n    pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;\n\n    return status;\n}\n\nmz_bool mz_zip_reader_end(mz_zip_archive *pZip)\n{\n    return mz_zip_reader_end_internal(pZip, MZ_TRUE);\n}\nmz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint flags)\n{\n    if ((!pZip) || (!pZip->m_pRead))\n        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);\n\n    if (!mz_zip_reader_init_internal(pZip, flags))\n        return MZ_FALSE;\n\n    pZip->m_zip_type = MZ_ZIP_TYPE_USER;\n    pZip->m_archive_size = size;\n\n    if (!mz_zip_reader_read_central_dir(pZip, flags))\n    {\n        mz_zip_reader_end_internal(pZip, MZ_FALSE);\n        return MZ_FALSE;\n    }\n\n    return MZ_TRUE;\n}\n\nstatic size_t mz_zip_mem_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)\n{\n    mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;\n    size_t s = (file_ofs >= pZip->m_archive_size) ? 0 : (size_t)MZ_MIN(pZip->m_archive_size - file_ofs, n);\n    memcpy(pBuf, (const mz_uint8 *)pZip->m_pState->m_pMem + file_ofs, s);\n    return s;\n}\n\nmz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint flags)\n{\n    if (!pMem)\n        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);\n\n    if (size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)\n        return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);\n\n    if (!mz_zip_reader_init_internal(pZip, flags))\n        return MZ_FALSE;\n\n    pZip->m_zip_type = MZ_ZIP_TYPE_MEMORY;\n    pZip->m_archive_size = size;\n    pZip->m_pRead = mz_zip_mem_read_func;\n    pZip->m_pIO_opaque = pZip;\n    pZip->m_pNeeds_keepalive = NULL;\n\n#ifdef __cplusplus\n    pZip->m_pState->m_pMem = const_cast<void *>(pMem);\n#else\n    pZip->m_pState->m_pMem = (void *)pMem;\n#endif\n\n    pZip->m_pState->m_mem_size = size;\n\n    if (!mz_zip_reader_read_central_dir(pZip, flags))\n    {\n        mz_zip_reader_end_internal(pZip, MZ_FALSE);\n        return MZ_FALSE;\n    }\n\n    return MZ_TRUE;\n}\n\n#ifndef MINIZ_NO_STDIO\nstatic size_t mz_zip_file_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)\n{\n    mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;\n    mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);\n\n    file_ofs += pZip->m_pState->m_file_archive_start_ofs;\n\n    if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET))))\n        return 0;\n\n    return MZ_FREAD(pBuf, 1, n, pZip->m_pState->m_pFile);\n}\n\nmz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags)\n{\n    return mz_zip_reader_init_file_v2(pZip, pFilename, flags, 0, 0);\n}\n\nmz_bool mz_zip_reader_init_file_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint flags, mz_uint64 file_start_ofs, mz_uint64 archive_size)\n{\n    mz_uint64 file_size;\n    MZ_FILE *pFile;\n\n    if ((!pZip) || (!pFilename) || ((archive_size) && (archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)))\n        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);\n\n    pFile = MZ_FOPEN(pFilename, \"rb\");\n    if (!pFile)\n        return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);\n\n    file_size = archive_size;\n    if (!file_size)\n    {\n        if (MZ_FSEEK64(pFile, 0, SEEK_END))\n        {\n            MZ_FCLOSE(pFile);\n            return mz_zip_set_error(pZip, MZ_ZIP_FILE_SEEK_FAILED);\n        }\n\n        file_size = MZ_FTELL64(pFile);\n    }\n\n    /* TODO: Better sanity check archive_size and the # of actual remaining bytes */\n\n    if (file_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)\n    {\n\tMZ_FCLOSE(pFile);\n        return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);\n    }\n\n    if (!mz_zip_reader_init_internal(pZip, flags))\n    {\n        MZ_FCLOSE(pFile);\n        return MZ_FALSE;\n    }\n\n    pZip->m_zip_type = MZ_ZIP_TYPE_FILE;\n    pZip->m_pRead = mz_zip_file_read_func;\n    pZip->m_pIO_opaque = pZip;\n    pZip->m_pState->m_pFile = pFile;\n    pZip->m_archive_size = file_size;\n    pZip->m_pState->m_file_archive_start_ofs = file_start_ofs;\n\n    if (!mz_zip_reader_read_central_dir(pZip, flags))\n    {\n        mz_zip_reader_end_internal(pZip, MZ_FALSE);\n        return MZ_FALSE;\n    }\n\n    return MZ_TRUE;\n}\n\nmz_bool mz_zip_reader_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, mz_uint64 archive_size, mz_uint flags)\n{\n    mz_uint64 cur_file_ofs;\n\n    if ((!pZip) || (!pFile))\n        return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);\n\n    cur_file_ofs = MZ_FTELL64(pFile);\n\n    if (!archive_size)\n    {\n        if (MZ_FSEEK64(pFile, 0, SEEK_END))\n            return mz_zip_set_error(pZip, MZ_ZIP_FILE_SEEK_FAILED);\n\n        archive_size = MZ_FTELL64(pFile) - cur_file_ofs;\n\n        if (archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)\n            return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);\n    }\n\n    if (!mz_zip_reader_init_internal(pZip, flags))\n        return MZ_FALSE;\n\n    pZip->m_zip_type = MZ_ZIP_TYPE_CFILE;\n    pZip->m_pRead = mz_zip_file_read_func;\n\n    pZip->m_pIO_opaque = pZip;\n    pZip->m_pState->m_pFile = pFile;\n    pZip->m_archive_size = archive_size;\n    pZip->m_pState->m_file_archive_start_ofs = cur_file_ofs;\n\n    if (!mz_zip_reader_read_central_dir(pZip, flags))\n    {\n        mz_zip_reader_end_internal(pZip, MZ_FALSE);\n        return MZ_FALSE;\n    }\n\n    return MZ_TRUE;\n}\n\n#endif /* #ifndef MINIZ_NO_STDIO */\n\nstatic MZ_FORCEINLINE const mz_uint8 *mz_zip_get_cdh(mz_zip_archive *pZip, mz_uint file_index)\n{\n    if ((!pZip) || (!pZip->m_pState) || (file_index >= pZip->m_total_files))\n        return NULL;\n    return &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index));\n}\n\nmz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index)\n{\n    mz_uint m_bit_flag;\n    const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);\n    if (!p)\n    {\n        mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);\n        return MZ_FALSE;\n    }\n\n    m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);\n    return (m_bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION)) != 0;\n}\n\nmz_bool mz_zip_reader_is_file_supported(mz_zip_archive *pZip, mz_uint file_index)\n{\n    mz_uint bit_flag;\n    mz_uint method;\n\n    const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);\n    if (!p)\n    {\n        mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);\n        return MZ_FALSE;\n    }\n\n    method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS);\n    bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);\n\n    if ((method != 0) && (method != MZ_DEFLATED))\n    {\n        mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);\n        return MZ_FALSE;\n    }\n\n    if (bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION))\n    {\n        mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);\n        return MZ_FALSE;\n    }\n\n    if (bit_flag & MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG)\n    {\n        mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE);\n        return MZ_FALSE;\n    }\n\n    return MZ_TRUE;\n}\n\nmz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index)\n{\n    mz_uint filename_len, attribute_mapping_id, external_attr;\n    const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);\n    if (!p)\n    {\n        mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);\n        return MZ_FALSE;\n    }\n\n    filename_len = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);\n    if (filename_len)\n    {\n        if (*(p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_len - 1) == '/')\n            return MZ_TRUE;\n    }\n\n    /* Bugfix: This code was also checking if the internal attribute was non-zero, which wasn't correct. */\n    /* Most/all zip writers (hopefully) set DOS file/directory attributes in the low 16-bits, so check for the DOS directory flag and ignore the source OS ID in the created by field. */\n    /* FIXME: Remove this check? Is it necessary - we already check the filename. */\n    attribute_mapping_id = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS) >> 8;\n    (void)attribute_mapping_id;\n\n    external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);\n    if ((external_attr & MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG) != 0)\n    {\n        return MZ_TRUE;\n    }\n\n    return MZ_FALSE;\n}\n\nstatic mz_bool mz_zip_file_stat_internal(mz_zip_archive *pZip, mz_uint file_index, const mz_uint8 *pCentral_dir_header, mz_zip_archive_file_stat *pStat, mz_bool *pFound_zip64_extra_data)\n{\n    mz_uint n;\n    const mz_uint8 *p = pCentral_dir_header;\n\n    if (pFound_zip64_extra_data)\n        *pFound_zip64_extra_data = MZ_FALSE;\n\n    if ((!p) || (!pStat))\n        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);\n\n    /* Extract fields from the central directory record. */\n    pStat->m_file_index = file_index;\n    pStat->m_central_dir_ofs = MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index);\n    pStat->m_version_made_by = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS);\n    pStat->m_version_needed = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_NEEDED_OFS);\n    pStat->m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);\n    pStat->m_method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS);\n#ifndef MINIZ_NO_TIME\n    pStat->m_time = mz_zip_dos_to_time_t(MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_TIME_OFS), MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_DATE_OFS));\n#endif\n    pStat->m_crc32 = MZ_READ_LE32(p + MZ_ZIP_CDH_CRC32_OFS);\n    pStat->m_comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);\n    pStat->m_uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);\n    pStat->m_internal_attr = MZ_READ_LE16(p + MZ_ZIP_CDH_INTERNAL_ATTR_OFS);\n    pStat->m_external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);\n    pStat->m_local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);\n\n    /* Copy as much of the filename and comment as possible. */\n    n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);\n    n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE - 1);\n    memcpy(pStat->m_filename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);\n    pStat->m_filename[n] = '\\0';\n\n    n = MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS);\n    n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE - 1);\n    pStat->m_comment_size = n;\n    memcpy(pStat->m_comment, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS), n);\n    pStat->m_comment[n] = '\\0';\n\n    /* Set some flags for convienance */\n    pStat->m_is_directory = mz_zip_reader_is_file_a_directory(pZip, file_index);\n    pStat->m_is_encrypted = mz_zip_reader_is_file_encrypted(pZip, file_index);\n    pStat->m_is_supported = mz_zip_reader_is_file_supported(pZip, file_index);\n\n    /* See if we need to read any zip64 extended information fields. */\n    /* Confusingly, these zip64 fields can be present even on non-zip64 archives (Debian zip on a huge files from stdin piped to stdout creates them). */\n    if (MZ_MAX(MZ_MAX(pStat->m_comp_size, pStat->m_uncomp_size), pStat->m_local_header_ofs) == MZ_UINT32_MAX)\n    {\n        /* Attempt to find zip64 extended information field in the entry's extra data */\n        mz_uint32 extra_size_remaining = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS);\n\n        if (extra_size_remaining)\n        {\n            const mz_uint8 *pExtra_data = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);\n\n            do\n            {\n                mz_uint32 field_id;\n                mz_uint32 field_data_size;\n\n                if (extra_size_remaining < (sizeof(mz_uint16) * 2))\n                    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);\n\n                field_id = MZ_READ_LE16(pExtra_data);\n                field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));\n\n                if ((field_data_size + sizeof(mz_uint16) * 2) > extra_size_remaining)\n                    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);\n\n                if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)\n                {\n                    const mz_uint8 *pField_data = pExtra_data + sizeof(mz_uint16) * 2;\n                    mz_uint32 field_data_remaining = field_data_size;\n\n                    if (pFound_zip64_extra_data)\n                        *pFound_zip64_extra_data = MZ_TRUE;\n\n                    if (pStat->m_uncomp_size == MZ_UINT32_MAX)\n                    {\n                        if (field_data_remaining < sizeof(mz_uint64))\n                            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);\n\n                        pStat->m_uncomp_size = MZ_READ_LE64(pField_data);\n                        pField_data += sizeof(mz_uint64);\n                        field_data_remaining -= sizeof(mz_uint64);\n                    }\n\n                    if (pStat->m_comp_size == MZ_UINT32_MAX)\n                    {\n                        if (field_data_remaining < sizeof(mz_uint64))\n                            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);\n\n                        pStat->m_comp_size = MZ_READ_LE64(pField_data);\n                        pField_data += sizeof(mz_uint64);\n                        field_data_remaining -= sizeof(mz_uint64);\n                    }\n\n                    if (pStat->m_local_header_ofs == MZ_UINT32_MAX)\n                    {\n                        if (field_data_remaining < sizeof(mz_uint64))\n                            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);\n\n                        pStat->m_local_header_ofs = MZ_READ_LE64(pField_data);\n                        pField_data += sizeof(mz_uint64);\n                        field_data_remaining -= sizeof(mz_uint64);\n                    }\n\n                    break;\n                }\n\n                pExtra_data += sizeof(mz_uint16) * 2 + field_data_size;\n                extra_size_remaining = extra_size_remaining - sizeof(mz_uint16) * 2 - field_data_size;\n            } while (extra_size_remaining);\n        }\n    }\n\n    return MZ_TRUE;\n}\n\nstatic MZ_FORCEINLINE mz_bool mz_zip_string_equal(const char *pA, const char *pB, mz_uint len, mz_uint flags)\n{\n    mz_uint i;\n    if (flags & MZ_ZIP_FLAG_CASE_SENSITIVE)\n        return 0 == memcmp(pA, pB, len);\n    for (i = 0; i < len; ++i)\n        if (MZ_TOLOWER(pA[i]) != MZ_TOLOWER(pB[i]))\n            return MZ_FALSE;\n    return MZ_TRUE;\n}\n\nstatic MZ_FORCEINLINE int mz_zip_filename_compare(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, const char *pR, mz_uint r_len)\n{\n    const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE;\n    mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS);\n    mz_uint8 l = 0, r = 0;\n    pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;\n    pE = pL + MZ_MIN(l_len, r_len);\n    while (pL < pE)\n    {\n        if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))\n            break;\n        pL++;\n        pR++;\n    }\n    return (pL == pE) ? (int)(l_len - r_len) : (l - r);\n}\n\nstatic mz_bool mz_zip_locate_file_binary_search(mz_zip_archive *pZip, const char *pFilename, mz_uint32 *pIndex)\n{\n    mz_zip_internal_state *pState = pZip->m_pState;\n    const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;\n    const mz_zip_array *pCentral_dir = &pState->m_central_dir;\n    mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0);\n    const uint32_t size = pZip->m_total_files;\n    const mz_uint filename_len = (mz_uint)strlen(pFilename);\n\n    if (pIndex)\n        *pIndex = 0;\n\n    if (size)\n    {\n        /* yes I could use uint32_t's, but then we would have to add some special case checks in the loop, argh, and */\n        /* honestly the major expense here on 32-bit CPU's will still be the filename compare */\n        mz_int64 l = 0, h = (mz_int64)size - 1;\n\n        while (l <= h)\n        {\n            mz_int64 m = l + ((h - l) >> 1);\n            uint32_t file_index = pIndices[(uint32_t)m];\n\n            int comp = mz_zip_filename_compare(pCentral_dir, pCentral_dir_offsets, file_index, pFilename, filename_len);\n            if (!comp)\n            {\n                if (pIndex)\n                    *pIndex = file_index;\n                return MZ_TRUE;\n            }\n            else if (comp < 0)\n                l = m + 1;\n            else\n                h = m - 1;\n        }\n    }\n\n    return mz_zip_set_error(pZip, MZ_ZIP_FILE_NOT_FOUND);\n}\n\nint mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags)\n{\n    mz_uint32 index;\n    if (!mz_zip_reader_locate_file_v2(pZip, pName, pComment, flags, &index))\n        return -1;\n    else\n        return (int)index;\n}\n\nmz_bool mz_zip_reader_locate_file_v2(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags, mz_uint32 *pIndex)\n{\n    mz_uint file_index;\n    size_t name_len, comment_len;\n\n    if (pIndex)\n        *pIndex = 0;\n\n    if ((!pZip) || (!pZip->m_pState) || (!pName))\n        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);\n\n    /* See if we can use a binary search */\n    if (((pZip->m_pState->m_init_flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0) &&\n        (pZip->m_zip_mode == MZ_ZIP_MODE_READING) &&\n        ((flags & (MZ_ZIP_FLAG_IGNORE_PATH | MZ_ZIP_FLAG_CASE_SENSITIVE)) == 0) && (!pComment) && (pZip->m_pState->m_sorted_central_dir_offsets.m_size))\n    {\n        return mz_zip_locate_file_binary_search(pZip, pName, pIndex);\n    }\n\n    /* Locate the entry by scanning the entire central directory */\n    name_len = strlen(pName);\n    if (name_len > MZ_UINT16_MAX)\n        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);\n\n    comment_len = pComment ? strlen(pComment) : 0;\n    if (comment_len > MZ_UINT16_MAX)\n        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);\n\n    for (file_index = 0; file_index < pZip->m_total_files; file_index++)\n    {\n        const mz_uint8 *pHeader = &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index));\n        mz_uint filename_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_FILENAME_LEN_OFS);\n        const char *pFilename = (const char *)pHeader + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;\n        if (filename_len < name_len)\n            continue;\n        if (comment_len)\n        {\n            mz_uint file_extra_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_EXTRA_LEN_OFS), file_comment_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_COMMENT_LEN_OFS);\n            const char *pFile_comment = pFilename + filename_len + file_extra_len;\n            if ((file_comment_len != comment_len) || (!mz_zip_string_equal(pComment, pFile_comment, file_comment_len, flags)))\n                continue;\n        }\n        if ((flags & MZ_ZIP_FLAG_IGNORE_PATH) && (filename_len))\n        {\n            int ofs = filename_len - 1;\n            do\n            {\n                if ((pFilename[ofs] == '/') || (pFilename[ofs] == '\\\\') || (pFilename[ofs] == ':'))\n                    break;\n            } while (--ofs >= 0);\n            ofs++;\n            pFilename += ofs;\n            filename_len -= ofs;\n        }\n        if ((filename_len == name_len) && (mz_zip_string_equal(pName, pFilename, filename_len, flags)))\n        {\n            if (pIndex)\n                *pIndex = file_index;\n            return MZ_TRUE;\n        }\n    }\n\n    return mz_zip_set_error(pZip, MZ_ZIP_FILE_NOT_FOUND);\n}\n\nmz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size)\n{\n    int status = TINFL_STATUS_DONE;\n    mz_uint64 needed_size, cur_file_ofs, comp_remaining, out_buf_ofs = 0, read_buf_size, read_buf_ofs = 0, read_buf_avail;\n    mz_zip_archive_file_stat file_stat;\n    void *pRead_buf;\n    mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];\n    mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;\n    tinfl_decompressor inflator;\n\n    if ((!pZip) || (!pZip->m_pState) || ((buf_size) && (!pBuf)) || ((user_read_buf_size) && (!pUser_read_buf)) || (!pZip->m_pRead))\n        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);\n\n    if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))\n        return MZ_FALSE;\n\n    /* A directory or zero length file */\n    if ((file_stat.m_is_directory) || (!file_stat.m_comp_size))\n        return MZ_TRUE;\n\n    /* Encryption and patch files are not supported. */\n    if (file_stat.m_bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG))\n        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);\n\n    /* This function only supports decompressing stored and deflate. */\n    if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))\n        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);\n\n    /* Ensure supplied output buffer is large enough. */\n    needed_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? file_stat.m_comp_size : file_stat.m_uncomp_size;\n    if (buf_size < needed_size)\n        return mz_zip_set_error(pZip, MZ_ZIP_BUF_TOO_SMALL);\n\n    /* Read and parse the local directory entry. */\n    cur_file_ofs = file_stat.m_local_header_ofs;\n    if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)\n        return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);\n\n    if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)\n        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);\n\n    cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);\n    if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)\n        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);\n\n    if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method))\n    {\n        /* The file is stored or the caller has requested the compressed data. */\n        if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, (size_t)needed_size) != needed_size)\n            return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);\n\n#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS\n        if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) == 0)\n        {\n            if (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32)\n                return mz_zip_set_error(pZip, MZ_ZIP_CRC_CHECK_FAILED);\n        }\n#endif\n\n        return MZ_TRUE;\n    }\n\n    /* Decompress the file either directly from memory or from a file input buffer. */\n    tinfl_init(&inflator);\n\n    if (pZip->m_pState->m_pMem)\n    {\n        /* Read directly from the archive in memory. */\n        pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;\n        read_buf_size = read_buf_avail = file_stat.m_comp_size;\n        comp_remaining = 0;\n    }\n    else if (pUser_read_buf)\n    {\n        /* Use a user provided read buffer. */\n        if (!user_read_buf_size)\n            return MZ_FALSE;\n        pRead_buf = (mz_uint8 *)pUser_read_buf;\n        read_buf_size = user_read_buf_size;\n        read_buf_avail = 0;\n        comp_remaining = file_stat.m_comp_size;\n    }\n    else\n    {\n        /* Temporarily allocate a read buffer. */\n        read_buf_size = MZ_MIN(file_stat.m_comp_size, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE);\n        if (((sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF))\n            return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);\n\n        if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size)))\n            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);\n\n        read_buf_avail = 0;\n        comp_remaining = file_stat.m_comp_size;\n    }\n\n    do\n    {\n        /* The size_t cast here should be OK because we've verified that the output buffer is >= file_stat.m_uncomp_size above */\n        size_t in_buf_size, out_buf_size = (size_t)(file_stat.m_uncomp_size - out_buf_ofs);\n        if ((!read_buf_avail) && (!pZip->m_pState->m_pMem))\n        {\n            read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);\n            if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)\n            {\n                status = TINFL_STATUS_FAILED;\n                mz_zip_set_error(pZip, MZ_ZIP_DECOMPRESSION_FAILED);\n                break;\n            }\n            cur_file_ofs += read_buf_avail;\n            comp_remaining -= read_buf_avail;\n            read_buf_ofs = 0;\n        }\n        in_buf_size = (size_t)read_buf_avail;\n        status = tinfl_decompress(&inflator, (mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8 *)pBuf, (mz_uint8 *)pBuf + out_buf_ofs, &out_buf_size, TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF | (comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0));\n        read_buf_avail -= in_buf_size;\n        read_buf_ofs += in_buf_size;\n        out_buf_ofs += out_buf_size;\n    } while (status == TINFL_STATUS_NEEDS_MORE_INPUT);\n\n    if (status == TINFL_STATUS_DONE)\n    {\n        /* Make sure the entire file was decompressed, and check its CRC. */\n        if (out_buf_ofs != file_stat.m_uncomp_size)\n        {\n            mz_zip_set_error(pZip, MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE);\n            status = TINFL_STATUS_FAILED;\n        }\n#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS\n        else if (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32)\n        {\n            mz_zip_set_error(pZip, MZ_ZIP_CRC_CHECK_FAILED);\n            status = TINFL_STATUS_FAILED;\n        }\n#endif\n    }\n\n    if ((!pZip->m_pState->m_pMem) && (!pUser_read_buf))\n        pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);\n\n    return status == TINFL_STATUS_DONE;\n}\n\nmz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size)\n{\n    mz_uint32 file_index;\n    if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))\n        return MZ_FALSE;\n    return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, pUser_read_buf, user_read_buf_size);\n}\n\nmz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags)\n{\n    return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, NULL, 0);\n}\n\nmz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags)\n{\n    return mz_zip_reader_extract_file_to_mem_no_alloc(pZip, pFilename, pBuf, buf_size, flags, NULL, 0);\n}\n\nvoid *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags)\n{\n    mz_uint64 comp_size, uncomp_size, alloc_size;\n    const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);\n    void *pBuf;\n\n    if (pSize)\n        *pSize = 0;\n\n    if (!p)\n    {\n        mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);\n        return NULL;\n    }\n\n    comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);\n    uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);\n\n    alloc_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? comp_size : uncomp_size;\n    if (((sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF))\n    {\n        mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);\n        return NULL;\n    }\n\n    if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)alloc_size)))\n    {\n        mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);\n        return NULL;\n    }\n\n    if (!mz_zip_reader_extract_to_mem(pZip, file_index, pBuf, (size_t)alloc_size, flags))\n    {\n        pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);\n        return NULL;\n    }\n\n    if (pSize)\n        *pSize = (size_t)alloc_size;\n    return pBuf;\n}\n\nvoid *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags)\n{\n    mz_uint32 file_index;\n    if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))\n    {\n        if (pSize)\n            *pSize = 0;\n        return MZ_FALSE;\n    }\n    return mz_zip_reader_extract_to_heap(pZip, file_index, pSize, flags);\n}\n\nmz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_index, mz_file_write_func pCallback, void *pOpaque, mz_uint flags)\n{\n    int status = TINFL_STATUS_DONE;\n    mz_uint file_crc32 = MZ_CRC32_INIT;\n    mz_uint64 read_buf_size, read_buf_ofs = 0, read_buf_avail, comp_remaining, out_buf_ofs = 0, cur_file_ofs;\n    mz_zip_archive_file_stat file_stat;\n    void *pRead_buf = NULL;\n    void *pWrite_buf = NULL;\n    mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];\n    mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;\n\n    if ((!pZip) || (!pZip->m_pState) || (!pCallback) || (!pZip->m_pRead))\n        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);\n\n    if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))\n        return MZ_FALSE;\n\n    /* A directory or zero length file */\n    if ((file_stat.m_is_directory) || (!file_stat.m_comp_size))\n        return MZ_TRUE;\n\n    /* Encryption and patch files are not supported. */\n    if (file_stat.m_bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG))\n        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);\n\n    /* This function only supports decompressing stored and deflate. */\n    if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))\n        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);\n\n    /* Read and do some minimal validation of the local directory entry (this doesn't crack the zip64 stuff, which we already have from the central dir) */\n    cur_file_ofs = file_stat.m_local_header_ofs;\n    if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)\n        return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);\n\n    if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)\n        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);\n\n    cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);\n    if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)\n        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);\n\n    /* Decompress the file either directly from memory or from a file input buffer. */\n    if (pZip->m_pState->m_pMem)\n    {\n        pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;\n        read_buf_size = read_buf_avail = file_stat.m_comp_size;\n        comp_remaining = 0;\n    }\n    else\n    {\n        read_buf_size = MZ_MIN(file_stat.m_comp_size, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE);\n        if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size)))\n            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);\n\n        read_buf_avail = 0;\n        comp_remaining = file_stat.m_comp_size;\n    }\n\n    if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method))\n    {\n        /* The file is stored or the caller has requested the compressed data. */\n        if (pZip->m_pState->m_pMem)\n        {\n            if (((sizeof(size_t) == sizeof(mz_uint32))) && (file_stat.m_comp_size > MZ_UINT32_MAX))\n                return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);\n\n            if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)file_stat.m_comp_size) != file_stat.m_comp_size)\n            {\n                mz_zip_set_error(pZip, MZ_ZIP_WRITE_CALLBACK_FAILED);\n                status = TINFL_STATUS_FAILED;\n            }\n            else if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))\n            {\n#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS\n                file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)file_stat.m_comp_size);\n#endif\n            }\n\n            cur_file_ofs += file_stat.m_comp_size;\n            out_buf_ofs += file_stat.m_comp_size;\n            comp_remaining = 0;\n        }\n        else\n        {\n            while (comp_remaining)\n            {\n                read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);\n                if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)\n                {\n                    mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);\n                    status = TINFL_STATUS_FAILED;\n                    break;\n                }\n\n#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS\n                if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))\n                {\n                    file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)read_buf_avail);\n                }\n#endif\n\n                if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)\n                {\n                    mz_zip_set_error(pZip, MZ_ZIP_WRITE_CALLBACK_FAILED);\n                    status = TINFL_STATUS_FAILED;\n                    break;\n                }\n\n                cur_file_ofs += read_buf_avail;\n                out_buf_ofs += read_buf_avail;\n                comp_remaining -= read_buf_avail;\n            }\n        }\n    }\n    else\n    {\n        tinfl_decompressor inflator;\n        tinfl_init(&inflator);\n\n        if (NULL == (pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, TINFL_LZ_DICT_SIZE)))\n        {\n            mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);\n            status = TINFL_STATUS_FAILED;\n        }\n        else\n        {\n            do\n            {\n                mz_uint8 *pWrite_buf_cur = (mz_uint8 *)pWrite_buf + (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));\n                size_t in_buf_size, out_buf_size = TINFL_LZ_DICT_SIZE - (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));\n                if ((!read_buf_avail) && (!pZip->m_pState->m_pMem))\n                {\n                    read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);\n                    if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)\n                    {\n                        mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);\n                        status = TINFL_STATUS_FAILED;\n                        break;\n                    }\n                    cur_file_ofs += read_buf_avail;\n                    comp_remaining -= read_buf_avail;\n                    read_buf_ofs = 0;\n                }\n\n                in_buf_size = (size_t)read_buf_avail;\n                status = tinfl_decompress(&inflator, (const mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8 *)pWrite_buf, pWrite_buf_cur, &out_buf_size, comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0);\n                read_buf_avail -= in_buf_size;\n                read_buf_ofs += in_buf_size;\n\n                if (out_buf_size)\n                {\n                    if (pCallback(pOpaque, out_buf_ofs, pWrite_buf_cur, out_buf_size) != out_buf_size)\n                    {\n                        mz_zip_set_error(pZip, MZ_ZIP_WRITE_CALLBACK_FAILED);\n                        status = TINFL_STATUS_FAILED;\n                        break;\n                    }\n\n#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS\n                    file_crc32 = (mz_uint32)mz_crc32(file_crc32, pWrite_buf_cur, out_buf_size);\n#endif\n                    if ((out_buf_ofs += out_buf_size) > file_stat.m_uncomp_size)\n                    {\n                        mz_zip_set_error(pZip, MZ_ZIP_DECOMPRESSION_FAILED);\n                        status = TINFL_STATUS_FAILED;\n                        break;\n                    }\n                }\n            } while ((status == TINFL_STATUS_NEEDS_MORE_INPUT) || (status == TINFL_STATUS_HAS_MORE_OUTPUT));\n        }\n    }\n\n    if ((status == TINFL_STATUS_DONE) && (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)))\n    {\n        /* Make sure the entire file was decompressed, and check its CRC. */\n        if (out_buf_ofs != file_stat.m_uncomp_size)\n        {\n            mz_zip_set_error(pZip, MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE);\n            status = TINFL_STATUS_FAILED;\n        }\n#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS\n        else if (file_crc32 != file_stat.m_crc32)\n        {\n            mz_zip_set_error(pZip, MZ_ZIP_DECOMPRESSION_FAILED);\n            status = TINFL_STATUS_FAILED;\n        }\n#endif\n    }\n\n    if (!pZip->m_pState->m_pMem)\n        pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);\n\n    if (pWrite_buf)\n        pZip->m_pFree(pZip->m_pAlloc_opaque, pWrite_buf);\n\n    return status == TINFL_STATUS_DONE;\n}\n\nmz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags)\n{\n    mz_uint32 file_index;\n    if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))\n        return MZ_FALSE;\n\n    return mz_zip_reader_extract_to_callback(pZip, file_index, pCallback, pOpaque, flags);\n}\n\nmz_zip_reader_extract_iter_state* mz_zip_reader_extract_iter_new(mz_zip_archive *pZip, mz_uint file_index, mz_uint flags)\n{\n    mz_zip_reader_extract_iter_state *pState;\n    mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];\n    mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;\n\n    /* Argument sanity check */\n    if ((!pZip) || (!pZip->m_pState))\n        return NULL;\n\n    /* Allocate an iterator status structure */\n    pState = (mz_zip_reader_extract_iter_state*)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_reader_extract_iter_state));\n    if (!pState)\n    {\n        mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);\n        return NULL;\n    }\n\n    /* Fetch file details */\n    if (!mz_zip_reader_file_stat(pZip, file_index, &pState->file_stat))\n    {\n        pZip->m_pFree(pZip->m_pAlloc_opaque, pState);\n        return NULL;\n    }\n\n    /* Encryption and patch files are not supported. */\n    if (pState->file_stat.m_bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG))\n    {\n        mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);\n        pZip->m_pFree(pZip->m_pAlloc_opaque, pState);\n        return NULL;\n    }\n\n    /* This function only supports decompressing stored and deflate. */\n    if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (pState->file_stat.m_method != 0) && (pState->file_stat.m_method != MZ_DEFLATED))\n    {\n        mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);\n        pZip->m_pFree(pZip->m_pAlloc_opaque, pState);\n        return NULL;\n    }\n\n    /* Init state - save args */\n    pState->pZip = pZip;\n    pState->flags = flags;\n\n    /* Init state - reset variables to defaults */\n    pState->status = TINFL_STATUS_DONE;\n#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS\n    pState->file_crc32 = MZ_CRC32_INIT;\n#endif\n    pState->read_buf_ofs = 0;\n    pState->out_buf_ofs = 0;\n    pState->pRead_buf = NULL;\n    pState->pWrite_buf = NULL;\n    pState->out_blk_remain = 0;\n\n    /* Read and parse the local directory entry. */\n    pState->cur_file_ofs = pState->file_stat.m_local_header_ofs;\n    if (pZip->m_pRead(pZip->m_pIO_opaque, pState->cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)\n    {\n        mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);\n        pZip->m_pFree(pZip->m_pAlloc_opaque, pState);\n        return NULL;\n    }\n\n    if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)\n    {\n        mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);\n        pZip->m_pFree(pZip->m_pAlloc_opaque, pState);\n        return NULL;\n    }\n\n    pState->cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);\n    if ((pState->cur_file_ofs + pState->file_stat.m_comp_size) > pZip->m_archive_size)\n    {\n        mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);\n        pZip->m_pFree(pZip->m_pAlloc_opaque, pState);\n        return NULL;\n    }\n\n    /* Decompress the file either directly from memory or from a file input buffer. */\n    if (pZip->m_pState->m_pMem)\n    {\n        pState->pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + pState->cur_file_ofs;\n        pState->read_buf_size = pState->read_buf_avail = pState->file_stat.m_comp_size;\n        pState->comp_remaining = pState->file_stat.m_comp_size;\n    }\n    else\n    {\n        if (!((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!pState->file_stat.m_method)))\n        {\n            /* Decompression required, therefore intermediate read buffer required */\n            pState->read_buf_size = MZ_MIN(pState->file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE);\n            if (NULL == (pState->pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)pState->read_buf_size)))\n            {\n                mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);\n                pZip->m_pFree(pZip->m_pAlloc_opaque, pState);\n                return NULL;\n            }\n        }\n        else\n        {\n            /* Decompression not required - we will be reading directly into user buffer, no temp buf required */\n            pState->read_buf_size = 0;\n        }\n        pState->read_buf_avail = 0;\n        pState->comp_remaining = pState->file_stat.m_comp_size;\n    }\n\n    if (!((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!pState->file_stat.m_method)))\n    {\n        /* Decompression required, init decompressor */\n        tinfl_init( &pState->inflator );\n\n        /* Allocate write buffer */\n        if (NULL == (pState->pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, TINFL_LZ_DICT_SIZE)))\n        {\n            mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);\n            if (pState->pRead_buf)\n                pZip->m_pFree(pZip->m_pAlloc_opaque, pState->pRead_buf);\n            pZip->m_pFree(pZip->m_pAlloc_opaque, pState);\n            return NULL;\n        }\n    }\n\n    return pState;\n}\n\nmz_zip_reader_extract_iter_state* mz_zip_reader_extract_file_iter_new(mz_zip_archive *pZip, const char *pFilename, mz_uint flags)\n{\n    mz_uint32 file_index;\n\n    /* Locate file index by name */\n    if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))\n        return NULL;\n\n    /* Construct iterator */\n    return mz_zip_reader_extract_iter_new(pZip, file_index, flags);\n}\n\nsize_t mz_zip_reader_extract_iter_read(mz_zip_reader_extract_iter_state* pState, void* pvBuf, size_t buf_size)\n{\n    size_t copied_to_caller = 0;\n\n    /* Argument sanity check */\n    if ((!pState) || (!pState->pZip) || (!pState->pZip->m_pState) || (!pvBuf))\n        return 0;\n\n    if ((pState->flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!pState->file_stat.m_method))\n    {\n        /* The file is stored or the caller has requested the compressed data, calc amount to return. */\n        copied_to_caller = MZ_MIN( buf_size, pState->comp_remaining );\n\n        /* Zip is in memory....or requires reading from a file? */\n        if (pState->pZip->m_pState->m_pMem)\n        {\n            /* Copy data to caller's buffer */\n            memcpy( pvBuf, pState->pRead_buf, copied_to_caller );\n            pState->pRead_buf = ((mz_uint8*)pState->pRead_buf) + copied_to_caller;\n        }\n        else\n        {\n            /* Read directly into caller's buffer */\n            if (pState->pZip->m_pRead(pState->pZip->m_pIO_opaque, pState->cur_file_ofs, pvBuf, copied_to_caller) != copied_to_caller)\n            {\n                /* Failed to read all that was asked for, flag failure and alert user */\n                mz_zip_set_error(pState->pZip, MZ_ZIP_FILE_READ_FAILED);\n                pState->status = TINFL_STATUS_FAILED;\n                copied_to_caller = 0;\n            }\n        }\n\n#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS\n        /* Compute CRC if not returning compressed data only */\n        if (!(pState->flags & MZ_ZIP_FLAG_COMPRESSED_DATA))\n            pState->file_crc32 = (mz_uint32)mz_crc32(pState->file_crc32, (const mz_uint8 *)pvBuf, copied_to_caller);\n#endif\n\n        /* Advance offsets, dec counters */\n        pState->cur_file_ofs += copied_to_caller;\n        pState->out_buf_ofs += copied_to_caller;\n        pState->comp_remaining -= copied_to_caller;\n    }\n    else\n    {\n        do\n        {\n            /* Calc ptr to write buffer - given current output pos and block size */\n            mz_uint8 *pWrite_buf_cur = (mz_uint8 *)pState->pWrite_buf + (pState->out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));\n\n            /* Calc max output size - given current output pos and block size */\n            size_t in_buf_size, out_buf_size = TINFL_LZ_DICT_SIZE - (pState->out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));\n\n            if (!pState->out_blk_remain)\n            {\n                /* Read more data from file if none available (and reading from file) */\n                if ((!pState->read_buf_avail) && (!pState->pZip->m_pState->m_pMem))\n                {\n                    /* Calc read size */\n                    pState->read_buf_avail = MZ_MIN(pState->read_buf_size, pState->comp_remaining);\n                    if (pState->pZip->m_pRead(pState->pZip->m_pIO_opaque, pState->cur_file_ofs, pState->pRead_buf, (size_t)pState->read_buf_avail) != pState->read_buf_avail)\n                    {\n                        mz_zip_set_error(pState->pZip, MZ_ZIP_FILE_READ_FAILED);\n                        pState->status = TINFL_STATUS_FAILED;\n                        break;\n                    }\n\n                    /* Advance offsets, dec counters */\n                    pState->cur_file_ofs += pState->read_buf_avail;\n                    pState->comp_remaining -= pState->read_buf_avail;\n                    pState->read_buf_ofs = 0;\n                }\n\n                /* Perform decompression */\n                in_buf_size = (size_t)pState->read_buf_avail;\n                pState->status = tinfl_decompress(&pState->inflator, (const mz_uint8 *)pState->pRead_buf + pState->read_buf_ofs, &in_buf_size, (mz_uint8 *)pState->pWrite_buf, pWrite_buf_cur, &out_buf_size, pState->comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0);\n                pState->read_buf_avail -= in_buf_size;\n                pState->read_buf_ofs += in_buf_size;\n\n                /* Update current output block size remaining */\n                pState->out_blk_remain = out_buf_size;\n            }\n\n            if (pState->out_blk_remain)\n            {\n                /* Calc amount to return. */\n                size_t to_copy = MZ_MIN( (buf_size - copied_to_caller), pState->out_blk_remain );\n\n                /* Copy data to caller's buffer */\n                memcpy( (uint8_t*)pvBuf + copied_to_caller, pWrite_buf_cur, to_copy );\n\n#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS\n                /* Perform CRC */\n                pState->file_crc32 = (mz_uint32)mz_crc32(pState->file_crc32, pWrite_buf_cur, to_copy);\n#endif\n\n                /* Decrement data consumed from block */\n                pState->out_blk_remain -= to_copy;\n\n                /* Inc output offset, while performing sanity check */\n                if ((pState->out_buf_ofs += to_copy) > pState->file_stat.m_uncomp_size)\n                {\n                    mz_zip_set_error(pState->pZip, MZ_ZIP_DECOMPRESSION_FAILED);\n                    pState->status = TINFL_STATUS_FAILED;\n                    break;\n                }\n\n                /* Increment counter of data copied to caller */\n                copied_to_caller += to_copy;\n            }\n        } while ( (copied_to_caller < buf_size) && ((pState->status == TINFL_STATUS_NEEDS_MORE_INPUT) || (pState->status == TINFL_STATUS_HAS_MORE_OUTPUT)) );\n    }\n\n    /* Return how many bytes were copied into user buffer */\n    return copied_to_caller;\n}\n\nmz_bool mz_zip_reader_extract_iter_free(mz_zip_reader_extract_iter_state* pState)\n{\n    int status;\n\n    /* Argument sanity check */\n    if ((!pState) || (!pState->pZip) || (!pState->pZip->m_pState))\n        return MZ_FALSE;\n\n    /* Was decompression completed and requested? */\n    if ((pState->status == TINFL_STATUS_DONE) && (!(pState->flags & MZ_ZIP_FLAG_COMPRESSED_DATA)))\n    {\n        /* Make sure the entire file was decompressed, and check its CRC. */\n        if (pState->out_buf_ofs != pState->file_stat.m_uncomp_size)\n        {\n            mz_zip_set_error(pState->pZip, MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE);\n            pState->status = TINFL_STATUS_FAILED;\n        }\n#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS\n        else if (pState->file_crc32 != pState->file_stat.m_crc32)\n        {\n            mz_zip_set_error(pState->pZip, MZ_ZIP_DECOMPRESSION_FAILED);\n            pState->status = TINFL_STATUS_FAILED;\n        }\n#endif\n    }\n\n    /* Free buffers */\n    if (!pState->pZip->m_pState->m_pMem)\n        pState->pZip->m_pFree(pState->pZip->m_pAlloc_opaque, pState->pRead_buf);\n    if (pState->pWrite_buf)\n        pState->pZip->m_pFree(pState->pZip->m_pAlloc_opaque, pState->pWrite_buf);\n\n    /* Save status */\n    status = pState->status;\n\n    /* Free context */\n    pState->pZip->m_pFree(pState->pZip->m_pAlloc_opaque, pState);\n\n    return status == TINFL_STATUS_DONE;\n}\n\n#ifndef MINIZ_NO_STDIO\nstatic size_t mz_zip_file_write_callback(void *pOpaque, mz_uint64 ofs, const void *pBuf, size_t n)\n{\n    (void)ofs;\n\n    return MZ_FWRITE(pBuf, 1, n, (MZ_FILE *)pOpaque);\n}\n\nmz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags)\n{\n    mz_bool status;\n    mz_zip_archive_file_stat file_stat;\n    MZ_FILE *pFile;\n\n    if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))\n        return MZ_FALSE;\n\n    if ((file_stat.m_is_directory) || (!file_stat.m_is_supported))\n        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE);\n\n    pFile = MZ_FOPEN(pDst_filename, \"wb\");\n    if (!pFile)\n        return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);\n\n    status = mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_file_write_callback, pFile, flags);\n\n    if (MZ_FCLOSE(pFile) == EOF)\n    {\n        if (status)\n            mz_zip_set_error(pZip, MZ_ZIP_FILE_CLOSE_FAILED);\n\n        status = MZ_FALSE;\n    }\n\n#if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_STDIO)\n    if (status)\n        mz_zip_set_file_times(pDst_filename, file_stat.m_time, file_stat.m_time);\n#endif\n\n    return status;\n}\n\nmz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags)\n{\n    mz_uint32 file_index;\n    if (!mz_zip_reader_locate_file_v2(pZip, pArchive_filename, NULL, flags, &file_index))\n        return MZ_FALSE;\n\n    return mz_zip_reader_extract_to_file(pZip, file_index, pDst_filename, flags);\n}\n\nmz_bool mz_zip_reader_extract_to_cfile(mz_zip_archive *pZip, mz_uint file_index, MZ_FILE *pFile, mz_uint flags)\n{\n    mz_zip_archive_file_stat file_stat;\n\n    if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))\n        return MZ_FALSE;\n\n    if ((file_stat.m_is_directory) || (!file_stat.m_is_supported))\n        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE);\n\n    return mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_file_write_callback, pFile, flags);\n}\n\nmz_bool mz_zip_reader_extract_file_to_cfile(mz_zip_archive *pZip, const char *pArchive_filename, MZ_FILE *pFile, mz_uint flags)\n{\n    mz_uint32 file_index;\n    if (!mz_zip_reader_locate_file_v2(pZip, pArchive_filename, NULL, flags, &file_index))\n        return MZ_FALSE;\n\n    return mz_zip_reader_extract_to_cfile(pZip, file_index, pFile, flags);\n}\n#endif /* #ifndef MINIZ_NO_STDIO */\n\nstatic size_t mz_zip_compute_crc32_callback(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)\n{\n    mz_uint32 *p = (mz_uint32 *)pOpaque;\n    (void)file_ofs;\n    *p = (mz_uint32)mz_crc32(*p, (const mz_uint8 *)pBuf, n);\n    return n;\n}\n\nmz_bool mz_zip_validate_file(mz_zip_archive *pZip, mz_uint file_index, mz_uint flags)\n{\n    mz_zip_archive_file_stat file_stat;\n    mz_zip_internal_state *pState;\n    const mz_uint8 *pCentral_dir_header;\n    mz_bool found_zip64_ext_data_in_cdir = MZ_FALSE;\n    mz_bool found_zip64_ext_data_in_ldir = MZ_FALSE;\n    mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];\n    mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;\n    mz_uint64 local_header_ofs = 0;\n    mz_uint32 local_header_filename_len, local_header_extra_len, local_header_crc32;\n    mz_uint64 local_header_comp_size, local_header_uncomp_size;\n    mz_uint32 uncomp_crc32 = MZ_CRC32_INIT;\n    mz_bool has_data_descriptor;\n    mz_uint32 local_header_bit_flags;\n\n    mz_zip_array file_data_array;\n    mz_zip_array_init(&file_data_array, 1);\n\n    if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (!pZip->m_pRead))\n        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);\n\n    if (file_index > pZip->m_total_files)\n        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);\n\n    pState = pZip->m_pState;\n\n    pCentral_dir_header = mz_zip_get_cdh(pZip, file_index);\n\n    if (!mz_zip_file_stat_internal(pZip, file_index, pCentral_dir_header, &file_stat, &found_zip64_ext_data_in_cdir))\n        return MZ_FALSE;\n\n    /* A directory or zero length file */\n    if ((file_stat.m_is_directory) || (!file_stat.m_uncomp_size))\n        return MZ_TRUE;\n\n    /* Encryption and patch files are not supported. */\n    if (file_stat.m_is_encrypted)\n        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);\n\n    /* This function only supports stored and deflate. */\n    if ((file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))\n        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);\n\n    if (!file_stat.m_is_supported)\n        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE);\n\n    /* Read and parse the local directory entry. */\n    local_header_ofs = file_stat.m_local_header_ofs;\n    if (pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)\n        return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);\n\n    if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)\n        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);\n\n    local_header_filename_len = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS);\n    local_header_extra_len = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);\n    local_header_comp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS);\n    local_header_uncomp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS);\n    local_header_crc32 = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_CRC32_OFS);\n    local_header_bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS);\n    has_data_descriptor = (local_header_bit_flags & 8) != 0;\n\n    if (local_header_filename_len != strlen(file_stat.m_filename))\n        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);\n\n    if ((local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + local_header_filename_len + local_header_extra_len + file_stat.m_comp_size) > pZip->m_archive_size)\n        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);\n\n    if (!mz_zip_array_resize(pZip, &file_data_array, MZ_MAX(local_header_filename_len, local_header_extra_len), MZ_FALSE))\n        return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);\n\n    if (local_header_filename_len)\n    {\n        if (pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE, file_data_array.m_p, local_header_filename_len) != local_header_filename_len)\n        {\n            mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);\n            goto handle_failure;\n        }\n\n        /* I've seen 1 archive that had the same pathname, but used backslashes in the local dir and forward slashes in the central dir. Do we care about this? For now, this case will fail validation. */\n        if (memcmp(file_stat.m_filename, file_data_array.m_p, local_header_filename_len) != 0)\n        {\n            mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);\n            goto handle_failure;\n        }\n    }\n\n    if ((local_header_extra_len) && ((local_header_comp_size == MZ_UINT32_MAX) || (local_header_uncomp_size == MZ_UINT32_MAX)))\n    {\n        mz_uint32 extra_size_remaining = local_header_extra_len;\n        const mz_uint8 *pExtra_data = (const mz_uint8 *)file_data_array.m_p;\n\n        if (pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + local_header_filename_len, file_data_array.m_p, local_header_extra_len) != local_header_extra_len)\n        {\n            mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);\n            goto handle_failure;\n        }\n\n        do\n        {\n            mz_uint32 field_id, field_data_size, field_total_size;\n\n            if (extra_size_remaining < (sizeof(mz_uint16) * 2))\n                return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);\n\n            field_id = MZ_READ_LE16(pExtra_data);\n            field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));\n            field_total_size = field_data_size + sizeof(mz_uint16) * 2;\n\n            if (field_total_size > extra_size_remaining)\n                return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);\n\n            if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)\n            {\n                const mz_uint8 *pSrc_field_data = pExtra_data + sizeof(mz_uint32);\n\n                if (field_data_size < sizeof(mz_uint64) * 2)\n                {\n                    mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);\n                    goto handle_failure;\n                }\n\n                local_header_uncomp_size = MZ_READ_LE64(pSrc_field_data);\n                local_header_comp_size = MZ_READ_LE64(pSrc_field_data + sizeof(mz_uint64));\n\n                found_zip64_ext_data_in_ldir = MZ_TRUE;\n                break;\n            }\n\n            pExtra_data += field_total_size;\n            extra_size_remaining -= field_total_size;\n        } while (extra_size_remaining);\n    }\n\n    /* TODO: parse local header extra data when local_header_comp_size is 0xFFFFFFFF! (big_descriptor.zip) */\n    /* I've seen zips in the wild with the data descriptor bit set, but proper local header values and bogus data descriptors */\n    if ((has_data_descriptor) && (!local_header_comp_size) && (!local_header_crc32))\n    {\n        mz_uint8 descriptor_buf[32];\n        mz_bool has_id;\n        const mz_uint8 *pSrc;\n        mz_uint32 file_crc32;\n        mz_uint64 comp_size = 0, uncomp_size = 0;\n\n        mz_uint32 num_descriptor_uint32s = ((pState->m_zip64) || (found_zip64_ext_data_in_ldir)) ? 6 : 4;\n\n        if (pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + local_header_filename_len + local_header_extra_len + file_stat.m_comp_size, descriptor_buf, sizeof(mz_uint32) * num_descriptor_uint32s) != (sizeof(mz_uint32) * num_descriptor_uint32s))\n        {\n            mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);\n            goto handle_failure;\n        }\n\n        has_id = (MZ_READ_LE32(descriptor_buf) == MZ_ZIP_DATA_DESCRIPTOR_ID);\n        pSrc = has_id ? (descriptor_buf + sizeof(mz_uint32)) : descriptor_buf;\n\n        file_crc32 = MZ_READ_LE32(pSrc);\n\n        if ((pState->m_zip64) || (found_zip64_ext_data_in_ldir))\n        {\n            comp_size = MZ_READ_LE64(pSrc + sizeof(mz_uint32));\n            uncomp_size = MZ_READ_LE64(pSrc + sizeof(mz_uint32) + sizeof(mz_uint64));\n        }\n        else\n        {\n            comp_size = MZ_READ_LE32(pSrc + sizeof(mz_uint32));\n            uncomp_size = MZ_READ_LE32(pSrc + sizeof(mz_uint32) + sizeof(mz_uint32));\n        }\n\n        if ((file_crc32 != file_stat.m_crc32) || (comp_size != file_stat.m_comp_size) || (uncomp_size != file_stat.m_uncomp_size))\n        {\n            mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);\n            goto handle_failure;\n        }\n    }\n    else\n    {\n        if ((local_header_crc32 != file_stat.m_crc32) || (local_header_comp_size != file_stat.m_comp_size) || (local_header_uncomp_size != file_stat.m_uncomp_size))\n        {\n            mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);\n            goto handle_failure;\n        }\n    }\n\n    mz_zip_array_clear(pZip, &file_data_array);\n\n    if ((flags & MZ_ZIP_FLAG_VALIDATE_HEADERS_ONLY) == 0)\n    {\n        if (!mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_compute_crc32_callback, &uncomp_crc32, 0))\n            return MZ_FALSE;\n\n        /* 1 more check to be sure, although the extract checks too. */\n        if (uncomp_crc32 != file_stat.m_crc32)\n        {\n            mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);\n            return MZ_FALSE;\n        }\n    }\n\n    return MZ_TRUE;\n\nhandle_failure:\n    mz_zip_array_clear(pZip, &file_data_array);\n    return MZ_FALSE;\n}\n\nmz_bool mz_zip_validate_archive(mz_zip_archive *pZip, mz_uint flags)\n{\n    mz_zip_internal_state *pState;\n    uint32_t i;\n\n    if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (!pZip->m_pRead))\n        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);\n\n    pState = pZip->m_pState;\n\n    /* Basic sanity checks */\n    if (!pState->m_zip64)\n    {\n        if (pZip->m_total_files > MZ_UINT16_MAX)\n            return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);\n\n        if (pZip->m_archive_size > MZ_UINT32_MAX)\n            return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);\n    }\n    else\n    {\n        if (pZip->m_total_files >= MZ_UINT32_MAX)\n            return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);\n\n        if (pState->m_central_dir.m_size >= MZ_UINT32_MAX)\n            return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);\n    }\n\n    for (i = 0; i < pZip->m_total_files; i++)\n    {\n        if (MZ_ZIP_FLAG_VALIDATE_LOCATE_FILE_FLAG & flags)\n        {\n            mz_uint32 found_index;\n            mz_zip_archive_file_stat stat;\n\n            if (!mz_zip_reader_file_stat(pZip, i, &stat))\n                return MZ_FALSE;\n\n            if (!mz_zip_reader_locate_file_v2(pZip, stat.m_filename, NULL, 0, &found_index))\n                return MZ_FALSE;\n\n            /* This check can fail if there are duplicate filenames in the archive (which we don't check for when writing - that's up to the user) */\n            if (found_index != i)\n                return mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);\n        }\n\n        if (!mz_zip_validate_file(pZip, i, flags))\n            return MZ_FALSE;\n    }\n\n    return MZ_TRUE;\n}\n\nmz_bool mz_zip_validate_mem_archive(const void *pMem, size_t size, mz_uint flags, mz_zip_error *pErr)\n{\n    mz_bool success = MZ_TRUE;\n    mz_zip_archive zip;\n    mz_zip_error actual_err = MZ_ZIP_NO_ERROR;\n\n    if ((!pMem) || (!size))\n    {\n        if (pErr)\n            *pErr = MZ_ZIP_INVALID_PARAMETER;\n        return MZ_FALSE;\n    }\n\n    mz_zip_zero_struct(&zip);\n\n    if (!mz_zip_reader_init_mem(&zip, pMem, size, flags))\n    {\n        if (pErr)\n            *pErr = zip.m_last_error;\n        return MZ_FALSE;\n    }\n\n    if (!mz_zip_validate_archive(&zip, flags))\n    {\n        actual_err = zip.m_last_error;\n        success = MZ_FALSE;\n    }\n\n    if (!mz_zip_reader_end_internal(&zip, success))\n    {\n        if (!actual_err)\n            actual_err = zip.m_last_error;\n        success = MZ_FALSE;\n    }\n\n    if (pErr)\n        *pErr = actual_err;\n\n    return success;\n}\n\n#ifndef MINIZ_NO_STDIO\nmz_bool mz_zip_validate_file_archive(const char *pFilename, mz_uint flags, mz_zip_error *pErr)\n{\n    mz_bool success = MZ_TRUE;\n    mz_zip_archive zip;\n    mz_zip_error actual_err = MZ_ZIP_NO_ERROR;\n\n    if (!pFilename)\n    {\n        if (pErr)\n            *pErr = MZ_ZIP_INVALID_PARAMETER;\n        return MZ_FALSE;\n    }\n\n    mz_zip_zero_struct(&zip);\n\n    if (!mz_zip_reader_init_file_v2(&zip, pFilename, flags, 0, 0))\n    {\n        if (pErr)\n            *pErr = zip.m_last_error;\n        return MZ_FALSE;\n    }\n\n    if (!mz_zip_validate_archive(&zip, flags))\n    {\n        actual_err = zip.m_last_error;\n        success = MZ_FALSE;\n    }\n\n    if (!mz_zip_reader_end_internal(&zip, success))\n    {\n        if (!actual_err)\n            actual_err = zip.m_last_error;\n        success = MZ_FALSE;\n    }\n\n    if (pErr)\n        *pErr = actual_err;\n\n    return success;\n}\n#endif /* #ifndef MINIZ_NO_STDIO */\n\n/* ------------------- .ZIP archive writing */\n\n#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS\n\nstatic MZ_FORCEINLINE void mz_write_le16(mz_uint8 *p, mz_uint16 v)\n{\n    p[0] = (mz_uint8)v;\n    p[1] = (mz_uint8)(v >> 8);\n}\nstatic MZ_FORCEINLINE void mz_write_le32(mz_uint8 *p, mz_uint32 v)\n{\n    p[0] = (mz_uint8)v;\n    p[1] = (mz_uint8)(v >> 8);\n    p[2] = (mz_uint8)(v >> 16);\n    p[3] = (mz_uint8)(v >> 24);\n}\nstatic MZ_FORCEINLINE void mz_write_le64(mz_uint8 *p, mz_uint64 v)\n{\n    mz_write_le32(p, (mz_uint32)v);\n    mz_write_le32(p + sizeof(mz_uint32), (mz_uint32)(v >> 32));\n}\n\n#define MZ_WRITE_LE16(p, v) mz_write_le16((mz_uint8 *)(p), (mz_uint16)(v))\n#define MZ_WRITE_LE32(p, v) mz_write_le32((mz_uint8 *)(p), (mz_uint32)(v))\n#define MZ_WRITE_LE64(p, v) mz_write_le64((mz_uint8 *)(p), (mz_uint64)(v))\n\nstatic size_t mz_zip_heap_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)\n{\n    mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;\n    mz_zip_internal_state *pState = pZip->m_pState;\n    mz_uint64 new_size = MZ_MAX(file_ofs + n, pState->m_mem_size);\n\n    if (!n)\n        return 0;\n\n    /* An allocation this big is likely to just fail on 32-bit systems, so don't even go there. */\n    if ((sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF))\n    {\n        mz_zip_set_error(pZip, MZ_ZIP_FILE_TOO_LARGE);\n        return 0;\n    }\n\n    if (new_size > pState->m_mem_capacity)\n    {\n        void *pNew_block;\n        size_t new_capacity = MZ_MAX(64, pState->m_mem_capacity);\n\n        while (new_capacity < new_size)\n            new_capacity *= 2;\n\n        if (NULL == (pNew_block = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pState->m_pMem, 1, new_capacity)))\n        {\n            mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);\n            return 0;\n        }\n\n        pState->m_pMem = pNew_block;\n        pState->m_mem_capacity = new_capacity;\n    }\n    memcpy((mz_uint8 *)pState->m_pMem + file_ofs, pBuf, n);\n    pState->m_mem_size = (size_t)new_size;\n    return n;\n}\n\nstatic mz_bool mz_zip_writer_end_internal(mz_zip_archive *pZip, mz_bool set_last_error)\n{\n    mz_zip_internal_state *pState;\n    mz_bool status = MZ_TRUE;\n\n    if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || ((pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) && (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED)))\n    {\n        if (set_last_error)\n            mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);\n        return MZ_FALSE;\n    }\n\n    pState = pZip->m_pState;\n    pZip->m_pState = NULL;\n    mz_zip_array_clear(pZip, &pState->m_central_dir);\n    mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);\n    mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);\n\n#ifndef MINIZ_NO_STDIO\n    if (pState->m_pFile)\n    {\n        if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE)\n        {\n            if (MZ_FCLOSE(pState->m_pFile) == EOF)\n            {\n                if (set_last_error)\n                    mz_zip_set_error(pZip, MZ_ZIP_FILE_CLOSE_FAILED);\n                status = MZ_FALSE;\n            }\n        }\n\n        pState->m_pFile = NULL;\n    }\n#endif /* #ifndef MINIZ_NO_STDIO */\n\n    if ((pZip->m_pWrite == mz_zip_heap_write_func) && (pState->m_pMem))\n    {\n        pZip->m_pFree(pZip->m_pAlloc_opaque, pState->m_pMem);\n        pState->m_pMem = NULL;\n    }\n\n    pZip->m_pFree(pZip->m_pAlloc_opaque, pState);\n    pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;\n    return status;\n}\n\nmz_bool mz_zip_writer_init_v2(mz_zip_archive *pZip, mz_uint64 existing_size, mz_uint flags)\n{\n    mz_bool zip64 = (flags & MZ_ZIP_FLAG_WRITE_ZIP64) != 0;\n\n    if ((!pZip) || (pZip->m_pState) || (!pZip->m_pWrite) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))\n        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);\n\n    if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING)\n    {\n        if (!pZip->m_pRead)\n            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);\n    }\n\n    if (pZip->m_file_offset_alignment)\n    {\n        /* Ensure user specified file offset alignment is a power of 2. */\n        if (pZip->m_file_offset_alignment & (pZip->m_file_offset_alignment - 1))\n            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);\n    }\n\n    if (!pZip->m_pAlloc)\n        pZip->m_pAlloc = miniz_def_alloc_func;\n    if (!pZip->m_pFree)\n        pZip->m_pFree = miniz_def_free_func;\n    if (!pZip->m_pRealloc)\n        pZip->m_pRealloc = miniz_def_realloc_func;\n\n    pZip->m_archive_size = existing_size;\n    pZip->m_central_directory_file_ofs = 0;\n    pZip->m_total_files = 0;\n\n    if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))\n        return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);\n\n    memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));\n\n    MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8));\n    MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32));\n    MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32));\n\n    pZip->m_pState->m_zip64 = zip64;\n    pZip->m_pState->m_zip64_has_extended_info_fields = zip64;\n\n    pZip->m_zip_type = MZ_ZIP_TYPE_USER;\n    pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;\n\n    return MZ_TRUE;\n}\n\nmz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size)\n{\n    return mz_zip_writer_init_v2(pZip, existing_size, 0);\n}\n\nmz_bool mz_zip_writer_init_heap_v2(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size, mz_uint flags)\n{\n    pZip->m_pWrite = mz_zip_heap_write_func;\n    pZip->m_pNeeds_keepalive = NULL;\n\n    if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING)\n        pZip->m_pRead = mz_zip_mem_read_func;\n\n    pZip->m_pIO_opaque = pZip;\n\n    if (!mz_zip_writer_init_v2(pZip, size_to_reserve_at_beginning, flags))\n        return MZ_FALSE;\n\n    pZip->m_zip_type = MZ_ZIP_TYPE_HEAP;\n\n    if (0 != (initial_allocation_size = MZ_MAX(initial_allocation_size, size_to_reserve_at_beginning)))\n    {\n        if (NULL == (pZip->m_pState->m_pMem = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, initial_allocation_size)))\n        {\n            mz_zip_writer_end_internal(pZip, MZ_FALSE);\n            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);\n        }\n        pZip->m_pState->m_mem_capacity = initial_allocation_size;\n    }\n\n    return MZ_TRUE;\n}\n\nmz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size)\n{\n    return mz_zip_writer_init_heap_v2(pZip, size_to_reserve_at_beginning, initial_allocation_size, 0);\n}\n\n#ifndef MINIZ_NO_STDIO\nstatic size_t mz_zip_file_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)\n{\n    mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;\n    mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);\n\n    file_ofs += pZip->m_pState->m_file_archive_start_ofs;\n\n    if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET))))\n    {\n        mz_zip_set_error(pZip, MZ_ZIP_FILE_SEEK_FAILED);\n        return 0;\n    }\n\n    return MZ_FWRITE(pBuf, 1, n, pZip->m_pState->m_pFile);\n}\n\nmz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning)\n{\n    return mz_zip_writer_init_file_v2(pZip, pFilename, size_to_reserve_at_beginning, 0);\n}\n\nmz_bool mz_zip_writer_init_file_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning, mz_uint flags)\n{\n    MZ_FILE *pFile;\n\n    pZip->m_pWrite = mz_zip_file_write_func;\n    pZip->m_pNeeds_keepalive = NULL;\n\n    if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING)\n        pZip->m_pRead = mz_zip_file_read_func;\n\n    pZip->m_pIO_opaque = pZip;\n\n    if (!mz_zip_writer_init_v2(pZip, size_to_reserve_at_beginning, flags))\n        return MZ_FALSE;\n\n    if (NULL == (pFile = MZ_FOPEN(pFilename, (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING) ? \"w+b\" : \"wb\")))\n    {\n        mz_zip_writer_end(pZip);\n        return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);\n    }\n\n    pZip->m_pState->m_pFile = pFile;\n    pZip->m_zip_type = MZ_ZIP_TYPE_FILE;\n\n    if (size_to_reserve_at_beginning)\n    {\n        mz_uint64 cur_ofs = 0;\n        char buf[4096];\n\n        MZ_CLEAR_OBJ(buf);\n\n        do\n        {\n            size_t n = (size_t)MZ_MIN(sizeof(buf), size_to_reserve_at_beginning);\n            if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_ofs, buf, n) != n)\n            {\n                mz_zip_writer_end(pZip);\n                return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);\n            }\n            cur_ofs += n;\n            size_to_reserve_at_beginning -= n;\n        } while (size_to_reserve_at_beginning);\n    }\n\n    return MZ_TRUE;\n}\n\nmz_bool mz_zip_writer_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, mz_uint flags)\n{\n    pZip->m_pWrite = mz_zip_file_write_func;\n    pZip->m_pNeeds_keepalive = NULL;\n\n    if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING)\n        pZip->m_pRead = mz_zip_file_read_func;\n\n    pZip->m_pIO_opaque = pZip;\n\n    if (!mz_zip_writer_init_v2(pZip, 0, flags))\n        return MZ_FALSE;\n\n    pZip->m_pState->m_pFile = pFile;\n    pZip->m_pState->m_file_archive_start_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);\n    pZip->m_zip_type = MZ_ZIP_TYPE_CFILE;\n\n    return MZ_TRUE;\n}\n#endif /* #ifndef MINIZ_NO_STDIO */\n\nmz_bool mz_zip_writer_init_from_reader_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint flags)\n{\n    mz_zip_internal_state *pState;\n\n    if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))\n        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);\n\n    if (flags & MZ_ZIP_FLAG_WRITE_ZIP64)\n    {\n        /* We don't support converting a non-zip64 file to zip64 - this seems like more trouble than it's worth. (What about the existing 32-bit data descriptors that could follow the compressed data?) */\n        if (!pZip->m_pState->m_zip64)\n            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);\n    }\n\n    /* No sense in trying to write to an archive that's already at the support max size */\n    if (pZip->m_pState->m_zip64)\n    {\n        if (pZip->m_total_files == MZ_UINT32_MAX)\n            return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);\n    }\n    else\n    {\n        if (pZip->m_total_files == MZ_UINT16_MAX)\n            return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);\n\n        if ((pZip->m_archive_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_ZIP_LOCAL_DIR_HEADER_SIZE) > MZ_UINT32_MAX)\n            return mz_zip_set_error(pZip, MZ_ZIP_FILE_TOO_LARGE);\n    }\n\n    pState = pZip->m_pState;\n\n    if (pState->m_pFile)\n    {\n#ifdef MINIZ_NO_STDIO\n        (void)pFilename;\n        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);\n#else\n        if (pZip->m_pIO_opaque != pZip)\n            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);\n\n        if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE)\n        {\n            if (!pFilename)\n                return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);\n\n            /* Archive is being read from stdio and was originally opened only for reading. Try to reopen as writable. */\n            if (NULL == (pState->m_pFile = MZ_FREOPEN(pFilename, \"r+b\", pState->m_pFile)))\n            {\n                /* The mz_zip_archive is now in a bogus state because pState->m_pFile is NULL, so just close it. */\n                mz_zip_reader_end_internal(pZip, MZ_FALSE);\n                return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);\n            }\n        }\n\n        pZip->m_pWrite = mz_zip_file_write_func;\n        pZip->m_pNeeds_keepalive = NULL;\n#endif /* #ifdef MINIZ_NO_STDIO */\n    }\n    else if (pState->m_pMem)\n    {\n        /* Archive lives in a memory block. Assume it's from the heap that we can resize using the realloc callback. */\n        if (pZip->m_pIO_opaque != pZip)\n            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);\n\n        pState->m_mem_capacity = pState->m_mem_size;\n        pZip->m_pWrite = mz_zip_heap_write_func;\n        pZip->m_pNeeds_keepalive = NULL;\n    }\n    /* Archive is being read via a user provided read function - make sure the user has specified a write function too. */\n    else if (!pZip->m_pWrite)\n        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);\n\n    /* Start writing new files at the archive's current central directory location. */\n    /* TODO: We could add a flag that lets the user start writing immediately AFTER the existing central dir - this would be safer. */\n    pZip->m_archive_size = pZip->m_central_directory_file_ofs;\n    pZip->m_central_directory_file_ofs = 0;\n\n    /* Clear the sorted central dir offsets, they aren't useful or maintained now. */\n    /* Even though we're now in write mode, files can still be extracted and verified, but file locates will be slow. */\n    /* TODO: We could easily maintain the sorted central directory offsets. */\n    mz_zip_array_clear(pZip, &pZip->m_pState->m_sorted_central_dir_offsets);\n\n    pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;\n\n    return MZ_TRUE;\n}\n\nmz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename)\n{\n    return mz_zip_writer_init_from_reader_v2(pZip, pFilename, 0);\n}\n\n/* TODO: pArchive_name is a terrible name here! */\nmz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags)\n{\n    return mz_zip_writer_add_mem_ex(pZip, pArchive_name, pBuf, buf_size, NULL, 0, level_and_flags, 0, 0);\n}\n\ntypedef struct\n{\n    mz_zip_archive *m_pZip;\n    mz_uint64 m_cur_archive_file_ofs;\n    mz_uint64 m_comp_size;\n} mz_zip_writer_add_state;\n\nstatic mz_bool mz_zip_writer_add_put_buf_callback(const void *pBuf, int len, void *pUser)\n{\n    mz_zip_writer_add_state *pState = (mz_zip_writer_add_state *)pUser;\n    if ((int)pState->m_pZip->m_pWrite(pState->m_pZip->m_pIO_opaque, pState->m_cur_archive_file_ofs, pBuf, len) != len)\n        return MZ_FALSE;\n\n    pState->m_cur_archive_file_ofs += len;\n    pState->m_comp_size += len;\n    return MZ_TRUE;\n}\n\n#define MZ_ZIP64_MAX_LOCAL_EXTRA_FIELD_SIZE (sizeof(mz_uint16) * 2 + sizeof(mz_uint64) * 2)\n#define MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE (sizeof(mz_uint16) * 2 + sizeof(mz_uint64) * 3)\nstatic mz_uint32 mz_zip_writer_create_zip64_extra_data(mz_uint8 *pBuf, mz_uint64 *pUncomp_size, mz_uint64 *pComp_size, mz_uint64 *pLocal_header_ofs)\n{\n    mz_uint8 *pDst = pBuf;\n    mz_uint32 field_size = 0;\n\n    MZ_WRITE_LE16(pDst + 0, MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID);\n    MZ_WRITE_LE16(pDst + 2, 0);\n    pDst += sizeof(mz_uint16) * 2;\n\n    if (pUncomp_size)\n    {\n        MZ_WRITE_LE64(pDst, *pUncomp_size);\n        pDst += sizeof(mz_uint64);\n        field_size += sizeof(mz_uint64);\n    }\n\n    if (pComp_size)\n    {\n        MZ_WRITE_LE64(pDst, *pComp_size);\n        pDst += sizeof(mz_uint64);\n        field_size += sizeof(mz_uint64);\n    }\n\n    if (pLocal_header_ofs)\n    {\n        MZ_WRITE_LE64(pDst, *pLocal_header_ofs);\n        pDst += sizeof(mz_uint64);\n        field_size += sizeof(mz_uint64);\n    }\n\n    MZ_WRITE_LE16(pBuf + 2, field_size);\n\n    return (mz_uint32)(pDst - pBuf);\n}\n\nstatic mz_bool mz_zip_writer_create_local_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size, mz_uint16 extra_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date)\n{\n    (void)pZip;\n    memset(pDst, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE);\n    MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_SIG_OFS, MZ_ZIP_LOCAL_DIR_HEADER_SIG);\n    MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_VERSION_NEEDED_OFS, method ? 20 : 0);\n    MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_BIT_FLAG_OFS, bit_flags);\n    MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_METHOD_OFS, method);\n    MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_TIME_OFS, dos_time);\n    MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_DATE_OFS, dos_date);\n    MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_CRC32_OFS, uncomp_crc32);\n    MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS, MZ_MIN(comp_size, MZ_UINT32_MAX));\n    MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS, MZ_MIN(uncomp_size, MZ_UINT32_MAX));\n    MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILENAME_LEN_OFS, filename_size);\n    MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_EXTRA_LEN_OFS, extra_size);\n    return MZ_TRUE;\n}\n\nstatic mz_bool mz_zip_writer_create_central_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst,\n                                                       mz_uint16 filename_size, mz_uint16 extra_size, mz_uint16 comment_size,\n                                                       mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32,\n                                                       mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date,\n                                                       mz_uint64 local_header_ofs, mz_uint32 ext_attributes)\n{\n    (void)pZip;\n    memset(pDst, 0, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);\n    MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_SIG_OFS, MZ_ZIP_CENTRAL_DIR_HEADER_SIG);\n    MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_NEEDED_OFS, method ? 20 : 0);\n    MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_BIT_FLAG_OFS, bit_flags);\n    MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_METHOD_OFS, method);\n    MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_TIME_OFS, dos_time);\n    MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_DATE_OFS, dos_date);\n    MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_CRC32_OFS, uncomp_crc32);\n    MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, MZ_MIN(comp_size, MZ_UINT32_MAX));\n    MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, MZ_MIN(uncomp_size, MZ_UINT32_MAX));\n    MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILENAME_LEN_OFS, filename_size);\n    MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_EXTRA_LEN_OFS, extra_size);\n    MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_COMMENT_LEN_OFS, comment_size);\n    MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS, ext_attributes);\n    MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_LOCAL_HEADER_OFS, MZ_MIN(local_header_ofs, MZ_UINT32_MAX));\n    return MZ_TRUE;\n}\n\nstatic mz_bool mz_zip_writer_add_to_central_dir(mz_zip_archive *pZip, const char *pFilename, mz_uint16 filename_size,\n                                                const void *pExtra, mz_uint16 extra_size, const void *pComment, mz_uint16 comment_size,\n                                                mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32,\n                                                mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date,\n                                                mz_uint64 local_header_ofs, mz_uint32 ext_attributes,\n                                                const char *user_extra_data, mz_uint user_extra_data_len)\n{\n    mz_zip_internal_state *pState = pZip->m_pState;\n    mz_uint32 central_dir_ofs = (mz_uint32)pState->m_central_dir.m_size;\n    size_t orig_central_dir_size = pState->m_central_dir.m_size;\n    mz_uint8 central_dir_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];\n\n    if (!pZip->m_pState->m_zip64)\n    {\n        if (local_header_ofs > 0xFFFFFFFF)\n            return mz_zip_set_error(pZip, MZ_ZIP_FILE_TOO_LARGE);\n    }\n\n    /* miniz doesn't support central dirs >= MZ_UINT32_MAX bytes yet */\n    if (((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + extra_size + user_extra_data_len + comment_size) >= MZ_UINT32_MAX)\n        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);\n\n    if (!mz_zip_writer_create_central_dir_header(pZip, central_dir_header, filename_size, extra_size + user_extra_data_len, comment_size, uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time, dos_date, local_header_ofs, ext_attributes))\n        return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);\n\n    if ((!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_dir_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) ||\n        (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pFilename, filename_size)) ||\n        (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pExtra, extra_size)) ||\n        (!mz_zip_array_push_back(pZip, &pState->m_central_dir, user_extra_data, user_extra_data_len)) ||\n        (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pComment, comment_size)) ||\n        (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &central_dir_ofs, 1)))\n    {\n        /* Try to resize the central directory array back into its original state. */\n        mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);\n        return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);\n    }\n\n    return MZ_TRUE;\n}\n\nstatic mz_bool mz_zip_writer_validate_archive_name(const char *pArchive_name)\n{\n    /* Basic ZIP archive filename validity checks: Valid filenames cannot start with a forward slash, cannot contain a drive letter, and cannot use DOS-style backward slashes. */\n    if (*pArchive_name == '/')\n        return MZ_FALSE;\n\n    while (*pArchive_name)\n    {\n        if ((*pArchive_name == '\\\\') || (*pArchive_name == ':'))\n            return MZ_FALSE;\n\n        pArchive_name++;\n    }\n\n    return MZ_TRUE;\n}\n\nstatic mz_uint mz_zip_writer_compute_padding_needed_for_file_alignment(mz_zip_archive *pZip)\n{\n    mz_uint32 n;\n    if (!pZip->m_file_offset_alignment)\n        return 0;\n    n = (mz_uint32)(pZip->m_archive_size & (pZip->m_file_offset_alignment - 1));\n    return (mz_uint)((pZip->m_file_offset_alignment - n) & (pZip->m_file_offset_alignment - 1));\n}\n\nstatic mz_bool mz_zip_writer_write_zeros(mz_zip_archive *pZip, mz_uint64 cur_file_ofs, mz_uint32 n)\n{\n    char buf[4096];\n    memset(buf, 0, MZ_MIN(sizeof(buf), n));\n    while (n)\n    {\n        mz_uint32 s = MZ_MIN(sizeof(buf), n);\n        if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_file_ofs, buf, s) != s)\n            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);\n\n        cur_file_ofs += s;\n        n -= s;\n    }\n    return MZ_TRUE;\n}\n\nmz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags,\n                                 mz_uint64 uncomp_size, mz_uint32 uncomp_crc32)\n{\n    return mz_zip_writer_add_mem_ex_v2(pZip, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, uncomp_size, uncomp_crc32, NULL, NULL, 0, NULL, 0);\n}\n\nmz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size,\n                                    mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32, MZ_TIME_T *last_modified,\n                                    const char *user_extra_data, mz_uint user_extra_data_len, const char *user_extra_data_central, mz_uint user_extra_data_central_len)\n{\n    mz_uint16 method = 0, dos_time = 0, dos_date = 0;\n    mz_uint level, ext_attributes = 0, num_alignment_padding_bytes;\n    mz_uint64 local_dir_header_ofs = pZip->m_archive_size, cur_archive_file_ofs = pZip->m_archive_size, comp_size = 0;\n    size_t archive_name_size;\n    mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];\n    tdefl_compressor *pComp = NULL;\n    mz_bool store_data_uncompressed;\n    mz_zip_internal_state *pState;\n    mz_uint8 *pExtra_data = NULL;\n    mz_uint32 extra_size = 0;\n    mz_uint8 extra_data[MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE];\n    mz_uint16 bit_flags = 0;\n\n    if ((int)level_and_flags < 0)\n        level_and_flags = MZ_DEFAULT_LEVEL;\n\n    if (uncomp_size || (buf_size && !(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)))\n        bit_flags |= MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR;\n\n    if (!(level_and_flags & MZ_ZIP_FLAG_ASCII_FILENAME))\n        bit_flags |= MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8;\n\n    level = level_and_flags & 0xF;\n    store_data_uncompressed = ((!level) || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA));\n\n    if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || ((buf_size) && (!pBuf)) || (!pArchive_name) || ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION))\n        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);\n\n    pState = pZip->m_pState;\n\n    if (pState->m_zip64)\n    {\n        if (pZip->m_total_files == MZ_UINT32_MAX)\n            return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);\n    }\n    else\n    {\n        if (pZip->m_total_files == MZ_UINT16_MAX)\n        {\n            pState->m_zip64 = MZ_TRUE;\n            /*return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); */\n        }\n        if ((buf_size > 0xFFFFFFFF) || (uncomp_size > 0xFFFFFFFF))\n        {\n            pState->m_zip64 = MZ_TRUE;\n            /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */\n        }\n    }\n\n    if ((!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (uncomp_size))\n        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);\n\n    if (!mz_zip_writer_validate_archive_name(pArchive_name))\n        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME);\n\n#ifndef MINIZ_NO_TIME\n    if (last_modified != NULL)\n    {\n        mz_zip_time_t_to_dos_time(*last_modified, &dos_time, &dos_date);\n    }\n    else\n    {\n        MZ_TIME_T cur_time;\n        time(&cur_time);\n        mz_zip_time_t_to_dos_time(cur_time, &dos_time, &dos_date);\n    }\n#endif /* #ifndef MINIZ_NO_TIME */\n\n\tif (!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA))\n\t{\n\t\tuncomp_crc32 = (mz_uint32)mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, buf_size);\n\t\tuncomp_size = buf_size;\n\t\tif (uncomp_size <= 3)\n\t\t{\n\t\t\tlevel = 0;\n\t\t\tstore_data_uncompressed = MZ_TRUE;\n\t\t}\n\t}\n\n    archive_name_size = strlen(pArchive_name);\n    if (archive_name_size > MZ_UINT16_MAX)\n        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME);\n\n    num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);\n\n    /* miniz doesn't support central dirs >= MZ_UINT32_MAX bytes yet */\n    if (((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE + comment_size) >= MZ_UINT32_MAX)\n        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);\n\n    if (!pState->m_zip64)\n    {\n        /* Bail early if the archive would obviously become too large */\n        if ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + archive_name_size \n\t\t\t+ MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size + user_extra_data_len + \n\t\t\tpState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + user_extra_data_central_len\n\t\t\t+ MZ_ZIP_DATA_DESCRIPTER_SIZE32) > 0xFFFFFFFF)\n        {\n            pState->m_zip64 = MZ_TRUE;\n            /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */\n        }\n    }\n\n    if ((archive_name_size) && (pArchive_name[archive_name_size - 1] == '/'))\n    {\n        /* Set DOS Subdirectory attribute bit. */\n        ext_attributes |= MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG;\n\n        /* Subdirectories cannot contain data. */\n        if ((buf_size) || (uncomp_size))\n            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);\n    }\n\n    /* Try to do any allocations before writing to the archive, so if an allocation fails the file remains unmodified. (A good idea if we're doing an in-place modification.) */\n    if ((!mz_zip_array_ensure_room(pZip, &pState->m_central_dir, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size + (pState->m_zip64 ? MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE : 0))) || (!mz_zip_array_ensure_room(pZip, &pState->m_central_dir_offsets, 1)))\n        return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);\n\n    if ((!store_data_uncompressed) && (buf_size))\n    {\n        if (NULL == (pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor))))\n            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);\n    }\n\n    if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes))\n    {\n        pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);\n        return MZ_FALSE;\n    }\n\n    local_dir_header_ofs += num_alignment_padding_bytes;\n    if (pZip->m_file_offset_alignment)\n    {\n        MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0);\n    }\n    cur_archive_file_ofs += num_alignment_padding_bytes;\n\n    MZ_CLEAR_OBJ(local_dir_header);\n\n    if (!store_data_uncompressed || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA))\n    {\n        method = MZ_DEFLATED;\n    }\n\n    if (pState->m_zip64)\n    {\n        if (uncomp_size >= MZ_UINT32_MAX || local_dir_header_ofs >= MZ_UINT32_MAX)\n        {\n            pExtra_data = extra_data;\n            extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,\n                                                               (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);\n        }\n\n        if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, extra_size + user_extra_data_len, 0, 0, 0, method, bit_flags, dos_time, dos_date))\n            return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);\n\n        if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))\n            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);\n\n        cur_archive_file_ofs += sizeof(local_dir_header);\n\n        if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)\n        {\n            pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);\n            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);\n        }\n        cur_archive_file_ofs += archive_name_size;\n\n        if (pExtra_data != NULL)\n        {\n            if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, extra_data, extra_size) != extra_size)\n                return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);\n\n            cur_archive_file_ofs += extra_size;\n        }\n    }\n    else\n    {\n        if ((comp_size > MZ_UINT32_MAX) || (cur_archive_file_ofs > MZ_UINT32_MAX))\n            return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);\n        if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, user_extra_data_len, 0, 0, 0, method, bit_flags, dos_time, dos_date))\n            return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);\n\n        if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))\n            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);\n\n        cur_archive_file_ofs += sizeof(local_dir_header);\n\n        if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)\n        {\n            pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);\n            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);\n        }\n        cur_archive_file_ofs += archive_name_size;\n    }\n\n\tif (user_extra_data_len > 0)\n\t{\n\t\tif (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, user_extra_data, user_extra_data_len) != user_extra_data_len)\n\t\t\treturn mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);\n\n\t\tcur_archive_file_ofs += user_extra_data_len;\n\t}\n\n    if (store_data_uncompressed)\n    {\n        if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pBuf, buf_size) != buf_size)\n        {\n            pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);\n            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);\n        }\n\n        cur_archive_file_ofs += buf_size;\n        comp_size = buf_size;\n    }\n    else if (buf_size)\n    {\n        mz_zip_writer_add_state state;\n\n        state.m_pZip = pZip;\n        state.m_cur_archive_file_ofs = cur_archive_file_ofs;\n        state.m_comp_size = 0;\n\n        if ((tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY) ||\n            (tdefl_compress_buffer(pComp, pBuf, buf_size, TDEFL_FINISH) != TDEFL_STATUS_DONE))\n        {\n            pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);\n            return mz_zip_set_error(pZip, MZ_ZIP_COMPRESSION_FAILED);\n        }\n\n        comp_size = state.m_comp_size;\n        cur_archive_file_ofs = state.m_cur_archive_file_ofs;\n    }\n\n    pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);\n    pComp = NULL;\n\n    if (uncomp_size)\n    {\n        mz_uint8 local_dir_footer[MZ_ZIP_DATA_DESCRIPTER_SIZE64];\n        mz_uint32 local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE32;\n\n        MZ_ASSERT(bit_flags & MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR);\n\n        MZ_WRITE_LE32(local_dir_footer + 0, MZ_ZIP_DATA_DESCRIPTOR_ID);\n        MZ_WRITE_LE32(local_dir_footer + 4, uncomp_crc32);\n        if (pExtra_data == NULL)\n        {\n            if (comp_size > MZ_UINT32_MAX)\n                return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);\n\n            MZ_WRITE_LE32(local_dir_footer + 8, comp_size);\n            MZ_WRITE_LE32(local_dir_footer + 12, uncomp_size);\n        }\n        else\n        {\n            MZ_WRITE_LE64(local_dir_footer + 8, comp_size);\n            MZ_WRITE_LE64(local_dir_footer + 16, uncomp_size);\n            local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE64;\n        }\n\n        if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_footer, local_dir_footer_size) != local_dir_footer_size)\n            return MZ_FALSE;\n\n        cur_archive_file_ofs += local_dir_footer_size;\n    }\n\n    if (pExtra_data != NULL)\n    {\n        extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,\n                                                           (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);\n    }\n\n    if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, pExtra_data, extra_size, pComment,\n                                          comment_size, uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time, dos_date, local_dir_header_ofs, ext_attributes,\n                                          user_extra_data_central, user_extra_data_central_len))\n        return MZ_FALSE;\n\n    pZip->m_total_files++;\n    pZip->m_archive_size = cur_archive_file_ofs;\n\n    return MZ_TRUE;\n}\n\n#ifndef MINIZ_NO_STDIO\nmz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name, MZ_FILE *pSrc_file, mz_uint64 size_to_add, const MZ_TIME_T *pFile_time, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags,\n                                const char *user_extra_data, mz_uint user_extra_data_len, const char *user_extra_data_central, mz_uint user_extra_data_central_len)\n{\n    mz_uint16 gen_flags = MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR;\n    mz_uint uncomp_crc32 = MZ_CRC32_INIT, level, num_alignment_padding_bytes;\n    mz_uint16 method = 0, dos_time = 0, dos_date = 0, ext_attributes = 0;\n    mz_uint64 local_dir_header_ofs, cur_archive_file_ofs = pZip->m_archive_size, uncomp_size = size_to_add, comp_size = 0;\n    size_t archive_name_size;\n    mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];\n    mz_uint8 *pExtra_data = NULL;\n    mz_uint32 extra_size = 0;\n    mz_uint8 extra_data[MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE];\n    mz_zip_internal_state *pState;\n\n    if (!(level_and_flags & MZ_ZIP_FLAG_ASCII_FILENAME))\n        gen_flags |= MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8;\n\n    if ((int)level_and_flags < 0)\n        level_and_flags = MZ_DEFAULT_LEVEL;\n    level = level_and_flags & 0xF;\n\n    /* Sanity checks */\n    if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pArchive_name) || ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION))\n        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);\n\n    pState = pZip->m_pState;\n\n    if ((!pState->m_zip64) && (uncomp_size > MZ_UINT32_MAX))\n    {\n        /* Source file is too large for non-zip64 */\n        /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */\n        pState->m_zip64 = MZ_TRUE;\n    }\n\n    /* We could support this, but why? */\n    if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)\n        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);\n\n    if (!mz_zip_writer_validate_archive_name(pArchive_name))\n        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME);\n\n    if (pState->m_zip64)\n    {\n        if (pZip->m_total_files == MZ_UINT32_MAX)\n            return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);\n    }\n    else\n    {\n        if (pZip->m_total_files == MZ_UINT16_MAX)\n        {\n            pState->m_zip64 = MZ_TRUE;\n            /*return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); */\n        }\n    }\n\n    archive_name_size = strlen(pArchive_name);\n    if (archive_name_size > MZ_UINT16_MAX)\n        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME);\n\n    num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);\n\n    /* miniz doesn't support central dirs >= MZ_UINT32_MAX bytes yet */\n    if (((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE + comment_size) >= MZ_UINT32_MAX)\n        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);\n\n    if (!pState->m_zip64)\n    {\n        /* Bail early if the archive would obviously become too large */\n        if ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + archive_name_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE \n\t\t\t+ archive_name_size + comment_size + user_extra_data_len + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + 1024\n\t\t\t+ MZ_ZIP_DATA_DESCRIPTER_SIZE32 + user_extra_data_central_len) > 0xFFFFFFFF)\n        {\n            pState->m_zip64 = MZ_TRUE;\n            /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */\n        }\n    }\n\n#ifndef MINIZ_NO_TIME\n    if (pFile_time)\n    {\n        mz_zip_time_t_to_dos_time(*pFile_time, &dos_time, &dos_date);\n    }\n#endif\n\n    if (uncomp_size <= 3)\n        level = 0;\n\n    if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes))\n    {\n        return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);\n    }\n\n    cur_archive_file_ofs += num_alignment_padding_bytes;\n    local_dir_header_ofs = cur_archive_file_ofs;\n\n    if (pZip->m_file_offset_alignment)\n    {\n        MZ_ASSERT((cur_archive_file_ofs & (pZip->m_file_offset_alignment - 1)) == 0);\n    }\n\n    if (uncomp_size && level)\n    {\n        method = MZ_DEFLATED;\n    }\n\n    MZ_CLEAR_OBJ(local_dir_header);\n    if (pState->m_zip64)\n    {\n        if (uncomp_size >= MZ_UINT32_MAX || local_dir_header_ofs >= MZ_UINT32_MAX)\n        {\n            pExtra_data = extra_data;\n            extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,\n                                                               (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);\n        }\n\n        if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, extra_size + user_extra_data_len, 0, 0, 0, method, gen_flags, dos_time, dos_date))\n            return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);\n\n        if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))\n            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);\n\n        cur_archive_file_ofs += sizeof(local_dir_header);\n\n        if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)\n        {\n            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);\n        }\n\n        cur_archive_file_ofs += archive_name_size;\n\n        if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, extra_data, extra_size) != extra_size)\n            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);\n\n        cur_archive_file_ofs += extra_size;\n    }\n    else\n    {\n        if ((comp_size > MZ_UINT32_MAX) || (cur_archive_file_ofs > MZ_UINT32_MAX))\n            return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);\n        if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, user_extra_data_len, 0, 0, 0, method, gen_flags, dos_time, dos_date))\n            return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);\n\n        if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))\n            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);\n\n        cur_archive_file_ofs += sizeof(local_dir_header);\n\n        if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)\n        {\n            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);\n        }\n\n        cur_archive_file_ofs += archive_name_size;\n    }\n\n    if (user_extra_data_len > 0)\n    {\n        if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, user_extra_data, user_extra_data_len) != user_extra_data_len)\n            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);\n\n        cur_archive_file_ofs += user_extra_data_len;\n    }\n\n    if (uncomp_size)\n    {\n        mz_uint64 uncomp_remaining = uncomp_size;\n        void *pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, MZ_ZIP_MAX_IO_BUF_SIZE);\n        if (!pRead_buf)\n        {\n            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);\n        }\n\n        if (!level)\n        {\n            while (uncomp_remaining)\n            {\n                mz_uint n = (mz_uint)MZ_MIN((mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE, uncomp_remaining);\n                if ((MZ_FREAD(pRead_buf, 1, n, pSrc_file) != n) || (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pRead_buf, n) != n))\n                {\n                    pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);\n                    return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);\n                }\n                uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, n);\n                uncomp_remaining -= n;\n                cur_archive_file_ofs += n;\n            }\n            comp_size = uncomp_size;\n        }\n        else\n        {\n            mz_bool result = MZ_FALSE;\n            mz_zip_writer_add_state state;\n            tdefl_compressor *pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor));\n            if (!pComp)\n            {\n                pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);\n                return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);\n            }\n\n            state.m_pZip = pZip;\n            state.m_cur_archive_file_ofs = cur_archive_file_ofs;\n            state.m_comp_size = 0;\n\n            if (tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY)\n            {\n                pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);\n                pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);\n                return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);\n            }\n\n            for (;;)\n            {\n                size_t in_buf_size = (mz_uint32)MZ_MIN(uncomp_remaining, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE);\n                tdefl_status status;\n                tdefl_flush flush = TDEFL_NO_FLUSH;\n\n                if (MZ_FREAD(pRead_buf, 1, in_buf_size, pSrc_file) != in_buf_size)\n                {\n                    mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);\n                    break;\n                }\n\n                uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, in_buf_size);\n                uncomp_remaining -= in_buf_size;\n\n                if (pZip->m_pNeeds_keepalive != NULL && pZip->m_pNeeds_keepalive(pZip->m_pIO_opaque))\n                    flush = TDEFL_FULL_FLUSH;\n\n                status = tdefl_compress_buffer(pComp, pRead_buf, in_buf_size, uncomp_remaining ? flush : TDEFL_FINISH);\n                if (status == TDEFL_STATUS_DONE)\n                {\n                    result = MZ_TRUE;\n                    break;\n                }\n                else if (status != TDEFL_STATUS_OKAY)\n                {\n                    mz_zip_set_error(pZip, MZ_ZIP_COMPRESSION_FAILED);\n                    break;\n                }\n            }\n\n            pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);\n\n            if (!result)\n            {\n                pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);\n                return MZ_FALSE;\n            }\n\n            comp_size = state.m_comp_size;\n            cur_archive_file_ofs = state.m_cur_archive_file_ofs;\n        }\n\n        pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);\n    }\n\n    {\n        mz_uint8 local_dir_footer[MZ_ZIP_DATA_DESCRIPTER_SIZE64];\n        mz_uint32 local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE32;\n\n        MZ_WRITE_LE32(local_dir_footer + 0, MZ_ZIP_DATA_DESCRIPTOR_ID);\n        MZ_WRITE_LE32(local_dir_footer + 4, uncomp_crc32);\n        if (pExtra_data == NULL)\n        {\n            if (comp_size > MZ_UINT32_MAX)\n                return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);\n\n            MZ_WRITE_LE32(local_dir_footer + 8, comp_size);\n            MZ_WRITE_LE32(local_dir_footer + 12, uncomp_size);\n        }\n        else\n        {\n            MZ_WRITE_LE64(local_dir_footer + 8, comp_size);\n            MZ_WRITE_LE64(local_dir_footer + 16, uncomp_size);\n            local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE64;\n        }\n\n        if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_footer, local_dir_footer_size) != local_dir_footer_size)\n            return MZ_FALSE;\n\n        cur_archive_file_ofs += local_dir_footer_size;\n    }\n\n    if (pExtra_data != NULL)\n    {\n        extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,\n                                                           (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);\n    }\n\n    if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, pExtra_data, extra_size, pComment, comment_size,\n                                          uncomp_size, comp_size, uncomp_crc32, method, gen_flags, dos_time, dos_date, local_dir_header_ofs, ext_attributes,\n                                          user_extra_data_central, user_extra_data_central_len))\n        return MZ_FALSE;\n\n    pZip->m_total_files++;\n    pZip->m_archive_size = cur_archive_file_ofs;\n\n    return MZ_TRUE;\n}\n\nmz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags)\n{\n    MZ_FILE *pSrc_file = NULL;\n    mz_uint64 uncomp_size = 0;\n    MZ_TIME_T file_modified_time;\n    MZ_TIME_T *pFile_time = NULL;\n    mz_bool status;\n\n    memset(&file_modified_time, 0, sizeof(file_modified_time));\n\n#if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_STDIO)\n    pFile_time = &file_modified_time;\n    if (!mz_zip_get_file_modified_time(pSrc_filename, &file_modified_time))\n        return mz_zip_set_error(pZip, MZ_ZIP_FILE_STAT_FAILED);\n#endif\n\n    pSrc_file = MZ_FOPEN(pSrc_filename, \"rb\");\n    if (!pSrc_file)\n        return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);\n\n    MZ_FSEEK64(pSrc_file, 0, SEEK_END);\n    uncomp_size = MZ_FTELL64(pSrc_file);\n    MZ_FSEEK64(pSrc_file, 0, SEEK_SET);\n\n    status = mz_zip_writer_add_cfile(pZip, pArchive_name, pSrc_file, uncomp_size, pFile_time, pComment, comment_size, level_and_flags, NULL, 0, NULL, 0);\n\n    MZ_FCLOSE(pSrc_file);\n\n    return status;\n}\n#endif /* #ifndef MINIZ_NO_STDIO */\n\nstatic mz_bool mz_zip_writer_update_zip64_extension_block(mz_zip_array *pNew_ext, mz_zip_archive *pZip, const mz_uint8 *pExt, uint32_t ext_len, mz_uint64 *pComp_size, mz_uint64 *pUncomp_size, mz_uint64 *pLocal_header_ofs, mz_uint32 *pDisk_start)\n{\n    /* + 64 should be enough for any new zip64 data */\n    if (!mz_zip_array_reserve(pZip, pNew_ext, ext_len + 64, MZ_FALSE))\n        return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);\n\n    mz_zip_array_resize(pZip, pNew_ext, 0, MZ_FALSE);\n\n    if ((pUncomp_size) || (pComp_size) || (pLocal_header_ofs) || (pDisk_start))\n    {\n        mz_uint8 new_ext_block[64];\n        mz_uint8 *pDst = new_ext_block;\n        mz_write_le16(pDst, MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID);\n        mz_write_le16(pDst + sizeof(mz_uint16), 0);\n        pDst += sizeof(mz_uint16) * 2;\n\n        if (pUncomp_size)\n        {\n            mz_write_le64(pDst, *pUncomp_size);\n            pDst += sizeof(mz_uint64);\n        }\n\n        if (pComp_size)\n        {\n            mz_write_le64(pDst, *pComp_size);\n            pDst += sizeof(mz_uint64);\n        }\n\n        if (pLocal_header_ofs)\n        {\n            mz_write_le64(pDst, *pLocal_header_ofs);\n            pDst += sizeof(mz_uint64);\n        }\n\n        if (pDisk_start)\n        {\n            mz_write_le32(pDst, *pDisk_start);\n            pDst += sizeof(mz_uint32);\n        }\n\n        mz_write_le16(new_ext_block + sizeof(mz_uint16), (mz_uint16)((pDst - new_ext_block) - sizeof(mz_uint16) * 2));\n\n        if (!mz_zip_array_push_back(pZip, pNew_ext, new_ext_block, pDst - new_ext_block))\n            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);\n    }\n\n    if ((pExt) && (ext_len))\n    {\n        mz_uint32 extra_size_remaining = ext_len;\n        const mz_uint8 *pExtra_data = pExt;\n\n        do\n        {\n            mz_uint32 field_id, field_data_size, field_total_size;\n\n            if (extra_size_remaining < (sizeof(mz_uint16) * 2))\n                return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);\n\n            field_id = MZ_READ_LE16(pExtra_data);\n            field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));\n            field_total_size = field_data_size + sizeof(mz_uint16) * 2;\n\n            if (field_total_size > extra_size_remaining)\n                return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);\n\n            if (field_id != MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)\n            {\n                if (!mz_zip_array_push_back(pZip, pNew_ext, pExtra_data, field_total_size))\n                    return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);\n            }\n\n            pExtra_data += field_total_size;\n            extra_size_remaining -= field_total_size;\n        } while (extra_size_remaining);\n    }\n\n    return MZ_TRUE;\n}\n\n/* TODO: This func is now pretty freakin complex due to zip64, split it up? */\nmz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint src_file_index)\n{\n    mz_uint n, bit_flags, num_alignment_padding_bytes, src_central_dir_following_data_size;\n    mz_uint64 src_archive_bytes_remaining, local_dir_header_ofs;\n    mz_uint64 cur_src_file_ofs, cur_dst_file_ofs;\n    mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];\n    mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;\n    mz_uint8 new_central_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];\n    size_t orig_central_dir_size;\n    mz_zip_internal_state *pState;\n    void *pBuf;\n    const mz_uint8 *pSrc_central_header;\n    mz_zip_archive_file_stat src_file_stat;\n    mz_uint32 src_filename_len, src_comment_len, src_ext_len;\n    mz_uint32 local_header_filename_size, local_header_extra_len;\n    mz_uint64 local_header_comp_size, local_header_uncomp_size;\n    mz_bool found_zip64_ext_data_in_ldir = MZ_FALSE;\n\n    /* Sanity checks */\n    if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pSource_zip->m_pRead))\n        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);\n\n    pState = pZip->m_pState;\n\n    /* Don't support copying files from zip64 archives to non-zip64, even though in some cases this is possible */\n    if ((pSource_zip->m_pState->m_zip64) && (!pZip->m_pState->m_zip64))\n        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);\n\n    /* Get pointer to the source central dir header and crack it */\n    if (NULL == (pSrc_central_header = mz_zip_get_cdh(pSource_zip, src_file_index)))\n        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);\n\n    if (MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_SIG_OFS) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG)\n        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);\n\n    src_filename_len = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_FILENAME_LEN_OFS);\n    src_comment_len = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_COMMENT_LEN_OFS);\n    src_ext_len = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS);\n    src_central_dir_following_data_size = src_filename_len + src_ext_len + src_comment_len;\n\n    /* TODO: We don't support central dir's >= MZ_UINT32_MAX bytes right now (+32 fudge factor in case we need to add more extra data) */\n    if ((pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_central_dir_following_data_size + 32) >= MZ_UINT32_MAX)\n        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);\n\n    num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);\n\n    if (!pState->m_zip64)\n    {\n        if (pZip->m_total_files == MZ_UINT16_MAX)\n            return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);\n    }\n    else\n    {\n        /* TODO: Our zip64 support still has some 32-bit limits that may not be worth fixing. */\n        if (pZip->m_total_files == MZ_UINT32_MAX)\n            return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);\n    }\n\n    if (!mz_zip_file_stat_internal(pSource_zip, src_file_index, pSrc_central_header, &src_file_stat, NULL))\n        return MZ_FALSE;\n\n    cur_src_file_ofs = src_file_stat.m_local_header_ofs;\n    cur_dst_file_ofs = pZip->m_archive_size;\n\n    /* Read the source archive's local dir header */\n    if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)\n        return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);\n\n    if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)\n        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);\n\n    cur_src_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;\n\n    /* Compute the total size we need to copy (filename+extra data+compressed data) */\n    local_header_filename_size = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS);\n    local_header_extra_len = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);\n    local_header_comp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS);\n    local_header_uncomp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS);\n    src_archive_bytes_remaining = local_header_filename_size + local_header_extra_len + src_file_stat.m_comp_size;\n\n    /* Try to find a zip64 extended information field */\n    if ((local_header_extra_len) && ((local_header_comp_size == MZ_UINT32_MAX) || (local_header_uncomp_size == MZ_UINT32_MAX)))\n    {\n        mz_zip_array file_data_array;\n        const mz_uint8 *pExtra_data;\n        mz_uint32 extra_size_remaining = local_header_extra_len;\n\n        mz_zip_array_init(&file_data_array, 1);\n        if (!mz_zip_array_resize(pZip, &file_data_array, local_header_extra_len, MZ_FALSE))\n        {\n            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);\n        }\n\n        if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, src_file_stat.m_local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + local_header_filename_size, file_data_array.m_p, local_header_extra_len) != local_header_extra_len)\n        {\n            mz_zip_array_clear(pZip, &file_data_array);\n            return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);\n        }\n\n        pExtra_data = (const mz_uint8 *)file_data_array.m_p;\n\n        do\n        {\n            mz_uint32 field_id, field_data_size, field_total_size;\n\n            if (extra_size_remaining < (sizeof(mz_uint16) * 2))\n            {\n                mz_zip_array_clear(pZip, &file_data_array);\n                return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);\n            }\n\n            field_id = MZ_READ_LE16(pExtra_data);\n            field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));\n            field_total_size = field_data_size + sizeof(mz_uint16) * 2;\n\n            if (field_total_size > extra_size_remaining)\n            {\n                mz_zip_array_clear(pZip, &file_data_array);\n                return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);\n            }\n\n            if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)\n            {\n                const mz_uint8 *pSrc_field_data = pExtra_data + sizeof(mz_uint32);\n\n                if (field_data_size < sizeof(mz_uint64) * 2)\n                {\n                    mz_zip_array_clear(pZip, &file_data_array);\n                    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);\n                }\n\n                local_header_uncomp_size = MZ_READ_LE64(pSrc_field_data);\n                local_header_comp_size = MZ_READ_LE64(pSrc_field_data + sizeof(mz_uint64)); /* may be 0 if there's a descriptor */\n\n                found_zip64_ext_data_in_ldir = MZ_TRUE;\n                break;\n            }\n\n            pExtra_data += field_total_size;\n            extra_size_remaining -= field_total_size;\n        } while (extra_size_remaining);\n\n        mz_zip_array_clear(pZip, &file_data_array);\n    }\n\n    if (!pState->m_zip64)\n    {\n        /* Try to detect if the new archive will most likely wind up too big and bail early (+(sizeof(mz_uint32) * 4) is for the optional descriptor which could be present, +64 is a fudge factor). */\n        /* We also check when the archive is finalized so this doesn't need to be perfect. */\n        mz_uint64 approx_new_archive_size = cur_dst_file_ofs + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + src_archive_bytes_remaining + (sizeof(mz_uint32) * 4) +\n                                            pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_central_dir_following_data_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + 64;\n\n        if (approx_new_archive_size >= MZ_UINT32_MAX)\n            return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);\n    }\n\n    /* Write dest archive padding */\n    if (!mz_zip_writer_write_zeros(pZip, cur_dst_file_ofs, num_alignment_padding_bytes))\n        return MZ_FALSE;\n\n    cur_dst_file_ofs += num_alignment_padding_bytes;\n\n    local_dir_header_ofs = cur_dst_file_ofs;\n    if (pZip->m_file_offset_alignment)\n    {\n        MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0);\n    }\n\n    /* The original zip's local header+ext block doesn't change, even with zip64, so we can just copy it over to the dest zip */\n    if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)\n        return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);\n\n    cur_dst_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;\n\n    /* Copy over the source archive bytes to the dest archive, also ensure we have enough buf space to handle optional data descriptor */\n    if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)MZ_MAX(32U, MZ_MIN((mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE, src_archive_bytes_remaining)))))\n        return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);\n\n    while (src_archive_bytes_remaining)\n    {\n        n = (mz_uint)MZ_MIN((mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE, src_archive_bytes_remaining);\n        if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, n) != n)\n        {\n            pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);\n            return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);\n        }\n        cur_src_file_ofs += n;\n\n        if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n)\n        {\n            pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);\n            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);\n        }\n        cur_dst_file_ofs += n;\n\n        src_archive_bytes_remaining -= n;\n    }\n\n    /* Now deal with the optional data descriptor */\n    bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS);\n    if (bit_flags & 8)\n    {\n        /* Copy data descriptor */\n        if ((pSource_zip->m_pState->m_zip64) || (found_zip64_ext_data_in_ldir))\n        {\n            /* src is zip64, dest must be zip64 */\n\n            /* name\t\t\tuint32_t's */\n            /* id\t\t\t\t1 (optional in zip64?) */\n            /* crc\t\t\t1 */\n            /* comp_size\t2 */\n            /* uncomp_size 2 */\n            if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, (sizeof(mz_uint32) * 6)) != (sizeof(mz_uint32) * 6))\n            {\n                pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);\n                return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);\n            }\n\n            n = sizeof(mz_uint32) * ((MZ_READ_LE32(pBuf) == MZ_ZIP_DATA_DESCRIPTOR_ID) ? 6 : 5);\n        }\n        else\n        {\n            /* src is NOT zip64 */\n            mz_bool has_id;\n\n            if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, sizeof(mz_uint32) * 4) != sizeof(mz_uint32) * 4)\n            {\n                pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);\n                return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);\n            }\n\n            has_id = (MZ_READ_LE32(pBuf) == MZ_ZIP_DATA_DESCRIPTOR_ID);\n\n            if (pZip->m_pState->m_zip64)\n            {\n                /* dest is zip64, so upgrade the data descriptor */\n                const mz_uint32 *pSrc_descriptor = (const mz_uint32 *)((const mz_uint8 *)pBuf + (has_id ? sizeof(mz_uint32) : 0));\n                const mz_uint32 src_crc32 = pSrc_descriptor[0];\n                const mz_uint64 src_comp_size = pSrc_descriptor[1];\n                const mz_uint64 src_uncomp_size = pSrc_descriptor[2];\n\n                mz_write_le32((mz_uint8 *)pBuf, MZ_ZIP_DATA_DESCRIPTOR_ID);\n                mz_write_le32((mz_uint8 *)pBuf + sizeof(mz_uint32) * 1, src_crc32);\n                mz_write_le64((mz_uint8 *)pBuf + sizeof(mz_uint32) * 2, src_comp_size);\n                mz_write_le64((mz_uint8 *)pBuf + sizeof(mz_uint32) * 4, src_uncomp_size);\n\n                n = sizeof(mz_uint32) * 6;\n            }\n            else\n            {\n                /* dest is NOT zip64, just copy it as-is */\n                n = sizeof(mz_uint32) * (has_id ? 4 : 3);\n            }\n        }\n\n        if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n)\n        {\n            pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);\n            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);\n        }\n\n        cur_src_file_ofs += n;\n        cur_dst_file_ofs += n;\n    }\n    pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);\n\n    /* Finally, add the new central dir header */\n    orig_central_dir_size = pState->m_central_dir.m_size;\n\n    memcpy(new_central_header, pSrc_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);\n\n    if (pState->m_zip64)\n    {\n        /* This is the painful part: We need to write a new central dir header + ext block with updated zip64 fields, and ensure the old fields (if any) are not included. */\n        const mz_uint8 *pSrc_ext = pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_filename_len;\n        mz_zip_array new_ext_block;\n\n        mz_zip_array_init(&new_ext_block, sizeof(mz_uint8));\n\n        MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, MZ_UINT32_MAX);\n        MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, MZ_UINT32_MAX);\n        MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, MZ_UINT32_MAX);\n\n        if (!mz_zip_writer_update_zip64_extension_block(&new_ext_block, pZip, pSrc_ext, src_ext_len, &src_file_stat.m_comp_size, &src_file_stat.m_uncomp_size, &local_dir_header_ofs, NULL))\n        {\n            mz_zip_array_clear(pZip, &new_ext_block);\n            return MZ_FALSE;\n        }\n\n        MZ_WRITE_LE16(new_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS, new_ext_block.m_size);\n\n        if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE))\n        {\n            mz_zip_array_clear(pZip, &new_ext_block);\n            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);\n        }\n\n        if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, src_filename_len))\n        {\n            mz_zip_array_clear(pZip, &new_ext_block);\n            mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);\n            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);\n        }\n\n        if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_ext_block.m_p, new_ext_block.m_size))\n        {\n            mz_zip_array_clear(pZip, &new_ext_block);\n            mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);\n            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);\n        }\n\n        if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_filename_len + src_ext_len, src_comment_len))\n        {\n            mz_zip_array_clear(pZip, &new_ext_block);\n            mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);\n            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);\n        }\n\n        mz_zip_array_clear(pZip, &new_ext_block);\n    }\n    else\n    {\n        /* sanity checks */\n        if (cur_dst_file_ofs > MZ_UINT32_MAX)\n            return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);\n\n        if (local_dir_header_ofs >= MZ_UINT32_MAX)\n            return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);\n\n        MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_dir_header_ofs);\n\n        if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE))\n            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);\n\n        if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, src_central_dir_following_data_size))\n        {\n            mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);\n            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);\n        }\n    }\n\n    /* This shouldn't trigger unless we screwed up during the initial sanity checks */\n    if (pState->m_central_dir.m_size >= MZ_UINT32_MAX)\n    {\n        /* TODO: Support central dirs >= 32-bits in size */\n        mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);\n        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);\n    }\n\n    n = (mz_uint32)orig_central_dir_size;\n    if (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &n, 1))\n    {\n        mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);\n        return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);\n    }\n\n    pZip->m_total_files++;\n    pZip->m_archive_size = cur_dst_file_ofs;\n\n    return MZ_TRUE;\n}\n\nmz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip)\n{\n    mz_zip_internal_state *pState;\n    mz_uint64 central_dir_ofs, central_dir_size;\n    mz_uint8 hdr[256];\n\n    if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING))\n        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);\n\n    pState = pZip->m_pState;\n\n    if (pState->m_zip64)\n    {\n        if ((pZip->m_total_files > MZ_UINT32_MAX) || (pState->m_central_dir.m_size >= MZ_UINT32_MAX))\n            return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);\n    }\n    else\n    {\n        if ((pZip->m_total_files > MZ_UINT16_MAX) || ((pZip->m_archive_size + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) > MZ_UINT32_MAX))\n            return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);\n    }\n\n    central_dir_ofs = 0;\n    central_dir_size = 0;\n    if (pZip->m_total_files)\n    {\n        /* Write central directory */\n        central_dir_ofs = pZip->m_archive_size;\n        central_dir_size = pState->m_central_dir.m_size;\n        pZip->m_central_directory_file_ofs = central_dir_ofs;\n        if (pZip->m_pWrite(pZip->m_pIO_opaque, central_dir_ofs, pState->m_central_dir.m_p, (size_t)central_dir_size) != central_dir_size)\n            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);\n\n        pZip->m_archive_size += central_dir_size;\n    }\n\n    if (pState->m_zip64)\n    {\n        /* Write zip64 end of central directory header */\n        mz_uint64 rel_ofs_to_zip64_ecdr = pZip->m_archive_size;\n\n        MZ_CLEAR_OBJ(hdr);\n        MZ_WRITE_LE32(hdr + MZ_ZIP64_ECDH_SIG_OFS, MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG);\n        MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS, MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE - sizeof(mz_uint32) - sizeof(mz_uint64));\n        MZ_WRITE_LE16(hdr + MZ_ZIP64_ECDH_VERSION_MADE_BY_OFS, 0x031E); /* TODO: always Unix */\n        MZ_WRITE_LE16(hdr + MZ_ZIP64_ECDH_VERSION_NEEDED_OFS, 0x002D);\n        MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS, pZip->m_total_files);\n        MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS, pZip->m_total_files);\n        MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_SIZE_OFS, central_dir_size);\n        MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_OFS_OFS, central_dir_ofs);\n        if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE)\n            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);\n\n        pZip->m_archive_size += MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE;\n\n        /* Write zip64 end of central directory locator */\n        MZ_CLEAR_OBJ(hdr);\n        MZ_WRITE_LE32(hdr + MZ_ZIP64_ECDL_SIG_OFS, MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG);\n        MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS, rel_ofs_to_zip64_ecdr);\n        MZ_WRITE_LE32(hdr + MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS, 1);\n        if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) != MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE)\n            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);\n\n        pZip->m_archive_size += MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE;\n    }\n\n    /* Write end of central directory record */\n    MZ_CLEAR_OBJ(hdr);\n    MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_SIG_OFS, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG);\n    MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS, MZ_MIN(MZ_UINT16_MAX, pZip->m_total_files));\n    MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS, MZ_MIN(MZ_UINT16_MAX, pZip->m_total_files));\n    MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_SIZE_OFS, MZ_MIN(MZ_UINT32_MAX, central_dir_size));\n    MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_OFS_OFS, MZ_MIN(MZ_UINT32_MAX, central_dir_ofs));\n\n    if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)\n        return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);\n\n#ifndef MINIZ_NO_STDIO\n    if ((pState->m_pFile) && (MZ_FFLUSH(pState->m_pFile) == EOF))\n        return mz_zip_set_error(pZip, MZ_ZIP_FILE_CLOSE_FAILED);\n#endif /* #ifndef MINIZ_NO_STDIO */\n\n    pZip->m_archive_size += MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE;\n\n    pZip->m_zip_mode = MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED;\n    return MZ_TRUE;\n}\n\nmz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **ppBuf, size_t *pSize)\n{\n    if ((!ppBuf) || (!pSize))\n        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);\n\n    *ppBuf = NULL;\n    *pSize = 0;\n\n    if ((!pZip) || (!pZip->m_pState))\n        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);\n\n    if (pZip->m_pWrite != mz_zip_heap_write_func)\n        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);\n\n    if (!mz_zip_writer_finalize_archive(pZip))\n        return MZ_FALSE;\n\n    *ppBuf = pZip->m_pState->m_pMem;\n    *pSize = pZip->m_pState->m_mem_size;\n    pZip->m_pState->m_pMem = NULL;\n    pZip->m_pState->m_mem_size = pZip->m_pState->m_mem_capacity = 0;\n\n    return MZ_TRUE;\n}\n\nmz_bool mz_zip_writer_end(mz_zip_archive *pZip)\n{\n    return mz_zip_writer_end_internal(pZip, MZ_TRUE);\n}\n\n#ifndef MINIZ_NO_STDIO\nmz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags)\n{\n    return mz_zip_add_mem_to_archive_file_in_place_v2(pZip_filename, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, NULL);\n}\n\nmz_bool mz_zip_add_mem_to_archive_file_in_place_v2(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_zip_error *pErr)\n{\n    mz_bool status, created_new_archive = MZ_FALSE;\n    mz_zip_archive zip_archive;\n    struct MZ_FILE_STAT_STRUCT file_stat;\n    mz_zip_error actual_err = MZ_ZIP_NO_ERROR;\n\n    mz_zip_zero_struct(&zip_archive);\n    if ((int)level_and_flags < 0)\n        level_and_flags = MZ_DEFAULT_LEVEL;\n\n    if ((!pZip_filename) || (!pArchive_name) || ((buf_size) && (!pBuf)) || ((comment_size) && (!pComment)) || ((level_and_flags & 0xF) > MZ_UBER_COMPRESSION))\n    {\n        if (pErr)\n            *pErr = MZ_ZIP_INVALID_PARAMETER;\n        return MZ_FALSE;\n    }\n\n    if (!mz_zip_writer_validate_archive_name(pArchive_name))\n    {\n        if (pErr)\n            *pErr = MZ_ZIP_INVALID_FILENAME;\n        return MZ_FALSE;\n    }\n\n    /* Important: The regular non-64 bit version of stat() can fail here if the file is very large, which could cause the archive to be overwritten. */\n    /* So be sure to compile with _LARGEFILE64_SOURCE 1 */\n    if (MZ_FILE_STAT(pZip_filename, &file_stat) != 0)\n    {\n        /* Create a new archive. */\n        if (!mz_zip_writer_init_file_v2(&zip_archive, pZip_filename, 0, level_and_flags))\n        {\n            if (pErr)\n                *pErr = zip_archive.m_last_error;\n            return MZ_FALSE;\n        }\n\n        created_new_archive = MZ_TRUE;\n    }\n    else\n    {\n        /* Append to an existing archive. */\n        if (!mz_zip_reader_init_file_v2(&zip_archive, pZip_filename, level_and_flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY, 0, 0))\n        {\n            if (pErr)\n                *pErr = zip_archive.m_last_error;\n            return MZ_FALSE;\n        }\n\n        if (!mz_zip_writer_init_from_reader_v2(&zip_archive, pZip_filename, level_and_flags))\n        {\n            if (pErr)\n                *pErr = zip_archive.m_last_error;\n\n            mz_zip_reader_end_internal(&zip_archive, MZ_FALSE);\n\n            return MZ_FALSE;\n        }\n    }\n\n    status = mz_zip_writer_add_mem_ex(&zip_archive, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, 0, 0);\n    actual_err = zip_archive.m_last_error;\n\n    /* Always finalize, even if adding failed for some reason, so we have a valid central directory. (This may not always succeed, but we can try.) */\n    if (!mz_zip_writer_finalize_archive(&zip_archive))\n    {\n        if (!actual_err)\n            actual_err = zip_archive.m_last_error;\n\n        status = MZ_FALSE;\n    }\n\n    if (!mz_zip_writer_end_internal(&zip_archive, status))\n    {\n        if (!actual_err)\n            actual_err = zip_archive.m_last_error;\n\n        status = MZ_FALSE;\n    }\n\n    if ((!status) && (created_new_archive))\n    {\n        /* It's a new archive and something went wrong, so just delete it. */\n        int ignoredStatus = MZ_DELETE_FILE(pZip_filename);\n        (void)ignoredStatus;\n    }\n\n    if (pErr)\n        *pErr = actual_err;\n\n    return status;\n}\n\nvoid *mz_zip_extract_archive_file_to_heap_v2(const char *pZip_filename, const char *pArchive_name, const char *pComment, size_t *pSize, mz_uint flags, mz_zip_error *pErr)\n{\n    mz_uint32 file_index;\n    mz_zip_archive zip_archive;\n    void *p = NULL;\n\n    if (pSize)\n        *pSize = 0;\n\n    if ((!pZip_filename) || (!pArchive_name))\n    {\n        if (pErr)\n            *pErr = MZ_ZIP_INVALID_PARAMETER;\n\n        return NULL;\n    }\n\n    mz_zip_zero_struct(&zip_archive);\n    if (!mz_zip_reader_init_file_v2(&zip_archive, pZip_filename, flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY, 0, 0))\n    {\n        if (pErr)\n            *pErr = zip_archive.m_last_error;\n\n        return NULL;\n    }\n\n    if (mz_zip_reader_locate_file_v2(&zip_archive, pArchive_name, pComment, flags, &file_index))\n    {\n        p = mz_zip_reader_extract_to_heap(&zip_archive, file_index, pSize, flags);\n    }\n\n    mz_zip_reader_end_internal(&zip_archive, p != NULL);\n\n    if (pErr)\n        *pErr = zip_archive.m_last_error;\n\n    return p;\n}\n\nvoid *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint flags)\n{\n    return mz_zip_extract_archive_file_to_heap_v2(pZip_filename, pArchive_name, NULL, pSize, flags, NULL);\n}\n\n#endif /* #ifndef MINIZ_NO_STDIO */\n\n#endif /* #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS */\n\n/* ------------------- Misc utils */\n\nmz_zip_mode mz_zip_get_mode(mz_zip_archive *pZip)\n{\n    return pZip ? pZip->m_zip_mode : MZ_ZIP_MODE_INVALID;\n}\n\nmz_zip_type mz_zip_get_type(mz_zip_archive *pZip)\n{\n    return pZip ? pZip->m_zip_type : MZ_ZIP_TYPE_INVALID;\n}\n\nmz_zip_error mz_zip_set_last_error(mz_zip_archive *pZip, mz_zip_error err_num)\n{\n    mz_zip_error prev_err;\n\n    if (!pZip)\n        return MZ_ZIP_INVALID_PARAMETER;\n\n    prev_err = pZip->m_last_error;\n\n    pZip->m_last_error = err_num;\n    return prev_err;\n}\n\nmz_zip_error mz_zip_peek_last_error(mz_zip_archive *pZip)\n{\n    if (!pZip)\n        return MZ_ZIP_INVALID_PARAMETER;\n\n    return pZip->m_last_error;\n}\n\nmz_zip_error mz_zip_clear_last_error(mz_zip_archive *pZip)\n{\n    return mz_zip_set_last_error(pZip, MZ_ZIP_NO_ERROR);\n}\n\nmz_zip_error mz_zip_get_last_error(mz_zip_archive *pZip)\n{\n    mz_zip_error prev_err;\n\n    if (!pZip)\n        return MZ_ZIP_INVALID_PARAMETER;\n\n    prev_err = pZip->m_last_error;\n\n    pZip->m_last_error = MZ_ZIP_NO_ERROR;\n    return prev_err;\n}\n\nconst char *mz_zip_get_error_string(mz_zip_error mz_err)\n{\n    switch (mz_err)\n    {\n        case MZ_ZIP_NO_ERROR:\n            return \"no error\";\n        case MZ_ZIP_UNDEFINED_ERROR:\n            return \"undefined error\";\n        case MZ_ZIP_TOO_MANY_FILES:\n            return \"too many files\";\n        case MZ_ZIP_FILE_TOO_LARGE:\n            return \"file too large\";\n        case MZ_ZIP_UNSUPPORTED_METHOD:\n            return \"unsupported method\";\n        case MZ_ZIP_UNSUPPORTED_ENCRYPTION:\n            return \"unsupported encryption\";\n        case MZ_ZIP_UNSUPPORTED_FEATURE:\n            return \"unsupported feature\";\n        case MZ_ZIP_FAILED_FINDING_CENTRAL_DIR:\n            return \"failed finding central directory\";\n        case MZ_ZIP_NOT_AN_ARCHIVE:\n            return \"not a ZIP archive\";\n        case MZ_ZIP_INVALID_HEADER_OR_CORRUPTED:\n            return \"invalid header or archive is corrupted\";\n        case MZ_ZIP_UNSUPPORTED_MULTIDISK:\n            return \"unsupported multidisk archive\";\n        case MZ_ZIP_DECOMPRESSION_FAILED:\n            return \"decompression failed or archive is corrupted\";\n        case MZ_ZIP_COMPRESSION_FAILED:\n            return \"compression failed\";\n        case MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE:\n            return \"unexpected decompressed size\";\n        case MZ_ZIP_CRC_CHECK_FAILED:\n            return \"CRC-32 check failed\";\n        case MZ_ZIP_UNSUPPORTED_CDIR_SIZE:\n            return \"unsupported central directory size\";\n        case MZ_ZIP_ALLOC_FAILED:\n            return \"allocation failed\";\n        case MZ_ZIP_FILE_OPEN_FAILED:\n            return \"file open failed\";\n        case MZ_ZIP_FILE_CREATE_FAILED:\n            return \"file create failed\";\n        case MZ_ZIP_FILE_WRITE_FAILED:\n            return \"file write failed\";\n        case MZ_ZIP_FILE_READ_FAILED:\n            return \"file read failed\";\n        case MZ_ZIP_FILE_CLOSE_FAILED:\n            return \"file close failed\";\n        case MZ_ZIP_FILE_SEEK_FAILED:\n            return \"file seek failed\";\n        case MZ_ZIP_FILE_STAT_FAILED:\n            return \"file stat failed\";\n        case MZ_ZIP_INVALID_PARAMETER:\n            return \"invalid parameter\";\n        case MZ_ZIP_INVALID_FILENAME:\n            return \"invalid filename\";\n        case MZ_ZIP_BUF_TOO_SMALL:\n            return \"buffer too small\";\n        case MZ_ZIP_INTERNAL_ERROR:\n            return \"internal error\";\n        case MZ_ZIP_FILE_NOT_FOUND:\n            return \"file not found\";\n        case MZ_ZIP_ARCHIVE_TOO_LARGE:\n            return \"archive is too large\";\n        case MZ_ZIP_VALIDATION_FAILED:\n            return \"validation failed\";\n        case MZ_ZIP_WRITE_CALLBACK_FAILED:\n            return \"write calledback failed\";\n        default:\n            break;\n    }\n\n    return \"unknown error\";\n}\n\n/* Note: Just because the archive is not zip64 doesn't necessarily mean it doesn't have Zip64 extended information extra field, argh. */\nmz_bool mz_zip_is_zip64(mz_zip_archive *pZip)\n{\n    if ((!pZip) || (!pZip->m_pState))\n        return MZ_FALSE;\n\n    return pZip->m_pState->m_zip64;\n}\n\nsize_t mz_zip_get_central_dir_size(mz_zip_archive *pZip)\n{\n    if ((!pZip) || (!pZip->m_pState))\n        return 0;\n\n    return pZip->m_pState->m_central_dir.m_size;\n}\n\nmz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip)\n{\n    return pZip ? pZip->m_total_files : 0;\n}\n\nmz_uint64 mz_zip_get_archive_size(mz_zip_archive *pZip)\n{\n    if (!pZip)\n        return 0;\n    return pZip->m_archive_size;\n}\n\nmz_uint64 mz_zip_get_archive_file_start_offset(mz_zip_archive *pZip)\n{\n    if ((!pZip) || (!pZip->m_pState))\n        return 0;\n    return pZip->m_pState->m_file_archive_start_ofs;\n}\n\nMZ_FILE *mz_zip_get_cfile(mz_zip_archive *pZip)\n{\n    if ((!pZip) || (!pZip->m_pState))\n        return 0;\n    return pZip->m_pState->m_pFile;\n}\n\nsize_t mz_zip_read_archive_data(mz_zip_archive *pZip, mz_uint64 file_ofs, void *pBuf, size_t n)\n{\n    if ((!pZip) || (!pZip->m_pState) || (!pBuf) || (!pZip->m_pRead))\n        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);\n\n    return pZip->m_pRead(pZip->m_pIO_opaque, file_ofs, pBuf, n);\n}\n\nmz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size)\n{\n    mz_uint n;\n    const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);\n    if (!p)\n    {\n        if (filename_buf_size)\n            pFilename[0] = '\\0';\n        mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);\n        return 0;\n    }\n    n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);\n    if (filename_buf_size)\n    {\n        n = MZ_MIN(n, filename_buf_size - 1);\n        memcpy(pFilename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);\n        pFilename[n] = '\\0';\n    }\n    return n + 1;\n}\n\nmz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat)\n{\n    return mz_zip_file_stat_internal(pZip, file_index, mz_zip_get_cdh(pZip, file_index), pStat, NULL);\n}\n\nmz_bool mz_zip_end(mz_zip_archive *pZip)\n{\n    if (!pZip)\n        return MZ_FALSE;\n\n    if (pZip->m_zip_mode == MZ_ZIP_MODE_READING)\n        return mz_zip_reader_end(pZip);\n#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS\n    else if ((pZip->m_zip_mode == MZ_ZIP_MODE_WRITING) || (pZip->m_zip_mode == MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED))\n        return mz_zip_writer_end(pZip);\n#endif\n\n    return MZ_FALSE;\n}\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /*#ifndef MINIZ_NO_ARCHIVE_APIS*/\n"
  },
  {
    "path": "libs/miniz/miniz.h",
    "content": "/* miniz.c 2.0.8 - public domain deflate/inflate, zlib-subset, ZIP reading/writing/appending, PNG writing\n   See \"unlicense\" statement at the end of this file.\n   Rich Geldreich <richgel99@gmail.com>, last updated Oct. 13, 2013\n   Implements RFC 1950: http://www.ietf.org/rfc/rfc1950.txt and RFC 1951: http://www.ietf.org/rfc/rfc1951.txt\n\n   Most API's defined in miniz.c are optional. For example, to disable the archive related functions just define\n   MINIZ_NO_ARCHIVE_APIS, or to get rid of all stdio usage define MINIZ_NO_STDIO (see the list below for more macros).\n\n   * Low-level Deflate/Inflate implementation notes:\n\n     Compression: Use the \"tdefl\" API's. The compressor supports raw, static, and dynamic blocks, lazy or\n     greedy parsing, match length filtering, RLE-only, and Huffman-only streams. It performs and compresses\n     approximately as well as zlib.\n\n     Decompression: Use the \"tinfl\" API's. The entire decompressor is implemented as a single function\n     coroutine: see tinfl_decompress(). It supports decompression into a 32KB (or larger power of 2) wrapping buffer, or into a memory\n     block large enough to hold the entire file.\n\n     The low-level tdefl/tinfl API's do not make any use of dynamic memory allocation.\n\n   * zlib-style API notes:\n\n     miniz.c implements a fairly large subset of zlib. There's enough functionality present for it to be a drop-in\n     zlib replacement in many apps:\n        The z_stream struct, optional memory allocation callbacks\n        deflateInit/deflateInit2/deflate/deflateReset/deflateEnd/deflateBound\n        inflateInit/inflateInit2/inflate/inflateEnd\n        compress, compress2, compressBound, uncompress\n        CRC-32, Adler-32 - Using modern, minimal code size, CPU cache friendly routines.\n        Supports raw deflate streams or standard zlib streams with adler-32 checking.\n\n     Limitations:\n      The callback API's are not implemented yet. No support for gzip headers or zlib static dictionaries.\n      I've tried to closely emulate zlib's various flavors of stream flushing and return status codes, but\n      there are no guarantees that miniz.c pulls this off perfectly.\n\n   * PNG writing: See the tdefl_write_image_to_png_file_in_memory() function, originally written by\n     Alex Evans. Supports 1-4 bytes/pixel images.\n\n   * ZIP archive API notes:\n\n     The ZIP archive API's where designed with simplicity and efficiency in mind, with just enough abstraction to\n     get the job done with minimal fuss. There are simple API's to retrieve file information, read files from\n     existing archives, create new archives, append new files to existing archives, or clone archive data from\n     one archive to another. It supports archives located in memory or the heap, on disk (using stdio.h),\n     or you can specify custom file read/write callbacks.\n\n     - Archive reading: Just call this function to read a single file from a disk archive:\n\n      void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name,\n        size_t *pSize, mz_uint zip_flags);\n\n     For more complex cases, use the \"mz_zip_reader\" functions. Upon opening an archive, the entire central\n     directory is located and read as-is into memory, and subsequent file access only occurs when reading individual files.\n\n     - Archives file scanning: The simple way is to use this function to scan a loaded archive for a specific file:\n\n     int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags);\n\n     The locate operation can optionally check file comments too, which (as one example) can be used to identify\n     multiple versions of the same file in an archive. This function uses a simple linear search through the central\n     directory, so it's not very fast.\n\n     Alternately, you can iterate through all the files in an archive (using mz_zip_reader_get_num_files()) and\n     retrieve detailed info on each file by calling mz_zip_reader_file_stat().\n\n     - Archive creation: Use the \"mz_zip_writer\" functions. The ZIP writer immediately writes compressed file data\n     to disk and builds an exact image of the central directory in memory. The central directory image is written\n     all at once at the end of the archive file when the archive is finalized.\n\n     The archive writer can optionally align each file's local header and file data to any power of 2 alignment,\n     which can be useful when the archive will be read from optical media. Also, the writer supports placing\n     arbitrary data blobs at the very beginning of ZIP archives. Archives written using either feature are still\n     readable by any ZIP tool.\n\n     - Archive appending: The simple way to add a single file to an archive is to call this function:\n\n      mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name,\n        const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags);\n\n     The archive will be created if it doesn't already exist, otherwise it'll be appended to.\n     Note the appending is done in-place and is not an atomic operation, so if something goes wrong\n     during the operation it's possible the archive could be left without a central directory (although the local\n     file headers and file data will be fine, so the archive will be recoverable).\n\n     For more complex archive modification scenarios:\n     1. The safest way is to use a mz_zip_reader to read the existing archive, cloning only those bits you want to\n     preserve into a new archive using using the mz_zip_writer_add_from_zip_reader() function (which compiles the\n     compressed file data as-is). When you're done, delete the old archive and rename the newly written archive, and\n     you're done. This is safe but requires a bunch of temporary disk space or heap memory.\n\n     2. Or, you can convert an mz_zip_reader in-place to an mz_zip_writer using mz_zip_writer_init_from_reader(),\n     append new files as needed, then finalize the archive which will write an updated central directory to the\n     original archive. (This is basically what mz_zip_add_mem_to_archive_file_in_place() does.) There's a\n     possibility that the archive's central directory could be lost with this method if anything goes wrong, though.\n\n     - ZIP archive support limitations:\n     No zip64 or spanning support. Extraction functions can only handle unencrypted, stored or deflated files.\n     Requires streams capable of seeking.\n\n   * This is a header file library, like stb_image.c. To get only a header file, either cut and paste the\n     below header, or create miniz.h, #define MINIZ_HEADER_FILE_ONLY, and then include miniz.c from it.\n\n   * Important: For best perf. be sure to customize the below macros for your target platform:\n     #define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1\n     #define MINIZ_LITTLE_ENDIAN 1\n     #define MINIZ_HAS_64BIT_REGISTERS 1\n\n   * On platforms using glibc, Be sure to \"#define _LARGEFILE64_SOURCE 1\" before including miniz.c to ensure miniz\n     uses the 64-bit variants: fopen64(), stat64(), etc. Otherwise you won't be able to process large files\n     (i.e. 32-bit stat() fails for me on files > 0x7FFFFFFF bytes).\n*/\n#pragma once\n\n\n\n\n\n/* Defines to completely disable specific portions of miniz.c: \n   If all macros here are defined the only functionality remaining will be CRC-32, adler-32, tinfl, and tdefl. */\n\n/* Define MINIZ_NO_STDIO to disable all usage and any functions which rely on stdio for file I/O. */\n/*#define MINIZ_NO_STDIO */\n\n/* If MINIZ_NO_TIME is specified then the ZIP archive functions will not be able to get the current time, or */\n/* get/set file times, and the C run-time funcs that get/set times won't be called. */\n/* The current downside is the times written to your archives will be from 1979. */\n/*#define MINIZ_NO_TIME */\n\n/* Define MINIZ_NO_ARCHIVE_APIS to disable all ZIP archive API's. */\n/*#define MINIZ_NO_ARCHIVE_APIS */\n\n/* Define MINIZ_NO_ARCHIVE_WRITING_APIS to disable all writing related ZIP archive API's. */\n/*#define MINIZ_NO_ARCHIVE_WRITING_APIS */\n\n/* Define MINIZ_NO_ZLIB_APIS to remove all ZLIB-style compression/decompression API's. */\n/*#define MINIZ_NO_ZLIB_APIS */\n\n/* Define MINIZ_NO_ZLIB_COMPATIBLE_NAME to disable zlib names, to prevent conflicts against stock zlib. */\n/*#define MINIZ_NO_ZLIB_COMPATIBLE_NAMES */\n\n/* Define MINIZ_NO_MALLOC to disable all calls to malloc, free, and realloc. \n   Note if MINIZ_NO_MALLOC is defined then the user must always provide custom user alloc/free/realloc\n   callbacks to the zlib and archive API's, and a few stand-alone helper API's which don't provide custom user\n   functions (such as tdefl_compress_mem_to_heap() and tinfl_decompress_mem_to_heap()) won't work. */\n/*#define MINIZ_NO_MALLOC */\n\n#if defined(__TINYC__) && (defined(__linux) || defined(__linux__))\n/* TODO: Work around \"error: include file 'sys\\utime.h' when compiling with tcc on Linux */\n#define MINIZ_NO_TIME\n#endif\n\n#include <stddef.h>\n\n#if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_ARCHIVE_APIS)\n#include <time.h>\n#endif\n\n#if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || defined(__i386) || defined(__i486__) || defined(__i486) || defined(i386) || defined(__ia64__) || defined(__x86_64__)\n/* MINIZ_X86_OR_X64_CPU is only used to help set the below macros. */\n#define MINIZ_X86_OR_X64_CPU 1\n#else\n#define MINIZ_X86_OR_X64_CPU 0\n#endif\n\n#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || MINIZ_X86_OR_X64_CPU\n/* Set MINIZ_LITTLE_ENDIAN to 1 if the processor is little endian. */\n#define MINIZ_LITTLE_ENDIAN 1\n#else\n#define MINIZ_LITTLE_ENDIAN 0\n#endif\n\n#if MINIZ_X86_OR_X64_CPU\n/* Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES to 1 on CPU's that permit efficient integer loads and stores from unaligned addresses. */\n#define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1\n#else\n#define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 0\n#endif\n\n#if defined(_M_X64) || defined(_WIN64) || defined(__MINGW64__) || defined(_LP64) || defined(__LP64__) || defined(__ia64__) || defined(__x86_64__)\n/* Set MINIZ_HAS_64BIT_REGISTERS to 1 if operations on 64-bit integers are reasonably fast (and don't involve compiler generated calls to helper functions). */\n#define MINIZ_HAS_64BIT_REGISTERS 1\n#else\n#define MINIZ_HAS_64BIT_REGISTERS 0\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* ------------------- zlib-style API Definitions. */\n\n/* For more compatibility with zlib, miniz.c uses unsigned long for some parameters/struct members. Beware: mz_ulong can be either 32 or 64-bits! */\ntypedef unsigned long mz_ulong;\n\n/* mz_free() internally uses the MZ_FREE() macro (which by default calls free() unless you've modified the MZ_MALLOC macro) to release a block allocated from the heap. */\nvoid mz_free(void *p);\n\n#define MZ_ADLER32_INIT (1)\n/* mz_adler32() returns the initial adler-32 value to use when called with ptr==NULL. */\nmz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len);\n\n#define MZ_CRC32_INIT (0)\n/* mz_crc32() returns the initial CRC-32 value to use when called with ptr==NULL. */\nmz_ulong mz_crc32(mz_ulong crc, const unsigned char *ptr, size_t buf_len);\n\n/* Compression strategies. */\nenum\n{\n    MZ_DEFAULT_STRATEGY = 0,\n    MZ_FILTERED = 1,\n    MZ_HUFFMAN_ONLY = 2,\n    MZ_RLE = 3,\n    MZ_FIXED = 4\n};\n\n/* Method */\n#define MZ_DEFLATED 8\n\n/* Heap allocation callbacks.\nNote that mz_alloc_func parameter types purpsosely differ from zlib's: items/size is size_t, not unsigned long. */\ntypedef void *(*mz_alloc_func)(void *opaque, size_t items, size_t size);\ntypedef void (*mz_free_func)(void *opaque, void *address);\ntypedef void *(*mz_realloc_func)(void *opaque, void *address, size_t items, size_t size);\n\n/* Compression levels: 0-9 are the standard zlib-style levels, 10 is best possible compression (not zlib compatible, and may be very slow), MZ_DEFAULT_COMPRESSION=MZ_DEFAULT_LEVEL. */\nenum\n{\n    MZ_NO_COMPRESSION = 0,\n    MZ_BEST_SPEED = 1,\n    MZ_BEST_COMPRESSION = 9,\n    MZ_UBER_COMPRESSION = 10,\n    MZ_DEFAULT_LEVEL = 6,\n    MZ_DEFAULT_COMPRESSION = -1\n};\n\n#define MZ_VERSION \"10.0.3\"\n#define MZ_VERNUM 0xA030\n#define MZ_VER_MAJOR 10\n#define MZ_VER_MINOR 0\n#define MZ_VER_REVISION 3\n#define MZ_VER_SUBREVISION 0\n\n#ifndef MINIZ_NO_ZLIB_APIS\n\n/* Flush values. For typical usage you only need MZ_NO_FLUSH and MZ_FINISH. The other values are for advanced use (refer to the zlib docs). */\nenum\n{\n    MZ_NO_FLUSH = 0,\n    MZ_PARTIAL_FLUSH = 1,\n    MZ_SYNC_FLUSH = 2,\n    MZ_FULL_FLUSH = 3,\n    MZ_FINISH = 4,\n    MZ_BLOCK = 5\n};\n\n/* Return status codes. MZ_PARAM_ERROR is non-standard. */\nenum\n{\n    MZ_OK = 0,\n    MZ_STREAM_END = 1,\n    MZ_NEED_DICT = 2,\n    MZ_ERRNO = -1,\n    MZ_STREAM_ERROR = -2,\n    MZ_DATA_ERROR = -3,\n    MZ_MEM_ERROR = -4,\n    MZ_BUF_ERROR = -5,\n    MZ_VERSION_ERROR = -6,\n    MZ_PARAM_ERROR = -10000\n};\n\n/* Window bits */\n#define MZ_DEFAULT_WINDOW_BITS 15\n\nstruct mz_internal_state;\n\n/* Compression/decompression stream struct. */\ntypedef struct mz_stream_s\n{\n    const unsigned char *next_in; /* pointer to next byte to read */\n    unsigned int avail_in;        /* number of bytes available at next_in */\n    mz_ulong total_in;            /* total number of bytes consumed so far */\n\n    unsigned char *next_out; /* pointer to next byte to write */\n    unsigned int avail_out;  /* number of bytes that can be written to next_out */\n    mz_ulong total_out;      /* total number of bytes produced so far */\n\n    char *msg;                       /* error msg (unused) */\n    struct mz_internal_state *state; /* internal state, allocated by zalloc/zfree */\n\n    mz_alloc_func zalloc; /* optional heap allocation function (defaults to malloc) */\n    mz_free_func zfree;   /* optional heap free function (defaults to free) */\n    void *opaque;         /* heap alloc function user pointer */\n\n    int data_type;     /* data_type (unused) */\n    mz_ulong adler;    /* adler32 of the source or uncompressed data */\n    mz_ulong reserved; /* not used */\n} mz_stream;\n\ntypedef mz_stream *mz_streamp;\n\n/* Returns the version string of miniz.c. */\nconst char *mz_version(void);\n\n/* mz_deflateInit() initializes a compressor with default options: */\n/* Parameters: */\n/*  pStream must point to an initialized mz_stream struct. */\n/*  level must be between [MZ_NO_COMPRESSION, MZ_BEST_COMPRESSION]. */\n/*  level 1 enables a specially optimized compression function that's been optimized purely for performance, not ratio. */\n/*  (This special func. is currently only enabled when MINIZ_USE_UNALIGNED_LOADS_AND_STORES and MINIZ_LITTLE_ENDIAN are defined.) */\n/* Return values: */\n/*  MZ_OK on success. */\n/*  MZ_STREAM_ERROR if the stream is bogus. */\n/*  MZ_PARAM_ERROR if the input parameters are bogus. */\n/*  MZ_MEM_ERROR on out of memory. */\nint mz_deflateInit(mz_streamp pStream, int level);\n\n/* mz_deflateInit2() is like mz_deflate(), except with more control: */\n/* Additional parameters: */\n/*   method must be MZ_DEFLATED */\n/*   window_bits must be MZ_DEFAULT_WINDOW_BITS (to wrap the deflate stream with zlib header/adler-32 footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate/no header or footer) */\n/*   mem_level must be between [1, 9] (it's checked but ignored by miniz.c) */\nint mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy);\n\n/* Quickly resets a compressor without having to reallocate anything. Same as calling mz_deflateEnd() followed by mz_deflateInit()/mz_deflateInit2(). */\nint mz_deflateReset(mz_streamp pStream);\n\n/* mz_deflate() compresses the input to output, consuming as much of the input and producing as much output as possible. */\n/* Parameters: */\n/*   pStream is the stream to read from and write to. You must initialize/update the next_in, avail_in, next_out, and avail_out members. */\n/*   flush may be MZ_NO_FLUSH, MZ_PARTIAL_FLUSH/MZ_SYNC_FLUSH, MZ_FULL_FLUSH, or MZ_FINISH. */\n/* Return values: */\n/*   MZ_OK on success (when flushing, or if more input is needed but not available, and/or there's more output to be written but the output buffer is full). */\n/*   MZ_STREAM_END if all input has been consumed and all output bytes have been written. Don't call mz_deflate() on the stream anymore. */\n/*   MZ_STREAM_ERROR if the stream is bogus. */\n/*   MZ_PARAM_ERROR if one of the parameters is invalid. */\n/*   MZ_BUF_ERROR if no forward progress is possible because the input and/or output buffers are empty. (Fill up the input buffer or free up some output space and try again.) */\nint mz_deflate(mz_streamp pStream, int flush);\n\n/* mz_deflateEnd() deinitializes a compressor: */\n/* Return values: */\n/*  MZ_OK on success. */\n/*  MZ_STREAM_ERROR if the stream is bogus. */\nint mz_deflateEnd(mz_streamp pStream);\n\n/* mz_deflateBound() returns a (very) conservative upper bound on the amount of data that could be generated by deflate(), assuming flush is set to only MZ_NO_FLUSH or MZ_FINISH. */\nmz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len);\n\n/* Single-call compression functions mz_compress() and mz_compress2(): */\n/* Returns MZ_OK on success, or one of the error codes from mz_deflate() on failure. */\nint mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len);\nint mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level);\n\n/* mz_compressBound() returns a (very) conservative upper bound on the amount of data that could be generated by calling mz_compress(). */\nmz_ulong mz_compressBound(mz_ulong source_len);\n\n/* Initializes a decompressor. */\nint mz_inflateInit(mz_streamp pStream);\n\n/* mz_inflateInit2() is like mz_inflateInit() with an additional option that controls the window size and whether or not the stream has been wrapped with a zlib header/footer: */\n/* window_bits must be MZ_DEFAULT_WINDOW_BITS (to parse zlib header/footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate). */\nint mz_inflateInit2(mz_streamp pStream, int window_bits);\n\n/* Decompresses the input stream to the output, consuming only as much of the input as needed, and writing as much to the output as possible. */\n/* Parameters: */\n/*   pStream is the stream to read from and write to. You must initialize/update the next_in, avail_in, next_out, and avail_out members. */\n/*   flush may be MZ_NO_FLUSH, MZ_SYNC_FLUSH, or MZ_FINISH. */\n/*   On the first call, if flush is MZ_FINISH it's assumed the input and output buffers are both sized large enough to decompress the entire stream in a single call (this is slightly faster). */\n/*   MZ_FINISH implies that there are no more source bytes available beside what's already in the input buffer, and that the output buffer is large enough to hold the rest of the decompressed data. */\n/* Return values: */\n/*   MZ_OK on success. Either more input is needed but not available, and/or there's more output to be written but the output buffer is full. */\n/*   MZ_STREAM_END if all needed input has been consumed and all output bytes have been written. For zlib streams, the adler-32 of the decompressed data has also been verified. */\n/*   MZ_STREAM_ERROR if the stream is bogus. */\n/*   MZ_DATA_ERROR if the deflate stream is invalid. */\n/*   MZ_PARAM_ERROR if one of the parameters is invalid. */\n/*   MZ_BUF_ERROR if no forward progress is possible because the input buffer is empty but the inflater needs more input to continue, or if the output buffer is not large enough. Call mz_inflate() again */\n/*   with more input data, or with more room in the output buffer (except when using single call decompression, described above). */\nint mz_inflate(mz_streamp pStream, int flush);\n\n/* Deinitializes a decompressor. */\nint mz_inflateEnd(mz_streamp pStream);\n\n/* Single-call decompression. */\n/* Returns MZ_OK on success, or one of the error codes from mz_inflate() on failure. */\nint mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len);\n\n/* Returns a string description of the specified error code, or NULL if the error code is invalid. */\nconst char *mz_error(int err);\n\n/* Redefine zlib-compatible names to miniz equivalents, so miniz.c can be used as a drop-in replacement for the subset of zlib that miniz.c supports. */\n/* Define MINIZ_NO_ZLIB_COMPATIBLE_NAMES to disable zlib-compatibility if you use zlib in the same project. */\n#ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES\ntypedef unsigned char Byte;\ntypedef unsigned int uInt;\ntypedef mz_ulong uLong;\ntypedef Byte Bytef;\ntypedef uInt uIntf;\ntypedef char charf;\ntypedef int intf;\ntypedef void *voidpf;\ntypedef uLong uLongf;\ntypedef void *voidp;\ntypedef void *const voidpc;\n#define Z_NULL 0\n#define Z_NO_FLUSH MZ_NO_FLUSH\n#define Z_PARTIAL_FLUSH MZ_PARTIAL_FLUSH\n#define Z_SYNC_FLUSH MZ_SYNC_FLUSH\n#define Z_FULL_FLUSH MZ_FULL_FLUSH\n#define Z_FINISH MZ_FINISH\n#define Z_BLOCK MZ_BLOCK\n#define Z_OK MZ_OK\n#define Z_STREAM_END MZ_STREAM_END\n#define Z_NEED_DICT MZ_NEED_DICT\n#define Z_ERRNO MZ_ERRNO\n#define Z_STREAM_ERROR MZ_STREAM_ERROR\n#define Z_DATA_ERROR MZ_DATA_ERROR\n#define Z_MEM_ERROR MZ_MEM_ERROR\n#define Z_BUF_ERROR MZ_BUF_ERROR\n#define Z_VERSION_ERROR MZ_VERSION_ERROR\n#define Z_PARAM_ERROR MZ_PARAM_ERROR\n#define Z_NO_COMPRESSION MZ_NO_COMPRESSION\n#define Z_BEST_SPEED MZ_BEST_SPEED\n#define Z_BEST_COMPRESSION MZ_BEST_COMPRESSION\n#define Z_DEFAULT_COMPRESSION MZ_DEFAULT_COMPRESSION\n#define Z_DEFAULT_STRATEGY MZ_DEFAULT_STRATEGY\n#define Z_FILTERED MZ_FILTERED\n#define Z_HUFFMAN_ONLY MZ_HUFFMAN_ONLY\n#define Z_RLE MZ_RLE\n#define Z_FIXED MZ_FIXED\n#define Z_DEFLATED MZ_DEFLATED\n#define Z_DEFAULT_WINDOW_BITS MZ_DEFAULT_WINDOW_BITS\n#define alloc_func mz_alloc_func\n#define free_func mz_free_func\n#define internal_state mz_internal_state\n#define z_stream mz_stream\n#define deflateInit mz_deflateInit\n#define deflateInit2 mz_deflateInit2\n#define deflateReset mz_deflateReset\n#define deflate mz_deflate\n#define deflateEnd mz_deflateEnd\n#define deflateBound mz_deflateBound\n#define compress mz_compress\n#define compress2 mz_compress2\n#define compressBound mz_compressBound\n#define inflateInit mz_inflateInit\n#define inflateInit2 mz_inflateInit2\n#define inflate mz_inflate\n#define inflateEnd mz_inflateEnd\n#define uncompress mz_uncompress\n#define crc32 mz_crc32\n#define adler32 mz_adler32\n#define MAX_WBITS 15\n#define MAX_MEM_LEVEL 9\n#define zError mz_error\n#define ZLIB_VERSION MZ_VERSION\n#define ZLIB_VERNUM MZ_VERNUM\n#define ZLIB_VER_MAJOR MZ_VER_MAJOR\n#define ZLIB_VER_MINOR MZ_VER_MINOR\n#define ZLIB_VER_REVISION MZ_VER_REVISION\n#define ZLIB_VER_SUBREVISION MZ_VER_SUBREVISION\n#define zlibVersion mz_version\n#define zlib_version mz_version()\n#endif /* #ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES */\n\n#endif /* MINIZ_NO_ZLIB_APIS */\n\n#ifdef __cplusplus\n}\n#endif\n#pragma once\n#include <assert.h>\n#include <stdint.h>\n#include <stdlib.h>\n#include <string.h>\n\n/* ------------------- Types and macros */\ntypedef unsigned char mz_uint8;\ntypedef signed short mz_int16;\ntypedef unsigned short mz_uint16;\ntypedef unsigned int mz_uint32;\ntypedef unsigned int mz_uint;\ntypedef int64_t mz_int64;\ntypedef uint64_t mz_uint64;\ntypedef int mz_bool;\n\n#define MZ_FALSE (0)\n#define MZ_TRUE (1)\n\n/* Works around MSVC's spammy \"warning C4127: conditional expression is constant\" message. */\n#ifdef _MSC_VER\n#define MZ_MACRO_END while (0, 0)\n#else\n#define MZ_MACRO_END while (0)\n#endif\n\n#ifdef MINIZ_NO_STDIO\n#define MZ_FILE void *\n#else\n#include <stdio.h>\n#define MZ_FILE FILE\n#endif /* #ifdef MINIZ_NO_STDIO */\n\n#ifdef MINIZ_NO_TIME\ntypedef struct mz_dummy_time_t_tag\n{\n    int m_dummy;\n} mz_dummy_time_t;\n#define MZ_TIME_T mz_dummy_time_t\n#else\n#define MZ_TIME_T time_t\n#endif\n\n#define MZ_ASSERT(x) assert(x)\n\n#ifdef MINIZ_NO_MALLOC\n#define MZ_MALLOC(x) NULL\n#define MZ_FREE(x) (void)x, ((void)0)\n#define MZ_REALLOC(p, x) NULL\n#else\n#define MZ_MALLOC(x) malloc(x)\n#define MZ_FREE(x) free(x)\n#define MZ_REALLOC(p, x) realloc(p, x)\n#endif\n\n#define MZ_MAX(a, b) (((a) > (b)) ? (a) : (b))\n#define MZ_MIN(a, b) (((a) < (b)) ? (a) : (b))\n#define MZ_CLEAR_OBJ(obj) memset(&(obj), 0, sizeof(obj))\n\n#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN\n#define MZ_READ_LE16(p) *((const mz_uint16 *)(p))\n#define MZ_READ_LE32(p) *((const mz_uint32 *)(p))\n#else\n#define MZ_READ_LE16(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U))\n#define MZ_READ_LE32(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U) | ((mz_uint32)(((const mz_uint8 *)(p))[2]) << 16U) | ((mz_uint32)(((const mz_uint8 *)(p))[3]) << 24U))\n#endif\n\n#define MZ_READ_LE64(p) (((mz_uint64)MZ_READ_LE32(p)) | (((mz_uint64)MZ_READ_LE32((const mz_uint8 *)(p) + sizeof(mz_uint32))) << 32U))\n\n#ifdef _MSC_VER\n#define MZ_FORCEINLINE __forceinline\n#elif defined(__GNUC__)\n#define MZ_FORCEINLINE __inline__ __attribute__((__always_inline__))\n#else\n#define MZ_FORCEINLINE inline\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nextern void *miniz_def_alloc_func(void *opaque, size_t items, size_t size);\nextern void miniz_def_free_func(void *opaque, void *address);\nextern void *miniz_def_realloc_func(void *opaque, void *address, size_t items, size_t size);\n\n#define MZ_UINT16_MAX (0xFFFFU)\n#define MZ_UINT32_MAX (0xFFFFFFFFU)\n\n#ifdef __cplusplus\n}\n#endif\n#pragma once\n\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n/* ------------------- Low-level Compression API Definitions */\n\n/* Set TDEFL_LESS_MEMORY to 1 to use less memory (compression will be slightly slower, and raw/dynamic blocks will be output more frequently). */\n#define TDEFL_LESS_MEMORY 0\n\n/* tdefl_init() compression flags logically OR'd together (low 12 bits contain the max. number of probes per dictionary search): */\n/* TDEFL_DEFAULT_MAX_PROBES: The compressor defaults to 128 dictionary probes per dictionary search. 0=Huffman only, 1=Huffman+LZ (fastest/crap compression), 4095=Huffman+LZ (slowest/best compression). */\nenum\n{\n    TDEFL_HUFFMAN_ONLY = 0,\n    TDEFL_DEFAULT_MAX_PROBES = 128,\n    TDEFL_MAX_PROBES_MASK = 0xFFF\n};\n\n/* TDEFL_WRITE_ZLIB_HEADER: If set, the compressor outputs a zlib header before the deflate data, and the Adler-32 of the source data at the end. Otherwise, you'll get raw deflate data. */\n/* TDEFL_COMPUTE_ADLER32: Always compute the adler-32 of the input data (even when not writing zlib headers). */\n/* TDEFL_GREEDY_PARSING_FLAG: Set to use faster greedy parsing, instead of more efficient lazy parsing. */\n/* TDEFL_NONDETERMINISTIC_PARSING_FLAG: Enable to decrease the compressor's initialization time to the minimum, but the output may vary from run to run given the same input (depending on the contents of memory). */\n/* TDEFL_RLE_MATCHES: Only look for RLE matches (matches with a distance of 1) */\n/* TDEFL_FILTER_MATCHES: Discards matches <= 5 chars if enabled. */\n/* TDEFL_FORCE_ALL_STATIC_BLOCKS: Disable usage of optimized Huffman tables. */\n/* TDEFL_FORCE_ALL_RAW_BLOCKS: Only use raw (uncompressed) deflate blocks. */\n/* The low 12 bits are reserved to control the max # of hash probes per dictionary lookup (see TDEFL_MAX_PROBES_MASK). */\nenum\n{\n    TDEFL_WRITE_ZLIB_HEADER = 0x01000,\n    TDEFL_COMPUTE_ADLER32 = 0x02000,\n    TDEFL_GREEDY_PARSING_FLAG = 0x04000,\n    TDEFL_NONDETERMINISTIC_PARSING_FLAG = 0x08000,\n    TDEFL_RLE_MATCHES = 0x10000,\n    TDEFL_FILTER_MATCHES = 0x20000,\n    TDEFL_FORCE_ALL_STATIC_BLOCKS = 0x40000,\n    TDEFL_FORCE_ALL_RAW_BLOCKS = 0x80000\n};\n\n/* High level compression functions: */\n/* tdefl_compress_mem_to_heap() compresses a block in memory to a heap block allocated via malloc(). */\n/* On entry: */\n/*  pSrc_buf, src_buf_len: Pointer and size of source block to compress. */\n/*  flags: The max match finder probes (default is 128) logically OR'd against the above flags. Higher probes are slower but improve compression. */\n/* On return: */\n/*  Function returns a pointer to the compressed data, or NULL on failure. */\n/*  *pOut_len will be set to the compressed data's size, which could be larger than src_buf_len on uncompressible data. */\n/*  The caller must free() the returned block when it's no longer needed. */\nvoid *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags);\n\n/* tdefl_compress_mem_to_mem() compresses a block in memory to another block in memory. */\n/* Returns 0 on failure. */\nsize_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags);\n\n/* Compresses an image to a compressed PNG file in memory. */\n/* On entry: */\n/*  pImage, w, h, and num_chans describe the image to compress. num_chans may be 1, 2, 3, or 4. */\n/*  The image pitch in bytes per scanline will be w*num_chans. The leftmost pixel on the top scanline is stored first in memory. */\n/*  level may range from [0,10], use MZ_NO_COMPRESSION, MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc. or a decent default is MZ_DEFAULT_LEVEL */\n/*  If flip is true, the image will be flipped on the Y axis (useful for OpenGL apps). */\n/* On return: */\n/*  Function returns a pointer to the compressed data, or NULL on failure. */\n/*  *pLen_out will be set to the size of the PNG image file. */\n/*  The caller must mz_free() the returned heap block (which will typically be larger than *pLen_out) when it's no longer needed. */\nvoid *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, size_t *pLen_out, mz_uint level, mz_bool flip);\nvoid *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out);\n\n/* Output stream interface. The compressor uses this interface to write compressed data. It'll typically be called TDEFL_OUT_BUF_SIZE at a time. */\ntypedef mz_bool (*tdefl_put_buf_func_ptr)(const void *pBuf, int len, void *pUser);\n\n/* tdefl_compress_mem_to_output() compresses a block to an output stream. The above helpers use this function internally. */\nmz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags);\n\nenum\n{\n    TDEFL_MAX_HUFF_TABLES = 3,\n    TDEFL_MAX_HUFF_SYMBOLS_0 = 288,\n    TDEFL_MAX_HUFF_SYMBOLS_1 = 32,\n    TDEFL_MAX_HUFF_SYMBOLS_2 = 19,\n    TDEFL_LZ_DICT_SIZE = 32768,\n    TDEFL_LZ_DICT_SIZE_MASK = TDEFL_LZ_DICT_SIZE - 1,\n    TDEFL_MIN_MATCH_LEN = 3,\n    TDEFL_MAX_MATCH_LEN = 258\n};\n\n/* TDEFL_OUT_BUF_SIZE MUST be large enough to hold a single entire compressed output block (using static/fixed Huffman codes). */\n#if TDEFL_LESS_MEMORY\nenum\n{\n    TDEFL_LZ_CODE_BUF_SIZE = 24 * 1024,\n    TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13) / 10,\n    TDEFL_MAX_HUFF_SYMBOLS = 288,\n    TDEFL_LZ_HASH_BITS = 12,\n    TDEFL_LEVEL1_HASH_SIZE_MASK = 4095,\n    TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3,\n    TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS\n};\n#else\nenum\n{\n    TDEFL_LZ_CODE_BUF_SIZE = 64 * 1024,\n    TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13) / 10,\n    TDEFL_MAX_HUFF_SYMBOLS = 288,\n    TDEFL_LZ_HASH_BITS = 15,\n    TDEFL_LEVEL1_HASH_SIZE_MASK = 4095,\n    TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3,\n    TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS\n};\n#endif\n\n/* The low-level tdefl functions below may be used directly if the above helper functions aren't flexible enough. The low-level functions don't make any heap allocations, unlike the above helper functions. */\ntypedef enum {\n    TDEFL_STATUS_BAD_PARAM = -2,\n    TDEFL_STATUS_PUT_BUF_FAILED = -1,\n    TDEFL_STATUS_OKAY = 0,\n    TDEFL_STATUS_DONE = 1\n} tdefl_status;\n\n/* Must map to MZ_NO_FLUSH, MZ_SYNC_FLUSH, etc. enums */\ntypedef enum {\n    TDEFL_NO_FLUSH = 0,\n    TDEFL_SYNC_FLUSH = 2,\n    TDEFL_FULL_FLUSH = 3,\n    TDEFL_FINISH = 4\n} tdefl_flush;\n\n/* tdefl's compression state structure. */\ntypedef struct\n{\n    tdefl_put_buf_func_ptr m_pPut_buf_func;\n    void *m_pPut_buf_user;\n    mz_uint m_flags, m_max_probes[2];\n    int m_greedy_parsing;\n    mz_uint m_adler32, m_lookahead_pos, m_lookahead_size, m_dict_size;\n    mz_uint8 *m_pLZ_code_buf, *m_pLZ_flags, *m_pOutput_buf, *m_pOutput_buf_end;\n    mz_uint m_num_flags_left, m_total_lz_bytes, m_lz_code_buf_dict_pos, m_bits_in, m_bit_buffer;\n    mz_uint m_saved_match_dist, m_saved_match_len, m_saved_lit, m_output_flush_ofs, m_output_flush_remaining, m_finished, m_block_index, m_wants_to_finish;\n    tdefl_status m_prev_return_status;\n    const void *m_pIn_buf;\n    void *m_pOut_buf;\n    size_t *m_pIn_buf_size, *m_pOut_buf_size;\n    tdefl_flush m_flush;\n    const mz_uint8 *m_pSrc;\n    size_t m_src_buf_left, m_out_buf_ofs;\n    mz_uint8 m_dict[TDEFL_LZ_DICT_SIZE + TDEFL_MAX_MATCH_LEN - 1];\n    mz_uint16 m_huff_count[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];\n    mz_uint16 m_huff_codes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];\n    mz_uint8 m_huff_code_sizes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];\n    mz_uint8 m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE];\n    mz_uint16 m_next[TDEFL_LZ_DICT_SIZE];\n    mz_uint16 m_hash[TDEFL_LZ_HASH_SIZE];\n    mz_uint8 m_output_buf[TDEFL_OUT_BUF_SIZE];\n} tdefl_compressor;\n\n/* Initializes the compressor. */\n/* There is no corresponding deinit() function because the tdefl API's do not dynamically allocate memory. */\n/* pBut_buf_func: If NULL, output data will be supplied to the specified callback. In this case, the user should call the tdefl_compress_buffer() API for compression. */\n/* If pBut_buf_func is NULL the user should always call the tdefl_compress() API. */\n/* flags: See the above enums (TDEFL_HUFFMAN_ONLY, TDEFL_WRITE_ZLIB_HEADER, etc.) */\ntdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags);\n\n/* Compresses a block of data, consuming as much of the specified input buffer as possible, and writing as much compressed data to the specified output buffer as possible. */\ntdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush);\n\n/* tdefl_compress_buffer() is only usable when the tdefl_init() is called with a non-NULL tdefl_put_buf_func_ptr. */\n/* tdefl_compress_buffer() always consumes the entire input buffer. */\ntdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush);\n\ntdefl_status tdefl_get_prev_return_status(tdefl_compressor *d);\nmz_uint32 tdefl_get_adler32(tdefl_compressor *d);\n\n/* Create tdefl_compress() flags given zlib-style compression parameters. */\n/* level may range from [0,10] (where 10 is absolute max compression, but may be much slower on some files) */\n/* window_bits may be -15 (raw deflate) or 15 (zlib) */\n/* strategy may be either MZ_DEFAULT_STRATEGY, MZ_FILTERED, MZ_HUFFMAN_ONLY, MZ_RLE, or MZ_FIXED */\nmz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy);\n\n/* Allocate the tdefl_compressor structure in C so that */\n/* non-C language bindings to tdefl_ API don't need to worry about */\n/* structure size and allocation mechanism. */\ntdefl_compressor *tdefl_compressor_alloc();\nvoid tdefl_compressor_free(tdefl_compressor *pComp);\n\n#ifdef __cplusplus\n}\n#endif\n#pragma once\n\n/* ------------------- Low-level Decompression API Definitions */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n/* Decompression flags used by tinfl_decompress(). */\n/* TINFL_FLAG_PARSE_ZLIB_HEADER: If set, the input has a valid zlib header and ends with an adler32 checksum (it's a valid zlib stream). Otherwise, the input is a raw deflate stream. */\n/* TINFL_FLAG_HAS_MORE_INPUT: If set, there are more input bytes available beyond the end of the supplied input buffer. If clear, the input buffer contains all remaining input. */\n/* TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF: If set, the output buffer is large enough to hold the entire decompressed stream. If clear, the output buffer is at least the size of the dictionary (typically 32KB). */\n/* TINFL_FLAG_COMPUTE_ADLER32: Force adler-32 checksum computation of the decompressed bytes. */\nenum\n{\n    TINFL_FLAG_PARSE_ZLIB_HEADER = 1,\n    TINFL_FLAG_HAS_MORE_INPUT = 2,\n    TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF = 4,\n    TINFL_FLAG_COMPUTE_ADLER32 = 8\n};\n\n/* High level decompression functions: */\n/* tinfl_decompress_mem_to_heap() decompresses a block in memory to a heap block allocated via malloc(). */\n/* On entry: */\n/*  pSrc_buf, src_buf_len: Pointer and size of the Deflate or zlib source data to decompress. */\n/* On return: */\n/*  Function returns a pointer to the decompressed data, or NULL on failure. */\n/*  *pOut_len will be set to the decompressed data's size, which could be larger than src_buf_len on uncompressible data. */\n/*  The caller must call mz_free() on the returned block when it's no longer needed. */\nvoid *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags);\n\n/* tinfl_decompress_mem_to_mem() decompresses a block in memory to another block in memory. */\n/* Returns TINFL_DECOMPRESS_MEM_TO_MEM_FAILED on failure, or the number of bytes written on success. */\n#define TINFL_DECOMPRESS_MEM_TO_MEM_FAILED ((size_t)(-1))\nsize_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags);\n\n/* tinfl_decompress_mem_to_callback() decompresses a block in memory to an internal 32KB buffer, and a user provided callback function will be called to flush the buffer. */\n/* Returns 1 on success or 0 on failure. */\ntypedef int (*tinfl_put_buf_func_ptr)(const void *pBuf, int len, void *pUser);\nint tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags);\n\nstruct tinfl_decompressor_tag;\ntypedef struct tinfl_decompressor_tag tinfl_decompressor;\n\n/* Allocate the tinfl_decompressor structure in C so that */\n/* non-C language bindings to tinfl_ API don't need to worry about */\n/* structure size and allocation mechanism. */\n\ntinfl_decompressor *tinfl_decompressor_alloc();\nvoid tinfl_decompressor_free(tinfl_decompressor *pDecomp);\n\n/* Max size of LZ dictionary. */\n#define TINFL_LZ_DICT_SIZE 32768\n\n/* Return status. */\ntypedef enum {\n    /* This flags indicates the inflator needs 1 or more input bytes to make forward progress, but the caller is indicating that no more are available. The compressed data */\n    /* is probably corrupted. If you call the inflator again with more bytes it'll try to continue processing the input but this is a BAD sign (either the data is corrupted or you called it incorrectly). */\n    /* If you call it again with no input you'll just get TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS again. */\n    TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS = -4,\n\n    /* This flag indicates that one or more of the input parameters was obviously bogus. (You can try calling it again, but if you get this error the calling code is wrong.) */\n    TINFL_STATUS_BAD_PARAM = -3,\n\n    /* This flags indicate the inflator is finished but the adler32 check of the uncompressed data didn't match. If you call it again it'll return TINFL_STATUS_DONE. */\n    TINFL_STATUS_ADLER32_MISMATCH = -2,\n\n    /* This flags indicate the inflator has somehow failed (bad code, corrupted input, etc.). If you call it again without resetting via tinfl_init() it it'll just keep on returning the same status failure code. */\n    TINFL_STATUS_FAILED = -1,\n\n    /* Any status code less than TINFL_STATUS_DONE must indicate a failure. */\n\n    /* This flag indicates the inflator has returned every byte of uncompressed data that it can, has consumed every byte that it needed, has successfully reached the end of the deflate stream, and */\n    /* if zlib headers and adler32 checking enabled that it has successfully checked the uncompressed data's adler32. If you call it again you'll just get TINFL_STATUS_DONE over and over again. */\n    TINFL_STATUS_DONE = 0,\n\n    /* This flag indicates the inflator MUST have more input data (even 1 byte) before it can make any more forward progress, or you need to clear the TINFL_FLAG_HAS_MORE_INPUT */\n    /* flag on the next call if you don't have any more source data. If the source data was somehow corrupted it's also possible (but unlikely) for the inflator to keep on demanding input to */\n    /* proceed, so be sure to properly set the TINFL_FLAG_HAS_MORE_INPUT flag. */\n    TINFL_STATUS_NEEDS_MORE_INPUT = 1,\n\n    /* This flag indicates the inflator definitely has 1 or more bytes of uncompressed data available, but it cannot write this data into the output buffer. */\n    /* Note if the source compressed data was corrupted it's possible for the inflator to return a lot of uncompressed data to the caller. I've been assuming you know how much uncompressed data to expect */\n    /* (either exact or worst case) and will stop calling the inflator and fail after receiving too much. In pure streaming scenarios where you have no idea how many bytes to expect this may not be possible */\n    /* so I may need to add some code to address this. */\n    TINFL_STATUS_HAS_MORE_OUTPUT = 2\n} tinfl_status;\n\n/* Initializes the decompressor to its initial state. */\n#define tinfl_init(r)     \\\n    do                    \\\n    {                     \\\n        (r)->m_state = 0; \\\n    }                     \\\n    MZ_MACRO_END\n#define tinfl_get_adler32(r) (r)->m_check_adler32\n\n/* Main low-level decompressor coroutine function. This is the only function actually needed for decompression. All the other functions are just high-level helpers for improved usability. */\n/* This is a universal API, i.e. it can be used as a building block to build any desired higher level decompression API. In the limit case, it can be called once per every byte input or output. */\ntinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags);\n\n/* Internal/private bits follow. */\nenum\n{\n    TINFL_MAX_HUFF_TABLES = 3,\n    TINFL_MAX_HUFF_SYMBOLS_0 = 288,\n    TINFL_MAX_HUFF_SYMBOLS_1 = 32,\n    TINFL_MAX_HUFF_SYMBOLS_2 = 19,\n    TINFL_FAST_LOOKUP_BITS = 10,\n    TINFL_FAST_LOOKUP_SIZE = 1 << TINFL_FAST_LOOKUP_BITS\n};\n\ntypedef struct\n{\n    mz_uint8 m_code_size[TINFL_MAX_HUFF_SYMBOLS_0];\n    mz_int16 m_look_up[TINFL_FAST_LOOKUP_SIZE], m_tree[TINFL_MAX_HUFF_SYMBOLS_0 * 2];\n} tinfl_huff_table;\n\n#if MINIZ_HAS_64BIT_REGISTERS\n#define TINFL_USE_64BIT_BITBUF 1\n#else\n#define TINFL_USE_64BIT_BITBUF 0\n#endif\n\n#if TINFL_USE_64BIT_BITBUF\ntypedef mz_uint64 tinfl_bit_buf_t;\n#define TINFL_BITBUF_SIZE (64)\n#else\ntypedef mz_uint32 tinfl_bit_buf_t;\n#define TINFL_BITBUF_SIZE (32)\n#endif\n\nstruct tinfl_decompressor_tag\n{\n    mz_uint32 m_state, m_num_bits, m_zhdr0, m_zhdr1, m_z_adler32, m_final, m_type, m_check_adler32, m_dist, m_counter, m_num_extra, m_table_sizes[TINFL_MAX_HUFF_TABLES];\n    tinfl_bit_buf_t m_bit_buf;\n    size_t m_dist_from_out_buf_start;\n    tinfl_huff_table m_tables[TINFL_MAX_HUFF_TABLES];\n    mz_uint8 m_raw_header[4], m_len_codes[TINFL_MAX_HUFF_SYMBOLS_0 + TINFL_MAX_HUFF_SYMBOLS_1 + 137];\n};\n\n#ifdef __cplusplus\n}\n#endif\n\n#pragma once\n\n\n/* ------------------- ZIP archive reading/writing */\n\n#ifndef MINIZ_NO_ARCHIVE_APIS\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nenum\n{\n    /* Note: These enums can be reduced as needed to save memory or stack space - they are pretty conservative. */\n    MZ_ZIP_MAX_IO_BUF_SIZE = 64 * 1024,\n    MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE = 512,\n    MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE = 512\n};\n\ntypedef struct\n{\n    /* Central directory file index. */\n    mz_uint32 m_file_index;\n\n    /* Byte offset of this entry in the archive's central directory. Note we currently only support up to UINT_MAX or less bytes in the central dir. */\n    mz_uint64 m_central_dir_ofs;\n\n    /* These fields are copied directly from the zip's central dir. */\n    mz_uint16 m_version_made_by;\n    mz_uint16 m_version_needed;\n    mz_uint16 m_bit_flag;\n    mz_uint16 m_method;\n\n#ifndef MINIZ_NO_TIME\n    MZ_TIME_T m_time;\n#endif\n\n    /* CRC-32 of uncompressed data. */\n    mz_uint32 m_crc32;\n\n    /* File's compressed size. */\n    mz_uint64 m_comp_size;\n\n    /* File's uncompressed size. Note, I've seen some old archives where directory entries had 512 bytes for their uncompressed sizes, but when you try to unpack them you actually get 0 bytes. */\n    mz_uint64 m_uncomp_size;\n\n    /* Zip internal and external file attributes. */\n    mz_uint16 m_internal_attr;\n    mz_uint32 m_external_attr;\n\n    /* Entry's local header file offset in bytes. */\n    mz_uint64 m_local_header_ofs;\n\n    /* Size of comment in bytes. */\n    mz_uint32 m_comment_size;\n\n    /* MZ_TRUE if the entry appears to be a directory. */\n    mz_bool m_is_directory;\n\n    /* MZ_TRUE if the entry uses encryption/strong encryption (which miniz_zip doesn't support) */\n    mz_bool m_is_encrypted;\n\n    /* MZ_TRUE if the file is not encrypted, a patch file, and if it uses a compression method we support. */\n    mz_bool m_is_supported;\n\n    /* Filename. If string ends in '/' it's a subdirectory entry. */\n    /* Guaranteed to be zero terminated, may be truncated to fit. */\n    char m_filename[MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE];\n\n    /* Comment field. */\n    /* Guaranteed to be zero terminated, may be truncated to fit. */\n    char m_comment[MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE];\n\n} mz_zip_archive_file_stat;\n\ntypedef size_t (*mz_file_read_func)(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n);\ntypedef size_t (*mz_file_write_func)(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n);\ntypedef mz_bool (*mz_file_needs_keepalive)(void *pOpaque);\n\nstruct mz_zip_internal_state_tag;\ntypedef struct mz_zip_internal_state_tag mz_zip_internal_state;\n\ntypedef enum {\n    MZ_ZIP_MODE_INVALID = 0,\n    MZ_ZIP_MODE_READING = 1,\n    MZ_ZIP_MODE_WRITING = 2,\n    MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED = 3\n} mz_zip_mode;\n\ntypedef enum {\n    MZ_ZIP_FLAG_CASE_SENSITIVE = 0x0100,\n    MZ_ZIP_FLAG_IGNORE_PATH = 0x0200,\n    MZ_ZIP_FLAG_COMPRESSED_DATA = 0x0400,\n    MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY = 0x0800,\n    MZ_ZIP_FLAG_VALIDATE_LOCATE_FILE_FLAG = 0x1000, /* if enabled, mz_zip_reader_locate_file() will be called on each file as its validated to ensure the func finds the file in the central dir (intended for testing) */\n    MZ_ZIP_FLAG_VALIDATE_HEADERS_ONLY = 0x2000,     /* validate the local headers, but don't decompress the entire file and check the crc32 */\n    MZ_ZIP_FLAG_WRITE_ZIP64 = 0x4000,               /* always use the zip64 file format, instead of the original zip file format with automatic switch to zip64. Use as flags parameter with mz_zip_writer_init*_v2 */\n    MZ_ZIP_FLAG_WRITE_ALLOW_READING = 0x8000,\n    MZ_ZIP_FLAG_ASCII_FILENAME = 0x10000\n} mz_zip_flags;\n\ntypedef enum {\n    MZ_ZIP_TYPE_INVALID = 0,\n    MZ_ZIP_TYPE_USER,\n    MZ_ZIP_TYPE_MEMORY,\n    MZ_ZIP_TYPE_HEAP,\n    MZ_ZIP_TYPE_FILE,\n    MZ_ZIP_TYPE_CFILE,\n    MZ_ZIP_TOTAL_TYPES\n} mz_zip_type;\n\n/* miniz error codes. Be sure to update mz_zip_get_error_string() if you add or modify this enum. */\ntypedef enum {\n    MZ_ZIP_NO_ERROR = 0,\n    MZ_ZIP_UNDEFINED_ERROR,\n    MZ_ZIP_TOO_MANY_FILES,\n    MZ_ZIP_FILE_TOO_LARGE,\n    MZ_ZIP_UNSUPPORTED_METHOD,\n    MZ_ZIP_UNSUPPORTED_ENCRYPTION,\n    MZ_ZIP_UNSUPPORTED_FEATURE,\n    MZ_ZIP_FAILED_FINDING_CENTRAL_DIR,\n    MZ_ZIP_NOT_AN_ARCHIVE,\n    MZ_ZIP_INVALID_HEADER_OR_CORRUPTED,\n    MZ_ZIP_UNSUPPORTED_MULTIDISK,\n    MZ_ZIP_DECOMPRESSION_FAILED,\n    MZ_ZIP_COMPRESSION_FAILED,\n    MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE,\n    MZ_ZIP_CRC_CHECK_FAILED,\n    MZ_ZIP_UNSUPPORTED_CDIR_SIZE,\n    MZ_ZIP_ALLOC_FAILED,\n    MZ_ZIP_FILE_OPEN_FAILED,\n    MZ_ZIP_FILE_CREATE_FAILED,\n    MZ_ZIP_FILE_WRITE_FAILED,\n    MZ_ZIP_FILE_READ_FAILED,\n    MZ_ZIP_FILE_CLOSE_FAILED,\n    MZ_ZIP_FILE_SEEK_FAILED,\n    MZ_ZIP_FILE_STAT_FAILED,\n    MZ_ZIP_INVALID_PARAMETER,\n    MZ_ZIP_INVALID_FILENAME,\n    MZ_ZIP_BUF_TOO_SMALL,\n    MZ_ZIP_INTERNAL_ERROR,\n    MZ_ZIP_FILE_NOT_FOUND,\n    MZ_ZIP_ARCHIVE_TOO_LARGE,\n    MZ_ZIP_VALIDATION_FAILED,\n    MZ_ZIP_WRITE_CALLBACK_FAILED,\n    MZ_ZIP_TOTAL_ERRORS\n} mz_zip_error;\n\ntypedef struct\n{\n    mz_uint64 m_archive_size;\n    mz_uint64 m_central_directory_file_ofs;\n\n    /* We only support up to UINT32_MAX files in zip64 mode. */\n    mz_uint32 m_total_files;\n    mz_zip_mode m_zip_mode;\n    mz_zip_type m_zip_type;\n    mz_zip_error m_last_error;\n\n    mz_uint64 m_file_offset_alignment;\n\n    mz_alloc_func m_pAlloc;\n    mz_free_func m_pFree;\n    mz_realloc_func m_pRealloc;\n    void *m_pAlloc_opaque;\n\n    mz_file_read_func m_pRead;\n    mz_file_write_func m_pWrite;\n    mz_file_needs_keepalive m_pNeeds_keepalive;\n    void *m_pIO_opaque;\n\n    mz_zip_internal_state *m_pState;\n\n} mz_zip_archive;\n\ntypedef struct\n{\n    mz_zip_archive *pZip;\n    mz_uint flags;\n\n    int status;\n#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS\n    mz_uint file_crc32;\n#endif\n    mz_uint64 read_buf_size, read_buf_ofs, read_buf_avail, comp_remaining, out_buf_ofs, cur_file_ofs;\n    mz_zip_archive_file_stat file_stat;\n    void *pRead_buf;\n    void *pWrite_buf;\n\n    size_t out_blk_remain;\n\n    tinfl_decompressor inflator;\n\n} mz_zip_reader_extract_iter_state;\n\n/* -------- ZIP reading */\n\n/* Inits a ZIP archive reader. */\n/* These functions read and validate the archive's central directory. */\nmz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint flags);\n\nmz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint flags);\n\n#ifndef MINIZ_NO_STDIO\n/* Read a archive from a disk file. */\n/* file_start_ofs is the file offset where the archive actually begins, or 0. */\n/* actual_archive_size is the true total size of the archive, which may be smaller than the file's actual size on disk. If zero the entire file is treated as the archive. */\nmz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags);\nmz_bool mz_zip_reader_init_file_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint flags, mz_uint64 file_start_ofs, mz_uint64 archive_size);\n\n/* Read an archive from an already opened FILE, beginning at the current file position. */\n/* The archive is assumed to be archive_size bytes long. If archive_size is < 0, then the entire rest of the file is assumed to contain the archive. */\n/* The FILE will NOT be closed when mz_zip_reader_end() is called. */\nmz_bool mz_zip_reader_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, mz_uint64 archive_size, mz_uint flags);\n#endif\n\n/* Ends archive reading, freeing all allocations, and closing the input archive file if mz_zip_reader_init_file() was used. */\nmz_bool mz_zip_reader_end(mz_zip_archive *pZip);\n\n/* -------- ZIP reading or writing */\n\n/* Clears a mz_zip_archive struct to all zeros. */\n/* Important: This must be done before passing the struct to any mz_zip functions. */\nvoid mz_zip_zero_struct(mz_zip_archive *pZip);\n\nmz_zip_mode mz_zip_get_mode(mz_zip_archive *pZip);\nmz_zip_type mz_zip_get_type(mz_zip_archive *pZip);\n\n/* Returns the total number of files in the archive. */\nmz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip);\n\nmz_uint64 mz_zip_get_archive_size(mz_zip_archive *pZip);\nmz_uint64 mz_zip_get_archive_file_start_offset(mz_zip_archive *pZip);\nMZ_FILE *mz_zip_get_cfile(mz_zip_archive *pZip);\n\n/* Reads n bytes of raw archive data, starting at file offset file_ofs, to pBuf. */\nsize_t mz_zip_read_archive_data(mz_zip_archive *pZip, mz_uint64 file_ofs, void *pBuf, size_t n);\n\n/* All mz_zip funcs set the m_last_error field in the mz_zip_archive struct. These functions retrieve/manipulate this field. */\n/* Note that the m_last_error functionality is not thread safe. */\nmz_zip_error mz_zip_set_last_error(mz_zip_archive *pZip, mz_zip_error err_num);\nmz_zip_error mz_zip_peek_last_error(mz_zip_archive *pZip);\nmz_zip_error mz_zip_clear_last_error(mz_zip_archive *pZip);\nmz_zip_error mz_zip_get_last_error(mz_zip_archive *pZip);\nconst char *mz_zip_get_error_string(mz_zip_error mz_err);\n\n/* MZ_TRUE if the archive file entry is a directory entry. */\nmz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index);\n\n/* MZ_TRUE if the file is encrypted/strong encrypted. */\nmz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index);\n\n/* MZ_TRUE if the compression method is supported, and the file is not encrypted, and the file is not a compressed patch file. */\nmz_bool mz_zip_reader_is_file_supported(mz_zip_archive *pZip, mz_uint file_index);\n\n/* Retrieves the filename of an archive file entry. */\n/* Returns the number of bytes written to pFilename, or if filename_buf_size is 0 this function returns the number of bytes needed to fully store the filename. */\nmz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size);\n\n/* Attempts to locates a file in the archive's central directory. */\n/* Valid flags: MZ_ZIP_FLAG_CASE_SENSITIVE, MZ_ZIP_FLAG_IGNORE_PATH */\n/* Returns -1 if the file cannot be found. */\nint mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags);\nint mz_zip_reader_locate_file_v2(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags, mz_uint32 *file_index);\n\n/* Returns detailed information about an archive file entry. */\nmz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat);\n\n/* MZ_TRUE if the file is in zip64 format. */\n/* A file is considered zip64 if it contained a zip64 end of central directory marker, or if it contained any zip64 extended file information fields in the central directory. */\nmz_bool mz_zip_is_zip64(mz_zip_archive *pZip);\n\n/* Returns the total central directory size in bytes. */\n/* The current max supported size is <= MZ_UINT32_MAX. */\nsize_t mz_zip_get_central_dir_size(mz_zip_archive *pZip);\n\n/* Extracts a archive file to a memory buffer using no memory allocation. */\n/* There must be at least enough room on the stack to store the inflator's state (~34KB or so). */\nmz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size);\nmz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size);\n\n/* Extracts a archive file to a memory buffer. */\nmz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags);\nmz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags);\n\n/* Extracts a archive file to a dynamically allocated heap buffer. */\n/* The memory will be allocated via the mz_zip_archive's alloc/realloc functions. */\n/* Returns NULL and sets the last error on failure. */\nvoid *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags);\nvoid *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags);\n\n/* Extracts a archive file using a callback function to output the file's data. */\nmz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_index, mz_file_write_func pCallback, void *pOpaque, mz_uint flags);\nmz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags);\n\n/* Extract a file iteratively */\nmz_zip_reader_extract_iter_state* mz_zip_reader_extract_iter_new(mz_zip_archive *pZip, mz_uint file_index, mz_uint flags);\nmz_zip_reader_extract_iter_state* mz_zip_reader_extract_file_iter_new(mz_zip_archive *pZip, const char *pFilename, mz_uint flags);\nsize_t mz_zip_reader_extract_iter_read(mz_zip_reader_extract_iter_state* pState, void* pvBuf, size_t buf_size);\nmz_bool mz_zip_reader_extract_iter_free(mz_zip_reader_extract_iter_state* pState);\n\n#ifndef MINIZ_NO_STDIO\n/* Extracts a archive file to a disk file and sets its last accessed and modified times. */\n/* This function only extracts files, not archive directory records. */\nmz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags);\nmz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags);\n\n/* Extracts a archive file starting at the current position in the destination FILE stream. */\nmz_bool mz_zip_reader_extract_to_cfile(mz_zip_archive *pZip, mz_uint file_index, MZ_FILE *File, mz_uint flags);\nmz_bool mz_zip_reader_extract_file_to_cfile(mz_zip_archive *pZip, const char *pArchive_filename, MZ_FILE *pFile, mz_uint flags);\n#endif\n\n#if 0\n/* TODO */\n\ttypedef void *mz_zip_streaming_extract_state_ptr;\n\tmz_zip_streaming_extract_state_ptr mz_zip_streaming_extract_begin(mz_zip_archive *pZip, mz_uint file_index, mz_uint flags);\n\tuint64_t mz_zip_streaming_extract_get_size(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState);\n\tuint64_t mz_zip_streaming_extract_get_cur_ofs(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState);\n\tmz_bool mz_zip_streaming_extract_seek(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState, uint64_t new_ofs);\n\tsize_t mz_zip_streaming_extract_read(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState, void *pBuf, size_t buf_size);\n\tmz_bool mz_zip_streaming_extract_end(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState);\n#endif\n\n/* This function compares the archive's local headers, the optional local zip64 extended information block, and the optional descriptor following the compressed data vs. the data in the central directory. */\n/* It also validates that each file can be successfully uncompressed unless the MZ_ZIP_FLAG_VALIDATE_HEADERS_ONLY is specified. */\nmz_bool mz_zip_validate_file(mz_zip_archive *pZip, mz_uint file_index, mz_uint flags);\n\n/* Validates an entire archive by calling mz_zip_validate_file() on each file. */\nmz_bool mz_zip_validate_archive(mz_zip_archive *pZip, mz_uint flags);\n\n/* Misc utils/helpers, valid for ZIP reading or writing */\nmz_bool mz_zip_validate_mem_archive(const void *pMem, size_t size, mz_uint flags, mz_zip_error *pErr);\nmz_bool mz_zip_validate_file_archive(const char *pFilename, mz_uint flags, mz_zip_error *pErr);\n\n/* Universal end function - calls either mz_zip_reader_end() or mz_zip_writer_end(). */\nmz_bool mz_zip_end(mz_zip_archive *pZip);\n\n/* -------- ZIP writing */\n\n#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS\n\n/* Inits a ZIP archive writer. */\n/*Set pZip->m_pWrite (and pZip->m_pIO_opaque) before calling mz_zip_writer_init or mz_zip_writer_init_v2*/\n/*The output is streamable, i.e. file_ofs in mz_file_write_func always increases only by n*/\nmz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size);\nmz_bool mz_zip_writer_init_v2(mz_zip_archive *pZip, mz_uint64 existing_size, mz_uint flags);\n\nmz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size);\nmz_bool mz_zip_writer_init_heap_v2(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size, mz_uint flags);\n\n#ifndef MINIZ_NO_STDIO\nmz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning);\nmz_bool mz_zip_writer_init_file_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning, mz_uint flags);\nmz_bool mz_zip_writer_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, mz_uint flags);\n#endif\n\n/* Converts a ZIP archive reader object into a writer object, to allow efficient in-place file appends to occur on an existing archive. */\n/* For archives opened using mz_zip_reader_init_file, pFilename must be the archive's filename so it can be reopened for writing. If the file can't be reopened, mz_zip_reader_end() will be called. */\n/* For archives opened using mz_zip_reader_init_mem, the memory block must be growable using the realloc callback (which defaults to realloc unless you've overridden it). */\n/* Finally, for archives opened using mz_zip_reader_init, the mz_zip_archive's user provided m_pWrite function cannot be NULL. */\n/* Note: In-place archive modification is not recommended unless you know what you're doing, because if execution stops or something goes wrong before */\n/* the archive is finalized the file's central directory will be hosed. */\nmz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename);\nmz_bool mz_zip_writer_init_from_reader_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint flags);\n\n/* Adds the contents of a memory buffer to an archive. These functions record the current local time into the archive. */\n/* To add a directory entry, call this method with an archive name ending in a forwardslash with an empty buffer. */\n/* level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION. */\nmz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags);\n\n/* Like mz_zip_writer_add_mem(), except you can specify a file comment field, and optionally supply the function with already compressed data. */\n/* uncomp_size/uncomp_crc32 are only used if the MZ_ZIP_FLAG_COMPRESSED_DATA flag is specified. */\nmz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags,\n                                 mz_uint64 uncomp_size, mz_uint32 uncomp_crc32);\n\nmz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags,\n                                    mz_uint64 uncomp_size, mz_uint32 uncomp_crc32, MZ_TIME_T *last_modified, const char *user_extra_data_local, mz_uint user_extra_data_local_len,\n                                    const char *user_extra_data_central, mz_uint user_extra_data_central_len);\n\n#ifndef MINIZ_NO_STDIO\n/* Adds the contents of a disk file to an archive. This function also records the disk file's modified time into the archive. */\n/* level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION. */\nmz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags);\n\n/* Like mz_zip_writer_add_file(), except the file data is read from the specified FILE stream. */\nmz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name, MZ_FILE *pSrc_file, mz_uint64 size_to_add,\n                                const MZ_TIME_T *pFile_time, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, const char *user_extra_data_local, mz_uint user_extra_data_local_len,\n                                const char *user_extra_data_central, mz_uint user_extra_data_central_len);\n#endif\n\n/* Adds a file to an archive by fully cloning the data from another archive. */\n/* This function fully clones the source file's compressed data (no recompression), along with its full filename, extra data (it may add or modify the zip64 local header extra data field), and the optional descriptor following the compressed data. */\nmz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint src_file_index);\n\n/* Finalizes the archive by writing the central directory records followed by the end of central directory record. */\n/* After an archive is finalized, the only valid call on the mz_zip_archive struct is mz_zip_writer_end(). */\n/* An archive must be manually finalized by calling this function for it to be valid. */\nmz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip);\n\n/* Finalizes a heap archive, returning a poiner to the heap block and its size. */\n/* The heap block will be allocated using the mz_zip_archive's alloc/realloc callbacks. */\nmz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **ppBuf, size_t *pSize);\n\n/* Ends archive writing, freeing all allocations, and closing the output file if mz_zip_writer_init_file() was used. */\n/* Note for the archive to be valid, it *must* have been finalized before ending (this function will not do it for you). */\nmz_bool mz_zip_writer_end(mz_zip_archive *pZip);\n\n/* -------- Misc. high-level helper functions: */\n\n/* mz_zip_add_mem_to_archive_file_in_place() efficiently (but not atomically) appends a memory blob to a ZIP archive. */\n/* Note this is NOT a fully safe operation. If it crashes or dies in some way your archive can be left in a screwed up state (without a central directory). */\n/* level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION. */\n/* TODO: Perhaps add an option to leave the existing central dir in place in case the add dies? We could then truncate the file (so the old central dir would be at the end) if something goes wrong. */\nmz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags);\nmz_bool mz_zip_add_mem_to_archive_file_in_place_v2(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_zip_error *pErr);\n\n/* Reads a single file from an archive into a heap block. */\n/* If pComment is not NULL, only the file with the specified comment will be extracted. */\n/* Returns NULL on failure. */\nvoid *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint flags);\nvoid *mz_zip_extract_archive_file_to_heap_v2(const char *pZip_filename, const char *pArchive_name, const char *pComment, size_t *pSize, mz_uint flags, mz_zip_error *pErr);\n\n#endif /* #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* MINIZ_NO_ARCHIVE_APIS */\n"
  },
  {
    "path": "libs/miniz/readme.md",
    "content": "## Miniz\n\nMiniz is a lossless, high performance data compression library in a single source file that implements the zlib (RFC 1950) and Deflate (RFC 1951) compressed data format specification standards. It supports the most commonly used functions exported by the zlib library, but is a completely independent implementation so zlib's licensing requirements do not apply. Miniz also contains simple to use functions for writing .PNG format image files and reading/writing/appending .ZIP format archives. Miniz's compression speed has been tuned to be comparable to zlib's, and it also has a specialized real-time compressor function designed to compare well against fastlz/minilzo.\n\n## Usage\n\nPlease use the files from the [releases page](https://github.com/richgel999/miniz/releases) in your projects. Do not use the git checkout directly! The different source and header files are [amalgamated](https://www.sqlite.org/amalgamation.html) into one `miniz.c`/`miniz.h` pair in a build step (`amalgamate.sh`). Include `miniz.c` and `miniz.h` in your project to use Miniz.\n\n## Features\n\n* MIT licensed\n* A portable, single source and header file library written in plain C. Tested with GCC, clang and Visual Studio.\n* Easily tuned and trimmed down by defines\n* A drop-in replacement for zlib's most used API's (tested in several open source projects that use zlib, such as libpng and libzip).\n* Fills a single threaded performance vs. compression ratio gap between several popular real-time compressors and zlib. For example, at level 1, miniz.c compresses around 5-9% better than minilzo, but is approx. 35% slower. At levels 2-9, miniz.c is designed to compare favorably against zlib's ratio and speed. See the miniz performance comparison page for example timings.\n* Not a block based compressor: miniz.c fully supports stream based processing using a coroutine-style implementation. The zlib-style API functions can be called a single byte at a time if that's all you've got.\n* Easy to use. The low-level compressor (tdefl) and decompressor (tinfl) have simple state structs which can be saved/restored as needed with simple memcpy's. The low-level codec API's don't use the heap in any way.\n* Entire inflater (including optional zlib header parsing and Adler-32 checking) is implemented in a single function as a coroutine, which is separately available in a small (~550 line) source file: miniz_tinfl.c\n* A fairly complete (but totally optional) set of .ZIP archive manipulation and extraction API's. The archive functionality is intended to solve common problems encountered in embedded, mobile, or game development situations. (The archive API's are purposely just powerful enough to write an entire archiver given a bit of additional higher-level logic.)\n\n## Known Problems\n\n* No support for encrypted archives. Not sure how useful this stuff is in practice.\n* Minimal documentation. The assumption is that the user is already familiar with the basic zlib API. I need to write an API wiki - for now I've tried to place key comments before each enum/API, and I've included 6 examples that demonstrate how to use the module's major features.\n\n## Special Thanks\n\nThanks to Alex Evans for the PNG writer function. Also, thanks to Paul Holden and Thorsten Scheuermann for feedback and testing, Matt Pritchard for all his encouragement, and Sean Barrett's various public domain libraries for inspiration (and encouraging me to write miniz.c in C, which was much more enjoyable and less painful than I thought it would be considering I've been programming in C++ for so long).\n\nThanks to Bruce Dawson for reporting a problem with the level_and_flags archive API parameter (which is fixed in v1.12) and general feedback, and Janez Zemva for indirectly encouraging me into writing more examples.\n\n## Patents\n\nI was recently asked if miniz avoids patent issues. miniz purposely uses the same core algorithms as the ones used by zlib. The compressor uses vanilla hash chaining as described [here](http://www.gzip.org/zlib/rfc-deflate.html#algorithm). Also see the [gzip FAQ](http://www.gzip.org/#faq11). In my opinion, if miniz falls prey to a patent attack then zlib/gzip are likely to be at serious risk too.\n\n\n[![Build Status](https://travis-ci.org/uroni/miniz.svg?branch=master)](https://travis-ci.org/uroni/miniz)"
  },
  {
    "path": "libs/rapidyaml/LICENSE.txt",
    "content": "Copyright (c) 2018, Joao Paulo Magalhaes <dev@jpmag.me>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the \"Software\"),\nto deal in the Software without restriction, including without limitation\nthe rights to use, copy, modify, merge, publish, distribute, sublicense,\nand/or sell copies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included\nin all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\nOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\nDEALINGS IN THE SOFTWARE."
  },
  {
    "path": "libs/rapidyaml/c4/allocator.hpp",
    "content": "#ifndef _C4_ALLOCATOR_HPP_\n#define _C4_ALLOCATOR_HPP_\n\n#include \"c4/memory_resource.hpp\"\n#include \"c4/ctor_dtor.hpp\"\n\n#include <memory> // std::allocator_traits\n#include <type_traits>\n\n/** @file allocator.hpp Contains classes to make typeful allocations (note\n * that memory resources are typeless) */\n\n/** @defgroup mem_res_providers Memory resource providers\n * @brief Policy classes which provide a memory resource for\n * use in an allocator.\n * @ingroup memory\n */\n\n/** @defgroup allocators Allocators\n * @brief Lightweight classes that act as handles to specific memory\n * resources and provide typeful memory.\n * @ingroup memory\n */\n\nnamespace c4 {\n\nC4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH(\"-Wold-style-cast\")\n\nnamespace detail {\ntemplate<class T> inline size_t size_for      (size_t num_objs) noexcept { return num_objs * sizeof(T); }\ntemplate<       > inline size_t size_for<void>(size_t num_objs) noexcept { return num_objs;             }\n} // namespace detail\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n/** provides a per-allocator memory resource\n * @ingroup mem_res_providers */\nclass MemRes\n{\npublic:\n\n    MemRes() : m_resource(get_memory_resource()) {}\n    MemRes(MemoryResource* r) noexcept : m_resource(r ? r : get_memory_resource()) {}\n\n    inline MemoryResource* resource() const { return m_resource; }\n\nprivate:\n\n    MemoryResource* m_resource;\n\n};\n\n\n/** the allocators using this will default to the global memory resource\n * @ingroup mem_res_providers */\nclass MemResGlobal\n{\npublic:\n\n    MemResGlobal() {}\n    MemResGlobal(MemoryResource* r) noexcept { C4_UNUSED(r); C4_ASSERT(r == get_memory_resource()); }\n\n    inline MemoryResource* resource() const { return get_memory_resource(); }\n};\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\nnamespace detail {\ntemplate<class MemRes>\nstruct _AllocatorUtil;\n\ntemplate<class T, class ...Args>\nstruct has_no_alloc\n    : public std::integral_constant<bool,\n                                    !(std::uses_allocator<T, MemoryResource*>::value)\n                                    && std::is_constructible<T, Args...>::value> {};\n\n// std::uses_allocator_v<U, MemoryResource> && std::is_constructible<U, std::allocator_arg_t, MemoryResource*, Args...>\n// ie can construct(std::allocator_arg_t, MemoryResource*, Args...)\ntemplate<class T, class ...Args>\nstruct has_alloc_arg\n    : public std::integral_constant<bool,\n                                    std::uses_allocator<T, MemoryResource*>::value\n                                    && std::is_constructible<T, std::allocator_arg_t, MemoryResource*, Args...>::value> {};\n// std::uses_allocator<U> && std::is_constructible<U, Args..., MemoryResource*>\n// ie, can construct(Args..., MemoryResource*)\ntemplate<class T, class ...Args>\nstruct has_alloc\n    : public std::integral_constant<bool,\n                                    std::uses_allocator<T, MemoryResource*>::value\n                                    && std::is_constructible<T, Args..., MemoryResource*>::value> {};\n\n} // namespace detail\n\n\ntemplate<class MemRes>\nstruct detail::_AllocatorUtil : public MemRes\n{\n    using MemRes::MemRes;\n\n    /** for construct:\n     * @see http://en.cppreference.com/w/cpp/experimental/polymorphic_allocator/construct */\n\n    // 1. types with no allocators\n    template <class U, class... Args>\n    C4_ALWAYS_INLINE typename std::enable_if<detail::has_no_alloc<U, Args...>::value, void>::type\n    construct(U *ptr, Args &&...args)\n    {\n        c4::construct(ptr, std::forward<Args>(args)...);\n    }\n    template<class U, class I, class... Args>\n    C4_ALWAYS_INLINE typename std::enable_if<detail::has_no_alloc<U, Args...>::value, void>::type\n    construct_n(U* ptr, I n, Args&&... args)\n    {\n        c4::construct_n(ptr, n, std::forward<Args>(args)...);\n    }\n\n    // 2. types using allocators (ie, containers)\n\n    // 2.1. can construct(std::allocator_arg_t, MemoryResource*, Args...)\n    template<class U, class... Args>\n    C4_ALWAYS_INLINE typename std::enable_if<detail::has_alloc_arg<U, Args...>::value, void>::type\n    construct(U* ptr, Args&&... args)\n    {\n        c4::construct(ptr, std::allocator_arg, this->resource(), std::forward<Args>(args)...);\n    }\n    template<class U, class I, class... Args>\n    C4_ALWAYS_INLINE typename std::enable_if<detail::has_alloc_arg<U, Args...>::value, void>::type\n    construct_n(U* ptr, I n, Args&&... args)\n    {\n        c4::construct_n(ptr, n, std::allocator_arg, this->resource(), std::forward<Args>(args)...);\n    }\n\n    // 2.2. can construct(Args..., MemoryResource*)\n    template<class U, class... Args>\n    C4_ALWAYS_INLINE typename std::enable_if<detail::has_alloc<U, Args...>::value, void>::type\n    construct(U* ptr, Args&&... args)\n    {\n        c4::construct(ptr, std::forward<Args>(args)..., this->resource());\n    }\n    template<class U, class I, class... Args>\n    C4_ALWAYS_INLINE typename std::enable_if<detail::has_alloc<U, Args...>::value, void>::type\n    construct_n(U* ptr, I n, Args&&... args)\n    {\n        c4::construct_n(ptr, n, std::forward<Args>(args)..., this->resource());\n    }\n\n    template<class U>\n    static C4_ALWAYS_INLINE void destroy(U* ptr)\n    {\n        c4::destroy(ptr);\n    }\n    template<class U, class I>\n    static C4_ALWAYS_INLINE void destroy_n(U* ptr, I n)\n    {\n        c4::destroy_n(ptr, n);\n    }\n};\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n/** An allocator is simply a proxy to a memory resource.\n * @param T\n * @param MemResProvider\n * @ingroup allocators */\ntemplate<class T, class MemResProvider=MemResGlobal>\nclass Allocator : public detail::_AllocatorUtil<MemResProvider>\n{\npublic:\n\n    using impl_type = detail::_AllocatorUtil<MemResProvider>;\n\n    using value_type = T;\n    using pointer = T*;\n    using const_pointer = T const*;\n    using reference = T&;\n    using const_reference = T const&;\n    using size_type = size_t;\n    using difference_type = std::ptrdiff_t;\n    using propagate_on_container_move_assigment = std::true_type;\n\npublic:\n\n    template<class U, class MRProv>\n    bool operator== (Allocator<U, MRProv> const& that) const\n    {\n        return this->resource() == that.resource();\n    }\n    template<class U, class MRProv>\n    bool operator!= (Allocator<U, MRProv> const& that) const\n    {\n        return this->resource() != that.resource();\n    }\n\npublic:\n\n    template<class U, class MRProv> friend class Allocator;\n    template<class U>\n    struct rebind\n    {\n        using other = Allocator<U, MemResProvider>;\n    };\n    template<class U>\n    typename rebind<U>::other rebound()\n    {\n        return typename rebind<U>::other(*this);\n    }\n\npublic:\n\n    using impl_type::impl_type;\n    Allocator() : impl_type() {} // VS demands this\n\n    template<class U> Allocator(Allocator<U, MemResProvider> const& that) : impl_type(that.resource()) {}\n\n    Allocator(Allocator const&) = default;\n    Allocator(Allocator     &&) = default;\n\n    Allocator& operator= (Allocator const&) = default; // WTF? why? @see http://en.cppreference.com/w/cpp/memory/polymorphic_allocator\n    Allocator& operator= (Allocator     &&) = default;\n\n    /** returns a default-constructed polymorphic allocator object\n     * @see http://en.cppreference.com/w/cpp/memory/polymorphic_allocator/select_on_container_copy_construction      */\n    Allocator select_on_container_copy_construct() const { return Allocator(*this); }\n\n    T* allocate(size_t num_objs, size_t alignment=alignof(T))\n    {\n        C4_ASSERT(this->resource() != nullptr);\n        C4_ASSERT(alignment >= alignof(T));\n        void* vmem = this->resource()->allocate(detail::size_for<T>(num_objs), alignment);\n        T* mem = static_cast<T*>(vmem);\n        return mem;\n    }\n\n    void deallocate(T * ptr, size_t num_objs, size_t alignment=alignof(T))\n    {\n        C4_ASSERT(this->resource() != nullptr);\n        C4_ASSERT(alignment>= alignof(T));\n        this->resource()->deallocate(ptr, detail::size_for<T>(num_objs), alignment);\n    }\n\n    T* reallocate(T* ptr, size_t oldnum, size_t newnum, size_t alignment=alignof(T))\n    {\n        C4_ASSERT(this->resource() != nullptr);\n        C4_ASSERT(alignment >= alignof(T));\n        void* vmem = this->resource()->reallocate(ptr, detail::size_for<T>(oldnum), detail::size_for<T>(newnum), alignment);\n        T* mem = static_cast<T*>(vmem);\n        return mem;\n    }\n\n};\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n/** @ingroup allocators */\ntemplate<class T, size_t N=16, size_t Alignment=alignof(T), class MemResProvider=MemResGlobal>\nclass SmallAllocator : public detail::_AllocatorUtil<MemResProvider>\n{\n    static_assert(Alignment >= alignof(T), \"invalid alignment\");\n\n    using impl_type = detail::_AllocatorUtil<MemResProvider>;\n\n    alignas(Alignment) char m_arr[N * sizeof(T)];\n    size_t m_num{0};\n\npublic:\n\n    using value_type = T;\n    using pointer = T*;\n    using const_pointer = T const*;\n    using reference = T&;\n    using const_reference = T const&;\n    using size_type = size_t;\n    using difference_type = std::ptrdiff_t;\n    using propagate_on_container_move_assigment = std::true_type;\n\n    template<class U>\n    bool operator== (SmallAllocator<U,N,Alignment,MemResProvider> const&) const\n    {\n        return false;\n    }\n    template<class U>\n    bool operator!= (SmallAllocator<U,N,Alignment,MemResProvider> const&) const\n    {\n        return true;\n    }\n\npublic:\n\n    template<class U, size_t, size_t, class> friend class SmallAllocator;\n    template<class U>\n    struct rebind\n    {\n        using other = SmallAllocator<U, N, alignof(U), MemResProvider>;\n    };\n    template<class U>\n    typename rebind<U>::other rebound()\n    {\n        return typename rebind<U>::other(*this);\n    }\n\npublic:\n\n    using impl_type::impl_type;\n    SmallAllocator() : impl_type() {} // VS demands this\n\n    template<class U, size_t N2, size_t A2, class MP2>\n    SmallAllocator(SmallAllocator<U,N2,A2,MP2> const& that) : impl_type(that.resource())\n    {\n        C4_ASSERT(that.m_num == 0);\n    }\n\n    SmallAllocator(SmallAllocator const&) = default;\n    SmallAllocator(SmallAllocator     &&) = default;\n\n    SmallAllocator& operator= (SmallAllocator const&) = default; // WTF? why? @see http://en.cppreference.com/w/cpp/memory/polymorphic_allocator\n    SmallAllocator& operator= (SmallAllocator     &&) = default;\n\n    /** returns a default-constructed polymorphic allocator object\n     * @see http://en.cppreference.com/w/cpp/memory/polymorphic_allocator/select_on_container_copy_construction      */\n    SmallAllocator select_on_container_copy_construct() const { return SmallAllocator(*this); }\n\n    T* allocate(size_t num_objs, size_t alignment=Alignment)\n    {\n        C4_ASSERT(this->resource() != nullptr);\n        C4_ASSERT(alignment >= alignof(T));\n        void *vmem;\n        if(m_num + num_objs <= N)\n        {\n            vmem = (m_arr + m_num * sizeof(T));\n        }\n        else\n        {\n            vmem = this->resource()->allocate(num_objs * sizeof(T), alignment);\n        }\n        m_num += num_objs;\n        T *mem = static_cast<T*>(vmem);\n        return mem;\n    }\n\n    void deallocate(T * ptr, size_t num_objs, size_t alignment=Alignment)\n    {\n        C4_ASSERT(m_num >= num_objs);\n        m_num -= num_objs;\n        if((char*)ptr >= m_arr && (char*)ptr < m_arr + (N * sizeof(T)))\n        {\n            return;\n        }\n        C4_ASSERT(this->resource() != nullptr);\n        C4_ASSERT(alignment >= alignof(T));\n        this->resource()->deallocate(ptr, num_objs * sizeof(T), alignment);\n    }\n\n    T* reallocate(T * ptr, size_t oldnum, size_t newnum, size_t alignment=Alignment)\n    {\n        C4_ASSERT(this->resource() != nullptr);\n        C4_ASSERT(alignment >= alignof(T));\n        if(oldnum <= N && newnum <= N)\n        {\n            return m_arr;\n        }\n        else if(oldnum <= N && newnum > N)\n        {\n            return allocate(newnum, alignment);\n        }\n        else if(oldnum > N && newnum <= N)\n        {\n            deallocate(ptr, oldnum, alignment);\n            return m_arr;\n        }\n        void* vmem = this->resource()->reallocate(ptr, oldnum * sizeof(T), newnum * sizeof(T), alignment);\n        T* mem = static_cast<T*>(vmem);\n        return mem;\n    }\n\n};\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n/** An allocator making use of the global memory resource.\n * @ingroup allocators */\ntemplate<class T> using allocator = Allocator<T, MemResGlobal>;\n/** An allocator with a per-instance memory resource\n * @ingroup allocators */\ntemplate<class T> using allocator_mr = Allocator<T, MemRes>;\n\n/** @ingroup allocators */\ntemplate<class T, size_t N=16, size_t Alignment=alignof(T)> using small_allocator = SmallAllocator<T, N, Alignment, MemResGlobal>;\n/** @ingroup allocators */\ntemplate<class T, size_t N=16, size_t Alignment=alignof(T)> using small_allocator_mr = SmallAllocator<T, N, Alignment, MemRes>;\n\nC4_SUPPRESS_WARNING_GCC_CLANG_POP\n\n} // namespace c4\n\n#endif /* _C4_ALLOCATOR_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/base64.cpp",
    "content": "#include \"c4/base64.hpp\"\n\n#ifdef __clang__\n#   pragma clang diagnostic push\n#   pragma clang diagnostic ignored \"-Wchar-subscripts\" // array subscript is of type 'char'\n#   pragma clang diagnostic ignored \"-Wold-style-cast\"\n#elif defined(__GNUC__)\n#   pragma GCC diagnostic push\n#   pragma GCC diagnostic ignored \"-Wchar-subscripts\"\n#   pragma GCC diagnostic ignored \"-Wtype-limits\"\n#   pragma GCC diagnostic ignored \"-Wold-style-cast\"\n#endif\n\nnamespace c4 {\n\nnamespace detail {\n\nconstexpr static const char base64_sextet_to_char_[64] = {\n    /* 0/ 65*/ 'A', /* 1/ 66*/ 'B', /* 2/ 67*/ 'C', /* 3/ 68*/ 'D',\n    /* 4/ 69*/ 'E', /* 5/ 70*/ 'F', /* 6/ 71*/ 'G', /* 7/ 72*/ 'H',\n    /* 8/ 73*/ 'I', /* 9/ 74*/ 'J', /*10/ 75*/ 'K', /*11/ 74*/ 'L',\n    /*12/ 77*/ 'M', /*13/ 78*/ 'N', /*14/ 79*/ 'O', /*15/ 78*/ 'P',\n    /*16/ 81*/ 'Q', /*17/ 82*/ 'R', /*18/ 83*/ 'S', /*19/ 82*/ 'T',\n    /*20/ 85*/ 'U', /*21/ 86*/ 'V', /*22/ 87*/ 'W', /*23/ 88*/ 'X',\n    /*24/ 89*/ 'Y', /*25/ 90*/ 'Z', /*26/ 97*/ 'a', /*27/ 98*/ 'b',\n    /*28/ 99*/ 'c', /*29/100*/ 'd', /*30/101*/ 'e', /*31/102*/ 'f',\n    /*32/103*/ 'g', /*33/104*/ 'h', /*34/105*/ 'i', /*35/106*/ 'j',\n    /*36/107*/ 'k', /*37/108*/ 'l', /*38/109*/ 'm', /*39/110*/ 'n',\n    /*40/111*/ 'o', /*41/112*/ 'p', /*42/113*/ 'q', /*43/114*/ 'r',\n    /*44/115*/ 's', /*45/116*/ 't', /*46/117*/ 'u', /*47/118*/ 'v',\n    /*48/119*/ 'w', /*49/120*/ 'x', /*50/121*/ 'y', /*51/122*/ 'z',\n    /*52/ 48*/ '0', /*53/ 49*/ '1', /*54/ 50*/ '2', /*55/ 51*/ '3',\n    /*56/ 52*/ '4', /*57/ 53*/ '5', /*58/ 54*/ '6', /*59/ 55*/ '7',\n    /*60/ 56*/ '8', /*61/ 57*/ '9', /*62/ 43*/ '+', /*63/ 47*/ '/',\n};\n\n// https://www.cs.cmu.edu/~pattis/15-1XX/common/handouts/ascii.html\nconstexpr static const char base64_char_to_sextet_[128] = {\n    #define __ char(-1) // undefined below\n    /*  0 NUL*/ __, /*  1 SOH*/ __, /*  2 STX*/ __, /*  3 ETX*/ __,\n    /*  4 EOT*/ __, /*  5 ENQ*/ __, /*  6 ACK*/ __, /*  7 BEL*/ __,\n    /*  8 BS */ __, /*  9 TAB*/ __, /* 10 LF */ __, /* 11 VT */ __,\n    /* 12 FF */ __, /* 13 CR */ __, /* 14 SO */ __, /* 15 SI */ __,\n    /* 16 DLE*/ __, /* 17 DC1*/ __, /* 18 DC2*/ __, /* 19 DC3*/ __,\n    /* 20 DC4*/ __, /* 21 NAK*/ __, /* 22 SYN*/ __, /* 23 ETB*/ __,\n    /* 24 CAN*/ __, /* 25 EM */ __, /* 26 SUB*/ __, /* 27 ESC*/ __,\n    /* 28 FS */ __, /* 29 GS */ __, /* 30 RS */ __, /* 31 US */ __,\n    /* 32 SPC*/ __, /* 33 !  */ __, /* 34 \"  */ __, /* 35 #  */ __,\n    /* 36 $  */ __, /* 37 %  */ __, /* 38 &  */ __, /* 39 '  */ __,\n    /* 40 (  */ __, /* 41 )  */ __, /* 42 *  */ __, /* 43 +  */ 62,\n    /* 44 ,  */ __, /* 45 -  */ __, /* 46 .  */ __, /* 47 /  */ 63,\n    /* 48 0  */ 52, /* 49 1  */ 53, /* 50 2  */ 54, /* 51 3  */ 55,\n    /* 52 4  */ 56, /* 53 5  */ 57, /* 54 6  */ 58, /* 55 7  */ 59,\n    /* 56 8  */ 60, /* 57 9  */ 61, /* 58 :  */ __, /* 59 ;  */ __,\n    /* 60 <  */ __, /* 61 =  */ __, /* 62 >  */ __, /* 63 ?  */ __,\n    /* 64 @  */ __, /* 65 A  */  0, /* 66 B  */  1, /* 67 C  */  2,\n    /* 68 D  */  3, /* 69 E  */  4, /* 70 F  */  5, /* 71 G  */  6,\n    /* 72 H  */  7, /* 73 I  */  8, /* 74 J  */  9, /* 75 K  */ 10,\n    /* 76 L  */ 11, /* 77 M  */ 12, /* 78 N  */ 13, /* 79 O  */ 14,\n    /* 80 P  */ 15, /* 81 Q  */ 16, /* 82 R  */ 17, /* 83 S  */ 18,\n    /* 84 T  */ 19, /* 85 U  */ 20, /* 86 V  */ 21, /* 87 W  */ 22,\n    /* 88 X  */ 23, /* 89 Y  */ 24, /* 90 Z  */ 25, /* 91 [  */ __,\n    /* 92 \\  */ __, /* 93 ]  */ __, /* 94 ^  */ __, /* 95 _  */ __,\n    /* 96 `  */ __, /* 97 a  */ 26, /* 98 b  */ 27, /* 99 c  */ 28,\n    /*100 d  */ 29, /*101 e  */ 30, /*102 f  */ 31, /*103 g  */ 32,\n    /*104 h  */ 33, /*105 i  */ 34, /*106 j  */ 35, /*107 k  */ 36,\n    /*108 l  */ 37, /*109 m  */ 38, /*110 n  */ 39, /*111 o  */ 40,\n    /*112 p  */ 41, /*113 q  */ 42, /*114 r  */ 43, /*115 s  */ 44,\n    /*116 t  */ 45, /*117 u  */ 46, /*118 v  */ 47, /*119 w  */ 48,\n    /*120 x  */ 49, /*121 y  */ 50, /*122 z  */ 51, /*123 {  */ __,\n    /*124 |  */ __, /*125 }  */ __, /*126 ~  */ __, /*127 DEL*/ __,\n    #undef __\n};\n\n#ifndef NDEBUG\nvoid base64_test_tables()\n{\n    for(size_t i = 0; i < C4_COUNTOF(detail::base64_sextet_to_char_); ++i)\n    {\n        char s2c = base64_sextet_to_char_[i];\n        char c2s = base64_char_to_sextet_[(int)s2c];\n        C4_CHECK((size_t)c2s == i);\n    }\n    for(size_t i = 0; i < C4_COUNTOF(detail::base64_char_to_sextet_); ++i)\n    {\n        char c2s = base64_char_to_sextet_[i];\n        if(c2s == char(-1))\n            continue;\n        char s2c = base64_sextet_to_char_[(int)c2s];\n        C4_CHECK((size_t)s2c == i);\n    }\n}\n#endif\n} // namespace detail\n\n\nbool base64_valid(csubstr encoded)\n{\n    if(encoded.len & 3u) // (encoded.len % 4u)\n        return false;\n    for(const char c : encoded)\n    {\n        if(c < 0/* || c >= 128*/)\n            return false;\n        if(c == '=')\n            continue;\n        if(detail::base64_char_to_sextet_[c] == char(-1))\n            return false;\n    }\n    return true;\n}\n\n\nsize_t base64_encode(substr buf, cblob data)\n{\n    #define c4append_(c) { if(pos < buf.len) { buf.str[pos] = (c); } ++pos; }\n    #define c4append_idx_(char_idx) \\\n    {\\\n         C4_XASSERT((char_idx) < sizeof(detail::base64_sextet_to_char_));\\\n         c4append_(detail::base64_sextet_to_char_[(char_idx)]);\\\n    }\n    size_t rem, pos = 0;\n    constexpr const uint32_t sextet_mask = uint32_t(1 << 6) - 1;\n    const unsigned char *C4_RESTRICT d = (const unsigned char *) data.buf; // cast to unsigned to avoid wrapping high-bits\n    for(rem = data.len; rem >= 3; rem -= 3, d += 3)\n    {\n        const uint32_t val = ((uint32_t(d[0]) << 16) | (uint32_t(d[1]) << 8) | (uint32_t(d[2])));\n        c4append_idx_((val >> 18) & sextet_mask);\n        c4append_idx_((val >> 12) & sextet_mask);\n        c4append_idx_((val >>  6) & sextet_mask);\n        c4append_idx_((val      ) & sextet_mask);\n    }\n    C4_ASSERT(rem < 3);\n    if(rem == 2)\n    {\n        const uint32_t val = ((uint32_t(d[0]) << 16) | (uint32_t(d[1]) << 8));\n        c4append_idx_((val >> 18) & sextet_mask);\n        c4append_idx_((val >> 12) & sextet_mask);\n        c4append_idx_((val >>  6) & sextet_mask);\n        c4append_('=');\n    }\n    else if(rem == 1)\n    {\n        const uint32_t val = ((uint32_t(d[0]) << 16));\n        c4append_idx_((val >> 18) & sextet_mask);\n        c4append_idx_((val >> 12) & sextet_mask);\n        c4append_('=');\n        c4append_('=');\n    }\n    return pos;\n\n    #undef c4append_\n    #undef c4append_idx_\n}\n\n\nsize_t base64_decode(csubstr encoded, blob data)\n{\n    #define c4append_(c) { if(wpos < data.len) { data.buf[wpos] = static_cast<c4::byte>(c); } ++wpos; }\n    #define c4appendval_(c, shift)\\\n    {\\\n        C4_XASSERT(c >= 0);\\\n        C4_XASSERT(size_t(c) < sizeof(detail::base64_char_to_sextet_));\\\n        val |= static_cast<uint32_t>(detail::base64_char_to_sextet_[(c)]) << ((shift) * 6);\\\n    }\n    C4_ASSERT(base64_valid(encoded));\n    C4_CHECK((encoded.len & 3u) == 0);\n    size_t wpos = 0;  // the write position\n    const char *C4_RESTRICT d = encoded.str;\n    constexpr const uint32_t full_byte = 0xff;\n    // process every quartet of input 6 bits --> triplet of output bytes\n    for(size_t rpos = 0; rpos < encoded.len; rpos += 4, d += 4)\n    {\n        if(d[2] == '=' || d[3] == '=') // skip the last quartet if it is padded\n        {\n            C4_ASSERT(d + 4 == encoded.str + encoded.len);\n            break;\n        }\n        uint32_t val = 0;\n        c4appendval_(d[3], 0);\n        c4appendval_(d[2], 1);\n        c4appendval_(d[1], 2);\n        c4appendval_(d[0], 3);\n        c4append_((val >> (2 * 8)) & full_byte);\n        c4append_((val >> (1 * 8)) & full_byte);\n        c4append_((val           ) & full_byte);\n    }\n    // deal with the last quartet when it is padded\n    if(d == encoded.str + encoded.len)\n        return wpos;\n    if(d[2] == '=') // 2 padding chars\n    {\n        C4_ASSERT(d + 4 == encoded.str + encoded.len);\n        C4_ASSERT(d[3] == '=');\n        uint32_t val = 0;\n        c4appendval_(d[1], 2);\n        c4appendval_(d[0], 3);\n        c4append_((val >> (2 * 8)) & full_byte);\n    }\n    else if(d[3] == '=') // 1 padding char\n    {\n        C4_ASSERT(d + 4 == encoded.str + encoded.len);\n        uint32_t val = 0;\n        c4appendval_(d[2], 1);\n        c4appendval_(d[1], 2);\n        c4appendval_(d[0], 3);\n        c4append_((val >> (2 * 8)) & full_byte);\n        c4append_((val >> (1 * 8)) & full_byte);\n    }\n    return wpos;\n    #undef c4append_\n    #undef c4appendval_\n}\n\n} // namespace c4\n\n#ifdef __clang__\n#    pragma clang diagnostic pop\n#elif defined(__GNUC__)\n#    pragma GCC diagnostic pop\n#endif\n"
  },
  {
    "path": "libs/rapidyaml/c4/base64.hpp",
    "content": "#ifndef _C4_BASE64_HPP_\n#define _C4_BASE64_HPP_\n\n/** @file base64.hpp encoding/decoding for base64.\n * @see https://en.wikipedia.org/wiki/Base64\n * @see https://www.base64encode.org/\n * */\n\n#include \"c4/charconv.hpp\"\n#include \"c4/blob.hpp\"\n\nnamespace c4 {\n\n/** @defgroup doc_base64 Base64 encoding/decoding\n * @see https://en.wikipedia.org/wiki/Base64\n * @see https://www.base64encode.org/\n * @{ */\n\n/** check that the given buffer is a valid base64 encoding\n * @see https://en.wikipedia.org/wiki/Base64 */\nC4CORE_EXPORT bool base64_valid(csubstr encoded);\n\n\n/** base64-encode binary data.\n * @param encoded [out] output buffer for encoded data\n * @param data [in] the input buffer with the binary data\n *\n * @return the number of bytes needed to return the output (ie the\n * required size for @p encoded). No writes occur beyond the end of\n * the output buffer, so it is safe to do a speculative call where the\n * encoded buffer is empty, or maybe too small. The caller should\n * ensure that the returned size is smaller than the size of the\n * encoded buffer.\n *\n * @note the result depends on endianness. If transfer between\n * little/big endian systems is desired, the caller should normalize\n * @p data before encoding.\n *\n * @see https://en.wikipedia.org/wiki/Base64 */\nC4CORE_EXPORT size_t base64_encode(substr encoded, cblob data);\n\n\n/** decode the base64 encoding in the given buffer\n * @param encoded [in] the encoded base64\n * @param data [out] the output buffer\n *\n * @return the number of bytes needed to return the output (ie the\n * required size for @p data). No writes occur beyond the end of the\n * output buffer, so it is safe to do a speculative call where the\n * data buffer is empty, or maybe too small. The caller should ensure\n * that the returned size is smaller than the size of the data buffer.\n *\n * @note the result depends on endianness. If transfer between\n * little/big endian systems is desired, the caller should normalize\n * @p data after decoding.\n *\n * @see https://en.wikipedia.org/wiki/Base64 */\nC4CORE_EXPORT size_t base64_decode(csubstr encoded, blob data);\n\n/** @} */ // base64\n\nnamespace fmt {\n\n/** @addtogroup doc_format_specifiers\n * @{ */\n\n/** @defgroup doc_base64_fmt Base64\n * @{ */\n\ntemplate<typename CharOrConstChar>\nstruct base64_wrapper_\n{\n    blob_<CharOrConstChar> data;\n    base64_wrapper_() : data() {}\n    base64_wrapper_(blob_<CharOrConstChar> blob) : data(blob) {}\n};\n/** a tag type to mark a payload as base64-encoded */\nusing const_base64_wrapper = base64_wrapper_<cbyte>;\n/** a tag type to mark a payload to be encoded as base64 */\nusing base64_wrapper = base64_wrapper_<byte>;\n\n\n/** mark a variable to be written in base64 format */\ntemplate<class ...Args>\nC4_ALWAYS_INLINE const_base64_wrapper cbase64(Args const& C4_RESTRICT ...args)\n{\n    return const_base64_wrapper(cblob(args...));\n}\n/** mark a csubstr to be written in base64 format */\nC4_ALWAYS_INLINE const_base64_wrapper cbase64(csubstr s)\n{\n    return const_base64_wrapper(cblob(s.str, s.len));\n}\n/** mark a variable to be written in base64 format */\ntemplate<class ...Args>\nC4_ALWAYS_INLINE const_base64_wrapper base64(Args const& C4_RESTRICT ...args)\n{\n    return const_base64_wrapper(cblob(args...));\n}\n/** mark a csubstr to be written in base64 format */\nC4_ALWAYS_INLINE const_base64_wrapper base64(csubstr s)\n{\n    return const_base64_wrapper(cblob(s.str, s.len));\n}\n\n/** mark a variable to be read in base64 format */\ntemplate<class ...Args>\nC4_ALWAYS_INLINE base64_wrapper base64(Args &... args)\n{\n    return base64_wrapper(blob(args...));\n}\n/** mark a variable to be read in base64 format */\nC4_ALWAYS_INLINE base64_wrapper base64(substr s)\n{\n    return base64_wrapper(blob(s.str, s.len));\n}\n\n/** @} */ // base64_fmt\n\n/** @} */ // format_specifiers\n\n} // namespace fmt\n\n\n/** write a variable in base64 format\n * @ingroup doc_to_chars */\ninline size_t to_chars(substr buf, fmt::const_base64_wrapper b)\n{\n    return base64_encode(buf, b.data);\n}\n\n/** read a variable in base64 format\n * @ingroup doc_from_chars */\ninline size_t from_chars(csubstr buf, fmt::base64_wrapper *b)\n{\n    return base64_decode(buf, b->data);\n}\n\n} // namespace c4\n\n#endif /* _C4_BASE64_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/bitmask.hpp",
    "content": "#ifndef _C4_BITMASK_HPP_\n#define _C4_BITMASK_HPP_\n\n/** @file bitmask.hpp bitmask utilities */\n\n#include <cstring>\n#include <type_traits>\n\n#include \"c4/enum.hpp\"\n#include \"c4/format.hpp\"\n\n#if defined(_MSC_VER)\n#   pragma warning(push)\n#   pragma warning(disable : 4996) // 'strncpy', fopen, etc: This function or variable may be unsafe\n#endif\n\n#if defined(__clang__)\n#   pragma clang diagnostic push\n#   pragma clang diagnostic ignored \"-Wold-style-cast\"\n#elif defined(__GNUC__)\n#   pragma GCC diagnostic push\n#   pragma GCC diagnostic ignored \"-Wold-style-cast\"\n#   if __GNUC__ >= 8\n#       pragma GCC diagnostic ignored \"-Wstringop-truncation\"\n#       pragma GCC diagnostic ignored \"-Wstringop-overflow\"\n#   endif\n#endif\n\nnamespace c4 {\n\n//-----------------------------------------------------------------------------\n/** write a bitmask to a stream, formatted as a string */\n\ntemplate<class Enum, class Stream>\nStream& bm2stream(Stream &s, typename std::underlying_type<Enum>::type bits, EnumOffsetType offst=EOFFS_PFX)\n{\n    using I = typename std::underlying_type<Enum>::type;\n    bool written = false;\n\n    auto const& pairs = esyms<Enum>();\n\n    // write non null value\n    if(bits)\n    {\n        // do reverse iteration to give preference to composite enum symbols,\n        // which are likely to appear at the end of the enum sequence\n        for(size_t i = pairs.size() - 1; i != size_t(-1); --i)\n        {\n            auto p = pairs[i];\n            I b(static_cast<I>(p.value));\n            if(b && (bits & b) == b)\n            {\n                if(written) s << '|'; // append bit-or character\n                written = true;\n                s << p.name_offs(offst); // append bit string\n                bits &= ~b;\n            }\n        }\n        return s;\n    }\n    else\n    {\n        // write a null value\n        for(size_t i = pairs.size() - 1; i != size_t(-1); --i)\n        {\n            auto p = pairs[i];\n            I b(static_cast<I>(p.value));\n            if(b == 0)\n            {\n                s << p.name_offs(offst);\n                written = true;\n                break;\n            }\n        }\n    }\n    if(!written)\n    {\n        s << '0';\n    }\n    return s;\n}\n\ntemplate<class Enum, class Stream>\ntypename std::enable_if<is_scoped_enum<Enum>::value, Stream&>::type\nbm2stream(Stream &s, Enum value, EnumOffsetType offst=EOFFS_PFX)\n{\n    using I = typename std::underlying_type<Enum>::type;\n    return bm2stream<Enum>(s, static_cast<I>(value), offst);\n}\n\n\n//-----------------------------------------------------------------------------\n\n// some utility macros, undefed below\n\n/// @cond dev\n\n/* Execute `code` if the `num` of characters is available in the str\n * buffer. This macro simplifies the code for bm2str().\n * @todo improve performance by writing from the end and moving only once. */\n#define _c4prependchars(code, num)                                      \\\n    if(str && (pos + num <= sz))                                        \\\n    {                                                                   \\\n        /* move the current string to the right */                      \\\n        memmove(str + num, str, pos);                                   \\\n        /* now write in the beginning of the string */                  \\\n        code;                                                           \\\n    }                                                                   \\\n    else if(str && sz)                                                  \\\n    {                                                                   \\\n        C4_ERROR(\"cannot write to string pos=%d num=%d sz=%d\",          \\\n                 (int)pos, (int)num, (int)sz);                          \\\n    }                                                                   \\\n    pos += num\n\n/* Execute `code` if the `num` of characters is available in the str\n * buffer. This macro simplifies the code for bm2str(). */\n#define _c4appendchars(code, num)                                       \\\n    if(str && (pos + num <= sz))                                        \\\n    {                                                                   \\\n        code;                                                           \\\n    }                                                                   \\\n    else if(str && sz)                                                  \\\n    {                                                                   \\\n        C4_ERROR(\"cannot write to string pos=%d num=%d sz=%d\",          \\\n                 (int)pos, (int)num, (int)sz);                          \\\n    }                                                                   \\\n    pos += num\n\n/// @endcond\n\n\n/** convert a bitmask to string.\n * return the number of characters written. To find the needed size,\n * call first with str=nullptr and sz=0 */\ntemplate<class Enum>\nsize_t bm2str\n(\n    typename std::underlying_type<Enum>::type bits,\n    char *str=nullptr,\n    size_t sz=0,\n    EnumOffsetType offst=EOFFS_PFX\n)\n{\n    using I = typename std::underlying_type<Enum>::type;\n    C4_ASSERT((str == nullptr) == (sz == 0));\n\n    auto syms = esyms<Enum>();\n    size_t pos = 0;\n    typename EnumSymbols<Enum>::Sym const* C4_RESTRICT zero = nullptr;\n\n    // do reverse iteration to give preference to composite enum symbols,\n    // which are likely to appear later in the enum sequence\n    for(size_t i = syms.size()-1; i != size_t(-1); --i)\n    {\n        auto const &C4_RESTRICT p = syms[i]; // do not copy, we are assigning to `zero`\n        I b = static_cast<I>(p.value);\n        if(b == 0)\n        {\n            zero = &p; // save this symbol for later\n        }\n        else if((bits & b) == b)\n        {\n            bits &= ~b;\n            // append bit-or character\n            if(pos > 0)\n            {\n                _c4prependchars(*str = '|', 1);\n            }\n            // append bit string\n            const char *pname = p.name_offs(offst);\n            size_t len = strlen(pname);\n            _c4prependchars(strncpy(str, pname, len), len);\n        }\n    }\n\n    C4_CHECK_MSG(bits == 0, \"could not find all bits\");\n    if(pos == 0) // make sure at least something is written\n    {\n        if(zero) // if we have a zero symbol, use that\n        {\n            const char *pname = zero->name_offs(offst);\n            size_t len = strlen(pname);\n            _c4prependchars(strncpy(str, pname, len), len);\n        }\n        else // otherwise just write an integer zero\n        {\n            _c4prependchars(*str = '0', 1);\n        }\n    }\n    _c4appendchars(str[pos] = '\\0', 1);\n\n    return pos;\n}\n\n\n// cleanup!\n#undef _c4appendchars\n#undef _c4prependchars\n\n\n/** scoped enums do not convert automatically to their underlying type,\n * so this SFINAE overload will accept scoped enum symbols and cast them\n * to the underlying type */\ntemplate<class Enum>\ntypename std::enable_if<is_scoped_enum<Enum>::value, size_t>::type\nbm2str\n(\n    Enum bits,\n    char *str=nullptr,\n    size_t sz=0,\n    EnumOffsetType offst=EOFFS_PFX\n)\n{\n    using I = typename std::underlying_type<Enum>::type;\n    return bm2str<Enum>(static_cast<I>(bits), str, sz, offst);\n}\n\n\n//-----------------------------------------------------------------------------\n\nnamespace detail {\n\n#ifdef __clang__\n#   pragma clang diagnostic push\n#elif defined(__GNUC__)\n#   pragma GCC diagnostic push\n#   if __GNUC__ >= 6\n#       pragma GCC diagnostic ignored \"-Wnull-dereference\"\n#   endif\n#endif\n\ntemplate<class Enum>\ntypename std::underlying_type<Enum>::type str2bm_read_one(const char *str, size_t sz, bool alnum)\n{\n    using I = typename std::underlying_type<Enum>::type;\n    auto pairs = esyms<Enum>();\n    if(alnum)\n    {\n        auto *p = pairs.find(str, sz);\n        C4_CHECK_MSG(p != nullptr, \"no valid enum pair name for '%.*s'\", (int)sz, str);\n        return static_cast<I>(p->value);\n    }\n    I tmp{0};\n    size_t len = uncat(csubstr(str, sz), tmp);\n    C4_CHECK_MSG(len != csubstr::npos, \"could not read string as an integral type: '%.*s'\", (int)sz, str);\n    return tmp;\n}\n\n#ifdef __clang__\n#   pragma clang diagnostic pop\n#elif defined(__GNUC__)\n#   pragma GCC diagnostic pop\n#endif\n} // namespace detail\n\n/** convert a string to a bitmask */\ntemplate<class Enum>\ntypename std::underlying_type<Enum>::type str2bm(const char *str, size_t sz)\n{\n    using I = typename std::underlying_type<Enum>::type;\n\n    I val = 0;\n    bool started = false;\n    bool alnum = false, num = false;\n    const char *f = nullptr, *pc = str;\n    for( ; pc < str+sz; ++pc)\n    {\n        const char c = *pc;\n        if((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_')\n        {\n            C4_CHECK(( ! num) || ((pc - f) == 1 && (c == 'x' || c == 'X'))); // accept hexadecimal numbers\n            if( ! started)\n            {\n                f = pc;\n                alnum = started = true;\n            }\n        }\n        else if(c >= '0' && c <= '9')\n        {\n            C4_CHECK( ! alnum);\n            if(!started)\n            {\n                f = pc;\n                num = started = true;\n            }\n        }\n        else if(c == ':' || c == ' ')\n        {\n            // skip this char\n        }\n        else if(c == '|' || c == '\\0')\n        {\n            C4_ASSERT(num != alnum);\n            C4_ASSERT(pc >= f);\n            val |= detail::str2bm_read_one<Enum>(f, static_cast<size_t>(pc-f), alnum);\n            started = num = alnum = false;\n            if(c == '\\0')\n            {\n                return val;\n            }\n        }\n        else\n        {\n            C4_ERROR(\"bad character '%c' in bitmask string\", c);\n        }\n    }\n\n    if(f)\n    {\n        C4_ASSERT(num != alnum);\n        C4_ASSERT(pc >= f);\n        val |= detail::str2bm_read_one<Enum>(f, static_cast<size_t>(pc-f), alnum);\n    }\n\n    return val;\n}\n\n/** convert a string to a bitmask */\ntemplate<class Enum>\ntypename std::underlying_type<Enum>::type str2bm(const char *str)\n{\n    return str2bm<Enum>(str, strlen(str));\n}\n\n} // namespace c4\n\n#ifdef _MSC_VER\n#   pragma warning(pop)\n#endif\n\n#if defined(__clang__)\n#   pragma clang diagnostic pop\n#elif defined(__GNUC__)\n#   pragma GCC diagnostic pop\n#endif\n\n#endif // _C4_BITMASK_HPP_\n"
  },
  {
    "path": "libs/rapidyaml/c4/blob.hpp",
    "content": "#ifndef _C4_BLOB_HPP_\n#define _C4_BLOB_HPP_\n\n#include \"c4/types.hpp\"\n#include \"c4/error.hpp\"\n\n/** @file blob.hpp Mutable and immutable binary data blobs.\n*/\n\nnamespace c4 {\n\ntemplate<class T>\nstruct blob_;\n\nnamespace detail {\ntemplate<class T> struct is_blob_type : std::integral_constant<bool, false> {};\ntemplate<class T> struct is_blob_type<blob_<T>> : std::integral_constant<bool, true> {};\ntemplate<class T> struct is_blob_value_type : std::integral_constant<bool, (std::is_fundamental<T>::value || std::is_trivially_copyable<T>::value)> {};\n} // namespace\n\ntemplate<class T>\nstruct blob_\n{\n    static_assert(std::is_same<T, byte>::value || std::is_same<T, cbyte>::value, \"must be either byte or cbyte\");\n    static_assert(sizeof(T) == 1u, \"must be either byte or cbyte\");\n\npublic:\n\n    T *    buf;\n    size_t len;\n\npublic:\n\n    C4_ALWAYS_INLINE blob_() noexcept = default;\n    C4_ALWAYS_INLINE blob_(blob_ const& that) noexcept = default;\n    C4_ALWAYS_INLINE blob_(blob_     && that) noexcept = default;\n    C4_ALWAYS_INLINE blob_& operator=(blob_     && that) noexcept = default;\n    C4_ALWAYS_INLINE blob_& operator=(blob_ const& that) noexcept = default;\n\n    template<class U, class=typename std::enable_if<std::is_const<T>::value && std::is_same<typename std::add_const<U>::type, T>::value, U>::type> C4_ALWAYS_INLINE blob_(blob_<U> const& that) noexcept : buf(that.buf), len(that.len) {}\n    template<class U, class=typename std::enable_if<std::is_const<T>::value && std::is_same<typename std::add_const<U>::type, T>::value, U>::type> C4_ALWAYS_INLINE blob_(blob_<U>     && that) noexcept : buf(that.buf), len(that.len) {}\n    template<class U, class=typename std::enable_if<std::is_const<T>::value && std::is_same<typename std::add_const<U>::type, T>::value, U>::type> C4_ALWAYS_INLINE blob_& operator=(blob_<U>     && that) noexcept { buf = that.buf; len = that.len; }\n    template<class U, class=typename std::enable_if<std::is_const<T>::value && std::is_same<typename std::add_const<U>::type, T>::value, U>::type> C4_ALWAYS_INLINE blob_& operator=(blob_<U> const& that) noexcept { buf = that.buf; len = that.len; }\n\n    C4_ALWAYS_INLINE blob_(void       *ptr, size_t n) noexcept : buf(reinterpret_cast<T*>(ptr)), len(n) {}\n    C4_ALWAYS_INLINE blob_(void const *ptr, size_t n) noexcept : buf(reinterpret_cast<T*>(ptr)), len(n) {}\n\n    #define _C4_REQUIRE_BLOBTYPE(ty) class=typename std::enable_if<((!detail::is_blob_type<ty>::value) && (detail::is_blob_value_type<ty>::value)), T>::type\n    template<class U, _C4_REQUIRE_BLOBTYPE(U)> C4_ALWAYS_INLINE blob_(U &var) noexcept : buf(reinterpret_cast<T*>(&var)), len(sizeof(U)) {}\n    template<class U, _C4_REQUIRE_BLOBTYPE(U)> C4_ALWAYS_INLINE blob_(U *ptr, size_t n) noexcept : buf(reinterpret_cast<T*>(ptr)), len(sizeof(U) * n) { C4_ASSERT(is_aligned(ptr)); }\n    template<class U, _C4_REQUIRE_BLOBTYPE(U)> C4_ALWAYS_INLINE blob_& operator= (U &var) noexcept { buf = reinterpret_cast<T*>(&var); len = sizeof(U); return *this; }\n    template<class U, size_t N, _C4_REQUIRE_BLOBTYPE(U)> C4_ALWAYS_INLINE blob_(U (&arr)[N]) noexcept : buf(reinterpret_cast<T*>(arr)), len(sizeof(U) * N) {}\n    template<class U, size_t N, _C4_REQUIRE_BLOBTYPE(U)> C4_ALWAYS_INLINE blob_& operator= (U (&arr)[N]) noexcept { buf = reinterpret_cast<T*>(arr); len = sizeof(U) * N; return *this; }\n    #undef _C4_REQUIRE_BLOBTYPE\n};\n\n/** an immutable binary blob */\nusing cblob = blob_<cbyte>;\n/** a mutable binary blob */\nusing  blob = blob_< byte>;\n\nC4_MUST_BE_TRIVIAL_COPY(blob);\nC4_MUST_BE_TRIVIAL_COPY(cblob);\n\n} // namespace c4\n\n#endif // _C4_BLOB_HPP_\n"
  },
  {
    "path": "libs/rapidyaml/c4/c4_pop.hpp",
    "content": "#ifdef _C4_PUSH_HPP_ // this must match the include guard from c4_push\n\n/** @file c4_pop.hpp disables the macros and control directives\n * enabled in c4_push.hpp.\n * @see c4_push.hpp */\n\n#include \"c4/unrestrict.hpp\"\n\n#ifdef C4_WIN\n#   include \"c4/windows_pop.hpp\"\n#endif\n\n#ifdef _MSC_VER\n#   pragma warning(pop)\n#endif\n\n#undef _C4_PUSH_HPP_\n\n#endif /* _C4_PUSH_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/c4_push.hpp",
    "content": "#ifndef _C4_PUSH_HPP_\n#define _C4_PUSH_HPP_\n\n\n/** @file c4_push.hpp enables macros and warning control directives\n * needed by c4core. This is implemented in a push/pop way.\n * @see c4_pop.hpp */\n\n\n#ifndef _C4_CONFIG_HPP_\n#include \"c4/config.hpp\"\n#endif\n\n#include \"c4/restrict.hpp\"\n\n#ifdef C4_WIN\n#   include \"c4/windows_push.hpp\"\n#endif\n\n#ifdef _MSC_VER\n#   pragma warning(push)\n#   pragma warning(disable : 4068) // unknown pragma\n#   pragma warning(disable : 4100) // unreferenced formal parameter\n#   pragma warning(disable : 4127) // conditional expression is constant -- eg  do {} while(1);\n#   pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union\n//#   pragma warning(disable : 4238) // nonstandard extension used: class rvalue used as lvalue\n#   pragma warning(disable : 4244)\n#   pragma warning(disable : 4503) // decorated name length exceeded, name was truncated\n#   pragma warning(disable : 4702) // unreachable code\n#   pragma warning(disable : 4714) // function marked as __forceinline not inlined\n#   pragma warning(disable : 4996) // 'strncpy', fopen, etc: This function or variable may be unsafe\n#   if C4_MSVC_VERSION != C4_MSVC_VERSION_2017\n#       pragma warning(disable : 4800) // forcing value to bool 'true' or 'false' (performance warning)\n#   endif\n#endif\n\n#endif /* _C4_PUSH_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/c4core.natvis",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?> \n\n<!--\nVery good intro:\n@see https://code.msdn.microsoft.com/windowsdesktop/Writing-type-visualizers-2eae77a2\nSee also:\n@see http://blogs.msdn.com/b/vcblog/archive/2013/06/28/using-visual-studio-2013-to-write-maintainable-native-visualizations-natvis.aspx?PageIndex=2\n@see http://blogs.msdn.com/b/vcblog/archive/2015/09/28/debug-visualizers-in-visual-c-2015.aspx\n@see http://stackoverflow.com/questions/36883414/limit-display-of-char-in-natvis-file-to-specific-length\n-->\n\n<AutoVisualizer xmlns=\"http://schemas.microsoft.com/vstudio/debugger/natvis/2010\">\n\n  <Type Name=\"c4::basic_substring&lt;*&gt;\">\n    <DisplayString>{str,[len]} (sz={len})</DisplayString>\n    <StringView>str,[len]</StringView>\n    <Expand>\n      <Item Name=\"[size]\">len</Item>\n      <ArrayItems>\n        <Size>len</Size>\n        <ValuePointer>str</ValuePointer>\n      </ArrayItems>\n    </Expand>\n  </Type>\n\n  <Type Name=\"c4::span&lt;*&gt;\">\n    <DisplayString>{m_ptr,[m_size]} (sz={m_size})</DisplayString>\n    <Expand>\n      <Item Name=\"[size]\">m_size</Item>\n      <ArrayItems>\n        <Size>m_size</Size>\n        <ValuePointer>m_ptr</ValuePointer>\n      </ArrayItems>\n    </Expand>\n  </Type>\n  <Type Name=\"c4::spanrs&lt;*&gt;\">\n    <DisplayString>{m_ptr,[m_size]} (sz={m_size}, cap={m_capacity})</DisplayString>\n    <Expand>\n      <Item Name=\"[size]\">m_size</Item>\n      <Item Name=\"[capacity]\">m_capacity</Item>\n      <ArrayItems>\n        <Size>m_size</Size>\n        <ValuePointer>m_ptr</ValuePointer>\n      </ArrayItems>\n    </Expand>\n  </Type>\n  <!-- display span<char>/span<const char> as a string too -->\n  <Type Name=\"c4::span&lt;char,*&gt;\">\n    <DisplayString>{m_ptr,[m_size]} (sz={m_size})</DisplayString>\n    <StringView>m_ptr,[m_size]</StringView>\n    <Expand>\n      <Item Name=\"[size]\">m_size</Item>\n      <ArrayItems>\n        <Size>m_size</Size>\n        <ValuePointer>m_ptr</ValuePointer>\n      </ArrayItems>\n    </Expand>\n  </Type>\n  <Type Name=\"c4::span&lt;const char,*&gt;\">\n    <DisplayString>{m_ptr,[m_size]} (sz={m_size})</DisplayString>\n    <StringView>m_ptr,[m_size]</StringView>\n    <Expand>\n      <Item Name=\"[size]\">m_size</Item>\n      <ArrayItems>\n        <Size>m_size</Size>\n        <ValuePointer>m_ptr</ValuePointer>\n      </ArrayItems>\n    </Expand>\n  </Type>\n  <!-- display spanrs<char>/spanrs<const char> as a string too -->\n  <Type Name=\"c4::spanrs&lt;char,*&gt;\">\n    <DisplayString>{m_ptr,[m_size]} (sz={m_size}, cap={m_capacity})</DisplayString>\n    <StringView>m_ptr,[m_size]</StringView>\n    <Expand>\n      <Item Name=\"[size]\">m_size</Item>\n      <Item Name=\"[capacity]\">m_capacity</Item>\n      <ArrayItems>\n        <Size>m_size</Size>\n        <ValuePointer>m_ptr</ValuePointer>\n      </ArrayItems>\n    </Expand>\n  </Type>\n  <Type Name=\"c4::spanrs&lt;const char,*&gt;\">\n    <DisplayString>{m_ptr,[m_size]} (sz={m_size}, cap={m_capacity})</DisplayString>\n    <StringView>m_ptr,[m_size]</StringView>\n    <Expand>\n      <Item Name=\"[size]\">m_size</Item>\n      <Item Name=\"[capacity]\">m_capacity</Item>\n      <ArrayItems>\n        <Size>m_size</Size>\n        <ValuePointer>m_ptr</ValuePointer>\n      </ArrayItems>\n    </Expand>\n  </Type>\n\n  <!-- =========================================================================================== -->\n  <Type Name=\"c4::string_impl&lt;*,*,*,*&gt;\">\n    <DisplayString>{(($T3*)this)->m_str,[(($T3*)this)->m_size]} (sz={(($T3*)this)->m_size})</DisplayString>\n    <StringView>(($T3*)this)->m_str,[(($T3*)this)->m_size]</StringView>\n    <Expand>\n      <Synthetic Name=\"m_str\">\n        <DisplayString>{(($T3*)this)->m_str,[(($T3*)this)->m_size]}</DisplayString>\n        <StringView>(($T3*)this)->m_str,[(($T3*)this)->m_size]</StringView>\n      </Synthetic>\n      <Synthetic Name=\"m_size\">\n        <DisplayString>{(($T3*)this)->m_size}</DisplayString>\n      </Synthetic>\n    </Expand>\n  </Type>\n  <Type Name=\"c4::basic_substring&lt;*,*&gt;\">\n    <DisplayString>{m_str,[m_size]} (sz={m_size})</DisplayString>\n    <StringView>m_str,[m_size]</StringView>\n    <Expand>\n      <Synthetic Name=\"[size]\">\n        <DisplayString>{m_size}</DisplayString>\n      </Synthetic>\n    </Expand>\n  </Type>\n  <Type Name=\"c4::basic_substringrs&lt;*,*&gt;\">\n    <DisplayString>{m_str,[m_size]} (sz={m_size},cap={m_capacity})</DisplayString>\n    <StringView>m_str,[m_size]</StringView>\n    <Expand>\n      <Synthetic Name=\"[size]\">\n        <DisplayString>{m_size}</DisplayString>\n      </Synthetic>\n      <Synthetic Name=\"[capacity]\">\n        <DisplayString>{m_capacity}</DisplayString>\n      </Synthetic>\n      <Synthetic Name=\"[full]\">\n        <DisplayString>{m_str,[m_capacity]}</DisplayString>\n        <StringView>m_str,[m_capacity]</StringView>\n      </Synthetic>\n    </Expand>\n  </Type>\n  <Type Name=\"c4::basic_string&lt;*,*,*&gt;\">\n    <DisplayString>{m_str,[m_size]} (sz={m_size},cap={m_capacity})</DisplayString>\n    <StringView>m_str,[m_size]</StringView>\n    <Expand>\n      <Synthetic Name=\"[size]\">\n        <DisplayString>{m_size}</DisplayString>\n      </Synthetic>\n      <Synthetic Name=\"[full]\">\n        <DisplayString>{m_str,[m_capacity]}</DisplayString>\n        <StringView>m_str,[m_capacity]</StringView>\n      </Synthetic>\n    </Expand>\n  </Type>\n\n  <!-- enum symbols -->\n  <Type Name=\"c4::EnumSymbols&lt;*&gt;::Sym\">\n    <DisplayString>{value} - {name}</DisplayString>\n    <Expand>\n      <Item Name=\"[value]\">value</Item>\n      <Item Name=\"[name]\">name</Item>\n    </Expand>\n  </Type>\n  <Type Name=\"c4::EnumSymbols&lt;*&gt;\">\n    <DisplayString>{m_symbols,[m_num]} (sz={m_num})</DisplayString>\n    <Expand>\n      <Item Name=\"[size]\">m_num</Item>\n      <ArrayItems>\n        <Size>m_num</Size>\n        <ValuePointer>m_symbols</ValuePointer>\n      </ArrayItems>\n    </Expand>\n  </Type>\n\n</AutoVisualizer>\n"
  },
  {
    "path": "libs/rapidyaml/c4/char_traits.cpp",
    "content": "#include \"c4/char_traits.hpp\"\n\nnamespace c4 {\n\nconstexpr const char char_traits< char >::whitespace_chars[];\nconstexpr const size_t char_traits< char >::num_whitespace_chars;\nconstexpr const wchar_t char_traits< wchar_t >::whitespace_chars[];\nconstexpr const size_t char_traits< wchar_t >::num_whitespace_chars;\n\n} // namespace c4\n"
  },
  {
    "path": "libs/rapidyaml/c4/char_traits.hpp",
    "content": "#ifndef _C4_CHAR_TRAITS_HPP_\n#define _C4_CHAR_TRAITS_HPP_\n\n#include \"c4/config.hpp\"\n\n#include <string> // needed because of std::char_traits\n#include <cctype>\n#include <cwctype>\n\nnamespace c4 {\n\nC4_ALWAYS_INLINE bool isspace(char c) { return std::isspace(c) != 0; }\nC4_ALWAYS_INLINE bool isspace(wchar_t c) { return std::iswspace(static_cast<wint_t>(c)) != 0; }\n\n//-----------------------------------------------------------------------------\ntemplate<typename C>\nstruct char_traits;\n\ntemplate<>\nstruct char_traits<char> : public std::char_traits<char>\n{\n    constexpr static const char whitespace_chars[] = \" \\f\\n\\r\\t\\v\";\n    constexpr static const size_t num_whitespace_chars = sizeof(whitespace_chars) - 1;\n};\n\ntemplate<>\nstruct char_traits<wchar_t> : public std::char_traits<wchar_t>\n{\n    constexpr static const wchar_t whitespace_chars[] = L\" \\f\\n\\r\\t\\v\";\n    constexpr static const size_t num_whitespace_chars = sizeof(whitespace_chars) - 1;\n};\n\n\n//-----------------------------------------------------------------------------\nnamespace detail {\ntemplate<typename C>\nstruct needed_chars;\ntemplate<>\nstruct needed_chars<char>\n{\n    template<class SizeType>\n    C4_ALWAYS_INLINE constexpr static SizeType for_bytes(SizeType num_bytes)\n    {\n        return num_bytes;\n    }\n};\ntemplate<>\nstruct needed_chars<wchar_t>\n{\n    template<class SizeType>\n    C4_ALWAYS_INLINE constexpr static SizeType for_bytes(SizeType num_bytes)\n    {\n        // wchar_t is not necessarily 2 bytes.\n        return (num_bytes / static_cast<SizeType>(sizeof(wchar_t))) + ((num_bytes & static_cast<SizeType>(SizeType(sizeof(wchar_t)) - SizeType(1))) != 0);\n    }\n};\n} // namespace detail\n\n/** get the number of C characters needed to store a number of bytes */\ntemplate<typename C, typename SizeType>\nC4_ALWAYS_INLINE constexpr SizeType num_needed_chars(SizeType num_bytes)\n{\n    return detail::needed_chars<C>::for_bytes(num_bytes);\n}\n\n\n//-----------------------------------------------------------------------------\n\n/** get the given text string as either char or wchar_t according to the given type */\n#define C4_TXTTY(txt, type) \\\n    /* is there a smarter way to do this? */\\\n    c4::detail::literal_as<type>::get(txt, C4_WIDEN(txt))\n\nnamespace detail {\ntemplate<typename C>\nstruct literal_as;\n\ntemplate<>\nstruct literal_as<char>\n{\n    C4_ALWAYS_INLINE static constexpr const char* get(const char* str, const wchar_t *)\n    {\n        return str;\n    }\n};\ntemplate<>\nstruct literal_as<wchar_t>\n{\n    C4_ALWAYS_INLINE static constexpr const wchar_t* get(const char*, const wchar_t *wstr)\n    {\n        return wstr;\n    }\n};\n} // namespace detail\n\n} // namespace c4\n\n#endif /* _C4_CHAR_TRAITS_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/charconv.hpp",
    "content": "#ifndef _C4_CHARCONV_HPP_\n#define _C4_CHARCONV_HPP_\n\n/** @file charconv.hpp Lightweight generic type-safe wrappers for\n * converting individual values to/from strings.\n */\n\n#include \"c4/language.hpp\"\n#include <inttypes.h>\n#include <type_traits>\n#include <climits>\n#include <limits>\n#include <utility>\n\n#include \"c4/config.hpp\"\n#include \"c4/substr.hpp\"\n#include \"c4/std/std_fwd.hpp\"\n#include \"c4/memory_util.hpp\"\n#include \"c4/szconv.hpp\"\n\n#ifndef C4CORE_NO_FAST_FLOAT\n#   if (C4_CPP >= 17)\n#       if defined(_MSC_VER)\n#           if (C4_MSVC_VERSION >= C4_MSVC_VERSION_2019) // VS2017 and lower do not have these macros\n#               include <charconv>\n#               define C4CORE_HAVE_STD_TOCHARS 1\n#               define C4CORE_HAVE_STD_FROMCHARS 0 // prefer fast_float with MSVC\n#               define C4CORE_HAVE_FAST_FLOAT 1\n#           else\n#               define C4CORE_HAVE_STD_TOCHARS 0\n#               define C4CORE_HAVE_STD_FROMCHARS 0\n#               define C4CORE_HAVE_FAST_FLOAT 1\n#           endif\n#       else\n#           if __has_include(<charconv>)\n#               include <charconv>\n#               if defined(__cpp_lib_to_chars)\n#                   define C4CORE_HAVE_STD_TOCHARS 1\n#                   define C4CORE_HAVE_STD_FROMCHARS 0 // glibc uses fast_float internally\n#                   define C4CORE_HAVE_FAST_FLOAT 1\n#               else\n#                   define C4CORE_HAVE_STD_TOCHARS 0\n#                   define C4CORE_HAVE_STD_FROMCHARS 0\n#                   define C4CORE_HAVE_FAST_FLOAT 1\n#               endif\n#           else\n#               define C4CORE_HAVE_STD_TOCHARS 0\n#               define C4CORE_HAVE_STD_FROMCHARS 0\n#               define C4CORE_HAVE_FAST_FLOAT 1\n#           endif\n#       endif\n#   else\n#       define C4CORE_HAVE_STD_TOCHARS 0\n#       define C4CORE_HAVE_STD_FROMCHARS 0\n#       define C4CORE_HAVE_FAST_FLOAT 1\n#   endif\n#   if C4CORE_HAVE_FAST_FLOAT\n        C4_SUPPRESS_WARNING_GCC_WITH_PUSH(\"-Wsign-conversion\")\n        C4_SUPPRESS_WARNING_GCC(\"-Warray-bounds\")\n#       if defined(__GNUC__) && __GNUC__ >= 5\n            C4_SUPPRESS_WARNING_GCC(\"-Wshift-count-overflow\")\n#       endif\n#       include \"c4/ext/fast_float.hpp\"\n        C4_SUPPRESS_WARNING_GCC_POP\n#   endif\n#elif (C4_CPP >= 17)\n#   define C4CORE_HAVE_FAST_FLOAT 0\n#   if defined(_MSC_VER)\n#       if (C4_MSVC_VERSION >= C4_MSVC_VERSION_2019) // VS2017 and lower do not have these macros\n#           include <charconv>\n#           define C4CORE_HAVE_STD_TOCHARS 1\n#           define C4CORE_HAVE_STD_FROMCHARS 1\n#       else\n#           define C4CORE_HAVE_STD_TOCHARS 0\n#           define C4CORE_HAVE_STD_FROMCHARS 0\n#       endif\n#   else\n#       if __has_include(<charconv>)\n#           include <charconv>\n#           if defined(__cpp_lib_to_chars)\n#               define C4CORE_HAVE_STD_TOCHARS 1\n#               define C4CORE_HAVE_STD_FROMCHARS 1 // glibc uses fast_float internally\n#           else\n#               define C4CORE_HAVE_STD_TOCHARS 0\n#               define C4CORE_HAVE_STD_FROMCHARS 0\n#           endif\n#       else\n#           define C4CORE_HAVE_STD_TOCHARS 0\n#           define C4CORE_HAVE_STD_FROMCHARS 0\n#       endif\n#   endif\n#else\n#   define C4CORE_HAVE_STD_TOCHARS 0\n#   define C4CORE_HAVE_STD_FROMCHARS 0\n#   define C4CORE_HAVE_FAST_FLOAT 0\n#endif\n\n\n#if !C4CORE_HAVE_STD_FROMCHARS\n#include <cstdio>\n#endif\n\n\n#if defined(_MSC_VER)\n#   pragma warning(push)\n#   pragma warning(disable: 4996) // snprintf/scanf: this function or variable may be unsafe\n#   if C4_MSVC_VERSION != C4_MSVC_VERSION_2017\n#       pragma warning(disable: 4800) //'int': forcing value to bool 'true' or 'false' (performance warning)\n#   endif\n#endif\n\n#if defined(__clang__)\n#   pragma clang diagnostic push\n#   pragma clang diagnostic ignored \"-Wtautological-constant-out-of-range-compare\"\n#   pragma clang diagnostic ignored \"-Wformat-nonliteral\"\n#   pragma clang diagnostic ignored \"-Wdouble-promotion\" // implicit conversion increases floating-point precision\n#   pragma clang diagnostic ignored \"-Wold-style-cast\"\n#elif defined(__GNUC__)\n#   pragma GCC diagnostic push\n#   pragma GCC diagnostic ignored \"-Wformat-nonliteral\"\n#   pragma GCC diagnostic ignored \"-Wdouble-promotion\" // implicit conversion increases floating-point precision\n#   pragma GCC diagnostic ignored \"-Wuseless-cast\"\n#   pragma GCC diagnostic ignored \"-Wold-style-cast\"\n#endif\n\n#if defined(__clang__)\n#define C4_NO_UBSAN_IOVRFLW __attribute__((no_sanitize(\"signed-integer-overflow\")))\n#elif defined(__GNUC__)\n#if __GNUC__ > 7\n#define C4_NO_UBSAN_IOVRFLW __attribute__((no_sanitize(\"signed-integer-overflow\")))\n#else\n#define C4_NO_UBSAN_IOVRFLW\n#endif\n#else\n#define C4_NO_UBSAN_IOVRFLW\n#endif\n\n\nnamespace c4 {\n\n/** @defgroup doc_charconv Charconv utilities\n *\n * Lightweight, very fast generic type-safe wrappers for converting\n * individual values to/from strings. These are the main generic\n * functions:\n *   - @ref doc_to_chars and its alias @ref doc_xtoa: implemented by calling @ref itoa()/@ref utoa()/@ref ftoa()/@ref dtoa() (or generically @ref xtoa())\n *   - @ref doc_from_chars and its alias @ref doc_atox: implemented by calling @ref atoi()/@ref atou()/@ref atof()/@ref atod() (or generically @ref atox())\n *   - @ref to_chars_sub()\n *   - @ref from_chars_first()\n *   - @ref xtoa()/@ref atox() are implemented in terms @ref write_dec()/@ref read_dec() et al (see @ref doc_write/@ref doc_read())\n *\n * And also some modest brag is in order: these functions are really\n * fast: faster even than C++17 `std::to_chars()` and\n * `std::to_chars()`, and many dozens of times faster than the\n * iostream abominations.\n *\n * For example, here are some benchmark comparisons for @ref\n * doc_from_chars (link leads to the main project README, where these\n * results are shown more systematically).\n *\n * <table>\n * <caption id=\"atox-i64-results\">atox,int64_t</caption>\n * <tr><th>g++12, linux <th>Visual Studio 2019\n * <tr><td> \\image html linux-x86_64-gxx12.1-Release-c4core-bm-charconv-atox-mega_bytes_per_second-i64.png <td> \\image html windows-x86_64-vs2019-Release-c4core-bm-charconv-atox-mega_bytes_per_second-i64.png\n * </table>\n *\n * <table>\n * <caption id=\"xtoa-i64-results\">xtoa,int64_t</caption>\n * <tr><th>g++12, linux <th>Visual Studio 2019\n * <tr><td> \\image html linux-x86_64-gxx12.1-Release-c4core-bm-charconv-xtoa-mega_bytes_per_second-i64.png <td> \\image html windows-x86_64-vs2019-Release-c4core-bm-charconv-xtoa-mega_bytes_per_second-i64.png\n * </table>\n *\n * To parse floating point, c4core uses\n * [fastfloat](https://github.com/fastfloat/fast_float), which is\n * extremely fast, by an even larger factor:\n *\n * <table>\n * <caption id=\"atox-float-results\">atox,float</caption>\n * <tr><th>g++12, linux <th>Visual Studio 2019\n * <tr><td> \\image html linux-x86_64-gxx12.1-Release-c4core-bm-charconv-atof-mega_bytes_per_second-float.png <td> \\image html windows-x86_64-vs2019-Release-c4core-bm-charconv-atof-mega_bytes_per_second-float.png\n * </table>\n *\n * @{\n */\n\n#if C4CORE_HAVE_STD_TOCHARS\n/** @warning Use only the symbol. Do not rely on the type or naked value of this enum. */\ntypedef enum : std::underlying_type<std::chars_format>::type {\n    /** print the real number in floating point format (like %f) */\n    FTOA_FLOAT = static_cast<std::underlying_type<std::chars_format>::type>(std::chars_format::fixed),\n    /** print the real number in scientific format (like %e) */\n    FTOA_SCIENT = static_cast<std::underlying_type<std::chars_format>::type>(std::chars_format::scientific),\n    /** print the real number in flexible format (like %g) */\n    FTOA_FLEX = static_cast<std::underlying_type<std::chars_format>::type>(std::chars_format::general),\n    /** print the real number in hexadecimal format (like %a) */\n    FTOA_HEXA = static_cast<std::underlying_type<std::chars_format>::type>(std::chars_format::hex),\n} RealFormat_e;\n#else\n/** @warning Use only the symbol. Do not rely on the type or naked value of this enum. */\ntypedef enum : char {\n    /** print the real number in floating point format (like %f) */\n    FTOA_FLOAT = 'f',\n    /** print the real number in scientific format (like %e) */\n    FTOA_SCIENT = 'e',\n    /** print the real number in flexible format (like %g) */\n    FTOA_FLEX = 'g',\n    /** print the real number in hexadecimal format (like %a) */\n    FTOA_HEXA = 'a',\n} RealFormat_e;\n#endif\n\n/** @cond dev */\n/** in some platforms, int,unsigned int\n *  are not any of int8_t...int64_t and\n *  long,unsigned long are not any of uint8_t...uint64_t */\ntemplate<class T>\nstruct is_fixed_length\n{\n    enum : bool {\n        /** true if T is one of the fixed length signed types */\n        value_i = (std::is_integral<T>::value\n                   && (std::is_same<T, int8_t>::value\n                       || std::is_same<T, int16_t>::value\n                       || std::is_same<T, int32_t>::value\n                       || std::is_same<T, int64_t>::value)),\n        /** true if T is one of the fixed length unsigned types */\n        value_u = (std::is_integral<T>::value\n                   && (std::is_same<T, uint8_t>::value\n                       || std::is_same<T, uint16_t>::value\n                       || std::is_same<T, uint32_t>::value\n                       || std::is_same<T, uint64_t>::value)),\n        /** true if T is one of the fixed length signed or unsigned types */\n        value = value_i || value_u\n    };\n};\n/** @endcond */\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n#ifdef _MSC_VER\n#   pragma warning(push)\n#elif defined(__clang__)\n#   pragma clang diagnostic push\n#elif defined(__GNUC__)\n#   pragma GCC diagnostic push\n#   pragma GCC diagnostic ignored \"-Wconversion\"\n#   if __GNUC__ >= 6\n#       pragma GCC diagnostic ignored \"-Wnull-dereference\"\n#   endif\n#endif\n\n/** @cond dev */\nnamespace detail {\n\n/* python command to get the values below:\ndef dec(v):\n    return str(v)\nfor bits in (8, 16, 32, 64):\n    imin, imax, umax = (-(1 << (bits - 1))), (1 << (bits - 1)) - 1, (1 << bits) - 1\n    for vname, v in ((\"imin\", imin), (\"imax\", imax), (\"umax\", umax)):\n        for f in (bin, oct, dec, hex):\n            print(f\"{bits}b: {vname}={v} {f.__name__}: len={len(f(v)):2d}: {v} {f(v)}\")\n*/\n\n// do not use the type as the template argument because in some\n// platforms long!=int32 and long!=int64. Just use the numbytes\n// which is more generic and spares lengthy SFINAE code.\ntemplate<size_t num_bytes, bool is_signed> struct charconv_digits_;\ntemplate<class T> using charconv_digits = charconv_digits_<sizeof(T), std::is_signed<T>::value>;\n\ntemplate<> struct charconv_digits_<1u, true> // int8_t\n{\n    enum : size_t {\n        maxdigits_bin       = 1 + 2 + 8, // -128==-0b10000000\n        maxdigits_oct       = 1 + 2 + 3, // -128==-0o200\n        maxdigits_dec       = 1     + 3, // -128\n        maxdigits_hex       = 1 + 2 + 2, // -128==-0x80\n        maxdigits_bin_nopfx =         8, // -128==-0b10000000\n        maxdigits_oct_nopfx =         3, // -128==-0o200\n        maxdigits_dec_nopfx =         3, // -128\n        maxdigits_hex_nopfx =         2, // -128==-0x80\n    };\n    // min values without sign!\n    static constexpr csubstr min_value_dec() noexcept { return csubstr(\"128\"); }\n    static constexpr csubstr min_value_hex() noexcept { return csubstr(\"80\"); }\n    static constexpr csubstr min_value_oct() noexcept { return csubstr(\"200\"); }\n    static constexpr csubstr min_value_bin() noexcept { return csubstr(\"10000000\"); }\n    static constexpr csubstr max_value_dec() noexcept { return csubstr(\"127\"); }\n    static constexpr bool    is_oct_overflow(csubstr str) noexcept { return !((str.len < 3) || (str.len == 3 && str[0] <= '1')); }\n};\ntemplate<> struct charconv_digits_<1u, false> // uint8_t\n{\n    enum : size_t {\n        maxdigits_bin       = 2 + 8, // 255 0b11111111\n        maxdigits_oct       = 2 + 3, // 255 0o377\n        maxdigits_dec       =     3, // 255\n        maxdigits_hex       = 2 + 2, // 255 0xff\n        maxdigits_bin_nopfx =     8, // 255 0b11111111\n        maxdigits_oct_nopfx =     3, // 255 0o377\n        maxdigits_dec_nopfx =     3, // 255\n        maxdigits_hex_nopfx =     2, // 255 0xff\n    };\n    static constexpr csubstr max_value_dec() noexcept { return csubstr(\"255\"); }\n    static constexpr bool    is_oct_overflow(csubstr str) noexcept { return !((str.len < 3) || (str.len == 3 && str[0] <= '3')); }\n};\ntemplate<> struct charconv_digits_<2u, true> // int16_t\n{\n    enum : size_t {\n        maxdigits_bin       = 1 + 2 + 16, // -32768 -0b1000000000000000\n        maxdigits_oct       = 1 + 2 +  6, // -32768 -0o100000\n        maxdigits_dec       = 1     +  5, // -32768 -32768\n        maxdigits_hex       = 1 + 2 +  4, // -32768 -0x8000\n        maxdigits_bin_nopfx =         16, // -32768 -0b1000000000000000\n        maxdigits_oct_nopfx =          6, // -32768 -0o100000\n        maxdigits_dec_nopfx =          5, // -32768 -32768\n        maxdigits_hex_nopfx =          4, // -32768 -0x8000\n    };\n    // min values without sign!\n    static constexpr csubstr min_value_dec() noexcept { return csubstr(\"32768\"); }\n    static constexpr csubstr min_value_hex() noexcept { return csubstr(\"8000\"); }\n    static constexpr csubstr min_value_oct() noexcept { return csubstr(\"100000\"); }\n    static constexpr csubstr min_value_bin() noexcept { return csubstr(\"1000000000000000\"); }\n    static constexpr csubstr max_value_dec() noexcept { return csubstr(\"32767\"); }\n    static constexpr bool    is_oct_overflow(csubstr str) noexcept { return !((str.len < 6)); }\n};\ntemplate<> struct charconv_digits_<2u, false> // uint16_t\n{\n    enum : size_t {\n        maxdigits_bin       = 2 + 16, // 65535 0b1111111111111111\n        maxdigits_oct       = 2 +  6, // 65535 0o177777\n        maxdigits_dec       =      6, // 65535 65535\n        maxdigits_hex       = 2 +  4, // 65535 0xffff\n        maxdigits_bin_nopfx =     16, // 65535 0b1111111111111111\n        maxdigits_oct_nopfx =      6, // 65535 0o177777\n        maxdigits_dec_nopfx =      6, // 65535 65535\n        maxdigits_hex_nopfx =      4, // 65535 0xffff\n    };\n    static constexpr csubstr max_value_dec() noexcept { return csubstr(\"65535\"); }\n    static constexpr bool    is_oct_overflow(csubstr str) noexcept { return !((str.len < 6) || (str.len == 6 && str[0] <= '1')); }\n};\ntemplate<> struct charconv_digits_<4u, true> // int32_t\n{\n    enum : size_t {\n        maxdigits_bin       = 1 + 2 + 32, // len=35: -2147483648 -0b10000000000000000000000000000000\n        maxdigits_oct       = 1 + 2 + 11, // len=14: -2147483648 -0o20000000000\n        maxdigits_dec       = 1     + 10, // len=11: -2147483648 -2147483648\n        maxdigits_hex       = 1 + 2 +  8, // len=11: -2147483648 -0x80000000\n        maxdigits_bin_nopfx =         32, // len=35: -2147483648 -0b10000000000000000000000000000000\n        maxdigits_oct_nopfx =         11, // len=14: -2147483648 -0o20000000000\n        maxdigits_dec_nopfx =         10, // len=11: -2147483648 -2147483648\n        maxdigits_hex_nopfx =          8, // len=11: -2147483648 -0x80000000\n    };\n    // min values without sign!\n    static constexpr csubstr min_value_dec() noexcept { return csubstr(\"2147483648\"); }\n    static constexpr csubstr min_value_hex() noexcept { return csubstr(\"80000000\"); }\n    static constexpr csubstr min_value_oct() noexcept { return csubstr(\"20000000000\"); }\n    static constexpr csubstr min_value_bin() noexcept { return csubstr(\"10000000000000000000000000000000\"); }\n    static constexpr csubstr max_value_dec() noexcept { return csubstr(\"2147483647\"); }\n    static constexpr bool    is_oct_overflow(csubstr str) noexcept { return !((str.len < 11) || (str.len == 11 && str[0] <= '1')); }\n};\ntemplate<> struct charconv_digits_<4u, false> // uint32_t\n{\n    enum : size_t {\n        maxdigits_bin       = 2 + 32, // len=34: 4294967295 0b11111111111111111111111111111111\n        maxdigits_oct       = 2 + 11, // len=13: 4294967295 0o37777777777\n        maxdigits_dec       =     10, // len=10: 4294967295 4294967295\n        maxdigits_hex       = 2 +  8, // len=10: 4294967295 0xffffffff\n        maxdigits_bin_nopfx =     32, // len=34: 4294967295 0b11111111111111111111111111111111\n        maxdigits_oct_nopfx =     11, // len=13: 4294967295 0o37777777777\n        maxdigits_dec_nopfx =     10, // len=10: 4294967295 4294967295\n        maxdigits_hex_nopfx =      8, // len=10: 4294967295 0xffffffff\n    };\n    static constexpr csubstr max_value_dec() noexcept { return csubstr(\"4294967295\"); }\n    static constexpr bool is_oct_overflow(csubstr str) noexcept { return !((str.len < 11) || (str.len == 11 && str[0] <= '3')); }\n};\ntemplate<> struct charconv_digits_<8u, true> // int32_t\n{\n    enum : size_t {\n        maxdigits_bin       = 1 + 2 + 64, // len=67: -9223372036854775808 -0b1000000000000000000000000000000000000000000000000000000000000000\n        maxdigits_oct       = 1 + 2 + 22, // len=25: -9223372036854775808 -0o1000000000000000000000\n        maxdigits_dec       = 1     + 19, // len=20: -9223372036854775808 -9223372036854775808\n        maxdigits_hex       = 1 + 2 + 16, // len=19: -9223372036854775808 -0x8000000000000000\n        maxdigits_bin_nopfx =         64, // len=67: -9223372036854775808 -0b1000000000000000000000000000000000000000000000000000000000000000\n        maxdigits_oct_nopfx =         22, // len=25: -9223372036854775808 -0o1000000000000000000000\n        maxdigits_dec_nopfx =         19, // len=20: -9223372036854775808 -9223372036854775808\n        maxdigits_hex_nopfx =         16, // len=19: -9223372036854775808 -0x8000000000000000\n    };\n    static constexpr csubstr min_value_dec() noexcept { return csubstr(\"9223372036854775808\"); }\n    static constexpr csubstr min_value_hex() noexcept { return csubstr(\"8000000000000000\"); }\n    static constexpr csubstr min_value_oct() noexcept { return csubstr(\"1000000000000000000000\"); }\n    static constexpr csubstr min_value_bin() noexcept { return csubstr(\"1000000000000000000000000000000000000000000000000000000000000000\"); }\n    static constexpr csubstr max_value_dec() noexcept { return csubstr(\"9223372036854775807\"); }\n    static constexpr bool    is_oct_overflow(csubstr str) noexcept { return !((str.len < 22)); }\n};\ntemplate<> struct charconv_digits_<8u, false>\n{\n    enum : size_t {\n        maxdigits_bin       = 2 + 64, // len=66: 18446744073709551615 0b1111111111111111111111111111111111111111111111111111111111111111\n        maxdigits_oct       = 2 + 22, // len=24: 18446744073709551615 0o1777777777777777777777\n        maxdigits_dec       =     20, // len=20: 18446744073709551615 18446744073709551615\n        maxdigits_hex       = 2 + 16, // len=18: 18446744073709551615 0xffffffffffffffff\n        maxdigits_bin_nopfx =     64, // len=66: 18446744073709551615 0b1111111111111111111111111111111111111111111111111111111111111111\n        maxdigits_oct_nopfx =     22, // len=24: 18446744073709551615 0o1777777777777777777777\n        maxdigits_dec_nopfx =     20, // len=20: 18446744073709551615 18446744073709551615\n        maxdigits_hex_nopfx =     16, // len=18: 18446744073709551615 0xffffffffffffffff\n    };\n    static constexpr csubstr max_value_dec() noexcept { return csubstr(\"18446744073709551615\"); }\n    static constexpr bool    is_oct_overflow(csubstr str) noexcept { return !((str.len < 22) || (str.len == 22 && str[0] <= '1')); }\n};\n} // namespace detail\n\n// Helper macros, undefined below\n#define _c4append(c) { if(C4_LIKELY(pos < buf.len)) { buf.str[pos++] = static_cast<char>(c); } else { ++pos; } }\n#define _c4appendhex(i) { if(C4_LIKELY(pos < buf.len)) { buf.str[pos++] = hexchars[i]; } else { ++pos; } }\n\n/** @endcond */\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n\n/** @defgroup doc_digits Get number of digits\n *\n * @note At first sight this code may look heavily branchy and\n * therefore inefficient. However, measurements revealed this to be\n * the fastest among the alternatives.\n *\n * @see https://github.com/biojppm/c4core/pull/77\n *\n * @{\n */\n\n/** decimal digits for 8 bit integers */\ntemplate<class T>\nC4_CONSTEXPR14 C4_ALWAYS_INLINE\nauto digits_dec(T v) noexcept\n    -> typename std::enable_if<sizeof(T) == 1u, unsigned>::type\n{\n    C4_STATIC_ASSERT(std::is_integral<T>::value);\n    C4_ASSERT(v >= 0);\n    return ((v >= 100) ? 3u : ((v >= 10) ? 2u : 1u));\n}\n\n/** decimal digits for 16 bit integers */\ntemplate<class T>\nC4_CONSTEXPR14 C4_ALWAYS_INLINE\nauto digits_dec(T v) noexcept\n    -> typename std::enable_if<sizeof(T) == 2u, unsigned>::type\n{\n    C4_STATIC_ASSERT(std::is_integral<T>::value);\n    C4_ASSERT(v >= 0);\n    return ((v >= 10000) ? 5u : (v >= 1000) ? 4u : (v >= 100) ? 3u : (v >= 10) ? 2u : 1u);\n}\n\n/** decimal digits for 32 bit integers */\ntemplate<class T>\nC4_CONSTEXPR14 C4_ALWAYS_INLINE\nauto digits_dec(T v) noexcept\n    -> typename std::enable_if<sizeof(T) == 4u, unsigned>::type\n{\n    C4_STATIC_ASSERT(std::is_integral<T>::value);\n    C4_ASSERT(v >= 0);\n    return ((v >= 1000000000) ? 10u : (v >= 100000000) ? 9u : (v >= 10000000) ? 8u :\n            (v >= 1000000) ? 7u : (v >= 100000) ? 6u : (v >= 10000) ? 5u :\n            (v >= 1000) ? 4u : (v >= 100) ? 3u : (v >= 10) ? 2u : 1u);\n}\n\n/** decimal digits for 64 bit integers */\ntemplate<class T>\nC4_CONSTEXPR14 C4_ALWAYS_INLINE\nauto digits_dec(T v) noexcept\n    -> typename std::enable_if<sizeof(T) == 8u, unsigned>::type\n{\n    // thanks @fargies!!!\n    // https://github.com/biojppm/c4core/pull/77#issuecomment-1063753568\n    C4_STATIC_ASSERT(std::is_integral<T>::value);\n    C4_ASSERT(v >= 0);\n    if(v >= 1000000000) // 10\n    {\n        if(v >= 100000000000000) // 15 [15-20] range\n        {\n            if(v >= 100000000000000000) // 18 (15 + (20 - 15) / 2)\n            {\n                if((typename std::make_unsigned<T>::type)v >= 10000000000000000000u) // 20\n                    return 20u;\n                else\n                    return (v >= 1000000000000000000) ? 19u : 18u;\n            }\n            else if(v >= 10000000000000000) // 17\n                return 17u;\n            else\n                return(v >= 1000000000000000) ? 16u : 15u;\n        }\n        else if(v >= 1000000000000) // 13\n            return (v >= 10000000000000) ? 14u : 13u;\n        else if(v >= 100000000000) // 12\n            return 12;\n        else\n            return(v >= 10000000000) ? 11u : 10u;\n    }\n    else if(v >= 10000) // 5 [5-9] range\n    {\n        if(v >= 10000000) // 8\n            return (v >= 100000000) ? 9u : 8u;\n        else if(v >= 1000000) // 7\n            return 7;\n        else\n            return (v >= 100000) ? 6u : 5u;\n    }\n    else if(v >= 100)\n        return (v >= 1000) ? 4u : 3u;\n    else\n        return (v >= 10) ? 2u : 1u;\n}\n\n\n/** return the number of digits required to encode an hexadecimal number. */\ntemplate<class T>\nC4_CONSTEXPR14 C4_ALWAYS_INLINE unsigned digits_hex(T v) noexcept\n{\n    C4_STATIC_ASSERT(std::is_integral<T>::value);\n    C4_ASSERT(v >= 0);\n    return v ? 1u + (msb((typename std::make_unsigned<T>::type)v) >> 2u) : 1u;\n}\n\n/** return the number of digits required to encode a binary number. */\ntemplate<class T>\nC4_CONSTEXPR14 C4_ALWAYS_INLINE unsigned digits_bin(T v) noexcept\n{\n    C4_STATIC_ASSERT(std::is_integral<T>::value);\n    C4_ASSERT(v >= 0);\n    return v ? 1u + msb((typename std::make_unsigned<T>::type)v) : 1u;\n}\n\n/** return the number of digits required to encode an octal number. */\ntemplate<class T>\nC4_CONSTEXPR14 C4_ALWAYS_INLINE unsigned digits_oct(T v_) noexcept\n{\n    // TODO: is there a better way?\n    C4_STATIC_ASSERT(std::is_integral<T>::value);\n    C4_ASSERT(v_ >= 0);\n    using U = typename\n        std::conditional<sizeof(T) <= sizeof(unsigned),\n                         unsigned,\n                         typename std::make_unsigned<T>::type>::type;\n    U v = (U) v_;  // safe because we require v_ >= 0\n    unsigned __n = 1;\n    const unsigned __b2 = 64u;\n    const unsigned __b3 = __b2 * 8u;\n    const unsigned long __b4 = __b3 * 8u;\n    while(true)\n\t{\n        if(v < 8u)\n            return __n;\n        if(v < __b2)\n            return __n + 1;\n        if(v < __b3)\n            return __n + 2;\n        if(v < __b4)\n            return __n + 3;\n        v /= (U) __b4;\n        __n += 4;\n\t}\n}\n\n/** @} */\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n/** @cond dev */\nnamespace detail {\nC4_INLINE_CONSTEXPR const char hexchars[] = \"0123456789abcdef\";\nC4_INLINE_CONSTEXPR const char digits0099[] =\n    \"0001020304050607080910111213141516171819\"\n    \"2021222324252627282930313233343536373839\"\n    \"4041424344454647484950515253545556575859\"\n    \"6061626364656667686970717273747576777879\"\n    \"8081828384858687888990919293949596979899\";\n} // namespace detail\n/** @endcond */\n\nC4_SUPPRESS_WARNING_GCC_PUSH\nC4_SUPPRESS_WARNING_GCC(\"-Warray-bounds\")  // gcc has false positives here\n#if (defined(__GNUC__) && (__GNUC__ >= 7))\nC4_SUPPRESS_WARNING_GCC(\"-Wstringop-overflow\")  // gcc has false positives here\n#endif\n\n/** @defgroup doc_write_unchecked Write with known number of digits\n *\n * Writes a value without checking the buffer length with regards to\n * the required number of digits to encode the value. It is the\n * responsibility of the caller to ensure that the provided number of\n * digits is enough to write the given value. Notwithstanding the\n * name, assertions are liberally performed, so this code is safe.\n *\n * @{ */\n\ntemplate<class T>\nC4_HOT C4_ALWAYS_INLINE\nvoid write_dec_unchecked(substr buf, T v, unsigned digits_v) noexcept\n{\n    C4_STATIC_ASSERT(std::is_integral<T>::value);\n    C4_ASSERT(v >= 0);\n    C4_ASSERT(buf.len >= digits_v);\n    C4_XASSERT(digits_v == digits_dec(v));\n    // in bm_xtoa: checkoncelog_singlediv_write2\n    while(v >= T(100))\n    {\n        T quo = v;\n        quo /= T(100);\n        const auto num = (v - quo * T(100)) << 1u;\n        v = quo;\n        buf.str[--digits_v] = detail::digits0099[num + 1];\n        buf.str[--digits_v] = detail::digits0099[num];\n    }\n    if(v >= T(10))\n    {\n        C4_ASSERT(digits_v == 2);\n        const auto num = v << 1u;\n        buf.str[1] = detail::digits0099[num + 1];\n        buf.str[0] = detail::digits0099[num];\n    }\n    else\n    {\n        C4_ASSERT(digits_v == 1);\n        buf.str[0] = (char)('0' + v);\n    }\n}\n\n\ntemplate<class T>\nC4_HOT C4_ALWAYS_INLINE\nvoid write_hex_unchecked(substr buf, T v, unsigned digits_v) noexcept\n{\n    C4_STATIC_ASSERT(std::is_integral<T>::value);\n    C4_ASSERT(v >= 0);\n    C4_ASSERT(buf.len >= digits_v);\n    C4_XASSERT(digits_v == digits_hex(v));\n    do {\n        buf.str[--digits_v] = detail::hexchars[v & T(15)];\n        v >>= 4;\n    } while(v);\n    C4_ASSERT(digits_v == 0);\n}\n\n\ntemplate<class T>\nC4_HOT C4_ALWAYS_INLINE\nvoid write_oct_unchecked(substr buf, T v, unsigned digits_v) noexcept\n{\n    C4_STATIC_ASSERT(std::is_integral<T>::value);\n    C4_ASSERT(v >= 0);\n    C4_ASSERT(buf.len >= digits_v);\n    C4_XASSERT(digits_v == digits_oct(v));\n    do {\n        buf.str[--digits_v] = (char)('0' + (v & T(7)));\n        v >>= 3;\n    } while(v);\n    C4_ASSERT(digits_v == 0);\n}\n\n\ntemplate<class T>\nC4_HOT C4_ALWAYS_INLINE\nvoid write_bin_unchecked(substr buf, T v, unsigned digits_v) noexcept\n{\n    C4_STATIC_ASSERT(std::is_integral<T>::value);\n    C4_ASSERT(v >= 0);\n    C4_ASSERT(buf.len >= digits_v);\n    C4_XASSERT(digits_v == digits_bin(v));\n    do {\n        buf.str[--digits_v] = (char)('0' + (v & T(1)));\n        v >>= 1;\n    } while(v);\n    C4_ASSERT(digits_v == 0);\n}\n\n/** @} */ // write_unchecked\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n/** @defgroup doc_write Write a value\n *\n * Writes a value without checking the buffer length\n * decimal number -- but asserting.\n *\n * @{ */\n\n/** write an integer to a string in decimal format. This is the\n * lowest level (and the fastest) function to do this task.\n * @note does not accept negative numbers\n * @note the resulting string is NOT zero-terminated.\n * @note it is ok to call this with an empty or too-small buffer;\n * no writes will occur, and the required size will be returned\n * @return the number of characters required for the buffer. */\ntemplate<class T>\nC4_ALWAYS_INLINE size_t write_dec(substr buf, T v) noexcept\n{\n    C4_STATIC_ASSERT(std::is_integral<T>::value);\n    C4_ASSERT(v >= 0);\n    unsigned digits = digits_dec(v);\n    if(C4_LIKELY(buf.len >= digits))\n        write_dec_unchecked(buf, v, digits);\n    return digits;\n}\n\n/** write an integer to a string in hexadecimal format. This is the\n * lowest level (and the fastest) function to do this task.\n * @note does not accept negative numbers\n * @note does not prefix with 0x\n * @note the resulting string is NOT zero-terminated.\n * @note it is ok to call this with an empty or too-small buffer;\n * no writes will occur, and the required size will be returned\n * @return the number of characters required for the buffer. */\ntemplate<class T>\nC4_ALWAYS_INLINE size_t write_hex(substr buf, T v) noexcept\n{\n    C4_STATIC_ASSERT(std::is_integral<T>::value);\n    C4_ASSERT(v >= 0);\n    unsigned digits = digits_hex(v);\n    if(C4_LIKELY(buf.len >= digits))\n        write_hex_unchecked(buf, v, digits);\n    return digits;\n}\n\n/** write an integer to a string in octal format. This is the\n * lowest level (and the fastest) function to do this task.\n * @note does not accept negative numbers\n * @note does not prefix with 0o\n * @note the resulting string is NOT zero-terminated.\n * @note it is ok to call this with an empty or too-small buffer;\n * no writes will occur, and the required size will be returned\n * @return the number of characters required for the buffer. */\ntemplate<class T>\nC4_ALWAYS_INLINE size_t write_oct(substr buf, T v) noexcept\n{\n    C4_STATIC_ASSERT(std::is_integral<T>::value);\n    C4_ASSERT(v >= 0);\n    unsigned digits = digits_oct(v);\n    if(C4_LIKELY(buf.len >= digits))\n        write_oct_unchecked(buf, v, digits);\n    return digits;\n}\n\n/** write an integer to a string in binary format. This is the\n * lowest level (and the fastest) function to do this task.\n * @note does not accept negative numbers\n * @note does not prefix with 0b\n * @note the resulting string is NOT zero-terminated.\n * @note it is ok to call this with an empty or too-small buffer;\n * no writes will occur, and the required size will be returned\n * @return the number of characters required for the buffer. */\ntemplate<class T>\nC4_ALWAYS_INLINE size_t write_bin(substr buf, T v) noexcept\n{\n    C4_STATIC_ASSERT(std::is_integral<T>::value);\n    C4_ASSERT(v >= 0);\n    unsigned digits = digits_bin(v);\n    C4_ASSERT(digits > 0);\n    if(C4_LIKELY(buf.len >= digits))\n        write_bin_unchecked(buf, v, digits);\n    return digits;\n}\n\n\n/** @cond dev */\nnamespace detail {\ntemplate<class U> using NumberWriter = size_t (*)(substr, U);\ntemplate<class T, NumberWriter<T> writer>\nsize_t write_num_digits(substr buf, T v, size_t num_digits) noexcept\n{\n    C4_STATIC_ASSERT(std::is_integral<T>::value);\n    size_t ret = writer(buf, v);\n    if(ret >= num_digits)\n        return ret;\n    else if(ret >= buf.len || num_digits > buf.len)\n        return num_digits;\n    C4_ASSERT(num_digits >= ret);\n    size_t delta = static_cast<size_t>(num_digits - ret);\n    memmove(buf.str + delta, buf.str, ret);\n    memset(buf.str, '0', delta);\n    return num_digits;\n}\n} // namespace detail\n/** @endcond */\n\n\n/** same as c4::write_dec(), but pad with zeroes on the left\n * such that the resulting string is @p num_digits wide.\n * If the given number is requires more than num_digits, then the number prevails. */\ntemplate<class T>\nC4_ALWAYS_INLINE size_t write_dec(substr buf, T val, size_t num_digits) noexcept\n{\n    return detail::write_num_digits<T, &write_dec<T>>(buf, val, num_digits);\n}\n\n/** same as c4::write_hex(), but pad with zeroes on the left\n * such that the resulting string is @p num_digits wide.\n * If the given number is requires more than num_digits, then the number prevails. */\ntemplate<class T>\nC4_ALWAYS_INLINE size_t write_hex(substr buf, T val, size_t num_digits) noexcept\n{\n    return detail::write_num_digits<T, &write_hex<T>>(buf, val, num_digits);\n}\n\n/** same as c4::write_bin(), but pad with zeroes on the left\n * such that the resulting string is @p num_digits wide.\n * If the given number is requires more than num_digits, then the number prevails. */\ntemplate<class T>\nC4_ALWAYS_INLINE size_t write_bin(substr buf, T val, size_t num_digits) noexcept\n{\n    return detail::write_num_digits<T, &write_bin<T>>(buf, val, num_digits);\n}\n\n/** same as c4::write_oct(), but pad with zeroes on the left\n * such that the resulting string is @p num_digits wide.\n * If the given number is requires more than num_digits, then the number prevails. */\ntemplate<class T>\nC4_ALWAYS_INLINE size_t write_oct(substr buf, T val, size_t num_digits) noexcept\n{\n    return detail::write_num_digits<T, &write_oct<T>>(buf, val, num_digits);\n}\n\n/** @} */ // write\n\nC4_SUPPRESS_WARNING_GCC_POP\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n\nC4_SUPPRESS_WARNING_MSVC_PUSH\nC4_SUPPRESS_WARNING_MSVC(4365) // '=': conversion from 'int' to 'I', signed/unsigned mismatch\n\n/** @defgroup doc_read Read a value\n *\n * @{ */\n\n/** read a decimal integer from a string. This is the\n * lowest level (and the fastest) function to do this task.\n * @note does not accept negative numbers\n * @note The string must be trimmed. Whitespace is not accepted.\n * @note the string must not be empty\n * @note there is no check for overflow; the value wraps around\n * in a way similar to the standard C/C++ overflow behavior.\n * For example, `read_dec<int8_t>(\"128\", &val)` returns true\n * and val will be set to 0 because 127 is the max i8 value.\n * @see overflows<T>() to find out if a number string overflows a type range\n * @return true if the conversion was successful (no overflow check) */\ntemplate<class I>\nC4_NO_UBSAN_IOVRFLW\nC4_ALWAYS_INLINE bool read_dec(csubstr s, I *C4_RESTRICT v) noexcept\n{\n    C4_STATIC_ASSERT(std::is_integral<I>::value);\n    C4_ASSERT(!s.empty());\n    *v = 0;\n    for(char c : s)\n    {\n        if(C4_UNLIKELY(c < '0' || c > '9'))\n            return false;\n        *v = (*v) * I(10) + (I(c) - I('0'));\n    }\n    return true;\n}\n\n/** read an hexadecimal integer from a string. This is the\n * lowest level (and the fastest) function to do this task.\n * @note does not accept negative numbers\n * @note does not accept leading 0x or 0X\n * @note the string must not be empty\n * @note the string must be trimmed. Whitespace is not accepted.\n * @note there is no check for overflow; the value wraps around\n * in a way similar to the standard C/C++ overflow behavior.\n * For example, `read_hex<int8_t>(\"80\", &val)` returns true\n * and val will be set to 0 because 7f is the max i8 value.\n * @see overflows<T>() to find out if a number string overflows a type range\n * @return true if the conversion was successful (no overflow check) */\ntemplate<class I>\nC4_NO_UBSAN_IOVRFLW\nC4_ALWAYS_INLINE bool read_hex(csubstr s, I *C4_RESTRICT v) noexcept\n{\n    C4_STATIC_ASSERT(std::is_integral<I>::value);\n    C4_ASSERT(!s.empty());\n    *v = 0;\n    for(char c : s)\n    {\n        I cv;\n        if(c >= '0' && c <= '9')\n            cv = I(c) - I('0');\n        else if(c >= 'a' && c <= 'f')\n            cv = I(10) + (I(c) - I('a'));\n        else if(c >= 'A' && c <= 'F')\n            cv = I(10) + (I(c) - I('A'));\n        else\n            return false;\n        *v = (*v) * I(16) + cv;\n    }\n    return true;\n}\n\n/** read a binary integer from a string. This is the\n * lowest level (and the fastest) function to do this task.\n * @note does not accept negative numbers\n * @note does not accept leading 0b or 0B\n * @note the string must not be empty\n * @note the string must be trimmed. Whitespace is not accepted.\n * @note there is no check for overflow; the value wraps around\n * in a way similar to the standard C/C++ overflow behavior.\n * For example, `read_bin<int8_t>(\"10000000\", &val)` returns true\n * and val will be set to 0 because 1111111 is the max i8 value.\n * @see overflows<T>() to find out if a number string overflows a type range\n * @return true if the conversion was successful (no overflow check) */\ntemplate<class I>\nC4_NO_UBSAN_IOVRFLW\nC4_ALWAYS_INLINE bool read_bin(csubstr s, I *C4_RESTRICT v) noexcept\n{\n    C4_STATIC_ASSERT(std::is_integral<I>::value);\n    C4_ASSERT(!s.empty());\n    *v = 0;\n    for(char c : s)\n    {\n        *v <<= 1;\n        if(c == '1')\n            *v |= 1;\n        else if(c != '0')\n            return false;\n    }\n    return true;\n}\n\n/** read an octal integer from a string. This is the\n * lowest level (and the fastest) function to do this task.\n * @note does not accept negative numbers\n * @note does not accept leading 0o or 0O\n * @note the string must not be empty\n * @note the string must be trimmed. Whitespace is not accepted.\n * @note there is no check for overflow; the value wraps around\n * in a way similar to the standard C/C++ overflow behavior.\n * For example, `read_oct<int8_t>(\"200\", &val)` returns true\n * and val will be set to 0 because 177 is the max i8 value.\n * @see overflows<T>() to find out if a number string overflows a type range\n * @return true if the conversion was successful (no overflow check) */\ntemplate<class I>\nC4_NO_UBSAN_IOVRFLW\nC4_ALWAYS_INLINE bool read_oct(csubstr s, I *C4_RESTRICT v) noexcept\n{\n    C4_STATIC_ASSERT(std::is_integral<I>::value);\n    C4_ASSERT(!s.empty());\n    *v = 0;\n    for(char c : s)\n    {\n        if(C4_UNLIKELY(c < '0' || c > '7'))\n            return false;\n        *v = (*v) * I(8) + (I(c) - I('0'));\n    }\n    return true;\n}\n\n/** @} */\n\nC4_SUPPRESS_WARNING_MSVC_POP\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\nC4_SUPPRESS_WARNING_GCC_WITH_PUSH(\"-Wswitch-default\")\n\n/** @cond dev */\nnamespace detail {\ninline size_t _itoa2buf(substr buf, size_t pos, csubstr val) noexcept\n{\n    C4_ASSERT(pos + val.len <= buf.len);\n    memcpy(buf.str + pos, val.str, val.len);\n    return pos + val.len;\n}\ninline size_t _itoa2bufwithdigits(substr buf, size_t pos, size_t num_digits, csubstr val) noexcept\n{\n    num_digits = num_digits > val.len ? num_digits - val.len : 0;\n    C4_ASSERT(num_digits + val.len <= buf.len);\n    for(size_t i = 0; i < num_digits; ++i)\n        _c4append('0');\n    return detail::_itoa2buf(buf, pos, val);\n}\ntemplate<class I>\nC4_NO_INLINE size_t _itoadec2buf(substr buf) noexcept\n{\n    using digits_type = detail::charconv_digits<I>;\n    if(C4_UNLIKELY(buf.len < digits_type::maxdigits_dec))\n        return digits_type::maxdigits_dec;\n    buf.str[0] = '-';\n    return detail::_itoa2buf(buf, 1, digits_type::min_value_dec());\n}\ntemplate<class I>\nC4_NO_INLINE size_t _itoa2buf(substr buf, I radix) noexcept\n{\n    using digits_type = detail::charconv_digits<I>;\n    size_t pos = 0;\n    if(C4_LIKELY(buf.len > 0))\n        buf.str[pos++] = '-';\n    switch(radix)\n    {\n    case I(10):\n        if(C4_UNLIKELY(buf.len < digits_type::maxdigits_dec))\n            return digits_type::maxdigits_dec;\n        pos =_itoa2buf(buf, pos, digits_type::min_value_dec());\n        break;\n    case I(16):\n        if(C4_UNLIKELY(buf.len < digits_type::maxdigits_hex))\n            return digits_type::maxdigits_hex;\n        buf.str[pos++] = '0';\n        buf.str[pos++] = 'x';\n        pos = _itoa2buf(buf, pos, digits_type::min_value_hex());\n        break;\n    case I( 2):\n        if(C4_UNLIKELY(buf.len < digits_type::maxdigits_bin))\n            return digits_type::maxdigits_bin;\n        buf.str[pos++] = '0';\n        buf.str[pos++] = 'b';\n        pos = _itoa2buf(buf, pos, digits_type::min_value_bin());\n        break;\n    case I( 8):\n        if(C4_UNLIKELY(buf.len < digits_type::maxdigits_oct))\n            return digits_type::maxdigits_oct;\n        buf.str[pos++] = '0';\n        buf.str[pos++] = 'o';\n        pos = _itoa2buf(buf, pos, digits_type::min_value_oct());\n        break;\n    }\n    return pos;\n}\ntemplate<class I>\nC4_NO_INLINE size_t _itoa2buf(substr buf, I radix, size_t num_digits) noexcept\n{\n    using digits_type = detail::charconv_digits<I>;\n    size_t pos = 0;\n    size_t needed_digits = 0;\n    if(C4_LIKELY(buf.len > 0))\n        buf.str[pos++] = '-';\n    switch(radix)\n    {\n    case I(10):\n        // add 1 to account for -\n        needed_digits = num_digits+1 > digits_type::maxdigits_dec ? num_digits+1 : digits_type::maxdigits_dec;\n        if(C4_UNLIKELY(buf.len < needed_digits))\n            return needed_digits;\n        pos = _itoa2bufwithdigits(buf, pos, num_digits, digits_type::min_value_dec());\n        break;\n    case I(16):\n        // add 3 to account for -0x\n        needed_digits = num_digits+3 > digits_type::maxdigits_hex ? num_digits+3 : digits_type::maxdigits_hex;\n        if(C4_UNLIKELY(buf.len < needed_digits))\n            return needed_digits;\n        buf.str[pos++] = '0';\n        buf.str[pos++] = 'x';\n        pos = _itoa2bufwithdigits(buf, pos, num_digits, digits_type::min_value_hex());\n        break;\n    case I(2):\n        // add 3 to account for -0b\n        needed_digits = num_digits+3 > digits_type::maxdigits_bin ? num_digits+3 : digits_type::maxdigits_bin;\n        if(C4_UNLIKELY(buf.len < needed_digits))\n            return needed_digits;\n        C4_ASSERT(buf.len >= digits_type::maxdigits_bin);\n        buf.str[pos++] = '0';\n        buf.str[pos++] = 'b';\n        pos = _itoa2bufwithdigits(buf, pos, num_digits, digits_type::min_value_bin());\n        break;\n    case I(8):\n        // add 3 to account for -0o\n        needed_digits = num_digits+3 > digits_type::maxdigits_oct ? num_digits+3 : digits_type::maxdigits_oct;\n        if(C4_UNLIKELY(buf.len < needed_digits))\n            return needed_digits;\n        C4_ASSERT(buf.len >= digits_type::maxdigits_oct);\n        buf.str[pos++] = '0';\n        buf.str[pos++] = 'o';\n        pos = _itoa2bufwithdigits(buf, pos, num_digits, digits_type::min_value_oct());\n        break;\n    }\n    return pos;\n}\n} // namespace detail\n/** @endcond */\n\n\n/** @defgroup doc_itoa itoa: signed to chars\n *\n * @{ */\n\n/** convert an integral signed decimal to a string.\n * @note the resulting string is NOT zero-terminated.\n * @note it is ok to call this with an empty or too-small buffer;\n * no writes will occur, and the needed size will be returned\n * @return the number of characters required for the buffer. */\ntemplate<class T>\nC4_ALWAYS_INLINE size_t itoa(substr buf, T v) noexcept\n{\n    C4_STATIC_ASSERT(std::is_signed<T>::value);\n    if(v >= T(0))\n    {\n        // write_dec() checks the buffer size, so no need to check here\n        return write_dec(buf, v);\n    }\n    // when T is the min value (eg i8: -128), negating it\n    // will overflow, so treat the min as a special case\n    else if(C4_LIKELY(v != std::numeric_limits<T>::min()))\n    {\n        v = -v;\n        unsigned digits = digits_dec(v);\n        if(C4_LIKELY(buf.len >= digits + 1u))\n        {\n            buf.str[0] = '-';\n            write_dec_unchecked(buf.sub(1), v, digits);\n        }\n        return digits + 1u;\n    }\n    return detail::_itoadec2buf<T>(buf);\n}\n\n/** convert an integral signed integer to a string, using a specific\n * radix. The radix must be 2, 8, 10 or 16.\n *\n * @note the resulting string is NOT zero-terminated.\n * @note it is ok to call this with an empty or too-small buffer;\n * no writes will occur, and the needed size will be returned\n * @return the number of characters required for the buffer. */\ntemplate<class T>\nC4_ALWAYS_INLINE size_t itoa(substr buf, T v, T radix) noexcept\n{\n    C4_STATIC_ASSERT(std::is_signed<T>::value);\n    C4_ASSERT(radix == 2 || radix == 8 || radix == 10 || radix == 16);\n    C4_SUPPRESS_WARNING_GCC_PUSH\n    #if (defined(__GNUC__) && (__GNUC__ >= 7))\n        C4_SUPPRESS_WARNING_GCC(\"-Wstringop-overflow\")  // gcc has a false positive here\n    #endif\n    // when T is the min value (eg i8: -128), negating it\n    // will overflow, so treat the min as a special case\n    if(C4_LIKELY(v != std::numeric_limits<T>::min()))\n    {\n        unsigned pos = 0;\n        if(v < 0)\n        {\n            v = -v;\n            if(C4_LIKELY(buf.len > 0))\n                buf.str[pos] = '-';\n            ++pos;\n        }\n        unsigned digits = 0;\n        switch(radix)\n        {\n        case T(10):\n            digits = digits_dec(v);\n            if(C4_LIKELY(buf.len >= pos + digits))\n                write_dec_unchecked(buf.sub(pos), v, digits);\n            break;\n        case T(16):\n            digits = digits_hex(v);\n            if(C4_LIKELY(buf.len >= pos + 2u + digits))\n            {\n                buf.str[pos + 0] = '0';\n                buf.str[pos + 1] = 'x';\n                write_hex_unchecked(buf.sub(pos + 2), v, digits);\n            }\n            digits += 2u;\n            break;\n        case T(2):\n            digits = digits_bin(v);\n            if(C4_LIKELY(buf.len >= pos + 2u + digits))\n            {\n                buf.str[pos + 0] = '0';\n                buf.str[pos + 1] = 'b';\n                write_bin_unchecked(buf.sub(pos + 2), v, digits);\n            }\n            digits += 2u;\n            break;\n        case T(8):\n            digits = digits_oct(v);\n            if(C4_LIKELY(buf.len >= pos + 2u + digits))\n            {\n                buf.str[pos + 0] = '0';\n                buf.str[pos + 1] = 'o';\n                write_oct_unchecked(buf.sub(pos + 2), v, digits);\n            }\n            digits += 2u;\n            break;\n        }\n        return pos + digits;\n    }\n    C4_SUPPRESS_WARNING_GCC_POP\n    // when T is the min value (eg i8: -128), negating it\n    // will overflow\n    return detail::_itoa2buf<T>(buf, radix);\n}\n\n\n/** same as c4::itoa(), but pad with zeroes on the left such that the\n * resulting string is @p num_digits wide, not accounting for radix\n * prefix (0x,0o,0b). The @p radix must be 2, 8, 10 or 16.\n *\n * @note the resulting string is NOT zero-terminated.\n * @note it is ok to call this with an empty or too-small buffer;\n * no writes will occur, and the needed size will be returned\n * @return the number of characters required for the buffer. */\ntemplate<class T>\nC4_ALWAYS_INLINE size_t itoa(substr buf, T v, T radix, size_t num_digits) noexcept\n{\n    C4_STATIC_ASSERT(std::is_signed<T>::value);\n    C4_ASSERT(radix == 2 || radix == 8 || radix == 10 || radix == 16);\n    C4_SUPPRESS_WARNING_GCC_PUSH\n    #if (defined(__GNUC__) && (__GNUC__ >= 7))\n        C4_SUPPRESS_WARNING_GCC(\"-Wstringop-overflow\")  // gcc has a false positive here\n    #endif\n    // when T is the min value (eg i8: -128), negating it\n    // will overflow, so treat the min as a special case\n    if(C4_LIKELY(v != std::numeric_limits<T>::min()))\n    {\n        unsigned pos = 0;\n        if(v < 0)\n        {\n            v = -v;\n            if(C4_LIKELY(buf.len > 0))\n                buf.str[pos] = '-';\n            ++pos;\n        }\n        unsigned total_digits = 0;\n        switch(radix)\n        {\n        case T(10):\n            total_digits = digits_dec(v);\n            total_digits = pos + (unsigned)(num_digits > total_digits ? num_digits : total_digits);\n            if(C4_LIKELY(buf.len >= total_digits))\n                write_dec(buf.sub(pos), v, num_digits);\n            break;\n        case T(16):\n            total_digits = digits_hex(v);\n            total_digits = pos + 2u + (unsigned)(num_digits > total_digits ? num_digits : total_digits);\n            if(C4_LIKELY(buf.len >= total_digits))\n            {\n                buf.str[pos + 0] = '0';\n                buf.str[pos + 1] = 'x';\n                write_hex(buf.sub(pos + 2), v, num_digits);\n            }\n            break;\n        case T(2):\n            total_digits = digits_bin(v);\n            total_digits = pos + 2u + (unsigned)(num_digits > total_digits ? num_digits : total_digits);\n            if(C4_LIKELY(buf.len >= total_digits))\n            {\n                buf.str[pos + 0] = '0';\n                buf.str[pos + 1] = 'b';\n                write_bin(buf.sub(pos + 2), v, num_digits);\n            }\n            break;\n        case T(8):\n            total_digits = digits_oct(v);\n            total_digits = pos + 2u + (unsigned)(num_digits > total_digits ? num_digits : total_digits);\n            if(C4_LIKELY(buf.len >= total_digits))\n            {\n                buf.str[pos + 0] = '0';\n                buf.str[pos + 1] = 'o';\n                write_oct(buf.sub(pos + 2), v, num_digits);\n            }\n            break;\n        }\n        return total_digits;\n    }\n    C4_SUPPRESS_WARNING_GCC_POP\n    // when T is the min value (eg i8: -128), negating it\n    // will overflow\n    return detail::_itoa2buf<T>(buf, radix, num_digits);\n}\n\n/** @} */\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n/** @defgroup doc_utoa utoa: unsigned to chars\n *\n * @{ */\n\n/** convert an integral unsigned decimal to a string.\n *\n * @note the resulting string is NOT zero-terminated.\n * @note it is ok to call this with an empty or too-small buffer;\n * no writes will occur, and the needed size will be returned\n * @return the number of characters required for the buffer. */\ntemplate<class T>\nC4_ALWAYS_INLINE size_t utoa(substr buf, T v) noexcept\n{\n    C4_STATIC_ASSERT(std::is_unsigned<T>::value);\n    // write_dec() does the buffer length check, so no need to check here\n    return write_dec(buf, v);\n}\n\n/** convert an integral unsigned integer to a string, using a specific\n * radix. The radix must be 2, 8, 10 or 16.\n *\n * @note the resulting string is NOT zero-terminated.\n * @note it is ok to call this with an empty or too-small buffer;\n * no writes will occur, and the needed size will be returned\n * @return the number of characters required for the buffer. */\ntemplate<class T>\nC4_ALWAYS_INLINE size_t utoa(substr buf, T v, T radix) noexcept\n{\n    C4_STATIC_ASSERT(std::is_unsigned<T>::value);\n    C4_ASSERT(radix == 10 || radix == 16 || radix == 2 || radix == 8);\n    unsigned digits = 0;\n    switch(radix)\n    {\n    case T(10):\n        digits = digits_dec(v);\n        if(C4_LIKELY(buf.len >= digits))\n            write_dec_unchecked(buf, v, digits);\n        break;\n    case T(16):\n        digits = digits_hex(v);\n        if(C4_LIKELY(buf.len >= digits+2u))\n        {\n            buf.str[0] = '0';\n            buf.str[1] = 'x';\n            write_hex_unchecked(buf.sub(2), v, digits);\n        }\n        digits += 2u;\n        break;\n    case T(2):\n        digits = digits_bin(v);\n        if(C4_LIKELY(buf.len >= digits+2u))\n        {\n            buf.str[0] = '0';\n            buf.str[1] = 'b';\n            write_bin_unchecked(buf.sub(2), v, digits);\n        }\n        digits += 2u;\n        break;\n    case T(8):\n        digits = digits_oct(v);\n        if(C4_LIKELY(buf.len >= digits+2u))\n        {\n            buf.str[0] = '0';\n            buf.str[1] = 'o';\n            write_oct_unchecked(buf.sub(2), v, digits);\n        }\n        digits += 2u;\n        break;\n    }\n    return digits;\n}\n\n/** same as c4::utoa(), but pad with zeroes on the left such that the\n * resulting string is @p num_digits wide. The @p radix must be 2,\n * 8, 10 or 16.\n *\n * @note the resulting string is NOT zero-terminated.\n * @note it is ok to call this with an empty or too-small buffer;\n * no writes will occur, and the needed size will be returned\n * @return the number of characters required for the buffer. */\ntemplate<class T>\nC4_ALWAYS_INLINE size_t utoa(substr buf, T v, T radix, size_t num_digits) noexcept\n{\n    C4_STATIC_ASSERT(std::is_unsigned<T>::value);\n    C4_ASSERT(radix == 10 || radix == 16 || radix == 2 || radix == 8);\n    unsigned total_digits = 0;\n    switch(radix)\n    {\n    case T(10):\n        total_digits = digits_dec(v);\n        total_digits = (unsigned)(num_digits > total_digits ? num_digits : total_digits);\n        if(C4_LIKELY(buf.len >= total_digits))\n            write_dec(buf, v, num_digits);\n        break;\n    case T(16):\n        total_digits = digits_hex(v);\n        total_digits = 2u + (unsigned)(num_digits > total_digits ? num_digits : total_digits);\n        if(C4_LIKELY(buf.len >= total_digits))\n        {\n            buf.str[0] = '0';\n            buf.str[1] = 'x';\n            write_hex(buf.sub(2), v, num_digits);\n        }\n        break;\n    case T(2):\n        total_digits = digits_bin(v);\n        total_digits = 2u + (unsigned)(num_digits > total_digits ? num_digits : total_digits);\n        if(C4_LIKELY(buf.len >= total_digits))\n        {\n            buf.str[0] = '0';\n            buf.str[1] = 'b';\n            write_bin(buf.sub(2), v, num_digits);\n        }\n        break;\n    case T(8):\n        total_digits = digits_oct(v);\n        total_digits = 2u + (unsigned)(num_digits > total_digits ? num_digits : total_digits);\n        if(C4_LIKELY(buf.len >= total_digits))\n        {\n            buf.str[0] = '0';\n            buf.str[1] = 'o';\n            write_oct(buf.sub(2), v, num_digits);\n        }\n        break;\n    }\n    return total_digits;\n}\nC4_SUPPRESS_WARNING_GCC_POP\n\n/** @} */\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n/** @defgroup doc_atoi atoi: chars to signed\n *\n * @{ */\n\n/** Convert a trimmed string to a signed integral value. The input\n * string can be formatted as decimal, binary (prefix 0b or 0B), octal\n * (prefix 0o or 0O) or hexadecimal (prefix 0x or 0X). Strings with\n * leading zeroes are considered as decimal and not octal (unlike the\n * C/C++ convention). Every character in the input string is read for\n * the conversion; the input string must not contain any leading or\n * trailing whitespace.\n *\n * @return true if the conversion was successful.\n *\n * @note a positive sign is not accepted. ie, the string must not\n * start with '+'\n *\n * @note overflow is not detected: the return status is true even if\n * the conversion would return a value outside of the type's range, in\n * which case the result will wrap around the type's range.  This is\n * similar to native behavior. See @ref doc_overflows and @ref\n * doc_overflow_checked for overflow checking utilities.\n *\n * @see atoi_first() if the string is not trimmed to the value to read. */\ntemplate<class T>\nC4_NO_UBSAN_IOVRFLW\nC4_ALWAYS_INLINE bool atoi(csubstr str, T * C4_RESTRICT v) noexcept\n{\n    C4_STATIC_ASSERT(std::is_integral<T>::value);\n    C4_STATIC_ASSERT(std::is_signed<T>::value);\n\n    if(C4_UNLIKELY(str.len == 0))\n        return false;\n\n    C4_ASSERT(str.str[0] != '+');\n\n    T sign = 1;\n    size_t start = 0;\n    if(str.str[0] == '-')\n    {\n        if(C4_UNLIKELY(str.len == ++start))\n            return false;\n        sign = -1;\n    }\n\n    bool parsed_ok = true;\n    if(str.str[start] != '0') // this should be the common case, so put it first\n    {\n        parsed_ok = read_dec(str.sub(start), v);\n    }\n    else if(str.len > start + 1)\n    {\n        // starts with 0: is it 0x, 0o, 0b?\n        const char pfx = str.str[start + 1];\n        if(pfx == 'x' || pfx == 'X')\n            parsed_ok = str.len > start + 2 && read_hex(str.sub(start + 2), v);\n        else if(pfx == 'b' || pfx == 'B')\n            parsed_ok = str.len > start + 2 && read_bin(str.sub(start + 2), v);\n        else if(pfx == 'o' || pfx == 'O')\n            parsed_ok = str.len > start + 2 && read_oct(str.sub(start + 2), v);\n        else\n            parsed_ok = read_dec(str.sub(start + 1), v);\n    }\n    else\n    {\n        parsed_ok = read_dec(str.sub(start), v);\n    }\n    if(C4_LIKELY(parsed_ok))\n        *v *= sign;\n    return parsed_ok;\n}\n\n\n/** Select the next range of characters in the string that can be parsed\n * as a signed integral value, and convert it using atoi(). Leading\n * whitespace (space, newline, tabs) is skipped.\n * @return the number of characters read for conversion, or csubstr::npos if the conversion failed\n * @see atoi() if the string is already trimmed to the value to read.\n * @see csubstr::first_int_span() */\ntemplate<class T>\nC4_ALWAYS_INLINE size_t atoi_first(csubstr str, T * C4_RESTRICT v)\n{\n    csubstr trimmed = str.first_int_span();\n    if(trimmed.len == 0)\n        return csubstr::npos;\n    if(atoi(trimmed, v))\n        return static_cast<size_t>(trimmed.end() - str.begin());\n    return csubstr::npos;\n}\n\n/** @} */\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n/** @defgroup doc_atou atou: chars to unsigned\n *\n * @{ */\n\n/** Convert a trimmed string to an unsigned integral value. The string can be\n * formatted as decimal, binary (prefix 0b or 0B), octal (prefix 0o or 0O)\n * or hexadecimal (prefix 0x or 0X). Every character in the input string is read\n * for the conversion; it must not contain any leading or trailing whitespace.\n *\n * @return true if the conversion was successful.\n *\n * @note overflow is not detected: the return status is true even if\n * the conversion would return a value outside of the type's range, in\n * which case the result will wrap around the type's range. See @ref\n * doc_overflows and @ref doc_overflow_checked for overflow checking\n * utilities.\n *\n * @note If the string has a minus character, the return status\n * will be false.\n *\n * @see atou_first() if the string is not trimmed to the value to read. */\ntemplate<class T>\nbool atou(csubstr str, T * C4_RESTRICT v) noexcept\n{\n    C4_STATIC_ASSERT(std::is_integral<T>::value);\n\n    if(C4_UNLIKELY(str.len == 0 || str.front() == '-'))\n        return false;\n\n    bool parsed_ok = true;\n    if(str.str[0] != '0')\n    {\n        parsed_ok = read_dec(str, v);\n    }\n    else\n    {\n        if(str.len > 1)\n        {\n            const char pfx = str.str[1];\n            if(pfx == 'x' || pfx == 'X')\n                parsed_ok = str.len > 2 && read_hex(str.sub(2), v);\n            else if(pfx == 'b' || pfx == 'B')\n                parsed_ok = str.len > 2 && read_bin(str.sub(2), v);\n            else if(pfx == 'o' || pfx == 'O')\n                parsed_ok = str.len > 2 && read_oct(str.sub(2), v);\n            else\n                parsed_ok = read_dec(str, v);\n        }\n        else\n        {\n            *v = 0; // we know the first character is 0\n        }\n    }\n    return parsed_ok;\n}\n\n\n/** Select the next range of characters in the string that can be parsed\n * as an unsigned integral value, and convert it using atou(). Leading\n * whitespace (space, newline, tabs) is skipped.\n * @return the number of characters read for conversion, or csubstr::npos if the conversion faileds\n * @see atou() if the string is already trimmed to the value to read.\n * @see csubstr::first_uint_span() */\ntemplate<class T>\nC4_ALWAYS_INLINE size_t atou_first(csubstr str, T *v)\n{\n    csubstr trimmed = str.first_uint_span();\n    if(trimmed.len == 0)\n        return csubstr::npos;\n    if(atou(trimmed, v))\n        return static_cast<size_t>(trimmed.end() - str.begin());\n    return csubstr::npos;\n}\n\n\n/** @} */\n\n#ifdef _MSC_VER\n#   pragma warning(pop)\n#elif defined(__clang__)\n#   pragma clang diagnostic pop\n#elif defined(__GNUC__)\n#   pragma GCC diagnostic pop\n#endif\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n/** @cond dev */\nnamespace detail {\ninline bool check_overflow(csubstr str, csubstr limit) noexcept\n{\n    if(str.len == limit.len)\n    {\n        for(size_t i = 0; i < limit.len; ++i)\n        {\n            if(str[i] < limit[i])\n                return false;\n            else if(str[i] > limit[i])\n                return true;\n        }\n        return false;\n    }\n    else\n        return str.len > limit.len;\n}\n} // namespace detail\n/** @endcond */\n\n\n/** @defgroup doc_overflows overflows: does a number string overflow a type\n *\n * @{ */\n\n/** Test if the following string would overflow when converted to\n * associated integral types; this function is dispatched with SFINAE\n * to handle differently signed and unsigned types.\n * @return true if number will overflow, false if it fits (or doesn't parse)\n * @see doc_overflow_checked for format specifiers to enforce no-overflow reads\n */\ntemplate<class T>\nauto overflows(csubstr str) noexcept\n    -> typename std::enable_if<std::is_unsigned<T>::value, bool>::type\n{\n    C4_STATIC_ASSERT(std::is_integral<T>::value);\n\n    if(C4_UNLIKELY(str.len == 0))\n    {\n        return false;\n    }\n    else if(str.str[0] == '0')\n    {\n        if (str.len == 1)\n            return false;\n        switch (str.str[1])\n        {\n            case 'x':\n            case 'X':\n            {\n                size_t fno = str.first_not_of('0', 2);\n                if (fno == csubstr::npos)\n                    return false;\n                return !(str.len <= fno + (sizeof(T) * 2));\n            }\n            case 'b':\n            case 'B':\n            {\n                size_t fno = str.first_not_of('0', 2);\n                if (fno == csubstr::npos)\n                    return false;\n                return !(str.len <= fno +(sizeof(T) * 8));\n            }\n            case 'o':\n            case 'O':\n            {\n                size_t fno = str.first_not_of('0', 2);\n                if(fno == csubstr::npos)\n                    return false;\n                return detail::charconv_digits<T>::is_oct_overflow(str.sub(fno));\n            }\n            default:\n            {\n                size_t fno = str.first_not_of('0', 1);\n                if(fno == csubstr::npos)\n                    return false;\n                return detail::check_overflow(str.sub(fno), detail::charconv_digits<T>::max_value_dec());\n            }\n        }\n    }\n    else if(C4_UNLIKELY(str[0] == '-'))\n    {\n        return true;\n    }\n    else\n    {\n        return detail::check_overflow(str, detail::charconv_digits<T>::max_value_dec());\n    }\n}\n\n\n/** Test if the following string would overflow when converted to\n * associated integral types; this function is dispatched with SFINAE\n * to handle differently signed and unsigned types.\n *\n * @return true if number will overflow, false if it fits (or doesn't parse)\n * @see doc_overflow_checked for format specifiers to enforce no-overflow reads\n */\ntemplate<class T>\nauto overflows(csubstr str)\n    -> typename std::enable_if<std::is_signed<T>::value, bool>::type\n{\n    C4_STATIC_ASSERT(std::is_integral<T>::value);\n    if(C4_UNLIKELY(str.len == 0))\n        return false;\n    if(str.str[0] == '-')\n    {\n        if(str.str[1] == '0')\n        {\n            if(str.len == 2)\n                return false;\n            switch(str.str[2])\n            {\n                case 'x':\n                case 'X':\n                {\n                    size_t fno = str.first_not_of('0', 3);\n                    if (fno == csubstr::npos)\n                        return false;\n                    return detail::check_overflow(str.sub(fno), detail::charconv_digits<T>::min_value_hex());\n                }\n                case 'b':\n                case 'B':\n                {\n                    size_t fno = str.first_not_of('0', 3);\n                    if (fno == csubstr::npos)\n                        return false;\n                    return detail::check_overflow(str.sub(fno), detail::charconv_digits<T>::min_value_bin());\n                }\n                case 'o':\n                case 'O':\n                {\n                    size_t fno = str.first_not_of('0', 3);\n                    if(fno == csubstr::npos)\n                        return false;\n                    return detail::check_overflow(str.sub(fno), detail::charconv_digits<T>::min_value_oct());\n                }\n                default:\n                {\n                    size_t fno = str.first_not_of('0', 2);\n                    if(fno == csubstr::npos)\n                        return false;\n                    return detail::check_overflow(str.sub(fno), detail::charconv_digits<T>::min_value_dec());\n                }\n            }\n        }\n        else\n            return detail::check_overflow(str.sub(1), detail::charconv_digits<T>::min_value_dec());\n    }\n    else if(str.str[0] == '0')\n    {\n        if (str.len == 1)\n            return false;\n        switch(str.str[1])\n        {\n            case 'x':\n            case 'X':\n            {\n                size_t fno = str.first_not_of('0', 2);\n                if (fno == csubstr::npos)\n                    return false;\n                const size_t len = str.len - fno;\n                return !((len < sizeof (T) * 2) || (len == sizeof(T) * 2 && str[fno] <= '7'));\n            }\n            case 'b':\n            case 'B':\n            {\n                size_t fno = str.first_not_of('0', 2);\n                if (fno == csubstr::npos)\n                    return false;\n                return !(str.len <= fno + (sizeof(T) * 8 - 1));\n            }\n            case 'o':\n            case 'O':\n            {\n                size_t fno = str.first_not_of('0', 2);\n                if(fno == csubstr::npos)\n                    return false;\n                return detail::charconv_digits<T>::is_oct_overflow(str.sub(fno));\n            }\n            default:\n            {\n                size_t fno = str.first_not_of('0', 1);\n                if(fno == csubstr::npos)\n                    return false;\n                return detail::check_overflow(str.sub(fno), detail::charconv_digits<T>::max_value_dec());\n            }\n        }\n    }\n    else\n        return detail::check_overflow(str, detail::charconv_digits<T>::max_value_dec());\n}\n\n/** @} */\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n/** @cond dev */\nnamespace detail {\n\n\n#if (!C4CORE_HAVE_STD_FROMCHARS)\n/** @see http://www.exploringbinary.com/ for many good examples on float-str conversion */\ntemplate<size_t N>\nvoid get_real_format_str(char (& C4_RESTRICT fmt)[N], int precision, RealFormat_e formatting, const char* length_modifier=\"\")\n{\n    int iret;\n    if(precision == -1)\n        iret = snprintf(fmt, sizeof(fmt), \"%%%s%c\", length_modifier, formatting);\n    else if(precision == 0)\n        iret = snprintf(fmt, sizeof(fmt), \"%%.%s%c\", length_modifier, formatting);\n    else\n        iret = snprintf(fmt, sizeof(fmt), \"%%.%d%s%c\", precision, length_modifier, formatting);\n    C4_ASSERT(iret >= 2 && size_t(iret) < sizeof(fmt));\n    C4_UNUSED(iret);\n}\n\n\n/** @todo we're depending on snprintf()/sscanf() for converting to/from\n * floating point numbers. Apparently, this increases the binary size\n * by a considerable amount. There are some lightweight printf\n * implementations:\n *\n * @see http://www.sparetimelabs.com/tinyprintf/tinyprintf.php (BSD)\n * @see https://github.com/weiss/c99-snprintf\n * @see https://github.com/nothings/stb/blob/master/stb_sprintf.h\n * @see http://www.exploringbinary.com/\n * @see https://blog.benoitblanchon.fr/lightweight-float-to-string/\n * @see http://www.ryanjuckett.com/programming/printing-floating-point-numbers/\n */\ntemplate<class T>\nsize_t print_one(substr str, const char* full_fmt, T v)\n{\n#ifdef _MSC_VER\n    /** use _snprintf() to prevent early termination of the output\n     * for writing the null character at the last position\n     * @see https://msdn.microsoft.com/en-us/library/2ts7cx93.aspx */\n    int iret = _snprintf(str.str, str.len, full_fmt, v);\n    if(iret < 0)\n    {\n        /* when buf.len is not enough, VS returns a negative value.\n         * so call it again with a negative value for getting an\n         * actual length of the string */\n        iret = snprintf(nullptr, 0, full_fmt, v);\n        C4_ASSERT(iret > 0);\n    }\n    size_t ret = (size_t) iret;\n    return ret;\n#else\n    int iret = snprintf(str.str, str.len, full_fmt, v);\n    C4_ASSERT(iret >= 0);\n    size_t ret = (size_t) iret;\n    if(ret >= str.len)\n        ++ret; /* snprintf() reserves the last character to write \\0 */\n    return ret;\n#endif\n}\n#endif // (!C4CORE_HAVE_STD_FROMCHARS)\n\n\n#if (!C4CORE_HAVE_STD_FROMCHARS) && (!C4CORE_HAVE_FAST_FLOAT)\n/** scans a string using the given type format, while at the same time\n * allowing non-null-terminated strings AND guaranteeing that the given\n * string length is strictly respected, so that no buffer overflows\n * might occur. */\ntemplate<typename T>\ninline size_t scan_one(csubstr str, const char *type_fmt, T *v)\n{\n    /* snscanf() is absolutely needed here as we must be sure that\n     * str.len is strictly respected, because substr is\n     * generally not null-terminated.\n     *\n     * Alas, there is no snscanf().\n     *\n     * So we fake it by using a dynamic format with an explicit\n     * field size set to the length of the given span.\n     * This trick is taken from:\n     * https://stackoverflow.com/a/18368910/5875572 */\n\n    /* this is the actual format we'll use for scanning */\n    char fmt[16];\n\n    /* write the length into it. Eg \"%12f\".\n     * Also, get the number of characters read from the string.\n     * So the final format ends up as \"%12f%n\"*/\n    int iret = std::snprintf(fmt, sizeof(fmt), \"%%\" \"%zu\" \"%s\" \"%%n\", str.len, type_fmt);\n    /* no nasty surprises, please! */\n    C4_ASSERT(iret >= 0 && size_t(iret) < C4_COUNTOF(fmt));\n\n    /* now we scan with confidence that the span length is respected */\n    int num_chars;\n    iret = std::sscanf(str.str, fmt, v, &num_chars);\n    /* scanf returns the number of successful conversions */\n    if(iret != 1) return csubstr::npos;\n    C4_ASSERT(num_chars >= 0);\n    return (size_t)(num_chars);\n}\n#endif // (!C4CORE_HAVE_STD_FROMCHARS) && (!C4CORE_HAVE_FAST_FLOAT)\n\n\n#if C4CORE_HAVE_STD_TOCHARS\ntemplate<class T>\nC4_ALWAYS_INLINE size_t rtoa(substr buf, T v, int precision=-1, RealFormat_e formatting=FTOA_FLEX) noexcept\n{\n    std::to_chars_result result;\n    size_t pos = 0;\n    if(formatting == FTOA_HEXA)\n    {\n        if(buf.len > size_t(2))\n        {\n            buf.str[0] = '0';\n            buf.str[1] = 'x';\n        }\n        pos += size_t(2);\n    }\n    if(precision == -1)\n        result = std::to_chars(buf.str + pos, buf.str + buf.len, v, (std::chars_format)formatting);\n    else\n        result = std::to_chars(buf.str + pos, buf.str + buf.len, v, (std::chars_format)formatting, precision);\n    if(result.ec == std::errc())\n    {\n        // all good, no errors.\n        C4_ASSERT(result.ptr >= buf.str);\n        ptrdiff_t delta = result.ptr - buf.str;\n        return static_cast<size_t>(delta);\n    }\n    C4_ASSERT(result.ec == std::errc::value_too_large);\n    // This is unfortunate.\n    //\n    // When the result can't fit in the given buffer,\n    // std::to_chars() returns the end pointer it was originally\n    // given, which is useless because here we would like to know\n    // _exactly_ how many characters the buffer must have to fit\n    // the result.\n    //\n    // So we take the pessimistic view, and assume as many digits\n    // as could ever be required:\n    size_t ret = static_cast<size_t>(std::numeric_limits<T>::max_digits10);\n    return ret > buf.len ? ret : buf.len + 1;\n}\n#endif // C4CORE_HAVE_STD_TOCHARS\n\n\n#if C4CORE_HAVE_FAST_FLOAT\ntemplate<class T>\nC4_ALWAYS_INLINE bool scan_rhex(csubstr s, T *C4_RESTRICT val) noexcept\n{\n    C4_ASSERT(s.len > 0);\n    C4_ASSERT(s.str[0] != '-');\n    C4_ASSERT(s.str[0] != '+');\n    C4_ASSERT(!s.begins_with(\"0x\"));\n    C4_ASSERT(!s.begins_with(\"0X\"));\n    size_t pos = 0;\n    // integer part\n    for( ; pos < s.len; ++pos)\n    {\n        const char c = s.str[pos];\n        if(c >= '0' && c <= '9')\n            *val = *val * T(16) + T(c - '0');\n        else if(c >= 'a' && c <= 'f')\n            *val = *val * T(16) + T(c - 'a');\n        else if(c >= 'A' && c <= 'F')\n            *val = *val * T(16) + T(c - 'A');\n        else if(c == '.')\n        {\n            ++pos;\n            break; // follow on to mantissa\n        }\n        else if(c == 'p' || c == 'P')\n        {\n            ++pos;\n            goto power; // no mantissa given, jump to power\n        }\n        else\n        {\n            return false;\n        }\n    }\n    // mantissa\n    {\n        // 0.0625 == 1/16 == value of first digit after the comma\n        for(T digit = T(0.0625); pos < s.len; ++pos, digit /= T(16))\n        {\n            const char c = s.str[pos];\n            if(c >= '0' && c <= '9')\n                *val += digit * T(c - '0');\n            else if(c >= 'a' && c <= 'f')\n                *val += digit * T(c - 'a');\n            else if(c >= 'A' && c <= 'F')\n                *val += digit * T(c - 'A');\n            else if(c == 'p' || c == 'P')\n            {\n                ++pos;\n                goto power; // mantissa finished, jump to power\n            }\n            else\n            {\n                return false;\n            }\n        }\n    }\n    return true;\npower:\n    if(C4_LIKELY(pos < s.len))\n    {\n        if(s.str[pos] == '+') // atoi() cannot handle a leading '+'\n            ++pos;\n        if(C4_LIKELY(pos < s.len))\n        {\n            int16_t powval = {};\n            if(C4_LIKELY(atoi(s.sub(pos), &powval)))\n            {\n                *val *= ipow<T, int16_t, 16>(powval);\n                return true;\n            }\n        }\n    }\n    return false;\n}\n#endif\n\n} // namespace detail\n/** @endcond */\n\n\n#undef _c4appendhex\n#undef _c4append\n\n\n/** @defgroup doc_ftoa ftoa: float32 to chars\n *\n * @{ */\n\n/** Convert a single-precision real number to string.  The string will\n * in general be NOT null-terminated.  For FTOA_FLEX, \\p precision is\n * the number of significand digits. Otherwise \\p precision is the\n * number of decimals. It is safe to call this function with an empty\n * or too-small buffer.\n *\n * @return the size of the buffer needed to write the number\n */\nC4_ALWAYS_INLINE size_t ftoa(substr str, float v, int precision=-1, RealFormat_e formatting=FTOA_FLEX) noexcept\n{\n#if C4CORE_HAVE_STD_TOCHARS\n    return detail::rtoa(str, v, precision, formatting);\n#else\n    char fmt[16];\n    detail::get_real_format_str(fmt, precision, formatting, /*length_modifier*/\"\");\n    return detail::print_one(str, fmt, v);\n#endif\n}\n\n/** @} */\n\n\n/** @defgroup doc_dtoa dtoa: float64 to chars\n *\n * @{ */\n\n/** Convert a double-precision real number to string.  The string will\n * in general be NOT null-terminated.  For FTOA_FLEX, \\p precision is\n * the number of significand digits. Otherwise \\p precision is the\n * number of decimals. It is safe to call this function with an empty\n * or too-small buffer.\n *\n * @return the size of the buffer needed to write the number\n */\nC4_ALWAYS_INLINE size_t dtoa(substr str, double v, int precision=-1, RealFormat_e formatting=FTOA_FLEX) noexcept\n{\n#if C4CORE_HAVE_STD_TOCHARS\n    return detail::rtoa(str, v, precision, formatting);\n#else\n    char fmt[16];\n    detail::get_real_format_str(fmt, precision, formatting, /*length_modifier*/\"l\");\n    return detail::print_one(str, fmt, v);\n#endif\n}\n\n/** @} */\n\n\n/** @defgroup doc_atof atof: chars to float32\n *\n * @{ */\n\n/** Convert a string to a single precision real number.\n * The input string must be trimmed to the value, ie\n * no leading or trailing whitespace can be present.\n * @return true iff the conversion succeeded\n * @see atof_first() if the string is not trimmed\n */\nC4_ALWAYS_INLINE bool atof(csubstr str, float * C4_RESTRICT v) noexcept\n{\n    C4_ASSERT(str.len > 0);\n    C4_ASSERT(str.triml(\" \\r\\t\\n\").len == str.len);\n#if C4CORE_HAVE_FAST_FLOAT\n    // fastfloat cannot parse hexadecimal floats\n    bool isneg = (str.str[0] == '-');\n    csubstr rem = str.sub(isneg || str.str[0] == '+');\n    if(!(rem.len >= 2 && (rem.str[0] == '0' && (rem.str[1] == 'x' || rem.str[1] == 'X'))))\n    {\n        fast_float::from_chars_result result;\n        result = fast_float::from_chars(str.str, str.str + str.len, *v);\n        return result.ec == std::errc();\n    }\n    else if(detail::scan_rhex(rem.sub(2), v))\n    {\n        *v *= isneg ? -1.f : 1.f;\n        return true;\n    }\n    return false;\n#elif C4CORE_HAVE_STD_FROMCHARS\n    std::from_chars_result result;\n    result = std::from_chars(str.str, str.str + str.len, *v);\n    return result.ec == std::errc();\n#else\n    csubstr rem = str.sub(str.str[0] == '-' || str.str[0] == '+');\n    if(!(rem.len >= 2 && (rem.str[0] == '0' && (rem.str[1] == 'x' || rem.str[1] == 'X'))))\n        return detail::scan_one(str, \"f\", v) != csubstr::npos;\n    else\n        return detail::scan_one(str, \"a\", v) != csubstr::npos;\n#endif\n}\n\n\n/** Convert a string to a single precision real number.\n * Leading whitespace is skipped until valid characters are found.\n * @return the number of characters read from the string, or npos if\n * conversion was not successful or if the string was empty */\ninline size_t atof_first(csubstr str, float * C4_RESTRICT v) noexcept\n{\n    csubstr trimmed = str.first_real_span();\n    if(trimmed.len == 0)\n        return csubstr::npos;\n    if(atof(trimmed, v))\n        return static_cast<size_t>(trimmed.end() - str.begin());\n    return csubstr::npos;\n}\n\n/** @} */\n\n\n/** @defgroup doc_atod atod: chars to float64\n *\n * @{ */\n\n/** Convert a string to a double precision real number.\n * The input string must be trimmed to the value, ie\n * no leading or trailing whitespace can be present.\n * @return true iff the conversion succeeded\n * @see atod_first() if the string is not trimmed\n */\nC4_ALWAYS_INLINE bool atod(csubstr str, double * C4_RESTRICT v) noexcept\n{\n    C4_ASSERT(str.len > 0);\n    C4_ASSERT(str.triml(\" \\r\\t\\n\").len == str.len);\n#if C4CORE_HAVE_FAST_FLOAT\n    // fastfloat cannot parse hexadecimal floats\n    bool isneg = (str.str[0] == '-');\n    csubstr rem = str.sub(isneg || str.str[0] == '+');\n    if(!(rem.len >= 2 && (rem.str[0] == '0' && (rem.str[1] == 'x' || rem.str[1] == 'X'))))\n    {\n        fast_float::from_chars_result result;\n        result = fast_float::from_chars(str.str, str.str + str.len, *v);\n        return result.ec == std::errc();\n    }\n    else if(detail::scan_rhex(rem.sub(2), v))\n    {\n        *v *= isneg ? -1. : 1.;\n        return true;\n    }\n    return false;\n#elif C4CORE_HAVE_STD_FROMCHARS\n    std::from_chars_result result;\n    result = std::from_chars(str.str, str.str + str.len, *v);\n    return result.ec == std::errc();\n#else\n    csubstr rem = str.sub(str.str[0] == '-' || str.str[0] == '+');\n    if(!(rem.len >= 2 && (rem.str[0] == '0' && (rem.str[1] == 'x' || rem.str[1] == 'X'))))\n        return detail::scan_one(str, \"lf\", v) != csubstr::npos;\n    else\n        return detail::scan_one(str, \"la\", v) != csubstr::npos;\n#endif\n}\n\n\n/** Convert a string to a double precision real number.\n * Leading whitespace is skipped until valid characters are found.\n * @return the number of characters read from the string, or npos if\n * conversion was not successful or if the string was empty */\ninline size_t atod_first(csubstr str, double * C4_RESTRICT v) noexcept\n{\n    csubstr trimmed = str.first_real_span();\n    if(trimmed.len == 0)\n        return csubstr::npos;\n    if(atod(trimmed, v))\n        return static_cast<size_t>(trimmed.end() - str.begin());\n    return csubstr::npos;\n}\n\n/** @} */\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n// generic versions\n\n/** @cond dev */\n// on some platforms, (unsigned) int and (unsigned) long\n// are not any of the fixed length types above\n#define _C4_IF_NOT_FIXED_LENGTH_I(T, ty) C4_ALWAYS_INLINE typename std::enable_if<std::  is_signed<T>::value && !is_fixed_length<T>::value_i, ty>\n#define _C4_IF_NOT_FIXED_LENGTH_U(T, ty) C4_ALWAYS_INLINE typename std::enable_if<std::is_unsigned<T>::value && !is_fixed_length<T>::value_u, ty>\n/** @endcond*/\n\n\n/** @defgroup doc_xtoa xtoa: generic value to chars\n *\n * Dispatches to the most appropriate and efficient conversion\n * function\n *\n * @{ */\nC4_ALWAYS_INLINE size_t xtoa(substr s,  uint8_t v) noexcept { return write_dec(s, v); }\nC4_ALWAYS_INLINE size_t xtoa(substr s, uint16_t v) noexcept { return write_dec(s, v); }\nC4_ALWAYS_INLINE size_t xtoa(substr s, uint32_t v) noexcept { return write_dec(s, v); }\nC4_ALWAYS_INLINE size_t xtoa(substr s, uint64_t v) noexcept { return write_dec(s, v); }\nC4_ALWAYS_INLINE size_t xtoa(substr s,   int8_t v) noexcept { return itoa(s, v); }\nC4_ALWAYS_INLINE size_t xtoa(substr s,  int16_t v) noexcept { return itoa(s, v); }\nC4_ALWAYS_INLINE size_t xtoa(substr s,  int32_t v) noexcept { return itoa(s, v); }\nC4_ALWAYS_INLINE size_t xtoa(substr s,  int64_t v) noexcept { return itoa(s, v); }\nC4_ALWAYS_INLINE size_t xtoa(substr s,    float v) noexcept { return ftoa(s, v); }\nC4_ALWAYS_INLINE size_t xtoa(substr s,   double v) noexcept { return dtoa(s, v); }\n\nC4_ALWAYS_INLINE size_t xtoa(substr s,  uint8_t v,  uint8_t radix) noexcept { return utoa(s, v, radix); }\nC4_ALWAYS_INLINE size_t xtoa(substr s, uint16_t v, uint16_t radix) noexcept { return utoa(s, v, radix); }\nC4_ALWAYS_INLINE size_t xtoa(substr s, uint32_t v, uint32_t radix) noexcept { return utoa(s, v, radix); }\nC4_ALWAYS_INLINE size_t xtoa(substr s, uint64_t v, uint64_t radix) noexcept { return utoa(s, v, radix); }\nC4_ALWAYS_INLINE size_t xtoa(substr s,   int8_t v,   int8_t radix) noexcept { return itoa(s, v, radix); }\nC4_ALWAYS_INLINE size_t xtoa(substr s,  int16_t v,  int16_t radix) noexcept { return itoa(s, v, radix); }\nC4_ALWAYS_INLINE size_t xtoa(substr s,  int32_t v,  int32_t radix) noexcept { return itoa(s, v, radix); }\nC4_ALWAYS_INLINE size_t xtoa(substr s,  int64_t v,  int64_t radix) noexcept { return itoa(s, v, radix); }\n\nC4_ALWAYS_INLINE size_t xtoa(substr s,  uint8_t v,  uint8_t radix, size_t num_digits) noexcept { return utoa(s, v, radix, num_digits); }\nC4_ALWAYS_INLINE size_t xtoa(substr s, uint16_t v, uint16_t radix, size_t num_digits) noexcept { return utoa(s, v, radix, num_digits); }\nC4_ALWAYS_INLINE size_t xtoa(substr s, uint32_t v, uint32_t radix, size_t num_digits) noexcept { return utoa(s, v, radix, num_digits); }\nC4_ALWAYS_INLINE size_t xtoa(substr s, uint64_t v, uint64_t radix, size_t num_digits) noexcept { return utoa(s, v, radix, num_digits); }\nC4_ALWAYS_INLINE size_t xtoa(substr s,   int8_t v,   int8_t radix, size_t num_digits) noexcept { return itoa(s, v, radix, num_digits); }\nC4_ALWAYS_INLINE size_t xtoa(substr s,  int16_t v,  int16_t radix, size_t num_digits) noexcept { return itoa(s, v, radix, num_digits); }\nC4_ALWAYS_INLINE size_t xtoa(substr s,  int32_t v,  int32_t radix, size_t num_digits) noexcept { return itoa(s, v, radix, num_digits); }\nC4_ALWAYS_INLINE size_t xtoa(substr s,  int64_t v,  int64_t radix, size_t num_digits) noexcept { return itoa(s, v, radix, num_digits); }\n\nC4_ALWAYS_INLINE size_t xtoa(substr s,  float v, int precision, RealFormat_e formatting=FTOA_FLEX) noexcept { return ftoa(s, v, precision, formatting); }\nC4_ALWAYS_INLINE size_t xtoa(substr s, double v, int precision, RealFormat_e formatting=FTOA_FLEX) noexcept { return dtoa(s, v, precision, formatting); }\n\ntemplate <class T> _C4_IF_NOT_FIXED_LENGTH_I(T, size_t)::type xtoa(substr buf, T v) noexcept { return itoa(buf, v); }\ntemplate <class T> _C4_IF_NOT_FIXED_LENGTH_U(T, size_t)::type xtoa(substr buf, T v) noexcept { return write_dec(buf, v); }\ntemplate <class T>\nC4_ALWAYS_INLINE size_t xtoa(substr s, T *v) noexcept { return itoa(s, (intptr_t)v, (intptr_t)16); }\n\n/** @} */\n\n/** @defgroup doc_atox atox: generic chars to value\n *\n * Dispatches to the most appropriate and efficient conversion\n * function\n *\n * @{ */\n\nC4_ALWAYS_INLINE bool atox(csubstr s,  uint8_t *C4_RESTRICT v) noexcept { return atou(s, v); }\nC4_ALWAYS_INLINE bool atox(csubstr s, uint16_t *C4_RESTRICT v) noexcept { return atou(s, v); }\nC4_ALWAYS_INLINE bool atox(csubstr s, uint32_t *C4_RESTRICT v) noexcept { return atou(s, v); }\nC4_ALWAYS_INLINE bool atox(csubstr s, uint64_t *C4_RESTRICT v) noexcept { return atou(s, v); }\nC4_ALWAYS_INLINE bool atox(csubstr s,   int8_t *C4_RESTRICT v) noexcept { return atoi(s, v); }\nC4_ALWAYS_INLINE bool atox(csubstr s,  int16_t *C4_RESTRICT v) noexcept { return atoi(s, v); }\nC4_ALWAYS_INLINE bool atox(csubstr s,  int32_t *C4_RESTRICT v) noexcept { return atoi(s, v); }\nC4_ALWAYS_INLINE bool atox(csubstr s,  int64_t *C4_RESTRICT v) noexcept { return atoi(s, v); }\nC4_ALWAYS_INLINE bool atox(csubstr s,    float *C4_RESTRICT v) noexcept { return atof(s, v); }\nC4_ALWAYS_INLINE bool atox(csubstr s,   double *C4_RESTRICT v) noexcept { return atod(s, v); }\n\ntemplate <class T> _C4_IF_NOT_FIXED_LENGTH_I(T, bool  )::type atox(csubstr buf, T *C4_RESTRICT v) noexcept { return atoi(buf, v); }\ntemplate <class T> _C4_IF_NOT_FIXED_LENGTH_U(T, bool  )::type atox(csubstr buf, T *C4_RESTRICT v) noexcept { return atou(buf, v); }\ntemplate <class T>\nC4_ALWAYS_INLINE bool atox(csubstr s, T **v) noexcept { intptr_t tmp; bool ret = atox(s, &tmp); if(ret) { *v = (T*)tmp; } return ret; }\n\n/** @} */\n\n\n/** @defgroup doc_to_chars to_chars: generalized chars to value\n *\n * Convert the given value, writing into the string.  The resulting\n * string will NOT be null-terminated.  Return the number of\n * characters needed.  This function is safe to call when the string\n * is too small - no writes will occur beyond the string's last\n * character.\n *\n * Dispatches to the most appropriate and efficient conversion\n * function.\n *\n * @see write_dec, doc_utoa, doc_itoa, doc_ftoa, doc_dtoa\n *\n * @warning When serializing floating point values (float or double),\n * be aware that because it uses defaults, to_chars() may cause a\n * truncation of the precision. To enforce a particular precision, use\n * for example @ref c4::fmt::real, or call directly @ref c4::ftoa or\n * @ref c4::dtoa.\n *\n * @{ */\n\nC4_ALWAYS_INLINE size_t to_chars(substr buf,  uint8_t v) noexcept { return write_dec(buf, v); }\nC4_ALWAYS_INLINE size_t to_chars(substr buf, uint16_t v) noexcept { return write_dec(buf, v); }\nC4_ALWAYS_INLINE size_t to_chars(substr buf, uint32_t v) noexcept { return write_dec(buf, v); }\nC4_ALWAYS_INLINE size_t to_chars(substr buf, uint64_t v) noexcept { return write_dec(buf, v); }\nC4_ALWAYS_INLINE size_t to_chars(substr buf,   int8_t v) noexcept { return itoa(buf, v); }\nC4_ALWAYS_INLINE size_t to_chars(substr buf,  int16_t v) noexcept { return itoa(buf, v); }\nC4_ALWAYS_INLINE size_t to_chars(substr buf,  int32_t v) noexcept { return itoa(buf, v); }\nC4_ALWAYS_INLINE size_t to_chars(substr buf,  int64_t v) noexcept { return itoa(buf, v); }\nC4_ALWAYS_INLINE size_t to_chars(substr buf,    float v) noexcept { return ftoa(buf, v); }\nC4_ALWAYS_INLINE size_t to_chars(substr buf,   double v) noexcept { return dtoa(buf, v); }\n\ntemplate <class T> _C4_IF_NOT_FIXED_LENGTH_I(T, size_t)::type to_chars(substr buf, T v) noexcept { return itoa(buf, v); }\ntemplate <class T> _C4_IF_NOT_FIXED_LENGTH_U(T, size_t)::type to_chars(substr buf, T v) noexcept { return write_dec(buf, v); }\ntemplate <class T>\nC4_ALWAYS_INLINE size_t to_chars(substr s, T *v) noexcept { return itoa(s, (intptr_t)v, (intptr_t)16); }\n\n/** @} */\n\n\n/** @defgroup doc_from_chars from_chars: generalized chars to value\n *\n * Read a value from the string, which must be trimmed to the value\n * (ie, no leading/trailing whitespace).  return true if the\n * conversion succeeded.  There is no check for overflow; the value\n * wraps around in a way similar to the standard C/C++ overflow\n * behavior. For example, from_chars<int8_t>(\"128\", &val) returns true\n * and val will be set tot 0. See @ref doc_overflows and @ref\n * doc_overflow_checked for facilities enforcing no-overflow.\n *\n * Dispatches to the most appropriate and efficient conversion\n * function\n *\n * @see doc_from_chars_first, atou, atoi, atof, atod\n * @{ */\n\nC4_ALWAYS_INLINE bool from_chars(csubstr buf,  uint8_t *C4_RESTRICT v) noexcept { return atou(buf, v); }\nC4_ALWAYS_INLINE bool from_chars(csubstr buf, uint16_t *C4_RESTRICT v) noexcept { return atou(buf, v); }\nC4_ALWAYS_INLINE bool from_chars(csubstr buf, uint32_t *C4_RESTRICT v) noexcept { return atou(buf, v); }\nC4_ALWAYS_INLINE bool from_chars(csubstr buf, uint64_t *C4_RESTRICT v) noexcept { return atou(buf, v); }\nC4_ALWAYS_INLINE bool from_chars(csubstr buf,   int8_t *C4_RESTRICT v) noexcept { return atoi(buf, v); }\nC4_ALWAYS_INLINE bool from_chars(csubstr buf,  int16_t *C4_RESTRICT v) noexcept { return atoi(buf, v); }\nC4_ALWAYS_INLINE bool from_chars(csubstr buf,  int32_t *C4_RESTRICT v) noexcept { return atoi(buf, v); }\nC4_ALWAYS_INLINE bool from_chars(csubstr buf,  int64_t *C4_RESTRICT v) noexcept { return atoi(buf, v); }\nC4_ALWAYS_INLINE bool from_chars(csubstr buf,    float *C4_RESTRICT v) noexcept { return atof(buf, v); }\nC4_ALWAYS_INLINE bool from_chars(csubstr buf,   double *C4_RESTRICT v) noexcept { return atod(buf, v); }\n\ntemplate <class T> _C4_IF_NOT_FIXED_LENGTH_I(T, bool  )::type from_chars(csubstr buf, T *C4_RESTRICT v) noexcept { return atoi(buf, v); }\ntemplate <class T> _C4_IF_NOT_FIXED_LENGTH_U(T, bool  )::type from_chars(csubstr buf, T *C4_RESTRICT v) noexcept { return atou(buf, v); }\ntemplate <class T>\nC4_ALWAYS_INLINE bool from_chars(csubstr buf, T **v) noexcept { intptr_t tmp; bool ret = from_chars(buf, &tmp); if(ret) { *v = (T*)tmp; } return ret; }\n\n/** @defgroup doc_from_chars_first from_chars_first: generalized chars to value\n *\n * Read the first valid sequence of characters from the string,\n * skipping leading whitespace, and convert it using @ref doc_from_chars .\n * Return the number of characters read for converting.\n *\n * Dispatches to the most appropriate and efficient conversion\n * function.\n *\n * @see atou_first, atoi_first, atof_first, atod_first\n * @{ */\n\nC4_ALWAYS_INLINE size_t from_chars_first(csubstr buf,  uint8_t *C4_RESTRICT v) noexcept { return atou_first(buf, v); }\nC4_ALWAYS_INLINE size_t from_chars_first(csubstr buf, uint16_t *C4_RESTRICT v) noexcept { return atou_first(buf, v); }\nC4_ALWAYS_INLINE size_t from_chars_first(csubstr buf, uint32_t *C4_RESTRICT v) noexcept { return atou_first(buf, v); }\nC4_ALWAYS_INLINE size_t from_chars_first(csubstr buf, uint64_t *C4_RESTRICT v) noexcept { return atou_first(buf, v); }\nC4_ALWAYS_INLINE size_t from_chars_first(csubstr buf,   int8_t *C4_RESTRICT v) noexcept { return atoi_first(buf, v); }\nC4_ALWAYS_INLINE size_t from_chars_first(csubstr buf,  int16_t *C4_RESTRICT v) noexcept { return atoi_first(buf, v); }\nC4_ALWAYS_INLINE size_t from_chars_first(csubstr buf,  int32_t *C4_RESTRICT v) noexcept { return atoi_first(buf, v); }\nC4_ALWAYS_INLINE size_t from_chars_first(csubstr buf,  int64_t *C4_RESTRICT v) noexcept { return atoi_first(buf, v); }\nC4_ALWAYS_INLINE size_t from_chars_first(csubstr buf,    float *C4_RESTRICT v) noexcept { return atof_first(buf, v); }\nC4_ALWAYS_INLINE size_t from_chars_first(csubstr buf,   double *C4_RESTRICT v) noexcept { return atod_first(buf, v); }\n\ntemplate <class T> _C4_IF_NOT_FIXED_LENGTH_I(T, size_t)::type from_chars_first(csubstr buf, T *C4_RESTRICT v) noexcept { return atoi_first(buf, v); }\ntemplate <class T> _C4_IF_NOT_FIXED_LENGTH_U(T, size_t)::type from_chars_first(csubstr buf, T *C4_RESTRICT v) noexcept { return atou_first(buf, v); }\ntemplate <class T>\nC4_ALWAYS_INLINE size_t from_chars_first(csubstr buf, T **v) noexcept { intptr_t tmp; bool ret = from_chars_first(buf, &tmp); if(ret) { *v = (T*)tmp; } return ret; }\n\n/** @} */\n\n/** @} */\n\n#undef _C4_IF_NOT_FIXED_LENGTH_I\n#undef _C4_IF_NOT_FIXED_LENGTH_U\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n/** call to_chars() and return a substr consisting of the\n * written portion of the input buffer. Ie, same as to_chars(),\n * but return a substr instead of a size_t.\n * Convert the given value to a string using to_chars(), and\n * return the resulting string, up to and including the last\n * written character.\n * @ingroup doc_to_chars\n * @see to_chars() */\ntemplate<class T>\nC4_ALWAYS_INLINE substr to_chars_sub(substr buf, T const& C4_RESTRICT v) noexcept\n{\n    size_t sz = to_chars(buf, v);\n    return buf.left_of(sz <= buf.len ? sz : buf.len);\n}\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n// bool implementation\n\n/** @ingroup doc_to_chars */\nC4_ALWAYS_INLINE size_t to_chars(substr buf, bool v) noexcept\n{\n    int val = v;\n    return to_chars(buf, val);\n}\n\n/** @ingroup doc_from_chars */\ninline bool from_chars(csubstr buf, bool * C4_RESTRICT v) noexcept\n{\n    if(buf == '0')\n    {\n        *v = false; return true;\n    }\n    else if(buf == '1')\n    {\n        *v = true; return true;\n    }\n    else if(buf == \"false\")\n    {\n        *v = false; return true;\n    }\n    else if(buf == \"true\")\n    {\n        *v = true; return true;\n    }\n    else if(buf == \"False\")\n    {\n        *v = false; return true;\n    }\n    else if(buf == \"True\")\n    {\n        *v = true; return true;\n    }\n    else if(buf == \"FALSE\")\n    {\n        *v = false; return true;\n    }\n    else if(buf == \"TRUE\")\n    {\n        *v = true; return true;\n    }\n    // fallback to c-style int bools\n    int val = 0;\n    bool ret = from_chars(buf, &val);\n    if(C4_LIKELY(ret))\n    {\n        *v = (val != 0);\n    }\n    return ret;\n}\n\n/** @ingroup doc_from_chars_first */\ninline size_t from_chars_first(csubstr buf, bool * C4_RESTRICT v) noexcept\n{\n    csubstr trimmed = buf.first_non_empty_span();\n    if(trimmed.len == 0 || !from_chars(buf, v))\n        return csubstr::npos;\n    return trimmed.len;\n}\n\n\n//-----------------------------------------------------------------------------\n// single-char implementation\n\n/** @ingroup doc_to_chars */\ninline size_t to_chars(substr buf, char v) noexcept\n{\n    if(buf.len > 0)\n    {\n        C4_XASSERT(buf.str);\n        buf.str[0] = v;\n    }\n    return 1;\n}\n\n/** extract a single character from a substring\n * @note to extract a string instead and not just a single character, use the csubstr overload\n * @ingroup doc_from_chars\n * */\ninline bool from_chars(csubstr buf, char * C4_RESTRICT v) noexcept\n{\n    if(buf.len != 1)\n        return false;\n    C4_XASSERT(buf.str);\n    *v = buf.str[0];\n    return true;\n}\n\n/** @ingroup doc_from_chars_first */\ninline size_t from_chars_first(csubstr buf, char * C4_RESTRICT v) noexcept\n{\n    if(buf.len < 1)\n        return csubstr::npos;\n    *v = buf.str[0];\n    return 1;\n}\n\n\n//-----------------------------------------------------------------------------\n// csubstr implementation\n\n/** @ingroup doc_to_chars */\ninline size_t to_chars(substr buf, csubstr v) noexcept\n{\n    C4_ASSERT(!buf.overlaps(v));\n    size_t len = buf.len < v.len ? buf.len : v.len;\n    // calling memcpy with null strings is undefined behavior\n    // and will wreak havoc in calling code's branches.\n    // see https://github.com/biojppm/rapidyaml/pull/264#issuecomment-1262133637\n    if(len)\n    {\n        C4_ASSERT(buf.str != nullptr);\n        C4_ASSERT(v.str != nullptr);\n        memcpy(buf.str, v.str, len);\n    }\n    return v.len;\n}\n\n/** @ingroup doc_from_chars */\ninline bool from_chars(csubstr buf, csubstr *C4_RESTRICT v) noexcept\n{\n    *v = buf;\n    return true;\n}\n\n/** @ingroup doc_from_chars_first */\ninline size_t from_chars_first(substr buf, csubstr * C4_RESTRICT v) noexcept\n{\n    csubstr trimmed = buf.first_non_empty_span();\n    if(trimmed.len == 0)\n        return csubstr::npos;\n    *v = trimmed;\n    return static_cast<size_t>(trimmed.end() - buf.begin());\n}\n\n\n//-----------------------------------------------------------------------------\n// substr\n\n/** @ingroup doc_to_chars */\ninline size_t to_chars(substr buf, substr v) noexcept\n{\n    C4_ASSERT(!buf.overlaps(v));\n    size_t len = buf.len < v.len ? buf.len : v.len;\n    // calling memcpy with null strings is undefined behavior\n    // and will wreak havoc in calling code's branches.\n    // see https://github.com/biojppm/rapidyaml/pull/264#issuecomment-1262133637\n    if(len)\n    {\n        C4_ASSERT(buf.str != nullptr);\n        C4_ASSERT(v.str != nullptr);\n        memcpy(buf.str, v.str, len);\n    }\n    return v.len;\n}\n\n/** @ingroup doc_from_chars */\ninline bool from_chars(csubstr buf, substr * C4_RESTRICT v) noexcept\n{\n    C4_ASSERT(!buf.overlaps(*v));\n    // is the destination buffer wide enough?\n    if(v->len >= buf.len)\n    {\n        // calling memcpy with null strings is undefined behavior\n        // and will wreak havoc in calling code's branches.\n        // see https://github.com/biojppm/rapidyaml/pull/264#issuecomment-1262133637\n        if(buf.len)\n        {\n            C4_ASSERT(buf.str != nullptr);\n            C4_ASSERT(v->str != nullptr);\n            memcpy(v->str, buf.str, buf.len);\n        }\n        v->len = buf.len;\n        return true;\n    }\n    return false;\n}\n\n/** @ingroup doc_from_chars_first */\ninline size_t from_chars_first(csubstr buf, substr * C4_RESTRICT v) noexcept\n{\n    csubstr trimmed = buf.first_non_empty_span();\n    C4_ASSERT(!trimmed.overlaps(*v));\n    if(C4_UNLIKELY(trimmed.len == 0))\n        return csubstr::npos;\n    size_t len = trimmed.len > v->len ? v->len : trimmed.len;\n    // calling memcpy with null strings is undefined behavior\n    // and will wreak havoc in calling code's branches.\n    // see https://github.com/biojppm/rapidyaml/pull/264#issuecomment-1262133637\n    if(len)\n    {\n        C4_ASSERT(buf.str != nullptr);\n        C4_ASSERT(v->str != nullptr);\n        memcpy(v->str, trimmed.str, len);\n    }\n    if(C4_UNLIKELY(trimmed.len > v->len))\n        return csubstr::npos;\n    return static_cast<size_t>(trimmed.end() - buf.begin());\n}\n\n\n//-----------------------------------------------------------------------------\n\n/** @ingroup doc_to_chars */\ntemplate<size_t N>\ninline size_t to_chars(substr buf, const char (& C4_RESTRICT v)[N]) noexcept\n{\n    csubstr sp(v);\n    return to_chars(buf, sp);\n}\n\n/** @ingroup doc_to_chars */\ninline size_t to_chars(substr buf, const char * C4_RESTRICT v) noexcept\n{\n    return to_chars(buf, to_csubstr(v));\n}\n\n/** @} */\n\n} // namespace c4\n\n#ifdef _MSC_VER\n#   pragma warning(pop)\n#endif\n\n#if defined(__clang__)\n#   pragma clang diagnostic pop\n#elif defined(__GNUC__)\n#   pragma GCC diagnostic pop\n#endif\n\n#endif /* _C4_CHARCONV_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/common.hpp",
    "content": "#ifndef _C4_COMMON_HPP_\n#define _C4_COMMON_HPP_\n\n#include \"c4/config.hpp\"\n\n#include \"c4/preprocessor.hpp\"\n#include \"c4/platform.hpp\"\n#include \"c4/cpu.hpp\"\n#include \"c4/compiler.hpp\"\n#include \"c4/language.hpp\"\n#include \"c4/error.hpp\"\n#include \"c4/time.hpp\"\n#include \"c4/types.hpp\"\n\n#endif /* _C4_COMMON_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/compiler.hpp",
    "content": "#ifndef _C4_COMPILER_HPP_\n#define _C4_COMPILER_HPP_\n\n/** @file compiler.hpp Provides compiler information macros\n * @ingroup basic_headers */\n\n#include \"c4/platform.hpp\"\n\n// Compilers:\n//      C4_MSVC\n//             Visual Studio 2022: MSVC++ 17, 1930\n//             Visual Studio 2019: MSVC++ 16, 1920\n//             Visual Studio 2017: MSVC++ 15\n//             Visual Studio 2015: MSVC++ 14\n//             Visual Studio 2013: MSVC++ 13\n//             Visual Studio 2013: MSVC++ 12\n//             Visual Studio 2012: MSVC++ 11\n//             Visual Studio 2010: MSVC++ 10\n//             Visual Studio 2008: MSVC++ 09\n//             Visual Studio 2005: MSVC++ 08\n//      C4_CLANG\n//      C4_GCC\n//      C4_ICC (intel compiler)\n/** @see http://sourceforge.net/p/predef/wiki/Compilers/ for a list of compiler identifier macros */\n/** @see https://msdn.microsoft.com/en-us/library/b0084kay.aspx for VS2013 predefined macros */\n\n#if defined(_MSC_VER) && !defined(__clang__)\n#   define C4_MSVC\n#   define C4_MSVC_VERSION_2022 17\n#   define C4_MSVC_VERSION_2019 16\n#   define C4_MSVC_VERSION_2017 15\n#   define C4_MSVC_VERSION_2015 14\n#   define C4_MSVC_VERSION_2013 12\n#   define C4_MSVC_VERSION_2012 11\n#   if _MSC_VER >= 1930\n#       define C4_MSVC_VERSION C4_MSVC_VERSION_2022  // visual studio 2022\n#       define C4_MSVC_2022\n#   elif _MSC_VER >= 1920\n#       define C4_MSVC_VERSION C4_MSVC_VERSION_2019  // visual studio 2019\n#       define C4_MSVC_2019\n#   elif _MSC_VER >= 1910\n#       define C4_MSVC_VERSION C4_MSVC_VERSION_2017  // visual studio 2017\n#       define C4_MSVC_2017\n#   elif _MSC_VER == 1900\n#       define C4_MSVC_VERSION C4_MSVC_VERSION_2015  // visual studio 2015\n#       define C4_MSVC_2015\n#   elif _MSC_VER == 1800\n#       error \"MSVC version not supported\"\n#       define C4_MSVC_VERSION C4_MSVC_VERSION_2013  // visual studio 2013\n#       define C4_MSVC_2013\n#   elif _MSC_VER == 1700\n#       error \"MSVC version not supported\"\n#       define C4_MSVC_VERSION C4_MSVC_VERSION_2012  // visual studio 2012\n#       define C4_MSVC_2012\n#   elif _MSC_VER == 1600\n#       error \"MSVC version not supported\"\n#       define C4_MSVC_VERSION 10  // visual studio 2010\n#       define C4_MSVC_2010\n#   elif _MSC_VER == 1500\n#       error \"MSVC version not supported\"\n#       define C4_MSVC_VERSION 09  // visual studio 2008\n#       define C4_MSVC_2008\n#   elif _MSC_VER == 1400\n#       error \"MSVC version not supported\"\n#       define C4_MSVC_VERSION 08  // visual studio 2005\n#       define C4_MSVC_2005\n#   else\n#       error \"MSVC version not supported\"\n#   endif // _MSC_VER\n#else\n#   define C4_MSVC_VERSION 0   // visual studio not present\n#   define C4_GCC_LIKE\n#   ifdef __INTEL_COMPILER // check ICC before checking GCC, as ICC defines __GNUC__ too\n#       define C4_ICC\n#       define C4_ICC_VERSION __INTEL_COMPILER\n#   elif defined(__APPLE_CC__)\n#       define C4_XCODE\n#       if defined(__clang__)\n#           define C4_CLANG\n#           ifndef __apple_build_version__\n#               define C4_CLANG_VERSION C4_VERSION_ENCODED(__clang_major__, __clang_minor__, __clang_patchlevel__)\n#           else\n#               define C4_CLANG_VERSION __apple_build_version__\n#           endif\n#       else\n#           define C4_XCODE_VERSION __APPLE_CC__\n#       endif\n#   elif defined(__clang__)\n#       define C4_CLANG\n#       ifndef __apple_build_version__\n#           define C4_CLANG_VERSION C4_VERSION_ENCODED(__clang_major__, __clang_minor__, __clang_patchlevel__)\n#       else\n#           define C4_CLANG_VERSION __apple_build_version__\n#       endif\n#   elif defined(__GNUC__)\n#       ifdef __MINGW32__\n#           define C4_MINGW\n#       endif\n#       define C4_GCC\n#       if defined(__GNUC_PATCHLEVEL__)\n#           define C4_GCC_VERSION C4_VERSION_ENCODED(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)\n#       else\n#           define C4_GCC_VERSION C4_VERSION_ENCODED(__GNUC__, __GNUC_MINOR__, 0)\n#       endif\n#       if __GNUC__ < 5\n#           if __GNUC__ == 4 && __GNUC_MINOR__ >= 8\n// provided by cmake sub-project\n#               include \"c4/gcc-4.8.hpp\"\n#           else\n// we do not support GCC < 4.8:\n//  * misses std::is_trivially_copyable\n//  * misses std::align\n//  * -Wshadow has false positives when a local function parameter has the same name as a method\n#               error \"GCC < 4.8 is not supported\"\n#           endif\n#       endif\n#   endif\n#endif // defined(C4_WIN) && defined(_MSC_VER)\n\n#endif /* _C4_COMPILER_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/config.hpp",
    "content": "#ifndef _C4_CONFIG_HPP_\n#define _C4_CONFIG_HPP_\n\n/** @defgroup basic_headers Basic headers\n * @brief Headers providing basic macros, platform+cpu+compiler information,\n * C++ facilities and basic typedefs. */\n\n/** @file config.hpp Contains configuration defines and includes the basic_headers.\n * @ingroup basic_headers */\n\n//#define C4_DEBUG\n\n#define C4_ERROR_SHOWS_FILELINE\n//#define C4_ERROR_SHOWS_FUNC\n//#define C4_ERROR_THROWS_EXCEPTION\n//#define C4_NO_ALLOC_DEFAULTS\n//#define C4_REDEFINE_CPPNEW\n\n#ifndef C4_SIZE_TYPE\n#   define C4_SIZE_TYPE size_t\n#endif\n\n#ifndef C4_STR_SIZE_TYPE\n#   define C4_STR_SIZE_TYPE C4_SIZE_TYPE\n#endif\n\n#ifndef C4_TIME_TYPE\n#   define C4_TIME_TYPE double\n#endif\n\n#include \"c4/export.hpp\"\n#include \"c4/preprocessor.hpp\"\n#include \"c4/platform.hpp\"\n#include \"c4/cpu.hpp\"\n#include \"c4/compiler.hpp\"\n#include \"c4/language.hpp\"\n#include \"c4/types.hpp\"\n\n#endif // _C4_CONFIG_HPP_\n"
  },
  {
    "path": "libs/rapidyaml/c4/cpu.hpp",
    "content": "#ifndef _C4_CPU_HPP_\n#define _C4_CPU_HPP_\n\n/** @file cpu.hpp Provides processor information macros\n * @ingroup basic_headers */\n\n// see also https://sourceforge.net/p/predef/wiki/Architectures/\n// see also https://sourceforge.net/p/predef/wiki/Endianness/\n// see also https://github.com/googlesamples/android-ndk/blob/android-mk/hello-jni/jni/hello-jni.c\n// see http://code.qt.io/cgit/qt/qtbase.git/tree/src/corelib/global/qprocessordetection.h\n\n#ifdef __ORDER_LITTLE_ENDIAN__\n#   define _C4EL __ORDER_LITTLE_ENDIAN__\n#else\n#   define _C4EL 1234\n#endif\n\n#ifdef __ORDER_BIG_ENDIAN__\n#   define _C4EB __ORDER_BIG_ENDIAN__\n#else\n#   define _C4EB 4321\n#endif\n\n// mixed byte order (eg, PowerPC or ia64)\n#define _C4EM 1111\n\n#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64)\n#    define C4_CPU_X86_64\n#    define C4_WORDSIZE 8\n#    define C4_BYTE_ORDER _C4EL\n\n#elif defined(__i386) || defined(__i386__) || defined(_M_IX86)\n#    define C4_CPU_X86\n#    define C4_WORDSIZE 4\n#    define C4_BYTE_ORDER _C4EL\n\n#elif defined(__arm__) || defined(_M_ARM) \\\n    || defined(__TARGET_ARCH_ARM) || defined(__aarch64__) || defined(_M_ARM64)\n#   if defined(__aarch64__) || defined(_M_ARM64)\n#       define C4_CPU_ARM64\n#       define C4_CPU_ARMV8\n#       define C4_WORDSIZE 8\n#   else\n#       define C4_CPU_ARM\n#       define C4_WORDSIZE 4\n#       if defined(__ARM_ARCH_8__) || defined(__ARM_ARCH_8A__)  \\\n        || (defined(__ARCH_ARM) && __ARCH_ARM >= 8) \\\n        || (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM >= 8)\n#           define C4_CPU_ARMV8\n#       elif defined(__ARM_ARCH_7__) || defined(_ARM_ARCH_7)    \\\n        || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) \\\n        || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) \\\n        || defined(__ARM_ARCH_7EM__) \\\n        || (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM >= 7) \\\n        || (defined(_M_ARM) && _M_ARM >= 7)\n#           define C4_CPU_ARMV7\n#       elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \\\n        || defined(__ARM_ARCH_6T2__) || defined(__ARM_ARCH_6Z__) \\\n        || defined(__ARM_ARCH_6K__)  || defined(__ARM_ARCH_6ZK__) \\\n        || defined(__ARM_ARCH_6M__) || defined(__ARM_ARCH_6KZ__) \\\n        || (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM >= 6)\n#           define C4_CPU_ARMV6\n#       elif defined(__ARM_ARCH_5TEJ__) \\\n        || defined(__ARM_ARCH_5TE__) \\\n        || (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM >= 5)\n#           define C4_CPU_ARMV5\n#       elif defined(__ARM_ARCH_4T__) \\\n        || (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM >= 4)\n#           define C4_CPU_ARMV4\n#       else\n#           error \"unknown CPU architecture: ARM\"\n#       endif\n#   endif\n#   if defined(__ARMEL__) || defined(__LITTLE_ENDIAN__) || defined(__AARCH64EL__) \\\n       || (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) \\\n       || defined(_MSC_VER) // winarm64 does not provide any of the above macros,\n                            // but advises little-endianess:\n                            // https://docs.microsoft.com/en-us/cpp/build/overview-of-arm-abi-conventions?view=msvc-170\n                            // So if it is visual studio compiling, we'll assume little endian.\n#       define C4_BYTE_ORDER _C4EL\n#   elif defined(__ARMEB__) || defined(__BIG_ENDIAN__) || defined(__AARCH64EB__) \\\n       || (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))\n#       define C4_BYTE_ORDER _C4EB\n#   elif defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_PDP_ENDIAN__)\n#       define C4_BYTE_ORDER _C4EM\n#   else\n#       error \"unknown endianness\"\n#   endif\n\n#elif defined(__ia64) || defined(__ia64__) || defined(_M_IA64)\n#   define C4_CPU_IA64\n#   define C4_WORDSIZE 8\n#   define C4_BYTE_ORDER _C4EM\n   // itanium is bi-endian - check byte order below\n\n#elif defined(__ppc__) || defined(__ppc) || defined(__powerpc__)       \\\n    || defined(_ARCH_COM) || defined(_ARCH_PWR) || defined(_ARCH_PPC)  \\\n    || defined(_M_MPPC) || defined(_M_PPC)\n#   if defined(__ppc64__) || defined(__powerpc64__) || defined(__64BIT__)\n#       define C4_CPU_PPC64\n#       define C4_WORDSIZE 8\n#   else\n#       define C4_CPU_PPC\n#       define C4_WORDSIZE 4\n#   endif\n#   define C4_BYTE_ORDER _C4EM\n   // ppc is bi-endian - check byte order below\n\n#elif defined(__s390x__) || defined(__zarch__) || defined(__SYSC_ZARCH_)\n#   define C4_CPU_S390_X\n#   define C4_WORDSIZE 8\n#   define C4_BYTE_ORDER _C4EB\n\n#elif defined(__xtensa__) || defined(__XTENSA__)\n#   define C4_CPU_XTENSA\n#   define C4_WORDSIZE 4\n// not sure about this...\n#   if defined(__XTENSA_EL__) || defined(__xtensa_el__)\n#       define C4_BYTE_ORDER _C4EL\n#   else\n#       define C4_BYTE_ORDER _C4EB\n#   endif\n\n#elif defined(__riscv)\n#   if __riscv_xlen == 64\n#       define C4_CPU_RISCV64\n#       define C4_WORDSIZE 8\n#   else\n#       define C4_CPU_RISCV32\n#       define C4_WORDSIZE 4\n#   endif\n#   define C4_BYTE_ORDER _C4EL\n\n#elif defined(__EMSCRIPTEN__)\n#   define C4_BYTE_ORDER _C4EL\n#   define C4_WORDSIZE 4\n\n#elif defined(__loongarch__)\n#   if defined(__loongarch64)\n#       define C4_CPU_LOONGARCH64\n#       define C4_WORDSIZE 8\n#   else\n#       define C4_CPU_LOONGARCH\n#       define C4_WORDSIZE 4\n#   endif\n#   define C4_BYTE_ORDER _C4EL\n\n#elif defined(SWIG)\n#   error \"please define CPU architecture macros when compiling with swig\"\n\n#else\n#   error \"unknown CPU architecture\"\n#endif\n\n#define C4_LITTLE_ENDIAN (C4_BYTE_ORDER == _C4EL)\n#define C4_BIG_ENDIAN (C4_BYTE_ORDER == _C4EB)\n#define C4_MIXED_ENDIAN (C4_BYTE_ORDER == _C4EM)\n\n#endif /* _C4_CPU_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/ctor_dtor.hpp",
    "content": "#ifndef _C4_CTOR_DTOR_HPP_\n#define _C4_CTOR_DTOR_HPP_\n\n#include \"c4/preprocessor.hpp\"\n#include \"c4/language.hpp\"\n#include \"c4/memory_util.hpp\"\n#include \"c4/error.hpp\"\n\n#include <type_traits>\n#include <utility> // std::forward\n\n/** @file ctor_dtor.hpp object construction and destruction facilities.\n * Some of these are not yet available in C++11. */\n\nnamespace c4 {\n\nC4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH(\"-Wold-style-cast\")\n\n/** default-construct an object, trivial version */\ntemplate <class U> C4_ALWAYS_INLINE typename std::enable_if<std::is_trivially_default_constructible<U>::value, void>::type\nconstruct(U *ptr) noexcept\n{\n    memset(ptr, 0, sizeof(U));\n}\n/** default-construct an object, non-trivial version */\ntemplate<class U> C4_ALWAYS_INLINE typename std ::enable_if< ! std::is_trivially_default_constructible<U>::value, void>::type\nconstruct(U* ptr) noexcept\n{\n    new ((void*)ptr) U();\n}\n\n/** default-construct n objects, trivial version */\ntemplate<class U, class I> C4_ALWAYS_INLINE typename std::enable_if<std::is_trivially_default_constructible<U>::value, void>::type\nconstruct_n(U* ptr, I n) noexcept\n{\n    memset(ptr, 0, n * sizeof(U));\n}\n/** default-construct n objects, non-trivial version */\ntemplate<class U, class I> C4_ALWAYS_INLINE typename std::enable_if< ! std::is_trivially_default_constructible<U>::value, void>::type\nconstruct_n(U* ptr, I n) noexcept\n{\n    for(I i = 0; i < n; ++i)\n    {\n        new ((void*)(ptr + i)) U();\n    }\n}\n\n#ifdef __clang__\n#   pragma clang diagnostic push\n#elif defined(__GNUC__)\n#   pragma GCC diagnostic push\n#   if __GNUC__ >= 6\n#       pragma GCC diagnostic ignored \"-Wnull-dereference\"\n#   endif\n#endif\n\ntemplate<class U, class ...Args>\ninline void construct(U* ptr, Args&&... args)\n{\n    new ((void*)ptr) U(std::forward<Args>(args)...);\n}\ntemplate<class U, class I, class ...Args>\ninline void construct_n(U* ptr, I n, Args&&... args)\n{\n    for(I i = 0; i < n; ++i)\n    {\n        new ((void*)(ptr + i)) U(args...);\n    }\n}\n\n#ifdef __clang__\n#   pragma clang diagnostic pop\n#elif defined(__GNUC__)\n#   pragma GCC diagnostic pop\n#endif\n\n\n//-----------------------------------------------------------------------------\n// copy-construct\n\ntemplate<class U> C4_ALWAYS_INLINE typename std::enable_if<std::is_trivially_copy_constructible<U>::value, void>::type\ncopy_construct(U* dst, U const* src) noexcept\n{\n    C4_ASSERT(dst != src);\n    memcpy(dst, src, sizeof(U));\n}\ntemplate<class U> C4_ALWAYS_INLINE typename std::enable_if< ! std::is_trivially_copy_constructible<U>::value, void>::type\ncopy_construct(U* dst, U const* src)\n{\n    C4_ASSERT(dst != src);\n    new ((void*)dst) U(*src);\n}\ntemplate<class U, class I> C4_ALWAYS_INLINE typename std::enable_if<std::is_trivially_copy_constructible<U>::value, void>::type\ncopy_construct_n(U* dst, U const* src, I n) noexcept\n{\n    C4_ASSERT(dst != src);\n    memcpy(dst, src, n * sizeof(U));\n}\ntemplate<class U, class I> C4_ALWAYS_INLINE typename std::enable_if< ! std::is_trivially_copy_constructible<U>::value, void>::type\ncopy_construct_n(U* dst, U const* src, I n)\n{\n    C4_ASSERT(dst != src);\n    for(I i = 0; i < n; ++i)\n    {\n        new ((void*)(dst + i)) U(*(src + i));\n    }\n}\n\ntemplate<class U> C4_ALWAYS_INLINE typename std::enable_if<std::is_scalar<U>::value, void>::type\ncopy_construct(U* dst, U src) noexcept // pass by value for scalar types\n{\n    *dst = src;\n}\ntemplate<class U> C4_ALWAYS_INLINE typename std::enable_if< ! std::is_scalar<U>::value, void>::type\ncopy_construct(U* dst, U const& src) // pass by reference for non-scalar types\n{\n    C4_ASSERT(dst != &src);\n    new ((void*)dst) U(src);\n}\ntemplate<class U, class I> C4_ALWAYS_INLINE typename std::enable_if<std::is_scalar<U>::value, void>::type\ncopy_construct_n(U* dst, U src, I n) noexcept // pass by value for scalar types\n{\n    for(I i = 0; i < n; ++i)\n    {\n        dst[i] = src;\n    }\n}\ntemplate<class U, class I> C4_ALWAYS_INLINE typename std::enable_if< ! std::is_scalar<U>::value, void>::type\ncopy_construct_n(U* dst, U const& src, I n) // pass by reference for non-scalar types\n{\n    C4_ASSERT(dst != &src);\n    for(I i = 0; i < n; ++i)\n    {\n        new ((void*)(dst + i)) U(src);\n    }\n}\n\ntemplate<class U, size_t N>\nC4_ALWAYS_INLINE void copy_construct(U (&dst)[N], U const (&src)[N]) noexcept\n{\n    copy_construct_n(dst, src, N);\n}\n\n//-----------------------------------------------------------------------------\n// copy-assign\n\ntemplate<class U> C4_ALWAYS_INLINE typename std::enable_if<std::is_trivially_copy_assignable<U>::value, void>::type\ncopy_assign(U* dst, U const* src) noexcept\n{\n    C4_ASSERT(dst != src);\n    memcpy(dst, src, sizeof(U));\n}\ntemplate<class U> C4_ALWAYS_INLINE typename std::enable_if< ! std::is_trivially_copy_assignable<U>::value, void>::type\ncopy_assign(U* dst, U const* src) noexcept\n{\n    C4_ASSERT(dst != src);\n    *dst = *src;\n}\ntemplate<class U, class I> C4_ALWAYS_INLINE typename std::enable_if<std::is_trivially_copy_assignable<U>::value, void>::type\ncopy_assign_n(U* dst, U const* src, I n) noexcept\n{\n    C4_ASSERT(dst != src);\n    memcpy(dst, src, n * sizeof(U));\n}\ntemplate<class U, class I> C4_ALWAYS_INLINE typename std::enable_if< ! std::is_trivially_copy_assignable<U>::value, void>::type\ncopy_assign_n(U* dst, U const* src, I n) noexcept\n{\n    C4_ASSERT(dst != src);\n    for(I i = 0; i < n; ++i)\n    {\n        dst[i] = src[i];\n    }\n}\n\ntemplate<class U> C4_ALWAYS_INLINE typename std::enable_if<std::is_scalar<U>::value, void>::type\ncopy_assign(U* dst, U src) noexcept // pass by value for scalar types\n{\n    *dst = src;\n}\ntemplate<class U> C4_ALWAYS_INLINE typename std::enable_if< ! std::is_scalar<U>::value, void>::type\ncopy_assign(U* dst, U const& src) noexcept // pass by reference for non-scalar types\n{\n    C4_ASSERT(dst != &src);\n    *dst = src;\n}\ntemplate<class U, class I> C4_ALWAYS_INLINE typename std::enable_if<std::is_scalar<U>::value, void>::type\ncopy_assign_n(U* dst, U src, I n) noexcept // pass by value for scalar types\n{\n    for(I i = 0; i < n; ++i)\n    {\n        dst[i] = src;\n    }\n}\ntemplate<class U, class I> C4_ALWAYS_INLINE typename std::enable_if< ! std::is_scalar<U>::value, void>::type\ncopy_assign_n(U* dst, U const& src, I n) noexcept // pass by reference for non-scalar types\n{\n    C4_ASSERT(dst != &src);\n    for(I i = 0; i < n; ++i)\n    {\n        dst[i] = src;\n    }\n}\n\ntemplate<class U, size_t N>\nC4_ALWAYS_INLINE void copy_assign(U (&dst)[N], U const (&src)[N]) noexcept\n{\n    copy_assign_n(dst, src, N);\n}\n\n//-----------------------------------------------------------------------------\n// move-construct\n\ntemplate<class U> C4_ALWAYS_INLINE typename std::enable_if<std::is_trivially_move_constructible<U>::value, void>::type\nmove_construct(U* dst, U* src) noexcept\n{\n    C4_ASSERT(dst != src);\n    memcpy(dst, src, sizeof(U));\n}\ntemplate<class U> C4_ALWAYS_INLINE typename std::enable_if< ! std::is_trivially_move_constructible<U>::value, void>::type\nmove_construct(U* dst, U* src) noexcept\n{\n    C4_ASSERT(dst != src);\n    new ((void*)dst) U(std::move(*src));\n}\ntemplate<class U, class I> C4_ALWAYS_INLINE typename std::enable_if<std::is_trivially_move_constructible<U>::value, void>::type\nmove_construct_n(U* dst, U* src, I n) noexcept\n{\n    C4_ASSERT(dst != src);\n    memcpy(dst, src, n * sizeof(U));\n}\ntemplate<class U, class I> C4_ALWAYS_INLINE typename std::enable_if< ! std::is_trivially_move_constructible<U>::value, void>::type\nmove_construct_n(U* dst, U* src, I n) noexcept\n{\n    C4_ASSERT(dst != src);\n    for(I i = 0; i < n; ++i)\n    {\n        new ((void*)(dst + i)) U(std::move(src[i]));\n    }\n}\n\n//-----------------------------------------------------------------------------\n// move-assign\n\ntemplate<class U> C4_ALWAYS_INLINE typename std::enable_if<std::is_trivially_move_assignable<U>::value, void>::type\nmove_assign(U* dst, U* src) noexcept\n{\n    C4_ASSERT(dst != src);\n    memcpy(dst, src, sizeof(U));\n}\ntemplate<class U> C4_ALWAYS_INLINE typename std::enable_if< ! std::is_trivially_move_assignable<U>::value, void>::type\nmove_assign(U* dst, U* src) noexcept\n{\n    C4_ASSERT(dst != src);\n    *dst = std::move(*src);\n}\ntemplate<class U, class I> C4_ALWAYS_INLINE typename std::enable_if<std::is_trivially_move_assignable<U>::value, void>::type\nmove_assign_n(U* dst, U* src, I n) noexcept\n{\n    C4_ASSERT(dst != src);\n    memcpy(dst, src, n * sizeof(U));\n}\ntemplate<class U, class I> C4_ALWAYS_INLINE typename std::enable_if< ! std::is_trivially_move_assignable<U>::value, void>::type\nmove_assign_n(U* dst, U* src, I n) noexcept\n{\n    C4_ASSERT(dst != src);\n    for(I i = 0; i < n; ++i)\n    {\n        *(dst + i) = std::move(*(src + i));\n    }\n}\n\n//-----------------------------------------------------------------------------\n// destroy\n\ntemplate<class U> C4_ALWAYS_INLINE typename std::enable_if<std::is_trivially_destructible<U>::value, void>::type\ndestroy(U* ptr) noexcept\n{\n    C4_UNUSED(ptr); // nothing to do\n}\ntemplate<class U> C4_ALWAYS_INLINE typename std::enable_if< ! std::is_trivially_destructible<U>::value, void>::type\ndestroy(U* ptr) noexcept\n{\n    ptr->~U();\n}\ntemplate<class U, class I> C4_ALWAYS_INLINE typename std::enable_if<std::is_trivially_destructible<U>::value, void>::type\ndestroy_n(U* ptr, I n) noexcept\n{\n    C4_UNUSED(ptr);\n    C4_UNUSED(n); // nothing to do\n}\ntemplate<class U, class I> C4_ALWAYS_INLINE typename std::enable_if< ! std::is_trivially_destructible<U>::value, void>::type\ndestroy_n(U* ptr, I n) noexcept\n{\n    for(I i = 0; i <n; ++i)\n    {\n        ptr[i].~U();\n    }\n}\n\n//-----------------------------------------------------------------------------\n\n/** makes room at the beginning of buf, which has a current size of n */\ntemplate<class U, class I> C4_ALWAYS_INLINE typename std::enable_if<std::is_trivially_move_constructible<U>::value, void>::type\nmake_room(U *buf, I bufsz, I room) C4_NOEXCEPT_A\n{\n    C4_ASSERT(bufsz >= 0 && room >= 0);\n    if(room >= bufsz)\n    {\n        memcpy (buf + room, buf, bufsz * sizeof(U));\n    }\n    else\n    {\n        memmove(buf + room, buf, bufsz * sizeof(U));\n    }\n}\n/** makes room at the beginning of buf, which has a current size of bufsz */\ntemplate<class U, class I> C4_ALWAYS_INLINE typename std::enable_if< ! std::is_trivially_move_constructible<U>::value, void>::type\nmake_room(U *buf, I bufsz, I room) C4_NOEXCEPT_A\n{\n    C4_ASSERT(bufsz >= 0 && room >= 0);\n    if(room >= bufsz)\n    {\n        for(I i = 0; i < bufsz; ++i)\n        {\n            new ((void*)(buf + (i + room))) U(std::move(buf[i]));\n        }\n    }\n    else\n    {\n        for(I i = 0; i < bufsz; ++i)\n        {\n            I w = bufsz-1 - i; // do a backwards loop\n            new ((void*)(buf + (w + room))) U(std::move(buf[w]));\n        }\n    }\n}\n\n/** make room to the right of pos */\ntemplate<class U, class I>\nC4_ALWAYS_INLINE void make_room(U *buf, I bufsz, I currsz, I pos, I room)\n{\n    C4_ASSERT(pos >= 0 && pos <= currsz);\n    C4_ASSERT(currsz <= bufsz);\n    C4_ASSERT(room + currsz <= bufsz);\n    C4_UNUSED(bufsz);\n    make_room(buf + pos, currsz - pos, room);\n}\n\n\n/** make room to the right of pos, copying to the beginning of a different buffer */\ntemplate<class U, class I> C4_ALWAYS_INLINE typename std::enable_if<std::is_trivially_move_constructible<U>::value, void>::type\nmake_room(U *dst, U const* src, I srcsz, I room, I pos) C4_NOEXCEPT_A\n{\n    C4_ASSERT(srcsz >= 0 && room >= 0 && pos >= 0);\n    C4_ASSERT(pos < srcsz || (pos == 0 && srcsz == 0));\n    memcpy(dst             , src      , pos           * sizeof(U));\n    memcpy(dst + room + pos, src + pos, (srcsz - pos) * sizeof(U));\n}\n/** make room to the right of pos, copying to the beginning of a different buffer */\ntemplate<class U, class I> C4_ALWAYS_INLINE typename std::enable_if< ! std::is_trivially_move_constructible<U>::value, void>::type\nmake_room(U *dst, U const* src, I srcsz, I room, I pos)\n{\n    C4_ASSERT(srcsz >= 0 && room >= 0 && pos >= 0);\n    C4_ASSERT(pos < srcsz || (pos == 0 && srcsz == 0));\n    for(I i = 0; i < pos; ++i)\n    {\n        new ((void*)(dst + i)) U(std::move(src[i]));\n    }\n    src += pos;\n    dst += room + pos;\n    for(I i = 0, e = srcsz - pos; i < e; ++i)\n    {\n        new ((void*)(dst + i)) U(std::move(src[i]));\n    }\n}\n\ntemplate<class U, class I>\nC4_ALWAYS_INLINE void make_room\n(\n    U      * dst, I dstsz,\n    U const* src, I srcsz,\n    I room, I pos\n)\n{\n    C4_ASSERT(pos >= 0 && pos < srcsz || (srcsz == 0 && pos == 0));\n    C4_ASSERT(pos >= 0 && pos < dstsz || (dstsz == 0 && pos == 0));\n    C4_ASSERT(srcsz+room <= dstsz);\n    C4_UNUSED(dstsz);\n    make_room(dst, src, srcsz, room, pos);\n}\n\n\n//-----------------------------------------------------------------------------\n/** destroy room at the beginning of buf, which has a current size of n */\ntemplate<class U, class I> C4_ALWAYS_INLINE typename std::enable_if<std::is_scalar<U>::value || (std::is_standard_layout<U>::value && std::is_trivial<U>::value), void>::type\ndestroy_room(U *buf, I n, I room) C4_NOEXCEPT_A\n{\n    C4_ASSERT(n >= 0 && room >= 0);\n    C4_ASSERT(room <= n);\n    if(room < n)\n    {\n        memmove(buf, buf + room, (n - room) * sizeof(U));\n    }\n    else\n    {\n        // nothing to do - no need to destroy scalar types\n    }\n}\n/** destroy room at the beginning of buf, which has a current size of n */\ntemplate<class U, class I> C4_ALWAYS_INLINE typename std::enable_if< ! (std::is_scalar<U>::value || (std::is_standard_layout<U>::value && std::is_trivial<U>::value)), void>::type\ndestroy_room(U *buf, I n, I room)\n{\n    C4_ASSERT(n >= 0 && room >= 0);\n    C4_ASSERT(room <= n);\n    if(room < n)\n    {\n        for(I i = 0, e = n - room; i < e; ++i)\n        {\n            buf[i] = std::move(buf[i + room]);\n        }\n    }\n    else\n    {\n        for(I i = 0; i < n; ++i)\n        {\n            buf[i].~U();\n        }\n    }\n}\n\n/** destroy room to the right of pos, copying to a different buffer */\ntemplate<class U, class I> C4_ALWAYS_INLINE typename std::enable_if<std::is_trivially_move_constructible<U>::value, void>::type\ndestroy_room(U *dst, U const* src, I n, I room, I pos) C4_NOEXCEPT_A\n{\n    C4_ASSERT(n >= 0 && room >= 0 && pos >= 0);\n    C4_ASSERT(pos <n);\n    C4_ASSERT(pos + room <= n);\n    memcpy(dst, src, pos * sizeof(U));\n    memcpy(dst + pos, src + room + pos, (n - pos - room) * sizeof(U));\n}\n/** destroy room to the right of pos, copying to a different buffer */\ntemplate<class U, class I> C4_ALWAYS_INLINE typename std::enable_if< ! std::is_trivially_move_constructible<U>::value, void>::type\ndestroy_room(U *dst, U const* src, I n, I room, I pos)\n{\n    C4_ASSERT(n >= 0 && room >= 0 && pos >= 0);\n    C4_ASSERT(pos < n);\n    C4_ASSERT(pos + room <= n);\n    for(I i = 0; i < pos; ++i)\n    {\n        new ((void*)(dst + i)) U(std::move(src[i]));\n    }\n    src += room + pos;\n    dst += pos;\n    for(I i = 0, e = n - pos - room; i < e; ++i)\n    {\n        new ((void*)(dst + i)) U(std::move(src[i]));\n    }\n}\n\nC4_SUPPRESS_WARNING_GCC_CLANG_POP\n\n} // namespace c4\n\n#endif /* _C4_CTOR_DTOR_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/dump.hpp",
    "content": "#ifndef C4_DUMP_HPP_\n#define C4_DUMP_HPP_\n\n#include <c4/substr.hpp>\n\nnamespace c4 {\n\nC4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH(\"-Wold-style-cast\")\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n/** type of the function to dump characters */\nusing DumperPfn = void (*)(csubstr buf);\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\ntemplate<DumperPfn dumpfn, class Arg>\ninline size_t dump(substr buf, Arg const& a)\n{\n    size_t sz = to_chars(buf, a); // need to serialize to the buffer\n    if(C4_LIKELY(sz <= buf.len))\n        dumpfn(buf.first(sz));\n    return sz;\n}\n\ntemplate<class DumperFn, class Arg>\ninline size_t dump(DumperFn &&dumpfn, substr buf, Arg const& a)\n{\n    size_t sz = to_chars(buf, a); // need to serialize to the buffer\n    if(C4_LIKELY(sz <= buf.len))\n        dumpfn(buf.first(sz));\n    return sz;\n}\n\ntemplate<DumperPfn dumpfn>\ninline size_t dump(substr buf, csubstr a)\n{\n    if(buf.len)\n        dumpfn(a); // dump directly, no need to serialize to the buffer\n    return 0; // no space was used in the buffer\n}\n\ntemplate<class DumperFn>\ninline size_t dump(DumperFn &&dumpfn, substr buf, csubstr a)\n{\n    if(buf.len)\n        dumpfn(a); // dump directly, no need to serialize to the buffer\n    return 0; // no space was used in the buffer\n}\n\ntemplate<DumperPfn dumpfn, size_t N>\ninline size_t dump(substr buf, const char (&a)[N])\n{\n    if(buf.len)\n        dumpfn(csubstr(a)); // dump directly, no need to serialize to the buffer\n    return 0; // no space was used in the buffer\n}\n\ntemplate<class DumperFn, size_t N>\ninline size_t dump(DumperFn &&dumpfn, substr buf, const char (&a)[N])\n{\n    if(buf.len)\n        dumpfn(csubstr(a)); // dump directly, no need to serialize to the buffer\n    return 0; // no space was used in the buffer\n}\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n/** */\nstruct DumpResults\n{\n    enum : size_t { noarg = (size_t)-1 };\n    size_t bufsize = 0;\n    size_t lastok = noarg;\n    bool success_until(size_t expected) const { return lastok == noarg ? false : lastok >= expected; }\n    bool write_arg(size_t arg) const { return lastok == noarg || arg > lastok; }\n    size_t argfail() const { return lastok + 1; }\n};\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n/// @cond dev\n// terminates the variadic recursion\ntemplate<class DumperFn>\nsize_t cat_dump(DumperFn &&, substr)\n{\n    return 0;\n}\n\n// terminates the variadic recursion\ntemplate<DumperPfn dumpfn>\nsize_t cat_dump(substr)\n{\n    return 0;\n}\n/// @endcond\n\n/** take the function pointer as a function argument */\ntemplate<class DumperFn, class Arg, class... Args>\nsize_t cat_dump(DumperFn &&dumpfn, substr buf, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)\n{\n    size_t size_for_a = dump(dumpfn, buf, a);\n    if(C4_UNLIKELY(size_for_a > buf.len))\n        buf = buf.first(0); // ensure no more calls\n    size_t size_for_more = cat_dump(dumpfn, buf, more...);\n    return size_for_more > size_for_a ? size_for_more : size_for_a;\n}\n\n/** take the function pointer as a template argument */\ntemplate<DumperPfn dumpfn,class Arg, class... Args>\nsize_t cat_dump(substr buf, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)\n{\n    size_t size_for_a = dump<dumpfn>(buf, a);\n    if(C4_LIKELY(size_for_a > buf.len))\n        buf = buf.first(0); // ensure no more calls\n    size_t size_for_more = cat_dump<dumpfn>(buf, more...);\n    return size_for_more > size_for_a ? size_for_more : size_for_a;\n}\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n/// @cond dev\nnamespace detail {\n\n// terminates the variadic recursion\ntemplate<DumperPfn dumpfn, class Arg>\nDumpResults cat_dump_resume(size_t currarg, DumpResults results, substr buf, Arg const& C4_RESTRICT a)\n{\n    if(C4_LIKELY(results.write_arg(currarg)))\n    {\n        size_t sz = dump<dumpfn>(buf, a);  // yield to the specialized function\n        if(currarg == results.lastok + 1 && sz <= buf.len)\n            results.lastok = currarg;\n        results.bufsize = sz > results.bufsize ? sz : results.bufsize;\n    }\n    return results;\n}\n\n// terminates the variadic recursion\ntemplate<class DumperFn, class Arg>\nDumpResults cat_dump_resume(size_t currarg, DumperFn &&dumpfn, DumpResults results, substr buf, Arg const& C4_RESTRICT a)\n{\n    if(C4_LIKELY(results.write_arg(currarg)))\n    {\n        size_t sz = dump(dumpfn, buf, a);  // yield to the specialized function\n        if(currarg == results.lastok + 1 && sz <= buf.len)\n            results.lastok = currarg;\n        results.bufsize = sz > results.bufsize ? sz : results.bufsize;\n    }\n    return results;\n}\n\ntemplate<DumperPfn dumpfn, class Arg, class... Args>\nDumpResults cat_dump_resume(size_t currarg, DumpResults results, substr buf, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)\n{\n    results = detail::cat_dump_resume<dumpfn>(currarg, results, buf, a);\n    return detail::cat_dump_resume<dumpfn>(currarg + 1u, results, buf, more...);\n}\n\ntemplate<class DumperFn, class Arg, class... Args>\nDumpResults cat_dump_resume(size_t currarg, DumperFn &&dumpfn, DumpResults results, substr buf, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)\n{\n    results = detail::cat_dump_resume(currarg, dumpfn, results, buf, a);\n    return detail::cat_dump_resume(currarg + 1u, dumpfn, results, buf, more...);\n}\n} // namespace detail\n/// @endcond\n\n\ntemplate<DumperPfn dumpfn, class Arg, class... Args>\nC4_ALWAYS_INLINE DumpResults cat_dump_resume(DumpResults results, substr buf, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)\n{\n    if(results.bufsize > buf.len)\n        return results;\n    return detail::cat_dump_resume<dumpfn>(0u, results, buf, a, more...);\n}\n\ntemplate<class DumperFn, class Arg, class... Args>\nC4_ALWAYS_INLINE DumpResults cat_dump_resume(DumperFn &&dumpfn, DumpResults results, substr buf, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)\n{\n    if(results.bufsize > buf.len)\n        return results;\n    return detail::cat_dump_resume(0u, dumpfn, results, buf, a, more...);\n}\n\ntemplate<DumperPfn dumpfn, class Arg, class... Args>\nC4_ALWAYS_INLINE DumpResults cat_dump_resume(substr buf, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)\n{\n    return detail::cat_dump_resume<dumpfn>(0u, DumpResults{}, buf, a, more...);\n}\n\ntemplate<class DumperFn, class Arg, class... Args>\nC4_ALWAYS_INLINE DumpResults cat_dump_resume(DumperFn &&dumpfn, substr buf, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)\n{\n    return detail::cat_dump_resume(0u, dumpfn, DumpResults{}, buf, a, more...);\n}\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n/// @cond dev\n// terminate the recursion\ntemplate<class DumperFn, class Sep>\nsize_t catsep_dump(DumperFn &&, substr, Sep const& C4_RESTRICT)\n{\n    return 0;\n}\n\n// terminate the recursion\ntemplate<DumperPfn dumpfn, class Sep>\nsize_t catsep_dump(substr, Sep const& C4_RESTRICT)\n{\n    return 0;\n}\n/// @endcond\n\n/** take the function pointer as a function argument */\ntemplate<class DumperFn, class Sep, class Arg, class... Args>\nsize_t catsep_dump(DumperFn &&dumpfn, substr buf, Sep const& C4_RESTRICT sep, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)\n{\n    size_t sz = dump(dumpfn, buf, a);\n    if(C4_UNLIKELY(sz > buf.len))\n        buf = buf.first(0); // ensure no more calls\n    if C4_IF_CONSTEXPR (sizeof...(more) > 0)\n    {\n        size_t szsep = dump(dumpfn, buf, sep);\n        if(C4_UNLIKELY(szsep > buf.len))\n            buf = buf.first(0); // ensure no more calls\n        sz = sz > szsep ? sz : szsep;\n    }\n    size_t size_for_more = catsep_dump(dumpfn, buf, sep, more...);\n    return size_for_more > sz ? size_for_more : sz;\n}\n\n/** take the function pointer as a template argument */\ntemplate<DumperPfn dumpfn, class Sep, class Arg, class... Args>\nsize_t catsep_dump(substr buf, Sep const& C4_RESTRICT sep, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)\n{\n    size_t sz = dump<dumpfn>(buf, a);\n    if(C4_UNLIKELY(sz > buf.len))\n        buf = buf.first(0); // ensure no more calls\n    if C4_IF_CONSTEXPR (sizeof...(more) > 0)\n    {\n        size_t szsep = dump<dumpfn>(buf, sep);\n        if(C4_UNLIKELY(szsep > buf.len))\n            buf = buf.first(0); // ensure no more calls\n        sz = sz > szsep ? sz : szsep;\n    }\n    size_t size_for_more = catsep_dump<dumpfn>(buf, sep, more...);\n    return size_for_more > sz ? size_for_more : sz;\n}\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n/// @cond dev\nnamespace detail {\ntemplate<DumperPfn dumpfn, class Arg>\nvoid catsep_dump_resume_(size_t currarg, DumpResults *C4_RESTRICT results, substr *C4_RESTRICT buf, Arg const& C4_RESTRICT a)\n{\n    if(C4_LIKELY(results->write_arg(currarg)))\n    {\n        size_t sz = dump<dumpfn>(*buf, a);\n        results->bufsize = sz > results->bufsize ? sz : results->bufsize;\n        if(C4_LIKELY(sz <= buf->len))\n            results->lastok = currarg;\n        else\n            buf->len = 0;\n    }\n}\n\ntemplate<class DumperFn, class Arg>\nvoid catsep_dump_resume_(size_t currarg, DumperFn &&dumpfn, DumpResults *C4_RESTRICT results, substr *C4_RESTRICT buf, Arg const& C4_RESTRICT a)\n{\n    if(C4_LIKELY(results->write_arg(currarg)))\n    {\n        size_t sz = dump(dumpfn, *buf, a);\n        results->bufsize = sz > results->bufsize ? sz : results->bufsize;\n        if(C4_LIKELY(sz <= buf->len))\n            results->lastok = currarg;\n        else\n            buf->len = 0;\n    }\n}\n\ntemplate<DumperPfn dumpfn, class Sep, class Arg>\nC4_ALWAYS_INLINE void catsep_dump_resume(size_t currarg, DumpResults *C4_RESTRICT results, substr *C4_RESTRICT buf, Sep const& C4_RESTRICT, Arg const& C4_RESTRICT a)\n{\n    detail::catsep_dump_resume_<dumpfn>(currarg, results, buf, a);\n}\n\ntemplate<class DumperFn, class Sep, class Arg>\nC4_ALWAYS_INLINE void catsep_dump_resume(size_t currarg, DumperFn &&dumpfn, DumpResults *C4_RESTRICT results, substr *C4_RESTRICT buf, Sep const& C4_RESTRICT, Arg const& C4_RESTRICT a)\n{\n    detail::catsep_dump_resume_(currarg, dumpfn, results, buf, a);\n}\n\ntemplate<DumperPfn dumpfn, class Sep, class Arg, class... Args>\nC4_ALWAYS_INLINE void catsep_dump_resume(size_t currarg, DumpResults *C4_RESTRICT results, substr *C4_RESTRICT buf, Sep const& C4_RESTRICT sep, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)\n{\n    detail::catsep_dump_resume_<dumpfn>(currarg     , results, buf, a);\n    detail::catsep_dump_resume_<dumpfn>(currarg + 1u, results, buf, sep);\n    detail::catsep_dump_resume <dumpfn>(currarg + 2u, results, buf, sep, more...);\n}\n\ntemplate<class DumperFn, class Sep, class Arg, class... Args>\nC4_ALWAYS_INLINE void catsep_dump_resume(size_t currarg, DumperFn &&dumpfn, DumpResults *C4_RESTRICT results, substr *C4_RESTRICT buf, Sep const& C4_RESTRICT sep, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)\n{\n    detail::catsep_dump_resume_(currarg     , dumpfn, results, buf, a);\n    detail::catsep_dump_resume_(currarg + 1u, dumpfn, results, buf, sep);\n    detail::catsep_dump_resume (currarg + 2u, dumpfn, results, buf, sep, more...);\n}\n} // namespace detail\n/// @endcond\n\n\ntemplate<DumperPfn dumpfn, class Sep, class... Args>\nC4_ALWAYS_INLINE DumpResults catsep_dump_resume(DumpResults results, substr buf, Sep const& C4_RESTRICT sep, Args const& C4_RESTRICT ...more)\n{\n    detail::catsep_dump_resume<dumpfn>(0u, &results, &buf, sep, more...);\n    return results;\n}\n\ntemplate<class DumperFn, class Sep, class... Args>\nC4_ALWAYS_INLINE DumpResults catsep_dump_resume(DumperFn &&dumpfn, DumpResults results, substr buf, Sep const& C4_RESTRICT sep, Args const& C4_RESTRICT ...more)\n{\n    detail::catsep_dump_resume(0u, dumpfn, &results, &buf, sep, more...);\n    return results;\n}\n\ntemplate<DumperPfn dumpfn, class Sep, class... Args>\nC4_ALWAYS_INLINE DumpResults catsep_dump_resume(substr buf, Sep const& C4_RESTRICT sep, Args const& C4_RESTRICT ...more)\n{\n    DumpResults results;\n    detail::catsep_dump_resume<dumpfn>(0u, &results, &buf, sep, more...);\n    return results;\n}\n\ntemplate<class DumperFn, class Sep, class... Args>\nC4_ALWAYS_INLINE DumpResults catsep_dump_resume(DumperFn &&dumpfn, substr buf, Sep const& C4_RESTRICT sep, Args const& C4_RESTRICT ...more)\n{\n    DumpResults results;\n    detail::catsep_dump_resume(0u, dumpfn, &results, &buf, sep, more...);\n    return results;\n}\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n/// @cond dev\n\n/** take the function pointer as a function argument */\ntemplate<class DumperFn>\nC4_ALWAYS_INLINE size_t format_dump(DumperFn &&dumpfn, substr buf, csubstr fmt)\n{\n    // we can dump without using buf\n    // but we'll only dump if the buffer is ok\n    if(C4_LIKELY(buf.len > 0 && fmt.len))\n        dumpfn(fmt);\n    return 0u;\n}\n\n/** take the function pointer as a template argument */\ntemplate<DumperPfn dumpfn>\nC4_ALWAYS_INLINE size_t format_dump(substr buf, csubstr fmt)\n{\n    // we can dump without using buf\n    // but we'll only dump if the buffer is ok\n    if(C4_LIKELY(buf.len > 0 && fmt.len > 0))\n        dumpfn(fmt);\n    return 0u;\n}\n\n/// @endcond\n\n\n/** take the function pointer as a function argument */\ntemplate<class DumperFn, class Arg, class... Args>\nC4_NO_INLINE size_t format_dump(DumperFn &&dumpfn, substr buf, csubstr fmt, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)\n{\n    // we can dump without using buf\n    // but we'll only dump if the buffer is ok\n    size_t pos = fmt.find(\"{}\"); // @todo use _find_fmt()\n    if(C4_UNLIKELY(pos == csubstr::npos))\n    {\n        if(C4_LIKELY(buf.len > 0 && fmt.len > 0))\n            dumpfn(fmt);\n        return 0u;\n    }\n    if(C4_LIKELY(buf.len > 0 && pos > 0))\n        dumpfn(fmt.first(pos)); // we can dump without using buf\n    fmt = fmt.sub(pos + 2); // skip {} do this before assigning to pos again\n    pos = dump(dumpfn, buf, a);\n    if(C4_UNLIKELY(pos > buf.len))\n        buf.len = 0; // ensure no more calls to dump\n    size_t size_for_more = format_dump(dumpfn, buf, fmt, more...);\n    return size_for_more > pos ? size_for_more : pos;\n}\n\n/** take the function pointer as a template argument */\ntemplate<DumperPfn dumpfn, class Arg, class... Args>\nC4_NO_INLINE size_t format_dump(substr buf, csubstr fmt, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)\n{\n    // we can dump without using buf\n    // but we'll only dump if the buffer is ok\n    size_t pos = fmt.find(\"{}\"); // @todo use _find_fmt()\n    if(C4_UNLIKELY(pos == csubstr::npos))\n    {\n        if(C4_LIKELY(buf.len > 0 && fmt.len > 0))\n            dumpfn(fmt);\n        return 0u;\n    }\n    if(C4_LIKELY(buf.len > 0 && pos > 0))\n        dumpfn(fmt.first(pos)); // we can dump without using buf\n    fmt = fmt.sub(pos + 2); // skip {} do this before assigning to pos again\n    pos = dump<dumpfn>(buf, a);\n    if(C4_UNLIKELY(pos > buf.len))\n        buf.len = 0; // ensure no more calls to dump\n    size_t size_for_more = format_dump<dumpfn>(buf, fmt, more...);\n    return size_for_more > pos ? size_for_more : pos;\n}\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n/// @cond dev\nnamespace detail {\n\ntemplate<DumperPfn dumpfn>\nDumpResults format_dump_resume(size_t currarg, DumpResults results, substr buf, csubstr fmt)\n{\n    // we can dump without using buf\n    // but we'll only dump if the buffer is ok\n    if(C4_LIKELY(buf.len > 0))\n    {\n        dumpfn(fmt);\n        results.lastok = currarg;\n    }\n    return results;\n}\n\ntemplate<class DumperFn>\nDumpResults format_dump_resume(size_t currarg, DumperFn &&dumpfn, DumpResults results, substr buf, csubstr fmt)\n{\n    // we can dump without using buf\n    // but we'll only dump if the buffer is ok\n    if(C4_LIKELY(buf.len > 0))\n    {\n        dumpfn(fmt);\n        results.lastok = currarg;\n    }\n    return results;\n}\n\ntemplate<DumperPfn dumpfn, class Arg, class... Args>\nDumpResults format_dump_resume(size_t currarg, DumpResults results, substr buf, csubstr fmt, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)\n{\n    // we need to process the format even if we're not\n    // going to print the first arguments because we're resuming\n    size_t pos = fmt.find(\"{}\"); // @todo use _find_fmt()\n    // we can dump without using buf\n    // but we'll only dump if the buffer is ok\n    if(C4_LIKELY(results.write_arg(currarg)))\n    {\n        if(C4_UNLIKELY(pos == csubstr::npos))\n        {\n            if(C4_LIKELY(buf.len > 0))\n            {\n                results.lastok = currarg;\n                dumpfn(fmt);\n            }\n            return results;\n        }\n        if(C4_LIKELY(buf.len > 0))\n        {\n            results.lastok = currarg;\n            dumpfn(fmt.first(pos));\n        }\n    }\n    fmt = fmt.sub(pos + 2);\n    if(C4_LIKELY(results.write_arg(currarg + 1)))\n    {\n        pos = dump<dumpfn>(buf, a);\n        results.bufsize = pos > results.bufsize ? pos : results.bufsize;\n        if(C4_LIKELY(pos <= buf.len))\n            results.lastok = currarg + 1;\n        else\n            buf.len = 0;\n    }\n    return detail::format_dump_resume<dumpfn>(currarg + 2u, results, buf, fmt, more...);\n}\n/// @endcond\n\n\ntemplate<class DumperFn, class Arg, class... Args>\nDumpResults format_dump_resume(size_t currarg, DumperFn &&dumpfn, DumpResults results, substr buf, csubstr fmt, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)\n{\n    // we need to process the format even if we're not\n    // going to print the first arguments because we're resuming\n    size_t pos = fmt.find(\"{}\"); // @todo use _find_fmt()\n    // we can dump without using buf\n    // but we'll only dump if the buffer is ok\n    if(C4_LIKELY(results.write_arg(currarg)))\n    {\n        if(C4_UNLIKELY(pos == csubstr::npos))\n        {\n            if(C4_LIKELY(buf.len > 0))\n            {\n                results.lastok = currarg;\n                dumpfn(fmt);\n            }\n            return results;\n        }\n        if(C4_LIKELY(buf.len > 0))\n        {\n            results.lastok = currarg;\n            dumpfn(fmt.first(pos));\n        }\n    }\n    fmt = fmt.sub(pos + 2);\n    if(C4_LIKELY(results.write_arg(currarg + 1)))\n    {\n        pos = dump(dumpfn, buf, a);\n        results.bufsize = pos > results.bufsize ? pos : results.bufsize;\n        if(C4_LIKELY(pos <= buf.len))\n            results.lastok = currarg + 1;\n        else\n            buf.len = 0;\n    }\n    return detail::format_dump_resume(currarg + 2u, dumpfn, results, buf, fmt, more...);\n}\n} // namespace detail\n\n\ntemplate<DumperPfn dumpfn, class... Args>\nC4_ALWAYS_INLINE DumpResults format_dump_resume(DumpResults results, substr buf, csubstr fmt, Args const& C4_RESTRICT ...more)\n{\n    return detail::format_dump_resume<dumpfn>(0u, results, buf, fmt, more...);\n}\n\ntemplate<class DumperFn, class... Args>\nC4_ALWAYS_INLINE DumpResults format_dump_resume(DumperFn &&dumpfn, DumpResults results, substr buf, csubstr fmt, Args const& C4_RESTRICT ...more)\n{\n    return detail::format_dump_resume(0u, dumpfn, results, buf, fmt, more...);\n}\n\n\ntemplate<DumperPfn dumpfn, class... Args>\nC4_ALWAYS_INLINE DumpResults format_dump_resume(substr buf, csubstr fmt, Args const& C4_RESTRICT ...more)\n{\n    return detail::format_dump_resume<dumpfn>(0u, DumpResults{}, buf, fmt, more...);\n}\n\ntemplate<class DumperFn, class... Args>\nC4_ALWAYS_INLINE DumpResults format_dump_resume(DumperFn &&dumpfn, substr buf, csubstr fmt, Args const& C4_RESTRICT ...more)\n{\n    return detail::format_dump_resume(0u, dumpfn, DumpResults{}, buf, fmt, more...);\n}\n\nC4_SUPPRESS_WARNING_GCC_CLANG_POP\n\n} // namespace c4\n\n\n#endif /* C4_DUMP_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/enum.hpp",
    "content": "#ifndef _C4_ENUM_HPP_\n#define _C4_ENUM_HPP_\n\n#include \"c4/error.hpp\"\n#include <string.h>\n\n/** @file enum.hpp utilities for enums: convert to/from string\n */\n\n\nnamespace c4 {\n\nC4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH(\"-Wold-style-cast\")\n\n//! taken from http://stackoverflow.com/questions/15586163/c11-type-trait-to-differentiate-between-enum-class-and-regular-enum\ntemplate<typename Enum>\nusing is_scoped_enum = std::integral_constant<bool, std::is_enum<Enum>::value && !std::is_convertible<Enum, int>::value>;\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\ntypedef enum {\n    EOFFS_NONE = 0,  ///< no offset\n    EOFFS_CLS = 1,   ///< get the enum offset for the class name. @see eoffs_cls()\n    EOFFS_PFX = 2,   ///< get the enum offset for the enum prefix. @see eoffs_pfx()\n    _EOFFS_LAST      ///< reserved\n} EnumOffsetType;\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n/** A simple (proxy) container for the value-name pairs of an enum type.\n * Uses linear search for finds; this could be improved for time-critical\n * code. */\ntemplate<class Enum>\nclass EnumSymbols\n{\npublic:\n\n    struct Sym\n    {\n        Enum value;\n        const char *name;\n\n        bool cmp(const char *s) const;\n        bool cmp(const char *s, size_t len) const;\n\n        const char *name_offs(EnumOffsetType t) const;\n    };\n\n    using const_iterator = Sym const*;\n\npublic:\n\n    template<size_t N>\n    EnumSymbols(Sym const (&p)[N]) : m_symbols(p), m_num(N) {}\n\n    size_t size() const { return m_num; }\n    bool empty() const { return m_num == 0; }\n\n    Sym const* get(Enum v) const { auto p = find(v); C4_CHECK_MSG(p != nullptr, \"could not find symbol=%zd\", (std::ptrdiff_t)v); return p; }\n    Sym const* get(const char *s) const { auto p = find(s); C4_CHECK_MSG(p != nullptr, \"could not find symbol \\\"%s\\\"\", s); return p; }\n    Sym const* get(const char *s, size_t len) const { auto p = find(s, len); C4_CHECK_MSG(p != nullptr, \"could not find symbol \\\"%.*s\\\"\", len, s); return p; }\n\n    Sym const* find(Enum v) const;\n    Sym const* find(const char *s) const;\n    Sym const* find(const char *s, size_t len) const;\n\n    Sym const& operator[] (size_t i) const { C4_CHECK(i < m_num); return m_symbols[i]; }\n\n    Sym const* begin() const { return m_symbols; }\n    Sym const* end  () const { return m_symbols + m_num; }\n\nprivate:\n\n    Sym const* m_symbols;\n    size_t const m_num;\n\n};\n\n//-----------------------------------------------------------------------------\n/** return an EnumSymbols object for the enum type T\n *\n * @warning SPECIALIZE! This needs to be specialized for each enum\n * type. Failure to provide a specialization will cause a linker\n * error. */\ntemplate<class Enum>\nEnumSymbols<Enum> const esyms();\n\n\n/** return the offset for an enum symbol class. For example,\n * eoffs_cls<MyEnumClass>() would be 13=strlen(\"MyEnumClass::\").\n *\n * With this function you can announce that the full prefix (including\n * an eventual enclosing class or C++11 enum class) is of a certain\n * length.\n *\n * @warning Needs to be specialized for each enum class type that\n * wants to use this. When no specialization is given, will return\n * 0. */\ntemplate<class Enum>\nsize_t eoffs_cls()\n{\n    return 0;\n}\n\n\n/** return the offset for an enum symbol prefix. This includes\n * eoffs_cls().  With this function you can announce that the full\n * prefix (including an eventual enclosing class or C++11 enum class\n * plus the string prefix) is of a certain length.\n *\n * @warning Needs to be specialized for each enum class type that\n * wants to use this. When no specialization is given, will return\n * 0. */\ntemplate<class Enum>\nsize_t eoffs_pfx()\n{\n    return 0;\n}\n\n\ntemplate<class Enum>\nsize_t eoffs(EnumOffsetType which)\n{\n    switch(which)\n    {\n    case EOFFS_NONE:\n        return 0;\n    case EOFFS_CLS:\n        return eoffs_cls<Enum>();\n    case EOFFS_PFX:\n    {\n        size_t pfx = eoffs_pfx<Enum>();\n        return pfx > 0 ? pfx : eoffs_cls<Enum>();\n    }\n    default:\n        C4_ERROR(\"unknown offset type %d\", (int)which);\n    }\n}\n\n\n//-----------------------------------------------------------------------------\n/** get the enum value corresponding to a c-string */\n\n#ifdef __clang__\n#   pragma clang diagnostic push\n#elif defined(__GNUC__)\n#   pragma GCC diagnostic push\n#   if __GNUC__ >= 6\n#       pragma GCC diagnostic ignored \"-Wnull-dereference\"\n#   endif\n#endif\n\ntemplate<class Enum>\nEnum str2e(const char* str)\n{\n    auto pairs = esyms<Enum>();\n    auto *p = pairs.get(str);\n    C4_CHECK_MSG(p != nullptr, \"no valid enum pair name for '%s'\", str);\n    return p->value;\n}\n\n/** get the c-string corresponding to an enum value */\ntemplate<class Enum>\nconst char* e2str(Enum e)\n{\n    auto es = esyms<Enum>();\n    auto *p = es.get(e);\n    C4_CHECK_MSG(p != nullptr, \"no valid enum pair name\");\n    return p->name;\n}\n\n/** like e2str(), but add an offset. */\ntemplate<class Enum>\nconst char* e2stroffs(Enum e, EnumOffsetType ot=EOFFS_PFX)\n{\n    const char *s = e2str<Enum>(e) + eoffs<Enum>(ot);\n    return s;\n}\n\n#ifdef __clang__\n#   pragma clang diagnostic pop\n#elif defined(__GNUC__)\n#   pragma GCC diagnostic pop\n#endif\n\n//-----------------------------------------------------------------------------\n/** Find a symbol by value. Returns nullptr when none is found */\ntemplate<class Enum>\ntypename EnumSymbols<Enum>::Sym const* EnumSymbols<Enum>::find(Enum v) const\n{\n    for(Sym const* p = this->m_symbols, *e = p+this->m_num; p < e; ++p)\n        if(p->value == v)\n            return p;\n    return nullptr;\n}\n\n/** Find a symbol by name. Returns nullptr when none is found */\ntemplate<class Enum>\ntypename EnumSymbols<Enum>::Sym const* EnumSymbols<Enum>::find(const char *s) const\n{\n    for(Sym const* p = this->m_symbols, *e = p+this->m_num; p < e; ++p)\n        if(p->cmp(s))\n            return p;\n    return nullptr;\n}\n\n/** Find a symbol by name. Returns nullptr when none is found */\ntemplate<class Enum>\ntypename EnumSymbols<Enum>::Sym const* EnumSymbols<Enum>::find(const char *s, size_t len) const\n{\n    for(Sym const* p = this->m_symbols, *e = p+this->m_num; p < e; ++p)\n        if(p->cmp(s, len))\n            return p;\n    return nullptr;\n}\n\n//-----------------------------------------------------------------------------\ntemplate<class Enum>\nbool EnumSymbols<Enum>::Sym::cmp(const char *s) const\n{\n    if(strcmp(name, s) == 0)\n        return true;\n\n    for(int i = 1; i < _EOFFS_LAST; ++i)\n    {\n        auto o = eoffs<Enum>((EnumOffsetType)i);\n        if(o > 0)\n            if(strcmp(name + o, s) == 0)\n                return true;\n    }\n\n    return false;\n}\n\ntemplate<class Enum>\nbool EnumSymbols<Enum>::Sym::cmp(const char *s, size_t len) const\n{\n    if(strncmp(name, s, len) == 0)\n        return true;\n\n    size_t nlen = 0;\n    for(int i = 1; i <_EOFFS_LAST; ++i)\n    {\n        auto o = eoffs<Enum>((EnumOffsetType)i);\n        if(o > 0)\n        {\n            if(!nlen)\n            {\n                nlen = strlen(name);\n            }\n            C4_ASSERT(o < nlen);\n            size_t rem = nlen - o;\n            auto m = len > rem ? len : rem;\n            if(len >= m && strncmp(name + o, s, m) == 0)\n                return true;\n        }\n    }\n\n    return false;\n}\n\n//-----------------------------------------------------------------------------\ntemplate<class Enum>\nconst char* EnumSymbols<Enum>::Sym::name_offs(EnumOffsetType t) const\n{\n    C4_ASSERT(eoffs<Enum>(t) < strlen(name));\n    return name + eoffs<Enum>(t);\n}\n\nC4_SUPPRESS_WARNING_GCC_CLANG_POP\n\n} // namespace c4\n\n#endif // _C4_ENUM_HPP_\n"
  },
  {
    "path": "libs/rapidyaml/c4/error.cpp",
    "content": "#include \"c4/error.hpp\"\n\n#include <stdlib.h>\n#include <stdio.h>\n#include <stdarg.h>\n\n#define C4_LOGF_ERR(...) fprintf(stderr, __VA_ARGS__); fflush(stderr)\n#define C4_LOGF_WARN(...) fprintf(stderr, __VA_ARGS__); fflush(stderr)\n#define C4_LOGP(msg, ...) printf(msg)\n\n#if defined(C4_XBOX) || (defined(C4_WIN) && defined(C4_MSVC))\n#   include \"c4/windows.hpp\"\n#elif defined(C4_PS4)\n#   include <libdbg.h>\n#elif defined(C4_UNIX) || defined(C4_LINUX)\n#   include <sys/stat.h>\n#   include <cstring>\n#   include <fcntl.h>\n#elif defined(C4_MACOS) || defined(C4_IOS)\n#   include <assert.h>\n#   include <stdbool.h>\n#   include <sys/types.h>\n#   include <sys/sysctl.h>\n#endif\n// the amalgamation tool is dumb and was omitting this include under MACOS.\n// So do it only once:\n#if defined(C4_UNIX) || defined(C4_LINUX) || defined(C4_MACOS) || defined(C4_IOS)\n#   include <unistd.h>\n#endif\n\n#if defined(C4_EXCEPTIONS_ENABLED) && defined(C4_ERROR_THROWS_EXCEPTION)\n#   include <exception>\n#endif\n\n#ifdef __clang__\n#   pragma clang diagnostic push\n#   pragma clang diagnostic ignored \"-Wformat-nonliteral\"\n#   pragma clang diagnostic ignored \"-Wold-style-cast\"\n#elif defined(__GNUC__)\n#   pragma GCC diagnostic push\n#   pragma GCC diagnostic ignored \"-Wformat-nonliteral\"\n#   pragma GCC diagnostic ignored \"-Wold-style-cast\"\n#endif\n\n\n//-----------------------------------------------------------------------------\nnamespace c4 {\n\nstatic error_flags         s_error_flags = ON_ERROR_DEFAULTS;\nstatic error_callback_type s_error_callback = nullptr;\n\n\n//-----------------------------------------------------------------------------\n\nerror_flags get_error_flags()\n{\n    return s_error_flags;\n}\nvoid set_error_flags(error_flags flags)\n{\n    s_error_flags = flags;\n}\n\nerror_callback_type get_error_callback()\n{\n    return s_error_callback;\n}\n/** Set the function which is called when an error occurs. */\nvoid set_error_callback(error_callback_type cb)\n{\n    s_error_callback = cb;\n}\n\n\n//-----------------------------------------------------------------------------\n\nvoid handle_error(srcloc where, const char *fmt, ...)\n{\n    char buf[1024];\n    size_t msglen = 0;\n    if(s_error_flags & (ON_ERROR_LOG|ON_ERROR_CALLBACK))\n    {\n        va_list args;\n        va_start(args, fmt);\n        int ilen = vsnprintf(buf, sizeof(buf), fmt, args); // ss.vprintf(fmt, args);\n        va_end(args);\n        msglen = ilen >= 0 && ilen < (int)sizeof(buf) ? static_cast<size_t>(ilen) : sizeof(buf)-1;\n    }\n\n    if(s_error_flags & ON_ERROR_LOG)\n    {\n        C4_LOGF_ERR(\"\\n\");\n#if defined(C4_ERROR_SHOWS_FILELINE) && defined(C4_ERROR_SHOWS_FUNC)\n        C4_LOGF_ERR(\"%s:%d: ERROR: %s\\n\", where.file, where.line, buf);\n        C4_LOGF_ERR(\"%s:%d: ERROR here: %s\\n\", where.file, where.line, where.func);\n#elif defined(C4_ERROR_SHOWS_FILELINE)\n        C4_LOGF_ERR(\"%s:%d: ERROR: %s\\n\", where.file, where.line, buf);\n#elif ! defined(C4_ERROR_SHOWS_FUNC)\n        C4_LOGF_ERR(\"ERROR: %s\\n\", buf);\n#endif\n    }\n\n    if(s_error_flags & ON_ERROR_CALLBACK)\n    {\n        if(s_error_callback)\n        {\n            s_error_callback(buf, msglen);\n        }\n    }\n\n    if(s_error_flags & ON_ERROR_THROW)\n    {\n#if defined(C4_EXCEPTIONS_ENABLED) && defined(C4_ERROR_THROWS_EXCEPTION)\n        throw std::runtime_error(buf);\n#endif\n    }\n\n    if(s_error_flags & ON_ERROR_ABORT)\n    {\n        abort();\n    }\n\n    abort(); // abort anyway, in case nothing was set\n    C4_UNREACHABLE_AFTER_ERR();\n}\n\n//-----------------------------------------------------------------------------\n\nvoid handle_warning(srcloc where, const char *fmt, ...)\n{\n    va_list args;\n    char buf[1024];\n    va_start(args, fmt);\n    vsnprintf(buf, sizeof(buf), fmt, args);\n    va_end(args);\n    C4_LOGF_WARN(\"\\n\");\n#if defined(C4_ERROR_SHOWS_FILELINE) && defined(C4_ERROR_SHOWS_FUNC)\n    C4_LOGF_WARN(\"%s:%d: WARNING: %s\\n\", where.file, where.line, buf);\n    C4_LOGF_WARN(\"%s:%d: WARNING: here: %s\\n\", where.file, where.line, where.func);\n#elif defined(C4_ERROR_SHOWS_FILELINE)\n    C4_LOGF_WARN(\"%s:%d: WARNING: %s\\n\", where.file, where.line, buf);\n#elif ! defined(C4_ERROR_SHOWS_FUNC)\n    C4_LOGF_WARN(\"WARNING: %s\\n\", buf);\n#endif\n}\n\n//-----------------------------------------------------------------------------\nbool is_debugger_attached()\n{\n#if defined(C4_UNIX) || defined(C4_LINUX)\n    static bool first_call = true;\n    static bool first_call_result = false;\n    if(first_call)\n    {\n        first_call = false;\n        C4_SUPPRESS_WARNING_GCC_PUSH\n        #if defined(__GNUC__) && __GNUC__ > 9\n        C4_SUPPRESS_WARNING_GCC(\"-Wanalyzer-fd-leak\")\n        #endif\n        //! @see http://stackoverflow.com/questions/3596781/how-to-detect-if-the-current-process-is-being-run-by-gdb\n        //! (this answer: http://stackoverflow.com/a/24969863/3968589 )\n        char buf[1024] = \"\";\n        int status_fd = open(\"/proc/self/status\", O_RDONLY);\n        if (status_fd == -1)\n        {\n            return 0;\n        }\n        else\n        {\n            ssize_t num_read = ::read(status_fd, buf, sizeof(buf));\n            if (num_read > 0)\n            {\n                static const char TracerPid[] = \"TracerPid:\";\n                char *tracer_pid;\n                if(num_read < 1024)\n                {\n                    buf[num_read] = 0;\n                }\n                tracer_pid = strstr(buf, TracerPid);\n                if (tracer_pid)\n                {\n                    first_call_result = !!::atoi(tracer_pid + sizeof(TracerPid) - 1);\n                }\n            }\n            close(status_fd);\n        }\n        C4_SUPPRESS_WARNING_GCC_POP\n    }\n    return first_call_result;\n#elif defined(C4_PS4)\n    return (sceDbgIsDebuggerAttached() != 0);\n#elif defined(C4_XBOX) || (defined(C4_WIN) && defined(C4_MSVC))\n    return IsDebuggerPresent() != 0;\n#elif defined(C4_MACOS) || defined(C4_IOS)\n    // https://stackoverflow.com/questions/2200277/detecting-debugger-on-mac-os-x\n    // Returns true if the current process is being debugged (either\n    // running under the debugger or has a debugger attached post facto).\n    int                 junk;\n    int                 mib[4];\n    struct kinfo_proc   info;\n    size_t              size;\n\n    // Initialize the flags so that, if sysctl fails for some bizarre\n    // reason, we get a predictable result.\n\n    info.kp_proc.p_flag = 0;\n\n    // Initialize mib, which tells sysctl the info we want, in this case\n    // we're looking for information about a specific process ID.\n\n    mib[0] = CTL_KERN;\n    mib[1] = KERN_PROC;\n    mib[2] = KERN_PROC_PID;\n    mib[3] = getpid();\n\n    // Call sysctl.\n\n    size = sizeof(info);\n    junk = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0);\n    assert(junk == 0);\n    (void)junk;\n\n    // We're being debugged if the P_TRACED flag is set.\n    return ((info.kp_proc.p_flag & P_TRACED) != 0);\n#else\n    return false;\n#endif\n} // is_debugger_attached()\n\n} // namespace c4\n\n\n#ifdef __clang__\n#   pragma clang diagnostic pop\n#elif defined(__GNUC__)\n#   pragma GCC diagnostic pop\n#endif\n"
  },
  {
    "path": "libs/rapidyaml/c4/error.hpp",
    "content": "#ifndef _C4_ERROR_HPP_\n#define _C4_ERROR_HPP_\n\n/** @file error.hpp Facilities for error reporting and runtime assertions. */\n\n/** @defgroup error_checking Error checking */\n\n#include \"c4/config.hpp\"\n\n#ifdef _DOXYGEN_\n    /** if this is defined and exceptions are enabled, then calls to C4_ERROR()\n     * will throw an exception\n     * @ingroup error_checking */\n#   define C4_EXCEPTIONS_ENABLED\n    /** if this is defined and exceptions are enabled, then calls to C4_ERROR()\n     *  will throw an exception\n     * @see C4_EXCEPTIONS_ENABLED\n     * @ingroup error_checking */\n#   define C4_ERROR_THROWS_EXCEPTION\n    /** evaluates to noexcept when C4_ERROR might be called and\n     * exceptions are disabled. Otherwise, defaults to nothing.\n     * @ingroup error_checking */\n#   define C4_NOEXCEPT\n#endif // _DOXYGEN_\n\n#if defined(C4_EXCEPTIONS_ENABLED) && defined(C4_ERROR_THROWS_EXCEPTION)\n#   define C4_NOEXCEPT\n#else\n#   define C4_NOEXCEPT noexcept\n#endif\n\n\nnamespace c4 {\nnamespace detail {\nstruct fail_type__ {};\n} // detail\n} // c4\n#define C4_STATIC_ERROR(dummy_type, errmsg)                             \\\n    static_assert(std::is_same<dummy_type, c4::detail::fail_type__>::value, errmsg)\n\n\n//-----------------------------------------------------------------------------\n\n#define C4_ASSERT_SAME_TYPE(ty1, ty2)                       \\\n    C4_STATIC_ASSERT(std::is_same<ty1 C4_COMMA_X ty2>::value)\n\n#define C4_ASSERT_DIFF_TYPE(ty1, ty2)                       \\\n    C4_STATIC_ASSERT( ! std::is_same<ty1 C4_COMMA_X ty2>::value)\n\n\n//-----------------------------------------------------------------------------\n\n#ifdef _DOXYGEN_\n/** utility macro that triggers a breakpoint when\n * the debugger is attached and NDEBUG is not defined.\n * @ingroup error_checking */\n#   define C4_DEBUG_BREAK()\n#endif // _DOXYGEN_\n\n\n#if defined(NDEBUG) || defined(C4_NO_DEBUG_BREAK)\n#   define C4_DEBUG_BREAK()\n#else\n#   ifdef __clang__\n#       pragma clang diagnostic push\n#       if !defined(__APPLE_CC__)\n#           if __clang_major__ >= 10\n#               pragma clang diagnostic ignored \"-Wgnu-inline-cpp-without-extern\" // debugbreak/debugbreak.h:50:16: error: 'gnu_inline' attribute without 'extern' in C++ treated as externally available, this changed in Clang 10 [-Werror,-Wgnu-inline-cpp-without-extern]\n#           endif\n#       else\n#           if __clang_major__ >= 13\n#               pragma clang diagnostic ignored \"-Wgnu-inline-cpp-without-extern\" // debugbreak/debugbreak.h:50:16: error: 'gnu_inline' attribute without 'extern' in C++ treated as externally available, this changed in Clang 10 [-Werror,-Wgnu-inline-cpp-without-extern]\n#           endif\n#       endif\n#   elif defined(__GNUC__)\n#   endif\n#   include <c4/ext/debugbreak/debugbreak.h>\n#   define C4_DEBUG_BREAK() if(c4::is_debugger_attached()) { ::debug_break(); }\n#   ifdef __clang__\n#       pragma clang diagnostic pop\n#   elif defined(__GNUC__)\n#   endif\n#endif\n\nnamespace c4 {\nC4CORE_EXPORT bool is_debugger_attached();\n} // namespace c4\n\n\n//-----------------------------------------------------------------------------\n\n#ifdef __clang__\n    /* NOTE: using , ## __VA_ARGS__ to deal with zero-args calls to\n     * variadic macros is not portable, but works in clang, gcc, msvc, icc.\n     * clang requires switching off compiler warnings for pedantic mode.\n     * @see http://stackoverflow.com/questions/32047685/variadic-macro-without-arguments */\n#   pragma clang diagnostic push\n#   pragma clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\" // warning: token pasting of ',' and __VA_ARGS__ is a GNU extension\n#elif defined(__GNUC__)\n    /* GCC also issues a warning for zero-args calls to variadic macros.\n     * This warning is switched on with -pedantic and apparently there is no\n     * easy way to turn it off as with clang. But marking this as a system\n     * header works.\n     * @see https://gcc.gnu.org/onlinedocs/cpp/System-Headers.html\n     * @see http://stackoverflow.com/questions/35587137/ */\n#   pragma GCC system_header\n#endif\n\n\n//-----------------------------------------------------------------------------\n\nnamespace c4 {\n\ntypedef enum : uint32_t {\n    /** when an error happens and the debugger is attached, call C4_DEBUG_BREAK().\n     * Without effect otherwise. */\n    ON_ERROR_DEBUGBREAK = 0x01 << 0,\n    /** when an error happens log a message. */\n    ON_ERROR_LOG = 0x01 << 1,\n    /** when an error happens invoke a callback if it was set with\n     * set_error_callback(). */\n    ON_ERROR_CALLBACK = 0x01 << 2,\n    /** when an error happens call std::terminate(). */\n    ON_ERROR_ABORT = 0x01 << 3,\n    /** when an error happens and exceptions are enabled throw an exception.\n     * Without effect otherwise. */\n    ON_ERROR_THROW = 0x01 << 4,\n    /** the default flags. */\n    ON_ERROR_DEFAULTS = ON_ERROR_DEBUGBREAK|ON_ERROR_LOG|ON_ERROR_CALLBACK|ON_ERROR_ABORT\n} ErrorFlags_e;\nusing error_flags = uint32_t;\nC4CORE_EXPORT void set_error_flags(error_flags f);\nC4CORE_EXPORT error_flags get_error_flags();\n\n\nusing error_callback_type = void (*)(const char* msg, size_t msg_size);\nC4CORE_EXPORT void set_error_callback(error_callback_type cb);\nC4CORE_EXPORT error_callback_type get_error_callback();\n\n\n//-----------------------------------------------------------------------------\n/** RAII class controling the error settings inside a scope. */\nstruct ScopedErrorSettings\n{\n    error_flags m_flags;\n    error_callback_type m_callback;\n\n    explicit ScopedErrorSettings(error_callback_type cb)\n    :   m_flags(get_error_flags()),\n        m_callback(get_error_callback())\n    {\n        set_error_callback(cb);\n    }\n    explicit ScopedErrorSettings(error_flags flags)\n    :   m_flags(get_error_flags()),\n        m_callback(get_error_callback())\n    {\n        set_error_flags(flags);\n    }\n    explicit ScopedErrorSettings(error_flags flags, error_callback_type cb)\n    :   m_flags(get_error_flags()),\n        m_callback(get_error_callback())\n    {\n        set_error_flags(flags);\n        set_error_callback(cb);\n    }\n    ~ScopedErrorSettings()\n    {\n        set_error_flags(m_flags);\n        set_error_callback(m_callback);\n    }\n};\n\n\n//-----------------------------------------------------------------------------\n\n/** source location */\nstruct srcloc;\n\n// watchout: for VS the [[noreturn]] needs to come before other annotations like C4CORE_EXPORT\n[[noreturn]] C4CORE_EXPORT void handle_error(srcloc s, const char *fmt, ...);\nC4CORE_EXPORT void handle_warning(srcloc s, const char *fmt, ...);\n\n\n#   define C4_ERROR(msg, ...)                               \\\n    do {                                                    \\\n        if(c4::get_error_flags() & c4::ON_ERROR_DEBUGBREAK) \\\n        {                                                   \\\n            C4_DEBUG_BREAK()                                \\\n        }                                                   \\\n        c4::handle_error(C4_SRCLOC(), msg, ## __VA_ARGS__); \\\n    } while(0)\n\n\n#   define C4_WARNING(msg, ...)                             \\\n    c4::handle_warning(C4_SRCLOC(), msg, ## __VA_ARGS__)\n\n\n#if defined(C4_ERROR_SHOWS_FILELINE) && defined(C4_ERROR_SHOWS_FUNC)\n\nstruct srcloc\n{\n    const char *file = \"\";\n    const char *func = \"\";\n    int line = 0;\n};\n#define C4_SRCLOC() c4::srcloc{__FILE__, C4_PRETTY_FUNC, __LINE__}\n\n#elif defined(C4_ERROR_SHOWS_FILELINE)\n\nstruct srcloc\n{\n    const char *file;\n    int line;\n};\n#define C4_SRCLOC() c4::srcloc{__FILE__, __LINE__}\n\n#elif ! defined(C4_ERROR_SHOWS_FUNC)\n\nstruct srcloc\n{\n};\n#define C4_SRCLOC() c4::srcloc()\n\n#else\n#   error not implemented\n#endif\n\n\n//-----------------------------------------------------------------------------\n// assertions\n\n// Doxygen needs this so that only one definition counts\n#ifdef _DOXYGEN_\n    /** Explicitly enables assertions, independently of NDEBUG status.\n     * This is meant to allow enabling assertions even when NDEBUG is defined.\n     * Defaults to undefined.\n     * @ingroup error_checking */\n#   define C4_USE_ASSERT\n    /** assert that a condition is true; this is turned off when NDEBUG\n     * is defined and C4_USE_ASSERT is not true.\n     * @ingroup error_checking  */\n#   define C4_ASSERT\n    /** same as C4_ASSERT(), additionally prints a printf-formatted message\n     * @ingroup error_checking */\n#   define C4_ASSERT_MSG\n    /** evaluates to C4_NOEXCEPT when C4_XASSERT is disabled; otherwise, defaults\n     * to noexcept\n     * @ingroup error_checking */\n#   define C4_NOEXCEPT_A\n#endif // _DOXYGEN_\n\n#ifndef C4_USE_ASSERT\n#   ifdef NDEBUG\n#       define C4_USE_ASSERT 0\n#   else\n#       define C4_USE_ASSERT 1\n#   endif\n#endif\n\n#if C4_USE_ASSERT\n#   define C4_ASSERT(cond) C4_CHECK(cond)\n#   define C4_ASSERT_MSG(cond, /*fmt, */...) C4_CHECK_MSG(cond, ## __VA_ARGS__)\n#   define C4_ASSERT_IF(predicate, cond) if(predicate) { C4_ASSERT(cond); }\n#   define C4_NOEXCEPT_A C4_NOEXCEPT\n#else\n#   define C4_ASSERT(cond)\n#   define C4_ASSERT_MSG(cond, /*fmt, */...)\n#   define C4_ASSERT_IF(predicate, cond)\n#   define C4_NOEXCEPT_A noexcept\n#endif\n\n\n//-----------------------------------------------------------------------------\n// extreme assertions\n\n// Doxygen needs this so that only one definition counts\n#ifdef _DOXYGEN_\n    /** Explicitly enables extreme assertions; this is meant to allow enabling\n     * assertions even when NDEBUG is defined. Defaults to undefined.\n     * @ingroup error_checking */\n#   define C4_USE_XASSERT\n    /** extreme assertion: can be switched off independently of\n     * the regular assertion; use for example for bounds checking in hot code.\n     * Turned on only when C4_USE_XASSERT is defined\n     * @ingroup error_checking */\n#   define C4_XASSERT\n    /** same as C4_XASSERT(), and additionally prints a printf-formatted message\n     * @ingroup error_checking */\n#   define C4_XASSERT_MSG\n    /** evaluates to C4_NOEXCEPT when C4_XASSERT is disabled; otherwise, defaults to noexcept\n     * @ingroup error_checking */\n#   define C4_NOEXCEPT_X\n#endif // _DOXYGEN_\n\n#ifndef C4_USE_XASSERT\n#   define C4_USE_XASSERT C4_USE_ASSERT\n#endif\n\n#if C4_USE_XASSERT\n#   define C4_XASSERT(cond) C4_CHECK(cond)\n#   define C4_XASSERT_MSG(cond, /*fmt, */...) C4_CHECK_MSG(cond, ## __VA_ARGS__)\n#   define C4_XASSERT_IF(predicate, cond) if(predicate) { C4_XASSERT(cond); }\n#   define C4_NOEXCEPT_X C4_NOEXCEPT\n#else\n#   define C4_XASSERT(cond)\n#   define C4_XASSERT_MSG(cond, /*fmt, */...)\n#   define C4_XASSERT_IF(predicate, cond)\n#   define C4_NOEXCEPT_X noexcept\n#endif\n\n\n//-----------------------------------------------------------------------------\n// checks: never switched-off\n\n/** Check that a condition is true, or raise an error when not\n * true. Unlike C4_ASSERT(), this check is not disabled in non-debug\n * builds.\n * @see C4_ASSERT\n * @ingroup error_checking\n *\n * @todo add constexpr-compatible compile-time assert:\n * https://akrzemi1.wordpress.com/2017/05/18/asserts-in-constexpr-functions/\n */\n#define C4_CHECK(cond)                              \\\n    do {                                            \\\n        if(C4_UNLIKELY(!(cond)))                    \\\n        {                                           \\\n            C4_ERROR(\"check failed: %s\", #cond);    \\\n        }                                           \\\n    } while(0)\n\n\n/** like C4_CHECK(), and additionally log a printf-style message.\n * @see C4_CHECK\n * @ingroup error_checking */\n#define C4_CHECK_MSG(cond, fmt, ...)                                    \\\n    do {                                                                \\\n        if(C4_UNLIKELY(!(cond)))                                        \\\n        {                                                               \\\n            C4_ERROR(\"check failed: \" #cond \"\\n\" fmt, ## __VA_ARGS__);  \\\n        }                                                               \\\n    } while(0)\n\n\n//-----------------------------------------------------------------------------\n// Common error conditions\n\n#define C4_NOT_IMPLEMENTED() C4_ERROR(\"NOT IMPLEMENTED\")\n#define C4_NOT_IMPLEMENTED_MSG(/*msg, */...) C4_ERROR(\"NOT IMPLEMENTED: \" __VA_ARGS__)\n#define C4_NOT_IMPLEMENTED_IF(condition) do { if(C4_UNLIKELY(condition)) { C4_ERROR(\"NOT IMPLEMENTED\"); } } while(0)\n#define C4_NOT_IMPLEMENTED_IF_MSG(condition, /*msg, */...) do { if(C4_UNLIKELY(condition)) { C4_ERROR(\"NOT IMPLEMENTED: \" __VA_ARGS__); } } while(0)\n\n#define C4_NEVER_REACH() do { C4_ERROR(\"never reach this point\"); C4_UNREACHABLE(); } while(0)\n#define C4_NEVER_REACH_MSG(/*msg, */...) do { C4_ERROR(\"never reach this point: \" __VA_ARGS__); C4_UNREACHABLE(); } while(0)\n\n\n\n//-----------------------------------------------------------------------------\n// helpers for warning suppression\n// idea adapted from https://github.com/onqtam/doctest/\n\n// TODO: add C4_MESSAGE() https://stackoverflow.com/questions/18252351/custom-preprocessor-macro-for-a-conditional-pragma-message-xxx?rq=1\n\n\n#ifdef C4_MSVC\n#define C4_SUPPRESS_WARNING_MSVC_PUSH __pragma(warning(push))\n#define C4_SUPPRESS_WARNING_MSVC(w)  __pragma(warning(disable : w))\n#define C4_SUPPRESS_WARNING_MSVC_POP __pragma(warning(pop))\n#else // C4_MSVC\n#define C4_SUPPRESS_WARNING_MSVC_PUSH\n#define C4_SUPPRESS_WARNING_MSVC(w)\n#define C4_SUPPRESS_WARNING_MSVC_POP\n#endif // C4_MSVC\n\n\n#ifdef C4_CLANG\n#define C4_PRAGMA_TO_STR(x) _Pragma(#x)\n#define C4_SUPPRESS_WARNING_CLANG_PUSH _Pragma(\"clang diagnostic push\")\n#define C4_SUPPRESS_WARNING_CLANG(w) C4_PRAGMA_TO_STR(clang diagnostic ignored w)\n#define C4_SUPPRESS_WARNING_CLANG_POP _Pragma(\"clang diagnostic pop\")\n#else // C4_CLANG\n#define C4_SUPPRESS_WARNING_CLANG_PUSH\n#define C4_SUPPRESS_WARNING_CLANG(w)\n#define C4_SUPPRESS_WARNING_CLANG_POP\n#endif // C4_CLANG\n\n\n#ifdef C4_GCC\n#define C4_PRAGMA_TO_STR(x) _Pragma(#x)\n#define C4_SUPPRESS_WARNING_GCC_PUSH _Pragma(\"GCC diagnostic push\")\n#define C4_SUPPRESS_WARNING_GCC(w) C4_PRAGMA_TO_STR(GCC diagnostic ignored w)\n#define C4_SUPPRESS_WARNING_GCC_POP _Pragma(\"GCC diagnostic pop\")\n#else // C4_GCC\n#define C4_SUPPRESS_WARNING_GCC_PUSH\n#define C4_SUPPRESS_WARNING_GCC(w)\n#define C4_SUPPRESS_WARNING_GCC_POP\n#endif // C4_GCC\n\n\n#define C4_SUPPRESS_WARNING_MSVC_WITH_PUSH(w)   \\\n    C4_SUPPRESS_WARNING_MSVC_PUSH               \\\n    C4_SUPPRESS_WARNING_MSVC(w)\n\n#define C4_SUPPRESS_WARNING_CLANG_WITH_PUSH(w)  \\\n    C4_SUPPRESS_WARNING_CLANG_PUSH              \\\n    C4_SUPPRESS_WARNING_CLANG(w)\n\n#define C4_SUPPRESS_WARNING_GCC_WITH_PUSH(w)    \\\n    C4_SUPPRESS_WARNING_GCC_PUSH                \\\n    C4_SUPPRESS_WARNING_GCC(w)\n\n\n#define C4_SUPPRESS_WARNING_GCC_CLANG_PUSH \\\n    C4_SUPPRESS_WARNING_GCC_PUSH     \\\n    C4_SUPPRESS_WARNING_CLANG_PUSH\n\n#define C4_SUPPRESS_WARNING_GCC_CLANG(w) \\\n    C4_SUPPRESS_WARNING_GCC(w)     \\\n    C4_SUPPRESS_WARNING_CLANG(w)\n\n#define C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH(w) \\\n    C4_SUPPRESS_WARNING_GCC_WITH_PUSH(w)     \\\n    C4_SUPPRESS_WARNING_CLANG_WITH_PUSH(w)\n\n#define C4_SUPPRESS_WARNING_GCC_CLANG_POP \\\n    C4_SUPPRESS_WARNING_GCC_POP     \\\n    C4_SUPPRESS_WARNING_CLANG_POP\n\n} // namespace c4\n\n#ifdef __clang__\n#   pragma clang diagnostic pop\n#endif\n\n#endif /* _C4_ERROR_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/export.hpp",
    "content": "#ifndef C4_EXPORT_HPP_\n#define C4_EXPORT_HPP_\n\n#ifdef _WIN32\n    #ifdef C4CORE_SHARED\n        #ifdef C4CORE_EXPORTS\n            #define C4CORE_EXPORT __declspec(dllexport)\n        #else\n            #define C4CORE_EXPORT __declspec(dllimport)\n        #endif\n    #else\n        #define C4CORE_EXPORT\n    #endif\n#else\n    #define C4CORE_EXPORT\n#endif\n\n#endif /* C4CORE_EXPORT_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/ext/debugbreak/debugbreak.h",
    "content": "/* Copyright (c) 2011-2021, Scott Tsai\n * \n * All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n * \n * 1. Redistributions of source code must retain the above copyright notice,\n *    this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright notice,\n *    this list of conditions and the following disclaimer in the documentation\n *    and/or other materials provided with the distribution.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n#ifndef DEBUG_BREAK_H\n#define DEBUG_BREAK_H\n\n#ifdef _MSC_VER\n\n#define debug_break __debugbreak\n\n#else\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define DEBUG_BREAK_USE_TRAP_INSTRUCTION 1\n#define DEBUG_BREAK_USE_BULTIN_TRAP      2\n#define DEBUG_BREAK_USE_SIGTRAP          3\n\n#if defined(__i386__) || defined(__x86_64__)\n\t#define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_TRAP_INSTRUCTION\n__inline__ static void trap_instruction(void)\n{\n\t__asm__ volatile(\"int $0x03\");\n}\n#elif defined(__thumb__)\n\t#define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_TRAP_INSTRUCTION\n/* FIXME: handle __THUMB_INTERWORK__ */\n__attribute__((always_inline))\n__inline__ static void trap_instruction(void)\n{\n\t/* See 'arm-linux-tdep.c' in GDB source.\n\t * Both instruction sequences below work. */\n#if 1\n\t/* 'eabi_linux_thumb_le_breakpoint' */\n\t__asm__ volatile(\".inst 0xde01\");\n#else\n\t/* 'eabi_linux_thumb2_le_breakpoint' */\n\t__asm__ volatile(\".inst.w 0xf7f0a000\");\n#endif\n\n\t/* Known problem:\n\t * After a breakpoint hit, can't 'stepi', 'step', or 'continue' in GDB.\n\t * 'step' would keep getting stuck on the same instruction.\n\t *\n\t * Workaround: use the new GDB commands 'debugbreak-step' and\n\t * 'debugbreak-continue' that become available\n\t * after you source the script from GDB:\n\t *\n\t * $ gdb -x debugbreak-gdb.py <... USUAL ARGUMENTS ...>\n\t *\n\t * 'debugbreak-step' would jump over the breakpoint instruction with\n\t * roughly equivalent of:\n\t * (gdb) set $instruction_len = 2\n\t * (gdb) tbreak *($pc + $instruction_len)\n\t * (gdb) jump   *($pc + $instruction_len)\n\t */\n}\n#elif defined(__arm__) && !defined(__thumb__)\n\t#define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_TRAP_INSTRUCTION\n__attribute__((always_inline))\n__inline__ static void trap_instruction(void)\n{\n\t/* See 'arm-linux-tdep.c' in GDB source,\n\t * 'eabi_linux_arm_le_breakpoint' */\n\t__asm__ volatile(\".inst 0xe7f001f0\");\n\t/* Known problem:\n\t * Same problem and workaround as Thumb mode */\n}\n#elif defined(__aarch64__) && defined(__APPLE__)\n\t#define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_BULTIN_DEBUGTRAP\n#elif defined(__aarch64__)\n\t#define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_TRAP_INSTRUCTION\n__attribute__((always_inline))\n__inline__ static void trap_instruction(void)\n{\n\t/* See 'aarch64-tdep.c' in GDB source,\n\t * 'aarch64_default_breakpoint' */\n\t__asm__ volatile(\".inst 0xd4200000\");\n}\n#elif defined(__powerpc__)\n\t/* PPC 32 or 64-bit, big or little endian */\n\t#define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_TRAP_INSTRUCTION\n__attribute__((always_inline))\n__inline__ static void trap_instruction(void)\n{\n\t/* See 'rs6000-tdep.c' in GDB source,\n\t * 'rs6000_breakpoint' */\n\t__asm__ volatile(\".4byte 0x7d821008\");\n\n\t/* Known problem:\n\t * After a breakpoint hit, can't 'stepi', 'step', or 'continue' in GDB.\n\t * 'step' stuck on the same instruction (\"twge r2,r2\").\n\t *\n\t * The workaround is the same as ARM Thumb mode: use debugbreak-gdb.py\n\t * or manually jump over the instruction. */\n}\n#elif defined(__riscv)\n\t/* RISC-V 32 or 64-bit, whether the \"C\" extension\n\t * for compressed, 16-bit instructions are supported or not */\n\t#define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_TRAP_INSTRUCTION\n__attribute__((always_inline))\n__inline__ static void trap_instruction(void)\n{\n\t/* See 'riscv-tdep.c' in GDB source,\n\t * 'riscv_sw_breakpoint_from_kind' */\n\t__asm__ volatile(\".4byte 0x00100073\");\n}\n#else\n\t#define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_SIGTRAP\n#endif\n\n\n#ifndef DEBUG_BREAK_IMPL\n#error \"debugbreak.h is not supported on this target\"\n#elif DEBUG_BREAK_IMPL == DEBUG_BREAK_USE_TRAP_INSTRUCTION\n__attribute__((always_inline))\n__inline__ static void debug_break(void)\n{\n\ttrap_instruction();\n}\n#elif DEBUG_BREAK_IMPL == DEBUG_BREAK_USE_BULTIN_DEBUGTRAP\n__attribute__((always_inline))\n__inline__ static void debug_break(void)\n{\n\t__builtin_debugtrap();\n}\n#elif DEBUG_BREAK_IMPL == DEBUG_BREAK_USE_BULTIN_TRAP\n__attribute__((always_inline))\n__inline__ static void debug_break(void)\n{\n\t__builtin_trap();\n}\n#elif DEBUG_BREAK_IMPL == DEBUG_BREAK_USE_SIGTRAP\n#include <signal.h>\n__attribute__((always_inline))\n__inline__ static void debug_break(void)\n{\n\traise(SIGTRAP);\n}\n#else\n#error \"invalid DEBUG_BREAK_IMPL value\"\n#endif\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* ifdef _MSC_VER */\n\n#endif /* ifndef DEBUG_BREAK_H */\n"
  },
  {
    "path": "libs/rapidyaml/c4/ext/fast_float.hpp",
    "content": "#ifndef _C4_EXT_FAST_FLOAT_HPP_\n#define _C4_EXT_FAST_FLOAT_HPP_\n\n#if defined(_MSC_VER) && !defined(__clang__)\n#   pragma warning(push)\n#   pragma warning(disable: 4365) // '=': conversion from 'const _Ty' to 'fast_float::limb', signed/unsigned mismatch\n#   pragma warning(disable: 4996) // snprintf/scanf: this function or variable may be unsafe\n#elif defined(__clang__) || defined(__APPLE_CC__) || defined(_LIBCPP_VERSION)\n#   pragma clang diagnostic push\n#   if (defined(__clang_major__) && (__clang_major__ >= 9)) || defined(__APPLE_CC__)\n#       pragma clang diagnostic ignored \"-Wfortify-source\"\n#   endif\n#   pragma clang diagnostic ignored \"-Wshift-count-overflow\"\n#   pragma clang diagnostic ignored \"-Wold-style-cast\"\n#elif defined(__GNUC__)\n#   pragma GCC diagnostic push\n#   pragma GCC diagnostic ignored \"-Wnarrowing\"\n#   pragma GCC diagnostic ignored \"-Wconversion\"\n#   pragma GCC diagnostic ignored \"-Wuseless-cast\"\n#   pragma GCC diagnostic ignored \"-Wold-style-cast\"\n#endif\n\n#include \"c4/ext/fast_float_all.h\"\n\n#ifdef _MSC_VER\n#   pragma warning(pop)\n#elif defined(__clang__) || defined(__APPLE_CC__)\n#   pragma clang diagnostic pop\n#elif defined(__GNUC__)\n#   pragma GCC diagnostic pop\n#endif\n\n#endif // _C4_EXT_FAST_FLOAT_HPP_\n"
  },
  {
    "path": "libs/rapidyaml/c4/ext/fast_float_all.h",
    "content": "// fast_float by Daniel Lemire\n// fast_float by João Paulo Magalhaes\n//\n//\n// with contributions from Eugene Golushkov\n// with contributions from Maksim Kita\n// with contributions from Marcin Wojdyr\n// with contributions from Neal Richardson\n// with contributions from Tim Paine\n// with contributions from Fabio Pellacini\n// with contributions from Lénárd Szolnoki\n// with contributions from Jan Pharago\n// with contributions from Maya Warrier\n// with contributions from Taha Khokhar\n//\n//\n// MIT License Notice\n//\n//    MIT License\n//    \n//    Copyright (c) 2021 The fast_float authors\n//    \n//    Permission is hereby granted, free of charge, to any\n//    person obtaining a copy of this software and associated\n//    documentation files (the \"Software\"), to deal in the\n//    Software without restriction, including without\n//    limitation the rights to use, copy, modify, merge,\n//    publish, distribute, sublicense, and/or sell copies of\n//    the Software, and to permit persons to whom the Software\n//    is furnished to do so, subject to the following\n//    conditions:\n//    \n//    The above copyright notice and this permission notice\n//    shall be included in all copies or substantial portions\n//    of the Software.\n//    \n//    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF\n//    ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED\n//    TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A\n//    PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT\n//    SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n//    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\n//    OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR\n//    IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n//    DEALINGS IN THE SOFTWARE.\n//\n\n#ifndef FASTFLOAT_CONSTEXPR_FEATURE_DETECT_H\n#define FASTFLOAT_CONSTEXPR_FEATURE_DETECT_H\n\n#ifdef __has_include\n#if __has_include(<version>)\n#include <version>\n#endif\n#endif\n\n// Testing for https://wg21.link/N3652, adopted in C++14\n#if __cpp_constexpr >= 201304\n#define FASTFLOAT_CONSTEXPR14 constexpr\n#else\n#define FASTFLOAT_CONSTEXPR14\n#endif\n\n#if defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806L\n#define FASTFLOAT_HAS_BIT_CAST 1\n#else\n#define FASTFLOAT_HAS_BIT_CAST 0\n#endif\n\n#if defined(__cpp_lib_is_constant_evaluated) && __cpp_lib_is_constant_evaluated >= 201811L\n#define FASTFLOAT_HAS_IS_CONSTANT_EVALUATED 1\n#else\n#define FASTFLOAT_HAS_IS_CONSTANT_EVALUATED 0\n#endif\n\n// Testing for relevant C++20 constexpr library features\n#if FASTFLOAT_HAS_IS_CONSTANT_EVALUATED \\\n    && FASTFLOAT_HAS_BIT_CAST \\\n    && __cpp_lib_constexpr_algorithms >= 201806L /*For std::copy and std::fill*/\n#define FASTFLOAT_CONSTEXPR20 constexpr\n#define FASTFLOAT_IS_CONSTEXPR 1\n#else\n#define FASTFLOAT_CONSTEXPR20\n#define FASTFLOAT_IS_CONSTEXPR 0\n#endif\n\n#endif // FASTFLOAT_CONSTEXPR_FEATURE_DETECT_H\n\n#ifndef FASTFLOAT_FLOAT_COMMON_H\n#define FASTFLOAT_FLOAT_COMMON_H\n\n#include <cfloat>\n#include <cstdint>\n#include <cassert>\n#include <cstring>\n#include <type_traits>\n#include <system_error>\n#ifdef __has_include\n  #if __has_include(<stdfloat>) && (__cplusplus > 202002L || _MSVC_LANG > 202002L)\n    #include <stdfloat>\n  #endif\n#endif\n\nnamespace fast_float {\n\n#define FASTFLOAT_JSONFMT (1 << 5)\n#define FASTFLOAT_FORTRANFMT (1 << 6)\n\nenum chars_format {\n  scientific = 1 << 0,\n  fixed = 1 << 2,\n  hex = 1 << 3,\n  no_infnan = 1 << 4,\n  // RFC 8259: https://datatracker.ietf.org/doc/html/rfc8259#section-6\n  json = FASTFLOAT_JSONFMT | fixed | scientific | no_infnan,\n  // Extension of RFC 8259 where, e.g., \"inf\" and \"nan\" are allowed.\n  json_or_infnan = FASTFLOAT_JSONFMT | fixed | scientific,\n  fortran = FASTFLOAT_FORTRANFMT | fixed | scientific,\n  general = fixed | scientific\n};\n\ntemplate <typename UC>\nstruct from_chars_result_t {\n  UC const* ptr;\n  std::errc ec;\n};\nusing from_chars_result = from_chars_result_t<char>;\n\ntemplate <typename UC>\nstruct parse_options_t {\n  constexpr explicit parse_options_t(chars_format fmt = chars_format::general,\n    UC dot = UC('.'))\n    : format(fmt), decimal_point(dot) {}\n\n  /** Which number formats are accepted */\n  chars_format format;\n  /** The character used as decimal point */\n  UC decimal_point;\n};\nusing parse_options = parse_options_t<char>;\n\n}\n\n#if FASTFLOAT_HAS_BIT_CAST\n#include <bit>\n#endif\n\n#if (defined(__x86_64) || defined(__x86_64__) || defined(_M_X64)   \\\n       || defined(__amd64) || defined(__aarch64__) || defined(_M_ARM64) \\\n       || defined(__MINGW64__)                                          \\\n       || defined(__s390x__)                                            \\\n       || (defined(__ppc64__) || defined(__PPC64__) || defined(__ppc64le__) || defined(__PPC64LE__)) \\\n       || defined(__loongarch64) )\n#define FASTFLOAT_64BIT 1\n#elif (defined(__i386) || defined(__i386__) || defined(_M_IX86)   \\\n     || defined(__arm__) || defined(_M_ARM) || defined(__ppc__)   \\\n     || defined(__MINGW32__) || defined(__EMSCRIPTEN__))\n#define FASTFLOAT_32BIT 1\n#else\n  // Need to check incrementally, since SIZE_MAX is a size_t, avoid overflow.\n  // We can never tell the register width, but the SIZE_MAX is a good approximation.\n  // UINTPTR_MAX and INTPTR_MAX are optional, so avoid them for max portability.\n  #if SIZE_MAX == 0xffff\n    #error Unknown platform (16-bit, unsupported)\n  #elif SIZE_MAX == 0xffffffff\n    #define FASTFLOAT_32BIT 1\n  #elif SIZE_MAX == 0xffffffffffffffff\n    #define FASTFLOAT_64BIT 1\n  #else\n    #error Unknown platform (not 32-bit, not 64-bit?)\n  #endif\n#endif\n\n#if ((defined(_WIN32) || defined(_WIN64)) && !defined(__clang__))\n#include <intrin.h>\n#endif\n\n#if defined(_MSC_VER) && !defined(__clang__)\n#define FASTFLOAT_VISUAL_STUDIO 1\n#endif\n\n#if defined __BYTE_ORDER__ && defined __ORDER_BIG_ENDIAN__\n#define FASTFLOAT_IS_BIG_ENDIAN (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)\n#elif defined _WIN32\n#define FASTFLOAT_IS_BIG_ENDIAN 0\n#else\n#if defined(__APPLE__) || defined(__FreeBSD__)\n#include <machine/endian.h>\n#elif defined(sun) || defined(__sun)\n#include <sys/byteorder.h>\n#elif defined(__MVS__)\n#include <sys/endian.h>\n#else\n#ifdef __has_include\n#if __has_include(<endian.h>)\n#include <endian.h>\n#endif //__has_include(<endian.h>)\n#endif //__has_include\n#endif\n#\n#ifndef __BYTE_ORDER__\n// safe choice\n#define FASTFLOAT_IS_BIG_ENDIAN 0\n#endif\n#\n#ifndef __ORDER_LITTLE_ENDIAN__\n// safe choice\n#define FASTFLOAT_IS_BIG_ENDIAN 0\n#endif\n#\n#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__\n#define FASTFLOAT_IS_BIG_ENDIAN 0\n#else\n#define FASTFLOAT_IS_BIG_ENDIAN 1\n#endif\n#endif\n\n#if defined(__SSE2__) || \\\n  (defined(FASTFLOAT_VISUAL_STUDIO) && \\\n    (defined(_M_AMD64) || defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP == 2)))\n#define FASTFLOAT_SSE2 1\n#endif\n\n#if defined(__aarch64__) || defined(_M_ARM64)\n#define FASTFLOAT_NEON 1\n#endif\n\n#if defined(FASTFLOAT_SSE2) || defined(FASTFLOAT_NEON)\n#define FASTFLOAT_HAS_SIMD 1\n#endif\n\n#if defined(__GNUC__)\n// disable -Wcast-align=strict (GCC only)\n#define FASTFLOAT_SIMD_DISABLE_WARNINGS \\\n  _Pragma(\"GCC diagnostic push\") \\\n  _Pragma(\"GCC diagnostic ignored \\\"-Wcast-align\\\"\")\n#else\n#define FASTFLOAT_SIMD_DISABLE_WARNINGS\n#endif\n\n#if defined(__GNUC__)\n#define FASTFLOAT_SIMD_RESTORE_WARNINGS \\\n  _Pragma(\"GCC diagnostic pop\")\n#else\n#define FASTFLOAT_SIMD_RESTORE_WARNINGS\n#endif\n\n\n\n#ifdef FASTFLOAT_VISUAL_STUDIO\n#define fastfloat_really_inline __forceinline\n#else\n#define fastfloat_really_inline inline __attribute__((always_inline))\n#endif\n\n#ifndef FASTFLOAT_ASSERT\n#define FASTFLOAT_ASSERT(x)  { ((void)(x)); }\n#endif\n\n#ifndef FASTFLOAT_DEBUG_ASSERT\n#define FASTFLOAT_DEBUG_ASSERT(x) { ((void)(x)); }\n#endif\n\n// rust style `try!()` macro, or `?` operator\n#define FASTFLOAT_TRY(x) { if (!(x)) return false; }\n\n#define FASTFLOAT_ENABLE_IF(...) typename std::enable_if<(__VA_ARGS__), int>::type\n\n\nnamespace fast_float {\n\nfastfloat_really_inline constexpr bool cpp20_and_in_constexpr() {\n#if FASTFLOAT_HAS_IS_CONSTANT_EVALUATED\n  return std::is_constant_evaluated();\n#else\n  return false;\n#endif\n}\n\ntemplate <typename T>\nfastfloat_really_inline constexpr bool is_supported_float_type() {\n  return std::is_same<T, float>::value || std::is_same<T, double>::value\n#if __STDCPP_FLOAT32_T__\n    || std::is_same<T, std::float32_t>::value\n#endif\n#if __STDCPP_FLOAT64_T__\n    || std::is_same<T, std::float64_t>::value\n#endif\n  ;\n}\n\ntemplate <typename UC>\nfastfloat_really_inline constexpr bool is_supported_char_type() {\n  return\n    std::is_same<UC, char>::value ||\n    std::is_same<UC, wchar_t>::value ||\n    std::is_same<UC, char16_t>::value ||\n    std::is_same<UC, char32_t>::value;\n}\n\n// Compares two ASCII strings in a case insensitive manner.\ntemplate <typename UC>\ninline FASTFLOAT_CONSTEXPR14 bool\nfastfloat_strncasecmp(UC const * input1, UC const * input2, size_t length) {\n  char running_diff{0};\n  for (size_t i = 0; i < length; ++i) {\n    running_diff |= (char(input1[i]) ^ char(input2[i]));\n  }\n  return (running_diff == 0) || (running_diff == 32);\n}\n\n#ifndef FLT_EVAL_METHOD\n#error \"FLT_EVAL_METHOD should be defined, please include cfloat.\"\n#endif\n\n// a pointer and a length to a contiguous block of memory\ntemplate <typename T>\nstruct span {\n  const T* ptr;\n  size_t length;\n  constexpr span(const T* _ptr, size_t _length) : ptr(_ptr), length(_length) {}\n  constexpr span() : ptr(nullptr), length(0) {}\n\n  constexpr size_t len() const noexcept {\n    return length;\n  }\n\n  FASTFLOAT_CONSTEXPR14 const T& operator[](size_t index) const noexcept {\n    FASTFLOAT_DEBUG_ASSERT(index < length);\n    return ptr[index];\n  }\n};\n\nstruct value128 {\n  uint64_t low;\n  uint64_t high;\n  constexpr value128(uint64_t _low, uint64_t _high) : low(_low), high(_high) {}\n  constexpr value128() : low(0), high(0) {}\n};\n\n/* Helper C++14 constexpr generic implementation of leading_zeroes */\nfastfloat_really_inline FASTFLOAT_CONSTEXPR14\nint leading_zeroes_generic(uint64_t input_num, int last_bit = 0) {\n    if(input_num & uint64_t(0xffffffff00000000)) { input_num >>= 32; last_bit |= 32; }\n    if(input_num & uint64_t(        0xffff0000)) { input_num >>= 16; last_bit |= 16; }\n    if(input_num & uint64_t(            0xff00)) { input_num >>=  8; last_bit |=  8; }\n    if(input_num & uint64_t(              0xf0)) { input_num >>=  4; last_bit |=  4; }\n    if(input_num & uint64_t(               0xc)) { input_num >>=  2; last_bit |=  2; }\n    if(input_num & uint64_t(               0x2)) { /* input_num >>=  1; */ last_bit |=  1; }\n    return 63 - last_bit;\n}\n\n/* result might be undefined when input_num is zero */\nfastfloat_really_inline FASTFLOAT_CONSTEXPR20\nint leading_zeroes(uint64_t input_num) {\n  assert(input_num > 0);\n  if (cpp20_and_in_constexpr()) {\n    return leading_zeroes_generic(input_num);\n  }\n#ifdef FASTFLOAT_VISUAL_STUDIO\n  #if defined(_M_X64) || defined(_M_ARM64)\n  unsigned long leading_zero = 0;\n  // Search the mask data from most significant bit (MSB)\n  // to least significant bit (LSB) for a set bit (1).\n  _BitScanReverse64(&leading_zero, input_num);\n  return (int)(63 - leading_zero);\n  #else\n  return leading_zeroes_generic(input_num);\n  #endif\n#else\n  return __builtin_clzll(input_num);\n#endif\n}\n\n// slow emulation routine for 32-bit\nfastfloat_really_inline constexpr uint64_t emulu(uint32_t x, uint32_t y) {\n    return x * (uint64_t)y;\n}\n\nfastfloat_really_inline FASTFLOAT_CONSTEXPR14\nuint64_t umul128_generic(uint64_t ab, uint64_t cd, uint64_t *hi) {\n  uint64_t ad = emulu((uint32_t)(ab >> 32), (uint32_t)cd);\n  uint64_t bd = emulu((uint32_t)ab, (uint32_t)cd);\n  uint64_t adbc = ad + emulu((uint32_t)ab, (uint32_t)(cd >> 32));\n  uint64_t adbc_carry = (uint64_t)(adbc < ad);\n  uint64_t lo = bd + (adbc << 32);\n  *hi = emulu((uint32_t)(ab >> 32), (uint32_t)(cd >> 32)) + (adbc >> 32) +\n        (adbc_carry << 32) + (uint64_t)(lo < bd);\n  return lo;\n}\n\n#ifdef FASTFLOAT_32BIT\n\n// slow emulation routine for 32-bit\n#if !defined(__MINGW64__)\nfastfloat_really_inline FASTFLOAT_CONSTEXPR14\nuint64_t _umul128(uint64_t ab, uint64_t cd, uint64_t *hi) {\n  return umul128_generic(ab, cd, hi);\n}\n#endif // !__MINGW64__\n\n#endif // FASTFLOAT_32BIT\n\n\n// compute 64-bit a*b\nfastfloat_really_inline FASTFLOAT_CONSTEXPR20\nvalue128 full_multiplication(uint64_t a, uint64_t b) {\n  if (cpp20_and_in_constexpr()) {\n    value128 answer;\n    answer.low = umul128_generic(a, b, &answer.high);\n    return answer;\n  }\n  value128 answer;\n#if defined(_M_ARM64) && !defined(__MINGW32__)\n  // ARM64 has native support for 64-bit multiplications, no need to emulate\n  // But MinGW on ARM64 doesn't have native support for 64-bit multiplications\n  answer.high = __umulh(a, b);\n  answer.low = a * b;\n#elif defined(FASTFLOAT_32BIT) || (defined(_WIN64) && !defined(__clang__) && !defined(__CYGWIN__))\n  answer.low = _umul128(a, b, &answer.high); // _umul128 not available on ARM64\n#elif defined(FASTFLOAT_64BIT) && defined(__SIZEOF_INT128__)\n  __uint128_t r = ((__uint128_t)a) * b;\n  answer.low = uint64_t(r);\n  answer.high = uint64_t(r >> 64);\n#else\n  answer.low = umul128_generic(a, b, &answer.high);\n#endif\n  return answer;\n}\n\nstruct adjusted_mantissa {\n  uint64_t mantissa{0};\n  int32_t power2{0}; // a negative value indicates an invalid result\n  adjusted_mantissa() = default;\n  constexpr bool operator==(const adjusted_mantissa &o) const {\n    return mantissa == o.mantissa && power2 == o.power2;\n  }\n  constexpr bool operator!=(const adjusted_mantissa &o) const {\n    return mantissa != o.mantissa || power2 != o.power2;\n  }\n};\n\n// Bias so we can get the real exponent with an invalid adjusted_mantissa.\nconstexpr static int32_t invalid_am_bias = -0x8000;\n\n// used for binary_format_lookup_tables<T>::max_mantissa\nconstexpr uint64_t constant_55555 = 5 * 5 * 5 * 5 * 5;\n\ntemplate <typename T, typename U = void>\nstruct binary_format_lookup_tables;\n\ntemplate <typename T> struct binary_format : binary_format_lookup_tables<T> {\n  using equiv_uint = typename std::conditional<sizeof(T) == 4, uint32_t, uint64_t>::type;\n\n  static inline constexpr int mantissa_explicit_bits();\n  static inline constexpr int minimum_exponent();\n  static inline constexpr int infinite_power();\n  static inline constexpr int sign_index();\n  static inline constexpr int min_exponent_fast_path(); // used when fegetround() == FE_TONEAREST\n  static inline constexpr int max_exponent_fast_path();\n  static inline constexpr int max_exponent_round_to_even();\n  static inline constexpr int min_exponent_round_to_even();\n  static inline constexpr uint64_t max_mantissa_fast_path(int64_t power);\n  static inline constexpr uint64_t max_mantissa_fast_path(); // used when fegetround() == FE_TONEAREST\n  static inline constexpr int largest_power_of_ten();\n  static inline constexpr int smallest_power_of_ten();\n  static inline constexpr T exact_power_of_ten(int64_t power);\n  static inline constexpr size_t max_digits();\n  static inline constexpr equiv_uint exponent_mask();\n  static inline constexpr equiv_uint mantissa_mask();\n  static inline constexpr equiv_uint hidden_bit_mask();\n};\n\ntemplate <typename U>\nstruct binary_format_lookup_tables<double, U> {\n  static constexpr double powers_of_ten[] = {\n      1e0,  1e1,  1e2,  1e3,  1e4,  1e5,  1e6,  1e7,  1e8,  1e9,  1e10, 1e11,\n      1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22};\n\n  // Largest integer value v so that (5**index * v) <= 1<<53.\n  // 0x10000000000000 == 1 << 53\n  static constexpr uint64_t max_mantissa[] = {\n      0x10000000000000,\n      0x10000000000000 / 5,\n      0x10000000000000 / (5 * 5),\n      0x10000000000000 / (5 * 5 * 5),\n      0x10000000000000 / (5 * 5 * 5 * 5),\n      0x10000000000000 / (constant_55555),\n      0x10000000000000 / (constant_55555 * 5),\n      0x10000000000000 / (constant_55555 * 5 * 5),\n      0x10000000000000 / (constant_55555 * 5 * 5 * 5),\n      0x10000000000000 / (constant_55555 * 5 * 5 * 5 * 5),\n      0x10000000000000 / (constant_55555 * constant_55555),\n      0x10000000000000 / (constant_55555 * constant_55555 * 5),\n      0x10000000000000 / (constant_55555 * constant_55555 * 5 * 5),\n      0x10000000000000 / (constant_55555 * constant_55555 * 5 * 5 * 5),\n      0x10000000000000 / (constant_55555 * constant_55555 * constant_55555),\n      0x10000000000000 / (constant_55555 * constant_55555 * constant_55555 * 5),\n      0x10000000000000 / (constant_55555 * constant_55555 * constant_55555 * 5 * 5),\n      0x10000000000000 / (constant_55555 * constant_55555 * constant_55555 * 5 * 5 * 5),\n      0x10000000000000 / (constant_55555 * constant_55555 * constant_55555 * 5 * 5 * 5 * 5),\n      0x10000000000000 / (constant_55555 * constant_55555 * constant_55555 * constant_55555),\n      0x10000000000000 / (constant_55555 * constant_55555 * constant_55555 * constant_55555 * 5),\n      0x10000000000000 / (constant_55555 * constant_55555 * constant_55555 * constant_55555 * 5 * 5),\n      0x10000000000000 / (constant_55555 * constant_55555 * constant_55555 * constant_55555 * 5 * 5 * 5),\n      0x10000000000000 / (constant_55555 * constant_55555 * constant_55555 * constant_55555 * 5 * 5 * 5 * 5)};\n};\n\ntemplate <typename U>\nconstexpr double binary_format_lookup_tables<double, U>::powers_of_ten[];\n\ntemplate <typename U>\nconstexpr uint64_t binary_format_lookup_tables<double, U>::max_mantissa[];\n\ntemplate <typename U>\nstruct binary_format_lookup_tables<float, U> {\n  static constexpr float powers_of_ten[] = {1e0f, 1e1f, 1e2f, 1e3f, 1e4f, 1e5f,\n                                     1e6f, 1e7f, 1e8f, 1e9f, 1e10f};\n\n  // Largest integer value v so that (5**index * v) <= 1<<24.\n  // 0x1000000 == 1<<24\n  static constexpr uint64_t max_mantissa[] = {\n        0x1000000,\n        0x1000000 / 5,\n        0x1000000 / (5 * 5),\n        0x1000000 / (5 * 5 * 5),\n        0x1000000 / (5 * 5 * 5 * 5),\n        0x1000000 / (constant_55555),\n        0x1000000 / (constant_55555 * 5),\n        0x1000000 / (constant_55555 * 5 * 5),\n        0x1000000 / (constant_55555 * 5 * 5 * 5),\n        0x1000000 / (constant_55555 * 5 * 5 * 5 * 5),\n        0x1000000 / (constant_55555 * constant_55555),\n        0x1000000 / (constant_55555 * constant_55555 * 5)};\n};\n\ntemplate <typename U>\nconstexpr float binary_format_lookup_tables<float, U>::powers_of_ten[];\n\ntemplate <typename U>\nconstexpr uint64_t binary_format_lookup_tables<float, U>::max_mantissa[];\n\ntemplate <> inline constexpr int binary_format<double>::min_exponent_fast_path() {\n#if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0)\n  return 0;\n#else\n  return -22;\n#endif\n}\n\ntemplate <> inline constexpr int binary_format<float>::min_exponent_fast_path() {\n#if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0)\n  return 0;\n#else\n  return -10;\n#endif\n}\n\ntemplate <> inline constexpr int binary_format<double>::mantissa_explicit_bits() {\n  return 52;\n}\ntemplate <> inline constexpr int binary_format<float>::mantissa_explicit_bits() {\n  return 23;\n}\n\ntemplate <> inline constexpr int binary_format<double>::max_exponent_round_to_even() {\n  return 23;\n}\n\ntemplate <> inline constexpr int binary_format<float>::max_exponent_round_to_even() {\n  return 10;\n}\n\ntemplate <> inline constexpr int binary_format<double>::min_exponent_round_to_even() {\n  return -4;\n}\n\ntemplate <> inline constexpr int binary_format<float>::min_exponent_round_to_even() {\n  return -17;\n}\n\ntemplate <> inline constexpr int binary_format<double>::minimum_exponent() {\n  return -1023;\n}\ntemplate <> inline constexpr int binary_format<float>::minimum_exponent() {\n  return -127;\n}\n\ntemplate <> inline constexpr int binary_format<double>::infinite_power() {\n  return 0x7FF;\n}\ntemplate <> inline constexpr int binary_format<float>::infinite_power() {\n  return 0xFF;\n}\n\ntemplate <> inline constexpr int binary_format<double>::sign_index() { return 63; }\ntemplate <> inline constexpr int binary_format<float>::sign_index() { return 31; }\n\ntemplate <> inline constexpr int binary_format<double>::max_exponent_fast_path() {\n  return 22;\n}\ntemplate <> inline constexpr int binary_format<float>::max_exponent_fast_path() {\n  return 10;\n}\n\ntemplate <> inline constexpr uint64_t binary_format<double>::max_mantissa_fast_path() {\n  return uint64_t(2) << mantissa_explicit_bits();\n}\ntemplate <> inline constexpr uint64_t binary_format<double>::max_mantissa_fast_path(int64_t power) {\n  // caller is responsible to ensure that\n  // power >= 0 && power <= 22\n  //\n  // Work around clang bug https://godbolt.org/z/zedh7rrhc\n  return (void)max_mantissa[0], max_mantissa[power];\n}\ntemplate <> inline constexpr uint64_t binary_format<float>::max_mantissa_fast_path() {\n  return uint64_t(2) << mantissa_explicit_bits();\n}\ntemplate <> inline constexpr uint64_t binary_format<float>::max_mantissa_fast_path(int64_t power) {\n  // caller is responsible to ensure that\n  // power >= 0 && power <= 10\n  //\n  // Work around clang bug https://godbolt.org/z/zedh7rrhc\n  return (void)max_mantissa[0], max_mantissa[power];\n}\n\ntemplate <>\ninline constexpr double binary_format<double>::exact_power_of_ten(int64_t power) {\n  // Work around clang bug https://godbolt.org/z/zedh7rrhc\n  return (void)powers_of_ten[0], powers_of_ten[power];\n}\ntemplate <>\ninline constexpr float binary_format<float>::exact_power_of_ten(int64_t power) {\n  // Work around clang bug https://godbolt.org/z/zedh7rrhc\n  return (void)powers_of_ten[0], powers_of_ten[power];\n}\n\n\ntemplate <>\ninline constexpr int binary_format<double>::largest_power_of_ten() {\n  return 308;\n}\ntemplate <>\ninline constexpr int binary_format<float>::largest_power_of_ten() {\n  return 38;\n}\n\ntemplate <>\ninline constexpr int binary_format<double>::smallest_power_of_ten() {\n  return -342;\n}\ntemplate <>\ninline constexpr int binary_format<float>::smallest_power_of_ten() {\n  return -64;\n}\n\ntemplate <> inline constexpr size_t binary_format<double>::max_digits() {\n  return 769;\n}\ntemplate <> inline constexpr size_t binary_format<float>::max_digits() {\n  return 114;\n}\n\ntemplate <> inline constexpr binary_format<float>::equiv_uint\n    binary_format<float>::exponent_mask() {\n  return 0x7F800000;\n}\ntemplate <> inline constexpr binary_format<double>::equiv_uint\n    binary_format<double>::exponent_mask() {\n  return 0x7FF0000000000000;\n}\n\ntemplate <> inline constexpr binary_format<float>::equiv_uint\n    binary_format<float>::mantissa_mask() {\n  return 0x007FFFFF;\n}\ntemplate <> inline constexpr binary_format<double>::equiv_uint\n    binary_format<double>::mantissa_mask() {\n  return 0x000FFFFFFFFFFFFF;\n}\n\ntemplate <> inline constexpr binary_format<float>::equiv_uint\n    binary_format<float>::hidden_bit_mask() {\n  return 0x00800000;\n}\ntemplate <> inline constexpr binary_format<double>::equiv_uint\n    binary_format<double>::hidden_bit_mask() {\n  return 0x0010000000000000;\n}\n\ntemplate<typename T>\nfastfloat_really_inline FASTFLOAT_CONSTEXPR20\nvoid to_float(bool negative, adjusted_mantissa am, T &value) {\n  using fastfloat_uint = typename binary_format<T>::equiv_uint;\n  fastfloat_uint word = (fastfloat_uint)am.mantissa;\n  word |= fastfloat_uint(am.power2) << binary_format<T>::mantissa_explicit_bits();\n  word |= fastfloat_uint(negative) << binary_format<T>::sign_index();\n#if FASTFLOAT_HAS_BIT_CAST\n  value = std::bit_cast<T>(word);\n#else\n  ::memcpy(&value, &word, sizeof(T));\n#endif\n}\n\n#ifdef FASTFLOAT_SKIP_WHITE_SPACE // disabled by default\ntemplate <typename = void>\nstruct space_lut {\n  static constexpr bool value[] = {\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};\n};\n\ntemplate <typename T>\nconstexpr bool space_lut<T>::value[];\n\ninline constexpr bool is_space(uint8_t c) { return space_lut<>::value[c]; }\n#endif\n\ntemplate<typename UC>\nstatic constexpr uint64_t int_cmp_zeros()\n{\n    static_assert((sizeof(UC) == 1) || (sizeof(UC) == 2) || (sizeof(UC) == 4), \"Unsupported character size\");\n    return (sizeof(UC) == 1) ? 0x3030303030303030 : (sizeof(UC) == 2) ? (uint64_t(UC('0')) << 48 | uint64_t(UC('0')) << 32 | uint64_t(UC('0')) << 16 | UC('0')) : (uint64_t(UC('0')) << 32 | UC('0'));\n}\ntemplate<typename UC>\nstatic constexpr int int_cmp_len()\n{\n    return sizeof(uint64_t) / sizeof(UC);\n}\ntemplate<typename UC>\nstatic constexpr UC const * str_const_nan()\n{\n    return nullptr;\n}\ntemplate<>\nconstexpr char const * str_const_nan<char>()\n{\n    return \"nan\";\n}\ntemplate<>\nconstexpr wchar_t const * str_const_nan<wchar_t>()\n{\n    return L\"nan\";\n}\ntemplate<>\nconstexpr char16_t const * str_const_nan<char16_t>()\n{\n    return u\"nan\";\n}\ntemplate<>\nconstexpr char32_t const * str_const_nan<char32_t>()\n{\n    return U\"nan\";\n}\ntemplate<typename UC>\nstatic constexpr UC const * str_const_inf()\n{\n    return nullptr;\n}\ntemplate<>\nconstexpr char const * str_const_inf<char>()\n{\n    return \"infinity\";\n}\ntemplate<>\nconstexpr wchar_t const * str_const_inf<wchar_t>()\n{\n    return L\"infinity\";\n}\ntemplate<>\nconstexpr char16_t const * str_const_inf<char16_t>()\n{\n    return u\"infinity\";\n}\ntemplate<>\nconstexpr char32_t const * str_const_inf<char32_t>()\n{\n    return U\"infinity\";\n}\n\n\ntemplate <typename = void>\nstruct int_luts {\n  static constexpr uint8_t chdigit[] = {\n    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,\n    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,\n    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,\n    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255,\n    255, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,\n    25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 255, 255, 255, 255, 255,\n    255, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,\n    25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 255, 255, 255, 255, 255,\n    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,\n    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,\n    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,\n    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,\n    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,\n    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,\n    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,\n    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255\n  };\n\n  static constexpr size_t maxdigits_u64[] = {\n    64, 41, 32, 28, 25, 23, 22, 21,\n    20, 19, 18, 18, 17, 17, 16, 16,\n    16, 16, 15, 15, 15, 15, 14, 14,\n    14, 14, 14, 14, 14, 13, 13, 13,\n    13, 13, 13\n  };\n\n  static constexpr uint64_t min_safe_u64[] = {\n    9223372036854775808ull, 12157665459056928801ull, 4611686018427387904, 7450580596923828125, 4738381338321616896,\n    3909821048582988049, 9223372036854775808ull, 12157665459056928801ull, 10000000000000000000ull, 5559917313492231481,\n    2218611106740436992, 8650415919381337933, 2177953337809371136, 6568408355712890625, 1152921504606846976, \n    2862423051509815793, 6746640616477458432, 15181127029874798299ull, 1638400000000000000, 3243919932521508681,\n    6221821273427820544, 11592836324538749809ull, 876488338465357824, 1490116119384765625, 2481152873203736576,\n    4052555153018976267, 6502111422497947648, 10260628712958602189ull, 15943230000000000000ull, 787662783788549761,\n    1152921504606846976, 1667889514952984961, 2386420683693101056, 3379220508056640625, 4738381338321616896\n  };\n};\n\ntemplate <typename T>\nconstexpr uint8_t int_luts<T>::chdigit[];\n\ntemplate <typename T>\nconstexpr size_t int_luts<T>::maxdigits_u64[];\n\ntemplate <typename T>\nconstexpr uint64_t int_luts<T>::min_safe_u64[];\n\ntemplate <typename UC>\nfastfloat_really_inline\nconstexpr uint8_t ch_to_digit(UC c) { return int_luts<>::chdigit[static_cast<unsigned char>(c)]; }\n\nfastfloat_really_inline\nconstexpr size_t max_digits_u64(int base) { return int_luts<>::maxdigits_u64[base - 2]; }\n\n// If a u64 is exactly max_digits_u64() in length, this is\n// the value below which it has definitely overflowed. \nfastfloat_really_inline\nconstexpr uint64_t min_safe_u64(int base) { return int_luts<>::min_safe_u64[base - 2]; }\n\n} // namespace fast_float\n\n#endif\n\n\n#ifndef FASTFLOAT_FAST_FLOAT_H\n#define FASTFLOAT_FAST_FLOAT_H\n\n\nnamespace fast_float {\n/**\n * This function parses the character sequence [first,last) for a number. It parses floating-point numbers expecting\n * a locale-indepent format equivalent to what is used by std::strtod in the default (\"C\") locale.\n * The resulting floating-point value is the closest floating-point values (using either float or double),\n * using the \"round to even\" convention for values that would otherwise fall right in-between two values.\n * That is, we provide exact parsing according to the IEEE standard.\n *\n * Given a successful parse, the pointer (`ptr`) in the returned value is set to point right after the\n * parsed number, and the `value` referenced is set to the parsed value. In case of error, the returned\n * `ec` contains a representative error, otherwise the default (`std::errc()`) value is stored.\n *\n * The implementation does not throw and does not allocate memory (e.g., with `new` or `malloc`).\n *\n * Like the C++17 standard, the `fast_float::from_chars` functions take an optional last argument of\n * the type `fast_float::chars_format`. It is a bitset value: we check whether\n * `fmt & fast_float::chars_format::fixed` and `fmt & fast_float::chars_format::scientific` are set\n * to determine whether we allow the fixed point and scientific notation respectively.\n * The default is  `fast_float::chars_format::general` which allows both `fixed` and `scientific`.\n */\ntemplate<typename T, typename UC = char, typename = FASTFLOAT_ENABLE_IF(is_supported_float_type<T>())>\nFASTFLOAT_CONSTEXPR20\nfrom_chars_result_t<UC> from_chars(UC const * first, UC const * last,\n                             T &value, chars_format fmt = chars_format::general)  noexcept;\n\n/**\n * Like from_chars, but accepts an `options` argument to govern number parsing.\n */\ntemplate<typename T, typename UC = char>\nFASTFLOAT_CONSTEXPR20\nfrom_chars_result_t<UC> from_chars_advanced(UC const * first, UC const * last,\n                                      T &value, parse_options_t<UC> options)  noexcept;\n/**\n* from_chars for integer types.\n*/\ntemplate <typename T, typename UC = char, typename = FASTFLOAT_ENABLE_IF(!is_supported_float_type<T>())>\nFASTFLOAT_CONSTEXPR20\nfrom_chars_result_t<UC> from_chars(UC const * first, UC const * last, T& value, int base = 10) noexcept;\n\n} // namespace fast_float\n#endif // FASTFLOAT_FAST_FLOAT_H\n\n#ifndef FASTFLOAT_ASCII_NUMBER_H\n#define FASTFLOAT_ASCII_NUMBER_H\n\n#include <cctype>\n#include <cstdint>\n#include <cstring>\n#include <iterator>\n#include <limits>\n#include <type_traits>\n\n\n#ifdef FASTFLOAT_SSE2\n#include <emmintrin.h>\n#endif\n\n#ifdef FASTFLOAT_NEON\n#include <arm_neon.h>\n#endif\n\nnamespace fast_float {\n\ntemplate <typename UC>\nfastfloat_really_inline constexpr bool has_simd_opt() {\n#ifdef FASTFLOAT_HAS_SIMD\n  return std::is_same<UC, char16_t>::value;\n#else\n  return false;\n#endif\n}\n\n// Next function can be micro-optimized, but compilers are entirely\n// able to optimize it well.\ntemplate <typename UC>\nfastfloat_really_inline constexpr bool is_integer(UC c) noexcept {\n  return !(c > UC('9') || c < UC('0'));\n}\n\nfastfloat_really_inline constexpr uint64_t byteswap(uint64_t val) {\n  return (val & 0xFF00000000000000) >> 56\n    | (val & 0x00FF000000000000) >> 40\n    | (val & 0x0000FF0000000000) >> 24\n    | (val & 0x000000FF00000000) >> 8\n    | (val & 0x00000000FF000000) << 8\n    | (val & 0x0000000000FF0000) << 24\n    | (val & 0x000000000000FF00) << 40\n    | (val & 0x00000000000000FF) << 56;\n}\n\n// Read 8 UC into a u64. Truncates UC if not char.\ntemplate <typename UC>\nfastfloat_really_inline FASTFLOAT_CONSTEXPR20\nuint64_t read8_to_u64(const UC *chars) {\n  if (cpp20_and_in_constexpr() || !std::is_same<UC, char>::value) {\n    uint64_t val = 0;\n    for(int i = 0; i < 8; ++i) {\n      val |= uint64_t(uint8_t(*chars)) << (i*8);\n      ++chars;\n    }\n    return val;\n  }\n  uint64_t val;\n  ::memcpy(&val, chars, sizeof(uint64_t));\n#if FASTFLOAT_IS_BIG_ENDIAN == 1\n  // Need to read as-if the number was in little-endian order.\n  val = byteswap(val);\n#endif\n  return val;\n}\n\n#ifdef FASTFLOAT_SSE2\n\nfastfloat_really_inline\nuint64_t simd_read8_to_u64(const __m128i data) {\nFASTFLOAT_SIMD_DISABLE_WARNINGS\n  const __m128i packed = _mm_packus_epi16(data, data);\n#ifdef FASTFLOAT_64BIT\n  return uint64_t(_mm_cvtsi128_si64(packed));\n#else\n  uint64_t value;\n  // Visual Studio + older versions of GCC don't support _mm_storeu_si64\n  _mm_storel_epi64(reinterpret_cast<__m128i*>(&value), packed);\n  return value;\n#endif\nFASTFLOAT_SIMD_RESTORE_WARNINGS\n}\n\nfastfloat_really_inline\nuint64_t simd_read8_to_u64(const char16_t* chars) {\nFASTFLOAT_SIMD_DISABLE_WARNINGS\n  return simd_read8_to_u64(_mm_loadu_si128(reinterpret_cast<const __m128i*>(chars)));\nFASTFLOAT_SIMD_RESTORE_WARNINGS\n}\n\n#elif defined(FASTFLOAT_NEON)\n\n\nfastfloat_really_inline\nuint64_t simd_read8_to_u64(const uint16x8_t data) {\nFASTFLOAT_SIMD_DISABLE_WARNINGS\n  uint8x8_t utf8_packed = vmovn_u16(data);\n  return vget_lane_u64(vreinterpret_u64_u8(utf8_packed), 0);\nFASTFLOAT_SIMD_RESTORE_WARNINGS\n}\n\nfastfloat_really_inline\nuint64_t simd_read8_to_u64(const char16_t* chars) {\nFASTFLOAT_SIMD_DISABLE_WARNINGS\n  return simd_read8_to_u64(vld1q_u16(reinterpret_cast<const uint16_t*>(chars)));\nFASTFLOAT_SIMD_RESTORE_WARNINGS\n}\n\n#endif // FASTFLOAT_SSE2\n\n// MSVC SFINAE is broken pre-VS2017\n#if defined(_MSC_VER) && _MSC_VER <= 1900\ntemplate <typename UC>\n#else\ntemplate <typename UC, FASTFLOAT_ENABLE_IF(!has_simd_opt<UC>()) = 0>\n#endif\n// dummy for compile\nuint64_t simd_read8_to_u64(UC const*) {\n  return 0;\n}\n\n// credit  @aqrit\nfastfloat_really_inline FASTFLOAT_CONSTEXPR14\nuint32_t parse_eight_digits_unrolled(uint64_t val) {\n  const uint64_t mask = 0x000000FF000000FF;\n  const uint64_t mul1 = 0x000F424000000064; // 100 + (1000000ULL << 32)\n  const uint64_t mul2 = 0x0000271000000001; // 1 + (10000ULL << 32)\n  val -= 0x3030303030303030;\n  val = (val * 10) + (val >> 8); // val = (val * 2561) >> 8;\n  val = (((val & mask) * mul1) + (((val >> 16) & mask) * mul2)) >> 32;\n  return uint32_t(val);\n}\n\n\n// Call this if chars are definitely 8 digits.\ntemplate <typename UC>\nfastfloat_really_inline FASTFLOAT_CONSTEXPR20\nuint32_t parse_eight_digits_unrolled(UC const * chars)  noexcept {\n  if (cpp20_and_in_constexpr() || !has_simd_opt<UC>()) {\n    return parse_eight_digits_unrolled(read8_to_u64(chars)); // truncation okay\n  }\n  return parse_eight_digits_unrolled(simd_read8_to_u64(chars));\n}\n\n\n// credit @aqrit\nfastfloat_really_inline constexpr bool is_made_of_eight_digits_fast(uint64_t val)  noexcept {\n  return !((((val + 0x4646464646464646) | (val - 0x3030303030303030)) &\n     0x8080808080808080));\n}\n\n\n#ifdef FASTFLOAT_HAS_SIMD\n\n// Call this if chars might not be 8 digits.\n// Using this style (instead of is_made_of_eight_digits_fast() then parse_eight_digits_unrolled())\n// ensures we don't load SIMD registers twice.\nfastfloat_really_inline FASTFLOAT_CONSTEXPR20\nbool simd_parse_if_eight_digits_unrolled(const char16_t* chars, uint64_t& i) noexcept {\n  if (cpp20_and_in_constexpr()) {\n    return false;\n  }   \n#ifdef FASTFLOAT_SSE2\nFASTFLOAT_SIMD_DISABLE_WARNINGS\n  const __m128i data = _mm_loadu_si128(reinterpret_cast<const __m128i*>(chars));\n\n  // (x - '0') <= 9\n  // http://0x80.pl/articles/simd-parsing-int-sequences.html\n  const __m128i t0 = _mm_add_epi16(data, _mm_set1_epi16(32720));\n  const __m128i t1 = _mm_cmpgt_epi16(t0, _mm_set1_epi16(-32759));\n\n  if (_mm_movemask_epi8(t1) == 0) {\n    i = i * 100000000 + parse_eight_digits_unrolled(simd_read8_to_u64(data));\n    return true;\n  }\n  else return false;\nFASTFLOAT_SIMD_RESTORE_WARNINGS\n#elif defined(FASTFLOAT_NEON)\nFASTFLOAT_SIMD_DISABLE_WARNINGS\n  const uint16x8_t data = vld1q_u16(reinterpret_cast<const uint16_t*>(chars));\n  \n  // (x - '0') <= 9\n  // http://0x80.pl/articles/simd-parsing-int-sequences.html\n  const uint16x8_t t0 = vsubq_u16(data, vmovq_n_u16('0'));\n  const uint16x8_t mask = vcltq_u16(t0, vmovq_n_u16('9' - '0' + 1));\n\n  if (vminvq_u16(mask) == 0xFFFF) {\n    i = i * 100000000 + parse_eight_digits_unrolled(simd_read8_to_u64(data));\n    return true;\n  }\n  else return false;\nFASTFLOAT_SIMD_RESTORE_WARNINGS\n#else\n  (void)chars; (void)i;\n  return false;\n#endif // FASTFLOAT_SSE2\n}\n\n#endif // FASTFLOAT_HAS_SIMD\n\n// MSVC SFINAE is broken pre-VS2017\n#if defined(_MSC_VER) && _MSC_VER <= 1900\ntemplate <typename UC>\n#else\ntemplate <typename UC, FASTFLOAT_ENABLE_IF(!has_simd_opt<UC>()) = 0>\n#endif\n// dummy for compile\nbool simd_parse_if_eight_digits_unrolled(UC const*, uint64_t&) {\n  return 0;\n}\n\n\ntemplate <typename UC, FASTFLOAT_ENABLE_IF(!std::is_same<UC, char>::value) = 0>\nfastfloat_really_inline FASTFLOAT_CONSTEXPR20\nvoid loop_parse_if_eight_digits(const UC*& p, const UC* const pend, uint64_t& i) {\n  if (!has_simd_opt<UC>()) {\n    return;\n  }\n  while ((std::distance(p, pend) >= 8) && simd_parse_if_eight_digits_unrolled(p, i)) { // in rare cases, this will overflow, but that's ok\n    p += 8;\n  }\n}\n\nfastfloat_really_inline FASTFLOAT_CONSTEXPR20\nvoid loop_parse_if_eight_digits(const char*& p, const char* const pend, uint64_t& i) {\n  // optimizes better than parse_if_eight_digits_unrolled() for UC = char.\n  while ((std::distance(p, pend) >= 8) && is_made_of_eight_digits_fast(read8_to_u64(p))) {\n    i = i * 100000000 + parse_eight_digits_unrolled(read8_to_u64(p)); // in rare cases, this will overflow, but that's ok\n    p += 8;\n  }\n}\n\ntemplate <typename UC>\nstruct parsed_number_string_t {\n  int64_t exponent{0};\n  uint64_t mantissa{0};\n  UC const * lastmatch{nullptr};\n  bool negative{false};\n  bool valid{false};\n  bool too_many_digits{false};\n  // contains the range of the significant digits\n  span<const UC> integer{};  // non-nullable\n  span<const UC> fraction{}; // nullable\n};\n\nusing byte_span = span<const char>;\nusing parsed_number_string = parsed_number_string_t<char>;\n\n// Assuming that you use no more than 19 digits, this will\n// parse an ASCII string.\ntemplate <typename UC>\nfastfloat_really_inline FASTFLOAT_CONSTEXPR20\nparsed_number_string_t<UC> parse_number_string(UC const *p, UC const * pend, parse_options_t<UC> options) noexcept {\n  chars_format const fmt = options.format;\n  UC const decimal_point = options.decimal_point;\n\n  parsed_number_string_t<UC> answer;\n  answer.valid = false;\n  answer.too_many_digits = false;\n  answer.negative = (*p == UC('-'));\n#ifdef FASTFLOAT_ALLOWS_LEADING_PLUS // disabled by default\n  if ((*p == UC('-')) || (!(fmt & FASTFLOAT_JSONFMT) && *p == UC('+'))) {\n#else\n  if (*p == UC('-')) { // C++17 20.19.3.(7.1) explicitly forbids '+' sign here\n#endif\n    ++p;\n    if (p == pend) {\n      return answer;\n    }\n    if (fmt & FASTFLOAT_JSONFMT) {\n      if (!is_integer(*p)) { // a sign must be followed by an integer\n        return answer;\n      }    \n    } else {\n      if (!is_integer(*p) && (*p != decimal_point)) { // a sign must be followed by an integer or the dot\n        return answer;\n      }\n    }\n  }\n  UC const * const start_digits = p;\n\n  uint64_t i = 0; // an unsigned int avoids signed overflows (which are bad)\n\n  while ((p != pend) && is_integer(*p)) {\n    // a multiplication by 10 is cheaper than an arbitrary integer\n    // multiplication\n    i = 10 * i +\n        uint64_t(*p - UC('0')); // might overflow, we will handle the overflow later\n    ++p;\n  }\n  UC const * const end_of_integer_part = p;\n  int64_t digit_count = int64_t(end_of_integer_part - start_digits);\n  answer.integer = span<const UC>(start_digits, size_t(digit_count));\n  if (fmt & FASTFLOAT_JSONFMT) {\n    // at least 1 digit in integer part, without leading zeros\n    if (digit_count == 0 || (start_digits[0] == UC('0') && digit_count > 1)) {\n      return answer;\n    }\n  }\n\n  int64_t exponent = 0;\n  const bool has_decimal_point = (p != pend) && (*p == decimal_point);\n  if (has_decimal_point) {\n    ++p;\n    UC const * before = p;\n    // can occur at most twice without overflowing, but let it occur more, since\n    // for integers with many digits, digit parsing is the primary bottleneck.\n    loop_parse_if_eight_digits(p, pend, i);\n\n    while ((p != pend) && is_integer(*p)) {\n      uint8_t digit = uint8_t(*p - UC('0'));\n      ++p;\n      i = i * 10 + digit; // in rare cases, this will overflow, but that's ok\n    }\n    exponent = before - p;\n    answer.fraction = span<const UC>(before, size_t(p - before));\n    digit_count -= exponent;\n  }\n  if (fmt & FASTFLOAT_JSONFMT) {\n    // at least 1 digit in fractional part\n    if (has_decimal_point && exponent == 0) {\n      return answer;\n    }\n  } \n  else if (digit_count == 0) { // we must have encountered at least one integer!\n    return answer;\n  }\n  int64_t exp_number = 0;            // explicit exponential part\n  if ( ((fmt & chars_format::scientific) &&\n        (p != pend) &&\n        ((UC('e') == *p) || (UC('E') == *p)))\n       ||\n       ((fmt & FASTFLOAT_FORTRANFMT) &&\n        (p != pend) &&\n        ((UC('+') == *p) || (UC('-') == *p) || (UC('d') == *p) || (UC('D') == *p)))) {\n    UC const * location_of_e = p;\n    if ((UC('e') == *p) || (UC('E') == *p) || (UC('d') == *p) || (UC('D') == *p)) {\n      ++p;\n    }\n    bool neg_exp = false;\n    if ((p != pend) && (UC('-') == *p)) {\n      neg_exp = true;\n      ++p;\n    } else if ((p != pend) && (UC('+') == *p)) { // '+' on exponent is allowed by C++17 20.19.3.(7.1)\n      ++p;\n    }\n    if ((p == pend) || !is_integer(*p)) {\n      if(!(fmt & chars_format::fixed)) {\n        // We are in error.\n        return answer;\n      }\n      // Otherwise, we will be ignoring the 'e'.\n      p = location_of_e;\n    } else {\n      while ((p != pend) && is_integer(*p)) {\n        uint8_t digit = uint8_t(*p - UC('0'));\n        if (exp_number < 0x10000000) {\n          exp_number = 10 * exp_number + digit;\n        }\n        ++p;\n      }\n      if(neg_exp) { exp_number = - exp_number; }\n      exponent += exp_number;\n    }\n  } else {\n    // If it scientific and not fixed, we have to bail out.\n    if((fmt & chars_format::scientific) && !(fmt & chars_format::fixed)) { return answer; }\n  }\n  answer.lastmatch = p;\n  answer.valid = true;\n\n  // If we frequently had to deal with long strings of digits,\n  // we could extend our code by using a 128-bit integer instead\n  // of a 64-bit integer. However, this is uncommon.\n  //\n  // We can deal with up to 19 digits.\n  if (digit_count > 19) { // this is uncommon\n    // It is possible that the integer had an overflow.\n    // We have to handle the case where we have 0.0000somenumber.\n    // We need to be mindful of the case where we only have zeroes...\n    // E.g., 0.000000000...000.\n    UC const * start = start_digits;\n    while ((start != pend) && (*start == UC('0') || *start == decimal_point)) {\n      if(*start == UC('0')) { digit_count --; }\n      start++;\n    }\n\n    if (digit_count > 19) {\n      answer.too_many_digits = true;\n      // Let us start again, this time, avoiding overflows.\n      // We don't need to check if is_integer, since we use the\n      // pre-tokenized spans from above.\n      i = 0;\n      p = answer.integer.ptr;\n      UC const* int_end = p + answer.integer.len();\n      const uint64_t minimal_nineteen_digit_integer{ 1000000000000000000 };\n      while ((i < minimal_nineteen_digit_integer) && (p != int_end)) {\n        i = i * 10 + uint64_t(*p - UC('0'));\n        ++p;\n      }\n      if (i >= minimal_nineteen_digit_integer) { // We have a big integers\n        exponent = end_of_integer_part - p + exp_number;\n      }\n      else { // We have a value with a fractional component.\n        p = answer.fraction.ptr;\n        UC const* frac_end = p + answer.fraction.len();\n        while ((i < minimal_nineteen_digit_integer) && (p != frac_end)) {\n          i = i * 10 + uint64_t(*p - UC('0'));\n          ++p;\n        }\n        exponent = answer.fraction.ptr - p + exp_number;\n      }\n      // We have now corrected both exponent and i, to a truncated value\n    }\n  }\n  answer.exponent = exponent;\n  answer.mantissa = i;\n  return answer;\n}\n\ntemplate <typename T, typename UC>\nfastfloat_really_inline FASTFLOAT_CONSTEXPR20\nfrom_chars_result_t<UC> parse_int_string(UC const* p, UC const* pend, T& value, int base) {\n  from_chars_result_t<UC> answer;\n  \n  UC const* const first = p;\n\n  bool negative = (*p == UC('-'));\n  if (!std::is_signed<T>::value && negative) {\n    answer.ec = std::errc::invalid_argument;\n    answer.ptr = first;\n    return answer;\n  }\n#ifdef FASTFLOAT_ALLOWS_LEADING_PLUS // disabled by default\n  if ((*p == UC('-')) || (*p == UC('+'))) {\n#else\n  if (*p == UC('-')) {\n#endif\n    ++p;\n  }\n\n  UC const* const start_num = p;\n\n  while (p!= pend && *p == UC('0')) {\n    ++p; \n  }\n\n  const bool has_leading_zeros = p > start_num;\n\n  UC const* const start_digits = p;\n\n  uint64_t i = 0;\n  if (base == 10) {\n    loop_parse_if_eight_digits(p, pend, i); // use SIMD if possible\n  }\n  while (p != pend) {\n    uint8_t digit = ch_to_digit(*p);\n    if (digit >= base) {\n      break;\n    }\n    i = uint64_t(base) * i + digit; // might overflow, check this later\n    p++; \n  }\n  \n  size_t digit_count = size_t(p - start_digits);\n\n  if (digit_count == 0) {\n    if (has_leading_zeros) {\n      value = 0;\n      answer.ec = std::errc();\n      answer.ptr = p;\n    }\n    else {\n      answer.ec = std::errc::invalid_argument;\n      answer.ptr = first;\n    }\n    return answer; \n  }\n\n  answer.ptr = p;\n\n  // check u64 overflow\n  size_t max_digits = max_digits_u64(base);\n  if (digit_count > max_digits) {\n    answer.ec = std::errc::result_out_of_range;\n    return answer;\n  }\n  // this check can be eliminated for all other types, but they will all require a max_digits(base) equivalent\n  if (digit_count == max_digits && i < min_safe_u64(base)) {\n    answer.ec = std::errc::result_out_of_range;\n    return answer;\n  }\n\n  // check other types overflow\n  if (!std::is_same<T, uint64_t>::value) {\n    if (i > uint64_t(std::numeric_limits<T>::max()) + uint64_t(negative)) {\n      answer.ec = std::errc::result_out_of_range;\n      return answer;\n    }\n  }\n\n  if (negative) {\n#ifdef FASTFLOAT_VISUAL_STUDIO\n#pragma warning(push)\n#pragma warning(disable: 4146) \n#endif\n    // this weird workaround is required because:\n    // - converting unsigned to signed when its value is greater than signed max is UB pre-C++23.\n    // - reinterpret_casting (~i + 1) would work, but it is not constexpr\n    // this is always optimized into a neg instruction (note: T is an integer type)\n    value = T(-std::numeric_limits<T>::max() - T(i - uint64_t(std::numeric_limits<T>::max())));\n#ifdef FASTFLOAT_VISUAL_STUDIO\n#pragma warning(pop)\n#endif\n  }\n  else { value = T(i); }\n\n  answer.ec = std::errc();\n  return answer;\n}\n\n} // namespace fast_float\n\n#endif\n\n#ifndef FASTFLOAT_FAST_TABLE_H\n#define FASTFLOAT_FAST_TABLE_H\n\n#include <cstdint>\n\nnamespace fast_float {\n\n/**\n * When mapping numbers from decimal to binary,\n * we go from w * 10^q to m * 2^p but we have\n * 10^q = 5^q * 2^q, so effectively\n * we are trying to match\n * w * 2^q * 5^q to m * 2^p. Thus the powers of two\n * are not a concern since they can be represented\n * exactly using the binary notation, only the powers of five\n * affect the binary significand.\n */\n\n/**\n * The smallest non-zero float (binary64) is 2^-1074.\n * We take as input numbers of the form w x 10^q where w < 2^64.\n * We have that w * 10^-343  <  2^(64-344) 5^-343 < 2^-1076.\n * However, we have that\n * (2^64-1) * 10^-342 =  (2^64-1) * 2^-342 * 5^-342 > 2^-1074.\n * Thus it is possible for a number of the form w * 10^-342 where\n * w is a 64-bit value to be a non-zero floating-point number.\n *********\n * Any number of form w * 10^309 where w>= 1 is going to be\n * infinite in binary64 so we never need to worry about powers\n * of 5 greater than 308.\n */\ntemplate <class unused = void>\nstruct powers_template {\n\nconstexpr static int smallest_power_of_five = binary_format<double>::smallest_power_of_ten();\nconstexpr static int largest_power_of_five = binary_format<double>::largest_power_of_ten();\nconstexpr static int number_of_entries = 2 * (largest_power_of_five - smallest_power_of_five + 1);\n// Powers of five from 5^-342 all the way to 5^308 rounded toward one.\nconstexpr static uint64_t power_of_five_128[number_of_entries] = {\n    0xeef453d6923bd65a,0x113faa2906a13b3f,\n    0x9558b4661b6565f8,0x4ac7ca59a424c507,\n    0xbaaee17fa23ebf76,0x5d79bcf00d2df649,\n    0xe95a99df8ace6f53,0xf4d82c2c107973dc,\n    0x91d8a02bb6c10594,0x79071b9b8a4be869,\n    0xb64ec836a47146f9,0x9748e2826cdee284,\n    0xe3e27a444d8d98b7,0xfd1b1b2308169b25,\n    0x8e6d8c6ab0787f72,0xfe30f0f5e50e20f7,\n    0xb208ef855c969f4f,0xbdbd2d335e51a935,\n    0xde8b2b66b3bc4723,0xad2c788035e61382,\n    0x8b16fb203055ac76,0x4c3bcb5021afcc31,\n    0xaddcb9e83c6b1793,0xdf4abe242a1bbf3d,\n    0xd953e8624b85dd78,0xd71d6dad34a2af0d,\n    0x87d4713d6f33aa6b,0x8672648c40e5ad68,\n    0xa9c98d8ccb009506,0x680efdaf511f18c2,\n    0xd43bf0effdc0ba48,0x212bd1b2566def2,\n    0x84a57695fe98746d,0x14bb630f7604b57,\n    0xa5ced43b7e3e9188,0x419ea3bd35385e2d,\n    0xcf42894a5dce35ea,0x52064cac828675b9,\n    0x818995ce7aa0e1b2,0x7343efebd1940993,\n    0xa1ebfb4219491a1f,0x1014ebe6c5f90bf8,\n    0xca66fa129f9b60a6,0xd41a26e077774ef6,\n    0xfd00b897478238d0,0x8920b098955522b4,\n    0x9e20735e8cb16382,0x55b46e5f5d5535b0,\n    0xc5a890362fddbc62,0xeb2189f734aa831d,\n    0xf712b443bbd52b7b,0xa5e9ec7501d523e4,\n    0x9a6bb0aa55653b2d,0x47b233c92125366e,\n    0xc1069cd4eabe89f8,0x999ec0bb696e840a,\n    0xf148440a256e2c76,0xc00670ea43ca250d,\n    0x96cd2a865764dbca,0x380406926a5e5728,\n    0xbc807527ed3e12bc,0xc605083704f5ecf2,\n    0xeba09271e88d976b,0xf7864a44c633682e,\n    0x93445b8731587ea3,0x7ab3ee6afbe0211d,\n    0xb8157268fdae9e4c,0x5960ea05bad82964,\n    0xe61acf033d1a45df,0x6fb92487298e33bd,\n    0x8fd0c16206306bab,0xa5d3b6d479f8e056,\n    0xb3c4f1ba87bc8696,0x8f48a4899877186c,\n    0xe0b62e2929aba83c,0x331acdabfe94de87,\n    0x8c71dcd9ba0b4925,0x9ff0c08b7f1d0b14,\n    0xaf8e5410288e1b6f,0x7ecf0ae5ee44dd9,\n    0xdb71e91432b1a24a,0xc9e82cd9f69d6150,\n    0x892731ac9faf056e,0xbe311c083a225cd2,\n    0xab70fe17c79ac6ca,0x6dbd630a48aaf406,\n    0xd64d3d9db981787d,0x92cbbccdad5b108,\n    0x85f0468293f0eb4e,0x25bbf56008c58ea5,\n    0xa76c582338ed2621,0xaf2af2b80af6f24e,\n    0xd1476e2c07286faa,0x1af5af660db4aee1,\n    0x82cca4db847945ca,0x50d98d9fc890ed4d,\n    0xa37fce126597973c,0xe50ff107bab528a0,\n    0xcc5fc196fefd7d0c,0x1e53ed49a96272c8,\n    0xff77b1fcbebcdc4f,0x25e8e89c13bb0f7a,\n    0x9faacf3df73609b1,0x77b191618c54e9ac,\n    0xc795830d75038c1d,0xd59df5b9ef6a2417,\n    0xf97ae3d0d2446f25,0x4b0573286b44ad1d,\n    0x9becce62836ac577,0x4ee367f9430aec32,\n    0xc2e801fb244576d5,0x229c41f793cda73f,\n    0xf3a20279ed56d48a,0x6b43527578c1110f,\n    0x9845418c345644d6,0x830a13896b78aaa9,\n    0xbe5691ef416bd60c,0x23cc986bc656d553,\n    0xedec366b11c6cb8f,0x2cbfbe86b7ec8aa8,\n    0x94b3a202eb1c3f39,0x7bf7d71432f3d6a9,\n    0xb9e08a83a5e34f07,0xdaf5ccd93fb0cc53,\n    0xe858ad248f5c22c9,0xd1b3400f8f9cff68,\n    0x91376c36d99995be,0x23100809b9c21fa1,\n    0xb58547448ffffb2d,0xabd40a0c2832a78a,\n    0xe2e69915b3fff9f9,0x16c90c8f323f516c,\n    0x8dd01fad907ffc3b,0xae3da7d97f6792e3,\n    0xb1442798f49ffb4a,0x99cd11cfdf41779c,\n    0xdd95317f31c7fa1d,0x40405643d711d583,\n    0x8a7d3eef7f1cfc52,0x482835ea666b2572,\n    0xad1c8eab5ee43b66,0xda3243650005eecf,\n    0xd863b256369d4a40,0x90bed43e40076a82,\n    0x873e4f75e2224e68,0x5a7744a6e804a291,\n    0xa90de3535aaae202,0x711515d0a205cb36,\n    0xd3515c2831559a83,0xd5a5b44ca873e03,\n    0x8412d9991ed58091,0xe858790afe9486c2,\n    0xa5178fff668ae0b6,0x626e974dbe39a872,\n    0xce5d73ff402d98e3,0xfb0a3d212dc8128f,\n    0x80fa687f881c7f8e,0x7ce66634bc9d0b99,\n    0xa139029f6a239f72,0x1c1fffc1ebc44e80,\n    0xc987434744ac874e,0xa327ffb266b56220,\n    0xfbe9141915d7a922,0x4bf1ff9f0062baa8,\n    0x9d71ac8fada6c9b5,0x6f773fc3603db4a9,\n    0xc4ce17b399107c22,0xcb550fb4384d21d3,\n    0xf6019da07f549b2b,0x7e2a53a146606a48,\n    0x99c102844f94e0fb,0x2eda7444cbfc426d,\n    0xc0314325637a1939,0xfa911155fefb5308,\n    0xf03d93eebc589f88,0x793555ab7eba27ca,\n    0x96267c7535b763b5,0x4bc1558b2f3458de,\n    0xbbb01b9283253ca2,0x9eb1aaedfb016f16,\n    0xea9c227723ee8bcb,0x465e15a979c1cadc,\n    0x92a1958a7675175f,0xbfacd89ec191ec9,\n    0xb749faed14125d36,0xcef980ec671f667b,\n    0xe51c79a85916f484,0x82b7e12780e7401a,\n    0x8f31cc0937ae58d2,0xd1b2ecb8b0908810,\n    0xb2fe3f0b8599ef07,0x861fa7e6dcb4aa15,\n    0xdfbdcece67006ac9,0x67a791e093e1d49a,\n    0x8bd6a141006042bd,0xe0c8bb2c5c6d24e0,\n    0xaecc49914078536d,0x58fae9f773886e18,\n    0xda7f5bf590966848,0xaf39a475506a899e,\n    0x888f99797a5e012d,0x6d8406c952429603,\n    0xaab37fd7d8f58178,0xc8e5087ba6d33b83,\n    0xd5605fcdcf32e1d6,0xfb1e4a9a90880a64,\n    0x855c3be0a17fcd26,0x5cf2eea09a55067f,\n    0xa6b34ad8c9dfc06f,0xf42faa48c0ea481e,\n    0xd0601d8efc57b08b,0xf13b94daf124da26,\n    0x823c12795db6ce57,0x76c53d08d6b70858,\n    0xa2cb1717b52481ed,0x54768c4b0c64ca6e,\n    0xcb7ddcdda26da268,0xa9942f5dcf7dfd09,\n    0xfe5d54150b090b02,0xd3f93b35435d7c4c,\n    0x9efa548d26e5a6e1,0xc47bc5014a1a6daf,\n    0xc6b8e9b0709f109a,0x359ab6419ca1091b,\n    0xf867241c8cc6d4c0,0xc30163d203c94b62,\n    0x9b407691d7fc44f8,0x79e0de63425dcf1d,\n    0xc21094364dfb5636,0x985915fc12f542e4,\n    0xf294b943e17a2bc4,0x3e6f5b7b17b2939d,\n    0x979cf3ca6cec5b5a,0xa705992ceecf9c42,\n    0xbd8430bd08277231,0x50c6ff782a838353,\n    0xece53cec4a314ebd,0xa4f8bf5635246428,\n    0x940f4613ae5ed136,0x871b7795e136be99,\n    0xb913179899f68584,0x28e2557b59846e3f,\n    0xe757dd7ec07426e5,0x331aeada2fe589cf,\n    0x9096ea6f3848984f,0x3ff0d2c85def7621,\n    0xb4bca50b065abe63,0xfed077a756b53a9,\n    0xe1ebce4dc7f16dfb,0xd3e8495912c62894,\n    0x8d3360f09cf6e4bd,0x64712dd7abbbd95c,\n    0xb080392cc4349dec,0xbd8d794d96aacfb3,\n    0xdca04777f541c567,0xecf0d7a0fc5583a0,\n    0x89e42caaf9491b60,0xf41686c49db57244,\n    0xac5d37d5b79b6239,0x311c2875c522ced5,\n    0xd77485cb25823ac7,0x7d633293366b828b,\n    0x86a8d39ef77164bc,0xae5dff9c02033197,\n    0xa8530886b54dbdeb,0xd9f57f830283fdfc,\n    0xd267caa862a12d66,0xd072df63c324fd7b,\n    0x8380dea93da4bc60,0x4247cb9e59f71e6d,\n    0xa46116538d0deb78,0x52d9be85f074e608,\n    0xcd795be870516656,0x67902e276c921f8b,\n    0x806bd9714632dff6,0xba1cd8a3db53b6,\n    0xa086cfcd97bf97f3,0x80e8a40eccd228a4,\n    0xc8a883c0fdaf7df0,0x6122cd128006b2cd,\n    0xfad2a4b13d1b5d6c,0x796b805720085f81,\n    0x9cc3a6eec6311a63,0xcbe3303674053bb0,\n    0xc3f490aa77bd60fc,0xbedbfc4411068a9c,\n    0xf4f1b4d515acb93b,0xee92fb5515482d44,\n    0x991711052d8bf3c5,0x751bdd152d4d1c4a,\n    0xbf5cd54678eef0b6,0xd262d45a78a0635d,\n    0xef340a98172aace4,0x86fb897116c87c34,\n    0x9580869f0e7aac0e,0xd45d35e6ae3d4da0,\n    0xbae0a846d2195712,0x8974836059cca109,\n    0xe998d258869facd7,0x2bd1a438703fc94b,\n    0x91ff83775423cc06,0x7b6306a34627ddcf,\n    0xb67f6455292cbf08,0x1a3bc84c17b1d542,\n    0xe41f3d6a7377eeca,0x20caba5f1d9e4a93,\n    0x8e938662882af53e,0x547eb47b7282ee9c,\n    0xb23867fb2a35b28d,0xe99e619a4f23aa43,\n    0xdec681f9f4c31f31,0x6405fa00e2ec94d4,\n    0x8b3c113c38f9f37e,0xde83bc408dd3dd04,\n    0xae0b158b4738705e,0x9624ab50b148d445,\n    0xd98ddaee19068c76,0x3badd624dd9b0957,\n    0x87f8a8d4cfa417c9,0xe54ca5d70a80e5d6,\n    0xa9f6d30a038d1dbc,0x5e9fcf4ccd211f4c,\n    0xd47487cc8470652b,0x7647c3200069671f,\n    0x84c8d4dfd2c63f3b,0x29ecd9f40041e073,\n    0xa5fb0a17c777cf09,0xf468107100525890,\n    0xcf79cc9db955c2cc,0x7182148d4066eeb4,\n    0x81ac1fe293d599bf,0xc6f14cd848405530,\n    0xa21727db38cb002f,0xb8ada00e5a506a7c,\n    0xca9cf1d206fdc03b,0xa6d90811f0e4851c,\n    0xfd442e4688bd304a,0x908f4a166d1da663,\n    0x9e4a9cec15763e2e,0x9a598e4e043287fe,\n    0xc5dd44271ad3cdba,0x40eff1e1853f29fd,\n    0xf7549530e188c128,0xd12bee59e68ef47c,\n    0x9a94dd3e8cf578b9,0x82bb74f8301958ce,\n    0xc13a148e3032d6e7,0xe36a52363c1faf01,\n    0xf18899b1bc3f8ca1,0xdc44e6c3cb279ac1,\n    0x96f5600f15a7b7e5,0x29ab103a5ef8c0b9,\n    0xbcb2b812db11a5de,0x7415d448f6b6f0e7,\n    0xebdf661791d60f56,0x111b495b3464ad21,\n    0x936b9fcebb25c995,0xcab10dd900beec34,\n    0xb84687c269ef3bfb,0x3d5d514f40eea742,\n    0xe65829b3046b0afa,0xcb4a5a3112a5112,\n    0x8ff71a0fe2c2e6dc,0x47f0e785eaba72ab,\n    0xb3f4e093db73a093,0x59ed216765690f56,\n    0xe0f218b8d25088b8,0x306869c13ec3532c,\n    0x8c974f7383725573,0x1e414218c73a13fb,\n    0xafbd2350644eeacf,0xe5d1929ef90898fa,\n    0xdbac6c247d62a583,0xdf45f746b74abf39,\n    0x894bc396ce5da772,0x6b8bba8c328eb783,\n    0xab9eb47c81f5114f,0x66ea92f3f326564,\n    0xd686619ba27255a2,0xc80a537b0efefebd,\n    0x8613fd0145877585,0xbd06742ce95f5f36,\n    0xa798fc4196e952e7,0x2c48113823b73704,\n    0xd17f3b51fca3a7a0,0xf75a15862ca504c5,\n    0x82ef85133de648c4,0x9a984d73dbe722fb,\n    0xa3ab66580d5fdaf5,0xc13e60d0d2e0ebba,\n    0xcc963fee10b7d1b3,0x318df905079926a8,\n    0xffbbcfe994e5c61f,0xfdf17746497f7052,\n    0x9fd561f1fd0f9bd3,0xfeb6ea8bedefa633,\n    0xc7caba6e7c5382c8,0xfe64a52ee96b8fc0,\n    0xf9bd690a1b68637b,0x3dfdce7aa3c673b0,\n    0x9c1661a651213e2d,0x6bea10ca65c084e,\n    0xc31bfa0fe5698db8,0x486e494fcff30a62,\n    0xf3e2f893dec3f126,0x5a89dba3c3efccfa,\n    0x986ddb5c6b3a76b7,0xf89629465a75e01c,\n    0xbe89523386091465,0xf6bbb397f1135823,\n    0xee2ba6c0678b597f,0x746aa07ded582e2c,\n    0x94db483840b717ef,0xa8c2a44eb4571cdc,\n    0xba121a4650e4ddeb,0x92f34d62616ce413,\n    0xe896a0d7e51e1566,0x77b020baf9c81d17,\n    0x915e2486ef32cd60,0xace1474dc1d122e,\n    0xb5b5ada8aaff80b8,0xd819992132456ba,\n    0xe3231912d5bf60e6,0x10e1fff697ed6c69,\n    0x8df5efabc5979c8f,0xca8d3ffa1ef463c1,\n    0xb1736b96b6fd83b3,0xbd308ff8a6b17cb2,\n    0xddd0467c64bce4a0,0xac7cb3f6d05ddbde,\n    0x8aa22c0dbef60ee4,0x6bcdf07a423aa96b,\n    0xad4ab7112eb3929d,0x86c16c98d2c953c6,\n    0xd89d64d57a607744,0xe871c7bf077ba8b7,\n    0x87625f056c7c4a8b,0x11471cd764ad4972,\n    0xa93af6c6c79b5d2d,0xd598e40d3dd89bcf,\n    0xd389b47879823479,0x4aff1d108d4ec2c3,\n    0x843610cb4bf160cb,0xcedf722a585139ba,\n    0xa54394fe1eedb8fe,0xc2974eb4ee658828,\n    0xce947a3da6a9273e,0x733d226229feea32,\n    0x811ccc668829b887,0x806357d5a3f525f,\n    0xa163ff802a3426a8,0xca07c2dcb0cf26f7,\n    0xc9bcff6034c13052,0xfc89b393dd02f0b5,\n    0xfc2c3f3841f17c67,0xbbac2078d443ace2,\n    0x9d9ba7832936edc0,0xd54b944b84aa4c0d,\n    0xc5029163f384a931,0xa9e795e65d4df11,\n    0xf64335bcf065d37d,0x4d4617b5ff4a16d5,\n    0x99ea0196163fa42e,0x504bced1bf8e4e45,\n    0xc06481fb9bcf8d39,0xe45ec2862f71e1d6,\n    0xf07da27a82c37088,0x5d767327bb4e5a4c,\n    0x964e858c91ba2655,0x3a6a07f8d510f86f,\n    0xbbe226efb628afea,0x890489f70a55368b,\n    0xeadab0aba3b2dbe5,0x2b45ac74ccea842e,\n    0x92c8ae6b464fc96f,0x3b0b8bc90012929d,\n    0xb77ada0617e3bbcb,0x9ce6ebb40173744,\n    0xe55990879ddcaabd,0xcc420a6a101d0515,\n    0x8f57fa54c2a9eab6,0x9fa946824a12232d,\n    0xb32df8e9f3546564,0x47939822dc96abf9,\n    0xdff9772470297ebd,0x59787e2b93bc56f7,\n    0x8bfbea76c619ef36,0x57eb4edb3c55b65a,\n    0xaefae51477a06b03,0xede622920b6b23f1,\n    0xdab99e59958885c4,0xe95fab368e45eced,\n    0x88b402f7fd75539b,0x11dbcb0218ebb414,\n    0xaae103b5fcd2a881,0xd652bdc29f26a119,\n    0xd59944a37c0752a2,0x4be76d3346f0495f,\n    0x857fcae62d8493a5,0x6f70a4400c562ddb,\n    0xa6dfbd9fb8e5b88e,0xcb4ccd500f6bb952,\n    0xd097ad07a71f26b2,0x7e2000a41346a7a7,\n    0x825ecc24c873782f,0x8ed400668c0c28c8,\n    0xa2f67f2dfa90563b,0x728900802f0f32fa,\n    0xcbb41ef979346bca,0x4f2b40a03ad2ffb9,\n    0xfea126b7d78186bc,0xe2f610c84987bfa8,\n    0x9f24b832e6b0f436,0xdd9ca7d2df4d7c9,\n    0xc6ede63fa05d3143,0x91503d1c79720dbb,\n    0xf8a95fcf88747d94,0x75a44c6397ce912a,\n    0x9b69dbe1b548ce7c,0xc986afbe3ee11aba,\n    0xc24452da229b021b,0xfbe85badce996168,\n    0xf2d56790ab41c2a2,0xfae27299423fb9c3,\n    0x97c560ba6b0919a5,0xdccd879fc967d41a,\n    0xbdb6b8e905cb600f,0x5400e987bbc1c920,\n    0xed246723473e3813,0x290123e9aab23b68,\n    0x9436c0760c86e30b,0xf9a0b6720aaf6521,\n    0xb94470938fa89bce,0xf808e40e8d5b3e69,\n    0xe7958cb87392c2c2,0xb60b1d1230b20e04,\n    0x90bd77f3483bb9b9,0xb1c6f22b5e6f48c2,\n    0xb4ecd5f01a4aa828,0x1e38aeb6360b1af3,\n    0xe2280b6c20dd5232,0x25c6da63c38de1b0,\n    0x8d590723948a535f,0x579c487e5a38ad0e,\n    0xb0af48ec79ace837,0x2d835a9df0c6d851,\n    0xdcdb1b2798182244,0xf8e431456cf88e65,\n    0x8a08f0f8bf0f156b,0x1b8e9ecb641b58ff,\n    0xac8b2d36eed2dac5,0xe272467e3d222f3f,\n    0xd7adf884aa879177,0x5b0ed81dcc6abb0f,\n    0x86ccbb52ea94baea,0x98e947129fc2b4e9,\n    0xa87fea27a539e9a5,0x3f2398d747b36224,\n    0xd29fe4b18e88640e,0x8eec7f0d19a03aad,\n    0x83a3eeeef9153e89,0x1953cf68300424ac,\n    0xa48ceaaab75a8e2b,0x5fa8c3423c052dd7,\n    0xcdb02555653131b6,0x3792f412cb06794d,\n    0x808e17555f3ebf11,0xe2bbd88bbee40bd0,\n    0xa0b19d2ab70e6ed6,0x5b6aceaeae9d0ec4,\n    0xc8de047564d20a8b,0xf245825a5a445275,\n    0xfb158592be068d2e,0xeed6e2f0f0d56712,\n    0x9ced737bb6c4183d,0x55464dd69685606b,\n    0xc428d05aa4751e4c,0xaa97e14c3c26b886,\n    0xf53304714d9265df,0xd53dd99f4b3066a8,\n    0x993fe2c6d07b7fab,0xe546a8038efe4029,\n    0xbf8fdb78849a5f96,0xde98520472bdd033,\n    0xef73d256a5c0f77c,0x963e66858f6d4440,\n    0x95a8637627989aad,0xdde7001379a44aa8,\n    0xbb127c53b17ec159,0x5560c018580d5d52,\n    0xe9d71b689dde71af,0xaab8f01e6e10b4a6,\n    0x9226712162ab070d,0xcab3961304ca70e8,\n    0xb6b00d69bb55c8d1,0x3d607b97c5fd0d22,\n    0xe45c10c42a2b3b05,0x8cb89a7db77c506a,\n    0x8eb98a7a9a5b04e3,0x77f3608e92adb242,\n    0xb267ed1940f1c61c,0x55f038b237591ed3,\n    0xdf01e85f912e37a3,0x6b6c46dec52f6688,\n    0x8b61313bbabce2c6,0x2323ac4b3b3da015,\n    0xae397d8aa96c1b77,0xabec975e0a0d081a,\n    0xd9c7dced53c72255,0x96e7bd358c904a21,\n    0x881cea14545c7575,0x7e50d64177da2e54,\n    0xaa242499697392d2,0xdde50bd1d5d0b9e9,\n    0xd4ad2dbfc3d07787,0x955e4ec64b44e864,\n    0x84ec3c97da624ab4,0xbd5af13bef0b113e,\n    0xa6274bbdd0fadd61,0xecb1ad8aeacdd58e,\n    0xcfb11ead453994ba,0x67de18eda5814af2,\n    0x81ceb32c4b43fcf4,0x80eacf948770ced7,\n    0xa2425ff75e14fc31,0xa1258379a94d028d,\n    0xcad2f7f5359a3b3e,0x96ee45813a04330,\n    0xfd87b5f28300ca0d,0x8bca9d6e188853fc,\n    0x9e74d1b791e07e48,0x775ea264cf55347e,\n    0xc612062576589dda,0x95364afe032a819e,\n    0xf79687aed3eec551,0x3a83ddbd83f52205,\n    0x9abe14cd44753b52,0xc4926a9672793543,\n    0xc16d9a0095928a27,0x75b7053c0f178294,\n    0xf1c90080baf72cb1,0x5324c68b12dd6339,\n    0x971da05074da7bee,0xd3f6fc16ebca5e04,\n    0xbce5086492111aea,0x88f4bb1ca6bcf585,\n    0xec1e4a7db69561a5,0x2b31e9e3d06c32e6,\n    0x9392ee8e921d5d07,0x3aff322e62439fd0,\n    0xb877aa3236a4b449,0x9befeb9fad487c3,\n    0xe69594bec44de15b,0x4c2ebe687989a9b4,\n    0x901d7cf73ab0acd9,0xf9d37014bf60a11,\n    0xb424dc35095cd80f,0x538484c19ef38c95,\n    0xe12e13424bb40e13,0x2865a5f206b06fba,\n    0x8cbccc096f5088cb,0xf93f87b7442e45d4,\n    0xafebff0bcb24aafe,0xf78f69a51539d749,\n    0xdbe6fecebdedd5be,0xb573440e5a884d1c,\n    0x89705f4136b4a597,0x31680a88f8953031,\n    0xabcc77118461cefc,0xfdc20d2b36ba7c3e,\n    0xd6bf94d5e57a42bc,0x3d32907604691b4d,\n    0x8637bd05af6c69b5,0xa63f9a49c2c1b110,\n    0xa7c5ac471b478423,0xfcf80dc33721d54,\n    0xd1b71758e219652b,0xd3c36113404ea4a9,\n    0x83126e978d4fdf3b,0x645a1cac083126ea,\n    0xa3d70a3d70a3d70a,0x3d70a3d70a3d70a4,\n    0xcccccccccccccccc,0xcccccccccccccccd,\n    0x8000000000000000,0x0,\n    0xa000000000000000,0x0,\n    0xc800000000000000,0x0,\n    0xfa00000000000000,0x0,\n    0x9c40000000000000,0x0,\n    0xc350000000000000,0x0,\n    0xf424000000000000,0x0,\n    0x9896800000000000,0x0,\n    0xbebc200000000000,0x0,\n    0xee6b280000000000,0x0,\n    0x9502f90000000000,0x0,\n    0xba43b74000000000,0x0,\n    0xe8d4a51000000000,0x0,\n    0x9184e72a00000000,0x0,\n    0xb5e620f480000000,0x0,\n    0xe35fa931a0000000,0x0,\n    0x8e1bc9bf04000000,0x0,\n    0xb1a2bc2ec5000000,0x0,\n    0xde0b6b3a76400000,0x0,\n    0x8ac7230489e80000,0x0,\n    0xad78ebc5ac620000,0x0,\n    0xd8d726b7177a8000,0x0,\n    0x878678326eac9000,0x0,\n    0xa968163f0a57b400,0x0,\n    0xd3c21bcecceda100,0x0,\n    0x84595161401484a0,0x0,\n    0xa56fa5b99019a5c8,0x0,\n    0xcecb8f27f4200f3a,0x0,\n    0x813f3978f8940984,0x4000000000000000,\n    0xa18f07d736b90be5,0x5000000000000000,\n    0xc9f2c9cd04674ede,0xa400000000000000,\n    0xfc6f7c4045812296,0x4d00000000000000,\n    0x9dc5ada82b70b59d,0xf020000000000000,\n    0xc5371912364ce305,0x6c28000000000000,\n    0xf684df56c3e01bc6,0xc732000000000000,\n    0x9a130b963a6c115c,0x3c7f400000000000,\n    0xc097ce7bc90715b3,0x4b9f100000000000,\n    0xf0bdc21abb48db20,0x1e86d40000000000,\n    0x96769950b50d88f4,0x1314448000000000,\n    0xbc143fa4e250eb31,0x17d955a000000000,\n    0xeb194f8e1ae525fd,0x5dcfab0800000000,\n    0x92efd1b8d0cf37be,0x5aa1cae500000000,\n    0xb7abc627050305ad,0xf14a3d9e40000000,\n    0xe596b7b0c643c719,0x6d9ccd05d0000000,\n    0x8f7e32ce7bea5c6f,0xe4820023a2000000,\n    0xb35dbf821ae4f38b,0xdda2802c8a800000,\n    0xe0352f62a19e306e,0xd50b2037ad200000,\n    0x8c213d9da502de45,0x4526f422cc340000,\n    0xaf298d050e4395d6,0x9670b12b7f410000,\n    0xdaf3f04651d47b4c,0x3c0cdd765f114000,\n    0x88d8762bf324cd0f,0xa5880a69fb6ac800,\n    0xab0e93b6efee0053,0x8eea0d047a457a00,\n    0xd5d238a4abe98068,0x72a4904598d6d880,\n    0x85a36366eb71f041,0x47a6da2b7f864750,\n    0xa70c3c40a64e6c51,0x999090b65f67d924,\n    0xd0cf4b50cfe20765,0xfff4b4e3f741cf6d,\n    0x82818f1281ed449f,0xbff8f10e7a8921a4,\n    0xa321f2d7226895c7,0xaff72d52192b6a0d,\n    0xcbea6f8ceb02bb39,0x9bf4f8a69f764490,\n    0xfee50b7025c36a08,0x2f236d04753d5b4,\n    0x9f4f2726179a2245,0x1d762422c946590,\n    0xc722f0ef9d80aad6,0x424d3ad2b7b97ef5,\n    0xf8ebad2b84e0d58b,0xd2e0898765a7deb2,\n    0x9b934c3b330c8577,0x63cc55f49f88eb2f,\n    0xc2781f49ffcfa6d5,0x3cbf6b71c76b25fb,\n    0xf316271c7fc3908a,0x8bef464e3945ef7a,\n    0x97edd871cfda3a56,0x97758bf0e3cbb5ac,\n    0xbde94e8e43d0c8ec,0x3d52eeed1cbea317,\n    0xed63a231d4c4fb27,0x4ca7aaa863ee4bdd,\n    0x945e455f24fb1cf8,0x8fe8caa93e74ef6a,\n    0xb975d6b6ee39e436,0xb3e2fd538e122b44,\n    0xe7d34c64a9c85d44,0x60dbbca87196b616,\n    0x90e40fbeea1d3a4a,0xbc8955e946fe31cd,\n    0xb51d13aea4a488dd,0x6babab6398bdbe41,\n    0xe264589a4dcdab14,0xc696963c7eed2dd1,\n    0x8d7eb76070a08aec,0xfc1e1de5cf543ca2,\n    0xb0de65388cc8ada8,0x3b25a55f43294bcb,\n    0xdd15fe86affad912,0x49ef0eb713f39ebe,\n    0x8a2dbf142dfcc7ab,0x6e3569326c784337,\n    0xacb92ed9397bf996,0x49c2c37f07965404,\n    0xd7e77a8f87daf7fb,0xdc33745ec97be906,\n    0x86f0ac99b4e8dafd,0x69a028bb3ded71a3,\n    0xa8acd7c0222311bc,0xc40832ea0d68ce0c,\n    0xd2d80db02aabd62b,0xf50a3fa490c30190,\n    0x83c7088e1aab65db,0x792667c6da79e0fa,\n    0xa4b8cab1a1563f52,0x577001b891185938,\n    0xcde6fd5e09abcf26,0xed4c0226b55e6f86,\n    0x80b05e5ac60b6178,0x544f8158315b05b4,\n    0xa0dc75f1778e39d6,0x696361ae3db1c721,\n    0xc913936dd571c84c,0x3bc3a19cd1e38e9,\n    0xfb5878494ace3a5f,0x4ab48a04065c723,\n    0x9d174b2dcec0e47b,0x62eb0d64283f9c76,\n    0xc45d1df942711d9a,0x3ba5d0bd324f8394,\n    0xf5746577930d6500,0xca8f44ec7ee36479,\n    0x9968bf6abbe85f20,0x7e998b13cf4e1ecb,\n    0xbfc2ef456ae276e8,0x9e3fedd8c321a67e,\n    0xefb3ab16c59b14a2,0xc5cfe94ef3ea101e,\n    0x95d04aee3b80ece5,0xbba1f1d158724a12,\n    0xbb445da9ca61281f,0x2a8a6e45ae8edc97,\n    0xea1575143cf97226,0xf52d09d71a3293bd,\n    0x924d692ca61be758,0x593c2626705f9c56,\n    0xb6e0c377cfa2e12e,0x6f8b2fb00c77836c,\n    0xe498f455c38b997a,0xb6dfb9c0f956447,\n    0x8edf98b59a373fec,0x4724bd4189bd5eac,\n    0xb2977ee300c50fe7,0x58edec91ec2cb657,\n    0xdf3d5e9bc0f653e1,0x2f2967b66737e3ed,\n    0x8b865b215899f46c,0xbd79e0d20082ee74,\n    0xae67f1e9aec07187,0xecd8590680a3aa11,\n    0xda01ee641a708de9,0xe80e6f4820cc9495,\n    0x884134fe908658b2,0x3109058d147fdcdd,\n    0xaa51823e34a7eede,0xbd4b46f0599fd415,\n    0xd4e5e2cdc1d1ea96,0x6c9e18ac7007c91a,\n    0x850fadc09923329e,0x3e2cf6bc604ddb0,\n    0xa6539930bf6bff45,0x84db8346b786151c,\n    0xcfe87f7cef46ff16,0xe612641865679a63,\n    0x81f14fae158c5f6e,0x4fcb7e8f3f60c07e,\n    0xa26da3999aef7749,0xe3be5e330f38f09d,\n    0xcb090c8001ab551c,0x5cadf5bfd3072cc5,\n    0xfdcb4fa002162a63,0x73d9732fc7c8f7f6,\n    0x9e9f11c4014dda7e,0x2867e7fddcdd9afa,\n    0xc646d63501a1511d,0xb281e1fd541501b8,\n    0xf7d88bc24209a565,0x1f225a7ca91a4226,\n    0x9ae757596946075f,0x3375788de9b06958,\n    0xc1a12d2fc3978937,0x52d6b1641c83ae,\n    0xf209787bb47d6b84,0xc0678c5dbd23a49a,\n    0x9745eb4d50ce6332,0xf840b7ba963646e0,\n    0xbd176620a501fbff,0xb650e5a93bc3d898,\n    0xec5d3fa8ce427aff,0xa3e51f138ab4cebe,\n    0x93ba47c980e98cdf,0xc66f336c36b10137,\n    0xb8a8d9bbe123f017,0xb80b0047445d4184,\n    0xe6d3102ad96cec1d,0xa60dc059157491e5,\n    0x9043ea1ac7e41392,0x87c89837ad68db2f,\n    0xb454e4a179dd1877,0x29babe4598c311fb,\n    0xe16a1dc9d8545e94,0xf4296dd6fef3d67a,\n    0x8ce2529e2734bb1d,0x1899e4a65f58660c,\n    0xb01ae745b101e9e4,0x5ec05dcff72e7f8f,\n    0xdc21a1171d42645d,0x76707543f4fa1f73,\n    0x899504ae72497eba,0x6a06494a791c53a8,\n    0xabfa45da0edbde69,0x487db9d17636892,\n    0xd6f8d7509292d603,0x45a9d2845d3c42b6,\n    0x865b86925b9bc5c2,0xb8a2392ba45a9b2,\n    0xa7f26836f282b732,0x8e6cac7768d7141e,\n    0xd1ef0244af2364ff,0x3207d795430cd926,\n    0x8335616aed761f1f,0x7f44e6bd49e807b8,\n    0xa402b9c5a8d3a6e7,0x5f16206c9c6209a6,\n    0xcd036837130890a1,0x36dba887c37a8c0f,\n    0x802221226be55a64,0xc2494954da2c9789,\n    0xa02aa96b06deb0fd,0xf2db9baa10b7bd6c,\n    0xc83553c5c8965d3d,0x6f92829494e5acc7,\n    0xfa42a8b73abbf48c,0xcb772339ba1f17f9,\n    0x9c69a97284b578d7,0xff2a760414536efb,\n    0xc38413cf25e2d70d,0xfef5138519684aba,\n    0xf46518c2ef5b8cd1,0x7eb258665fc25d69,\n    0x98bf2f79d5993802,0xef2f773ffbd97a61,\n    0xbeeefb584aff8603,0xaafb550ffacfd8fa,\n    0xeeaaba2e5dbf6784,0x95ba2a53f983cf38,\n    0x952ab45cfa97a0b2,0xdd945a747bf26183,\n    0xba756174393d88df,0x94f971119aeef9e4,\n    0xe912b9d1478ceb17,0x7a37cd5601aab85d,\n    0x91abb422ccb812ee,0xac62e055c10ab33a,\n    0xb616a12b7fe617aa,0x577b986b314d6009,\n    0xe39c49765fdf9d94,0xed5a7e85fda0b80b,\n    0x8e41ade9fbebc27d,0x14588f13be847307,\n    0xb1d219647ae6b31c,0x596eb2d8ae258fc8,\n    0xde469fbd99a05fe3,0x6fca5f8ed9aef3bb,\n    0x8aec23d680043bee,0x25de7bb9480d5854,\n    0xada72ccc20054ae9,0xaf561aa79a10ae6a,\n    0xd910f7ff28069da4,0x1b2ba1518094da04,\n    0x87aa9aff79042286,0x90fb44d2f05d0842,\n    0xa99541bf57452b28,0x353a1607ac744a53,\n    0xd3fa922f2d1675f2,0x42889b8997915ce8,\n    0x847c9b5d7c2e09b7,0x69956135febada11,\n    0xa59bc234db398c25,0x43fab9837e699095,\n    0xcf02b2c21207ef2e,0x94f967e45e03f4bb,\n    0x8161afb94b44f57d,0x1d1be0eebac278f5,\n    0xa1ba1ba79e1632dc,0x6462d92a69731732,\n    0xca28a291859bbf93,0x7d7b8f7503cfdcfe,\n    0xfcb2cb35e702af78,0x5cda735244c3d43e,\n    0x9defbf01b061adab,0x3a0888136afa64a7,\n    0xc56baec21c7a1916,0x88aaa1845b8fdd0,\n    0xf6c69a72a3989f5b,0x8aad549e57273d45,\n    0x9a3c2087a63f6399,0x36ac54e2f678864b,\n    0xc0cb28a98fcf3c7f,0x84576a1bb416a7dd,\n    0xf0fdf2d3f3c30b9f,0x656d44a2a11c51d5,\n    0x969eb7c47859e743,0x9f644ae5a4b1b325,\n    0xbc4665b596706114,0x873d5d9f0dde1fee,\n    0xeb57ff22fc0c7959,0xa90cb506d155a7ea,\n    0x9316ff75dd87cbd8,0x9a7f12442d588f2,\n    0xb7dcbf5354e9bece,0xc11ed6d538aeb2f,\n    0xe5d3ef282a242e81,0x8f1668c8a86da5fa,\n    0x8fa475791a569d10,0xf96e017d694487bc,\n    0xb38d92d760ec4455,0x37c981dcc395a9ac,\n    0xe070f78d3927556a,0x85bbe253f47b1417,\n    0x8c469ab843b89562,0x93956d7478ccec8e,\n    0xaf58416654a6babb,0x387ac8d1970027b2,\n    0xdb2e51bfe9d0696a,0x6997b05fcc0319e,\n    0x88fcf317f22241e2,0x441fece3bdf81f03,\n    0xab3c2fddeeaad25a,0xd527e81cad7626c3,\n    0xd60b3bd56a5586f1,0x8a71e223d8d3b074,\n    0x85c7056562757456,0xf6872d5667844e49,\n    0xa738c6bebb12d16c,0xb428f8ac016561db,\n    0xd106f86e69d785c7,0xe13336d701beba52,\n    0x82a45b450226b39c,0xecc0024661173473,\n    0xa34d721642b06084,0x27f002d7f95d0190,\n    0xcc20ce9bd35c78a5,0x31ec038df7b441f4,\n    0xff290242c83396ce,0x7e67047175a15271,\n    0x9f79a169bd203e41,0xf0062c6e984d386,\n    0xc75809c42c684dd1,0x52c07b78a3e60868,\n    0xf92e0c3537826145,0xa7709a56ccdf8a82,\n    0x9bbcc7a142b17ccb,0x88a66076400bb691,\n    0xc2abf989935ddbfe,0x6acff893d00ea435,\n    0xf356f7ebf83552fe,0x583f6b8c4124d43,\n    0x98165af37b2153de,0xc3727a337a8b704a,\n    0xbe1bf1b059e9a8d6,0x744f18c0592e4c5c,\n    0xeda2ee1c7064130c,0x1162def06f79df73,\n    0x9485d4d1c63e8be7,0x8addcb5645ac2ba8,\n    0xb9a74a0637ce2ee1,0x6d953e2bd7173692,\n    0xe8111c87c5c1ba99,0xc8fa8db6ccdd0437,\n    0x910ab1d4db9914a0,0x1d9c9892400a22a2,\n    0xb54d5e4a127f59c8,0x2503beb6d00cab4b,\n    0xe2a0b5dc971f303a,0x2e44ae64840fd61d,\n    0x8da471a9de737e24,0x5ceaecfed289e5d2,\n    0xb10d8e1456105dad,0x7425a83e872c5f47,\n    0xdd50f1996b947518,0xd12f124e28f77719,\n    0x8a5296ffe33cc92f,0x82bd6b70d99aaa6f,\n    0xace73cbfdc0bfb7b,0x636cc64d1001550b,\n    0xd8210befd30efa5a,0x3c47f7e05401aa4e,\n    0x8714a775e3e95c78,0x65acfaec34810a71,\n    0xa8d9d1535ce3b396,0x7f1839a741a14d0d,\n    0xd31045a8341ca07c,0x1ede48111209a050,\n    0x83ea2b892091e44d,0x934aed0aab460432,\n    0xa4e4b66b68b65d60,0xf81da84d5617853f,\n    0xce1de40642e3f4b9,0x36251260ab9d668e,\n    0x80d2ae83e9ce78f3,0xc1d72b7c6b426019,\n    0xa1075a24e4421730,0xb24cf65b8612f81f,\n    0xc94930ae1d529cfc,0xdee033f26797b627,\n    0xfb9b7cd9a4a7443c,0x169840ef017da3b1,\n    0x9d412e0806e88aa5,0x8e1f289560ee864e,\n    0xc491798a08a2ad4e,0xf1a6f2bab92a27e2,\n    0xf5b5d7ec8acb58a2,0xae10af696774b1db,\n    0x9991a6f3d6bf1765,0xacca6da1e0a8ef29,\n    0xbff610b0cc6edd3f,0x17fd090a58d32af3,\n    0xeff394dcff8a948e,0xddfc4b4cef07f5b0,\n    0x95f83d0a1fb69cd9,0x4abdaf101564f98e,\n    0xbb764c4ca7a4440f,0x9d6d1ad41abe37f1,\n    0xea53df5fd18d5513,0x84c86189216dc5ed,\n    0x92746b9be2f8552c,0x32fd3cf5b4e49bb4,\n    0xb7118682dbb66a77,0x3fbc8c33221dc2a1,\n    0xe4d5e82392a40515,0xfabaf3feaa5334a,\n    0x8f05b1163ba6832d,0x29cb4d87f2a7400e,\n    0xb2c71d5bca9023f8,0x743e20e9ef511012,\n    0xdf78e4b2bd342cf6,0x914da9246b255416,\n    0x8bab8eefb6409c1a,0x1ad089b6c2f7548e,\n    0xae9672aba3d0c320,0xa184ac2473b529b1,\n    0xda3c0f568cc4f3e8,0xc9e5d72d90a2741e,\n    0x8865899617fb1871,0x7e2fa67c7a658892,\n    0xaa7eebfb9df9de8d,0xddbb901b98feeab7,\n    0xd51ea6fa85785631,0x552a74227f3ea565,\n    0x8533285c936b35de,0xd53a88958f87275f,\n    0xa67ff273b8460356,0x8a892abaf368f137,\n    0xd01fef10a657842c,0x2d2b7569b0432d85,\n    0x8213f56a67f6b29b,0x9c3b29620e29fc73,\n    0xa298f2c501f45f42,0x8349f3ba91b47b8f,\n    0xcb3f2f7642717713,0x241c70a936219a73,\n    0xfe0efb53d30dd4d7,0xed238cd383aa0110,\n    0x9ec95d1463e8a506,0xf4363804324a40aa,\n    0xc67bb4597ce2ce48,0xb143c6053edcd0d5,\n    0xf81aa16fdc1b81da,0xdd94b7868e94050a,\n    0x9b10a4e5e9913128,0xca7cf2b4191c8326,\n    0xc1d4ce1f63f57d72,0xfd1c2f611f63a3f0,\n    0xf24a01a73cf2dccf,0xbc633b39673c8cec,\n    0x976e41088617ca01,0xd5be0503e085d813,\n    0xbd49d14aa79dbc82,0x4b2d8644d8a74e18,\n    0xec9c459d51852ba2,0xddf8e7d60ed1219e,\n    0x93e1ab8252f33b45,0xcabb90e5c942b503,\n    0xb8da1662e7b00a17,0x3d6a751f3b936243,\n    0xe7109bfba19c0c9d,0xcc512670a783ad4,\n    0x906a617d450187e2,0x27fb2b80668b24c5,\n    0xb484f9dc9641e9da,0xb1f9f660802dedf6,\n    0xe1a63853bbd26451,0x5e7873f8a0396973,\n    0x8d07e33455637eb2,0xdb0b487b6423e1e8,\n    0xb049dc016abc5e5f,0x91ce1a9a3d2cda62,\n    0xdc5c5301c56b75f7,0x7641a140cc7810fb,\n    0x89b9b3e11b6329ba,0xa9e904c87fcb0a9d,\n    0xac2820d9623bf429,0x546345fa9fbdcd44,\n    0xd732290fbacaf133,0xa97c177947ad4095,\n    0x867f59a9d4bed6c0,0x49ed8eabcccc485d,\n    0xa81f301449ee8c70,0x5c68f256bfff5a74,\n    0xd226fc195c6a2f8c,0x73832eec6fff3111,\n    0x83585d8fd9c25db7,0xc831fd53c5ff7eab,\n    0xa42e74f3d032f525,0xba3e7ca8b77f5e55,\n    0xcd3a1230c43fb26f,0x28ce1bd2e55f35eb,\n    0x80444b5e7aa7cf85,0x7980d163cf5b81b3,\n    0xa0555e361951c366,0xd7e105bcc332621f,\n    0xc86ab5c39fa63440,0x8dd9472bf3fefaa7,\n    0xfa856334878fc150,0xb14f98f6f0feb951,\n    0x9c935e00d4b9d8d2,0x6ed1bf9a569f33d3,\n    0xc3b8358109e84f07,0xa862f80ec4700c8,\n    0xf4a642e14c6262c8,0xcd27bb612758c0fa,\n    0x98e7e9cccfbd7dbd,0x8038d51cb897789c,\n    0xbf21e44003acdd2c,0xe0470a63e6bd56c3,\n    0xeeea5d5004981478,0x1858ccfce06cac74,\n    0x95527a5202df0ccb,0xf37801e0c43ebc8,\n    0xbaa718e68396cffd,0xd30560258f54e6ba,\n    0xe950df20247c83fd,0x47c6b82ef32a2069,\n    0x91d28b7416cdd27e,0x4cdc331d57fa5441,\n    0xb6472e511c81471d,0xe0133fe4adf8e952,\n    0xe3d8f9e563a198e5,0x58180fddd97723a6,\n    0x8e679c2f5e44ff8f,0x570f09eaa7ea7648,};\n};\n\ntemplate <class unused>\nconstexpr uint64_t powers_template<unused>::power_of_five_128[number_of_entries];\n\nusing powers = powers_template<>;\n\n} // namespace fast_float\n\n#endif\n\n#ifndef FASTFLOAT_DECIMAL_TO_BINARY_H\n#define FASTFLOAT_DECIMAL_TO_BINARY_H\n\n#include <cfloat>\n#include <cinttypes>\n#include <cmath>\n#include <cstdint>\n#include <cstdlib>\n#include <cstring>\n\nnamespace fast_float {\n\n// This will compute or rather approximate w * 5**q and return a pair of 64-bit words approximating\n// the result, with the \"high\" part corresponding to the most significant bits and the\n// low part corresponding to the least significant bits.\n//\ntemplate <int bit_precision>\nfastfloat_really_inline FASTFLOAT_CONSTEXPR20\nvalue128 compute_product_approximation(int64_t q, uint64_t w) {\n  const int index = 2 * int(q - powers::smallest_power_of_five);\n  // For small values of q, e.g., q in [0,27], the answer is always exact because\n  // The line value128 firstproduct = full_multiplication(w, power_of_five_128[index]);\n  // gives the exact answer.\n  value128 firstproduct = full_multiplication(w, powers::power_of_five_128[index]);\n  static_assert((bit_precision >= 0) && (bit_precision <= 64), \" precision should  be in (0,64]\");\n  constexpr uint64_t precision_mask = (bit_precision < 64) ?\n               (uint64_t(0xFFFFFFFFFFFFFFFF) >> bit_precision)\n               : uint64_t(0xFFFFFFFFFFFFFFFF);\n  if((firstproduct.high & precision_mask) == precision_mask) { // could further guard with  (lower + w < lower)\n    // regarding the second product, we only need secondproduct.high, but our expectation is that the compiler will optimize this extra work away if needed.\n    value128 secondproduct = full_multiplication(w, powers::power_of_five_128[index + 1]);\n    firstproduct.low += secondproduct.high;\n    if(secondproduct.high > firstproduct.low) {\n      firstproduct.high++;\n    }\n  }\n  return firstproduct;\n}\n\nnamespace detail {\n/**\n * For q in (0,350), we have that\n *  f = (((152170 + 65536) * q ) >> 16);\n * is equal to\n *   floor(p) + q\n * where\n *   p = log(5**q)/log(2) = q * log(5)/log(2)\n *\n * For negative values of q in (-400,0), we have that\n *  f = (((152170 + 65536) * q ) >> 16);\n * is equal to\n *   -ceil(p) + q\n * where\n *   p = log(5**-q)/log(2) = -q * log(5)/log(2)\n */\n  constexpr fastfloat_really_inline int32_t power(int32_t q)  noexcept  {\n    return (((152170 + 65536) * q) >> 16) + 63;\n  }\n} // namespace detail\n\n// create an adjusted mantissa, biased by the invalid power2\n// for significant digits already multiplied by 10 ** q.\ntemplate <typename binary>\nfastfloat_really_inline FASTFLOAT_CONSTEXPR14\nadjusted_mantissa compute_error_scaled(int64_t q, uint64_t w, int lz) noexcept  {\n  int hilz = int(w >> 63) ^ 1;\n  adjusted_mantissa answer;\n  answer.mantissa = w << hilz;\n  int bias = binary::mantissa_explicit_bits() - binary::minimum_exponent();\n  answer.power2 = int32_t(detail::power(int32_t(q)) + bias - hilz - lz - 62 + invalid_am_bias);\n  return answer;\n}\n\n// w * 10 ** q, without rounding the representation up.\n// the power2 in the exponent will be adjusted by invalid_am_bias.\ntemplate <typename binary>\nfastfloat_really_inline FASTFLOAT_CONSTEXPR20\nadjusted_mantissa compute_error(int64_t q, uint64_t w)  noexcept  {\n  int lz = leading_zeroes(w);\n  w <<= lz;\n  value128 product = compute_product_approximation<binary::mantissa_explicit_bits() + 3>(q, w);\n  return compute_error_scaled<binary>(q, product.high, lz);\n}\n\n// w * 10 ** q\n// The returned value should be a valid ieee64 number that simply need to be packed.\n// However, in some very rare cases, the computation will fail. In such cases, we\n// return an adjusted_mantissa with a negative power of 2: the caller should recompute\n// in such cases.\ntemplate <typename binary>\nfastfloat_really_inline FASTFLOAT_CONSTEXPR20\nadjusted_mantissa compute_float(int64_t q, uint64_t w)  noexcept  {\n  adjusted_mantissa answer;\n  if ((w == 0) || (q < binary::smallest_power_of_ten())) {\n    answer.power2 = 0;\n    answer.mantissa = 0;\n    // result should be zero\n    return answer;\n  }\n  if (q > binary::largest_power_of_ten()) {\n    // we want to get infinity:\n    answer.power2 = binary::infinite_power();\n    answer.mantissa = 0;\n    return answer;\n  }\n  // At this point in time q is in [powers::smallest_power_of_five, powers::largest_power_of_five].\n\n  // We want the most significant bit of i to be 1. Shift if needed.\n  int lz = leading_zeroes(w);\n  w <<= lz;\n\n  // The required precision is binary::mantissa_explicit_bits() + 3 because\n  // 1. We need the implicit bit\n  // 2. We need an extra bit for rounding purposes\n  // 3. We might lose a bit due to the \"upperbit\" routine (result too small, requiring a shift)\n\n  value128 product = compute_product_approximation<binary::mantissa_explicit_bits() + 3>(q, w);\n  // The computed 'product' is always sufficient.\n  // Mathematical proof:\n  // Noble Mushtak and Daniel Lemire, Fast Number Parsing Without Fallback (to appear)\n  // See script/mushtak_lemire.py\n\n  // The \"compute_product_approximation\" function can be slightly slower than a branchless approach:\n  // value128 product = compute_product(q, w);\n  // but in practice, we can win big with the compute_product_approximation if its additional branch\n  // is easily predicted. Which is best is data specific.\n  int upperbit = int(product.high >> 63);\n  int shift = upperbit + 64 - binary::mantissa_explicit_bits() - 3;\n\n  answer.mantissa = product.high >> shift;\n\n  answer.power2 = int32_t(detail::power(int32_t(q)) + upperbit - lz - binary::minimum_exponent());\n  if (answer.power2 <= 0) { // we have a subnormal?\n    // Here have that answer.power2 <= 0 so -answer.power2 >= 0\n    if(-answer.power2 + 1 >= 64) { // if we have more than 64 bits below the minimum exponent, you have a zero for sure.\n      answer.power2 = 0;\n      answer.mantissa = 0;\n      // result should be zero\n      return answer;\n    }\n    // next line is safe because -answer.power2 + 1 < 64\n    answer.mantissa >>= -answer.power2 + 1;\n    // Thankfully, we can't have both \"round-to-even\" and subnormals because\n    // \"round-to-even\" only occurs for powers close to 0.\n    answer.mantissa += (answer.mantissa & 1); // round up\n    answer.mantissa >>= 1;\n    // There is a weird scenario where we don't have a subnormal but just.\n    // Suppose we start with 2.2250738585072013e-308, we end up\n    // with 0x3fffffffffffff x 2^-1023-53 which is technically subnormal\n    // whereas 0x40000000000000 x 2^-1023-53  is normal. Now, we need to round\n    // up 0x3fffffffffffff x 2^-1023-53  and once we do, we are no longer\n    // subnormal, but we can only know this after rounding.\n    // So we only declare a subnormal if we are smaller than the threshold.\n    answer.power2 = (answer.mantissa < (uint64_t(1) << binary::mantissa_explicit_bits())) ? 0 : 1;\n    return answer;\n  }\n\n  // usually, we round *up*, but if we fall right in between and and we have an\n  // even basis, we need to round down\n  // We are only concerned with the cases where 5**q fits in single 64-bit word.\n  if ((product.low <= 1) &&  (q >= binary::min_exponent_round_to_even()) && (q <= binary::max_exponent_round_to_even()) &&\n      ((answer.mantissa & 3) == 1) ) { // we may fall between two floats!\n    // To be in-between two floats we need that in doing\n    //   answer.mantissa = product.high >> (upperbit + 64 - binary::mantissa_explicit_bits() - 3);\n    // ... we dropped out only zeroes. But if this happened, then we can go back!!!\n    if((answer.mantissa  << shift) ==  product.high) {\n      answer.mantissa &= ~uint64_t(1);          // flip it so that we do not round up\n    }\n  }\n\n  answer.mantissa += (answer.mantissa & 1); // round up\n  answer.mantissa >>= 1;\n  if (answer.mantissa >= (uint64_t(2) << binary::mantissa_explicit_bits())) {\n    answer.mantissa = (uint64_t(1) << binary::mantissa_explicit_bits());\n    answer.power2++; // undo previous addition\n  }\n\n  answer.mantissa &= ~(uint64_t(1) << binary::mantissa_explicit_bits());\n  if (answer.power2 >= binary::infinite_power()) { // infinity\n    answer.power2 = binary::infinite_power();\n    answer.mantissa = 0;\n  }\n  return answer;\n}\n\n} // namespace fast_float\n\n#endif\n\n#ifndef FASTFLOAT_BIGINT_H\n#define FASTFLOAT_BIGINT_H\n\n#include <algorithm>\n#include <cstdint>\n#include <climits>\n#include <cstring>\n\n\nnamespace fast_float {\n\n// the limb width: we want efficient multiplication of double the bits in\n// limb, or for 64-bit limbs, at least 64-bit multiplication where we can\n// extract the high and low parts efficiently. this is every 64-bit\n// architecture except for sparc, which emulates 128-bit multiplication.\n// we might have platforms where `CHAR_BIT` is not 8, so let's avoid\n// doing `8 * sizeof(limb)`.\n#if defined(FASTFLOAT_64BIT) && !defined(__sparc)\n#define FASTFLOAT_64BIT_LIMB 1\ntypedef uint64_t limb;\nconstexpr size_t limb_bits = 64;\n#else\n#define FASTFLOAT_32BIT_LIMB\ntypedef uint32_t limb;\nconstexpr size_t limb_bits = 32;\n#endif\n\ntypedef span<limb> limb_span;\n\n// number of bits in a bigint. this needs to be at least the number\n// of bits required to store the largest bigint, which is\n// `log2(10**(digits + max_exp))`, or `log2(10**(767 + 342))`, or\n// ~3600 bits, so we round to 4000.\nconstexpr size_t bigint_bits = 4000;\nconstexpr size_t bigint_limbs = bigint_bits / limb_bits;\n\n// vector-like type that is allocated on the stack. the entire\n// buffer is pre-allocated, and only the length changes.\ntemplate <uint16_t size>\nstruct stackvec {\n  limb data[size];\n  // we never need more than 150 limbs\n  uint16_t length{0};\n\n  stackvec() = default;\n  stackvec(const stackvec &) = delete;\n  stackvec &operator=(const stackvec &) = delete;\n  stackvec(stackvec &&) = delete;\n  stackvec &operator=(stackvec &&other) = delete;\n\n  // create stack vector from existing limb span.\n  FASTFLOAT_CONSTEXPR20 stackvec(limb_span s) {\n    FASTFLOAT_ASSERT(try_extend(s));\n  }\n\n  FASTFLOAT_CONSTEXPR14 limb& operator[](size_t index) noexcept {\n    FASTFLOAT_DEBUG_ASSERT(index < length);\n    return data[index];\n  }\n  FASTFLOAT_CONSTEXPR14 const limb& operator[](size_t index) const noexcept {\n    FASTFLOAT_DEBUG_ASSERT(index < length);\n    return data[index];\n  }\n  // index from the end of the container\n  FASTFLOAT_CONSTEXPR14 const limb& rindex(size_t index) const noexcept {\n    FASTFLOAT_DEBUG_ASSERT(index < length);\n    size_t rindex = length - index - 1;\n    return data[rindex];\n  }\n\n  // set the length, without bounds checking.\n  FASTFLOAT_CONSTEXPR14 void set_len(size_t len) noexcept {\n    length = uint16_t(len);\n  }\n  constexpr size_t len() const noexcept {\n    return length;\n  }\n  constexpr bool is_empty() const noexcept {\n    return length == 0;\n  }\n  constexpr size_t capacity() const noexcept {\n    return size;\n  }\n  // append item to vector, without bounds checking\n  FASTFLOAT_CONSTEXPR14 void push_unchecked(limb value) noexcept {\n    data[length] = value;\n    length++;\n  }\n  // append item to vector, returning if item was added\n  FASTFLOAT_CONSTEXPR14 bool try_push(limb value) noexcept {\n    if (len() < capacity()) {\n      push_unchecked(value);\n      return true;\n    } else {\n      return false;\n    }\n  }\n  // add items to the vector, from a span, without bounds checking\n  FASTFLOAT_CONSTEXPR20 void extend_unchecked(limb_span s) noexcept {\n    limb* ptr = data + length;\n    std::copy_n(s.ptr, s.len(), ptr);\n    set_len(len() + s.len());\n  }\n  // try to add items to the vector, returning if items were added\n  FASTFLOAT_CONSTEXPR20 bool try_extend(limb_span s) noexcept {\n    if (len() + s.len() <= capacity()) {\n      extend_unchecked(s);\n      return true;\n    } else {\n      return false;\n    }\n  }\n  // resize the vector, without bounds checking\n  // if the new size is longer than the vector, assign value to each\n  // appended item.\n  FASTFLOAT_CONSTEXPR20\n  void resize_unchecked(size_t new_len, limb value) noexcept {\n    if (new_len > len()) {\n      size_t count = new_len - len();\n      limb* first = data + len();\n      limb* last = first + count;\n      ::std::fill(first, last, value);\n      set_len(new_len);\n    } else {\n      set_len(new_len);\n    }\n  }\n  // try to resize the vector, returning if the vector was resized.\n  FASTFLOAT_CONSTEXPR20 bool try_resize(size_t new_len, limb value) noexcept {\n    if (new_len > capacity()) {\n      return false;\n    } else {\n      resize_unchecked(new_len, value);\n      return true;\n    }\n  }\n  // check if any limbs are non-zero after the given index.\n  // this needs to be done in reverse order, since the index\n  // is relative to the most significant limbs.\n  FASTFLOAT_CONSTEXPR14 bool nonzero(size_t index) const noexcept {\n    while (index < len()) {\n      if (rindex(index) != 0) {\n        return true;\n      }\n      index++;\n    }\n    return false;\n  }\n  // normalize the big integer, so most-significant zero limbs are removed.\n  FASTFLOAT_CONSTEXPR14 void normalize() noexcept {\n    while (len() > 0 && rindex(0) == 0) {\n      length--;\n    }\n  }\n};\n\nfastfloat_really_inline FASTFLOAT_CONSTEXPR14\nuint64_t empty_hi64(bool& truncated) noexcept {\n  truncated = false;\n  return 0;\n}\n\nfastfloat_really_inline FASTFLOAT_CONSTEXPR20\nuint64_t uint64_hi64(uint64_t r0, bool& truncated) noexcept {\n  truncated = false;\n  int shl = leading_zeroes(r0);\n  return r0 << shl;\n}\n\nfastfloat_really_inline FASTFLOAT_CONSTEXPR20\nuint64_t uint64_hi64(uint64_t r0, uint64_t r1, bool& truncated) noexcept {\n  int shl = leading_zeroes(r0);\n  if (shl == 0) {\n    truncated = r1 != 0;\n    return r0;\n  } else {\n    int shr = 64 - shl;\n    truncated = (r1 << shl) != 0;\n    return (r0 << shl) | (r1 >> shr);\n  }\n}\n\nfastfloat_really_inline FASTFLOAT_CONSTEXPR20\nuint64_t uint32_hi64(uint32_t r0, bool& truncated) noexcept {\n  return uint64_hi64(r0, truncated);\n}\n\nfastfloat_really_inline FASTFLOAT_CONSTEXPR20\nuint64_t uint32_hi64(uint32_t r0, uint32_t r1, bool& truncated) noexcept {\n  uint64_t x0 = r0;\n  uint64_t x1 = r1;\n  return uint64_hi64((x0 << 32) | x1, truncated);\n}\n\nfastfloat_really_inline FASTFLOAT_CONSTEXPR20\nuint64_t uint32_hi64(uint32_t r0, uint32_t r1, uint32_t r2, bool& truncated) noexcept {\n  uint64_t x0 = r0;\n  uint64_t x1 = r1;\n  uint64_t x2 = r2;\n  return uint64_hi64(x0, (x1 << 32) | x2, truncated);\n}\n\n// add two small integers, checking for overflow.\n// we want an efficient operation. for msvc, where\n// we don't have built-in intrinsics, this is still\n// pretty fast.\nfastfloat_really_inline FASTFLOAT_CONSTEXPR20\nlimb scalar_add(limb x, limb y, bool& overflow) noexcept {\n  limb z;\n// gcc and clang\n#if defined(__has_builtin)\n  #if __has_builtin(__builtin_add_overflow)\n    if (!cpp20_and_in_constexpr()) {\n      overflow = __builtin_add_overflow(x, y, &z);\n      return z;\n    }\n  #endif\n#endif\n\n  // generic, this still optimizes correctly on MSVC.\n  z = x + y;\n  overflow = z < x;\n  return z;\n}\n\n// multiply two small integers, getting both the high and low bits.\nfastfloat_really_inline FASTFLOAT_CONSTEXPR20\nlimb scalar_mul(limb x, limb y, limb& carry) noexcept {\n#ifdef FASTFLOAT_64BIT_LIMB\n  #if defined(__SIZEOF_INT128__)\n  // GCC and clang both define it as an extension.\n  __uint128_t z = __uint128_t(x) * __uint128_t(y) + __uint128_t(carry);\n  carry = limb(z >> limb_bits);\n  return limb(z);\n  #else\n  // fallback, no native 128-bit integer multiplication with carry.\n  // on msvc, this optimizes identically, somehow.\n  value128 z = full_multiplication(x, y);\n  bool overflow;\n  z.low = scalar_add(z.low, carry, overflow);\n  z.high += uint64_t(overflow);  // cannot overflow\n  carry = z.high;\n  return z.low;\n  #endif\n#else\n  uint64_t z = uint64_t(x) * uint64_t(y) + uint64_t(carry);\n  carry = limb(z >> limb_bits);\n  return limb(z);\n#endif\n}\n\n// add scalar value to bigint starting from offset.\n// used in grade school multiplication\ntemplate <uint16_t size>\ninline FASTFLOAT_CONSTEXPR20\nbool small_add_from(stackvec<size>& vec, limb y, size_t start) noexcept {\n  size_t index = start;\n  limb carry = y;\n  bool overflow;\n  while (carry != 0 && index < vec.len()) {\n    vec[index] = scalar_add(vec[index], carry, overflow);\n    carry = limb(overflow);\n    index += 1;\n  }\n  if (carry != 0) {\n    FASTFLOAT_TRY(vec.try_push(carry));\n  }\n  return true;\n}\n\n// add scalar value to bigint.\ntemplate <uint16_t size>\nfastfloat_really_inline FASTFLOAT_CONSTEXPR20\nbool small_add(stackvec<size>& vec, limb y) noexcept {\n  return small_add_from(vec, y, 0);\n}\n\n// multiply bigint by scalar value.\ntemplate <uint16_t size>\ninline FASTFLOAT_CONSTEXPR20\nbool small_mul(stackvec<size>& vec, limb y) noexcept {\n  limb carry = 0;\n  for (size_t index = 0; index < vec.len(); index++) {\n    vec[index] = scalar_mul(vec[index], y, carry);\n  }\n  if (carry != 0) {\n    FASTFLOAT_TRY(vec.try_push(carry));\n  }\n  return true;\n}\n\n// add bigint to bigint starting from index.\n// used in grade school multiplication\ntemplate <uint16_t size>\nFASTFLOAT_CONSTEXPR20\nbool large_add_from(stackvec<size>& x, limb_span y, size_t start) noexcept {\n  // the effective x buffer is from `xstart..x.len()`, so exit early\n  // if we can't get that current range.\n  if (x.len() < start || y.len() > x.len() - start) {\n      FASTFLOAT_TRY(x.try_resize(y.len() + start, 0));\n  }\n\n  bool carry = false;\n  for (size_t index = 0; index < y.len(); index++) {\n    limb xi = x[index + start];\n    limb yi = y[index];\n    bool c1 = false;\n    bool c2 = false;\n    xi = scalar_add(xi, yi, c1);\n    if (carry) {\n      xi = scalar_add(xi, 1, c2);\n    }\n    x[index + start] = xi;\n    carry = c1 | c2;\n  }\n\n  // handle overflow\n  if (carry) {\n    FASTFLOAT_TRY(small_add_from(x, 1, y.len() + start));\n  }\n  return true;\n}\n\n// add bigint to bigint.\ntemplate <uint16_t size>\nfastfloat_really_inline FASTFLOAT_CONSTEXPR20\nbool large_add_from(stackvec<size>& x, limb_span y) noexcept {\n  return large_add_from(x, y, 0);\n}\n\n// grade-school multiplication algorithm\ntemplate <uint16_t size>\nFASTFLOAT_CONSTEXPR20\nbool long_mul(stackvec<size>& x, limb_span y) noexcept {\n  limb_span xs = limb_span(x.data, x.len());\n  stackvec<size> z(xs);\n  limb_span zs = limb_span(z.data, z.len());\n\n  if (y.len() != 0) {\n    limb y0 = y[0];\n    FASTFLOAT_TRY(small_mul(x, y0));\n    for (size_t index = 1; index < y.len(); index++) {\n      limb yi = y[index];\n      stackvec<size> zi;\n      if (yi != 0) {\n        // re-use the same buffer throughout\n        zi.set_len(0);\n        FASTFLOAT_TRY(zi.try_extend(zs));\n        FASTFLOAT_TRY(small_mul(zi, yi));\n        limb_span zis = limb_span(zi.data, zi.len());\n        FASTFLOAT_TRY(large_add_from(x, zis, index));\n      }\n    }\n  }\n\n  x.normalize();\n  return true;\n}\n\n// grade-school multiplication algorithm\ntemplate <uint16_t size>\nFASTFLOAT_CONSTEXPR20\nbool large_mul(stackvec<size>& x, limb_span y) noexcept {\n  if (y.len() == 1) {\n    FASTFLOAT_TRY(small_mul(x, y[0]));\n  } else {\n    FASTFLOAT_TRY(long_mul(x, y));\n  }\n  return true;\n}\n\ntemplate <typename = void>\nstruct pow5_tables {\n  static constexpr uint32_t large_step = 135;\n  static constexpr uint64_t small_power_of_5[] = {\n    1UL, 5UL, 25UL, 125UL, 625UL, 3125UL, 15625UL, 78125UL, 390625UL,\n    1953125UL, 9765625UL, 48828125UL, 244140625UL, 1220703125UL,\n    6103515625UL, 30517578125UL, 152587890625UL, 762939453125UL,\n    3814697265625UL, 19073486328125UL, 95367431640625UL, 476837158203125UL,\n    2384185791015625UL, 11920928955078125UL, 59604644775390625UL,\n    298023223876953125UL, 1490116119384765625UL, 7450580596923828125UL,\n  };\n#ifdef FASTFLOAT_64BIT_LIMB\n  constexpr static limb large_power_of_5[] = {\n    1414648277510068013UL, 9180637584431281687UL, 4539964771860779200UL,\n    10482974169319127550UL, 198276706040285095UL};\n#else\n  constexpr static limb large_power_of_5[] = {\n    4279965485U, 329373468U, 4020270615U, 2137533757U, 4287402176U,\n    1057042919U, 1071430142U, 2440757623U, 381945767U, 46164893U};\n#endif\n};\n\ntemplate <typename T>\nconstexpr uint32_t pow5_tables<T>::large_step;\n\ntemplate <typename T>\nconstexpr uint64_t pow5_tables<T>::small_power_of_5[];\n\ntemplate <typename T>\nconstexpr limb pow5_tables<T>::large_power_of_5[];\n\n// big integer type. implements a small subset of big integer\n// arithmetic, using simple algorithms since asymptotically\n// faster algorithms are slower for a small number of limbs.\n// all operations assume the big-integer is normalized.\nstruct bigint : pow5_tables<> {\n  // storage of the limbs, in little-endian order.\n  stackvec<bigint_limbs> vec;\n\n  FASTFLOAT_CONSTEXPR20 bigint(): vec() {}\n  bigint(const bigint &) = delete;\n  bigint &operator=(const bigint &) = delete;\n  bigint(bigint &&) = delete;\n  bigint &operator=(bigint &&other) = delete;\n\n  FASTFLOAT_CONSTEXPR20 bigint(uint64_t value): vec() {\n#ifdef FASTFLOAT_64BIT_LIMB\n    vec.push_unchecked(value);\n#else\n    vec.push_unchecked(uint32_t(value));\n    vec.push_unchecked(uint32_t(value >> 32));\n#endif\n    vec.normalize();\n  }\n\n  // get the high 64 bits from the vector, and if bits were truncated.\n  // this is to get the significant digits for the float.\n  FASTFLOAT_CONSTEXPR20 uint64_t hi64(bool& truncated) const noexcept {\n#ifdef FASTFLOAT_64BIT_LIMB\n    if (vec.len() == 0) {\n      return empty_hi64(truncated);\n    } else if (vec.len() == 1) {\n      return uint64_hi64(vec.rindex(0), truncated);\n    } else {\n      uint64_t result = uint64_hi64(vec.rindex(0), vec.rindex(1), truncated);\n      truncated |= vec.nonzero(2);\n      return result;\n    }\n#else\n    if (vec.len() == 0) {\n      return empty_hi64(truncated);\n    } else if (vec.len() == 1) {\n      return uint32_hi64(vec.rindex(0), truncated);\n    } else if (vec.len() == 2) {\n      return uint32_hi64(vec.rindex(0), vec.rindex(1), truncated);\n    } else {\n      uint64_t result = uint32_hi64(vec.rindex(0), vec.rindex(1), vec.rindex(2), truncated);\n      truncated |= vec.nonzero(3);\n      return result;\n    }\n#endif\n  }\n\n  // compare two big integers, returning the large value.\n  // assumes both are normalized. if the return value is\n  // negative, other is larger, if the return value is\n  // positive, this is larger, otherwise they are equal.\n  // the limbs are stored in little-endian order, so we\n  // must compare the limbs in ever order.\n  FASTFLOAT_CONSTEXPR20 int compare(const bigint& other) const noexcept {\n    if (vec.len() > other.vec.len()) {\n      return 1;\n    } else if (vec.len() < other.vec.len()) {\n      return -1;\n    } else {\n      for (size_t index = vec.len(); index > 0; index--) {\n        limb xi = vec[index - 1];\n        limb yi = other.vec[index - 1];\n        if (xi > yi) {\n          return 1;\n        } else if (xi < yi) {\n          return -1;\n        }\n      }\n      return 0;\n    }\n  }\n\n  // shift left each limb n bits, carrying over to the new limb\n  // returns true if we were able to shift all the digits.\n  FASTFLOAT_CONSTEXPR20 bool shl_bits(size_t n) noexcept {\n    // Internally, for each item, we shift left by n, and add the previous\n    // right shifted limb-bits.\n    // For example, we transform (for u8) shifted left 2, to:\n    //      b10100100 b01000010\n    //      b10 b10010001 b00001000\n    FASTFLOAT_DEBUG_ASSERT(n != 0);\n    FASTFLOAT_DEBUG_ASSERT(n < sizeof(limb) * 8);\n\n    size_t shl = n;\n    size_t shr = limb_bits - shl;\n    limb prev = 0;\n    for (size_t index = 0; index < vec.len(); index++) {\n      limb xi = vec[index];\n      vec[index] = (xi << shl) | (prev >> shr);\n      prev = xi;\n    }\n\n    limb carry = prev >> shr;\n    if (carry != 0) {\n      return vec.try_push(carry);\n    }\n    return true;\n  }\n\n  // move the limbs left by `n` limbs.\n  FASTFLOAT_CONSTEXPR20 bool shl_limbs(size_t n) noexcept {\n    FASTFLOAT_DEBUG_ASSERT(n != 0);\n    if (n + vec.len() > vec.capacity()) {\n      return false;\n    } else if (!vec.is_empty()) {\n      // move limbs\n      limb* dst = vec.data + n;\n      const limb* src = vec.data;\n      std::copy_backward(src, src + vec.len(), dst + vec.len());\n      // fill in empty limbs\n      limb* first = vec.data;\n      limb* last = first + n;\n      ::std::fill(first, last, 0);\n      vec.set_len(n + vec.len());\n      return true;\n    } else {\n      return true;\n    }\n  }\n\n  // move the limbs left by `n` bits.\n  FASTFLOAT_CONSTEXPR20 bool shl(size_t n) noexcept {\n    size_t rem = n % limb_bits;\n    size_t div = n / limb_bits;\n    if (rem != 0) {\n      FASTFLOAT_TRY(shl_bits(rem));\n    }\n    if (div != 0) {\n      FASTFLOAT_TRY(shl_limbs(div));\n    }\n    return true;\n  }\n\n  // get the number of leading zeros in the bigint.\n  FASTFLOAT_CONSTEXPR20 int ctlz() const noexcept {\n    if (vec.is_empty()) {\n      return 0;\n    } else {\n#ifdef FASTFLOAT_64BIT_LIMB\n      return leading_zeroes(vec.rindex(0));\n#else\n      // no use defining a specialized leading_zeroes for a 32-bit type.\n      uint64_t r0 = vec.rindex(0);\n      return leading_zeroes(r0 << 32);\n#endif\n    }\n  }\n\n  // get the number of bits in the bigint.\n  FASTFLOAT_CONSTEXPR20 int bit_length() const noexcept {\n    int lz = ctlz();\n    return int(limb_bits * vec.len()) - lz;\n  }\n\n  FASTFLOAT_CONSTEXPR20 bool mul(limb y) noexcept {\n    return small_mul(vec, y);\n  }\n\n  FASTFLOAT_CONSTEXPR20 bool add(limb y) noexcept {\n    return small_add(vec, y);\n  }\n\n  // multiply as if by 2 raised to a power.\n  FASTFLOAT_CONSTEXPR20 bool pow2(uint32_t exp) noexcept {\n    return shl(exp);\n  }\n\n  // multiply as if by 5 raised to a power.\n  FASTFLOAT_CONSTEXPR20 bool pow5(uint32_t exp) noexcept {\n    // multiply by a power of 5\n    size_t large_length = sizeof(large_power_of_5) / sizeof(limb);\n    limb_span large = limb_span(large_power_of_5, large_length);\n    while (exp >= large_step) {\n      FASTFLOAT_TRY(large_mul(vec, large));\n      exp -= large_step;\n    }\n#ifdef FASTFLOAT_64BIT_LIMB\n    uint32_t small_step = 27;\n    limb max_native = 7450580596923828125UL;\n#else\n    uint32_t small_step = 13;\n    limb max_native = 1220703125U;\n#endif\n    while (exp >= small_step) {\n      FASTFLOAT_TRY(small_mul(vec, max_native));\n      exp -= small_step;\n    }\n    if (exp != 0) {\n      // Work around clang bug https://godbolt.org/z/zedh7rrhc\n      // This is similar to https://github.com/llvm/llvm-project/issues/47746,\n      // except the workaround described there don't work here\n      FASTFLOAT_TRY(\n        small_mul(vec, limb(((void)small_power_of_5[0], small_power_of_5[exp])))\n      );\n    }\n\n    return true;\n  }\n\n  // multiply as if by 10 raised to a power.\n  FASTFLOAT_CONSTEXPR20 bool pow10(uint32_t exp) noexcept {\n    FASTFLOAT_TRY(pow5(exp));\n    return pow2(exp);\n  }\n};\n\n} // namespace fast_float\n\n#endif\n\n#ifndef FASTFLOAT_DIGIT_COMPARISON_H\n#define FASTFLOAT_DIGIT_COMPARISON_H\n\n#include <algorithm>\n#include <cstdint>\n#include <cstring>\n#include <iterator>\n\n\nnamespace fast_float {\n\n// 1e0 to 1e19\nconstexpr static uint64_t powers_of_ten_uint64[] = {\n    1UL, 10UL, 100UL, 1000UL, 10000UL, 100000UL, 1000000UL, 10000000UL, 100000000UL,\n    1000000000UL, 10000000000UL, 100000000000UL, 1000000000000UL, 10000000000000UL,\n    100000000000000UL, 1000000000000000UL, 10000000000000000UL, 100000000000000000UL,\n    1000000000000000000UL, 10000000000000000000UL};\n\n// calculate the exponent, in scientific notation, of the number.\n// this algorithm is not even close to optimized, but it has no practical\n// effect on performance: in order to have a faster algorithm, we'd need\n// to slow down performance for faster algorithms, and this is still fast.\ntemplate <typename UC>\nfastfloat_really_inline FASTFLOAT_CONSTEXPR14\nint32_t scientific_exponent(parsed_number_string_t<UC> & num) noexcept {\n  uint64_t mantissa = num.mantissa;\n  int32_t exponent = int32_t(num.exponent);\n  while (mantissa >= 10000) {\n    mantissa /= 10000;\n    exponent += 4;\n  }\n  while (mantissa >= 100) {\n    mantissa /= 100;\n    exponent += 2;\n  }\n  while (mantissa >= 10) {\n    mantissa /= 10;\n    exponent += 1;\n  }\n  return exponent;\n}\n\n// this converts a native floating-point number to an extended-precision float.\ntemplate <typename T>\nfastfloat_really_inline FASTFLOAT_CONSTEXPR20\nadjusted_mantissa to_extended(T value) noexcept {\n  using equiv_uint = typename binary_format<T>::equiv_uint;\n  constexpr equiv_uint exponent_mask = binary_format<T>::exponent_mask();\n  constexpr equiv_uint mantissa_mask = binary_format<T>::mantissa_mask();\n  constexpr equiv_uint hidden_bit_mask = binary_format<T>::hidden_bit_mask();\n\n  adjusted_mantissa am;\n  int32_t bias = binary_format<T>::mantissa_explicit_bits() - binary_format<T>::minimum_exponent();\n  equiv_uint bits;\n#if FASTFLOAT_HAS_BIT_CAST\n  bits = std::bit_cast<equiv_uint>(value);\n#else\n  ::memcpy(&bits, &value, sizeof(T));\n#endif\n  if ((bits & exponent_mask) == 0) {\n    // denormal\n    am.power2 = 1 - bias;\n    am.mantissa = bits & mantissa_mask;\n  } else {\n    // normal\n    am.power2 = int32_t((bits & exponent_mask) >> binary_format<T>::mantissa_explicit_bits());\n    am.power2 -= bias;\n    am.mantissa = (bits & mantissa_mask) | hidden_bit_mask;\n  }\n\n  return am;\n}\n\n// get the extended precision value of the halfway point between b and b+u.\n// we are given a native float that represents b, so we need to adjust it\n// halfway between b and b+u.\ntemplate <typename T>\nfastfloat_really_inline FASTFLOAT_CONSTEXPR20\nadjusted_mantissa to_extended_halfway(T value) noexcept {\n  adjusted_mantissa am = to_extended(value);\n  am.mantissa <<= 1;\n  am.mantissa += 1;\n  am.power2 -= 1;\n  return am;\n}\n\n// round an extended-precision float to the nearest machine float.\ntemplate <typename T, typename callback>\nfastfloat_really_inline FASTFLOAT_CONSTEXPR14\nvoid round(adjusted_mantissa& am, callback cb) noexcept {\n  int32_t mantissa_shift = 64 - binary_format<T>::mantissa_explicit_bits() - 1;\n  if (-am.power2 >= mantissa_shift) {\n    // have a denormal float\n    int32_t shift = -am.power2 + 1;\n    cb(am, std::min<int32_t>(shift, 64));\n    // check for round-up: if rounding-nearest carried us to the hidden bit.\n    am.power2 = (am.mantissa < (uint64_t(1) << binary_format<T>::mantissa_explicit_bits())) ? 0 : 1;\n    return;\n  }\n\n  // have a normal float, use the default shift.\n  cb(am, mantissa_shift);\n\n  // check for carry\n  if (am.mantissa >= (uint64_t(2) << binary_format<T>::mantissa_explicit_bits())) {\n    am.mantissa = (uint64_t(1) << binary_format<T>::mantissa_explicit_bits());\n    am.power2++;\n  }\n\n  // check for infinite: we could have carried to an infinite power\n  am.mantissa &= ~(uint64_t(1) << binary_format<T>::mantissa_explicit_bits());\n  if (am.power2 >= binary_format<T>::infinite_power()) {\n    am.power2 = binary_format<T>::infinite_power();\n    am.mantissa = 0;\n  }\n}\n\ntemplate <typename callback>\nfastfloat_really_inline FASTFLOAT_CONSTEXPR14\nvoid round_nearest_tie_even(adjusted_mantissa& am, int32_t shift, callback cb) noexcept {\n  const uint64_t mask\n  = (shift == 64)\n    ? UINT64_MAX\n    : (uint64_t(1) << shift) - 1;\n  const uint64_t halfway\n  = (shift == 0)\n    ? 0\n    : uint64_t(1) << (shift - 1);\n  uint64_t truncated_bits = am.mantissa & mask;\n  bool is_above = truncated_bits > halfway;\n  bool is_halfway = truncated_bits == halfway;\n\n  // shift digits into position\n  if (shift == 64) {\n    am.mantissa = 0;\n  } else {\n    am.mantissa >>= shift;\n  }\n  am.power2 += shift;\n\n  bool is_odd = (am.mantissa & 1) == 1;\n  am.mantissa += uint64_t(cb(is_odd, is_halfway, is_above));\n}\n\nfastfloat_really_inline FASTFLOAT_CONSTEXPR14\nvoid round_down(adjusted_mantissa& am, int32_t shift) noexcept {\n  if (shift == 64) {\n    am.mantissa = 0;\n  } else {\n    am.mantissa >>= shift;\n  }\n  am.power2 += shift;\n}\ntemplate <typename UC>\nfastfloat_really_inline FASTFLOAT_CONSTEXPR20\nvoid skip_zeros(UC const * & first, UC const * last) noexcept {\n  uint64_t val;\n  while (!cpp20_and_in_constexpr() && std::distance(first, last) >= int_cmp_len<UC>()) {\n    ::memcpy(&val, first, sizeof(uint64_t));\n    if (val != int_cmp_zeros<UC>()) {\n      break;\n    }\n    first += int_cmp_len<UC>();\n  }\n  while (first != last) {\n    if (*first != UC('0')) {\n      break;\n    }\n    first++;\n  }\n}\n\n// determine if any non-zero digits were truncated.\n// all characters must be valid digits.\ntemplate <typename UC>\nfastfloat_really_inline FASTFLOAT_CONSTEXPR20\nbool is_truncated(UC const * first, UC const * last) noexcept {\n  // do 8-bit optimizations, can just compare to 8 literal 0s.\n  uint64_t val;\n  while (!cpp20_and_in_constexpr() && std::distance(first, last) >= int_cmp_len<UC>()) {\n    ::memcpy(&val, first, sizeof(uint64_t));\n    if (val != int_cmp_zeros<UC>()) {\n      return true;\n    }\n    first += int_cmp_len<UC>();\n  }\n  while (first != last) {\n    if (*first != UC('0')) {\n      return true;\n    }\n    ++first;\n  }\n  return false;\n}\ntemplate <typename UC>\nfastfloat_really_inline FASTFLOAT_CONSTEXPR20\nbool is_truncated(span<const UC> s) noexcept {\n  return is_truncated(s.ptr, s.ptr + s.len());\n}\n\n\ntemplate <typename UC>\nfastfloat_really_inline FASTFLOAT_CONSTEXPR20\nvoid parse_eight_digits(const UC*& p, limb& value, size_t& counter, size_t& count) noexcept {\n  value = value * 100000000 + parse_eight_digits_unrolled(p);\n  p += 8;\n  counter += 8;\n  count += 8;\n}\n\ntemplate <typename UC>\nfastfloat_really_inline FASTFLOAT_CONSTEXPR14\nvoid parse_one_digit(UC const *& p, limb& value, size_t& counter, size_t& count) noexcept {\n  value = value * 10 + limb(*p - UC('0'));\n  p++;\n  counter++;\n  count++;\n}\n\nfastfloat_really_inline FASTFLOAT_CONSTEXPR20\nvoid add_native(bigint& big, limb power, limb value) noexcept {\n  big.mul(power);\n  big.add(value);\n}\n\nfastfloat_really_inline FASTFLOAT_CONSTEXPR20\nvoid round_up_bigint(bigint& big, size_t& count) noexcept {\n  // need to round-up the digits, but need to avoid rounding\n  // ....9999 to ...10000, which could cause a false halfway point.\n  add_native(big, 10, 1);\n  count++;\n}\n\n// parse the significant digits into a big integer\ntemplate <typename UC>\ninline FASTFLOAT_CONSTEXPR20\nvoid parse_mantissa(bigint& result, parsed_number_string_t<UC>& num, size_t max_digits, size_t& digits) noexcept {\n  // try to minimize the number of big integer and scalar multiplication.\n  // therefore, try to parse 8 digits at a time, and multiply by the largest\n  // scalar value (9 or 19 digits) for each step.\n  size_t counter = 0;\n  digits = 0;\n  limb value = 0;\n#ifdef FASTFLOAT_64BIT_LIMB\n  size_t step = 19;\n#else\n  size_t step = 9;\n#endif\n\n  // process all integer digits.\n  UC const * p = num.integer.ptr;\n  UC const * pend = p + num.integer.len();\n  skip_zeros(p, pend);\n  // process all digits, in increments of step per loop\n  while (p != pend) {\n    while ((std::distance(p, pend) >= 8) && (step - counter >= 8) && (max_digits - digits >= 8)) {\n      parse_eight_digits(p, value, counter, digits);\n    }\n    while (counter < step && p != pend && digits < max_digits) {\n      parse_one_digit(p, value, counter, digits);\n    }\n    if (digits == max_digits) {\n      // add the temporary value, then check if we've truncated any digits\n      add_native(result, limb(powers_of_ten_uint64[counter]), value);\n      bool truncated = is_truncated(p, pend);\n      if (num.fraction.ptr != nullptr) {\n        truncated |= is_truncated(num.fraction);\n      }\n      if (truncated) {\n        round_up_bigint(result, digits);\n      }\n      return;\n    } else {\n      add_native(result, limb(powers_of_ten_uint64[counter]), value);\n      counter = 0;\n      value = 0;\n    }\n  }\n\n  // add our fraction digits, if they're available.\n  if (num.fraction.ptr != nullptr) {\n    p = num.fraction.ptr;\n    pend = p + num.fraction.len();\n    if (digits == 0) {\n      skip_zeros(p, pend);\n    }\n    // process all digits, in increments of step per loop\n    while (p != pend) {\n      while ((std::distance(p, pend) >= 8) && (step - counter >= 8) && (max_digits - digits >= 8)) {\n        parse_eight_digits(p, value, counter, digits);\n      }\n      while (counter < step && p != pend && digits < max_digits) {\n        parse_one_digit(p, value, counter, digits);\n      }\n      if (digits == max_digits) {\n        // add the temporary value, then check if we've truncated any digits\n        add_native(result, limb(powers_of_ten_uint64[counter]), value);\n        bool truncated = is_truncated(p, pend);\n        if (truncated) {\n          round_up_bigint(result, digits);\n        }\n        return;\n      } else {\n        add_native(result, limb(powers_of_ten_uint64[counter]), value);\n        counter = 0;\n        value = 0;\n      }\n    }\n  }\n\n  if (counter != 0) {\n    add_native(result, limb(powers_of_ten_uint64[counter]), value);\n  }\n}\n\ntemplate <typename T>\ninline FASTFLOAT_CONSTEXPR20\nadjusted_mantissa positive_digit_comp(bigint& bigmant, int32_t exponent) noexcept {\n  FASTFLOAT_ASSERT(bigmant.pow10(uint32_t(exponent)));\n  adjusted_mantissa answer;\n  bool truncated;\n  answer.mantissa = bigmant.hi64(truncated);\n  int bias = binary_format<T>::mantissa_explicit_bits() - binary_format<T>::minimum_exponent();\n  answer.power2 = bigmant.bit_length() - 64 + bias;\n\n  round<T>(answer, [truncated](adjusted_mantissa& a, int32_t shift) {\n    round_nearest_tie_even(a, shift, [truncated](bool is_odd, bool is_halfway, bool is_above) -> bool {\n      return is_above || (is_halfway && truncated) || (is_odd && is_halfway);\n    });\n  });\n\n  return answer;\n}\n\n// the scaling here is quite simple: we have, for the real digits `m * 10^e`,\n// and for the theoretical digits `n * 2^f`. Since `e` is always negative,\n// to scale them identically, we do `n * 2^f * 5^-f`, so we now have `m * 2^e`.\n// we then need to scale by `2^(f- e)`, and then the two significant digits\n// are of the same magnitude.\ntemplate <typename T>\ninline FASTFLOAT_CONSTEXPR20\nadjusted_mantissa negative_digit_comp(bigint& bigmant, adjusted_mantissa am, int32_t exponent) noexcept {\n  bigint& real_digits = bigmant;\n  int32_t real_exp = exponent;\n\n  // get the value of `b`, rounded down, and get a bigint representation of b+h\n  adjusted_mantissa am_b = am;\n  // gcc7 buf: use a lambda to remove the noexcept qualifier bug with -Wnoexcept-type.\n  round<T>(am_b, [](adjusted_mantissa&a, int32_t shift) { round_down(a, shift); });\n  T b;\n  to_float(false, am_b, b);\n  adjusted_mantissa theor = to_extended_halfway(b);\n  bigint theor_digits(theor.mantissa);\n  int32_t theor_exp = theor.power2;\n\n  // scale real digits and theor digits to be same power.\n  int32_t pow2_exp = theor_exp - real_exp;\n  uint32_t pow5_exp = uint32_t(-real_exp);\n  if (pow5_exp != 0) {\n    FASTFLOAT_ASSERT(theor_digits.pow5(pow5_exp));\n  }\n  if (pow2_exp > 0) {\n    FASTFLOAT_ASSERT(theor_digits.pow2(uint32_t(pow2_exp)));\n  } else if (pow2_exp < 0) {\n    FASTFLOAT_ASSERT(real_digits.pow2(uint32_t(-pow2_exp)));\n  }\n\n  // compare digits, and use it to director rounding\n  int ord = real_digits.compare(theor_digits);\n  adjusted_mantissa answer = am;\n  round<T>(answer, [ord](adjusted_mantissa& a, int32_t shift) {\n    round_nearest_tie_even(a, shift, [ord](bool is_odd, bool _, bool __) -> bool {\n      (void)_;  // not needed, since we've done our comparison\n      (void)__; // not needed, since we've done our comparison\n      if (ord > 0) {\n        return true;\n      } else if (ord < 0) {\n        return false;\n      } else {\n        return is_odd;\n      }\n    });\n  });\n\n  return answer;\n}\n\n// parse the significant digits as a big integer to unambiguously round the\n// the significant digits. here, we are trying to determine how to round\n// an extended float representation close to `b+h`, halfway between `b`\n// (the float rounded-down) and `b+u`, the next positive float. this\n// algorithm is always correct, and uses one of two approaches. when\n// the exponent is positive relative to the significant digits (such as\n// 1234), we create a big-integer representation, get the high 64-bits,\n// determine if any lower bits are truncated, and use that to direct\n// rounding. in case of a negative exponent relative to the significant\n// digits (such as 1.2345), we create a theoretical representation of\n// `b` as a big-integer type, scaled to the same binary exponent as\n// the actual digits. we then compare the big integer representations\n// of both, and use that to direct rounding.\ntemplate <typename T, typename UC>\ninline FASTFLOAT_CONSTEXPR20\nadjusted_mantissa digit_comp(parsed_number_string_t<UC>& num, adjusted_mantissa am) noexcept {\n  // remove the invalid exponent bias\n  am.power2 -= invalid_am_bias;\n\n  int32_t sci_exp = scientific_exponent(num);\n  size_t max_digits = binary_format<T>::max_digits();\n  size_t digits = 0;\n  bigint bigmant;\n  parse_mantissa(bigmant, num, max_digits, digits);\n  // can't underflow, since digits is at most max_digits.\n  int32_t exponent = sci_exp + 1 - int32_t(digits);\n  if (exponent >= 0) {\n    return positive_digit_comp<T>(bigmant, exponent);\n  } else {\n    return negative_digit_comp<T>(bigmant, am, exponent);\n  }\n}\n\n} // namespace fast_float\n\n#endif\n\n#ifndef FASTFLOAT_PARSE_NUMBER_H\n#define FASTFLOAT_PARSE_NUMBER_H\n\n\n#include <cmath>\n#include <cstring>\n#include <limits>\n#include <system_error>\nnamespace fast_float {\n\n\nnamespace detail {\n/**\n * Special case +inf, -inf, nan, infinity, -infinity.\n * The case comparisons could be made much faster given that we know that the\n * strings a null-free and fixed.\n **/\ntemplate <typename T, typename UC>\nfrom_chars_result_t<UC> FASTFLOAT_CONSTEXPR14\nparse_infnan(UC const * first, UC const * last, T &value)  noexcept  {\n  from_chars_result_t<UC> answer{};\n  answer.ptr = first;\n  answer.ec = std::errc(); // be optimistic\n  bool minusSign = false;\n  if (*first == UC('-')) { // assume first < last, so dereference without checks; C++17 20.19.3.(7.1) explicitly forbids '+' here\n      minusSign = true;\n      ++first;\n  }\n#ifdef FASTFLOAT_ALLOWS_LEADING_PLUS // disabled by default\n  if (*first == UC('+')) {\n      ++first;\n  }\n#endif\n  if (last - first >= 3) {\n    if (fastfloat_strncasecmp(first, str_const_nan<UC>(), 3)) {\n      answer.ptr = (first += 3);\n      value = minusSign ? -std::numeric_limits<T>::quiet_NaN() : std::numeric_limits<T>::quiet_NaN();\n      // Check for possible nan(n-char-seq-opt), C++17 20.19.3.7, C11 7.20.1.3.3. At least MSVC produces nan(ind) and nan(snan).\n      if(first != last && *first == UC('(')) {\n        for(UC const * ptr = first + 1; ptr != last; ++ptr) {\n          if (*ptr == UC(')')) {\n            answer.ptr = ptr + 1; // valid nan(n-char-seq-opt)\n            break;\n          }\n          else if(!((UC('a') <= *ptr && *ptr <= UC('z')) || (UC('A') <= *ptr && *ptr <= UC('Z')) || (UC('0') <= *ptr && *ptr <= UC('9')) || *ptr == UC('_')))\n            break; // forbidden char, not nan(n-char-seq-opt)\n        }\n      }\n      return answer;\n    }\n    if (fastfloat_strncasecmp(first, str_const_inf<UC>(), 3)) {\n      if ((last - first >= 8) && fastfloat_strncasecmp(first + 3, str_const_inf<UC>() + 3, 5)) {\n        answer.ptr = first + 8;\n      } else {\n        answer.ptr = first + 3;\n      }\n      value = minusSign ? -std::numeric_limits<T>::infinity() : std::numeric_limits<T>::infinity();\n      return answer;\n    }\n  }\n  answer.ec = std::errc::invalid_argument;\n  return answer;\n}\n\n/**\n * Returns true if the floating-pointing rounding mode is to 'nearest'.\n * It is the default on most system. This function is meant to be inexpensive.\n * Credit : @mwalcott3\n */\nfastfloat_really_inline bool rounds_to_nearest() noexcept {\n  // https://lemire.me/blog/2020/06/26/gcc-not-nearest/\n#if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0)\n  return false;\n#endif\n  // See\n  // A fast function to check your floating-point rounding mode\n  // https://lemire.me/blog/2022/11/16/a-fast-function-to-check-your-floating-point-rounding-mode/\n  //\n  // This function is meant to be equivalent to :\n  // prior: #include <cfenv>\n  //  return fegetround() == FE_TONEAREST;\n  // However, it is expected to be much faster than the fegetround()\n  // function call.\n  //\n  // The volatile keywoard prevents the compiler from computing the function\n  // at compile-time.\n  // There might be other ways to prevent compile-time optimizations (e.g., asm).\n  // The value does not need to be std::numeric_limits<float>::min(), any small\n  // value so that 1 + x should round to 1 would do (after accounting for excess\n  // precision, as in 387 instructions).\n  static volatile float fmin = std::numeric_limits<float>::min();\n  float fmini = fmin; // we copy it so that it gets loaded at most once.\n  //\n  // Explanation:\n  // Only when fegetround() == FE_TONEAREST do we have that\n  // fmin + 1.0f == 1.0f - fmin.\n  //\n  // FE_UPWARD:\n  //  fmin + 1.0f > 1\n  //  1.0f - fmin == 1\n  //\n  // FE_DOWNWARD or  FE_TOWARDZERO:\n  //  fmin + 1.0f == 1\n  //  1.0f - fmin < 1\n  //\n  // Note: This may fail to be accurate if fast-math has been\n  // enabled, as rounding conventions may not apply.\n  #ifdef FASTFLOAT_VISUAL_STUDIO\n  #   pragma warning(push)\n  //  todo: is there a VS warning?\n  //  see https://stackoverflow.com/questions/46079446/is-there-a-warning-for-floating-point-equality-checking-in-visual-studio-2013\n  #elif defined(__clang__)\n  #   pragma clang diagnostic push\n  #   pragma clang diagnostic ignored \"-Wfloat-equal\"\n  #elif defined(__GNUC__)\n  #   pragma GCC diagnostic push\n  #   pragma GCC diagnostic ignored \"-Wfloat-equal\"\n  #endif\n  return (fmini + 1.0f == 1.0f - fmini);\n  #ifdef FASTFLOAT_VISUAL_STUDIO\n  #   pragma warning(pop)\n  #elif defined(__clang__)\n  #   pragma clang diagnostic pop\n  #elif defined(__GNUC__)\n  #   pragma GCC diagnostic pop\n  #endif\n}\n\n} // namespace detail\n\ntemplate <typename T>\nstruct from_chars_caller\n{\n  template <typename UC>\n  FASTFLOAT_CONSTEXPR20\n  static from_chars_result_t<UC> call(UC const * first, UC const * last,\n                                      T &value, parse_options_t<UC> options)  noexcept {\n    return from_chars_advanced(first, last, value, options);\n  }\n};\n\n#if __STDCPP_FLOAT32_T__ == 1\ntemplate <>\nstruct from_chars_caller<std::float32_t>\n{\n  template <typename UC>\n  FASTFLOAT_CONSTEXPR20\n  static from_chars_result_t<UC> call(UC const * first, UC const * last,\n                                      std::float32_t &value, parse_options_t<UC> options) noexcept{\n    // if std::float32_t is defined, and we are in C++23 mode; macro set for float32; \n    // set value to float due to equivalence between float and float32_t\n    float val;\n    auto ret = from_chars_advanced(first, last, val, options);\n    value = val;\n    return ret;\n  }\n};\n#endif\n\n#if __STDCPP_FLOAT64_T__ == 1\ntemplate <>\nstruct from_chars_caller<std::float64_t>\n{\n  template <typename UC>\n  FASTFLOAT_CONSTEXPR20\n  static from_chars_result_t<UC> call(UC const * first, UC const * last,\n                                      std::float64_t &value, parse_options_t<UC> options) noexcept{\n    // if std::float64_t is defined, and we are in C++23 mode; macro set for float64;\n    // set value as double due to equivalence between double and float64_t\n    double val;\n    auto ret = from_chars_advanced(first, last, val, options);\n    value = val;\n    return ret;\n  }\n};\n#endif\n\n\ntemplate<typename T, typename UC, typename>\nFASTFLOAT_CONSTEXPR20\nfrom_chars_result_t<UC> from_chars(UC const * first, UC const * last,\n                             T &value, chars_format fmt /*= chars_format::general*/)  noexcept  {\n  return from_chars_caller<T>::call(first, last, value, parse_options_t<UC>(fmt));\n}\n\n/**\n * This function overload takes parsed_number_string_t structure that is created and populated\n * either by from_chars_advanced function taking chars range and parsing options\n * or other parsing custom function implemented by user.\n */\ntemplate<typename T, typename UC>\nFASTFLOAT_CONSTEXPR20\nfrom_chars_result_t<UC> from_chars_advanced(parsed_number_string_t<UC>& pns,\n                                      T &value)  noexcept  {\n\n  static_assert (is_supported_float_type<T>(), \"only some floating-point types are supported\");\n  static_assert (is_supported_char_type<UC>(), \"only char, wchar_t, char16_t and char32_t are supported\");\n\n  from_chars_result_t<UC> answer;\n\n  answer.ec = std::errc(); // be optimistic\n  answer.ptr = pns.lastmatch;\n  // The implementation of the Clinger's fast path is convoluted because\n  // we want round-to-nearest in all cases, irrespective of the rounding mode\n  // selected on the thread.\n  // We proceed optimistically, assuming that detail::rounds_to_nearest() returns\n  // true.\n  if (binary_format<T>::min_exponent_fast_path() <= pns.exponent && pns.exponent <= binary_format<T>::max_exponent_fast_path() && !pns.too_many_digits) {\n    // Unfortunately, the conventional Clinger's fast path is only possible\n    // when the system rounds to the nearest float.\n    //\n    // We expect the next branch to almost always be selected.\n    // We could check it first (before the previous branch), but\n    // there might be performance advantages at having the check\n    // be last.\n    if(!cpp20_and_in_constexpr() && detail::rounds_to_nearest())  {\n      // We have that fegetround() == FE_TONEAREST.\n      // Next is Clinger's fast path.\n      if (pns.mantissa <=binary_format<T>::max_mantissa_fast_path()) {\n        value = T(pns.mantissa);\n        if (pns.exponent < 0) { value = value / binary_format<T>::exact_power_of_ten(-pns.exponent); }\n        else { value = value * binary_format<T>::exact_power_of_ten(pns.exponent); }\n        if (pns.negative) { value = -value; }\n        return answer;\n      }\n    } else {\n      // We do not have that fegetround() == FE_TONEAREST.\n      // Next is a modified Clinger's fast path, inspired by Jakub Jelínek's proposal\n      if (pns.exponent >= 0 && pns.mantissa <=binary_format<T>::max_mantissa_fast_path(pns.exponent)) {\n#if defined(__clang__) || defined(FASTFLOAT_32BIT)\n        // Clang may map 0 to -0.0 when fegetround() == FE_DOWNWARD\n        if(pns.mantissa == 0) {\n          value = pns.negative ? T(-0.) : T(0.);\n          return answer;\n        }\n#endif\n        value = T(pns.mantissa) * binary_format<T>::exact_power_of_ten(pns.exponent);\n        if (pns.negative) { value = -value; }\n        return answer;\n      }\n    }\n  }\n  adjusted_mantissa am = compute_float<binary_format<T>>(pns.exponent, pns.mantissa);\n  if(pns.too_many_digits && am.power2 >= 0) {\n    if(am != compute_float<binary_format<T>>(pns.exponent, pns.mantissa + 1)) {\n      am = compute_error<binary_format<T>>(pns.exponent, pns.mantissa);\n    }\n  }\n  // If we called compute_float<binary_format<T>>(pns.exponent, pns.mantissa) and we have an invalid power (am.power2 < 0),\n  // then we need to go the long way around again. This is very uncommon.\n  if(am.power2 < 0) { am = digit_comp<T>(pns, am); }\n  to_float(pns.negative, am, value);\n  // Test for over/underflow.\n  if ((pns.mantissa != 0 && am.mantissa == 0 && am.power2 == 0) || am.power2 == binary_format<T>::infinite_power()) {\n    answer.ec = std::errc::result_out_of_range;\n  }\n  return answer;\n}\n\ntemplate<typename T, typename UC>\nFASTFLOAT_CONSTEXPR20\nfrom_chars_result_t<UC> from_chars_advanced(UC const * first, UC const * last,\n                                      T &value, parse_options_t<UC> options)  noexcept  {\n\n  static_assert (is_supported_float_type<T>(), \"only some floating-point types are supported\");\n  static_assert (is_supported_char_type<UC>(), \"only char, wchar_t, char16_t and char32_t are supported\");\n\n  from_chars_result_t<UC> answer;\n#ifdef FASTFLOAT_SKIP_WHITE_SPACE  // disabled by default\n  while ((first != last) && fast_float::is_space(uint8_t(*first))) {\n    first++;\n  }\n#endif\n  if (first == last) {\n    answer.ec = std::errc::invalid_argument;\n    answer.ptr = first;\n    return answer;\n  }\n  parsed_number_string_t<UC> pns = parse_number_string<UC>(first, last, options);\n  if (!pns.valid) {\n    if (options.format & chars_format::no_infnan) {\n      answer.ec = std::errc::invalid_argument;\n      answer.ptr = first;\n      return answer;\n    } else {\n      return detail::parse_infnan(first, last, value);\n    }\n  }\n\n  // call overload that takes parsed_number_string_t directly.\n  return from_chars_advanced(pns, value);\n}\n\n\ntemplate <typename T, typename UC, typename>\nFASTFLOAT_CONSTEXPR20\nfrom_chars_result_t<UC> from_chars(UC const* first, UC const* last, T& value, int base) noexcept {\n  static_assert (is_supported_char_type<UC>(), \"only char, wchar_t, char16_t and char32_t are supported\");\n\n  from_chars_result_t<UC> answer;\n#ifdef FASTFLOAT_SKIP_WHITE_SPACE  // disabled by default\n  while ((first != last) && fast_float::is_space(uint8_t(*first))) {\n    first++;\n  }\n#endif\n  if (first == last || base < 2 || base > 36) {\n    answer.ec = std::errc::invalid_argument;\n    answer.ptr = first;\n    return answer;\n  }\n  return parse_int_string(first, last, value, base);\n}\n\n} // namespace fast_float\n\n#endif\n"
  },
  {
    "path": "libs/rapidyaml/c4/ext/rng/rng.hpp",
    "content": "/* Copyright (c) 2018 Arvid Gerstmann.\n *\n * https://arvid.io/2018/07/02/better-cxx-prng/\n *\n * This code is licensed under MIT license. */\n#ifndef AG_RANDOM_H\n#define AG_RANDOM_H\n\n#include <stdint.h>\n#include <random>\n\n\n#ifdef __clang__\n#   pragma clang diagnostic push\n#   pragma clang diagnostic ignored \"-Wold-style-cast\"\n#elif defined(__GNUC__)\n#   pragma GCC diagnostic push\n#   pragma GCC diagnostic ignored \"-Wold-style-cast\"\n#endif\n\nnamespace c4 {\nnamespace rng {\n\nclass splitmix\n{\npublic:\n    using result_type = uint32_t;\n    static constexpr result_type (min)() { return 0; }\n    static constexpr result_type (max)() { return UINT32_MAX; }\n    friend bool operator==(splitmix const &, splitmix const &);\n    friend bool operator!=(splitmix const &, splitmix const &);\n\n    splitmix() : m_seed(1) {}\n    explicit splitmix(uint64_t s) : m_seed(s) {}\n    explicit splitmix(std::random_device &rd)\n    {\n        seed(rd);\n    }\n\n    void seed(uint64_t s) { m_seed = s; }\n    void seed(std::random_device &rd)\n    {\n        m_seed = uint64_t(rd()) << 31 | uint64_t(rd());\n    }\n\n    result_type operator()()\n    {\n        uint64_t z = (m_seed += UINT64_C(0x9E3779B97F4A7C15));\n        z = (z ^ (z >> 30)) * UINT64_C(0xBF58476D1CE4E5B9);\n        z = (z ^ (z >> 27)) * UINT64_C(0x94D049BB133111EB);\n        return result_type((z ^ (z >> 31)) >> 31);\n    }\n\n    void discard(unsigned long long n)\n    {\n        for (unsigned long long i = 0; i < n; ++i)\n            operator()();\n    }\n\nprivate:\n    uint64_t m_seed;\n};\n\ninline bool operator==(splitmix const &lhs, splitmix const &rhs)\n{\n    return lhs.m_seed == rhs.m_seed;\n}\ninline bool operator!=(splitmix const &lhs, splitmix const &rhs)\n{\n    return lhs.m_seed != rhs.m_seed;\n}\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\nclass xorshift\n{\npublic:\n    using result_type = uint32_t;\n    static constexpr result_type (min)() { return 0; }\n    static constexpr result_type (max)() { return UINT32_MAX; }\n    friend bool operator==(xorshift const &, xorshift const &);\n    friend bool operator!=(xorshift const &, xorshift const &);\n\n    xorshift() : m_seed(0xc1f651c67c62c6e0ull) {}\n    explicit xorshift(std::random_device &rd)\n    {\n        seed(rd);\n    }\n\n    void seed(uint64_t s) { m_seed = s; }\n    void seed(std::random_device &rd)\n    {\n        m_seed = uint64_t(rd()) << 31 | uint64_t(rd());\n    }\n\n    result_type operator()()\n    {\n        uint64_t result = m_seed * 0xd989bcacc137dcd5ull;\n        m_seed ^= m_seed >> 11;\n        m_seed ^= m_seed << 31;\n        m_seed ^= m_seed >> 18;\n        return uint32_t(result >> 32ull);\n    }\n\n    void discard(unsigned long long n)\n    {\n        for (unsigned long long i = 0; i < n; ++i)\n            operator()();\n    }\n\nprivate:\n    uint64_t m_seed;\n};\n\ninline bool operator==(xorshift const &lhs, xorshift const &rhs)\n{\n    return lhs.m_seed == rhs.m_seed;\n}\ninline bool operator!=(xorshift const &lhs, xorshift const &rhs)\n{\n    return lhs.m_seed != rhs.m_seed;\n}\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\nclass pcg\n{\npublic:\n    using result_type = uint32_t;\n    static constexpr result_type (min)() { return 0; }\n    static constexpr result_type (max)() { return UINT32_MAX; }\n    friend bool operator==(pcg const &, pcg const &);\n    friend bool operator!=(pcg const &, pcg const &);\n\n    pcg()\n        : m_state(0x853c49e6748fea9bULL)\n        , m_inc(0xda3e39cb94b95bdbULL)\n    {}\n    explicit pcg(uint64_t s) { m_state = s; m_inc = m_state << 1; }\n    explicit pcg(std::random_device &rd)\n    {\n        seed(rd);\n    }\n\n    void seed(uint64_t s) { m_state = s; }\n    void seed(std::random_device &rd)\n    {\n        uint64_t s0 = uint64_t(rd()) << 31 | uint64_t(rd());\n        uint64_t s1 = uint64_t(rd()) << 31 | uint64_t(rd());\n\n        m_state = 0;\n        m_inc = (s1 << 1) | 1;\n        (void)operator()();\n        m_state += s0;\n        (void)operator()();\n    }\n\n    result_type operator()()\n    {\n        uint64_t oldstate = m_state;\n        m_state = oldstate * 6364136223846793005ULL + m_inc;\n        uint32_t xorshifted = uint32_t(((oldstate >> 18u) ^ oldstate) >> 27u);\n        //int rot = oldstate >> 59u; // the original. error?\n        int64_t rot = (int64_t)oldstate >> 59u; // error?\n        return (xorshifted >> rot) | (xorshifted << ((uint64_t)(-rot) & 31));\n    }\n\n    void discard(unsigned long long n)\n    {\n        for (unsigned long long i = 0; i < n; ++i)\n            operator()();\n    }\n\nprivate:\n    uint64_t m_state;\n    uint64_t m_inc;\n};\n\ninline bool operator==(pcg const &lhs, pcg const &rhs)\n{\n    return lhs.m_state == rhs.m_state\n        && lhs.m_inc == rhs.m_inc;\n}\ninline bool operator!=(pcg const &lhs, pcg const &rhs)\n{\n    return lhs.m_state != rhs.m_state\n        || lhs.m_inc != rhs.m_inc;\n}\n\n} // namespace rng\n} // namespace c4\n\n#ifdef __clang__\n#   pragma clang diagnostic pop\n#elif defined(__GNUC__)\n#   pragma GCC diagnostic pop\n#endif\n\n#endif /* AG_RANDOM_H */\n"
  },
  {
    "path": "libs/rapidyaml/c4/ext/sg14/README.md",
    "content": "https://github.com/WG21-SG14/SG14/blob/master/SG14/inplace_function.h\n"
  },
  {
    "path": "libs/rapidyaml/c4/ext/sg14/inplace_function.h",
    "content": "/*\n * Boost Software License - Version 1.0 - August 17th, 2003\n *\n * Permission is hereby granted, free of charge, to any person or organization\n * obtaining a copy of the software and accompanying documentation covered by\n * this license (the \"Software\") to use, reproduce, display, distribute,\n * execute, and transmit the Software, and to prepare derivative works of the\n * Software, and to permit third-parties to whom the Software is furnished to\n * do so, all subject to the following:\n *\n * The copyright notices in the Software and this entire statement, including\n * the above license grant, this restriction and the following disclaimer,\n * must be included in all copies of the Software, in whole or in part, and\n * all derivative works of the Software, unless such copies or derivative\n * works are solely in the form of machine-executable object code generated by\n * a source language processor.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT\n * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE\n * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,\n * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n#ifndef _C4_EXT_SG14_INPLACE_FUNCTION_H_\n#define _C4_EXT_SG14_INPLACE_FUNCTION_H_\n\n#include <type_traits>\n#include <utility>\n#include <functional>\n#include <cstdlib>\n\nnamespace stdext {\n\nnamespace inplace_function_detail {\n\nstatic constexpr size_t InplaceFunctionDefaultCapacity = 32;\n\n#if defined(__GLIBCXX__)  // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61458\ntemplate<size_t Cap>\nunion aligned_storage_helper {\n    struct double1 { double a; };\n    struct double4 { double a[4]; };\n    template<class T> using maybe = typename std::conditional<(Cap >= sizeof(T)), T, char>::type;\n    char real_data[Cap];\n    maybe<int> a;\n    maybe<long> b;\n    maybe<long long> c;\n    maybe<void*> d;\n    maybe<void(*)()> e;\n    maybe<double1> f;\n    maybe<double4> g;\n    maybe<long double> h;\n};\n\ntemplate<size_t Cap, size_t Align = std::alignment_of<aligned_storage_helper<Cap>>::value>\nstruct aligned_storage {\n    using type = typename std::aligned_storage<Cap, Align>::type;\n};\n#else\nusing std::aligned_storage;\n#endif\n\ntemplate<typename T> struct wrapper\n{\n    using type = T;\n};\n\ntemplate<typename R, typename... Args> struct vtable\n{\n    using storage_ptr_t = void*;\n\n    using invoke_ptr_t = R(*)(storage_ptr_t, Args&&...);\n    using process_ptr_t = void(*)(storage_ptr_t, storage_ptr_t);\n    using destructor_ptr_t = void(*)(storage_ptr_t);\n\n    const invoke_ptr_t invoke_ptr;\n    const process_ptr_t copy_ptr;\n    const process_ptr_t move_ptr;\n    const destructor_ptr_t destructor_ptr;\n\n    explicit constexpr vtable() noexcept :\n        invoke_ptr{ [](storage_ptr_t, Args&&...) -> R\n            {\n                #if (defined(_MSC_VER) && (defined(_CPPUNWIND) && (__CPPUNWIND == 1)))  \\\n                    ||                                                  \\\n                    (defined(__EXCEPTIONS) || defined(__cpp_exceptions))\n                throw std::bad_function_call();\n                #else\n                std::abort();\n                #endif\n            }\n        },\n        copy_ptr{ [](storage_ptr_t, storage_ptr_t) noexcept -> void {} },\n        move_ptr{ [](storage_ptr_t, storage_ptr_t) noexcept -> void {} },\n        destructor_ptr{ [](storage_ptr_t) noexcept -> void {} }\n    {}\n\n    template<typename C> explicit constexpr vtable(wrapper<C>) noexcept :\n        invoke_ptr{ [](storage_ptr_t storage_ptr, Args&&... args)\n            noexcept(noexcept(std::declval<C>()(args...))) -> R\n            { return (*static_cast<C*>(storage_ptr))(\n                std::forward<Args>(args)...\n            ); }\n        },\n        copy_ptr{ [](storage_ptr_t dst_ptr, storage_ptr_t src_ptr)\n            noexcept(std::is_nothrow_copy_constructible<C>::value) -> void\n            { new (dst_ptr) C{ (*static_cast<C*>(src_ptr)) }; }\n        },\n        move_ptr{ [](storage_ptr_t dst_ptr, storage_ptr_t src_ptr)\n            noexcept(std::is_nothrow_move_constructible<C>::value) -> void\n            { new (dst_ptr) C{ std::move(*static_cast<C*>(src_ptr)) }; }\n        },\n        destructor_ptr{ [](storage_ptr_t storage_ptr)\n            noexcept -> void\n            { static_cast<C*>(storage_ptr)->~C(); }\n        }\n    {}\n\n    vtable(const vtable&) = delete;\n    vtable(vtable&&) = delete;\n\n    vtable& operator= (const vtable&) = delete;\n    vtable& operator= (vtable&&) = delete;\n\n    ~vtable() = default;\n};\n\ntemplate<size_t DstCap, size_t DstAlign, size_t SrcCap, size_t SrcAlign>\nstruct is_valid_inplace_dst : std::true_type\n{\n    static_assert(DstCap >= SrcCap,\n        \"Can't squeeze larger inplace_function into a smaller one\"\n    );\n\n    static_assert(DstAlign % SrcAlign == 0,\n        \"Incompatible inplace_function alignments\"\n    );\n};\n\n} // namespace inplace_function_detail\n\ntemplate<\n    typename Signature,\n    size_t Capacity = inplace_function_detail::InplaceFunctionDefaultCapacity,\n    size_t Alignment = std::alignment_of<typename inplace_function_detail::aligned_storage<Capacity>::type>::value\n>\nclass inplace_function; // unspecified\n\ntemplate<\n    typename R,\n    typename... Args,\n    size_t Capacity,\n    size_t Alignment\n>\nclass inplace_function<R(Args...), Capacity, Alignment>\n{\n    static const constexpr inplace_function_detail::vtable<R, Args...> empty_vtable{};\npublic:\n    using capacity = std::integral_constant<size_t, Capacity>;\n    using alignment = std::integral_constant<size_t, Alignment>;\n\n    using storage_t = typename inplace_function_detail::aligned_storage<Capacity, Alignment>::type;\n    using vtable_t = inplace_function_detail::vtable<R, Args...>;\n    using vtable_ptr_t = const vtable_t*;\n\n    template <typename, size_t, size_t>\tfriend class inplace_function;\n\n    inplace_function() noexcept :\n        vtable_ptr_{std::addressof(empty_vtable)}\n    {}\n\n    template<\n        typename T,\n        typename C = typename std::decay<T>::type,\n        typename = typename std::enable_if<\n            !(std::is_same<C, inplace_function>::value\n            || std::is_convertible<C, inplace_function>::value)\n        >::type\n    >\n    inplace_function(T&& closure)\n    {\n#if __cplusplus >= 201703L\n        static_assert(std::is_invocable_r<R, C, Args...>::value,\n            \"inplace_function cannot be constructed from non-callable type\"\n        );\n#endif\n        static_assert(std::is_copy_constructible<C>::value,\n            \"inplace_function cannot be constructed from non-copyable type\"\n        );\n\n        static_assert(sizeof(C) <= Capacity,\n            \"inplace_function cannot be constructed from object with this (large) size\"\n        );\n\n        static_assert(Alignment % std::alignment_of<C>::value == 0,\n            \"inplace_function cannot be constructed from object with this (large) alignment\"\n        );\n\n        static const vtable_t vt{inplace_function_detail::wrapper<C>{}};\n        vtable_ptr_ = std::addressof(vt);\n\n        new (std::addressof(storage_)) C{std::forward<T>(closure)};\n    }\n\n    inplace_function(std::nullptr_t) noexcept :\n        vtable_ptr_{std::addressof(empty_vtable)}\n    {}\n\n    inplace_function(const inplace_function& other) :\n        vtable_ptr_{other.vtable_ptr_}\n    {\n        vtable_ptr_->copy_ptr(\n            std::addressof(storage_),\n            std::addressof(other.storage_)\n        );\n    }\n\n    inplace_function(inplace_function&& other) :\n        vtable_ptr_{other.vtable_ptr_}\n    {\n        vtable_ptr_->move_ptr(\n            std::addressof(storage_),\n            std::addressof(other.storage_)\n        );\n    }\n\n    inplace_function& operator= (std::nullptr_t) noexcept\n    {\n        vtable_ptr_->destructor_ptr(std::addressof(storage_));\n        vtable_ptr_ = std::addressof(empty_vtable);\n        return *this;\n    }\n\n    inplace_function& operator= (const inplace_function& other)\n    {\n        if(this != std::addressof(other))\n        {\n            vtable_ptr_->destructor_ptr(std::addressof(storage_));\n\n            vtable_ptr_ = other.vtable_ptr_;\n            vtable_ptr_->copy_ptr(\n                std::addressof(storage_),\n                std::addressof(other.storage_)\n            );\n        }\n        return *this;\n    }\n\n    inplace_function& operator= (inplace_function&& other)\n    {\n        if(this != std::addressof(other))\n        {\n            vtable_ptr_->destructor_ptr(std::addressof(storage_));\n\n            vtable_ptr_ = other.vtable_ptr_;\n            vtable_ptr_->move_ptr(\n                std::addressof(storage_),\n                std::addressof(other.storage_)\n            );\n        }\n        return *this;\n    }\n\n    ~inplace_function()\n    {\n        vtable_ptr_->destructor_ptr(std::addressof(storage_));\n    }\n\n    R operator() (Args... args) const\n    {\n        return vtable_ptr_->invoke_ptr(\n            std::addressof(storage_),\n            std::forward<Args>(args)...\n        );\n    }\n\n    constexpr bool operator== (std::nullptr_t) const noexcept\n    {\n        return !operator bool();\n    }\n\n    constexpr bool operator!= (std::nullptr_t) const noexcept\n    {\n        return operator bool();\n    }\n\n    explicit constexpr operator bool() const noexcept\n    {\n        return vtable_ptr_ != std::addressof(empty_vtable);\n    }\n\n    template<size_t Cap, size_t Align>\n    operator inplace_function<R(Args...), Cap, Align>() const&\n    {\n        static_assert(inplace_function_detail::is_valid_inplace_dst<\n            Cap, Align, Capacity, Alignment\n        >::value, \"conversion not allowed\");\n\n        return {vtable_ptr_, vtable_ptr_->copy_ptr, std::addressof(storage_)};\n    }\n\n    template<size_t Cap, size_t Align>\n    operator inplace_function<R(Args...), Cap, Align>() &&\n    {\n        static_assert(inplace_function_detail::is_valid_inplace_dst<\n            Cap, Align, Capacity, Alignment\n        >::value, \"conversion not allowed\");\n\n        return {vtable_ptr_, vtable_ptr_->move_ptr, std::addressof(storage_)};\n    }\n\n    void swap(inplace_function& other)\n    {\n        if (this == std::addressof(other)) return;\n\n        storage_t tmp;\n        vtable_ptr_->move_ptr(\n            std::addressof(tmp),\n            std::addressof(storage_)\n        );\n        vtable_ptr_->destructor_ptr(std::addressof(storage_));\n\n        other.vtable_ptr_->move_ptr(\n            std::addressof(storage_),\n            std::addressof(other.storage_)\n        );\n        other.vtable_ptr_->destructor_ptr(std::addressof(other.storage_));\n\n        vtable_ptr_->move_ptr(\n            std::addressof(other.storage_),\n            std::addressof(tmp)\n        );\n        vtable_ptr_->destructor_ptr(std::addressof(tmp));\n\n        std::swap(vtable_ptr_, other.vtable_ptr_);\n    }\n\nprivate:\n    vtable_ptr_t vtable_ptr_;\n    mutable storage_t storage_;\n\n    inplace_function(\n        vtable_ptr_t vtable_ptr,\n        typename vtable_t::process_ptr_t process_ptr,\n        typename vtable_t::storage_ptr_t storage_ptr\n    ) : vtable_ptr_{vtable_ptr}\n    {\n        process_ptr(std::addressof(storage_), storage_ptr);\n    }\n};\n\n} // namespace stdext\n\n#endif /* _C4_EXT_SG14_INPLACE_FUNCTION_H_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/format.cpp",
    "content": "#include \"c4/format.hpp\"\n\n#include <memory> // for std::align\n\n#ifdef __clang__\n#   pragma clang diagnostic push\n#   pragma clang diagnostic ignored \"-Wformat-nonliteral\"\n#   pragma clang diagnostic ignored \"-Wold-style-cast\"\n#elif defined(__GNUC__)\n#   pragma GCC diagnostic push\n#   pragma GCC diagnostic ignored \"-Wformat-nonliteral\"\n#   pragma GCC diagnostic ignored \"-Wold-style-cast\"\n#endif\n\nnamespace c4 {\n\n\nsize_t to_chars(substr buf, fmt::const_raw_wrapper r)\n{\n    void * vptr = buf.str;\n    size_t space = buf.len;\n    auto ptr = (decltype(buf.str)) std::align(r.alignment, r.len, vptr, space);\n    if(ptr == nullptr)\n    {\n        // if it was not possible to align, return a conservative estimate\n        // of the required space\n        return r.alignment + r.len;\n    }\n    C4_CHECK(ptr >= buf.begin() && ptr <= buf.end());\n    size_t sz = static_cast<size_t>(ptr - buf.str) + r.len;\n    if(sz <= buf.len)\n    {\n        memcpy(ptr, r.buf, r.len);\n    }\n    return sz;\n}\n\n\nbool from_chars(csubstr buf, fmt::raw_wrapper *r)\n{\n    C4_SUPPRESS_WARNING_GCC_WITH_PUSH(\"-Wcast-qual\")\n    void * vptr = (void*)buf.str;\n    C4_SUPPRESS_WARNING_GCC_POP\n    size_t space = buf.len;\n    auto ptr = (decltype(buf.str)) std::align(r->alignment, r->len, vptr, space);\n    C4_CHECK(ptr != nullptr);\n    C4_CHECK(ptr >= buf.begin() && ptr <= buf.end());\n    C4_SUPPRESS_WARNING_GCC_PUSH\n    #if defined(__GNUC__) && __GNUC__ > 9\n    C4_SUPPRESS_WARNING_GCC(\"-Wanalyzer-null-argument\")\n    #endif\n    memcpy(r->buf, ptr, r->len);\n    C4_SUPPRESS_WARNING_GCC_POP\n    return true;\n}\n\n\n} // namespace c4\n\n#ifdef __clang__\n#   pragma clang diagnostic pop\n#elif defined(__GNUC__)\n#   pragma GCC diagnostic pop\n#endif\n"
  },
  {
    "path": "libs/rapidyaml/c4/format.hpp",
    "content": "#ifndef _C4_FORMAT_HPP_\n#define _C4_FORMAT_HPP_\n\n/** @file format.hpp provides type-safe facilities for formatting arguments\n * to string buffers */\n\n#include \"c4/charconv.hpp\"\n#include \"c4/blob.hpp\"\n\n\n#ifdef _MSC_VER\n#   pragma warning(push)\n#   if C4_MSVC_VERSION != C4_MSVC_VERSION_2017\n#       pragma warning(disable: 4800) // forcing value to bool 'true' or 'false' (performance warning)\n#   endif\n#   pragma warning(disable: 4996) // snprintf/scanf: this function or variable may be unsafe\n#elif defined(__clang__)\n#   pragma clang diagnostic push\n#elif defined(__GNUC__)\n#   pragma GCC diagnostic push\n#   pragma GCC diagnostic ignored \"-Wuseless-cast\"\n#endif\n\n/** @defgroup doc_format_utils Format utilities\n *\n * @brief Provides generic and type-safe formatting/scanning utilities\n * built on top of @ref doc_to_chars() and @ref doc_from_chars,\n * forwarding the arguments to these functions, which in turn use the\n * @ref doc_charconv utilities. Like @ref doc_charconv, the formatting\n * facilities are very efficient and many times faster than printf().\n *\n * @see [a formatting sample in rapidyaml's docs](https://rapidyaml.readthedocs.io/latest/doxygen/group__doc__quickstart.html#gac2425b515eb552589708cfff70c52b14)\n * */\n\n/** @defgroup doc_format_specifiers Format specifiers\n *\n * @brief Format specifiers are tag types and functions that are used\n * together with @ref doc_to_chars and @ref doc_from_chars\n *\n * @see [a formatting sample in rapidyaml's docs](https://rapidyaml.readthedocs.io/latest/doxygen/group__doc__quickstart.html#gac2425b515eb552589708cfff70c52b14)\n * @ingroup doc_format_utils */\n\nnamespace c4 {\n\n/** @addtogroup doc_format_utils\n * @{ */\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n// formatting truthy types as booleans\n\nnamespace fmt {\n\n/** @addtogroup doc_format_specifiers\n * @{ */\n\n/** @defgroup doc_boolean_specifiers boolean specifiers\n * @{ */\n\n/** write a variable as an alphabetic boolean, ie as either true or false\n * @param strict_read */\ntemplate<class T>\nstruct boolalpha_\n{\n    boolalpha_(T val_, bool strict_read_=false) : val(val_ ? true : false), strict_read(strict_read_) {}\n    bool val;\n    bool strict_read;\n};\n\ntemplate<class T>\nboolalpha_<T> boolalpha(T const& val, bool strict_read=false)\n{\n    return boolalpha_<T>(val, strict_read);\n}\n\n/** @} */\n\n/** @} */\n\n} // namespace fmt\n\n/** write a variable as an alphabetic boolean, ie as either true or\n * false\n * @ingroup doc_to_chars */\ntemplate<class T>\ninline size_t to_chars(substr buf, fmt::boolalpha_<T> fmt)\n{\n    return to_chars(buf, fmt.val ? \"true\" : \"false\");\n}\n\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n// formatting integral types\n\nnamespace fmt {\n\n/** @addtogroup doc_format_specifiers\n * @{ */\n\n/** @defgroup doc_integer_specifiers Integer specifiers\n * @{ */\n\n/** format an integral type with a custom radix */\ntemplate<typename T>\nstruct integral_\n{\n    C4_STATIC_ASSERT(std::is_integral<T>::value);\n    T val;\n    T radix;\n    C4_ALWAYS_INLINE integral_(T val_, T radix_) : val(val_), radix(radix_) {}\n};\n\n/** format an integral type with a custom radix, and pad with zeroes on the left */\ntemplate<typename T>\nstruct integral_padded_\n{\n    C4_STATIC_ASSERT(std::is_integral<T>::value);\n    T val;\n    T radix;\n    size_t num_digits;\n    C4_ALWAYS_INLINE integral_padded_(T val_, T radix_, size_t nd) : val(val_), radix(radix_), num_digits(nd) {}\n};\n\n\n/** format an integral type with a custom radix */\ntemplate<class T>\nC4_ALWAYS_INLINE integral_<T> integral(T val, T radix=10)\n{\n    return integral_<T>(val, radix);\n}\n/** format an integral type with a custom radix */\ntemplate<class T>\nC4_ALWAYS_INLINE integral_<intptr_t> integral(T const* val, T radix=10)\n{\n    return integral_<intptr_t>(reinterpret_cast<intptr_t>(val), static_cast<intptr_t>(radix));\n}\n/** format an integral type with a custom radix */\ntemplate<class T>\nC4_ALWAYS_INLINE integral_<intptr_t> integral(std::nullptr_t, T radix=10)\n{\n    return integral_<intptr_t>(intptr_t(0), static_cast<intptr_t>(radix));\n}\n\n\n/** format the pointer as an hexadecimal value */\ntemplate<class T>\ninline integral_<intptr_t> hex(T * v)\n{\n    return integral_<intptr_t>(reinterpret_cast<intptr_t>(v), intptr_t(16));\n}\n/** format the pointer as an hexadecimal value */\ntemplate<class T>\ninline integral_<intptr_t> hex(T const* v)\n{\n    return integral_<intptr_t>(reinterpret_cast<intptr_t>(v), intptr_t(16));\n}\n/** format null as an hexadecimal value\n * @overload hex */\ninline integral_<intptr_t> hex(std::nullptr_t)\n{\n    return integral_<intptr_t>(0, intptr_t(16));\n}\n/** format the integral_ argument as an hexadecimal value\n * @overload hex */\ntemplate<class T>\ninline integral_<T> hex(T v)\n{\n    return integral_<T>(v, T(16));\n}\n\n/** format the pointer as an octal value */\ntemplate<class T>\ninline integral_<intptr_t> oct(T const* v)\n{\n    return integral_<intptr_t>(reinterpret_cast<intptr_t>(v), intptr_t(8));\n}\n/** format the pointer as an octal value */\ntemplate<class T>\ninline integral_<intptr_t> oct(T * v)\n{\n    return integral_<intptr_t>(reinterpret_cast<intptr_t>(v), intptr_t(8));\n}\n/** format null as an octal value */\ninline integral_<intptr_t> oct(std::nullptr_t)\n{\n    return integral_<intptr_t>(intptr_t(0), intptr_t(8));\n}\n/** format the integral_ argument as an octal value */\ntemplate<class T>\ninline integral_<T> oct(T v)\n{\n    return integral_<T>(v, T(8));\n}\n\n/** format the pointer as a binary 0-1 value\n * @see c4::raw() if you want to use a binary memcpy instead of 0-1 formatting */\ntemplate<class T>\ninline integral_<intptr_t> bin(T const* v)\n{\n    return integral_<intptr_t>(reinterpret_cast<intptr_t>(v), intptr_t(2));\n}\n/** format the pointer as a binary 0-1 value\n * @see c4::raw() if you want to use a binary memcpy instead of 0-1 formatting */\ntemplate<class T>\ninline integral_<intptr_t> bin(T * v)\n{\n    return integral_<intptr_t>(reinterpret_cast<intptr_t>(v), intptr_t(2));\n}\n/** format null as a binary 0-1 value\n * @see c4::raw() if you want to use a binary memcpy instead of 0-1 formatting */\ninline integral_<intptr_t> bin(std::nullptr_t)\n{\n    return integral_<intptr_t>(intptr_t(0), intptr_t(2));\n}\n/** format the integral_ argument as a binary 0-1 value\n * @see c4::raw() if you want to use a raw memcpy-based binary dump instead of 0-1 formatting */\ntemplate<class T>\ninline integral_<T> bin(T v)\n{\n    return integral_<T>(v, T(2));\n}\n\n/** @} */ // integer_specifiers\n\n\n/** @defgroup doc_zpad Pad the number with zeroes on the left\n * @{ */\n\n/** pad the argument with zeroes on the left, with decimal radix */\ntemplate<class T>\nC4_ALWAYS_INLINE integral_padded_<T> zpad(T val, size_t num_digits)\n{\n    return integral_padded_<T>(val, T(10), num_digits);\n}\n/** pad the argument with zeroes on the left */\ntemplate<class T>\nC4_ALWAYS_INLINE integral_padded_<T> zpad(integral_<T> val, size_t num_digits)\n{\n    return integral_padded_<T>(val.val, val.radix, num_digits);\n}\n/** pad the argument with zeroes on the left */\nC4_ALWAYS_INLINE integral_padded_<intptr_t> zpad(std::nullptr_t, size_t num_digits)\n{\n    return integral_padded_<intptr_t>(0, 16, num_digits);\n}\n/** pad the argument with zeroes on the left */\ntemplate<class T>\nC4_ALWAYS_INLINE integral_padded_<intptr_t> zpad(T const* val, size_t num_digits)\n{\n    return integral_padded_<intptr_t>(reinterpret_cast<intptr_t>(val), 16, num_digits);\n}\ntemplate<class T>\nC4_ALWAYS_INLINE integral_padded_<intptr_t> zpad(T * val, size_t num_digits)\n{\n    return integral_padded_<intptr_t>(reinterpret_cast<intptr_t>(val), 16, num_digits);\n}\n\n/** @} */ // zpad\n\n\n/** @defgroup doc_overflow_checked Check read for overflow\n * @{ */\n\ntemplate<class T>\nstruct overflow_checked_\n{\n    static_assert(std::is_integral<T>::value, \"range checking only for integral types\");\n    C4_ALWAYS_INLINE overflow_checked_(T &val_) : val(&val_) {}\n    T *val;\n};\ntemplate<class T>\nC4_ALWAYS_INLINE overflow_checked_<T> overflow_checked(T &val)\n{\n   return overflow_checked_<T>(val);\n}\n\n/** @} */ // overflow_checked\n\n/** @} */ // format_specifiers\n\n\n} // namespace fmt\n\n/** format an integer signed type\n * @ingroup doc_to_chars */\ntemplate<typename T>\nC4_ALWAYS_INLINE\ntypename std::enable_if<std::is_signed<T>::value, size_t>::type\nto_chars(substr buf, fmt::integral_<T> fmt)\n{\n    return itoa(buf, fmt.val, fmt.radix);\n}\n/** format an integer signed type, pad with zeroes\n * @ingroup doc_to_chars */\ntemplate<typename T>\nC4_ALWAYS_INLINE\ntypename std::enable_if<std::is_signed<T>::value, size_t>::type\nto_chars(substr buf, fmt::integral_padded_<T> fmt)\n{\n    return itoa(buf, fmt.val, fmt.radix, fmt.num_digits);\n}\n\n/** format an integer unsigned type\n * @ingroup doc_to_chars */\ntemplate<typename T>\nC4_ALWAYS_INLINE\ntypename std::enable_if<std::is_unsigned<T>::value, size_t>::type\nto_chars(substr buf, fmt::integral_<T> fmt)\n{\n    return utoa(buf, fmt.val, fmt.radix);\n}\n/** format an integer unsigned type, pad with zeroes\n * @ingroup doc_to_chars */\ntemplate<typename T>\nC4_ALWAYS_INLINE\ntypename std::enable_if<std::is_unsigned<T>::value, size_t>::type\nto_chars(substr buf, fmt::integral_padded_<T> fmt)\n{\n    return utoa(buf, fmt.val, fmt.radix, fmt.num_digits);\n}\n\n/** read an integer type, detecting overflow (returns false on overflow)\n * @ingroup doc_from_chars */\ntemplate<class T>\nC4_ALWAYS_INLINE bool from_chars(csubstr s, fmt::overflow_checked_<T> wrapper)\n{\n    if(C4_LIKELY(!overflows<T>(s)))\n        return atox(s, wrapper.val);\n    return false;\n}\n/** read an integer type, detecting overflow (returns false on overflow)\n * @ingroup doc_from_chars */\ntemplate<class T>\nC4_ALWAYS_INLINE bool from_chars(csubstr s, fmt::overflow_checked_<T> *wrapper)\n{\n    if(C4_LIKELY(!overflows<T>(s)))\n        return atox(s, wrapper->val);\n    return false;\n}\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n// formatting real types\n\nnamespace fmt {\n\n/** @addtogroup doc_format_specifiers\n * @{ */\n\n/** @defgroup doc_real_specifiers Real specifiers\n * @{ */\n\ntemplate<class T>\nstruct real_\n{\n    T val;\n    int precision;\n    RealFormat_e fmt;\n    real_(T v, int prec=-1, RealFormat_e f=FTOA_FLOAT) : val(v), precision(prec), fmt(f)  {}\n};\n\ntemplate<class T>\nreal_<T> real(T val, int precision, RealFormat_e fmt=FTOA_FLOAT)\n{\n    return real_<T>(val, precision, fmt);\n}\n\n/** @} */ // real_specifiers\n\n/** @} */ // format_specifiers\n\n} // namespace fmt\n\n/** @ingroup doc_to_chars */\ninline size_t to_chars(substr buf, fmt::real_< float> fmt) { return ftoa(buf, fmt.val, fmt.precision, fmt.fmt); }\n/** @ingroup doc_to_chars */\ninline size_t to_chars(substr buf, fmt::real_<double> fmt) { return dtoa(buf, fmt.val, fmt.precision, fmt.fmt); }\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n// writing raw binary data\n\nnamespace fmt {\n\n/** @addtogroup doc_format_specifiers\n * @{ */\n\n/** @defgroup doc_raw_binary_specifiers Raw binary data\n * @{ */\n\n/** @see blob_ */\ntemplate<class T>\nstruct raw_wrapper_ : public blob_<T>\n{\n    size_t alignment;\n\n    C4_ALWAYS_INLINE raw_wrapper_(blob_<T> data, size_t alignment_) noexcept\n        :\n        blob_<T>(data),\n        alignment(alignment_)\n    {\n        C4_ASSERT_MSG(alignment > 0 && (alignment & (alignment - 1)) == 0, \"alignment must be a power of two\");\n    }\n};\n\nusing const_raw_wrapper = raw_wrapper_<cbyte>;\nusing raw_wrapper = raw_wrapper_<byte>;\n\n/** mark a variable to be written in raw binary format, using memcpy\n * @see blob_ */\ninline const_raw_wrapper craw(cblob data, size_t alignment=alignof(max_align_t))\n{\n    return const_raw_wrapper(data, alignment);\n}\n/** mark a variable to be written in raw binary format, using memcpy\n * @see blob_ */\ninline const_raw_wrapper raw(cblob data, size_t alignment=alignof(max_align_t))\n{\n    return const_raw_wrapper(data, alignment);\n}\n/** mark a variable to be written in raw binary format, using memcpy\n * @see blob_ */\ntemplate<class T>\ninline const_raw_wrapper craw(T const& C4_RESTRICT data, size_t alignment=alignof(T))\n{\n    return const_raw_wrapper(cblob(data), alignment);\n}\n/** mark a variable to be written in raw binary format, using memcpy\n * @see blob_ */\ntemplate<class T>\ninline const_raw_wrapper raw(T const& C4_RESTRICT data, size_t alignment=alignof(T))\n{\n    return const_raw_wrapper(cblob(data), alignment);\n}\n\n/** mark a variable to be read in raw binary format, using memcpy */\ninline raw_wrapper raw(blob data, size_t alignment=alignof(max_align_t))\n{\n    return raw_wrapper(data, alignment);\n}\n/** mark a variable to be read in raw binary format, using memcpy */\ntemplate<class T>\ninline raw_wrapper raw(T & C4_RESTRICT data, size_t alignment=alignof(T))\n{\n    return raw_wrapper(blob(data), alignment);\n}\n\n/** @} */ // raw_binary_specifiers\n\n/** @} */ // format_specifiers\n\n} // namespace fmt\n\n\n/** write a variable in raw binary format, using memcpy\n * @ingroup doc_to_chars */\nC4CORE_EXPORT size_t to_chars(substr buf, fmt::const_raw_wrapper r);\n\n/** read a variable in raw binary format, using memcpy\n * @ingroup doc_from_chars */\nC4CORE_EXPORT bool from_chars(csubstr buf, fmt::raw_wrapper *r);\n/** read a variable in raw binary format, using memcpy\n * @ingroup doc_from_chars */\ninline bool from_chars(csubstr buf, fmt::raw_wrapper r)\n{\n    return from_chars(buf, &r);\n}\n\n/** read a variable in raw binary format, using memcpy\n * @ingroup doc_from_chars_first */\ninline size_t from_chars_first(csubstr buf, fmt::raw_wrapper *r)\n{\n    return from_chars(buf, r);\n}\n/** read a variable in raw binary format, using memcpy\n * @ingroup doc_from_chars_first */\ninline size_t from_chars_first(csubstr buf, fmt::raw_wrapper r)\n{\n    return from_chars(buf, &r);\n}\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n// formatting aligned to left/right\n\nnamespace fmt {\n\n/** @addtogroup doc_format_specifiers\n * @{ */\n\n/** @defgroup doc_alignment_specifiers Alignment specifiers\n * @{ */\n\ntemplate<class T>\nstruct left_\n{\n    T val;\n    size_t width;\n    char pad;\n    left_(T v, size_t w, char p) : val(v), width(w), pad(p) {}\n};\n\ntemplate<class T>\nstruct right_\n{\n    T val;\n    size_t width;\n    char pad;\n    right_(T v, size_t w, char p) : val(v), width(w), pad(p) {}\n};\n\n/** mark an argument to be aligned left */\ntemplate<class T>\nleft_<T> left(T val, size_t width, char padchar=' ')\n{\n    return left_<T>(val, width, padchar);\n}\n\n/** mark an argument to be aligned right */\ntemplate<class T>\nright_<T> right(T val, size_t width, char padchar=' ')\n{\n    return right_<T>(val, width, padchar);\n}\n\n/** @} */ // alignment_specifiers\n\n/** @} */ // format_specifiers\n\n} // namespace fmt\n\n\n/** @ingroup doc_to_chars */\ntemplate<class T>\nsize_t to_chars(substr buf, fmt::left_<T> const& C4_RESTRICT align)\n{\n    size_t ret = to_chars(buf, align.val);\n    if(ret >= buf.len || ret >= align.width)\n        return ret > align.width ? ret : align.width;\n    buf.first(align.width).sub(ret).fill(align.pad);\n    to_chars(buf, align.val);\n    return align.width;\n}\n\n/** @ingroup doc_to_chars */\ntemplate<class T>\nsize_t to_chars(substr buf, fmt::right_<T> const& C4_RESTRICT align)\n{\n    size_t ret = to_chars(buf, align.val);\n    if(ret >= buf.len || ret >= align.width)\n        return ret > align.width ? ret : align.width;\n    size_t rem = static_cast<size_t>(align.width - ret);\n    buf.first(rem).fill(align.pad);\n    to_chars(buf.sub(rem), align.val);\n    return align.width;\n}\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n/** @defgroup doc_cat cat: concatenate arguments to string\n * @{ */\n\n/** @cond dev */\n// terminates the variadic recursion\ninline size_t cat(substr /*buf*/)\n{\n    return 0;\n}\n/** @endcond */\n\n\n/** serialize the arguments, concatenating them to the given fixed-size buffer.\n * The buffer size is strictly respected: no writes will occur beyond its end.\n * @return the number of characters needed to write all the arguments into the buffer.\n * @see c4::catrs() if instead of a fixed-size buffer, a resizeable container is desired\n * @see c4::uncat() for the inverse function\n * @see c4::catsep() if a separator between each argument is to be used\n * @see c4::format() if a format string is desired */\ntemplate<class Arg, class... Args>\nsize_t cat(substr buf, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)\n{\n    size_t num = to_chars(buf, a);\n    buf  = buf.len >= num ? buf.sub(num) : substr{};\n    num += cat(buf, more...);\n    return num;\n}\n\n/** like c4::cat() but return a substr instead of a size */\ntemplate<class... Args>\nsubstr cat_sub(substr buf, Args && ...args)\n{\n    size_t sz = cat(buf, std::forward<Args>(args)...);\n    C4_CHECK(sz <= buf.len);\n    return {buf.str, sz <= buf.len ? sz : buf.len};\n}\n\n/** @} */\n\n\n//-----------------------------------------------------------------------------\n\n\n/** @defgroup doc_uncat uncat: read concatenated arguments from string\n * @{ */\n\n/** @cond dev */\n// terminates the variadic recursion\ninline size_t uncat(csubstr /*buf*/)\n{\n    return 0;\n}\n/** @endcond */\n\n\n/** deserialize the arguments from the given buffer.\n *\n * @return the number of characters read from the buffer, or csubstr::npos\n *   if a conversion was not successful.\n * @see c4::cat(). c4::uncat() is the inverse of c4::cat(). */\ntemplate<class Arg, class... Args>\nsize_t uncat(csubstr buf, Arg & C4_RESTRICT a, Args & C4_RESTRICT ...more)\n{\n    size_t out = from_chars_first(buf, &a);\n    if(C4_UNLIKELY(out == csubstr::npos))\n        return csubstr::npos;\n    buf  = buf.len >= out ? buf.sub(out) : substr{};\n    size_t num = uncat(buf, more...);\n    if(C4_UNLIKELY(num == csubstr::npos))\n        return csubstr::npos;\n    return out + num;\n}\n\n/** @} */\n\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n\n/** @defgroup doc_catsep catsep: cat arguments to string with separator\n * @{ */\n\n/** @cond dev */\nnamespace detail {\ntemplate<class Sep>\nC4_ALWAYS_INLINE size_t catsep_more(substr /*buf*/, Sep const& C4_RESTRICT /*sep*/)\n{\n    return 0;\n}\n\ntemplate<class Sep, class Arg, class... Args>\nsize_t catsep_more(substr buf, Sep const& C4_RESTRICT sep, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)\n{\n    size_t ret = to_chars(buf, sep);\n    size_t num = ret;\n    buf  = buf.len >= ret ? buf.sub(ret) : substr{};\n    ret  = to_chars(buf, a);\n    num += ret;\n    buf  = buf.len >= ret ? buf.sub(ret) : substr{};\n    ret  = catsep_more(buf, sep, more...);\n    num += ret;\n    return num;\n}\n\n\ntemplate<class Sep>\ninline size_t uncatsep_more(csubstr /*buf*/, Sep & /*sep*/)\n{\n    return 0;\n}\n\ntemplate<class Sep, class Arg, class... Args>\nsize_t uncatsep_more(csubstr buf, Sep & C4_RESTRICT sep, Arg & C4_RESTRICT a, Args & C4_RESTRICT ...more)\n{\n    size_t ret = from_chars_first(buf, &sep);\n    size_t num = ret;\n    if(C4_UNLIKELY(ret == csubstr::npos))\n        return csubstr::npos;\n    buf  = buf.len >= ret ? buf.sub(ret) : substr{};\n    ret  = from_chars_first(buf, &a);\n    if(C4_UNLIKELY(ret == csubstr::npos))\n        return csubstr::npos;\n    num += ret;\n    buf  = buf.len >= ret ? buf.sub(ret) : substr{};\n    ret  = uncatsep_more(buf, sep, more...);\n    if(C4_UNLIKELY(ret == csubstr::npos))\n        return csubstr::npos;\n    num += ret;\n    return num;\n}\n\n} // namespace detail\n\ntemplate<class Sep>\nsize_t catsep(substr /*buf*/, Sep const& C4_RESTRICT /*sep*/)\n{\n    return 0;\n}\n/** @endcond */\n\n\n/** serialize the arguments, concatenating them to the given fixed-size\n * buffer, using a separator between each argument.\n * The buffer size is strictly respected: no writes will occur beyond its end.\n * @return the number of characters needed to write all the arguments into the buffer.\n * @see c4::catseprs() if instead of a fixed-size buffer, a resizeable container is desired\n * @see c4::uncatsep() for the inverse function (ie, reading instead of writing)\n * @see c4::cat() if no separator is needed\n * @see c4::format() if a format string is desired */\ntemplate<class Sep, class Arg, class... Args>\nsize_t catsep(substr buf, Sep const& C4_RESTRICT sep, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)\n{\n    size_t num = to_chars(buf, a);\n    buf  = buf.len >= num ? buf.sub(num) : substr{};\n    num += detail::catsep_more(buf, sep, more...);\n    return num;\n}\n\n/** like c4::catsep() but return a substr instead of a size\n * @see c4::catsep(). c4::uncatsep() is the inverse of c4::catsep(). */\ntemplate<class... Args>\nsubstr catsep_sub(substr buf, Args && ...args)\n{\n    size_t sz = catsep(buf, std::forward<Args>(args)...);\n    C4_CHECK(sz <= buf.len);\n    return {buf.str, sz <= buf.len ? sz : buf.len};\n}\n\n/** @} */\n\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n/** @defgroup doc_uncatsep uncatsep: deserialize the separated arguments from a string\n * @{ */\n\n/** deserialize the arguments from the given buffer.\n *\n * @return the number of characters read from the buffer, or csubstr::npos\n *   if a conversion was not successful.\n * @see c4::cat(). c4::uncat() is the inverse of c4::cat(). */\n\n/** deserialize the arguments from the given buffer, using a separator.\n *\n * @return the number of characters read from the buffer, or csubstr::npos\n *   if a conversion was not successful\n * @see c4::catsep(). c4::uncatsep() is the inverse of c4::catsep(). */\ntemplate<class Sep, class Arg, class... Args>\nsize_t uncatsep(csubstr buf, Sep & C4_RESTRICT sep, Arg & C4_RESTRICT a, Args & C4_RESTRICT ...more)\n{\n    size_t ret = from_chars_first(buf, &a), num = ret;\n    if(C4_UNLIKELY(ret == csubstr::npos))\n        return csubstr::npos;\n    buf  = buf.len >= ret ? buf.sub(ret) : substr{};\n    ret  = detail::uncatsep_more(buf, sep, more...);\n    if(C4_UNLIKELY(ret == csubstr::npos))\n        return csubstr::npos;\n    num += ret;\n    return num;\n}\n\n/** @} */\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n/** @defgroup doc_format format: formatted string interpolation\n * @{ */\n\n/// @cond dev\n// terminates the variadic recursion\ninline size_t format(substr buf, csubstr fmt)\n{\n    return to_chars(buf, fmt);\n}\n/// @endcond\n\n\n/** using a format string, serialize the arguments into the given\n * fixed-size buffer.\n * The buffer size is strictly respected: no writes will occur beyond its end.\n * In the format string, each argument is marked with a compact\n * curly-bracket pair: {}. Arguments beyond the last curly bracket pair\n * are silently ignored. For example:\n * @code{.cpp}\n * c4::format(buf, \"the {} drank {} {}\", \"partier\", 5, \"beers\"); // the partier drank 5 beers\n * c4::format(buf, \"the {} drank {} {}\", \"programmer\", 6, \"coffees\"); // the programmer drank 6 coffees\n * @endcode\n * @return the number of characters needed to write into the buffer.\n * @see c4::formatrs() if instead of a fixed-size buffer, a resizeable container is desired\n * @see c4::unformat() for the inverse function\n * @see c4::cat() if no format or separator is needed\n * @see c4::catsep() if no format is needed, but a separator must be used */\ntemplate<class Arg, class... Args>\nsize_t format(substr buf, csubstr fmt, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)\n{\n    size_t pos = fmt.find(\"{}\"); // @todo use _find_fmt()\n    if(C4_UNLIKELY(pos == csubstr::npos))\n        return to_chars(buf, fmt);\n    size_t num = to_chars(buf, fmt.sub(0, pos));\n    size_t out = num;\n    buf  = buf.len >= num ? buf.sub(num) : substr{};\n    num  = to_chars(buf, a);\n    out += num;\n    buf  = buf.len >= num ? buf.sub(num) : substr{};\n    num  = format(buf, fmt.sub(pos + 2), more...);\n    out += num;\n    return out;\n}\n\n/** like c4::format() but return a substr instead of a size\n * @see c4::format()\n * @see c4::catsep(). uncatsep() is the inverse of catsep(). */\ntemplate<class... Args>\nsubstr format_sub(substr buf, csubstr fmt, Args const& C4_RESTRICT ...args)\n{\n    size_t sz = c4::format(buf, fmt, args...);\n    C4_CHECK(sz <= buf.len);\n    return {buf.str, sz <= buf.len ? sz : buf.len};\n}\n\n/** @} */\n\n\n//-----------------------------------------------------------------------------\n\n/** @defgroup doc_unformat unformat: formatted read from string\n * @{ */\n\n/// @cond dev\n// terminates the variadic recursion\ninline size_t unformat(csubstr /*buf*/, csubstr fmt)\n{\n    return fmt.len;\n}\n/// @endcond\n\n\n/** using a format string, deserialize the arguments from the given\n * buffer.\n * @return the number of characters read from the buffer, or npos if a conversion failed.\n * @see c4::format(). c4::unformat() is the inverse function to format(). */\ntemplate<class Arg, class... Args>\nsize_t unformat(csubstr buf, csubstr fmt, Arg & C4_RESTRICT a, Args & C4_RESTRICT ...more)\n{\n    const size_t pos = fmt.find(\"{}\");\n    if(C4_UNLIKELY(pos == csubstr::npos))\n        return unformat(buf, fmt);\n    size_t num = pos;\n    size_t out = num;\n    buf  = buf.len >= num ? buf.sub(num) : substr{};\n    num  = from_chars_first(buf, &a);\n    if(C4_UNLIKELY(num == csubstr::npos))\n        return csubstr::npos;\n    out += num;\n    buf  = buf.len >= num ? buf.sub(num) : substr{};\n    num  = unformat(buf, fmt.sub(pos + 2), more...);\n    if(C4_UNLIKELY(num == csubstr::npos))\n        return csubstr::npos;\n    out += num;\n    return out;\n}\n\n/** @} */\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n/** cat+resize: like c4::cat(), but receives a container, and resizes\n * it as needed to contain the result. The container is\n * overwritten. To append to it, use the append overload.\n * @see c4::cat()\n * @ingroup doc_cat */\ntemplate<class CharOwningContainer, class... Args>\ninline void catrs(CharOwningContainer * C4_RESTRICT cont, Args const& C4_RESTRICT ...args)\n{\nretry:\n    substr buf = to_substr(*cont);\n    size_t ret = cat(buf, args...);\n    cont->resize(ret);\n    if(ret > buf.len)\n        goto retry;\n}\n\n/** cat+resize: like c4::cat(), but creates and returns a new\n * container sized as needed to contain the result.\n * @see c4::cat()\n * @ingroup doc_cat */\ntemplate<class CharOwningContainer, class... Args>\ninline CharOwningContainer catrs(Args const& C4_RESTRICT ...args)\n{\n    CharOwningContainer cont;\n    catrs(&cont, args...);\n    return cont;\n}\n\n/** cat+resize+append: like c4::cat(), but receives a container, and\n * appends to it instead of overwriting it. The container is resized\n * as needed to contain the result.\n *\n * @return the region newly appended to the original container\n * @see c4::cat()\n * @see c4::catrs()\n * @ingroup doc_cat */\ntemplate<class CharOwningContainer, class... Args>\ninline csubstr catrs_append(CharOwningContainer * C4_RESTRICT cont, Args const& C4_RESTRICT ...args)\n{\n    const size_t pos = cont->size();\nretry:\n    substr buf = to_substr(*cont).sub(pos);\n    size_t ret = cat(buf, args...);\n    cont->resize(pos + ret);\n    if(ret > buf.len)\n        goto retry;\n    return to_csubstr(*cont).range(pos, cont->size());\n}\n\n\n//-----------------------------------------------------------------------------\n\n/** catsep+resize: like c4::catsep(), but receives a container, and\n * resizes it as needed to contain the result.  The container is\n * overwritten. To append to the container use the append overload.\n *\n * @see c4::catsep()\n * @ingroup doc_catsep */\ntemplate<class CharOwningContainer, class Sep, class... Args>\ninline void catseprs(CharOwningContainer * C4_RESTRICT cont, Sep const& C4_RESTRICT sep, Args const& C4_RESTRICT ...args)\n{\nretry:\n    substr buf = to_substr(*cont);\n    size_t ret = catsep(buf, sep, args...);\n    cont->resize(ret);\n    if(ret > buf.len)\n        goto retry;\n}\n\n/** catsep+resize: like c4::catsep(), but create a new container with\n * the result.\n *\n * @return the requested container\n * @ingroup doc_catsep */\ntemplate<class CharOwningContainer, class Sep, class... Args>\ninline CharOwningContainer catseprs(Sep const& C4_RESTRICT sep, Args const& C4_RESTRICT ...args)\n{\n    CharOwningContainer cont;\n    catseprs(&cont, sep, args...);\n    return cont;\n}\n\n\n/** catsep+resize+append: like catsep(), but receives a container, and\n * appends the arguments, resizing the container as needed to contain\n * the result. The buffer is appended to.\n *\n * @return a csubstr of the appended part\n * @ingroup formatting_functions\n * @ingroup doc_catsep */\ntemplate<class CharOwningContainer, class Sep, class... Args>\ninline csubstr catseprs_append(CharOwningContainer * C4_RESTRICT cont, Sep const& C4_RESTRICT sep, Args const& C4_RESTRICT ...args)\n{\n    const size_t pos = cont->size();\nretry:\n    substr buf = to_substr(*cont).sub(pos);\n    size_t ret = catsep(buf, sep, args...);\n    cont->resize(pos + ret);\n    if(ret > buf.len)\n        goto retry;\n    return to_csubstr(*cont).range(pos, cont->size());\n}\n\n\n//-----------------------------------------------------------------------------\n\n/** format+resize: like c4::format(), but receives a container, and\n * resizes it as needed to contain the result.  The container is\n * overwritten. To append to the container use the append overload.\n *\n * @see c4::format()\n * @ingroup doc_format */\ntemplate<class CharOwningContainer, class... Args>\ninline void formatrs(CharOwningContainer * C4_RESTRICT cont, csubstr fmt, Args const& C4_RESTRICT ...args)\n{\nretry:\n    substr buf = to_substr(*cont);\n    size_t ret = format(buf, fmt, args...);\n    cont->resize(ret);\n    if(ret > buf.len)\n        goto retry;\n}\n\n/** format+resize: like c4::format(), but create a new container with\n * the result.\n *\n * @return the requested container\n * @ingroup doc_format */\ntemplate<class CharOwningContainer, class... Args>\ninline CharOwningContainer formatrs(csubstr fmt, Args const& C4_RESTRICT ...args)\n{\n    CharOwningContainer cont;\n    formatrs(&cont, fmt, args...);\n    return cont;\n}\n\n/** format+resize+append: like format(), but receives a container, and appends the\n * arguments, resizing the container as needed to contain the\n * result. The buffer is appended to.\n * @return the region newly appended to the original container\n * @ingroup formatting_functions\n * @ingroup doc_format */\ntemplate<class CharOwningContainer, class... Args>\ninline csubstr formatrs_append(CharOwningContainer * C4_RESTRICT cont, csubstr fmt, Args const& C4_RESTRICT ...args)\n{\n    const size_t pos = cont->size();\nretry:\n    substr buf = to_substr(*cont).sub(pos);\n    size_t ret = format(buf, fmt, args...);\n    cont->resize(pos + ret);\n    if(ret > buf.len)\n        goto retry;\n    return to_csubstr(*cont).range(pos, cont->size());\n}\n\n/** @} */\n\n} // namespace c4\n\n#ifdef _MSC_VER\n#   pragma warning(pop)\n#elif defined(__clang__)\n#   pragma clang diagnostic pop\n#elif defined(__GNUC__)\n#   pragma GCC diagnostic pop\n#endif\n\n#endif /* _C4_FORMAT_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/gcc-4.8.hpp",
    "content": "#ifndef _C4_GCC_4_8_HPP_\n#define _C4_GCC_4_8_HPP_\n\n#if __GNUC__ == 4 && __GNUC_MINOR__ >= 8\n/* STL polyfills for old GNU compilers */\n\n_Pragma(\"GCC diagnostic ignored \\\"-Wshadow\\\"\")\n_Pragma(\"GCC diagnostic ignored \\\"-Wmissing-field-initializers\\\"\")\n\n#if __cplusplus\n#include <cstdint>\n#include <type_traits>\n\nnamespace std {\n\ntemplate<typename _Tp>\nstruct is_trivially_copyable : public integral_constant<bool,\n    is_destructible<_Tp>::value && __has_trivial_destructor(_Tp) &&\n    (__has_trivial_constructor(_Tp) || __has_trivial_copy(_Tp) || __has_trivial_assign(_Tp))>\n{ };\n\ntemplate<typename _Tp>\nusing is_trivially_copy_constructible = has_trivial_copy_constructor<_Tp>;\n\ntemplate<typename _Tp>\nusing is_trivially_default_constructible = has_trivial_default_constructor<_Tp>;\n\ntemplate<typename _Tp>\nusing is_trivially_copy_assignable = has_trivial_copy_assign<_Tp>;\n\n/* not supported */\ntemplate<typename _Tp>\nstruct is_trivially_move_constructible : false_type\n{ };\n\n/* not supported */\ntemplate<typename _Tp>\nstruct is_trivially_move_assignable : false_type\n{ };\n\ninline void *align(size_t __align, size_t __size, void*& __ptr, size_t& __space) noexcept\n{\n    if (__space < __size)\n        return nullptr;\n    const auto __intptr = reinterpret_cast<uintptr_t>(__ptr);\n    const auto __aligned = (__intptr - 1u + __align) & -__align;\n    const auto __diff = __aligned - __intptr;\n    if (__diff > (__space - __size))\n        return nullptr;\n    else\n    {\n        __space -= __diff;\n        return __ptr = reinterpret_cast<void*>(__aligned);\n    }\n}\n\n#if __GNUC__ == 4 && __GNUC_MINOR__ == 8\ntypedef long double max_align_t ;\n#endif\n\n}\n#else // __cplusplus\n\n#include <string.h>\n// see https://sourceware.org/bugzilla/show_bug.cgi?id=25399 (ubuntu gcc-4.8)\n#define memset(s, c, count) __builtin_memset(s, c, count)\n\n#endif // __cplusplus\n\n#endif // __GNUC__ == 4 && __GNUC_MINOR__ >= 8\n\n#endif // _C4_GCC_4_8_HPP_\n"
  },
  {
    "path": "libs/rapidyaml/c4/hash.hpp",
    "content": "#ifndef _C4_HASH_HPP_\n#define _C4_HASH_HPP_\n\n#include \"c4/config.hpp\"\n#include <climits>\n\n/** @file hash.hpp */\n\n/** @defgroup hash Hash utils\n * @see http://aras-p.info/blog/2016/08/02/Hash-Functions-all-the-way-down/ */\n\nnamespace c4 {\n\nnamespace detail {\n\n/** @internal\n * @ingroup hash\n * @see this was taken a great answer in stackoverflow:\n * https://stackoverflow.com/a/34597785/5875572\n * @see http://aras-p.info/blog/2016/08/02/Hash-Functions-all-the-way-down/ */\ntemplate<typename ResultT, ResultT OffsetBasis, ResultT Prime>\nclass basic_fnv1a final\n{\n\n  static_assert(std::is_unsigned<ResultT>::value, \"need unsigned integer\");\n\npublic:\n\n    using result_type = ResultT;\n\nprivate:\n\n    result_type state_ {};\n\npublic:\n\n    C4_CONSTEXPR14 basic_fnv1a() noexcept : state_ {OffsetBasis} {}\n\n    C4_CONSTEXPR14 void update(const void *const data, const size_t size) noexcept\n    {\n        auto cdata = static_cast<const unsigned char *>(data);\n        auto acc = this->state_;\n        for(size_t i = 0; i < size; ++i)\n        {\n            const auto next = size_t(cdata[i]);\n            acc = (acc ^ next) * Prime;\n        }\n        this->state_ = acc;\n    }\n\n    C4_CONSTEXPR14 result_type digest() const noexcept\n    {\n        return this->state_;\n    }\n\n};\n\nusing fnv1a_32 = basic_fnv1a<uint32_t, UINT32_C(          2166136261), UINT32_C(     16777619)>;\nusing fnv1a_64 = basic_fnv1a<uint64_t, UINT64_C(14695981039346656037), UINT64_C(1099511628211)>;\n\ntemplate<size_t Bits> struct fnv1a;\ntemplate<> struct fnv1a<32> { using type = fnv1a_32; };\ntemplate<> struct fnv1a<64> { using type = fnv1a_64; };\n\n} // namespace detail\n\n\n/** @ingroup hash */\ntemplate<size_t Bits>\nusing fnv1a_t = typename detail::fnv1a<Bits>::type;\n\n\n/** @ingroup hash */\nC4_CONSTEXPR14 inline size_t hash_bytes(const void *const data, const size_t size) noexcept\n{\n    fnv1a_t<CHAR_BIT * sizeof(size_t)> fn{};\n    fn.update(data, size);\n    return fn.digest();\n}\n\n/**\n * @overload hash_bytes\n * @ingroup hash */\ntemplate<size_t N>\nC4_CONSTEXPR14 inline size_t hash_bytes(const char (&str)[N]) noexcept\n{\n    fnv1a_t<CHAR_BIT * sizeof(size_t)> fn{};\n    fn.update(str, N);\n    return fn.digest();\n}\n\n} // namespace c4\n\n\n#endif // _C4_HASH_HPP_\n"
  },
  {
    "path": "libs/rapidyaml/c4/language.cpp",
    "content": "#include \"c4/language.hpp\"\n\nnamespace c4 {\nnamespace detail {\n\n#ifndef __GNUC__\nvoid use_char_pointer(char const volatile* v)\n{\n    C4_UNUSED(v);\n}\n#else\nvoid foo() {} // to avoid empty file warning from the linker\n#endif\n\n} // namespace detail\n} // namespace c4\n"
  },
  {
    "path": "libs/rapidyaml/c4/language.hpp",
    "content": "#ifndef _C4_LANGUAGE_HPP_\n#define _C4_LANGUAGE_HPP_\n\n/** @file language.hpp Provides language standard information macros and\n * compiler agnostic utility macros: namespace facilities, function attributes,\n * variable attributes, etc.\n * @ingroup basic_headers */\n\n#include \"c4/preprocessor.hpp\"\n#include \"c4/compiler.hpp\"\n\n/* Detect C++ standard.\n * @see http://stackoverflow.com/a/7132549/5875572 */\n#ifndef C4_CPP\n#   if defined(_MSC_VER) && !defined(__clang__)\n#       if _MSC_VER >= 1910  // >VS2015: VS2017, VS2019, VS2022\n#           if (!defined(_MSVC_LANG))\n#               error _MSVC not defined\n#           endif\n#           if _MSVC_LANG >= 201705L\n#               define C4_CPP 20\n#               define C4_CPP20\n#           elif _MSVC_LANG == 201703L\n#               define C4_CPP 17\n#               define C4_CPP17\n#           elif _MSVC_LANG >= 201402L\n#               define C4_CPP 14\n#               define C4_CPP14\n#           elif _MSVC_LANG >= 201103L\n#               define C4_CPP 11\n#               define C4_CPP11\n#           else\n#               error C++ lesser than C++11 not supported\n#           endif\n#       else\n#           if _MSC_VER == 1900\n#               define C4_CPP 14  // VS2015 is c++14 https://devblogs.microsoft.com/cppblog/c111417-features-in-vs-2015-rtm/\n#               define C4_CPP14\n#           elif _MSC_VER == 1800 // VS2013\n#               define C4_CPP 11\n#               define C4_CPP11\n#           else\n#               error C++ lesser than C++11 not supported\n#           endif\n#       endif\n#   elif defined(__INTEL_COMPILER) // https://software.intel.com/en-us/node/524490\n#       ifdef __INTEL_CXX20_MODE__ // not sure about this\n#           define C4_CPP 20\n#           define C4_CPP20\n#       elif defined __INTEL_CXX17_MODE__ // not sure about this\n#           define C4_CPP 17\n#           define C4_CPP17\n#       elif defined __INTEL_CXX14_MODE__ // not sure about this\n#           define C4_CPP 14\n#           define C4_CPP14\n#       elif defined __INTEL_CXX11_MODE__\n#           define C4_CPP 11\n#           define C4_CPP11\n#       else\n#           error C++ lesser than C++11 not supported\n#       endif\n#   else\n#       ifndef __cplusplus\n#           error __cplusplus is not defined?\n#       endif\n#       if __cplusplus == 1\n#           error cannot handle __cplusplus==1\n#       elif __cplusplus >= 201709L\n#           define C4_CPP 20\n#           define C4_CPP20\n#       elif __cplusplus >= 201703L\n#           define C4_CPP 17\n#           define C4_CPP17\n#       elif __cplusplus >= 201402L\n#           define C4_CPP 14\n#           define C4_CPP14\n#       elif __cplusplus >= 201103L\n#           define C4_CPP 11\n#           define C4_CPP11\n#       elif __cplusplus >= 199711L\n#           error C++ lesser than C++11 not supported\n#       endif\n#   endif\n#else\n#   ifdef C4_CPP == 20\n#       define C4_CPP20\n#   elif C4_CPP == 17\n#       define C4_CPP17\n#   elif C4_CPP == 14\n#       define C4_CPP14\n#   elif C4_CPP == 11\n#       define C4_CPP11\n#   elif C4_CPP == 98\n#       define C4_CPP98\n#       error C++ lesser than C++11 not supported\n#   else\n#       error C4_CPP must be one of 20, 17, 14, 11, 98\n#   endif\n#endif\n\n#ifdef C4_CPP20\n#   define C4_CPP17\n#   define C4_CPP14\n#   define C4_CPP11\n#elif defined(C4_CPP17)\n#   define C4_CPP14\n#   define C4_CPP11\n#elif defined(C4_CPP14)\n#   define C4_CPP11\n#endif\n\n/** lifted from this answer: http://stackoverflow.com/a/20170989/5875572 */\n#if defined(_MSC_VER) && !defined(__clang__)\n#  if _MSC_VER < 1900\n#    define C4_CONSTEXPR11\n#    define C4_CONSTEXPR14\n#  elif _MSC_VER < 2000\n#    define C4_CONSTEXPR11 constexpr\n#    define C4_CONSTEXPR14\n#  else\n#    define C4_CONSTEXPR11 constexpr\n#    define C4_CONSTEXPR14 constexpr\n#  endif\n#else\n#  if __cplusplus < 201103\n#    define C4_CONSTEXPR11\n#    define C4_CONSTEXPR14\n#  elif __cplusplus == 201103\n#    define C4_CONSTEXPR11 constexpr\n#    define C4_CONSTEXPR14\n#  else\n#    define C4_CONSTEXPR11 constexpr\n#    define C4_CONSTEXPR14 constexpr\n#  endif\n#endif  // _MSC_VER\n\n\n#if C4_CPP < 17\n#define C4_IF_CONSTEXPR\n#define C4_INLINE_CONSTEXPR constexpr\n#else\n#define C4_IF_CONSTEXPR constexpr\n#define C4_INLINE_CONSTEXPR inline constexpr\n#endif\n\n#if defined(_MSC_VER) && !defined(__clang__)\n#  if (defined(_CPPUNWIND) && (_CPPUNWIND == 1))\n#    define C4_EXCEPTIONS\n#  endif\n#else\n#  if defined(__EXCEPTIONS) || defined(__cpp_exceptions)\n#    define C4_EXCEPTIONS\n#  endif\n#endif\n\n#ifdef C4_EXCEPTIONS\n#  define C4_IF_EXCEPTIONS_(exc_code, setjmp_code) exc_code\n#  define C4_IF_EXCEPTIONS(exc_code, setjmp_code) do { exc_code } while(0)\n#else\n#  define C4_IF_EXCEPTIONS_(exc_code, setjmp_code) setjmp_code\n#  define C4_IF_EXCEPTIONS(exc_code, setjmp_code) do { setjmp_code } while(0)\n#endif\n\n#if defined(_MSC_VER) && !defined(__clang__)\n#  if defined(_CPPRTTI)\n#    define C4_RTTI\n#  endif\n#else\n#  if defined(__GXX_RTTI)\n#    define C4_RTTI\n#  endif\n#endif\n\n#ifdef C4_RTTI\n#  define C4_IF_RTTI_(code_rtti, code_no_rtti) code_rtti\n#  define C4_IF_RTTI(code_rtti, code_no_rtti) do { code_rtti } while(0)\n#else\n#  define C4_IF_RTTI_(code_rtti, code_no_rtti) code_no_rtti\n#  define C4_IF_RTTI(code_rtti, code_no_rtti) do { code_no_rtti } while(0)\n#endif\n\n\n//------------------------------------------------------------\n\n#define _C4_BEGIN_NAMESPACE(ns) namespace ns {\n#define _C4_END_NAMESPACE(ns)   }\n\n// MSVC cant handle the C4_FOR_EACH macro... need to fix this\n//#define C4_BEGIN_NAMESPACE(...) C4_FOR_EACH_SEP(_C4_BEGIN_NAMESPACE, , __VA_ARGS__)\n//#define C4_END_NAMESPACE(...) C4_FOR_EACH_SEP(_C4_END_NAMESPACE, , __VA_ARGS__)\n#define C4_BEGIN_NAMESPACE(ns) namespace ns {\n#define C4_END_NAMESPACE(ns) }\n\n#define C4_BEGIN_HIDDEN_NAMESPACE namespace /*hidden*/ {\n#define C4_END_HIDDEN_NAMESPACE } /* namespace hidden */\n\n//------------------------------------------------------------\n\n#ifndef C4_API\n#   if defined(_MSC_VER) && !defined(__clang__)\n#       if defined(C4_EXPORT)\n#           define C4_API __declspec(dllexport)\n#       elif defined(C4_IMPORT)\n#           define C4_API __declspec(dllimport)\n#       else\n#           define C4_API\n#       endif\n#   else\n#       define C4_API\n#   endif\n#endif\n\n#if defined(_MSC_VER) && !defined(__clang__)\n#   define C4_RESTRICT __restrict\n#   define C4_RESTRICT_FN __declspec(restrict)\n#   define C4_NO_INLINE __declspec(noinline)\n#   define C4_ALWAYS_INLINE inline __forceinline\n/** these are not available in VS AFAIK */\n#   define C4_CONST\n#   define C4_PURE\n#   define C4_FLATTEN\n#   define C4_HOT         /** @todo */\n#   define C4_COLD        /** @todo */\n#   define C4_ASSUME(...) __assume(__VA_ARGS__)\n#   define C4_EXPECT(x, y) x /** @todo */\n#   define C4_LIKELY(x)   x\n#   define C4_UNLIKELY(x) x\n#   define C4_UNREACHABLE() _c4_msvc_unreachable()\n#   define C4_ATTR_FORMAT(...) /** */\n#   define C4_NORETURN [[noreturn]]\n#   if _MSC_VER >= 1700 // VS2012\n#       define C4_NODISCARD _Check_return_\n#   else\n#       define C4_NODISCARD\n#   endif\n[[noreturn]] __forceinline void _c4_msvc_unreachable() { __assume(false); } ///< https://stackoverflow.com/questions/60802864/emulating-gccs-builtin-unreachable-in-visual-studio\n#   define C4_UNREACHABLE_AFTER_ERR() /* */\n#else\n    ///< @todo assuming gcc-like compiler. check it is actually so.\n/** for function attributes in GCC,\n * @see https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes */\n/** for __builtin functions in GCC,\n * @see https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html */\n#   define C4_RESTRICT __restrict__\n#   define C4_RESTRICT_FN __attribute__((restrict))\n#   define C4_NO_INLINE __attribute__((noinline))\n#   define C4_ALWAYS_INLINE inline __attribute__((always_inline))\n#   define C4_CONST __attribute__((const))\n#   define C4_PURE __attribute__((pure))\n/** force inlining of every callee function */\n#   define C4_FLATTEN __atribute__((flatten))\n/** mark a function as hot, ie as having a visible impact in CPU time\n * thus making it more likely to inline, etc\n * @see http://stackoverflow.com/questions/15028990/semantics-of-gcc-hot-attribute */\n#   define C4_HOT __attribute__((hot))\n/** mark a function as cold, ie as NOT having a visible impact in CPU time\n * @see http://stackoverflow.com/questions/15028990/semantics-of-gcc-hot-attribute */\n#   define C4_COLD __attribute__((cold))\n#   define C4_EXPECT(x, y) __builtin_expect(x, y) ///< @see https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html\n#   define C4_LIKELY(x)   __builtin_expect(x, 1)\n#   define C4_UNLIKELY(x) __builtin_expect(x, 0)\n#   define C4_UNREACHABLE() __builtin_unreachable()\n#   define C4_ATTR_FORMAT(...) //__attribute__((format (__VA_ARGS__))) ///< @see https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes\n#   define C4_NORETURN __attribute__((noreturn))\n#   define C4_NODISCARD __attribute__((warn_unused_result))\n#   define C4_UNREACHABLE_AFTER_ERR() C4_UNREACHABLE()\n// C4_ASSUME\n// see https://stackoverflow.com/questions/63493968/reproducing-clangs-builtin-assume-for-gcc\n// preferred option: C++ standard attribute\n#   ifdef __has_cpp_attribute\n#       if __has_cpp_attribute(assume) >= 202207L\n#           define C4_ASSUME(...) [[assume(__VA_ARGS__)]]\n#       endif\n#   endif\n// first fallback: compiler intrinsics/attributes for assumptions\n#   ifndef C4_ASSUME\n#       if defined(__clang__)\n#           define C4_ASSUME(...) __builtin_assume(__VA_ARGS__)\n#       elif defined(__GNUC__)\n#       if __GNUC__ >= 13\n#           define C4_ASSUME(...) __attribute__((__assume__(__VA_ARGS__)))\n#       endif\n#       endif\n#   endif\n// second fallback: possibly evaluating uses of unreachable()\n// Set this to 1 if you want to allow assumptions to possibly evaluate.\n#   ifndef C4_ASSUME_ALLOW_EVAL\n#       define C4_ASSUME_ALLOW_EVAL 0\n#   endif\n#   if !defined(C4_ASSUME) && (C4_ASSUME_ALLOW_EVAL)\n#       define C4_ASSUME(...) do { if (!bool(__VA_ARGS__)) C4_UNREACHABLE(); ) while(0)\n#   endif\n// last fallback: define macro as doing nothing\n#   ifndef C4_ASSUME\n#       define C4_ASSUME(...)\n#   endif\n#endif\n\n\n#if C4_CPP >= 14\n#   define C4_DEPRECATED(msg) [[deprecated(msg)]]\n#else\n#   if defined(_MSC_VER)\n#       define C4_DEPRECATED(msg) __declspec(deprecated(msg))\n#   else // defined(__GNUC__) || defined(__clang__)\n#       define C4_DEPRECATED(msg) __attribute__((deprecated(msg)))\n#   endif\n#endif\n\n\n#ifdef _MSC_VER\n#   define C4_FUNC __FUNCTION__\n#   define C4_PRETTY_FUNC __FUNCSIG__\n#else /// @todo assuming gcc-like compiler. check it is actually so.\n#   define C4_FUNC __FUNCTION__\n#   define C4_PRETTY_FUNC __PRETTY_FUNCTION__\n#endif\n\n/** prevent compiler warnings about a specific var being unused */\n#define C4_UNUSED(var) (void)var\n\n#if C4_CPP >= 17\n#define C4_STATIC_ASSERT(cond) static_assert(cond)\n#else\n#define C4_STATIC_ASSERT(cond) static_assert((cond), #cond)\n#endif\n#define C4_STATIC_ASSERT_MSG(cond, msg) static_assert((cond), #cond \": \" msg)\n\n/** @def C4_DONT_OPTIMIZE idea lifted from GoogleBenchmark.\n * @see https://github.com/google/benchmark/blob/master/include/benchmark/benchmark_api.h */\nnamespace c4 {\nnamespace detail {\n#ifdef __GNUC__\n#   define C4_DONT_OPTIMIZE(var) c4::detail::dont_optimize(var)\ntemplate< class T >\nC4_ALWAYS_INLINE void dont_optimize(T const& value) { asm volatile(\"\" : : \"g\"(value) : \"memory\"); }\n#else\n#   define C4_DONT_OPTIMIZE(var) c4::detail::use_char_pointer(reinterpret_cast< const char* >(&var))\nvoid use_char_pointer(char const volatile*);\n#endif\n} // namespace detail\n} // namespace c4\n\n/** @def C4_KEEP_EMPTY_LOOP prevent an empty loop from being optimized out.\n * @see http://stackoverflow.com/a/7084193/5875572 */\n#if defined(_MSC_VER) && !defined(__clang__)\n#   define C4_KEEP_EMPTY_LOOP { char c; C4_DONT_OPTIMIZE(c); }\n#else\n#   define C4_KEEP_EMPTY_LOOP { asm(\"\"); }\n#endif\n\n/** @def C4_VA_LIST_REUSE_MUST_COPY\n * @todo <jpmag> I strongly suspect that this is actually only in UNIX platforms. revisit this. */\n#ifdef __GNUC__\n#   define C4_VA_LIST_REUSE_MUST_COPY\n#endif\n\n#endif /* _C4_LANGUAGE_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/memory_resource.cpp",
    "content": "#include \"c4/memory_resource.hpp\"\n#include \"c4/memory_util.hpp\"\n\n#include <stdlib.h>\n#include <string.h>\n#if defined(C4_POSIX) || defined(C4_IOS) || defined(C4_MACOS) || defined(C4_ARM)\n#   include <errno.h>\n#endif\n#if defined(C4_ARM)\n#   include <malloc.h>\n#endif\n\n#include <memory>\n\nnamespace c4 {\n\nC4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH(\"-Wold-style-cast\")\n\nnamespace detail {\n\n\n#ifdef C4_NO_ALLOC_DEFAULTS\naalloc_pfn s_aalloc = nullptr;\nfree_pfn s_afree = nullptr;\narealloc_pfn s_arealloc = nullptr;\n#else\n\n\nvoid afree_impl(void *ptr)\n{\n#if defined(C4_WIN) || defined(C4_XBOX)\n    ::_aligned_free(ptr);\n#else\n    ::free(ptr);\n#endif\n}\n\n\nvoid* aalloc_impl(size_t size, size_t alignment)\n{\n    // alignment must be nonzero and a power of 2\n    C4_CHECK(alignment > 0 && (alignment & (alignment - 1u)) == 0);\n    // NOTE: alignment needs to be sized in multiples of sizeof(void*)\n    if(C4_UNLIKELY(alignment < sizeof(void*)))\n        alignment = sizeof(void*);\n    static_assert((sizeof(void*) & (sizeof(void*)-1u)) == 0, \"sizeof(void*) must be a power of 2\");\n    C4_CHECK(((alignment & (sizeof(void*) - 1u))) == 0u);\n    void *mem;\n#if defined(C4_WIN) || defined(C4_XBOX)\n    mem = ::_aligned_malloc(size, alignment);\n    C4_CHECK(mem != nullptr || size == 0);\n#elif defined(C4_POSIX) || defined(C4_IOS) || defined(C4_MACOS)\n    int ret = ::posix_memalign(&mem, alignment, size);\n    if(C4_UNLIKELY(ret))\n    {\n        C4_ASSERT(ret != EINVAL); // this was already handled above\n        if(ret == ENOMEM)\n        {\n            C4_ERROR(\"There was insufficient memory to fulfill the \"\n                     \"allocation request of %zu bytes (alignment=%lu)\", size, size);\n        }\n        return nullptr;\n    }\n#elif defined(C4_ARM) || defined(C4_ANDROID)\n    // https://stackoverflow.com/questions/53614538/undefined-reference-to-posix-memalign-in-arm-gcc\n    // https://electronics.stackexchange.com/questions/467382/e2-studio-undefined-reference-to-posix-memalign/467753\n    mem = memalign(alignment, size);\n    C4_CHECK(mem != nullptr || size == 0);\n#else\n    (void)size;\n    (void)alignment;\n    mem = nullptr;\n    C4_NOT_IMPLEMENTED_MSG(\"need to implement an aligned allocation for this platform\");\n#endif\n    C4_ASSERT_MSG((uintptr_t(mem) & (alignment-1)) == 0, \"address %p is not aligned to %zu boundary\", mem, alignment);\n    return mem;\n}\n\n\nvoid* arealloc_impl(void* ptr, size_t oldsz, size_t newsz, size_t alignment)\n{\n    /** @todo make this more efficient\n     * @see https://stackoverflow.com/questions/9078259/does-realloc-keep-the-memory-alignment-of-posix-memalign\n     * @see look for qReallocAligned() in http://code.qt.io/cgit/qt/qtbase.git/tree/src/corelib/global/qmalloc.cpp\n     */\n    void *tmp = aalloc(newsz, alignment);\n    size_t min = newsz < oldsz ? newsz : oldsz;\n    if(mem_overlaps(ptr, tmp, oldsz, newsz))\n    {\n        ::memmove(tmp, ptr, min);\n    }\n    else\n    {\n        ::memcpy(tmp, ptr, min);\n    }\n    afree(ptr);\n    return tmp;\n}\n\naalloc_pfn s_aalloc = aalloc_impl;\nafree_pfn s_afree = afree_impl;\narealloc_pfn s_arealloc = arealloc_impl;\n\n#endif // C4_NO_ALLOC_DEFAULTS\n\n} // namespace detail\n\n\naalloc_pfn get_aalloc()\n{\n    return detail::s_aalloc;\n}\nvoid set_aalloc(aalloc_pfn fn)\n{\n    detail::s_aalloc = fn;\n}\n\nafree_pfn get_afree()\n{\n    return detail::s_afree;\n}\nvoid set_afree(afree_pfn fn)\n{\n    detail::s_afree = fn;\n}\n\narealloc_pfn get_arealloc()\n{\n    return detail::s_arealloc;\n}\nvoid set_arealloc(arealloc_pfn fn)\n{\n    detail::s_arealloc = fn;\n}\n\n\nvoid* aalloc(size_t sz, size_t alignment)\n{\n    C4_ASSERT_MSG(c4::get_aalloc() != nullptr, \"did you forget to call set_aalloc()?\");\n    auto fn = c4::get_aalloc();\n    void* ptr = fn(sz, alignment);\n    return ptr;\n}\n\nvoid afree(void* ptr)\n{\n    C4_ASSERT_MSG(c4::get_afree() != nullptr, \"did you forget to call set_afree()?\");\n    auto fn = c4::get_afree();\n    fn(ptr);\n}\n\nvoid* arealloc(void *ptr, size_t oldsz, size_t newsz, size_t alignment)\n{\n    C4_ASSERT_MSG(c4::get_arealloc() != nullptr, \"did you forget to call set_arealloc()?\");\n    auto fn = c4::get_arealloc();\n    void* nptr = fn(ptr, oldsz, newsz, alignment);\n    return nptr;\n}\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\nvoid detail::_MemoryResourceSingleChunk::release()\n{\n    if(m_mem && m_owner)\n    {\n        impl_type::deallocate(m_mem, m_size);\n    }\n    m_mem = nullptr;\n    m_size = 0;\n    m_owner = false;\n    m_pos = 0;\n}\n\nvoid detail::_MemoryResourceSingleChunk::acquire(size_t sz)\n{\n    clear();\n    m_owner = true;\n    m_mem = (char*) impl_type::allocate(sz, alignof(max_align_t));\n    m_size = sz;\n    m_pos = 0;\n}\n\nvoid detail::_MemoryResourceSingleChunk::acquire(void *mem, size_t sz)\n{\n    clear();\n    m_owner = false;\n    m_mem = (char*) mem;\n    m_size = sz;\n    m_pos = 0;\n}\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\nvoid* MemoryResourceLinear::do_allocate(size_t sz, size_t alignment, void *hint)\n{\n    C4_UNUSED(hint);\n    if(sz == 0) return nullptr;\n    // make sure there's enough room to allocate\n    if(m_pos + sz > m_size)\n    {\n        C4_ERROR(\"out of memory\");\n    }\n    void *mem = m_mem + m_pos;\n    size_t space = m_size - m_pos;\n    if(std::align(alignment, sz, mem, space))\n    {\n        C4_ASSERT(m_pos <= m_size);\n        C4_ASSERT(m_size - m_pos >= space);\n        m_pos += (m_size - m_pos) - space;\n        m_pos += sz;\n        C4_ASSERT(m_pos <= m_size);\n    }\n    else\n    {\n        C4_ERROR(\"could not align memory\");\n    }\n    return mem;\n}\n\nvoid MemoryResourceLinear::do_deallocate(void* ptr, size_t sz, size_t alignment)\n{\n    C4_UNUSED(ptr);\n    C4_UNUSED(sz);\n    C4_UNUSED(alignment);\n    // nothing to do!!\n}\n\nvoid* MemoryResourceLinear::do_reallocate(void* ptr, size_t oldsz, size_t newsz, size_t alignment)\n{\n    if(newsz == oldsz) return ptr;\n    // is ptr the most recently allocated (MRA) block?\n    char *cptr = (char*)ptr;\n    bool same_pos = (m_mem + m_pos == cptr + oldsz);\n    // no need to get more memory when shrinking\n    if(newsz < oldsz)\n    {\n        // if this is the MRA, we can safely shrink the position\n        if(same_pos)\n        {\n            m_pos -= oldsz - newsz;\n        }\n        return ptr;\n    }\n    // we're growing the block, and it fits in size\n    else if(same_pos && cptr + newsz <= m_mem + m_size)\n    {\n        // if this is the MRA, we can safely shrink the position\n        m_pos += newsz - oldsz;\n        return ptr;\n    }\n    // we're growing the block or it doesn't fit -\n    // delegate any of these situations to do_deallocate()\n    return do_allocate(newsz, alignment, ptr);\n}\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n/** @todo add a free list allocator. A good candidate because of its\n * small size is TLSF.\n *\n * @see https://github.com/mattconte/tlsf\n *\n * Comparisons:\n *\n * @see https://www.researchgate.net/publication/262375150_A_Comparative_Study_on_Memory_Allocators_in_Multicore_and_Multithreaded_Applications_-_SBESC_2011_-_Presentation_Slides\n * @see http://webkit.sed.hu/blog/20100324/war-allocators-tlsf-action\n * @see https://github.com/emeryberger/Malloc-Implementations/tree/master/allocators\n *\n * */\n\nC4_SUPPRESS_WARNING_GCC_CLANG_POP\n\n} // namespace c4\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n#ifdef C4_REDEFINE_CPPNEW\n#include <new>\nvoid* operator new(size_t size)\n{\n    auto *mr = ::c4::get_memory_resource();\n    return mr->allocate(size);\n}\nvoid operator delete(void *p) noexcept\n{\n    C4_NEVER_REACH();\n}\nvoid operator delete(void *p, size_t size)\n{\n    auto *mr = ::c4::get_memory_resource();\n    mr->deallocate(p, size);\n}\nvoid* operator new[](size_t size)\n{\n    return operator new(size);\n}\nvoid operator delete[](void *p) noexcept\n{\n    operator delete(p);\n}\nvoid operator delete[](void *p, size_t size)\n{\n    operator delete(p, size);\n}\nvoid* operator new(size_t size, std::nothrow_t)\n{\n    return operator new(size);\n}\nvoid operator delete(void *p, std::nothrow_t)\n{\n    operator delete(p);\n}\nvoid operator delete(void *p, size_t size, std::nothrow_t)\n{\n    operator delete(p, size);\n}\nvoid* operator new[](size_t size, std::nothrow_t)\n{\n    return operator new(size);\n}\nvoid operator delete[](void *p, std::nothrow_t)\n{\n    operator delete(p);\n}\nvoid operator delete[](void *p, size_t, std::nothrow_t)\n{\n    operator delete(p, size);\n}\n#endif // C4_REDEFINE_CPPNEW\n"
  },
  {
    "path": "libs/rapidyaml/c4/memory_resource.hpp",
    "content": "#ifndef _C4_MEMORY_RESOURCE_HPP_\n#define _C4_MEMORY_RESOURCE_HPP_\n\n/** @file memory_resource.hpp Provides facilities to allocate typeless\n *  memory, via the memory resource model consecrated with C++17. */\n\n/** @defgroup memory memory utilities */\n\n/** @defgroup raw_memory_alloc Raw memory allocation\n * @ingroup memory\n */\n\n/** @defgroup memory_resources Memory resources\n * @ingroup memory\n */\n\n#include \"c4/config.hpp\"\n#include \"c4/error.hpp\"\n\nnamespace c4 {\n\n// need these forward decls here\nstruct MemoryResource;\nstruct MemoryResourceMalloc;\nstruct MemoryResourceStack;\nMemoryResourceMalloc* get_memory_resource_malloc();\nMemoryResourceStack* get_memory_resource_stack();\nnamespace detail { MemoryResource*& get_memory_resource(); }\n\n\n// c-style allocation ---------------------------------------------------------\n\n// this API provides aligned allocation functions.\n// These functions forward the call to a user-modifiable function.\n\n\n// aligned allocation.\n\n/** Aligned allocation. Merely calls the current get_aalloc() function.\n * @see get_aalloc()\n * @ingroup raw_memory_alloc */\nvoid* aalloc(size_t sz, size_t alignment);\n\n/** Aligned free. Merely calls the current get_afree() function.\n * @see get_afree()\n * @ingroup raw_memory_alloc */\nvoid afree(void* ptr);\n\n/** Aligned reallocation. Merely calls the current get_arealloc() function.\n * @see get_arealloc()\n * @ingroup raw_memory_alloc */\nvoid* arealloc(void* ptr, size_t oldsz, size_t newsz, size_t alignment);\n\n\n// allocation setup facilities.\n\n/** Function pointer type for aligned allocation\n * @see set_aalloc()\n * @ingroup raw_memory_alloc */\nusing aalloc_pfn = void* (*)(size_t size, size_t alignment);\n\n/** Function pointer type for aligned deallocation\n * @see set_afree()\n * @ingroup raw_memory_alloc */\nusing afree_pfn = void  (*)(void *ptr);\n\n/** Function pointer type for aligned reallocation\n * @see set_arealloc()\n * @ingroup raw_memory_alloc */\nusing arealloc_pfn = void* (*)(void *ptr, size_t oldsz, size_t newsz, size_t alignment);\n\n\n// allocation function pointer setters/getters\n\n/** Set the global aligned allocation function.\n * @see aalloc()\n * @see get_aalloc()\n * @ingroup raw_memory_alloc */\nvoid set_aalloc(aalloc_pfn fn);\n\n/** Set the global aligned deallocation function.\n * @see afree()\n * @see get_afree()\n * @ingroup raw_memory_alloc */\nvoid set_afree(afree_pfn fn);\n\n/** Set the global aligned reallocation function.\n * @see arealloc()\n * @see get_arealloc()\n * @ingroup raw_memory_alloc */\nvoid set_arealloc(arealloc_pfn fn);\n\n\n/** Get the global aligned reallocation function.\n * @see arealloc()\n * @ingroup raw_memory_alloc */\naalloc_pfn get_aalloc();\n\n/** Get the global aligned deallocation function.\n * @see afree()\n * @ingroup raw_memory_alloc */\nafree_pfn get_afree();\n\n/** Get the global aligned reallocation function.\n * @see arealloc()\n * @ingroup raw_memory_alloc */\narealloc_pfn get_arealloc();\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n// c++-style allocation -------------------------------------------------------\n\n/** C++17-style memory_resource base class. See http://en.cppreference.com/w/cpp/experimental/memory_resource\n * @ingroup memory_resources */\nstruct MemoryResource\n{\n    const char *name = nullptr;\n    virtual ~MemoryResource() {}\n\n    void* allocate(size_t sz, size_t alignment=alignof(max_align_t), void *hint=nullptr)\n    {\n        void *mem = this->do_allocate(sz, alignment, hint);\n        C4_CHECK_MSG(mem != nullptr, \"could not allocate %lu bytes\", sz);\n        return mem;\n    }\n\n    void* reallocate(void* ptr, size_t oldsz, size_t newsz, size_t alignment=alignof(max_align_t))\n    {\n        void *mem = this->do_reallocate(ptr, oldsz, newsz, alignment);\n        C4_CHECK_MSG(mem != nullptr, \"could not reallocate from %lu to %lu bytes\", oldsz, newsz);\n        return mem;\n    }\n\n    void deallocate(void* ptr, size_t sz, size_t alignment=alignof(max_align_t))\n    {\n        this->do_deallocate(ptr, sz, alignment);\n    }\n\nprotected:\n\n    virtual void* do_allocate(size_t sz, size_t alignment, void* hint) = 0;\n    virtual void* do_reallocate(void* ptr, size_t oldsz, size_t newsz, size_t alignment) = 0;\n    virtual void  do_deallocate(void* ptr, size_t sz, size_t alignment) = 0;\n\n};\n\n/** get the current global memory resource. To avoid static initialization\n * order problems, this is implemented using a function call to ensure\n * that it is available when first used.\n * @ingroup memory_resources */\nC4_ALWAYS_INLINE MemoryResource* get_memory_resource()\n{\n    return detail::get_memory_resource();\n}\n\n/** set the global memory resource\n * @ingroup memory_resources */\nC4_ALWAYS_INLINE void set_memory_resource(MemoryResource* mr)\n{\n    C4_ASSERT(mr != nullptr);\n    detail::get_memory_resource() = mr;\n}\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n/** A c4::aalloc-based memory resource. Thread-safe if the implementation\n * called by c4::aalloc() is safe.\n * @ingroup memory_resources */\nstruct MemoryResourceMalloc : public MemoryResource\n{\n\n    MemoryResourceMalloc() { name = \"malloc\"; }\n    virtual ~MemoryResourceMalloc() override {}\n\nprotected:\n\n    virtual void* do_allocate(size_t sz, size_t alignment, void *hint) override\n    {\n        C4_UNUSED(hint);\n        return c4::aalloc(sz, alignment);\n    }\n\n    virtual void  do_deallocate(void* ptr, size_t sz, size_t alignment) override\n    {\n        C4_UNUSED(sz);\n        C4_UNUSED(alignment);\n        c4::afree(ptr);\n    }\n\n    virtual void* do_reallocate(void* ptr, size_t oldsz, size_t newsz, size_t alignment) override\n    {\n        return c4::arealloc(ptr, oldsz, newsz, alignment);\n    }\n\n};\n\n/** returns a malloc-based memory resource\n * @ingroup memory_resources */\nC4_ALWAYS_INLINE MemoryResourceMalloc* get_memory_resource_malloc()\n{\n    /** @todo use a nifty counter:\n     * https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Nifty_Counter */\n    static MemoryResourceMalloc mr;\n    return &mr;\n}\n\nnamespace detail {\nC4_ALWAYS_INLINE MemoryResource* & get_memory_resource()\n{\n    /** @todo use a nifty counter:\n     * https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Nifty_Counter */\n    thread_local static MemoryResource* mr = get_memory_resource_malloc();\n    return mr;\n}\n} // namespace detail\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\nnamespace detail {\n\n/** Allows a memory resource to obtain its memory from another memory resource.\n * @ingroup memory_resources */\nstruct DerivedMemoryResource : public MemoryResource\n{\npublic:\n\n    DerivedMemoryResource(MemoryResource *mr_=nullptr) : m_local(mr_ ? mr_ : get_memory_resource()) {}\n\nprivate:\n\n    MemoryResource *m_local;\n\nprotected:\n\n    virtual void* do_allocate(size_t sz, size_t alignment, void* hint) override\n    {\n        return m_local->allocate(sz, alignment, hint);\n    }\n\n    virtual void* do_reallocate(void* ptr, size_t oldsz, size_t newsz, size_t alignment) override\n    {\n        return m_local->reallocate(ptr, oldsz, newsz, alignment);\n    }\n\n    virtual void do_deallocate(void* ptr, size_t sz, size_t alignment) override\n    {\n        return m_local->deallocate(ptr, sz, alignment);\n    }\n};\n\n/** Provides common facilities for memory resource consisting of a single memory block\n * @ingroup memory_resources */\nstruct _MemoryResourceSingleChunk : public DerivedMemoryResource\n{\n\n    C4_NO_COPY_OR_MOVE(_MemoryResourceSingleChunk);\n\n    using impl_type = DerivedMemoryResource;\n\npublic:\n\n    _MemoryResourceSingleChunk(MemoryResource *impl=nullptr) : DerivedMemoryResource(impl) { name = \"linear_malloc\"; }\n\n    /** initialize with owned memory, allocated from the given (or the global) memory resource */\n    _MemoryResourceSingleChunk(size_t sz, MemoryResource *impl=nullptr) : _MemoryResourceSingleChunk(impl) { acquire(sz); }\n    /** initialize with borrowed memory */\n    _MemoryResourceSingleChunk(void *mem, size_t sz) : _MemoryResourceSingleChunk() { acquire(mem, sz); }\n\n    virtual ~_MemoryResourceSingleChunk() override { release(); }\n\npublic:\n\n    void const* mem() const { return m_mem; }\n\n    size_t capacity() const { return m_size; }\n    size_t size() const { return m_pos; }\n    size_t slack() const { C4_ASSERT(m_size >= m_pos); return m_size - m_pos; }\n\npublic:\n\n    char  *m_mem{nullptr};\n    size_t m_size{0};\n    size_t m_pos{0};\n    bool   m_owner;\n\npublic:\n\n    /** set the internal pointer to the beginning of the linear buffer */\n    void clear() { m_pos = 0; }\n\n    /** initialize with owned memory, allocated from the global memory resource */\n    void acquire(size_t sz);\n    /** initialize with borrowed memory */\n    void acquire(void *mem, size_t sz);\n    /** release the memory */\n    void release();\n\n};\n\n} // namespace detail\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n/** provides a linear memory resource. Allocates incrementally from a linear\n * buffer, without ever deallocating. Deallocations are a no-op, and the\n * memory is freed only when the resource is release()d. The memory used by\n * this object can be either owned or borrowed. When borrowed, no calls to\n * malloc/free take place.\n *\n * @ingroup memory_resources */\nstruct MemoryResourceLinear : public detail::_MemoryResourceSingleChunk\n{\n\n    C4_NO_COPY_OR_MOVE(MemoryResourceLinear);\n\npublic:\n\n    using detail::_MemoryResourceSingleChunk::_MemoryResourceSingleChunk;\n\nprotected:\n\n    virtual void* do_allocate(size_t sz, size_t alignment, void *hint) override;\n    virtual void  do_deallocate(void* ptr, size_t sz, size_t alignment) override;\n    virtual void* do_reallocate(void* ptr, size_t oldsz, size_t newsz, size_t alignment) override;\n};\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n/** provides a stack-type malloc-based memory resource.\n * @ingroup memory_resources */\nstruct MemoryResourceStack : public detail::_MemoryResourceSingleChunk\n{\n\n    C4_NO_COPY_OR_MOVE(MemoryResourceStack);\n\npublic:\n\n    using detail::_MemoryResourceSingleChunk::_MemoryResourceSingleChunk;\n\nprotected:\n\n    virtual void* do_allocate(size_t sz, size_t alignment, void *hint) override;\n    virtual void  do_deallocate(void* ptr, size_t sz, size_t alignment) override;\n    virtual void* do_reallocate(void* ptr, size_t oldsz, size_t newsz, size_t alignment) override;\n};\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n/** provides a linear array-based memory resource.\n * @see MemoryResourceLinear\n * @ingroup memory_resources */\ntemplate<size_t N>\nstruct MemoryResourceLinearArr : public MemoryResourceLinear\n{\n    #ifdef _MSC_VER\n    #pragma warning(push)\n    #pragma warning(disable: 4324) // structure was padded due to alignment specifier\n    #endif\n    alignas(alignof(max_align_t)) char m_arr[N];\n    #ifdef _MSC_VER\n    #pragma warning(pop)\n    #endif\n    MemoryResourceLinearArr() : MemoryResourceLinear(m_arr, N) { name = \"linear_arr\"; }\n};\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\nstruct AllocationCounts\n{\n    struct Item\n    {\n        ssize_t allocs;\n        ssize_t size;\n\n        void add(size_t sz)\n        {\n            ++allocs;\n            size += static_cast<ssize_t>(sz);\n        }\n        void rem(size_t sz)\n        {\n            --allocs;\n            size -= static_cast<ssize_t>(sz);\n        }\n        Item max(Item const& that) const\n        {\n            Item r(*this);\n            r.allocs = r.allocs > that.allocs ? r.allocs : that.allocs;\n            r.size = r.size > that.size ? r.size : that.size;\n            return r;\n        }\n    };\n\n    Item curr  = {0, 0};\n    Item total = {0, 0};\n    Item max   = {0, 0};\n\n    void clear_counts()\n    {\n        curr  = {0, 0};\n        total = {0, 0};\n        max   = {0, 0};\n    }\n\n    void update(AllocationCounts const& that)\n    {\n        curr.allocs += that.curr.allocs;\n        curr.size += that.curr.size;\n        total.allocs += that.total.allocs;\n        total.size += that.total.size;\n        max.allocs += that.max.allocs;\n        max.size += that.max.size;\n    }\n\n    void add_counts(void* ptr, size_t sz)\n    {\n        if(ptr == nullptr) return;\n        curr.add(sz);\n        total.add(sz);\n        max = max.max(curr);\n    }\n\n    void rem_counts(void *ptr, size_t sz)\n    {\n        if(ptr == nullptr) return;\n        curr.rem(sz);\n    }\n\n    AllocationCounts operator- (AllocationCounts const& that) const\n    {\n        AllocationCounts r(*this);\n        r.curr.allocs -= that.curr.allocs;\n        r.curr.size -= that.curr.size;\n        r.total.allocs -= that.total.allocs;\n        r.total.size -= that.total.size;\n        r.max.allocs -= that.max.allocs;\n        r.max.size -= that.max.size;\n        return r;\n    }\n\n    AllocationCounts operator+ (AllocationCounts const& that) const\n    {\n        AllocationCounts r(*this);\n        r.curr.allocs += that.curr.allocs;\n        r.curr.size += that.curr.size;\n        r.total.allocs += that.total.allocs;\n        r.total.size += that.total.size;\n        r.max.allocs += that.max.allocs;\n        r.max.size += that.max.size;\n        return r;\n    }\n};\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n/** a MemoryResource which latches onto another MemoryResource\n * and counts allocations and sizes.\n * @ingroup memory_resources */\nclass MemoryResourceCounts : public MemoryResource\n{\npublic:\n\n    MemoryResourceCounts() : m_resource(get_memory_resource())\n    {\n        C4_ASSERT(m_resource != this);\n        name = \"MemoryResourceCounts\";\n    }\n    MemoryResourceCounts(MemoryResource *res) : m_resource(res)\n    {\n        C4_ASSERT(m_resource != this);\n        name = \"MemoryResourceCounts\";\n    }\n\n    MemoryResource *resource() { return m_resource; }\n    AllocationCounts const& counts() const { return m_counts; }\n\nprotected:\n\n    MemoryResource *m_resource;\n    AllocationCounts m_counts;\n\nprotected:\n\n    virtual void* do_allocate(size_t sz, size_t alignment, void * /*hint*/) override\n    {\n        void *ptr = m_resource->allocate(sz, alignment);\n        m_counts.add_counts(ptr, sz);\n        return ptr;\n    }\n\n    virtual void  do_deallocate(void* ptr, size_t sz, size_t alignment) override\n    {\n        m_counts.rem_counts(ptr, sz);\n        m_resource->deallocate(ptr, sz, alignment);\n    }\n\n    virtual void* do_reallocate(void* ptr, size_t oldsz, size_t newsz, size_t alignment) override\n    {\n        m_counts.rem_counts(ptr, oldsz);\n        void* nptr = m_resource->reallocate(ptr, oldsz, newsz, alignment);\n        m_counts.add_counts(nptr, newsz);\n        return nptr;\n    }\n\n};\n\n//-----------------------------------------------------------------------------\n/** RAII class which binds a memory resource with a scope duration.\n * @ingroup memory_resources */\nstruct ScopedMemoryResource\n{\n    MemoryResource *m_original;\n\n    ScopedMemoryResource(MemoryResource *r)\n    :\n        m_original(get_memory_resource())\n    {\n        set_memory_resource(r);\n    }\n\n    ~ScopedMemoryResource()\n    {\n        set_memory_resource(m_original);\n    }\n};\n\n//-----------------------------------------------------------------------------\n/** RAII class which counts allocations and frees inside a scope. Can\n * optionally set also the memory resource to be used.\n * @ingroup memory_resources */\nstruct ScopedMemoryResourceCounts\n{\n    MemoryResourceCounts mr;\n\n    ScopedMemoryResourceCounts() : mr()\n    {\n        set_memory_resource(&mr);\n    }\n    ScopedMemoryResourceCounts(MemoryResource *m) : mr(m)\n    {\n        set_memory_resource(&mr);\n    }\n    ~ScopedMemoryResourceCounts()\n    {\n        set_memory_resource(mr.resource());\n    }\n};\n\n} // namespace c4\n\n#endif /* _C4_MEMORY_RESOURCE_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/memory_util.cpp",
    "content": "#include \"c4/memory_util.hpp\"\n#include \"c4/error.hpp\"\n\nnamespace c4 {\n\n\n/** Fills 'dest' with the first 'pattern_size' bytes at 'pattern', 'num_times'. */\nvoid mem_repeat(void* dest, void const* pattern, size_t pattern_size, size_t num_times)\n{\n    if(C4_UNLIKELY(num_times == 0))\n        return;\n    C4_ASSERT( ! mem_overlaps(dest, pattern, num_times*pattern_size, pattern_size));\n    char *begin = static_cast<char*>(dest);\n    char *end   = begin + num_times * pattern_size;\n    // copy the pattern once\n    ::memcpy(begin, pattern, pattern_size);\n    // now copy from dest to itself, doubling up every time\n    size_t n = pattern_size;\n    while(begin + 2*n < end)\n    {\n        ::memcpy(begin + n, begin, n);\n        n <<= 1; // double n\n    }\n    // copy the missing part\n    if(begin + n < end)\n    {\n        ::memcpy(begin + n, begin, static_cast<size_t>(end - (begin + n)));\n    }\n}\n\n\n} // namespace c4\n"
  },
  {
    "path": "libs/rapidyaml/c4/memory_util.hpp",
    "content": "#ifndef _C4_MEMORY_UTIL_HPP_\n#define _C4_MEMORY_UTIL_HPP_\n\n#include \"c4/config.hpp\"\n#include \"c4/error.hpp\"\n#include \"c4/compiler.hpp\"\n#include \"c4/cpu.hpp\"\n#ifdef C4_MSVC\n#include <intrin.h>\n#endif\n#include <string.h>\n\n#if (defined(__GNUC__) && __GNUC__ >= 10) || defined(__has_builtin)\n#define _C4_USE_LSB_INTRINSIC(which) __has_builtin(which)\n#define _C4_USE_MSB_INTRINSIC(which) __has_builtin(which)\n#elif defined(C4_MSVC)\n#define _C4_USE_LSB_INTRINSIC(which) true\n#define _C4_USE_MSB_INTRINSIC(which) true\n#else\n// let's try our luck\n#define _C4_USE_LSB_INTRINSIC(which) true\n#define _C4_USE_MSB_INTRINSIC(which) true\n#endif\n\n\n/** @file memory_util.hpp Some memory utilities. */\n\nnamespace c4 {\n\nC4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH(\"-Wold-style-cast\")\n\n/** set the given memory to zero */\nC4_ALWAYS_INLINE void mem_zero(void* mem, size_t num_bytes)\n{\n    memset(mem, 0, num_bytes);\n}\n/** set the given memory to zero */\ntemplate<class T>\nC4_ALWAYS_INLINE void mem_zero(T* mem, size_t num_elms)\n{\n    memset(mem, 0, sizeof(T) * num_elms);\n}\n/** set the given memory to zero */\ntemplate<class T>\nC4_ALWAYS_INLINE void mem_zero(T* mem)\n{\n    memset(mem, 0, sizeof(T));\n}\n\nC4_ALWAYS_INLINE C4_CONST bool mem_overlaps(void const* a, void const* b, size_t sza, size_t szb)\n{\n    // thanks @timwynants\n    return (((const char*)b + szb) > a && b < ((const char*)a+sza));\n}\n\nvoid mem_repeat(void* dest, void const* pattern, size_t pattern_size, size_t num_times);\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\ntemplate<class T>\nC4_ALWAYS_INLINE C4_CONST bool is_aligned(T *ptr, uintptr_t alignment=alignof(T))\n{\n    return (uintptr_t(ptr) & (alignment - uintptr_t(1))) == uintptr_t(0);\n}\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n// least significant bit\n\n/** @name msb Compute the least significant bit\n * @note the input value must be nonzero\n * @note the input type must be unsigned\n */\n/** @{ */\n\n// https://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightLinear\n#define _c4_lsb_fallback                                                \\\n    unsigned c = 0;                                                     \\\n    v = (v ^ (v - 1)) >> 1; /* Set v's trailing 0s to 1s and zero rest */ \\\n    for(; v; ++c)                                                       \\\n        v >>= 1;                                                        \\\n    return (unsigned) c\n\n// u8\ntemplate<class I>\nC4_CONSTEXPR14\nauto lsb(I v) noexcept\n    -> typename std::enable_if<sizeof(I) == 1u, unsigned>::type\n{\n    C4_STATIC_ASSERT(std::is_unsigned<I>::value);\n    C4_ASSERT(v != 0);\n    #if _C4_USE_LSB_INTRINSIC(__builtin_ctz)\n        // upcast to use the intrinsic, it's cheaper.\n        #ifdef C4_MSVC\n            #if !defined(C4_CPU_ARM64) && !defined(C4_CPU_ARM)\n                unsigned long bit;\n                _BitScanForward(&bit, (unsigned long)v);\n                return bit;\n            #else\n                _c4_lsb_fallback;\n            #endif\n        #else\n            return (unsigned)__builtin_ctz((unsigned)v);\n        #endif\n    #else\n        _c4_lsb_fallback;\n    #endif\n}\n\n// u16\ntemplate<class I>\nC4_CONSTEXPR14\nauto lsb(I v) noexcept\n    -> typename std::enable_if<sizeof(I) == 2u, unsigned>::type\n{\n    C4_STATIC_ASSERT(std::is_unsigned<I>::value);\n    C4_ASSERT(v != 0);\n    #if _C4_USE_LSB_INTRINSIC(__builtin_ctz)\n        // upcast to use the intrinsic, it's cheaper.\n        // Then remember that the upcast makes it to 31bits\n        #ifdef C4_MSVC\n            #if !defined(C4_CPU_ARM64) && !defined(C4_CPU_ARM)\n                unsigned long bit;\n                _BitScanForward(&bit, (unsigned long)v);\n                return bit;\n            #else\n                _c4_lsb_fallback;\n            #endif\n        #else\n            return (unsigned)__builtin_ctz((unsigned)v);\n        #endif\n    #else\n        _c4_lsb_fallback;\n    #endif\n}\n\n// u32\ntemplate<class I>\nC4_CONSTEXPR14\nauto lsb(I v) noexcept\n    -> typename std::enable_if<sizeof(I) == 4u, unsigned>::type\n{\n    C4_STATIC_ASSERT(std::is_unsigned<I>::value);\n    C4_ASSERT(v != 0);\n    #if _C4_USE_LSB_INTRINSIC(__builtin_ctz)\n        #ifdef C4_MSVC\n            #if !defined(C4_CPU_ARM64) && !defined(C4_CPU_ARM)\n                unsigned long bit;\n                _BitScanForward(&bit, v);\n                return bit;\n            #else\n                _c4_lsb_fallback;\n            #endif\n        #else\n            return (unsigned)__builtin_ctz((unsigned)v);\n        #endif\n    #else\n        _c4_lsb_fallback;\n    #endif\n}\n\n// u64 in 64bits\ntemplate<class I>\nC4_CONSTEXPR14\nauto lsb(I v) noexcept\n    -> typename std::enable_if<sizeof(I) == 8u && sizeof(unsigned long) == 8u, unsigned>::type\n{\n    C4_STATIC_ASSERT(std::is_unsigned<I>::value);\n    C4_ASSERT(v != 0);\n    #if _C4_USE_LSB_INTRINSIC(__builtin_ctzl)\n        #if defined(C4_MSVC)\n            #if !defined(C4_CPU_ARM64) && !defined(C4_CPU_ARM)\n                unsigned long bit;\n                _BitScanForward64(&bit, v);\n                return bit;\n            #else\n                _c4_lsb_fallback;\n            #endif\n        #else\n            return (unsigned)__builtin_ctzl((unsigned long)v);\n        #endif\n    #else\n        _c4_lsb_fallback;\n    #endif\n}\n\n// u64 in 32bits\ntemplate<class I>\nC4_CONSTEXPR14\nauto lsb(I v) noexcept\n    -> typename std::enable_if<sizeof(I) == 8u && sizeof(unsigned long long) == 8u && sizeof(unsigned long) != sizeof(unsigned long long), unsigned>::type\n{\n    C4_STATIC_ASSERT(std::is_unsigned<I>::value);\n    C4_ASSERT(v != 0);\n    #if _C4_USE_LSB_INTRINSIC(__builtin_ctzll)\n        #if defined(C4_MSVC)\n            #if !defined(C4_CPU_X86) && !defined(C4_CPU_ARM64) && !defined(C4_CPU_ARM)\n                unsigned long bit;\n                _BitScanForward64(&bit, v);\n                return bit;\n            #else\n                _c4_lsb_fallback;\n            #endif\n        #else\n            return (unsigned)__builtin_ctzll((unsigned long long)v);\n        #endif\n    #else\n        _c4_lsb_fallback;\n    #endif\n}\n\n#undef _c4_lsb_fallback\n\n/** @} */\n\n\nnamespace detail {\ntemplate<class I, I val, unsigned num_bits, bool finished> struct _lsb11;\ntemplate<class I, I val, unsigned num_bits>\nstruct _lsb11<I, val, num_bits, false>\n{\n    enum : unsigned { num = _lsb11<I, (val>>1), num_bits+I(1), (((val>>1)&I(1))!=I(0))>::num };\n};\ntemplate<class I, I val, unsigned num_bits>\nstruct _lsb11<I, val, num_bits, true>\n{\n    enum : unsigned { num = num_bits };\n};\n} // namespace detail\n\n\n/** TMP version of lsb(); this needs to be implemented with template\n * meta-programming because C++11 cannot use a constexpr function with\n * local variables\n * @see lsb */\ntemplate<class I, I number>\nstruct lsb11\n{\n    static_assert(number != 0, \"lsb: number must be nonzero\");\n    enum : unsigned { value = detail::_lsb11<I, number, 0, ((number&I(1))!=I(0))>::num};\n};\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n// most significant bit\n\n\n/** @name msb Compute the most significant bit\n * @note the input value must be nonzero\n * @note the input type must be unsigned\n */\n/** @{ */\n\n\n#define _c4_msb8_fallback                       \\\n    unsigned n = 0;                             \\\n    if(v & I(0xf0)) v >>= 4, n |= I(4);         \\\n    if(v & I(0x0c)) v >>= 2, n |= I(2);         \\\n    if(v & I(0x02)) v >>= 1, n |= I(1);         \\\n    return n\n\n#define _c4_msb16_fallback                      \\\n    unsigned n = 0;                             \\\n    if(v & I(0xff00)) v >>= 8, n |= I(8);       \\\n    if(v & I(0x00f0)) v >>= 4, n |= I(4);       \\\n    if(v & I(0x000c)) v >>= 2, n |= I(2);       \\\n    if(v & I(0x0002)) v >>= 1, n |= I(1);       \\\n    return n\n\n#define _c4_msb32_fallback                      \\\n    unsigned n = 0;                             \\\n    if(v & I(0xffff0000)) v >>= 16, n |= 16;    \\\n    if(v & I(0x0000ff00)) v >>= 8, n |= 8;      \\\n    if(v & I(0x000000f0)) v >>= 4, n |= 4;      \\\n    if(v & I(0x0000000c)) v >>= 2, n |= 2;      \\\n    if(v & I(0x00000002)) v >>= 1, n |= 1;      \\\n    return n\n\n#define _c4_msb64_fallback                              \\\n    unsigned n = 0;                                     \\\n    if(v & I(0xffffffff00000000)) v >>= 32, n |= I(32); \\\n    if(v & I(0x00000000ffff0000)) v >>= 16, n |= I(16); \\\n    if(v & I(0x000000000000ff00)) v >>= 8, n |= I(8);   \\\n    if(v & I(0x00000000000000f0)) v >>= 4, n |= I(4);   \\\n    if(v & I(0x000000000000000c)) v >>= 2, n |= I(2);   \\\n    if(v & I(0x0000000000000002)) v >>= 1, n |= I(1);   \\\n    return n\n\n\n// u8\ntemplate<class I>\nC4_CONSTEXPR14\nauto msb(I v) noexcept\n    -> typename std::enable_if<sizeof(I) == 1u, unsigned>::type\n{\n    C4_STATIC_ASSERT(std::is_unsigned<I>::value);\n    C4_ASSERT(v != 0);\n    #if _C4_USE_MSB_INTRINSIC(__builtin_clz)\n        // upcast to use the intrinsic, it's cheaper.\n        // Then remember that the upcast makes it to 31bits\n        #ifdef C4_MSVC\n            #if !defined(C4_CPU_ARM64) && !defined(C4_CPU_ARM)\n                unsigned long bit;\n                _BitScanReverse(&bit, (unsigned long)v);\n                return bit;\n            #else\n                _c4_msb8_fallback;\n            #endif\n        #else\n            return 31u - (unsigned)__builtin_clz((unsigned)v);\n        #endif\n    #else\n        _c4_msb8_fallback;\n    #endif\n}\n\n// u16\ntemplate<class I>\nC4_CONSTEXPR14\nauto msb(I v) noexcept\n    -> typename std::enable_if<sizeof(I) == 2u, unsigned>::type\n{\n    C4_STATIC_ASSERT(std::is_unsigned<I>::value);\n    C4_ASSERT(v != 0);\n    #if _C4_USE_MSB_INTRINSIC(__builtin_clz)\n        // upcast to use the intrinsic, it's cheaper.\n        // Then remember that the upcast makes it to 31bits\n        #ifdef C4_MSVC\n            #if !defined(C4_CPU_ARM64) && !defined(C4_CPU_ARM)\n                unsigned long bit;\n                _BitScanReverse(&bit, (unsigned long)v);\n                return bit;\n            #else\n                _c4_msb16_fallback;\n            #endif\n        #else\n            return 31u - (unsigned)__builtin_clz((unsigned)v);\n        #endif\n    #else\n        _c4_msb16_fallback;\n    #endif\n}\n\n// u32\ntemplate<class I>\nC4_CONSTEXPR14\nauto msb(I v) noexcept\n    -> typename std::enable_if<sizeof(I) == 4u, unsigned>::type\n{\n    C4_STATIC_ASSERT(std::is_unsigned<I>::value);\n    C4_ASSERT(v != 0);\n    #if _C4_USE_MSB_INTRINSIC(__builtin_clz)\n        #ifdef C4_MSVC\n            #if !defined(C4_CPU_ARM64) && !defined(C4_CPU_ARM)\n                unsigned long bit;\n                _BitScanReverse(&bit, v);\n                return bit;\n            #else\n                _c4_msb32_fallback;\n            #endif\n        #else\n            return 31u - (unsigned)__builtin_clz((unsigned)v);\n        #endif\n    #else\n        _c4_msb32_fallback;\n    #endif\n}\n\n// u64 in 64bits\ntemplate<class I>\nC4_CONSTEXPR14\nauto msb(I v) noexcept\n    -> typename std::enable_if<sizeof(I) == 8u && sizeof(unsigned long) == 8u, unsigned>::type\n{\n    C4_STATIC_ASSERT(std::is_unsigned<I>::value);\n    C4_ASSERT(v != 0);\n    #if _C4_USE_MSB_INTRINSIC(__builtin_clzl)\n        #ifdef C4_MSVC\n            #if !defined(C4_CPU_ARM64) && !defined(C4_CPU_ARM)\n                unsigned long bit;\n                _BitScanReverse64(&bit, v);\n                return bit;\n            #else\n                _c4_msb64_fallback;\n            #endif\n        #else\n            return 63u - (unsigned)__builtin_clzl((unsigned long)v);\n        #endif\n    #else\n        _c4_msb64_fallback;\n    #endif\n}\n\n// u64 in 32bits\ntemplate<class I>\nC4_CONSTEXPR14\nauto msb(I v) noexcept\n    -> typename std::enable_if<sizeof(I) == 8u && sizeof(unsigned long long) == 8u && sizeof(unsigned long) != sizeof(unsigned long long), unsigned>::type\n{\n    C4_STATIC_ASSERT(std::is_unsigned<I>::value);\n    C4_ASSERT(v != 0);\n    #if _C4_USE_MSB_INTRINSIC(__builtin_clzll)\n        #ifdef C4_MSVC\n            #if !defined(C4_CPU_X86) && !defined(C4_CPU_ARM64) && !defined(C4_CPU_ARM)\n                unsigned long bit;\n                _BitScanReverse64(&bit, v);\n                return bit;\n            #else\n                _c4_msb64_fallback;\n            #endif\n        #else\n            return 63u - (unsigned)__builtin_clzll((unsigned long long)v);\n        #endif\n    #else\n        _c4_msb64_fallback;\n    #endif\n}\n\n#undef _c4_msb8_fallback\n#undef _c4_msb16_fallback\n#undef _c4_msb32_fallback\n#undef _c4_msb64_fallback\n\n/** @} */\n\n\nnamespace detail {\ntemplate<class I, I val, I num_bits, bool finished> struct _msb11;\ntemplate<class I, I val, I num_bits>\nstruct _msb11< I, val, num_bits, false>\n{\n    enum : unsigned { num = _msb11<I, (val>>1), num_bits+I(1), ((val>>1)==I(0))>::num };\n};\ntemplate<class I, I val, I num_bits>\nstruct _msb11<I, val, num_bits, true>\n{\n    static_assert(val == 0, \"bad implementation\");\n    enum : unsigned { num = (unsigned)(num_bits-1) };\n};\n} // namespace detail\n\n\n/** TMP version of msb(); this needs to be implemented with template\n * meta-programming because C++11 cannot use a constexpr function with\n * local variables\n * @see msb */\ntemplate<class I, I number>\nstruct msb11\n{\n    enum : unsigned { value = detail::_msb11<I, number, 0, (number==I(0))>::num };\n};\n\n\n\n#undef _C4_USE_LSB_INTRINSIC\n#undef _C4_USE_MSB_INTRINSIC\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n// there is an implicit conversion below; it happens when E or B are\n// narrower than int, and thus any operation will upcast the result to\n// int, and then downcast to assign\nC4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH(\"-Wconversion\")\n\n/** integer power; this function is constexpr-14 because of the local\n * variables */\ntemplate<class B, class E>\nC4_CONSTEXPR14 C4_CONST auto ipow(B base, E exponent) noexcept -> typename std::enable_if<std::is_signed<E>::value, B>::type\n{\n    C4_STATIC_ASSERT(std::is_integral<E>::value);\n    B r = B(1);\n    if(exponent >= 0)\n    {\n        for(E e = 0; e < exponent; ++e)\n            r *= base;\n    }\n    else\n    {\n        exponent *= E(-1);\n        for(E e = 0; e < exponent; ++e)\n            r /= base;\n    }\n    return r;\n}\n\n/** integer power; this function is constexpr-14 because of the local\n * variables */\ntemplate<class B, B base, class E>\nC4_CONSTEXPR14 C4_CONST auto ipow(E exponent) noexcept -> typename std::enable_if<std::is_signed<E>::value, B>::type\n{\n    C4_STATIC_ASSERT(std::is_integral<E>::value);\n    B r = B(1);\n    if(exponent >= 0)\n    {\n        for(E e = 0; e < exponent; ++e)\n            r *= base;\n    }\n    else\n    {\n        exponent *= E(-1);\n        for(E e = 0; e < exponent; ++e)\n            r /= base;\n    }\n    return r;\n}\n\n/** integer power; this function is constexpr-14 because of the local\n * variables */\ntemplate<class B, class Base, Base base, class E>\nC4_CONSTEXPR14 C4_CONST auto ipow(E exponent) noexcept -> typename std::enable_if<std::is_signed<E>::value, B>::type\n{\n    C4_STATIC_ASSERT(std::is_integral<E>::value);\n    B r = B(1);\n    B bbase = B(base);\n    if(exponent >= 0)\n    {\n        for(E e = 0; e < exponent; ++e)\n            r *= bbase;\n    }\n    else\n    {\n        exponent *= E(-1);\n        for(E e = 0; e < exponent; ++e)\n            r /= bbase;\n    }\n    return r;\n}\n\n/** integer power; this function is constexpr-14 because of the local\n * variables */\ntemplate<class B, class E>\nC4_CONSTEXPR14 C4_CONST auto ipow(B base, E exponent) noexcept -> typename std::enable_if<!std::is_signed<E>::value, B>::type\n{\n    C4_STATIC_ASSERT(std::is_integral<E>::value);\n    B r = B(1);\n    for(E e = 0; e < exponent; ++e)\n        r *= base;\n    return r;\n}\n\n/** integer power; this function is constexpr-14 because of the local\n * variables */\ntemplate<class B, B base, class E>\nC4_CONSTEXPR14 C4_CONST auto ipow(E exponent) noexcept -> typename std::enable_if<!std::is_signed<E>::value, B>::type\n{\n    C4_STATIC_ASSERT(std::is_integral<E>::value);\n    B r = B(1);\n    for(E e = 0; e < exponent; ++e)\n        r *= base;\n    return r;\n}\n/** integer power; this function is constexpr-14 because of the local\n * variables */\ntemplate<class B, class Base, Base base, class E>\nC4_CONSTEXPR14 C4_CONST auto ipow(E exponent) noexcept -> typename std::enable_if<!std::is_signed<E>::value, B>::type\n{\n    C4_STATIC_ASSERT(std::is_integral<E>::value);\n    B r = B(1);\n    B bbase = B(base);\n    for(E e = 0; e < exponent; ++e)\n        r *= bbase;\n    return r;\n}\n\nC4_SUPPRESS_WARNING_GCC_CLANG_POP\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n/** return a mask with all bits set [first_bit,last_bit[; this function\n * is constexpr-14 because of the local variables */\ntemplate<class I>\nC4_CONSTEXPR14 I contiguous_mask(I first_bit, I last_bit)\n{\n    I r = 0;\n    for(I i = first_bit; i < last_bit; ++i)\n    {\n        r |= (I(1) << i);\n    }\n    return r;\n}\n\n\nnamespace detail {\n\ntemplate<class I, I val, I first, I last, bool finished>\nstruct _ctgmsk11;\n\ntemplate<class I, I val, I first, I last>\nstruct _ctgmsk11< I, val, first, last, true>\n{\n    enum : I { value = _ctgmsk11<I, val|(I(1)<<first), first+I(1), last, (first+1!=last)>::value };\n};\n\ntemplate<class I, I val, I first, I last>\nstruct _ctgmsk11< I, val, first, last, false>\n{\n    enum : I { value = val };\n};\n\n} // namespace detail\n\n\n/** TMP version of contiguous_mask(); this needs to be implemented with template\n * meta-programming because C++11 cannot use a constexpr function with\n * local variables\n * @see contiguous_mask */\ntemplate<class I, I first_bit, I last_bit>\nstruct contiguous_mask11\n{\n    enum : I { value = detail::_ctgmsk11<I, I(0), first_bit, last_bit, (first_bit!=last_bit)>::value };\n};\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n/** use Empty Base Class Optimization to reduce the size of a pair of\n * potentially empty types*/\n\nnamespace detail {\ntypedef enum {\n    tpc_same,\n    tpc_same_empty,\n    tpc_both_empty,\n    tpc_first_empty,\n    tpc_second_empty,\n    tpc_general\n} TightPairCase_e;\n\ntemplate<class First, class Second>\nconstexpr TightPairCase_e tpc_which_case()\n{\n    return std::is_same<First, Second>::value ?\n               std::is_empty<First>::value ?\n                   tpc_same_empty\n                   :\n                   tpc_same\n               :\n               std::is_empty<First>::value && std::is_empty<Second>::value ?\n                   tpc_both_empty\n                   :\n                   std::is_empty<First>::value ?\n                       tpc_first_empty\n                       :\n                       std::is_empty<Second>::value ?\n                           tpc_second_empty\n                           :\n                           tpc_general\n           ;\n}\n\ntemplate<class First, class Second, TightPairCase_e Case>\nstruct tight_pair\n{\nprivate:\n\n    First m_first;\n    Second m_second;\n\npublic:\n\n    using first_type = First;\n    using second_type = Second;\n\n    tight_pair() : m_first(), m_second() {}\n    tight_pair(First const& f, Second const& s) : m_first(f), m_second(s) {}\n\n    C4_ALWAYS_INLINE C4_CONSTEXPR14 First       & first ()       { return m_first; }\n    C4_ALWAYS_INLINE C4_CONSTEXPR14 First  const& first () const { return m_first; }\n    C4_ALWAYS_INLINE C4_CONSTEXPR14 Second      & second()       { return m_second; }\n    C4_ALWAYS_INLINE C4_CONSTEXPR14 Second const& second() const { return m_second; }\n};\n\ntemplate<class First, class Second>\nstruct tight_pair<First, Second, tpc_same_empty> : public First\n{\n    static_assert(std::is_same<First, Second>::value, \"bad implementation\");\n\n    using first_type = First;\n    using second_type = Second;\n\n    tight_pair() : First() {}\n    tight_pair(First const& f, Second const& /*s*/) : First(f) {}\n\n    C4_ALWAYS_INLINE C4_CONSTEXPR14 First      & first ()       { return static_cast<First      &>(*this); }\n    C4_ALWAYS_INLINE C4_CONSTEXPR14 First const& first () const { return static_cast<First const&>(*this); }\n    C4_ALWAYS_INLINE C4_CONSTEXPR14 Second      & second()       { return reinterpret_cast<Second      &>(*this); }\n    C4_ALWAYS_INLINE C4_CONSTEXPR14 Second const& second() const { return reinterpret_cast<Second const&>(*this); }\n};\n\ntemplate<class First, class Second>\nstruct tight_pair<First, Second, tpc_both_empty> : public First, public Second\n{\n    using first_type = First;\n    using second_type = Second;\n\n    tight_pair() : First(), Second() {}\n    tight_pair(First const& f, Second const& s) : First(f), Second(s) {}\n\n    C4_ALWAYS_INLINE C4_CONSTEXPR14 First      & first ()       { return static_cast<First      &>(*this); }\n    C4_ALWAYS_INLINE C4_CONSTEXPR14 First const& first () const { return static_cast<First const&>(*this); }\n    C4_ALWAYS_INLINE C4_CONSTEXPR14 Second      & second()       { return static_cast<Second      &>(*this); }\n    C4_ALWAYS_INLINE C4_CONSTEXPR14 Second const& second() const { return static_cast<Second const&>(*this); }\n};\n\ntemplate<class First, class Second>\nstruct tight_pair<First, Second, tpc_same> : public First\n{\n    Second m_second;\n\n    using first_type = First;\n    using second_type = Second;\n\n    tight_pair() : First() {}\n    tight_pair(First const& f, Second const& s) : First(f), m_second(s) {}\n\n    C4_ALWAYS_INLINE C4_CONSTEXPR14 First      & first ()       { return static_cast<First      &>(*this); }\n    C4_ALWAYS_INLINE C4_CONSTEXPR14 First const& first () const { return static_cast<First const&>(*this); }\n    C4_ALWAYS_INLINE C4_CONSTEXPR14 Second      & second()       { return m_second; }\n    C4_ALWAYS_INLINE C4_CONSTEXPR14 Second const& second() const { return m_second; }\n};\n\ntemplate<class First, class Second>\nstruct tight_pair<First, Second, tpc_first_empty> : public First\n{\n    Second m_second;\n\n    using first_type = First;\n    using second_type = Second;\n\n    tight_pair() : First(), m_second() {}\n    tight_pair(First const& f, Second const& s) : First(f), m_second(s) {}\n\n    C4_ALWAYS_INLINE C4_CONSTEXPR14 First      & first ()       { return static_cast<First      &>(*this); }\n    C4_ALWAYS_INLINE C4_CONSTEXPR14 First const& first () const { return static_cast<First const&>(*this); }\n    C4_ALWAYS_INLINE C4_CONSTEXPR14 Second      & second()       { return m_second; }\n    C4_ALWAYS_INLINE C4_CONSTEXPR14 Second const& second() const { return m_second; }\n};\n\ntemplate<class First, class Second>\nstruct tight_pair<First, Second, tpc_second_empty> : public Second\n{\n    First m_first;\n\n    using first_type = First;\n    using second_type = Second;\n\n    tight_pair() : Second(), m_first() {}\n    tight_pair(First const& f, Second const& s) : Second(s), m_first(f) {}\n\n    C4_ALWAYS_INLINE C4_CONSTEXPR14 First      & first ()       { return m_first; }\n    C4_ALWAYS_INLINE C4_CONSTEXPR14 First const& first () const { return m_first; }\n    C4_ALWAYS_INLINE C4_CONSTEXPR14 Second      & second()       { return static_cast<Second      &>(*this); }\n    C4_ALWAYS_INLINE C4_CONSTEXPR14 Second const& second() const { return static_cast<Second const&>(*this); }\n};\n\n} // namespace detail\n\ntemplate<class First, class Second>\nusing tight_pair = detail::tight_pair<First, Second, detail::tpc_which_case<First,Second>()>;\n\nC4_SUPPRESS_WARNING_GCC_CLANG_POP\n\n} // namespace c4\n\n#endif /* _C4_MEMORY_UTIL_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/platform.hpp",
    "content": "#ifndef _C4_PLATFORM_HPP_\n#define _C4_PLATFORM_HPP_\n\n/** @file platform.hpp Provides platform information macros\n * @ingroup basic_headers */\n\n// see also https://sourceforge.net/p/predef/wiki/OperatingSystems/\n\n#if defined(_WIN64)\n#   define C4_WIN\n#   define C4_WIN64\n#elif defined(_WIN32)\n#   define C4_WIN\n#   define C4_WIN32\n#elif defined(__ANDROID__)\n#   define C4_ANDROID\n#elif defined(__APPLE__)\n#   include \"TargetConditionals.h\"\n#   if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR\n#       define C4_IOS\n#   elif TARGET_OS_MAC || TARGET_OS_OSX\n#       define C4_MACOS\n#   else\n#       error \"Unknown Apple platform\"\n#   endif\n#elif defined(__linux__) || defined(__linux)\n#   define C4_UNIX\n#   define C4_LINUX\n#elif defined(__unix__) || defined(__unix)\n#   define C4_UNIX\n#elif defined(__arm__) || defined(__aarch64__)\n#   define C4_ARM\n#elif defined(__xtensa__) || defined(__XTENSA__)\n#   define C4_XTENSA\n#elif defined(SWIG)\n#   define C4_SWIG\n#else\n#   error \"unknown platform\"\n#endif\n\n#if defined(__posix) || defined(C4_UNIX) || defined(C4_LINUX)\n#   define C4_POSIX\n#endif\n\n\n#endif /* _C4_PLATFORM_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/preprocessor.hpp",
    "content": "#ifndef _C4_PREPROCESSOR_HPP_\n#define _C4_PREPROCESSOR_HPP_\n\n/** @file preprocessor.hpp Contains basic macros and preprocessor utilities.\n * @ingroup basic_headers */\n\n#ifdef __clang__\n    /* NOTE: using , ## __VA_ARGS__ to deal with zero-args calls to\n     * variadic macros is not portable, but works in clang, gcc, msvc, icc.\n     * clang requires switching off compiler warnings for pedantic mode.\n     * @see http://stackoverflow.com/questions/32047685/variadic-macro-without-arguments */\n#   pragma clang diagnostic push\n#   pragma clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\" // warning: token pasting of ',' and __VA_ARGS__ is a GNU extension\n#elif defined(__GNUC__)\n    /* GCC also issues a warning for zero-args calls to variadic macros.\n     * This warning is switched on with -pedantic and apparently there is no\n     * easy way to turn it off as with clang. But marking this as a system\n     * header works.\n     * @see https://gcc.gnu.org/onlinedocs/cpp/System-Headers.html\n     * @see http://stackoverflow.com/questions/35587137/ */\n#   pragma GCC system_header\n#endif\n\n#define C4_WIDEN(str) L\"\" str\n\n#define C4_COUNTOF(arr) (sizeof(arr)/sizeof((arr)[0]))\n\n#define C4_EXPAND(arg) arg\n\n/** useful in some macro calls with template arguments */\n#define C4_COMMA ,\n/** useful in some macro calls with template arguments\n * @see C4_COMMA */\n#define C4_COMMA_X C4_COMMA\n\n/** expand and quote */\n#define C4_XQUOTE(arg) _C4_XQUOTE(arg)\n#define _C4_XQUOTE(arg) C4_QUOTE(arg)\n#define C4_QUOTE(arg) #arg\n\n/** expand and concatenate */\n#define C4_XCAT(arg1, arg2) _C4_XCAT(arg1, arg2)\n#define _C4_XCAT(arg1, arg2) C4_CAT(arg1, arg2)\n#define C4_CAT(arg1, arg2) arg1##arg2\n\n#define C4_VERSION_CAT(major, minor, patch) ((major)*10000 + (minor)*100 + (patch))\n\n/** A preprocessor foreach. Spectacular trick taken from:\n * http://stackoverflow.com/a/1872506/5875572\n * The first argument is for a macro receiving a single argument,\n * which will be called with every subsequent argument. There is\n * currently a limit of 32 arguments, and at least 1 must be provided.\n *\nExample:\n@code{.cpp}\nstruct Example {\n    int a;\n    int b;\n    int c;\n};\n// define a one-arg macro to be called\n#define PRN_STRUCT_OFFSETS(field) PRN_STRUCT_OFFSETS_(Example, field)\n#define PRN_STRUCT_OFFSETS_(structure, field) printf(C4_XQUOTE(structure) \":\" C4_XQUOTE(field)\" - offset=%zu\\n\", offsetof(structure, field));\n\n// now call the macro for a, b and c\nC4_FOR_EACH(PRN_STRUCT_OFFSETS, a, b, c);\n@endcode */\n#define C4_FOR_EACH(what, ...) C4_FOR_EACH_SEP(what, ;, __VA_ARGS__)\n\n/** same as C4_FOR_EACH(), but use a custom separator between statements.\n * If a comma is needed as the separator, use the C4_COMMA macro.\n * @see C4_FOR_EACH\n * @see C4_COMMA\n */\n#define C4_FOR_EACH_SEP(what, sep, ...) _C4_FOR_EACH_(_C4_FOR_EACH_NARG(__VA_ARGS__), what, sep, __VA_ARGS__)\n\n/// @cond dev\n\n#define _C4_FOR_EACH_01(what, sep, x) what(x) sep\n#define _C4_FOR_EACH_02(what, sep, x, ...) what(x) sep _C4_FOR_EACH_01(what, sep, __VA_ARGS__)\n#define _C4_FOR_EACH_03(what, sep, x, ...) what(x) sep _C4_FOR_EACH_02(what, sep, __VA_ARGS__)\n#define _C4_FOR_EACH_04(what, sep, x, ...) what(x) sep _C4_FOR_EACH_03(what, sep, __VA_ARGS__)\n#define _C4_FOR_EACH_05(what, sep, x, ...) what(x) sep _C4_FOR_EACH_04(what, sep, __VA_ARGS__)\n#define _C4_FOR_EACH_06(what, sep, x, ...) what(x) sep _C4_FOR_EACH_05(what, sep, __VA_ARGS__)\n#define _C4_FOR_EACH_07(what, sep, x, ...) what(x) sep _C4_FOR_EACH_06(what, sep, __VA_ARGS__)\n#define _C4_FOR_EACH_08(what, sep, x, ...) what(x) sep _C4_FOR_EACH_07(what, sep, __VA_ARGS__)\n#define _C4_FOR_EACH_09(what, sep, x, ...) what(x) sep _C4_FOR_EACH_08(what, sep, __VA_ARGS__)\n#define _C4_FOR_EACH_10(what, sep, x, ...) what(x) sep _C4_FOR_EACH_09(what, sep, __VA_ARGS__)\n#define _C4_FOR_EACH_11(what, sep, x, ...) what(x) sep _C4_FOR_EACH_10(what, sep, __VA_ARGS__)\n#define _C4_FOR_EACH_12(what, sep, x, ...) what(x) sep _C4_FOR_EACH_11(what, sep, __VA_ARGS__)\n#define _C4_FOR_EACH_13(what, sep, x, ...) what(x) sep _C4_FOR_EACH_12(what, sep, __VA_ARGS__)\n#define _C4_FOR_EACH_14(what, sep, x, ...) what(x) sep _C4_FOR_EACH_13(what, sep, __VA_ARGS__)\n#define _C4_FOR_EACH_15(what, sep, x, ...) what(x) sep _C4_FOR_EACH_14(what, sep, __VA_ARGS__)\n#define _C4_FOR_EACH_16(what, sep, x, ...) what(x) sep _C4_FOR_EACH_15(what, sep, __VA_ARGS__)\n#define _C4_FOR_EACH_17(what, sep, x, ...) what(x) sep _C4_FOR_EACH_16(what, sep, __VA_ARGS__)\n#define _C4_FOR_EACH_18(what, sep, x, ...) what(x) sep _C4_FOR_EACH_17(what, sep, __VA_ARGS__)\n#define _C4_FOR_EACH_19(what, sep, x, ...) what(x) sep _C4_FOR_EACH_18(what, sep, __VA_ARGS__)\n#define _C4_FOR_EACH_20(what, sep, x, ...) what(x) sep _C4_FOR_EACH_19(what, sep, __VA_ARGS__)\n#define _C4_FOR_EACH_21(what, sep, x, ...) what(x) sep _C4_FOR_EACH_20(what, sep, __VA_ARGS__)\n#define _C4_FOR_EACH_22(what, sep, x, ...) what(x) sep _C4_FOR_EACH_21(what, sep, __VA_ARGS__)\n#define _C4_FOR_EACH_23(what, sep, x, ...) what(x) sep _C4_FOR_EACH_22(what, sep, __VA_ARGS__)\n#define _C4_FOR_EACH_24(what, sep, x, ...) what(x) sep _C4_FOR_EACH_23(what, sep, __VA_ARGS__)\n#define _C4_FOR_EACH_25(what, sep, x, ...) what(x) sep _C4_FOR_EACH_24(what, sep, __VA_ARGS__)\n#define _C4_FOR_EACH_26(what, sep, x, ...) what(x) sep _C4_FOR_EACH_25(what, sep, __VA_ARGS__)\n#define _C4_FOR_EACH_27(what, sep, x, ...) what(x) sep _C4_FOR_EACH_26(what, sep, __VA_ARGS__)\n#define _C4_FOR_EACH_28(what, sep, x, ...) what(x) sep _C4_FOR_EACH_27(what, sep, __VA_ARGS__)\n#define _C4_FOR_EACH_29(what, sep, x, ...) what(x) sep _C4_FOR_EACH_28(what, sep, __VA_ARGS__)\n#define _C4_FOR_EACH_30(what, sep, x, ...) what(x) sep _C4_FOR_EACH_29(what, sep, __VA_ARGS__)\n#define _C4_FOR_EACH_31(what, sep, x, ...) what(x) sep _C4_FOR_EACH_30(what, sep, __VA_ARGS__)\n#define _C4_FOR_EACH_32(what, sep, x, ...) what(x) sep _C4_FOR_EACH_31(what, sep, __VA_ARGS__)\n#define _C4_FOR_EACH_NARG(...) _C4_FOR_EACH_NARG_(__VA_ARGS__, _C4_FOR_EACH_RSEQ_N())\n#define _C4_FOR_EACH_NARG_(...) _C4_FOR_EACH_ARG_N(__VA_ARGS__)\n#define _C4_FOR_EACH_ARG_N(_01, _02, _03, _04, _05, _06, _07, _08, _09, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, N, ...) N\n#define _C4_FOR_EACH_RSEQ_N() 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 09, 08, 07, 06, 05, 04, 03, 02, 01\n#define _C4_FOR_EACH_(N, what, sep, ...) C4_XCAT(_C4_FOR_EACH_, N)(what, sep, __VA_ARGS__)\n\n/// @endcond\n\n#ifdef __clang__\n#   pragma clang diagnostic pop\n#endif\n\n#endif /* _C4_PREPROCESSOR_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/restrict.hpp",
    "content": "#ifndef _C4_RESTRICT_HPP_\n#define _C4_RESTRICT_HPP_\n\n/** @file restrict.hpp macros defining shorthand symbols for restricted\n * pointers and references\n * @see unrestrict.hpp\n * @see restrict\n */\n\n/** @defgroup restrict Restrict utilities\n * macros defining shorthand symbols for restricted\n * pointers and references\n * ```cpp\n * void sum_arrays(size_t sz, float const* C4_RESTRICT a, float const *C4_RESTRICT b, float *result);\n * float * C4_RESTRICT ptr;\n * float & C4_RESTRICT ref = *ptr;\n * float const* C4_RESTRICT cptr;\n * float const& C4_RESTRICT cref = *cptr;\n *\n * // becomes this:\n * #include <c4/restrict.hpp>\n * void sum_arrays(size_t sz, float c$ a, float c$ b, float * result);\n * float   $ ptr;\n * float  $$ ref = *ptr;\n * float  c$ cptr;\n * float c$$ cref = *cptr;\n * ```\n * @ingroup types\n * @{ */\n\n/** @def \\$ a restricted pointer */\n/** @def c\\$ a restricted pointer to const data */\n\n/** @def \\$\\$  a restricted reference */\n/** @def c\\$\\$  a restricted reference to const data */\n\n#ifdef __clang__\n#   pragma clang diagnostic push\n#   pragma clang diagnostic ignored \"-Wdollar-in-identifier-extension\"\n#elif defined(__GNUC__)\n#endif\n\n#define   $       * C4_RESTRICT // a restricted pointer\n#define  c$  const* C4_RESTRICT // a restricted pointer to const data\n\n#define  $$       & C4_RESTRICT // restricted reference\n#define c$$  const& C4_RESTRICT // restricted reference to const data\n\n/** @} */\n\n#endif /* _C4_RESTRICT_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/span.hpp",
    "content": "#ifndef _C4_SPAN_HPP_\n#define _C4_SPAN_HPP_\n\n/** @file span.hpp Provides span classes. */\n\n#include \"c4/config.hpp\"\n#include \"c4/error.hpp\"\n#include \"c4/szconv.hpp\"\n\n#include <algorithm>\n\nnamespace c4 {\n\nC4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH(\"-Wold-style-cast\")\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n/** a crtp base for implementing span classes\n *\n * A span is a non-owning range of elements contiguously stored in memory.\n * Unlike STL's array_view, the span allows write-access to its members.\n *\n * To obtain subspans from a span, the following const member functions\n * are available:\n *  - subspan(first, num)\n *  - range(first, last)\n *  - first(num)\n *  - last(num)\n *\n * A span can also be resized via the following non-const member functions:\n *  - resize(sz)\n *  - ltrim(num)\n *  - rtrim(num)\n *\n * @see span\n * @see cspan\n * @see spanrs\n * @see cspanrs\n * @see spanrsl\n * @see cspanrsl\n */\ntemplate<class T, class I, class SpanImpl>\nclass span_crtp\n{\n// some utility defines, undefined at the end of this class\n#define _c4this  ((SpanImpl      *)this)\n#define _c4cthis ((SpanImpl const*)this)\n#define _c4ptr   ((SpanImpl      *)this)->m_ptr\n#define _c4cptr  ((SpanImpl const*)this)->m_ptr\n#define _c4sz    ((SpanImpl      *)this)->m_size\n#define _c4csz   ((SpanImpl const*)this)->m_size\n\npublic:\n\n    _c4_DEFINE_ARRAY_TYPES(T, I);\n\npublic:\n\n    C4_ALWAYS_INLINE constexpr I value_size() const noexcept { return sizeof(T); }\n    C4_ALWAYS_INLINE constexpr I elm_size  () const noexcept { return sizeof(T); }\n    C4_ALWAYS_INLINE constexpr I type_size () const noexcept { return sizeof(T); }\n    C4_ALWAYS_INLINE           I byte_size () const noexcept { return _c4csz*sizeof(T); }\n\n    C4_ALWAYS_INLINE bool empty()    const noexcept { return _c4csz == 0; }\n    C4_ALWAYS_INLINE I    size()     const noexcept { return _c4csz; }\n    //C4_ALWAYS_INLINE I    capacity() const noexcept { return _c4sz; } // this must be defined by impl classes\n\n    C4_ALWAYS_INLINE void clear() noexcept { _c4sz = 0; }\n\n    C4_ALWAYS_INLINE T      * data()       noexcept { return _c4ptr; }\n    C4_ALWAYS_INLINE T const* data() const noexcept { return _c4cptr; }\n\n    C4_ALWAYS_INLINE       iterator  begin()       noexcept { return _c4ptr; }\n    C4_ALWAYS_INLINE const_iterator  begin() const noexcept { return _c4cptr; }\n    C4_ALWAYS_INLINE const_iterator cbegin() const noexcept { return _c4cptr; }\n\n    C4_ALWAYS_INLINE       iterator  end()       noexcept { return _c4ptr  + _c4sz; }\n    C4_ALWAYS_INLINE const_iterator  end() const noexcept { return _c4cptr + _c4csz; }\n    C4_ALWAYS_INLINE const_iterator cend() const noexcept { return _c4cptr + _c4csz; }\n\n    C4_ALWAYS_INLINE       reverse_iterator  rbegin()       noexcept { return reverse_iterator(_c4ptr + _c4sz); }\n    C4_ALWAYS_INLINE const_reverse_iterator  rbegin() const noexcept { return reverse_iterator(_c4cptr + _c4csz); }\n    C4_ALWAYS_INLINE const_reverse_iterator crbegin() const noexcept { return reverse_iterator(_c4cptr + _c4csz); }\n\n    C4_ALWAYS_INLINE       reverse_iterator  rend()       noexcept { return const_reverse_iterator(_c4ptr); }\n    C4_ALWAYS_INLINE const_reverse_iterator  rend() const noexcept { return const_reverse_iterator(_c4cptr); }\n    C4_ALWAYS_INLINE const_reverse_iterator crend() const noexcept { return const_reverse_iterator(_c4cptr); }\n\n    C4_ALWAYS_INLINE T      & front()       C4_NOEXCEPT_X { C4_XASSERT(!empty()); return _c4ptr [0]; }\n    C4_ALWAYS_INLINE T const& front() const C4_NOEXCEPT_X { C4_XASSERT(!empty()); return _c4cptr[0]; }\n\n    C4_ALWAYS_INLINE T      & back()       C4_NOEXCEPT_X { C4_XASSERT(!empty()); return _c4ptr [_c4sz  - 1]; }\n    C4_ALWAYS_INLINE T const& back() const C4_NOEXCEPT_X { C4_XASSERT(!empty()); return _c4cptr[_c4csz - 1]; }\n\n    C4_ALWAYS_INLINE T      & operator[] (I i)       C4_NOEXCEPT_X { C4_XASSERT(i >= 0 && i < _c4sz ); return _c4ptr [i]; }\n    C4_ALWAYS_INLINE T const& operator[] (I i) const C4_NOEXCEPT_X { C4_XASSERT(i >= 0 && i < _c4csz); return _c4cptr[i]; }\n\n    C4_ALWAYS_INLINE SpanImpl subspan(I first, I num) const C4_NOEXCEPT_X\n    {\n        C4_XASSERT((first >= 0 && first < _c4csz) || (first == _c4csz && num == 0));\n        C4_XASSERT((first + num >= 0) && (first + num <= _c4csz));\n        return _c4cthis->_select(_c4cptr + first, num);\n    }\n    C4_ALWAYS_INLINE SpanImpl subspan(I first) const C4_NOEXCEPT_X ///< goes up until the end of the span\n    {\n        C4_XASSERT(first >= 0 && first <= _c4csz);\n        return _c4cthis->_select(_c4cptr + first, _c4csz - first);\n    }\n\n    C4_ALWAYS_INLINE SpanImpl range(I first, I last) const C4_NOEXCEPT_X ///< last element is NOT included\n    {\n        C4_XASSERT(((first >= 0) && (first < _c4csz)) || (first == _c4csz && first == last));\n        C4_XASSERT((last >= 0) && (last <= _c4csz));\n        C4_XASSERT(last >= first);\n        return _c4cthis->_select(_c4cptr + first, last - first);\n    }\n    C4_ALWAYS_INLINE SpanImpl range(I first) const C4_NOEXCEPT_X ///< goes up until the end of the span\n    {\n        C4_XASSERT(((first >= 0) && (first <= _c4csz)));\n        return _c4cthis->_select(_c4cptr + first, _c4csz - first);\n    }\n\n    C4_ALWAYS_INLINE SpanImpl first(I num) const C4_NOEXCEPT_X ///< get the first num elements, starting at 0\n    {\n        C4_XASSERT((num >= 0) && (num <= _c4csz));\n        return _c4cthis->_select(_c4cptr, num);\n    }\n    C4_ALWAYS_INLINE SpanImpl last(I num) const C4_NOEXCEPT_X ///< get the last num elements, starting at size()-num\n    {\n        C4_XASSERT((num >= 0) && (num <= _c4csz));\n        return _c4cthis->_select(_c4cptr + _c4csz - num, num);\n    }\n\n    bool is_subspan(span_crtp const& ss) const noexcept\n    {\n        if(_c4cptr == nullptr) return false;\n        auto *b = begin(), *e = end();\n        auto *ssb = ss.begin(), *sse = ss.end();\n        if(ssb >= b && sse <= e)\n        {\n            return true;\n        }\n        else\n        {\n            return false;\n        }\n    }\n\n    /** COMPLement Left: return the complement to the left of the beginning of the given subspan.\n     * If ss does not begin inside this, returns an empty substring. */\n    SpanImpl compll(span_crtp const& ss) const C4_NOEXCEPT_X\n    {\n        auto ssb = ss.begin();\n        auto b = begin();\n        auto e = end();\n        if(ssb >= b && ssb <= e)\n        {\n            return subspan(0, static_cast<size_t>(ssb - b));\n        }\n        else\n        {\n            return subspan(0, 0);\n        }\n    }\n\n    /** COMPLement Right: return the complement to the right of the end of the given subspan.\n     * If ss does not end inside this, returns an empty substring. */\n    SpanImpl complr(span_crtp const& ss) const C4_NOEXCEPT_X\n    {\n        auto sse = ss.end();\n        auto b = begin();\n        auto e = end();\n        if(sse >= b && sse <= e)\n        {\n            return subspan(static_cast<size_t>(sse - b), static_cast<size_t>(e - sse));\n        }\n        else\n        {\n            return subspan(0, 0);\n        }\n    }\n\n    C4_ALWAYS_INLINE bool same_span(span_crtp const& that) const noexcept\n    {\n        return size() == that.size() && data() == that.data();\n    }\n    template<class I2, class Impl2>\n    C4_ALWAYS_INLINE bool same_span(span_crtp<T, I2, Impl2> const& that) const C4_NOEXCEPT_X\n    {\n        I tsz = szconv<I>(that.size()); // x-asserts that the size does not overflow\n        return size() == tsz && data() == that.data();\n    }\n\n#undef _c4this\n#undef _c4cthis\n#undef _c4ptr\n#undef _c4cptr\n#undef _c4sz\n#undef _c4csz\n};\n\n//-----------------------------------------------------------------------------\ntemplate<class T, class Il, class Ir, class _Impll, class _Implr>\ninline constexpr bool operator==\n(\n    span_crtp<T, Il, _Impll> const& l,\n    span_crtp<T, Ir, _Implr> const& r\n)\n{\n#if C4_CPP >= 14\n    return std::equal(l.begin(), l.end(), r.begin(), r.end());\n#else\n    return l.same_span(r) || std::equal(l.begin(), l.end(), r.begin());\n#endif\n}\n\ntemplate<class T, class Il, class Ir, class _Impll, class _Implr>\ninline constexpr bool operator!=\n(\n    span_crtp<T, Il, _Impll> const& l,\n    span_crtp<T, Ir, _Implr> const& r\n)\n{\n    return ! (l == r);\n}\n\n//-----------------------------------------------------------------------------\ntemplate<class T, class Il, class Ir, class _Impll, class _Implr>\ninline constexpr bool operator<\n(\n    span_crtp<T, Il, _Impll> const& l,\n    span_crtp<T, Ir, _Implr> const& r\n)\n{\n    return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end());\n}\n\ntemplate<class T, class Il, class Ir, class _Impll, class _Implr>\ninline constexpr bool operator<=\n(\n    span_crtp<T, Il, _Impll> const& l,\n    span_crtp<T, Ir, _Implr> const& r\n)\n{\n    return ! (l > r);\n}\n\n//-----------------------------------------------------------------------------\ntemplate<class T, class Il, class Ir, class _Impll, class _Implr>\ninline constexpr bool operator>\n(\n    span_crtp<T, Il, _Impll> const& l,\n    span_crtp<T, Ir, _Implr> const& r\n)\n{\n    return r < l;\n}\n\n//-----------------------------------------------------------------------------\ntemplate<class T, class Il, class Ir, class _Impll, class _Implr>\ninline constexpr bool operator>=\n(\n    span_crtp<T, Il, _Impll> const& l,\n    span_crtp<T, Ir, _Implr> const& r\n)\n{\n    return ! (l < r);\n}\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n/** A non-owning span of elements contiguously stored in memory. */\ntemplate<class T, class I=C4_SIZE_TYPE>\nclass span : public span_crtp<T, I, span<T, I>>\n{\n    friend class span_crtp<T, I, span<T, I>>;\n\n    T * C4_RESTRICT m_ptr;\n    I   m_size;\n\n    C4_ALWAYS_INLINE span _select(T *p, I sz) const { return span(p, sz); }\n\npublic:\n\n    _c4_DEFINE_ARRAY_TYPES(T, I);\n    using NCT = typename std::remove_const<T>::type; //!< NCT=non const type\n    using CT = typename std::add_const<T>::type; //!< CT=const type\n    using const_type = span<CT, I>;\n\n    /// convert automatically to span of const T\n    operator span<CT, I> () const { span<CT, I> s(m_ptr, m_size); return s; }\n\npublic:\n\n    C4_ALWAYS_INLINE C4_CONSTEXPR14 span() noexcept : m_ptr{nullptr}, m_size{0} {}\n\n    span(span const&) = default;\n    span(span     &&) = default;\n\n    span& operator= (span const&) = default;\n    span& operator= (span     &&) = default;\n\npublic:\n\n    /** @name Construction and assignment from same type */\n    /** @{ */\n\n    template<size_t N> C4_ALWAYS_INLINE C4_CONSTEXPR14      span  (T (&arr)[N]) noexcept : m_ptr{arr}, m_size{N} {}\n    template<size_t N> C4_ALWAYS_INLINE C4_CONSTEXPR14 void assign(T (&arr)[N]) noexcept { m_ptr = arr; m_size = N; }\n\n    C4_ALWAYS_INLINE C4_CONSTEXPR14        span(T *p, I sz) noexcept : m_ptr{p}, m_size{sz} {}\n    C4_ALWAYS_INLINE C4_CONSTEXPR14 void   assign(T *p, I sz) noexcept { m_ptr = p; m_size = sz; }\n\n    C4_ALWAYS_INLINE C4_CONSTEXPR14      span  (c4::aggregate_t, std::initializer_list<T> il) noexcept : m_ptr{&*il.begin()}, m_size{il.size()} {}\n    C4_ALWAYS_INLINE C4_CONSTEXPR14 void assign(c4::aggregate_t, std::initializer_list<T> il) noexcept { m_ptr = &*il.begin(); m_size = il.size(); }\n\n    /** @} */\n\npublic:\n\n    C4_ALWAYS_INLINE I capacity() const noexcept { return m_size; }\n\n    C4_ALWAYS_INLINE void resize(I sz) C4_NOEXCEPT_A { C4_ASSERT(sz <= m_size); m_size = sz; }\n    C4_ALWAYS_INLINE void rtrim (I n ) C4_NOEXCEPT_A { C4_ASSERT(n >= 0 && n < m_size); m_size -= n; }\n    C4_ALWAYS_INLINE void ltrim (I n ) C4_NOEXCEPT_A { C4_ASSERT(n >= 0 && n < m_size); m_size -= n; m_ptr += n; }\n\n};\ntemplate<class T, class I=C4_SIZE_TYPE> using cspan = span<const T, I>;\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n/** A non-owning span resizeable up to a capacity. Subselection or resizing\n * will keep the original provided it starts at begin(). If subselection or\n * resizing change the pointer, then the original capacity information will\n * be lost.\n *\n * Thus, resizing via resize() and ltrim() and subselecting via first()\n * or any of subspan() or range() when starting from the beginning will keep\n * the original capacity. OTOH, using last(), or any of subspan() or range()\n * with an offset from the start will remove from capacity (shifting the\n * pointer) by the corresponding offset. If this is undesired, then consider\n * using spanrsl.\n *\n * @see spanrs for a span resizeable on the right\n * @see spanrsl for a span resizeable on the right and left\n */\n\ntemplate<class T, class I=C4_SIZE_TYPE>\nclass spanrs : public span_crtp<T, I, spanrs<T, I>>\n{\n    friend class span_crtp<T, I, spanrs<T, I>>;\n\n    T * C4_RESTRICT m_ptr;\n    I   m_size;\n    I   m_capacity;\n\n    C4_ALWAYS_INLINE spanrs _select(T *p, I sz) const noexcept\n    {\n        C4_ASSERT(p >= m_ptr);\n        size_t delta = static_cast<size_t>(p - m_ptr);\n        C4_ASSERT(m_capacity >= delta);\n        return spanrs(p, sz, static_cast<size_t>(m_capacity - delta));\n    }\n\npublic:\n\n    _c4_DEFINE_ARRAY_TYPES(T, I);\n    using NCT = typename std::remove_const<T>::type; //!< NCT=non const type\n    using CT = typename std::add_const<T>::type; //!< CT=const type\n    using const_type = spanrs<CT, I>;\n\n    /// convert automatically to span of T\n    C4_ALWAYS_INLINE operator span<T, I > () const noexcept { return span<T, I>(m_ptr, m_size); }\n    /// convert automatically to span of const T\n    //C4_ALWAYS_INLINE operator span<CT, I> () const noexcept { span<CT, I> s(m_ptr, m_size); return s; }\n    /// convert automatically to spanrs of const T\n    C4_ALWAYS_INLINE operator spanrs<CT, I> () const noexcept { spanrs<CT, I> s(m_ptr, m_size, m_capacity); return s; }\n\npublic:\n\n    C4_ALWAYS_INLINE spanrs() noexcept : m_ptr{nullptr}, m_size{0}, m_capacity{0} {}\n\n    spanrs(spanrs const&) = default;\n    spanrs(spanrs     &&) = default;\n\n    spanrs& operator= (spanrs const&) = default;\n    spanrs& operator= (spanrs     &&) = default;\n\npublic:\n\n    /** @name Construction and assignment from same type */\n    /** @{ */\n\n    C4_ALWAYS_INLINE      spanrs(T *p, I sz) noexcept : m_ptr{p}, m_size{sz}, m_capacity{sz} {}\n    /** @warning will reset the capacity to sz */\n    C4_ALWAYS_INLINE void assign(T *p, I sz) noexcept { m_ptr = p; m_size = sz; m_capacity = sz; }\n\n    C4_ALWAYS_INLINE      spanrs(T *p, I sz, I cap) noexcept : m_ptr{p}, m_size{sz}, m_capacity{cap} {}\n    C4_ALWAYS_INLINE void assign(T *p, I sz, I cap) noexcept { m_ptr = p; m_size = sz; m_capacity = cap; }\n\n    template<size_t N> C4_ALWAYS_INLINE      spanrs(T (&arr)[N]) noexcept : m_ptr{arr}, m_size{N}, m_capacity{N} {}\n    template<size_t N> C4_ALWAYS_INLINE void assign(T (&arr)[N]) noexcept { m_ptr = arr; m_size = N; m_capacity = N; }\n\n    C4_ALWAYS_INLINE      spanrs(c4::aggregate_t, std::initializer_list<T> il) noexcept : m_ptr{il.begin()}, m_size{il.size()}, m_capacity{il.size()} {}\n    C4_ALWAYS_INLINE void assign(c4::aggregate_t, std::initializer_list<T> il) noexcept { m_ptr = il.begin(); m_size = il.size(); m_capacity = il.size(); }\n\n    /** @} */\n\npublic:\n\n    C4_ALWAYS_INLINE I capacity() const noexcept { return m_capacity; }\n\n    C4_ALWAYS_INLINE void resize(I sz) C4_NOEXCEPT_A { C4_ASSERT(sz <= m_capacity); m_size = sz; }\n    C4_ALWAYS_INLINE void rtrim (I n ) C4_NOEXCEPT_A { C4_ASSERT(n >= 0 && n < m_size); m_size -= n; }\n    C4_ALWAYS_INLINE void ltrim (I n ) C4_NOEXCEPT_A { C4_ASSERT(n >= 0 && n < m_size); m_size -= n; m_ptr += n; m_capacity -= n; }\n\n};\ntemplate<class T, class I=C4_SIZE_TYPE> using cspanrs = spanrs<const T, I>;\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n/** A non-owning span which always retains the capacity of the original\n * range it was taken from (though it may loose its original size).\n * The resizing methods resize(), ltrim(), rtrim() as well\n * as the subselection methods subspan(), range(), first() and last() can be\n * used at will without loosing the original capacity; the full capacity span\n * can always be recovered by calling original().\n */\ntemplate<class T, class I=C4_SIZE_TYPE>\nclass spanrsl : public span_crtp<T, I, spanrsl<T, I>>\n{\n    friend class span_crtp<T, I, spanrsl<T, I>>;\n\n    T *C4_RESTRICT m_ptr;      ///< the current ptr. the original ptr is (m_ptr - m_offset).\n    I   m_size;     ///< the current size. the original size is unrecoverable.\n    I   m_capacity; ///< the current capacity. the original capacity is (m_capacity + m_offset).\n    I   m_offset;   ///< the offset of the current m_ptr to the start of the original memory block.\n\n    C4_ALWAYS_INLINE spanrsl _select(T *p, I sz) const noexcept\n    {\n        C4_ASSERT(p >= m_ptr);\n        I delta = static_cast<I>(p - m_ptr);\n        C4_ASSERT(m_capacity >= delta);\n        return spanrsl(p, sz, static_cast<I>(m_capacity - delta), m_offset + delta);\n    }\n\npublic:\n\n    _c4_DEFINE_ARRAY_TYPES(T, I);\n    using NCT = typename std::remove_const<T>::type; //!< NCT=non const type\n    using CT = typename std::add_const<T>::type; //!< CT=const type\n    using const_type = spanrsl<CT, I>;\n\n    C4_ALWAYS_INLINE operator span<T, I> () const noexcept { return span<T, I>(m_ptr, m_size); }\n    C4_ALWAYS_INLINE operator spanrs<T, I> () const noexcept { return spanrs<T, I>(m_ptr, m_size, m_capacity); }\n    C4_ALWAYS_INLINE operator spanrsl<CT, I> () const noexcept { return spanrsl<CT, I>(m_ptr, m_size, m_capacity, m_offset); }\n\npublic:\n\n    C4_ALWAYS_INLINE spanrsl() noexcept : m_ptr{nullptr}, m_size{0}, m_capacity{0}, m_offset{0} {}\n\n    spanrsl(spanrsl const&) = default;\n    spanrsl(spanrsl     &&) = default;\n\n    spanrsl& operator= (spanrsl const&) = default;\n    spanrsl& operator= (spanrsl     &&) = default;\n\npublic:\n\n    C4_ALWAYS_INLINE     spanrsl(T *p, I sz) noexcept : m_ptr{p}, m_size{sz}, m_capacity{sz}, m_offset{0} {}\n    C4_ALWAYS_INLINE void assign(T *p, I sz) noexcept { m_ptr = p; m_size = sz; m_capacity = sz; m_offset = 0; }\n\n    C4_ALWAYS_INLINE     spanrsl(T *p, I sz, I cap) noexcept : m_ptr{p}, m_size{sz}, m_capacity{cap}, m_offset{0} {}\n    C4_ALWAYS_INLINE void assign(T *p, I sz, I cap) noexcept { m_ptr = p; m_size = sz; m_capacity = cap; m_offset = 0; }\n\n    C4_ALWAYS_INLINE     spanrsl(T *p, I sz, I cap, I offs) noexcept : m_ptr{p}, m_size{sz}, m_capacity{cap}, m_offset{offs} {}\n    C4_ALWAYS_INLINE void assign(T *p, I sz, I cap, I offs) noexcept { m_ptr = p; m_size = sz; m_capacity = cap; m_offset = offs; }\n\n    template<size_t N> C4_ALWAYS_INLINE     spanrsl(T (&arr)[N]) noexcept : m_ptr{arr}, m_size{N}, m_capacity{N}, m_offset{0} {}\n    template<size_t N> C4_ALWAYS_INLINE void assign(T (&arr)[N]) noexcept { m_ptr = arr; m_size = N; m_capacity = N; m_offset = 0; }\n\n    C4_ALWAYS_INLINE      spanrsl(c4::aggregate_t, std::initializer_list<T> il) noexcept : m_ptr{il.begin()}, m_size{il.size()}, m_capacity{il.size()}, m_offset{0} {}\n    C4_ALWAYS_INLINE void assign (c4::aggregate_t, std::initializer_list<T> il) noexcept { m_ptr = il.begin(); m_size = il.size(); m_capacity = il.size(); m_offset = 0; }\n\npublic:\n\n    C4_ALWAYS_INLINE I offset() const noexcept { return m_offset; }\n    C4_ALWAYS_INLINE I capacity() const noexcept { return m_capacity; }\n\n    C4_ALWAYS_INLINE void resize(I sz) C4_NOEXCEPT_A { C4_ASSERT(sz <= m_capacity); m_size = sz; }\n    C4_ALWAYS_INLINE void rtrim (I n ) C4_NOEXCEPT_A { C4_ASSERT(n >= 0 && n < m_size); m_size -= n; }\n    C4_ALWAYS_INLINE void ltrim (I n ) C4_NOEXCEPT_A { C4_ASSERT(n >= 0 && n < m_size); m_size -= n; m_ptr += n; m_offset += n; m_capacity -= n; }\n\n    /** recover the original span as an spanrsl */\n    C4_ALWAYS_INLINE spanrsl original() const\n    {\n        return spanrsl(m_ptr - m_offset, m_capacity + m_offset, m_capacity + m_offset, 0);\n    }\n    /** recover the original span as a different span type. Example: spanrs<...> orig = s.original<spanrs>(); */\n    template<template<class, class> class OtherSpanType>\n    C4_ALWAYS_INLINE OtherSpanType<T, I> original()\n    {\n        return OtherSpanType<T, I>(m_ptr - m_offset, m_capacity + m_offset);\n    }\n};\ntemplate<class T, class I=C4_SIZE_TYPE> using cspanrsl = spanrsl<const T, I>;\n\nC4_SUPPRESS_WARNING_GCC_CLANG_POP\n\n} // namespace c4\n\n\n#endif /* _C4_SPAN_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/std/std.hpp",
    "content": "#ifndef _C4_STD_STD_HPP_\n#define _C4_STD_STD_HPP_\n\n/** @file std.hpp includes all c4-std interop files */\n\n#include \"c4/std/vector.hpp\"\n#include \"c4/std/string.hpp\"\n#include \"c4/std/string_view.hpp\"\n#include \"c4/std/tuple.hpp\"\n\n#endif // _C4_STD_STD_HPP_\n"
  },
  {
    "path": "libs/rapidyaml/c4/std/std_fwd.hpp",
    "content": "#ifndef _C4_STD_STD_FWD_HPP_\n#define _C4_STD_STD_FWD_HPP_\n\n/** @file std_fwd.hpp includes all c4-std interop fwd files */\n\n#include \"c4/std/vector_fwd.hpp\"\n#include \"c4/std/string_fwd.hpp\"\n//#include \"c4/std/tuple_fwd.hpp\"\n\n#endif // _C4_STD_STD_FWD_HPP_\n"
  },
  {
    "path": "libs/rapidyaml/c4/std/string.hpp",
    "content": "#ifndef _C4_STD_STRING_HPP_\n#define _C4_STD_STRING_HPP_\n\n/** @file string.hpp */\n\n#ifndef C4CORE_SINGLE_HEADER\n#include \"c4/substr.hpp\"\n#endif\n\n#include <string>\n\nnamespace c4 {\n\n//-----------------------------------------------------------------------------\n\n/** get a writeable view to an existing std::string.\n * When the string is empty, the returned view will be pointing\n * at the character with value '\\0', but the size will be zero.\n * @see https://en.cppreference.com/w/cpp/string/basic_string/operator_at\n */\nC4_ALWAYS_INLINE c4::substr to_substr(std::string &s) noexcept\n{\n    #if C4_CPP < 11\n    #error this function will have undefined behavior\n    #endif\n    // since c++11 it is legal to call s[s.size()].\n    return c4::substr(&s[0], s.size());\n}\n\n/** get a readonly view to an existing std::string.\n * When the string is empty, the returned view will be pointing\n * at the character with value '\\0', but the size will be zero.\n * @see https://en.cppreference.com/w/cpp/string/basic_string/operator_at\n */\nC4_ALWAYS_INLINE c4::csubstr to_csubstr(std::string const& s) noexcept\n{\n    #if C4_CPP < 11\n    #error this function will have undefined behavior\n    #endif\n    // since c++11 it is legal to call s[s.size()].\n    return c4::csubstr(&s[0], s.size());\n}\n\n//-----------------------------------------------------------------------------\n\nC4_ALWAYS_INLINE bool operator== (c4::csubstr ss, std::string const& s) { return ss.compare(to_csubstr(s)) == 0; }\nC4_ALWAYS_INLINE bool operator!= (c4::csubstr ss, std::string const& s) { return ss.compare(to_csubstr(s)) != 0; }\nC4_ALWAYS_INLINE bool operator>= (c4::csubstr ss, std::string const& s) { return ss.compare(to_csubstr(s)) >= 0; }\nC4_ALWAYS_INLINE bool operator>  (c4::csubstr ss, std::string const& s) { return ss.compare(to_csubstr(s)) >  0; }\nC4_ALWAYS_INLINE bool operator<= (c4::csubstr ss, std::string const& s) { return ss.compare(to_csubstr(s)) <= 0; }\nC4_ALWAYS_INLINE bool operator<  (c4::csubstr ss, std::string const& s) { return ss.compare(to_csubstr(s)) <  0; }\n\nC4_ALWAYS_INLINE bool operator== (std::string const& s, c4::csubstr ss) { return ss.compare(to_csubstr(s)) == 0; }\nC4_ALWAYS_INLINE bool operator!= (std::string const& s, c4::csubstr ss) { return ss.compare(to_csubstr(s)) != 0; }\nC4_ALWAYS_INLINE bool operator>= (std::string const& s, c4::csubstr ss) { return ss.compare(to_csubstr(s)) <= 0; }\nC4_ALWAYS_INLINE bool operator>  (std::string const& s, c4::csubstr ss) { return ss.compare(to_csubstr(s)) <  0; }\nC4_ALWAYS_INLINE bool operator<= (std::string const& s, c4::csubstr ss) { return ss.compare(to_csubstr(s)) >= 0; }\nC4_ALWAYS_INLINE bool operator<  (std::string const& s, c4::csubstr ss) { return ss.compare(to_csubstr(s)) >  0; }\n\n//-----------------------------------------------------------------------------\n\n/** copy an std::string to a writeable string view */\ninline size_t to_chars(c4::substr buf, std::string const& s)\n{\n    C4_ASSERT(!buf.overlaps(to_csubstr(s)));\n    size_t len = buf.len < s.size() ? buf.len : s.size();\n    // calling memcpy with null strings is undefined behavior\n    // and will wreak havoc in calling code's branches.\n    // see https://github.com/biojppm/rapidyaml/pull/264#issuecomment-1262133637\n    if(len)\n    {\n        C4_ASSERT(s.data() != nullptr);\n        C4_ASSERT(buf.str != nullptr);\n        memcpy(buf.str, s.data(), len);\n    }\n    return s.size(); // return the number of needed chars\n}\n\n/** copy a string view to an existing std::string */\ninline bool from_chars(c4::csubstr buf, std::string * s)\n{\n    s->resize(buf.len);\n    C4_ASSERT(!buf.overlaps(to_csubstr(*s)));\n    // calling memcpy with null strings is undefined behavior\n    // and will wreak havoc in calling code's branches.\n    // see https://github.com/biojppm/rapidyaml/pull/264#issuecomment-1262133637\n    if(buf.len)\n    {\n        C4_ASSERT(buf.str != nullptr);\n        memcpy(&(*s)[0], buf.str, buf.len);\n    }\n    return true;\n}\n\n} // namespace c4\n\n#endif // _C4_STD_STRING_HPP_\n"
  },
  {
    "path": "libs/rapidyaml/c4/std/string_fwd.hpp",
    "content": "#ifndef _C4_STD_STRING_FWD_HPP_\n#define _C4_STD_STRING_FWD_HPP_\n\n/** @file string_fwd.hpp */\n\n#ifndef DOXYGEN\n\n#ifndef C4CORE_SINGLE_HEADER\n#include \"c4/substr_fwd.hpp\"\n#endif\n\n#include <cstddef>\n\n// forward declarations for std::string\n#if defined(__GLIBCXX__) || defined(__GLIBCPP__)\n#include <bits/stringfwd.h>  // use the fwd header in glibcxx\n#elif defined(_LIBCPP_VERSION) || defined(__APPLE_CC__)\n#include <iosfwd>  // use the fwd header in stdlibc++\n#elif defined(_MSC_VER)\n#include \"c4/error.hpp\"\n//! @todo is there a fwd header in msvc?\nnamespace std {\nC4_SUPPRESS_WARNING_MSVC_WITH_PUSH(4643) // Forward declaring 'char_traits' in namespace std is not permitted by the C++ Standard.\ntemplate<typename> struct char_traits;\ntemplate<typename> class allocator;\ntemplate<typename _CharT, typename _Traits, typename _Alloc> class basic_string;\nusing string = basic_string<char, char_traits<char>, allocator<char>>;\nC4_SUPPRESS_WARNING_MSVC_POP\n} /* namespace std */\n#else\n#error \"unknown standard library\"\n#endif\n\nnamespace c4 {\n\nc4::substr to_substr(std::string &s) noexcept;\nc4::csubstr to_csubstr(std::string const& s) noexcept;\n\nbool operator== (c4::csubstr ss, std::string const& s);\nbool operator!= (c4::csubstr ss, std::string const& s);\nbool operator>= (c4::csubstr ss, std::string const& s);\nbool operator>  (c4::csubstr ss, std::string const& s);\nbool operator<= (c4::csubstr ss, std::string const& s);\nbool operator<  (c4::csubstr ss, std::string const& s);\n\nbool operator== (std::string const& s, c4::csubstr ss);\nbool operator!= (std::string const& s, c4::csubstr ss);\nbool operator>= (std::string const& s, c4::csubstr ss);\nbool operator>  (std::string const& s, c4::csubstr ss);\nbool operator<= (std::string const& s, c4::csubstr ss);\nbool operator<  (std::string const& s, c4::csubstr ss);\n\nsize_t to_chars(c4::substr buf, std::string const& s);\nbool from_chars(c4::csubstr buf, std::string * s);\n\n} // namespace c4\n\n#endif // DOXYGEN\n#endif // _C4_STD_STRING_FWD_HPP_\n"
  },
  {
    "path": "libs/rapidyaml/c4/std/string_view.hpp",
    "content": "#ifndef _C4_STD_STRING_VIEW_HPP_\n#define _C4_STD_STRING_VIEW_HPP_\n\n/** @file string_view.hpp */\n\n#ifndef C4CORE_SINGLE_HEADER\n#include \"c4/language.hpp\"\n#endif\n\n#if (C4_CPP >= 17 && defined(__cpp_lib_string_view)) || defined(__DOXYGEN__)\n\n#ifndef C4CORE_SINGLE_HEADER\n#include \"c4/substr.hpp\"\n#endif\n\n#include <string_view>\n\n\nnamespace c4 {\n\n//-----------------------------------------------------------------------------\n\n/** create a csubstr from an existing std::string_view. */\nC4_ALWAYS_INLINE c4::csubstr to_csubstr(std::string_view s) noexcept\n{\n    return c4::csubstr(s.data(), s.size());\n}\n\n\n//-----------------------------------------------------------------------------\n\nC4_ALWAYS_INLINE bool operator== (c4::csubstr ss, std::string_view s) { return ss.compare(s.data(), s.size()) == 0; }\nC4_ALWAYS_INLINE bool operator!= (c4::csubstr ss, std::string_view s) { return ss.compare(s.data(), s.size()) != 0; }\nC4_ALWAYS_INLINE bool operator>= (c4::csubstr ss, std::string_view s) { return ss.compare(s.data(), s.size()) >= 0; }\nC4_ALWAYS_INLINE bool operator>  (c4::csubstr ss, std::string_view s) { return ss.compare(s.data(), s.size()) >  0; }\nC4_ALWAYS_INLINE bool operator<= (c4::csubstr ss, std::string_view s) { return ss.compare(s.data(), s.size()) <= 0; }\nC4_ALWAYS_INLINE bool operator<  (c4::csubstr ss, std::string_view s) { return ss.compare(s.data(), s.size()) <  0; }\n\nC4_ALWAYS_INLINE bool operator== (std::string_view s, c4::csubstr ss) { return ss.compare(s.data(), s.size()) == 0; }\nC4_ALWAYS_INLINE bool operator!= (std::string_view s, c4::csubstr ss) { return ss.compare(s.data(), s.size()) != 0; }\nC4_ALWAYS_INLINE bool operator<= (std::string_view s, c4::csubstr ss) { return ss.compare(s.data(), s.size()) >= 0; }\nC4_ALWAYS_INLINE bool operator<  (std::string_view s, c4::csubstr ss) { return ss.compare(s.data(), s.size()) >  0; }\nC4_ALWAYS_INLINE bool operator>= (std::string_view s, c4::csubstr ss) { return ss.compare(s.data(), s.size()) <= 0; }\nC4_ALWAYS_INLINE bool operator>  (std::string_view s, c4::csubstr ss) { return ss.compare(s.data(), s.size()) <  0; }\n\n\n//-----------------------------------------------------------------------------\n\n/** copy an std::string_view to a writeable substr */\ninline size_t to_chars(c4::substr buf, std::string_view s)\n{\n    C4_ASSERT(!buf.overlaps(to_csubstr(s)));\n    size_t sz = s.size();\n    size_t len = buf.len < sz ? buf.len : sz;\n    // calling memcpy with null strings is undefined behavior\n    // and will wreak havoc in calling code's branches.\n    // see https://github.com/biojppm/rapidyaml/pull/264#issuecomment-1262133637\n    if(len)\n    {\n        C4_ASSERT(s.data() != nullptr);\n        C4_ASSERT(buf.str != nullptr);\n        memcpy(buf.str, s.data(), len);\n    }\n    return sz; // return the number of needed chars\n}\n\n} // namespace c4\n\n#endif // C4_STRING_VIEW_AVAILABLE\n\n#endif // _C4_STD_STRING_VIEW_HPP_\n"
  },
  {
    "path": "libs/rapidyaml/c4/std/tuple.hpp",
    "content": "#ifndef _C4_STD_TUPLE_HPP_\n#define _C4_STD_TUPLE_HPP_\n\n/** @file tuple.hpp */\n\n#ifndef C4CORE_SINGLE_HEADER\n#include \"c4/format.hpp\"\n#endif\n\n#include <tuple>\n\n/** this is a work in progress */\n#undef C4_TUPLE_TO_CHARS\n\nnamespace c4 {\n\n#ifdef C4_TUPLE_TO_CHARS\nnamespace detail {\n\ntemplate< size_t Curr, class... Types >\nstruct tuple_helper\n{\n    static size_t do_cat(substr buf, std::tuple< Types... > const& tp)\n    {\n        size_t num = to_chars(buf, std::get<Curr>(tp));\n        buf = buf.len >= num ? buf.sub(num) : substr{};\n        num += tuple_helper< Curr+1, Types... >::do_cat(buf, tp);\n        return num;\n    }\n\n    static size_t do_uncat(csubstr buf, std::tuple< Types... > & tp)\n    {\n        size_t num = from_str_trim(buf, &std::get<Curr>(tp));\n        if(num == csubstr::npos) return csubstr::npos;\n        buf = buf.len >= num ? buf.sub(num) : substr{};\n        num += tuple_helper< Curr+1, Types... >::do_uncat(buf, tp);\n        return num;\n    }\n\n    template< class Sep >\n    static size_t do_catsep_more(substr buf, Sep const& sep, std::tuple< Types... > const& tp)\n    {\n        size_t ret = to_chars(buf, sep), num = ret;\n        buf  = buf.len >= ret ? buf.sub(ret) : substr{};\n        ret  = to_chars(buf, std::get<Curr>(tp));\n        num += ret;\n        buf  = buf.len >= ret ? buf.sub(ret) : substr{};\n        ret  = tuple_helper< Curr+1, Types... >::do_catsep_more(buf, sep, tp);\n        num += ret;\n        return num;\n    }\n\n    template< class Sep >\n    static size_t do_uncatsep_more(csubstr buf, Sep & sep, std::tuple< Types... > & tp)\n    {\n        size_t ret = from_str_trim(buf, &sep), num = ret;\n        if(ret == csubstr::npos) return csubstr::npos;\n        buf  = buf.len >= ret ? buf.sub(ret) : substr{};\n        ret  = from_str_trim(buf, &std::get<Curr>(tp));\n        if(ret == csubstr::npos) return csubstr::npos;\n        num += ret;\n        buf  = buf.len >= ret ? buf.sub(ret) : substr{};\n        ret  = tuple_helper< Curr+1, Types... >::do_uncatsep_more(buf, sep, tp);\n        if(ret == csubstr::npos) return csubstr::npos;\n        num += ret;\n        return num;\n    }\n\n    static size_t do_format(substr buf, csubstr fmt, std::tuple< Types... > const& tp)\n    {\n        auto pos = fmt.find(\"{}\");\n        if(pos != csubstr::npos)\n        {\n            size_t num = to_chars(buf, fmt.sub(0, pos));\n            size_t out = num;\n            buf  = buf.len >= num ? buf.sub(num) : substr{};\n            num  = to_chars(buf, std::get<Curr>(tp));\n            out += num;\n            buf  = buf.len >= num ? buf.sub(num) : substr{};\n            num  = tuple_helper< Curr+1, Types... >::do_format(buf, fmt.sub(pos + 2), tp);\n            out += num;\n            return out;\n        }\n        else\n        {\n            return format(buf, fmt);\n        }\n    }\n\n    static size_t do_unformat(csubstr buf, csubstr fmt, std::tuple< Types... > & tp)\n    {\n        auto pos = fmt.find(\"{}\");\n        if(pos != csubstr::npos)\n        {\n            size_t num = pos;\n            size_t out = num;\n            buf  = buf.len >= num ? buf.sub(num) : substr{};\n            num  = from_str_trim(buf, &std::get<Curr>(tp));\n            out += num;\n            buf  = buf.len >= num ? buf.sub(num) : substr{};\n            num  = tuple_helper< Curr+1, Types... >::do_unformat(buf, fmt.sub(pos + 2), tp);\n            out += num;\n            return out;\n        }\n        else\n        {\n            return tuple_helper< sizeof...(Types), Types... >::do_unformat(buf, fmt, tp);\n        }\n    }\n\n};\n\n/** @todo VS compilation fails for this class */\ntemplate< class... Types >\nstruct tuple_helper< sizeof...(Types), Types... >\n{\n    static size_t do_cat(substr /*buf*/, std::tuple<Types...> const& /*tp*/) { return 0; }\n    static size_t do_uncat(csubstr /*buf*/, std::tuple<Types...> & /*tp*/) { return 0; }\n\n    template< class Sep > static size_t do_catsep_more(substr /*buf*/, Sep const& /*sep*/, std::tuple<Types...> const& /*tp*/) { return 0; }\n    template< class Sep > static size_t do_uncatsep_more(csubstr /*buf*/, Sep & /*sep*/, std::tuple<Types...> & /*tp*/) { return 0; }\n\n    static size_t do_format(substr buf, csubstr fmt, std::tuple<Types...> const& /*tp*/)\n    {\n        return to_chars(buf, fmt);\n    }\n\n    static size_t do_unformat(csubstr buf, csubstr fmt, std::tuple<Types...> const& /*tp*/)\n    {\n        return 0;\n    }\n};\n\n} // namespace detail\n\ntemplate< class... Types >\ninline size_t cat(substr buf, std::tuple< Types... > const& tp)\n{\n    return detail::tuple_helper< 0, Types... >::do_cat(buf, tp);\n}\n\ntemplate< class... Types >\ninline size_t uncat(csubstr buf, std::tuple< Types... > & tp)\n{\n    return detail::tuple_helper< 0, Types... >::do_uncat(buf, tp);\n}\n\ntemplate< class Sep, class... Types >\ninline size_t catsep(substr buf, Sep const& sep, std::tuple< Types... > const& tp)\n{\n    size_t num = to_chars(buf, std::cref(std::get<0>(tp)));\n    buf  = buf.len >= num ? buf.sub(num) : substr{};\n    num += detail::tuple_helper< 1, Types... >::do_catsep_more(buf, sep, tp);\n    return num;\n}\n\ntemplate< class Sep, class... Types >\ninline size_t uncatsep(csubstr buf, Sep & sep, std::tuple< Types... > & tp)\n{\n    size_t ret = from_str_trim(buf, &std::get<0>(tp)), num = ret;\n    if(ret == csubstr::npos) return csubstr::npos;\n    buf  = buf.len >= ret ? buf.sub(ret) : substr{};\n    ret  = detail::tuple_helper< 1, Types... >::do_uncatsep_more(buf, sep, tp);\n    if(ret == csubstr::npos) return csubstr::npos;\n    num += ret;\n    return num;\n}\n\ntemplate< class... Types >\ninline size_t format(substr buf, csubstr fmt, std::tuple< Types... > const& tp)\n{\n    return detail::tuple_helper< 0, Types... >::do_format(buf, fmt, tp);\n}\n\ntemplate< class... Types >\ninline size_t unformat(csubstr buf, csubstr fmt, std::tuple< Types... > & tp)\n{\n    return detail::tuple_helper< 0, Types... >::do_unformat(buf, fmt, tp);\n}\n#endif // C4_TUPLE_TO_CHARS\n\n} // namespace c4\n\n#endif /* _C4_STD_TUPLE_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/std/vector.hpp",
    "content": "#ifndef _C4_STD_VECTOR_HPP_\n#define _C4_STD_VECTOR_HPP_\n\n/** @file vector.hpp provides conversion and comparison facilities\n * from/between std::vector<char> to c4::substr and c4::csubstr.\n * @todo add to_span() and friends\n */\n\n#ifndef C4CORE_SINGLE_HEADER\n#include \"c4/substr.hpp\"\n#endif\n\n#include <vector>\n\nnamespace c4 {\n\n//-----------------------------------------------------------------------------\n\n/** get a substr (writeable string view) of an existing std::vector<char> */\ntemplate<class Alloc>\nc4::substr to_substr(std::vector<char, Alloc> &vec)\n{\n    char *data = vec.empty() ? nullptr : vec.data(); // data() may or may not return a null pointer.\n    return c4::substr(data, vec.size());\n}\n\n/** get a csubstr (read-only string) view of an existing std::vector<char> */\ntemplate<class Alloc>\nc4::csubstr to_csubstr(std::vector<char, Alloc> const& vec)\n{\n    const char *data = vec.empty() ? nullptr : vec.data(); // data() may or may not return a null pointer.\n    return c4::csubstr(data, vec.size());\n}\n\n//-----------------------------------------------------------------------------\n// comparisons between substrings and std::vector<char>\n\ntemplate<class Alloc> C4_ALWAYS_INLINE bool operator!= (c4::csubstr ss, std::vector<char, Alloc> const& s) { return ss != to_csubstr(s); }\ntemplate<class Alloc> C4_ALWAYS_INLINE bool operator== (c4::csubstr ss, std::vector<char, Alloc> const& s) { return ss == to_csubstr(s); }\ntemplate<class Alloc> C4_ALWAYS_INLINE bool operator>= (c4::csubstr ss, std::vector<char, Alloc> const& s) { return ss >= to_csubstr(s); }\ntemplate<class Alloc> C4_ALWAYS_INLINE bool operator>  (c4::csubstr ss, std::vector<char, Alloc> const& s) { return ss >  to_csubstr(s); }\ntemplate<class Alloc> C4_ALWAYS_INLINE bool operator<= (c4::csubstr ss, std::vector<char, Alloc> const& s) { return ss <= to_csubstr(s); }\ntemplate<class Alloc> C4_ALWAYS_INLINE bool operator<  (c4::csubstr ss, std::vector<char, Alloc> const& s) { return ss <  to_csubstr(s); }\n\ntemplate<class Alloc> C4_ALWAYS_INLINE bool operator!= (std::vector<char, Alloc> const& s, c4::csubstr ss) { return ss != to_csubstr(s); }\ntemplate<class Alloc> C4_ALWAYS_INLINE bool operator== (std::vector<char, Alloc> const& s, c4::csubstr ss) { return ss == to_csubstr(s); }\ntemplate<class Alloc> C4_ALWAYS_INLINE bool operator>= (std::vector<char, Alloc> const& s, c4::csubstr ss) { return ss <= to_csubstr(s); }\ntemplate<class Alloc> C4_ALWAYS_INLINE bool operator>  (std::vector<char, Alloc> const& s, c4::csubstr ss) { return ss <  to_csubstr(s); }\ntemplate<class Alloc> C4_ALWAYS_INLINE bool operator<= (std::vector<char, Alloc> const& s, c4::csubstr ss) { return ss >= to_csubstr(s); }\ntemplate<class Alloc> C4_ALWAYS_INLINE bool operator<  (std::vector<char, Alloc> const& s, c4::csubstr ss) { return ss >  to_csubstr(s); }\n\n//-----------------------------------------------------------------------------\n\n/** copy a std::vector<char> to a writeable string view */\ntemplate<class Alloc>\ninline size_t to_chars(c4::substr buf, std::vector<char, Alloc> const& s)\n{\n    C4_ASSERT(!buf.overlaps(to_csubstr(s)));\n    size_t len = buf.len < s.size() ? buf.len : s.size();\n    // calling memcpy with null strings is undefined behavior\n    // and will wreak havoc in calling code's branches.\n    // see https://github.com/biojppm/rapidyaml/pull/264#issuecomment-1262133637\n    if(len > 0)\n    {\n        memcpy(buf.str, s.data(), len);\n    }\n    return s.size(); // return the number of needed chars\n}\n\n/** copy a string view to an existing std::vector<char> */\ntemplate<class Alloc>\ninline bool from_chars(c4::csubstr buf, std::vector<char, Alloc> * s)\n{\n    s->resize(buf.len);\n    C4_ASSERT(!buf.overlaps(to_csubstr(*s)));\n    // calling memcpy with null strings is undefined behavior\n    // and will wreak havoc in calling code's branches.\n    // see https://github.com/biojppm/rapidyaml/pull/264#issuecomment-1262133637\n    if(buf.len > 0)\n    {\n        memcpy(&(*s)[0], buf.str, buf.len);\n    }\n    return true;\n}\n\n} // namespace c4\n\n#endif // _C4_STD_VECTOR_HPP_\n"
  },
  {
    "path": "libs/rapidyaml/c4/std/vector_fwd.hpp",
    "content": "#ifndef _C4_STD_VECTOR_FWD_HPP_\n#define _C4_STD_VECTOR_FWD_HPP_\n\n/** @file vector_fwd.hpp */\n\n#include <cstddef>\n\n// forward declarations for std::vector\n#if defined(__GLIBCXX__) || defined(__GLIBCPP__) || defined(_MSC_VER)\n#if defined(_MSC_VER)\n__pragma(warning(push))\n__pragma(warning(disable : 4643))\n#endif\nnamespace std {\ntemplate<typename> class allocator;\n#ifdef _GLIBCXX_DEBUG\ninline namespace __debug {\ntemplate<typename T, typename Alloc> class vector;\n}\n#else\ntemplate<typename T, typename Alloc> class vector;\n#endif\n} // namespace std\n#if defined(_MSC_VER)\n__pragma(warning(pop))\n#endif\n#elif defined(_LIBCPP_ABI_NAMESPACE)\nnamespace std {\ninline namespace _LIBCPP_ABI_NAMESPACE {\ntemplate<typename> class allocator;\ntemplate<typename T, typename Alloc> class vector;\n} // namespace _LIBCPP_ABI_NAMESPACE\n} // namespace std\n#else\n#error \"unknown standard library\"\n#endif\n\n#ifndef C4CORE_SINGLE_HEADER\n#include \"c4/substr_fwd.hpp\"\n#endif\n\nnamespace c4 {\n\ntemplate<class Alloc> c4::substr to_substr(std::vector<char, Alloc> &vec);\ntemplate<class Alloc> c4::csubstr to_csubstr(std::vector<char, Alloc> const& vec);\n\ntemplate<class Alloc> bool operator!= (c4::csubstr ss, std::vector<char, Alloc> const& s);\ntemplate<class Alloc> bool operator== (c4::csubstr ss, std::vector<char, Alloc> const& s);\ntemplate<class Alloc> bool operator>= (c4::csubstr ss, std::vector<char, Alloc> const& s);\ntemplate<class Alloc> bool operator>  (c4::csubstr ss, std::vector<char, Alloc> const& s);\ntemplate<class Alloc> bool operator<= (c4::csubstr ss, std::vector<char, Alloc> const& s);\ntemplate<class Alloc> bool operator<  (c4::csubstr ss, std::vector<char, Alloc> const& s);\n\ntemplate<class Alloc> bool operator!= (std::vector<char, Alloc> const& s, c4::csubstr ss);\ntemplate<class Alloc> bool operator== (std::vector<char, Alloc> const& s, c4::csubstr ss);\ntemplate<class Alloc> bool operator>= (std::vector<char, Alloc> const& s, c4::csubstr ss);\ntemplate<class Alloc> bool operator>  (std::vector<char, Alloc> const& s, c4::csubstr ss);\ntemplate<class Alloc> bool operator<= (std::vector<char, Alloc> const& s, c4::csubstr ss);\ntemplate<class Alloc> bool operator<  (std::vector<char, Alloc> const& s, c4::csubstr ss);\n\ntemplate<class Alloc> size_t to_chars(c4::substr buf, std::vector<char, Alloc> const& s);\ntemplate<class Alloc> bool from_chars(c4::csubstr buf, std::vector<char, Alloc> * s);\n\n} // namespace c4\n\n#endif // _C4_STD_VECTOR_FWD_HPP_\n"
  },
  {
    "path": "libs/rapidyaml/c4/substr.hpp",
    "content": "#ifndef _C4_SUBSTR_HPP_\n#define _C4_SUBSTR_HPP_\n\n/** @file substr.hpp read+write string views */\n\n#include <string.h>\n#include <ctype.h>\n#include <type_traits>\n\n#include \"c4/config.hpp\"\n#include \"c4/error.hpp\"\n#include \"c4/substr_fwd.hpp\"\n\n#ifdef __clang__\n#   pragma clang diagnostic push\n#   pragma clang diagnostic ignored \"-Wold-style-cast\"\n#elif defined(__GNUC__)\n#   pragma GCC diagnostic push\n#   pragma GCC diagnostic ignored \"-Wtype-limits\" // disable warnings on size_t>=0, used heavily in assertions below. These assertions are a preparation step for providing the index type as a template parameter.\n#   pragma GCC diagnostic ignored \"-Wuseless-cast\"\n#   pragma GCC diagnostic ignored \"-Wold-style-cast\"\n#endif\n\n\nnamespace c4 {\n\n/** @defgroup doc_substr Substring: read/write string views\n * @{ */\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n/** @cond dev */\nnamespace detail {\ntemplate<typename C>\nstatic inline void _do_reverse(C *C4_RESTRICT first, C *C4_RESTRICT last)\n{\n    while(last > first)\n    {\n        C tmp = *last;\n        *last-- = *first;\n        *first++ = tmp;\n    }\n}\n} // namespace detail\n/** @endcond */\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n/** @cond dev */\n// utility macros to deuglify SFINAE code; undefined after the class.\n// https://stackoverflow.com/questions/43051882/how-to-disable-a-class-member-funrtion-for-certain-template-types\n#define C4_REQUIRE_RW(ret_type) \\\n    template <typename U=C> \\\n    typename std::enable_if< ! std::is_const<U>::value, ret_type>::type\n/** @endcond */\n\n\n/** a non-owning string-view, consisting of a character pointer\n * and a length.\n *\n * @note The pointer is explicitly restricted.\n *\n * @see a [quickstart\n * sample](https://rapidyaml.readthedocs.io/latest/doxygen/group__doc__quickstart.html#ga43e253da0692c13967019446809c1113)\n * in rapidyaml's documentation.\n *\n * @see @ref substr and @ref to_substr()\n * @see @ref csubstr and @ref to_csubstr()\n */\ntemplate<class C>\nstruct C4CORE_EXPORT basic_substring\n{\npublic:\n\n    /** a restricted pointer to the first character of the substring */\n    C * C4_RESTRICT str;\n    /** the length of the substring */\n    size_t          len;\n\npublic:\n\n    /** @name Types */\n    /** @{ */\n\n    using  CC  = typename std::add_const<C>::type;     //!< CC=const char\n    using NCC_ = typename std::remove_const<C>::type; //!< NCC_=non const char\n\n    using ro_substr = basic_substring<CC>;\n    using rw_substr = basic_substring<NCC_>;\n\n    using char_type = C;\n    using size_type = size_t;\n\n    using iterator = C*;\n    using const_iterator = CC*;\n\n    enum : size_t { npos = (size_t)-1, NONE = (size_t)-1 };\n\n    /// convert automatically to substring of const C\n    template<class U=C>\n    C4_ALWAYS_INLINE operator typename std::enable_if<!std::is_const<U>::value, ro_substr const&>::type () const noexcept\n    {\n        return *(ro_substr const*)this; // don't call the str+len ctor because it does a check\n    }\n\n    /** @} */\n\npublic:\n\n    /** @name Default construction and assignment */\n    /** @{ */\n\n    C4_ALWAYS_INLINE constexpr basic_substring() noexcept : str(), len() {}\n\n    C4_ALWAYS_INLINE basic_substring(basic_substring const&) noexcept = default;\n    C4_ALWAYS_INLINE basic_substring(basic_substring     &&) noexcept = default;\n    C4_ALWAYS_INLINE basic_substring(std::nullptr_t) noexcept : str(nullptr), len(0) {}\n\n    C4_ALWAYS_INLINE basic_substring& operator= (basic_substring const&) noexcept = default;\n    C4_ALWAYS_INLINE basic_substring& operator= (basic_substring     &&) noexcept = default;\n    C4_ALWAYS_INLINE basic_substring& operator= (std::nullptr_t) noexcept { str = nullptr; len = 0; return *this; }\n\n    C4_ALWAYS_INLINE void clear() noexcept { str = nullptr; len = 0; }\n\n    /** @} */\n\npublic:\n\n    /** @name Construction and assignment from characters with the same type */\n    /** @{ */\n\n    /** Construct from an array.\n     * @warning the input string need not be zero terminated, but the\n     * length is taken as if the string was zero terminated */\n    template<size_t N>\n    C4_ALWAYS_INLINE constexpr basic_substring(C (&s_)[N]) noexcept : str(s_), len(N-1) {}\n    /** Construct from a pointer and length.\n     * @warning the input string need not be zero terminated. */\n    C4_ALWAYS_INLINE basic_substring(C *s_, size_t len_) noexcept : str(s_), len(len_) { C4_ASSERT(str || !len_); }\n    /** Construct from two pointers.\n     * @warning the end pointer MUST BE larger than or equal to the begin pointer\n     * @warning the input string need not be zero terminated */\n    C4_ALWAYS_INLINE basic_substring(C *beg_, C *end_) noexcept : str(beg_), len(static_cast<size_t>(end_ - beg_)) { C4_ASSERT(end_ >= beg_); }\n    /** Construct from a C-string (zero-terminated string)\n     * @warning the input string MUST BE zero terminated.\n     * @warning will call strlen()\n     * @note this overload uses SFINAE to prevent it from overriding the array ctor\n     * @see For a more detailed explanation on why the plain overloads cannot\n     * coexist, see http://cplusplus.bordoon.com/specializeForCharacterArrays.html */\n    template<class U, typename std::enable_if<std::is_same<U, C*>::value || std::is_same<U, NCC_*>::value, int>::type=0>\n    C4_ALWAYS_INLINE basic_substring(U s_) noexcept : str(s_), len(s_ ? strlen(s_) : 0) {}\n\n    /** Assign from an array.\n     * @warning the input string need not be zero terminated, but the\n     * length is taken as if the string was zero terminated */\n    template<size_t N>\n    C4_ALWAYS_INLINE void assign(C (&s_)[N]) noexcept { str = (s_); len = (N-1); }\n    /** Assign from a pointer and length.\n     * @warning the input string need not be zero terminated. */\n    C4_ALWAYS_INLINE void assign(C *s_, size_t len_) noexcept { str = s_; len = len_; C4_ASSERT(str || !len_); }\n    /** Assign from two pointers.\n     * @warning the end pointer MUST BE larger than or equal to the begin pointer\n     * @warning the input string need not be zero terminated. */\n    C4_ALWAYS_INLINE void assign(C *beg_, C *end_) noexcept { C4_ASSERT(end_ >= beg_); str = (beg_); len = static_cast<size_t>(end_ - beg_); }\n    /** Assign from a C-string (zero-terminated string)\n     * @warning the input string must be zero terminated.\n     * @warning will call strlen()\n     * @note this overload uses SFINAE to prevent it from overriding the array ctor\n     * @see For a more detailed explanation on why the plain overloads cannot\n     * coexist, see http://cplusplus.bordoon.com/specializeForCharacterArrays.html */\n    template<class U, typename std::enable_if<std::is_same<U, C*>::value || std::is_same<U, NCC_*>::value, int>::type=0>\n    C4_ALWAYS_INLINE void assign(U s_) noexcept { str = (s_); len = (s_ ? strlen(s_) : 0); }\n\n    /** Assign from an array.\n     * @warning the input string need not be zero terminated. */\n    template<size_t N>\n    C4_ALWAYS_INLINE basic_substring& operator= (C (&s_)[N]) noexcept { str = (s_); len = (N-1); return *this; }\n    /** Assign from a C-string (zero-terminated string)\n     * @warning the input string MUST BE zero terminated.\n     * @warning will call strlen()\n     * @note this overload uses SFINAE to prevent it from overriding the array ctor\n     * @see For a more detailed explanation on why the plain overloads cannot\n     * coexist, see http://cplusplus.bordoon.com/specializeForCharacterArrays.html */\n    template<class U, typename std::enable_if<std::is_same<U, C*>::value || std::is_same<U, NCC_*>::value, int>::type=0>\n    C4_ALWAYS_INLINE basic_substring& operator= (U s_) noexcept { str = s_; len = s_ ? strlen(s_) : 0; return *this; }\n\n    /** @} */\n\npublic:\n\n    /** @name Standard accessor methods */\n    /** @{ */\n\n    C4_ALWAYS_INLINE C4_PURE bool   has_str()   const noexcept { return ! empty() && str[0] != C(0); }\n    C4_ALWAYS_INLINE C4_PURE bool   empty()     const noexcept { return (len == 0 || str == nullptr); }\n    C4_ALWAYS_INLINE C4_PURE bool   not_empty() const noexcept { return (len != 0 && str != nullptr); }\n    C4_ALWAYS_INLINE C4_PURE size_t size()      const noexcept { return len; }\n\n    C4_ALWAYS_INLINE C4_PURE iterator begin() noexcept { return str; }\n    C4_ALWAYS_INLINE C4_PURE iterator end  () noexcept { return str + len; }\n\n    C4_ALWAYS_INLINE C4_PURE const_iterator begin() const noexcept { return str; }\n    C4_ALWAYS_INLINE C4_PURE const_iterator end  () const noexcept { return str + len; }\n\n    C4_ALWAYS_INLINE C4_PURE C      * data()       noexcept { return str; }\n    C4_ALWAYS_INLINE C4_PURE C const* data() const noexcept { return str; }\n\n    C4_ALWAYS_INLINE C4_PURE C      & operator[] (size_t i)       noexcept { C4_ASSERT(i >= 0 && i < len); return str[i]; }\n    C4_ALWAYS_INLINE C4_PURE C const& operator[] (size_t i) const noexcept { C4_ASSERT(i >= 0 && i < len); return str[i]; }\n\n    C4_ALWAYS_INLINE C4_PURE C      & front()       noexcept { C4_ASSERT(len > 0 && str != nullptr); return *str; }\n    C4_ALWAYS_INLINE C4_PURE C const& front() const noexcept { C4_ASSERT(len > 0 && str != nullptr); return *str; }\n\n    C4_ALWAYS_INLINE C4_PURE C      & back()       noexcept { C4_ASSERT(len > 0 && str != nullptr); return *(str + len - 1); }\n    C4_ALWAYS_INLINE C4_PURE C const& back() const noexcept { C4_ASSERT(len > 0 && str != nullptr); return *(str + len - 1); }\n\n    /** @} */\n\npublic:\n\n    /** @name Comparison methods */\n    /** @{ */\n\n    C4_PURE int compare(C const c) const noexcept\n    {\n        C4_XASSERT((str != nullptr) || len == 0);\n        if(C4_LIKELY(str != nullptr && len > 0))\n            return (*str != c) ? *str - c : (static_cast<int>(len) - 1);\n        else\n            return -1;\n    }\n\n    C4_PURE int compare(const char *C4_RESTRICT that, size_t sz) const noexcept\n    {\n        C4_XASSERT(that || sz  == 0);\n        C4_XASSERT(str  || len == 0);\n        if(C4_LIKELY(str && that))\n        {\n            {\n                const size_t min = len < sz ? len : sz;\n                for(size_t i = 0; i < min; ++i)\n                    if(str[i] != that[i])\n                        return str[i] < that[i] ? -1 : 1;\n            }\n            if(len < sz)\n                return -1;\n            else if(len == sz)\n                return 0;\n            else\n                return 1;\n        }\n        else if(len == sz)\n        {\n            C4_XASSERT(len == 0 && sz == 0);\n            return 0;\n        }\n        return len < sz ? -1 : 1;\n    }\n\n    C4_ALWAYS_INLINE C4_PURE int compare(ro_substr const that) const noexcept { return this->compare(that.str, that.len); }\n\n    C4_ALWAYS_INLINE C4_PURE bool operator== (std::nullptr_t) const noexcept { return str == nullptr; }\n    C4_ALWAYS_INLINE C4_PURE bool operator!= (std::nullptr_t) const noexcept { return str != nullptr; }\n\n    C4_ALWAYS_INLINE C4_PURE bool operator== (C const c) const noexcept { return this->compare(c) == 0; }\n    C4_ALWAYS_INLINE C4_PURE bool operator!= (C const c) const noexcept { return this->compare(c) != 0; }\n    C4_ALWAYS_INLINE C4_PURE bool operator<  (C const c) const noexcept { return this->compare(c) <  0; }\n    C4_ALWAYS_INLINE C4_PURE bool operator>  (C const c) const noexcept { return this->compare(c) >  0; }\n    C4_ALWAYS_INLINE C4_PURE bool operator<= (C const c) const noexcept { return this->compare(c) <= 0; }\n    C4_ALWAYS_INLINE C4_PURE bool operator>= (C const c) const noexcept { return this->compare(c) >= 0; }\n\n    template<class U> C4_ALWAYS_INLINE C4_PURE bool operator== (basic_substring<U> const that) const noexcept { return this->compare(that) == 0; }\n    template<class U> C4_ALWAYS_INLINE C4_PURE bool operator!= (basic_substring<U> const that) const noexcept { return this->compare(that) != 0; }\n    template<class U> C4_ALWAYS_INLINE C4_PURE bool operator<  (basic_substring<U> const that) const noexcept { return this->compare(that) <  0; }\n    template<class U> C4_ALWAYS_INLINE C4_PURE bool operator>  (basic_substring<U> const that) const noexcept { return this->compare(that) >  0; }\n    template<class U> C4_ALWAYS_INLINE C4_PURE bool operator<= (basic_substring<U> const that) const noexcept { return this->compare(that) <= 0; }\n    template<class U> C4_ALWAYS_INLINE C4_PURE bool operator>= (basic_substring<U> const that) const noexcept { return this->compare(that) >= 0; }\n\n    template<size_t N> C4_ALWAYS_INLINE C4_PURE bool operator== (const char (&that)[N]) const noexcept { return this->compare(that, N-1) == 0; }\n    template<size_t N> C4_ALWAYS_INLINE C4_PURE bool operator!= (const char (&that)[N]) const noexcept { return this->compare(that, N-1) != 0; }\n    template<size_t N> C4_ALWAYS_INLINE C4_PURE bool operator<  (const char (&that)[N]) const noexcept { return this->compare(that, N-1) <  0; }\n    template<size_t N> C4_ALWAYS_INLINE C4_PURE bool operator>  (const char (&that)[N]) const noexcept { return this->compare(that, N-1) >  0; }\n    template<size_t N> C4_ALWAYS_INLINE C4_PURE bool operator<= (const char (&that)[N]) const noexcept { return this->compare(that, N-1) <= 0; }\n    template<size_t N> C4_ALWAYS_INLINE C4_PURE bool operator>= (const char (&that)[N]) const noexcept { return this->compare(that, N-1) >= 0; }\n\n    /** @} */\n\npublic:\n\n    /** @name Sub-selection methods */\n    /** @{ */\n\n    /** true if *this is a substring of that (ie, from the same buffer) */\n    C4_ALWAYS_INLINE C4_PURE bool is_sub(ro_substr const that) const noexcept\n    {\n        return that.is_super(*this);\n    }\n\n    /** true if that is a substring of *this (ie, from the same buffer) */\n    C4_ALWAYS_INLINE C4_PURE bool is_super(ro_substr const that) const noexcept\n    {\n        if(C4_LIKELY(len > 0))\n            return that.str >= str && that.str+that.len <= str+len;\n        else\n            return that.len == 0 && that.str == str && str != nullptr;\n    }\n\n    /** true if there is overlap of at least one element between that and *this */\n    C4_ALWAYS_INLINE C4_PURE bool overlaps(ro_substr const that) const noexcept\n    {\n        // thanks @timwynants\n        return that.str+that.len > str && that.str < str+len;\n    }\n\npublic:\n\n    /** return [first,len[ */\n    C4_ALWAYS_INLINE C4_PURE basic_substring sub(size_t first) const noexcept\n    {\n        C4_ASSERT(first >= 0 && first <= len);\n        return basic_substring(str + first, len - first);\n    }\n\n    /** return [first,first+num[. If num==npos, return [first,len[ */\n    C4_ALWAYS_INLINE C4_PURE basic_substring sub(size_t first, size_t num) const noexcept\n    {\n        C4_ASSERT(first >= 0 && first <= len);\n        C4_ASSERT((num >= 0 && num <= len) || (num == npos));\n        size_t rnum = num != npos ? num : len - first;\n        C4_ASSERT((first >= 0 && first + rnum <= len) || (num == 0));\n        return basic_substring(str + first, rnum);\n    }\n\n    /** return [first,last[. If last==npos, return [first,len[ */\n    C4_ALWAYS_INLINE C4_PURE basic_substring range(size_t first, size_t last=npos) const noexcept\n    {\n        C4_ASSERT(first >= 0 && first <= len);\n        last = last != npos ? last : len;\n        C4_ASSERT(first <= last);\n        C4_ASSERT(last  >= 0 && last  <= len);\n        return basic_substring(str + first, last - first);\n    }\n\n    /** return the first @p num elements: [0,num[*/\n    C4_ALWAYS_INLINE C4_PURE basic_substring first(size_t num) const noexcept\n    {\n        C4_ASSERT(num <= len || num == npos);\n        return basic_substring(str, num != npos ? num : len);\n    }\n\n    /** return the last @p num elements: [len-num,len[*/\n    C4_ALWAYS_INLINE C4_PURE basic_substring last(size_t num) const noexcept\n    {\n        C4_ASSERT(num <= len || num == npos);\n        return num != npos ?\n            basic_substring(str + len - num, num) :\n            *this;\n    }\n\n    /** offset from the ends: return [left,len-right[ ; ie, trim a\n        number of characters from the left and right. This is\n        equivalent to python's negative list indices. */\n    C4_ALWAYS_INLINE C4_PURE basic_substring offs(size_t left, size_t right) const noexcept\n    {\n        C4_ASSERT(left  >= 0 && left  <= len);\n        C4_ASSERT(right >= 0 && right <= len);\n        C4_ASSERT(left  <= len - right + 1);\n        return basic_substring(str + left, len - right - left);\n    }\n\n    /** return [0, pos[ . Same as .first(pos), but provided for compatibility with .right_of() */\n    C4_ALWAYS_INLINE C4_PURE basic_substring left_of(size_t pos) const noexcept\n    {\n        C4_ASSERT(pos <= len || pos == npos);\n        return (pos != npos) ?\n            basic_substring(str, pos) :\n            *this;\n    }\n\n    /** return [0, pos+include_pos[ . Same as .first(pos+1), but provided for compatibility with .right_of() */\n    C4_ALWAYS_INLINE C4_PURE basic_substring left_of(size_t pos, bool include_pos) const noexcept\n    {\n        C4_ASSERT(pos <= len || pos == npos);\n        return (pos != npos) ?\n            basic_substring(str, pos+include_pos) :\n            *this;\n    }\n\n    /** return [pos+1, len[ */\n    C4_ALWAYS_INLINE C4_PURE basic_substring right_of(size_t pos) const noexcept\n    {\n        C4_ASSERT(pos <= len || pos == npos);\n        return (pos != npos) ?\n            basic_substring(str + (pos + 1), len - (pos + 1)) :\n            basic_substring(str + len, size_t(0));\n    }\n\n    /** return [pos+!include_pos, len[ */\n    C4_ALWAYS_INLINE C4_PURE basic_substring right_of(size_t pos, bool include_pos) const noexcept\n    {\n        C4_ASSERT(pos <= len || pos == npos);\n        return (pos != npos) ?\n            basic_substring(str + (pos + !include_pos), len - (pos + !include_pos)) :\n            basic_substring(str + len, size_t(0));\n    }\n\npublic:\n\n    /** given @p subs a substring of the current string, get the\n     * portion of the current string to the left of it */\n    C4_ALWAYS_INLINE C4_PURE basic_substring left_of(ro_substr const subs) const noexcept\n    {\n        C4_ASSERT(is_super(subs) || subs.empty());\n        auto ssb = subs.begin();\n        auto b = begin();\n        auto e = end();\n        if(ssb >= b && ssb <= e)\n            return sub(0, static_cast<size_t>(ssb - b));\n        else\n            return sub(0, 0);\n    }\n\n    /** given @p subs a substring of the current string, get the\n     * portion of the current string to the right of it */\n    C4_ALWAYS_INLINE C4_PURE basic_substring right_of(ro_substr const subs) const noexcept\n    {\n        C4_ASSERT(is_super(subs) || subs.empty());\n        auto sse = subs.end();\n        auto b = begin();\n        auto e = end();\n        if(sse >= b && sse <= e)\n            return sub(static_cast<size_t>(sse - b), static_cast<size_t>(e - sse));\n        else\n            return sub(0, 0);\n    }\n\n    /** @} */\n\npublic:\n\n    /** @name Removing characters (trim()) / patterns (strip()) from the tips of the string */\n    /** @{ */\n\n    /** trim left */\n    basic_substring triml(const C c) const\n    {\n        if( ! empty())\n        {\n            size_t pos = first_not_of(c);\n            if(pos != npos)\n                return sub(pos);\n        }\n        return sub(0, 0);\n    }\n    /** trim left ANY of the characters.\n     * @see stripl() to remove a pattern from the left */\n    basic_substring triml(ro_substr chars) const\n    {\n        if( ! empty())\n        {\n            size_t pos = first_not_of(chars);\n            if(pos != npos)\n                return sub(pos);\n        }\n        return sub(0, 0);\n    }\n\n    /** trim the character c from the right */\n    basic_substring trimr(const C c) const\n    {\n        if( ! empty())\n        {\n            size_t pos = last_not_of(c, npos);\n            if(pos != npos)\n                return sub(0, pos+1);\n        }\n        return sub(0, 0);\n    }\n    /** trim right ANY of the characters\n     * @see stripr() to remove a pattern from the right  */\n    basic_substring trimr(ro_substr chars) const\n    {\n        if( ! empty())\n        {\n            size_t pos = last_not_of(chars, npos);\n            if(pos != npos)\n                return sub(0, pos+1);\n        }\n        return sub(0, 0);\n    }\n\n    /** trim the character c left and right */\n    basic_substring trim(const C c) const\n    {\n        return triml(c).trimr(c);\n    }\n    /** trim left and right ANY of the characters\n     * @see strip() to remove a pattern from the left and right */\n    basic_substring trim(ro_substr const chars) const\n    {\n        return triml(chars).trimr(chars);\n    }\n\n    /** remove a pattern from the left\n     * @see triml() to remove characters*/\n    basic_substring stripl(ro_substr pattern) const\n    {\n        if( ! begins_with(pattern))\n            return *this;\n        return sub(pattern.len < len ? pattern.len : len);\n    }\n\n    /** remove a pattern from the right\n     * @see trimr() to remove characters*/\n    basic_substring stripr(ro_substr pattern) const\n    {\n        if( ! ends_with(pattern))\n            return *this;\n        return left_of(len - (pattern.len < len ? pattern.len : len));\n    }\n\n    /** @} */\n\npublic:\n\n    /** @name Lookup methods */\n    /** @{ */\n\n    inline size_t find(const C c, size_t start_pos=0) const\n    {\n        return first_of(c, start_pos);\n    }\n    inline size_t find(ro_substr pattern, size_t start_pos=0) const\n    {\n        C4_ASSERT(start_pos == npos || (start_pos >= 0 && start_pos <= len));\n        if(len < pattern.len) return npos;\n        for(size_t i = start_pos, e = len - pattern.len + 1; i < e; ++i)\n        {\n            bool gotit = true;\n            for(size_t j = 0; j < pattern.len; ++j)\n            {\n                C4_ASSERT(i + j < len);\n                if(str[i + j] != pattern.str[j])\n                {\n                    gotit = false;\n                    break;\n                }\n            }\n            if(gotit)\n            {\n                return i;\n            }\n        }\n        return npos;\n    }\n\npublic:\n\n    /** count the number of occurrences of c */\n    inline size_t count(const C c, size_t pos=0) const\n    {\n        C4_ASSERT(pos >= 0 && pos <= len);\n        size_t num = 0;\n        pos = find(c, pos);\n        while(pos != npos)\n        {\n            ++num;\n            pos = find(c, pos + 1);\n        }\n        return num;\n    }\n\n    /** count the number of occurrences of s */\n    inline size_t count(ro_substr c, size_t pos=0) const\n    {\n        C4_ASSERT(pos >= 0 && pos <= len);\n        size_t num = 0;\n        pos = find(c, pos);\n        while(pos != npos)\n        {\n            ++num;\n            pos = find(c, pos + c.len);\n        }\n        return num;\n    }\n\n    /** get the substr consisting of the first occurrence of @p c after @p pos, or an empty substr if none occurs */\n    inline basic_substring select(const C c, size_t pos=0) const\n    {\n        pos = find(c, pos);\n        return pos != npos ? sub(pos, 1) : basic_substring();\n    }\n\n    /** get the substr consisting of the first occurrence of @p pattern after @p pos, or an empty substr if none occurs */\n    inline basic_substring select(ro_substr pattern, size_t pos=0) const\n    {\n        pos = find(pattern, pos);\n        return pos != npos ? sub(pos, pattern.len) : basic_substring();\n    }\n\npublic:\n\n    struct first_of_any_result\n    {\n        size_t which;\n        size_t pos;\n        inline operator bool() const { return which != NONE && pos != npos; }\n    };\n\n    first_of_any_result first_of_any(ro_substr s0, ro_substr s1) const\n    {\n        ro_substr s[2] = {s0, s1};\n        return first_of_any_iter(&s[0], &s[0] + 2);\n    }\n\n    first_of_any_result first_of_any(ro_substr s0, ro_substr s1, ro_substr s2) const\n    {\n        ro_substr s[3] = {s0, s1, s2};\n        return first_of_any_iter(&s[0], &s[0] + 3);\n    }\n\n    first_of_any_result first_of_any(ro_substr s0, ro_substr s1, ro_substr s2, ro_substr s3) const\n    {\n        ro_substr s[4] = {s0, s1, s2, s3};\n        return first_of_any_iter(&s[0], &s[0] + 4);\n    }\n\n    first_of_any_result first_of_any(ro_substr s0, ro_substr s1, ro_substr s2, ro_substr s3, ro_substr s4) const\n    {\n        ro_substr s[5] = {s0, s1, s2, s3, s4};\n        return first_of_any_iter(&s[0], &s[0] + 5);\n    }\n\n    template<class It>\n    first_of_any_result first_of_any_iter(It first_span, It last_span) const\n    {\n        for(size_t i = 0; i < len; ++i)\n        {\n            size_t curr = 0;\n            for(It it = first_span; it != last_span; ++curr, ++it)\n            {\n                auto const& chars = *it;\n                if((i + chars.len) > len) continue;\n                bool gotit = true;\n                for(size_t j = 0; j < chars.len; ++j)\n                {\n                    C4_ASSERT(i + j < len);\n                    if(str[i + j] != chars[j])\n                    {\n                        gotit = false;\n                        break;\n                    }\n                }\n                if(gotit)\n                {\n                    return {curr, i};\n                }\n            }\n        }\n        return {NONE, npos};\n    }\n\npublic:\n\n    /** true if the first character of the string is @p c */\n    bool begins_with(const C c) const\n    {\n        return len > 0 ? str[0] == c : false;\n    }\n\n    /** true if the first @p num characters of the string are @p c */\n    bool begins_with(const C c, size_t num) const\n    {\n        if(len < num)\n        {\n            return false;\n        }\n        for(size_t i = 0; i < num; ++i)\n        {\n            if(str[i] != c)\n            {\n                return false;\n            }\n        }\n        return true;\n    }\n\n    /** true if the string begins with the given @p pattern */\n    bool begins_with(ro_substr pattern) const\n    {\n        if(len < pattern.len)\n        {\n            return false;\n        }\n        for(size_t i = 0; i < pattern.len; ++i)\n        {\n            if(str[i] != pattern[i])\n            {\n                return false;\n            }\n        }\n        return true;\n    }\n\n    /** true if the first character of the string is any of the given @p chars */\n    bool begins_with_any(ro_substr chars) const\n    {\n        if(len == 0)\n        {\n            return false;\n        }\n        for(size_t i = 0; i < chars.len; ++i)\n        {\n            if(str[0] == chars.str[i])\n            {\n                return true;\n            }\n        }\n        return false;\n    }\n\n    /** true if the last character of the string is @p c */\n    bool ends_with(const C c) const\n    {\n        return len > 0 ? str[len-1] == c : false;\n    }\n\n    /** true if the last @p num characters of the string are @p c */\n    bool ends_with(const C c, size_t num) const\n    {\n        if(len < num)\n        {\n            return false;\n        }\n        for(size_t i = len - num; i < len; ++i)\n        {\n            if(str[i] != c)\n            {\n                return false;\n            }\n        }\n        return true;\n    }\n\n    /** true if the string ends with the given @p pattern */\n    bool ends_with(ro_substr pattern) const\n    {\n        if(len < pattern.len)\n        {\n            return false;\n        }\n        for(size_t i = 0, s = len-pattern.len; i < pattern.len; ++i)\n        {\n            if(str[s+i] != pattern[i])\n            {\n                return false;\n            }\n        }\n        return true;\n    }\n\n    /** true if the last character of the string is any of the given @p chars */\n    bool ends_with_any(ro_substr chars) const\n    {\n        if(len == 0)\n        {\n            return false;\n        }\n        for(size_t i = 0; i < chars.len; ++i)\n        {\n            if(str[len - 1] == chars[i])\n            {\n                return true;\n            }\n        }\n        return false;\n    }\n\npublic:\n\n    /** @return the first position where c is found in the string, or npos if none is found */\n    size_t first_of(const C c, size_t start=0) const\n    {\n        C4_ASSERT(start == npos || (start >= 0 && start <= len));\n        for(size_t i = start; i < len; ++i)\n        {\n            if(str[i] == c)\n                return i;\n        }\n        return npos;\n    }\n\n    /** @return the last position where c is found in the string, or npos if none is found */\n    size_t last_of(const C c, size_t start=npos) const\n    {\n        C4_ASSERT(start == npos || (start >= 0 && start <= len));\n        if(start == npos)\n            start = len;\n        for(size_t i = start-1; i != size_t(-1); --i)\n        {\n            if(str[i] == c)\n                return i;\n        }\n        return npos;\n    }\n\n    /** @return the first position where ANY of the chars is found in the string, or npos if none is found */\n    size_t first_of(ro_substr chars, size_t start=0) const\n    {\n        C4_ASSERT(start == npos || (start >= 0 && start <= len));\n        for(size_t i = start; i < len; ++i)\n        {\n            for(size_t j = 0; j < chars.len; ++j)\n            {\n                if(str[i] == chars[j])\n                    return i;\n            }\n        }\n        return npos;\n    }\n\n    /** @return the last position where ANY of the chars is found in the string, or npos if none is found */\n    size_t last_of(ro_substr chars, size_t start=npos) const\n    {\n        C4_ASSERT(start == npos || (start >= 0 && start <= len));\n        if(start == npos)\n            start = len;\n        for(size_t i = start-1; i != size_t(-1); --i)\n        {\n            for(size_t j = 0; j < chars.len; ++j)\n            {\n                if(str[i] == chars[j])\n                    return i;\n            }\n        }\n        return npos;\n    }\n\npublic:\n\n    size_t first_not_of(const C c) const\n    {\n        for(size_t i = 0; i < len; ++i)\n        {\n            if(str[i] != c)\n                return i;\n        }\n        return npos;\n    }\n\n    size_t first_not_of(const C c, size_t start) const\n    {\n        C4_ASSERT((start >= 0 && start <= len) || (start == len && len == 0));\n        for(size_t i = start; i < len; ++i)\n        {\n            if(str[i] != c)\n                return i;\n        }\n        return npos;\n    }\n\n    size_t last_not_of(const C c) const\n    {\n        for(size_t i = len-1; i != size_t(-1); --i)\n        {\n            if(str[i] != c)\n                return i;\n        }\n        return npos;\n    }\n\n    size_t last_not_of(const C c, size_t start) const\n    {\n        C4_ASSERT(start == npos || (start >= 0 && start <= len));\n        if(start == npos)\n            start = len;\n        for(size_t i = start-1; i != size_t(-1); --i)\n        {\n            if(str[i] != c)\n                return i;\n        }\n        return npos;\n    }\n\n    size_t first_not_of(ro_substr chars) const\n    {\n        for(size_t i = 0; i < len; ++i)\n        {\n            bool gotit = true;\n            for(size_t j = 0; j < chars.len; ++j)\n            {\n                if(str[i] == chars.str[j])\n                {\n                    gotit = false;\n                    break;\n                }\n            }\n            if(gotit)\n            {\n                return i;\n            }\n        }\n        return npos;\n    }\n\n    size_t first_not_of(ro_substr chars, size_t start) const\n    {\n        C4_ASSERT((start >= 0 && start <= len) || (start == len && len == 0));\n        for(size_t i = start; i < len; ++i)\n        {\n            bool gotit = true;\n            for(size_t j = 0; j < chars.len; ++j)\n            {\n                if(str[i] == chars.str[j])\n                {\n                    gotit = false;\n                    break;\n                }\n            }\n            if(gotit)\n            {\n                return i;\n            }\n        }\n        return npos;\n    }\n\n    size_t last_not_of(ro_substr chars) const\n    {\n        for(size_t i = len-1; i != size_t(-1); --i)\n        {\n            bool gotit = true;\n            for(size_t j = 0; j < chars.len; ++j)\n            {\n                if(str[i] == chars.str[j])\n                {\n                    gotit = false;\n                    break;\n                }\n            }\n            if(gotit)\n            {\n                return i;\n            }\n        }\n        return npos;\n    }\n\n    size_t last_not_of(ro_substr chars, size_t start) const\n    {\n        C4_ASSERT(start == npos || (start >= 0 && start <= len));\n        if(start == npos)\n            start = len;\n        for(size_t i = start-1; i != size_t(-1); --i)\n        {\n            bool gotit = true;\n            for(size_t j = 0; j < chars.len; ++j)\n            {\n                if(str[i] == chars.str[j])\n                {\n                    gotit = false;\n                    break;\n                }\n            }\n            if(gotit)\n            {\n                return i;\n            }\n        }\n        return npos;\n    }\n\n    /** @} */\n\npublic:\n\n    /** @name Range lookup methods */\n    /** @{ */\n\n    /** get the range delimited by an open-close pair of characters.\n     * @note There must be no nested pairs.\n     * @note No checks for escapes are performed. */\n    basic_substring pair_range(CC open, CC close) const\n    {\n        size_t b = find(open);\n        if(b == npos)\n            return basic_substring();\n        size_t e = find(close, b+1);\n        if(e == npos)\n            return basic_substring();\n        basic_substring ret = range(b, e+1);\n        C4_ASSERT(ret.sub(1).find(open) == npos);\n        return ret;\n    }\n\n    /** get the range delimited by a single open-close character (eg, quotes).\n     * @note The open-close character can be escaped. */\n    basic_substring pair_range_esc(CC open_close, CC escape=CC('\\\\'))\n    {\n        size_t b = find(open_close);\n        if(b == npos) return basic_substring();\n        for(size_t i = b+1; i < len; ++i)\n        {\n            CC c = str[i];\n            if(c == open_close)\n            {\n                if(str[i-1] != escape)\n                {\n                    return range(b, i+1);\n                }\n            }\n        }\n        return basic_substring();\n    }\n\n    /** get the range delimited by an open-close pair of characters,\n     * with possibly nested occurrences. No checks for escapes are\n     * performed. */\n    basic_substring pair_range_nested(CC open, CC close) const\n    {\n        size_t b = find(open);\n        if(b == npos) return basic_substring();\n        size_t e, curr = b+1, count = 0;\n        const char both[] = {open, close, '\\0'};\n        while((e = first_of(both, curr)) != npos)\n        {\n            if(str[e] == open)\n            {\n                ++count;\n                curr = e+1;\n            }\n            else if(str[e] == close)\n            {\n                if(count == 0) return range(b, e+1);\n                --count;\n                curr = e+1;\n            }\n        }\n        return basic_substring();\n    }\n\n    basic_substring unquoted() const\n    {\n        constexpr const C dq('\"'), sq('\\'');\n        if(len >= 2 && (str[len - 2] != C('\\\\')) &&\n           ((begins_with(sq) && ends_with(sq))\n            ||\n            (begins_with(dq) && ends_with(dq))))\n        {\n            return range(1, len -1);\n        }\n        return *this;\n    }\n\n    /** @} */\n\npublic:\n\n    /** @name Number-matching query methods */\n    /** @{ */\n\n    /** @return true if the substring contents are a floating-point or integer number.\n     * @note any leading or trailing whitespace will return false. */\n    bool is_number() const\n    {\n        if(empty() || (first_non_empty_span().empty()))\n            return false;\n        if(first_uint_span() == *this)\n            return true;\n        if(first_int_span() == *this)\n            return true;\n        if(first_real_span() == *this)\n            return true;\n        return false;\n    }\n\n    /** @return true if the substring contents are a real number.\n     * @note any leading or trailing whitespace will return false. */\n    bool is_real() const\n    {\n        if(empty() || (first_non_empty_span().empty()))\n            return false;\n        if(first_real_span() == *this)\n            return true;\n        return false;\n    }\n\n    /** @return true if the substring contents are an integer number.\n     * @note any leading or trailing whitespace will return false. */\n    bool is_integer() const\n    {\n        if(empty() || (first_non_empty_span().empty()))\n            return false;\n        if(first_uint_span() == *this)\n            return true;\n        if(first_int_span() == *this)\n            return true;\n        return false;\n    }\n\n    /** @return true if the substring contents are an unsigned integer number.\n     * @note any leading or trailing whitespace will return false. */\n    bool is_unsigned_integer() const\n    {\n        if(empty() || (first_non_empty_span().empty()))\n            return false;\n        if(first_uint_span() == *this)\n            return true;\n        return false;\n    }\n\n    /** get the first span consisting exclusively of non-empty characters */\n    basic_substring first_non_empty_span() const\n    {\n        constexpr const ro_substr empty_chars(\" \\n\\r\\t\");\n        size_t pos = first_not_of(empty_chars);\n        if(pos == npos)\n            return first(0);\n        auto ret = sub(pos);\n        pos = ret.first_of(empty_chars);\n        return ret.first(pos);\n    }\n\n    /** get the first span which can be interpreted as an unsigned integer */\n    basic_substring first_uint_span() const\n    {\n        basic_substring ne = first_non_empty_span();\n        if(ne.empty())\n            return ne;\n        if(ne.str[0] == '-')\n            return first(0);\n        size_t skip_start = size_t(ne.str[0] == '+');\n        return ne._first_integral_span(skip_start);\n    }\n\n    /** get the first span which can be interpreted as a signed integer */\n    basic_substring first_int_span() const\n    {\n        basic_substring ne = first_non_empty_span();\n        if(ne.empty())\n            return ne;\n        size_t skip_start = size_t(ne.str[0] == '+' || ne.str[0] == '-');\n        return ne._first_integral_span(skip_start);\n    }\n\n    basic_substring _first_integral_span(size_t skip_start) const\n    {\n        C4_ASSERT(!empty());\n        if(skip_start == len)\n            return first(0);\n        C4_ASSERT(skip_start < len);\n        if(len >= skip_start + 3)\n        {\n            if(str[skip_start] != '0')\n            {\n                for(size_t i = skip_start; i < len; ++i)\n                {\n                    char c = str[i];\n                    if(c < '0' || c > '9')\n                        return i > skip_start && _is_delim_char(c) ? first(i) : first(0);\n                }\n            }\n            else\n            {\n                char next = str[skip_start + 1];\n                if(next == 'x' || next == 'X')\n                {\n                    skip_start += 2;\n                    for(size_t i = skip_start; i < len; ++i)\n                    {\n                        const char c = str[i];\n                        if( ! _is_hex_char(c))\n                            return i > skip_start && _is_delim_char(c) ? first(i) : first(0);\n                    }\n                    return *this;\n                }\n                else if(next == 'b' || next == 'B')\n                {\n                    skip_start += 2;\n                    for(size_t i = skip_start; i < len; ++i)\n                    {\n                        const char c = str[i];\n                        if(c != '0' && c != '1')\n                            return i > skip_start && _is_delim_char(c) ? first(i) : first(0);\n                    }\n                    return *this;\n                }\n                else if(next == 'o' || next == 'O')\n                {\n                    skip_start += 2;\n                    for(size_t i = skip_start; i < len; ++i)\n                    {\n                        const char c = str[i];\n                        if(c < '0' || c > '7')\n                            return i > skip_start && _is_delim_char(c) ? first(i) : first(0);\n                    }\n                    return *this;\n                }\n            }\n        }\n        // must be a decimal, or it is not a an number\n        for(size_t i = skip_start; i < len; ++i)\n        {\n            const char c = str[i];\n            if(c < '0' || c > '9')\n                return i > skip_start && _is_delim_char(c) ? first(i) : first(0);\n        }\n        return *this;\n    }\n\n    /** get the first span which can be interpreted as a real (floating-point) number */\n    basic_substring first_real_span() const\n    {\n        basic_substring ne = first_non_empty_span();\n        if(ne.empty())\n            return ne;\n        const size_t skip_start = (ne.str[0] == '+' || ne.str[0] == '-');\n        C4_ASSERT(skip_start == 0 || skip_start == 1);\n        // if we have at least three digits after the leading sign, it\n        // can be decimal, or hex, or bin or oct. Ex:\n        // non-decimal: 0x0, 0b0, 0o0\n        // decimal: 1.0, 10., 1e1, 100, inf, nan, infinity\n        if(ne.len >= skip_start+3)\n        {\n            // if it does not have leading 0, it must be decimal, or it is not a real\n            if(ne.str[skip_start] != '0')\n            {\n                if(ne.str[skip_start] == 'i') // is it infinity or inf?\n                {\n                    basic_substring word = ne._word_follows(skip_start + 1, \"nfinity\");\n                    if(word.len)\n                        return word;\n                    return ne._word_follows(skip_start + 1, \"nf\");\n                }\n                else if(ne.str[skip_start] == 'n') // is it nan?\n                {\n                    return ne._word_follows(skip_start + 1, \"an\");\n                }\n                else // must be a decimal, or it is not a real\n                {\n                    return ne._first_real_span_dec(skip_start);\n                }\n            }\n            else // starts with 0. is it 0x, 0b or 0o?\n            {\n                const char next = ne.str[skip_start + 1];\n                // hexadecimal\n                if(next == 'x' || next == 'X')\n                    return ne._first_real_span_hex(skip_start + 2);\n                // binary\n                else if(next == 'b' || next == 'B')\n                    return ne._first_real_span_bin(skip_start + 2);\n                // octal\n                else if(next == 'o' || next == 'O')\n                    return ne._first_real_span_oct(skip_start + 2);\n                // none of the above. may still be a decimal.\n                else\n                    return ne._first_real_span_dec(skip_start); // do not skip the 0.\n            }\n        }\n        // less than 3 chars after the leading sign. It is either a\n        // decimal or it is not a real. (cannot be any of 0x0, etc).\n        return ne._first_real_span_dec(skip_start);\n    }\n\n    /** true if the character is a delimiter character *at the end* */\n    static constexpr C4_ALWAYS_INLINE C4_CONST bool _is_delim_char(char c) noexcept\n    {\n        return c == ' ' || c == '\\n'\n            || c == ']' || c == ')'  || c == '}'\n            || c == ',' || c == ';' || c == '\\r' || c == '\\t' || c == '\\0';\n    }\n\n    /** true if the character is in [0-9a-fA-F] */\n    static constexpr C4_ALWAYS_INLINE C4_CONST bool _is_hex_char(char c) noexcept\n    {\n        return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');\n    }\n\n    C4_NO_INLINE C4_PURE basic_substring _word_follows(size_t pos, csubstr word) const noexcept\n    {\n        size_t posend = pos + word.len;\n        if(len >= posend && sub(pos, word.len) == word)\n            if(len == posend || _is_delim_char(str[posend]))\n                return first(posend);\n        return first(0);\n    }\n\n    // this function is declared inside the class to avoid a VS error with __declspec(dllimport)\n    C4_NO_INLINE C4_PURE basic_substring _first_real_span_dec(size_t pos) const noexcept\n    {\n        bool intchars = false;\n        bool fracchars = false;\n        bool powchars;\n        // integral part\n        for( ; pos < len; ++pos)\n        {\n            const char c = str[pos];\n            if(c >= '0' && c <= '9')\n            {\n                intchars = true;\n            }\n            else if(c == '.')\n            {\n                ++pos;\n                goto fractional_part_dec;\n            }\n            else if(c == 'e' || c == 'E')\n            {\n                ++pos;\n                goto power_part_dec;\n            }\n            else if(_is_delim_char(c))\n            {\n                return intchars ? first(pos) : first(0);\n            }\n            else\n            {\n                return first(0);\n            }\n        }\n        // no . or p were found; this is either an integral number\n        // or not a number at all\n        return intchars ?\n            *this :\n            first(0);\n    fractional_part_dec:\n        C4_ASSERT(pos > 0);\n        C4_ASSERT(str[pos - 1] == '.');\n        for( ; pos < len; ++pos)\n        {\n            const char c = str[pos];\n            if(c >= '0' && c <= '9')\n            {\n                fracchars = true;\n            }\n            else if(c == 'e' || c == 'E')\n            {\n                ++pos;\n                goto power_part_dec;\n            }\n            else if(_is_delim_char(c))\n            {\n                return intchars || fracchars ? first(pos) : first(0);\n            }\n            else\n            {\n                return first(0);\n            }\n        }\n        return intchars || fracchars ?\n            *this :\n            first(0);\n    power_part_dec:\n        C4_ASSERT(pos > 0);\n        C4_ASSERT(str[pos - 1] == 'e' || str[pos - 1] == 'E');\n        // either digits, or +, or - are expected here, followed by more digits.\n        if((len == pos) || ((!intchars) && (!fracchars)))\n            return first(0);\n        if(str[pos] == '-' || str[pos] == '+')\n            ++pos; // skip the sign\n        powchars = false;\n        for( ; pos < len; ++pos)\n        {\n            const char c = str[pos];\n            if(c >= '0' && c <= '9')\n                powchars = true;\n            else if(powchars && _is_delim_char(c))\n                return first(pos);\n            else\n                return first(0);\n        }\n        return powchars ? *this : first(0);\n    }\n\n    // this function is declared inside the class to avoid a VS error with __declspec(dllimport)\n    C4_NO_INLINE C4_PURE basic_substring _first_real_span_hex(size_t pos) const noexcept\n    {\n        bool intchars = false;\n        bool fracchars = false;\n        bool powchars;\n        // integral part\n        for( ; pos < len; ++pos)\n        {\n            const char c = str[pos];\n            if(_is_hex_char(c))\n            {\n                intchars = true;\n            }\n            else if(c == '.')\n            {\n                ++pos;\n                goto fractional_part_hex;\n            }\n            else if(c == 'p' || c == 'P')\n            {\n                ++pos;\n                goto power_part_hex;\n            }\n            else if(_is_delim_char(c))\n            {\n                return intchars ? first(pos) : first(0);\n            }\n            else\n            {\n                return first(0);\n            }\n        }\n        // no . or p were found; this is either an integral number\n        // or not a number at all\n        return intchars ?\n            *this :\n            first(0);\n    fractional_part_hex:\n        C4_ASSERT(pos > 0);\n        C4_ASSERT(str[pos - 1] == '.');\n        for( ; pos < len; ++pos)\n        {\n            const char c = str[pos];\n            if(_is_hex_char(c))\n            {\n                fracchars = true;\n            }\n            else if(c == 'p' || c == 'P')\n            {\n                ++pos;\n                goto power_part_hex;\n            }\n            else if(_is_delim_char(c))\n            {\n                return intchars || fracchars ? first(pos) : first(0);\n            }\n            else\n            {\n                return first(0);\n            }\n        }\n        return intchars || fracchars ?\n            *this :\n            first(0);\n    power_part_hex:\n        C4_ASSERT(pos > 0);\n        C4_ASSERT(str[pos - 1] == 'p' || str[pos - 1] == 'P');\n        // either a + or a - is expected here, followed by more chars.\n        // also, using (pos+1) in this check will cause an early\n        // return when no more chars follow the sign.\n        if(len <= (pos+1) || (str[pos] != '+' && str[pos] != '-') || ((!intchars) && (!fracchars)))\n            return first(0);\n        ++pos; // this was the sign.\n        // ... so the (pos+1) ensures that we enter the loop and\n        // hence that there exist chars in the power part\n        powchars = false;\n        for( ; pos < len; ++pos)\n        {\n            const char c = str[pos];\n            if(c >= '0' && c <= '9')\n                powchars = true;\n            else if(powchars && _is_delim_char(c))\n                return first(pos);\n            else\n                return first(0);\n        }\n        return *this;\n    }\n\n    // this function is declared inside the class to avoid a VS error with __declspec(dllimport)\n    C4_NO_INLINE C4_PURE basic_substring _first_real_span_bin(size_t pos) const noexcept\n    {\n        bool intchars = false;\n        bool fracchars = false;\n        bool powchars;\n        // integral part\n        for( ; pos < len; ++pos)\n        {\n            const char c = str[pos];\n            if(c == '0' || c == '1')\n            {\n                intchars = true;\n            }\n            else if(c == '.')\n            {\n                ++pos;\n                goto fractional_part_bin;\n            }\n            else if(c == 'p' || c == 'P')\n            {\n                ++pos;\n                goto power_part_bin;\n            }\n            else if(_is_delim_char(c))\n            {\n                return intchars ? first(pos) : first(0);\n            }\n            else\n            {\n                return first(0);\n            }\n        }\n        // no . or p were found; this is either an integral number\n        // or not a number at all\n        return intchars ?\n            *this :\n            first(0);\n    fractional_part_bin:\n        C4_ASSERT(pos > 0);\n        C4_ASSERT(str[pos - 1] == '.');\n        for( ; pos < len; ++pos)\n        {\n            const char c = str[pos];\n            if(c == '0' || c == '1')\n            {\n                fracchars = true;\n            }\n            else if(c == 'p' || c == 'P')\n            {\n                ++pos;\n                goto power_part_bin;\n            }\n            else if(_is_delim_char(c))\n            {\n                return intchars || fracchars ? first(pos) : first(0);\n            }\n            else\n            {\n                return first(0);\n            }\n        }\n        return intchars || fracchars ?\n            *this :\n            first(0);\n    power_part_bin:\n        C4_ASSERT(pos > 0);\n        C4_ASSERT(str[pos - 1] == 'p' || str[pos - 1] == 'P');\n        // either a + or a - is expected here, followed by more chars.\n        // also, using (pos+1) in this check will cause an early\n        // return when no more chars follow the sign.\n        if(len <= (pos+1) || (str[pos] != '+' && str[pos] != '-') || ((!intchars) && (!fracchars)))\n            return first(0);\n        ++pos; // this was the sign.\n        // ... so the (pos+1) ensures that we enter the loop and\n        // hence that there exist chars in the power part\n        powchars = false;\n        for( ; pos < len; ++pos)\n        {\n            const char c = str[pos];\n            if(c >= '0' && c <= '9')\n                powchars = true;\n            else if(powchars && _is_delim_char(c))\n                return first(pos);\n            else\n                return first(0);\n        }\n        return *this;\n    }\n\n    // this function is declared inside the class to avoid a VS error with __declspec(dllimport)\n    C4_NO_INLINE C4_PURE basic_substring _first_real_span_oct(size_t pos) const noexcept\n    {\n        bool intchars = false;\n        bool fracchars = false;\n        bool powchars;\n        // integral part\n        for( ; pos < len; ++pos)\n        {\n            const char c = str[pos];\n            if(c >= '0' && c <= '7')\n            {\n                intchars = true;\n            }\n            else if(c == '.')\n            {\n                ++pos;\n                goto fractional_part_oct;\n            }\n            else if(c == 'p' || c == 'P')\n            {\n                ++pos;\n                goto power_part_oct;\n            }\n            else if(_is_delim_char(c))\n            {\n                return intchars ? first(pos) : first(0);\n            }\n            else\n            {\n                return first(0);\n            }\n        }\n        // no . or p were found; this is either an integral number\n        // or not a number at all\n        return intchars ?\n            *this :\n            first(0);\n    fractional_part_oct:\n        C4_ASSERT(pos > 0);\n        C4_ASSERT(str[pos - 1] == '.');\n        for( ; pos < len; ++pos)\n        {\n            const char c = str[pos];\n            if(c >= '0' && c <= '7')\n            {\n                fracchars = true;\n            }\n            else if(c == 'p' || c == 'P')\n            {\n                ++pos;\n                goto power_part_oct;\n            }\n            else if(_is_delim_char(c))\n            {\n                return intchars || fracchars ? first(pos) : first(0);\n            }\n            else\n            {\n                return first(0);\n            }\n        }\n        return intchars || fracchars ?\n            *this :\n            first(0);\n    power_part_oct:\n        C4_ASSERT(pos > 0);\n        C4_ASSERT(str[pos - 1] == 'p' || str[pos - 1] == 'P');\n        // either a + or a - is expected here, followed by more chars.\n        // also, using (pos+1) in this check will cause an early\n        // return when no more chars follow the sign.\n        if(len <= (pos+1) || (str[pos] != '+' && str[pos] != '-') || ((!intchars) && (!fracchars)))\n            return first(0);\n        ++pos; // this was the sign.\n        // ... so the (pos+1) ensures that we enter the loop and\n        // hence that there exist chars in the power part\n        powchars = false;\n        for( ; pos < len; ++pos)\n        {\n            const char c = str[pos];\n            if(c >= '0' && c <= '9')\n                powchars = true;\n            else if(powchars && _is_delim_char(c))\n                return first(pos);\n            else\n                return first(0);\n        }\n        return *this;\n    }\n\n    /** @} */\n\npublic:\n\n    /** @name Splitting methods */\n    /** @{ */\n\n    /** returns true if the string has not been exhausted yet, meaning\n     * it's ok to call next_split() again. When no instance of sep\n     * exists in the string, returns the full string. When the input\n     * is an empty string, the output string is the empty string. */\n    bool next_split(C sep, size_t *C4_RESTRICT start_pos, basic_substring *C4_RESTRICT out) const\n    {\n        if(C4_LIKELY(*start_pos < len))\n        {\n            for(size_t i = *start_pos; i < len; i++)\n            {\n                if(str[i] == sep)\n                {\n                    out->assign(str + *start_pos, i - *start_pos);\n                    *start_pos = i+1;\n                    return true;\n                }\n            }\n            out->assign(str + *start_pos, len - *start_pos);\n            *start_pos = len + 1;\n            return true;\n        }\n        else\n        {\n            bool valid = len > 0 && (*start_pos == len);\n            if(valid && str && str[len-1] == sep)\n            {\n                out->assign(str + len, size_t(0)); // the cast is needed to prevent overload ambiguity\n            }\n            else\n            {\n                out->assign(str + len + 1, size_t(0)); // the cast is needed to prevent overload ambiguity\n            }\n            *start_pos = len + 1;\n            return valid;\n        }\n    }\n\nprivate:\n\n    struct split_proxy_impl\n    {\n        struct split_iterator_impl\n        {\n            split_proxy_impl const* m_proxy;\n            basic_substring m_str;\n            size_t m_pos;\n            NCC_ m_sep;\n\n            split_iterator_impl(split_proxy_impl const* proxy, size_t pos, C sep)\n                : m_proxy(proxy), m_pos(pos), m_sep(sep)\n            {\n                _tick();\n            }\n\n            void _tick()\n            {\n                m_proxy->m_str.next_split(m_sep, &m_pos, &m_str);\n            }\n\n            split_iterator_impl& operator++ () { _tick(); return *this; }\n            split_iterator_impl  operator++ (int) { split_iterator_impl it = *this; _tick(); return it; }\n\n            basic_substring& operator*  () { return  m_str; }\n            basic_substring* operator-> () { return &m_str; }\n\n            bool operator!= (split_iterator_impl const& that) const\n            {\n                return !(this->operator==(that));\n            }\n            bool operator== (split_iterator_impl const& that) const\n            {\n                C4_XASSERT((m_sep == that.m_sep) && \"cannot compare split iterators with different separators\");\n                if(m_str.size() != that.m_str.size())\n                    return false;\n                if(m_str.data() != that.m_str.data())\n                    return false;\n                return m_pos == that.m_pos;\n            }\n        };\n\n        basic_substring m_str;\n        size_t m_start_pos;\n        C m_sep;\n\n        split_proxy_impl(basic_substring str_, size_t start_pos, C sep)\n            : m_str(str_), m_start_pos(start_pos), m_sep(sep)\n        {\n        }\n\n        split_iterator_impl begin() const\n        {\n            auto it = split_iterator_impl(this, m_start_pos, m_sep);\n            return it;\n        }\n        split_iterator_impl end() const\n        {\n            size_t pos = m_str.size() + 1;\n            auto it = split_iterator_impl(this, pos, m_sep);\n            return it;\n        }\n    };\n\npublic:\n\n    using split_proxy = split_proxy_impl;\n\n    /** a view into the splits */\n    split_proxy split(C sep, size_t start_pos=0) const\n    {\n        C4_XASSERT((start_pos >= 0 && start_pos < len) || empty());\n        auto ss = sub(0, len);\n        auto it = split_proxy(ss, start_pos, sep);\n        return it;\n    }\n\npublic:\n\n    /** pop right: return the first split from the right. Use\n     * gpop_left() to get the reciprocal part.\n     */\n    basic_substring pop_right(C sep=C('/'), bool skip_empty=false) const\n    {\n        if(C4_LIKELY(len > 1))\n        {\n            auto pos = last_of(sep);\n            if(pos != npos)\n            {\n                if(pos + 1 < len) // does not end with sep\n                {\n                    return sub(pos + 1); // return from sep to end\n                }\n                else // the string ends with sep\n                {\n                    if( ! skip_empty)\n                    {\n                        return sub(pos + 1, 0);\n                    }\n                    auto ppos = last_not_of(sep); // skip repeated seps\n                    if(ppos == npos) // the string is all made of seps\n                    {\n                        return sub(0, 0);\n                    }\n                    // find the previous sep\n                    auto pos0 = last_of(sep, ppos);\n                    if(pos0 == npos) // only the last sep exists\n                    {\n                        return sub(0); // return the full string (because skip_empty is true)\n                    }\n                    ++pos0;\n                    return sub(pos0);\n                }\n            }\n            else // no sep was found, return the full string\n            {\n                return *this;\n            }\n        }\n        else if(len == 1)\n        {\n            if(begins_with(sep))\n            {\n                return sub(0, 0);\n            }\n            return *this;\n        }\n        else // an empty string\n        {\n            return basic_substring();\n        }\n    }\n\n    /** return the first split from the left. Use gpop_right() to get\n     * the reciprocal part. */\n    basic_substring pop_left(C sep = C('/'), bool skip_empty=false) const\n    {\n        if(C4_LIKELY(len > 1))\n        {\n            auto pos = first_of(sep);\n            if(pos != npos)\n            {\n                if(pos > 0)  // does not start with sep\n                {\n                    return sub(0, pos); //  return everything up to it\n                }\n                else  // the string starts with sep\n                {\n                    if( ! skip_empty)\n                    {\n                        return sub(0, 0);\n                    }\n                    auto ppos = first_not_of(sep); // skip repeated seps\n                    if(ppos == npos) // the string is all made of seps\n                    {\n                        return sub(0, 0);\n                    }\n                    // find the next sep\n                    auto pos0 = first_of(sep, ppos);\n                    if(pos0 == npos) // only the first sep exists\n                    {\n                        return sub(0); // return the full string (because skip_empty is true)\n                    }\n                    C4_XASSERT(pos0 > 0);\n                    // return everything up to the second sep\n                    return sub(0, pos0);\n                }\n            }\n            else // no sep was found, return the full string\n            {\n                return sub(0);\n            }\n        }\n        else if(len == 1)\n        {\n            if(begins_with(sep))\n            {\n                return sub(0, 0);\n            }\n            return sub(0);\n        }\n        else // an empty string\n        {\n            return basic_substring();\n        }\n    }\n\npublic:\n\n    /** greedy pop left. eg, csubstr(\"a/b/c\").gpop_left('/')=\"c\" */\n    basic_substring gpop_left(C sep = C('/'), bool skip_empty=false) const\n    {\n        auto ss = pop_right(sep, skip_empty);\n        ss = left_of(ss);\n        if(ss.find(sep) != npos)\n        {\n            if(ss.ends_with(sep))\n            {\n                if(skip_empty)\n                {\n                    ss = ss.trimr(sep);\n                }\n                else\n                {\n                    ss = ss.sub(0, ss.len-1); // safe to subtract because ends_with(sep) is true\n                }\n            }\n        }\n        return ss;\n    }\n\n    /** greedy pop right. eg, csubstr(\"a/b/c\").gpop_right('/')=\"a\" */\n    basic_substring gpop_right(C sep = C('/'), bool skip_empty=false) const\n    {\n        auto ss = pop_left(sep, skip_empty);\n        ss = right_of(ss);\n        if(ss.find(sep) != npos)\n        {\n            if(ss.begins_with(sep))\n            {\n                if(skip_empty)\n                {\n                    ss = ss.triml(sep);\n                }\n                else\n                {\n                    ss = ss.sub(1);\n                }\n            }\n        }\n        return ss;\n    }\n\n    /** @} */\n\npublic:\n\n    /** @name Path-like manipulation methods */\n    /** @{ */\n\n    basic_substring basename(C sep=C('/')) const\n    {\n        auto ss = pop_right(sep, /*skip_empty*/true);\n        ss = ss.trimr(sep);\n        return ss;\n    }\n\n    basic_substring dirname(C sep=C('/')) const\n    {\n        auto ss = basename(sep);\n        ss = ss.empty() ? *this : left_of(ss);\n        return ss;\n    }\n\n    C4_ALWAYS_INLINE basic_substring name_wo_extshort() const\n    {\n        return gpop_left('.');\n    }\n\n    C4_ALWAYS_INLINE basic_substring name_wo_extlong() const\n    {\n        return pop_left('.');\n    }\n\n    C4_ALWAYS_INLINE basic_substring extshort() const\n    {\n        return pop_right('.');\n    }\n\n    C4_ALWAYS_INLINE basic_substring extlong() const\n    {\n        return gpop_right('.');\n    }\n\n    /** @} */\n\npublic:\n\n    /** @name Content-modification methods (only for non-const C) */\n    /** @{ */\n\n    /** convert the string to upper-case\n     * @note this method requires that the string memory is writeable and is SFINAEd out for const C */\n    C4_REQUIRE_RW(void) toupper()\n    {\n        for(size_t i = 0; i < len; ++i)\n        {\n            str[i] = static_cast<C>(::toupper(str[i]));\n        }\n    }\n\n    /** convert the string to lower-case\n     * @note this method requires that the string memory is writeable and is SFINAEd out for const C */\n    C4_REQUIRE_RW(void) tolower()\n    {\n        for(size_t i = 0; i < len; ++i)\n        {\n            str[i] = static_cast<C>(::tolower(str[i]));\n        }\n    }\n\npublic:\n\n    /** fill the entire contents with the given @p val\n     * @note this method requires that the string memory is writeable and is SFINAEd out for const C */\n    C4_REQUIRE_RW(void) fill(C val)\n    {\n        for(size_t i = 0; i < len; ++i)\n        {\n            str[i] = val;\n        }\n    }\n\npublic:\n\n    /** set the current substring to a copy of the given csubstr\n     * @note this method requires that the string memory is writeable and is SFINAEd out for const C */\n    C4_REQUIRE_RW(void) copy_from(ro_substr that, size_t ifirst=0, size_t num=npos)\n    {\n        C4_ASSERT(ifirst >= 0 && ifirst <= len);\n        num = num != npos ? num : len - ifirst;\n        num = num < that.len ? num : that.len;\n        C4_ASSERT(ifirst + num >= 0 && ifirst + num <= len);\n        // calling memcpy with null strings is undefined behavior\n        // and will wreak havoc in calling code's branches.\n        // see https://github.com/biojppm/rapidyaml/pull/264#issuecomment-1262133637\n        if(num)\n            memcpy(str + sizeof(C) * ifirst, that.str, sizeof(C) * num);\n    }\n\npublic:\n\n    /** reverse in place\n     * @note this method requires that the string memory is writeable and is SFINAEd out for const C */\n    C4_REQUIRE_RW(void) reverse()\n    {\n        if(len == 0) return;\n        detail::_do_reverse(str, str + len - 1);\n    }\n\n    /** revert a subpart in place\n     * @note this method requires that the string memory is writeable and is SFINAEd out for const C */\n    C4_REQUIRE_RW(void) reverse_sub(size_t ifirst, size_t num)\n    {\n        C4_ASSERT(ifirst >= 0 && ifirst <= len);\n        C4_ASSERT(ifirst + num >= 0 && ifirst + num <= len);\n        if(num == 0) return;\n        detail::_do_reverse(str + ifirst, str + ifirst + num - 1);\n    }\n\n    /** revert a range in place\n     * @note this method requires that the string memory is writeable and is SFINAEd out for const C */\n    C4_REQUIRE_RW(void) reverse_range(size_t ifirst, size_t ilast)\n    {\n        C4_ASSERT(ifirst >= 0 && ifirst <= len);\n        C4_ASSERT(ilast  >= 0 && ilast  <= len);\n        if(ifirst == ilast) return;\n        detail::_do_reverse(str + ifirst, str + ilast - 1);\n    }\n\npublic:\n\n    /** erase part of the string. eg, with char s[] = \"0123456789\",\n     * substr(s).erase(3, 2) = \"01256789\", and s is now \"01245678989\"\n     * @note this method requires that the string memory is writeable and is SFINAEd out for const C */\n    C4_REQUIRE_RW(basic_substring) erase(size_t pos, size_t num)\n    {\n        C4_ASSERT(pos >= 0 && pos+num <= len);\n        size_t num_to_move = len - pos - num;\n        memmove(str + pos, str + pos + num, sizeof(C) * num_to_move);\n        return basic_substring{str, len - num};\n    }\n\n    /** @note this method requires that the string memory is writeable and is SFINAEd out for const C */\n    C4_REQUIRE_RW(basic_substring) erase_range(size_t first, size_t last)\n    {\n        C4_ASSERT(first <= last);\n        return erase(first, static_cast<size_t>(last-first));\n    }\n\n    /** erase a part of the string.\n     * @note @p sub must be a substring of this string\n     * @note this method requires that the string memory is writeable and is SFINAEd out for const C */\n    C4_REQUIRE_RW(basic_substring) erase(ro_substr sub)\n    {\n        C4_ASSERT(is_super(sub));\n        C4_ASSERT(sub.str >= str);\n        return erase(static_cast<size_t>(sub.str - str), sub.len);\n    }\n\npublic:\n\n    /** replace every occurrence of character @p value with the character @p repl\n     * @return the number of characters that were replaced\n     * @note this method requires that the string memory is writeable and is SFINAEd out for const C */\n    C4_REQUIRE_RW(size_t) replace(C value, C repl, size_t pos=0)\n    {\n        C4_ASSERT((pos >= 0 && pos <= len) || pos == npos);\n        size_t did_it = 0;\n        while((pos = find(value, pos)) != npos)\n        {\n            str[pos++] = repl;\n            ++did_it;\n        }\n        return did_it;\n    }\n\n    /** replace every occurrence of each character in @p value with\n     * the character @p repl.\n     * @return the number of characters that were replaced\n     * @note this method requires that the string memory is writeable and is SFINAEd out for const C */\n    C4_REQUIRE_RW(size_t) replace(ro_substr chars, C repl, size_t pos=0)\n    {\n        C4_ASSERT((pos >= 0 && pos <= len) || pos == npos);\n        size_t did_it = 0;\n        while((pos = first_of(chars, pos)) != npos)\n        {\n            str[pos++] = repl;\n            ++did_it;\n        }\n        return did_it;\n    }\n\n    /** replace @p pattern with @p repl, and write the result into\n     * @p dst. pattern and repl don't need equal sizes.\n     *\n     * @return the required size for dst. No overflow occurs if\n     * dst.len is smaller than the required size; this can be used to\n     * determine the required size for an existing container. */\n    size_t replace_all(rw_substr dst, ro_substr pattern, ro_substr repl, size_t pos=0) const\n    {\n        C4_ASSERT( ! pattern.empty()); //!< @todo relax this precondition\n        C4_ASSERT( ! this  ->overlaps(dst)); //!< @todo relax this precondition\n        C4_ASSERT( ! pattern.overlaps(dst));\n        C4_ASSERT( ! repl   .overlaps(dst));\n        C4_ASSERT((pos >= 0 && pos <= len) || pos == npos);\n        C4_SUPPRESS_WARNING_GCC_PUSH\n        C4_SUPPRESS_WARNING_GCC(\"-Warray-bounds\")  // gcc11 has a false positive here\n        #if (!defined(__clang__)) && (defined(__GNUC__) && (__GNUC__ >= 7))\n        C4_SUPPRESS_WARNING_GCC(\"-Wstringop-overflow\")  // gcc11 has a false positive here\n        #endif\n        #define _c4append(first, last)                                  \\\n            {                                                           \\\n                C4_ASSERT((last) >= (first));                           \\\n                size_t num = static_cast<size_t>((last) - (first));     \\\n                if(num > 0 && sz + num <= dst.len)                      \\\n                {                                                       \\\n                    memcpy(dst.str + sz, first, num * sizeof(C));       \\\n                }                                                       \\\n                sz += num;                                              \\\n            }\n        size_t sz = 0;\n        size_t b = pos;\n        _c4append(str, str + pos);\n        do {\n            size_t e = find(pattern, b);\n            if(e == npos)\n            {\n                _c4append(str + b, str + len);\n                break;\n            }\n            _c4append(str + b, str + e);\n            _c4append(repl.begin(), repl.end());\n            b = e + pattern.size();\n        } while(b < len && b != npos);\n        return sz;\n        #undef _c4append\n        C4_SUPPRESS_WARNING_GCC_POP\n    }\n\n    /** @} */\n\n}; // template class basic_substring\n\n\n#undef C4_REQUIRE_RW\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n\n/** @defgroup doc_substr_adapters substr adapters\n *\n * to_substr() and to_csubstr() is used in generic code like\n * format(), and allow adding construction of substrings from new\n * types like containers.\n * @{ */\n\n\n/** neutral version for use in generic code */\nC4_ALWAYS_INLINE substr to_substr(substr s) noexcept { return s; }\n/** neutral version for use in generic code */\nC4_ALWAYS_INLINE csubstr to_csubstr(substr s) noexcept { return s; }\n/** neutral version for use in generic code */\nC4_ALWAYS_INLINE csubstr to_csubstr(csubstr s) noexcept { return s; }\n\n\ntemplate<size_t N>\nC4_ALWAYS_INLINE substr\nto_substr(char (&s)[N]) noexcept { substr ss(s, N-1); return ss; }\ntemplate<size_t N>\nC4_ALWAYS_INLINE csubstr\nto_csubstr(const char (&s)[N]) noexcept { csubstr ss(s, N-1); return ss; }\n\n\n/** @note this overload uses SFINAE to prevent it from overriding the array overload\n * @see For a more detailed explanation on why the plain overloads cannot\n * coexist, see http://cplusplus.bordoon.com/specializeForCharacterArrays.html */\ntemplate<class U>\nC4_ALWAYS_INLINE typename std::enable_if<std::is_same<U, char*>::value, substr>::type\nto_substr(U s) noexcept { substr ss(s); return ss; }\n/** @note this overload uses SFINAE to prevent it from overriding the array overload\n * @see For a more detailed explanation on why the plain overloads cannot\n * coexist, see http://cplusplus.bordoon.com/specializeForCharacterArrays.html */\ntemplate<class U>\nC4_ALWAYS_INLINE typename std::enable_if<std::is_same<U, const char*>::value || std::is_same<U, char*>::value, csubstr>::type\nto_csubstr(U s) noexcept { csubstr ss(s); return ss; }\n\n\n/** @} */\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n/** @defgroup doc_substr_cmp substr comparison operators\n * @{ */\n\ntemplate<typename C, size_t N> inline bool operator== (const char (&s)[N], basic_substring<C> const that) noexcept { return that.compare(s, N-1) == 0; }\ntemplate<typename C, size_t N> inline bool operator!= (const char (&s)[N], basic_substring<C> const that) noexcept { return that.compare(s, N-1) != 0; }\ntemplate<typename C, size_t N> inline bool operator<  (const char (&s)[N], basic_substring<C> const that) noexcept { return that.compare(s, N-1) >  0; }\ntemplate<typename C, size_t N> inline bool operator>  (const char (&s)[N], basic_substring<C> const that) noexcept { return that.compare(s, N-1) <  0; }\ntemplate<typename C, size_t N> inline bool operator<= (const char (&s)[N], basic_substring<C> const that) noexcept { return that.compare(s, N-1) >= 0; }\ntemplate<typename C, size_t N> inline bool operator>= (const char (&s)[N], basic_substring<C> const that) noexcept { return that.compare(s, N-1) <= 0; }\n\ntemplate<typename C> inline bool operator== (const char c, basic_substring<C> const that) noexcept { return that.compare(c) == 0; }\ntemplate<typename C> inline bool operator!= (const char c, basic_substring<C> const that) noexcept { return that.compare(c) != 0; }\ntemplate<typename C> inline bool operator<  (const char c, basic_substring<C> const that) noexcept { return that.compare(c) >  0; }\ntemplate<typename C> inline bool operator>  (const char c, basic_substring<C> const that) noexcept { return that.compare(c) <  0; }\ntemplate<typename C> inline bool operator<= (const char c, basic_substring<C> const that) noexcept { return that.compare(c) >= 0; }\ntemplate<typename C> inline bool operator>= (const char c, basic_substring<C> const that) noexcept { return that.compare(c) <= 0; }\n\n/** @} */\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n/* C4_SUBSTR_NO_OSTREAM_LSHIFT doctest does not deal well with\n * template operator<<\n * @see https://github.com/onqtam/doctest/pull/431 */\n#ifndef C4_SUBSTR_NO_OSTREAM_LSHIFT\n#ifdef __clang__\n#   pragma clang diagnostic push\n#   pragma clang diagnostic ignored \"-Wsign-conversion\"\n#elif defined(__GNUC__)\n#   pragma GCC diagnostic push\n#   pragma GCC diagnostic ignored \"-Wsign-conversion\"\n#endif\n\n/** output the string to a stream */\ntemplate<class OStream, class C>\ninline OStream& operator<< (OStream& os, basic_substring<C> s)\n{\n    os.write(s.str, s.len);\n    return os;\n}\n\n// this causes ambiguity\n///** this is used by google test */\n//template<class OStream, class C>\n//inline void PrintTo(basic_substring<C> s, OStream* os)\n//{\n//    os->write(s.str, s.len);\n//}\n\n#ifdef __clang__\n#   pragma clang diagnostic pop\n#elif defined(__GNUC__)\n#   pragma GCC diagnostic pop\n#endif\n#endif // !C4_SUBSTR_NO_OSTREAM_LSHIFT\n\n/** @} */\n\n} // namespace c4\n\n\n#ifdef __clang__\n#   pragma clang diagnostic pop\n#elif defined(__GNUC__)\n#   pragma GCC diagnostic pop\n#endif\n\n#endif /* _C4_SUBSTR_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/substr_fwd.hpp",
    "content": "#ifndef _C4_SUBSTR_FWD_HPP_\n#define _C4_SUBSTR_FWD_HPP_\n\n#include \"c4/export.hpp\"\n\nnamespace c4 {\n\n#ifndef DOXYGEN\ntemplate<class C> struct basic_substring;\nusing csubstr = C4CORE_EXPORT basic_substring<const char>;\nusing substr = C4CORE_EXPORT basic_substring<char>;\n#endif // !DOXYGEN\n\n} // namespace c4\n\n#endif /* _C4_SUBSTR_FWD_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/szconv.hpp",
    "content": "#ifndef _C4_SZCONV_HPP_\n#define _C4_SZCONV_HPP_\n\n/** @file szconv.hpp utilities to deal safely with narrowing conversions */\n\n#include \"c4/config.hpp\"\n#include \"c4/error.hpp\"\n\n#include <limits>\n\nnamespace c4 {\n\nC4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH(\"-Wold-style-cast\")\n\n/** @todo this would be so much easier with calls to numeric_limits::max()... */\ntemplate<class SizeOut, class SizeIn>\nstruct is_narrower_size : std::conditional\n<\n   (std::is_signed<SizeOut>::value == std::is_signed<SizeIn>::value)\n   ?\n   (sizeof(SizeOut) < sizeof(SizeIn))\n   :\n   (\n       (sizeof(SizeOut) < sizeof(SizeIn))\n       ||\n       (\n           (sizeof(SizeOut) == sizeof(SizeIn))\n           &&\n           (std::is_signed<SizeOut>::value && std::is_unsigned<SizeIn>::value)\n       )\n   ),\n   std::true_type,\n   std::false_type\n>::type\n{\n    static_assert(std::is_integral<SizeIn >::value, \"must be integral type\");\n    static_assert(std::is_integral<SizeOut>::value, \"must be integral type\");\n};\n\n\n/** when SizeOut is wider than SizeIn, assignment can occur without reservations */\ntemplate<class SizeOut, class SizeIn>\nC4_ALWAYS_INLINE\ntypename std::enable_if< ! is_narrower_size<SizeOut, SizeIn>::value, SizeOut>::type\nszconv(SizeIn sz) noexcept\n{\n    return static_cast<SizeOut>(sz);\n}\n\n/** when SizeOut is narrower than SizeIn, narrowing will occur, so we check\n * for overflow. Note that this check is done only if C4_XASSERT is enabled.\n * @see C4_XASSERT */\ntemplate<class SizeOut, class SizeIn>\nC4_ALWAYS_INLINE\ntypename std::enable_if<is_narrower_size<SizeOut, SizeIn>::value, SizeOut>::type\nszconv(SizeIn sz)\n{\n    C4_XASSERT(sz >= 0);\n    C4_XASSERT_MSG((SizeIn)sz <= (SizeIn)std::numeric_limits<SizeOut>::max(), \"size conversion overflow: in=%zu\", (size_t)sz);\n    SizeOut szo = static_cast<SizeOut>(sz);\n    return szo;\n}\n\nC4_SUPPRESS_WARNING_GCC_CLANG_POP\n\n} // namespace c4\n\n#endif /* _C4_SZCONV_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/type_name.hpp",
    "content": "#ifndef _C4_TYPENAME_HPP_\n#define _C4_TYPENAME_HPP_\n\n/** @file type_name.hpp compile-time type name */\n\n#include \"c4/span.hpp\"\n#include \"c4/compiler.hpp\"\n\n/// @cond dev\nstruct _c4t\n{\n    const char *str;\n    size_t sz;\n    template<size_t N>\n    constexpr _c4t(const char (&s)[N]) : str(s), sz(N-1) {} // take off the \\0\n};\n// this is a more abbreviated way of getting the type name\n// (if we used span in the return type, the name would involve\n// templates and would create longer type name strings,\n// as well as larger differences between compilers)\ntemplate<class T>\nC4_CONSTEXPR14 C4_ALWAYS_INLINE\n_c4t _c4tn()\n{\n    auto p = _c4t(C4_PRETTY_FUNC);\n    return p;\n}\n/// @endcond\n\n\nnamespace c4 {\n\n/** compile-time type name\n * @see http://stackoverflow.com/a/20170989/5875572 */\ntemplate<class T>\nC4_CONSTEXPR14 cspan<char> type_name()\n{\n    const _c4t p = _c4tn<T>();\n\n#if (0) // enable this to debug and find the offsets\n    for(size_t index = 0; index < p.sz; ++index)\n        printf(\" %2c\", p.str[index]);\n    printf(\"\\n\");\n    for(size_t index = 0; index < p.sz; ++index)\n        printf(\" %2zu\", index);\n    printf(\"\\n\");\n#endif\n\n#if defined(_MSC_VER)\n#   if defined(__clang__) // Visual Studio has the clang toolset\n#   if (_MSC_VER >= 1930) // do not use this: defined(C4_MSVC_2022)\n    // ..............................xxx.\n    // _c4t __cdecl _c4tn(void) [T = int]\n    enum : size_t { tstart = 30, tend = 1};\n#   else\n    // example:\n    // ..........................xxx.\n    // _c4t __cdecl _c4tn() [T = int]\n    enum : size_t { tstart = 26, tend = 1};\n#   endif\n#   elif defined(C4_MSVC_2015) || defined(C4_MSVC_2017) || defined(C4_MSVC_2019) || defined(C4_MSVC_2022)\n    // Note: subtract 7 at the end because the function terminates with \">(void)\" in VS2015+\n    cspan<char>::size_type tstart = 26, tend = 7;\n\n    const char *C4_RESTRICT s = p.str + tstart; // look at the start\n\n    // we're not using strcmp() or memcmp() to spare the #include\n\n    // does it start with 'class '?\n    if(p.sz > 6 && s[0] == 'c' && s[1] == 'l' && s[2] == 'a' && s[3] == 's' && s[4] == 's' && s[5] == ' ')\n    {\n        tstart += 6;\n    }\n    // does it start with 'struct '?\n    else if(p.sz > 7 && s[0] == 's' && s[1] == 't' && s[2] == 'r' && s[3] == 'u' && s[4] == 'c' && s[5] == 't' && s[6] == ' ')\n    {\n        tstart += 7;\n    }\n\n#   else\n    C4_NOT_IMPLEMENTED();\n#   endif\n\n#elif defined(__ICC)\n    // example:\n    // ........................xxx.\n    // \"_c4t _c4tn() [with T = int]\"\n    enum : size_t { tstart = 23, tend = 1};\n\n#elif defined(__clang__)\n    // example:\n    // ...................xxx.\n    // \"_c4t _c4tn() [T = int]\"\n    enum : size_t { tstart = 18, tend = 1};\n\n#elif defined(__GNUC__)\n    #if __GNUC__ >= 7 && C4_CPP >= 14\n        // example:\n        // ..................................xxx.\n        // \"constexpr _c4t _c4tn() [with T = int]\"\n        enum : size_t { tstart = 33, tend = 1 };\n    #else\n        // example:\n        // ........................xxx.\n        // \"_c4t _c4tn() [with T = int]\"\n        enum : size_t { tstart = 23, tend = 1 };\n    #endif\n#else\n    C4_NOT_IMPLEMENTED();\n#endif\n\n    cspan<char> o(p.str + tstart, p.sz - tstart - tend);\n\n    return o;\n}\n\n/** compile-time type name\n * @overload */\ntemplate<class T>\nC4_CONSTEXPR14 C4_ALWAYS_INLINE cspan<char> type_name(T const&)\n{\n    return type_name<T>();\n}\n\n} // namespace c4\n\n#endif //_C4_TYPENAME_HPP_\n"
  },
  {
    "path": "libs/rapidyaml/c4/types.hpp",
    "content": "#ifndef _C4_TYPES_HPP_\n#define _C4_TYPES_HPP_\n\n#include <stdint.h>\n#include <stddef.h>\n#include <type_traits>\n\n#if __cplusplus >= 201103L\n#include <utility>  // for integer_sequence and friends\n#endif\n\n#include \"c4/preprocessor.hpp\"\n#include \"c4/language.hpp\"\n\n/** @file types.hpp basic types, and utility macros and traits for types.\n * @ingroup basic_headers */\n\n/** @defgroup types Type utilities */\n\nnamespace c4 {\n\n/** @defgroup intrinsic_types Intrinsic types\n * @ingroup types\n * @{ */\n\nusing cbyte = const char; /**< a constant byte */\nusing  byte =       char; /**< a mutable byte */\n\nusing  i8 =   int8_t;\nusing i16 =  int16_t;\nusing i32 =  int32_t;\nusing i64 =  int64_t;\nusing  u8 =  uint8_t;\nusing u16 = uint16_t;\nusing u32 = uint32_t;\nusing u64 = uint64_t;\n\nusing f32 =  float;\nusing f64 = double;\n\nusing ssize_t = typename std::make_signed<size_t>::type;\n\n/** @} */\n\n//--------------------------------------------------\n\n/** @defgroup utility_types Utility types\n * @ingroup types\n * @{ */\n\n// some tag types\n\n#if !defined(__clang__) && defined(__GNUC__)\n#pragma GCC diagnostic push\n#if __GNUC__ >= 6\n#pragma GCC diagnostic ignored \"-Wunused-const-variable\"\n#endif\n#endif\n\n/** a tag type for initializing the containers with variadic arguments a la\n * initializer_list, minus the initializer_list overload problems.\n */\nstruct aggregate_t {};\n/** @see aggregate_t */\nconstexpr const aggregate_t aggregate{};\n\n/** a tag type for specifying the initial capacity of allocatable contiguous storage */\nstruct with_capacity_t {};\n/** @see with_capacity_t */\nconstexpr const with_capacity_t with_capacity{};\n\n/** a tag type for disambiguating template parameter packs in variadic template overloads */\nstruct varargs_t {};\n/** @see with_capacity_t */\nconstexpr const varargs_t varargs{};\n\n#if !defined(__clang__) && defined(__GNUC__)\n#pragma GCC diagnostic pop\n#endif\n\n\n//--------------------------------------------------\n\n/** whether a value should be used in place of a const-reference in argument passing. */\ntemplate<class T>\nstruct cref_uses_val\n{\n    enum { value = (\n    std::is_scalar<T>::value\n    ||\n    (\n#if C4_CPP >= 20\n        (std::is_trivially_copyable<T>::value && std::is_standard_layout<T>::value)\n#else\n        std::is_pod<T>::value\n#endif\n        &&\n        sizeof(T) <= sizeof(size_t))) };\n};\n/** utility macro to override the default behaviour for c4::fastcref<T>\n @see fastcref */\n#define C4_CREF_USES_VAL(T) \\\ntemplate<>                  \\\nstruct cref_uses_val<T>     \\\n{                           \\\n    enum { value = true };  \\\n};\n\n/** Whether to use pass-by-value or pass-by-const-reference in a function argument\n * or return type. */\ntemplate<class T>\nusing fastcref = typename std::conditional<c4::cref_uses_val<T>::value, T, T const&>::type;\n\n//--------------------------------------------------\n\n/** Just what its name says. Useful sometimes as a default empty policy class. */\nstruct EmptyStruct\n{\n    template<class... T> EmptyStruct(T && ...){}\n};\n\n/** Just what its name says. Useful sometimes as a default policy class to\n * be inherited from. */\nstruct EmptyStructVirtual\n{\n    virtual ~EmptyStructVirtual() = default;\n    template<class... T> EmptyStructVirtual(T && ...){}\n};\n\n\n/** */\ntemplate<class T>\nstruct inheritfrom : public T {};\n\n//--------------------------------------------------\n// Utilities to make a class obey size restrictions (eg, min size or size multiple of).\n// DirectX usually makes this restriction with uniform buffers.\n// This is also useful for padding to prevent false-sharing.\n\n/** how many bytes must be added to size such that the result is at least minsize? */\nC4_ALWAYS_INLINE constexpr size_t min_remainder(size_t size, size_t minsize) noexcept\n{\n    return size < minsize ? minsize-size : 0;\n}\n\n/** how many bytes must be added to size such that the result is a multiple of multipleof?  */\nC4_ALWAYS_INLINE constexpr size_t mult_remainder(size_t size, size_t multipleof) noexcept\n{\n    return (((size % multipleof) != 0) ? (multipleof-(size % multipleof)) : 0);\n}\n\n/* force the following class to be tightly packed. */\n#pragma pack(push, 1)\n/** pad a class with more bytes at the end.\n * @see http://stackoverflow.com/questions/21092415/force-c-structure-to-pack-tightly */\ntemplate<class T, size_t BytesToPadAtEnd>\nstruct Padded : public T\n{\n    using T::T;\n    using T::operator=;\n    Padded(T const& val) : T(val) {}\n    Padded(T && val) : T(val) {}\n    char ___c4padspace___[BytesToPadAtEnd];\n};\n#pragma pack(pop)\n/** When the padding argument is 0, we cannot declare the char[] array. */\ntemplate<class T>\nstruct Padded<T, 0> : public T\n{\n    using T::T;\n    using T::operator=;\n    Padded(T const& val) : T(val) {}\n    Padded(T && val) : T(val) {}\n};\n\n/** make T have a size which is at least Min bytes */\ntemplate<class T, size_t Min>\nusing MinSized = Padded<T, min_remainder(sizeof(T), Min)>;\n\n/** make T have a size which is a multiple of Mult bytes */\ntemplate<class T, size_t Mult>\nusing MultSized = Padded<T, mult_remainder(sizeof(T), Mult)>;\n\n/** make T have a size which is simultaneously:\n *  -bigger or equal than Min\n *  -a multiple of Mult */\ntemplate<class T, size_t Min, size_t Mult>\nusing MinMultSized = MultSized<MinSized<T, Min>, Mult>;\n\n/** make T be suitable for use as a uniform buffer. (at least with DirectX). */\ntemplate<class T>\nusing UbufSized = MinMultSized<T, 64, 16>;\n\n\n//-----------------------------------------------------------------------------\n\n#define C4_NO_COPY_CTOR(ty) ty(ty const&) = delete\n#define C4_NO_MOVE_CTOR(ty) ty(ty     &&) = delete\n#define C4_NO_COPY_ASSIGN(ty) ty& operator=(ty const&) = delete\n#define C4_NO_MOVE_ASSIGN(ty) ty& operator=(ty     &&) = delete\n#define C4_DEFAULT_COPY_CTOR(ty) ty(ty const&) noexcept = default\n#define C4_DEFAULT_MOVE_CTOR(ty) ty(ty     &&) noexcept = default\n#define C4_DEFAULT_COPY_ASSIGN(ty) ty& operator=(ty const&) noexcept = default\n#define C4_DEFAULT_MOVE_ASSIGN(ty) ty& operator=(ty     &&) noexcept = default\n\n#define C4_NO_COPY_OR_MOVE_CTOR(ty) \\\n    C4_NO_COPY_CTOR(ty); \\\n    C4_NO_MOVE_CTOR(ty)\n\n#define C4_NO_COPY_OR_MOVE_ASSIGN(ty) \\\n    C4_NO_COPY_ASSIGN(ty); \\\n    C4_NO_MOVE_ASSIGN(ty)\n\n#define C4_NO_COPY_OR_MOVE(ty) \\\n    C4_NO_COPY_OR_MOVE_CTOR(ty); \\\n    C4_NO_COPY_OR_MOVE_ASSIGN(ty)\n\n#define C4_DEFAULT_COPY_AND_MOVE_CTOR(ty) \\\n    C4_DEFAULT_COPY_CTOR(ty); \\\n    C4_DEFAULT_MOVE_CTOR(ty)\n\n#define C4_DEFAULT_COPY_AND_MOVE_ASSIGN(ty) \\\n    C4_DEFAULT_COPY_ASSIGN(ty); \\\n    C4_DEFAULT_MOVE_ASSIGN(ty)\n\n#define C4_DEFAULT_COPY_AND_MOVE(ty) \\\n    C4_DEFAULT_COPY_AND_MOVE_CTOR(ty); \\\n    C4_DEFAULT_COPY_AND_MOVE_ASSIGN(ty)\n\n/** @see https://en.cppreference.com/w/cpp/named_req/TriviallyCopyable */\n#define C4_MUST_BE_TRIVIAL_COPY(ty) \\\n    static_assert(std::is_trivially_copyable<ty>::value, #ty \" must be trivially copyable\")\n\n/** @} */\n\n\n//-----------------------------------------------------------------------------\n\n/** @defgroup traits_types Type traits utilities\n * @ingroup types\n * @{ */\n\n// http://stackoverflow.com/questions/10821380/is-t-an-instance-of-a-template-in-c\ntemplate<template<typename...> class X, typename    T> struct is_instance_of_tpl             : std::false_type {};\ntemplate<template<typename...> class X, typename... Y> struct is_instance_of_tpl<X, X<Y...>> : std::true_type {};\n\n//-----------------------------------------------------------------------------\n\n/** SFINAE. use this macro to enable a template function overload\nbased on a compile-time condition.\n@code\n// define an overload for a non-pod type\ntemplate<class T, C4_REQUIRE_T(std::is_pod<T>::value)>\nvoid foo() { std::cout << \"pod type\\n\"; }\n\n// define an overload for a non-pod type\ntemplate<class T, C4_REQUIRE_T(!std::is_pod<T>::value)>\nvoid foo() { std::cout << \"nonpod type\\n\"; }\n\nstruct non_pod\n{\n    non_pod() : name(\"asdfkjhasdkjh\") {}\n    const char *name;\n};\n\nint main()\n{\n    foo<float>(); // prints \"pod type\"\n    foo<non_pod>(); // prints \"nonpod type\"\n}\n@endcode */\n#define C4_REQUIRE_T(cond) typename std::enable_if<cond, bool>::type* = nullptr\n\n/** enable_if for a return type\n * @see C4_REQUIRE_T */\n#define C4_REQUIRE_R(cond, type_) typename std::enable_if<cond, type_>::type\n\n//-----------------------------------------------------------------------------\n/** define a traits class reporting whether a type provides a member typedef */\n#define C4_DEFINE_HAS_TYPEDEF(member_typedef)               \\\ntemplate<typename T>                                        \\\nstruct has_##stype                                          \\\n{                                                           \\\nprivate:                                                    \\\n                                                            \\\n    typedef char                      yes;                  \\\n    typedef struct { char array[2]; } no;                   \\\n                                                            \\\n    template<typename C>                                    \\\n    static yes _test(typename C::member_typedef*);          \\\n                                                            \\\n    template<typename C>                                    \\\n    static no  _test(...);                                  \\\n                                                            \\\npublic:                                                     \\\n                                                            \\\n    enum { value = (sizeof(_test<T>(0)) == sizeof(yes)) };  \\\n                                                            \\\n}\n\n\n/** @} */\n\n\n//-----------------------------------------------------------------------------\n\n\n/** @defgroup type_declarations Type declaration utilities\n * @ingroup types\n * @{ */\n\n#define _c4_DEFINE_ARRAY_TYPES_WITHOUT_ITERATOR(T, I)           \\\n                                                                \\\n    using size_type = I;                                        \\\n    using ssize_type = typename std::make_signed<I>::type;      \\\n    using difference_type = typename std::make_signed<I>::type; \\\n                                                                \\\n    using value_type = T;                                       \\\n    using pointer = T*;                                         \\\n    using const_pointer = T const*;                             \\\n    using reference = T&;                                       \\\n    using const_reference = T const&\n\n#define _c4_DEFINE_TUPLE_ARRAY_TYPES_WITHOUT_ITERATOR(interior_types, I) \\\n                                                                        \\\n    using size_type = I;                                                \\\n    using ssize_type = typename std::make_signed<I>::type;              \\\n    using difference_type = typename std::make_signed<I>::type;         \\\n                                                                        \\\n    template<I n> using value_type = typename std::tuple_element< n, std::tuple<interior_types...>>::type; \\\n    template<I n> using pointer = value_type<n>*;                       \\\n    template<I n> using const_pointer = value_type<n> const*;           \\\n    template<I n> using reference = value_type<n>&;                     \\\n    template<I n> using const_reference = value_type<n> const&\n\n\n#define _c4_DEFINE_ARRAY_TYPES(T, I)                                \\\n                                                                    \\\n    _c4_DEFINE_ARRAY_TYPES_WITHOUT_ITERATOR(T, I);                  \\\n                                                                    \\\n    using iterator = T*;                                            \\\n    using const_iterator = T const*;                                \\\n    using reverse_iterator = std::reverse_iterator<T*>;             \\\n    using const_reverse_iterator = std::reverse_iterator<T const*>\n\n\n#define _c4_DEFINE_TUPLE_ARRAY_TYPES(interior_types, I)                 \\\n                                                                        \\\n    _c4_DEFINE_TUPLE_ARRAY_TYPES_WITHOUT_ITERATOR(interior_types, I);   \\\n                                                                        \\\n    template<I n> using iterator = value_type<n>*;                      \\\n    template<I n> using const_iterator = value_type<n> const*;          \\\n    template<I n> using reverse_iterator = std::reverse_iterator< value_type<n>*>; \\\n    template<I n> using const_reverse_iterator = std::reverse_iterator< value_type<n> const*>\n\n\n\n/** @} */\n\n\n//-----------------------------------------------------------------------------\n\n\n/** @defgroup compatility_utilities Backport implementation of some Modern C++ utilities\n * @ingroup types\n * @{ */\n\n//-----------------------------------------------------------------------------\n// index_sequence and friends are available only for C++14 and later.\n// A C++11 implementation is provided here.\n// This implementation was copied over from clang.\n// see http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/utility?revision=211563&view=markup#l687\n\n#if __cplusplus > 201103L\n\nusing std::integer_sequence;\nusing std::index_sequence;\nusing std::make_integer_sequence;\nusing std::make_index_sequence;\nusing std::index_sequence_for;\n\n#else\n\n/** C++11 implementation of integer sequence\n * @see https://en.cppreference.com/w/cpp/utility/integer_sequence\n * @see taken from clang: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/utility?revision=211563&view=markup#l687 */\ntemplate<class _Tp, _Tp... _Ip>\nstruct integer_sequence\n{\n    static_assert(std::is_integral<_Tp>::value,\n                  \"std::integer_sequence can only be instantiated with an integral type\" );\n    using value_type = _Tp;\n    static constexpr size_t size() noexcept { return sizeof...(_Ip); }\n};\n\n/** C++11 implementation of index sequence\n * @see https://en.cppreference.com/w/cpp/utility/integer_sequence\n * @see taken from clang: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/utility?revision=211563&view=markup#l687 */\ntemplate<size_t... _Ip>\nusing index_sequence = integer_sequence<size_t, _Ip...>;\n\n/** @cond DONT_DOCUMENT_THIS */\nnamespace __detail {\n\ntemplate<typename _Tp, size_t ..._Extra>\nstruct __repeat;\n\ntemplate<typename _Tp, _Tp ..._Np, size_t ..._Extra>\nstruct __repeat<integer_sequence<_Tp, _Np...>, _Extra...>\n{\n    using type = integer_sequence<_Tp,\n                            _Np...,\n                            sizeof...(_Np) + _Np...,\n                            2 * sizeof...(_Np) + _Np...,\n                            3 * sizeof...(_Np) + _Np...,\n                            4 * sizeof...(_Np) + _Np...,\n                            5 * sizeof...(_Np) + _Np...,\n                            6 * sizeof...(_Np) + _Np...,\n                            7 * sizeof...(_Np) + _Np...,\n                            _Extra...>;\n};\n\ntemplate<size_t _Np> struct __parity;\ntemplate<size_t _Np> struct __make : __parity<_Np % 8>::template __pmake<_Np> {};\n\ntemplate<> struct __make<0> { using type = integer_sequence<size_t>; };\ntemplate<> struct __make<1> { using type = integer_sequence<size_t, 0>; };\ntemplate<> struct __make<2> { using type = integer_sequence<size_t, 0, 1>; };\ntemplate<> struct __make<3> { using type = integer_sequence<size_t, 0, 1, 2>; };\ntemplate<> struct __make<4> { using type = integer_sequence<size_t, 0, 1, 2, 3>; };\ntemplate<> struct __make<5> { using type = integer_sequence<size_t, 0, 1, 2, 3, 4>; };\ntemplate<> struct __make<6> { using type = integer_sequence<size_t, 0, 1, 2, 3, 4, 5>; };\ntemplate<> struct __make<7> { using type = integer_sequence<size_t, 0, 1, 2, 3, 4, 5, 6>; };\n\ntemplate<> struct __parity<0> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type> {}; };\ntemplate<> struct __parity<1> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type, _Np - 1> {}; };\ntemplate<> struct __parity<2> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type, _Np - 2, _Np - 1> {}; };\ntemplate<> struct __parity<3> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type, _Np - 3, _Np - 2, _Np - 1> {}; };\ntemplate<> struct __parity<4> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type, _Np - 4, _Np - 3, _Np - 2, _Np - 1> {}; };\ntemplate<> struct __parity<5> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type, _Np - 5, _Np - 4, _Np - 3, _Np - 2, _Np - 1> {}; };\ntemplate<> struct __parity<6> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type, _Np - 6, _Np - 5, _Np - 4, _Np - 3, _Np - 2, _Np - 1> {}; };\ntemplate<> struct __parity<7> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type, _Np - 7, _Np - 6, _Np - 5, _Np - 4, _Np - 3, _Np - 2, _Np - 1> {}; };\n\ntemplate<typename _Tp, typename _Up>\nstruct __convert\n{\n    template<typename> struct __result;\n    template<_Tp ..._Np> struct __result<integer_sequence<_Tp, _Np...>>\n    {\n        using type = integer_sequence<_Up, _Np...>;\n    };\n};\n\ntemplate<typename _Tp>\nstruct __convert<_Tp, _Tp>\n{\n    template<typename _Up> struct __result\n    {\n         using type = _Up;\n    };\n};\n\ntemplate<typename _Tp, _Tp _Np>\nusing __make_integer_sequence_unchecked = typename __detail::__convert<size_t, _Tp>::template __result<typename __detail::__make<_Np>::type>::type;\n\ntemplate<class _Tp, _Tp _Ep>\nstruct __make_integer_sequence\n{\n    static_assert(std::is_integral<_Tp>::value,\n                  \"std::make_integer_sequence can only be instantiated with an integral type\" );\n    static_assert(0 <= _Ep, \"std::make_integer_sequence input shall not be negative\");\n    typedef __make_integer_sequence_unchecked<_Tp, _Ep> type;\n};\n\n} // namespace __detail\n/** @endcond */\n\n\n/** C++11 implementation of index sequence\n * @see https://en.cppreference.com/w/cpp/utility/integer_sequence\n * @see taken from clang: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/utility?revision=211563&view=markup#l687 */\ntemplate<class _Tp, _Tp _Np>\nusing make_integer_sequence = typename __detail::__make_integer_sequence<_Tp, _Np>::type;\n\n/** C++11 implementation of index sequence\n * @see https://en.cppreference.com/w/cpp/utility/integer_sequence\n * @see taken from clang: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/utility?revision=211563&view=markup#l687 */\ntemplate<size_t _Np>\nusing make_index_sequence = make_integer_sequence<size_t, _Np>;\n\n/** C++11 implementation of index sequence\n * @see https://en.cppreference.com/w/cpp/utility/integer_sequence\n * @see taken from clang: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/utility?revision=211563&view=markup#l687 */\ntemplate<class... _Tp>\nusing index_sequence_for = make_index_sequence<sizeof...(_Tp)>;\n#endif\n\n/** @} */\n\n\n} // namespace c4\n\n#endif /* _C4_TYPES_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/unrestrict.hpp",
    "content": "#ifdef _C4_RESTRICT_HPP_ // must match the include guard from restrict.hpp\n\n/** @file unrestrict.hpp cleans up restrict macros  */\n\n#undef   $\n#undef  $$\n#undef  c$\n#undef c$$\n\n#undef _C4_RESTRICT_HPP_\n\n#ifdef __clang__\n#   pragma clang diagnostic pop\n#elif defined(__GNUC__)\n#endif\n\n#endif /* _C4_RESTRICT_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/utf.cpp",
    "content": "#include \"c4/utf.hpp\"\n#include \"c4/charconv.hpp\"\n\nnamespace c4 {\n\nC4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH(\"-Wold-style-cast\")\n\nsize_t decode_code_point(uint8_t *C4_RESTRICT buf, size_t buflen, const uint32_t code)\n{\n    C4_UNUSED(buflen);\n    C4_ASSERT(buflen >= 4);\n    if (code <= UINT32_C(0x7f))\n    {\n        buf[0] = (uint8_t)code;\n        return 1u;\n    }\n    else if(code <= UINT32_C(0x7ff))\n    {\n        buf[0] = (uint8_t)(UINT32_C(0xc0) | (code >> 6));             /* 110xxxxx */\n        buf[1] = (uint8_t)(UINT32_C(0x80) | (code & UINT32_C(0x3f))); /* 10xxxxxx */\n        return 2u;\n    }\n    else if(code <= UINT32_C(0xffff))\n    {\n        buf[0] = (uint8_t)(UINT32_C(0xe0) | ((code >> 12)));                  /* 1110xxxx */\n        buf[1] = (uint8_t)(UINT32_C(0x80) | ((code >>  6) & UINT32_C(0x3f))); /* 10xxxxxx */\n        buf[2] = (uint8_t)(UINT32_C(0x80) | ((code      ) & UINT32_C(0x3f))); /* 10xxxxxx */\n        return 3u;\n    }\n    else if(code <= UINT32_C(0x10ffff))\n    {\n        buf[0] = (uint8_t)(UINT32_C(0xf0) | ((code >> 18)));                  /* 11110xxx */\n        buf[1] = (uint8_t)(UINT32_C(0x80) | ((code >> 12) & UINT32_C(0x3f))); /* 10xxxxxx */\n        buf[2] = (uint8_t)(UINT32_C(0x80) | ((code >>  6) & UINT32_C(0x3f))); /* 10xxxxxx */\n        buf[3] = (uint8_t)(UINT32_C(0x80) | ((code      ) & UINT32_C(0x3f))); /* 10xxxxxx */\n        return 4u;\n    }\n    return 0;\n}\n\nsubstr decode_code_point(substr out, csubstr code_point)\n{\n    C4_ASSERT(out.len >= 4);\n    C4_ASSERT(!code_point.begins_with(\"U+\"));\n    C4_ASSERT(!code_point.begins_with(\"\\\\x\"));\n    C4_ASSERT(!code_point.begins_with(\"\\\\u\"));\n    C4_ASSERT(!code_point.begins_with(\"\\\\U\"));\n    C4_ASSERT(!code_point.begins_with('0'));\n    C4_ASSERT(code_point.len <= 8);\n    C4_ASSERT(code_point.len > 0);\n    uint32_t code_point_val;\n    C4_CHECK(read_hex(code_point, &code_point_val));\n    size_t ret = decode_code_point((uint8_t*)out.str, out.len, code_point_val);\n    C4_ASSERT(ret <= 4);\n    return out.first(ret);\n}\n\nC4_SUPPRESS_WARNING_GCC_CLANG_POP\n\n} // namespace c4\n"
  },
  {
    "path": "libs/rapidyaml/c4/utf.hpp",
    "content": "#ifndef C4_UTF_HPP_\n#define C4_UTF_HPP_\n\n#include \"c4/language.hpp\"\n#include \"c4/substr_fwd.hpp\"\n#include <stddef.h>\n#include <stdint.h>\n\nnamespace c4 {\n\nsubstr decode_code_point(substr out, csubstr code_point);\nsize_t decode_code_point(uint8_t *C4_RESTRICT buf, size_t buflen, const uint32_t code);\n\n} // namespace c4\n\n#endif // C4_UTF_HPP_\n"
  },
  {
    "path": "libs/rapidyaml/c4/windows.hpp",
    "content": "#ifndef _C4_WINDOWS_HPP_\n#define _C4_WINDOWS_HPP_\n\n#if defined(_WIN64) || defined(_WIN32)\n#include \"c4/windows_push.hpp\"\n#include <windows.h>\n#include \"c4/windows_pop.hpp\"\n#endif\n\n#endif /* _C4_WINDOWS_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/windows_pop.hpp",
    "content": "#ifndef _C4_WINDOWS_POP_HPP_\n#define _C4_WINDOWS_POP_HPP_\n\n#if defined(_WIN64) || defined(_WIN32)\n\n#ifdef _c4_AMD64_\n#    undef _c4_AMD64_\n#    undef _AMD64_\n#endif\n#ifdef _c4_X86_\n#    undef _c4_X86_\n#    undef _X86_\n#endif\n#ifdef _c4_ARM_\n#    undef _c4_ARM_\n#    undef _ARM_\n#endif\n\n#ifdef _c4_NOMINMAX\n#    undef _c4_NOMINMAX\n#    undef NOMINMAX\n#endif\n\n#ifdef NOGDI\n#    undef _c4_NOGDI\n#    undef NOGDI\n#endif\n\n#ifdef VC_EXTRALEAN\n#    undef _c4_VC_EXTRALEAN\n#    undef VC_EXTRALEAN\n#endif\n\n#ifdef WIN32_LEAN_AND_MEAN\n#    undef _c4_WIN32_LEAN_AND_MEAN\n#    undef WIN32_LEAN_AND_MEAN\n#endif\n\n#endif /* defined(_WIN64) || defined(_WIN32) */\n\n#endif /* _C4_WINDOWS_POP_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/windows_push.hpp",
    "content": "#ifndef _C4_WINDOWS_PUSH_HPP_\n#define _C4_WINDOWS_PUSH_HPP_\n\n/** @file windows_push.hpp sets up macros to include windows header files\n * without pulling in all of <windows.h>\n *\n * @see #include windows_pop.hpp to undefine these macros\n *\n * @see https://aras-p.info/blog/2018/01/12/Minimizing-windows.h/ */\n\n\n#if defined(_WIN64) || defined(_WIN32)\n\n#if defined(_M_AMD64)\n#   ifndef _AMD64_\n#       define _c4_AMD64_\n#       define _AMD64_\n#   endif\n#elif defined(_M_IX86)\n#   ifndef _X86_\n#       define _c4_X86_\n#       define _X86_\n#   endif\n#elif defined(_M_ARM64)\n#   ifndef _ARM64_\n#       define _c4_ARM64_\n#       define _ARM64_\n#   endif\n#elif defined(_M_ARM)\n#   ifndef _ARM_\n#       define _c4_ARM_\n#       define _ARM_\n#   endif\n#endif\n\n#ifndef NOMINMAX\n#    define _c4_NOMINMAX\n#    define NOMINMAX\n#endif\n\n#ifndef NOGDI\n#    define _c4_NOGDI\n#    define NOGDI\n#endif\n\n#ifndef VC_EXTRALEAN\n#    define _c4_VC_EXTRALEAN\n#    define VC_EXTRALEAN\n#endif\n\n#ifndef WIN32_LEAN_AND_MEAN\n#    define _c4_WIN32_LEAN_AND_MEAN\n#    define WIN32_LEAN_AND_MEAN\n#endif\n\n/*  If defined, the following flags inhibit definition\n *     of the indicated items.\n *\n *  NOGDICAPMASKS     - CC_*, LC_*, PC_*, CP_*, TC_*, RC_\n *  NOVIRTUALKEYCODES - VK_*\n *  NOWINMESSAGES     - WM_*, EM_*, LB_*, CB_*\n *  NOWINSTYLES       - WS_*, CS_*, ES_*, LBS_*, SBS_*, CBS_*\n *  NOSYSMETRICS      - SM_*\n *  NOMENUS           - MF_*\n *  NOICONS           - IDI_*\n *  NOKEYSTATES       - MK_*\n *  NOSYSCOMMANDS     - SC_*\n *  NORASTEROPS       - Binary and Tertiary raster ops\n *  NOSHOWWINDOW      - SW_*\n *  OEMRESOURCE       - OEM Resource values\n *  NOATOM            - Atom Manager routines\n *  NOCLIPBOARD       - Clipboard routines\n *  NOCOLOR           - Screen colors\n *  NOCTLMGR          - Control and Dialog routines\n *  NODRAWTEXT        - DrawText() and DT_*\n *  NOGDI             - All GDI defines and routines\n *  NOKERNEL          - All KERNEL defines and routines\n *  NOUSER            - All USER defines and routines\n *  NONLS             - All NLS defines and routines\n *  NOMB              - MB_* and MessageBox()\n *  NOMEMMGR          - GMEM_*, LMEM_*, GHND, LHND, associated routines\n *  NOMETAFILE        - typedef METAFILEPICT\n *  NOMINMAX          - Macros min(a,b) and max(a,b)\n *  NOMSG             - typedef MSG and associated routines\n *  NOOPENFILE        - OpenFile(), OemToAnsi, AnsiToOem, and OF_*\n *  NOSCROLL          - SB_* and scrolling routines\n *  NOSERVICE         - All Service Controller routines, SERVICE_ equates, etc.\n *  NOSOUND           - Sound driver routines\n *  NOTEXTMETRIC      - typedef TEXTMETRIC and associated routines\n *  NOWH              - SetWindowsHook and WH_*\n *  NOWINOFFSETS      - GWL_*, GCL_*, associated routines\n *  NOCOMM            - COMM driver routines\n *  NOKANJI           - Kanji support stuff.\n *  NOHELP            - Help engine interface.\n *  NOPROFILER        - Profiler interface.\n *  NODEFERWINDOWPOS  - DeferWindowPos routines\n *  NOMCX             - Modem Configuration Extensions\n */\n\n#endif /* defined(_WIN64) || defined(_WIN32) */\n\n#endif /* _C4_WINDOWS_PUSH_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/yml/common.cpp",
    "content": "#include \"c4/yml/common.hpp\"\n\n#ifndef RYML_NO_DEFAULT_CALLBACKS\n#   include <stdlib.h>\n#   include <stdio.h>\n#   ifdef RYML_DEFAULT_CALLBACK_USES_EXCEPTIONS\n#       include <stdexcept>\n#   endif\n#endif // RYML_NO_DEFAULT_CALLBACKS\n\n\nnamespace c4 {\nnamespace yml {\n\nC4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH(\"-Wold-style-cast\")\nC4_SUPPRESS_WARNING_MSVC_WITH_PUSH(4702/*unreachable code*/) // on the call to the unreachable macro\n\nnamespace {\nCallbacks s_default_callbacks;\n} // anon namespace\n\n#ifndef RYML_NO_DEFAULT_CALLBACKS\nvoid report_error_impl(const char* msg, size_t length, Location loc, FILE *f)\n{\n    if(!f)\n        f = stderr;\n    if(loc)\n    {\n        if(!loc.name.empty())\n        {\n            // this is more portable than using fprintf(\"%.*s:\") which\n            // is not available in some embedded platforms\n            fwrite(loc.name.str, 1, loc.name.len, f);\n            fputc(':', f);\n        }\n        fprintf(f, \"%zu:\", loc.line);\n        if(loc.col)\n            fprintf(f, \"%zu:\", loc.col);\n        if(loc.offset)\n            fprintf(f, \" (%zuB):\", loc.offset);\n        fputc(' ', f);\n    }\n    RYML_ASSERT(!csubstr(msg, length).ends_with('\\0'));\n    fwrite(msg, 1, length, f);\n    fputc('\\n', f);\n    fflush(f);\n}\n\n[[noreturn]] void error_impl(const char* msg, size_t length, Location loc, void * /*user_data*/)\n{\n    RYML_ASSERT(!csubstr(msg, length).ends_with('\\0'));\n    report_error_impl(msg, length, loc, nullptr);\n#ifdef RYML_DEFAULT_CALLBACK_USES_EXCEPTIONS\n    throw std::runtime_error(std::string(msg, length));\n#else\n    ::abort();\n#endif\n}\n\nvoid* allocate_impl(size_t length, void * /*hint*/, void * /*user_data*/)\n{\n    void *mem = ::malloc(length);\n    if(mem == nullptr)\n    {\n        const char msg[] = \"could not allocate memory\";\n        error_impl(msg, sizeof(msg)-1, {}, nullptr);\n    }\n    return mem;\n}\n\nvoid free_impl(void *mem, size_t /*length*/, void * /*user_data*/)\n{\n    ::free(mem);\n}\n#endif // RYML_NO_DEFAULT_CALLBACKS\n\n\n\nCallbacks::Callbacks()\n    :\n    m_user_data(nullptr),\n    #ifndef RYML_NO_DEFAULT_CALLBACKS\n    m_allocate(allocate_impl),\n    m_free(free_impl),\n    m_error(error_impl)\n    #else\n    m_allocate(nullptr),\n    m_free(nullptr),\n    m_error(nullptr)\n    #endif\n{\n}\n\nCallbacks::Callbacks(void *user_data, pfn_allocate alloc_, pfn_free free_, pfn_error error_)\n    :\n    m_user_data(user_data),\n    #ifndef RYML_NO_DEFAULT_CALLBACKS\n    m_allocate(alloc_ ? alloc_ : allocate_impl),\n    m_free(free_ ? free_ : free_impl),\n    m_error((error_ ? error_ : error_impl))\n    #else\n    m_allocate(alloc_),\n    m_free(free_),\n    m_error(error_)\n    #endif\n{\n    RYML_CHECK(m_allocate);\n    RYML_CHECK(m_free);\n    RYML_CHECK(m_error);\n}\n\n\nvoid set_callbacks(Callbacks const& c)\n{\n    s_default_callbacks = c;\n}\n\nCallbacks const& get_callbacks()\n{\n    return s_default_callbacks;\n}\n\nvoid reset_callbacks()\n{\n    set_callbacks(Callbacks());\n}\n\n// the [[noreturn]] attribute needs to be here as well (UB otherwise)\n// https://en.cppreference.com/w/cpp/language/attributes/noreturn\n[[noreturn]] void error(Callbacks const& cb, const char *msg, size_t msg_len, Location loc)\n{\n    cb.m_error(msg, msg_len, loc, cb.m_user_data);\n    abort(); // call abort in case the error callback didn't interrupt execution\n    C4_UNREACHABLE();\n}\n\n// the [[noreturn]] attribute needs to be here as well (UB otherwise)\n// see https://en.cppreference.com/w/cpp/language/attributes/noreturn\n[[noreturn]] void error(const char *msg, size_t msg_len, Location loc)\n{\n    error(s_default_callbacks, msg, msg_len, loc);\n    C4_UNREACHABLE();\n}\n\nC4_SUPPRESS_WARNING_MSVC_POP\nC4_SUPPRESS_WARNING_GCC_CLANG_POP\n\n} // namespace yml\n} // namespace c4\n"
  },
  {
    "path": "libs/rapidyaml/c4/yml/common.hpp",
    "content": "#ifndef _C4_YML_COMMON_HPP_\n#define _C4_YML_COMMON_HPP_\n\n/** @file common.hpp Common utilities and infrastructure used by ryml. */\n\n#include <cstddef>\n#include <c4/substr.hpp>\n#include <c4/dump.hpp>\n#include <c4/yml/export.hpp>\n\n#if defined(C4_MSVC) || defined(C4_MINGW)\n#include <malloc.h>\n#else\n#include <alloca.h>\n#endif\n\n\n\n//-----------------------------------------------------------------------------\n\n#ifndef RYML_ERRMSG_SIZE\n/// size for the error message buffer\n#define RYML_ERRMSG_SIZE (1024)\n#endif\n\n#ifndef RYML_LOGBUF_SIZE\n/// size for the buffer used to format individual values to string\n/// while preparing an error message. This is only used for formatting\n/// individual values in the message; final messages will be larger\n/// than this value (see @ref RYML_ERRMSG_SIZE). This is also used for\n/// the detailed debug log messages when RYML_DBG is defined.\n#define RYML_LOGBUF_SIZE (256)\n#endif\n\n#ifndef RYML_LOGBUF_SIZE_MAX\n/// size for the fallback larger log buffer. When @ref\n/// RYML_LOGBUF_SIZE is not large enough to convert a value to string,\n/// then temporary stack memory is allocated up to\n/// RYML_LOGBUF_SIZE_MAX. This limit is in place to prevent a stack\n/// overflow. If the printed value requires more than\n/// RYML_LOGBUF_SIZE_MAX, the value is silently skipped.\n#define RYML_LOGBUF_SIZE_MAX (1024)\n#endif\n\n#ifndef RYML_LOCATIONS_SMALL_THRESHOLD\n/// threshold at which a location search will revert from linear to\n/// binary search.\n#define RYML_LOCATIONS_SMALL_THRESHOLD (30)\n#endif\n\n\n//-----------------------------------------------------------------------------\n// Specify groups to have a predefined topic order in doxygen:\n\n/** @defgroup doc_quickstart Quickstart\n *\n * Example code for every feature.\n */\n\n/** @defgroup doc_parse Parse utilities\n * @see sample::sample_parse_in_place\n * @see sample::sample_parse_in_arena\n * @see sample::sample_parse_file\n * @see sample::sample_parse_reuse_tree\n * @see sample::sample_parse_reuse_parser\n * @see sample::sample_parse_reuse_tree_and_parser\n * @see sample::sample_location_tracking\n */\n\n/** @defgroup doc_emit Emit utilities\n *\n * Utilities to emit YAML and JSON, either to a memory buffer or to a\n * file or ostream-like class.\n *\n * @see sample::sample_emit_to_container\n * @see sample::sample_emit_to_stream\n * @see sample::sample_emit_to_file\n * @see sample::sample_emit_nested_node\n * @see sample::sample_emit_style\n */\n\n/** @defgroup doc_node_type Node types\n */\n\n/** @defgroup doc_tree Tree utilities\n * @see sample::sample_quick_overview\n * @see sample::sample_iterate_trees\n * @see sample::sample_create_trees\n * @see sample::sample_tree_arena\n *\n * @see sample::sample_static_trees\n * @see sample::sample_location_tracking\n *\n * @see sample::sample_docs\n * @see sample::sample_anchors_and_aliases\n * @see sample::sample_tags\n */\n\n/** @defgroup doc_node_classes Node classes\n *\n * High-level node classes.\n *\n * @see sample::sample_quick_overview\n * @see sample::sample_iterate_trees\n * @see sample::sample_create_trees\n * @see sample::sample_tree_arena\n */\n\n/** @defgroup doc_callbacks Callbacks for errors and allocation\n *\n * Functions called by ryml to allocate/free memory and to report\n * errors.\n *\n * @see sample::sample_error_handler\n * @see sample::sample_global_allocator\n * @see sample::sample_per_tree_allocator\n */\n\n/** @defgroup doc_serialization Serialization/deserialization\n *\n * Contains information on how to serialize and deserialize\n * fundamental types, user scalar types, user container types and\n * interop with std scalar/container types.\n *\n */\n\n/** @defgroup doc_ref_utils Anchor/Reference utilities\n *\n * @see sample::sample_anchors_and_aliases\n * */\n\n/** @defgroup doc_tag_utils Tag utilities\n * @see sample::sample_tags\n */\n\n/** @defgroup doc_preprocessors Preprocessors\n *\n * Functions for preprocessing YAML prior to parsing.\n */\n\n\n//-----------------------------------------------------------------------------\n\n// document macros for doxygen\n#ifdef __DOXYGEN__ // defined in Doxyfile::PREDEFINED\n\n/** define this macro with a boolean value to enable/disable\n * assertions to check preconditions and assumptions throughout the\n * codebase; this causes a slowdown of the code, and larger code\n * size. By default, this macro is defined unless NDEBUG is defined\n * (see C4_USE_ASSERT); as a result, by default this macro is truthy\n * only in debug builds. */\n#   define RYML_USE_ASSERT\n\n/** (Undefined by default) Define this macro to disable ryml's default\n * implementation of the callback functions; see @ref c4::yml::Callbacks  */\n#   define RYML_NO_DEFAULT_CALLBACKS\n\n/** (Undefined by default) When this macro is defined (and\n * @ref RYML_NO_DEFAULT_CALLBACKS is not defined), the default error\n * handler will throw C++ exceptions of type `std::runtime_error`. */\n#   define RYML_DEFAULT_CALLBACK_USES_EXCEPTIONS\n\n/** Conditionally expands to `noexcept` when @ref RYML_USE_ASSERT is 0 and\n * is empty otherwise. The user is unable to override this macro. */\n#   define RYML_NOEXCEPT\n\n#endif\n\n\n//-----------------------------------------------------------------------------\n\n\n/** @cond dev*/\n#ifndef RYML_USE_ASSERT\n#   define RYML_USE_ASSERT C4_USE_ASSERT\n#endif\n\n#if RYML_USE_ASSERT\n#   define RYML_ASSERT(cond) RYML_CHECK(cond)\n#   define RYML_ASSERT_MSG(cond, msg) RYML_CHECK_MSG(cond, msg)\n#   define _RYML_CB_ASSERT(cb, cond) _RYML_CB_CHECK((cb), (cond))\n#   define _RYML_CB_ASSERT_(cb, cond, loc) _RYML_CB_CHECK((cb), (cond), (loc))\n#   define RYML_NOEXCEPT\n#else\n#   define RYML_ASSERT(cond)\n#   define RYML_ASSERT_MSG(cond, msg)\n#   define _RYML_CB_ASSERT(cb, cond)\n#   define _RYML_CB_ASSERT_(cb, cond, loc)\n#   define RYML_NOEXCEPT noexcept\n#endif\n\n#define RYML_DEPRECATED(msg) C4_DEPRECATED(msg)\n\n#define RYML_CHECK(cond)                                                \\\n    do {                                                                \\\n        if(C4_UNLIKELY(!(cond)))                                        \\\n        {                                                               \\\n            RYML_DEBUG_BREAK();                                         \\\n            c4::yml::error(\"check failed: \" #cond, c4::yml::Location(__FILE__, __LINE__, 0)); \\\n            C4_UNREACHABLE_AFTER_ERR();                                 \\\n        }                                                               \\\n    } while(0)\n\n#define RYML_CHECK_MSG(cond, msg)                                       \\\n    do                                                                  \\\n    {                                                                   \\\n        if(C4_UNLIKELY(!(cond)))                                        \\\n        {                                                               \\\n            RYML_DEBUG_BREAK();                                         \\\n            c4::yml::error(msg \": check failed: \" #cond, c4::yml::Location(__FILE__, __LINE__, 0)); \\\n            C4_UNREACHABLE_AFTER_ERR();                                 \\\n        }                                                               \\\n    } while(0)\n\n#if defined(RYML_DBG) && !defined(NDEBUG) && !defined(C4_NO_DEBUG_BREAK)\n#   define RYML_DEBUG_BREAK()                               \\\n    do {                                                    \\\n        if(c4::get_error_flags() & c4::ON_ERROR_DEBUGBREAK) \\\n        {                                                   \\\n            C4_DEBUG_BREAK();                               \\\n        }                                                   \\\n    } while(0)\n#else\n#   define RYML_DEBUG_BREAK()\n#endif\n\n/** @endcond */\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\nnamespace c4 {\nnamespace yml {\n\nC4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH(\"-Wold-style-cast\")\n\n\n#ifndef RYML_ID_TYPE\n/** The type of a node id in the YAML tree. In the future, the default\n * will likely change to int32_t, which was observed to be faster.\n * @see id_type */\n#define RYML_ID_TYPE size_t\n#endif\n\n\n/** The type of a node id in the YAML tree; to override the default\n * type, define the macro @ref RYML_ID_TYPE to a suitable integer\n * type. */\nusing id_type = RYML_ID_TYPE;\nstatic_assert(std::is_integral<id_type>::value, \"id_type must be an integer type\");\n\n\nC4_SUPPRESS_WARNING_GCC_WITH_PUSH(\"-Wuseless-cast\")\nenum : id_type {\n    /** an index to none */\n    NONE = id_type(-1),\n};\nC4_SUPPRESS_WARNING_GCC_CLANG_POP\n\n\nenum : size_t {\n    /** a null string position */\n    npos = size_t(-1)\n};\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n//! holds a position into a source buffer\nstruct RYML_EXPORT LineCol\n{\n    //! number of bytes from the beginning of the source buffer\n    size_t offset;\n    //! line\n    size_t line;\n    //! column\n    size_t col;\n\n    LineCol() = default;\n    //! construct from line and column\n    LineCol(size_t l, size_t c) : offset(0), line(l), col(c) {}\n    //! construct from offset, line and column\n    LineCol(size_t o, size_t l, size_t c) : offset(o), line(l), col(c) {}\n};\nstatic_assert(std::is_trivial<LineCol>::value, \"LineCol not trivial\");\nstatic_assert(std::is_standard_layout<LineCol>::value, \"Location not trivial\");\n\n\n//! a source file position\nstruct RYML_EXPORT Location\n{\n    //! number of bytes from the beginning of the source buffer\n    size_t offset;\n    //! line\n    size_t line;\n    //! column\n    size_t col;\n    //! file name\n    csubstr name;\n\n    operator bool () const { return !name.empty() || line != 0 || offset != 0 || col != 0; }\n    operator LineCol const& () const { return reinterpret_cast<LineCol const&>(*this); }\n\n    Location() = default;\n    Location(                         size_t l, size_t c) : offset( ), line(l), col(c), name( ) {}\n    Location(               size_t b, size_t l, size_t c) : offset(b), line(l), col(c), name( ) {}\n    Location(    csubstr n,           size_t l, size_t c) : offset( ), line(l), col(c), name(n) {}\n    Location(    csubstr n, size_t b, size_t l, size_t c) : offset(b), line(l), col(c), name(n) {}\n    Location(const char *n,           size_t l, size_t c) : offset( ), line(l), col(c), name(to_csubstr(n)) {}\n    Location(const char *n, size_t b, size_t l, size_t c) : offset(b), line(l), col(c), name(to_csubstr(n)) {}\n};\nstatic_assert(std::is_standard_layout<Location>::value, \"Location not trivial\");\n\n\n//-----------------------------------------------------------------------------\n\n/** @addtogroup doc_callbacks\n *\n * @{ */\n\nstruct Callbacks;\n\n\n/** set the global callbacks for the library; after a call to this\n * function, these callbacks will be used by newly created objects\n * (unless they are copying older objects with different\n * callbacks). If @ref RYML_NO_DEFAULT_CALLBACKS is defined, it is\n * mandatory to call this function prior to using any other library\n * facility.\n *\n * @warning This function is NOT thread-safe.\n *\n * @warning the error callback must never return: see @ref pfn_error\n * for more details */\nRYML_EXPORT void set_callbacks(Callbacks const& c);\n\n/** get the global callbacks\n * @warning This function is not thread-safe. */\nRYML_EXPORT Callbacks const& get_callbacks();\n\n/** set the global callbacks back to their defaults ()\n * @warning This function is not thread-safe. */\nRYML_EXPORT void reset_callbacks();\n\n\n/** the type of the function used to report errors\n *\n * @warning When given by the user, this function MUST interrupt\n * execution, typically by either throwing an exception, or using\n * `std::longjmp()` ([see\n * documentation](https://en.cppreference.com/w/cpp/utility/program/setjmp))\n * or by calling `std::abort()`. If the function returned, the parser\n * would enter into an infinite loop, or the program may crash. */\nusing pfn_error = void (*) (const char* msg, size_t msg_len, Location location, void *user_data);\n\n\n/** the type of the function used to allocate memory; ryml will only\n * allocate memory through this callback. */\nusing pfn_allocate = void* (*)(size_t len, void* hint, void *user_data);\n\n\n/** the type of the function used to free memory; ryml will only free\n * memory through this callback. */\nusing pfn_free = void (*)(void* mem, size_t size, void *user_data);\n\n\n/** a c-style callbacks class. Can be used globally by the library\n * and/or locally by @ref Tree and @ref Parser objects. */\nstruct RYML_EXPORT Callbacks\n{\n    void *       m_user_data;\n    pfn_allocate m_allocate;\n    pfn_free     m_free;\n    pfn_error    m_error;\n\n    /** Construct an object with the default callbacks. If\n     * @ref RYML_NO_DEFAULT_CALLBACKS is defined, the object will have null\n     * members.*/\n    Callbacks();\n\n    /** Construct an object with the given callbacks.\n     *\n     * @param user_data Data to be forwarded in every call to a callback.\n     *\n     * @param alloc A pointer to an allocate function. Unless\n     *        @ref RYML_NO_DEFAULT_CALLBACKS is defined, when this\n     *        parameter is null, will fall back to ryml's default\n     *        alloc implementation.\n     *\n     * @param free A pointer to a free function. Unless\n     *        @ref RYML_NO_DEFAULT_CALLBACKS is defined, when this\n     *        parameter is null, will fall back to ryml's default free\n     *        implementation.\n     *\n     * @param error A pointer to an error function, which must never\n     *        return (see @ref pfn_error). Unless\n     *        @ref RYML_NO_DEFAULT_CALLBACKS is defined, when this\n     *        parameter is null, will fall back to ryml's default\n     *        error implementation.\n     */\n    Callbacks(void *user_data, pfn_allocate alloc, pfn_free free, pfn_error error);\n\n    bool operator!= (Callbacks const& that) const { return !operator==(that); }\n    bool operator== (Callbacks const& that) const\n    {\n        return (m_user_data == that.m_user_data &&\n                m_allocate == that.m_allocate &&\n                m_free == that.m_free &&\n                m_error == that.m_error);\n    }\n};\n\n\n/** @} */\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n/// @cond dev\n\n// BEWARE! MSVC requires that [[noreturn]] appears before RYML_EXPORT\n[[noreturn]] RYML_EXPORT void error(Callbacks const& cb, const char *msg, size_t msg_len, Location loc);\n[[noreturn]] RYML_EXPORT void error(const char *msg, size_t msg_len, Location loc);\n\n[[noreturn]] inline void error(const char *msg, size_t msg_len)\n{\n    error(msg, msg_len, Location{});\n}\ntemplate<size_t N>\n[[noreturn]] inline void error(const char (&msg)[N], Location loc)\n{\n    error(msg, N-1, loc);\n}\ntemplate<size_t N>\n[[noreturn]] inline void error(const char (&msg)[N])\n{\n    error(msg, N-1, Location{});\n}\n\n#define _RYML_CB_ERR(cb, msg_literal)                                   \\\n    _RYML_CB_ERR_(cb, msg_literal, c4::yml::Location(__FILE__, 0, __LINE__, 0))\n#define _RYML_CB_CHECK(cb, cond)                                        \\\n    _RYML_CB_CHECK_(cb, cond, c4::yml::Location(__FILE__, 0, __LINE__, 0))\n#define _RYML_CB_ERR_(cb, msg_literal, loc)                             \\\ndo                                                                      \\\n{                                                                       \\\n    const char msg[] = msg_literal;                                     \\\n    RYML_DEBUG_BREAK();                                                 \\\n    c4::yml::error((cb), msg, sizeof(msg)-1, loc);                      \\\n    C4_UNREACHABLE_AFTER_ERR();                                         \\\n} while(0)\n#define _RYML_CB_CHECK_(cb, cond, loc)                                  \\\n    do                                                                  \\\n    {                                                                   \\\n        if(C4_UNLIKELY(!(cond)))                                        \\\n        {                                                               \\\n            const char msg[] = \"check failed: \" #cond;                  \\\n            RYML_DEBUG_BREAK();                                         \\\n            c4::yml::error((cb), msg, sizeof(msg)-1, loc);              \\\n            C4_UNREACHABLE_AFTER_ERR();                                 \\\n        }                                                               \\\n    } while(0)\n#define _RYML_CB_ALLOC_HINT(cb, T, num, hint) (T*) (cb).m_allocate((num) * sizeof(T), (hint), (cb).m_user_data)\n#define _RYML_CB_ALLOC(cb, T, num) _RYML_CB_ALLOC_HINT((cb), T, (num), nullptr)\n#define _RYML_CB_FREE(cb, buf, T, num)                              \\\n    do {                                                            \\\n        (cb).m_free((buf), (num) * sizeof(T), (cb).m_user_data);    \\\n        (buf) = nullptr;                                            \\\n    } while(0)\n\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\ntypedef enum {\n    BLOCK_LITERAL, //!< keep newlines (|)\n    BLOCK_FOLD     //!< replace newline with single space (>)\n} BlockStyle_e;\n\ntypedef enum {\n    CHOMP_CLIP,    //!< single newline at end (default)\n    CHOMP_STRIP,   //!< no newline at end     (-)\n    CHOMP_KEEP     //!< all newlines from end (+)\n} BlockChomp_e;\n\n\n/** Abstracts the fact that a scalar filter result may not fit in the\n * intended memory. */\nstruct FilterResult\n{\n    C4_ALWAYS_INLINE bool valid() const noexcept { return str.str != nullptr; }\n    C4_ALWAYS_INLINE size_t required_len() const noexcept { return str.len; }\n    C4_ALWAYS_INLINE csubstr get() { RYML_ASSERT(valid()); return str; }\n    csubstr str;\n};\n/** Abstracts the fact that a scalar filter result may not fit in the\n * intended memory. */\nstruct FilterResultExtending\n{\n    C4_ALWAYS_INLINE bool valid() const noexcept { return str.str != nullptr; }\n    C4_ALWAYS_INLINE size_t required_len() const noexcept { return reqlen; }\n    C4_ALWAYS_INLINE csubstr get() { RYML_ASSERT(valid()); return str; }\n    csubstr str;\n    size_t reqlen;\n};\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n\nnamespace detail {\n// is there a better way to do this?\ntemplate<int8_t signedval, uint8_t unsignedval>\nstruct _charconstant_t\n    : public std::conditional<std::is_signed<char>::value,\n                              std::integral_constant<int8_t, signedval>,\n                              std::integral_constant<uint8_t, unsignedval>>::type\n{};\n#define _RYML_CHCONST(signedval, unsignedval) ::c4::yml::detail::_charconstant_t<INT8_C(signedval), UINT8_C(unsignedval)>::value\n} // namespace detail\n\n\nnamespace detail {\nstruct _SubstrWriter\n{\n    substr buf;\n    size_t pos;\n    _SubstrWriter(substr buf_, size_t pos_=0) : buf(buf_), pos(pos_) { C4_ASSERT(buf.str); }\n    void append(csubstr s)\n    {\n        C4_ASSERT(!s.overlaps(buf));\n        C4_ASSERT(s.str || !s.len);\n        if(s.len && pos + s.len <= buf.len)\n        {\n            C4_ASSERT(s.str);\n            memcpy(buf.str + pos, s.str, s.len);\n        }\n        pos += s.len;\n    }\n    void append(char c)\n    {\n        C4_ASSERT(buf.str);\n        if(pos < buf.len)\n            buf.str[pos] = c;\n        ++pos;\n    }\n    void append_n(char c, size_t numtimes)\n    {\n        C4_ASSERT(buf.str);\n        if(numtimes && pos + numtimes < buf.len)\n            memset(buf.str + pos, c, numtimes);\n        pos += numtimes;\n    }\n    size_t slack() const { return pos <= buf.len ? buf.len - pos : 0; }\n    size_t excess() const { return pos > buf.len ? pos - buf.len : 0; }\n    //! get the part written so far\n    csubstr curr() const { return pos <= buf.len ? buf.first(pos) : buf; }\n    //! get the part that is still free to write to (the remainder)\n    substr rem() { return pos < buf.len ? buf.sub(pos) : buf.last(0); }\n\n    size_t advance(size_t more) { pos += more; return pos; }\n};\n} // namespace detail\n\n\nnamespace detail {\n// dumpfn is a function abstracting prints to terminal (or to string).\ntemplate<class DumpFn, class ...Args>\nC4_NO_INLINE void _dump(DumpFn &&dumpfn, csubstr fmt, Args&& ...args)\n{\n    DumpResults results;\n    // try writing everything:\n    {\n        // buffer for converting individual arguments. it is defined\n        // in a child scope to free it in case the buffer is too small\n        // for any of the arguments.\n        char writebuf[RYML_LOGBUF_SIZE];\n        results = format_dump_resume(std::forward<DumpFn>(dumpfn), writebuf, fmt, std::forward<Args>(args)...);\n    }\n    // if any of the arguments failed to fit the buffer, allocate a\n    // larger buffer (up to a limit) and resume writing.\n    //\n    // results.bufsize is set to the size of the largest element\n    // serialized. Eg int(1) will require 1 byte.\n    if(C4_UNLIKELY(results.bufsize > RYML_LOGBUF_SIZE))\n    {\n        const size_t bufsize = results.bufsize <= RYML_LOGBUF_SIZE_MAX ? results.bufsize : RYML_LOGBUF_SIZE_MAX;\n        #ifdef C4_MSVC\n        substr largerbuf = {static_cast<char*>(_alloca(bufsize)), bufsize};\n        #else\n        substr largerbuf = {static_cast<char*>(alloca(bufsize)), bufsize};\n        #endif\n        results = format_dump_resume(std::forward<DumpFn>(dumpfn), results, largerbuf, fmt, std::forward<Args>(args)...);\n    }\n}\ntemplate<class ...Args>\nC4_NORETURN C4_NO_INLINE void _report_err(Callbacks const& C4_RESTRICT callbacks, csubstr fmt, Args const& C4_RESTRICT ...args)\n{\n    char errmsg[RYML_ERRMSG_SIZE] = {0};\n    detail::_SubstrWriter writer(errmsg);\n    auto dumpfn = [&writer](csubstr s){ writer.append(s); };\n    _dump(dumpfn, fmt, args...);\n    writer.append('\\n');\n    const size_t len = writer.pos < RYML_ERRMSG_SIZE ? writer.pos : RYML_ERRMSG_SIZE;\n    callbacks.m_error(errmsg, len, {}, callbacks.m_user_data);\n    C4_UNREACHABLE_AFTER_ERR();\n}\n} // namespace detail\n\n\ninline csubstr _c4prc(const char &C4_RESTRICT c) // pass by reference!\n{\n    switch(c)\n    {\n    case '\\n': return csubstr(\"\\\\n\");\n    case '\\t': return csubstr(\"\\\\t\");\n    case '\\0': return csubstr(\"\\\\0\");\n    case '\\r': return csubstr(\"\\\\r\");\n    case '\\f': return csubstr(\"\\\\f\");\n    case '\\b': return csubstr(\"\\\\b\");\n    case '\\v': return csubstr(\"\\\\v\");\n    case '\\a': return csubstr(\"\\\\a\");\n    default: return csubstr(&c, 1);\n    }\n}\n\n/// @endcond\n\nC4_SUPPRESS_WARNING_GCC_POP\n\n} // namespace yml\n} // namespace c4\n\n#endif /* _C4_YML_COMMON_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/yml/detail/checks.hpp",
    "content": "#ifndef C4_YML_DETAIL_CHECKS_HPP_\n#define C4_YML_DETAIL_CHECKS_HPP_\n\n#include \"c4/yml/tree.hpp\"\n\n#ifdef __clang__\n#   pragma clang diagnostic push\n#elif defined(__GNUC__)\n#   pragma GCC diagnostic push\n#   pragma GCC diagnostic ignored \"-Wtype-limits\" // error: comparison of unsigned expression >= 0 is always true\n#elif defined(_MSC_VER)\n#   pragma warning(push)\n#   pragma warning(disable: 4296/*expression is always 'boolean_value'*/)\n#endif\n\nnamespace c4 {\nnamespace yml {\n\n\nvoid check_invariants(Tree const& t, id_type node=NONE);\nvoid check_free_list(Tree const& t);\nvoid check_arena(Tree const& t);\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\ninline void check_invariants(Tree const& t, id_type node)\n{\n    if(node == NONE)\n    {\n        if(t.size() == 0) return;\n        node = t.root_id();\n    }\n\n    NodeData const& n = *t._p(node);\n#if defined(RYML_DBG) && 0\n    if(n.m_first_child != NONE || n.m_last_child != NONE)\n    {\n        printf(\"check(%zu): fc=%zu lc=%zu\\n\", node, n.m_first_child, n.m_last_child);\n    }\n    else\n    {\n        printf(\"check(%zu)\\n\", node);\n    }\n#endif\n\n    C4_CHECK(n.m_parent != node);\n    if(n.m_parent == NONE)\n    {\n        C4_CHECK(t.is_root(node));\n    }\n    else //if(n.m_parent != NONE)\n    {\n        C4_CHECK(t.has_child(n.m_parent, node));\n\n        auto const& p = *t._p(n.m_parent);\n        if(n.m_prev_sibling == NONE)\n        {\n            C4_CHECK(p.m_first_child == node);\n            C4_CHECK(t.first_sibling(node) == node);\n        }\n        else\n        {\n            C4_CHECK(p.m_first_child != node);\n            C4_CHECK(t.first_sibling(node) != node);\n        }\n\n        if(n.m_next_sibling == NONE)\n        {\n            C4_CHECK(p.m_last_child == node);\n            C4_CHECK(t.last_sibling(node) == node);\n        }\n        else\n        {\n            C4_CHECK(p.m_last_child != node);\n            C4_CHECK(t.last_sibling(node) != node);\n        }\n    }\n\n    C4_CHECK(n.m_first_child != node);\n    C4_CHECK(n.m_last_child != node);\n    if(n.m_first_child != NONE || n.m_last_child != NONE)\n    {\n        C4_CHECK(n.m_first_child != NONE);\n        C4_CHECK(n.m_last_child != NONE);\n    }\n\n    C4_CHECK(n.m_prev_sibling != node);\n    C4_CHECK(n.m_next_sibling != node);\n    if(n.m_prev_sibling != NONE)\n    {\n        C4_CHECK(t._p(n.m_prev_sibling)->m_next_sibling == node);\n        C4_CHECK(t._p(n.m_prev_sibling)->m_prev_sibling != node);\n    }\n    if(n.m_next_sibling != NONE)\n    {\n        C4_CHECK(t._p(n.m_next_sibling)->m_prev_sibling == node);\n        C4_CHECK(t._p(n.m_next_sibling)->m_next_sibling != node);\n    }\n\n    id_type count = 0;\n    for(id_type i = n.m_first_child; i != NONE; i = t.next_sibling(i))\n    {\n#if defined(RYML_DBG) && 0\n        printf(\"check(%zu):               descend to child[%zu]=%zu\\n\", node, count, i);\n#endif\n        auto const& ch = *t._p(i);\n        C4_CHECK(ch.m_parent == node);\n        C4_CHECK(ch.m_next_sibling != i);\n        ++count;\n    }\n    C4_CHECK(count == t.num_children(node));\n\n    if(n.m_prev_sibling == NONE && n.m_next_sibling == NONE)\n    {\n        if(n.m_parent != NONE)\n        {\n            C4_CHECK(t.num_children(n.m_parent) == 1);\n            C4_CHECK(t.num_siblings(node) == 1);\n        }\n    }\n\n    if(node == t.root_id())\n    {\n        C4_CHECK(t.size() == t.m_size);\n        C4_CHECK(t.capacity() == t.m_cap);\n        C4_CHECK(t.m_cap == t.m_size + t.slack());\n        check_free_list(t);\n        check_arena(t);\n    }\n\n    for(id_type i = t.first_child(node); i != NONE; i = t.next_sibling(i))\n    {\n        check_invariants(t, i);\n    }\n}\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\ninline void check_free_list(Tree const& t)\n{\n    if(t.m_free_head == NONE)\n    {\n        C4_CHECK(t.m_free_tail == t.m_free_head);\n        return;\n    }\n\n    C4_CHECK(t.m_free_head >= 0 && t.m_free_head < t.m_cap);\n    C4_CHECK(t.m_free_tail >= 0 && t.m_free_tail < t.m_cap);\n\n    auto const& head = *t._p(t.m_free_head);\n    //auto const& tail = *t._p(t.m_free_tail);\n\n    //C4_CHECK(head.m_prev_sibling == NONE);\n    //C4_CHECK(tail.m_next_sibling == NONE);\n\n    id_type count = 0;\n    for(id_type i = t.m_free_head, prev = NONE; i != NONE; i = t._p(i)->m_next_sibling)\n    {\n        auto const& elm = *t._p(i);\n        if(&elm != &head)\n        {\n            C4_CHECK(elm.m_prev_sibling == prev);\n        }\n        prev = i;\n        ++count;\n    }\n    C4_CHECK(count == t.slack());\n}\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\ninline void check_arena(Tree const& t)\n{\n    C4_CHECK(t.m_arena.len == 0 || (t.m_arena_pos >= 0 && t.m_arena_pos <= t.m_arena.len));\n    C4_CHECK(t.arena_size() == t.m_arena_pos);\n    C4_CHECK(t.arena_slack() + t.m_arena_pos == t.m_arena.len);\n}\n\n\n} /* namespace yml */\n} /* namespace c4 */\n\n#ifdef __clang__\n#   pragma clang diagnostic pop\n#elif defined(__GNUC__)\n#   pragma GCC diagnostic pop\n#elif defined(_MSC_VER)\n#   pragma warning(pop)\n#endif\n\n#endif /* C4_YML_DETAIL_CHECKS_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/yml/detail/parser_dbg.hpp",
    "content": "#ifndef _C4_YML_DETAIL_PARSER_DBG_HPP_\n#define _C4_YML_DETAIL_PARSER_DBG_HPP_\n\n#ifndef _C4_YML_COMMON_HPP_\n#include \"../common.hpp\"\n#endif\n\n#ifdef RYML_DBG\n#include <cstdio>\n#endif\n\n\n//-----------------------------------------------------------------------------\n// some debugging scaffolds\n\n#if defined(_MSC_VER)\n#   pragma warning(push)\n#   pragma warning(disable: 4068/*unknown pragma*/)\n#endif\n\n#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Wunknown-pragmas\"\n//#pragma GCC diagnostic ignored \"-Wpragma-system-header-outside-header\"\n#pragma GCC system_header\n\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Werror\"\n#pragma clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"\n\n\n#ifndef RYML_DBG\n#   define _c4err(fmt, ...)   \\\n    this->_err(\"ERROR: \" fmt, ## __VA_ARGS__)\n#   define _c4dbgt(fmt, ...)\n#   define _c4dbgpf(fmt, ...)\n#   define _c4dbgpf_(fmt, ...)\n#   define _c4dbgp(msg)\n#   define _c4dbgp_(msg)\n#   define _c4dbgq(msg)\n#   define _c4presc(...)\n#   define _c4prscalar(msg, scalar, keep_newlines)\n#else\n#   define _c4err(fmt, ...)   \\\n    do { RYML_DEBUG_BREAK(); this->_err(\"ERROR:\\n\" \"{}:{}: \" fmt, __FILE__, __LINE__, ## __VA_ARGS__); } while(0)\n#   define _c4dbgt(fmt, ...)   do { if(_dbg_enabled()) {                \\\n                               this->_dbg (\"{}:{}: \"   fmt     , __FILE__, __LINE__, ## __VA_ARGS__); } } while(0)\n#   define _c4dbgpf(fmt, ...)  _dbg_printf(\"{}:{}: \"   fmt \"\\n\", __FILE__, __LINE__, ## __VA_ARGS__)\n#   define _c4dbgpf_(fmt, ...) _dbg_printf(\"{}:{}: \"   fmt     , __FILE__, __LINE__, ## __VA_ARGS__)\n#   define _c4dbgp(msg)        _dbg_printf(\"{}:{}: \"   msg \"\\n\", __FILE__, __LINE__                )\n#   define _c4dbgp_(msg)       _dbg_printf(\"{}:{}: \"   msg     , __FILE__, __LINE__                )\n#   define _c4dbgq(msg)        _dbg_printf(msg \"\\n\")\n#   define _c4presc(...)       do { if(_dbg_enabled()) __c4presc(__VA_ARGS__); } while(0)\n#   define _c4prscalar(msg, scalar, keep_newlines)                  \\\n    do {                                                            \\\n        _c4dbgpf_(\"{}: [{}]~~~\", msg, scalar.len);                  \\\n        if(_dbg_enabled()) {                                        \\\n            __c4presc((scalar).str, (scalar).len, (keep_newlines)); \\\n        }                                                           \\\n        _c4dbgq(\"~~~\");                                             \\\n    } while(0)\n#endif // RYML_DBG\n\n\n//-----------------------------------------------------------------------------\n\n#ifdef RYML_DBG\n\n#include <c4/dump.hpp>\nnamespace c4 {\ninline bool& _dbg_enabled() { static bool enabled = true; return enabled; }\ninline void _dbg_set_enabled(bool yes) { _dbg_enabled() = yes; }\ninline void _dbg_dumper(csubstr s)\n{\n    if(s.str)\n        fwrite(s.str, 1, s.len, stdout);\n}\ninline substr _dbg_buf() noexcept\n{\n    static char writebuf[2048];\n    return writebuf;\n}\ntemplate<class ...Args>\nC4_NO_INLINE void _dbg_printf(c4::csubstr fmt, Args const& ...args)\n{\n    if(_dbg_enabled())\n    {\n        substr buf = _dbg_buf();\n        const size_t needed_size = c4::format_dump(&_dbg_dumper, buf, fmt, args...);\n        C4_CHECK(needed_size <= buf.len);\n    }\n}\ninline void __c4presc(const char *s, size_t len, bool keep_newlines=false)\n{\n    RYML_ASSERT(s || !len);\n    size_t prev = 0;\n    for(size_t i = 0; i < len; ++i)\n    {\n        switch(s[i])\n        {\n        case '\\n'  : _dbg_printf(\"{}{}{}\", csubstr(s+prev, i-prev), csubstr(\"\\\\n\"), csubstr(keep_newlines ? \"\\n\":\"\")); prev = i+1; break;\n        case '\\t'  : _dbg_printf(\"{}{}\", csubstr(s+prev, i-prev), csubstr(\"\\\\t\")); prev = i+1; break;\n        case '\\0'  : _dbg_printf(\"{}{}\", csubstr(s+prev, i-prev), csubstr(\"\\\\0\")); prev = i+1; break;\n        case '\\r'  : _dbg_printf(\"{}{}\", csubstr(s+prev, i-prev), csubstr(\"\\\\r\")); prev = i+1; break;\n        case '\\f'  : _dbg_printf(\"{}{}\", csubstr(s+prev, i-prev), csubstr(\"\\\\f\")); prev = i+1; break;\n        case '\\b'  : _dbg_printf(\"{}{}\", csubstr(s+prev, i-prev), csubstr(\"\\\\b\")); prev = i+1; break;\n        case '\\v'  : _dbg_printf(\"{}{}\", csubstr(s+prev, i-prev), csubstr(\"\\\\v\")); prev = i+1; break;\n        case '\\a'  : _dbg_printf(\"{}{}\", csubstr(s+prev, i-prev), csubstr(\"\\\\a\")); prev = i+1; break;\n        case '\\x1b': _dbg_printf(\"{}{}\", csubstr(s+prev, i-prev), csubstr(\"\\\\x1b\")); prev = i+1; break;\n        case -0x3e/*0xc2u*/:\n            if(i+1 < len)\n            {\n                if(s[i+1] == -0x60/*0xa0u*/)\n                {\n                    _dbg_printf(\"{}{}\", csubstr(s+prev, i-prev), csubstr(\"\\\\_\")); prev = i+1;\n                }\n                else if(s[i+1] == -0x7b/*0x85u*/)\n                {\n                    _dbg_printf(\"{}{}\", csubstr(s+prev, i-prev), csubstr(\"\\\\N\")); prev = i+1;\n                }\n            }\n            break;\n        case -0x1e/*0xe2u*/:\n            if(i+2 < len && s[i+1] == -0x80/*0x80u*/)\n            {\n                if(s[i+2] == -0x58/*0xa8u*/)\n                {\n                    _dbg_printf(\"{}{}\", csubstr(s+prev, i-prev), csubstr(\"\\\\L\")); prev = i+1;\n                }\n                else if(s[i+2] == -0x57/*0xa9u*/)\n                {\n                    _dbg_printf(\"{}{}\", csubstr(s+prev, i-prev), csubstr(\"\\\\P\")); prev = i+1;\n                }\n            }\n            break;\n        }\n    }\n    if(len > prev)\n        _dbg_printf(\"{}\", csubstr(s+prev, len-prev));\n}\ninline void __c4presc(csubstr s, bool keep_newlines=false)\n{\n    __c4presc(s.str, s.len, keep_newlines);\n}\n} // namespace c4\n\n#endif // RYML_DBG\n\n#pragma clang diagnostic pop\n#pragma GCC diagnostic pop\n\n#if defined(_MSC_VER)\n#   pragma warning(pop)\n#endif\n\n#endif /* _C4_YML_DETAIL_PARSER_DBG_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/yml/detail/print.hpp",
    "content": "#ifndef C4_YML_DETAIL_PRINT_HPP_\n#define C4_YML_DETAIL_PRINT_HPP_\n\n#include \"c4/yml/tree.hpp\"\n#include \"c4/yml/node.hpp\"\n\n#ifdef RYML_DBG\n#define _c4dbg_tree(...) print_tree(__VA_ARGS__)\n#define _c4dbg_node(...) print_tree(__VA_ARGS__)\n#else\n#define _c4dbg_tree(...)\n#define _c4dbg_node(...)\n#endif\n\nnamespace c4 {\nnamespace yml {\n\nC4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH(\"-Wold-style-cast\")\nC4_SUPPRESS_WARNING_GCC(\"-Wuseless-cast\")\n\ninline const char* _container_style_code(Tree const& p, id_type node)\n{\n    if(p.is_container(node))\n    {\n        if(p._p(node)->m_type & (FLOW_SL|FLOW_ML))\n        {\n            return \"[FLOW]\";\n        }\n        if(p._p(node)->m_type & (BLOCK))\n        {\n            return \"[BLCK]\";\n        }\n    }\n    return \"\";\n}\ninline char _scalar_code(NodeType masked)\n{\n    if(masked & (KEY_LITERAL|VAL_LITERAL))\n        return '|';\n    if(masked & (KEY_FOLDED|VAL_FOLDED))\n        return '>';\n    if(masked & (KEY_SQUO|VAL_SQUO))\n        return '\\'';\n    if(masked & (KEY_DQUO|VAL_DQUO))\n        return '\"';\n    if(masked & (KEY_PLAIN|VAL_PLAIN))\n        return '~';\n    return '@';\n}\ninline char _scalar_code_key(NodeType t)\n{\n    return _scalar_code(t & KEY_STYLE);\n}\ninline char _scalar_code_val(NodeType t)\n{\n    return _scalar_code(t & VAL_STYLE);\n}\ninline char _scalar_code_key(Tree const& p, id_type node)\n{\n    return _scalar_code_key(p._p(node)->m_type);\n}\ninline char _scalar_code_val(Tree const& p, id_type node)\n{\n    return _scalar_code_key(p._p(node)->m_type);\n}\ninline id_type print_node(Tree const& p, id_type node, int level, id_type count, bool print_children)\n{\n    printf(\"[%zu]%*s[%zu] %p\", (size_t)count, (2*level), \"\", (size_t)node, (void const*)p.get(node));\n    if(p.is_root(node))\n    {\n        printf(\" [ROOT]\");\n    }\n    char typebuf[128];\n    csubstr typestr = p.type(node).type_str(typebuf);\n    RYML_CHECK(typestr.str);\n    printf(\" %.*s\", (int)typestr.len, typestr.str);\n    if(p.has_key(node))\n    {\n        if(p.has_key_anchor(node))\n        {\n            csubstr ka = p.key_anchor(node);\n            printf(\" &%.*s\", (int)ka.len, ka.str);\n        }\n        if(p.has_key_tag(node))\n        {\n            csubstr kt = p.key_tag(node);\n            printf(\" <%.*s>\", (int)kt.len, kt.str);\n        }\n        const char code = _scalar_code_key(p, node);\n        csubstr k  = p.key(node);\n        printf(\" %c%.*s%c :\", code, (int)k.len, k.str, code);\n    }\n    if(p.has_val_anchor(node))\n    {\n        csubstr a = p.val_anchor(node);\n        printf(\" &%.*s'\", (int)a.len, a.str);\n    }\n    if(p.has_val_tag(node))\n    {\n        csubstr vt = p.val_tag(node);\n        printf(\" <%.*s>\", (int)vt.len, vt.str);\n    }\n    if(p.has_val(node))\n    {\n        const char code = _scalar_code_val(p, node);\n        csubstr v  = p.val(node);\n        printf(\" %c%.*s%c\", code, (int)v.len, v.str, code);\n    }\n    printf(\"  (%zu sibs)\", (size_t)p.num_siblings(node));\n\n    ++count;\n\n    if(!p.is_container(node))\n    {\n        printf(\"\\n\");\n    }\n    else\n    {\n        printf(\" (%zu children)\\n\", (size_t)p.num_children(node));\n        if(print_children)\n        {\n            for(id_type i = p.first_child(node); i != NONE; i = p.next_sibling(i))\n            {\n                count = print_node(p, i, level+1, count, print_children);\n            }\n        }\n    }\n\n    return count;\n}\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\ninline void print_node(ConstNodeRef const& p, int level=0)\n{\n    print_node(*p.tree(), p.id(), level, 0, true);\n}\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\ninline id_type print_tree(const char *message, Tree const& p, id_type node=NONE)\n{\n    printf(\"--------------------------------------\\n\");\n    if(message != nullptr)\n        printf(\"%s:\\n\", message);\n    id_type ret = 0;\n    if(!p.empty())\n    {\n        if(node == NONE)\n            node = p.root_id();\n        ret = print_node(p, node, 0, 0, true);\n    }\n    printf(\"#nodes=%zu vs #printed=%zu\\n\", (size_t)p.size(), (size_t)ret);\n    printf(\"--------------------------------------\\n\");\n    return ret;\n}\n\ninline id_type print_tree(Tree const& p, id_type node=NONE)\n{\n    return print_tree(nullptr, p, node);\n}\n\ninline void print_tree(ConstNodeRef const& p, int level)\n{\n    print_node(p, level);\n    for(ConstNodeRef ch : p.children())\n    {\n        print_tree(ch, level+1);\n    }\n}\n\nC4_SUPPRESS_WARNING_GCC_CLANG_POP\n\n} /* namespace yml */\n} /* namespace c4 */\n\n\n#endif /* C4_YML_DETAIL_PRINT_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/yml/detail/stack.hpp",
    "content": "#ifndef _C4_YML_DETAIL_STACK_HPP_\n#define _C4_YML_DETAIL_STACK_HPP_\n\n#ifndef _C4_YML_COMMON_HPP_\n#include \"../common.hpp\"\n#endif\n\n#ifdef RYML_DBG\n#   include <type_traits>\n#endif\n\n#include <string.h>\n\nnamespace c4 {\nnamespace yml {\n\nC4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH(\"-Wold-style-cast\")\n\nnamespace detail {\n\n/** A lightweight contiguous stack with Small Storage\n * Optimization. This is required because std::vector can throw\n * exceptions, and we don't want to enforce any particular error\n * mechanism. */\ntemplate<class T, id_type N=16>\nclass stack\n{\n    static_assert(std::is_trivially_copyable<T>::value, \"T must be trivially copyable\");\n    static_assert(std::is_trivially_destructible<T>::value, \"T must be trivially destructible\");\n\npublic:\n\n    enum : id_type { sso_size = N };\n\npublic:\n\n    T              m_buf[size_t(N)];\n    T *C4_RESTRICT m_stack;\n    id_type        m_size;\n    id_type        m_capacity;\n    Callbacks      m_callbacks;\n\npublic:\n\n    constexpr static bool is_contiguous() { return true; }\n\n    stack(Callbacks const& cb)\n        : m_buf()\n        , m_stack(m_buf)\n        , m_size(0)\n        , m_capacity(N)\n        , m_callbacks(cb) {}\n    stack() : stack(get_callbacks()) {}\n    ~stack()\n    {\n        _free();\n    }\n\n    stack(stack const& that) RYML_NOEXCEPT : stack(that.m_callbacks)\n    {\n        resize(that.m_size);\n        _cp(&that);\n    }\n\n    stack(stack &&that) noexcept : stack(that.m_callbacks)\n    {\n        _mv(&that);\n    }\n\n    stack& operator= (stack const& that) RYML_NOEXCEPT\n    {\n        _cb(that.m_callbacks);\n        resize(that.m_size);\n        _cp(&that);\n        return *this;\n    }\n\n    stack& operator= (stack &&that) noexcept\n    {\n        _cb(that.m_callbacks);\n        _mv(&that);\n        return *this;\n    }\n\npublic:\n\n    id_type size() const { return m_size; }\n    id_type empty() const { return m_size == 0; }\n    id_type capacity() const { return m_capacity; }\n\n    void clear()\n    {\n        m_size = 0;\n    }\n\n    void resize(id_type sz)\n    {\n        reserve(sz);\n        m_size = sz;\n    }\n\n    void reserve(id_type sz);\n\n    void push(T const& C4_RESTRICT n)\n    {\n        _RYML_CB_ASSERT(m_callbacks, (const char*)&n + sizeof(T) < (const char*)m_stack || &n > m_stack + m_capacity);\n        if(m_size == m_capacity)\n        {\n            id_type cap = m_capacity == 0 ? N : 2 * m_capacity;\n            reserve(cap);\n        }\n        m_stack[m_size] = n;\n        ++m_size;\n    }\n\n    void push_top()\n    {\n        _RYML_CB_ASSERT(m_callbacks, m_size > 0);\n        if(m_size == m_capacity)\n        {\n            id_type cap = m_capacity == 0 ? N : 2 * m_capacity;\n            reserve(cap);\n        }\n        m_stack[m_size] = m_stack[m_size - 1];\n        ++m_size;\n    }\n\n    T const& C4_RESTRICT pop()\n    {\n        _RYML_CB_ASSERT(m_callbacks, m_size > 0);\n        --m_size;\n        return m_stack[m_size];\n    }\n\n    C4_ALWAYS_INLINE T const& C4_RESTRICT top() const { _RYML_CB_ASSERT(m_callbacks, m_size > 0); return m_stack[m_size - 1]; }\n    C4_ALWAYS_INLINE T      & C4_RESTRICT top()       { _RYML_CB_ASSERT(m_callbacks, m_size > 0); return m_stack[m_size - 1]; }\n\n    C4_ALWAYS_INLINE T const& C4_RESTRICT bottom() const { _RYML_CB_ASSERT(m_callbacks, m_size > 0); return m_stack[0]; }\n    C4_ALWAYS_INLINE T      & C4_RESTRICT bottom()       { _RYML_CB_ASSERT(m_callbacks, m_size > 0); return m_stack[0]; }\n\n    C4_ALWAYS_INLINE T const& C4_RESTRICT top(id_type i) const { _RYML_CB_ASSERT(m_callbacks, i < m_size); return m_stack[m_size - 1 - i]; }\n    C4_ALWAYS_INLINE T      & C4_RESTRICT top(id_type i)       { _RYML_CB_ASSERT(m_callbacks, i < m_size); return m_stack[m_size - 1 - i]; }\n\n    C4_ALWAYS_INLINE T const& C4_RESTRICT bottom(id_type i) const { _RYML_CB_ASSERT(m_callbacks, i < m_size); return m_stack[i]; }\n    C4_ALWAYS_INLINE T      & C4_RESTRICT bottom(id_type i)       { _RYML_CB_ASSERT(m_callbacks, i < m_size); return m_stack[i]; }\n\n    C4_ALWAYS_INLINE T const& C4_RESTRICT operator[](id_type i) const { _RYML_CB_ASSERT(m_callbacks, i < m_size); return m_stack[i]; }\n    C4_ALWAYS_INLINE T      & C4_RESTRICT operator[](id_type i)       { _RYML_CB_ASSERT(m_callbacks, i < m_size); return m_stack[i]; }\n\npublic:\n\n    using       iterator = T       *;\n    using const_iterator = T const *;\n\n    iterator begin() { return m_stack; }\n    iterator end  () { return m_stack + m_size; }\n\n    const_iterator begin() const { return (const_iterator)m_stack; }\n    const_iterator end  () const { return (const_iterator)m_stack + m_size; }\n\npublic:\n\n    void _free();\n    void _cp(stack const* C4_RESTRICT that);\n    void _mv(stack * that);\n    void _cb(Callbacks const& cb);\n\n};\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\ntemplate<class T, id_type N>\nvoid stack<T, N>::reserve(id_type sz)\n{\n    if(sz <= m_size)\n        return;\n    if(sz <= N)\n    {\n        m_stack = m_buf;\n        m_capacity = N;\n        return;\n    }\n    T *buf = (T*) m_callbacks.m_allocate((size_t)sz * sizeof(T), m_stack, m_callbacks.m_user_data);\n    _RYML_CB_ASSERT(m_callbacks, ((uintptr_t)buf % alignof(T)) == 0u);\n    memcpy(buf, m_stack, (size_t)m_size * sizeof(T));\n    if(m_stack != m_buf)\n    {\n        m_callbacks.m_free(m_stack, (size_t)m_capacity * sizeof(T), m_callbacks.m_user_data);\n    }\n    m_stack = buf;\n    m_capacity = sz;\n}\n\n\n//-----------------------------------------------------------------------------\n\ntemplate<class T, id_type N>\nvoid stack<T, N>::_free()\n{\n    _RYML_CB_ASSERT(m_callbacks, m_stack != nullptr); // this structure cannot be memset() to zero\n    if(m_stack != m_buf)\n    {\n        m_callbacks.m_free(m_stack, (size_t)m_capacity * sizeof(T), m_callbacks.m_user_data);\n        m_stack = m_buf;\n        m_size = N;\n        m_capacity = N;\n    }\n    else\n    {\n        _RYML_CB_ASSERT(m_callbacks, m_capacity == N);\n    }\n}\n\n\n//-----------------------------------------------------------------------------\n\ntemplate<class T, id_type N>\nvoid stack<T, N>::_cp(stack const* C4_RESTRICT that)\n{\n    if(that->m_stack != that->m_buf)\n    {\n        _RYML_CB_ASSERT(m_callbacks, that->m_capacity > N);\n        _RYML_CB_ASSERT(m_callbacks, that->m_size <= that->m_capacity);\n    }\n    else\n    {\n        _RYML_CB_ASSERT(m_callbacks, that->m_capacity <= N);\n        _RYML_CB_ASSERT(m_callbacks, that->m_size <= that->m_capacity);\n    }\n    memcpy(m_stack, that->m_stack, that->m_size * sizeof(T));\n    m_size = that->m_size;\n    m_capacity = that->m_size < N ? N : that->m_size;\n    m_callbacks = that->m_callbacks;\n}\n\n\n//-----------------------------------------------------------------------------\n\ntemplate<class T, id_type N>\nvoid stack<T, N>::_mv(stack * that)\n{\n    if(that->m_stack != that->m_buf)\n    {\n        _RYML_CB_ASSERT(m_callbacks, that->m_capacity > N);\n        _RYML_CB_ASSERT(m_callbacks, that->m_size <= that->m_capacity);\n        m_stack = that->m_stack;\n    }\n    else\n    {\n        _RYML_CB_ASSERT(m_callbacks, that->m_capacity <= N);\n        _RYML_CB_ASSERT(m_callbacks, that->m_size <= that->m_capacity);\n        memcpy(m_buf, that->m_buf, that->m_size * sizeof(T));\n        m_stack = m_buf;\n    }\n    m_size = that->m_size;\n    m_capacity = that->m_capacity;\n    m_callbacks = that->m_callbacks;\n    // make sure no deallocation happens on destruction\n    _RYML_CB_ASSERT(m_callbacks, that->m_stack != m_buf);\n    that->m_stack = that->m_buf;\n    that->m_capacity = N;\n    that->m_size = 0;\n}\n\n\n//-----------------------------------------------------------------------------\n\ntemplate<class T, id_type N>\nvoid stack<T, N>::_cb(Callbacks const& cb)\n{\n    if(cb != m_callbacks)\n    {\n        _free();\n        m_callbacks = cb;\n    }\n}\n\n} // namespace detail\n\nC4_SUPPRESS_WARNING_GCC_CLANG_POP\n\n} // namespace yml\n} // namespace c4\n\n#endif /* _C4_YML_DETAIL_STACK_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/yml/emit.def.hpp",
    "content": "#ifndef _C4_YML_EMIT_DEF_HPP_\n#define _C4_YML_EMIT_DEF_HPP_\n\n#ifndef _C4_YML_EMIT_HPP_\n#include \"c4/yml/emit.hpp\"\n#endif\n\n/** @file emit.def.hpp Definitions for emit functions. */\n#ifndef _C4_YML_DETAIL_PARSER_DBG_HPP_\n#include \"c4/yml/detail/parser_dbg.hpp\"\n#endif\n\nnamespace c4 {\nnamespace yml {\n\ntemplate<class Writer>\nsubstr Emitter<Writer>::emit_as(EmitType_e type, Tree const& t, id_type id, bool error_on_excess)\n{\n    if(t.empty())\n    {\n        _RYML_CB_ASSERT(t.callbacks(), id == NONE);\n        return {};\n    }\n    if(id == NONE)\n        id = t.root_id();\n    _RYML_CB_CHECK(t.callbacks(), id < t.capacity());\n    m_tree = &t;\n    m_flow = false;\n    if(type == EMIT_YAML)\n        _emit_yaml(id);\n    else if(type == EMIT_JSON)\n        _do_visit_json(id, 0);\n    else\n        _RYML_CB_ERR(m_tree->callbacks(), \"unknown emit type\");\n    m_tree = nullptr;\n    return this->Writer::_get(error_on_excess);\n}\n\n\n//-----------------------------------------------------------------------------\n\ntemplate<class Writer>\nvoid Emitter<Writer>::_emit_yaml(id_type id)\n{\n    // save branches in the visitor by doing the initial stream/doc\n    // logic here, sparing the need to check stream/val/keyval inside\n    // the visitor functions\n    auto dispatch = [this](id_type node){\n        NodeType ty = m_tree->type(node);\n        if(ty.is_flow_sl())\n            _do_visit_flow_sl(node, 0);\n        else if(ty.is_flow_ml())\n            _do_visit_flow_ml(node, 0);\n        else\n        {\n            _do_visit_block(node, 0);\n        }\n    };\n    if(!m_tree->is_root(id))\n    {\n        if(m_tree->is_container(id) && !m_tree->type(id).is_flow())\n        {\n            id_type ilevel = 0;\n            if(m_tree->has_key(id))\n            {\n                this->Writer::_do_write(m_tree->key(id));\n                this->Writer::_do_write(\":\\n\");\n                ++ilevel;\n            }\n            _do_visit_block_container(id, 0, ilevel, ilevel);\n            return;\n        }\n    }\n\n    TagDirectiveRange tagds = m_tree->tag_directives();\n    auto write_tag_directives = [&tagds, this](const id_type next_node){\n        TagDirective const* C4_RESTRICT end = tagds.b;\n        while(end < tagds.e)\n        {\n            if(end->next_node_id > next_node)\n                break;\n            ++end;\n        }\n        const id_type parent = m_tree->parent(next_node);\n        for( ; tagds.b != end; ++tagds.b)\n        {\n            if(next_node != m_tree->first_child(parent))\n                this->Writer::_do_write(\"...\\n\");\n            this->Writer::_do_write(\"%TAG \");\n            this->Writer::_do_write(tagds.b->handle);\n            this->Writer::_do_write(' ');\n            this->Writer::_do_write(tagds.b->prefix);\n            this->Writer::_do_write('\\n');\n        }\n    };\n    if(m_tree->is_stream(id))\n    {\n        const id_type first_child = m_tree->first_child(id);\n        if(first_child != NONE)\n            write_tag_directives(first_child);\n        for(id_type child = first_child; child != NONE; child = m_tree->next_sibling(child))\n        {\n            dispatch(child);\n            if(m_tree->is_doc(child) && m_tree->type(child).is_flow_sl())\n                this->Writer::_do_write('\\n');\n            if(m_tree->next_sibling(child) != NONE)\n                write_tag_directives(m_tree->next_sibling(child));\n        }\n    }\n    else if(m_tree->is_container(id))\n    {\n        dispatch(id);\n    }\n    else if(m_tree->is_doc(id))\n    {\n        _RYML_CB_ASSERT(m_tree->callbacks(), !m_tree->is_container(id)); // checked above\n        _RYML_CB_ASSERT(m_tree->callbacks(), m_tree->is_val(id)); // so it must be a val\n        _write_doc(id);\n    }\n    else if(m_tree->is_keyval(id))\n    {\n        _writek(id, 0);\n        this->Writer::_do_write(\": \");\n        _writev(id, 0);\n        if(!m_tree->type(id).is_flow())\n            this->Writer::_do_write('\\n');\n    }\n    else if(m_tree->is_val(id))\n    {\n        //this->Writer::_do_write(\"- \");\n        _writev(id, 0);\n        if(!m_tree->type(id).is_flow())\n            this->Writer::_do_write('\\n');\n    }\n    else if(m_tree->type(id) == NOTYPE)\n    {\n        ;\n    }\n    else\n    {\n        _RYML_CB_ERR(m_tree->callbacks(), \"unknown type\");\n    }\n}\n\n#define _rymlindent_nextline() this->_indent(ilevel + 1);\n\ntemplate<class Writer>\nvoid Emitter<Writer>::_write_doc(id_type id)\n{\n    RYML_ASSERT(m_tree->is_doc(id));\n    RYML_ASSERT(!m_tree->has_key(id));\n    if(!m_tree->is_root(id))\n    {\n        RYML_ASSERT(m_tree->is_stream(m_tree->parent(id)));\n        this->Writer::_do_write(\"---\");\n    }\n    //\n    if(!m_tree->has_val(id)) // this is more frequent\n    {\n        const bool tag = m_tree->has_val_tag(id);\n        const bool anchor = m_tree->has_val_anchor(id);\n        if(!tag && !anchor)\n        {\n            ;\n        }\n        else if(!tag && anchor)\n        {\n            if(!m_tree->is_root(id))\n                this->Writer::_do_write(' ');\n            this->Writer::_do_write('&');\n            this->Writer::_do_write(m_tree->val_anchor(id));\n            #ifdef RYML_NO_COVERAGE__TO_BE_DELETED\n            if(m_tree->has_children(id) && m_tree->is_root(id))\n                this->Writer::_do_write('\\n');\n            #endif\n        }\n        else if(tag && !anchor)\n        {\n            if(!m_tree->is_root(id))\n                this->Writer::_do_write(' ');\n            _write_tag(m_tree->val_tag(id));\n            #ifdef RYML_NO_COVERAGE__TO_BE_DELETED\n            if(m_tree->has_children(id) && m_tree->is_root(id))\n                this->Writer::_do_write('\\n');\n            #endif\n        }\n        else // tag && anchor\n        {\n            if(!m_tree->is_root(id))\n                this->Writer::_do_write(' ');\n            _write_tag(m_tree->val_tag(id));\n            this->Writer::_do_write(\" &\");\n            this->Writer::_do_write(m_tree->val_anchor(id));\n            #ifdef RYML_NO_COVERAGE__TO_BE_DELETED\n            if(m_tree->has_children(id) && m_tree->is_root(id))\n                this->Writer::_do_write('\\n');\n            #endif\n        }\n    }\n    else // docval\n    {\n        _RYML_CB_ASSERT(m_tree->callbacks(), m_tree->has_val(id));\n        // some plain scalars such as '...' and '---' must not\n        // appear at 0-indentation\n        const csubstr val = m_tree->val(id);\n        const bool preceded_by_3_dashes = !m_tree->is_root(id);\n        const type_bits style_marks = m_tree->type(id) & (KEY_STYLE|VAL_STYLE);\n        const bool is_plain = m_tree->type(id).is_val_plain();\n        const bool is_ambiguous = (is_plain || !style_marks)\n            && ((val.begins_with(\"...\") || val.begins_with(\"---\"))\n                ||\n                (val.find('\\n') != npos));\n        if(preceded_by_3_dashes)\n        {\n            if(val.len == 0 && !m_tree->has_val_anchor(id) && !m_tree->has_val_tag(id))\n            {\n                this->Writer::_do_write('\\n');\n                return;\n            }\n            else if(val.len && is_ambiguous)\n            {\n                this->Writer::_do_write('\\n');\n            }\n            else\n            {\n                this->Writer::_do_write(' ');\n            }\n        }\n        id_type ilevel = 0u;\n        if(is_ambiguous)\n        {\n            _rymlindent_nextline();\n            ++ilevel;\n        }\n        _writev(id, ilevel);\n        if(val.len && m_tree->is_root(id))\n            this->Writer::_do_write('\\n');\n    }\n    if(!m_tree->is_root(id))\n        this->Writer::_do_write('\\n');\n}\n\ntemplate<class Writer>\nvoid Emitter<Writer>::_do_visit_flow_sl(id_type node, id_type depth, id_type ilevel)\n{\n    const bool prev_flow = m_flow;\n    m_flow = true;\n    _RYML_CB_ASSERT(m_tree->callbacks(), !m_tree->is_stream(node));\n    _RYML_CB_ASSERT(m_tree->callbacks(), m_tree->is_container(node) || m_tree->is_doc(node));\n    _RYML_CB_ASSERT(m_tree->callbacks(), m_tree->is_root(node) || (m_tree->parent_is_map(node) || m_tree->parent_is_seq(node)));\n    if(C4_UNLIKELY(depth > m_opts.max_depth()))\n        _RYML_CB_ERR(m_tree->callbacks(), \"max depth exceeded\");\n\n    if(m_tree->is_doc(node))\n    {\n        _write_doc(node);\n        #ifdef RYML_NO_COVERAGE__TO_BE_DELETED\n        if(!m_tree->has_children(node))\n            return;\n        else\n        #endif\n        {\n            if(m_tree->is_map(node))\n            {\n                this->Writer::_do_write('{');\n            }\n            else\n            {\n                _RYML_CB_ASSERT(m_tree->callbacks(), m_tree->is_seq(node));\n                this->Writer::_do_write('[');\n            }\n        }\n    }\n    else if(m_tree->is_container(node))\n    {\n        _RYML_CB_ASSERT(m_tree->callbacks(), m_tree->is_map(node) || m_tree->is_seq(node));\n\n        bool spc = false; // write a space\n\n        if(m_tree->has_key(node))\n        {\n            _writek(node, ilevel);\n            this->Writer::_do_write(':');\n            spc = true;\n        }\n\n        if(m_tree->has_val_tag(node))\n        {\n            if(spc)\n                this->Writer::_do_write(' ');\n            _write_tag(m_tree->val_tag(node));\n            spc = true;\n        }\n\n        if(m_tree->has_val_anchor(node))\n        {\n            if(spc)\n                this->Writer::_do_write(' ');\n            this->Writer::_do_write('&');\n            this->Writer::_do_write(m_tree->val_anchor(node));\n            spc = true;\n        }\n\n        if(spc)\n            this->Writer::_do_write(' ');\n\n        if(m_tree->is_map(node))\n        {\n            this->Writer::_do_write('{');\n        }\n        else\n        {\n            _RYML_CB_ASSERT(m_tree->callbacks(), m_tree->is_seq(node));\n            this->Writer::_do_write('[');\n        }\n    } // container\n\n    for(id_type child = m_tree->first_child(node), count = 0; child != NONE; child = m_tree->next_sibling(child))\n    {\n        if(count++)\n            this->Writer::_do_write(',');\n        if(m_tree->is_keyval(child))\n        {\n            _writek(child, ilevel);\n            this->Writer::_do_write(\": \");\n            _writev(child, ilevel);\n        }\n        else if(m_tree->is_val(child))\n        {\n            _writev(child, ilevel);\n        }\n        else\n        {\n            // with single-line flow, we can never go back to block\n            _do_visit_flow_sl(child, depth + 1, ilevel + 1);\n        }\n    }\n\n    if(m_tree->is_map(node))\n    {\n        this->Writer::_do_write('}');\n    }\n    else if(m_tree->is_seq(node))\n    {\n        this->Writer::_do_write(']');\n    }\n    m_flow = prev_flow;\n}\n\nC4_SUPPRESS_WARNING_MSVC_WITH_PUSH(4702) // unreachable error, triggered by flow_ml not implemented\n\ntemplate<class Writer>\nvoid Emitter<Writer>::_do_visit_flow_ml(id_type id, id_type depth, id_type ilevel, id_type do_indent)\n{\n    C4_UNUSED(id);\n    C4_UNUSED(depth);\n    C4_UNUSED(ilevel);\n    C4_UNUSED(do_indent);\n    c4::yml::error(\"not implemented\");\n    #ifdef THIS_IS_A_WORK_IN_PROGRESS\n    if(C4_UNLIKELY(depth > m_opts.max_depth()))\n        _RYML_CB_ERR(m_tree->callbacks(), \"max depth exceeded\");\n    const bool prev_flow = m_flow;\n    m_flow = true;\n    // do it...\n    m_flow = prev_flow;\n    #endif\n}\n\ntemplate<class Writer>\nvoid Emitter<Writer>::_do_visit_block_container(id_type node, id_type depth, id_type level, bool do_indent)\n{\n    if(m_tree->is_seq(node))\n    {\n        for(id_type child = m_tree->first_child(node); child != NONE; child = m_tree->next_sibling(child))\n        {\n            _RYML_CB_ASSERT(m_tree->callbacks(), !m_tree->has_key(child));\n            if(m_tree->is_val(child))\n            {\n                _indent(level, do_indent);\n                this->Writer::_do_write(\"- \");\n                _writev(child, level);\n                this->Writer::_do_write('\\n');\n            }\n            else\n            {\n                _RYML_CB_ASSERT(m_tree->callbacks(), m_tree->is_container(child));\n                NodeType ty = m_tree->type(child);\n                if(ty.is_flow_sl())\n                {\n                    _indent(level, do_indent);\n                    this->Writer::_do_write(\"- \");\n                    _do_visit_flow_sl(child, depth+1, 0u);\n                    this->Writer::_do_write('\\n');\n                }\n                else if(ty.is_flow_ml())\n                {\n                    _indent(level, do_indent);\n                    this->Writer::_do_write(\"- \");\n                    _do_visit_flow_ml(child, depth+1, 0u, do_indent);\n                    this->Writer::_do_write('\\n');\n                }\n                else\n                {\n                    _do_visit_block(child, depth+1, level, do_indent); // same indentation level\n                }\n            }\n            do_indent = true;\n        }\n    }\n    else // map\n    {\n        _RYML_CB_ASSERT(m_tree->callbacks(), m_tree->is_map(node));\n        for(id_type ich = m_tree->first_child(node); ich != NONE; ich = m_tree->next_sibling(ich))\n        {\n            _RYML_CB_ASSERT(m_tree->callbacks(), m_tree->has_key(ich));\n            if(m_tree->is_keyval(ich))\n            {\n                _indent(level, do_indent);\n                _writek(ich, level);\n                this->Writer::_do_write(\": \");\n                _writev(ich, level);\n                this->Writer::_do_write('\\n');\n            }\n            else\n            {\n                _RYML_CB_ASSERT(m_tree->callbacks(), m_tree->is_container(ich));\n                NodeType ty = m_tree->type(ich);\n                if(ty.is_flow_sl())\n                {\n                    _indent(level, do_indent);\n                    _do_visit_flow_sl(ich, depth+1, 0u);\n                    this->Writer::_do_write('\\n');\n                }\n                else if(ty.is_flow_ml())\n                {\n                    _indent(level, do_indent);\n                    _do_visit_flow_ml(ich, depth+1, 0u);\n                    this->Writer::_do_write('\\n');\n                }\n                else\n                {\n                    _do_visit_block(ich, depth+1, level, do_indent); // same level!\n                }\n            } // keyval vs container\n            do_indent = true;\n        } // for children\n    } // seq vs map\n}\n\ntemplate<class Writer>\nvoid Emitter<Writer>::_do_visit_block(id_type node, id_type depth, id_type ilevel, id_type do_indent)\n{\n    _RYML_CB_ASSERT(m_tree->callbacks(), !m_tree->is_stream(node));\n    _RYML_CB_ASSERT(m_tree->callbacks(), m_tree->is_container(node) || m_tree->is_doc(node));\n    _RYML_CB_ASSERT(m_tree->callbacks(), m_tree->is_root(node) || (m_tree->parent_is_map(node) || m_tree->parent_is_seq(node)));\n    if(C4_UNLIKELY(depth > m_opts.max_depth()))\n        _RYML_CB_ERR(m_tree->callbacks(), \"max depth exceeded\");\n    if(m_tree->is_doc(node))\n    {\n        _write_doc(node);\n        if(!m_tree->has_children(node))\n            return;\n    }\n    else if(m_tree->is_container(node))\n    {\n        _RYML_CB_ASSERT(m_tree->callbacks(), m_tree->is_map(node) || m_tree->is_seq(node));\n        bool spc = false; // write a space\n        bool nl = false;  // write a newline\n        if(m_tree->has_key(node))\n        {\n            _indent(ilevel, do_indent);\n            _writek(node, ilevel);\n            this->Writer::_do_write(':');\n            spc = true;\n        }\n        else if(!m_tree->is_root(node))\n        {\n            _indent(ilevel, do_indent);\n            this->Writer::_do_write('-');\n            spc = true;\n        }\n\n        if(m_tree->has_val_tag(node))\n        {\n            if(spc)\n                this->Writer::_do_write(' ');\n            _write_tag(m_tree->val_tag(node));\n            spc = true;\n            nl = true;\n        }\n\n        if(m_tree->has_val_anchor(node))\n        {\n            if(spc)\n                this->Writer::_do_write(' ');\n            this->Writer::_do_write('&');\n            this->Writer::_do_write(m_tree->val_anchor(node));\n            spc = true;\n            nl = true;\n        }\n\n        if(m_tree->has_children(node))\n        {\n            if(m_tree->has_key(node))\n                nl = true;\n            else\n                if(!m_tree->is_root(node) && !nl)\n                    spc = true;\n        }\n        else\n        {\n            if(m_tree->is_seq(node))\n                this->Writer::_do_write(\" []\\n\");\n            else if(m_tree->is_map(node))\n                this->Writer::_do_write(\" {}\\n\");\n            return;\n        }\n\n        if(spc && !nl)\n            this->Writer::_do_write(' ');\n\n        do_indent = 0;\n        if(nl)\n        {\n            this->Writer::_do_write('\\n');\n            do_indent = 1;\n        }\n    } // container\n\n    id_type next_level = ilevel + 1;\n    if(m_tree->is_root(node) || m_tree->is_doc(node))\n        next_level = ilevel; // do not indent at top level\n\n    _do_visit_block_container(node, depth, next_level, do_indent);\n}\n\nC4_SUPPRESS_WARNING_MSVC_POP\n\n\ntemplate<class Writer>\nvoid Emitter<Writer>::_do_visit_json(id_type id, id_type depth)\n{\n    _RYML_CB_CHECK(m_tree->callbacks(), !m_tree->is_stream(id)); // JSON does not have streams\n    if(C4_UNLIKELY(depth > m_opts.max_depth()))\n        _RYML_CB_ERR(m_tree->callbacks(), \"max depth exceeded\");\n    if(m_tree->is_keyval(id))\n    {\n        _writek_json(id);\n        this->Writer::_do_write(\": \");\n        _writev_json(id);\n    }\n    else if(m_tree->is_val(id))\n    {\n        _writev_json(id);\n    }\n    else if(m_tree->is_container(id))\n    {\n        if(m_tree->has_key(id))\n        {\n            _writek_json(id);\n            this->Writer::_do_write(\": \");\n        }\n        if(m_tree->is_seq(id))\n            this->Writer::_do_write('[');\n        else if(m_tree->is_map(id))\n            this->Writer::_do_write('{');\n    }  // container\n\n    for(id_type ich = m_tree->first_child(id); ich != NONE; ich = m_tree->next_sibling(ich))\n    {\n        if(ich != m_tree->first_child(id))\n            this->Writer::_do_write(',');\n        _do_visit_json(ich, depth+1);\n    }\n\n    if(m_tree->is_seq(id))\n        this->Writer::_do_write(']');\n    else if(m_tree->is_map(id))\n        this->Writer::_do_write('}');\n}\n\ntemplate<class Writer>\nvoid Emitter<Writer>::_write(NodeScalar const& C4_RESTRICT sc, NodeType flags, id_type ilevel)\n{\n    if( ! sc.tag.empty())\n    {\n        _write_tag(sc.tag);\n        this->Writer::_do_write(' ');\n    }\n    if(flags.has_anchor())\n    {\n        RYML_ASSERT(flags.is_ref() != flags.has_anchor());\n        RYML_ASSERT( ! sc.anchor.empty());\n        this->Writer::_do_write('&');\n        this->Writer::_do_write(sc.anchor);\n        this->Writer::_do_write(' ');\n    }\n    else if(flags.is_ref())\n    {\n        if(sc.anchor != \"<<\")\n            this->Writer::_do_write('*');\n        this->Writer::_do_write(sc.anchor);\n        if(flags.is_key_ref())\n            this->Writer::_do_write(' ');\n        return;\n    }\n\n    // ensure the style flags only have one of KEY or VAL\n    _RYML_CB_ASSERT(m_tree->callbacks(), ((flags & SCALAR_STYLE) == 0) || (((flags&KEY_STYLE) == 0) != ((flags&VAL_STYLE) == 0)));\n    type_bits style_marks = flags & SCALAR_STYLE;\n    if(!style_marks)\n        style_marks = scalar_style_choose(sc.scalar);\n    if(style_marks & (KEY_LITERAL|VAL_LITERAL))\n    {\n        _write_scalar_literal(sc.scalar, ilevel, flags.has_key());\n    }\n    else if(style_marks & (KEY_FOLDED|VAL_FOLDED))\n    {\n        _write_scalar_folded(sc.scalar, ilevel, flags.has_key());\n    }\n    else if(style_marks & (KEY_SQUO|VAL_SQUO))\n    {\n        _write_scalar_squo(sc.scalar, ilevel);\n    }\n    else if(style_marks & (KEY_DQUO|VAL_DQUO))\n    {\n        _write_scalar_dquo(sc.scalar, ilevel);\n    }\n    else if(style_marks & (KEY_PLAIN|VAL_PLAIN))\n    {\n        if(C4_LIKELY(!(sc.scalar.begins_with(\": \") || sc.scalar.begins_with(\":\\t\"))))\n            _write_scalar_plain(sc.scalar, ilevel);\n        else\n            _write_scalar_squo(sc.scalar, ilevel);\n    }\n    else\n    {\n        _RYML_CB_ERR(m_tree->callbacks(), \"not implemented\");\n    }\n}\n\ntemplate<class Writer>\nvoid Emitter<Writer>::_write_json(NodeScalar const& C4_RESTRICT sc, NodeType flags)\n{\n    if(flags & (KEYTAG|VALTAG))\n        if(m_opts.json_error_flags() & EmitOptions::JSON_ERR_ON_TAG)\n            _RYML_CB_ERR(m_tree->callbacks(), \"JSON does not have tags\");\n    if(C4_UNLIKELY(flags.has_anchor()))\n        if(m_opts.json_error_flags() & EmitOptions::JSON_ERR_ON_ANCHOR)\n            _RYML_CB_ERR(m_tree->callbacks(), \"JSON does not have anchors\");\n    if(sc.scalar.len)\n    {\n        // use double quoted style...\n        // if it is a key (mandatory in JSON)\n        // if the style is marked quoted\n        bool dquoted = ((flags & (KEY|VALQUO))\n                        || (scalar_style_json_choose(sc.scalar) & SCALAR_DQUO)); // choose the style\n        if(dquoted)\n            _write_scalar_json_dquo(sc.scalar);\n        else\n            this->Writer::_do_write(sc.scalar);\n    }\n    else\n    {\n        if(sc.scalar.str || (flags & (KEY|VALQUO|KEYTAG|VALTAG)))\n            this->Writer::_do_write(\"\\\"\\\"\");\n        else\n            this->Writer::_do_write(\"null\");\n    }\n}\n\ntemplate<class Writer>\nsize_t Emitter<Writer>::_write_escaped_newlines(csubstr s, size_t i)\n{\n    RYML_ASSERT(s.len > i);\n    RYML_ASSERT(s.str[i] == '\\n');\n    //_c4dbgpf(\"nl@i={} rem=[{}]~~~{}~~~\", i, s.sub(i).len, s.sub(i));\n    // add an extra newline for each sequence of consecutive\n    // newline/whitespace\n    this->Writer::_do_write('\\n');\n    do\n    {\n        this->Writer::_do_write('\\n'); // write the newline again\n        ++i; // increase the outer loop counter!\n    } while(i < s.len && s.str[i] == '\\n');\n    _RYML_CB_ASSERT(m_tree->callbacks(), i > 0);\n    --i;\n    _RYML_CB_ASSERT(m_tree->callbacks(), s.str[i] == '\\n');\n    return i;\n}\n\ninline bool _is_indented_block(csubstr s, size_t prev, size_t i) noexcept\n{\n    if(prev == 0 && s.begins_with_any(\" \\t\"))\n        return true;\n    const size_t pos = s.first_not_of('\\n', i);\n    return (pos != npos) && (s.str[pos] == ' ' || s.str[pos] == '\\t');\n}\n\ntemplate<class Writer>\nsize_t Emitter<Writer>::_write_indented_block(csubstr s, size_t i, id_type ilevel)\n{\n    //_c4dbgpf(\"indblock@i={} rem=[{}]~~~\\n{}~~~\", i, s.sub(i).len, s.sub(i));\n    _RYML_CB_ASSERT(m_tree->callbacks(), i > 0);\n    _RYML_CB_ASSERT(m_tree->callbacks(), s.str[i-1] == '\\n');\n    _RYML_CB_ASSERT(m_tree->callbacks(), i < s.len);\n    _RYML_CB_ASSERT(m_tree->callbacks(), s.str[i] == ' ' || s.str[i] == '\\t' || s.str[i] == '\\n');\nagain:\n    size_t pos = s.find(\"\\n \", i);\n    if(pos == npos)\n        pos = s.find(\"\\n\\t\", i);\n    if(pos != npos)\n    {\n        ++pos;\n        //_c4dbgpf(\"indblock line@i={} rem=[{}]~~~\\n{}~~~\", i, s.range(i, pos).len, s.range(i, pos));\n        _rymlindent_nextline();\n        this->Writer::_do_write(s.range(i, pos));\n        i = pos;\n        goto again;\n    }\n    // consume the newlines after the indented block\n    // to prevent them from being escaped\n    pos = s.find('\\n', i);\n    if(pos != npos)\n    {\n        const size_t pos2 = s.first_not_of('\\n', pos);\n        pos = (pos2 != npos) ? pos2 : pos;\n        //_c4dbgpf(\"indblock line@i={} rem=[{}]~~~\\n{}~~~\", i, s.range(i, pos).len, s.range(i, pos));\n        _rymlindent_nextline();\n        this->Writer::_do_write(s.range(i, pos));\n        i = pos;\n    }\n    return i;\n}\n\ntemplate<class Writer>\nvoid Emitter<Writer>::_write_scalar_literal(csubstr s, id_type ilevel, bool explicit_key)\n{\n    _RYML_CB_ASSERT(m_tree->callbacks(), s.find(\"\\r\") == csubstr::npos);\n    if(explicit_key)\n        this->Writer::_do_write(\"? \");\n    csubstr trimmed = s.trimr('\\n');\n    const size_t numnewlines_at_end = s.len - trimmed.len;\n    const bool is_newline_only = (trimmed.len == 0 && (s.len > 0));\n    const bool explicit_indentation = s.triml(\"\\n\\r\").begins_with_any(\" \\t\");\n    //\n    this->Writer::_do_write('|');\n    if(explicit_indentation)\n        this->Writer::_do_write('2');\n    //\n    if(numnewlines_at_end > 1 || is_newline_only)\n        this->Writer::_do_write('+');\n    else if(numnewlines_at_end == 0)\n        this->Writer::_do_write('-');\n    //\n    if(trimmed.len)\n    {\n        this->Writer::_do_write('\\n');\n        size_t pos = 0; // tracks the last character that was already written\n        for(size_t i = 0; i < trimmed.len; ++i)\n        {\n            if(trimmed[i] != '\\n')\n                continue;\n            // write everything up to this point\n            csubstr since_pos = trimmed.range(pos, i+1); // include the newline\n            _rymlindent_nextline()\n            this->Writer::_do_write(since_pos);\n            pos = i+1; // already written\n        }\n        if(pos < trimmed.len)\n        {\n            _rymlindent_nextline()\n            this->Writer::_do_write(trimmed.sub(pos));\n        }\n    }\n    for(size_t i = !is_newline_only; i < numnewlines_at_end; ++i)\n        this->Writer::_do_write('\\n');\n    if(explicit_key)\n        this->Writer::_do_write('\\n');\n}\n\ntemplate<class Writer>\nvoid Emitter<Writer>::_write_scalar_folded(csubstr s, id_type ilevel, bool explicit_key)\n{\n    if(explicit_key)\n        this->Writer::_do_write(\"? \");\n    _RYML_CB_ASSERT(m_tree->callbacks(), s.find(\"\\r\") == csubstr::npos);\n    csubstr trimmed = s.trimr('\\n');\n    const size_t numnewlines_at_end = s.len - trimmed.len;\n    const bool is_newline_only = (trimmed.len == 0 && (s.len > 0));\n    const bool explicit_indentation = s.triml(\"\\n\\r\").begins_with_any(\" \\t\");\n    //\n    this->Writer::_do_write('>');\n    if(explicit_indentation)\n        this->Writer::_do_write('2');\n    //\n    if(numnewlines_at_end == 0)\n        this->Writer::_do_write('-');\n    else if(numnewlines_at_end > 1 || is_newline_only)\n        this->Writer::_do_write('+');\n    //\n    if(trimmed.len)\n    {\n        this->Writer::_do_write('\\n');\n        size_t pos = 0; // tracks the last character that was already written\n        for(size_t i = 0; i < trimmed.len; ++i)\n        {\n            if(trimmed[i] != '\\n')\n                continue;\n            // escape newline sequences\n            if( ! _is_indented_block(s, pos, i))\n            {\n                if(pos < i)\n                {\n                    _rymlindent_nextline()\n                    this->Writer::_do_write(s.range(pos, i));\n                    i = _write_escaped_newlines(s, i);\n                    pos = i+1;\n                }\n                else\n                {\n                    if(i+1 < s.len)\n                    {\n                        if(s.str[i+1] == '\\n')\n                        {\n                            ++i;\n                            i = _write_escaped_newlines(s, i);\n                            pos = i+1;\n                        }\n                        else\n                        {\n                            this->Writer::_do_write('\\n');\n                            pos = i+1;\n                        }\n                    }\n                }\n            }\n            else // do not escape newlines in indented blocks\n            {\n                ++i;\n                _rymlindent_nextline()\n                this->Writer::_do_write(s.range(pos, i));\n                if(pos > 0 || !s.begins_with_any(\" \\t\"))\n                    i = _write_indented_block(s, i, ilevel);\n                pos = i;\n            }\n        }\n        if(pos < trimmed.len)\n        {\n            _rymlindent_nextline()\n            this->Writer::_do_write(trimmed.sub(pos));\n        }\n    }\n    for(size_t i = !is_newline_only; i < numnewlines_at_end; ++i)\n        this->Writer::_do_write('\\n');\n    if(explicit_key)\n        this->Writer::_do_write('\\n');\n}\n\ntemplate<class Writer>\nvoid Emitter<Writer>::_write_scalar_squo(csubstr s, id_type ilevel)\n{\n    size_t pos = 0; // tracks the last character that was already written\n    this->Writer::_do_write('\\'');\n    for(size_t i = 0; i < s.len; ++i)\n    {\n        if(s[i] == '\\n')\n        {\n            this->Writer::_do_write(s.range(pos, i));  // write everything up to (excluding) this char\n            //_c4dbgpf(\"newline at {}. writing ~~~{}~~~\", i, s.range(pos, i));\n            i = _write_escaped_newlines(s, i);\n            //_c4dbgpf(\"newline --> {}\", i);\n            if(i < s.len)\n                _rymlindent_nextline()\n            pos = i+1;\n        }\n        else if(s[i] == '\\'')\n        {\n            csubstr sub = s.range(pos, i+1);\n            //_c4dbgpf(\"squote at {}. writing ~~~{}~~~\", i, sub);\n            this->Writer::_do_write(sub); // write everything up to (including) this squote\n            this->Writer::_do_write('\\''); // write the squote again\n            pos = i+1;\n        }\n    }\n    // write missing characters at the end of the string\n    if(pos < s.len)\n        this->Writer::_do_write(s.sub(pos));\n    this->Writer::_do_write('\\'');\n}\n\ntemplate<class Writer>\nvoid Emitter<Writer>::_write_scalar_dquo(csubstr s, id_type ilevel)\n{\n    size_t pos = 0; // tracks the last character that was already written\n    this->Writer::_do_write('\"');\n    for(size_t i = 0; i < s.len; ++i)\n    {\n        const char curr = s.str[i];\n        switch(curr)\n        {\n        case '\"':\n        case '\\\\':\n        {\n            csubstr sub = s.range(pos, i);\n            this->Writer::_do_write(sub);  // write everything up to (excluding) this char\n            this->Writer::_do_write('\\\\'); // write the escape\n            this->Writer::_do_write(curr); // write the char\n            pos = i+1;\n            break;\n        }\n#ifndef prefer_writing_newlines_as_double_newlines\n        case '\\n':\n        {\n            csubstr sub = s.range(pos, i);\n            this->Writer::_do_write(sub);   // write everything up to (excluding) this char\n            this->Writer::_do_write(\"\\\\n\"); // write the escape\n            pos = i+1;\n            (void)ilevel;\n            break;\n        }\n#else\n        case '\\n':\n        {\n            // write everything up to (excluding) this newline\n            //_c4dbgpf(\"nl@i={} rem=[{}]~~~{}~~~\", i, s.sub(i).len, s.sub(i));\n            this->Writer::_do_write(s.range(pos, i));\n            i = _write_escaped_newlines(s, i);\n            ++i;\n            pos = i;\n            // as for the next line...\n            if(i < s.len)\n            {\n                _rymlindent_nextline() // indent the next line\n                // escape leading whitespace, and flush it\n                size_t first = s.first_not_of(\" \\t\", i);\n                _c4dbgpf(\"@i={} first={} rem=[{}]~~~{}~~~\", i, first, s.sub(i).len, s.sub(i));\n                if(first > i)\n                {\n                    if(first == npos)\n                        first = s.len;\n                    this->Writer::_do_write('\\\\');\n                    this->Writer::_do_write(s.range(i, first));\n                    this->Writer::_do_write('\\\\');\n                    i = first-1;\n                    pos = first;\n                }\n            }\n            break;\n        }\n        // escape trailing whitespace before a newline\n        case ' ':\n        case '\\t':\n        {\n            const size_t next = s.first_not_of(\" \\t\\r\", i);\n            if(next != npos && s.str[next] == '\\n')\n            {\n                csubstr sub = s.range(pos, i);\n                this->Writer::_do_write(sub);  // write everything up to (excluding) this char\n                this->Writer::_do_write('\\\\'); // escape the whitespace\n                pos = i;\n            }\n            break;\n        }\n#endif\n        case '\\r':\n        {\n            csubstr sub = s.range(pos, i);\n            this->Writer::_do_write(sub);  // write everything up to (excluding) this char\n            this->Writer::_do_write(\"\\\\r\"); // write the escaped char\n            pos = i+1;\n            break;\n        }\n        case '\\b':\n        {\n            csubstr sub = s.range(pos, i);\n            this->Writer::_do_write(sub);  // write everything up to (excluding) this char\n            this->Writer::_do_write(\"\\\\b\"); // write the escaped char\n            pos = i+1;\n            break;\n        }\n        }\n    }\n    // write missing characters at the end of the string\n    if(pos < s.len)\n        this->Writer::_do_write(s.sub(pos));\n    this->Writer::_do_write('\"');\n}\n\ntemplate<class Writer>\nvoid Emitter<Writer>::_write_scalar_plain(csubstr s, id_type ilevel)\n{\n    if(C4_UNLIKELY(ilevel == 0 && (s.begins_with(\"...\") || s.begins_with(\"---\"))))\n    {\n        _rymlindent_nextline()     // indent the next line\n        ++ilevel;\n    }\n    size_t pos = 0; // tracks the last character that was already written\n    for(size_t i = 0; i < s.len; ++i)\n    {\n        const char curr = s.str[i];\n        if(curr == '\\n')\n        {\n            csubstr sub = s.range(pos, i);\n            this->Writer::_do_write(sub);  // write everything up to (including) this newline\n            i = _write_escaped_newlines(s, i);\n            pos = i+1;\n            if(pos < s.len)\n                _rymlindent_nextline()     // indent the next line\n        }\n    }\n    // write missing characters at the end of the string\n    if(pos < s.len)\n        this->Writer::_do_write(s.sub(pos));\n}\n\n#undef _rymlindent_nextline\n\ntemplate<class Writer>\nvoid Emitter<Writer>::_write_scalar_json_dquo(csubstr s)\n{\n    size_t pos = 0;\n    this->Writer::_do_write('\"');\n    for(size_t i = 0; i < s.len; ++i)\n    {\n        switch(s.str[i])\n        {\n        case '\"':\n            this->Writer ::_do_write(s.range(pos, i));\n            this->Writer ::_do_write(\"\\\\\\\"\");\n            pos = i + 1;\n            break;\n        case '\\n':\n            this->Writer ::_do_write(s.range(pos, i));\n            this->Writer ::_do_write(\"\\\\n\");\n            pos = i + 1;\n            break;\n        case '\\t':\n            this->Writer ::_do_write(s.range(pos, i));\n            this->Writer ::_do_write(\"\\\\t\");\n            pos = i + 1;\n            break;\n        case '\\\\':\n            this->Writer ::_do_write(s.range(pos, i));\n            this->Writer ::_do_write(\"\\\\\\\\\");\n            pos = i + 1;\n            break;\n        case '\\r':\n            this->Writer ::_do_write(s.range(pos, i));\n            this->Writer ::_do_write(\"\\\\r\");\n            pos = i + 1;\n            break;\n        case '\\b':\n            this->Writer ::_do_write(s.range(pos, i));\n            this->Writer ::_do_write(\"\\\\b\");\n            pos = i + 1;\n            break;\n        case '\\f':\n            this->Writer ::_do_write(s.range(pos, i));\n            this->Writer ::_do_write(\"\\\\f\");\n            pos = i + 1;\n            break;\n        }\n    }\n    if(pos < s.len)\n    {\n        csubstr sub = s.sub(pos);\n        this->Writer::_do_write(sub);\n    }\n    this->Writer::_do_write('\"');\n}\n\n} // namespace yml\n} // namespace c4\n\n#endif /* _C4_YML_EMIT_DEF_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/yml/emit.hpp",
    "content": "#ifndef _C4_YML_EMIT_HPP_\n#define _C4_YML_EMIT_HPP_\n\n/** @file emit.hpp Utilities to emit YAML and JSON. */\n\n#ifndef _C4_YML_WRITER_HPP_\n#include \"./writer.hpp\"\n#endif\n\n#ifndef _C4_YML_TREE_HPP_\n#include \"./tree.hpp\"\n#endif\n\n#ifndef _C4_YML_NODE_HPP_\n#include \"./node.hpp\"\n#endif\n\n#define RYML_DEPRECATE_EMIT                                             \\\n    RYML_DEPRECATED(\"use emit_yaml() instead. \"                         \\\n                    \"See https://github.com/biojppm/rapidyaml/issues/120\")\n#define RYML_DEPRECATE_EMITRS                                           \\\n    RYML_DEPRECATED(\"use emitrs_yaml() instead. \"                       \\\n                    \"See https://github.com/biojppm/rapidyaml/issues/120\")\n\n#ifdef emit\n#error \"emit is defined, likely from a Qt include. \"                    \\\n    \"This will cause a compilation error. \"                             \\\n    \"See https://github.com/biojppm/rapidyaml/issues/120\"\n#endif\n\n\nC4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH(\"-Wold-style-cast\")\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\nnamespace c4 {\nnamespace yml {\n\n/** @addtogroup doc_emit\n *\n * @{\n */\n\n// fwd declarations\ntemplate<class Writer> class Emitter;\ntemplate<class OStream>\nusing EmitterOStream = Emitter<WriterOStream<OStream>>;\nusing EmitterFile = Emitter<WriterFile>;\nusing EmitterBuf  = Emitter<WriterBuf>;\n\nnamespace detail {\ninline bool is_set_(ConstNodeRef n) { return n.tree() && (n.id() != NONE); }\n}\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n/** Specifies the type of content to emit */\ntypedef enum {\n    EMIT_YAML = 0, ///< emit YAML\n    EMIT_JSON = 1  ///< emit JSON\n} EmitType_e;\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n/** A lightweight object containing options to be used when emitting. */\nstruct EmitOptions\n{\n    typedef enum : uint32_t {\n        DEFAULT_FLAGS = 0,\n        JSON_ERR_ON_TAG = 1 << 0,\n        JSON_ERR_ON_ANCHOR = 1 << 1,\n        _JSON_ERR_MASK = JSON_ERR_ON_TAG|JSON_ERR_ON_ANCHOR,\n    } EmitOptionFlags_e;\n\npublic:\n\n    /** @name option flags\n     *\n     * @{ */\n    C4_ALWAYS_INLINE EmitOptionFlags_e json_error_flags() const noexcept { return m_option_flags; }\n    EmitOptions& json_error_flags(EmitOptionFlags_e d) noexcept { m_option_flags = (EmitOptionFlags_e)(d & _JSON_ERR_MASK); return *this; }\n    /** @} */\n\npublic:\n\n    /** @name max depth for the emitted tree\n     *\n     * This makes the emitter fail when emitting trees exceeding the\n     * max_depth.\n     *\n     * @{ */\n    C4_ALWAYS_INLINE id_type max_depth() const noexcept { return m_max_depth; }\n    EmitOptions& max_depth(id_type d) noexcept { m_max_depth = d; return *this; }\n    static constexpr const id_type max_depth_default = 64;\n    /** @} */\n\npublic:\n\n    bool operator== (const EmitOptions& that) const noexcept\n    {\n        return m_max_depth == that.m_max_depth &&\n            m_option_flags == that.m_option_flags;\n    }\n\nprivate:\n\n    /** @cond dev */\n    id_type m_max_depth{max_depth_default};\n    EmitOptionFlags_e m_option_flags{DEFAULT_FLAGS};\n    /** @endcond */\n};\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n/** A stateful emitter, for use with a writer such as @ref WriterBuf,\n * @ref WriterFile, or @ref WriterOStream */\ntemplate<class Writer>\nclass Emitter : public Writer\n{\npublic:\n\n    /** Construct the emitter and its internal Writer state, using default emit options.\n     * @param args arguments to be forwarded to the constructor of the writer.\n     * */\n    template<class ...Args>\n    Emitter(Args &&...args) : Writer(std::forward<Args>(args)...), m_tree(), m_opts(), m_flow(false) {}\n\n    /** Construct the emitter and its internal Writer state.\n     *\n     * @param opts EmitOptions\n     * @param args arguments to be forwarded to the constructor of the writer.\n     * */\n    template<class ...Args>\n    Emitter(EmitOptions const& opts, Args &&...args) : Writer(std::forward<Args>(args)...), m_tree(), m_opts(opts), m_flow(false) {}\n\n    /** emit!\n     *\n     * When writing to a buffer, returns a substr of the emitted YAML.\n     * If the given buffer has insufficient space, the returned substr\n     * will be null and its size will be the needed space. Whatever\n     * the size of the buffer, it is guaranteed that no writes are\n     * done past its end.\n     *\n     * When writing to a file, the returned substr will be null, but its\n     * length will be set to the number of bytes written.\n     *\n     * @param type specify what to emit\n     * @param t the tree to emit\n     * @param id the id of the node to emit\n     * @param error_on_excess when true, an error is raised when the\n     *        output buffer is too small for the emitted YAML/JSON\n     * */\n    substr emit_as(EmitType_e type, Tree const& t, id_type id, bool error_on_excess);\n    /** emit starting at the root node */\n    substr emit_as(EmitType_e type, Tree const& t, bool error_on_excess=true)\n    {\n        if(t.empty())\n            return {};\n        return this->emit_as(type, t, t.root_id(), error_on_excess);\n    }\n    /** emit starting at the given node */\n    substr emit_as(EmitType_e type, ConstNodeRef const& n, bool error_on_excess=true)\n    {\n        if(!detail::is_set_(n))\n            return {};\n        _RYML_CB_CHECK(n.tree()->callbacks(), n.readable());\n        return this->emit_as(type, *n.tree(), n.id(), error_on_excess);\n    }\n\npublic:\n\n    /** get the emit options for this object */\n    EmitOptions const& options() const noexcept { return m_opts; }\n\n    /** set the max depth for emitted trees (to prevent a stack overflow) */\n    void max_depth(id_type max_depth) noexcept { m_opts.max_depth(max_depth); }\n    /** get the max depth for emitted trees (to prevent a stack overflow) */\n    id_type max_depth() const noexcept { return m_opts.max_depth(); }\n\nprivate:\n\n    Tree const* C4_RESTRICT m_tree;\n    EmitOptions m_opts;\n    bool m_flow;\n\nprivate:\n\n    void _emit_yaml(id_type id);\n    void _do_visit_flow_sl(id_type id, id_type depth, id_type ilevel=0);\n    void _do_visit_flow_ml(id_type id, id_type depth, id_type ilevel=0, id_type do_indent=1);\n    void _do_visit_block(id_type id, id_type depth, id_type ilevel=0, id_type do_indent=1);\n    void _do_visit_block_container(id_type id, id_type depth, id_type next_level, bool do_indent);\n    void _do_visit_json(id_type id, id_type depth);\n\nprivate:\n\n    void _write(NodeScalar const& C4_RESTRICT sc, NodeType flags, id_type level);\n    void _write_json(NodeScalar const& C4_RESTRICT sc, NodeType flags);\n\n    void _write_doc(id_type id);\n    void _write_scalar_json_dquo(csubstr s);\n    void _write_scalar_literal(csubstr s, id_type level, bool as_key);\n    void _write_scalar_folded(csubstr s, id_type level, bool as_key);\n    void _write_scalar_squo(csubstr s, id_type level);\n    void _write_scalar_dquo(csubstr s, id_type level);\n    void _write_scalar_plain(csubstr s, id_type level);\n\n    size_t _write_escaped_newlines(csubstr s, size_t i);\n    size_t _write_indented_block(csubstr s, size_t i, id_type level);\n\n    void _write_tag(csubstr tag)\n    {\n        if(!tag.begins_with('!'))\n            this->Writer::_do_write('!');\n        this->Writer::_do_write(tag);\n    }\n\n    enum : type_bits {\n        _keysc =  (KEY|KEYREF|KEYANCH|KEYQUO|KEY_STYLE) | ~(VAL|VALREF|VALANCH|VALQUO|VAL_STYLE) | CONTAINER_STYLE,\n        _valsc = ~(KEY|KEYREF|KEYANCH|KEYQUO|KEY_STYLE) |  (VAL|VALREF|VALANCH|VALQUO|VAL_STYLE) | CONTAINER_STYLE,\n        _keysc_json =  (KEY)  | ~(VAL),\n        _valsc_json = ~(KEY)  |  (VAL),\n    };\n\n    C4_ALWAYS_INLINE void _writek(id_type id, id_type level) { _write(m_tree->keysc(id), (m_tree->_p(id)->m_type.type & ~_valsc), level); }\n    C4_ALWAYS_INLINE void _writev(id_type id, id_type level) { _write(m_tree->valsc(id), (m_tree->_p(id)->m_type.type & ~_keysc), level); }\n\n    C4_ALWAYS_INLINE void _writek_json(id_type id) { _write_json(m_tree->keysc(id), m_tree->_p(id)->m_type.type & ~(VAL)); }\n    C4_ALWAYS_INLINE void _writev_json(id_type id) { _write_json(m_tree->valsc(id), m_tree->_p(id)->m_type.type & ~(KEY)); }\n\n    void _indent(id_type level, bool enabled)\n    {\n        if(enabled)\n            this->Writer::_do_write(' ', 2u * (size_t)level);\n    }\n    void _indent(id_type level)\n    {\n        if(!m_flow)\n            this->Writer::_do_write(' ', 2u * (size_t)level);\n    }\n};\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n/** @defgroup doc_emit_to_file Emit to file\n *\n * @{\n */\n\n\n// emit from tree and node id -----------------------\n\n/** (1) emit YAML to the given file, starting at the given node. A null\n * file defaults to stdout. Return the number of bytes written. */\ninline size_t emit_yaml(Tree const& t, id_type id, EmitOptions const& opts, FILE *f)\n{\n    EmitterFile em(opts, f);\n    return em.emit_as(EMIT_YAML, t, id, /*error_on_excess*/true).len;\n}\n/** (2) like (1), but use default emit options */\ninline size_t emit_yaml(Tree const& t, id_type id, FILE *f)\n{\n    EmitterFile em(f);\n    return em.emit_as(EMIT_YAML, t, id, /*error_on_excess*/true).len;\n}\n/** (1) emit JSON to the given file, starting at the given node. A null\n * file defaults to stdout.  Return the number of bytes written. */\ninline size_t emit_json(Tree const& t, id_type id, EmitOptions const& opts, FILE *f)\n{\n    EmitterFile em(opts, f);\n    return em.emit_as(EMIT_JSON, t, id, /*error_on_excess*/true).len;\n}\n/** (2) like (1), but use default emit options */\ninline size_t emit_json(Tree const& t, id_type id, FILE *f)\n{\n    EmitterFile em(f);\n    return em.emit_as(EMIT_JSON, t, id, /*error_on_excess*/true).len;\n}\n\n\n// emit from root -------------------------\n\n/** (1) emit YAML to the given file, starting at the root node. A null file defaults to stdout.\n * Return the number of bytes written. */\ninline size_t emit_yaml(Tree const& t, EmitOptions const& opts, FILE *f=nullptr)\n{\n    EmitterFile em(opts, f);\n    return em.emit_as(EMIT_YAML, t, /*error_on_excess*/true).len;\n}\n/** (2) like (1), but use default emit options */\ninline size_t emit_yaml(Tree const& t, FILE *f=nullptr)\n{\n    EmitterFile em(f);\n    return em.emit_as(EMIT_YAML, t, /*error_on_excess*/true).len;\n}\n/** (1) emit JSON to the given file. A null file defaults to stdout.\n * Return the number of bytes written. */\ninline size_t emit_json(Tree const& t, EmitOptions const& opts, FILE *f=nullptr)\n{\n    EmitterFile em(opts, f);\n    return em.emit_as(EMIT_JSON, t, /*error_on_excess*/true).len;\n}\n/** (2) like (1), but use default emit options */\ninline size_t emit_json(Tree const& t, FILE *f=nullptr)\n{\n    EmitterFile em(f);\n    return em.emit_as(EMIT_JSON, t, /*error_on_excess*/true).len;\n}\n\n\n// emit from ConstNodeRef ------------------------\n\n/** (1) emit YAML to the given file. A null file defaults to stdout.\n * Return the number of bytes written. */\ninline size_t emit_yaml(ConstNodeRef const& r, EmitOptions const& opts, FILE *f=nullptr)\n{\n    if(!detail::is_set_(r))\n        return {};\n    EmitterFile em(opts, f);\n    return em.emit_as(EMIT_YAML, r, /*error_on_excess*/true).len;\n}\n/** (2) like (1), but use default emit options */\ninline size_t emit_yaml(ConstNodeRef const& r, FILE *f=nullptr)\n{\n    if(!detail::is_set_(r))\n        return {};\n    EmitterFile em(f);\n    return em.emit_as(EMIT_YAML, r, /*error_on_excess*/true).len;\n}\n/** (1) emit JSON to the given file. A null file defaults to stdout.\n * Return the number of bytes written. */\ninline size_t emit_json(ConstNodeRef const& r, EmitOptions const& opts, FILE *f=nullptr)\n{\n    if(!detail::is_set_(r))\n        return {};\n    EmitterFile em(opts, f);\n    return em.emit_as(EMIT_JSON, r, /*error_on_excess*/true).len;\n}\n/** (2) like (1), but use default emit options */\ninline size_t emit_json(ConstNodeRef const& r, FILE *f=nullptr)\n{\n    if(!detail::is_set_(r))\n        return {};\n    EmitterFile em(f);\n    return em.emit_as(EMIT_JSON, r, /*error_on_excess*/true).len;\n}\n\n/** @} */\n\n\n//-----------------------------------------------------------------------------\n\n/** @defgroup doc_emit_to_ostream Emit to an STL-like ostream\n *\n * @{\n */\n\n/** emit YAML to an STL-like ostream */\ntemplate<class OStream>\ninline OStream& operator<< (OStream& s, Tree const& t)\n{\n    EmitterOStream<OStream> em(s);\n    em.emit_as(EMIT_YAML, t);\n    return s;\n}\n\n/** emit YAML to an STL-like ostream\n * @overload */\ntemplate<class OStream>\ninline OStream& operator<< (OStream& s, ConstNodeRef const& n)\n{\n    if(!detail::is_set_(n))\n        return s;\n    EmitterOStream<OStream> em(s);\n    em.emit_as(EMIT_YAML, n);\n    return s;\n}\n\n/** mark a tree or node to be emitted as yaml when using @ref\n * operator<<, with options. For example:\n *\n * ```cpp\n * Tree t = parse_in_arena(\"{foo: bar}\");\n * std::cout << t; // emits YAML\n * std::cout << as_yaml(t); // emits YAML, same as above\n * std::cout << as_yaml(t, EmitOptions().max_depth(10)); // emits JSON with a max tree depth\n * ```\n *\n * @see @ref operator<< */\nstruct as_json\n{\n    Tree const* tree;\n    size_t node;\n    EmitOptions options;\n    as_json(Tree const& t, EmitOptions const& opts={}) : tree(&t), node(t.empty() ? NONE : t.root_id()), options(opts)  {}\n    as_json(Tree const& t, size_t id, EmitOptions const& opts={}) : tree(&t), node(id), options(opts)  {}\n    as_json(ConstNodeRef const& n, EmitOptions const& opts={}) : tree(n.tree()), node(n.id()), options(opts) {}\n};\n\n/** mark a tree or node to be emitted as yaml when using @ref\n * operator<< . For example:\n *\n * ```cpp\n * Tree t = parse_in_arena(\"{foo: bar}\");\n * std::cout << t; // emits YAML\n * std::cout << as_json(t); // emits JSON\n * std::cout << as_json(t, EmitOptions().max_depth(10)); // emits JSON with a max tree depth\n * ```\n *\n * @see @ref operator<< */\nstruct as_yaml\n{\n    Tree const* tree;\n    size_t node;\n    EmitOptions options;\n    as_yaml(Tree const& t, EmitOptions const& opts={}) : tree(&t), node(t.empty() ? NONE : t.root_id()), options(opts)  {}\n    as_yaml(Tree const& t, size_t id, EmitOptions const& opts={}) : tree(&t), node(id), options(opts)  {}\n    as_yaml(ConstNodeRef const& n, EmitOptions const& opts={}) : tree(n.tree()), node(n.id()), options(opts) {}\n};\n\n/** emit json to an STL-like stream */\ntemplate<class OStream>\ninline OStream& operator<< (OStream& s, as_json const& j)\n{\n    if(!j.tree || j.node == NONE)\n        return s;\n    EmitterOStream<OStream> em(j.options, s);\n    em.emit_as(EMIT_JSON, *j.tree, j.node, true);\n    return s;\n}\n\n/** emit yaml to an STL-like stream */\ntemplate<class OStream>\ninline OStream& operator<< (OStream& s, as_yaml const& y)\n{\n    if(!y.tree || y.node == NONE)\n        return s;\n    EmitterOStream<OStream> em(y.options, s);\n    em.emit_as(EMIT_YAML, *y.tree, y.node, true);\n    return s;\n}\n\n/** @} */\n\n\n//-----------------------------------------------------------------------------\n\n/** @defgroup doc_emit_to_buffer Emit to memory buffer\n *\n * @{\n */\n\n// emit from tree and node id -----------------------\n\n/** (1) emit YAML to the given buffer. Return a substr trimmed to the emitted YAML.\n * @param t the tree to emit.\n * @param id the node where to start emitting.\n * @param opts emit options.\n * @param buf the output buffer.\n * @param opts emit options.\n * @param error_on_excess Raise an error if the space in the buffer is insufficient.\n * @return a substr trimmed to the result in the output buffer. If the buffer is\n * insufficient (when error_on_excess is false), the string pointer of the\n * result will be set to null, and the length will report the required buffer size. */\ninline substr emit_yaml(Tree const& t, id_type id, EmitOptions const& opts, substr buf, bool error_on_excess=true)\n{\n    EmitterBuf em(opts, buf);\n    return em.emit_as(EMIT_YAML, t, id, error_on_excess);\n}\n/** (2) like (1), but use default emit options */\ninline substr emit_yaml(Tree const& t, id_type id, substr buf, bool error_on_excess=true)\n{\n    EmitterBuf em(buf);\n    return em.emit_as(EMIT_YAML, t, id, error_on_excess);\n}\n/** (1) emit JSON to the given buffer. Return a substr trimmed to the emitted JSON.\n * @param t the tree to emit.\n * @param id the node where to start emitting.\n * @param opts emit options.\n * @param buf the output buffer.\n * @param opts emit options.\n * @param error_on_excess Raise an error if the space in the buffer is insufficient.\n * @return a substr trimmed to the result in the output buffer. If the buffer is\n * insufficient (when error_on_excess is false), the string pointer of the\n * result will be set to null, and the length will report the required buffer size. */\ninline substr emit_json(Tree const& t, id_type id, EmitOptions const& opts, substr buf, bool error_on_excess=true)\n{\n    EmitterBuf em(opts, buf);\n    return em.emit_as(EMIT_JSON, t, id, error_on_excess);\n}\n/** (2) like (1), but use default emit options */\ninline substr emit_json(Tree const& t, id_type id, substr buf, bool error_on_excess=true)\n{\n    EmitterBuf em(buf);\n    return em.emit_as(EMIT_JSON, t, id, error_on_excess);\n}\n\n\n// emit from root -------------------------\n\n/** (1) emit YAML to the given buffer. Return a substr trimmed to the emitted YAML.\n * @param t the tree; will be emitted from the root node.\n * @param buf the output buffer.\n * @param error_on_excess Raise an error if the space in the buffer is insufficient.\n * @return a substr trimmed to the result in the output buffer. If the buffer is\n * insufficient (when error_on_excess is false), the string pointer of the\n * result will be set to null, and the length will report the required buffer size. */\ninline substr emit_yaml(Tree const& t, EmitOptions const& opts, substr buf, bool error_on_excess=true)\n{\n    EmitterBuf em(opts, buf);\n    return em.emit_as(EMIT_YAML, t, error_on_excess);\n}\n/** (2) like (1), but use default emit options */\ninline substr emit_yaml(Tree const& t, substr buf, bool error_on_excess=true)\n{\n    EmitterBuf em(buf);\n    return em.emit_as(EMIT_YAML, t, error_on_excess);\n}\n/** (1) emit JSON to the given buffer. Return a substr trimmed to the emitted JSON.\n * @param t the tree; will be emitted from the root node.\n * @param buf the output buffer.\n * @param error_on_excess Raise an error if the space in the buffer is insufficient.\n * @return a substr trimmed to the result in the output buffer. If the buffer is\n * insufficient (when error_on_excess is false), the string pointer of the\n * result will be set to null, and the length will report the required buffer size. */\ninline substr emit_json(Tree const& t, EmitOptions const& opts, substr buf, bool error_on_excess=true)\n{\n    EmitterBuf em(opts, buf);\n    return em.emit_as(EMIT_JSON, t, error_on_excess);\n}\n/** (2) like (1), but use default emit options */\ninline substr emit_json(Tree const& t, substr buf, bool error_on_excess=true)\n{\n    EmitterBuf em(buf);\n    return em.emit_as(EMIT_JSON, t, error_on_excess);\n}\n\n\n// emit from ConstNodeRef ------------------------\n\n/** (1) emit YAML to the given buffer. Return a substr trimmed to the emitted YAML.\n * @param r the starting node.\n * @param buf the output buffer.\n * @param opts emit options.\n * @param error_on_excess Raise an error if the space in the buffer is insufficient.\n * @return a substr trimmed to the result in the output buffer. If the buffer is\n * insufficient (when error_on_excess is false), the string pointer of the\n * result will be set to null, and the length will report the required buffer size. */\ninline substr emit_yaml(ConstNodeRef const& r, EmitOptions const& opts, substr buf, bool error_on_excess=true)\n{\n    if(!detail::is_set_(r))\n        return {};\n    EmitterBuf em(opts, buf);\n    return em.emit_as(EMIT_YAML, r, error_on_excess);\n}\n/** (2) like (1), but use default emit options */\ninline substr emit_yaml(ConstNodeRef const& r, substr buf, bool error_on_excess=true)\n{\n    if(!detail::is_set_(r))\n        return {};\n    EmitterBuf em(buf);\n    return em.emit_as(EMIT_YAML, r, error_on_excess);\n}\n/** (1) emit JSON to the given buffer. Return a substr trimmed to the emitted JSON.\n * @param r the starting node.\n * @param buf the output buffer.\n * @param opts emit options.\n * @param error_on_excess Raise an error if the space in the buffer is insufficient.\n * @return a substr trimmed to the result in the output buffer. If the buffer is\n * insufficient (when error_on_excess is false), the string pointer of the\n * result will be set to null, and the length will report the required buffer size. */\ninline substr emit_json(ConstNodeRef const& r, EmitOptions const& opts, substr buf, bool error_on_excess=true)\n{\n    if(!detail::is_set_(r))\n        return {};\n    EmitterBuf em(opts, buf);\n    return em.emit_as(EMIT_JSON, r, error_on_excess);\n}\n/** (2) like (1), but use default emit options */\ninline substr emit_json(ConstNodeRef const& r, substr buf, bool error_on_excess=true)\n{\n    if(!detail::is_set_(r))\n        return {};\n    EmitterBuf em(buf);\n    return em.emit_as(EMIT_JSON, r, error_on_excess);\n}\n\n\n//-----------------------------------------------------------------------------\n\n/** @defgroup doc_emit_to_container Emit to resizeable container\n *\n * @{\n */\n\n// emit from tree and node id ---------------------------\n\n/** (1) emit+resize: emit YAML to the given `std::string`/`std::vector`-like\n * container, resizing it as needed to fit the emitted YAML. If @p append is\n * set to true, the emitted YAML is appended at the end of the container.\n *\n * @return a substr trimmed to the emitted YAML (excluding the initial contents, when appending) */\ntemplate<class CharOwningContainer>\nsubstr emitrs_yaml(Tree const& t, id_type id, EmitOptions const& opts, CharOwningContainer * cont, bool append=false)\n{\n    size_t startpos = append ? cont->size() : 0u;\n    cont->resize(cont->capacity()); // otherwise the first emit would be certain to fail\n    substr buf = to_substr(*cont).sub(startpos);\n    substr ret = emit_yaml(t, id, opts, buf, /*error_on_excess*/false);\n    if(ret.str == nullptr && ret.len > 0)\n    {\n        cont->resize(startpos + ret.len);\n        buf = to_substr(*cont).sub(startpos);\n        ret = emit_yaml(t, id, opts, buf, /*error_on_excess*/true);\n    }\n    else\n    {\n        cont->resize(startpos + ret.len);\n    }\n    return ret;\n}\n/** (2) like (1), but use default emit options */\ntemplate<class CharOwningContainer>\nsubstr emitrs_yaml(Tree const& t, id_type id, CharOwningContainer * cont, bool append=false)\n{\n    return emitrs_yaml(t, id, EmitOptions{}, cont, append);\n}\n/** (1) emit+resize: emit JSON to the given `std::string`/`std::vector`-like\n * container, resizing it as needed to fit the emitted JSON. If @p append is\n * set to true, the emitted YAML is appended at the end of the container.\n *\n * @return a substr trimmed to the emitted JSON (excluding the initial contents, when appending) */\ntemplate<class CharOwningContainer>\nsubstr emitrs_json(Tree const& t, id_type id, EmitOptions const& opts, CharOwningContainer * cont, bool append=false)\n{\n    const size_t startpos = append ? cont->size() : 0u;\n    cont->resize(cont->capacity()); // otherwise the first emit would be certain to fail\n    substr buf = to_substr(*cont).sub(startpos);\n    EmitterBuf em(opts, buf);\n    substr ret = emit_json(t, id, opts, buf, /*error_on_excess*/false);\n    if(ret.str == nullptr && ret.len > 0)\n    {\n        cont->resize(startpos + ret.len);\n        buf = to_substr(*cont).sub(startpos);\n        ret = emit_json(t, id, opts, buf, /*error_on_excess*/true);\n    }\n    else\n    {\n        cont->resize(startpos + ret.len);\n    }\n    return ret;\n}\n/** (2) like (1), but use default emit options */\ntemplate<class CharOwningContainer>\nsubstr emitrs_json(Tree const& t, id_type id, CharOwningContainer * cont, bool append=false)\n{\n    return emitrs_json(t, id, EmitOptions{}, cont, append);\n}\n\n\n/** (3) emit+resize: YAML to a newly-created `std::string`/`std::vector`-like container. */\ntemplate<class CharOwningContainer>\nCharOwningContainer emitrs_yaml(Tree const& t, id_type id, EmitOptions const& opts={})\n{\n    CharOwningContainer c;\n    emitrs_yaml(t, id, opts, &c);\n    return c;\n}\n/** (3) emit+resize: JSON to a newly-created `std::string`/`std::vector`-like container. */\ntemplate<class CharOwningContainer>\nCharOwningContainer emitrs_json(Tree const& t, id_type id, EmitOptions const& opts={})\n{\n    CharOwningContainer c;\n    emitrs_json(t, id, opts, &c);\n    return c;\n}\n\n\n// emit from root -------------------------\n\n/** (1) emit+resize: YAML to the given `std::string`/`std::vector`-like\n * container, resizing it as needed to fit the emitted YAML.\n * @return a substr trimmed to the new emitted contents. */\ntemplate<class CharOwningContainer>\nsubstr emitrs_yaml(Tree const& t, EmitOptions const& opts, CharOwningContainer * cont, bool append=false)\n{\n    if(t.empty())\n        return {};\n    return emitrs_yaml(t, t.root_id(), opts, cont, append);\n}\n/** (2) like (1), but use default emit options */\ntemplate<class CharOwningContainer>\nsubstr emitrs_yaml(Tree const& t, CharOwningContainer * cont, bool append=false)\n{\n    if(t.empty())\n        return {};\n    return emitrs_yaml(t, t.root_id(), EmitOptions{}, cont, append);\n}\n/** (1) emit+resize: JSON to the given `std::string`/`std::vector`-like\n * container, resizing it as needed to fit the emitted JSON.\n * @return a substr trimmed to the new emitted contents. */\ntemplate<class CharOwningContainer>\nsubstr emitrs_json(Tree const& t, EmitOptions const& opts, CharOwningContainer * cont, bool append=false)\n{\n    if(t.empty())\n        return {};\n    return emitrs_json(t, t.root_id(), opts, cont, append);\n}\n/** (2) like (1), but use default emit options */\ntemplate<class CharOwningContainer>\nsubstr emitrs_json(Tree const& t, CharOwningContainer * cont, bool append=false)\n{\n    if(t.empty())\n        return {};\n    return emitrs_json(t, t.root_id(), EmitOptions{}, cont, append);\n}\n\n\n/** (3) emit+resize: YAML to a newly-created `std::string`/`std::vector`-like container. */\ntemplate<class CharOwningContainer>\nCharOwningContainer emitrs_yaml(Tree const& t, EmitOptions const& opts={})\n{\n    CharOwningContainer c;\n    if(t.empty())\n        return c;\n    emitrs_yaml(t, t.root_id(), opts, &c);\n    return c;\n}\n/** (3) emit+resize: JSON to a newly-created `std::string`/`std::vector`-like container. */\ntemplate<class CharOwningContainer>\nCharOwningContainer emitrs_json(Tree const& t, EmitOptions const& opts={})\n{\n    CharOwningContainer c;\n    if(t.empty())\n        return c;\n    emitrs_json(t, t.root_id(), opts, &c);\n    return c;\n}\n\n\n// emit from ConstNodeRef ------------------------\n\n\n/** (1) emit+resize: YAML to the given `std::string`/`std::vector`-like container,\n * resizing it as needed to fit the emitted YAML.\n * @return a substr trimmed to the new emitted contents */\ntemplate<class CharOwningContainer>\nsubstr emitrs_yaml(ConstNodeRef const& n, EmitOptions const& opts, CharOwningContainer * cont, bool append=false)\n{\n    if(!detail::is_set_(n))\n        return {};\n    _RYML_CB_CHECK(n.tree()->callbacks(), n.readable());\n    return emitrs_yaml(*n.tree(), n.id(), opts, cont, append);\n}\n/** (2) like (1), but use default emit options */\ntemplate<class CharOwningContainer>\nsubstr emitrs_yaml(ConstNodeRef const& n, CharOwningContainer * cont, bool append=false)\n{\n    if(!detail::is_set_(n))\n        return {};\n    _RYML_CB_CHECK(n.tree()->callbacks(), n.readable());\n    return emitrs_yaml(*n.tree(), n.id(), EmitOptions{}, cont, append);\n}\n/** (1) emit+resize: JSON to the given `std::string`/`std::vector`-like container,\n * resizing it as needed to fit the emitted JSON.\n * @return a substr trimmed to the new emitted contents */\ntemplate<class CharOwningContainer>\nsubstr emitrs_json(ConstNodeRef const& n, EmitOptions const& opts, CharOwningContainer * cont, bool append=false)\n{\n    if(!detail::is_set_(n))\n        return {};\n    _RYML_CB_CHECK(n.tree()->callbacks(), n.readable());\n    return emitrs_json(*n.tree(), n.id(), opts, cont, append);\n}\n/** (2) like (1), but use default emit options */\ntemplate<class CharOwningContainer>\nsubstr emitrs_json(ConstNodeRef const& n, CharOwningContainer * cont, bool append=false)\n{\n    if(!detail::is_set_(n))\n        return {};\n    _RYML_CB_CHECK(n.tree()->callbacks(), n.readable());\n    return emitrs_json(*n.tree(), n.id(), EmitOptions{}, cont, append);\n}\n\n\n/** (3) emit+resize: YAML to a newly-created `std::string`/`std::vector`-like container. */\ntemplate<class CharOwningContainer>\nCharOwningContainer emitrs_yaml(ConstNodeRef const& n, EmitOptions const& opts={})\n{\n    if(!detail::is_set_(n))\n        return {};\n    _RYML_CB_CHECK(n.tree()->callbacks(), n.readable());\n    CharOwningContainer c;\n    emitrs_yaml(*n.tree(), n.id(), opts, &c);\n    return c;\n}\n/** (3) emit+resize: JSON to a newly-created `std::string`/`std::vector`-like container. */\ntemplate<class CharOwningContainer>\nCharOwningContainer emitrs_json(ConstNodeRef const& n, EmitOptions const& opts={})\n{\n    if(!detail::is_set_(n))\n        return {};\n    _RYML_CB_CHECK(n.tree()->callbacks(), n.readable());\n    CharOwningContainer c;\n    emitrs_json(*n.tree(), n.id(), opts, &c);\n    return c;\n}\n\n\n/** @} */\n\n\n//-----------------------------------------------------------------------------\n\n/** @cond dev */\n\nRYML_DEPRECATE_EMIT inline size_t emit(Tree const& t, id_type id, FILE *f)\n{\n    return emit_yaml(t, id, f);\n}\nRYML_DEPRECATE_EMIT inline size_t emit(Tree const& t, FILE *f=nullptr)\n{\n    return emit_yaml(t, f);\n}\nRYML_DEPRECATE_EMIT inline size_t emit(ConstNodeRef const& r, FILE *f=nullptr)\n{\n    return emit_yaml(r, f);\n}\n\nRYML_DEPRECATE_EMIT inline substr emit(Tree const& t, id_type id, substr buf, bool error_on_excess=true)\n{\n    return emit_yaml(t, id, buf, error_on_excess);\n}\nRYML_DEPRECATE_EMIT inline substr emit(Tree const& t, substr buf, bool error_on_excess=true)\n{\n    return emit_yaml(t, buf, error_on_excess);\n}\nRYML_DEPRECATE_EMIT inline substr emit(ConstNodeRef const& r, substr buf, bool error_on_excess=true)\n{\n    return emit_yaml(r, buf, error_on_excess);\n}\n\ntemplate<class CharOwningContainer>\nRYML_DEPRECATE_EMITRS substr emitrs(Tree const& t, id_type id, CharOwningContainer * cont)\n{\n    return emitrs_yaml(t, id, cont);\n}\ntemplate<class CharOwningContainer>\nRYML_DEPRECATE_EMITRS CharOwningContainer emitrs(Tree const& t, id_type id)\n{\n    return emitrs_yaml<CharOwningContainer>(t, id);\n}\ntemplate<class CharOwningContainer>\nRYML_DEPRECATE_EMITRS substr emitrs(Tree const& t, CharOwningContainer * cont)\n{\n    return emitrs_yaml(t, cont);\n}\ntemplate<class CharOwningContainer>\nRYML_DEPRECATE_EMITRS CharOwningContainer emitrs(Tree const& t)\n{\n    return emitrs_yaml<CharOwningContainer>(t);\n}\ntemplate<class CharOwningContainer>\nRYML_DEPRECATE_EMITRS substr emitrs(ConstNodeRef const& n, CharOwningContainer * cont)\n{\n    return emitrs_yaml(n, cont);\n}\ntemplate<class CharOwningContainer>\nRYML_DEPRECATE_EMITRS CharOwningContainer emitrs(ConstNodeRef const& n)\n{\n    return emitrs_yaml<CharOwningContainer>(n);\n}\n/** @endcond */\n\n\n} // namespace yml\n} // namespace c4\n\nC4_SUPPRESS_WARNING_GCC_CLANG_POP\n\n#undef RYML_DEPRECATE_EMIT\n#undef RYML_DEPRECATE_EMITRS\n\n#include \"c4/yml/emit.def.hpp\"\n\n#endif /* _C4_YML_EMIT_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/yml/event_handler_stack.hpp",
    "content": "#ifndef _C4_YML_EVENT_HANDLER_STACK_HPP_\n#define _C4_YML_EVENT_HANDLER_STACK_HPP_\n\n#ifndef _C4_YML_DETAIL_STACK_HPP_\n#include \"c4/yml/detail/stack.hpp\"\n#endif\n\n#ifndef _C4_YML_DETAIL_PARSER_DBG_HPP_\n#include \"c4/yml/detail/parser_dbg.hpp\"\n#endif\n\n#ifndef _C4_YML_PARSER_STATE_HPP_\n#include \"c4/yml/parser_state.hpp\"\n#endif\n\n#ifdef RYML_DBG\n#ifndef _C4_YML_DETAIL_PRINT_HPP_\n#include \"c4/yml/detail/print.hpp\"\n#endif\n#endif\n\nnamespace c4 {\nnamespace yml {\n\n/** @addtogroup doc_event_handlers\n * @{ */\n\nnamespace detail {\nusing pfn_relocate_arena = void (*)(void*, csubstr prev_arena, substr next_arena);\n} // detail\n\n/** Use this class a base of implementations of event handler to\n * simplify the stack logic. */\ntemplate<class HandlerImpl, class HandlerState>\nstruct EventHandlerStack\n{\n    static_assert(std::is_base_of<ParserState, HandlerState>::value,\n                  \"ParserState must be a base of HandlerState\");\n\n    using state = HandlerState;\n    using pfn_relocate_arena = detail::pfn_relocate_arena;\n\npublic:\n\n    detail::stack<state> m_stack;\n    state *C4_RESTRICT   m_curr;    ///< current stack level: top of the stack. cached here for easier access.\n    state *C4_RESTRICT   m_parent;  ///< parent of the current stack level.\n    pfn_relocate_arena   m_relocate_arena; ///< callback when the arena gets relocated\n    void *               m_relocate_arena_data;\n\nprotected:\n\n    EventHandlerStack() : m_stack(), m_curr(), m_parent(), m_relocate_arena(), m_relocate_arena_data() {}\n    EventHandlerStack(Callbacks const& cb) : m_stack(cb), m_curr(), m_parent(), m_relocate_arena(), m_relocate_arena_data() {}\n\nprotected:\n\n    void _stack_start_parse(const char *filename, pfn_relocate_arena relocate_arena, void *relocate_arena_data)\n    {\n        _RYML_CB_ASSERT(m_stack.m_callbacks, m_curr != nullptr);\n        _RYML_CB_ASSERT(m_stack.m_callbacks, relocate_arena != nullptr);\n        _RYML_CB_ASSERT(m_stack.m_callbacks, relocate_arena_data != nullptr);\n        m_curr->start_parse(filename, m_curr->node_id);\n        m_relocate_arena = relocate_arena;\n        m_relocate_arena_data = relocate_arena_data;\n    }\n\n    void _stack_finish_parse()\n    {\n    }\n\nprotected:\n\n    void _stack_reset_root()\n    {\n        m_stack.clear();\n        m_stack.push({});\n        m_parent = nullptr;\n        m_curr = &m_stack.top();\n    }\n\n    void _stack_reset_non_root()\n    {\n        m_stack.clear();\n        m_stack.push({}); // parent\n        m_stack.push({}); // node\n        m_parent = &m_stack.top(1);\n        m_curr = &m_stack.top();\n    }\n\n    void _stack_push()\n    {\n        m_stack.push_top();\n        m_parent = &m_stack.top(1); // don't use m_curr. watch out for relocations inside the prev push\n        m_curr = &m_stack.top();\n        m_curr->reset_after_push();\n    }\n\n    void _stack_pop()\n    {\n        _RYML_CB_ASSERT(m_stack.m_callbacks, m_parent);\n        _RYML_CB_ASSERT(m_stack.m_callbacks, m_stack.size() > 1);\n        m_parent->reset_before_pop(*m_curr);\n        m_stack.pop();\n        m_parent = m_stack.size() > 1 ? &m_stack.top(1) : nullptr;\n        m_curr = &m_stack.top();\n        #ifdef RYML_DBG\n        if(m_parent)\n            _c4dbgpf(\"popped! top is now node={} (parent={})\", m_curr->node_id, m_parent->node_id);\n        else\n            _c4dbgpf(\"popped! top is now node={} @ ROOT\", m_curr->node_id);\n        #endif\n    }\n\nprotected:\n\n    // undefined at the end\n    #define _has_any_(bits) (static_cast<HandlerImpl const* C4_RESTRICT>(this)->template _has_any__<bits>())\n\n    bool _stack_should_push_on_begin_doc() const\n    {\n        const bool is_root = (m_stack.size() == 1u);\n        return is_root && (_has_any_(DOC|VAL|MAP|SEQ) || m_curr->has_children);\n    }\n\n    bool _stack_should_pop_on_end_doc() const\n    {\n        const bool is_root = (m_stack.size() == 1u);\n        return !is_root && _has_any_(DOC);\n    }\n\nprotected:\n\n    void _stack_relocate_to_new_arena(csubstr prev, substr curr)\n    {\n        for(state &st : m_stack)\n        {\n            if(st.line_contents.rem.is_sub(prev))\n                st.line_contents.rem = _stack_relocate_to_new_arena(st.line_contents.rem, prev, curr);\n            if(st.line_contents.full.is_sub(prev))\n                st.line_contents.full = _stack_relocate_to_new_arena(st.line_contents.full, prev, curr);\n            if(st.line_contents.stripped.is_sub(prev))\n                st.line_contents.stripped = _stack_relocate_to_new_arena(st.line_contents.stripped, prev, curr);\n        }\n        _RYML_CB_ASSERT(m_stack.m_callbacks, m_relocate_arena != nullptr);\n        _RYML_CB_ASSERT(m_stack.m_callbacks, m_relocate_arena_data != nullptr);\n        m_relocate_arena(m_relocate_arena_data, prev, curr);\n    }\n\n    substr _stack_relocate_to_new_arena(csubstr s, csubstr prev, substr curr)\n    {\n        _RYML_CB_ASSERT(m_stack.m_callbacks, prev.is_super(s));\n        auto pos = s.str - prev.str;\n        substr out = {curr.str + pos, s.len};\n        _RYML_CB_ASSERT(m_stack.m_callbacks, curr.is_super(out));\n        return out;\n    }\n\npublic:\n\n    /** Check whether the current parse tokens are trailing on the\n     * previous doc, and raise an error if they are. This function is\n     * called by the parse engine (not the event handler) before a doc\n     * is started. */\n    void check_trailing_doc_token() const\n    {\n        const bool is_root = (m_stack.size() == 1u);\n        const bool isndoc = (m_curr->flags & NDOC) != 0;\n        const bool suspicious = _has_any_(MAP|SEQ|VAL);\n        _c4dbgpf(\"target={} isroot={} suspicious={} ndoc={}\", m_curr->node_id, is_root, suspicious, isndoc);\n        if((is_root || _has_any_(DOC)) && suspicious && !isndoc)\n            _RYML_CB_ERR_(m_stack.m_callbacks, \"parse error\", m_curr->pos);\n    }\n\nprotected:\n\n    #undef _has_any_\n\n};\n\n/** @} */\n\n} // namespace yml\n} // namespace c4\n\n#endif /* _C4_YML_EVENT_HANDLER_STACK_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/yml/event_handler_tree.hpp",
    "content": "#ifndef _C4_YML_EVENT_HANDLER_TREE_HPP_\n#define _C4_YML_EVENT_HANDLER_TREE_HPP_\n\n#ifndef _C4_YML_TREE_HPP_\n#include \"c4/yml/tree.hpp\"\n#endif\n\n#ifndef _C4_YML_EVENT_HANDLER_STACK_HPP_\n#include \"c4/yml/event_handler_stack.hpp\"\n#endif\n\nC4_SUPPRESS_WARNING_MSVC_WITH_PUSH(4702) // unreachable code\n\nnamespace c4 {\nnamespace yml {\n\n/** @addtogroup doc_event_handlers\n * @{ */\n\n\n/** The stack state needed specifically by @ref EventHandlerTree */\nstruct EventHandlerTreeState : public ParserState\n{\n    NodeData *tr_data;\n};\n\n\n/** The event handler to create a ryml @ref Tree. See the\n * documentation for @ref doc_event_handlers, which has important\n * notes about the event model used by rapidyaml. */\nstruct EventHandlerTree : public EventHandlerStack<EventHandlerTree, EventHandlerTreeState>\n{\n\n    /** @name types\n     * @{ */\n\n    using state = EventHandlerTreeState;\n\n    /** @} */\n\npublic:\n\n    /** @cond dev */\n    Tree *C4_RESTRICT m_tree;\n    id_type m_id;\n    size_t m_num_directives;\n    bool m_yaml_directive;\n\n    #if RYML_DBG\n    #define _enable_(bits) _enable__<bits>(); _c4dbgpf(\"node[{}]: enable {}\", m_curr->node_id, #bits)\n    #define _disable_(bits) _disable__<bits>(); _c4dbgpf(\"node[{}]: disable {}\", m_curr->node_id, #bits)\n    #else\n    #define _enable_(bits) _enable__<bits>()\n    #define _disable_(bits) _disable__<bits>()\n    #endif\n    #define _has_any_(bits) _has_any__<bits>()\n    /** @endcond */\n\npublic:\n\n    /** @name construction and resetting\n     * @{ */\n\n    EventHandlerTree() : EventHandlerStack(), m_tree(), m_id(NONE), m_num_directives(), m_yaml_directive() {}\n    EventHandlerTree(Callbacks const& cb) : EventHandlerStack(cb), m_tree(), m_id(NONE), m_num_directives(), m_yaml_directive() {}\n    EventHandlerTree(Tree *tree, id_type id) : EventHandlerStack(tree->callbacks()), m_tree(tree), m_id(id), m_num_directives(), m_yaml_directive()\n    {\n        reset(tree, id);\n    }\n\n    void reset(Tree *tree, id_type id)\n    {\n        if(C4_UNLIKELY(!tree))\n            _RYML_CB_ERR(m_stack.m_callbacks, \"null tree\");\n        if(C4_UNLIKELY(id >= tree->capacity()))\n            _RYML_CB_ERR(tree->callbacks(), \"invalid node\");\n        if(C4_UNLIKELY(!tree->is_root(id)))\n            if(C4_UNLIKELY(tree->is_map(tree->parent(id))))\n                if(C4_UNLIKELY(!tree->has_key(id)))\n                    _RYML_CB_ERR(tree->callbacks(), \"destination node belongs to a map and has no key\");\n        m_tree = tree;\n        m_id = id;\n        if(m_tree->is_root(id))\n        {\n            _stack_reset_root();\n            _reset_parser_state(m_curr, id, m_tree->root_id());\n        }\n        else\n        {\n            _stack_reset_non_root();\n            _reset_parser_state(m_parent, id, m_tree->parent(id));\n            _reset_parser_state(m_curr, id, id);\n        }\n        m_num_directives = 0;\n        m_yaml_directive = false;\n    }\n\n    /** @} */\n\npublic:\n\n    /** @name parse events\n     * @{ */\n\n    void start_parse(const char* filename, detail::pfn_relocate_arena relocate_arena, void *relocate_arena_data)\n    {\n        _RYML_CB_ASSERT(m_stack.m_callbacks, m_tree != nullptr);\n        this->_stack_start_parse(filename, relocate_arena, relocate_arena_data);\n    }\n\n    void finish_parse()\n    {\n        _RYML_CB_ASSERT(m_stack.m_callbacks, m_tree != nullptr);\n        if(m_num_directives && !m_tree->is_stream(m_tree->root_id()))\n            _RYML_CB_ERR_(m_stack.m_callbacks, \"directives cannot be used without a document\", {});\n        this->_stack_finish_parse();\n        /* This pointer is temporary. Remember that:\n         *\n         * - this handler object may be held by the user\n         * - it may be used with a temporary tree inside the parse function\n         * - when the parse function returns the temporary tree, its address\n         *   will change\n         *\n         * As a result, the user could try to read the tree from m_tree, and\n         * end up reading the stale temporary object.\n         *\n         * So it is better to clear it here; then the user will get an obvious\n         * segfault if reading from m_tree. */\n        m_tree = nullptr;\n    }\n\n    void cancel_parse()\n    {\n        m_tree = nullptr;\n    }\n\n    /** @} */\n\npublic:\n\n    /** @name YAML stream events */\n    /** @{ */\n\n    C4_ALWAYS_INLINE void begin_stream() const noexcept { /*nothing to do*/ }\n\n    C4_ALWAYS_INLINE void end_stream() const noexcept { /*nothing to do*/ }\n\n    /** @} */\n\npublic:\n\n    /** @name YAML document events */\n    /** @{ */\n\n    /** implicit doc start (without ---) */\n    void begin_doc()\n    {\n        _c4dbgp(\"begin_doc\");\n        if(_stack_should_push_on_begin_doc())\n        {\n            _c4dbgp(\"push!\");\n            _set_root_as_stream();\n            _push();\n            _enable_(DOC);\n        }\n    }\n    /** implicit doc end (without ...) */\n    void end_doc()\n    {\n        _c4dbgp(\"end_doc\");\n        if(_stack_should_pop_on_end_doc())\n        {\n            _remove_speculative();\n            _c4dbgp(\"pop!\");\n            _pop();\n        }\n    }\n\n    /** explicit doc start, with --- */\n    void begin_doc_expl()\n    {\n        _c4dbgp(\"begin_doc_expl\");\n        _RYML_CB_ASSERT(m_stack.m_callbacks, m_tree->root_id() == m_curr->node_id);\n        if(!m_tree->is_stream(m_tree->root_id())) //if(_should_push_on_begin_doc())\n        {\n            _c4dbgp(\"ensure stream\");\n            _set_root_as_stream();\n            id_type first = m_tree->first_child(m_tree->root_id());\n            _RYML_CB_ASSERT(m_stack.m_callbacks, m_tree->is_stream(m_tree->root_id()));\n            _RYML_CB_ASSERT(m_stack.m_callbacks, m_tree->num_children(m_tree->root_id()) == 1u);\n            if(m_tree->has_children(first) || m_tree->is_val(first))\n            {\n                _c4dbgp(\"push!\");\n                _push();\n            }\n            else\n            {\n                _c4dbgp(\"tweak\");\n                _push();\n                _remove_speculative();\n                m_curr->node_id = m_tree->last_child(m_tree->root_id());\n                m_curr->tr_data = m_tree->_p(m_curr->node_id);\n            }\n        }\n        else\n        {\n            _c4dbgp(\"push!\");\n            _push();\n        }\n        _enable_(DOC);\n    }\n    /** explicit doc end, with ... */\n    void end_doc_expl()\n    {\n        _c4dbgp(\"end_doc_expl\");\n        _remove_speculative();\n        if(_stack_should_pop_on_end_doc())\n        {\n            _c4dbgp(\"pop!\");\n            _pop();\n        }\n        m_yaml_directive = false;\n    }\n\n    /** @} */\n\npublic:\n\n    /** @name YAML map events */\n    /** @{ */\n\n    void begin_map_key_flow()\n    {\n        _RYML_CB_ERR_(m_stack.m_callbacks, \"ryml trees cannot handle containers as keys\", m_curr->pos);\n    }\n    void begin_map_key_block()\n    {\n        _RYML_CB_ERR_(m_stack.m_callbacks, \"ryml trees cannot handle containers as keys\", m_curr->pos);\n    }\n\n    void begin_map_val_flow()\n    {\n        _c4dbgpf(\"node[{}]: begin_map_val_flow\", m_curr->node_id);\n        _RYML_CB_CHECK(m_stack.m_callbacks, !_has_any_(VAL));\n        _enable_(MAP|FLOW_SL);\n        _save_loc();\n        _push();\n    }\n    void begin_map_val_block()\n    {\n        _c4dbgpf(\"node[{}]: begin_map_val_block\", m_curr->node_id);\n        _RYML_CB_CHECK(m_stack.m_callbacks, !_has_any_(VAL));\n        _enable_(MAP|BLOCK);\n        _save_loc();\n        _push();\n    }\n\n    void end_map()\n    {\n        _pop();\n        _c4dbgpf(\"node[{}]: end_map_val\", m_curr->node_id);\n    }\n\n    /** @} */\n\npublic:\n\n    /** @name YAML seq events */\n    /** @{ */\n\n    void begin_seq_key_flow()\n    {\n        _RYML_CB_ERR_(m_stack.m_callbacks, \"ryml trees cannot handle containers as keys\", m_curr->pos);\n    }\n    void begin_seq_key_block()\n    {\n        _RYML_CB_ERR_(m_stack.m_callbacks, \"ryml trees cannot handle containers as keys\", m_curr->pos);\n    }\n\n    void begin_seq_val_flow()\n    {\n        _c4dbgpf(\"node[{}]: begin_seq_val_flow\", m_curr->node_id);\n        _RYML_CB_CHECK(m_stack.m_callbacks, !_has_any_(VAL));\n        _enable_(SEQ|FLOW_SL);\n        _save_loc();\n        _push();\n    }\n    void begin_seq_val_block()\n    {\n        _c4dbgpf(\"node[{}]: begin_seq_val_block\", m_curr->node_id);\n        _RYML_CB_CHECK(m_stack.m_callbacks, !_has_any_(VAL));\n        _enable_(SEQ|BLOCK);\n        _save_loc();\n        _push();\n    }\n\n    void end_seq()\n    {\n        _pop();\n        _c4dbgpf(\"node[{}]: end_seq_val\", m_curr->node_id);\n    }\n\n    /** @} */\n\npublic:\n\n    /** @name YAML structure events */\n    /** @{ */\n\n    void add_sibling()\n    {\n        _RYML_CB_ASSERT(m_stack.m_callbacks, m_tree);\n        _RYML_CB_ASSERT(m_stack.m_callbacks, m_parent);\n        _RYML_CB_ASSERT(m_stack.m_callbacks, m_tree->has_children(m_parent->node_id));\n        NodeData const* prev = m_tree->m_buf; // watchout against relocation of the tree nodes\n        _set_state_(m_curr, m_tree->_append_child__unprotected(m_parent->node_id));\n        if(prev != m_tree->m_buf)\n            _refresh_after_relocation();\n        _c4dbgpf(\"node[{}]: added sibling={} prev={}\", m_parent->node_id, m_curr->node_id, m_tree->prev_sibling(m_curr->node_id));\n    }\n\n    /** set the previous val as the first key of a new map, with flow style.\n     *\n     * See the documentation for @ref doc_event_handlers, which has\n     * important notes about this event.\n     */\n    void actually_val_is_first_key_of_new_map_flow()\n    {\n        if(C4_UNLIKELY(m_tree->is_container(m_curr->node_id)))\n            _RYML_CB_ERR_(m_stack.m_callbacks, \"ryml trees cannot handle containers as keys\", m_curr->pos);\n        _RYML_CB_ASSERT(m_stack.m_callbacks, m_parent);\n        _RYML_CB_ASSERT(m_stack.m_callbacks, m_tree->is_seq(m_parent->node_id));\n        _RYML_CB_ASSERT(m_stack.m_callbacks, !m_tree->is_container(m_curr->node_id));\n        _RYML_CB_ASSERT(m_stack.m_callbacks, !m_tree->has_key(m_curr->node_id));\n        const NodeData tmp = _val2key_(*m_curr->tr_data);\n        _disable_(_VALMASK|VAL_STYLE);\n        m_curr->tr_data->m_val = {};\n        begin_map_val_flow();\n        m_curr->tr_data->m_type = tmp.m_type;\n        m_curr->tr_data->m_key = tmp.m_key;\n    }\n\n    /** like its flow counterpart, but this function can only be\n     * called after the end of a flow-val at root or doc level.\n     *\n     * See the documentation for @ref doc_event_handlers, which has\n     * important notes about this event.\n     */\n    void actually_val_is_first_key_of_new_map_block()\n    {\n        _RYML_CB_ERR_(m_stack.m_callbacks, \"ryml trees cannot handle containers as keys\", m_curr->pos);\n    }\n\n    /** @} */\n\npublic:\n\n    /** @name YAML scalar events */\n    /** @{ */\n\n\n    C4_ALWAYS_INLINE void set_key_scalar_plain(csubstr scalar) noexcept\n    {\n        _c4dbgpf(\"node[{}]: set key scalar plain: [{}]~~~{}~~~ ({})\", m_curr->node_id, scalar.len, scalar, reinterpret_cast<void const*>(scalar.str));\n        m_curr->tr_data->m_key.scalar = scalar;\n        _enable_(KEY|KEY_PLAIN);\n    }\n    C4_ALWAYS_INLINE void set_val_scalar_plain(csubstr scalar) noexcept\n    {\n        _c4dbgpf(\"node[{}]: set val scalar plain: [{}]~~~{}~~~ ({})\", m_curr->node_id, scalar.len, scalar, reinterpret_cast<void const*>(scalar.str));\n        m_curr->tr_data->m_val.scalar = scalar;\n        _enable_(VAL|VAL_PLAIN);\n    }\n\n\n    C4_ALWAYS_INLINE void set_key_scalar_dquoted(csubstr scalar) noexcept\n    {\n        _c4dbgpf(\"node[{}]: set key scalar dquot: [{}]~~~{}~~~ ({})\", m_curr->node_id, scalar.len, scalar, reinterpret_cast<void const*>(scalar.str));\n        m_curr->tr_data->m_key.scalar = scalar;\n        _enable_(KEY|KEY_DQUO);\n    }\n    C4_ALWAYS_INLINE void set_val_scalar_dquoted(csubstr scalar) noexcept\n    {\n        _c4dbgpf(\"node[{}]: set val scalar dquot: [{}]~~~{}~~~ ({})\", m_curr->node_id, scalar.len, scalar, reinterpret_cast<void const*>(scalar.str));\n        m_curr->tr_data->m_val.scalar = scalar;\n        _enable_(VAL|VAL_DQUO);\n    }\n\n\n    C4_ALWAYS_INLINE void set_key_scalar_squoted(csubstr scalar) noexcept\n    {\n        _c4dbgpf(\"node[{}]: set key scalar squot: [{}]~~~{}~~~ ({})\", m_curr->node_id, scalar.len, scalar, reinterpret_cast<void const*>(scalar.str));\n        m_curr->tr_data->m_key.scalar = scalar;\n        _enable_(KEY|KEY_SQUO);\n    }\n    C4_ALWAYS_INLINE void set_val_scalar_squoted(csubstr scalar) noexcept\n    {\n        _c4dbgpf(\"node[{}]: set val scalar squot: [{}]~~~{}~~~ ({})\", m_curr->node_id, scalar.len, scalar, reinterpret_cast<void const*>(scalar.str));\n        m_curr->tr_data->m_val.scalar = scalar;\n        _enable_(VAL|VAL_SQUO);\n    }\n\n\n    C4_ALWAYS_INLINE void set_key_scalar_literal(csubstr scalar) noexcept\n    {\n        _c4dbgpf(\"node[{}]: set key scalar literal: [{}]~~~{}~~~ ({})\", m_curr->node_id, scalar.len, scalar, reinterpret_cast<void const*>(scalar.str));\n        m_curr->tr_data->m_key.scalar = scalar;\n        _enable_(KEY|KEY_LITERAL);\n    }\n    C4_ALWAYS_INLINE void set_val_scalar_literal(csubstr scalar) noexcept\n    {\n        _c4dbgpf(\"node[{}]: set val scalar literal: [{}]~~~{}~~~ ({})\", m_curr->node_id, scalar.len, scalar, reinterpret_cast<void const*>(scalar.str));\n        m_curr->tr_data->m_val.scalar = scalar;\n        _enable_(VAL|VAL_LITERAL);\n    }\n\n\n    C4_ALWAYS_INLINE void set_key_scalar_folded(csubstr scalar) noexcept\n    {\n        _c4dbgpf(\"node[{}]: set key scalar folded: [{}]~~~{}~~~ ({})\", m_curr->node_id, scalar.len, scalar, reinterpret_cast<void const*>(scalar.str));\n        m_curr->tr_data->m_key.scalar = scalar;\n        _enable_(KEY|KEY_FOLDED);\n    }\n    C4_ALWAYS_INLINE void set_val_scalar_folded(csubstr scalar) noexcept\n    {\n        _c4dbgpf(\"node[{}]: set val scalar folded: [{}]~~~{}~~~ ({})\", m_curr->node_id, scalar.len, scalar, reinterpret_cast<void const*>(scalar.str));\n        m_curr->tr_data->m_val.scalar = scalar;\n        _enable_(VAL|VAL_FOLDED);\n    }\n\n\n    C4_ALWAYS_INLINE void mark_key_scalar_unfiltered() noexcept\n    {\n        _enable_(KEY_UNFILT);\n    }\n    C4_ALWAYS_INLINE void mark_val_scalar_unfiltered() noexcept\n    {\n        _enable_(VAL_UNFILT);\n    }\n\n    /** @} */\n\npublic:\n\n    /** @name YAML anchor/reference events */\n    /** @{ */\n\n    void set_key_anchor(csubstr anchor)\n    {\n        _c4dbgpf(\"node[{}]: set key anchor: [{}]~~~{}~~~\", m_curr->node_id, anchor.len, anchor);\n        _RYML_CB_ASSERT(m_stack.m_callbacks, m_tree);\n        if(C4_UNLIKELY(_has_any_(KEYREF)))\n            _RYML_CB_ERR_(m_tree->callbacks(), \"key cannot have both anchor and ref\", m_curr->pos);\n        _RYML_CB_ASSERT(m_tree->callbacks(), !anchor.begins_with('&'));\n        _enable_(KEYANCH);\n        m_curr->tr_data->m_key.anchor = anchor;\n    }\n    void set_val_anchor(csubstr anchor)\n    {\n        _c4dbgpf(\"node[{}]: set val anchor: [{}]~~~{}~~~\", m_curr->node_id, anchor.len, anchor);\n        _RYML_CB_ASSERT(m_stack.m_callbacks, m_tree);\n        if(C4_UNLIKELY(_has_any_(VALREF)))\n            _RYML_CB_ERR_(m_tree->callbacks(), \"val cannot have both anchor and ref\", m_curr->pos);\n        _RYML_CB_ASSERT(m_tree->callbacks(), !anchor.begins_with('&'));\n        _enable_(VALANCH);\n        m_curr->tr_data->m_val.anchor = anchor;\n    }\n\n    void set_key_ref(csubstr ref)\n    {\n        _c4dbgpf(\"node[{}]: set key ref: [{}]~~~{}~~~\", m_curr->node_id, ref.len, ref);\n        _RYML_CB_ASSERT(m_stack.m_callbacks, m_tree);\n        if(C4_UNLIKELY(_has_any_(KEYANCH)))\n            _RYML_CB_ERR_(m_tree->callbacks(), \"key cannot have both anchor and ref\", m_curr->pos);\n        _RYML_CB_ASSERT(m_tree->callbacks(), ref.begins_with('*'));\n        _enable_(KEY|KEYREF);\n        m_curr->tr_data->m_key.anchor = ref.sub(1);\n        m_curr->tr_data->m_key.scalar = ref;\n    }\n    void set_val_ref(csubstr ref)\n    {\n        _c4dbgpf(\"node[{}]: set val ref: [{}]~~~{}~~~\", m_curr->node_id, ref.len, ref);\n        _RYML_CB_ASSERT(m_stack.m_callbacks, m_tree);\n        if(C4_UNLIKELY(_has_any_(VALANCH)))\n            _RYML_CB_ERR_(m_tree->callbacks(), \"val cannot have both anchor and ref\", m_curr->pos);\n        _RYML_CB_ASSERT(m_tree->callbacks(), ref.begins_with('*'));\n        _enable_(VAL|VALREF);\n        m_curr->tr_data->m_val.anchor = ref.sub(1);\n        m_curr->tr_data->m_val.scalar = ref;\n    }\n\n    /** @} */\n\npublic:\n\n    /** @name YAML tag events */\n    /** @{ */\n\n    void set_key_tag(csubstr tag) noexcept\n    {\n        _c4dbgpf(\"node[{}]: set key tag: [{}]~~~{}~~~\", m_curr->node_id, tag.len, tag);\n        _enable_(KEYTAG);\n        m_curr->tr_data->m_key.tag = tag;\n    }\n    void set_val_tag(csubstr tag) noexcept\n    {\n        _c4dbgpf(\"node[{}]: set val tag: [{}]~~~{}~~~\", m_curr->node_id, tag.len, tag);\n        _enable_(VALTAG);\n        m_curr->tr_data->m_val.tag = tag;\n    }\n\n    /** @} */\n\npublic:\n\n    /** @name YAML directive events */\n    /** @{ */\n\n    C4_NO_INLINE void add_directive(csubstr directive)\n    {\n        _c4dbgpf(\"% directive! {}\", directive);\n        _RYML_CB_ASSERT(m_tree->callbacks(), directive.begins_with('%'));\n        if(directive.begins_with(\"%TAG\"))\n        {\n            if(C4_UNLIKELY(!m_tree->add_tag_directive(directive)))\n                _RYML_CB_ERR_(m_stack.m_callbacks, \"failed to add directive\", m_curr->pos);\n        }\n        else if(directive.begins_with(\"%YAML\"))\n        {\n            _c4dbgpf(\"%YAML directive! ignoring...: {}\", directive);\n            if(C4_UNLIKELY(m_yaml_directive))\n                _RYML_CB_ERR_(m_stack.m_callbacks, \"multiple yaml directives\", m_curr->pos);\n            m_yaml_directive = true;\n        }\n        else\n        {\n            _c4dbgpf(\"unknown directive! ignoring... {}\", directive);\n        }\n        ++m_num_directives;\n    }\n\n    /** @} */\n\npublic:\n\n    /** @name arena functions */\n    /** @{ */\n\n    substr alloc_arena(size_t len)\n    {\n        _RYML_CB_ASSERT(m_stack.m_callbacks, m_tree);\n        csubstr prev = m_tree->arena();\n        substr out = m_tree->alloc_arena(len);\n        substr curr = m_tree->arena();\n        if(curr.str != prev.str)\n            _stack_relocate_to_new_arena(prev, curr);\n        return out;\n    }\n\n    substr alloc_arena(size_t len, substr *relocated)\n    {\n        _RYML_CB_ASSERT(m_stack.m_callbacks, m_tree);\n        csubstr prev = m_tree->arena();\n        if(!prev.is_super(*relocated))\n            return alloc_arena(len);\n        substr out = alloc_arena(len);\n        substr curr = m_tree->arena();\n        if(curr.str != prev.str)\n            *relocated = _stack_relocate_to_new_arena(*relocated, prev, curr);\n        return out;\n    }\n\n    /** @} */\n\npublic:\n\n    /** @cond dev */\n    void _reset_parser_state(state* st, id_type parse_root, id_type node)\n    {\n        _RYML_CB_ASSERT(m_stack.m_callbacks, m_tree);\n        _set_state_(st, node);\n        const NodeType type = m_tree->type(node);\n        #ifdef RYML_DBG\n        char flagbuf[80];\n        _c4dbgpf(\"resetting state: initial flags={}\", detail::_parser_flags_to_str(flagbuf, st->flags));\n        #endif\n        if(type == NOTYPE)\n        {\n            _c4dbgpf(\"node[{}] is notype\", node);\n            if(m_tree->is_root(parse_root))\n            {\n                _c4dbgpf(\"node[{}] is root\", node);\n                st->flags |= RUNK|RTOP;\n            }\n            else\n            {\n                _c4dbgpf(\"node[{}] is not root. setting USTY\", node);\n                st->flags |= USTY;\n            }\n        }\n        else if(type.is_map())\n        {\n            _c4dbgpf(\"node[{}] is map\", node);\n            st->flags |= RMAP|USTY;\n        }\n        else if(type.is_seq())\n        {\n            _c4dbgpf(\"node[{}] is map\", node);\n            st->flags |= RSEQ|USTY;\n        }\n        else if(type.has_key())\n        {\n            _c4dbgpf(\"node[{}] has key. setting USTY\", node);\n            st->flags |= USTY;\n        }\n        else\n        {\n            _RYML_CB_ERR(m_tree->callbacks(), \"cannot append to node\");\n        }\n        if(type.is_doc())\n        {\n            _c4dbgpf(\"node[{}] is doc\", node);\n            st->flags |= RDOC;\n        }\n        #ifdef RYML_DBG\n        _c4dbgpf(\"resetting state: final flags={}\", detail::_parser_flags_to_str(flagbuf, st->flags));\n        #endif\n    }\n\n    /** push a new parent, add a child to the new parent, and set the\n     * child as the current node */\n    void _push()\n    {\n        _stack_push();\n        NodeData const* prev = m_tree->m_buf; // watch out against relocation of the tree nodes\n        m_curr->node_id = m_tree->_append_child__unprotected(m_parent->node_id);\n        m_curr->tr_data = m_tree->_p(m_curr->node_id);\n        if(prev != m_tree->m_buf)\n            _refresh_after_relocation();\n        _c4dbgpf(\"pushed! level={}. top is now node={} (parent={})\", m_curr->level, m_curr->node_id, m_parent ? m_parent->node_id : NONE);\n    }\n    /** end the current scope */\n    void _pop()\n    {\n        _remove_speculative_with_parent();\n        _stack_pop();\n    }\n\npublic:\n\n    template<type_bits bits> C4_HOT C4_ALWAYS_INLINE void _enable__() noexcept\n    {\n        m_curr->tr_data->m_type.type = static_cast<NodeType_e>(m_curr->tr_data->m_type.type | bits);\n    }\n    template<type_bits bits> C4_HOT C4_ALWAYS_INLINE void _disable__() noexcept\n    {\n        m_curr->tr_data->m_type.type = static_cast<NodeType_e>(m_curr->tr_data->m_type.type & (~bits));\n    }\n    template<type_bits bits> C4_HOT C4_ALWAYS_INLINE bool _has_any__() const noexcept\n    {\n        return (m_curr->tr_data->m_type.type & bits) != 0;\n    }\n\npublic:\n\n    C4_ALWAYS_INLINE void _set_state_(state *C4_RESTRICT s, id_type id) noexcept\n    {\n        s->node_id = id;\n        s->tr_data = m_tree->_p(id);\n    }\n    void _refresh_after_relocation()\n    {\n        _c4dbgp(\"tree: refreshing stack data after tree data relocation\");\n        for(auto &st : m_stack)\n            st.tr_data = m_tree->_p(st.node_id);\n    }\n\n    void _set_root_as_stream()\n    {\n        _c4dbgp(\"set root as stream\");\n        _RYML_CB_ASSERT(m_tree->callbacks(), m_tree->root_id() == 0u);\n        _RYML_CB_ASSERT(m_tree->callbacks(), m_curr->node_id == 0u);\n        const bool hack = !m_tree->has_children(m_curr->node_id) && !m_tree->is_val(m_curr->node_id);\n        if(hack)\n            m_tree->_p(m_tree->root_id())->m_type.add(VAL);\n        m_tree->set_root_as_stream();\n        _RYML_CB_ASSERT(m_tree->callbacks(), m_tree->is_stream(m_tree->root_id()));\n        _RYML_CB_ASSERT(m_tree->callbacks(), m_tree->has_children(m_tree->root_id()));\n        _RYML_CB_ASSERT(m_tree->callbacks(), m_tree->is_doc(m_tree->first_child(m_tree->root_id())));\n        if(hack)\n            m_tree->_p(m_tree->first_child(m_tree->root_id()))->m_type.rem(VAL);\n        _set_state_(m_curr, m_tree->root_id());\n    }\n\n    static NodeData _val2key_(NodeData const& C4_RESTRICT d) noexcept\n    {\n        NodeData r = d;\n        r.m_key = d.m_val;\n        r.m_val = {};\n        r.m_type = d.m_type;\n        static_assert((_VALMASK >> 1u) == _KEYMASK, \"required for this function to work\");\n        static_assert((VAL_STYLE >> 1u) == KEY_STYLE, \"required for this function to work\");\n        r.m_type.type = ((d.m_type.type & (_VALMASK|VAL_STYLE)) >> 1u);\n        r.m_type.type = (r.m_type.type & ~(_VALMASK|VAL_STYLE));\n        r.m_type.type = (r.m_type.type | KEY);\n        return r;\n    }\n\n    void _remove_speculative()\n    {\n        _c4dbgp(\"remove speculative node\");\n        _RYML_CB_ASSERT(m_stack.m_callbacks, m_tree);\n        _RYML_CB_ASSERT(m_tree->callbacks(), m_tree->size() > 0);\n        const id_type last_added = m_tree->size() - 1;\n        if(m_tree->has_parent(last_added))\n            if(m_tree->_p(last_added)->m_type == NOTYPE)\n                m_tree->remove(last_added);\n    }\n\n    void _remove_speculative_with_parent()\n    {\n        _RYML_CB_ASSERT(m_stack.m_callbacks, m_tree);\n        _RYML_CB_ASSERT(m_tree->callbacks(), m_tree->size() > 0);\n        const id_type last_added = m_tree->size() - 1;\n        _RYML_CB_ASSERT(m_tree->callbacks(), m_tree->has_parent(last_added));\n        if(m_tree->_p(last_added)->m_type == NOTYPE)\n        {\n            _c4dbgpf(\"remove speculative node with parent. parent={} node={} parent(node)={}\", m_parent->node_id, last_added, m_tree->parent(last_added));\n            m_tree->remove(last_added);\n        }\n    }\n\n    C4_ALWAYS_INLINE void _save_loc()\n    {\n        _RYML_CB_ASSERT(m_stack.m_callbacks, m_tree);\n        _RYML_CB_ASSERT(m_tree->callbacks(), m_tree->_p(m_curr->node_id)->m_val.scalar.len == 0);\n        m_tree->_p(m_curr->node_id)->m_val.scalar.str = m_curr->line_contents.rem.str;\n    }\n\n#undef _enable_\n#undef _disable_\n#undef _has_any_\n\n    /** @endcond */\n};\n\n/** @} */\n\n} // namespace yml\n} // namespace c4\n\nC4_SUPPRESS_WARNING_MSVC_POP\n\n#endif /* _C4_YML_EVENT_HANDLER_TREE_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/yml/export.hpp",
    "content": "#ifndef C4_YML_EXPORT_HPP_\n#define C4_YML_EXPORT_HPP_\n\n#ifdef _WIN32\n    #ifdef RYML_SHARED\n        #ifdef RYML_EXPORTS\n            #define RYML_EXPORT __declspec(dllexport)\n        #else\n            #define RYML_EXPORT __declspec(dllimport)\n        #endif\n    #else\n        #define RYML_EXPORT\n    #endif\n#else\n    #define RYML_EXPORT\n#endif\n\n#endif /* C4_YML_EXPORT_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/yml/filter_processor.hpp",
    "content": "#ifndef _C4_YML_FILTER_PROCESSOR_HPP_\n#define _C4_YML_FILTER_PROCESSOR_HPP_\n\n#include \"c4/yml/common.hpp\"\n\n#ifdef RYML_DBG\n#include \"c4/charconv.hpp\"\n#include \"c4/yml/detail/parser_dbg.hpp\"\n#endif\n\nnamespace c4 {\nnamespace yml {\n\n/** @defgroup doc_filter_processors Scalar filter processors\n *\n * These are internal classes used by @ref ParseEngine to parse the\n * scalars; normally there is no reason for a user to be manually\n * using these classes.\n *\n * @ingroup doc_parse */\n/** @{ */\n\n//-----------------------------------------------------------------------------\n\n/** Filters an input string into a different output string */\nstruct FilterProcessorSrcDst\n{\n    csubstr src;\n    substr dst;\n    size_t rpos; ///< read position\n    size_t wpos; ///< write position\n\n    C4_ALWAYS_INLINE FilterProcessorSrcDst(csubstr src_, substr dst_) noexcept\n        : src(src_)\n        , dst(dst_)\n        , rpos(0)\n        , wpos(0)\n    {\n        RYML_ASSERT(!dst.overlaps(src));\n    }\n\n    C4_ALWAYS_INLINE void setwpos(size_t wpos_) noexcept { wpos = wpos_; }\n    C4_ALWAYS_INLINE void setpos(size_t rpos_, size_t wpos_) noexcept { rpos = rpos_; wpos = wpos_; }\n    C4_ALWAYS_INLINE void set_at_end() noexcept { skip(src.len - rpos); }\n\n    C4_ALWAYS_INLINE bool has_more_chars() const noexcept { return rpos < src.len; }\n    C4_ALWAYS_INLINE bool has_more_chars(size_t maxpos) const noexcept { RYML_ASSERT(maxpos <= src.len); return rpos < maxpos; }\n\n    C4_ALWAYS_INLINE csubstr rem() const noexcept { return src.sub(rpos); }\n    C4_ALWAYS_INLINE csubstr sofar() const noexcept { return csubstr(dst.str, wpos <= dst.len ? wpos : dst.len); }\n    C4_ALWAYS_INLINE FilterResult result() const noexcept\n    {\n        FilterResult ret;\n        ret.str.str = wpos <= dst.len ? dst.str : nullptr;\n        ret.str.len = wpos;\n        return ret;\n    }\n\n    C4_ALWAYS_INLINE char curr() const noexcept { RYML_ASSERT(rpos < src.len); return src[rpos]; }\n    C4_ALWAYS_INLINE char next() const noexcept { return rpos+1 < src.len ? src[rpos+1] : '\\0'; }\n    C4_ALWAYS_INLINE bool skipped_chars() const noexcept { return wpos != rpos; }\n\n    C4_ALWAYS_INLINE void skip() noexcept { ++rpos; }\n    C4_ALWAYS_INLINE void skip(size_t num) noexcept { rpos += num; }\n\n    C4_ALWAYS_INLINE void set_at(size_t pos, char c) noexcept\n    {\n        RYML_ASSERT(pos < wpos);\n        dst.str[pos] = c;\n    }\n    C4_ALWAYS_INLINE void set(char c) noexcept\n    {\n        if(wpos < dst.len)\n            dst.str[wpos] = c;\n        ++wpos;\n    }\n    C4_ALWAYS_INLINE void set(char c, size_t num) noexcept\n    {\n        RYML_ASSERT(num > 0);\n        if(wpos + num <= dst.len)\n            memset(dst.str + wpos, c, num);\n        wpos += num;\n    }\n\n    C4_ALWAYS_INLINE void copy() noexcept\n    {\n        RYML_ASSERT(rpos < src.len);\n        if(wpos < dst.len)\n            dst.str[wpos] = src.str[rpos];\n        ++wpos;\n        ++rpos;\n    }\n    C4_ALWAYS_INLINE void copy(size_t num) noexcept\n    {\n        RYML_ASSERT(num);\n        RYML_ASSERT(rpos+num <= src.len);\n        if(wpos + num <= dst.len)\n            memcpy(dst.str + wpos, src.str + rpos, num);\n        wpos += num;\n        rpos += num;\n    }\n\n    C4_ALWAYS_INLINE void translate_esc(char c) noexcept\n    {\n        if(wpos < dst.len)\n            dst.str[wpos] = c;\n        ++wpos;\n        rpos += 2;\n    }\n    C4_ALWAYS_INLINE void translate_esc_bulk(const char *C4_RESTRICT s, size_t nw, size_t nr) noexcept\n    {\n        RYML_ASSERT(nw > 0);\n        RYML_ASSERT(nr > 0);\n        RYML_ASSERT(rpos+nr <= src.len);\n        if(wpos+nw <= dst.len)\n            memcpy(dst.str + wpos, s, nw);\n        wpos += nw;\n        rpos += 1 + nr;\n    }\n    C4_ALWAYS_INLINE void translate_esc_extending(const char *C4_RESTRICT s, size_t nw, size_t nr) noexcept\n    {\n        translate_esc_bulk(s, nw, nr);\n    }\n};\n\n\n//-----------------------------------------------------------------------------\n// filter in place\n\n// debugging scaffold\n/** @cond dev */\n#if defined(RYML_DBG) && 0\n#define _c4dbgip(...) _c4dbgpf(__VA_ARGS__)\n#else\n#define _c4dbgip(...)\n#endif\n/** @endcond */\n\n/** Filters in place. While the result may be larger than the source,\n * any extending happens only at the end of the string. Consequently,\n * it's impossible for characters to be left unfiltered.\n *\n * @see FilterProcessorInplaceMidExtending */\nstruct FilterProcessorInplaceEndExtending\n{\n    substr src;  ///< the subject string\n    size_t wcap; ///< write capacity - the capacity of the subject string's buffer\n    size_t rpos; ///< read position\n    size_t wpos; ///< write position\n\n    C4_ALWAYS_INLINE FilterProcessorInplaceEndExtending(substr src_, size_t wcap_) noexcept\n        : src(src_)\n        , wcap(wcap_)\n        , rpos(0)\n        , wpos(0)\n    {\n        RYML_ASSERT(wcap >= src.len);\n    }\n\n    C4_ALWAYS_INLINE void setwpos(size_t wpos_) noexcept { wpos = wpos_; }\n    C4_ALWAYS_INLINE void setpos(size_t rpos_, size_t wpos_) noexcept { rpos = rpos_; wpos = wpos_; }\n    C4_ALWAYS_INLINE void set_at_end() noexcept { skip(src.len - rpos); }\n\n    C4_ALWAYS_INLINE bool has_more_chars() const noexcept { return rpos < src.len; }\n    C4_ALWAYS_INLINE bool has_more_chars(size_t maxpos) const noexcept { RYML_ASSERT(maxpos <= src.len); return rpos < maxpos; }\n\n    C4_ALWAYS_INLINE FilterResult result() const noexcept\n    {\n        _c4dbgip(\"inplace: wpos={} wcap={} small={}\", wpos, wcap, wpos > rpos);\n        FilterResult ret;\n        ret.str.str = (wpos <= wcap) ? src.str : nullptr;\n        ret.str.len = wpos;\n        return ret;\n    }\n    C4_ALWAYS_INLINE csubstr sofar() const noexcept { return csubstr(src.str, wpos <= wcap ? wpos : wcap); }\n    C4_ALWAYS_INLINE csubstr rem() const noexcept { return src.sub(rpos); }\n\n    C4_ALWAYS_INLINE char curr() const noexcept { RYML_ASSERT(rpos < src.len); return src[rpos]; }\n    C4_ALWAYS_INLINE char next() const noexcept { return rpos+1 < src.len ? src[rpos+1] : '\\0'; }\n\n    C4_ALWAYS_INLINE void skip() noexcept { ++rpos; }\n    C4_ALWAYS_INLINE void skip(size_t num) noexcept { rpos += num; }\n\n    void set_at(size_t pos, char c) noexcept\n    {\n        RYML_ASSERT(pos < wpos);\n        const size_t save = wpos;\n        wpos = pos;\n        set(c);\n        wpos = save;\n    }\n    void set(char c) noexcept\n    {\n        if(wpos < wcap)  // respect write-capacity\n            src.str[wpos] = c;\n        ++wpos;\n    }\n    void set(char c, size_t num) noexcept\n    {\n        RYML_ASSERT(num);\n        if(wpos + num <= wcap)  // respect write-capacity\n            memset(src.str + wpos, c, num);\n        wpos += num;\n    }\n\n    void copy() noexcept\n    {\n        RYML_ASSERT(wpos <= rpos);\n        RYML_ASSERT(rpos < src.len);\n        if(wpos < wcap)  // respect write-capacity\n            src.str[wpos] = src.str[rpos];\n        ++rpos;\n        ++wpos;\n    }\n    void copy(size_t num) noexcept\n    {\n        RYML_ASSERT(num);\n        RYML_ASSERT(rpos+num <= src.len);\n        RYML_ASSERT(wpos <= rpos);\n        if(wpos + num <= wcap)  // respect write-capacity\n        {\n            if(wpos + num <= rpos) // there is no overlap\n                memcpy(src.str + wpos, src.str + rpos, num);\n            else                   // there is overlap\n                memmove(src.str + wpos, src.str + rpos, num);\n        }\n        rpos += num;\n        wpos += num;\n    }\n\n    void translate_esc(char c) noexcept\n    {\n        RYML_ASSERT(rpos + 2 <= src.len);\n        RYML_ASSERT(wpos <= rpos);\n        if(wpos < wcap) // respect write-capacity\n            src.str[wpos] = c;\n        rpos += 2; // add 1u to account for the escape character\n        ++wpos;\n    }\n\n    void translate_esc_bulk(const char *C4_RESTRICT s, size_t nw, size_t nr) noexcept\n    {\n        RYML_ASSERT(nw > 0);\n        RYML_ASSERT(nr > 0);\n        RYML_ASSERT(nw <= nr + 1u);\n        RYML_ASSERT(rpos+nr <= src.len);\n        RYML_ASSERT(wpos <= rpos);\n        const size_t wpos_next = wpos + nw;\n        const size_t rpos_next = rpos + nr + 1u; // add 1u to account for the escape character\n        RYML_ASSERT(wpos_next <= rpos_next);\n        if(wpos_next <= wcap)\n            memcpy(src.str + wpos, s, nw);\n        rpos = rpos_next;\n        wpos = wpos_next;\n    }\n\n    C4_ALWAYS_INLINE void translate_esc_extending(const char *C4_RESTRICT s, size_t nw, size_t nr) noexcept\n    {\n        translate_esc_bulk(s, nw, nr);\n    }\n};\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n/** Filters in place. The result may be larger than the source, and\n * extending may happen anywhere. As a result some characters may be\n * left unfiltered when there is no slack in the buffer and the\n * write-position would overlap the read-position. Consequently, it's\n * possible for characters to be left unfiltered. In YAML, this\n * happens only with double-quoted strings, and only with a small\n * number of escape sequences such as `\\L` which is substituted by three\n * bytes. These escape sequences cause a call to translate_esc_extending()\n * which is the only entry point to this unfiltered situation.\n *\n * @see FilterProcessorInplaceMidExtending */\nstruct FilterProcessorInplaceMidExtending\n{\n    substr src;  ///< the subject string\n    size_t wcap; ///< write capacity - the capacity of the subject string's buffer\n    size_t rpos; ///< read position\n    size_t wpos; ///< write position\n    size_t maxcap; ///< the max capacity needed for filtering the string. This may be larger than the final string size.\n    bool unfiltered_chars; ///< number of characters that were not added to wpos from lack of capacity\n\n    C4_ALWAYS_INLINE FilterProcessorInplaceMidExtending(substr src_, size_t wcap_) noexcept\n        : src(src_)\n        , wcap(wcap_)\n        , rpos(0)\n        , wpos(0)\n        , maxcap(src.len)\n        , unfiltered_chars(false)\n    {\n        RYML_ASSERT(wcap >= src.len);\n    }\n\n    C4_ALWAYS_INLINE void setwpos(size_t wpos_) noexcept { wpos = wpos_; }\n    C4_ALWAYS_INLINE void setpos(size_t rpos_, size_t wpos_) noexcept { rpos = rpos_; wpos = wpos_; }\n    C4_ALWAYS_INLINE void set_at_end() noexcept { skip(src.len - rpos); }\n\n    C4_ALWAYS_INLINE bool has_more_chars() const noexcept { return rpos < src.len; }\n    C4_ALWAYS_INLINE bool has_more_chars(size_t maxpos) const noexcept { RYML_ASSERT(maxpos <= src.len); return rpos < maxpos; }\n\n    C4_ALWAYS_INLINE FilterResultExtending result() const noexcept\n    {\n        _c4dbgip(\"inplace: wpos={} wcap={} unfiltered={} maxcap={}\", this->wpos, this->wcap, this->unfiltered_chars, this->maxcap);\n        FilterResultExtending ret;\n        ret.str.str = (wpos <= wcap && !unfiltered_chars) ? src.str : nullptr;\n        ret.str.len = wpos;\n        ret.reqlen = maxcap;\n        return ret;\n    }\n    C4_ALWAYS_INLINE csubstr sofar() const noexcept { return csubstr(src.str, wpos <= wcap ? wpos : wcap); }\n    C4_ALWAYS_INLINE csubstr rem() const noexcept { return src.sub(rpos); }\n\n    C4_ALWAYS_INLINE char curr() const noexcept { RYML_ASSERT(rpos < src.len); return src[rpos]; }\n    C4_ALWAYS_INLINE char next() const noexcept { return rpos+1 < src.len ? src[rpos+1] : '\\0'; }\n\n    C4_ALWAYS_INLINE void skip() noexcept { ++rpos; }\n    C4_ALWAYS_INLINE void skip(size_t num) noexcept { rpos += num; }\n\n    void set_at(size_t pos, char c) noexcept\n    {\n        RYML_ASSERT(pos < wpos);\n        const size_t save = wpos;\n        wpos = pos;\n        set(c);\n        wpos = save;\n    }\n    void set(char c) noexcept\n    {\n        if(wpos < wcap)  // respect write-capacity\n        {\n            if((wpos <= rpos) && !unfiltered_chars)\n                src.str[wpos] = c;\n        }\n        else\n        {\n            _c4dbgip(\"inplace: add unwritten {}->{}   maxcap={}->{}!\", unfiltered_chars, true, maxcap, (wpos+1u > maxcap ? wpos+1u : maxcap));\n            unfiltered_chars = true;\n        }\n        ++wpos;\n        maxcap = wpos > maxcap ? wpos : maxcap;\n    }\n    void set(char c, size_t num) noexcept\n    {\n        RYML_ASSERT(num);\n        if(wpos + num <= wcap)  // respect write-capacity\n        {\n            if((wpos <= rpos) && !unfiltered_chars)\n                memset(src.str + wpos, c, num);\n        }\n        else\n        {\n            _c4dbgip(\"inplace: add unwritten {}->{}   maxcap={}->{}!\", unfiltered_chars, true, maxcap, (wpos+num > maxcap ? wpos+num : maxcap));\n            unfiltered_chars = true;\n        }\n        wpos += num;\n        maxcap = wpos > maxcap ? wpos : maxcap;\n    }\n\n    void copy() noexcept\n    {\n        RYML_ASSERT(rpos < src.len);\n        if(wpos < wcap)  // respect write-capacity\n        {\n            if((wpos < rpos) && !unfiltered_chars)  // write only if wpos is behind rpos\n                src.str[wpos] = src.str[rpos];\n        }\n        else\n        {\n            _c4dbgip(\"inplace: add unwritten {}->{} (wpos={}!=rpos={})={}  (wpos={}<wcap={})   maxcap={}->{}!\", unfiltered_chars, true, wpos, rpos, wpos!=rpos, wpos, wcap, wpos<wcap, maxcap, (wpos+1u > maxcap ? wpos+1u : maxcap));\n            unfiltered_chars = true;\n        }\n        ++rpos;\n        ++wpos;\n        maxcap = wpos > maxcap ? wpos : maxcap;\n    }\n    void copy(size_t num) noexcept\n    {\n        RYML_ASSERT(num);\n        RYML_ASSERT(rpos+num <= src.len);\n        if(wpos + num <= wcap)  // respect write-capacity\n        {\n            if((wpos < rpos) && !unfiltered_chars)  // write only if wpos is behind rpos\n            {\n                if(wpos + num <= rpos) // there is no overlap\n                    memcpy(src.str + wpos, src.str + rpos, num);\n                else                   // there is overlap\n                    memmove(src.str + wpos, src.str + rpos, num);\n            }\n        }\n        else\n        {\n            _c4dbgip(\"inplace: add unwritten {}->{} (wpos={}!=rpos={})={}  (wpos={}<wcap={})  maxcap={}->{}!\", unfiltered_chars, true, wpos, rpos, wpos!=rpos, wpos, wcap, wpos<wcap);\n            unfiltered_chars = true;\n        }\n        rpos += num;\n        wpos += num;\n        maxcap = wpos > maxcap ? wpos : maxcap;\n    }\n\n    void translate_esc(char c) noexcept\n    {\n        RYML_ASSERT(rpos + 2 <= src.len);\n        if(wpos < wcap) // respect write-capacity\n        {\n            if((wpos <= rpos) && !unfiltered_chars)\n                src.str[wpos] = c;\n        }\n        else\n        {\n            _c4dbgip(\"inplace: add unfiltered {}->{}  maxcap={}->{}!\", unfiltered_chars, true, maxcap, (wpos+1u > maxcap ? wpos+1u : maxcap));\n            unfiltered_chars = true;\n        }\n        rpos += 2;\n        ++wpos;\n        maxcap = wpos > maxcap ? wpos : maxcap;\n    }\n\n    C4_NO_INLINE void translate_esc_bulk(const char *C4_RESTRICT s, size_t nw, size_t nr) noexcept\n    {\n        RYML_ASSERT(nw > 0);\n        RYML_ASSERT(nr > 0);\n        RYML_ASSERT(nr+1u >= nw);\n        const size_t wpos_next = wpos + nw;\n        const size_t rpos_next = rpos + nr + 1u; // add 1u to account for the escape character\n        if(wpos_next <= wcap)  // respect write-capacity\n        {\n            if((wpos <= rpos) && !unfiltered_chars)  // write only if wpos is behind rpos\n                memcpy(src.str + wpos, s, nw);\n        }\n        else\n        {\n            _c4dbgip(\"inplace: add unwritten {}->{} (wpos={}!=rpos={})={}  (wpos={}<wcap={})  maxcap={}->{}!\", unfiltered_chars, true, wpos, rpos, wpos!=rpos, wpos, wcap, wpos<wcap);\n            unfiltered_chars = true;\n        }\n        rpos = rpos_next;\n        wpos = wpos_next;\n        maxcap = wpos > maxcap ? wpos : maxcap;\n    }\n\n    C4_NO_INLINE void translate_esc_extending(const char *C4_RESTRICT s, size_t nw, size_t nr) noexcept\n    {\n        RYML_ASSERT(nw > 0);\n        RYML_ASSERT(nr > 0);\n        RYML_ASSERT(rpos+nr <= src.len);\n        const size_t wpos_next = wpos + nw;\n        const size_t rpos_next = rpos + nr + 1u; // add 1u to account for the escape character\n        if(wpos_next <= rpos_next) // read and write do not overlap. just do a vanilla copy.\n        {\n            if((wpos_next <= wcap) && !unfiltered_chars)\n                memcpy(src.str + wpos, s, nw);\n            rpos = rpos_next;\n            wpos = wpos_next;\n            maxcap = wpos > maxcap ? wpos : maxcap;\n        }\n        else // there is overlap. move the (to-be-read) string to the right.\n        {\n            const size_t excess = wpos_next - rpos_next;\n            RYML_ASSERT(wpos_next > rpos_next);\n            if(src.len + excess <= wcap) // ensure we do not go past the end\n            {\n                RYML_ASSERT(rpos+nr+excess <= src.len);\n                if(wpos_next <= wcap)\n                {\n                    if(!unfiltered_chars)\n                    {\n                        memmove(src.str + wpos_next, src.str + rpos_next, src.len - rpos_next);\n                        memcpy(src.str + wpos, s, nw);\n                    }\n                    rpos = wpos_next; // wpos, not rpos\n                }\n                else\n                {\n                    rpos = rpos_next;\n                    //const size_t unw = nw > (nr + 1u) ? nw - (nr + 1u) : 0;\n                    _c4dbgip(\"inplace: add unfiltered {}->{}   maxcap={}->{}!\", unfiltered_chars, true);\n                    unfiltered_chars = true;\n                }\n                wpos = wpos_next;\n                // extend the string up to capacity\n                src.len += excess;\n                maxcap = wpos > maxcap ? wpos : maxcap;\n            }\n            else\n            {\n                //const size_t unw = nw > (nr + 1u) ? nw - (nr + 1u) : 0;\n                RYML_ASSERT(rpos_next <= src.len);\n                const size_t required_size = wpos_next + (src.len - rpos_next);\n                _c4dbgip(\"inplace: add unfiltered {}->{}   maxcap={}->{}!\", unfiltered_chars, true, maxcap, required_size > maxcap ? required_size : maxcap);\n                RYML_ASSERT(required_size > wcap);\n                unfiltered_chars = true;\n                maxcap = required_size > maxcap ? required_size : maxcap;\n                wpos = wpos_next;\n                rpos = rpos_next;\n            }\n        }\n    }\n};\n\n#undef _c4dbgip\n\n\n/** @} */\n\n} // namespace yml\n} // namespace c4\n\n#endif /* _C4_YML_FILTER_PROCESSOR_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/yml/fwd.hpp",
    "content": "#ifndef _C4_YML_FWD_HPP_\n#define _C4_YML_FWD_HPP_\n\n/** @file fwd.hpp forward declarations */\n\nnamespace c4 {\nnamespace yml {\n\nstruct NodeScalar;\nstruct NodeInit;\nstruct NodeData;\nstruct NodeType;\nclass NodeRef;\nclass ConstNodeRef;\nclass Tree;\nstruct ReferenceResolver;\ntemplate<class EventHandler> class ParseEngine;\nstruct EventHandlerTree;\nusing Parser = ParseEngine<EventHandlerTree>;\n\n} // namespace c4\n} // namespace yml\n\n#endif /* _C4_YML_FWD_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/yml/node.cpp",
    "content": "#include \"c4/yml/node.hpp\"\n\nnamespace c4 {\nnamespace yml {\n\n\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\nsize_t NodeRef::set_key_serialized(c4::fmt::const_base64_wrapper w)\n{\n    _apply_seed();\n    csubstr encoded = this->to_arena(w);\n    this->set_key(encoded);\n    return encoded.len;\n}\n\nsize_t NodeRef::set_val_serialized(c4::fmt::const_base64_wrapper w)\n{\n    _apply_seed();\n    csubstr encoded = this->to_arena(w);\n    this->set_val(encoded);\n    return encoded.len;\n}\n\n} // namespace yml\n} // namespace c4\n"
  },
  {
    "path": "libs/rapidyaml/c4/yml/node.hpp",
    "content": "#ifndef _C4_YML_NODE_HPP_\n#define _C4_YML_NODE_HPP_\n\n/** @file node.hpp Node classes */\n\n#include <cstddef>\n\n#include \"c4/yml/tree.hpp\"\n#include \"c4/base64.hpp\"\n\n#ifdef __clang__\n#   pragma clang diagnostic push\n#   pragma clang diagnostic ignored \"-Wtype-limits\"\n#   pragma clang diagnostic ignored \"-Wold-style-cast\"\n#elif defined(__GNUC__)\n#   pragma GCC diagnostic push\n#   pragma GCC diagnostic ignored \"-Wtype-limits\"\n#   pragma GCC diagnostic ignored \"-Wold-style-cast\"\n#   pragma GCC diagnostic ignored \"-Wuseless-cast\"\n#elif defined(_MSC_VER)\n#   pragma warning(push)\n#   pragma warning(disable: 4251/*needs to have dll-interface to be used by clients of struct*/)\n#   pragma warning(disable: 4296/*expression is always 'boolean_value'*/)\n#endif\n\nnamespace c4 {\nnamespace yml {\n\n/** @addtogroup doc_node_classes\n *\n * @{\n */\n\n\n/** @defgroup doc_serialization_helpers Serialization helpers\n *\n * @{\n */\ntemplate<class K> struct Key { K & k; };\ntemplate<> struct Key<fmt::const_base64_wrapper> { fmt::const_base64_wrapper wrapper; };\ntemplate<> struct Key<fmt::base64_wrapper> { fmt::base64_wrapper wrapper; };\n\ntemplate<class K> C4_ALWAYS_INLINE Key<K> key(K & k) { return Key<K>{k}; }\nC4_ALWAYS_INLINE Key<fmt::const_base64_wrapper> key(fmt::const_base64_wrapper w) { return {w}; }\nC4_ALWAYS_INLINE Key<fmt::base64_wrapper> key(fmt::base64_wrapper w) { return {w}; }\n\ntemplate<class T> void write(NodeRef *n, T const& v);\n\ntemplate<class T>\ntypename std::enable_if< ! std::is_floating_point<T>::value, bool>::type\nread(NodeRef const& n, T *v);\n\ntemplate<class T>\ntypename std::enable_if<   std::is_floating_point<T>::value, bool>::type\nread(NodeRef const& n, T *v);\n\n/** @} */\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n// forward decls\nclass NodeRef;\nclass ConstNodeRef;\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n/** @cond dev */\nnamespace detail {\n\ntemplate<class NodeRefType>\nstruct child_iterator\n{\n    using value_type = NodeRefType;\n    using tree_type = typename NodeRefType::tree_type;\n\n    tree_type * C4_RESTRICT m_tree;\n    id_type m_child_id;\n\n    child_iterator(tree_type * t, id_type id) : m_tree(t), m_child_id(id) {}\n\n    child_iterator& operator++ () { RYML_ASSERT(m_child_id != NONE); m_child_id = m_tree->next_sibling(m_child_id); return *this; }\n    child_iterator& operator-- () { RYML_ASSERT(m_child_id != NONE); m_child_id = m_tree->prev_sibling(m_child_id); return *this; }\n\n    NodeRefType operator*  () const { return NodeRefType(m_tree, m_child_id); }\n    NodeRefType operator-> () const { return NodeRefType(m_tree, m_child_id); }\n\n    bool operator!= (child_iterator that) const { RYML_ASSERT(m_tree == that.m_tree); return m_child_id != that.m_child_id; }\n    bool operator== (child_iterator that) const { RYML_ASSERT(m_tree == that.m_tree); return m_child_id == that.m_child_id; }\n};\n\ntemplate<class NodeRefType>\nstruct children_view_\n{\n    using n_iterator = child_iterator<NodeRefType>;\n\n    n_iterator b, e;\n\n    inline children_view_(n_iterator const& C4_RESTRICT b_,\n                          n_iterator const& C4_RESTRICT e_) : b(b_), e(e_) {}\n\n    inline n_iterator begin() const { return b; }\n    inline n_iterator end  () const { return e; }\n};\n\ntemplate<class NodeRefType, class Visitor>\nbool _visit(NodeRefType &node, Visitor fn, id_type indentation_level, bool skip_root=false)\n{\n    id_type increment = 0;\n    if( ! (node.is_root() && skip_root))\n    {\n        if(fn(node, indentation_level))\n            return true;\n        ++increment;\n    }\n    if(node.has_children())\n    {\n        for(auto ch : node.children())\n        {\n            if(_visit(ch, fn, indentation_level + increment, false)) // no need to forward skip_root as it won't be root\n            {\n                return true;\n            }\n        }\n    }\n    return false;\n}\n\ntemplate<class NodeRefType, class Visitor>\nbool _visit_stacked(NodeRefType &node, Visitor fn, id_type indentation_level, bool skip_root=false)\n{\n    id_type increment = 0;\n    if( ! (node.is_root() && skip_root))\n    {\n        if(fn(node, indentation_level))\n        {\n            return true;\n        }\n        ++increment;\n    }\n    if(node.has_children())\n    {\n        fn.push(node, indentation_level);\n        for(auto ch : node.children())\n        {\n            if(_visit_stacked(ch, fn, indentation_level + increment, false)) // no need to forward skip_root as it won't be root\n            {\n                fn.pop(node, indentation_level);\n                return true;\n            }\n        }\n        fn.pop(node, indentation_level);\n    }\n    return false;\n}\n\ntemplate<class Impl, class ConstImpl>\nstruct RoNodeMethods;\n} // detail\n/** @endcond */\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n\n/** a CRTP base providing read-only methods for @ref ConstNodeRef and @ref NodeRef */\nnamespace detail {\ntemplate<class Impl, class ConstImpl>\nstruct RoNodeMethods\n{\n    C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH(\"-Wcast-align\")\n    /** @cond dev */\n    // helper CRTP macros, undefined at the end\n    #define tree_ ((ConstImpl const* C4_RESTRICT)this)->m_tree\n    #define id_ ((ConstImpl const* C4_RESTRICT)this)->m_id\n    #define tree__ ((Impl const* C4_RESTRICT)this)->m_tree\n    #define id__ ((Impl const* C4_RESTRICT)this)->m_id\n    // require readable: this is a precondition for reading from the\n    // tree using this object.\n    #define _C4RR()                                       \\\n        RYML_ASSERT(tree_ != nullptr);                    \\\n        _RYML_CB_ASSERT(tree_->m_callbacks, id_ != NONE); \\\n        _RYML_CB_ASSERT(tree_->m_callbacks, (((Impl const* C4_RESTRICT)this)->readable()))\n    // a SFINAE beautifier to enable a function only if the\n    // implementation is mutable\n    #define _C4_IF_MUTABLE(ty) typename std::enable_if<!std::is_same<U, ConstImpl>::value, ty>::type\n    /** @endcond */\n\npublic:\n\n    /** @name node property getters */\n    /** @{ */\n\n    /** returns the data or null when the id is NONE */\n    C4_ALWAYS_INLINE NodeData const* get() const RYML_NOEXCEPT { return ((Impl const*)this)->readable() ? tree_->get(id_) : nullptr; }\n    /** returns the data or null when the id is NONE */\n    template<class U=Impl>\n    C4_ALWAYS_INLINE auto get() RYML_NOEXCEPT -> _C4_IF_MUTABLE(NodeData*) { return ((Impl const*)this)->readable() ? tree__->get(id__) : nullptr; }\n\n    C4_ALWAYS_INLINE NodeType    type()     const RYML_NOEXCEPT { _C4RR(); return tree_->type(id_); }     /**< Forward to @ref Tree::type_str(). Node must be readable. */\n    C4_ALWAYS_INLINE const char* type_str() const RYML_NOEXCEPT { _C4RR(); return tree_->type_str(id_); } /**< Forward to @ref Tree::type_str(). Node must be readable. */\n\n    C4_ALWAYS_INLINE csubstr key()        const RYML_NOEXCEPT { _C4RR(); return tree_->key(id_); }        /**< Forward to @ref Tree::key(). Node must be readable. */\n    C4_ALWAYS_INLINE csubstr key_tag()    const RYML_NOEXCEPT { _C4RR(); return tree_->key_tag(id_); }    /**< Forward to @ref Tree::key_tag(). Node must be readable. */\n    C4_ALWAYS_INLINE csubstr key_ref()    const RYML_NOEXCEPT { _C4RR(); return tree_->key_ref(id_); }    /**< Forward to @ref Tree::key_ref(). Node must be readable. */\n    C4_ALWAYS_INLINE csubstr key_anchor() const RYML_NOEXCEPT { _C4RR(); return tree_->key_anchor(id_); } /**< Forward to @ref Tree::key_anchor(). Node must be readable. */\n\n    C4_ALWAYS_INLINE csubstr val()        const RYML_NOEXCEPT { _C4RR(); return tree_->val(id_); }        /**< Forward to @ref Tree::val(). Node must be readable. */\n    C4_ALWAYS_INLINE csubstr val_tag()    const RYML_NOEXCEPT { _C4RR(); return tree_->val_tag(id_); }    /**< Forward to @ref Tree::val_tag(). Node must be readable. */\n    C4_ALWAYS_INLINE csubstr val_ref()    const RYML_NOEXCEPT { _C4RR(); return tree_->val_ref(id_); }    /**< Forward to @ref Tree::val_ref(). Node must be readable. */\n    C4_ALWAYS_INLINE csubstr val_anchor() const RYML_NOEXCEPT { _C4RR(); return tree_->val_anchor(id_); } /**< Forward to @ref Tree::val_anchor(). Node must be readable. */\n\n    C4_ALWAYS_INLINE NodeScalar const& keysc() const RYML_NOEXCEPT { _C4RR(); return tree_->keysc(id_); } /**< Forward to @ref Tree::keysc(). Node must be readable. */\n    C4_ALWAYS_INLINE NodeScalar const& valsc() const RYML_NOEXCEPT { _C4RR(); return tree_->valsc(id_); } /**< Forward to @ref Tree::valsc(). Node must be readable. */\n\n    C4_ALWAYS_INLINE bool key_is_null() const RYML_NOEXCEPT { _C4RR(); return tree_->key_is_null(id_); } /**< Forward to @ref Tree::key_is_null(). Node must be readable. */\n    C4_ALWAYS_INLINE bool val_is_null() const RYML_NOEXCEPT { _C4RR(); return tree_->val_is_null(id_); } /**< Forward to @ref Tree::val_is_null(). Node must be readable. */\n\n    C4_ALWAYS_INLINE bool is_key_unfiltered() const noexcept { _C4RR(); return tree_->is_key_unfiltered(id_); } /**< Forward to @ref Tree::is_key_unfiltered(). Node must be readable. */\n    C4_ALWAYS_INLINE bool is_val_unfiltered() const noexcept { _C4RR(); return tree_->is_val_unfiltered(id_); } /**< Forward to @ref Tree::is_val_unfiltered(). Node must be readable. */\n\n    /** @} */\n\npublic:\n\n    /** @name node type predicates */\n    /** @{ */\n\n    C4_ALWAYS_INLINE bool empty()            const RYML_NOEXCEPT { _C4RR(); return tree_->empty(id_); } /**< Forward to @ref Tree::empty(). Node must be readable. */\n    C4_ALWAYS_INLINE bool is_stream()        const RYML_NOEXCEPT { _C4RR(); return tree_->is_stream(id_); } /**< Forward to @ref Tree::is_stream(). Node must be readable. */\n    C4_ALWAYS_INLINE bool is_doc()           const RYML_NOEXCEPT { _C4RR(); return tree_->is_doc(id_); } /**< Forward to @ref Tree::is_doc(). Node must be readable. */\n    C4_ALWAYS_INLINE bool is_container()     const RYML_NOEXCEPT { _C4RR(); return tree_->is_container(id_); } /**< Forward to @ref Tree::is_container(). Node must be readable. */\n    C4_ALWAYS_INLINE bool is_map()           const RYML_NOEXCEPT { _C4RR(); return tree_->is_map(id_); } /**< Forward to @ref Tree::is_map(). Node must be readable. */\n    C4_ALWAYS_INLINE bool is_seq()           const RYML_NOEXCEPT { _C4RR(); return tree_->is_seq(id_); } /**< Forward to @ref Tree::is_seq(). Node must be readable. */\n    C4_ALWAYS_INLINE bool has_val()          const RYML_NOEXCEPT { _C4RR(); return tree_->has_val(id_); } /**< Forward to @ref Tree::has_val(). Node must be readable. */\n    C4_ALWAYS_INLINE bool has_key()          const RYML_NOEXCEPT { _C4RR(); return tree_->has_key(id_); } /**< Forward to @ref Tree::has_key(). Node must be readable. */\n    C4_ALWAYS_INLINE bool is_val()           const RYML_NOEXCEPT { _C4RR(); return tree_->is_val(id_); } /**< Forward to @ref Tree::is_val(). Node must be readable. */\n    C4_ALWAYS_INLINE bool is_keyval()        const RYML_NOEXCEPT { _C4RR(); return tree_->is_keyval(id_); } /**< Forward to @ref Tree::is_keyval(). Node must be readable. */\n    C4_ALWAYS_INLINE bool has_key_tag()      const RYML_NOEXCEPT { _C4RR(); return tree_->has_key_tag(id_); } /**< Forward to @ref Tree::has_key_tag(). Node must be readable. */\n    C4_ALWAYS_INLINE bool has_val_tag()      const RYML_NOEXCEPT { _C4RR(); return tree_->has_val_tag(id_); } /**< Forward to @ref Tree::has_val_tag(). Node must be readable. */\n    C4_ALWAYS_INLINE bool has_key_anchor()   const RYML_NOEXCEPT { _C4RR(); return tree_->has_key_anchor(id_); } /**< Forward to @ref Tree::has_key_anchor(). Node must be readable. */\n    C4_ALWAYS_INLINE bool has_val_anchor()   const RYML_NOEXCEPT { _C4RR(); return tree_->has_val_anchor(id_); } /**< Forward to @ref Tree::has_val_anchor(). Node must be readable. */\n    C4_ALWAYS_INLINE bool has_anchor()       const RYML_NOEXCEPT { _C4RR(); return tree_->has_anchor(id_); } /**< Forward to @ref Tree::has_anchor(). Node must be readable. */\n    C4_ALWAYS_INLINE bool is_key_ref()       const RYML_NOEXCEPT { _C4RR(); return tree_->is_key_ref(id_); } /**< Forward to @ref Tree::is_key_ref(). Node must be readable. */\n    C4_ALWAYS_INLINE bool is_val_ref()       const RYML_NOEXCEPT { _C4RR(); return tree_->is_val_ref(id_); } /**< Forward to @ref Tree::is_val_ref(). Node must be readable. */\n    C4_ALWAYS_INLINE bool is_ref()           const RYML_NOEXCEPT { _C4RR(); return tree_->is_ref(id_); } /**< Forward to @ref Tree::is_ref(). Node must be readable. */\n    C4_ALWAYS_INLINE bool parent_is_seq()    const RYML_NOEXCEPT { _C4RR(); return tree_->parent_is_seq(id_); } /**< Forward to @ref Tree::parent_is_seq(). Node must be readable. */\n    C4_ALWAYS_INLINE bool parent_is_map()    const RYML_NOEXCEPT { _C4RR(); return tree_->parent_is_map(id_); } /**< Forward to @ref Tree::parent_is_map(). Node must be readable. */\n\n    RYML_DEPRECATED(\"use has_key_anchor()\")  bool is_key_anchor() const noexcept { _C4RR(); return tree_->has_key_anchor(id_); }\n    RYML_DEPRECATED(\"use has_val_anchor()\")  bool is_val_hanchor() const noexcept { _C4RR(); return tree_->has_val_anchor(id_); }\n    RYML_DEPRECATED(\"use has_anchor()\")      bool is_anchor()     const noexcept { _C4RR(); return tree_->has_anchor(id_); }\n    RYML_DEPRECATED(\"use has_anchor() || is_ref()\") bool is_anchor_or_ref() const noexcept { _C4RR(); return tree_->is_anchor_or_ref(id_); }\n\n    /** @} */\n\npublic:\n\n    /** @name node container+scalar style predicates */\n    /** @{ */\n\n    // documentation to the right -->\n\n    C4_ALWAYS_INLINE bool type_has_any(NodeType_e bits)  const RYML_NOEXCEPT { _C4RR(); return tree_->type_has_any(id_, bits); }  /**< Forward to @ref Tree::type_has_any(). Node must be readable. */\n    C4_ALWAYS_INLINE bool type_has_all(NodeType_e bits)  const RYML_NOEXCEPT { _C4RR(); return tree_->type_has_all(id_, bits); }  /**< Forward to @ref Tree::type_has_all(). Node must be readable. */\n    C4_ALWAYS_INLINE bool type_has_none(NodeType_e bits) const RYML_NOEXCEPT { _C4RR(); return tree_->type_has_none(id_, bits); } /**< Forward to @ref Tree::type_has_none(). Node must be readable. */\n\n    C4_ALWAYS_INLINE bool is_container_styled() const RYML_NOEXCEPT { _C4RR(); return tree_->is_container_styled(id_); } /**< Forward to @ref Tree::is_container_styled(). Node must be readable. */\n    C4_ALWAYS_INLINE bool is_block()            const RYML_NOEXCEPT { _C4RR(); return tree_->is_block(id_); }   /**< Forward to @ref Tree::is_block(). Node must be readable. */\n    C4_ALWAYS_INLINE bool is_flow_sl()          const RYML_NOEXCEPT { _C4RR(); return tree_->is_flow_sl(id_); } /**< Forward to @ref Tree::is_flow_sl(). Node must be readable. */\n    C4_ALWAYS_INLINE bool is_flow_ml()          const RYML_NOEXCEPT { _C4RR(); return tree_->is_flow_ml(id_); } /**< Forward to @ref Tree::is_flow_ml(). Node must be readable. */\n    C4_ALWAYS_INLINE bool is_flow()             const RYML_NOEXCEPT { _C4RR(); return tree_->is_flow(id_); }    /**< Forward to @ref Tree::is_flow(). Node must be readable. */\n\n    C4_ALWAYS_INLINE bool is_key_styled()       const RYML_NOEXCEPT { _C4RR(); return tree_->is_key_styled(id_); }  /**< Forward to @ref Tree::is_key_styled(). Node must be readable. */\n    C4_ALWAYS_INLINE bool is_val_styled()       const RYML_NOEXCEPT { _C4RR(); return tree_->is_val_styled(id_); }  /**< Forward to @ref Tree::is_val_styled(). Node must be readable. */\n    C4_ALWAYS_INLINE bool is_key_literal()      const RYML_NOEXCEPT { _C4RR(); return tree_->is_key_literal(id_); } /**< Forward to @ref Tree::is_key_literal(). Node must be readable. */\n    C4_ALWAYS_INLINE bool is_val_literal()      const RYML_NOEXCEPT { _C4RR(); return tree_->is_val_literal(id_); } /**< Forward to @ref Tree::is_val_literal(). Node must be readable. */\n    C4_ALWAYS_INLINE bool is_key_folded()       const RYML_NOEXCEPT { _C4RR(); return tree_->is_key_folded(id_); }  /**< Forward to @ref Tree::is_key_folded(). Node must be readable. */\n    C4_ALWAYS_INLINE bool is_val_folded()       const RYML_NOEXCEPT { _C4RR(); return tree_->is_val_folded(id_); }  /**< Forward to @ref Tree::is_val_folded(). Node must be readable. */\n    C4_ALWAYS_INLINE bool is_key_squo()         const RYML_NOEXCEPT { _C4RR(); return tree_->is_key_squo(id_); }    /**< Forward to @ref Tree::is_key_squo(). Node must be readable. */\n    C4_ALWAYS_INLINE bool is_val_squo()         const RYML_NOEXCEPT { _C4RR(); return tree_->is_val_squo(id_); }    /**< Forward to @ref Tree::is_val_squo(). Node must be readable. */\n    C4_ALWAYS_INLINE bool is_key_dquo()         const RYML_NOEXCEPT { _C4RR(); return tree_->is_key_dquo(id_); }    /**< Forward to @ref Tree::is_key_dquo(). Node must be readable. */\n    C4_ALWAYS_INLINE bool is_val_dquo()         const RYML_NOEXCEPT { _C4RR(); return tree_->is_val_dquo(id_); }    /**< Forward to @ref Tree::is_val_dquo(). Node must be readable. */\n    C4_ALWAYS_INLINE bool is_key_plain()        const RYML_NOEXCEPT { _C4RR(); return tree_->is_key_plain(id_); }   /**< Forward to @ref Tree::is_key_plain(). Node must be readable. */\n    C4_ALWAYS_INLINE bool is_val_plain()        const RYML_NOEXCEPT { _C4RR(); return tree_->is_val_plain(id_); }   /**< Forward to @ref Tree::is_val_plain(). Node must be readable. */\n    C4_ALWAYS_INLINE bool is_key_quoted()       const RYML_NOEXCEPT { _C4RR(); return tree_->is_key_quoted(id_); }  /**< Forward to @ref Tree::is_key_quoted(). Node must be readable. */\n    C4_ALWAYS_INLINE bool is_val_quoted()       const RYML_NOEXCEPT { _C4RR(); return tree_->is_val_quoted(id_); }  /**< Forward to @ref Tree::is_val_quoted(). Node must be readable. */\n    C4_ALWAYS_INLINE bool is_quoted()           const RYML_NOEXCEPT { _C4RR(); return tree_->is_quoted(id_); }      /**< Forward to @ref Tree::is_quoted(). Node must be readable. */\n\n    /** @} */\n\npublic:\n\n    /** @name hierarchy predicates */\n    /** @{ */\n\n    // documentation to the right -->\n\n    C4_ALWAYS_INLINE bool is_root()    const RYML_NOEXCEPT { _C4RR(); return tree_->is_root(id_); } /**< Forward to @ref Tree::is_root(). Node must be readable. */\n    C4_ALWAYS_INLINE bool has_parent() const RYML_NOEXCEPT { _C4RR(); return tree_->has_parent(id_); } /**< Forward to @ref Tree::has_parent()  Node must be readable. */\n\n    C4_ALWAYS_INLINE bool has_child(ConstImpl const& n) const RYML_NOEXCEPT { _C4RR(); return n.readable() ? tree_->has_child(id_, n.m_id) : false; } /**< Forward to @ref Tree::has_child(). Node must be readable. */\n    C4_ALWAYS_INLINE bool has_child(id_type node) const RYML_NOEXCEPT { _C4RR(); return tree_->has_child(id_, node); } /**< Forward to @ref Tree::has_child(). Node must be readable. */\n    C4_ALWAYS_INLINE bool has_child(csubstr name) const RYML_NOEXCEPT { _C4RR(); return tree_->has_child(id_, name); } /**< Forward to @ref Tree::has_child(). Node must be readable. */\n    C4_ALWAYS_INLINE bool has_children() const RYML_NOEXCEPT { _C4RR(); return tree_->has_children(id_); } /**< Forward to @ref Tree::has_child(). Node must be readable. */\n\n    C4_ALWAYS_INLINE bool has_sibling(ConstImpl const& n) const RYML_NOEXCEPT { _C4RR(); return n.readable() ? tree_->has_sibling(id_, n.m_id) : false; } /**< Forward to @ref Tree::has_sibling(). Node must be readable. */\n    C4_ALWAYS_INLINE bool has_sibling(id_type node) const RYML_NOEXCEPT { _C4RR(); return tree_->has_sibling(id_, node); } /**< Forward to @ref Tree::has_sibling(). Node must be readable. */\n    C4_ALWAYS_INLINE bool has_sibling(csubstr name) const RYML_NOEXCEPT { _C4RR(); return tree_->has_sibling(id_, name); } /**< Forward to @ref Tree::has_sibling(). Node must be readable. */\n    C4_ALWAYS_INLINE bool has_other_siblings() const RYML_NOEXCEPT { _C4RR(); return tree_->has_other_siblings(id_); }  /**< Forward to @ref Tree::has_sibling(). Node must be readable. */\n\n    RYML_DEPRECATED(\"use has_other_siblings()\") bool has_siblings() const RYML_NOEXCEPT { _C4RR(); return tree_->has_siblings(id_); }\n\n    /** @} */\n\npublic:\n\n    /** @name hierarchy getters */\n    /** @{ */\n\n    // documentation to the right -->\n\n    template<class U=Impl>\n    C4_ALWAYS_INLINE auto doc(id_type i) RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { RYML_ASSERT(tree_); return {tree__, tree__->doc(i)}; } /**< Forward to @ref Tree::doc(). Node must be readable. */\n    /** succeeds even when the node may have invalid or seed id */\n    C4_ALWAYS_INLINE ConstImpl doc(id_type i) const RYML_NOEXCEPT { RYML_ASSERT(tree_); return {tree_, tree_->doc(i)}; }                /**< Forward to @ref Tree::doc(). Node must be readable. */\n\n    template<class U=Impl>\n    C4_ALWAYS_INLINE auto parent() RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _C4RR(); return {tree__, tree__->parent(id__)}; } /**< Forward to @ref Tree::parent(). Node must be readable. */\n    C4_ALWAYS_INLINE ConstImpl parent() const RYML_NOEXCEPT { _C4RR(); return {tree_, tree_->parent(id_)}; }                 /**< Forward to @ref Tree::parent(). Node must be readable. */\n\n    template<class U=Impl>\n    C4_ALWAYS_INLINE auto first_child() RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _C4RR(); return {tree__, tree__->first_child(id__)}; }  /**< Forward to @ref Tree::first_child(). Node must be readable. */\n    C4_ALWAYS_INLINE ConstImpl first_child() const RYML_NOEXCEPT { _C4RR(); return {tree_, tree_->first_child(id_)}; }                  /**< Forward to @ref Tree::first_child(). Node must be readable. */\n\n    template<class U=Impl>\n    C4_ALWAYS_INLINE auto last_child() RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _C4RR(); return {tree__, tree__->last_child(id__)}; }  /**< Forward to @ref Tree::last_child(). Node must be readable. */\n    C4_ALWAYS_INLINE ConstImpl last_child () const RYML_NOEXCEPT { _C4RR(); return {tree_, tree_->last_child (id_)}; }                /**< Forward to @ref Tree::last_child(). Node must be readable. */\n\n    template<class U=Impl>\n    C4_ALWAYS_INLINE auto child(id_type pos) RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _C4RR(); return {tree__, tree__->child(id__, pos)}; }  /**< Forward to @ref Tree::child(). Node must be readable. */\n    C4_ALWAYS_INLINE ConstImpl child(id_type pos) const RYML_NOEXCEPT { _C4RR(); return {tree_, tree_->child(id_, pos)}; }                  /**< Forward to @ref Tree::child(). Node must be readable. */\n\n    template<class U=Impl>\n    C4_ALWAYS_INLINE auto find_child(csubstr name)  RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _C4RR(); return {tree__, tree__->find_child(id__, name)}; }  /**< Forward to @ref Tree::first_child(). Node must be readable. */\n    C4_ALWAYS_INLINE ConstImpl find_child(csubstr name) const RYML_NOEXCEPT { _C4RR(); return {tree_, tree_->find_child(id_, name)}; }                   /**< Forward to @ref Tree::first_child(). Node must be readable. */\n\n    template<class U=Impl>\n    C4_ALWAYS_INLINE auto prev_sibling() RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _C4RR(); return {tree__, tree__->prev_sibling(id__)}; }  /**< Forward to @ref Tree::prev_sibling(). Node must be readable. */\n    C4_ALWAYS_INLINE ConstImpl prev_sibling() const RYML_NOEXCEPT { _C4RR(); return {tree_, tree_->prev_sibling(id_)}; }                  /**< Forward to @ref Tree::prev_sibling(). Node must be readable. */\n\n    template<class U=Impl>\n    C4_ALWAYS_INLINE auto next_sibling() RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _C4RR(); return {tree__, tree__->next_sibling(id__)}; }  /**< Forward to @ref Tree::next_sibling(). Node must be readable. */\n    C4_ALWAYS_INLINE ConstImpl next_sibling() const RYML_NOEXCEPT { _C4RR(); return {tree_, tree_->next_sibling(id_)}; }                  /**< Forward to @ref Tree::next_sibling(). Node must be readable. */\n\n    template<class U=Impl>\n    C4_ALWAYS_INLINE auto first_sibling() RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _C4RR(); return {tree__, tree__->first_sibling(id__)}; }  /**< Forward to @ref Tree::first_sibling(). Node must be readable. */\n    C4_ALWAYS_INLINE ConstImpl first_sibling() const RYML_NOEXCEPT { _C4RR(); return {tree_, tree_->first_sibling(id_)}; }                  /**< Forward to @ref Tree::first_sibling(). Node must be readable. */\n\n    template<class U=Impl>\n    C4_ALWAYS_INLINE auto last_sibling() RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _C4RR(); return {tree__, tree__->last_sibling(id__)}; }  /**< Forward to @ref Tree::last_sibling(). Node must be readable. */\n    C4_ALWAYS_INLINE ConstImpl last_sibling () const RYML_NOEXCEPT { _C4RR(); return {tree_, tree_->last_sibling(id_)}; }                 /**< Forward to @ref Tree::last_sibling(). Node must be readable. */\n\n    template<class U=Impl>\n    C4_ALWAYS_INLINE auto sibling(id_type pos) RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _C4RR(); return {tree__, tree__->sibling(id__, pos)}; }  /**< Forward to @ref Tree::sibling(). Node must be readable. */\n    C4_ALWAYS_INLINE ConstImpl sibling(id_type pos) const RYML_NOEXCEPT { _C4RR(); return {tree_, tree_->sibling(id_, pos)}; }                  /**< Forward to @ref Tree::sibling(). Node must be readable. */\n\n    template<class U=Impl>\n    C4_ALWAYS_INLINE auto find_sibling(csubstr name) RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _C4RR(); return {tree__, tree__->find_sibling(id__, name)}; }  /**< Forward to @ref Tree::find_sibling(). Node must be readable. */\n    C4_ALWAYS_INLINE ConstImpl find_sibling(csubstr name) const RYML_NOEXCEPT { _C4RR(); return {tree_, tree_->find_sibling(id_, name)}; }                  /**< Forward to @ref Tree::find_sibling(). Node must be readable. */\n\n    C4_ALWAYS_INLINE id_type num_children() const RYML_NOEXCEPT { _C4RR(); return tree_->num_children(id_); } /**< O(num_children). Forward to @ref Tree::num_children(). */\n    C4_ALWAYS_INLINE id_type num_siblings() const RYML_NOEXCEPT { _C4RR(); return tree_->num_siblings(id_); } /**< O(num_children). Forward to @ref Tree::num_siblings(). */\n    C4_ALWAYS_INLINE id_type num_other_siblings() const RYML_NOEXCEPT { _C4RR(); return tree_->num_other_siblings(id_); } /**< O(num_siblings). Forward to @ref Tree::num_other_siblings(). */\n    C4_ALWAYS_INLINE id_type child_pos(ConstImpl const& n) const RYML_NOEXCEPT { _C4RR(); _RYML_CB_ASSERT(tree_->m_callbacks, n.readable()); return tree_->child_pos(id_, n.m_id); } /**< O(num_children). Forward to @ref Tree::child_pos(). */\n    C4_ALWAYS_INLINE id_type sibling_pos(ConstImpl const& n) const RYML_NOEXCEPT { _C4RR(); _RYML_CB_ASSERT(tree_->callbacks(), n.readable()); return tree_->child_pos(tree_->parent(id_), n.m_id); } /**< O(num_siblings). Forward to @ref Tree::sibling_pos(). */\n\n    C4_ALWAYS_INLINE id_type depth_asc() const RYML_NOEXCEPT { _C4RR(); return tree_->depth_asc(id_); } /** O(log(num_nodes)). Forward to Tree::depth_asc(). Node must be readable. */\n    C4_ALWAYS_INLINE id_type depth_desc() const RYML_NOEXCEPT { _C4RR(); return tree_->depth_desc(id_); } /** O(num_nodes). Forward to Tree::depth_desc(). Node must be readable. */\n\n    /** @} */\n\npublic:\n\n    /** @name square_brackets\n     * operator[] */\n    /** @{ */\n\n    /** Find child by key; complexity is O(num_children).\n     *\n     * Returns the requested node, or an object in seed state if no\n     * such child is found (see @ref NodeRef for an explanation of\n     * what is seed state). When the object is in seed state, using it\n     * to read from the tree is UB. The seed node can be used to write\n     * to the tree provided that its create() method is called prior\n     * to writing, which happens in most modifying methods in\n     * NodeRef. It is the caller's responsibility to verify that the\n     * returned node is readable before subsequently using it to read\n     * from the tree.\n     *\n     * @warning the calling object must be readable. This precondition\n     * is asserted. The assertion is performed only if @ref\n     * RYML_USE_ASSERT is set to true. As with the non-const overload,\n     * it is UB to call this method if the node is not readable.\n     *\n     * @see https://github.com/biojppm/rapidyaml/issues/389 */\n    template<class U=Impl>\n    C4_ALWAYS_INLINE auto operator[] (csubstr key) RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl)\n    {\n        _C4RR();\n        id_type ch = tree__->find_child(id__, key);\n        return ch != NONE ? Impl(tree__, ch) : Impl(tree__, id__, key);\n    }\n\n    /** Find child by position; complexity is O(pos).\n     *\n     * Returns the requested node, or an object in seed state if no\n     * such child is found (see @ref NodeRef for an explanation of\n     * what is seed state). When the object is in seed state, using it\n     * to read from the tree is UB. The seed node can be used to write\n     * to the tree provided that its create() method is called prior\n     * to writing, which happens in most modifying methods in\n     * NodeRef. It is the caller's responsibility to verify that the\n     * returned node is readable before subsequently using it to read\n     * from the tree.\n     *\n     * @warning the calling object must be readable. This precondition\n     * is asserted. The assertion is performed only if @ref\n     * RYML_USE_ASSERT is set to true. As with the non-const overload,\n     * it is UB to call this method if the node is not readable.\n     *\n     * @see https://github.com/biojppm/rapidyaml/issues/389 */\n    template<class U=Impl>\n    C4_ALWAYS_INLINE auto operator[] (id_type pos) RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl)\n    {\n        _C4RR();\n        id_type ch = tree__->child(id__, pos);\n        return ch != NONE ? Impl(tree__, ch) : Impl(tree__, id__, pos);\n    }\n\n    /** Find a child by key; complexity is O(num_children).\n     *\n     * Behaves similar to the non-const overload, but further asserts\n     * that the returned node is readable (because it can never be in\n     * a seed state). The assertion is performed only if @ref\n     * RYML_USE_ASSERT is set to true. As with the non-const overload,\n     * it is UB to use the return value if it is not valid.\n     *\n     * @see https://github.com/biojppm/rapidyaml/issues/389  */\n    C4_ALWAYS_INLINE ConstImpl operator[] (csubstr key) const RYML_NOEXCEPT\n    {\n        _C4RR();\n        id_type ch = tree_->find_child(id_, key);\n        _RYML_CB_ASSERT(tree_->m_callbacks, ch != NONE);\n        return {tree_, ch};\n    }\n\n    /** Find a child by position; complexity is O(pos).\n     *\n     * Behaves similar to the non-const overload, but further asserts\n     * that the returned node is readable (because it can never be in\n     * a seed state). This assertion is performed only if @ref\n     * RYML_USE_ASSERT is set to true. As with the non-const overload,\n     * it is UB to use the return value if it is not valid.\n     *\n     * @see https://github.com/biojppm/rapidyaml/issues/389  */\n    C4_ALWAYS_INLINE ConstImpl operator[] (id_type pos) const RYML_NOEXCEPT\n    {\n        _C4RR();\n        id_type ch = tree_->child(id_, pos);\n        _RYML_CB_ASSERT(tree_->m_callbacks, ch != NONE);\n        return {tree_, ch};\n    }\n\n    /** @} */\n\npublic:\n\n    /** @name at\n     *\n     * These functions are the analogue to operator[], with the\n     * difference that they emit an error instead of an\n     * assertion. That is, if any of the pre or post conditions is\n     * violated, an error is always emitted (resulting in a call to\n     * the error callback).\n     *\n     * @{ */\n\n    /** Find child by key; complexity is O(num_children).\n     *\n     * Returns the requested node, or an object in seed state if no\n     * such child is found (see @ref NodeRef for an explanation of\n     * what is seed state). When the object is in seed state, using it\n     * to read from the tree is UB. The seed node can be subsequently\n     * used to write to the tree provided that its create() method is\n     * called prior to writing, which happens inside most mutating\n     * methods in NodeRef. It is the caller's responsibility to verify\n     * that the returned node is readable before subsequently using it\n     * to read from the tree.\n     *\n     * @warning This method will call the error callback (regardless\n     * of build type or of the value of RYML_USE_ASSERT) whenever any\n     * of the following preconditions is violated: a) the object is\n     * valid (points at a tree and a node), b) the calling object must\n     * be readable (must not be in seed state), c) the calling object\n     * must be pointing at a MAP node. The preconditions are similar\n     * to the non-const operator[](csubstr), but instead of using\n     * assertions, this function directly checks those conditions and\n     * calls the error callback if any of the checks fail.\n     *\n     * @note since it is valid behavior for the returned node to be in\n     * seed state, the error callback is not invoked when this\n     * happens. */\n    template<class U=Impl>\n    C4_ALWAYS_INLINE auto at(csubstr key) -> _C4_IF_MUTABLE(Impl)\n    {\n        RYML_CHECK(tree_ != nullptr);\n        _RYML_CB_CHECK(tree_->m_callbacks, (id_ >= 0 && id_ < tree_->capacity()));\n        _RYML_CB_CHECK(tree_->m_callbacks, ((Impl const*)this)->readable());\n        _RYML_CB_CHECK(tree_->m_callbacks, tree_->is_map(id_));\n        id_type ch = tree__->find_child(id__, key);\n        return ch != NONE ? Impl(tree__, ch) : Impl(tree__, id__, key);\n    }\n\n    /** Find child by position; complexity is O(pos).\n     *\n     * Returns the requested node, or an object in seed state if no\n     * such child is found (see @ref NodeRef for an explanation of\n     * what is seed state). When the object is in seed state, using it\n     * to read from the tree is UB. The seed node can be used to write\n     * to the tree provided that its create() method is called prior\n     * to writing, which happens in most modifying methods in\n     * NodeRef. It is the caller's responsibility to verify that the\n     * returned node is readable before subsequently using it to read\n     * from the tree.\n     *\n     * @warning This method will call the error callback (regardless\n     * of build type or of the value of RYML_USE_ASSERT) whenever any\n     * of the following preconditions is violated: a) the object is\n     * valid (points at a tree and a node), b) the calling object must\n     * be readable (must not be in seed state), c) the calling object\n     * must be pointing at a MAP node. The preconditions are similar\n     * to the non-const operator[](id_type), but instead of using\n     * assertions, this function directly checks those conditions and\n     * calls the error callback if any of the checks fail.\n     *\n     * @note since it is valid behavior for the returned node to be in\n     * seed state, the error callback is not invoked when this\n     * happens. */\n    template<class U=Impl>\n    C4_ALWAYS_INLINE auto at(id_type pos) -> _C4_IF_MUTABLE(Impl)\n    {\n        RYML_CHECK(tree_ != nullptr);\n        const id_type cap = tree_->capacity();\n        _RYML_CB_CHECK(tree_->m_callbacks, (id_ >= 0 && id_ < cap));\n        _RYML_CB_CHECK(tree_->m_callbacks, (pos >= 0 && pos < cap));\n        _RYML_CB_CHECK(tree_->m_callbacks, ((Impl const*)this)->readable());\n        _RYML_CB_CHECK(tree_->m_callbacks, tree_->is_container(id_));\n        id_type ch = tree__->child(id__, pos);\n        return ch != NONE ? Impl(tree__, ch) : Impl(tree__, id__, pos);\n    }\n\n    /** Get a child by name, with error checking; complexity is\n     * O(num_children).\n     *\n     * Behaves as operator[](csubstr) const, but always raises an\n     * error (even when RYML_USE_ASSERT is set to false) when the\n     * returned node does not exist, or when this node is not\n     * readable, or when it is not a map. This behaviour is similar to\n     * std::vector::at(), but the error consists in calling the error\n     * callback instead of directly raising an exception. */\n    ConstImpl at(csubstr key) const\n    {\n        RYML_CHECK(tree_ != nullptr);\n        _RYML_CB_CHECK(tree_->m_callbacks, (id_ >= 0 && id_ < tree_->capacity()));\n        _RYML_CB_CHECK(tree_->m_callbacks, ((Impl const*)this)->readable());\n        _RYML_CB_CHECK(tree_->m_callbacks, tree_->is_map(id_));\n        id_type ch = tree_->find_child(id_, key);\n        _RYML_CB_CHECK(tree_->m_callbacks, ch != NONE);\n        return {tree_, ch};\n    }\n\n    /** Get a child by position, with error checking; complexity is\n     * O(pos).\n     *\n     * Behaves as operator[](id_type) const, but always raises an error\n     * (even when RYML_USE_ASSERT is set to false) when the returned\n     * node does not exist, or when this node is not readable, or when\n     * it is not a container. This behaviour is similar to\n     * std::vector::at(), but the error consists in calling the error\n     * callback instead of directly raising an exception. */\n    ConstImpl at(id_type pos) const\n    {\n        RYML_CHECK(tree_ != nullptr);\n        const id_type cap = tree_->capacity();\n        _RYML_CB_CHECK(tree_->m_callbacks, (id_ >= 0 && id_ < cap));\n        _RYML_CB_CHECK(tree_->m_callbacks, (pos >= 0 && pos < cap));\n        _RYML_CB_CHECK(tree_->m_callbacks, ((Impl const*)this)->readable());\n        _RYML_CB_CHECK(tree_->m_callbacks, tree_->is_container(id_));\n        const id_type ch = tree_->child(id_, pos);\n        _RYML_CB_CHECK(tree_->m_callbacks, ch != NONE);\n        return {tree_, ch};\n    }\n\n    /** @} */\n\npublic:\n\n    /** @name deserialization */\n    /** @{ */\n\n    /** deserialize the node's val to the given variable, forwarding\n     * to the user-overrideable @ref read() function. */\n    template<class T>\n    ConstImpl const& operator>> (T &v) const\n    {\n        _C4RR();\n        if( ! read((ConstImpl const&)*this, &v))\n            _RYML_CB_ERR(tree_->m_callbacks, \"could not deserialize value\");\n        return *((ConstImpl const*)this);\n    }\n\n    /** deserialize the node's key to the given variable, forwarding\n     * to the user-overrideable @ref read() function; use @ref key()\n     * to disambiguate; for example: `node >> ryml::key(var)` */\n    template<class T>\n    ConstImpl const& operator>> (Key<T> v) const\n    {\n        _C4RR();\n        if(key().empty() || ! from_chars(key(), &v.k))\n            _RYML_CB_ERR(tree_->m_callbacks, \"could not deserialize key\");\n        return *((ConstImpl const*)this);\n    }\n\n    /** deserialize the node's key as base64. lightweight wrapper over @ref deserialize_key() */\n    ConstImpl const& operator>> (Key<fmt::base64_wrapper> w) const\n    {\n        deserialize_key(w.wrapper);\n        return *((ConstImpl const*)this);\n    }\n\n    /** deserialize the node's val as base64. lightweight wrapper over @ref deserialize_val() */\n    ConstImpl const& operator>> (fmt::base64_wrapper w) const\n    {\n        deserialize_val(w);\n        return *((ConstImpl const*)this);\n    }\n\n    /** decode the base64-encoded key and assign the\n     * decoded blob to the given buffer/\n     * @return the size of base64-decoded blob */\n    size_t deserialize_key(fmt::base64_wrapper v) const\n    {\n        _C4RR();\n        return from_chars(key(), &v);\n    }\n    /** decode the base64-encoded key and assign the\n     * decoded blob to the given buffer/\n     * @return the size of base64-decoded blob */\n    size_t deserialize_val(fmt::base64_wrapper v) const\n    {\n        _C4RR();\n        return from_chars(val(), &v);\n    };\n\n    /** look for a child by name, if it exists assign to var. return\n     * true if the child existed. */\n    template<class T>\n    bool get_if(csubstr name, T *var) const\n    {\n        _C4RR();\n        ConstImpl ch = find_child(name);\n        if(!ch.readable())\n            return false;\n        ch >> *var;\n        return true;\n    }\n\n    /** look for a child by name, if it exists assign to var,\n     * otherwise default to fallback. return true if the child\n     * existed. */\n    template<class T>\n    bool get_if(csubstr name, T *var, T const& fallback) const\n    {\n        _C4RR();\n        ConstImpl ch = find_child(name);\n        if(ch.readable())\n        {\n            ch >> *var;\n            return true;\n        }\n        else\n        {\n            *var = fallback;\n            return false;\n        }\n    }\n\n    /** @} */\n\npublic:\n\n    #if defined(__clang__)\n    #   pragma clang diagnostic push\n    #   pragma clang diagnostic ignored \"-Wnull-dereference\"\n    #elif defined(__GNUC__)\n    #   pragma GCC diagnostic push\n    #   if __GNUC__ >= 6\n    #       pragma GCC diagnostic ignored \"-Wnull-dereference\"\n    #   endif\n    #endif\n\n    /** @name iteration */\n    /** @{ */\n\n    using iterator = detail::child_iterator<Impl>;\n    using const_iterator = detail::child_iterator<ConstImpl>;\n    using children_view = detail::children_view_<Impl>;\n    using const_children_view = detail::children_view_<ConstImpl>;\n\n    /** get an iterator to the first child */\n    template<class U=Impl>\n    C4_ALWAYS_INLINE auto begin() RYML_NOEXCEPT -> _C4_IF_MUTABLE(iterator) { _C4RR(); return iterator(tree__, tree__->first_child(id__)); }\n    /** get an iterator to the first child */\n    C4_ALWAYS_INLINE const_iterator begin() const RYML_NOEXCEPT { _C4RR(); return const_iterator(tree_, tree_->first_child(id_)); }\n    /** get an iterator to the first child */\n    C4_ALWAYS_INLINE const_iterator cbegin() const RYML_NOEXCEPT { _C4RR(); return const_iterator(tree_, tree_->first_child(id_)); }\n\n    /** get an iterator to after the last child */\n    template<class U=Impl>\n    C4_ALWAYS_INLINE auto end() RYML_NOEXCEPT -> _C4_IF_MUTABLE(iterator) { _C4RR(); return iterator(tree__, NONE); }\n    /** get an iterator to after the last child */\n    C4_ALWAYS_INLINE const_iterator end() const RYML_NOEXCEPT { _C4RR(); return const_iterator(tree_, NONE); }\n    /** get an iterator to after the last child */\n    C4_ALWAYS_INLINE const_iterator cend() const RYML_NOEXCEPT { _C4RR(); return const_iterator(tree_, tree_->first_child(id_)); }\n\n    /** get an iterable view over children */\n    template<class U=Impl>\n    C4_ALWAYS_INLINE auto children() RYML_NOEXCEPT -> _C4_IF_MUTABLE(children_view) { _C4RR(); return children_view(begin(), end()); }\n    /** get an iterable view over children */\n    C4_ALWAYS_INLINE const_children_view children() const RYML_NOEXCEPT { _C4RR(); return const_children_view(begin(), end()); }\n    /** get an iterable view over children */\n    C4_ALWAYS_INLINE const_children_view cchildren() const RYML_NOEXCEPT { _C4RR(); return const_children_view(begin(), end()); }\n\n    /** get an iterable view over all siblings (including the calling node) */\n    template<class U=Impl>\n    C4_ALWAYS_INLINE auto siblings() RYML_NOEXCEPT -> _C4_IF_MUTABLE(children_view)\n    {\n        _C4RR();\n        NodeData const *nd = tree__->get(id__);\n        return (nd->m_parent != NONE) ? // does it have a parent?\n            children_view(iterator(tree__, tree_->get(nd->m_parent)->m_first_child), iterator(tree__, NONE))\n            :\n            children_view(end(), end());\n    }\n    /** get an iterable view over all siblings (including the calling node) */\n    C4_ALWAYS_INLINE const_children_view siblings() const RYML_NOEXCEPT\n    {\n        _C4RR();\n        NodeData const *nd = tree_->get(id_);\n        return (nd->m_parent != NONE) ? // does it have a parent?\n            const_children_view(const_iterator(tree_, tree_->get(nd->m_parent)->m_first_child), const_iterator(tree_, NONE))\n            :\n            const_children_view(end(), end());\n    }\n    /** get an iterable view over all siblings (including the calling node) */\n    C4_ALWAYS_INLINE const_children_view csiblings() const RYML_NOEXCEPT { return siblings(); }\n\n    /** visit every child node calling fn(node) */\n    template<class Visitor>\n    bool visit(Visitor fn, id_type indentation_level=0, bool skip_root=true) const RYML_NOEXCEPT\n    {\n        _C4RR();\n        return detail::_visit(*(ConstImpl const*)this, fn, indentation_level, skip_root);\n    }\n    /** visit every child node calling fn(node) */\n    template<class Visitor, class U=Impl>\n    auto visit(Visitor fn, id_type indentation_level=0, bool skip_root=true) RYML_NOEXCEPT\n        -> _C4_IF_MUTABLE(bool)\n    {\n        _C4RR();\n        return detail::_visit(*(Impl*)this, fn, indentation_level, skip_root);\n    }\n\n    /** visit every child node calling fn(node, level) */\n    template<class Visitor>\n    bool visit_stacked(Visitor fn, id_type indentation_level=0, bool skip_root=true) const RYML_NOEXCEPT\n    {\n        _C4RR();\n        return detail::_visit_stacked(*(ConstImpl const*)this, fn, indentation_level, skip_root);\n    }\n    /** visit every child node calling fn(node, level) */\n    template<class Visitor, class U=Impl>\n    auto visit_stacked(Visitor fn, id_type indentation_level=0, bool skip_root=true) RYML_NOEXCEPT\n        -> _C4_IF_MUTABLE(bool)\n    {\n        _C4RR();\n        return detail::_visit_stacked(*(Impl*)this, fn, indentation_level, skip_root);\n    }\n\n    /** @} */\n\n    #if defined(__clang__)\n    #   pragma clang diagnostic pop\n    #elif defined(__GNUC__)\n    #   pragma GCC diagnostic pop\n    #endif\n\n    #undef _C4_IF_MUTABLE\n    #undef _C4RR\n    #undef tree_\n    #undef tree__\n    #undef id_\n    #undef id__\n\n    C4_SUPPRESS_WARNING_GCC_CLANG_POP\n};\n} // detail\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n/** Holds a pointer to an existing tree, and a node id. It can be used\n * only to read from the tree.\n *\n * @warning The lifetime of the tree must be larger than that of this\n * object. It is up to the user to ensure that this happens. */\nclass RYML_EXPORT ConstNodeRef : public detail::RoNodeMethods<ConstNodeRef, ConstNodeRef>\n{\npublic:\n\n    using tree_type = Tree const;\n\npublic:\n\n    Tree const* C4_RESTRICT m_tree;\n    id_type m_id;\n\n    friend NodeRef;\n    friend struct detail::RoNodeMethods<ConstNodeRef, ConstNodeRef>;\n\npublic:\n\n    /** @name construction */\n    /** @{ */\n\n    ConstNodeRef() noexcept : m_tree(nullptr), m_id(NONE) {}\n    ConstNodeRef(Tree const &t) noexcept : m_tree(&t), m_id(t .root_id()) {}\n    ConstNodeRef(Tree const *t) noexcept : m_tree(t ), m_id(t->root_id()) {}\n    ConstNodeRef(Tree const *t, id_type id) noexcept : m_tree(t), m_id(id) {}\n    ConstNodeRef(std::nullptr_t) noexcept : m_tree(nullptr), m_id(NONE) {}\n\n    ConstNodeRef(ConstNodeRef const&) noexcept = default;\n    ConstNodeRef(ConstNodeRef     &&) noexcept = default;\n\n    ConstNodeRef(NodeRef const&) noexcept;\n    ConstNodeRef(NodeRef     &&) noexcept;\n\n    /** @} */\n\npublic:\n\n    /** @name assignment */\n    /** @{ */\n\n    ConstNodeRef& operator= (std::nullptr_t) noexcept { m_tree = nullptr; m_id = NONE; return *this; }\n\n    ConstNodeRef& operator= (ConstNodeRef const&) noexcept = default;\n    ConstNodeRef& operator= (ConstNodeRef     &&) noexcept = default;\n\n    ConstNodeRef& operator= (NodeRef const&) noexcept;\n    ConstNodeRef& operator= (NodeRef     &&) noexcept;\n\n\n    /** @} */\n\npublic:\n\n    /** @name state queries\n     *\n     * see @ref NodeRef for an explanation on what these states mean */\n    /** @{ */\n\n    C4_ALWAYS_INLINE bool invalid() const noexcept { return (!m_tree) || (m_id == NONE); }\n    /** because a ConstNodeRef cannot be used to write to the tree,\n     * readable() has the same meaning as !invalid() */\n    C4_ALWAYS_INLINE bool readable() const noexcept { return m_tree != nullptr && m_id != NONE; }\n    /** because a ConstNodeRef cannot be used to write to the tree, it can never be a seed.\n     * This method is provided for API equivalence between ConstNodeRef and NodeRef. */\n    constexpr static C4_ALWAYS_INLINE bool is_seed() noexcept { return false; }\n\n    RYML_DEPRECATED(\"use one of readable(), is_seed() or !invalid()\") bool valid() const noexcept { return m_tree != nullptr && m_id != NONE; }\n\n    /** @} */\n\npublic:\n\n    /** @name member getters */\n    /** @{ */\n\n    C4_ALWAYS_INLINE Tree const* tree() const noexcept { return m_tree; }\n    C4_ALWAYS_INLINE id_type id() const noexcept { return m_id; }\n\n    /** @} */\n\npublic:\n\n    /** @name comparisons */\n    /** @{ */\n\n    C4_ALWAYS_INLINE bool operator== (ConstNodeRef const& that) const RYML_NOEXCEPT { return that.m_tree == m_tree && m_id == that.m_id; }\n    C4_ALWAYS_INLINE bool operator!= (ConstNodeRef const& that) const RYML_NOEXCEPT { return ! this->operator== (that); }\n\n    /** @cond dev */\n    RYML_DEPRECATED(\"use invalid()\")  bool operator== (std::nullptr_t) const noexcept { return m_tree == nullptr || m_id == NONE; }\n    RYML_DEPRECATED(\"use !invalid()\") bool operator!= (std::nullptr_t) const noexcept { return !(m_tree == nullptr || m_id == NONE); }\n\n    RYML_DEPRECATED(\"use (this->val() == s)\") bool operator== (csubstr s) const RYML_NOEXCEPT { RYML_ASSERT(m_tree); _RYML_CB_ASSERT(m_tree->m_callbacks, m_id != NONE); return m_tree->val(m_id) == s; }\n    RYML_DEPRECATED(\"use (this->val() != s)\") bool operator!= (csubstr s) const RYML_NOEXCEPT { RYML_ASSERT(m_tree); _RYML_CB_ASSERT(m_tree->m_callbacks, m_id != NONE); return m_tree->val(m_id) != s; }\n    /** @endcond */\n\n    /** @} */\n\n};\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n/** A reference to a node in an existing yaml tree, offering a more\n * convenient API than the index-based API used in the tree.\n *\n * Unlike its imutable ConstNodeRef peer, a NodeRef can be used to\n * mutate the tree, both by writing to existing nodes and by creating\n * new nodes to subsequently write to. Semantically, a NodeRef\n * object can be in one of three states:\n *\n * ```text\n * invalid  := not pointing at anything\n * readable := points at an existing tree/node\n * seed     := points at an existing tree, and the node\n *             may come to exist, if we write to it.\n * ```\n *\n * So both `readable` and `seed` are states where the node is also `valid`.\n *\n * ```cpp\n * Tree t = parse_in_arena(\"{a: b}\");\n * NodeRef invalid; // not pointing at anything.\n * NodeRef readable = t[\"a\"]; // also valid, because \"a\" exists\n * NodeRef seed = t[\"none\"]; // also valid, but is seed because \"none\" is not in the map\n * ```\n *\n * When the object is in seed state, using it to read from the tree is\n * UB. The seed node can be used to write to the tree, provided that\n * its create() method is called prior to writing, which happens in\n * most modifying methods in NodeRef.\n *\n * It is the owners's responsibility to verify that an existing\n * node is readable before subsequently using it to read from the\n * tree.\n *\n * @warning The lifetime of the tree must be larger than that of this\n * object. It is up to the user to ensure that this happens.\n */\nclass RYML_EXPORT NodeRef : public detail::RoNodeMethods<NodeRef, ConstNodeRef>\n{\npublic:\n\n    using tree_type = Tree;\n    using base_type = detail::RoNodeMethods<NodeRef, ConstNodeRef>;\n\nprivate:\n\n    Tree *C4_RESTRICT m_tree;\n    id_type m_id;\n\n    /** This member is used to enable lazy operator[] writing. When a child\n     * with a key or index is not found, m_id is set to the id of the parent\n     * and the asked-for key or index are stored in this member until a write\n     * does happen. Then it is given as key or index for creating the child.\n     * When a key is used, the csubstr stores it (so the csubstr's string is\n     * non-null and the csubstr's size is different from NONE). When an index is\n     * used instead, the csubstr's string is set to null, and only the csubstr's\n     * size is set to a value different from NONE. Otherwise, when operator[]\n     * does find the child then this member is empty: the string is null and\n     * the size is NONE. */\n    csubstr m_seed;\n\n    friend ConstNodeRef;\n    friend struct detail::RoNodeMethods<NodeRef, ConstNodeRef>;\n\n    // require valid: a helper macro, undefined at the end\n    #define _C4RR()                                                         \\\n        RYML_ASSERT(m_tree != nullptr);                                     \\\n        _RYML_CB_ASSERT(m_tree->m_callbacks, m_id != NONE && !is_seed())\n    // require id: a helper macro, undefined at the end\n    #define _C4RID()                                                        \\\n        RYML_ASSERT(m_tree != nullptr);                                     \\\n        _RYML_CB_ASSERT(m_tree->m_callbacks, m_id != NONE)\n\npublic:\n\n    /** @name construction */\n    /** @{ */\n\n    NodeRef() noexcept : m_tree(nullptr), m_id(NONE), m_seed() { _clear_seed(); }\n    NodeRef(Tree &t) noexcept : m_tree(&t), m_id(t .root_id()), m_seed() { _clear_seed(); }\n    NodeRef(Tree *t) noexcept : m_tree(t ), m_id(t->root_id()), m_seed() { _clear_seed(); }\n    NodeRef(Tree *t, id_type id) noexcept : m_tree(t), m_id(id), m_seed() { _clear_seed(); }\n    NodeRef(Tree *t, id_type id, id_type seed_pos) noexcept : m_tree(t), m_id(id), m_seed() { m_seed.str = nullptr; m_seed.len = (size_t)seed_pos; }\n    NodeRef(Tree *t, id_type id, csubstr  seed_key) noexcept : m_tree(t), m_id(id), m_seed(seed_key) {}\n    NodeRef(std::nullptr_t) noexcept : m_tree(nullptr), m_id(NONE), m_seed() {}\n\n    inline void _clear_seed() noexcept { /*do the following manually or an assert is triggered: */ m_seed.str = nullptr; m_seed.len = npos; }\n\n    /** @} */\n\npublic:\n\n    /** @name assignment */\n    /** @{ */\n\n    NodeRef(NodeRef const&) noexcept = default;\n    NodeRef(NodeRef     &&) noexcept = default;\n\n    NodeRef& operator= (NodeRef const&) noexcept = default;\n    NodeRef& operator= (NodeRef     &&) noexcept = default;\n\n    /** @} */\n\npublic:\n\n    /** @name state_queries\n     * @{ */\n\n    /** true if the object is not referring to any existing or seed node. @see the doc for @ref NodeRef */\n    inline bool invalid() const noexcept { return m_tree == nullptr || m_id == NONE; }\n    /** true if the object is not invalid and in seed state. @see the doc for @ref NodeRef */\n    inline bool is_seed() const noexcept { return (m_tree != NULL && m_id != NONE) && (m_seed.str != nullptr || m_seed.len != (size_t)NONE); }\n    /** true if the object is not invalid and not in seed state. @see the doc for @ref NodeRef */\n    inline bool readable() const noexcept { return (m_tree != NULL && m_id != NONE) && (m_seed.str == nullptr && m_seed.len == (size_t)NONE); }\n\n    RYML_DEPRECATED(\"use one of readable(), is_seed() or !invalid()\") inline bool valid() const { return m_tree != nullptr && m_id != NONE; }\n\n    /** @} */\n\npublic:\n\n    /** @name comparisons */\n    /** @{ */\n\n    bool operator== (NodeRef const& that) const\n    {\n        if(m_tree == that.m_tree && m_id == that.m_id)\n        {\n            bool seed = is_seed();\n            if(seed == that.is_seed())\n            {\n                if(seed)\n                {\n                    return (m_seed.len == that.m_seed.len)\n                        && (m_seed.str == that.m_seed.str\n                            || m_seed == that.m_seed); // do strcmp only in the last resort\n                }\n                return true;\n            }\n        }\n        return false;\n    }\n    inline bool operator!= (NodeRef const& that) const { return ! this->operator==(that); }\n\n    inline bool operator== (ConstNodeRef const& that) const { return m_tree == that.m_tree && m_id == that.m_id && !is_seed(); }\n    inline bool operator!= (ConstNodeRef const& that) const { return ! this->operator==(that); }\n\n    /** @cond dev */\n    RYML_DEPRECATED(\"use !readable()\") bool operator== (std::nullptr_t) const { return m_tree == nullptr || m_id == NONE || is_seed(); }\n    RYML_DEPRECATED(\"use readable()\")  bool operator!= (std::nullptr_t) const { return !(m_tree == nullptr || m_id == NONE || is_seed()); }\n\n    RYML_DEPRECATED(\"use `this->val() == s`\") bool operator== (csubstr s) const { _C4RR(); _RYML_CB_ASSERT(m_tree->m_callbacks, has_val()); return m_tree->val(m_id) == s; }\n    RYML_DEPRECATED(\"use `this->val() != s`\") bool operator!= (csubstr s) const { _C4RR(); _RYML_CB_ASSERT(m_tree->m_callbacks, has_val()); return m_tree->val(m_id) != s; }\n    /** @endcond */\n\npublic:\n\n    /** @name node_property_getters\n     * @{ */\n\n    C4_ALWAYS_INLINE Tree * tree() noexcept { return m_tree; }\n    C4_ALWAYS_INLINE Tree const* tree() const noexcept { return m_tree; }\n\n    C4_ALWAYS_INLINE id_type id() const noexcept { return m_id; }\n\n    /** @} */\n\npublic:\n\n    /** @name node_modifiers */\n    /** @{ */\n\n    void create() { _apply_seed(); }\n\n    void change_type(NodeType t) { _C4RR(); m_tree->change_type(m_id, t); }\n\n    void set_type(NodeType t) { _apply_seed(); m_tree->_set_flags(m_id, t); }\n    void set_key(csubstr key) { _apply_seed(); m_tree->_set_key(m_id, key); }\n    void set_val(csubstr val) { _apply_seed(); m_tree->_set_val(m_id, val); }\n    void set_key_tag(csubstr key_tag) { _apply_seed(); m_tree->set_key_tag(m_id, key_tag); }\n    void set_val_tag(csubstr val_tag) { _apply_seed(); m_tree->set_val_tag(m_id, val_tag); }\n    void set_key_anchor(csubstr key_anchor) { _apply_seed(); m_tree->set_key_anchor(m_id, key_anchor); }\n    void set_val_anchor(csubstr val_anchor) { _apply_seed(); m_tree->set_val_anchor(m_id, val_anchor); }\n    void set_key_ref(csubstr key_ref) { _apply_seed(); m_tree->set_key_ref(m_id, key_ref); }\n    void set_val_ref(csubstr val_ref) { _apply_seed(); m_tree->set_val_ref(m_id, val_ref); }\n\n    void set_container_style(NodeType_e style) { _C4RR(); m_tree->set_container_style(m_id, style); }\n    void set_key_style(NodeType_e style) { _C4RR(); m_tree->set_key_style(m_id, style); }\n    void set_val_style(NodeType_e style) { _C4RR(); m_tree->set_val_style(m_id, style); }\n\npublic:\n\n    inline void clear()\n    {\n        if(is_seed())\n            return;\n        m_tree->remove_children(m_id);\n        m_tree->_clear(m_id);\n    }\n\n    inline void clear_key()\n    {\n        if(is_seed())\n            return;\n        m_tree->_clear_key(m_id);\n    }\n\n    inline void clear_val()\n    {\n        if(is_seed())\n            return;\n        m_tree->_clear_val(m_id);\n    }\n\n    inline void clear_children()\n    {\n        if(is_seed())\n            return;\n        m_tree->remove_children(m_id);\n    }\n\n    inline void operator= (NodeType_e t)\n    {\n        _apply_seed();\n        m_tree->_add_flags(m_id, t);\n    }\n\n    inline void operator|= (NodeType_e t)\n    {\n        _apply_seed();\n        m_tree->_add_flags(m_id, t);\n    }\n\n    inline void operator= (NodeInit const& v)\n    {\n        _apply_seed();\n        _apply(v);\n    }\n\n    inline void operator= (NodeScalar const& v)\n    {\n        _apply_seed();\n        _apply(v);\n    }\n\n    inline void operator= (std::nullptr_t)\n    {\n        _apply_seed();\n        _apply(csubstr{});\n    }\n\n    inline void operator= (csubstr v)\n    {\n        _apply_seed();\n        _apply(v);\n    }\n\n    template<size_t N>\n    inline void operator= (const char (&v)[N])\n    {\n        _apply_seed();\n        csubstr sv;\n        sv.assign<N>(v);\n        _apply(sv);\n    }\n\n    /** @} */\n\npublic:\n\n    /** @name serialization */\n    /** @{ */\n\n    /** serialize a variable to the arena */\n    template<class T>\n    inline csubstr to_arena(T const& C4_RESTRICT s)\n    {\n        RYML_ASSERT(m_tree); // no need for valid or readable\n        return m_tree->to_arena(s);\n    }\n\n    template<class T>\n    size_t set_key_serialized(T const& C4_RESTRICT k)\n    {\n        _apply_seed();\n        csubstr s = m_tree->to_arena(k);\n        m_tree->_set_key(m_id, s);\n        return s.len;\n    }\n    size_t set_key_serialized(std::nullptr_t)\n    {\n        _apply_seed();\n        m_tree->_set_key(m_id, csubstr{});\n        return 0;\n    }\n\n    template<class T>\n    size_t set_val_serialized(T const& C4_RESTRICT v)\n    {\n        _apply_seed();\n        csubstr s = m_tree->to_arena(v);\n        m_tree->_set_val(m_id, s);\n        return s.len;\n    }\n    size_t set_val_serialized(std::nullptr_t)\n    {\n        _apply_seed();\n        m_tree->_set_val(m_id, csubstr{});\n        return 0;\n    }\n\n    /** encode a blob as base64 into the tree's arena, then assign the\n     * result to the node's key\n     * @return the size of base64-encoded blob */\n    size_t set_key_serialized(fmt::const_base64_wrapper w);\n    /** encode a blob as base64 into the tree's arena, then assign the\n     * result to the node's val\n     * @return the size of base64-encoded blob */\n    size_t set_val_serialized(fmt::const_base64_wrapper w);\n\n    /** serialize a variable, then assign the result to the node's val */\n    inline NodeRef& operator<< (csubstr s)\n    {\n        // this overload is needed to prevent ambiguity (there's also\n        // operator<< for writing a substr to a stream)\n        _apply_seed();\n        write(this, s);\n        _RYML_CB_ASSERT(m_tree->m_callbacks, val() == s);\n        return *this;\n    }\n\n    template<class T>\n    inline NodeRef& operator<< (T const& C4_RESTRICT v)\n    {\n        _apply_seed();\n        write(this, v);\n        return *this;\n    }\n\n    /** serialize a variable, then assign the result to the node's key */\n    template<class T>\n    inline NodeRef& operator<< (Key<const T> const& C4_RESTRICT v)\n    {\n        _apply_seed();\n        set_key_serialized(v.k);\n        return *this;\n    }\n\n    /** serialize a variable, then assign the result to the node's key */\n    template<class T>\n    inline NodeRef& operator<< (Key<T> const& C4_RESTRICT v)\n    {\n        _apply_seed();\n        set_key_serialized(v.k);\n        return *this;\n    }\n\n    NodeRef& operator<< (Key<fmt::const_base64_wrapper> w)\n    {\n        set_key_serialized(w.wrapper);\n        return *this;\n    }\n\n    NodeRef& operator<< (fmt::const_base64_wrapper w)\n    {\n        set_val_serialized(w);\n        return *this;\n    }\n\n    /** @} */\n\nprivate:\n\n    void _apply_seed()\n    {\n        _C4RID();\n        if(m_seed.str) // we have a seed key: use it to create the new child\n        {\n            m_id = m_tree->append_child(m_id);\n            m_tree->_set_key(m_id, m_seed);\n            m_seed.str = nullptr;\n            m_seed.len = (size_t)NONE;\n        }\n        else if(m_seed.len != (size_t)NONE) // we have a seed index: create a child at that position\n        {\n            _RYML_CB_ASSERT(m_tree->m_callbacks, (size_t)m_tree->num_children(m_id) == m_seed.len);\n            m_id = m_tree->append_child(m_id);\n            m_seed.str = nullptr;\n            m_seed.len = (size_t)NONE;\n        }\n        else\n        {\n            _RYML_CB_ASSERT(m_tree->m_callbacks, readable());\n        }\n    }\n\n    inline void _apply(csubstr v)\n    {\n        m_tree->_set_val(m_id, v);\n    }\n\n    inline void _apply(NodeScalar const& v)\n    {\n        m_tree->_set_val(m_id, v);\n    }\n\n    inline void _apply(NodeInit const& i)\n    {\n        m_tree->_set(m_id, i);\n    }\n\npublic:\n\n    /** @name modification of hierarchy */\n    /** @{ */\n\n    inline NodeRef insert_child(NodeRef after)\n    {\n        _C4RR();\n        _RYML_CB_ASSERT(m_tree->m_callbacks, after.m_tree == m_tree);\n        NodeRef r(m_tree, m_tree->insert_child(m_id, after.m_id));\n        return r;\n    }\n\n    inline NodeRef insert_child(NodeInit const& i, NodeRef after)\n    {\n        _C4RR();\n        _RYML_CB_ASSERT(m_tree->m_callbacks, after.m_tree == m_tree);\n        NodeRef r(m_tree, m_tree->insert_child(m_id, after.m_id));\n        r._apply(i);\n        return r;\n    }\n\n    inline NodeRef prepend_child()\n    {\n        _C4RR();\n        NodeRef r(m_tree, m_tree->insert_child(m_id, NONE));\n        return r;\n    }\n\n    inline NodeRef prepend_child(NodeInit const& i)\n    {\n        _C4RR();\n        NodeRef r(m_tree, m_tree->insert_child(m_id, NONE));\n        r._apply(i);\n        return r;\n    }\n\n    inline NodeRef append_child()\n    {\n        _C4RR();\n        NodeRef r(m_tree, m_tree->append_child(m_id));\n        return r;\n    }\n\n    inline NodeRef append_child(NodeInit const& i)\n    {\n        _C4RR();\n        NodeRef r(m_tree, m_tree->append_child(m_id));\n        r._apply(i);\n        return r;\n    }\n\n    inline NodeRef insert_sibling(ConstNodeRef const& after)\n    {\n        _C4RR();\n        _RYML_CB_ASSERT(m_tree->m_callbacks, after.m_tree == m_tree);\n        NodeRef r(m_tree, m_tree->insert_sibling(m_id, after.m_id));\n        return r;\n    }\n\n    inline NodeRef insert_sibling(NodeInit const& i, ConstNodeRef const& after)\n    {\n        _C4RR();\n        _RYML_CB_ASSERT(m_tree->m_callbacks, after.m_tree == m_tree);\n        NodeRef r(m_tree, m_tree->insert_sibling(m_id, after.m_id));\n        r._apply(i);\n        return r;\n    }\n\n    inline NodeRef prepend_sibling()\n    {\n        _C4RR();\n        NodeRef r(m_tree, m_tree->prepend_sibling(m_id));\n        return r;\n    }\n\n    inline NodeRef prepend_sibling(NodeInit const& i)\n    {\n        _C4RR();\n        NodeRef r(m_tree, m_tree->prepend_sibling(m_id));\n        r._apply(i);\n        return r;\n    }\n\n    inline NodeRef append_sibling()\n    {\n        _C4RR();\n        NodeRef r(m_tree, m_tree->append_sibling(m_id));\n        return r;\n    }\n\n    inline NodeRef append_sibling(NodeInit const& i)\n    {\n        _C4RR();\n        NodeRef r(m_tree, m_tree->append_sibling(m_id));\n        r._apply(i);\n        return r;\n    }\n\npublic:\n\n    inline void remove_child(NodeRef & child)\n    {\n        _C4RR();\n        _RYML_CB_ASSERT(m_tree->m_callbacks, has_child(child));\n        _RYML_CB_ASSERT(m_tree->m_callbacks, child.parent().id() == id());\n        m_tree->remove(child.id());\n        child.clear();\n    }\n\n    //! remove the nth child of this node\n    inline void remove_child(id_type pos)\n    {\n        _C4RR();\n        _RYML_CB_ASSERT(m_tree->m_callbacks, pos >= 0 && pos < num_children());\n        id_type child = m_tree->child(m_id, pos);\n        _RYML_CB_ASSERT(m_tree->m_callbacks, child != NONE);\n        m_tree->remove(child);\n    }\n\n    //! remove a child by name\n    inline void remove_child(csubstr key)\n    {\n        _C4RR();\n        id_type child = m_tree->find_child(m_id, key);\n        _RYML_CB_ASSERT(m_tree->m_callbacks, child != NONE);\n        m_tree->remove(child);\n    }\n\npublic:\n\n    /** change the node's position within its parent, placing it after\n     * @p after. To move to the first position in the parent, simply\n     * pass an empty or default-constructed reference like this:\n     * `n.move({})`. */\n    inline void move(ConstNodeRef const& after)\n    {\n        _C4RR();\n        m_tree->move(m_id, after.m_id);\n    }\n\n    /** move the node to a different @p parent (which may belong to a\n     * different tree), placing it after @p after. When the\n     * destination parent is in a new tree, then this node's tree\n     * pointer is reset to the tree of the parent node. */\n    inline void move(NodeRef const& parent, ConstNodeRef const& after)\n    {\n        _C4RR();\n        if(parent.m_tree == m_tree)\n        {\n            m_tree->move(m_id, parent.m_id, after.m_id);\n        }\n        else\n        {\n            parent.m_tree->move(m_tree, m_id, parent.m_id, after.m_id);\n            m_tree = parent.m_tree;\n        }\n    }\n\n    /** duplicate the current node somewhere within its parent, and\n     * place it after the node @p after. To place into the first\n     * position of the parent, simply pass an empty or\n     * default-constructed reference like this: `n.move({})`. */\n    inline NodeRef duplicate(ConstNodeRef const& after) const\n    {\n        _C4RR();\n        _RYML_CB_ASSERT(m_tree->m_callbacks, m_tree == after.m_tree || after.m_id == NONE);\n        id_type dup = m_tree->duplicate(m_id, m_tree->parent(m_id), after.m_id);\n        NodeRef r(m_tree, dup);\n        return r;\n    }\n\n    /** duplicate the current node somewhere into a different @p parent\n     * (possibly from a different tree), and place it after the node\n     * @p after. To place into the first position of the parent,\n     * simply pass an empty or default-constructed reference like\n     * this: `n.move({})`. */\n    inline NodeRef duplicate(NodeRef const& parent, ConstNodeRef const& after) const\n    {\n        _C4RR();\n        _RYML_CB_ASSERT(m_tree->m_callbacks, parent.m_tree == after.m_tree || after.m_id == NONE);\n        if(parent.m_tree == m_tree)\n        {\n            id_type dup = m_tree->duplicate(m_id, parent.m_id, after.m_id);\n            NodeRef r(m_tree, dup);\n            return r;\n        }\n        else\n        {\n            id_type dup = parent.m_tree->duplicate(m_tree, m_id, parent.m_id, after.m_id);\n            NodeRef r(parent.m_tree, dup);\n            return r;\n        }\n    }\n\n    inline void duplicate_children(NodeRef const& parent, ConstNodeRef const& after) const\n    {\n        _C4RR();\n        _RYML_CB_ASSERT(m_tree->m_callbacks, parent.m_tree == after.m_tree);\n        if(parent.m_tree == m_tree)\n        {\n            m_tree->duplicate_children(m_id, parent.m_id, after.m_id);\n        }\n        else\n        {\n            parent.m_tree->duplicate_children(m_tree, m_id, parent.m_id, after.m_id);\n        }\n    }\n\n    /** @} */\n\n#undef _C4RR\n#undef _C4RID\n};\n\n\n//-----------------------------------------------------------------------------\n\ninline ConstNodeRef::ConstNodeRef(NodeRef const& that) noexcept\n    : m_tree(that.m_tree)\n    , m_id(!that.is_seed() ? that.id() : (id_type)NONE)\n{\n}\n\ninline ConstNodeRef::ConstNodeRef(NodeRef && that) noexcept\n    : m_tree(that.m_tree)\n    , m_id(!that.is_seed() ? that.id() : (id_type)NONE)\n{\n}\n\n\ninline ConstNodeRef& ConstNodeRef::operator= (NodeRef const& that) noexcept\n{\n    m_tree = (that.m_tree);\n    m_id = (!that.is_seed() ? that.id() : (id_type)NONE);\n    return *this;\n}\n\ninline ConstNodeRef& ConstNodeRef::operator= (NodeRef && that) noexcept\n{\n    m_tree = (that.m_tree);\n    m_id = (!that.is_seed() ? that.id() : (id_type)NONE);\n    return *this;\n}\n\n\n//-----------------------------------------------------------------------------\n\n/** @addtogroup doc_serialization_helpers\n *\n * @{\n */\n\ntemplate<class T>\ninline void write(NodeRef *n, T const& v)\n{\n    n->set_val_serialized(v);\n}\n\nnamespace detail {\n// SFINAE overloads for skipping leading + which cannot be read by the charconv functions\ntemplate<class T>\nC4_ALWAYS_INLINE auto read_skip_plus(csubstr val, T *v)\n    -> typename std::enable_if<std::is_arithmetic<T>::value, bool>::type\n{\n    if(val.begins_with('+'))\n        val = val.sub(1);\n    return from_chars(val, v);\n}\ntemplate<class T>\nC4_ALWAYS_INLINE auto read_skip_plus(csubstr val, T *v)\n    -> typename std::enable_if< ! std::is_arithmetic<T>::value, bool>::type\n{\n    return from_chars(val, v);\n}\n} // namespace detail\n\n/** convert the val of a scalar node to a particular type, by\n * forwarding its val to @ref from_chars<T>(). The full string is\n * used.\n * @return false if the conversion failed */\ntemplate<class T>\ninline auto read(NodeRef const& n, T *v)\n    -> typename std::enable_if< ! std::is_floating_point<T>::value, bool>::type\n{\n    csubstr val = n.val();\n    if(val.empty())\n        return false;\n    return detail::read_skip_plus(val, v);\n}\n/** convert the val of a scalar node to a particular type, by\n * forwarding its val to @ref from_chars<T>(). The full string is\n * used.\n * @return false if the conversion failed */\ntemplate<class T>\ninline auto read(ConstNodeRef const& n, T *v)\n    -> typename std::enable_if< ! std::is_floating_point<T>::value, bool>::type\n{\n    csubstr val = n.val();\n    if(val.empty())\n        return false;\n    return detail::read_skip_plus(val, v);\n}\n\n/** convert the val of a scalar node to a floating point type, by\n * forwarding its val to @ref from_chars_float<T>().\n *\n * @return false if the conversion failed\n *\n * @warning Unlike non-floating types, only the leading part of the\n * string that may constitute a number is processed. This happens\n * because the float parsing is delegated to fast_float, which is\n * implemented that way. Consequently, for example, all of `\"34\"`,\n * `\"34 \"` `\"34hg\"` `\"34 gh\"` will be read as 34. If you are not sure\n * about the contents of the data, you can use\n * csubstr::first_real_span() to check before calling `>>`, for\n * example like this:\n *\n * ```cpp\n * csubstr val = node.val();\n * if(val.first_real_span() == val)\n *     node >> v;\n * else\n *     ERROR(\"not a real\")\n * ```\n */\ntemplate<class T>\ntypename std::enable_if<std::is_floating_point<T>::value, bool>::type\ninline read(NodeRef const& n, T *v)\n{\n    csubstr val = n.val();\n    if(val.empty())\n        return false;\n    return from_chars_float(val, v);\n}\n/** convert the val of a scalar node to a floating point type, by\n * forwarding its val to @ref from_chars_float<T>().\n *\n * @return false if the conversion failed\n *\n * @warning Unlike non-floating types, only the leading part of the\n * string that may constitute a number is processed. This happens\n * because the float parsing is delegated to fast_float, which is\n * implemented that way. Consequently, for example, all of `\"34\"`,\n * `\"34 \"` `\"34hg\"` `\"34 gh\"` will be read as 34. If you are not sure\n * about the contents of the data, you can use\n * csubstr::first_real_span() to check before calling `>>`, for\n * example like this:\n *\n * ```cpp\n * csubstr val = node.val();\n * if(val.first_real_span() == val)\n *     node >> v;\n * else\n *     ERROR(\"not a real\")\n * ```\n */\ntemplate<class T>\ntypename std::enable_if<std::is_floating_point<T>::value, bool>::type\ninline read(ConstNodeRef const& n, T *v)\n{\n    csubstr val = n.val();\n    if(val.empty())\n        return false;\n    return from_chars_float(val, v);\n}\n\n/** @} */\n\n/** @} */\n\n\n} // namespace yml\n} // namespace c4\n\n\n\n#ifdef __clang__\n#   pragma clang diagnostic pop\n#elif defined(__GNUC__)\n#   pragma GCC diagnostic pop\n#elif defined(_MSC_VER)\n#   pragma warning(pop)\n#endif\n\n#endif /* _C4_YML_NODE_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/yml/node_type.cpp",
    "content": "#include \"c4/yml/node_type.hpp\"\n\nnamespace c4 {\nnamespace yml {\n\nconst char* NodeType::type_str(NodeType_e ty) noexcept\n{\n    switch(ty & _TYMASK)\n    {\n    case KEYVAL:\n        return \"KEYVAL\";\n    case KEY:\n        return \"KEY\";\n    case VAL:\n        return \"VAL\";\n    case MAP:\n        return \"MAP\";\n    case SEQ:\n        return \"SEQ\";\n    case KEYMAP:\n        return \"KEYMAP\";\n    case KEYSEQ:\n        return \"KEYSEQ\";\n    case DOCSEQ:\n        return \"DOCSEQ\";\n    case DOCMAP:\n        return \"DOCMAP\";\n    case DOCVAL:\n        return \"DOCVAL\";\n    case DOC:\n        return \"DOC\";\n    case STREAM:\n        return \"STREAM\";\n    case NOTYPE:\n        return \"NOTYPE\";\n    default:\n        if((ty & KEYVAL) == KEYVAL)\n            return \"KEYVAL***\";\n        if((ty & KEYMAP) == KEYMAP)\n            return \"KEYMAP***\";\n        if((ty & KEYSEQ) == KEYSEQ)\n            return \"KEYSEQ***\";\n        if((ty & DOCSEQ) == DOCSEQ)\n            return \"DOCSEQ***\";\n        if((ty & DOCMAP) == DOCMAP)\n            return \"DOCMAP***\";\n        if((ty & DOCVAL) == DOCVAL)\n            return \"DOCVAL***\";\n        if(ty & KEY)\n            return \"KEY***\";\n        if(ty & VAL)\n            return \"VAL***\";\n        if(ty & MAP)\n            return \"MAP***\";\n        if(ty & SEQ)\n            return \"SEQ***\";\n        if(ty & DOC)\n            return \"DOC***\";\n        return \"(unk)\";\n    }\n}\n\ncsubstr NodeType::type_str(substr buf, NodeType_e flags) noexcept\n{\n    size_t pos = 0;\n    bool gotone = false;\n\n    #define _prflag(fl, txt)                                    \\\n    do {                                                        \\\n        if((flags & fl) == (fl))                                \\\n        {                                                       \\\n            if(gotone)                                          \\\n            {                                                   \\\n                if(pos + 1 < buf.len)                           \\\n                    buf[pos] = '|';                             \\\n                ++pos;                                          \\\n            }                                                   \\\n            csubstr fltxt = txt;                                \\\n            if(pos + fltxt.len <= buf.len)                      \\\n                memcpy(buf.str + pos, fltxt.str, fltxt.len);    \\\n            pos += fltxt.len;                                   \\\n            gotone = true;                                      \\\n            flags = (flags & ~fl); /*remove the flag*/          \\\n        }                                                       \\\n    } while(0)\n\n    _prflag(STREAM, \"STREAM\");\n    _prflag(DOC, \"DOC\");\n    // key properties\n    _prflag(KEY, \"KEY\");\n    _prflag(KEYTAG, \"KTAG\");\n    _prflag(KEYANCH, \"KANCH\");\n    _prflag(KEYREF, \"KREF\");\n    _prflag(KEY_LITERAL, \"KLITERAL\");\n    _prflag(KEY_FOLDED, \"KFOLDED\");\n    _prflag(KEY_SQUO, \"KSQUO\");\n    _prflag(KEY_DQUO, \"KDQUO\");\n    _prflag(KEY_PLAIN, \"KPLAIN\");\n    _prflag(KEY_UNFILT, \"KUNFILT\");\n    // val properties\n    _prflag(VAL, \"VAL\");\n    _prflag(VALTAG, \"VTAG\");\n    _prflag(VALANCH, \"VANCH\");\n    _prflag(VALREF, \"VREF\");\n    _prflag(VAL_UNFILT, \"VUNFILT\");\n    _prflag(VAL_LITERAL, \"VLITERAL\");\n    _prflag(VAL_FOLDED, \"VFOLDED\");\n    _prflag(VAL_SQUO, \"VSQUO\");\n    _prflag(VAL_DQUO, \"VDQUO\");\n    _prflag(VAL_PLAIN, \"VPLAIN\");\n    _prflag(VAL_UNFILT, \"VUNFILT\");\n    // container properties\n    _prflag(MAP, \"MAP\");\n    _prflag(SEQ, \"SEQ\");\n    _prflag(FLOW_SL, \"FLOWSL\");\n    _prflag(FLOW_ML, \"FLOWML\");\n    _prflag(BLOCK, \"BLCK\");\n    if(pos == 0)\n        _prflag(NOTYPE, \"NOTYPE\");\n\n    #undef _prflag\n\n    if(pos < buf.len)\n    {\n        buf[pos] = '\\0';\n        return buf.first(pos);\n    }\n    else\n    {\n        csubstr failed;\n        failed.len = pos + 1;\n        failed.str = nullptr;\n        return failed;\n    }\n}\n\n\n//-----------------------------------------------------------------------------\n\n// see https://www.yaml.info/learn/quote.html#noplain\nbool scalar_style_query_squo(csubstr s) noexcept\n{\n    return ! s.first_of_any(\"\\n \", \"\\n\\t\");\n}\n\n// see https://www.yaml.info/learn/quote.html#noplain\nbool scalar_style_query_plain(csubstr s) noexcept\n{\n    if(s.begins_with(\"-.\"))\n    {\n        if(s == \"-.inf\" || s == \"-.INF\")\n            return true;\n        else if(s.sub(2).is_number())\n            return true;\n    }\n    else if(s.begins_with_any(\"0123456789.-+\") && s.is_number())\n    {\n        return true;\n    }\n    return s != ':'\n        && ( ! s.begins_with_any(\"-:?*&,'\\\"{}[]|>%#@`\\r\")) // @ and ` are reserved characters\n        && ( ! s.ends_with_any(\":#\"))\n             // make this check in the last place, as it has linear\n             // complexity, while the previous ones are\n             // constant-time\n        && (s.first_of(\"\\n#:[]{},\") == npos);\n}\n\nNodeType_e scalar_style_choose(csubstr s) noexcept\n{\n    if(s.len)\n    {\n        if(s.begins_with_any(\" \\n\\t\")\n           ||\n           s.ends_with_any(\" \\n\\t\"))\n        {\n            return SCALAR_DQUO;\n        }\n        else if( ! scalar_style_query_plain(s))\n        {\n            return scalar_style_query_squo(s) ? SCALAR_SQUO : SCALAR_DQUO;\n        }\n        // nothing remarkable - use plain\n        return SCALAR_PLAIN;\n    }\n    return s.str ? SCALAR_SQUO : SCALAR_PLAIN;\n}\n\nNodeType_e scalar_style_json_choose(csubstr s) noexcept\n{\n    // do not quote special cases\n    bool plain = (\n        (s == \"true\" || s == \"false\" || s == \"null\")\n        ||\n        (\n            // do not quote numbers\n            s.is_number()\n            &&\n            (\n                // quote integral numbers if they have a leading 0\n                // https://github.com/biojppm/rapidyaml/issues/291\n                (!(s.len > 1 && s.begins_with('0')))\n                // do not quote reals with leading 0\n                // https://github.com/biojppm/rapidyaml/issues/313\n                || (s.find('.') != csubstr::npos)\n            )\n        )\n    );\n    return plain ? SCALAR_PLAIN : SCALAR_DQUO;\n}\n\n} // namespace yml\n} // namespace c4\n"
  },
  {
    "path": "libs/rapidyaml/c4/yml/node_type.hpp",
    "content": "#ifndef C4_YML_NODE_TYPE_HPP_\n#define C4_YML_NODE_TYPE_HPP_\n\n#ifndef _C4_YML_COMMON_HPP_\n#include \"c4/yml/common.hpp\"\n#endif\n\nC4_SUPPRESS_WARNING_MSVC_PUSH\nC4_SUPPRESS_WARNING_GCC_CLANG_PUSH\nC4_SUPPRESS_WARNING_GCC_CLANG(\"-Wold-style-cast\")\n\nnamespace c4 {\nnamespace yml {\n\n/** @addtogroup doc_node_type\n *\n * @{\n */\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n\n/** the integral type necessary to cover all the bits for NodeType_e */\nusing type_bits = uint32_t;\n\n\n/** a bit mask for marking node types and styles */\ntypedef enum : type_bits {\n    #define __(v) (type_bits(1) << v) // a convenience define, undefined below\n    NOTYPE  = 0,         ///< no node type or style is set\n    KEY     = __(0),     ///< is member of a map, must have non-empty key\n    VAL     = __(1),     ///< a scalar: has a scalar (ie string) value, possibly empty. must be a leaf node, and cannot be MAP or SEQ\n    MAP     = __(2),     ///< a map: a parent of KEYVAL/KEYSEQ/KEYMAP nodes\n    SEQ     = __(3),     ///< a seq: a parent of VAL/SEQ/MAP nodes\n    DOC     = __(4),     ///< a document\n    STREAM  = __(5)|SEQ, ///< a stream: a seq of docs\n    KEYREF  = __(6),     ///< a *reference: the key references an &anchor\n    VALREF  = __(7),     ///< a *reference: the val references an &anchor\n    KEYANCH = __(8),     ///< the key has an &anchor\n    VALANCH = __(9),     ///< the val has an &anchor\n    KEYTAG  = __(10),    ///< the key has a tag\n    VALTAG  = __(11),    ///< the val has a tag\n    _TYMASK = __(12)-1,  ///< all the bits up to here\n    //\n    // unfiltered flags:\n    //\n    KEY_UNFILT  = __(12), ///< the key scalar was left unfiltered; the parser was set not to filter. @see ParserOptions\n    VAL_UNFILT  = __(13), ///< the val scalar was left unfiltered; the parser was set not to filter. @see ParserOptions\n    //\n    // style flags:\n    //\n    FLOW_SL     = __(14), ///< mark container with single-line flow style (seqs as '[val1,val2], maps as '{key: val,key2: val2}')\n    FLOW_ML     = __(15), ///< (NOT IMPLEMENTED, work in progress) mark container with multi-line flow style (seqs as '[\\n  val1,\\n  val2\\n], maps as '{\\n  key: val,\\n  key2: val2\\n}')\n    BLOCK       = __(16), ///< mark container with block style (seqs as '- val\\n', maps as 'key: val')\n    KEY_LITERAL = __(17), ///< mark key scalar as multiline, block literal |\n    VAL_LITERAL = __(18), ///< mark val scalar as multiline, block literal |\n    KEY_FOLDED  = __(19), ///< mark key scalar as multiline, block folded >\n    VAL_FOLDED  = __(20), ///< mark val scalar as multiline, block folded >\n    KEY_SQUO    = __(21), ///< mark key scalar as single quoted '\n    VAL_SQUO    = __(22), ///< mark val scalar as single quoted '\n    KEY_DQUO    = __(23), ///< mark key scalar as double quoted \"\n    VAL_DQUO    = __(24), ///< mark val scalar as double quoted \"\n    KEY_PLAIN   = __(25), ///< mark key scalar as plain scalar (unquoted, even when multiline)\n    VAL_PLAIN   = __(26), ///< mark val scalar as plain scalar (unquoted, even when multiline)\n    //\n    // type combination masks:\n    //\n    KEYVAL  = KEY|VAL,\n    KEYSEQ  = KEY|SEQ,\n    KEYMAP  = KEY|MAP,\n    DOCMAP  = DOC|MAP,\n    DOCSEQ  = DOC|SEQ,\n    DOCVAL  = DOC|VAL,\n    //\n    // style combination masks:\n    //\n    SCALAR_LITERAL = KEY_LITERAL|VAL_LITERAL,\n    SCALAR_FOLDED  = KEY_FOLDED|VAL_FOLDED,\n    SCALAR_SQUO    = KEY_SQUO|VAL_SQUO,\n    SCALAR_DQUO    = KEY_DQUO|VAL_DQUO,\n    SCALAR_PLAIN   = KEY_PLAIN|VAL_PLAIN,\n    KEYQUO         = KEY_SQUO|KEY_DQUO|KEY_FOLDED|KEY_LITERAL, ///< key style is one of ', \", > or |\n    VALQUO         = VAL_SQUO|VAL_DQUO|VAL_FOLDED|VAL_LITERAL, ///< val style is one of ', \", > or |\n    KEY_STYLE      = KEY_LITERAL|KEY_FOLDED|KEY_SQUO|KEY_DQUO|KEY_PLAIN, ///< mask of all the scalar styles for key (not container styles!)\n    VAL_STYLE      = VAL_LITERAL|VAL_FOLDED|VAL_SQUO|VAL_DQUO|VAL_PLAIN, ///< mask of all the scalar styles for val (not container styles!)\n    SCALAR_STYLE   = KEY_STYLE|VAL_STYLE,\n    CONTAINER_STYLE_FLOW  = FLOW_SL|FLOW_ML,\n    CONTAINER_STYLE_BLOCK = BLOCK,\n    CONTAINER_STYLE       = FLOW_SL|FLOW_ML|BLOCK,\n    STYLE          = SCALAR_STYLE | CONTAINER_STYLE,\n    //\n    // mixed masks\n    _KEYMASK = KEY | KEYQUO | KEYANCH | KEYREF | KEYTAG,\n    _VALMASK = VAL | VALQUO | VALANCH | VALREF | VALTAG,\n    #undef __\n} NodeType_e;\n\nconstexpr C4_ALWAYS_INLINE C4_CONST NodeType_e operator|  (NodeType_e lhs, NodeType_e rhs) noexcept { return (NodeType_e)(((type_bits)lhs) | ((type_bits)rhs)); }\nconstexpr C4_ALWAYS_INLINE C4_CONST NodeType_e operator&  (NodeType_e lhs, NodeType_e rhs) noexcept { return (NodeType_e)(((type_bits)lhs) & ((type_bits)rhs)); }\nconstexpr C4_ALWAYS_INLINE C4_CONST NodeType_e operator>> (NodeType_e bits, uint32_t n) noexcept { return (NodeType_e)(((type_bits)bits) >> n); }\nconstexpr C4_ALWAYS_INLINE C4_CONST NodeType_e operator<< (NodeType_e bits, uint32_t n) noexcept { return (NodeType_e)(((type_bits)bits) << n); }\nconstexpr C4_ALWAYS_INLINE C4_CONST NodeType_e operator~  (NodeType_e bits) noexcept { return (NodeType_e)(~(type_bits)bits); }\nC4_ALWAYS_INLINE NodeType_e& operator&= (NodeType_e &subject, NodeType_e bits) noexcept { subject = (NodeType_e)((type_bits)subject & (type_bits)bits); return subject; }\nC4_ALWAYS_INLINE NodeType_e& operator|= (NodeType_e &subject, NodeType_e bits) noexcept { subject = (NodeType_e)((type_bits)subject | (type_bits)bits); return subject; }\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n/** wraps a NodeType_e element with some syntactic sugar and predicates */\nstruct RYML_EXPORT NodeType\n{\npublic:\n\n    NodeType_e type;\n\npublic:\n\n    C4_ALWAYS_INLINE NodeType() noexcept : type(NOTYPE) {}\n    C4_ALWAYS_INLINE NodeType(NodeType_e t) noexcept : type(t) {}\n    C4_ALWAYS_INLINE NodeType(type_bits t) noexcept : type((NodeType_e)t) {}\n\n    C4_ALWAYS_INLINE bool has_any(NodeType_e t) const noexcept { return (type & t) != 0u; }\n    C4_ALWAYS_INLINE bool has_all(NodeType_e t) const noexcept { return (type & t) == t; }\n    C4_ALWAYS_INLINE bool has_none(NodeType_e t) const noexcept { return (type & t) == 0; }\n\n    C4_ALWAYS_INLINE void set(NodeType_e t) noexcept { type = t; }\n    C4_ALWAYS_INLINE void add(NodeType_e t) noexcept { type = (type|t); }\n    C4_ALWAYS_INLINE void rem(NodeType_e t) noexcept { type = (type & ~t); }\n    C4_ALWAYS_INLINE void addrem(NodeType_e bits_to_add, NodeType_e bits_to_remove) noexcept { type |= bits_to_add; type &= ~bits_to_remove; }\n\n    C4_ALWAYS_INLINE void clear() noexcept { type = NOTYPE; }\n\npublic:\n\n    C4_ALWAYS_INLINE operator NodeType_e      & C4_RESTRICT ()       noexcept { return type; }\n    C4_ALWAYS_INLINE operator NodeType_e const& C4_RESTRICT () const noexcept { return type; }\n\npublic:\n\n    /** @name node type queries\n     * @{ */\n\n    /** return a preset string based on the node type */\n    C4_ALWAYS_INLINE const char *type_str() const noexcept { return type_str(type); }\n    /** return a preset string based on the node type */\n    static const char* type_str(NodeType_e t) noexcept;\n\n    /** fill a string with the node type flags. If the string is small, returns {null, len} */\n    C4_ALWAYS_INLINE csubstr type_str(substr buf) const noexcept { return type_str(buf, type); }\n    /** fill a string with the node type flags. If the string is small, returns {null, len}  */\n    static csubstr type_str(substr buf, NodeType_e t) noexcept;\n\npublic:\n\n    /** @name node type queries\n     * @{ */\n\n    C4_ALWAYS_INLINE bool is_notype()         const noexcept { return type == NOTYPE; }\n    C4_ALWAYS_INLINE bool is_stream()         const noexcept { return ((type & STREAM) == STREAM) != 0; }\n    C4_ALWAYS_INLINE bool is_doc()            const noexcept { return (type & DOC) != 0; }\n    C4_ALWAYS_INLINE bool is_container()      const noexcept { return (type & (MAP|SEQ|STREAM)) != 0; }\n    C4_ALWAYS_INLINE bool is_map()            const noexcept { return (type & MAP) != 0; }\n    C4_ALWAYS_INLINE bool is_seq()            const noexcept { return (type & SEQ) != 0; }\n    C4_ALWAYS_INLINE bool has_key()           const noexcept { return (type & KEY) != 0; }\n    C4_ALWAYS_INLINE bool has_val()           const noexcept { return (type & VAL) != 0; }\n    C4_ALWAYS_INLINE bool is_val()            const noexcept { return (type & KEYVAL) == VAL; }\n    C4_ALWAYS_INLINE bool is_keyval()         const noexcept { return (type & KEYVAL) == KEYVAL; }\n    C4_ALWAYS_INLINE bool has_key_tag()       const noexcept { return (type & KEYTAG) != 0; }\n    C4_ALWAYS_INLINE bool has_val_tag()       const noexcept { return (type & VALTAG) != 0; }\n    C4_ALWAYS_INLINE bool has_key_anchor()    const noexcept { return (type & KEYANCH) != 0; }\n    C4_ALWAYS_INLINE bool has_val_anchor()    const noexcept { return (type & VALANCH) != 0; }\n    C4_ALWAYS_INLINE bool has_anchor()        const noexcept { return (type & (KEYANCH|VALANCH)) != 0; }\n    C4_ALWAYS_INLINE bool is_key_ref()        const noexcept { return (type & KEYREF) != 0; }\n    C4_ALWAYS_INLINE bool is_val_ref()        const noexcept { return (type & VALREF) != 0; }\n    C4_ALWAYS_INLINE bool is_ref()            const noexcept { return (type & (KEYREF|VALREF)) != 0; }\n\n    C4_ALWAYS_INLINE bool is_key_unfiltered() const noexcept { return (type & (KEY_UNFILT)) != 0; }\n    C4_ALWAYS_INLINE bool is_val_unfiltered() const noexcept { return (type & (VAL_UNFILT)) != 0; }\n\n    RYML_DEPRECATED(\"use has_key_anchor()\")    bool is_key_anchor() const noexcept { return has_key_anchor(); }\n    RYML_DEPRECATED(\"use has_val_anchor()\")    bool is_val_anchor() const noexcept { return has_val_anchor(); }\n    RYML_DEPRECATED(\"use has_anchor()\")        bool is_anchor() const noexcept { return has_anchor(); }\n    RYML_DEPRECATED(\"use has_anchor() || is_ref()\") bool is_anchor_or_ref() const noexcept { return has_anchor() || is_ref(); }\n    /** @} */\n\npublic:\n\n    /** @name container+scalar style queries\n     * @{ */\n\n    C4_ALWAYS_INLINE bool is_container_styled() const noexcept { return (type & (CONTAINER_STYLE)) != 0; }\n    C4_ALWAYS_INLINE bool is_block() const noexcept { return (type & (BLOCK)) != 0; }\n    C4_ALWAYS_INLINE bool is_flow_sl() const noexcept { return (type & (FLOW_SL)) != 0; }\n    C4_ALWAYS_INLINE bool is_flow_ml() const noexcept { return (type & (FLOW_ML)) != 0; }\n    C4_ALWAYS_INLINE bool is_flow() const noexcept { return (type & (FLOW_ML|FLOW_SL)) != 0; }\n\n    C4_ALWAYS_INLINE bool is_key_styled() const noexcept { return (type & (KEY_STYLE)) != 0; }\n    C4_ALWAYS_INLINE bool is_val_styled() const noexcept { return (type & (VAL_STYLE)) != 0; }\n    C4_ALWAYS_INLINE bool is_key_literal() const noexcept { return (type & (KEY_LITERAL)) != 0; }\n    C4_ALWAYS_INLINE bool is_val_literal() const noexcept { return (type & (VAL_LITERAL)) != 0; }\n    C4_ALWAYS_INLINE bool is_key_folded() const noexcept { return (type & (KEY_FOLDED)) != 0; }\n    C4_ALWAYS_INLINE bool is_val_folded() const noexcept { return (type & (VAL_FOLDED)) != 0; }\n    C4_ALWAYS_INLINE bool is_key_squo() const noexcept { return (type & (KEY_SQUO)) != 0; }\n    C4_ALWAYS_INLINE bool is_val_squo() const noexcept { return (type & (VAL_SQUO)) != 0; }\n    C4_ALWAYS_INLINE bool is_key_dquo() const noexcept { return (type & (KEY_DQUO)) != 0; }\n    C4_ALWAYS_INLINE bool is_val_dquo() const noexcept { return (type & (VAL_DQUO)) != 0; }\n    C4_ALWAYS_INLINE bool is_key_plain() const noexcept { return (type & (KEY_PLAIN)) != 0; }\n    C4_ALWAYS_INLINE bool is_val_plain() const noexcept { return (type & (VAL_PLAIN)) != 0; }\n    C4_ALWAYS_INLINE bool is_key_quoted() const noexcept { return (type & KEYQUO) != 0; }\n    C4_ALWAYS_INLINE bool is_val_quoted() const noexcept { return (type & VALQUO) != 0; }\n    C4_ALWAYS_INLINE bool is_quoted() const noexcept { return (type & (KEYQUO|VALQUO)) != 0; }\n\n    C4_ALWAYS_INLINE void set_container_style(NodeType_e style) noexcept { type = ((style & CONTAINER_STYLE) | (type & ~CONTAINER_STYLE)); }\n    C4_ALWAYS_INLINE void set_key_style(NodeType_e style) noexcept { type = ((style & KEY_STYLE) | (type & ~KEY_STYLE)); }\n    C4_ALWAYS_INLINE void set_val_style(NodeType_e style) noexcept { type = ((style & VAL_STYLE) | (type & ~VAL_STYLE)); }\n\n    /** @} */\n\n};\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n/** @name scalar style helpers\n * @{ */\n\n/** choose a YAML emitting style based on the scalar's contents */\nRYML_EXPORT NodeType_e scalar_style_choose(csubstr scalar) noexcept;\n\n/** choose a json style based on the scalar's contents */\nRYML_EXPORT NodeType_e scalar_style_json_choose(csubstr scalar) noexcept;\n\n/** query whether a scalar can be encoded using single quotes.\n * It may not be possible, notably when there is leading\n * whitespace after a newline. */\nRYML_EXPORT bool scalar_style_query_squo(csubstr s) noexcept;\n\n/** query whether a scalar can be encoded using plain style (no\n * quotes, not a literal/folded block scalar). */\nRYML_EXPORT bool scalar_style_query_plain(csubstr s) noexcept;\n\n/** YAML-sense query of nullity. returns true if the scalar points\n * to `nullptr` or is otherwise equal to one of the strings\n * `\"~\"`,`\"null\"`,`\"Null\"`,`\"NULL\"` */\nRYML_EXPORT inline C4_NO_INLINE bool scalar_is_null(csubstr s) noexcept\n{\n    return s.str == nullptr ||\n        s == \"~\" ||\n        s == \"null\" ||\n        s == \"Null\" ||\n        s == \"NULL\";\n}\n\n/** @} */\n\n\n/** @} */\n\n} // namespace yml\n} // namespace c4\n\nC4_SUPPRESS_WARNING_MSVC_POP\nC4_SUPPRESS_WARNING_GCC_CLANG_POP\n\n#endif /* C4_YML_NODE_TYPE_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/yml/parse.cpp",
    "content": "#include \"c4/yml/parse.hpp\"\n\n#ifndef _C4_YML_NODE_HPP_\n#include \"c4/yml/node.hpp\"\n#endif\n#ifndef _C4_YML_PARSE_ENGINE_HPP_\n#include \"c4/yml/parse_engine.hpp\"\n#endif\n#ifndef _C4_YML_PARSE_ENGINE_DEF_HPP_\n#include \"c4/yml/parse_engine.def.hpp\"\n#endif\n#ifndef _C4_YML_EVENT_HANDLER_TREE_HPP_\n#include \"c4/yml/event_handler_tree.hpp\"\n#endif\n\n\n//-----------------------------------------------------------------------------\n\nnamespace c4 {\nnamespace yml {\n\n// instantiate the parser class\ntemplate class ParseEngine<EventHandlerTree>;\n\nnamespace {\ninline void _reset_tree_handler(Parser *parser, Tree *t, id_type node_id)\n{\n    RYML_ASSERT(parser);\n    RYML_ASSERT(t);\n    if(!parser->m_evt_handler)\n        _RYML_CB_ERR(t->m_callbacks, \"event handler is not set\");\n    parser->m_evt_handler->reset(t, node_id);\n    RYML_ASSERT(parser->m_evt_handler->m_tree == t);\n}\n} // namespace\n\nvoid parse_in_place(Parser *parser, csubstr filename, substr yaml, Tree *t, id_type node_id)\n{\n    _reset_tree_handler(parser, t, node_id);\n    parser->parse_in_place_ev(filename, yaml);\n}\n\nvoid parse_json_in_place(Parser *parser, csubstr filename, substr json, Tree *t, id_type node_id)\n{\n    _reset_tree_handler(parser, t, node_id);\n    parser->parse_json_in_place_ev(filename, json);\n}\n\n\n// this is vertically aligned to highlight the parameter differences.\nvoid parse_in_place(Parser *parser,                   substr yaml, Tree *t, id_type node_id) { parse_in_place(parser, {}, yaml, t, node_id); }\nvoid parse_in_place(Parser *parser, csubstr filename, substr yaml, Tree *t                ) { RYML_CHECK(t); parse_in_place(parser, filename, yaml, t, t->root_id()); }\nvoid parse_in_place(Parser *parser,                   substr yaml, Tree *t                ) { RYML_CHECK(t); parse_in_place(parser, {}      , yaml, t, t->root_id()); }\nvoid parse_in_place(Parser *parser, csubstr filename, substr yaml, NodeRef node           ) { RYML_CHECK(!node.invalid()); parse_in_place(parser, filename, yaml, node.tree(), node.id()); }\nvoid parse_in_place(Parser *parser,                   substr yaml, NodeRef node           ) { RYML_CHECK(!node.invalid()); parse_in_place(parser, {}      , yaml, node.tree(), node.id()); }\nTree parse_in_place(Parser *parser, csubstr filename, substr yaml                         ) { RYML_CHECK(parser); RYML_CHECK(parser->m_evt_handler); Tree tree(parser->callbacks()); parse_in_place(parser, filename, yaml, &tree, tree.root_id()); return tree; }\nTree parse_in_place(Parser *parser,                   substr yaml                         ) { RYML_CHECK(parser); RYML_CHECK(parser->m_evt_handler); Tree tree(parser->callbacks()); parse_in_place(parser, {}      , yaml, &tree, tree.root_id()); return tree; }\n\n// this is vertically aligned to highlight the parameter differences.\nvoid parse_in_place(csubstr filename, substr yaml, Tree *t, id_type node_id) { RYML_CHECK(t); Parser::handler_type event_handler(t->callbacks()); Parser parser(&event_handler); parse_in_place(&parser, filename, yaml, t, node_id); }\nvoid parse_in_place(                  substr yaml, Tree *t, id_type node_id) { RYML_CHECK(t); Parser::handler_type event_handler(t->callbacks()); Parser parser(&event_handler); parse_in_place(&parser, {}      , yaml, t, node_id); }\nvoid parse_in_place(csubstr filename, substr yaml, Tree *t                ) { RYML_CHECK(t); Parser::handler_type event_handler(t->callbacks()); Parser parser(&event_handler); parse_in_place(&parser, filename, yaml, t, t->root_id()); }\nvoid parse_in_place(                  substr yaml, Tree *t                ) { RYML_CHECK(t); Parser::handler_type event_handler(t->callbacks()); Parser parser(&event_handler); parse_in_place(&parser, {}      , yaml, t, t->root_id()); }\nvoid parse_in_place(csubstr filename, substr yaml, NodeRef node           ) { RYML_CHECK(!node.invalid()); Parser::handler_type event_handler(node.tree()->callbacks()); Parser parser(&event_handler); parse_in_place(&parser, filename, yaml, node.tree(), node.id()); }\nvoid parse_in_place(                  substr yaml, NodeRef node           ) { RYML_CHECK(!node.invalid()); Parser::handler_type event_handler(node.tree()->callbacks()); Parser parser(&event_handler); parse_in_place(&parser, {}      , yaml, node.tree(), node.id()); }\nTree parse_in_place(csubstr filename, substr yaml                         ) { Parser::handler_type event_handler; Parser parser(&event_handler); Tree tree(parser.callbacks()); parse_in_place(&parser, filename, yaml, &tree, tree.root_id()); return tree; }\nTree parse_in_place(                  substr yaml                         ) { Parser::handler_type event_handler; Parser parser(&event_handler); Tree tree(parser.callbacks()); parse_in_place(&parser, {}      , yaml, &tree, tree.root_id()); return tree; }\n\n\n// this is vertically aligned to highlight the parameter differences.\nvoid parse_json_in_place(Parser *parser,                   substr json, Tree *t, id_type node_id) { parse_json_in_place(parser, {}, json, t, node_id); }\nvoid parse_json_in_place(Parser *parser, csubstr filename, substr json, Tree *t                ) { RYML_CHECK(t); parse_json_in_place(parser, filename, json, t, t->root_id()); }\nvoid parse_json_in_place(Parser *parser,                   substr json, Tree *t                ) { RYML_CHECK(t); parse_json_in_place(parser, {}      , json, t, t->root_id()); }\nvoid parse_json_in_place(Parser *parser, csubstr filename, substr json, NodeRef node           ) { RYML_CHECK(!node.invalid()); parse_json_in_place(parser, filename, json, node.tree(), node.id()); }\nvoid parse_json_in_place(Parser *parser,                   substr json, NodeRef node           ) { RYML_CHECK(!node.invalid()); parse_json_in_place(parser, {}      , json, node.tree(), node.id()); }\nTree parse_json_in_place(Parser *parser, csubstr filename, substr json                         ) { RYML_CHECK(parser); RYML_CHECK(parser->m_evt_handler); Tree tree(parser->callbacks()); parse_json_in_place(parser, filename, json, &tree, tree.root_id()); return tree; }\nTree parse_json_in_place(Parser *parser,                   substr json                         ) { RYML_CHECK(parser); RYML_CHECK(parser->m_evt_handler); Tree tree(parser->callbacks()); parse_json_in_place(parser, {}      , json, &tree, tree.root_id()); return tree; }\n\n// this is vertically aligned to highlight the parameter differences.\nvoid parse_json_in_place(csubstr filename, substr json, Tree *t, id_type node_id) { RYML_CHECK(t); Parser::handler_type event_handler(t->callbacks()); Parser parser(&event_handler); parse_json_in_place(&parser, filename, json, t, node_id); }\nvoid parse_json_in_place(                  substr json, Tree *t, id_type node_id) { RYML_CHECK(t); Parser::handler_type event_handler(t->callbacks()); Parser parser(&event_handler); parse_json_in_place(&parser, {}      , json, t, node_id); }\nvoid parse_json_in_place(csubstr filename, substr json, Tree *t                ) { RYML_CHECK(t); Parser::handler_type event_handler(t->callbacks()); Parser parser(&event_handler); parse_json_in_place(&parser, filename, json, t, t->root_id()); }\nvoid parse_json_in_place(                  substr json, Tree *t                ) { RYML_CHECK(t); Parser::handler_type event_handler(t->callbacks()); Parser parser(&event_handler); parse_json_in_place(&parser, {}      , json, t, t->root_id()); }\nvoid parse_json_in_place(csubstr filename, substr json, NodeRef node           ) { RYML_CHECK(!node.invalid()); Parser::handler_type event_handler(node.tree()->callbacks()); Parser parser(&event_handler); parse_json_in_place(&parser, filename, json, node.tree(), node.id()); }\nvoid parse_json_in_place(                  substr json, NodeRef node           ) { RYML_CHECK(!node.invalid()); Parser::handler_type event_handler(node.tree()->callbacks()); Parser parser(&event_handler); parse_json_in_place(&parser, {}      , json, node.tree(), node.id()); }\nTree parse_json_in_place(csubstr filename, substr json                         ) { Parser::handler_type event_handler; Parser parser(&event_handler); Tree tree(parser.callbacks()); parse_json_in_place(&parser, filename, json, &tree, tree.root_id()); return tree; }\nTree parse_json_in_place(                  substr json                         ) { Parser::handler_type event_handler; Parser parser(&event_handler); Tree tree(parser.callbacks()); parse_json_in_place(&parser, {}      , json, &tree, tree.root_id()); return tree; }\n\n\n// this is vertically aligned to highlight the parameter differences.\nvoid parse_in_arena(Parser *parser, csubstr filename, csubstr yaml, Tree *t, id_type node_id) { RYML_CHECK(t); substr src = t->copy_to_arena(yaml); parse_in_place(parser, filename, src, t, node_id); }\nvoid parse_in_arena(Parser *parser,                   csubstr yaml, Tree *t, id_type node_id) { RYML_CHECK(t); substr src = t->copy_to_arena(yaml); parse_in_place(parser, {}      , src, t, node_id); }\nvoid parse_in_arena(Parser *parser, csubstr filename, csubstr yaml, Tree *t                ) { RYML_CHECK(t); substr src = t->copy_to_arena(yaml); parse_in_place(parser, filename, src, t, t->root_id()); }\nvoid parse_in_arena(Parser *parser,                   csubstr yaml, Tree *t                ) { RYML_CHECK(t); substr src = t->copy_to_arena(yaml); parse_in_place(parser, {}      , src, t, t->root_id()); }\nvoid parse_in_arena(Parser *parser, csubstr filename, csubstr yaml, NodeRef node           ) { RYML_CHECK(!node.invalid()); substr src = node.tree()->copy_to_arena(yaml); parse_in_place(parser, filename, src, node.tree(), node.id()); }\nvoid parse_in_arena(Parser *parser,                   csubstr yaml, NodeRef node           ) { RYML_CHECK(!node.invalid()); substr src = node.tree()->copy_to_arena(yaml); parse_in_place(parser, {}      , src, node.tree(), node.id()); }\nTree parse_in_arena(Parser *parser, csubstr filename, csubstr yaml                         ) { RYML_CHECK(parser); RYML_CHECK(parser->m_evt_handler); Tree tree(parser->callbacks()); substr src = tree.copy_to_arena(yaml); parse_in_place(parser, filename, src, &tree, tree.root_id()); return tree; }\nTree parse_in_arena(Parser *parser,                   csubstr yaml                         ) { RYML_CHECK(parser); RYML_CHECK(parser->m_evt_handler); Tree tree(parser->callbacks()); substr src = tree.copy_to_arena(yaml); parse_in_place(parser, {}      , src, &tree, tree.root_id()); return tree; }\n\n// this is vertically aligned to highlight the parameter differences.\nvoid parse_in_arena(csubstr filename, csubstr yaml, Tree *t, id_type node_id) { RYML_CHECK(t); Parser::handler_type event_handler(t->callbacks()); Parser parser(&event_handler); substr src = t->copy_to_arena(yaml); parse_in_place(&parser, filename, src, t, node_id); }\nvoid parse_in_arena(                  csubstr yaml, Tree *t, id_type node_id) { RYML_CHECK(t); Parser::handler_type event_handler(t->callbacks()); Parser parser(&event_handler); substr src = t->copy_to_arena(yaml); parse_in_place(&parser, {}      , src, t, node_id); }\nvoid parse_in_arena(csubstr filename, csubstr yaml, Tree *t                ) { RYML_CHECK(t); Parser::handler_type event_handler(t->callbacks()); Parser parser(&event_handler); substr src = t->copy_to_arena(yaml); parse_in_place(&parser, filename, src, t, t->root_id()); }\nvoid parse_in_arena(                  csubstr yaml, Tree *t                ) { RYML_CHECK(t); Parser::handler_type event_handler(t->callbacks()); Parser parser(&event_handler); substr src = t->copy_to_arena(yaml); parse_in_place(&parser, {}      , src, t, t->root_id()); }\nvoid parse_in_arena(csubstr filename, csubstr yaml, NodeRef node           ) { RYML_CHECK(!node.invalid()); Parser::handler_type event_handler(node.tree()->callbacks()); Parser parser(&event_handler); substr src = node.tree()->copy_to_arena(yaml); parse_in_place(&parser, filename, src, node.tree(), node.id()); }\nvoid parse_in_arena(                  csubstr yaml, NodeRef node           ) { RYML_CHECK(!node.invalid()); Parser::handler_type event_handler(node.tree()->callbacks()); Parser parser(&event_handler); substr src = node.tree()->copy_to_arena(yaml); parse_in_place(&parser, {}      , src, node.tree(), node.id()); }\nTree parse_in_arena(csubstr filename, csubstr yaml                         ) { Parser::handler_type event_handler; Parser parser(&event_handler); Tree tree(parser.callbacks()); substr src = tree.copy_to_arena(yaml); parse_in_place(&parser, filename, src, &tree, tree.root_id()); return tree; }\nTree parse_in_arena(                  csubstr yaml                         ) { Parser::handler_type event_handler; Parser parser(&event_handler); Tree tree(parser.callbacks()); substr src = tree.copy_to_arena(yaml); parse_in_place(&parser, {}      , src, &tree, tree.root_id()); return tree; }\n\n\n// this is vertically aligned to highlight the parameter differences.\nvoid parse_json_in_arena(Parser *parser, csubstr filename, csubstr json, Tree *t, id_type node_id) { RYML_CHECK(t); substr src = t->copy_to_arena(json); parse_json_in_place(parser, filename, src, t, node_id); }\nvoid parse_json_in_arena(Parser *parser,                   csubstr json, Tree *t, id_type node_id) { RYML_CHECK(t); substr src = t->copy_to_arena(json); parse_json_in_place(parser, {}      , src, t, node_id); }\nvoid parse_json_in_arena(Parser *parser, csubstr filename, csubstr json, Tree *t                ) { RYML_CHECK(t); substr src = t->copy_to_arena(json); parse_json_in_place(parser, filename, src, t, t->root_id()); }\nvoid parse_json_in_arena(Parser *parser,                   csubstr json, Tree *t                ) { RYML_CHECK(t); substr src = t->copy_to_arena(json); parse_json_in_place(parser, {}      , src, t, t->root_id()); }\nvoid parse_json_in_arena(Parser *parser, csubstr filename, csubstr json, NodeRef node           ) { RYML_CHECK(!node.invalid()); substr src = node.tree()->copy_to_arena(json); parse_json_in_place(parser, filename, src, node.tree(), node.id()); }\nvoid parse_json_in_arena(Parser *parser,                   csubstr json, NodeRef node           ) { RYML_CHECK(!node.invalid()); substr src = node.tree()->copy_to_arena(json); parse_json_in_place(parser, {}      , src, node.tree(), node.id()); }\nTree parse_json_in_arena(Parser *parser, csubstr filename, csubstr json                         ) { RYML_CHECK(parser); RYML_CHECK(parser->m_evt_handler); Tree tree(parser->callbacks()); substr src = tree.copy_to_arena(json); parse_json_in_place(parser, filename, src, &tree, tree.root_id()); return tree; }\nTree parse_json_in_arena(Parser *parser,                   csubstr json                         ) { RYML_CHECK(parser); RYML_CHECK(parser->m_evt_handler); Tree tree(parser->callbacks()); substr src = tree.copy_to_arena(json); parse_json_in_place(parser, {}      , src, &tree, tree.root_id()); return tree; }\n\n// this is vertically aligned to highlight the parameter differences.\nvoid parse_json_in_arena(csubstr filename, csubstr json, Tree *t, id_type node_id) { RYML_CHECK(t); Parser::handler_type event_handler(t->callbacks()); Parser parser(&event_handler); substr src = t->copy_to_arena(json); parse_json_in_place(&parser, filename, src, t, node_id); }\nvoid parse_json_in_arena(                  csubstr json, Tree *t, id_type node_id) { RYML_CHECK(t); Parser::handler_type event_handler(t->callbacks()); Parser parser(&event_handler); substr src = t->copy_to_arena(json); parse_json_in_place(&parser, {}      , src, t, node_id); }\nvoid parse_json_in_arena(csubstr filename, csubstr json, Tree *t                ) { RYML_CHECK(t); Parser::handler_type event_handler(t->callbacks()); Parser parser(&event_handler); substr src = t->copy_to_arena(json); parse_json_in_place(&parser, filename, src, t, t->root_id()); }\nvoid parse_json_in_arena(                  csubstr json, Tree *t                ) { RYML_CHECK(t); Parser::handler_type event_handler(t->callbacks()); Parser parser(&event_handler); substr src = t->copy_to_arena(json); parse_json_in_place(&parser, {}      , src, t, t->root_id()); }\nvoid parse_json_in_arena(csubstr filename, csubstr json, NodeRef node           ) { RYML_CHECK(!node.invalid()); Parser::handler_type event_handler(node.tree()->callbacks()); Parser parser(&event_handler); substr src = node.tree()->copy_to_arena(json); parse_json_in_place(&parser, filename, src, node.tree(), node.id()); }\nvoid parse_json_in_arena(                  csubstr json, NodeRef node           ) { RYML_CHECK(!node.invalid()); Parser::handler_type event_handler(node.tree()->callbacks()); Parser parser(&event_handler); substr src = node.tree()->copy_to_arena(json); parse_json_in_place(&parser, {}      , src, node.tree(), node.id()); }\nTree parse_json_in_arena(csubstr filename, csubstr json                         ) { Parser::handler_type event_handler; Parser parser(&event_handler); Tree tree(parser.callbacks()); substr src = tree.copy_to_arena(json); parse_json_in_place(&parser, filename, src, &tree, tree.root_id()); return tree; }\nTree parse_json_in_arena(                  csubstr json                         ) { Parser::handler_type event_handler; Parser parser(&event_handler); Tree tree(parser.callbacks()); substr src = tree.copy_to_arena(json); parse_json_in_place(&parser, {}      , src, &tree, tree.root_id()); return tree; }\n\n\nRYML_EXPORT C4_NO_INLINE size_t _find_last_newline_and_larger_indentation(csubstr s, size_t indentation) noexcept\n{\n    if(indentation + 1 > s.len)\n        return npos;\n    for(size_t i = s.len-indentation-1; i != size_t(-1); --i)\n    {\n        if(s.str[i] == '\\n')\n        {\n            csubstr rem = s.sub(i + 1);\n            size_t first = rem.first_not_of(' ');\n            first = (first != npos) ? first : rem.len;\n            if(first > indentation)\n                return i;\n        }\n    }\n    return npos;\n}\n\n//-----------------------------------------------------------------------------\n\nRYML_EXPORT id_type estimate_tree_capacity(csubstr src)\n{\n    id_type num_nodes = 1; // root\n    for(size_t i = 0; i < src.len; ++i)\n    {\n        const char c = src.str[i];\n        num_nodes += (c == '\\n') || (c == ',') || (c == '[') || (c == '{');\n    }\n    return num_nodes;\n}\n\n} // namespace yml\n} // namespace c4\n"
  },
  {
    "path": "libs/rapidyaml/c4/yml/parse.hpp",
    "content": "#ifndef _C4_YML_PARSE_HPP_\n#define _C4_YML_PARSE_HPP_\n\n#ifndef _C4_YML_COMMON_HPP_\n#include \"c4/yml/common.hpp\"\n#endif\n\nnamespace c4 {\nnamespace yml {\n\nclass Tree;\nclass NodeRef;\ntemplate<class EventHandler> class ParseEngine;\nstruct EventHandlerTree;\nRYML_EXPORT id_type estimate_tree_capacity(csubstr src);\n\n\n/** @addtogroup doc_parse\n * @{ */\n\n/** This is the main ryml parser, where the parser events are handled\n * to create a ryml tree.\n *\n * @warning Because the ryml @ref Tree does not accept containers as\n * keys, this class cannot successfully parse YAML source with this\n * feature. See @ref ParseEngine for more details.\n *\n * @see ParserOptions\n * @see ParseEngine\n * @see EventHandlerTree\n * */\nusing Parser = RYML_EXPORT ParseEngine<EventHandlerTree>;\n\n\n//-----------------------------------------------------------------------------\n\n/** @defgroup doc_parse_in_place__with_existing_parser Parse in place with existing parser\n *\n * @brief parse a mutable YAML source buffer. Scalars requiring\n * filtering are mutated in place (except in the rare cases where the\n * filtered scalar is longer than the original scalar, or where\n * filtering was disabled before the call). These overloads accept an\n * existing parser object, and provide the opportunity to use special\n * parser options.\n *\n * @see ParserOptions\n *\n * @{\n */\n\n// this is vertically aligned to highlight the parameter differences.\n\nRYML_EXPORT void parse_in_place(Parser *parser, csubstr filename, substr yaml, Tree *t, id_type node_id); /**< (1) parse YAML into an existing tree node.\n                                                                                                          *\n                                                                                                          * The filename will be used in any error messages\n                                                                                                          * arising during the parse. The callbacks in the\n                                                                                                          * tree are kept, and used to allocate\n                                                                                                          * the tree members, if any allocation is required. */\nRYML_EXPORT void parse_in_place(Parser *parser,                   substr yaml, Tree *t, id_type node_id); /**< (2) like (1) but no filename will be reported */\nRYML_EXPORT void parse_in_place(Parser *parser, csubstr filename, substr yaml, Tree *t                 ); /**< (3) parse YAML into an existing tree, into its root node.\n                                                                                                          *\n                                                                                                          * The filename will be used in any error messages\n                                                                                                          * arising during the parse. The callbacks in the\n                                                                                                          * tree are kept, and used to allocate\n                                                                                                          * the tree members, if any allocation is required. */\nRYML_EXPORT void parse_in_place(Parser *parser,                   substr yaml, Tree *t                 ); /**< (4) like (3) but no filename will be reported */\nRYML_EXPORT void parse_in_place(Parser *parser, csubstr filename, substr yaml, NodeRef node            ); /**< (5) like (1) but the node is given as a NodeRef */\nRYML_EXPORT void parse_in_place(Parser *parser,                   substr yaml, NodeRef node            ); /**< (6) like (5) but no filename will be reported */\nRYML_EXPORT Tree parse_in_place(Parser *parser, csubstr filename, substr yaml                          ); /**< (7) create a new tree, and parse YAML into its root node.\n                                                                                                          *\n                                                                                                          * The filename will be used in any error messages\n                                                                                                          * arising during the parse. The tree is created with\n                                                                                                          * the callbacks currently in the parser.\n                                                                                                          */\nRYML_EXPORT Tree parse_in_place(Parser *parser,                   substr yaml                          ); /**< (8) like (7) but no filename will be reported */\n\n\n// this is vertically aligned to highlight the parameter differences.\nRYML_EXPORT void parse_json_in_place(Parser *parser, csubstr filename, substr json, Tree *t, id_type node_id); ///< (1) parse JSON into an existing tree node. The filename will be used in any error messages arising during the parse.\nRYML_EXPORT void parse_json_in_place(Parser *parser,                   substr json, Tree *t, id_type node_id); ///< (2) like (1) but no filename will be reported\nRYML_EXPORT void parse_json_in_place(Parser *parser, csubstr filename, substr json, Tree *t                 ); ///< (3) parse JSON into an existing tree, into its root node.\nRYML_EXPORT void parse_json_in_place(Parser *parser,                   substr json, Tree *t                 ); ///< (4) like (3) but no filename will be reported\nRYML_EXPORT void parse_json_in_place(Parser *parser, csubstr filename, substr json, NodeRef node            ); ///< (5) like (1) but the node is given as a NodeRef\nRYML_EXPORT void parse_json_in_place(Parser *parser,                   substr json, NodeRef node            ); ///< (6) like (5) but no filename will be reported\nRYML_EXPORT Tree parse_json_in_place(Parser *parser, csubstr filename, substr json                          ); ///< (7) create a new tree, and parse JSON into its root node.\nRYML_EXPORT Tree parse_json_in_place(Parser *parser,                   substr json                          ); ///< (8) like (7) but no filename will be reported\n\n/** @} */\n\n\n//-----------------------------------------------------------------------------\n\n/** @defgroup doc_parse_in_place___with_temporary_parser Parse in place with temporary parser\n *\n * @brief parse a mutable YAML source buffer. Scalars requiring\n * filtering are mutated in place (except in the rare cases where the\n * filtered scalar is longer than the original scalar).\n *\n * @note These freestanding functions use a temporary parser object,\n * and are convenience functions to enable the user to easily parse\n * YAML without the need to explicitly instantiate a parser and event\n * handler. Note that some properties (notably node locations in the\n * original source code) are only available through the parser\n * class. If you need access to any of these properties, use\n * the appropriate overload from @ref doc_parse_in_place__with_existing_parser\n *\n * @{\n */\n\n// this is vertically aligned to highlight the parameter differences.\nRYML_EXPORT void parse_in_place(csubstr filename, substr yaml, Tree *t, id_type node_id); ///< (1) parse YAML into an existing tree node. The filename will be used in any error messages arising during the parse.\nRYML_EXPORT void parse_in_place(                  substr yaml, Tree *t, id_type node_id); ///< (2) like (1) but no filename will be reported\nRYML_EXPORT void parse_in_place(csubstr filename, substr yaml, Tree *t                 ); ///< (3) parse YAML into an existing tree, into its root node.\nRYML_EXPORT void parse_in_place(                  substr yaml, Tree *t                 ); ///< (4) like (3) but no filename will be reported\nRYML_EXPORT void parse_in_place(csubstr filename, substr yaml, NodeRef node            ); ///< (5) like (1) but the node is given as a NodeRef\nRYML_EXPORT void parse_in_place(                  substr yaml, NodeRef node            ); ///< (6) like (5) but no filename will be reported\nRYML_EXPORT Tree parse_in_place(csubstr filename, substr yaml                          ); ///< (7) create a new tree, and parse YAML into its root node.\nRYML_EXPORT Tree parse_in_place(                  substr yaml                          ); ///< (8) like (7) but no filename will be reported\n\n// this is vertically aligned to highlight the parameter differences.\nRYML_EXPORT void parse_json_in_place(csubstr filename, substr json, Tree *t, id_type node_id); ///< (1) parse JSON into an existing tree node. The filename will be used in any error messages arising during the parse.\nRYML_EXPORT void parse_json_in_place(                  substr json, Tree *t, id_type node_id); ///< (2) like (1) but no filename will be reported\nRYML_EXPORT void parse_json_in_place(csubstr filename, substr json, Tree *t                 ); ///< (3) parse JSON into an existing tree, into its root node.\nRYML_EXPORT void parse_json_in_place(                  substr json, Tree *t                 ); ///< (4) like (3) but no filename will be reported\nRYML_EXPORT void parse_json_in_place(csubstr filename, substr json, NodeRef node            ); ///< (5) like (1) but the node is given as a NodeRef\nRYML_EXPORT void parse_json_in_place(                  substr json, NodeRef node            ); ///< (6) like (5) but no filename will be reported\nRYML_EXPORT Tree parse_json_in_place(csubstr filename, substr json                          ); ///< (7) create a new tree, and parse JSON into its root node.\nRYML_EXPORT Tree parse_json_in_place(                  substr json                          ); ///< (8) like (7) but no filename will be reported\n\n/** @} */\n\n\n//-----------------------------------------------------------------------------\n\n\n/** @defgroup doc_parse_in_arena__with_existing_parser Parse in arena with existing parser\n *\n * @brief parse a read-only (immutable) YAML source buffer. This is\n * achieved by first copying the contents of the buffer to the tree's\n * arena, and then calling @ref parse_in_arena() . All the resulting\n * scalars will be filtered in the arena. These overloads accept an\n * existing parser object, and provide the opportunity to use special\n * parser options.\n *\n * @see ParserOptions\n *\n *\n * @note These freestanding functions use a temporary parser object,\n * and are convenience functions to easily parse YAML without the need\n * to instantiate a separate parser. Note that some properties\n * (notably node locations in the original source code) are only\n * available through the parser class. If you need access to any of\n * these properties, use the appropriate overload from @ref\n * doc_parse_in_arena__with_existing_parser\n *\n * @warning overloads receiving a substr YAML buffer are intentionally\n * left undefined, such that calling parse_in_arena() with a substr\n * will cause a linker error. This is to prevent an accidental copy of\n * the source buffer to the tree's arena, because substr (which is\n * mutable) is implicitly convertible to csubstr (which is\n * immutable). If you really intend to parse a mutable buffer in the\n * tree's arena, convert it first to immutable by assigning the substr\n * to a csubstr prior to calling parse_in_arena(). This is not needed\n * for parse_in_place() because csubstr is not implicitly convertible\n * to substr. To be clear:\n * ```c++\n * substr mutable_buffer = ...;\n * parser.parse_in_arena(mutable_buffer); // linker error\n *\n * csubstr immutable_buffer = ...;\n * parser.parse_in_arena(immutable_buffer); // ok\n * ```\n *\n * @{\n */\n\n#define RYML_DONT_PARSE_SUBSTR_IN_ARENA \"\"                      \\\n    \"Do not pass a (mutable) substr to parse_in_arena(); \"      \\\n    \"if you have a substr, it should be parsed in place. \"      \\\n    \"Consider using parse_in_place() instead, or convert \"      \\\n    \"the buffer to csubstr prior to calling. This function \"    \\\n    \" is deliberately left undefined, so that calling it \"      \\\n    \"will cause a linker error.\"\n\n// this is vertically aligned to highlight the parameter differences.\nRYML_EXPORT void parse_in_arena(Parser *parser, csubstr filename, csubstr yaml, Tree *t, id_type node_id); ///< (1) parse YAML into an existing tree node. The filename will be used in any error messages arising during the parse.\nRYML_EXPORT void parse_in_arena(Parser *parser,                   csubstr yaml, Tree *t, id_type node_id); ///< (2) like (1) but no filename will be reported\nRYML_EXPORT void parse_in_arena(Parser *parser, csubstr filename, csubstr yaml, Tree *t                 ); ///< (3) parse YAML into an existing tree, into its root node.\nRYML_EXPORT void parse_in_arena(Parser *parser,                   csubstr yaml, Tree *t                 ); ///< (4) like (3) but no filename will be reported\nRYML_EXPORT void parse_in_arena(Parser *parser, csubstr filename, csubstr yaml, NodeRef node            ); ///< (5) like (1) but the node is given as a NodeRef\nRYML_EXPORT void parse_in_arena(Parser *parser,                   csubstr yaml, NodeRef node            ); ///< (6) like (5) but no filename will be reported\nRYML_EXPORT Tree parse_in_arena(Parser *parser, csubstr filename, csubstr yaml                          ); ///< (7) create a new tree, and parse YAML into its root node.\nRYML_EXPORT Tree parse_in_arena(Parser *parser,                   csubstr yaml                          ); ///< (8) like (7) but no filename will be reported\n\n// this is vertically aligned to highlight the parameter differences.\nRYML_EXPORT void parse_json_in_arena(Parser *parser, csubstr filename, csubstr json, Tree *t, id_type node_id); ///< (1) parse JSON into an existing tree node. The filename will be used in any error messages arising during the parse.\nRYML_EXPORT void parse_json_in_arena(Parser *parser,                   csubstr json, Tree *t, id_type node_id); ///< (2) like (1) but no filename will be reported\nRYML_EXPORT void parse_json_in_arena(Parser *parser, csubstr filename, csubstr json, Tree *t                 ); ///< (3) parse JSON into an existing tree, into its root node.\nRYML_EXPORT void parse_json_in_arena(Parser *parser,                   csubstr json, Tree *t                 ); ///< (4) like (3) but no filename will be reported\nRYML_EXPORT void parse_json_in_arena(Parser *parser, csubstr filename, csubstr json, NodeRef node            ); ///< (5) like (1) but the node is given as a NodeRef\nRYML_EXPORT void parse_json_in_arena(Parser *parser,                   csubstr json, NodeRef node            ); ///< (6) like (5) but no filename will be reported\nRYML_EXPORT Tree parse_json_in_arena(Parser *parser, csubstr filename, csubstr json                          ); ///< (7) create a new tree, and parse JSON into its root node.\nRYML_EXPORT Tree parse_json_in_arena(Parser *parser,                   csubstr json                          ); ///< (8) like (7) but no filename will be reported\n\n/* READ THE DEPRECATION NOTE!\n *\n * All of the functions below are intentionally left undefined, to\n * prevent them being used.\n *\n */\n/** @cond dev */\nRYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena(Parser *parser,                   substr yaml, Tree *t, id_type node_id);\nRYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena(Parser *parser, csubstr filename, substr yaml, Tree *t, id_type node_id);\nRYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena(Parser *parser,                   substr yaml, Tree *t                 );\nRYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena(Parser *parser, csubstr filename, substr yaml, Tree *t                 );\nRYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena(Parser *parser,                   substr yaml, NodeRef node            );\nRYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena(Parser *parser, csubstr filename, substr yaml, NodeRef node            );\nRYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) Tree parse_in_arena(Parser *parser,                   substr yaml                          );\nRYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) Tree parse_in_arena(Parser *parser, csubstr filename, substr yaml                          );\nRYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_json_in_arena(Parser *parser,                   substr json, Tree *t, id_type node_id);\nRYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_json_in_arena(Parser *parser, csubstr filename, substr json, Tree *t, id_type node_id);\nRYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_json_in_arena(Parser *parser,                   substr json, Tree *t                 );\nRYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_json_in_arena(Parser *parser, csubstr filename, substr json, Tree *t                 );\nRYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_json_in_arena(Parser *parser,                   substr json, NodeRef node            );\nRYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_json_in_arena(Parser *parser, csubstr filename, substr json, NodeRef node            );\nRYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) Tree parse_json_in_arena(Parser *parser,                   substr json                          );\nRYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) Tree parse_json_in_arena(Parser *parser, csubstr filename, substr json                          );\n/** @endcond */\n\n/** @} */\n\n\n//-----------------------------------------------------------------------------\n\n\n/** @defgroup doc_parse_in_arena__with_temporary_parser Parse in arena with temporary parser\n *\n * @brief parse a read-only (immutable) YAML source buffer. This is\n * achieved by first copying the contents of the buffer to the tree's\n * arena, and then calling @ref parse_in_arena() .\n *\n * @note These freestanding functions use a temporary parser object,\n * and are convenience functions to easily one-off parse YAML without\n * the need to instantiate a separate parser. Note that some\n * properties (notably node locations in the original source code) are\n * only available through the parser class. If you need access to any\n * of these properties, use the appropriate overload from @ref\n * doc_parse_in_arena__with_existing_parser\n *\n * @warning overloads receiving a substr YAML buffer are intentionally\n * left undefined, such that calling parse_in_arena() with a substr\n * will cause a linker error. This is to prevent an accidental copy of\n * the source buffer to the tree's arena, because substr (which is\n * mutable) is implicitly convertible to csubstr (which is\n * immutable). If you really intend to parse a mutable buffer in the\n * tree's arena, convert it first to immutable by assigning the substr\n * to a csubstr prior to calling parse_in_arena(). This is not needed\n * for parse_in_place() because csubstr is not implicitly convertible\n * to substr. To be clear:\n * ```c++\n * substr mutable_buffer = ...;\n * parser.parse_in_arena(mutable_buffer); // linker error\n *\n * csubstr immutable_buffer = ...;\n * parser.parse_in_arena(immutable_buffer); // ok\n * ```\n *\n * @{\n */\n\n// this is vertically aligned to highlight the parameter differences.\nRYML_EXPORT void parse_in_arena(csubstr filename, csubstr yaml, Tree *t, id_type node_id); ///< (1) parse YAML into an existing tree node. The filename will be used in any error messages arising during the parse.\nRYML_EXPORT void parse_in_arena(                  csubstr yaml, Tree *t, id_type node_id); ///< (2) like (1) but no filename will be reported\nRYML_EXPORT void parse_in_arena(csubstr filename, csubstr yaml, Tree *t                 ); ///< (3) parse YAML into an existing tree, into its root node.\nRYML_EXPORT void parse_in_arena(                  csubstr yaml, Tree *t                 ); ///< (4) like (3) but no filename will be reported\nRYML_EXPORT void parse_in_arena(csubstr filename, csubstr yaml, NodeRef node            ); ///< (5) like (1) but the node is given as a NodeRef\nRYML_EXPORT void parse_in_arena(                  csubstr yaml, NodeRef node            ); ///< (6) like (5) but no filename will be reported\nRYML_EXPORT Tree parse_in_arena(csubstr filename, csubstr yaml                          ); ///< (7) create a new tree, and parse YAML into its root node.\nRYML_EXPORT Tree parse_in_arena(                  csubstr yaml                          ); ///< (8) like (7) but no filename will be reported\n\n// this is vertically aligned to highlight the parameter differences.\nRYML_EXPORT void parse_json_in_arena(csubstr filename, csubstr json, Tree *t, id_type node_id); ///< (1) parse JSON into an existing tree node. The filename will be used in any error messages arising during the parse.\nRYML_EXPORT void parse_json_in_arena(                  csubstr json, Tree *t, id_type node_id); ///< (2) like (1) but no filename will be reported\nRYML_EXPORT void parse_json_in_arena(csubstr filename, csubstr json, Tree *t                 ); ///< (3) parse JSON into an existing tree, into its root node.\nRYML_EXPORT void parse_json_in_arena(                  csubstr json, Tree *t                 ); ///< (4) like (3) but no filename will be reported\nRYML_EXPORT void parse_json_in_arena(csubstr filename, csubstr json, NodeRef node            ); ///< (5) like (1) but the node is given as a NodeRef\nRYML_EXPORT void parse_json_in_arena(                  csubstr json, NodeRef node            ); ///< (6) like (5) but no filename will be reported\nRYML_EXPORT Tree parse_json_in_arena(csubstr filename, csubstr json                          ); ///< (7) create a new tree, and parse JSON into its root node.\nRYML_EXPORT Tree parse_json_in_arena(                  csubstr json                          ); ///< (8) like (7) but no filename will be reported\n\n/* READ THE DEPRECATION NOTE!\n *\n * All of the functions below are intentionally left undefined, to\n * prevent them being used.\n */\n/** @cond dev */\nRYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena(                  substr yaml, Tree *t, id_type node_id);\nRYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena(csubstr filename, substr yaml, Tree *t, id_type node_id);\nRYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena(                  substr yaml, Tree *t                 );\nRYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena(csubstr filename, substr yaml, Tree *t                 );\nRYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena(                  substr yaml, NodeRef node            );\nRYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena(csubstr filename, substr yaml, NodeRef node            );\nRYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) Tree parse_in_arena(                  substr yaml                          );\nRYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) Tree parse_in_arena(csubstr filename, substr yaml                          );\nRYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_json_in_arena(                  substr json, Tree *t, id_type node_id);\nRYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_json_in_arena(csubstr filename, substr json, Tree *t, id_type node_id);\nRYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_json_in_arena(                  substr json, Tree *t                 );\nRYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_json_in_arena(csubstr filename, substr json, Tree *t                 );\nRYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_json_in_arena(                  substr json, NodeRef node            );\nRYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_json_in_arena(csubstr filename, substr json, NodeRef node            );\nRYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) Tree parse_json_in_arena(                  substr json                          );\nRYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) Tree parse_json_in_arena(csubstr filename, substr json                          );\n/** @endcond */\n\n/** @} */\n/** @} */\n\n} // namespace yml\n} // namespace c4\n\n#endif /* _C4_YML_PARSE_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/yml/parse_engine.def.hpp",
    "content": "#ifndef _C4_YML_PARSE_ENGINE_DEF_HPP_\n#define _C4_YML_PARSE_ENGINE_DEF_HPP_\n\n#include \"c4/yml/parse_engine.hpp\"\n#include \"c4/error.hpp\"\n#include \"c4/charconv.hpp\"\n#include \"c4/utf.hpp\"\n#include <c4/dump.hpp>\n\n#include <ctype.h>\n\n#include \"c4/yml/detail/parser_dbg.hpp\"\n#include \"c4/yml/filter_processor.hpp\"\n#ifdef RYML_DBG\n#include \"c4/yml/detail/print.hpp\"\n#endif\n\n\n#if defined(RYML_WITH_TAB_TOKENS)\n#define _RYML_WITH_TAB_TOKENS(...) __VA_ARGS__\n#define _RYML_WITHOUT_TAB_TOKENS(...)\n#define _RYML_WITH_OR_WITHOUT_TAB_TOKENS(with, without) with\n#else\n#define _RYML_WITH_TAB_TOKENS(...)\n#define _RYML_WITHOUT_TAB_TOKENS(...) __VA_ARGS__\n#define _RYML_WITH_OR_WITHOUT_TAB_TOKENS(with, without) without\n#endif\n\n\n// scaffold:\n#define _c4dbgnextline()                           \\\n    do {                                           \\\n       _c4dbgq(\"\\n-----------\");                   \\\n       _c4dbgt(\"handling line={}, offset={}B\",     \\\n               m_evt_handler->m_curr->pos.line,    \\\n               m_evt_handler->m_curr->pos.offset); \\\n    } while(0)\n\n\n#if defined(_MSC_VER)\n#   pragma warning(push)\n#   pragma warning(disable: 4296/*expression is always 'boolean_value'*/)\n#   pragma warning(disable: 4702/*unreachable code*/)\n#elif defined(__clang__)\n#   pragma clang diagnostic push\n#   pragma clang diagnostic ignored \"-Wtype-limits\" // to remove a warning on an assertion that a size_t >= 0. Later on, this size_t will turn into a template argument, and then it can become < 0.\n#   pragma clang diagnostic ignored \"-Wformat-nonliteral\"\n#   pragma clang diagnostic ignored \"-Wold-style-cast\"\n#elif defined(__GNUC__)\n#   pragma GCC diagnostic push\n#   pragma GCC diagnostic ignored \"-Wtype-limits\" // to remove a warning on an assertion that a size_t >= 0. Later on, this size_t will turn into a template argument, and then it can become < 0.\n#   pragma GCC diagnostic ignored \"-Wformat-nonliteral\"\n#   pragma GCC diagnostic ignored \"-Wold-style-cast\"\n#   if __GNUC__ >= 7\n#       pragma GCC diagnostic ignored \"-Wduplicated-branches\"\n#   endif\n#endif\n\nnamespace c4 {\nnamespace yml {\n\nnamespace {\n\nC4_HOT C4_ALWAYS_INLINE bool _is_blck_token(csubstr s) noexcept\n{\n    RYML_ASSERT(s.len > 0);\n    RYML_ASSERT(s.str[0] == '-' || s.str[0] == ':' || s.str[0] == '?');\n    return ((s.len == 1) || ((s.str[1] == ' ') _RYML_WITH_TAB_TOKENS( || (s.str[1] == '\\t'))));\n}\n\ninline bool _is_doc_begin_token(csubstr s)\n{\n    RYML_ASSERT(s.begins_with('-'));\n    RYML_ASSERT(!s.ends_with(\"\\n\"));\n    RYML_ASSERT(!s.ends_with(\"\\r\"));\n    return (s.len >= 3 && s.str[1] == '-' && s.str[2] == '-')\n        && (s.len == 3 || (s.str[3] == ' ' _RYML_WITH_TAB_TOKENS(|| s.str[3] == '\\t')));\n}\n\ninline bool _is_doc_end_token(csubstr s)\n{\n    RYML_ASSERT(s.begins_with('.'));\n    RYML_ASSERT(!s.ends_with(\"\\n\"));\n    RYML_ASSERT(!s.ends_with(\"\\r\"));\n    return (s.len >= 3 && s.str[1] == '.' && s.str[2] == '.')\n        && (s.len == 3 || (s.str[3] == ' ' _RYML_WITH_TAB_TOKENS(|| s.str[3] == '\\t')));\n}\n\ninline bool _is_doc_token(csubstr s) noexcept\n{\n    //\n    // NOTE: this function was failing under some scenarios when\n    // compiled with gcc -O2 (but not -O3 or -O1 or -O0), likely\n    // related to optimizer assumptions on the input string and\n    // possibly caused from UB around assignment to that string (the\n    // call site was in _scan_block()). For more details see:\n    //\n    // https://github.com/biojppm/rapidyaml/issues/440\n    //\n    // The current version does not suffer this problem, but it may\n    // appear again.\n    //\n    if(s.len >= 3)\n    {\n        switch(s.str[0])\n        {\n        case '-':\n            //return _is_doc_begin_token(s); // this was failing with gcc -O2\n            return (s.str[1] == '-' && s.str[2] == '-')\n                && (s.len == 3 || (s.str[3] == ' ' _RYML_WITH_TAB_TOKENS(|| s.str[3] == '\\t')));\n        case '.':\n            //return _is_doc_end_token(s); // this was failing with gcc -O2\n            return (s.str[1] == '.' && s.str[2] == '.')\n                && (s.len == 3 || (s.str[3] == ' ' _RYML_WITH_TAB_TOKENS(|| s.str[3] == '\\t')));\n        }\n    }\n    return false;\n}\n\ninline size_t _is_special_json_scalar(csubstr s)\n{\n    RYML_ASSERT(s.len);\n    switch(s.str[0])\n    {\n    case 'f':\n        if(s.len >= 5 && s.begins_with(\"false\"))\n            return 5u;\n        break;\n    case 't':\n        if(s.len >= 4 && s.begins_with(\"true\"))\n            return 4u;\n        break;\n    case 'n':\n        if(s.len >= 4 && s.begins_with(\"null\"))\n            return 4u;\n        break;\n    }\n    return 0u;\n}\n\n\n//-----------------------------------------------------------------------------\n\nC4_ALWAYS_INLINE size_t _extend_from_combined_newline(char nl, char following)\n{\n    return (nl == '\\n' && following == '\\r') || (nl == '\\r' && following == '\\n');\n}\n\n//! look for the next newline chars, and jump to the right of those\ninline substr from_next_line(substr rem)\n{\n    size_t nlpos = rem.first_of(\"\\r\\n\");\n    if(nlpos == csubstr::npos)\n        return {};\n    const char nl = rem[nlpos];\n    rem = rem.right_of(nlpos);\n    if(rem.empty())\n        return {};\n    if(_extend_from_combined_newline(nl, rem.front()))\n        rem = rem.sub(1);\n    return rem;\n}\n\n\n//-----------------------------------------------------------------------------\n\ninline size_t _count_following_newlines(csubstr r, size_t *C4_RESTRICT i)\n{\n    RYML_ASSERT(r[*i] == '\\n');\n    size_t numnl_following = 0;\n    ++(*i);\n    for( ; *i < r.len; ++(*i))\n    {\n        if(r.str[*i] == '\\n')\n            ++numnl_following;\n        // skip leading whitespace\n        else if(r.str[*i] == ' ' || r.str[*i] == '\\t' || r.str[*i] == '\\r')\n            ;\n        else\n            break;\n    }\n    return numnl_following;\n}\n\n/** @p i is set to the first non whitespace character after the line\n * @return the number of empty lines after the initial position */\ninline size_t _count_following_newlines(csubstr r, size_t *C4_RESTRICT i, size_t indentation)\n{\n    RYML_ASSERT(r[*i] == '\\n');\n    size_t numnl_following = 0;\n    ++(*i);\n    if(indentation == 0)\n    {\n        for( ; *i < r.len; ++(*i))\n        {\n            if(r.str[*i] == '\\n')\n                ++numnl_following;\n            // skip leading whitespace\n            else if(r.str[*i] == ' ' || r.str[*i] == '\\t' || r.str[*i] == '\\r')\n                ;\n            else\n                break;\n        }\n    }\n    else\n    {\n        for( ; *i < r.len; ++(*i))\n        {\n            if(r.str[*i] == '\\n')\n            {\n                ++numnl_following;\n                // skip the indentation after the newline\n                size_t stop = *i + indentation;\n                for( ; *i < r.len; ++(*i))\n                {\n                    if(r.str[*i] != ' ' && r.str[*i] != '\\r')\n                        break;\n                    RYML_ASSERT(*i < stop);\n                }\n                C4_UNUSED(stop);\n            }\n            // skip leading whitespace\n            else if(r.str[*i] == ' ' || r.str[*i] == '\\t' || r.str[*i] == '\\r')\n                ;\n            else\n                break;\n        }\n    }\n    return numnl_following;\n}\n\n} // anon namespace\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\ntemplate<class EventHandler>\nParseEngine<EventHandler>::~ParseEngine()\n{\n    _free();\n    _clr();\n}\n\ntemplate<class EventHandler>\nParseEngine<EventHandler>::ParseEngine(EventHandler *evt_handler, ParserOptions opts)\n    : m_options(opts)\n    , m_file()\n    , m_buf()\n    , m_evt_handler(evt_handler)\n    , m_pending_anchors()\n    , m_pending_tags()\n    , m_newline_offsets()\n    , m_newline_offsets_size(0)\n    , m_newline_offsets_capacity(0)\n    , m_newline_offsets_buf()\n{\n    RYML_CHECK(evt_handler);\n}\n\ntemplate<class EventHandler>\nParseEngine<EventHandler>::ParseEngine(ParseEngine &&that)\n    : m_options(that.m_options)\n    , m_file(that.m_file)\n    , m_buf(that.m_buf)\n    , m_evt_handler(that.m_evt_handler)\n    , m_pending_anchors(that.m_pending_anchors)\n    , m_pending_tags(that.m_pending_tags)\n    , m_newline_offsets(that.m_newline_offsets)\n    , m_newline_offsets_size(that.m_newline_offsets_size)\n    , m_newline_offsets_capacity(that.m_newline_offsets_capacity)\n    , m_newline_offsets_buf(that.m_newline_offsets_buf)\n{\n    that._clr();\n}\n\ntemplate<class EventHandler>\nParseEngine<EventHandler>::ParseEngine(ParseEngine const& that)\n    : m_options(that.m_options)\n    , m_file(that.m_file)\n    , m_buf(that.m_buf)\n    , m_evt_handler(that.m_evt_handler)\n    , m_pending_anchors(that.m_pending_anchors)\n    , m_pending_tags(that.m_pending_tags)\n    , m_newline_offsets()\n    , m_newline_offsets_size()\n    , m_newline_offsets_capacity()\n    , m_newline_offsets_buf()\n{\n    if(that.m_newline_offsets_capacity)\n    {\n        _resize_locations(that.m_newline_offsets_capacity);\n        _RYML_CB_CHECK(m_evt_handler->m_stack.m_callbacks, m_newline_offsets_capacity == that.m_newline_offsets_capacity);\n        memcpy(m_newline_offsets, that.m_newline_offsets, that.m_newline_offsets_size * sizeof(size_t));\n        m_newline_offsets_size = that.m_newline_offsets_size;\n    }\n}\n\ntemplate<class EventHandler>\nParseEngine<EventHandler>& ParseEngine<EventHandler>::operator=(ParseEngine &&that)\n{\n    _free();\n    m_options = (that.m_options);\n    m_file = (that.m_file);\n    m_buf = (that.m_buf);\n    m_evt_handler = that.m_evt_handler;\n    m_pending_anchors = that.m_pending_anchors;\n    m_pending_tags = that.m_pending_tags;\n    m_newline_offsets = (that.m_newline_offsets);\n    m_newline_offsets_size = (that.m_newline_offsets_size);\n    m_newline_offsets_capacity = (that.m_newline_offsets_capacity);\n    m_newline_offsets_buf = (that.m_newline_offsets_buf);\n    that._clr();\n    return *this;\n}\n\ntemplate<class EventHandler>\nParseEngine<EventHandler>& ParseEngine<EventHandler>::operator=(ParseEngine const& that)\n{\n    _free();\n    m_options = (that.m_options);\n    m_file = (that.m_file);\n    m_buf = (that.m_buf);\n    m_evt_handler = that.m_evt_handler;\n    m_pending_anchors = that.m_pending_anchors;\n    m_pending_tags = that.m_pending_tags;\n    if(that.m_newline_offsets_capacity > m_newline_offsets_capacity)\n        _resize_locations(that.m_newline_offsets_capacity);\n    _RYML_CB_CHECK(m_evt_handler->m_stack.m_callbacks, m_newline_offsets_capacity >= that.m_newline_offsets_capacity);\n    _RYML_CB_CHECK(m_evt_handler->m_stack.m_callbacks, m_newline_offsets_capacity >= that.m_newline_offsets_size);\n    memcpy(m_newline_offsets, that.m_newline_offsets, that.m_newline_offsets_size * sizeof(size_t));\n    m_newline_offsets_size = that.m_newline_offsets_size;\n    m_newline_offsets_buf = that.m_newline_offsets_buf;\n    return *this;\n}\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_clr()\n{\n    m_options = {};\n    m_file = {};\n    m_buf = {};\n    m_evt_handler = {};\n    m_pending_anchors = {};\n    m_pending_tags = {};\n    m_newline_offsets = {};\n    m_newline_offsets_size = {};\n    m_newline_offsets_capacity = {};\n    m_newline_offsets_buf = {};\n}\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_free()\n{\n    if(m_newline_offsets)\n    {\n        _RYML_CB_FREE(m_evt_handler->m_stack.m_callbacks, m_newline_offsets, size_t, m_newline_offsets_capacity);\n        m_newline_offsets = nullptr;\n        m_newline_offsets_size = 0u;\n        m_newline_offsets_capacity = 0u;\n        m_newline_offsets_buf = 0u;\n    }\n}\n\n\n//-----------------------------------------------------------------------------\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_reset()\n{\n    m_pending_anchors = {};\n    m_pending_tags = {};\n    if(m_options.locations())\n    {\n        _prepare_locations();\n    }\n    m_was_inside_qmrk = false;\n}\n\n\n//-----------------------------------------------------------------------------\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_relocate_arena(csubstr prev_arena, substr next_arena)\n{\n    #define _ryml_relocate(s)                                   \\\n    if(s.is_sub(prev_arena))                                    \\\n    {                                                           \\\n        s.str = next_arena.str + (s.str - prev_arena.str);      \\\n    }\n    _ryml_relocate(m_buf);\n    _ryml_relocate(m_newline_offsets_buf);\n    for(size_t i = 0; i < m_pending_tags.num_entries; ++i)\n        _ryml_relocate(m_pending_tags.annotations[i].str);\n    for(size_t i = 0; i < m_pending_anchors.num_entries; ++i)\n        _ryml_relocate(m_pending_anchors.annotations[i].str);\n    #undef _ryml_relocate\n}\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_s_relocate_arena(void* data, csubstr prev_arena, substr next_arena)\n{\n    ((ParseEngine*)data)->_relocate_arena(prev_arena, next_arena);\n}\n\n\n//-----------------------------------------------------------------------------\n\ntemplate<class EventHandler>\ntemplate<class DumpFn>\nvoid ParseEngine<EventHandler>::_fmt_msg(DumpFn &&dumpfn) const\n{\n    auto const *const C4_RESTRICT st = m_evt_handler->m_curr;\n    auto const& lc = st->line_contents;\n    csubstr contents = lc.stripped;\n    if(contents.len)\n    {\n        // print the yaml src line\n        size_t offs = 3u + to_chars(substr{}, st->pos.line) + to_chars(substr{}, st->pos.col);\n        if(m_file.len)\n        {\n            detail::_dump(dumpfn, \"{}:\", m_file);\n            offs += m_file.len + 1;\n        }\n        detail::_dump(dumpfn, \"{}:{}: \", st->pos.line, st->pos.col);\n        csubstr maybe_full_content = (contents.len < 80u ? contents : contents.first(80u));\n        csubstr maybe_ellipsis = (contents.len < 80u ? csubstr{} : csubstr(\"...\"));\n        detail::_dump(dumpfn, \"{}{}  (size={})\\n\", maybe_full_content, maybe_ellipsis, contents.len);\n        // highlight the remaining portion of the previous line\n        size_t firstcol = (size_t)(lc.rem.begin() - lc.full.begin());\n        size_t lastcol = firstcol + lc.rem.len;\n        for(size_t i = 0; i < offs + firstcol; ++i)\n            dumpfn(\" \");\n        dumpfn(\"^\");\n        for(size_t i = 1, e = (lc.rem.len < 80u ? lc.rem.len : 80u); i < e; ++i)\n            dumpfn(\"~\");\n        detail::_dump(dumpfn, \"{}  (cols {}-{})\\n\", maybe_ellipsis, firstcol+1, lastcol+1);\n    }\n    else\n    {\n        dumpfn(\"\\n\");\n    }\n\n#ifdef RYML_DBG\n    // next line: print the state flags\n    {\n        char flagbuf_[128];\n        detail::_dump(dumpfn, \"top state: {}\\n\", detail::_parser_flags_to_str(flagbuf_, m_evt_handler->m_curr->flags));\n    }\n#endif\n}\n\n\n//-----------------------------------------------------------------------------\n\ntemplate<class EventHandler>\ntemplate<class ...Args>\nvoid ParseEngine<EventHandler>::_err(csubstr fmt, Args const& C4_RESTRICT ...args) const\n{\n    char errmsg[RYML_ERRMSG_SIZE];\n    detail::_SubstrWriter writer(errmsg);\n    auto dumpfn = [&writer](csubstr s){ writer.append(s); };\n    detail::_dump(dumpfn, fmt, args...);\n    writer.append('\\n');\n    _fmt_msg(dumpfn);\n    size_t len = writer.pos < RYML_ERRMSG_SIZE ? writer.pos : RYML_ERRMSG_SIZE;\n    m_evt_handler->cancel_parse();\n    m_evt_handler->m_stack.m_callbacks.m_error(errmsg, len, m_evt_handler->m_curr->pos, m_evt_handler->m_stack.m_callbacks.m_user_data);\n}\n\n\n//-----------------------------------------------------------------------------\n#ifdef RYML_DBG\ntemplate<class EventHandler>\ntemplate<class ...Args>\nvoid ParseEngine<EventHandler>::_dbg(csubstr fmt, Args const& C4_RESTRICT ...args) const\n{\n    if(_dbg_enabled())\n    {\n        auto dumpfn = [](csubstr s){ if(s.str) fwrite(s.str, 1, s.len, stdout); };\n        detail::_dump(dumpfn, fmt, args...);\n        dumpfn(\"\\n\");\n        _fmt_msg(dumpfn);\n    }\n}\n#endif\n\n\n//-----------------------------------------------------------------------------\ntemplate<class EventHandler>\nbool ParseEngine<EventHandler>::_finished_file() const\n{\n    bool ret = m_evt_handler->m_curr->pos.offset >= m_buf.len;\n    if(ret)\n    {\n        _c4dbgp(\"finished file!!!\");\n    }\n    return ret;\n}\n\ntemplate<class EventHandler>\nC4_HOT C4_ALWAYS_INLINE bool ParseEngine<EventHandler>::_finished_line() const\n{\n    return m_evt_handler->m_curr->line_contents.rem.empty();\n}\n\n\n//-----------------------------------------------------------------------------\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_maybe_skip_whitespace_tokens()\n{\n    csubstr rem = m_evt_handler->m_curr->line_contents.rem;\n    if(rem.len && (rem.str[0] == ' ' _RYML_WITH_TAB_TOKENS(|| rem.str[0] == '\\t')))\n    {\n        size_t pos = rem.first_not_of(_RYML_WITH_OR_WITHOUT_TAB_TOKENS(\" \\t\", ' '));\n        if(pos == npos)\n            pos = rem.len; // maybe the line is just all whitespace\n        _c4dbgpf(\"skip {} whitespace characters\", pos);\n        _line_progressed(pos);\n    }\n}\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_maybe_skipchars(char c)\n{\n    csubstr rem = m_evt_handler->m_curr->line_contents.rem;\n    if(rem.len && rem.str[0] == c)\n    {\n        size_t pos = rem.first_not_of(c);\n        if(pos == npos)\n            pos = rem.len; // maybe the line is just all c\n        _c4dbgpf(\"skip {}x'{}'\", pos, c);\n        _line_progressed(pos);\n    }\n}\n\n#ifdef RYML_NO_COVERAGE__TO_BE_DELETED\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_maybe_skipchars_up_to(char c, size_t max_to_skip)\n{\n    csubstr rem = m_evt_handler->m_curr->line_contents.rem;\n    if(rem.len && rem.str[0] == c)\n    {\n        size_t pos = rem.first_not_of(c);\n        if(pos == npos)\n            pos = rem.len; // maybe the line is just all c\n        if(pos > max_to_skip)\n            pos = max_to_skip;\n        _c4dbgpf(\"skip {}x'{}'\", pos, c);\n        _line_progressed(pos);\n    }\n}\n#endif\n\ntemplate<class EventHandler>\ntemplate<size_t N>\nvoid ParseEngine<EventHandler>::_skipchars(const char (&chars)[N])\n{\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, m_evt_handler->m_curr->line_contents.rem.begins_with_any(chars));\n    size_t pos = m_evt_handler->m_curr->line_contents.rem.first_not_of(chars);\n    if(pos == npos)\n        pos = m_evt_handler->m_curr->line_contents.rem.len; // maybe the line is just whitespace\n    _c4dbgpf(\"skip {} characters\", pos);\n    _line_progressed(pos);\n}\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_skip_comment()\n{\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, m_evt_handler->m_curr->line_contents.rem.begins_with('#'));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, m_evt_handler->m_curr->line_contents.rem.is_sub(m_evt_handler->m_curr->line_contents.full));\n    csubstr rem = m_evt_handler->m_curr->line_contents.rem;\n    csubstr full = m_evt_handler->m_curr->line_contents.full;\n    // raise an error if the comment is not preceded by whitespace\n    if(!full.begins_with('#'))\n    {\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, rem.str > full.str);\n        const char c = full[(size_t)(rem.str - full.str - 1)];\n        if(C4_UNLIKELY(c != ' ' && c != '\\t'))\n            _RYML_CB_ERR(m_evt_handler->m_stack.m_callbacks, \"comment not preceded by whitespace\");\n    }\n    else\n    {\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, rem.str == full.str);\n    }\n    _c4dbgpf(\"comment was '{}'\", rem);\n    _line_progressed(rem.len);\n}\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_maybe_skip_comment()\n{\n    csubstr s = m_evt_handler->m_curr->line_contents.rem.triml(' ');\n    if(s.begins_with('#'))\n    {\n        _line_progressed((size_t)(s.str - m_evt_handler->m_curr->line_contents.rem.str));\n        _skip_comment();\n    }\n}\n\ntemplate<class EventHandler>\nbool ParseEngine<EventHandler>::_maybe_scan_following_colon() noexcept\n{\n    if(m_evt_handler->m_curr->line_contents.rem.len)\n    {\n        if(m_evt_handler->m_curr->line_contents.rem.str[0] == ' ' || m_evt_handler->m_curr->line_contents.rem.str[0] == '\\t')\n        {\n            size_t pos = m_evt_handler->m_curr->line_contents.rem.first_not_of(\" \\t\");\n            if(pos == npos)\n                pos = m_evt_handler->m_curr->line_contents.rem.len; // maybe the line has only spaces\n            _c4dbgpf(\"skip {}x'{}'\", pos, ' ');\n            _line_progressed(pos);\n        }\n        if(m_evt_handler->m_curr->line_contents.rem.len && (m_evt_handler->m_curr->line_contents.rem.str[0] == ':'))\n        {\n            _c4dbgp(\"found ':' colon next\");\n            _line_progressed(1);\n            return true;\n        }\n    }\n    return false;\n}\n\ntemplate<class EventHandler>\nbool ParseEngine<EventHandler>::_maybe_scan_following_comma() noexcept\n{\n    if(m_evt_handler->m_curr->line_contents.rem.len)\n    {\n        if(m_evt_handler->m_curr->line_contents.rem.str[0] == ' ' || m_evt_handler->m_curr->line_contents.rem.str[0] == '\\t')\n        {\n            size_t pos = m_evt_handler->m_curr->line_contents.rem.first_not_of(\" \\t\");\n            if(pos == npos)\n                pos = m_evt_handler->m_curr->line_contents.rem.len; // maybe the line has only spaces\n            _c4dbgpf(\"skip {}x'{}'\", pos, ' ');\n            _line_progressed(pos);\n        }\n        if(m_evt_handler->m_curr->line_contents.rem.len && (m_evt_handler->m_curr->line_contents.rem.str[0] == ','))\n        {\n            _c4dbgp(\"found ',' comma next\");\n            _line_progressed(1);\n            return true;\n        }\n    }\n    return false;\n}\n\n\n//-----------------------------------------------------------------------------\n\ntemplate<class EventHandler>\ncsubstr ParseEngine<EventHandler>::_scan_anchor()\n{\n    csubstr s = m_evt_handler->m_curr->line_contents.rem;\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, s.begins_with('&'));\n    csubstr anchor = s.range(1, s.first_of(' '));\n    _line_progressed(1u + anchor.len);\n    _maybe_skipchars(' ');\n    return anchor;\n}\n\ntemplate<class EventHandler>\ncsubstr ParseEngine<EventHandler>::_scan_ref_seq()\n{\n    csubstr s = m_evt_handler->m_curr->line_contents.rem;\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, s.begins_with('*'));\n    csubstr ref = s.first(s.first_of(\",] :\"));\n    _line_progressed(ref.len);\n    return ref;\n}\n\ntemplate<class EventHandler>\ncsubstr ParseEngine<EventHandler>::_scan_ref_map()\n{\n    csubstr s = m_evt_handler->m_curr->line_contents.rem;\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, s.begins_with('*'));\n    csubstr ref = s.first(s.first_of(\",} \"));\n    _line_progressed(ref.len);\n    return ref;\n}\n\ntemplate<class EventHandler>\ncsubstr ParseEngine<EventHandler>::_scan_tag()\n{\n    csubstr rem = m_evt_handler->m_curr->line_contents.rem.triml(' ');\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, rem.begins_with('!'));\n    csubstr t;\n    if(rem.begins_with(\"!!\"))\n    {\n        _c4dbgp(\"begins with '!!'\");\n        if(has_any(FLOW))\n            t = rem.left_of(rem.first_of(\" ,\"));\n        else\n            t = rem.left_of(rem.first_of(' '));\n    }\n    else if(rem.begins_with(\"!<\"))\n    {\n        _c4dbgp(\"begins with '!<'\");\n        t = rem.left_of(rem.first_of('>'), true);\n    }\n    #ifdef RYML_NO_COVERAGE__TO_BE_DELETED\n    else if(rem.begins_with(\"!h!\"))\n    {\n        _c4dbgp(\"begins with '!h!'\");\n        t = rem.left_of(rem.first_of(' '));\n    }\n    #endif\n    else\n    {\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, rem.begins_with('!'));\n        _c4dbgp(\"begins with '!'\");\n        if(has_any(FLOW))\n            t = rem.left_of(rem.first_of(\" ,\"));\n        else\n            t = rem.left_of(rem.first_of(' '));\n    }\n    _line_progressed(t.len);\n    _maybe_skip_whitespace_tokens();\n    return t;\n}\n\n\n//-----------------------------------------------------------------------------\n\ntemplate<class EventHandler>\nbool ParseEngine<EventHandler>::_is_valid_start_scalar_plain_flow(csubstr s)\n{\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, !s.empty());\n\n    // it's not a scalar if it starts with any of these characters:\n    switch(s.str[0])\n    {\n    // these are all legal tokens which mean no scalar is starting:\n    case '[':\n    case ']':\n    case '{':\n    case '}':\n    case '!':\n    case '&':\n    case '*':\n    case '|':\n    case '>':\n    case '#':\n        _c4dbgpf(\"not a scalar: found non-scalar token '{}'\", _c4prc(s.str[0]));\n        return false;\n    // '-' and ':' are illegal at the beginning if not followed by a scalar character\n    case '-':\n    case ':':\n        if(s.len > 1)\n        {\n            switch(s.str[1])\n            {\n            case '\\n':\n            case '\\r':\n            case '{':\n            case '[':\n            //_RYML_WITHOUT_TAB_TOKENS(case '\\t'):\n                _c4err(\"invalid token \\\":{}\\\"\", _c4prc(s.str[1]));\n                break;\n            case ' ':\n            case '}':\n            case ']':\n                if(s.str[0] == ':')\n                {\n                    _c4dbgpf(\"not a scalar: found non-scalar token '{}{}'\", s.str[0], s.str[1]);\n                    return false;\n                }\n                break;\n            default:\n                break;\n            }\n        }\n        else\n        {\n            return false;\n        }\n        break;\n    case '?':\n        if(s.len > 1)\n        {\n            switch(s.str[1])\n            {\n            case ' ':\n            case '\\n':\n            case '\\r':\n            _RYML_WITHOUT_TAB_TOKENS(case '\\t':)\n                _c4dbgpf(\"not a scalar: found non-scalar token '?{}'\", _c4prc(s.str[1]));\n                return false;\n            case '{':\n            case '}':\n            case '[':\n            case ']':\n                _c4err(\"invalid token \\\"?{}\\\"\", _c4prc(s.str[1]));\n                break;\n            default:\n                break;\n            }\n        }\n        else\n        {\n            return false;\n        }\n        break;\n    // everything else is a legal starting character\n    default:\n        break;\n    }\n\n    return true;\n}\n\ntemplate<class EventHandler>\nbool ParseEngine<EventHandler>::_scan_scalar_plain_seq_flow(ScannedScalar *C4_RESTRICT sc)\n{\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RMAP));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(BLCK));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_any(RSEQ|RSEQIMAP));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_any(FLOW));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_any(RVAL));\n\n    substr s = m_evt_handler->m_curr->line_contents.rem;\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, !s.begins_with(' '));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, !s.begins_with('\\n'));\n\n    if(!s.len)\n        return false;\n\n    if(!_is_valid_start_scalar_plain_flow(s))\n        return false;\n\n    _c4dbgp(\"scanning seqflow scalar...\");\n\n    const size_t start_offset = m_evt_handler->m_curr->pos.offset;\n    bool needs_filter = false;\n    while(true)\n    {\n        _c4dbgpf(\"scanning scalar: curr line=[{}]~~~{}~~~\", s.len, s);\n        for(size_t i = 0; i < s.len; ++i)\n        {\n            const char c = s.str[i];\n            switch(c)\n            {\n            case ',':\n                _c4dbgpf(\"found terminating character at {}: '{}'\", i, c);\n                _line_progressed(i);\n                if(m_evt_handler->m_curr->pos.offset + i > start_offset)\n                {\n                    goto ended_scalar;\n                }\n                else\n                {\n                    _c4dbgp(\"at the beginning. no scalar here.\");\n                    return false;\n                }\n                break;\n            case ']':\n                _c4dbgpf(\"found terminating character at {}: '{}'\", i, c);\n                _line_progressed(i);\n                goto ended_scalar;\n                break;\n            case '#':\n                _c4dbgp(\"found suspicious '#'\");\n                if(!i || (s.str[i-1] == ' ' _RYML_WITH_TAB_TOKENS(|| s.str[i-1] == '\\t')))\n                {\n                    _c4dbgpf(\"found terminating character at {}: '{}'\", i, c);\n                    _line_progressed(i);\n                    goto ended_scalar;\n                }\n                break;\n            case ':':\n                _c4dbgp(\"found suspicious ':'\");\n                if(s.len > i+1)\n                {\n                    const char next = s.str[i+1];\n                    _c4dbgpf(\"next char is '{}'\", _c4prc(next));\n                    if(next == ' ' || next == ',' _RYML_WITH_TAB_TOKENS(|| next == '\\t'))\n                    {\n                        _c4dbgp(\"map starting!\");\n                        if(m_evt_handler->m_curr->pos.offset + i > start_offset)\n                        {\n                            _c4dbgp(\"scalar finished!\");\n                            _line_progressed(i);\n                            goto ended_scalar;\n                        }\n                        else\n                        {\n                            _c4dbgp(\"at the beginning. no scalar here.\");\n                            return false;\n                        }\n                    }\n                    else\n                    {\n                        _c4dbgp(\"it's a scalar indeed.\");\n                        ++i; // skip the next char\n                    }\n                }\n                else if(s.len == i+1)\n                {\n                    _c4dbgp(\"':' at line end. map starting!\");\n                    return false;\n                }\n                break;\n            case '[':\n            case '{':\n            case '}':\n                _line_progressed(i);\n                _c4err(\"invalid character: '{}'\", c); // noreturn\n            default:\n                ;\n            }\n        }\n        _line_progressed(s.len);\n        if(!_finished_file())\n        {\n            _c4dbgp(\"next line!\");\n            _line_ended();\n            _scan_line();\n        }\n        else\n        {\n            _c4dbgp(\"file finished!\");\n            goto ended_scalar;\n        }\n        s = m_evt_handler->m_curr->line_contents.rem;\n        needs_filter = true;\n    }\n\nended_scalar:\n\n    sc->scalar = m_buf.range(start_offset, m_evt_handler->m_curr->pos.offset).trimr(_RYML_WITH_OR_WITHOUT_TAB_TOKENS(\" \\t\", ' '));\n    sc->needs_filter = needs_filter;\n\n    _c4prscalar(\"scanned plain scalar\", sc->scalar, /*keep_newlines*/true);\n\n    return true;\n}\n\ntemplate<class EventHandler>\nbool ParseEngine<EventHandler>::_scan_scalar_plain_map_flow(ScannedScalar *C4_RESTRICT sc)\n{\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RSEQ) || has_any(RSEQIMAP));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(BLCK));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_any(RMAP|RSEQIMAP));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_any(FLOW));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_any(RKEY|RVAL|QMRK));\n\n    substr s = m_evt_handler->m_curr->line_contents.rem;\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, !s.begins_with(' '));\n\n    if(!s.len)\n        return false;\n\n    if(!_is_valid_start_scalar_plain_flow(s))\n        return false;\n\n    _c4dbgp(\"scanning scalar...\");\n\n    const size_t start_offset = m_evt_handler->m_curr->pos.offset;\n    bool needs_filter = false;\n    while(true)\n    {\n        for(size_t i = 0; i < s.len; ++i)\n        {\n            const char c = s.str[i];\n            switch(c)\n            {\n            case ',':\n            case '}':\n                _line_progressed(i);\n                _c4dbgpf(\"found terminating character: '{}'\", c);\n                goto ended_scalar;\n            case ':':\n                if(s.len == i+1 || s.str[i+1] == ' ' || s.str[i+1] == ',' || s.str[i+1] == '}' _RYML_WITH_TAB_TOKENS(|| s.str[i+1] == '\\t'))\n                {\n                    _line_progressed(i);\n                    _c4dbgpf(\"found terminating character: '{}'\", c);\n                    goto ended_scalar;\n                }\n                break;\n            case '{':\n            case '[':\n                _line_progressed(i);\n                _c4err(\"invalid character: '{}'\", c); // noreturn\n                break;\n            case ']':\n                _line_progressed(i);\n                if(has_any(RSEQIMAP))\n                    goto ended_scalar;\n                else\n                    _c4err(\"invalid character: '{}'\", c); // noreturn\n                break;\n            case '#':\n                if(!i || s.str[i-1] == ' ' _RYML_WITH_TAB_TOKENS(|| s.str[i-1] == '\\t'))\n                {\n                    _line_progressed(i);\n                    _c4dbgpf(\"found terminating character: '{}'\", c);\n                    goto ended_scalar;\n                }\n                break;\n            default:\n                ;\n            }\n        }\n        _c4dbgp(\"next line!\");\n        _line_progressed(s.len);\n        if(!_finished_file())\n        {\n            _c4dbgp(\"next line!\");\n            _line_ended();\n            _scan_line();\n        }\n        else\n        {\n            _c4dbgp(\"file finished!\");\n            goto ended_scalar;\n        }\n        s = m_evt_handler->m_curr->line_contents.rem;\n        needs_filter = true;\n    }\n\nended_scalar:\n\n    sc->scalar = m_buf.range(start_offset, m_evt_handler->m_curr->pos.offset).trimr(_RYML_WITH_OR_WITHOUT_TAB_TOKENS(\" \\n\\t\\r\", \" \\n\\r\"));\n    sc->needs_filter = needs_filter;\n\n    _c4dbgpf(\"scalar was [{}]~~~{}~~~\", sc->scalar.len, sc->scalar);\n\n    return true;\n}\n\ntemplate<class EventHandler>\nbool ParseEngine<EventHandler>::_scan_scalar_seq_json(ScannedScalar *C4_RESTRICT sc)\n{\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RMAP));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(BLCK));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_any(RSEQ));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_any(FLOW));\n\n    substr s = m_evt_handler->m_curr->line_contents.rem;\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, !s.begins_with(' '));\n\n    if(!s.len)\n        return false;\n\n    _c4dbgp(\"scanning scalar...\");\n\n    switch(s.str[0])\n    {\n    case ']':\n    case '{':\n    case ',':\n        _c4dbgp(\"not a scalar.\");\n        return false;\n    }\n\n    {\n        const size_t len = _is_special_json_scalar(s);\n        if(len)\n        {\n            sc->scalar = s.first(len);\n            sc->needs_filter = false;\n            _c4dbgpf(\"special json scalar: '{}'\", sc->scalar);\n            _line_progressed(len);\n            return true;\n        }\n    }\n\n    // must be a number\n    size_t i = 0;\n    for( ; i < s.len; ++i)\n    {\n        const char c = s.str[i];\n        switch(c)\n        {\n        case ',':\n        case ']':\n        case ' ':\n        case '\\t':\n            _c4dbgpf(\"found terminating character: '{}'\", c);\n            goto ended_scalar;\n        case '#':\n            if(!i || s.str[i-1] == ' ')\n            {\n                _c4dbgpf(\"found terminating character: '{}'\", c);\n                goto ended_scalar;\n            }\n            break;\n        default:\n            ;\n        }\n    }\n\nended_scalar:\n\n    if(C4_LIKELY(i > 0))\n    {\n        _line_progressed(i);\n        sc->scalar = s.first(i);\n        sc->needs_filter = false;\n        _c4dbgpf(\"scalar was [{}]~~~{}~~~\", sc->scalar.len, sc->scalar);\n        return true;\n    }\n\n    return false;\n}\n\ntemplate<class EventHandler>\nbool ParseEngine<EventHandler>::_scan_scalar_map_json(ScannedScalar *C4_RESTRICT sc)\n{\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RSEQ));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(BLCK));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_any(RMAP));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_any(FLOW));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_any(RKEY|RVAL));\n\n    substr s = m_evt_handler->m_curr->line_contents.rem;\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, !s.begins_with(' '));\n\n    if(!s.len)\n        return false;\n\n    _c4dbgp(\"scanning scalar...\");\n\n    {\n        const size_t len = _is_special_json_scalar(s);\n        if(len)\n        {\n            sc->scalar = s.first(len);\n            sc->needs_filter = false;\n            _c4dbgpf(\"special json scalar: '{}'\", sc->scalar);\n            _line_progressed(len);\n            return true;\n        }\n    }\n\n    // must be a number\n    size_t i = 0;\n    for( ; i < s.len; ++i)\n    {\n        const char c = s.str[i];\n        switch(c)\n        {\n        case ',':\n        case '}':\n        case ' ':\n        case '\\t':\n            _c4dbgpf(\"found terminating character: '{}'\", c);\n            goto ended_scalar;\n        case '#':\n            if(!i || s.str[i-1] == ' ')\n            {\n                _c4dbgpf(\"found terminating character: '{}'\", c);\n                goto ended_scalar;\n            }\n            break;\n        default:\n            ;\n        }\n    }\n\nended_scalar:\n\n    if(C4_LIKELY(i > 0))\n    {\n        _line_progressed(i);\n        sc->scalar = s.first(i);\n        sc->needs_filter = false;\n        _c4dbgpf(\"scalar was [{}]~~~{}~~~\", sc->scalar.len, sc->scalar);\n        return true;\n    }\n\n    return false;\n}\n\ntemplate<class EventHandler>\nbool ParseEngine<EventHandler>::_is_doc_begin(csubstr s)\n{\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, s[0] == '-');\n    return (m_evt_handler->m_curr->line_contents.indentation == 0u && _at_line_begin() && _is_doc_begin_token(s));\n}\n\ntemplate<class EventHandler>\nbool ParseEngine<EventHandler>::_is_doc_end(csubstr s)\n{\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, s[0] == '.');\n    return (m_evt_handler->m_curr->line_contents.indentation == 0u && _at_line_begin() && _is_doc_end_token(s));\n}\n\ntemplate<class EventHandler>\nbool ParseEngine<EventHandler>::_scan_scalar_plain_blck(ScannedScalar *C4_RESTRICT sc, size_t indentation)\n{\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(FLOW));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RSEQIMAP));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_any(BLCK|RUNK|USTY));\n\n    substr s = m_evt_handler->m_curr->line_contents.rem;\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, !s.begins_with(' '));\n\n    if(!s.len)\n        return false;\n\n    switch(s.str[0])\n    {\n    case '-':\n        if(_is_blck_token(s))\n        {\n            return false;\n        }\n        else if(_is_doc_begin(s))\n        {\n            _c4dbgp(\"token is doc start\");\n            return false;\n        }\n        break;\n    case ':':\n    case '?':\n        if(_is_blck_token(s))\n            return false;\n        break;\n    case '[':\n    case '{':\n    case '&':\n    case '*':\n    case '!':\n    _RYML_WITH_TAB_TOKENS(case '\\t':)\n        return false;\n    case '.':\n        if(_is_doc_end(s))\n        {\n            _c4dbgp(\"token is doc end\");\n            return false;\n        }\n        break;\n    }\n\n    _c4dbgpf(\"plain scalar! indentation={}\", indentation);\n\n    const size_t start_offset = m_evt_handler->m_curr->pos.offset;\n    const size_t start_line = m_evt_handler->m_curr->pos.line;\n\n    bool needs_filter = false;\n    while(true)\n    {\n        _c4dbgpf(\"plain scalar line: [{}]~~~{}~~~\", s.len, s);\n        for(size_t i = 0; i < s.len; ++i)\n        {\n            const char curr = s.str[i];\n            //_c4dbgpf(\"[{}]='{}'\", i, _c4prc(curr));\n            switch(curr)\n            {\n            case ':':\n                _c4dbgpf(\"[{}]: got suspicious ':'\", i);\n                // are there more characters?\n                if((i + 1 == s.len) || ((s.str[i+1] == ' ') _RYML_WITH_TAB_TOKENS( || (s.str[i+1] == '\\t'))))\n                {\n                    _c4dbgpf(\"followed by '{}'\", i+1 == s.len ? csubstr(\"\\\\n\") : _c4prc(s.str[i+1]));\n                    _line_progressed(i);\n                    // ': ' is accepted only on the first line\n                    if(C4_LIKELY(m_evt_handler->m_curr->pos.line == start_line))\n                    {\n                        _c4dbgp(\"start line. scalar ends here\");\n                        goto ended_scalar;\n                    }\n                    else\n                    {\n                        _c4err(\"parse error\");\n                    }\n                }\n                else\n                {\n                    size_t j = i;\n                    while(j + 1 < s.len && s.str[j+1] == ':')\n                    {\n                        _c4dbgp(\"skip colon\");\n                        ++j;\n                    }\n                    i = j > i ? j-1 : i;\n                    _c4dbgp(\"nothing to see here\");\n                }\n                break;\n            case '#':\n                _c4dbgp(\"got suspicious '#'\");\n                if(!i || (s.str[i-1] == ' ' || s.str[i-1] == '\\t'))\n                {\n                    _c4dbgp(\"comment! scalar ends here\");\n                    _line_progressed(i);\n                    goto ended_scalar;\n                }\n                else\n                {\n                    _c4dbgp(\"nothing to see here\");\n                }\n                break;\n            }\n        }\n        _line_progressed(s.len);\n        csubstr next_peeked = _peek_next_line(m_evt_handler->m_curr->pos.offset);\n        next_peeked = next_peeked.trimr(\"\\n\\r\");\n        const size_t next_indentation = next_peeked.first_not_of(' ');\n        _c4dbgpf(\"indentation curr={} next={}\", indentation, next_indentation);\n        if(next_indentation < indentation)\n        {\n            _c4dbgp(\"smaller indentation! scalar ended\");\n            goto ended_scalar;\n        }\n        else if(next_indentation == 0 && next_peeked.len > 0)\n        {\n            const char first = next_peeked.str[0];\n            switch(first)\n            {\n            case '-':\n                next_peeked = next_peeked.trimr(\"\\n\\r\");\n                _c4dbgpf(\"doc begin? peeked=[{}]~~~{}{}~~~\", next_peeked.len, next_peeked.len >= 3 ? next_peeked.first(3) : next_peeked, next_peeked.len > 3 ? \"...\" : \"\");\n                if(_is_doc_begin_token(next_peeked))\n                {\n                    _c4dbgp(\"doc begin! scalar ended\");\n                    goto ended_scalar;\n                }\n                break;\n            case '.':\n                next_peeked = next_peeked.trimr(\"\\n\\r\");\n                _c4dbgpf(\"doc end? peeked=[{}]~~~{}{}~~~\", next_peeked.len, next_peeked.len >= 3 ? next_peeked.first(3) : next_peeked, next_peeked.len > 3 ? \"...\" : \"\");\n                if(_is_doc_end_token(next_peeked))\n                {\n                    _c4dbgp(\"doc end! scalar ended\");\n                    goto ended_scalar;\n                }\n                break;\n            }\n        }\n        // load with next line\n        _c4dbgp(\"next line!\");\n        if(!_finished_file())\n        {\n            _c4dbgp(\"next line!\");\n            _line_ended();\n            _scan_line();\n        }\n        else\n        {\n            _c4dbgp(\"file finished!\");\n            goto ended_scalar;\n        }\n        s = m_evt_handler->m_curr->line_contents.rem;\n        needs_filter = true;\n    }\n\nended_scalar:\n\n    sc->scalar = m_buf.range(start_offset, m_evt_handler->m_curr->pos.offset).trimr(\" \\n\\r\\t\");\n    sc->needs_filter = needs_filter;\n\n    _c4dbgpf(\"scalar was [{}]~~~{}~~~\", sc->scalar.len, sc->scalar);\n\n    return true;\n}\n\ntemplate<class EventHandler>\nbool ParseEngine<EventHandler>::_scan_scalar_plain_seq_blck(ScannedScalar *C4_RESTRICT sc)\n{\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RMAP));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(FLOW));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RSEQIMAP));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_any(RSEQ));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_any(BLCK));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_any(RVAL));\n    return _scan_scalar_plain_blck(sc, m_evt_handler->m_curr->indref + 1u);\n}\n\ntemplate<class EventHandler>\nbool ParseEngine<EventHandler>::_scan_scalar_plain_map_blck(ScannedScalar *C4_RESTRICT sc)\n{\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RSEQ));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(FLOW));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_any(RMAP));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_any(BLCK));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_any(RKEY|RVAL|QMRK));\n    return _scan_scalar_plain_blck(sc, m_evt_handler->m_curr->indref + 1u);\n}\n\ntemplate<class EventHandler>\nbool ParseEngine<EventHandler>::_scan_scalar_plain_unk(ScannedScalar *C4_RESTRICT sc)\n{\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks,  has_any(RUNK|USTY));\n    return _scan_scalar_plain_blck(sc, m_evt_handler->m_curr->indref);\n}\n\n\n//-----------------------------------------------------------------------------\n\ntemplate<class EventHandler>\nsubstr ParseEngine<EventHandler>::_peek_next_line(size_t pos) const\n{\n    substr rem{}; // declare here because of the goto\n    size_t nlpos{}; // declare here because of the goto\n    pos = pos == npos ? m_evt_handler->m_curr->pos.offset : pos;\n    if(pos >= m_buf.len)\n        goto next_is_empty;\n\n    // look for the next newline chars, and jump to the right of those\n    rem = from_next_line(m_buf.sub(pos));\n    if(rem.empty())\n        goto next_is_empty;\n\n    // now get everything up to and including the following newline chars\n    nlpos = rem.first_of(\"\\r\\n\");\n    if((nlpos != csubstr::npos) && (nlpos + 1 < rem.len))\n        nlpos += _extend_from_combined_newline(rem[nlpos], rem[nlpos+1]);\n    rem = rem.left_of(nlpos, /*include_pos*/true);\n\n    _c4dbgpf(\"peek next line @ {}: (len={})'{}'\", pos, rem.len, rem.trimr(\"\\r\\n\"));\n    return rem;\n\nnext_is_empty:\n    _c4dbgpf(\"peek next line @ {}: (len=0)''\", pos);\n    return {};\n}\n\n//-----------------------------------------------------------------------------\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_scan_line()\n{\n    if(C4_LIKELY(m_evt_handler->m_curr->pos.offset < m_buf.len))\n        m_evt_handler->m_curr->line_contents.reset_with_next_line(m_buf, m_evt_handler->m_curr->pos.offset);\n    else\n        m_evt_handler->m_curr->line_contents.reset(m_buf.last(0), m_buf.last(0));\n}\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_line_progressed(size_t ahead)\n{\n    _c4dbgpf(\"line[{}] ({} cols) progressed by {}:  col {}-->{}   offset {}-->{}\", m_evt_handler->m_curr->pos.line, m_evt_handler->m_curr->line_contents.full.len, ahead, m_evt_handler->m_curr->pos.col, m_evt_handler->m_curr->pos.col+ahead, m_evt_handler->m_curr->pos.offset, m_evt_handler->m_curr->pos.offset+ahead);\n    m_evt_handler->m_curr->pos.offset += ahead;\n    m_evt_handler->m_curr->pos.col += ahead;\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, m_evt_handler->m_curr->pos.col <= m_evt_handler->m_curr->line_contents.stripped.len+1);\n    m_evt_handler->m_curr->line_contents.rem = m_evt_handler->m_curr->line_contents.rem.sub(ahead);\n}\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_line_ended()\n{\n    _c4dbgpf(\"line[{}] ({} cols) ended! offset {}-->{} / col {}-->{}\",\n             m_evt_handler->m_curr->pos.line,\n             m_evt_handler->m_curr->line_contents.full.len,\n             m_evt_handler->m_curr->pos.offset, m_evt_handler->m_curr->pos.offset + m_evt_handler->m_curr->line_contents.full.len - m_evt_handler->m_curr->line_contents.stripped.len,\n             m_evt_handler->m_curr->pos.col, 1);\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, m_evt_handler->m_curr->pos.col == m_evt_handler->m_curr->line_contents.stripped.len + 1);\n    m_evt_handler->m_curr->pos.offset += m_evt_handler->m_curr->line_contents.full.len - m_evt_handler->m_curr->line_contents.stripped.len;\n    ++m_evt_handler->m_curr->pos.line;\n    m_evt_handler->m_curr->pos.col = 1;\n}\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_line_ended_undo()\n{\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, m_evt_handler->m_curr->pos.col == 1u);\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, m_evt_handler->m_curr->pos.line > 0u);\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, m_evt_handler->m_curr->pos.offset >= m_evt_handler->m_curr->line_contents.full.len - m_evt_handler->m_curr->line_contents.stripped.len);\n    const size_t delta = m_evt_handler->m_curr->line_contents.full.len - m_evt_handler->m_curr->line_contents.stripped.len;\n    _c4dbgpf(\"line[{}] undo ended! line {}-->{}, offset {}-->{}\", m_evt_handler->m_curr->pos.line, m_evt_handler->m_curr->pos.line, m_evt_handler->m_curr->pos.line - 1, m_evt_handler->m_curr->pos.offset, m_evt_handler->m_curr->pos.offset - delta);\n    m_evt_handler->m_curr->pos.offset -= delta;\n    --m_evt_handler->m_curr->pos.line;\n    m_evt_handler->m_curr->pos.col = m_evt_handler->m_curr->line_contents.stripped.len + 1u;\n    // don't forget to undo also the changes to the remainder of the line\n    //_RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, m_evt_handler->m_curr->pos.offset >= m_buf.len || m_buf[m_evt_handler->m_curr->pos.offset] == '\\n' || m_buf[m_evt_handler->m_curr->pos.offset] == '\\r');\n    m_evt_handler->m_curr->line_contents.rem = m_buf.sub(m_evt_handler->m_curr->pos.offset, 0);\n}\n\n\n//-----------------------------------------------------------------------------\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_set_indentation(size_t indentation)\n{\n    m_evt_handler->m_curr->indref = indentation;\n    _c4dbgpf(\"state[{}]: saving indentation: {}\", m_evt_handler->m_curr->level, m_evt_handler->m_curr->indref);\n}\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_save_indentation()\n{\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, m_evt_handler->m_curr->line_contents.rem.begin() >= m_evt_handler->m_curr->line_contents.full.begin());\n    m_evt_handler->m_curr->indref = m_evt_handler->m_curr->line_contents.current_col();\n    _c4dbgpf(\"state[{}]: saving indentation: {}\", m_evt_handler->m_curr->level, m_evt_handler->m_curr->indref);\n}\n\n\n//-----------------------------------------------------------------------------\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_end_map_blck()\n{\n    _c4dbgp(\"mapblck: end\");\n    if(has_any(RKCL|RVAL))\n    {\n        _c4dbgp(\"mapblck: set missing val\");\n        _handle_annotations_before_blck_val_scalar();\n        m_evt_handler->set_val_scalar_plain({});\n    }\n    else if(has_any(QMRK))\n    {\n        _c4dbgp(\"mapblck: set missing keyval\");\n        _handle_annotations_before_blck_key_scalar();\n        m_evt_handler->set_key_scalar_plain({});\n        _handle_annotations_before_blck_val_scalar();\n        m_evt_handler->set_val_scalar_plain({});\n    }\n    m_evt_handler->end_map();\n}\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_end_seq_blck()\n{\n    if(has_any(RVAL))\n    {\n        _c4dbgp(\"seqblck: set missing val\");\n        _handle_annotations_before_blck_val_scalar();\n        m_evt_handler->set_val_scalar_plain({});\n    }\n    m_evt_handler->end_seq();\n}\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_end2_map()\n{\n    _c4dbgp(\"map: end\");\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_any(RMAP));\n    if(has_any(BLCK))\n    {\n        _end_map_blck();\n    }\n    else\n    {\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(FLOW));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_any(USTY));\n        m_evt_handler->_pop();\n    }\n}\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_end2_seq()\n{\n    _c4dbgp(\"seq: end\");\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_any(RSEQ));\n    if(has_any(BLCK))\n    {\n        _end_seq_blck();\n    }\n    else\n    {\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(FLOW));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_any(USTY));\n        m_evt_handler->_pop();\n    }\n}\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_begin2_doc()\n{\n    m_doc_empty = true;\n    add_flags(RDOC);\n    m_evt_handler->begin_doc();\n    m_evt_handler->m_curr->indref = 0; // ?\n}\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_begin2_doc_expl()\n{\n    m_doc_empty = true;\n    add_flags(RDOC);\n    m_evt_handler->begin_doc_expl();\n    m_evt_handler->m_curr->indref = 0; // ?\n}\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_end2_doc()\n{\n    _c4dbgp(\"doc: end\");\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_any(RDOC));\n    if(m_doc_empty)\n    {\n        _c4dbgp(\"doc was empty; add empty val\");\n        m_evt_handler->set_val_scalar_plain({});\n    }\n    m_evt_handler->end_doc();\n}\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_end2_doc_expl()\n{\n    _c4dbgp(\"doc: end\");\n    if(m_doc_empty)\n    {\n        _c4dbgp(\"doc: no children; add empty val\");\n        m_evt_handler->set_val_scalar_plain({});\n    }\n    m_evt_handler->end_doc_expl();\n}\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_maybe_begin_doc()\n{\n    if(has_none(RDOC))\n    {\n        _c4dbgp(\"doc must be started\");\n        _begin2_doc();\n    }\n}\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_maybe_end_doc()\n{\n    if(has_any(RDOC))\n    {\n        _c4dbgp(\"doc must be finished\");\n        _end2_doc();\n    }\n}\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_end_doc_suddenly__pop()\n{\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, m_evt_handler->m_stack.size() >= 1);\n    if(m_evt_handler->m_stack[0].flags & RDOC)\n    {\n        _c4dbgp(\"root is RDOC\");\n        if(m_evt_handler->m_curr->level != 0)\n            _handle_indentation_pop(&m_evt_handler->m_stack[0]);\n    }\n    else if((m_evt_handler->m_stack.size() > 1) && (m_evt_handler->m_stack[1].flags & RDOC))\n    {\n        _c4dbgp(\"root is STREAM\");\n        if(m_evt_handler->m_curr->level != 1)\n            _handle_indentation_pop(&m_evt_handler->m_stack[1]);\n    }\n    else\n    {\n        _c4err(\"internal error\");\n    }\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_any(RDOC));\n}\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_end_doc_suddenly()\n{\n    _c4dbgp(\"end doc suddenly\");\n    _end_doc_suddenly__pop();\n    _end2_doc_expl();\n    addrem_flags(RUNK|RTOP|NDOC, RMAP|RSEQ|RDOC);\n}\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_start_doc_suddenly()\n{\n    _c4dbgp(\"start doc suddenly\");\n    _end_doc_suddenly__pop();\n    _end2_doc();\n    _begin2_doc_expl();\n}\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_end_stream()\n{\n    _c4dbgpf(\"end_stream, level={} node_id={}\", m_evt_handler->m_curr->level, m_evt_handler->m_curr->node_id);\n    if(has_all(RSEQ|FLOW))\n        _c4err(\"missing terminating ]\");\n    else if(has_all(RMAP|FLOW))\n        _c4err(\"missing terminating }\");\n    if(m_evt_handler->m_stack.size() > 1)\n        _handle_indentation_pop(m_evt_handler->m_stack.begin());\n    if(has_all(RDOC))\n    {\n        _end2_doc();\n    }\n    else if(has_all(RTOP|RUNK))\n    {\n        if(m_pending_anchors.num_entries || m_pending_tags.num_entries)\n        {\n            if(m_doc_empty)\n            {\n                m_evt_handler->begin_doc();\n                _handle_annotations_before_blck_val_scalar();\n                m_evt_handler->set_val_scalar_plain({});\n                m_evt_handler->end_doc();\n            }\n        }\n    }\n    m_evt_handler->end_stream();\n}\n\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_handle_indentation_pop(ParserState const* popto)\n{\n    _c4dbgpf(\"popping {} level{}: from level {}(@ind={}) to level {}(@ind={})\", m_evt_handler->m_curr->level - popto->level, (((m_evt_handler->m_curr->level - popto->level) > 1) ? \"s\" : \"\"), m_evt_handler->m_curr->level, m_evt_handler->m_curr->indref, popto->level, popto->indref);\n    while(m_evt_handler->m_curr != popto)\n    {\n        if(has_any(RSEQ))\n        {\n            _c4dbgpf(\"popping seq at level {} (indentation={},addr={})\", m_evt_handler->m_curr->level, m_evt_handler->m_curr->indref, m_evt_handler->m_curr);\n            _end2_seq();\n        }\n        else if(has_any(RMAP))\n        {\n            _c4dbgpf(\"popping map at level {} (indentation={},addr={})\", m_evt_handler->m_curr->level, m_evt_handler->m_curr->indref, m_evt_handler->m_curr);\n            _end2_map();\n        }\n        else\n        {\n            break;\n        }\n    }\n    _c4dbgpf(\"current level is {} (indentation={})\", m_evt_handler->m_curr->level, m_evt_handler->m_curr->indref);\n}\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_handle_indentation_pop_from_block_seq()\n{\n    // search the stack frame to jump to based on its indentation\n    using state_type = typename EventHandler::state;\n    state_type const* popto = nullptr;\n    auto &stack = m_evt_handler->m_stack;\n    _RYML_CB_ASSERT(stack.m_callbacks, stack.is_contiguous()); // this search relies on the stack being contiguous\n    _RYML_CB_ASSERT(stack.m_callbacks, m_evt_handler->m_curr >= stack.begin() && m_evt_handler->m_curr < stack.end());\n    const size_t ind = m_evt_handler->m_curr->line_contents.indentation;\n    #ifdef RYML_DBG\n    if(_dbg_enabled())\n    {\n        char flagbuf_[128];\n        for(state_type const& s : stack)\n            _dbg_printf(\"state[{}]: ind={} node={} flags={}\\n\", s.level, s.indref, s.node_id, detail::_parser_flags_to_str(flagbuf_, s.flags));\n    }\n    #endif\n    for(state_type const* s = m_evt_handler->m_curr-1; s >= stack.begin(); --s)\n    {\n        _c4dbgpf(\"searching for state with indentation {}. curr={} (level={},node={})\", ind, s->indref, s->level, s->node_id);\n        if(s->indref == ind)\n        {\n            _c4dbgpf(\"gotit!!! level={} node={}\", s->level, s->node_id);\n            popto = s;\n            break;\n        }\n    }\n    if(!popto || popto >= m_evt_handler->m_curr || popto->level >= m_evt_handler->m_curr->level)\n    {\n        _c4err(\"parse error: incorrect indentation?\");\n    }\n    _handle_indentation_pop(popto);\n}\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_handle_indentation_pop_from_block_map()\n{\n    // search the stack frame to jump to based on its indentation\n    using state_type = typename EventHandler::state;\n    auto &stack = m_evt_handler->m_stack;\n    _RYML_CB_ASSERT(stack.m_callbacks, stack.is_contiguous()); // this search relies on the stack being contiguous\n    _RYML_CB_ASSERT(stack.m_callbacks, m_evt_handler->m_curr >= stack.begin() && m_evt_handler->m_curr < stack.end());\n    const size_t ind = m_evt_handler->m_curr->line_contents.indentation;\n    state_type const* popto = nullptr;\n    #ifdef RYML_DBG\n    char flagbuf_[128];\n    if(_dbg_enabled())\n    {\n        for(state_type const& s : stack)\n            _dbg_printf(\"state[{}]: ind={} node={} flags={}\\n\", s.level, s.indref, s.node_id, detail::_parser_flags_to_str(flagbuf_, s.flags));\n    }\n    #endif\n    for(state_type const* s = m_evt_handler->m_curr-1; s > stack.begin(); --s) // never go to the stack bottom. that's the root\n    {\n        _c4dbgpf(\"searching for state with indentation {}. current: ind={},level={},node={},flags={}\", ind, s->indref, s->level, s->node_id, detail::_parser_flags_to_str(flagbuf_, s->flags));\n        if(s->indref < ind)\n        {\n            break;\n        }\n        else if(s->indref == ind)\n        {\n            _c4dbgpf(\"same indentation!!! level={} node={}\", s->level, s->node_id);\n            if(popto && has_any(RTOP, s) && has_none(RMAP|RSEQ, s))\n            {\n                break;\n            }\n            popto = s;\n            if(has_all(RSEQ|BLCK, s))\n            {\n                csubstr rem = m_evt_handler->m_curr->line_contents.rem;\n                const size_t first = rem.first_not_of(' ');\n                _RYML_CB_ASSERT(stack.m_callbacks, first == ind || first == npos);\n                rem = rem.right_of(first, true);\n                _c4dbgpf(\"indentless? rem='{}' first={}\", rem, first);\n                if(rem.begins_with('-') && _is_blck_token(rem))\n                {\n                    _c4dbgp(\"parent was indentless seq\");\n                    break;\n                }\n            }\n        }\n    }\n    if(!popto || popto >= m_evt_handler->m_curr || popto->level >= m_evt_handler->m_curr->level)\n    {\n        _c4err(\"parse error: incorrect indentation?\");\n    }\n    _handle_indentation_pop(popto);\n}\n\n\n//-----------------------------------------------------------------------------\ntemplate<class EventHandler>\ntypename ParseEngine<EventHandler>::ScannedScalar ParseEngine<EventHandler>::_scan_scalar_squot()\n{\n    // quoted scalars can spread over multiple lines!\n    // nice explanation here: http://yaml-multiline.info/\n\n    // a span to the end of the file\n    size_t b = m_evt_handler->m_curr->pos.offset;\n    substr s = m_buf.sub(b);\n    if(s.begins_with(' '))\n    {\n        s = s.triml(' ');\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, m_buf.sub(b).is_super(s));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, s.begin() >= m_buf.sub(b).begin());\n        _line_progressed((size_t)(s.begin() - m_buf.sub(b).begin()));\n    }\n    b = m_evt_handler->m_curr->pos.offset; // take this into account\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, s.begins_with('\\''));\n\n    // skip the opening quote\n    _line_progressed(1);\n    s = s.sub(1);\n\n    bool needs_filter = false;\n\n    size_t numlines = 1; // we already have one line\n    size_t pos = npos; // find the pos of the matching quote\n    while( ! _finished_file())\n    {\n        const csubstr line = m_evt_handler->m_curr->line_contents.rem;\n        bool line_is_blank = true;\n        _c4dbgpf(\"scanning single quoted scalar @ line[{}]: ~~~{}~~~\", m_evt_handler->m_curr->pos.line, line);\n        for(size_t i = 0; i < line.len; ++i)\n        {\n            const char curr = line.str[i];\n            if(curr == '\\'') // single quotes are escaped with two single quotes\n            {\n                const char next = i+1 < line.len ? line.str[i+1] : '~';\n                if(next != '\\'') // so just look for the first quote\n                {                // without another after it\n                    pos = i;\n                    break;\n                }\n                else\n                {\n                    needs_filter = true; // needs filter to remove escaped quotes\n                    ++i; // skip the escaped quote\n                }\n            }\n            else if(curr != ' ')\n            {\n                line_is_blank = false;\n            }\n        }\n\n        // leading whitespace also needs filtering\n        needs_filter = needs_filter\n            || (numlines > 1)\n            || line_is_blank\n            || (_at_line_begin() && line.begins_with(' '));\n\n        if(pos == npos)\n        {\n            _line_progressed(line.len);\n            ++numlines;\n        }\n        else\n        {\n            _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, pos >= 0 && pos < m_buf.len);\n            _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, m_buf[m_evt_handler->m_curr->pos.offset + pos] == '\\'');\n            _line_progressed(pos + 1); // progress beyond the quote\n            pos = m_evt_handler->m_curr->pos.offset - b - 1; // but we stop before it\n            break;\n        }\n\n        _line_ended();\n        _scan_line();\n    }\n\n    if(pos == npos)\n    {\n        _c4err(\"reached end of file while looking for closing quote\");\n    }\n    else\n    {\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, pos > 0);\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, s.end() >= m_buf.begin() && s.end() <= m_buf.end());\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, s.end() == m_buf.end() || *s.end() == '\\'');\n        s = s.sub(0, pos-1);\n    }\n\n    _c4prscalar(\"scanned squoted scalar\", s, /*keep_newlines*/true);\n\n    return ScannedScalar { s, needs_filter };\n}\n\n\n//-----------------------------------------------------------------------------\ntemplate<class EventHandler>\ntypename ParseEngine<EventHandler>::ScannedScalar ParseEngine<EventHandler>::_scan_scalar_dquot()\n{\n    // quoted scalars can spread over multiple lines!\n    // nice explanation here: http://yaml-multiline.info/\n\n    // a span to the end of the file\n    size_t b = m_evt_handler->m_curr->pos.offset;\n    substr s = m_buf.sub(b);\n    if(s.begins_with(' '))\n    {\n        s = s.triml(' ');\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, m_buf.sub(b).is_super(s));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, s.begin() >= m_buf.sub(b).begin());\n        _line_progressed((size_t)(s.begin() - m_buf.sub(b).begin()));\n    }\n    b = m_evt_handler->m_curr->pos.offset; // take this into account\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, s.begins_with('\"'));\n\n    // skip the opening quote\n    _line_progressed(1);\n    s = s.sub(1);\n\n    bool needs_filter = false;\n\n    size_t numlines = 1; // we already have one line\n    size_t pos = npos; // find the pos of the matching quote\n    while( ! _finished_file())\n    {\n        const csubstr line = m_evt_handler->m_curr->line_contents.rem;\n        bool line_is_blank = true;\n        _c4dbgpf(\"scanning double quoted scalar @ line[{}]:  line='{}'\", m_evt_handler->m_curr->pos.line, line);\n        for(size_t i = 0; i < line.len; ++i)\n        {\n            const char curr = line.str[i];\n            if(curr != ' ')\n                line_is_blank = false;\n            // every \\ is an escape\n            if(curr == '\\\\')\n            {\n                const char next = i+1 < line.len ? line.str[i+1] : '~';\n                needs_filter = true;\n                if(next == '\"' || next == '\\\\')\n                    ++i;\n            }\n            else if(curr == '\"')\n            {\n                pos = i;\n                break;\n            }\n        }\n\n        // leading whitespace also needs filtering\n        needs_filter = needs_filter\n            || (numlines > 1)\n            || line_is_blank\n            || (_at_line_begin() && line.begins_with(' '));\n\n        if(pos == npos)\n        {\n            _line_progressed(line.len);\n            ++numlines;\n        }\n        else\n        {\n            _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, pos >= 0 && pos < m_buf.len);\n            _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, m_buf[m_evt_handler->m_curr->pos.offset + pos] == '\"');\n            _line_progressed(pos + 1); // progress beyond the quote\n            pos = m_evt_handler->m_curr->pos.offset - b - 1; // but we stop before it\n            break;\n        }\n\n        _line_ended();\n        _scan_line();\n    }\n\n    if(pos == npos)\n    {\n        _c4err(\"reached end of file looking for closing quote\");\n    }\n    else\n    {\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, pos > 0);\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, s.end() == m_buf.end() || *s.end() == '\"');\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, s.end() >= m_buf.begin() && s.end() <= m_buf.end());\n        s = s.sub(0, pos-1);\n    }\n\n    _c4prscalar(\"scanned dquoted scalar\", s, /*keep_newlines*/true);\n\n    return ScannedScalar { s, needs_filter };\n}\n\n\n//-----------------------------------------------------------------------------\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_scan_block(ScannedBlock *C4_RESTRICT sb, size_t indref)\n{\n    _c4dbgpf(\"blck: indref={}\", indref);\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, indref != npos);\n\n    // nice explanation here: http://yaml-multiline.info/\n    csubstr s = m_evt_handler->m_curr->line_contents.rem;\n    csubstr trimmed = s.triml(' ');\n    if(trimmed.str > s.str)\n    {\n        _c4dbgp(\"skipping whitespace\");\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, trimmed.str >= s.str);\n        _line_progressed(static_cast<size_t>(trimmed.str - s.str));\n        s = trimmed;\n    }\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, s.begins_with('|') || s.begins_with('>'));\n\n    _c4dbgpf(\"blck: specs=[{}]~~~{}~~~\", s.len, s);\n\n    // parse the spec\n    BlockChomp_e chomp = CHOMP_CLIP; // default to clip unless + or - are used\n    size_t indentation = npos; // have to find out if no spec is given\n    csubstr digits;\n    if(s.len > 1)\n    {\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, s.begins_with_any(\"|>\"));\n        csubstr t = s.sub(1);\n        _c4dbgpf(\"blck: spec is multichar: '{}'\", t);\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, t.len >= 1);\n        size_t pos = t.first_of(\"-+\");\n        _c4dbgpf(\"blck: spec chomp char at {}\", pos);\n        if(pos != npos)\n        {\n            if(t[pos] == '-')\n                chomp = CHOMP_STRIP;\n            else if(t[pos] == '+')\n                chomp = CHOMP_KEEP;\n            if(pos == 0)\n                t = t.sub(1);\n            else\n                t = t.first(pos);\n        }\n        // from here to the end, only digits are considered\n        digits = t.left_of(t.first_not_of(\"0123456789\"));\n        if( ! digits.empty())\n        {\n            if(C4_UNLIKELY(digits.len > 1))\n                _c4err(\"parse error: invalid indentation\");\n            _c4dbgpf(\"blck: parse indentation digits: [{}]~~~{}~~~\", digits.len, digits);\n            if(C4_UNLIKELY( ! c4::atou(digits, &indentation)))\n                _c4err(\"parse error: could not read indentation as decimal\");\n            if(C4_UNLIKELY( ! indentation))\n                _c4err(\"parse error: null indentation\");\n            _c4dbgpf(\"blck: indentation specified: {}. add {} from curr state -> {}\", indentation, m_evt_handler->m_curr->indref, indentation+indref);\n            indentation += m_evt_handler->m_curr->indref;\n        }\n    }\n\n    _c4dbgpf(\"blck: style={}  chomp={}  indentation={}\", s.begins_with('>') ? \"fold\" : \"literal\", chomp==CHOMP_CLIP ? \"clip\" : (chomp==CHOMP_STRIP ? \"strip\" : \"keep\"), indentation);\n\n    // finish the current line\n    _line_progressed(s.len);\n    _line_ended();\n    _scan_line();\n\n    // start with a zero-length block, already pointing at the right place\n    substr raw_block(m_buf.data() + m_evt_handler->m_curr->pos.offset, size_t(0));// m_evt_handler->m_curr->line_contents.full.sub(0, 0);\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, raw_block.begin() == m_evt_handler->m_curr->line_contents.full.begin());\n\n    // read every full line into a raw block,\n    // from which newlines are to be stripped as needed.\n    //\n    // If no explicit indentation was given, pick it from the first\n    // non-empty line. See\n    // https://yaml.org/spec/1.2.2/#8111-block-indentation-indicator\n    size_t num_lines = 0;\n    size_t first = m_evt_handler->m_curr->pos.line;\n    size_t provisional_indentation = npos;\n    LineContents lc;\n    while(( ! _finished_file()))\n    {\n        // peek next line, but do not advance immediately\n        lc.reset_with_next_line(m_buf, m_evt_handler->m_curr->pos.offset);\n        _c4dbgpf(\"blck: peeking at [{}]~~~{}~~~\", lc.stripped.len, lc.stripped);\n        // evaluate termination conditions\n        if(indentation != npos)\n        {\n            _c4dbgpf(\"blck: indentation={}\", indentation);\n            // stop when the line is deindented and not empty\n            if(lc.indentation < indentation && ( ! lc.rem.trim(\" \\t\").empty()))\n            {\n                if(raw_block.len)\n                {\n                    _c4dbgpf(\"blck: indentation decreased ref={} thisline={}\", indentation, lc.indentation);\n                }\n                else\n                {\n                    _c4err(\"indentation decreased without any scalar\");\n                }\n                break;\n            }\n            else if(indentation == 0)\n            {\n                _c4dbgpf(\"blck: noindent. lc.rem=[{}]~~~{}~~~\", lc.rem.len, lc.rem);\n                if(_is_doc_token(lc.rem))\n                {\n                    _c4dbgp(\"blck: stop. indentation=0 and doc ended\");\n                    break;\n                }\n            }\n        }\n        else\n        {\n            const size_t fns = lc.stripped.first_not_of(' ');\n            _c4dbgpf(\"blck: indentation ref not set. firstnonws={}\", fns);\n            if(fns != npos) // non-empty line\n            {\n                _RYML_WITH_TAB_TOKENS(\n                    if(C4_UNLIKELY(lc.stripped.begins_with('\\t')))\n                        _c4err(\"parse error\");\n                )\n                _c4dbgpf(\"blck: line not empty. indref={} indprov={} indentation={}\", indref, provisional_indentation, lc.indentation);\n                if(provisional_indentation == npos)\n                {\n                    if(lc.indentation < indref)\n                    {\n                        _c4dbgpf(\"blck: block terminated indentation={} < indref={}\", lc.indentation, indref);\n                        if(raw_block.len == 0)\n                        {\n                            _c4dbgp(\"blck: was empty, undo next line\");\n                            _line_ended_undo();\n                        }\n                        break;\n                    }\n                    else if(lc.indentation == m_evt_handler->m_curr->indref)\n                    {\n                        if(has_any(RSEQ|RMAP))\n                        {\n                            _c4dbgpf(\"blck: block terminated. reading container and indentation={}==indref={}\", lc.indentation, m_evt_handler->m_curr->indref);\n                            break;\n                        }\n                    }\n                    _c4dbgpf(\"blck: set indentation ref from this line: ref={}\", lc.indentation);\n                    indentation = lc.indentation;\n                }\n                else\n                {\n                    if(lc.indentation >= provisional_indentation)\n                    {\n                        _c4dbgpf(\"blck: set indentation ref from provisional indentation: provisional_ref={}, thisline={}\", provisional_indentation, lc.indentation);\n                        //indentation = provisional_indentation ? provisional_indentation : lc.indentation;\n                        indentation = lc.indentation;\n                    }\n                    else\n                    {\n                        break;\n                        //_c4err(\"parse error: first non-empty block line should have at least the original indentation\");\n                    }\n                }\n            }\n            else // empty line\n            {\n                _c4dbgpf(\"blck: line empty or {} spaces. line_indentation={} prov_indentation={}\", lc.stripped.len, lc.indentation, provisional_indentation);\n                if(provisional_indentation != npos)\n                {\n                    if(lc.stripped.len >= provisional_indentation)\n                    {\n                        _c4dbgpf(\"blck: increase provisional_ref {} -> {}\", provisional_indentation, lc.stripped.len);\n                        provisional_indentation = lc.stripped.len;\n                    }\n                    #ifdef RYML_NO_COVERAGE__TO_BE_DELETED\n                    else if(lc.indentation >= provisional_indentation && lc.indentation != npos)\n                    {\n                        _c4dbgpf(\"blck: increase provisional_ref {} -> {}\", provisional_indentation, lc.indentation);\n                        provisional_indentation = lc.indentation;\n                    }\n                    #endif\n                }\n                else\n                {\n                    provisional_indentation = lc.indentation ? lc.indentation : has_any(RSEQ|RVAL);\n                    _c4dbgpf(\"blck: initialize provisional_ref={}\", provisional_indentation);\n                    if(provisional_indentation == npos)\n                    {\n                        provisional_indentation = lc.stripped.len ? lc.stripped.len : has_any(RSEQ|RVAL);\n                        _c4dbgpf(\"blck: initialize provisional_ref={}\", provisional_indentation);\n                    }\n                    if(provisional_indentation < indref)\n                    {\n                        provisional_indentation = indref;\n                        _c4dbgpf(\"blck: initialize provisional_ref={}\", provisional_indentation);\n                    }\n                }\n            }\n        }\n        // advance now that we know the folded scalar continues\n        m_evt_handler->m_curr->line_contents = lc;\n        _c4dbgpf(\"blck: append '{}'\", m_evt_handler->m_curr->line_contents.rem);\n        raw_block.len += m_evt_handler->m_curr->line_contents.full.len;\n        _line_progressed(m_evt_handler->m_curr->line_contents.rem.len);\n        _line_ended();\n        ++num_lines;\n    }\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, m_evt_handler->m_curr->pos.line == (first + num_lines) || (raw_block.len == 0));\n    C4_UNUSED(num_lines);\n    C4_UNUSED(first);\n\n    if(indentation == npos)\n    {\n        _c4dbgpf(\"blck: set indentation from provisional: {}\", provisional_indentation);\n        indentation = provisional_indentation;\n    }\n\n    if(num_lines)\n        _line_ended_undo();\n\n    _c4prscalar(\"scanned block\", raw_block, /*keep_newlines*/true);\n\n    sb->scalar = raw_block;\n    sb->indentation = indentation;\n    sb->chomp = chomp;\n}\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n// a debugging scaffold:\n#if 0\n#define _c4dbgfws(fmt, ...) _c4dbgpf(\"filt_ws[{}->{}]: \" fmt, proc.rpos, proc.wpos, __VA_ARGS__)\n#else\n#define _c4dbgfws(...)\n#endif\n\ntemplate<class EventHandler>\ntemplate<class FilterProcessor>\nbool ParseEngine<EventHandler>::_filter_ws_handle_to_first_non_space(FilterProcessor &proc)\n{\n    _c4dbgfws(\"found whitespace '{}'\", _c4prc(proc.curr()));\n    _RYML_CB_ASSERT(this->callbacks(), proc.curr() == ' ' || proc.curr() == '\\t');\n\n    const size_t first_pos = proc.rpos > 0 ? proc.src.first_not_of(\" \\t\", proc.rpos) : proc.src.first_not_of(' ', proc.rpos);\n    if(first_pos != npos)\n    {\n        const char first_char = proc.src[first_pos];\n        _c4dbgfws(\"firstnonws='{}'@{}\", _c4prc(first_char), first_pos);\n        if(first_char == '\\n' || first_char == '\\r') // skip trailing whitespace\n        {\n            _c4dbgfws(\"whitespace is trailing on line\", \"\");\n            proc.skip(first_pos - proc.rpos);\n        }\n        else // a legit whitespace\n        {\n            proc.copy();\n            _c4dbgfws(\"legit whitespace. sofar=[{}]~~~{}~~~\", proc.wpos, proc.sofar());\n        }\n        return true;\n    }\n    _c4dbgfws(\"whitespace is trailing on line\", \"\");\n    return false;\n}\n\ntemplate<class EventHandler>\ntemplate<class FilterProcessor>\nvoid ParseEngine<EventHandler>::_filter_ws_copy_trailing(FilterProcessor &proc)\n{\n    if(!_filter_ws_handle_to_first_non_space(proc))\n    {\n        _c4dbgfws(\"... everything else is trailing whitespace - copy {} chars\", proc.src.len - proc.rpos);\n        proc.copy(proc.src.len - proc.rpos);\n    }\n}\n\ntemplate<class EventHandler>\ntemplate<class FilterProcessor>\nvoid ParseEngine<EventHandler>::_filter_ws_skip_trailing(FilterProcessor &proc)\n{\n    if(!_filter_ws_handle_to_first_non_space(proc))\n    {\n        _c4dbgfws(\"... everything else is trailing whitespace - skip {} chars\", proc.src.len - proc.rpos);\n        proc.skip(proc.src.len - proc.rpos);\n    }\n}\n\n#undef _c4dbgfws\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n/* plain scalars */\n\n// a debugging scaffold:\n#if 0\n#define _c4dbgfps(fmt, ...) _c4dbgpf(\"filt_plain[{}->{}]: \" fmt, proc.rpos, proc.wpos, __VA_ARGS__)\n#else\n#define _c4dbgfps(fmt, ...)\n#endif\n\ntemplate<class EventHandler>\ntemplate<class FilterProcessor>\nvoid ParseEngine<EventHandler>::_filter_nl_plain(FilterProcessor &C4_RESTRICT proc, size_t indentation)\n{\n    _RYML_CB_ASSERT(this->callbacks(), proc.curr() == '\\n');\n\n    _c4dbgfps(\"found newline. sofar=[{}]~~~{}~~~\", proc.wpos, proc.sofar());\n    size_t ii = proc.rpos;\n    const size_t numnl_following = _count_following_newlines(proc.src, &ii, indentation);\n    if(numnl_following)\n    {\n        proc.set('\\n', numnl_following);\n        _c4dbgfps(\"{} consecutive (empty) lines {}. totalws={}\", 1+numnl_following, ii < proc.src.len ? \"in the middle\" : \"at the end\", proc.rpos-ii);\n    }\n    else\n    {\n        const size_t ret = proc.src.first_not_of(\" \\t\", proc.rpos+1);\n        if(ret != npos)\n        {\n            proc.set(' ');\n             _c4dbgfps(\"single newline. convert to space. ret={}/{}. sofar=[{}]~~~{}~~~\", ii, proc.src.len, proc.wpos, proc.sofar());\n        }\n        else\n        {\n            _c4dbgfps(\"last newline, everything else is whitespace. ii={}/{}\", ii, proc.src.len);\n            ii = proc.src.len;\n        }\n    }\n    proc.rpos = ii;\n}\n\ntemplate<class EventHandler>\ntemplate<class FilterProcessor>\nauto ParseEngine<EventHandler>::_filter_plain(FilterProcessor &C4_RESTRICT proc, size_t indentation) -> decltype(proc.result())\n{\n    _RYML_CB_ASSERT(this->callbacks(), indentation != npos);\n    _c4dbgfps(\"before=[{}]~~~{}~~~\", proc.src.len, proc.src);\n\n    while(proc.has_more_chars())\n    {\n        const char curr = proc.curr();\n        _c4dbgfps(\"'{}', sofar=[{}]~~~{}~~~\", _c4prc(curr), proc.wpos, proc.sofar());\n        switch(curr)\n        {\n        case ' ':\n        _RYML_WITH_TAB_TOKENS(case '\\t':)\n            _c4dbgfps(\"whitespace\", curr);\n            _filter_ws_skip_trailing(proc);\n            break;\n        case '\\n':\n            _c4dbgfps(\"newline\", curr);\n            _filter_nl_plain(proc, /*indentation*/indentation);\n            break;\n        case '\\r':  // skip \\r --- https://stackoverflow.com/questions/1885900\n            _c4dbgfps(\"carriage return, ignore\", curr);\n            proc.skip();\n            break;\n        default:\n            proc.copy();\n            break;\n        }\n    }\n\n    _c4dbgfps(\"after[{}]=~~~{}~~~\", proc.wpos, proc.sofar());\n\n    return proc.result();\n}\n\n#undef _c4dbgfps\n\n\ntemplate<class EventHandler>\nFilterResult ParseEngine<EventHandler>::filter_scalar_plain(csubstr scalar, substr dst, size_t indentation)\n{\n    FilterProcessorSrcDst proc(scalar, dst);\n    return _filter_plain(proc, indentation);\n}\n\ntemplate<class EventHandler>\nFilterResult ParseEngine<EventHandler>::filter_scalar_plain_in_place(substr dst, size_t cap, size_t indentation)\n{\n    FilterProcessorInplaceEndExtending proc(dst, cap);\n    return _filter_plain(proc, indentation);\n}\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n/* single quoted */\n\n// a debugging scaffold:\n#if 0\n#define _c4dbgfsq(fmt, ...) _c4dbgpf(\"filt_squo[{}->{}]: \" fmt, proc.rpos, proc.wpos, __VA_ARGS__)\n#else\n#define _c4dbgfsq(fmt, ...)\n#endif\n\ntemplate<class EventHandler>\ntemplate<class FilterProcessor>\nvoid ParseEngine<EventHandler>::_filter_nl_squoted(FilterProcessor &C4_RESTRICT proc)\n{\n    _RYML_CB_ASSERT(this->callbacks(), proc.curr() == '\\n');\n\n    _c4dbgfsq(\"found newline. sofar=[{}]~~~{}~~~\", proc.wpos, proc.sofar());\n    size_t ii = proc.rpos;\n    const size_t numnl_following = _count_following_newlines(proc.src, &ii);\n    if(numnl_following)\n    {\n        proc.set('\\n', numnl_following);\n        _c4dbgfsq(\"{} consecutive (empty) lines {}. totalws={}\", 1+numnl_following, ii < proc.src.len ? \"in the middle\" : \"at the end\", proc.rpos-ii);\n    }\n    else\n    {\n        const size_t ret = proc.src.first_not_of(\" \\t\", proc.rpos+1);\n        if(ret != npos)\n        {\n            proc.set(' ');\n            _c4dbgfsq(\"single newline. convert to space. ret={}/{}. sofar=[{}]~~~{}~~~\", ii, proc.src.len, proc.wpos, proc.sofar());\n        }\n        else\n        {\n            proc.set(' ');\n            _c4dbgfsq(\"single newline. convert to space. ii={}/{}. sofar=[{}]~~~{}~~~\", ii, proc.src.len, proc.wpos, proc.sofar());\n        }\n    }\n    proc.rpos = ii;\n}\n\ntemplate<class EventHandler>\ntemplate<class FilterProcessor>\nauto ParseEngine<EventHandler>::_filter_squoted(FilterProcessor &C4_RESTRICT proc) -> decltype(proc.result())\n{\n    _c4dbgfsq(\"before=[{}]~~~{}~~~\", proc.src.len, proc.src);\n\n    // from the YAML spec for double-quoted scalars:\n    // https://yaml.org/spec/1.2-old/spec.html#style/flow/single-quoted\n    while(proc.has_more_chars())\n    {\n        const char curr = proc.curr();\n        _c4dbgfsq(\"'{}', sofar=[{}]~~~{}~~~\", _c4prc(curr), proc.wpos, proc.sofar());\n        switch(curr)\n        {\n        case ' ':\n        case '\\t':\n            _c4dbgfsq(\"whitespace\", curr);\n            _filter_ws_copy_trailing(proc);\n            break;\n        case '\\n':\n            _c4dbgfsq(\"newline\", curr);\n            _filter_nl_squoted(proc);\n            break;\n        case '\\r':  // skip \\r --- https://stackoverflow.com/questions/1885900\n            _c4dbgfsq(\"skip cr\", curr);\n            proc.skip();\n            break;\n        case '\\'':\n            _c4dbgfsq(\"squote\", curr);\n            if(proc.next() == '\\'')\n            {\n                _c4dbgfsq(\"two consecutive squotes\", curr);\n                proc.skip();\n                proc.copy();\n            }\n            else\n            {\n                _c4err(\"filter error\");\n            }\n            break;\n        default:\n            proc.copy();\n            break;\n        }\n    }\n\n    _c4dbgfsq(\": #filteredchars={} after=~~~[{}]{}~~~\", proc.src.len-proc.sofar().len, proc.sofar().len, proc.sofar());\n\n    return proc.result();\n}\n\n#undef _c4dbgfsq\n\ntemplate<class EventHandler>\nFilterResult ParseEngine<EventHandler>::filter_scalar_squoted(csubstr scalar, substr dst)\n{\n    FilterProcessorSrcDst proc(scalar, dst);\n    return _filter_squoted(proc);\n}\n\ntemplate<class EventHandler>\nFilterResult ParseEngine<EventHandler>::filter_scalar_squoted_in_place(substr dst, size_t cap)\n{\n    FilterProcessorInplaceEndExtending proc(dst, cap);\n    return _filter_squoted(proc);\n}\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n/* double quoted */\n\n// a debugging scaffold:\n#if 0\n#define _c4dbgfdq(fmt, ...) _c4dbgpf(\"filt_dquo[{}->{}]: \" fmt, proc.rpos, proc.wpos, __VA_ARGS__)\n#else\n#define _c4dbgfdq(...)\n#endif\n\ntemplate<class EventHandler>\ntemplate<class FilterProcessor>\nvoid ParseEngine<EventHandler>::_filter_nl_dquoted(FilterProcessor &C4_RESTRICT proc)\n{\n    _RYML_CB_ASSERT(this->callbacks(), proc.curr() == '\\n');\n\n    _c4dbgfdq(\"found newline. sofar=[{}]~~~{}~~~\", proc.wpos, proc.sofar());\n    size_t ii = proc.rpos;\n    const size_t numnl_following = _count_following_newlines(proc.src, &ii);\n    if(numnl_following)\n    {\n        proc.set('\\n', numnl_following);\n        _c4dbgfdq(\"{} consecutive (empty) lines {}. totalws={}\", 1+numnl_following, ii < proc.src.len ? \"in the middle\" : \"at the end\", proc.rpos-ii);\n    }\n    else\n    {\n        const size_t ret = proc.src.first_not_of(\" \\t\", proc.rpos+1);\n        if(ret != npos)\n        {\n            proc.set(' ');\n            _c4dbgfdq(\"single newline. convert to space. ret={}/{}. sofar=[{}]~~~{}~~~\", ii, proc.src.len, proc.wpos, proc.sofar());\n        }\n        else\n        {\n            proc.set(' ');\n            _c4dbgfdq(\"single newline. convert to space. ii={}/{}. sofar=[{}]~~~{}~~~\", ii, proc.src.len, proc.wpos, proc.sofar());\n        }\n        if(ii < proc.src.len && proc.src.str[ii] == '\\\\')\n        {\n            _c4dbgfdq(\"backslash at [{}]\", ii);\n            const char next = ii+1 < proc.src.len ? proc.src.str[ii+1] : '\\0';\n            if(next == ' ' || next == '\\t')\n            {\n                _c4dbgfdq(\"extend skip to backslash\", \"\");\n                ++ii;\n            }\n        }\n    }\n    proc.rpos = ii;\n}\n\ntemplate<class EventHandler>\ntemplate<class FilterProcessor>\nvoid ParseEngine<EventHandler>::_filter_dquoted_backslash(FilterProcessor &C4_RESTRICT proc)\n{\n    char next = proc.next();\n    _c4dbgfdq(\"backslash, next='{}'\", _c4prc(next));\n    if(next == '\\r')\n    {\n        if(proc.rpos+2 < proc.src.len && proc.src.str[proc.rpos+2] == '\\n')\n        {\n            proc.skip(); // newline escaped with \\ -- skip both (add only one as i is loop-incremented)\n            next = '\\n';\n            _c4dbgfdq(\"[{}]: was \\\\r\\\\n, now next='\\\\n'\", proc.rpos);\n        }\n    }\n\n    if(next == '\\n')\n    {\n        size_t ii = proc.rpos + 2;\n        for( ; ii < proc.src.len; ++ii)\n        {\n            // skip leading whitespace\n            if(proc.src.str[ii] == ' ' || proc.src.str[ii] == '\\t')\n                ;\n            else\n                break;\n        }\n        proc.skip(ii - proc.rpos);\n    }\n    else if(next == '\"' || next == '/' || next == ' ' || next == '\\t')\n    {\n        // escapes for json compatibility\n        proc.translate_esc(next);\n        _c4dbgfdq(\"here, used '{}'\", _c4prc(next));\n    }\n    else if(next == '\\r')\n    {\n        proc.skip();\n    }\n    else if(next == 'n')\n    {\n        proc.translate_esc('\\n');\n    }\n    else if(next == 'r')\n    {\n        proc.translate_esc('\\r');\n    }\n    else if(next == 't')\n    {\n        proc.translate_esc('\\t');\n    }\n    else if(next == '\\\\')\n    {\n        proc.translate_esc('\\\\');\n    }\n    else if(next == 'x') // UTF8\n    {\n        if(C4_UNLIKELY(proc.rpos + 1u + 2u >= proc.src.len))\n            _c4err(\"\\\\x requires 2 hex digits. scalar pos={}\", proc.rpos);\n        csubstr codepoint = proc.src.sub(proc.rpos + 2u, 2u);\n        _c4dbgfdq(\"utf8 ~~~{}~~~ rpos={} rem=~~~{}~~~\", codepoint, proc.rpos, proc.src.sub(proc.rpos));\n        uint8_t byteval = {};\n        if(C4_UNLIKELY(!read_hex(codepoint, &byteval)))\n            _c4err(\"failed to read \\\\x codepoint. scalar pos={}\", proc.rpos);\n        proc.translate_esc_bulk((const char*)&byteval, 1u, /*nread*/3u);\n        _c4dbgfdq(\"utf8 after rpos={} rem=~~~{}~~~\", proc.rpos, proc.src.sub(proc.rpos));\n    }\n    else if(next == 'u') // UTF16\n    {\n        if(C4_UNLIKELY(proc.rpos + 1u + 4u >= proc.src.len))\n            _c4err(\"\\\\u requires 4 hex digits. scalar pos={}\", proc.rpos);\n        char readbuf[8];\n        csubstr codepoint = proc.src.sub(proc.rpos + 2u, 4u);\n        uint32_t codepoint_val = {};\n        if(C4_UNLIKELY(!read_hex(codepoint, &codepoint_val)))\n            _c4err(\"failed to parse \\\\u codepoint. scalar pos={}\", proc.rpos);\n        const size_t numbytes = decode_code_point((uint8_t*)readbuf, sizeof(readbuf), codepoint_val);\n        if(C4_UNLIKELY(numbytes == 0))\n            _c4err(\"failed to decode code point={}\", proc.rpos);\n        _RYML_CB_ASSERT(callbacks(), numbytes <= 4);\n        proc.translate_esc_bulk(readbuf, numbytes, /*nread*/5u);\n    }\n    else if(next == 'U') // UTF32\n    {\n        if(C4_UNLIKELY(proc.rpos + 1u + 8u >= proc.src.len))\n            _c4err(\"\\\\U requires 8 hex digits. scalar pos={}\", proc.rpos);\n        char readbuf[8];\n        csubstr codepoint = proc.src.sub(proc.rpos + 2u, 8u);\n        uint32_t codepoint_val = {};\n        if(C4_UNLIKELY(!read_hex(codepoint, &codepoint_val)))\n            _c4err(\"failed to parse \\\\U codepoint. scalar pos={}\", proc.rpos);\n        const size_t numbytes = decode_code_point((uint8_t*)readbuf, sizeof(readbuf), codepoint_val);\n        if(C4_UNLIKELY(numbytes == 0))\n            _c4err(\"failed to decode code point={}\", proc.rpos);\n        _RYML_CB_ASSERT(callbacks(), numbytes <= 4);\n        proc.translate_esc_bulk(readbuf, numbytes, /*nread*/9u);\n    }\n    // https://yaml.org/spec/1.2.2/#rule-c-ns-esc-char\n    else if(next == '0')\n    {\n        proc.translate_esc('\\0');\n    }\n    else if(next == 'b') // backspace\n    {\n        proc.translate_esc('\\b');\n    }\n    else if(next == 'f') // form feed\n    {\n        proc.translate_esc('\\f');\n    }\n    else if(next == 'a') // bell character\n    {\n        proc.translate_esc('\\a');\n    }\n    else if(next == 'v') // vertical tab\n    {\n        proc.translate_esc('\\v');\n    }\n    else if(next == 'e') // escape character\n    {\n        proc.translate_esc('\\x1b');\n    }\n    else if(next == '_') // unicode non breaking space \\u00a0\n    {\n        // https://www.compart.com/en/unicode/U+00a0\n        const char payload[] = {\n            _RYML_CHCONST(-0x3e, 0xc2),\n            _RYML_CHCONST(-0x60, 0xa0),\n        };\n        proc.translate_esc_bulk(payload, /*nwrite*/2, /*nread*/1);\n    }\n    else if(next == 'N') // unicode next line \\u0085\n    {\n        // https://www.compart.com/en/unicode/U+0085\n        const char payload[] = {\n            _RYML_CHCONST(-0x3e, 0xc2),\n            _RYML_CHCONST(-0x7b, 0x85),\n        };\n        proc.translate_esc_bulk(payload, /*nwrite*/2, /*nread*/1);\n    }\n    else if(next == 'L') // unicode line separator \\u2028\n    {\n        // https://www.utf8-chartable.de/unicode-utf8-table.pl?start=8192&number=1024&names=-&utf8=0x&unicodeinhtml=hex\n        const char payload[] = {\n            _RYML_CHCONST(-0x1e, 0xe2),\n            _RYML_CHCONST(-0x80, 0x80),\n            _RYML_CHCONST(-0x58, 0xa8),\n        };\n        proc.translate_esc_extending(payload, /*nwrite*/3, /*nread*/1);\n    }\n    else if(next == 'P') // unicode paragraph separator \\u2029\n    {\n        // https://www.utf8-chartable.de/unicode-utf8-table.pl?start=8192&number=1024&names=-&utf8=0x&unicodeinhtml=hex\n        const char payload[] = {\n            _RYML_CHCONST(-0x1e, 0xe2),\n            _RYML_CHCONST(-0x80, 0x80),\n            _RYML_CHCONST(-0x57, 0xa9),\n        };\n        proc.translate_esc_extending(payload, /*nwrite*/3, /*nread*/1);\n    }\n    else if(next == '\\0')\n    {\n        proc.skip();\n    }\n    else\n    {\n        _c4err(\"unknown character '{}' after '\\\\' pos={}\", _c4prc(next), proc.rpos);\n    }\n    _c4dbgfdq(\"backslash...sofar=[{}]~~~{}~~~\", proc.wpos, proc.sofar());\n}\n\n\ntemplate<class EventHandler>\ntemplate<class FilterProcessor>\nauto ParseEngine<EventHandler>::_filter_dquoted(FilterProcessor &C4_RESTRICT proc) -> decltype(proc.result())\n{\n    _c4dbgfdq(\"before=[{}]~~~{}~~~\", proc.src.len, proc.src);\n    // from the YAML spec for double-quoted scalars:\n    // https://yaml.org/spec/1.2-old/spec.html#style/flow/double-quoted\n    while(proc.has_more_chars())\n    {\n        const char curr = proc.curr();\n        _c4dbgfdq(\"'{}' sofar=[{}]~~~{}~~~\", _c4prc(curr), proc.wpos, proc.sofar());\n        switch(curr)\n        {\n        case ' ':\n        case '\\t':\n        {\n            _c4dbgfdq(\"whitespace\", curr);\n            _filter_ws_copy_trailing(proc);\n            break;\n        }\n        case '\\n':\n        {\n            _c4dbgfdq(\"newline\", curr);\n            _filter_nl_dquoted(proc);\n            break;\n        }\n        case '\\r':  // skip \\r --- https://stackoverflow.com/questions/1885900\n        {\n            _c4dbgfdq(\"carriage return, ignore\", curr);\n            proc.skip();\n            break;\n        }\n        case '\\\\':\n        {\n            _filter_dquoted_backslash(proc);\n            break;\n        }\n        default:\n        {\n            proc.copy();\n            break;\n        }\n        }\n    }\n    _c4dbgfdq(\"after[{}]=~~~{}~~~\", proc.wpos, proc.sofar());\n    return proc.result();\n}\n\n#undef _c4dbgfdq\n\n\ntemplate<class EventHandler>\nFilterResult ParseEngine<EventHandler>::filter_scalar_dquoted(csubstr scalar, substr dst)\n{\n    FilterProcessorSrcDst proc(scalar, dst);\n    return _filter_dquoted(proc);\n}\n\ntemplate<class EventHandler>\nFilterResultExtending ParseEngine<EventHandler>::filter_scalar_dquoted_in_place(substr dst, size_t cap)\n{\n    FilterProcessorInplaceMidExtending proc(dst, cap);\n    return _filter_dquoted(proc);\n}\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n// block filtering helpers\n\ntemplate<class EventHandler>\ntemplate<class FilterProcessor>\nvoid ParseEngine<EventHandler>::_filter_chomp(FilterProcessor &C4_RESTRICT proc, BlockChomp_e chomp, size_t indentation)\n{\n    _RYML_CB_ASSERT(this->callbacks(), chomp == CHOMP_CLIP || chomp == CHOMP_KEEP || chomp == CHOMP_STRIP);\n    _RYML_CB_ASSERT(this->callbacks(), proc.rem().first_not_of(\" \\n\\r\") == npos);\n\n    // a debugging scaffold:\n    #if 0\n    #define _c4dbgchomp(fmt, ...) _c4dbgpf(\"chomp[{}->{}]: \" fmt, proc.rpos, proc.wpos, __VA_ARGS__)\n    #else\n    #define _c4dbgchomp(...)\n    #endif\n\n    // advance to the last line having spaces beyond the indentation\n    {\n        size_t last = _find_last_newline_and_larger_indentation(proc.rem(), indentation);\n        if(last != npos)\n        {\n            _c4dbgchomp(\"found newline and larger indentation. last={}\", last);\n            last = proc.rpos + last + size_t(1) + indentation;  // last started at to-be-read.\n            _RYML_CB_ASSERT(this->callbacks(), last <= proc.src.len);\n            // remove indentation spaces, copy the rest\n            while((proc.rpos < last) && proc.has_more_chars())\n            {\n                const char curr = proc.curr();\n                _c4dbgchomp(\"curr='{}'\", _c4prc(curr));\n                switch(curr)\n                {\n                case '\\n':\n                    {\n                        _c4dbgchomp(\"newline! remlen={}\", proc.rem().len);\n                        proc.copy();\n                        // are there spaces after the newline?\n                        csubstr at_next_line = proc.rem();\n                        if(at_next_line.begins_with(' '))\n                        {\n                            _c4dbgchomp(\"next line begins with spaces. indentation={}\", indentation);\n                            // there are spaces.\n                            size_t first_non_space = at_next_line.first_not_of(' ');\n                            _c4dbgchomp(\"first_non_space={}\", first_non_space);\n                            if(first_non_space == npos)\n                            {\n                                _c4dbgchomp(\"{} spaces, to the end\", at_next_line.len);\n                                first_non_space = at_next_line.len;\n                            }\n                            if(first_non_space <= indentation)\n                            {\n                                _c4dbgchomp(\"skip spaces={}<=indentation={}\", first_non_space, indentation);\n                                proc.skip(first_non_space);\n                            }\n                            else\n                            {\n                                _c4dbgchomp(\"skip indentation={}<spaces={}\", indentation, first_non_space);\n                                proc.skip(indentation);\n                                // copy the spaces after the indentation\n                                _c4dbgchomp(\"copy {}={}-{} spaces\", first_non_space - indentation, first_non_space, indentation);\n                                proc.copy(first_non_space - indentation);\n                            }\n                        }\n                        break;\n                    }\n                case '\\r':\n                    proc.skip();\n                    break;\n                default:\n                    _c4err(\"parse error\");\n                    break;\n                }\n            }\n        }\n    }\n\n    // from now on, we only have line ends (or indentation spaces)\n    switch(chomp)\n    {\n    case CHOMP_CLIP:\n    {\n        bool had_one = false;\n        while(proc.has_more_chars())\n        {\n            const char curr = proc.curr();\n            _c4dbgchomp(\"CLIP: '{}'\", _c4prc(curr));\n            switch(curr)\n            {\n            case '\\n':\n            {\n                _c4dbgchomp(\"copy newline!\", curr);\n                proc.copy();\n                proc.set_at_end();\n                had_one = true;\n                break;\n            }\n            case ' ':\n            case '\\r':\n                _c4dbgchomp(\"skip!\", curr);\n                proc.skip();\n                break;\n            }\n        }\n        if(!had_one) // there were no newline characters. add one.\n        {\n            _c4dbgchomp(\"chomp=CLIP: add missing newline @{}\", proc.wpos);\n            proc.set('\\n');\n        }\n        break;\n    }\n    case CHOMP_KEEP:\n    {\n        _c4dbgchomp(\"chomp=KEEP: copy all remaining new lines of {} characters\", proc.rem().len);\n        while(proc.has_more_chars())\n        {\n            const char curr = proc.curr();\n            _c4dbgchomp(\"KEEP: '{}'\", _c4prc(curr));\n            switch(curr)\n            {\n            case '\\n':\n                _c4dbgchomp(\"copy newline!\", curr);\n                proc.copy();\n                break;\n            case ' ':\n            case '\\r':\n                _c4dbgchomp(\"skip!\", curr);\n                proc.skip();\n                break;\n            }\n        }\n        break;\n    }\n    case CHOMP_STRIP:\n    {\n        _c4dbgchomp(\"chomp=STRIP: strip {} characters\", proc.rem().len);\n        // nothing to do!\n        break;\n    }\n    }\n\n    #undef _c4dbgchomp\n}\n\n\n// a debugging scaffold:\n#if 0\n#define _c4dbgfb(fmt, ...) _c4dbgpf(\"filt_block[{}->{}]: \" fmt, proc.rpos, proc.wpos, __VA_ARGS__)\n#else\n#define _c4dbgfb(...)\n#endif\n\ntemplate<class EventHandler>\ntemplate<class FilterProcessor>\nvoid ParseEngine<EventHandler>::_filter_block_indentation(FilterProcessor &C4_RESTRICT proc, size_t indentation)\n{\n    csubstr rem = proc.rem(); // remaining\n    if(rem.len)\n    {\n        size_t first = rem.first_not_of(' ');\n        if(first != npos)\n        {\n            _c4dbgfb(\"{} spaces follow before next nonws character\", first);\n            if(first < indentation)\n            {\n                _c4dbgfb(\"skip {}<{} spaces from indentation\", first, indentation);\n                proc.skip(first);\n            }\n            else\n            {\n                _c4dbgfb(\"skip {} spaces from indentation\", indentation);\n                proc.skip(indentation);\n            }\n        }\n        #ifdef RYML_NO_COVERAGE__TO_BE_DELETED\n        else\n        {\n            _c4dbgfb(\"all spaces to the end: {} spaces\", first);\n            first = rem.len;\n            if(first)\n            {\n                if(first < indentation)\n                {\n                    _c4dbgfb(\"skip everything\", first);\n                    proc.skip(proc.src.len - proc.rpos);\n                }\n                else\n                {\n                    _c4dbgfb(\"skip {} spaces from indentation\", indentation);\n                    proc.skip(indentation);\n                }\n            }\n        }\n        #endif\n    }\n}\n\ntemplate<class EventHandler>\ntemplate<class FilterProcessor>\nsize_t ParseEngine<EventHandler>::_handle_all_whitespace(FilterProcessor &C4_RESTRICT proc, BlockChomp_e chomp)\n{\n    csubstr contents = proc.src.trimr(\" \\n\\r\");\n    _c4dbgfb(\"ws: contents_len={} wslen={}\", contents.len, proc.src.len-contents.len);\n    if(!contents.len)\n    {\n        _c4dbgfb(\"ws: all whitespace: len={}\", proc.src.len);\n        if(chomp == CHOMP_KEEP && proc.src.len)\n        {\n            _c4dbgfb(\"ws: chomp=KEEP all {} newlines\", proc.src.count('\\n'));\n            while(proc.has_more_chars())\n            {\n                const char curr = proc.curr();\n                if(curr == '\\n')\n                    proc.copy();\n                else\n                    proc.skip();\n            }\n            if(!proc.wpos)\n            {\n                proc.set('\\n');\n            }\n        }\n    }\n    return contents.len;\n}\n\ntemplate<class EventHandler>\ntemplate<class FilterProcessor>\nsize_t ParseEngine<EventHandler>::_extend_to_chomp(FilterProcessor &C4_RESTRICT proc, size_t contents_len)\n{\n    _c4dbgfb(\"contents_len={}\", contents_len);\n\n    _RYML_CB_ASSERT(this->callbacks(), contents_len > 0u);\n\n    // extend contents to just before the first newline at the end,\n    // in case it is preceded by spaces\n    size_t firstnewl = proc.src.first_of('\\n', contents_len);\n    if(firstnewl != npos)\n    {\n        contents_len = firstnewl;\n        _c4dbgfb(\"contents_len={}  <--- firstnewl={}\", contents_len, firstnewl);\n    }\n    else\n    {\n        contents_len = proc.src.len;\n        _c4dbgfb(\"contents_len={}  <--- src.len={}\", contents_len, proc.src.len);\n    }\n\n    return contents_len;\n}\n\n#undef _c4dbgfb\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n// a debugging scaffold:\n#if 0\n#define _c4dbgfbl(fmt, ...) _c4dbgpf(\"filt_block_lit[{}->{}]: \" fmt, proc.rpos, proc.wpos, __VA_ARGS__)\n#else\n#define _c4dbgfbl(...)\n#endif\n\ntemplate<class EventHandler>\ntemplate<class FilterProcessor>\nauto ParseEngine<EventHandler>::_filter_block_literal(FilterProcessor &C4_RESTRICT proc, size_t indentation, BlockChomp_e chomp) -> decltype(proc.result())\n{\n    _c4dbgfbl(\"indentation={} before=[{}]~~~{}~~~\", indentation, proc.src.len, proc.src);\n\n    size_t contents_len = _handle_all_whitespace(proc, chomp);\n    if(!contents_len)\n        return proc.result();\n\n    contents_len = _extend_to_chomp(proc, contents_len);\n\n    _c4dbgfbl(\"to filter=[{}]~~~{}~~~\", contents_len, proc.src.first(contents_len));\n\n    _filter_block_indentation(proc, indentation);\n\n    // now filter the bulk\n    while(proc.has_more_chars(/*maxpos*/contents_len))\n    {\n        const char curr = proc.curr();\n        _c4dbgfbl(\"'{}' sofar=[{}]~~~{}~~~\",  _c4prc(curr), proc.wpos, proc.sofar());\n        switch(curr)\n        {\n        case '\\n':\n        {\n            _c4dbgfbl(\"found newline. skip indentation on the next line\", curr);\n            proc.copy();  // copy the newline\n            _filter_block_indentation(proc, indentation);\n            break;\n        }\n        case '\\r':\n            proc.skip();\n            break;\n        default:\n            proc.copy();\n            break;\n        }\n    }\n\n    _c4dbgfbl(\"before chomp: #tochomp={}   sofar=[{}]~~~{}~~~\", proc.rem().len, proc.sofar().len, proc.sofar());\n\n    _filter_chomp(proc, chomp, indentation);\n\n    _c4dbgfbl(\"final=[{}]~~~{}~~~\", proc.sofar().len, proc.sofar());\n\n    return proc.result();\n}\n\n#undef _c4dbgfbl\n\ntemplate<class EventHandler>\nFilterResult ParseEngine<EventHandler>::filter_scalar_block_literal(csubstr scalar, substr dst, size_t indentation, BlockChomp_e chomp)\n{\n    FilterProcessorSrcDst proc(scalar, dst);\n    return _filter_block_literal(proc, indentation, chomp);\n}\n\ntemplate<class EventHandler>\nFilterResult ParseEngine<EventHandler>::filter_scalar_block_literal_in_place(substr scalar, size_t cap, size_t indentation, BlockChomp_e chomp)\n{\n    FilterProcessorInplaceEndExtending proc(scalar, cap);\n    return _filter_block_literal(proc, indentation, chomp);\n}\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n// a debugging scaffold:\n#if 0\n#define _c4dbgfbf(fmt, ...) _c4dbgpf(\"filt_block_folded[{}->{}]: \" fmt, proc.rpos, proc.wpos, __VA_ARGS__)\n#else\n#define _c4dbgfbf(...)\n#endif\n\n\ntemplate<class EventHandler>\ntemplate<class FilterProcessor>\nvoid ParseEngine<EventHandler>::_filter_block_folded_newlines_leading(FilterProcessor &C4_RESTRICT proc, size_t indentation, size_t len)\n{\n    _filter_block_indentation(proc, indentation);\n    while(proc.has_more_chars(len))\n    {\n        const char curr = proc.curr();\n        _c4dbgfbf(\"'{}' sofar=[{}]~~~{}~~~\",  _c4prc(curr), proc.wpos, proc.sofar());\n        switch(curr)\n        {\n        case '\\n':\n            _c4dbgfbf(\"newline.\", curr);\n            proc.copy();\n            _filter_block_indentation(proc, indentation);\n            break;\n        case '\\r':\n            proc.skip();\n            break;\n        case ' ':\n        case '\\t':\n        {\n            size_t first = proc.rem().first_not_of(\" \\t\");\n            _c4dbgfbf(\"space. first={}\", first);\n            if(first == npos)\n                first = proc.rem().len;\n            _c4dbgfbf(\"... indentation increased to {}\",  first);\n            _filter_block_folded_indented_block(proc, indentation, len, first);\n            break;\n        }\n        default:\n            _c4dbgfbf(\"newl leading: not space, not newline. stop.\", 0);\n            return;\n        }\n    }\n}\n\ntemplate<class EventHandler>\ntemplate<class FilterProcessor>\nsize_t ParseEngine<EventHandler>::_filter_block_folded_newlines_compress(FilterProcessor &C4_RESTRICT proc, size_t num_newl, size_t wpos_at_first_newl)\n{\n    switch(num_newl)\n    {\n    case 1u:\n        _c4dbgfbf(\"... this is the first newline. turn into space. wpos={}\", proc.wpos);\n        wpos_at_first_newl = proc.wpos;\n        proc.skip();\n        proc.set(' ');\n        break;\n    case 2u:\n        _c4dbgfbf(\"... this is the second newline. prev space (at wpos={}) must be newline\", wpos_at_first_newl);\n        _RYML_CB_ASSERT(this->callbacks(), wpos_at_first_newl != npos);\n        _RYML_CB_ASSERT(this->callbacks(), proc.sofar()[wpos_at_first_newl] == ' ');\n        _RYML_CB_ASSERT(this->callbacks(), wpos_at_first_newl + 1u == proc.wpos);\n        proc.skip();\n        proc.set_at(wpos_at_first_newl, '\\n');\n        _RYML_CB_ASSERT(this->callbacks(), proc.sofar()[wpos_at_first_newl] == '\\n');\n        break;\n    default:\n        _c4dbgfbf(\"... subsequent newline (num_newl={}). copy\", num_newl);\n        proc.copy();\n        break;\n    }\n    return wpos_at_first_newl;\n}\n\ntemplate<class EventHandler>\ntemplate<class FilterProcessor>\nvoid ParseEngine<EventHandler>::_filter_block_folded_newlines(FilterProcessor &C4_RESTRICT proc, size_t indentation, size_t len)\n{\n    _RYML_CB_ASSERT(this->callbacks(), proc.curr() == '\\n');\n    size_t num_newl = 0;\n    size_t wpos_at_first_newl = npos;\n    while(proc.has_more_chars(len))\n    {\n        const char curr = proc.curr();\n        _c4dbgfbf(\"'{}' sofar=[{}]~~~{}~~~\",  _c4prc(curr), proc.wpos, proc.sofar());\n        switch(curr)\n        {\n        case '\\n':\n        {\n            _c4dbgfbf(\"newline. sofar={}\", num_newl);\n            // NOTE: vs2022-32bit-release builds were giving wrong\n            // results in this block, if it was written as either\n            // as a  switch(num_newl) or its equivalent if-form.\n            //\n            // For this reason, we're using a dedicated function\n            // (**_compress), which seems to work around the issue.\n            //\n            // The manifested problem was that somewhere between the\n            // assignment to curr and this point, proc.wpos (the\n            // write-position of the processor) jumped to npos, which\n            // made the write wrap-around! To make things worse,\n            // enabling prints via _c4dbgpf() and _c4dbgfbf() made the\n            // problem go away!\n            //\n            // The only way to make the problem appear with prints\n            // enabled was by disabling all prints in this function\n            // (including in the block which was moved to the compress\n            // function) and then selectively enabling only some of\n            // those prints.\n            //\n            // This may be due to some bug in the cl-x86 optimizer; or\n            // it may be triggered by some UB which may be\n            // inadvertedly present in this function or in the filter\n            // processor. This is despite our best efforts to weed out\n            // any such UB problem: neither clang-tidy nor none of the\n            // sanitizers, or gcc's -fanalyzer pointed to any problems\n            // in this code.\n            //\n            // In the end, moving this block to a separate function\n            // was the only way to bury the problem. But it may\n            // resurface again, as The Undead, rising to from the\n            // grave to haunt us with his terrible presence.\n            //\n            // We may have to revisit this. With a stake, and lots of\n            // garlic.\n            wpos_at_first_newl = _filter_block_folded_newlines_compress(proc, ++num_newl, wpos_at_first_newl);\n            _filter_block_indentation(proc, indentation);\n            break;\n        }\n        case ' ':\n        case '\\t':\n            {\n                size_t first = proc.rem().first_not_of(\" \\t\");\n                _c4dbgfbf(\"space. first={}\", first);\n                if(first == npos)\n                    first = proc.rem().len;\n                _c4dbgfbf(\"... indentation increased to {}\",  first);\n                if(num_newl)\n                {\n                    _c4dbgfbf(\"... prev space (at wpos={}) must be newline\", wpos_at_first_newl);\n                    proc.set_at(wpos_at_first_newl, '\\n');\n                }\n                if(num_newl > 1u)\n                {\n                    _c4dbgfbf(\"... add missing newline\", wpos_at_first_newl);\n                    proc.set('\\n');\n                }\n                _filter_block_folded_indented_block(proc, indentation, len, first);\n                num_newl = 0;\n                wpos_at_first_newl = npos;\n                break;\n            }\n        case '\\r':\n            proc.skip();\n            break;\n        default:\n            _c4dbgfbf(\"not space, not newline. stop.\", 0);\n            return;\n        }\n    }\n}\n\n\ntemplate<class EventHandler>\ntemplate<class FilterProcessor>\nvoid ParseEngine<EventHandler>::_filter_block_folded_indented_block(FilterProcessor &C4_RESTRICT proc, size_t indentation, size_t len, size_t curr_indentation) noexcept\n{\n    _RYML_CB_ASSERT(this->callbacks(), (proc.rem().first_not_of(\" \\t\") == curr_indentation) || (proc.rem().first_not_of(\" \\t\") == npos));\n    if(curr_indentation)\n        proc.copy(curr_indentation);\n    while(proc.has_more_chars(len))\n    {\n        const char curr = proc.curr();\n        _c4dbgfbf(\"'{}' sofar=[{}]~~~{}~~~\",  _c4prc(curr), proc.wpos, proc.sofar());\n        switch(curr)\n        {\n        case '\\n':\n            {\n                proc.copy();\n                _filter_block_indentation(proc, indentation);\n                csubstr rem = proc.rem();\n                const size_t first = rem.first_not_of(' ');\n                _c4dbgfbf(\"newline. firstns={}\",  first);\n                if(first == 0)\n                {\n                    const char c = rem[first];\n                    _c4dbgfbf(\"firstns={}='{}'\", first, _c4prc(c));\n                    if(c == '\\n' || c == '\\r')\n                    {\n                        ;\n                    }\n                    else\n                    {\n                        _c4dbgfbf(\"done with indented block\",  first);\n                        goto endloop;\n                    }\n                }\n                else if(first != npos)\n                {\n                    proc.copy(first);\n                    _c4dbgfbf(\"copy all {} spaces\",  first);\n                }\n                break;\n            }\n            break;\n        case '\\r':\n            proc.skip();\n            break;\n        default:\n            proc.copy();\n            break;\n        }\n    }\n endloop:\n    return;\n}\n\n\ntemplate<class EventHandler>\ntemplate<class FilterProcessor>\nauto ParseEngine<EventHandler>::_filter_block_folded(FilterProcessor &C4_RESTRICT proc, size_t indentation, BlockChomp_e chomp) -> decltype(proc.result())\n{\n    _c4dbgfbf(\"indentation={} before=[{}]~~~{}~~~\", indentation, proc.src.len, proc.src);\n\n    size_t contents_len = _handle_all_whitespace(proc, chomp);\n    if(!contents_len)\n        return proc.result();\n\n    contents_len = _extend_to_chomp(proc, contents_len);\n\n    _c4dbgfbf(\"to filter=[{}]~~~{}~~~\", contents_len, proc.src.first(contents_len));\n\n    _filter_block_folded_newlines_leading(proc, indentation, contents_len);\n\n    // now filter the bulk\n    while(proc.has_more_chars(/*maxpos*/contents_len))\n    {\n        const char curr = proc.curr();\n        _c4dbgfbf(\"'{}' sofar=[{}]~~~{}~~~\",  _c4prc(curr), proc.wpos, proc.sofar());\n        switch(curr)\n        {\n        case '\\n':\n        {\n            _c4dbgfbf(\"found newline\", curr);\n            _filter_block_folded_newlines(proc, indentation, contents_len);\n            break;\n        }\n        case '\\r':\n            proc.skip();\n            break;\n        default:\n            proc.copy();\n            break;\n        }\n    }\n\n    _c4dbgfbf(\"before chomp: #tochomp={}   sofar=[{}]~~~{}~~~\", proc.rem().len, proc.sofar().len, proc.sofar());\n\n    _filter_chomp(proc, chomp, indentation);\n\n    _c4dbgfbf(\"final=[{}]~~~{}~~~\", proc.sofar().len, proc.sofar());\n\n    return proc.result();\n}\n\n#undef _c4dbgfbf\n\ntemplate<class EventHandler>\nFilterResult ParseEngine<EventHandler>::filter_scalar_block_folded(csubstr scalar, substr dst, size_t indentation, BlockChomp_e chomp)\n{\n    FilterProcessorSrcDst proc(scalar, dst);\n    return _filter_block_folded(proc, indentation, chomp);\n}\n\ntemplate<class EventHandler>\nFilterResult ParseEngine<EventHandler>::filter_scalar_block_folded_in_place(substr scalar, size_t cap, size_t indentation, BlockChomp_e chomp)\n{\n    FilterProcessorInplaceEndExtending proc(scalar, cap);\n    return _filter_block_folded(proc, indentation, chomp);\n}\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\ntemplate<class EventHandler>\ncsubstr ParseEngine<EventHandler>::_filter_scalar_plain(substr s, size_t indentation)\n{\n    _c4dbgpf(\"filtering plain scalar: s=[{}]~~~{}~~~\", s.len, s);\n    FilterResult r = this->filter_scalar_plain_in_place(s, s.len, indentation);\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, r.valid());\n    _c4dbgpf(\"filtering plain scalar: success! s=[{}]~~~{}~~~\", r.get().len, r.get());\n    return r.get();\n}\n\n//-----------------------------------------------------------------------------\n\ntemplate<class EventHandler>\ncsubstr ParseEngine<EventHandler>::_filter_scalar_squot(substr s)\n{\n    _c4dbgpf(\"filtering squo scalar: s=[{}]~~~{}~~~\", s.len, s);\n    FilterResult r = this->filter_scalar_squoted_in_place(s, s.len);\n    _RYML_CB_ASSERT(this->callbacks(), r.valid());\n    _c4dbgpf(\"filtering squo scalar: success! s=[{}]~~~{}~~~\", r.get().len, r.get());\n    return r.get();\n}\n\n\n//-----------------------------------------------------------------------------\n\ntemplate<class EventHandler>\ncsubstr ParseEngine<EventHandler>::_filter_scalar_dquot(substr s)\n{\n    _c4dbgpf(\"filtering dquo scalar: s=[{}]~~~{}~~~\", s.len, s);\n    FilterResultExtending r = this->filter_scalar_dquoted_in_place(s, s.len);\n    if(C4_LIKELY(r.valid()))\n    {\n        _c4dbgpf(\"filtering dquo scalar: success! s=[{}]~~~{}~~~\", r.get().len, r.get());\n        return r.get();\n    }\n    else\n    {\n        const size_t len = r.required_len();\n        _c4dbgpf(\"filtering dquo scalar: not enough space: needs {}, have {}\", len, s.len);\n        substr dst = m_evt_handler->alloc_arena(len, &s);\n        _c4dbgpf(\"filtering dquo scalar: dst.len={}\", dst.len);\n        _RYML_CB_ASSERT(this->callbacks(), dst.len == len);\n        FilterResult rsd = this->filter_scalar_dquoted(s, dst);\n        _c4dbgpf(\"filtering dquo scalar: ... result now needs {} was {}\", rsd.required_len(), len);\n        _RYML_CB_ASSERT(this->callbacks(), rsd.required_len() <= len); // may be smaller!\n        _RYML_CB_CHECK(m_evt_handler->m_stack.m_callbacks, rsd.valid());\n        _c4dbgpf(\"filtering dquo scalar: success! s=[{}]~~~{}~~~\", rsd.get().len, rsd.get());\n        return rsd.get();\n    }\n}\n\n\n//-----------------------------------------------------------------------------\ntemplate<class EventHandler>\ncsubstr ParseEngine<EventHandler>::_filter_scalar_literal(substr s, size_t indentation, BlockChomp_e chomp)\n{\n    _c4dbgpf(\"filtering block literal scalar: s=[{}]~~~{}~~~\", s.len, s);\n    FilterResult r = this->filter_scalar_block_literal_in_place(s, s.len, indentation, chomp);\n    if(C4_LIKELY(r.valid()))\n    {\n        _c4dbgpf(\"filtering block literal scalar: success! s=[{}]~~~{}~~~\", r.get().len, r.get());\n        return r.get();\n    }\n    else\n    {\n        _c4dbgpf(\"filtering block literal scalar: not enough space: needs {}, have {}\", r.required_len(), s.len);\n        substr dst = m_evt_handler->alloc_arena(r.required_len(), &s);\n        FilterResult rsd = this->filter_scalar_block_literal(s, dst, indentation, chomp);\n        _RYML_CB_CHECK(m_evt_handler->m_stack.m_callbacks, rsd.valid());\n        _c4dbgpf(\"filtering block literal scalar: success! s=[{}]~~~{}~~~\", rsd.get().len, rsd.get());\n        return rsd.get();\n    }\n}\n\n\n//-----------------------------------------------------------------------------\ntemplate<class EventHandler>\ncsubstr ParseEngine<EventHandler>::_filter_scalar_folded(substr s, size_t indentation, BlockChomp_e chomp)\n{\n    _c4dbgpf(\"filtering block folded scalar: s=[{}]~~~{}~~~\", s.len, s);\n    FilterResult r = this->filter_scalar_block_folded_in_place(s, s.len, indentation, chomp);\n    if(C4_LIKELY(r.valid()))\n    {\n        _c4dbgpf(\"filtering block folded scalar: success! s=[{}]~~~{}~~~\", r.get().len, r.get());\n        return r.get();\n    }\n    else\n    {\n        _c4dbgpf(\"filtering block folded scalar: not enough space: needs {}, have {}\", r.required_len(), s.len);\n        substr dst = m_evt_handler->alloc_arena(r.required_len(), &s);\n        FilterResult rsd = this->filter_scalar_block_folded(s, dst, indentation, chomp);\n        _RYML_CB_CHECK(m_evt_handler->m_stack.m_callbacks, rsd.valid());\n        _c4dbgpf(\"filtering block folded scalar: success! s=[{}]~~~{}~~~\", rsd.get().len, rsd.get());\n        return rsd.get();\n    }\n}\n\n\n//-----------------------------------------------------------------------------\n\ntemplate<class EventHandler>\ncsubstr ParseEngine<EventHandler>::_maybe_filter_key_scalar_plain(ScannedScalar const& C4_RESTRICT sc, size_t indentation)\n{\n    if(sc.needs_filter)\n    {\n        if(m_options.scalar_filtering())\n        {\n            return _filter_scalar_plain(sc.scalar, indentation);\n        }\n        else\n        {\n            _c4dbgp(\"plain scalar left unfiltered\");\n            m_evt_handler->mark_key_scalar_unfiltered();\n        }\n    }\n    else\n    {\n        _c4dbgp(\"plain scalar doesn't need filtering\");\n    }\n    return sc.scalar;\n}\n\ntemplate<class EventHandler>\ncsubstr ParseEngine<EventHandler>::_maybe_filter_val_scalar_plain(ScannedScalar const& C4_RESTRICT sc, size_t indentation)\n{\n    if(sc.needs_filter)\n    {\n        if(m_options.scalar_filtering())\n        {\n            return _filter_scalar_plain(sc.scalar, indentation);\n        }\n        else\n        {\n            _c4dbgp(\"plain scalar left unfiltered\");\n            m_evt_handler->mark_val_scalar_unfiltered();\n        }\n    }\n    else\n    {\n        _c4dbgp(\"plain scalar doesn't need filtering\");\n    }\n    return sc.scalar;\n}\n\n\n//-----------------------------------------------------------------------------\n\ntemplate<class EventHandler>\ncsubstr ParseEngine<EventHandler>::_maybe_filter_key_scalar_squot(ScannedScalar const& C4_RESTRICT sc)\n{\n    if(sc.needs_filter)\n    {\n        if(m_options.scalar_filtering())\n        {\n            return _filter_scalar_squot(sc.scalar);\n        }\n        else\n        {\n            _c4dbgp(\"squo key scalar left unfiltered\");\n            m_evt_handler->mark_key_scalar_unfiltered();\n        }\n    }\n    else\n    {\n        _c4dbgp(\"squo key scalar doesn't need filtering\");\n    }\n    return sc.scalar;\n}\n\ntemplate<class EventHandler>\ncsubstr ParseEngine<EventHandler>::_maybe_filter_val_scalar_squot(ScannedScalar const& C4_RESTRICT sc)\n{\n    if(sc.needs_filter)\n    {\n        if(m_options.scalar_filtering())\n        {\n            return _filter_scalar_squot(sc.scalar);\n        }\n        else\n        {\n            _c4dbgp(\"squo val scalar left unfiltered\");\n            m_evt_handler->mark_val_scalar_unfiltered();\n        }\n    }\n    else\n    {\n        _c4dbgp(\"squo val scalar doesn't need filtering\");\n    }\n    return sc.scalar;\n}\n\n\n//-----------------------------------------------------------------------------\n\ntemplate<class EventHandler>\ncsubstr ParseEngine<EventHandler>::_maybe_filter_key_scalar_dquot(ScannedScalar const& C4_RESTRICT sc)\n{\n    if(sc.needs_filter)\n    {\n        if(m_options.scalar_filtering())\n        {\n            return _filter_scalar_dquot(sc.scalar);\n        }\n        else\n        {\n            _c4dbgp(\"dquo scalar left unfiltered\");\n            m_evt_handler->mark_key_scalar_unfiltered();\n        }\n    }\n    else\n    {\n        _c4dbgp(\"dquo scalar doesn't need filtering\");\n    }\n    return sc.scalar;\n}\n\ntemplate<class EventHandler>\ncsubstr ParseEngine<EventHandler>::_maybe_filter_val_scalar_dquot(ScannedScalar const& C4_RESTRICT sc)\n{\n    if(sc.needs_filter)\n    {\n        if(m_options.scalar_filtering())\n        {\n            return _filter_scalar_dquot(sc.scalar);\n        }\n        else\n        {\n            _c4dbgp(\"dquo scalar left unfiltered\");\n            m_evt_handler->mark_val_scalar_unfiltered();\n        }\n    }\n    else\n    {\n        _c4dbgp(\"dquo scalar doesn't need filtering\");\n    }\n    return sc.scalar;\n}\n\n\n//-----------------------------------------------------------------------------\n\ntemplate<class EventHandler>\ncsubstr ParseEngine<EventHandler>::_maybe_filter_key_scalar_literal(ScannedBlock const& C4_RESTRICT sb)\n{\n    if(m_options.scalar_filtering())\n    {\n        return _filter_scalar_literal(sb.scalar, sb.indentation, sb.chomp);\n    }\n    else\n    {\n        _c4dbgp(\"literal scalar left unfiltered\");\n        m_evt_handler->mark_key_scalar_unfiltered();\n    }\n    return sb.scalar;\n}\n\ntemplate<class EventHandler>\ncsubstr ParseEngine<EventHandler>::_maybe_filter_val_scalar_literal(ScannedBlock const& C4_RESTRICT sb)\n{\n    if(m_options.scalar_filtering())\n    {\n        return _filter_scalar_literal(sb.scalar, sb.indentation, sb.chomp);\n    }\n    else\n    {\n        _c4dbgp(\"literal scalar left unfiltered\");\n        m_evt_handler->mark_val_scalar_unfiltered();\n    }\n    return sb.scalar;\n}\n\n\n//-----------------------------------------------------------------------------\n\ntemplate<class EventHandler>\ncsubstr ParseEngine<EventHandler>::_maybe_filter_key_scalar_folded(ScannedBlock const& C4_RESTRICT sb)\n{\n    if(m_options.scalar_filtering())\n    {\n        return _filter_scalar_folded(sb.scalar, sb.indentation, sb.chomp);\n    }\n    else\n    {\n        _c4dbgp(\"folded scalar left unfiltered\");\n        m_evt_handler->mark_key_scalar_unfiltered();\n    }\n    return sb.scalar;\n}\n\ntemplate<class EventHandler>\ncsubstr ParseEngine<EventHandler>::_maybe_filter_val_scalar_folded(ScannedBlock const& C4_RESTRICT sb)\n{\n    if(m_options.scalar_filtering())\n    {\n        return _filter_scalar_folded(sb.scalar, sb.indentation, sb.chomp);\n    }\n    else\n    {\n        _c4dbgp(\"folded scalar left unfiltered\");\n        m_evt_handler->mark_val_scalar_unfiltered();\n    }\n    return sb.scalar;\n}\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n#ifdef RYML_DBG  //   !!! <----------------------------------\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::add_flags(ParserFlag_t on, ParserState * s)\n{\n    char buf1_[64], buf2_[64], buf3_[64];\n    csubstr buf1 = detail::_parser_flags_to_str(buf1_, on);\n    csubstr buf2 = detail::_parser_flags_to_str(buf2_, s->flags);\n    csubstr buf3 = detail::_parser_flags_to_str(buf3_, s->flags|on);\n    _c4dbgpf(\"state[{}]: add {}: before={} after={}\", s->level, buf1, buf2, buf3);\n    s->flags |= on;\n}\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::addrem_flags(ParserFlag_t on, ParserFlag_t off, ParserState * s)\n{\n    char buf1_[64], buf2_[64], buf3_[64], buf4_[64];\n    csubstr buf1 = detail::_parser_flags_to_str(buf1_, on);\n    csubstr buf2 = detail::_parser_flags_to_str(buf2_, off);\n    csubstr buf3 = detail::_parser_flags_to_str(buf3_, s->flags);\n    csubstr buf4 = detail::_parser_flags_to_str(buf4_, ((s->flags|on)&(~off)));\n    _c4dbgpf(\"state[{}]: add {} / rem {}: before={} after={}\", s->level, buf1, buf2, buf3, buf4);\n    s->flags |= on;\n    s->flags &= ~off;\n}\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::rem_flags(ParserFlag_t off, ParserState * s)\n{\n    char buf1_[64], buf2_[64], buf3_[64];\n    csubstr buf1 = detail::_parser_flags_to_str(buf1_, off);\n    csubstr buf2 = detail::_parser_flags_to_str(buf2_, s->flags);\n    csubstr buf3 = detail::_parser_flags_to_str(buf3_, s->flags&(~off));\n    _c4dbgpf(\"state[{}]: rem {}: before={} after={}\", s->level, buf1, buf2, buf3);\n    s->flags &= ~off;\n}\n\ninline C4_NO_INLINE csubstr detail::_parser_flags_to_str(substr buf, ParserFlag_t flags)\n{\n    size_t pos = 0;\n    bool gotone = false;\n\n    #define _prflag(fl)                                     \\\n    if((flags & fl) == (fl))                                \\\n    {                                                       \\\n        if(gotone)                                          \\\n        {                                                   \\\n            if(pos + 1 < buf.len)                           \\\n                buf[pos] = '|';                             \\\n            ++pos;                                          \\\n        }                                                   \\\n        csubstr fltxt = #fl;                                \\\n        if(pos + fltxt.len <= buf.len)                      \\\n            memcpy(buf.str + pos, fltxt.str, fltxt.len);    \\\n        pos += fltxt.len;                                   \\\n        gotone = true;                                      \\\n    }\n\n    _prflag(RTOP);\n    _prflag(RUNK);\n    _prflag(RMAP);\n    _prflag(RSEQ);\n    _prflag(FLOW);\n    _prflag(BLCK);\n    _prflag(QMRK);\n    _prflag(RKEY);\n    _prflag(RVAL);\n    _prflag(RKCL);\n    _prflag(RNXT);\n    _prflag(SSCL);\n    _prflag(QSCL);\n    _prflag(RSET);\n    _prflag(RDOC);\n    _prflag(NDOC);\n    _prflag(USTY);\n    _prflag(RSEQIMAP);\n\n    #undef _prflag\n\n    if(pos == 0)\n        if(buf.len > 0)\n            buf[pos++] = '0';\n\n    RYML_CHECK(pos <= buf.len);\n\n    return buf.first(pos);\n}\n\n#endif // RYML_DBG   !!! <----------------------------------\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\ntemplate<class EventHandler>\ncsubstr ParseEngine<EventHandler>::location_contents(Location const& loc) const\n{\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, loc.offset < m_buf.len);\n    return m_buf.sub(loc.offset);\n}\n\ntemplate<class EventHandler>\nLocation ParseEngine<EventHandler>::location(ConstNodeRef node) const\n{\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, node.readable());\n    return location(*node.tree(), node.id());\n}\n\ntemplate<class EventHandler>\nLocation ParseEngine<EventHandler>::location(Tree const& tree, id_type node) const\n{\n    // try hard to avoid getting the location from a null string.\n    Location loc;\n    if(_location_from_node(tree, node, &loc, 0))\n        return loc;\n    return val_location(m_buf.str);\n}\n\ntemplate<class EventHandler>\nbool ParseEngine<EventHandler>::_location_from_node(Tree const& tree, id_type node, Location *C4_RESTRICT loc, id_type level) const\n{\n    if(tree.has_key(node))\n    {\n        csubstr k = tree.key(node);\n        if(C4_LIKELY(k.str != nullptr))\n        {\n            _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, k.is_sub(m_buf));\n            _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, m_buf.is_super(k));\n            *loc = val_location(k.str);\n            return true;\n        }\n    }\n\n    if(tree.has_val(node))\n    {\n        csubstr v = tree.val(node);\n        if(C4_LIKELY(v.str != nullptr))\n        {\n            _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, v.is_sub(m_buf));\n            _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, m_buf.is_super(v));\n            *loc = val_location(v.str);\n            return true;\n        }\n    }\n\n    if(tree.is_container(node))\n    {\n        if(_location_from_cont(tree, node, loc))\n            return true;\n    }\n\n    if(tree.type(node) != NOTYPE && level == 0)\n    {\n        // try the prev sibling\n        {\n            const id_type prev = tree.prev_sibling(node);\n            if(prev != NONE)\n            {\n                if(_location_from_node(tree, prev, loc, level+1))\n                    return true;\n            }\n        }\n        // try the next sibling\n        {\n            const id_type next = tree.next_sibling(node);\n            if(next != NONE)\n            {\n                if(_location_from_node(tree, next, loc, level+1))\n                    return true;\n            }\n        }\n        // try the parent\n        {\n            const id_type parent = tree.parent(node);\n            if(parent != NONE)\n            {\n                if(_location_from_node(tree, parent, loc, level+1))\n                    return true;\n            }\n        }\n    }\n\n    return false;\n}\n\ntemplate<class EventHandler>\nbool ParseEngine<EventHandler>::_location_from_cont(Tree const& tree, id_type node, Location *C4_RESTRICT loc) const\n{\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, tree.is_container(node));\n    if(!tree.is_stream(node))\n    {\n        const char *node_start = tree._p(node)->m_val.scalar.str;  // this was stored in the container\n        if(tree.has_children(node))\n        {\n            id_type child = tree.first_child(node);\n            if(tree.has_key(child))\n            {\n                // when a map starts, the container was set after the key\n                csubstr k = tree.key(child);\n                if(k.str && node_start > k.str)\n                    node_start = k.str;\n            }\n        }\n        *loc = val_location(node_start);\n        return true;\n    }\n    else // it's a stream\n    {\n        *loc = val_location(m_buf.str); // just return the front of the buffer\n    }\n    return true;\n}\n\n\ntemplate<class EventHandler>\nLocation ParseEngine<EventHandler>::val_location(const char *val) const\n{\n    if(C4_UNLIKELY(val == nullptr))\n        return {m_file, 0, 0, 0};\n    _RYML_CB_CHECK(m_evt_handler->m_stack.m_callbacks, m_options.locations());\n    // NOTE: if any of these checks fails, the parser needs to be\n    // instantiated with locations enabled.\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, m_buf.str == m_newline_offsets_buf.str);\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, m_buf.len == m_newline_offsets_buf.len);\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, m_options.locations());\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, !_locations_dirty());\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, m_newline_offsets != nullptr);\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, m_newline_offsets_size > 0);\n    // NOTE: the pointer needs to belong to the buffer that was used to parse.\n    csubstr src = m_buf;\n    _RYML_CB_CHECK(m_evt_handler->m_stack.m_callbacks, val != nullptr || src.str == nullptr);\n    _RYML_CB_CHECK(m_evt_handler->m_stack.m_callbacks, (val >= src.begin() && val <= src.end()) || (src.str == nullptr && val == nullptr));\n    // ok. search the first stored newline after the given ptr\n    using lineptr_type = size_t const* C4_RESTRICT;\n    lineptr_type lineptr = nullptr;\n    size_t offset = (size_t)(val - src.begin());\n    if(m_newline_offsets_size < RYML_LOCATIONS_SMALL_THRESHOLD)\n    {\n        // just do a linear search if the size is small.\n        for(lineptr_type curr = m_newline_offsets, last = m_newline_offsets + m_newline_offsets_size; curr < last; ++curr)\n        {\n            if(*curr > offset)\n            {\n                lineptr = curr;\n                break;\n            }\n        }\n    }\n    else\n    {\n        // do a bisection search if the size is not small.\n        //\n        // We could use std::lower_bound but this is simple enough and\n        // spares the costly include of <algorithm>.\n        size_t count = m_newline_offsets_size;\n        size_t step;\n        lineptr_type it;\n        lineptr = m_newline_offsets;\n        while(count)\n        {\n            step = count >> 1;\n            it = lineptr + step;\n            if(*it < offset)\n            {\n                lineptr = ++it;\n                count -= step + 1;\n            }\n            else\n            {\n                count = step;\n            }\n        }\n    }\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, lineptr >= m_newline_offsets);\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, lineptr <= m_newline_offsets + m_newline_offsets_size);\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, *lineptr > offset);\n    Location loc;\n    loc.name = m_file;\n    loc.offset = offset;\n    loc.line = (size_t)(lineptr - m_newline_offsets);\n    if(lineptr > m_newline_offsets)\n        loc.col = (offset - *(lineptr-1) - 1u);\n    else\n        loc.col = offset;\n    return loc;\n}\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_prepare_locations()\n{\n    m_newline_offsets_buf = m_buf;\n    size_t numnewlines = 1u + m_buf.count('\\n');\n    _resize_locations(numnewlines);\n    m_newline_offsets_size = 0;\n    for(size_t i = 0; i < m_buf.len; i++)\n        if(m_buf[i] == '\\n')\n            m_newline_offsets[m_newline_offsets_size++] = i;\n    m_newline_offsets[m_newline_offsets_size++] = m_buf.len;\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, m_newline_offsets_size == numnewlines);\n}\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_resize_locations(size_t numnewlines)\n{\n    if(numnewlines > m_newline_offsets_capacity)\n    {\n        if(m_newline_offsets)\n            _RYML_CB_FREE(m_evt_handler->m_stack.m_callbacks, m_newline_offsets, size_t, m_newline_offsets_capacity);\n        m_newline_offsets = _RYML_CB_ALLOC_HINT(m_evt_handler->m_stack.m_callbacks, size_t, numnewlines, m_newline_offsets);\n        m_newline_offsets_capacity = numnewlines;\n    }\n}\n\ntemplate<class EventHandler>\nbool ParseEngine<EventHandler>::_locations_dirty() const\n{\n    return !m_newline_offsets_size;\n}\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_handle_flow_skip_whitespace()\n{\n    if(m_evt_handler->m_curr->line_contents.rem.len > 0)\n    {\n        csubstr rem = m_evt_handler->m_curr->line_contents.rem;\n        if(rem.str[0] == ' ' || rem.str[0] == '\\t')\n        {\n            _c4dbgpf(\"starts with whitespace: '{}'\", _c4prc(rem.str[0]));\n            _skipchars(\" \\t\");\n            rem = m_evt_handler->m_curr->line_contents.rem;\n        }\n        // comments\n        if(rem.begins_with('#'))\n        {\n            _c4dbgpf(\"it's a comment: {}\", m_evt_handler->m_curr->line_contents.rem);\n            _line_progressed(m_evt_handler->m_curr->line_contents.rem.len);\n        }\n    }\n}\n\n\n//-----------------------------------------------------------------------------\n\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_add_annotation(Annotation *C4_RESTRICT dst, csubstr str, size_t indentation, size_t line)\n{\n    _c4dbgpf(\"store annotation[{}]: '{}' indentation={} line={}\", dst->num_entries, str, indentation, line);\n    if(C4_UNLIKELY(dst->num_entries >= C4_COUNTOF(dst->annotations)))\n        _c4err(\"too many annotations\");\n    dst->annotations[dst->num_entries].str = str;\n    dst->annotations[dst->num_entries].indentation = indentation;\n    dst->annotations[dst->num_entries].line = line;\n    ++dst->num_entries;\n}\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_clear_annotations(Annotation *C4_RESTRICT dst)\n{\n    dst->num_entries = 0;\n}\n\n#ifdef RYML_NO_COVERAGE__TO_BE_DELETED\ntemplate<class EventHandler>\nbool ParseEngine<EventHandler>::_handle_indentation_from_annotations()\n{\n    if(m_pending_anchors.num_entries == 1u || m_pending_tags.num_entries == 1u)\n    {\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, m_pending_anchors.num_entries < 2u && m_pending_tags.num_entries < 2u);\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, m_pending_anchors.annotations[0].line < m_evt_handler->m_curr->pos.line);\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, m_pending_tags.annotations[1].line < m_evt_handler->m_curr->pos.line);\n        size_t to_skip = m_evt_handler->m_curr->indref;\n        if(m_pending_anchors.num_entries)\n            to_skip = m_pending_anchors.annotations[0].indentation > to_skip ? m_pending_anchors.annotations[0].indentation : to_skip;\n        if(m_pending_tags.num_entries)\n            to_skip = m_pending_tags.annotations[0].indentation > to_skip ? m_pending_tags.annotations[0].indentation : to_skip;\n        _c4dbgpf(\"annotations pending, skip indentation up to {}!\", to_skip);\n        _maybe_skipchars_up_to(' ', to_skip);\n        return true;\n    }\n    return false;\n}\n#endif\n\ntemplate<class EventHandler>\nbool ParseEngine<EventHandler>::_annotations_require_key_container() const\n{\n    return m_pending_tags.num_entries > 1 || m_pending_anchors.num_entries > 1;\n}\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_check_tag(csubstr tag)\n{\n    if(!tag.begins_with(\"!<\"))\n    {\n        if(C4_UNLIKELY(tag.first_of(\"[]{},\") != npos))\n            _RYML_CB_ERR_(m_evt_handler->m_stack.m_callbacks, \"tags must not contain any of '[]{},'\", m_evt_handler->m_curr->pos);\n    }\n    else\n    {\n        if(C4_UNLIKELY(!tag.ends_with('>')))\n            _RYML_CB_ERR_(m_evt_handler->m_stack.m_callbacks, \"malformed tag\", m_evt_handler->m_curr->pos);\n    }\n}\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_handle_annotations_before_blck_key_scalar()\n{\n    _c4dbgpf(\"annotations_before_blck_key_scalar, node={}\", m_evt_handler->m_curr->node_id);\n    if(m_pending_tags.num_entries)\n    {\n        _c4dbgpf(\"annotations_before_blck_key_scalar, #tags={}\", m_pending_tags.num_entries);\n        if(C4_LIKELY(m_pending_tags.num_entries == 1))\n        {\n            _check_tag(m_pending_tags.annotations[0].str);\n            m_evt_handler->set_key_tag(m_pending_tags.annotations[0].str);\n            _clear_annotations(&m_pending_tags);\n        }\n        else\n        {\n            _c4err(\"too many tags\");\n        }\n    }\n    if(m_pending_anchors.num_entries)\n    {\n        _c4dbgpf(\"annotations_before_blck_key_scalar, #anchors={}\", m_pending_anchors.num_entries);\n        if(C4_LIKELY(m_pending_anchors.num_entries == 1))\n        {\n            m_evt_handler->set_key_anchor(m_pending_anchors.annotations[0].str);\n            _clear_annotations(&m_pending_anchors);\n        }\n        else\n        {\n            _c4err(\"too many anchors\");\n        }\n    }\n}\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_handle_annotations_before_blck_val_scalar()\n{\n    _c4dbgpf(\"annotations_before_blck_val_scalar, node={}\", m_evt_handler->m_curr->node_id);\n    if(m_pending_tags.num_entries)\n    {\n        _c4dbgpf(\"annotations_before_blck_val_scalar, #tags={}\", m_pending_tags.num_entries);\n        if(C4_LIKELY(m_pending_tags.num_entries == 1))\n        {\n            _check_tag(m_pending_tags.annotations[0].str);\n            m_evt_handler->set_val_tag(m_pending_tags.annotations[0].str);\n            _clear_annotations(&m_pending_tags);\n        }\n        else\n        {\n            _c4err(\"too many tags\");\n        }\n    }\n    if(m_pending_anchors.num_entries)\n    {\n        _c4dbgpf(\"annotations_before_blck_val_scalar, #anchors={}\", m_pending_anchors.num_entries);\n        if(C4_LIKELY(m_pending_anchors.num_entries == 1))\n        {\n            m_evt_handler->set_val_anchor(m_pending_anchors.annotations[0].str);\n            _clear_annotations(&m_pending_anchors);\n        }\n        else\n        {\n            _c4err(\"too many anchors\");\n        }\n    }\n}\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_handle_annotations_before_start_mapblck(size_t current_line)\n{\n    _c4dbgpf(\"annotations_before_start_mapblck, current_line={}\", current_line);\n    if(m_pending_tags.num_entries == 2)\n    {\n        _c4dbgp(\"2 tags, setting entry 0\");\n        _check_tag(m_pending_tags.annotations[0].str);\n        m_evt_handler->set_val_tag(m_pending_tags.annotations[0].str);\n    }\n    else if(m_pending_tags.num_entries == 1)\n    {\n        _c4dbgpf(\"1 tag. line={}, curr={}\", m_pending_tags.annotations[0].line);\n        if(m_pending_tags.annotations[0].line < current_line)\n        {\n            _c4dbgp(\"...tag is for the map. setting it.\");\n            _check_tag(m_pending_tags.annotations[0].str);\n            m_evt_handler->set_val_tag(m_pending_tags.annotations[0].str);\n            _clear_annotations(&m_pending_tags);\n        }\n    }\n    //\n    if(m_pending_anchors.num_entries == 2)\n    {\n        _c4dbgp(\"2 anchors, setting entry 0\");\n        m_evt_handler->set_val_anchor(m_pending_anchors.annotations[0].str);\n    }\n    else if(m_pending_anchors.num_entries == 1)\n    {\n        _c4dbgpf(\"1 anchor. line={}, curr={}\", m_pending_anchors.annotations[0].line);\n        if(m_pending_anchors.annotations[0].line < current_line)\n        {\n            _c4dbgp(\"...anchor is for the map. setting it.\");\n            m_evt_handler->set_val_anchor(m_pending_anchors.annotations[0].str);\n            _clear_annotations(&m_pending_anchors);\n        }\n    }\n}\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_handle_annotations_before_start_mapblck_as_key()\n{\n    _c4dbgp(\"annotations_before_start_mapblck_as_key\");\n    if(m_pending_tags.num_entries == 2)\n    {\n        _check_tag(m_pending_tags.annotations[0].str);\n        m_evt_handler->set_key_tag(m_pending_tags.annotations[0].str);\n    }\n    if(m_pending_anchors.num_entries == 2)\n    {\n        m_evt_handler->set_key_anchor(m_pending_anchors.annotations[0].str);\n    }\n}\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_handle_annotations_and_indentation_after_start_mapblck(size_t key_indentation, size_t key_line)\n{\n    _c4dbgp(\"annotations_after_start_mapblck\");\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, m_pending_tags.num_entries <= 2);\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, m_pending_anchors.num_entries <= 2);\n    if(m_pending_anchors.num_entries || m_pending_tags.num_entries)\n    {\n        key_indentation = _select_indentation_from_annotations(key_indentation, key_line);\n        switch(m_pending_tags.num_entries)\n        {\n        case 1u:\n            _check_tag(m_pending_tags.annotations[0].str);\n            m_evt_handler->set_key_tag(m_pending_tags.annotations[0].str);\n            _clear_annotations(&m_pending_tags);\n            break;\n        case 2u:\n            _check_tag(m_pending_tags.annotations[1].str);\n            m_evt_handler->set_key_tag(m_pending_tags.annotations[1].str);\n            _clear_annotations(&m_pending_tags);\n            break;\n        }\n        switch(m_pending_anchors.num_entries)\n        {\n        case 1u:\n            m_evt_handler->set_key_anchor(m_pending_anchors.annotations[0].str);\n            _clear_annotations(&m_pending_anchors);\n            break;\n        case 2u:\n            m_evt_handler->set_key_anchor(m_pending_anchors.annotations[1].str);\n            _clear_annotations(&m_pending_anchors);\n            break;\n        }\n    }\n    _set_indentation(key_indentation);\n}\n\ntemplate<class EventHandler>\nsize_t ParseEngine<EventHandler>::_select_indentation_from_annotations(size_t val_indentation, size_t val_line)\n{\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, m_pending_tags.num_entries || m_pending_anchors.num_entries);\n    // select the left-most annotation on the max line\n    auto const *C4_RESTRICT curr = m_pending_anchors.num_entries ? &m_pending_anchors.annotations[0] : &m_pending_tags.annotations[0];\n    for(size_t i = 0; i < m_pending_anchors.num_entries; ++i)\n    {\n        auto const& C4_RESTRICT ann = m_pending_anchors.annotations[i];\n        if(ann.line > curr->line)\n            curr = &ann;\n        else if(ann.indentation < curr->indentation)\n            curr = &ann;\n    }\n    for(size_t j = 0; j < m_pending_tags.num_entries; ++j)\n    {\n        auto const& C4_RESTRICT ann = m_pending_tags.annotations[j];\n        if(ann.line > curr->line)\n            curr = &ann;\n        else if(ann.indentation < curr->indentation)\n            curr = &ann;\n    }\n    return curr->line < val_line ? val_indentation : curr->indentation;\n}\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_handle_directive(csubstr rem)\n{\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, rem.is_sub(m_evt_handler->m_curr->line_contents.rem));\n    const size_t pos = rem.find('#');\n    _c4dbgpf(\"handle_directive: pos={} rem={}\", pos, rem);\n    if(pos == npos) // no comments\n    {\n        m_evt_handler->add_directive(rem);\n        _line_progressed(rem.len);\n    }\n    else\n    {\n        csubstr to_comment = rem.first(pos);\n        csubstr trimmed = to_comment.trimr(\" \\t\");\n        m_evt_handler->add_directive(trimmed);\n        _line_progressed(pos);\n        _skip_comment();\n    }\n}\n\n\n//-----------------------------------------------------------------------------\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_handle_seq_json()\n{\nseqjson_start:\n    _c4dbgpf(\"handle2_seq_json: node_id={} level={} indentation={}\", m_evt_handler->m_curr->node_id, m_evt_handler->m_curr->level, m_evt_handler->m_curr->indref);\n\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RKEY));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_all(RSEQ));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_all(FLOW));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_any(RVAL|RNXT));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_all(RVAL) != has_all(RNXT));\n\n    _handle_flow_skip_whitespace();\n    csubstr rem = m_evt_handler->m_curr->line_contents.rem;\n    if(!rem.len)\n        goto seqjson_again;\n\n    if(has_any(RVAL))\n    {\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RNXT));\n        const char first = rem.str[0];\n        _c4dbgpf(\"mapjson[RVAL]: '{}'\", first);\n        switch(first)\n        {\n        case '\"':\n        {\n            _c4dbgp(\"seqjson[RVAL]: scanning double-quoted scalar\");\n            ScannedScalar sc = _scan_scalar_dquot();\n            csubstr maybe_filtered = _maybe_filter_val_scalar_dquot(sc);\n            m_evt_handler->set_val_scalar_dquoted(maybe_filtered);\n            addrem_flags(RNXT, RVAL);\n            break;\n        }\n        case '[':\n        {\n            _c4dbgp(\"seqjson[RVAL]: start child seqjson\");\n            addrem_flags(RNXT, RVAL);\n            m_evt_handler->begin_seq_val_flow();\n            addrem_flags(RVAL, RNXT);\n            _line_progressed(1);\n            break;\n        }\n        case '{':\n        {\n            _c4dbgp(\"seqjson[RVAL]: start child mapjson\");\n            addrem_flags(RNXT, RVAL);\n            m_evt_handler->begin_map_val_flow();\n            addrem_flags(RMAP|RKEY, RSEQ|RVAL|RNXT);\n            _line_progressed(1);\n            goto seqjson_finish;\n        }\n        case ']': // this happens on a trailing comma like \", ]\"\n        {\n            _c4dbgp(\"seqjson[RVAL]: end!\");\n            rem_flags(RSEQ);\n            m_evt_handler->end_seq();\n            _line_progressed(1);\n            if(!has_all(RSEQ|FLOW))\n                goto seqjson_finish;\n            break;\n        }\n        default:\n        {\n            ScannedScalar sc;\n            if(_scan_scalar_seq_json(&sc))\n            {\n                _c4dbgp(\"seqjson[RVAL]: it's a plain scalar.\");\n                csubstr maybe_filtered = _maybe_filter_val_scalar_plain(sc, m_evt_handler->m_curr->indref);\n                m_evt_handler->set_val_scalar_plain(maybe_filtered);\n                addrem_flags(RNXT, RVAL);\n            }\n            else\n            {\n                _c4err(\"parse error\");\n            }\n        }\n        }\n    }\n    else // RNXT\n    {\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_any(RNXT));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RVAL));\n        const char first = rem.str[0];\n        _c4dbgpf(\"mapjson[RNXT]: '{}'\", first);\n        switch(first)\n        {\n        case ',':\n        {\n            _c4dbgp(\"seqjson[RNXT]: expect next val\");\n            addrem_flags(RVAL, RNXT);\n            m_evt_handler->add_sibling();\n            _line_progressed(1);\n            break;\n        }\n        case ']':\n        {\n            _c4dbgp(\"seqjson[RNXT]: end!\");\n            m_evt_handler->end_seq();\n            _line_progressed(1);\n            goto seqjson_finish;\n        }\n        default:\n            _c4err(\"parse error\");\n        }\n    }\n\n seqjson_again:\n    _c4dbgt(\"seqjson: go again\", 0);\n    if(_finished_line())\n    {\n        if(C4_LIKELY(!_finished_file()))\n        {\n            _line_ended();\n            _scan_line();\n            _c4dbgnextline();\n        }\n        else\n        {\n            _c4err(\"missing terminating ]\");\n        }\n    }\n    goto seqjson_start;\n\n seqjson_finish:\n    _c4dbgp(\"seqjson: finish\");\n}\n\n\n//-----------------------------------------------------------------------------\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_handle_map_json()\n{\nmapjson_start:\n    _c4dbgpf(\"handle2_map_json: node_id={} level={} indentation={}\", m_evt_handler->m_curr->node_id, m_evt_handler->m_curr->level, m_evt_handler->m_curr->indref);\n\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_all(RMAP));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_all(FLOW));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(QMRK));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_any(RKEY|RKCL|RVAL|RNXT));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, 1 == (has_any(RKEY) + has_any(RKCL) + has_any(RVAL) + has_any(RNXT)));\n\n    _handle_flow_skip_whitespace();\n    csubstr rem = m_evt_handler->m_curr->line_contents.rem;\n    if(!rem.len)\n        goto mapjson_again;\n\n    if(has_any(RKEY))\n    {\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RKCL));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RVAL));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RNXT));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(QMRK));\n        const char first = rem.str[0];\n        _c4dbgpf(\"mapjson[RKEY]: '{}'\", first);\n        switch(first)\n        {\n        case '\"':\n        {\n            _c4dbgp(\"mapjson[RKEY]: scanning double-quoted scalar\");\n            ScannedScalar sc = _scan_scalar_dquot();\n            csubstr maybe_filtered = _maybe_filter_key_scalar_dquot(sc);\n            m_evt_handler->set_key_scalar_dquoted(maybe_filtered);\n            addrem_flags(RKCL, RKEY);\n            break;\n        }\n        case '}': // this happens on a trailing comma like \", }\"\n        {\n            _c4dbgp(\"mapjson[RKEY]: end!\");\n            m_evt_handler->end_map();\n            _line_progressed(1);\n            goto mapjson_finish;\n        }\n        default:\n            _c4err(\"parse error\");\n        }\n    }\n    else if(has_any(RVAL))\n    {\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RKEY));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RKCL));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RNXT));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(QMRK));\n        const char first = rem.str[0];\n        _c4dbgpf(\"mapjson[RVAL]: '{}'\", first);\n        switch(first)\n        {\n        case '\"':\n        {\n            _c4dbgp(\"mapjson[RVAL]: scanning double-quoted scalar\");\n            ScannedScalar sc = _scan_scalar_dquot();\n            csubstr maybe_filtered = _maybe_filter_val_scalar_dquot(sc);\n            m_evt_handler->set_val_scalar_dquoted(maybe_filtered);\n            addrem_flags(RNXT, RVAL);\n            break;\n        }\n        case '[':\n        {\n            _c4dbgp(\"mapjson[RVAL]: start val seqjson\");\n            addrem_flags(RNXT, RVAL);\n            m_evt_handler->begin_seq_val_flow();\n            _set_indentation(m_evt_handler->m_parent->indref);\n            addrem_flags(RSEQ|RVAL, RMAP|RNXT);\n            _line_progressed(1);\n            goto mapjson_finish;\n        }\n        case '{':\n        {\n            _c4dbgp(\"mapjson[RVAL]: start val mapjson\");\n            addrem_flags(RNXT, RVAL);\n            m_evt_handler->begin_map_val_flow();\n            _set_indentation(m_evt_handler->m_parent->indref);\n            addrem_flags(RKEY, RNXT);\n            _line_progressed(1);\n            // keep going in this function\n            break;\n        }\n        default:\n        {\n            ScannedScalar sc;\n            if(_scan_scalar_map_json(&sc))\n            {\n                _c4dbgp(\"mapjson[RVAL]: plain scalar.\");\n                csubstr maybe_filtered = _maybe_filter_val_scalar_plain(sc, m_evt_handler->m_curr->indref);\n                m_evt_handler->set_val_scalar_plain(maybe_filtered);\n                addrem_flags(RNXT, RVAL);\n            }\n            else\n            {\n                _c4err(\"parse error\");\n            }\n            break;\n        }\n        }\n    }\n    else if(has_any(RKCL)) // read the key colon\n    {\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RKEY));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RVAL));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RNXT));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(QMRK));\n        const char first = rem.str[0];\n        _c4dbgpf(\"mapjson[RKCL]: '{}'\", first);\n        if(first == ':')\n        {\n            _c4dbgp(\"mapjson[RKCL]: found the colon\");\n            addrem_flags(RVAL, RKCL);\n            _line_progressed(1);\n        }\n        else\n        {\n            _c4err(\"parse error\");\n        }\n    }\n    else if(has_any(RNXT))\n    {\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RKEY));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RKCL));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RVAL));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(QMRK));\n        _c4dbgpf(\"mapjson[RNXT]: '{}'\", rem.str[0]);\n        if(rem.begins_with(','))\n        {\n            _c4dbgp(\"mapjson[RNXT]: expect next keyval\");\n            m_evt_handler->add_sibling();\n            addrem_flags(RKEY, RNXT);\n            _line_progressed(1);\n        }\n        else if(rem.begins_with('}'))\n        {\n            _c4dbgp(\"mapjson[RNXT]: end!\");\n            m_evt_handler->end_map();\n            _line_progressed(1);\n            goto mapjson_finish;\n        }\n        else\n        {\n            _c4err(\"parse error\");\n        }\n    }\n\n mapjson_again:\n    _c4dbgt(\"mapjson: go again\", 0);\n    if(_finished_line())\n    {\n        if(C4_LIKELY(!_finished_file()))\n        {\n            _line_ended();\n            _scan_line();\n            _c4dbgnextline();\n        }\n        else\n        {\n            _c4err(\"missing terminating }\");\n        }\n    }\n    goto mapjson_start;\n\n mapjson_finish:\n    _c4dbgp(\"mapjson: finish\");\n}\n\n\n//-----------------------------------------------------------------------------\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_handle_seq_imap()\n{\nseqimap_start:\n    _c4dbgpf(\"handle2_seq_imap: node_id={} level={} indref={}\", m_evt_handler->m_curr->node_id, m_evt_handler->m_curr->level, m_evt_handler->m_curr->indref);\n\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_all(RSEQIMAP));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RKEY));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_any(RVAL|RNXT|QMRK|RKCL));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, 1 == has_all(RVAL) + has_all(RNXT) + has_all(QMRK) + has_all(RKCL));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, m_evt_handler->m_stack.size() >= 3);\n\n    _handle_flow_skip_whitespace();\n    csubstr rem = m_evt_handler->m_curr->line_contents.rem;\n    if(!rem.len)\n        goto seqimap_again;\n\n    if(has_any(RVAL))\n    {\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_any(RVAL));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RNXT));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(QMRK));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RKCL));\n        const char first = rem.str[0];\n        _c4dbgpf(\"seqimap[RVAL]: '{}'\", _c4prc(first));\n        ScannedScalar sc;\n        if(first == '\\'')\n        {\n            _c4dbgp(\"seqimap[RVAL]: scanning single-quoted scalar\");\n            sc = _scan_scalar_squot();\n            csubstr maybe_filtered = _maybe_filter_val_scalar_squot(sc);\n            m_evt_handler->set_val_scalar_squoted(maybe_filtered);\n            m_evt_handler->end_map();\n            goto seqimap_finish;\n        }\n        else if(first == '\"')\n        {\n            _c4dbgp(\"seqimap[RVAL]: scanning double-quoted scalar\");\n            sc = _scan_scalar_dquot();\n            csubstr maybe_filtered = _maybe_filter_val_scalar_dquot(sc);\n            m_evt_handler->set_val_scalar_dquoted(maybe_filtered);\n            m_evt_handler->end_map();\n            goto seqimap_finish;\n        }\n        // block scalars (ie | and >) cannot appear in flow containers\n        else if(_scan_scalar_plain_map_flow(&sc))\n        {\n            _c4dbgp(\"seqimap[RVAL]: it's a scalar.\");\n            csubstr maybe_filtered = _maybe_filter_val_scalar_plain(sc, m_evt_handler->m_curr->indref);\n            m_evt_handler->set_val_scalar_plain(maybe_filtered);\n            m_evt_handler->end_map();\n            goto seqimap_finish;\n        }\n        else if(first == '[')\n        {\n            _c4dbgp(\"seqimap[RVAL]: start child seqflow\");\n            addrem_flags(RNXT, RVAL);\n            m_evt_handler->begin_seq_val_flow();\n            addrem_flags(RVAL, RNXT|RSEQIMAP);\n            _set_indentation(m_evt_handler->m_parent->indref);\n            _line_progressed(1);\n            goto seqimap_finish;\n        }\n        else if(first == '{')\n        {\n            _c4dbgp(\"seqimap[RVAL]: start child mapflow\");\n            addrem_flags(RNXT, RVAL);\n            m_evt_handler->begin_map_val_flow();\n            addrem_flags(RMAP|RKEY, RSEQ|RVAL|RSEQIMAP|RNXT);\n            _set_indentation(m_evt_handler->m_parent->indref);\n            _line_progressed(1);\n            goto seqimap_finish;\n        }\n        else if(first == ',' || first == ']')\n        {\n            _c4dbgp(\"seqimap[RVAL]: finish without val.\");\n            m_evt_handler->set_val_scalar_plain({});\n            m_evt_handler->end_map();\n            goto seqimap_finish;\n        }\n        else if(first == '&')\n        {\n            csubstr anchor = _scan_anchor();\n            _c4dbgp(\"seqimap[RVAL]: anchor!\");\n            m_evt_handler->set_val_anchor(anchor);\n        }\n        else if(first == '*')\n        {\n            csubstr ref = _scan_ref_seq();\n            _c4dbgp(\"seqimap[RVAL]: ref!\");\n            m_evt_handler->set_val_ref(ref);\n            addrem_flags(RNXT, RVAL);\n        }\n        else\n        {\n            _c4err(\"parse error\");\n        }\n    }\n    else if(has_any(RNXT))\n    {\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_any(RNXT));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RVAL));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(QMRK));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RKCL));\n        const char first = rem.str[0];\n        _c4dbgpf(\"seqimap[RNXT]: '{}'\", _c4prc(first));\n        if(first == ',' || first == ']')\n        {\n            // we may get here because a map or a seq started and we\n            // return later\n            _c4dbgp(\"seqimap: done\");\n            m_evt_handler->end_map();\n            goto seqimap_finish;\n        }\n        else\n        {\n            _c4err(\"parse error\");\n        }\n    }\n    else if(has_any(QMRK))\n    {\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_any(QMRK));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RVAL));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RNXT));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RKCL));\n        const char first = rem.str[0];\n        _c4dbgpf(\"seqimap[QMRK]: '{}'\", _c4prc(first));\n        ScannedScalar sc;\n        if(first == '\\'')\n        {\n            _c4dbgp(\"seqimap[QMRK]: scanning single-quoted scalar\");\n            sc = _scan_scalar_squot();\n            csubstr maybe_filtered = _maybe_filter_key_scalar_squot(sc);\n            m_evt_handler->set_key_scalar_squoted(maybe_filtered);\n            addrem_flags(RKCL, QMRK);\n            goto seqimap_again;\n        }\n        else if(first == '\"')\n        {\n            _c4dbgp(\"seqimap[QMRK]: scanning double-quoted scalar\");\n            sc = _scan_scalar_dquot();\n            csubstr maybe_filtered = _maybe_filter_key_scalar_dquot(sc);\n            m_evt_handler->set_key_scalar_dquoted(maybe_filtered);\n            addrem_flags(RKCL, QMRK);\n            goto seqimap_again;\n        }\n        // block scalars (ie | and >) cannot appear in flow containers\n        else if(_scan_scalar_plain_map_flow(&sc))\n        {\n            _c4dbgp(\"seqimap[QMRK]: it's a scalar.\");\n            csubstr maybe_filtered = _maybe_filter_key_scalar_plain(sc, m_evt_handler->m_curr->indref);\n            m_evt_handler->set_key_scalar_plain(maybe_filtered);\n            addrem_flags(RKCL, QMRK);\n            goto seqimap_again;\n        }\n        else if(first == '[')\n        {\n            _c4dbgp(\"seqimap[QMRK]: start child seqflow\");\n            addrem_flags(RKCL, QMRK);\n            m_evt_handler->begin_seq_key_flow();\n            addrem_flags(RSEQ|RVAL, RKCL|RSEQIMAP);\n            _set_indentation(m_evt_handler->m_parent->indref);\n            _line_progressed(1);\n            goto seqimap_finish;\n        }\n        else if(first == '{')\n        {\n            _c4dbgp(\"seqimap[QMRK]: start child mapflow\");\n            addrem_flags(RKCL, QMRK);\n            m_evt_handler->begin_map_key_flow();\n            addrem_flags(RMAP|RKEY, RSEQ|RKCL|RSEQIMAP);\n            _set_indentation(m_evt_handler->m_parent->indref);\n            _line_progressed(1);\n            goto seqimap_finish;\n        }\n        else if(first == ',' || first == ']')\n        {\n            _c4dbgp(\"seqimap[QMRK]: finish without key.\");\n            m_evt_handler->set_key_scalar_plain({});\n            m_evt_handler->set_val_scalar_plain({});\n            m_evt_handler->end_map();\n            goto seqimap_finish;\n        }\n        else if(first == '&')\n        {\n            csubstr anchor = _scan_anchor();\n            _c4dbgp(\"seqimap[QMRK]: anchor!\");\n            m_evt_handler->set_key_anchor(anchor);\n        }\n        else if(first == '*')\n        {\n            csubstr ref = _scan_ref_seq();\n            _c4dbgp(\"seqimap[QMRK]: ref!\");\n            m_evt_handler->set_key_ref(ref);\n            addrem_flags(RKCL, QMRK);\n        }\n        else\n        {\n            _c4err(\"parse error\");\n        }\n    }\n    else if(has_any(RKCL))\n    {\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RVAL));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RNXT));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(QMRK));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_any(RKCL));\n        const char first = rem.str[0];\n        _c4dbgpf(\"seqimap[RKCL]: '{}'\", _c4prc(first));\n        if(first == ':')\n        {\n            _c4dbgp(\"seqimap[RKCL]: found ':'\");\n            addrem_flags(RVAL, RKCL);\n            _line_progressed(1);\n            goto seqimap_again;\n        }\n        else if(first == ',' || first == ']')\n        {\n            _c4dbgp(\"seqimap[RKCL]: found ','. finish without val\");\n            m_evt_handler->set_val_scalar_plain({});\n            m_evt_handler->end_map();\n            goto seqimap_finish;\n        }\n        else\n        {\n            _c4err(\"parse error\");\n        }\n    }\n\n seqimap_again:\n    _c4dbgt(\"seqimap: go again\", 0);\n    if(_finished_line())\n    {\n        if(C4_LIKELY(!_finished_file()))\n        {\n            _line_ended();\n            _scan_line();\n            _c4dbgnextline();\n        }\n        else\n        {\n            _c4err(\"parse error\");\n        }\n    }\n    goto seqimap_start;\n\n seqimap_finish:\n    _c4dbgp(\"seqimap: finish\");\n}\n\n\n//-----------------------------------------------------------------------------\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_handle_seq_flow()\n{\nseqflow_start:\n    _c4dbgpf(\"handle2_seq_flow: node_id={} level={} indentation={}\", m_evt_handler->m_curr->node_id, m_evt_handler->m_curr->level, m_evt_handler->m_curr->indref);\n\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RKEY));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_all(RSEQ));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_all(FLOW));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_any(RVAL|RNXT));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_all(RVAL) != has_all(RNXT));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, m_evt_handler->m_curr->indref != npos);\n\n    _handle_flow_skip_whitespace();\n    csubstr rem = m_evt_handler->m_curr->line_contents.rem;\n    if(!rem.len)\n        goto seqflow_again;\n\n    if(has_any(RVAL))\n    {\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RNXT));\n        const char first = rem.str[0];\n        ScannedScalar sc;\n        if(first == '\\'')\n        {\n            _c4dbgp(\"seqflow[RVAL]: scanning single-quoted scalar\");\n            sc = _scan_scalar_squot();\n            csubstr maybe_filtered = _maybe_filter_val_scalar_squot(sc);\n            m_evt_handler->set_val_scalar_squoted(maybe_filtered);\n            addrem_flags(RNXT, RVAL);\n        }\n        else if(first == '\"')\n        {\n            _c4dbgp(\"seqflow[RVAL]: scanning double-quoted scalar\");\n            sc = _scan_scalar_dquot();\n            csubstr maybe_filtered = _maybe_filter_val_scalar_dquot(sc);\n            m_evt_handler->set_val_scalar_dquoted(maybe_filtered);\n            addrem_flags(RNXT, RVAL);\n        }\n        // block scalars (ie | and >) cannot appear in flow containers\n        else if(_scan_scalar_plain_seq_flow(&sc))\n        {\n            _c4dbgp(\"seqflow[RVAL]: it's a scalar.\");\n            csubstr maybe_filtered = _maybe_filter_val_scalar_plain(sc, m_evt_handler->m_curr->indref);\n            m_evt_handler->set_val_scalar_plain(maybe_filtered);\n            addrem_flags(RNXT, RVAL);\n        }\n        else if(first == '[')\n        {\n            _c4dbgp(\"seqflow[RVAL]: start child seqflow\");\n            addrem_flags(RNXT, RVAL);\n            m_evt_handler->begin_seq_val_flow();\n            _set_indentation(m_evt_handler->m_parent->indref);\n            addrem_flags(RVAL, RNXT);\n            _line_progressed(1);\n        }\n        else if(first == '{')\n        {\n            _c4dbgp(\"seqflow[RVAL]: start child mapflow\");\n            addrem_flags(RNXT, RVAL);\n            m_evt_handler->begin_map_val_flow();\n            _set_indentation(m_evt_handler->m_parent->indref);\n            addrem_flags(RMAP|RKEY, RSEQ|RVAL|RNXT);\n            _line_progressed(1);\n            goto seqflow_finish;\n        }\n        else if(first == ']') // this happens on a trailing comma like \", ]\"\n        {\n            _c4dbgp(\"seqflow[RVAL]: end!\");\n            _line_progressed(1);\n            m_evt_handler->end_seq();\n            goto seqflow_finish;\n        }\n        else if(first == '*')\n        {\n            csubstr ref = _scan_ref_seq();\n            _c4dbgpf(\"seqflow[RVAL]: ref! [{}]~~~{}~~~\", ref.len, ref);\n            m_evt_handler->set_val_ref(ref);\n            addrem_flags(RNXT, RVAL);\n        }\n        else if(first == '&')\n        {\n            csubstr anchor = _scan_anchor();\n            _c4dbgpf(\"seqflow[RVAL]: anchor! [{}]~~~{}~~~\", anchor.len, anchor);\n            m_evt_handler->set_val_anchor(anchor);\n            if(_maybe_scan_following_comma())\n            {\n                _c4dbgp(\"seqflow[RVAL]: empty scalar!\");\n                m_evt_handler->set_val_scalar_plain({});\n                m_evt_handler->add_sibling();\n            }\n        }\n        else if(first == '!')\n        {\n            csubstr tag = _scan_tag();\n            _c4dbgpf(\"seqflow[RVAL]: tag! [{}]~~~{}~~~\", tag.len, tag);\n            _check_tag(tag);\n            m_evt_handler->set_val_tag(tag);\n            if(_maybe_scan_following_comma())\n            {\n                _c4dbgp(\"seqflow[RVAL]: empty scalar!\");\n                m_evt_handler->set_val_scalar_plain({});\n                m_evt_handler->add_sibling();\n            }\n        }\n        else if(first == ':')\n        {\n            _c4dbgpf(\"seqflow[RVAL]: actually seqimap at node[{}], with empty key\", m_evt_handler->m_curr->node_id);\n            addrem_flags(RNXT, RVAL);\n            m_evt_handler->begin_map_val_flow();\n            _set_indentation(m_evt_handler->m_parent->indref);\n            m_evt_handler->set_key_scalar_plain({});\n            addrem_flags(RSEQIMAP|RVAL, RSEQ|RNXT);\n            _line_progressed(1);\n            goto seqflow_finish;\n        }\n        else if(first == '?')\n        {\n            _c4dbgp(\"seqflow[RVAL]: start child mapflow, explicit key\");\n            addrem_flags(RNXT, RVAL);\n            m_was_inside_qmrk = true;\n            m_evt_handler->begin_map_val_flow();\n            _set_indentation(m_evt_handler->m_parent->indref);\n            addrem_flags(RSEQIMAP|QMRK, RSEQ|RNXT);\n            _line_progressed(1);\n            _maybe_skip_whitespace_tokens();\n            goto seqflow_finish;\n        }\n        else\n        {\n            _c4err(\"parse error\");\n        }\n    }\n    else // RNXT\n    {\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_any(RNXT));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RVAL));\n        const char first = rem.str[0];\n        if(first == ',')\n        {\n            _c4dbgp(\"seqflow[RNXT]: expect next val\");\n            addrem_flags(RVAL, RNXT);\n            m_evt_handler->add_sibling();\n            _line_progressed(1);\n        }\n        else if(first == ']')\n        {\n            _c4dbgp(\"seqflow[RNXT]: end!\");\n            m_evt_handler->end_seq();\n            _line_progressed(1);\n            goto seqflow_finish;\n        }\n        else if(first == ':')\n        {\n            _c4dbgpf(\"seqflow[RNXT]: actually seqimap at node[{}]\", m_evt_handler->m_curr->node_id);\n            m_evt_handler->actually_val_is_first_key_of_new_map_flow();\n            _set_indentation(m_evt_handler->m_parent->indref);\n            _line_progressed(1);\n            addrem_flags(RSEQIMAP|RVAL, RNXT);\n            goto seqflow_finish;\n        }\n        else\n        {\n            _c4err(\"parse error\");\n        }\n    }\n\n seqflow_again:\n    _c4dbgt(\"seqflow: go again\", 0);\n    if(_finished_line())\n    {\n        if(C4_LIKELY(!_finished_file()))\n        {\n            _line_ended();\n            _scan_line();\n            _c4dbgnextline();\n        }\n        else\n        {\n            _c4err(\"missing terminating ]\");\n        }\n    }\n    goto seqflow_start;\n\n seqflow_finish:\n    _c4dbgp(\"seqflow: finish\");\n}\n\n\n//-----------------------------------------------------------------------------\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_handle_map_flow()\n{\nmapflow_start:\n    _c4dbgpf(\"handle2_map_flow: node_id={} level={} indentation={}\", m_evt_handler->m_curr->node_id, m_evt_handler->m_curr->level, m_evt_handler->m_curr->indref);\n\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_all(RMAP));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_all(FLOW));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_any(RKEY|RKCL|RVAL|RNXT|QMRK));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, 1 == (has_any(RKEY) + has_any(RKCL) + has_any(RVAL) + has_any(RNXT) + has_any(QMRK)));\n\n    _handle_flow_skip_whitespace();\n    csubstr rem = m_evt_handler->m_curr->line_contents.rem;\n    if(!rem.len)\n        goto mapflow_again;\n\n    if(has_any(RKEY))\n    {\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RKCL));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RVAL));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RNXT));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(QMRK));\n        const char first = rem.str[0];\n        _c4dbgpf(\"mapflow[RKEY]: '{}'\", first);\n        ScannedScalar sc;\n        if(first == '\\'')\n        {\n            _c4dbgp(\"mapflow[RKEY]: scanning single-quoted scalar\");\n            sc = _scan_scalar_squot();\n            csubstr maybe_filtered = _maybe_filter_key_scalar_squot(sc);\n            m_evt_handler->set_key_scalar_squoted(maybe_filtered);\n            addrem_flags(RKCL, RKEY|QMRK);\n        }\n        else if(first == '\"')\n        {\n            _c4dbgp(\"mapflow[RKEY]: scanning double-quoted scalar\");\n            sc = _scan_scalar_dquot();\n            csubstr maybe_filtered = _maybe_filter_key_scalar_dquot(sc);\n            m_evt_handler->set_key_scalar_dquoted(maybe_filtered);\n            addrem_flags(RKCL, RKEY|QMRK);\n        }\n        // block scalars (ie | and >) cannot appear in flow containers\n        else if(_scan_scalar_plain_map_flow(&sc))\n        {\n            _c4dbgp(\"mapflow[RKEY]: plain scalar\");\n            csubstr maybe_filtered = _maybe_filter_key_scalar_plain(sc, m_evt_handler->m_curr->indref);\n            m_evt_handler->set_key_scalar_plain(maybe_filtered);\n            addrem_flags(RKCL, RKEY|QMRK);\n        }\n        else if(first == '?')\n        {\n            _c4dbgp(\"mapflow[RKEY]: explicit key\");\n            _line_progressed(1);\n            addrem_flags(QMRK, RKEY);\n            _maybe_skip_whitespace_tokens();\n        }\n        else if(first == ':')\n        {\n            _c4dbgp(\"mapflow[RKEY]: setting empty key\");\n            m_evt_handler->set_key_scalar_plain({});\n            addrem_flags(RVAL, RKEY|QMRK);\n            _line_progressed(1);\n            _maybe_skip_whitespace_tokens();\n        }\n        else if(first == '}') // this happens on a trailing comma like \", }\"\n        {\n            _c4dbgp(\"mapflow[RKEY]: end!\");\n            m_evt_handler->end_map();\n            _line_progressed(1);\n            goto mapflow_finish;\n        }\n        else if(first == '&')\n        {\n            csubstr anchor = _scan_anchor();\n            _c4dbgpf(\"mapflow[RKEY]: key anchor! [{}]~~~{}~~~\", anchor.len, anchor);\n            m_evt_handler->set_key_anchor(anchor);\n        }\n        else if(first == '*')\n        {\n            csubstr ref = _scan_ref_map();\n            _c4dbgpf(\"mapflow[RKEY]: key ref! [{}]~~~{}~~~\", ref.len, ref);\n            m_evt_handler->set_key_ref(ref);\n            addrem_flags(RKCL, RKEY);\n        }\n        else if(first == '[')\n        {\n            // RYML's tree cannot store container keys, but that's\n            // handled inside the tree sink. Other sink types may be\n            // able to handle it.\n            _c4dbgp(\"mapflow[RKEY]: start child seqflow (!)\");\n            addrem_flags(RKCL, RKEY);\n            m_evt_handler->begin_seq_key_flow();\n            addrem_flags(RSEQ|RVAL, RMAP|RKCL);\n            _set_indentation(m_evt_handler->m_parent->indref);\n            _line_progressed(1);\n            goto mapflow_finish;\n        }\n        else if(first == '{')\n        {\n            // RYML's tree cannot store container keys, but that's\n            // handled inside the tree sink. Other sink types may be\n            // able to handle it.\n            _c4dbgp(\"mapflow[RKEY]: start child mapflow (!)\");\n            addrem_flags(RKCL, RKEY);\n            m_evt_handler->begin_map_key_flow();\n            addrem_flags(RKEY, RVAL|RKCL);\n            _set_indentation(m_evt_handler->m_parent->indref);\n            _line_progressed(1);\n            // keep going in this function\n        }\n        else if(first == '!')\n        {\n            csubstr tag = _scan_tag();\n            _c4dbgpf(\"mapflow[RKEY]: tag! [{}]~~~{}~~~\", tag.len, tag);\n            _check_tag(tag);\n            m_evt_handler->set_key_tag(tag);\n        }\n        else\n        {\n            _c4err(\"parse error\");\n        }\n    }\n    else if(has_any(RKCL)) // read the key colon\n    {\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RKEY));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RVAL));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RNXT));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(QMRK));\n        const char first = rem.str[0];\n        _c4dbgpf(\"mapflow[RKCL]: '{}'\", first);\n        if(first == ':')\n        {\n            _c4dbgp(\"mapflow[RKCL]: found the colon\");\n            addrem_flags(RVAL, RKCL);\n            _line_progressed(1);\n        }\n        else if(first == '}')\n        {\n            _c4dbgp(\"mapflow[RKCL]: end with missing val!\");\n            addrem_flags(RVAL, RKCL);\n            m_evt_handler->set_val_scalar_plain({});\n            m_evt_handler->end_map();\n            _line_progressed(1);\n            goto mapflow_finish;\n        }\n        else if(first == ',')\n        {\n            _c4dbgp(\"mapflow[RKCL]: got comma. val is missing\");\n            m_evt_handler->set_val_scalar_plain({});\n            m_evt_handler->add_sibling();\n            addrem_flags(RKEY, RKCL);\n            _line_progressed(1);\n        }\n        else\n        {\n            _c4err(\"parse error\");\n        }\n    }\n    else if(has_any(RVAL))\n    {\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RKEY));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RKCL));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RNXT));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(QMRK));\n        const char first = rem.str[0];\n        _c4dbgpf(\"mapflow[RVAL]: '{}'\", first);\n        ScannedScalar sc;\n        if(first == '\\'')\n        {\n            _c4dbgp(\"mapflow[RVAL]: scanning single-quoted scalar\");\n            sc = _scan_scalar_squot();\n            csubstr maybe_filtered = _maybe_filter_val_scalar_squot(sc);\n            m_evt_handler->set_val_scalar_squoted(maybe_filtered);\n            addrem_flags(RNXT, RVAL);\n        }\n        else if(first == '\"')\n        {\n            _c4dbgp(\"mapflow[RVAL]: scanning double-quoted scalar\");\n            sc = _scan_scalar_dquot();\n            csubstr maybe_filtered = _maybe_filter_val_scalar_dquot(sc);\n            m_evt_handler->set_val_scalar_dquoted(maybe_filtered);\n            addrem_flags(RNXT, RVAL);\n        }\n        // block scalars (ie | and >) cannot appear in flow containers\n        else if(_scan_scalar_plain_map_flow(&sc))\n        {\n            _c4dbgp(\"mapflow[RVAL]: plain scalar.\");\n            csubstr maybe_filtered = _maybe_filter_val_scalar_plain(sc, m_evt_handler->m_curr->indref);\n            m_evt_handler->set_val_scalar_plain(maybe_filtered);\n            addrem_flags(RNXT, RVAL);\n        }\n        else if(first == '[')\n        {\n            _c4dbgp(\"mapflow[RVAL]: start val seqflow\");\n            addrem_flags(RNXT, RVAL);\n            m_evt_handler->begin_seq_val_flow();\n            _set_indentation(m_evt_handler->m_parent->indref);\n            addrem_flags(RSEQ|RVAL, RMAP|RNXT);\n            _line_progressed(1);\n            goto mapflow_finish;\n        }\n        else if(first == '{')\n        {\n            _c4dbgp(\"mapflow[RVAL]: start val mapflow\");\n            addrem_flags(RNXT, RVAL);\n            m_evt_handler->begin_map_val_flow();\n            _set_indentation(m_evt_handler->m_parent->indref);\n            addrem_flags(RKEY, RNXT);\n            _line_progressed(1);\n            // keep going in this function\n        }\n        else if(first == '}')\n        {\n            _c4dbgp(\"mapflow[RVAL]: end!\");\n            m_evt_handler->set_val_scalar_plain({});\n            m_evt_handler->end_map();\n            _line_progressed(1);\n            goto mapflow_finish;\n        }\n        else if(first == '*')\n        {\n            csubstr ref = _scan_ref_map();\n            _c4dbgpf(\"mapflow[RVAL]: key ref! [{}]~~~{}~~~\", ref.len, ref);\n            m_evt_handler->set_val_ref(ref);\n            addrem_flags(RNXT, RVAL);\n        }\n        else if(first == '&')\n        {\n            csubstr anchor = _scan_anchor();\n            _c4dbgpf(\"mapflow[RVAL]: key anchor! [{}]~~~{}~~~\", anchor.len, anchor);\n            m_evt_handler->set_val_anchor(anchor);\n        }\n        else if(first == '!')\n        {\n            csubstr tag = _scan_tag();\n            _c4dbgpf(\"mapflow[RVAL]: tag! [{}]~~~{}~~~\", tag.len, tag);\n            _check_tag(tag);\n            m_evt_handler->set_val_tag(tag);\n        }\n        else\n        {\n            _c4err(\"parse error\");\n        }\n    }\n    else if(has_any(RNXT))\n    {\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RKEY));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RKCL));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RVAL));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(QMRK));\n        _c4dbgpf(\"mapflow[RNXT]: '{}'\", rem.str[0]);\n        if(rem.begins_with(','))\n        {\n            _c4dbgp(\"mapflow[RNXT]: expect next keyval\");\n            m_evt_handler->add_sibling();\n            addrem_flags(RKEY, RNXT);\n            _line_progressed(1);\n        }\n        else if(rem.begins_with('}'))\n        {\n            _c4dbgp(\"mapflow[RNXT]: end!\");\n            m_evt_handler->end_map();\n            _line_progressed(1);\n            goto mapflow_finish;\n        }\n        else\n        {\n            _c4err(\"parse error\");\n        }\n    }\n    else if(has_any(QMRK))\n    {\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RKEY));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RKCL));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RVAL));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RNXT));\n        const char first = rem.str[0];\n        _c4dbgpf(\"mapflow[QMRK]: '{}'\", first);\n        ScannedScalar sc;\n        if(first == '\\'')\n        {\n            _c4dbgp(\"mapflow[QMRK]: scanning single-quoted scalar\");\n            sc = _scan_scalar_squot();\n            csubstr maybe_filtered = _maybe_filter_key_scalar_squot(sc);\n            m_evt_handler->set_key_scalar_squoted(maybe_filtered);\n            addrem_flags(RKCL, QMRK);\n        }\n        else if(first == '\"')\n        {\n            _c4dbgp(\"mapflow[QMRK]: scanning double-quoted scalar\");\n            sc = _scan_scalar_dquot();\n            csubstr maybe_filtered = _maybe_filter_key_scalar_dquot(sc);\n            m_evt_handler->set_key_scalar_dquoted(maybe_filtered);\n            addrem_flags(RKCL, QMRK);\n        }\n        // block scalars (ie | and >) cannot appear in flow containers\n        else if(_scan_scalar_plain_map_flow(&sc))\n        {\n            _c4dbgp(\"mapflow[QMRK]: plain scalar\");\n            csubstr maybe_filtered = _maybe_filter_key_scalar_plain(sc, m_evt_handler->m_curr->indref);\n            m_evt_handler->set_key_scalar_plain(maybe_filtered);\n            addrem_flags(RKCL, QMRK);\n        }\n        else if(first == ':')\n        {\n            _c4dbgp(\"mapflow[QMRK]: setting empty key\");\n            m_evt_handler->set_key_scalar_plain({});\n            addrem_flags(RVAL, QMRK);\n            _line_progressed(1);\n            _maybe_skip_whitespace_tokens();\n        }\n        else if(first == '}') // this happens on a trailing comma like \", }\"\n        {\n            _c4dbgp(\"mapflow[QMRK]: end!\");\n            m_evt_handler->set_key_scalar_plain({});\n            m_evt_handler->set_val_scalar_plain({});\n            m_evt_handler->end_map();\n            _line_progressed(1);\n            goto mapflow_finish;\n        }\n        else if(first == '&')\n        {\n            csubstr anchor = _scan_anchor();\n            _c4dbgpf(\"mapflow[QMRK]: key anchor! [{}]~~~{}~~~\", anchor.len, anchor);\n            m_evt_handler->set_key_anchor(anchor);\n        }\n        else if(first == '*')\n        {\n            csubstr ref = _scan_ref_map();\n            _c4dbgpf(\"mapflow[QMRK]: key ref! [{}]~~~{}~~~\", ref.len, ref);\n            m_evt_handler->set_key_ref(ref);\n            addrem_flags(RKCL, QMRK);\n        }\n        else if(first == '[')\n        {\n            // RYML's tree cannot store container keys, but that's\n            // handled inside the tree sink. Other sink types may be\n            // able to handle it.\n            _c4dbgp(\"mapflow[QMRK]: start child seqflow (!)\");\n            addrem_flags(RKCL, QMRK);\n            m_evt_handler->begin_seq_key_flow();\n            addrem_flags(RSEQ|RVAL, RMAP|RKCL);\n            _set_indentation(m_evt_handler->m_parent->indref);\n            _line_progressed(1);\n            goto mapflow_finish;\n        }\n        else if(first == '{')\n        {\n            // RYML's tree cannot store container keys, but that's\n            // handled inside the tree sink. Other sink types may be\n            // able to handle it.\n            _c4dbgp(\"mapflow[QMRK]: start child mapflow (!)\");\n            addrem_flags(RKCL, QMRK);\n            m_evt_handler->begin_map_key_flow();\n            _set_indentation(m_evt_handler->m_parent->indref);\n            addrem_flags(RKEY, RKCL);\n            _line_progressed(1);\n            // keep going in this function\n        }\n        else if(first == '!')\n        {\n            csubstr tag = _scan_tag();\n            _c4dbgpf(\"mapflow[QMRK]: tag! [{}]~~~{}~~~\", tag.len, tag);\n            _check_tag(tag);\n            m_evt_handler->set_key_tag(tag);\n        }\n        else\n        {\n            _c4err(\"parse error\");\n        }\n    }\n\n mapflow_again:\n    _c4dbgt(\"mapflow: go again\", 0);\n    if(_finished_line())\n    {\n        if(C4_LIKELY(!_finished_file()))\n        {\n            _line_ended();\n            _scan_line();\n            _c4dbgnextline();\n        }\n        else\n        {\n            _c4err(\"missing terminating }\");\n        }\n    }\n    goto mapflow_start;\n\n mapflow_finish:\n    _c4dbgp(\"mapflow: finish\");\n}\n\n\n//-----------------------------------------------------------------------------\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_handle_seq_block()\n{\nseqblck_start:\n    _c4dbgpf(\"handle2_seq_block: seq_id={} node_id={} level={} indent={}\", m_evt_handler->m_parent->node_id, m_evt_handler->m_curr->node_id, m_evt_handler->m_curr->level, m_evt_handler->m_curr->indref);\n\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_all(RSEQ));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_all(BLCK));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_any(RVAL|RNXT));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, 1 == (has_any(RVAL) + has_any(RNXT)));\n\n    _maybe_skip_comment();\n    csubstr rem = m_evt_handler->m_curr->line_contents.rem;\n    if(!rem.len)\n        goto seqblck_again;\n\n    if(has_any(RVAL))\n    {\n        _c4dbgpf(\"seqblck[RVAL]: col={}\", m_evt_handler->m_curr->pos.col);\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RNXT));\n        if(m_evt_handler->m_curr->at_line_beginning())\n        {\n            _c4dbgpf(\"seqblck[RVAL]: indref={} indentation={}\", m_evt_handler->m_curr->indref, m_evt_handler->m_curr->line_contents.indentation);\n            if(m_evt_handler->m_curr->indentation_ge())\n            {\n                _c4dbgpf(\"seqblck[RVAL]: skip {} from indentation\", m_evt_handler->m_curr->line_contents.indentation);\n                _line_progressed(m_evt_handler->m_curr->line_contents.indentation);\n                rem = m_evt_handler->m_curr->line_contents.rem;\n                if(!rem.len)\n                    goto seqblck_again;\n            }\n            else if(m_evt_handler->m_curr->indentation_lt())\n            {\n                _c4dbgp(\"seqblck[RVAL]: smaller indentation!\");\n                _handle_indentation_pop_from_block_seq();\n                goto seqblck_finish;\n            }\n            else if(m_evt_handler->m_curr->line_contents.indentation == npos)\n            {\n                _c4dbgp(\"seqblck[RVAL]: empty line!\");\n                _line_progressed(m_evt_handler->m_curr->line_contents.rem.len);\n                goto seqblck_again;\n            }\n        }\n        #ifdef RYML_NO_COVERAGE__TO_BE_DELETED\n        else\n        {\n            // accomodate annotation on the previous line. eg:\n            // - &elm\n            //   foo            # <-- on this line\n            // - &elm\n            //   &foo foo: bar  # <-- on this line\n            if(rem.str[0] == ' ')\n            {\n                if(_handle_indentation_from_annotations())\n                {\n                    _c4dbgp(\"seqblck[RVAL]: annotations!\");\n                    rem = m_evt_handler->m_curr->line_contents.rem;\n                    if(!rem.len)\n                        goto seqblck_again;\n                }\n            }\n        }\n        #endif\n        _RYML_CB_ASSERT(callbacks(), rem.len);\n        _c4dbgpf(\"seqblck[RVAL]: '{}' node_id={}\", rem.str[0], m_evt_handler->m_curr->node_id);\n        const char first = rem.str[0];\n        const size_t startline = m_evt_handler->m_curr->pos.line;\n        // warning: the gcc optimizer on x86 builds is brittle with\n        // this function:\n        const size_t startindent = m_evt_handler->m_curr->line_contents.current_col();\n        ScannedScalar sc;\n        if(first == '\\'')\n        {\n            _c4dbgp(\"seqblck[RVAL]: single-quoted scalar\");\n            sc = _scan_scalar_squot();\n            if(!_maybe_scan_following_colon())\n            {\n                _c4dbgp(\"seqblck[RVAL]: set as val\");\n                _handle_annotations_before_blck_val_scalar();\n                csubstr maybe_filtered = _maybe_filter_val_scalar_squot(sc); // VAL!\n                m_evt_handler->set_val_scalar_squoted(maybe_filtered);\n                addrem_flags(RNXT, RVAL);\n            }\n            else\n            {\n                _c4dbgp(\"seqblck[RVAL]: start mapblck, set scalar as key\");\n                addrem_flags(RNXT, RVAL);\n                _handle_annotations_before_start_mapblck(startline);\n                m_evt_handler->begin_map_val_block();\n                _handle_annotations_and_indentation_after_start_mapblck(startindent, startline);\n                csubstr maybe_filtered = _maybe_filter_key_scalar_squot(sc); // KEY!\n                m_evt_handler->set_key_scalar_squoted(maybe_filtered);\n                addrem_flags(RMAP|RVAL, RSEQ|RNXT);\n                _maybe_skip_whitespace_tokens();\n                goto seqblck_finish;\n            }\n        }\n        else if(first == '\"')\n        {\n            _c4dbgp(\"seqblck[RVAL]: double-quoted scalar\");\n            sc = _scan_scalar_dquot();\n            if(!_maybe_scan_following_colon())\n            {\n                _c4dbgp(\"seqblck[RVAL]: set as val\");\n                _handle_annotations_before_blck_val_scalar();\n                csubstr maybe_filtered = _maybe_filter_val_scalar_dquot(sc); // VAL!\n                m_evt_handler->set_val_scalar_dquoted(maybe_filtered);\n                addrem_flags(RNXT, RVAL);\n            }\n            else\n            {\n                _c4dbgp(\"seqblck[RVAL]: start mapblck, set scalar as key\");\n                addrem_flags(RNXT, RVAL);\n                _handle_annotations_before_start_mapblck(startline);\n                m_evt_handler->begin_map_val_block();\n                _handle_annotations_and_indentation_after_start_mapblck(startindent, startline);\n                csubstr maybe_filtered = _maybe_filter_key_scalar_dquot(sc); // KEY!\n                m_evt_handler->set_key_scalar_dquoted(maybe_filtered);\n                addrem_flags(RMAP|RVAL, RSEQ|RNXT);\n                _maybe_skip_whitespace_tokens();\n                goto seqblck_finish;\n            }\n        }\n        // block scalars can only appear as keys when in QMRK scope\n        // (ie, after ? tokens), so no need to scan following colon in\n        // here.\n        else if(first == '|')\n        {\n            _c4dbgp(\"seqblck[RVAL]: block-literal scalar\");\n            ScannedBlock sb;\n            _scan_block(&sb, m_evt_handler->m_curr->indref + 1);\n            _handle_annotations_before_blck_val_scalar();\n            csubstr maybe_filtered = _maybe_filter_val_scalar_literal(sb);\n            m_evt_handler->set_val_scalar_literal(maybe_filtered);\n            addrem_flags(RNXT, RVAL);\n        }\n        else if(first == '>')\n        {\n            _c4dbgp(\"seqblck[RVAL]: block-folded scalar\");\n            ScannedBlock sb;\n            _scan_block(&sb, m_evt_handler->m_curr->indref + 1);\n            _handle_annotations_before_blck_val_scalar();\n            csubstr maybe_filtered = _maybe_filter_val_scalar_folded(sb);\n            m_evt_handler->set_val_scalar_folded(maybe_filtered);\n            addrem_flags(RNXT, RVAL);\n        }\n        else if(_scan_scalar_plain_seq_blck(&sc))\n        {\n            _c4dbgp(\"seqblck[RVAL]: plain scalar.\");\n            if(!_maybe_scan_following_colon())\n            {\n                _c4dbgp(\"seqblck[RVAL]: set as val\");\n                _handle_annotations_before_blck_val_scalar();\n                csubstr maybe_filtered = _maybe_filter_val_scalar_plain(sc, m_evt_handler->m_curr->indref);  // VAL!\n                m_evt_handler->set_val_scalar_plain(maybe_filtered);\n                addrem_flags(RNXT, RVAL);\n            }\n            else\n            {\n                if(startindent > m_evt_handler->m_curr->indref)\n                {\n                    _c4dbgp(\"seqblck[RVAL]: start mapblck, set scalar as key\");\n                    addrem_flags(RNXT, RVAL);\n                    _handle_annotations_before_start_mapblck(startline);\n                    m_evt_handler->begin_map_val_block();\n                    _handle_annotations_and_indentation_after_start_mapblck(startindent, startline);\n                    csubstr maybe_filtered = _maybe_filter_key_scalar_plain(sc, m_evt_handler->m_curr->indref);  // KEY!\n                    m_evt_handler->set_key_scalar_plain(maybe_filtered);\n                    addrem_flags(RMAP|RVAL, RSEQ|RNXT);\n                    _maybe_skip_whitespace_tokens();\n                    goto seqblck_finish;\n                }\n                else if(m_evt_handler->m_parent && m_evt_handler->m_parent->indref == startindent && has_any(RMAP|BLCK, m_evt_handler->m_parent))\n                {\n                    _c4dbgp(\"seqblck[RVAL]: empty val + end indentless seq + set key\");\n                    m_evt_handler->set_val_scalar_plain({});\n                    m_evt_handler->end_seq();\n                    m_evt_handler->add_sibling();\n                    csubstr maybe_filtered = _maybe_filter_key_scalar_plain(sc, m_evt_handler->m_curr->indref);  // KEY!\n                    m_evt_handler->set_key_scalar_plain(maybe_filtered);\n                    addrem_flags(RVAL, RNXT|RKEY);\n                    _maybe_skip_whitespace_tokens();\n                    goto seqblck_finish;\n                }\n                else\n                {\n                    _c4err(\"parse error\");\n                }\n            }\n        }\n        else if(first == '[')\n        {\n            _c4dbgp(\"seqblck[RVAL]: start child seqflow\");\n            addrem_flags(RNXT, RVAL);\n            m_evt_handler->begin_seq_val_flow();\n            addrem_flags(FLOW|RVAL, BLCK|RNXT);\n            _line_progressed(1);\n            _set_indentation(m_evt_handler->m_parent->indref + 1u);\n            goto seqblck_finish;\n        }\n        else if(first == '{')\n        {\n            _c4dbgp(\"seqblck[RVAL]: start child mapflow\");\n            addrem_flags(RNXT, RVAL);\n            _handle_annotations_before_blck_val_scalar();\n            m_evt_handler->begin_map_val_flow();\n            addrem_flags(RMAP|RKEY|FLOW, BLCK|RSEQ|RVAL|RNXT);\n            _line_progressed(1);\n            _set_indentation(m_evt_handler->m_parent->indref + 1u);\n            goto seqblck_finish;\n        }\n        else if(first == '-')\n        {\n            if(startindent == m_evt_handler->m_curr->indref)\n            {\n                _c4dbgp(\"seqblck[RVAL]: prev val was empty\");\n                _handle_annotations_before_blck_val_scalar();\n                m_evt_handler->set_val_scalar_plain({});\n                // keep in RVAL, but for the next sibling\n                m_evt_handler->add_sibling();\n            }\n            else\n            {\n                _c4dbgp(\"seqblck[RVAL]: start child seqblck\");\n                _RYML_CB_ASSERT(this->callbacks(), startindent > m_evt_handler->m_curr->indref);\n                addrem_flags(RNXT, RVAL);\n                _handle_annotations_before_blck_val_scalar();\n                m_evt_handler->begin_seq_val_block();\n                addrem_flags(RVAL, RNXT);\n                _save_indentation();\n                // keep going on inside this function\n            }\n            _line_progressed(1);\n            _maybe_skip_whitespace_tokens();\n        }\n        else if(first == ':')\n        {\n            _c4dbgp(\"seqblck[RVAL]: start child mapblck with empty key\");\n            addrem_flags(RNXT, RVAL);\n            _handle_annotations_before_start_mapblck(startline);\n            m_evt_handler->begin_map_val_block();\n            _handle_annotations_and_indentation_after_start_mapblck(startindent, startline);\n            m_evt_handler->set_key_scalar_plain({});\n            addrem_flags(RMAP|RVAL, RSEQ|RNXT);\n            _line_progressed(1);\n            _maybe_skip_whitespace_tokens();\n            goto seqblck_finish;\n        }\n        else if(first == '&')\n        {\n            const csubstr anchor = _scan_anchor();\n            _c4dbgpf(\"seqblck[RVAL]: anchor! [{}]~~~{}~~~\", anchor.len, anchor);\n            // we need to buffer the anchors, as there may be two\n            // consecutive anchors in here\n            _add_annotation(&m_pending_anchors, anchor, startindent, startline);\n        }\n        else if(first == '*')\n        {\n            csubstr ref = _scan_ref_seq();\n            _c4dbgpf(\"seqblck[RVAL]: ref! [{}]~~~{}~~~\", ref.len, ref);\n            if(!_maybe_scan_following_colon())\n            {\n                _c4dbgp(\"seqblck[RVAL]: set ref as val!\");\n                _handle_annotations_before_blck_val_scalar();\n                m_evt_handler->set_val_ref(ref);\n                addrem_flags(RNXT, RVAL);\n            }\n            else\n            {\n                _c4dbgp(\"seqblck[RVAL]: ref is key of map\");\n                addrem_flags(RNXT, RVAL);\n                _handle_annotations_before_start_mapblck(startline);\n                m_evt_handler->begin_map_val_block();\n                _handle_annotations_and_indentation_after_start_mapblck(startindent, startline);\n                m_evt_handler->set_key_ref(ref);\n                addrem_flags(RMAP|RVAL, RSEQ|RNXT);\n                _set_indentation(startindent);\n                _maybe_skip_whitespace_tokens();\n                goto seqblck_finish;\n            }\n        }\n        else if(first == '!')\n        {\n            csubstr tag = _scan_tag();\n            _c4dbgpf(\"seqblck[RVAL]: val tag! [{}]~~~{}~~~\", tag.len, tag);\n            // we need to buffer the tags, as there may be two\n            // consecutive tags in here\n            _add_annotation(&m_pending_tags, tag, startindent, startline);\n        }\n        else if(first == '?')\n        {\n            _c4dbgp(\"seqblck[RVAL]: start child mapblck, explicit key\");\n            addrem_flags(RNXT, RVAL);\n            m_was_inside_qmrk = true;\n            m_evt_handler->begin_map_val_block();\n            addrem_flags(RMAP|QMRK, RSEQ|RNXT);\n            _save_indentation();\n            _line_progressed(1);\n            _maybe_skip_whitespace_tokens();\n            goto seqblck_finish;\n        }\n        else\n        {\n            _c4err(\"parse error\");\n        }\n    }\n    else // RNXT\n    {\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_any(RNXT));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RVAL));\n        //\n        // handle indentation\n        //\n        _c4dbgpf(\"seqblck[RNXT]: indref={} indentation={}\", m_evt_handler->m_curr->indref, m_evt_handler->m_curr->line_contents.indentation);\n        if(C4_UNLIKELY(!_at_line_begin()))\n            _c4err(\"parse error\");\n        if(m_evt_handler->m_curr->indentation_ge())\n        {\n            _c4dbgpf(\"seqblck[RNXT]: skip {} from indref\", m_evt_handler->m_curr->indref);\n            _line_progressed(m_evt_handler->m_curr->indref);\n            _maybe_skip_whitespace_tokens();\n            rem = m_evt_handler->m_curr->line_contents.rem;\n            if(!rem.len)\n                goto seqblck_again;\n        }\n        else if(m_evt_handler->m_curr->indentation_lt())\n        {\n            _c4dbgp(\"seqblck[RNXT]: smaller indentation!\");\n            _handle_indentation_pop_from_block_seq();\n            if(has_all(RSEQ|BLCK))\n            {\n                _c4dbgp(\"seqblck[RNXT]: still seqblck!\");\n                _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_any(RNXT));\n                _line_progressed(m_evt_handler->m_curr->line_contents.indentation);\n                rem = m_evt_handler->m_curr->line_contents.rem;\n                if(!rem.len)\n                    goto seqblck_again;\n            }\n            else\n            {\n                _c4dbgp(\"seqblck[RNXT]: no longer seqblck!\");\n                goto seqblck_finish;\n            }\n        }\n        else if(m_evt_handler->m_curr->line_contents.indentation == npos)\n        {\n            _c4dbgpf(\"seqblck[RNXT]: blank line, len={}\", m_evt_handler->m_curr->line_contents.rem);\n            _line_progressed(m_evt_handler->m_curr->line_contents.rem.len);\n            rem = m_evt_handler->m_curr->line_contents.rem;\n            if(!rem.len)\n                goto seqblck_again;\n        }\n        //\n        // now handle the tokens\n        //\n        const char first = rem.str[0];\n        _c4dbgpf(\"seqblck[RNXT]: '{}' node_id={}\", first, m_evt_handler->m_curr->node_id);\n        if(first == '-')\n        {\n            if(m_evt_handler->m_curr->indref > 0 || m_evt_handler->m_curr->line_contents.indentation > 0 || !_is_doc_begin_token(rem))\n            {\n                _c4dbgp(\"seqblck[RNXT]: expect next val\");\n                addrem_flags(RVAL, RNXT);\n                m_evt_handler->add_sibling();\n                _line_progressed(1);\n                _maybe_skip_whitespace_tokens();\n            }\n            else\n            {\n                _c4dbgp(\"seqblck[RNXT]: start doc\");\n                _start_doc_suddenly();\n                _line_progressed(3);\n                _maybe_skip_whitespace_tokens();\n                goto seqblck_finish;\n            }\n        }\n        else if(first == ':')\n        {\n            // This happens for example in `- [a: b]: c` (after\n            // terminating the seq, ie, after `]`). All other cases\n            // (ie colon after scalars) are caught elsewhere (ie, in\n            // RVAL state).\n            auto const *C4_RESTRICT prev_state = m_evt_handler->m_parent;\n            if(C4_LIKELY(prev_state && (prev_state->flags & RMAP)))\n            {\n                _c4dbgp(\"seqblck[RNXT]: actually this seq was '?' key of parent map\");\n                m_evt_handler->end_seq();\n                goto seqblck_finish;\n            }\n            else\n            {\n                _c4err(\"parse error\");\n            }\n        }\n        else if(first == '.')\n        {\n            _c4dbgp(\"seqblck[RNXT]: maybe doc?\");\n            csubstr rs = rem.sub(1);\n            if(rs == \"..\" || rs.begins_with(\".. \"))\n            {\n                _c4dbgp(\"seqblck[RNXT]: end+start doc\");\n                _end_doc_suddenly();\n                _line_progressed(3);\n                _maybe_skip_whitespace_tokens();\n                goto seqblck_finish;\n            }\n            else\n            {\n                _c4err(\"parse error\");\n            }\n        }\n        else\n        {\n            // may be an indentless sequence nested in a map...\n            //if(m_evt_handler->m_stack.size() >= 2)\n            #ifdef RYML_DBG\n            char flagbuf_[128];\n            for(auto const& s : m_evt_handler->m_stack)\n            {\n                _dbg_printf(\"state[{}]: ind={} node={} flags={}\\n\", s.level, s.indref, s.node_id, detail::_parser_flags_to_str(flagbuf_, s.flags));\n            }\n            #endif\n            if(m_evt_handler->m_parent && has_all(RMAP|BLCK, m_evt_handler->m_parent) && m_evt_handler->m_curr->indref == m_evt_handler->m_parent->indref)\n            {\n                _c4dbgpf(\"seqblck[RNXT]: end indentless seq, go to parent={}. node={}\", m_evt_handler->m_parent->node_id, m_evt_handler->m_curr->node_id);\n                _RYML_CB_ASSERT(this->callbacks(), m_evt_handler->m_curr != m_evt_handler->m_parent);\n                _handle_indentation_pop(m_evt_handler->m_parent);\n                _RYML_CB_ASSERT(this->callbacks(), has_all(RMAP|BLCK));\n                m_evt_handler->add_sibling();\n                addrem_flags(RKEY, RNXT);\n                goto seqblck_finish;\n            }\n            else //if(first != '*')\n            {\n                _c4err(\"parse error\");\n            }\n        }\n    }\n\n seqblck_again:\n    _c4dbgt(\"seqblck: go again\", 0);\n    if(_finished_line())\n    {\n        _line_ended();\n        _scan_line();\n        if(_finished_file())\n        {\n            _c4dbgp(\"seqblck: finish!\");\n            _end_seq_blck();\n            goto seqblck_finish;\n        }\n        _c4dbgnextline();\n    }\n    goto seqblck_start;\n\n seqblck_finish:\n    _c4dbgp(\"seqblck: finish\");\n}\n\n\n//-----------------------------------------------------------------------------\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_handle_map_block()\n{\nmapblck_start:\n    _c4dbgpf(\"handle2_map_block: map_id={} node_id={} level={} indref={}\", m_evt_handler->m_parent->node_id, m_evt_handler->m_curr->node_id, m_evt_handler->m_curr->level, m_evt_handler->m_curr->indref);\n\n    // states: RKEY|QMRK -> RKCL -> RVAL -> RNXT\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_all(RMAP));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_all(BLCK));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_any(RKEY|RKCL|RVAL|RNXT|QMRK));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, 1 == (has_any(RKEY) + has_any(RKCL) + has_any(RVAL) + has_any(RNXT) + has_any(QMRK)));\n\n    _maybe_skip_comment();\n    csubstr rem = m_evt_handler->m_curr->line_contents.rem;\n    if(!rem.len)\n        goto mapblck_again;\n\n    if(has_any(RKEY))\n    {\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RKCL));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(QMRK));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RVAL));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RNXT));\n        //\n        // handle indentation\n        //\n        if(m_evt_handler->m_curr->at_line_beginning())\n        {\n            if(m_evt_handler->m_curr->indentation_eq())\n            {\n                _c4dbgpf(\"mapblck[RKEY]: skip {} from indref\", m_evt_handler->m_curr->indref);\n                _line_progressed(m_evt_handler->m_curr->indref);\n                rem = m_evt_handler->m_curr->line_contents.rem;\n                if(!rem.len)\n                    goto mapblck_again;\n            }\n            else if(m_evt_handler->m_curr->indentation_lt())\n            {\n                _c4dbgp(\"mapblck[RKEY]: smaller indentation!\");\n                _handle_indentation_pop_from_block_map();\n                _line_progressed(m_evt_handler->m_curr->line_contents.indentation);\n                if(has_all(RMAP|BLCK))\n                {\n                    _c4dbgp(\"mapblck[RKEY]: still mapblck!\");\n                    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_any(RKEY));\n                    rem = m_evt_handler->m_curr->line_contents.rem;\n                    if(!rem.len)\n                        goto mapblck_again;\n                }\n                else\n                {\n                    _c4dbgp(\"mapblck[RKEY]: no longer mapblck!\");\n                    goto mapblck_finish;\n                }\n            }\n            else\n            {\n                _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, m_evt_handler->m_curr->indentation_gt());\n                _c4err(\"invalid indentation\");\n            }\n        }\n        //\n        // now handle the tokens\n        //\n        const char first = rem.str[0];\n        const size_t startline = m_evt_handler->m_curr->pos.line;\n        const size_t startindent = m_evt_handler->m_curr->line_contents.current_col();\n        _c4dbgpf(\"mapblck[RKEY]: '{}'\", first);\n        ScannedScalar sc;\n        if(first == '\\'')\n        {\n            _c4dbgp(\"mapblck[RKEY]: scanning single-quoted scalar\");\n            sc = _scan_scalar_squot();\n            csubstr maybe_filtered = _maybe_filter_val_scalar_squot(sc);\n            _handle_annotations_before_blck_key_scalar();\n            m_evt_handler->set_key_scalar_squoted(maybe_filtered);\n            addrem_flags(RVAL, RKEY);\n            if(!_maybe_scan_following_colon())\n                _c4err(\"could not find ':' colon after key\");\n            _maybe_skip_whitespace_tokens();\n        }\n        else if(first == '\"')\n        {\n            _c4dbgp(\"mapblck[RKEY]: scanning double-quoted scalar\");\n            sc = _scan_scalar_dquot();\n            csubstr maybe_filtered = _maybe_filter_val_scalar_dquot(sc);\n            _handle_annotations_before_blck_key_scalar();\n            m_evt_handler->set_key_scalar_dquoted(maybe_filtered);\n            addrem_flags(RVAL, RKEY);\n            if(!_maybe_scan_following_colon())\n                _c4err(\"could not find ':' colon after key\");\n            _maybe_skip_whitespace_tokens();\n        }\n        // block scalars (| and >) can not be used as keys unless they\n        // appear in an explicit QMRK scope (ie, after the ? token),\n        else if(C4_UNLIKELY(first == '|'))\n        {\n            _c4err(\"block literal keys must be enclosed in '?'\");\n        }\n        else if(C4_UNLIKELY(first == '>'))\n        {\n            _c4err(\"block literal keys must be enclosed in '?'\");\n        }\n        else if(_scan_scalar_plain_map_blck(&sc))\n        {\n            _c4dbgp(\"mapblck[RKEY]: plain scalar\");\n            csubstr maybe_filtered = _maybe_filter_val_scalar_plain(sc, m_evt_handler->m_curr->indref);\n            _handle_annotations_before_blck_key_scalar();\n            m_evt_handler->set_key_scalar_plain(maybe_filtered);\n            addrem_flags(RVAL, RKEY);\n            if(!_maybe_scan_following_colon())\n                _c4err(\"could not find ':' colon after key\");\n            _maybe_skip_whitespace_tokens();\n        }\n        else if(first == '?')\n        {\n            _c4dbgp(\"mapblck[RKEY]: key token!\");\n            addrem_flags(QMRK, RKEY);\n            _line_progressed(1);\n            _maybe_skip_whitespace_tokens();\n            m_was_inside_qmrk = true;\n            goto mapblck_again;\n        }\n        else if(first == ':')\n        {\n            _c4dbgp(\"mapblck[RKEY]: setting empty key\");\n            _handle_annotations_before_blck_key_scalar();\n            m_evt_handler->set_key_scalar_plain({});\n            addrem_flags(RVAL, RKEY);\n            _line_progressed(1);\n            _maybe_skip_whitespace_tokens();\n        }\n        else if(first == '*')\n        {\n            csubstr ref = _scan_ref_map();\n            _c4dbgpf(\"mapblck[RKEY]: key ref! [{}]~~~{}~~~\", ref.len, ref);\n            _handle_annotations_before_blck_key_scalar();\n            m_evt_handler->set_key_ref(ref);\n            addrem_flags(RVAL, RKEY);\n            if(!_maybe_scan_following_colon())\n                _c4err(\"could not find ':' colon after key\");\n            _maybe_skip_whitespace_tokens();\n        }\n        else if(first == '&')\n        {\n            csubstr anchor = _scan_anchor();\n            _c4dbgpf(\"mapblck[RKEY]: key anchor! [{}]~~~{}~~~\", anchor.len, anchor);\n            _add_annotation(&m_pending_anchors, anchor, startindent, startline);\n        }\n        else if(first == '!')\n        {\n            csubstr tag = _scan_tag();\n            _c4dbgpf(\"mapblck[RKEY]: key tag! [{}]~~~{}~~~\", tag.len, tag);\n            _add_annotation(&m_pending_tags, tag, startindent, startline);\n        }\n        else if(first == '[')\n        {\n            // RYML's tree cannot store container keys, but that's\n            // handled inside the tree handler. Other handlers may be\n            // able to handle it.\n            _c4dbgp(\"mapblck[RKEY]: start child seqflow (!)\");\n            addrem_flags(RKCL, RKEY);\n            _handle_annotations_before_blck_key_scalar();\n            m_evt_handler->begin_seq_key_flow();\n            addrem_flags(RSEQ|FLOW|RVAL, RMAP|BLCK|RKCL);\n            _line_progressed(1);\n            _set_indentation(startindent);\n            goto mapblck_finish;\n        }\n        else if(first == '{')\n        {\n            // RYML's tree cannot store container keys, but that's\n            // handled inside the tree handler. Other handlers may be\n            // able to handle it.\n            _c4dbgp(\"mapblck[RKEY]: start child mapflow (!)\");\n            addrem_flags(RKCL, RKEY);\n            _handle_annotations_before_blck_key_scalar();\n            m_evt_handler->begin_map_key_flow();\n            addrem_flags(FLOW|RKEY, BLCK|RKCL);\n            _line_progressed(1);\n            _set_indentation(startindent);\n            goto mapblck_finish;\n        }\n        else if(first == '-')\n        {\n            _c4dbgp(\"mapblck[RKEY]: maybe doc?\");\n            if(m_evt_handler->m_curr->line_contents.indentation == 0 && _is_doc_begin_token(rem))\n            {\n                _c4dbgp(\"mapblck[RKEY]: end+start doc\");\n                _start_doc_suddenly();\n                _line_progressed(3);\n                _maybe_skip_whitespace_tokens();\n                goto mapblck_finish;\n            }\n            else\n            {\n                _c4err(\"parse error\");\n            }\n        }\n        else if(first == '.')\n        {\n            _c4dbgp(\"mapblck[RKEY]: maybe end doc?\");\n            if(m_evt_handler->m_curr->line_contents.indentation == 0 && _is_doc_end_token(rem))\n            {\n                _c4dbgp(\"mapblck[RKEY]: end doc\");\n                _end_doc_suddenly();\n                _line_progressed(3);\n                _maybe_skip_whitespace_tokens();\n                goto mapblck_finish;\n            }\n            else\n            {\n                _c4err(\"parse error\");\n            }\n        }\n       _RYML_WITH_TAB_TOKENS(\n        else if(first == '\\t')\n        {\n            _c4dbgp(\"mapblck[RKEY]: skip tabs\");\n            _maybe_skipchars('\\t');\n        })\n        else\n        {\n            _c4err(\"parse error\");\n        }\n    }\n    else if(has_any(RKCL)) // read the key colon\n    {\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RKEY));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RVAL));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RNXT));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(QMRK));\n        //\n        // handle indentation\n        //\n        if(m_evt_handler->m_curr->at_line_beginning())\n        {\n            if(m_evt_handler->m_curr->indentation_eq())\n            {\n                _c4dbgpf(\"mapblck[RKCL]: skip {} from indref\", m_evt_handler->m_curr->indref);\n                _line_progressed(m_evt_handler->m_curr->indref);\n                rem = m_evt_handler->m_curr->line_contents.rem;\n                if(!rem.len)\n                    goto mapblck_again;\n            }\n            else if(C4_UNLIKELY(m_evt_handler->m_curr->indentation_lt()))\n            {\n                _c4err(\"invalid indentation\");\n            }\n        }\n        const char first = rem.str[0];\n        _c4dbgpf(\"mapblck[RKCL]: '{}'\", first);\n        if(first == ':')\n        {\n            _c4dbgp(\"mapblck[RKCL]: found the colon\");\n            addrem_flags(RVAL, RKCL);\n            _line_progressed(1);\n            _maybe_skip_whitespace_tokens();\n        }\n        else if(first == '?')\n        {\n            _c4dbgp(\"mapblck[RKCL]: got '?'. val was empty\");\n            _RYML_CB_CHECK(m_evt_handler->m_stack.m_callbacks, m_was_inside_qmrk);\n            m_evt_handler->set_val_scalar_plain({});\n            m_evt_handler->add_sibling();\n            addrem_flags(QMRK, RKCL);\n            _line_progressed(1);\n            _maybe_skip_whitespace_tokens();\n        }\n        else if(first == '-')\n        {\n            if(m_evt_handler->m_curr->indref == 0 || m_evt_handler->m_curr->line_contents.indentation == 0 || _is_doc_begin_token(rem))\n            {\n                _c4dbgp(\"mapblck[RKCL]: end+start doc\");\n                _RYML_CB_CHECK(m_evt_handler->m_stack.m_callbacks, _is_doc_begin_token(rem));\n                _start_doc_suddenly();\n                _line_progressed(3);\n                _maybe_skip_whitespace_tokens();\n                goto mapblck_finish;\n            }\n            else\n            {\n                _c4err(\"parse error\");\n            }\n        }\n        else if(first == '.')\n        {\n            _c4dbgp(\"mapblck[RKCL]: maybe end doc?\");\n            csubstr rs = rem.sub(1);\n            if(rs == \"..\" || rs.begins_with(\".. \"))\n            {\n                _c4dbgp(\"mapblck[RKCL]: end+start doc\");\n                _end_doc_suddenly();\n                _line_progressed(3);\n                goto mapblck_finish;\n            }\n            else\n            {\n                _c4err(\"parse error\");\n            }\n        }\n        else if(m_was_inside_qmrk)\n        {\n            _RYML_CB_CHECK(m_evt_handler->m_stack.m_callbacks, m_evt_handler->m_curr->indentation_eq());\n            _c4dbgp(\"mapblck[RKCL]: missing :\");\n            m_evt_handler->set_val_scalar_plain({});\n            m_evt_handler->add_sibling();\n            m_was_inside_qmrk = false;\n            addrem_flags(RKEY, RKCL);\n        }\n        else\n        {\n            _c4err(\"parse error\");\n        }\n    }\n    else if(has_any(RVAL))\n    {\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RKEY));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RKCL));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RNXT));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(QMRK));\n        //\n        // handle indentation\n        //\n        if(m_evt_handler->m_curr->at_line_beginning())\n        {\n            _c4dbgpf(\"mapblck[RVAL]: indref={} indentation={}\", m_evt_handler->m_curr->indref, m_evt_handler->m_curr->line_contents.indentation);\n            m_evt_handler->m_curr->more_indented = false;\n            if(m_evt_handler->m_curr->indref == npos)\n            {\n                _c4dbgpf(\"mapblck[RVAL]: setting indentation={}\", m_evt_handler->m_parent->indref);\n                _set_indentation(m_evt_handler->m_curr->line_contents.indentation);\n                _line_progressed(m_evt_handler->m_curr->indref);\n                rem = m_evt_handler->m_curr->line_contents.rem;\n                if(!rem.len)\n                    goto mapblck_again;\n            }\n            else if(m_evt_handler->m_curr->indentation_eq())\n            {\n                _c4dbgp(\"mapblck[RVAL]: skip indentation!\");\n                _line_progressed(m_evt_handler->m_curr->indref);\n                rem = m_evt_handler->m_curr->line_contents.rem;\n                if(!rem.len)\n                    goto mapblck_again;\n                // TODO: this is valid:\n                //\n                // ```yaml\n                // a:\n                // b:\n                // ---\n                // a:\n                //  b\n                // ---\n                // a:\n                //  b: c\n                // ```\n                //\n                // ... but this is not:\n                //\n                // ```yaml\n                // a:\n                // v\n                // ---\n                // a: b: c\n                // ```\n                //\n                // here, we probably need to set a boolean on the state\n                // to disambiguate between these cases.\n            }\n            else if(m_evt_handler->m_curr->indentation_gt())\n            {\n                _c4dbgp(\"mapblck[RVAL]: more indented!\");\n                m_evt_handler->m_curr->more_indented = true;\n                _line_progressed(m_evt_handler->m_curr->line_contents.indentation);\n                rem = m_evt_handler->m_curr->line_contents.rem;\n                if(!rem.len)\n                    goto mapblck_again;\n            }\n            else if(m_evt_handler->m_curr->indentation_lt())\n            {\n                _c4dbgp(\"mapblck[RVAL]: smaller indentation!\");\n                _handle_indentation_pop_from_block_map();\n                if(has_all(RMAP|BLCK))\n                {\n                    _c4dbgp(\"mapblck[RVAL]: still mapblck!\");\n                    _line_progressed(m_evt_handler->m_curr->line_contents.indentation);\n                    if(has_any(RNXT))\n                    {\n                        _c4dbgp(\"mapblck[RVAL]: speculatively expect next keyval\");\n                        m_evt_handler->add_sibling();\n                        addrem_flags(RKEY, RNXT);\n                    }\n                    goto mapblck_again;\n                }\n                else\n                {\n                    _c4dbgp(\"mapblck[RVAL]: no longer mapblck!\");\n                    goto mapblck_finish;\n                }\n            }\n            else if(m_evt_handler->m_curr->line_contents.indentation == npos)\n            {\n                _c4dbgp(\"mapblck[RVAL]: empty line!\");\n                _line_progressed(m_evt_handler->m_curr->line_contents.rem.len);\n                goto mapblck_again;\n            }\n        }\n        //\n        // now handle the tokens\n        //\n        const char first = rem.str[0];\n        const size_t startline = m_evt_handler->m_curr->pos.line;\n        const size_t startindent = m_evt_handler->m_curr->line_contents.current_col();\n        _c4dbgpf(\"mapblck[RVAL]: '{}'\", first);\n        ScannedScalar sc;\n        if(first == '\\'')\n        {\n            _c4dbgp(\"mapblck[RVAL]: scanning single-quoted scalar\");\n            sc = _scan_scalar_squot();\n            if(!_maybe_scan_following_colon())\n            {\n                _c4dbgp(\"mapblck[RVAL]: set as val\");\n                _handle_annotations_before_blck_val_scalar();\n                csubstr maybe_filtered = _maybe_filter_val_scalar_squot(sc); // VAL!\n                m_evt_handler->set_val_scalar_squoted(maybe_filtered);\n                addrem_flags(RNXT, RVAL);\n            }\n            else\n            {\n                if(startindent != m_evt_handler->m_curr->indref)\n                {\n                    _c4dbgp(\"mapblck[RVAL]: start new block map, set scalar as key\");\n                    _handle_annotations_before_start_mapblck(startline);\n                    addrem_flags(RNXT, RVAL);\n                    m_evt_handler->begin_map_val_block();\n                    _handle_annotations_and_indentation_after_start_mapblck(startindent, startline);\n                    csubstr maybe_filtered = _maybe_filter_key_scalar_squot(sc); // KEY!\n                    m_evt_handler->set_key_scalar_squoted(maybe_filtered);\n                    _maybe_skip_whitespace_tokens();\n                    _set_indentation(m_evt_handler->m_curr->line_contents.indentation);\n                    // keep the child state on RVAL\n                    addrem_flags(RVAL, RNXT);\n                }\n                else\n                {\n                    _c4dbgp(\"mapblck[RVAL]: prev val empty+this is a key\");\n                    m_evt_handler->set_val_scalar_plain({});\n                    m_evt_handler->add_sibling();\n                    csubstr maybe_filtered = _maybe_filter_key_scalar_squot(sc); // KEY!\n                    m_evt_handler->set_key_scalar_squoted(maybe_filtered);\n                    // keep going on RVAL\n                    _maybe_skip_whitespace_tokens();\n                }\n            }\n        }\n        else if(first == '\"')\n        {\n            _c4dbgp(\"mapblck[RVAL]: scanning double-quoted scalar\");\n            sc = _scan_scalar_dquot();\n            if(!_maybe_scan_following_colon())\n            {\n                _c4dbgp(\"mapblck[RVAL]: set as val\");\n                _handle_annotations_before_blck_val_scalar();\n                csubstr maybe_filtered = _maybe_filter_val_scalar_dquot(sc); // VAL!\n                m_evt_handler->set_val_scalar_dquoted(maybe_filtered);\n                addrem_flags(RNXT, RVAL);\n            }\n            else\n            {\n                if(startindent != m_evt_handler->m_curr->indref)\n                {\n                    _c4dbgp(\"mapblck[RVAL]: start new block map, set scalar as key\");\n                    _handle_annotations_before_start_mapblck(startline);\n                    addrem_flags(RNXT, RVAL);\n                    m_evt_handler->begin_map_val_block();\n                    _handle_annotations_and_indentation_after_start_mapblck(startindent, startline);\n                    csubstr maybe_filtered = _maybe_filter_key_scalar_dquot(sc); // KEY!\n                    m_evt_handler->set_key_scalar_dquoted(maybe_filtered);\n                    _maybe_skip_whitespace_tokens();\n                    _set_indentation(m_evt_handler->m_curr->line_contents.indentation);\n                    // keep the child state on RVAL\n                    addrem_flags(RVAL, RNXT);\n                }\n                else\n                {\n                    _c4dbgp(\"mapblck[RVAL]: prev val empty+this is a key\");\n                    m_evt_handler->set_val_scalar_plain({});\n                    m_evt_handler->add_sibling();\n                    csubstr maybe_filtered = _maybe_filter_key_scalar_dquot(sc); // KEY!\n                    m_evt_handler->set_key_scalar_dquoted(maybe_filtered);\n                    // keep going on RVAL\n                    _maybe_skip_whitespace_tokens();\n                }\n            }\n        }\n        // block scalars can only appear as keys when in QMRK scope\n        // (ie, after ? tokens), so no need to scan following colon\n        else if(first == '|')\n        {\n            _c4dbgp(\"mapblck[RVAL]: scanning block-literal scalar\");\n            ScannedBlock sb;\n            _scan_block(&sb, m_evt_handler->m_curr->indref + 1);\n            _handle_annotations_before_blck_val_scalar();\n            csubstr maybe_filtered = _maybe_filter_val_scalar_literal(sb);\n            m_evt_handler->set_val_scalar_literal(maybe_filtered);\n            addrem_flags(RNXT, RVAL);\n        }\n        else if(first == '>')\n        {\n            _c4dbgp(\"mapblck[RVAL]: scanning block-folded scalar\");\n            ScannedBlock sb;\n            _scan_block(&sb, m_evt_handler->m_curr->indref + 1);\n            _handle_annotations_before_blck_val_scalar();\n            csubstr maybe_filtered = _maybe_filter_val_scalar_folded(sb);\n            m_evt_handler->set_val_scalar_folded(maybe_filtered);\n            addrem_flags(RNXT, RVAL);\n        }\n        else if(_scan_scalar_plain_map_blck(&sc))\n        {\n            _c4dbgp(\"mapblck[RVAL]: plain scalar.\");\n            if(!_maybe_scan_following_colon())\n            {\n                _c4dbgp(\"mapblck[RVAL]: set as val\");\n                _handle_annotations_before_blck_val_scalar();\n                csubstr maybe_filtered = _maybe_filter_val_scalar_plain(sc, m_evt_handler->m_curr->indref); // VAL!\n                m_evt_handler->set_val_scalar_plain(maybe_filtered);\n                addrem_flags(RNXT, RVAL);\n            }\n            else\n            {\n                if(startindent != m_evt_handler->m_curr->indref)\n                {\n                    _c4dbgpf(\"mapblck[RVAL]: start new block map, set scalar as key {}\", m_evt_handler->m_curr->indref);\n                    addrem_flags(RNXT, RVAL);\n                    _handle_annotations_before_start_mapblck(startline);\n                    m_evt_handler->begin_map_val_block();\n                    _handle_annotations_and_indentation_after_start_mapblck(startindent, startline);\n                    csubstr maybe_filtered = _maybe_filter_key_scalar_plain(sc, m_evt_handler->m_curr->indref); // KEY!\n                    m_evt_handler->set_key_scalar_plain(maybe_filtered);\n                    _maybe_skip_whitespace_tokens();\n                    _set_indentation(m_evt_handler->m_curr->line_contents.indentation);\n                    // keep the child state on RVAL\n                    addrem_flags(RVAL, RNXT);\n                }\n                else\n                {\n                    _c4dbgp(\"mapblck[RVAL]: prev val empty+this is a key\");\n                    _handle_annotations_before_blck_val_scalar();\n                    m_evt_handler->set_val_scalar_plain({});\n                    m_evt_handler->add_sibling();\n                    csubstr maybe_filtered = _maybe_filter_key_scalar_plain(sc, m_evt_handler->m_curr->indref); // KEY!\n                    m_evt_handler->set_key_scalar_plain(maybe_filtered);\n                    // keep going on RVAL\n                    _maybe_skip_whitespace_tokens();\n                }\n            }\n        }\n        else if(first == '-')\n        {\n            if(rem.len == 1 || rem.str[1] == ' ' _RYML_WITH_TAB_TOKENS(|| rem.str[1] == '\\t'))\n            {\n                _c4dbgp(\"mapblck[RVAL]: start val seqblck\");\n                addrem_flags(RNXT, RVAL);\n                _handle_annotations_before_blck_val_scalar();\n                m_evt_handler->begin_seq_val_block();\n                addrem_flags(RSEQ|RVAL, RMAP|RNXT);\n                _set_indentation(startindent);\n                _line_progressed(1);\n                _maybe_skip_whitespace_tokens();\n                goto mapblck_finish;\n            }\n            else if(m_evt_handler->m_curr->indref == 0 || m_evt_handler->m_curr->line_contents.indentation == 0 || _is_doc_begin_token(rem))\n            {\n                _c4dbgp(\"mapblck[RVAL]: end+start doc\");\n                _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, _is_doc_begin_token(rem));\n                _start_doc_suddenly();\n                _line_progressed(3);\n                _maybe_skip_whitespace_tokens();\n                goto mapblck_finish;\n            }\n            else\n            {\n                _c4err(\"parse error\");\n            }\n        }\n        else if(first == '[')\n        {\n            _c4dbgp(\"mapblck[RVAL]: start val seqflow\");\n            addrem_flags(RNXT, RVAL);\n            _handle_annotations_before_blck_val_scalar();\n            m_evt_handler->begin_seq_val_flow();\n            addrem_flags(RSEQ|FLOW|RVAL, RMAP|BLCK|RNXT|BLCK);\n            _set_indentation(m_evt_handler->m_curr->indref + 1u);\n            _line_progressed(1);\n            goto mapblck_finish;\n        }\n        else if(first == '{')\n        {\n            _c4dbgp(\"mapblck[RVAL]: start val mapflow\");\n            addrem_flags(RNXT, RVAL);\n            _handle_annotations_before_blck_val_scalar();\n            m_evt_handler->begin_map_val_flow();\n            addrem_flags(RKEY|FLOW, BLCK|RVAL|RNXT);\n            m_evt_handler->m_curr->scalar_col = m_evt_handler->m_curr->line_contents.indentation;\n            _set_indentation(m_evt_handler->m_curr->indref + 1u);\n            _line_progressed(1);\n            goto mapblck_finish;\n        }\n        else if(first == '*')\n        {\n            csubstr ref = _scan_ref_map();\n            _c4dbgpf(\"mapblck[RVAL]: ref! [{}]~~~{}~~~\", ref.len, ref);\n            if(startindent == m_evt_handler->m_curr->indref)\n            {\n                _c4dbgpf(\"mapblck[RVAL]: same indentation {}\", startindent);\n                m_evt_handler->set_val_ref(ref);\n                addrem_flags(RNXT, RVAL);\n            }\n            else\n            {\n                _c4dbgpf(\"mapblck[RVAL]: larger indentation {}>{}\", startindent, m_evt_handler->m_curr->indref);\n                _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, startindent > m_evt_handler->m_curr->indref);\n                if(_maybe_scan_following_colon())\n                {\n                    _c4dbgp(\"mapblck[RVAL]: start child map, block\");\n                    addrem_flags(RNXT, RVAL);\n                    _handle_annotations_before_blck_val_scalar();\n                    m_evt_handler->begin_map_val_block();\n                    m_evt_handler->set_key_ref(ref);\n                    _set_indentation(startindent);\n                    // keep going in RVAL\n                    addrem_flags(RVAL, RNXT);\n                }\n                else\n                {\n                    _c4dbgp(\"mapblck[RVAL]: was val ref\");\n                    _handle_annotations_before_blck_val_scalar();\n                    m_evt_handler->set_val_ref(ref);\n                    addrem_flags(RNXT, RVAL);\n                }\n            }\n            _maybe_skip_whitespace_tokens();\n        }\n        else if(first == '&')\n        {\n            csubstr anchor = _scan_anchor();\n            _c4dbgpf(\"mapblck[RVAL]: anchor! [{}]~~~{}~~~\", anchor.len, anchor);\n            if(startindent == m_evt_handler->m_curr->indref)\n            {\n                _c4dbgp(\"mapblck[RVAL]: anchor for next key. val is missing!\");\n                m_evt_handler->set_val_scalar_plain({});\n                m_evt_handler->add_sibling();\n                addrem_flags(RKEY, RVAL);\n            }\n            // we need to buffer the anchors, as there may be two\n            // consecutive anchors in here\n            _add_annotation(&m_pending_anchors, anchor, startindent, startline);\n        }\n        else if(first == '!')\n        {\n            csubstr tag = _scan_tag();\n            _c4dbgpf(\"mapblck[RVAL]: tag! [{}]~~~{}~~~\", tag.len, tag);\n            if(startindent == m_evt_handler->m_curr->indref)\n            {\n                _c4dbgp(\"mapblck[RVAL]: tag for next key. val is missing!\");\n                _handle_annotations_before_blck_val_scalar();\n                m_evt_handler->set_val_scalar_plain({});\n                m_evt_handler->add_sibling();\n                addrem_flags(RKEY, RVAL);\n            }\n            // we need to buffer the tags, as there may be two\n            // consecutive tags in here\n            _add_annotation(&m_pending_tags, tag, startindent, startline);\n        }\n        else if(first == '?')\n        {\n            if(startindent == m_evt_handler->m_curr->indref)\n            {\n                _c4dbgp(\"mapblck[RVAL]: got '?'. val was empty\");\n                _handle_annotations_before_blck_val_scalar();\n                m_evt_handler->set_val_scalar_plain({});\n                m_evt_handler->add_sibling();\n                addrem_flags(QMRK, RVAL);\n            }\n            else if(startindent > m_evt_handler->m_curr->indref)\n            {\n                _c4dbgp(\"mapblck[RVAL]: start val mapblck\");\n                addrem_flags(RNXT, RVAL);\n                _handle_annotations_before_blck_val_scalar();\n                m_evt_handler->begin_map_val_block();\n                addrem_flags(QMRK|BLCK, RNXT);\n                _set_indentation(startindent);\n            }\n            else\n            {\n                _c4err(\"parse error\");\n            }\n            m_was_inside_qmrk = true;\n            _line_progressed(1);\n            _maybe_skip_whitespace_tokens();\n            goto mapblck_again;\n        }\n        else if(first == ':')\n        {\n            if(startindent == m_evt_handler->m_curr->indref)\n            {\n                _c4dbgp(\"mapblck[RVAL]: got ':'. val was empty, next key as well\");\n                m_evt_handler->set_val_scalar_plain({});\n                m_evt_handler->add_sibling();\n                m_evt_handler->set_key_scalar_plain({});\n                _line_progressed(1);\n                _maybe_skip_whitespace_tokens();\n                goto mapblck_again;\n            }\n            else\n            {\n                _c4err(\"parse error\");\n            }\n        }\n        else if(first == '.')\n        {\n            _c4dbgp(\"mapblck[RVAL]: maybe doc?\");\n            csubstr rs = rem.sub(1);\n            if(rs == \"..\" || rs.begins_with(\".. \"))\n            {\n                _c4dbgp(\"seqblck[RVAL]: end doc expl\");\n                _end_doc_suddenly();\n                _line_progressed(3);\n                _maybe_skip_whitespace_tokens();\n                goto mapblck_finish;\n            }\n            else\n            {\n                _c4err(\"parse error\");\n            }\n        }\n       _RYML_WITH_TAB_TOKENS(\n        else if(first == '\\t')\n        {\n            _c4dbgp(\"mapblck[RVAL]: skip tabs\");\n            _maybe_skipchars('\\t');\n        })\n        else\n        {\n            _c4err(\"parse error\");\n        }\n    }\n    else if(has_any(RNXT))\n    {\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RKEY));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RKCL));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RVAL));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(QMRK));\n        //\n        // handle indentation\n        //\n        if(m_evt_handler->m_curr->at_line_beginning())\n        {\n            _c4dbgpf(\"mapblck[RNXT]: indref={} indentation={}\", m_evt_handler->m_curr->indref, m_evt_handler->m_curr->line_contents.indentation);\n            if(m_evt_handler->m_curr->indentation_eq())\n            {\n                _c4dbgpf(\"mapblck[RNXT]: skip {} from indref\", m_evt_handler->m_curr->indref);\n                _line_progressed(m_evt_handler->m_curr->indref);\n                _c4dbgp(\"mapblck[RNXT]: speculatively expect next keyval\");\n                m_evt_handler->add_sibling();\n                addrem_flags(RKEY, RNXT);\n                goto mapblck_again;\n            }\n            else if(m_evt_handler->m_curr->indentation_lt())\n            {\n                _c4dbgp(\"mapblck[RNXT]: smaller indentation!\");\n                _handle_indentation_pop_from_block_map();\n                if(has_all(RMAP|BLCK))\n                {\n                    _line_progressed(m_evt_handler->m_curr->line_contents.indentation);\n                    if(!has_any(RKCL))\n                    {\n                        _c4dbgp(\"mapblck[RNXT]: speculatively expect next keyval\");\n                        m_evt_handler->add_sibling();\n                        addrem_flags(RKEY, RNXT);\n                    }\n                    goto mapblck_again;\n                }\n                else\n                {\n                    goto mapblck_finish;\n                }\n            }\n        }\n        //\n        // handle tokens\n        //\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, rem.len > 0);\n        const char first = rem.str[0];\n        _c4dbgpf(\"mapblck[RNXT]: '{}'\", _c4prc(first));\n        if(first == ':')\n        {\n            if(m_evt_handler->m_curr->more_indented)\n            {\n                _c4dbgp(\"mapblck[RNXT]: start child block map\");\n                C4_NOT_IMPLEMENTED();\n                //m_evt_handler->actually_as_block_map();\n                _line_progressed(1);\n                _set_indentation(m_evt_handler->m_curr->scalar_col);\n                m_evt_handler->m_curr->more_indented = false;\n                goto mapblck_again;\n            }\n            else\n            {\n                _c4err(\"parse error\");\n            }\n        }\n        else if(first == ' ')\n        {\n            _c4dbgp(\"mapblck[RNXT]: skip spaces\");\n            _maybe_skip_whitespace_tokens();\n        }\n        else\n        {\n            _c4err(\"parse error\");\n        }\n    }\n    else if(has_any(QMRK))\n    {\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RKEY));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RKCL));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RVAL));\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RNXT));\n        //\n        // handle indentation\n        //\n        if(m_evt_handler->m_curr->at_line_beginning())\n        {\n            _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, m_evt_handler->m_curr->line_contents.indentation != npos);\n            if(m_evt_handler->m_curr->indentation_eq())\n            {\n                _c4dbgpf(\"mapblck[QMRK]: skip {} from indref\", m_evt_handler->m_curr->indref);\n                _line_progressed(m_evt_handler->m_curr->indref);\n                rem = m_evt_handler->m_curr->line_contents.rem;\n                if(!rem.len)\n                    goto mapblck_again;\n            }\n            else if(m_evt_handler->m_curr->indentation_lt())\n            {\n                _c4dbgp(\"mapblck[QMRK]: smaller indentation!\");\n                _handle_indentation_pop_from_block_map();\n                _line_progressed(m_evt_handler->m_curr->line_contents.indentation);\n                if(has_all(RMAP|BLCK))\n                {\n                    _c4dbgp(\"mapblck[QMRK]: still mapblck!\");\n                    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_any(QMRK));\n                    rem = m_evt_handler->m_curr->line_contents.rem;\n                    if(!rem.len)\n                        goto mapblck_again;\n                }\n                else\n                {\n                    _c4dbgp(\"mapblck[QMRK]: no longer mapblck!\");\n                    goto mapblck_finish;\n                }\n            }\n            // indentation can be larger in QMRK state\n            else\n            {\n                _c4dbgp(\"mapblck[QMRK]: larger indentation !\");\n                _line_progressed(m_evt_handler->m_curr->line_contents.indentation);\n                rem = m_evt_handler->m_curr->line_contents.rem;\n                if(!rem.len)\n                    goto mapblck_again;\n            }\n        }\n        //\n        // now handle the tokens\n        //\n        const char first = rem.str[0];\n        const size_t startline = m_evt_handler->m_curr->pos.line;\n        const size_t startindent = m_evt_handler->m_curr->line_contents.current_col();\n        _c4dbgpf(\"mapblck[QMRK]: '{}'\", first);\n        ScannedScalar sc;\n        if(first == '\\'')\n        {\n            _c4dbgp(\"mapblck[QMRK]: scanning single-quoted scalar\");\n            sc = _scan_scalar_squot();\n            csubstr maybe_filtered = _maybe_filter_key_scalar_squot(sc); // KEY!\n            if(!_maybe_scan_following_colon())\n            {\n                _c4dbgp(\"mapblck[QMRK]: set as key\");\n                _handle_annotations_before_blck_key_scalar();\n                m_evt_handler->set_key_scalar_squoted(maybe_filtered);\n                addrem_flags(RKCL, QMRK);\n            }\n            else\n            {\n                _c4dbgp(\"mapblck[QMRK]: start new block map as key (!), set scalar as key\");\n                addrem_flags(RKCL, QMRK);\n                _handle_annotations_before_start_mapblck_as_key();\n                m_evt_handler->begin_map_key_block();\n                _handle_annotations_and_indentation_after_start_mapblck(startindent, startline);\n                m_evt_handler->set_key_scalar_squoted(maybe_filtered);\n                _maybe_skip_whitespace_tokens();\n                _set_indentation(startindent);\n                // keep the child state on RVAL\n                addrem_flags(RVAL, RKCL|QMRK);\n            }\n        }\n        else if(first == '\"')\n        {\n            _c4dbgp(\"mapblck[QMRK]: scanning double-quoted scalar\");\n            sc = _scan_scalar_dquot();\n            csubstr maybe_filtered = _maybe_filter_key_scalar_dquot(sc); // KEY!\n            if(!_maybe_scan_following_colon())\n            {\n                _c4dbgp(\"mapblck[QMRK]: set as key\");\n                _handle_annotations_before_blck_key_scalar();\n                m_evt_handler->set_key_scalar_dquoted(maybe_filtered);\n                addrem_flags(RKCL, QMRK);\n            }\n            else\n            {\n                _c4dbgp(\"mapblck[QMRK]: start new block map as key (!), set scalar as key\");\n                addrem_flags(RKCL, QMRK);\n                _handle_annotations_before_start_mapblck_as_key();\n                m_evt_handler->begin_map_key_block();\n                _handle_annotations_and_indentation_after_start_mapblck(startindent, startline);\n                m_evt_handler->set_key_scalar_dquoted(maybe_filtered);\n                _maybe_skip_whitespace_tokens();\n                _set_indentation(startindent);\n                // keep the child state on RVAL\n                addrem_flags(RVAL, RKCL|QMRK);\n            }\n        }\n        else if(first == '|')\n        {\n            _c4dbgp(\"mapblck[QMRK]: scanning block-literal scalar\");\n            ScannedBlock sb;\n            _scan_block(&sb, m_evt_handler->m_curr->indref + 1);\n            csubstr maybe_filtered = _maybe_filter_key_scalar_literal(sb); // KEY!\n            _handle_annotations_before_blck_key_scalar();\n            m_evt_handler->set_key_scalar_literal(maybe_filtered);\n            addrem_flags(RKCL, QMRK);\n        }\n        else if(first == '>')\n        {\n            _c4dbgp(\"mapblck[QMRK]: scanning block-literal scalar\");\n            ScannedBlock sb;\n            _scan_block(&sb, m_evt_handler->m_curr->indref + 1);\n            csubstr maybe_filtered = _maybe_filter_key_scalar_folded(sb); // KEY!\n            _handle_annotations_before_blck_key_scalar();\n            m_evt_handler->set_key_scalar_folded(maybe_filtered);\n            addrem_flags(RKCL, QMRK);\n        }\n        else if(_scan_scalar_plain_map_blck(&sc))\n        {\n            _c4dbgp(\"mapblck[QMRK]: plain scalar\");\n            csubstr maybe_filtered = _maybe_filter_key_scalar_plain(sc, m_evt_handler->m_curr->indref); // KEY!\n            if(!_maybe_scan_following_colon())\n            {\n                _c4dbgp(\"mapblck[QMRK]: set as key\");\n                _handle_annotations_before_blck_key_scalar();\n                m_evt_handler->set_key_scalar_plain(maybe_filtered);\n                addrem_flags(RKCL, QMRK);\n            }\n            else\n            {\n                _c4dbgp(\"mapblck[QMRK]: start new block map as key (!), set scalar as key\");\n                addrem_flags(RKCL, QMRK);\n                _handle_annotations_before_start_mapblck_as_key();\n                m_evt_handler->begin_map_key_block();\n                _handle_annotations_and_indentation_after_start_mapblck(startindent, startline);\n                m_evt_handler->set_key_scalar_plain(maybe_filtered);\n                _maybe_skip_whitespace_tokens();\n                _set_indentation(startindent);\n                // keep the child state on RVAL\n                addrem_flags(RVAL, RKCL|QMRK);\n            }\n        }\n        else if(first == ':')\n        {\n            if(startindent == m_evt_handler->m_curr->indref)\n            {\n                _c4dbgp(\"mapblck[QMRK]: empty key\");\n                addrem_flags(RVAL, QMRK);\n                _handle_annotations_before_blck_key_scalar();\n                m_evt_handler->set_key_scalar_plain({});\n                _line_progressed(1);\n                _maybe_skip_whitespace_tokens();\n            }\n            else\n            {\n                _c4dbgp(\"mapblck[QMRK]: start new block map as key (!), empty key\");\n                addrem_flags(RKCL, QMRK);\n                _handle_annotations_before_start_mapblck_as_key();\n                m_evt_handler->begin_map_key_block();\n                _handle_annotations_and_indentation_after_start_mapblck(startindent, startline);\n                m_evt_handler->set_key_scalar_plain({});\n                _line_progressed(1);\n                _maybe_skip_whitespace_tokens();\n                _set_indentation(startindent);\n                // keep the child state on RVAL\n                addrem_flags(RVAL, RKCL|QMRK);\n            }\n        }\n        else if(first == '*')\n        {\n            csubstr ref = _scan_ref_map();\n            _c4dbgpf(\"mapblck[QMRK]: key ref! [{}]~~~{}~~~\", ref.len, ref);\n            if(!_maybe_scan_following_colon())\n            {\n                _c4dbgp(\"mapblck[QMRK]: set ref as key\");\n                _handle_annotations_before_blck_key_scalar();\n                m_evt_handler->set_key_ref(ref);\n                addrem_flags(RKCL, QMRK);\n            }\n            else\n            {\n                _c4dbgp(\"mapblck[QMRK]: start new block map as key (!), set ref as key\");\n                addrem_flags(RKCL, QMRK);\n                _handle_annotations_before_blck_key_scalar();\n                m_evt_handler->begin_map_key_block();\n                m_evt_handler->set_key_ref(ref);\n                _set_indentation(startindent);\n                // keep the child state on RVAL\n                addrem_flags(RVAL, RKCL|QMRK);\n            }\n            _maybe_skip_whitespace_tokens();\n        }\n        else if(first == '&')\n        {\n            csubstr anchor = _scan_anchor();\n            _c4dbgpf(\"mapblck[QMRK]: key anchor! [{}]~~~{}~~~\", anchor.len, anchor);\n            _add_annotation(&m_pending_anchors, anchor, startindent, startline);\n        }\n        else if(first == '!')\n        {\n            csubstr tag = _scan_tag();\n            _c4dbgpf(\"mapblck[QMRK]: key tag! [{}]~~~{}~~~\", tag.len, tag);\n            _add_annotation(&m_pending_tags, tag, startindent, startline);\n        }\n        else if(first == '-')\n        {\n            _c4dbgp(\"mapblck[QMRK]: maybe doc?\");\n            csubstr rs = rem.sub(1);\n            if(rs == \"--\" || rs.begins_with(\"-- \"))\n            {\n                _c4dbgp(\"mapblck[QMRK]: end+start doc\");\n                _start_doc_suddenly();\n                _line_progressed(3);\n            }\n            else\n            {\n                _c4dbgp(\"mapblck[QMRK]: start child seqblck (!)\");\n                addrem_flags(RKCL, RKEY|QMRK);\n                m_evt_handler->begin_seq_key_block();\n                addrem_flags(RVAL|RSEQ, RMAP|RKCL|QMRK);\n                _set_indentation(startindent);\n                _line_progressed(1);\n            }\n            _maybe_skip_whitespace_tokens();\n            goto mapblck_finish;\n        }\n        else if(first == '[')\n        {\n            _c4dbgp(\"mapblck[QMRK]: start child seqflow (!)\");\n            addrem_flags(RKCL, RKEY|QMRK);\n            m_evt_handler->begin_seq_key_flow();\n            addrem_flags(RVAL|RSEQ|FLOW, RMAP|RKCL|QMRK|BLCK);\n            _set_indentation(m_evt_handler->m_parent->indref);\n            _line_progressed(1);\n            goto mapblck_finish;\n        }\n        else if(first == '{')\n        {\n            _c4dbgp(\"mapblck[QMRK]: start child mapblck (!)\");\n            addrem_flags(RKCL, RKEY|QMRK);\n            m_evt_handler->begin_map_key_flow();\n            addrem_flags(RKEY|FLOW, RVAL|RKCL|QMRK|BLCK);\n            _set_indentation(m_evt_handler->m_parent->indref);\n            _line_progressed(1);\n            goto mapblck_finish;\n        }\n        else if(first == '?')\n        {\n            _c4dbgp(\"mapblck[QMRK]: another QMRK '?'\");\n            m_evt_handler->set_key_scalar_plain({});\n            m_evt_handler->set_val_scalar_plain({});\n            m_evt_handler->add_sibling();\n            _line_progressed(1);\n        }\n        else if(first == '.')\n        {\n            _c4dbgp(\"mapblck[QMRK]: maybe end doc?\");\n            csubstr rs = rem.sub(1);\n            if(rs == \"..\" || rs.begins_with(\".. \"))\n            {\n                _c4dbgp(\"mapblck[QMRK]: end+start doc\");\n                _end_doc_suddenly();\n                _line_progressed(3);\n                goto mapblck_finish;\n            }\n            else\n            {\n                _c4err(\"parse error\");\n            }\n        }\n        else\n        {\n            _c4err(\"parse error\");\n        }\n    }\n\n mapblck_again:\n    _c4dbgt(\"mapblck: again\", 0);\n    if(_finished_line())\n    {\n        _line_ended();\n        _scan_line();\n        if(_finished_file())\n        {\n            _c4dbgp(\"mapblck: file finished!\");\n            _end_map_blck();\n            goto mapblck_finish;\n        }\n        _c4dbgnextline();\n    }\n    goto mapblck_start;\n\n mapblck_finish:\n    _c4dbgp(\"mapblck: finish\");\n}\n\n\n//-----------------------------------------------------------------------------\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_handle_unk_json()\n{\n    _c4dbgpf(\"handle_unk_json indref={} target={}\", m_evt_handler->m_curr->indref, m_evt_handler->m_curr->node_id);\n\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RNXT|RSEQ|RMAP));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_all(RTOP));\n\n    _maybe_skip_comment();\n    csubstr rem = m_evt_handler->m_curr->line_contents.rem;\n    if(!rem.len)\n        return;\n\n    size_t pos = rem.first_not_of(\" \\t\");\n    if(pos)\n    {\n        pos = pos != npos ? pos : rem.len;\n        _c4dbgpf(\"skipping indentation of {}\", pos);\n        _line_progressed(pos);\n        rem = m_evt_handler->m_curr->line_contents.rem;\n        if(!rem.len)\n            return;\n        _c4dbgpf(\"rem is now [{}]~~~{}~~~\", rem.len, rem);\n    }\n\n    if(rem.begins_with('['))\n    {\n        _c4dbgp(\"it's a seq\");\n        m_evt_handler->check_trailing_doc_token();\n        _maybe_begin_doc();\n        m_evt_handler->begin_seq_val_flow();\n        addrem_flags(RSEQ|FLOW|RVAL, RUNK|RTOP|RDOC);\n        _set_indentation(m_evt_handler->m_curr->line_contents.current_col(rem));\n        m_doc_empty = false;\n        _line_progressed(1);\n    }\n    else if(rem.begins_with('{'))\n    {\n        _c4dbgp(\"it's a map\");\n        m_evt_handler->check_trailing_doc_token();\n        _maybe_begin_doc();\n        m_evt_handler->begin_map_val_flow();\n        addrem_flags(RMAP|FLOW|RKEY, RVAL|RTOP|RUNK|RDOC);\n        m_doc_empty = false;\n        _set_indentation(m_evt_handler->m_curr->line_contents.current_col(rem));\n        _line_progressed(1);\n    }\n    else\n    {\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks,  ! has_any(SSCL));\n        _maybe_skip_whitespace_tokens();\n        csubstr s = m_evt_handler->m_curr->line_contents.rem;\n        if(!s.len)\n            return;\n        const size_t startindent = m_evt_handler->m_curr->line_contents.indentation; // save\n        const char first = s.str[0];\n        ScannedScalar sc;\n        if(first == '\"')\n        {\n            _c4dbgp(\"runk_json: scanning double-quoted scalar\");\n            m_evt_handler->check_trailing_doc_token();\n            _maybe_begin_doc();\n            add_flags(RDOC);\n            m_doc_empty = false;\n            sc = _scan_scalar_dquot();\n            csubstr maybe_filtered = _maybe_filter_val_scalar_dquot(sc);\n            if(!_maybe_scan_following_colon())\n            {\n                _c4dbgp(\"runk_json: set as val\");\n                _handle_annotations_before_blck_val_scalar();\n                m_evt_handler->set_val_scalar_dquoted(maybe_filtered);\n            }\n            else\n            {\n                _c4err(\"parse error\");\n            }\n        }\n        else if(_scan_scalar_plain_unk(&sc))\n        {\n            _c4dbgp(\"runk_json: got a plain scalar\");\n            m_evt_handler->check_trailing_doc_token();\n            _maybe_begin_doc();\n            add_flags(RDOC);\n            m_doc_empty = false;\n            if(!_maybe_scan_following_colon())\n            {\n                _c4dbgp(\"runk_json: set as val\");\n                _handle_annotations_before_blck_val_scalar();\n                csubstr maybe_filtered = _maybe_filter_val_scalar_plain(sc, startindent);\n                m_evt_handler->set_val_scalar_plain(maybe_filtered);\n            }\n            else\n            {\n                _c4err(\"parse error\");\n            }\n        }\n        else\n        {\n            _c4err(\"parse error\");\n        }\n    }\n}\n\n\n//-----------------------------------------------------------------------------\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::_handle_unk()\n{\n    _c4dbgpf(\"handle_unk indref={} target={}\", m_evt_handler->m_curr->indref, m_evt_handler->m_curr->node_id);\n\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(RNXT|RSEQ|RMAP));\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_all(RTOP));\n\n    _maybe_skip_comment();\n    csubstr rem = m_evt_handler->m_curr->line_contents.rem;\n    if(!rem.len)\n        return;\n\n    size_t pos = rem.first_not_of(\" \\t\");\n    if(pos)\n    {\n        pos = pos != npos ? pos : rem.len;\n        _c4dbgpf(\"skipping {} whitespace characters\", pos);\n        _line_progressed(pos);\n        rem = m_evt_handler->m_curr->line_contents.rem;\n        if(!rem.len)\n            return;\n        _c4dbgpf(\"rem is now [{}]~~~{}~~~\", rem.len, rem);\n    }\n\n    if(m_evt_handler->m_curr->line_contents.indentation == 0u && _at_line_begin())\n    {\n        const char first = rem.str[0];\n        _c4dbgp(\"rtop: zero indent + at line begin\");\n        if(first == '-')\n        {\n            _c4dbgp(\"rtop: suspecting doc\");\n            if(_is_doc_begin_token(rem))\n            {\n                _c4dbgp(\"rtop: begin doc\");\n                _maybe_end_doc();\n                _begin2_doc_expl();\n                _set_indentation(0);\n                addrem_flags(RDOC|RUNK, NDOC);\n                _line_progressed(3u);\n                _maybe_skip_whitespace_tokens();\n                return;\n            }\n        }\n        else if(first == '.')\n        {\n            _c4dbgp(\"rtop: suspecting doc end\");\n            if(_is_doc_end_token(rem))\n            {\n                _c4dbgp(\"rtop: end doc\");\n                if(has_any(RDOC))\n                {\n                    _end2_doc_expl();\n                }\n                else\n                {\n                    _c4dbgp(\"rtop: ignore end doc\");\n                }\n                addrem_flags(NDOC|RUNK, RDOC);\n                _line_progressed(3u);\n                _maybe_skip_whitespace_tokens();\n                return;\n            }\n        }\n        else if(first == '%')\n        {\n            _c4dbgpf(\"directive: {}\", rem);\n            if(C4_UNLIKELY(!m_doc_empty && has_none(NDOC)))\n                _RYML_CB_ERR(m_evt_handler->m_stack.m_callbacks, \"need document footer before directives\");\n            _handle_directive(rem);\n            return;\n        }\n    }\n\n    /* no else-if! */\n    char first = rem.str[0];\n\n    if(first == '[')\n    {\n        m_evt_handler->check_trailing_doc_token();\n        _maybe_begin_doc();\n        m_doc_empty = false;\n        const size_t startindent = m_evt_handler->m_curr->line_contents.current_col(rem);\n        if(C4_LIKELY( ! _annotations_require_key_container()))\n        {\n            _c4dbgp(\"it's a seq, flow\");\n            _handle_annotations_before_blck_val_scalar();\n            m_evt_handler->begin_seq_val_flow();\n            addrem_flags(RSEQ|FLOW|RVAL, RUNK|RTOP|RDOC);\n            _set_indentation(startindent);\n        }\n        else\n        {\n            _c4dbgp(\"start new block map, set flow seq as key (!)\");\n            _handle_annotations_before_start_mapblck(m_evt_handler->m_curr->pos.line);\n            m_evt_handler->begin_map_val_block();\n            addrem_flags(RMAP|BLCK|RKCL, RUNK|RTOP|RDOC);\n            _handle_annotations_and_indentation_after_start_mapblck(startindent, m_evt_handler->m_curr->pos.line);\n            m_evt_handler->begin_seq_key_flow();\n            addrem_flags(RSEQ|FLOW|RVAL, RMAP|BLCK|RKCL);\n            _set_indentation(startindent);\n        }\n        _line_progressed(1);\n    }\n    else if(first == '{')\n    {\n        m_evt_handler->check_trailing_doc_token();\n        _maybe_begin_doc();\n        m_doc_empty = false;\n        const size_t startindent = m_evt_handler->m_curr->line_contents.current_col(rem);\n        if(C4_LIKELY( ! _annotations_require_key_container()))\n        {\n            _c4dbgp(\"it's a map, flow\");\n            _handle_annotations_before_blck_val_scalar();\n            m_evt_handler->begin_map_val_flow();\n            addrem_flags(RMAP|FLOW|RKEY, RVAL|RTOP|RUNK|RDOC);\n            _set_indentation(startindent);\n        }\n        else\n        {\n            _c4dbgp(\"start new block map, set flow map as key (!)\");\n            _handle_annotations_before_start_mapblck(m_evt_handler->m_curr->pos.line);\n            m_evt_handler->begin_map_val_block();\n            addrem_flags(RMAP|BLCK|RKCL, RUNK|RTOP|RDOC);\n            _handle_annotations_and_indentation_after_start_mapblck(startindent, m_evt_handler->m_curr->pos.line);\n            m_evt_handler->begin_map_key_flow();\n            addrem_flags(RMAP|FLOW|RKEY, BLCK|RKCL);\n            _set_indentation(startindent);\n        }\n        _line_progressed(1);\n    }\n    else if(first == '-' && _is_blck_token(rem))\n    {\n        _c4dbgp(\"it's a seq, block\");\n        m_evt_handler->check_trailing_doc_token();\n        _maybe_begin_doc();\n        _handle_annotations_before_blck_val_scalar();\n        m_evt_handler->begin_seq_val_block();\n        addrem_flags(RSEQ|BLCK|RVAL, RNXT|RTOP|RUNK|RDOC);\n        m_doc_empty = false;\n        _set_indentation(m_evt_handler->m_curr->line_contents.current_col(rem));\n        _line_progressed(1);\n        _maybe_skip_whitespace_tokens();\n    }\n    else if(first == '?' && _is_blck_token(rem))\n    {\n        _c4dbgp(\"it's a map + this key is complex\");\n        m_evt_handler->check_trailing_doc_token();\n        _maybe_begin_doc();\n        _handle_annotations_before_blck_val_scalar();\n        m_evt_handler->begin_map_val_block();\n        addrem_flags(RMAP|BLCK|QMRK, RKEY|RVAL|RTOP|RUNK);\n        m_doc_empty = false;\n        m_was_inside_qmrk = true;\n        _save_indentation();\n        _line_progressed(1);\n        _maybe_skip_whitespace_tokens();\n    }\n    else if(first == ':' && _is_blck_token(rem))\n    {\n        if(m_doc_empty)\n        {\n            _c4dbgp(\"it's a map with an empty key\");\n            m_evt_handler->check_trailing_doc_token();\n            _maybe_begin_doc();\n            _handle_annotations_before_blck_val_scalar();\n            m_evt_handler->begin_map_val_block();\n            m_evt_handler->set_key_scalar_plain({});\n            m_doc_empty = false;\n            _save_indentation();\n        }\n        else\n        {\n            _c4dbgp(\"actually prev val is a key!\");\n            size_t prev_indentation = m_evt_handler->m_curr->indref;\n            m_evt_handler->actually_val_is_first_key_of_new_map_block();\n            _set_indentation(prev_indentation);\n        }\n        addrem_flags(RMAP|BLCK|RVAL, RTOP|RUNK|RDOC);\n        _line_progressed(1);\n        _maybe_skip_whitespace_tokens();\n    }\n    else if(first == '&')\n    {\n        csubstr anchor = _scan_anchor();\n        _c4dbgpf(\"anchor! [{}]~~~{}~~~\", anchor.len, anchor);\n        m_evt_handler->check_trailing_doc_token();\n        _maybe_begin_doc();\n        const size_t indentation = m_evt_handler->m_curr->line_contents.current_col(rem);\n        const size_t line = m_evt_handler->m_curr->pos.line;\n        _add_annotation(&m_pending_anchors, anchor, indentation, line);\n        _set_indentation(m_evt_handler->m_curr->line_contents.current_col(rem));\n        m_doc_empty = false;\n    }\n    else if(first == '*')\n    {\n        csubstr ref = _scan_ref_map();\n        _c4dbgpf(\"ref! [{}]~~~{}~~~\", ref.len, ref);\n        m_evt_handler->check_trailing_doc_token();\n        _maybe_begin_doc();\n        m_doc_empty = false;\n        if(!_maybe_scan_following_colon())\n        {\n            _c4dbgp(\"runk: set val ref\");\n            _handle_annotations_before_blck_val_scalar();\n            m_evt_handler->set_val_ref(ref);\n        }\n        else\n        {\n            _c4dbgp(\"runk: start new block map, set ref as key\");\n            const size_t startindent = m_evt_handler->m_curr->line_contents.indentation; // save\n            const size_t startline = m_evt_handler->m_curr->pos.line; // save\n            _handle_annotations_before_start_mapblck(startline);\n            m_evt_handler->begin_map_val_block();\n            _handle_annotations_and_indentation_after_start_mapblck(startindent, startline);\n            m_evt_handler->set_key_ref(ref);\n            _maybe_skip_whitespace_tokens();\n            _set_indentation(startindent);\n            addrem_flags(RMAP|BLCK|RVAL, RTOP|RUNK|RDOC);\n        }\n    }\n    else if(first == '!')\n    {\n        csubstr tag = _scan_tag();\n        _c4dbgpf(\"unk: val tag! [{}]~~~{}~~~\", tag.len, tag);\n        // we need to buffer the tags, as there may be two\n        // consecutive tags in here\n        const size_t indentation = m_evt_handler->m_curr->line_contents.current_col(rem);\n        const size_t line = m_evt_handler->m_curr->pos.line;\n        _add_annotation(&m_pending_tags, tag, indentation, line);\n    }\n    else\n    {\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks,  ! has_any(SSCL));\n        _maybe_skip_whitespace_tokens();\n        csubstr s = m_evt_handler->m_curr->line_contents.rem;\n        if(!s.len)\n            return;\n        const size_t startindent = m_evt_handler->m_curr->line_contents.indentation; // save\n        const size_t startline = m_evt_handler->m_curr->pos.line; // save\n        first = s.str[0];\n        ScannedScalar sc;\n        if(first == '\\'')\n        {\n            _c4dbgp(\"runk: scanning single-quoted scalar\");\n            m_evt_handler->check_trailing_doc_token();\n            _maybe_begin_doc();\n            add_flags(RDOC);\n            m_doc_empty = false;\n            sc = _scan_scalar_squot();\n            if(!_maybe_scan_following_colon())\n            {\n                _c4dbgp(\"runk: set as val\");\n                _handle_annotations_before_blck_val_scalar();\n                csubstr maybe_filtered = _maybe_filter_val_scalar_squot(sc);\n                m_evt_handler->set_val_scalar_squoted(maybe_filtered);\n            }\n            else\n            {\n                _c4dbgp(\"runk: start new block map, set scalar as key\");\n                _handle_annotations_before_start_mapblck(startline);\n                m_evt_handler->begin_map_val_block();\n                _handle_annotations_and_indentation_after_start_mapblck(startindent, startline);\n                csubstr maybe_filtered = _maybe_filter_key_scalar_squot(sc);\n                m_evt_handler->set_key_scalar_squoted(maybe_filtered);\n                _maybe_skip_whitespace_tokens();\n                _set_indentation(startindent);\n                addrem_flags(RMAP|BLCK|RVAL, RTOP|RUNK|RDOC);\n            }\n        }\n        else if(first == '\"')\n        {\n            _c4dbgp(\"runk: scanning double-quoted scalar\");\n            m_evt_handler->check_trailing_doc_token();\n            _maybe_begin_doc();\n            add_flags(RDOC);\n            m_doc_empty = false;\n            sc = _scan_scalar_dquot();\n            if(!_maybe_scan_following_colon())\n            {\n                _c4dbgp(\"runk: set as val\");\n                _handle_annotations_before_blck_val_scalar();\n                csubstr maybe_filtered = _maybe_filter_val_scalar_dquot(sc);\n                m_evt_handler->set_val_scalar_dquoted(maybe_filtered);\n            }\n            else\n            {\n                _c4dbgp(\"runk: start new block map, set double-quoted scalar as key\");\n                _handle_annotations_before_start_mapblck(startline);\n                m_evt_handler->begin_map_val_block();\n                _handle_annotations_and_indentation_after_start_mapblck(startindent, startline);\n                csubstr maybe_filtered = _maybe_filter_key_scalar_dquot(sc);\n                m_evt_handler->set_key_scalar_dquoted(maybe_filtered);\n                _maybe_skip_whitespace_tokens();\n                _set_indentation(startindent);\n                addrem_flags(RMAP|BLCK|RVAL, RTOP|RUNK|RDOC);\n            }\n        }\n        else if(first == '|')\n        {\n            _c4dbgp(\"runk: scanning block-literal scalar\");\n            m_evt_handler->check_trailing_doc_token();\n            _maybe_begin_doc();\n            add_flags(RDOC);\n            m_doc_empty = false;\n            ScannedBlock sb;\n            _scan_block(&sb, startindent);\n            if(C4_LIKELY(!_maybe_scan_following_colon()))\n            {\n                _c4dbgp(\"runk: set as val\");\n                _handle_annotations_before_blck_val_scalar();\n                csubstr maybe_filtered = _maybe_filter_val_scalar_literal(sb);\n                m_evt_handler->set_val_scalar_literal(maybe_filtered);\n            }\n            else\n            {\n                _c4err(\"block literal keys must be enclosed in '?'\");\n            }\n        }\n        else if(first == '>')\n        {\n            _c4dbgp(\"runk: scanning block-folded scalar\");\n            m_evt_handler->check_trailing_doc_token();\n            _maybe_begin_doc();\n            add_flags(RDOC);\n            m_doc_empty = false;\n            ScannedBlock sb;\n            _scan_block(&sb, startindent);\n            if(C4_LIKELY(!_maybe_scan_following_colon()))\n            {\n                _c4dbgp(\"runk: set as val\");\n                _handle_annotations_before_blck_val_scalar();\n                csubstr maybe_filtered = _maybe_filter_val_scalar_folded(sb);\n                m_evt_handler->set_val_scalar_folded(maybe_filtered);\n            }\n            else\n            {\n                _c4err(\"block folded keys must be enclosed in '?'\");\n            }\n        }\n        else if(_scan_scalar_plain_unk(&sc))\n        {\n            _c4dbgp(\"runk: got a plain scalar\");\n            m_evt_handler->check_trailing_doc_token();\n            _maybe_begin_doc();\n            add_flags(RDOC);\n            m_doc_empty = false;\n            if(!_maybe_scan_following_colon())\n            {\n                _c4dbgp(\"runk: set as val\");\n                _handle_annotations_before_blck_val_scalar();\n                csubstr maybe_filtered = _maybe_filter_val_scalar_plain(sc, startindent);\n                m_evt_handler->set_val_scalar_plain(maybe_filtered);\n            }\n            else\n            {\n                _c4dbgp(\"runk: start new block map, set scalar as key\");\n                _handle_annotations_before_start_mapblck(startline);\n                m_evt_handler->begin_map_val_block();\n                _handle_annotations_and_indentation_after_start_mapblck(startindent, startline);\n                csubstr maybe_filtered = _maybe_filter_key_scalar_plain(sc, startindent);\n                m_evt_handler->set_key_scalar_plain(maybe_filtered);\n                _maybe_skip_whitespace_tokens();\n                _set_indentation(startindent);\n                addrem_flags(RMAP|BLCK|RVAL, RTOP|RUNK|RDOC);\n            }\n        }\n    }\n}\n\n\n//-----------------------------------------------------------------------------\n\ntemplate<class EventHandler>\nC4_COLD void ParseEngine<EventHandler>::_handle_usty()\n{\n    _c4dbgpf(\"handle_usty target={}\", m_evt_handler->m_curr->indref, m_evt_handler->m_curr->node_id);\n\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_none(BLCK|FLOW));\n\n    #ifdef RYML_NO_COVERAGE__TO_BE_DELETED\n    if(has_any(RNXT))\n    {\n        _c4dbgp(\"usty[RNXT]: finishing!\");\n        _end_stream();\n    }\n    #endif\n\n    _maybe_skip_comment();\n    csubstr rem = m_evt_handler->m_curr->line_contents.rem;\n    if(!rem.len)\n        return;\n\n    size_t pos = rem.first_not_of(\" \\t\");\n    if(pos)\n    {\n        pos = pos != npos ? pos : rem.len;\n        _c4dbgpf(\"skipping indentation of {}\", pos);\n        _line_progressed(pos);\n        rem = m_evt_handler->m_curr->line_contents.rem;\n        if(!rem.len)\n            return;\n        _c4dbgpf(\"rem is now [{}]~~~{}~~~\", rem.len, rem);\n    }\n\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, rem.len > 0);\n    size_t startindent = m_evt_handler->m_curr->line_contents.indentation; // save\n    char first = rem.str[0];\n    if(has_any(RSEQ)) // destination is a sequence\n    {\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks,  ! has_any(RMAP));\n        _c4dbgpf(\"usty[RSEQ]: first='{}'\", _c4prc(first));\n        if(first == '[')\n        {\n            _c4dbgp(\"usty[RSEQ]: it's a flow seq. merging it\");\n            add_flags(RNXT);\n            m_evt_handler->_push();\n            addrem_flags(FLOW|RVAL, RNXT|USTY);\n            _set_indentation(startindent);\n            _line_progressed(1);\n            _maybe_skip_whitespace_tokens();\n        }\n        else if(first == '-' && _is_blck_token(rem))\n        {\n            _c4dbgp(\"usty[RSEQ]: it's a block seq. merging it\");\n            add_flags(RNXT);\n            m_evt_handler->_push();\n            addrem_flags(BLCK|RVAL, RNXT|USTY);\n            _set_indentation(startindent);\n            _line_progressed(1);\n            _maybe_skip_whitespace_tokens();\n        }\n        else\n        {\n            _c4err(\"can only parse a seq into an existing seq\");\n        }\n    }\n    else if(has_any(RMAP)) // destination is a map\n    {\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks,  ! has_any(RSEQ));\n        _c4dbgpf(\"usty[RMAP]: first='{}'\", _c4prc(first));\n        if(first == '{')\n        {\n            _c4dbgp(\"usty[RMAP]: it's a flow map. merging it\");\n            add_flags(RNXT);\n            _handle_annotations_before_blck_val_scalar();\n            m_evt_handler->_push();\n            addrem_flags(RMAP|FLOW|RKEY, RNXT|USTY);\n            _set_indentation(startindent);\n            _line_progressed(1);\n            _maybe_skip_whitespace_tokens();\n        }\n        else if(first == '?' && _is_blck_token(rem))\n        {\n            _c4dbgp(\"usty[RMAP]: it's a block map + this key is complex\");\n            add_flags(RNXT);\n            _handle_annotations_before_blck_val_scalar();\n            m_evt_handler->_push();\n            addrem_flags(RMAP|BLCK|QMRK, RNXT|USTY);\n            m_was_inside_qmrk = true;\n            _save_indentation();\n            _line_progressed(1);\n            _maybe_skip_whitespace_tokens();\n        }\n        else if(first == ':' && _is_blck_token(rem))\n        {\n            _c4dbgp(\"usty[RMAP]: it's a map with an empty key\");\n            add_flags(RNXT);\n            _handle_annotations_before_blck_val_scalar();\n            m_evt_handler->_push();\n            m_evt_handler->set_key_scalar_plain({});\n            addrem_flags(RMAP|BLCK|RVAL, RNXT|USTY);\n            _save_indentation();\n            _line_progressed(1);\n            _maybe_skip_whitespace_tokens();\n        }\n        else if(rem.begins_with('&'))\n        {\n            csubstr anchor = _scan_anchor();\n            _c4dbgpf(\"usty[RMAP]: anchor! [{}]~~~{}~~~\", anchor.len, anchor);\n            const size_t indentation = m_evt_handler->m_curr->line_contents.current_col(rem);\n            const size_t line = m_evt_handler->m_curr->pos.line;\n            _add_annotation(&m_pending_anchors, anchor, indentation, line);\n            _set_indentation(m_evt_handler->m_curr->line_contents.current_col(rem));\n        }\n        else if(first == '*')\n        {\n            csubstr ref = _scan_ref_map();\n            _c4dbgpf(\"usty[RMAP]: ref! [{}]~~~{}~~~\", ref.len, ref);\n            if(!_maybe_scan_following_colon())\n            {\n                _c4err(\"cannot read a VAL to a map\");\n            }\n            else\n            {\n                _c4dbgp(\"usty[RMAP]: start new block map, set ref as key\");\n                const size_t startline = m_evt_handler->m_curr->pos.line; // save\n                add_flags(RNXT);\n                _handle_annotations_before_start_mapblck(startline);\n                m_evt_handler->_push();\n                _handle_annotations_and_indentation_after_start_mapblck(startindent, startline);\n                m_evt_handler->set_key_ref(ref);\n                _maybe_skip_whitespace_tokens();\n                _set_indentation(startindent);\n                addrem_flags(RMAP|BLCK|RVAL, RNXT|USTY);\n            }\n        }\n        else if(first == '!')\n        {\n            csubstr tag = _scan_tag();\n            _c4dbgpf(\"usty[RMAP]: val tag! [{}]~~~{}~~~\", tag.len, tag);\n            // we need to buffer the tags, as there may be two\n            // consecutive tags in here\n            const size_t indentation = m_evt_handler->m_curr->line_contents.current_col(rem);\n            const size_t line = m_evt_handler->m_curr->pos.line;\n            _add_annotation(&m_pending_tags, tag, indentation, line);\n        }\n        else if(first == '[' || (first == '-' && _is_blck_token(rem)))\n        {\n            _c4err(\"cannot parse a seq into an existing map\");\n        }\n        else\n        {\n            _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks,  ! has_any(SSCL));\n            startindent = m_evt_handler->m_curr->line_contents.indentation; // save\n            const size_t startline = m_evt_handler->m_curr->pos.line; // save\n            ScannedScalar sc;\n            _c4dbgpf(\"usty[RMAP]: maybe scalar. first='{}'\", _c4prc(first));\n            if(first == '\\'')\n            {\n                _c4dbgp(\"usty[RMAP]: scanning single-quoted scalar\");\n                sc = _scan_scalar_squot();\n                if(!_maybe_scan_following_colon())\n                {\n                    _c4err(\"cannot read a VAL to a map\");\n                }\n                else\n                {\n                    _c4dbgp(\"usty[RMAP]: start new block map, set scalar as key\");\n                    add_flags(RNXT);\n                    _handle_annotations_before_start_mapblck(startline);\n                    m_evt_handler->_push();\n                    _handle_annotations_and_indentation_after_start_mapblck(startindent, startline);\n                    csubstr maybe_filtered = _maybe_filter_key_scalar_squot(sc);\n                    m_evt_handler->set_key_scalar_squoted(maybe_filtered);\n                    _set_indentation(startindent);\n                    addrem_flags(RMAP|BLCK|RVAL, RNXT|USTY);\n                    _maybe_skip_whitespace_tokens();\n                }\n            }\n            else if(first == '\"')\n            {\n                _c4dbgp(\"usty[RMAP]: scanning double-quoted scalar\");\n                sc = _scan_scalar_dquot();\n                if(!_maybe_scan_following_colon())\n                {\n                    _c4err(\"cannot read a VAL to a map\");\n                }\n                else\n                {\n                    _c4dbgp(\"usty[RMAP]: start new block map, set double-quoted scalar as key\");\n                    add_flags(RNXT);\n                    _handle_annotations_before_start_mapblck(startline);\n                    m_evt_handler->_push();\n                    _handle_annotations_and_indentation_after_start_mapblck(startindent, startline);\n                    csubstr maybe_filtered = _maybe_filter_key_scalar_dquot(sc);\n                    m_evt_handler->set_key_scalar_dquoted(maybe_filtered);\n                    _set_indentation(startindent);\n                    addrem_flags(RMAP|BLCK|RVAL, RNXT|USTY);\n                    _maybe_skip_whitespace_tokens();\n                }\n            }\n            else if(first == '|')\n            {\n                _c4err(\"block literal keys must be enclosed in '?'\");\n            }\n            else if(first == '>')\n            {\n                _c4err(\"block literal keys must be enclosed in '?'\");\n            }\n            else if(_scan_scalar_plain_unk(&sc))\n            {\n                _c4dbgp(\"usty[RMAP]: got a plain scalar\");\n                if(!_maybe_scan_following_colon())\n                {\n                    _c4err(\"cannot read a VAL to a map\");\n                }\n                else\n                {\n                    _c4dbgp(\"usty[RMAP]: start new block map, set scalar as key\");\n                    add_flags(RNXT);\n                    _handle_annotations_before_start_mapblck(startline);\n                    m_evt_handler->_push();\n                    _handle_annotations_and_indentation_after_start_mapblck(startindent, startline);\n                    csubstr maybe_filtered = _maybe_filter_key_scalar_plain(sc, startindent);\n                    m_evt_handler->set_key_scalar_plain(maybe_filtered);\n                    _set_indentation(startindent);\n                    addrem_flags(RMAP|BLCK|RVAL, RNXT|USTY);\n                    _maybe_skip_whitespace_tokens();\n                }\n            }\n            else\n            {\n                _c4err(\"parse error\");\n            }\n        }\n    }\n    else // destination is unknown\n    {\n        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks,  ! has_any(RSEQ));\n        _c4dbgpf(\"usty[UNK]: first='{}'\", _c4prc(first));\n        if(first == '[')\n        {\n            _c4dbgp(\"usty[UNK]: it's a flow seq\");\n            add_flags(RNXT);\n            _handle_annotations_before_blck_val_scalar();\n            m_evt_handler->begin_seq_val_flow();\n            addrem_flags(RSEQ|FLOW|RVAL, RNXT|USTY);\n            _set_indentation(startindent);\n            _line_progressed(1);\n            _maybe_skip_whitespace_tokens();\n        }\n        else if(first == '-' && _is_blck_token(rem))\n        {\n            _c4dbgp(\"usty[UNK]: it's a block seq\");\n            add_flags(RNXT);\n            _handle_annotations_before_blck_val_scalar();\n            m_evt_handler->begin_seq_val_block();\n            addrem_flags(RSEQ|BLCK|RVAL, RNXT|USTY);\n            _set_indentation(startindent);\n            _line_progressed(1);\n            _maybe_skip_whitespace_tokens();\n        }\n        else if(first == '{')\n        {\n            _c4dbgp(\"usty[UNK]: it's a flow map\");\n            add_flags(RNXT);\n            _handle_annotations_before_blck_val_scalar();\n            m_evt_handler->begin_map_val_flow();\n            addrem_flags(RMAP|FLOW|RKEY, RNXT|USTY);\n            _set_indentation(startindent);\n            _line_progressed(1);\n            _maybe_skip_whitespace_tokens();\n        }\n        else if(first == '?' && _is_blck_token(rem))\n        {\n            _c4dbgp(\"usty[UNK]: it's a map + this key is complex\");\n            add_flags(RNXT);\n            _handle_annotations_before_blck_val_scalar();\n            m_evt_handler->begin_map_val_block();\n            addrem_flags(RMAP|BLCK|QMRK, RNXT|USTY);\n            m_was_inside_qmrk = true;\n            _save_indentation();\n            _line_progressed(1);\n            _maybe_skip_whitespace_tokens();\n        }\n        else if(first == ':' && _is_blck_token(rem))\n        {\n            _c4dbgp(\"usty[UNK]: it's a map with an empty key\");\n            add_flags(RNXT);\n            _handle_annotations_before_blck_val_scalar();\n            m_evt_handler->begin_map_val_block();\n            m_evt_handler->set_key_scalar_plain({});\n            addrem_flags(RMAP|BLCK|RVAL, RNXT|USTY);\n            _save_indentation();\n            _line_progressed(1);\n            _maybe_skip_whitespace_tokens();\n        }\n        else if(first == '&')\n        {\n            csubstr anchor = _scan_anchor();\n            _c4dbgpf(\"usty[UNK]: anchor! [{}]~~~{}~~~\", anchor.len, anchor);\n            const size_t indentation = m_evt_handler->m_curr->line_contents.current_col(rem);\n            const size_t line = m_evt_handler->m_curr->pos.line;\n            _add_annotation(&m_pending_anchors, anchor, indentation, line);\n            _set_indentation(m_evt_handler->m_curr->line_contents.current_col(rem));\n        }\n        else if(first == '*')\n        {\n            csubstr ref = _scan_ref_map();\n            _c4dbgpf(\"usty[UNK]: ref! [{}]~~~{}~~~\", ref.len, ref);\n            if(!_maybe_scan_following_colon())\n            {\n                _c4dbgp(\"usty[UNK]: set val ref\");\n                _handle_annotations_before_blck_val_scalar();\n                m_evt_handler->set_val_ref(ref);\n            }\n            else\n            {\n                _c4dbgp(\"usty[UNK]: start new block map, set ref as key\");\n                const size_t startline = m_evt_handler->m_curr->pos.line; // save\n                add_flags(RNXT);\n                _handle_annotations_before_start_mapblck(startline);\n                m_evt_handler->begin_map_val_block();\n                _handle_annotations_and_indentation_after_start_mapblck(startindent, startline);\n                m_evt_handler->set_key_ref(ref);\n                _maybe_skip_whitespace_tokens();\n                _set_indentation(startindent);\n                addrem_flags(RMAP|BLCK|RVAL, RNXT|USTY);\n            }\n        }\n        else if(first == '!')\n        {\n            csubstr tag = _scan_tag();\n            _c4dbgpf(\"usty[UNK]: val tag! [{}]~~~{}~~~\", tag.len, tag);\n            // we need to buffer the tags, as there may be two\n            // consecutive tags in here\n            const size_t indentation = m_evt_handler->m_curr->line_contents.current_col(rem);\n            const size_t line = m_evt_handler->m_curr->pos.line;\n            _add_annotation(&m_pending_tags, tag, indentation, line);\n        }\n        else\n        {\n            _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks,  ! has_any(SSCL));\n            startindent = m_evt_handler->m_curr->line_contents.indentation; // save\n            const size_t startline = m_evt_handler->m_curr->pos.line; // save\n            first = rem.str[0];\n            ScannedScalar sc;\n            _c4dbgpf(\"usty[UNK]: maybe scalar. first='{}'\", _c4prc(first));\n            if(first == '\\'')\n            {\n                _c4dbgp(\"usty[UNK]: scanning single-quoted scalar\");\n                sc = _scan_scalar_squot();\n                if(!_maybe_scan_following_colon())\n                {\n                    _c4dbgp(\"usty[UNK]: set as val\");\n                    _handle_annotations_before_blck_val_scalar();\n                    csubstr maybe_filtered = _maybe_filter_val_scalar_squot(sc);\n                    m_evt_handler->set_val_scalar_squoted(maybe_filtered);\n                    _end_stream();\n                }\n                else\n                {\n                    _c4dbgp(\"usty[UNK]: start new block map, set scalar as key\");\n                    add_flags(RNXT);\n                    _handle_annotations_before_start_mapblck(startline);\n                    m_evt_handler->begin_map_val_block();\n                    _handle_annotations_and_indentation_after_start_mapblck(startindent, startline);\n                    csubstr maybe_filtered = _maybe_filter_key_scalar_squot(sc);\n                    m_evt_handler->set_key_scalar_squoted(maybe_filtered);\n                    _set_indentation(startindent);\n                    addrem_flags(RMAP|BLCK|RVAL, RNXT|USTY);\n                    _maybe_skip_whitespace_tokens();\n                }\n            }\n            else if(first == '\"')\n            {\n                _c4dbgp(\"usty[UNK]: scanning double-quoted scalar\");\n                sc = _scan_scalar_dquot();\n                if(!_maybe_scan_following_colon())\n                {\n                    _c4dbgp(\"usty[UNK]: set as val\");\n                    _handle_annotations_before_blck_val_scalar();\n                    csubstr maybe_filtered = _maybe_filter_val_scalar_dquot(sc);\n                    m_evt_handler->set_val_scalar_dquoted(maybe_filtered);\n                    _end_stream();\n                }\n                else\n                {\n                    _c4dbgp(\"usty[UNK]: start new block map, set double-quoted scalar as key\");\n                    add_flags(RNXT);\n                    _handle_annotations_before_start_mapblck(startline);\n                    m_evt_handler->begin_map_val_block();\n                    _handle_annotations_and_indentation_after_start_mapblck(startindent, startline);\n                    csubstr maybe_filtered = _maybe_filter_key_scalar_dquot(sc);\n                    m_evt_handler->set_key_scalar_dquoted(maybe_filtered);\n                    _set_indentation(startindent);\n                    addrem_flags(RMAP|BLCK|RVAL, RNXT|USTY);\n                    _maybe_skip_whitespace_tokens();\n                }\n            }\n            else if(first == '|')\n            {\n                _c4dbgp(\"usty[UNK]: scanning block-literal scalar\");\n                ScannedBlock sb;\n                _scan_block(&sb, startindent);\n                _c4dbgp(\"usty[UNK]: set as val\");\n                _handle_annotations_before_blck_val_scalar();\n                csubstr maybe_filtered = _maybe_filter_val_scalar_literal(sb);\n                m_evt_handler->set_val_scalar_literal(maybe_filtered);\n                _end_stream();\n            }\n            else if(first == '>')\n            {\n                _c4dbgp(\"usty[UNK]: scanning block-folded scalar\");\n                ScannedBlock sb;\n                _scan_block(&sb, startindent);\n                _c4dbgp(\"usty[UNK]: set as val\");\n                _handle_annotations_before_blck_val_scalar();\n                csubstr maybe_filtered = _maybe_filter_val_scalar_folded(sb);\n                m_evt_handler->set_val_scalar_folded(maybe_filtered);\n                _end_stream();\n            }\n            else if(_scan_scalar_plain_unk(&sc))\n            {\n                _c4dbgp(\"usty[UNK]: got a plain scalar\");\n                if(!_maybe_scan_following_colon())\n                {\n                    _c4dbgp(\"usty[UNK]: set as val\");\n                    _handle_annotations_before_blck_val_scalar();\n                    csubstr maybe_filtered = _maybe_filter_val_scalar_plain(sc, startindent);\n                    m_evt_handler->set_val_scalar_plain(maybe_filtered);\n                    _end_stream();\n                }\n                else\n                {\n                    _c4dbgp(\"usty[UNK]: start new block map, set scalar as key\");\n                    add_flags(RNXT);\n                    _handle_annotations_before_start_mapblck(startline);\n                    m_evt_handler->begin_map_val_block();\n                    _handle_annotations_and_indentation_after_start_mapblck(startindent, startline);\n                    csubstr maybe_filtered = _maybe_filter_key_scalar_plain(sc, startindent);\n                    m_evt_handler->set_key_scalar_plain(maybe_filtered);\n                    _set_indentation(startindent);\n                    addrem_flags(RMAP|BLCK|RVAL, RNXT|USTY);\n                    _maybe_skip_whitespace_tokens();\n                }\n            }\n            else\n            {\n                _c4err(\"parse error\");\n            }\n        }\n    }\n}\n\n\n//-----------------------------------------------------------------------------\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::parse_json_in_place_ev(csubstr filename, substr src)\n{\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, m_evt_handler->m_stack.size() >= 1);\n    m_file = filename;\n    m_buf = src;\n    _reset();\n    m_evt_handler->start_parse(filename.str, &_s_relocate_arena, this);\n    m_evt_handler->begin_stream();\n    while( ! _finished_file())\n    {\n        _scan_line();\n        while( ! _finished_line())\n        {\n            _c4dbgnextline();\n            _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks,  ! m_evt_handler->m_curr->line_contents.rem.empty());\n            if(has_any(RSEQ))\n            {\n                _handle_seq_json();\n            }\n            else if(has_any(RMAP))\n            {\n                _handle_map_json();\n            }\n            else if(has_any(RUNK))\n            {\n                _handle_unk_json();\n            }\n            else\n            {\n                _c4err(\"internal error\");\n            }\n        }\n        if(_finished_file())\n            break; // it may have finished because of multiline blocks\n        _line_ended();\n    }\n    _end_stream();\n    m_evt_handler->finish_parse();\n}\n\n\n//-----------------------------------------------------------------------------\n\ntemplate<class EventHandler>\nvoid ParseEngine<EventHandler>::parse_in_place_ev(csubstr filename, substr src)\n{\n    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, m_evt_handler->m_stack.size() >= 1);\n    m_file = filename;\n    m_buf = src;\n    _reset();\n    m_evt_handler->start_parse(filename.str, &_s_relocate_arena, this);\n    m_evt_handler->begin_stream();\n    while( ! _finished_file())\n    {\n        _scan_line();\n        while( ! _finished_line())\n        {\n            _c4dbgnextline();\n            _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks,  ! m_evt_handler->m_curr->line_contents.rem.empty());\n            if(has_any(FLOW))\n            {\n                if(has_none(RSEQIMAP))\n                {\n                    if(has_any(RSEQ))\n                    {\n                        _handle_seq_flow();\n                    }\n                    else\n                    {\n                        _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_all(RMAP));\n                        _handle_map_flow();\n                    }\n                }\n                else\n                {\n                    _handle_seq_imap();\n                }\n            }\n            else if(has_any(BLCK))\n            {\n                if(has_any(RSEQ))\n                {\n                    _handle_seq_block();\n                }\n                else\n                {\n                    _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, has_all(RMAP));\n                    _handle_map_block();\n                }\n            }\n            else if(has_any(RUNK))\n            {\n                _handle_unk();\n            }\n            else if(has_any(USTY))\n            {\n                _handle_usty();\n            }\n            else\n            {\n                _c4err(\"internal error\");\n            }\n        }\n        if(_finished_file())\n            break; // it may have finished because of multiline blocks\n        _line_ended();\n    }\n    _end_stream();\n    m_evt_handler->finish_parse();\n}\n\n} // namespace yml\n} // namespace c4\n\n#undef _c4dbgnextline\n\n#if defined(_MSC_VER)\n#   pragma warning(pop)\n#elif defined(__clang__)\n#   pragma clang diagnostic pop\n#elif defined(__GNUC__)\n#   pragma GCC diagnostic pop\n#endif\n\n#endif // _C4_YML_PARSE_ENGINE_DEF_HPP_\n"
  },
  {
    "path": "libs/rapidyaml/c4/yml/parse_engine.hpp",
    "content": "#ifndef _C4_YML_PARSE_ENGINE_HPP_\n#define _C4_YML_PARSE_ENGINE_HPP_\n\n#ifndef _C4_YML_DETAIL_PARSER_DBG_HPP_\n#include \"c4/yml/detail/parser_dbg.hpp\"\n#endif\n\n#ifndef _C4_YML_PARSER_STATE_HPP_\n#include \"c4/yml/parser_state.hpp\"\n#endif\n\n\n#if defined(_MSC_VER)\n#   pragma warning(push)\n#   pragma warning(disable: 4251/*needs to have dll-interface to be used by clients of struct*/)\n#endif\n\n\nnamespace c4 {\nnamespace yml {\n\n/** @addtogroup doc_parse\n * @{ */\n\n/** @defgroup doc_event_handlers Event Handlers\n *\n * @brief rapidyaml implements its parsing logic with a two-level\n * model, where a @ref ParseEngine object reads through the YAML\n * source, and dispatches events to an EventHandler bound to the @ref\n * ParseEngine. Because @ref ParseEngine is templated on the event\n * handler, the binding uses static polymorphism, without any virtual\n * functions. The actual handler object can be changed at run time,\n * (but of course needs to be the type of the template parameter).\n * This is thus a very efficient architecture, and further enables the\n * user to provide his own custom handler if he wishes to bypass the\n * rapidyaml @ref Tree.\n *\n * There are two handlers implemented in this project:\n *\n * - @ref EventHandlerTree is the handler responsible for creating the\n *   ryml @ref Tree\n *\n * - @ref EventHandlerYamlStd is the handler responsible for emitting\n *   standardized [YAML test suite\n *   events](https://github.com/yaml/yaml-test-suite), used (only) in\n *   the CI of this project.\n *\n *\n * ### Event model\n *\n * The event model used by the parse engine and event handlers follows\n * very closely the event model in the [YAML test\n * suite](https://github.com/yaml/yaml-test-suite).\n *\n * Consider for example this YAML,\n * ```yaml\n * {foo: bar,foo2: bar2}\n * ```\n * which would produce these events in the test-suite parlance:\n * ```\n * +STR\n * +DOC\n * +MAP {}\n * =VAL :foo\n * =VAL :bar\n * =VAL :foo2\n * =VAL :bar2\n * -MAP\n * -DOC\n * -STR\n * ```\n *\n * For reference, the @ref ParseEngine object will produce this\n * sequence of calls to its bound EventHandler:\n * ```cpp\n * handler.begin_stream();\n * handler.begin_doc();\n * handler.begin_map_val_flow();\n * handler.set_key_scalar_plain(\"foo\");\n * handler.set_val_scalar_plain(\"bar\");\n * handler.add_sibling();\n * handler.set_key_scalar_plain(\"foo2\");\n * handler.set_val_scalar_plain(\"bar2\");\n * handler.end_map();\n * handler.end_doc();\n * handler.end_stream();\n * ```\n *\n * For many other examples of all areas of YAML and how ryml's parse\n * model corresponds to the YAML standard model, refer to the [unit\n * tests for the parse\n * engine](https://github.com/biojppm/rapidyaml/tree/master/test/test_parse_engine.cpp).\n *\n *\n * ### Special events\n *\n * Most of the parsing events adopted by rapidyaml in its event model\n * are fairly obvious, but there are two less-obvious events requiring\n * some explanation.\n *\n * These events exist to make it easier to parse some special YAML\n * cases. They are called by the parser when a just-handled\n * value/container is actually the first key of a new map:\n *\n *   - `actually_val_is_first_key_of_new_map_flow()` (@ref EventHandlerTree::actually_val_is_first_key_of_new_map_flow() \"see implementation in EventHandlerTree\" / @ref EventHandlerYamlStd::actually_val_is_first_key_of_new_map_flow() \"see implementation in EventHandlerYamlStd\")\n *   - `actually_val_is_first_key_of_new_map_block()` (@ref EventHandlerTree::actually_val_is_first_key_of_new_map_block() \"see implementation in EventHandlerTree\" / @ref EventHandlerYamlStd::actually_val_is_first_key_of_new_map_block() \"see implementation in EventHandlerYamlStd\")\n *\n * For example, consider an implicit map inside a seq: `[a: b, c:\n * d]` which is parsed as `[{a: b}, {c: d}]`. The standard event\n * sequence for this YAML would be the following:\n * ```cpp\n * handler.begin_seq_val_flow();\n * handler.begin_map_val_flow();\n * handler.set_key_scalar_plain(\"a\");\n * handler.set_val_scalar_plain(\"b\");\n * handler.end_map();\n * handler.add_sibling();\n * handler.begin_map_val_flow();\n * handler.set_key_scalar_plain(\"c\");\n * handler.set_val_scalar_plain(\"d\");\n * handler.end_map();\n * handler.end_seq();\n * ```\n * The problem with this event sequence is that it forces the\n * parser to delay setting the val scalar (in this case \"a\" and\n * \"c\") until it knows whether the scalar is a key or a val. This\n * would require the parser to store the scalar until this\n * time. For instance, in the example above, the parser should\n * delay setting \"a\" and \"c\", because they are in fact keys and\n * not vals. Until then, the parser would have to store \"a\" and\n * \"c\" in its internal state. The downside is that this complexity\n * cost would apply even if there is no implicit map -- every val\n * in a seq would have to be delayed until one of the\n * disambiguating subsequent tokens `,-]:` is found.\n * By calling this function, the parser can avoid this complexity,\n * by preemptively setting the scalar as a val. Then a call to\n * this function will create the map and rearrange the scalar as\n * key. Now the cost applies only once: when a seqimap starts. So\n * the following (easier and cheaper) event sequence below has the\n * same effect as the event sequence above:\n * ```cpp\n * handler.begin_seq_val_flow();\n * handler.set_val_scalar_plain(\"notmap\");\n * handler.set_val_scalar_plain(\"a\"); // preemptively set \"a\" as val!\n * handler.actually_as_new_map_key(); // create a map, move the \"a\" val as the key of the first child of the new map\n * handler.set_val_scalar_plain(\"b\"); // now \"a\" is a key and \"b\" the val\n * handler.end_map();\n * handler.set_val_scalar_plain(\"c\"); // \"c\" also as val!\n * handler.actually_as_block_flow();  // likewise\n * handler.set_val_scalar_plain(\"d\"); // now \"c\" is a key and \"b\" the val\n * handler.end_map();\n * handler.end_seq();\n * ```\n * This also applies to container keys (although ryml's tree\n * cannot accomodate these): the parser can preemptively set a\n * container as a val, and call this event to turn that container\n * into a key. For example, consider this yaml:\n * ```yaml\n *   [aa, bb]: [cc, dd]\n * # ^       ^ ^\n * # |       | |\n * # (2)   (1) (3)     <- event sequence\n * ```\n * The standard event sequence for this YAML would be the\n * following:\n * ```cpp\n * handler.begin_map_val_block();       // (1)\n * handler.begin_seq_key_flow();        // (2)\n * handler.set_val_scalar_plain(\"aa\");\n * handler.add_sibling();\n * handler.set_val_scalar_plain(\"bb\");\n * handler.end_seq();\n * handler.begin_seq_val_flow();        // (3)\n * handler.set_val_scalar_plain(\"cc\");\n * handler.add_sibling();\n * handler.set_val_scalar_plain(\"dd\");\n * handler.end_seq();\n * handler.end_map();\n * ```\n * The problem with the sequence above is that, reading from\n * left-to-right, the parser can only detect the proper calls at\n * (1) and (2) once it reaches (1) in the YAML source. So, the\n * parser would have to buffer the entire event sequence starting\n * from the beginning until it reaches (1). Using this function,\n * the parser can do instead:\n * ```cpp\n * handler.begin_seq_val_flow();        // (2) -- preemptively as val!\n * handler.set_val_scalar_plain(\"aa\");\n * handler.add_sibling();\n * handler.set_val_scalar_plain(\"bb\");\n * handler.end_seq();\n * handler.actually_as_new_map_key();   // (1) -- adjust when finding that the prev val was actually a key.\n * handler.begin_seq_val_flow();        // (3) -- go on as before\n * handler.set_val_scalar_plain(\"cc\");\n * handler.add_sibling();\n * handler.set_val_scalar_plain(\"dd\");\n * handler.end_seq();\n * handler.end_map();\n * ```\n */\n\nclass Tree;\nclass NodeRef;\nclass ConstNodeRef;\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n/** Options to give to the parser to control its behavior. */\nstruct RYML_EXPORT ParserOptions\n{\nprivate:\n\n    typedef enum : uint32_t {\n        SCALAR_FILTERING = (1u << 0),\n        LOCATIONS = (1u << 1),\n        DEFAULTS = SCALAR_FILTERING,\n    } Flags_e;\n\n    uint32_t flags = DEFAULTS;\n\npublic:\n\n    ParserOptions() = default;\n\npublic:\n\n    /** @name source location tracking */\n    /** @{ */\n\n    /** enable/disable source location tracking */\n    ParserOptions& locations(bool enabled) noexcept\n    {\n        if(enabled)\n            flags |= LOCATIONS;\n        else\n            flags &= ~LOCATIONS;\n        return *this;\n    }\n    /** query source location tracking status */\n    C4_ALWAYS_INLINE bool locations() const noexcept { return (flags & LOCATIONS); }\n\n    /** @} */\n\npublic:\n\n    /** @name scalar filtering status (experimental; disable at your discretion) */\n    /** @{ */\n\n    /** enable/disable scalar filtering while parsing */\n    ParserOptions& scalar_filtering(bool enabled) noexcept\n    {\n        if(enabled)\n            flags |= SCALAR_FILTERING;\n        else\n            flags &= ~SCALAR_FILTERING;\n        return *this;\n    }\n    /** query scalar filtering status */\n    C4_ALWAYS_INLINE bool scalar_filtering() const noexcept { return (flags & SCALAR_FILTERING); }\n\n    /** @} */\n};\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n/** This is the main driver of parsing logic: it scans the YAML or\n * JSON source for tokens, and emits the appropriate sequence of\n * parsing events to its event handler. The parse engine itself has no\n * special limitations, and *can* accomodate containers as keys; it is the\n * event handler may introduce additional constraints.\n *\n * There are two implemented handlers (see @ref doc_event_handlers,\n * which has important notes about the event model):\n *\n * - @ref EventHandlerTree is the handler responsible for creating the\n *   ryml @ref Tree\n *\n * - @ref EventHandlerYamlStd is the handler responsible for emitting\n *   standardized [YAML test suite\n *   events](https://github.com/yaml/yaml-test-suite), used (only) in\n *   the CI of this project. This is not part of the library and is\n *   not installed.\n */\ntemplate<class EventHandler>\nclass ParseEngine\n{\npublic:\n\n    using handler_type = EventHandler;\n\npublic:\n\n    /** @name construction and assignment */\n    /** @{ */\n\n    ParseEngine(EventHandler *evt_handler, ParserOptions opts={});\n    ~ParseEngine();\n\n    ParseEngine(ParseEngine &&);\n    ParseEngine(ParseEngine const&);\n    ParseEngine& operator=(ParseEngine &&);\n    ParseEngine& operator=(ParseEngine const&);\n\n    /** @} */\n\npublic:\n\n    /** @name modifiers */\n    /** @{ */\n\n    /** Reserve a certain capacity for the parsing stack.\n     * This should be larger than the expected depth of the parsed\n     * YAML tree.\n     *\n     * The parsing stack is the only (potential) heap memory used\n     * directly by the parser.\n     *\n     * If the requested capacity is below the default\n     * stack size of 16, the memory is used directly in the parser\n     * object; otherwise it will be allocated from the heap.\n     *\n     * @note this reserves memory only for the parser itself; all the\n     * allocations for the parsed tree will go through the tree's\n     * allocator (when different).\n     *\n     * @note for maximum efficiency, the tree and the arena can (and\n     * should) also be reserved. */\n    void reserve_stack(id_type capacity)\n    {\n        m_evt_handler->m_stack.reserve(capacity);\n    }\n\n    /** Reserve a certain capacity for the array used to track node\n     * locations in the source buffer. */\n    void reserve_locations(size_t num_source_lines)\n    {\n        _resize_locations(num_source_lines);\n    }\n\n    RYML_DEPRECATED(\"filter arena no longer needed\")\n    void reserve_filter_arena(size_t) {}\n\n    /** @} */\n\npublic:\n\n    /** @name getters */\n    /** @{ */\n\n    /** Get the options used to build this parser object. */\n    ParserOptions const& options() const { return m_options; }\n\n    /** Get the current callbacks in the parser. */\n    Callbacks const& callbacks() const { RYML_ASSERT(m_evt_handler); return m_evt_handler->m_stack.m_callbacks; }\n\n    /** Get the name of the latest file parsed by this object. */\n    csubstr filename() const { return m_file; }\n\n    /** Get the latest YAML buffer parsed by this object. */\n    csubstr source() const { return m_buf; }\n\n    id_type stack_capacity() const { RYML_ASSERT(m_evt_handler); return m_evt_handler->m_stack.capacity(); }\n    size_t locations_capacity() const { return m_newline_offsets_capacity; }\n\n    RYML_DEPRECATED(\"filter arena no longer needed\")\n    size_t filter_arena_capacity() const { return 0u; }\n\n    /** @} */\n\npublic:\n\n    /** @name parse methods */\n    /** @{ */\n\n    /** parse YAML in place, emitting events to the current handler */\n    void parse_in_place_ev(csubstr filename, substr src);\n\n    /** parse JSON in place, emitting events to the current handler */\n    void parse_json_in_place_ev(csubstr filename, substr src);\n\n    /** @} */\n\npublic:\n\n    /** @name deprecated parse methods\n     * @{ */\n\n    /** @cond dev */\n    template<class U=EventHandler> RYML_DEPRECATED(\"removed, deliberately undefined. use the freestanding function in parse.hpp.\") typename std::enable_if<U::is_wtree, void>::type parse_in_place(csubstr filename, substr yaml, Tree *t, size_t node_id);\n    template<class U=EventHandler> RYML_DEPRECATED(\"removed, deliberately undefined. use the freestanding function in parse.hpp.\") typename std::enable_if<U::is_wtree, void>::type parse_in_place(                  substr yaml, Tree *t, size_t node_id);\n    template<class U=EventHandler> RYML_DEPRECATED(\"removed, deliberately undefined. use the freestanding function in parse.hpp.\") typename std::enable_if<U::is_wtree, void>::type parse_in_place(csubstr filename, substr yaml, Tree *t                );\n    template<class U=EventHandler> RYML_DEPRECATED(\"removed, deliberately undefined. use the freestanding function in parse.hpp.\") typename std::enable_if<U::is_wtree, void>::type parse_in_place(                  substr yaml, Tree *t                );\n    template<class U=EventHandler> RYML_DEPRECATED(\"removed, deliberately undefined. use the freestanding function in parse.hpp.\") typename std::enable_if<U::is_wtree, void>::type parse_in_place(csubstr filename, substr yaml, NodeRef node           );\n    template<class U=EventHandler> RYML_DEPRECATED(\"removed, deliberately undefined. use the freestanding function in parse.hpp.\") typename std::enable_if<U::is_wtree, void>::type parse_in_place(                  substr yaml, NodeRef node           );\n    template<class U=EventHandler> RYML_DEPRECATED(\"removed, deliberately undefined. use the freestanding function in parse.hpp.\") typename std::enable_if<U::is_wtree, Tree>::type parse_in_place(csubstr filename, substr yaml                         );\n    template<class U=EventHandler> RYML_DEPRECATED(\"removed, deliberately undefined. use the freestanding function in parse.hpp.\") typename std::enable_if<U::is_wtree, Tree>::type parse_in_place(                  substr yaml                         );\n    template<class U=EventHandler> RYML_DEPRECATED(\"removed, deliberately undefined. use the freestanding function in parse.hpp.\") typename std::enable_if<U::is_wtree, void>::type parse_in_arena(csubstr filename, csubstr yaml, Tree *t, size_t node_id);\n    template<class U=EventHandler> RYML_DEPRECATED(\"removed, deliberately undefined. use the freestanding function in parse.hpp.\") typename std::enable_if<U::is_wtree, void>::type parse_in_arena(                  csubstr yaml, Tree *t, size_t node_id);\n    template<class U=EventHandler> RYML_DEPRECATED(\"removed, deliberately undefined. use the freestanding function in parse.hpp.\") typename std::enable_if<U::is_wtree, void>::type parse_in_arena(csubstr filename, csubstr yaml, Tree *t                );\n    template<class U=EventHandler> RYML_DEPRECATED(\"removed, deliberately undefined. use the freestanding function in parse.hpp.\") typename std::enable_if<U::is_wtree, void>::type parse_in_arena(                  csubstr yaml, Tree *t                );\n    template<class U=EventHandler> RYML_DEPRECATED(\"removed, deliberately undefined. use the freestanding function in parse.hpp.\") typename std::enable_if<U::is_wtree, void>::type parse_in_arena(csubstr filename, csubstr yaml, NodeRef node           );\n    template<class U=EventHandler> RYML_DEPRECATED(\"removed, deliberately undefined. use the freestanding function in parse.hpp.\") typename std::enable_if<U::is_wtree, void>::type parse_in_arena(                  csubstr yaml, NodeRef node           );\n    template<class U=EventHandler> RYML_DEPRECATED(\"removed, deliberately undefined. use the freestanding function in parse.hpp.\") typename std::enable_if<U::is_wtree, Tree>::type parse_in_arena(csubstr filename, csubstr yaml                         );\n    template<class U=EventHandler> RYML_DEPRECATED(\"removed, deliberately undefined. use the freestanding function in parse.hpp.\") typename std::enable_if<U::is_wtree, Tree>::type parse_in_arena(                  csubstr yaml                         );\n    template<class U=EventHandler> RYML_DEPRECATED(\"removed, deliberately undefined. use the freestanding csubstr version in parse.hpp.\") typename std::enable_if<U::is_wtree, void>::type parse_in_arena(csubstr filename, substr yaml, Tree *t, size_t node_id);\n    template<class U=EventHandler> RYML_DEPRECATED(\"removed, deliberately undefined. use the freestanding csubstr version in parse.hpp.\") typename std::enable_if<U::is_wtree, void>::type parse_in_arena(                  substr yaml, Tree *t, size_t node_id);\n    template<class U=EventHandler> RYML_DEPRECATED(\"removed, deliberately undefined. use the freestanding csubstr version in parse.hpp.\") typename std::enable_if<U::is_wtree, void>::type parse_in_arena(csubstr filename, substr yaml, Tree *t                );\n    template<class U=EventHandler> RYML_DEPRECATED(\"removed, deliberately undefined. use the freestanding csubstr version in parse.hpp.\") typename std::enable_if<U::is_wtree, void>::type parse_in_arena(                  substr yaml, Tree *t                );\n    template<class U=EventHandler> RYML_DEPRECATED(\"removed, deliberately undefined. use the freestanding csubstr version in parse.hpp.\") typename std::enable_if<U::is_wtree, void>::type parse_in_arena(csubstr filename, substr yaml, NodeRef node           );\n    template<class U=EventHandler> RYML_DEPRECATED(\"removed, deliberately undefined. use the freestanding csubstr version in parse.hpp.\") typename std::enable_if<U::is_wtree, void>::type parse_in_arena(                  substr yaml, NodeRef node           );\n    template<class U=EventHandler> RYML_DEPRECATED(\"removed, deliberately undefined. use the freestanding csubstr version in parse.hpp.\") typename std::enable_if<U::is_wtree, Tree>::type parse_in_arena(csubstr filename, substr yaml                         );\n    template<class U=EventHandler> RYML_DEPRECATED(\"removed, deliberately undefined. use the freestanding csubstr version in parse.hpp.\") typename std::enable_if<U::is_wtree, Tree>::type parse_in_arena(                  substr yaml                         );\n    /** @endcond */\n\n    /** @} */\n\npublic:\n\n    /** @name locations */\n    /** @{ */\n\n    /** Get the location of a node of the last tree to be parsed by this parser. */\n    Location location(Tree const& tree, id_type node_id) const;\n    /** Get the location of a node of the last tree to be parsed by this parser. */\n    Location location(ConstNodeRef node) const;\n    /** Get the string starting at a particular location, to the end\n     * of the parsed source buffer. */\n    csubstr location_contents(Location const& loc) const;\n    /** Given a pointer to a buffer position, get the location.\n     * @param[in] val must be pointing to somewhere in the source\n     * buffer that was last parsed by this object. */\n    Location val_location(const char *val) const;\n\n    /** @} */\n\npublic:\n\n    /** @name scalar filtering */\n    /** @{*/\n\n    /** filter a plain scalar */\n    FilterResult filter_scalar_plain(csubstr scalar, substr dst, size_t indentation);\n    /** filter a plain scalar in place */\n    FilterResult filter_scalar_plain_in_place(substr scalar, size_t cap, size_t indentation);\n\n    /** filter a single-quoted scalar */\n    FilterResult filter_scalar_squoted(csubstr scalar, substr dst);\n    /** filter a single-quoted scalar in place */\n    FilterResult filter_scalar_squoted_in_place(substr scalar, size_t cap);\n\n    /** filter a double-quoted scalar */\n    FilterResult filter_scalar_dquoted(csubstr scalar, substr dst);\n    /** filter a double-quoted scalar in place */\n    FilterResultExtending filter_scalar_dquoted_in_place(substr scalar, size_t cap);\n\n    /** filter a block-literal scalar */\n    FilterResult filter_scalar_block_literal(csubstr scalar, substr dst, size_t indentation, BlockChomp_e chomp);\n    /** filter a block-literal scalar in place */\n    FilterResult filter_scalar_block_literal_in_place(substr scalar, size_t cap, size_t indentation, BlockChomp_e chomp);\n\n    /** filter a block-folded scalar */\n    FilterResult filter_scalar_block_folded(csubstr scalar, substr dst, size_t indentation, BlockChomp_e chomp);\n    /** filter a block-folded scalar in place */\n    FilterResult filter_scalar_block_folded_in_place(substr scalar, size_t cap, size_t indentation, BlockChomp_e chomp);\n\n    /** @} */\n\nprivate:\n\n    struct ScannedScalar\n    {\n        substr scalar;\n        bool needs_filter;\n    };\n\n    struct ScannedBlock\n    {\n        substr scalar;\n        size_t indentation;\n        BlockChomp_e chomp;\n    };\n\n    bool    _is_doc_begin(csubstr s);\n    bool    _is_doc_end(csubstr s);\n\n    bool    _scan_scalar_plain_blck(ScannedScalar *C4_RESTRICT sc, size_t indentation);\n    bool    _scan_scalar_plain_seq_flow(ScannedScalar *C4_RESTRICT sc);\n    bool    _scan_scalar_plain_seq_blck(ScannedScalar *C4_RESTRICT sc);\n    bool    _scan_scalar_plain_map_flow(ScannedScalar *C4_RESTRICT sc);\n    bool    _scan_scalar_plain_map_blck(ScannedScalar *C4_RESTRICT sc);\n    bool    _scan_scalar_map_json(ScannedScalar *C4_RESTRICT sc);\n    bool    _scan_scalar_seq_json(ScannedScalar *C4_RESTRICT sc);\n    bool    _scan_scalar_plain_unk(ScannedScalar *C4_RESTRICT sc);\n    bool    _is_valid_start_scalar_plain_flow(csubstr s);\n\n    ScannedScalar _scan_scalar_squot();\n    ScannedScalar _scan_scalar_dquot();\n\n    void    _scan_block(ScannedBlock *C4_RESTRICT sb, size_t indref);\n\n    csubstr _scan_anchor();\n    csubstr _scan_ref_seq();\n    csubstr _scan_ref_map();\n    csubstr _scan_tag();\n\npublic: // exposed for testing\n\n    /** @cond dev */\n    csubstr _filter_scalar_plain(substr s, size_t indentation);\n    csubstr _filter_scalar_squot(substr s);\n    csubstr _filter_scalar_dquot(substr s);\n    csubstr _filter_scalar_literal(substr s, size_t indentation, BlockChomp_e chomp);\n    csubstr _filter_scalar_folded(substr s, size_t indentation, BlockChomp_e chomp);\n\n    csubstr _maybe_filter_key_scalar_plain(ScannedScalar const& sc, size_t indendation);\n    csubstr _maybe_filter_val_scalar_plain(ScannedScalar const& sc, size_t indendation);\n    csubstr _maybe_filter_key_scalar_squot(ScannedScalar const& sc);\n    csubstr _maybe_filter_val_scalar_squot(ScannedScalar const& sc);\n    csubstr _maybe_filter_key_scalar_dquot(ScannedScalar const& sc);\n    csubstr _maybe_filter_val_scalar_dquot(ScannedScalar const& sc);\n    csubstr _maybe_filter_key_scalar_literal(ScannedBlock const& sb);\n    csubstr _maybe_filter_val_scalar_literal(ScannedBlock const& sb);\n    csubstr _maybe_filter_key_scalar_folded(ScannedBlock const& sb);\n    csubstr _maybe_filter_val_scalar_folded(ScannedBlock const& sb);\n    /** @endcond */\n\nprivate:\n\n    void  _handle_map_block();\n    void  _handle_seq_block();\n    void  _handle_map_flow();\n    void  _handle_seq_flow();\n    void  _handle_seq_imap();\n    void  _handle_map_json();\n    void  _handle_seq_json();\n\n    void  _handle_unk();\n    void  _handle_unk_json();\n    void  _handle_usty();\n\n    void  _handle_flow_skip_whitespace();\n\n    void  _end_map_blck();\n    void  _end_seq_blck();\n    void  _end2_map();\n    void  _end2_seq();\n\n    void  _begin2_doc();\n    void  _begin2_doc_expl();\n    void  _end2_doc();\n    void  _end2_doc_expl();\n\n    void  _maybe_begin_doc();\n    void  _maybe_end_doc();\n\n    void  _start_doc_suddenly();\n    void  _end_doc_suddenly();\n    void  _end_doc_suddenly__pop();\n    void  _end_stream();\n\n    void  _set_indentation(size_t indentation);\n    void  _save_indentation();\n    void  _handle_indentation_pop_from_block_seq();\n    void  _handle_indentation_pop_from_block_map();\n    void  _handle_indentation_pop(ParserState const* dst);\n\n    void _maybe_skip_comment();\n    void _skip_comment();\n    void _maybe_skip_whitespace_tokens();\n    void _maybe_skipchars(char c);\n    #ifdef RYML_NO_COVERAGE__TO_BE_DELETED\n    void _maybe_skipchars_up_to(char c, size_t max_to_skip);\n    #endif\n    template<size_t N>\n    void _skipchars(const char (&chars)[N]);\n    bool _maybe_scan_following_colon() noexcept;\n    bool _maybe_scan_following_comma() noexcept;\n\npublic:\n\n    /** @cond dev */\n    template<class FilterProcessor> auto _filter_plain(FilterProcessor &C4_RESTRICT proc, size_t indentation) -> decltype(proc.result());\n    template<class FilterProcessor> auto _filter_squoted(FilterProcessor &C4_RESTRICT proc) -> decltype(proc.result());\n    template<class FilterProcessor> auto _filter_dquoted(FilterProcessor &C4_RESTRICT proc) -> decltype(proc.result());\n    template<class FilterProcessor> auto _filter_block_literal(FilterProcessor &C4_RESTRICT proc, size_t indentation, BlockChomp_e chomp) -> decltype(proc.result());\n    template<class FilterProcessor> auto _filter_block_folded(FilterProcessor &C4_RESTRICT proc, size_t indentation, BlockChomp_e chomp) -> decltype(proc.result());\n    /** @endcond */\n\npublic:\n\n    /** @cond dev */\n    template<class FilterProcessor> void   _filter_nl_plain(FilterProcessor &C4_RESTRICT proc, size_t indentation);\n    template<class FilterProcessor> void   _filter_nl_squoted(FilterProcessor &C4_RESTRICT proc);\n    template<class FilterProcessor> void   _filter_nl_dquoted(FilterProcessor &C4_RESTRICT proc);\n\n    template<class FilterProcessor> bool   _filter_ws_handle_to_first_non_space(FilterProcessor &C4_RESTRICT proc);\n    template<class FilterProcessor> void   _filter_ws_copy_trailing(FilterProcessor &C4_RESTRICT proc);\n    template<class FilterProcessor> void   _filter_ws_skip_trailing(FilterProcessor &C4_RESTRICT proc);\n\n    template<class FilterProcessor> void   _filter_dquoted_backslash(FilterProcessor &C4_RESTRICT proc);\n\n    template<class FilterProcessor> void   _filter_chomp(FilterProcessor &C4_RESTRICT proc, BlockChomp_e chomp, size_t indentation);\n    template<class FilterProcessor> size_t _handle_all_whitespace(FilterProcessor &C4_RESTRICT proc, BlockChomp_e chomp);\n    template<class FilterProcessor> size_t _extend_to_chomp(FilterProcessor &C4_RESTRICT proc, size_t contents_len);\n    template<class FilterProcessor> void   _filter_block_indentation(FilterProcessor &C4_RESTRICT proc, size_t indentation);\n    template<class FilterProcessor> void   _filter_block_folded_newlines(FilterProcessor &C4_RESTRICT proc, size_t indentation, size_t len);\n    template<class FilterProcessor> size_t _filter_block_folded_newlines_compress(FilterProcessor &C4_RESTRICT proc, size_t num_newl, size_t wpos_at_first_newl);\n    template<class FilterProcessor> void   _filter_block_folded_newlines_leading(FilterProcessor &C4_RESTRICT proc, size_t indentation, size_t len);\n    template<class FilterProcessor> void   _filter_block_folded_indented_block(FilterProcessor &C4_RESTRICT proc, size_t indentation, size_t len, size_t curr_indentation) noexcept;\n\n    /** @endcond */\n\nprivate:\n\n    void _line_progressed(size_t ahead);\n    void _line_ended();\n    void _line_ended_undo();\n\n    bool  _finished_file() const;\n    bool  _finished_line() const;\n\n    void   _scan_line();\n    substr _peek_next_line(size_t pos=npos) const;\n\n    inline bool _at_line_begin() const\n    {\n        return m_evt_handler->m_curr->line_contents.rem.begin() == m_evt_handler->m_curr->line_contents.full.begin();\n    }\n\n    void _relocate_arena(csubstr prev_arena, substr next_arena);\n    static void _s_relocate_arena(void*, csubstr prev_arena, substr next_arena);\n\nprivate:\n\n    C4_ALWAYS_INLINE bool has_all(ParserFlag_t f) const noexcept { return (m_evt_handler->m_curr->flags & f) == f; }\n    C4_ALWAYS_INLINE bool has_any(ParserFlag_t f) const noexcept { return (m_evt_handler->m_curr->flags & f) != 0; }\n    C4_ALWAYS_INLINE bool has_none(ParserFlag_t f) const noexcept { return (m_evt_handler->m_curr->flags & f) == 0; }\n    static C4_ALWAYS_INLINE bool has_all(ParserFlag_t f, ParserState const* C4_RESTRICT s) noexcept { return (s->flags & f) == f; }\n    static C4_ALWAYS_INLINE bool has_any(ParserFlag_t f, ParserState const* C4_RESTRICT s) noexcept { return (s->flags & f) != 0; }\n    static C4_ALWAYS_INLINE bool has_none(ParserFlag_t f, ParserState const* C4_RESTRICT s) noexcept { return (s->flags & f) == 0; }\n\n    #ifndef RYML_DBG\n    C4_ALWAYS_INLINE static void add_flags(ParserFlag_t on, ParserState *C4_RESTRICT s) noexcept { s->flags |= on; }\n    C4_ALWAYS_INLINE static void addrem_flags(ParserFlag_t on, ParserFlag_t off, ParserState *C4_RESTRICT s) noexcept { s->flags &= ~off; s->flags |= on; }\n    C4_ALWAYS_INLINE static void rem_flags(ParserFlag_t off, ParserState *C4_RESTRICT s) noexcept { s->flags &= ~off; }\n    C4_ALWAYS_INLINE void add_flags(ParserFlag_t on) noexcept { m_evt_handler->m_curr->flags |= on; }\n    C4_ALWAYS_INLINE void addrem_flags(ParserFlag_t on, ParserFlag_t off) noexcept { m_evt_handler->m_curr->flags &= ~off; m_evt_handler->m_curr->flags |= on; }\n    C4_ALWAYS_INLINE void rem_flags(ParserFlag_t off) noexcept { m_evt_handler->m_curr->flags &= ~off; }\n    #else\n    static void add_flags(ParserFlag_t on, ParserState *C4_RESTRICT s);\n    static void addrem_flags(ParserFlag_t on, ParserFlag_t off, ParserState *C4_RESTRICT s);\n    static void rem_flags(ParserFlag_t off, ParserState *C4_RESTRICT s);\n    C4_ALWAYS_INLINE void add_flags(ParserFlag_t on) noexcept { add_flags(on, m_evt_handler->m_curr); }\n    C4_ALWAYS_INLINE void addrem_flags(ParserFlag_t on, ParserFlag_t off) noexcept { addrem_flags(on, off, m_evt_handler->m_curr); }\n    C4_ALWAYS_INLINE void rem_flags(ParserFlag_t off) noexcept { rem_flags(off, m_evt_handler->m_curr); }\n    #endif\n\nprivate:\n\n    void _prepare_locations();\n    void _resize_locations(size_t sz);\n    bool _locations_dirty() const;\n\n    bool _location_from_cont(Tree const& tree, id_type node, Location *C4_RESTRICT loc) const;\n    bool _location_from_node(Tree const& tree, id_type node, Location *C4_RESTRICT loc, id_type level) const;\n\nprivate:\n\n    void _reset();\n    void _free();\n    void _clr();\n\n    #ifdef RYML_DBG\n    template<class ...Args> void _dbg(csubstr fmt, Args const& C4_RESTRICT ...args) const;\n    #endif\n    template<class ...Args> void _err(csubstr fmt, Args const& C4_RESTRICT ...args) const;\n    template<class ...Args> void _errloc(csubstr fmt, Location const& loc, Args const& C4_RESTRICT ...args) const;\n\n    template<class DumpFn>  void _fmt_msg(DumpFn &&dumpfn) const;\n\nprivate:\n\n    /** store pending tag or anchor/ref annotations */\n    struct Annotation\n    {\n        struct Entry\n        {\n            csubstr str;\n            size_t indentation;\n            size_t line;\n        };\n        Entry annotations[2];\n        size_t num_entries;\n    };\n\n    void _add_annotation(Annotation *C4_RESTRICT dst, csubstr str, size_t indentation, size_t line);\n    void _clear_annotations(Annotation *C4_RESTRICT dst);\n    bool _has_pending_annotations() const { return m_pending_tags.num_entries || m_pending_anchors.num_entries; }\n    #ifdef RYML_NO_COVERAGE__TO_BE_DELETED\n    bool _handle_indentation_from_annotations();\n    #endif\n    bool _annotations_require_key_container() const;\n    void _handle_annotations_before_blck_key_scalar();\n    void _handle_annotations_before_blck_val_scalar();\n    void _handle_annotations_before_start_mapblck(size_t current_line);\n    void _handle_annotations_before_start_mapblck_as_key();\n    void _handle_annotations_and_indentation_after_start_mapblck(size_t key_indentation, size_t key_line);\n    size_t _select_indentation_from_annotations(size_t val_indentation, size_t val_line);\n    void _handle_directive(csubstr rem);\n\n    void _check_tag(csubstr tag);\n\nprivate:\n\n    ParserOptions m_options;\n\n    csubstr m_file;\n    substr  m_buf;\n\npublic:\n\n    /** @cond dev */\n    EventHandler *C4_RESTRICT m_evt_handler;\n    /** @endcond */\n\nprivate:\n\n    Annotation m_pending_anchors;\n    Annotation m_pending_tags;\n\n    bool m_was_inside_qmrk;\n    bool m_doc_empty = true;\n\nprivate:\n\n    size_t *m_newline_offsets;\n    size_t  m_newline_offsets_size;\n    size_t  m_newline_offsets_capacity;\n    csubstr m_newline_offsets_buf;\n\n};\n\n/** @cond dev */\nRYML_EXPORT C4_NO_INLINE size_t _find_last_newline_and_larger_indentation(csubstr s, size_t indentation) noexcept;\n/** @endcond */\n\n\n/** Quickly inspect the source to estimate the number of nodes the\n * resulting tree is likely have. If a tree is empty before\n * parsing, considerable time will be spent growing it, so calling\n * this to reserve the tree size prior to parsing is likely to\n * result in a time gain. We encourage using this method before\n * parsing, but as always measure its impact in performance to\n * obtain a good trade-off.\n *\n * @note since this method is meant for optimizing performance, it\n * is approximate. The result may be actually smaller than the\n * resulting number of nodes, notably if the YAML uses implicit\n * maps as flow seq members as in `[these: are, individual:\n * maps]`. */\nRYML_EXPORT id_type estimate_tree_capacity(csubstr src);\n\n/** @} */\n\n} // namespace yml\n} // namespace c4\n\n#if defined(_MSC_VER)\n#   pragma warning(pop)\n#endif\n\n#endif /* _C4_YML_PARSE_ENGINE_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/yml/parser_state.hpp",
    "content": "#ifndef _C4_YML_PARSER_STATE_HPP_\n#define _C4_YML_PARSER_STATE_HPP_\n\n#ifndef _C4_YML_COMMON_HPP_\n#include \"c4/yml/common.hpp\"\n#endif\n\nnamespace c4 {\nnamespace yml {\n\n/** data type for @ref ParserState_e */\nusing ParserFlag_t = int;\n\n/** Enumeration of the state flags for the parser */\ntypedef enum : ParserFlag_t {\n    RTOP = 0x01 <<  0,   ///< reading at top level\n    RUNK = 0x01 <<  1,   ///< reading unknown state (when starting): must determine whether scalar, map or seq\n    RMAP = 0x01 <<  2,   ///< reading a map\n    RSEQ = 0x01 <<  3,   ///< reading a seq\n    FLOW = 0x01 <<  4,   ///< reading is inside explicit flow chars: [] or {}\n    BLCK = 0x01 <<  5,   ///< reading in block mode\n    QMRK = 0x01 <<  6,   ///< reading an explicit key (`? key`)\n    RKEY = 0x01 <<  7,   ///< reading a scalar as key\n    RVAL = 0x01 <<  9,   ///< reading a scalar as val\n    RKCL = 0x01 <<  8,   ///< reading the key colon (ie the : after the key in the map)\n    RNXT = 0x01 << 10,   ///< read next val or keyval\n    SSCL = 0x01 << 11,   ///< there's a stored scalar\n    QSCL = 0x01 << 12,   ///< stored scalar was quoted\n    RSET = 0x01 << 13,   ///< the (implicit) map being read is a !!set. @see https://yaml.org/type/set.html\n    RDOC = 0x01 << 14,   ///< reading a document\n    NDOC = 0x01 << 15,   ///< no document mode. a document has ended and another has not started yet.\n    USTY = 0x01 << 16,   ///< reading in unknown style mode - must determine FLOW or BLCK\n    //! reading an implicit map nested in an explicit seq.\n    //! eg, {key: [key2: value2, key3: value3]}\n    //! is parsed as {key: [{key2: value2}, {key3: value3}]}\n    RSEQIMAP = 0x01 << 17,\n} ParserState_e;\n\n#ifdef RYML_DBG\n/** @cond dev */\nnamespace detail {\ncsubstr _parser_flags_to_str(substr buf, ParserFlag_t flags);\n} // namespace\n/** @endcond */\n#endif\n\n\n/** Helper to control the line contents while parsing a buffer */\nstruct LineContents\n{\n    substr  rem;         ///< the stripped line remainder; initially starts at the first non-space character\n    size_t  indentation; ///< the number of spaces on the beginning of the line\n    substr  full;        ///< the full line, including newlines on the right\n    substr  stripped;    ///< the stripped line, excluding newlines on the right\n\n    LineContents() = default;\n\n    void reset_with_next_line(substr buf, size_t offset)\n    {\n        RYML_ASSERT(offset <= buf.len);\n        size_t e = offset;\n        // get the current line stripped of newline chars\n        while(e < buf.len && (buf.str[e] != '\\n' && buf.str[e] != '\\r'))\n            ++e;\n        RYML_ASSERT(e >= offset);\n        const substr stripped_ = buf.range(offset, e);\n        // advance pos to include the first line ending\n        if(e < buf.len && buf.str[e] == '\\r')\n            ++e;\n        if(e < buf.len && buf.str[e] == '\\n')\n            ++e;\n        const substr full_ = buf.range(offset, e);\n        reset(full_, stripped_);\n    }\n\n    void reset(substr full_, substr stripped_)\n    {\n        rem = stripped_;\n        indentation = stripped_.first_not_of(' ');  // find the first column where the character is not a space\n        full = full_;\n        stripped = stripped_;\n    }\n\n    C4_ALWAYS_INLINE size_t current_col() const RYML_NOEXCEPT\n    {\n        // WARNING: gcc x86 release builds were wrong (eg returning 0\n        // when the result should be 4 ) when this function was like\n        // this:\n        //\n        //return current_col(rem);\n        //\n        // (see below for the full definition of the called overload\n        // of current_col())\n        //\n        // ... so we explicitly inline the code in here:\n        RYML_ASSERT(rem.str >= full.str);\n        size_t col = static_cast<size_t>(rem.str - full.str);\n        return col;\n        //\n        // this was happening only on builds specifically with (gcc\n        // AND x86 AND release); no other builds were having the\n        // problem: not in debug, not in x64, not in other\n        // architectures, not in clang, not in visual studio. WTF!?\n        //\n        // Enabling debug prints with RYML_DBG made the problem go\n        // away, so these could not be used to debug the\n        // problem. Adding prints inside the called current_col() also\n        // made the problem go away! WTF!???\n        //\n        // a prize will be offered to anybody able to explain why this\n        // was happening.\n    }\n\n    C4_ALWAYS_INLINE size_t current_col(csubstr s) const RYML_NOEXCEPT\n    {\n        RYML_ASSERT(s.str >= full.str);\n        RYML_ASSERT(full.is_super(s));\n        size_t col = static_cast<size_t>(s.str - full.str);\n        return col;\n    }\n};\nstatic_assert(std::is_standard_layout<LineContents>::value, \"LineContents not standard\");\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\nstruct ParserState\n{\n    LineContents line_contents;\n    Location     pos;\n    ParserFlag_t flags;\n    size_t       indref;  ///< the reference indentation in the current block scope\n    id_type      level;\n    id_type      node_id; ///< don't hold a pointer to the node as it will be relocated during tree resizes\n    size_t       scalar_col; // the column where the scalar (or its quotes) begin\n    bool         more_indented;\n    bool         has_children;\n\n    ParserState() = default;\n\n    void start_parse(const char *file, id_type node_id_)\n    {\n        level = 0;\n        pos.name = to_csubstr(file);\n        pos.offset = 0;\n        pos.line = 1;\n        pos.col = 1;\n        node_id = node_id_;\n        more_indented = false;\n        scalar_col = 0;\n        indref = 0;\n        has_children = false;\n    }\n\n    void reset_after_push()\n    {\n        node_id = NONE;\n        indref = npos;\n        more_indented = false;\n        ++level;\n        has_children = false;\n    }\n\n    C4_ALWAYS_INLINE void reset_before_pop(ParserState const& to_pop)\n    {\n        pos = to_pop.pos;\n        line_contents = to_pop.line_contents;\n    }\n\npublic:\n\n    C4_ALWAYS_INLINE bool at_line_beginning() const noexcept\n    {\n        return line_contents.rem.str == line_contents.full.str;\n    }\n    C4_ALWAYS_INLINE bool indentation_eq() const noexcept\n    {\n        RYML_ASSERT(indref != npos);\n        return line_contents.indentation != npos && line_contents.indentation == indref;\n    }\n    C4_ALWAYS_INLINE bool indentation_ge() const noexcept\n    {\n        RYML_ASSERT(indref != npos);\n        return line_contents.indentation != npos && line_contents.indentation >= indref;\n    }\n    C4_ALWAYS_INLINE bool indentation_gt() const noexcept\n    {\n        RYML_ASSERT(indref != npos);\n        return line_contents.indentation != npos && line_contents.indentation > indref;\n    }\n    C4_ALWAYS_INLINE bool indentation_lt() const noexcept\n    {\n        RYML_ASSERT(indref != npos);\n        return line_contents.indentation != npos && line_contents.indentation < indref;\n    }\n};\nstatic_assert(std::is_standard_layout<ParserState>::value, \"ParserState not standard\");\n\n\n} // namespace yml\n} // namespace c4\n\n#endif /* _C4_YML_PARSER_STATE_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/yml/preprocess.cpp",
    "content": "#include \"c4/yml/preprocess.hpp\"\n#include \"c4/yml/detail/parser_dbg.hpp\"\n\n/** @file preprocess.hpp Functions for preprocessing YAML prior to parsing. */\n\nnamespace c4 {\nnamespace yml {\n\nC4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH(\"-Wold-style-cast\")\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\nnamespace {\nC4_ALWAYS_INLINE bool _is_idchar(char c)\n{\n    return (c >= 'a' && c <= 'z')\n        || (c >= 'A' && c <= 'Z')\n        || (c >= '0' && c <= '9')\n        || (c == '_' || c == '-' || c == '~' || c == '$');\n}\n\ntypedef enum { kReadPending = 0, kKeyPending = 1, kValPending = 2 } _ppstate;\nC4_ALWAYS_INLINE _ppstate _next(_ppstate s)\n{\n    int n = (int)s + 1;\n    return (_ppstate)(n <= (int)kValPending ? n : 0);\n}\n} // empty namespace\n\n\n//-----------------------------------------------------------------------------\n\nsize_t preprocess_rxmap(csubstr s, substr buf)\n{\n    detail::_SubstrWriter writer(buf);\n    _ppstate state = kReadPending;\n    size_t last = 0;\n\n    if(s.begins_with('{'))\n    {\n        RYML_CHECK(s.ends_with('}'));\n        s = s.offs(1, 1);\n    }\n\n    writer.append('{');\n\n    for(size_t i = 0; i < s.len; ++i)\n    {\n        const char curr = s[i];\n        const char next = i+1 < s.len ? s[i+1] : '\\0';\n\n        if(curr == '\\'' || curr == '\"')\n        {\n            csubstr ss = s.sub(i).pair_range_esc(curr, '\\\\');\n            i += static_cast<size_t>(ss.end() - (s.str + i));\n            state = _next(state);\n        }\n        else if(state == kReadPending && _is_idchar(curr))\n        {\n            state = _next(state);\n        }\n\n        switch(state)\n        {\n        case kKeyPending:\n        {\n            if(curr == ':' && next == ' ')\n            {\n                state = _next(state);\n            }\n            else if(curr == ',' && next == ' ')\n            {\n                writer.append(s.range(last, i));\n                writer.append(\": 1, \");\n                last = i + 2;\n            }\n            break;\n        }\n        case kValPending:\n        {\n            if(curr == '[' || curr == '{' || curr == '(')\n            {\n                csubstr ss = s.sub(i).pair_range_nested(curr, '\\\\');\n                i += static_cast<size_t>(ss.end() - (s.str + i));\n                state = _next(state);\n            }\n            else if(curr == ',' && next == ' ')\n            {\n                state = _next(state);\n            }\n            break;\n        }\n        default:\n            // nothing to do\n            break;\n        }\n    }\n\n    writer.append(s.sub(last));\n    if(state == kKeyPending)\n        writer.append(\": 1\");\n    writer.append('}');\n\n    return writer.pos;\n}\n\nC4_SUPPRESS_WARNING_GCC_CLANG_POP\n\n} // namespace yml\n} // namespace c4\n"
  },
  {
    "path": "libs/rapidyaml/c4/yml/preprocess.hpp",
    "content": "#ifndef _C4_YML_PREPROCESS_HPP_\n#define _C4_YML_PREPROCESS_HPP_\n\n/** @file preprocess.hpp Functions for preprocessing YAML prior to parsing. */\n\n#ifndef _C4_YML_COMMON_HPP_\n#include \"./common.hpp\"\n#endif\n#include <c4/substr.hpp>\n\n\nnamespace c4 {\nnamespace yml {\n\n/** @addtogroup doc_preprocessors\n * @{\n */\n\n/** @cond dev */\nnamespace detail {\nusing Preprocessor = size_t(csubstr, substr);\ntemplate<Preprocessor PP, class CharContainer>\nsubstr preprocess_into_container(csubstr input, CharContainer *out)\n{\n    // try to write once. the preprocessor will stop writing at the end of\n    // the container, but will process all the input to determine the\n    // required container size.\n    size_t sz = PP(input, to_substr(*out));\n    // if the container size is not enough, resize, and run again in the\n    // resized container\n    if(sz > out->size())\n    {\n        out->resize(sz);\n        sz = PP(input, to_substr(*out));\n    }\n    return to_substr(*out).first(sz);\n}\n} // namespace detail\n/** @endcond */\n\n\n//-----------------------------------------------------------------------------\n\n/** @defgroup doc_preprocess_rxmap preprocess_rxmap\n *\n * @brief Convert flow-type relaxed maps (with implicit bools) into strict YAML\n * flow map:\n *\n * @code{.yaml}\n * {a, b, c, d: [e, f], g: {a, b}}\n * # is converted into this:\n * {a: 1, b: 1, c: 1, d: [e, f], g: {a, b}}\n * @endcode\n\n * @note this is NOT recursive - conversion happens only in the top-level map\n * @param rxmap A relaxed map\n * @param buf output buffer\n * @param out output container\n *\n * @{\n */\n\n/** Write into a given output buffer. This function is safe to call with\n * empty or small buffers; it won't write beyond the end of the buffer.\n *\n * @return the number of characters required for output\n */\nRYML_EXPORT size_t preprocess_rxmap(csubstr rxmap, substr buf);\n\n\n/** Write into an existing container. It is resized to contained the output.\n * @return a substr of the container\n * @overload preprocess_rxmap */\ntemplate<class CharContainer>\nsubstr preprocess_rxmap(csubstr rxmap, CharContainer *out)\n{\n    return detail::preprocess_into_container<preprocess_rxmap>(rxmap, out);\n}\n\n\n/** Create a container with the result.\n * @overload preprocess_rxmap */\ntemplate<class CharContainer>\nCharContainer preprocess_rxmap(csubstr rxmap)\n{\n    CharContainer out;\n    preprocess_rxmap(rxmap, &out);\n    return out;\n}\n\n/** @} */ // preprocess_rxmap\n/** @} */ // group\n\n} // namespace yml\n} // namespace c4\n\n#endif /* _C4_YML_PREPROCESS_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/yml/reference_resolver.cpp",
    "content": "#include \"c4/yml/reference_resolver.hpp\"\n#include \"c4/dump.hpp\" // this is needed to resolve a function in the next header\n#include \"c4/yml/common.hpp\"\n#include \"c4/yml/detail/parser_dbg.hpp\"\n#ifdef RYML_DBG\n#include \"c4/yml/detail/print.hpp\"\n#else\n#define _c4dbg_tree(...)\n#define _c4dbg_node(...)\n#endif\n\nnamespace c4 {\nnamespace yml {\n\nid_type ReferenceResolver::count_anchors_and_refs_(id_type n)\n{\n    id_type c = 0;\n    c += m_tree->has_key_anchor(n);\n    c += m_tree->has_val_anchor(n);\n    c += m_tree->is_key_ref(n);\n    c += m_tree->is_val_ref(n);\n    c += m_tree->has_key(n) && m_tree->key(n) == \"<<\";\n    for(id_type ch = m_tree->first_child(n); ch != NONE; ch = m_tree->next_sibling(ch))\n        c += count_anchors_and_refs_(ch);\n    return c;\n}\n\nvoid ReferenceResolver::gather_anchors_and_refs__(id_type n)\n{\n    // insert key refs BEFORE inserting val refs\n    if(m_tree->has_key(n))\n    {\n        if(m_tree->key(n) == \"<<\")\n        {\n            _c4dbgpf(\"node[{}]: key is <<\", n);\n            if(m_tree->has_val(n))\n            {\n                if(m_tree->is_val_ref(n))\n                {\n                    _c4dbgpf(\"node[{}]: val ref, inheriting!\", n);\n                    m_refs.push({VALREF, n, NONE, NONE, NONE, NONE});\n                    //m_refs.push({KEYREF, n, NONE, NONE, NONE, NONE});\n                }\n                else\n                {\n                    _c4dbgpf(\"node[{}]: not ref!\", n);\n                }\n            }\n            else if(m_tree->is_seq(n))\n            {\n                // for merging multiple inheritance targets\n                //   <<: [ *CENTER, *BIG ]\n                _c4dbgpf(\"node[{}]: is seq!\", n);\n                for(id_type ich = m_tree->first_child(n); ich != NONE; ich = m_tree->next_sibling(ich))\n                {\n                    _c4dbgpf(\"node[{}]: val ref, inheriting multiple: {}\", n, ich);\n                    if(m_tree->is_container(ich))\n                    {\n                        detail::_report_err(m_tree->m_callbacks, \"ERROR: node {} child {}: refs for << cannot be containers.'\", n, ich);\n                        C4_UNREACHABLE_AFTER_ERR();\n                    }\n                    m_refs.push({VALREF, ich, NONE, NONE, n, m_tree->next_sibling(n)});\n                }\n                return; // don't descend into the seq\n            }\n            else\n            {\n                detail::_report_err(m_tree->m_callbacks, \"ERROR: node {}: refs for << must be either val or seq\", n);\n                C4_UNREACHABLE_AFTER_ERR();\n            }\n        }\n        else if(m_tree->is_key_ref(n))\n        {\n            _c4dbgpf(\"node[{}]: key ref: '{}'\", n, m_tree->key_ref(n));\n            _RYML_CB_ASSERT(m_tree->m_callbacks, m_tree->key(n) != \"<<\");\n            _RYML_CB_CHECK(m_tree->m_callbacks, (!m_tree->has_key(n)) || m_tree->key(n).ends_with(m_tree->key_ref(n)));\n            m_refs.push({KEYREF, n, NONE, NONE, NONE, NONE});\n        }\n    }\n    // val ref\n    if(m_tree->is_val_ref(n) && (!m_tree->has_key(n) || m_tree->key(n) != \"<<\"))\n    {\n        _c4dbgpf(\"node[{}]: val ref: '{}'\", n, m_tree->val_ref(n));\n        RYML_CHECK((!m_tree->has_val(n)) || m_tree->val(n).ends_with(m_tree->val_ref(n)));\n        m_refs.push({VALREF, n, NONE, NONE, NONE, NONE});\n    }\n    // anchors\n    if(m_tree->has_key_anchor(n))\n    {\n        _c4dbgpf(\"node[{}]: key anchor: '{}'\", n, m_tree->key_anchor(n));\n        RYML_CHECK(m_tree->has_key(n));\n        m_refs.push({KEYANCH, n, NONE, NONE, NONE, NONE});\n    }\n    if(m_tree->has_val_anchor(n))\n    {\n        _c4dbgpf(\"node[{}]: val anchor: '{}'\", n, m_tree->val_anchor(n));\n        RYML_CHECK(m_tree->has_val(n) || m_tree->is_container(n));\n        m_refs.push({VALANCH, n, NONE, NONE, NONE, NONE});\n    }\n    // recurse\n    for(id_type ch = m_tree->first_child(n); ch != NONE; ch = m_tree->next_sibling(ch))\n        gather_anchors_and_refs__(ch);\n}\n\nvoid ReferenceResolver::gather_anchors_and_refs_()\n{\n    _c4dbgp(\"gathering anchors and refs...\");\n\n    // minimize (re-)allocations by counting first\n    id_type num_anchors_and_refs = count_anchors_and_refs_(m_tree->root_id());\n    if(!num_anchors_and_refs)\n        return;\n    m_refs.reserve(num_anchors_and_refs);\n    m_refs.clear();\n\n    // now descend through the hierarchy\n    gather_anchors_and_refs__(m_tree->root_id());\n\n    _c4dbgpf(\"found {} anchors/refs\", m_refs.size());\n\n    // finally connect the reference list\n    id_type prev_anchor = NONE;\n    id_type count = 0;\n    for(auto &rd : m_refs)\n    {\n        rd.prev_anchor = prev_anchor;\n        if(rd.type.has_anchor())\n            prev_anchor = count;\n        ++count;\n    }\n    _c4dbgp(\"gathering anchors and refs: finished\");\n}\n\nid_type ReferenceResolver::lookup_(RefData *C4_RESTRICT ra)\n{\n    RYML_ASSERT(ra->type.is_key_ref() || ra->type.is_val_ref());\n    RYML_ASSERT(ra->type.is_key_ref() != ra->type.is_val_ref());\n    csubstr refname;\n    if(ra->type.is_val_ref())\n    {\n        refname = m_tree->val_ref(ra->node);\n    }\n    else\n    {\n        RYML_ASSERT(ra->type.is_key_ref());\n        refname = m_tree->key_ref(ra->node);\n    }\n    while(ra->prev_anchor != NONE)\n    {\n        ra = &m_refs[ra->prev_anchor];\n        if(m_tree->has_anchor(ra->node, refname))\n            return ra->node;\n    }\n    detail::_report_err(m_tree->m_callbacks, \"ERROR: anchor not found: '{}'\", refname);\n    C4_UNREACHABLE_AFTER_ERR();\n}\n\nvoid ReferenceResolver::reset_(Tree *t_)\n{\n    if(t_->callbacks() != m_refs.m_callbacks)\n    {\n        m_refs.m_callbacks = t_->callbacks();\n    }\n    m_refs.clear();\n    m_tree = t_;\n}\n\nvoid ReferenceResolver::resolve(Tree *t_)\n{\n    _c4dbgp(\"resolving references...\");\n\n    reset_(t_);\n\n    _c4dbg_tree(\"unresolved tree\", *m_tree);\n\n    gather_anchors_and_refs_();\n    if(m_refs.empty())\n        return;\n\n    /* from the specs: \"an alias node refers to the most recent\n     * node in the serialization having the specified anchor\". So\n     * we need to start looking upward from ref nodes.\n     *\n     * @see http://yaml.org/spec/1.2/spec.html#id2765878 */\n    _c4dbgp(\"matching anchors/refs...\");\n    for(id_type i = 0, e = m_refs.size(); i < e; ++i)\n    {\n        RefData &C4_RESTRICT refdata = m_refs.top(i);\n        if( ! refdata.type.is_ref())\n            continue;\n        refdata.target = lookup_(&refdata);\n    }\n    _c4dbgp(\"matching anchors/refs: finished\");\n\n    // insert the resolved references\n    _c4dbgp(\"modifying tree...\");\n    id_type prev_parent_ref = NONE;\n    id_type prev_parent_ref_after = NONE;\n    for(id_type i = 0, e = m_refs.size(); i < e; ++i)\n    {\n        RefData const& C4_RESTRICT refdata = m_refs[i];\n        _c4dbgpf(\"instance {}/{}...\", i, e);\n        if( ! refdata.type.is_ref())\n            continue;\n        _c4dbgpf(\"instance {} is reference!\", i);\n        if(refdata.parent_ref != NONE)\n        {\n            _c4dbgpf(\"ref {} has parent: {}\", i, refdata.parent_ref);\n            _RYML_CB_ASSERT(m_tree->m_callbacks, m_tree->is_seq(refdata.parent_ref));\n            const id_type p = m_tree->parent(refdata.parent_ref);\n            const id_type after = (prev_parent_ref != refdata.parent_ref) ?\n                refdata.parent_ref//prev_sibling(rd.parent_ref_sibling)\n                :\n                prev_parent_ref_after;\n            prev_parent_ref = refdata.parent_ref;\n            prev_parent_ref_after = m_tree->duplicate_children_no_rep(refdata.target, p, after);\n            m_tree->remove(refdata.node);\n        }\n        else\n        {\n            _c4dbgpf(\"ref {} has no parent\", i, refdata.parent_ref);\n            if(m_tree->has_key(refdata.node) && m_tree->key(refdata.node) == \"<<\")\n            {\n                _c4dbgpf(\"ref {} is inheriting\", i);\n                _RYML_CB_ASSERT(m_tree->m_callbacks, m_tree->is_keyval(refdata.node));\n                const id_type p = m_tree->parent(refdata.node);\n                const id_type after = m_tree->prev_sibling(refdata.node);\n                m_tree->duplicate_children_no_rep(refdata.target, p, after);\n                m_tree->remove(refdata.node);\n            }\n            else if(refdata.type.is_key_ref())\n            {\n                _c4dbgpf(\"ref {} is key ref\", i);\n                _RYML_CB_ASSERT(m_tree->m_callbacks, m_tree->is_key_ref(refdata.node));\n                _RYML_CB_ASSERT(m_tree->m_callbacks, m_tree->has_key_anchor(refdata.target) || m_tree->has_val_anchor(refdata.target));\n                if(m_tree->has_val_anchor(refdata.target) && m_tree->val_anchor(refdata.target) == m_tree->key_ref(refdata.node))\n                {\n                    _RYML_CB_CHECK(m_tree->m_callbacks, !m_tree->is_container(refdata.target));\n                    _RYML_CB_CHECK(m_tree->m_callbacks, m_tree->has_val(refdata.target));\n                    const type_bits existing_style_flags = VAL_STYLE & m_tree->_p(refdata.target)->m_type.type;\n                    static_assert((VAL_STYLE >> 1u) == (KEY_STYLE), \"bad flags\");\n                    m_tree->_p(refdata.node)->m_key.scalar = m_tree->val(refdata.target);\n                    m_tree->_add_flags(refdata.node, KEY | (existing_style_flags >> 1u));\n                }\n                else\n                {\n                    _RYML_CB_CHECK(m_tree->m_callbacks, m_tree->key_anchor(refdata.target) == m_tree->key_ref(refdata.node));\n                    m_tree->_p(refdata.node)->m_key.scalar = m_tree->key(refdata.target);\n                    // keys cannot be containers, so don't inherit container flags\n                    const type_bits existing_style_flags = KEY_STYLE & m_tree->_p(refdata.target)->m_type.type;\n                    m_tree->_add_flags(refdata.node, KEY | existing_style_flags);\n                }\n            }\n            else // val ref\n            {\n                _c4dbgpf(\"ref {} is val ref\", i);\n                _RYML_CB_ASSERT(m_tree->m_callbacks, refdata.type.is_val_ref());\n                if(m_tree->has_key_anchor(refdata.target) && m_tree->key_anchor(refdata.target) == m_tree->val_ref(refdata.node))\n                {\n                    _RYML_CB_CHECK(m_tree->m_callbacks, !m_tree->is_container(refdata.target));\n                    _RYML_CB_CHECK(m_tree->m_callbacks, m_tree->has_val(refdata.target));\n                    // keys cannot be containers, so don't inherit container flags\n                    const type_bits existing_style_flags = (KEY_STYLE) & m_tree->_p(refdata.target)->m_type.type;\n                    static_assert((KEY_STYLE << 1u) == (VAL_STYLE), \"bad flags\");\n                    m_tree->_p(refdata.node)->m_val.scalar = m_tree->key(refdata.target);\n                    m_tree->_add_flags(refdata.node, VAL | (existing_style_flags << 1u));\n                }\n                else\n                {\n                    m_tree->duplicate_contents(refdata.target, refdata.node);\n                }\n            }\n        }\n    }\n    _c4dbgp(\"modifying tree: finished\");\n\n    // clear anchors and refs\n    _c4dbgp(\"clearing anchors/refs\");\n    for(auto const& C4_RESTRICT ar : m_refs)\n    {\n        m_tree->rem_anchor_ref(ar.node);\n        if(ar.parent_ref != NONE)\n            if(m_tree->type(ar.parent_ref) != NOTYPE)\n                m_tree->remove(ar.parent_ref);\n    }\n    _c4dbgp(\"clearing anchors/refs: finished\");\n\n    _c4dbg_tree(\"resolved tree\", *m_tree);\n\n    m_tree = nullptr;\n    _c4dbgp(\"resolving references: finished\");\n}\n\n\n} // namespace ryml\n} // namespace c4\n"
  },
  {
    "path": "libs/rapidyaml/c4/yml/reference_resolver.hpp",
    "content": "#ifndef _C4_YML_REFERENCE_RESOLVER_HPP_\n#define _C4_YML_REFERENCE_RESOLVER_HPP_\n\n#include \"c4/yml/tree.hpp\"\n#include \"c4/yml/detail/stack.hpp\"\n\n\nnamespace c4 {\nnamespace yml {\n\n/** @addtogroup doc_ref_utils\n * @{\n */\n\n/** Reusable object to resolve references/aliases in the tree. */\nstruct RYML_EXPORT ReferenceResolver\n{\n    ReferenceResolver() = default;\n\n    /** Resolve references: for each reference, look for a matching\n     * anchor, and copy its contents to the ref node.\n     *\n     * This method first does a full traversal of the tree to gather\n     * all anchors and references in a separate collection, then it\n     * goes through that collection to locate the names, which it does\n     * by obeying the YAML standard diktat that \"an alias node refers\n     * to the most recent node in the serialization having the\n     * specified anchor\"\n     *\n     * So, depending on the number of anchor/alias nodes, this is a\n     * potentially expensive operation, with a best-case linear\n     * complexity (from the initial traversal).\n     *\n     * @todo verify sanity against anchor-ref attacks (https://en.wikipedia.org/wiki/Billion_laughs_attack )\n     */\n    void resolve(Tree *t_);\n\npublic:\n\n    /** @cond dev */\n\n    struct RefData\n    {\n        NodeType type;\n        id_type node;\n        id_type prev_anchor;\n        id_type target;\n        id_type parent_ref;\n        id_type parent_ref_sibling;\n    };\n\n    void reset_(Tree *t_);\n    void gather_anchors_and_refs_();\n    void gather_anchors_and_refs__(id_type n);\n    id_type count_anchors_and_refs_(id_type n);\n\n    id_type lookup_(RefData *C4_RESTRICT ra);\n\npublic:\n\n    Tree *C4_RESTRICT m_tree;\n    /** We're using this stack purely as an array. */\n    detail::stack<RefData> m_refs;\n\n    /** @endcond */\n};\n\n/** @} */\n\n} // namespace ryml\n} // namespace c4\n\n\n#endif // _C4_YML_REFERENCE_RESOLVER_HPP_\n"
  },
  {
    "path": "libs/rapidyaml/c4/yml/std/map.hpp",
    "content": "#ifndef _C4_YML_STD_MAP_HPP_\n#define _C4_YML_STD_MAP_HPP_\n\n/** @file map.hpp write/read std::map to/from a YAML tree. */\n\n#include \"c4/yml/node.hpp\"\n#include <map>\n\nnamespace c4 {\nnamespace yml {\n\n// std::map requires child nodes in the data\n// tree hierarchy (a MAP node in ryml parlance).\n// So it should be serialized via write()/read().\n\ntemplate<class K, class V, class Less, class Alloc>\nvoid write(c4::yml::NodeRef *n, std::map<K, V, Less, Alloc> const& m)\n{\n    *n |= c4::yml::MAP;\n    for(auto const& C4_RESTRICT p : m)\n    {\n        auto ch = n->append_child();\n        ch << c4::yml::key(p.first);\n        ch << p.second;\n    }\n}\n\ntemplate<class K, class V, class Less, class Alloc>\nbool read(c4::yml::ConstNodeRef const& n, std::map<K, V, Less, Alloc> * m)\n{\n    K k{};\n    V v{};\n    for(auto const& C4_RESTRICT ch : n)\n    {\n        ch >> c4::yml::key(k);\n        ch >> v;\n        m->emplace(std::make_pair(std::move(k), std::move(v)));\n    }\n    return true;\n}\n\n} // namespace yml\n} // namespace c4\n\n#endif // _C4_YML_STD_MAP_HPP_\n"
  },
  {
    "path": "libs/rapidyaml/c4/yml/std/std.hpp",
    "content": "#ifndef _C4_YML_STD_STD_HPP_\n#define _C4_YML_STD_STD_HPP_\n\n#include \"c4/yml/std/string.hpp\"\n#include \"c4/yml/std/vector.hpp\"\n#include \"c4/yml/std/map.hpp\"\n\n#endif // _C4_YML_STD_STD_HPP_\n"
  },
  {
    "path": "libs/rapidyaml/c4/yml/std/string.hpp",
    "content": "#ifndef C4_YML_STD_STRING_HPP_\n#define C4_YML_STD_STRING_HPP_\n\n/** @file string.hpp substring conversions for/from std::string */\n\n// everything we need is implemented here:\n#include <c4/std/string.hpp>\n\n#endif // C4_YML_STD_STRING_HPP_\n"
  },
  {
    "path": "libs/rapidyaml/c4/yml/std/vector.hpp",
    "content": "#ifndef _C4_YML_STD_VECTOR_HPP_\n#define _C4_YML_STD_VECTOR_HPP_\n\n#include \"c4/yml/node.hpp\"\n#include <c4/std/vector.hpp>\n#include <vector>\n\nnamespace c4 {\nnamespace yml {\n\n// vector is a sequence-like type, and it requires child nodes\n// in the data tree hierarchy (a SEQ node in ryml parlance).\n// So it should be serialized via write()/read().\n\n\ntemplate<class V, class Alloc>\nvoid write(c4::yml::NodeRef *n, std::vector<V, Alloc> const& vec)\n{\n    *n |= c4::yml::SEQ;\n    for(V const& v : vec)\n        n->append_child() << v;\n}\n\ntemplate<class V, class Alloc>\nbool read(c4::yml::ConstNodeRef const& n, std::vector<V, Alloc> *vec)\n{\n    C4_SUPPRESS_WARNING_GCC_WITH_PUSH(\"-Wuseless-cast\")\n    vec->resize(static_cast<size_t>(n.num_children()));\n    C4_SUPPRESS_WARNING_GCC_POP\n    size_t pos = 0;\n    for(ConstNodeRef const child : n)\n        child >> (*vec)[pos++];\n    return true;\n}\n\n/** specialization: std::vector<bool> uses std::vector<bool>::reference as\n * the return value of its operator[]. */\ntemplate<class Alloc>\nbool read(c4::yml::ConstNodeRef const& n, std::vector<bool, Alloc> *vec)\n{\n    C4_SUPPRESS_WARNING_GCC_WITH_PUSH(\"-Wuseless-cast\")\n    vec->resize(static_cast<size_t>(n.num_children()));\n    C4_SUPPRESS_WARNING_GCC_POP\n    size_t pos = 0;\n    bool tmp = {};\n    for(ConstNodeRef const child : n)\n    {\n        child >> tmp;\n        (*vec)[pos++] = tmp;\n    }\n    return true;\n}\n\n} // namespace yml\n} // namespace c4\n\n#endif // _C4_YML_STD_VECTOR_HPP_\n"
  },
  {
    "path": "libs/rapidyaml/c4/yml/tag.cpp",
    "content": "#include \"c4/yml/tag.hpp\"\n#include \"c4/yml/tree.hpp\"\n#include \"c4/yml/detail/parser_dbg.hpp\"\n\n\nnamespace c4 {\nnamespace yml {\n\nbool is_custom_tag(csubstr tag)\n{\n    if((tag.len > 2) && (tag.str[0] == '!'))\n    {\n        size_t pos = tag.find('!', 1);\n        return pos != npos && pos > 1 && tag.str[1] != '<';\n    }\n    return false;\n}\n\ncsubstr normalize_tag(csubstr tag)\n{\n    YamlTag_e t = to_tag(tag);\n    if(t != TAG_NONE)\n        return from_tag(t);\n    if(tag.begins_with(\"!<\"))\n        tag = tag.sub(1);\n    if(tag.begins_with(\"<!\"))\n        return tag;\n    return tag;\n}\n\ncsubstr normalize_tag_long(csubstr tag)\n{\n    YamlTag_e t = to_tag(tag);\n    if(t != TAG_NONE)\n        return from_tag_long(t);\n    if(tag.begins_with(\"!<\"))\n        tag = tag.sub(1);\n    if(tag.begins_with(\"<!\"))\n        return tag;\n    return tag;\n}\n\ncsubstr normalize_tag_long(csubstr tag, substr output)\n{\n    csubstr result = normalize_tag_long(tag);\n    if(result.begins_with(\"!!\"))\n    {\n        tag = tag.sub(2);\n        const csubstr pfx = \"<tag:yaml.org,2002:\";\n        const size_t len = pfx.len + tag.len + 1;\n        if(len <= output.len)\n        {\n            memcpy(output.str          , pfx.str, pfx.len);\n            memcpy(output.str + pfx.len, tag.str, tag.len);\n            output[pfx.len + tag.len] = '>';\n            result = output.first(len);\n        }\n        else\n        {\n            result.str = nullptr;\n            result.len = len;\n        }\n    }\n    return result;\n}\n\nYamlTag_e to_tag(csubstr tag)\n{\n    if(tag.begins_with(\"!<\"))\n        tag = tag.sub(1);\n    if(tag.begins_with(\"!!\"))\n        tag = tag.sub(2);\n    else if(tag.begins_with('!'))\n        return TAG_NONE;\n    else if(tag.begins_with(\"tag:yaml.org,2002:\"))\n    {\n        RYML_ASSERT(csubstr(\"tag:yaml.org,2002:\").len == 18);\n        tag = tag.sub(18);\n    }\n    else if(tag.begins_with(\"<tag:yaml.org,2002:\"))\n    {\n        RYML_ASSERT(csubstr(\"<tag:yaml.org,2002:\").len == 19);\n        tag = tag.sub(19);\n        if(!tag.len)\n            return TAG_NONE;\n        tag = tag.offs(0, 1);\n    }\n\n    if(tag == \"map\")\n        return TAG_MAP;\n    else if(tag == \"omap\")\n        return TAG_OMAP;\n    else if(tag == \"pairs\")\n        return TAG_PAIRS;\n    else if(tag == \"set\")\n        return TAG_SET;\n    else if(tag == \"seq\")\n        return TAG_SEQ;\n    else if(tag == \"binary\")\n        return TAG_BINARY;\n    else if(tag == \"bool\")\n        return TAG_BOOL;\n    else if(tag == \"float\")\n        return TAG_FLOAT;\n    else if(tag == \"int\")\n        return TAG_INT;\n    else if(tag == \"merge\")\n        return TAG_MERGE;\n    else if(tag == \"null\")\n        return TAG_NULL;\n    else if(tag == \"str\")\n        return TAG_STR;\n    else if(tag == \"timestamp\")\n        return TAG_TIMESTAMP;\n    else if(tag == \"value\")\n        return TAG_VALUE;\n    else if(tag == \"yaml\")\n        return TAG_YAML;\n\n    return TAG_NONE;\n}\n\ncsubstr from_tag_long(YamlTag_e tag)\n{\n    switch(tag)\n    {\n    case TAG_MAP:\n        return {\"<tag:yaml.org,2002:map>\"};\n    case TAG_OMAP:\n        return {\"<tag:yaml.org,2002:omap>\"};\n    case TAG_PAIRS:\n        return {\"<tag:yaml.org,2002:pairs>\"};\n    case TAG_SET:\n        return {\"<tag:yaml.org,2002:set>\"};\n    case TAG_SEQ:\n        return {\"<tag:yaml.org,2002:seq>\"};\n    case TAG_BINARY:\n        return {\"<tag:yaml.org,2002:binary>\"};\n    case TAG_BOOL:\n        return {\"<tag:yaml.org,2002:bool>\"};\n    case TAG_FLOAT:\n        return {\"<tag:yaml.org,2002:float>\"};\n    case TAG_INT:\n        return {\"<tag:yaml.org,2002:int>\"};\n    case TAG_MERGE:\n        return {\"<tag:yaml.org,2002:merge>\"};\n    case TAG_NULL:\n        return {\"<tag:yaml.org,2002:null>\"};\n    case TAG_STR:\n        return {\"<tag:yaml.org,2002:str>\"};\n    case TAG_TIMESTAMP:\n        return {\"<tag:yaml.org,2002:timestamp>\"};\n    case TAG_VALUE:\n        return {\"<tag:yaml.org,2002:value>\"};\n    case TAG_YAML:\n        return {\"<tag:yaml.org,2002:yaml>\"};\n    case TAG_NONE:\n    default:\n        return {\"\"};\n    }\n}\n\ncsubstr from_tag(YamlTag_e tag)\n{\n    switch(tag)\n    {\n    case TAG_MAP:\n        return {\"!!map\"};\n    case TAG_OMAP:\n        return {\"!!omap\"};\n    case TAG_PAIRS:\n        return {\"!!pairs\"};\n    case TAG_SET:\n        return {\"!!set\"};\n    case TAG_SEQ:\n        return {\"!!seq\"};\n    case TAG_BINARY:\n        return {\"!!binary\"};\n    case TAG_BOOL:\n        return {\"!!bool\"};\n    case TAG_FLOAT:\n        return {\"!!float\"};\n    case TAG_INT:\n        return {\"!!int\"};\n    case TAG_MERGE:\n        return {\"!!merge\"};\n    case TAG_NULL:\n        return {\"!!null\"};\n    case TAG_STR:\n        return {\"!!str\"};\n    case TAG_TIMESTAMP:\n        return {\"!!timestamp\"};\n    case TAG_VALUE:\n        return {\"!!value\"};\n    case TAG_YAML:\n        return {\"!!yaml\"};\n    case TAG_NONE:\n    default:\n        return {\"\"};\n    }\n}\n\n\nbool TagDirective::create_from_str(csubstr directive_)\n{\n    csubstr directive = directive_;\n    directive = directive.sub(4);\n    if(!directive.begins_with(' '))\n        return false;\n    directive = directive.triml(' ');\n    size_t pos = directive.find(' ');\n    if(pos == npos)\n        return false;\n    handle = directive.first(pos);\n    directive = directive.sub(handle.len).triml(' ');\n    pos = directive.find(' ');\n    if(pos != npos)\n        directive = directive.first(pos);\n    prefix = directive;\n    next_node_id = NONE;\n    _c4dbgpf(\"%TAG: handle={} prefix={}\", handle, prefix);\n    return true;\n}\n\nbool TagDirective::create_from_str(csubstr directive_, Tree *tree)\n{\n    _RYML_CB_CHECK(tree->callbacks(), directive_.begins_with(\"%TAG \"));\n    if(!create_from_str(directive_))\n    {\n        _RYML_CB_ERR(tree->callbacks(), \"invalid tag directive\");\n    }\n    next_node_id = tree->size();\n    if(tree->size() > 0)\n    {\n        const id_type prev = tree->size() - 1;\n        if(tree->is_root(prev) && tree->type(prev) != NOTYPE && !tree->is_stream(prev))\n            ++next_node_id;\n    }\n    _c4dbgpf(\"%TAG: handle={} prefix={} next_node={}\", handle, prefix, next_node_id);\n    return true;\n}\n\nsize_t TagDirective::transform(csubstr tag, substr output, Callbacks const& callbacks) const\n{\n    _c4dbgpf(\"%TAG: handle={} prefix={} next_node={}. tag={}\", handle, prefix, next_node_id, tag);\n    _RYML_CB_ASSERT(callbacks, tag.len >= handle.len);\n    csubstr rest = tag.sub(handle.len);\n    _c4dbgpf(\"%TAG: rest={}\", rest);\n    if(rest.begins_with('<'))\n    {\n        _c4dbgpf(\"%TAG: begins with <. rest={}\", rest);\n        if(C4_UNLIKELY(!rest.ends_with('>')))\n            _RYML_CB_ERR(callbacks, \"malformed tag\");\n        rest = rest.offs(1, 1);\n        if(rest.begins_with(prefix))\n        {\n            _c4dbgpf(\"%TAG: already transformed! actual={}\", rest.sub(prefix.len));\n            return 0; // return 0 to signal that the tag is local and cannot be resolved\n        }\n    }\n    size_t len = 1u + prefix.len + rest.len + 1u;\n    size_t numpc = rest.count('%');\n    if(numpc == 0)\n    {\n        if(len <= output.len)\n        {\n            output.str[0] = '<';\n            memcpy(1u + output.str, prefix.str, prefix.len);\n            memcpy(1u + output.str + prefix.len, rest.str, rest.len);\n            output.str[1u + prefix.len + rest.len] = '>';\n        }\n    }\n    else\n    {\n        // need to decode URI % sequences\n        size_t pos = rest.find('%');\n        _RYML_CB_ASSERT(callbacks, pos != npos);\n        do {\n            size_t next = rest.first_not_of(\"0123456789abcdefABCDEF\", pos+1);\n            if(next == npos)\n                next = rest.len;\n            _RYML_CB_CHECK(callbacks, pos+1 < next);\n            _RYML_CB_CHECK(callbacks, pos+1 + 2 <= next);\n            size_t delta = next - (pos+1);\n            len -= delta;\n            pos = rest.find('%', pos+1);\n        } while(pos != npos);\n        if(len <= output.len)\n        {\n            size_t prev = 0, wpos = 0;\n            auto appendstr = [&](csubstr s) { memcpy(output.str + wpos, s.str, s.len); wpos += s.len; };\n            auto appendchar = [&](char c) { output.str[wpos++] = c; };\n            appendchar('<');\n            appendstr(prefix);\n            pos = rest.find('%');\n            _RYML_CB_ASSERT(callbacks, pos != npos);\n            do {\n                size_t next = rest.first_not_of(\"0123456789abcdefABCDEF\", pos+1);\n                if(next == npos)\n                    next = rest.len;\n                _RYML_CB_CHECK(callbacks, pos+1 < next);\n                _RYML_CB_CHECK(callbacks, pos+1 + 2 <= next);\n                uint8_t val;\n                if(C4_UNLIKELY(!read_hex(rest.range(pos+1, next), &val) || val > 127))\n                    _RYML_CB_ERR(callbacks, \"invalid URI character\");\n                appendstr(rest.range(prev, pos));\n                appendchar(static_cast<char>(val));\n                prev = next;\n                pos = rest.find('%', pos+1);\n            } while(pos != npos);\n            _RYML_CB_ASSERT(callbacks, pos == npos);\n            _RYML_CB_ASSERT(callbacks, prev > 0);\n            _RYML_CB_ASSERT(callbacks, rest.len >= prev);\n            appendstr(rest.sub(prev));\n            appendchar('>');\n            _RYML_CB_ASSERT(callbacks, wpos == len);\n        }\n    }\n    return len;\n}\n\n} // namespace yml\n} // namespace c4\n"
  },
  {
    "path": "libs/rapidyaml/c4/yml/tag.hpp",
    "content": "#ifndef _C4_YML_TAG_HPP_\n#define _C4_YML_TAG_HPP_\n\n#include <c4/yml/common.hpp>\n\nnamespace c4 {\nnamespace yml {\n\nclass Tree;\n\n/** @addtogroup doc_tag_utils\n *\n * @{\n */\n\n\n#ifndef RYML_MAX_TAG_DIRECTIVES\n/** the maximum number of tag directives in a Tree */\n#define RYML_MAX_TAG_DIRECTIVES 4\n#endif\n\n/** the integral type necessary to cover all the bits marking node tags */\nusing tag_bits = uint16_t;\n\n/** a bit mask for marking tags for types */\ntypedef enum : tag_bits {\n    TAG_NONE      =  0,\n    // container types\n    TAG_MAP       =  1, /**< !!map   Unordered set of key: value pairs without duplicates. @see https://yaml.org/type/map.html */\n    TAG_OMAP      =  2, /**< !!omap  Ordered sequence of key: value pairs without duplicates. @see https://yaml.org/type/omap.html */\n    TAG_PAIRS     =  3, /**< !!pairs Ordered sequence of key: value pairs allowing duplicates. @see https://yaml.org/type/pairs.html */\n    TAG_SET       =  4, /**< !!set   Unordered set of non-equal values. @see https://yaml.org/type/set.html */\n    TAG_SEQ       =  5, /**< !!seq   Sequence of arbitrary values. @see https://yaml.org/type/seq.html */\n    // scalar types\n    TAG_BINARY    =  6, /**< !!binary A sequence of zero or more octets (8 bit values). @see https://yaml.org/type/binary.html */\n    TAG_BOOL      =  7, /**< !!bool   Mathematical Booleans. @see https://yaml.org/type/bool.html */\n    TAG_FLOAT     =  8, /**< !!float  Floating-point approximation to real numbers. https://yaml.org/type/float.html */\n    TAG_INT       =  9, /**< !!float  Mathematical integers. https://yaml.org/type/int.html */\n    TAG_MERGE     = 10, /**< !!merge  Specify one or more mapping to be merged with the current one. https://yaml.org/type/merge.html */\n    TAG_NULL      = 11, /**< !!null   Devoid of value. https://yaml.org/type/null.html */\n    TAG_STR       = 12, /**< !!str    A sequence of zero or more Unicode characters. https://yaml.org/type/str.html */\n    TAG_TIMESTAMP = 13, /**< !!timestamp A point in time https://yaml.org/type/timestamp.html */\n    TAG_VALUE     = 14, /**< !!value  Specify the default value of a mapping https://yaml.org/type/value.html */\n    TAG_YAML      = 15, /**< !!yaml   Specify the default value of a mapping https://yaml.org/type/yaml.html */\n} YamlTag_e;\n\nRYML_EXPORT YamlTag_e to_tag(csubstr tag);\nRYML_EXPORT csubstr from_tag(YamlTag_e tag);\nRYML_EXPORT csubstr from_tag_long(YamlTag_e tag);\nRYML_EXPORT csubstr normalize_tag(csubstr tag);\nRYML_EXPORT csubstr normalize_tag_long(csubstr tag);\nRYML_EXPORT csubstr normalize_tag_long(csubstr tag, substr output);\n\nRYML_EXPORT bool is_custom_tag(csubstr tag);\n\n\nstruct RYML_EXPORT TagDirective\n{\n    /** Eg `!e!` in `%TAG !e! tag:example.com,2000:app/` */\n    csubstr handle;\n    /** Eg `tag:example.com,2000:app/` in `%TAG !e! tag:example.com,2000:app/` */\n    csubstr prefix;\n    /** The next node to which this tag directive applies */\n    id_type next_node_id;\n\n    bool create_from_str(csubstr directive_); ///< leaves next_node_id unfilled\n    bool create_from_str(csubstr directive_, Tree *tree);\n    size_t transform(csubstr tag, substr output, Callbacks const& callbacks) const;\n};\n\nstruct RYML_EXPORT TagDirectiveRange\n{\n    TagDirective const* C4_RESTRICT b;\n    TagDirective const* C4_RESTRICT e;\n    C4_ALWAYS_INLINE TagDirective const* begin() const noexcept { return b; }\n    C4_ALWAYS_INLINE TagDirective const* end() const noexcept { return e; }\n};\n\n/** @} */\n\n} // namespace yml\n} // namespace c4\n\n#endif /* _C4_YML_TAG_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/yml/tree.cpp",
    "content": "#include \"c4/yml/tree.hpp\"\n#include \"c4/yml/detail/parser_dbg.hpp\"\n#include \"c4/yml/node.hpp\"\n#include \"c4/yml/reference_resolver.hpp\"\n\n\nC4_SUPPRESS_WARNING_MSVC_WITH_PUSH(4296/*expression is always 'boolean_value'*/)\nC4_SUPPRESS_WARNING_MSVC(4702/*unreachable code*/)\nC4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH(\"-Wold-style-cast\")\nC4_SUPPRESS_WARNING_GCC(\"-Wtype-limits\")\nC4_SUPPRESS_WARNING_GCC(\"-Wuseless-cast\")\n\nnamespace c4 {\nnamespace yml {\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\nNodeRef Tree::rootref()\n{\n    return NodeRef(this, root_id());\n}\nConstNodeRef Tree::rootref() const\n{\n    return ConstNodeRef(this, root_id());\n}\n\nConstNodeRef Tree::crootref() const\n{\n    return ConstNodeRef(this, root_id());\n}\n\nNodeRef Tree::ref(id_type id)\n{\n    _RYML_CB_ASSERT(m_callbacks, id != NONE && id >= 0 && id < m_cap);\n    return NodeRef(this, id);\n}\nConstNodeRef Tree::ref(id_type id) const\n{\n    _RYML_CB_ASSERT(m_callbacks, id != NONE && id >= 0 && id < m_cap);\n    return ConstNodeRef(this, id);\n}\nConstNodeRef Tree::cref(id_type id) const\n{\n    _RYML_CB_ASSERT(m_callbacks, id != NONE && id >= 0 && id < m_cap);\n    return ConstNodeRef(this, id);\n}\n\nNodeRef Tree::operator[] (csubstr key)\n{\n    return rootref()[key];\n}\nConstNodeRef Tree::operator[] (csubstr key) const\n{\n    return rootref()[key];\n}\n\nNodeRef Tree::operator[] (id_type i)\n{\n    return rootref()[i];\n}\nConstNodeRef Tree::operator[] (id_type i) const\n{\n    return rootref()[i];\n}\n\nNodeRef Tree::docref(id_type i)\n{\n    return ref(doc(i));\n}\nConstNodeRef Tree::docref(id_type i) const\n{\n    return cref(doc(i));\n}\nConstNodeRef Tree::cdocref(id_type i) const\n{\n    return cref(doc(i));\n}\n\n\n//-----------------------------------------------------------------------------\nTree::Tree(Callbacks const& cb)\n    : m_buf(nullptr)\n    , m_cap(0)\n    , m_size(0)\n    , m_free_head(NONE)\n    , m_free_tail(NONE)\n    , m_arena()\n    , m_arena_pos(0)\n    , m_callbacks(cb)\n    , m_tag_directives()\n{\n}\n\nTree::Tree(id_type node_capacity, size_t arena_capacity, Callbacks const& cb)\n    : Tree(cb)\n{\n    reserve(node_capacity);\n    reserve_arena(arena_capacity);\n}\n\nTree::~Tree()\n{\n    _free();\n}\n\n\nTree::Tree(Tree const& that) : Tree(that.m_callbacks)\n{\n    _copy(that);\n}\n\nTree& Tree::operator= (Tree const& that)\n{\n    _free();\n    m_callbacks = that.m_callbacks;\n    _copy(that);\n    return *this;\n}\n\nTree::Tree(Tree && that) noexcept : Tree(that.m_callbacks)\n{\n    _move(that);\n}\n\nTree& Tree::operator= (Tree && that) RYML_NOEXCEPT\n{\n    _free();\n    m_callbacks = that.m_callbacks;\n    _move(that);\n    return *this;\n}\n\nvoid Tree::_free()\n{\n    if(m_buf)\n    {\n        _RYML_CB_ASSERT(m_callbacks, m_cap > 0);\n        _RYML_CB_FREE(m_callbacks, m_buf, NodeData, (size_t)m_cap);\n    }\n    if(m_arena.str)\n    {\n        _RYML_CB_ASSERT(m_callbacks, m_arena.len > 0);\n        _RYML_CB_FREE(m_callbacks, m_arena.str, char, m_arena.len);\n    }\n    _clear();\n}\n\n\nC4_SUPPRESS_WARNING_GCC_PUSH\n#if defined(__GNUC__) && __GNUC__>= 8\n    C4_SUPPRESS_WARNING_GCC_WITH_PUSH(\"-Wclass-memaccess\") // error: ‘void* memset(void*, int, size_t)’ clearing an object of type ‘class c4::yml::Tree’ with no trivial copy-assignment; use assignment or value-initialization instead\n#endif\n\nvoid Tree::_clear()\n{\n    m_buf = nullptr;\n    m_cap = 0;\n    m_size = 0;\n    m_free_head = 0;\n    m_free_tail = 0;\n    m_arena = {};\n    m_arena_pos = 0;\n    for(id_type i = 0; i < RYML_MAX_TAG_DIRECTIVES; ++i)\n        m_tag_directives[i] = {};\n}\n\nvoid Tree::_copy(Tree const& that)\n{\n    _RYML_CB_ASSERT(m_callbacks, m_buf == nullptr);\n    _RYML_CB_ASSERT(m_callbacks, m_arena.str == nullptr);\n    _RYML_CB_ASSERT(m_callbacks, m_arena.len == 0);\n    if(that.m_cap)\n    {\n        m_buf = _RYML_CB_ALLOC_HINT(m_callbacks, NodeData, (size_t)that.m_cap, that.m_buf);\n        memcpy(m_buf, that.m_buf, (size_t)that.m_cap * sizeof(NodeData));\n    }\n    m_cap = that.m_cap;\n    m_size = that.m_size;\n    m_free_head = that.m_free_head;\n    m_free_tail = that.m_free_tail;\n    m_arena_pos = that.m_arena_pos;\n    m_arena = that.m_arena;\n    if(that.m_arena.str)\n    {\n        _RYML_CB_ASSERT(m_callbacks, that.m_arena.len > 0);\n        substr arena;\n        arena.str = _RYML_CB_ALLOC_HINT(m_callbacks, char, that.m_arena.len, that.m_arena.str);\n        arena.len = that.m_arena.len;\n        _relocate(arena); // does a memcpy of the arena and updates nodes using the old arena\n        m_arena = arena;\n    }\n    for(id_type i = 0; i < RYML_MAX_TAG_DIRECTIVES; ++i)\n        m_tag_directives[i] = that.m_tag_directives[i];\n}\n\nvoid Tree::_move(Tree & that) noexcept\n{\n    _RYML_CB_ASSERT(m_callbacks, m_buf == nullptr);\n    _RYML_CB_ASSERT(m_callbacks, m_arena.str == nullptr);\n    _RYML_CB_ASSERT(m_callbacks, m_arena.len == 0);\n    m_buf = that.m_buf;\n    m_cap = that.m_cap;\n    m_size = that.m_size;\n    m_free_head = that.m_free_head;\n    m_free_tail = that.m_free_tail;\n    m_arena = that.m_arena;\n    m_arena_pos = that.m_arena_pos;\n    for(id_type i = 0; i < RYML_MAX_TAG_DIRECTIVES; ++i)\n        m_tag_directives[i] = that.m_tag_directives[i];\n    that._clear();\n}\n\nvoid Tree::_relocate(substr next_arena)\n{\n    _RYML_CB_ASSERT(m_callbacks, next_arena.not_empty());\n    _RYML_CB_ASSERT(m_callbacks, next_arena.len >= m_arena.len);\n    if(m_arena_pos)\n        memcpy(next_arena.str, m_arena.str, m_arena_pos);\n    for(NodeData *C4_RESTRICT n = m_buf, *e = m_buf + m_cap; n != e; ++n)\n    {\n        if(in_arena(n->m_key.scalar))\n            n->m_key.scalar = _relocated(n->m_key.scalar, next_arena);\n        if(in_arena(n->m_key.tag))\n            n->m_key.tag = _relocated(n->m_key.tag, next_arena);\n        if(in_arena(n->m_key.anchor))\n            n->m_key.anchor = _relocated(n->m_key.anchor, next_arena);\n        if(in_arena(n->m_val.scalar))\n            n->m_val.scalar = _relocated(n->m_val.scalar, next_arena);\n        if(in_arena(n->m_val.tag))\n            n->m_val.tag = _relocated(n->m_val.tag, next_arena);\n        if(in_arena(n->m_val.anchor))\n            n->m_val.anchor = _relocated(n->m_val.anchor, next_arena);\n    }\n    for(TagDirective &C4_RESTRICT td : m_tag_directives)\n    {\n        if(in_arena(td.prefix))\n            td.prefix = _relocated(td.prefix, next_arena);\n        if(in_arena(td.handle))\n            td.handle = _relocated(td.handle, next_arena);\n    }\n}\n\n\n//-----------------------------------------------------------------------------\nvoid Tree::reserve(id_type cap)\n{\n    if(cap > m_cap)\n    {\n        NodeData *buf = _RYML_CB_ALLOC_HINT(m_callbacks, NodeData, (size_t)cap, m_buf);\n        if(m_buf)\n        {\n            memcpy(buf, m_buf, (size_t)m_cap * sizeof(NodeData));\n            _RYML_CB_FREE(m_callbacks, m_buf, NodeData, (size_t)m_cap);\n        }\n        id_type first = m_cap, del = cap - m_cap;\n        m_cap = cap;\n        m_buf = buf;\n        _clear_range(first, del);\n        if(m_free_head != NONE)\n        {\n            _RYML_CB_ASSERT(m_callbacks, m_buf != nullptr);\n            _RYML_CB_ASSERT(m_callbacks, m_free_tail != NONE);\n            m_buf[m_free_tail].m_next_sibling = first;\n            m_buf[first].m_prev_sibling = m_free_tail;\n            m_free_tail = cap-1;\n        }\n        else\n        {\n            _RYML_CB_ASSERT(m_callbacks, m_free_tail == NONE);\n            m_free_head = first;\n            m_free_tail = cap-1;\n        }\n        _RYML_CB_ASSERT(m_callbacks, m_free_head == NONE || (m_free_head >= 0 && m_free_head < cap));\n        _RYML_CB_ASSERT(m_callbacks, m_free_tail == NONE || (m_free_tail >= 0 && m_free_tail < cap));\n\n        if( ! m_size)\n            _claim_root();\n    }\n}\n\n\n//-----------------------------------------------------------------------------\nvoid Tree::clear()\n{\n    _clear_range(0, m_cap);\n    m_size = 0;\n    if(m_buf)\n    {\n        _RYML_CB_ASSERT(m_callbacks, m_cap >= 0);\n        m_free_head = 0;\n        m_free_tail = m_cap-1;\n        _claim_root();\n    }\n    else\n    {\n        m_free_head = NONE;\n        m_free_tail = NONE;\n    }\n    for(id_type i = 0; i < RYML_MAX_TAG_DIRECTIVES; ++i)\n        m_tag_directives[i] = {};\n}\n\nvoid Tree::_claim_root()\n{\n    id_type r = _claim();\n    _RYML_CB_ASSERT(m_callbacks, r == 0);\n    _set_hierarchy(r, NONE, NONE);\n}\n\n\n//-----------------------------------------------------------------------------\nvoid Tree::_clear_range(id_type first, id_type num)\n{\n    if(num == 0)\n        return; // prevent overflow when subtracting\n    _RYML_CB_ASSERT(m_callbacks, first >= 0 && first + num <= m_cap);\n    memset(m_buf + first, 0, (size_t)num * sizeof(NodeData)); // TODO we should not need this\n    for(id_type i = first, e = first + num; i < e; ++i)\n    {\n        _clear(i);\n        NodeData *n = m_buf + i;\n        n->m_prev_sibling = i - 1;\n        n->m_next_sibling = i + 1;\n    }\n    m_buf[first + num - 1].m_next_sibling = NONE;\n}\n\nC4_SUPPRESS_WARNING_GCC_POP\n\n\n//-----------------------------------------------------------------------------\nvoid Tree::_release(id_type i)\n{\n    _RYML_CB_ASSERT(m_callbacks, i >= 0 && i < m_cap);\n\n    _rem_hierarchy(i);\n    _free_list_add(i);\n    _clear(i);\n\n    --m_size;\n}\n\n//-----------------------------------------------------------------------------\n// add to the front of the free list\nvoid Tree::_free_list_add(id_type i)\n{\n    _RYML_CB_ASSERT(m_callbacks, i >= 0 && i < m_cap);\n    NodeData &C4_RESTRICT w = m_buf[i];\n\n    w.m_parent = NONE;\n    w.m_next_sibling = m_free_head;\n    w.m_prev_sibling = NONE;\n    if(m_free_head != NONE)\n        m_buf[m_free_head].m_prev_sibling = i;\n    m_free_head = i;\n    if(m_free_tail == NONE)\n        m_free_tail = m_free_head;\n}\n\nvoid Tree::_free_list_rem(id_type i)\n{\n    if(m_free_head == i)\n        m_free_head = _p(i)->m_next_sibling;\n    _rem_hierarchy(i);\n}\n\n//-----------------------------------------------------------------------------\nid_type Tree::_claim()\n{\n    if(m_free_head == NONE || m_buf == nullptr)\n    {\n        id_type sz = 2 * m_cap;\n        sz = sz ? sz : 16;\n        reserve(sz);\n        _RYML_CB_ASSERT(m_callbacks, m_free_head != NONE);\n    }\n\n    _RYML_CB_ASSERT(m_callbacks, m_size < m_cap);\n    _RYML_CB_ASSERT(m_callbacks, m_free_head >= 0 && m_free_head < m_cap);\n\n    id_type ichild = m_free_head;\n    NodeData *child = m_buf + ichild;\n\n    ++m_size;\n    m_free_head = child->m_next_sibling;\n    if(m_free_head == NONE)\n    {\n        m_free_tail = NONE;\n        _RYML_CB_ASSERT(m_callbacks, m_size == m_cap);\n    }\n\n    _clear(ichild);\n\n    return ichild;\n}\n\n//-----------------------------------------------------------------------------\n\nC4_SUPPRESS_WARNING_GCC_PUSH\nC4_SUPPRESS_WARNING_CLANG_PUSH\nC4_SUPPRESS_WARNING_CLANG(\"-Wnull-dereference\")\n#if defined(__GNUC__)\n#if (__GNUC__ >= 6)\nC4_SUPPRESS_WARNING_GCC(\"-Wnull-dereference\")\n#endif\n#if (__GNUC__ > 9)\nC4_SUPPRESS_WARNING_GCC(\"-Wanalyzer-fd-leak\")\n#endif\n#endif\n\nvoid Tree::_set_hierarchy(id_type ichild, id_type iparent, id_type iprev_sibling)\n{\n    _RYML_CB_ASSERT(m_callbacks, ichild >= 0 && ichild < m_cap);\n    _RYML_CB_ASSERT(m_callbacks, iparent == NONE || (iparent >= 0 && iparent < m_cap));\n    _RYML_CB_ASSERT(m_callbacks, iprev_sibling == NONE || (iprev_sibling >= 0 && iprev_sibling < m_cap));\n\n    NodeData *C4_RESTRICT child = _p(ichild);\n\n    child->m_parent = iparent;\n    child->m_prev_sibling = NONE;\n    child->m_next_sibling = NONE;\n\n    if(iparent == NONE)\n    {\n        _RYML_CB_ASSERT(m_callbacks, ichild == 0);\n        _RYML_CB_ASSERT(m_callbacks, iprev_sibling == NONE);\n    }\n\n    if(iparent == NONE)\n        return;\n\n    id_type inext_sibling = iprev_sibling != NONE ? next_sibling(iprev_sibling) : first_child(iparent);\n    NodeData *C4_RESTRICT parent = get(iparent);\n    NodeData *C4_RESTRICT psib   = get(iprev_sibling);\n    NodeData *C4_RESTRICT nsib   = get(inext_sibling);\n\n    if(psib)\n    {\n        _RYML_CB_ASSERT(m_callbacks, next_sibling(iprev_sibling) == id(nsib));\n        child->m_prev_sibling = id(psib);\n        psib->m_next_sibling = id(child);\n        _RYML_CB_ASSERT(m_callbacks, psib->m_prev_sibling != psib->m_next_sibling || psib->m_prev_sibling == NONE);\n    }\n\n    if(nsib)\n    {\n        _RYML_CB_ASSERT(m_callbacks, prev_sibling(inext_sibling) == id(psib));\n        child->m_next_sibling = id(nsib);\n        nsib->m_prev_sibling = id(child);\n        _RYML_CB_ASSERT(m_callbacks, nsib->m_prev_sibling != nsib->m_next_sibling || nsib->m_prev_sibling == NONE);\n    }\n\n    if(parent->m_first_child == NONE)\n    {\n        _RYML_CB_ASSERT(m_callbacks, parent->m_last_child == NONE);\n        parent->m_first_child = id(child);\n        parent->m_last_child = id(child);\n    }\n    else\n    {\n        if(child->m_next_sibling == parent->m_first_child)\n            parent->m_first_child = id(child);\n\n        if(child->m_prev_sibling == parent->m_last_child)\n            parent->m_last_child = id(child);\n    }\n}\n\nC4_SUPPRESS_WARNING_GCC_POP\nC4_SUPPRESS_WARNING_CLANG_POP\n\n\n//-----------------------------------------------------------------------------\nvoid Tree::_rem_hierarchy(id_type i)\n{\n    _RYML_CB_ASSERT(m_callbacks, i >= 0 && i < m_cap);\n\n    NodeData &C4_RESTRICT w = m_buf[i];\n\n    // remove from the parent\n    if(w.m_parent != NONE)\n    {\n        NodeData &C4_RESTRICT p = m_buf[w.m_parent];\n        if(p.m_first_child == i)\n        {\n            p.m_first_child = w.m_next_sibling;\n        }\n        if(p.m_last_child == i)\n        {\n            p.m_last_child = w.m_prev_sibling;\n        }\n    }\n\n    // remove from the used list\n    if(w.m_prev_sibling != NONE)\n    {\n        NodeData *C4_RESTRICT prev = get(w.m_prev_sibling);\n        prev->m_next_sibling = w.m_next_sibling;\n    }\n    if(w.m_next_sibling != NONE)\n    {\n        NodeData *C4_RESTRICT next = get(w.m_next_sibling);\n        next->m_prev_sibling = w.m_prev_sibling;\n    }\n}\n\n//-----------------------------------------------------------------------------\nid_type Tree::_do_reorder(id_type *node, id_type count)\n{\n    // swap this node if it's not in place\n    if(*node != count)\n    {\n        _swap(*node, count);\n        *node = count;\n    }\n    ++count; // bump the count from this node\n\n    // now descend in the hierarchy\n    for(id_type i = first_child(*node); i != NONE; i = next_sibling(i))\n    {\n        // this child may have been relocated to a different index,\n        // so get an updated version\n        count = _do_reorder(&i, count);\n    }\n    return count;\n}\n\nvoid Tree::reorder()\n{\n    id_type r = root_id();\n    _do_reorder(&r, 0);\n}\n\n\n//-----------------------------------------------------------------------------\nvoid Tree::_swap(id_type n_, id_type m_)\n{\n    _RYML_CB_ASSERT(m_callbacks, (parent(n_) != NONE) || type(n_) == NOTYPE);\n    _RYML_CB_ASSERT(m_callbacks, (parent(m_) != NONE) || type(m_) == NOTYPE);\n    NodeType tn = type(n_);\n    NodeType tm = type(m_);\n    if(tn != NOTYPE && tm != NOTYPE)\n    {\n        _swap_props(n_, m_);\n        _swap_hierarchy(n_, m_);\n    }\n    else if(tn == NOTYPE && tm != NOTYPE)\n    {\n        _copy_props(n_, m_);\n        _free_list_rem(n_);\n        _copy_hierarchy(n_, m_);\n        _clear(m_);\n        _free_list_add(m_);\n    }\n    else if(tn != NOTYPE && tm == NOTYPE)\n    {\n        _copy_props(m_, n_);\n        _free_list_rem(m_);\n        _copy_hierarchy(m_, n_);\n        _clear(n_);\n        _free_list_add(n_);\n    }\n    else\n    {\n        C4_NEVER_REACH();\n    }\n}\n\n//-----------------------------------------------------------------------------\nvoid Tree::_swap_hierarchy(id_type ia, id_type ib)\n{\n    if(ia == ib) return;\n\n    for(id_type i = first_child(ia); i != NONE; i = next_sibling(i))\n    {\n        if(i == ib || i == ia)\n            continue;\n        _p(i)->m_parent = ib;\n    }\n\n    for(id_type i = first_child(ib); i != NONE; i = next_sibling(i))\n    {\n        if(i == ib || i == ia)\n            continue;\n        _p(i)->m_parent = ia;\n    }\n\n    auto & C4_RESTRICT a  = *_p(ia);\n    auto & C4_RESTRICT b  = *_p(ib);\n    auto & C4_RESTRICT pa = *_p(a.m_parent);\n    auto & C4_RESTRICT pb = *_p(b.m_parent);\n\n    if(&pa == &pb)\n    {\n        if((pa.m_first_child == ib && pa.m_last_child == ia)\n            ||\n           (pa.m_first_child == ia && pa.m_last_child == ib))\n        {\n            std::swap(pa.m_first_child, pa.m_last_child);\n        }\n        else\n        {\n            bool changed = false;\n            if(pa.m_first_child == ia)\n            {\n                pa.m_first_child = ib;\n                changed = true;\n            }\n            if(pa.m_last_child  == ia)\n            {\n                pa.m_last_child = ib;\n                changed = true;\n            }\n            if(pb.m_first_child == ib && !changed)\n            {\n                pb.m_first_child = ia;\n            }\n            if(pb.m_last_child  == ib && !changed)\n            {\n                pb.m_last_child  = ia;\n            }\n        }\n    }\n    else\n    {\n        if(pa.m_first_child == ia)\n            pa.m_first_child = ib;\n        if(pa.m_last_child  == ia)\n            pa.m_last_child  = ib;\n        if(pb.m_first_child == ib)\n            pb.m_first_child = ia;\n        if(pb.m_last_child  == ib)\n            pb.m_last_child  = ia;\n    }\n    std::swap(a.m_first_child , b.m_first_child);\n    std::swap(a.m_last_child  , b.m_last_child);\n\n    if(a.m_prev_sibling != ib && b.m_prev_sibling != ia &&\n       a.m_next_sibling != ib && b.m_next_sibling != ia)\n    {\n        if(a.m_prev_sibling != NONE && a.m_prev_sibling != ib)\n            _p(a.m_prev_sibling)->m_next_sibling = ib;\n        if(a.m_next_sibling != NONE && a.m_next_sibling != ib)\n            _p(a.m_next_sibling)->m_prev_sibling = ib;\n        if(b.m_prev_sibling != NONE && b.m_prev_sibling != ia)\n            _p(b.m_prev_sibling)->m_next_sibling = ia;\n        if(b.m_next_sibling != NONE && b.m_next_sibling != ia)\n            _p(b.m_next_sibling)->m_prev_sibling = ia;\n        std::swap(a.m_prev_sibling, b.m_prev_sibling);\n        std::swap(a.m_next_sibling, b.m_next_sibling);\n    }\n    else\n    {\n        if(a.m_next_sibling == ib) // n will go after m\n        {\n            _RYML_CB_ASSERT(m_callbacks, b.m_prev_sibling == ia);\n            if(a.m_prev_sibling != NONE)\n            {\n                _RYML_CB_ASSERT(m_callbacks, a.m_prev_sibling != ib);\n                _p(a.m_prev_sibling)->m_next_sibling = ib;\n            }\n            if(b.m_next_sibling != NONE)\n            {\n                _RYML_CB_ASSERT(m_callbacks, b.m_next_sibling != ia);\n                _p(b.m_next_sibling)->m_prev_sibling = ia;\n            }\n            id_type ns = b.m_next_sibling;\n            b.m_prev_sibling = a.m_prev_sibling;\n            b.m_next_sibling = ia;\n            a.m_prev_sibling = ib;\n            a.m_next_sibling = ns;\n        }\n        else if(a.m_prev_sibling == ib) // m will go after n\n        {\n            _RYML_CB_ASSERT(m_callbacks, b.m_next_sibling == ia);\n            if(b.m_prev_sibling != NONE)\n            {\n                _RYML_CB_ASSERT(m_callbacks, b.m_prev_sibling != ia);\n                _p(b.m_prev_sibling)->m_next_sibling = ia;\n            }\n            if(a.m_next_sibling != NONE)\n            {\n                _RYML_CB_ASSERT(m_callbacks, a.m_next_sibling != ib);\n                _p(a.m_next_sibling)->m_prev_sibling = ib;\n            }\n            id_type ns = b.m_prev_sibling;\n            a.m_prev_sibling = b.m_prev_sibling;\n            a.m_next_sibling = ib;\n            b.m_prev_sibling = ia;\n            b.m_next_sibling = ns;\n        }\n        else\n        {\n            C4_NEVER_REACH();\n        }\n    }\n    _RYML_CB_ASSERT(m_callbacks, a.m_next_sibling != ia);\n    _RYML_CB_ASSERT(m_callbacks, a.m_prev_sibling != ia);\n    _RYML_CB_ASSERT(m_callbacks, b.m_next_sibling != ib);\n    _RYML_CB_ASSERT(m_callbacks, b.m_prev_sibling != ib);\n\n    if(a.m_parent != ib && b.m_parent != ia)\n    {\n        std::swap(a.m_parent, b.m_parent);\n    }\n    else\n    {\n        if(a.m_parent == ib && b.m_parent != ia)\n        {\n            a.m_parent = b.m_parent;\n            b.m_parent = ia;\n        }\n        else if(a.m_parent != ib && b.m_parent == ia)\n        {\n            b.m_parent = a.m_parent;\n            a.m_parent = ib;\n        }\n        else\n        {\n            C4_NEVER_REACH();\n        }\n    }\n}\n\n//-----------------------------------------------------------------------------\nvoid Tree::_copy_hierarchy(id_type dst_, id_type src_)\n{\n    auto const& C4_RESTRICT src = *_p(src_);\n    auto      & C4_RESTRICT dst = *_p(dst_);\n    auto      & C4_RESTRICT prt = *_p(src.m_parent);\n    for(id_type i = src.m_first_child; i != NONE; i = next_sibling(i))\n    {\n        _p(i)->m_parent = dst_;\n    }\n    if(src.m_prev_sibling != NONE)\n    {\n        _p(src.m_prev_sibling)->m_next_sibling = dst_;\n    }\n    if(src.m_next_sibling != NONE)\n    {\n        _p(src.m_next_sibling)->m_prev_sibling = dst_;\n    }\n    if(prt.m_first_child == src_)\n    {\n        prt.m_first_child = dst_;\n    }\n    if(prt.m_last_child  == src_)\n    {\n        prt.m_last_child  = dst_;\n    }\n    dst.m_parent       = src.m_parent;\n    dst.m_first_child  = src.m_first_child;\n    dst.m_last_child   = src.m_last_child;\n    dst.m_prev_sibling = src.m_prev_sibling;\n    dst.m_next_sibling = src.m_next_sibling;\n}\n\n//-----------------------------------------------------------------------------\nvoid Tree::_swap_props(id_type n_, id_type m_)\n{\n    NodeData &C4_RESTRICT n = *_p(n_);\n    NodeData &C4_RESTRICT m = *_p(m_);\n    std::swap(n.m_type, m.m_type);\n    std::swap(n.m_key, m.m_key);\n    std::swap(n.m_val, m.m_val);\n}\n\n//-----------------------------------------------------------------------------\nvoid Tree::move(id_type node, id_type after)\n{\n    _RYML_CB_ASSERT(m_callbacks, node != NONE);\n    _RYML_CB_ASSERT(m_callbacks, node != after);\n    _RYML_CB_ASSERT(m_callbacks,  ! is_root(node));\n    _RYML_CB_ASSERT(m_callbacks, (after == NONE) || (has_sibling(node, after) && has_sibling(after, node)));\n\n    _rem_hierarchy(node);\n    _set_hierarchy(node, parent(node), after);\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Tree::move(id_type node, id_type new_parent, id_type after)\n{\n    _RYML_CB_ASSERT(m_callbacks, node != NONE);\n    _RYML_CB_ASSERT(m_callbacks, node != after);\n    _RYML_CB_ASSERT(m_callbacks, new_parent != NONE);\n    _RYML_CB_ASSERT(m_callbacks, new_parent != node);\n    _RYML_CB_ASSERT(m_callbacks, new_parent != after);\n    _RYML_CB_ASSERT(m_callbacks,  ! is_root(node));\n\n    _rem_hierarchy(node);\n    _set_hierarchy(node, new_parent, after);\n}\n\nid_type Tree::move(Tree *src, id_type node, id_type new_parent, id_type after)\n{\n    _RYML_CB_ASSERT(m_callbacks, src != nullptr);\n    _RYML_CB_ASSERT(m_callbacks, node != NONE);\n    _RYML_CB_ASSERT(m_callbacks, new_parent != NONE);\n    _RYML_CB_ASSERT(m_callbacks, new_parent != after);\n\n    id_type dup = duplicate(src, node, new_parent, after);\n    src->remove(node);\n    return dup;\n}\n\nvoid Tree::set_root_as_stream()\n{\n    id_type root = root_id();\n    if(is_stream(root))\n        return;\n    // don't use _add_flags() because it's checked and will fail\n    if(!has_children(root))\n    {\n        if(is_val(root))\n        {\n            _p(root)->m_type.add(SEQ);\n            id_type next_doc = append_child(root);\n            _copy_props_wo_key(next_doc, root);\n            _p(next_doc)->m_type.add(DOC);\n            _p(next_doc)->m_type.rem(SEQ);\n        }\n        _p(root)->m_type = STREAM;\n        return;\n    }\n    _RYML_CB_ASSERT(m_callbacks, !has_key(root));\n    id_type next_doc = append_child(root);\n    _copy_props_wo_key(next_doc, root);\n    _add_flags(next_doc, DOC);\n    for(id_type prev = NONE, ch = first_child(root), next = next_sibling(ch); ch != NONE; )\n    {\n        if(ch == next_doc)\n            break;\n        move(ch, next_doc, prev);\n        prev = ch;\n        ch = next;\n        next = next_sibling(next);\n    }\n    _p(root)->m_type = STREAM;\n}\n\n\n//-----------------------------------------------------------------------------\nvoid Tree::remove_children(id_type node)\n{\n    _RYML_CB_ASSERT(m_callbacks, get(node) != nullptr);\n    id_type ich = get(node)->m_first_child;\n    while(ich != NONE)\n    {\n        remove_children(ich);\n        _RYML_CB_ASSERT(m_callbacks, get(ich) != nullptr);\n        id_type next = get(ich)->m_next_sibling;\n        _release(ich);\n        if(ich == get(node)->m_last_child)\n            break;\n        ich = next;\n    }\n}\n\nbool Tree::change_type(id_type node, NodeType type)\n{\n    _RYML_CB_ASSERT(m_callbacks, type.is_val() || type.is_map() || type.is_seq());\n    _RYML_CB_ASSERT(m_callbacks, type.is_val() + type.is_map() + type.is_seq() == 1);\n    _RYML_CB_ASSERT(m_callbacks, type.has_key() == has_key(node) || (has_key(node) && !type.has_key()));\n    NodeData *d = _p(node);\n    if(type.is_map() && is_map(node))\n        return false;\n    else if(type.is_seq() && is_seq(node))\n        return false;\n    else if(type.is_val() && is_val(node))\n        return false;\n    d->m_type = (d->m_type & (~(MAP|SEQ|VAL))) | type;\n    remove_children(node);\n    return true;\n}\n\n\n//-----------------------------------------------------------------------------\nid_type Tree::duplicate(id_type node, id_type parent, id_type after)\n{\n    return duplicate(this, node, parent, after);\n}\n\nid_type Tree::duplicate(Tree const* src, id_type node, id_type parent, id_type after)\n{\n    _RYML_CB_ASSERT(m_callbacks, src != nullptr);\n    _RYML_CB_ASSERT(m_callbacks, node != NONE);\n    _RYML_CB_ASSERT(m_callbacks, parent != NONE);\n    _RYML_CB_ASSERT(m_callbacks,  ! src->is_root(node));\n\n    id_type copy = _claim();\n\n    _copy_props(copy, src, node);\n    _set_hierarchy(copy, parent, after);\n    duplicate_children(src, node, copy, NONE);\n\n    return copy;\n}\n\n//-----------------------------------------------------------------------------\nid_type Tree::duplicate_children(id_type node, id_type parent, id_type after)\n{\n    return duplicate_children(this, node, parent, after);\n}\n\nid_type Tree::duplicate_children(Tree const* src, id_type node, id_type parent, id_type after)\n{\n    _RYML_CB_ASSERT(m_callbacks, src != nullptr);\n    _RYML_CB_ASSERT(m_callbacks, node != NONE);\n    _RYML_CB_ASSERT(m_callbacks, parent != NONE);\n    _RYML_CB_ASSERT(m_callbacks, after == NONE || has_child(parent, after));\n\n    id_type prev = after;\n    for(id_type i = src->first_child(node); i != NONE; i = src->next_sibling(i))\n    {\n        prev = duplicate(src, i, parent, prev);\n    }\n\n    return prev;\n}\n\n//-----------------------------------------------------------------------------\nvoid Tree::duplicate_contents(id_type node, id_type where)\n{\n    duplicate_contents(this, node, where);\n}\n\nvoid Tree::duplicate_contents(Tree const *src, id_type node, id_type where)\n{\n    _RYML_CB_ASSERT(m_callbacks, src != nullptr);\n    _RYML_CB_ASSERT(m_callbacks, node != NONE);\n    _RYML_CB_ASSERT(m_callbacks, where != NONE);\n    _copy_props_wo_key(where, src, node);\n    duplicate_children(src, node, where, last_child(where));\n}\n\n//-----------------------------------------------------------------------------\nid_type Tree::duplicate_children_no_rep(id_type node, id_type parent, id_type after)\n{\n    return duplicate_children_no_rep(this, node, parent, after);\n}\n\nid_type Tree::duplicate_children_no_rep(Tree const *src, id_type node, id_type parent, id_type after)\n{\n    _RYML_CB_ASSERT(m_callbacks, node != NONE);\n    _RYML_CB_ASSERT(m_callbacks, parent != NONE);\n    _RYML_CB_ASSERT(m_callbacks, after == NONE || has_child(parent, after));\n\n    // don't loop using pointers as there may be a relocation\n\n    // find the position where \"after\" is\n    id_type after_pos = NONE;\n    if(after != NONE)\n    {\n        for(id_type i = first_child(parent), icount = 0; i != NONE; ++icount, i = next_sibling(i))\n        {\n            if(i == after)\n            {\n                after_pos = icount;\n                break;\n            }\n        }\n        _RYML_CB_ASSERT(m_callbacks, after_pos != NONE);\n    }\n\n    // for each child to be duplicated...\n    id_type prev = after;\n    for(id_type i = src->first_child(node); i != NONE; i = src->next_sibling(i))\n    {\n        if(is_seq(parent))\n        {\n            prev = duplicate(i, parent, prev);\n        }\n        else\n        {\n            _RYML_CB_ASSERT(m_callbacks, is_map(parent));\n            // does the parent already have a node with key equal to that of the current duplicate?\n            id_type rep = NONE, rep_pos = NONE;\n            for(id_type j = first_child(parent), jcount = 0; j != NONE; ++jcount, j = next_sibling(j))\n            {\n                if(key(j) == key(i))\n                {\n                    rep = j;\n                    rep_pos = jcount;\n                    break;\n                }\n            }\n            if(rep == NONE) // there is no repetition; just duplicate\n            {\n                prev = duplicate(src, i, parent, prev);\n            }\n            else  // yes, there is a repetition\n            {\n                if(after_pos != NONE && rep_pos < after_pos)\n                {\n                    // rep is located before the node which will be inserted,\n                    // and will be overridden by the duplicate. So replace it.\n                    remove(rep);\n                    prev = duplicate(src, i, parent, prev);\n                }\n                else if(prev == NONE)\n                {\n                    // first iteration with prev = after = NONE and repetition\n                    prev = rep;\n                }\n                else if(rep != prev)\n                {\n                    // rep is located after the node which will be inserted\n                    // and overrides it. So move the rep into this node's place.\n                    move(rep, prev);\n                    prev = rep;\n                }\n            } // there's a repetition\n        }\n    }\n\n    return prev;\n}\n\n\n//-----------------------------------------------------------------------------\n\nvoid Tree::merge_with(Tree const *src, id_type src_node, id_type dst_node)\n{\n    _RYML_CB_ASSERT(m_callbacks, src != nullptr);\n    if(src_node == NONE)\n        src_node = src->root_id();\n    if(dst_node == NONE)\n        dst_node = root_id();\n    _RYML_CB_ASSERT(m_callbacks, src->has_val(src_node) || src->is_seq(src_node) || src->is_map(src_node));\n    if(src->has_val(src_node))\n    {\n        type_bits mask_src = ~STYLE; // keep the existing style if it is already a val\n        if( ! has_val(dst_node))\n        {\n            if(has_children(dst_node))\n                remove_children(dst_node);\n            mask_src |= VAL_STYLE; // copy the src style\n        }\n        if(src->is_keyval(src_node))\n        {\n            _copy_props(dst_node, src, src_node, mask_src);\n        }\n        else\n        {\n            _RYML_CB_ASSERT(m_callbacks, src->is_val(src_node));\n            _copy_props_wo_key(dst_node, src, src_node, mask_src);\n        }\n    }\n    else if(src->is_seq(src_node))\n    {\n        if( ! is_seq(dst_node))\n        {\n            if(has_children(dst_node))\n                remove_children(dst_node);\n            _clear_type(dst_node);\n            if(src->has_key(src_node))\n                to_seq(dst_node, src->key(src_node));\n            else\n                to_seq(dst_node);\n            _p(dst_node)->m_type = src->_p(src_node)->m_type;\n        }\n        for(id_type sch = src->first_child(src_node); sch != NONE; sch = src->next_sibling(sch))\n        {\n            id_type dch = append_child(dst_node);\n            _copy_props_wo_key(dch, src, sch);\n            merge_with(src, sch, dch);\n        }\n    }\n    else\n    {\n        _RYML_CB_ASSERT(m_callbacks, src->is_map(src_node));\n        if( ! is_map(dst_node))\n        {\n            if(has_children(dst_node))\n                remove_children(dst_node);\n            _clear_type(dst_node);\n            if(src->has_key(src_node))\n                to_map(dst_node, src->key(src_node));\n            else\n                to_map(dst_node);\n            _p(dst_node)->m_type = src->_p(src_node)->m_type;\n        }\n        for(id_type sch = src->first_child(src_node); sch != NONE; sch = src->next_sibling(sch))\n        {\n            id_type dch = find_child(dst_node, src->key(sch));\n            if(dch == NONE)\n            {\n                dch = append_child(dst_node);\n                _copy_props(dch, src, sch);\n            }\n            merge_with(src, sch, dch);\n        }\n    }\n}\n\n\n//-----------------------------------------------------------------------------\n\nvoid Tree::resolve()\n{\n    if(m_size == 0)\n        return;\n    ReferenceResolver rr;\n    resolve(&rr);\n}\n\nvoid Tree::resolve(ReferenceResolver *C4_RESTRICT rr)\n{\n    if(m_size == 0)\n        return;\n    rr->resolve(this);\n}\n\n\n//-----------------------------------------------------------------------------\n\nid_type Tree::num_children(id_type node) const\n{\n    id_type count = 0;\n    for(id_type i = first_child(node); i != NONE; i = next_sibling(i))\n        ++count;\n    return count;\n}\n\nid_type Tree::child(id_type node, id_type pos) const\n{\n    _RYML_CB_ASSERT(m_callbacks, node != NONE);\n    id_type count = 0;\n    for(id_type i = first_child(node); i != NONE; i = next_sibling(i))\n    {\n        if(count++ == pos)\n            return i;\n    }\n    return NONE;\n}\n\nid_type Tree::child_pos(id_type node, id_type ch) const\n{\n    _RYML_CB_ASSERT(m_callbacks, node != NONE);\n    id_type count = 0;\n    for(id_type i = first_child(node); i != NONE; i = next_sibling(i))\n    {\n        if(i == ch)\n            return count;\n        ++count;\n    }\n    return NONE;\n}\n\n#if defined(__clang__)\n#   pragma clang diagnostic push\n#   pragma GCC diagnostic ignored \"-Wnull-dereference\"\n#elif defined(__GNUC__)\n#   pragma GCC diagnostic push\n#   if __GNUC__ >= 6\n#       pragma GCC diagnostic ignored \"-Wnull-dereference\"\n#   endif\n#   if __GNUC__ > 9\n#       pragma GCC diagnostic ignored \"-Wanalyzer-null-dereference\"\n#   endif\n#endif\n\nid_type Tree::find_child(id_type node, csubstr const& name) const\n{\n    _RYML_CB_ASSERT(m_callbacks, node != NONE);\n    _RYML_CB_ASSERT(m_callbacks, is_map(node));\n    if(get(node)->m_first_child == NONE)\n    {\n        _RYML_CB_ASSERT(m_callbacks, _p(node)->m_last_child == NONE);\n        return NONE;\n    }\n    else\n    {\n        _RYML_CB_ASSERT(m_callbacks, _p(node)->m_last_child != NONE);\n    }\n    for(id_type i = first_child(node); i != NONE; i = next_sibling(i))\n    {\n        if(_p(i)->m_key.scalar == name)\n        {\n            return i;\n        }\n    }\n    return NONE;\n}\n\n#if defined(__clang__)\n#   pragma clang diagnostic pop\n#elif defined(__GNUC__)\n#   pragma GCC diagnostic pop\n#endif\n\nnamespace {\nid_type depth_desc_(Tree const& C4_RESTRICT t, id_type id, id_type currdepth=0, id_type maxdepth=0)\n{\n    maxdepth = currdepth > maxdepth ? currdepth : maxdepth;\n    for(id_type child = t.first_child(id); child != NONE; child = t.next_sibling(child))\n    {\n        const id_type d = depth_desc_(t, child, currdepth+1, maxdepth);\n        maxdepth = d > maxdepth ? d : maxdepth;\n    }\n    return maxdepth;\n}\n}\n\nid_type Tree::depth_desc(id_type node) const\n{\n    _RYML_CB_ASSERT(m_callbacks, node != NONE);\n    return depth_desc_(*this, node);\n}\n\nid_type Tree::depth_asc(id_type node) const\n{\n    _RYML_CB_ASSERT(m_callbacks, node != NONE);\n    id_type depth = 0;\n    while(!is_root(node))\n    {\n        ++depth;\n        node = parent(node);\n    }\n    return depth;\n}\n\n\n//-----------------------------------------------------------------------------\n\nvoid Tree::to_val(id_type node, csubstr val, type_bits more_flags)\n{\n    _RYML_CB_ASSERT(m_callbacks,  ! has_children(node));\n    _RYML_CB_ASSERT(m_callbacks, parent(node) == NONE || ! parent_is_map(node));\n    _set_flags(node, VAL|more_flags);\n    _p(node)->m_key.clear();\n    _p(node)->m_val = val;\n}\n\nvoid Tree::to_keyval(id_type node, csubstr key, csubstr val, type_bits more_flags)\n{\n    _RYML_CB_ASSERT(m_callbacks,  ! has_children(node));\n    _RYML_CB_ASSERT(m_callbacks, parent(node) == NONE || parent_is_map(node));\n    _set_flags(node, KEYVAL|more_flags);\n    _p(node)->m_key = key;\n    _p(node)->m_val = val;\n}\n\nvoid Tree::to_map(id_type node, type_bits more_flags)\n{\n    _RYML_CB_ASSERT(m_callbacks,  ! has_children(node));\n    _RYML_CB_ASSERT(m_callbacks, parent(node) == NONE || ! parent_is_map(node)); // parent must not have children with keys\n    _set_flags(node, MAP|more_flags);\n    _p(node)->m_key.clear();\n    _p(node)->m_val.clear();\n}\n\nvoid Tree::to_map(id_type node, csubstr key, type_bits more_flags)\n{\n    _RYML_CB_ASSERT(m_callbacks,  ! has_children(node));\n    _RYML_CB_ASSERT(m_callbacks, parent(node) == NONE || parent_is_map(node));\n    _set_flags(node, KEY|MAP|more_flags);\n    _p(node)->m_key = key;\n    _p(node)->m_val.clear();\n}\n\nvoid Tree::to_seq(id_type node, type_bits more_flags)\n{\n    _RYML_CB_ASSERT(m_callbacks,  ! has_children(node));\n    _RYML_CB_ASSERT(m_callbacks, parent(node) == NONE || parent_is_seq(node));\n    _set_flags(node, SEQ|more_flags);\n    _p(node)->m_key.clear();\n    _p(node)->m_val.clear();\n}\n\nvoid Tree::to_seq(id_type node, csubstr key, type_bits more_flags)\n{\n    _RYML_CB_ASSERT(m_callbacks,  ! has_children(node));\n    _RYML_CB_ASSERT(m_callbacks, parent(node) == NONE || parent_is_map(node));\n    _set_flags(node, KEY|SEQ|more_flags);\n    _p(node)->m_key = key;\n    _p(node)->m_val.clear();\n}\n\nvoid Tree::to_doc(id_type node, type_bits more_flags)\n{\n    _RYML_CB_ASSERT(m_callbacks,  ! has_children(node));\n    _set_flags(node, DOC|more_flags);\n    _p(node)->m_key.clear();\n    _p(node)->m_val.clear();\n}\n\nvoid Tree::to_stream(id_type node, type_bits more_flags)\n{\n    _RYML_CB_ASSERT(m_callbacks,  ! has_children(node));\n    _set_flags(node, STREAM|more_flags);\n    _p(node)->m_key.clear();\n    _p(node)->m_val.clear();\n}\n\n\n//-----------------------------------------------------------------------------\nid_type Tree::num_tag_directives() const\n{\n    // this assumes we have a very small number of tag directives\n    for(id_type i = 0; i < RYML_MAX_TAG_DIRECTIVES; ++i)\n        if(m_tag_directives[i].handle.empty())\n            return i;\n    return RYML_MAX_TAG_DIRECTIVES;\n}\n\nvoid Tree::clear_tag_directives()\n{\n    for(TagDirective &td : m_tag_directives)\n        td = {};\n}\n\nid_type Tree::add_tag_directive(TagDirective const& td)\n{\n    _RYML_CB_CHECK(m_callbacks, !td.handle.empty());\n    _RYML_CB_CHECK(m_callbacks, !td.prefix.empty());\n    _RYML_CB_CHECK(m_callbacks, td.handle.begins_with('!'));\n    _RYML_CB_CHECK(m_callbacks, td.handle.ends_with('!'));\n    // https://yaml.org/spec/1.2.2/#rule-ns-word-char\n    _RYML_CB_CHECK(m_callbacks, td.handle == '!' || td.handle == \"!!\" || td.handle.trim('!').first_not_of(\"01234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-\") == npos);\n    id_type pos = num_tag_directives();\n    _RYML_CB_CHECK(m_callbacks, pos < RYML_MAX_TAG_DIRECTIVES);\n    m_tag_directives[pos] = td;\n    return pos;\n}\n\nbool Tree::add_tag_directive(csubstr directive_)\n{\n    TagDirective td;\n    if(td.create_from_str(directive_, this))\n    {\n        add_tag_directive(td);\n        return true;\n    }\n    return false;\n}\n\nsize_t Tree::resolve_tag(substr output, csubstr tag, id_type node_id) const\n{\n    // lookup from the end. We want to find the first directive that\n    // matches the tag and has a target node id leq than the given\n    // node_id.\n    for(id_type i = RYML_MAX_TAG_DIRECTIVES-1; i != (id_type)-1; --i)\n    {\n        auto const& td = m_tag_directives[i];\n        if(td.handle.empty())\n            continue;\n        if(tag.begins_with(td.handle) && td.next_node_id <= node_id)\n            return td.transform(tag, output, m_callbacks);\n    }\n    if(tag.begins_with('!'))\n    {\n        if(is_custom_tag(tag))\n        {\n            _RYML_CB_ERR(m_callbacks, \"tag directive not found\");\n        }\n    }\n    return 0; // return 0 to signal that the tag is local and cannot be resolved\n}\n\nnamespace {\ncsubstr _transform_tag(Tree *t, csubstr tag, id_type node)\n{\n    _c4dbgpf(\"[{}] resolving tag ~~~{}~~~\", node, tag);\n    size_t required_size = t->resolve_tag(substr{}, tag, node);\n    if(!required_size)\n    {\n        if(tag.begins_with(\"!<\"))\n            tag = tag.sub(1);\n        _c4dbgpf(\"[{}] resolved tag: ~~~{}~~~\", node, tag);\n        return tag;\n    }\n    const char *prev_arena = t->arena().str;(void)prev_arena;\n    substr buf = t->alloc_arena(required_size);\n    _RYML_CB_ASSERT(t->m_callbacks, t->arena().str == prev_arena);\n    size_t actual_size = t->resolve_tag(buf, tag, node);\n    _RYML_CB_ASSERT(t->m_callbacks, actual_size <= required_size);\n    _c4dbgpf(\"[{}] resolved tag: ~~~{}~~~\", node, buf.first(actual_size));\n    return buf.first(actual_size);\n}\nvoid _resolve_tags(Tree *t, id_type node)\n{\n    NodeData *C4_RESTRICT d = t->_p(node);\n    if(d->m_type & KEYTAG)\n        d->m_key.tag = _transform_tag(t, d->m_key.tag, node);\n    if(d->m_type & VALTAG)\n        d->m_val.tag = _transform_tag(t, d->m_val.tag, node);\n    for(id_type child = t->first_child(node); child != NONE; child = t->next_sibling(child))\n        _resolve_tags(t, child);\n}\nsize_t _count_resolved_tags_size(Tree const* t, id_type node)\n{\n    size_t sz = 0;\n    NodeData const* C4_RESTRICT d = t->_p(node);\n    if(d->m_type & KEYTAG)\n        sz += t->resolve_tag(substr{}, d->m_key.tag, node);\n    if(d->m_type & VALTAG)\n        sz += t->resolve_tag(substr{}, d->m_val.tag, node);\n    for(id_type child = t->first_child(node); child != NONE; child = t->next_sibling(child))\n        sz += _count_resolved_tags_size(t, child);\n    return sz;\n}\nvoid _normalize_tags(Tree *t, id_type node)\n{\n    NodeData *C4_RESTRICT d = t->_p(node);\n    if(d->m_type & KEYTAG)\n        d->m_key.tag = normalize_tag(d->m_key.tag);\n    if(d->m_type & VALTAG)\n        d->m_val.tag = normalize_tag(d->m_val.tag);\n    for(id_type child = t->first_child(node); child != NONE; child = t->next_sibling(child))\n        _normalize_tags(t, child);\n}\nvoid _normalize_tags_long(Tree *t, id_type node)\n{\n    NodeData *C4_RESTRICT d = t->_p(node);\n    if(d->m_type & KEYTAG)\n        d->m_key.tag = normalize_tag_long(d->m_key.tag);\n    if(d->m_type & VALTAG)\n        d->m_val.tag = normalize_tag_long(d->m_val.tag);\n    for(id_type child = t->first_child(node); child != NONE; child = t->next_sibling(child))\n        _normalize_tags_long(t, child);\n}\n} // namespace\n\nvoid Tree::resolve_tags()\n{\n    if(empty())\n        return;\n    size_t needed_size = _count_resolved_tags_size(this, root_id());\n    if(needed_size)\n        reserve_arena(arena_size() + needed_size);\n    _resolve_tags(this, root_id());\n}\n\nvoid Tree::normalize_tags()\n{\n    if(empty())\n        return;\n    _normalize_tags(this, root_id());\n}\n\nvoid Tree::normalize_tags_long()\n{\n    if(empty())\n        return;\n    _normalize_tags_long(this, root_id());\n}\n\n\n//-----------------------------------------------------------------------------\n\ncsubstr Tree::lookup_result::resolved() const\n{\n    csubstr p = path.first(path_pos);\n    if(p.ends_with('.'))\n        p = p.first(p.len-1);\n    return p;\n}\n\ncsubstr Tree::lookup_result::unresolved() const\n{\n    return path.sub(path_pos);\n}\n\nvoid Tree::_advance(lookup_result *r, size_t more) const\n{\n    r->path_pos += more;\n    if(r->path.sub(r->path_pos).begins_with('.'))\n        ++r->path_pos;\n}\n\nTree::lookup_result Tree::lookup_path(csubstr path, id_type start) const\n{\n    if(start == NONE)\n        start = root_id();\n    lookup_result r(path, start);\n    if(path.empty())\n        return r;\n    _lookup_path(&r);\n    if(r.target == NONE && r.closest == start)\n        r.closest = NONE;\n    return r;\n}\n\nid_type Tree::lookup_path_or_modify(csubstr default_value, csubstr path, id_type start)\n{\n    id_type target = _lookup_path_or_create(path, start);\n    if(parent_is_map(target))\n        to_keyval(target, key(target), default_value);\n    else\n        to_val(target, default_value);\n    return target;\n}\n\nid_type Tree::lookup_path_or_modify(Tree const *src, id_type src_node, csubstr path, id_type start)\n{\n    id_type target = _lookup_path_or_create(path, start);\n    merge_with(src, src_node, target);\n    return target;\n}\n\nid_type Tree::_lookup_path_or_create(csubstr path, id_type start)\n{\n    if(start == NONE)\n        start = root_id();\n    lookup_result r(path, start);\n    _lookup_path(&r);\n    if(r.target != NONE)\n    {\n        C4_ASSERT(r.unresolved().empty());\n        return r.target;\n    }\n    _lookup_path_modify(&r);\n    return r.target;\n}\n\nvoid Tree::_lookup_path(lookup_result *r) const\n{\n    C4_ASSERT( ! r->unresolved().empty());\n    _lookup_path_token parent{\"\", type(r->closest)};\n    id_type node;\n    do\n    {\n        node = _next_node(r, &parent);\n        if(node != NONE)\n            r->closest = node;\n        if(r->unresolved().empty())\n        {\n            r->target = node;\n            return;\n        }\n    } while(node != NONE);\n}\n\nvoid Tree::_lookup_path_modify(lookup_result *r)\n{\n    C4_ASSERT( ! r->unresolved().empty());\n    _lookup_path_token parent{\"\", type(r->closest)};\n    id_type node;\n    do\n    {\n        node = _next_node_modify(r, &parent);\n        if(node != NONE)\n            r->closest = node;\n        if(r->unresolved().empty())\n        {\n            r->target = node;\n            return;\n        }\n    } while(node != NONE);\n}\n\nid_type Tree::_next_node(lookup_result * r, _lookup_path_token *parent) const\n{\n    _lookup_path_token token = _next_token(r, *parent);\n    if( ! token)\n        return NONE;\n\n    id_type node = NONE;\n    csubstr prev = token.value;\n    if(token.type == MAP || token.type == SEQ)\n    {\n        _RYML_CB_ASSERT(m_callbacks, !token.value.begins_with('['));\n        //_RYML_CB_ASSERT(m_callbacks, is_container(r->closest) || r->closest == NONE);\n        _RYML_CB_ASSERT(m_callbacks, is_map(r->closest));\n        node = find_child(r->closest, token.value);\n    }\n    else if(token.type == KEYVAL)\n    {\n        _RYML_CB_ASSERT(m_callbacks, r->unresolved().empty());\n        if(is_map(r->closest))\n            node = find_child(r->closest, token.value);\n    }\n    else if(token.type == KEY)\n    {\n        _RYML_CB_ASSERT(m_callbacks, token.value.begins_with('[') && token.value.ends_with(']'));\n        token.value = token.value.offs(1, 1).trim(' ');\n        id_type idx = 0;\n        _RYML_CB_CHECK(m_callbacks, from_chars(token.value, &idx));\n        node = child(r->closest, idx);\n    }\n    else\n    {\n        C4_NEVER_REACH();\n    }\n\n    if(node != NONE)\n    {\n        *parent = token;\n    }\n    else\n    {\n        csubstr p = r->path.sub(r->path_pos > 0 ? r->path_pos - 1 : r->path_pos);\n        r->path_pos -= prev.len;\n        if(p.begins_with('.'))\n            r->path_pos -= 1u;\n    }\n\n    return node;\n}\n\nid_type Tree::_next_node_modify(lookup_result * r, _lookup_path_token *parent)\n{\n    _lookup_path_token token = _next_token(r, *parent);\n    if( ! token)\n        return NONE;\n\n    id_type node = NONE;\n    if(token.type == MAP || token.type == SEQ)\n    {\n        _RYML_CB_ASSERT(m_callbacks, !token.value.begins_with('['));\n        //_RYML_CB_ASSERT(m_callbacks, is_container(r->closest) || r->closest == NONE);\n        if( ! is_container(r->closest))\n        {\n            if(has_key(r->closest))\n                to_map(r->closest, key(r->closest));\n            else\n                to_map(r->closest);\n        }\n        else\n        {\n            if(is_map(r->closest))\n                node = find_child(r->closest, token.value);\n            else\n            {\n                id_type pos = NONE;\n                _RYML_CB_CHECK(m_callbacks, c4::atox(token.value, &pos));\n                _RYML_CB_ASSERT(m_callbacks, pos != NONE);\n                node = child(r->closest, pos);\n            }\n        }\n        if(node == NONE)\n        {\n            _RYML_CB_ASSERT(m_callbacks, is_map(r->closest));\n            node = append_child(r->closest);\n            NodeData *n = _p(node);\n            n->m_key.scalar = token.value;\n            n->m_type.add(KEY);\n        }\n    }\n    else if(token.type == KEYVAL)\n    {\n        _RYML_CB_ASSERT(m_callbacks, r->unresolved().empty());\n        if(is_map(r->closest))\n        {\n            node = find_child(r->closest, token.value);\n            if(node == NONE)\n                node = append_child(r->closest);\n        }\n        else\n        {\n            _RYML_CB_ASSERT(m_callbacks, !is_seq(r->closest));\n            _add_flags(r->closest, MAP);\n            node = append_child(r->closest);\n        }\n        NodeData *n = _p(node);\n        n->m_key.scalar = token.value;\n        n->m_val.scalar = \"\";\n        n->m_type.add(KEYVAL);\n    }\n    else if(token.type == KEY)\n    {\n        _RYML_CB_ASSERT(m_callbacks, token.value.begins_with('[') && token.value.ends_with(']'));\n        token.value = token.value.offs(1, 1).trim(' ');\n        id_type idx;\n        if( ! from_chars(token.value, &idx))\n             return NONE;\n        if( ! is_container(r->closest))\n        {\n            if(has_key(r->closest))\n            {\n                csubstr k = key(r->closest);\n                _clear_type(r->closest);\n                to_seq(r->closest, k);\n            }\n            else\n            {\n                _clear_type(r->closest);\n                to_seq(r->closest);\n            }\n        }\n        _RYML_CB_ASSERT(m_callbacks, is_container(r->closest));\n        node = child(r->closest, idx);\n        if(node == NONE)\n        {\n            _RYML_CB_ASSERT(m_callbacks, num_children(r->closest) <= idx);\n            for(id_type i = num_children(r->closest); i <= idx; ++i)\n            {\n                node = append_child(r->closest);\n                if(i < idx)\n                {\n                    if(is_map(r->closest))\n                        to_keyval(node, /*\"~\"*/{}, /*\"~\"*/{});\n                    else if(is_seq(r->closest))\n                        to_val(node, /*\"~\"*/{});\n                }\n            }\n        }\n    }\n    else\n    {\n        C4_NEVER_REACH();\n    }\n\n    _RYML_CB_ASSERT(m_callbacks, node != NONE);\n    *parent = token;\n    return node;\n}\n\n/* types of tokens:\n * - seeing \"map.\"  ---> \"map\"/MAP\n * - finishing \"scalar\" ---> \"scalar\"/KEYVAL\n * - seeing \"seq[n]\" ---> \"seq\"/SEQ (--> \"[n]\"/KEY)\n * - seeing \"[n]\" ---> \"[n]\"/KEY\n */\nTree::_lookup_path_token Tree::_next_token(lookup_result *r, _lookup_path_token const& parent) const\n{\n    csubstr unres = r->unresolved();\n    if(unres.empty())\n        return {};\n\n    // is it an indexation like [0], [1], etc?\n    if(unres.begins_with('['))\n    {\n        size_t pos = unres.find(']');\n        if(pos == csubstr::npos)\n            return {};\n        csubstr idx = unres.first(pos + 1);\n        _advance(r, pos + 1);\n        return {idx, KEY};\n    }\n\n    // no. so it must be a name\n    size_t pos = unres.first_of(\".[\");\n    if(pos == csubstr::npos)\n    {\n        _advance(r, unres.len);\n        NodeType t;\n        if(( ! parent) || parent.type.is_seq())\n            return {unres, VAL};\n        return {unres, KEYVAL};\n    }\n\n    // it's either a map or a seq\n    _RYML_CB_ASSERT(m_callbacks, unres[pos] == '.' || unres[pos] == '[');\n    if(unres[pos] == '.')\n    {\n        _RYML_CB_ASSERT(m_callbacks, pos != 0);\n        _advance(r, pos + 1);\n        return {unres.first(pos), MAP};\n    }\n\n    _RYML_CB_ASSERT(m_callbacks, unres[pos] == '[');\n    _advance(r, pos);\n    return {unres.first(pos), SEQ};\n}\n\n\n} // namespace ryml\n} // namespace c4\n\n\nC4_SUPPRESS_WARNING_GCC_CLANG_POP\nC4_SUPPRESS_WARNING_MSVC_POP\n"
  },
  {
    "path": "libs/rapidyaml/c4/yml/tree.hpp",
    "content": "#ifndef _C4_YML_TREE_HPP_\n#define _C4_YML_TREE_HPP_\n\n/** @file tree.hpp */\n\n#include \"c4/error.hpp\"\n#include \"c4/types.hpp\"\n#ifndef _C4_YML_FWD_HPP_\n#include \"c4/yml/fwd.hpp\"\n#endif\n#ifndef _C4_YML_COMMON_HPP_\n#include \"c4/yml/common.hpp\"\n#endif\n#ifndef C4_YML_NODE_TYPE_HPP_\n#include \"c4/yml/node_type.hpp\"\n#endif\n#ifndef _C4_YML_TAG_HPP_\n#include \"c4/yml/tag.hpp\"\n#endif\n#ifndef _C4_CHARCONV_HPP_\n#include <c4/charconv.hpp>\n#endif\n\n#include <cmath>\n#include <limits>\n\n\nC4_SUPPRESS_WARNING_MSVC_PUSH\nC4_SUPPRESS_WARNING_MSVC(4251) // needs to have dll-interface to be used by clients of struct\nC4_SUPPRESS_WARNING_MSVC(4296) // expression is always 'boolean_value'\nC4_SUPPRESS_WARNING_GCC_CLANG_PUSH\nC4_SUPPRESS_WARNING_GCC_CLANG(\"-Wold-style-cast\")\nC4_SUPPRESS_WARNING_GCC(\"-Wuseless-cast\")\nC4_SUPPRESS_WARNING_GCC(\"-Wtype-limits\")\n\n\nnamespace c4 {\nnamespace yml {\n\n/** encode a floating point value to a string. */\ntemplate<class T>\nsize_t to_chars_float(substr buf, T val)\n{\n    C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH(\"-Wfloat-equal\");\n    static_assert(std::is_floating_point<T>::value, \"must be floating point\");\n    if(C4_UNLIKELY(std::isnan(val)))\n        return to_chars(buf, csubstr(\".nan\"));\n    else if(C4_UNLIKELY(val == std::numeric_limits<T>::infinity()))\n        return to_chars(buf, csubstr(\".inf\"));\n    else if(C4_UNLIKELY(val == -std::numeric_limits<T>::infinity()))\n        return to_chars(buf, csubstr(\"-.inf\"));\n    return to_chars(buf, val);\n    C4_SUPPRESS_WARNING_GCC_CLANG_POP\n}\n\n\n/** decode a floating point from string. Accepts special values: .nan,\n * .inf, -.inf */\ntemplate<class T>\nbool from_chars_float(csubstr buf, T *C4_RESTRICT val)\n{\n    static_assert(std::is_floating_point<T>::value, \"must be floating point\");\n    if(C4_LIKELY(from_chars(buf, val)))\n    {\n        return true;\n    }\n    else if(C4_UNLIKELY(buf.begins_with('+')))\n    {\n        return from_chars(buf.sub(1), val);\n    }\n    else if(C4_UNLIKELY(buf == \".nan\" || buf == \".NaN\" || buf == \".NAN\"))\n    {\n        *val = std::numeric_limits<T>::quiet_NaN();\n        return true;\n    }\n    else if(C4_UNLIKELY(buf == \".inf\" || buf == \".Inf\" || buf == \".INF\"))\n    {\n        *val = std::numeric_limits<T>::infinity();\n        return true;\n    }\n    else if(C4_UNLIKELY(buf == \"-.inf\" || buf == \"-.Inf\" || buf == \"-.INF\"))\n    {\n        *val = -std::numeric_limits<T>::infinity();\n        return true;\n    }\n    else\n    {\n        return false;\n    }\n}\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n\n/** @addtogroup doc_tree\n *\n * @{\n */\n\n/** a node scalar is a csubstr, which may be tagged and anchored. */\nstruct NodeScalar\n{\n    csubstr tag;\n    csubstr scalar;\n    csubstr anchor;\n\npublic:\n\n    /// initialize as an empty scalar\n    inline NodeScalar() noexcept : tag(), scalar(), anchor() {}\n\n    /// initialize as an untagged scalar\n    template<size_t N>\n    inline NodeScalar(const char (&s)[N]) noexcept : tag(), scalar(s), anchor() {}\n    inline NodeScalar(csubstr      s    ) noexcept : tag(), scalar(s), anchor() {}\n\n    /// initialize as a tagged scalar\n    template<size_t N, size_t M>\n    inline NodeScalar(const char (&t)[N], const char (&s)[N]) noexcept : tag(t), scalar(s), anchor() {}\n    inline NodeScalar(csubstr      t    , csubstr      s    ) noexcept : tag(t), scalar(s), anchor() {}\n\npublic:\n\n    ~NodeScalar() noexcept = default;\n    NodeScalar(NodeScalar &&) noexcept = default;\n    NodeScalar(NodeScalar const&) noexcept = default;\n    NodeScalar& operator= (NodeScalar &&) noexcept = default;\n    NodeScalar& operator= (NodeScalar const&) noexcept = default;\n\npublic:\n\n    bool empty() const noexcept { return tag.empty() && scalar.empty() && anchor.empty(); }\n\n    void clear() noexcept { tag.clear(); scalar.clear(); anchor.clear(); }\n\n    void set_ref_maybe_replacing_scalar(csubstr ref, bool has_scalar) RYML_NOEXCEPT\n    {\n        csubstr trimmed = ref.begins_with('*') ? ref.sub(1) : ref;\n        anchor = trimmed;\n        if((!has_scalar) || !scalar.ends_with(trimmed))\n            scalar = ref;\n    }\n};\nC4_MUST_BE_TRIVIAL_COPY(NodeScalar);\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n/** convenience class to initialize nodes */\nstruct NodeInit\n{\n\n    NodeType   type;\n    NodeScalar key;\n    NodeScalar val;\n\npublic:\n\n    /// initialize as an empty node\n    NodeInit() : type(NOTYPE), key(), val() {}\n    /// initialize as a typed node\n    NodeInit(NodeType_e t) : type(t), key(), val() {}\n    /// initialize as a sequence member\n    NodeInit(NodeScalar const& v) : type(VAL), key(), val(v) { _add_flags(); }\n    /// initialize as a sequence member with explicit type\n    NodeInit(NodeScalar const& v, NodeType_e t) : type(t|VAL), key(), val(v) { _add_flags(); }\n    /// initialize as a mapping member\n    NodeInit(              NodeScalar const& k, NodeScalar const& v) : type(KEYVAL), key(k), val(v) { _add_flags(); }\n    /// initialize as a mapping member with explicit type\n    NodeInit(NodeType_e t, NodeScalar const& k, NodeScalar const& v) : type(t), key(k), val(v) { _add_flags(); }\n    /// initialize as a mapping member with explicit type (eg for SEQ or MAP)\n    NodeInit(NodeType_e t, NodeScalar const& k                     ) : type(t), key(k), val( ) { _add_flags(KEY); }\n\npublic:\n\n    void clear()\n    {\n        type.clear();\n        key.clear();\n        val.clear();\n    }\n\n    void _add_flags(type_bits more_flags=0)\n    {\n        type = (type|more_flags);\n        if( ! key.tag.empty())\n            type = (type|KEYTAG);\n        if( ! val.tag.empty())\n            type = (type|VALTAG);\n        if( ! key.anchor.empty())\n            type = (type|KEYANCH);\n        if( ! val.anchor.empty())\n            type = (type|VALANCH);\n    }\n\n    bool _check() const\n    {\n        // key cannot be empty\n        RYML_ASSERT(key.scalar.empty() == ((type & KEY) == 0));\n        // key tag cannot be empty\n        RYML_ASSERT(key.tag.empty() == ((type & KEYTAG) == 0));\n        // val may be empty even though VAL is set. But when VAL is not set, val must be empty\n        RYML_ASSERT(((type & VAL) != 0) || val.scalar.empty());\n        // val tag cannot be empty\n        RYML_ASSERT(val.tag.empty() == ((type & VALTAG) == 0));\n        return true;\n    }\n};\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\n/** contains the data for each YAML node. */\nstruct NodeData\n{\n    NodeType   m_type;\n\n    NodeScalar m_key;\n    NodeScalar m_val;\n\n    id_type    m_parent;\n    id_type    m_first_child;\n    id_type    m_last_child;\n    id_type    m_next_sibling;\n    id_type    m_prev_sibling;\n};\nC4_MUST_BE_TRIVIAL_COPY(NodeData);\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n\nclass RYML_EXPORT Tree\n{\npublic:\n\n    /** @name construction and assignment */\n    /** @{ */\n\n    Tree() : Tree(get_callbacks()) {}\n    Tree(Callbacks const& cb);\n    Tree(id_type node_capacity, size_t arena_capacity=0) : Tree(node_capacity, arena_capacity, get_callbacks()) {}\n    Tree(id_type node_capacity, size_t arena_capacity, Callbacks const& cb);\n\n    ~Tree();\n\n    Tree(Tree const& that);\n    Tree(Tree     && that) noexcept;\n\n    Tree& operator= (Tree const& that);\n    Tree& operator= (Tree     && that) RYML_NOEXCEPT;\n\n    /** @} */\n\npublic:\n\n    /** @name memory and sizing */\n    /** @{ */\n\n    void reserve(id_type node_capacity);\n\n    /** clear the tree and zero every node\n     * @note does NOT clear the arena\n     * @see clear_arena() */\n    void clear();\n    inline void clear_arena() { m_arena_pos = 0; }\n\n    inline bool   empty() const { return m_size == 0; }\n\n    inline id_type size() const { return m_size; }\n    inline id_type capacity() const { return m_cap; }\n    inline id_type slack() const { RYML_ASSERT(m_cap >= m_size); return m_cap - m_size; }\n\n    Callbacks const& callbacks() const { return m_callbacks; }\n    void callbacks(Callbacks const& cb) { m_callbacks = cb; }\n\n    /** @} */\n\npublic:\n\n    /** @name node getters */\n    /** @{ */\n\n    //! get the index of a node belonging to this tree.\n    //! @p n can be nullptr, in which case NONE is returned\n    id_type id(NodeData const* n) const\n    {\n        if( ! n)\n            return NONE;\n        _RYML_CB_ASSERT(m_callbacks, n >= m_buf && n < m_buf + m_cap);\n        return static_cast<id_type>(n - m_buf);\n    }\n\n    //! get a pointer to a node's NodeData.\n    //! i can be NONE, in which case a nullptr is returned\n    inline NodeData *get(id_type node)\n    {\n        if(node == NONE)\n            return nullptr;\n        _RYML_CB_ASSERT(m_callbacks, node >= 0 && node < m_cap);\n        return m_buf + node;\n    }\n    //! get a pointer to a node's NodeData.\n    //! i can be NONE, in which case a nullptr is returned.\n    inline NodeData const *get(id_type node) const\n    {\n        if(node == NONE)\n            return nullptr;\n        _RYML_CB_ASSERT(m_callbacks, node >= 0 && node < m_cap);\n        return m_buf + node;\n    }\n\n    //! An if-less form of get() that demands a valid node index.\n    //! This function is implementation only; use at your own risk.\n    inline NodeData       * _p(id_type node)       { _RYML_CB_ASSERT(m_callbacks, node != NONE && node >= 0 && node < m_cap); return m_buf + node; }\n    //! An if-less form of get() that demands a valid node index.\n    //! This function is implementation only; use at your own risk.\n    inline NodeData const * _p(id_type node) const { _RYML_CB_ASSERT(m_callbacks, node != NONE && node >= 0 && node < m_cap); return m_buf + node; }\n\n    //! Get the id of the root node\n    id_type root_id()       { if(m_cap == 0) { reserve(16); } _RYML_CB_ASSERT(m_callbacks, m_cap > 0 && m_size > 0); return 0; }\n    //! Get the id of the root node\n    id_type root_id() const {                                 _RYML_CB_ASSERT(m_callbacks, m_cap > 0 && m_size > 0); return 0; }\n\n    //! Get a NodeRef of a node by id\n    NodeRef      ref(id_type node);\n    //! Get a NodeRef of a node by id\n    ConstNodeRef ref(id_type node) const;\n    //! Get a NodeRef of a node by id\n    ConstNodeRef cref(id_type node) const;\n\n    //! Get the root as a NodeRef\n    NodeRef      rootref();\n    //! Get the root as a ConstNodeRef\n    ConstNodeRef rootref() const;\n    //! Get the root as a ConstNodeRef\n    ConstNodeRef crootref() const;\n\n    //! get the i-th document of the stream\n    //! @note @p i is NOT the node id, but the doc position within the stream\n    NodeRef      docref(id_type i);\n    //! get the i-th document of the stream\n    //! @note @p i is NOT the node id, but the doc position within the stream\n    ConstNodeRef docref(id_type i) const;\n    //! get the i-th document of the stream\n    //! @note @p i is NOT the node id, but the doc position within the stream\n    ConstNodeRef cdocref(id_type i) const;\n\n    //! find a root child by name, return it as a NodeRef\n    //! @note requires the root to be a map.\n    NodeRef      operator[] (csubstr key);\n    //! find a root child by name, return it as a NodeRef\n    //! @note requires the root to be a map.\n    ConstNodeRef operator[] (csubstr key) const;\n\n    //! find a root child by index: return the root node's @p i-th child as a NodeRef\n    //! @note @p i is NOT the node id, but the child's position\n    NodeRef      operator[] (id_type i);\n    //! find a root child by index: return the root node's @p i-th child as a NodeRef\n    //! @note @p i is NOT the node id, but the child's position\n    ConstNodeRef operator[] (id_type i) const;\n\n    /** @} */\n\npublic:\n\n    /** @name node property getters */\n    /** @{ */\n\n    NodeType type(id_type node) const { return _p(node)->m_type; }\n    const char* type_str(id_type node) const { return NodeType::type_str(_p(node)->m_type); }\n\n    csubstr    const& key       (id_type node) const { _RYML_CB_ASSERT(m_callbacks, has_key(node)); return _p(node)->m_key.scalar; }\n    csubstr    const& key_tag   (id_type node) const { _RYML_CB_ASSERT(m_callbacks, has_key_tag(node)); return _p(node)->m_key.tag; }\n    csubstr    const& key_ref   (id_type node) const { _RYML_CB_ASSERT(m_callbacks, is_key_ref(node)); return _p(node)->m_key.anchor; }\n    csubstr    const& key_anchor(id_type node) const { _RYML_CB_ASSERT(m_callbacks, has_key_anchor(node)); return _p(node)->m_key.anchor; }\n    NodeScalar const& keysc     (id_type node) const { _RYML_CB_ASSERT(m_callbacks, has_key(node)); return _p(node)->m_key; }\n\n    csubstr    const& val       (id_type node) const { _RYML_CB_ASSERT(m_callbacks, has_val(node)); return _p(node)->m_val.scalar; }\n    csubstr    const& val_tag   (id_type node) const { _RYML_CB_ASSERT(m_callbacks, has_val_tag(node)); return _p(node)->m_val.tag; }\n    csubstr    const& val_ref   (id_type node) const { _RYML_CB_ASSERT(m_callbacks, is_val_ref(node)); return _p(node)->m_val.anchor; }\n    csubstr    const& val_anchor(id_type node) const { _RYML_CB_ASSERT(m_callbacks, has_val_anchor(node)); return _p(node)->m_val.anchor; }\n    NodeScalar const& valsc     (id_type node) const { _RYML_CB_ASSERT(m_callbacks, has_val(node)); return _p(node)->m_val; }\n\n    /** @} */\n\npublic:\n\n    /** @name node type predicates */\n    /** @{ */\n\n    C4_ALWAYS_INLINE bool type_has_any(id_type node, NodeType_e bits) const { return _p(node)->m_type.has_any(bits); }\n    C4_ALWAYS_INLINE bool type_has_all(id_type node, NodeType_e bits) const { return _p(node)->m_type.has_all(bits); }\n    C4_ALWAYS_INLINE bool type_has_none(id_type node, NodeType_e bits) const { return _p(node)->m_type.has_none(bits); }\n\n    C4_ALWAYS_INLINE bool is_stream(id_type node) const { return _p(node)->m_type.is_stream(); }\n    C4_ALWAYS_INLINE bool is_doc(id_type node) const { return _p(node)->m_type.is_doc(); }\n    C4_ALWAYS_INLINE bool is_container(id_type node) const { return _p(node)->m_type.is_container(); }\n    C4_ALWAYS_INLINE bool is_map(id_type node) const { return _p(node)->m_type.is_map(); }\n    C4_ALWAYS_INLINE bool is_seq(id_type node) const { return _p(node)->m_type.is_seq(); }\n    C4_ALWAYS_INLINE bool has_key(id_type node) const { return _p(node)->m_type.has_key(); }\n    C4_ALWAYS_INLINE bool has_val(id_type node) const { return _p(node)->m_type.has_val(); }\n    C4_ALWAYS_INLINE bool is_val(id_type node) const { return _p(node)->m_type.is_val(); }\n    C4_ALWAYS_INLINE bool is_keyval(id_type node) const { return _p(node)->m_type.is_keyval(); }\n    C4_ALWAYS_INLINE bool has_key_tag(id_type node) const { return _p(node)->m_type.has_key_tag(); }\n    C4_ALWAYS_INLINE bool has_val_tag(id_type node) const { return _p(node)->m_type.has_val_tag(); }\n    C4_ALWAYS_INLINE bool has_key_anchor(id_type node) const { return _p(node)->m_type.has_key_anchor(); }\n    C4_ALWAYS_INLINE bool has_val_anchor(id_type node) const { return _p(node)->m_type.has_val_anchor(); }\n    C4_ALWAYS_INLINE bool has_anchor(id_type node) const { return _p(node)->m_type.has_anchor(); }\n    C4_ALWAYS_INLINE bool is_key_ref(id_type node) const { return _p(node)->m_type.is_key_ref(); }\n    C4_ALWAYS_INLINE bool is_val_ref(id_type node) const { return _p(node)->m_type.is_val_ref(); }\n    C4_ALWAYS_INLINE bool is_ref(id_type node) const { return _p(node)->m_type.is_ref(); }\n\n    C4_ALWAYS_INLINE bool parent_is_seq(id_type node) const { _RYML_CB_ASSERT(m_callbacks, has_parent(node)); return is_seq(_p(node)->m_parent); }\n    C4_ALWAYS_INLINE bool parent_is_map(id_type node) const { _RYML_CB_ASSERT(m_callbacks, has_parent(node)); return is_map(_p(node)->m_parent); }\n\n    /** true when the node has an anchor named a */\n    C4_ALWAYS_INLINE bool has_anchor(id_type node, csubstr a) const { return _p(node)->m_key.anchor == a || _p(node)->m_val.anchor == a; }\n\n    /** true if the node key does not have any KEYQUO flags, and its scalar verifies scalar_is_null().\n     * @warning the node must verify .has_key() (asserted) (ie must be a member of a map)\n     * @see https://github.com/biojppm/rapidyaml/issues/413 */\n    C4_ALWAYS_INLINE bool key_is_null(id_type node) const { _RYML_CB_ASSERT(m_callbacks, has_key(node)); NodeData const* C4_RESTRICT n = _p(node); return !n->m_type.is_key_quoted() && scalar_is_null(n->m_key.scalar); }\n    /** true if the node key does not have any VALQUO flags, and its scalar verifies scalar_is_null().\n     * @warning the node must verify .has_val() (asserted) (ie must be a scalar / must not be a container)\n     * @see https://github.com/biojppm/rapidyaml/issues/413 */\n    C4_ALWAYS_INLINE bool val_is_null(id_type node) const { _RYML_CB_ASSERT(m_callbacks, has_val(node)); NodeData const* C4_RESTRICT n = _p(node); return !n->m_type.is_val_quoted() && scalar_is_null(n->m_val.scalar); }\n\n    /// true if the key was a scalar requiring filtering and was left\n    /// unfiltered during the parsing (see ParserOptions)\n    C4_ALWAYS_INLINE bool is_key_unfiltered(id_type node) const { return _p(node)->m_type.is_key_unfiltered(); }\n    /// true if the val was a scalar requiring filtering and was left\n    /// unfiltered during the parsing (see ParserOptions)\n    C4_ALWAYS_INLINE bool is_val_unfiltered(id_type node) const { return _p(node)->m_type.is_val_unfiltered(); }\n\n    RYML_DEPRECATED(\"use has_key_anchor()\")    bool is_key_anchor(id_type node) const { return _p(node)->m_type.has_key_anchor(); }\n    RYML_DEPRECATED(\"use has_val_anchor()\")    bool is_val_anchor(id_type node) const { return _p(node)->m_type.has_val_anchor(); }\n    RYML_DEPRECATED(\"use has_anchor()\")        bool is_anchor(id_type node) const { return _p(node)->m_type.has_anchor(); }\n    RYML_DEPRECATED(\"use has_anchor_or_ref()\") bool is_anchor_or_ref(id_type node) const { return _p(node)->m_type.has_anchor() || _p(node)->m_type.is_ref(); }\n\n    /** @} */\n\npublic:\n\n    /** @name hierarchy predicates */\n    /** @{ */\n\n    bool is_root(id_type node) const { _RYML_CB_ASSERT(m_callbacks, _p(node)->m_parent != NONE || node == 0); return _p(node)->m_parent == NONE; }\n\n    bool has_parent(id_type node) const { return _p(node)->m_parent != NONE; }\n\n    /** true when key and val are empty, and has no children */\n    bool empty(id_type node) const { return ! has_children(node) && _p(node)->m_key.empty() && (( ! (_p(node)->m_type & VAL)) || _p(node)->m_val.empty()); }\n\n    /** true if @p node has a child with id @p ch */\n    bool has_child(id_type node, id_type ch) const { return _p(ch)->m_parent == node; }\n    /** true if @p node has a child with key @p key */\n    bool has_child(id_type node, csubstr key) const { return find_child(node, key) != NONE; }\n    /** true if @p node has any children key */\n    bool has_children(id_type node) const { return _p(node)->m_first_child != NONE; }\n\n    /** true if @p node has a sibling with id @p sib */\n    bool has_sibling(id_type node, id_type sib) const { return _p(node)->m_parent == _p(sib)->m_parent; }\n    /** true if one of the node's siblings has the given key */\n    bool has_sibling(id_type node, csubstr key) const { return find_sibling(node, key) != NONE; }\n    /** true if node is not a single child */\n    bool has_other_siblings(id_type node) const\n    {\n        NodeData const *n = _p(node);\n        if(C4_LIKELY(n->m_parent != NONE))\n        {\n            n = _p(n->m_parent);\n            return n->m_first_child != n->m_last_child;\n        }\n        return false;\n    }\n\n    RYML_DEPRECATED(\"use has_other_siblings()\") bool has_siblings(id_type /*node*/) const { return true; }\n\n    /** @} */\n\npublic:\n\n    /** @name hierarchy getters */\n    /** @{ */\n\n    id_type parent(id_type node) const { return _p(node)->m_parent; }\n\n    id_type prev_sibling(id_type node) const { return _p(node)->m_prev_sibling; }\n    id_type next_sibling(id_type node) const { return _p(node)->m_next_sibling; }\n\n    /** O(#num_children) */\n    id_type num_children(id_type node) const;\n    id_type child_pos(id_type node, id_type ch) const;\n    id_type first_child(id_type node) const { return _p(node)->m_first_child; }\n    id_type last_child(id_type node) const { return _p(node)->m_last_child; }\n    id_type child(id_type node, id_type pos) const;\n    id_type find_child(id_type node, csubstr const& key) const;\n\n    /** O(#num_siblings) */\n    /** counts with this */\n    id_type num_siblings(id_type node) const { return is_root(node) ? 1 : num_children(_p(node)->m_parent); }\n    /** does not count with this */\n    id_type num_other_siblings(id_type node) const { id_type ns = num_siblings(node); _RYML_CB_ASSERT(m_callbacks, ns > 0); return ns-1; }\n    id_type sibling_pos(id_type node, id_type sib) const { _RYML_CB_ASSERT(m_callbacks,  ! is_root(node) || node == root_id()); return child_pos(_p(node)->m_parent, sib); }\n    id_type first_sibling(id_type node) const { return is_root(node) ? node : _p(_p(node)->m_parent)->m_first_child; }\n    id_type last_sibling(id_type node) const { return is_root(node) ? node : _p(_p(node)->m_parent)->m_last_child; }\n    id_type sibling(id_type node, id_type pos) const { return child(_p(node)->m_parent, pos); }\n    id_type find_sibling(id_type node, csubstr const& key) const { return find_child(_p(node)->m_parent, key); }\n\n    id_type doc(id_type i) const { id_type rid = root_id(); _RYML_CB_ASSERT(m_callbacks, is_stream(rid)); return child(rid, i); } //!< gets the @p i document node index. requires that the root node is a stream.\n\n    id_type depth_asc(id_type node) const; /**< O(log(num_tree_nodes)) get the ascending depth of the node: number of levels between root and node */\n    id_type depth_desc(id_type node) const; /**< O(num_tree_nodes) get the descending depth of the node: number of levels between node and deepest child */\n\n    /** @} */\n\npublic:\n\n    /** @name node style predicates and modifiers. see the corresponding predicate in NodeType */\n    /** @{ */\n\n    C4_ALWAYS_INLINE bool is_container_styled(id_type node) const { return _p(node)->m_type.is_container_styled(); }\n    C4_ALWAYS_INLINE bool is_block(id_type node) const { return _p(node)->m_type.is_block(); }\n    C4_ALWAYS_INLINE bool is_flow_sl(id_type node) const { return _p(node)->m_type.is_flow_sl(); }\n    C4_ALWAYS_INLINE bool is_flow_ml(id_type node) const { return _p(node)->m_type.is_flow_ml(); }\n    C4_ALWAYS_INLINE bool is_flow(id_type node) const { return _p(node)->m_type.is_flow(); }\n\n    C4_ALWAYS_INLINE bool is_key_styled(id_type node) const { return _p(node)->m_type.is_key_styled(); }\n    C4_ALWAYS_INLINE bool is_val_styled(id_type node) const { return _p(node)->m_type.is_val_styled(); }\n    C4_ALWAYS_INLINE bool is_key_literal(id_type node) const { return _p(node)->m_type.is_key_literal(); }\n    C4_ALWAYS_INLINE bool is_val_literal(id_type node) const { return _p(node)->m_type.is_val_literal(); }\n    C4_ALWAYS_INLINE bool is_key_folded(id_type node) const { return _p(node)->m_type.is_key_folded(); }\n    C4_ALWAYS_INLINE bool is_val_folded(id_type node) const { return _p(node)->m_type.is_val_folded(); }\n    C4_ALWAYS_INLINE bool is_key_squo(id_type node) const { return _p(node)->m_type.is_key_squo(); }\n    C4_ALWAYS_INLINE bool is_val_squo(id_type node) const { return _p(node)->m_type.is_val_squo(); }\n    C4_ALWAYS_INLINE bool is_key_dquo(id_type node) const { return _p(node)->m_type.is_key_dquo(); }\n    C4_ALWAYS_INLINE bool is_val_dquo(id_type node) const { return _p(node)->m_type.is_val_dquo(); }\n    C4_ALWAYS_INLINE bool is_key_plain(id_type node) const { return _p(node)->m_type.is_key_plain(); }\n    C4_ALWAYS_INLINE bool is_val_plain(id_type node) const { return _p(node)->m_type.is_val_plain(); }\n    C4_ALWAYS_INLINE bool is_key_quoted(id_type node) const { return _p(node)->m_type.is_key_quoted(); }\n    C4_ALWAYS_INLINE bool is_val_quoted(id_type node) const { return _p(node)->m_type.is_val_quoted(); }\n    C4_ALWAYS_INLINE bool is_quoted(id_type node) const { return _p(node)->m_type.is_quoted(); }\n\n    C4_ALWAYS_INLINE void set_container_style(id_type node, NodeType_e style) { _RYML_CB_ASSERT(m_callbacks, is_container(node)); _p(node)->m_type.set_container_style(style); }\n    C4_ALWAYS_INLINE void set_key_style(id_type node, NodeType_e style) { _RYML_CB_ASSERT(m_callbacks, has_key(node)); _p(node)->m_type.set_key_style(style); }\n    C4_ALWAYS_INLINE void set_val_style(id_type node, NodeType_e style) { _RYML_CB_ASSERT(m_callbacks, has_val(node)); _p(node)->m_type.set_val_style(style); }\n\n    /** @} */\n\npublic:\n\n    /** @name node type modifiers */\n    /** @{ */\n\n    void to_keyval(id_type node, csubstr key, csubstr val, type_bits more_flags=0);\n    void to_map(id_type node, csubstr key, type_bits more_flags=0);\n    void to_seq(id_type node, csubstr key, type_bits more_flags=0);\n    void to_val(id_type node, csubstr val, type_bits more_flags=0);\n    void to_map(id_type node, type_bits more_flags=0);\n    void to_seq(id_type node, type_bits more_flags=0);\n    void to_doc(id_type node, type_bits more_flags=0);\n    void to_stream(id_type node, type_bits more_flags=0);\n\n    void set_key(id_type node, csubstr key) { _RYML_CB_ASSERT(m_callbacks, has_key(node)); _p(node)->m_key.scalar = key; }\n    void set_val(id_type node, csubstr val) { _RYML_CB_ASSERT(m_callbacks, has_val(node)); _p(node)->m_val.scalar = val; }\n\n    void set_key_tag(id_type node, csubstr tag) { _RYML_CB_ASSERT(m_callbacks, has_key(node)); _p(node)->m_key.tag = tag; _add_flags(node, KEYTAG); }\n    void set_val_tag(id_type node, csubstr tag) { _RYML_CB_ASSERT(m_callbacks, has_val(node) || is_container(node)); _p(node)->m_val.tag = tag; _add_flags(node, VALTAG); }\n\n    void set_key_anchor(id_type node, csubstr anchor) { _RYML_CB_ASSERT(m_callbacks,  ! is_key_ref(node)); _p(node)->m_key.anchor = anchor.triml('&'); _add_flags(node, KEYANCH); }\n    void set_val_anchor(id_type node, csubstr anchor) { _RYML_CB_ASSERT(m_callbacks,  ! is_val_ref(node)); _p(node)->m_val.anchor = anchor.triml('&'); _add_flags(node, VALANCH); }\n    void set_key_ref   (id_type node, csubstr ref   ) { _RYML_CB_ASSERT(m_callbacks,  ! has_key_anchor(node)); NodeData* C4_RESTRICT n = _p(node); n->m_key.set_ref_maybe_replacing_scalar(ref, n->m_type.has_key()); _add_flags(node, KEY|KEYREF); }\n    void set_val_ref   (id_type node, csubstr ref   ) { _RYML_CB_ASSERT(m_callbacks,  ! has_val_anchor(node)); NodeData* C4_RESTRICT n = _p(node); n->m_val.set_ref_maybe_replacing_scalar(ref, n->m_type.has_val()); _add_flags(node, VAL|VALREF); }\n\n    void rem_key_anchor(id_type node) { _p(node)->m_key.anchor.clear(); _rem_flags(node, KEYANCH); }\n    void rem_val_anchor(id_type node) { _p(node)->m_val.anchor.clear(); _rem_flags(node, VALANCH); }\n    void rem_key_ref   (id_type node) { _p(node)->m_key.anchor.clear(); _rem_flags(node, KEYREF); }\n    void rem_val_ref   (id_type node) { _p(node)->m_val.anchor.clear(); _rem_flags(node, VALREF); }\n    void rem_anchor_ref(id_type node) { _p(node)->m_key.anchor.clear(); _p(node)->m_val.anchor.clear(); _rem_flags(node, KEYANCH|VALANCH|KEYREF|VALREF); }\n\n    /** @} */\n\npublic:\n\n    /** @name tree modifiers */\n    /** @{ */\n\n    /** reorder the tree in memory so that all the nodes are stored\n     * in a linear sequence when visited in depth-first order.\n     * This will invalidate existing ids, since the node id is its\n     * position in the tree's node array. */\n    void reorder();\n\n    /** Resolve references (aliases <- anchors) in the tree.\n     *\n     * Dereferencing is opt-in; after parsing, Tree::resolve() has to\n     * be called explicitly for obtaining resolved references in the\n     * tree. This method will @ref ReferenceResolver::resolve()\n     * to resolve all references and substitute the anchored values in\n     * place of the reference.\n     *\n     * This method first does a full traversal of the tree to gather all\n     * anchors and references in a separate collection, then it goes through\n     * that collection to locate the names, which it does by obeying the YAML\n     * standard diktat that \"an alias node refers to the most recent node in\n     * the serialization having the specified anchor\"\n     *\n     * So, depending on the number of anchor/alias nodes, this is a\n     * potentially expensive operation, with a best-case linear complexity\n     * (from the initial traversal). This potential cost is the reason for\n     * requiring an explicit call.\n     *\n     * @see ReferenceResolver::resolve()\n     */\n    void resolve(ReferenceResolver *C4_RESTRICT rr);\n\n    /** Resolve references using a throw-away resolver. */\n    void resolve();\n\n    /** @} */\n\npublic:\n\n    /** @name tag directives */\n    /** @{ */\n\n    void resolve_tags();\n    void normalize_tags();\n    void normalize_tags_long();\n\n    id_type num_tag_directives() const;\n    bool add_tag_directive(csubstr directive);\n    id_type add_tag_directive(TagDirective const& td);\n    void clear_tag_directives();\n\n    /** resolve the given tag, appearing at node_id. Write the result into output.\n     * @return the number of characters required for the resolved tag */\n    size_t resolve_tag(substr output, csubstr tag, id_type node_id) const;\n    csubstr resolve_tag_sub(substr output, csubstr tag, id_type node_id) const\n    {\n        size_t needed = resolve_tag(output, tag, node_id);\n        return needed <= output.len ? output.first(needed) : output;\n    }\n\n    TagDirective const* begin_tag_directives() const { return m_tag_directives; }\n    TagDirective const* end_tag_directives() const { return m_tag_directives + num_tag_directives(); }\n    c4::yml::TagDirectiveRange tag_directives() const { return c4::yml::TagDirectiveRange{begin_tag_directives(), end_tag_directives()}; }\n\n    RYML_DEPRECATED(\"use c4::yml::tag_directive_const_iterator\") typedef TagDirective const* tag_directive_const_iterator;\n    RYML_DEPRECATED(\"use c4::yml::TagDirectiveRange\") typedef c4::yml::TagDirectiveRange TagDirectiveProxy;\n\n    /** @} */\n\npublic:\n\n    /** @name modifying hierarchy */\n    /** @{ */\n\n    /** create and insert a new child of @p parent. insert after the (to-be)\n     * sibling @p after, which must be a child of @p parent. To insert as the\n     * first child, set after to NONE */\n    C4_ALWAYS_INLINE id_type insert_child(id_type parent, id_type after)\n    {\n        _RYML_CB_ASSERT(m_callbacks, parent != NONE);\n        _RYML_CB_ASSERT(m_callbacks, is_container(parent) || is_root(parent));\n        _RYML_CB_ASSERT(m_callbacks, after == NONE || (_p(after)->m_parent == parent));\n        id_type child = _claim();\n        _set_hierarchy(child, parent, after);\n        return child;\n    }\n    /** create and insert a node as the first child of @p parent */\n    C4_ALWAYS_INLINE id_type prepend_child(id_type parent) { return insert_child(parent, NONE); }\n    /** create and insert a node as the last child of @p parent */\n    C4_ALWAYS_INLINE id_type append_child(id_type parent) { return insert_child(parent, _p(parent)->m_last_child); }\n    C4_ALWAYS_INLINE id_type _append_child__unprotected(id_type parent)\n    {\n        id_type child = _claim();\n        _set_hierarchy(child, parent, _p(parent)->m_last_child);\n        return child;\n    }\n\npublic:\n\n    #if defined(__clang__)\n    #   pragma clang diagnostic push\n    #   pragma clang diagnostic ignored \"-Wnull-dereference\"\n    #elif defined(__GNUC__)\n    #   pragma GCC diagnostic push\n    #   if __GNUC__ >= 6\n    #       pragma GCC diagnostic ignored \"-Wnull-dereference\"\n    #   endif\n    #endif\n\n    //! create and insert a new sibling of n. insert after \"after\"\n    C4_ALWAYS_INLINE id_type insert_sibling(id_type node, id_type after)\n    {\n        return insert_child(_p(node)->m_parent, after);\n    }\n    /** create and insert a node as the first node of @p parent */\n    C4_ALWAYS_INLINE id_type prepend_sibling(id_type node) { return prepend_child(_p(node)->m_parent); }\n    C4_ALWAYS_INLINE id_type  append_sibling(id_type node) { return append_child(_p(node)->m_parent); }\n\npublic:\n\n    /** remove an entire branch at once: ie remove the children and the node itself */\n    inline void remove(id_type node)\n    {\n        remove_children(node);\n        _release(node);\n    }\n\n    /** remove all the node's children, but keep the node itself */\n    void remove_children(id_type node);\n\n    /** change the @p type of the node to one of MAP, SEQ or VAL.  @p\n     * type must have one and only one of MAP,SEQ,VAL; @p type may\n     * possibly have KEY, but if it does, then the @p node must also\n     * have KEY. Changing to the same type is a no-op. Otherwise,\n     * changing to a different type will initialize the node with an\n     * empty value of the desired type: changing to VAL will\n     * initialize with a null scalar (~), changing to MAP will\n     * initialize with an empty map ({}), and changing to SEQ will\n     * initialize with an empty seq ([]). */\n    bool change_type(id_type node, NodeType type);\n\n    bool change_type(id_type node, type_bits type)\n    {\n        return change_type(node, (NodeType)type);\n    }\n\n    #if defined(__clang__)\n    #   pragma clang diagnostic pop\n    #elif defined(__GNUC__)\n    #   pragma GCC diagnostic pop\n    #endif\n\npublic:\n\n    /** change the node's position in the parent */\n    void move(id_type node, id_type after);\n\n    /** change the node's parent and position */\n    void move(id_type node, id_type new_parent, id_type after);\n\n    /** change the node's parent and position to a different tree\n     * @return the index of the new node in the destination tree */\n    id_type move(Tree * src, id_type node, id_type new_parent, id_type after);\n\n    /** ensure the first node is a stream. Eg, change this tree\n     *\n     *  DOCMAP\n     *    MAP\n     *      KEYVAL\n     *      KEYVAL\n     *    SEQ\n     *      VAL\n     *\n     * to\n     *\n     *  STREAM\n     *    DOCMAP\n     *      MAP\n     *        KEYVAL\n     *        KEYVAL\n     *      SEQ\n     *        VAL\n     *\n     * If the root is already a stream, this is a no-op.\n     */\n    void set_root_as_stream();\n\npublic:\n\n    /** recursively duplicate a node from this tree into a new parent,\n     * placing it after one of its children\n     * @return the index of the copy */\n    id_type duplicate(id_type node, id_type new_parent, id_type after);\n    /** recursively duplicate a node from a different tree into a new parent,\n     * placing it after one of its children\n     * @return the index of the copy */\n    id_type duplicate(Tree const* src, id_type node, id_type new_parent, id_type after);\n\n    /** recursively duplicate the node's children (but not the node)\n     * @return the index of the last duplicated child */\n    id_type duplicate_children(id_type node, id_type parent, id_type after);\n    /** recursively duplicate the node's children (but not the node), where\n     * the node is from a different tree\n     * @return the index of the last duplicated child */\n    id_type duplicate_children(Tree const* src, id_type node, id_type parent, id_type after);\n\n    void duplicate_contents(id_type node, id_type where);\n    void duplicate_contents(Tree const* src, id_type node, id_type where);\n\n    /** duplicate the node's children (but not the node) in a new parent, but\n     * omit repetitions where a duplicated node has the same key (in maps) or\n     * value (in seqs). If one of the duplicated children has the same key\n     * (in maps) or value (in seqs) as one of the parent's children, the one\n     * that is placed closest to the end will prevail. */\n    id_type duplicate_children_no_rep(id_type node, id_type parent, id_type after);\n    id_type duplicate_children_no_rep(Tree const* src, id_type node, id_type parent, id_type after);\n\npublic:\n\n    void merge_with(Tree const* src, id_type src_node=NONE, id_type dst_root=NONE);\n\n    /** @} */\n\npublic:\n\n    /** @name internal string arena */\n    /** @{ */\n\n    /** get the current size of the tree's internal arena */\n    RYML_DEPRECATED(\"use arena_size() instead\") size_t arena_pos() const { return m_arena_pos; }\n    /** get the current size of the tree's internal arena */\n    inline size_t arena_size() const { return m_arena_pos; }\n    /** get the current capacity of the tree's internal arena */\n    inline size_t arena_capacity() const { return m_arena.len; }\n    /** get the current slack of the tree's internal arena */\n    inline size_t arena_slack() const { _RYML_CB_ASSERT(m_callbacks, m_arena.len >= m_arena_pos); return m_arena.len - m_arena_pos; }\n\n    /** get the current arena */\n    csubstr arena() const { return m_arena.first(m_arena_pos); }\n    /** get the current arena */\n    substr arena() { return m_arena.first(m_arena_pos); }\n\n    /** return true if the given substring is part of the tree's string arena */\n    bool in_arena(csubstr s) const\n    {\n        return m_arena.is_super(s);\n    }\n\n    /** serialize the given floating-point variable to the tree's\n     * arena, growing it as needed to accomodate the serialization.\n     *\n     * @note Growing the arena may cause relocation of the entire\n     * existing arena, and thus change the contents of individual\n     * nodes, and thus cost O(numnodes)+O(arenasize). To avoid this\n     * cost, ensure that the arena is reserved to an appropriate size\n     * using .reserve_arena()\n     *\n     * @see alloc_arena() */\n    template<class T>\n    typename std::enable_if<std::is_floating_point<T>::value, csubstr>::type\n    to_arena(T const& C4_RESTRICT a)\n    {\n        substr rem(m_arena.sub(m_arena_pos));\n        size_t num = to_chars_float(rem, a);\n        if(num > rem.len)\n        {\n            rem = _grow_arena(num);\n            num = to_chars_float(rem, a);\n            _RYML_CB_ASSERT(m_callbacks, num <= rem.len);\n        }\n        rem = _request_span(num);\n        return rem;\n    }\n\n    /** serialize the given non-floating-point variable to the tree's\n     * arena, growing it as needed to accomodate the serialization.\n     *\n     * @note Growing the arena may cause relocation of the entire\n     * existing arena, and thus change the contents of individual\n     * nodes, and thus cost O(numnodes)+O(arenasize). To avoid this\n     * cost, ensure that the arena is reserved to an appropriate size\n     * using .reserve_arena()\n     *\n     * @see alloc_arena() */\n    template<class T>\n    typename std::enable_if<!std::is_floating_point<T>::value, csubstr>::type\n    to_arena(T const& C4_RESTRICT a)\n    {\n        substr rem(m_arena.sub(m_arena_pos));\n        size_t num = to_chars(rem, a);\n        if(num > rem.len)\n        {\n            rem = _grow_arena(num);\n            num = to_chars(rem, a);\n            _RYML_CB_ASSERT(m_callbacks, num <= rem.len);\n        }\n        rem = _request_span(num);\n        return rem;\n    }\n\n    /** serialize the given csubstr to the tree's arena, growing the\n     * arena as needed to accomodate the serialization.\n     *\n     * @note Growing the arena may cause relocation of the entire\n     * existing arena, and thus change the contents of individual\n     * nodes, and thus cost O(numnodes)+O(arenasize). To avoid this\n     * cost, ensure that the arena is reserved to an appropriate size\n     * using .reserve_arena()\n     *\n     * @see alloc_arena() */\n    csubstr to_arena(csubstr a)\n    {\n        if(a.len > 0)\n        {\n            substr rem(m_arena.sub(m_arena_pos));\n            size_t num = to_chars(rem, a);\n            if(num > rem.len)\n            {\n                rem = _grow_arena(num);\n                num = to_chars(rem, a);\n                _RYML_CB_ASSERT(m_callbacks, num <= rem.len);\n            }\n            return _request_span(num);\n        }\n        else\n        {\n            if(a.str == nullptr)\n            {\n                return csubstr{};\n            }\n            else if(m_arena.str == nullptr)\n            {\n                // Arena is empty and we want to store a non-null\n                // zero-length string.\n                // Even though the string has zero length, we need\n                // some \"memory\" to store a non-nullptr string\n                _grow_arena(1);\n            }\n            return _request_span(0);\n        }\n    }\n    C4_ALWAYS_INLINE csubstr to_arena(const char *s)\n    {\n        return to_arena(to_csubstr(s));\n    }\n    C4_ALWAYS_INLINE csubstr to_arena(std::nullptr_t)\n    {\n        return csubstr{};\n    }\n\n    /** copy the given substr to the tree's arena, growing it by the\n     * required size\n     *\n     * @note Growing the arena may cause relocation of the entire\n     * existing arena, and thus change the contents of individual\n     * nodes, and thus cost O(numnodes)+O(arenasize). To avoid this\n     * cost, ensure that the arena is reserved to an appropriate size\n     * using .reserve_arena()\n     *\n     * @see alloc_arena() */\n    substr copy_to_arena(csubstr s)\n    {\n        substr cp = alloc_arena(s.len);\n        _RYML_CB_ASSERT(m_callbacks, cp.len == s.len);\n        _RYML_CB_ASSERT(m_callbacks, !s.overlaps(cp));\n        #if (!defined(__clang__)) && (defined(__GNUC__) && __GNUC__ >= 10)\n        C4_SUPPRESS_WARNING_GCC_PUSH\n        C4_SUPPRESS_WARNING_GCC(\"-Wstringop-overflow=\") // no need for terminating \\0\n        C4_SUPPRESS_WARNING_GCC( \"-Wrestrict\") // there's an assert to ensure no violation of restrict behavior\n        #endif\n        if(s.len)\n            memcpy(cp.str, s.str, s.len);\n        #if (!defined(__clang__)) && (defined(__GNUC__) && __GNUC__ >= 10)\n        C4_SUPPRESS_WARNING_GCC_POP\n        #endif\n        return cp;\n    }\n\n    /** grow the tree's string arena by the given size and return a substr\n     * of the added portion\n     *\n     * @note Growing the arena may cause relocation of the entire\n     * existing arena, and thus change the contents of individual\n     * nodes, and thus cost O(numnodes)+O(arenasize). To avoid this\n     * cost, ensure that the arena is reserved to an appropriate size\n     * using .reserve_arena().\n     *\n     * @see reserve_arena() */\n    substr alloc_arena(size_t sz)\n    {\n        if(sz > arena_slack())\n            _grow_arena(sz - arena_slack());\n        substr s = _request_span(sz);\n        return s;\n    }\n\n    /** ensure the tree's internal string arena is at least the given capacity\n     * @warning This operation may be expensive, with a potential complexity of O(numNodes)+O(arenasize).\n     * @warning Growing the arena may cause relocation of the entire\n     * existing arena, and thus change the contents of individual nodes. */\n    void reserve_arena(size_t arena_cap)\n    {\n        if(arena_cap > m_arena.len)\n        {\n            substr buf;\n            buf.str = (char*) m_callbacks.m_allocate(arena_cap, m_arena.str, m_callbacks.m_user_data);\n            buf.len = arena_cap;\n            if(m_arena.str)\n            {\n                _RYML_CB_ASSERT(m_callbacks, m_arena.len >= 0);\n                _relocate(buf); // does a memcpy and changes nodes using the arena\n                m_callbacks.m_free(m_arena.str, m_arena.len, m_callbacks.m_user_data);\n            }\n            m_arena = buf;\n        }\n    }\n\n    /** @} */\n\nprivate:\n\n    substr _grow_arena(size_t more)\n    {\n        size_t cap = m_arena.len + more;\n        cap = cap < 2 * m_arena.len ? 2 * m_arena.len : cap;\n        cap = cap < 64 ? 64 : cap;\n        reserve_arena(cap);\n        return m_arena.sub(m_arena_pos);\n    }\n\n    substr _request_span(size_t sz)\n    {\n        _RYML_CB_ASSERT(m_callbacks, m_arena_pos + sz <= m_arena.len);\n        substr s;\n        s = m_arena.sub(m_arena_pos, sz);\n        m_arena_pos += sz;\n        return s;\n    }\n\n    substr _relocated(csubstr s, substr next_arena) const\n    {\n        _RYML_CB_ASSERT(m_callbacks, m_arena.is_super(s));\n        _RYML_CB_ASSERT(m_callbacks, m_arena.sub(0, m_arena_pos).is_super(s));\n        auto pos = (s.str - m_arena.str); // this is larger than 0 based on the assertions above\n        substr r(next_arena.str + pos, s.len);\n        _RYML_CB_ASSERT(m_callbacks, r.str - next_arena.str == pos);\n        _RYML_CB_ASSERT(m_callbacks, next_arena.sub(0, m_arena_pos).is_super(r));\n        return r;\n    }\n\npublic:\n\n    /** @name lookup */\n    /** @{ */\n\n    struct lookup_result\n    {\n        id_type  target;\n        id_type  closest;\n        size_t  path_pos;\n        csubstr path;\n\n        inline operator bool() const { return target != NONE; }\n\n        lookup_result() : target(NONE), closest(NONE), path_pos(0), path() {}\n        lookup_result(csubstr path_, id_type start) : target(NONE), closest(start), path_pos(0), path(path_) {}\n\n        /** get the part ot the input path that was resolved */\n        csubstr resolved() const;\n        /** get the part ot the input path that was unresolved */\n        csubstr unresolved() const;\n    };\n\n    /** for example foo.bar[0].baz */\n    lookup_result lookup_path(csubstr path, id_type start=NONE) const;\n\n    /** defaulted lookup: lookup @p path; if the lookup fails, recursively modify\n     * the tree so that the corresponding lookup_path() would return the\n     * default value.\n     * @see lookup_path() */\n    id_type lookup_path_or_modify(csubstr default_value, csubstr path, id_type start=NONE);\n\n    /** defaulted lookup: lookup @p path; if the lookup fails, recursively modify\n     * the tree so that the corresponding lookup_path() would return the\n     * branch @p src_node (from the tree @p src).\n     * @see lookup_path() */\n    id_type lookup_path_or_modify(Tree const *src, id_type src_node, csubstr path, id_type start=NONE);\n\n    /** @} */\n\nprivate:\n\n    struct _lookup_path_token\n    {\n        csubstr value;\n        NodeType type;\n        _lookup_path_token() : value(), type() {}\n        _lookup_path_token(csubstr v, NodeType t) : value(v), type(t) {}\n        inline operator bool() const { return type != NOTYPE; }\n        bool is_index() const { return value.begins_with('[') && value.ends_with(']'); }\n    };\n\n    id_type _lookup_path_or_create(csubstr path, id_type start);\n\n    void   _lookup_path       (lookup_result *r) const;\n    void   _lookup_path_modify(lookup_result *r);\n\n    id_type _next_node       (lookup_result *r, _lookup_path_token *parent) const;\n    id_type _next_node_modify(lookup_result *r, _lookup_path_token *parent);\n\n    void   _advance(lookup_result *r, size_t more) const;\n\n    _lookup_path_token _next_token(lookup_result *r, _lookup_path_token const& parent) const;\n\nprivate:\n\n    void _clear();\n    void _free();\n    void _copy(Tree const& that);\n    void _move(Tree      & that) noexcept;\n\n    void _relocate(substr next_arena);\n\npublic:\n\n    /** @cond dev*/\n\n    #if ! RYML_USE_ASSERT\n    C4_ALWAYS_INLINE void _check_next_flags(id_type, type_bits) {}\n    #else\n    void _check_next_flags(id_type node, type_bits f)\n    {\n        auto n = _p(node);\n        type_bits o = n->m_type; // old\n        C4_UNUSED(o);\n        if(f & MAP)\n        {\n            RYML_ASSERT_MSG((f & SEQ) == 0, \"cannot mark simultaneously as map and seq\");\n            RYML_ASSERT_MSG((f & VAL) == 0, \"cannot mark simultaneously as map and val\");\n            RYML_ASSERT_MSG((o & SEQ) == 0, \"cannot turn a seq into a map; clear first\");\n            RYML_ASSERT_MSG((o & VAL) == 0, \"cannot turn a val into a map; clear first\");\n        }\n        else if(f & SEQ)\n        {\n            RYML_ASSERT_MSG((f & MAP) == 0, \"cannot mark simultaneously as seq and map\");\n            RYML_ASSERT_MSG((f & VAL) == 0, \"cannot mark simultaneously as seq and val\");\n            RYML_ASSERT_MSG((o & MAP) == 0, \"cannot turn a map into a seq; clear first\");\n            RYML_ASSERT_MSG((o & VAL) == 0, \"cannot turn a val into a seq; clear first\");\n        }\n        if(f & KEY)\n        {\n            _RYML_CB_ASSERT(m_callbacks, !is_root(node));\n            auto pid = parent(node); C4_UNUSED(pid);\n            _RYML_CB_ASSERT(m_callbacks, is_map(pid));\n        }\n        if((f & VAL) && !is_root(node))\n        {\n            auto pid = parent(node); C4_UNUSED(pid);\n            _RYML_CB_ASSERT(m_callbacks, is_map(pid) || is_seq(pid));\n        }\n    }\n    #endif\n\n    inline void _set_flags(id_type node, NodeType_e f) { _check_next_flags(node, f); _p(node)->m_type = f; }\n    inline void _set_flags(id_type node, type_bits  f) { _check_next_flags(node, f); _p(node)->m_type = f; }\n\n    inline void _add_flags(id_type node, NodeType_e f) { NodeData *d = _p(node); type_bits fb = f |  d->m_type; _check_next_flags(node, fb); d->m_type = (NodeType_e) fb; }\n    inline void _add_flags(id_type node, type_bits  f) { NodeData *d = _p(node);                f |= d->m_type; _check_next_flags(node,  f); d->m_type = f; }\n\n    inline void _rem_flags(id_type node, NodeType_e f) { NodeData *d = _p(node); type_bits fb = d->m_type & ~f; _check_next_flags(node, fb); d->m_type = (NodeType_e) fb; }\n    inline void _rem_flags(id_type node, type_bits  f) { NodeData *d = _p(node);            f = d->m_type & ~f; _check_next_flags(node,  f); d->m_type = f; }\n\n    void _set_key(id_type node, csubstr key, type_bits more_flags=0)\n    {\n        _p(node)->m_key.scalar = key;\n        _add_flags(node, KEY|more_flags);\n    }\n    void _set_key(id_type node, NodeScalar const& key, type_bits more_flags=0)\n    {\n        _p(node)->m_key = key;\n        _add_flags(node, KEY|more_flags);\n    }\n\n    void _set_val(id_type node, csubstr val, type_bits more_flags=0)\n    {\n        _RYML_CB_ASSERT(m_callbacks, num_children(node) == 0);\n        _RYML_CB_ASSERT(m_callbacks, !is_seq(node) && !is_map(node));\n        _p(node)->m_val.scalar = val;\n        _add_flags(node, VAL|more_flags);\n    }\n    void _set_val(id_type node, NodeScalar const& val, type_bits more_flags=0)\n    {\n        _RYML_CB_ASSERT(m_callbacks, num_children(node) == 0);\n        _RYML_CB_ASSERT(m_callbacks,  ! is_container(node));\n        _p(node)->m_val = val;\n        _add_flags(node, VAL|more_flags);\n    }\n\n    void _set(id_type node, NodeInit const& i)\n    {\n        _RYML_CB_ASSERT(m_callbacks, i._check());\n        NodeData *n = _p(node);\n        _RYML_CB_ASSERT(m_callbacks, n->m_key.scalar.empty() || i.key.scalar.empty() || i.key.scalar == n->m_key.scalar);\n        _add_flags(node, i.type);\n        if(n->m_key.scalar.empty())\n        {\n            if( ! i.key.scalar.empty())\n            {\n                _set_key(node, i.key.scalar);\n            }\n        }\n        n->m_key.tag = i.key.tag;\n        n->m_val = i.val;\n    }\n\n    void _set_parent_as_container_if_needed(id_type in)\n    {\n        NodeData const* n = _p(in);\n        id_type ip = parent(in);\n        if(ip != NONE)\n        {\n            if( ! (is_seq(ip) || is_map(ip)))\n            {\n                if((in == first_child(ip)) && (in == last_child(ip)))\n                {\n                    if( ! n->m_key.empty() || has_key(in))\n                    {\n                        _add_flags(ip, MAP);\n                    }\n                    else\n                    {\n                        _add_flags(ip, SEQ);\n                    }\n                }\n            }\n        }\n    }\n\n    void _seq2map(id_type node)\n    {\n        _RYML_CB_ASSERT(m_callbacks, is_seq(node));\n        for(id_type i = first_child(node); i != NONE; i = next_sibling(i))\n        {\n            NodeData *C4_RESTRICT ch = _p(i);\n            if(ch->m_type.is_keyval())\n                continue;\n            ch->m_type.add(KEY);\n            ch->m_key = ch->m_val;\n        }\n        auto *C4_RESTRICT n = _p(node);\n        n->m_type.rem(SEQ);\n        n->m_type.add(MAP);\n    }\n\n    id_type _do_reorder(id_type *node, id_type count);\n\n    void _swap(id_type n_, id_type m_);\n    void _swap_props(id_type n_, id_type m_);\n    void _swap_hierarchy(id_type n_, id_type m_);\n    void _copy_hierarchy(id_type dst_, id_type src_);\n\n    inline void _copy_props(id_type dst_, id_type src_)\n    {\n        _copy_props(dst_, this, src_);\n    }\n\n    inline void _copy_props_wo_key(id_type dst_, id_type src_)\n    {\n        _copy_props_wo_key(dst_, this, src_);\n    }\n\n    void _copy_props(id_type dst_, Tree const* that_tree, id_type src_)\n    {\n        auto      & C4_RESTRICT dst = *_p(dst_);\n        auto const& C4_RESTRICT src = *that_tree->_p(src_);\n        dst.m_type = src.m_type;\n        dst.m_key  = src.m_key;\n        dst.m_val  = src.m_val;\n    }\n\n    void _copy_props(id_type dst_, Tree const* that_tree, id_type src_, type_bits src_mask)\n    {\n        auto      & C4_RESTRICT dst = *_p(dst_);\n        auto const& C4_RESTRICT src = *that_tree->_p(src_);\n        dst.m_type = (src.m_type & src_mask) | (dst.m_type & ~src_mask);\n        dst.m_key  = src.m_key;\n        dst.m_val  = src.m_val;\n    }\n\n    void _copy_props_wo_key(id_type dst_, Tree const* that_tree, id_type src_)\n    {\n        auto      & C4_RESTRICT dst = *_p(dst_);\n        auto const& C4_RESTRICT src = *that_tree->_p(src_);\n        dst.m_type = (src.m_type & ~_KEYMASK) | (dst.m_type & _KEYMASK);\n        dst.m_val  = src.m_val;\n    }\n\n    void _copy_props_wo_key(id_type dst_, Tree const* that_tree, id_type src_, type_bits src_mask)\n    {\n        auto      & C4_RESTRICT dst = *_p(dst_);\n        auto const& C4_RESTRICT src = *that_tree->_p(src_);\n        dst.m_type = (src.m_type & ((~_KEYMASK)|src_mask)) | (dst.m_type & (_KEYMASK|~src_mask));\n        dst.m_val  = src.m_val;\n    }\n\n    inline void _clear_type(id_type node)\n    {\n        _p(node)->m_type = NOTYPE;\n    }\n\n    inline void _clear(id_type node)\n    {\n        auto *C4_RESTRICT n = _p(node);\n        n->m_type = NOTYPE;\n        n->m_key.clear();\n        n->m_val.clear();\n        n->m_parent = NONE;\n        n->m_first_child = NONE;\n        n->m_last_child = NONE;\n    }\n\n    inline void _clear_key(id_type node)\n    {\n        _p(node)->m_key.clear();\n        _rem_flags(node, KEY);\n    }\n\n    inline void _clear_val(id_type node)\n    {\n        _p(node)->m_val.clear();\n        _rem_flags(node, VAL);\n    }\n\n    /** @endcond */\n\nprivate:\n\n    void _clear_range(id_type first, id_type num);\n\npublic:\n    id_type _claim();\nprivate:\n    void   _claim_root();\n    void   _release(id_type node);\n    void   _free_list_add(id_type node);\n    void   _free_list_rem(id_type node);\n\n    void _set_hierarchy(id_type node, id_type parent, id_type after_sibling);\n    void _rem_hierarchy(id_type node);\n\npublic:\n\n    // members are exposed, but you should NOT access them directly\n\n    NodeData *m_buf;\n    id_type   m_cap;\n\n    id_type m_size;\n\n    id_type m_free_head;\n    id_type m_free_tail;\n\n    substr m_arena;\n    size_t m_arena_pos;\n\n    Callbacks m_callbacks;\n\n    TagDirective m_tag_directives[RYML_MAX_TAG_DIRECTIVES];\n\n};\n\n/** @} */\n\n} // namespace yml\n} // namespace c4\n\n\nC4_SUPPRESS_WARNING_MSVC_POP\nC4_SUPPRESS_WARNING_GCC_CLANG_POP\n\n\n#endif /* _C4_YML_TREE_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/yml/version.cpp",
    "content": "#include \"c4/yml/version.hpp\"\n\nnamespace c4 {\nnamespace yml {\n\ncsubstr version()\n{\n  return RYML_VERSION;\n}\n\nint version_major()\n{\n  return RYML_VERSION_MAJOR;\n}\n\nint version_minor()\n{\n  return RYML_VERSION_MINOR;\n}\n\nint version_patch()\n{\n  return RYML_VERSION_PATCH;\n}\n\n} // namespace yml\n} // namespace c4\n"
  },
  {
    "path": "libs/rapidyaml/c4/yml/version.hpp",
    "content": "#ifndef _C4_YML_VERSION_HPP_\n#define _C4_YML_VERSION_HPP_\n\n/** @file version.hpp */\n\n#define RYML_VERSION \"0.7.2\"\n#define RYML_VERSION_MAJOR 0\n#define RYML_VERSION_MINOR 7\n#define RYML_VERSION_PATCH 2\n\n#include <c4/substr.hpp>\n#include <c4/yml/export.hpp>\n\nnamespace c4 {\nnamespace yml {\n\nRYML_EXPORT csubstr version();\nRYML_EXPORT int version_major();\nRYML_EXPORT int version_minor();\nRYML_EXPORT int version_patch();\n\n} // namespace yml\n} // namespace c4\n\n#endif /* _C4_YML_VERSION_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/yml/writer.hpp",
    "content": "#ifndef _C4_YML_WRITER_HPP_\n#define _C4_YML_WRITER_HPP_\n\n#ifndef _C4_YML_COMMON_HPP_\n#include \"./common.hpp\"\n#endif\n\n#include <c4/substr.hpp>\n#include <stdio.h>  // fwrite(), fputc()\n#include <string.h> // memcpy()\n\n\nnamespace c4 {\nnamespace yml {\n\n/** @addtogroup doc_emit\n * @{\n */\n\n/** @defgroup doc_writers Writer objects to use with an Emitter\n * @see Emitter\n * @{\n */\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n/** A writer that outputs to a file. Defaults to stdout. */\nstruct WriterFile\n{\n    FILE * m_file;\n    size_t m_pos;\n\n    WriterFile(FILE *f = nullptr) : m_file(f ? f : stdout), m_pos(0) {}\n\n    inline substr _get(bool /*error_on_excess*/)\n    {\n        substr sp;\n        sp.str = nullptr;\n        sp.len = m_pos;\n        return sp;\n    }\n\n    template<size_t N>\n    inline void _do_write(const char (&a)[N])\n    {\n        fwrite(a, sizeof(char), N - 1, m_file);\n        m_pos += N - 1;\n    }\n\n    inline void _do_write(csubstr sp)\n    {\n        #if defined(__clang__)\n        #   pragma clang diagnostic push\n        #   pragma GCC diagnostic ignored \"-Wsign-conversion\"\n        #elif defined(__GNUC__)\n        #   pragma GCC diagnostic push\n        #   pragma GCC diagnostic ignored \"-Wsign-conversion\"\n        #endif\n        if(sp.empty()) return;\n        fwrite(sp.str, sizeof(csubstr::char_type), sp.len, m_file);\n        m_pos += sp.len;\n        #if defined(__clang__)\n        #   pragma clang diagnostic pop\n        #elif defined(__GNUC__)\n        #   pragma GCC diagnostic pop\n        #endif\n    }\n\n    inline void _do_write(const char c)\n    {\n        fputc(c, m_file);\n        ++m_pos;\n    }\n\n    inline void _do_write(const char c, size_t num_times)\n    {\n        for(size_t i = 0; i < num_times; ++i)\n            fputc(c, m_file);\n        m_pos += num_times;\n    }\n};\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n/** A writer that outputs to an STL-like ostream. */\ntemplate<class OStream>\nstruct WriterOStream\n{\n    OStream& m_stream;\n    size_t   m_pos;\n\n    WriterOStream(OStream &s) : m_stream(s), m_pos(0) {}\n\n    inline substr _get(bool /*error_on_excess*/)\n    {\n        substr sp;\n        sp.str = nullptr;\n        sp.len = m_pos;\n        return sp;\n    }\n\n    template<size_t N>\n    inline void _do_write(const char (&a)[N])\n    {\n        m_stream.write(a, N - 1);\n        m_pos += N - 1;\n    }\n\n    inline void _do_write(csubstr sp)\n    {\n        #if defined(__clang__)\n        #   pragma clang diagnostic push\n        #   pragma GCC diagnostic ignored \"-Wsign-conversion\"\n        #elif defined(__GNUC__)\n        #   pragma GCC diagnostic push\n        #   pragma GCC diagnostic ignored \"-Wsign-conversion\"\n        #endif\n        if(sp.empty()) return;\n        m_stream.write(sp.str, sp.len);\n        m_pos += sp.len;\n        #if defined(__clang__)\n        #   pragma clang diagnostic pop\n        #elif defined(__GNUC__)\n        #   pragma GCC diagnostic pop\n        #endif\n    }\n\n    inline void _do_write(const char c)\n    {\n        m_stream.put(c);\n        ++m_pos;\n    }\n\n    inline void _do_write(const char c, size_t num_times)\n    {\n        for(size_t i = 0; i < num_times; ++i)\n            m_stream.put(c);\n        m_pos += num_times;\n    }\n};\n\n\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n//-----------------------------------------------------------------------------\n/** a writer to a substr */\nstruct WriterBuf\n{\n    substr m_buf;\n    size_t m_pos;\n\n    WriterBuf(substr sp) : m_buf(sp), m_pos(0) {}\n\n    inline substr _get(bool error_on_excess)\n    {\n        if(m_pos <= m_buf.len)\n        {\n            return m_buf.first(m_pos);\n        }\n        if(error_on_excess)\n        {\n            c4::yml::error(\"not enough space in the given buffer\");\n        }\n        substr sp;\n        sp.str = nullptr;\n        sp.len = m_pos;\n        return sp;\n    }\n\n    template<size_t N>\n    inline void _do_write(const char (&a)[N])\n    {\n        RYML_ASSERT( ! m_buf.overlaps(a));\n        if(m_pos + N-1 <= m_buf.len)\n        {\n            memcpy(&(m_buf[m_pos]), a, N-1);\n        }\n        m_pos += N-1;\n    }\n\n    inline void _do_write(csubstr sp)\n    {\n        if(sp.empty()) return;\n        RYML_ASSERT( ! sp.overlaps(m_buf));\n        if(m_pos + sp.len <= m_buf.len)\n        {\n            memcpy(&(m_buf[m_pos]), sp.str, sp.len);\n        }\n        m_pos += sp.len;\n    }\n\n    inline void _do_write(const char c)\n    {\n        if(m_pos + 1 <= m_buf.len)\n            m_buf[m_pos] = c;\n        ++m_pos;\n    }\n\n    inline void _do_write(const char c, size_t num_times)\n    {\n        if(m_pos + num_times <= m_buf.len)\n            for(size_t i = 0; i < num_times; ++i)\n                m_buf[m_pos + i] = c;\n        m_pos += num_times;\n    }\n};\n\n/** @ } */\n\n/** @ } */\n\n\n} // namespace yml\n} // namespace c4\n\n#endif /* _C4_YML_WRITER_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/c4/yml/yml.hpp",
    "content": "#ifndef _C4_YML_YML_HPP_\n#define _C4_YML_YML_HPP_\n\n#include \"c4/yml/version.hpp\"\n#include \"c4/yml/tree.hpp\"\n#include \"c4/yml/node.hpp\"\n#include \"c4/yml/emit.hpp\"\n#include \"c4/yml/event_handler_tree.hpp\"\n#include \"c4/yml/parse_engine.hpp\"\n#include \"c4/yml/filter_processor.hpp\"\n#include \"c4/yml/parse.hpp\"\n#include \"c4/yml/preprocess.hpp\"\n#include \"c4/yml/reference_resolver.hpp\"\n#include \"c4/yml/tag.hpp\"\n\n#endif // _C4_YML_YML_HPP_\n"
  },
  {
    "path": "libs/rapidyaml/ryml-gdbtypes.py",
    "content": "# To make this file known to Qt Creator using:\n# Tools > Options > Debugger > Locals & Expressions > Extra Debugging Helpers\n# Any contents here will be picked up by GDB, LLDB, and CDB based\n# debugging in Qt Creator automatically.\n\n\n# Example to display a simple type\n# template<typename U, typename V> struct MapNode\n# {\n#     U key;\n#     V data;\n# }\n#\n# def qdump__MapNode(d, value):\n#    d.putValue(\"This is the value column contents\")\n#    d.putExpandable()\n#    if d.isExpanded():\n#        with Children(d):\n#            # Compact simple case.\n#            d.putSubItem(\"key\", value[\"key\"])\n#            # Same effect, with more customization possibilities.\n#            with SubItem(d, \"data\")\n#                d.putItem(\"data\", value[\"data\"])\n\n# Check http://doc.qt.io/qtcreator/creator-debugging-helpers.html\n# for more details or look at qttypes.py, stdtypes.py, boosttypes.py\n# for more complex examples.\n\n# to try parsing:\n# env PYTHONPATH=/usr/share/qtcreator/debugger/ python src/ryml-gdbtypes.py\n\n\nimport dumper\n#from dumper import Dumper, Value, Children, SubItem\n#from dumper import SubItem, Children\nfrom dumper import *\n\nimport sys\nimport os\n\n\n# -----------------------------------------------------------------------------\n# -----------------------------------------------------------------------------\n# -----------------------------------------------------------------------------\n\n# QtCreator makes it really hard to figure out problems in this code.\n# So here are some debugging utilities.\n\n\n# FIXME. this decorator is not working; find out why.\ndef dbglog(func):\n    \"\"\"a decorator that logs entry and exit of functions\"\"\"\n    if not _DBG:\n        return func\n    def func_wrapper(*args, **kwargs):\n        _dbg_enter(func.__name__)\n        ret = func(*args, **kwargs)\n        _dbg_exit(func.__name__)\n        return ret\n    return func_wrapper\n\n\n_DBG = False\n_dbg_log = None\n_dbg_stack = 0\ndef _dbg(*args, **kwargs):\n    global _dbg_log, _dbg_stack\n    if not _DBG:\n        return\n    if _dbg_log is None:\n        filename = os.path.join(os.path.dirname(__file__), \"dbg.txt\")\n        _dbg_log = open(filename, \"w\")\n    kwargs['file'] = _dbg_log\n    kwargs['flush'] = True\n    print(\"  \" * _dbg_stack, *args, **kwargs)\n\n\ndef _dbg_enter(name):\n    global _dbg_stack\n    _dbg(name, \"- enter\")\n    _dbg_stack += 1\n\n\ndef _dbg_exit(name):\n    global _dbg_stack\n    _dbg_stack -= 1\n    _dbg(name, \"- exit!\")\n\n\n\n# -----------------------------------------------------------------------------\n# -----------------------------------------------------------------------------\n# -----------------------------------------------------------------------------\n\n\nNPOS = 18446744073709551615\nMAX_SUBSTR_LEN_DISPLAY = 80\nMAX_SUBSTR_LEN_EXPAND = 1000\n\n\ndef get_str_value(d, value, limit=0):\n    # adapted from dumper.py::Dumper::putCharArrayValue()\n    m_str = value[\"str\"].pointer()\n    m_len = value[\"len\"].integer()\n    if m_len == NPOS:\n        _dbg(\"getstr... 1\", m_len)\n        m_str = \"!!!!!<npos>!!!!!\"\n        m_len = len(m_str)\n        return m_str, m_len\n    if limit == 0:\n        limit = d.displayStringLimit\n    elided, shown = d.computeLimit(m_len, limit)\n    mem = bytes(d.readRawMemory(m_str, shown))\n    mem = mem.decode('utf8')\n    return mem, m_len\n\n\ndef __display_csubstr(d, value, limit=0):\n    m_str, m_len = get_str_value(d, value)\n    safe_len = min(m_len, MAX_SUBSTR_LEN_DISPLAY)\n    disp = m_str[0:safe_len]\n    # ensure the string escapes characters like \\n\\r\\t etc\n    disp = disp.encode('unicode_escape').decode('utf8')\n    # WATCHOUT. quotes in the string will make qtcreator hang!!!\n    disp = disp.replace('\"', '\\\\\"')\n    disp = disp.replace('\\'', '\\\\')\n    if m_len <= MAX_SUBSTR_LEN_DISPLAY:\n        d.putValue(f\"[{m_len}] '{disp}'\")\n    else:\n        d.putValue(f\"[{m_len}] '{disp}'...\")\n    return m_str, m_len\n\n\ndef qdump__c4__csubstr(d, value):\n    m_str, m_len = __display_csubstr(d, value)\n    d.putExpandable()\n    if d.isExpanded():\n        with Children(d):\n            safe_len = min(m_len, MAX_SUBSTR_LEN_EXPAND)\n            for i in range(safe_len):\n                ct = d.createType('char')\n                d.putSubItem(safe_len, d.createValue(value[\"str\"].pointer() + i, ct))\n            d.putSubItem(\"len\", value[\"len\"])\n            d.putPtrItem(\"str\", value[\"str\"].pointer())\n\n\ndef qdump__c4__substr(d, value):\n    qdump__c4__csubstr(d, value)\n\n\ndef qdump__c4__basic_substring(d, value):\n    qdump__c4__csubstr(d, value)\n\n\ndef qdump__c4__yml__NodeScalar(d, value):\n    alen = value[\"anchor\"][\"len\"].integer()\n    tlen = value[\"tag\"   ][\"len\"].integer()\n    m_str, m_len = get_str_value(d, value[\"scalar\"])\n    if alen == 0 and tlen == 0:\n        d.putValue(f'\\'{m_str}\\'')\n    elif alen == 0 and tlen > 0:\n        d.putValue(f'\\'{m_str}\\' [Ta]')\n    elif alen > 0 and tlen == 0:\n        d.putValue(f'\\'{m_str}\\' [tA]')\n    elif alen > 0 and tlen > 0:\n        d.putValue(f'\\'{m_str}\\' [TA]')\n    d.putExpandable()\n    if d.isExpanded():\n        with Children(d):\n            d.putSubItem(\"[scalar]\", value[\"scalar\"])\n            if tlen > 0:\n                d.putSubItem(\"[tag]\", value[\"tag\"])\n            if alen > 0:\n                d.putSubItem(\"[anchor or ref]\", value[\"anchor\"])\n\n\ndef _format_enum_value(int_value, enum_map):\n    str_value = enum_map.get(int_value, None)\n    display = f'{int_value}' if str_value is None else f'{str_value} ({int_value})'\n    return display\n\n\ndef _format_bitmask_value(int_value, enum_map):\n    str_value = enum_map.get(int_value, None)\n    if str_value:\n        return f'{str_value} ({int_value})'\n    else:\n        out = \"\"\n        orig = int_value\n        # do in reverse to get compound flags first\n        for k, v in reversed(enum_map.items()):\n            if (k != 0):\n                if (int_value & k) == k:\n                    if len(out) > 0:\n                        out += '|'\n                    out += v\n                    int_value &= ~k\n            else:\n                if len(out) == 0 and int_value == 0:\n                    return v\n        if out == \"\":\n            return f'{int_value}'\n        return f\"{out} ({orig})\"\n\n\ndef _c4bit(*ints):\n    ret = 0\n    for i in ints:\n        ret |= 1 << i\n    return ret\n\n\nnode_types = {\n    0: \"NOTYPE\",\n    _c4bit(0): \"VAL\"     ,\n    _c4bit(1): \"KEY\"     ,\n    _c4bit(2): \"MAP\"     ,\n    _c4bit(3): \"SEQ\"     ,\n    _c4bit(4): \"DOC\"     ,\n    _c4bit(5,3): \"STREAM\",\n    _c4bit(6): \"KEYREF\"  ,\n    _c4bit(7): \"VALREF\"  ,\n    _c4bit(8): \"KEYANCH\" ,\n    _c4bit(9): \"VALANCH\" ,\n    _c4bit(10): \"KEYTAG\" ,\n    _c4bit(11): \"VALTAG\" ,\n    _c4bit(12): \"VALQUO\" ,\n    _c4bit(13): \"KEYQUO\" ,\n    _c4bit(1,0): \"KEYVAL\",\n    _c4bit(1,3): \"KEYSEQ\",\n    _c4bit(1,2): \"KEYMAP\",\n    _c4bit(4,2): \"DOCMAP\",\n    _c4bit(4,3): \"DOCSEQ\",\n    _c4bit(4,0): \"DOCVAL\",\n    #\n    _c4bit(14): \"STYLE_FLOW_SL\",\n    _c4bit(15): \"STYLE_FLOW_ML\",\n    _c4bit(16): \"STYLE_BLOCK\",\n    #\n    _c4bit(17): \"KEY_LITERAL\",\n    _c4bit(18): \"VAL_LITERAL\",\n    _c4bit(19): \"KEY_FOLDED\",\n    _c4bit(20): \"VAL_FOLDED\",\n    _c4bit(21): \"KEY_SQUO\",\n    _c4bit(22): \"VAL_SQUO\",\n    _c4bit(23): \"KEY_DQUO\",\n    _c4bit(24): \"VAL_DQUO\",\n    _c4bit(25): \"KEY_PLAIN\",\n    _c4bit(26): \"VAL_PLAIN\",\n}\nnode_types_rev = {v: k for k, v in node_types.items()}\n\n\ndef _node_type_has_all(node_type_value, type_name):\n    exp = node_types_rev[type_name]\n    return (node_type_value & exp) == exp\n\n\ndef _node_type_has_any(node_type_value, type_name):\n    exp = node_types_rev[type_name]\n    return (node_type_value & exp) != 0\n\n\ndef qdump__c4__yml__NodeType_e(d, value):\n    v = _format_bitmask_value(value.integer(), node_types)\n    d.putValue(v)\n\n\ndef qdump__c4__yml__NodeType(d, value):\n    qdump__c4__yml__NodeType_e(d, value[\"type\"])\n\n\ndef qdump__c4__yml__NodeData(d, value):\n    d.putValue(\"wtf\")\n    ty = _format_bitmask_value(value.integer(), node_types)\n    t = value[\"m_type\"][\"type\"].integer()\n    k = value[\"m_key\"][\"scalar\"]\n    v = value[\"m_val\"][\"scalar\"]\n    sk, lk = get_str_value(d, k)\n    sv, lv = get_str_value(d, v)\n    if _node_type_has_all(t, \"KEYVAL\"):\n        d.putValue(f\"'{sk}': '{sv}'    {ty}\")\n    elif _node_type_has_any(t, \"KEY\"):\n        d.putValue(f\"'{sk}':    {ty}\")\n    elif _node_type_has_any(t, \"VAL\"):\n        d.putValue(f\"'{sv}'    {ty}\")\n    else:\n        d.putValue(f\"{ty}\")\n    d.putExpandable()\n    if d.isExpanded():\n        with Children(d):\n            d.putSubItem(\"m_type\", value[\"m_type\"])\n            # key\n            if _node_type_has_any(t, \"KEY\"):\n                d.putSubItem(\"m_key\", value[\"m_key\"])\n            if _node_type_has_any(t, \"KEYREF\"):\n                with SubItem(d, \"m_key.ref\"):\n                    s_, _ = get_str_value(d, value[\"m_key\"][\"anchor\"])\n                    d.putValue(f\"'{s_}'\")\n            if _node_type_has_any(t, \"KEYANCH\"):\n                with SubItem(d, \"m_key.anchor\"):\n                    s_, _ = get_str_value(d, value[\"m_key\"][\"anchor\"])\n                    d.putValue(f\"'{s_}'\")\n            if _node_type_has_any(t, \"KEYTAG\"):\n                with SubItem(d, \"m_key.tag\"):\n                    s_, _ = get_str_value(d, value[\"m_key\"][\"tag\"])\n                    d.putValue(f\"'{s_}'\")\n            # val\n            if _node_type_has_any(t, \"VAL\"):\n                d.putSubItem(\"m_val\", value[\"m_val\"])\n            if _node_type_has_any(t, \"VALREF\"):\n                with SubItem(d, \"m_val.ref\"):\n                    s_, _ = get_str_value(d, value[\"m_val\"][\"anchor\"])\n                    d.putValue(f\"'{s_}'\")\n            if _node_type_has_any(t, \"VALANCH\"):\n                with SubItem(d, \"m_val.anchor\"):\n                    s_, _ = get_str_value(d, value[\"m_val\"][\"anchor\"])\n                    d.putValue(f\"'{s_}'\")\n            if _node_type_has_any(t, \"VALTAG\"):\n                with SubItem(d, \"m_val.tag\"):\n                    s_, _ = get_str_value(d, value[\"m_val\"][\"tag\"])\n                    d.putValue(f\"'{s_}'\")\n            # hierarchy\n            _dump_node_index(d, \"m_parent\", value)\n            _dump_node_index(d, \"m_first_child\", value)\n            _dump_node_index(d, \"m_last_child\", value)\n            _dump_node_index(d, \"m_next_sibling\", value)\n            _dump_node_index(d, \"m_prev_sibling\", value)\n\n\ndef _dump_node_index(d, name, value):\n    if int(value[name].integer()) == NPOS:\n        pass\n        #with SubItem(d, name):\n        #    d.putValue(\"-\")\n    else:\n        d.putSubItem(name, value[name])\n\n\n# c4::yml::Tree\ndef qdump__c4__yml__Tree(d, value):\n    m_size = value[\"m_size\"].integer()\n    m_cap = value[\"m_cap\"].integer()\n    d.putExpandable()\n    if d.isExpanded():\n        #d.putArrayData(value[\"m_buf\"], m_size, value[\"m_buf\"].dereference())\n        with Children(d):\n            with SubItem(d, f\"[nodes]\"):\n                d.putItemCount(m_size)\n                d.putArrayData(value[\"m_buf\"].pointer(), m_size, value[\"m_buf\"].type.dereference())\n            d.putPtrItem(\"m_buf\", value[\"m_buf\"].pointer())\n            d.putIntItem(\"m_size\", value[\"m_size\"])\n            d.putIntItem(\"m_cap (capacity)\", value[\"m_cap\"])\n            d.putIntItem(\"[slack]\", m_cap - m_size)\n            d.putIntItem(\"m_free_head\", value[\"m_free_head\"])\n            d.putIntItem(\"m_free_tail\", value[\"m_free_tail\"])\n            d.putSubItem(\"m_arena\", value[\"m_arena\"])\n\n\ndef qdump__c4__yml__detail__stack(d, value):\n    T = value.type[0]\n    N = value.type[0]\n    m_size = value[\"m_size\"].integer()\n    m_capacity = value[\"m_capacity\"].integer()\n    d.putItemCount(m_size)\n    if d.isExpanded():\n        with Children(d):\n            with SubItem(d, f\"[nodes]\"):\n                d.putItemCount(m_size)\n                d.putArrayData(value[\"m_stack\"].pointer(), m_size, T)\n            d.putIntItem(\"m_size\", value[\"m_size\"])\n            d.putIntItem(\"m_capacity\", value[\"m_capacity\"])\n            #d.putIntItem(\"[small capacity]\", N)\n            d.putIntItem(\"[is large]\", value[\"m_buf\"].address() == value[\"m_stack\"].pointer())\n            d.putPtrItem(\"m_stack\", value[\"m_stack\"].pointer())\n            d.putPtrItem(\"m_buf\", value[\"m_buf\"].address())\n\n\ndef qdump__c4__yml__detail__ReferenceResolver__refdata(d, value):\n    node = value[\"node\"].integer()\n    ty = _format_bitmask_value(value[\"type\"].integer(), node_types)\n    d.putValue(f'{node}   {ty}')\n    d.putExpandable()\n    if d.isExpanded():\n        with Children(d):\n            d.putSubItem(\"type\", value[\"type\"])\n            d.putSubItem(\"node\", value[\"node\"])\n            _dump_node_index(d, \"prev_anchor\", value)\n            _dump_node_index(d, \"target\", value)\n            _dump_node_index(d, \"parent_ref\", value)\n            _dump_node_index(d, \"parent_ref_sibling\", value)\n"
  },
  {
    "path": "libs/rapidyaml/ryml.hpp",
    "content": "#ifndef _RYML_HPP_\n#define _RYML_HPP_\n\n#include \"c4/yml/yml.hpp\"\n\nnamespace ryml {\nusing namespace c4::yml;\nusing namespace c4;\n}\n\n#endif /* _RYML_HPP_ */\n"
  },
  {
    "path": "libs/rapidyaml/ryml.natvis",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?> \n\n<!--\nVery good intro:\n@see https://docs.microsoft.com/en-us/visualstudio/debugger/create-custom-views-of-native-objects?view=vs-2017\n@see https://code.msdn.microsoft.com/windowsdesktop/Writing-type-visualizers-2eae77a2\nSee also:\n@see http://blogs.msdn.com/b/vcblog/archive/2013/06/28/using-visual-studio-2013-to-write-maintainable-native-visualizations-natvis.aspx?PageIndex=2\n@see http://blogs.msdn.com/b/vcblog/archive/2015/09/28/debug-visualizers-in-visual-c-2015.aspx\n@see http://stackoverflow.com/questions/36883414/limit-display-of-char-in-natvis-file-to-specific-length\n-->\n\n<AutoVisualizer xmlns=\"http://schemas.microsoft.com/vstudio/debugger/natvis/2010\">\n\n  <Type Name=\"c4::yml::NodeScalar\">\n    <DisplayString Condition=\"(tag.len == 0) &amp;&amp; (anchor.len == 0)\">{scalar.str,[scalar.len]}</DisplayString>\n    <DisplayString Condition=\"(tag.len >  0) &amp;&amp; (anchor.len == 0)\">{scalar.str,[scalar.len]} [T]</DisplayString>\n    <DisplayString Condition=\"(tag.len == 0) &amp;&amp; (anchor.len >  0)\">{scalar.str,[scalar.len]} [A]</DisplayString>\n    <DisplayString Condition=\"(tag.len >  0) &amp;&amp; (anchor.len >  0)\">{scalar.str,[scalar.len]} [T][A]</DisplayString>\n    <Expand>\n      <Item Name=\"scalar\">scalar</Item>\n      <Item Name=\"tag\">tag</Item>\n      <Item Name=\"anchor\">anchor</Item>\n    </Expand>\n  </Type>\n\n  <Type Name=\"c4::yml::NodeType\">\n    <DisplayString Condition=\"((type &amp; c4::yml::KEY  ) == c4::yml::KEY) &amp;&amp; ((type &amp; c4::yml::VAL) == c4::yml::VAL)\">[KEYVAL]</DisplayString>\n    <DisplayString Condition=\"((type &amp; c4::yml::KEY  ) == c4::yml::KEY) &amp;&amp; ((type &amp; c4::yml::SEQ) == c4::yml::SEQ)\">[KEYSEQ]</DisplayString>\n    <DisplayString Condition=\"((type &amp; c4::yml::KEY  ) == c4::yml::KEY) &amp;&amp; ((type &amp; c4::yml::MAP) == c4::yml::MAP)\">[KEYMAP]</DisplayString>\n    <DisplayString Condition=\"((type &amp; c4::yml::DOC  ) == c4::yml::DOC) &amp;&amp; ((type &amp; c4::yml::VAL) == c4::yml::VAL)\">[DOCVAL]</DisplayString>\n    <DisplayString Condition=\"((type &amp; c4::yml::DOC  ) == c4::yml::DOC) &amp;&amp; ((type &amp; c4::yml::SEQ) == c4::yml::SEQ)\">[DOCSEQ]</DisplayString>\n    <DisplayString Condition=\"((type &amp; c4::yml::DOC  ) == c4::yml::DOC) &amp;&amp; ((type &amp; c4::yml::MAP) == c4::yml::MAP)\">[DOCMAP]</DisplayString>\n    <DisplayString Condition=\"(type &amp; c4::yml::VAL   ) == c4::yml::VAL\"   >[VAL]</DisplayString>\n    <DisplayString Condition=\"(type &amp; c4::yml::KEY   ) == c4::yml::KEY\"   >[KEY]</DisplayString>\n    <DisplayString Condition=\"(type &amp; c4::yml::SEQ   ) == c4::yml::SEQ\"   >[SEQ]</DisplayString>\n    <DisplayString Condition=\"(type &amp; c4::yml::MAP   ) == c4::yml::MAP\"   >[MAP]</DisplayString>\n    <DisplayString Condition=\"(type &amp; c4::yml::DOC   ) == c4::yml::DOC\"   >[DOC]</DisplayString>\n    <DisplayString Condition=\"(type &amp; c4::yml::STREAM) == c4::yml::STREAM\">[STREAM]</DisplayString>\n    <DisplayString Condition=\"(type &amp; c4::yml::NOTYPE) == c4::yml::NOTYPE\">[NOTYPE]</DisplayString>\n    <Expand>\n      <Synthetic Name=\"[type bits]\">\n        <Expand>\n          <Item Name=\"[0]\" Condition=\"(type &amp; c4::yml::KEY) != 0\">c4::yml::KEY</Item>\n          <Item Name=\"[1]\" Condition=\"(type &amp; c4::yml::VAL) != 0\">c4::yml::VAL</Item>\n          <Item Name=\"[2]\" Condition=\"(type &amp; c4::yml::MAP) != 0\">c4::yml::MAP</Item>\n          <Item Name=\"[3]\" Condition=\"(type &amp; c4::yml::SEQ) != 0\">c4::yml::SEQ</Item>\n          <Item Name=\"[4]\" Condition=\"(type &amp; c4::yml::DOC) != 0\">c4::yml::DOC</Item>\n          <Item Name=\"[5]\" Condition=\"(type &amp; c4::yml::STREAM) != 0\">c4::yml::STREAM</Item>\n          <Item Name=\"[6]\" Condition=\"(type &amp; c4::yml::KEYREF) != 0\">c4::yml::KEYREF</Item>\n          <Item Name=\"[7]\" Condition=\"(type &amp; c4::yml::VALREF) != 0\">c4::yml::VALREF</Item>\n          <Item Name=\"[8]\" Condition=\"(type &amp; c4::yml::KEYANCH) != 0\">c4::yml::KEYANCH</Item>\n          <Item Name=\"[9]\" Condition=\"(type &amp; c4::yml::VALANCH) != 0\">c4::yml::VALANCH</Item>\n          <Item Name=\"[10]\" Condition=\"(type &amp; c4::yml::KEYTAG) != 0\">c4::yml::KEYTAG</Item>\n          <Item Name=\"[11]\" Condition=\"(type &amp; c4::yml::VALTAG) != 0\">c4::yml::VALTAG</Item>\n        </Expand>\n      </Synthetic>\n      <Synthetic Name=\"[style bits]\">\n        <Expand>\n          <Item Name=\"[0]\" Condition=\"(type &amp; c4::yml::_WIP_KEY_UNFILT) != 0\">c4::yml::_WIP_KEY_UNFILT</Item>\n          <Item Name=\"[1]\" Condition=\"(type &amp; c4::yml::_WIP_VAL_UNFILT) != 0\">c4::yml::_WIP_VAL_UNFILT</Item>\n          <Item Name=\"[2]\" Condition=\"(type &amp; c4::yml::_WIP_STYLE_FLOW_SL) != 0\">c4::yml::_WIP_STYLE_FLOW</Item>\n          <Item Name=\"[3]\" Condition=\"(type &amp; c4::yml::_WIP_STYLE_FLOW_ML) != 0\">c4::yml::_WIP_STYLE_FLOW</Item>\n          <Item Name=\"[4]\" Condition=\"(type &amp; c4::yml::_WIP_STYLE_BLOCK) != 0\">c4::yml::_WIP_STYLE_BLOCK</Item>\n          <Item Name=\"[5]\" Condition=\"(type &amp; c4::yml::_WIP_KEY_LITERAL) != 0\">c4::yml::_WIP_KEY_LITERAL</Item>\n          <Item Name=\"[6]\" Condition=\"(type &amp; c4::yml::_WIP_VAL_LITERAL) != 0\">c4::yml::_WIP_VAL_LITERAL</Item>\n          <Item Name=\"[7]\" Condition=\"(type &amp; c4::yml::_WIP_KEY_FOLDED) != 0\">c4::yml::_WIP_KEY_FOLDED</Item>\n          <Item Name=\"[8]\" Condition=\"(type &amp; c4::yml::_WIP_VAL_FOLDED) != 0\">c4::yml::_WIP_VAL_FOLDED</Item>\n          <Item Name=\"[9]\" Condition=\"(type &amp; c4::yml::_WIP_KEY_SQUO) != 0\">c4::yml::_WIP_KEY_SQUO</Item>\n          <Item Name=\"[10]\" Condition=\"(type &amp; c4::yml::_WIP_VAL_SQUO) != 0\">c4::yml::_WIP_VAL_SQUO</Item>\n          <Item Name=\"[11]\" Condition=\"(type &amp; c4::yml::_WIP_KEY_DQUO) != 0\">c4::yml::_WIP_KEY_DQUO</Item>\n          <Item Name=\"[12]\" Condition=\"(type &amp; c4::yml::_WIP_VAL_DQUO) != 0\">c4::yml::_WIP_VAL_DQUO</Item>\n          <Item Name=\"[13]\" Condition=\"(type &amp; c4::yml::_WIP_KEY_PLAIN) != 0\">c4::yml::_WIP_KEY_PLAIN</Item>\n          <Item Name=\"[14]\" Condition=\"(type &amp; c4::yml::_WIP_VAL_PLAIN) != 0\">c4::yml::_WIP_VAL_PLAIN</Item>\n        </Expand>\n      </Synthetic>\n    </Expand>\n  </Type>\n\n  <Type Name=\"c4::yml::NodeData\">\n    <DisplayString Condition=\"((m_type.type &amp; c4::yml::KEY  ) == c4::yml::KEY) &amp;&amp; ((m_type.type &amp; c4::yml::VAL) == c4::yml::VAL)\">[KEYVAL] {m_key.scalar.str,[m_key.scalar.len]}: {m_val.scalar.str,[m_val.scalar.len]}</DisplayString>\n    <DisplayString Condition=\"((m_type.type &amp; c4::yml::KEY  ) == c4::yml::KEY) &amp;&amp; ((m_type.type &amp; c4::yml::SEQ) == c4::yml::SEQ)\">[KEYSEQ] {m_key.scalar.str,[m_key.scalar.len]}</DisplayString>\n    <DisplayString Condition=\"((m_type.type &amp; c4::yml::KEY  ) == c4::yml::KEY) &amp;&amp; ((m_type.type &amp; c4::yml::MAP) == c4::yml::MAP)\">[KEYMAP] {m_key.scalar.str,[m_key.scalar.len]}</DisplayString>\n    <DisplayString Condition=\"((m_type.type &amp; c4::yml::DOC  ) == c4::yml::DOC) &amp;&amp; ((m_type.type &amp; c4::yml::SEQ) == c4::yml::SEQ)\">[DOCSEQ]</DisplayString>\n    <DisplayString Condition=\"((m_type.type &amp; c4::yml::DOC  ) == c4::yml::DOC) &amp;&amp; ((m_type.type &amp; c4::yml::MAP) == c4::yml::MAP)\">[DOCMAP]</DisplayString>\n    <DisplayString Condition=\"(m_type.type &amp; c4::yml::VAL   ) == c4::yml::VAL\"   >[VAL] {m_val.scalar.str,[m_val.scalar.len]}</DisplayString>\n    <DisplayString Condition=\"(m_type.type &amp; c4::yml::KEY   ) == c4::yml::KEY\"   >[KEY] {m_key.scalar.str,[m_key.scalar.len]}</DisplayString>\n    <DisplayString Condition=\"(m_type.type &amp; c4::yml::SEQ   ) == c4::yml::SEQ\"   >[SEQ]</DisplayString>\n    <DisplayString Condition=\"(m_type.type &amp; c4::yml::MAP   ) == c4::yml::MAP\"   >[MAP]</DisplayString>\n    <DisplayString Condition=\"(m_type.type &amp; c4::yml::DOC   ) == c4::yml::DOC\"   >[DOC]</DisplayString>\n    <DisplayString Condition=\"(m_type.type &amp; c4::yml::STREAM) == c4::yml::STREAM\">[STREAM]</DisplayString>\n    <DisplayString Condition=\"(m_type.type &amp; c4::yml::NOTYPE) == c4::yml::NOTYPE\">[NOTYPE]</DisplayString>\n    <Expand>\n      <Item Name=\"type\">m_type</Item>\n      <Item Name=\"key\" Condition=\"(m_type.type &amp; c4::yml::KEY) != 0\">m_key</Item>\n      <Item Name=\"val\" Condition=\"(m_type.type &amp; c4::yml::VAL) != 0\">m_val</Item>\n      <Item Name=\"key quoted\" Condition=\"((m_type.type &amp; c4::yml::KEY) != 0) &amp;&amp; ((m_type.type &amp; c4::yml::KEYQUO) != 0)\">c4::yml::KEYQUO</Item>\n      <Item Name=\"val quoted\" Condition=\"((m_type.type &amp; c4::yml::VAL) != 0) &amp;&amp; ((m_type.type &amp; c4::yml::VALQUO) != 0)\">c4::yml::VALQUO</Item>\n      <Item Name=\"key ref\" Condition=\"(m_type.type &amp; c4::yml::KEYREF) != 0\">m_key.anchor</Item>\n      <Item Name=\"val ref\" Condition=\"(m_type.type &amp; c4::yml::VALREF) != 0\">m_val.anchor</Item>\n      <Item Name=\"key anchor\" Condition=\"(m_type.type &amp; c4::yml::KEYANCH) != 0\">m_key.anchor</Item>\n      <Item Name=\"val anchor\" Condition=\"(m_type.type &amp; c4::yml::VALANCH) != 0\">m_val.anchor</Item>\n      <Item Name=\"parent\" Condition=\"m_parent == c4::yml::NONE\">NONE</Item>\n      <Item Name=\"parent\" Condition=\"m_parent != c4::yml::NONE\">m_parent</Item>\n      <Item Name=\"first child\"  Condition=\"m_first_child != c4::yml::NONE\">m_first_child</Item>\n      <Item Name=\"last child\"   Condition=\"m_last_child != c4::yml::NONE\">m_last_child</Item>\n      <Item Name=\"prev sibling\" Condition=\"m_prev_sibling != c4::yml::NONE\">m_prev_sibling</Item>\n      <Item Name=\"next sibling\" Condition=\"m_next_sibling != c4::yml::NONE\">m_next_sibling</Item>\n    </Expand>\n  </Type>\n\n  <Type Name=\"c4::yml::Tree\">\n    <DisplayString>sz={m_size}, cap={m_cap}</DisplayString>\n    <Expand>\n      <Item Name=\"[size]\">m_size</Item>\n      <Item Name=\"[capacity]\">m_cap</Item>\n      <Synthetic Name=\"[buffer]\">\n        <Expand>\n          <ArrayItems>\n            <Size>m_cap</Size>\n            <ValuePointer>m_buf</ValuePointer>\n          </ArrayItems>\n        </Expand>\n      </Synthetic>\n      <Item Name=\"free head\">m_free_head</Item>\n      <Item Name=\"arena\">m_arena</Item>\n    </Expand>\n  </Type>\n\n  <Type Name=\"c4::yml::Tree::_lookup_path_token\">\n    <DisplayString>{value} ({type})</DisplayString>\n    <Expand>\n      <Item Name=\"value\">value</Item>\n      <Item Name=\"type\">type</Item>\n    </Expand>\n  </Type>\n\n  <Type Name=\"c4::yml::Tree::lookup_result\">\n    <DisplayString>{path} -- target={target} closest={closest}</DisplayString>\n    <Expand>\n      <Item Name=\"target\">target</Item>\n      <Item Name=\"closest\">closest</Item>\n      <Item Name=\"path_pos\">path_pos</Item>\n      <Item Name=\"path\">path</Item>\n      <Synthetic Name=\"[resolved]\">\n        <DisplayString>{path.str,[path_pos]}</DisplayString>\n      </Synthetic>\n      <Synthetic Name=\"[unresolved]\">\n        <DisplayString>{path.str+path_pos,[path.len-path_pos]}</DisplayString>\n      </Synthetic>\n    </Expand>\n  </Type>\n\n  <Type Name=\"c4::yml::NodeRef\">\n    <DisplayString Condition=\"(m_id == c4::yml::NONE)\">(void)</DisplayString>\n    <DisplayString Condition=\"(m_seed.len != c4::yml::NONE) &amp;&amp; (m_seed.str == nullptr)\">[INDEX SEED for] {*(m_tree->m_buf + m_id)}</DisplayString>\n    <DisplayString Condition=\"(m_seed.len != c4::yml::NONE) &amp;&amp; (m_seed.str != nullptr)\">[NAMED SEED for] {*(m_tree->m_buf + m_id)}</DisplayString>\n    <DisplayString>{*(m_tree->m_buf + m_id)}</DisplayString>\n    <Expand>\n      <Item Name=\"id\">m_id</Item>\n      <Item Name=\"element\">*(m_tree->m_buf + m_id)</Item>\n      <Item Name=\"tree\">m_tree</Item>\n      <Synthetic Name=\"[children]\" Condition=\"(m_id != c4::yml::NONE) &amp;&amp; (((m_tree->m_buf + m_id)->m_type.type &amp; (c4::yml::MAP|c4::yml::SEQ)) != 0)\">\n        <Expand>\n          <CustomListItems>\n            <Variable Name=\"tree\" InitialValue=\"m_tree\"/>\n            <Variable Name=\"buf\" InitialValue=\"m_tree->m_buf\"/>\n            <Variable Name=\"curr\" InitialValue=\"(m_tree->m_buf + m_id)->m_first_child\"/>\n            <Loop>\n              <Item>buf + curr</Item>\n              <Exec>curr = (buf + curr)->m_next_sibling</Exec>\n              <Break Condition=\"curr == c4::yml::NONE\"/>\n            </Loop>\n          </CustomListItems>\n        </Expand>\n      </Synthetic>\n    </Expand>\n  </Type>\n\n  <Type Name=\"c4::yml::ConstNodeRef\">\n    <DisplayString Condition=\"(m_id == c4::yml::NONE)\">(void)</DisplayString>\n    <DisplayString>{*(m_tree->m_buf + m_id)}</DisplayString>\n    <Expand>\n      <Item Name=\"id\">m_id</Item>\n      <Item Name=\"element\">*(m_tree->m_buf + m_id)</Item>\n      <Item Name=\"tree\">m_tree</Item>\n      <Synthetic Name=\"[children]\" Condition=\"(m_id != c4::yml::NONE) &amp;&amp; (((m_tree->m_buf + m_id)->m_type.type &amp; (c4::yml::MAP|c4::yml::SEQ)) != 0)\">\n        <Expand>\n          <CustomListItems>\n            <Variable Name=\"tree\" InitialValue=\"m_tree\"/>\n            <Variable Name=\"buf\" InitialValue=\"m_tree->m_buf\"/>\n            <Variable Name=\"curr\" InitialValue=\"(m_tree->m_buf + m_id)->m_first_child\"/>\n            <Loop>\n              <Item>buf + curr</Item>\n              <Exec>curr = (buf + curr)->m_next_sibling</Exec>\n              <Break Condition=\"curr == c4::yml::NONE\"/>\n            </Loop>\n          </CustomListItems>\n        </Expand>\n      </Synthetic>\n    </Expand>\n  </Type>\n\n  <Type Name=\"c4::yml::detail::ReferenceResolver\">\n    <DisplayString>#refs={refs.m_size} #nodes={t->m_size}</DisplayString>\n    <Expand>\n      <Synthetic Name=\"[ref_nodes]\">\n        <Expand>\n          <CustomListItems>\n            <Variable Name=\"curr\" InitialValue=\"0\"/>\n            <Loop>\n              <Item>t->m_buf + (refs.m_stack + curr)->node</Item>\n              <Exec>curr = curr+1</Exec>\n              <Break Condition=\"curr >= refs.m_size\"/>\n            </Loop>\n          </CustomListItems>\n        </Expand>\n      </Synthetic>\n      <Synthetic Name=\"[refs]\">\n        <Expand>\n          <ArrayItems>\n            <Size>refs.m_size</Size>\n            <ValuePointer>refs.m_stack</ValuePointer>\n          </ArrayItems>\n        </Expand>\n      </Synthetic>\n      <Item Name=\"[tree]\">t</Item>\n    </Expand>\n  </Type>\n\n  <Type Name=\"c4::yml::detail::stack&lt;*,*&gt;\">\n    <DisplayString>sz={m_size} cap={m_capacity}</DisplayString>\n    <Expand>\n      <Item Name=\"[size]\">m_size</Item>\n      <Item Name=\"[capacity]\">m_capacity</Item>\n      <Item Name=\"[is small]\">m_buf == m_stack</Item>\n      <Synthetic Name=\"[items]\">\n        <Expand>\n          <ArrayItems>\n            <Size>m_size</Size>\n            <ValuePointer>m_stack</ValuePointer>\n          </ArrayItems>\n        </Expand>\n      </Synthetic>\n    </Expand>\n  </Type>\n\n  <Type Name=\"c4::yml::detail::FilterProcessorSrcDst\">\n    <DisplayString>src={src.str,[rpos]} dst={dst.str,[wpos]}</DisplayString>\n    <Expand>\n      <Item Name=\"[src]\">src</Item>\n      <Item Name=\"[dst]\">dst</Item>\n      <Item Name=\"[rpos]\">rpos</Item>\n      <Item Name=\"[wpos]\">wpos</Item>\n      <Synthetic Name=\"[read]\">\n        <StringView>src.str,[rpos]</StringView>\n        <Expand>\n          <ArrayItems>\n            <Size>rpos</Size>\n            <ValuePointer>src.str</ValuePointer>\n          </ArrayItems>\n        </Expand>\n      </Synthetic>\n    </Expand>\n  </Type>\n\n  <Type Name=\"c4::yml::detail::FilterProcessorInplace\">\n    <DisplayString>src={src.str,[rpos]} dst={src.str,[wpos]}</DisplayString>\n    <Expand>\n      <Item Name=\"[rpos]\">rpos</Item>\n      <Item Name=\"[wpos]\">wpos</Item>\n      <Item Name=\"[wcap]\">wcap</Item>\n      <Synthetic Name=\"[buf]\">\n        <StringView>src.str,[wcap]</StringView>\n        <Expand>\n          <ArrayItems>\n            <Size>wcap</Size>\n            <ValuePointer>src.str</ValuePointer>\n          </ArrayItems>\n        </Expand>\n      </Synthetic>\n      <Item Name=\"[src]\">src</Item>\n      <Synthetic Name=\"[to be read]\">\n        <StringView>src.str+rpos,[src.len-rpos]</StringView>\n        <Expand>\n          <ArrayItems><Size>src.len-rpos</Size><ValuePointer>src.str+rpos</ValuePointer></ArrayItems>\n        </Expand>\n      </Synthetic>\n      <Synthetic Name=\"[read]\">\n        <StringView>src.str,[rpos]</StringView>\n        <Expand>\n          <ArrayItems><Size>rpos</Size><ValuePointer>src.str</ValuePointer></ArrayItems>\n        </Expand>\n      </Synthetic>\n      <Synthetic Name=\"[written]\">\n        <StringView>src.str,[wpos]</StringView>\n        <Expand>\n          <ArrayItems><Size>wpos</Size><ValuePointer>src.str</ValuePointer></ArrayItems>\n        </Expand>\n      </Synthetic>\n    </Expand>\n  </Type>\n\n</AutoVisualizer>\n"
  },
  {
    "path": "libs/rapidyaml/ryml_std.hpp",
    "content": "#ifndef _RYML_STD_HPP_\n#define _RYML_STD_HPP_\n\n#include \"./c4/yml/std/std.hpp\"\n\n#endif /* _RYML_STD_HPP_ */\n"
  },
  {
    "path": "obj/.gitkeep",
    "content": ""
  },
  {
    "path": "res/linux/openxcom.desktop",
    "content": "[Desktop Entry]\nVersion=1.0\nType=Application\nName=OpenXcom\nComment=Open-source clone of UFO: Enemy Unknown\nExec=openxcom\nTerminal=false\nIcon=openxcom\nCategories=Game;StrategyGame;\n"
  },
  {
    "path": "res/windows/openxcom.manifest",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">\n   <trustInfo xmlns=\"urn:schemas-microsoft-com:asm.v2\">\n      <security>\n         <requestedPrivileges>\n            <requestedExecutionLevel level=\"asInvoker\" uiAccess=\"false\" />\n         </requestedPrivileges>\n      </security>\n   </trustInfo>\n   <application xmlns=\"urn:schemas-microsoft-com:asm.v3\">\n      <windowsSettings>\n         <dpiAware xmlns=\"http://schemas.microsoft.com/SMI/2005/WindowsSettings\">True/PM</dpiAware>\n\t\t <dpiAwareness xmlns=\"http://schemas.microsoft.com/SMI/2016/WindowsSettings\">PerMonitorV2, PerMonitor</dpiAwareness>\n      </windowsSettings>\n   </application>\n</assembly>"
  },
  {
    "path": "scripts/build-openxcom",
    "content": "#!/usr/bin/env bash\n# By Morgan Hardwood\n# Version 2018-12-04\n# This script gets the latest source code for the given program and compiles it.\n\n# The name of the program, used for the folder names:\nprog=\"openxcom\"\n\n# The name of the compiled executable:\nexe=\"${prog}\"\n\n# The name of the sub-folder, if any, relative to the folder into which the\n# compiled executable is placed.\n# e.g. If the executable ends up in:\n#   ~/programs/someProgram/foo/bar/someExecutable\n# then set it to:\n#   exeRelativePath=\"foo/bar\"\n# or if the executable ends up in\n#   ~/programs/someProgram/someExecutable\n# then leave it empty:\n# exeRelativePath=\"\"\nexeRelativePath=\"\"\n\n# The path to the repository:\nrepo=\"https://github.com/OpenXcom/OpenXcom.git\"\n\n# No touching below this line, with the exception of the \"Compile\" section\n# -----------------------------------------------------------------------------\n\n# The name of the project's standard branch, typically \"master\":\nmaster=\"master\"\n\nbuildOnly=\"false\"\nbuildType=\"release\"\n\n# Removes the trailing forward-slash if one is present\nexeRelativePath=\"${exeRelativePath/%\\/}\"\n# Append forward-slash to exeRelativePath only if it is not empty.\nexePath=\"${exeRelativePath:+${exeRelativePath}/}${exe}\"\n\n# Command-line arguments\nwhile getopts \"bdh?-\" opt; do\n    case \"${opt}\" in\n        b)  buildOnly=\"true\"\n            ;;\n        d)  buildType=\"debug\"\n            ;;\n        h|\\?|-) printf '%s\\n' \"This script gets the latest source code for ${prog} and compiles it.\" \\\n                \"\" \\\n                \"  -b\" \\\n                \"     Optional. If specified, the script only compiles the source, it does not try to update the source. If not specified, the source will be updated first.\" \\\n                \"  -d\" \\\n                \"     Optional. Compile a \\\"debug\\\" build. If not specified, a \\\"release\\\" build will be made.\" \\\n                \"\"\n        exit 0\n        ;;\n    esac\ndone\nshift $((OPTIND-1))\n[ \"$1\" = \"--\" ] && shift\n\nprintf '%s\\n' \"\" \"Program name: ${prog}\" \"Build type: ${buildType}\" \"Build without updating: ${buildOnly}\" \"\"\n\n# Clone if needed\ncloned=\"false\"\nupdates=\"false\"\nif [[ ! -d \"$HOME/programs/code-${prog}\" ]]; then\n    mkdir -p \"$HOME/programs\" || exit 1\n    git clone \"$repo\" \"$HOME/programs/code-${prog}\" || exit 1\n    pushd \"$HOME/programs/code-${prog}\" 1>/dev/null || exit 1\n    cloned=\"true\"\nelse\n    pushd \"$HOME/programs/code-${prog}\" 1>/dev/null || exit 1\n    git fetch\n    if [[ $(git rev-parse HEAD) != $(git rev-parse '@{u}') ]]; then\n        updates=\"true\"\n    fi\nfi\n\n# Pull updates if necessary\nif [[ \"$updates\" = \"true\" && \"$buildOnly\" = \"false\" ]]; then\n    git pull || exit 1\nfi\n\n# Find out which branch git is on\nbranch=\"$(git rev-parse --abbrev-ref HEAD)\"\n\n# Set build and install folder names\nif [[ $branch = $master && $buildType = release ]]; then\n    buildDir=\"$HOME/programs/code-${prog}/build\"\n    installDir=\"$HOME/programs/${prog}\"\nelse\n    buildDir=\"$HOME/programs/code-${prog}/build-${branch}-${buildType}\"\n    installDir=\"$HOME/programs/${prog}-${branch}-${buildType}\"\nfi\n\nexistsExe=\"false\"\nif [[ -e \"${installDir}/${exePath}\" ]]; then\n    existsExe=\"true\"\nfi\n\n# Quit if no updates and build-only flag not set\nif [[ \"$cloned\" = \"false\" && \"$buildOnly\" = \"false\" && \"$updates\" = \"false\" && \"$existsExe\" = \"true\" ]]; then\n    printf '%s\\n' \"No updates, nothing to do.\"\n    exit 0\nfi\n\n# Determine CPU count\ncpuCount=\"fail\"\nif command -v nproc >/dev/null 2>&1; then\n    cpuCount=\"$(nproc --all)\"\nfi\nif [[ ! ( $cpuCount -ge 1 && $cpuCount -le 64 ) ]]; then\n    cpuCount=1\nfi\n\n# Prepare folders\nrm -rf \"${installDir}\"\nmkdir -p \"${buildDir}\" \"${installDir}\" || exit 1\ncd \"${buildDir}\" || exit 1\n\n# -----------------------------------------------------------------------------\n# Compile\n\n# See:\n# http://rawpedia.rawtherapee.com/Linux#Compile_RawTherapee\n\ncmake \\\n    -DCMAKE_INSTALL_BINDIR:STRING=\"${installDir}\" \\\n    -DCMAKE_INSTALL_PREFIX:STRING=\"${installDir}\" \\\n    -DCMAKE_BUILD_TYPE=\"$buildType\"  \\\n    \"$HOME/programs/code-${prog}\" || exit 1\n\nmake --jobs=\"$cpuCount\" install || exit 1\nmake install || exit 1\n\n# Finished\n\nprintf '%s\\n' \"\" \\\n    \"OpenXcom requires resources from the original UFO: Enemy Unknown or Terror from the Deep.\" \\\n    \"\" \\\n    \"Installation:\" \\\n    \"    1. Copy the following folders from the original, unpatched games\" \\\n    \"        UFO: Enemy Unknown or Terror from the Deep\" \\\n    \"        to ~/.local/share/openxcom/UFO/\" \\\n    \"        GEODATA, GEOGRAPH, MAPS, ROUTES, SOUND, TERRAIN, UFOGRAPH, UFOINTRO and UNITS\" \\\n    \"        (folders are case-sensitive)\" \\\n    \"\" \\\n    \"    2. Overwrite those folders with the ones from the 'OpenXcom UFO Patch':\" \\\n    \"        https://openxcom.org/downloads-extras/\"\n\nprintf '%s\\n' \"\" \"To run ${prog} type:\" \"${installDir}/${exePath}\" \"\"\n\npopd 1>/dev/null\n"
  },
  {
    "path": "scripts/git-bash-helpers.sh",
    "content": "#!/bin/bash\n\nif [[ -z \"$1\" ]];\nthen\n  echo \"alias prefix required\"\n  exit 1;\nfi;\n\ngit config alias.$1-clean '!'\"f() { (git diff --quiet --cached --exit-code || (echo 'not commited changes'; false)) && (git diff --quiet --exit-code || (echo 'working dir dirty'; false)); }; f\"\ngit config alias.$1-version-bump '!'\"f() { vim -T dumb --noplugin -n -c 'silent! %s/\\\\(\\\"Extended \\\\d\\\\+[.,]\\\\d\\\\+\\\\)\\\"/\\\\=submatch(1).\\\".0\\\\\\\"\\\"/g' -c '%s/\\\\%\\\\(#define MIN_REQUIRED_RULESET_VERSION_NUMBER\\\\)\\\\@<!\\\\([\\\" ]\\\\d\\\\+[.,]\\\\d\\\\+[.,]\\\\)\\\\(\\\\d\\\\+\\\\)/\\\\=submatch(1).eval(submatch(2)+1)/g' -c '%s/(v\\\\d\\\\d\\\\d\\\\d-\\\\d\\\\d-\\\\d\\\\d)/\\\\=\\\"(v\\\".strftime(\\\"%Y-%m-%d\\\").\\\")\\\"/g' -c ':wq' src/version.h && git add src/version.h; }; f\"\ngit config alias.$1-version-bump-commit '!'\"f() { git $1-clean && git $1-version-bump && git commit --no-edit -m \\\"OXCE \\$(grep -oP '(?<=Extended )\\\\d+\\\\.\\\\d+(\\\\.\\\\d+)?' src/version.h)\\\"; }; f\"\ngit config alias.$1-version-set '!'\"f() { ([[ \\$# -eq 2 ]] || (echo 'wrong args num'; false)) && vim -T dumb --noplugin -n -c '%s/\\\\%\\\\(#define MIN_REQUIRED_RULESET_VERSION_NUMBER \\\\)\\\\@<!\\\\d\\\\+[.,]\\\\d\\\\+\\\\([.,]\\\\)\\\\d\\\\+/\\\\=\\\"'\\$1'\\\".submatch(1).\\\"'\\$2'\\\".submatch(1).\\\"0\\\"/g' -c '%s/(v\\\\d\\\\d\\\\d\\\\d-\\\\d\\\\d-\\\\d\\\\d)/\\\\=\\\"(v\\\".strftime(\\\"%Y-%m-%d\\\").\\\")\\\"/g' -c ':wq' src/version.h && git add src/version.h && git $1-version-common-set \\\"\\$@\\\" 0; }; f\"\ngit config alias.$1-version-set-commit '!'\"f() { git $1-clean && git $1-version-set \\\"\\$@\\\" && git commit --no-edit -m \\\"OXCE v\\$1.\\$2\\\"; }; f\"\ngit config alias.$1-version-common-set '!'\"f() { ([[ \\$# -eq 3 ]] || (echo 'wrong args num'; false)) && vim -T dumb --noplugin -n -c '%s/\\\\%\\\\(#define MIN_REQUIRED_RULESET_VERSION_NUMBER \\\\)\\\\@<=\\\\d\\\\+,\\\\d\\\\+,\\\\d\\\\+,\\\\d\\\\+/\\\\=\\\"'\\$1','\\$2','\\$3',0\\\"/g' -c ':wq' src/version.h && git add src/version.h && vim -T dumb --noplugin -n -c 'argdo %s/\\\\%\\\\(version: \\\\)\\\\@<=\\\\(\\\\d\\\\+.\\\\d\\\\+.\\\\d\\\\+\\\\)/\\\\=\\\"'\\$1'.'\\$2'.'\\$3'\\\"/g | update' -c 'qa' bin/common/dont-touch.me bin/standard/xcom1/metadata.yml bin/standard/xcom2/metadata.yml && git add -f bin/common/dont-touch.me bin/standard/xcom1/metadata.yml bin/standard/xcom2/metadata.yml && git add src/version.h; }; f\"\n"
  },
  {
    "path": "scripts/init-build-server.sh",
    "content": "#!/bin/bash\n\n\napt install git zip\ncd /opt\ngit clone https://github.com/mxe/mxe.git;\nsudo chown -R `whoami`: mxe\ncd mxe;\nsudo apt update\nsudo apt-get install \\\n    autoconf \\\n    automake \\\n    autopoint \\\n    bash \\\n    bison \\\n    bzip2 \\\n    flex \\\n    g++ \\\n    g++-multilib \\\n    gettext \\\n    git \\\n    gperf \\\n    intltool \\\n    libc6-dev-i386 \\\n    libgdk-pixbuf2.0-dev \\\n    libltdl-dev \\\n    libgl-dev \\\n    libssl-dev \\\n    libtool-bin \\\n    libxml-parser-perl \\\n    lzip \\\n    make \\\n    openssl \\\n    p7zip-full \\\n    patch \\\n    perl \\\n    python3 \\\n    python3-mako \\\n    python3-pkg-resources \\\n    python-is-python3 \\\n    ruby \\\n    sed \\\n    unzip \\\n    wget \\\n    xz-utils;\nmake MXE_TARGETS=\"x86_64-w64-mingw32.static i686-w64-mingw32.static\" JOBS=8 sdl sdl_gfx sdl_mixer sdl_image\nmake MXE_TARGETS=\"x86_64-w64-mingw32.static i686-w64-mingw32.static\" MXE_PLUGIN_DIRS=plugins/gcc14 JOBS=8 gcc\n\ncd ..\ngit clone https://github.com/MeridianOXC/OpenXcom.git\ncd OpenXcom\nrm deps/dummy.txt\nrmdir deps\n\n\n#windows build\nmkdir -p build/win64\ncd build/win64\nexport PATH=/opt/mxe/usr/bin:$PATH\n/opt/mxe/usr/bin/x86_64-w64-mingw32.static-cmake -DCMAKE_BUILD_TYPE=Release -DDEV_BUILD=OFF -DBUILD_PACKAGE=OFF -B. -S../..\nmake -j8\ncd -\n\n\n#linux build\n\nmkdir -p build/linux\ncd build/linux\ncmake -DCMAKE_BUILD_TYPE=Release -DDEV_BUILD=OFF -DBUILD_PACKAGE=OFF -B. -S../..\nmake -j8\ncd -\n"
  },
  {
    "path": "scripts/macports-config.yml",
    "content": "version: '2.11.5'\nprefix: /opt/local\nvariants:\n  select:\n    - universal\nports:\n  - name: libsdl\n    select:\n      - compat\n  - name: libsdl_gfx\n  - name: libsdl_image\n  - name: libsdl_mixer\n"
  },
  {
    "path": "src/Basescape/BaseInfoState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"BaseInfoState.h\"\n#include <sstream>\n#include <cmath>\n#include \"../Engine/Game.h\"\n#include \"../Engine/Action.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/Bar.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextEdit.h\"\n#include \"../Engine/Surface.h\"\n#include \"MiniBaseView.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Base.h\"\n#include \"MonthlyCostsState.h\"\n#include \"TransfersState.h\"\n#include \"StoresState.h\"\n#include \"BasescapeState.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Base Info screen.\n * @param game Pointer to the core game.\n * @param base Pointer to the base to get info from.\n * @param state Pointer to the Basescape state.\n */\nBaseInfoState::BaseInfoState(Base *base, BasescapeState *state) : _base(base), _state(state)\n{\n\t// Create objects\n\t_bg = new Surface(320, 200, 0, 0);\n\t_mini = new MiniBaseView(128, 16, 182, 8);\n\t_btnOk = new TextButton(30, 14, 10, 180);\n\t_btnTransfers = new TextButton(80, 14, 46, 180);\n\t_btnStores = new TextButton(80, 14, 132, 180);\n\t_btnMonthlyCosts = new TextButton(92, 14, 218, 180);\n\t_edtBase = new TextEdit(this, 127, 16, 8, 8);\n\n\t_txtPersonnel = new Text(300, 9, 8, 30);\n\t_txtSoldiers = new Text(114, 9, 8, 41);\n\t_numSoldiers = new Text(40, 9, 126, 41);\n\t_barSoldiers = new Bar(150, 5, 166, 43);\n\t_txtEngineers = new Text(114, 9, 8, 51);\n\t_numEngineers = new Text(40, 9, 126, 51);\n\t_barEngineers = new Bar(150, 5, 166, 53);\n\t_txtScientists = new Text(114, 9, 8, 61);\n\t_numScientists = new Text(40, 9, 126, 61);\n\t_barScientists = new Bar(150, 5, 166, 63);\n\n\t_txtSpace = new Text(300, 9, 8, 72);\n\t_txtQuarters = new Text(114, 9, 8, 83);\n\t_numQuarters = new Text(40, 9, 126, 83);\n\t_barQuarters = new Bar(150, 5, 166, 85);\n\t_txtStores = new Text(114, 9, 8, 93);\n\t_numStores = new Text(40, 9, 126, 93);\n\t_barStores = new Bar(150, 5, 166, 95);\n\t_txtLaboratories = new Text(114, 9, 8, 103);\n\t_numLaboratories = new Text(40, 9, 126, 103);\n\t_barLaboratories = new Bar(150, 5, 166, 105);\n\t_txtWorkshops = new Text(114, 9, 8, 113);\n\t_numWorkshops = new Text(40, 9, 126, 113);\n\t_barWorkshops = new Bar(150, 5, 166, 115);\n\tif (Options::storageLimitsEnforced)\n\t{\n\t\t_txtContainment = new Text(114, 9, 8, 123);\n\t\t_numContainment = new Text(40, 9, 126, 123);\n\t\t_barContainment = new Bar(150, 5, 166, 125);\n\t}\n\t_txtHangars = new Text(114, 9, 8, Options::storageLimitsEnforced ? 133 : 123);\n\t_numHangars = new Text(40, 9, 126, Options::storageLimitsEnforced ? 133 : 123);\n\t_barHangars = new Bar(150, 5, 166, Options::storageLimitsEnforced ? 135 : 125);\n\n\t_txtDefense = new Text(114, 9, 8, Options::storageLimitsEnforced ? 147 : 138);\n\t_numDefense = new Text(40, 9, 126, Options::storageLimitsEnforced ? 147 : 138);\n\t_barDefense = new Bar(150, 5, 166, Options::storageLimitsEnforced ? 149 : 140);\n\t_txtShortRange = new Text(114, 9, 8, Options::storageLimitsEnforced ? 157 : 153);\n\t_numShortRange = new Text(40, 9, 126, Options::storageLimitsEnforced ? 157 : 153);\n\t_barShortRange = new Bar(150, 5, 166, Options::storageLimitsEnforced ? 159 : 155);\n\t_txtLongRange = new Text(114, 9, 8, Options::storageLimitsEnforced ? 167 : 163);\n\t_numLongRange = new Text(40, 9, 126, Options::storageLimitsEnforced ? 167 : 163);\n\t_barLongRange = new Bar(150, 5, 166, Options::storageLimitsEnforced ? 169 : 165);\n\n\t// Set palette\n\tsetInterface(\"baseInfo\");\n\n\tadd(_bg);\n\tadd(_mini, \"miniBase\", \"basescape\");\n\tadd(_btnOk, \"button\", \"baseInfo\");\n\tadd(_btnTransfers, \"button\", \"baseInfo\");\n\tadd(_btnStores, \"button\", \"baseInfo\");\n\tadd(_btnMonthlyCosts, \"button\", \"baseInfo\");\n\tadd(_edtBase, \"text1\", \"baseInfo\");\n\n\tadd(_txtPersonnel, \"text1\", \"baseInfo\");\n\tadd(_txtSoldiers, \"text2\", \"baseInfo\");\n\tadd(_numSoldiers, \"numbers\", \"baseInfo\");\n\tadd(_barSoldiers, \"personnelBars\", \"baseInfo\");\n\tadd(_txtEngineers, \"text2\", \"baseInfo\");\n\tadd(_numEngineers, \"numbers\", \"baseInfo\");\n\tadd(_barEngineers, \"personnelBars\", \"baseInfo\");\n\tadd(_txtScientists, \"text2\", \"baseInfo\");\n\tadd(_numScientists, \"numbers\", \"baseInfo\");\n\tadd(_barScientists, \"personnelBars\", \"baseInfo\");\n\n\tadd(_txtSpace, \"text1\", \"baseInfo\");\n\tadd(_txtQuarters, \"text2\", \"baseInfo\");\n\tadd(_numQuarters, \"numbers\", \"baseInfo\");\n\tadd(_barQuarters, \"facilityBars\", \"baseInfo\");\n\tadd(_txtStores, \"text2\", \"baseInfo\");\n\tadd(_numStores, \"numbers\", \"baseInfo\");\n\tadd(_barStores, \"facilityBars\", \"baseInfo\");\n\tadd(_txtLaboratories, \"text2\", \"baseInfo\");\n\tadd(_numLaboratories, \"numbers\", \"baseInfo\");\n\tadd(_barLaboratories, \"facilityBars\", \"baseInfo\");\n\tadd(_txtWorkshops, \"text2\", \"baseInfo\");\n\tadd(_numWorkshops, \"numbers\", \"baseInfo\");\n\tadd(_barWorkshops, \"facilityBars\", \"baseInfo\");\n\tif (Options::storageLimitsEnforced)\n\t{\n\t\tadd(_txtContainment, \"text2\", \"baseInfo\");\n\t\tadd(_numContainment, \"numbers\", \"baseInfo\");\n\t\tadd(_barContainment, \"facilityBars\", \"baseInfo\");\n\t}\n\tadd(_txtHangars, \"text2\", \"baseInfo\");\n\tadd(_numHangars, \"numbers\", \"baseInfo\");\n\tadd(_barHangars, \"facilityBars\", \"baseInfo\");\n\n\tadd(_txtDefense, \"text2\", \"baseInfo\");\n\tadd(_numDefense, \"numbers\", \"baseInfo\");\n\tadd(_barDefense, \"defenceBar\", \"baseInfo\");\n\tadd(_txtShortRange, \"text2\", \"baseInfo\");\n\tadd(_numShortRange, \"numbers\", \"baseInfo\");\n\tadd(_barShortRange, \"detectionBars\", \"baseInfo\");\n\tadd(_txtLongRange, \"text2\", \"baseInfo\");\n\tadd(_numLongRange, \"numbers\", \"baseInfo\");\n\tadd(_barLongRange, \"detectionBars\", \"baseInfo\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tstd::ostringstream ss;\n\tif (Options::storageLimitsEnforced)\n\t{\n\t\tss << \"ALT\";\n\t}\n\tss << \"BACK07.SCR\";\n\t_game->getMod()->getSurface(ss.str())->blitNShade(_bg, 0, 0);\n\n\t_mini->setTexture(_game->getMod()->getSurfaceSet(\"BASEBITS.PCK\"));\n\t_mini->setBases(_game->getSavedGame()->getBases());\n\tfor (size_t i = 0; i < _game->getSavedGame()->getBases()->size(); ++i)\n\t{\n\t\tif (_game->getSavedGame()->getBases()->at(i) == _base)\n\t\t{\n\t\t\t_mini->setSelectedBase(i);\n\t\t\tbreak;\n\t\t}\n\t}\n\t_mini->onMouseClick((ActionHandler)&BaseInfoState::miniClick);\n\t_mini->onKeyboardPress((ActionHandler)&BaseInfoState::handleKeyPress);\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&BaseInfoState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&BaseInfoState::btnOkClick, Options::keyCancel);\n\n\t_btnTransfers->setText(tr(\"STR_TRANSFERS_UC\"));\n\t_btnTransfers->onMouseClick((ActionHandler)&BaseInfoState::btnTransfersClick);\n\n\t_btnStores->setText(tr(\"STR_STORES_UC\"));\n\t_btnStores->onMouseClick((ActionHandler)&BaseInfoState::btnStoresClick);\n\n\t_btnMonthlyCosts->setText(tr(\"STR_MONTHLY_COSTS\"));\n\t_btnMonthlyCosts->onMouseClick((ActionHandler)&BaseInfoState::btnMonthlyCostsClick);\n\n\t_edtBase->setBig();\n\t_edtBase->onChange((ActionHandler)&BaseInfoState::edtBaseChange);\n\n\t_txtPersonnel->setText(tr(\"STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL\"));\n\n\t_txtSoldiers->setText(tr(\"STR_SOLDIERS\"));\n\n\t_barSoldiers->setScale(1.0);\n\n\t_txtEngineers->setText(tr(\"STR_ENGINEERS\"));\n\n\t_barEngineers->setScale(1.0);\n\n\t_txtScientists->setText(tr(\"STR_SCIENTISTS\"));\n\n\t_barScientists->setScale(1.0);\n\n\n\t_txtSpace->setText(tr(\"STR_SPACE_USED_SPACE_AVAILABLE\"));\n\n\t_txtQuarters->setText(tr(\"STR_LIVING_QUARTERS_PLURAL\"));\n\n\t_barQuarters->setScale(0.5);\n\n\t_txtStores->setText(tr(\"STR_STORES\"));\n\n\t_barStores->setScale(0.5);\n\n\t_txtLaboratories->setText(tr(\"STR_LABORATORIES\"));\n\n\t_barLaboratories->setScale(0.5);\n\n\t_txtWorkshops->setText(tr(\"STR_WORK_SHOPS\"));\n\n\t_barWorkshops->setScale(0.5);\n\n\tif (Options::storageLimitsEnforced)\n\t{\n\t\t_txtContainment->setText(tr(\"STR_ALIEN_CONTAINMENT\"));\n\n\t\t_barContainment->setScale(0.5);\n\t}\n\n\t_txtHangars->setText(tr(\"STR_HANGARS\"));\n\n\t_barHangars->setScale(18.0);\n\n\n\t_txtDefense->setText(tr(\"STR_DEFENSE_STRENGTH\"));\n\n\t_barDefense->setScale(0.125);\n\n\t_txtShortRange->setText(tr(\"STR_SHORT_RANGE_DETECTION\"));\n\n\t_barShortRange->setScale(25.0);\n\n\t_txtLongRange->setText(tr(\"STR_LONG_RANGE_DETECTION\"));\n\n\t_barLongRange->setScale(25.0);\n}\n\n/**\n *\n */\nBaseInfoState::~BaseInfoState()\n{\n\n}\n\n/**\n * The player can change the selected base.\n */\nvoid BaseInfoState::init()\n{\n\tState::init();\n\t_edtBase->setText(_base->getName());\n\n\tstd::ostringstream ss;\n\tss << _base->getAvailableSoldiers() << \":\" << _base->getTotalSoldiers();\n\t_numSoldiers->setText(ss.str());\n\n\tif (!Options::oxceBaseInfoScaleEnabled || _base->getTotalSoldiers() * _barSoldiers->getScale() < MAX_BAR_WIDTH)\n\t{\n\t\t_barSoldiers->setMax(_base->getTotalSoldiers());\n\t\t_barSoldiers->setValue(_base->getAvailableSoldiers());\n\t}\n\telse\n\t{\n\t\t_barSoldiers->setMax(MAX_BAR_WIDTH);\n\t\t_barSoldiers->setValue(_base->getAvailableSoldiers() * MAX_BAR_WIDTH / _base->getTotalSoldiers());\n\t}\n\n\tstd::ostringstream ss2;\n\tss2 << _base->getAvailableEngineers() << \":\" << _base->getTotalEngineers();\n\t_numEngineers->setText(ss2.str());\n\n\tif (!Options::oxceBaseInfoScaleEnabled || _base->getTotalEngineers() * _barEngineers->getScale() < MAX_BAR_WIDTH)\n\t{\n\t\t_barEngineers->setMax(_base->getTotalEngineers());\n\t\t_barEngineers->setValue(_base->getAvailableEngineers());\n\t}\n\telse\n\t{\n\t\t_barEngineers->setMax(MAX_BAR_WIDTH);\n\t\t_barEngineers->setValue(_base->getAvailableEngineers() * MAX_BAR_WIDTH / _base->getTotalEngineers());\n\t}\n\n\tstd::ostringstream ss3;\n\tss3 << _base->getAvailableScientists() << \":\" << _base->getTotalScientists();\n\t_numScientists->setText(ss3.str());\n\n\tif (!Options::oxceBaseInfoScaleEnabled || _base->getTotalScientists() * _barScientists->getScale() < MAX_BAR_WIDTH)\n\t{\n\t\t_barScientists->setMax(_base->getTotalScientists());\n\t\t_barScientists->setValue(_base->getAvailableScientists());\n\t}\n\telse\n\t{\n\t\t_barScientists->setMax(MAX_BAR_WIDTH);\n\t\t_barScientists->setValue(_base->getAvailableScientists() * MAX_BAR_WIDTH / _base->getTotalScientists());\n\t}\n\n\n\tstd::ostringstream ss4;\n\tss4 << _base->getUsedQuarters() << \":\" << _base->getAvailableQuarters();\n\t_numQuarters->setText(ss4.str());\n\n\tif (!Options::oxceBaseInfoScaleEnabled || _base->getAvailableQuarters() * _barQuarters->getScale() < MAX_BAR_WIDTH)\n\t{\n\t\t_barQuarters->setMax(_base->getAvailableQuarters());\n\t\t_barQuarters->setValue(_base->getUsedQuarters());\n\t}\n\telse\n\t{\n\t\t_barQuarters->setMax(MAX_BAR_WIDTH);\n\t\t_barQuarters->setValue(_base->getUsedQuarters() * MAX_BAR_WIDTH / _base->getAvailableQuarters());\n\t\t_barQuarters->setScale(1.0);\n\t}\n\n\tstd::ostringstream ss5;\n\tss5 << (int)floor(_base->getUsedStores() + 0.05) << \":\" << _base->getAvailableStores();\n\t_numStores->setText(ss5.str());\n\n\tif (!Options::oxceBaseInfoScaleEnabled || _base->getAvailableStores() * _barStores->getScale() < MAX_BAR_WIDTH)\n\t{\n\t\t_barStores->setMax(_base->getAvailableStores());\n\t\t_barStores->setValue((int)floor(_base->getUsedStores() + 0.05));\n\t}\n\telse\n\t{\n\t\t_barStores->setMax(MAX_BAR_WIDTH);\n\t\t_barStores->setValue(((int)floor(_base->getUsedStores() + 0.05)) * MAX_BAR_WIDTH / _base->getAvailableStores());\n\t\t_barStores->setScale(1.0);\n\t}\n\n\tstd::ostringstream ss6;\n\tss6 << _base->getUsedLaboratories() << \":\" << _base->getAvailableLaboratories();\n\t_numLaboratories->setText(ss6.str());\n\n\tif (!Options::oxceBaseInfoScaleEnabled || _base->getAvailableLaboratories() * _barLaboratories->getScale() < MAX_BAR_WIDTH)\n\t{\n\t\t_barLaboratories->setMax(_base->getAvailableLaboratories());\n\t\t_barLaboratories->setValue(_base->getUsedLaboratories());\n\t}\n\telse\n\t{\n\t\t_barLaboratories->setMax(MAX_BAR_WIDTH);\n\t\t_barLaboratories->setValue(_base->getUsedLaboratories() * MAX_BAR_WIDTH / _base->getAvailableLaboratories());\n\t\t_barLaboratories->setScale(1.0);\n\t}\n\n\tstd::ostringstream ss7;\n\tss7 << _base->getUsedWorkshops() << \":\" << _base->getAvailableWorkshops();\n\t_numWorkshops->setText(ss7.str());\n\n\tif (!Options::oxceBaseInfoScaleEnabled || _base->getAvailableWorkshops() * _barWorkshops->getScale() < MAX_BAR_WIDTH)\n\t{\n\t\t_barWorkshops->setMax(_base->getAvailableWorkshops());\n\t\t_barWorkshops->setValue(_base->getUsedWorkshops());\n\t}\n\telse\n\t{\n\t\t_barWorkshops->setMax(MAX_BAR_WIDTH);\n\t\t_barWorkshops->setValue(_base->getUsedWorkshops() * MAX_BAR_WIDTH / _base->getAvailableWorkshops());\n\t\t_barWorkshops->setScale(1.0);\n\t}\n\n\tif (Options::storageLimitsEnforced)\n\t{\n\t\tstd::ostringstream ss72;\n\t\tss72 << _base->getUsedContainment(0) << \":\" << _base->getAvailableContainment(0);\n\t\t_numContainment->setText(ss72.str());\n\n\t\t_barContainment->setMax(_base->getAvailableContainment(0));\n\t\t_barContainment->setValue(_base->getUsedContainment(0));\n\t}\n\n\tstd::ostringstream ss8;\n\tss8 << _base->getUsedHangars() << \":\" << _base->getAvailableHangars();\n\t_numHangars->setText(ss8.str());\n\n\t_barHangars->setMax(_base->getAvailableHangars());\n\t_barHangars->setValue(_base->getUsedHangars());\n\n\n\tstd::ostringstream ss9;\n\tss9 << _base->getDefenseValue();\n\t_numDefense->setText(ss9.str());\n\n\t_barDefense->setMax(_base->getDefenseValue());\n\t_barDefense->setValue(_base->getDefenseValue());\n\tif (Options::oxceBaseInfoDefenseScaleMultiplier != 100)\n\t{\n\t\t_barDefense->setScale(0.125 * Options::oxceBaseInfoDefenseScaleMultiplier / 100.0);\n\t}\n\n\tstd::ostringstream ss10;\n\tint shortRangeDetection = _base->getShortRangeDetection();\n\tss10 << shortRangeDetection;\n\t_numShortRange->setText(ss10.str());\n\n\t_barShortRange->setMax(shortRangeDetection);\n\t_barShortRange->setValue(shortRangeDetection);\n\n\tstd::ostringstream ss11;\n\tint longRangeDetection = _base->getLongRangeDetection();\n\tss11 << longRangeDetection;\n\t_numLongRange->setText(ss11.str());\n\n\t_barLongRange->setMax(longRangeDetection);\n\t_barLongRange->setValue(longRangeDetection);\n}\n\n/**\n * Changes the base name.\n * @param action Pointer to an action.\n */\nvoid BaseInfoState::edtBaseChange(Action *)\n{\n\t_base->setName(_edtBase->getText());\n}\n\n/**\n * Selects a new base to display.\n * @param action Pointer to an action.\n */\nvoid BaseInfoState::miniClick(Action *)\n{\n\tsize_t base = _mini->getHoveredBase();\n\tif (base < _game->getSavedGame()->getBases()->size())\n\t{\n\t\t_mini->setSelectedBase(base);\n\t\t_base = _game->getSavedGame()->getBases()->at(base);\n\t\t_state->setBase(_base);\n\t\tinit();\n\t}\n}\n\n/**\n * Selects a new base to display.\n * @param action Pointer to an action.\n */\nvoid BaseInfoState::handleKeyPress(Action *action)\n{\n\tif (action->getDetails()->type == SDL_KEYDOWN)\n\t{\n\t\tSDLKey baseKeys[] = {\n\t\t\tOptions::keyBaseSelect1,\n\t\t\tOptions::keyBaseSelect2,\n\t\t\tOptions::keyBaseSelect3,\n\t\t\tOptions::keyBaseSelect4,\n\t\t\tOptions::keyBaseSelect5,\n\t\t\tOptions::keyBaseSelect6,\n\t\t\tOptions::keyBaseSelect7,\n\t\t\tOptions::keyBaseSelect8\n\t\t};\n\t\tint key = action->getDetails()->key.keysym.sym;\n\t\tfor (size_t i = 0; i < _game->getSavedGame()->getBases()->size(); ++i)\n\t\t{\n\t\t\tif (key == baseKeys[i])\n\t\t\t{\n\t\t\t\t_mini->setSelectedBase(i);\n\t\t\t\t_base = _game->getSavedGame()->getBases()->at(i);\n\t\t\t\t_state->setBase(_base);\n\t\t\t\tinit();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid BaseInfoState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Goes to the Transfers window.\n * @param action Pointer to an action.\n */\nvoid BaseInfoState::btnTransfersClick(Action *)\n{\n\t_game->pushState(new TransfersState(_base));\n}\n\n/**\n * Goes to the Stores screen.\n * @param action Pointer to an action.\n */\nvoid BaseInfoState::btnStoresClick(Action *)\n{\n\t_game->pushState(new StoresState(_base));\n}\n\n/**\n * Goes to the Monthly Costs screen.\n * @param action Pointer to an action.\n */\nvoid BaseInfoState::btnMonthlyCostsClick(Action *)\n{\n\t_game->pushState(new MonthlyCostsState(_base));\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/BaseInfoState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass BasescapeState;\nclass Base;\nclass Surface;\nclass MiniBaseView;\nclass TextButton;\nclass TextEdit;\nclass Text;\nclass Bar;\n\n/**\n * Base Info screen that shows all the\n * stats of a base from the Basescape.\n */\nclass BaseInfoState : public State\n{\nprivate:\n\tstatic const int MAX_BAR_WIDTH = 140;\n\n\tBase *_base;\n\tBasescapeState *_state;\n\n\tSurface *_bg;\n\tMiniBaseView *_mini;\n\tTextButton *_btnOk, *_btnTransfers, *_btnStores, *_btnMonthlyCosts;\n\tTextEdit *_edtBase;\n\n\tText *_txtPersonnel, *_txtSoldiers, *_txtEngineers, *_txtScientists;\n\tText *_numSoldiers, *_numEngineers, *_numScientists;\n\tBar *_barSoldiers, *_barEngineers, *_barScientists;\n\n\tText *_txtSpace, *_txtQuarters, *_txtStores, *_txtLaboratories, *_txtWorkshops, *_txtContainment, *_txtHangars;\n\tText *_numQuarters, *_numStores, *_numLaboratories, *_numWorkshops, *_numContainment, *_numHangars;\n\tBar *_barQuarters, *_barStores, *_barLaboratories, *_barWorkshops, *_barContainment, *_barHangars;\n\n\tText *_txtDefense, *_txtShortRange, *_txtLongRange;\n\tText *_numDefense, *_numShortRange, *_numLongRange;\n\tBar *_barDefense, *_barShortRange, *_barLongRange;\npublic:\n\t/// Creates the Base Info state.\n\tBaseInfoState(Base *base, BasescapeState *state);\n\t/// Cleans up the Base Info state.\n\t~BaseInfoState();\n\t/// Updates the base stats.\n\tvoid init() override;\n\t/// Handler for changing the text on the Name edit.\n\tvoid edtBaseChange(Action *action);\n\t/// Handler for clicking the mini base view.\n\tvoid miniClick(Action *action);\n\t/// Handler for selecting bases.\n\tvoid handleKeyPress(Action *action);\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the Transfers button.\n\tvoid btnTransfersClick(Action *action);\n\t/// Handler for clicking the Stores button.\n\tvoid btnStoresClick(Action *action);\n\t/// Handler for clicking the Monthly Costs button.\n\tvoid btnMonthlyCostsClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/BaseView.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"BaseView.h\"\n#include <algorithm>\n#include <sstream>\n#include <cmath>\n#include \"../Engine/SurfaceSet.h\"\n#include \"../Engine/Action.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/BaseFacility.h\"\n#include \"../Mod/RuleBaseFacility.h\"\n#include \"../Savegame/Craft.h\"\n#include \"../Interface/Text.h\"\n#include \"../Engine/Timer.h\"\n#include \"../Engine/Options.h\"\n#include <climits>\n#include \"../Mod/Texture.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Sets up a base view with the specified size and position.\n * @param width Width in pixels.\n * @param height Height in pixels.\n * @param x X position in pixels.\n * @param y Y position in pixels.\n */\nBaseView::BaseView(int width, int height, int x, int y) : InteractiveSurface(width, height, x, y),\n\t_base(0), _texture(0), _selFacility(0), _big(0), _small(0), _lang(0),\n\t_gridX(0), _gridY(0), _selSizeX(0), _selSizeY(0),\n\t_selector(0), _blink(true),\n\t_redColor(0), _yellowColor(0), _greenColor(0), _highContrast(true),\n\t_cellColor(0), _selectorColor(0)\n{\n\t// Clear grid\n\tfor (int i = 0; i < BASE_SIZE; ++i)\n\t{\n\t\tfor (int j = 0; j < BASE_SIZE; ++j)\n\t\t{\n\t\t\t_facilities[i][j] = 0;\n\t\t}\n\t}\n\n\t_timer = new Timer(100);\n\t_timer->onTimer((SurfaceHandler)&BaseView::blink);\n\t_timer->start();\n}\n\n/**\n * Deletes contents.\n */\nBaseView::~BaseView()\n{\n\tdelete _selector;\n\tdelete _timer;\n}\n\n/**\n * Changes the various resources needed for text rendering.\n * The different fonts need to be passed in advance since the\n * text size can change mid-text, and the language affects\n * how the text is rendered.\n * @param big Pointer to large-size font.\n * @param small Pointer to small-size font.\n * @param lang Pointer to current language.\n */\nvoid BaseView::initText(Font *big, Font *small, Language *lang)\n{\n\t_big = big;\n\t_small = small;\n\t_lang = lang;\n}\n\n/**\n * Changes the current base to display and\n * initializes the internal base grid.\n * @param base Pointer to base to display.\n */\nvoid BaseView::setBase(Base *base)\n{\n\t_base = base;\n\t_selFacility = 0;\n\n\t// Clear grid\n\tfor (int x = 0; x < BASE_SIZE; ++x)\n\t{\n\t\tfor (int y = 0; y < BASE_SIZE; ++y)\n\t\t{\n\t\t\t_facilities[x][y] = 0;\n\t\t}\n\t}\n\n\t// Fill grid with base facilities\n\tfor (auto* fac : *_base->getFacilities())\n\t{\n\t\tfor (int y = fac->getY(); y < fac->getY() + fac->getRules()->getSizeY(); ++y)\n\t\t{\n\t\t\tfor (int x = fac->getX(); x < fac->getX() + fac->getRules()->getSizeX(); ++x)\n\t\t\t{\n\t\t\t\t_facilities[x][y] = fac;\n\t\t\t}\n\t\t}\n\t}\n\n\t_redraw = true;\n}\n\n/**\n * Changes the texture to use for drawing\n * the various base elements.\n * @param texture Pointer to SurfaceSet to use.\n */\nvoid BaseView::setTexture(SurfaceSet *texture)\n{\n\t_texture = texture;\n}\n\n/**\n * Returns the facility the mouse is currently over.\n * @return Pointer to base facility (0 if none).\n */\nBaseFacility *BaseView::getSelectedFacility() const\n{\n\treturn _selFacility;\n}\n\n/**\n * Prevents any mouseover bugs on dismantling base facilities before setBase has had time to update the base.\n */\nvoid BaseView::resetSelectedFacility()\n{\n\t_facilities[_selFacility->getX()][_selFacility->getY()] = 0;\n\t_selFacility = 0;\n}\n\n\n/**\n * Returns the X position of the grid square\n * the mouse is currently over.\n * @return X position on the grid.\n */\nint BaseView::getGridX() const\n{\n\treturn _gridX;\n}\n\n/**\n * Returns the Y position of the grid square\n * the mouse is currently over.\n * @return Y position on the grid.\n */\nint BaseView::getGridY() const\n{\n\treturn _gridY;\n}\n\n/**\n * If enabled, the base view will respond to player input,\n * highlighting the selected facility.\n * @param size Facility length (0 disables it).\n */\nvoid BaseView::setSelectable(int sizeX, int sizeY)\n{\n\t_selSizeX = sizeX;\n\t_selSizeY = sizeY;\n\tif (_selSizeX > 0 && _selSizeY > 0)\n\t{\n\t\t_selector = new Surface(sizeX * GRID_SIZE, sizeY * GRID_SIZE, _x, _y);\n\t\t_selector->setPalette(getPalette());\n\t\tSDL_Rect r;\n\t\tr.w = _selector->getWidth();\n\t\tr.h = _selector->getHeight();\n\t\tr.x = 0;\n\t\tr.y = 0;\n\t\t_selector->drawRect(&r, _selectorColor);\n\t\tr.w -= 2;\n\t\tr.h -= 2;\n\t\tr.x++;\n\t\tr.y++;\n\t\t_selector->drawRect(&r, 0);\n\t\t_selector->setVisible(false);\n\t}\n\telse\n\t{\n\t\tdelete _selector;\n\t}\n}\n\n/**\n * Returns if a certain facility can be successfully\n * placed on the currently selected square.\n * @param rule Facility type.\n * @param facilityBeingMoved Selected facility.\n * @param isStartFacility Is this a start facility?\n * @return 0 if placeable, otherwise error code for why we couldn't place it\n * 1: not connected to lift or on top of another facility (standard OXC behavior)\n * 2: trying to upgrade over existing facility, but it's in use\n * 3: trying to upgrade over existing facility, but it's already being upgraded\n * 4: trying to upgrade over existing facility, but size/placement mismatch\n * 5: trying to upgrade over existing facility, but ruleset of new facility requires a specific existing facility\n * 6: trying to upgrade over existing facility, but ruleset disallows it\n * 7: trying to upgrade over existing facility, but all buildings next to it are under construction and build queue is off\n */\nBasePlacementErrors BaseView::getPlacementError(const RuleBaseFacility *rule, BaseFacility *facilityBeingMoved, bool isStartFacility) const\n{\n\t// We'll need to know for the final check if we're upgrading an existing facility\n\tbool buildingOverExisting = false;\n\n\t// Area where we want to place a new building\n\tconst BaseAreaSubset placementArea = BaseAreaSubset(rule->getSizeX(), rule->getSizeY()).offset(_gridX, _gridY);\n\t// Whole base\n\tconst BaseAreaSubset baseArea = BaseAreaSubset(BASE_SIZE, BASE_SIZE);\n\n\t// Check if the facility fits inside the base boundaries\n\tif (BaseAreaSubset::intersection(placementArea, baseArea) != placementArea)\n\t{\n\t\treturn BPE_NotConnected;\n\t}\n\n\t// Check usage of facilites in the area that will be replaced by a new building\n\tif (facilityBeingMoved == nullptr)\n\t{\n\t\tBasePlacementErrors areaUseError = _base->isAreaInUse(placementArea, rule);\n\t\tif (areaUseError != BPE_None)\n\t\t{\n\t\t\treturn areaUseError;\n\t\t}\n\t}\n\n\t// Check if all squares are occupied already (for facilities that can be built only as upgrades)\n\tif (rule->isUpgradeOnly())\n\t{\n\t\tfor (int y = placementArea.beg_y; y < placementArea.end_y; ++y)\n\t\t{\n\t\t\tfor (int x = placementArea.beg_x; x < placementArea.end_x; ++x)\n\t\t\t{\n\t\t\t\tBaseFacility* facility = _facilities[x][y];\n\t\t\t\tif (!facility)\n\t\t\t\t{\n\t\t\t\t\treturn BPE_UpgradeOnly;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check if square isn't occupied\n\tfor (int y = placementArea.beg_y; y < placementArea.end_y; ++y)\n\t{\n\t\tfor (int x = placementArea.beg_x; x < placementArea.end_x; ++x)\n\t\t{\n\t\t\tBaseFacility* facility = _facilities[x][y];\n\t\t\tif (facility != 0)\n\t\t\t{\n\t\t\t\tif (isStartFacility)\n\t\t\t\t{\n\t\t\t\t\treturn BPE_NotConnected;\n\t\t\t\t}\n\t\t\t\t// when moving an existing facility, it should not block itself\n\t\t\t\tif (facilityBeingMoved == nullptr)\n\t\t\t\t{\n\t\t\t\t\t// Further check to see if the facility already there can be built over and we're not removing an important base function\n\t\t\t\t\tBasePlacementErrors canBuildOverError = rule->getCanBuildOverOtherFacility(facility->getRules());\n\t\t\t\t\tif (canBuildOverError != BPE_None)\n\t\t\t\t\t{\n\t\t\t\t\t\treturn canBuildOverError;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Make sure the facility we're building over is entirely within the size of the one we're checking\n\t\t\t\t\tconst BaseAreaSubset removedArea = facility->getPlacement();\n\t\t\t\t\tif (BaseAreaSubset::intersection(placementArea, removedArea) != removedArea)\n\t\t\t\t\t{\n\t\t\t\t\t\treturn BPE_UpgradeSizeMismatch;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Make sure this facility is not already being upgraded\n\t\t\t\t\tif (facility->getIfHadPreviousFacility() && facility->getBuildTime() != 0)\n\t\t\t\t\t{\n\t\t\t\t\t\treturn BPE_Upgrading;\n\t\t\t\t\t}\n\n\t\t\t\t\tbuildingOverExisting = true;\n\t\t\t\t}\n\t\t\t\telse if (facility != facilityBeingMoved)\n\t\t\t\t{\n\t\t\t\t\treturn BPE_NotConnected;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tbool bq=Options::allowBuildingQueue;\n\tbool hasConnectingFacility = false;\n\n\t// Check for another facility to connect to\n\tfor (int i = 0; i < rule->getSizeX(); ++i)\n\t{\n\t\t// top\n\t\tif (_gridY > 0 && _facilities[_gridX + i][_gridY - 1] != 0)\n\t\t{\n\t\t\thasConnectingFacility = true;\n\t\t\tif ((!buildingOverExisting && bq) || _facilities[_gridX + i][_gridY - 1]->isBuiltOrHadPreviousFacility())\n\t\t\t\treturn BPE_None;\n\t\t}\n\t\t// bottom\n\t\tif (_gridY + rule->getSizeY() < BASE_SIZE && _facilities[_gridX + i][_gridY + rule->getSizeY()] != 0)\n\t\t{\n\t\t\thasConnectingFacility = true;\n\t\t\tif ((!buildingOverExisting && bq) || _facilities[_gridX + i][_gridY + rule->getSizeY()]->isBuiltOrHadPreviousFacility())\n\t\t\t\treturn BPE_None;\n\t\t}\n\t}\n\tfor (int i = 0; i < rule->getSizeY(); ++i)\n\t{\n\t\t// left\n\t\tif (_gridX > 0 && _facilities[_gridX - 1][_gridY + i] != 0)\n\t\t{\n\t\t\thasConnectingFacility = true;\n\t\t\tif ((!buildingOverExisting && bq) || _facilities[_gridX - 1][_gridY + i]->isBuiltOrHadPreviousFacility())\n\t\t\t\treturn BPE_None;\n\t\t}\n\t\t// right\n\t\tif (_gridX + rule->getSizeX() < BASE_SIZE && _facilities[_gridX + rule->getSizeX()][_gridY + i] != 0)\n\t\t{\n\t\t\thasConnectingFacility = true;\n\t\t\tif ((!buildingOverExisting && bq) || _facilities[_gridX + rule->getSizeX()][_gridY + i]->isBuiltOrHadPreviousFacility())\n\t\t\t\treturn BPE_None;\n\t\t}\n\t}\n\n\t// We can assume if we've reached this point that none of the connecting facilities are finished!\n\tif (hasConnectingFacility && (!bq || buildingOverExisting))\n\t\treturn BPE_Queue;\n\n\treturn BPE_NotConnected;\n}\n\n/**\n * Returns if the placed facility is placed in queue or not.\n * @param rule Facility type.\n * @return True if queued, False otherwise.\n */\nbool BaseView::isQueuedBuilding(const RuleBaseFacility *rule) const\n{\n\tfor (int i = 0; i < rule->getSizeX(); ++i)\n\t{\n\t\tif ((_gridY > 0 && _facilities[_gridX + i][_gridY - 1] != 0 && _facilities[_gridX + i][_gridY - 1]->isBuiltOrHadPreviousFacility()) ||\n\t\t\t(_gridY + rule->getSizeY() < BASE_SIZE && _facilities[_gridX + i][_gridY + rule->getSizeY()] != 0 && _facilities[_gridX + i][_gridY + rule->getSizeY()]->isBuiltOrHadPreviousFacility()))\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\tfor (int i = 0; i < rule->getSizeY(); ++i)\n\t{\n\t\tif ((_gridX > 0 && _facilities[_gridX - 1][_gridY + i] != 0 && _facilities[_gridX - 1][_gridY + i]->isBuiltOrHadPreviousFacility()) ||\n\t\t\t(_gridX + rule->getSizeX() < BASE_SIZE && _facilities[_gridX + rule->getSizeX()][_gridY + i] != 0 && _facilities[_gridX + rule->getSizeX()][_gridY + i]->isBuiltOrHadPreviousFacility()))\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n}\n\n/**\n * ReCalculates the remaining build-time of all queued buildings.\n */\nvoid BaseView::reCalcQueuedBuildings()\n{\n\tsetBase(_base);\n\tstd::vector<BaseFacility*> facilities;\n\tfor (auto* fac : *_base->getFacilities())\n\t{\n\t\tif (fac->getAdjustedBuildTime() > 0)\n\t\t{\n\t\t\t// Set all queued buildings to infinite.\n\t\t\tif (fac->getAdjustedBuildTime() > fac->getRules()->getBuildTime())\n\t\t\t{\n\t\t\t\tfac->setBuildTime(INT_MAX);\n\t\t\t}\n\t\t\tfacilities.push_back(fac);\n\t\t}\n\t}\n\n\t// Applying a simple Dijkstra Algorithm\n\twhile (!facilities.empty())\n\t{\n\t\tauto min = facilities.begin();\n\t\tfor (auto it = facilities.begin(); it != facilities.end(); ++it)\n\t\t{\n\t\t\tif ((*it)->getAdjustedBuildTime() < (*min)->getAdjustedBuildTime())\n\t\t\t{\n\t\t\t\tmin = it;\n\t\t\t}\n\t\t}\n\t\tBaseFacility* facility=(*min);\n\t\tfacilities.erase(min);\n\t\tconst RuleBaseFacility *rule=facility->getRules();\n\t\tint x=facility->getX(), y=facility->getY();\n\t\tfor (int i = 0; i < rule->getSizeX(); ++i)\n\t\t{\n\t\t\tif (y > 0) updateNeighborFacilityBuildTime(facility,_facilities[x + i][y - 1]);\n\t\t\tif (y + rule->getSizeY() < BASE_SIZE) updateNeighborFacilityBuildTime(facility,_facilities[x + i][y + rule->getSizeY()]);\n\t\t}\n\t\tfor (int i = 0; i < rule->getSizeY(); ++i)\n\t\t{\n\t\t\tif (x > 0) updateNeighborFacilityBuildTime(facility, _facilities[x - 1][y + i]);\n\t\t\tif (x + rule->getSizeX() < BASE_SIZE) updateNeighborFacilityBuildTime(facility, _facilities[x + rule->getSizeX()][y + i]);\n\t\t}\n\t}\n}\n\n/**\n * Updates the neighborFacility's build time. This is for internal use only (reCalcQueuedBuildings()).\n * @param facility Pointer to a base facility.\n * @param neighbor Pointer to a neighboring base facility.\n */\nvoid BaseView::updateNeighborFacilityBuildTime(BaseFacility* facility, BaseFacility* neighbor)\n{\n\tif (facility != 0 && neighbor != 0\n\t&& neighbor->getAdjustedBuildTime() > neighbor->getRules()->getBuildTime()\n\t&& facility->getAdjustedBuildTime() + neighbor->getRules()->getBuildTime() < neighbor->getAdjustedBuildTime())\n\t\tneighbor->setBuildTime(facility->getAdjustedBuildTime() + neighbor->getRules()->getBuildTime());\n}\n\n/**\n * Keeps the animation timers running.\n */\nvoid BaseView::think()\n{\n\t_timer->think(0, this);\n}\n\n/**\n * Makes the facility selector blink.\n */\nvoid BaseView::blink()\n{\n\t_blink = !_blink;\n\n\tif (_selSizeX > 0 && _selSizeY > 0)\n\t{\n\t\tSDL_Rect r;\n\t\tif (_blink)\n\t\t{\n\t\t\tr.w = _selector->getWidth();\n\t\t\tr.h = _selector->getHeight();\n\t\t\tr.x = 0;\n\t\t\tr.y = 0;\n\t\t\t_selector->drawRect(&r, _selectorColor);\n\t\t\tr.w -= 2;\n\t\t\tr.h -= 2;\n\t\t\tr.x++;\n\t\t\tr.y++;\n\t\t\t_selector->drawRect(&r, 0);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tr.w = _selector->getWidth();\n\t\t\tr.h = _selector->getHeight();\n\t\t\tr.x = 0;\n\t\t\tr.y = 0;\n\t\t\t_selector->drawRect(&r, 0);\n\t\t}\n\t}\n}\n\n/**\n * Draws the view of all the facilities in the base, connectors\n * between them and crafts landed in hangars.\n */\nvoid BaseView::draw()\n{\n\tSurface::draw();\n\n\t// Draw grid squares\n\tfor (int x = 0; x < BASE_SIZE; ++x)\n\t{\n\t\tfor (int y = 0; y < BASE_SIZE; ++y)\n\t\t{\n\t\t\tSurface *frame = _texture->getFrame(_base->getGlobeTexture() ? _base->getGlobeTexture()->getBaseGridSprite() : 0);\n\t\t\tint fx = (x * GRID_SIZE);\n\t\t\tint fy = (y * GRID_SIZE);\n\t\t\tframe->blitNShade(this, fx, fy);\n\t\t}\n\t}\n\n\tauto craftIt = _base->getCrafts()->begin();\n\n\tfor (const auto* fac : *_base->getFacilities())\n\t{\n\t\t// Draw facility shape\n\t\tint num = 0;\n\t\tfor (int y = fac->getY(); y < fac->getY() + fac->getRules()->getSizeY(); ++y)\n\t\t{\n\t\t\tfor (int x = fac->getX(); x < fac->getX() + fac->getRules()->getSizeX(); ++x)\n\t\t\t{\n\t\t\t\tSurface *frame;\n\n\t\t\t\tint outline = fac->getRules()->isSmall() ? 3 : fac->getRules()->getSizeX() * fac->getRules()->getSizeY();\n\t\t\t\tif (fac->getBuildTime() == 0)\n\t\t\t\t\tframe = _texture->getFrame(fac->getRules()->getSpriteShape() + num);\n\t\t\t\telse\n\t\t\t\t\tframe = _texture->getFrame(fac->getRules()->getSpriteShape() + num + outline);\n\n\t\t\t\tint fx = (x * GRID_SIZE);\n\t\t\t\tint fy = (y * GRID_SIZE);\n\t\t\t\tframe->blitNShade(this, fx, fy);\n\n\t\t\t\tnum++;\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (const auto* fac : *_base->getFacilities())\n\t{\n\t\t// Draw connectors\n\t\tif (fac->isBuiltOrHadPreviousFacility() && !fac->getRules()->connectorsDisabled())\n\t\t{\n\t\t\t// Facilities to the right\n\t\t\tint x = fac->getX() + fac->getRules()->getSizeX();\n\t\t\tif (x < BASE_SIZE)\n\t\t\t{\n\t\t\t\tfor (int y = fac->getY(); y < fac->getY() + fac->getRules()->getSizeY(); ++y)\n\t\t\t\t{\n\t\t\t\t\tif (_facilities[x][y] != 0 && _facilities[x][y]->isBuiltOrHadPreviousFacility() && !_facilities[x][y]->getRules()->connectorsDisabled())\n\t\t\t\t\t{\n\t\t\t\t\t\tSurface *frame = _texture->getFrame(7);\n\t\t\t\t\t\tint fx = (x * GRID_SIZE - GRID_SIZE / 2);\n\t\t\t\t\t\tint fy = (y * GRID_SIZE);\n\t\t\t\t\t\tframe->blitNShade(this, fx, fy);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Facilities to the bottom\n\t\t\tint y = fac->getY() + fac->getRules()->getSizeY();\n\t\t\tif (y < BASE_SIZE)\n\t\t\t{\n\t\t\t\tfor (int subX = fac->getX(); subX < fac->getX() + fac->getRules()->getSizeX(); ++subX)\n\t\t\t\t{\n\t\t\t\t\tif (_facilities[subX][y] != 0 && _facilities[subX][y]->isBuiltOrHadPreviousFacility() && !_facilities[subX][y]->getRules()->connectorsDisabled())\n\t\t\t\t\t{\n\t\t\t\t\t\tSurface *frame = _texture->getFrame(8);\n\t\t\t\t\t\tint fx = (subX * GRID_SIZE);\n\t\t\t\t\t\tint fy = (y * GRID_SIZE - GRID_SIZE / 2);\n\t\t\t\t\t\tframe->blitNShade(this, fx, fy);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// TODO: make const in the future\n\tfor (auto* fac : *_base->getFacilities())\n\t{\n\t\t// Draw facility graphic\n\t\tint num = 0;\n\t\tfor (int y = fac->getY(); y < fac->getY() + fac->getRules()->getSizeY(); ++y)\n\t\t{\n\t\t\tfor (int x = fac->getX(); x < fac->getX() + fac->getRules()->getSizeX(); ++x)\n\t\t\t{\n\t\t\t\tif (fac->getRules()->getSpriteEnabled())\n\t\t\t\t{\n\t\t\t\t\tSurface *frame = _texture->getFrame(fac->getRules()->getSpriteFacility() + num);\n\t\t\t\t\tint fx = (x * GRID_SIZE);\n\t\t\t\t\tint fy = (y * GRID_SIZE);\n\t\t\t\t\tframe->blitNShade(this, fx, fy);\n\t\t\t\t}\n\n\t\t\t\tnum++;\n\t\t\t}\n\t\t}\n\n\t\t// Draw crafts\n\t\tfac->setCraftForDrawing(0);\n\t\tif (fac->getBuildTime() == 0 && fac->getRules()->getCrafts() > 0)\n\t\t{\n\t\t\tif (craftIt != _base->getCrafts()->end())\n\t\t\t{\n\t\t\t\tif ((*craftIt)->getStatus() != \"STR_OUT\")\n\t\t\t\t{\n\t\t\t\t\tSurface *frame = _texture->getFrame((*craftIt)->getSkinSprite() + 33);\n\t\t\t\t\tint fx = (fac->getX() * GRID_SIZE + (fac->getRules()->getSizeX() - 1) * GRID_SIZE / 2 + 2);\n\t\t\t\t\tint fy = (fac->getY() * GRID_SIZE + (fac->getRules()->getSizeY() - 1) * GRID_SIZE / 2 - 4);\n\t\t\t\t\tframe->blitNShade(this, fx, fy);\n\t\t\t\t\tfac->setCraftForDrawing(*craftIt);\n\t\t\t\t}\n\t\t\t\t++craftIt;\n\t\t\t}\n\t\t}\n\n\t\t// Draw time remaining\n\t\tif (fac->getBuildTime() > 0 || fac->getDisabled())\n\t\t{\n\t\t\tText *text = new Text(GRID_SIZE * fac->getRules()->getSizeX(), 16, 0, 0);\n\t\t\ttext->setPalette(getPalette());\n\t\t\ttext->initText(_big, _small, _lang);\n\t\t\ttext->setX(fac->getX() * GRID_SIZE);\n\t\t\ttext->setY(fac->getY() * GRID_SIZE + (GRID_SIZE * fac->getRules()->getSizeY() - 16) / 2);\n\t\t\ttext->setBig();\n\t\t\tstd::ostringstream ss;\n\t\t\tif (fac->getDisabled())\n\t\t\t\tss << \"X\";\n\t\t\telse\n\t\t\t\tss << fac->getBuildTime();\n\t\t\tif (fac->getIfHadPreviousFacility()) // Indicate that this facility still counts for connectivity\n\t\t\t\tss << \"*\";\n\t\t\ttext->setAlign(ALIGN_CENTER);\n\t\t\ttext->setColor(_cellColor);\n\t\t\ttext->setText(ss.str());\n\t\t\ttext->blit(this->getSurface());\n\t\t\tdelete text;\n\t\t}\n\n\t\t// Draw ammo indicator\n\t\tif (fac->getBuildTime() == 0 && fac->getRules()->getAmmoMax() > 0)\n\t\t{\n\t\t\tText* text = new Text(GRID_SIZE * fac->getRules()->getSizeX(), 9, 0, 0);\n\t\t\ttext->setPalette(getPalette());\n\t\t\ttext->initText(_big, _small, _lang);\n\t\t\ttext->setX(fac->getX() * GRID_SIZE);\n\t\t\ttext->setY(fac->getY() * GRID_SIZE);\n\t\t\ttext->setHighContrast(_highContrast);\n\t\t\tif (fac->getAmmo() >= fac->getRules()->getAmmoMax())\n\t\t\t\ttext->setColor(_greenColor); // 100%\n\t\t\telse if (fac->getAmmo() <= fac->getRules()->getAmmoMax() / 2)\n\t\t\t\ttext->setColor(_redColor); // 0-50%\n\t\t\telse\n\t\t\t\ttext->setColor(_yellowColor); // 51-99%\n\t\t\tstd::ostringstream ss;\n\t\t\tss << fac->getAmmo() << \"/\" << fac->getRules()->getAmmoMax();\n\t\t\ttext->setText(ss.str());\n\t\t\ttext->blit(this->getSurface());\n\t\t\tdelete text;\n\t\t}\n\t}\n}\n\n/**\n * Blits the base view and selector.\n * @param surface Pointer to surface to blit onto.\n */\nvoid BaseView::blit(SDL_Surface *surface)\n{\n\tSurface::blit(surface);\n\tif (_selector != 0)\n\t{\n\t\t_selector->blit(surface);\n\t}\n}\n\n/**\n * Selects the facility the mouse is over.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid BaseView::mouseOver(Action *action, State *state)\n{\n\t_gridX = (int)floor(action->getRelativeXMouse() / (GRID_SIZE * action->getXScale()));\n\t_gridY = (int)floor(action->getRelativeYMouse() / (GRID_SIZE * action->getYScale()));\n\tif (_gridX >= 0 && _gridX < BASE_SIZE && _gridY >= 0 && _gridY < BASE_SIZE)\n\t{\n\t\t_selFacility = _facilities[_gridX][_gridY];\n\t\tif (_selSizeX > 0 && _selSizeY > 0)\n\t\t{\n\t\t\tif (_gridX + _selSizeX - 1 < BASE_SIZE && _gridY + _selSizeY - 1 < BASE_SIZE)\n\t\t\t{\n\t\t\t\t_selector->setX(_x + _gridX * GRID_SIZE);\n\t\t\t\t_selector->setY(_y + _gridY * GRID_SIZE);\n\t\t\t\t_selector->setVisible(true);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_selector->setVisible(false);\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\t_selFacility = 0;\n\t\tif (_selSizeX > 0 && _selSizeY > 0)\n\t\t{\n\t\t\t_selector->setVisible(false);\n\t\t}\n\t}\n\n\tInteractiveSurface::mouseOver(action, state);\n}\n\n/**\n * Deselects the facility.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid BaseView::mouseOut(Action *action, State *state)\n{\n\t_selFacility = 0;\n\tif (_selSizeX > 0 && _selSizeY > 0)\n\t{\n\t\t_selector->setVisible(false);\n\t}\n\n\tInteractiveSurface::mouseOut(action, state);\n}\n\nvoid BaseView::setColor(Uint8 color)\n{\n\t_cellColor = color;\n}\nvoid BaseView::setSecondaryColor(Uint8 color)\n{\n\t_selectorColor = color;\n}\nvoid BaseView::setOtherColors(Uint8 red, Uint8 yellow, Uint8 green, bool highContrast)\n{\n\t_redColor = red;\n\t_yellowColor = yellow;\n\t_greenColor = green;\n\t_highContrast = highContrast;\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/BaseView.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/InteractiveSurface.h\"\n\nnamespace OpenXcom\n{\n\nclass Base;\nclass SurfaceSet;\nclass BaseFacility;\nclass RuleBaseFacility;\nclass Font;\nclass Language;\nclass Timer;\nenum BasePlacementErrors : int;\n\n/**\n * Interactive view of a base.\n * Takes a certain base and displays all its facilities\n * and status, allowing players to manage them.\n */\nclass BaseView : public InteractiveSurface\n{\nprivate:\n\tstatic const int BASE_SIZE = 6;\n\tstatic const int GRID_SIZE = 32;\n\n\tBase *_base;\n\tSurfaceSet *_texture;\n\tBaseFacility *_facilities[BASE_SIZE][BASE_SIZE], *_selFacility;\n\tFont *_big, *_small;\n\tLanguage *_lang;\n\tint _gridX, _gridY;\n\tint _selSizeX, _selSizeY;\n\tSurface *_selector;\n\tbool _blink;\n\tTimer *_timer;\n\tUint8 _redColor, _yellowColor, _greenColor;\n\tbool _highContrast;\n\tUint8 _cellColor, _selectorColor;\n\t/// Updates the neighborFacility's build time. This is for internal use only (reCalcQueuedBuildings()).\n\tvoid updateNeighborFacilityBuildTime(BaseFacility* facility, BaseFacility* neighbor);\npublic:\n\t/// Creates a new base view at the specified position and size.\n\tBaseView(int width, int height, int x = 0, int y = 0);\n\t/// Cleans up the base view.\n\t~BaseView();\n\t/// Initializes the base view's various resources.\n\tvoid initText(Font *big, Font *small, Language *lang) override;\n\t/// Sets the base to display.\n\tvoid setBase(Base *base);\n\t/// Sets the texture for this base view.\n\tvoid setTexture(SurfaceSet *texture);\n\t/// Gets the currently selected facility.\n\tBaseFacility *getSelectedFacility() const;\n\t/// Prevents any mouseover bugs on dismantling base facilities before setBase has had time to update the base.\n\tvoid resetSelectedFacility();\n\t/// Gets the X position of the currently selected square.\n\tint getGridX() const;\n\t/// Gets the Y position of the currently selected square.\n\tint getGridY() const;\n\t/// Sets whether the base view is selectable.\n\tvoid setSelectable(int sizeX, int sizeY);\n\t/// Checks if a facility can be placed. Returns 0 if it can, otherwise an int for why not.\n\tBasePlacementErrors getPlacementError(const RuleBaseFacility *rule, BaseFacility *facilityBeingMoved = nullptr, bool isStartFacility = false) const;\n\t/// Checks if the placed facility is placed in queue or not.\n\tbool isQueuedBuilding(const RuleBaseFacility *rule) const;\n\t/// ReCalculates the remaining build-time of all queued buildings.\n\tvoid reCalcQueuedBuildings();\n\t/// Handles the timers.\n\tvoid think() override;\n\t/// Blinks the selector.\n\tvoid blink();\n\t/// Draws the base view.\n\tvoid draw() override;\n\t/// Blits the base view onto another surface.\n\tvoid blit(SDL_Surface *surface) override;\n\t/// Special handling for mouse hovers.\n\tvoid mouseOver(Action *action, State *state) override;\n\t/// Special handling for mouse hovering out.\n\tvoid mouseOut(Action *action, State *state) override;\n\n\tvoid setColor(Uint8 color) override;\n\tvoid setSecondaryColor(Uint8 color) override;\n\tvoid setOtherColors(Uint8 red, Uint8 yellow, Uint8 green, bool highContrast);\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/BasescapeState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"BasescapeState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextEdit.h\"\n#include \"BaseView.h\"\n#include \"MiniBaseView.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/BaseFacility.h\"\n#include \"../Mod/RuleBaseFacility.h\"\n#include \"../Savegame/Region.h\"\n#include \"../Mod/RuleRegion.h\"\n#include \"../Menu/ErrorMessageState.h\"\n#include \"DismantleFacilityState.h\"\n#include \"../Geoscape/BuildNewBaseState.h\"\n#include \"../Engine/Action.h\"\n#include \"BaseInfoState.h\"\n#include \"SoldiersState.h\"\n#include \"CraftsState.h\"\n#include \"BuildFacilitiesState.h\"\n#include \"ResearchState.h\"\n#include \"ManageAlienContainmentState.h\"\n#include \"ManufactureState.h\"\n#include \"PurchaseState.h\"\n#include \"SellState.h\"\n#include \"TransferBaseState.h\"\n#include \"CraftInfoState.h\"\n#include \"../Geoscape/AllocatePsiTrainingState.h\"\n#include \"../Geoscape/AllocateTrainingState.h\"\n#include \"../Mod/RuleInterface.h\"\n#include \"PlaceFacilityState.h\"\n#include \"../Ufopaedia/Ufopaedia.h\"\n#include \"../Battlescape/BattlescapeGenerator.h\"\n#include \"../Battlescape/BriefingState.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"../Geoscape/Globe.h\"\n#include \"../Mod/RuleGlobe.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Basescape screen.\n * @param game Pointer to the core game.\n * @param base Pointer to the base to get info from.\n * @param globe Pointer to the Geoscape globe.\n */\nBasescapeState::BasescapeState(Base *base, Globe *globe) : _base(base), _globe(globe)\n{\n\t// Create objects\n\t_txtFacility = new Text(192, 9, 0, 0);\n\t_view = new BaseView(192, 192, 0, 8);\n\t_mini = new MiniBaseView(128, 16, 192, 41);\n\t_edtBase = new TextEdit(this, 127, 17, 193, 0);\n\t_txtLocation = new Text(126, 9, 194, 16);\n\t_txtFunds = new Text(126, 9, 194, 24);\n\t_btnNewBase = new TextButton(128, 12, 192, 58);\n\t_btnBaseInfo = new TextButton(128, 12, 192, 71);\n\t_btnSoldiers = new TextButton(128, 12, 192, 84);\n\t_btnCrafts = new TextButton(128, 12, 192, 97);\n\t_btnFacilities = new TextButton(128, 12, 192, 110);\n\t_btnResearch = new TextButton(128, 12, 192, 123);\n\t_btnManufacture = new TextButton(128, 12, 192, 136);\n\t_btnTransfer = new TextButton(128, 12, 192, 149);\n\t_btnPurchase = new TextButton(128, 12, 192, 162);\n\t_btnSell = new TextButton(128, 12, 192, 175);\n\t_btnGeoscape = new TextButton(128, 12, 192, 188);\n\n\t// Set palette\n\tsetInterface(\"basescape\");\n\n\tadd(_view, \"baseView\", \"basescape\");\n\tadd(_mini, \"miniBase\", \"basescape\");\n\tadd(_txtFacility, \"textTooltip\", \"basescape\");\n\tadd(_edtBase, \"text1\", \"basescape\");\n\tadd(_txtLocation, \"text2\", \"basescape\");\n\tadd(_txtFunds, \"text3\", \"basescape\");\n\tadd(_btnNewBase, \"button\", \"basescape\");\n\tadd(_btnBaseInfo, \"button\", \"basescape\");\n\tadd(_btnSoldiers, \"button\", \"basescape\");\n\tadd(_btnCrafts, \"button\", \"basescape\");\n\tadd(_btnFacilities, \"button\", \"basescape\");\n\tadd(_btnResearch, \"button\", \"basescape\");\n\tadd(_btnManufacture, \"button\", \"basescape\");\n\tadd(_btnTransfer, \"button\", \"basescape\");\n\tadd(_btnPurchase, \"button\", \"basescape\");\n\tadd(_btnSell, \"button\", \"basescape\");\n\tadd(_btnGeoscape, \"button\", \"basescape\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tif (_globe)\n\t{\n\t\tfor (auto* xbase : *_game->getSavedGame()->getBases())\n\t\t{\n\t\t\tint texture, shade;\n\t\t\t_globe->getPolygonTextureAndShade(xbase->getLongitude(), xbase->getLatitude(), &texture, &shade);\n\t\t\tauto* globeTexture = _game->getMod()->getGlobe()->getTexture(texture);\n\t\t\txbase->setGlobeTexture(globeTexture);\n\t\t}\n\t}\n\n\tauto* itf = _game->getMod()->getInterface(\"basescape\")->getElementOptional(\"trafficLights\");\n\tif (itf)\n\t{\n\t\t_view->setOtherColors(itf->color, itf->color2, itf->border, !itf->TFTDMode);\n\t}\n\t_view->setTexture(_game->getMod()->getSurfaceSet(\"BASEBITS.PCK\"));\n\t_view->onMouseClick((ActionHandler)&BasescapeState::viewLeftClick, SDL_BUTTON_LEFT);\n\t_view->onMouseClick((ActionHandler)&BasescapeState::viewRightClick, SDL_BUTTON_RIGHT);\n\t_view->onMouseClick((ActionHandler)&BasescapeState::viewMiddleClick, SDL_BUTTON_MIDDLE);\n\t_view->onMouseOver((ActionHandler)&BasescapeState::viewMouseOver);\n\t_view->onMouseOut((ActionHandler)&BasescapeState::viewMouseOut);\n\n\t_mini->setTexture(_game->getMod()->getSurfaceSet(\"BASEBITS.PCK\"));\n\t_mini->setBases(_game->getSavedGame()->getBases());\n\t_mini->onMouseClick((ActionHandler)&BasescapeState::miniLeftClick, SDL_BUTTON_LEFT);\n\t_mini->onMouseClick((ActionHandler)&BasescapeState::miniRightClick, SDL_BUTTON_RIGHT);\n\t_mini->onKeyboardPress((ActionHandler)&BasescapeState::handleKeyPress);\n\n\t_edtBase->setBig();\n\t_edtBase->onChange((ActionHandler)&BasescapeState::edtBaseChange);\n\n\t_btnNewBase->setText(tr(\"STR_BUILD_NEW_BASE_UC\"));\n\t_btnNewBase->onMouseClick((ActionHandler)&BasescapeState::btnNewBaseClick);\n\t_btnNewBase->onKeyboardPress((ActionHandler)&BasescapeState::btnNewBaseClick, Options::keyBasescapeBuildNewBase);\n\n\t_btnBaseInfo->setText(tr(\"STR_BASE_INFORMATION\"));\n\t_btnBaseInfo->onMouseClick((ActionHandler)&BasescapeState::btnBaseInfoClick);\n\t_btnBaseInfo->onKeyboardPress((ActionHandler)&BasescapeState::btnBaseInfoClick, Options::keyBasescapeBaseInfo);\n\n\t_btnSoldiers->setText(tr(\"STR_SOLDIERS_UC\"));\n\t_btnSoldiers->onMouseClick((ActionHandler)&BasescapeState::btnSoldiersClick);\n\t_btnSoldiers->onKeyboardPress((ActionHandler)&BasescapeState::btnSoldiersClick, Options::keyBasescapeSoldiers);\n\n\t_btnCrafts->setText(tr(\"STR_EQUIP_CRAFT\"));\n\t_btnCrafts->onMouseClick((ActionHandler)&BasescapeState::btnCraftsClick);\n\t_btnCrafts->onKeyboardPress((ActionHandler)&BasescapeState::btnCraftsClick, Options::keyBasescapeCrafts);\n\n\t_btnFacilities->setText(tr(\"STR_BUILD_FACILITIES\"));\n\t_btnFacilities->onMouseClick((ActionHandler)&BasescapeState::btnFacilitiesClick);\n\t_btnFacilities->onKeyboardPress((ActionHandler)&BasescapeState::btnFacilitiesClick, Options::keyBasescapeFacilities);\n\n\t_btnResearch->setText(tr(\"STR_RESEARCH\"));\n\t_btnResearch->onMouseClick((ActionHandler)&BasescapeState::btnResearchClick);\n\t_btnResearch->onKeyboardPress((ActionHandler)&BasescapeState::btnResearchClick, Options::keyBasescapeResearch);\n\n\t_btnManufacture->setText(tr(\"STR_MANUFACTURE\"));\n\t_btnManufacture->onMouseClick((ActionHandler)&BasescapeState::btnManufactureClick);\n\t_btnManufacture->onKeyboardPress((ActionHandler)&BasescapeState::btnManufactureClick, Options::keyBasescapeManufacture);\n\n\t_btnTransfer->setText(tr(\"STR_TRANSFER_UC\"));\n\t_btnTransfer->onMouseClick((ActionHandler)&BasescapeState::btnTransferClick);\n\t_btnTransfer->onKeyboardPress((ActionHandler)&BasescapeState::btnTransferClick, Options::keyBasescapeTransfer);\n\n\t_btnPurchase->setText(tr(\"STR_PURCHASE_RECRUIT\"));\n\t_btnPurchase->onMouseClick((ActionHandler)&BasescapeState::btnPurchaseClick);\n\t_btnPurchase->onKeyboardPress((ActionHandler)&BasescapeState::btnPurchaseClick, Options::keyBasescapePurchase);\n\n\t_btnSell->setText(tr(\"STR_SELL_SACK_UC\"));\n\t_btnSell->onMouseClick((ActionHandler)&BasescapeState::btnSellClick);\n\t_btnSell->onKeyboardPress((ActionHandler)&BasescapeState::btnSellClick, Options::keyBasescapeSell);\n\n\t_btnGeoscape->setText(tr(\"STR_GEOSCAPE_UC\"));\n\t_btnGeoscape->onMouseClick((ActionHandler)&BasescapeState::btnGeoscapeClick);\n\t_btnGeoscape->onKeyboardPress((ActionHandler)&BasescapeState::btnGeoscapeClick, Options::keyCancel);\n}\n\n/**\n *\n */\nBasescapeState::~BasescapeState()\n{\n\t// Clean up any temporary bases\n\tbool exists = false;\n\tfor (const auto* xbase : *_game->getSavedGame()->getBases())\n\t{\n\t\tif (xbase == _base)\n\t\t{\n\t\t\texists = true;\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (!exists)\n\t{\n\t\tdelete _base;\n\t}\n}\n\n/**\n * The player can change the selected base\n * or change info on other screens.\n */\nvoid BasescapeState::init()\n{\n\tState::init();\n\n\tsetBase(_base);\n\t_view->setBase(_base);\n\t_mini->draw();\n\t_edtBase->setText(_base->getName());\n\n\t// Get area\n\tfor (const auto* region : *_game->getSavedGame()->getRegions())\n\t{\n\t\tif (region->getRules()->insideRegion(_base->getLongitude(), _base->getLatitude()))\n\t\t{\n\t\t\t_txtLocation->setText(tr(region->getRules()->getType()));\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t_txtFunds->setText(tr(\"STR_FUNDS\").arg(Unicode::formatFunding(_game->getSavedGame()->getFunds())));\n\n\t_btnNewBase->setVisible(_game->getSavedGame()->getBases()->size() < MiniBaseView::MAX_BASES);\n\n\tif (!_game->getMod()->getNewBaseUnlockResearch().empty())\n\t{\n\t\tbool newBasesUnlocked = _game->getSavedGame()->isResearched(_game->getMod()->getNewBaseUnlockResearch(), true);\n\t\tif (!newBasesUnlocked)\n\t\t{\n\t\t\t_btnNewBase->setVisible(false);\n\t\t}\n\t}\n}\n\n/**\n * Changes the base currently displayed on screen.\n * @param base Pointer to new base to display.\n */\nvoid BasescapeState::setBase(Base *base)\n{\n\tif (!_game->getSavedGame()->getBases()->empty())\n\t{\n\t\t// Check if base still exists\n\t\tbool exists = false;\n\t\tfor (size_t i = 0; i < _game->getSavedGame()->getBases()->size(); ++i)\n\t\t{\n\t\t\tif (_game->getSavedGame()->getBases()->at(i) == base)\n\t\t\t{\n\t\t\t\t_base = base;\n\t\t\t\t_mini->setSelectedBase(i);\n\t\t\t\t_game->getSavedGame()->setSelectedBase(i);\n\t\t\t\texists = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\t// If base was removed, select first one\n\t\tif (!exists)\n\t\t{\n\t\t\t_base = _game->getSavedGame()->getBases()->front();\n\t\t\t_mini->setSelectedBase(0);\n\t\t\t_game->getSavedGame()->setSelectedBase(0);\n\t\t}\n\t}\n\telse\n\t{\n\t\t// Use a blank base for special case when player has no bases\n\t\t_base = new Base(_game->getMod());\n\t\t_mini->setSelectedBase(0);\n\t\t_game->getSavedGame()->setSelectedBase(0);\n\t}\n}\n\n/**\n * Goes to the Build New Base screen.\n * @param action Pointer to an action.\n */\nvoid BasescapeState::btnNewBaseClick(Action *)\n{\n\tBase *base = new Base(_game->getMod());\n\t_game->popState();\n\t_game->pushState(new BuildNewBaseState(base, _globe, false));\n}\n\n/**\n * Goes to the Base Info screen.\n * @param action Pointer to an action.\n */\nvoid BasescapeState::btnBaseInfoClick(Action *)\n{\n\t_game->pushState(new BaseInfoState(_base, this));\n}\n\n/**\n * Goes to the Soldiers screen.\n * @param action Pointer to an action.\n */\nvoid BasescapeState::btnSoldiersClick(Action *)\n{\n\t_game->pushState(new SoldiersState(_base));\n}\n\n/**\n * Goes to the Crafts screen.\n * @param action Pointer to an action.\n */\nvoid BasescapeState::btnCraftsClick(Action *)\n{\n\t_game->pushState(new CraftsState(_base));\n}\n\n/**\n * Opens the Build Facilities window.\n * @param action Pointer to an action.\n */\nvoid BasescapeState::btnFacilitiesClick(Action *)\n{\n\t_game->pushState(new BuildFacilitiesState(_base, this));\n}\n\n/**\n * Goes to the Research screen.\n * @param action Pointer to an action.\n */\nvoid BasescapeState::btnResearchClick(Action *)\n{\n\t_game->pushState(new ResearchState(_base));\n}\n\n/**\n * Goes to the Manufacture screen.\n * @param action Pointer to an action.\n */\nvoid BasescapeState::btnManufactureClick(Action *)\n{\n\t_game->pushState(new ManufactureState(_base));\n}\n\n/**\n * Goes to the Purchase screen.\n * @param action Pointer to an action.\n */\nvoid BasescapeState::btnPurchaseClick(Action *)\n{\n\t_game->pushState(new PurchaseState(_base));\n}\n\n/**\n * Goes to the Sell screen.\n * @param action Pointer to an action.\n */\nvoid BasescapeState::btnSellClick(Action *)\n{\n\t_game->pushState(new SellState(_base, 0));\n}\n\n/**\n * Goes to the Select Destination Base window.\n * @param action Pointer to an action.\n */\nvoid BasescapeState::btnTransferClick(Action *)\n{\n\t_game->pushState(new TransferBaseState(_base, nullptr));\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid BasescapeState::btnGeoscapeClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Processes clicking on facilities.\n * @param action Pointer to an action.\n */\nvoid BasescapeState::viewLeftClick(Action *)\n{\n\tBaseFacility *fac = _view->getSelectedFacility();\n\tif (fac != 0)\n\t{\n\t\tif (_game->isCtrlPressed() && Options::isPasswordCorrect())\n\t\t{\n\t\t\t// Ctrl + left click on a base facility allows moving it\n\t\t\t_game->pushState(new PlaceFacilityState(_base, fac->getRules(), fac));\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (fac->getRules()->isLift() && _base->getFacilities()->size() > 1)\n\t\t\t{\n\t\t\t\t// Note: vehicles will not be deployed in the base preview\n\t\t\t\tif (_base->getAvailableSoldiers(true, true) > 0/* || !_base->getVehicles()->empty()*/)\n\t\t\t\t{\n\t\t\t\t\tint texture, shade;\n\t\t\t\t\t_globe->getPolygonTextureAndShade(_base->getLongitude(), _base->getLatitude(), &texture, &shade);\n\t\t\t\t\tauto* globeTexture = _game->getMod()->getGlobe()->getTexture(texture);\n\n\t\t\t\t\tSavedBattleGame* bgame = new SavedBattleGame(_game->getMod(), _game->getLanguage(), true);\n\t\t\t\t\t_game->getSavedGame()->setBattleGame(bgame);\n\t\t\t\t\tBattlescapeGenerator bgen = BattlescapeGenerator(_game);\n\t\t\t\t\tbgame->setMissionType(\"STR_BASE_DEFENSE\");\n\t\t\t\t\tbgen.setBase(_base);\n\t\t\t\t\tbgen.setWorldTexture(globeTexture, globeTexture);\n\t\t\t\t\tbgen.run();\n\n\t\t\t\t\t_game->pushState(new BriefingState(0, _base));\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tint errorColor1 = _game->getMod()->getInterface(\"basescape\")->getElement(\"errorMessage\")->color;\n\t\t\tint errorColor2 = _game->getMod()->getInterface(\"basescape\")->getElement(\"errorPalette\")->color;\n\t\t\t// Is facility in use?\n\t\t\tif (BasePlacementErrors placementErrorCode = fac->inUse())\n\t\t\t{\n\t\t\t\tswitch (placementErrorCode)\n\t\t\t\t{\n\t\t\t\tcase BPE_Used_Stores:\n\t\t\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_FACILITY_IN_USE_STORAGE\"), _palette, errorColor1, \"BACK13.SCR\", errorColor2));\n\t\t\t\t\tbreak;\n\t\t\t\tcase BPE_Used_Quarters:\n\t\t\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_FACILITY_IN_USE_QUARTERS\"), _palette, errorColor1, \"BACK13.SCR\", errorColor2));\n\t\t\t\t\tbreak;\n\t\t\t\tcase BPE_Used_Laboratories:\n\t\t\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_FACILITY_IN_USE_LABORATORIES\"), _palette, errorColor1, \"BACK13.SCR\", errorColor2));\n\t\t\t\t\tbreak;\n\t\t\t\tcase BPE_Used_Workshops:\n\t\t\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_FACILITY_IN_USE_WORKSHOPS\"), _palette, errorColor1, \"BACK13.SCR\", errorColor2));\n\t\t\t\t\tbreak;\n\t\t\t\tcase BPE_Used_Hangars:\n\t\t\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_FACILITY_IN_USE_HANGARS\"), _palette, errorColor1, \"BACK13.SCR\", errorColor2));\n\t\t\t\t\tbreak;\n\t\t\t\tcase BPE_Used_PsiLabs:\n\t\t\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_FACILITY_IN_USE_PSI_LABS\"), _palette, errorColor1, \"BACK13.SCR\", errorColor2));\n\t\t\t\t\tbreak;\n\t\t\t\tcase BPE_Used_Gyms:\n\t\t\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_FACILITY_IN_USE_GYMS\"), _palette, errorColor1, \"BACK13.SCR\", errorColor2));\n\t\t\t\t\tbreak;\n\t\t\t\tcase BPE_Used_AlienContainment:\n\t\t\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_FACILITY_IN_USE_PRISONS\"), _palette, errorColor1, \"BACK13.SCR\", errorColor2));\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_FACILITY_IN_USE\"), _palette, errorColor1, \"BACK13.SCR\", errorColor2));\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Would base become disconnected?\n\t\t\telse if (!_base->getDisconnectedFacilities(fac).empty() && fac->getRules()->getLeavesBehindOnSell().size() == 0)\n\t\t\t{\n\t\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_CANNOT_DISMANTLE_FACILITY\"), _palette, errorColor1, \"BACK13.SCR\", errorColor2));\n\t\t\t}\n\t\t\t// Is this facility being built from a dismantled one or building over a previous building?\n\t\t\telse if (fac->getBuildTime() > 0 && fac->getIfHadPreviousFacility())\n\t\t\t{\n\t\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_CANNOT_DISMANTLE_FACILITY_UPGRADING\"), _palette, errorColor1, \"BACK13.SCR\", errorColor2));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_game->pushState(new DismantleFacilityState(_base, _view, fac));\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Processes right clicking on facilities.\n * @param action Pointer to an action.\n */\nvoid BasescapeState::viewRightClick(Action *)\n{\n\tBaseFacility *f = _view->getSelectedFacility();\n\tif (f == 0)\n\t{\n\t\t_game->pushState(new BaseInfoState(_base, this));\n\t}\n\telse if (f->getRules()->getRightClickActionType() != 0)\n\t{\n\t\tswitch (f->getRules()->getRightClickActionType())\n\t\t{\n\t\t\tcase 1: _game->pushState(new ManageAlienContainmentState(_base, f->getRules()->getPrisonType(), OPT_GEOSCAPE)); break;\n\t\t\tcase 2: _game->pushState(new ManufactureState(_base)); break;\n\t\t\tcase 3: _game->pushState(new ResearchState(_base)); break;\n\t\t\tcase 4: _game->pushState(new AllocateTrainingState(_base)); break;\n\t\t\tcase 5: if (Options::anytimePsiTraining) _game->pushState(new AllocatePsiTrainingState(_base)); break;\n\t\t\tcase 6: _game->pushState(new SoldiersState(_base)); break;\n\t\t\tcase 7: _game->pushState(new SellState(_base, 0)); break;\n\t\t\tdefault: _game->popState(); break;\n\t\t}\n\t}\n\telse if (f->getRules()->isMindShield())\n\t{\n\t\tif (f->getBuildTime() == 0)\n\t\t{\n\t\t\tf->setDisabled(!f->getDisabled());\n\t\t\t_view->draw();\n\t\t\t_mini->draw();\n\t\t}\n\t}\n\telse if (f->getRules()->getCrafts() > 0)\n\t{\n\t\tif (f->getCraftForDrawing() == 0)\n\t\t{\n\t\t\t_game->pushState(new CraftsState(_base));\n\t\t}\n\t\telse\n\t\t\tfor (size_t craft = 0; craft < _base->getCrafts()->size(); ++craft)\n\t\t\t{\n\t\t\t\tif (f->getCraftForDrawing() == _base->getCrafts()->at(craft))\n\t\t\t\t{\n\t\t\t\t\t_game->pushState(new CraftInfoState(_base, craft));\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t}\n\telse if (f->getRules()->getStorage() > 0)\n\t{\n\t\t_game->pushState(new SellState(_base, 0));\n\t}\n\telse if (f->getRules()->getPersonnel() > 0)\n\t{\n\t\t_game->pushState(new SoldiersState(_base));\n\t}\n\telse if (f->getRules()->getPsiLaboratories() > 0 && Options::anytimePsiTraining && _base->getAvailablePsiLabs() > 0)\n\t{\n\t\t_game->pushState(new AllocatePsiTrainingState(_base));\n\t}\n\telse if (f->getRules()->getTrainingFacilities() > 0 && _base->getAvailableTraining() > 0)\n\t{\n\t\t_game->pushState(new AllocateTrainingState(_base));\n\t}\n\telse if (f->getRules()->getLaboratories() > 0)\n\t{\n\t\t_game->pushState(new ResearchState(_base));\n\t}\n\telse if (f->getRules()->getWorkshops() > 0)\n\t{\n\t\t_game->pushState(new ManufactureState(_base));\n\t}\n\telse if (f->getRules()->getAliens() > 0)\n\t{\n\t\t_game->pushState(new ManageAlienContainmentState(_base, f->getRules()->getPrisonType(), OPT_GEOSCAPE));\n\t}\n\telse if (f->getRules()->isLift() || f->getRules()->getRadarRange() > 0)\n\t{\n\t\t_game->popState();\n\t}\n}\n\n/**\n* Opens the corresponding Ufopaedia article.\n* @param action Pointer to an action.\n*/\nvoid BasescapeState::viewMiddleClick(Action *)\n{\n\tBaseFacility *f = _view->getSelectedFacility();\n\tif (f)\n\t{\n\t\tstd::string articleId = f->getRules()->getUfopediaType();\n\t\tUfopaedia::openArticle(_game, articleId);\n\t}\n}\n\n/**\n * Displays the name of the facility the mouse is over.\n * @param action Pointer to an action.\n */\nvoid BasescapeState::viewMouseOver(Action *)\n{\n\tBaseFacility *f = _view->getSelectedFacility();\n\tstd::ostringstream ss;\n\tif (f != 0)\n\t{\n\t\tif (f->getRules()->getCrafts() == 0 || f->getBuildTime() > 0)\n\t\t{\n\t\t\tss << tr(f->getRules()->getType());\n\t\t}\n\t\telse\n\t\t{\n\t\t\tss << tr(f->getRules()->getType());\n\t\t\tif (f->getCraftForDrawing() != 0)\n\t\t\t{\n\t\t\t\tss << \" \" << tr(\"STR_CRAFT_\").arg(f->getCraftForDrawing()->getName(_game->getLanguage()));\n\t\t\t}\n\t\t}\n\t}\n\t_txtFacility->setText(ss.str());\n}\n\n/**\n * Clears the facility name.\n * @param action Pointer to an action.\n */\nvoid BasescapeState::viewMouseOut(Action *)\n{\n\t_txtFacility->setText(\"\");\n}\n\n/**\n * Selects a new base to display.\n * @param action Pointer to an action.\n */\nvoid BasescapeState::miniLeftClick(Action *)\n{\n\tsize_t base = _mini->getHoveredBase();\n\tif (base < _game->getSavedGame()->getBases()->size())\n\t{\n\t\t_base = _game->getSavedGame()->getBases()->at(base);\n\t\tinit();\n\t}\n}\n\n/**\n * Moves the current base to the left in the list of bases.\n * @param action Pointer to an action.\n */\nvoid BasescapeState::miniRightClick(Action *)\n{\n\tsize_t baseIndex = _mini->getHoveredBase();\n\n\tif (baseIndex > 0 && baseIndex < _game->getSavedGame()->getBases()->size())\n\t{\n\t\tauto& bases = *_game->getSavedGame()->getBases();\n\n\t\t// only able to move the currently selected base\n\t\tif (bases[baseIndex] == _base)\n\t\t{\n\t\t\tstd::swap(bases[baseIndex], bases[baseIndex - 1]);\n\t\t\tinit();\n\t\t}\n\t}\n}\n\n/**\n * Selects a new base to display.\n * @param action Pointer to an action.\n */\nvoid BasescapeState::handleKeyPress(Action *action)\n{\n\tif (action->getDetails()->type == SDL_KEYDOWN)\n\t{\n\t\tSDLKey baseKeys[] = {\n\t\t\tOptions::keyBaseSelect1,\n\t\t\tOptions::keyBaseSelect2,\n\t\t\tOptions::keyBaseSelect3,\n\t\t\tOptions::keyBaseSelect4,\n\t\t\tOptions::keyBaseSelect5,\n\t\t\tOptions::keyBaseSelect6,\n\t\t\tOptions::keyBaseSelect7,\n\t\t\tOptions::keyBaseSelect8\n\t\t};\n\t\tint key = action->getDetails()->key.keysym.sym;\n\t\tfor (size_t i = 0; i < _game->getSavedGame()->getBases()->size(); ++i)\n\t\t{\n\t\t\tif (key == baseKeys[i])\n\t\t\t{\n\t\t\t\t_base = _game->getSavedGame()->getBases()->at(i);\n\t\t\t\tinit();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Changes the Base name.\n * @param action Pointer to an action.\n */\nvoid BasescapeState::edtBaseChange(Action *)\n{\n\t_base->setName(_edtBase->getText());\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/BasescapeState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass BaseView;\nclass MiniBaseView;\nclass Text;\nclass TextButton;\nclass TextEdit;\nclass Base;\nclass Globe;\n\n/**\n * Basescape screen that shows a base's layout\n * and lets the player manage their bases.\n */\nclass BasescapeState : public State\n{\nprivate:\n\tBaseView *_view;\n\tMiniBaseView *_mini;\n\tText *_txtFacility, *_txtLocation, *_txtFunds;\n\tTextEdit *_edtBase;\n\tTextButton *_btnNewBase, *_btnBaseInfo, *_btnSoldiers, *_btnCrafts, *_btnFacilities, *_btnResearch, *_btnManufacture, *_btnTransfer, *_btnPurchase, *_btnSell, *_btnGeoscape;\n\tBase *_base;\n\tGlobe *_globe;\npublic:\n\t/// Creates the Basescape state.\n\tBasescapeState(Base *base, Globe *globe);\n\t/// Cleans up the Basescape state.\n\t~BasescapeState();\n\t/// Updates the base stats.\n\tvoid init() override;\n\t/// Sets a new base to display.\n\tvoid setBase(Base *base);\n\t/// Handler for clicking the Build New Base button.\n\tvoid btnNewBaseClick(Action *action);\n\t/// Handler for clicking the Base Information button.\n\tvoid btnBaseInfoClick(Action *action);\n\t/// Handler for clicking the Soldiers button.\n\tvoid btnSoldiersClick(Action *action);\n\t/// Handler for clicking the Equip Craft button.\n\tvoid btnCraftsClick(Action *action);\n\t/// Handler for clicking the Build Facilities button.\n\tvoid btnFacilitiesClick(Action *action);\n\t/// Handler for clicking the Research button.\n\tvoid btnResearchClick(Action *action);\n\t/// Handler for clicking the Manufacture button.\n\tvoid btnManufactureClick(Action *action);\n\t/// Handler for clicking the Purchase/Hire button.\n\tvoid btnPurchaseClick(Action *action);\n\t/// Handler for clicking the Sell/Sack button.\n\tvoid btnSellClick(Action *action);\n\t/// Handler for clicking the Transfer button.\n\tvoid btnTransferClick(Action *action);\n\t/// Handler for clicking the Geoscape button.\n\tvoid btnGeoscapeClick(Action *action);\n\t/// Handler for clicking the base view.\n\tvoid viewLeftClick(Action *action);\n\t/// Handler for right clicking the base view.\n\tvoid viewRightClick(Action *action);\n\t/// Handler for middle clicking the base view.\n\tvoid viewMiddleClick(Action *action);\n\t/// Handler for hovering the base view.\n\tvoid viewMouseOver(Action *action);\n\t/// Handler for hovering out of the base view.\n\tvoid viewMouseOut(Action *action);\n\t/// Handler for clicking the mini base view (left button).\n\tvoid miniLeftClick(Action *action);\n\t/// Handler for clicking the mini base view (right button).\n\tvoid miniRightClick(Action *action);\n\t/// Handler for changing the text on the Name edit.\n\tvoid edtBaseChange(Action *action);\n\t/// Handler for pressing a base selection hotkey.\n\tvoid handleKeyPress(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/BuildFacilitiesState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <algorithm>\n#include \"BuildFacilitiesState.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Mod/RuleBaseFacility.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Base.h\"\n#include \"PlaceFacilityState.h\"\n#include \"../Ufopaedia/Ufopaedia.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Build Facilities window.\n * @param game Pointer to the core game.\n * @param base Pointer to the base to get info from.\n * @param state Pointer to the base state to refresh.\n */\nBuildFacilitiesState::BuildFacilitiesState(Base *base, State *state) : _base(base), _state(state), _lstScroll(0)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 128, 160, 192, 40, POPUP_VERTICAL);\n\t_btnOk = new TextButton(112, 16, 200, 176);\n\t_lstFacilities = new TextList(104, 104, 200, 64);\n\t_txtTitle = new Text(118, 17, 197, 48);\n\n\t// Set palette\n\tsetInterface(\"selectFacility\");\n\n\tadd(_window, \"window\", \"selectFacility\");\n\tadd(_btnOk, \"button\", \"selectFacility\");\n\tadd(_txtTitle, \"text\", \"selectFacility\");\n\tadd(_lstFacilities, \"list\", \"selectFacility\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"selectFacility\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&BuildFacilitiesState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&BuildFacilitiesState::btnOkClick, Options::keyCancel);\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_INSTALLATION\"));\n\n\t_lstFacilities->setColumns(1, 104);\n\t_lstFacilities->setSelectable(true);\n\t_lstFacilities->setBackground(_window);\n\t_lstFacilities->setMargin(2);\n\t_lstFacilities->setWordWrap(true);\n\t_lstFacilities->setScrolling(true, 0);\n\t_lstFacilities->onMouseClick((ActionHandler)&BuildFacilitiesState::lstFacilitiesClick);\n\t_lstFacilities->onMouseClick((ActionHandler)&BuildFacilitiesState::lstFacilitiesClick, SDL_BUTTON_MIDDLE);\n\n}\n\n/**\n *\n */\nBuildFacilitiesState::~BuildFacilitiesState()\n{\n\n}\n\n/**\n * Populates the build list from the current \"available\" facilities.\n */\nvoid BuildFacilitiesState::populateBuildList()\n{\n\t_facilities.clear();\n\t_disabledFacilities.clear();\n\t_lstFacilities->clearList();\n\n\tRuleBaseFacilityFunctions providedBaseFunc = _base->getProvidedBaseFunc({});\n\tRuleBaseFacilityFunctions forbiddenBaseFunc = _base->getForbiddenBaseFunc({});\n\tRuleBaseFacilityFunctions futureBaseFunc = _base->getFutureBaseFunc({});\n\n\tfor (auto& facilityType : _game->getMod()->getBaseFacilitiesList())\n\t{\n\t\tRuleBaseFacility *rule = _game->getMod()->getBaseFacility(facilityType);\n\t\tif (!rule->isAllowedForBaseType(_base->isFakeUnderwater()))\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\t\tif ((rule->isLift() && !rule->isUpgradeOnly())\n\t\t\t|| !_game->getSavedGame()->isResearched(rule->getRequirements()))\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\t\tif (_base->isMaxAllowedLimitReached(rule))\n\t\t{\n\t\t\t_disabledFacilities.push_back(rule);\n\t\t\tcontinue;\n\t\t}\n\t\tRuleBaseFacilityFunctions req = rule->getRequireBaseFunc();\n\t\tRuleBaseFacilityFunctions forb = rule->getForbiddenBaseFunc();\n\t\tRuleBaseFacilityFunctions prov = rule->getProvidedBaseFunc();\n\t\tif ((~providedBaseFunc & req).any())\n\t\t{\n\t\t\t_disabledFacilities.push_back(rule);\n\t\t\tcontinue;\n\t\t}\n\n\t\t// do not check requirements for bulding that can overbuild others, correct check will be done when you will try to place it somewhere\n\t\tif (rule->getBuildOverFacilities().empty())\n\t\t{\n\t\t\tif ((forbiddenBaseFunc & prov).any())\n\t\t\t{\n\t\t\t\t_disabledFacilities.push_back(rule);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif ((futureBaseFunc & forb).any())\n\t\t\t{\n\t\t\t\t_disabledFacilities.push_back(rule);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\t// but we can still check at least the inherent base funcs (of the base country/region)\n\t\telse\n\t\t{\n\t\t\tif ((_base->getInherentForbiddenBaseFunc() & prov).any())\n\t\t\t{\n\t\t\t\t_disabledFacilities.push_back(rule);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif ((_base->getInherentFutureBaseFunc() & forb).any())\n\t\t\t{\n\t\t\t\t_disabledFacilities.push_back(rule);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\t_facilities.push_back(rule);\n\t}\n\n\tint row = 0;\n\tfor (const auto* facRule : _facilities)\n\t{\n\t\t_lstFacilities->addRow(1, tr(facRule->getType()).c_str());\n\t\t++row;\n\t}\n\n\tif (!_disabledFacilities.empty())\n\t{\n\t\tUint8 disabledColor = _lstFacilities->getSecondaryColor();\n\t\tfor (const auto* facRule : _disabledFacilities)\n\t\t{\n\t\t\t_lstFacilities->addRow(1, tr(facRule->getType()).c_str());\n\t\t\t_lstFacilities->setRowColor(row, disabledColor);\n\t\t\t++row;\n\t\t}\n\t}\n\n\tif (_lstScroll > 0)\n\t{\n\t\t_lstFacilities->scrollTo(_lstScroll);\n\t\t_lstScroll = 0;\n\t}\n}\n\n/**\n * The player can change the selected base\n * or change info on other screens.\n */\nvoid BuildFacilitiesState::init()\n{\n\t_state->init();\n\tState::init();\n\n\tpopulateBuildList();\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid BuildFacilitiesState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Places the selected facility.\n * @param action Pointer to an action.\n */\nvoid BuildFacilitiesState::lstFacilitiesClick(Action *action)\n{\n\tauto index = _lstFacilities->getSelectedRow();\n\t_lstScroll = _lstFacilities->getScroll();\n\n\tif (action->getDetails()->button.button == SDL_BUTTON_MIDDLE)\n\t{\n\t\tstd::string tmp = (index >= _facilities.size()) ? _disabledFacilities[index - _facilities.size()]->getUfopediaType() : _facilities[index]->getUfopediaType();\n\t\tUfopaedia::openArticle(_game, tmp);\n\t\treturn;\n\t}\n\n\tif (index >= _facilities.size())\n\t{\n\t\treturn;\n\t}\n\t_game->pushState(new PlaceFacilityState(_base, _facilities[index]));\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/BuildFacilitiesState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <vector>\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass Base;\nclass TextButton;\nclass Window;\nclass Text;\nclass TextList;\nclass RuleBaseFacility;\n\n/**\n * Window shown with all the facilities\n * available to build.\n */\nclass BuildFacilitiesState : public State\n{\nprotected:\n\tBase *_base;\n\tState *_state;\n\tstd::vector<RuleBaseFacility*> _facilities, _disabledFacilities;\n\tsize_t _lstScroll;\n\n\tTextButton *_btnOk;\n\tWindow *_window;\n\tText *_txtTitle;\n\tTextList *_lstFacilities;\npublic:\n\t/// Creates the Build Facilities state.\n\tBuildFacilitiesState(Base *base, State *state);\n\t/// Cleans up the Build Facilities state.\n\t~BuildFacilitiesState();\n\t/// Populates the build option list.\n\tvirtual void populateBuildList();\n\t/// Updates the base stats.\n\tvoid init() override;\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the Facilities list.\n\tvirtual void lstFacilitiesClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/CraftArmorState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"CraftArmorState.h\"\n#include <climits>\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/ComboBox.h\"\n#include \"../Engine/Action.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Menu/ErrorMessageState.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/Soldier.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Craft.h\"\n#include \"../Mod/Armor.h\"\n#include \"SoldierArmorState.h\"\n#include \"../Savegame/ItemContainer.h\"\n#include \"../Mod/RuleInterface.h\"\n#include \"../Mod/RuleSoldier.h\"\n#include \"../Ufopaedia/Ufopaedia.h\"\n#include <algorithm>\n#include \"../Engine/Unicode.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Craft Armor screen.\n * @param game Pointer to the core game.\n * @param base Pointer to the base to get info from.\n * @param craft ID of the selected craft.\n */\nCraftArmorState::CraftArmorState(Base *base, size_t craft) : _base(base), _craft(craft), _savedScrollPosition(0), _origSoldierOrder(*_base->getSoldiers()), _dynGetter(NULL)\n{\n\t// Create objects\n\t_window = new Window(this, 320, 200, 0, 0);\n\t_btnOk = new TextButton(148, 16, 164, 176);\n\t_txtTitle = new Text(300, 17, 16, 7);\n\t_txtName = new Text(114, 9, 16, 32);\n\t_txtCraft = new Text(76, 9, 122, 32);\n\t_txtArmor = new Text(100, 9, 192, 32);\n\t_lstSoldiers = new TextList(288, 128, 8, 40);\n\t_cbxSortBy = new ComboBox(this, 148, 16, 8, 176, true);\n\n\ttouchComponentsCreate(_txtTitle, true);\n\n\t// Set palette\n\tsetInterface(\"craftArmor\");\n\n\tadd(_window, \"window\", \"craftArmor\");\n\tadd(_btnOk, \"button\", \"craftArmor\");\n\tadd(_txtTitle, \"text\", \"craftArmor\");\n\tadd(_txtName, \"text\", \"craftArmor\");\n\tadd(_txtCraft, \"text\", \"craftArmor\");\n\tadd(_txtArmor, \"text\", \"craftArmor\");\n\tadd(_lstSoldiers, \"list\", \"craftArmor\");\n\tadd(_cbxSortBy, \"button\", \"craftArmor\");\n\n\ttouchComponentsAdd(\"button2\", \"craftArmor\", _window);\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"craftArmor\");\n\n\ttouchComponentsConfigure();\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&CraftArmorState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&CraftArmorState::btnOkClick, Options::keyCancel);\n\t_btnOk->onKeyboardPress((ActionHandler)&CraftArmorState::btnDeequipAllArmorClick, Options::keyRemoveArmorFromAllCrafts);\n\t_btnOk->onKeyboardPress((ActionHandler)&CraftArmorState::btnDeequipCraftArmorClick, Options::keyRemoveArmorFromCraft);\n\n\t_txtTitle->setBig();\n\t_txtTitle->setText(tr(\"STR_SELECT_ARMOR\"));\n\n\t_txtName->setText(tr(\"STR_NAME_UC\"));\n\n\t_txtCraft->setText(tr(\"STR_CRAFT\"));\n\n\t_txtArmor->setText(tr(\"STR_ARMOR\"));\n\n\t// populate sort options\n\tstd::vector<std::string> sortOptions;\n\tsortOptions.push_back(tr(\"STR_ORIGINAL_ORDER\"));\n\t_sortFunctors.push_back(NULL);\n\n#define PUSH_IN(strId, functor) \\\n\tsortOptions.push_back(tr(strId)); \\\n\t_sortFunctors.push_back(new SortFunctor(_game, functor));\n\n\tPUSH_IN(\"STR_ID\", idStat);\n\tPUSH_IN(\"STR_NAME_UC\", nameStat);\n\tPUSH_IN(\"STR_CRAFT\", craftIdStat);\n\tPUSH_IN(\"STR_SOLDIER_TYPE\", typeStat);\n\tPUSH_IN(\"STR_RANK\", rankStat);\n\tPUSH_IN(\"STR_IDLE_DAYS\", idleDaysStat);\n\tPUSH_IN(\"STR_MISSIONS2\", missionsStat);\n\tPUSH_IN(\"STR_KILLS2\", killsStat);\n\tPUSH_IN(\"STR_WOUND_RECOVERY2\", woundRecoveryStat);\n\tif (_game->getMod()->isManaFeatureEnabled() && !_game->getMod()->getReplenishManaAfterMission())\n\t{\n\t\tPUSH_IN(\"STR_MANA_MISSING\", manaMissingStat);\n\t}\n\tPUSH_IN(\"STR_TIME_UNITS\", tuStat);\n\tPUSH_IN(\"STR_STAMINA\", staminaStat);\n\tPUSH_IN(\"STR_HEALTH\", healthStat);\n\tPUSH_IN(\"STR_BRAVERY\", braveryStat);\n\tPUSH_IN(\"STR_REACTIONS\", reactionsStat);\n\tPUSH_IN(\"STR_FIRING_ACCURACY\", firingStat);\n\tPUSH_IN(\"STR_THROWING_ACCURACY\", throwingStat);\n\tPUSH_IN(\"STR_MELEE_ACCURACY\", meleeStat);\n\tPUSH_IN(\"STR_STRENGTH\", strengthStat);\n\tif (_game->getMod()->isManaFeatureEnabled())\n\t{\n\t\t// \"unlock\" is checked later\n\t\tPUSH_IN(\"STR_MANA_POOL\", manaStat);\n\t}\n\tPUSH_IN(\"STR_PSIONIC_STRENGTH\", psiStrengthStat);\n\tPUSH_IN(\"STR_PSIONIC_SKILL\", psiSkillStat);\n\n#undef PUSH_IN\n\n\t_cbxSortBy->setOptions(sortOptions);\n\t_cbxSortBy->setSelected(0);\n\t_cbxSortBy->onChange((ActionHandler)&CraftArmorState::cbxSortByChange);\n\t_cbxSortBy->setText(tr(\"STR_SORT_BY\"));\n\n\t_lstSoldiers->setColumns(3, 106, 70, 104);\n\t_lstSoldiers->setAlign(ALIGN_RIGHT, 3);\n\t_lstSoldiers->setSelectable(true);\n\t_lstSoldiers->setBackground(_window);\n\t_lstSoldiers->setMargin(8);\n\t_lstSoldiers->onLeftArrowClick((ActionHandler)&CraftArmorState::lstItemsLeftArrowClick);\n\t_lstSoldiers->onRightArrowClick((ActionHandler)&CraftArmorState::lstItemsRightArrowClick);\n\t_lstSoldiers->onMouseClick((ActionHandler)&CraftArmorState::lstSoldiersClick, 0);\n\t_lstSoldiers->onMousePress((ActionHandler)&CraftArmorState::lstSoldiersMousePress);\n}\n\n/**\n * cleans up dynamic state\n */\nCraftArmorState::~CraftArmorState()\n{\n\tfor (auto* sortFunctor : _sortFunctors)\n\t{\n\t\tdelete sortFunctor;\n\t}\n}\n\n/**\n * Sorts the soldiers list by the selected criterion\n * @param action Pointer to an action.\n */\nvoid CraftArmorState::cbxSortByChange(Action *action)\n{\n\tbool ctrlPressed = _game->isCtrlPressed(true);\n\tsize_t selIdx = _cbxSortBy->getSelected();\n\tif (selIdx == (size_t)-1)\n\t{\n\t\treturn;\n\t}\n\n\tSortFunctor *compFunc = _sortFunctors[selIdx];\n\t_dynGetter = NULL;\n\tif (compFunc)\n\t{\n\t\tif (selIdx != 2 && selIdx != 3)\n\t\t{\n\t\t\t_dynGetter = compFunc->getGetter();\n\t\t}\n\n\t\t// if CTRL is pressed, we only want to show the dynamic column, without actual sorting\n\t\tif (!ctrlPressed)\n\t\t{\n\t\t\tif (selIdx == 2)\n\t\t\t{\n\t\t\t\tstd::stable_sort(_base->getSoldiers()->begin(), _base->getSoldiers()->end(),\n\t\t\t\t\t[](const Soldier* a, const Soldier* b)\n\t\t\t\t\t{\n\t\t\t\t\t\treturn Unicode::naturalCompare(a->getName(), b->getName());\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t}\n\t\t\telse if (selIdx == 3)\n\t\t\t{\n\t\t\t\tstd::stable_sort(_base->getSoldiers()->begin(), _base->getSoldiers()->end(),\n\t\t\t\t\t[](const Soldier* a, const Soldier* b)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (a->getCraft())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (b->getCraft())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (a->getCraft()->getRules() == b->getCraft()->getRules())\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\treturn a->getCraft()->getId() < b->getCraft()->getId();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\treturn a->getCraft()->getRules() < b->getCraft()->getRules();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\treturn true; // a < b\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn false; // b > a\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tstd::stable_sort(_base->getSoldiers()->begin(), _base->getSoldiers()->end(), *compFunc);\n\t\t\t}\n\t\t\tif (_game->isShiftPressed(true))\n\t\t\t{\n\t\t\t\tstd::reverse(_base->getSoldiers()->begin(), _base->getSoldiers()->end());\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\t// restore original ordering, ignoring (of course) those\n\t\t// soldiers that have been sacked since this state started\n\t\tfor (const auto* origSoldier : _origSoldierOrder)\n\t\t{\n\t\t\tauto soldierIt = std::find(_base->getSoldiers()->begin(), _base->getSoldiers()->end(), origSoldier);\n\t\t\tif (soldierIt != _base->getSoldiers()->end())\n\t\t\t{\n\t\t\t\tSoldier *s = *soldierIt;\n\t\t\t\t_base->getSoldiers()->erase(soldierIt);\n\t\t\t\t_base->getSoldiers()->insert(_base->getSoldiers()->end(), s);\n\t\t\t}\n\t\t}\n\t}\n\n\tinitList(_lstSoldiers->getScroll());\n}\n\n/**\n * The soldier armors can change\n * after going into other screens.\n */\nvoid CraftArmorState::init()\n{\n\tState::init();\n\t_base->prepareSoldierStatsWithBonuses(); // refresh stats for sorting\n\tinitList(_savedScrollPosition);\n\n\tint row = 0;\n\tfor (const auto* soldier : *_base->getSoldiers())\n\t{\n\t\t_lstSoldiers->setCellText(row, 2, tr(soldier->getArmor()->getType()));\n\t\trow++;\n\t}\n\n\ttouchComponentsRefresh();\n}\n\n/**\n * Shows the soldiers in a list at specified offset/scroll.\n */\nvoid CraftArmorState::initList(size_t scrl)\n{\n\tUint8 otherCraftColor = _game->getMod()->getInterface(\"craftArmor\")->getElement(\"otherCraft\")->color;\n\tint row = 0;\n\t_lstSoldiers->clearList();\n\n\tif (_dynGetter != NULL)\n\t{\n\t\t_lstSoldiers->setArrowColumn(160, ARROW_VERTICAL);\n\t\t_lstSoldiers->setColumns(4, 106, 70, 88, 16);\n\t}\n\telse\n\t{\n\t\t_lstSoldiers->setArrowColumn(-1, ARROW_VERTICAL);\n\t\t_lstSoldiers->setColumns(3, 106, 70, 104);\n\t}\n\n\tCraft *c = _base->getCrafts()->at(_craft);\n\tBaseSumDailyRecovery recovery = _base->getSumRecoveryPerDay();\n\tfor (const auto* soldier : *_base->getSoldiers())\n\t{\n\t\tif (_dynGetter != NULL)\n\t\t{\n\t\t\t// call corresponding getter\n\t\t\tint dynStat = (*_dynGetter)(_game, soldier);\n\t\t\tstd::ostringstream ss;\n\t\t\tss << dynStat;\n\t\t\t_lstSoldiers->addRow(4, soldier->getName(true).c_str(), soldier->getCraftString(_game->getLanguage(), recovery).c_str(), tr(soldier->getArmor()->getType()).c_str(), ss.str().c_str());\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_lstSoldiers->addRow(3, soldier->getName(true).c_str(), soldier->getCraftString(_game->getLanguage(), recovery).c_str(), tr(soldier->getArmor()->getType()).c_str());\n\t\t}\n\n\t\tUint8 color;\n\t\tif (soldier->getCraft() == c)\n\t\t{\n\t\t\tcolor = _lstSoldiers->getSecondaryColor();\n\t\t}\n\t\telse if (soldier->getCraft() != 0)\n\t\t{\n\t\t\tcolor = otherCraftColor;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tcolor = _lstSoldiers->getColor();\n\t\t}\n\t\t_lstSoldiers->setRowColor(row, color);\n\t\trow++;\n\t}\n\tif (scrl)\n\t\t_lstSoldiers->scrollTo(scrl);\n\t_lstSoldiers->draw();\n}\n\n/**\n * Reorders a soldier up.\n * @param action Pointer to an action.\n */\nvoid CraftArmorState::lstItemsLeftArrowClick(Action *action)\n{\n\tunsigned int row = _lstSoldiers->getSelectedRow();\n\tif (row > 0)\n\t{\n\t\tif (_game->isLeftClick(action, true))\n\t\t{\n\t\t\tmoveSoldierUp(action, row);\n\t\t}\n\t\telse if (_game->isRightClick(action, true))\n\t\t{\n\t\t\tmoveSoldierUp(action, row, true);\n\t\t}\n\t}\n\t_cbxSortBy->setText(tr(\"STR_SORT_BY\"));\n\t_cbxSortBy->setSelected(-1);\n}\n\n/**\n * Moves a soldier up on the list.\n * @param action Pointer to an action.\n * @param row Selected soldier row.\n * @param max Move the soldier to the top?\n */\nvoid CraftArmorState::moveSoldierUp(Action *action, unsigned int row, bool max)\n{\n\tSoldier *s = _base->getSoldiers()->at(row);\n\tif (max)\n\t{\n\t\t_base->getSoldiers()->erase(_base->getSoldiers()->begin() + row);\n\t\t_base->getSoldiers()->insert(_base->getSoldiers()->begin(), s);\n\t}\n\telse\n\t{\n\t\t_base->getSoldiers()->at(row) = _base->getSoldiers()->at(row - 1);\n\t\t_base->getSoldiers()->at(row - 1) = s;\n\t\tif (row != _lstSoldiers->getScroll())\n\t\t{\n\t\t\tSDL_WarpMouse(action->getLeftBlackBand() + action->getXMouse(), action->getTopBlackBand() + action->getYMouse() - static_cast<Uint16>(8 * action->getYScale()));\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_lstSoldiers->scrollUp(false);\n\t\t}\n\t}\n\tinitList(_lstSoldiers->getScroll());\n}\n\n/**\n * Reorders a soldier down.\n * @param action Pointer to an action.\n */\nvoid CraftArmorState::lstItemsRightArrowClick(Action *action)\n{\n\tunsigned int row = _lstSoldiers->getSelectedRow();\n\tsize_t numSoldiers = _base->getSoldiers()->size();\n\tif (0 < numSoldiers && INT_MAX >= numSoldiers && row < numSoldiers - 1)\n\t{\n\t\tif (_game->isLeftClick(action, true))\n\t\t{\n\t\t\tmoveSoldierDown(action, row);\n\t\t}\n\t\telse if (_game->isRightClick(action, true))\n\t\t{\n\t\t\tmoveSoldierDown(action, row, true);\n\t\t}\n\t}\n\t_cbxSortBy->setText(tr(\"STR_SORT_BY\"));\n\t_cbxSortBy->setSelected(-1);\n}\n\n/**\n * Moves a soldier down on the list.\n * @param action Pointer to an action.\n * @param row Selected soldier row.\n * @param max Move the soldier to the bottom?\n */\nvoid CraftArmorState::moveSoldierDown(Action *action, unsigned int row, bool max)\n{\n\tSoldier *s = _base->getSoldiers()->at(row);\n\tif (max)\n\t{\n\t\t_base->getSoldiers()->erase(_base->getSoldiers()->begin() + row);\n\t\t_base->getSoldiers()->insert(_base->getSoldiers()->end(), s);\n\t}\n\telse\n\t{\n\t\t_base->getSoldiers()->at(row) = _base->getSoldiers()->at(row + 1);\n\t\t_base->getSoldiers()->at(row + 1) = s;\n\t\tif (row != _lstSoldiers->getVisibleRows() - 1 + _lstSoldiers->getScroll())\n\t\t{\n\t\t\tSDL_WarpMouse(action->getLeftBlackBand() + action->getXMouse(), action->getTopBlackBand() + action->getYMouse() + static_cast<Uint16>(8 * action->getYScale()));\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_lstSoldiers->scrollDown(false);\n\t\t}\n\t}\n\tinitList(_lstSoldiers->getScroll());\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid CraftArmorState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Shows the Select Armor window.\n * @param action Pointer to an action.\n */\nvoid CraftArmorState::lstSoldiersClick(Action *action)\n{\n\tdouble mx = action->getAbsoluteXMouse();\n\tif (mx >= _lstSoldiers->getArrowsLeftEdge() && mx < _lstSoldiers->getArrowsRightEdge())\n\t{\n\t\treturn;\n\t}\n\n\tSoldier *s = _base->getSoldiers()->at(_lstSoldiers->getSelectedRow());\n\tif (!(s->getCraft() && s->getCraft()->getStatus() == \"STR_OUT\"))\n\t{\n\t\tif (_game->isLeftClick(action, true))\n\t\t{\n\t\t\tif (_game->isCtrlPressed(true))\n\t\t\t{\n\t\t\t\tCraft* c = _base->getCrafts()->at(_craft);\n\t\t\t\tif (s->getCraft() == c)\n\t\t\t\t{\n\t\t\t\t\ts->setCraftAndMoveEquipment(0, _base, _game->getSavedGame()->getMonthsPassed() == -1);\n\t\t\t\t\t_lstSoldiers->setCellText(_lstSoldiers->getSelectedRow(), 1, tr(\"STR_NONE_UC\"));\n\t\t\t\t\t_lstSoldiers->setRowColor(_lstSoldiers->getSelectedRow(), _lstSoldiers->getColor());\n\t\t\t\t}\n\t\t\t\telse if (s->hasFullHealth())\n\t\t\t\t{\n\t\t\t\t\tint space = c->getSpaceAvailable();\n\t\t\t\t\tCraftPlacementErrors err = c->validateAddingSoldier(space, s);\n\t\t\t\t\tif (err == CPE_None)\n\t\t\t\t\t{\n\t\t\t\t\t\ts->setCraftAndMoveEquipment(c, _base, _game->getSavedGame()->getMonthsPassed() == -1, true);\n\t\t\t\t\t\t_lstSoldiers->setCellText(_lstSoldiers->getSelectedRow(), 1, c->getName(_game->getLanguage()));\n\t\t\t\t\t\t_lstSoldiers->setRowColor(_lstSoldiers->getSelectedRow(), _lstSoldiers->getSecondaryColor());\n\t\t\t\t\t}\n\t\t\t\t\telse if (err == CPE_SoldierGroupNotAllowed)\n\t\t\t\t\t{\n\t\t\t\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_SOLDIER_GROUP_NOT_ALLOWED\"), _palette, _game->getMod()->getInterface(\"soldierInfo\")->getElement(\"errorMessage\")->color, \"BACK01.SCR\", _game->getMod()->getInterface(\"soldierInfo\")->getElement(\"errorPalette\")->color));\n\t\t\t\t\t}\n\t\t\t\t\telse if (err == CPE_SoldierGroupNotSame)\n\t\t\t\t\t{\n\t\t\t\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_SOLDIER_GROUP_NOT_SAME\"), _palette, _game->getMod()->getInterface(\"soldierInfo\")->getElement(\"errorMessage\")->color, \"BACK01.SCR\", _game->getMod()->getInterface(\"soldierInfo\")->getElement(\"errorPalette\")->color));\n\t\t\t\t\t}\n\t\t\t\t\telse if (err == CPE_ArmorGroupNotAllowed)\n\t\t\t\t\t{\n\t\t\t\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_ARMOR_GROUP_NOT_ALLOWED\"), _palette, _game->getMod()->getInterface(\"soldierInfo\")->getElement(\"errorMessage\")->color, \"BACK01.SCR\", _game->getMod()->getInterface(\"soldierInfo\")->getElement(\"errorPalette\")->color));\n\t\t\t\t\t}\n\t\t\t\t\telse if (space > 0)\n\t\t\t\t\t{\n\t\t\t\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_NOT_ENOUGH_CRAFT_SPACE\"), _palette, _game->getMod()->getInterface(\"soldierInfo\")->getElement(\"errorMessage\")->color, \"BACK01.SCR\", _game->getMod()->getInterface(\"soldierInfo\")->getElement(\"errorPalette\")->color));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_savedScrollPosition = _lstSoldiers->getScroll();\n\t\t\t\t_game->pushState(new SoldierArmorState(_base, _lstSoldiers->getSelectedRow(), SA_GEOSCAPE));\n\t\t\t}\n\t\t}\n\t\telse if (_game->isRightClick(action, true))\n\t\t{\n\t\t\tSavedGame *save;\n\t\t\tsave = _game->getSavedGame();\n\t\t\tArmor *a = _game->isCtrlPressed(true) ? s->getRules()->getDefaultArmor() : _game->getMod()->getArmor(save->getLastSelectedArmor());\n\t\t\tbool armorUnlocked = true;\n\t\t\tif (a && a->getRequiredResearch() && !_game->getSavedGame()->isResearched(a->getRequiredResearch()))\n\t\t\t{\n\t\t\t\tarmorUnlocked = false;\n\t\t\t}\n\t\t\tif (armorUnlocked && a)\n\t\t\t{\n\t\t\t\tCraft* craft = s->getCraft();\n\t\t\t\tif (craft && !craft->validateArmorChange(s->getArmor()->getSize(), a->getSize()))\n\t\t\t\t{\n\t\t\t\t\tarmorUnlocked = false; // armor not valid due to craft constraints\n\t\t\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_NOT_ENOUGH_CRAFT_SPACE\"), _palette, _game->getMod()->getInterface(\"soldierInfo\")->getElement(\"errorMessage\")->color, \"BACK01.SCR\", _game->getMod()->getInterface(\"soldierInfo\")->getElement(\"errorPalette\")->color));\n\t\t\t\t}\n\t\t\t}\n\t\t\t//if (armorUnlocked && a && a->getRequiredBonus())\n\t\t\t{\n\t\t\t\t// refresh soldier's _bonusCache, needed below in Armor::getCanBeUsedBy()\n\t\t\t\t//s->getBonuses(_game->getMod());\n\t\t\t}\n\t\t\tif (armorUnlocked && a && a->getCanBeUsedBy(s))\n\t\t\t{\n\t\t\t\tif (save->getMonthsPassed() != -1)\n\t\t\t\t{\n\t\t\t\t\tif (a->getStoreItem() == nullptr ||\n\t\t\t\t\t\ta->getStoreItem() == s->getArmor()->getStoreItem() ||\n\t\t\t\t\t\t_base->getStorageItems()->getItem(a->getStoreItem()) > 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (s->getArmor()->getStoreItem())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_base->getStorageItems()->addItem(s->getArmor()->getStoreItem());\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (a->getStoreItem())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_base->getStorageItems()->removeItem(a->getStoreItem());\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ts->setArmor(a, true);\n\t\t\t\t\t\ts->prepareStatsWithBonuses(_game->getMod()); // refresh stats for sorting\n\t\t\t\t\t\t_lstSoldiers->setCellText(_lstSoldiers->getSelectedRow(), 2, tr(a->getType()));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\ts->setArmor(a, true);\n\t\t\t\t\ts->prepareStatsWithBonuses(_game->getMod()); // refresh stats for sorting\n\t\t\t\t\t_lstSoldiers->setCellText(_lstSoldiers->getSelectedRow(), 2, tr(a->getType()));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse if (_game->isMiddleClick(action, true))\n\t\t{\n\t\t\tstd::string articleId = s->getArmor()->getUfopediaType();\n\t\t\tUfopaedia::openArticle(_game, articleId);\n\t\t}\n\t}\n}\n\n/**\n * Handles the mouse-wheels on the arrow-buttons.\n * @param action Pointer to an action.\n */\nvoid CraftArmorState::lstSoldiersMousePress(Action *action)\n{\n\tif (Options::changeValueByMouseWheel == 0)\n\t\treturn;\n\tunsigned int row = _lstSoldiers->getSelectedRow();\n\tsize_t numSoldiers = _base->getSoldiers()->size();\n\tif (action->getDetails()->button.button == SDL_BUTTON_WHEELUP &&\n\t\trow > 0)\n\t{\n\t\tif (action->getAbsoluteXMouse() >= _lstSoldiers->getArrowsLeftEdge() &&\n\t\t\taction->getAbsoluteXMouse() <= _lstSoldiers->getArrowsRightEdge())\n\t\t{\n\t\t\tmoveSoldierUp(action, row);\n\t\t}\n\t}\n\telse if (action->getDetails()->button.button == SDL_BUTTON_WHEELDOWN &&\n\t\t0 < numSoldiers && INT_MAX >= numSoldiers && row < numSoldiers - 1)\n\t{\n\t\tif (action->getAbsoluteXMouse() >= _lstSoldiers->getArrowsLeftEdge() &&\n\t\t\taction->getAbsoluteXMouse() <= _lstSoldiers->getArrowsRightEdge())\n\t\t{\n\t\t\tmoveSoldierDown(action, row);\n\t\t}\n\t}\n}\n\n/**\n * De-equip armor from all soldiers located in the base (i.e. not out on a mission).\n * @param action Pointer to an action.\n */\nvoid CraftArmorState::btnDeequipAllArmorClick(Action *action)\n{\n\tint row = 0;\n\tfor (auto* soldier : *_base->getSoldiers())\n\t{\n\t\tif (!(soldier->getCraft() && soldier->getCraft()->getStatus() == \"STR_OUT\"))\n\t\t{\n\t\t\tArmor *a = soldier->getRules()->getDefaultArmor();\n\n\t\t\tif (soldier->getCraft() && !soldier->getCraft()->validateArmorChange(soldier->getArmor()->getSize(), a->getSize()))\n\t\t\t{\n\t\t\t\t// silently ignore\n\t\t\t\trow++;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (a->getStoreItem() == nullptr || _base->getStorageItems()->getItem(a->getStoreItem()) > 0)\n\t\t\t{\n\t\t\t\tif (soldier->getArmor()->getStoreItem())\n\t\t\t\t{\n\t\t\t\t\t_base->getStorageItems()->addItem(soldier->getArmor()->getStoreItem());\n\t\t\t\t}\n\t\t\t\tif (a->getStoreItem())\n\t\t\t\t{\n\t\t\t\t\t_base->getStorageItems()->removeItem(a->getStoreItem());\n\t\t\t\t}\n\n\t\t\t\tsoldier->setArmor(a, true);\n\t\t\t\tsoldier->prepareStatsWithBonuses(_game->getMod()); // refresh stats for sorting\n\t\t\t\t_lstSoldiers->setCellText(row, 2, tr(a->getType()));\n\t\t\t}\n\t\t}\n\t\trow++;\n\t}\n}\n\n/**\n * De-equip armor of all soldiers on the current craft, and also all soldiers not assigned to any craft.\n * @param action Pointer to an action.\n */\nvoid CraftArmorState::btnDeequipCraftArmorClick(Action *action)\n{\n\tCraft *c = _base->getCrafts()->at(_craft);\n\tint row = 0;\n\tfor (auto* s : *_base->getSoldiers())\n\t{\n\t\tif (s->getCraft() == c || s->getCraft() == 0)\n\t\t{\n\t\t\tArmor *a = s->getRules()->getDefaultArmor();\n\n\t\t\tif (s->getCraft() && !s->getCraft()->validateArmorChange(s->getArmor()->getSize(), a->getSize()))\n\t\t\t{\n\t\t\t\t// silently ignore\n\t\t\t\trow++;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (a->getStoreItem() == nullptr || _base->getStorageItems()->getItem(a->getStoreItem()) > 0)\n\t\t\t{\n\t\t\t\tif (s->getArmor()->getStoreItem())\n\t\t\t\t{\n\t\t\t\t\t_base->getStorageItems()->addItem(s->getArmor()->getStoreItem());\n\t\t\t\t}\n\t\t\t\tif (a->getStoreItem())\n\t\t\t\t{\n\t\t\t\t\t_base->getStorageItems()->removeItem(a->getStoreItem());\n\t\t\t\t}\n\n\t\t\t\ts->setArmor(a, true);\n\t\t\t\ts->prepareStatsWithBonuses(_game->getMod()); // refresh stats for sorting\n\t\t\t\t_lstSoldiers->setCellText(row, 2, tr(a->getType()));\n\t\t\t}\n\t\t}\n\t\trow++;\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/CraftArmorState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/TouchState.h\"\n#include <vector>\n#include \"SoldierSortUtil.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass TextList;\nclass ComboBox;\nclass Base;\nclass Soldier;\nstruct SortFunctor;\n\n/**\n * Select Armor screen that lets the player\n * pick armor for the soldiers on the craft.\n */\nclass CraftArmorState : public TouchState\n{\nprivate:\n\tTextButton *_btnOk;\n\tWindow *_window;\n\tText *_txtTitle, *_txtName, *_txtCraft, *_txtArmor;\n\tComboBox *_cbxSortBy;\n\tTextList *_lstSoldiers;\n\n\tBase *_base;\n\tsize_t _craft, _savedScrollPosition;\n\tstd::vector<Soldier *> _origSoldierOrder;\n\tstd::vector<SortFunctor *> _sortFunctors;\n\tgetStatFn_t _dynGetter;\n\t///initializes the display list based on the craft soldier's list and the position to display\n\tvoid initList(size_t scrl);\npublic:\n\t/// Creates the Craft Armor state.\n\tCraftArmorState(Base *base, size_t craft);\n\t/// Cleans up the Craft Armor state.\n\t~CraftArmorState();\n\t/// Handler for changing the sort by combobox.\n\tvoid cbxSortByChange(Action *action);\n\t/// Updates the soldier armors.\n\tvoid init() override;\n\t/// Handler for clicking the Soldiers reordering button.\n\tvoid lstItemsLeftArrowClick(Action *action);\n\t/// Moves a soldier up.\n\tvoid moveSoldierUp(Action *action, unsigned int row, bool max = false);\n\t/// Handler for clicking the Soldiers reordering button.\n\tvoid lstItemsRightArrowClick(Action *action);\n\t/// Moves a soldier down.\n\tvoid moveSoldierDown(Action *action, unsigned int row, bool max = false);\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the Soldiers list.\n\tvoid lstSoldiersClick(Action *action);\n\t/// Handler for pressing-down a mouse-button in the list.\n\tvoid lstSoldiersMousePress(Action *action);\n\t/// Handler for clicking the De-equip All Armor button.\n\tvoid btnDeequipAllArmorClick(Action *action);\n\tvoid btnDeequipCraftArmorClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/CraftEquipmentLoadState.cpp",
    "content": "/*\n* Copyright 2010-2015 OpenXcom Developers.\n*\n* This file is part of OpenXcom.\n*\n* OpenXcom is free software: you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation, either version 3 of the License, or\n* (at your option) any later version.\n*\n* OpenXcom is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*\n* You should have received a copy of the GNU General Public License\n* along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n*/\n#include \"CraftEquipmentLoadState.h\"\n#include \"CraftEquipmentState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/ToggleTextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Savegame/ItemContainer.h\"\n#include \"../Savegame/SavedGame.h\"\n\nnamespace OpenXcom\n{\n\n/**\n* Initializes all the elements in the Load Craft Loadout window.\n*/\nCraftEquipmentLoadState::CraftEquipmentLoadState(CraftEquipmentState *parent) : _parent(parent)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 240, 136, 40, 36+1, POPUP_BOTH);\n\t_txtTitle = new Text(230, 16, 45, 44+3);\n\t_lstLoadout = new TextList(208, 80, 48, 60);\n\t_btnOnlyAdd = new ToggleTextButton(100, 16, 56, 148);\n\t_btnCancel = new TextButton(100, 16, 164, 148);\n\n\t// Set palette\n\tsetInterface(\"craftEquipmentLoad\");\n\n\tadd(_window, \"window\", \"craftEquipmentLoad\");\n\tadd(_txtTitle, \"text\", \"craftEquipmentLoad\");\n\tadd(_lstLoadout, \"list\", \"craftEquipmentLoad\");\n\tadd(_btnOnlyAdd, \"button\", \"craftEquipmentLoad\");\n\tadd(_btnCancel, \"button\", \"craftEquipmentLoad\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"craftEquipmentLoad\");\n\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_LOAD_CRAFT_LOADOUT_TEMPLATE\"));\n\n\t_lstLoadout->setColumns(1, 192);\n\t_lstLoadout->setSelectable(true);\n\t_lstLoadout->setBackground(_window);\n\t_lstLoadout->setMargin(8);\n\t_lstLoadout->onMouseClick((ActionHandler)&CraftEquipmentLoadState::lstLoadoutClick);\n\n\t_btnOnlyAdd->setText(tr(\"STR_ADD_ON_TOP\"));\n\n\t_btnCancel->setText(tr(\"STR_CANCEL_UC\"));\n\t_btnCancel->onMouseClick((ActionHandler)&CraftEquipmentLoadState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&CraftEquipmentLoadState::btnCancelClick, Options::keyCancel);\n\n\tfor (int i = 0; i < SavedGame::MAX_CRAFT_LOADOUT_TEMPLATES; ++i)\n\t{\n\t\tItemContainer *item = _game->getSavedGame()->getGlobalCraftLoadout(i);\n\t\tif (item->getContents()->empty())\n\t\t{\n\t\t\t_lstLoadout->addRow(1, tr(\"STR_EMPTY_SLOT_N\").arg(i + 1).c_str());\n\t\t}\n\t\telse\n\t\t{\n\t\t\tconst std::string &itemName = _game->getSavedGame()->getGlobalCraftLoadoutName(i);\n\t\t\tif (itemName.empty())\n\t\t\t{\n\t\t\t\t_lstLoadout->addRow(1, tr(\"STR_UNNAMED_SLOT_N\").arg(i + 1).c_str());\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_lstLoadout->addRow(1, itemName.c_str());\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n*\n*/\nCraftEquipmentLoadState::~CraftEquipmentLoadState()\n{\n\n}\n\n/**\n* Returns to the previous screen.\n* @param action Pointer to an action.\n*/\nvoid CraftEquipmentLoadState::btnCancelClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n* Loads the template and returns to the previous screen.\n* @param action Pointer to an action.\n*/\nvoid CraftEquipmentLoadState::lstLoadoutClick(Action *)\n{\n\t_game->popState();\n\tbool addOnTop = _btnOnlyAdd->getPressed() || _game->isCtrlPressed();\n\t_parent->loadGlobalLoadout(_lstLoadout->getSelectedRow(), addOnTop);\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/CraftEquipmentLoadState.h",
    "content": "#pragma once\n/*\n* Copyright 2010-2015 OpenXcom Developers.\n*\n* This file is part of OpenXcom.\n*\n* OpenXcom is free software: you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation, either version 3 of the License, or\n* (at your option) any later version.\n*\n* OpenXcom is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*\n* You should have received a copy of the GNU General Public License\n* along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n*/\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass ToggleTextButton;\nclass Window;\nclass Text;\nclass TextList;\nclass CraftEquipmentState;\n\n/**\n* Craft Loadout Load window that allows changing of the equipment onboard.\n*/\nclass CraftEquipmentLoadState : public State\n{\nprivate:\n\tCraftEquipmentState *_parent;\n\tWindow *_window;\n\tText *_txtTitle;\n\tTextList *_lstLoadout;\n\tToggleTextButton *_btnOnlyAdd;\n\tTextButton *_btnCancel;\npublic:\n\t/// Creates the Load Craft Loadout state.\n\tCraftEquipmentLoadState(CraftEquipmentState *parent);\n\t/// Cleans up the Load Craft Loadout state.\n\t~CraftEquipmentLoadState();\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action *action);\n\t/// Handler for clicking the Loadout list.\n\tvoid lstLoadoutClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/CraftEquipmentSaveState.cpp",
    "content": "/*\n* Copyright 2010-2015 OpenXcom Developers.\n*\n* This file is part of OpenXcom.\n*\n* OpenXcom is free software: you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation, either version 3 of the License, or\n* (at your option) any later version.\n*\n* OpenXcom is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*\n* You should have received a copy of the GNU General Public License\n* along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n*/\n#include \"CraftEquipmentSaveState.h\"\n#include \"CraftEquipmentState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Language.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextEdit.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Savegame/ItemContainer.h\"\n#include \"../Savegame/SavedGame.h\"\n\nnamespace OpenXcom\n{\n\n/**\n* Initializes all the elements in the Save Craft Loadout window.\n*/\nCraftEquipmentSaveState::CraftEquipmentSaveState(CraftEquipmentState *parent) : _parent(parent), _previousSelectedRow(-1), _selectedRow(-1)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 240, 136, 40, 36 + 1, POPUP_BOTH);\n\t_txtTitle = new Text(230, 16, 45, 44 + 3);\n\t_lstLoadout = new TextList(208, 80, 48, 60);\n\t_btnCancel = new TextButton(80, 16, 165, 148);\n\t_btnSave = new TextButton(80, 16, 75, 148);\n\t_edtSave = new TextEdit(this, 188, 9, 0, 0);\n\n\t// Set palette\n\tsetInterface(\"craftEquipmentSave\");\n\n\tadd(_window, \"window\", \"craftEquipmentSave\");\n\tadd(_txtTitle, \"text\", \"craftEquipmentSave\");\n\tadd(_lstLoadout, \"list\", \"craftEquipmentSave\");\n\tadd(_btnCancel, \"button\", \"craftEquipmentSave\");\n\tadd(_btnSave, \"button\", \"craftEquipmentSave\");\n\tadd(_edtSave);\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"craftEquipmentSave\");\n\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_SAVE_CRAFT_LOADOUT_TEMPLATE\"));\n\n\t_lstLoadout->setColumns(1, 192);\n\t_lstLoadout->setSelectable(true);\n\t_lstLoadout->setBackground(_window);\n\t_lstLoadout->setMargin(8);\n\t_lstLoadout->onMousePress((ActionHandler)&CraftEquipmentSaveState::lstLoadoutPress);\n\n\t_btnCancel->setText(tr(\"STR_CANCEL_UC\"));\n\t_btnCancel->onMouseClick((ActionHandler)&CraftEquipmentSaveState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&CraftEquipmentSaveState::btnCancelClick, Options::keyCancel);\n\n\t_btnSave->setText(tr(\"STR_SAVE_UC\"));\n\t_btnSave->onMouseClick((ActionHandler)&CraftEquipmentSaveState::btnSaveClick);\n\n\t_edtSave->setColor(_lstLoadout->getSecondaryColor());\n\t_edtSave->setVisible(false);\n\t_edtSave->onKeyboardPress((ActionHandler)&CraftEquipmentSaveState::edtSaveKeyPress);\n\n\tfor (int i = 0; i < SavedGame::MAX_CRAFT_LOADOUT_TEMPLATES; ++i)\n\t{\n\t\tItemContainer *item = _game->getSavedGame()->getGlobalCraftLoadout(i);\n\t\tif (item->empty())\n\t\t{\n\t\t\t_lstLoadout->addRow(1, tr(\"STR_EMPTY_SLOT_N\").arg(i + 1).c_str());\n\t\t}\n\t\telse\n\t\t{\n\t\t\tconst std::string &itemName = _game->getSavedGame()->getGlobalCraftLoadoutName(i);\n\t\t\tif (itemName.empty())\n\t\t\t{\n\t\t\t\t_lstLoadout->addRow(1, tr(\"STR_UNNAMED_SLOT_N\").arg(i + 1).c_str());\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_lstLoadout->addRow(1, itemName.c_str());\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n*\n*/\nCraftEquipmentSaveState::~CraftEquipmentSaveState()\n{\n\n}\n\n/**\n* Returns to the previous screen.\n* @param action Pointer to an action.\n*/\nvoid CraftEquipmentSaveState::btnCancelClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n* Saves the selected template.\n* @param action Pointer to an action.\n*/\nvoid CraftEquipmentSaveState::btnSaveClick(Action *)\n{\n\tif (_selectedRow != -1)\n\t{\n\t\tsaveTemplate();\n\t}\n}\n\n/**\n* Names the selected template.\n* @param action Pointer to an action.\n*/\nvoid CraftEquipmentSaveState::lstLoadoutPress(Action *action)\n{\n\t_previousSelectedRow = _selectedRow;\n\t_selectedRow = _lstLoadout->getSelectedRow();\n\tif (_previousSelectedRow > -1)\n\t{\n\t\t_lstLoadout->setCellText(_previousSelectedRow, 0, _selected);\n\t}\n\t_selected = _lstLoadout->getCellText(_selectedRow, 0);\n\n\tif (action->getDetails()->button.button == SDL_BUTTON_RIGHT && _edtSave->isFocused())\n\t{\n\t\t_previousSelectedRow = -1;\n\t\t_selectedRow = -1;\n\n\t\t_edtSave->setText(\"\");\n\t\t_edtSave->setVisible(false);\n\t\t_edtSave->setFocus(false, false);\n\t\t_lstLoadout->setScrolling(true);\n\t}\n\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT)\n\t{\n\t\t_lstLoadout->setCellText(_selectedRow, 0, \"\");\n\n\t\t_edtSave->setText(_selected);\n\t\t_edtSave->setX(_lstLoadout->getColumnX(0));\n\t\t_edtSave->setY(_lstLoadout->getRowY(_selectedRow));\n\t\t_edtSave->setVisible(true);\n\t\t_edtSave->setFocus(true, false);\n\t\t_lstLoadout->setScrolling(false);\n\t}\n}\n\n\n/**\n* Saves the selected template.\n* @param action Pointer to an action.\n*/\nvoid CraftEquipmentSaveState::edtSaveKeyPress(Action *action)\n{\n\tif (action->getDetails()->key.keysym.sym == SDLK_RETURN ||\n\t\taction->getDetails()->key.keysym.sym == SDLK_KP_ENTER)\n\t{\n\t\tsaveTemplate();\n\t}\n}\n\n/**\n* Saves the selected template.\n*/\nvoid CraftEquipmentSaveState::saveTemplate()\n{\n\tif (_selectedRow >= 0 && _selectedRow < SavedGame::MAX_CRAFT_LOADOUT_TEMPLATES)\n\t{\n\t\t_game->getSavedGame()->setGlobalCraftLoadoutName(_selectedRow, _edtSave->getText());\n\t\t_parent->saveGlobalLoadout(_selectedRow);\n\n\t\t_game->popState();\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/CraftEquipmentSaveState.h",
    "content": "#pragma once\n/*\n* Copyright 2010-2015 OpenXcom Developers.\n*\n* This file is part of OpenXcom.\n*\n* OpenXcom is free software: you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation, either version 3 of the License, or\n* (at your option) any later version.\n*\n* OpenXcom is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*\n* You should have received a copy of the GNU General Public License\n* along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n*/\n#include <string>\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass TextEdit;\nclass TextButton;\nclass Window;\nclass Text;\nclass TextList;\nclass CraftEquipmentState;\n\n/**\n* Craft Loadout Save window that allows saving of the equipment onboard to a global template.\n*/\nclass CraftEquipmentSaveState : public State\n{\nprivate:\n\tCraftEquipmentState *_parent;\n\tWindow *_window;\n\tText *_txtTitle;\n\tTextList *_lstLoadout;\n\tTextButton *_btnCancel, *_btnSave;\n\tTextEdit *_edtSave;\n\tstd::string _selected;\n\tint _previousSelectedRow, _selectedRow;\npublic:\n\t/// Creates the Save Craft Loadout state.\n\tCraftEquipmentSaveState(CraftEquipmentState *parent);\n\t/// Cleans up the Save Craft Loadout state.\n\t~CraftEquipmentSaveState();\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action *action);\n\t/// Handler for clicking the Save button.\n\tvoid btnSaveClick(Action *action);\n\t/// Handler for clicking the Loadout list.\n\tvoid lstLoadoutPress(Action *action);\n\t/// Handler for pressing a key on the Save edit.\n\tvoid edtSaveKeyPress(Action *action);\n\t/// Save template.\n\tvoid saveTemplate();\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/CraftEquipmentState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"CraftEquipmentState.h\"\n#include \"CraftEquipmentLoadState.h\"\n#include \"CraftEquipmentSaveState.h\"\n#include <climits>\n#include <sstream>\n#include <algorithm>\n#include <locale>\n#include \"../Engine/CrossPlatform.h\"\n#include \"../Engine/Screen.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Timer.h\"\n#include \"../Engine/Collections.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/ComboBox.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextEdit.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/Craft.h\"\n#include \"../Mod/RuleCraft.h\"\n#include \"../Savegame/ItemContainer.h\"\n#include \"../Mod/RuleItemCategory.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"../Savegame/Vehicle.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Menu/ErrorMessageState.h\"\n#include \"../Battlescape/CannotReequipState.h\"\n#include \"../Battlescape/DebriefingState.h\"\n#include \"../Battlescape/InventoryState.h\"\n#include \"../Battlescape/BattlescapeGenerator.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"../Mod/RuleInterface.h\"\n#include \"../Ufopaedia/Ufopaedia.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Craft Equipment screen.\n * @param game Pointer to the core game.\n * @param base Pointer to the base to get info from.\n * @param craft ID of the selected craft.\n */\nCraftEquipmentState::CraftEquipmentState(Base *base, size_t craft) :\n\t_lstScroll(0), _sel(0), _craft(craft), _base(base), _totalItems(0), _totalItemStorageSize(0.0), _ammoColor(0),\n\t_reload(true), _returningFromGlobalTemplates(false), _returningFromInventory(false), _firstInit(true), _isNewBattle(false)\n{\n\tCraft *c = _base->getCrafts()->at(_craft);\n\tbool craftHasACrew = c->getNumTotalSoldiers() > 0;\n\t_isNewBattle = _game->getSavedGame()->getMonthsPassed() == -1;\n\n\t// Create objects\n\t_window = new Window(this, 320, 200, 0, 0);\n\t_btnQuickSearch = new TextEdit(this, 48, 9, Options::oxceBaseTouchButtons ? 10 : 264, Options::oxceBaseTouchButtons ? 13 : 12);\n\t_btnOk = new TextButton((craftHasACrew || _isNewBattle)?30:140, 16, (craftHasACrew || _isNewBattle)?274:164, 176);\n\t_btnClear = new TextButton(102, 16, 164, 176);\n\t_btnInventory = new TextButton(102, 16, 164, 176);\n\t_txtTitle = new Text(300, 17, 16, 7);\n\t_txtItem = new Text(144, 9, 16, 32);\n\t_txtStores = new Text(150, 9, 160, 32);\n\t_txtAvailable = new Text(110, 9, 16, 24);\n\t_txtUsed = new Text(110, 9, 130, 24);\n\t_txtCrew = new Text(71, 9, 244, 24);\n\t_lstEquipment = new TextList(288, 128, 8, 40);\n\t_cbxFilterBy = new ComboBox(this, 140, 16, 16, 176, true);\n\n\ttouchComponentsCreate(_txtTitle);\n\n\t// Set palette\n\tsetInterface(\"craftEquipment\");\n\n\t_ammoColor = _game->getMod()->getInterface(\"craftEquipment\")->getElement(\"ammoColor\")->color;\n\n\tadd(_window, \"window\", \"craftEquipment\");\n\tadd(_btnQuickSearch, \"button\", \"craftEquipment\");\n\tadd(_btnOk, \"button\", \"craftEquipment\");\n\tadd(_btnClear, \"button\", \"craftEquipment\");\n\tadd(_btnInventory, \"button\", \"craftEquipment\");\n\tadd(_txtTitle, \"text\", \"craftEquipment\");\n\tadd(_txtItem, \"text\", \"craftEquipment\");\n\tadd(_txtStores, \"text\", \"craftEquipment\");\n\tadd(_txtAvailable, \"text\", \"craftEquipment\");\n\tadd(_txtUsed, \"text\", \"craftEquipment\");\n\tadd(_txtCrew, \"text\", \"craftEquipment\");\n\tadd(_lstEquipment, \"list\", \"craftEquipment\");\n\tadd(_cbxFilterBy, \"button\", \"craftEquipment\");\n\n\ttouchComponentsAdd(\"button2\", \"craftEquipment\", _window);\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"craftEquipment\");\n\n\ttouchComponentsConfigure();\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&CraftEquipmentState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&CraftEquipmentState::btnOkClick, Options::keyCancel);\n\t_btnOk->onKeyboardPress((ActionHandler)&CraftEquipmentState::btnClearClick, Options::keyRemoveEquipmentFromCraft);\n\t_btnOk->onKeyboardPress((ActionHandler)&CraftEquipmentState::btnLoadClick, Options::keyCraftLoadoutLoad);\n\t_btnOk->onKeyboardPress((ActionHandler)&CraftEquipmentState::btnSaveClick, Options::keyCraftLoadoutSave);\n\n\t_btnClear->setText(tr(\"STR_UNLOAD_CRAFT\"));\n\t_btnClear->onMouseClick((ActionHandler)&CraftEquipmentState::btnClearClick);\n\t_btnClear->setVisible(_isNewBattle);\n\n\t_btnInventory->setText(tr(\"STR_INVENTORY\"));\n\t_btnInventory->onMouseClick((ActionHandler)&CraftEquipmentState::btnInventoryClick);\n\t_btnInventory->setVisible(craftHasACrew && !_isNewBattle);\n\t_btnInventory->onKeyboardPress((ActionHandler)&CraftEquipmentState::btnInventoryClick, Options::keyBattleInventory);\n\n\t_txtTitle->setBig();\n\tif (Options::oxceBaseTouchButtons)\n\t{\n\t\t_txtTitle->setAlign(ALIGN_CENTER);\n\t\t_txtTitle->setText(c->getName(_game->getLanguage()));\n\t}\n\telse\n\t{\n\t\t_txtTitle->setAlign(ALIGN_LEFT);\n\t\t_txtTitle->setText(tr(\"STR_EQUIPMENT_FOR_CRAFT\").arg(c->getName(_game->getLanguage())));\n\t}\n\n\t_txtItem->setText(tr(\"STR_ITEM\"));\n\n\t_txtStores->setText(tr(\"STR_STORES\"));\n\n\t_txtAvailable->setText(tr(\"STR_SPACE_AVAILABLE\").arg(c->getSpaceAvailable()));\n\n\t_txtUsed->setText(tr(\"STR_SPACE_USED\").arg(c->getSpaceUsed()));\n\n\tstd::ostringstream ss3;\n\tss3 << tr(\"STR_SOLDIERS_UC\") << \">\" << Unicode::TOK_COLOR_FLIP << c->getNumTotalSoldiers();\n\t_txtCrew->setText(ss3.str());\n\n\t// populate sort options\n\t_categoryStrings.push_back(\"STR_ALL\");\n\t_categoryStrings.push_back(\"STR_EQUIPPED\");\n\tbool hasUnassigned = false;\n\tfor (auto& itemType : _game->getMod()->getItemsList())\n\t{\n\t\tRuleItem *rule = _game->getMod()->getItem(itemType);\n\t\tUnit* isVehicle = rule->getVehicleUnit();\n\t\tint cQty = isVehicle ? c->getVehicleCount(itemType) : c->getItems()->getItem(rule);\n\n\t\tif ((isVehicle || rule->isInventoryItem()) && rule->canBeEquippedToCraftInventory() &&\n\t\t\t_game->getSavedGame()->isResearched(rule->getRequirements()) &&\n\t\t\t(_base->getStorageItems()->getItem(rule) > 0 || cQty > 0))\n\t\t{\n\t\t\tif (rule->getCategories().empty())\n\t\t\t{\n\t\t\t\thasUnassigned = true;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tfor (auto& itemCategoryName : rule->getCategories())\n\t\t\t\t{\n\t\t\t\t\t_usedCategoryStrings[itemCategoryName] = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tauto& itemCategories = _game->getMod()->getItemCategoriesList();\n\tfor (auto& categoryName : itemCategories)\n\t{\n\t\tif (_usedCategoryStrings[categoryName])\n\t\t{\n\t\t\tif (!_game->getMod()->getItemCategory(categoryName)->isHidden())\n\t\t\t{\n\t\t\t\t_categoryStrings.push_back(categoryName);\n\t\t\t}\n\t\t}\n\t}\n\tif (hasUnassigned && !itemCategories.empty())\n\t{\n\t\t_categoryStrings.push_back(\"STR_UNASSIGNED\");\n\t}\n\t_categoryStrings.push_back(\"STR_NOT_EQUIPPED\");\n\n\t_cbxFilterBy->setOptions(_categoryStrings, true);\n\t_cbxFilterBy->setSelected(0);\n\t_cbxFilterBy->onChange((ActionHandler)&CraftEquipmentState::cbxFilterByChange);\n\n\t_lstEquipment->setArrowColumn(203, ARROW_HORIZONTAL);\n\t_lstEquipment->setColumns(3, 156, 83, 41);\n\t_lstEquipment->setSelectable(true);\n\t_lstEquipment->setBackground(_window);\n\t_lstEquipment->setMargin(8);\n\t_lstEquipment->onLeftArrowPress((ActionHandler)&CraftEquipmentState::lstEquipmentLeftArrowPress);\n\t_lstEquipment->onLeftArrowRelease((ActionHandler)&CraftEquipmentState::lstEquipmentLeftArrowRelease);\n\t_lstEquipment->onLeftArrowClick((ActionHandler)&CraftEquipmentState::lstEquipmentLeftArrowClick);\n\t_lstEquipment->onRightArrowPress((ActionHandler)&CraftEquipmentState::lstEquipmentRightArrowPress);\n\t_lstEquipment->onRightArrowRelease((ActionHandler)&CraftEquipmentState::lstEquipmentRightArrowRelease);\n\t_lstEquipment->onRightArrowClick((ActionHandler)&CraftEquipmentState::lstEquipmentRightArrowClick);\n\t_lstEquipment->onMousePress((ActionHandler)&CraftEquipmentState::lstEquipmentMousePress);\n\n\t_btnQuickSearch->setText(\"\"); // redraw\n\t_btnQuickSearch->onEnter((ActionHandler)&CraftEquipmentState::btnQuickSearchApply);\n\t_btnQuickSearch->setVisible(Options::oxceQuickSearchButton);\n\n\t_btnOk->onKeyboardRelease((ActionHandler)&CraftEquipmentState::btnQuickSearchToggle, Options::keyToggleQuickSearch);\n\n\t_timerLeft = new Timer(250);\n\t_timerLeft->onTimer((StateHandler)&CraftEquipmentState::moveLeft);\n\t_timerRight = new Timer(250);\n\t_timerRight->onTimer((StateHandler)&CraftEquipmentState::moveRight);\n}\n\n/**\n *\n */\nCraftEquipmentState::~CraftEquipmentState()\n{\n\tdelete _timerLeft;\n\tdelete _timerRight;\n}\n\n/**\n * Filters the equipment list by the selected criterion\n * @param action Pointer to an action.\n */\nvoid CraftEquipmentState::cbxFilterByChange(Action *action)\n{\n\tinitList();\n}\n\n/**\n* Resets the savegame when coming back from the inventory.\n*/\nvoid CraftEquipmentState::init()\n{\n\tState::init();\n\n\t_game->getSavedGame()->setBattleGame(0);\n\n\tCraft *c = _base->getCrafts()->at(_craft);\n\tc->setInBattlescape(false);\n\n\t// don't reload after closing error popups\n\tif (_reload)\n\t{\n\t\tif (Options::oxceAlternateCraftEquipmentManagement && !_isNewBattle)\n\t\t{\n\t\t\t// skip when returning from craft equipment template load/save\n\t\t\tif (!_returningFromGlobalTemplates)\n\t\t\t{\n\t\t\t\tc->calculateTotalSoldierEquipment();\n\t\t\t}\n\t\t\tif (_returningFromInventory)\n\t\t\t{\n\t\t\t\t// now that we're back from the inventory screen, we need to remove all the excess base gear\n\t\t\t\tfor (_sel = 0; _sel != _items.size(); ++_sel)\n\t\t\t\t{\n\t\t\t\t\tint excessQty = c->getItems()->getItem(_items[_sel]) - (c->getExtraItems()->getItem(_items[_sel]) + c->getSoldierItems()->getItem(_items[_sel]));\n\t\t\t\t\tmoveLeftByValue(excessQty);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tinitList();\n\t}\n\t_reload = true;\n\t_returningFromGlobalTemplates = false;\n\t_returningFromInventory = false;\n\t_firstInit = false;\n\n\ttouchComponentsRefresh();\n}\n\n/**\n* Quick search toggle.\n* @param action Pointer to an action.\n*/\nvoid CraftEquipmentState::btnQuickSearchToggle(Action *action)\n{\n\tif (_btnQuickSearch->getVisible())\n\t{\n\t\t_btnQuickSearch->setText(\"\");\n\t\t_btnQuickSearch->setVisible(false);\n\t\tbtnQuickSearchApply(action);\n\t}\n\telse\n\t{\n\t\t_btnQuickSearch->setVisible(true);\n\t\t_btnQuickSearch->setFocus(true);\n\t}\n}\n\n/**\n* Quick search.\n* @param action Pointer to an action.\n*/\nvoid CraftEquipmentState::btnQuickSearchApply(Action *)\n{\n\tinitList();\n}\n\n/**\n * Shows the equipment in a list filtered by selected criterion.\n */\nvoid CraftEquipmentState::initList()\n{\n\tstd::string searchString = _btnQuickSearch->getText();\n\tUnicode::upperCase(searchString);\n\n\tsize_t selIdx = _cbxFilterBy->getSelected();\n\tif (selIdx == (size_t)-1)\n\t{\n\t\treturn;\n\t}\n\tconst std::string selectedCategory = _categoryStrings[selIdx];\n\tbool categoryFilterEnabled = (selectedCategory != \"STR_ALL\");\n\tbool categoryUnassigned = (selectedCategory == \"STR_UNASSIGNED\");\n\tbool categoryEquipped = (selectedCategory == \"STR_EQUIPPED\");\n\tbool categoryNotEquipped = (selectedCategory == \"STR_NOT_EQUIPPED\");\n\tbool shareAmmoCategories = _game->getMod()->getShareAmmoCategories();\n\n\tCraft *c = _base->getCrafts()->at(_craft);\n\n\t// reset\n\t_totalItems = 0;\n\t_totalItemStorageSize = 0.0;\n\t_items.clear();\n\t_lstEquipment->clearList();\n\n\tint row = 0;\n\tfor (auto& itemType : _game->getMod()->getItemsList())\n\t{\n\t\tconst RuleItem *rule = _game->getMod()->getItem(itemType);\n\n\t\tUnit* isVehicle = rule->getVehicleUnit();\n\t\tint cQty = 0;\n\t\tif (isVehicle)\n\t\t{\n\t\t\tcQty = c->getVehicleCount(itemType);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tcQty = c->getItems()->getItem(rule);\n\t\t\t_totalItems += cQty;\n\t\t\t_totalItemStorageSize += cQty * rule->getSize();\n\t\t}\n\n\t\tint bQty = _base->getStorageItems()->getItem(rule);\n\t\tint reserved = 0;\n\t\tif (Options::oxceAlternateCraftEquipmentManagement && !_isNewBattle)\n\t\t{\n\t\t\treserved = c->getSoldierItems()->getItem(rule);\n\t\t}\n\t\tif ((isVehicle || rule->isInventoryItem()) && rule->canBeEquippedToCraftInventory() &&\n\t\t\t(bQty > 0 || cQty > 0 || reserved > 0))\n\t\t{\n\t\t\t// check research requirements\n\t\t\tif (!_game->getSavedGame()->isResearched(rule->getRequirements()))\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// filter by category\n\t\t\tif (categoryFilterEnabled)\n\t\t\t{\n\t\t\t\tif (categoryUnassigned)\n\t\t\t\t{\n\t\t\t\t\tif (!rule->getCategories().empty())\n\t\t\t\t\t{\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (categoryEquipped)\n\t\t\t\t{\n\t\t\t\t\tif (!(cQty > 0))\n\t\t\t\t\t{\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (categoryNotEquipped)\n\t\t\t\t{\n\t\t\t\t\tif (cQty > 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tbool isOK = rule->belongsToCategory(selectedCategory);\n\t\t\t\t\tif (shareAmmoCategories && !isOK && rule->getBattleType() == BT_FIREARM)\n\t\t\t\t\t{\n\t\t\t\t\t\tfor (auto* ammoRule : *rule->getPrimaryCompatibleAmmo())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (_base->getStorageItems()->getItem(ammoRule) > 0 || c->getItems()->getItem(ammoRule) > 0)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (ammoRule->isInventoryItem() && ammoRule->canBeEquippedToCraftInventory() && _game->getSavedGame()->isResearched(ammoRule->getRequirements()))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tisOK = ammoRule->belongsToCategory(selectedCategory);\n\t\t\t\t\t\t\t\t\tif (isOK) break;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (!isOK) continue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// quick search\n\t\t\tif (!searchString.empty())\n\t\t\t{\n\t\t\t\tstd::string projectName = tr(itemType);\n\t\t\t\tUnicode::upperCase(projectName);\n\t\t\t\tif (projectName.find(searchString) == std::string::npos)\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t_items.push_back(itemType);\n\t\t\tstd::ostringstream ss, ss2;\n\t\t\tif (Options::oxceAlternateCraftEquipmentManagement && !_isNewBattle)\n\t\t\t{\n\t\t\t\t// doing this once (on opening the screen) is enough\n\t\t\t\t// and just to make sure, we must skip this when returning from craft equipment template load/save\n\t\t\t\tif (_firstInit && !isVehicle && cQty < reserved && !_returningFromGlobalTemplates)\n\t\t\t\t{\n\t\t\t\t\t// try to automatically add more items (if possible)\n\t\t\t\t\tint itemsToAdd = std::min(bQty, reserved - cQty);\n\t\t\t\t\tif (itemsToAdd > 0)\n\t\t\t\t\t{\n\t\t\t\t\t\t_base->getStorageItems()->removeItem(rule, itemsToAdd);\n\t\t\t\t\t\tbQty -= itemsToAdd;\n\t\t\t\t\t\tc->getItems()->addItem(rule, itemsToAdd);\n\t\t\t\t\t\tcQty += itemsToAdd;\n\t\t\t\t\t\t_totalItems += itemsToAdd;\n\t\t\t\t\t\t_totalItemStorageSize += itemsToAdd * rule->getSize();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (isVehicle)\n\t\t\t\t\tss2 << cQty;\n\t\t\t\telse if (cQty - reserved > 0)\n\t\t\t\t\tss2 << reserved << \"/+\" << cQty - reserved;\n\t\t\t\telse if (cQty - reserved == 0)\n\t\t\t\t\tss2 << cQty;\n\t\t\t\telse\n\t\t\t\t\tss2 << cQty << \"/\" << cQty - reserved;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tss2 << cQty;\n\t\t\t}\n\t\t\tif (!_isNewBattle)\n\t\t\t{\n\t\t\t\tss << bQty;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tss << \"-\";\n\t\t\t}\n\n\t\t\tstd::string s = tr(itemType);\n\t\t\tif (rule->getBattleType() == BT_AMMO)\n\t\t\t{\n\t\t\t\ts.insert(0, \"  \");\n\t\t\t}\n\t\t\t_lstEquipment->addRow(3, s.c_str(), ss.str().c_str(), ss2.str().c_str());\n\n\t\t\tUint8 color;\n\t\t\tif (cQty == 0)\n\t\t\t{\n\t\t\t\tif (rule->getBattleType() == BT_AMMO)\n\t\t\t\t{\n\t\t\t\t\tcolor = _ammoColor;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tcolor = _lstEquipment->getColor();\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t\tcolor = _lstEquipment->getSecondaryColor();\n\t\t\t}\n\t\t\t_lstEquipment->setRowColor(row, color);\n\n\t\t\t++row;\n\t\t}\n\t}\n\n\t_lstEquipment->draw();\n\tif (_lstScroll > 0)\n\t{\n\t\t_lstEquipment->scrollTo(_lstScroll);\n\t\t_lstScroll = 0;\n\t}\n}\n\n/**\n * Runs the arrow timers.\n */\nvoid CraftEquipmentState::think()\n{\n\tState::think();\n\n\t_timerLeft->think(this, 0);\n\t_timerRight->think(this, 0);\n}\n\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid CraftEquipmentState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Starts moving the item to the base.\n * @param action Pointer to an action.\n */\nvoid CraftEquipmentState::lstEquipmentLeftArrowPress(Action *action)\n{\n\t_sel = _lstEquipment->getSelectedRow();\n\tif (_game->isLeftClick(action, true) && !_timerLeft->isRunning()) _timerLeft->start();\n}\n\n/**\n * Stops moving the item to the base.\n * @param action Pointer to an action.\n */\nvoid CraftEquipmentState::lstEquipmentLeftArrowRelease(Action *action)\n{\n\tif (_game->isLeftClick(action, true))\n\t{\n\t\t_timerLeft->stop();\n\t}\n}\n\n/**\n * Moves all the items to the base on right-click.\n * @param action Pointer to an action.\n */\nvoid CraftEquipmentState::lstEquipmentLeftArrowClick(Action *action)\n{\n\tif (_game->isRightClick(action, true)) moveLeftByValue(INT_MAX);\n\tif (_game->isLeftClick(action, true))\n\t{\n\t\tmoveLeftByValue(_game->getScrollStep());\n\t\t_timerRight->setInterval(250);\n\t\t_timerLeft->setInterval(250);\n\t}\n}\n\n/**\n * Starts moving the item to the craft.\n * @param action Pointer to an action.\n */\nvoid CraftEquipmentState::lstEquipmentRightArrowPress(Action *action)\n{\n\t_sel = _lstEquipment->getSelectedRow();\n\tif (_game->isLeftClick(action, true) && !_timerRight->isRunning()) _timerRight->start();\n}\n\n/**\n * Stops moving the item to the craft.\n * @param action Pointer to an action.\n */\nvoid CraftEquipmentState::lstEquipmentRightArrowRelease(Action *action)\n{\n\tif (_game->isLeftClick(action, true))\n\t{\n\t\t_timerRight->stop();\n\t}\n}\n\n/**\n * Moves all the items (as much as possible) to the craft on right-click.\n * @param action Pointer to an action.\n */\nvoid CraftEquipmentState::lstEquipmentRightArrowClick(Action *action)\n{\n\tif (_game->isRightClick(action, true)) moveRightByValue(INT_MAX);\n\tif (_game->isLeftClick(action, true))\n\t{\n\t\tmoveRightByValue(_game->getScrollStep());\n\t\t_timerRight->setInterval(250);\n\t\t_timerLeft->setInterval(250);\n\t}\n}\n\n/**\n * Handles the mouse-wheels on the arrow-buttons.\n * @param action Pointer to an action.\n */\nvoid CraftEquipmentState::lstEquipmentMousePress(Action *action)\n{\n\t_sel = _lstEquipment->getSelectedRow();\n\tif (action->getDetails()->button.button == SDL_BUTTON_WHEELUP)\n\t{\n\t\t_timerRight->stop();\n\t\t_timerLeft->stop();\n\t\tif (action->getAbsoluteXMouse() >= _lstEquipment->getArrowsLeftEdge() &&\n\t\t\taction->getAbsoluteXMouse() <= _lstEquipment->getArrowsRightEdge())\n\t\t{\n\t\t\tmoveRightByValue(Options::changeValueByMouseWheel);\n\t\t}\n\t}\n\telse if (action->getDetails()->button.button == SDL_BUTTON_WHEELDOWN)\n\t{\n\t\t_timerRight->stop();\n\t\t_timerLeft->stop();\n\t\tif (action->getAbsoluteXMouse() >= _lstEquipment->getArrowsLeftEdge() &&\n\t\t\taction->getAbsoluteXMouse() <= _lstEquipment->getArrowsRightEdge())\n\t\t{\n\t\t\tmoveLeftByValue(Options::changeValueByMouseWheel);\n\t\t}\n\t}\n\telse if (_game->isMiddleClick(action, true))\n\t{\n\t\t_lstScroll = _lstEquipment->getScroll();\n\t\tRuleItem *rule = _game->getMod()->getItem(_items[_sel]);\n\t\tstd::string articleId = rule->getUfopediaType();\n\t\tUfopaedia::openArticle(_game, articleId);\n\t}\n}\n\n/**\n * Updates the displayed quantities of the\n * selected item on the list.\n */\nvoid CraftEquipmentState::updateQuantity()\n{\n\tCraft *c = _base->getCrafts()->at(_craft);\n\tRuleItem *item = _game->getMod()->getItem(_items[_sel], true);\n\tint cQty = 0;\n\tif (item->getVehicleUnit())\n\t{\n\t\tcQty = c->getVehicleCount(_items[_sel]);\n\t}\n\telse\n\t{\n\t\tcQty = c->getItems()->getItem(item);\n\t}\n\tstd::ostringstream ss, ss2;\n\tif (!_isNewBattle)\n\t{\n\t\tss << _base->getStorageItems()->getItem(item);\n\t}\n\telse\n\t{\n\t\tss << \"-\";\n\t}\n\tif (Options::oxceAlternateCraftEquipmentManagement && !_isNewBattle)\n\t{\n\t\tint reserved = c->getSoldierItems()->getItem(item);\n\t\tif (item->getVehicleUnit())\n\t\t\tss2 << cQty;\n\t\telse if (cQty - reserved > 0)\n\t\t\tss2 << reserved << \"/+\" << cQty - reserved;\n\t\telse if (cQty - reserved == 0)\n\t\t\tss2 << cQty;\n\t\telse\n\t\t\tss2 << cQty << \"/\" << cQty - reserved;\n\t}\n\telse\n\t{\n\t\tss2 << cQty;\n\t}\n\n\tUint8 color;\n\tif (cQty == 0)\n\t{\n\t\tif (item->getBattleType() == BT_AMMO)\n\t\t{\n\t\t\tcolor = _ammoColor;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tcolor = _lstEquipment->getColor();\n\t\t}\n\t}\n\telse\n\t{\n\t\tcolor = _lstEquipment->getSecondaryColor();\n\t}\n\t_lstEquipment->setRowColor(_sel, color);\n\t_lstEquipment->setCellText(_sel, 1, ss.str());\n\t_lstEquipment->setCellText(_sel, 2, ss2.str());\n\n\t_txtAvailable->setText(tr(\"STR_SPACE_AVAILABLE\").arg(c->getSpaceAvailable()));\n\t_txtUsed->setText(tr(\"STR_SPACE_USED\").arg(c->getSpaceUsed()));\n}\n\n/**\n * Moves the selected item to the base.\n */\nvoid CraftEquipmentState::moveLeft()\n{\n\t_timerLeft->setInterval(50);\n\t_timerRight->setInterval(50);\n\tmoveLeftByValue(_game->getScrollStep());\n}\n\n/**\n * Moves the given number of items (selected) to the base.\n * @param change Item difference.\n */\nvoid CraftEquipmentState::moveLeftByValue(int change)\n{\n\tCraft *c = _base->getCrafts()->at(_craft);\n\tconst RuleItem *item = _game->getMod()->getItem(_items[_sel], true);\n\tint cQty = 0;\n\tif (item->getVehicleUnit()) cQty = c->getVehicleCount(_items[_sel]);\n\telse cQty = c->getItems()->getItem(item);\n\tif (change <= 0 || cQty <= 0) return;\n\tif (Options::oxceAlternateCraftEquipmentManagement && !_isNewBattle)\n\t{\n\t\tint reserved = c->getSoldierItems()->getItem(item);\n\t\tif (cQty - reserved > 0)\n\t\t{\n\t\t\tchange = std::min(cQty - reserved, change);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t//change = 0;\n\t\t\treturn;\n\t\t}\n\t}\n\telse\n\t{\n\t\tchange = std::min(cQty, change);\n\t}\n\t// Convert vehicle to item\n\tif (item->getVehicleUnit())\n\t{\n\t\tif (item->getVehicleClipAmmo())\n\t\t{\n\t\t\t// Calculate how much ammo needs to be added to the base.\n\t\t\tconst RuleItem *ammo = item->getVehicleClipAmmo();\n\t\t\tint ammoPerVehicle = item->getVehicleClipsLoaded();\n\n\t\t\t// Put the vehicles and their ammo back as separate items.\n\t\t\tif (!_isNewBattle)\n\t\t\t{\n\t\t\t\t_base->getStorageItems()->addItem(item, change);\n\t\t\t\t_base->getStorageItems()->addItem(ammo, ammoPerVehicle * change);\n\t\t\t}\n\t\t\t// now delete the vehicles from the craft.\n\t\t\tCollections::deleteIf(*c->getVehicles(), change,\n\t\t\t\t[&](Vehicle* v)\n\t\t\t\t{\n\t\t\t\t\treturn v->getRules() == item;\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (!_isNewBattle)\n\t\t\t{\n\t\t\t\t_base->getStorageItems()->addItem(item, change);\n\t\t\t}\n\t\t\tCollections::deleteIf(*c->getVehicles(), change,\n\t\t\t\t[&](Vehicle* v)\n\t\t\t\t{\n\t\t\t\t\treturn v->getRules() == item;\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t}\n\telse\n\t{\n\t\tc->getItems()->removeItem(item, change);\n\t\t_totalItems -= change;\n\t\t_totalItemStorageSize -= change * item->getSize();\n\t\tif (!_isNewBattle)\n\t\t{\n\t\t\t_base->getStorageItems()->addItem(item, change);\n\t\t}\n\t}\n\tupdateQuantity();\n}\n\n/**\n * Moves the selected item to the craft.\n */\nvoid CraftEquipmentState::moveRight()\n{\n\t_timerLeft->setInterval(50);\n\t_timerRight->setInterval(50);\n\tmoveRightByValue(_game->getScrollStep());\n}\n\n/**\n * Moves the given number of items (selected) to the craft.\n * @param change Item difference.\n * @param suppressErrors Suppress error messages?\n */\nvoid CraftEquipmentState::moveRightByValue(int change, bool suppressErrors)\n{\n\tCraft *c = _base->getCrafts()->at(_craft);\n\tconst RuleItem *item = _game->getMod()->getItem(_items[_sel], true);\n\tint bqty = _base->getStorageItems()->getItem(item);\n\tif (_isNewBattle)\n\t{\n\t\tif (change == INT_MAX)\n\t\t{\n\t\t\tchange = 10;\n\t\t}\n\t\tbqty = change;\n\t}\n\tif (0 >= change || 0 >= bqty) return;\n\tchange = std::min(bqty, change);\n\t// Do we need to convert item to vehicle?\n\tif (item->getVehicleUnit())\n\t{\n\t\tint size = item->getVehicleUnit()->getArmor()->getTotalSize();\n\t\t// Check if there's enough room\n\t\tint room = c->validateAddingVehicles(size);\n\t\tif (room > 0)\n\t\t{\n\t\t\tchange = std::min(room, change);\n\t\t\tif (item->getVehicleClipAmmo())\n\t\t\t{\n\t\t\t\t// And now let's see if we can add the total number of vehicles.\n\t\t\t\tconst RuleItem *ammo = item->getVehicleClipAmmo();\n\t\t\t\tint ammoPerVehicle = item->getVehicleClipsLoaded();\n\n\t\t\t\tint baseQty = _base->getStorageItems()->getItem(ammo) / ammoPerVehicle;\n\t\t\t\tif (_isNewBattle)\n\t\t\t\t\tbaseQty = change;\n\t\t\t\tint canBeAdded = std::min(change, baseQty);\n\t\t\t\tif (canBeAdded > 0)\n\t\t\t\t{\n\t\t\t\t\tfor (int i = 0; i < canBeAdded; ++i)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (!_isNewBattle)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_base->getStorageItems()->removeItem(ammo, ammoPerVehicle);\n\t\t\t\t\t\t\t_base->getStorageItems()->removeItem(item);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tc->getVehicles()->push_back(new Vehicle(item, item->getVehicleClipSize(), size));\n\t\t\t\t\t\tc->resetCustomDeployment(); // adding a vehicle into a craft invalidates a custom craft deployment\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif (!suppressErrors)\n\t\t\t\t\t{\n\t\t\t\t\t\t// So we haven't managed to increase the count of vehicles because of the ammo\n\t\t\t\t\t\t_timerRight->stop();\n\t\t\t\t\t\tLocalizedText msg(tr(\"STR_NOT_ENOUGH_AMMO_TO_ARM_HWP\").arg(ammoPerVehicle).arg(tr(ammo->getType())));\n\t\t\t\t\t\t_game->pushState(new ErrorMessageState(msg, _palette, _game->getMod()->getInterface(\"craftEquipment\")->getElement(\"errorMessage\")->color, \"BACK04.SCR\", _game->getMod()->getInterface(\"craftEquipment\")->getElement(\"errorPalette\")->color));\n\t\t\t\t\t\t_reload = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t\tfor (int i = 0; i < change; ++i)\n\t\t\t\t{\n\t\t\t\t\tc->getVehicles()->push_back(new Vehicle(item, item->getVehicleClipSize(), size));\n\t\t\t\t\tc->resetCustomDeployment(); // adding a vehicle into a craft invalidates a custom craft deployment\n\t\t\t\t\tif (!_isNewBattle)\n\t\t\t\t\t{\n\t\t\t\t\t\t_base->getStorageItems()->removeItem(item);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\tif (_totalItems + change > c->getMaxItemsClamped())\n\t\t{\n\t\t\tif (!suppressErrors)\n\t\t\t{\n\t\t\t\t_timerRight->stop();\n\t\t\t\tLocalizedText msg(tr(\"STR_NO_MORE_EQUIPMENT_ALLOWED\", c->getMaxItemsClamped()));\n\t\t\t\t_game->pushState(new ErrorMessageState(msg, _palette, _game->getMod()->getInterface(\"craftEquipment\")->getElement(\"errorMessage\")->color, \"BACK04.SCR\", _game->getMod()->getInterface(\"craftEquipment\")->getElement(\"errorPalette\")->color));\n\t\t\t\t_reload = false;\n\t\t\t}\n\t\t\tchange = c->getMaxItemsClamped() - _totalItems;\n\t\t\tif (change < 0)\n\t\t\t{\n\t\t\t\t// if the player is already over the maximum (e.g. after a mod update), don't go into some ridiculous minus values\n\t\t\t\tchange = 0;\n\t\t\t}\n\t\t}\n\t\tif (_totalItemStorageSize + (change * item->getSize()) > c->getMaxStorageSpaceClamped() + 0.05)\n\t\t{\n\t\t\tif (item->getSize() > 0.0)\n\t\t\t{\n\t\t\t\tchange = (int)floor((c->getMaxStorageSpaceClamped() + 0.05 - _totalItemStorageSize) / item->getSize());\n\t\t\t}\n\t\t\tif (change < 0)\n\t\t\t{\n\t\t\t\t// if the player is already over the maximum (e.g. after a mod update), don't go into some ridiculous minus values\n\t\t\t\tchange = 0;\n\t\t\t}\n\t\t\tif (!suppressErrors)\n\t\t\t{\n\t\t\t\t_timerRight->stop();\n\t\t\t\tLocalizedText msg(tr(\"STR_NO_MORE_EQUIPMENT_ALLOWED_BY_SIZE\").arg(c->getMaxStorageSpaceClamped()));\n\t\t\t\t_game->pushState(new ErrorMessageState(msg, _palette, _game->getMod()->getInterface(\"craftEquipment\")->getElement(\"errorMessage\")->color, \"BACK04.SCR\", _game->getMod()->getInterface(\"craftEquipment\")->getElement(\"errorPalette\")->color));\n\t\t\t\t_reload = false;\n\t\t\t}\n\t\t}\n\t\tc->getItems()->addItem(item, change);\n\t\t_totalItems += change;\n\t\t_totalItemStorageSize += change * item->getSize();\n\t\tif (!_isNewBattle)\n\t\t{\n\t\t\t_base->getStorageItems()->removeItem(item, change);\n\t\t}\n\t}\n\tupdateQuantity();\n}\n\n/**\n * Empties the contents of the craft, moving all of the items back to the base.\n */\nvoid CraftEquipmentState::btnClearClick(Action *)\n{\n\tfor (_sel = 0; _sel != _items.size(); ++_sel)\n\t{\n\t\tmoveLeftByValue(INT_MAX);\n\t}\n\n\t// in New Battle, clear also stuff that is not displayed on the GUI (for whatever reason)\n\tif (_isNewBattle)\n\t{\n\t\tCraft* c = _base->getCrafts()->at(_craft);\n\t\tc->getItems()->clear();\n\t}\n}\n\n/**\n * Displays the inventory screen for the soldiers\n * inside the craft.\n * @param action Pointer to an action.\n */\nvoid CraftEquipmentState::btnInventoryClick(Action *)\n{\n\tCraft *craft = _base->getCrafts()->at(_craft);\n\tif (craft->getNumTotalSoldiers() > 0)\n\t{\n\t\tif (Options::oxceAlternateCraftEquipmentManagement && !_isNewBattle)\n\t\t{\n\t\t\t// This is a bit tricky... here's what we're doing:\n\t\t\t// * Remember the extra craft items (i.e. items that are on the craft, but not equipped by soldiers)\n\t\t\t// * Move all equipment from the base into the craft.\n\t\t\t// * Run the inventory screen.\n\t\t\t// * Remove excess items from the craft when CraftEquipmentState::init() is called after leaving the inventory screen.\n\t\t\t// (After this, the craft should have all the updated soldier equipment, and the same extra items as before.)\n\n\t\t\t// Note: the current implementation assumes no limit to the number or size of items a craft can hold.\n\t\t\t//       If the craft has limited space, then we just won't have all the base items available on the inventory screen.\n\n\t\t\tauto& extras = *craft->getExtraItems();\n\t\t\textras.clear();\n\n\t\t\t// temporarily ignore craft limits\n\t\t\tint maxItemsBackup = craft->getCraftStats().maxItems;\n\t\t\tdouble maxStorageSpaceBackup = craft->getCraftStats().maxStorageSpace;\n\t\t\tcraft->setMaxItemsRaw(999999);\n\t\t\tcraft->setMaxStorageSpaceRaw(99999.0);\n\n\t\t\tfor (_sel = 0; _sel != _items.size(); ++_sel)\n\t\t\t{\n\t\t\t\tRuleItem* rule = _game->getMod()->getItem(_items[_sel], true);\n\t\t\t\tif (craft->getItems()->getItem(rule) > 0)\n\t\t\t\t{\n\t\t\t\t\textras.addItem(rule, craft->getItems()->getItem(rule) - craft->getSoldierItems()->getItem(rule));\n\t\t\t\t}\n\t\t\t\tif (!rule->getVehicleUnit() && rule->canBeEquippedBeforeBaseDefense())\n\t\t\t\t{\n\t\t\t\t\tmoveRightByValue(INT_MAX, true);\n\t\t\t\t}\n\t\t\t}\n\t\t\t// restore limits\n\t\t\tcraft->setMaxItemsRaw(maxItemsBackup);\n\t\t\tcraft->setMaxStorageSpaceRaw(maxStorageSpaceBackup);\n\t\t}\n\n\t\tSavedBattleGame *bgame = new SavedBattleGame(_game->getMod(), _game->getLanguage());\n\t\t_game->getSavedGame()->setBattleGame(bgame);\n\n\t\tif (_game->isCtrlPressed(true) && _game->isAltPressed(true))\n\t\t{\n\t\t\t_game->getSavedGame()->setDisableSoldierEquipment(true);\n\t\t}\n\t\tBattlescapeGenerator bgen = BattlescapeGenerator(_game);\n\t\tbgen.runInventory(craft);\n\n\t\t_game->getScreen()->clear();\n\t\t_game->pushState(new InventoryState(false, 0, _base));\n\t\t_returningFromInventory = true;\n\t}\n}\n\nvoid CraftEquipmentState::saveGlobalLoadout(int index)\n{\n\t// clear the template\n\tItemContainer *tmpl = _game->getSavedGame()->getGlobalCraftLoadout(index);\n\ttmpl->clear();\n\n\tCraft *c = _base->getCrafts()->at(_craft);\n\t// save only what is visible on the screen (can be DIFFERENT than what's really in the craft for various reasons)\n\tfor (const auto& itemType : _items)\n\t{\n\t\tconst RuleItem *item = _game->getMod()->getItem(itemType, true);\n\t\tint cQty = 0;\n\t\tif (item->getVehicleUnit())\n\t\t{\n\t\t\tcQty = c->getVehicleCount(itemType);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tcQty = c->getItems()->getItem(item);\n\t\t}\n\t\tif (cQty > 0)\n\t\t{\n\t\t\ttmpl->addItem(item, cQty);\n\t\t}\n\t}\n}\n\nvoid CraftEquipmentState::loadGlobalLoadout(int index, bool onlyAddItems)\n{\n\t// temporarily turn off alternate craft equipment management to allow removing all items from the craft\n\tbool backup = Options::oxceAlternateCraftEquipmentManagement;\n\tOptions::oxceAlternateCraftEquipmentManagement = false;\n\n\t// reset filters and reload the full equipment list\n\t_btnQuickSearch->setText(\"\");\n\t_cbxFilterBy->setSelected(0);\n\tinitList();\n\n\tCraft* c = _base->getCrafts()->at(_craft);\n\n\tItemContainer craftItemsBackup;\n\tstd::vector<Vehicle*> craftVehiclesBackup;\n\tif (onlyAddItems)\n\t{\n\t\t// remember for later, make copies\n\t\tcraftItemsBackup = *c->getItems();\n\t\tcraftVehiclesBackup = *c->getVehicles();\n\t}\n\telse\n\t{\n\t\t// first move everything visible back to base\n\t\tfor (_sel = 0; _sel != _items.size(); ++_sel)\n\t\t{\n\t\t\tmoveLeftByValue(INT_MAX);\n\t\t}\n\t}\n\n\t// now start applying the template (consider ONLY items visible on the GUI)\n\tItemContainer *tmpl = _game->getSavedGame()->getGlobalCraftLoadout(index);\n\tfor (_sel = 0; _sel != _items.size(); ++_sel)\n\t{\n\t\tRuleItem *item = _game->getMod()->getItem(_items[_sel], true);\n\t\tint tQty = tmpl->getItem(item);\n\t\tmoveRightByValue(tQty, true);\n\t}\n\n\t// lastly check and report what's missing\n\tstd::string craftName = c->getName(_game->getLanguage());\n\tstd::vector<ReequipStat> _missingItems;\n\tfor (const auto& templateItem : *tmpl->getContents())\n\t{\n\t\tconst RuleItem *item = templateItem.first;\n\t\tif (item)\n\t\t{\n\t\t\tint tQty = templateItem.second;\n\t\t\tint cQty = 0;\n\t\t\tif (item->getVehicleUnit())\n\t\t\t{\n\t\t\t\t// Note: we will also report HWPs as missing:\n\t\t\t\t// - if there is not enough ammo to arm them\n\t\t\t\t// - if there is not enough cargo space in the craft\n\t\t\t\tcQty = c->getVehicleCount(item->getType());\n\t\t\t\tif (onlyAddItems)\n\t\t\t\t{\n\t\t\t\t\tint total = 0;\n\t\t\t\t\tfor (const auto* vehicle : craftVehiclesBackup)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (vehicle->getRules() == item)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttotal++;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tcQty -= total; // i.e. only count newly added vehicles\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tcQty = c->getItems()->getItem(item);\n\t\t\t\tif (onlyAddItems)\n\t\t\t\t{\n\t\t\t\t\tcQty -= craftItemsBackup.getItem(item); // i.e. only count newly added items\n\t\t\t\t}\n\t\t\t}\n\t\t\tint missing = tQty - cQty;\n\t\t\tif (missing > 0)\n\t\t\t{\n\t\t\t\tReequipStat stat = { item->getType(), missing, craftName, item->getListOrder() };\n\t\t\t\t_missingItems.push_back(stat);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (!_missingItems.empty())\n\t{\n\t\tstd::sort(_missingItems.begin(), _missingItems.end(), [](const ReequipStat &a, const ReequipStat &b)\n\t\t\t{\n\t\t\t\treturn a.listOrder < b.listOrder;\n\t\t\t}\n\t\t);\n\t\t_game->pushState(new CannotReequipState(_missingItems, _base));\n\t}\n\n\t// turn back the original setting\n\tOptions::oxceAlternateCraftEquipmentManagement = backup;\n}\n\n/**\n* Opens the CraftEquipmentLoadState screen.\n* @param action Pointer to an action.\n*/\nvoid CraftEquipmentState::btnLoadClick(Action *)\n{\n\t//if (!_isNewBattle)\n\t{\n\t\t_game->pushState(new CraftEquipmentLoadState(this));\n\t\t_returningFromGlobalTemplates = true;\n\t}\n}\n\n/**\n* Opens the CraftEquipmentSaveState screen.\n* @param action Pointer to an action.\n*/\nvoid CraftEquipmentState::btnSaveClick(Action *)\n{\n\tif (!_isNewBattle)\n\t{\n\t\t_game->pushState(new CraftEquipmentSaveState(this));\n\t\t_returningFromGlobalTemplates = true;\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/CraftEquipmentState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/TouchState.h\"\n#include <vector>\n#include <map>\n#include <string>\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass TextEdit;\nclass TextList;\nclass ComboBox;\nclass Timer;\nclass Base;\n\n/**\n * Equipment screen that lets the player\n * pick the equipment to carry on a craft.\n */\nclass CraftEquipmentState : public TouchState\n{\nprivate:\n\tTextButton *_btnOk, *_btnClear, *_btnInventory;\n\tTextEdit *_btnQuickSearch;\n\tWindow *_window;\n\tText *_txtTitle, *_txtItem, *_txtStores, *_txtAvailable, *_txtUsed, *_txtCrew;\n\tstd::vector<std::string> _categoryStrings;\n\tstd::map<std::string, bool> _usedCategoryStrings;\n\tComboBox *_cbxFilterBy;\n\tTextList *_lstEquipment;\n\tsize_t _lstScroll;\n\tTimer *_timerLeft, *_timerRight;\n\tsize_t _sel, _craft;\n\tBase *_base;\n\tstd::vector<std::string> _items;\n\tint _totalItems;\n\tdouble _totalItemStorageSize;\n\tUint8 _ammoColor;\n\tbool _reload;\n\tbool _returningFromGlobalTemplates;\n\tbool _returningFromInventory;\n\tbool _firstInit;\n\tbool _isNewBattle;\n\t/// Updates quantities of item.\n\tvoid updateQuantity();\n\t/// initializes the displayed list\n\tvoid initList();\npublic:\n\t/// Creates the Craft Equipment state.\n\tCraftEquipmentState(Base *base, size_t craft);\n\t/// Cleans up the Craft Equipment state.\n\t~CraftEquipmentState();\n\t/// Handler for changing the filter by combobox.\n\tvoid cbxFilterByChange(Action *action);\n\t/// Resets state.\n\tvoid init() override;\n\t/// Runs the timers.\n\tvoid think() override;\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handlers for Quick Search.\n\tvoid btnQuickSearchToggle(Action *action);\n\tvoid btnQuickSearchApply(Action *action);\n\t/// Handler for pressing a Move Left arrow in the list.\n\tvoid lstEquipmentLeftArrowPress(Action *action);\n\t/// Handler for releasing a Move Left arrow in the list.\n\tvoid lstEquipmentLeftArrowRelease(Action *action);\n\t/// Handler for clicking a Move Left arrow in the list.\n\tvoid lstEquipmentLeftArrowClick(Action *action);\n\t/// Handler for pressing a Move Right arrow in the list.\n\tvoid lstEquipmentRightArrowPress(Action *action);\n\t/// Handler for releasing a Move Right arrow in the list.\n\tvoid lstEquipmentRightArrowRelease(Action *action);\n\t/// Handler for clicking a Move Right arrow in the list.\n\tvoid lstEquipmentRightArrowClick(Action *action);\n\t/// Handler for pressing-down a mouse-button in the list.\n\tvoid lstEquipmentMousePress(Action *action);\n\t/// Moves an item to the base.\n\tvoid moveLeft();\n\t/// Moves the given number of items to the base.\n\tvoid moveLeftByValue(int change);\n\t/// Moves an item to the craft.\n\tvoid moveRight();\n\t/// Moves the given number of items to the craft.\n\tvoid moveRightByValue(int change, bool suppressErrors = false);\n\t/// Empties the contents of the craft, moving all of the items back to the base.\n\tvoid btnClearClick(Action *action);\n\t/// Handler for clicking the Inventory button.\n\tvoid btnInventoryClick(Action *action);\n\t/// Methods for handling the global craft loadout save/load hotkeys.\n\tvoid saveGlobalLoadout(int index);\n\tvoid loadGlobalLoadout(int index, bool onlyAddItems = false);\n\t/// Handler for clicking the Load button.\n\tvoid btnLoadClick(Action *action);\n\t/// Handler for clicking the Save button.\n\tvoid btnSaveClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/CraftInfoState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"CraftInfoState.h\"\n#include <cmath>\n#include <sstream>\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Logger.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextEdit.h\"\n#include \"../Engine/SurfaceSet.h\"\n#include \"../Engine/Action.h\"\n#include \"../Savegame/ItemContainer.h\"\n#include \"../Savegame/Craft.h\"\n#include \"../Mod/RuleCraft.h\"\n#include \"../Savegame/CraftWeapon.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Mod/RuleCraftWeapon.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Vehicle.h\"\n#include \"CraftSoldiersState.h\"\n#include \"CraftWeaponsState.h\"\n#include \"CraftEquipmentState.h\"\n#include \"CraftArmorState.h\"\n#include \"CraftPilotsState.h\"\n#include \"../Ufopaedia/Ufopaedia.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Craft Info screen.\n * @param game Pointer to the core game.\n * @param base Pointer to the base to get info from.\n * @param craftId ID of the selected craft.\n */\nCraftInfoState::CraftInfoState(Base *base, size_t craftId) : _base(base), _craftId(craftId), _craft(0)\n{\n\t// Create objects\n\tif (_game->getSavedGame()->getMonthsPassed() != -1)\n\t{\n\t\t_window = new Window(this, 320, 200, 0, 0, POPUP_BOTH);\n\t}\n\telse\n\t{\n\t\t_window = new Window(this, 320, 200, 0, 0, POPUP_NONE);\n\t}\n\n\t_craft = _base->getCrafts()->at(_craftId);\n\t_weaponNum = _craft->getRules()->getWeapons();\n\tif (_weaponNum > RuleCraft::WeaponMax)\n\t\t_weaponNum = RuleCraft::WeaponMax;\n\n\tint showNewBattle = 0;\n\tif (_game->getSavedGame()->getDebugMode() && _game->getSavedGame()->getMonthsPassed() != -1)\n\t{\n\t\t// only the first craft can be used\n\t\tif (_craftId == 0 && _craft->getRules()->isForNewBattle())\n\t\t{\n\t\t\tshowNewBattle = 1;\n\t\t}\n\t}\n\n\tconst int top = _weaponNum > 2 ? 42 : 64;\n\tconst int top_row = 41;\n\tconst int bottom = 125;\n\tconst int bottom_row = 17;\n\tbool pilots = _craft->getRules()->getPilots() > 0;\n\t_btnOk = new TextButton((pilots ? 218 : 288) - showNewBattle * 98, 16, pilots ? 86 : 16, 176);\n\t_btnNewBattle = new TextButton(92, 16, 212, 176);\n\tfor (int i = 0; i < _weaponNum; ++i)\n\t{\n\t\tconst int x = i % 2 ? 282 : 14;\n\t\tconst int y = top + (i / 2) * top_row;\n\t\t_btnW[i] = new TextButton(24, 32, x, y);\n\t}\n\t_btnCrew = new TextButton(64, 16, 16, bottom);\n\t_btnEquip = new TextButton(64, 16, 16, bottom + bottom_row);\n\t_btnArmor = new TextButton(64, 16, 16, bottom + 2 * bottom_row);\n\t_btnPilots = new TextButton(64, 16, 16, bottom + 3 * bottom_row);\n\t_edtCraft = new TextEdit(this, 140, 16, 80, 8);\n\t_txtDamage = new Text(100, 17, 14, 24);\n\t_txtShield = new Text(100, 17, 120, 24);\n\t_txtFuel = new Text(82, 17, 228, 24);\n\t_txtSkin = new Text(32, 9, 144, 46);\n\tfor (int i = 0; i < _weaponNum; ++i)\n\t{\n\t\tconst int x = i % 2 ? 204 : 46;\n\t\tconst int y = top + (i / 2) * top_row;\n\t\tconst int d = i % 2 ? 20 : 0;\n\t\t_txtWName[i] = new Text(95, 16, x - d, y);\n\t\t_txtWAmmo[i] = new Text(75, 24, x, y + 16);\n\t}\n\t_sprite = new InteractiveSurface(32, 40, 144, 56);\n\tfor (int i = 0; i < _weaponNum; ++i)\n\t{\n\t\tconst int x = i % 2 ? 184 : 121;\n\t\tconst int y = top + 16 + (i / 2) * top_row;\n\t\t_weapon[i] = new InteractiveSurface(15, 17, x, y);\n\t}\n\t_crew = new Surface(220, 18, 85, bottom - 1);\n\t_equip = new Surface(220, 18, 85, bottom + bottom_row);\n\n\t// Set palette\n\tsetInterface(\"craftInfo\");\n\n\tadd(_window, \"window\", \"craftInfo\");\n\tadd(_btnOk, \"button\", \"craftInfo\");\n\tadd(_btnNewBattle, \"button\", \"craftInfo\");\n\tfor (int i = 0; i < _weaponNum; ++i)\n\t{\n\t\tadd(_btnW[i], \"button\", \"craftInfo\");\n\t}\n\tadd(_btnCrew, \"button\", \"craftInfo\");\n\tadd(_btnEquip, \"button\", \"craftInfo\");\n\tadd(_btnArmor, \"button\", \"craftInfo\");\n\tadd(_btnPilots, \"button\", \"craftInfo\");\n\tadd(_edtCraft, \"text1\", \"craftInfo\");\n\tadd(_txtDamage, \"text1\", \"craftInfo\");\n\tadd(_txtShield, \"text1\", \"craftInfo\");\n\tadd(_txtFuel, \"text1\", \"craftInfo\");\n\tadd(_txtSkin, \"text1\", \"craftInfo\");\n\tfor (int i = 0; i < _weaponNum; ++i)\n\t{\n\t\tadd(_txtWName[i], \"text2\", \"craftInfo\");\n\t\tadd(_txtWAmmo[i], \"text3\", \"craftInfo\");\n\t\tadd(_weapon[i]);\n\t}\n\tadd(_sprite);\n\tadd(_crew);\n\tadd(_equip);\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"craftInfo\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&CraftInfoState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&CraftInfoState::btnOkClick, Options::keyCancel);\n\t_btnOk->onKeyboardPress((ActionHandler)&CraftInfoState::btnUfopediaClick, Options::keyGeoUfopedia);\n\n\t_btnNewBattle->setText(tr(\"STR_NEW_BATTLE\"));\n\t_btnNewBattle->onMouseClick((ActionHandler)&CraftInfoState::btnNewBattleClick);\n\t_btnNewBattle->setVisible(showNewBattle > 0);\n\n\tfor (int i = 0; i < _weaponNum; ++i)\n\t{\n\t\tconst char num[] = { char('1' + i), 0 };\n\t\t_btnW[i]->setText(num);\n\t\t_btnW[i]->onMouseClick((ActionHandler)&CraftInfoState::btnWClick);\n\t\t_weapon[i]->onMouseClick((ActionHandler)&CraftInfoState::btnWIconClick);\n\t\t_weapon[i]->onMouseClick((ActionHandler)&CraftInfoState::btnWIconMiddleClick, SDL_BUTTON_MIDDLE);\n\t}\n\n\t_sprite->onMouseClick((ActionHandler)&CraftInfoState::btnCraftIconClick);\n\n\t_btnCrew->setText(tr(\"STR_CREW\"));\n\t_btnCrew->onMouseClick((ActionHandler)&CraftInfoState::btnCrewClick);\n\n\t_btnEquip->setText(tr(\"STR_EQUIPMENT_UC\"));\n\t_btnEquip->onMouseClick((ActionHandler)&CraftInfoState::btnEquipClick);\n\n\t_btnArmor->setText(tr(\"STR_ARMOR\"));\n\t_btnArmor->onMouseClick((ActionHandler)&CraftInfoState::btnArmorClick);\n\n\t_btnPilots->setText(tr(\"STR_PILOTS\"));\n\t_btnPilots->onMouseClick((ActionHandler)&CraftInfoState::btnPilotsClick);\n\t_btnPilots->setVisible(pilots);\n\n\t_edtCraft->setBig();\n\t_edtCraft->setAlign(ALIGN_CENTER);\n\t_edtCraft->onChange((ActionHandler)&CraftInfoState::edtCraftChange);\n\n\t_txtSkin->setAlign(ALIGN_CENTER);\n\tif (_craft->getRules()->getMaxSkinIndex() > 0)\n\t{\n\t\t_txtSkin->setText(tr(\"STR_CRAFT_SKIN_ID\").arg(_craft->getSkinIndex()));\n\t}\n\n\tfor (int i =0; i < _weaponNum; ++i)\n\t{\n\t\t_txtWName[i]->setWordWrap(true);\n\t}\n}\n\n/**\n *\n */\nCraftInfoState::~CraftInfoState()\n{\n\n}\n\n/**\n * The craft info can change\n * after going into other screens.\n */\nvoid CraftInfoState::init()\n{\n\tState::init();\n\n\t_edtCraft->setText(_craft->getName(_game->getLanguage()));\n\n\t_sprite->clear();\n\tSurfaceSet *texture = _game->getMod()->getSurfaceSet(\"BASEBITS.PCK\");\n\ttexture->getFrame(_craft->getSkinSprite() + 33)->blitNShade(_sprite, 0, 0);\n\n\tstd::ostringstream firlsLine;\n\tfirlsLine << tr(\"STR_DAMAGE_UC_\").arg(Unicode::formatPercentage(_craft->getDamagePercentage()));\n\tif (_craft->getStatus() == \"STR_REPAIRS\" && _craft->getDamage() > 0)\n\t{\n\t\tint damageHours = (int)ceil((double)_craft->getDamage() / _craft->getRules()->getRepairRate());\n\t\tfirlsLine << formatTime(damageHours);\n\t}\n\t_txtDamage->setText(firlsLine.str());\n\n\tstd::ostringstream secondLine;\n\tsecondLine << tr(\"STR_FUEL\").arg(Unicode::formatPercentage(_craft->getFuelPercentage()));\n\tif (_craft->getStatus() == \"STR_REFUELLING\" && _craft->getFuelMax() - _craft->getFuel() > 0)\n\t{\n\t\tint fuelHours = (int)ceil((double)(_craft->getFuelMax() - _craft->getFuel()) / _craft->getRules()->getRefuelRate() / 2.0);\n\t\tsecondLine << formatTime(fuelHours);\n\t}\n\t_txtFuel->setText(secondLine.str());\n\n\tstd::ostringstream thirdLine;\n\tif (_craft->getShieldCapacity() != 0)\n\t{\n\t\tthirdLine << tr(\"STR_SHIELD\").arg(Unicode::formatPercentage(_craft->getShieldPercentage()));\n\t\tif (_craft->getShield() < _craft->getShieldCapacity())\n\t\t{\n\t\t\tif (_craft->getRules()->getShieldRechargeAtBase() != 0)\n\t\t\t{\n\t\t\t\tint shieldHours = (int)ceil((double)(_craft->getShieldCapacity() - _craft->getShield()) / _craft->getRules()->getShieldRechargeAtBase());\n\t\t\t\tthirdLine << formatTime(shieldHours);\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\tthirdLine << \"\";\n\t}\n\t_txtShield->setText(thirdLine.str());\n\n\tif (_craft->getRules()->getMaxUnitsLimit() > 0)\n\t{\n\t\t_crew->clear();\n\t\t_equip->clear();\n\n\t\tSurface *frame1 = texture->getFrame(38);\n\n\t\tSurfaceSet *customArmorPreviews = _game->getMod()->getSurfaceSet(\"CustomArmorPreviews\");\n\t\tint x = 0;\n\t\tfor (const auto* soldier : *_base->getSoldiers())\n\t\t{\n\t\t\tif (soldier->getCraft() == _craft)\n\t\t\t{\n\t\t\t\tfor (int index : soldier->getArmor()->getCustomArmorPreviewIndex())\n\t\t\t\t{\n\t\t\t\t\tSurface *customFrame1 = customArmorPreviews->getFrame(index);\n\t\t\t\t\tif (customFrame1)\n\t\t\t\t\t{\n\t\t\t\t\t\t// modded armor previews\n\t\t\t\t\t\tcustomFrame1->blitNShade(_crew, x, 0);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// vanilla\n\t\t\t\t\t\tframe1->blitNShade(_crew, x, 0);\n\t\t\t\t\t}\n\t\t\t\t\tx += 10;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tSurface *frame2 = texture->getFrame(40);\n\n\t\tSurfaceSet *customItemPreviews = _game->getMod()->getSurfaceSet(\"CustomItemPreviews\");\n\t\tx = 0;\n\t\tfor (const auto* vehicle : *_craft->getVehicles())\n\t\t{\n\t\t\tfor (int index : vehicle->getRules()->getCustomItemPreviewIndex())\n\t\t\t{\n\t\t\t\tSurface *customFrame2 = customItemPreviews->getFrame(index);\n\t\t\t\tif (customFrame2)\n\t\t\t\t{\n\t\t\t\t\t// modded HWP/auxiliary previews\n\t\t\t\t\tcustomFrame2->blitNShade(_equip, x, 0);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// vanilla\n\t\t\t\t\tframe2->blitNShade(_equip, x, 0);\n\t\t\t\t}\n\t\t\t\tx += 10;\n\t\t\t}\n\t\t}\n\n\t\tSurface *frame3 = texture->getFrame(39);\n\n\t\tusing ArrayIndexes = std::array<int, 3>;\n\t\tusing ArraySurfaces = std::array<const Surface *, 3>;\n\t\tstd::map<ArrayIndexes, std::tuple<ArraySurfaces, size_t>, std::greater<>> itemsBySprite;\n\n\t\tfor (auto& item : *_craft->getItems()->getContents())\n\t\t{\n\t\t\tArrayIndexes ind = { };\n\n\t\t\t// fill default values\n\t\t\tfor (auto& arr : ind)\n\t\t\t{\n\t\t\t\tarr = -1;\n\t\t\t}\n\n\t\t\t// load values from config, zip will clip range to min length of one of arguments\n\t\t\tfor (auto [arr, prev] : Collections::zipTie(Collections::range(ind), Collections::range(item.first->getCustomItemPreviewIndex())))\n\t\t\t{\n\t\t\t\tarr = prev;\n\t\t\t}\n\n\t\t\tauto& pos = itemsBySprite[ind];\n\n\t\t\t// update surfaces if not set yet\n\t\t\tfor (auto [surf, arr] : Collections::zipTie(Collections::range(std::get<ArraySurfaces>(pos)), Collections::range(ind)))\n\t\t\t{\n\t\t\t\tif (surf != nullptr || arr < 0)\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tsurf = customItemPreviews->getFrame(arr);\n\t\t\t}\n\n\t\t\tstd::get<size_t>(pos) += item.second;\n\t\t}\n\n\t\tfor (const auto& pair : itemsBySprite)\n\t\t{\n\t\t\tconst auto& pos = pair.second;\n\t\t\tif (std::get<ArraySurfaces>(pos)[0])\n\t\t\t{\n\t\t\t\t// new logic for items grouped by sprite\n\t\t\t\tsize_t i = 4, next = 8;\n\n\t\t\t\t// draw icons for next \"fibonacci\" item count\n\t\t\t\tdo\n\t\t\t\t{\n\t\t\t\t\tfor (auto& s : std::get<ArraySurfaces>(pos))\n\t\t\t\t\t{\n\t\t\t\t\t\tif (s)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ts->blitNShade(_equip, x, 0);\n\t\t\t\t\t\t\tx += 10;\n\t\t\t\t\t\t\ti = std::exchange(next, next + i); // calling this here make multi part sprites occupy similar size to single part ones\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\twhile (i <= std::get<size_t>(pos));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// classic behavior\n\t\t\t\tfor (size_t i = 0; i < std::get<size_t>(pos); i += 4)\n\t\t\t\t{\n\t\t\t\t\tframe3->blitNShade(_equip, x, 0);\n\t\t\t\t\tx += 10;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\t_crew->setVisible(false);\n\t\t_equip->setVisible(false);\n\t\t_btnCrew->setVisible(false);\n\t\t_btnEquip->setVisible(false);\n\t\t_btnArmor->setVisible(false);\n\t\t_btnPilots->setVisible(false);\n\t}\n\n\tfor (int i = 0; i < _weaponNum; ++i)\n\t{\n\t\tCraftWeapon *w1 = _craft->getWeapons()->at(i);\n\n\t\t_weapon[i]->clear();\n\t\tif (w1 != 0)\n\t\t{\n\t\t\tSurface *frame = texture->getFrame(w1->getRules()->getSprite() + 48);\n\t\t\tframe->blitNShade(_weapon[i], 0, 0);\n\n\t\t\tstd::ostringstream weaponLine;\n\t\t\tif (w1->isDisabled()) weaponLine << \"*\";\n\t\t\tweaponLine << Unicode::TOK_COLOR_FLIP << tr(w1->getRules()->getType());\n\t\t\t_txtWName[i]->setText(weaponLine.str());\n\t\t\tweaponLine.str(\"\");\n\t\t\tif (!w1->getRules()->getTooltip().empty())\n\t\t\t{\n\t\t\t\tweaponLine << (tr(w1->getRules()->getTooltip())\n\t\t\t\t\t.arg(w1->getAmmo())                                    // {0}\n\t\t\t\t\t.arg(w1->getRules()->getAmmoMax())                     // {1}\n\t\t\t\t\t.arg(w1->getRules()->getBonusStats().fuelMax)          // {2}\n\t\t\t\t\t.arg(w1->getRules()->getBonusStats().speedMax)         // {3}\n\t\t\t\t\t.arg(w1->getRules()->getBonusStats().damageMax)        // {4}\n\t\t\t\t\t.arg(w1->getRules()->getBonusStats().armor)            // {5}\n\t\t\t\t\t.arg(w1->getRules()->getBonusStats().shieldCapacity)); // {6}\n\t\t\t}\n\t\t\telse if (w1->getRules()->getAmmoMax())\n\t\t\t{\n\t\t\t\tweaponLine << tr(\"STR_AMMO_\").arg(w1->getAmmo()) << \"\\n\" << Unicode::TOK_COLOR_FLIP;\n\t\t\t\tweaponLine << tr(\"STR_MAX\").arg(w1->getRules()->getAmmoMax());\n\t\t\t\tif (_craft->getStatus() == \"STR_REARMING\" && w1->getAmmo() < w1->getRules()->getAmmoMax() && !w1->isDisabled())\n\t\t\t\t{\n\t\t\t\t\tint rearmHours = (int)ceil((double)(w1->getRules()->getAmmoMax() - w1->getAmmo()) / w1->getRules()->getRearmRate());\n\t\t\t\t\tweaponLine << formatTime(rearmHours);\n\t\t\t\t}\n\t\t\t}\n\t\t\t_txtWAmmo[i]->setText(weaponLine.str());\n\t\t\tif (!_craft->getRules()->getFixedWeaponInSlot(i).empty())\n\t\t\t{\n\t\t\t\t_btnW[i]->setVisible(false); // cannot remove or change a fixed weapon\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_txtWName[i]->setText(\"\");\n\t\t\t_txtWAmmo[i]->setText(\"\");\n\t\t}\n\t}\n\n}\n\n/**\n * Turns an amount of time into a\n * day/hour string.\n * @param total Amount in hours.\n */\nstd::string CraftInfoState::formatTime(int total)\n{\n\tstd::ostringstream ss;\n\tint days = total / 24;\n\tint hours = total % 24;\n\tss << \"\\n(\";\n\tif (days > 0)\n\t{\n\t\tss << tr(\"STR_DAY\", days) << \"/\";\n\t}\n\tif (hours > 0)\n\t{\n\t\tss << tr(\"STR_HOUR\", hours);\n\t}\n\tss << \")\";\n\treturn ss.str();\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid CraftInfoState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Opens the corresponding Ufopaedia craft article.\n * @param action Pointer to an action.\n */\nvoid CraftInfoState::btnUfopediaClick(Action *)\n{\n\tif (_craft)\n\t{\n\t\tstd::string articleId = _craft->getRules()->getType();\n\t\tUfopaedia::openArticle(_game, articleId);\n\t}\n}\n\n/**\n * Updates the New Battle file (battle.cfg) and returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid CraftInfoState::btnNewBattleClick(Action *)\n{\n\t_game->popState();\n\n\tsize_t mission = 0;\n\tsize_t craft = 0;\n\tsize_t darkness = 0;\n\tsize_t terrain = 0;\n\tsize_t alienRace = 0;\n\tsize_t difficulty = 0;\n\tsize_t alienTech = 0;\n\n\tstd::string s = Options::getMasterUserFolder() + \"battle.cfg\";\n\tif (!CrossPlatform::fileExists(s))\n\t{\n\t\t// nothing\n\t}\n\telse\n\t{\n\t\ttry\n\t\t{\n\t\t\tYAML::YamlRootNodeReader reader(s);\n\t\t\tmission = reader[\"mission\"].readVal(0);\n\t\t\t//craft = reader[\"craft\"].readVal(0);\n\t\t\tdarkness = reader[\"darkness\"].readVal(0);\n\t\t\tterrain = reader[\"terrain\"].readVal(0);\n\t\t\talienRace = reader[\"alienRace\"].readVal(0);\n\t\t\t//difficulty = reader[\"difficulty\"].readVal(0);\n\t\t\talienTech = reader[\"alienTech\"].readVal(0);\n\t\t}\n\t\tcatch (YAML::Exception& e)\n\t\t{\n\t\t\tLog(LOG_WARNING) << e.what();\n\t\t}\n\t}\n\n\t// index of the craft type in the New Battle combobox\n\tsize_t idx = 0;\n\tfor (auto& craftType : _game->getMod()->getCraftsList())\n\t{\n\t\tconst RuleCraft* rule = _game->getMod()->getCraft(craftType);\n\t\tif (rule->isForNewBattle())\n\t\t{\n\t\t\tif (rule == _craft->getRules())\n\t\t\t{\n\t\t\t\tcraft = idx;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t++idx;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// don't increase the index, these crafts are not in the New Battle combobox\n\t\t}\n\t}\n\n\t// transfer also the difficulty\n\tdifficulty = _game->getSavedGame()->getDifficulty();\n\n\tYAML::YamlRootNodeWriter writer;\n\twriter.setAsMap();\n\twriter.write(\"mission\", mission);\n\twriter.write(\"craft\", craft);\n\twriter.write(\"darkness\", darkness);\n\twriter.write(\"terrain\", terrain);\n\twriter.write(\"alienRace\", alienRace);\n\twriter.write(\"difficulty\", difficulty);\n\twriter.write(\"alienTech\", alienTech);\n\t_base->save(writer[\"base\"]);\n\tstd::string yaml = writer.emit().yaml;\n\n\tif (!CrossPlatform::writeFile(s, yaml))\n\t{\n\t\tLog(LOG_WARNING) << \"Failed to save \" << s;\n\t}\n}\n\n/**\n * Goes to the Select Armament window\n * for the weapons.\n * @param action Pointer to an action.\n */\nvoid CraftInfoState::btnWClick(Action * act)\n{\n\tfor (int i = 0; i < _weaponNum; ++i)\n\t{\n\t\tif (act->getSender() == _btnW[i])\n\t\t{\n\t\t\t_game->pushState(new CraftWeaponsState(_base, _craftId, i));\n\t\t\treturn;\n\t\t}\n\t}\n}\n\n/**\n * Toggles the enabled/disabled status of the weapon.\n * @param action Pointer to an action.\n */\nvoid CraftInfoState::btnWIconClick(Action *action)\n{\n\tfor (int i = 0; i < _weaponNum; ++i)\n\t{\n\t\tif (action->getSender() == _weapon[i])\n\t\t{\n\t\t\tCraftWeapon *w1 = _craft->getWeapons()->at(i);\n\t\t\tif (w1)\n\t\t\t{\n\t\t\t\t// Toggle the weapon status\n\t\t\t\tw1->setDisabled(!w1->isDisabled());\n\n\t\t\t\t// If we just enabled the weapon, we should begin rearming immediately.\n\t\t\t\tif (!w1->isDisabled())\n\t\t\t\t{\n\t\t\t\t\t_craft->checkup();\n\t\t\t\t}\n\n\t\t\t\t// Update the onscreen info.\n\t\t\t\t// Note: This method is overkill, since we only need to update a few things. But at least this ensures we haven't missed anything.\n\t\t\t\tinit();\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Opens the corresponding Ufopaedia craft weapon article.\n * @param action Pointer to an action.\n */\nvoid CraftInfoState::btnWIconMiddleClick(Action* action)\n{\n\tfor (int i = 0; i < _weaponNum; ++i)\n\t{\n\t\tif (action->getSender() == _weapon[i])\n\t\t{\n\t\t\tCraftWeapon* w1 = _craft->getWeapons()->at(i);\n\t\t\tif (w1)\n\t\t\t{\n\t\t\t\tRuleCraftWeapon* rule = w1->getRules();\n\t\t\t\tif (rule)\n\t\t\t\t{\n\t\t\t\t\tstd::string articleId = rule->getUfopediaType();\n\t\t\t\t\tUfopaedia::openArticle(_game, articleId);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Toggles the craft skin.\n * @param action Pointer to an action.\n */\nvoid CraftInfoState::btnCraftIconClick(Action *action)\n{\n\tif (_craft->getRules()->getMaxSkinIndex() > 0)\n\t{\n\t\tint newIndex = _craft->getSkinIndex() + 1;\n\t\tif (newIndex > _craft->getRules()->getMaxSkinIndex())\n\t\t{\n\t\t\tnewIndex = 0;\n\t\t}\n\t\t_craft->setSkinIndex(newIndex);\n\n\t\t_txtSkin->setText(tr(\"STR_CRAFT_SKIN_ID\").arg(_craft->getSkinIndex()));\n\n\t\t_sprite->clear();\n\t\tSurfaceSet* texture = _game->getMod()->getSurfaceSet(\"BASEBITS.PCK\");\n\t\ttexture->getFrame(_craft->getSkinSprite() + 33)->blitNShade(_sprite, 0, 0);\n\t}\n}\n\n/**\n * Goes to the Select Squad screen.\n * @param action Pointer to an action.\n */\nvoid CraftInfoState::btnCrewClick(Action *)\n{\n\t_game->pushState(new CraftSoldiersState(_base, _craftId));\n}\n\n/**\n * Goes to the Select Equipment screen.\n * @param action Pointer to an action.\n */\nvoid CraftInfoState::btnEquipClick(Action *)\n{\n\t_game->pushState(new CraftEquipmentState(_base, _craftId));\n}\n\n/**\n * Goes to the Select Armor screen.\n * @param action Pointer to an action.\n */\nvoid CraftInfoState::btnArmorClick(Action *)\n{\n\t_game->pushState(new CraftArmorState(_base, _craftId));\n}\n\n/**\n * Goes to the Pilots Info screen.\n * @param action Pointer to an action.\n */\nvoid CraftInfoState::btnPilotsClick(Action *)\n{\n\t_game->pushState(new CraftPilotsState(_base, _craftId));\n}\n\n/**\n * Changes the Craft name.\n * @param action Pointer to an action.\n */\nvoid CraftInfoState::edtCraftChange(Action *action)\n{\n\tif (_edtCraft->getText() == _craft->getDefaultName(_game->getLanguage()))\n\t{\n\t\t_craft->setName(\"\");\n\t}\n\telse\n\t{\n\t\t_craft->setName(_edtCraft->getText());\n\t}\n\tif (action->getDetails()->key.keysym.sym == SDLK_RETURN ||\n\t\taction->getDetails()->key.keysym.sym == SDLK_KP_ENTER)\n\t{\n\t\t_edtCraft->setText(_craft->getName(_game->getLanguage()));\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/CraftInfoState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include \"../Mod/RuleCraft.h\"\n\nnamespace OpenXcom\n{\n\nclass Base;\nclass InteractiveSurface;\nclass TextButton;\nclass Window;\nclass Text;\nclass TextEdit;\nclass Surface;\nclass Craft;\n\n/**\n * Craft Info screen that shows all the\n * info of a specific craft.\n */\nclass CraftInfoState : public State\n{\nprivate:\n\tBase *_base;\n\tsize_t _craftId;\n\tCraft *_craft;\n\tint _weaponNum;\n\n\tTextButton *_btnOk, *_btnW[RuleCraft::WeaponMax], *_btnCrew, *_btnEquip, *_btnArmor, *_btnPilots, *_btnNewBattle;\n\tWindow *_window;\n\tTextEdit *_edtCraft;\n\tText *_txtDamage, *_txtShield, *_txtFuel, *_txtSkin;\n\tText *_txtWName[RuleCraft::WeaponMax], *_txtWAmmo[RuleCraft::WeaponMax];\n\tInteractiveSurface *_sprite, *_weapon[RuleCraft::WeaponMax];\n\tSurface *_crew, *_equip;\n\t/// Formats an amount of time.\n\tstd::string formatTime(int time);\npublic:\n\t/// Creates the Craft Info state.\n\tCraftInfoState(Base *base, size_t craftId);\n\t/// Cleans up the Craft Info state.\n\t~CraftInfoState();\n\t/// Updates the craft info.\n\tvoid init() override;\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the Ufopedia button.\n\tvoid btnUfopediaClick(Action *action);\n\t/// Handler for clicking the New Battle button.\n\tvoid btnNewBattleClick(Action *action);\n\t/// Handler for clicking the weapon button.\n\tvoid btnWClick(Action *action);\n\t/// Handler for clicking one of the weapon icons.\n\tvoid btnWIconClick(Action *action);\n\tvoid btnWIconMiddleClick(Action* action);\n\t/// Handler for clicking one of the craft icon.\n\tvoid btnCraftIconClick(Action *action);\n\t/// Handler for clicking the Crew button.\n\tvoid btnCrewClick(Action *action);\n\t/// Handler for clicking the Equipment button.\n\tvoid btnEquipClick(Action *action);\n\t/// Handler for clicking the Armor button.\n\tvoid btnArmorClick(Action *action);\n\t/// Handler for clicking the Pilots button.\n\tvoid btnPilotsClick(Action *action);\n\t/// Handler for changing the text on the Name edit.\n\tvoid edtCraftChange(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/CraftPilotSelectState.cpp",
    "content": "/*\n * Copyright 2010-2015 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"CraftPilotSelectState.h\"\n#include <sstream>\n#include <algorithm>\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/Craft.h\"\n#include \"../Savegame/Soldier.h\"\n#include \"../Mod/RuleSoldier.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Soldier Armor window.\n * @param game Pointer to the core game.\n * @param base Pointer to the base to get info from.\n * @param soldier ID of the selected soldier.\n */\nCraftPilotSelectState::CraftPilotSelectState(Base *base, size_t craft) : _base(base), _craft(craft)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 232, 156, 44, 28, POPUP_BOTH);\n\t_btnCancel = new TextButton(180, 16, 70, 158);\n\t_txtTitle = new Text(222, 9, 49, 36);\n\t_txtName = new Text(120, 9, 60, 52);\n\t_txtFiringAcc = new Text(20, 9, 190, 52);\n\t_txtReactions = new Text(20, 9, 210, 52);\n\t_txtBravery = new Text(20, 9, 230, 52);\n\t_lstPilot = new TextList(200, 80, 53, 68);\n\n\tsetInterface(\"craftPilotsSelect\");\n\n\tadd(_window, \"window\", \"craftPilotsSelect\");\n\tadd(_btnCancel, \"button\", \"craftPilotsSelect\");\n\tadd(_txtTitle, \"text2\", \"craftPilotsSelect\");\n\tadd(_txtName, \"text1\", \"craftPilotsSelect\");\n\tadd(_txtFiringAcc, \"text1\", \"craftPilotsSelect\");\n\tadd(_txtReactions, \"text1\", \"craftPilotsSelect\");\n\tadd(_txtBravery, \"text1\", \"craftPilotsSelect\");\n\tadd(_lstPilot, \"list\", \"craftPilotsSelect\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"craftPilotsSelect\");\n\n\t_btnCancel->setText(tr(\"STR_CANCEL_UC\"));\n\t_btnCancel->onMouseClick((ActionHandler)&CraftPilotSelectState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&CraftPilotSelectState::btnCancelClick, Options::keyCancel);\n\n\tCraft *c = _base->getCrafts()->at(_craft);\n\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_SELECT_PILOT\"));\n\n\t_txtName->setText(tr(\"STR_NAME\"));\n\n\t_txtFiringAcc->setText(tr(\"STR_FIRING_ACCURACY_ABBREVIATION\"));\n\t_txtReactions->setText(tr(\"STR_REACTIONS_ABBREVIATION\"));\n\t_txtBravery->setText(tr(\"STR_BRAVERY_ABBREVIATION\"));\n\n\t_lstPilot->setColumns(4, 124, 20, 20, 20);\n\t_lstPilot->setAlign(ALIGN_RIGHT);\n\t_lstPilot->setAlign(ALIGN_LEFT, 0);\n\t_lstPilot->setSelectable(true);\n\t_lstPilot->setBackground(_window);\n\t_lstPilot->setMargin(8);\n\n\tfor (const auto* soldier : *_base->getSoldiers())\n\t{\n\t\t// must be on board & able to drive\n\t\tif (soldier->getCraft() == c && soldier->hasAllPilotingRequirements())\n\t\t{\n\t\t\t// is not assigned yet\n\t\t\tif (!c->isPilot(soldier->getId()))\n\t\t\t{\n\t\t\t\t_pilot.push_back(soldier->getId());\n\n\t\t\t\tstd::ostringstream ss1;\n\t\t\t\tss1 << soldier->getStatsWithSoldierBonusesOnly()->firing;\n\t\t\t\tstd::ostringstream ss2;\n\t\t\t\tss2 << soldier->getStatsWithSoldierBonusesOnly()->reactions;\n\t\t\t\tstd::ostringstream ss3;\n\t\t\t\tss3 << soldier->getStatsWithSoldierBonusesOnly()->bravery;\n\t\t\t\t_lstPilot->addRow(4, soldier->getName(false).c_str(), ss1.str().c_str(), ss2.str().c_str(), ss3.str().c_str());\n\t\t\t}\n\t\t}\n\t}\n\n\t_lstPilot->onMouseClick((ActionHandler)&CraftPilotSelectState::lstPilotClick);\n}\n\n/**\n *\n */\nCraftPilotSelectState::~CraftPilotSelectState()\n{\n\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid CraftPilotSelectState::btnCancelClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Adds the selected pilot to the list and returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid CraftPilotSelectState::lstPilotClick(Action *)\n{\n\tint pilotId = _pilot[_lstPilot->getSelectedRow()];\n\tCraft *c = _base->getCrafts()->at(_craft);\n\tc->addPilot(pilotId);\n\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/CraftPilotSelectState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2015 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <vector>\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass Base;\nclass Soldier;\nclass TextButton;\nclass Window;\nclass Text;\nclass TextList;\n\n/**\n * Select Pilot window that allows assigning a pilot to a craft.\n */\nclass CraftPilotSelectState : public State\n{\nprivate:\n\tBase *_base;\n\tsize_t _craft;\n\n\tTextButton *_btnCancel;\n\tWindow *_window;\n\tText *_txtTitle, *_txtName, *_txtFiringAcc, *_txtReactions, *_txtBravery;\n\tTextList *_lstPilot;\n\tstd::vector<int> _pilot;\npublic:\n\t/// Creates the Select Pilot state.\n\tCraftPilotSelectState(Base *base, size_t craft);\n\t/// Cleans up the Select Pilot state.\n\t~CraftPilotSelectState();\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action *action);\n\t/// Handler for clicking the Pilot list.\n\tvoid lstPilotClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/CraftPilotsState.cpp",
    "content": "/*\n * Copyright 2010-2015 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"CraftPilotsState.h\"\n#include \"CraftPilotSelectState.h\"\n#include <sstream>\n#include <algorithm>\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/Craft.h\"\n#include \"../Mod/RuleCraft.h\"\n#include \"../Savegame/Soldier.h\"\n#include \"../Mod/RuleSoldier.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Craft Pilots screen.\n */\nCraftPilotsState::CraftPilotsState(Base *base, size_t craft) : _base(base), _craft(craft)\n{\n\t// Create objects\n\t_window = new Window(this, 320, 200, 0, 0);\n\t_btnOk = new TextButton(300, 20, 10, 170);\n\t_txtTitle = new Text(310, 17, 5, 12);\n\t_txtFiringAcc = new Text(108, 9, 74, 32);\n\t_txtReactions = new Text(58, 9, 182, 32);\n\t_txtBravery = new Text(58, 9, 240, 32);\n\t_txtPilots = new Text(150, 9, 10, 40);\n\t_lstPilots = new TextList(288, 32, 10, 48);\n\t_btnAdd = new TextButton(146, 20, 10, 96);\n\t_btnRemoveAll = new TextButton(146, 20, 164, 96);\n\n\t_txtRequired = new Text(288, 9, 10, 84);\n\n\t_txtAccuracyBonus = new Text(100, 9, 10, 128);\n\t_txtAccuracyBonusValue = new Text(150, 9, 110, 128);\n\t_txtDodgeBonus = new Text(100, 9, 10, 140);\n\t_txtDodgeBonusValue = new Text(150, 9, 110, 140);\n\t_txtApproachSpeed = new Text(100, 9, 10, 152);\n\t_txtApproachSpeedValue = new Text(150, 9, 110, 152);\n\n\t// Set palette\n\tsetInterface(\"craftPilots\");\n\n\tadd(_window, \"window\", \"craftPilots\");\n\tadd(_btnOk, \"button\", \"craftPilots\");\n\tadd(_txtTitle, \"text1\", \"craftPilots\");\n\tadd(_txtFiringAcc, \"text1\", \"craftPilots\");\n\tadd(_txtReactions, \"text1\", \"craftPilots\");\n\tadd(_txtBravery, \"text1\", \"craftPilots\");\n\tadd(_txtPilots, \"text1\", \"craftPilots\");\n\tadd(_lstPilots, \"list\", \"craftPilots\");\n\tadd(_btnAdd, \"button\", \"craftPilots\");\n\tadd(_btnRemoveAll, \"button\", \"craftPilots\");\n\tadd(_txtRequired, \"text1\", \"craftPilots\");\n\tadd(_txtAccuracyBonus, \"text1\", \"craftPilots\");\n\tadd(_txtAccuracyBonusValue, \"text2\", \"craftPilots\");\n\tadd(_txtDodgeBonus, \"text1\", \"craftPilots\");\n\tadd(_txtDodgeBonusValue, \"text2\", \"craftPilots\");\n\tadd(_txtApproachSpeed, \"text1\", \"craftPilots\");\n\tadd(_txtApproachSpeedValue, \"text2\", \"craftPilots\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"craftPilots\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&CraftPilotsState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&CraftPilotsState::btnOkClick, Options::keyOk);\n\t_btnOk->onKeyboardPress((ActionHandler)&CraftPilotsState::btnOkClick, Options::keyCancel);\n\n\tCraft *c = _base->getCrafts()->at(_craft);\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_PILOTS_FOR_CRAFT\").arg(c->getName(_game->getLanguage())));\n\n\t_txtFiringAcc->setText(tr(\"STR_FIRING_ACCURACY\"));\n\t_txtFiringAcc->setAlign(ALIGN_RIGHT);\n\n\t_txtReactions->setText(tr(\"STR_REACTIONS\"));\n\t_txtReactions->setAlign(ALIGN_RIGHT);\n\n\t_txtBravery->setText(tr(\"STR_BRAVERY\"));\n\t_txtBravery->setAlign(ALIGN_RIGHT);\n\n\t_txtPilots->setText(tr(\"STR_PILOTS\"));\n\n\t_lstPilots->setColumns(5, 114, 58, 58, 58, 0);\n\t_lstPilots->setAlign(ALIGN_RIGHT);\n\t_lstPilots->setAlign(ALIGN_LEFT, 0);\n\t_lstPilots->setDot(true);\n\n\t_txtRequired->setText(tr(\"STR_PILOTS_REQUIRED\").arg(c->getRules()->getPilots()));\n\n\t_btnAdd->setText(tr(\"STR_ADD_PILOT\"));\n\t_btnAdd->onMouseClick((ActionHandler)&CraftPilotsState::btnAddClick);\n\t_btnRemoveAll->setText(tr(\"STR_REMOVE_ALL_PILOTS\"));\n\t_btnRemoveAll->onMouseClick((ActionHandler)&CraftPilotsState::btnRemoveAllClick);\n\n\t_txtAccuracyBonus->setText(tr(\"STR_ACCURACY_BONUS\"));\n\t_txtDodgeBonus->setText(tr(\"STR_DODGE_BONUS\"));\n\t_txtApproachSpeed->setText(tr(\"STR_APPROACH_SPEED\"));\n\n\tfor (auto* soldier : *_base->getSoldiers())\n\t{\n\t\tif (soldier->getCraft() == c)\n\t\t{\n\t\t\tsoldier->prepareStatsWithBonuses(_game->getMod()); // refresh soldier bonuses\n\t\t}\n\t}\n}\n\n/**\n *\n */\nCraftPilotsState::~CraftPilotsState()\n{\n\n}\n\n/**\n* Initializes the state.\n*/\nvoid CraftPilotsState::init()\n{\n\tState::init();\n\tupdateUI();\n}\n\n/**\n* Updates the data on the screen.\n*/\nvoid CraftPilotsState::updateUI()\n{\n\t_lstPilots->clearList();\n\n\tCraft *c = _base->getCrafts()->at(_craft);\n\n\tconst std::vector<Soldier*> pilots = c->getPilotList(false, nullptr); // stats already refreshed in the constructor\n\tfor (const auto* pilot : pilots)\n\t{\n\t\tstd::ostringstream ss1;\n\t\tss1 << pilot->getStatsWithSoldierBonusesOnly()->firing;\n\t\tstd::ostringstream ss2;\n\t\tss2 << pilot->getStatsWithSoldierBonusesOnly()->reactions;\n\t\tstd::ostringstream ss3;\n\t\tss3 << pilot->getStatsWithSoldierBonusesOnly()->bravery;\n\t\t_lstPilots->addRow(5, pilot->getName(false).c_str(), ss1.str().c_str(), ss2.str().c_str(), ss3.str().c_str(), \"\");\n\t}\n\n\tstd::ostringstream ss1;\n\tint accBonus = c->getPilotAccuracyBonus(pilots, _game->getMod());\n\tss1 << (accBonus > 0 ? \"+\" : \"\") << accBonus << \"%\";\n\t_txtAccuracyBonusValue->setText(ss1.str().c_str());\n\n\tstd::ostringstream ss2;\n\tint dodgeBonus = c->getPilotDodgeBonus(pilots, _game->getMod());\n\tss2 << (dodgeBonus > 0 ? \"+\" : \"\") << dodgeBonus << \"%\";\n\t_txtDodgeBonusValue->setText(ss2.str().c_str());\n\n\tstd::ostringstream ss3;\n\tint approachSpeed = c->getPilotApproachSpeedModifier(pilots, _game->getMod());\n\tswitch (approachSpeed)\n\t{\n\tcase 1:\n\t\tss3 << tr(\"STR_COWARDLY\");\n\t\tbreak;\n\tcase 2:\n\t\tss3 << tr(\"STR_NORMAL\");\n\t\tbreak;\n\tcase 3:\n\t\tss3 << tr(\"STR_BOLD\");\n\t\tbreak;\n\tcase 4:\n\t\tss3 << tr(\"STR_VERY_BOLD\");\n\t\tbreak;\n\tdefault:\n\t\tss3 << tr(\"STR_UNKNOWN\");\n\t\tbreak;\n\t}\n\t_txtApproachSpeedValue->setText(ss3.str().c_str());\n\n\t_btnAdd->setVisible((int)(_lstPilots->getTexts()) < c->getRules()->getPilots());\n\n\tint availablePilots = 0;\n\tfor (const auto* soldier : *_base->getSoldiers())\n\t{\n\t\t// must be on board & able to drive\n\t\tif (soldier->getCraft() == c && soldier->hasAllPilotingRequirements())\n\t\t{\n\t\t\tavailablePilots++;\n\t\t}\n\t}\n\t_btnRemoveAll->setVisible(availablePilots != c->getRules()->getPilots());\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid CraftPilotsState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n* Opens a Pilot Selection screen.\n* @param action Pointer to an action.\n*/\nvoid CraftPilotsState::btnAddClick(Action *)\n{\n\t_game->pushState(new CraftPilotSelectState(_base, _craft));\n}\n\n/**\n* Clears the pilot list.\n* @param action Pointer to an action.\n*/\nvoid CraftPilotsState::btnRemoveAllClick(Action *)\n{\n\tCraft *c = _base->getCrafts()->at(_craft);\n\n\tc->removeAllPilots();\n\n\tupdateUI();\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/CraftPilotsState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2015 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass Base;\nclass TextButton;\nclass Window;\nclass Text;\nclass TextList;\n\n/**\n * Displays info about craft pilot(s).\n */\nclass CraftPilotsState : public State\n{\nprivate:\n\tBase *_base;\n\tsize_t _craft;\n\n\tTextButton *_btnOk, *_btnAdd, *_btnRemoveAll;\n\tWindow *_window;\n\tText *_txtTitle, *_txtFiringAcc, *_txtReactions, *_txtBravery, *_txtPilots;\n\tText *_txtRequired;\n\tTextList *_lstPilots;\n\tText *_txtAccuracyBonus, *_txtAccuracyBonusValue;\n\tText *_txtDodgeBonus, *_txtDodgeBonusValue;\n\tText *_txtApproachSpeed, *_txtApproachSpeedValue;\n\t/// Updates the UI data.\n\tvoid updateUI();\npublic:\n\t/// Creates the Craft Pilots state.\n\tCraftPilotsState(Base *base, size_t craft);\n\t/// Cleans up the Craft Pilots state.\n\t~CraftPilotsState();\n\t/// Initializes the state.\n\tvoid init() override;\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the Add button.\n\tvoid btnAddClick(Action *action);\n\t/// Handler for clicking the RemoveAll button.\n\tvoid btnRemoveAllClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/CraftSoldiersState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"CraftSoldiersState.h\"\n#include <algorithm>\n#include <functional>\n#include <climits>\n#include <algorithm>\n#include \"../Engine/Action.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/ComboBox.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Menu/ErrorMessageState.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/Soldier.h\"\n#include \"../Savegame/Craft.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"SoldierInfoState.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Mod/RuleInterface.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Battlescape/BattlescapeGenerator.h\"\n#include \"../Battlescape/BriefingState.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Craft Soldiers screen.\n * @param game Pointer to the core game.\n * @param base Pointer to the base to get info from.\n * @param craft ID of the selected craft.\n */\nCraftSoldiersState::CraftSoldiersState(Base *base, size_t craft)\n\t\t:  _base(base), _craft(craft), _otherCraftColor(0), _origSoldierOrder(*_base->getSoldiers()), _dynGetter(NULL)\n{\n\tbool hidePreview = _game->getSavedGame()->getMonthsPassed() == -1;\n\tCraft *c = _base->getCrafts()->at(_craft);\n\tif (c && !c->getRules()->isForNewBattle())\n\t{\n\t\t// no battlescape map available\n\t\thidePreview = true;\n\t}\n\n\t// Create objects\n\t_window = new Window(this, 320, 200, 0, 0);\n\t_btnOk = new TextButton(hidePreview ? 148 : 30, 16, hidePreview ? 164 : 274, 176);\n\t_btnPreview = new TextButton(102, 16, 164, 176);\n\t_txtTitle = new Text(300, 17, 16, 7);\n\t_txtName = new Text(114, 9, 16, 32);\n\t_txtRank = new Text(102, 9, 122, 32);\n\t_txtCraft = new Text(84, 9, 220, 32);\n\t_txtAvailable = new Text(110, 9, 16, 24);\n\t_txtUsed = new Text(110, 9, 122, 24);\n\t_cbxSortBy = new ComboBox(this, 148, 16, 8, 176, true);\n\t_lstSoldiers = new TextList(288, 128, 8, 40);\n\n\ttouchComponentsCreate(_txtTitle, true);\n\n\t// Set palette\n\tsetInterface(\"craftSoldiers\");\n\n\tadd(_window, \"window\", \"craftSoldiers\");\n\tadd(_btnOk, \"button\", \"craftSoldiers\");\n\tadd(_btnPreview, \"button\", \"craftSoldiers\");\n\tadd(_txtTitle, \"text\", \"craftSoldiers\");\n\tadd(_txtName, \"text\", \"craftSoldiers\");\n\tadd(_txtRank, \"text\", \"craftSoldiers\");\n\tadd(_txtCraft, \"text\", \"craftSoldiers\");\n\tadd(_txtAvailable, \"text\", \"craftSoldiers\");\n\tadd(_txtUsed, \"text\", \"craftSoldiers\");\n\tadd(_lstSoldiers, \"list\", \"craftSoldiers\");\n\tadd(_cbxSortBy, \"button\", \"craftSoldiers\");\n\n\ttouchComponentsAdd(\"button2\", \"craftSoldiers\", _window);\n\n\t_otherCraftColor = _game->getMod()->getInterface(\"craftSoldiers\")->getElement(\"otherCraft\")->color;\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"craftSoldiers\");\n\n\ttouchComponentsConfigure();\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&CraftSoldiersState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&CraftSoldiersState::btnOkClick, Options::keyCancel);\n\t_btnOk->onKeyboardPress((ActionHandler)&CraftSoldiersState::btnDeassignAllSoldiersClick, Options::keyRemoveSoldiersFromAllCrafts);\n\t_btnOk->onKeyboardPress((ActionHandler)&CraftSoldiersState::btnDeassignCraftSoldiersClick, Options::keyRemoveSoldiersFromCraft);\n\n\t_btnPreview->setText(tr(\"STR_CRAFT_DEPLOYMENT_PREVIEW\"));\n\t_btnPreview->setVisible(!hidePreview);\n\t_btnPreview->onMouseClick((ActionHandler)&CraftSoldiersState::btnPreviewClick);\n\n\t_txtTitle->setBig();\n\tif (Options::oxceBaseTouchButtons)\n\t{\n\t\t_txtTitle->setAlign(ALIGN_CENTER);\n\t\t_txtTitle->setText(c->getName(_game->getLanguage()));\n\t}\n\telse\n\t{\n\t\t_txtTitle->setAlign(ALIGN_LEFT);\n\t\t_txtTitle->setText(tr(\"STR_SELECT_SQUAD_FOR_CRAFT\").arg(c->getName(_game->getLanguage())));\n\t}\n\n\t_txtName->setText(tr(\"STR_NAME_UC\"));\n\n\t_txtRank->setText(tr(\"STR_RANK\"));\n\n\t_txtCraft->setText(tr(\"STR_CRAFT\"));\n\n\t// populate sort options\n\tstd::vector<std::string> sortOptions;\n\tsortOptions.push_back(tr(\"STR_ORIGINAL_ORDER\"));\n\t_sortFunctors.push_back(NULL);\n\n#define PUSH_IN(strId, functor) \\\n\tsortOptions.push_back(tr(strId)); \\\n\t_sortFunctors.push_back(new SortFunctor(_game, functor));\n\n\tPUSH_IN(\"STR_ID\", idStat);\n\tPUSH_IN(\"STR_NAME_UC\", nameStat);\n\tPUSH_IN(\"STR_CRAFT\", craftIdStat);\n\tPUSH_IN(\"STR_SOLDIER_TYPE\", typeStat);\n\tPUSH_IN(\"STR_RANK\", rankStat);\n\tPUSH_IN(\"STR_IDLE_DAYS\", idleDaysStat);\n\tPUSH_IN(\"STR_MISSIONS2\", missionsStat);\n\tPUSH_IN(\"STR_KILLS2\", killsStat);\n\tPUSH_IN(\"STR_WOUND_RECOVERY2\", woundRecoveryStat);\n\tif (_game->getMod()->isManaFeatureEnabled() && !_game->getMod()->getReplenishManaAfterMission())\n\t{\n\t\tPUSH_IN(\"STR_MANA_MISSING\", manaMissingStat);\n\t}\n\tPUSH_IN(\"STR_TIME_UNITS\", tuStat);\n\tPUSH_IN(\"STR_STAMINA\", staminaStat);\n\tPUSH_IN(\"STR_HEALTH\", healthStat);\n\tPUSH_IN(\"STR_BRAVERY\", braveryStat);\n\tPUSH_IN(\"STR_REACTIONS\", reactionsStat);\n\tPUSH_IN(\"STR_FIRING_ACCURACY\", firingStat);\n\tPUSH_IN(\"STR_THROWING_ACCURACY\", throwingStat);\n\tPUSH_IN(\"STR_MELEE_ACCURACY\", meleeStat);\n\tPUSH_IN(\"STR_STRENGTH\", strengthStat);\n\tif (_game->getMod()->isManaFeatureEnabled())\n\t{\n\t\t// \"unlock\" is checked later\n\t\tPUSH_IN(\"STR_MANA_POOL\", manaStat);\n\t}\n\tPUSH_IN(\"STR_PSIONIC_STRENGTH\", psiStrengthStat);\n\tPUSH_IN(\"STR_PSIONIC_SKILL\", psiSkillStat);\n\n#undef PUSH_IN\n\n\t_cbxSortBy->setOptions(sortOptions);\n\t_cbxSortBy->setSelected(0);\n\t_cbxSortBy->onChange((ActionHandler)&CraftSoldiersState::cbxSortByChange);\n\t_cbxSortBy->setText(tr(\"STR_SORT_BY\"));\n\n\t_lstSoldiers->setArrowColumn(188, ARROW_VERTICAL);\n\t_lstSoldiers->setColumns(3, 106, 98, 76);\n\t_lstSoldiers->setAlign(ALIGN_RIGHT, 3);\n\t_lstSoldiers->setSelectable(true);\n\t_lstSoldiers->setBackground(_window);\n\t_lstSoldiers->setMargin(8);\n\t_lstSoldiers->onLeftArrowClick((ActionHandler)&CraftSoldiersState::lstItemsLeftArrowClick);\n\t_lstSoldiers->onRightArrowClick((ActionHandler)&CraftSoldiersState::lstItemsRightArrowClick);\n\t_lstSoldiers->onMouseClick((ActionHandler)&CraftSoldiersState::lstSoldiersClick, 0);\n\t_lstSoldiers->onMousePress((ActionHandler)&CraftSoldiersState::lstSoldiersMousePress);\n}\n\n/**\n * cleans up dynamic state\n */\nCraftSoldiersState::~CraftSoldiersState()\n{\n\tfor (auto* sortFunctor : _sortFunctors)\n\t{\n\t\tdelete sortFunctor;\n\t}\n}\n\n/**\n * Sorts the soldiers list by the selected criterion\n * @param action Pointer to an action.\n */\nvoid CraftSoldiersState::cbxSortByChange(Action *)\n{\n\tbool ctrlPressed = _game->isCtrlPressed(true);\n\tsize_t selIdx = _cbxSortBy->getSelected();\n\tif (selIdx == (size_t)-1)\n\t{\n\t\treturn;\n\t}\n\n\tSortFunctor *compFunc = _sortFunctors[selIdx];\n\t_dynGetter = NULL;\n\tif (compFunc)\n\t{\n\t\tif (selIdx != 2 && selIdx != 3)\n\t\t{\n\t\t\t_dynGetter = compFunc->getGetter();\n\t\t}\n\n\t\t// if CTRL is pressed, we only want to show the dynamic column, without actual sorting\n\t\tif (!ctrlPressed)\n\t\t{\n\t\t\tif (selIdx == 2)\n\t\t\t{\n\t\t\t\tstd::stable_sort(_base->getSoldiers()->begin(), _base->getSoldiers()->end(),\n\t\t\t\t\t[](const Soldier* a, const Soldier* b)\n\t\t\t\t\t{\n\t\t\t\t\t\treturn Unicode::naturalCompare(a->getName(), b->getName());\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t}\n\t\t\telse if (selIdx == 3)\n\t\t\t{\n\t\t\t\tstd::stable_sort(_base->getSoldiers()->begin(), _base->getSoldiers()->end(),\n\t\t\t\t\t[](const Soldier* a, const Soldier* b)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (a->getCraft())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (b->getCraft())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (a->getCraft()->getRules() == b->getCraft()->getRules())\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\treturn a->getCraft()->getId() < b->getCraft()->getId();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\treturn a->getCraft()->getRules() < b->getCraft()->getRules();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\treturn true; // a < b\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn false; // b > a\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tstd::stable_sort(_base->getSoldiers()->begin(), _base->getSoldiers()->end(), *compFunc);\n\t\t\t}\n\t\t\tif (_game->isShiftPressed(true))\n\t\t\t{\n\t\t\t\tstd::reverse(_base->getSoldiers()->begin(), _base->getSoldiers()->end());\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\t// restore original ordering, ignoring (of course) those\n\t\t// soldiers that have been sacked since this state started\n\t\tfor (const auto* origSoldier : _origSoldierOrder)\n\t\t{\n\t\t\tauto soldierIt = std::find(_base->getSoldiers()->begin(), _base->getSoldiers()->end(), origSoldier);\n\t\t\tif (soldierIt != _base->getSoldiers()->end())\n\t\t\t{\n\t\t\t\tSoldier *s = *soldierIt;\n\t\t\t\t_base->getSoldiers()->erase(soldierIt);\n\t\t\t\t_base->getSoldiers()->insert(_base->getSoldiers()->end(), s);\n\t\t\t}\n\t\t}\n\t}\n\n\tsize_t originalScrollPos = _lstSoldiers->getScroll();\n\tinitList(originalScrollPos);\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid CraftSoldiersState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Shows the battlescape preview.\n * @param action Pointer to an action.\n */\nvoid CraftSoldiersState::btnPreviewClick(Action *)\n{\n\tCraft* c = _base->getCrafts()->at(_craft);\n\tif (c->getSpaceUsed() <= 0)\n\t{\n\t\t// at least one unit must be onboard\n\t\treturn;\n\t}\n\n\tSavedBattleGame* bgame = new SavedBattleGame(_game->getMod(), _game->getLanguage(), true);\n\t_game->getSavedGame()->setBattleGame(bgame);\n\tBattlescapeGenerator bgen = BattlescapeGenerator(_game);\n\tbgame->setMissionType(c->getRules()->getCustomPreviewType());\n\tbgame->setCraftForPreview(c);\n\tbgen.setCraft(c);\n\tbgen.run();\n\n\t// needed for preview of craft deployment tiles\n\tbgame->setCraftPos(bgen.getCraftPos());\n\tbgame->setCraftZ(bgen.getCraftZ());\n\tbgame->calculateCraftTiles();\n\n\t_game->pushState(new BriefingState(c));\n}\n\n/**\n * Shows the soldiers in a list at specified offset/scroll.\n */\nvoid CraftSoldiersState::initList(size_t scrl)\n{\n\tint row = 0;\n\t_lstSoldiers->clearList();\n\n\tif (_dynGetter != NULL)\n\t{\n\t\t_lstSoldiers->setColumns(4, 106, 98, 60, 16);\n\t}\n\telse\n\t{\n\t\t_lstSoldiers->setColumns(3, 106, 98, 76);\n\t}\n\n\tCraft *c = _base->getCrafts()->at(_craft);\n\tBaseSumDailyRecovery recovery = _base->getSumRecoveryPerDay();\n\tfor (const auto* soldier : *_base->getSoldiers())\n\t{\n\t\tif (_dynGetter != NULL)\n\t\t{\n\t\t\t// call corresponding getter\n\t\t\tint dynStat = (*_dynGetter)(_game, soldier);\n\t\t\tstd::ostringstream ss;\n\t\t\tss << dynStat;\n\t\t\t_lstSoldiers->addRow(4, soldier->getName(true, 19).c_str(), tr(soldier->getRankString()).c_str(), soldier->getCraftString(_game->getLanguage(), recovery).c_str(), ss.str().c_str());\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_lstSoldiers->addRow(3, soldier->getName(true, 19).c_str(), tr(soldier->getRankString()).c_str(), soldier->getCraftString(_game->getLanguage(), recovery).c_str());\n\t\t}\n\n\t\tUint8 color;\n\t\tif (soldier->getCraft() == c)\n\t\t{\n\t\t\tcolor = _lstSoldiers->getSecondaryColor();\n\t\t}\n\t\telse if (soldier->getCraft() != 0)\n\t\t{\n\t\t\tcolor = _otherCraftColor;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tcolor = _lstSoldiers->getColor();\n\t\t}\n\t\t_lstSoldiers->setRowColor(row, color);\n\t\trow++;\n\t}\n\tif (scrl)\n\t\t_lstSoldiers->scrollTo(scrl);\n\t_lstSoldiers->draw();\n\n\t_txtAvailable->setText(tr(\"STR_SPACE_AVAILABLE\").arg(c->getSpaceAvailable()));\n\t_txtUsed->setText(tr(\"STR_SPACE_USED\").arg(c->getSpaceUsed()));\n}\n\n/**\n * Shows the soldiers in a list.\n */\nvoid CraftSoldiersState::init()\n{\n\tState::init();\n\t_base->prepareSoldierStatsWithBonuses(); // refresh stats for sorting\n\tinitList(_lstSoldiers->getScroll());\n\n\t// update the label to indicate presence of a saved craft deployment\n\tCraft* c = _base->getCrafts()->at(_craft);\n\tif (c->hasCustomDeployment())\n\t\t_btnPreview->setText(tr(\"STR_CRAFT_DEPLOYMENT_PREVIEW_SAVED\"));\n\telse\n\t\t_btnPreview->setText(tr(\"STR_CRAFT_DEPLOYMENT_PREVIEW\"));\n\n\ttouchComponentsRefresh();\n}\n\n/**\n * Reorders a soldier up.\n * @param action Pointer to an action.\n */\nvoid CraftSoldiersState::lstItemsLeftArrowClick(Action *action)\n{\n\tunsigned int row = _lstSoldiers->getSelectedRow();\n\tif (row > 0)\n\t{\n\t\tif (_game->isLeftClick(action, true))\n\t\t{\n\t\t\tmoveSoldierUp(action, row);\n\t\t}\n\t\telse if (_game->isRightClick(action, true))\n\t\t{\n\t\t\tmoveSoldierUp(action, row, true);\n\t\t}\n\t}\n\t_cbxSortBy->setText(tr(\"STR_SORT_BY\"));\n\t_cbxSortBy->setSelected(-1);\n}\n\n/**\n * Moves a soldier up on the list.\n * @param action Pointer to an action.\n * @param row Selected soldier row.\n * @param max Move the soldier to the top?\n */\nvoid CraftSoldiersState::moveSoldierUp(Action *action, unsigned int row, bool max)\n{\n\tSoldier *s = _base->getSoldiers()->at(row);\n\tif (max)\n\t{\n\t\t_base->getSoldiers()->erase(_base->getSoldiers()->begin() + row);\n\t\t_base->getSoldiers()->insert(_base->getSoldiers()->begin(), s);\n\t}\n\telse\n\t{\n\t\t_base->getSoldiers()->at(row) = _base->getSoldiers()->at(row - 1);\n\t\t_base->getSoldiers()->at(row - 1) = s;\n\t\tif (row != _lstSoldiers->getScroll())\n\t\t{\n\t\t\tSDL_WarpMouse(action->getLeftBlackBand() + action->getXMouse(), action->getTopBlackBand() + action->getYMouse() - static_cast<Uint16>(8 * action->getYScale()));\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_lstSoldiers->scrollUp(false);\n\t\t}\n\t}\n\tinitList(_lstSoldiers->getScroll());\n}\n\n/**\n * Reorders a soldier down.\n * @param action Pointer to an action.\n */\nvoid CraftSoldiersState::lstItemsRightArrowClick(Action *action)\n{\n\tunsigned int row = _lstSoldiers->getSelectedRow();\n\tsize_t numSoldiers = _base->getSoldiers()->size();\n\tif (0 < numSoldiers && INT_MAX >= numSoldiers && row < numSoldiers - 1)\n\t{\n\t\tif (_game->isLeftClick(action, true))\n\t\t{\n\t\t\tmoveSoldierDown(action, row);\n\t\t}\n\t\telse if (_game->isRightClick(action, true))\n\t\t{\n\t\t\tmoveSoldierDown(action, row, true);\n\t\t}\n\t}\n\t_cbxSortBy->setText(tr(\"STR_SORT_BY\"));\n\t_cbxSortBy->setSelected(-1);\n}\n\n/**\n * Moves a soldier down on the list.\n * @param action Pointer to an action.\n * @param row Selected soldier row.\n * @param max Move the soldier to the bottom?\n */\nvoid CraftSoldiersState::moveSoldierDown(Action *action, unsigned int row, bool max)\n{\n\tSoldier *s = _base->getSoldiers()->at(row);\n\tif (max)\n\t{\n\t\t_base->getSoldiers()->erase(_base->getSoldiers()->begin() + row);\n\t\t_base->getSoldiers()->insert(_base->getSoldiers()->end(), s);\n\t}\n\telse\n\t{\n\t\t_base->getSoldiers()->at(row) = _base->getSoldiers()->at(row + 1);\n\t\t_base->getSoldiers()->at(row + 1) = s;\n\t\tif (row != _lstSoldiers->getVisibleRows() - 1 + _lstSoldiers->getScroll())\n\t\t{\n\t\t\tSDL_WarpMouse(action->getLeftBlackBand() + action->getXMouse(), action->getTopBlackBand() + action->getYMouse() + static_cast<Uint16>(8 * action->getYScale()));\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_lstSoldiers->scrollDown(false);\n\t\t}\n\t}\n\tinitList(_lstSoldiers->getScroll());\n}\n\n/**\n * Shows the selected soldier's info.\n * @param action Pointer to an action.\n */\nvoid CraftSoldiersState::lstSoldiersClick(Action *action)\n{\n\tdouble mx = action->getAbsoluteXMouse();\n\tif (mx >= _lstSoldiers->getArrowsLeftEdge() && mx < _lstSoldiers->getArrowsRightEdge())\n\t{\n\t\treturn;\n\t}\n\tint row = _lstSoldiers->getSelectedRow();\n\tif (_game->isLeftClick(action, true))\n\t{\n\t\tCraft *c = _base->getCrafts()->at(_craft);\n\t\tSoldier *s = _base->getSoldiers()->at(_lstSoldiers->getSelectedRow());\n\t\tif (s->getCraft() == c)\n\t\t{\n\t\t\ts->setCraftAndMoveEquipment(0, _base, _game->getSavedGame()->getMonthsPassed() == -1);\n\t\t\t_lstSoldiers->setCellText(row, 2, tr(\"STR_NONE_UC\"));\n\t\t\t_lstSoldiers->setRowColor(row, _lstSoldiers->getColor());\n\t\t}\n\t\telse if (s->getCraft() && s->getCraft()->getStatus() == \"STR_OUT\")\n\t\t{\n\t\t\t// nothing\n\t\t}\n\t\telse if (s->hasFullHealth())\n\t\t{\n\t\t\tint space = c->getSpaceAvailable();\n\t\t\tCraftPlacementErrors err = c->validateAddingSoldier(space, s);\n\t\t\tif (err == CPE_None)\n\t\t\t{\n\t\t\t\ts->setCraftAndMoveEquipment(c, _base, _game->getSavedGame()->getMonthsPassed() == -1, true);\n\t\t\t\t_lstSoldiers->setCellText(row, 2, c->getName(_game->getLanguage()));\n\t\t\t\t_lstSoldiers->setRowColor(row, _lstSoldiers->getSecondaryColor());\n\n\t\t\t\t// update the label to indicate absence of a saved craft deployment\n\t\t\t\t_btnPreview->setText(tr(\"STR_CRAFT_DEPLOYMENT_PREVIEW\"));\n\t\t\t}\n\t\t\telse if (err == CPE_SoldierGroupNotAllowed)\n\t\t\t{\n\t\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_SOLDIER_GROUP_NOT_ALLOWED\"), _palette, _game->getMod()->getInterface(\"soldierInfo\")->getElement(\"errorMessage\")->color, \"BACK01.SCR\", _game->getMod()->getInterface(\"soldierInfo\")->getElement(\"errorPalette\")->color));\n\t\t\t}\n\t\t\telse if (err == CPE_SoldierGroupNotSame)\n\t\t\t{\n\t\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_SOLDIER_GROUP_NOT_SAME\"), _palette, _game->getMod()->getInterface(\"soldierInfo\")->getElement(\"errorMessage\")->color, \"BACK01.SCR\", _game->getMod()->getInterface(\"soldierInfo\")->getElement(\"errorPalette\")->color));\n\t\t\t}\n\t\t\telse if (err == CPE_ArmorGroupNotAllowed)\n\t\t\t{\n\t\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_ARMOR_GROUP_NOT_ALLOWED\"), _palette, _game->getMod()->getInterface(\"soldierInfo\")->getElement(\"errorMessage\")->color, \"BACK01.SCR\", _game->getMod()->getInterface(\"soldierInfo\")->getElement(\"errorPalette\")->color));\n\t\t\t}\n\t\t\telse if (space > 0)\n\t\t\t{\n\t\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_NOT_ENOUGH_CRAFT_SPACE\"), _palette, _game->getMod()->getInterface(\"soldierInfo\")->getElement(\"errorMessage\")->color, \"BACK01.SCR\", _game->getMod()->getInterface(\"soldierInfo\")->getElement(\"errorPalette\")->color));\n\t\t\t}\n\t\t}\n\n\t\t_txtAvailable->setText(tr(\"STR_SPACE_AVAILABLE\").arg(c->getSpaceAvailable()));\n\t\t_txtUsed->setText(tr(\"STR_SPACE_USED\").arg(c->getSpaceUsed()));\n\t}\n\telse if (_game->isRightClick(action, true))\n\t{\n\t\t_game->pushState(new SoldierInfoState(_base, row, false));\n\t}\n}\n\n/**\n * Handles the mouse-wheels on the arrow-buttons.\n * @param action Pointer to an action.\n */\nvoid CraftSoldiersState::lstSoldiersMousePress(Action *action)\n{\n\tif (Options::changeValueByMouseWheel == 0)\n\t\treturn;\n\tunsigned int row = _lstSoldiers->getSelectedRow();\n\tsize_t numSoldiers = _base->getSoldiers()->size();\n\tif (action->getDetails()->button.button == SDL_BUTTON_WHEELUP &&\n\t\trow > 0)\n\t{\n\t\tif (action->getAbsoluteXMouse() >= _lstSoldiers->getArrowsLeftEdge() &&\n\t\t\taction->getAbsoluteXMouse() <= _lstSoldiers->getArrowsRightEdge())\n\t\t{\n\t\t\tmoveSoldierUp(action, row);\n\t\t}\n\t}\n\telse if (action->getDetails()->button.button == SDL_BUTTON_WHEELDOWN &&\n\t\t\t 0 < numSoldiers && INT_MAX >= numSoldiers && row < numSoldiers - 1)\n\t{\n\t\tif (action->getAbsoluteXMouse() >= _lstSoldiers->getArrowsLeftEdge() &&\n\t\t\taction->getAbsoluteXMouse() <= _lstSoldiers->getArrowsRightEdge())\n\t\t{\n\t\t\tmoveSoldierDown(action, row);\n\t\t}\n\t}\n}\n\n/**\n * De-assign all soldiers from all craft located in the base (i.e. not out on a mission).\n * @param action Pointer to an action.\n */\nvoid CraftSoldiersState::btnDeassignAllSoldiersClick(Action *action)\n{\n\tint row = 0;\n\tfor (auto* soldier : *_base->getSoldiers())\n\t{\n\t\tif (soldier->getCraft() && soldier->getCraft()->getStatus() != \"STR_OUT\")\n\t\t{\n\t\t\tsoldier->setCraftAndMoveEquipment(0, _base, _game->getSavedGame()->getMonthsPassed() == -1);\n\t\t\t_lstSoldiers->setCellText(row, 2, tr(\"STR_NONE_UC\"));\n\t\t\t_lstSoldiers->setRowColor(row, _lstSoldiers->getColor());\n\t\t}\n\t\trow++;\n\t}\n\n\tCraft *c = _base->getCrafts()->at(_craft);\n\t_txtAvailable->setText(tr(\"STR_SPACE_AVAILABLE\").arg(c->getSpaceAvailable()));\n\t_txtUsed->setText(tr(\"STR_SPACE_USED\").arg(c->getSpaceUsed()));\n}\n\n/**\n * De-assign all soldiers from the current craft.\n * @param action Pointer to an action.\n */\nvoid CraftSoldiersState::btnDeassignCraftSoldiersClick(Action *action)\n{\n\tCraft *c = _base->getCrafts()->at(_craft);\n\tint row = 0;\n\tfor (auto* soldier : *_base->getSoldiers())\n\t{\n\t\tif (soldier->getCraft() == c)\n\t\t{\n\t\t\tsoldier->setCraftAndMoveEquipment(0, _base, _game->getSavedGame()->getMonthsPassed() == -1);\n\t\t\t_lstSoldiers->setCellText(row, 2, tr(\"STR_NONE_UC\"));\n\t\t\t_lstSoldiers->setRowColor(row, _lstSoldiers->getColor());\n\t\t}\n\t\trow++;\n\t}\n\n\t_txtAvailable->setText(tr(\"STR_SPACE_AVAILABLE\").arg(c->getSpaceAvailable()));\n\t_txtUsed->setText(tr(\"STR_SPACE_USED\").arg(c->getSpaceUsed()));\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/CraftSoldiersState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/TouchState.h\"\n#include <vector>\n#include \"SoldierSortUtil.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass TextList;\nclass ComboBox;\nclass Base;\nclass Soldier;\nstruct SortFunctor;\n\n/**\n * Select Squad screen that lets the player\n * pick the soldiers to assign to a craft.\n */\nclass CraftSoldiersState : public TouchState\n{\nprivate:\n\tTextButton *_btnOk;\n\tTextButton *_btnPreview;\n\tWindow *_window;\n\tText *_txtTitle, *_txtName, *_txtRank, *_txtCraft, *_txtAvailable, *_txtUsed;\n\tComboBox *_cbxSortBy;\n\tTextList *_lstSoldiers;\n\n\tBase *_base;\n\tsize_t _craft;\n\tUint8 _otherCraftColor;\n\tstd::vector<Soldier *> _origSoldierOrder;\n\tstd::vector<SortFunctor *> _sortFunctors;\n\tgetStatFn_t _dynGetter;\n\t/// initializes the display list based on the craft soldier's list and the position to display\n\tvoid initList(size_t scrl);\npublic:\n\t/// Creates the Craft Soldiers state.\n\tCraftSoldiersState(Base *base, size_t craft);\n\t/// Cleans up the Craft Soldiers state.\n\t~CraftSoldiersState();\n\t/// Handler for changing the sort by combobox.\n\tvoid cbxSortByChange(Action *action);\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the Preview button.\n\tvoid btnPreviewClick(Action *action);\n\t/// Updates the soldiers list.\n\tvoid init() override;\n\t/// Handler for clicking the Soldiers reordering button.\n\tvoid lstItemsLeftArrowClick(Action *action);\n\t/// Moves a soldier up.\n\tvoid moveSoldierUp(Action *action, unsigned int row, bool max = false);\n\t/// Handler for clicking the Soldiers reordering button.\n\tvoid lstItemsRightArrowClick(Action *action);\n\t/// Moves a soldier down.\n\tvoid moveSoldierDown(Action *action, unsigned int row, bool max = false);\n\t/// Handler for clicking the Soldiers list.\n\tvoid lstSoldiersClick(Action *action);\n\t/// Handler for pressing-down a mouse-button in the list.\n\tvoid lstSoldiersMousePress(Action *action);\n\t/// Handler for clicking the De-assign All Soldiers button.\n\tvoid btnDeassignAllSoldiersClick(Action *action);\n\tvoid btnDeassignCraftSoldiersClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/CraftWeaponsState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"CraftWeaponsState.h\"\n#include <sstream>\n#include \"../fmath.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Savegame/Craft.h\"\n#include \"../Savegame/CraftWeapon.h\"\n#include \"../Menu/ErrorMessageState.h\"\n#include \"../Mod/RuleCraft.h\"\n#include \"../Mod/RuleCraftWeapon.h\"\n#include \"../Mod/RuleInterface.h\"\n#include \"../Savegame/ItemContainer.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Ufopaedia/Ufopaedia.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Craft Weapons window.\n * @param game Pointer to the core game.\n * @param base Pointer to the base to get info from.\n * @param craft ID of the selected craft.\n * @param weapon ID of the selected weapon.\n */\nCraftWeaponsState::CraftWeaponsState(Base *base, size_t craft, size_t weapon) : _base(base), _craft(base->getCrafts()->at(craft)), _weapon(weapon)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 220, 160, 50, 20, POPUP_BOTH);\n\t_btnCancel = new TextButton(140, 16, 90, 156);\n\t_txtTitle = new Text(208, 17, 56, 28);\n\t_txtArmament = new Text(76, 9, 66, 52);\n\t_txtQuantity = new Text(50, 9, 140, 52);\n\t_txtAmmunition = new Text(68, 17, 200, 44);\n\t_lstWeapons = new TextList(188, 64, 58, 68);\n\t_txtCurrentWeapon = new Text(188, 9, 66, 140);\n\n\t// Set palette\n\tsetInterface(\"craftWeapons\");\n\n\tadd(_window, \"window\", \"craftWeapons\");\n\tadd(_btnCancel, \"button\", \"craftWeapons\");\n\tadd(_txtTitle, \"text\", \"craftWeapons\");\n\tadd(_txtArmament, \"text\", \"craftWeapons\");\n\tadd(_txtQuantity, \"text\", \"craftWeapons\");\n\tadd(_txtAmmunition, \"text\", \"craftWeapons\");\n\tadd(_lstWeapons, \"list\", \"craftWeapons\");\n\tadd(_txtCurrentWeapon, \"text\", \"craftWeapons\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"craftWeapons\");\n\n\t_btnCancel->setText(tr(\"STR_CANCEL_UC\"));\n\t_btnCancel->onMouseClick((ActionHandler)&CraftWeaponsState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&CraftWeaponsState::btnCancelClick, Options::keyCancel);\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_SELECT_ARMAMENT\"));\n\n\t_txtArmament->setText(tr(\"STR_ARMAMENT\"));\n\n\t_txtQuantity->setText(tr(\"STR_QUANTITY_UC\"));\n\n\t_txtAmmunition->setText(tr(\"STR_AMMUNITION_AVAILABLE\"));\n\t_txtAmmunition->setWordWrap(true);\n\t_txtAmmunition->setVerticalAlign(ALIGN_BOTTOM);\n\n\tconst std::string slotName = _craft->getRules()->getWeaponSlotString(weapon);\n\tCraftWeapon *current = _craft->getWeapons()->at(_weapon);\n\tif (current != 0)\n\t{\n\t\t_txtCurrentWeapon->setText(tr(slotName).arg(tr(current->getRules()->getType())));\n\t}\n\telse\n\t{\n\t\t_txtCurrentWeapon->setText(tr(slotName).arg(tr(\"STR_NONE_UC\")));\n\t}\n\n\t_lstWeapons->setColumns(3, 94, 50, 36);\n\t_lstWeapons->setSelectable(true);\n\t_lstWeapons->setBackground(_window);\n\t_lstWeapons->setMargin(8);\n\n\t_lstWeapons->addRow(1, tr(\"STR_NONE_UC\").c_str());\n\t_weapons.push_back(0);\n\n\tfor (auto& craftWeaponType : _game->getMod()->getCraftWeaponsList())\n\t{\n\t\tRuleCraftWeapon *w = _game->getMod()->getCraftWeapon(craftWeaponType);\n\t\tconst RuleCraft *c = _craft->getRules();\n\t\tbool isResearched = _game->getSavedGame()->isResearched(w->getLauncherItem()->getRequirements());\n\t\tif (w->getClipItem())\n\t\t{\n\t\t\tisResearched = isResearched && _game->getSavedGame()->isResearched(w->getClipItem()->getRequirements());\n\t\t}\n\t\tif (isResearched && _base->getStorageItems()->getItem(w->getLauncherItem()) > 0 && c->isValidWeaponSlot(weapon, w->getWeaponType()))\n\t\t{\n\t\t\t_weapons.push_back(w);\n\t\t\tstd::ostringstream ss, ss2;\n\t\t\tss << _base->getStorageItems()->getItem(w->getLauncherItem());\n\t\t\tif (w->getClipItem())\n\t\t\t{\n\t\t\t\tss2 << _base->getStorageItems()->getItem(w->getClipItem());\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tss2 << tr(\"STR_NOT_AVAILABLE\");\n\t\t\t}\n\t\t\t_lstWeapons->addRow(3, tr(w->getType()).c_str(), ss.str().c_str(), ss2.str().c_str());\n\t\t}\n\t}\n\t_lstWeapons->onMouseClick((ActionHandler)&CraftWeaponsState::lstWeaponsClick);\n\t_lstWeapons->onMouseClick((ActionHandler)&CraftWeaponsState::lstWeaponsMiddleClick, SDL_BUTTON_MIDDLE);\n}\n\n/**\n *\n */\nCraftWeaponsState::~CraftWeaponsState()\n{\n\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid CraftWeaponsState::btnCancelClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Equips the weapon on the craft and returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid CraftWeaponsState::lstWeaponsClick(Action *)\n{\n\tCraftWeapon *current = _craft->getWeapons()->at(_weapon);\n\n\tconst RuleCraftWeapon* refWeapon = _weapons[_lstWeapons->getSelectedRow()];\n\tconst RuleCraftWeapon* currWeapon = current ? current->getRules() : nullptr;\n\t{\n\t\tint refCapBonus1 = refWeapon ? refWeapon->getBonusStats().soldiers : 0;\n\t\tint currCapBonus1 = currWeapon ? currWeapon->getBonusStats().soldiers : 0;\n\t\tint diff1 = (refCapBonus1 - currCapBonus1);\n\t\tif (diff1)\n\t\t{\n\t\t\tif ((_craft->getMaxUnitsRaw() - _craft->getSpaceUsed() + diff1) < 0)\n\t\t\t{\n\t\t\t\t_game->popState();\n\t\t\t\t_game->pushState(new ErrorMessageState(\n\t\t\t\t\ttr(\"STR_NOT_ENOUGH_CARGO_SPACE\"),\n\t\t\t\t\t_palette,\n\t\t\t\t\t_game->getMod()->getInterface(\"craftWeapons\")->getElement(\"errorMessage\")->color,\n\t\t\t\t\t\"BACK14.SCR\",\n\t\t\t\t\t_game->getMod()->getInterface(\"craftWeapons\")->getElement(\"errorPalette\")->color)\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\t{\n\t\tint refCapBonus2 = refWeapon ? refWeapon->getBonusStats().vehicles : 0;\n\t\tint currCapBonus2 = currWeapon ? currWeapon->getBonusStats().vehicles : 0;\n\t\tint diff2 = (refCapBonus2 - currCapBonus2);\n\t\tif (diff2)\n\t\t{\n\t\t\tif ((_craft->getMaxVehiclesAndLargeSoldiersRaw() - _craft->getNumVehiclesAndLargeSoldiers() + diff2) < 0)\n\t\t\t{\n\t\t\t\t_game->popState();\n\t\t\t\t_game->pushState(new ErrorMessageState(\n\t\t\t\t\ttr(\"STR_NOT_ENOUGH_HWP_CAPACITY\"),\n\t\t\t\t\t_palette,\n\t\t\t\t\t_game->getMod()->getInterface(\"craftWeapons\")->getElement(\"errorMessage\")->color,\n\t\t\t\t\t\"BACK14.SCR\",\n\t\t\t\t\t_game->getMod()->getInterface(\"craftWeapons\")->getElement(\"errorPalette\")->color)\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\t{\n\t\tint refCapBonus3 = refWeapon ? refWeapon->getBonusStats().maxItems : 0;\n\t\tint currCapBonus3 = currWeapon ? currWeapon->getBonusStats().maxItems : 0;\n\t\tint diff3 = (refCapBonus3 - currCapBonus3);\n\n\t\tdouble refCapBonus4 = refWeapon ? refWeapon->getBonusStats().maxStorageSpace : 0.0;\n\t\tdouble currCapBonus4 = currWeapon ? currWeapon->getBonusStats().maxStorageSpace : 0.0;\n\t\tdouble diff4 = (refCapBonus4 - currCapBonus4);\n\t\tbool diff4_b = !AreSame(refCapBonus4, currCapBonus4); // floating math\n\n\t\tint totalItems = 0;\n\t\tdouble totalItemStorageSize = 0.0;\n\t\tif (diff3 || diff4_b)\n\t\t{\n\t\t\tfor (auto& itemType : _game->getMod()->getItemsList())\n\t\t\t{\n\t\t\t\tRuleItem* rule = _game->getMod()->getItem(itemType);\n\n\t\t\t\tUnit* isVehicle = rule->getVehicleUnit();\n\t\t\t\tint cQty = 0;\n\t\t\t\tif (isVehicle)\n\t\t\t\t{\n\t\t\t\t\tcQty = _craft->getVehicleCount(itemType);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tcQty = _craft->getItems()->getItem(rule);\n\t\t\t\t\ttotalItems += cQty;\n\t\t\t\t\ttotalItemStorageSize += cQty * rule->getSize();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (diff3)\n\t\t{\n\t\t\tif ((_craft->getMaxItemsRaw() - totalItems + diff3) < 0)\n\t\t\t{\n\t\t\t\t_game->popState();\n\t\t\t\t_game->pushState(new ErrorMessageState(\n\t\t\t\t\ttr(\"STR_NOT_ENOUGH_STORAGE_SPACE_1\"),\n\t\t\t\t\t_palette,\n\t\t\t\t\t_game->getMod()->getInterface(\"craftWeapons\")->getElement(\"errorMessage\")->color,\n\t\t\t\t\t\"BACK14.SCR\",\n\t\t\t\t\t_game->getMod()->getInterface(\"craftWeapons\")->getElement(\"errorPalette\")->color)\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tif (diff4_b)\n\t\t{\n\t\t\tif ((_craft->getMaxStorageSpaceRaw() - totalItemStorageSize + diff4) < 0.0)\n\t\t\t{\n\t\t\t\t_game->popState();\n\t\t\t\t_game->pushState(new ErrorMessageState(\n\t\t\t\t\ttr(\"STR_NOT_ENOUGH_STORAGE_SPACE_2\"),\n\t\t\t\t\t_palette,\n\t\t\t\t\t_game->getMod()->getInterface(\"craftWeapons\")->getElement(\"errorMessage\")->color,\n\t\t\t\t\t\"BACK14.SCR\",\n\t\t\t\t\t_game->getMod()->getInterface(\"craftWeapons\")->getElement(\"errorPalette\")->color)\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Remove current weapon\n\tif (current != 0)\n\t{\n\t\t_base->getStorageItems()->addItem(current->getRules()->getLauncherItem());\n\t\t_base->getStorageItems()->addItem(current->getRules()->getClipItem(), current->getClipsLoaded());\n\t\t_craft->addCraftStats(-current->getRules()->getBonusStats());\n\t\t// Make sure any extra shield is removed from craft too when the shield capacity decreases (exploit protection)\n\t\t_craft->setShield(_craft->getShield());\n\t\tdelete current;\n\t\t_craft->getWeapons()->at(_weapon) = 0;\n\t}\n\n\t// Equip new weapon\n\tif (_weapons[_lstWeapons->getSelectedRow()] != 0)\n\t{\n\t\tCraftWeapon *sel = new CraftWeapon(_weapons[_lstWeapons->getSelectedRow()], 0);\n\t\t_craft->addCraftStats(sel->getRules()->getBonusStats());\n\t\t_base->getStorageItems()->removeItem(sel->getRules()->getLauncherItem());\n\t\t_craft->getWeapons()->at(_weapon) = sel;\n\t}\n\n\t_craft->checkup();\n\t_game->popState();\n}\n\n/**\n* Opens the corresponding Ufopaedia article.\n* @param action Pointer to an action.\n*/\nvoid CraftWeaponsState::lstWeaponsMiddleClick(Action *)\n{\n\tRuleCraftWeapon *rule = _weapons[_lstWeapons->getSelectedRow()];\n\n\tif (rule != 0)\n\t{\n\t\tstd::string articleId = rule->getUfopediaType();\n\t\tUfopaedia::openArticle(_game, articleId);\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/CraftWeaponsState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <vector>\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass Base;\nclass Craft;\nclass TextButton;\nclass Window;\nclass Text;\nclass TextList;\nclass RuleCraftWeapon;\n\n/**\n * Select Armament window for\n * changing the weapon equipped on a craft.\n */\nclass CraftWeaponsState : public State\n{\nprivate:\n\tBase *_base;\n\tCraft *_craft;\n\tsize_t _weapon;\n\n\tTextButton *_btnCancel;\n\tWindow *_window;\n\tText *_txtTitle, *_txtArmament, *_txtQuantity, *_txtAmmunition, *_txtCurrentWeapon;\n\tTextList *_lstWeapons;\n\tstd::vector<RuleCraftWeapon*> _weapons;\npublic:\n\t/// Creates the Craft Weapons state.\n\tCraftWeaponsState(Base *base, size_t craft, size_t weapon);\n\t/// Cleans up the Craft Weapons state.\n\t~CraftWeaponsState();\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action *action);\n\t/// Handler for clicking the Weapons list.\n\tvoid lstWeaponsClick(Action *action);\n\t/// Handler for middle clicking the Weapons list.\n\tvoid lstWeaponsMiddleClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/CraftsState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"CraftsState.h\"\n#include <sstream>\n#include \"../Engine/Action.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Savegame/Craft.h\"\n#include \"../Mod/RuleCraft.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Menu/ErrorMessageState.h\"\n#include \"CraftInfoState.h\"\n#include \"SellState.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Mod/RuleInterface.h\"\n#include \"../Ufopaedia/Ufopaedia.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Equip Craft screen.\n * @param game Pointer to the core game.\n * @param base Pointer to the base to get info from.\n */\nCraftsState::CraftsState(Base *base) : _base(base)\n{\n\t// Create objects\n\t_window = new Window(this, 320, 200, 0, 0);\n\t_btnOk = new TextButton(288, 16, 16, 176);\n\t_txtTitle = new Text(298, 17, 16, 8);\n\t_txtBase = new Text(298, 17, 16, 24);\n\t_txtName = new Text(94, 9, 16, 40);\n\t_txtStatus = new Text(50, 9, 110, 40);\n\t_txtWeapon = new Text(50, 17, 160, 40);\n\t_txtCrew = new Text(58, 9, 210, 40);\n\t_txtHwp = new Text(46, 9, 268, 40);\n\t_lstCrafts = new TextList(288, 112, 8, 58);\n\n\t// Set palette\n\tsetInterface(\"craftSelect\");\n\n\tadd(_window, \"window\", \"craftSelect\");\n\tadd(_btnOk, \"button\", \"craftSelect\");\n\tadd(_txtTitle, \"text\", \"craftSelect\");\n\tadd(_txtBase, \"text\", \"craftSelect\");\n\tadd(_txtName, \"text\", \"craftSelect\");\n\tadd(_txtStatus, \"text\", \"craftSelect\");\n\tadd(_txtWeapon, \"text\", \"craftSelect\");\n\tadd(_txtCrew, \"text\", \"craftSelect\");\n\tadd(_txtHwp, \"text\", \"craftSelect\");\n\tadd(_lstCrafts, \"list\", \"craftSelect\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"craftSelect\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&CraftsState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&CraftsState::btnOkClick, Options::keyCancel);\n\n\t_txtTitle->setBig();\n\t_txtTitle->setText(tr(\"STR_INTERCEPTION_CRAFT\"));\n\n\t_txtBase->setBig();\n\t_txtBase->setText(tr(\"STR_BASE_\").arg(_base->getName()));\n\n\t_txtName->setText(tr(\"STR_NAME_UC\"));\n\n\t_txtStatus->setText(tr(\"STR_STATUS\"));\n\n\t_txtWeapon->setText(tr(\"STR_WEAPON_SYSTEMS\"));\n\t_txtWeapon->setWordWrap(true);\n\n\t_txtCrew->setText(tr(\"STR_CREW\"));\n\n\t_txtHwp->setText(tr(\"STR_HWPS\"));\n\t_lstCrafts->setColumns(5, 94, 68, 44, 46, 28);\n\t_lstCrafts->setSelectable(true);\n\t_lstCrafts->setBackground(_window);\n\t_lstCrafts->setMargin(8);\n\t_lstCrafts->onMouseClick((ActionHandler)&CraftsState::lstCraftsClick);\n\t_lstCrafts->onMouseClick((ActionHandler)&CraftsState::lstCraftsClick, SDL_BUTTON_RIGHT);\n\t_lstCrafts->onMouseClick((ActionHandler)&CraftsState::lstCraftsClick, SDL_BUTTON_MIDDLE);\n}\n\n/**\n *\n */\nCraftsState::~CraftsState()\n{\n\n}\n\n/**\n * The soldier names can change\n * after going into other screens.\n */\nvoid CraftsState::init()\n{\n\tState::init();\n\n\tinitList(0);\n}\n\n/**\n * Shows the crafts in a list at specified offset/scroll.\n */\nvoid CraftsState::initList(size_t scrl)\n{\n\t_lstCrafts->clearList();\n\tfor (const auto* craft : *_base->getCrafts())\n\t{\n\t\tstd::ostringstream ss, ss2, ss3;\n\t\tss << craft->getNumWeapons() << \"/\" << craft->getRules()->getWeapons();\n\t\tss2 << craft->getNumTotalSoldiers();\n\t\tss3 << craft->getNumTotalVehicles();\n\t\t_lstCrafts->addRow(5, craft->getName(_game->getLanguage()).c_str(), tr(craft->getStatus()).c_str(), ss.str().c_str(), ss2.str().c_str(), ss3.str().c_str());\n\t}\n\n\tif (scrl)\n\t\t_lstCrafts->scrollTo(scrl);\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid CraftsState::btnOkClick(Action *)\n{\n\t_game->popState();\n\n\tif (_game->getSavedGame()->getMonthsPassed() > -1 && Options::storageLimitsEnforced && _base->storesOverfull())\n\t{\n\t\t_game->pushState(new SellState(_base, 0));\n\t\t_game->pushState(new ErrorMessageState(tr(\"STR_STORAGE_EXCEEDED\").arg(_base->getName()), _palette, _game->getMod()->getInterface(\"craftSelect\")->getElement(\"errorMessage\")->color, \"BACK01.SCR\", _game->getMod()->getInterface(\"craftSelect\")->getElement(\"errorPalette\")->color));\n\t}\n}\n\n/**\n * Shows the selected craft's info.\n * @param action Pointer to an action.\n */\nvoid CraftsState::lstCraftsClick(Action *action)\n{\n\tauto& crafts = *_base->getCrafts();\n\tauto row = _lstCrafts->getSelectedRow();\n\n\tif (_game->isLeftClick(action))\n\t{\n\t\tif (crafts[row]->getStatus() != \"STR_OUT\")\n\t\t{\n\t\t\t_game->pushState(new CraftInfoState(_base, row));\n\t\t}\n\t}\n\telse if (_game->isRightClick(action))\n\t{\n\t\tbool shift = _game->isShiftPressed();\n\t\tif (shift && row < (crafts.size() - 1))\n\t\t{\n\t\t\t// move craft down in the list\n\t\t\tstd::swap(crafts[row], crafts[row + 1]);\n\n\t\t\t// warp mouse\n\t\t\tif (row != _lstCrafts->getVisibleRows() - 1 + _lstCrafts->getScroll())\n\t\t\t{\n\t\t\t\tSDL_WarpMouse(action->getLeftBlackBand() + action->getXMouse(), action->getTopBlackBand() + action->getYMouse() + static_cast<Uint16>(8 * action->getYScale()));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_lstCrafts->scrollDown(false);\n\t\t\t}\n\n\t\t\t// reload the UI\n\t\t\tinitList(_lstCrafts->getScroll());\n\t\t}\n\t\tif (!shift && row > 0)\n\t\t{\n\t\t\t// move craft up in the list\n\t\t\tstd::swap(crafts[row], crafts[row - 1]);\n\n\t\t\t// warp mouse\n\t\t\tif (row != _lstCrafts->getScroll())\n\t\t\t{\n\t\t\t\tSDL_WarpMouse(action->getLeftBlackBand() + action->getXMouse(), action->getTopBlackBand() + action->getYMouse() - static_cast<Uint16>(8 * action->getYScale()));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_lstCrafts->scrollUp(false);\n\t\t\t}\n\n\t\t\t// reload the UI\n\t\t\tinitList(_lstCrafts->getScroll());\n\t\t}\n\t}\n\telse if (_game->isMiddleClick(action))\n\t{\n\t\tstd::string articleId = crafts[row]->getRules()->getType();\n\t\tUfopaedia::openArticle(_game, articleId);\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/CraftsState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass TextList;\nclass Base;\n\n/**\n * Equip Craft screen that lets the player\n * manage all the crafts in a base.\n */\nclass CraftsState : public State\n{\nprivate:\n\tTextButton *_btnOk;\n\tWindow *_window;\n\tText *_txtTitle, *_txtBase, *_txtName, *_txtStatus, *_txtWeapon, *_txtCrew, *_txtHwp;\n\tTextList *_lstCrafts;\n\tBase *_base;\n\n\tvoid initList(size_t scrl);\npublic:\n\t/// Creates the Crafts state.\n\tCraftsState(Base *base);\n\t/// Cleans up the Crafts state.\n\t~CraftsState();\n\t/// Updates the craft info.\n\tvoid init() override;\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the Crafts list.\n\tvoid lstCraftsClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/DismantleFacilityState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"DismantleFacilityState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Sound.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/BaseFacility.h\"\n#include \"../Savegame/ItemContainer.h\"\n#include \"BaseView.h\"\n#include \"../Mod/RuleBaseFacility.h\"\n#include \"../Savegame/SavedGame.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in a Dismantle Facility window.\n * @param game Pointer to the core game.\n * @param base Pointer to the base to get info from.\n * @param view Pointer to the baseview to update.\n * @param fac Pointer to the facility to dismantle.\n */\nDismantleFacilityState::DismantleFacilityState(Base *base, BaseView *view, BaseFacility *fac) : _base(base), _view(view), _fac(fac)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 152, 80, 20, 60);\n\t_btnOk = new TextButton(44, 16, 36, 115);\n\t_btnCancel = new TextButton(44, 16, 112, 115);\n\t_txtTitle = new Text(142, 9, 25, 75);\n\t_txtFacility = new Text(142, 9, 25, 85);\n\t_txtRefundValue = new Text(142, 9, 25, 100);\n\n\t// Set palette\n\tsetInterface(\"dismantleFacility\");\n\n\tadd(_window, \"window\", \"dismantleFacility\");\n\tadd(_btnOk, \"button\", \"dismantleFacility\");\n\tadd(_btnCancel, \"button\", \"dismantleFacility\");\n\tadd(_txtTitle, \"text\", \"dismantleFacility\");\n\tadd(_txtFacility, \"text\", \"dismantleFacility\");\n\tadd(_txtRefundValue, \"text\", \"dismantleFacility\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"dismantleFacility\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&DismantleFacilityState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&DismantleFacilityState::btnOkClick, Options::keyOk);\n\n\t_btnCancel->setText(tr(\"STR_CANCEL_UC\"));\n\t_btnCancel->onMouseClick((ActionHandler)&DismantleFacilityState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&DismantleFacilityState::btnCancelClick, Options::keyCancel);\n\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_DISMANTLE\"));\n\n\t_txtFacility->setAlign(ALIGN_CENTER);\n\t_txtFacility->setText(tr(_fac->getRules()->getType()));\n\n\tint refundValue = 0;\n\tif (_fac->getBuildTime() > _fac->getRules()->getBuildTime())\n\t{\n\t\t// if only queued... full refund (= build cost)\n\t\trefundValue = _fac->getRules()->getBuildCost();\n\t}\n\telse\n\t{\n\t\t// if already building or already built... partial refund (by default 0, used in mods)\n\t\trefundValue = _fac->getRules()->getRefundValue();\n\t}\n\n\t_txtRefundValue->setAlign(ALIGN_CENTER);\n\tif (refundValue < 0)\n\t{\n\t\t_txtRefundValue->setText(tr(\"STR_REFUND_VALUE_NEGATIVE\").arg(Unicode::formatFunding(-refundValue)));\n\t\tif (_game->getSavedGame()->getFunds() < -refundValue)\n\t\t{\n\t\t\t// cannot afford dismantle, expenses too high\n\t\t\t_btnOk->setVisible(false);\n\t\t}\n\t}\n\telse\n\t{\n\t\t_txtRefundValue->setText(tr(\"STR_REFUND_VALUE\").arg(Unicode::formatFunding(refundValue)));\n\t}\n\t_txtRefundValue->setVisible(refundValue != 0);\n}\n\n/**\n *\n */\nDismantleFacilityState::~DismantleFacilityState()\n{\n\n}\n\n/**\n * Dismantles the facility and returns\n * to the previous screen.\n * @param action Pointer to an action.\n */\nvoid DismantleFacilityState::btnOkClick(Action *)\n{\n\tif (!_fac->getRules()->isLift())\n\t{\n\t\tconst std::map<std::string, std::pair<int, int> > &itemCost = _fac->getRules()->getBuildCostItems();\n\n\t\tif (_fac->getBuildTime() > _fac->getRules()->getBuildTime())\n\t\t{\n\t\t\t// Give full refund if this is a (not yet started) queued build.\n\t\t\t_game->getSavedGame()->setFunds(_game->getSavedGame()->getFunds() + _fac->getRules()->getBuildCost());\n\t\t\tfor (auto& pair : itemCost)\n\t\t\t{\n\t\t\t\t_base->getStorageItems()->addItem(_game->getMod()->getItem(pair.first, true), pair.second.first);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// Give partial refund if this is a started build or a completed facility.\n\t\t\t_game->getSavedGame()->setFunds(_game->getSavedGame()->getFunds() + _fac->getRules()->getRefundValue());\n\t\t\tfor (auto& pair : itemCost)\n\t\t\t{\n\t\t\t\t_base->getStorageItems()->addItem(_game->getMod()->getItem(pair.first, true), pair.second.second);\n\t\t\t}\n\t\t}\n\t\tif (_fac->getAmmo() > 0)\n\t\t{\n\t\t\t// Full refund of loaded ammo\n\t\t\t_base->getStorageItems()->addItem(_fac->getRules()->getAmmoItem(), _fac->getAmmo());\n\t\t\t_fac->setAmmo(0);\n\t\t}\n\n\t\tfor (auto facIt = _base->getFacilities()->begin(); facIt != _base->getFacilities()->end(); ++facIt)\n\t\t{\n\t\t\tif (*facIt == _fac)\n\t\t\t{\n\t\t\t\t_base->getFacilities()->erase(facIt);\n\t\t\t\t// Determine if we leave behind any facilities when this one is removed\n\t\t\t\tif (_fac->getBuildTime() == 0 && _fac->getRules()->getLeavesBehindOnSell().size() != 0)\n\t\t\t\t{\n\t\t\t\t\tconst auto& facList = _fac->getRules()->getLeavesBehindOnSell();\n\t\t\t\t\tif (facList.at(0)->getPlaceSound() != Mod::NO_SOUND)\n\t\t\t\t\t{\n\t\t\t\t\t\t_game->getMod()->getSound(\"GEO.CAT\", facList.at(0)->getPlaceSound())->play();\n\t\t\t\t\t}\n\t\t\t\t\t// Make sure the size of the facilities left behind matches the one we removed\n\t\t\t\t\tif (facList.at(0)->getSizeX() == _fac->getRules()->getSizeX() && facList.at(0)->getSizeY() == _fac->getRules()->getSizeY()) // equal size facilities\n\t\t\t\t\t{\n\t\t\t\t\t\tBaseFacility *fac = new BaseFacility(facList.at(0), _base);\n\t\t\t\t\t\tfac->setX(_fac->getX());\n\t\t\t\t\t\tfac->setY(_fac->getY());\n\t\t\t\t\t\tif (_fac->getRules()->getRemovalTime() <= -1)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfac->setBuildTime(fac->getRules()->getBuildTime());\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfac->setBuildTime(_fac->getRules()->getRemovalTime());\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (fac->getBuildTime() != 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfac->setIfHadPreviousFacility(true);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t_base->getFacilities()->push_back(fac);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tsize_t j = 0;\n\t\t\t\t\t\t// Otherwise, assume the list of facilities is size 1, and just iterate over it to fill in the old facility's place\n\t\t\t\t\t\tfor (int y = _fac->getY(); y != _fac->getY() + _fac->getRules()->getSizeY(); ++y)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfor (int x = _fac->getX(); x != _fac->getX() + _fac->getRules()->getSizeX(); ++x)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tBaseFacility *fac = new BaseFacility(facList.at(j), _base);\n\t\t\t\t\t\t\t\tfac->setX(x);\n\t\t\t\t\t\t\t\tfac->setY(y);\n\t\t\t\t\t\t\t\tif (_fac->getRules()->getRemovalTime() <= -1)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tfac->setBuildTime(fac->getRules()->getBuildTime());\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tfac->setBuildTime(_fac->getRules()->getRemovalTime());\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (fac->getBuildTime() != 0)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tfac->setIfHadPreviousFacility(true);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t_base->getFacilities()->push_back(fac);\n\n\t\t\t\t\t\t\t\t++j;\n\t\t\t\t\t\t\t\tif (j == facList.size())\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tj = 0;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t_view->resetSelectedFacility();\n\t\t\t\tdelete _fac;\n\t\t\t\t// Reset the basescape view in case new facilities were created by removing the old one\n\t\t\t\t_view->setBase(_base);\n\t\t\t\tif (Options::allowBuildingQueue) _view->reCalcQueuedBuildings();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\t// Remove whole base if it's the access lift\n\telse\n\t{\n\t\tfor (auto xbaseIt = _game->getSavedGame()->getBases()->begin(); xbaseIt != _game->getSavedGame()->getBases()->end(); ++xbaseIt)\n\t\t{\n\t\t\tif (*xbaseIt == _base)\n\t\t\t{\n\t\t\t\t_game->getSavedGame()->getBases()->erase(xbaseIt);\n\t\t\t\tdelete _base;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\t_game->popState();\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid DismantleFacilityState::btnCancelClick(Action *)\n{\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/DismantleFacilityState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass Base;\nclass BaseView;\nclass BaseFacility;\nclass TextButton;\nclass Window;\nclass Text;\n\n/**\n * Window shown when the player tries to\n * dismantle a facility.\n */\nclass DismantleFacilityState : public State\n{\nprivate:\n\tBase *_base;\n\tBaseView *_view;\n\tBaseFacility *_fac;\n\n\tTextButton *_btnOk, *_btnCancel;\n\tWindow *_window;\n\tText *_txtTitle, *_txtFacility, *_txtRefundValue;\npublic:\n\t/// Creates the Dismantle Facility state.\n\tDismantleFacilityState(Base *base, BaseView *view, BaseFacility *fac);\n\t/// Cleans up the Dismantle Facility state.\n\t~DismantleFacilityState();\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/GlobalAlienContainmentState.cpp",
    "content": "/*\n * Copyright 2010-2023 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"GlobalAlienContainmentState.h\"\n#include \"ManageAlienContainmentState.h\"\n#include \"TechTreeViewerState.h\"\n#include <sstream>\n#include <set>\n#include \"../Engine/Game.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Interface/Window.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleResearch.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/BaseFacility.h\"\n#include \"../Savegame/ItemContainer.h\"\n#include \"../Savegame/ResearchProject.h\"\n#include \"../Savegame/SavedGame.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the GlobalAlienContainment screen.\n */\nGlobalAlienContainmentState::GlobalAlienContainmentState(bool openedFromBasescape) : _openedFromBasescape(openedFromBasescape)\n{\n\t// Create objects\n\t_window = new Window(this, 320, 200, 0, 0);\n\t_btnOk = new TextButton(304, 16, 8, 176);\n\t_txtTitle = new Text(310, 17, 5, 8);\n\t_txtTotalUsed = new Text(150, 9, 10, 24);\n\t_txtTotalInterrogated = new Text(150, 9, 130, 24);\n\t_txtPrisoner = new Text(146, 9, 10, 34);\n\t_txtPrisonerAmount = new Text(60, 9, 156, 34);\n\t_txtPrisonersInterrogated = new Text(80, 9, 216, 34);\n\t_lstPrisoners = new TextList(288, 128, 8, 44);\n\n\t// Set palette\n\tsetInterface(\"globalContainmentMenu\");\n\n\tadd(_window, \"window\", \"globalContainmentMenu\");\n\tadd(_btnOk, \"button\", \"globalContainmentMenu\");\n\tadd(_txtTitle, \"text\", \"globalContainmentMenu\");\n\tadd(_txtTotalUsed, \"text\", \"globalContainmentMenu\");\n\tadd(_txtTotalInterrogated, \"text\", \"globalContainmentMenu\");\n\tadd(_txtPrisoner, \"text\", \"globalContainmentMenu\");\n\tadd(_txtPrisonerAmount, \"text\", \"globalContainmentMenu\");\n\tadd(_txtPrisonersInterrogated, \"text\", \"globalContainmentMenu\");\n\tadd(_lstPrisoners, \"list\", \"globalContainmentMenu\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"globalContainmentMenu\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&GlobalAlienContainmentState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&GlobalAlienContainmentState::btnOkClick, Options::keyCancel);\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_PRISONER_OVERVIEW\"));\n\n\t_txtPrisoner->setText(tr(\"STR_PRISONER\"));\n\n\t_txtPrisonerAmount->setAlign(ALIGN_CENTER);\n\t_txtPrisonerAmount->setText(tr(\"STR_PRISONER_AMOUNT\"));\n\n\t_txtPrisonersInterrogated->setAlign(ALIGN_CENTER);\n\t_txtPrisonersInterrogated->setText(tr(\"STR_PRISONER_INTERROGATED\"));\n\n\n\t_lstPrisoners->setColumns(3, 146, 60, 80);\n\t_lstPrisoners->setSelectable(true);\n\t_lstPrisoners->setBackground(_window);\n\t_lstPrisoners->setMargin(2);\n\t_lstPrisoners->setWordWrap(true);\n\t_lstPrisoners->setAlign(ALIGN_CENTER, 1);\n\t_lstPrisoners->setAlign(ALIGN_CENTER, 2);\n\t_lstPrisoners->onMouseClick((ActionHandler)&GlobalAlienContainmentState::onSelectBase, SDL_BUTTON_LEFT);\n\t_lstPrisoners->onMouseClick((ActionHandler)&GlobalAlienContainmentState::onOpenTechTreeViewer, SDL_BUTTON_MIDDLE);\n}\n\n/**\n *\n */\nGlobalAlienContainmentState::~GlobalAlienContainmentState()\n{\n}\n\n/**\n * Updates the prisoner list\n * after going to other screens.\n */\nvoid GlobalAlienContainmentState::init()\n{\n\tState::init();\n\tfillPrisonerList();\n}\n\n/**\n * Fills the list with all prisoners from all bases. Also updates totals.\n */\nvoid GlobalAlienContainmentState::fillPrisonerList()\n{\n\t_topics.clear();\n\t_lstPrisoners->clearList();\n\n\tint totalInterrogated = 0;\n\tint totalUsed = 0;\n\n\t// determine prison types used in the game\n\tstd::set<int> prisonTypes = { 0 };\n\tbool noTypes = true;\n\tfor (auto& facType : _game->getMod()->getBaseFacilitiesList())\n\t{\n\t\tauto* facRule = _game->getMod()->getBaseFacility(facType);\n\t\tif (facRule->getPrisonType() > 0)\n\t\t{\n\t\t\tprisonTypes.insert(facRule->getPrisonType());\n\t\t\tnoTypes = false;\n\t\t}\n\t}\n\n\tfor (auto* xbase : *_game->getSavedGame()->getBases())\n\t{\n\t\tbool displayed = false;\n\t\tint totalBaseCapacity = 0;\n\n\t\t// determine prison types used in the base\n\t\tstd::set<int> occupiedPrisonTypes;\n\t\tfor(int prisonType : prisonTypes)\n\t\t{\n\t\t\ttotalBaseCapacity += xbase->getAvailableContainment(prisonType);\n\n\t\t\tfor(auto* baseFacility : *xbase->getFacilities())\n\t\t\t{\n\t\t\t\tif(baseFacility->getRules()->getAliens() > 0 && baseFacility->getRules()->getPrisonType() == prisonType)\n\t\t\t\t{\n\t\t\t\t\tint usedSpace = xbase->getUsedContainment(prisonType);\n\t\t\t\t\tif (usedSpace > 0)\n\t\t\t\t\t{\n\t\t\t\t\t\toccupiedPrisonTypes.insert(prisonType);\n\t\t\t\t\t}\n\t\t\t\t\ttotalUsed += usedSpace;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t}\n\t\t}\n\n\t\tfor (int prisonType : occupiedPrisonTypes)\n\t\t{\n\t\t\tstd::vector<std::string> researchList;\n\t\t\tfor (const auto* proj : xbase->getResearch())\n\t\t\t{\n\t\t\t\tconst RuleResearch* research = proj->getRules();\n\t\t\t\tconst RuleItem* item = research->getNeededItem();\n\t\t\t\tif (research->isHoldingNeededItem() && item && item->isAlien() && item->getPrisonType() == prisonType)\n\t\t\t\t{\n\t\t\t\t\tresearchList.push_back(research->getName());\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tstd::string baseNameAndPrisonType = xbase->getName(_game->getLanguage());\n\t\t\tif (!noTypes)\n\t\t\t{\n\t\t\t\tbaseNameAndPrisonType = baseNameAndPrisonType + \" - \" + std::string(trAlt(\"STR_PRISON_TYPE\", prisonType));\n\t\t\t}\n\t\t\t_lstPrisoners->addRow(3, baseNameAndPrisonType.c_str(), \"\", \"\");\n\t\t\t_lstPrisoners->setRowColor(_lstPrisoners->getLastRowIndex(), _lstPrisoners->getSecondaryColor());\n\t\t\t_topics.push_back(std::make_tuple(\"\", nullptr, 0));\n\t\t\tdisplayed = true;\n\n\t\t\tfor (auto& itemType : _game->getMod()->getItemsList())\n\t\t\t{\n\t\t\t\tRuleItem* rule = _game->getMod()->getItem(itemType, true);\n\t\t\t\tif (rule->isAlien() && rule->getPrisonType() == prisonType)\n\t\t\t\t{\n\t\t\t\t\tint qty = xbase->getStorageItems()->getItem(rule);\n\t\t\t\t\tif (qty > 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tstd::ostringstream ss;\n\t\t\t\t\t\tss << qty;\n\t\t\t\t\t\tstd::string rqty;\n\t\t\t\t\t\tauto researchIt = std::find(researchList.begin(), researchList.end(), itemType);\n\t\t\t\t\t\tif (researchIt != researchList.end())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\trqty = \"1\";\n\t\t\t\t\t\t\tresearchList.erase(researchIt);\n\t\t\t\t\t\t\ttotalInterrogated++;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\trqty = \"0\";\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t_lstPrisoners->addRow(3, tr(itemType).c_str(), ss.str().c_str(), rqty.c_str());\n\t\t\t\t\t\t_topics.push_back(std::make_tuple(itemType, xbase, prisonType));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (const auto& researchName : researchList)\n\t\t\t{\n\t\t\t\t_lstPrisoners->addRow(3, tr(researchName).c_str(), \"0\", \"1\");\n\t\t\t\t_topics.push_back(std::make_tuple(researchName, xbase, prisonType));\n\t\t\t\ttotalInterrogated++;\n\t\t\t}\n\t\t}\n\n\t\tif (!displayed && totalBaseCapacity > 0)\n\t\t{\n\t\t\t_lstPrisoners->addRow(3, xbase->getName(_game->getLanguage()).c_str(), \"\", \"\");\n\t\t\t_lstPrisoners->setRowColor(_lstPrisoners->getLastRowIndex(), _lstPrisoners->getSecondaryColor());\n\t\t\t_topics.push_back(std::make_tuple(\"\", nullptr, 0));\n\n\t\t\t_lstPrisoners->addRow(3, tr(\"STR_NONE\").c_str(), \"\", \"\");\n\t\t\t_topics.push_back(std::make_tuple(\"\", xbase, 0));\n\t\t}\n\t}\n\n\t_txtTotalUsed->setText(tr(\"STR_TOTAL_IN_PRISON\").arg(totalUsed));\n\t_txtTotalInterrogated->setText(tr(\"STR_TOTAL_INTERROGATED\").arg(totalInterrogated));\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid GlobalAlienContainmentState::btnOkClick(Action*)\n{\n\t_game->popState();\n}\n\n/**\n * Goes to the base's research screen when clicking its project\n * @param action Pointer to an action.\n */\nvoid GlobalAlienContainmentState::onSelectBase(Action*)\n{\n\tauto& tuple = _topics[_lstPrisoners->getSelectedRow()];\n\tBase* base = std::get<1>(tuple);\n\tint prisonType = std::get<2>(tuple);\n\n\tif (base)\n\t{\n\t\t// close this window\n\t\t_game->popState();\n\n\t\t// close Manage Alien Containment UI (goes back to BaseView)\n\t\tif (_openedFromBasescape)\n\t\t{\n\t\t\t_game->popState();\n\t\t}\n\n\t\t// open new window\n\t\t_game->pushState(new ManageAlienContainmentState(base, prisonType, OPT_GEOSCAPE));\n\t}\n}\n\n/**\n * Opens the TechTreeViewer for the corresponding topic.\n * @param action Pointer to an action.\n */\nvoid GlobalAlienContainmentState::onOpenTechTreeViewer(Action*)\n{\n\tauto& tuple = _topics[_lstPrisoners->getSelectedRow()];\n\tconst RuleResearch* selectedTopic = _game->getMod()->getResearch(std::get<0>(tuple));\n\n\tif (selectedTopic)\n\t{\n\t\t_game->pushState(new TechTreeViewerState(selectedTopic, 0));\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/GlobalAlienContainmentState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2023 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass Base;\nclass Text;\nclass TextButton;\nclass TextList;\nclass Window;\n\n/**\n * Global Alien Containment screen that provides overview\n * of all the prisoners in all the bases.\n */\nclass GlobalAlienContainmentState : public State\n{\nprivate:\n\tTextButton *_btnOk;\n\tWindow *_window;\n\tText *_txtTitle, *_txtTotalUsed, *_txtTotalInterrogated, *_txtPrisoner, *_txtPrisonerAmount, *_txtPrisonersInterrogated;\n\tTextList *_lstPrisoners;\n\n\tstd::vector<std::tuple<std::string, Base*, int> > _topics;\n\tbool _openedFromBasescape;\npublic:\n\t/// Creates the GlobalAlienContainmentState.\n\tGlobalAlienContainmentState(bool openedFromBasescape);\n\t/// Cleans up the GlobalAlienContainmentState.\n\t~GlobalAlienContainmentState();\n\t/// Updates the prisoner list.\n\tvoid init() override;\n\t/// Fills the list with all prisoners from all bases.\n\tvoid fillPrisonerList();\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the prisoners list.\n\tvoid onSelectBase(Action *action);\n\tvoid onOpenTechTreeViewer(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/GlobalManufactureState.cpp",
    "content": "/*\n * Copyright 2010-2019 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"GlobalManufactureState.h\"\n#include <sstream>\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Mod/RuleManufacture.h\"\n#include \"../Savegame/Production.h\"\n#include \"ManufactureState.h\"\n#include \"TechTreeViewerState.h\"\n#include \"../Ufopaedia/Ufopaedia.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the GlobalManufacture screen.\n */\nGlobalManufactureState::GlobalManufactureState(bool openedFromBasescape) : _openedFromBasescape(openedFromBasescape)\n{\n\t// Create objects\n\t_window = new Window(this, 320, 200, 0, 0);\n\t_btnOk = new TextButton(304, 16, 8, 176);\n\t_txtTitle = new Text(310, 17, 5, 8);\n\t_txtAvailable = new Text(150, 9, 8, 24);\n\t_txtAllocated = new Text(150, 9, 160, 24);\n\t_txtSpace = new Text(150, 9, 8, 34);\n\t_txtFunds = new Text(150, 9, 160, 34);\n\t_txtItem = new Text(80, 9, 10, 52);\n\t_txtEngineers = new Text(56, 18, 112, 44);\n\t_txtProduced = new Text(56, 18, 168, 44);\n\t_txtCost = new Text(44, 27, 222, 44);\n\t_txtTimeLeft = new Text(60, 27, 260, 44);\n\t_lstManufacture = new TextList(288, 88, 8, 80);\n\n\t// Set palette\n\tsetInterface(\"globalManufactureMenu\");\n\n\tadd(_window, \"window\", \"globalManufactureMenu\");\n\tadd(_btnOk, \"button\", \"globalManufactureMenu\");\n\tadd(_txtTitle, \"text1\", \"globalManufactureMenu\");\n\tadd(_txtAvailable, \"text1\", \"globalManufactureMenu\");\n\tadd(_txtAllocated, \"text1\", \"globalManufactureMenu\");\n\tadd(_txtSpace, \"text1\", \"globalManufactureMenu\");\n\tadd(_txtFunds, \"text1\", \"globalManufactureMenu\");\n\tadd(_txtItem, \"text2\", \"globalManufactureMenu\");\n\tadd(_txtEngineers, \"text2\", \"globalManufactureMenu\");\n\tadd(_txtProduced, \"text2\", \"globalManufactureMenu\");\n\tadd(_txtCost, \"text2\", \"globalManufactureMenu\");\n\tadd(_txtTimeLeft, \"text2\", \"globalManufactureMenu\");\n\tadd(_lstManufacture, \"list\", \"globalManufactureMenu\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"globalManufactureMenu\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&GlobalManufactureState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&GlobalManufactureState::btnOkClick, Options::keyCancel);\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_PRODUCTION_OVERVIEW\"));\n\n\t_txtFunds->setText(tr(\"STR_CURRENT_FUNDS\").arg(Unicode::formatFunding(_game->getSavedGame()->getFunds())));\n\n\t_txtItem->setText(tr(\"STR_ITEM\"));\n\n\t_txtEngineers->setText(tr(\"STR_ENGINEERS__ALLOCATED\"));\n\t_txtEngineers->setWordWrap(true);\n\n\t_txtProduced->setText(tr(\"STR_UNITS_PRODUCED\"));\n\t_txtProduced->setWordWrap(true);\n\n\t_txtCost->setText(tr(\"STR_COST__PER__UNIT\"));\n\t_txtCost->setWordWrap(true);\n\n\t_txtTimeLeft->setText(tr(\"STR_DAYS_HOURS_LEFT\"));\n\t_txtTimeLeft->setWordWrap(true);\n\n\t_lstManufacture->setColumns(5, 114, 16, 52, 56, 48);\n\t_lstManufacture->setAlign(ALIGN_RIGHT);\n\t_lstManufacture->setAlign(ALIGN_LEFT, 0);\n\t_lstManufacture->setSelectable(true);\n\t_lstManufacture->setBackground(_window);\n\t_lstManufacture->setMargin(2);\n\t_lstManufacture->setWordWrap(true);\n\t_lstManufacture->onMouseClick((ActionHandler)&GlobalManufactureState::onSelectBase, SDL_BUTTON_LEFT);\n\t_lstManufacture->onMouseClick((ActionHandler)&GlobalManufactureState::onOpenTechTreeViewer, SDL_BUTTON_MIDDLE);\n}\n\n/**\n *\n */\nGlobalManufactureState::~GlobalManufactureState()\n{\n\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid GlobalManufactureState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Goes to the base's manufacture screen when clicking its project\n * @param action Pointer to an action.\n */\nvoid GlobalManufactureState::onSelectBase(Action *)\n{\n\tBase *base = _bases[_lstManufacture->getSelectedRow()];\n\n\tif (base)\n\t{\n\t\t// close this window\n\t\t_game->popState();\n\n\t\t// close Manufacture UI (goes back to BaseView)\n\t\tif (_openedFromBasescape)\n\t\t{\n\t\t\t_game->popState();\n\t\t}\n\n\t\t// open new window\n\t\t_game->pushState(new ManufactureState(base));\n\t}\n}\n\n/**\n * Opens the TechTreeViewer for the corresponding topic.\n * @param action Pointer to an action.\n */\nvoid GlobalManufactureState::onOpenTechTreeViewer(Action *)\n{\n\tconst RuleManufacture *selectedTopic = _topics[_lstManufacture->getSelectedRow()];\n\n\tif (selectedTopic)\n\t{\n\t\tif (_game->isCtrlPressed())\n\t\t{\n\t\t\tstd::string articleId = selectedTopic->getName();\n\t\t\tUfopaedia::openArticle(_game, articleId);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_game->pushState(new TechTreeViewerState(0, selectedTopic));\n\t\t}\n\t}\n}\n\n/**\n * Updates the production list\n * after going to other screens.\n */\nvoid GlobalManufactureState::init()\n{\n\tState::init();\n\tfillProductionList();\n}\n\n/**\n * Fills the list with Productions from all bases. Also updates total count of available workshop space and available/allocated engineers.\n */\nvoid GlobalManufactureState::fillProductionList()\n{\n\t_bases.clear();\n\t_topics.clear();\n\t_lstManufacture->clearList();\n\n\tint availableEngineers = 0;\n\tint allocatedEngineers = 0;\n\tint freeWorkshops = 0;\n\n\tfor (Base *xbase : *_game->getSavedGame()->getBases())\n\t{\n\t\tauto& baseProductions = xbase->getProductions();\n\t\tif (!baseProductions.empty() || xbase->getEngineers() > 0)\n\t\t{\n\t\t\tstd::string baseName = xbase->getName(_game->getLanguage());\n\t\t\t_lstManufacture->addRow(3, baseName.c_str(), \"\", \"\");\n\t\t\t_lstManufacture->setRowColor(_lstManufacture->getLastRowIndex(), _lstManufacture->getSecondaryColor());\n\n\t\t\t// dummy\n\t\t\t_bases.push_back(0);\n\t\t\t_topics.push_back(0);\n\t\t}\n\t\tfor (const auto* prod : baseProductions)\n\t\t{\n\t\t\tstd::ostringstream s1;\n\t\t\ts1 << prod->getAssignedEngineers();\n\t\t\tstd::ostringstream s2;\n\t\t\ts2 << prod->getAmountProduced() << \"/\";\n\t\t\tif (prod->getInfiniteAmount()) s2 << \"∞\";\n\t\t\telse s2 << prod->getAmountTotal();\n\t\t\tif (prod->getSellItems()) s2 << \" $\";\n\t\t\tstd::ostringstream s3;\n\t\t\ts3 << Unicode::formatFunding(prod->getRules()->getManufactureCost());\n\t\t\tstd::ostringstream s4;\n\t\t\tif (prod->getInfiniteAmount())\n\t\t\t{\n\t\t\t\ts4 << \"∞\";\n\t\t\t}\n\t\t\telse if (prod->getAssignedEngineers() > 0)\n\t\t\t{\n\t\t\t\tint timeLeft = prod->getAmountTotal() * prod->getRules()->getManufactureTime() - prod->getTimeSpent();\n\t\t\t\tint numEffectiveEngineers = prod->getAssignedEngineers();\n\t\t\t\t// ensure we round up since it takes an entire hour to manufacture any part of that hour's capacity\n\t\t\t\tint hoursLeft = (timeLeft + numEffectiveEngineers - 1) / numEffectiveEngineers;\n\t\t\t\tint daysLeft = hoursLeft / 24;\n\t\t\t\tint hours = hoursLeft % 24;\n\t\t\t\ts4 << daysLeft << \"/\" << hours;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\n\t\t\t\ts4 << \"-\";\n\t\t\t}\n\t\t\t_lstManufacture->addRow(5, tr(prod->getRules()->getName()).c_str(), s1.str().c_str(), s2.str().c_str(), s3.str().c_str(), s4.str().c_str());\n\n\t\t\t_bases.push_back(xbase);\n\t\t\t_topics.push_back(prod->getRules());\n\t\t}\n\t\tif (baseProductions.empty() && xbase->getEngineers() > 0)\n\t\t{\n\t\t\t_lstManufacture->addRow(5, tr(\"STR_NONE\").c_str(), \"\", \"\", \"\", \"\");\n\n\t\t\t_bases.push_back(xbase);\n\t\t\t_topics.push_back(0);\n\t\t}\n\n\t\tavailableEngineers += xbase->getAvailableEngineers();\n\t\tallocatedEngineers += xbase->getAllocatedEngineers();\n\t\tfreeWorkshops += xbase->getFreeWorkshops();\n\t}\n\n\t_txtAvailable->setText(tr(\"STR_ENGINEERS_AVAILABLE\").arg(availableEngineers));\n\t_txtAllocated->setText(tr(\"STR_ENGINEERS_ALLOCATED\").arg(allocatedEngineers));\n\t_txtSpace->setText(tr(\"STR_WORKSHOP_SPACE_AVAILABLE\").arg(freeWorkshops));\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/GlobalManufactureState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2019 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass TextList;\nclass Base;\nclass RuleManufacture;\n\n/**\n * Global Manufacture screen that provides overview\n * of the ongoing manufacturing operations in all the bases.\n */\nclass GlobalManufactureState : public State\n{\nprivate:\n\tTextButton *_btnOk;\n\tWindow *_window;\n\tText *_txtTitle, *_txtAvailable, *_txtAllocated, *_txtSpace, *_txtFunds, *_txtItem, *_txtEngineers, *_txtProduced, *_txtCost, *_txtTimeLeft;\n\tTextList *_lstManufacture;\n\n\tstd::vector<Base*> _bases;\n\tstd::vector<const RuleManufacture*> _topics;\n\tbool _openedFromBasescape;\npublic:\n\t/// Creates the GlobalManufacture state.\n\tGlobalManufactureState(bool openedFromBasescape);\n\t/// Cleans up the GlobalManufacture state.\n\t~GlobalManufactureState();\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the Production list.\n\tvoid onSelectBase(Action *action);\n\tvoid onOpenTechTreeViewer(Action *action);\n\t/// Updates the production list.\n\tvoid init() override;\n\t/// Fills the list with Productions from all bases.\n\tvoid fillProductionList();\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/GlobalResearchDiaryState.cpp",
    "content": "/*\n * Copyright 2010-2025 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"GlobalResearchDiaryState.h\"\n#include <sstream>\n#include \"../Engine/CrossPlatform.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/ArrowButton.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextEdit.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Interface/Window.h\"\n#include \"../Savegame/ResearchDiary.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Mod/RuleResearch.h\"\n#include \"../Ufopaedia/Ufopaedia.h\"\n#include \"TechTreeViewerState.h\"\n#include <algorithm>\n#include <locale>\n\nnamespace OpenXcom\n{\n\nstruct compareItemName\n{\n\tbool operator()(const TranslatedResearchDiaryItem* a, const TranslatedResearchDiaryItem* b) const\n\t{\n\t\treturn Unicode::naturalCompare(a->name, b->name);\n\t}\n};\n\nstruct compareItemSortOrder\n{\n\tbool operator()(const TranslatedResearchDiaryItem* a, const TranslatedResearchDiaryItem* b) const\n\t{\n\t\treturn a->sortOrder < b->sortOrder;\n\t}\n};\n\n\n/**\n * Initializes all the elements in the Research Diary window.\n */\nGlobalResearchDiaryState::GlobalResearchDiaryState() : _doNotReset(false)\n{\n\t// Create objects\n\t_window = new Window(this, 320, 200, 0, 0);\n\t_btnQuickSearch = new TextEdit(this, 48, 9, 10, 19);\n\t_btnOk = new TextButton(304, 16, 8, 176);\n\t_txtTitle = new Text(310, 17, 5, 8);\n\t_txtName = new Text(142, 9, 10, 29);\n\t_txtType = new Text(48, 9, 193, 29);\n\t_txtDate = new Text(54, 9, 242, 29);\n\t_lstItems = new TextList(288, 96, 8, 38);\n\t_sortName = new ArrowButton(ARROW_NONE, 11, 8, 10, 29);\n\t_sortDate = new ArrowButton(ARROW_NONE, 11, 8, 242, 29);\n\t_txtTooltip = new Text(304, 40, 8, 135);\n\n\t// Set palette\n\tsetInterface(\"globalResearchDiary\");\n\n\tadd(_window, \"window\", \"globalResearchDiary\");\n\tadd(_btnQuickSearch, \"button\", \"globalResearchDiary\");\n\tadd(_btnOk, \"button\", \"globalResearchDiary\");\n\tadd(_txtTitle, \"text\", \"globalResearchDiary\");\n\tadd(_txtName, \"text\", \"globalResearchDiary\");\n\tadd(_txtType, \"text\", \"globalResearchDiary\");\n\tadd(_txtDate, \"text\", \"globalResearchDiary\");\n\tadd(_lstItems, \"list\", \"globalResearchDiary\");\n\tadd(_sortName, \"text\", \"globalResearchDiary\");\n\tadd(_sortDate, \"text\", \"globalResearchDiary\");\n\tadd(_txtTooltip, \"text\", \"globalResearchDiary\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"globalResearchDiary\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&GlobalResearchDiaryState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&GlobalResearchDiaryState::btnOkClick, Options::keyOk);\n\t_btnOk->onKeyboardPress((ActionHandler)&GlobalResearchDiaryState::btnOkClick, Options::keyCancel);\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_RESEARCH_DIARY\"));\n\n\t_txtName->setText(tr(\"STR_NAME_UC\"));\n\n\t_txtType->setText(tr(\"STR_TYPE\"));\n\t_txtType->setAlign(ALIGN_CENTER);\n\n\t_txtDate->setText(tr(\"STR_DATE_UC\"));\n\n\t_lstItems->setColumns(3, 204, 28, 54);\n\t_lstItems->setSelectable(true);\n\t_lstItems->setBackground(_window);\n\t_lstItems->setMargin(2);\n\t_lstItems->onMouseClick((ActionHandler)&GlobalResearchDiaryState::lstItemLClick, SDL_BUTTON_LEFT);\n\t_lstItems->onMouseClick((ActionHandler)&GlobalResearchDiaryState::lstItemMClick, SDL_BUTTON_MIDDLE);\n\t_lstItems->onMouseOver((ActionHandler)&GlobalResearchDiaryState::lstItemMouseOver);\n\t_lstItems->onMouseOut((ActionHandler)&GlobalResearchDiaryState::lstItemMouseOut);\n\n\t_sortName->setX(_sortName->getX() + _txtName->getTextWidth() + 4);\n\t_sortName->onMouseClick((ActionHandler)&GlobalResearchDiaryState::sortNameClick);\n\n\t_sortDate->setX(_sortDate->getX() + _txtDate->getTextWidth() + 4);\n\t_sortDate->onMouseClick((ActionHandler)&GlobalResearchDiaryState::sortDateClick);\n\n\t_itemOrder = RESEARCH_DIARY_SORT_NONE;\n\n\t_btnQuickSearch->setText(\"\"); // redraw\n\t_btnQuickSearch->onEnter((ActionHandler)&GlobalResearchDiaryState::btnQuickSearchApply);\n\t_btnQuickSearch->setVisible(Options::oxceQuickSearchButton);\n\n\t_btnOk->onKeyboardRelease((ActionHandler)&GlobalResearchDiaryState::btnQuickSearchToggle, Options::keyToggleQuickSearch);\n\n\t// translate only once\n\tauto& vec = _game->getSavedGame()->getResearchDiary();\n\tint sortOrder = vec.size();\n\tfor (auto it = vec.rbegin(); it != vec.rend(); ++it)\n\t{\n\t\tauto* researchDiaryEntry = (*it);\n\n\t\tstd::string translation = tr(researchDiaryEntry->research->getName());\n\t\tstd::string upper = translation;\n\t\tUnicode::upperCase(upper);\n\n\t\tstd::ostringstream ss3;\n\t\tss3 << researchDiaryEntry->year << \"-\";\n\t\tif (researchDiaryEntry->month < 10) ss3 << \"0\";\n\t\tss3 << researchDiaryEntry->month << \"-\";\n\t\tif (researchDiaryEntry->day < 10) ss3 << \"0\";\n\t\tss3 << researchDiaryEntry->day;\n\n\t\t_itemList.push_back(TranslatedResearchDiaryItem(researchDiaryEntry, translation, upper, ss3.str(), sortOrder));\n\t\tsortOrder--;\n\t}\n\n\t_txtTooltip->setVerticalAlign(ALIGN_MIDDLE);\n\t_txtTooltip->setWordWrap(true);\n}\n\n/**\n *\n */\nGlobalResearchDiaryState::~GlobalResearchDiaryState()\n{\n\n}\n\n/**\n * Returns to the previous screen.\n */\nvoid GlobalResearchDiaryState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n* Quick search toggle.\n* @param action Pointer to an action.\n*/\nvoid GlobalResearchDiaryState::btnQuickSearchToggle(Action *action)\n{\n\tif (_btnQuickSearch->getVisible())\n\t{\n\t\t_btnQuickSearch->setText(\"\");\n\t\t_btnQuickSearch->setVisible(false);\n\t\tbtnQuickSearchApply(action);\n\t}\n\telse\n\t{\n\t\t_btnQuickSearch->setVisible(true);\n\t\t_btnQuickSearch->setFocus(true);\n\t}\n}\n\n/**\n* Quick search.\n*/\nvoid GlobalResearchDiaryState::btnQuickSearchApply(Action *)\n{\n\tinitList();\n}\n\n/**\n * Reloads the item list.\n */\nvoid GlobalResearchDiaryState::initList()\n{\n\tstd::string searchString = _btnQuickSearch->getText();\n\tUnicode::upperCase(searchString);\n\n\t// clear everything\n\t_filteredItemList.clear();\n\n\t// find relevant items\n\tfor (auto& origItem : _itemList)\n\t{\n\t\t// quick search\n\t\tif (!searchString.empty())\n\t\t{\n\t\t\tif (origItem.upperName.find(searchString) == std::string::npos && origItem.date.find(searchString) == std::string::npos)\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\t_filteredItemList.push_back(&origItem);\n\t}\n\n\tsortList();\n}\n\n/**\n * Refreshes the item list.\n */\nvoid GlobalResearchDiaryState::init()\n{\n\tState::init();\n\n\t// coming back from TechTreeViewer/Ufopedia\n\tif (_doNotReset)\n\t{\n\t\t_doNotReset = false;\n\t\treturn;\n\t}\n\n\tinitList();\n}\n\n/**\n * Updates the sorting arrows based on the current setting.\n */\nvoid GlobalResearchDiaryState::updateArrows()\n{\n\t_sortName->setShape(ARROW_NONE);\n\t_sortDate->setShape(ARROW_NONE);\n\tswitch (_itemOrder)\n\t{\n\tcase RESEARCH_DIARY_SORT_NONE:\n\t\t_sortDate->setShape(ARROW_SMALL_DOWN); // it is already sorted by date in the original vector\n\t\tbreak;\n\tcase RESEARCH_DIARY_SORT_NAME_ASC:\n\t\t_sortName->setShape(ARROW_SMALL_UP);\n\t\tbreak;\n\tcase RESEARCH_DIARY_SORT_NAME_DESC:\n\t\t_sortName->setShape(ARROW_SMALL_DOWN);\n\t\tbreak;\n\tcase RESEARCH_DIARY_SORT_DATE_ASC:\n\t\t_sortDate->setShape(ARROW_SMALL_UP);\n\t\tbreak;\n\tcase RESEARCH_DIARY_SORT_DATE_DESC:\n\t\t_sortDate->setShape(ARROW_SMALL_DOWN);\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n}\n\n/**\n * Sorts the list.\n */\nvoid GlobalResearchDiaryState::sortList()\n{\n\tupdateArrows();\n\n\tswitch (_itemOrder)\n\t{\n\tcase RESEARCH_DIARY_SORT_NONE:\n\t\tbreak;\n\tcase RESEARCH_DIARY_SORT_NAME_ASC:\n\t\tstd::stable_sort(_filteredItemList.begin(), _filteredItemList.end(), compareItemName());\n\t\tbreak;\n\tcase RESEARCH_DIARY_SORT_NAME_DESC:\n\t\tstd::stable_sort(_filteredItemList.rbegin(), _filteredItemList.rend(), compareItemName());\n\t\tbreak;\n\tcase RESEARCH_DIARY_SORT_DATE_ASC:\n\t\tstd::stable_sort(_filteredItemList.begin(), _filteredItemList.end(), compareItemSortOrder());\n\t\tbreak;\n\tcase RESEARCH_DIARY_SORT_DATE_DESC:\n\t\tstd::stable_sort(_filteredItemList.rbegin(), _filteredItemList.rend(), compareItemSortOrder());\n\t\tbreak;\n\t}\n\n\tupdateList();\n}\n\n/**\n * Updates the list with the current diary items.\n */\nvoid GlobalResearchDiaryState::updateList()\n{\n\t_lstItems->clearList();\n\n\tfor (const auto* item : _filteredItemList)\n\t{\n\t\tstd::ostringstream ss2;\n\t\tss2 << (int)item->diaryEntry->source.type;\n\t\t_lstItems->addRow(3, item->name.c_str(), ss2.str().c_str(), item->date.c_str());\n\t}\n}\n\n/**\n * Sorts the items by name.\n */\nvoid GlobalResearchDiaryState::sortNameClick(Action *)\n{\n\t_itemOrder = _itemOrder == RESEARCH_DIARY_SORT_NAME_ASC ? RESEARCH_DIARY_SORT_NAME_DESC : RESEARCH_DIARY_SORT_NAME_ASC;\n\tsortList();\n}\n\n/**\n * Sorts the items by date.\n */\nvoid GlobalResearchDiaryState::sortDateClick(Action *)\n{\n\t_itemOrder = _itemOrder == RESEARCH_DIARY_SORT_DATE_ASC ? RESEARCH_DIARY_SORT_DATE_DESC : RESEARCH_DIARY_SORT_DATE_ASC;\n\tsortList();\n}\n\n/**\n * Handles mouse L-clicks.\n * @param action Pointer to an action.\n */\nvoid GlobalResearchDiaryState::lstItemLClick(Action* action)\n{\n\tauto* selectedTopic = _filteredItemList[_lstItems->getSelectedRow()]->diaryEntry->research;\n\t_doNotReset = true;\n\t_game->pushState(new TechTreeViewerState(selectedTopic, 0));\n}\n\n/**\n * Handles mouse M-clicks.\n * @param action Pointer to an action.\n */\nvoid GlobalResearchDiaryState::lstItemMClick(Action* action)\n{\n\tauto* selectedTopic = _filteredItemList[_lstItems->getSelectedRow()]->diaryEntry->research;\n\t_doNotReset = true;\n\tUfopaedia::openArticle(_game, selectedTopic->getName());\n}\n\nvoid GlobalResearchDiaryState::lstItemMouseOver(Action *)\n{\n\tsize_t sel = _lstItems->getSelectedRow();\n\tif (sel < _filteredItemList.size())\n\t{\n\t\tauto item = _filteredItemList[sel];\n\n\t\tstd::string sourceNameTranslated;\n\t\tif (item->diaryEntry->source.type != BASE) sourceNameTranslated = tr(item->diaryEntry->source.name);\n\n\t\tstd::string descTemplate{ item->diaryEntry->source.getTypeString() };\n\t\tstd::string desc = tr(descTemplate).arg(item->diaryEntry->research->getName()).arg(item->diaryEntry->source.name).arg(sourceNameTranslated);\n\n\t\t_txtTooltip->setText(desc);\n\t}\n\telse\n\t{\n\t\t_txtTooltip->setText(\"\");\n\t}\n}\n\nvoid GlobalResearchDiaryState::lstItemMouseOut(Action *)\n{\n\t_txtTooltip->setText(\"\");\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/GlobalResearchDiaryState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2025 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include <vector>\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass TextEdit;\nclass TextList;\nclass ArrowButton;\nstruct ResearchDiaryEntry;\n\n/// Research diary sorting modes.\nenum ReserachDiarySort\n{\n\tRESEARCH_DIARY_SORT_NONE,\n\tRESEARCH_DIARY_SORT_NAME_ASC,\n\tRESEARCH_DIARY_SORT_NAME_DESC,\n\tRESEARCH_DIARY_SORT_DATE_ASC,\n\tRESEARCH_DIARY_SORT_DATE_DESC\n};\n\nstruct TranslatedResearchDiaryItem\n{\n\tTranslatedResearchDiaryItem(ResearchDiaryEntry* _diaryEntry, const std::string& _name, const std::string& _upperName, const std::string& _date, int _sortOrder)\n\t\t: diaryEntry(_diaryEntry), name(_name), upperName(_upperName), date(_date), sortOrder(_sortOrder)\n\t{\n\t}\n\tResearchDiaryEntry* diaryEntry;\n\tstd::string name;\n\tstd::string upperName;\n\tstd::string date;\n\tint sortOrder;\n};\n\n/**\n * Research Diary window that displays all discovered research.\n */\nclass GlobalResearchDiaryState : public State\n{\nprivate:\n\tTextButton *_btnOk;\n\tTextEdit *_btnQuickSearch;\n\tWindow *_window;\n\tText *_txtTitle, *_txtName, *_txtType, *_txtDate;\n\tTextList *_lstItems;\n\tArrowButton *_sortName, *_sortDate;\n\tText *_txtTooltip;\n\tbool _doNotReset;\n\n\tstd::vector<TranslatedResearchDiaryItem> _itemList;\n\tstd::vector<TranslatedResearchDiaryItem*> _filteredItemList;\n\tvoid initList();\n\tReserachDiarySort _itemOrder;\n\tvoid updateArrows();\npublic:\n\t/// Creates the GlobalResearchDiary state.\n\tGlobalResearchDiaryState();\n\t/// Cleans up the GlobalResearchDiary state.\n\t~GlobalResearchDiaryState();\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action* action);\n\t/// Handlers for Quick Search.\n\tvoid btnQuickSearchToggle(Action* action);\n\tvoid btnQuickSearchApply(Action* action);\n\t/// Sets up the item list.\n\tvoid init() override;\n\t/// Sorts the item list.\n\tvoid sortList();\n\t/// Updates the item list.\n\tvirtual void updateList();\n\t/// Handler for clicking the Name arrow.\n\tvoid sortNameClick(Action* action);\n\t/// Handler for clicking the Date arrow.\n\tvoid sortDateClick(Action* action);\n\t/// Handler for clicking the item list.\n\tvoid lstItemLClick(Action* action);\n\tvoid lstItemMClick(Action* action);\n\t/// Handler for moving the mouse over an item.\n\tvoid lstItemMouseOver(Action* action);\n\t/// Handler for moving the mouse outside the list.\n\tvoid lstItemMouseOut(Action* action);\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/GlobalResearchState.cpp",
    "content": "/*\n * Copyright 2010-2018 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"GlobalResearchState.h\"\n#include <sstream>\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Base.h\"\n#include \"ResearchState.h\"\n#include \"../Savegame/ResearchProject.h\"\n#include \"../Mod/RuleResearch.h\"\n#include \"TechTreeViewerState.h\"\n#include \"GlobalResearchDiaryState.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the GlobalResearch screen.\n */\nGlobalResearchState::GlobalResearchState(bool openedFromBasescape) : _openedFromBasescape(openedFromBasescape)\n{\n\t// Create objects\n\t_window = new Window(this, 320, 200, 0, 0);\n\t_btnDiary = new TextButton(148, 16, 8, 176);\n\t_btnOk = new TextButton(148, 16, 164, 176);\n\t_txtTitle = new Text(310, 17, 5, 8);\n\t_txtAvailable = new Text(150, 9, 10, 24);\n\t_txtAllocated = new Text(150, 9, 160, 24);\n\t_txtSpace = new Text(300, 9, 10, 34);\n\t_txtProject = new Text(110, 17, 10, 44);\n\t_txtScientists = new Text(106, 17, 120, 44);\n\t_txtProgress = new Text(84, 9, 226, 44);\n\t_lstResearch = new TextList(288, 112, 8, 62);\n\n\t// Set palette\n\tsetInterface(\"globalResearchMenu\");\n\n\tadd(_window, \"window\", \"globalResearchMenu\");\n\tadd(_btnDiary, \"button\", \"globalResearchMenu\");\n\tadd(_btnOk, \"button\", \"globalResearchMenu\");\n\tadd(_txtTitle, \"text\", \"globalResearchMenu\");\n\tadd(_txtAvailable, \"text\", \"globalResearchMenu\");\n\tadd(_txtAllocated, \"text\", \"globalResearchMenu\");\n\tadd(_txtSpace, \"text\", \"globalResearchMenu\");\n\tadd(_txtProject, \"text\", \"globalResearchMenu\");\n\tadd(_txtScientists, \"text\", \"globalResearchMenu\");\n\tadd(_txtProgress, \"text\", \"globalResearchMenu\");\n\tadd(_lstResearch, \"list\", \"globalResearchMenu\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"globalResearchMenu\");\n\n\t_btnDiary->setText(tr(\"STR_RESEARCH_DIARY\"));\n\t_btnDiary->onMouseClick((ActionHandler)&GlobalResearchState::btnDiaryClick);\n\t_btnDiary->onKeyboardPress((ActionHandler)&GlobalResearchState::btnDiaryClick, Options::keyGeoGlobalResearch);\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&GlobalResearchState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&GlobalResearchState::btnOkClick, Options::keyCancel);\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_RESEARCH_OVERVIEW\"));\n\n\t_txtProject->setWordWrap(true);\n\t_txtProject->setText(tr(\"STR_RESEARCH_PROJECT\"));\n\n\t_txtScientists->setWordWrap(true);\n\t_txtScientists->setText(tr(\"STR_SCIENTISTS_ALLOCATED_UC\"));\n\n\t_txtProgress->setText(tr(\"STR_PROGRESS\"));\n\n\t_lstResearch->setColumns(3, 158, 58, 70);\n\t_lstResearch->setSelectable(true);\n\t_lstResearch->setBackground(_window);\n\t_lstResearch->setMargin(2);\n\t_lstResearch->setWordWrap(true);\n\t_lstResearch->onMouseClick((ActionHandler)&GlobalResearchState::onSelectBase, SDL_BUTTON_LEFT);\n\t_lstResearch->onMouseClick((ActionHandler)&GlobalResearchState::onOpenTechTreeViewer, SDL_BUTTON_MIDDLE);\n}\n\n/**\n *\n */\nGlobalResearchState::~GlobalResearchState()\n{\n}\n\n/**\n * Displays the Research Diary UI.\n * @param action Pointer to an action.\n */\nvoid GlobalResearchState::btnDiaryClick(Action *)\n{\n\t_game->pushState(new GlobalResearchDiaryState());\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid GlobalResearchState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Goes to the base's research screen when clicking its project\n * @param action Pointer to an action.\n */\nvoid GlobalResearchState::onSelectBase(Action *)\n{\n\tBase *base = _bases[_lstResearch->getSelectedRow()];\n\n\tif (base)\n\t{\n\t\t// close this window\n\t\t_game->popState();\n\n\t\t// close Research UI (goes back to BaseView)\n\t\tif (_openedFromBasescape)\n\t\t{\n\t\t\t_game->popState();\n\t\t}\n\n\t\t// open new window\n\t\t_game->pushState(new ResearchState(base));\n\t}\n}\n\n/**\n * Opens the TechTreeViewer for the corresponding topic.\n * @param action Pointer to an action.\n */\nvoid GlobalResearchState::onOpenTechTreeViewer(Action *)\n{\n\tconst RuleResearch *selectedTopic = _topics[_lstResearch->getSelectedRow()];\n\n\tif (selectedTopic)\n\t{\n\t\t_game->pushState(new TechTreeViewerState(selectedTopic, 0));\n\t}\n}\n\n/**\n * Updates the research list\n * after going to other screens.\n */\nvoid GlobalResearchState::init()\n{\n\tState::init();\n\tfillProjectList();\n}\n\n/**\n * Fills the list with ResearchProjects from all bases. Also updates total count of available lab space and available/allocated scientists.\n */\nvoid GlobalResearchState::fillProjectList()\n{\n\t_bases.clear();\n\t_topics.clear();\n\t_lstResearch->clearList();\n\n\tint availableScientists = 0;\n\tint allocatedScientists = 0;\n\tint freeLaboratories = 0;\n\n\tfor (Base *xbase : *_game->getSavedGame()->getBases())\n\t{\n\t\tauto& baseProjects = xbase->getResearch();\n\t\tif (!baseProjects.empty() || xbase->getScientists() > 0)\n\t\t{\n\t\t\tstd::string baseName = xbase->getName(_game->getLanguage());\n\t\t\t_lstResearch->addRow(3, baseName.c_str(), \"\", \"\");\n\t\t\t_lstResearch->setRowColor(_lstResearch->getLastRowIndex(), _lstResearch->getSecondaryColor());\n\n\t\t\t// dummy\n\t\t\t_bases.push_back(0);\n\t\t\t_topics.push_back(0);\n\t\t}\n\t\tfor (const auto* proj : baseProjects)\n\t\t{\n\t\t\tstd::ostringstream sstr;\n\t\t\tsstr << proj->getAssigned();\n\t\t\tconst RuleResearch *r = proj->getRules();\n\n\t\t\tstd::string wstr = tr(r->getName());\n\t\t\t_lstResearch->addRow(3, wstr.c_str(), sstr.str().c_str(), tr(proj->getResearchProgress()).c_str());\n\n\t\t\t_bases.push_back(xbase);\n\t\t\t_topics.push_back(r);\n\t\t}\n\t\tif (baseProjects.empty() && xbase->getScientists() > 0)\n\t\t{\n\t\t\t_lstResearch->addRow(3, tr(\"STR_NONE\").c_str(), \"\", \"\");\n\n\t\t\t_bases.push_back(xbase);\n\t\t\t_topics.push_back(0);\n\t\t}\n\n\t\tavailableScientists += xbase->getAvailableScientists();\n\t\tallocatedScientists += xbase->getAllocatedScientists();\n\t\tfreeLaboratories += xbase->getFreeLaboratories();\n\t}\n\n\t_txtAvailable->setText(tr(\"STR_SCIENTISTS_AVAILABLE\").arg(availableScientists));\n\t_txtAllocated->setText(tr(\"STR_SCIENTISTS_ALLOCATED\").arg(allocatedScientists));\n\t_txtSpace->setText(tr(\"STR_LABORATORY_SPACE_AVAILABLE\").arg(freeLaboratories));\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/GlobalResearchState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2018 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass TextList;\nclass Base;\nclass RuleResearch;\n\n/**\n * Global Research screen that provides overview\n * of the ongoing research operations in all the bases.\n */\nclass GlobalResearchState : public State\n{\nprivate:\n\tTextButton *_btnOk;\n\tTextButton *_btnDiary;\n\tWindow *_window;\n\tText *_txtTitle, *_txtAvailable, *_txtAllocated, *_txtSpace, *_txtProject, *_txtScientists, *_txtProgress;\n\tTextList *_lstResearch;\n\n\tstd::vector<Base*> _bases;\n\tstd::vector<const RuleResearch*> _topics;\n\tbool _openedFromBasescape;\npublic:\n\t/// Creates the GlobalResearchState.\n\tGlobalResearchState(bool openedFromBasescape);\n\t/// Cleans up the GlobalResearchState.\n\t~GlobalResearchState();\n\t/// Handler for clicking the Diary button.\n\tvoid btnDiaryClick(Action* action);\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the ResearchProject list.\n\tvoid onSelectBase(Action *action);\n\tvoid onOpenTechTreeViewer(Action *action);\n\t/// Fills the list with ResearchProjects from all bases.\n\tvoid fillProjectList();\n\t/// Updates the research list.\n\tvoid init() override;\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/ItemLocationsState.cpp",
    "content": "/*\n * Copyright 2010-2025 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ItemLocationsState.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/ItemContainer.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Transfer.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements on the UI.\n */\nItemLocationsState::ItemLocationsState(const RuleItem* selectedItem)\n{\n\t_screen = false;\n\n\t_window = new Window(this, 222, 144, 49, 32);\n\t_txtTitle = new Text(200, 9, 59, 42);\n\t_txtBase = new Text(98, 9, 59, 56);\n\t_txtQuantity = new Text(98, 9, 159, 56);\n\t_lstLocations = new TextList(186, 64, 57, 70);\n\t_btnOk = new TextButton(100, 16, 110, 150);\n\n\t// Set palette\n\tsetInterface(\"itemLocations\");\n\n\tadd(_window, \"window\", \"itemLocations\");\n\tadd(_txtTitle, \"text\", \"itemLocations\");\n\tadd(_txtBase, \"text\", \"itemLocations\");\n\tadd(_txtQuantity, \"text\", \"itemLocations\");\n\tadd(_btnOk, \"button\", \"itemLocations\");\n\tadd(_lstLocations, \"list\", \"itemLocations\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"itemLocations\");\n\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_TOPIC\").arg(tr(selectedItem->getType())));\n\n\t_txtBase->setText(tr(\"STR_BASE\"));\n\t_txtQuantity->setText(tr(\"STR_QUANTITY_UC\"));\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&ItemLocationsState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&ItemLocationsState::btnOkClick, Options::keyCancel);\n\n\t_lstLocations->setColumns(3, 100, 40, 30);\n\t_lstLocations->setBackground(_window);\n\t_lstLocations->setMargin(2);\n\t_lstLocations->setSelectable(true);\n\n\tfor (auto* xbase : *_game->getSavedGame()->getBases())\n\t{\n\t\tstd::ostringstream ssInBase, ssInTransfer;\n\t\tssInBase << xbase->getStorageItems()->getItem(selectedItem);\n\t\tint total = 0;\n\t\tfor (auto* xtransfer : *xbase->getTransfers())\n\t\t{\n\t\t\tif (xtransfer->getType() == TRANSFER_ITEM && xtransfer->getItems() == selectedItem)\n\t\t\t{\n\t\t\t\ttotal += xtransfer->getQuantity();\n\t\t\t}\n\t\t}\n\t\tssInTransfer << \"+\" << total;\n\t\t_lstLocations->addRow(3, xbase->getName().c_str(), ssInBase.str().c_str(), ssInTransfer.str().c_str());\n\t}\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid ItemLocationsState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/ItemLocationsState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2025 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass Window;\nclass Text;\nclass TextButton;\nclass TextList;\nclass RuleItem;\n\n/**\n * Window which displays item locations (i.e. which base has how much).\n */\nclass ItemLocationsState : public State\n{\nprivate:\n\tWindow *_window;\n\tText *_txtTitle;\n\tText *_txtBase, *_txtQuantity;\n\tTextList *_lstLocations;\n\tTextButton *_btnOk;\npublic:\n\t/// Creates the ItemLocationsState state.\n\tItemLocationsState(const RuleItem* selectedItem);\n\t/// Cleans up the ItemLocationsState state\n\t~ItemLocationsState() = default;\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action* action);\n};\n}\n"
  },
  {
    "path": "src/Basescape/ManageAlienContainmentState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ManageAlienContainmentState.h\"\n#include \"GlobalAlienContainmentState.h\"\n#include <climits>\n#include <sstream>\n#include <algorithm>\n#include \"../Engine/Action.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Savegame/ResearchProject.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/ItemContainer.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"../Mod/RuleResearch.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Engine/Timer.h\"\n#include \"../Engine/Options.h\"\n#include \"../Menu/ErrorMessageState.h\"\n#include \"SellState.h\"\n#include \"../Mod/RuleInterface.h\"\n#include \"TechTreeViewerState.h\"\n#include \"TransferBaseState.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Manage Alien Containment screen.\n * @param game Pointer to the core game.\n * @param base Pointer to the base to get info from.\n * @param origin Game section that originated this state.\n */\nManageAlienContainmentState::ManageAlienContainmentState(Base *base, int prisonType, OptionsOrigin origin) :\n\t_base(base), _prisonType(prisonType), _origin(origin), _sel(0), _aliensSold(0), _total(0), _doNotReset(false), _threeButtons(false)\n{\n\t_threeButtons = Options::canSellLiveAliens && Options::retainCorpses;\n\n\t// Create objects\n\t_window = new Window(this, 320, 200, 0, 0);\n\tif (_threeButtons)\n\t{\n\t\t// 3 buttons\n\t\t_btnOk = new TextButton(96, 16, 8, 176);\n\t\t_btnSell = new TextButton(96, 16, 112, 176);\n\t\t_btnCancel = new TextButton(96, 16, 216, 176);\n\t\t_btnTransfer = new TextButton(96, 16, 216, 176);\n\t\t_btnCleanup = new TextButton(96, 16, 8, 176);\n\t}\n\telse\n\t{\n\t\t// 2 buttons\n\t\t_btnOk = new TextButton(148, 16, 8, 176);\n\t\t_btnSell = new TextButton(148, 16, 8, 176);\n\t\t_btnCancel = new TextButton(148, 16, 164, 176);\n\t\t_btnTransfer = new TextButton(148, 16, 164, 176);\n\t\t_btnCleanup = new TextButton(148, 16, 8, 176);\n\t}\n\t_txtTitle = new Text(310, 17, 5, 8);\n\t_txtAvailable =  new Text(190, 9, 10, 24);\n\t_txtValueOfSales =  new Text(190, 9, 10, 32);\n\t_txtUsed = new Text(110, 9, 136, 24);\n\t_txtItem = new Text(120, 9, 10, 41);\n\t_txtLiveAliens = new Text(54, 18, 153, 32);\n\t_txtDeadAliens = new Text(54, 18, 207, 32);\n\t_txtInterrogatedAliens = new Text(54, 18, 261, 32);\n\t_lstAliens = new TextList(286, 112, 8, 53);\n\n\ttouchComponentsCreate(_txtTitle);\n\n\t// Set palette\n\tsetInterface(\"manageContainment\");\n\n\tadd(_window, \"window\", \"manageContainment\");\n\tadd(_btnSell, \"button\", \"manageContainment\");\n\tadd(_btnOk, \"button\", \"manageContainment\");\n\tadd(_btnCancel, \"button\", \"manageContainment\");\n\tadd(_btnTransfer, \"button\", \"manageContainment\");\n\tadd(_btnCleanup, \"button\", \"manageContainment\");\n\tadd(_txtTitle, \"text\", \"manageContainment\");\n\tadd(_txtAvailable, \"text\", \"manageContainment\");\n\tadd(_txtValueOfSales, \"text\", \"manageContainment\");\n\tadd(_txtUsed, \"text\", \"manageContainment\");\n\tadd(_txtItem, \"text\", \"manageContainment\");\n\tadd(_txtLiveAliens, \"text\", \"manageContainment\");\n\tadd(_txtDeadAliens, \"text\", \"manageContainment\");\n\tadd(_txtInterrogatedAliens, \"text\", \"manageContainment\");\n\tadd(_lstAliens, \"list\", \"manageContainment\");\n\n\ttouchComponentsAdd(\"button2\", \"manageContainment\", _window);\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"manageContainment\");\n\n\ttouchComponentsConfigure();\n\n\t_btnOk->setText(trAlt(_threeButtons ? \"STR_KILL_SELECTED\" : \"STR_REMOVE_SELECTED\", _prisonType));\n\t_btnOk->onMouseClick((ActionHandler)&ManageAlienContainmentState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&ManageAlienContainmentState::btnOkClick, Options::keyOk);\n\t_btnOk->onKeyboardPress((ActionHandler)&ManageAlienContainmentState::onGlobalAlienContainmentClick, Options::keyGeoGlobalAlienContainment);\n\n\t_btnSell->setText(trAlt(\"STR_SELL_SELECTED\", _prisonType));\n\t_btnSell->onMouseClick((ActionHandler)&ManageAlienContainmentState::btnSellClick);\n\n\t_btnCancel->setText(tr(\"STR_CANCEL\"));\n\t_btnCancel->onMouseClick((ActionHandler)&ManageAlienContainmentState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&ManageAlienContainmentState::btnCancelClick, Options::keyCancel);\n\n\t_btnTransfer->setText(tr(\"STR_GO_TO_TRANSFERS\"));\n\t_btnTransfer->onMouseClick((ActionHandler)&ManageAlienContainmentState::btnTransferClick);\n\n\t_btnCleanup->setText(tr(\"STR_PRISON_CLEANUP\"));\n\t_btnCleanup->onMouseClick((ActionHandler)&ManageAlienContainmentState::btnCleanupClick);\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(trAlt(\"STR_MANAGE_CONTAINMENT\", _prisonType));\n\n\t_txtItem->setText(trAlt(\"STR_ALIEN\", _prisonType));\n\n\t_txtLiveAliens->setText(trAlt(\"STR_LIVE_ALIENS\", _prisonType));\n\t_txtLiveAliens->setWordWrap(true);\n\t_txtLiveAliens->setVerticalAlign(ALIGN_BOTTOM);\n\n\t_txtDeadAliens->setText(trAlt(\"STR_DEAD_ALIENS\", _prisonType));\n\t_txtDeadAliens->setWordWrap(true);\n\t_txtDeadAliens->setVerticalAlign(ALIGN_BOTTOM);\n\n\t_txtInterrogatedAliens->setText(trAlt(\"STR_UNDER_INTERROGATION\", _prisonType));\n\t_txtInterrogatedAliens->setWordWrap(true);\n\t_txtInterrogatedAliens->setVerticalAlign(ALIGN_BOTTOM);\n\n\t_lstAliens->setArrowColumn(184, ARROW_HORIZONTAL);\n\tif (Options::canSellLiveAliens) {\n\t\t_lstAliens->setColumns(5, 120, 40, 64, 46, 46);\n\t} else {\n\t\t_lstAliens->setColumns(5, 150, 10, 64, 46, 46);\n\t}\n\t_lstAliens->setSelectable(true);\n\t_lstAliens->setBackground(_window);\n\t_lstAliens->setMargin(2);\n\t_lstAliens->onLeftArrowPress((ActionHandler)&ManageAlienContainmentState::lstItemsLeftArrowPress);\n\t_lstAliens->onLeftArrowRelease((ActionHandler)&ManageAlienContainmentState::lstItemsLeftArrowRelease);\n\t_lstAliens->onLeftArrowClick((ActionHandler)&ManageAlienContainmentState::lstItemsLeftArrowClick);\n\t_lstAliens->onRightArrowPress((ActionHandler)&ManageAlienContainmentState::lstItemsRightArrowPress);\n\t_lstAliens->onRightArrowRelease((ActionHandler)&ManageAlienContainmentState::lstItemsRightArrowRelease);\n\t_lstAliens->onRightArrowClick((ActionHandler)&ManageAlienContainmentState::lstItemsRightArrowClick);\n\t_lstAliens->onMousePress((ActionHandler)&ManageAlienContainmentState::lstItemsMousePress);\n\n\t_timerInc = new Timer(250);\n\t_timerInc->onTimer((StateHandler)&ManageAlienContainmentState::increase);\n\t_timerDec = new Timer(250);\n\t_timerDec->onTimer((StateHandler)&ManageAlienContainmentState::decrease);\n}\n\n/**\n *\n */\nManageAlienContainmentState::~ManageAlienContainmentState()\n{\n\tdelete _timerInc;\n\tdelete _timerDec;\n}\n\n/**\n* Resets stuff when coming back from other screens.\n*/\nvoid ManageAlienContainmentState::init()\n{\n\tState::init();\n\n\t// coming back from TechTreeViewer\n\tif (_doNotReset)\n\t{\n\t\t_doNotReset = false;\n\t\treturn;\n\t}\n\n\tresetListAndTotals();\n\n\ttouchComponentsRefresh();\n}\n\n/**\n * Resets the list and the totals, updates button visibility.\n */\nvoid ManageAlienContainmentState::resetListAndTotals()\n{\n\t_qtys.clear();\n\t_aliens.clear();\n\t_sel = 0;\n\t_aliensSold = 0;\n\t_total = 0;\n\n\t_lstAliens->clearList();\n\n\tstd::vector<std::string> researchList;\n\tfor (const auto* proj : _base->getResearch())\n\t{\n\t\tconst RuleResearch *research = proj->getRules();\n\t\tconst RuleItem *item = research->getNeededItem();\n\t\tif (research->isHoldingNeededItem() && item && item->isAlien() && item->getPrisonType() == _prisonType)\n\t\t{\n\t\t\tresearchList.push_back(research->getName());\n\t\t}\n\t}\n\n\tfor (auto& itemType : _game->getMod()->getItemsList())\n\t{\n\t\tRuleItem *rule = _game->getMod()->getItem(itemType, true);\n\n\t\tint qty = _base->getStorageItems()->getItem(rule);\n\t\tif (qty > 0 && rule->isAlien() && rule->getPrisonType() == _prisonType)\n\t\t{\n\t\t\t_qtys.push_back(0);\n\t\t\t_aliens.push_back(itemType);\n\t\t\tstd::ostringstream ss;\n\t\t\tss << qty;\n\t\t\tstd::string rqty;\n\t\t\tauto researchIt = std::find(researchList.begin(), researchList.end(), itemType);\n\t\t\tif (researchIt != researchList.end())\n\t\t\t{\n\t\t\t\trqty = \"1\";\n\t\t\t\tresearchList.erase(researchIt);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\trqty = \"0\";\n\t\t\t}\n\n\t\t\tstd::string formattedCost = \"\";\n\t\t\tif (Options::canSellLiveAliens)\n\t\t\t{\n\t\t\t\tint64_t adjustedCost = rule->getSellCostAdjusted(_base, _game->getSavedGame());\n\t\t\t\tformattedCost = Unicode::formatFunding(adjustedCost / 1000).append(\"K\");\n\t\t\t}\n\n\t\t\t_lstAliens->addRow(5, tr(itemType).c_str(), formattedCost.c_str(), ss.str().c_str(), \"0\", rqty.c_str());\n\t\t}\n\t}\n\n\tfor (const auto& researchName : researchList)\n\t{\n\t\t_aliens.push_back(researchName);\n\t\t_qtys.push_back(0);\n\t\t_lstAliens->addRow(5, tr(researchName).c_str(), Options::canSellLiveAliens ? \"-\" : \"\", \"0\", \"0\", \"1\");\n\t\t_lstAliens->setRowColor(_qtys.size() -1, _lstAliens->getSecondaryColor());\n\t}\n\n\t// update totals\n\tint availableContainment = _base->getAvailableContainment(_prisonType);\n\tint usedContainment = _base->getUsedContainment(_prisonType);\n\tint freeContainment = availableContainment - usedContainment;\n\t{\n\t\t_txtAvailable->setText(tr(\"STR_SPACE_AVAILABLE\").arg(freeContainment));\n\n\t\t_txtUsed->setText(tr(\"STR_SPACE_USED\").arg(usedContainment));\n\n\t\tif (Options::canSellLiveAliens)\n\t\t{\n\t\t\t_txtValueOfSales->setText(tr(\"STR_VALUE_OF_SALES\").arg(Unicode::formatFunding(_total)));\n\t\t}\n\t}\n\n\t// update buttons\n\t{\n\t\tbool overCrowded = false;\n\t\tif (availableContainment == 0 || Options::storageLimitsEnforced)\n\t\t{\n\t\t\toverCrowded = (freeContainment < 0);\n\t\t}\n\n\t\t_btnCancel->setVisible(!overCrowded);\n\t\t_btnOk->setVisible(!overCrowded);\n\t\t_btnSell->setVisible(!overCrowded && _threeButtons);\n\t\t_btnTransfer->setVisible(overCrowded);\n\n\t\tint usedContainmentExternal = _base->getUsedContainment(_prisonType, true);\n\t\tbool needToCleanup = overCrowded && usedContainmentExternal > 0 && availableContainment < usedContainmentExternal;\n\n\t\t_btnCleanup->setVisible(needToCleanup);\n\t}\n}\n\n/**\n * Runs the arrow timers.\n */\nvoid ManageAlienContainmentState::think()\n{\n\tState::think();\n\n\t_timerInc->think(this, 0);\n\t_timerDec->think(this, 0);\n}\n\n/**\n * Deals with the selected aliens.\n * @param action Pointer to an action.\n */\nvoid ManageAlienContainmentState::btnOkClick(Action *)\n{\n\tbool sell = Options::canSellLiveAliens && !Options::retainCorpses; // in all other cases, it's kill, not sell\n\tdealWithSelectedAliens(sell);\n}\n\n/**\n * Opens the Global Alien Containment UI.\n * @param action Pointer to an action.\n */\nvoid ManageAlienContainmentState::onGlobalAlienContainmentClick(Action *)\n{\n\t_game->pushState(new GlobalAlienContainmentState(true));\n}\n\n/**\n * Deals with the selected aliens.\n * @param action Pointer to an action.\n */\nvoid ManageAlienContainmentState::btnSellClick(Action *)\n{\n\tdealWithSelectedAliens(true); // this one is always sell\n}\n\n/**\n * Deals with the selected aliens.\n */\nvoid ManageAlienContainmentState::dealWithSelectedAliens(bool sell)\n{\n\tfor (size_t i = 0; i < _qtys.size(); ++i)\n\t{\n\t\tif (_qtys[i] > 0)\n\t\t{\n\t\t\t// remove the aliens\n\t\t\t_base->getStorageItems()->removeItem(_aliens[i], _qtys[i]);\n\n\t\t\tif (sell)\n\t\t\t{\n\t\t\t\tint64_t adjustedCost = _game->getMod()->getItem(_aliens[i], true)->getSellCostAdjusted(_base, _game->getSavedGame());\n\t\t\t\tadjustedCost = adjustedCost * _qtys[i];\n\t\t\t\t_game->getSavedGame()->setFunds(_game->getSavedGame()->getFunds() + adjustedCost);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// add the corpses\n\t\t\t\tUnit* ruleUnit = _game->getMod()->getUnit(_aliens[i], false);\n\t\t\t\tif (ruleUnit)\n\t\t\t\t{\n\t\t\t\t\tauto* ruleCorpse = ruleUnit->getArmor()->getCorpseGeoscape();\n\t\t\t\t\tif (ruleCorpse && ruleCorpse->isRecoverable() && ruleCorpse->isCorpseRecoverable())\n\t\t\t\t\t{\n\t\t\t\t\t\t_base->getStorageItems()->addItem(ruleCorpse, _qtys[i]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t_game->popState();\n\n\tif (Options::storageLimitsEnforced && _base->storesOverfull())\n\t{\n\t\tif (_origin == OPT_BATTLESCAPE)\n\t\t{\n\t\t\t// not used anymore, because multiple prison types could spam this screen; it will pop up in Geoscape anyway\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_game->pushState(new SellState(_base, 0, _origin));\n\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_STORAGE_EXCEEDED\").arg(_base->getName()), _palette, _game->getMod()->getInterface(\"manageContainment\")->getElement(\"errorMessage\")->color, \"BACK13.SCR\", _game->getMod()->getInterface(\"manageContainment\")->getElement(\"errorPalette\")->color));\n\t\t}\n \t}\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid ManageAlienContainmentState::btnCancelClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n* Opens the Transfer UI and gives the player an option to transfer stuff instead of selling it.\n* Returns back to this screen when finished.\n* @param action Pointer to an action.\n*/\nvoid ManageAlienContainmentState::btnTransferClick(Action *)\n{\n\t_game->pushState(new TransferBaseState(_base, nullptr));\n}\n\n/**\n * Cancels all prisoner interrogations. Cancels all incoming prisoner transfers.\n * Allows the player to sell interrogated prisoners in case the prisons were destroyed (e.g. during a base defense).\n * Reloads the screen when finished.\n * @param action Pointer to an action.\n */\nvoid ManageAlienContainmentState::btnCleanupClick(Action *)\n{\n\t// cleanup\n\t_base->cleanupPrisons(_prisonType);\n\n\t// reset\n\tresetListAndTotals();\n}\n\n/**\n * Starts increasing the alien count.\n * @param action Pointer to an action.\n */\nvoid ManageAlienContainmentState::lstItemsRightArrowPress(Action *action)\n{\n\t_sel = _lstAliens->getSelectedRow();\n\tif (_game->isLeftClick(action, true) && !_timerInc->isRunning()) _timerInc->start();\n}\n\n/**\n * Stops increasing the alien count.\n * @param action Pointer to an action.\n */\nvoid ManageAlienContainmentState::lstItemsRightArrowRelease(Action *action)\n{\n\tif (_game->isLeftClick(action, true))\n\t{\n\t\t_timerInc->stop();\n\t}\n}\n\n/**\n * Increases the selected alien count;\n * by one on left-click, to max on right-click.\n * @param action Pointer to an action.\n */\nvoid ManageAlienContainmentState::lstItemsRightArrowClick(Action *action)\n{\n\tif (_game->isRightClick(action, true)) increaseByValue(INT_MAX);\n\tif (_game->isLeftClick(action, true))\n\t{\n\t\tincreaseByValue(_game->getScrollStep());\n\t\t_timerInc->setInterval(250);\n\t\t_timerDec->setInterval(250);\n\t}\n}\n\n/**\n * Starts decreasing the alien count.\n * @param action Pointer to an action.\n */\nvoid ManageAlienContainmentState::lstItemsLeftArrowPress(Action *action)\n{\n\t_sel = _lstAliens->getSelectedRow();\n\tif (_game->isLeftClick(action, true) && !_timerDec->isRunning()) _timerDec->start();\n}\n\n/**\n * Stops decreasing the alien count.\n * @param action Pointer to an action.\n */\nvoid ManageAlienContainmentState::lstItemsLeftArrowRelease(Action *action)\n{\n\tif (_game->isLeftClick(action, true))\n\t{\n\t\t_timerDec->stop();\n\t}\n}\n\n/**\n * Decreases the selected alien count;\n * by one on left-click, to 0 on right-click.\n * @param action Pointer to an action.\n */\nvoid ManageAlienContainmentState::lstItemsLeftArrowClick(Action *action)\n{\n\tif (_game->isRightClick(action, true)) decreaseByValue(INT_MAX);\n\tif (_game->isLeftClick(action, true))\n\t{\n\t\tdecreaseByValue(_game->getScrollStep());\n\t\t_timerInc->setInterval(250);\n\t\t_timerDec->setInterval(250);\n\t}\n}\n\n/**\n * Handles the mouse-wheels on the arrow-buttons.\n * @param action Pointer to an action.\n */\nvoid ManageAlienContainmentState::lstItemsMousePress(Action *action)\n{\n\t_sel = _lstAliens->getSelectedRow();\n\tif (action->getDetails()->button.button == SDL_BUTTON_WHEELUP)\n\t{\n\t\t_timerInc->stop();\n\t\t_timerDec->stop();\n\t\tif (action->getAbsoluteXMouse() >= _lstAliens->getArrowsLeftEdge() &&\n\t\t\taction->getAbsoluteXMouse() <= _lstAliens->getArrowsRightEdge())\n\t\t{\n\t\t\tincreaseByValue(Options::changeValueByMouseWheel);\n\t\t}\n\t}\n\telse if (action->getDetails()->button.button == SDL_BUTTON_WHEELDOWN)\n\t{\n\t\t_timerInc->stop();\n\t\t_timerDec->stop();\n\t\tif (action->getAbsoluteXMouse() >= _lstAliens->getArrowsLeftEdge() &&\n\t\t\taction->getAbsoluteXMouse() <= _lstAliens->getArrowsRightEdge())\n\t\t{\n\t\t\tdecreaseByValue(Options::changeValueByMouseWheel);\n\t\t}\n\t}\n\telse if (_game->isMiddleClick(action, true))\n\t{\n\t\tRuleResearch *selectedTopic = _game->getMod()->getResearch(_aliens[_sel]);\n\t\tif (selectedTopic != 0)\n\t\t{\n\t\t\t_doNotReset = true;\n\t\t\t_game->pushState(new TechTreeViewerState(selectedTopic, 0));\n\t\t}\n\t}\n}\n\n/**\n * Gets the quantity of the currently selected alien on the base.\n * @return Quantity of selected alien on the base.\n */\nint ManageAlienContainmentState::getQuantity()\n{\n\treturn _base->getStorageItems()->getItem(_aliens[_sel]);\n}\n\n/**\n * Increases the quantity of the selected alien to exterminate by one.\n */\nvoid ManageAlienContainmentState::increase()\n{\n\t_timerDec->setInterval(50);\n\t_timerInc->setInterval(50);\n\tincreaseByValue(_game->getScrollStep());\n}\n\n/**\n * Increases the quantity of the selected alien to exterminate by \"change\".\n * @param change How much we want to add.\n */\nvoid ManageAlienContainmentState::increaseByValue(int change)\n{\n\tint qty = getQuantity() - _qtys[_sel];\n\tif (change <= 0 || qty <= 0) return;\n\n\tchange = std::min(qty, change);\n\t_qtys[_sel] += change;\n\t_aliensSold += change;\n\tupdateStrings();\n}\n\n/**\n * Decreases the quantity of the selected alien to exterminate by one.\n */\nvoid ManageAlienContainmentState::decrease()\n{\n\t_timerInc->setInterval(50);\n\t_timerDec->setInterval(50);\n\tdecreaseByValue(_game->getScrollStep());\n}\n\n/**\n * Decreases the quantity of the selected alien to exterminate by \"change\".\n * @param change How much we want to remove.\n */\nvoid ManageAlienContainmentState::decreaseByValue(int change)\n{\n\tif (change <= 0 || _qtys[_sel] <= 0) return;\n\tchange = std::min(_qtys[_sel], change);\n\t_qtys[_sel] -= change;\n\t_aliensSold -= change;\n\tupdateStrings();\n}\n\n/**\n * Updates the quantity-strings of the selected alien.\n */\nvoid ManageAlienContainmentState::updateStrings()\n{\n\tstd::ostringstream ss, ss2;\n\tint qty = getQuantity() - _qtys[_sel];\n\tss << qty;\n\tss2 << _qtys[_sel];\n\n\t_lstAliens->setRowColor(_sel, (qty == 0)? _lstAliens->getSecondaryColor() : _lstAliens->getColor());\n\t_lstAliens->setCellText(_sel, 2, ss.str());\n\t_lstAliens->setCellText(_sel, 3, ss2.str());\n\n\tint aliens = _base->getUsedContainment(_prisonType) - _aliensSold;\n\tint availableContainment = _base->getAvailableContainment(_prisonType);\n\tint spaces = availableContainment - aliens;\n\tif (availableContainment == 0 || Options::storageLimitsEnforced)\n\t{\n\t\t_btnOk->setVisible(spaces >= 0);\n\t\t_btnSell->setVisible(spaces >= 0 && _threeButtons);\n\t}\n\t_txtAvailable->setText(tr(\"STR_SPACE_AVAILABLE\").arg(spaces));\n\t_txtUsed->setText(tr(\"STR_SPACE_USED\").arg(aliens));\n\n\tif (Options::canSellLiveAliens)\n\t{\n\t\t// we could probably keep track of _total with each change (only adding deltas), but I am lazy today\n\t\t_total = 0;\n\t\tfor (size_t i = 0; i < _qtys.size(); ++i)\n\t\t{\n\t\t\tif (_qtys[i] > 0)\n\t\t\t{\n\t\t\t\tint64_t adjustedCost = _game->getMod()->getItem(_aliens[i])->getSellCostAdjusted(_base, _game->getSavedGame());\n\t\t\t\tadjustedCost *= _qtys[i];\n\t\t\t\t_total += adjustedCost;\n\t\t\t}\n\t\t}\n\t\t_txtValueOfSales->setText(tr(\"STR_VALUE_OF_SALES\").arg(Unicode::formatFunding(_total)));\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/ManageAlienContainmentState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/TouchState.h\"\n#include \"../Menu/OptionsBaseState.h\"\n#include <vector>\n#include <string>\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass TextList;\nclass Timer;\nclass Base;\n\n/**\n * ManageAlienContainment screen that lets the player manage\n * alien numbers in a particular base.\n */\nclass ManageAlienContainmentState : public TouchState\n{\nprivate:\n\tBase *_base;\n\tint _prisonType;\n\tOptionsOrigin _origin;\n\tTextButton *_btnOk, *_btnSell, *_btnCancel, *_btnTransfer, *_btnCleanup;\n\tWindow *_window;\n\tText *_txtTitle, *_txtUsed, *_txtAvailable, *_txtValueOfSales, *_txtItem, *_txtLiveAliens, *_txtDeadAliens, *_txtInterrogatedAliens;\n\tTextList *_lstAliens;\n\tTimer *_timerInc, *_timerDec;\n\tstd::vector<int> _qtys;\n\tstd::vector<std::string> _aliens;\n\tsize_t _sel;\n\tint _aliensSold;\n\tint64_t _total;\n\tbool _doNotReset, _threeButtons;\n\n\t/// Gets selected quantity.\n\tint getQuantity();\n\t/// Deals with the selected aliens.\n\tvoid dealWithSelectedAliens(bool sell);\npublic:\n\t/// Creates the ManageAlienContainment state.\n\tManageAlienContainmentState(Base *base, int prisonType, OptionsOrigin origin);\n\t/// Cleans up the ManageAlienContainment state.\n\t~ManageAlienContainmentState();\n\t/// Resets state.\n\tvoid init() override;\n\t/// Resets the list and the totals, updates button visibility.\n\tvoid resetListAndTotals();\n\t/// Runs the timers.\n\tvoid think() override;\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for opening the Global Alien Containment UI.\n\tvoid onGlobalAlienContainmentClick(Action *action);\n\t/// Handler for clicking the Sell button.\n\tvoid btnSellClick(Action *action);\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action *action);\n\t/// Handler for clicking the Transfer button.\n\tvoid btnTransferClick(Action *action);\n\t/// Handler for clicking the Cleanup button.\n\tvoid btnCleanupClick(Action *action);\n\t/// Handler for pressing an Increase arrow in the list.\n\tvoid lstItemsLeftArrowPress(Action *action);\n\t/// Handler for releasing an Increase arrow in the list.\n\tvoid lstItemsLeftArrowRelease(Action *action);\n\t/// Handler for clicking an Increase arrow in the list.\n\tvoid lstItemsLeftArrowClick(Action *action);\n\t/// Handler for pressing a Decrease arrow in the list.\n\tvoid lstItemsRightArrowPress(Action *action);\n\t/// Handler for releasing a Decrease arrow in the list.\n\tvoid lstItemsRightArrowRelease(Action *action);\n\t/// Handler for clicking a Decrease arrow in the list.\n\tvoid lstItemsRightArrowClick(Action *action);\n\t/// Handler for pressing-down a mouse-button in the list.\n\tvoid lstItemsMousePress(Action *action);\n\t/// Increases the quantity of an alien by one.\n\tvoid increase();\n\t/// Increases the quantity of an alien by the given value.\n\tvoid increaseByValue(int change);\n\t/// Decreases the quantity of an alien by one.\n\tvoid decrease();\n\t/// Decreases the quantity of an alien by the given value.\n\tvoid decreaseByValue(int change);\n\t/// Updates the quantity-strings of the selected alien.\n\tvoid updateStrings();\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/ManufactureDependenciesTreeState.cpp",
    "content": "/*\n * Copyright 2010-2015 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ManufactureDependenciesTreeState.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleBaseFacility.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"../Mod/RuleManufacture.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Savegame/SavedGame.h\"\n#include <unordered_map>\n#include <unordered_set>\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements on the UI.\n */\nManufactureDependenciesTreeState::ManufactureDependenciesTreeState(const std::string &selectedItem) : _selectedItem(selectedItem), _showAll(false)\n{\n\t_screen = false;\n\n\t_window = new Window(this, 222, 144, 49, 32);\n\t_txtTitle = new Text(182, 9, 53, 42);\n\t_lstTopics = new TextList(198, 96, 53, 54);\n\t_btnShowAll = new TextButton(100, 16, 57, 153);\n\t_btnOk = new TextButton(100, 16, 163, 153);\n\n\t// Set palette\n\tsetInterface(\"dependencyTree\");\n\n\tadd(_window, \"window\", \"dependencyTree\");\n\tadd(_txtTitle, \"text\", \"dependencyTree\");\n\tadd(_btnShowAll, \"button\", \"dependencyTree\");\n\tadd(_btnOk, \"button\", \"dependencyTree\");\n\tadd(_lstTopics, \"list\", \"dependencyTree\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"dependencyTree\");\n\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_TOPIC\").arg(tr(_selectedItem)));\n\n\t_btnShowAll->setText(tr(\"STR_SHOW_ALL\"));\n\t_btnShowAll->onMouseClick((ActionHandler)&ManufactureDependenciesTreeState::btnShowAllClick);\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&ManufactureDependenciesTreeState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&ManufactureDependenciesTreeState::btnOkClick, Options::keyCancel);\n\n\t_lstTopics->setColumns(1, 182);\n\t_lstTopics->setBackground(_window);\n\t_lstTopics->setMargin(0);\n\t_lstTopics->setAlign(ALIGN_CENTER);\n\n\tif (Options::oxceDisableProductionDependencyTree)\n\t{\n\t\t_txtTitle->setHeight(_txtTitle->getHeight() * 11);\n\t\t_txtTitle->setWordWrap(true);\n\t\t_txtTitle->setText(tr(\"STR_THIS_FEATURE_IS_DISABLED_3\"));\n\t\t_btnShowAll->setVisible(false);\n\t\t_lstTopics->setVisible(false);\n\t\treturn;\n\t}\n}\n\nManufactureDependenciesTreeState::~ManufactureDependenciesTreeState()\n{\n}\n\n/**\n* Initializes the screen (fills the list).\n*/\nvoid ManufactureDependenciesTreeState::init()\n{\n\tState::init();\n\n\tif (!Options::oxceDisableProductionDependencyTree)\n\t{\n\t\tinitList();\n\t}\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid ManufactureDependenciesTreeState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n* Shows spoilers.\n* @param action Pointer to an action.\n*/\nvoid ManufactureDependenciesTreeState::btnShowAllClick(Action *)\n{\n\t_showAll = true;\n\t_btnOk->setWidth(_btnOk->getX() - _btnShowAll->getX() + _btnOk->getWidth());\n\t_btnOk->setX(_btnShowAll->getX());\n\t_btnShowAll->setVisible(false);\n\tinitList();\n}\n\n/**\n* Shows the tree.\n*/\nvoid ManufactureDependenciesTreeState::initList()\n{\n\t_lstTopics->clearList();\n\n\t// dependency map (item -> vector of items that needs this item)\n\tstd::unordered_map< std::string, std::vector<std::string> > deps;\n\n\tfor (auto& manufName : _game->getMod()->getManufactureList())\n\t{\n\t\tRuleManufacture *rule = _game->getMod()->getManufacture(manufName);\n\t\tfor (auto& pair : rule->getRequiredItems())\n\t\t{\n\t\t\tdeps[pair.first->getType()].push_back(manufName);\n\t\t}\n\t}\n\n\t// breadth-first tree search\n\tint row = 0;\n\tconst std::vector<std::string> firstLevel = deps[_selectedItem];\n\tstd::vector<std::string> secondLevel;\n\tstd::vector<std::string> thirdLevel;\n\tstd::vector<std::string> fourthLevel;\n\tstd::vector<std::string> fifthLevel;\n\n\tstd::unordered_set<std::string> alreadyVisited;\n\talreadyVisited.insert(_selectedItem);\n\tfor (const auto& name : firstLevel)\n\t{\n\t\talreadyVisited.insert(name);\n\t}\n\n\tstd::vector<const RuleBaseFacility*> facilitiesLevel;\n\tfor (auto& facilityType : _game->getMod()->getBaseFacilitiesList())\n\t{\n\t\tRuleBaseFacility* facilityRule = _game->getMod()->getBaseFacility(facilityType);\n\t\tfor (auto& itemRequired : facilityRule->getBuildCostItems())\n\t\t{\n\t\t\tif (itemRequired.first == _selectedItem)\n\t\t\t{\n\t\t\t\tfacilitiesLevel.push_back(facilityRule);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (firstLevel.empty() && facilitiesLevel.empty())\n\t{\n\t\t_lstTopics->addRow(1, tr(\"STR_NO_DEPENDENCIES\").c_str());\n\t\t_lstTopics->setRowColor(row, _lstTopics->getSecondaryColor());\n\t\t++row;\n\t\treturn;\n\t}\n\n\t// first level\n\t_lstTopics->addRow(1, tr(\"STR_DIRECT_DEPENDENCIES\").c_str());\n\t_lstTopics->setRowColor(row, _lstTopics->getSecondaryColor());\n\t++row;\n\n\t// first list all the dependent base facilities\n\tfor (auto* fac : facilitiesLevel)\n\t{\n\t\tif (_showAll || _game->getSavedGame()->isResearched(fac->getRequirements()))\n\t\t{\n\t\t\t_lstTopics->addRow(1, tr(fac->getType()).c_str());\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_lstTopics->addRow(1, \"***\");\n\t\t}\n\t\t++row;\n\t}\n\n\tfor (const auto& name : firstLevel)\n\t{\n\t\tif (_showAll || _game->getSavedGame()->isResearched(_game->getMod()->getManufacture(name)->getRequirements()))\n\t\t{\n\t\t\t_lstTopics->addRow(1, tr(name).c_str());\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_lstTopics->addRow(1, \"***\");\n\t\t}\n\t\t++row;\n\n\t\tfor (const auto& goDeeper : deps[name])\n\t\t{\n\t\t\tif (alreadyVisited.find(goDeeper) == alreadyVisited.end())\n\t\t\t{\n\t\t\t\tsecondLevel.push_back(goDeeper);\n\t\t\t\talreadyVisited.insert(goDeeper);\n\t\t\t}\n\t\t}\n\t}\n\n\t_lstTopics->addRow(1, \"\");\n\t++row;\n\tif (secondLevel.empty())\n\t{\n\t\t_lstTopics->addRow(1, tr(\"STR_END_OF_SEARCH\").c_str());\n\t\t_lstTopics->setRowColor(row, _lstTopics->getSecondaryColor());\n\t\t++row;\n\t\treturn;\n\t}\n\n\t// second level\n\t_lstTopics->addRow(1, tr(\"STR_LEVEL_2_DEPENDENCIES\").c_str());\n\t_lstTopics->setRowColor(row, _lstTopics->getSecondaryColor());\n\t++row;\n\n\tfor (const auto& name : secondLevel)\n\t{\n\t\tif (_showAll || _game->getSavedGame()->isResearched(_game->getMod()->getManufacture(name)->getRequirements()))\n\t\t{\n\t\t\t_lstTopics->addRow(1, tr(name).c_str());\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_lstTopics->addRow(1, \"***\");\n\t\t}\n\t\t++row;\n\n\t\tfor (const auto& goDeeper : deps[name])\n\t\t{\n\t\t\tif (alreadyVisited.find(goDeeper) == alreadyVisited.end())\n\t\t\t{\n\t\t\t\tthirdLevel.push_back(goDeeper);\n\t\t\t\talreadyVisited.insert(goDeeper);\n\t\t\t}\n\t\t}\n\t}\n\n\t_lstTopics->addRow(1, \"\");\n\t++row;\n\tif (thirdLevel.empty())\n\t{\n\t\t_lstTopics->addRow(1, tr(\"STR_END_OF_SEARCH\").c_str());\n\t\t_lstTopics->setRowColor(row, _lstTopics->getSecondaryColor());\n\t\t++row;\n\t\treturn;\n\t}\n\n\t// third level\n\t_lstTopics->addRow(1, tr(\"STR_LEVEL_3_DEPENDENCIES\").c_str());\n\t_lstTopics->setRowColor(row, _lstTopics->getSecondaryColor());\n\t++row;\n\n\tfor (const auto& name : thirdLevel)\n\t{\n\t\tif (_showAll || _game->getSavedGame()->isResearched(_game->getMod()->getManufacture(name)->getRequirements()))\n\t\t{\n\t\t\t_lstTopics->addRow(1, tr(name).c_str());\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_lstTopics->addRow(1, \"***\");\n\t\t}\n\t\t++row;\n\n\t\tfor (const auto& goDeeper : deps[name])\n\t\t{\n\t\t\tif (alreadyVisited.find(goDeeper) == alreadyVisited.end())\n\t\t\t{\n\t\t\t\tfourthLevel.push_back(goDeeper);\n\t\t\t\talreadyVisited.insert(goDeeper);\n\t\t\t}\n\t\t}\n\t}\n\n\t_lstTopics->addRow(1, \"\");\n\t++row;\n\tif (fourthLevel.empty())\n\t{\n\t\t_lstTopics->addRow(1, tr(\"STR_END_OF_SEARCH\").c_str());\n\t\t_lstTopics->setRowColor(row, _lstTopics->getSecondaryColor());\n\t\t++row;\n\t\treturn;\n\t}\n\n\t// fourth level\n\t_lstTopics->addRow(1, tr(\"STR_LEVEL_4_DEPENDENCIES\").c_str());\n\t_lstTopics->setRowColor(row, _lstTopics->getSecondaryColor());\n\t++row;\n\n\tfor (const auto& name : fourthLevel)\n\t{\n\t\tif (_showAll || _game->getSavedGame()->isResearched(_game->getMod()->getManufacture(name)->getRequirements()))\n\t\t{\n\t\t\t_lstTopics->addRow(1, tr(name).c_str());\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_lstTopics->addRow(1, \"***\");\n\t\t}\n\t\t++row;\n\n\t\tfor (const auto& goDeeper : deps[name])\n\t\t{\n\t\t\tif (alreadyVisited.find(goDeeper) == alreadyVisited.end())\n\t\t\t{\n\t\t\t\tfifthLevel.push_back(goDeeper);\n\t\t\t\talreadyVisited.insert(goDeeper);\n\t\t\t}\n\t\t}\n\t}\n\n\t_lstTopics->addRow(1, \"\");\n\t++row;\n\tif (fifthLevel.empty())\n\t{\n\t\t_lstTopics->addRow(1, tr(\"STR_END_OF_SEARCH\").c_str());\n\t\t_lstTopics->setRowColor(row, _lstTopics->getSecondaryColor());\n\t\t++row;\n\t\treturn;\n\t}\n\n\t_lstTopics->addRow(1, tr(\"STR_MORE_DEPENDENCIES\").c_str());\n\t_lstTopics->setRowColor(row, _lstTopics->getSecondaryColor());\n\t++row;\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/ManufactureDependenciesTreeState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2015 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass Window;\nclass Text;\nclass TextButton;\nclass TextList;\n\n/**\n * Window which displays manufacture dependencies tree.\n */\nclass ManufactureDependenciesTreeState : public State\n{\nprivate:\n\tWindow *_window;\n\tText *_txtTitle;\n\tTextList *_lstTopics;\n\tTextButton *_btnOk, *_btnShowAll;\n\tstd::string _selectedItem;\n\tbool _showAll;\n\tvoid initList();\npublic:\n\t/// Creates the ManufactureDependenciesTree state.\n\tManufactureDependenciesTreeState(const std::string &selectedItem);\n\t/// Cleans up the ManufactureDependenciesTree state\n\t~ManufactureDependenciesTreeState();\n\t/// Initializes the state.\n\tvoid init() override;\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the [Show All] button.\n\tvoid btnShowAllClick(Action *action);\n};\n}\n"
  },
  {
    "path": "src/Basescape/ManufactureInfoState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ManufactureInfoState.h\"\n#include <algorithm>\n#include \"../Interface/Window.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/ToggleTextButton.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/ArrowButton.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleCraft.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"../Mod/RuleManufacture.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/Production.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/ItemContainer.h\"\n#include \"../Engine/Timer.h\"\n#include \"../Menu/ErrorMessageState.h\"\n#include \"../Mod/RuleInterface.h\"\n#include <climits>\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all elements in the Production settings screen (new Production).\n * @param game Pointer to the core game.\n * @param base Pointer to the base to get info from.\n * @param item The RuleManufacture to produce.\n */\nManufactureInfoState::ManufactureInfoState (Base *base, RuleManufacture *item) : _base(base), _item(item), _production(0)\n{\n\tbuildUi();\n}\n\n/**\n * Initializes all elements in the Production settings screen (modifying Production).\n * @param game Pointer to the core game.\n * @param base Pointer to the base to get info from.\n * @param production The Production to modify.\n */\nManufactureInfoState::ManufactureInfoState (Base *base, Production *production) : _base(base), _item(0), _production(production)\n{\n\tbuildUi();\n}\n\n/**\n * Builds screen User Interface.\n */\nvoid ManufactureInfoState::buildUi()\n{\n\t_screen = false;\n\n\t_window = new Window(this, 320, 160, 0, 20, POPUP_BOTH);\n\t_txtTitle = new Text(320, 17, 0, 30);\n\t_btnOk = new TextButton(136, 16, 168, 155);\n\t_btnStop = new TextButton(136, 16, 16, 155);\n\t_btnSell = new ToggleTextButton(60, 16, 244, 61);\n\t_btnFallback = new ToggleTextButton(72, 16, 168, 61);\n\t_txtAvailableEngineer = new Text(160, 9, 16, 50);\n\t_txtAvailableSpace = new Text(160, 9, 16, 60);\n\t_txtHoursPerUnit = new Text(150, 9, 16, 70);\n\t_txtMonthlyProfit = new Text(160, 9, 168, 50);\n\t_txtAllocatedEngineer = new Text(112, 32, 16, 80);\n\t_txtUnitToProduce = new Text(112, 48, 168, 64);\n\t_txtEngineerUp = new Text(90, 9, 40, 118);\n\t_txtEngineerDown = new Text(90, 9, 40, 138);\n\t_txtUnitUp = new Text(90, 9, 192, 118);\n\t_txtUnitDown = new Text(90, 9, 192, 138);\n\t_btnEngineerUp = new ArrowButton(ARROW_BIG_UP, 13, 14, 132, 114);\n\t_btnEngineerDown = new ArrowButton(ARROW_BIG_DOWN, 13, 14, 132, 136);\n\t_btnUnitInfinity = new ArrowButton(ARROW_BIG_UP, 13, 14, 300, 114);\n\t_btnUnitMinimum = new ArrowButton(ARROW_BIG_DOWN, 13, 14, 300, 136);\n\t_btnUnitUp = new ArrowButton(ARROW_BIG_UP, 13, 14, 284, 114);\n\t_btnUnitDown = new ArrowButton(ARROW_BIG_DOWN, 13, 14, 284, 136);\n\t_txtAllocated = new Text(40, 16, 128, 88);\n\t_txtTodo = new Text(40, 16, 280, 88);\n\n\t_surfaceEngineers = new InteractiveSurface(160, 150, 0, 25);\n\t_surfaceEngineers->onMouseClick((ActionHandler)&ManufactureInfoState::handleWheelEngineer, 0);\n\n\t_surfaceUnits = new InteractiveSurface(160, 150, 160, 25);\n\t_surfaceUnits->onMouseClick((ActionHandler)&ManufactureInfoState::handleWheelUnit, 0);\n\n\t// Set palette\n\tsetInterface(\"manufactureInfo\");\n\n\tadd(_surfaceEngineers);\n\tadd(_surfaceUnits);\n\tadd(_window, \"window\", \"manufactureInfo\");\n\tadd(_txtTitle, \"text\", \"manufactureInfo\");\n\tadd(_txtAvailableEngineer, \"text\", \"manufactureInfo\");\n\tadd(_txtAvailableSpace, \"text\", \"manufactureInfo\");\n\tadd(_txtHoursPerUnit, \"text\", \"manufactureInfo\");\n\tadd(_txtMonthlyProfit, \"text\", \"manufactureInfo\");\n\tadd(_txtAllocatedEngineer, \"text\", \"manufactureInfo\");\n\tadd(_txtAllocated, \"text\", \"manufactureInfo\");\n\tadd(_txtUnitToProduce, \"text\", \"manufactureInfo\");\n\tadd(_txtTodo, \"text\", \"manufactureInfo\");\n\tadd(_txtEngineerUp, \"text\", \"manufactureInfo\");\n\tadd(_txtEngineerDown, \"text\", \"manufactureInfo\");\n\tadd(_btnEngineerUp, \"button1\", \"manufactureInfo\");\n\tadd(_btnEngineerDown, \"button1\", \"manufactureInfo\");\n\tadd(_txtUnitUp, \"text\", \"manufactureInfo\");\n\tadd(_txtUnitDown, \"text\", \"manufactureInfo\");\n\tadd(_btnUnitInfinity, \"button1\", \"manufactureInfo\");\n\tadd(_btnUnitMinimum, \"button1\", \"manufactureInfo\");\n\tadd(_btnUnitUp, \"button1\", \"manufactureInfo\");\n\tadd(_btnUnitDown, \"button1\", \"manufactureInfo\");\n\tadd(_btnOk, \"button2\", \"manufactureInfo\");\n\tadd(_btnStop, \"button2\", \"manufactureInfo\");\n\tadd(_btnSell, \"button1\", \"manufactureInfo\");\n\tadd(_btnFallback, \"button1\", \"manufactureInfo\");\n\n\tcenterAllSurfaces();\n\n\tsetWindowBackground(_window, \"manufactureInfo\");\n\n\t_txtTitle->setText(tr(_item ? _item->getName() : _production->getRules()->getName()));\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\n\t_txtAllocatedEngineer->setText(tr(\"STR_ENGINEERS__ALLOCATED\"));\n\t_txtAllocatedEngineer->setBig();\n\t_txtAllocatedEngineer->setWordWrap(true);\n\t_txtAllocatedEngineer->setVerticalAlign(ALIGN_BOTTOM);\n\n\t_txtAllocated->setBig();\n\n\t_txtTodo->setBig();\n\n\t_txtUnitToProduce->setText(tr(\"STR_UNITS_TO_PRODUCE\"));\n\t_txtUnitToProduce->setBig();\n\t_txtUnitToProduce->setWordWrap(true);\n\t_txtUnitToProduce->setVerticalAlign(ALIGN_BOTTOM);\n\n\t_txtEngineerUp->setText(tr(\"STR_INCREASE_UC\"));\n\n\t_txtEngineerDown->setText(tr(\"STR_DECREASE_UC\"));\n\n\t_btnEngineerUp->onMousePress((ActionHandler)&ManufactureInfoState::moreEngineerPress);\n\t_btnEngineerUp->onMouseRelease((ActionHandler)&ManufactureInfoState::moreEngineerRelease);\n\t_btnEngineerUp->onMouseClick((ActionHandler)&ManufactureInfoState::moreEngineerClick, 0);\n\n\t_btnEngineerDown->onMousePress((ActionHandler)&ManufactureInfoState::lessEngineerPress);\n\t_btnEngineerDown->onMouseRelease((ActionHandler)&ManufactureInfoState::lessEngineerRelease);\n\t_btnEngineerDown->onMouseClick((ActionHandler)&ManufactureInfoState::lessEngineerClick, 0);\n\n\t_btnUnitUp->onMousePress((ActionHandler)&ManufactureInfoState::moreUnitPress);\n\t_btnUnitUp->onMouseRelease((ActionHandler)&ManufactureInfoState::moreUnitRelease);\n\t_btnUnitUp->onMouseClick((ActionHandler)&ManufactureInfoState::moreUnitClick, 0);\n\n\t_btnUnitDown->onMousePress((ActionHandler)&ManufactureInfoState::lessUnitPress);\n\t_btnUnitDown->onMouseRelease((ActionHandler)&ManufactureInfoState::lessUnitRelease);\n\t_btnUnitDown->onMouseClick((ActionHandler)&ManufactureInfoState::lessUnitClick, 0);\n\n\t_txtUnitUp->setText(tr(\"STR_INCREASE_UC\"));\n\n\t_txtUnitDown->setText(tr(\"STR_DECREASE_UC\"));\n\n\t_btnSell->setText(tr(\"STR_SELL_PRODUCTION\"));\n\t_btnSell->onMouseClick((ActionHandler)&ManufactureInfoState::btnSellClick, 0);\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&ManufactureInfoState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&ManufactureInfoState::btnOkClick, Options::keyOk);\n\t_btnOk->onKeyboardPress((ActionHandler)&ManufactureInfoState::btnOkClick, Options::keyCancel);\n\n\tif (!_item && _production)\n\t{\n\t\tif (_production->getRules()->getRefund())\n\t\t{\n\t\t\t_btnStop->setText(tr(\"STR_REFUND_PRODUCTION\"));\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_btnStop->setText(tr(\"STR_STOP_PRODUCTION\"));\n\t\t}\n\t}\n\telse\n\t{\n\t\t_btnStop->setText(tr(\"STR_CANCEL_UC\"));\n\t}\n\t_btnStop->onMouseClick((ActionHandler)&ManufactureInfoState::btnStopClick);\n\tif (!_production)\n\t{\n\t\t_production = new Production (_item, 1);\n\t\t_base->addProduction(_production);\n\t}\n\t_btnSell->setPressed(_production->getSellItems());\n\t_btnSell->setVisible(_production->getRules()->canAutoSell());\n\tinitProfitInfo();\n\tsetAssignedEngineer();\n\n\t_btnFallback->setText(tr(\"STR_FALLBACK_PRODUCTION\"));\n\t_btnFallback->setPressed(_production->isFallback());\n\t_btnFallback->setVisible(Options::oxceBaseManufactureFallbackButton);\n\n\tif (Options::oxceBaseManufactureInfinityButton)\n\t{\n\t\tif (_production->getRules()->getProducedCraft())\n\t\t{\n\t\t\t_btnUnitInfinity->setVisible(false);\n\t\t\t_btnUnitMinimum->setVisible(false);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_btnUnitInfinity->onMouseClick((ActionHandler)&ManufactureInfoState::infinityUnitClick, 0);\n\t\t\t_btnUnitMinimum->onMouseClick((ActionHandler)&ManufactureInfoState::minimumUnitClick, 0);\n\t\t}\n\t}\n\telse\n\t{\n\t\t_btnUnitInfinity->setVisible(false);\n\t\t_btnUnitMinimum->setVisible(false);\n\t}\n\n\t_txtHoursPerUnit->setText(tr(\"STR_HOURS_PER_UNIT\").arg(_production->getRules()->getManufactureTime()));\n\n\t_timerMoreEngineer = new Timer(250);\n\t_timerLessEngineer = new Timer(250);\n\t_timerMoreUnit = new Timer(250);\n\t_timerLessUnit = new Timer(250);\n\t_timerMoreEngineer->onTimer((StateHandler)&ManufactureInfoState::onMoreEngineer);\n\t_timerLessEngineer->onTimer((StateHandler)&ManufactureInfoState::onLessEngineer);\n\t_timerMoreUnit->onTimer((StateHandler)&ManufactureInfoState::onMoreUnit);\n\t_timerLessUnit->onTimer((StateHandler)&ManufactureInfoState::onLessUnit);\n}\n\nvoid ManufactureInfoState::initProfitInfo ()\n{\n\tconst RuleManufacture *manuf = _production->getRules();\n\n\t_producedItemsValue = 0;\n\tauto* ruleCraft = manuf->getProducedCraft();\n\tif (ruleCraft)\n\t{\n\t\t_producedItemsValue += ruleCraft->getSellCost();\n\t}\n\telse\n\t{\n\t\tfor (auto& pair : manuf->getProducedItems())\n\t\t{\n\t\t\tint64_t adjustedSellValue = pair.first->getSellCostAdjusted(_base, _game->getSavedGame());\n\t\t\tadjustedSellValue *= pair.second;\n\t\t\t_producedItemsValue += adjustedSellValue;\n\t\t}\n\t}\n}\n\n// note that this function calculates only the change in funds, not the change\n// in net worth.  after discussion in the forums, it was decided that focusing\n// only on visible changes in funds was clearer and more valuable to the player\n// than trying to take used materials and maintenance costs into account.\nint ManufactureInfoState::getMonthlyNetFunds () const\n{\n\t// does not take into account leap years, but a game is unlikely to take long enough for that to matter\n\tstatic const int AVG_HOURS_PER_MONTH = (365 * 24) / 12;\n\n\tconst RuleManufacture *item = _production->getRules();\n\tint saleValue = _btnSell->getPressed() ? _producedItemsValue : 0;\n\n\tint numEngineers = _production->getAssignedEngineers();\n\tint manHoursPerMonth = AVG_HOURS_PER_MONTH * numEngineers;\n\tif (!_production->getInfiniteAmount())\n\t{\n\t\t// scale down to actual number of man hours required if the job will\n\t\t// take less than one month\n\t\tint manHoursRemaining = item->getManufactureTime() * (_production->getAmountTotal() - _production->getAmountProduced());\n\t\tmanHoursPerMonth = std::min(manHoursPerMonth, manHoursRemaining);\n\t}\n\tfloat itemsPerMonth = (float)manHoursPerMonth / (float)item->getManufactureTime();\n\n\treturn (saleValue - item->getManufactureCost()) * itemsPerMonth;\n}\n\n/**\n * Frees up memory that's not automatically cleaned on exit\n */\nManufactureInfoState::~ManufactureInfoState()\n{\n\tdelete _timerMoreEngineer;\n\tdelete _timerLessEngineer;\n\tdelete _timerMoreUnit;\n\tdelete _timerLessUnit;\n}\n\n/**\n * Refreshes profit values.\n * @param action A pointer to an Action.\n */\nvoid ManufactureInfoState::btnSellClick(Action *)\n{\n\tsetAssignedEngineer();\n}\n\n/**\n * Stops this Production. Returns to the previous screen.\n * @param action A pointer to an Action.\n */\nvoid ManufactureInfoState::btnStopClick(Action *)\n{\n\tif (!_item && _production && _production->getRules()->getRefund())\n\t{\n\t\t_production->refundItem(_base, _game->getSavedGame(), _game->getMod());\n\t}\n\t_base->removeProduction(_production);\n\texitState();\n}\n\n/**\n * Starts this Production (if new). Returns to the previous screen.\n * @param action A pointer to an Action.\n */\nvoid ManufactureInfoState::btnOkClick(Action *)\n{\n\tif (_item)\n\t{\n\t\t_production->startItem(_base, _game->getSavedGame(), _game->getMod());\n\t}\n\t_production->setSellItems(_btnSell->getPressed());\n\tif (_btnFallback->getPressed())\n\t{\n\t\tfor (auto* p : _base->getProductions())\n\t\t{\n\t\t\tp->setFallback(false);\n\t\t}\n\t\t_production->setFallback(true);\n\t}\n\texitState();\n}\n\n/**\n * Returns to the previous screen.\n */\nvoid ManufactureInfoState::exitState()\n{\n\t_game->popState();\n\tif (_item)\n\t{\n\t\t_game->popState();\n\t}\n}\n\n/**\n * Updates display of assigned/available engineer/workshop space.\n */\nvoid ManufactureInfoState::setAssignedEngineer()\n{\n\t_txtAvailableEngineer->setText(tr(\"STR_ENGINEERS_AVAILABLE_UC\").arg(_base->getAvailableEngineers()));\n\t_txtAvailableSpace->setText(tr(\"STR_WORKSHOP_SPACE_AVAILABLE_UC\").arg(_base->getFreeWorkshops()));\n\tstd::ostringstream s3;\n\ts3 << \">\" << Unicode::TOK_COLOR_FLIP << _production->getAssignedEngineers();\n\t_txtAllocated->setText(s3.str());\n\tstd::ostringstream s4;\n\ts4 << \">\" << Unicode::TOK_COLOR_FLIP;\n\tif (_production->getInfiniteAmount()) s4 << \"∞\";\n\telse s4 << _production->getAmountTotal();\n\t_txtTodo->setText(s4.str());\n\t_txtMonthlyProfit->setText(tr(\"STR_MONTHLY_PROFIT\").arg(Unicode::formatFunding(getMonthlyNetFunds()).c_str()));\n}\n\n/**\n * Adds given number of engineers to the project if possible.\n * @param change How much we want to add.\n */\nvoid ManufactureInfoState::moreEngineer(int change)\n{\n\tif (change <= 0) return;\n\tint availableEngineer = _base->getAvailableEngineers();\n\tint availableWorkSpace = _base->getFreeWorkshops();\n\tif (_production->isQueuedOnly())\n\t{\n\t\t// start counting the workshop space now\n\t\tavailableWorkSpace -= _production->getRules()->getRequiredSpace();\n\t}\n\tif (availableEngineer > 0 && availableWorkSpace > 0)\n\t{\n\t\tchange = std::min(std::min(availableEngineer, availableWorkSpace), change);\n\t\t_production->setAssignedEngineers(_production->getAssignedEngineers()+change);\n\t\t_base->setEngineers(_base->getEngineers()-change);\n\t\tsetAssignedEngineer();\n\t}\n\telse if (availableWorkSpace <= 0 && availableEngineer > 0 && _production->isQueuedOnly() && _production->getRules()->getRequiredSpace() > 0)\n\t{\n\t\t_timerMoreEngineer->stop();\n\t\t_game->pushState(new ErrorMessageState(\n\t\t\ttr(\"STR_NOT_ENOUGH_WORK_SPACE\"),\n\t\t\t_palette,\n\t\t\t_game->getMod()->getInterface(\"basescape\")->getElement(\"errorMessage\")->color,\n\t\t\t\"BACK17.SCR\",\n\t\t\t_game->getMod()->getInterface(\"basescape\")->getElement(\"errorPalette\")->color)\n\t\t);\n\t}\n}\n\n/**\n * Starts the timerMoreEngineer.\n * @param action A pointer to an Action.\n */\nvoid ManufactureInfoState::moreEngineerPress(Action *action)\n{\n\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT) _timerMoreEngineer->start();\n}\n\n/**\n * Stops the timerMoreEngineer.\n * @param action A pointer to an Action.\n */\nvoid ManufactureInfoState::moreEngineerRelease(Action *action)\n{\n\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT)\n\t{\n\t\t_timerMoreEngineer->setInterval(250);\n\t\t_timerMoreEngineer->stop();\n\t}\n}\n\n/**\n * Allocates all engineers.\n * @param action A pointer to an Action.\n */\nvoid ManufactureInfoState::moreEngineerClick(Action *action)\n{\n\tif (action->getDetails()->button.button == SDL_BUTTON_RIGHT) moreEngineer(INT_MAX);\n\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT) moreEngineer(1);\n}\n\n/**\n * Removes the given number of engineers from the project if possible.\n * @param change How much we want to subtract.\n */\nvoid ManufactureInfoState::lessEngineer(int change)\n{\n\tif (change <= 0) return;\n\tint assigned = _production->getAssignedEngineers();\n\tif (assigned > 0)\n\t{\n\t\tchange = std::min(assigned, change);\n\t\t_production->setAssignedEngineers(assigned-change);\n\t\t_base->setEngineers(_base->getEngineers()+change);\n\t\tsetAssignedEngineer();\n\t}\n}\n\n/**\n * Starts the timerLessEngineer.\n * @param action A pointer to an Action.\n */\nvoid ManufactureInfoState::lessEngineerPress(Action *action)\n{\n\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT) _timerLessEngineer->start();\n}\n\n/**\n * Stops the timerLessEngineer.\n * @param action A pointer to an Action.\n */\nvoid ManufactureInfoState::lessEngineerRelease(Action *action)\n{\n\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT)\n\t{\n\t\t_timerLessEngineer->setInterval(250);\n\t\t_timerLessEngineer->stop();\n\t}\n}\n\n/**\n * Removes engineers from the production.\n * @param action A pointer to an Action.\n */\nvoid ManufactureInfoState::lessEngineerClick(Action *action)\n{\n\tif (action->getDetails()->button.button == SDL_BUTTON_RIGHT) lessEngineer(INT_MAX);\n\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT) lessEngineer(1);\n}\n\n/**\n * Adds given number of units to produce to the project if possible.\n * @param change How much we want to add.\n */\nvoid ManufactureInfoState::moreUnit(int change)\n{\n\tif (change <= 0) return;\n\tif (_production->getRules()->getProducedCraft() && _base->getAvailableHangars() - _base->getUsedHangars() <= 0)\n\t{\n\t\t_timerMoreUnit->stop();\n\t\t_game->pushState(new ErrorMessageState(tr(\"STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION\"), _palette, _game->getMod()->getInterface(\"basescape\")->getElement(\"errorMessage\")->color, \"BACK17.SCR\", _game->getMod()->getInterface(\"basescape\")->getElement(\"errorPalette\")->color));\n\t}\n\telse\n\t{\n\t\tint units = _production->getAmountTotal();\n\t\tif (units == 1 && change > 1)\n\t\t{\n\t\t\t--change; // e.g. jump from 1 to 10, not to 11\n\t\t}\n\t\tchange = std::min(INT_MAX - units, change);\n\t\tif (_production->getRules()->getProducedCraft())\n\t\t\tchange = std::min(_base->getAvailableHangars() - _base->getUsedHangars(), change);\n\t\t_production->setAmountTotal(units+change);\n\t\tsetAssignedEngineer();\n\t}\n}\n\n/**\n * Starts the timerMoreUnit.\n * @param action A pointer to an Action.\n */\nvoid ManufactureInfoState::moreUnitPress(Action *action)\n{\n\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT && _production->getAmountTotal() < INT_MAX)\n\t\t_timerMoreUnit->start();\n}\n\n/**\n * Stops the timerMoreUnit.\n * @param action A pointer to an Action.\n */\nvoid ManufactureInfoState::moreUnitRelease(Action *action)\n{\n\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT)\n\t{\n\t\t_timerMoreUnit->setInterval(250);\n\t\t_timerMoreUnit->stop();\n\t}\n}\n\n/**\n * Increases the \"units to produce\", in the case of a right-click, to infinite, and 1 on left-click.\n * @param action A pointer to an Action.\n */\nvoid ManufactureInfoState::moreUnitClick(Action *action)\n{\n\tif (_production->getInfiniteAmount()) return; // We can't increase over infinite :)\n\tif (action->getDetails()->button.button == SDL_BUTTON_RIGHT)\n\t{\n\t\tif (_production->getRules()->getProducedCraft())\n\t\t{\n\t\t\tmoreUnit(INT_MAX);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_production->setInfiniteAmount(true);\n\t\t\tsetAssignedEngineer();\n\t\t}\n\t}\n\telse if (action->getDetails()->button.button == SDL_BUTTON_LEFT)\n\t{\n\t\tmoreUnit(1);\n\t}\n}\n\n/**\n * Increases the \"units to produce\" to infinite (\"right-click button\" on mobile platforms).\n * @param action A pointer to an Action.\n */\nvoid ManufactureInfoState::infinityUnitClick(Action* action)\n{\n\tif (_production->getInfiniteAmount()) return; // We can't increase over infinite :)\n\n\tif (_production->getRules()->getProducedCraft())\n\t{\n\t\t// nothing\n\t}\n\telse\n\t{\n\t\t_production->setInfiniteAmount(true);\n\t\tsetAssignedEngineer();\n\t}\n}\n\n/**\n * Removes the given number of units to produce from the project if possible.\n * @param change How much we want to subtract.\n */\nvoid ManufactureInfoState::lessUnit(int change)\n{\n\tif (change <= 0) return;\n\tint units = _production->getAmountTotal();\n\tchange = std::min(units-(_production->getAmountProduced()+1), change);\n\t_production->setAmountTotal(units-change);\n\tsetAssignedEngineer();\n}\n\n/**\n * Starts the timerLessUnit.\n * @param action A pointer to an Action.\n */\nvoid ManufactureInfoState::lessUnitPress(Action *action)\n{\n\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT) _timerLessUnit->start();\n}\n\n/**\n * Stops the timerLessUnit.\n * @param action A pointer to an Action.\n */\nvoid ManufactureInfoState::lessUnitRelease(Action *action)\n{\n\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT)\n\t{\n\t\t_timerLessUnit->setInterval(250);\n\t\t_timerLessUnit->stop();\n\t}\n}\n\n/**\n * Decreases the units to produce.\n * @param action A pointer to an Action.\n */\nvoid ManufactureInfoState::lessUnitClick(Action *action)\n{\n\tif (action->getDetails()->button.button == SDL_BUTTON_RIGHT\n\t||  action->getDetails()->button.button == SDL_BUTTON_LEFT)\n\t{\n\t\tbool wasInfinite = _production->getInfiniteAmount();\n\t\t_production->setInfiniteAmount(false);\n\t\tif (action->getDetails()->button.button == SDL_BUTTON_RIGHT\n\t\t|| _production->getAmountTotal() <= _production->getAmountProduced())\n\t\t{ // So the produced item number is increased over the planned, OR it was simply a right-click\n\t\t\t_production->setAmountTotal(_production->getAmountProduced()+1);\n\t\t\tsetAssignedEngineer();\n\t\t}\n\t\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT)\n\t\t{\n\t\t\tif (wasInfinite)\n\t\t\t{\n\t\t\t\t// when infinite amount is decreased by 1, set the amount to maximum possible (capped at 999) considering current funds and store supplies\n\t\t\t\tint productionPossible = 999;\n\t\t\t\tauto* manufRule = _production->getRules();\n\t\t\t\tif (manufRule->getManufactureCost() > 0)\n\t\t\t\t{\n\t\t\t\t\tint64_t byFunds = _game->getSavedGame()->getFunds() / manufRule->getManufactureCost();\n\t\t\t\t\tif (byFunds < 1000LL)\n\t\t\t\t\t{\n\t\t\t\t\t\tint byFundsInt = (int)byFunds;\n\t\t\t\t\t\tproductionPossible = std::min(productionPossible, byFundsInt);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfor (auto& item : manufRule->getRequiredItems())\n\t\t\t\t{\n\t\t\t\t\tproductionPossible = std::min(productionPossible, _base->getStorageItems()->getItem(item.first) / item.second);\n\t\t\t\t}\n\t\t\t\tproductionPossible = std::max(0, productionPossible);\n\n\t\t\t\tint newTotal = _production->getAmountProduced() + productionPossible;\n\t\t\t\tif (!_item)\n\t\t\t\t{\n\t\t\t\t\tnewTotal += 1; // +1 for the item being produced currently\n\t\t\t\t}\n\t\t\t\t_production->setAmountTotal(newTotal + 1); // +1 because of lessUnit(1) call below\n\t\t\t}\n\t\t\tlessUnit(1);\n\t\t}\n\t}\n}\n\n/**\n * Decreases the units to produce (\"right-click button\" on mobile platforms).\n * @param action A pointer to an Action.\n */\nvoid ManufactureInfoState::minimumUnitClick(Action* action)\n{\n\t_production->setInfiniteAmount(false);\n\t_production->setAmountTotal(_production->getAmountProduced() + 1);\n\tsetAssignedEngineer();\n}\n\n/**\n * Assigns one more engineer (if possible).\n */\nvoid ManufactureInfoState::onMoreEngineer()\n{\n\t_timerMoreEngineer->setInterval(50);\n\tmoreEngineer(1);\n}\n\n/**\n * Removes one engineer (if possible).\n */\nvoid ManufactureInfoState::onLessEngineer()\n{\n\t_timerLessEngineer->setInterval(50);\n\tlessEngineer(1);\n}\n\n/**\n * Increases or decreases the Engineers according the mouse-wheel used.\n * @param action A pointer to an Action.\n */\nvoid ManufactureInfoState::handleWheelEngineer(Action *action)\n{\n\tif (action->getDetails()->button.button == SDL_BUTTON_WHEELUP) moreEngineer(Options::changeValueByMouseWheel);\n\telse if (action->getDetails()->button.button == SDL_BUTTON_WHEELDOWN) lessEngineer(Options::changeValueByMouseWheel);\n}\n\n/**\n * Builds one more unit.\n */\nvoid ManufactureInfoState::onMoreUnit()\n{\n\t_timerMoreUnit->setInterval(50);\n\tmoreUnit(1);\n}\n\n/**\n * Builds one less unit( if possible).\n */\nvoid ManufactureInfoState::onLessUnit()\n{\n\t_timerLessUnit->setInterval(50);\n\tlessUnit(1);\n}\n\n/**\n * Increases or decreases the Units to produce according the mouse-wheel used.\n * @param action A pointer to an Action.\n */\nvoid ManufactureInfoState::handleWheelUnit(Action *action)\n{\n\tif (action->getDetails()->button.button == SDL_BUTTON_WHEELUP) moreUnit(Options::changeValueByMouseWheel);\n\telse if (action->getDetails()->button.button == SDL_BUTTON_WHEELDOWN) lessUnit(Options::changeValueByMouseWheel);\n}\n\n/**\n * Runs state functionality every cycle (used to update the timer).\n */\nvoid ManufactureInfoState::think()\n{\n\tState::think();\n\t_timerMoreEngineer->think(this, 0);\n\t_timerLessEngineer->think(this, 0);\n\t_timerMoreUnit->think(this, 0);\n\t_timerLessUnit->think(this, 0);\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/ManufactureInfoState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass Base;\nclass Window;\nclass Text;\nclass ArrowButton;\nclass TextButton;\nclass ToggleTextButton;\nclass RuleManufacture;\nclass Production;\nclass Timer;\nclass InteractiveSurface;\n\n/**\n * Screen that allows changing of Production settings (assigned engineer, units to build).\n */\nclass ManufactureInfoState : public State\n{\nprivate:\n\tBase * _base;\n\tRuleManufacture * _item;\n\tProduction * _production;\n\tWindow * _window;\n\tArrowButton * _btnUnitInfinity, * _btnUnitMinimum;\n\tArrowButton * _btnUnitUp, * _btnUnitDown, * _btnEngineerUp, * _btnEngineerDown;\n\tTextButton * _btnStop, * _btnOk;\n\tText * _txtTitle, * _txtAvailableEngineer, * _txtAvailableSpace, * _txtHoursPerUnit, * _txtMonthlyProfit;\n\tText * _txtAllocatedEngineer, * _txtUnitToProduce, * _txtUnitUp, * _txtUnitDown, * _txtEngineerUp, * _txtEngineerDown, * _txtAllocated, * _txtTodo;\n\tToggleTextButton *_btnSell;\n\tToggleTextButton *_btnFallback;\n\tTimer * _timerMoreEngineer, * _timerMoreUnit, * _timerLessEngineer, * _timerLessUnit;\n\tInteractiveSurface *_surfaceEngineers, *_surfaceUnits;\n\tint _producedItemsValue;\n\t/// Caches static data for monthly profit calculations\n\tvoid initProfitInfo ();\n\t/// Calculates the monthly change in funds due to the job\n\tint getMonthlyNetFunds () const;\n\t/// Handler for the Sell button.\n\tvoid btnSellClick (Action * action);\n\t/// Handler for the Stop button.\n\tvoid btnStopClick (Action * action);\n\t/// Handler for the OK button.\n\tvoid btnOkClick (Action * action);\n\t/// Adds given number of engineers to the project if possible.\n\tvoid moreEngineer(int change);\n\t/// Handler for pressing the more engineer button.\n\tvoid moreEngineerPress(Action * action);\n\t/// Handler for releasing the more engineer button.\n\tvoid moreEngineerRelease(Action * action);\n\t/// Handler for clicking the more engineer button.\n\tvoid moreEngineerClick(Action * action);\n\t/// Adds given number of units to produce to the project if possible.\n\tvoid moreUnit(int change);\n\t/// Handler for pressing the more unit button.\n\tvoid moreUnitPress(Action * action);\n\t/// Handler for releasing the more unit button.\n\tvoid moreUnitRelease(Action * action);\n\t/// Handler for clicking the more unit button.\n\tvoid moreUnitClick(Action * action);\n\tvoid infinityUnitClick(Action* action);\n\t/// Removes the given number of engineers from the project if possible.\n\tvoid lessEngineer(int change);\n\t/// Handler for pressing the less engineer button.\n\tvoid lessEngineerPress(Action * action);\n\t/// Handler for releasing the less engineer button.\n\tvoid lessEngineerRelease(Action * action);\n\t/// Handler for clicking the less engineer button.\n\tvoid lessEngineerClick(Action * action);\n\t/// Removes the given number of units to produce from the project if possible.\n\tvoid lessUnit(int change);\n\t/// Handler for pressing the less unit button.\n\tvoid lessUnitPress(Action * action);\n\t/// Handler for releasing the less unit button.\n\tvoid lessUnitRelease(Action * action);\n\t/// Handler for clicking the less unit button.\n\tvoid lessUnitClick(Action * action);\n\tvoid minimumUnitClick(Action* action);\n\t/// Adds one engineer to the production (if possible).\n\tvoid onMoreEngineer();\n\t/// Removes one engineer from the production (if possible).\n\tvoid onLessEngineer();\n\t/// Handler for using the mouse wheel on the Engineer-part of the screen.\n\tvoid handleWheelEngineer(Action *action);\n\t/// Increases count of number of units to make.\n\tvoid onMoreUnit();\n\t/// Decreases count of number of units to make (if possible).\n\tvoid onLessUnit();\n\t/// Handler for using the mouse wheel on the Unit-part of the screen.\n\tvoid handleWheelUnit(Action *action);\n\t/// Updates display of assigned/available engineers and workshop space.\n\tvoid setAssignedEngineer();\n\t/// Runs state functionality every cycle.\n\tvoid think() override;\n\t/// Builds the User Interface.\n\tvoid buildUi();\n\t/// Helper to exit the State.\n\tvoid exitState();\npublic:\n\t/// Creates the State (new production).\n\tManufactureInfoState(Base * base, RuleManufacture * _item);\n\t/// Creates the State (modify production).\n\tManufactureInfoState(Base * base, Production * production);\n\t/// Cleans up the state\n\t~ManufactureInfoState();\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/ManufactureStartState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ManufactureStartState.h\"\n#include <sstream>\n#include \"../Interface/Window.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Menu/ErrorMessageState.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"../Mod/RuleManufacture.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/ItemContainer.h\"\n#include \"ManufactureInfoState.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Mod/RuleInterface.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the productions start screen.\n * @param game Pointer to the core game.\n * @param base Pointer to the base to get info from.\n * @param item The RuleManufacture to produce.\n */\nManufactureStartState::ManufactureStartState(Base *base, RuleManufacture *item) :  _base(base), _item(item)\n{\n\t_screen = false;\n\n\t_window = new Window(this, 320, 160, 0, 20);\n\t_btnCancel = new TextButton(136, 16, 16, 155);\n\t_txtTitle = new Text(320, 17, 0, 30);\n\t_txtManHour = new Text(290, 9, 16, 50);\n\t_txtCost = new Text(290, 9, 16, 60);\n\t_txtWorkSpace = new Text(290, 9, 16, 70);\n\n\t_txtRequiredItemsTitle = new Text(290, 9, 16, 84);\n\t_txtItemNameColumn = new Text(60, 16, 30, 92);\n\t_txtUnitRequiredColumn = new Text(60, 16, 155, 92);\n\t_txtUnitAvailableColumn = new Text(60, 16, 230, 92);\n\t_lstRequiredItems = new TextList(270, 40, 30, 108);\n\n\t_btnStart = new TextButton(136, 16, 168, 155);\n\n\t// Set palette\n\tsetInterface(\"allocateManufacture\");\n\n\tadd(_window, \"window\", \"allocateManufacture\");\n\tadd(_txtTitle, \"text\", \"allocateManufacture\");\n\tadd(_txtManHour, \"text\", \"allocateManufacture\");\n\tadd(_txtCost, \"text\", \"allocateManufacture\");\n\tadd(_txtWorkSpace, \"text\", \"allocateManufacture\");\n\tadd(_btnCancel, \"button\", \"allocateManufacture\");\n\n\tadd(_txtRequiredItemsTitle, \"text\", \"allocateManufacture\");\n\tadd(_txtItemNameColumn, \"text\", \"allocateManufacture\");\n\tadd(_txtUnitRequiredColumn, \"text\", \"allocateManufacture\");\n\tadd(_txtUnitAvailableColumn, \"text\", \"allocateManufacture\");\n\tadd(_lstRequiredItems, \"list\", \"allocateManufacture\");\n\n\tadd(_btnStart, \"button\", \"allocateManufacture\");\n\n\tcenterAllSurfaces();\n\n\tsetWindowBackground(_window, \"allocateManufacture\");\n\n\t_txtTitle->setText(tr(_item->getName()));\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\n\t_txtManHour->setText(tr(\"STR_ENGINEER_HOURS_TO_PRODUCE_ONE_UNIT\").arg(_item->getManufactureTime()));\n\n\t_txtCost->setText(tr(\"STR_COST_PER_UNIT_\").arg(Unicode::formatFunding(_item->getManufactureCost())));\n\n\t_txtWorkSpace->setText(tr(\"STR_WORK_SPACE_REQUIRED\").arg(_item->getRequiredSpace()));\n\n\t_btnCancel->setText(tr(\"STR_CANCEL_UC\"));\n\t_btnCancel->onMouseClick((ActionHandler)&ManufactureStartState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&ManufactureStartState::btnCancelClick, Options::keyCancel);\n\n\tbool productionPossible = _item->haveEnoughMoneyForOneMoreUnit(_game->getSavedGame()->getFunds());\n\t// check available workspace later\n\t//int availableWorkSpace = _base->getFreeWorkshops();\n\t//productionPossible &= (availableWorkSpace > 0);\n\n\t_txtRequiredItemsTitle->setText(tr(\"STR_SPECIAL_MATERIALS_REQUIRED\"));\n\t_txtRequiredItemsTitle->setAlign(ALIGN_CENTER);\n\n\t_txtItemNameColumn->setText(tr(\"STR_ITEM_REQUIRED\"));\n\t_txtItemNameColumn->setWordWrap(true);\n\n\t_txtUnitRequiredColumn->setText(tr(\"STR_UNITS_REQUIRED\"));\n\t_txtUnitRequiredColumn->setWordWrap(true);\n\n\t_txtUnitAvailableColumn->setText(tr(\"STR_UNITS_AVAILABLE\"));\n\t_txtUnitAvailableColumn->setWordWrap(true);\n\n\t_lstRequiredItems->setColumns(3, 140, 75, 55);\n\t_lstRequiredItems->setBackground(_window);\n\n\tbool hasRequirements = _item->getRequiredCrafts().size() > 0 || _item->getRequiredItems().size() > 0;\n\tint row = 0;\n\tfor (auto& iter : _item->getRequiredCrafts())\n\t{\n\t\tint count = base->getCraftCountForProduction(iter.first);\n\n\t\tstd::ostringstream s1, s2;\n\t\ts1 << iter.second;\n\t\ts2 << count;\n\t\tproductionPossible &= (count >= iter.second);\n\t\t_lstRequiredItems->addRow(3, tr(iter.first->getType()).c_str(), s1.str().c_str(), s2.str().c_str());\n\t\t_lstRequiredItems->setCellColor(row, 1, _lstRequiredItems->getSecondaryColor());\n\t\t_lstRequiredItems->setCellColor(row, 2, _lstRequiredItems->getSecondaryColor());\n\t\trow++;\n\t}\n\tfor (auto& iter : _item->getRequiredItems())\n\t{\n\t\tint count = base->getStorageItems()->getItem(iter.first);\n\n\t\tstd::ostringstream s1, s2;\n\t\ts1 << iter.second;\n\t\ts2 << count;\n\t\tproductionPossible &= (count >= iter.second);\n\t\t_lstRequiredItems->addRow(3, tr(iter.first->getType()).c_str(), s1.str().c_str(), s2.str().c_str());\n\t\t_lstRequiredItems->setCellColor(row, 1, _lstRequiredItems->getSecondaryColor());\n\t\t_lstRequiredItems->setCellColor(row, 2, _lstRequiredItems->getSecondaryColor());\n\t\trow++;\n\t}\n\tif (_item->getSpawnedPersonType() != \"\")\n\t{\n\t\tif (base->getAvailableQuarters() <= base->getUsedQuarters())\n\t\t{\n\t\t\tproductionPossible = false;\n\t\t}\n\n\t\t// separator line\n\t\t_lstRequiredItems->addRow(1, tr(\"STR_PERSON_JOINING\").c_str());\n\t\t_lstRequiredItems->setCellColor(row, 0, _lstRequiredItems->getSecondaryColor());\n\t\trow++;\n\n\t\t// person joining\n\t\tstd::ostringstream s1;\n\t\ts1 << Unicode::TOK_COLOR_FLIP << 1;\n\t\t_lstRequiredItems->addRow(2, tr(_item->getSpawnedPersonName() != \"\" ? _item->getSpawnedPersonName() : _item->getSpawnedPersonType()).c_str(), s1.str().c_str());\n\t\trow++;\n\t}\n\tif (!_item->getRandomProducedItems().empty())\n\t{\n\t\t// separator line\n\t\t_lstRequiredItems->addRow(1, tr(\"STR_RANDOM_PRODUCTION_DISCLAIMER\").c_str());\n\t\t_lstRequiredItems->setCellColor(row, 0, _lstRequiredItems->getSecondaryColor());\n\t\trow++;\n\t}\n\tbool hasVanillaOutput = false;\n\tif (_item->getProducedItems().size() == 1)\n\t{\n\t\tconst RuleItem* match = _game->getMod()->getItem(_item->getName(), false);\n\t\tif (match)\n\t\t{\n\t\t\tauto iter = _item->getProducedItems().find(match);\n\t\t\tif (iter != _item->getProducedItems().end())\n\t\t\t{\n\t\t\t\thasVanillaOutput = ((*iter).second == 1);\n\t\t\t}\n\t\t}\n\t}\n\tif (!hasVanillaOutput && !_item->getProducedItems().empty())\n\t{\n\t\t// separator line\n\t\t_lstRequiredItems->addRow(1, tr(\"STR_UNITS_PRODUCED\").c_str());\n\t\t_lstRequiredItems->setCellColor(row, 0, _lstRequiredItems->getSecondaryColor());\n\t\trow++;\n\n\t\t// produced items\n\t\tfor (auto& iter : _item->getProducedItems())\n\t\t{\n\t\t\tstd::ostringstream s1;\n\t\t\ts1 << Unicode::TOK_COLOR_FLIP << iter.second;\n\t\t\t_lstRequiredItems->addRow(2, tr(iter.first->getType()).c_str(), s1.str().c_str());\n\t\t\trow++;\n\t\t}\n\t}\n\n\t_txtRequiredItemsTitle->setVisible(hasRequirements);\n\t_txtItemNameColumn->setVisible(hasRequirements);\n\t_txtUnitRequiredColumn->setVisible(hasRequirements);\n\t_txtUnitAvailableColumn->setVisible(hasRequirements);\n\t_lstRequiredItems->setVisible(row);\n\n\t_btnStart->setText(tr(\"STR_START_PRODUCTION\"));\n\t_btnStart->onMouseClick((ActionHandler)&ManufactureStartState::btnStartClick);\n\t_btnStart->onKeyboardPress((ActionHandler)&ManufactureStartState::btnStartClick, Options::keyOk);\n\t_btnStart->setVisible(productionPossible);\n\n\tif (_item)\n\t{\n\t\t// mark new as normal\n\t\tif (_game->getSavedGame()->getManufactureRuleStatus(_item->getName()) == RuleManufacture::MANU_STATUS_NEW)\n\t\t{\n\t\t\t_game->getSavedGame()->setManufactureRuleStatus(_item->getName(), RuleManufacture::MANU_STATUS_NORMAL);\n\t\t}\n\t}\n}\n\n/**\n * Returns to previous screen.\n * @param action A pointer to an Action.\n */\nvoid ManufactureStartState::btnCancelClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Go to the Production settings screen.\n * @param action A pointer to an Action.\n */\nvoid ManufactureStartState::btnStartClick(Action *)\n{\n\tif (_item->getProducedCraft() && _base->getAvailableHangars() - _base->getUsedHangars() <= 0)\n\t{\n\t\t_game->pushState(new ErrorMessageState(tr(\"STR_NO_FREE_HANGARS_FOR_CRAFT_PRODUCTION\"), _palette, _game->getMod()->getInterface(\"basescape\")->getElement(\"errorMessage\")->color, \"BACK17.SCR\", _game->getMod()->getInterface(\"basescape\")->getElement(\"errorPalette\")->color));\n\t}\n\t//else if (_item->getRequiredSpace() > _base->getFreeWorkshops())\n\t//{\n\t//\t_game->pushState(new ErrorMessageState(tr(\"STR_NOT_ENOUGH_WORK_SPACE\"), _palette, _game->getMod()->getInterface(\"basescape\")->getElement(\"errorMessage\")->color, \"BACK17.SCR\", _game->getMod()->getInterface(\"basescape\")->getElement(\"errorPalette\")->color));\n\t//}\n\telse\n\t{\n\t\t_game->pushState(new ManufactureInfoState(_base, _item));\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/ManufactureStartState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass Base;\nclass RuleManufacture;\nclass Window;\nclass TextButton;\nclass Text;\nclass TextList;\n\n/**\n * Screen which displays needed elements to start productions (items/required workshop state/cost to build a unit, ...).\n */\nclass ManufactureStartState : public State\n{\nprivate:\n\tBase *_base;\n\tRuleManufacture *_item;\n\tWindow *_window;\n\tTextButton *_btnCancel, *_btnStart;\n\tText *_txtTitle, *_txtManHour, *_txtCost, *_txtWorkSpace, *_txtRequiredItemsTitle, *_txtItemNameColumn, *_txtUnitRequiredColumn, *_txtUnitAvailableColumn;\n\tTextList *_lstRequiredItems;\npublic:\n\t/// Creates the State.\n\tManufactureStartState(Base *base, RuleManufacture *item);\n\t/// Handler for the Cancel button.\n\tvoid btnCancelClick(Action *action);\n\t/// Handler for the start button.\n\tvoid btnStartClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/ManufactureState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ManufactureState.h\"\n#include <sstream>\n#include \"../Engine/Action.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Mod/RuleManufacture.h\"\n#include \"../Savegame/Production.h\"\n#include \"NewManufactureListState.h\"\n#include \"GlobalManufactureState.h\"\n#include \"ManufactureInfoState.h\"\n#include \"TechTreeViewerState.h\"\n#include \"../Ufopaedia/Ufopaedia.h\"\n#include <algorithm>\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Manufacture screen.\n * @param game Pointer to the core game.\n * @param base Pointer to the base to get info from.\n */\nManufactureState::ManufactureState(Base *base) : _base(base)\n{\n\t// Create objects\n\t_window = new Window(this, 320, 200, 0, 0);\n\t_btnNew = new TextButton(148, 16, 8, 176);\n\t_btnOk = new TextButton(148, 16, 164, 176);\n\t_txtTitle = new Text(310, 17, 5, 8);\n\t_txtAvailable = new Text(150, 9, 8, 24);\n\t_txtAllocated = new Text(150, 9, 160, 24);\n\t_txtSpace = new Text(150, 9, 8, 34);\n\t_txtFunds = new Text(150, 9, 160, 34);\n\t_txtItem = new Text(80, 9, 10, 52);\n\t_txtEngineers = new Text(56, 18, 112, 44);\n\t_txtProduced = new Text(56, 18, 168, 44);\n\t_txtCost = new Text(44, 27, 222, 44);\n\t_txtTimeLeft = new Text(60, 27, 260, 44);\n\t_lstManufacture = new TextList(288, 88, 8, 80);\n\n\t// Set palette\n\tsetInterface(\"manufactureMenu\");\n\n\tadd(_window, \"window\", \"manufactureMenu\");\n\tadd(_btnNew, \"button\", \"manufactureMenu\");\n\tadd(_btnOk, \"button\", \"manufactureMenu\");\n\tadd(_txtTitle, \"text1\", \"manufactureMenu\");\n\tadd(_txtAvailable, \"text1\", \"manufactureMenu\");\n\tadd(_txtAllocated, \"text1\", \"manufactureMenu\");\n\tadd(_txtSpace, \"text1\", \"manufactureMenu\");\n\tadd(_txtFunds, \"text1\", \"manufactureMenu\");\n\tadd(_txtItem, \"text2\", \"manufactureMenu\");\n\tadd(_txtEngineers, \"text2\", \"manufactureMenu\");\n\tadd(_txtProduced, \"text2\", \"manufactureMenu\");\n\tadd(_txtCost, \"text2\", \"manufactureMenu\");\n\tadd(_txtTimeLeft, \"text2\", \"manufactureMenu\");\n\tadd(_lstManufacture, \"list\", \"manufactureMenu\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"manufactureMenu\");\n\n\t_btnNew->setText(tr(\"STR_NEW_PRODUCTION\"));\n\t_btnNew->onMouseClick((ActionHandler)&ManufactureState::btnNewProductionClick);\n\t_btnNew->onKeyboardPress((ActionHandler)&ManufactureState::btnNewProductionClick, Options::keyToggleQuickSearch);\n\t_btnNew->onKeyboardPress((ActionHandler)&ManufactureState::onCurrentGlobalProductionClick, Options::keyGeoGlobalProduction);\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&ManufactureState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&ManufactureState::btnOkClick, Options::keyCancel);\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_CURRENT_PRODUCTION\"));\n\n\t_txtItem->setText(tr(\"STR_ITEM\"));\n\n\t_txtEngineers->setText(tr(\"STR_ENGINEERS__ALLOCATED\"));\n\t_txtEngineers->setWordWrap(true);\n\n\t_txtProduced->setText(tr(\"STR_UNITS_PRODUCED\"));\n\t_txtProduced->setWordWrap(true);\n\n\t_txtCost->setText(tr(\"STR_COST__PER__UNIT\"));\n\t_txtCost->setWordWrap(true);\n\n\t_txtTimeLeft->setText(tr(\"STR_DAYS_HOURS_LEFT\"));\n\t_txtTimeLeft->setWordWrap(true);\n\n\t_lstManufacture->setColumns(5, 114, 16, 52, 56, 48);\n\t_lstManufacture->setAlign(ALIGN_RIGHT);\n\t_lstManufacture->setAlign(ALIGN_LEFT, 0);\n\t_lstManufacture->setSelectable(true);\n\t_lstManufacture->setBackground(_window);\n\t_lstManufacture->setMargin(2);\n\t_lstManufacture->setWordWrap(true);\n\t_lstManufacture->onMouseClick((ActionHandler)&ManufactureState::lstManufactureClickLeft, SDL_BUTTON_LEFT);\n\t_lstManufacture->onMouseClick((ActionHandler)&ManufactureState::lstManufactureClickMiddle, SDL_BUTTON_MIDDLE);\n\t_lstManufacture->onMousePress((ActionHandler)&ManufactureState::lstManufactureMousePress);\n}\n\n/**\n *\n */\nManufactureState::~ManufactureState()\n{\n\n}\n\n/**\n * Updates the production list\n * after going to other screens.\n */\nvoid ManufactureState::init()\n{\n\tState::init();\n\tfillProductionList(0);\n\n\tif (Options::oxceManufactureScrollSpeed > 0 || Options::oxceManufactureScrollSpeedWithCtrl > 0)\n\t{\n\t\t// 140 +/- 20\n\t\t_lstManufacture->setNoScrollArea(_txtAllocated->getX() - 40, _txtAllocated->getX());\n\t}\n\telse\n\t{\n\t\t_lstManufacture->setNoScrollArea(0, 0);\n\t}\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid ManufactureState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Opens the Global Production UI.\n * @param action Pointer to an action.\n */\nvoid ManufactureState::onCurrentGlobalProductionClick(Action *)\n{\n\t_game->pushState(new GlobalManufactureState(true));\n}\n\n/**\n * Opens the screen with the list of possible productions.\n * @param action Pointer to an action.\n */\nvoid ManufactureState::btnNewProductionClick(Action *)\n{\n\t_game->pushState(new NewManufactureListState(_base));\n}\n\n/**\n * Fills the list of base productions.\n */\nvoid ManufactureState::fillProductionList(size_t scrl)\n{\n\t_lstManufacture->clearList();\n\tfor (const auto* prod : _base->getProductions())\n\t{\n\t\tstd::ostringstream s1;\n\t\ts1 << prod->getAssignedEngineers();\n\t\tstd::ostringstream s2;\n\t\ts2 << prod->getAmountProduced() << \"/\";\n\t\tif (prod->getInfiniteAmount()) s2 << \"∞\";\n\t\telse s2 << prod->getAmountTotal();\n\t\tif (prod->getSellItems()) s2 << \" $\";\n\t\tstd::ostringstream s3;\n\t\ts3 << Unicode::formatFunding(prod->getRules()->getManufactureCost());\n\t\tstd::ostringstream s4;\n\t\tif (prod->getInfiniteAmount())\n\t\t{\n\t\t\ts4 << \"∞\";\n\t\t}\n\t\telse if (prod->getAssignedEngineers() > 0)\n\t\t{\n\t\t\tint timeLeft = prod->getAmountTotal() * prod->getRules()->getManufactureTime() - prod->getTimeSpent();\n\t\t\tint numEffectiveEngineers = prod->getAssignedEngineers();\n\t\t\t// ensure we round up since it takes an entire hour to manufacture any part of that hour's capacity\n\t\t\tint hoursLeft = (timeLeft + numEffectiveEngineers - 1) / numEffectiveEngineers;\n\t\t\tint daysLeft = hoursLeft / 24;\n\t\t\tint hours = hoursLeft % 24;\n\t\t\ts4 << daysLeft << \"/\" << hours;\n\t\t}\n\t\telse\n\t\t{\n\n\t\t\ts4 << \"-\";\n\t\t}\n\t\t_lstManufacture->addRow(5, tr(prod->getRules()->getName()).c_str(), s1.str().c_str(), s2.str().c_str(), s3.str().c_str(), s4.str().c_str());\n\t}\n\t_txtAvailable->setText(tr(\"STR_ENGINEERS_AVAILABLE\").arg(_base->getAvailableEngineers()));\n\t_txtAllocated->setText(tr(\"STR_ENGINEERS_ALLOCATED\").arg(_base->getAllocatedEngineers()));\n\t_txtSpace->setText(tr(\"STR_WORKSHOP_SPACE_AVAILABLE\").arg(_base->getFreeWorkshops()));\n\t_txtFunds->setText(tr(\"STR_CURRENT_FUNDS\").arg(Unicode::formatFunding(_game->getSavedGame()->getFunds())));\n\n\tif (scrl)\n\t\t_lstManufacture->scrollTo(scrl);\n}\n\n/**\n * Opens the screen displaying production settings.\n * @param action Pointer to an action.\n */\nvoid ManufactureState::lstManufactureClickLeft(Action *)\n{\n\tconst std::vector<Production*> productions(_base->getProductions());\n\t_game->pushState(new ManufactureInfoState(_base, productions[_lstManufacture->getSelectedRow()]));\n}\n\n/**\n* Opens the TechTreeViewer for the corresponding topic.\n* @param action Pointer to an action.\n*/\nvoid ManufactureState::lstManufactureClickMiddle(Action *)\n{\n\tconst std::vector<Production*> productions(_base->getProductions());\n\tconst RuleManufacture *selectedTopic = productions[_lstManufacture->getSelectedRow()]->getRules();\n\tif (_game->isCtrlPressed())\n\t{\n\t\tstd::string articleId = selectedTopic->getName();\n\t\tUfopaedia::openArticle(_game, articleId);\n\t}\n\telse\n\t{\n\t\t_game->pushState(new TechTreeViewerState(0, selectedTopic));\n\t}\n}\n\n/**\n * Handles the mouse-wheels.\n * @param action Pointer to an action.\n */\nvoid ManufactureState::lstManufactureMousePress(Action *action)\n{\n\tif (!_lstManufacture->isInsideNoScrollArea(action->getAbsoluteXMouse()))\n\t{\n\t\treturn;\n\t}\n\n\tint change = Options::oxceManufactureScrollSpeed;\n\tif (_game->isCtrlPressed())\n\t\tchange = Options::oxceManufactureScrollSpeedWithCtrl;\n\n\tif (action->getDetails()->button.button == SDL_BUTTON_WHEELUP)\n\t{\n\t\tProduction *selectedProject = _base->getProductions()[_lstManufacture->getSelectedRow()];\n\t\tint availableWorkSpace = _base->getFreeWorkshops();\n\t\tif (selectedProject->isQueuedOnly())\n\t\t{\n\t\t\t// start counting the workshop space now\n\t\t\tavailableWorkSpace -= selectedProject->getRules()->getRequiredSpace();\n\t\t}\n\t\tchange = std::min(change, _base->getAvailableEngineers());\n\t\tchange = std::min(change, availableWorkSpace);\n\t\tif (change > 0)\n\t\t{\n\t\t\tselectedProject->setAssignedEngineers(selectedProject->getAssignedEngineers() + change);\n\t\t\t_base->setEngineers(_base->getEngineers() - change);\n\t\t\tfillProductionList(_lstManufacture->getScroll());\n\t\t}\n\t}\n\telse if (action->getDetails()->button.button == SDL_BUTTON_WHEELDOWN)\n\t{\n\t\tProduction *selectedProject = _base->getProductions()[_lstManufacture->getSelectedRow()];\n\t\tchange = std::min(change, selectedProject->getAssignedEngineers());\n\t\tif (change > 0)\n\t\t{\n\t\t\tselectedProject->setAssignedEngineers(selectedProject->getAssignedEngineers() - change);\n\t\t\t_base->setEngineers(_base->getEngineers() + change);\n\t\t\tfillProductionList(_lstManufacture->getScroll());\n\t\t}\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/ManufactureState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass TextList;\nclass Base;\n\n/**\n * Manufacture screen that lets the player manage\n * all the manufacturing operations of a base.\n */\nclass ManufactureState : public State\n{\nprivate:\n\tBase *_base;\n\tTextButton *_btnNew, *_btnOk;\n\tWindow *_window;\n\tText *_txtTitle, *_txtAvailable, *_txtAllocated, *_txtSpace, *_txtFunds, *_txtItem, *_txtEngineers, *_txtProduced, *_txtCost, *_txtTimeLeft;\n\tTextList *_lstManufacture;\n\tvoid lstManufactureClickLeft(Action * action);\n\tvoid lstManufactureClickMiddle(Action * action);\n\tvoid lstManufactureMousePress(Action *action);\npublic:\n\t/// Creates the Manufacture state.\n\tManufactureState(Base *base);\n\t/// Cleans up the Manufacture state.\n\t~ManufactureState();\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for opening the Global Production UI.\n\tvoid onCurrentGlobalProductionClick(Action *action);\n\t/// Updates the production list.\n\tvoid init() override;\n\t/// Handler for the New Production button.\n\tvoid btnNewProductionClick(Action * action);\n\t/// Fills the list of base productions.\n\tvoid fillProductionList(size_t scrl);\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/MiniBaseView.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"MiniBaseView.h\"\n#include <cmath>\n#include \"../Engine/SurfaceSet.h\"\n#include \"../Engine/Action.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/BaseFacility.h\"\n#include \"../Mod/RuleBaseFacility.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Sets up a mini base view with the specified size and position.\n * @param width Width in pixels.\n * @param height Height in pixels.\n * @param x X position in pixels.\n * @param y Y position in pixels.\n */\nMiniBaseView::MiniBaseView(int width, int height, int x, int y) : InteractiveSurface(width, height, x, y), _bases(0), _texture(0), _base(0), _hoverBase(0), _red(0), _green(0), _blue(0)\n{\n}\n\n/**\n *\n */\nMiniBaseView::~MiniBaseView()\n{\n}\n\n/**\n * Changes the current list of bases to display.\n * @param bases Pointer to base list to display.\n */\nvoid MiniBaseView::setBases(std::vector<Base*> *bases)\n{\n\t_bases = bases;\n\t_redraw = true;\n}\n\n/**\n * Changes the texture to use for drawing\n * the various base elements.\n * @param texture Pointer to SurfaceSet to use.\n */\nvoid MiniBaseView::setTexture(SurfaceSet *texture)\n{\n\t_texture = texture;\n}\n\n/**\n * Returns the base the mouse cursor is currently over.\n * @return ID of the base.\n */\nsize_t MiniBaseView::getHoveredBase() const\n{\n\treturn _hoverBase;\n}\n\n/**\n * Changes the base that is currently selected on\n * the mini base view.\n * @param base ID of base.\n */\nvoid MiniBaseView::setSelectedBase(size_t base)\n{\n\t_base = base;\n\t_redraw = true;\n}\n\n/**\n * Draws the view of all the bases with facilities\n * in varying colors.\n */\nvoid MiniBaseView::draw()\n{\n\tSurface::draw();\n\tfor (size_t i = 0; i < MAX_BASES; ++i)\n\t{\n\t\t// Draw base squares\n\t\tif (i == _base)\n\t\t{\n\t\t\tSDL_Rect r;\n\t\t\tr.x = i * (MINI_SIZE + 2);\n\t\t\tr.y = 0;\n\t\t\tr.w = MINI_SIZE + 2;\n\t\t\tr.h = MINI_SIZE + 2;\n\t\t\tdrawRect(&r, 1);\n\t\t}\n\t\t_texture->getFrame(41)->blitNShade(this, i * (MINI_SIZE + 2), 0);\n\n\t\t// Draw facilities\n\t\tif (i < _bases->size())\n\t\t{\n\t\t\tSDL_Rect r;\n\t\t\tlock();\n\t\t\tfor (const auto* fac : *_bases->at(i)->getFacilities())\n\t\t\t{\n\t\t\t\tint color;\n\t\t\t\tif (fac->getDisabled())\n\t\t\t\t\tcolor = _blue;\n\t\t\t\telse if (fac->getBuildTime() == 0)\n\t\t\t\t\tcolor = _green;\n\t\t\t\telse\n\t\t\t\t\tcolor = _red;\n\n\t\t\t\tr.x = i * (MINI_SIZE + 2) + 2 + fac->getX() * 2;\n\t\t\t\tr.y = 2 + fac->getY() * 2;\n\t\t\t\tr.w = fac->getRules()->getSizeX() * 2;\n\t\t\t\tr.h = fac->getRules()->getSizeY() * 2;\n\t\t\t\tdrawRect(&r, color+3);\n\t\t\t\tr.x++;\n\t\t\t\tr.y++;\n\t\t\t\tr.w--;\n\t\t\t\tr.h--;\n\t\t\t\tdrawRect(&r, color+5);\n\t\t\t\tr.x--;\n\t\t\t\tr.y--;\n\t\t\t\tdrawRect(&r, color+2);\n\t\t\t\tr.x++;\n\t\t\t\tr.y++;\n\t\t\t\tr.w--;\n\t\t\t\tr.h--;\n\t\t\t\tdrawRect(&r, color+3);\n\t\t\t\tr.x--;\n\t\t\t\tr.y--;\n\t\t\t\tsetPixel(r.x, r.y, color+1);\n\t\t\t}\n\t\t\tunlock();\n\t\t}\n\t}\n}\n\n/**\n * Selects the base the mouse is over.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid MiniBaseView::mouseOver(Action *action, State *state)\n{\n\t_hoverBase = (int)floor(action->getRelativeXMouse() / ((MINI_SIZE + 2) * action->getXScale()));\n\tInteractiveSurface::mouseOver(action, state);\n}\n\nvoid MiniBaseView::setColor(Uint8 color)\n{\n\t_green = color;\n}\nvoid MiniBaseView::setSecondaryColor(Uint8 color)\n{\n\t_red = color;\n}\nvoid MiniBaseView::setBorderColor(Uint8 color)\n{\n\t_blue = color;\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/MiniBaseView.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <vector>\n#include \"../Engine/InteractiveSurface.h\"\n\nnamespace OpenXcom\n{\n\nclass Base;\nclass SurfaceSet;\n\n/**\n * Mini view of a base.\n * Takes all the bases and displays their layout\n * and allows players to swap between them.\n */\nclass MiniBaseView : public InteractiveSurface\n{\nprivate:\n\tstatic const int MINI_SIZE = 14;\n\n\tstd::vector<Base*> *_bases;\n\tSurfaceSet *_texture;\n\tsize_t _base, _hoverBase;\n\tUint8 _red, _green, _blue;\npublic:\n\tstatic const size_t MAX_BASES = 8;\n\t/// Creates a new mini base view at the specified position and size.\n\tMiniBaseView(int width, int height, int x = 0, int y = 0);\n\t/// Cleans up the mini base view.\n\t~MiniBaseView();\n\t/// Sets the base list to display.\n\tvoid setBases(std::vector<Base*> *bases);\n\t/// Sets the texture for the mini base view.\n\tvoid setTexture(SurfaceSet *texture);\n\t/// Gets the base the mouse is over.\n\tsize_t getHoveredBase() const;\n\t/// Sets the selected base for the mini base view.\n\tvoid setSelectedBase(size_t base);\n\t/// Draws the mini base view.\n\tvoid draw() override;\n\t/// Special handling for mouse hovers.\n\tvoid mouseOver(Action *action, State *state) override;\n\tvoid setColor(Uint8 color) override;\n\tvoid setSecondaryColor(Uint8 color) override;\n\tvoid setBorderColor(Uint8 color) override;\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/MonthlyCostsState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"MonthlyCostsState.h\"\n#include <sstream>\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Mod/RuleCraft.h\"\n#include \"../Mod/RuleSoldier.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Monthly Costs screen.\n * @param game Pointer to the core game.\n * @param base Pointer to the base to get info from.\n */\nMonthlyCostsState::MonthlyCostsState(Base *base) : _base(base)\n{\n\t// Create objects\n\t_window = new Window(this, 320, 200, 0, 0);\n\t_btnOk = new TextButton(300, 20, 10, 170);\n\t_txtTitle = new Text(310, 17, 5, 12);\n\t_txtCost = new Text(80, 9, 115, 32);\n\t_txtQuantity = new Text(55, 9, 195, 32);\n\t_txtTotal = new Text(60, 9, 249, 32);\n\t_txtRental = new Text(150, 9, 10, 40);\n\t_txtSalaries = new Text(150, 9, 10, 80);\n\t_txtIncome = new Text(150, 9, 10, 146);\n\t_txtMaintenance = new Text(150, 9, 10, 154);\n\t_lstCrafts = new TextList(288, 32, 10, 48);\n\t_lstSalaries = new TextList(288, 40, 10, 88);\n\t_lstMaintenance = new TextList(300, 9, 10, 128);\n\t_lstTotal = new TextList(100, 9, 205, 150);\n\n\t// Set palette\n\tsetInterface(\"costsInfo\");\n\n\tadd(_window, \"window\", \"costsInfo\");\n\tadd(_btnOk, \"button\", \"costsInfo\");\n\tadd(_txtTitle, \"text1\", \"costsInfo\");\n\tadd(_txtCost, \"text1\", \"costsInfo\");\n\tadd(_txtQuantity, \"text1\", \"costsInfo\");\n\tadd(_txtTotal, \"text1\", \"costsInfo\");\n\tadd(_txtRental, \"text1\", \"costsInfo\");\n\tadd(_lstCrafts, \"list\", \"costsInfo\");\n\tadd(_txtSalaries, \"text1\", \"costsInfo\");\n\tadd(_lstSalaries, \"list\", \"costsInfo\");\n\tadd(_lstMaintenance, \"text1\", \"costsInfo\");\n\tadd(_txtIncome, \"list\", \"costsInfo\");\n\tadd(_txtMaintenance, \"list\", \"costsInfo\");\n\tadd(_lstTotal, \"text2\", \"costsInfo\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"costsInfo\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&MonthlyCostsState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&MonthlyCostsState::btnOkClick, Options::keyOk);\n\t_btnOk->onKeyboardPress((ActionHandler)&MonthlyCostsState::btnOkClick, Options::keyCancel);\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_MONTHLY_COSTS\"));\n\n\t_txtCost->setText(tr(\"STR_COST_PER_UNIT\"));\n\n\t_txtQuantity->setText(tr(\"STR_QUANTITY\"));\n\n\t_txtTotal->setText(tr(\"STR_TOTAL\"));\n\n\t_txtRental->setText(tr(\"STR_CRAFT_RENTAL\"));\n\n\t_txtSalaries->setText(tr(\"STR_SALARIES\"));\n\n\tstd::ostringstream ss;\n\tss << tr(\"STR_INCOME\") << \"=\" << Unicode::formatFunding(_game->getSavedGame()->getCountryFunding());\n\t_txtIncome->setText(ss.str());\n\n\tstd::ostringstream ss2;\n\tss2 << tr(\"STR_MAINTENANCE\") << \"=\" << Unicode::formatFunding(_game->getSavedGame()->getBaseMaintenance());\n\t_txtMaintenance->setText(ss2.str());\n\n\t_lstCrafts->setColumns(4, 125, 70, 44, 50);\n\t_lstCrafts->setDot(true);\n\n\tfor (auto& craftType : _game->getMod()->getCraftsList())\n\t{\n\t\tRuleCraft *craft = _game->getMod()->getCraft(craftType);\n\t\tif (craft->getRentCost() != 0 && _game->getSavedGame()->isResearched(craft->getRequirements()))\n\t\t{\n\t\t\tint count = _base->getCraftCount(craft);\n\t\t\tif (count > 0 || craft->forceShowInMonthlyCosts())\n\t\t\t{\n\t\t\t\tstd::ostringstream ss3;\n\t\t\t\tss3 << count;\n\t\t\t\t_lstCrafts->addRow(4, tr(craftType).c_str(), Unicode::formatFunding(craft->getRentCost()).c_str(), ss3.str().c_str(), Unicode::formatFunding(count * craft->getRentCost()).c_str());\n\t\t\t}\n\t\t}\n\t}\n\n\t_lstSalaries->setColumns(4, 125, 70, 44, 50);\n\t_lstSalaries->setDot(true);\n\n\tauto& soldierTypes = _game->getMod()->getSoldiersList();\n\n\tbool dynamicSalaries = false;\n\tfor (auto& soldierType : soldierTypes)\n\t{\n\t\tif (_game->getMod()->getSoldier(soldierType)->isSalaryDynamic())\n\t\t{\n\t\t\tdynamicSalaries = true;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (!dynamicSalaries)\n\t{\n\t\t// vanilla\n\t\tfor (auto& soldierType : soldierTypes)\n\t\t{\n\t\t\tRuleSoldier *soldier = _game->getMod()->getSoldier(soldierType);\n\t\t\tif (soldier->getSalaryCost(0) != 0 && _game->getSavedGame()->isResearched(soldier->getRequirements()))\n\t\t\t{\n\t\t\t\tstd::pair<int, int> info = _base->getSoldierCountAndSalary(soldierType);\n\t\t\t\tstd::ostringstream ss4;\n\t\t\t\tss4 << info.first;\n\t\t\t\tstd::string name = soldierType;\n\t\t\t\tif (soldierTypes.size() == 1)\n\t\t\t\t{\n\t\t\t\t\tname = \"STR_SOLDIERS\";\n\t\t\t\t}\n\t\t\t\tstd::string costPerUnit = Unicode::formatFunding(soldier->getSalaryCost(0)); // 0 = default rookie salary\n\t\t\t\tif (info.first > 0 || soldierTypes.size() == 1)\n\t\t\t\t{\n\t\t\t\t\t_lstSalaries->addRow(4, tr(name).c_str(), costPerUnit.c_str(), ss4.str().c_str(), Unicode::formatFunding(info.second).c_str());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\t// one or more soldier types with *different* salaries per rank\n\t\tstd::ostringstream ss4;\n\t\tint count = 0;\n\t\tint salary = 0;\n\t\tfor (auto& soldierType : soldierTypes)\n\t\t{\n\t\t\tstd::pair<int, int> info = _base->getSoldierCountAndSalary(soldierType);\n\t\t\tcount += info.first;\n\t\t\tsalary += info.second;\n\t\t}\n\t\tss4 << count;\n\t\t_lstSalaries->addRow(4, tr(\"STR_SOLDIERS\").c_str(), \"\", ss4.str().c_str(), Unicode::formatFunding(salary).c_str());\n\t}\n\tstd::ostringstream ss5;\n\tss5 << _base->getTotalEngineers();\n\t_lstSalaries->addRow(4, tr(\"STR_ENGINEERS\").c_str(), Unicode::formatFunding(_game->getMod()->getEngineerCost()).c_str(), ss5.str().c_str(), Unicode::formatFunding(_base->getTotalEngineers() * _game->getMod()->getEngineerCost()).c_str());\n\tstd::ostringstream ss6;\n\tss6 << _base->getTotalScientists();\n\t_lstSalaries->addRow(4, tr(\"STR_SCIENTISTS\").c_str(), Unicode::formatFunding(_game->getMod()->getScientistCost()).c_str(), ss6.str().c_str(), Unicode::formatFunding(_base->getTotalScientists() * _game->getMod()->getScientistCost()).c_str());\n\tstd::ostringstream ss6b;\n\tint staffCount, inventoryCount;\n\tint totalOtherCost = _base->getTotalOtherStaffAndInventoryCost(staffCount, inventoryCount);\n\tss6b << staffCount << \"/\" << inventoryCount;\n\t_lstSalaries->addRow(4, tr(\"STR_OTHER_EMPLOYEES\").c_str(), \"\", ss6b.str().c_str(), Unicode::formatFunding(totalOtherCost).c_str());\n\n\t_lstMaintenance->setColumns(2, 239, 60);\n\t_lstMaintenance->setDot(true);\n\tstd::ostringstream ss7;\n\tss7 << Unicode::TOK_COLOR_FLIP << Unicode::formatFunding(_base->getFacilityMaintenance());\n\t_lstMaintenance->addRow(2, tr(\"STR_BASE_MAINTENANCE\").c_str(), ss7.str().c_str());\n\n\t_lstTotal->setColumns(2, 44, 55);\n\t_lstTotal->setDot(true);\n\t_lstTotal->addRow(2, tr(\"STR_TOTAL\").c_str(), Unicode::formatFunding(_base->getMonthlyMaintenace()).c_str());\n}\n\n/**\n *\n */\nMonthlyCostsState::~MonthlyCostsState()\n{\n\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid MonthlyCostsState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/MonthlyCostsState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass Base;\nclass TextButton;\nclass Window;\nclass Text;\nclass TextList;\n\n/**\n * Monthly Costs screen that displays all\n * the maintenance costs of a particular base.\n */\nclass MonthlyCostsState : public State\n{\nprivate:\n\tBase *_base;\n\n\tTextButton *_btnOk;\n\tWindow *_window;\n\tText *_txtTitle, *_txtCost, *_txtQuantity, *_txtTotal, *_txtRental, *_txtSalaries, *_txtIncome, *_txtMaintenance;\n\tTextList *_lstCrafts, *_lstSalaries, *_lstMaintenance, *_lstTotal;\npublic:\n\t/// Creates the Monthly Costs state.\n\tMonthlyCostsState(Base *base);\n\t/// Cleans up the Monthly Costs state.\n\t~MonthlyCostsState();\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/NewManufactureListState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <algorithm>\n#include <locale>\n#include \"NewManufactureListState.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/ToggleTextButton.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextEdit.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Interface/ComboBox.h\"\n#include \"../Engine/CrossPlatform.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleInterface.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"../Mod/RuleManufacture.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/ItemContainer.h\"\n#include \"ManufactureStartState.h\"\n#include \"TechTreeViewerState.h\"\n#include \"../Ufopaedia/Ufopaedia.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the productions list screen.\n * @param game Pointer to the core game.\n * @param base Pointer to the base to get info from.\n */\nNewManufactureListState::NewManufactureListState(Base *base) : _base(base), _showRequirements(false), _refreshCategories(true), _doInit(true), _lstScroll(0)\n{\n\t_screen = false;\n\n\t_window = new Window(this, 320, 156, 0, 22, POPUP_BOTH);\n\t_btnQuickSearch = new TextEdit(this, 48, 9, 10, 35);\n\t_btnOk = new TextButton(148, 16, 164, 154);\n\t_btnShowOnlyNew = new ToggleTextButton(148, 16, 8, 154);\n\t_txtTitle = new Text(320, 17, 0, 30);\n\t_txtItem = new Text(156, 9, 10, 62);\n\t_txtCategory = new Text(130, 9, 166, 62);\n\t_lstManufacture = new TextList(288, 80, 8, 70);\n\t_cbxFilter = new ComboBox(this, 146, 16, 10, 46);\n\t_cbxCategory = new ComboBox(this, 146, 16, 166, 46);\n\n\ttouchComponentsCreate(_txtTitle, true, -1, +22);\n\n\t// Set palette\n\tsetInterface(\"selectNewManufacture\");\n\n\tadd(_window, \"window\", \"selectNewManufacture\");\n\tadd(_btnQuickSearch, \"button\", \"selectNewManufacture\");\n\tadd(_btnOk, \"button\", \"selectNewManufacture\");\n\tadd(_btnShowOnlyNew, \"button\", \"selectNewManufacture\");\n\tadd(_txtTitle, \"text\", \"selectNewManufacture\");\n\tadd(_txtItem, \"text\", \"selectNewManufacture\");\n\tadd(_txtCategory, \"text\", \"selectNewManufacture\");\n\tadd(_lstManufacture, \"list\", \"selectNewManufacture\");\n\tadd(_cbxFilter, \"catBox\", \"selectNewManufacture\");\n\tadd(_cbxCategory, \"catBox\", \"selectNewManufacture\");\n\n\ttouchComponentsAdd(\"button2\", \"selectNewManufacture\", _window);\n\n\t_colorNormal = _lstManufacture->getColor();\n\t_colorNew = Options::oxceHighlightNewTopics ? _lstManufacture->getSecondaryColor() : _colorNormal;\n\t_colorHidden = _game->getMod()->getInterface(\"selectNewManufacture\")->getElement(\"listExtended\")->color;\n\t_colorFacilityRequired = _game->getMod()->getInterface(\"selectNewManufacture\")->getElement(\"listExtended\")->color2;\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"selectNewManufacture\");\n\n\ttouchComponentsConfigure();\n\n\t_txtTitle->setText(tr(\"STR_PRODUCTION_ITEMS\"));\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\n\t_txtItem->setText(tr(\"STR_ITEM\"));\n\n\t_txtCategory->setText(tr(\"STR_CATEGORY\"));\n\n\t_lstManufacture->setColumns(3, 156, 120, 10);\n\t_lstManufacture->setSelectable(true);\n\t_lstManufacture->setBackground(_window);\n\t_lstManufacture->setMargin(2);\n\t_lstManufacture->onMouseClick((ActionHandler)&NewManufactureListState::lstProdClick, SDL_BUTTON_LEFT);\n\t_lstManufacture->onMouseClick((ActionHandler)&NewManufactureListState::lstProdClick, SDL_BUTTON_RIGHT);\n\t_lstManufacture->onMouseClick((ActionHandler)&NewManufactureListState::lstProdClick, SDL_BUTTON_MIDDLE);\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&NewManufactureListState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&NewManufactureListState::btnOkClick, Options::keyCancel);\n\t_btnOk->onKeyboardPress((ActionHandler)&NewManufactureListState::btnMarkAllAsSeenClick, Options::keyMarkAllAsSeen);\n\n\t_btnShowOnlyNew->setText(tr(\"STR_SHOW_ONLY_NEW\"));\n\t_btnShowOnlyNew->onMouseClick((ActionHandler)&NewManufactureListState::btnShowOnlyNewClick);\n\n\tstd::vector<std::string> filterOptions;\n\tfilterOptions.push_back(\"STR_FILTER_DEFAULT\");\n\tfilterOptions.push_back(\"STR_FILTER_DEFAULT_SUPPLIES_OK\");\n\tfilterOptions.push_back(\"STR_FILTER_DEFAULT_NO_SUPPLIES\");\n\tfilterOptions.push_back(\"STR_FILTER_FACILITY_REQUIRED\");\n\tfilterOptions.push_back(\"STR_FILTER_HIDDEN\");\n\t_cbxFilter->setOptions(filterOptions, true);\n\tif (Options::oxceManufactureFilterSuppliesOK)\n\t{\n\t\t_cbxFilter->setSelected(MANU_FILTER_DEFAULT_SUPPLIES_OK);\n\t}\n\t_cbxFilter->onChange((ActionHandler)&NewManufactureListState::cbxFilterChange);\n\n\t_catStrings.push_back(\"STR_ALL_ITEMS\");\n\t_cbxCategory->setOptions(_catStrings, true);\n\n\t_btnQuickSearch->setText(\"\"); // redraw\n\t_btnQuickSearch->onEnter((ActionHandler)&NewManufactureListState::btnQuickSearchApply);\n\t_btnQuickSearch->setVisible(Options::oxceQuickSearchButton);\n\n\t_btnOk->onKeyboardRelease((ActionHandler)&NewManufactureListState::btnQuickSearchToggle, Options::keyToggleQuickSearch);\n}\n\n/**\n * Initializes state (fills list of possible productions).\n */\nvoid NewManufactureListState::init()\n{\n\tState::init();\n\n\tif (_doInit)\n\t{\n\t\tfillProductionList(_refreshCategories);\n\t}\n\t_doInit = true;\n\t_refreshCategories = true;\n\n\ttouchComponentsRefresh();\n}\n\n/**\n * Returns to the previous screen.\n * @param action A pointer to an Action.\n */\nvoid NewManufactureListState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * LRM-click routing.\n * @param action A pointer to an Action.\n */\nvoid NewManufactureListState::lstProdClick(Action* action)\n{\n\tif (_game->isLeftClick(action, true))\n\t{\n\t\tlstProdClickLeft(action);\n\t}\n\telse if (_game->isRightClick(action, true))\n\t{\n\t\tlstProdClickRight(action);\n\t}\n\telse if (_game->isMiddleClick(action, true))\n\t{\n\t\tlstProdClickMiddle(action);\n\t}\n}\n\n/**\n * Opens the Production settings screen.\n * @param action A pointer to an Action.\n */\nvoid NewManufactureListState::lstProdClickLeft(Action *)\n{\n\t_lstScroll = _lstManufacture->getScroll();\n\n\tManufacturingFilterType basicFilter = (ManufacturingFilterType)(_cbxFilter->getSelected());\n\tif (basicFilter == MANU_FILTER_FACILITY_REQUIRED)\n\t\treturn;\n\n\tRuleManufacture* rule = _game->getMod()->getManufacture(_displayedStrings[_lstManufacture->getSelectedRow()]);\n\n\t// check and display error messages only further down the chain\n\t_refreshCategories = false;\n\t_game->pushState(new ManufactureStartState(_base, rule));\n}\n\n/**\n* Changes the status (new -> normal -> hidden -> new).\n* @param action A pointer to an Action.\n*/\nvoid NewManufactureListState::lstProdClickRight(Action *)\n{\n\tManufacturingFilterType basicFilter = (ManufacturingFilterType)(_cbxFilter->getSelected());\n\tif (basicFilter == MANU_FILTER_FACILITY_REQUIRED)\n\t{\n\t\t// display either category or requirements\n\t\t_showRequirements = !_showRequirements;\n\t\tRuleBaseFacilityFunctions baseFunc = _base->getProvidedBaseFunc({});\n\n\t\tfor (size_t row = 0; row < _lstManufacture->getTexts(); ++row)\n\t\t{\n\t\t\tRuleManufacture *info = _game->getMod()->getManufacture(_displayedStrings[row]);\n\t\t\tif (info)\n\t\t\t{\n\t\t\t\tif (_showRequirements)\n\t\t\t\t{\n\t\t\t\t\tstd::ostringstream ss;\n\t\t\t\t\tint count = 0;\n\t\t\t\t\tstd::vector<std::string> missed = _game->getMod()->getBaseFunctionNames(~baseFunc & info->getRequireBaseFunc());\n\t\t\t\t\tfor (const auto& name : missed)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (count > 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tss << \", \";\n\t\t\t\t\t\t}\n\t\t\t\t\t\tss << tr(name);\n\t\t\t\t\t\tcount++;\n\t\t\t\t\t}\n\t\t\t\t\t_lstManufacture->setCellText(row, 1, ss.str().c_str());\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t_lstManufacture->setCellText(row, 1, tr(info->getCategory()));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\t// change status\n\t\tconst std::string rule = _displayedStrings[_lstManufacture->getSelectedRow()];\n\t\tint oldState = _game->getSavedGame()->getManufactureRuleStatus(rule);\n\t\tint newState = (oldState + 1) % RuleManufacture::MANU_STATUSES;\n\t\tif (!Options::oxceHighlightNewTopics)\n\t\t{\n\t\t\t// only switch between hidden and not hidden\n\t\t\tnewState = (oldState == RuleManufacture::MANU_STATUS_HIDDEN) ? RuleManufacture::MANU_STATUS_NORMAL : RuleManufacture::MANU_STATUS_HIDDEN;\n\t\t}\n\t\t_game->getSavedGame()->setManufactureRuleStatus(rule, newState);\n\n\t\tif (newState == RuleManufacture::MANU_STATUS_HIDDEN)\n\t\t{\n\t\t\t_lstManufacture->setRowColor(_lstManufacture->getSelectedRow(), _colorHidden);\n\t\t}\n\t\telse if (newState == RuleManufacture::MANU_STATUS_NEW)\n\t\t{\n\t\t\t_lstManufacture->setRowColor(_lstManufacture->getSelectedRow(), _colorNew);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_lstManufacture->setRowColor(_lstManufacture->getSelectedRow(), _colorNormal);\n\t\t}\n\t}\n}\n\n/**\n* Opens the TechTreeViewer for the corresponding topic.\n* @param action Pointer to an action.\n*/\nvoid NewManufactureListState::lstProdClickMiddle(Action *)\n{\n\t_doInit = false;\n\n\tstd::string articleId = _displayedStrings[_lstManufacture->getSelectedRow()];\n\tif (_game->isCtrlPressed(true))\n\t{\n\t\tUfopaedia::openArticle(_game, articleId);\n\t}\n\telse\n\t{\n\t\tconst RuleManufacture* selectedTopic = _game->getMod()->getManufacture(articleId);\n\t\t_game->pushState(new TechTreeViewerState(0, selectedTopic));\n\t}\n}\n\n/**\n* Updates the production list to match the basic filter\n*/\n\nvoid NewManufactureListState::cbxFilterChange(Action *)\n{\n\tfillProductionList(true);\n}\n\n/**\n * Updates the production list to match the category filter\n */\n\nvoid NewManufactureListState::cbxCategoryChange(Action *)\n{\n\tfillProductionList(false);\n}\n\n/**\n* Quick search toggle.\n* @param action Pointer to an action.\n*/\nvoid NewManufactureListState::btnQuickSearchToggle(Action *action)\n{\n\tif (_btnQuickSearch->getVisible())\n\t{\n\t\t_btnQuickSearch->setText(\"\");\n\t\t_btnQuickSearch->setVisible(false);\n\t\tbtnQuickSearchApply(action);\n\t}\n\telse\n\t{\n\t\t_btnQuickSearch->setVisible(true);\n\t\t_btnQuickSearch->setFocus(true);\n\t}\n}\n\n/**\n* Quick search.\n* @param action Pointer to an action.\n*/\nvoid NewManufactureListState::btnQuickSearchApply(Action *)\n{\n\tfillProductionList(false);\n}\n\n/**\n* Filter to display only new items.\n* @param action Pointer to an action.\n*/\nvoid NewManufactureListState::btnShowOnlyNewClick(Action *)\n{\n\tfillProductionList(false);\n}\n\n/**\n* Marks all items as seen\n* @param action Pointer to an action.\n*/\nvoid NewManufactureListState::btnMarkAllAsSeenClick(Action *)\n{\n\tManufacturingFilterType basicFilter = (ManufacturingFilterType)(_cbxFilter->getSelected());\n\tif (basicFilter == MANU_FILTER_FACILITY_REQUIRED)\n\t\treturn;\n\n\tfor (const auto& name : _displayedStrings)\n\t{\n\t\t// mark all (new) manufacture items as normal\n\t\tif (_game->getSavedGame()->getManufactureRuleStatus(name) != RuleManufacture::MANU_STATUS_HIDDEN)\n\t\t{\n\t\t\t_game->getSavedGame()->setManufactureRuleStatus(name, RuleManufacture::MANU_STATUS_NORMAL);\n\t\t}\n\t}\n\n\tfillProductionList(false);\n}\n\n/**\n * Fills the list of possible productions.\n */\nvoid NewManufactureListState::fillProductionList(bool refreshCategories)\n{\n\tstd::string searchString = _btnQuickSearch->getText();\n\tUnicode::upperCase(searchString);\n\n\tif (refreshCategories)\n\t{\n\t\t_cbxCategory->onChange(0);\n\t\t_cbxCategory->setSelected(0);\n\t}\n\n\t_showRequirements = false;\n\n\t_lstManufacture->clearList();\n\t_possibleProductions.clear();\n\tManufacturingFilterType basicFilter = (ManufacturingFilterType)(_cbxFilter->getSelected());\n\t_game->getSavedGame()->getAvailableProductions(_possibleProductions, _game->getMod(), _base, basicFilter);\n\t_displayedStrings.clear();\n\n\tItemContainer * itemContainer (_base->getStorageItems());\n\tint row = 0;\n\tbool hasUnseen = false;\n\tfor (const auto* manuf : _possibleProductions)\n\t{\n\t\tif ((manuf->getCategory() == _catStrings[_cbxCategory->getSelected()]) || (_catStrings[_cbxCategory->getSelected()] == \"STR_ALL_ITEMS\"))\n\t\t{\n\t\t\t// filter\n\t\t\tbool isHidden = _game->getSavedGame()->getManufactureRuleStatus(manuf->getName()) == RuleManufacture::MANU_STATUS_HIDDEN;\n\t\t\tif (basicFilter == MANU_FILTER_DEFAULT && isHidden)\n\t\t\t\tcontinue;\n\t\t\tif (basicFilter == MANU_FILTER_DEFAULT_SUPPLIES_OK && isHidden)\n\t\t\t\tcontinue;\n\t\t\tif (basicFilter == MANU_FILTER_DEFAULT_NO_SUPPLIES && isHidden)\n\t\t\t\tcontinue;\n\t\t\tif (basicFilter == MANU_FILTER_HIDDEN && !isHidden)\n\t\t\t\tcontinue;\n\n\t\t\tbool isNew = _game->getSavedGame()->getManufactureRuleStatus(manuf->getName()) == RuleManufacture::MANU_STATUS_NEW;\n\t\t\tif (_btnShowOnlyNew->getPressed())\n\t\t\t{\n\t\t\t\tif (!isNew)\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// quick search\n\t\t\tif (!searchString.empty())\n\t\t\t{\n\t\t\t\tstd::string projectName = tr(manuf->getName());\n\t\t\t\tUnicode::upperCase(projectName);\n\t\t\t\tif (projectName.find(searchString) == std::string::npos)\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// supplies calculation\n\t\t\tint productionPossible = 10; // max\n\t\t\tif (manuf->getManufactureCost() > 0)\n\t\t\t{\n\t\t\t\tint64_t byFunds = _game->getSavedGame()->getFunds() / manuf->getManufactureCost();\n\t\t\t\tif (byFunds < 10LL)\n\t\t\t\t{\n\t\t\t\t\tint byFundsInt = (int)byFunds;\n\t\t\t\t\tproductionPossible = std::min(productionPossible, byFundsInt);\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (auto& iter : manuf->getRequiredItems())\n\t\t\t{\n\t\t\t\tproductionPossible = std::min(productionPossible, itemContainer->getItem(iter.first) / iter.second);\n\t\t\t}\n\t\t\tstd::ostringstream ss;\n\t\t\tif (productionPossible <= 0)\n\t\t\t{\n\t\t\t\tif (basicFilter == MANU_FILTER_DEFAULT_SUPPLIES_OK)\n\t\t\t\t\tcontinue;\n\t\t\t\tss << '-';\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (basicFilter == MANU_FILTER_DEFAULT_NO_SUPPLIES)\n\t\t\t\t\tcontinue;\n\t\t\t\tif (productionPossible < 10)\n\t\t\t\t{\n\t\t\t\t\tss << productionPossible;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tss << '+';\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t_lstManufacture->addRow(3, tr(manuf->getName()).c_str(), tr(manuf->getCategory()).c_str(), ss.str().c_str());\n\t\t\t_displayedStrings.push_back(manuf->getName().c_str());\n\n\t\t\t// colors\n\t\t\tif (basicFilter == MANU_FILTER_FACILITY_REQUIRED)\n\t\t\t{\n\t\t\t\t_lstManufacture->setRowColor(row, _colorFacilityRequired);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (isHidden)\n\t\t\t\t{\n\t\t\t\t\t_lstManufacture->setRowColor(row, _colorHidden);\n\t\t\t\t}\n\t\t\t\telse if (isNew)\n\t\t\t\t{\n\t\t\t\t\t_lstManufacture->setRowColor(row, _colorNew);\n\t\t\t\t\thasUnseen = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\trow++;\n\t\t}\n\t}\n\n\tstd::string label = tr(\"STR_SHOW_ONLY_NEW\");\n\t_btnShowOnlyNew->setText((hasUnseen ? \"* \" : \"\") + label);\n\tif (_lstScroll > 0)\n\t{\n\t\t_lstManufacture->scrollTo(_lstScroll);\n\t\t_lstScroll = 0;\n\t}\n\n\tif (refreshCategories)\n\t{\n\t\t_catStrings.clear();\n\t\t_catStrings.push_back(\"STR_ALL_ITEMS\");\n\n\t\tfor (size_t r = 0; r < _lstManufacture->getTexts(); ++r)\n\t\t{\n\t\t\tRuleManufacture *info = _game->getMod()->getManufacture(_displayedStrings[r]);\n\t\t\tif (info)\n\t\t\t{\n\t\t\t\tbool addCategory = true;\n\t\t\t\tfor (size_t x = 0; x < _catStrings.size(); ++x)\n\t\t\t\t{\n\t\t\t\t\tif (info->getCategory().c_str() == _catStrings[x])\n\t\t\t\t\t{\n\t\t\t\t\t\taddCategory = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (addCategory)\n\t\t\t\t{\n\t\t\t\t\t_catStrings.push_back(info->getCategory().c_str());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t_cbxCategory->setOptions(_catStrings, true);\n\t\t_cbxCategory->onChange((ActionHandler)&NewManufactureListState::cbxCategoryChange);\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/NewManufactureListState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/TouchState.h\"\n#include <vector>\n\nnamespace OpenXcom\n{\n\nclass Base;\nclass TextButton;\nclass ToggleTextButton;\nclass Window;\nclass Text;\nclass TextEdit;\nclass TextList;\nclass RuleManufacture;\nclass ComboBox;\n\n/**\n * Screen which list possible productions.\n */\nclass NewManufactureListState : public TouchState\n{\nprivate:\n\tBase *_base;\n\tbool _showRequirements, _refreshCategories, _doInit;\n\tTextButton *_btnOk;\n\tToggleTextButton *_btnShowOnlyNew;\n\tTextEdit *_btnQuickSearch;\n\tWindow *_window;\n\tText *_txtTitle, *_txtItem, *_txtCategory;\n\tTextList *_lstManufacture;\n\tsize_t _lstScroll;\n\tComboBox *_cbxCategory;\n\tComboBox *_cbxFilter;\n\tstd::vector<RuleManufacture *> _possibleProductions;\n\tstd::vector<std::string> _catStrings;\n\tstd::vector<std::string> _displayedStrings;\n\tUint8 _colorNormal, _colorNew;\n\tUint8 _colorHidden, _colorFacilityRequired;\n\npublic:\n\t/// Creates the state.\n\tNewManufactureListState(Base *base);\n\t/// Initializes state.\n\tvoid init() override;\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action * action);\n\t/// Handlers for Quick Search.\n\tvoid btnQuickSearchToggle(Action *action);\n\tvoid btnQuickSearchApply(Action *action);\n\t/// Handlers for clicking on the list.\n\tvoid lstProdClick(Action* action);\n\tvoid lstProdClickLeft (Action * action);\n\tvoid lstProdClickRight(Action * action);\n\tvoid lstProdClickMiddle(Action * action);\n\t/// Handler for changing the category filter\n\tvoid cbxCategoryChange (Action * action);\n\t/// Handler for changing the basic filter\n\tvoid cbxFilterChange(Action * action);\n\t/// Handler for clicking the [Show Only New] button.\n\tvoid btnShowOnlyNewClick(Action *action);\n\t/// Handler for clicking the [Mark All As Seen] button.\n\tvoid btnMarkAllAsSeenClick(Action *action);\n\t/// Fills the list of possible productions.\n\tvoid fillProductionList(bool refreshCategories);\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/NewResearchListState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <locale>\n#include \"NewResearchListState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/ComboBox.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/ToggleTextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextEdit.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Mod/RuleInterface.h\"\n#include \"../Mod/RuleResearch.h\"\n#include \"ResearchInfoState.h\"\n#include \"TechTreeViewerState.h\"\n\nnamespace OpenXcom\n{\n/**\n * Initializes all the elements in the Research list screen.\n * @param game Pointer to the core game.\n * @param base Pointer to the base to get info from.\n * @param sortByCost Should the list be sorted by cost or listOrder?\n */\nNewResearchListState::NewResearchListState(Base *base, bool sortByCost) : _base(base), _sortByCost(sortByCost), _lstScroll(0)\n{\n\tif (Options::isPasswordCorrect())\n\t{\n\t\t_sortByCost = !_sortByCost;\n\t}\n\n\t_screen = false;\n\n\t_window = new Window(this, 230, 140, 45, 30, POPUP_BOTH);\n\t_btnQuickSearch = new TextEdit(this, 48, 9, 53, 38);\n\t_btnOK = new TextButton(103, 16, 164, 146);\n\t_cbxSort = new ComboBox(this, 103, 16, 53, 146, true);\n\t_btnShowOnlyNew = new ToggleTextButton(103, 16, 53, 146);\n\t_txtTitle = new Text(214, 16, 53, 38);\n\t_lstResearch = new TextList(198, 88, 53, 54);\n\n\ttouchComponentsCreate(_txtTitle, true, -45, +30);\n\n\t// Set palette\n\tsetInterface(\"selectNewResearch\");\n\n\tadd(_window, \"window\", \"selectNewResearch\");\n\tadd(_btnQuickSearch, \"button\", \"selectNewResearch\");\n\tadd(_btnOK, \"button\", \"selectNewResearch\");\n\tadd(_btnShowOnlyNew, \"button\", \"selectNewResearch\");\n\tadd(_txtTitle, \"text\", \"selectNewResearch\");\n\tadd(_lstResearch, \"list\", \"selectNewResearch\");\n\tadd(_cbxSort, \"button\", \"selectNewResearch\");\n\n\ttouchComponentsAdd(\"button2\", \"selectNewResearch\", _window);\n\n\t_colorNormal = _lstResearch->getColor();\n\t_colorNew = Options::oxceHighlightNewTopics ? _lstResearch->getSecondaryColor() : _colorNormal;\n\t_colorHidden = _game->getMod()->getInterface(\"selectNewResearch\")->getElement(\"listExtended\")->color;\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"selectNewResearch\");\n\n\ttouchComponentsConfigure();\n\n\t_btnOK->setText(tr(\"STR_OK\"));\n\t_btnOK->onMouseClick((ActionHandler)&NewResearchListState::btnOKClick);\n\t_btnOK->onKeyboardPress((ActionHandler)&NewResearchListState::btnOKClick, Options::keyCancel);\n\t_btnOK->onKeyboardPress((ActionHandler)&NewResearchListState::btnMarkAllAsSeenClick, Options::keyMarkAllAsSeen);\n\n\t_isSortingEnabled = _game->getMod()->getEnableNewResearchSorting();\n\tif (_isSortingEnabled)\n\t{\n\t\t_btnShowOnlyNew->setVisible(false);\n\t\tstd::vector<std::string> sortOptions;\n\t\tsortOptions.push_back(\"STR_SORT_DEFAULT\");\n\t\tsortOptions.push_back(\"STR_SORT_BY_COST\");\n\t\tsortOptions.push_back(\"STR_SORT_BY_NAME\");\n\t\tsortOptions.push_back(\"STR_SHOW_ONLY_NEW\"); // this is a filter, replacement for the hidden \"Show Only New\" toggle button\n\t\tsortOptions.push_back(\"STR_FILTER_HIDDEN\"); // this is a filter\n\t\t_cbxSort->setOptions(sortOptions, true);\n\t\tif (_sortByCost)\n\t\t{\n\t\t\t_cbxSort->setSelected(1);\n\t\t}\n\t\t_cbxSort->onChange((ActionHandler)&NewResearchListState::cbxSortChange);\n\t}\n\telse\n\t{\n\t\t_cbxSort->setVisible(false);\n\t\t_btnShowOnlyNew->setText(tr(\"STR_SHOW_ONLY_NEW\"));\n\t\t_btnShowOnlyNew->onMouseClick((ActionHandler)&NewResearchListState::btnShowOnlyNewClick);\n\t}\n\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_NEW_RESEARCH_PROJECTS\"));\n\n\t_lstResearch->setColumns(1, 190);\n\t_lstResearch->setSelectable(true);\n\t_lstResearch->setBackground(_window);\n\t_lstResearch->setMargin(8);\n\t_lstResearch->setAlign(ALIGN_CENTER);\n\t_lstResearch->onMouseClick((ActionHandler)&NewResearchListState::onClick, SDL_BUTTON_LEFT);\n\t_lstResearch->onMouseClick((ActionHandler)&NewResearchListState::onClick, SDL_BUTTON_RIGHT);\n\t_lstResearch->onMouseClick((ActionHandler)&NewResearchListState::onClick, SDL_BUTTON_MIDDLE);\n\n\t_btnQuickSearch->setText(\"\"); // redraw\n\t_btnQuickSearch->onEnter((ActionHandler)&NewResearchListState::btnQuickSearchApply);\n\t_btnQuickSearch->setVisible(Options::oxceQuickSearchButton);\n\n\t_btnOK->onKeyboardRelease((ActionHandler)&NewResearchListState::btnQuickSearchToggle, Options::keyToggleQuickSearch);\n}\n\n/**\n * Initializes the screen (fills the list).\n */\nvoid NewResearchListState::init()\n{\n\tState::init();\n\tfillProjectList(false);\n\n\ttouchComponentsRefresh();\n}\n\n/**\n * LRM-click routing.\n * @param action A pointer to an Action.\n */\nvoid NewResearchListState::onClick(Action* action)\n{\n\tif (_game->isLeftClick(action, true))\n\t{\n\t\tonSelectProject(action);\n\t}\n\telse if (_game->isRightClick(action, true))\n\t{\n\t\tonToggleProjectStatus(action);\n\t}\n\telse if (_game->isMiddleClick(action, true))\n\t{\n\t\tonOpenTechTreeViewer(action);\n\t}\n}\n\n/**\n * Selects the RuleResearch to work on.\n * @param action Pointer to an action.\n */\nvoid NewResearchListState::onSelectProject(Action *)\n{\n\t_lstScroll = _lstResearch->getScroll();\n\t_game->pushState(new ResearchInfoState(_base, _projects[_lstResearch->getSelectedRow()]));\n}\n\n/**\n* Selects the RuleResearch to work on.\n* @param action Pointer to an action.\n*/\nvoid NewResearchListState::onToggleProjectStatus(Action *)\n{\n\tif (!Options::oxceHighlightNewTopics && !_isSortingEnabled)\n\t{\n\t\t// there are no statuses to toggle\n\t\treturn;\n\t}\n\n\t// change status\n\tconst std::string& rule = _projects[_lstResearch->getSelectedRow()]->getName();\n\tint oldState = _game->getSavedGame()->getResearchRuleStatus(rule);\n\tint newState = RuleResearch::RESEARCH_STATUS_NEW;\n\n\tif (oldState == RuleResearch::RESEARCH_STATUS_NEW)\n\t{\n\t\tnewState = Options::oxceHighlightNewTopics ? RuleResearch::RESEARCH_STATUS_NORMAL : RuleResearch::RESEARCH_STATUS_HIDDEN;\n\t}\n\telse if (oldState == RuleResearch::RESEARCH_STATUS_NORMAL)\n\t{\n\t\tnewState = _isSortingEnabled ? RuleResearch::RESEARCH_STATUS_HIDDEN : RuleResearch::RESEARCH_STATUS_NEW;\n\t}\n\n\t_game->getSavedGame()->setResearchRuleStatus(rule, newState);\n\n\tif (newState == RuleResearch::RESEARCH_STATUS_HIDDEN)\n\t{\n\t\t_lstResearch->setRowColor(_lstResearch->getSelectedRow(), _colorHidden);\n\t}\n\telse if (newState == RuleResearch::RESEARCH_STATUS_NEW)\n\t{\n\t\t_lstResearch->setRowColor(_lstResearch->getSelectedRow(), _colorNew);\n\t}\n\telse\n\t{\n\t\t_lstResearch->setRowColor(_lstResearch->getSelectedRow(), _colorNormal);\n\t}\n}\n\n/**\n* Opens the TechTreeViewer for the corresponding topic.\n* @param action Pointer to an action.\n*/\nvoid NewResearchListState::onOpenTechTreeViewer(Action *)\n{\n\t_lstScroll = _lstResearch->getScroll();\n\tconst RuleResearch *selectedTopic = _projects[_lstResearch->getSelectedRow()];\n\t_game->pushState(new TechTreeViewerState(selectedTopic, 0));\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid NewResearchListState::btnOKClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n* Quick search toggle.\n* @param action Pointer to an action.\n*/\nvoid NewResearchListState::btnQuickSearchToggle(Action *action)\n{\n\tif (_btnQuickSearch->getVisible())\n\t{\n\t\t_btnQuickSearch->setText(\"\");\n\t\t_btnQuickSearch->setVisible(false);\n\t\tbtnQuickSearchApply(action);\n\t}\n\telse\n\t{\n\t\t_btnQuickSearch->setVisible(true);\n\t\t_btnQuickSearch->setFocus(true);\n\t}\n}\n\n/**\n* Quick search.\n* @param action Pointer to an action.\n*/\nvoid NewResearchListState::btnQuickSearchApply(Action *)\n{\n\tfillProjectList(false);\n}\n\n/**\n * Updates the research list based on the selected option.\n */\nvoid NewResearchListState::cbxSortChange(Action *)\n{\n\tfillProjectList(false);\n}\n\n/**\n* Filter to display only new items.\n* @param action Pointer to an action.\n*/\nvoid NewResearchListState::btnShowOnlyNewClick(Action *)\n{\n\tfillProjectList(false);\n}\n\n/**\n * Marks all items as seen\n * @param action Pointer to an action.\n */\nvoid NewResearchListState::btnMarkAllAsSeenClick(Action *)\n{\n\tfillProjectList(true);\n}\n\n/**\n * Fills the list with possible ResearchProjects.\n */\nvoid NewResearchListState::fillProjectList(bool markAllAsSeen)\n{\n\tstd::string searchString = _btnQuickSearch->getText();\n\tUnicode::upperCase(searchString);\n\n\t_projects.clear();\n\t_lstResearch->clearList();\n\t// Note: this is the *only* place where this method is called with considerDebugMode = true\n\t_game->getSavedGame()->getAvailableResearchProjects(_projects, _game->getMod() , _base, true);\n\tsize_t selectedSort = _cbxSort->getSelected();\n\tif (selectedSort == 1 || (selectedSort == 3 && _sortByCost))\n\t{\n\t\tstd::sort(_projects.begin(), _projects.end(), [&](RuleResearch* a, RuleResearch* b) { return a->getCost() < b->getCost(); });\n\t}\n\telse if (selectedSort == 2)\n\t{\n\t\tstd::sort(_projects.begin(), _projects.end(), [&](RuleResearch* a, RuleResearch* b) { return Unicode::naturalCompare(tr(a->getName()), tr(b->getName())); });\n\t}\n\telse\n\t{\n\t\t// sort by list order\n\t\tstd::sort(_projects.begin(), _projects.end(), [&](RuleResearch* a, RuleResearch* b) { return a->getListOrder() < b->getListOrder(); });\n\t}\n\tauto researchRuleIt = _projects.begin();\n\tRuleResearch* rule = nullptr;\n\tint row = 0;\n\tbool hasUnseen = false;\n\tint ruleStatus = 0;\n\twhile (researchRuleIt != _projects.end())\n\t{\n\t\trule = (*researchRuleIt);\n\t\truleStatus = _game->getSavedGame()->getResearchRuleStatus(rule->getName());\n\n\t\t// filter\n\t\tif (_btnShowOnlyNew->getPressed() || selectedSort == 3)\n\t\t{\n\t\t\tif (ruleStatus != RuleResearch::RESEARCH_STATUS_NEW)\n\t\t\t{\n\t\t\t\tresearchRuleIt = _projects.erase(researchRuleIt);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\telse if (selectedSort <= 2)\n\t\t{\n\t\t\tif (ruleStatus == RuleResearch::RESEARCH_STATUS_HIDDEN)\n\t\t\t{\n\t\t\t\tresearchRuleIt = _projects.erase(researchRuleIt);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\telse if (selectedSort == 4)\n\t\t{\n\t\t\tif (ruleStatus != RuleResearch::RESEARCH_STATUS_HIDDEN)\n\t\t\t{\n\t\t\t\tresearchRuleIt = _projects.erase(researchRuleIt);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\t// quick search\n\t\tif (!searchString.empty())\n\t\t{\n\t\t\tstd::string projectName = tr(rule->getName());\n\t\t\tUnicode::upperCase(projectName);\n\t\t\tif (projectName.find(searchString) == std::string::npos)\n\t\t\t{\n\t\t\t\tresearchRuleIt = _projects.erase(researchRuleIt);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\t// EXPLANATION\n\t\t// -----------\n\t\t// Projects with \"requires\" can only be discovered/researched indirectly\n\t\t//  - this is because we can't reliably determine if they are unlocked or not\n\t\t// Example:\n\t\t//  - Alien Origins + Alien Leader => ALIEN_LEADER_PLUS is discovered\n\t\t//  - Alien Leader + Alien Origins => ALIEN_LEADER_PLUS is NOT discovered (you need to research another alien leader/commander)\n\t\t// If we wanted to allow also direct research of projects with \"requires\",\n\t\t// we would need to implement a slightly more complicated unlocking algorithm\n\t\t// and more importantly, we would need to remember the list of unlocked topics\n\t\t// in the save file (currently this is not done, the list is calculated on-the-fly).\n\t\t// Summary:\n\t\t//  - it would be possible to remove this condition, but more refactoring would be needed\n\t\t//  - for now, handling \"requires\" via zero-cost helpers (e.g. STR_LEADER_PLUS)... is enough\n\t\tif (rule->getRequirements().empty())\n\t\t{\n\t\t\t_lstResearch->addRow(1, tr(rule->getName()).c_str());\n\t\t\tif (markAllAsSeen)\n\t\t\t{\n\t\t\t\t// mark all (filtered) research items as normal\n\t\t\t\t_game->getSavedGame()->setResearchRuleStatus(rule->getName(), RuleResearch::RESEARCH_STATUS_NORMAL);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (ruleStatus == RuleResearch::RESEARCH_STATUS_NEW)\n\t\t\t\t{\n\t\t\t\t\t_lstResearch->setRowColor(row, _colorNew);\n\t\t\t\t\thasUnseen = true;\n\t\t\t\t}\n\t\t\t\telse if (ruleStatus == RuleResearch::RESEARCH_STATUS_HIDDEN)\n\t\t\t\t{\n\t\t\t\t\t_lstResearch->setRowColor(row, _colorHidden);\n\t\t\t\t}\n\t\t\t}\n\t\t\trow++;\n\t\t\t++researchRuleIt;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tresearchRuleIt = _projects.erase(researchRuleIt);\n\t\t}\n\t}\n\n\tstd::string label = tr(\"STR_SHOW_ONLY_NEW\");\n\t_btnShowOnlyNew->setText((hasUnseen ? \"* \" : \"\") + label);\n\tif (_lstScroll > 0)\n\t{\n\t\t_lstResearch->scrollTo(_lstScroll);\n\t\t_lstScroll = 0;\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/NewResearchListState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/TouchState.h\"\n#include <vector>\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass ToggleTextButton;\nclass Window;\nclass Text;\nclass TextEdit;\nclass TextList;\nclass Base;\nclass RuleResearch;\nclass ComboBox;\n\n/**\n * Window which displays possible research projects.\n */\nclass NewResearchListState : public TouchState\n{\nprivate:\n\tBase *_base;\n\tbool _sortByCost;\n\tTextButton *_btnOK;\n\tComboBox *_cbxSort;\n\tToggleTextButton *_btnShowOnlyNew;\n\tTextEdit *_btnQuickSearch;\n\tWindow *_window;\n\tText *_txtTitle;\n\tTextList *_lstResearch;\n\tsize_t _lstScroll;\n\tUint8 _colorNormal, _colorNew, _colorHidden;\n\tbool _isSortingEnabled;\n\tvoid onClick(Action* action);\n\tvoid onSelectProject(Action *action);\n\tvoid onToggleProjectStatus(Action *action);\n\tvoid onOpenTechTreeViewer(Action *action);\n\tstd::vector<RuleResearch *> _projects;\npublic:\n\t/// Creates the New research list state.\n\tNewResearchListState(Base *base, bool sortByCost);\n\t/// Handler for clicking the OK button.\n\tvoid btnOKClick(Action *action);\n\t/// Handlers for Quick Search.\n\tvoid btnQuickSearchToggle(Action *action);\n\tvoid btnQuickSearchApply(Action *action);\n\t/// Handler for changing the sorting.\n\tvoid cbxSortChange(Action *action);\n\t/// Handler for clicking the [Show Only New] button.\n\tvoid btnShowOnlyNewClick(Action *action);\n\t/// Handler for clicking the [Mark All As Seen] button.\n\tvoid btnMarkAllAsSeenClick(Action *action);\n\t/// Fills the ResearchProject list with possible ResearchProjects.\n\tvoid fillProjectList(bool markAllAsSeen);\n\t/// Initializes the state.\n\tvoid init() override;\n};\n}\n"
  },
  {
    "path": "src/Basescape/PlaceFacilityState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"PlaceFacilityState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Sound.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"BaseView.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/BaseFacility.h\"\n#include \"../Savegame/ItemContainer.h\"\n#include \"../Mod/RuleBaseFacility.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Menu/ErrorMessageState.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Mod/RuleInterface.h\"\n#include <algorithm>\n#include <climits>\n#include <cmath>\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Place Facility window.\n * @param game Pointer to the core game.\n * @param base Pointer to the base to get info from.\n * @param rule Pointer to the facility ruleset to build.\n */\nPlaceFacilityState::PlaceFacilityState(Base *base, const RuleBaseFacility *rule, BaseFacility *origFac) : _base(base), _rule(rule), _origFac(origFac)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 128, 160, 192, 40);\n\t_view = new BaseView(192, 192, 0, 8);\n\t_btnCancel = new TextButton(112, 16, 200, 176);\n\t_txtFacility = new Text(110, 9, 202, 50);\n\t_txtCost = new Text(110, 9, 202, 62);\n\t_numCost = new Text(110, 17, 202, 70);\n\t_numResources = new Text(110, 25, 202, 87);\n\tconst size_t resourceTextOffset = 9*std::min((size_t)3, (_origFac == nullptr ? _rule->getBuildCostItems().size() : 0));\n\t_txtTime = new Text(110, 9, 202, 90+resourceTextOffset);\n\t_numTime = new Text(110, 17, 202, 98+resourceTextOffset);\n\t_txtMaintenance = new Text(110, 9, 202, 118+resourceTextOffset);\n\t_numMaintenance = new Text(110, 17, 202, 126+resourceTextOffset);\n\n\t// Set palette\n\tsetInterface(\"placeFacility\");\n\n\tadd(_window, \"window\", \"placeFacility\");\n\tadd(_view, \"baseView\", \"basescape\");\n\tadd(_btnCancel, \"button\", \"placeFacility\");\n\tadd(_txtFacility, \"text\", \"placeFacility\");\n\tadd(_txtCost, \"text\", \"placeFacility\");\n\tadd(_numCost, \"numbers\", \"placeFacility\");\n\tadd(_numResources, \"numbers\", \"placeFacility\");\n\tadd(_txtTime, \"text\", \"placeFacility\");\n\tadd(_numTime, \"numbers\", \"placeFacility\");\n\tadd(_txtMaintenance, \"text\", \"placeFacility\");\n\tadd(_numMaintenance, \"numbers\", \"placeFacility\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"placeFacility\");\n\n\tauto* itf = _game->getMod()->getInterface(\"basescape\")->getElementOptional(\"trafficLights\");\n\tif (itf)\n\t{\n\t\t_view->setOtherColors(itf->color, itf->color2, itf->border, !itf->TFTDMode);\n\t}\n\t_view->setTexture(_game->getMod()->getSurfaceSet(\"BASEBITS.PCK\"));\n\t_view->setBase(_base);\n\t_view->setSelectable(rule->getSizeX(), rule->getSizeY());\n\t_view->onMouseClick((ActionHandler)&PlaceFacilityState::viewClick);\n\n\t_btnCancel->setText(tr(\"STR_CANCEL\"));\n\t_btnCancel->onMouseClick((ActionHandler)&PlaceFacilityState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&PlaceFacilityState::btnCancelClick, Options::keyCancel);\n\n\t_txtFacility->setText(tr(_rule->getType()));\n\n\t_txtCost->setText(tr(\"STR_COST_UC\"));\n\n\t_numCost->setBig();\n\t_numCost->setText(Unicode::formatFunding(_origFac != nullptr ? 0 : _rule->getBuildCost()));\n\n\tif (_origFac == nullptr && !_rule->getBuildCostItems().empty())\n\t{\n\t\tstd::ostringstream ss;\n\n\t\t// Currently, the text box will only fit three lines of items.\n\t\t// But I'm going to add everything to the list anyway.\n\t\tfor (auto& item : _rule->getBuildCostItems())\n\t\t{\n\t\t\t// Note: `item` is of the form (item name, (cost number, refund number))\n\t\t\tsize_t max = 19;\n\t\t\tif (item.second.first > 9) --max;\n\t\t\tif (item.second.first > 99) --max;\n\t\t\tstd::string name = tr(item.first);\n\t\t\tif (Unicode::codePointLengthUTF8(name) > max)\n\t\t\t{\n\t\t\t\tname = Unicode::codePointSubstrUTF8(name, 0, max);\n\t\t\t}\n\n\t\t\tss << name << \": \" << item.second.first << std::endl;\n\t\t}\n\t\t_numResources->setText(ss.str());\n\t}\n\n\t_txtTime->setText(tr(\"STR_CONSTRUCTION_TIME_UC\"));\n\n\t_numTime->setBig();\n\t_numTime->setText(tr(\"STR_DAY\", _origFac != 0 ? 0 : _rule->getBuildTime()));\n\n\t_txtMaintenance->setText(tr(\"STR_MAINTENANCE_UC\"));\n\n\t_numMaintenance->setBig();\n\t_numMaintenance->setText(Unicode::formatFunding(_rule->getMonthlyCost()));\n}\n\n/**\n *\n */\nPlaceFacilityState::~PlaceFacilityState()\n{\n\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid PlaceFacilityState::btnCancelClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Processes clicking on facilities.\n * @param action Pointer to an action.\n */\nvoid PlaceFacilityState::viewClick(Action *)\n{\n\tif (_origFac != 0)\n\t{\n\t\t// EXPERIMENTAL!: just moving an existing facility\n\t\tif (_view->getGridX() == _origFac->getX() && _view->getGridY() == _origFac->getY())\n\t\t{\n\t\t\t// unchanged location -> no message, no cost.\n\t\t\t_game->popState();\n\t\t}\n\t\telse if (_view->getPlacementError(_rule, _origFac))\n\t\t{\n\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_CANNOT_BUILD_HERE\"), _palette, _game->getMod()->getInterface(\"placeFacility\")->getElement(\"errorMessage\")->color, \"BACK01.SCR\", _game->getMod()->getInterface(\"placeFacility\")->getElement(\"errorPalette\")->color));\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_origFac->setX(_view->getGridX());\n\t\t\t_origFac->setY(_view->getGridY());\n\t\t\tif (Options::allowBuildingQueue)\n\t\t\t{\n\t\t\t\t// first reset (maybe the moved facility is not queued anymore)\n\t\t\t\tif (abs(_origFac->getBuildTime()) > _rule->getBuildTime()) _origFac->setBuildTime(_rule->getBuildTime());\n\t\t\t\t// if it is still in the queue though, recalc\n\t\t\t\tif (_origFac->getBuildTime() > 0 && _view->isQueuedBuilding(_rule)) _origFac->setBuildTime(INT_MAX);\n\t\t\t\t_view->reCalcQueuedBuildings();\n\t\t\t}\n\t\t\t_game->popState();\n\t\t}\n\t}\n\telse\n\t{\n\t\t// Pre-calculate refunds\n\t\tconst BaseAreaSubset areaToBuildOverTemp = BaseAreaSubset(_rule->getSizeX(), _rule->getSizeY()).offset(_view->getGridX(), _view->getGridY());\n\t\tint refundValueTemp = 0;\n\t\tstd::map<const std::string, int> refundItemsTemp;\n\t\tfor (int i = _base->getFacilities()->size() - 1; i >= 0; --i)\n\t\t{\n\t\t\tBaseFacility* checkFacilityTemp = _base->getFacilities()->at(i);\n\t\t\tif (BaseAreaSubset::intersection(areaToBuildOverTemp, checkFacilityTemp->getPlacement()))\n\t\t\t{\n\t\t\t\tconst std::map<std::string, std::pair<int, int> >& itemCostTemp = checkFacilityTemp->getRules()->getBuildCostItems();\n\t\t\t\tif (checkFacilityTemp->getBuildTime() > checkFacilityTemp->getRules()->getBuildTime())\n\t\t\t\t{\n\t\t\t\t\trefundValueTemp = checkFacilityTemp->getRules()->getBuildCost();\n\t\t\t\t\tfor (auto& itemTemp : itemCostTemp)\n\t\t\t\t\t\trefundItemsTemp[itemTemp.first] += itemTemp.second.first;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\trefundValueTemp = checkFacilityTemp->getRules()->getRefundValue();\n\t\t\t\t\tfor (auto& itemTemp : itemCostTemp)\n\t\t\t\t\t\trefundItemsTemp[itemTemp.first] += itemTemp.second.second;\n\t\t\t\t}\n\t\t\t\tif (checkFacilityTemp->getAmmo() > 0)\n\t\t\t\t\trefundItemsTemp[checkFacilityTemp->getRules()->getAmmoItem()->getType()] += checkFacilityTemp->getAmmo();\n\t\t\t}\n\t\t}\n\n\t\t// placing a brand new facility\n\t\tBasePlacementErrors placementErrorCode = _view->getPlacementError(_rule);\n\t\tif (placementErrorCode)\n\t\t{\n\t\t\tint errorColor1 = _game->getMod()->getInterface(\"placeFacility\")->getElement(\"errorMessage\")->color;\n\t\t\tint errorColor2 = _game->getMod()->getInterface(\"placeFacility\")->getElement(\"errorPalette\")->color;\n\t\t\tswitch (placementErrorCode)\n\t\t\t{\n\t\t\t\tcase BPE_Used_Stores:\n\t\t\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_FACILITY_IN_USE_STORAGE\"), _palette, errorColor1, \"BACK01.SCR\", errorColor2));\n\t\t\t\t\tbreak;\n\t\t\t\tcase BPE_Used_Quarters:\n\t\t\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_FACILITY_IN_USE_QUARTERS\"), _palette, errorColor1, \"BACK01.SCR\", errorColor2));\n\t\t\t\t\tbreak;\n\t\t\t\tcase BPE_Used_Laboratories:\n\t\t\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_FACILITY_IN_USE_LABORATORIES\"), _palette, errorColor1, \"BACK01.SCR\", errorColor2));\n\t\t\t\t\tbreak;\n\t\t\t\tcase BPE_Used_Workshops:\n\t\t\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_FACILITY_IN_USE_WORKSHOPS\"), _palette, errorColor1, \"BACK01.SCR\", errorColor2));\n\t\t\t\t\tbreak;\n\t\t\t\tcase BPE_Used_Hangars:\n\t\t\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_FACILITY_IN_USE_HANGARS\"), _palette, errorColor1, \"BACK01.SCR\", errorColor2));\n\t\t\t\t\tbreak;\n\t\t\t\tcase BPE_Used_PsiLabs:\n\t\t\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_FACILITY_IN_USE_PSI_LABS\"), _palette, errorColor1, \"BACK01.SCR\", errorColor2));\n\t\t\t\t\tbreak;\n\t\t\t\tcase BPE_Used_Gyms:\n\t\t\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_FACILITY_IN_USE_GYMS\"), _palette, errorColor1, \"BACK01.SCR\", errorColor2));\n\t\t\t\t\tbreak;\n\t\t\t\tcase BPE_Used_AlienContainment:\n\t\t\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_FACILITY_IN_USE_PRISONS\"), _palette, errorColor1, \"BACK01.SCR\", errorColor2));\n\t\t\t\t\tbreak;\n\t\t\t\tcase BPE_NotConnected:\n\t\t\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_CANNOT_BUILD_HERE\"), _palette, errorColor1, \"BACK01.SCR\", errorColor2));\n\t\t\t\t\tbreak;\n\t\t\t\tcase BPE_Used:\n\t\t\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_FACILITY_IN_USE\"), _palette, errorColor1, \"BACK01.SCR\", errorColor2));\n\t\t\t\t\tbreak;\n\t\t\t\tcase BPE_Upgrading:\n\t\t\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_CANNOT_UPGRADE_FACILITY_ALREADY_UPGRADING\"), _palette, errorColor1, \"BACK01.SCR\", errorColor2));\n\t\t\t\t\tbreak;\n\t\t\t\tcase BPE_UpgradeSizeMismatch:\n\t\t\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_CANNOT_UPGRADE_FACILITY_WRONG_SIZE\"), _palette, errorColor1, \"BACK13.SCR\", errorColor2));\n\t\t\t\t\tbreak;\n\t\t\t\tcase BPE_UpgradeRequireSpecific:\n\t\t\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_CANNOT_UPGRADE_FACILITY_WRONG_TYPE\"), _palette, errorColor1, \"BACK13.SCR\", errorColor2));\n\t\t\t\t\tbreak;\n\t\t\t\tcase BPE_UpgradeDisallowed:\n\t\t\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_CANNOT_UPGRADE_FACILITY_DISALLOWED\"), _palette, errorColor1, \"BACK13.SCR\", errorColor2));\n\t\t\t\t\tbreak;\n\t\t\t\tcase BPE_Queue:\n\t\t\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_CANNOT_BUILD_QUEUE_OFF\"), _palette, errorColor1, \"BACK13.SCR\", errorColor2));\n\t\t\t\t\tbreak;\n\t\t\t\tcase BPE_ForbiddenByOther:\n\t\t\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_FACILITY_FORBIDDEN_BY_OTHER\"), _palette, errorColor1, \"BACK01.SCR\", errorColor2));\n\t\t\t\t\tbreak;\n\t\t\t\tcase BPE_ForbiddenByThis:\n\t\t\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_FACILITY_OTHER_FORBIDDEN_BY_THIS\"), _palette, errorColor1, \"BACK01.SCR\", errorColor2));\n\t\t\t\t\tbreak;\n\t\t\t\tcase BPE_UpgradeOnly:\n\t\t\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_CANNOT_BUILD_UPGRADE_ONLY\"), _palette, errorColor1, \"BACK13.SCR\", errorColor2));\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_CANNOT_BUILD_HERE\"), _palette, errorColor1, \"BACK01.SCR\", errorColor2));\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\telse if (_game->getSavedGame()->getFunds() < (_rule->getBuildCost() - refundValueTemp))\n\t\t{\n\t\t\t_game->popState();\n\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_NOT_ENOUGH_MONEY\"), _palette, _game->getMod()->getInterface(\"placeFacility\")->getElement(\"errorMessage\")->color, \"BACK01.SCR\", _game->getMod()->getInterface(\"placeFacility\")->getElement(\"errorPalette\")->color));\n\t\t}\n\t\telse\n\t\t{\n\t\t\tfor (const auto& item: _rule->getBuildCostItems())\n\t\t\t{\n\t\t\t\tint needed = (item.second.first - refundItemsTemp[item.first]) - _base->getStorageItems()->getItem(item.first);\n\t\t\t\tif (needed > 0)\n\t\t\t\t{\n\t\t\t\t\t_game->popState();\n\t\t\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_NOT_ENOUGH_ITEMS\").arg(tr(item.first)).arg(needed), _palette, _game->getMod()->getInterface(\"placeFacility\")->getElement(\"errorMessage\")->color, \"BACK01.SCR\", _game->getMod()->getInterface(\"placeFacility\")->getElement(\"errorPalette\")->color));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Remove any facilities we're building over\n\t\t\tdouble reducedBuildTime = 0.0;\n\t\t\tbool buildingOver = false;\n\t\t\tconst BaseAreaSubset areaToBuildOver = BaseAreaSubset(_rule->getSizeX(), _rule->getSizeY()).offset(_view->getGridX(), _view->getGridY());\n\t\t\tfor (int i = _base->getFacilities()->size() - 1; i >= 0; --i)\n\t\t\t{\n\t\t\t\tBaseFacility *checkFacility = _base->getFacilities()->at(i);\n\t\t\t\tif (BaseAreaSubset::intersection(areaToBuildOver, checkFacility->getPlacement()))\n\t\t\t\t{\n\t\t\t\t\t// Get a refund from the facility we're building over\n\t\t\t\t\tconst std::map<std::string, std::pair<int, int> > &itemCost = checkFacility->getRules()->getBuildCostItems();\n\n\t\t\t\t\tif (checkFacility->getBuildTime() > checkFacility->getRules()->getBuildTime())\n\t\t\t\t\t{\n\t\t\t\t\t\t// Give full refund if this is a (not yet started) queued build.\n\t\t\t\t\t\t_game->getSavedGame()->setFunds(_game->getSavedGame()->getFunds() + checkFacility->getRules()->getBuildCost());\n\t\t\t\t\t\tfor (auto& item : itemCost)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_base->getStorageItems()->addItem(_game->getMod()->getItem(item.first, true), item.second.first);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// Give partial refund if this is a started build or a completed facility.\n\t\t\t\t\t\t_game->getSavedGame()->setFunds(_game->getSavedGame()->getFunds() + checkFacility->getRules()->getRefundValue());\n\t\t\t\t\t\tfor (auto& item : itemCost)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_base->getStorageItems()->addItem(_game->getMod()->getItem(item.first, true), item.second.second);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Reduce the build time of the new facility\n\t\t\t\t\t\tdouble oldSizeSquared = (checkFacility->getRules()->getSizeX() * checkFacility->getRules()->getSizeY());\n\t\t\t\t\t\tdouble newSizeSquared = (_rule->getSizeX() * _rule->getSizeY());\n\t\t\t\t\t\treducedBuildTime += (checkFacility->getRules()->getBuildTime() - checkFacility->getBuildTime()) * oldSizeSquared / newSizeSquared;\n\n\t\t\t\t\t\t// This only counts as building over something if it wasn't in construction\n\t\t\t\t\t\tif (checkFacility->getBuildTime() == 0)\n\t\t\t\t\t\t\tbuildingOver = true;\n\t\t\t\t\t}\n\t\t\t\t\tif (checkFacility->getAmmo() > 0)\n\t\t\t\t\t{\n\t\t\t\t\t\t// Full refund of loaded ammo\n\t\t\t\t\t\t_base->getStorageItems()->addItem(checkFacility->getRules()->getAmmoItem(), checkFacility->getAmmo());\n\t\t\t\t\t\tcheckFacility->setAmmo(0);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove the facility from the base\n\t\t\t\t\t_base->getFacilities()->erase(_base->getFacilities()->begin() + i);\n\t\t\t\t\tdelete checkFacility;\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tBaseFacility *fac = new BaseFacility(_rule, _base);\n\t\t\tfac->setX(_view->getGridX());\n\t\t\tfac->setY(_view->getGridY());\n\t\t\tfac->setBuildTime(_rule->getBuildTime());\n\t\t\tif (buildingOver)\n\t\t\t{\n\t\t\t\tfac->setIfHadPreviousFacility(true);\n\t\t\t\treducedBuildTime = reducedBuildTime * _game->getMod()->getBuildTimeReductionScaling() / 100.0;\n\t\t\t\tint reducedBuildTimeRounded = (int)std::round(reducedBuildTime);\n\t\t\t\tfac->setBuildTime(std::max(1, fac->getBuildTime() - reducedBuildTimeRounded));\n\t\t\t}\n\t\t\t_base->getFacilities()->push_back(fac);\n\t\t\tif (fac->getRules()->getPlaceSound() != Mod::NO_SOUND)\n\t\t\t{\n\t\t\t\t_game->getMod()->getSound(\"GEO.CAT\", fac->getRules()->getPlaceSound())->play();\n\t\t\t}\n\t\t\tif (Options::allowBuildingQueue)\n\t\t\t{\n\t\t\t\tif (_view->isQueuedBuilding(_rule)) fac->setBuildTime(INT_MAX);\n\t\t\t\t_view->reCalcQueuedBuildings();\n\t\t\t}\n\t\t\t_view->setBase(_base);\n\t\t\t_game->getSavedGame()->setFunds(_game->getSavedGame()->getFunds() - _rule->getBuildCost());\n\t\t\tfor (const auto& item: _rule->getBuildCostItems())\n\t\t\t{\n\t\t\t\t_base->getStorageItems()->removeItem(item.first, item.second.first);\n\t\t\t}\n\t\t\tif (!_game->isShiftPressed())\n\t\t\t{\n\t\t\t\t_game->popState();\n\t\t\t}\n\t\t}\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/PlaceFacilityState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass Base;\nclass BaseFacility;\nclass RuleBaseFacility;\nclass BaseView;\nclass TextButton;\nclass Window;\nclass Text;\n\n/**\n * Window shown when the player tries to\n * build a facility.\n */\nclass PlaceFacilityState : public State\n{\nprotected:\n\tBase *_base;\n\tconst RuleBaseFacility *_rule;\n\tBaseFacility *_origFac;\n\n\tBaseView *_view;\n\tTextButton *_btnCancel;\n\tWindow *_window;\n\tText *_txtFacility, *_txtCost, *_numCost, *_numResources, *_txtTime, *_numTime, *_txtMaintenance, *_numMaintenance;\npublic:\n\t/// Creates the Place Facility state.\n\tPlaceFacilityState(Base *base, const RuleBaseFacility *rule, BaseFacility *origFac = 0);\n\t/// Cleans up the Place Facility state.\n\t~PlaceFacilityState();\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action *action);\n\t/// Handler for clicking the base view.\n\tvoid viewClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/PlaceLiftState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"PlaceLiftState.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Sound.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Interface/Window.h\"\n#include \"BaseView.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/BaseFacility.h\"\n#include \"../Mod/RuleBaseFacility.h\"\n#include \"BasescapeState.h\"\n#include \"SelectStartFacilityState.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Ufopaedia/Ufopaedia.h\"\n#include \"../Mod/RuleInterface.h\"\n#include \"../Geoscape/Globe.h\"\n#include \"../Mod/RuleGlobe.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Place Lift screen.\n * @param game Pointer to the core game.\n * @param base Pointer to the base to get info from.\n * @param globe Pointer to the Geoscape globe.\n * @param first Is this a custom starting base?\n */\nPlaceLiftState::PlaceLiftState(Base *base, Globe *globe, bool first) : _base(base), _globe(globe), _first(first)\n{\n\t// Create objects\n\t_view = new BaseView(192, 192, 0, 8);\n\t_txtTitle = new Text(320, 9, 0, 0);\n\t_window = new Window(this, 128, 160, 192, 40, POPUP_NONE);\n\t_txtHeader = new Text(118, 17, 197, 48);\n\t_lstAccessLifts = new TextList(104, 104, 200, 64);\n\n\t// Set palette\n\tsetInterface(\"placeFacility\");\n\n\tadd(_view, \"baseView\", \"basescape\");\n\tadd(_txtTitle, \"text\", \"placeFacility\");\n\tadd(_window, \"window\", \"selectFacility\");\n\tadd(_txtHeader, \"text\", \"selectFacility\");\n\tadd(_lstAccessLifts, \"list\", \"selectFacility\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"selectFacility\");\n\n\tif (_globe && _base)\n\t{\n\t\tint texture, shade;\n\t\t_globe->getPolygonTextureAndShade(_base->getLongitude(), _base->getLatitude(), &texture, &shade);\n\t\tauto* globeTexture = _game->getMod()->getGlobe()->getTexture(texture);\n\t\t_base->setGlobeTexture(globeTexture);\n\t}\n\n\tauto* itf = _game->getMod()->getInterface(\"basescape\")->getElementOptional(\"trafficLights\");\n\tif (itf)\n\t{\n\t\t_view->setOtherColors(itf->color, itf->color2, itf->border, !itf->TFTDMode);\n\t}\n\t_view->setTexture(_game->getMod()->getSurfaceSet(\"BASEBITS.PCK\"));\n\t_view->setBase(_base);\n\n\t_lift = nullptr;\n\tfor (auto& facilityType : _game->getMod()->getBaseFacilitiesList())\n\t{\n\t\tauto* facilityRule = _game->getMod()->getBaseFacility(facilityType);\n\t\tif ((facilityRule->isLift() && !facilityRule->isUpgradeOnly())\n\t\t\t&& facilityRule->isAllowedForBaseType(_base->isFakeUnderwater()) && _game->getSavedGame()->isResearched(facilityRule->getRequirements()))\n\t\t{\n\t\t\t_accessLifts.push_back(facilityRule);\n\t\t}\n\t}\n\tif (_first || _accessLifts.size() == 1)\n\t{\n\t\t_lift = _accessLifts.front();\n\t}\n\n\t_txtHeader->setBig();\n\t_txtHeader->setAlign(ALIGN_CENTER);\n\t_txtHeader->setText(tr(\"STR_INSTALLATION\"));\n\n\t_lstAccessLifts->setColumns(1, 104);\n\t_lstAccessLifts->setSelectable(true);\n\t_lstAccessLifts->setBackground(_window);\n\t_lstAccessLifts->setMargin(2);\n\t_lstAccessLifts->setWordWrap(true);\n\t_lstAccessLifts->setScrolling(true, 0);\n\t_lstAccessLifts->onMouseClick((ActionHandler)&PlaceLiftState::lstAccessLiftsClick);\n\t_lstAccessLifts->onMouseClick((ActionHandler)&PlaceLiftState::lstAccessLiftsClick, SDL_BUTTON_MIDDLE);\n\n\tfor (const auto* facRule : _accessLifts)\n\t{\n\t\t_lstAccessLifts->addRow(1, tr(facRule->getType()).c_str());\n\t}\n\n\tif (_lift)\n\t{\n\t\t_lstAccessLifts->setVisible(false);\n\t\t_txtHeader->setVisible(false);\n\t\t_window->setVisible(false);\n\n\t\t_view->setSelectable(_lift->getSizeX(), _lift->getSizeY());\n\t\t_view->onMouseClick((ActionHandler)&PlaceLiftState::viewClick);\n\t}\n\n\t_txtTitle->setText(tr(\"STR_SELECT_POSITION_FOR_ACCESS_LIFT\"));\n}\n\n/**\n *\n */\nPlaceLiftState::~PlaceLiftState()\n{\n\n}\n\n/**\n * Processes clicking on facilities.\n * @param action Pointer to an action.\n */\nvoid PlaceLiftState::viewClick(Action *)\n{\n\tBaseFacility *fac = new BaseFacility(_lift, _base);\n\tfac->setX(_view->getGridX());\n\tfac->setY(_view->getGridY());\n\t_base->getFacilities()->push_back(fac);\n\tif (fac->getRules()->getPlaceSound() != Mod::NO_SOUND)\n\t{\n\t\t_game->getMod()->getSound(\"GEO.CAT\", fac->getRules()->getPlaceSound())->play();\n\t}\n\t_game->popState();\n\tBasescapeState *bState = new BasescapeState(_base, _globe);\n\t_game->getSavedGame()->setSelectedBase(_game->getSavedGame()->getBases()->size() - 1);\n\t_game->pushState(bState);\n\tif (_first)\n\t{\n\t\t_game->pushState(new SelectStartFacilityState(_base, bState, _globe));\n\t}\n}\n\n/**\n * Selects the access lift to place.\n * @param action Pointer to an action.\n */\nvoid PlaceLiftState::lstAccessLiftsClick(Action *action)\n{\n\tauto index = _lstAccessLifts->getSelectedRow();\n\tif (index >= _accessLifts.size())\n\t{\n\t\treturn;\n\t}\n\n\tif (action->getDetails()->button.button == SDL_BUTTON_MIDDLE)\n\t{\n\t\tUfopaedia::openArticle(_game, _accessLifts[index]->getUfopediaType());\n\t\treturn;\n\t}\n\n\t_lift = _accessLifts[index];\n\n\tif (_lift)\n\t{\n\t\t_lstAccessLifts->setVisible(false);\n\t\t_txtHeader->setVisible(false);\n\t\t_window->setVisible(false);\n\n\t\t_view->setSelectable(_lift->getSizeX(), _lift->getSizeY());\n\t\t_view->onMouseClick((ActionHandler)&PlaceLiftState::viewClick);\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/PlaceLiftState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass Base;\nclass BaseView;\nclass Text;\nclass TextList;\nclass Window;\nclass Globe;\nclass RuleBaseFacility;\n\n/**\n * Screen shown when the player has to\n * place the access lift of a base.\n */\nclass PlaceLiftState : public State\n{\nprivate:\n\tBase *_base;\n\tGlobe *_globe;\n\tBaseView *_view;\n\tText *_txtTitle;\n\tbool _first;\n\tRuleBaseFacility *_lift;\n\n\tstd::vector<RuleBaseFacility*> _accessLifts;\n\tWindow *_window;\n\tText *_txtHeader;\n\tTextList *_lstAccessLifts;\npublic:\n\t/// Creates the Place Lift state.\n\tPlaceLiftState(Base *base, Globe *globe, bool first);\n\t/// Cleans up the Place Lift state.\n\t~PlaceLiftState();\n\t/// Handler for clicking the base view.\n\tvoid viewClick(Action *action);\n\t/// Handler for clicking the Access Lifts list.\n\tvoid lstAccessLiftsClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/PlaceStartFacilityState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"PlaceStartFacilityState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Sound.h\"\n#include \"../Interface/Text.h\"\n#include \"BaseView.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/BaseFacility.h\"\n#include \"../Mod/RuleBaseFacility.h\"\n#include \"../Menu/ErrorMessageState.h\"\n#include \"SelectStartFacilityState.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleInterface.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Place Facility window.\n * @param game Pointer to the core game.\n * @param base Pointer to the base to get info from.\n * @param select Pointer to the selection state.\n * @param rule Pointer to the facility ruleset to build.\n */\nPlaceStartFacilityState::PlaceStartFacilityState(Base *base, SelectStartFacilityState *select, const RuleBaseFacility *rule) : PlaceFacilityState(base, rule), _select(select)\n{\n\t_view->onMouseClick((ActionHandler)&PlaceStartFacilityState::viewClick);\n\t_numCost->setText(tr(\"STR_NONE\"));\n\t_numTime->setText(tr(\"STR_NONE\"));\n}\n\n/**\n *\n */\nPlaceStartFacilityState::~PlaceStartFacilityState()\n{\n\n}\n\n/**\n * Processes clicking on facilities.\n * @param action Pointer to an action.\n */\nvoid PlaceStartFacilityState::viewClick(Action *)\n{\n\tif (_view->getPlacementError(_rule, nullptr, true))\n\t{\n\t\t_game->popState();\n\t\t_game->pushState(new ErrorMessageState(tr(\"STR_CANNOT_BUILD_HERE\"), _palette, _game->getMod()->getInterface(\"basescape\")->getElement(\"errorMessage\")->color, \"BACK01.SCR\", _game->getMod()->getInterface(\"basescape\")->getElement(\"errorPalette\")->color));\n\t}\n\telse\n\t{\n\t\tBaseFacility *fac = new BaseFacility(_rule, _base);\n\t\tfac->setX(_view->getGridX());\n\t\tfac->setY(_view->getGridY());\n\t\t_base->getFacilities()->push_back(fac);\n\t\tif (fac->getRules()->getPlaceSound() != Mod::NO_SOUND)\n\t\t{\n\t\t\t_game->getMod()->getSound(\"GEO.CAT\", fac->getRules()->getPlaceSound())->play();\n\t\t}\n\t\t_game->popState();\n\t\t_select->facilityBuilt();\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/PlaceStartFacilityState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"PlaceFacilityState.h\"\n\nnamespace OpenXcom\n{\n\nclass SelectStartFacilityState;\n\n/**\n * Window shown when the player tries to\n * build a facility.\n */\nclass PlaceStartFacilityState : public PlaceFacilityState\n{\nprivate:\n\tSelectStartFacilityState *_select;\n\npublic:\n\t/// Creates the Place Facility state.\n\tPlaceStartFacilityState(Base *base, SelectStartFacilityState *select, const RuleBaseFacility *rule);\n\t/// Cleans up the Place Facility state.\n\t~PlaceStartFacilityState();\n\t/// Handler for clicking the base view.\n\tvoid viewClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/PurchaseState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"PurchaseState.h\"\n#include \"ItemLocationsState.h\"\n#include <sstream>\n#include <climits>\n#include <iomanip>\n#include <algorithm>\n#include <locale>\n#include \"../fmath.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Timer.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextEdit.h\"\n#include \"../Interface/ComboBox.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Mod/RuleCraft.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Engine/Action.h\"\n#include \"../Savegame/Craft.h\"\n#include \"../Savegame/ItemContainer.h\"\n#include \"../Menu/ErrorMessageState.h\"\n#include \"../Mod/RuleInterface.h\"\n#include \"../Mod/RuleSoldier.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Ufopaedia/Ufopaedia.h\"\n#include \"../Battlescape/CannotReequipState.h\"\n#include \"../Savegame/Country.h\"\n#include \"../Mod/RuleCountry.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * @brief Combines any number of functions into a function that returns true if all of them are true.\n * Short circuits as well.\n * @tparam ...Functions type of the function to combine.\n * @param ...funcs the functions to combine.\n * @return a new function that is true only if all predicates are satisfied.\n*/\ntemplate <typename... Functions>\ninline constexpr auto allOf(Functions... funcs)\n{\n\treturn [=](const auto& x)\n\t{\n\t\treturn (... && funcs(x));\n\t};\n}\n\n/**\n * Initializes all the elements in the Purchase/Hire screen.\n * @param game Pointer to the core game.\n * @param base Pointer to the base to get info from.\n */\nPurchaseState::PurchaseState(Base *base, CannotReequipState *parent) : _base(base), _parent(parent), _sel(0), _total(0), _pQty(0), _cQty(0), _iQty(0.0), _ammoColor(0)\n{\n\t_autoBuyDone = false;\n\tif (_parent)\n\t{\n\t\tfor (auto& i : _parent->getMissingItems())\n\t\t{\n\t\t\tif (i.qty > 0)\n\t\t\t{\n\t\t\t\tauto* rule = _game->getMod()->getItem(i.item);\n\t\t\t\tif (rule)\n\t\t\t\t{\n\t\t\t\t\t_missingItemsMap[rule] = i.qty;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Create objects\n\t_window = new Window(this, 320, 200, 0, 0);\n\t_btnQuickSearch = new TextEdit(this, 48, 9, 10, 13);\n\t_btnOk = new TextButton(148, 16, 8, 176);\n\t_btnCancel = new TextButton(148, 16, 164, 176);\n\t_txtTitle = new Text(310, 17, 5, 8);\n\t_txtFunds = new Text(150, 9, 10, 24);\n\t_txtPurchases = new Text(150, 9, 160, 24);\n\t_txtSpaceUsed = new Text(150, 9, 160, 34);\n\t_txtCost = new Text(102, 9, 152, 44);\n\t_txtQuantity = new Text(60, 9, 256, 44);\n\t_cbxCategory = new ComboBox(this, 120, 16, 10, 36);\n\t_lstItems = new TextList(287, 120, 8, 54);\n\n\ttouchComponentsCreate(_txtTitle);\n\n\t// Set palette\n\tsetInterface(\"buyMenu\");\n\n\t_ammoColor = _game->getMod()->getInterface(\"buyMenu\")->getElement(\"ammoColor\")->color;\n\n\tadd(_window, \"window\", \"buyMenu\");\n\tadd(_btnQuickSearch, \"button\", \"buyMenu\");\n\tadd(_btnOk, \"button\", \"buyMenu\");\n\tadd(_btnCancel, \"button\", \"buyMenu\");\n\tadd(_txtTitle, \"text\", \"buyMenu\");\n\tadd(_txtFunds, \"text\", \"buyMenu\");\n\tadd(_txtPurchases, \"text\", \"buyMenu\");\n\tadd(_txtSpaceUsed, \"text\", \"buyMenu\");\n\tadd(_txtCost, \"text\", \"buyMenu\");\n\tadd(_txtQuantity, \"text\", \"buyMenu\");\n\tadd(_lstItems, \"list\", \"buyMenu\");\n\tadd(_cbxCategory, \"text\", \"buyMenu\");\n\n\ttouchComponentsAdd(\"button2\", \"buyMenu\", _window);\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"buyMenu\");\n\n\ttouchComponentsConfigure();\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&PurchaseState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&PurchaseState::btnOkClick, Options::keyOk);\n\n\t_btnCancel->setText(tr(\"STR_CANCEL\"));\n\t_btnCancel->onMouseClick((ActionHandler)&PurchaseState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&PurchaseState::btnCancelClick, Options::keyCancel);\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_PURCHASE_HIRE_PERSONNEL\"));\n\n\t_txtFunds->setText(tr(\"STR_CURRENT_FUNDS\").arg(Unicode::formatFunding(_game->getSavedGame()->getFunds())));\n\n\t_txtPurchases->setText(tr(\"STR_COST_OF_PURCHASES\").arg(Unicode::formatFunding(_total)));\n\n\t_txtSpaceUsed->setVisible(Options::storageLimitsEnforced);\n\tstd::ostringstream ss;\n\tss << _base->getUsedStores() << \":\" << _base->getAvailableStores();\n\t_txtSpaceUsed->setText(tr(\"STR_SPACE_USED\").arg(ss.str()));\n\n\t_txtCost->setText(tr(\"STR_COST_PER_UNIT_UC\"));\n\n\t_txtQuantity->setText(tr(\"STR_QUANTITY_UC\"));\n\n\t_lstItems->setArrowColumn(227, ARROW_VERTICAL);\n\t_lstItems->setColumns(4, 150, 55, 50, 32);\n\t_lstItems->setSelectable(true);\n\t_lstItems->setBackground(_window);\n\t_lstItems->setMargin(2);\n\t_lstItems->onLeftArrowPress((ActionHandler)&PurchaseState::lstItemsLeftArrowPress);\n\t_lstItems->onLeftArrowRelease((ActionHandler)&PurchaseState::lstItemsLeftArrowRelease);\n\t_lstItems->onLeftArrowClick((ActionHandler)&PurchaseState::lstItemsLeftArrowClick);\n\t_lstItems->onRightArrowPress((ActionHandler)&PurchaseState::lstItemsRightArrowPress);\n\t_lstItems->onRightArrowRelease((ActionHandler)&PurchaseState::lstItemsRightArrowRelease);\n\t_lstItems->onRightArrowClick((ActionHandler)&PurchaseState::lstItemsRightArrowClick);\n\t_lstItems->onMousePress((ActionHandler)&PurchaseState::lstItemsMousePress);\n\n\t_cats.push_back(\"STR_ALL_ITEMS\");\n\t_cats.push_back(\"STR_FILTER_HIDDEN\");\n\t_cats.push_back(\"STR_FILTER_EQUIPPED\");\n\tif (!_missingItemsMap.empty())\n\t{\n\t\t_cats.push_back(\"STR_FILTER_MISSING\");\n\t}\n\n\tRuleBaseFacilityFunctions providedBaseFunc = _base->getProvidedBaseFunc({});\n\n\t// setup the filter methods to be used in various situations (craft, soldiers, items).\n\tconstexpr auto costIsNotZero = [](const auto* rule)\n\t{\n\t\treturn rule->getBuyCost() != 0;\n\t};\n\tconstexpr auto requirementsAreResearched = [](const auto* rule)\n\t{\n\t\treturn _game->getSavedGame()->isResearched(rule->getRequirements());\n\t};\n\tconstexpr auto buyRequirementsAreResearched = [](const auto* rule)\n\t{\n\t\treturn _game->getSavedGame()->isResearched(rule->getBuyRequirements());\n\t};\n\tauto necessaryBaseFunctionsPresent = [&providedBaseFunc](const auto* rule)\n\t{\n\t\treturn (~providedBaseFunc & rule->getRequiresBuyBaseFunc()).none();\n\t};\n\tconstexpr auto requiredCountryAllied = [](const auto* rule)\n\t{\n\t\tif (!rule->getRequiresBuyCountry().empty())\n\t\t{\n\t\t\tfor (const auto* country : *_game->getSavedGame()->getCountries())\n\t\t\t{\n\t\t\t\tif (country->getPact() && country->getRules()->getType() == rule->getRequiresBuyCountry())\n\t\t\t\t{\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t};\n\n\tauto craftAndSoldierFilter = allOf(costIsNotZero, requirementsAreResearched, necessaryBaseFunctionsPresent, requiredCountryAllied);\n\tauto itemFilter = allOf(costIsNotZero, requirementsAreResearched, buyRequirementsAreResearched, necessaryBaseFunctionsPresent, requiredCountryAllied);\n\n\tfor (auto& soldierType : _game->getMod()->getSoldiersList())\n\t{\n\t\tRuleSoldier *rule = _game->getMod()->getSoldier(soldierType);\n\t\tif (craftAndSoldierFilter(rule))\n\t\t{\n\t\t\tTransferRow row = { TRANSFER_SOLDIER, rule, tr(rule->getType()), rule->getBuyCost(), _base->getSoldierCountAndSalary(rule->getType()).first, 0, 0, -4, 0, 0, 0 };\n\t\t\t_items.push_back(row);\n\t\t\tstd::string cat = getCategory(_items.size() - 1);\n\t\t\tif (std::find(_cats.begin(), _cats.end(), cat) == _cats.end())\n\t\t\t{\n\t\t\t\t_cats.push_back(cat);\n\t\t\t}\n\t\t}\n\t}\n\tif ((_game->getMod()->getHireScientistsUnlockResearch().empty() || _game->getSavedGame()->isResearched(_game->getMod()->getHireScientistsUnlockResearch(), true))\n\t\t&& (~providedBaseFunc & _game->getMod()->getHireScientistsRequiresBaseFunc()).none())\n\t{\n\t\tTransferRow row = { TRANSFER_SCIENTIST, 0, tr(\"STR_SCIENTIST\"), _game->getMod()->getHireScientistCost(), _base->getTotalScientists(), 0, 0, -3, 0, 0, 0 };\n\t\t_items.push_back(row);\n\t\tstd::string cat = getCategory(_items.size() - 1);\n\t\tif (std::find(_cats.begin(), _cats.end(), cat) == _cats.end())\n\t\t{\n\t\t\t_cats.push_back(cat);\n\t\t}\n\t}\n\tif ((_game->getMod()->getHireEngineersUnlockResearch().empty() || _game->getSavedGame()->isResearched(_game->getMod()->getHireEngineersUnlockResearch(), true))\n\t\t&& (~providedBaseFunc & _game->getMod()->getHireEngineersRequiresBaseFunc()).none())\n\t{\n\t\tTransferRow row = { TRANSFER_ENGINEER, 0, tr(\"STR_ENGINEER\"), _game->getMod()->getHireEngineerCost(), _base->getTotalEngineers(), 0, 0, -2, 0, 0, 0 };\n\t\t_items.push_back(row);\n\t\tstd::string cat = getCategory(_items.size() - 1);\n\t\tif (std::find(_cats.begin(), _cats.end(), cat) == _cats.end())\n\t\t{\n\t\t\t_cats.push_back(cat);\n\t\t}\n\t}\n\tfor (auto& craftType : _game->getMod()->getCraftsList())\n\t{\n\t\tRuleCraft *rule = _game->getMod()->getCraft(craftType);\n\t\tif (craftAndSoldierFilter(rule))\n\t\t{\n\t\t\tTransferRow row = { TRANSFER_CRAFT, rule, tr(rule->getType()), rule->getBuyCost(), _base->getCraftCount(rule), 0, 0, -1, 0, 0, 0 };\n\t\t\t_items.push_back(row);\n\t\t\tstd::string cat = getCategory(_items.size() - 1);\n\t\t\tif (std::find(_cats.begin(), _cats.end(), cat) == _cats.end())\n\t\t\t{\n\t\t\t\t_cats.push_back(cat);\n\t\t\t}\n\t\t}\n\t}\n\tfor (auto& itemType : _game->getMod()->getItemsList())\n\t{\n\t\tRuleItem *rule = _game->getMod()->getItem(itemType);\n\t\tif (itemFilter(rule))\n\t\t{\n\t\t\tTransferRow row = { TRANSFER_ITEM, rule, tr(rule->getType()), rule->getBuyCostAdjusted(_base, _game->getSavedGame()), _base->getStorageItems()->getItem(rule), 0, 0, rule->getListOrder(), 0, 0, 0 };\n\t\t\t_items.push_back(row);\n\t\t\tstd::string cat = getCategory(_items.size() - 1);\n\t\t\tif (std::find(_cats.begin(), _cats.end(), cat) == _cats.end())\n\t\t\t{\n\t\t\t\t_cats.push_back(cat);\n\t\t\t}\n\t\t}\n\t}\n\n\t_vanillaCategories = _cats.size();\n\tif (_game->getMod()->getDisplayCustomCategories() > 0)\n\t{\n\t\tbool hasUnassigned = false;\n\n\t\t// first find all relevant item categories\n\t\tstd::vector<std::string> tempCats;\n\t\tfor (const auto& transferRow : _items)\n\t\t{\n\t\t\tif (transferRow.type == TRANSFER_ITEM)\n\t\t\t{\n\t\t\t\tRuleItem *rule = (RuleItem*)(transferRow.rule);\n\t\t\t\tif (rule->getCategories().empty())\n\t\t\t\t{\n\t\t\t\t\thasUnassigned = true;\n\t\t\t\t}\n\t\t\t\tfor (auto& itemCategoryName : rule->getCategories())\n\t\t\t\t{\n\t\t\t\t\tif (std::find(tempCats.begin(), tempCats.end(), itemCategoryName) == tempCats.end())\n\t\t\t\t\t{\n\t\t\t\t\t\ttempCats.push_back(itemCategoryName);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// then use them nicely in order\n\t\tif (_game->getMod()->getDisplayCustomCategories() == 1)\n\t\t{\n\t\t\t_cats.clear();\n\t\t\t_cats.push_back(\"STR_ALL_ITEMS\");\n\t\t\t_cats.push_back(\"STR_FILTER_HIDDEN\");\n\t\t\t_cats.push_back(\"STR_FILTER_EQUIPPED\");\n\t\t\tif (!_missingItemsMap.empty())\n\t\t\t{\n\t\t\t\t_cats.push_back(\"STR_FILTER_MISSING\");\n\t\t\t}\n\t\t\t_vanillaCategories = _cats.size();\n\t\t}\n\t\tfor (auto& categoryName : _game->getMod()->getItemCategoriesList())\n\t\t{\n\t\t\tif (std::find(tempCats.begin(), tempCats.end(), categoryName) != tempCats.end())\n\t\t\t{\n\t\t\t\t_cats.push_back(categoryName);\n\t\t\t}\n\t\t}\n\t\tif (hasUnassigned)\n\t\t{\n\t\t\t_cats.push_back(\"STR_UNASSIGNED\");\n\t\t}\n\t}\n\n\t_cbxCategory->setOptions(_cats, true);\n\tif (!_missingItemsMap.empty())\n\t{\n\t\t_cbxCategory->setSelected(3); // STR_FILTER_MISSING\n\t}\n\t_cbxCategory->onChange((ActionHandler)&PurchaseState::cbxCategoryChange);\n\n\t_btnQuickSearch->setText(\"\"); // redraw\n\t_btnQuickSearch->onEnter((ActionHandler)&PurchaseState::btnQuickSearchApply);\n\t_btnQuickSearch->setVisible(Options::oxceQuickSearchButton);\n\n\t_btnOk->onKeyboardRelease((ActionHandler)&PurchaseState::btnQuickSearchToggle, Options::keyToggleQuickSearch);\n\n\tupdateList();\n\n\t_autoBuyDone = true;\n\tif (!_missingItemsMap.empty())\n\t{\n\t\t_txtPurchases->setText(tr(\"STR_COST_OF_PURCHASES\").arg(Unicode::formatFunding(_total)));\n\t\tstd::ostringstream ss5;\n\t\tss5 << _base->getUsedStores();\n\t\tif (std::abs(_iQty) > 0.05)\n\t\t{\n\t\t\tss5 << \"(\";\n\t\t\tif (_iQty > 0.05)\n\t\t\t\tss5 << \"+\";\n\t\t\tss5 << std::fixed << std::setprecision(1) << _iQty << \")\";\n\t\t}\n\t\tss5 << \":\" << _base->getAvailableStores();\n\t\t_txtSpaceUsed->setText(tr(\"STR_SPACE_USED\").arg(ss5.str()));\n\t}\n\n\t_timerInc = new Timer(250);\n\t_timerInc->onTimer((StateHandler)&PurchaseState::increase);\n\t_timerDec = new Timer(250);\n\t_timerDec->onTimer((StateHandler)&PurchaseState::decrease);\n}\n\n/**\n *\n */\nPurchaseState::~PurchaseState()\n{\n\tdelete _timerInc;\n\tdelete _timerDec;\n}\n\n/**\n * Resets stuff when coming back from other screens.\n */\nvoid PurchaseState::init()\n{\n\tState::init();\n\n\ttouchComponentsRefresh();\n}\n\n/**\n * Runs the arrow timers.\n */\nvoid PurchaseState::think()\n{\n\tState::think();\n\n\t_timerInc->think(this, 0);\n\t_timerDec->think(this, 0);\n}\n\n/**\n * Determines the category a row item belongs in.\n * @param sel Selected row.\n * @returns Item category.\n */\nstd::string PurchaseState::getCategory(int sel) const\n{\n\tRuleItem *rule = 0;\n\tswitch (_items[sel].type)\n\t{\n\tcase TRANSFER_SOLDIER:\n\tcase TRANSFER_SCIENTIST:\n\tcase TRANSFER_ENGINEER:\n\t\treturn \"STR_PERSONNEL\";\n\tcase TRANSFER_CRAFT:\n\t\treturn \"STR_CRAFT_ARMAMENT\";\n\tcase TRANSFER_ITEM:\n\t\trule = (RuleItem*)_items[sel].rule;\n\t\tif (rule->getBattleType() == BT_CORPSE || rule->isAlien())\n\t\t{\n\t\t\tif (rule->getVehicleUnit())\n\t\t\t\treturn \"STR_PERSONNEL\"; // OXCE: critters fighting for us\n\t\t\tif (rule->isAlien())\n\t\t\t\treturn \"STR_PRISONERS\"; // OXCE: live aliens\n\t\t\treturn \"STR_ALIENS\";\n\t\t}\n\t\tif (rule->getBattleType() == BT_NONE)\n\t\t{\n\t\t\tif (_game->getMod()->isCraftWeaponStorageItem(rule))\n\t\t\t\treturn \"STR_CRAFT_ARMAMENT\";\n\t\t\tif (_game->getMod()->isArmorStorageItem(rule))\n\t\t\t\treturn \"STR_ARMORS\"; // OXCE: armors\n\t\t\treturn \"STR_COMPONENTS\";\n\t\t}\n\t\treturn \"STR_EQUIPMENT\";\n\t}\n\treturn \"STR_ALL_ITEMS\";\n}\n\n/**\n * Determines if a row item belongs to a given category.\n * @param sel Selected row.\n * @param cat Category.\n * @returns True if row item belongs to given category, otherwise False.\n */\nbool PurchaseState::belongsToCategory(int sel, const std::string &cat) const\n{\n\tswitch (_items[sel].type)\n\t{\n\tcase TRANSFER_SOLDIER:\n\tcase TRANSFER_SCIENTIST:\n\tcase TRANSFER_ENGINEER:\n\tcase TRANSFER_CRAFT:\n\t\treturn false;\n\tcase TRANSFER_ITEM:\n\t\tRuleItem *rule = (RuleItem*)_items[sel].rule;\n\t\treturn rule->belongsToCategory(cat);\n\t}\n\treturn false;\n}\n\n/**\n * Determines if a row item is supposed to be hidden\n * @param sel Selected row.\n * @param cat Category.\n * @returns True if row item is hidden\n */\nbool PurchaseState::isHidden(int sel) const\n{\n\tstd::string itemName;\n\tbool isCraft = false;\n\n\tswitch (_items[sel].type)\n\t{\n\tcase TRANSFER_SOLDIER:\n\tcase TRANSFER_SCIENTIST:\n\tcase TRANSFER_ENGINEER:\n\t\treturn false;\n\tcase TRANSFER_CRAFT:\n\t\tisCraft = true; // fall-through\n\tcase TRANSFER_ITEM:\n\t\tif (isCraft)\n\t\t{\n\t\t\tRuleCraft *rule = (RuleCraft*)_items[sel].rule;\n\t\t\tif (rule != 0)\n\t\t\t{\n\t\t\t\titemName = rule->getType();\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tRuleItem *rule = (RuleItem*)_items[sel].rule;\n\t\t\tif (rule != 0)\n\t\t\t{\n\t\t\t\titemName = rule->getType();\n\t\t\t}\n\t\t}\n\t\tif (!itemName.empty())\n\t\t{\n\t\t\tauto& hiddenMap = _game->getSavedGame()->getHiddenPurchaseItems();\n\t\t\tauto iter = hiddenMap.find(itemName);\n\t\t\tif (iter != hiddenMap.end())\n\t\t\t{\n\t\t\t\treturn iter->second;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// not found = not hidden\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn false;\n}\n\n/**\n * Determines if a row item corresponds to equipped items\n * @param sel Selected row.\n * @returns True if row item is considered equipped\n */\nbool PurchaseState::isEquipped(int sel) const\n{\n\tswitch (_items[sel].type)\n\t{\n\tcase TRANSFER_SOLDIER:\n\tcase TRANSFER_SCIENTIST:\n\tcase TRANSFER_ENGINEER:\n\tcase TRANSFER_CRAFT:\n\t\treturn false;\n\tcase TRANSFER_ITEM:\n\t\tRuleItem* rule = (RuleItem*)_items[sel].rule;\n\t\tif (rule)\n\t\t{\n\t\t\t// iterate all craft, also craft which are currently not at the base\n\t\t\tfor (auto* xcraft : *_base->getCrafts())\n\t\t\t{\n\t\t\t\tif (xcraft->getItems()->getItem(rule) > 0)\n\t\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn false;\n}\n\n/**\n * Determines if a row item is in the map of missing items.\n * @param sel Selected row.\n * @returns Number of missing items that can be bought. -1 if not missing.\n */\nint PurchaseState::getMissingQty(int sel) const\n{\n\tswitch (_items[sel].type)\n\t{\n\tcase TRANSFER_SOLDIER:\n\tcase TRANSFER_SCIENTIST:\n\tcase TRANSFER_ENGINEER:\n\tcase TRANSFER_CRAFT:\n\t\treturn -1;\n\tcase TRANSFER_ITEM:\n\t\tRuleItem* rule = (RuleItem*)_items[sel].rule;\n\t\tif (rule)\n\t\t{\n\t\t\tauto iter = _missingItemsMap.find(rule);\n\t\t\tif (iter != _missingItemsMap.end())\n\t\t\t{\n\t\t\t\tif (rule->getMonthlyBuyLimit() > 0)\n\t\t\t\t{\n\t\t\t\t\tauto& itemPurchaseLimitLog = _game->getSavedGame()->getMonthlyPurchaseLimitLog();\n\t\t\t\t\tint maxByLimit = std::max(0, rule->getMonthlyBuyLimit() - itemPurchaseLimitLog[rule->getType()]);\n\t\t\t\t\treturn std::min(maxByLimit, iter->second);\n\t\t\t\t}\n\n\t\t\t\treturn iter->second;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// not found = not missing\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn -1;\n}\n\n/**\n* Quick search toggle.\n* @param action Pointer to an action.\n*/\nvoid PurchaseState::btnQuickSearchToggle(Action *action)\n{\n\tif (_btnQuickSearch->getVisible())\n\t{\n\t\t_btnQuickSearch->setText(\"\");\n\t\t_btnQuickSearch->setVisible(false);\n\t\tbtnQuickSearchApply(action);\n\t}\n\telse\n\t{\n\t\t_btnQuickSearch->setVisible(true);\n\t\t_btnQuickSearch->setFocus(true);\n\t}\n}\n\n/**\n* Quick search.\n* @param action Pointer to an action.\n*/\nvoid PurchaseState::btnQuickSearchApply(Action *)\n{\n\tupdateList();\n}\n\n/**\n * Filters the current list of items.\n */\nvoid PurchaseState::updateList()\n{\n\tstd::string searchString = _btnQuickSearch->getText();\n\tUnicode::upperCase(searchString);\n\n\t_lstItems->clearList();\n\t_rows.clear();\n\n\tsize_t selCategory = _cbxCategory->getSelected();\n\tconst std::string selectedCategory = _cats[selCategory];\n\tbool categoryFilterEnabled = (selectedCategory != \"STR_ALL_ITEMS\");\n\tbool categoryUnassigned = (selectedCategory == \"STR_UNASSIGNED\");\n\tbool categoryHidden = (selectedCategory == \"STR_FILTER_HIDDEN\");\n\tbool categoryEquipped = (selectedCategory == \"STR_FILTER_EQUIPPED\");\n\tbool categoryMissing = (selectedCategory == \"STR_FILTER_MISSING\");\n\n\tfor (size_t i = 0; i < _items.size(); ++i)\n\t{\n\t\t// filter\n\t\tif (categoryMissing)\n\t\t{\n\t\t\tint missingQty = getMissingQty(i);\n\t\t\tif (missingQty > -1)\n\t\t\t{\n\t\t\t\tif (!_autoBuyDone)\n\t\t\t\t{\n\t\t\t\t\tRuleItem* rule = (RuleItem*)_items[i].rule;\n\t\t\t\t\tif (rule->isAlien())\n\t\t\t\t\t{\n\t\t\t\t\t\t// don't buy automatically\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t_items[i].amount += missingQty; // buy automatically\n\n\t\t\t\t\t\t_iQty  += missingQty * rule->getSize(); // update total size\n\t\t\t\t\t\t_total += missingQty * _items[i].cost;  // update total cost\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\telse if (categoryEquipped)\n\t\t{\n\t\t\t// Note: showing also hidden items (if they are equipped)\n\t\t\tif (!isEquipped(i))\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tbool hidden = isHidden(i);\n\t\t\tif (categoryHidden)\n\t\t\t{\n\t\t\t\tif (!hidden)\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (hidden)\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\telse if (selCategory >= _vanillaCategories)\n\t\t\t{\n\t\t\t\tif (categoryUnassigned && _items[i].type == TRANSFER_ITEM)\n\t\t\t\t{\n\t\t\t\t\tRuleItem* rule = (RuleItem*)_items[i].rule;\n\t\t\t\t\tif (!rule->getCategories().empty())\n\t\t\t\t\t{\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (categoryFilterEnabled && !belongsToCategory(i, selectedCategory))\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (categoryFilterEnabled && selectedCategory != getCategory(i))\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// quick search\n\t\tif (!searchString.empty())\n\t\t{\n\t\t\tstd::string projectName = _items[i].name;\n\t\t\tUnicode::upperCase(projectName);\n\t\t\tif (projectName.find(searchString) == std::string::npos)\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\tstd::string name = _items[i].name;\n\t\tbool ammo = false;\n\t\tif (_items[i].type == TRANSFER_ITEM)\n\t\t{\n\t\t\tRuleItem *rule = (RuleItem*)_items[i].rule;\n\t\t\tammo = (rule->getBattleType() == BT_AMMO || (rule->getBattleType() == BT_NONE && rule->getClipSize() > 0));\n\t\t\tif (ammo)\n\t\t\t{\n\t\t\t\tname.insert(0, \"  \");\n\t\t\t}\n\t\t}\n\t\tstd::ostringstream ssQty, ssAmount;\n\t\tssQty << _items[i].qtySrc;\n\t\tssAmount << _items[i].amount;\n\t\t_lstItems->addRow(4, name.c_str(), Unicode::formatFunding(_items[i].cost).c_str(), ssQty.str().c_str(), ssAmount.str().c_str());\n\t\t_rows.push_back(i);\n\t\tif (_items[i].amount > 0)\n\t\t{\n\t\t\t_lstItems->setRowColor(_rows.size() - 1, _lstItems->getSecondaryColor());\n\t\t}\n\t\telse if (ammo)\n\t\t{\n\t\t\t_lstItems->setRowColor(_rows.size() - 1, _ammoColor);\n\t\t}\n\t}\n}\n\n/**\n * Purchases the selected items.\n * @param action Pointer to an action.\n */\nvoid PurchaseState::btnOkClick(Action *)\n{\n\tif (!_missingItemsMap.empty())\n\t{\n\t\tstd::string errorMessage;\n\t\tif (_total > _game->getSavedGame()->getFunds())\n\t\t{\n\t\t\terrorMessage = tr(\"STR_NOT_ENOUGH_MONEY\");\n\t\t}\n\t\tif (_base->storesOverfull(_iQty))\n\t\t{\n\t\t\terrorMessage = tr(\"STR_NOT_ENOUGH_STORE_SPACE\");\n\t\t}\n\t\tif (!errorMessage.empty())\n\t\t{\n\t\t\tRuleInterface* menuInterface = _game->getMod()->getInterface(\"buyMenu\");\n\t\t\t_game->pushState(new ErrorMessageState(errorMessage, _palette, menuInterface->getElement(\"errorMessage\")->color, \"BACK13.SCR\", menuInterface->getElement(\"errorPalette\")->color));\n\t\t\treturn;\n\t\t}\n\t}\n\n\t_game->getSavedGame()->setFunds(_game->getSavedGame()->getFunds() - _total);\n\tfor (const auto& transferRow : _items)\n\t{\n\t\tif (transferRow.amount > 0)\n\t\t{\n\t\t\tTransfer *t = 0;\n\t\t\tswitch (transferRow.type)\n\t\t\t{\n\t\t\tcase TRANSFER_SOLDIER:\n\t\t\t\tfor (int s = 0; s < transferRow.amount; s++)\n\t\t\t\t{\n\t\t\t\t\tRuleSoldier *rule = (RuleSoldier*)transferRow.rule;\n\t\t\t\t\tif (rule->getMonthlyBuyLimit() > 0)\n\t\t\t\t\t{\n\t\t\t\t\t\t// remember the hire for the limit check\n\t\t\t\t\t\tauto& soldierHireLimitLog = _game->getSavedGame()->getMonthlyPurchaseLimitLog();\n\t\t\t\t\t\tsoldierHireLimitLog[rule->getType()] += 1;\n\t\t\t\t\t}\n\t\t\t\t\tint time = rule->getTransferTime();\n\t\t\t\t\tif (time == 0)\n\t\t\t\t\t\ttime = _game->getMod()->getPersonnelTime();\n\t\t\t\t\tt = new Transfer(time);\n\t\t\t\t\tint nationality = _game->getSavedGame()->selectSoldierNationalityByLocation(_game->getMod(), rule, _base);\n\t\t\t\t\tSoldier* soldier = _game->getMod()->genSoldier(_game->getSavedGame(), rule, nationality);\n\t\t\t\t\tif (!rule->getSpawnedSoldierTemplate().yaml.empty())\n\t\t\t\t\t{\n\t\t\t\t\t\tYAML::YamlRootNodeReader reader(rule->getSpawnedSoldierTemplate(), \"(spawned soldier template)\");\n\t\t\t\t\t\tint nationalityOrig = soldier->getNationality();\n\t\t\t\t\t\tsoldier->load(reader.toBase(), _game->getMod(), _game->getSavedGame(), _game->getMod()->getScriptGlobal(), true); // load from soldier template\n\t\t\t\t\t\tif (soldier->getNationality() != nationalityOrig)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsoldier->genName();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tt->setSoldier(soldier);\n\t\t\t\t\t_base->getTransfers()->push_back(t);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase TRANSFER_SCIENTIST:\n\t\t\t\tt = new Transfer(_game->getMod()->getPersonnelTime());\n\t\t\t\tt->setScientists(transferRow.amount);\n\t\t\t\t_base->getTransfers()->push_back(t);\n\t\t\t\tbreak;\n\t\t\tcase TRANSFER_ENGINEER:\n\t\t\t\tt = new Transfer(_game->getMod()->getPersonnelTime());\n\t\t\t\tt->setEngineers(transferRow.amount);\n\t\t\t\t_base->getTransfers()->push_back(t);\n\t\t\t\tbreak;\n\t\t\tcase TRANSFER_CRAFT:\n\t\t\t\tfor (int c = 0; c < transferRow.amount; c++)\n\t\t\t\t{\n\t\t\t\t\tRuleCraft *rule = (RuleCraft*)transferRow.rule;\n\t\t\t\t\tif (rule->getMonthlyBuyLimit() > 0)\n\t\t\t\t\t{\n\t\t\t\t\t\t// remember the purchase for the limit check\n\t\t\t\t\t\tauto& craftPurchaseLimitLog = _game->getSavedGame()->getMonthlyPurchaseLimitLog();\n\t\t\t\t\t\tcraftPurchaseLimitLog[rule->getType()] += 1;\n\t\t\t\t\t}\n\t\t\t\t\tt = new Transfer(rule->getTransferTime());\n\t\t\t\t\tCraft *craft = new Craft(rule, _base, _game->getSavedGame()->getId(rule->getType()));\n\t\t\t\t\tcraft->initFixedWeapons(_game->getMod());\n\t\t\t\t\tcraft->setStatus(\"STR_REFUELLING\");\n\t\t\t\t\tt->setCraft(craft);\n\t\t\t\t\t_base->getTransfers()->push_back(t);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase TRANSFER_ITEM:\n\t\t\t\t{\n\t\t\t\t\tRuleItem *rule = (RuleItem*)transferRow.rule;\n\t\t\t\t\tif (rule->getMonthlyBuyLimit() > 0)\n\t\t\t\t\t{\n\t\t\t\t\t\t// remember the purchase for the limit check\n\t\t\t\t\t\tauto& itemPurchaseLimitLog = _game->getSavedGame()->getMonthlyPurchaseLimitLog();\n\t\t\t\t\t\titemPurchaseLimitLog[rule->getType()] += transferRow.amount;\n\t\t\t\t\t}\n\t\t\t\t\tt = new Transfer(rule->getTransferTime());\n\t\t\t\t\tt->setItems(rule, transferRow.amount);\n\t\t\t\t\t_base->getTransfers()->push_back(t);\n\t\t\t\t\tif (_parent && !_missingItemsMap.empty() && _missingItemsMap.find(rule) != _missingItemsMap.end())\n\t\t\t\t\t{\n\t\t\t\t\t\t// remember the decreased amount for next buy\n\t\t\t\t\t\t_parent->decreaseMissingItemCount(rule, transferRow.amount);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\t_game->popState();\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid PurchaseState::btnCancelClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Starts increasing the item.\n * @param action Pointer to an action.\n */\nvoid PurchaseState::lstItemsLeftArrowPress(Action *action)\n{\n\t_sel = _lstItems->getSelectedRow();\n\tif (_game->isLeftClick(action, true) && !_timerInc->isRunning()) _timerInc->start();\n}\n\n/**\n * Stops increasing the item.\n * @param action Pointer to an action.\n */\nvoid PurchaseState::lstItemsLeftArrowRelease(Action *action)\n{\n\tif (_game->isLeftClick(action, true))\n\t{\n\t\t_timerInc->stop();\n\t}\n}\n\n/**\n * Increases the item by one on left-click,\n * to max on right-click.\n * @param action Pointer to an action.\n */\nvoid PurchaseState::lstItemsLeftArrowClick(Action *action)\n{\n\tif (_game->isRightClick(action, true)) increaseByValue(INT_MAX);\n\tif (_game->isLeftClick(action, true))\n\t{\n\t\tincreaseByValue(_game->getScrollStep());\n\t\t_timerInc->setInterval(250);\n\t\t_timerDec->setInterval(250);\n\t}\n}\n\n/**\n * Starts decreasing the item.\n * @param action Pointer to an action.\n */\nvoid PurchaseState::lstItemsRightArrowPress(Action *action)\n{\n\t_sel = _lstItems->getSelectedRow();\n\tif (_game->isLeftClick(action, true) && !_timerDec->isRunning()) _timerDec->start();\n}\n\n/**\n * Stops decreasing the item.\n * @param action Pointer to an action.\n */\nvoid PurchaseState::lstItemsRightArrowRelease(Action *action)\n{\n\tif (_game->isLeftClick(action, true))\n\t{\n\t\t_timerDec->stop();\n\t}\n}\n\n/**\n * Decreases the item by one on left-click,\n * to 0 on right-click.\n * @param action Pointer to an action.\n */\nvoid PurchaseState::lstItemsRightArrowClick(Action *action)\n{\n\tif (_game->isRightClick(action, true)) decreaseByValue(INT_MAX);\n\tif (_game->isLeftClick(action, true))\n\t{\n\t\tdecreaseByValue(_game->getScrollStep());\n\t\t_timerInc->setInterval(250);\n\t\t_timerDec->setInterval(250);\n\t}\n}\n\n/**\n * Handles the mouse-wheels on the arrow-buttons.\n * @param action Pointer to an action.\n */\nvoid PurchaseState::lstItemsMousePress(Action *action)\n{\n\t_sel = _lstItems->getSelectedRow();\n\tif (action->getDetails()->button.button == SDL_BUTTON_WHEELUP)\n\t{\n\t\t_timerInc->stop();\n\t\t_timerDec->stop();\n\t\tif (action->getAbsoluteXMouse() >= _lstItems->getArrowsLeftEdge() &&\n\t\t\taction->getAbsoluteXMouse() <= _lstItems->getArrowsRightEdge())\n\t\t{\n\t\t\tincreaseByValue(Options::changeValueByMouseWheel);\n\t\t}\n\t}\n\telse if (action->getDetails()->button.button == SDL_BUTTON_WHEELDOWN)\n\t{\n\t\t_timerInc->stop();\n\t\t_timerDec->stop();\n\t\tif (action->getAbsoluteXMouse() >= _lstItems->getArrowsLeftEdge() &&\n\t\t\taction->getAbsoluteXMouse() <= _lstItems->getArrowsRightEdge())\n\t\t{\n\t\t\tdecreaseByValue(Options::changeValueByMouseWheel);\n\t\t}\n\t}\n\telse if (_game->isMiddleClick(action, true))\n\t{\n\t\tif (getRow().type == TRANSFER_ITEM)\n\t\t{\n\t\t\tRuleItem *rule = (RuleItem*)getRow().rule;\n\t\t\tif (rule != 0)\n\t\t\t{\n\t\t\t\tstd::string articleId = rule->getUfopediaType();\n\t\t\t\tUfopaedia::openArticle(_game, articleId);\n\t\t\t}\n\t\t}\n\t\telse if (getRow().type == TRANSFER_CRAFT)\n\t\t{\n\t\t\tRuleCraft *rule = (RuleCraft*)getRow().rule;\n\t\t\tif (rule != 0)\n\t\t\t{\n\t\t\t\tstd::string articleId = rule->getType();\n\t\t\t\tUfopaedia::openArticle(_game, articleId);\n\t\t\t}\n\t\t}\n\t}\n\telse if (_game->isRightClick(action, true))\n\t{\n\t\tif (action->getAbsoluteXMouse() >= _lstItems->getArrowsLeftEdge() &&\n\t\t\taction->getAbsoluteXMouse() <= _lstItems->getArrowsRightEdge())\n\t\t{\n\t\t\treturn;\n\t\t}\n\t\tstd::string itemName;\n\t\tif (getRow().type == TRANSFER_ITEM)\n\t\t{\n\t\t\tRuleItem *rule = (RuleItem*)getRow().rule;\n\t\t\tif (rule != 0)\n\t\t\t{\n\t\t\t\tif (_game->isCtrlPressed(true))\n\t\t\t\t{\n\t\t\t\t\t_game->pushState(new ItemLocationsState(rule));\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\titemName = rule->getType();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse if (getRow().type == TRANSFER_CRAFT)\n\t\t{\n\t\t\tRuleCraft *rule = (RuleCraft*)getRow().rule;\n\t\t\tif (rule != 0)\n\t\t\t{\n\t\t\t\titemName = rule->getType();\n\t\t\t}\n\t\t}\n\t\tif (!itemName.empty())\n\t\t{\n\t\t\tauto& hiddenMap = _game->getSavedGame()->getHiddenPurchaseItems();\n\t\t\tauto iter = hiddenMap.find(itemName);\n\t\t\tif (iter != hiddenMap.end())\n\t\t\t{\n\t\t\t\t// found => flip it\n\t\t\t\t_game->getSavedGame()->setHiddenPurchaseItemsStatus(itemName, !iter->second);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// not found = not hidden yet => hide it\n\t\t\t\t_game->getSavedGame()->setHiddenPurchaseItemsStatus(itemName, true);\n\t\t\t}\n\n\t\t\t// update screen\n\t\t\tsize_t scrollPos = _lstItems->getScroll();\n\t\t\tupdateList();\n\t\t\t_lstItems->scrollTo(scrollPos);\n\t\t}\n\t}\n}\n\n/**\n * Increases the quantity of the selected item to buy by one.\n */\nvoid PurchaseState::increase()\n{\n\t_timerDec->setInterval(50);\n\t_timerInc->setInterval(50);\n\tincreaseByValue(_game->getScrollStep());\n}\n\n/**\n * Increases the quantity of the selected item to buy by \"change\".\n * @param change How much we want to add.\n */\nvoid PurchaseState::increaseByValue(int change)\n{\n\tif (0 >= change) return;\n\tstd::string errorMessage;\n\n\tif (_total + getRow().cost > _game->getSavedGame()->getFunds())\n\t{\n\t\terrorMessage = tr(\"STR_NOT_ENOUGH_MONEY\");\n\t}\n\telse\n\t{\n\t\tRuleItem *rule = nullptr;\n\t\tRuleSoldier* ruleS = nullptr;\n\t\tRuleCraft* ruleC = nullptr;\n\t\tswitch (getRow().type)\n\t\t{\n\t\tcase TRANSFER_SOLDIER:\n\t\t\truleS = (RuleSoldier*)getRow().rule;\n\t\t\tif (ruleS->getMonthlyBuyLimit() > 0)\n\t\t\t{\n\t\t\t\tauto& soldierHireLimitLog = _game->getSavedGame()->getMonthlyPurchaseLimitLog();\n\t\t\t\tint alreadyBought = soldierHireLimitLog[ruleS->getType()];\n\t\t\t\tint maxByLimit = std::max(0, ruleS->getMonthlyBuyLimit() - alreadyBought - getRow().amount);\n\t\t\t\tif (maxByLimit <= 0)\n\t\t\t\t{\n\t\t\t\t\terrorMessage = tr(!ruleS->getMonthlyBuyLimitMessage().empty() ? ruleS->getMonthlyBuyLimitMessage() : \"STR_MONTHLY_SOLDIER_HIRING_LIMIT_EXCEEDED\")\n\t\t\t\t\t\t.arg(ruleS->getMonthlyBuyLimit())                 // {0} limit\n\t\t\t\t\t\t.arg(alreadyBought)                               // {1} already bought\n\t\t\t\t\t\t.arg(ruleS->getMonthlyBuyLimit() - alreadyBought) // {2} remaining\n\t\t\t\t\t\t.arg(tr(ruleS->getType()));                       // {3} soldier type\n\t\t\t\t}\n\t\t\t}\n\t\t\t// fall-through\n\t\tcase TRANSFER_SCIENTIST:\n\t\tcase TRANSFER_ENGINEER:\n\t\t\tif (_pQty + 1 > _base->getAvailableQuarters() - _base->getUsedQuarters())\n\t\t\t{\n\t\t\t\terrorMessage = tr(\"STR_NOT_ENOUGH_LIVING_SPACE\");\n\t\t\t}\n\t\t\tbreak;\n\t\tcase TRANSFER_CRAFT:\n\t\t\truleC = (RuleCraft*)getRow().rule;\n\t\t\tif (_cQty + 1 > _base->getAvailableHangars() - _base->getUsedHangars())\n\t\t\t{\n\t\t\t\terrorMessage = tr(\"STR_NO_FREE_HANGARS_FOR_PURCHASE\");\n\t\t\t}\n\t\t\telse if (ruleC->getMonthlyBuyLimit() > 0)\n\t\t\t{\n\t\t\t\tauto& craftPurchaseLimitLog = _game->getSavedGame()->getMonthlyPurchaseLimitLog();\n\t\t\t\tint alreadyBought = craftPurchaseLimitLog[ruleC->getType()];\n\t\t\t\tint maxByLimit = std::max(0, ruleC->getMonthlyBuyLimit() - alreadyBought - getRow().amount);\n\t\t\t\tif (maxByLimit <= 0)\n\t\t\t\t{\n\t\t\t\t\terrorMessage = tr(!ruleC->getMonthlyBuyLimitMessage().empty() ? ruleC->getMonthlyBuyLimitMessage() : \"STR_MONTHLY_CRAFT_PURCHASE_LIMIT_EXCEEDED\")\n\t\t\t\t\t\t.arg(ruleC->getMonthlyBuyLimit())                 // {0} limit\n\t\t\t\t\t\t.arg(alreadyBought)                               // {1} already bought\n\t\t\t\t\t\t.arg(ruleC->getMonthlyBuyLimit() - alreadyBought) // {2} remaining\n\t\t\t\t\t\t.arg(tr(ruleC->getType()));                       // {3} craft type\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tcase TRANSFER_ITEM:\n\t\t\trule = (RuleItem*)getRow().rule;\n\t\t\tif (_base->storesOverfull(_iQty + rule->getSize()))\n\t\t\t{\n\t\t\t\terrorMessage = tr(\"STR_NOT_ENOUGH_STORE_SPACE\");\n\t\t\t}\n\t\t\telse if (rule->isAlien())\n\t\t\t{\n\t\t\t\tint p = rule->getPrisonType();\n\t\t\t\tif (_iPrisonQty[p] + 1 > _base->getAvailableContainment(p) - _base->getUsedContainment(p))\n\t\t\t\t{\n\t\t\t\t\terrorMessage = trAlt(\"STR_NOT_ENOUGH_PRISON_SPACE\", p);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (rule->getMonthlyBuyLimit() > 0)\n\t\t\t{\n\t\t\t\tauto& itemPurchaseLimitLog = _game->getSavedGame()->getMonthlyPurchaseLimitLog();\n\t\t\t\tint alreadyBought = itemPurchaseLimitLog[rule->getType()];\n\t\t\t\tint maxByLimit = std::max(0, rule->getMonthlyBuyLimit() - alreadyBought - getRow().amount);\n\t\t\t\tif (maxByLimit <= 0)\n\t\t\t\t{\n\t\t\t\t\terrorMessage = tr(!rule->getMonthlyBuyLimitMessage().empty() ? rule->getMonthlyBuyLimitMessage() : \"STR_MONTHLY_ITEM_PURCHASE_LIMIT_EXCEEDED\")\n\t\t\t\t\t\t.arg(rule->getMonthlyBuyLimit())                 // {0} limit\n\t\t\t\t\t\t.arg(alreadyBought)                              // {1} already bought\n\t\t\t\t\t\t.arg(rule->getMonthlyBuyLimit() - alreadyBought) // {2} remaining\n\t\t\t\t\t\t.arg(tr(rule->getType()));                       // {3} item type\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (errorMessage.empty())\n\t{\n\t\tint maxByMoney = (_game->getSavedGame()->getFunds() - _total) / getRow().cost;\n\t\tif (maxByMoney >= 0)\n\t\t\tchange = std::min(maxByMoney, change);\n\t\tswitch (getRow().type)\n\t\t{\n\t\tcase TRANSFER_SOLDIER:\n\t\t\t{\n\t\t\t\tRuleSoldier *ruleS = (RuleSoldier*)getRow().rule;\n\t\t\t\tif (ruleS->getMonthlyBuyLimit() > 0)\n\t\t\t\t{\n\t\t\t\t\tauto& soldierHireLimitLog = _game->getSavedGame()->getMonthlyPurchaseLimitLog();\n\t\t\t\t\tint maxByLimit = std::max(0, ruleS->getMonthlyBuyLimit() - soldierHireLimitLog[ruleS->getType()] - getRow().amount);\n\t\t\t\t\tchange = std::min(maxByLimit, change);\n\t\t\t\t}\n\t\t\t}\n\t\t\t// fall-through\n\t\tcase TRANSFER_SCIENTIST:\n\t\tcase TRANSFER_ENGINEER:\n\t\t\t{\n\t\t\t\tint maxByQuarters = _base->getAvailableQuarters() - _base->getUsedQuarters() - _pQty;\n\t\t\t\tchange = std::min(maxByQuarters, change);\n\t\t\t\t_pQty += change;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase TRANSFER_CRAFT:\n\t\t\t{\n\t\t\t\tRuleCraft *ruleC = (RuleCraft*)getRow().rule;\n\t\t\t\tif (ruleC->getMonthlyBuyLimit() > 0)\n\t\t\t\t{\n\t\t\t\t\tauto& craftPurchaseLimitLog = _game->getSavedGame()->getMonthlyPurchaseLimitLog();\n\t\t\t\t\tint maxByLimit = std::max(0, ruleC->getMonthlyBuyLimit() - craftPurchaseLimitLog[ruleC->getType()] - getRow().amount);\n\t\t\t\t\tchange = std::min(maxByLimit, change);\n\t\t\t\t}\n\t\t\t\tint maxByHangars = _base->getAvailableHangars() - _base->getUsedHangars() - _cQty;\n\t\t\t\tchange = std::min(maxByHangars, change);\n\t\t\t\t_cQty += change;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase TRANSFER_ITEM:\n\t\t\t{\n\t\t\t\tRuleItem *rule = (RuleItem*)getRow().rule;\n\t\t\t\tif (rule->getMonthlyBuyLimit() > 0)\n\t\t\t\t{\n\t\t\t\t\tauto& itemPurchaseLimitLog = _game->getSavedGame()->getMonthlyPurchaseLimitLog();\n\t\t\t\t\tint maxByLimit = std::max(0, rule->getMonthlyBuyLimit() - itemPurchaseLimitLog[rule->getType()] - getRow().amount);\n\t\t\t\t\tchange = std::min(maxByLimit, change);\n\t\t\t\t}\n\t\t\t\tint p = rule->getPrisonType();\n\t\t\t\tif (rule->isAlien())\n\t\t\t\t{\n\t\t\t\t\tint maxByPrisons = _base->getAvailableContainment(p) - _base->getUsedContainment(p) - _iPrisonQty[p];\n\t\t\t\t\tchange = std::min(maxByPrisons, change);\n\t\t\t\t}\n\t\t\t\t// both aliens and items\n\t\t\t\t{\n\t\t\t\t\tdouble storesNeededPerItem = rule->getSize();\n\t\t\t\t\tdouble freeStores = _base->getAvailableStores() - _base->getUsedStores() - _iQty;\n\t\t\t\t\tdouble maxByStores = (double)(INT_MAX);\n\t\t\t\t\tif (!AreSame(storesNeededPerItem, 0.0) && storesNeededPerItem > 0.0)\n\t\t\t\t\t{\n\t\t\t\t\t\tmaxByStores = (freeStores + 0.05) / storesNeededPerItem;\n\t\t\t\t\t}\n\t\t\t\t\tchange = std::min((int)maxByStores, change);\n\t\t\t\t\t_iQty += change * storesNeededPerItem;\n\t\t\t\t}\n\t\t\t\tif (rule->isAlien())\n\t\t\t\t{\n\t\t\t\t\t_iPrisonQty[p] += change;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tgetRow().amount += change;\n\t\t_total += getRow().cost * change;\n\t\tupdateItemStrings();\n\t}\n\telse\n\t{\n\t\t_timerInc->stop();\n\t\tRuleInterface *menuInterface = _game->getMod()->getInterface(\"buyMenu\");\n\t\t_game->pushState(new ErrorMessageState(\n\t\t\terrorMessage,\n\t\t\t_palette,\n\t\t\tmenuInterface->getElement(\"errorMessage\")->color,\n\t\t\t\"BACK13.SCR\",\n\t\t\tmenuInterface->getElement(\"errorPalette\")->color,\n\t\t\tmenuInterface->getElement(\"errorMessage\")->color2\n\t\t));\n\t}\n}\n\n/**\n * Decreases the quantity of the selected item to buy by one.\n */\nvoid PurchaseState::decrease()\n{\n\t_timerInc->setInterval(50);\n\t_timerDec->setInterval(50);\n\tdecreaseByValue(_game->getScrollStep());\n}\n\n/**\n * Decreases the quantity of the selected item to buy by \"change\".\n * @param change how much we want to add.\n */\nvoid PurchaseState::decreaseByValue(int change)\n{\n\tif (0 >= change || 0 >= getRow().amount) return;\n\tchange = std::min(getRow().amount, change);\n\n\tRuleItem *rule = nullptr;\n\tswitch (getRow().type)\n\t{\n\tcase TRANSFER_SOLDIER:\n\tcase TRANSFER_SCIENTIST:\n\tcase TRANSFER_ENGINEER:\n\t\t_pQty -= change;\n\t\tbreak;\n\tcase TRANSFER_CRAFT:\n\t\t_cQty -= change;\n\t\tbreak;\n\tcase TRANSFER_ITEM:\n\t\trule = (RuleItem*)getRow().rule;\n\t\t_iQty -= rule->getSize() * change;\n\t\tif (rule->isAlien())\n\t\t{\n\t\t\t_iPrisonQty[rule->getPrisonType()] -= change;\n\t\t}\n\t\tbreak;\n\t}\n\tgetRow().amount -= change;\n\t_total -= getRow().cost * change;\n\tupdateItemStrings();\n}\n\n/**\n * Updates the quantity-strings of the selected item.\n */\nvoid PurchaseState::updateItemStrings()\n{\n\t_txtPurchases->setText(tr(\"STR_COST_OF_PURCHASES\").arg(Unicode::formatFunding(_total)));\n\tstd::ostringstream ss, ss5;\n\tss << getRow().amount;\n\t_lstItems->setCellText(_sel, 3, ss.str());\n\tif (getRow().amount > 0)\n\t{\n\t\t_lstItems->setRowColor(_sel, _lstItems->getSecondaryColor());\n\t}\n\telse\n\t{\n\t\t_lstItems->setRowColor(_sel, _lstItems->getColor());\n\t\tif (getRow().type == TRANSFER_ITEM)\n\t\t{\n\t\t\tRuleItem *rule = (RuleItem*)getRow().rule;\n\t\t\tif (rule->getBattleType() == BT_AMMO || (rule->getBattleType() == BT_NONE && rule->getClipSize() > 0))\n\t\t\t{\n\t\t\t\t_lstItems->setRowColor(_sel, _ammoColor);\n\t\t\t}\n\t\t}\n\t}\n\tss5 << _base->getUsedStores();\n\tif (std::abs(_iQty) > 0.05)\n\t{\n\t\tss5 << \"(\";\n\t\tif (_iQty > 0.05)\n\t\t\tss5 << \"+\";\n\t\tss5 << std::fixed << std::setprecision(1) << _iQty << \")\";\n\t}\n\tss5 << \":\" << _base->getAvailableStores();\n\t_txtSpaceUsed->setText(tr(\"STR_SPACE_USED\").arg(ss5.str()));\n}\n\n/**\n * Updates the production list to match the category filter.\n */\nvoid PurchaseState::cbxCategoryChange(Action *)\n{\n\tupdateList();\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/PurchaseState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/TouchState.h\"\n#include \"../Savegame/Transfer.h\"\n#include <vector>\n#include <string>\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass TextEdit;\nclass TextList;\nclass ComboBox;\nclass Timer;\nclass Base;\nclass CannotReequipState;\nclass RuleItem;\n\n/**\n * Purchase/Hire screen that lets the player buy\n * new items for a base.\n */\nclass PurchaseState : public TouchState\n{\nprivate:\n\tBase *_base;\n\tCannotReequipState *_parent;\n\tbool _autoBuyDone;\n\tstd::map<RuleItem*, int> _missingItemsMap;\n\n\tTextButton *_btnOk, *_btnCancel;\n\tTextEdit *_btnQuickSearch;\n\tWindow *_window;\n\tText *_txtTitle, *_txtFunds, *_txtPurchases, *_txtCost, *_txtQuantity, *_txtSpaceUsed;\n\tComboBox *_cbxCategory;\n\tTextList *_lstItems;\n\tstd::vector<TransferRow> _items;\n\tstd::vector<int> _rows;\n\tstd::vector<std::string> _cats;\n\tsize_t _vanillaCategories;\n\tsize_t _sel;\n\tint _total, _pQty, _cQty;\n\tdouble _iQty;\n\tstd::map<int, int> _iPrisonQty;\n\tUint8 _ammoColor;\n\tTimer *_timerInc, *_timerDec;\n\t/// Gets the category of the current selection.\n\tstd::string getCategory(int sel) const;\n\t/// Determines if the current selection belongs to a given category.\n\tbool belongsToCategory(int sel, const std::string &cat) const;\n\t/// Checks for hidden items\n\tbool isHidden(int sel) const;\n\t/// Checks for equipped items\n\tbool isEquipped(int sel) const;\n\t/// Checks for missing items\n\tint getMissingQty(int sel) const;\n\t/// Gets the row of the current selection.\n\tTransferRow &getRow() { return _items[_rows[_sel]]; }\npublic:\n\t/// Creates the Purchase state.\n\tPurchaseState(Base *base, CannotReequipState *parent = nullptr);\n\t/// Cleans up the Purchase state.\n\t~PurchaseState();\n\t/// Resets state.\n\tvoid init() override;\n\t/// Runs the timers.\n\tvoid think() override;\n\t/// Updates the item list.\n\tvoid updateList();\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action *action);\n\t/// Handlers for Quick Search.\n\tvoid btnQuickSearchToggle(Action *action);\n\tvoid btnQuickSearchApply(Action *action);\n\t/// Handler for pressing an Increase arrow in the list.\n\tvoid lstItemsLeftArrowPress(Action *action);\n\t/// Handler for releasing an Increase arrow in the list.\n\tvoid lstItemsLeftArrowRelease(Action *action);\n\t/// Handler for clicking an Increase arrow in the list.\n\tvoid lstItemsLeftArrowClick(Action *action);\n\t/// Handler for pressing a Decrease arrow in the list.\n\tvoid lstItemsRightArrowPress(Action *action);\n\t/// Handler for releasing a Decrease arrow in the list.\n\tvoid lstItemsRightArrowRelease(Action *action);\n\t/// Handler for clicking a Decrease arrow in the list.\n\tvoid lstItemsRightArrowClick(Action *action);\n\t/// Handler for pressing-down a mouse-button in the list.\n\tvoid lstItemsMousePress(Action *action);\n\t/// Increases the quantity of an item by one.\n\tvoid increase();\n\t/// Increases the quantity of an item by the given value.\n\tvoid increaseByValue(int change);\n\t/// Decreases the quantity of an item by one.\n\tvoid decrease();\n\t/// Decreases the quantity of an item by the given value.\n\tvoid decreaseByValue(int change);\n\t/// Updates the quantity-strings of the selected item.\n\tvoid updateItemStrings();\n\t/// Handler for changing the category filter.\n\tvoid cbxCategoryChange(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/ResearchInfoState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ResearchInfoState.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Mod/RuleResearch.h\"\n#include \"../Savegame/ItemContainer.h\"\n#include \"../Savegame/ResearchProject.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Interface/ArrowButton.h\"\n#include \"../Engine/Timer.h\"\n#include \"../Engine/RNG.h\"\n#include <climits>\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the ResearchProject screen.\n * @param game Pointer to the core game.\n * @param base Pointer to the base to get info from.\n * @param rule A RuleResearch which will be used to create a new ResearchProject\n */\nResearchInfoState::ResearchInfoState(Base *base, RuleResearch *rule) : _base(base), _project(nullptr), _rule(rule)\n{\n\tint rng = RNG::generate(50, 150);\n\tint randomizedCost = rule->getCost() * rng / 100;\n\tif (rule->getCost() > 0)\n\t{\n\t\trandomizedCost = std::max(1, randomizedCost);\n\t}\n\t_project = new ResearchProject(rule, randomizedCost);\n\n\tbuildUi();\n}\n\n/**\n * Initializes all the elements in the ResearchProject screen.\n * @param game Pointer to the core game.\n * @param base Pointer to the base to get info from.\n * @param project A ResearchProject to modify\n */\nResearchInfoState::ResearchInfoState(Base *base, ResearchProject *project) : _base(base), _project(project), _rule(0)\n{\n\tbuildUi();\n}\n\n/**\n * Builds dialog.\n */\nvoid ResearchInfoState::buildUi()\n{\n\t_screen = false;\n\n\t_window = new Window(this, 230, 140, 45, 30);\n\t_txtTitle = new Text(210, 17, 61, 40);\n\n\t_txtAvailableScientist = new Text(210, 9, 61, 60);\n\t_txtAvailableSpace = new Text(210, 9, 61, 70);\n\t_txtAllocatedScientist = new Text(210, 17, 61, 80);\n\t_txtMore = new Text(110, 17, 85, 100);\n\t_txtLess = new Text(110, 17, 85, 120);\n\t_btnCancel = new TextButton(90, 16, 61, 145);\n\t_btnOk = new TextButton(90, 16, 169, 145);\n\n\t_btnMore = new ArrowButton(ARROW_BIG_UP, 13, 14, 195, 100);\n\t_btnLess = new ArrowButton(ARROW_BIG_DOWN, 13, 14, 195, 120);\n\n\t_surfaceScientists = new InteractiveSurface(230, 140, 45, 30);\n\t_surfaceScientists->onMouseClick((ActionHandler)&ResearchInfoState::handleWheel, 0);\n\n\t// Set palette\n\tsetInterface(\"allocateResearch\");\n\n\tadd(_surfaceScientists);\n\tadd(_window, \"window\", \"allocateResearch\");\n\tadd(_btnOk, \"button2\", \"allocateResearch\");\n\tadd(_btnCancel, \"button2\", \"allocateResearch\");\n\tadd(_txtTitle, \"text\", \"allocateResearch\");\n\tadd(_txtAvailableScientist, \"text\", \"allocateResearch\");\n\tadd(_txtAvailableSpace, \"text\", \"allocateResearch\");\n\tadd(_txtAllocatedScientist, \"text\", \"allocateResearch\");\n\tadd(_txtMore, \"text\", \"allocateResearch\");\n\tadd(_txtLess, \"text\", \"allocateResearch\");\n\tadd(_btnMore, \"button1\", \"allocateResearch\");\n\tadd(_btnLess, \"button1\", \"allocateResearch\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"allocateResearch\");\n\n\t_txtTitle->setBig();\n\n\t_txtTitle->setText(_rule ? tr(_rule->getName()) : tr(_project->getRules()->getName()));\n\n\t_txtAllocatedScientist->setBig();\n\n\t_txtMore->setText(tr(\"STR_INCREASE\"));\n\t_txtLess->setText(tr(\"STR_DECREASE\"));\n\n\t_txtMore->setBig();\n\t_txtLess->setBig();\n\n\tif (_rule)\n\t{\n\t\t_base->addResearch(_project);\n\t\tif (_rule->isHoldingNeededItem())\n\t\t{\n\t\t\t_base->getStorageItems()->removeItem(_rule->getNeededItem(), 1);\n\t\t}\n\t}\n\tsetAssignedScientist();\n\t_btnMore->onMousePress((ActionHandler)&ResearchInfoState::morePress);\n\t_btnMore->onMouseRelease((ActionHandler)&ResearchInfoState::moreRelease);\n\t_btnMore->onMouseClick((ActionHandler)&ResearchInfoState::moreClick, 0);\n\t_btnLess->onMousePress((ActionHandler)&ResearchInfoState::lessPress);\n\t_btnLess->onMouseRelease((ActionHandler)&ResearchInfoState::lessRelease);\n\t_btnLess->onMouseClick((ActionHandler)&ResearchInfoState::lessClick, 0);\n\n\t_timerMore = new Timer(250);\n\t_timerMore->onTimer((StateHandler)&ResearchInfoState::more);\n\t_timerLess = new Timer(250);\n\t_timerLess->onTimer((StateHandler)&ResearchInfoState::less);\n\n\t_btnOk->onMouseClick((ActionHandler)&ResearchInfoState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&ResearchInfoState::btnOkClick, Options::keyOk);\n\tif (_rule)\n\t{\n\t\t_btnOk->setText(tr(\"STR_START_PROJECT\"));\n\t\t_btnCancel->setText(tr(\"STR_CANCEL_UC\"));\n\t\t_btnCancel->onKeyboardPress((ActionHandler)&ResearchInfoState::btnCancelClick, Options::keyCancel);\n\t}\n\telse\n\t{\n\t\t_btnOk->setText(tr(\"STR_OK\"));\n\t\t_btnCancel->setText(tr(\"STR_CANCEL_PROJECT\"));\n\t\t_btnOk->onKeyboardPress((ActionHandler)&ResearchInfoState::btnOkClick, Options::keyCancel);\n\t}\n\t_btnCancel->onMouseClick((ActionHandler)&ResearchInfoState::btnCancelClick);\n\n\tif (_rule)\n\t{\n\t\t// mark new/hidden as normal\n\t\t_game->getSavedGame()->setResearchRuleStatus(_rule->getName(), RuleResearch::RESEARCH_STATUS_NORMAL);\n\t}\n}\n\n/**\n * Frees up memory that's not automatically cleaned on exit\n */\nResearchInfoState::~ResearchInfoState()\n{\n\tdelete _timerLess;\n\tdelete _timerMore;\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid ResearchInfoState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Returns to the previous screen, removing the current project from the active\n * research list.\n * @param action Pointer to an action.\n */\nvoid ResearchInfoState::btnCancelClick(Action *)\n{\n\t_base->removeResearch(_project);\n\t_game->popState();\n}\n\n/**\n * Updates count of assigned/free scientists and available lab space.\n */\nvoid ResearchInfoState::setAssignedScientist()\n{\n\t_txtAvailableScientist->setText(tr(\"STR_SCIENTISTS_AVAILABLE_UC\").arg(_base->getAvailableScientists()));\n\t_txtAvailableSpace->setText(tr(\"STR_LABORATORY_SPACE_AVAILABLE_UC\").arg(_base->getFreeLaboratories()));\n\t_txtAllocatedScientist->setText(tr(\"STR_SCIENTISTS_ALLOCATED\").arg(_project->getAssigned()));\n}\n\n/**\n * Increases or decreases the scientists according the mouse-wheel used.\n * @param action Pointer to an Action.\n */\nvoid ResearchInfoState::handleWheel(Action *action)\n{\n\tif (action->getDetails()->button.button == SDL_BUTTON_WHEELUP) moreByValue(Options::changeValueByMouseWheel);\n\telse if (action->getDetails()->button.button == SDL_BUTTON_WHEELDOWN) lessByValue(Options::changeValueByMouseWheel);\n}\n\n/**\n * Starts the timeMore timer.\n * @param action Pointer to an Action.\n */\nvoid ResearchInfoState::morePress(Action *action)\n{\n\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT) _timerMore->start();\n}\n\n/**\n * Stops the timeMore timer.\n * @param action Pointer to an Action.\n */\nvoid ResearchInfoState::moreRelease(Action *action)\n{\n\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT)\n\t{\n\t\t_timerMore->setInterval(250);\n\t\t_timerMore->stop();\n\t}\n}\n\n/**\n * Allocates scientists to the current project;\n * one scientist on left-click, all scientists on right-click.\n * @param action Pointer to an Action.\n */\nvoid ResearchInfoState::moreClick(Action *action)\n{\n\tif (action->getDetails()->button.button == SDL_BUTTON_RIGHT)\n\t\tmoreByValue(INT_MAX);\n\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT)\n\t\tmoreByValue(1);\n}\n\n/**\n * Starts the timeLess timer.\n * @param action Pointer to an Action.\n */\nvoid ResearchInfoState::lessPress(Action *action)\n{\n\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT) _timerLess->start();\n}\n\n/**\n * Stops the timeLess timer.\n * @param action Pointer to an Action.\n */\nvoid ResearchInfoState::lessRelease(Action *action)\n{\n\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT)\n\t{\n\t\t_timerLess->setInterval(250);\n\t\t_timerLess->stop();\n\t}\n}\n\n/**\n * Removes scientists from the current project;\n * one scientist on left-click, all scientists on right-click.\n * @param action Pointer to an Action.\n */\nvoid ResearchInfoState::lessClick(Action *action)\n{\n\tif (action->getDetails()->button.button == SDL_BUTTON_RIGHT)\n\t\tlessByValue(INT_MAX);\n\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT)\n\t\tlessByValue(1);\n}\n\n/**\n * Adds one scientist to the project if possible.\n */\nvoid ResearchInfoState::more()\n{\n\t_timerMore->setInterval(50);\n\tmoreByValue(1);\n}\n\n/**\n * Adds the given number of scientists to the project if possible.\n * @param change Number of scientists to add.\n */\nvoid ResearchInfoState::moreByValue(int change)\n{\n\tif (0 >= change) return;\n\tint freeScientist = _base->getAvailableScientists();\n\tint freeSpaceLab = _base->getFreeLaboratories();\n\tif (freeScientist > 0 && freeSpaceLab > 0)\n\t{\n\t\tchange = std::min(std::min(freeScientist, freeSpaceLab), change);\n\t\t_project->setAssigned(_project->getAssigned()+change);\n\t\t_base->setScientists(_base->getScientists()-change);\n\t\tsetAssignedScientist();\n\t}\n}\n\n/**\n * Removes one scientist from the project if possible.\n */\nvoid ResearchInfoState::less()\n{\n\t_timerLess->setInterval(50);\n\tlessByValue(1);\n}\n\n/**\n * Removes the given number of scientists from the project if possible.\n * @param change Number of scientists to subtract.\n */\nvoid ResearchInfoState::lessByValue(int change)\n{\n\tif (0 >= change) return;\n\tint assigned = _project->getAssigned();\n\tif (assigned > 0)\n\t{\n\t\tchange = std::min(assigned, change);\n\t\t_project->setAssigned(assigned-change);\n\t\t_base->setScientists(_base->getScientists()+change);\n\t\tsetAssignedScientist();\n\t}\n}\n\n/**\n * Runs state functionality every cycle (used to update the timer).\n */\nvoid ResearchInfoState::think()\n{\n\tState::think();\n\n\t_timerLess->think (this, 0);\n\t_timerMore->think (this, 0);\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/ResearchInfoState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass Base;\nclass RuleResearch;\nclass ResearchProject;\nclass ArrowButton;\nclass Timer;\nclass InteractiveSurface;\n\n/**\n * Window which allows changing of the number of assigned scientist to a project.\n */\nclass ResearchInfoState : public State\n{\nprivate:\n\tBase *_base;\n\tTextButton *_btnOk;\n\tTextButton *_btnCancel;\n\tArrowButton *_btnMore, *_btnLess;\n\tWindow *_window;\n\tText *_txtTitle, *_txtAvailableScientist, *_txtAvailableSpace, *_txtAllocatedScientist, *_txtMore, *_txtLess;\n\tvoid setAssignedScientist();\n\tResearchProject *_project;\n\tRuleResearch *_rule;\n\tvoid buildUi();\n\tTimer *_timerMore, *_timerLess;\n\tInteractiveSurface *_surfaceScientists;\npublic:\n\t/// Creates the ResearchProject state.\n\tResearchInfoState(Base *base, RuleResearch *rule);\n\tResearchInfoState(Base *base, ResearchProject *project);\n\t/// Cleans up the ResearchInfo state\n\t~ResearchInfoState();\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action *action);\n\t/// Function called every time the _timerMore timer is triggered.\n\tvoid more();\n\t/// Add given number of scientists to the project if possible\n\tvoid moreByValue(int change);\n\t/// Function called every time the _timerLess timer is triggered.\n\tvoid less();\n\t/// Remove the given number of scientists from the project if possible\n\tvoid lessByValue(int change);\n\t/// Handler for using the mouse wheel.\n\tvoid handleWheel(Action *action);\n\t/// Handler for pressing the More button.\n\tvoid morePress(Action *action);\n\t/// Handler for releasing the More button.\n\tvoid moreRelease(Action *action);\n\t/// Handler for clicking the More button.\n\tvoid moreClick(Action *action);\n\t/// Handler for pressing the Less button.\n\tvoid lessPress(Action *action);\n\t/// Handler for releasing the Less button.\n\tvoid lessRelease(Action *action);\n\t/// Handler for clicking the Less button.\n\tvoid lessClick(Action *action);\n\t/// Runs state functionality every cycle(used to update the timer).\n\tvoid think() override;\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/ResearchState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ResearchState.h\"\n#include <sstream>\n#include \"../Engine/Action.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Savegame/Base.h\"\n#include \"NewResearchListState.h\"\n#include \"GlobalResearchState.h\"\n#include \"../Savegame/ResearchProject.h\"\n#include \"../Mod/RuleResearch.h\"\n#include \"ResearchInfoState.h\"\n#include \"TechTreeViewerState.h\"\n#include <algorithm>\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Research screen.\n * @param game Pointer to the core game.\n * @param base Pointer to the base to get info from.\n */\nResearchState::ResearchState(Base *base) : _base(base)\n{\n\t// Create objects\n\t_window = new Window(this, 320, 200, 0, 0);\n\t_btnNew = new TextButton(148, 16, 8, 176);\n\t_btnOk = new TextButton(148, 16, 164, 176);\n\t_txtTitle = new Text(310, 17, 5, 8);\n\t_txtAvailable = new Text(150, 9, 10, 24);\n\t_txtAllocated = new Text(150, 9, 160, 24);\n\t_txtSpace = new Text(300, 9, 10, 34);\n\t_txtProject = new Text(110, 17, 10, 44);\n\t_txtScientists = new Text(106, 17, 120, 44);\n\t_txtProgress = new Text(84, 9, 226, 44);\n\t_lstResearch = new TextList(288, 112, 8, 62);\n\n\t// Set palette\n\tsetInterface(\"researchMenu\");\n\n\tadd(_window, \"window\", \"researchMenu\");\n\tadd(_btnNew, \"button\", \"researchMenu\");\n\tadd(_btnOk, \"button\", \"researchMenu\");\n\tadd(_txtTitle, \"text\", \"researchMenu\");\n\tadd(_txtAvailable, \"text\", \"researchMenu\");\n\tadd(_txtAllocated, \"text\", \"researchMenu\");\n\tadd(_txtSpace, \"text\", \"researchMenu\");\n\tadd(_txtProject, \"text\", \"researchMenu\");\n\tadd(_txtScientists, \"text\", \"researchMenu\");\n\tadd(_txtProgress, \"text\", \"researchMenu\");\n\tadd(_lstResearch, \"list\", \"researchMenu\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"researchMenu\");\n\n\t_btnNew->setText(tr(\"STR_NEW_PROJECT\"));\n\t_btnNew->onMouseClick((ActionHandler)&ResearchState::btnNewClick);\n\t_btnNew->onKeyboardPress((ActionHandler)&ResearchState::btnNewClick, Options::keyToggleQuickSearch);\n\t_btnNew->onKeyboardPress((ActionHandler)&ResearchState::onCurrentGlobalResearchClick, Options::keyGeoGlobalResearch);\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&ResearchState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&ResearchState::btnOkClick, Options::keyCancel);\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_CURRENT_RESEARCH\"));\n\n\t_txtProject->setWordWrap(true);\n\t_txtProject->setText(tr(\"STR_RESEARCH_PROJECT\"));\n\n\t_txtScientists->setWordWrap(true);\n\t_txtScientists->setText(tr(\"STR_SCIENTISTS_ALLOCATED_UC\"));\n\n\t_txtProgress->setText(tr(\"STR_PROGRESS\"));\n\n\tif (Options::oxceBaseResearchReorder)\n\t{\n\t\t_lstResearch->setArrowColumn(192, ARROW_VERTICAL);\n\t}\n\t_lstResearch->setColumns(3, 158, 58, 70);\n\t_lstResearch->setSelectable(true);\n\t_lstResearch->setBackground(_window);\n\t_lstResearch->setMargin(2);\n\t_lstResearch->setWordWrap(true);\n\tif (Options::oxceBaseResearchReorder)\n\t{\n\t\t_lstResearch->onLeftArrowClick((ActionHandler)&ResearchState::lstResearchLeftArrowClick);\n\t\t_lstResearch->onRightArrowClick((ActionHandler)&ResearchState::lstResearchRightArrowClick);\n\t}\n\t_lstResearch->onMouseClick((ActionHandler)&ResearchState::onSelectProject, SDL_BUTTON_LEFT);\n\t_lstResearch->onMouseClick((ActionHandler)&ResearchState::onOpenTechTreeViewer, SDL_BUTTON_MIDDLE);\n\t_lstResearch->onMousePress((ActionHandler)&ResearchState::lstResearchMousePress);\n}\n\n/**\n *\n */\nResearchState::~ResearchState()\n{\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid ResearchState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid ResearchState::btnNewClick(Action *)\n{\n\tbool sortByCost = _game->isCtrlPressed() && _game->isAltPressed();\n\t_game->pushState(new NewResearchListState(_base, sortByCost));\n}\n\n/**\n * Displays the list of possible ResearchProjects.\n * @param action Pointer to an action.\n */\nvoid ResearchState::onSelectProject(Action *action)\n{\n\tdouble mx = action->getAbsoluteXMouse();\n\tif (mx >= _lstResearch->getArrowsLeftEdge() && mx < _lstResearch->getArrowsRightEdge())\n\t{\n\t\treturn;\n\t}\n\n\tconst std::vector<ResearchProject *> & baseProjects(_base->getResearch());\n\t_game->pushState(new ResearchInfoState(_base, baseProjects[_lstResearch->getSelectedRow()]));\n}\n\n/**\n* Opens the TechTreeViewer for the corresponding topic.\n* @param action Pointer to an action.\n*/\nvoid ResearchState::onOpenTechTreeViewer(Action *action)\n{\n\tdouble mx = action->getAbsoluteXMouse();\n\tif (mx >= _lstResearch->getArrowsLeftEdge() && mx < _lstResearch->getArrowsRightEdge())\n\t{\n\t\treturn;\n\t}\n\n\tconst std::vector<ResearchProject *> & baseProjects(_base->getResearch());\n\tconst RuleResearch *selectedTopic = baseProjects[_lstResearch->getSelectedRow()]->getRules();\n\t_game->pushState(new TechTreeViewerState(selectedTopic, 0));\n}\n\n/**\n * Handles the mouse-wheels.\n * @param action Pointer to an action.\n */\nvoid ResearchState::lstResearchMousePress(Action *action)\n{\n\tif (!_lstResearch->isInsideNoScrollArea(action->getAbsoluteXMouse()))\n\t{\n\t\treturn;\n\t}\n\n\tint change = Options::oxceResearchScrollSpeed;\n\tif (_game->isCtrlPressed())\n\t\tchange = Options::oxceResearchScrollSpeedWithCtrl;\n\n\tif (action->getDetails()->button.button == SDL_BUTTON_WHEELUP)\n\t{\n\t\tchange = std::min(change, _base->getAvailableScientists());\n\t\tchange = std::min(change, _base->getFreeLaboratories());\n\t\tif (change > 0)\n\t\t{\n\t\t\tResearchProject *selectedProject = _base->getResearch()[_lstResearch->getSelectedRow()];\n\t\t\tselectedProject->setAssigned(selectedProject->getAssigned() + change);\n\t\t\t_base->setScientists(_base->getScientists() - change);\n\t\t\tfillProjectList(_lstResearch->getScroll());\n\t\t}\n\t}\n\telse if (action->getDetails()->button.button == SDL_BUTTON_WHEELDOWN)\n\t{\n\t\tResearchProject *selectedProject = _base->getResearch()[_lstResearch->getSelectedRow()];\n\t\tchange = std::min(change, selectedProject->getAssigned());\n\t\tif (change > 0)\n\t\t{\n\t\t\tselectedProject->setAssigned(selectedProject->getAssigned() - change);\n\t\t\t_base->setScientists(_base->getScientists() + change);\n\t\t\tfillProjectList(_lstResearch->getScroll());\n\t\t}\n\t}\n}\n\n/**\n * Opens the Current Global Research UI.\n * @param action Pointer to an action.\n */\nvoid ResearchState::onCurrentGlobalResearchClick(Action *)\n{\n\t_game->pushState(new GlobalResearchState(true));\n}\n/**\n * Updates the research list\n * after going to other screens.\n */\nvoid ResearchState::init()\n{\n\tState::init();\n\tfillProjectList(0);\n\n\tif (Options::oxceResearchScrollSpeed > 0 || Options::oxceResearchScrollSpeedWithCtrl > 0)\n\t{\n\t\t// 175 +/- 20\n\t\t_lstResearch->setNoScrollArea(_txtAllocated->getX() - 5, _txtAllocated->getX() + 35);\n\t}\n\telse\n\t{\n\t\t_lstResearch->setNoScrollArea(0, 0);\n\t}\n}\n\n/**\n * Fills the list with Base ResearchProjects. Also updates count of available lab space and available/allocated scientists.\n */\nvoid ResearchState::fillProjectList(size_t scrl)\n{\n\t_lstResearch->clearList();\n\tfor (const auto* proj : _base->getResearch())\n\t{\n\t\tstd::ostringstream sstr;\n\t\tsstr << proj->getAssigned();\n\t\tconst RuleResearch *r = proj->getRules();\n\n\t\tstd::string wstr = tr(r->getName());\n\t\t_lstResearch->addRow(3, wstr.c_str(), sstr.str().c_str(), tr(proj->getResearchProgress()).c_str());\n\t}\n\t_txtAvailable->setText(tr(\"STR_SCIENTISTS_AVAILABLE\").arg(_base->getAvailableScientists()));\n\t_txtAllocated->setText(tr(\"STR_SCIENTISTS_ALLOCATED\").arg(_base->getAllocatedScientists()));\n\t_txtSpace->setText(tr(\"STR_LABORATORY_SPACE_AVAILABLE\").arg(_base->getFreeLaboratories()));\n\n\tif (scrl)\n\t\t_lstResearch->scrollTo(scrl);\n}\n\n/**\n * Reorders a research topic up.\n * @param action Pointer to an action.\n */\nvoid ResearchState::lstResearchLeftArrowClick(Action* action)\n{\n\tunsigned int row = _lstResearch->getSelectedRow();\n\tif (row > 0)\n\t{\n\t\tif (_game->isLeftClick(action, true))\n\t\t{\n\t\t\tmoveTopicUp(action, row);\n\t\t}\n\t\telse if (_game->isRightClick(action, true))\n\t\t{\n\t\t\tmoveTopicUp(action, row, true);\n\t\t}\n\t}\n}\n\n/**\n * Moves a research topic up on the list.\n * @param action Pointer to an action.\n * @param row Selected research topic row.\n * @param max Move the research topic to the top?\n */\nvoid ResearchState::moveTopicUp(Action* action, unsigned int row, bool max)\n{\n\tauto& topics = _base->getResearch();\n\tif (max)\n\t{\n\t\tauto* r = topics.at(row);\n\t\ttopics.erase(topics.begin() + row);\n\t\ttopics.insert(topics.begin(), r);\n\t}\n\telse\n\t{\n\t\tstd::swap(topics[row], topics[row - 1]);\n\t\tif (row != _lstResearch->getScroll())\n\t\t{\n\t\t\tSDL_WarpMouse(action->getLeftBlackBand() + action->getXMouse(), action->getTopBlackBand() + action->getYMouse() - static_cast<Uint16>(8 * action->getYScale()));\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_lstResearch->scrollUp(false);\n\t\t}\n\t}\n\tfillProjectList(_lstResearch->getScroll());\n}\n\n/**\n * Reorders a research topic down.\n * @param action Pointer to an action.\n */\nvoid ResearchState::lstResearchRightArrowClick(Action* action)\n{\n\tunsigned int row = _lstResearch->getSelectedRow();\n\tsize_t numTopics = _base->getResearch().size();\n\tif (0 < numTopics && INT_MAX >= numTopics && row < numTopics - 1)\n\t{\n\t\tif (_game->isLeftClick(action, true))\n\t\t{\n\t\t\tmoveTopicDown(action, row);\n\t\t}\n\t\telse if (_game->isRightClick(action, true))\n\t\t{\n\t\t\tmoveTopicDown(action, row, true);\n\t\t}\n\t}\n}\n\n/**\n * Moves a research topic down on the list.\n * @param action Pointer to an action.\n * @param row Selected research topic row.\n * @param max Move the research topic to the bottom?\n */\nvoid ResearchState::moveTopicDown(Action* action, unsigned int row, bool max)\n{\n\tauto& topics = _base->getResearch();\n\tif (max)\n\t{\n\t\tauto* r = topics.at(row);\n\t\ttopics.erase(topics.begin() + row);\n\t\ttopics.insert(topics.end(), r);\n\t}\n\telse\n\t{\n\t\tstd::swap(topics[row], topics[row + 1]);\n\t\tif (row != _lstResearch->getVisibleRows() - 1 + _lstResearch->getScroll())\n\t\t{\n\t\t\tSDL_WarpMouse(action->getLeftBlackBand() + action->getXMouse(), action->getTopBlackBand() + action->getYMouse() + static_cast<Uint16>(8 * action->getYScale()));\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_lstResearch->scrollDown(false);\n\t\t}\n\t}\n\tfillProjectList(_lstResearch->getScroll());\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/ResearchState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass TextList;\nclass Base;\n\n/**\n * Research screen that lets the player manage\n * all the researching operations of a base.\n */\nclass ResearchState : public State\n{\nprivate:\n\tBase *_base;\n\tTextButton *_btnNew, *_btnOk;\n\tWindow *_window;\n\tText *_txtTitle, *_txtAvailable, *_txtAllocated, *_txtSpace, *_txtProject, *_txtScientists, *_txtProgress;\n\tTextList *_lstResearch;\npublic:\n\t/// Creates the Research state.\n\tResearchState(Base *base);\n\t/// Cleans up the Research state.\n\t~ResearchState();\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the New Research button.\n\tvoid btnNewClick(Action *action);\n\t/// Handler for clicking the ResearchProject list.\n\tvoid onSelectProject(Action *action);\n\tvoid onOpenTechTreeViewer(Action *action);\n\tvoid lstResearchMousePress(Action *action);\n\t/// Handler for opening the Current Global Research UI.\n\tvoid onCurrentGlobalResearchClick(Action *action);\n\t/// Fills the ResearchProject list with Base ResearchProjects.\n\tvoid fillProjectList(size_t scrl);\n\t/// Updates the research list.\n\tvoid init() override;\n\n\t/// Handler for clicking the reordering up button.\n\tvoid lstResearchLeftArrowClick(Action* action);\n\t/// Moves a research topic up.\n\tvoid moveTopicUp(Action* action, unsigned int row, bool max = false);\n\t/// Handler for clicking the reordering down button.\n\tvoid lstResearchRightArrowClick(Action* action);\n\t/// Moves a research topic down.\n\tvoid moveTopicDown(Action* action, unsigned int row, bool max = false);\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/SackSoldierState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <sstream>\n#include \"SackSoldierState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/ItemContainer.h\"\n#include \"../Savegame/Soldier.h\"\n#include \"../Mod/Armor.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in a Sack Soldier window.\n * @param game Pointer to the core game.\n * @param base Pointer to the base to get info from.\n * @param soldierId ID of the soldier to sack.\n */\nSackSoldierState::SackSoldierState(Base *base, size_t soldierId) : _base(base), _soldierId(soldierId)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 152, 80, 84, 60);\n\t_btnOk = new TextButton(44, 16, 100, 115);\n\t_btnCancel = new TextButton(44, 16, 176, 115);\n\t_txtTitle = new Text(142, 9, 89, 75);\n\t_txtSoldier = new Text(142, 9, 89, 85);\n\n\t// Set palette\n\tsetInterface(\"sackSoldier\");\n\n\tadd(_window, \"window\", \"sackSoldier\");\n\tadd(_btnOk, \"button\", \"sackSoldier\");\n\tadd(_btnCancel, \"button\", \"sackSoldier\");\n\tadd(_txtTitle, \"text\", \"sackSoldier\");\n\tadd(_txtSoldier, \"text\", \"sackSoldier\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"sackSoldier\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&SackSoldierState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&SackSoldierState::btnOkClick, Options::keyOk);\n\n\t_btnCancel->setText(tr(\"STR_CANCEL_UC\"));\n\t_btnCancel->onMouseClick((ActionHandler)&SackSoldierState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&SackSoldierState::btnCancelClick, Options::keyCancel);\n\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_SACK\"));\n\n\tstd::ostringstream ss;\n\tss << _base->getSoldiers()->at(_soldierId)->getName(true) << \"?\";\n\n\t_txtSoldier->setAlign(ALIGN_CENTER);\n\t_txtSoldier->setText(ss.str());\n}\n\n/**\n *\n */\nSackSoldierState::~SackSoldierState()\n{\n\n}\n\n/**\n * Sacks the soldier and returns\n * to the previous screen.\n * @param action Pointer to an action.\n */\nvoid SackSoldierState::btnOkClick(Action *)\n{\n\tSoldier *soldier = _base->getSoldiers()->at(_soldierId);\n\tif (soldier->getArmor()->getStoreItem())\n\t{\n\t\t_base->getStorageItems()->addItem(soldier->getArmor()->getStoreItem());\n\t}\n\t_base->getSoldiers()->erase(_base->getSoldiers()->begin() + _soldierId);\n\tdelete soldier;\n\t_game->popState();\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid SackSoldierState::btnCancelClick(Action *)\n{\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/SackSoldierState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass Base;\nclass TextButton;\nclass Window;\nclass Text;\n\n/**\n * Window shown when the player tries to\n * sack a soldier.\n */\nclass SackSoldierState : public State\n{\nprivate:\n\tBase *_base;\n\tsize_t _soldierId;\n\n\tTextButton *_btnOk, *_btnCancel;\n\tWindow *_window;\n\tText *_txtTitle, *_txtSoldier;\npublic:\n\t/// Creates the Sack Soldier state.\n\tSackSoldierState(Base *base, size_t soldierId);\n\t/// Cleans up the Sack Soldier state.\n\t~SackSoldierState();\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/SelectStartFacilityState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"SelectStartFacilityState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleBaseFacility.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/BaseFacility.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Engine/Options.h\"\n#include \"PlaceStartFacilityState.h\"\n#include \"PlaceLiftState.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Build Facilities window.\n * @param game Pointer to the core game.\n * @param base Pointer to the base to get info from.\n * @param state Pointer to the base state to refresh.\n * @param globe Pointer to the globe to refresh.\n */\nSelectStartFacilityState::SelectStartFacilityState(Base *base, State *state, Globe *globe) : BuildFacilitiesState(base, state), _globe(globe)\n{\n\t_facilities = _game->getMod()->getCustomBaseFacilities(_game->getSavedGame()->getDifficulty());\n\n\t_btnOk->setText(tr(\"STR_RESET\"));\n\t_btnOk->onMouseClick((ActionHandler)&SelectStartFacilityState::btnOkClick);\n\t_btnOk->onKeyboardPress(0, Options::keyCancel);\n\n\t_lstFacilities->onMouseClick((ActionHandler)&SelectStartFacilityState::lstFacilitiesClick);\n}\n\n/**\n *\n */\nSelectStartFacilityState::~SelectStartFacilityState()\n{\n\n}\n\n/**\n * Populates the build list from the current \"available\" facilities.\n */\nvoid SelectStartFacilityState::populateBuildList()\n{\n\t_lstFacilities->clearList();\n\tfor (const auto* rule : _facilities)\n\t{\n\t\t_lstFacilities->addRow(1, tr(rule->getType()).c_str());\n\t}\n}\n\n/**\n * Resets the base building.\n * @param action Pointer to an action.\n */\nvoid SelectStartFacilityState::btnOkClick(Action *)\n{\n\tfor (auto* fac : *_base->getFacilities())\n\t{\n\t\tdelete fac;\n\t}\n\t_base->getFacilities()->clear();\n\t_game->popState();\n\t_game->popState();\n\t_game->pushState(new PlaceLiftState(_base, _globe, true));\n}\n\n/**\n * Places the selected facility.\n * @param action Pointer to an action.\n */\nvoid SelectStartFacilityState::lstFacilitiesClick(Action *)\n{\n\t_game->pushState(new PlaceStartFacilityState(_base, this, _facilities[_lstFacilities->getSelectedRow()]));\n}\n\n/**\n * Callback from PlaceStartFacilityState.\n * Removes placed facility from the list.\n */\nvoid SelectStartFacilityState::facilityBuilt()\n{\n\t_facilities.erase(_facilities.begin() + _lstFacilities->getSelectedRow());\n\tif (_facilities.empty())\n\t{\n\t\t_game->popState();\n\t\t_game->popState(); // return to geoscape, force timer to start.\n\t}\n\telse\n\t{\n\t\tpopulateBuildList();\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/SelectStartFacilityState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"BuildFacilitiesState.h\"\n\nnamespace OpenXcom\n{\n\nclass Globe;\n\n/**\n * Window shown with all the facilities\n * available to build.\n */\nclass SelectStartFacilityState : public BuildFacilitiesState\n{\nprivate:\n\tGlobe *_globe;\npublic:\n\t/// Creates the Build Facilities state.\n\tSelectStartFacilityState(Base *base, State *state, Globe *globe);\n\t/// Cleans up the Build Facilities state.\n\t~SelectStartFacilityState();\n\t/// Populates the build option list.\n\tvirtual void populateBuildList() override;\n\t/// Handler for clicking the Reset button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the Facilities list.\n\tvoid lstFacilitiesClick(Action *action) override;\n\t/// Handler for when the facility is actually built.\n\tvoid facilityBuilt();\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/SellState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"SellState.h\"\n#include \"ItemLocationsState.h\"\n#include \"ManufactureDependenciesTreeState.h\"\n#include <algorithm>\n#include <locale>\n#include <sstream>\n#include <climits>\n#include <cmath>\n#include <iomanip>\n#include \"../Engine/Action.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextEdit.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Interface/ComboBox.h\"\n#include \"../Savegame/BaseFacility.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/Soldier.h\"\n#include \"../Savegame/Craft.h\"\n#include \"../Savegame/ItemContainer.h\"\n#include \"../Savegame/Vehicle.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Mod/RuleCraft.h\"\n#include \"../Savegame/CraftWeapon.h\"\n#include \"../Mod/RuleCraftWeapon.h\"\n#include \"../Engine/Timer.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Mod/RuleInterface.h\"\n#include \"../Battlescape/DebriefingState.h\"\n#include \"TransferBaseState.h\"\n#include \"TechTreeViewerState.h\"\n#include \"../Ufopaedia/Ufopaedia.h\"\n#include \"../Menu/ErrorMessageState.h\"\n#include \"../Engine/Sound.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Sell/Sack screen.\n * @param game Pointer to the core game.\n * @param base Pointer to the base to get info from.\n * @param origin Game section that originated this state.\n */\nSellState::SellState(Base *base, DebriefingState *debriefingState, OptionsOrigin origin) : _base(base), _debriefingState(debriefingState), _sel(0), _total(0), _spaceChange(0), _origin(origin),\n\t_reset(false), _sellAllButOne(false), _delayedInitDone(false), _previousSort(TransferSortDirection::BY_LIST_ORDER), _currentSort(TransferSortDirection::BY_LIST_ORDER)\n{\n\t_timerInc = new Timer(250);\n\t_timerInc->onTimer((StateHandler)&SellState::increase);\n\t_timerDec = new Timer(250);\n\t_timerDec->onTimer((StateHandler)&SellState::decrease);\n}\n\n/**\n * Delayed constructor functionality.\n */\nvoid SellState::delayedInit()\n{\n\tif (_delayedInitDone)\n\t{\n\t\treturn;\n\t}\n\t_delayedInitDone = true;\n\n\tbool overfull = _debriefingState == 0 && Options::storageLimitsEnforced && _base->storesOverfull();\n\tbool overfullCritical = overfull ? _base->storesOverfullCritical() : false;\n\n\t// Create objects\n\t_window = new Window(this, 320, 200, 0, 0);\n\t_btnQuickSearch = new TextEdit(this, 48, 9, 10, 13);\n\t//_btnOk = new TextButton(overfull? 288:148, 16, overfull? 16:8, 176);\n\t_btnOk = new TextButton(148, 16, 8, 176);\n\t_btnCancel = new TextButton(148, 16, 164, 176);\n\t_btnTransfer = new TextButton(148, 16, 164, 176);\n\t_txtTitle = new Text(310, 17, 5, 8);\n\t_txtSales = new Text(150, 9, 10, 24);\n\t_txtFunds = new Text(150, 9, 160, 24);\n\t_txtSpaceUsed = new Text(150, 9, 160, 34);\n\t_txtQuantity = new Text(54, 9, 136, 44);\n\t_txtSell = new Text(96, 9, 190, 44);\n\t_txtValue = new Text(40, 9, 270, 44);\n\t_cbxCategory = new ComboBox(this, 120, 16, 10, 36);\n\t_lstItems = new TextList(287, 120, 8, 54);\n\n\ttouchComponentsCreate(_txtTitle);\n\n\t// Set palette\n\tsetInterface(\"sellMenu\");\n\n\t_ammoColor = _game->getMod()->getInterface(\"sellMenu\")->getElement(\"ammoColor\")->color;\n\n\tadd(_window, \"window\", \"sellMenu\");\n\tadd(_btnQuickSearch, \"button\", \"sellMenu\");\n\tadd(_btnOk, \"button\", \"sellMenu\");\n\tadd(_btnCancel, \"button\", \"sellMenu\");\n\tadd(_btnTransfer, \"button\", \"sellMenu\");\n\tadd(_txtTitle, \"text\", \"sellMenu\");\n\tadd(_txtSales, \"text\", \"sellMenu\");\n\tadd(_txtFunds, \"text\", \"sellMenu\");\n\tadd(_txtSpaceUsed, \"text\", \"sellMenu\");\n\tadd(_txtQuantity, \"text\", \"sellMenu\");\n\tadd(_txtSell, \"text\", \"sellMenu\");\n\tadd(_txtValue, \"text\", \"sellMenu\");\n\tadd(_lstItems, \"list\", \"sellMenu\");\n\tadd(_cbxCategory, \"text\", \"sellMenu\");\n\n\ttouchComponentsAdd(\"button2\", \"sellMenu\", _window);\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"sellMenu\");\n\n\ttouchComponentsConfigure();\n\n\t_btnOk->setText(tr(\"STR_SELL_SACK\"));\n\t_btnOk->onMouseClick((ActionHandler)&SellState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&SellState::btnOkClick, Options::keyOk);\n\n\t_btnCancel->setText(tr(\"STR_CANCEL\"));\n\t_btnCancel->onMouseClick((ActionHandler)&SellState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&SellState::btnCancelClick, Options::keyCancel);\n\n\t_btnTransfer->setText(tr(\"STR_GO_TO_TRANSFERS\"));\n\t_btnTransfer->onMouseClick((ActionHandler)&SellState::btnTransferClick);\n\n\t_btnCancel->setVisible(!overfull);\n\t_btnOk->setVisible(!overfull);\n\t_btnTransfer->setVisible(overfull);\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_SELL_ITEMS_SACK_PERSONNEL\"));\n\n\t_txtFunds->setText(tr(\"STR_FUNDS\").arg(Unicode::formatFunding(_game->getSavedGame()->getFunds())));\n\n\t_txtSpaceUsed->setVisible(Options::storageLimitsEnforced);\n\n\tstd::ostringstream ss;\n\tss << _base->getUsedStores() << \":\" << _base->getAvailableStores();\n\t_txtSpaceUsed->setText(ss.str());\n\t_txtSpaceUsed->setText(tr(\"STR_SPACE_USED\").arg(ss.str()));\n\n\t_txtQuantity->setText(tr(\"STR_QUANTITY_UC\"));\n\n\t_txtSell->setText(tr(\"STR_SELL_SACK\"));\n\n\t_txtValue->setText(tr(\"STR_VALUE\"));\n\n\t_lstItems->setArrowColumn(182, ARROW_VERTICAL);\n\t_lstItems->setColumns(4, 156, 54, 24, 53);\n\t_lstItems->setSelectable(true);\n\t_lstItems->setBackground(_window);\n\t_lstItems->setMargin(2);\n\t_lstItems->onLeftArrowPress((ActionHandler)&SellState::lstItemsLeftArrowPress);\n\t_lstItems->onLeftArrowRelease((ActionHandler)&SellState::lstItemsLeftArrowRelease);\n\t_lstItems->onLeftArrowClick((ActionHandler)&SellState::lstItemsLeftArrowClick);\n\t_lstItems->onRightArrowPress((ActionHandler)&SellState::lstItemsRightArrowPress);\n\t_lstItems->onRightArrowRelease((ActionHandler)&SellState::lstItemsRightArrowRelease);\n\t_lstItems->onRightArrowClick((ActionHandler)&SellState::lstItemsRightArrowClick);\n\t_lstItems->onMousePress((ActionHandler)&SellState::lstItemsMousePress);\n\n\t_cats.push_back(\"STR_ALL_ITEMS\");\n\t_cats.push_back(\"STR_FILTER_HIDDEN\");\n\tif (Options::oxceBaseFilterResearchable)\n\t{\n\t\t_cats.push_back(\"STR_FILTER_RESEARCHED\");\n\t\t_cats.push_back(\"STR_FILTER_RESEARCHABLE\");\n\t}\n\n\tfor (auto* soldier : *_base->getSoldiers())\n\t{\n\t\tif (_debriefingState) break;\n\t\tif (soldier->getCraft() == 0)\n\t\t{\n\t\t\tTransferRow row = { TRANSFER_SOLDIER, soldier, soldier->getName(true), 0, 1, 0, 0, -4, 0, 0, 0 };\n\t\t\t_items.push_back(row);\n\t\t\tstd::string cat = getCategory(_items.size() - 1);\n\t\t\tif (std::find(_cats.begin(), _cats.end(), cat) == _cats.end())\n\t\t\t{\n\t\t\t\t_cats.push_back(cat);\n\t\t\t}\n\t\t}\n\t}\n\tfor (auto* craft : *_base->getCrafts())\n\t{\n\t\tif (_debriefingState) break;\n\t\tif (craft->getStatus() != \"STR_OUT\")\n\t\t{\n\t\t\tTransferRow row = { TRANSFER_CRAFT, craft, craft->getName(_game->getLanguage()), craft->getRules()->getSellCost(), 1, 0, 0, -3, 0, 0, craft->getRules()->getSellCost() };\n\t\t\t_items.push_back(row);\n\t\t\tstd::string cat = getCategory(_items.size() - 1);\n\t\t\tif (std::find(_cats.begin(), _cats.end(), cat) == _cats.end())\n\t\t\t{\n\t\t\t\t_cats.push_back(cat);\n\t\t\t}\n\t\t}\n\t}\n\tif (_base->getAvailableScientists() > 0 && _debriefingState == 0)\n\t{\n\t\tTransferRow row = { TRANSFER_SCIENTIST, 0, tr(\"STR_SCIENTIST\"), 0, _base->getAvailableScientists(), 0, 0, -2, 0, 0, 0 };\n\t\t_items.push_back(row);\n\t\tstd::string cat = getCategory(_items.size() - 1);\n\t\tif (std::find(_cats.begin(), _cats.end(), cat) == _cats.end())\n\t\t{\n\t\t\t_cats.push_back(cat);\n\t\t}\n\t}\n\tif (_base->getAvailableEngineers() > 0 && _debriefingState == 0)\n\t{\n\t\tTransferRow row = { TRANSFER_ENGINEER, 0, tr(\"STR_ENGINEER\"), 0, _base->getAvailableEngineers(), 0, 0, -1, 0, 0, 0 };\n\t\t_items.push_back(row);\n\t\tstd::string cat = getCategory(_items.size() - 1);\n\t\tif (std::find(_cats.begin(), _cats.end(), cat) == _cats.end())\n\t\t{\n\t\t\t_cats.push_back(cat);\n\t\t}\n\t}\n\tfor (auto& itemType : _game->getMod()->getItemsList())\n\t{\n\t\tconst RuleItem *rule = _game->getMod()->getItem(itemType, true);\n\t\tint qty = 0;\n\t\tif (_debriefingState != 0)\n\t\t{\n\t\t\tqty = _debriefingState->getRecoveredItemCount(rule);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tqty = _base->getStorageItems()->getItem(rule);\n\t\t\tif (Options::storageLimitsEnforced && (_origin == OPT_BATTLESCAPE || overfullCritical))\n\t\t\t{\n\t\t\t\tfor (auto* transfer : *_base->getTransfers())\n\t\t\t\t{\n\t\t\t\t\tif (transfer->getItems() == rule)\n\t\t\t\t\t{\n\t\t\t\t\t\tqty += transfer->getQuantity();\n\t\t\t\t\t}\n\t\t\t\t\telse if (transfer->getCraft())\n\t\t\t\t\t{\n\t\t\t\t\t\tqty += overfullCritical ? transfer->getCraft()->getTotalItemCount(rule) : transfer->getCraft()->getItems()->getItem(rule);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfor (auto* craft : *_base->getCrafts())\n\t\t\t\t{\n\t\t\t\t\tqty +=  overfullCritical ? craft->getTotalItemCount(rule) : craft->getItems()->getItem(rule);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (qty > 0 && (Options::canSellLiveAliens || !rule->isAlien()))\n\t\t{\n\t\t\tTransferRow row = { TRANSFER_ITEM, rule, tr(itemType), rule->getSellCostAdjusted(_base, _game->getSavedGame()), qty, 0, 0, rule->getListOrder(), rule->getSize(), qty * rule->getSize(), (int64_t)qty * rule->getSellCostAdjusted(_base, _game->getSavedGame()) };\n\t\t\tif ((_debriefingState != 0) && (_game->getSavedGame()->getAutosell(rule)))\n\t\t\t{\n\t\t\t\trow.amount = qty;\n\t\t\t\t_total += row.cost * qty;\n\t\t\t\t_spaceChange -= qty * rule->getSize();\n\t\t\t}\n\t\t\t_items.push_back(row);\n\t\t\tstd::string cat = getCategory(_items.size() - 1);\n\t\t\tif (std::find(_cats.begin(), _cats.end(), cat) == _cats.end())\n\t\t\t{\n\t\t\t\t_cats.push_back(cat);\n\t\t\t}\n\t\t}\n\t}\n\n\t_vanillaCategories = _cats.size();\n\tif (_game->getMod()->getDisplayCustomCategories() > 0)\n\t{\n\t\tbool hasUnassigned = false;\n\n\t\t// first find all relevant item categories\n\t\tstd::vector<std::string> tempCats;\n\t\tfor (const auto& transferRow : _items)\n\t\t{\n\t\t\tif (transferRow.type == TRANSFER_ITEM)\n\t\t\t{\n\t\t\t\tRuleItem *rule = (RuleItem*)(transferRow.rule);\n\t\t\t\tif (rule->getCategories().empty())\n\t\t\t\t{\n\t\t\t\t\thasUnassigned = true;\n\t\t\t\t}\n\t\t\t\tfor (auto& itemCategoryName : rule->getCategories())\n\t\t\t\t{\n\t\t\t\t\tif (std::find(tempCats.begin(), tempCats.end(), itemCategoryName) == tempCats.end())\n\t\t\t\t\t{\n\t\t\t\t\t\ttempCats.push_back(itemCategoryName);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// then use them nicely in order\n\t\tif (_game->getMod()->getDisplayCustomCategories() == 1)\n\t\t{\n\t\t\t_cats.clear();\n\t\t\t_cats.push_back(\"STR_ALL_ITEMS\");\n\t\t\t_cats.push_back(\"STR_FILTER_HIDDEN\");\n\t\t\tif (Options::oxceBaseFilterResearchable)\n\t\t\t{\n\t\t\t\t_cats.push_back(\"STR_FILTER_RESEARCHED\");\n\t\t\t\t_cats.push_back(\"STR_FILTER_RESEARCHABLE\");\n\t\t\t}\n\t\t\t_vanillaCategories = _cats.size();\n\t\t}\n\t\tfor (auto& categoryName : _game->getMod()->getItemCategoriesList())\n\t\t{\n\t\t\tif (std::find(tempCats.begin(), tempCats.end(), categoryName) != tempCats.end())\n\t\t\t{\n\t\t\t\t_cats.push_back(categoryName);\n\t\t\t}\n\t\t}\n\t\tif (hasUnassigned)\n\t\t{\n\t\t\t_cats.push_back(\"STR_UNASSIGNED\");\n\t\t}\n\t}\n\n\t_txtSales->setText(tr(\"STR_VALUE_OF_SALES\").arg(Unicode::formatFunding(_total)));\n\n\t_cbxCategory->setOptions(_cats, true);\n\t_cbxCategory->onChange((ActionHandler)&SellState::cbxCategoryChange);\n\t_cbxCategory->onKeyboardPress((ActionHandler)&SellState::btnSellAllClick, Options::keySellAll);\n\t_cbxCategory->onKeyboardPress((ActionHandler)&SellState::btnSellAllButOneClick, Options::keySellAllButOne);\n\n\t_btnQuickSearch->setText(\"\"); // redraw\n\t_btnQuickSearch->onEnter((ActionHandler)&SellState::btnQuickSearchApply);\n\t_btnQuickSearch->setVisible(Options::oxceQuickSearchButton);\n\n\t// OK button is not always visible, so bind it here\n\t_cbxCategory->onKeyboardRelease((ActionHandler)&SellState::btnQuickSearchToggle, Options::keyToggleQuickSearch);\n\n\tupdateList();\n}\n\n/**\n *\n */\nSellState::~SellState()\n{\n\tdelete _timerInc;\n\tdelete _timerDec;\n}\n\n/**\n* Resets stuff when coming back from other screens.\n*/\nvoid SellState::init()\n{\n\tdelayedInit();\n\n\tState::init();\n\n\tif (_reset)\n\t{\n\t\t_game->popState();\n\t\t_game->pushState(new SellState(_base, _debriefingState, _origin));\n\t}\n\n\ttouchComponentsRefresh();\n}\n\n/**\n * Runs the arrow timers.\n */\nvoid SellState::think()\n{\n\tState::think();\n\n\t_timerInc->think(this, 0);\n\t_timerDec->think(this, 0);\n}\n\n/**\n * Determines the category a row item belongs in.\n * @param sel Selected row.\n * @returns Item category.\n */\nstd::string SellState::getCategory(int sel) const\n{\n\tRuleItem *rule = 0;\n\tswitch (_items[sel].type)\n\t{\n\tcase TRANSFER_SOLDIER:\n\tcase TRANSFER_SCIENTIST:\n\tcase TRANSFER_ENGINEER:\n\t\treturn \"STR_PERSONNEL\";\n\tcase TRANSFER_CRAFT:\n\t\treturn \"STR_CRAFT_ARMAMENT\";\n\tcase TRANSFER_ITEM:\n\t\trule = (RuleItem*)_items[sel].rule;\n\t\tif (rule->getBattleType() == BT_CORPSE || rule->isAlien())\n\t\t{\n\t\t\tif (rule->getVehicleUnit())\n\t\t\t\treturn \"STR_PERSONNEL\"; // OXCE: critters fighting for us\n\t\t\tif (rule->isAlien())\n\t\t\t\treturn \"STR_PRISONERS\"; // OXCE: live aliens\n\t\t\treturn \"STR_ALIENS\";\n\t\t}\n\t\tif (rule->getBattleType() == BT_NONE)\n\t\t{\n\t\t\tif (_game->getMod()->isCraftWeaponStorageItem(rule))\n\t\t\t\treturn \"STR_CRAFT_ARMAMENT\";\n\t\t\tif (_game->getMod()->isArmorStorageItem(rule))\n\t\t\t\treturn \"STR_ARMORS\"; // OXCE: armors\n\t\t\treturn \"STR_COMPONENTS\";\n\t\t}\n\t\treturn \"STR_EQUIPMENT\";\n\t}\n\treturn \"STR_ALL_ITEMS\";\n}\n\n/**\n * Determines if a row item belongs to a given category.\n * @param sel Selected row.\n * @param cat Category.\n * @returns True if row item belongs to given category, otherwise False.\n */\nbool SellState::belongsToCategory(int sel, const std::string &cat) const\n{\n\tswitch (_items[sel].type)\n\t{\n\tcase TRANSFER_SOLDIER:\n\tcase TRANSFER_SCIENTIST:\n\tcase TRANSFER_ENGINEER:\n\tcase TRANSFER_CRAFT:\n\t\treturn false;\n\tcase TRANSFER_ITEM:\n\t\tRuleItem *rule = (RuleItem*)_items[sel].rule;\n\t\treturn rule->belongsToCategory(cat);\n\t}\n\treturn false;\n}\n\n/**\n * Determines if a row item is supposed to be hidden\n * @param sel Selected row.\n * @param cat Category.\n * @returns True if row item is hidden\n */\nbool SellState::isHidden(int sel) const\n{\n\tstd::string itemName;\n\n\tswitch (_items[sel].type)\n\t{\n\tcase TRANSFER_SOLDIER:\n\tcase TRANSFER_SCIENTIST:\n\tcase TRANSFER_ENGINEER:\n\t\treturn false;\n\tcase TRANSFER_CRAFT:\n\t\treturn false;\n\tcase TRANSFER_ITEM:\n\t\tRuleItem* rule = (RuleItem*)_items[sel].rule;\n\t\tif (rule != 0)\n\t\t{\n\t\t\titemName = rule->getType();\n\t\t}\n\t\tif (!itemName.empty())\n\t\t{\n\t\t\tauto& hiddenMap = _game->getSavedGame()->getHiddenPurchaseItems();\n\t\t\tauto iter = hiddenMap.find(itemName);\n\t\t\tif (iter != hiddenMap.end())\n\t\t\t{\n\t\t\t\treturn iter->second;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// not found = not hidden\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn false;\n}\n\n/**\n* Quick search toggle.\n* @param action Pointer to an action.\n*/\nvoid SellState::btnQuickSearchToggle(Action *action)\n{\n\tif (_btnQuickSearch->getVisible())\n\t{\n\t\t_btnQuickSearch->setText(\"\");\n\t\t_btnQuickSearch->setVisible(false);\n\t\tbtnQuickSearchApply(action);\n\t}\n\telse\n\t{\n\t\t_btnQuickSearch->setVisible(true);\n\t\t_btnQuickSearch->setFocus(true);\n\t}\n}\n\n/**\n* Quick search.\n* @param action Pointer to an action.\n*/\nvoid SellState::btnQuickSearchApply(Action *)\n{\n\tupdateList();\n}\n\n/**\n * Filters the current list of items.\n */\nvoid SellState::updateList()\n{\n\tstd::string searchString = _btnQuickSearch->getText();\n\tUnicode::upperCase(searchString);\n\n\t_lstItems->clearList();\n\t_rows.clear();\n\n\tsize_t selCategory = _cbxCategory->getSelected();\n\tconst std::string selectedCategory = _cats[selCategory];\n\tbool categoryFilterEnabled = (selectedCategory != \"STR_ALL_ITEMS\");\n\tbool categoryUnassigned = (selectedCategory == \"STR_UNASSIGNED\");\n\tbool categoryHidden = (selectedCategory == \"STR_FILTER_HIDDEN\");\n\tbool categoryResearched = (selectedCategory == \"STR_FILTER_RESEARCHED\");\n\tbool categoryResearchable = (selectedCategory == \"STR_FILTER_RESEARCHABLE\");\n\n\tif (_previousSort != _currentSort)\n\t{\n\t\tswitch (_currentSort)\n\t\t{\n\t\tcase TransferSortDirection::BY_TOTAL_COST: std::stable_sort(_items.begin(), _items.end(), [](const TransferRow a, const TransferRow b) { return a.totalCost > b.totalCost; }); break;\n\t\tcase TransferSortDirection::BY_UNIT_COST:  std::stable_sort(_items.begin(), _items.end(), [](const TransferRow a, const TransferRow b) { return a.cost > b.cost; }); break;\n\t\tcase TransferSortDirection::BY_TOTAL_SIZE: std::stable_sort(_items.begin(), _items.end(), [](const TransferRow a, const TransferRow b) { return a.totalSize > b.totalSize; }); break;\n\t\tcase TransferSortDirection::BY_UNIT_SIZE:  std::stable_sort(_items.begin(), _items.end(), [](const TransferRow a, const TransferRow b) { return a.size > b.size; }); break;\n\t\tdefault:                                   std::stable_sort(_items.begin(), _items.end(), [](const TransferRow a, const TransferRow b) { return a.listOrder < b.listOrder; }); break;\n\t\t}\n\t}\n\n\tfor (size_t i = 0; i < _items.size(); ++i)\n\t{\n\t\t// filter\n\t\tif (categoryHidden)\n\t\t{\n\t\t\tbool hidden = isHidden(i);\n\t\t\tif (!hidden)\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\telse if (categoryResearched || categoryResearchable)\n\t\t{\n\t\t\tif (_items[i].type == TRANSFER_ITEM)\n\t\t\t{\n\t\t\t\tRuleItem* rule = (RuleItem*)_items[i].rule;\n\t\t\t\tbool isResearchable = _game->getSavedGame()->isResearchable(rule, _game->getMod());\n\t\t\t\tif (categoryResearched && isResearchable) continue;\n\t\t\t\tif (categoryResearchable && !isResearchable) continue;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// don't show non-items (e.g. craft, personnel)\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\telse if (selCategory >= _vanillaCategories)\n\t\t{\n\t\t\tif (categoryUnassigned && _items[i].type == TRANSFER_ITEM)\n\t\t\t{\n\t\t\t\tRuleItem* rule = (RuleItem*)_items[i].rule;\n\t\t\t\tif (!rule->getCategories().empty())\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (categoryFilterEnabled && !belongsToCategory(i, selectedCategory))\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (categoryFilterEnabled && selectedCategory != getCategory(i))\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\t// quick search\n\t\tif (!searchString.empty())\n\t\t{\n\t\t\tstd::string projectName = _items[i].name;\n\t\t\tUnicode::upperCase(projectName);\n\t\t\tif (projectName.find(searchString) == std::string::npos)\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\tstd::string name = _items[i].name;\n\t\tbool ammo = false;\n\t\tif (_items[i].type == TRANSFER_ITEM)\n\t\t{\n\t\t\tRuleItem *rule = (RuleItem*)_items[i].rule;\n\t\t\tammo = (rule->getBattleType() == BT_AMMO || (rule->getBattleType() == BT_NONE && rule->getClipSize() > 0));\n\t\t\tif (ammo)\n\t\t\t{\n\t\t\t\tname.insert(0, \"  \");\n\t\t\t}\n\t\t}\n\t\tstd::ostringstream ssQty, ssAmount;\n\t\tssQty << _items[i].qtySrc - _items[i].amount;\n\t\tssAmount << _items[i].amount;\n\t\tint64_t adjustedCost = _items[i].cost;\n\t\t_lstItems->addRow(4, name.c_str(), ssQty.str().c_str(), ssAmount.str().c_str(), Unicode::formatFunding(adjustedCost).c_str());\n\t\t_rows.push_back(i);\n\t\tif (_items[i].amount > 0)\n\t\t{\n\t\t\t_lstItems->setRowColor(_rows.size() - 1, _lstItems->getSecondaryColor());\n\t\t}\n\t\telse if (ammo)\n\t\t{\n\t\t\t_lstItems->setRowColor(_rows.size() - 1, _ammoColor);\n\t\t}\n\t}\n}\n\n/**\n * Sells the selected items.\n * @param action Pointer to an action.\n */\nvoid SellState::btnOkClick(Action *)\n{\n\t_game->getSavedGame()->setFunds(_game->getSavedGame()->getFunds() + _total);\n\n\tauto cleanUpContainer = [&](ItemContainer* container, const RuleItem* rule, int toRemove) -> int\n\t{\n\t\tint curr = container->getItem(rule);\n\t\tif (curr >= toRemove)\n\t\t{\n\t\t\tcontainer->removeItem(rule, toRemove);\n\t\t\treturn 0;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tcontainer->removeItem(rule, INT_MAX);\n\t\t\treturn toRemove - curr;\n\t\t}\n\t};\n\n\tauto cleanUpCraft = [&](Craft* craft2, const RuleItem* rule, int toRemove) -> int\n\t{\n\t\tstruct S\n\t\t{\n\t\t\tint ToRemove, ToSave;\n\t\t\tconst RuleItem* rule;\n\t\t};\n\n\t\tauto tryRemove = [&toRemove, rule](int curr, const RuleItem* i) -> S\n\t\t{\n\t\t\tif (i == rule)\n\t\t\t{\n\t\t\t\tint r = std::min(toRemove, curr);\n\t\t\t\ttoRemove -= r;\n\t\t\t\tcurr -= r;\n\t\t\t\treturn S{ r, curr, i };\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn S{ 0, curr, i };\n\t\t\t}\n\t\t};\n\t\tauto tryStore = [&](S s)\n\t\t{\n\t\t\tif (s.ToSave > 0)\n\t\t\t{\n\t\t\t\t_base->getStorageItems()->addItem(s.rule, s.ToSave);\n\t\t\t}\n\t\t};\n\n\t\tfor (auto*& w :* craft2->getWeapons())\n\t\t{\n\t\t\tif (w != nullptr)\n\t\t\t{\n\t\t\t\tauto* wr = w->getRules();\n\n\t\t\t\tauto launcher = tryRemove(1, wr->getLauncherItem());\n\t\t\t\tauto clip = tryRemove(w->getClipsLoaded(), wr->getClipItem());\n\t\t\t\tif (launcher.ToRemove || clip.ToRemove)\n\t\t\t\t{\n\t\t\t\t\ttryStore(launcher);\n\t\t\t\t\ttryStore(clip);\n\n\t\t\t\t\tdelete w;\n\t\t\t\t\tw = nullptr;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tCollections::deleteIf(\n\t\t\t*craft2->getVehicles(),\n\t\t\t[&](Vehicle* v)\n\t\t\t{\n\t\t\t\tauto* clipType = v->getRules()->getVehicleClipAmmo();\n\n\t\t\t\tauto launcher = tryRemove(1, v->getRules());\n\t\t\t\tauto clip = tryRemove(v->getRules()->getVehicleClipsLoaded(), clipType);\n\n\t\t\t\tif (launcher.ToRemove || clip.ToRemove)\n\t\t\t\t{\n\t\t\t\t\ttryStore(launcher);\n\t\t\t\t\ttryStore(clip);\n\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\n\t\treturn toRemove;\n\t};\n\n\tSoldier* tmpSoldier;\n\tCraft* tmpCraft;\n\n\tfor (const auto& transferRow : _items)\n\t{\n\t\tif (transferRow.amount > 0)\n\t\t{\n\t\t\tswitch (transferRow.type)\n\t\t\t{\n\t\t\tcase TRANSFER_SOLDIER:\n\t\t\t\ttmpSoldier = (Soldier*)transferRow.rule;\n\t\t\t\tfor (auto soldierIt = _base->getSoldiers()->begin(); soldierIt != _base->getSoldiers()->end(); ++soldierIt)\n\t\t\t\t{\n\t\t\t\t\tif (*soldierIt == tmpSoldier)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (tmpSoldier->getArmor()->getStoreItem())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_base->getStorageItems()->addItem(tmpSoldier->getArmor()->getStoreItem());\n\t\t\t\t\t\t}\n\t\t\t\t\t\t_base->getSoldiers()->erase(soldierIt);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tdelete tmpSoldier;\n\t\t\t\tbreak;\n\t\t\tcase TRANSFER_CRAFT:\n\t\t\t\ttmpCraft = (Craft*)transferRow.rule;\n\t\t\t\t_base->removeCraft(tmpCraft, true);\n\t\t\t\tdelete tmpCraft;\n\t\t\t\tbreak;\n\t\t\tcase TRANSFER_SCIENTIST:\n\t\t\t\t_base->setScientists(_base->getScientists() - transferRow.amount);\n\t\t\t\tbreak;\n\t\t\tcase TRANSFER_ENGINEER:\n\t\t\t\t_base->setEngineers(_base->getEngineers() - transferRow.amount);\n\t\t\t\tbreak;\n\t\t\tcase TRANSFER_ITEM:\n\t\t\t\tRuleItem *item = (RuleItem*)transferRow.rule;\n\t\t\t\t{\n\t\t\t\t\t// remove all of said items from base\n\t\t\t\t\tint toRemove = cleanUpContainer(_base->getStorageItems(), item, transferRow.amount);\n\n\t\t\t\t\t// if we still need to remove any, remove them from the crafts first, and keep a running tally\n\t\t\t\t\tfor (auto* craft : *_base->getCrafts())\n\t\t\t\t\t{\n\t\t\t\t\t\tif (toRemove <= 0) break; // loop finished\n\t\t\t\t\t\ttoRemove = cleanUpContainer(craft->getItems(), item, toRemove);\n\t\t\t\t\t\tif (toRemove > 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttoRemove = cleanUpCraft(craft, item, toRemove);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// if there are STILL any left to remove, take them from the transfers, and if necessary, delete it.\n\t\t\t\t\tfor (auto transferIt = _base->getTransfers()->begin(); transferIt != _base->getTransfers()->end() && toRemove;)\n\t\t\t\t\t{\n\t\t\t\t\t\tauto* transfer = (*transferIt);\n\t\t\t\t\t\tif (transfer->getItems() == item)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (transfer->getQuantity() <= toRemove)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttoRemove -= transfer->getQuantity();\n\t\t\t\t\t\t\t\tdelete transfer;\n\t\t\t\t\t\t\t\ttransferIt = _base->getTransfers()->erase(transferIt);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttransfer->setItems(transfer->getItems(), transfer->getQuantity() - toRemove);\n\t\t\t\t\t\t\t\ttoRemove = 0;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (transfer->getCraft())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttoRemove = cleanUpContainer(transfer->getCraft()->getItems(), item, toRemove);\n\t\t\t\t\t\t\t\tif (toRemove > 0)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\ttoRemove = cleanUpCraft(transfer->getCraft(), item, toRemove);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t++transferIt;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Note: this only updates a helper map, it doesn't affect real item recovery (that has already happened and all items are already in the base)\n\t\t\t\tif (_debriefingState != 0)\n\t\t\t\t{\n\t\t\t\t\t// remember the decreased amount for next sell/transfer\n\t\t\t\t\t_debriefingState->decreaseRecoveredItemCount(item, transferRow.amount);\n\n\t\t\t\t\t// set autosell status if we sold all of the item\n\t\t\t\t\t_game->getSavedGame()->setAutosell(item, (transferRow.qtySrc == transferRow.amount));\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (_debriefingState != 0 && transferRow.type == TRANSFER_ITEM)\n\t\t\t{\n\t\t\t\t// disable autosell since we haven't sold any of the item.\n\t\t\t\t_game->getSavedGame()->setAutosell((RuleItem*)transferRow.rule, false);\n\t\t\t}\n\t\t}\n\t}\n\tif (_debriefingState != 0 && _debriefingState->getTotalRecoveredItemCount() <= 0)\n\t{\n\t\t_debriefingState->hideSellTransferButtons();\n\t}\n\t_game->popState();\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid SellState::btnCancelClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n* Opens the Transfer UI and gives the player an option to transfer stuff instead of selling it.\n* Returns back to this screen when finished.\n* @param action Pointer to an action.\n*/\nvoid SellState::btnTransferClick(Action *)\n{\n\t_reset = true;\n\t_game->pushState(new TransferBaseState(_base, nullptr));\n}\n\n/**\n* Increase all items to max, i.e. sell everything.\n* @param action Pointer to an action.\n*/\nvoid SellState::btnSellAllClick(Action *)\n{\n\tbool allItemsSelected = true;\n\tfor (size_t i = 0; i < _lstItems->getTexts(); ++i)\n\t{\n\t\tif (_items[_rows[i]].qtySrc > _items[_rows[i]].amount)\n\t\t{\n\t\t\tallItemsSelected = false;\n\t\t\tbreak;\n\t\t}\n\t}\n\tint dir = allItemsSelected ? -1 : 1;\n\n\tsize_t backup = _sel;\n\tfor (size_t i = 0; i < _lstItems->getTexts(); ++i)\n\t{\n\t\t_sel = i;\n\t\tchangeByValue(INT_MAX, dir);\n\t}\n\t_sel = backup;\n}\n\n/**\n* Increase all items to max - 1, i.e. sell everything but one.\n* @param action Pointer to an action.\n*/\nvoid SellState::btnSellAllButOneClick(Action *)\n{\n\t_sellAllButOne = true;\n\tbtnSellAllClick(nullptr);\n\t_sellAllButOne = false;\n}\n\n/**\n * Starts increasing the item.\n * @param action Pointer to an action.\n */\nvoid SellState::lstItemsLeftArrowPress(Action *action)\n{\n\t_sel = _lstItems->getSelectedRow();\n\tif (_game->isLeftClick(action, true) && !_timerInc->isRunning()) _timerInc->start();\n}\n\n/**\n * Stops increasing the item.\n * @param action Pointer to an action.\n */\nvoid SellState::lstItemsLeftArrowRelease(Action *action)\n{\n\tif (_game->isLeftClick(action, true))\n\t{\n\t\t_timerInc->stop();\n\t}\n}\n\n/**\n * Increases the selected item;\n * by one on left-click, to max on right-click.\n * @param action Pointer to an action.\n */\nvoid SellState::lstItemsLeftArrowClick(Action *action)\n{\n\tif (_game->isRightClick(action, true)) changeByValue(INT_MAX, 1);\n\tif (_game->isLeftClick(action, true))\n\t{\n\t\tchangeByValue(_game->getScrollStep(), 1);\n\t\t_timerInc->setInterval(250);\n\t\t_timerDec->setInterval(250);\n\t}\n}\n\n/**\n * Starts decreasing the item.\n * @param action Pointer to an action.\n */\nvoid SellState::lstItemsRightArrowPress(Action *action)\n{\n\t_sel = _lstItems->getSelectedRow();\n\tif (_game->isLeftClick(action, true) && !_timerDec->isRunning()) _timerDec->start();\n}\n\n/**\n * Stops decreasing the item.\n * @param action Pointer to an action.\n */\nvoid SellState::lstItemsRightArrowRelease(Action *action)\n{\n\tif (_game->isLeftClick(action, true))\n\t{\n\t\t_timerDec->stop();\n\t}\n}\n\n/**\n * Decreases the selected item;\n * by one on left-click, to 0 on right-click.\n * @param action Pointer to an action.\n */\nvoid SellState::lstItemsRightArrowClick(Action *action)\n{\n\tif (_game->isRightClick(action, true)) changeByValue(INT_MAX, -1);\n\tif (_game->isLeftClick(action, true))\n\t{\n\t\tchangeByValue(_game->getScrollStep(), -1);\n\t\t_timerInc->setInterval(250);\n\t\t_timerDec->setInterval(250);\n\t}\n}\n\n/**\n * Handles the mouse-wheels on the arrow-buttons.\n * @param action Pointer to an action.\n */\nvoid SellState::lstItemsMousePress(Action *action)\n{\n\t_sel = _lstItems->getSelectedRow();\n\tif (action->getDetails()->button.button == SDL_BUTTON_WHEELUP)\n\t{\n\t\t_timerInc->stop();\n\t\t_timerDec->stop();\n\t\tif (action->getAbsoluteXMouse() >= _lstItems->getArrowsLeftEdge() &&\n\t\t\taction->getAbsoluteXMouse() <= _lstItems->getArrowsRightEdge())\n\t\t{\n\t\t\tchangeByValue(Options::changeValueByMouseWheel, 1);\n\t\t}\n\t}\n\telse if (action->getDetails()->button.button == SDL_BUTTON_WHEELDOWN)\n\t{\n\t\t_timerInc->stop();\n\t\t_timerDec->stop();\n\t\tif (action->getAbsoluteXMouse() >= _lstItems->getArrowsLeftEdge() &&\n\t\t\taction->getAbsoluteXMouse() <= _lstItems->getArrowsRightEdge())\n\t\t{\n\t\t\tchangeByValue(Options::changeValueByMouseWheel, -1);\n\t\t}\n\t}\n\telse if (_game->isRightClick(action, true))\n\t{\n\t\tif (action->getAbsoluteXMouse() >= _lstItems->getArrowsLeftEdge() &&\n\t\t\taction->getAbsoluteXMouse() <= _lstItems->getArrowsRightEdge())\n\t\t{\n\t\t\treturn;\n\t\t}\n\t\tif (getRow().type == TRANSFER_ITEM)\n\t\t{\n\t\t\tRuleItem *rule = (RuleItem*)getRow().rule;\n\t\t\tif (rule != 0)\n\t\t\t{\n\t\t\t\tif (_game->isCtrlPressed(true))\n\t\t\t\t{\n\t\t\t\t\tif (_game->isShiftPressed(true))\n\t\t\t\t\t{\n\t\t\t\t\t\tif (!rule->getType().empty())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tbool categoryHidden = (_cats[_cbxCategory->getSelected()] == \"STR_FILTER_HIDDEN\");\n\n\t\t\t\t\t\t\tauto& hiddenMap = _game->getSavedGame()->getHiddenPurchaseItems();\n\t\t\t\t\t\t\tauto iter = hiddenMap.find(rule->getType());\n\t\t\t\t\t\t\tbool hidden = false;\n\t\t\t\t\t\t\tif (iter != hiddenMap.end())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// found => unhide it when in \"Hidden\" view; mark it as hidden otherwise\n\t\t\t\t\t\t\t\thidden = !categoryHidden;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// not found = not hidden yet => mark it as hidden\n\t\t\t\t\t\t\t\thidden = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t_game->getSavedGame()->setHiddenPurchaseItemsStatus(rule->getType(), hidden);\n\n\t\t\t\t\t\t\tif (categoryHidden)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// update screen\n\t\t\t\t\t\t\t\tsize_t scrollPos = _lstItems->getScroll();\n\t\t\t\t\t\t\t\tupdateList();\n\t\t\t\t\t\t\t\t_lstItems->scrollTo(scrollPos);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// no screen update, at least play a sound\n\t\t\t\t\t\t\t\t_game->getMod()->getSound(\"GEO.CAT\", Mod::UFO_EXPLODE)->play();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t_game->pushState(new ItemLocationsState(rule));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t_game->pushState(new ManufactureDependenciesTreeState(rule->getType()));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\telse if (_game->isMiddleClick(action, true))\n\t{\n\t\tif (getRow().type == TRANSFER_ITEM)\n\t\t{\n\t\t\tRuleItem *rule = (RuleItem*)getRow().rule;\n\t\t\tif (rule != 0)\n\t\t\t{\n\t\t\t\tstd::string articleId = rule->getUfopediaType();\n\t\t\t\tif (_game->isCtrlPressed(true))\n\t\t\t\t{\n\t\t\t\t\tUfopaedia::openArticle(_game, articleId);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tconst RuleResearch* selectedTopic = _game->getMod()->getResearch(articleId, false);\n\t\t\t\t\tif (selectedTopic)\n\t\t\t\t\t{\n\t\t\t\t\t\t_game->pushState(new TechTreeViewerState(selectedTopic, 0));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse if (getRow().type == TRANSFER_CRAFT)\n\t\t{\n\t\t\tCraft *rule = (Craft*)getRow().rule;\n\t\t\tif (rule != 0)\n\t\t\t{\n\t\t\t\tstd::string articleId = rule->getRules()->getType();\n\t\t\t\tif (_game->isCtrlPressed(true))\n\t\t\t\t{\n\t\t\t\t\tUfopaedia::openArticle(_game, articleId);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t_game->pushState(new TechTreeViewerState(0, 0, 0, rule->getRules()));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Increases the quantity of the selected item to sell by one.\n */\nvoid SellState::increase()\n{\n\t_timerDec->setInterval(50);\n\t_timerInc->setInterval(50);\n\tchangeByValue(_game->getScrollStep(), 1);\n}\n\n/**\n * Increases or decreases the quantity of the selected item to sell.\n * @param change How much we want to add or remove.\n * @param dir Direction to change, +1 to increase or -1 to decrease.\n */\nvoid SellState::changeByValue(int change, int dir)\n{\n\tif (dir > 0 && getRow().type == TRANSFER_ITEM)\n\t{\n\t\tconst RuleItem* tmpItem = (const RuleItem*)getRow().rule;;\n\t\tif (!tmpItem->getSellActionMessage().empty() && !_game->isShiftPressed(true))\n\t\t{\n\t\t\t_timerInc->stop();\n\t\t\t_timerDec->stop();\n\t\t\tRuleInterface* menuInterface = _game->getMod()->getInterface(\"buyMenu\");\n\t\t\t_game->pushState(new ErrorMessageState(\n\t\t\t\ttr(tmpItem->getSellActionMessage()),\n\t\t\t\t_palette,\n\t\t\t\tmenuInterface->getElement(\"errorMessage\")->color,\n\t\t\t\t\"BACK13.SCR\",\n\t\t\t\tmenuInterface->getElement(\"errorPalette\")->color)\n\t\t\t);\n\n\t\t\treturn;\n\t\t}\n\t}\n\n\tif (dir > 0)\n\t{\n\t\tif (0 >= change || getRow().qtySrc <= getRow().amount) return;\n\t\tchange = std::min(getRow().qtySrc - getRow().amount, change);\n\t\tif (_sellAllButOne && change > 0)\n\t\t{\n\t\t\t--change;\n\t\t}\n\t}\n\telse\n\t{\n\t\tif (0 >= change || 0 >= getRow().amount) return;\n\t\tchange = std::min(getRow().amount, change);\n\t}\n\tgetRow().amount += dir * change;\n\t_total += dir * getRow().cost * change;\n\n\t// Calculate the change in storage space.\n\tSoldier *soldier;\n\tconst RuleItem *item;\n\tswitch (getRow().type)\n\t{\n\tcase TRANSFER_SOLDIER:\n\t\tsoldier = (Soldier*)getRow().rule;\n\t\tif (soldier->getArmor()->getStoreItem())\n\t\t{\n\t\t\t_spaceChange += dir * soldier->getArmor()->getStoreItem()->getSize();\n\t\t}\n\t\tbreak;\n\tcase TRANSFER_CRAFT:\n\t\t// Note: in OXCE, there is no storage space change, everything on the craft is already included in the base storage space calculations\n\t\tbreak;\n\tcase TRANSFER_ITEM:\n\t\titem = (const RuleItem*)getRow().rule;\n\t\t_spaceChange -= dir * change * item->getSize();\n\t\tbreak;\n\tdefault:\n\t\t//TRANSFER_SCIENTIST and TRANSFER_ENGINEER do not own anything that takes storage\n\t\tbreak;\n\t}\n\n\tupdateItemStrings();\n}\n\n/**\n * Decreases the quantity of the selected item to sell by one.\n */\nvoid SellState::decrease()\n{\n\t_timerInc->setInterval(50);\n\t_timerDec->setInterval(50);\n\tchangeByValue(_game->getScrollStep(), -1);\n}\n\n/**\n * Updates the quantity-strings of the selected item.\n */\nvoid SellState::updateItemStrings()\n{\n\tstd::ostringstream ss, ss2, ss3;\n\tss << getRow().amount;\n\t_lstItems->setCellText(_sel, 2, ss.str());\n\tss2 << getRow().qtySrc - getRow().amount;\n\t_lstItems->setCellText(_sel, 1, ss2.str());\n\t_txtSales->setText(tr(\"STR_VALUE_OF_SALES\").arg(Unicode::formatFunding(_total)));\n\n\tif (getRow().amount > 0)\n\t{\n\t\t_lstItems->setRowColor(_sel, _lstItems->getSecondaryColor());\n\t}\n\telse\n\t{\n\t\t_lstItems->setRowColor(_sel, _lstItems->getColor());\n\t\tif (getRow().type == TRANSFER_ITEM)\n\t\t{\n\t\t\tRuleItem *rule = (RuleItem*)getRow().rule;\n\t\t\tif (rule->getBattleType() == BT_AMMO || (rule->getBattleType() == BT_NONE && rule->getClipSize() > 0))\n\t\t\t{\n\t\t\t\t_lstItems->setRowColor(_sel, _ammoColor);\n\t\t\t}\n\t\t}\n\t}\n\n\tss3 << _base->getUsedStores();\n\tif (std::abs(_spaceChange) > 0.05)\n\t{\n\t\tss3 << \"(\";\n\t\tif (_spaceChange > 0.05)\n\t\t\tss3 << \"+\";\n\t\tss3 << std::fixed << std::setprecision(1) << _spaceChange << \")\";\n\t}\n\tss3 << \":\" << _base->getAvailableStores();\n\t_txtSpaceUsed->setText(tr(\"STR_SPACE_USED\").arg(ss3.str()));\n\tif (_debriefingState == 0 && Options::storageLimitsEnforced)\n\t{\n\t\t_btnOk->setVisible(!_base->storesOverfull(_spaceChange));\n\t}\n}\n\n/**\n* Updates the production list to match the category filter.\n*/\nvoid SellState::cbxCategoryChange(Action *)\n{\n\t_previousSort = _currentSort;\n\n\tif (_game->isCtrlPressed(true))\n\t{\n\t\t_currentSort = _game->isShiftPressed(true) ? TransferSortDirection::BY_UNIT_SIZE : TransferSortDirection::BY_TOTAL_SIZE;\n\t}\n\telse if (_game->isAltPressed(true))\n\t{\n\t\t_currentSort = _game->isShiftPressed(true) ? TransferSortDirection::BY_UNIT_COST : TransferSortDirection::BY_TOTAL_COST;\n\t}\n\telse\n\t{\n\t\t_currentSort = TransferSortDirection::BY_LIST_ORDER;\n\t}\n\n\tupdateList();\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/SellState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/TouchState.h\"\n#include \"../Savegame/Transfer.h\"\n#include \"../Menu/OptionsBaseState.h\"\n#include <vector>\n#include <string>\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass TextEdit;\nclass TextList;\nclass ComboBox;\nclass Timer;\nclass Base;\nclass DebriefingState;\nclass RuleItem;\n\n/**\n * Sell/Sack screen that lets the player sell\n * any items in a particular base.\n */\nclass SellState : public TouchState\n{\nprivate:\n\tBase *_base;\n\tDebriefingState *_debriefingState;\n\tTextButton *_btnOk, *_btnCancel, *_btnTransfer;\n\tTextEdit *_btnQuickSearch;\n\tWindow *_window;\n\tText *_txtTitle, *_txtSales, *_txtFunds, *_txtQuantity, *_txtSell, *_txtValue, *_txtSpaceUsed;\n\tComboBox *_cbxCategory;\n\tTextList *_lstItems;\n\tstd::vector<TransferRow> _items;\n\tstd::vector<int> _rows;\n\tstd::vector<std::string> _cats;\n\tsize_t _vanillaCategories;\n\tsize_t _sel;\n\tint64_t _total;\n\tdouble _spaceChange;\n\tTimer *_timerInc, *_timerDec;\n\tUint8 _ammoColor;\n\tOptionsOrigin _origin;\n\tbool _reset;\n\tbool _sellAllButOne;\n\tbool _delayedInitDone;\n\tTransferSortDirection _previousSort, _currentSort;\n\n\t/// Gets the category of the current selection.\n\tstd::string getCategory(int sel) const;\n\t/// Determines if the current selection belongs to a given category.\n\tbool belongsToCategory(int sel, const std::string &cat) const;\n\t/// Checks for hidden items\n\tbool isHidden(int sel) const;\n\t/// Gets the row of the current selection.\n\tTransferRow &getRow() { return _items[_rows[_sel]]; }\npublic:\n\t/// Creates the Sell state.\n\tSellState(Base *base, DebriefingState *debriefingState, OptionsOrigin origin = OPT_GEOSCAPE);\n\tvoid delayedInit();\n\t/// Cleans up the Sell state.\n\t~SellState();\n\t/// Resets state.\n\tvoid init() override;\n\t/// Runs the timers.\n\tvoid think() override;\n\t/// Updates the item list.\n\tvoid updateList();\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action *action);\n\t/// Handler for clicking the Transfer button.\n\tvoid btnTransferClick(Action *action);\n\t/// Handlers for Quick Search.\n\tvoid btnQuickSearchToggle(Action *action);\n\tvoid btnQuickSearchApply(Action *action);\n\t/// Handler for pressing the \"Sell all\" hotkey.\n\tvoid btnSellAllClick(Action *action);\n\t/// Handler for pressing the \"Sell all but one\" hotkey.\n\tvoid btnSellAllButOneClick(Action *action);\n\t/// Handler for pressing an Increase arrow in the list.\n\tvoid lstItemsLeftArrowPress(Action *action);\n\t/// Handler for releasing an Increase arrow in the list.\n\tvoid lstItemsLeftArrowRelease(Action *action);\n\t/// Handler for clicking an Increase arrow in the list.\n\tvoid lstItemsLeftArrowClick(Action *action);\n\t/// Handler for pressing a Decrease arrow in the list.\n\tvoid lstItemsRightArrowPress(Action *action);\n\t/// Handler for releasing a Decrease arrow in the list.\n\tvoid lstItemsRightArrowRelease(Action *action);\n\t/// Handler for clicking a Decrease arrow in the list.\n\tvoid lstItemsRightArrowClick(Action *action);\n\t/// Handler for pressing-down a mouse-button in the list.\n\tvoid lstItemsMousePress(Action *action);\n\t/// Increases the quantity of an item by one.\n\tvoid increase();\n\t/// Decreases the quantity of an item by one.\n\tvoid decrease();\n\t/// Changes the quantity of an item by the given value.\n\tvoid changeByValue(int change, int dir);\n\t/// Updates the quantity-strings of the selected item.\n\tvoid updateItemStrings();\n\t/// Handler for changing the category filter.\n\tvoid cbxCategoryChange(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/SoldierArmorState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"SoldierArmorState.h\"\n#include <sstream>\n#include <algorithm>\n#include \"../Engine/Action.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/ArrowButton.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextEdit.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Menu/ErrorMessageState.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Mod/RuleInterface.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Craft.h\"\n#include \"../Savegame/Soldier.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/ItemContainer.h\"\n#include \"../Mod/RuleSoldier.h\"\n#include \"../Ufopaedia/Ufopaedia.h\"\n\nnamespace OpenXcom\n{\n\nstruct compareArmorName\n{\n\tbool operator()(const ArmorItem &a, const ArmorItem &b) const\n\t{\n\t\treturn Unicode::naturalCompare(a.name, b.name);\n\t}\n};\n\n\n/**\n * Initializes all the elements in the Soldier Armor window.\n * @param base Pointer to the base to get info from.\n * @param soldier ID of the selected soldier.\n */\nSoldierArmorState::SoldierArmorState(Base *base, size_t soldier, SoldierArmorOrigin origin) : _base(base), _soldier(soldier), _origin(origin)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 192, 160, 64, 20, POPUP_BOTH);\n\t_btnQuickSearch = new TextEdit(this, 48, 9, 80, 43);\n\t_btnCancel = new TextButton(140, 16, 90, 156);\n\t_txtTitle = new Text(182, 16, 69, 28);\n\t_txtType = new Text(90, 9, 80, 52);\n\t_txtQuantity = new Text(70, 9, 190, 52);\n\t_lstArmor = new TextList(160, 80, 73, 68);\n\t_sortName = new ArrowButton(ARROW_NONE, 11, 8, 80, 52);\n\n\t// Set palette\n\tif (_origin == SA_BATTLESCAPE)\n\t{\n\t\tsetStandardPalette(\"PAL_BATTLESCAPE\");\n\t}\n\telse\n\t{\n\t\tsetInterface(\"soldierArmor\");\n\t}\n\n\tadd(_window, \"window\", \"soldierArmor\");\n\tadd(_btnQuickSearch, \"button\", \"soldierArmor\");\n\tadd(_btnCancel, \"button\", \"soldierArmor\");\n\tadd(_txtTitle, \"text\", \"soldierArmor\");\n\tadd(_txtType, \"text\", \"soldierArmor\");\n\tadd(_txtQuantity, \"text\", \"soldierArmor\");\n\tadd(_lstArmor, \"list\", \"soldierArmor\");\n\tadd(_sortName, \"text\", \"soldierArmor\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"soldierArmor\");\n\n\t_btnCancel->setText(tr(\"STR_CANCEL_UC\"));\n\t_btnCancel->onMouseClick((ActionHandler)&SoldierArmorState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&SoldierArmorState::btnCancelClick, Options::keyCancel);\n\n\tSoldier *s = _base->getSoldiers()->at(_soldier);\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_SELECT_ARMOR_FOR_SOLDIER\").arg(s->getName()));\n\n\t_txtType->setText(tr(\"STR_TYPE\"));\n\n\t_txtQuantity->setText(tr(\"STR_QUANTITY_UC\"));\n\n\t_lstArmor->setColumns(2, 132, 21);\n\t_lstArmor->setSelectable(true);\n\t_lstArmor->setBackground(_window);\n\t_lstArmor->setMargin(8);\n\n\t_sortName->setX(_sortName->getX() + _txtType->getTextWidth() + 4);\n\t_sortName->onMouseClick((ActionHandler)&SoldierArmorState::sortNameClick);\n\n\t{\n\t\t// refresh soldier's _bonusCache, needed below in Armor::getCanBeUsedBy()\n\t\t//s->getBonuses(_game->getMod());\n\t}\n\n\tfor (auto* a : _game->getMod()->getArmorsForSoldiers())\n\t{\n\t\tif (a->getRequiredResearch() && !_game->getSavedGame()->isResearched(a->getRequiredResearch()))\n\t\t\tcontinue;\n\t\tif (!a->getCanBeUsedBy(s))\n\t\t\tcontinue;\n\t\tif (a->hasInfiniteSupply())\n\t\t{\n\t\t\t_armors.push_back(ArmorItem(a->getType(), tr(a->getType()), \"\"));\n\t\t}\n\t\telse if (_base->getStorageItems()->getItem(a->getStoreItem()) > 0 || a->getStoreItem() == s->getArmor()->getStoreItem())\n\t\t{\n\t\t\tstd::ostringstream ss;\n\t\t\tif (_game->getSavedGame()->getMonthsPassed() > -1)\n\t\t\t{\n\t\t\t\tss << _base->getStorageItems()->getItem(a->getStoreItem());\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tss << \"-\";\n\t\t\t}\n\t\t\t_armors.push_back(ArmorItem(a->getType(), tr(a->getType()), ss.str()));\n\t\t}\n\t}\n\n\t_btnQuickSearch->setText(\"\"); // redraw\n\t_btnQuickSearch->onEnter((ActionHandler)&SoldierArmorState::btnQuickSearchApply);\n\t_btnQuickSearch->setVisible(Options::oxceQuickSearchButton);\n\n\t_btnCancel->onKeyboardRelease((ActionHandler)&SoldierArmorState::btnQuickSearchToggle, Options::keyToggleQuickSearch);\n\n\t_armorOrder = ARMOR_SORT_NONE;\n\tsortList();\n\n\t_lstArmor->onMouseClick((ActionHandler)&SoldierArmorState::lstArmorClick);\n\t_lstArmor->onMouseClick((ActionHandler)&SoldierArmorState::lstArmorClickMiddle, SDL_BUTTON_MIDDLE);\n\n\t// switch to battlescape theme if called from inventory\n\tif (_origin == SA_BATTLESCAPE)\n\t{\n\t\tapplyBattlescapeTheme(\"soldierArmor\");\n\t}\n}\n\n/**\n *\n */\nSoldierArmorState::~SoldierArmorState()\n{\n\n}\n\n/**\n* Updates the sorting arrows based\n* on the current setting.\n*/\nvoid SoldierArmorState::updateArrows()\n{\n\t_sortName->setShape(ARROW_NONE);\n\tswitch (_armorOrder)\n\t{\n\tcase ARMOR_SORT_NAME_ASC:\n\t\t_sortName->setShape(ARROW_SMALL_UP);\n\t\tbreak;\n\tcase ARMOR_SORT_NAME_DESC:\n\t\t_sortName->setShape(ARROW_SMALL_DOWN);\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n}\n\n/**\n* Sorts the armor list.\n*/\nvoid SoldierArmorState::sortList()\n{\n\tupdateArrows();\n\n\tswitch (_armorOrder)\n\t{\n\tcase ARMOR_SORT_NAME_ASC:\n\t\tstd::stable_sort(_armors.begin(), _armors.end(), compareArmorName());\n\t\tbreak;\n\tcase ARMOR_SORT_NAME_DESC:\n\t\tstd::stable_sort(_armors.rbegin(), _armors.rend(), compareArmorName());\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n\n\tupdateList();\n}\n\n/**\n* Updates the armor list with the current list\n* of available armors.\n*/\nvoid SoldierArmorState::updateList()\n{\n\tstd::string searchString = _btnQuickSearch->getText();\n\tUnicode::upperCase(searchString);\n\n\t_lstArmor->clearList();\n\t_indices.clear();\n\n\tint index = -1;\n\tfor (const auto& armorItem : _armors)\n\t{\n\t\t++index;\n\n\t\t// quick search\n\t\tif (!searchString.empty())\n\t\t{\n\t\t\tstd::string armorName = armorItem.name;\n\t\t\tUnicode::upperCase(armorName);\n\t\t\tif (armorName.find(searchString) == std::string::npos)\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\t_lstArmor->addRow(2, armorItem.name.c_str(), armorItem.quantity.c_str());\n\t\t_indices.push_back(index);\n\t}\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid SoldierArmorState::btnCancelClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Quick search toggle.\n * @param action Pointer to an action.\n */\nvoid SoldierArmorState::btnQuickSearchToggle(Action* action)\n{\n\tif (_btnQuickSearch->getVisible())\n\t{\n\t\t_btnQuickSearch->setText(\"\");\n\t\t_btnQuickSearch->setVisible(false);\n\t\tbtnQuickSearchApply(action);\n\t}\n\telse\n\t{\n\t\t_btnQuickSearch->setVisible(true);\n\t\t_btnQuickSearch->setFocus(true);\n\t}\n}\n\n/**\n * Quick search.\n * @param action Pointer to an action.\n */\nvoid SoldierArmorState::btnQuickSearchApply(Action*)\n{\n\tupdateList();\n}\n\n/**\n * Equips the armor on the soldier and returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid SoldierArmorState::lstArmorClick(Action *)\n{\n\tSoldier *soldier = _base->getSoldiers()->at(_soldier);\n\tArmor *prev = soldier->getArmor();\n\tArmor *next = _game->getMod()->getArmor(_armors[_indices[_lstArmor->getSelectedRow()]].type);\n\tCraft *craft = soldier->getCraft();\n\tif (craft)\n\t{\n\t\tif (!craft->validateArmorChange(prev->getSize(), next->getSize()))\n\t\t{\n\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_NOT_ENOUGH_CRAFT_SPACE\"), _palette, _game->getMod()->getInterface(\"soldierInfo\")->getElement(\"errorMessage\")->color, \"BACK01.SCR\", _game->getMod()->getInterface(\"soldierInfo\")->getElement(\"errorPalette\")->color));\n\t\t\treturn;\n\t\t}\n\t}\n\tif (_game->getSavedGame()->getMonthsPassed() != -1)\n\t{\n\t\tif (prev->getStoreItem())\n\t\t{\n\t\t\t_base->getStorageItems()->addItem(prev->getStoreItem());\n\t\t}\n\t\tif (next->getStoreItem())\n\t\t{\n\t\t\t_base->getStorageItems()->removeItem(next->getStoreItem());\n\t\t}\n\t}\n\tsoldier->setArmor(next, true);\n\t_game->getSavedGame()->setLastSelectedArmor(next->getType());\n\n\t_game->popState();\n}\n\n/**\n* Shows corresponding Ufopaedia article.\n* @param action Pointer to an action.\n*/\nvoid SoldierArmorState::lstArmorClickMiddle(Action *action)\n{\n\tArmor* armor = _game->getMod()->getArmor(_armors[_indices[_lstArmor->getSelectedRow()]].type, true);\n\tstd::string articleId = armor->getUfopediaType();\n\tUfopaedia::openArticle(_game, articleId);\n}\n\n/**\n* Sorts the armors by name.\n* @param action Pointer to an action.\n*/\nvoid SoldierArmorState::sortNameClick(Action *)\n{\n\t_armorOrder = _armorOrder == ARMOR_SORT_NAME_ASC ? ARMOR_SORT_NAME_DESC : ARMOR_SORT_NAME_ASC;\n\tsortList();\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/SoldierArmorState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <vector>\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nenum SoldierArmorOrigin\n{\n\tSA_GEOSCAPE,\n\tSA_BATTLESCAPE\n};\n\nclass Base;\nclass TextButton;\nclass Window;\nclass Text;\nclass TextEdit;\nclass TextList;\nclass Armor;\nclass ArrowButton;\n\n/// Armor sorting modes.\nenum ArmorSort\n{\n\tARMOR_SORT_NONE,\n\tARMOR_SORT_NAME_ASC,\n\tARMOR_SORT_NAME_DESC,\n};\n\nstruct ArmorItem\n{\n\tArmorItem(const std::string &_type, const std::string &_name, const std::string &_quantity) : type(_type), name(_name), quantity(_quantity)\n\t{\n\t}\n\tstd::string type;\n\tstd::string name, quantity;\n};\n\n/**\n * Select Armor window that allows changing\n * of the armor equipped on a soldier.\n */\nclass SoldierArmorState : public State\n{\nprivate:\n\tBase *_base;\n\tsize_t _soldier;\n\n\tSoldierArmorOrigin _origin;\n\tTextButton *_btnCancel;\n\tTextEdit *_btnQuickSearch;\n\tWindow *_window;\n\tText *_txtTitle, *_txtType, *_txtQuantity;\n\tTextList *_lstArmor;\n\tArrowButton *_sortName;\n\tstd::vector<ArmorItem> _armors;\n\tstd::vector<int> _indices;\n\tArmorSort _armorOrder;\n\tvoid updateArrows();\npublic:\n\t/// Creates the Soldier Armor state.\n\tSoldierArmorState(Base *base, size_t soldier, SoldierArmorOrigin origin);\n\t/// Cleans up the Soldier Armor state.\n\t~SoldierArmorState();\n\t/// Sorts the armor list.\n\tvoid sortList();\n\t/// Updates the armor list.\n\tvoid updateList();\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action *action);\n\t/// Handlers for Quick Search.\n\tvoid btnQuickSearchToggle(Action* action);\n\tvoid btnQuickSearchApply(Action* action);\n\t/// Handler for clicking the Weapons list.\n\tvoid lstArmorClick(Action *action);\n\t/// Handler for clicking the Weapons list.\n\tvoid lstArmorClickMiddle(Action *action);\n\t/// Handler for clicking the Name arrow.\n\tvoid sortNameClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/SoldierAvatarState.cpp",
    "content": "/*\n * Copyright 2010-2015 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"SoldierAvatarState.h\"\n#include <sstream>\n#include <string>\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Soldier.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Mod/RuleSoldier.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Soldier Avatar window.\n * @param game Pointer to the core game.\n * @param base Pointer to the base to get info from.\n * @param soldier ID of the selected soldier.\n */\nSoldierAvatarState::SoldierAvatarState(Base *base, size_t soldier) : _base(base), _soldier(soldier)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 240, 160, 40, 24, POPUP_BOTH);\n\t_soldierSurface = new Surface(320, 200, 0, 0);\n\t_btnCancel = new TextButton(100, 16, 55, 160);\n\t_btnOk = new TextButton(100, 16, 165, 160);\n\t_txtTitle = new Text(182, 16, 69, 32);\n\t_txtType = new Text(90, 9, 122, 58);\n\t_lstAvatar = new TextList(132, 80, 115, 72);\n\n\t// Set palette\n\tsetStandardPalette(\"PAL_BATTLESCAPE\");\n\n\tadd(_window, \"window\", \"soldierAvatar\");\n\tadd(_soldierSurface);\n\tadd(_btnCancel, \"button\", \"soldierAvatar\");\n\tadd(_btnOk, \"button\", \"soldierAvatar\");\n\tadd(_txtTitle, \"text\", \"soldierAvatar\");\n\tadd(_txtType, \"text\", \"soldierAvatar\");\n\tadd(_lstAvatar, \"list\", \"soldierAvatar\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"soldierAvatar\");\n\n\t_btnCancel->setText(tr(\"STR_CANCEL_UC\"));\n\t_btnCancel->onMouseClick((ActionHandler)&SoldierAvatarState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&SoldierAvatarState::btnCancelClick, Options::keyCancel);\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&SoldierAvatarState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&SoldierAvatarState::btnOkClick, Options::keyOk);\n\n\tSoldier *s = _base->getSoldiers()->at(_soldier);\n\t_origAvatar = SoldierAvatar(\"original\", s->getGender(), s->getLook(), s->getLookVariant());\n\tinitPreview(s);\n\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_SELECT_AVATAR_FOR\").arg(s->getName()));\n\n\t_txtType->setText(tr(\"STR_TYPE\"));\n\n\t_lstAvatar->setColumns(1, 125);\n\t_lstAvatar->setSelectable(true);\n\t_lstAvatar->setBackground(_window);\n\t_lstAvatar->setMargin(8);\n\n\tstd::string prefix = \"STR_AVATAR_NAME_\";\n\tfor (int variant = 0; variant <= _game->getMod()->getMaxLookVariant(); ++variant)\n\t{\n\t\tif (!_game->isAltPressed())\n\t\t{\n\t\t\t_avatars.push_back(SoldierAvatar(prefix + std::to_string(variant * 8 + 1), GENDER_MALE, LOOK_BLONDE, variant));\n\t\t\t_avatars.push_back(SoldierAvatar(prefix + std::to_string(variant * 8 + 2), GENDER_MALE, LOOK_BROWNHAIR, variant));\n\t\t\t_avatars.push_back(SoldierAvatar(prefix + std::to_string(variant * 8 + 3), GENDER_MALE, LOOK_ORIENTAL, variant));\n\t\t\t_avatars.push_back(SoldierAvatar(prefix + std::to_string(variant * 8 + 4), GENDER_MALE, LOOK_AFRICAN, variant));\n\t\t}\n\t\tif (!_game->isCtrlPressed())\n\t\t{\n\t\t\t_avatars.push_back(SoldierAvatar(prefix + std::to_string(variant * 8 + 5), GENDER_FEMALE, LOOK_BLONDE, variant));\n\t\t\t_avatars.push_back(SoldierAvatar(prefix + std::to_string(variant * 8 + 6), GENDER_FEMALE, LOOK_BROWNHAIR, variant));\n\t\t\t_avatars.push_back(SoldierAvatar(prefix + std::to_string(variant * 8 + 7), GENDER_FEMALE, LOOK_ORIENTAL, variant));\n\t\t\t_avatars.push_back(SoldierAvatar(prefix + std::to_string(variant * 8 + 8), GENDER_FEMALE, LOOK_AFRICAN, variant));\n\t\t}\n\t}\n\n\tfor (const auto& soldierAvatar : _avatars)\n\t{\n\t\t_lstAvatar->addRow(1, tr(soldierAvatar.getAvatarName()).c_str());\n\t}\n\t_lstAvatar->onMouseClick((ActionHandler)&SoldierAvatarState::lstAvatarClick);\n\n\t// switch to battlescape theme if called from inventory\n\tapplyBattlescapeTheme(\"soldierAvatar\");\n}\n\n/**\n * Shows the preview\n * @param s Soldier.\n */\nvoid SoldierAvatarState::initPreview(Soldier *s)\n{\n\t_soldierSurface->clear();\n\n\tif (!s)\n\t{\n\t\treturn;\n\t}\n\n\tif (s->getArmor()->hasLayersDefinition())\n\t{\n\t\tfor (const auto& layer : s->getArmorLayers())\n\t\t{\n\t\t\tauto* surf = _game->getMod()->getSurface(layer, true);\n\t\t\tsurf->blitNShade(_soldierSurface, 0, 0);\n\t\t}\n\t}\n\telse\n\t{\n\t\tconst std::string look = s->getArmor()->getSpriteInventory();\n\t\tconst std::string gender = s->getGender() == GENDER_MALE ? \"M\" : \"F\";\n\t\tstd::stringstream ss;\n\t\tSurface *surf = 0;\n\n\t\tfor (int i = 0; i <= RuleSoldier::LookVariantBits; ++i)\n\t\t{\n\t\t\tss.str(\"\");\n\t\t\tss << look;\n\t\t\tss << gender;\n\t\t\tss << (int)s->getLook() + (s->getLookVariant() & (RuleSoldier::LookVariantMask >> i)) * 4;\n\t\t\tss << \".SPK\";\n\t\t\tstd::string debug = ss.str();\n\t\t\tsurf = _game->getMod()->getSurface(ss.str(), false);\n\t\t\tif (surf)\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (!surf)\n\t\t{\n\t\t\tss.str(\"\");\n\t\t\tss << look;\n\t\t\tss << \".SPK\";\n\t\t\tsurf = _game->getMod()->getSurface(ss.str(), false);\n\t\t}\n\t\tif (!surf)\n\t\t{\n\t\t\tsurf = _game->getMod()->getSurface(look, true);\n\t\t}\n\t\tsurf->blitNShade(_soldierSurface, 0, 0);\n\t}\n}\n\n/**\n *\n */\nSoldierAvatarState::~SoldierAvatarState()\n{\n\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid SoldierAvatarState::btnCancelClick(Action *)\n{\n\tSoldier *soldier = _base->getSoldiers()->at(_soldier);\n\n\t// revert the avatar to original\n\tsoldier->setGender(_origAvatar.getGender());\n\tsoldier->setLook(_origAvatar.getLook());\n\tsoldier->setLookVariant(_origAvatar.getLookVariant());\n\n\t_game->popState();\n}\n\n/**\n * Changes the avatar on the soldier and returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid SoldierAvatarState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Changes the avatar on the soldier and returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid SoldierAvatarState::lstAvatarClick(Action *)\n{\n\tSoldier *soldier = _base->getSoldiers()->at(_soldier);\n\n\t// change the avatar\n\tsoldier->setGender(_avatars[_lstAvatar->getSelectedRow()].getGender());\n\tsoldier->setLook(_avatars[_lstAvatar->getSelectedRow()].getLook());\n\tsoldier->setLookVariant(_avatars[_lstAvatar->getSelectedRow()].getLookVariant());\n\n\tinitPreview(soldier);\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/SoldierAvatarState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2015 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <vector>\n#include \"../Engine/State.h\"\n#include \"../Savegame/SoldierAvatar.h\"\n\nnamespace OpenXcom\n{\n\nclass Base;\nclass TextButton;\nclass Window;\nclass Text;\nclass TextList;\nclass Soldier;\nclass SoldierAvatar;\n\n/**\n * Select Avatar window that allows changing\n * of the soldier's avatar.\n */\nclass SoldierAvatarState : public State\n{\nprivate:\n\tBase *_base;\n\tsize_t _soldier;\n\n\tTextButton *_btnCancel, *_btnOk;\n\tWindow *_window;\n\tText *_txtTitle, *_txtType;\n\tSurface *_soldierSurface;\n\tTextList *_lstAvatar;\n\tstd::vector<SoldierAvatar> _avatars;\n\tSoldierAvatar _origAvatar;\n\t/// Creates the avatar preview\n\tvoid initPreview(Soldier *s);\npublic:\n\t/// Creates the Soldier Avatar state.\n\tSoldierAvatarState(Base *base, size_t soldier);\n\t/// Cleans up the Soldier Avatar state.\n\t~SoldierAvatarState();\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action *action);\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the Avatar list.\n\tvoid lstAvatarClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/SoldierBonusState.cpp",
    "content": "/*\n * Copyright 2010-2019 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"SoldierBonusState.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/HelperMeta.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Interface/ToggleTextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Mod/ArticleDefinition.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleSoldierBonus.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Soldier.h\"\n#include \"../Ufopaedia/StatsForNerdsState.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the SoldierBonus window.\n * @param base Pointer to the base to get info from.\n * @param soldier ID of the selected soldier.\n */\nSoldierBonusState::SoldierBonusState(Base *base, size_t soldier) : _base(base), _soldier(soldier)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 192, 160, 64, 20, POPUP_BOTH);\n\t_btnSummary = new ToggleTextButton(84, 16, 73, 156);\n\t_btnCancel = new TextButton(84, 16, 164, 156);\n\t_txtTitle = new Text(182, 16, 69, 28);\n\t_txtType = new Text(90, 9, 80, 52);\n\t_lstBonuses = new TextList(158, 80, 73, 68);\n\t_lstSummary = new TextList(158, 80, 73, 68);\n\n\t// Set palette\n\tsetInterface(\"soldierBonus\");\n\n\tadd(_window, \"window\", \"soldierBonus\");\n\tadd(_btnSummary, \"button\", \"soldierBonus\");\n\tadd(_btnCancel, \"button\", \"soldierBonus\");\n\tadd(_txtTitle, \"text\", \"soldierBonus\");\n\tadd(_txtType, \"text\", \"soldierBonus\");\n\tadd(_lstBonuses, \"list\", \"soldierBonus\");\n\tadd(_lstSummary, \"list\", \"soldierBonus\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"soldierBonus\");\n\n\t_btnSummary->setText(tr(\"STR_SUMMARY\"));\n\t_btnSummary->onMouseClick((ActionHandler)&SoldierBonusState::btnSummaryClick);\n\n\t_btnCancel->setText(tr(\"STR_CANCEL_UC\"));\n\t_btnCancel->onMouseClick((ActionHandler)&SoldierBonusState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&SoldierBonusState::btnCancelClick, Options::keyCancel);\n\n\tSoldier *s = _base ? _base->getSoldiers()->at(_soldier) : _game->getSavedGame()->getDeadSoldiers()->at(_soldier);\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_SOLDIER_BONUSES_FOR\").arg(s->getName()));\n\n\t_txtType->setText(tr(\"STR_TYPE\"));\n\n\t_lstBonuses->setColumns(1, 150);\n\t_lstBonuses->setSelectable(true);\n\t_lstBonuses->setBackground(_window);\n\t_lstBonuses->setMargin(8);\n\n\t_bonuses.clear();\n\t_lstBonuses->clearList();\n\tfor (auto* bonusRule : *s->getBonuses(nullptr))\n\t{\n\t\t_bonuses.push_back(bonusRule->getName());\n\t\t_lstBonuses->addRow(1, tr(bonusRule->getName()).c_str());\n\t}\n\n\t_lstBonuses->onMouseClick((ActionHandler)& SoldierBonusState::lstBonusesClick);\n\n\t_lstSummary->setColumns(2, 122, 20);\n\t_lstSummary->setAlign(ALIGN_RIGHT, 1);\n\t_lstSummary->setSelectable(true);\n\t_lstSummary->setBackground(_window);\n\t_lstSummary->setMargin(8);\n\t_lstSummary->setVisible(false);\n\n\tint visibilityAtDark = 0;\n\tint visibilityAtDay = 0;\n\tint psiVision = 0;\n\tint bonusVisibilityThroughSmoke = 0;\n\tint bonusVisibilityThroughFire = 0;\n\n\tint frontArmor = 0, leftArmor = 0, rightArmor = 0, rearArmor = 0, underArmor = 0;\n\tUnitStats stats;\n\tbool timeRecovery = false, energyRecovery = false, moraleRecovery = false, healthRecovery = false, stunRecovery = false, manaRecovery = false;\n\tfor (auto* bonusRule : *s->getBonuses(nullptr))\n\t{\n\t\tfrontArmor += bonusRule->getFrontArmor();\n\t\tleftArmor  += bonusRule->getLeftSideArmor();\n\t\trightArmor += bonusRule->getRightSideArmor();\n\t\trearArmor  += bonusRule->getRearArmor();\n\t\tunderArmor += bonusRule->getUnderArmor();\n\n\t\tvisibilityAtDark += bonusRule->getVisibilityAtDark();\n\t\tvisibilityAtDay += bonusRule->getVisibilityAtDay();\n\t\tpsiVision += bonusRule->getPsiVision();\n\t\tbonusVisibilityThroughSmoke += bonusRule->getVisibilityThroughSmoke();\n\t\tbonusVisibilityThroughFire += bonusRule->getVisibilityThroughFire();\n\n\t\tstats += *bonusRule->getStats();\n\t\ttimeRecovery = timeRecovery || bonusRule->getTimeRecoveryRaw()->isModded();\n\t\tenergyRecovery = energyRecovery || bonusRule->getEnergyRecoveryRaw()->isModded();\n\t\tmoraleRecovery = moraleRecovery || bonusRule->getMoraleRecoveryRaw()->isModded();\n\t\thealthRecovery = healthRecovery || bonusRule->getHealthRecoveryRaw()->isModded();\n\t\tstunRecovery = stunRecovery || bonusRule->getStunRegenerationRaw()->isModded();\n\t\tmanaRecovery = manaRecovery || bonusRule->getManaRecoveryRaw()->isModded();\n\t}\n\tif (stats.tu != 0)\n\t\t_lstSummary->addRow(2, tr(\"STR_TIME_UNITS\").c_str(), std::to_string(stats.tu).c_str());\n\tif (stats.stamina != 0)\n\t\t_lstSummary->addRow(2, tr(\"STR_STAMINA\").c_str(), std::to_string(stats.stamina).c_str());\n\tif (stats.health != 0)\n\t\t_lstSummary->addRow(2, tr(\"STR_HEALTH\").c_str(), std::to_string(stats.health).c_str());\n\tif (stats.bravery != 0)\n\t\t_lstSummary->addRow(2, tr(\"STR_BRAVERY\").c_str(), std::to_string(stats.bravery).c_str());\n\tif (stats.reactions != 0)\n\t\t_lstSummary->addRow(2, tr(\"STR_REACTIONS\").c_str(), std::to_string(stats.reactions).c_str());\n\tif (stats.firing != 0)\n\t\t_lstSummary->addRow(2, tr(\"STR_FIRING_ACCURACY\").c_str(), std::to_string(stats.firing).c_str());\n\tif (stats.throwing != 0)\n\t\t_lstSummary->addRow(2, tr(\"STR_THROWING_ACCURACY\").c_str(), std::to_string(stats.throwing).c_str());\n\tif (stats.melee != 0)\n\t\t_lstSummary->addRow(2, tr(\"STR_MELEE_ACCURACY\").c_str(), std::to_string(stats.melee).c_str());\n\tif (stats.strength != 0)\n\t\t_lstSummary->addRow(2, tr(\"STR_STRENGTH\").c_str(), std::to_string(stats.strength).c_str());\n\tif (stats.mana != 0)\n\t\t_lstSummary->addRow(2, tr(\"STR_MANA_POOL\").c_str(), std::to_string(stats.mana).c_str());\n\tif (stats.psiStrength != 0)\n\t\t_lstSummary->addRow(2, tr(\"STR_PSIONIC_STRENGTH\").c_str(), std::to_string(stats.psiStrength).c_str());\n\tif (stats.psiSkill != 0)\n\t\t_lstSummary->addRow(2, tr(\"STR_PSIONIC_SKILL\").c_str(), std::to_string(stats.psiSkill).c_str());\n\n\n\thelper::SingleRun gap;\n\n\n\tgap.reset();\n\tif (frontArmor != 0)\n\t{\n\t\tif (gap.tryRun()) _lstSummary->addRow(1, \"\");\n\t\t_lstSummary->addRow(2, tr(\"STR_FRONT_ARMOR_UC\").c_str(), std::to_string(frontArmor).c_str());\n\t}\n\tif (leftArmor != 0)\n\t{\n\t\tif (gap.tryRun()) _lstSummary->addRow(1, \"\");\n\t\t_lstSummary->addRow(2, tr(\"STR_LEFT_ARMOR_UC\").c_str(), std::to_string(leftArmor).c_str());\n\t}\n\tif (rightArmor != 0)\n\t{\n\t\tif (gap.tryRun()) _lstSummary->addRow(1, \"\");\n\t\t_lstSummary->addRow(2, tr(\"STR_RIGHT_ARMOR_UC\").c_str(), std::to_string(rightArmor).c_str());\n\t}\n\tif (rearArmor != 0)\n\t{\n\t\tif (gap.tryRun()) _lstSummary->addRow(1, \"\");\n\t\t_lstSummary->addRow(2, tr(\"STR_REAR_ARMOR_UC\").c_str(), std::to_string(rearArmor).c_str());\n\t}\n\tif (underArmor != 0)\n\t{\n\t\tif (gap.tryRun()) _lstSummary->addRow(1, \"\");\n\t\t_lstSummary->addRow(2, tr(\"STR_UNDER_ARMOR_UC\").c_str(), std::to_string(underArmor).c_str());\n\t}\n\n\n\tgap.reset();\n\tif (visibilityAtDark != 0)\n\t{\n\t\tif (gap.tryRun()) _lstSummary->addRow(1, \"\");\n\t\t_lstSummary->addRow(2, tr(\"visibilityAtDark\").c_str(), std::to_string(visibilityAtDark).c_str());\n\t}\n\tif (visibilityAtDay != 0)\n\t{\n\t\tif (gap.tryRun()) _lstSummary->addRow(1, \"\");\n\t\t_lstSummary->addRow(2, tr(\"visibilityAtDay\").c_str(), std::to_string(visibilityAtDay).c_str());\n\t}\n\tif (psiVision != 0)\n\t{\n\t\tif (gap.tryRun()) _lstSummary->addRow(1, \"\");\n\t\t_lstSummary->addRow(2, tr(\"psiVision\").c_str(), std::to_string(psiVision).c_str());\n\t}\n\tif (bonusVisibilityThroughSmoke != 0)\n\t{\n\t\tif (gap.tryRun()) _lstSummary->addRow(1, \"\");\n\t\t_lstSummary->addRow(2, tr(\"heatVision\").c_str(), std::to_string(bonusVisibilityThroughSmoke).c_str());\n\t}\n\tif (bonusVisibilityThroughFire != 0)\n\t{\n\t\tif (gap.tryRun()) _lstSummary->addRow(1, \"\");\n\t\t_lstSummary->addRow(2, tr(\"visibilityThroughFire\").c_str(), std::to_string(bonusVisibilityThroughFire).c_str());\n\t}\n\n\n\tif (timeRecovery || energyRecovery || moraleRecovery || healthRecovery || stunRecovery || manaRecovery)\n\t{\n\t\t_lstSummary->addRow(1, \"\");\n\t\t_lstSummary->addRow(1, tr(\"recovery\").c_str());\n\t\tif (timeRecovery)\n\t\t\t_lstSummary->addRow(1, tr(\"time\").c_str());\n\t\tif (energyRecovery)\n\t\t\t_lstSummary->addRow(1, tr(\"energy\").c_str());\n\t\tif (moraleRecovery)\n\t\t\t_lstSummary->addRow(1, tr(\"morale\").c_str());\n\t\tif (healthRecovery)\n\t\t\t_lstSummary->addRow(1, tr(\"health\").c_str());\n\t\tif (stunRecovery)\n\t\t\t_lstSummary->addRow(1, tr(\"stun\").c_str());\n\t\tif (manaRecovery)\n\t\t\t_lstSummary->addRow(1, tr(\"mana\").c_str());\n\t}\n}\n\n/**\n *\n */\nSoldierBonusState::~SoldierBonusState()\n{\n\n}\n\n/**\n * Toggles Summary view.\n * @param action Pointer to an action.\n */\nvoid SoldierBonusState::btnSummaryClick(Action*)\n{\n\t_lstBonuses->setVisible(!_btnSummary->getPressed());\n\t_lstSummary->setVisible(_btnSummary->getPressed());\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid SoldierBonusState::btnCancelClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Shows corresponding Stats for Nerds article.\n * @param action Pointer to an action.\n */\nvoid SoldierBonusState::lstBonusesClick(Action *)\n{\n\tstd::string articleId = _bonuses[_lstBonuses->getSelectedRow()];\n\t_game->pushState(new StatsForNerdsState(UFOPAEDIA_TYPE_UNKNOWN, articleId, false, false, false));\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/SoldierBonusState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2019 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <vector>\n#include <string>\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass Base;\nclass TextButton;\nclass ToggleTextButton;\nclass Window;\nclass Text;\nclass TextList;\n\n/**\n * SoldierBonus window displays all soldier bonuses.\n */\nclass SoldierBonusState : public State\n{\nprivate:\n\tBase *_base;\n\tsize_t _soldier;\n\tstd::vector<std::string> _bonuses;\n\n\tTextButton *_btnCancel;\n\tToggleTextButton *_btnSummary;\n\tWindow *_window;\n\tText *_txtTitle, *_txtType;\n\tTextList *_lstBonuses;\n\tTextList *_lstSummary;\npublic:\n\t/// Creates the SoldierBonus state.\n\tSoldierBonusState(Base *base, size_t soldier);\n\t/// Cleans up the SoldierBonus state.\n\t~SoldierBonusState();\n\t/// Handler for clicking the Summary button.\n\tvoid btnSummaryClick(Action *action);\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action *action);\n\t/// Handler for clicking the Bonuses list.\n\tvoid lstBonusesClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/SoldierDiaryLightState.cpp",
    "content": "/*\n * Copyright 2010-2015 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"SoldierDiaryLightState.h\"\n#include <sstream>\n#include <string>\n#include \"../Engine/Game.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Savegame/Soldier.h\"\n#include \"../Savegame/SoldierDiary.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Soldier Diary Light window.\n * @param soldier Pointer to the soldier to get info from.\n */\nSoldierDiaryLightState::SoldierDiaryLightState(Soldier* soldier) : _soldier(soldier)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 240, 160, 40, 24, POPUP_BOTH);\n\t_btnOk = new TextButton(100, 16, 110, 160);\n\t_txtTitle = new Text(220, 9, 50, 36);\n\t_lstStats = new TextList(177, 96, 74, 56);\n\n\t// Set palette\n\tsetStandardPalette(\"PAL_BATTLESCAPE\");\n\n\tadd(_window, \"window\", \"soldierDiaryLight\");\n\tadd(_btnOk, \"button\", \"soldierDiaryLight\");\n\tadd(_txtTitle, \"text\", \"soldierDiaryLight\");\n\tadd(_lstStats, \"list\", \"soldierDiaryLight\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"soldierDiaryLight\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&SoldierDiaryLightState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&SoldierDiaryLightState::btnOkClick, Options::keyOk);\n\t_btnOk->onKeyboardPress((ActionHandler)&SoldierDiaryLightState::btnOkClick, Options::keyCancel);\n\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_NEUTRALIZATIONS_BY_WEAPON\"));\n\n\t_lstStats->setColumns(2, 156, 20);\n\t_lstStats->setBackground(_window);\n\t_lstStats->setDot(true);\n\n\tfor (const auto& mapItem : _soldier->getDiary()->getWeaponTotal())\n\t{\n\t\tstd::ostringstream ss;\n\t\tss << mapItem.second;\n\t\t_lstStats->addRow(2, tr(mapItem.first).c_str(), ss.str().c_str());\n\t}\n\n\t// switch to battlescape theme if called from inventory\n\tapplyBattlescapeTheme(\"soldierDiaryLight\");\n}\n\n/**\n *\n */\nSoldierDiaryLightState::~SoldierDiaryLightState()\n{\n\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid SoldierDiaryLightState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/SoldierDiaryLightState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2015 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <vector>\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass Soldier;\nclass TextButton;\nclass Window;\nclass Text;\nclass TextList;\n\n/**\n * Soldier Diary Light window that allows viewing basic data from the soldier's diary.\n */\nclass SoldierDiaryLightState : public State\n{\nprivate:\n\tSoldier* _soldier;\n\n\tTextButton *_btnOk;\n\tWindow *_window;\n\tText *_txtTitle;\n\tTextList *_lstStats;\npublic:\n\t/// Creates the Soldier Diary Light state.\n\tSoldierDiaryLightState(Soldier* soldier);\n\t/// Cleans up the Soldier Diary Light state.\n\t~SoldierDiaryLightState();\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/SoldierDiaryMissionState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"SoldierDiaryMissionState.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Soldier.h\"\n#include \"../Savegame/SoldierDiary.h\"\n#include \"../Savegame/MissionStatistics.h\"\n#include \"../Savegame/BattleUnitStatistics.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Soldier Diary Mission window.\n * @param soldier Pointer to the selected soldier.\n * @param rowEntry number to get mission info from.\n */\nSoldierDiaryMissionState::SoldierDiaryMissionState(Soldier *soldier, int rowEntry) : _soldier(soldier), _rowEntry(rowEntry)\n{\n\t_screen = false;\n\n\t// Create object\n\t_window = new Window(this, 300, 128, 10, 36, POPUP_HORIZONTAL);\n\t_btnOk = new TextButton(240, 16, 40, 140);\n\t_btnPrev = new TextButton(28, 14, 18, 44);\n\t_btnNext = new TextButton(28, 14, 274, 44);\n\t_txtTitle = new Text(262, 9, 29, 44);\n\t_txtUFO = new Text(262, 9, 29, 52);\n\t_txtScore = new Text(180, 9, 29, 68);\n\t_txtKills = new Text(120, 9, 169, 68);\n\t_txtLocation = new Text(180, 9, 29, 76);\n\t_txtRace = new Text(120, 9, 169, 76);\n\t_txtDaylight = new Text(120, 9, 169, 84);\n\t_txtDaysWounded = new Text(180, 9, 29, 84);\n\t_txtNoRecord = new Text(240, 9, 29, 100);\n\t_lstKills = new TextList(270, 32, 20, 100);\n\n\t// Set palette\n\tsetInterface(\"soldierDiaryMission\");\n\n\tadd(_window, \"window\", \"soldierDiaryMission\");\n\tadd(_btnOk, \"button\", \"soldierDiaryMission\");\n\tadd(_btnPrev, \"button\", \"soldierDiaryMission\");\n\tadd(_btnNext, \"button\", \"soldierDiaryMission\");\n\tadd(_txtTitle, \"text\", \"soldierDiaryMission\");\n\tadd(_txtUFO, \"text\", \"soldierDiaryMission\");\n\tadd(_txtScore, \"text\", \"soldierDiaryMission\");\n\tadd(_txtKills, \"text\", \"soldierDiaryMission\");\n\tadd(_txtLocation, \"text\", \"soldierDiaryMission\");\n\tadd(_txtRace, \"text\", \"soldierDiaryMission\");\n\tadd(_txtDaylight, \"text\", \"soldierDiaryMission\");\n\tadd(_txtDaysWounded, \"text\", \"soldierDiaryMission\");\n\tadd(_txtNoRecord, \"text\", \"soldierDiaryMission\");\n\tadd(_lstKills, \"list\", \"soldierDiaryMission\");\n\n\tcenterAllSurfaces();\n\n\t// Set up object\n\tsetWindowBackground(_window, \"soldierDiaryMission\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&SoldierDiaryMissionState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&SoldierDiaryMissionState::btnOkClick, Options::keyCancel);\n\n\t_btnPrev->setText(\"<<\");\n\t_btnPrev->onMouseClick((ActionHandler)&SoldierDiaryMissionState::btnPrevClick);\n\t_btnPrev->onKeyboardPress((ActionHandler)&SoldierDiaryMissionState::btnPrevClick, Options::keyBattleNextUnit);\n\n\t_btnNext->setText(\">>\");\n\t_btnNext->onMouseClick((ActionHandler)&SoldierDiaryMissionState::btnNextClick);\n\t_btnNext->onKeyboardPress((ActionHandler)&SoldierDiaryMissionState::btnNextClick, Options::keyBattlePrevUnit);\n\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\n\t_txtUFO->setAlign(ALIGN_CENTER);\n\n\t_lstKills->setColumns(3, 60, 110, 100);\n}\n\n/**\n *\n */\nSoldierDiaryMissionState::~SoldierDiaryMissionState()\n{\n\n}\n\n/**\n *  Clears all the variables and reinitializes the stats for the mission.\n *\n */\nvoid SoldierDiaryMissionState::init()\n{\n\tState::init();\n\tif (_soldier->getDiary()->getMissionIdList().empty())\n\t{\n\t\t_game->popState();\n\t\treturn;\n\t}\n\tstd::vector<MissionStatistics*> *missionStatistics = _game->getSavedGame()->getMissionStatistics();\n\tunsigned int missionId = _soldier->getDiary()->getMissionIdList().at(_rowEntry);\n\tif (missionId > missionStatistics->size())\n\t{\n\t\tmissionId = 0;\n\t}\n\tMissionStatistics *ms = missionStatistics->at(missionId);\n\n\tint daysWounded = 0;\n\tauto injuryIt = ms->injuryList.find(_soldier->getId());\n\tif (injuryIt != ms->injuryList.end())\n\t{\n\t\tdaysWounded = (*injuryIt).second;\n\t}\n\n\t_lstKills->clearList();\n\t_txtTitle->setText(tr(ms->type));\n\tif (ms->isUfoMission())\n\t{\n\t\t_txtUFO->setText(tr(ms->ufo));\n\t}\n\t_txtUFO->setVisible(ms->isUfoMission());\n\t_txtScore->setText(tr(\"STR_SCORE_VALUE\").arg(ms->score));\n\t_txtLocation->setText(tr(\"STR_LOCATION\").arg(tr(ms->getLocationString())));\n\t_txtRace->setText(tr(\"STR_RACE_TYPE\").arg(tr(ms->alienRace)));\n\t_txtRace->setVisible(ms->alienRace != \"STR_UNKNOWN\");\n\t_txtDaylight->setText(tr(\"STR_DAYLIGHT_TYPE\").arg(tr(ms->getDaylightString(_game->getMod()))));\n\t_txtDaysWounded->setText(tr(\"STR_DAYS_WOUNDED\").arg(daysWounded));\n\t_txtDaysWounded->setVisible(daysWounded != 0);\n\n\tint kills = 0;\n\tbool stunOrKill = false;\n\n\tfor (const auto* battleUnitKills : _soldier->getDiary()->getKills())\n\t{\n\t\tif ((unsigned int)battleUnitKills->mission != missionId) continue;\n\n\t\tswitch (battleUnitKills->status)\n\t\t{\n\t\tcase STATUS_DEAD:\n\t\t\tkills++;\n\t\t//Fall-through\n\t\tcase STATUS_UNCONSCIOUS:\n\t\tcase STATUS_PANICKING:\n\t\tcase STATUS_TURNING:\n\t\t\tstunOrKill = true;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\n\t\t_lstKills->addRow(3, tr(battleUnitKills->getKillStatusString()).c_str(),\n\t\t\t\t\t\t\t battleUnitKills->getUnitName(_game->getLanguage()).c_str(),\n\t\t\t\t\t\t\t tr(battleUnitKills->weapon).c_str());\n\t}\n\n\t_txtNoRecord->setAlign(ALIGN_CENTER);\n\t_txtNoRecord->setText(tr(\"STR_NO_RECORD\"));\n\t_txtNoRecord->setVisible(!stunOrKill);\n\n\t_txtKills->setText(tr(\"STR_KILLS\").arg(kills));\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid SoldierDiaryMissionState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Goes to the previous mission.\n * @param action Pointer to an action.\n */\nvoid SoldierDiaryMissionState::btnPrevClick(Action *)\n{\n\tif (_rowEntry == 0)\n\t\t_rowEntry = _soldier->getDiary()->getMissionTotal() - 1;\n\telse\n\t\t_rowEntry--;\n\tinit();\n}\n\n/**\n * Goes to the next mission.\n * @param action Pointer to an action.\n */\nvoid SoldierDiaryMissionState::btnNextClick(Action *)\n{\n\t_rowEntry++;\n\tif (_rowEntry >= _soldier->getDiary()->getMissionTotal())\n\t\t_rowEntry = 0;\n\tinit();\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/SoldierDiaryMissionState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass TextList;\nclass Soldier;\n\n/**\n * Diary window that show\n * mission details for a soldier.\n */\nclass SoldierDiaryMissionState : public State\n{\nprivate:\n\tSoldier *_soldier;\n\n\tTextButton *_btnOk, *_btnPrev, *_btnNext;\n\tWindow *_window;\n\tText *_txtTitle, *_txtUFO, *_txtScore, *_txtKills, *_txtLocation, *_txtRace, *_txtDaylight, *_txtDaysWounded;\n\tText *_txtNoRecord;\n\tTextList *_lstKills;\n\n\tint _rowEntry;\npublic:\n\t/// Creates the Soldier Diary Mission state.\n\tSoldierDiaryMissionState(Soldier *soldier, int rowEntry);\n\t/// Cleans up the Soldier Diary Mission state.\n\t~SoldierDiaryMissionState();\n\t/// Handler for clicking the Cancel button.\n\tvoid btnOkClick(Action *action);\n\t/// Updates the mission info.\n\tvoid init() override;\n\t/// Handler for clicking the Previous button.\n\tvoid btnPrevClick(Action *action);\n\t/// Handler for clicking the Next button.\n\tvoid btnNextClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/SoldierDiaryOverviewState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"SoldierDiaryOverviewState.h\"\n#include \"SoldierDiaryPerformanceState.h\"\n#include \"SoldierDiaryMissionState.h\"\n#include \"SoldierInfoState.h\"\n#include <sstream>\n#include \"../Mod/Mod.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/Soldier.h\"\n#include \"../Savegame/SoldierDeath.h\"\n#include \"../Savegame/SoldierDiary.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/MissionStatistics.h\"\n#include \"../Savegame/BattleUnitStatistics.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Soldier Diary screen.\n * @param base Pointer to the base to get info from.\n * @param soldierId ID of the selected soldier.\n * @param soldierInfoState Pointer to the Soldier Info screen.\n */\nSoldierDiaryOverviewState::SoldierDiaryOverviewState(Base *base, size_t soldierId, SoldierInfoState *soldierInfoState) :\n\t_base(base), _soldierId(soldierId), _soldierInfoState(soldierInfoState), _doNotReset(false)\n{\n\tif (_base == 0)\n\t{\n\t\t_list = _game->getSavedGame()->getDeadSoldiers();\n\t}\n\telse\n\t{\n\t\t_list = _base->getSoldiers();\n\t}\n\n\t// Create objects\n\t_window = new Window(this, 320, 200, 0, 0);\n\t_btnKills = new TextButton(70, 16, 8, 176);\n\t_btnMissions = new TextButton(70, 16, 86, 176);\n\t_btnCommendations = new TextButton(70, 16, 164, 176);\n\t_btnOk = new TextButton(70, 16, 242, 176);\n\t_btnPrev = new TextButton(28, 14, 8, 8);\n\t_btnNext = new TextButton(28, 14, 284, 8);\n\t_txtTitle = new Text(310, 16, 5, 8);\n\tif (!_base)\n\t{\n\t\t_txtDeathTitle = new Text(150, 9, 16, 36);\n\t\t_txtDeathDate = new Text(90, 9, 218, 36);\n\t\t_txtDeathInfo = new Text(292, 9, 16, 44);\n\t}\n\tint offset = (!_base) ? 24 : 0;\n\t_txtMission = new Text(114, 9, 16, 36 + offset);\n\t_txtRating = new Text(102, 9, 120, 36 + offset);\n\t_txtDate = new Text(90, 9, 218, 36 + offset);\n\t_lstDiary = new TextList(288, 120 - offset, 8, 44 + offset);\n\n\t// Set palette\n\tsetInterface(\"soldierDiary\");\n\n\tadd(_window, \"window\", \"soldierDiary\");\n\tadd(_btnOk, \"button\", \"soldierDiary\");\n\tadd(_btnKills, \"button\", \"soldierDiary\");\n\tadd(_btnMissions, \"button\", \"soldierDiary\");\n\tadd(_btnCommendations, \"button\", \"soldierDiary\");\n\tadd(_btnPrev, \"button\", \"soldierDiary\");\n\tadd(_btnNext, \"button\", \"soldierDiary\");\n\tadd(_txtTitle, \"text1\", \"soldierDiary\");\n\tif (!_base)\n\t{\n\t\tadd(_txtDeathTitle, \"text2\", \"soldierDiary\");\n\t\tadd(_txtDeathInfo, \"text3\", \"soldierDiary\");\n\t\tadd(_txtDeathDate, \"text3\", \"soldierDiary\");\n\t}\n\tadd(_txtMission, \"text2\", \"soldierDiary\");\n\tadd(_txtRating, \"text2\", \"soldierDiary\");\n\tadd(_txtDate, \"text2\", \"soldierDiary\");\n\tadd(_lstDiary, \"list\", \"soldierDiary\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"soldierDiary\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&SoldierDiaryOverviewState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&SoldierDiaryOverviewState::btnOkClick, Options::keyCancel);\n\n\t_btnKills->setText(tr(\"STR_COMBAT\"));\n\t_btnKills->onMouseClick((ActionHandler)&SoldierDiaryOverviewState::btnKillsClick);\n\n\t_btnMissions->setText(tr(\"STR_PERFORMANCE\"));\n\t_btnMissions->onMouseClick((ActionHandler)&SoldierDiaryOverviewState::btnMissionsClick);\n\n\t_btnCommendations->setText(tr(\"STR_AWARDS\"));\n\t_btnCommendations->onMouseClick((ActionHandler)&SoldierDiaryOverviewState::btnCommendationsClick);\n\t_btnCommendations->setVisible(!_game->getMod()->getCommendationsList().empty());\n\n\t_btnPrev->setText(\"<<\");\n\tif (_base == 0)\n\t{\n\t\t_btnPrev->onMouseClick((ActionHandler)&SoldierDiaryOverviewState::btnNextClick);\n\t\t_btnPrev->onKeyboardPress((ActionHandler)&SoldierDiaryOverviewState::btnNextClick, Options::keyBattlePrevUnit);\n\t}\n\telse\n\t{\n\t\t_btnPrev->onMouseClick((ActionHandler)&SoldierDiaryOverviewState::btnPrevClick);\n\t\t_btnPrev->onKeyboardPress((ActionHandler)&SoldierDiaryOverviewState::btnPrevClick, Options::keyBattlePrevUnit);\n\t}\n\n\t_btnNext->setText(\">>\");\n\tif (_base == 0)\n\t{\n\t\t_btnNext->onMouseClick((ActionHandler)&SoldierDiaryOverviewState::btnPrevClick);\n\t\t_btnNext->onKeyboardPress((ActionHandler)&SoldierDiaryOverviewState::btnPrevClick, Options::keyBattleNextUnit);\n\t}\n\telse\n\t{\n\t\t_btnNext->onMouseClick((ActionHandler)&SoldierDiaryOverviewState::btnNextClick);\n\t\t_btnNext->onKeyboardPress((ActionHandler)&SoldierDiaryOverviewState::btnNextClick, Options::keyBattleNextUnit);\n\t}\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t// Text is decided in init()\n\n\t_txtMission->setText(tr(\"STR_MISSION\"));\n\n\t_txtRating->setText(tr(\"STR_RATING_UC\"));\n\n\t_txtDate->setText(tr(\"STR_DATE_UC\"));\n\n\t_lstDiary->setColumns(5, 104, 98, 30, 25, 35);\n\t_lstDiary->setSelectable(true);\n\t_lstDiary->setBackground(_window);\n\t_lstDiary->setMargin(8);\n\t_lstDiary->onMouseClick((ActionHandler)&SoldierDiaryOverviewState::lstDiaryInfoClick);\n}\n\n/**\n *\n */\nSoldierDiaryOverviewState::~SoldierDiaryOverviewState()\n{\n\n}\n\n/**\n *  Clears all the variables and reinitializes the list of medals for the soldier.\n *\n */\nvoid SoldierDiaryOverviewState::init()\n{\n\tState::init();\n\n\t// coming back from SoldierDiaryMissionState\n\tif (_doNotReset)\n\t{\n\t\t_doNotReset = false;\n\t\treturn;\n\t}\n\n\tif (_list->empty())\n\t{\n\t\t_game->popState();\n\t\treturn;\n\t}\n\tif (_soldierId >= _list->size())\n\t{\n\t\t_soldierId = 0;\n\t}\n\t_soldier = _list->at(_soldierId);\n\t_txtTitle->setText(_soldier->getName());\n\n\tif (!_base && _soldier->getDeath())\n\t{\n\t\tstd::string deathTitleText, deathInfoText;\n\t\tconst BattleUnitKills *cause = _soldier->getDeath()->getCause();\n\t\tif (cause)\n\t\t{\n\t\t\tdeathTitleText = _game->getLanguage()->getString(\"STR_KILLED_IN_ACTION\", _soldier->getGender());\n\t\t\tdeathInfoText = tr(\"STR_KILLER_AND_WEAPON\")\n\t\t\t\t.arg(cause->getUnitName(_game->getLanguage()))\n\t\t\t\t.arg(tr(cause->weapon));\n\t\t}\n\t\telse\n\t\t{\n\t\t\tdeathTitleText = _game->getLanguage()->getString(\"STR_MISSING_IN_ACTION\", _soldier->getGender());\n\t\t}\n\n\t\tstd::ostringstream deathDateText;\n\t\tconst GameTime *t = _soldier->getDeath()->getTime();\n\t\tdeathDateText << t->getDayString(_game->getLanguage()) << \" \" << _game->getLanguage()->getString(t->getMonthString()) << \" \" << t->getYear();\n\n\t\t_txtDeathTitle->setText(deathTitleText);\n\t\t_txtDeathDate->setText(deathDateText.str());\n\t\t_txtDeathInfo->setText(deathInfoText);\n\t}\n\n\t_lstDiary->clearList();\n\n\tunsigned int row = 0;\n\tfor (const auto* missionStats : *_game->getSavedGame()->getMissionStatistics())\n\t{\n\t\tint missionId = missionStats->id;\n\t\tbool wasOnMission = false;\n\n\t\t// See if this mission is part of the soldier's vector of missions\n\t\tfor (const int& mId : _soldier->getDiary()->getMissionIdList())\n\t\t{\n\t\t\tif (missionId == mId)\n\t\t\t{\n\t\t\t\twasOnMission = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (!wasOnMission)\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\n\t\tstd::ostringstream ss;\n\t\tss << missionStats->time.getYear();\n\n\t\t_lstDiary->addRow(5, missionStats->getMissionName(_game->getLanguage()).c_str(),\n\t\t\t\t\t\t\t missionStats->getRatingString(_game->getLanguage()).c_str(),\n\t\t\t\t\t\t\t missionStats->time.getDayString(_game->getLanguage()).c_str(),\n\t\t\t\t\t\t\t tr(missionStats->time.getMonthString()).c_str(),\n\t\t\t\t\t\t\t ss.str().c_str());\n\t\trow++;\n\t}\n\tif (row > 0 && _lstDiary->getScroll() >= row)\n\t{\n\t\t_lstDiary->scrollTo(0);\n\t}\n}\n\n/**\n * Set the soldier's Id.\n */\nvoid SoldierDiaryOverviewState::setSoldierId(size_t soldier)\n{\n\t_soldierId = soldier;\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid SoldierDiaryOverviewState::btnOkClick(Action *)\n{\n\t_soldierInfoState->setSoldierId(_soldierId);\n\t_game->popState();\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid SoldierDiaryOverviewState::btnKillsClick(Action *)\n{\n\t_game->pushState(new SoldierDiaryPerformanceState(_base, _soldierId, this, DIARY_KILLS));\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid SoldierDiaryOverviewState::btnMissionsClick(Action *)\n{\n\t_game->pushState(new SoldierDiaryPerformanceState(_base, _soldierId, this, DIARY_MISSIONS));\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid SoldierDiaryOverviewState::btnCommendationsClick(Action *)\n{\n\t_game->pushState(new SoldierDiaryPerformanceState(_base, _soldierId, this, DIARY_COMMENDATIONS));\n}\n\n\n/**\n * Goes to the previous soldier.\n * @param action Pointer to an action.\n */\nvoid SoldierDiaryOverviewState::btnPrevClick(Action *)\n{\n\tif (_soldierId == 0)\n\t\t_soldierId = _list->size() - 1;\n\telse\n\t\t_soldierId--;\n\tinit();\n}\n\n/**\n * Goes to the next soldier.\n * @param action Pointer to an action.\n */\nvoid SoldierDiaryOverviewState::btnNextClick(Action *)\n{\n\t_soldierId++;\n\tif (_soldierId >= _list->size())\n\t\t_soldierId = 0;\n\tinit();\n}\n\n/**\n * Shows the selected soldier's info.\n * @param action Pointer to an action.\n */\nvoid SoldierDiaryOverviewState::lstDiaryInfoClick(Action *)\n{\n\tint absoluteRowEntry = _lstDiary->getSelectedRow();\n\t_doNotReset = true;\n\t_game->pushState(new SoldierDiaryMissionState(_soldier, absoluteRowEntry));\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/SoldierDiaryOverviewState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include <vector>\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass TextList;\nclass Base;\nclass SoldierInfoState;\nclass Soldier;\n\n/**\n * Diary screen that shows all the\n * missions a soldier has.\n */\nclass SoldierDiaryOverviewState : public State\n{\nprivate:\n\tBase *_base;\n\tsize_t _soldierId;\n\tSoldierInfoState *_soldierInfoState;\n\tSoldier *_soldier;\n\tstd::vector<Soldier*> *_list;\n\n\tTextButton *_btnOk, *_btnPrev, *_btnNext, *_btnKills, *_btnMissions, *_btnCommendations;\n\tWindow *_window;\n\tText *_txtTitle, *_txtMission, *_txtRating, *_txtDate, *_txtDeathTitle, *_txtDeathInfo, *_txtDeathDate;\n\tTextList *_lstDiary;\n\tbool _doNotReset;\n\npublic:\n\t/// Creates the Soldier Diary state.\n\tSoldierDiaryOverviewState(Base *base, size_t soldierId, SoldierInfoState *soldierInfoState);\n\t/// Cleans up the Soldier Diary state.\n\t~SoldierDiaryOverviewState();\n\t/// Updates the soldier info.\n\tvoid init() override;\n\t/// Set the soldier's Id.\n\tvoid setSoldierId(size_t soldierId);\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the Previous button.\n\tvoid btnPrevClick(Action *action);\n\t/// Handler for clicking the Next button.\n\tvoid btnNextClick(Action *action);\n\t/// Handler for clicking the Kills button.\n\tvoid btnKillsClick(Action *action);\n\t/// Handler for clicking the Missions button.\n\tvoid btnMissionsClick(Action *action);\n\t/// Handler for clicking the Commendations button.\n\tvoid btnCommendationsClick(Action *action);\n\t/// Handler for clicking on mission list.\n\tvoid lstDiaryInfoClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/SoldierDiaryPerformanceState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"SoldierDiaryPerformanceState.h\"\n#include \"SoldierDiaryOverviewState.h\"\n#include <sstream>\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/SurfaceSet.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/Soldier.h\"\n#include \"../Savegame/SoldierDiary.h\"\n#include \"../Mod/RuleCommendations.h\"\n#include \"../Engine/Action.h\"\n#include \"../Ufopaedia/Ufopaedia.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Soldier Diary Totals screen.\n * @param base Pointer to the base to get info from.\n * @param soldier ID of the selected soldier.\n * @param soldierInfoState Pointer to the Soldier Diary screen.\n * @param display Type of totals to display.\n */\nSoldierDiaryPerformanceState::SoldierDiaryPerformanceState(Base *base, size_t soldierId, SoldierDiaryOverviewState *soldierDiaryOverviewState, SoldierDiaryDisplay display) :\n\t_base(base), _soldierId(soldierId), _soldierDiaryOverviewState(soldierDiaryOverviewState), _display(display), _lastScrollPos(0), _doNotReset(false)\n{\n\tif (_base == 0)\n\t{\n\t\t_list = _game->getSavedGame()->getDeadSoldiers();\n\t}\n\telse\n\t{\n\t\t_list = _base->getSoldiers();\n\t}\n\n\t// Create objects\n\t_window = new Window(this, 320, 200, 0, 0);\n\t_btnPrev = new TextButton(28, 14, 8, 8);\n\t_btnNext = new TextButton(28, 14, 284, 8);\n\t_btnKills = new TextButton(70, 16, 8, 176);\n\t_btnMissions = new TextButton(70, 16, 86, 176);\n\t_btnCommendations = new TextButton(70, 16, 164, 176);\n\t_btnOk = new TextButton(70, 16, 242, 176);\n\t_txtTitle = new Text(310, 16, 5, 8);\n\t_lstPerformance = new TextList(288, 128, 8, 28);\n\t_lstKillTotals = new TextList(302, 9, 8, 164);\n\t_lstMissionTotals = new TextList(302, 9, 8, 164);\n\t// Commendation stat\n\t_txtMedalName = new Text(120, 18, 16, 36);\n\t_txtMedalLevel = new Text(120, 18, 186, 36);\n\t_txtMedalInfo = new Text(280, 32, 20, 135);\n\t_lstCommendations = new TextList(240, 80, 48, 52);\n\tfor (int i = 0; i != 10; ++i)\n\t{\n\t\t_commendations.push_back(new Surface(31, 8, 16, 52 + 8*i));\n\t\t_commendationDecorations.push_back(new Surface(31, 8, 16, 52 + 8*i));\n\t}\n\n\t// Set palette\n\tsetInterface(\"soldierDiaryPerformance\");\n\n\tadd(_window, \"window\", \"soldierDiaryPerformance\");\n\tadd(_btnOk, \"button\", \"soldierDiaryPerformance\");\n\tadd(_btnKills, \"button\", \"soldierDiaryPerformance\");\n\tadd(_btnMissions, \"button\", \"soldierDiaryPerformance\");\n\tadd(_btnCommendations, \"button\", \"soldierDiaryPerformance\");\n\tadd(_btnPrev, \"button\", \"soldierDiaryPerformance\");\n\tadd(_btnNext, \"button\", \"soldierDiaryPerformance\");\n\tadd(_txtTitle, \"text1\", \"soldierDiaryPerformance\");\n\tadd(_lstPerformance, \"list\", \"soldierDiaryPerformance\");\n\tadd(_lstKillTotals, \"text2\", \"soldierDiaryPerformance\");\n\tadd(_lstMissionTotals, \"text2\", \"soldierDiaryPerformance\");\n\tadd(_txtMedalName, \"text2\", \"soldierDiaryPerformance\");\n\tadd(_txtMedalLevel, \"text2\", \"soldierDiaryPerformance\");\n\tadd(_txtMedalInfo, \"text2\", \"soldierDiaryPerformance\");\n\tadd(_lstCommendations, \"list\", \"soldierDiaryPerformance\");\n\tfor (int i = 0; i != 10; ++i)\n\t{\n\t\tadd(_commendations[i]);\n\t\tadd(_commendationDecorations[i]);\n\t}\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"soldierDiaryPerformance\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&SoldierDiaryPerformanceState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&SoldierDiaryPerformanceState::btnOkClick, Options::keyCancel);\n\n\t_btnKills->setText(tr(\"STR_COMBAT\"));\n\t_btnKills->onMouseClick((ActionHandler)&SoldierDiaryPerformanceState::btnKillsToggle);\n\n\t_btnMissions->setText(tr(\"STR_PERFORMANCE\"));\n\t_btnMissions->onMouseClick((ActionHandler)&SoldierDiaryPerformanceState::btnMissionsToggle);\n\n\t_btnCommendations->setText(tr(\"STR_AWARDS\"));\n\t_btnCommendations->onMouseClick((ActionHandler)&SoldierDiaryPerformanceState::btnCommendationsToggle);\n\n\t_btnPrev->setText(\"<<\");\n\tif (_base == 0)\n\t{\n\t\t_btnPrev->onMouseClick((ActionHandler)&SoldierDiaryPerformanceState::btnNextClick);\n\t\t_btnPrev->onKeyboardPress((ActionHandler)&SoldierDiaryPerformanceState::btnNextClick, Options::keyBattlePrevUnit);\n\t}\n\telse\n\t{\n\t\t_btnPrev->onMouseClick((ActionHandler)&SoldierDiaryPerformanceState::btnPrevClick);\n\t\t_btnPrev->onKeyboardPress((ActionHandler)&SoldierDiaryPerformanceState::btnPrevClick, Options::keyBattlePrevUnit);\n\t}\n\n\t_btnNext->setText(\">>\");\n\tif (_base == 0)\n\t{\n\t\t_btnNext->onMouseClick((ActionHandler)&SoldierDiaryPerformanceState::btnPrevClick);\n\t\t_btnNext->onKeyboardPress((ActionHandler)&SoldierDiaryPerformanceState::btnPrevClick, Options::keyBattleNextUnit);\n\t}\n\telse\n\t{\n\t\t_btnNext->onMouseClick((ActionHandler)&SoldierDiaryPerformanceState::btnNextClick);\n\t\t_btnNext->onKeyboardPress((ActionHandler)&SoldierDiaryPerformanceState::btnNextClick, Options::keyBattleNextUnit);\n\t}\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\n\t// Text is decided in init()\n\t_lstPerformance->setColumns(2, 273, 15);\n\t_lstPerformance->setDot(true);\n\n\t_lstKillTotals->setColumns(4, 72, 72, 72, 86);\n\n\t_lstMissionTotals->setColumns(4, 72, 72, 72, 86);\n\n\t_txtMedalName->setText(tr(\"STR_MEDAL_NAME\"));\n\n\t_txtMedalLevel->setText(tr(\"STR_MEDAL_DECOR_LEVEL\"));\n\n\t_txtMedalInfo->setWordWrap(true);\n\n\t_lstCommendations->setColumns(2, 138, 100);\n\t_lstCommendations->setSelectable(true);\n\t_lstCommendations->setBackground(_window);\n\t_lstCommendations->onMouseOver((ActionHandler)&SoldierDiaryPerformanceState::lstInfoMouseOver);\n\t_lstCommendations->onMouseOut((ActionHandler)&SoldierDiaryPerformanceState::lstInfoMouseOut);\n\t_lstCommendations->onMousePress((ActionHandler)&SoldierDiaryPerformanceState::handle);\n\t_lstCommendations->onMouseClick((ActionHandler)&SoldierDiaryPerformanceState::lstInfoMouseClick);\n\n\tif (_display == DIARY_KILLS)\n\t{\n\t\t_group = _btnKills;\n\t}\n\telse if (_display == DIARY_MISSIONS)\n\t{\n\t\t_group = _btnMissions;\n\t}\n\telse if (_display == DIARY_COMMENDATIONS)\n\t{\n\t\t_group = _btnCommendations;\n\t}\n\t_btnKills->setGroup(&_group);\n\t_btnMissions->setGroup(&_group);\n\t_btnCommendations->setGroup(&_group);\n}\n\n/**\n *\n */\nSoldierDiaryPerformanceState::~SoldierDiaryPerformanceState()\n{\n\n}\n\n/**\n *  Clears all the variables and reinitializes the list of kills or missions for the soldier.\n */\nvoid SoldierDiaryPerformanceState::init()\n{\n\tState::init();\n\n\t// coming back from Ufopedia\n\tif (_doNotReset)\n\t{\n\t\t_doNotReset = false;\n\t\treturn;\n\t}\n\n\t// Clear sprites\n\tfor (int i = 0; i != 10; ++i)\n\t{\n\t\t_commendations[i]->clear();\n\t\t_commendationDecorations[i]->clear();\n\t}\n\t// Reset scroll depth for lists\n\t_lstPerformance->scrollTo(0);\n\t_lstKillTotals->scrollTo(0);\n\t_lstMissionTotals->scrollTo(0);\n\t_lstCommendations->scrollTo(0);\n\t_lastScrollPos = 0;\n\t_lstPerformance->setVisible(_display != DIARY_COMMENDATIONS);\n\t// Set visibility for kills\n\t_lstKillTotals->setVisible(_display == DIARY_KILLS);\n\t// Set visibility for missions\n\t_lstMissionTotals->setVisible(_display == DIARY_MISSIONS);\n\t// Set visibility for commendations\n\t_txtMedalName->setVisible(_display == DIARY_COMMENDATIONS);\n\t_txtMedalLevel->setVisible(_display == DIARY_COMMENDATIONS);\n\t_txtMedalInfo->setVisible(_display == DIARY_COMMENDATIONS);\n\t_lstCommendations->setVisible(_display == DIARY_COMMENDATIONS);\n\t_btnCommendations->setVisible(!_game->getMod()->getCommendationsList().empty());\n\n\tif (_list->empty())\n\t{\n\t\t_game->popState();\n\t\treturn;\n\t}\n\tif (_soldierId >= _list->size())\n\t{\n\t\t_soldierId = 0;\n\t}\n\t_soldier = _list->at(_soldierId);\n\t_lstKillTotals->clearList();\n\t_lstMissionTotals->clearList();\n\t_commendationsListEntry.clear();\n\t_commendationsNames.clear();\n\t_sortedCommendations.clear();\n\t_txtTitle->setText(_soldier->getName());\n\t_lstPerformance->clearList();\n\t_lstCommendations->clearList();\n\tif (_display == DIARY_KILLS)\n\t{\n\t\tstd::map<std::string, int> mapArray[] = {\n\t\t\t_soldier->getDiary()->getWeaponTotal(),\n\t\t\t_soldier->getDiary()->getAlienRaceTotal(),\n\t\t\t_soldier->getDiary()->getAlienRankTotal()\n\t\t};\n\t\tstd::string titleArray[] = { \"STR_NEUTRALIZATIONS_BY_WEAPON\", \"STR_NEUTRALIZATIONS_BY_RACE\", \"STR_NEUTRALIZATIONS_BY_RANK\" };\n\n\t\tfor (int i = 0; i != 3; ++i)\n\t\t{\n\t\t\t_lstPerformance->addRow(1, tr(titleArray[i]).c_str());\n\t\t\t_lstPerformance->setRowColor(_lstPerformance->getLastRowIndex(), _lstPerformance->getSecondaryColor());\n\t\t\tfor (const auto& mapItem : mapArray[i])\n\t\t\t{\n\t\t\t\tstd::ostringstream ss;\n\t\t\t\tss << mapItem.second;\n\t\t\t\t_lstPerformance->addRow(2, tr(mapItem.first).c_str(), ss.str().c_str());\n\t\t\t}\n\t\t\tif (i != 2)\n\t\t\t{\n\t\t\t\t_lstPerformance->addRow(1, \"\");\n\t\t\t}\n\t\t}\n\n\t\tif (_soldier->getCurrentStats()->psiSkill > 0 || (Options::psiStrengthEval && _game->getSavedGame()->isResearched(_game->getMod()->getPsiRequirements())))\n\t\t{\n\t\t\t_lstKillTotals->addRow(4, tr(\"STR_KILLS\").arg(_soldier->getDiary()->getKillTotal()).c_str(),\n\t\t\t\t\t\t\t\t\t\ttr(\"STR_STUNS\").arg(_soldier->getDiary()->getStunTotal()).c_str(),\n\t\t\t\t\t\t\t\t\t\ttr(\"STR_DIARY_ACCURACY\").arg(_soldier->getDiary()->getAccuracy()).c_str(),\n\t\t\t\t\t\t\t\t\t\ttr(\"STR_MINDCONTROLS\").arg(_soldier->getDiary()->getControlTotal()).c_str());\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_lstKillTotals->addRow(3, tr(\"STR_KILLS\").arg(_soldier->getDiary()->getKillTotal()).c_str(),\n\t\t\t\t\t\t\t\t\t\ttr(\"STR_STUNS\").arg(_soldier->getDiary()->getStunTotal()).c_str(),\n\t\t\t\t\t\t\t\t\t\ttr(\"STR_DIARY_ACCURACY\").arg(_soldier->getDiary()->getAccuracy()).c_str());\n\t\t}\n\n\t}\n\telse if (_display == DIARY_MISSIONS)\n\t{\n\t\tstd::map<std::string, int> mapArray[] = {\n\t\t\t_soldier->getDiary()->getRegionTotal(_game->getSavedGame()->getMissionStatistics()),\n\t\t\t_soldier->getDiary()->getTypeTotal(_game->getSavedGame()->getMissionStatistics()),\n\t\t\t_soldier->getDiary()->getUFOTotal(_game->getSavedGame()->getMissionStatistics())\n\t\t};\n\t\tstd::string titleArray[] = { \"STR_MISSIONS_BY_LOCATION\", \"STR_MISSIONS_BY_TYPE\", \"STR_MISSIONS_BY_UFO\" };\n\n\t\tfor (int i = 0; i != 3; ++i)\n\t\t{\n\t\t\t_lstPerformance->addRow(1, tr(titleArray[i]).c_str());\n\t\t\t_lstPerformance->setRowColor(_lstPerformance->getLastRowIndex(), _lstPerformance->getSecondaryColor());\n\t\t\tfor (const auto& mapItem : mapArray[i])\n\t\t\t{\n\t\t\t\tif (mapItem.first == \"NO_UFO\") continue;\n\t\t\t\tstd::ostringstream ss;\n\t\t\t\tss << mapItem.second;\n\t\t\t\t_lstPerformance->addRow(2, tr(mapItem.first).c_str(), ss.str().c_str());\n\t\t\t}\n\t\t\tif (i != 2)\n\t\t\t{\n\t\t\t\t_lstPerformance->addRow(1, \"\");\n\t\t\t}\n\t\t}\n\n\t\t_lstMissionTotals->addRow(4, tr(\"STR_MISSIONS\").arg(_soldier->getDiary()->getMissionTotal()).c_str(),\n\t\t\t\t\t\t\t\t\ttr(\"STR_WINS\").arg(_soldier->getDiary()->getWinTotal(_game->getSavedGame()->getMissionStatistics())).c_str(),\n\t\t\t\t\t\t\t\t\ttr(\"STR_SCORE_VALUE\").arg(_soldier->getDiary()->getScoreTotal(_game->getSavedGame()->getMissionStatistics())).c_str(),\n\t\t\t\t\t\t\t\t\ttr(\"STR_DAYS_WOUNDED\").arg(_soldier->getDiary()->getDaysWoundedTotal()).c_str());\n\t}\n\telse if (_display == DIARY_COMMENDATIONS && !_game->getMod()->getCommendationsList().empty())\n\t{\n\t\t// pre-calc translations\n\t\tfor (auto* sc : *_soldier->getDiary()->getSoldierCommendations())\n\t\t{\n\t\t\tif (sc->getNoun() != \"noNoun\")\n\t\t\t{\n\t\t\t\tstd::string tmp = tr(sc->getType()).arg(tr(sc->getNoun()));\n\t\t\t\t_sortedCommendations.push_back(std::make_pair(tmp, sc));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tstd::string tmp = tr(sc->getType());\n\t\t\t\t_sortedCommendations.push_back(std::make_pair(tmp, sc));\n\t\t\t}\n\t\t}\n\t\t// sort by translation\n\t\tstd::stable_sort(_sortedCommendations.begin(), _sortedCommendations.end(),\n\t\t\t[](const auto& lhs, const auto& rhs)\n\t\t\t{\n\t\t\t\treturn Unicode::naturalCompare(lhs.first, rhs.first);\n\t\t\t}\n\t\t);\n\t\t// fill the lists\n\t\tfor (const auto& pair : _sortedCommendations)\n\t\t{\n\t\t\tRuleCommendations* commendation = pair.second->getRule();\n\t\t\tif (pair.second->getNoun() != \"noNoun\")\n\t\t\t{\n\t\t\t\t_lstCommendations->addRow(2, pair.first.c_str(), tr(pair.second->getDecorationDescription()).c_str());\n\t\t\t\t_commendationsListEntry.push_back(tr(commendation->getDescription()).arg(tr(pair.second->getNoun())));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_lstCommendations->addRow(2, pair.first.c_str(), tr(pair.second->getDecorationDescription()).c_str());\n\t\t\t\t_commendationsListEntry.push_back(tr(commendation->getDescription()));\n\t\t\t}\n\t\t\t_commendationsNames.push_back(pair.second->getType());\n\t\t}\n\t\tdrawSprites();\n\t}\n}\n\n/**\n * Draws sprites\n *\n */\nvoid SoldierDiaryPerformanceState::drawSprites()\n{\n\tif (_display != DIARY_COMMENDATIONS) return;\n\n\t// Commendation sprites\n\tSurfaceSet* commendationSprite = _game->getMod()->getSurfaceSet(\"Commendations\");\n\tSurfaceSet* commendationDecoration = _game->getMod()->getSurfaceSet(\"CommendationDecorations\");\n\n\t// Clear sprites\n\tfor (int i = 0; i != 10; ++i)\n\t{\n\t\t_commendations[i]->clear();\n\t\t_commendationDecorations[i]->clear();\n\t}\n\n\tint vectorPosition = 0; // Where we are currently located in the vector\n\tint scrollDepth = _lstCommendations->getScroll(); // So we know where to start\n\n\tfor (const auto& pair : _sortedCommendations)\n\t{\n\t\tRuleCommendations *commendation = pair.second->getRule();\n\t\t// Skip commendations that are not visible in the textlist\n\t\tif ( vectorPosition < scrollDepth || vectorPosition - scrollDepth >= (int)_commendations.size())\n\t\t{\n\t\t\tvectorPosition++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tint _sprite = commendation->getSprite();\n\t\tint _decorationSprite = pair.second->getDecorationLevelInt();\n\n\t\t// Handle commendation sprites\n\t\tcommendationSprite->getFrame(_sprite)->blitNShade(_commendations[vectorPosition - scrollDepth], 0, 0);\n\n\t\t// Handle commendation decoration sprites\n\t\tif (_decorationSprite != 0)\n\t\t{\n\t\t\tcommendationDecoration->getFrame(_decorationSprite)->blitNShade(_commendationDecorations[vectorPosition - scrollDepth], 0, 0);\n\t\t}\n\n\t\tvectorPosition++;\n\t}\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid SoldierDiaryPerformanceState::btnOkClick(Action *)\n{\n\t_soldierDiaryOverviewState->setSoldierId(_soldierId);\n\t_game->popState();\n}\n\n/**\n * Goes to the previous soldier.\n * @param action Pointer to an action.\n */\nvoid SoldierDiaryPerformanceState::btnPrevClick(Action *)\n{\n\tif (_soldierId == 0)\n\t\t_soldierId = _list->size() - 1;\n\telse\n\t\t_soldierId--;\n\tinit();\n}\n\n/**\n * Goes to the next soldier.\n * @param action Pointer to an action.\n */\nvoid SoldierDiaryPerformanceState::btnNextClick(Action *)\n{\n\t_soldierId++;\n\tif (_soldierId >= _list->size())\n\t\t_soldierId = 0;\n\tinit();\n}\n\n/**\n * Display Kills totals.\n */\nvoid SoldierDiaryPerformanceState::btnKillsToggle(Action *)\n{\n\t_display = DIARY_KILLS;\n\tinit();\n}\n\n/**\n * Display Missions totals.\n */\nvoid SoldierDiaryPerformanceState::btnMissionsToggle(Action *)\n{\n\t_display = DIARY_MISSIONS;\n\tinit();\n}\n\n/**\n * Display Commendations.\n */\nvoid SoldierDiaryPerformanceState::btnCommendationsToggle(Action *)\n{\n\t_display = DIARY_COMMENDATIONS;\n\tinit();\n}\n\n/*\n *\n */\nvoid SoldierDiaryPerformanceState::lstInfoMouseOver(Action *)\n{\n\tsize_t _sel;\n\t_sel = _lstCommendations->getSelectedRow();\n\n\tif ( _commendationsListEntry.empty() || _sel > _commendationsListEntry.size() - 1)\n\t{\n\t\t_txtMedalInfo->setText(\"\");\n\t}\n\telse\n\t{\n\t\t_txtMedalInfo->setText(_commendationsListEntry[_sel]);\n\t}\n}\n\n/*\n *  Clears the Medal information\n */\nvoid SoldierDiaryPerformanceState::lstInfoMouseOut(Action *)\n{\n\t_txtMedalInfo->setText(\"\");\n}\n\n/*\n*\n*/\nvoid SoldierDiaryPerformanceState::lstInfoMouseClick(Action *)\n{\n\t_doNotReset = true;\n\tUfopaedia::openArticle(_game, _commendationsNames[_lstCommendations->getSelectedRow()]);\n}\n\n/**\n * Runs state functionality every cycle.\n * Used to update sprite vector\n */\nvoid SoldierDiaryPerformanceState::think()\n{\n\tState::think();\n\n\tif ((unsigned int)_lastScrollPos != _lstCommendations->getScroll())\n\t{\n\t\tdrawSprites();\n\t\t_lastScrollPos = _lstCommendations->getScroll();\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/SoldierDiaryPerformanceState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include <vector>\n#include <string>\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass TextList;\nclass Base;\nclass SoldierDiaryOverviewState;\nclass Surface;\nclass Soldier;\nclass SoldierCommendations;\n\nenum SoldierDiaryDisplay { DIARY_KILLS, DIARY_MISSIONS, DIARY_COMMENDATIONS };\n\n/**\n * Diary screen that lists soldier totals.\n */\nclass SoldierDiaryPerformanceState : public State\n{\nprivate:\n\tBase *_base;\n\tsize_t _soldierId;\n\tSoldierDiaryOverviewState *_soldierDiaryOverviewState;\n\tSoldier *_soldier;\n\tstd::vector<Soldier*> *_list;\n\n\tTextButton *_btnOk, *_btnPrev, *_btnNext, *_btnKills, *_btnMissions, *_btnCommendations;\n\tWindow *_window;\n\tText *_txtTitle, *_txtMedalName, *_txtMedalLevel, *_txtMedalInfo;\n\tTextList *_lstPerformance, *_lstKillTotals, *_lstMissionTotals, *_lstCommendations;\n\tstd::vector<std::string> _commendationsListEntry;\n\tstd::vector<std::string> _commendationsNames;\n\tstd::vector<std::pair<std::string, SoldierCommendations*> > _sortedCommendations;\n\tstd::vector<Surface*> _commendations, _commendationDecorations;\n\n\tSoldierDiaryDisplay _display;\n\tint _lastScrollPos;\n\tTextButton *_group;\n\tbool _doNotReset;\n\npublic:\n\t/// Creates the Soldier Diary Totals state.\n\tSoldierDiaryPerformanceState(Base *base, size_t soldierId, SoldierDiaryOverviewState *soldierDiaryState, SoldierDiaryDisplay display);\n\t/// Cleans up the Soldier Diary Totals state.\n\t~SoldierDiaryPerformanceState();\n\t/// Updates the soldier info.\n\tvoid init() override;\n\t/// Draw sprites.\n\tvoid drawSprites();\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the Previous button.\n\tvoid btnPrevClick(Action *action);\n\t/// Handler for clicking the Next button.\n\tvoid btnNextClick(Action *action);\n\t/// Handler for clicking the Kills button.\n\tvoid btnKillsToggle(Action *action);\n\t/// Handler for clicking the Missions button.\n\tvoid btnMissionsToggle(Action *action);\n\t/// Handler for clicking the Missions button.\n\tvoid btnCommendationsToggle(Action *action);\n\t/// Handler for moving the mouse over a medal.\n\tvoid lstInfoMouseOver(Action *action);\n\t/// Handler for moving the mouse outside the medals list.\n\tvoid lstInfoMouseOut(Action *action);\n\t/// Handler for clicking on a medal.\n\tvoid lstInfoMouseClick(Action *action);\n\t/// Runs state functionality every cycle.\n\tvoid think() override;\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/SoldierInfoState.cpp",
    "content": "/*\n * Copyright 2010-2017 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"SoldierInfoState.h\"\n#include \"SoldierDiaryOverviewState.h\"\n#include <algorithm>\n#include <sstream>\n#include \"../Engine/Game.h\"\n#include \"../Engine/Action.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/Bar.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextEdit.h\"\n#include \"../Engine/Surface.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/Craft.h\"\n#include \"../Savegame/Soldier.h\"\n#include \"../Engine/SurfaceSet.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Menu/ErrorMessageState.h\"\n#include \"SellState.h\"\n#include \"SoldierArmorState.h\"\n#include \"SoldierBonusState.h\"\n#include \"SoldierTransformState.h\"\n#include \"SoldierRankState.h\"\n#include \"SackSoldierState.h\"\n#include \"../Mod/RuleInterface.h\"\n#include \"../Mod/RuleSoldier.h\"\n#include \"../Savegame/SoldierDeath.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Soldier Info screen.\n * @param game Pointer to the core game.\n * @param base Pointer to the base to get info from. NULL to use the dead soldiers list.\n * @param soldierId ID of the selected soldier.\n */\nSoldierInfoState::SoldierInfoState(Base *base, size_t soldierId, bool forceLimits, bool readOnly) :\n\t_base(base), _soldierId(soldierId), _forceLimits(forceLimits), _readOnly(readOnly), _noTransformations(false), _soldier(0)\n{\n\tif (_base == 0)\n\t{\n\t\t_list = _game->getSavedGame()->getDeadSoldiers();\n\t\tif (_soldierId >= _list->size())\n\t\t{\n\t\t\t_soldierId = 0;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_soldierId = _list->size() - (1 + _soldierId);\n\t\t}\n\t}\n\telse\n\t{\n\t\t_list = _base->getSoldiers();\n\t}\n\n\t// Create objects\n\t_bg = new Surface(320, 200, 0, 0);\n\t_rank = new InteractiveSurface(26, 23, 4, 4);\n\t_flag = new InteractiveSurface(40, 20, 275, 6);\n\t_btnPrev = new TextButton(28, 14, 0, 33);\n\t_btnOk = new TextButton(48, 14, 30, 33);\n\t_btnNext = new TextButton(28, 14, 80, 33);\n\t_btnArmor = new TextButton(110, 14, 130, 33);\n\t_btnBonuses = new TextButton(16, 14, 242, 33);\n\t_btnTransformations = new TextButton(18, 14, 110, 33);\n\t_edtSoldier = new TextEdit(this, 210, 16, 40, 9);\n\t_btnSack = new TextButton(60, 14, 260, 33);\n\t_btnDiary = new TextButton(60, 14, 260, 48);\n\t_txtRank = new Text(130, 9, 0, 48);\n\t_txtMissions = new Text(100, 9, 130, 48);\n\t_txtKills = new Text(100, 9, 200, 48);\n\t_txtStuns = new Text(60, 9, 260, 48);\n\t_txtCraft = new Text(130, 9, 0, 56);\n\t_txtRecovery = new Text(180, 9, 130, 56);\n\t_txtPsionic = new Text(150, 9, 0, 66);\n\t_txtDead = new Text(150, 9, 130, 33);\n\n\tint yPos = 80;\n\tint step = 11;\n\tif (_game->getMod()->isManaFeatureEnabled())\n\t{\n\t\tyPos = 81;\n\t\tstep = 10;\n\t}\n\n\t_txtTimeUnits = new Text(120, 9, 6, yPos);\n\t_numTimeUnits = new Text(18, 9, 131, yPos);\n\t_barTimeUnits = new Bar(170, 7, 150, yPos);\n\tyPos += step;\n\n\t_txtStamina = new Text(120, 9, 6, yPos);\n\t_numStamina = new Text(18, 9, 131, yPos);\n\t_barStamina = new Bar(170, 7, 150, yPos);\n\tyPos += step;\n\n\t_txtHealth = new Text(120, 9, 6, yPos);\n\t_numHealth = new Text(18, 9, 131, yPos);\n\t_barHealth = new Bar(170, 7, 150, yPos);\n\tyPos += step;\n\n\t_txtBravery = new Text(120, 9, 6, yPos);\n\t_numBravery = new Text(18, 9, 131, yPos);\n\t_barBravery = new Bar(170, 7, 150, yPos);\n\tyPos += step;\n\n\t_txtReactions = new Text(120, 9, 6, yPos);\n\t_numReactions = new Text(18, 9, 131, yPos);\n\t_barReactions = new Bar(170, 7, 150, yPos);\n\tyPos += step;\n\n\t_txtFiring = new Text(120, 9, 6, yPos);\n\t_numFiring = new Text(18, 9, 131, yPos);\n\t_barFiring = new Bar(170, 7, 150, yPos);\n\tyPos += step;\n\n\t_txtThrowing = new Text(120, 9, 6, yPos);\n\t_numThrowing = new Text(18, 9, 131, yPos);\n\t_barThrowing = new Bar(170, 7, 150, yPos);\n\tyPos += step;\n\n\t_txtMelee = new Text(120, 9, 6, yPos);\n\t_numMelee = new Text(18, 9, 131, yPos);\n\t_barMelee = new Bar(170, 7, 150, yPos);\n\tyPos += step;\n\n\t_txtStrength = new Text(120, 9, 6, yPos);\n\t_numStrength = new Text(18, 9, 131, yPos);\n\t_barStrength = new Bar(170, 7, 150, yPos);\n\tyPos += step;\n\n\tif (_game->getMod()->isManaFeatureEnabled())\n\t{\n\t\t_txtMana = new Text(120, 9, 6, yPos);\n\t\t_numMana = new Text(18, 9, 131, yPos);\n\t\t_barMana = new Bar(170, 7, 150, yPos);\n\t\tyPos += step;\n\t}\n\n\t_txtPsiStrength = new Text(120, 9, 6, yPos);\n\t_numPsiStrength = new Text(18, 9, 131, yPos);\n\t_barPsiStrength = new Bar(170, 7, 150, yPos);\n\tyPos += step;\n\n\t_txtPsiSkill = new Text(120, 9, 6, yPos);\n\t_numPsiSkill = new Text(18, 9, 131, yPos);\n\t_barPsiSkill = new Bar(170, 7, 150, yPos);\n\n\t// Set palette\n\tsetInterface(\"soldierInfo\");\n\n\tadd(_bg);\n\tadd(_rank);\n\tadd(_flag);\n\tadd(_btnOk, \"button\", \"soldierInfo\");\n\tadd(_btnPrev, \"button\", \"soldierInfo\");\n\tadd(_btnNext, \"button\", \"soldierInfo\");\n\tadd(_btnArmor, \"button\", \"soldierInfo\");\n\tadd(_btnBonuses, \"button\", \"soldierInfo\");\n\tadd(_btnTransformations, \"button\", \"soldierInfo\");\n\tadd(_edtSoldier, \"text1\", \"soldierInfo\");\n\tadd(_btnSack, \"button\", \"soldierInfo\");\n\tadd(_btnDiary, \"button\", \"soldierInfo\");\n\tadd(_txtRank, \"text1\", \"soldierInfo\");\n\tadd(_txtMissions, \"text1\", \"soldierInfo\");\n\tadd(_txtKills, \"text1\", \"soldierInfo\");\n\tadd(_txtStuns, \"text1\", \"soldierInfo\");\n\tadd(_txtCraft, \"text1\", \"soldierInfo\");\n\tadd(_txtRecovery, \"text1\", \"soldierInfo\");\n\tadd(_txtPsionic, \"text2\", \"soldierInfo\");\n\tadd(_txtDead, \"text2\", \"soldierInfo\");\n\n\tadd(_txtTimeUnits, \"text2\", \"soldierInfo\");\n\tadd(_numTimeUnits, \"numbers\", \"soldierInfo\");\n\tadd(_barTimeUnits, \"barTUs\", \"soldierInfo\");\n\n\tadd(_txtStamina, \"text2\", \"soldierInfo\");\n\tadd(_numStamina, \"numbers\", \"soldierInfo\");\n\tadd(_barStamina, \"barEnergy\", \"soldierInfo\");\n\n\tadd(_txtHealth, \"text2\", \"soldierInfo\");\n\tadd(_numHealth, \"numbers\", \"soldierInfo\");\n\tadd(_barHealth, \"barHealth\", \"soldierInfo\");\n\n\tadd(_txtBravery, \"text2\", \"soldierInfo\");\n\tadd(_numBravery, \"numbers\", \"soldierInfo\");\n\tadd(_barBravery, \"barBravery\", \"soldierInfo\");\n\n\tadd(_txtReactions, \"text2\", \"soldierInfo\");\n\tadd(_numReactions, \"numbers\", \"soldierInfo\");\n\tadd(_barReactions, \"barReactions\", \"soldierInfo\");\n\n\tadd(_txtFiring, \"text2\", \"soldierInfo\");\n\tadd(_numFiring, \"numbers\", \"soldierInfo\");\n\tadd(_barFiring, \"barFiring\", \"soldierInfo\");\n\n\tadd(_txtThrowing, \"text2\", \"soldierInfo\");\n\tadd(_numThrowing, \"numbers\", \"soldierInfo\");\n\tadd(_barThrowing, \"barThrowing\", \"soldierInfo\");\n\n\tadd(_txtMelee, \"text2\", \"soldierInfo\");\n\tadd(_numMelee, \"numbers\", \"soldierInfo\");\n\tadd(_barMelee, \"barMelee\", \"soldierInfo\");\n\n\tadd(_txtStrength, \"text2\", \"soldierInfo\");\n\tadd(_numStrength, \"numbers\", \"soldierInfo\");\n\tadd(_barStrength, \"barStrength\", \"soldierInfo\");\n\n\tif (_game->getMod()->isManaFeatureEnabled())\n\t{\n\t\tadd(_txtMana, \"text2\", \"soldierInfo\");\n\t\tadd(_numMana, \"numbers\", \"soldierInfo\");\n\t\tadd(_barMana, \"barMana\", \"soldierInfo\");\n\t}\n\n\tadd(_txtPsiStrength, \"text2\", \"soldierInfo\");\n\tadd(_numPsiStrength, \"numbers\", \"soldierInfo\");\n\tadd(_barPsiStrength, \"barPsiStrength\", \"soldierInfo\");\n\n\tadd(_txtPsiSkill, \"text2\", \"soldierInfo\");\n\tadd(_numPsiSkill, \"numbers\", \"soldierInfo\");\n\tadd(_barPsiSkill, \"barPsiSkill\", \"soldierInfo\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\t_game->getMod()->getSurface(\"BACK06.SCR\")->blitNShade(_bg, 0, 0);\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&SoldierInfoState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&SoldierInfoState::btnOkClick, Options::keyCancel);\n\n\t_btnPrev->setText(\"<<\");\n\tif (_base == 0)\n\t{\n\t\t_btnPrev->onMouseClick((ActionHandler)&SoldierInfoState::btnNextClick);\n\t\t_btnPrev->onKeyboardPress((ActionHandler)&SoldierInfoState::btnNextClick, Options::keyBattlePrevUnit);\n\t}\n\telse\n\t{\n\t\t_btnPrev->onMouseClick((ActionHandler)&SoldierInfoState::btnPrevClick);\n\t\t_btnPrev->onKeyboardPress((ActionHandler)&SoldierInfoState::btnPrevClick, Options::keyBattlePrevUnit);\n\t}\n\n\t_btnNext->setText(\">>\");\n\tif (_base == 0)\n\t{\n\t\t_btnNext->onMouseClick((ActionHandler)&SoldierInfoState::btnPrevClick);\n\t\t_btnNext->onKeyboardPress((ActionHandler)&SoldierInfoState::btnPrevClick, Options::keyBattleNextUnit);\n\t}\n\telse\n\t{\n\t\t_btnNext->onMouseClick((ActionHandler)&SoldierInfoState::btnNextClick);\n\t\t_btnNext->onKeyboardPress((ActionHandler)&SoldierInfoState::btnNextClick, Options::keyBattleNextUnit);\n\t}\n\n\t_btnArmor->setText(tr(\"STR_ARMOR\"));\n\t_btnArmor->onMouseClick((ActionHandler)&SoldierInfoState::btnArmorClick);\n\tif (_readOnly)\n\t{\n\t\t_btnArmor->setVisible(false);\n\t}\n\n\t_btnBonuses->setText(tr(\"STR_BONUSES_BUTTON\")); // tiny button, default translation is \" \"\n\t_btnBonuses->onMouseClick((ActionHandler)&SoldierInfoState::btnBonusesClick);\n\n\t_btnTransformations->setText(tr(\"STR_TRANSFORMATIONS_BUTTON\"));\n\t_btnTransformations->onMouseClick((ActionHandler)&SoldierInfoState::btnTransformationsClick);\n\n\tstd::vector<RuleSoldierTransformation*> availableTransformations;\n\tif (_base)\n\t{\n\t\t_game->getSavedGame()->getAvailableTransformations(availableTransformations, _game->getMod(), _base);\n\t}\n\tif (availableTransformations.empty())\n\t{\n\t\t_noTransformations = true;\n\t}\n\n\t_edtSoldier->setBig();\n\t_edtSoldier->onChange((ActionHandler)&SoldierInfoState::edtSoldierChange);\n\t_edtSoldier->onMousePress((ActionHandler)&SoldierInfoState::edtSoldierPress);\n\n\t// Can't change nationality of dead soldiers\n\tif (_base != 0)\n\t{\n\t\t// Ignore also if flags are used to indicate number of kills\n\t\tif (_game->getMod()->getFlagByKills().empty())\n\t\t{\n\t\t\t_flag->onMouseClick((ActionHandler)&SoldierInfoState::btnFlagClick, SDL_BUTTON_LEFT);\n\t\t\t_flag->onMouseClick((ActionHandler)&SoldierInfoState::btnFlagClick, SDL_BUTTON_RIGHT);\n\t\t}\n\n\t\t_rank->onMouseClick((ActionHandler)&SoldierInfoState::btnRankClick);\n\t}\n\n\t_btnSack->setText(tr(\"STR_SACK\"));\n\t_btnSack->onMouseClick((ActionHandler)&SoldierInfoState::btnSackClick);\n\n\t_btnDiary->setText(tr(\"STR_DIARY\"));\n\t_btnDiary->onMouseClick((ActionHandler)&SoldierInfoState::btnDiaryClick);\n\t_btnDiary->setVisible(Options::soldierDiaries);\n\n\t_txtPsionic->setText(tr(\"STR_IN_PSIONIC_TRAINING\"));\n\n\t_txtTimeUnits->setText(tr(\"STR_TIME_UNITS\"));\n\n\t_barTimeUnits->setScale(1.0);\n\n\t_txtStamina->setText(tr(\"STR_STAMINA\"));\n\n\t_barStamina->setScale(1.0);\n\n\t_txtHealth->setText(tr(\"STR_HEALTH\"));\n\n\t_barHealth->setScale(1.0);\n\n\t_txtBravery->setText(tr(\"STR_BRAVERY\"));\n\n\t_barBravery->setScale(1.0);\n\n\t_txtReactions->setText(tr(\"STR_REACTIONS\"));\n\n\t_barReactions->setScale(1.0);\n\n\t_txtFiring->setText(tr(\"STR_FIRING_ACCURACY\"));\n\n\t_barFiring->setScale(1.0);\n\n\t_txtThrowing->setText(tr(\"STR_THROWING_ACCURACY\"));\n\n\t_barThrowing->setScale(1.0);\n\n\t_txtMelee->setText(tr(\"STR_MELEE_ACCURACY\"));\n\n\t_barMelee->setScale(1.0);\n\n\t_txtStrength->setText(tr(\"STR_STRENGTH\"));\n\n\t_barStrength->setScale(1.0);\n\n\tif (_game->getMod()->isManaFeatureEnabled())\n\t{\n\t\t_txtMana->setText(tr(\"STR_MANA_POOL\"));\n\t\t_barMana->setScale(1.0);\n\t}\n\n\t_txtPsiStrength->setText(tr(\"STR_PSIONIC_STRENGTH\"));\n\n\t_barPsiStrength->setScale(1.0);\n\n\t_txtPsiSkill->setText(tr(\"STR_PSIONIC_SKILL\"));\n\n\t_barPsiSkill->setScale(1.0);\n}\n\n/**\n *\n */\nSoldierInfoState::~SoldierInfoState()\n{\n\n}\n\n/**\n * Updates soldier stats when\n * the soldier changes.\n */\nvoid SoldierInfoState::init()\n{\n\tState::init();\n\tif (_list->empty())\n\t{\n\t\t_game->popState();\n\t\treturn;\n\t}\n\tif (_soldierId >= _list->size())\n\t{\n\t\t_soldierId = 0;\n\t}\n\t_soldier = _list->at(_soldierId);\n\t_edtSoldier->setBig();\n\t_edtSoldier->setText(_soldier->getName());\n\tconst UnitStats *initial = _soldier->getInitStats();\n\tconst UnitStats *current = _soldier->getCurrentStats();\n\tconst UnitStats max = _soldier->getRules()->getStatCaps();\n\n\tbool hasBonus = _soldier->prepareStatsWithBonuses(_game->getMod()); // refresh all bonuses\n\tUnitStats withArmor = *_soldier->getStatsWithAllBonuses();\n\t_btnBonuses->setVisible(hasBonus);\n\n\tSurfaceSet *texture = _game->getMod()->getSurfaceSet(\"BASEBITS.PCK\");\n\tauto* frame = texture->getFrame(_soldier->getRankSprite());\n\tif (frame)\n\t{\n\t\tframe->blitNShade(_rank, 0, 0);\n\t}\n\n\tstd::ostringstream flagId;\n\tflagId << \"Flag\";\n\tconst std::vector<int> mapping = _game->getMod()->getFlagByKills();\n\tif (mapping.empty())\n\t{\n\t\tflagId << _soldier->getNationality() + _soldier->getRules()->getFlagOffset();\n\t}\n\telse\n\t{\n\t\tint index = 0;\n\t\tfor (int item : mapping)\n\t\t{\n\t\t\tif (_soldier->getKills() <= item)\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tindex++;\n\t\t}\n\t\tflagId << index + _soldier->getRules()->getFlagOffset();\n\t}\n\tSurface *flagTexture = _game->getMod()->getSurface(flagId.str().c_str(), false);\n\t_flag->clear();\n\tif (flagTexture != 0)\n\t{\n\t\tflagTexture->blitNShade(_flag, _flag->getWidth() - flagTexture->getWidth(), 0); // align right\n\t}\n\n\t// formats a stat for display.\n\tauto formatStat = [](UnitStats::Type current2, UnitStats::Type max2, UnitStats::Type withArmor2, UnitStats::Type initial2, Text* number, Bar* bar)\n\t{\n\t\tstd::ostringstream ss;\n\t\tif (current2 >= max2)\n\t\t{\n\t\t\tss << Unicode::TOK_COLOR_FLIP;\n\t\t}\n\t\tss << withArmor2;\n\t\tnumber->setText(ss.str());\n\t\tbar->setMax(current2);\n\t\tbar->setValue(withArmor2);\n\t\tbar->setValue2(std::min(withArmor2, initial2));\n\t};\n\n\tformatStat(current->tu, max.tu, withArmor.tu, initial->tu, _numTimeUnits, _barTimeUnits);\n\tformatStat(current->stamina, max.stamina, withArmor.stamina, initial->stamina, _numStamina, _barStamina);\n\tformatStat(current->health, max.health, withArmor.health, initial->health, _numHealth, _barHealth);\n\tformatStat(current->bravery, max.bravery, withArmor.bravery, initial->bravery, _numBravery, _barBravery);\n\tformatStat(current->reactions, max.reactions, withArmor.reactions, initial->reactions, _numReactions, _barReactions);\n\tformatStat(current->firing, max.firing, withArmor.firing, initial->firing, _numFiring, _barFiring);\n\tformatStat(current->throwing, max.throwing, withArmor.throwing, initial->throwing, _numThrowing, _barThrowing);\n\tformatStat(current->melee, max.melee, withArmor.melee, initial->melee, _numMelee, _barMelee);\n\tformatStat(current->strength, max.strength, withArmor.strength, initial->strength, _numStrength, _barStrength);\n\n\tstd::string wsArmor;\n\tif (_soldier->getArmor() == _soldier->getRules()->getDefaultArmor())\n\t{\n\t\twsArmor= tr(\"STR_ARMOR_\").arg(tr(_soldier->getArmor()->getType()));\n\t}\n\telse\n\t{\n\t\twsArmor = tr(_soldier->getArmor()->getType());\n\t}\n\n\t_btnArmor->setText(wsArmor);\n\n\tbool showNastyButtons = !_readOnly && _game->getSavedGame()->getMonthsPassed() > -1 && !(_soldier->getCraft() && _soldier->getCraft()->getStatus() == \"STR_OUT\");\n\n\t_btnSack->setVisible(showNastyButtons);\n\t_btnTransformations->setVisible(showNastyButtons && !_noTransformations);\n\n\t_txtRank->setText(tr(\"STR_RANK_\").arg(tr(_soldier->getRankString())));\n\n\t_txtMissions->setText(tr(\"STR_MISSIONS\").arg(_soldier->getMissions()));\n\n\t_txtKills->setText(tr(\"STR_KILLS\").arg(_soldier->getKills()));\n\n\t_txtStuns->setText(tr(\"STR_STUNS\").arg(_soldier->getStuns()));\n\t_txtStuns->setVisible(!Options::soldierDiaries);\n\n\tstd::string craft;\n\tif (_soldier->getCraft() == 0)\n\t{\n\t\tcraft = tr(\"STR_NONE_UC\");\n\t}\n\telse\n\t{\n\t\tcraft = _soldier->getCraft()->getName(_game->getLanguage());\n\t}\n\t_txtCraft->setText(tr(\"STR_CRAFT_\").arg(craft));\n\n\tBaseSumDailyRecovery recovery = _base ? _base->getSumRecoveryPerDay() : BaseSumDailyRecovery();\n\tauto getDaysOrInfinity = [&](int days)\n\t{\n\t\tif (days < 0)\n\t\t{\n\t\t\treturn std::string{ \"∞\" };\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn std::string{tr(\"STR_DAY\", days)};\n\t\t}\n\t};\n\tif (_soldier->isWounded())\n\t{\n\t\tint recoveryTime = _soldier->getNeededRecoveryTime(recovery);\n\t\t_txtRecovery->setText(tr(\"STR_WOUND_RECOVERY\").arg(getDaysOrInfinity(recoveryTime)));\n\t}\n\telse\n\t{\n\t\t_txtRecovery->setText(\"\");\n\t\tif (_soldier->getManaMissing() > 0)\n\t\t{\n\t\t\tint manaRecoveryTime = _soldier->getManaRecovery(recovery.ManaRecovery);\n\t\t\t_txtRecovery->setText(tr(\"STR_MANA_RECOVERY\").arg(getDaysOrInfinity(manaRecoveryTime)));\n\t\t}\n\t\tif (_soldier->getHealthMissing() > 0)\n\t\t{\n\t\t\tint healthRecoveryTime = _soldier->getHealthRecovery(recovery.HealthRecovery);\n\t\t\t_txtRecovery->setText(tr(\"STR_HEALTH_RECOVERY\").arg(getDaysOrInfinity(healthRecoveryTime)));\n\t\t}\n\t}\n\n\t_txtPsionic->setVisible(_soldier->isInPsiTraining());\n\n\tif (_game->getMod()->isManaFeatureEnabled())\n\t{\n\t\tif (_game->getSavedGame()->isManaUnlocked(_game->getMod()))\n\t\t{\n\t\t\tformatStat(current->mana, max.mana, withArmor.mana, initial->mana, _numMana, _barMana);\n\n\t\t\t_txtMana->setVisible(true);\n\t\t\t_numMana->setVisible(true);\n\t\t\t_barMana->setVisible(true);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_txtMana->setVisible(false);\n\t\t\t_numMana->setVisible(false);\n\t\t\t_barMana->setVisible(false);\n\t\t}\n\t}\n\n\tif (current->psiSkill > 0 || (Options::psiStrengthEval && _game->getSavedGame()->isResearched(_game->getMod()->getPsiRequirements())))\n\t{\n\t\tformatStat(current->psiStrength, max.psiStrength, withArmor.psiStrength, initial->psiStrength, _numPsiStrength, _barPsiStrength);\n\n\t\t_txtPsiStrength->setVisible(true);\n\t\t_numPsiStrength->setVisible(true);\n\t\t_barPsiStrength->setVisible(true);\n\t}\n\telse\n\t{\n\t\t_txtPsiStrength->setVisible(false);\n\t\t_numPsiStrength->setVisible(false);\n\t\t_barPsiStrength->setVisible(false);\n\t}\n\n\tif (current->psiSkill > 0)\n\t{\n\t\tformatStat(current->psiSkill, max.psiSkill, withArmor.psiSkill, initial->psiSkill, _numPsiSkill, _barPsiSkill);\n\n\t\t_txtPsiSkill->setVisible(true);\n\t\t_numPsiSkill->setVisible(true);\n\t\t_barPsiSkill->setVisible(true);\n\t}\n\telse\n\t{\n\t\t_txtPsiSkill->setVisible(false);\n\t\t_numPsiSkill->setVisible(false);\n\t\t_barPsiSkill->setVisible(false);\n\t}\n\n\t// Dead can't talk\n\tif (_base == 0)\n\t{\n\t\t_btnArmor->setVisible(false);\n\t\t_btnSack->setVisible(false);\n\t\t_txtCraft->setVisible(false);\n\t\t_txtDead->setVisible(true);\n\t\tstd::string status = \"STR_MISSING_IN_ACTION\";\n\t\tif (_soldier->getDeath() && _soldier->getDeath()->getCause())\n\t\t{\n\t\t\tstatus = \"STR_KILLED_IN_ACTION\";\n\t\t}\n\t\t_txtDead->setText(tr(status, _soldier->getGender()));\n\t}\n\telse\n\t{\n\t\t_txtDead->setVisible(false);\n\t}\n}\n\n/**\n * Takes care of any events from the core game engine.\n * @param action Pointer to an action.\n */\nvoid SoldierInfoState::handle(Action* action)\n{\n\tState::handle(action);\n\n\tif (Options::oxceThumbButtons && action->getDetails()->type == SDL_MOUSEBUTTONDOWN)\n\t{\n\t\tif (action->getDetails()->button.button == SDL_BUTTON_X1)\n\t\t{\n\t\t\tbtnNextClick(action);\n\t\t}\n\t\telse if (action->getDetails()->button.button == SDL_BUTTON_X2)\n\t\t{\n\t\t\tbtnPrevClick(action);\n\t\t}\n\t}\n}\n\n/**\n * Disables the soldier input.\n * @param action Pointer to an action.\n */\nvoid SoldierInfoState::edtSoldierPress(Action *)\n{\n\tif (_base == 0)\n\t{\n\t\t_edtSoldier->setFocus(false);\n\t}\n}\n\n/**\n * Set the soldier Id.\n */\nvoid SoldierInfoState::setSoldierId(size_t soldier)\n{\n\t_soldierId = soldier;\n}\n\n/**\n * Changes the soldier's name.\n * @param action Pointer to an action.\n */\nvoid SoldierInfoState::edtSoldierChange(Action *)\n{\n\t_soldier->setName(_edtSoldier->getText());\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid SoldierInfoState::btnOkClick(Action *)\n{\n\n\t_game->popState();\n\tif (_game->getSavedGame()->getMonthsPassed() > -1 && Options::storageLimitsEnforced && _base != 0 && _base->storesOverfull())\n\t{\n\t\tif (_forceLimits)\n\t\t{\n\t\t\t// Note: we could sell a currently opened craft here and crash the game\n\t\t\t_game->pushState(new SellState(_base, 0));\n\t\t}\n\t\t_game->pushState(new ErrorMessageState(tr(\"STR_STORAGE_EXCEEDED\").arg(_base->getName()), _palette, _game->getMod()->getInterface(\"soldierInfo\")->getElement(\"errorMessage\")->color, \"BACK01.SCR\", _game->getMod()->getInterface(\"soldierInfo\")->getElement(\"errorPalette\")->color));\n\t}\n}\n\n/**\n * Goes to the previous soldier.\n * @param action Pointer to an action.\n */\nvoid SoldierInfoState::btnPrevClick(Action *)\n{\n\tif (_soldierId == 0)\n\t\t_soldierId = _list->size() - 1;\n\telse\n\t\t_soldierId--;\n\tinit();\n}\n\n/**\n * Goes to the next soldier.\n * @param action Pointer to an action.\n */\nvoid SoldierInfoState::btnNextClick(Action *)\n{\n\t_soldierId++;\n\tif (_soldierId >= _list->size())\n\t\t_soldierId = 0;\n\tinit();\n}\n\n/**\n * Shows the Select Armor window.\n * @param action Pointer to an action.\n */\nvoid SoldierInfoState::btnArmorClick(Action *)\n{\n\tif (!_soldier->getCraft() || (_soldier->getCraft() && _soldier->getCraft()->getStatus() != \"STR_OUT\"))\n\t{\n\t\t_game->pushState(new SoldierArmorState(_base, _soldierId, SA_GEOSCAPE));\n\t}\n}\n\n/**\n * Shows the SoldierBonus window.\n * @param action Pointer to an action.\n */\nvoid SoldierInfoState::btnBonusesClick(Action *)\n{\n\t_game->pushState(new SoldierBonusState(_base, _soldierId));\n}\n\n/**\n * Shows the SoldierTransform window.\n * @param action Pointer to an action.\n */\nvoid SoldierInfoState::btnTransformationsClick(Action*)\n{\n\t_game->pushState(new SoldierTransformState(_base, _soldierId));\n}\n\n/**\n * Shows the Sack Soldier window.\n * @param action Pointer to an action.\n */\nvoid SoldierInfoState::btnSackClick(Action *)\n{\n\t_game->pushState(new SackSoldierState(_base, _soldierId));\n}\n\n/**\n * Shows the Diary Soldier window.\n * @param action Pointer to an action.\n */\nvoid SoldierInfoState::btnDiaryClick(Action *)\n{\n\t_game->pushState(new SoldierDiaryOverviewState(_base, _soldierId, this));\n}\n\n/**\n* Changes soldier's nationality.\n* @param action Pointer to an action.\n*/\nvoid SoldierInfoState::btnFlagClick(Action *action)\n{\n\tint temp = _soldier->getNationality();\n\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT)\n\t{\n\t\ttemp += 1;\n\t}\n\telse if (action->getDetails()->button.button == SDL_BUTTON_RIGHT)\n\t{\n\t\ttemp += -1;\n\t}\n\n\tconst std::vector<SoldierNamePool*> &names = _soldier->getRules()->getNames();\n\tif (!names.empty())\n\t{\n\t\tconst int max = names.size();\n\t\tif (temp > max - 1)\n\t\t{\n\t\t\ttemp = 0;\n\t\t}\n\t\telse if (temp < 0)\n\t\t{\n\t\t\ttemp = max - 1;\n\t\t}\n\t}\n\telse\n\t{\n\t\ttemp = 0;\n\t}\n\n\t_soldier->setNationality(temp);\n\tinit();\n}\n\n/**\n * Shows the Manual Promotion window.\n * @param action Pointer to an action.\n */\nvoid SoldierInfoState::btnRankClick(Action *)\n{\n\tif (Options::oxceManualPromotions)\n\t{\n\t\t_game->pushState(new SoldierRankState(_base, _soldierId));\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/SoldierInfoState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include <vector>\n\nnamespace OpenXcom\n{\n\nclass Base;\nclass Surface;\nclass TextButton;\nclass Text;\nclass TextEdit;\nclass Bar;\nclass Soldier;\n\n/**\n * Soldier Info screen that shows all the\n * info of a specific soldier.\n */\nclass SoldierInfoState : public State\n{\nprivate:\n\tBase *_base;\n\tsize_t _soldierId;\n\tbool _forceLimits;\n\tbool _readOnly;\n\tbool _noTransformations;\n\tSoldier *_soldier;\n\tstd::vector<Soldier*> *_list;\n\n\tSurface *_bg;\n\tInteractiveSurface *_rank;\n\tInteractiveSurface *_flag;\n\tTextButton *_btnOk, *_btnPrev, *_btnNext, *_btnArmor, *_btnSack, *_btnDiary, *_btnBonuses, *_btnTransformations;\n\tText *_txtRank, *_txtMissions, *_txtKills, *_txtCraft, *_txtRecovery, *_txtPsionic, *_txtDead;\n\tText *_txtStuns;\n\tTextEdit *_edtSoldier;\n\n\tText *_txtTimeUnits, *_txtStamina, *_txtHealth, *_txtBravery, *_txtReactions, *_txtFiring, *_txtThrowing, *_txtMelee, *_txtStrength, *_txtPsiStrength, *_txtPsiSkill, *_txtMana;\n\tText *_numTimeUnits, *_numStamina, *_numHealth, *_numBravery, *_numReactions, *_numFiring, *_numThrowing, *_numMelee, *_numStrength, *_numPsiStrength, *_numPsiSkill, *_numMana;\n\tBar *_barTimeUnits, *_barStamina, *_barHealth, *_barBravery, *_barReactions, *_barFiring, *_barThrowing, *_barMelee, *_barStrength, *_barPsiStrength, *_barPsiSkill, *_barMana;\n\npublic:\n\t/// Creates the Soldier Info state.\n\tSoldierInfoState(Base *base, size_t soldierId, bool forceLimits = true, bool readOnly = false);\n\t/// Cleans up the Soldier Info state.\n\t~SoldierInfoState();\n\t/// Updates the soldier info.\n\tvoid init() override;\n\t/// Handles keypresses.\n\tvoid handle(Action* action) override;\n\t/// Set the soldier Id.\n\tvoid setSoldierId(size_t soldier);\n\t/// Handler for pressing on the Name edit.\n\tvoid edtSoldierPress(Action *action);\n\t/// Handler for changing text on the Name edit.\n\tvoid edtSoldierChange(Action *action);\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the Previous button.\n\tvoid btnPrevClick(Action *action);\n\t/// Handler for clicking the Next button.\n\tvoid btnNextClick(Action *action);\n\t/// Handler for clicking the Armor button.\n\tvoid btnArmorClick(Action *action);\n\t/// Handler for clicking the Bonuses button.\n\tvoid btnBonusesClick(Action *action);\n\t/// Handler for clicking the Transformations button.\n\tvoid btnTransformationsClick(Action* action);\n\t/// Handler for clicking the Sack button.\n\tvoid btnSackClick(Action *action);\n\t/// Handler for clicking the Diary button.\n\tvoid btnDiaryClick(Action *action);\n\t/// Handler for clicking the flag.\n\tvoid btnFlagClick(Action *action);\n\t/// Handler for clicking the rank.\n\tvoid btnRankClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/SoldierMemorialState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"SoldierMemorialState.h\"\n#include <sstream>\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextEdit.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/Soldier.h\"\n#include \"../Savegame/SoldierDeath.h\"\n#include \"../Savegame/GameTime.h\"\n#include \"SoldierInfoState.h\"\n#include \"../Menu/StatisticsState.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Soldier Memorial screen.\n * @param game Pointer to the core game.\n */\nSoldierMemorialState::SoldierMemorialState()\n{\n\t// Create objects\n\t_window = new Window(this, 320, 200, 0, 0);\n\t_btnQuickSearch = new TextEdit(this, 48, 9, 16, 10);\n\t_btnOk = new TextButton(148, 16, 164, 176);\n\t_btnStatistics = new TextButton(148, 16, 8, 176);\n\t_txtTitle = new Text(310, 17, 5, 8);\n\t_txtName = new Text(114, 9, 16, 36);\n\t_txtRank = new Text(102, 9, 130, 36);\n\t_txtDate = new Text(90, 9, 218, 36);\n\t_txtRecruited = new Text(150, 9, 16, 24);\n\t_txtLost = new Text(150, 9, 160, 24);\n\t_lstSoldiers = new TextList(288, 120, 8, 44);\n\n\t// Set palette\n\tsetInterface(\"soldierMemorial\");\n\n\tadd(_window, \"window\", \"soldierMemorial\");\n\tadd(_btnQuickSearch, \"button\", \"soldierMemorial\");\n\tadd(_btnOk, \"button\", \"soldierMemorial\");\n\tadd(_btnStatistics, \"button\", \"soldierMemorial\");\n\tadd(_txtTitle, \"text\", \"soldierMemorial\");\n\tadd(_txtName, \"text\", \"soldierMemorial\");\n\tadd(_txtRank, \"text\", \"soldierMemorial\");\n\tadd(_txtDate, \"text\", \"soldierMemorial\");\n\tadd(_txtRecruited, \"text\", \"soldierMemorial\");\n\tadd(_txtLost, \"text\", \"soldierMemorial\");\n\tadd(_lstSoldiers, \"list\", \"soldierMemorial\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"soldierMemorial\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&SoldierMemorialState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&SoldierMemorialState::btnOkClick, Options::keyCancel);\n\n\t_btnStatistics->setText(tr(\"STR_STATISTICS\"));\n\t_btnStatistics->onMouseClick((ActionHandler)&SoldierMemorialState::btnStatisticsClick);\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_MEMORIAL\"));\n\n\t_txtName->setText(tr(\"STR_NAME_UC\"));\n\n\t_txtRank->setText(tr(\"STR_RANK\"));\n\n\t_txtDate->setText(tr(\"STR_DATE_UC\"));\n\n\tsize_t lost = _game->getSavedGame()->getDeadSoldiers()->size();\n\tsize_t recruited = lost;\n\tfor (const auto* xbase : *_game->getSavedGame()->getBases())\n\t{\n\t\trecruited += xbase->getTotalSoldiers();\n\t}\n\n\t_txtRecruited->setText(tr(\"STR_SOLDIERS_RECRUITED_UC\").arg(recruited));\n\n\t_txtLost->setText(tr(\"STR_SOLDIERS_LOST_UC\").arg(lost));\n\n\t_lstSoldiers->setColumns(5, 114, 88, 30, 25, 35);\n\t_lstSoldiers->setSelectable(true);\n\t_lstSoldiers->setBackground(_window);\n\t_lstSoldiers->setMargin(8);\n\t_lstSoldiers->onMouseClick((ActionHandler)&SoldierMemorialState::lstSoldiersClick);\n\n\t_btnQuickSearch->setText(\"\"); // redraw\n\t_btnQuickSearch->onEnter((ActionHandler)&SoldierMemorialState::btnQuickSearchApply);\n\t_btnQuickSearch->setVisible(Options::oxceQuickSearchButton);\n\n\t_btnOk->onKeyboardRelease((ActionHandler)&SoldierMemorialState::btnQuickSearchToggle, Options::keyToggleQuickSearch);\n}\n\n/**\n *\n */\nSoldierMemorialState::~SoldierMemorialState()\n{\n\n}\n\n/**\n * Initializes the screen (fills the list).\n */\nvoid SoldierMemorialState::init()\n{\n\tState::init();\n\n\tfillMemorialList();\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid SoldierMemorialState::btnOkClick(Action *)\n{\n\t_game->popState();\n\t_game->getMod()->playMusic(\"GMGEO\");\n}\n\n/**\n * Quick search toggle.\n * @param action Pointer to an action.\n */\nvoid SoldierMemorialState::btnQuickSearchToggle(Action *action)\n{\n\tif (_btnQuickSearch->getVisible())\n\t{\n\t\t_btnQuickSearch->setText(\"\");\n\t\t_btnQuickSearch->setVisible(false);\n\t\tbtnQuickSearchApply(action);\n\t}\n\telse\n\t{\n\t\t_btnQuickSearch->setVisible(true);\n\t\t_btnQuickSearch->setFocus(true);\n\t}\n}\n\n/**\n * Quick search.\n * @param action Pointer to an action.\n */\nvoid SoldierMemorialState::btnQuickSearchApply(Action *)\n{\n\tfillMemorialList();\n}\n\n/**\n* Shows the Statistics screen.\n* @param action Pointer to an action.\n*/\nvoid SoldierMemorialState::btnStatisticsClick(Action *)\n{\n\t_game->pushState(new StatisticsState);\n}\n\n/**\n * Shows the selected soldier's info.\n * @param action Pointer to an action.\n */\nvoid SoldierMemorialState::lstSoldiersClick(Action *)\n{\n\t_game->pushState(new SoldierInfoState(0, _indices[_lstSoldiers->getSelectedRow()]));\n}\n\n/**\n * Fills the list with filtered memorial entries.\n */\nvoid SoldierMemorialState::fillMemorialList()\n{\n\tstd::string searchString = _btnQuickSearch->getText();\n\tUnicode::upperCase(searchString);\n\n\t_lstSoldiers->clearList();\n\t_indices.clear();\n\n\tint index = -1;\n\tfor (std::vector<Soldier *>::reverse_iterator i = _game->getSavedGame()->getDeadSoldiers()->rbegin(); i != _game->getSavedGame()->getDeadSoldiers()->rend(); ++i)\n\t{\n\t\t++index;\n\t\tconst Soldier* deadSoldier = (*i);\n\n\t\t// quick search\n\t\tif (!searchString.empty())\n\t\t{\n\t\t\tstd::string soldierName = deadSoldier->getName();\n\t\t\tUnicode::upperCase(soldierName);\n\t\t\tif (soldierName.find(searchString) == std::string::npos)\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\tconst SoldierDeath *death = deadSoldier->getDeath();\n\n\t\tstd::ostringstream saveDay, saveMonth, saveYear;\n\t\tsaveDay << death->getTime()->getDayString(_game->getLanguage());\n\t\tsaveMonth << tr(death->getTime()->getMonthString());\n\t\tsaveYear << death->getTime()->getYear();\n\t\t_lstSoldiers->addRow(5, deadSoldier->getName().c_str(), tr(deadSoldier->getRankString()).c_str(), saveDay.str().c_str(), saveMonth.str().c_str(), saveYear.str().c_str());\n\t\t_indices.push_back(index);\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/SoldierMemorialState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass TextEdit;\nclass TextList;\n\n/**\n * Screen that shows all the soldiers\n * that have died throughout the game.\n */\nclass SoldierMemorialState : public State\n{\nprivate:\n\tTextButton *_btnOk, *_btnStatistics;\n\tTextEdit *_btnQuickSearch;\n\tWindow *_window;\n\tText *_txtTitle, *_txtName, *_txtRank, *_txtDate, *_txtRecruited, *_txtLost;\n\tTextList *_lstSoldiers;\n\tstd::vector<int> _indices;\n\tvoid fillMemorialList();\npublic:\n\t/// Creates the Soldiers state.\n\tSoldierMemorialState();\n\t/// Cleans up the Soldiers state.\n\t~SoldierMemorialState();\n\t/// Initializes the state.\n\tvoid init() override;\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handlers for Quick Search.\n\tvoid btnQuickSearchToggle(Action *action);\n\tvoid btnQuickSearchApply(Action *action);\n\t/// Handler for clicking the Statistics button.\n\tvoid btnStatisticsClick(Action *action);\n\t/// Handler for clicking the Soldiers list.\n\tvoid lstSoldiersClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/SoldierRankState.cpp",
    "content": "﻿/*\n * Copyright 2010-2023 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"SoldierRankState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Interface/Window.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleSoldier.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/RankCount.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Soldier.h\"\n#include \"../Ufopaedia/Ufopaedia.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Soldier Rank window.\n * @param base Pointer to the base to get info from.\n * @param soldierId ID of the selected soldier.\n */\nSoldierRankState::SoldierRankState(Base* base, size_t soldierId) : _base(base), _soldierId(soldierId)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 192, 160, 64, 20, POPUP_BOTH);\n\t_btnCancel = new TextButton(140, 16, 90, 156);\n\t_txtTitle = new Text(182, 17, 69, 28);\n\t_txtRank = new Text(90, 9, 80, 52);\n\t_txtOpening = new Text(70, 9, 190, 52);\n\t_lstRanks = new TextList(160, 80, 73, 68);\n\n\t// Set palette\n\tsetInterface(\"soldierRank\");\n\n\tadd(_window, \"window\", \"soldierRank\");\n\tadd(_btnCancel, \"button\", \"soldierRank\");\n\tadd(_txtTitle, \"text\", \"soldierRank\");\n\tadd(_txtRank, \"text\", \"soldierRank\");\n\tadd(_txtOpening, \"text\", \"soldierRank\");\n\tadd(_lstRanks, \"list\", \"soldierRank\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"soldierRank\");\n\n\t_btnCancel->setText(tr(\"STR_CANCEL_UC\"));\n\t_btnCancel->onMouseClick((ActionHandler)&SoldierRankState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&SoldierRankState::btnCancelClick, Options::keyCancel);\n\n\tSoldier *soldier = _base->getSoldiers()->at(_soldierId);\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_PROMOTE_SOLDIER\").arg(tr(soldier->getRankString())).arg(soldier->getName()));\n\n\t_txtRank->setText(tr(\"STR_RANK_HEADER\"));\n\n\t_txtOpening->setText(tr(\"STR_OPENINGS_HEADER\"));\n\n\t_lstRanks->setColumns(2, 132, 21);\n\t_lstRanks->setSelectable(true);\n\t_lstRanks->setBackground(_window);\n\t_lstRanks->setMargin(8);\n\n\tPromotionOpenings openings = PromotionOpenings(_game->getSavedGame()->getAllActiveSoldiers(), _game->getMod());\n\n\t// a copy is unavoidable here because me may want to modify this set.\n\tstd::vector<std::string> rankStringsCopy = soldier->getRules()->getRankStrings();\n\n\t// if the rank strings is empty and the soldier is allowed promotion, build a default set of rank strings.\n\t// ideally this would be encoded in the data someplace instead of relying on this behavior for empty rank strings.\n\tif (rankStringsCopy.empty() && soldier->getRules()->getAllowPromotion())\n\t{\n\t\trankStringsCopy = { \"STR_ROOKIE\", \"STR_SQUADDIE\", \"STR_SERGEANT\", \"STR_CAPTAIN\", \"STR_COLONEL\", \"STR_COMMANDER\" };\n\t}\n\n\t// build the promotion list.\n\tfor (const auto& rank : { RANK_ROOKIE, RANK_SQUADDIE, RANK_SERGEANT, RANK_CAPTAIN, RANK_COLONEL, RANK_COMMANDER })\n\t{\n\t\tif ((size_t)rank < rankStringsCopy.size())\n\t\t{\n\t\t\t_ranks.push_back(RankItem(rank, rankStringsCopy[rank], openings[rank], openings.isManualPromotionPossible(soldier, rank)));\n\t\t}\n\t}\n\n\tfor (const auto& rankItem : _ranks)\n\t{\n\t\tconst std::string quantityText = rankItem.openings >= 0 ? std::to_string(rankItem.openings) : \"-\";\n\n\t\t_lstRanks->addRow(2, tr(rankItem.name).c_str(), quantityText.c_str());\n\n\t\tif (!rankItem.promotionAllowed)\n\t\t{\n\t\t\t// disabled\n\t\t\t_lstRanks->setCellColor(_lstRanks->getLastRowIndex(), 0, _lstRanks->getSecondaryColor());\n\t\t}\n\t}\n\n\t_lstRanks->onMouseClick((ActionHandler)&SoldierRankState::lstRankClick);\n\t_lstRanks->onMouseClick((ActionHandler)&SoldierRankState::lstRankClickMiddle, SDL_BUTTON_MIDDLE);\n}\n\n/**\n *\n */\nSoldierRankState::~SoldierRankState()\n{\n}\n\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid SoldierRankState::btnCancelClick(Action*)\n{\n\t_game->popState();\n}\n\n/**\n * Promotes/demotes the soldier if possible.\n * @param action Pointer to an action.\n */\nvoid SoldierRankState::lstRankClick(Action*)\n{\n\tconst RankItem& selectedRank = _ranks[_lstRanks->getSelectedRow()];\n\tif (selectedRank.promotionAllowed)\n\t{\n\t\tSoldier* soldier = _base->getSoldiers()->at(_soldierId);\n\t\tsoldier->setRank(selectedRank.rank);\n\n\t\t_game->popState();\n\t}\n}\n\n/**\n * Opens the corresponding Ufopaedia article.\n * @param action Pointer to an action.\n */\nvoid SoldierRankState::lstRankClickMiddle(Action* action)\n{\n\tstd::string articleId = _ranks[_lstRanks->getSelectedRow()].name;\n\tUfopaedia::openArticle(_game, articleId);\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/SoldierRankState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2023 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include \"../Savegame/Soldier.h\"\n\nnamespace OpenXcom\n{\n\nstruct RankItem\n{\n\tRankItem(SoldierRank _rank, const std::string& _name, int _openings, bool _promotionAllowed)\n\t\t: rank(_rank), name(_name), openings(_openings), promotionAllowed(_promotionAllowed)\n\t{\n\t}\n\tSoldierRank rank;\n\tstd::string name;\n\tint openings;\n\tbool promotionAllowed;\n};\n\nclass Base;\nclass Text;\nclass TextButton;\nclass TextList;\nclass Window;\n\nclass SoldierRankState : public State\n{\nprivate:\n\tBase *_base;\n\tsize_t _soldierId;\n\n\tTextButton *_btnCancel;\n\tWindow *_window;\n\tText *_txtTitle, *_txtRank, *_txtOpening;\n\tTextList *_lstRanks;\n\tstd::vector<RankItem> _ranks;\n\n  public:\n\t/// Creates the Soldier Rank state.\n\tSoldierRankState(Base* base, size_t soldier);\n\t/// Cleans up the Soldier Rank state.\n\t~SoldierRankState();\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action* action);\n\t/// Handler for left clicking the ranks list (promotes/demotes if possible).\n\tvoid lstRankClick(Action* action);\n\t/// Handler for middle clicking the ranks list (opens ufopedia article if possible).\n\tvoid lstRankClickMiddle(Action* action);\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/SoldierSortUtil.cpp",
    "content": "#include \"SoldierSortUtil.h\"\n#include \"../Mod/RuleSoldier.h\"\n\n#define GET_ATTRIB_STAT_FN(attrib) \\\n\tint OpenXcom::attrib##Stat(const Game *game, const Soldier *s) { return s->getStatsWithAllBonuses()->attrib; }\nGET_ATTRIB_STAT_FN(tu)\nGET_ATTRIB_STAT_FN(stamina)\nGET_ATTRIB_STAT_FN(health)\nGET_ATTRIB_STAT_FN(bravery)\nGET_ATTRIB_STAT_FN(reactions)\nGET_ATTRIB_STAT_FN(firing)\nGET_ATTRIB_STAT_FN(throwing)\nGET_ATTRIB_STAT_FN(strength)\nint OpenXcom::manaStat(const Game* game, const Soldier* s)\n{\n\t// don't reveal mana before it would otherwise be known\n\tif (game->getSavedGame()->isManaUnlocked(game->getMod()))\n\t{\n\t\treturn s->getStatsWithAllBonuses()->mana;\n\t}\n\treturn 0;\n}\nint OpenXcom::psiStrengthStat(const Game *game, const Soldier *s)\n{\n\t// don't reveal psi strength before it would otherwise be known\n\tif (s->getCurrentStats()->psiSkill > 0\n\t\t|| (Options::psiStrengthEval\n\t\t&& game->getSavedGame()->isResearched(game->getMod()->getPsiRequirements())))\n\t{\n\t\treturn s->getStatsWithAllBonuses()->psiStrength;\n\t}\n\treturn 0;\n}\nint OpenXcom::psiSkillStat(const Game *game, const Soldier *s)\n{\n\t// when Options::anytimePsiTraining is turned on, psiSkill can actually have a negative value\n\tif (s->getCurrentStats()->psiSkill > 0)\n\t{\n\t\treturn s->getStatsWithAllBonuses()->psiSkill;\n\t}\n\treturn 0;\n}\nGET_ATTRIB_STAT_FN(melee)\n#undef GET_ATTRIB_STAT_FN\n\n#define GET_ATTRIB_STAT_FN(attrib) \\\n\tint OpenXcom::attrib##StatBase(const Game *game, const Soldier *s) { return s->getCurrentStats()->attrib; }\nGET_ATTRIB_STAT_FN(tu)\nGET_ATTRIB_STAT_FN(stamina)\nGET_ATTRIB_STAT_FN(health)\nGET_ATTRIB_STAT_FN(bravery)\nGET_ATTRIB_STAT_FN(reactions)\nGET_ATTRIB_STAT_FN(firing)\nGET_ATTRIB_STAT_FN(throwing)\nGET_ATTRIB_STAT_FN(strength)\nint OpenXcom::manaStatBase(const Game* game, const Soldier* s)\n{\n\t// don't reveal mana before it would otherwise be known\n\tif (game->getSavedGame()->isManaUnlocked(game->getMod()))\n\t{\n\t\treturn s->getCurrentStats()->mana;\n\t}\n\treturn 0;\n}\nint OpenXcom::psiStrengthStatBase(const Game *game, const Soldier *s)\n{\n\t// don't reveal psi strength before it would otherwise be known\n\tif (s->getCurrentStats()->psiSkill > 0\n\t\t|| (Options::psiStrengthEval\n\t\t&& game->getSavedGame()->isResearched(game->getMod()->getPsiRequirements())))\n\t{\n\t\treturn s->getCurrentStats()->psiStrength;\n\t}\n\treturn 0;\n}\nint OpenXcom::psiSkillStatBase(const Game *game, const Soldier *s)\n{\n\t// when Options::anytimePsiTraining is turned on, psiSkill can actually have a negative value\n\tif (s->getCurrentStats()->psiSkill > 0)\n\t{\n\t\treturn s->getCurrentStats()->psiSkill;\n\t}\n\treturn 0;\n}\nGET_ATTRIB_STAT_FN(melee)\n#undef GET_ATTRIB_STAT_FN\n\n#define GET_ATTRIB_STAT_FN(attrib) \\\n\tint OpenXcom::attrib##StatPlus(const Game *game, const Soldier *s) { return s->getStatsWithSoldierBonusesOnly()->attrib; }\nGET_ATTRIB_STAT_FN(tu)\nGET_ATTRIB_STAT_FN(stamina)\nGET_ATTRIB_STAT_FN(health)\nGET_ATTRIB_STAT_FN(bravery)\nGET_ATTRIB_STAT_FN(reactions)\nGET_ATTRIB_STAT_FN(firing)\nGET_ATTRIB_STAT_FN(throwing)\nGET_ATTRIB_STAT_FN(strength)\nint OpenXcom::manaStatPlus(const Game* game, const Soldier* s)\n{\n\t// don't reveal mana before it would otherwise be known\n\tif (game->getSavedGame()->isManaUnlocked(game->getMod()))\n\t{\n\t\treturn s->getStatsWithSoldierBonusesOnly()->mana;\n\t}\n\treturn 0;\n}\nint OpenXcom::psiStrengthStatPlus(const Game *game, const Soldier *s)\n{\n\t// don't reveal psi strength before it would otherwise be known\n\tif (s->getCurrentStats()->psiSkill > 0\n\t\t|| (Options::psiStrengthEval\n\t\t&& game->getSavedGame()->isResearched(game->getMod()->getPsiRequirements())))\n\t{\n\t\treturn s->getStatsWithSoldierBonusesOnly()->psiStrength;\n\t}\n\treturn 0;\n}\nint OpenXcom::psiSkillStatPlus(const Game *game, const Soldier *s)\n{\n\t// when Options::anytimePsiTraining is turned on, psiSkill can actually have a negative value\n\tif (s->getCurrentStats()->psiSkill > 0)\n\t{\n\t\treturn s->getStatsWithSoldierBonusesOnly()->psiSkill;\n\t}\n\treturn 0;\n}\nGET_ATTRIB_STAT_FN(melee)\n#undef GET_ATTRIB_STAT_FN\n\n\n#define GET_SOLDIER_STAT_FN(attrib, camelCaseAttrib) \\\n\tint OpenXcom::attrib##Stat(const Game *game, const Soldier *s) { return s->get##camelCaseAttrib(); }\nGET_SOLDIER_STAT_FN(id, Id)\nint OpenXcom::nameStat(const Game *game, const Soldier *s)\n{\n\treturn 0;\n}\nint OpenXcom::craftIdStat(const Game *game, const Soldier *s)\n{\n\tif (s->getCraft())\n\t{\n\t\treturn s->getCraft()->getId();\n\t}\n\treturn 0;\n}\nint OpenXcom::typeStat(const Game *game, const Soldier *s)\n{\n\treturn s->getRules()->getListOrder();\n}\nGET_SOLDIER_STAT_FN(rank, Rank)\nGET_SOLDIER_STAT_FN(missions, Missions)\nGET_SOLDIER_STAT_FN(kills, Kills)\n//GET_SOLDIER_STAT_FN(woundRecovery, WoundRecovery)\nint OpenXcom::woundRecoveryStat(const Game *game, const Soldier *s)\n{\n\treturn s->getWoundRecovery(0.0f, 0.0f);\n}\nGET_SOLDIER_STAT_FN(manaMissing, ManaMissing)\nint OpenXcom::idleDaysStat(const Game *game, const Soldier *s)\n{\n\treturn game->getSavedGame()->getSoldierIdleDays(s);\n}\n#undef GET_SOLDIER_STAT_FN\n"
  },
  {
    "path": "src/Basescape/SoldierSortUtil.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2019 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/Game.h\"\n#include \"../Savegame/Soldier.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Mod/Mod.h\"\n\nnamespace OpenXcom\n{\n\ntypedef int (*getStatFn_t)(const Game*, const Soldier*);\n\nstruct SortFunctor\n{\n\tGame *_game;\n\tgetStatFn_t _getStatFn;\n\tSortFunctor(Game *game, getStatFn_t getStatFn) : _game(game), _getStatFn(getStatFn) { }\n\tbool operator()(Soldier *a, Soldier *b)\n\t{\n\t\tbool ret = _getStatFn(_game, a) < _getStatFn(_game, b);\n\t\treturn ret;\n\t}\n\tgetStatFn_t getGetter()\n\t{\n\t\treturn _getStatFn;\n\t}\n};\n\n#define GET_ATTRIB_STAT_FN(attrib) \\\n\tint attrib##Stat(const Game *game, const Soldier *s);\nGET_ATTRIB_STAT_FN(tu)\nGET_ATTRIB_STAT_FN(stamina)\nGET_ATTRIB_STAT_FN(health)\nGET_ATTRIB_STAT_FN(bravery)\nGET_ATTRIB_STAT_FN(reactions)\nGET_ATTRIB_STAT_FN(firing)\nGET_ATTRIB_STAT_FN(throwing)\nGET_ATTRIB_STAT_FN(strength)\nGET_ATTRIB_STAT_FN(mana)\nGET_ATTRIB_STAT_FN(psiStrength)\nGET_ATTRIB_STAT_FN(psiSkill)\nGET_ATTRIB_STAT_FN(melee)\n#undef GET_ATTRIB_STAT_FN\n\n#define GET_ATTRIB_STAT_FN(attrib) \\\n\tint attrib##StatBase(const Game *game, const Soldier *s);\nGET_ATTRIB_STAT_FN(tu)\nGET_ATTRIB_STAT_FN(stamina)\nGET_ATTRIB_STAT_FN(health)\nGET_ATTRIB_STAT_FN(bravery)\nGET_ATTRIB_STAT_FN(reactions)\nGET_ATTRIB_STAT_FN(firing)\nGET_ATTRIB_STAT_FN(throwing)\nGET_ATTRIB_STAT_FN(strength)\nGET_ATTRIB_STAT_FN(mana)\nGET_ATTRIB_STAT_FN(psiStrength)\nGET_ATTRIB_STAT_FN(psiSkill)\nGET_ATTRIB_STAT_FN(melee)\n#undef GET_ATTRIB_STAT_FN\n\n#define GET_ATTRIB_STAT_FN(attrib) \\\n\tint attrib##StatPlus(const Game *game, const Soldier *s);\nGET_ATTRIB_STAT_FN(tu)\nGET_ATTRIB_STAT_FN(stamina)\nGET_ATTRIB_STAT_FN(health)\nGET_ATTRIB_STAT_FN(bravery)\nGET_ATTRIB_STAT_FN(reactions)\nGET_ATTRIB_STAT_FN(firing)\nGET_ATTRIB_STAT_FN(throwing)\nGET_ATTRIB_STAT_FN(strength)\nGET_ATTRIB_STAT_FN(mana)\nGET_ATTRIB_STAT_FN(psiStrength)\nGET_ATTRIB_STAT_FN(psiSkill)\nGET_ATTRIB_STAT_FN(melee)\n#undef GET_ATTRIB_STAT_FN\n\n#define GET_SOLDIER_STAT_FN(attrib, camelCaseAttrib) \\\n\tint attrib##Stat(const Game *game, const Soldier *s);\nGET_SOLDIER_STAT_FN(id, Id)\nGET_SOLDIER_STAT_FN(name, Name)\nGET_SOLDIER_STAT_FN(craftId, CraftId)\nGET_SOLDIER_STAT_FN(type, Type)\nGET_SOLDIER_STAT_FN(rank, Rank)\nGET_SOLDIER_STAT_FN(missions, Missions)\nGET_SOLDIER_STAT_FN(kills, Kills)\nGET_SOLDIER_STAT_FN(woundRecovery, WoundRecovery)\nGET_SOLDIER_STAT_FN(manaMissing, ManaMissing)\nGET_SOLDIER_STAT_FN(idleDays, IdleDays)\n#undef GET_SOLDIER_STAT_FN\n\n}\n"
  },
  {
    "path": "src/Basescape/SoldierTransformState.cpp",
    "content": "/*\n * Copyright 2010-2024 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"SoldierTransformState.h\"\n#include \"SoldierTransformationState.h\"\n#include <algorithm>\n#include \"../Engine/Action.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/ArrowButton.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/TextEdit.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Interface/Window.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleSoldierTransformation.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Ufopaedia/Ufopaedia.h\"\n\nnamespace OpenXcom\n{\n\nstruct compareTransformationName\n{\n\tbool operator()(const TransformationItem& a, const TransformationItem& b) const\n\t{\n\t\treturn Unicode::naturalCompare(a.name, b.name);\n\t}\n};\n\n\n/**\n * Initializes all the elements in the Soldier Transform window.\n * @param base Pointer to the base to get info from.\n * @param soldier ID of the selected soldier.\n */\nSoldierTransformState::SoldierTransformState(Base* base, size_t soldier) : _base(base), _soldier(soldier)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 192, 160, 64, 20, POPUP_BOTH);\n\t_btnQuickSearch = new TextEdit(this, 48, 9, 80, 43);\n\t_btnCancel = new TextButton(140, 16, 90, 156);\n\t_txtTitle = new Text(182, 16, 69, 28);\n\t_txtType = new Text(90, 9, 80, 52);\n\t_lstTransformations = new TextList(160, 80, 73, 68);\n\t_sortName = new ArrowButton(ARROW_NONE, 11, 8, 80, 52);\n\n\t// Set palette\n\tsetInterface(\"soldierTransform\");\n\n\tadd(_window, \"window\", \"soldierTransform\");\n\tadd(_btnQuickSearch, \"button\", \"soldierTransform\");\n\tadd(_btnCancel, \"button\", \"soldierTransform\");\n\tadd(_txtTitle, \"text\", \"soldierTransform\");\n\tadd(_txtType, \"text\", \"soldierTransform\");\n\tadd(_lstTransformations, \"list\", \"soldierTransform\");\n\tadd(_sortName, \"text\", \"soldierTransform\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"soldierTransform\");\n\n\t_btnCancel->setText(tr(\"STR_CANCEL_UC\"));\n\t_btnCancel->onMouseClick((ActionHandler)&SoldierTransformState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&SoldierTransformState::btnCancelClick, Options::keyCancel);\n\n\tSoldier *s = _base->getSoldiers()->at(_soldier);\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_SELECT_TRANSFORMATION_FOR\").arg(s->getName()));\n\n\t_txtType->setText(tr(\"STR_TYPE\"));\n\n\t_lstTransformations->setColumns(1, 153);\n\t_lstTransformations->setSelectable(true);\n\t_lstTransformations->setBackground(_window);\n\t_lstTransformations->setMargin(8);\n\n\t_sortName->setX(_sortName->getX() + _txtType->getTextWidth() + 4);\n\t_sortName->onMouseClick((ActionHandler)&SoldierTransformState::sortNameClick);\n\n\tstd::vector<RuleSoldierTransformation*> availableTransformations;\n\t_game->getSavedGame()->getAvailableTransformations(availableTransformations, _game->getMod(), _base);\n\n\tfor (auto* trRule : availableTransformations)\n\t{\n\t\tif (!s->isEligibleForTransformation(trRule))\n\t\t\tcontinue;\n\n\t\t_transformations.push_back(TransformationItem(trRule->getName(), tr(trRule->getName())));\n\t}\n\n\t_btnQuickSearch->setText(\"\"); // redraw\n\t_btnQuickSearch->onEnter((ActionHandler)&SoldierTransformState::btnQuickSearchApply);\n\t_btnQuickSearch->setVisible(Options::oxceQuickSearchButton);\n\n\t_btnCancel->onKeyboardRelease((ActionHandler)&SoldierTransformState::btnQuickSearchToggle, Options::keyToggleQuickSearch);\n\n\t_transformationOrder = TRANSFORM_SORT_NONE;\n\tsortList();\n\n\t_lstTransformations->onMouseClick((ActionHandler)&SoldierTransformState::lstTransformationClick);\n\t_lstTransformations->onMouseClick((ActionHandler)&SoldierTransformState::lstTransformationClickMiddle, SDL_BUTTON_MIDDLE);\n}\n\n/**\n *\n */\nSoldierTransformState::~SoldierTransformState()\n{\n\n}\n\n/**\n * Updates the sorting arrows based on the current setting.\n */\nvoid SoldierTransformState::updateArrows()\n{\n\t_sortName->setShape(ARROW_NONE);\n\tswitch (_transformationOrder)\n\t{\n\tcase TRANSFORM_SORT_NAME_ASC:\n\t\t_sortName->setShape(ARROW_SMALL_UP);\n\t\tbreak;\n\tcase TRANSFORM_SORT_NAME_DESC:\n\t\t_sortName->setShape(ARROW_SMALL_DOWN);\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n}\n\n/**\n * Sorts the transformations list.\n */\nvoid SoldierTransformState::sortList()\n{\n\tupdateArrows();\n\n\tswitch (_transformationOrder)\n\t{\n\tcase TRANSFORM_SORT_NAME_ASC:\n\t\tstd::stable_sort(_transformations.begin(), _transformations.end(), compareTransformationName());\n\t\tbreak;\n\tcase TRANSFORM_SORT_NAME_DESC:\n\t\tstd::stable_sort(_transformations.rbegin(), _transformations.rend(), compareTransformationName());\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n\n\tupdateList();\n}\n\n/**\n * Updates the transformations list.\n */\nvoid SoldierTransformState::updateList()\n{\n\tstd::string searchString = _btnQuickSearch->getText();\n\tUnicode::upperCase(searchString);\n\n\t_lstTransformations->clearList();\n\t_indices.clear();\n\n\tint index = -1;\n\tfor (const auto& TransformationItem : _transformations)\n\t{\n\t\t++index;\n\n\t\t// quick search\n\t\tif (!searchString.empty())\n\t\t{\n\t\t\tstd::string trType = TransformationItem.name;\n\t\t\tUnicode::upperCase(trType);\n\t\t\tif (trType.find(searchString) == std::string::npos)\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\t_lstTransformations->addRow(1, TransformationItem.name.c_str());\n\t\t_indices.push_back(index);\n\t}\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid SoldierTransformState::btnCancelClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Quick search toggle.\n * @param action Pointer to an action.\n */\nvoid SoldierTransformState::btnQuickSearchToggle(Action* action)\n{\n\tif (_btnQuickSearch->getVisible())\n\t{\n\t\t_btnQuickSearch->setText(\"\");\n\t\t_btnQuickSearch->setVisible(false);\n\t\tbtnQuickSearchApply(action);\n\t}\n\telse\n\t{\n\t\t_btnQuickSearch->setVisible(true);\n\t\t_btnQuickSearch->setFocus(true);\n\t}\n}\n\n/**\n * Quick search.\n * @param action Pointer to an action.\n */\nvoid SoldierTransformState::btnQuickSearchApply(Action*)\n{\n\tupdateList();\n}\n\n/**\n * Opens the SoldierTransformation state.\n * @param action Pointer to an action.\n */\nvoid SoldierTransformState::lstTransformationClick(Action *)\n{\n\tstd::string trType = _transformations[_indices[_lstTransformations->getSelectedRow()]].type;\n\tRuleSoldierTransformation* transformationRule = _game->getMod()->getSoldierTransformation(trType, false);\n\n\tif (transformationRule)\n\t{\n\t\tSoldier* soldier = _base->getSoldiers()->at(_soldier);\n\n\t\t_game->popState();\n\t\t_game->pushState(new SoldierTransformationState(transformationRule, _base, soldier, nullptr));\n\t}\n}\n\n/**\n * Shows the corresponding Ufopaedia article.\n * @param action Pointer to an action.\n */\nvoid SoldierTransformState::lstTransformationClickMiddle(Action*)\n{\n\tstd::string trType = _transformations[_indices[_lstTransformations->getSelectedRow()]].type;\n\tRuleSoldierTransformation* transformationRule = _game->getMod()->getSoldierTransformation(trType, false);\n\n\tif (transformationRule)\n\t{\n\t\tUfopaedia::openArticle(_game, transformationRule->getName());\n\t}\n}\n\n/**\n * Sorts the transformations by name.\n * @param action Pointer to an action.\n */\nvoid SoldierTransformState::sortNameClick(Action*)\n{\n\t_transformationOrder = _transformationOrder == TRANSFORM_SORT_NAME_ASC ? TRANSFORM_SORT_NAME_DESC : TRANSFORM_SORT_NAME_ASC;\n\tsortList();\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/SoldierTransformState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2024 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <vector>\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass ArrowButton;\nclass Base;\nclass Text;\nclass TextButton;\nclass TextEdit;\nclass TextList;\nclass Window;\n\n/// Transformation sorting modes.\nenum TransformationSort\n{\n\tTRANSFORM_SORT_NONE,\n\tTRANSFORM_SORT_NAME_ASC,\n\tTRANSFORM_SORT_NAME_DESC,\n};\n\nstruct TransformationItem\n{\n\tTransformationItem(const std::string &_type, const std::string &_name) : type(_type), name(_name)\n\t{\n\t}\n\tstd::string type;\n\tstd::string name;\n};\n\n/**\n * Soldier Transform window that allows performing a transformation on a soldier.\n */\nclass SoldierTransformState : public State\n{\nprivate:\n\tBase *_base;\n\tsize_t _soldier;\n\n\tTextButton *_btnCancel;\n\tTextEdit *_btnQuickSearch;\n\tWindow *_window;\n\tText *_txtTitle, *_txtType;\n\tTextList *_lstTransformations;\n\tArrowButton *_sortName;\n\tstd::vector<TransformationItem> _transformations;\n\tstd::vector<int> _indices;\n\tTransformationSort _transformationOrder;\n\tvoid updateArrows();\npublic:\n\t/// Creates the Soldier Transformation state.\n\tSoldierTransformState(Base* base, size_t soldier);\n\t/// Cleans up the Soldier Transformation state.\n\t~SoldierTransformState();\n\t/// Sorts the transformations list.\n\tvoid sortList();\n\t/// Updates the transformations list.\n\tvoid updateList();\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action* action);\n\t/// Handlers for Quick Search.\n\tvoid btnQuickSearchToggle(Action* action);\n\tvoid btnQuickSearchApply(Action* action);\n\t/// Handler for clicking the transformations list.\n\tvoid lstTransformationClick(Action* action);\n\t/// Handler for clicking the transformations list.\n\tvoid lstTransformationClickMiddle(Action* action);\n\t/// Handler for clicking the Name arrow.\n\tvoid sortNameClick(Action* action);\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/SoldierTransformationListState.cpp",
    "content": "/*\n * Copyright 2010-2020 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"SoldierTransformationListState.h\"\n#include <algorithm>\n#include <climits>\n#include \"../Engine/Action.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Screen.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Interface/ComboBox.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/TextEdit.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Interface/ToggleTextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"../Mod/RuleSoldierTransformation.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/ItemContainer.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Soldier.h\"\n#include \"../Ufopaedia/Ufopaedia.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Transformations Overview screen.\n * @param base Pointer to the base to get info from.\n * @param screenActions Pointer to the list of transformations in the parent SoldiersState.\n */\nSoldierTransformationListState::SoldierTransformationListState(Base *base, ComboBox *screenActions) : _base(base), _screenActions(screenActions)\n{\n\t// Calculate once\n\t_game->getSavedGame()->getAvailableTransformations(_availableTransformations, _game->getMod(), _base);\n\n\t// Create objects\n\t_window = new Window(this, 320, 200, 0, 0);\n\t_txtTitle = new Text(310, 17, 5, 8);\n\t_cbxSoldierType = new ComboBox(this, 148, 16, 8, 30, false);\n\t_cbxSoldierStatus = new ComboBox(this, 148, 16, 164, 30, false);\n\t_btnQuickSearch = new TextEdit(this, 48, 9, 16, 48);\n\t_txtProject = new Text(140, 9, 16, 58);\n\t_txtNumber = new Text(78, 17, 160, 50);\n\t_txtSoldierNumber = new Text(78, 17, 238, 50);\n\t_lstTransformations = new TextList(288, 104, 8, 68);\n\t_btnOnlyEligible = new ToggleTextButton(148, 16, 8, 176);\n\t_btnOK = new TextButton(148, 16, 164, 176);\n\n\t// Set palette\n\tsetInterface(\"transformationList\");\n\n\tadd(_window, \"window\", \"transformationList\");\n\tadd(_txtTitle, \"text1\", \"transformationList\");\n\tadd(_btnQuickSearch, \"button\", \"transformationList\");\n\tadd(_txtProject, \"text2\", \"transformationList\");\n\tadd(_txtNumber, \"text2\", \"transformationList\");\n\tadd(_txtSoldierNumber, \"text2\", \"transformationList\");\n\tadd(_lstTransformations, \"list\", \"transformationList\");\n\tadd(_btnOnlyEligible, \"button\", \"transformationList\");\n\tadd(_btnOK, \"button\", \"transformationList\");\n\tadd(_cbxSoldierType, \"button2\", \"transformationList\");\n\tadd(_cbxSoldierStatus, \"button2\", \"transformationList\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"transformationList\");\n\n\t_btnOnlyEligible->setText(tr(\"STR_SHOW_ONLY_ELIGIBLE\"));\n\t_btnOnlyEligible->setPressed(Options::oxceBaseSoldierTransformationShowOnlyEligible);\n\t_btnOnlyEligible->onMouseClick((ActionHandler)&SoldierTransformationListState::btnOnlyEligibleClick);\n\n\t_btnOK->setText(tr(\"STR_OK\"));\n\t_btnOK->onMouseClick((ActionHandler)&SoldierTransformationListState::btnOkClick);\n\t_btnOK->onKeyboardPress((ActionHandler)&SoldierTransformationListState::btnOkClick, Options::keyCancel);\n\t_btnOK->onKeyboardPress((ActionHandler)&SoldierTransformationListState::btnOkClick, Options::keyOk);\n\n\tstd::vector<std::string> availableOptions;\n\tavailableOptions.push_back(\"STR_ALL_SOLDIER_TYPES\");\n\tfor (auto& soldierType : _game->getMod()->getSoldiersList())\n\t{\n\t\tavailableOptions.push_back(soldierType);\n\t}\n\n\t_cbxSoldierType->setOptions(availableOptions, true);\n\t_cbxSoldierType->setSelected(0);\n\t_cbxSoldierType->onChange((ActionHandler)&SoldierTransformationListState::cbxSoldierTypeChange);\n\n\tavailableOptions.clear();\n\tavailableOptions.push_back(\"STR_ALL_SOLDIERS\");\n\tavailableOptions.push_back(\"STR_HEALTHY_SOLDIERS\");\n\tavailableOptions.push_back(\"STR_WOUNDED_SOLDIERS\");\n\tavailableOptions.push_back(\"STR_DEAD_SOLDIERS\");\n\n\t_cbxSoldierStatus->setOptions(availableOptions, true);\n\t_cbxSoldierStatus->setSelected(0);\n\t_cbxSoldierStatus->onChange((ActionHandler)&SoldierTransformationListState::cbxSoldierStatusChange);\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_TRANSFORMATIONS_OVERVIEW\"));\n\n\t_txtProject->setAlign(ALIGN_LEFT);\n\t_txtProject->setText(tr(\"STR_PROJECT_NAME\"));\n\n\t_txtNumber->setAlign(ALIGN_CENTER);\n\t_txtNumber->setWordWrap(true);\n\t_txtNumber->setText(tr(\"STR_AVAILABLE_MATERIALS\"));\n\n\t_txtSoldierNumber->setAlign(ALIGN_CENTER);\n\t_txtSoldierNumber->setWordWrap(true);\n\t_txtSoldierNumber->setText(tr(\"STR_ELIGIBLE_SOLDIERS\"));\n\n\t_lstTransformations->setColumns(3, 178, 10, 78);\n\t_lstTransformations->setAlign(ALIGN_RIGHT, 1);\n\t_lstTransformations->setAlign(ALIGN_RIGHT, 2);\n\t_lstTransformations->setSelectable(true);\n\t_lstTransformations->setBackground(_window);\n\t_lstTransformations->setMargin(8);\n\t_lstTransformations->onMouseClick((ActionHandler)&SoldierTransformationListState::lstTransformationsClick);\n\t_lstTransformations->onMouseClick((ActionHandler)&SoldierTransformationListState::lstTransformationsClick, SDL_BUTTON_MIDDLE);\n\n\t_btnQuickSearch->setText(\"\"); // redraw\n\t_btnQuickSearch->onEnter((ActionHandler)&SoldierTransformationListState::btnQuickSearchApply);\n\t_btnQuickSearch->setVisible(Options::oxceQuickSearchButton);\n\n\t_btnOK->onKeyboardRelease((ActionHandler)&SoldierTransformationListState::btnQuickSearchToggle, Options::keyToggleQuickSearch);\n\n\tinitList();\n}\n\n/**\n * Cleans up dynamic state.\n */\nSoldierTransformationListState::~SoldierTransformationListState()\n{\n\n}\n\n/**\n * Inits the list.\n */\nvoid SoldierTransformationListState::initList()\n{\n\t_lstTransformations->clearList();\n\t_transformationIndices.clear();\n\n\tstd::string searchString = _btnQuickSearch->getText();\n\tUnicode::upperCase(searchString);\n\n\tint currentIndex = -1;\n\tItemContainer* itemContainer(_base->getStorageItems());\n\tfor (const auto* transformationRule : _availableTransformations)\n\t{\n\t\t++currentIndex;\n\n\t\t// quick search\n\t\tif (!searchString.empty())\n\t\t{\n\t\t\tstd::string transformationName = tr(transformationRule->getName());\n\t\t\tUnicode::upperCase(transformationName);\n\t\t\tif (transformationName.find(searchString) == std::string::npos)\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\tif (_cbxSoldierType->getSelected() > 0 &&\n\t\t\tstd::find(\n\t\t\t\ttransformationRule->getAllowedSoldierTypes().begin(),\n\t\t\t\ttransformationRule->getAllowedSoldierTypes().end(),\n\t\t\t\t_game->getMod()->getSoldiersList().at(_cbxSoldierType->getSelected() - 1)) == transformationRule->getAllowedSoldierTypes().end())\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\n\t\tswitch (_cbxSoldierStatus->getSelected())\n\t\t{\n\t\tcase 1:\n\t\t\tif (!transformationRule->isAllowingAliveSoldiers()) continue;\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\tif (!transformationRule->isAllowingWoundedSoldiers()) continue;\n\t\t\tbreak;\n\t\tcase 3:\n\t\t\tif (!transformationRule->isAllowingDeadSoldiers()) continue;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\n\t\tstd::ostringstream col1;\n\t\tstd::ostringstream col2;\n\n\t\t// supplies calculation\n\t\tint projectsPossible = 10; // max\n\t\tif (transformationRule->getCost() > 0)\n\t\t{\n\t\t\tint byFunds = _game->getSavedGame()->getFunds() / transformationRule->getCost();\n\t\t\tprojectsPossible = std::min(projectsPossible, byFunds);\n\t\t}\n\t\tfor (auto& item : transformationRule->getRequiredItems())\n\t\t{\n\t\t\tRuleItem* itemRule = _game->getMod()->getItem(item.first);\n\t\t\tprojectsPossible = std::min(projectsPossible, itemContainer->getItem(itemRule) / item.second);\n\t\t}\n\t\tif (projectsPossible <= 0)\n\t\t{\n\t\t\tcol1 << '-';\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (projectsPossible < 10)\n\t\t\t{\n\t\t\t\tcol1 << projectsPossible;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tcol1 << '+';\n\t\t\t}\n\t\t}\n\n\t\tint eligibleSoldiers = 0;\n\t\tfor (const auto* soldier : *_base->getSoldiers())\n\t\t{\n\t\t\tif (soldier->getCraft() && soldier->getCraft()->getStatus() == \"STR_OUT\")\n\t\t\t{\n\t\t\t\t// soldiers outside of the base are not eligible\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (soldier->isEligibleForTransformation(transformationRule))\n\t\t\t{\n\t\t\t\t++eligibleSoldiers;\n\t\t\t}\n\t\t}\n\t\tfor (const auto* deadMan : *_game->getSavedGame()->getDeadSoldiers())\n\t\t{\n\t\t\tif (deadMan->isEligibleForTransformation(transformationRule))\n\t\t\t{\n\t\t\t\t++eligibleSoldiers;\n\t\t\t}\n\t\t}\n\n\t\tif (eligibleSoldiers <= 0)\n\t\t{\n\t\t\tif (_btnOnlyEligible->getPressed()) continue;\n\n\t\t\tcol2 << '-';\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (eligibleSoldiers < 10)\n\t\t\t{\n\t\t\t\tcol2 << eligibleSoldiers;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tcol2 << '+';\n\t\t\t}\n\t\t}\n\n\t\t_lstTransformations->addRow(3, tr(transformationRule->getName()).c_str(), col1.str().c_str(), col2.str().c_str());\n\t\t_transformationIndices.push_back(currentIndex);\n\t}\n}\n\n/**\n * Quick search toggle.\n * @param action Pointer to an action.\n */\nvoid SoldierTransformationListState::btnQuickSearchToggle(Action *action)\n{\n\tif (_btnQuickSearch->getVisible())\n\t{\n\t\t_btnQuickSearch->setText(\"\");\n\t\t_btnQuickSearch->setVisible(false);\n\t\tbtnQuickSearchApply(action);\n\t}\n\telse\n\t{\n\t\t_btnQuickSearch->setVisible(true);\n\t\t_btnQuickSearch->setFocus(true);\n\t}\n}\n\n/**\n * Quick search.\n * @param action Pointer to an action.\n */\nvoid SoldierTransformationListState::btnQuickSearchApply(Action *)\n{\n\tinitList();\n}\n\n/**\n * Filters the list of transformations by soldier type.\n * @param action Pointer to an action\n */\nvoid SoldierTransformationListState::cbxSoldierTypeChange(Action *)\n{\n\tinitList();\n}\n\n/**\n * Filters the list of transformations by soldier status.\n * @param action Pointer to an action\n */\nvoid SoldierTransformationListState::cbxSoldierStatusChange(Action *)\n{\n\tinitList();\n}\n\n/**\n * Toggles showing transformations with eligible soldiers and all transformations.\n * @param action Pointer to an action.\n */\nvoid SoldierTransformationListState::btnOnlyEligibleClick(Action *)\n{\n\tOptions::oxceBaseSoldierTransformationShowOnlyEligible = _btnOnlyEligible->getPressed();\n\n\tinitList();\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid SoldierTransformationListState::btnOkClick(Action *)\n{\n\t_screenActions->setSelected(0);\n\t_game->popState();\n}\n\n/**\n * Selects a transformation (L-click) or shows info about a transformation (M-click).\n * @param action Pointer to an action.\n */\nvoid SoldierTransformationListState::lstTransformationsClick(Action *action)\n{\n\tint transformationIndex = _transformationIndices.at(_lstTransformations->getSelectedRow());\n\n\tif (action->getDetails()->button.button == SDL_BUTTON_MIDDLE)\n\t{\n\t\tstd::string articleId = _availableTransformations.at(transformationIndex)->getName();\n\t\tUfopaedia::openArticle(_game, articleId);\n\t\treturn;\n\t}\n\n\t_screenActions->setSelected(_screenActions->getSelected() + transformationIndex + 1);\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/SoldierTransformationListState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2020 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include <vector>\n#include \"SoldierSortUtil.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass ToggleTextButton;\nclass Window;\nclass Text;\nclass TextEdit;\nclass TextList;\nclass ComboBox;\nclass Base;\nclass RuleSoldierTransformation;\n\n/**\n * Transformations Overview screen that lets the player\n * manage all the soldier transformations in a base.\n */\nclass SoldierTransformationListState : public State\n{\nprivate:\n\tBase* _base;\n\tComboBox* _screenActions;\n\tTextButton* _btnOK;\n\tToggleTextButton* _btnOnlyEligible;\n\tWindow* _window;\n\tText* _txtTitle, * _txtProject, * _txtNumber, * _txtSoldierNumber;\n\tComboBox* _cbxSoldierType, * _cbxSoldierStatus;\n\tTextEdit* _btnQuickSearch;\n\tTextList* _lstTransformations;\n\tstd::vector<int> _transformationIndices;\n\tstd::vector<RuleSoldierTransformation*> _availableTransformations;\npublic:\n\t/// Creates the Transformations Overview state.\n\tSoldierTransformationListState(Base* base, ComboBox* screenActions);\n\t/// Cleans up the Transformations Overview state.\n\t~SoldierTransformationListState();\n\t/// Refreshes the list of transformations.\n\tvoid initList();\n\t/// Toggles the quick search.\n\tvoid btnQuickSearchToggle(Action* action);\n\t/// Applies the quick search.\n\tvoid btnQuickSearchApply(Action* action);\n\t/// Handler for changing the soldier type combo box.\n\tvoid cbxSoldierTypeChange(Action* action);\n\t/// Handler for changing the soldier status combo box.\n\tvoid cbxSoldierStatusChange(Action* action);\n\t/// Handler for toggling showing only transformations with eligible soldiers.\n\tvoid btnOnlyEligibleClick(Action* action);\n\t/// Closes the transformations overview without selecting one.\n\tvoid btnOkClick(Action* action);\n\t/// Handler for clicking the Transformations list.\n\tvoid lstTransformationsClick(Action* action);\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/SoldierTransformationState.cpp",
    "content": "/*\n * Copyright 2010-2018 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"SoldierTransformationState.h\"\n#include <sstream>\n#include <algorithm>\n#include \"../Engine/Action.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Screen.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/TextEdit.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Interface/Window.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleSoldier.h\"\n#include \"../Mod/RuleSoldierBonus.h\"\n#include \"../Mod/RuleSoldierTransformation.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/ItemContainer.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Soldier.h\"\n#include \"../Savegame/Transfer.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Soldier Transformation GUI\n * @param transformationRule Pointer to the transformation ruleset\n * @param base Pointer to the current base\n * @param sourceSoldier Pointer to the selected soldier\n * @param filteredListOfSoldiers Pointer to the list of available soldiers\n */\nSoldierTransformationState::SoldierTransformationState(RuleSoldierTransformation *transformationRule, Base *base, Soldier *sourceSoldier, std::vector<Soldier *> *filteredListOfSoldiers) :\n\t_transformationRule(transformationRule), _base(base), _sourceSoldier(sourceSoldier), _filteredListOfSoldiers(filteredListOfSoldiers)\n{\n\t_window = new Window(this, 320, 200, 0, 0);\n\t_btnCancel = new TextButton(148, 16, 8, 176);\n\t_btnStart = new TextButton(148, 16, 164, 176);\n\n\t_btnLeftArrow = new TextButton(16, 16, 8, 8);\n\t_btnRightArrow = new TextButton(16, 16, 296, 8);\n\t_edtSoldier = new TextEdit(this, 210, 16, 54, 8);\n\n\t_txtCost = new Text(290, 9, 16, 30);\n\t_txtTransferTime = new Text(290, 9, 16, 40);\n\t_txtRecoveryTime = new Text(290, 9, 16, 50);\n\n\t_txtRequiredItems = new Text(290, 9, 16, 64);\n\t_txtItemNameColumn = new Text(60, 16, 30, 72);\n\t_txtUnitRequiredColumn = new Text(60, 16, 155, 72);\n\t_txtUnitAvailableColumn = new Text(60, 16, 230, 72);\n\t_lstRequiredItems = new TextList(270, 32, 30, 88);\n\n\t_lstStatChanges = new TextList(288, 40, 16, 130);\n\n\t// Set palette\n\tsetInterface(\"soldierTransformation\");\n\n\tadd(_window, \"window\", \"soldierTransformation\");\n\tadd(_btnCancel, \"button\", \"soldierTransformation\");\n\tadd(_btnStart, \"button\", \"soldierTransformation\");\n\n\tadd(_btnLeftArrow, \"button\", \"soldierTransformation\");\n\tadd(_btnRightArrow, \"button\", \"soldierTransformation\");\n\tadd(_edtSoldier, \"text\", \"soldierTransformation\");\n\n\tadd(_txtCost, \"text\", \"soldierTransformation\");\n\tadd(_txtTransferTime, \"text\", \"soldierTransformation\");\n\tadd(_txtRecoveryTime, \"text\", \"soldierTransformation\");\n\n\tadd(_txtRequiredItems, \"text\", \"soldierTransformation\");\n\tadd(_txtItemNameColumn, \"text\", \"soldierTransformation\");\n\tadd(_txtUnitRequiredColumn, \"text\", \"soldierTransformation\");\n\tadd(_txtUnitAvailableColumn, \"text\", \"soldierTransformation\");\n\tadd(_lstRequiredItems, \"list1\", \"soldierTransformation\");\n\n\tadd(_lstStatChanges, \"list2\", \"soldierTransformation\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"soldierTransformation\");\n\n\t_btnCancel->setText(tr(\"STR_CANCEL_UC\"));\n\t_btnCancel->onMouseClick((ActionHandler)&SoldierTransformationState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&SoldierTransformationState::btnCancelClick, Options::keyCancel);\n\n\t_btnStart->setText(tr(_transformationRule->getName()));\n\t_btnStart->onMouseClick((ActionHandler)&SoldierTransformationState::btnStartClick);\n\t_btnStart->onKeyboardPress((ActionHandler)&SoldierTransformationState::btnStartClick, Options::keyOk);\n\n\tif (_filteredListOfSoldiers && _filteredListOfSoldiers->size() > 1)\n\t{\n\t\t_btnLeftArrow->setText(\"<<\");\n\t\t_btnLeftArrow->onMouseClick((ActionHandler)&SoldierTransformationState::btnLeftArrowClick);\n\t\t_btnLeftArrow->onKeyboardPress((ActionHandler)&SoldierTransformationState::btnLeftArrowClick, Options::keyGeoLeft);\n\n\t\t_btnRightArrow->setText(\">>\");\n\t\t_btnRightArrow->onMouseClick((ActionHandler)&SoldierTransformationState::btnRightArrowClick);\n\t\t_btnRightArrow->onKeyboardPress((ActionHandler)&SoldierTransformationState::btnRightArrowClick, Options::keyGeoRight);\n\t}\n\telse\n\t{\n\t\t_btnLeftArrow->setVisible(false);\n\t\t_btnRightArrow->setVisible(false);\n\t}\n\n\t_edtSoldier->setBig();\n\t_edtSoldier->setAlign(ALIGN_CENTER);\n\n\t_txtRequiredItems->setText(tr(\"STR_SPECIAL_MATERIALS_REQUIRED\"));\n\t_txtRequiredItems->setAlign(ALIGN_CENTER);\n\n\t_txtItemNameColumn->setText(tr(\"STR_ITEM_REQUIRED\"));\n\t_txtItemNameColumn->setWordWrap(true);\n\n\t_txtUnitRequiredColumn->setText(tr(\"STR_UNITS_REQUIRED\"));\n\t_txtUnitRequiredColumn->setWordWrap(true);\n\n\t_txtUnitAvailableColumn->setText(tr(\"STR_UNITS_AVAILABLE\"));\n\t_txtUnitAvailableColumn->setWordWrap(true);\n\n\t_lstRequiredItems->setColumns(3, 140, 75, 55);\n\n\tif (_game->getMod()->isManaFeatureEnabled())\n\t{\n\t\t_lstStatChanges->setColumns(14, 72, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0);\n\t}\n\telse\n\t{\n\t\t_lstStatChanges->setColumns(13, 90, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0);\n\t}\n\t_lstStatChanges->setAlign(ALIGN_RIGHT);\n\t_lstStatChanges->setAlign(ALIGN_LEFT, 0);\n\n\tinitTransformationData();\n}\n\n/**\n * cleans up dynamic state\n */\nSoldierTransformationState::~SoldierTransformationState()\n{\n\n}\n\n/**\n * Creates a string for the soldier stats table\n */\nstd::string SoldierTransformationState::formatStat(int stat, bool plus, bool hide)\n{\n\tif (hide) return \"\\x01?\\x01\"; //Unicode::TOK_COLOR_FLIP\n\tif (stat == 0) return \"\";\n\n\tstd::ostringstream ss;\n\tss << Unicode::TOK_COLOR_FLIP;\n\tif (plus && stat > 0) ss << '+';\n\tss << stat << Unicode::TOK_COLOR_FLIP;\n\treturn ss.str();\n}\n\n/**\n * Sets all the values for the data fields on the screen\n */\nvoid SoldierTransformationState::initTransformationData()\n{\n\t_edtSoldier->setText(_sourceSoldier->getName());\n\n\t_lstRequiredItems->clearList();\n\t_lstStatChanges->clearList();\n\n\tbool transformationPossible = _game->getSavedGame()->getFunds() >= _transformationRule->getCost();\n\n\tif (_base->getAvailableQuarters() <= _base->getUsedQuarters() &&\n\t\t(_transformationRule->isCreatingClone() ||\n\t\t(_transformationRule->isAllowingDeadSoldiers() && _sourceSoldier->getDeath())))\n\t{\n\t\ttransformationPossible = false;\n\t}\n\n\t_txtCost->setText(tr(\"STR_COST_\").arg(Unicode::formatFunding(_transformationRule->getCost())));\n\n\tint transferTime = 0;\n\tif (!Mod::isEmptyRuleName(_transformationRule->getProducedItem()))\n\t{\n\t\ttransferTime = _transformationRule->getTransferTime() > 0 ? _transformationRule->getTransferTime() : 1;\n\t}\n\telse if (_transformationRule->getTransferTime() > 0 || _transformationRule->isCreatingClone() || _sourceSoldier->getDeath())\n\t{\n\t\ttransferTime = _transformationRule->getTransferTime() > 0 ? _transformationRule->getTransferTime() : 24;\n\t}\n\t_txtTransferTime->setText(tr(\"STR_TRANSFER_TIME\").arg(tr(\"STR_HOUR\", transferTime)));\n\t_txtRecoveryTime->setText(tr(\"STR_RECOVERY_TIME\").arg(tr(\"STR_DAY\", _transformationRule->getRecoveryTime())));\n\n\tint row = 0;\n\tfor (auto& requiredItem : _transformationRule->getRequiredItems())\n\t{\n\t\tstd::ostringstream s1, s2;\n\t\ts1 << requiredItem.second;\n\t\tconst auto* rule = _game->getMod()->getItem(requiredItem.first);\n\t\tif (rule != 0)\n\t\t{\n\t\t\ts2 << _base->getStorageItems()->getItem(rule);\n\t\t\ttransformationPossible &= (_base->getStorageItems()->getItem(rule) >= requiredItem.second);\n\t\t}\n\n\t\t_lstRequiredItems->addRow(3, tr(requiredItem.first).c_str(), s1.str().c_str(), s2.str().c_str());\n\t\t_lstRequiredItems->setCellColor(row, 1, _lstRequiredItems->getSecondaryColor());\n\t\t_lstRequiredItems->setCellColor(row, 2, _lstRequiredItems->getSecondaryColor());\n\t\trow++;\n\t}\n\n\t_btnStart->setVisible(transformationPossible);\n\n\tif (!Mod::isEmptyRuleName(_transformationRule->getProducedItem()))\n\t{\n\t\t_txtRecoveryTime->setVisible(false);\n\n\t\t// no need to show the rest, the soldier will be removed from existence after this project\n\t\treturn;\n\t}\n\n\tUnitStats currentStats = *_sourceSoldier->getCurrentStats();\n\tUnitStats changedStatsMin = _sourceSoldier->calculateStatChanges(_game->getMod(), _transformationRule, _sourceSoldier, 1, _sourceSoldier->getRules());\n\tUnitStats changedStatsMax = _sourceSoldier->calculateStatChanges(_game->getMod(), _transformationRule, _sourceSoldier, 2, _sourceSoldier->getRules());\n\tUnitStats bonusStats;\n\tauto* bonusRule = _game->getMod()->getSoldierBonus(_transformationRule->getSoldierBonusType(), false);\n\tif (bonusRule)\n\t{\n\t\tbonusStats += *bonusRule->getStats();\n\t}\n\n\tbool showPsiSkill = currentStats.psiSkill > 0;\n\tbool showPsiStrength = showPsiSkill || (Options::psiStrengthEval && _game->getSavedGame()->isResearched(_game->getMod()->getPsiRequirements()));\n\n\tUnitStats rerollFlags = _transformationRule->getRerollStats();\n\n\tUnitStats randomFlags;\n\tbool twoRows = _transformationRule->getShowMinMax();\n\tif (!twoRows)\n\t{\n\t\trandomFlags += UnitStats::isRandom(_transformationRule->getFlatMin(), _transformationRule->getFlatMax());\n\t\trandomFlags += UnitStats::isRandom(_transformationRule->getPercentMin(), _transformationRule->getPercentMax());\n\t\trandomFlags += UnitStats::isRandom(_transformationRule->getPercentGainedMin(), _transformationRule->getPercentGainedMax());\n\t}\n\n\tif (_game->getMod()->isManaFeatureEnabled())\n\t{\n\t\tbool showMana = _game->getSavedGame()->isManaUnlocked(_game->getMod());\n\n\t\t_lstStatChanges->addRow(14, \"\",\n\t\t\ttr(\"STR_TIME_UNITS_ABBREVIATION\").c_str(),\n\t\t\ttr(\"STR_STAMINA_ABBREVIATION\").c_str(),\n\t\t\ttr(\"STR_HEALTH_ABBREVIATION\").c_str(),\n\t\t\ttr(\"STR_BRAVERY_ABBREVIATION\").c_str(),\n\t\t\ttr(\"STR_REACTIONS_ABBREVIATION\").c_str(),\n\t\t\ttr(\"STR_FIRING_ACCURACY_ABBREVIATION\").c_str(),\n\t\t\ttr(\"STR_THROWING_ACCURACY_ABBREVIATION\").c_str(),\n\t\t\ttr(\"STR_MELEE_ACCURACY_ABBREVIATION\").c_str(),\n\t\t\ttr(\"STR_STRENGTH_ABBREVIATION\").c_str(),\n\t\t\ttr(\"STR_MANA_ABBREVIATION\").c_str(),\n\t\t\ttr(\"STR_PSIONIC_STRENGTH_ABBREVIATION\").c_str(),\n\t\t\ttr(\"STR_PSIONIC_SKILL_ABBREVIATION\").c_str(),\n\t\t\t\"\");\n\t\t_lstStatChanges->addRow(14, tr(\"STR_CURRENT_STATS\").c_str(),\n\t\t\tformatStat(currentStats.tu, false, false).c_str(),\n\t\t\tformatStat(currentStats.stamina, false, false).c_str(),\n\t\t\tformatStat(currentStats.health, false, false).c_str(),\n\t\t\tformatStat(currentStats.bravery, false, false).c_str(),\n\t\t\tformatStat(currentStats.reactions, false, false).c_str(),\n\t\t\tformatStat(currentStats.firing, false, false).c_str(),\n\t\t\tformatStat(currentStats.throwing, false, false).c_str(),\n\t\t\tformatStat(currentStats.melee, false, false).c_str(),\n\t\t\tformatStat(currentStats.strength, false, false).c_str(),\n\t\t\tformatStat(currentStats.mana, false, !showMana).c_str(),\n\t\t\tformatStat(currentStats.psiStrength, false, !showPsiStrength).c_str(),\n\t\t\tformatStat(currentStats.psiSkill, false, !showPsiSkill).c_str(),\n\t\t\t\"\");\n\t\t_lstStatChanges->addRow(14, tr(twoRows ? \"STR_CHANGES_MIN\" : \"STR_CHANGES\").c_str(),\n\t\t\tformatStat(changedStatsMin.tu, true, rerollFlags.tu || randomFlags.tu).c_str(),\n\t\t\tformatStat(changedStatsMin.stamina, true, rerollFlags.stamina || randomFlags.stamina).c_str(),\n\t\t\tformatStat(changedStatsMin.health, true, rerollFlags.health || randomFlags.health).c_str(),\n\t\t\tformatStat(changedStatsMin.bravery, true, rerollFlags.bravery || randomFlags.bravery).c_str(),\n\t\t\tformatStat(changedStatsMin.reactions, true, rerollFlags.reactions || randomFlags.reactions).c_str(),\n\t\t\tformatStat(changedStatsMin.firing, true, rerollFlags.firing || randomFlags.firing).c_str(),\n\t\t\tformatStat(changedStatsMin.throwing, true, rerollFlags.throwing || randomFlags.throwing).c_str(),\n\t\t\tformatStat(changedStatsMin.melee, true, rerollFlags.melee || randomFlags.melee).c_str(),\n\t\t\tformatStat(changedStatsMin.strength, true, rerollFlags.strength || randomFlags.strength).c_str(),\n\t\t\tformatStat(changedStatsMin.mana, true, !showMana || rerollFlags.mana || randomFlags.mana).c_str(),\n\t\t\tformatStat(changedStatsMin.psiStrength, true, !showPsiStrength || rerollFlags.psiStrength || randomFlags.psiStrength).c_str(),\n\t\t\tformatStat(changedStatsMin.psiSkill, true, !showPsiSkill || rerollFlags.psiSkill || randomFlags.psiSkill).c_str(),\n\t\t\t\"\");\n\t\tif (twoRows)\n\t\t{\n\t\t\t_lstStatChanges->addRow(14, tr(\"STR_CHANGES_MAX\").c_str(),\n\t\t\t\tformatStat(changedStatsMax.tu, true, rerollFlags.tu).c_str(),\n\t\t\t\tformatStat(changedStatsMax.stamina, true, rerollFlags.stamina).c_str(),\n\t\t\t\tformatStat(changedStatsMax.health, true, rerollFlags.health).c_str(),\n\t\t\t\tformatStat(changedStatsMax.bravery, true, rerollFlags.bravery).c_str(),\n\t\t\t\tformatStat(changedStatsMax.reactions, true, rerollFlags.reactions).c_str(),\n\t\t\t\tformatStat(changedStatsMax.firing, true, rerollFlags.firing).c_str(),\n\t\t\t\tformatStat(changedStatsMax.throwing, true, rerollFlags.throwing).c_str(),\n\t\t\t\tformatStat(changedStatsMax.melee, true, rerollFlags.melee).c_str(),\n\t\t\t\tformatStat(changedStatsMax.strength, true, rerollFlags.strength).c_str(),\n\t\t\t\tformatStat(changedStatsMax.mana, true, !showMana || rerollFlags.mana).c_str(),\n\t\t\t\tformatStat(changedStatsMax.psiStrength, true, !showPsiStrength || rerollFlags.psiStrength).c_str(),\n\t\t\t\tformatStat(changedStatsMax.psiSkill, true, !showPsiSkill || rerollFlags.psiSkill).c_str(),\n\t\t\t\t\"\");\n\t\t}\n\t\tif (bonusRule)\n\t\t{\n\t\t\t_lstStatChanges->addRow(14, tr(\"STR_BONUS_STATS\").c_str(),\n\t\t\t\tformatStat(bonusStats.tu, true, false).c_str(),\n\t\t\t\tformatStat(bonusStats.stamina, true, false).c_str(),\n\t\t\t\tformatStat(bonusStats.health, true, false).c_str(),\n\t\t\t\tformatStat(bonusStats.bravery, true, false).c_str(),\n\t\t\t\tformatStat(bonusStats.reactions, true, false).c_str(),\n\t\t\t\tformatStat(bonusStats.firing, true, false).c_str(),\n\t\t\t\tformatStat(bonusStats.throwing, true, false).c_str(),\n\t\t\t\tformatStat(bonusStats.melee, true, false).c_str(),\n\t\t\t\tformatStat(bonusStats.strength, true, false).c_str(),\n\t\t\t\tformatStat(bonusStats.mana, true, false).c_str(),\n\t\t\t\tformatStat(bonusStats.psiStrength, true, false).c_str(),\n\t\t\t\tformatStat(bonusStats.psiSkill, true, false).c_str(),\n\t\t\t\t\"\");\n\t\t}\n\t}\n\telse\n\t{\n\t\t_lstStatChanges->addRow(13, \"\",\n\t\t\ttr(\"STR_TIME_UNITS_ABBREVIATION\").c_str(),\n\t\t\ttr(\"STR_STAMINA_ABBREVIATION\").c_str(),\n\t\t\ttr(\"STR_HEALTH_ABBREVIATION\").c_str(),\n\t\t\ttr(\"STR_BRAVERY_ABBREVIATION\").c_str(),\n\t\t\ttr(\"STR_REACTIONS_ABBREVIATION\").c_str(),\n\t\t\ttr(\"STR_FIRING_ACCURACY_ABBREVIATION\").c_str(),\n\t\t\ttr(\"STR_THROWING_ACCURACY_ABBREVIATION\").c_str(),\n\t\t\ttr(\"STR_MELEE_ACCURACY_ABBREVIATION\").c_str(),\n\t\t\ttr(\"STR_STRENGTH_ABBREVIATION\").c_str(),\n\t\t\ttr(\"STR_PSIONIC_STRENGTH_ABBREVIATION\").c_str(),\n\t\t\ttr(\"STR_PSIONIC_SKILL_ABBREVIATION\").c_str(),\n\t\t\t\"\");\n\t\t_lstStatChanges->addRow(13, tr(\"STR_CURRENT_STATS\").c_str(),\n\t\t\tformatStat(currentStats.tu, false, false).c_str(),\n\t\t\tformatStat(currentStats.stamina, false, false).c_str(),\n\t\t\tformatStat(currentStats.health, false, false).c_str(),\n\t\t\tformatStat(currentStats.bravery, false, false).c_str(),\n\t\t\tformatStat(currentStats.reactions, false, false).c_str(),\n\t\t\tformatStat(currentStats.firing, false, false).c_str(),\n\t\t\tformatStat(currentStats.throwing, false, false).c_str(),\n\t\t\tformatStat(currentStats.melee, false, false).c_str(),\n\t\t\tformatStat(currentStats.strength, false, false).c_str(),\n\t\t\tformatStat(currentStats.psiStrength, false, !showPsiStrength).c_str(),\n\t\t\tformatStat(currentStats.psiSkill, false, !showPsiSkill).c_str(),\n\t\t\t\"\");\n\t\t_lstStatChanges->addRow(13, tr(twoRows ? \"STR_CHANGES_MIN\" : \"STR_CHANGES\").c_str(),\n\t\t\tformatStat(changedStatsMin.tu, true, rerollFlags.tu || randomFlags.tu).c_str(),\n\t\t\tformatStat(changedStatsMin.stamina, true, rerollFlags.stamina || randomFlags.stamina).c_str(),\n\t\t\tformatStat(changedStatsMin.health, true, rerollFlags.health || randomFlags.health).c_str(),\n\t\t\tformatStat(changedStatsMin.bravery, true, rerollFlags.bravery || randomFlags.bravery).c_str(),\n\t\t\tformatStat(changedStatsMin.reactions, true, rerollFlags.reactions || randomFlags.reactions).c_str(),\n\t\t\tformatStat(changedStatsMin.firing, true, rerollFlags.firing || randomFlags.firing).c_str(),\n\t\t\tformatStat(changedStatsMin.throwing, true, rerollFlags.throwing || randomFlags.throwing).c_str(),\n\t\t\tformatStat(changedStatsMin.melee, true, rerollFlags.melee || randomFlags.melee).c_str(),\n\t\t\tformatStat(changedStatsMin.strength, true, rerollFlags.strength || randomFlags.strength).c_str(),\n\t\t\tformatStat(changedStatsMin.psiStrength, true, !showPsiStrength || rerollFlags.psiStrength || randomFlags.psiStrength).c_str(),\n\t\t\tformatStat(changedStatsMin.psiSkill, true, !showPsiSkill || rerollFlags.psiSkill || randomFlags.psiSkill).c_str(),\n\t\t\t\"\");\n\t\tif (twoRows)\n\t\t{\n\t\t\t_lstStatChanges->addRow(13, tr(\"STR_CHANGES\").c_str(),\n\t\t\t\tformatStat(changedStatsMax.tu, true, rerollFlags.tu).c_str(),\n\t\t\t\tformatStat(changedStatsMax.stamina, true, rerollFlags.stamina).c_str(),\n\t\t\t\tformatStat(changedStatsMax.health, true, rerollFlags.health).c_str(),\n\t\t\t\tformatStat(changedStatsMax.bravery, true, rerollFlags.bravery).c_str(),\n\t\t\t\tformatStat(changedStatsMax.reactions, true, rerollFlags.reactions).c_str(),\n\t\t\t\tformatStat(changedStatsMax.firing, true, rerollFlags.firing).c_str(),\n\t\t\t\tformatStat(changedStatsMax.throwing, true, rerollFlags.throwing).c_str(),\n\t\t\t\tformatStat(changedStatsMax.melee, true, rerollFlags.melee).c_str(),\n\t\t\t\tformatStat(changedStatsMax.strength, true, rerollFlags.strength).c_str(),\n\t\t\t\tformatStat(changedStatsMax.psiStrength, true, !showPsiStrength || rerollFlags.psiStrength).c_str(),\n\t\t\t\tformatStat(changedStatsMax.psiSkill, true, !showPsiSkill || rerollFlags.psiSkill).c_str(),\n\t\t\t\t\"\");\n\t\t}\n\t\tif (bonusRule)\n\t\t{\n\t\t\t_lstStatChanges->addRow(13, tr(\"STR_BONUS_STATS\").c_str(),\n\t\t\t\tformatStat(bonusStats.tu, true, false).c_str(),\n\t\t\t\tformatStat(bonusStats.stamina, true, false).c_str(),\n\t\t\t\tformatStat(bonusStats.health, true, false).c_str(),\n\t\t\t\tformatStat(bonusStats.bravery, true, false).c_str(),\n\t\t\t\tformatStat(bonusStats.reactions, true, false).c_str(),\n\t\t\t\tformatStat(bonusStats.firing, true, false).c_str(),\n\t\t\t\tformatStat(bonusStats.throwing, true, false).c_str(),\n\t\t\t\tformatStat(bonusStats.melee, true, false).c_str(),\n\t\t\t\tformatStat(bonusStats.strength, true, false).c_str(),\n\t\t\t\tformatStat(bonusStats.psiStrength, true, false).c_str(),\n\t\t\t\tformatStat(bonusStats.psiSkill, true, false).c_str(),\n\t\t\t\t\"\");\n\t\t}\n\t}\n}\n\n/**\n * Returns to previous screen.\n * @param action A pointer to an Action.\n */\nvoid SoldierTransformationState::btnCancelClick(Action *action)\n{\n\t_game->popState();\n}\n\n/**\n * Performs the selected transformation on the selected soldier\n * @param action A pointer to an Action.\n */\nvoid SoldierTransformationState::btnStartClick(Action *action)\n{\n\t// Pay upfront, no refunds\n\t_game->getSavedGame()->setFunds(_game->getSavedGame()->getFunds() - _transformationRule->getCost());\n\n\tfor (auto& requiredItem : _transformationRule->getRequiredItems())\n\t{\n\t\tconst auto* rule = _game->getMod()->getItem(requiredItem.first);\n\t\tif (rule != 0)\n\t\t{\n\t\t\t_base->getStorageItems()->removeItem(rule, requiredItem.second);\n\t\t}\n\t}\n\n\t// Generate an event (side effect)\n\tconst std::string choice = _transformationRule->chooseEvent();\n\tif (!choice.empty())\n\t{\n\t\tRuleEvent* eventToSpawn = _game->getMod()->getEvent(choice, false);\n\t\tif (eventToSpawn)\n\t\t{\n\t\t\t_game->getSavedGame()->spawnEvent(eventToSpawn);\n\t\t}\n\t}\n\n\t// Here we go\n\tif (!Mod::isEmptyRuleName(_transformationRule->getProducedItem()))\n\t{\n\t\tretire();\n\t}\n\telse\n\t{\n\t\tperformTransformation();\n\t}\n\n\t_game->popState();\n}\n\nvoid SoldierTransformationState::performTransformation()\n{\n\tSoldier *destinationSoldier = 0;\n\n\tif (_transformationRule->isCreatingClone())\n\t{\n\t\tint newId = _game->getSavedGame()->getId(\"STR_SOLDIER\");\n\t\tRuleSoldier *newSoldierType = _game->getMod()->getSoldier(_sourceSoldier->getRules()->getType());\n\t\tif (!Mod::isEmptyRuleName(_transformationRule->getProducedSoldierType()))\n\t\t{\n\t\t\tnewSoldierType = _game->getMod()->getSoldier(_transformationRule->getProducedSoldierType());\n\t\t}\n\t\tdestinationSoldier = new Soldier(\n\t\t\tnewSoldierType,\n\t\t\tnewSoldierType->getDefaultArmor(),\n\t\t\t_sourceSoldier->getNationality(), // try to preserve nationality if possible\n\t\t\tnewId);\n\n\t\t// copy stuff that is not influenced by transformation ruleset\n\t\tdestinationSoldier->setGender(_sourceSoldier->getGender());\n\t\tdestinationSoldier->setLook(_sourceSoldier->getLook());\n\t\tdestinationSoldier->setLookVariant(_sourceSoldier->getLookVariant());\n\n\t\t// preserve nationality only for soldiers of the same type\n\t\tif (_sourceSoldier->getRules() == newSoldierType)\n\t\t{\n\t\t\tdestinationSoldier->setNationality(_sourceSoldier->getNationality());\n\t\t}\n\n\t\t// allow easy name handling when cloning (e.g. John Doe III => John Doe IV)\n\t\tdestinationSoldier->setName(_edtSoldier->getText());\n\t}\n\telse\n\t{\n\t\tdestinationSoldier = _sourceSoldier;\n\n\t\t// some players want to rename soldiers too\n\t\tdestinationSoldier->setName(_edtSoldier->getText());\n\n\t\tif (_sourceSoldier->getDeath())\n\t\t{\n\t\t\t// true resurrect = remove from Memorial Wall\n\t\t\tauto it = find(_game->getSavedGame()->getDeadSoldiers()->begin(), _game->getSavedGame()->getDeadSoldiers()->end(), _sourceSoldier);\n\t\t\tif (it != _game->getSavedGame()->getDeadSoldiers()->end())\n\t\t\t{\n\t\t\t\t_game->getSavedGame()->getDeadSoldiers()->erase(it);\n\t\t\t}\n\t\t}\n\t\telse if (_transformationRule->getTransferTime() > 0)\n\t\t{\n\t\t\t// transfer time on a live soldier already at the base (doesn't make much sense, but we need to handle it anyway)\n\t\t\tauto it = find(_base->getSoldiers()->begin(), _base->getSoldiers()->end(), _sourceSoldier);\n\t\t\tif (it != _base->getSoldiers()->end())\n\t\t\t{\n\t\t\t\t_base->getSoldiers()->erase(it);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (_transformationRule->getTransferTime() > 0 || _transformationRule->isCreatingClone() || _sourceSoldier->getDeath())\n\t{\n\t\t// handle training (transfer rules)\n\t\tdestinationSoldier->setPsiTraining(false);\n\t\tif (destinationSoldier->isInTraining())\n\t\t{\n\t\t\tdestinationSoldier->setReturnToTrainingWhenHealed(true);\n\t\t}\n\t\tdestinationSoldier->setTraining(false);\n\n\t\tint transferTime = _transformationRule->getTransferTime() > 0 ? _transformationRule->getTransferTime() : 24;\n\t\tTransfer *transfer = new Transfer(transferTime);\n\t\ttransfer->setSoldier(destinationSoldier);\n\t\t_base->getTransfers()->push_back(transfer);\n\t}\n\n\tdestinationSoldier->transform(_game->getMod(), _transformationRule, _sourceSoldier, _base);\n}\n\nvoid SoldierTransformationState::retire()\n{\n\t// remove the soldier from existence\n\t{\n\t\tif (_sourceSoldier->getDeath())\n\t\t{\n\t\t\t// I wonder if anyone will ever use THIS option\n\t\t\tauto it = find(_game->getSavedGame()->getDeadSoldiers()->begin(), _game->getSavedGame()->getDeadSoldiers()->end(), _sourceSoldier);\n\t\t\tif (it != _game->getSavedGame()->getDeadSoldiers()->end())\n\t\t\t{\n\t\t\t\tdelete (*it);\n\t\t\t\t_game->getSavedGame()->getDeadSoldiers()->erase(it);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tauto it = find(_base->getSoldiers()->begin(), _base->getSoldiers()->end(), _sourceSoldier);\n\t\t\tif (it != _base->getSoldiers()->end())\n\t\t\t{\n\t\t\t\tdelete (*it);\n\t\t\t\t_base->getSoldiers()->erase(it);\n\t\t\t}\n\t\t}\n\t}\n\n\t// create the item\n\t{\n\t\tint transferTime = _transformationRule->getTransferTime() > 0 ? _transformationRule->getTransferTime() : 1;\n\t\tTransfer *transfer = new Transfer(transferTime);\n\t\ttransfer->setItems(_game->getMod()->getItem(_transformationRule->getProducedItem(), true), 1);\n\t\t_base->getTransfers()->push_back(transfer);\n\t}\n}\n\n/**\n * Handles pressing the Left arrow button\n * @param action A pointer to an Action.\n */\nvoid SoldierTransformationState::btnLeftArrowClick(Action *action)\n{\n\tauto iter = find(_filteredListOfSoldiers->begin(), _filteredListOfSoldiers->end(), _sourceSoldier);\n\tif (iter == _filteredListOfSoldiers->begin())\n\t{\n\t\titer = _filteredListOfSoldiers->end();\n\t}\n\n\t--iter;\n\t_sourceSoldier = *iter;\n\tinitTransformationData();\n}\n\n/**\n * Handles pressing the Right arrow button\n * @param action A pointer to an Action.\n */\nvoid SoldierTransformationState::btnRightArrowClick(Action *action)\n{\n\tauto iter = find(_filteredListOfSoldiers->begin(), _filteredListOfSoldiers->end(), _sourceSoldier);\n\tif (iter == _filteredListOfSoldiers->end() - 1)\n\t{\n\t\titer = _filteredListOfSoldiers->begin();\n\t}\n\telse\n\t{\n\t\t++iter;\n\t}\n\n\t_sourceSoldier = *iter;\n\tinitTransformationData();\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/SoldierTransformationState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2018 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include <vector>\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass TextEdit;\nclass TextList;\nclass Base;\nclass Soldier;\nclass RuleSoldierTransformation;\n\n/**\n * Screen that allocates a soldier to a transformation project\n */\nclass SoldierTransformationState : public State\n{\nprivate:\n\tRuleSoldierTransformation *_transformationRule;\n\tBase *_base;\n\tSoldier *_sourceSoldier;\n\tstd::vector<Soldier *> *_filteredListOfSoldiers;\n\tWindow *_window;\n\tTextEdit *_edtSoldier;\n\tText *_txtCost, *_txtTransferTime, *_txtRecoveryTime, *_txtRequiredItems, *_txtItemNameColumn, *_txtUnitRequiredColumn, *_txtUnitAvailableColumn;\n\tTextList *_lstRequiredItems, *_lstStatChanges;\n\tTextButton *_btnCancel, *_btnLeftArrow, *_btnRightArrow, *_btnStart;\n\n\t/// Creates a string for the soldier stats table\n\tstd::string formatStat(int stat, bool plus, bool hide);\n\npublic:\n\t/// Creates the soldier transformation state\n\tSoldierTransformationState(RuleSoldierTransformation *transformationRule, Base *base, Soldier *selectedSoldier, std::vector<Soldier *> *filteredListOfSoldiers);\n\t/// Cleans up the soldier transformation state\n\t~SoldierTransformationState();\n\t/// Initialize all the values in the data fields\n\tvoid initTransformationData();\n\t/// Handler for pressing the Cancel button\n\tvoid btnCancelClick(Action *action);\n\t/// Handler for pressing the Start button\n\tvoid btnStartClick(Action *action);\n\tvoid performTransformation();\n\tvoid retire();\n\t/// Handler for pressing the Left arrow button\n\tvoid btnLeftArrowClick(Action *action);\n\t/// Handler for pressing the Right arrow button\n\tvoid btnRightArrowClick(Action *action);\n\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/SoldiersState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"SoldiersState.h\"\n#include <climits>\n#include \"../Engine/Screen.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleSoldierTransformation.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/ComboBox.h\"\n#include \"../Engine/Action.h\"\n#include \"../Geoscape/AllocatePsiTrainingState.h\"\n#include \"../Geoscape/AllocateTrainingState.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/BattleUnit.h\"\n#include \"../Savegame/Soldier.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"SoldierInfoState.h\"\n#include \"SoldierMemorialState.h\"\n#include \"SoldierTransformationState.h\"\n#include \"SoldierTransformationListState.h\"\n#include \"../Battlescape/InventoryState.h\"\n#include \"../Battlescape/BattlescapeGenerator.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include <algorithm>\n#include \"../Engine/Unicode.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Soldiers screen.\n * @param game Pointer to the core game.\n * @param base Pointer to the base to get info from.\n */\nSoldiersState::SoldiersState(Base *base) : _base(base), _origSoldierOrder(*_base->getSoldiers()), _dynGetter(NULL), _mainOffset(0)\n{\n\tbool isPsiBtnVisible = Options::anytimePsiTraining && _base->getAvailablePsiLabs() > 0;\n\tbool isTrnBtnVisible = _base->getAvailableTraining() > 0;\n\tstd::vector<RuleSoldierTransformation* > availableTransformations;\n\t_game->getSavedGame()->getAvailableTransformations(availableTransformations, _game->getMod(), _base);\n\tbool isTransformationAvailable = availableTransformations.size() > 0;\n\n\t// if both training buttons would be displayed, or if there are any transformations, switch to combobox\n\tbool showCombobox = isTransformationAvailable || (isPsiBtnVisible && isTrnBtnVisible) || Options::oxceAlternateCraftEquipmentManagement;\n\t// 3 buttons or 2 buttons?\n\tbool showThreeButtons = !showCombobox && (isPsiBtnVisible || isTrnBtnVisible);\n\n\t// Create objects\n\t_window = new Window(this, 320, 200, 0, 0);\n\tif (showThreeButtons)\n\t{\n\t\t_btnOk = preAdd(new TextButton(96, 16, 216, 176));\n\t\t_btnMemorial = preAdd(new TextButton(96, 16, 8, 176));\n\t}\n\telse\n\t{\n\t\t_btnOk = preAdd(new TextButton(148, 16, 164, 176));\n\t\t_btnMemorial = preAdd(new TextButton(148, 16, 8, 176));\n\t}\n\t_btnPsiTraining = preAdd(new TextButton(96, 16, 112, 176));\n\t_btnTraining = preAdd(new TextButton(96, 16, 112, 176));\n\t_cbxScreenActions = preAdd(new ComboBox(this, 148, 16, 8, 176, true));\n\t_txtTitle = new Text(168, 17, 16, 8);\n\t_cbxSortBy = new ComboBox(this, 120, 16, 192, 8, false);\n\t_txtName = new Text(114, 9, 16, 32);\n\t_txtRank = new Text(102, 9, 122, 32);\n\t_txtCraft = new Text(82, 9, 220, 32);\n\t_lstSoldiers = new TextList(288, 128, 8, 40);\n\n\t// Set palette\n\tsetInterface(\"soldierList\");\n\n\tadd(_window, \"window\", \"soldierList\");\n\tadd(_btnOk, \"button\", \"soldierList\");\n\tadd(_txtTitle, \"text1\", \"soldierList\");\n\tadd(_txtName, \"text2\", \"soldierList\");\n\tadd(_txtRank, \"text2\", \"soldierList\");\n\tadd(_txtCraft, \"text2\", \"soldierList\");\n\tadd(_lstSoldiers, \"list\", \"soldierList\");\n\tadd(_cbxSortBy, \"button\", \"soldierList\");\n\tif (showCombobox)\n\t{\n\t\tadd(_cbxScreenActions, \"button\", \"soldierList\");\n\t}\n\telse\n\t{\n\t\tadd(_btnMemorial, \"button\", \"soldierList\");\n\t\tadd(_btnPsiTraining, \"button\", \"soldierList\");\n\t\tadd(_btnTraining, \"button\", \"soldierList\");\n\t}\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"soldierList\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&SoldiersState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&SoldiersState::btnOkClick, Options::keyCancel);\n\t_btnOk->onKeyboardPress((ActionHandler)&SoldiersState::btnInventoryClick, Options::keyBattleInventory);\n\t_btnOk->onKeyboardPress((ActionHandler)&SoldiersState::btnTransformationsOverviewClick, SDLK_t);\n\n\t_btnPsiTraining->setText(tr(\"STR_PSI_TRAINING\"));\n\t_btnPsiTraining->onMouseClick((ActionHandler)&SoldiersState::btnPsiTrainingClick);\n\t_btnPsiTraining->setVisible(isPsiBtnVisible);\n\n\t_btnTraining->setText(tr(\"STR_TRAINING\"));\n\t_btnTraining->onMouseClick((ActionHandler)&SoldiersState::btnTrainingClick);\n\t_btnTraining->setVisible(isTrnBtnVisible);\n\n\t_btnMemorial->setText(tr(\"STR_MEMORIAL\"));\n\t_btnMemorial->onMouseClick((ActionHandler)&SoldiersState::btnMemorialClick);\n\n\t_availableOptions.clear();\n\tif (showCombobox)\n\t{\n\t\t_btnMemorial->setVisible(false);\n\t\t_btnPsiTraining->setVisible(false);\n\t\t_btnTraining->setVisible(false);\n\n\t\t_availableOptions.push_back(\"STR_SOLDIER_INFO\");\n\t\t_availableOptions.push_back(\"STR_MEMORIAL\");\n\t\t_availableOptions.push_back(\"STR_INVENTORY\");\n\n\t\tif (isPsiBtnVisible)\n\t\t\t_availableOptions.push_back(\"STR_PSI_TRAINING\");\n\n\t\tif (isTrnBtnVisible)\n\t\t\t_availableOptions.push_back(\"STR_TRAINING\");\n\n\t\tif (isTransformationAvailable)\n\t\t{\n\t\t\t_mainOffset = _availableOptions.size();\n\t\t\t_availableOptions.push_back(\"STR_TRANSFORMATIONS_OVERVIEW\");\n\t\t}\n\n\t\tbool refreshDeadSoldierStats = false;\n\t\tfor (const auto* transformationRule : availableTransformations)\n\t\t{\n\t\t\t_availableOptions.push_back(transformationRule->getName());\n\t\t\tif (transformationRule->isAllowingDeadSoldiers())\n\t\t\t{\n\t\t\t\trefreshDeadSoldierStats = true;\n\t\t\t}\n\t\t}\n\t\tif (refreshDeadSoldierStats)\n\t\t{\n\t\t\tfor (auto* deadMan : *_game->getSavedGame()->getDeadSoldiers())\n\t\t\t{\n\t\t\t\tdeadMan->prepareStatsWithBonuses(_game->getMod()); // refresh stats for sorting\n\t\t\t}\n\t\t}\n\n\t\t_cbxScreenActions->setOptions(_availableOptions, true);\n\t\t_cbxScreenActions->setSelected(0);\n\t\t_cbxScreenActions->onChange((ActionHandler)&SoldiersState::cbxScreenActionsChange);\n\t}\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_LEFT);\n\t_txtTitle->setText(tr(\"STR_SOLDIER_LIST\"));\n\n\t_txtName->setText(tr(\"STR_NAME_UC\"));\n\n\t_txtRank->setText(tr(\"STR_RANK\"));\n\n\t_txtCraft->setText(tr(\"STR_CRAFT\"));\n\n\t// populate sort options\n\tstd::vector<std::string> sortOptions;\n\tsortOptions.push_back(tr(\"STR_ORIGINAL_ORDER\"));\n\t_sortFunctors.push_back(NULL);\n\n#define PUSH_IN(strId, functor) \\\n\tsortOptions.push_back(tr(strId)); \\\n\t_sortFunctors.push_back(new SortFunctor(_game, functor));\n\n\tPUSH_IN(\"STR_ID\", idStat);\n\tPUSH_IN(\"STR_NAME_UC\", nameStat);\n\tPUSH_IN(\"STR_CRAFT\", craftIdStat);\n\tPUSH_IN(\"STR_SOLDIER_TYPE\", typeStat);\n\tPUSH_IN(\"STR_RANK\", rankStat);\n\tPUSH_IN(\"STR_IDLE_DAYS\", idleDaysStat);\n\tPUSH_IN(\"STR_MISSIONS2\", missionsStat);\n\tPUSH_IN(\"STR_KILLS2\", killsStat);\n\tPUSH_IN(\"STR_WOUND_RECOVERY2\", woundRecoveryStat);\n\tif (_game->getMod()->isManaFeatureEnabled() && !_game->getMod()->getReplenishManaAfterMission())\n\t{\n\t\tPUSH_IN(\"STR_MANA_MISSING\", manaMissingStat);\n\t}\n\tPUSH_IN(\"STR_TIME_UNITS\", tuStat);\n\tPUSH_IN(\"STR_STAMINA\", staminaStat);\n\tPUSH_IN(\"STR_HEALTH\", healthStat);\n\tPUSH_IN(\"STR_BRAVERY\", braveryStat);\n\tPUSH_IN(\"STR_REACTIONS\", reactionsStat);\n\tPUSH_IN(\"STR_FIRING_ACCURACY\", firingStat);\n\tPUSH_IN(\"STR_THROWING_ACCURACY\", throwingStat);\n\tPUSH_IN(\"STR_MELEE_ACCURACY\", meleeStat);\n\tPUSH_IN(\"STR_STRENGTH\", strengthStat);\n\tif (_game->getMod()->isManaFeatureEnabled())\n\t{\n\t\t// \"unlock\" is checked later\n\t\tPUSH_IN(\"STR_MANA_POOL\", manaStat);\n\t}\n\tPUSH_IN(\"STR_PSIONIC_STRENGTH\", psiStrengthStat);\n\tPUSH_IN(\"STR_PSIONIC_SKILL\", psiSkillStat);\n\n#undef PUSH_IN\n\n\t_cbxSortBy->setOptions(sortOptions);\n\t_cbxSortBy->setSelected(0);\n\t_cbxSortBy->onChange((ActionHandler)&SoldiersState::cbxSortByChange);\n\t_cbxSortBy->setText(tr(\"STR_SORT_BY\"));\n\n\t//_lstSoldiers->setArrowColumn(188, ARROW_VERTICAL);\n\t_lstSoldiers->setColumns(3, 106, 98, 76);\n\t_lstSoldiers->setAlign(ALIGN_RIGHT, 3);\n\t_lstSoldiers->setSelectable(true);\n\t_lstSoldiers->setBackground(_window);\n\t_lstSoldiers->setMargin(8);\n\t_lstSoldiers->onLeftArrowClick((ActionHandler)&SoldiersState::lstItemsLeftArrowClick);\n\t_lstSoldiers->onRightArrowClick((ActionHandler)&SoldiersState::lstItemsRightArrowClick);\n\t_lstSoldiers->onMouseClick((ActionHandler)&SoldiersState::lstSoldiersClick);\n\t_lstSoldiers->onMouseClick((ActionHandler)&SoldiersState::lstSoldiersClick, SDL_BUTTON_RIGHT);\n\t_lstSoldiers->onMousePress((ActionHandler)&SoldiersState::lstSoldiersMousePress);\n}\n\n/**\n * cleans up dynamic state\n */\nSoldiersState::~SoldiersState()\n{\n\tfor (auto* sortFunctor : _sortFunctors)\n\t{\n\t\tdelete sortFunctor;\n\t}\n}\n\n/**\n * Sorts the soldiers list by the selected criterion\n * @param action Pointer to an action.\n */\nvoid SoldiersState::cbxSortByChange(Action *action)\n{\n\tbool ctrlPressed = _game->isCtrlPressed();\n\tsize_t selIdx = _cbxSortBy->getSelected();\n\tif (selIdx == (size_t)-1)\n\t{\n\t\treturn;\n\t}\n\n\tSortFunctor *compFunc = _sortFunctors[selIdx];\n\t_dynGetter = NULL;\n\tif (compFunc)\n\t{\n\t\tif (selIdx != 2 && selIdx != 3)\n\t\t{\n\t\t\t_dynGetter = compFunc->getGetter();\n\t\t}\n\n\t\t// if CTRL is pressed, we only want to show the dynamic column, without actual sorting\n\t\tif (!ctrlPressed)\n\t\t{\n\t\t\tif (selIdx == 2)\n\t\t\t{\n\t\t\t\tstd::stable_sort(_base->getSoldiers()->begin(), _base->getSoldiers()->end(),\n\t\t\t\t\t[](const Soldier* a, const Soldier* b)\n\t\t\t\t\t{\n\t\t\t\t\t\treturn Unicode::naturalCompare(a->getName(), b->getName());\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t}\n\t\t\telse if (selIdx == 3)\n\t\t\t{\n\t\t\t\tstd::stable_sort(_base->getSoldiers()->begin(), _base->getSoldiers()->end(),\n\t\t\t\t\t[](const Soldier* a, const Soldier* b)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (a->getCraft())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (b->getCraft())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (a->getCraft()->getRules() == b->getCraft()->getRules())\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\treturn a->getCraft()->getId() < b->getCraft()->getId();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\treturn a->getCraft()->getRules() < b->getCraft()->getRules();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\treturn true; // a < b\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn false; // b > a\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tstd::stable_sort(_base->getSoldiers()->begin(), _base->getSoldiers()->end(), *compFunc);\n\t\t\t}\n\t\t\tif (_game->isShiftPressed())\n\t\t\t{\n\t\t\t\tstd::reverse(_base->getSoldiers()->begin(), _base->getSoldiers()->end());\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\t// restore original ordering, ignoring (of course) those\n\t\t// soldiers that have been sacked since this state started\n\t\tfor (const auto* origSoldier : _origSoldierOrder)\n\t\t{\n\t\t\tauto soldierIt = std::find(_base->getSoldiers()->begin(), _base->getSoldiers()->end(), origSoldier);\n\t\t\tif (soldierIt != _base->getSoldiers()->end())\n\t\t\t{\n\t\t\t\tSoldier *s = *soldierIt;\n\t\t\t\t_base->getSoldiers()->erase(soldierIt);\n\t\t\t\t_base->getSoldiers()->insert(_base->getSoldiers()->end(), s);\n\t\t\t}\n\t\t}\n\t}\n\n\tsize_t originalScrollPos = _lstSoldiers->getScroll();\n\tinitList(originalScrollPos);\n}\n\n/**\n * Updates the soldiers list\n * after going to other screens.\n */\nvoid SoldiersState::init()\n{\n\tState::init();\n\n\t// resets the savegame when coming back from the inventory\n\t_game->getSavedGame()->setBattleGame(0);\n\t_base->setInBattlescape(false);\n\n\t_base->prepareSoldierStatsWithBonuses(); // refresh stats for sorting\n\tinitList(_lstSoldiers->getScroll());\n}\n\n/**\n * Shows the soldiers in a list at specified offset/scroll.\n */\nvoid SoldiersState::initList(size_t scrl)\n{\n\t_lstSoldiers->clearList();\n\n\t_filteredListOfSoldiers.clear();\n\t_filteredIndicesOfSoldiers.clear();\n\n\tstd::string selAction = \"STR_SOLDIER_INFO\";\n\tif (!_availableOptions.empty())\n\t{\n\t\tselAction = _availableOptions.at(_cbxScreenActions->getSelected());\n\t}\n\n\tint offset = 0;\n\tif (selAction == \"STR_SOLDIER_INFO\")\n\t{\n\t\t_lstSoldiers->setArrowColumn(188, ARROW_VERTICAL);\n\n\t\t// all soldiers in the base\n\t\t_filteredListOfSoldiers = *_base->getSoldiers();\n\t}\n\telse\n\t{\n\t\toffset = 20;\n\t\t_lstSoldiers->setArrowColumn(-1, ARROW_VERTICAL);\n\n\t\t// filtered list of soldiers eligible for transformation\n\t\tRuleSoldierTransformation *transformationRule = _game->getMod()->getSoldierTransformation(selAction);\n\t\tif (transformationRule)\n\t\t{\n\t\t\tint idx = -1;\n\t\t\tfor (auto* soldier : *_base->getSoldiers())\n\t\t\t{\n\t\t\t\tidx++;\n\t\t\t\tif (soldier->getCraft() && soldier->getCraft()->getStatus() == \"STR_OUT\")\n\t\t\t\t{\n\t\t\t\t\t// soldiers outside of the base are not eligible\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (soldier->isEligibleForTransformation(transformationRule))\n\t\t\t\t{\n\t\t\t\t\t_filteredListOfSoldiers.push_back(soldier);\n\t\t\t\t\t_filteredIndicesOfSoldiers.push_back(idx);\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (auto* deadMan : *_game->getSavedGame()->getDeadSoldiers())\n\t\t\t{\n\t\t\t\tif (deadMan->isEligibleForTransformation(transformationRule))\n\t\t\t\t{\n\t\t\t\t\t_filteredListOfSoldiers.push_back(deadMan);\n\t\t\t\t\t_filteredIndicesOfSoldiers.push_back(-1); // invalid\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (_dynGetter != NULL)\n\t{\n\t\t_lstSoldiers->setColumns(4, 106, 98 - offset, 60 + offset, 16);\n\t}\n\telse\n\t{\n\t\t_lstSoldiers->setColumns(3, 106, 98 - offset, 76 + offset);\n\t}\n\t_txtCraft->setX(_txtRank->getX() + 98 - offset);\n\n\tBaseSumDailyRecovery recovery = _base->getSumRecoveryPerDay();\n\tunsigned int row = 0;\n\tfor (const auto* soldier : _filteredListOfSoldiers)\n\t{\n\t\tstd::string craftString = soldier->getCraftString(_game->getLanguage(), recovery);\n\n\t\tif (_dynGetter != NULL)\n\t\t{\n\t\t\t// call corresponding getter\n\t\t\tint dynStat = (*_dynGetter)(_game, soldier);\n\t\t\tstd::ostringstream ss;\n\t\t\tss << dynStat;\n\t\t\t_lstSoldiers->addRow(4, soldier->getName(true).c_str(), tr(soldier->getRankString()).c_str(), craftString.c_str(), ss.str().c_str());\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_lstSoldiers->addRow(3, soldier->getName(true).c_str(), tr(soldier->getRankString()).c_str(), craftString.c_str());\n\t\t}\n\n\t\tif (soldier->getCraft() == 0)\n\t\t{\n\t\t\t_lstSoldiers->setRowColor(row, _lstSoldiers->getSecondaryColor());\n\t\t}\n\t\tif (soldier->getDeath())\n\t\t{\n\t\t\t_lstSoldiers->setRowColor(row, _txtCraft->getColor());\n\t\t}\n\t\trow++;\n\t}\n\tif (scrl)\n\t\t_lstSoldiers->scrollTo(scrl);\n\t_lstSoldiers->draw();\n}\n\n\n/**\n * Reorders a soldier up.\n * @param action Pointer to an action.\n */\nvoid SoldiersState::lstItemsLeftArrowClick(Action *action)\n{\n\tunsigned int row = _lstSoldiers->getSelectedRow();\n\tif (row > 0)\n\t{\n\t\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT)\n\t\t{\n\t\t\tmoveSoldierUp(action, row);\n\t\t}\n\t\telse if (action->getDetails()->button.button == SDL_BUTTON_RIGHT)\n\t\t{\n\t\t\tmoveSoldierUp(action, row, true);\n\t\t}\n\t}\n\t_cbxSortBy->setText(tr(\"STR_SORT_BY\"));\n\t_cbxSortBy->setSelected(-1);\n}\n\n/**\n * Moves a soldier up on the list.\n * @param action Pointer to an action.\n * @param row Selected soldier row.\n * @param max Move the soldier to the top?\n */\nvoid SoldiersState::moveSoldierUp(Action *action, unsigned int row, bool max)\n{\n\tSoldier *s = _base->getSoldiers()->at(row);\n\tif (max)\n\t{\n\t\t_base->getSoldiers()->erase(_base->getSoldiers()->begin() + row);\n\t\t_base->getSoldiers()->insert(_base->getSoldiers()->begin(), s);\n\t}\n\telse\n\t{\n\t\t_base->getSoldiers()->at(row) = _base->getSoldiers()->at(row - 1);\n\t\t_base->getSoldiers()->at(row - 1) = s;\n\t\tif (row != _lstSoldiers->getScroll())\n\t\t{\n\t\t\tSDL_WarpMouse(action->getLeftBlackBand() + action->getXMouse(), action->getTopBlackBand() + action->getYMouse() - static_cast<Uint16>(8 * action->getYScale()));\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_lstSoldiers->scrollUp(false);\n\t\t}\n\t}\n\tinitList(_lstSoldiers->getScroll());\n}\n\n/**\n * Reorders a soldier down.\n * @param action Pointer to an action.\n */\nvoid SoldiersState::lstItemsRightArrowClick(Action *action)\n{\n\tunsigned int row = _lstSoldiers->getSelectedRow();\n\tsize_t numSoldiers = _base->getSoldiers()->size();\n\tif (0 < numSoldiers && INT_MAX >= numSoldiers && row < numSoldiers - 1)\n\t{\n\t\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT)\n\t\t{\n\t\t\tmoveSoldierDown(action, row);\n\t\t}\n\t\telse if (action->getDetails()->button.button == SDL_BUTTON_RIGHT)\n\t\t{\n\t\t\tmoveSoldierDown(action, row, true);\n\t\t}\n\t}\n\t_cbxSortBy->setText(tr(\"STR_SORT_BY\"));\n\t_cbxSortBy->setSelected(-1);\n}\n\n/**\n * Moves a soldier down on the list.\n * @param action Pointer to an action.\n * @param row Selected soldier row.\n * @param max Move the soldier to the bottom?\n */\nvoid SoldiersState::moveSoldierDown(Action *action, unsigned int row, bool max)\n{\n\tSoldier *s = _base->getSoldiers()->at(row);\n\tif (max)\n\t{\n\t\t_base->getSoldiers()->erase(_base->getSoldiers()->begin() + row);\n\t\t_base->getSoldiers()->insert(_base->getSoldiers()->end(), s);\n\t}\n\telse\n\t{\n\t\t_base->getSoldiers()->at(row) = _base->getSoldiers()->at(row + 1);\n\t\t_base->getSoldiers()->at(row + 1) = s;\n\t\tif (row != _lstSoldiers->getVisibleRows() - 1 + _lstSoldiers->getScroll())\n\t\t{\n\t\t\tSDL_WarpMouse(action->getLeftBlackBand() + action->getXMouse(), action->getTopBlackBand() + action->getYMouse() + static_cast<Uint16>(8 * action->getYScale()));\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_lstSoldiers->scrollDown(false);\n\t\t}\n\t}\n\tinitList(_lstSoldiers->getScroll());\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid SoldiersState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Opens the Psionic Training screen.\n * @param action Pointer to an action.\n */\nvoid SoldiersState::btnPsiTrainingClick(Action *)\n{\n\t_game->pushState(new AllocatePsiTrainingState(_base));\n}\n\n/**\n * Opens the Martial Training screen.\n * @param action Pointer to an action.\n */\nvoid SoldiersState::btnTrainingClick(Action *)\n{\n\t_game->pushState(new AllocateTrainingState(_base));\n}\n\n/**\n * Opens the Memorial screen.\n * @param action Pointer to an action.\n */\nvoid SoldiersState::btnMemorialClick(Action *)\n{\n\t_game->pushState(new SoldierMemorialState);\n}\n\n/**\n * Opens the Transformations Overview screen.\n * @param action Pointer to an action.\n */\nvoid SoldiersState::btnTransformationsOverviewClick(Action *)\n{\n\tif (_mainOffset > 0)\n\t{\n\t\t// needed in SoldierTransformationListState::lstTransformationsClick()\n\t\t_cbxScreenActions->setSelected(_mainOffset);\n\n\t\t_game->pushState(new SoldierTransformationListState(_base, _cbxScreenActions));\n\t}\n}\n\n/**\n * Opens the selected screen from the combo box\n * @param action Pointer to an action\n */\nvoid SoldiersState::cbxScreenActionsChange(Action *action)\n{\n\tconst std::string selAction = _availableOptions.at(_cbxScreenActions->getSelected());\n\n\tif (selAction == \"STR_MEMORIAL\")\n\t{\n\t\t_cbxScreenActions->setSelected(0);\n\t\t_game->pushState(new SoldierMemorialState);\n\t}\n\telse if (selAction == \"STR_INVENTORY\")\n\t{\n\t\t_cbxScreenActions->setSelected(0);\n\t\tbtnInventoryClick(nullptr);\n\t}\n\telse if (selAction == \"STR_PSI_TRAINING\")\n\t{\n\t\t_cbxScreenActions->setSelected(0);\n\t\t_game->pushState(new AllocatePsiTrainingState(_base));\n\t}\n\telse if (selAction == \"STR_TRAINING\")\n\t{\n\t\t_cbxScreenActions->setSelected(0);\n\t\t_game->pushState(new AllocateTrainingState(_base));\n\t}\n\telse if (selAction == \"STR_TRANSFORMATIONS_OVERVIEW\")\n\t{\n\t\t_game->pushState(new SoldierTransformationListState(_base, _cbxScreenActions));\n\t}\n\telse\n\t{\n\t\t// \"STR_SOLDIER_INFO\" or any available soldier transformation\n\t\tinitList(0);\n\t}\n}\n\n/**\n* Displays the inventory screen for the soldiers inside the base.\n* @param action Pointer to an action.\n*/\nvoid SoldiersState::btnInventoryClick(Action *)\n{\n\tif (_base->getAvailableSoldiers(true, true) > 0)\n\t{\n\t\tSavedBattleGame *bgame = new SavedBattleGame(_game->getMod(), _game->getLanguage());\n\t\t_game->getSavedGame()->setBattleGame(bgame);\n\t\tbgame->setMissionType(\"STR_BASE_DEFENSE\");\n\n\t\tif (_game->isCtrlPressed() && _game->isAltPressed())\n\t\t{\n\t\t\t_game->getSavedGame()->setDisableSoldierEquipment(true);\n\t\t}\n\t\tBattlescapeGenerator bgen = BattlescapeGenerator(_game);\n\t\tbgen.setBase(_base);\n\t\tbgen.runInventory(0);\n\n\t\t// pre-select the soldier under the mouse cursor (if possible)\n\t\tif (_availableOptions.empty() || _cbxScreenActions->getSelected() == 0)\n\t\t{\n\t\t\tsize_t idx = _lstSoldiers->getSelectedRow();\n\t\t\tif (idx < _base->getSoldiers()->size())\n\t\t\t{\n\t\t\t\tint soldierId = _base->getSoldiers()->at(idx)->getId();\n\t\t\t\tfor (auto* unit : *bgame->getUnits())\n\t\t\t\t{\n\t\t\t\t\tif (unit->getId() == soldierId)\n\t\t\t\t\t{\n\t\t\t\t\t\tbgame->setSelectedUnit(unit);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t_game->getScreen()->clear();\n\t\t_game->pushState(new InventoryState(false, 0, _base, true));\n\t}\n}\n\n/**\n * Shows the selected soldier's info.\n * @param action Pointer to an action.\n */\nvoid SoldiersState::lstSoldiersClick(Action *action)\n{\n\tdouble mx = action->getAbsoluteXMouse();\n\tif (mx >= _lstSoldiers->getArrowsLeftEdge() && mx < _lstSoldiers->getArrowsRightEdge())\n\t{\n\t\treturn;\n\t}\n\n\tstd::string selAction = \"STR_SOLDIER_INFO\";\n\tif (!_availableOptions.empty())\n\t{\n\t\tselAction = _availableOptions.at(_cbxScreenActions->getSelected());\n\t}\n\tif (selAction == \"STR_SOLDIER_INFO\")\n\t{\n\t\tif (action->getDetails()->button.button == SDL_BUTTON_RIGHT)\n\t\t{\n\t\t\tbtnInventoryClick(nullptr);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_game->pushState(new SoldierInfoState(_base, _lstSoldiers->getSelectedRow()));\n\t\t}\n\t}\n\telse if (action->getDetails()->button.button == SDL_BUTTON_RIGHT)\n\t{\n\t\tsize_t idx = _lstSoldiers->getSelectedRow();\n\t\tif (idx < _filteredIndicesOfSoldiers.size())\n\t\t{\n\t\t\tint soldierId = _filteredIndicesOfSoldiers[idx];\n\t\t\tif (soldierId > -1)\n\t\t\t{\n\t\t\t\t_game->pushState(new SoldierInfoState(_base, soldierId));\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\tRuleSoldierTransformation *transformationRule = _game->getMod()->getSoldierTransformation(selAction);\n\t\tif (transformationRule)\n\t\t{\n\t\t\t_game->pushState(new SoldierTransformationState(\n\t\t\t\ttransformationRule,\n\t\t\t\t_base,\n\t\t\t\t_filteredListOfSoldiers.at(_lstSoldiers->getSelectedRow()),\n\t\t\t\t&_filteredListOfSoldiers));\n\t\t}\n\t}\n}\n\n/**\n * Handles the mouse-wheels on the arrow-buttons.\n * @param action Pointer to an action.\n */\nvoid SoldiersState::lstSoldiersMousePress(Action *action)\n{\n\tif (Options::changeValueByMouseWheel == 0)\n\t\treturn;\n\tunsigned int row = _lstSoldiers->getSelectedRow();\n\tsize_t numSoldiers = _base->getSoldiers()->size();\n\tif (action->getDetails()->button.button == SDL_BUTTON_WHEELUP &&\n\t\trow > 0)\n\t{\n\t\tif (action->getAbsoluteXMouse() >= _lstSoldiers->getArrowsLeftEdge() &&\n\t\t\taction->getAbsoluteXMouse() <= _lstSoldiers->getArrowsRightEdge())\n\t\t{\n\t\t\tmoveSoldierUp(action, row);\n\t\t}\n\t}\n\telse if (action->getDetails()->button.button == SDL_BUTTON_WHEELDOWN &&\n\t\t0 < numSoldiers && INT_MAX >= numSoldiers && row < numSoldiers - 1)\n\t{\n\t\tif (action->getAbsoluteXMouse() >= _lstSoldiers->getArrowsLeftEdge() &&\n\t\t\taction->getAbsoluteXMouse() <= _lstSoldiers->getArrowsRightEdge())\n\t\t{\n\t\t\tmoveSoldierDown(action, row);\n\t\t}\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/SoldiersState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include <vector>\n#include \"SoldierSortUtil.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass TextList;\nclass ComboBox;\nclass Base;\nclass Soldier;\nstruct SortFunctor;\n\n/**\n * Soldiers screen that lets the player\n * manage all the soldiers in a base.\n */\nclass SoldiersState : public State\n{\nprivate:\n\tTextButton *_btnOk, *_btnPsiTraining, *_btnTraining, *_btnMemorial;\n\tWindow *_window;\n\tText *_txtTitle, *_txtName, *_txtRank, *_txtCraft;\n\tComboBox *_cbxSortBy, *_cbxScreenActions;\n\tTextList *_lstSoldiers;\n\tBase *_base;\n\tstd::vector<Soldier *> _origSoldierOrder, _filteredListOfSoldiers;\n\tstd::vector<int> _filteredIndicesOfSoldiers;\n\tstd::vector<SortFunctor *> _sortFunctors;\n\tgetStatFn_t _dynGetter;\n\tstd::vector<std::string> _availableOptions;\n\tsize_t _mainOffset;\n\t///initializes the display list based on the craft soldier's list and the position to display\n\tvoid initList(size_t scrl);\npublic:\n\t/// Creates the Soldiers state.\n\tSoldiersState(Base *base);\n\t/// Cleans up the Soldiers state.\n\t~SoldiersState();\n\t/// Handler for changing the sort by combobox.\n\tvoid cbxSortByChange(Action *action);\n\t/// Updates the soldier names.\n\tvoid init() override;\n\t/// Handler for clicking the Soldiers reordering button.\n\tvoid lstItemsLeftArrowClick(Action *action);\n\t/// Moves a soldier up.\n\tvoid moveSoldierUp(Action *action, unsigned int row, bool max = false);\n\t/// Handler for clicking the Soldiers reordering button.\n\tvoid lstItemsRightArrowClick(Action *action);\n\t/// Moves a soldier down.\n\tvoid moveSoldierDown(Action *action, unsigned int row, bool max = false);\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the Psi Training button.\n\tvoid btnPsiTrainingClick(Action *action);\n\tvoid btnTrainingClick(Action *action);\n\t/// Handler for clicking the Memorial button.\n\tvoid btnMemorialClick(Action *action);\n\t/// Handler for clicking the Transformations Overview button/hotkey.\n\tvoid btnTransformationsOverviewClick(Action *action);\n\t/// Handler for changing the screen actions combo box.\n\tvoid cbxScreenActionsChange(Action *action);\n\t/// Handler for clicking the Inventory button.\n\tvoid btnInventoryClick(Action *action);\n\t/// Handler for clicking the Soldiers list.\n\tvoid lstSoldiersClick(Action *action);\n\t/// Handler for pressing-down a mouse-button in the list.\n\tvoid lstSoldiersMousePress(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/StoresState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"StoresState.h\"\n#include \"ItemLocationsState.h\"\n#include <sstream>\n#include \"../Engine/CrossPlatform.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/ArrowButton.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextEdit.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Interface/ToggleTextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/BaseFacility.h\"\n#include \"../Savegame/Craft.h\"\n#include \"../Savegame/ItemContainer.h\"\n#include \"../Savegame/ResearchProject.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Soldier.h\"\n#include \"../Savegame/Transfer.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"../Mod/RuleResearch.h\"\n#include \"../Ufopaedia/Ufopaedia.h\"\n#include <algorithm>\n#include <locale>\n\nnamespace OpenXcom\n{\n\nstruct compareItemName\n{\n\tbool operator()(const StoredItem &a, const StoredItem &b) const\n\t{\n\t\treturn Unicode::naturalCompare(a.name, b.name);\n\t}\n};\n\nstruct compareItemQuantity\n{\n\tbool operator()(const StoredItem &a, const StoredItem &b) const\n\t{\n\t\treturn a.quantity < b.quantity;\n\t}\n};\n\nstruct compareItemSize\n{\n\tbool operator()(const StoredItem &a, const StoredItem &b) const\n\t{\n\t\treturn a.size < b.size;\n\t}\n};\n\nstruct compareItemSpaceUsed\n{\n\tbool operator()(const StoredItem &a, const StoredItem &b) const\n\t{\n\t\treturn a.spaceUsed < b.spaceUsed;\n\t}\n};\n\n\n/**\n * Initializes all the elements in the Stores window.\n * @param base Pointer to the base to get info from.\n */\nStoresState::StoresState(Base *base) : _base(base)\n{\n\t// Create objects\n\t_window = new Window(this, 320, 200, 0, 0);\n\t_btnQuickSearch = new TextEdit(this, 48, 9, 10, 20);\n\t_btnOk = new TextButton(148, 16, 164, 176);\n\t_btnGrandTotal = new ToggleTextButton(148, 16, 8, 176);\n\t_txtTitle = new Text(310, 17, 5, 8);\n\t_txtItem = new Text(142, 9, 10, 32);\n\t_txtQuantity = new Text(54, 9, 152, 32);\n\t_txtSize = new Text(54, 9, 212, 32);\n\t_txtSpaceUsed = new Text(54, 9, 248, 32);\n\t_lstStores = new TextList(288, 128, 8, 40);\n\t_sortName = new ArrowButton(ARROW_NONE, 11, 8, 10, 32);\n\t_sortQuantity = new ArrowButton(ARROW_NONE, 11, 8, 152, 32);\n\t_sortSize = new ArrowButton(ARROW_NONE, 11, 8, 212, 32);\n\t_sortSpaceUsed = new ArrowButton(ARROW_NONE, 11, 8, 248, 32);\n\n\t// Set palette\n\tsetInterface(\"storesInfo\");\n\n\tadd(_window, \"window\", \"storesInfo\");\n\tadd(_btnQuickSearch, \"button\", \"storesInfo\");\n\tadd(_btnOk, \"button\", \"storesInfo\");\n\tadd(_btnGrandTotal, \"button\", \"storesInfo\");\n\tadd(_txtTitle, \"text\", \"storesInfo\");\n\tadd(_txtItem, \"text\", \"storesInfo\");\n\tadd(_txtQuantity, \"text\", \"storesInfo\");\n\tadd(_txtSize, \"text\", \"storesInfo\");\n\tadd(_txtSpaceUsed, \"text\", \"storesInfo\");\n\tadd(_lstStores, \"list\", \"storesInfo\");\n\tadd(_sortName, \"text\", \"storesInfo\");\n\tadd(_sortQuantity, \"text\", \"storesInfo\");\n\tadd(_sortSize, \"text\", \"storesInfo\");\n\tadd(_sortSpaceUsed, \"text\", \"storesInfo\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"storesInfo\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&StoresState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&StoresState::btnOkClick, Options::keyOk);\n\t_btnOk->onKeyboardPress((ActionHandler)&StoresState::btnOkClick, Options::keyCancel);\n\n\t_btnGrandTotal->setText(tr(\"STR_GRAND_TOTAL\"));\n\t_btnGrandTotal->onMouseClick((ActionHandler)&StoresState::btnGrandTotalClick);\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_STORES\"));\n\n\t_txtItem->setText(tr(\"STR_ITEM\"));\n\n\t_txtQuantity->setText(tr(\"STR_QUANTITY_UC\"));\n\t_txtSize->setText(tr(\"STR_SIZE_UC\"));\n\t_txtSpaceUsed->setText(tr(\"STR_SPACE_USED_UC\"));\n\n\t_lstStores->setColumns(4, 162, 40, 50, 34);\n\t_lstStores->setSelectable(true);\n\t_lstStores->setBackground(_window);\n\t_lstStores->setMargin(2);\n\t_lstStores->onMouseClick((ActionHandler)&StoresState::lstStoresClick, SDL_BUTTON_LEFT);\n\t_lstStores->onMouseClick((ActionHandler)&StoresState::lstStoresClick, SDL_BUTTON_MIDDLE);\n\n\t_sortName->setX(_sortName->getX() + _txtItem->getTextWidth() + 4);\n\t_sortName->onMouseClick((ActionHandler)&StoresState::sortNameClick);\n\n\t_sortQuantity->setX(_sortQuantity->getX() + _txtQuantity->getTextWidth() + 4);\n\t_sortQuantity->onMouseClick((ActionHandler)&StoresState::sortQuantityClick);\n\n\t_sortSize->setX(_sortSize->getX() + _txtSize->getTextWidth() + 4);\n\t_sortSize->onMouseClick((ActionHandler)&StoresState::sortSizeClick);\n\n\t_sortSpaceUsed->setX(_sortSpaceUsed->getX() + _txtSpaceUsed->getTextWidth() + 4);\n\t_sortSpaceUsed->onMouseClick((ActionHandler)&StoresState::sortSpaceUsedClick);\n\n\t_itemOrder = ITEM_SORT_NONE;\n\n\t_btnQuickSearch->setText(\"\"); // redraw\n\t_btnQuickSearch->onEnter((ActionHandler)&StoresState::btnQuickSearchApply);\n\t_btnQuickSearch->setVisible(Options::oxceQuickSearchButton);\n\n\t_btnOk->onKeyboardRelease((ActionHandler)&StoresState::btnQuickSearchToggle, Options::keyToggleQuickSearch);\n}\n\n/**\n *\n */\nStoresState::~StoresState()\n{\n\n}\n\n/**\n * Returns to the previous screen.\n */\nvoid StoresState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n* Quick search toggle.\n* @param action Pointer to an action.\n*/\nvoid StoresState::btnQuickSearchToggle(Action *action)\n{\n\tif (_btnQuickSearch->getVisible())\n\t{\n\t\t_btnQuickSearch->setText(\"\");\n\t\t_btnQuickSearch->setVisible(false);\n\t\tbtnQuickSearchApply(action);\n\t}\n\telse\n\t{\n\t\t_btnQuickSearch->setVisible(true);\n\t\t_btnQuickSearch->setFocus(true);\n\t}\n}\n\n/**\n* Quick search.\n*/\nvoid StoresState::btnQuickSearchApply(Action *)\n{\n\tinitList();\n}\n\n/**\n * Reloads the item list.\n */\nvoid StoresState::initList()\n{\n\tbool grandTotal = _btnGrandTotal->getPressed();\n\n\tstd::string searchString = _btnQuickSearch->getText();\n\tUnicode::upperCase(searchString);\n\n\t// clear everything\n\t_itemList.clear();\n\n\t// find relevant items\n\tfor (auto& itemType : _game->getMod()->getItemsList())\n\t{\n\t\t// quick search\n\t\tif (!searchString.empty())\n\t\t{\n\t\t\tstd::string projectName = tr(itemType);\n\t\t\tUnicode::upperCase(projectName);\n\t\t\tif (projectName.find(searchString) == std::string::npos)\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\tint qty = 0;\n\t\tauto* rule = _game->getMod()->getItem(itemType, true);\n\t\tif (!grandTotal)\n\t\t{\n\t\t\t// items in stores from this base only\n\t\t\tqty += _base->getStorageItems()->getItem(rule);\n\t\t}\n\t\telse\n\t\t{\n\n\t\t\t// items from all bases\n\t\t\tfor (auto* xbase : *_game->getSavedGame()->getBases())\n\t\t\t{\n\t\t\t\t// 1. items in base stores\n\t\t\t\tqty += xbase->getStorageItems()->getItem(rule);\n\n\t\t\t\t// 1b. items from base defense facilities\n\t\t\t\tfor (const auto* facility : *xbase->getFacilities())\n\t\t\t\t{\n\t\t\t\t\tif (facility->getRules()->getAmmoMax() > 0 && facility->getRules()->getAmmoItem() == rule)\n\t\t\t\t\t{\n\t\t\t\t\t\tqty += facility->getAmmo();\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// 2. items from craft\n\t\t\t\tfor (const auto* craft : *xbase->getCrafts())\n\t\t\t\t{\n\t\t\t\t\tqty += craft->getTotalItemCount(rule);\n\t\t\t\t}\n\n\t\t\t\t// 3. armor in use (worn by soldiers)\n\t\t\t\tfor (const auto* soldier : *xbase->getSoldiers())\n\t\t\t\t{\n\t\t\t\t\tif (soldier->getArmor()->getStoreItem() == rule)\n\t\t\t\t\t{\n\t\t\t\t\t\tqty += 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// 4. items/aliens in research\n\t\t\t\tfor (const auto* research : xbase->getResearch())\n\t\t\t\t{\n\t\t\t\t\tconst auto* rrule = research->getRules();\n\t\t\t\t\tif (rrule->isHoldingNeededItem())\n\t\t\t\t\t{\n\t\t\t\t\t\tif (rrule->getNeededItem() && rrule->getNeededItem() == rule)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tqty += 1;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// 5. items in transfer\n\t\t\t\tfor (auto* transfer : *xbase->getTransfers())\n\t\t\t\t{\n\t\t\t\t\tif (transfer->getCraft())\n\t\t\t\t\t{\n\t\t\t\t\t\t// 5a. craft equipment, weapons, vehicles\n\t\t\t\t\t\tqty += transfer->getCraft()->getTotalItemCount(rule);\n\t\t\t\t\t}\n\t\t\t\t\telse if (transfer->getSoldier())\n\t\t\t\t\t{\n\t\t\t\t\t\t// 5c. armor in use (worn by soldiers)\n\t\t\t\t\t\tif (transfer->getSoldier()->getArmor()->getStoreItem() == rule)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tqty += 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse if (transfer->getItems() == rule)\n\t\t\t\t\t{\n\t\t\t\t\t\t// 5b. items in transfer\n\t\t\t\t\t\tqty += transfer->getQuantity();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (qty > 0)\n\t\t{\n\t\t\t_itemList.push_back(StoredItem(rule, tr(itemType), qty, rule->getSize(), qty * rule->getSize()));\n\t\t}\n\t}\n\n\tsortList();\n}\n\n/**\n * Refreshes the item list.\n */\nvoid StoresState::init()\n{\n\tState::init();\n\n\tinitList();\n}\n\n/**\n * Includes items from all bases.\n */\nvoid StoresState::btnGrandTotalClick(Action *)\n{\n\tinitList();\n}\n\n/**\n * Updates the sorting arrows based on the current setting.\n */\nvoid StoresState::updateArrows()\n{\n\t_sortName->setShape(ARROW_NONE);\n\t_sortQuantity->setShape(ARROW_NONE);\n\t_sortSize->setShape(ARROW_NONE);\n\t_sortSpaceUsed->setShape(ARROW_NONE);\n\tswitch (_itemOrder)\n\t{\n\tcase ITEM_SORT_NONE:\n\t\tbreak;\n\tcase ITEM_SORT_NAME_ASC:\n\t\t_sortName->setShape(ARROW_SMALL_UP);\n\t\tbreak;\n\tcase ITEM_SORT_NAME_DESC:\n\t\t_sortName->setShape(ARROW_SMALL_DOWN);\n\t\tbreak;\n\tcase ITEM_SORT_QUANTITY_ASC:\n\t\t_sortQuantity->setShape(ARROW_SMALL_UP);\n\t\tbreak;\n\tcase ITEM_SORT_QUANTITY_DESC:\n\t\t_sortQuantity->setShape(ARROW_SMALL_DOWN);\n\t\tbreak;\n\tcase ITEM_SORT_SIZE_ASC:\n\t\t_sortSize->setShape(ARROW_SMALL_UP);\n\t\tbreak;\n\tcase ITEM_SORT_SIZE_DESC:\n\t\t_sortSize->setShape(ARROW_SMALL_DOWN);\n\t\tbreak;\n\tcase ITEM_SORT_SPACE_USED_ASC:\n\t\t_sortSpaceUsed->setShape(ARROW_SMALL_UP);\n\t\tbreak;\n\tcase ITEM_SORT_SPACE_USED_DESC:\n\t\t_sortSpaceUsed->setShape(ARROW_SMALL_DOWN);\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n}\n\n/**\n * Sorts the item list.\n */\nvoid StoresState::sortList()\n{\n\tupdateArrows();\n\n\tswitch (_itemOrder)\n\t{\n\tcase ITEM_SORT_NONE:\n\t\tbreak;\n\tcase ITEM_SORT_NAME_ASC:\n\t\tstd::stable_sort(_itemList.begin(), _itemList.end(), compareItemName());\n\t\tbreak;\n\tcase ITEM_SORT_NAME_DESC:\n\t\tstd::stable_sort(_itemList.rbegin(), _itemList.rend(), compareItemName());\n\t\tbreak;\n\tcase ITEM_SORT_QUANTITY_ASC:\n\t\tstd::stable_sort(_itemList.begin(), _itemList.end(), compareItemQuantity());\n\t\tbreak;\n\tcase ITEM_SORT_QUANTITY_DESC:\n\t\tstd::stable_sort(_itemList.rbegin(), _itemList.rend(), compareItemQuantity());\n\t\tbreak;\n\tcase ITEM_SORT_SIZE_ASC:\n\t\tstd::stable_sort(_itemList.begin(), _itemList.end(), compareItemSize());\n\t\tbreak;\n\tcase ITEM_SORT_SIZE_DESC:\n\t\tstd::stable_sort(_itemList.rbegin(), _itemList.rend(), compareItemSize());\n\t\tbreak;\n\tcase ITEM_SORT_SPACE_USED_ASC:\n\t\tstd::stable_sort(_itemList.begin(), _itemList.end(), compareItemSpaceUsed());\n\t\tbreak;\n\tcase ITEM_SORT_SPACE_USED_DESC:\n\t\tstd::stable_sort(_itemList.rbegin(), _itemList.rend(), compareItemSpaceUsed());\n\t\tbreak;\n\t}\n\n\tupdateList();\n}\n\n/**\n * Updates the item list with the current list of available items.\n */\nvoid StoresState::updateList()\n{\n\t_lstStores->clearList();\n\n\tfor (const auto& item : _itemList)\n\t{\n\t\tstd::ostringstream ss, ss2, ss3;\n\t\tss << item.quantity;\n\t\tss2 << item.size;\n\t\tss3 << item.spaceUsed;\n\t\t_lstStores->addRow(4, item.name.c_str(), ss.str().c_str(), ss2.str().c_str(), ss3.str().c_str());\n\t}\n}\n\n/**\n * Sorts the items by name.\n */\nvoid StoresState::sortNameClick(Action *)\n{\n\t_itemOrder = _itemOrder == ITEM_SORT_NAME_ASC ? ITEM_SORT_NAME_DESC : ITEM_SORT_NAME_ASC;\n\tsortList();\n}\n\n/**\n * Sorts the items by quantity.\n */\nvoid StoresState::sortQuantityClick(Action *)\n{\n\t_itemOrder = _itemOrder == ITEM_SORT_QUANTITY_ASC ? ITEM_SORT_QUANTITY_DESC : ITEM_SORT_QUANTITY_ASC;\n\tsortList();\n}\n\n/**\n * Sorts the items by size.\n */\nvoid StoresState::sortSizeClick(Action *)\n{\n\t_itemOrder = _itemOrder == ITEM_SORT_SIZE_ASC ? ITEM_SORT_SIZE_DESC : ITEM_SORT_SIZE_ASC;\n\tsortList();\n}\n\n/**\n * Sorts the items by space used.\n */\nvoid StoresState::sortSpaceUsedClick(Action *)\n{\n\t_itemOrder = _itemOrder == ITEM_SORT_SPACE_USED_ASC ? ITEM_SORT_SPACE_USED_DESC : ITEM_SORT_SPACE_USED_ASC;\n\tsortList();\n}\n\n/**\n * Handles mouse clicks.\n * @param action Pointer to an action.\n */\nvoid StoresState::lstStoresClick(Action* action)\n{\n\tif (_game->isMiddleClick(action))\n\t{\n\t\tauto* rule = _itemList[_lstStores->getSelectedRow()].rule;\n\n\t\tstd::string articleId = rule->getUfopediaType();\n\t\tUfopaedia::openArticle(_game, articleId);\n\t}\n\telse if (_game->isLeftClick(action))\n\t{\n\t\tauto* rule = _itemList[_lstStores->getSelectedRow()].rule;\n\n\t\t_game->pushState(new ItemLocationsState(rule));\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/StoresState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include <vector>\n\nnamespace OpenXcom\n{\n\nclass Base;\nclass RuleItem;\nclass TextButton;\nclass ToggleTextButton;\nclass Window;\nclass Text;\nclass TextEdit;\nclass TextList;\nclass ArrowButton;\n\n/// Item sorting modes.\nenum ItemSort\n{\n\tITEM_SORT_NONE,\n\tITEM_SORT_NAME_ASC,\n\tITEM_SORT_NAME_DESC,\n\tITEM_SORT_QUANTITY_ASC,\n\tITEM_SORT_QUANTITY_DESC,\n\tITEM_SORT_SIZE_ASC,\n\tITEM_SORT_SIZE_DESC,\n\tITEM_SORT_SPACE_USED_ASC,\n\tITEM_SORT_SPACE_USED_DESC\n};\n\nstruct StoredItem\n{\n\tStoredItem(RuleItem* _rule, const std::string &_name, int _quantity, double _size, double _spaceUsed)\n\t\t: rule(_rule), name(_name), quantity(_quantity), size(_size), spaceUsed(_spaceUsed)\n\t{\n\t}\n\tRuleItem* rule;\n\tstd::string name;\n\tint quantity;\n\tdouble size;\n\tdouble spaceUsed;\n};\n\n/**\n * Stores window that displays all\n * the items currently stored in a base.\n */\nclass StoresState : public State\n{\nprivate:\n\tBase *_base;\n\n\tTextButton *_btnOk;\n\tTextEdit *_btnQuickSearch;\n\tToggleTextButton *_btnGrandTotal;\n\tWindow *_window;\n\tText *_txtTitle, *_txtItem, *_txtQuantity, *_txtSize, *_txtSpaceUsed;\n\tTextList *_lstStores;\n\tArrowButton *_sortName, *_sortQuantity, *_sortSize, *_sortSpaceUsed;\n\n\tstd::vector<StoredItem> _itemList;\n\tvoid initList();\n\tItemSort _itemOrder;\n\tvoid updateArrows();\npublic:\n\t/// Creates the Stores state.\n\tStoresState(Base *base);\n\t/// Cleans up the Stores state.\n\t~StoresState();\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handlers for Quick Search.\n\tvoid btnQuickSearchToggle(Action *action);\n\tvoid btnQuickSearchApply(Action *action);\n\t/// Handler for clicking the Grand Total button.\n\tvoid btnGrandTotalClick(Action *action);\n\t/// Sets up the item list.\n\tvoid init() override;\n\t/// Sorts the item list.\n\tvoid sortList();\n\t/// Updates the item list.\n\tvirtual void updateList();\n\t/// Handler for clicking the Name arrow.\n\tvoid sortNameClick(Action *action);\n\t/// Handler for clicking the Quantity arrow.\n\tvoid sortQuantityClick(Action *action);\n\t/// Handler for clicking the Size arrow.\n\tvoid sortSizeClick(Action *action);\n\t/// Handler for clicking the Space Used arrow.\n\tvoid sortSpaceUsedClick(Action *action);\n\t/// Handler for clicking the Stores list.\n\tvoid lstStoresClick(Action* action);\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/TechTreeSelectState.cpp",
    "content": "/*\n * Copyright 2010-2015 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <locale>\n#include \"TechTreeSelectState.h\"\n#include \"TechTreeViewerState.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleArcScript.h\"\n#include \"../Mod/RuleEventScript.h\"\n#include \"../Mod/RuleMissionScript.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextEdit.h\"\n#include \"../Interface/TextList.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements on the UI.\n * @param parent Pointer to parent state.\n */\nTechTreeSelectState::TechTreeSelectState(TechTreeViewerState *parent) : _parent(parent)\n{\n\t_screen = false;\n\n\t_window = new Window(this, 230, 140, 45, 32);\n\t_btnQuickSearch = new TextEdit(this, 198, 9, 53, 52);\n\t_txtTitle = new Text(182, 9, 53, 42);\n\t_lstTopics = new TextList(198, 80, 53, 62);\n\t_btnOk = new TextButton(206, 16, 57, 145);\n\n\t// Set palette\n\tsetInterface(\"techTreeSelect\");\n\n\tadd(_window, \"window\", \"techTreeSelect\");\n\tadd(_btnQuickSearch, \"button\", \"techTreeSelect\");\n\tadd(_txtTitle, \"text\", \"techTreeSelect\");\n\tadd(_btnOk, \"button\", \"techTreeSelect\");\n\tadd(_lstTopics, \"list\", \"techTreeSelect\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"techTreeSelect\");\n\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_AVAILABLE_TOPICS\"));\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&TechTreeSelectState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&TechTreeSelectState::btnOkClick, Options::keyCancel);\n\n\t_lstTopics->setColumns(1, 198);\n\t_lstTopics->setSelectable(true);\n\t_lstTopics->setBackground(_window);\n\t_lstTopics->setMargin(0);\n\t_lstTopics->setAlign(ALIGN_CENTER);\n\t_lstTopics->onMouseClick((ActionHandler)&TechTreeSelectState::onSelectTopic);\n\n\t_btnQuickSearch->setText(\"\"); // redraw\n\t_btnQuickSearch->setDrawBackground(false);\n\t_btnQuickSearch->onEnter((ActionHandler)&TechTreeSelectState::btnQuickSearchApply);\n\t_btnQuickSearch->setVisible(true);\n\t_btnQuickSearch->setFocus(true);\n\n\t_btnOk->onKeyboardRelease((ActionHandler)&TechTreeSelectState::btnQuickSearchToggle, Options::keyToggleQuickSearch);\n}\n\nTechTreeSelectState::~TechTreeSelectState()\n{\n}\n\n/**\n* Initializes the screen (fills the lists).\n*/\nvoid TechTreeSelectState::init()\n{\n\tState::init();\n\tinitLists();\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid TechTreeSelectState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n* Quick search toggle.\n* @param action Pointer to an action.\n*/\nvoid TechTreeSelectState::btnQuickSearchToggle(Action *action)\n{\n\tif (_btnQuickSearch->getVisible())\n\t{\n\t\t_btnQuickSearch->setText(\"\");\n\t\t_btnQuickSearch->setVisible(false);\n\t\tbtnQuickSearchApply(action);\n\t}\n\telse\n\t{\n\t\t_btnQuickSearch->setVisible(true);\n\t\t_btnQuickSearch->setFocus(true);\n\t}\n}\n\n/**\n* Quick search.\n* @param action Pointer to an action.\n*/\nvoid TechTreeSelectState::btnQuickSearchApply(Action *)\n{\n\tinitLists();\n}\n\n/**\n* Shows the filtered topics.\n*/\nvoid TechTreeSelectState::initLists()\n{\n\tstd::string searchString = _btnQuickSearch->getText();\n\tUnicode::upperCase(searchString);\n\n\t_firstManufacturingTopicIndex = 0;\n\t_firstFacilitiesTopicIndex = 0;\n\t_firstItemTopicIndex = 0;\n\t_firstCraftTopicIndex = 0;\n\n\t_availableTopics.clear();\n\t_lstTopics->clearList();\n\n\tif (searchString.length() < 3)\n\t{\n\t\t_lstTopics->addRow(1, tr(\"STR_QS_THREE_LETTERS_A\").c_str());\n\t\t_lstTopics->addRow(1, tr(\"STR_QS_THREE_LETTERS_B\").c_str());\n\t\treturn;\n\t}\n\n\tint row = 0;\n\tstd::unordered_set<std::string> tmpList;\n\tif (searchString == \"ASCRIPT\")\n\t{\n\t\tfor (auto& arcScriptId : *_game->getMod()->getArcScriptList())\n\t\t{\n\t\t\tauto* arcScript = _game->getMod()->getArcScript(arcScriptId, false);\n\t\t\tif (arcScript)\n\t\t\t{\n\t\t\t\tfor (auto& trigger : arcScript->getResearchTriggers())\n\t\t\t\t{\n\t\t\t\t\ttmpList.insert(trigger.first);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\telse if (searchString == \"ESCRIPT\")\n\t{\n\t\tfor (auto& eventScriptId : *_game->getMod()->getEventScriptList())\n\t\t{\n\t\t\tauto* eventScript = _game->getMod()->getEventScript(eventScriptId, false);\n\t\t\tif (eventScript)\n\t\t\t{\n\t\t\t\tfor (auto& trigger : eventScript->getResearchTriggers())\n\t\t\t\t{\n\t\t\t\t\ttmpList.insert(trigger.first);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\telse if (searchString == \"MSCRIPT\")\n\t{\n\t\tfor (auto& missionScriptId : *_game->getMod()->getMissionScriptList())\n\t\t{\n\t\t\tauto* missionScript = _game->getMod()->getMissionScript(missionScriptId, false);\n\t\t\tif (missionScript)\n\t\t\t{\n\t\t\t\tfor (auto& trigger : missionScript->getResearchTriggers())\n\t\t\t\t{\n\t\t\t\t\ttmpList.insert(trigger.first);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif (!tmpList.empty())\n\t{\n\t\tfor (auto& tmp : tmpList)\n\t\t{\n\t\t\t_availableTopics.push_back(tmp);\n\t\t\t_lstTopics->addRow(1, tr(tmp).c_str());\n\t\t\t_lstTopics->setRowColor(row, _parent->getResearchColor(tmp));\n\t\t\t++row;\n\t\t}\n\t\t_firstManufacturingTopicIndex = row;\n\t\t_firstFacilitiesTopicIndex = row;\n\t\t_firstItemTopicIndex = row;\n\t\t_firstCraftTopicIndex = row;\n\t\treturn;\n\t}\n\n\tfor (auto& res : _game->getMod()->getResearchList())\n\t{\n\t\tstd::string projectName = tr(res);\n\t\tUnicode::upperCase(projectName);\n\t\tif (searchString == \"SHAZAM\")\n\t\t{\n\t\t\tif (_parent->isDiscoveredResearch(res))\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\telse if (projectName.find(searchString) == std::string::npos)\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\n\t\t_availableTopics.push_back(res);\n\t\t_lstTopics->addRow(1, tr(res).c_str());\n\t\t_lstTopics->setRowColor(row, _parent->getResearchColor(res));\n\t\t++row;\n\t}\n\n\t_firstManufacturingTopicIndex = row;\n\n\tfor (auto& manuf : _game->getMod()->getManufactureList())\n\t{\n\t\tstd::string projectName = tr(manuf);\n\t\tUnicode::upperCase(projectName);\n\t\tif (searchString == \"SHAZAM\")\n\t\t{\n\t\t\tif (_parent->isDiscoveredManufacture(manuf))\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\telse if (projectName.find(searchString) == std::string::npos)\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\n\t\t_availableTopics.push_back(manuf);\n\t\tstd::ostringstream ss;\n\t\tss << tr(manuf);\n\t\tss << tr(\"STR_M_FLAG\");\n\t\t_lstTopics->addRow(1, ss.str().c_str());\n\t\tif (!_parent->isDiscoveredManufacture(manuf))\n\t\t{\n\t\t\t_lstTopics->setRowColor(row, _lstTopics->getSecondaryColor());\n\t\t}\n\t\t++row;\n\t}\n\n\t_firstFacilitiesTopicIndex = row;\n\n\tfor (auto& facType : _game->getMod()->getBaseFacilitiesList())\n\t{\n\t\tstd::string facilityName = tr(facType);\n\t\tUnicode::upperCase(facilityName);\n\t\tif (searchString == \"SHAZAM\")\n\t\t{\n\t\t\tif (_parent->isDiscoveredFacility(facType))\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\telse if (facilityName.find(searchString) == std::string::npos)\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\n\t\t_availableTopics.push_back(facType);\n\t\tstd::ostringstream ss;\n\t\tss << tr(facType);\n\t\tss << tr(\"STR_F_FLAG\");\n\t\t_lstTopics->addRow(1, ss.str().c_str());\n\t\tif (!_parent->isDiscoveredFacility(facType))\n\t\t{\n\t\t\t_lstTopics->setRowColor(row, _lstTopics->getSecondaryColor());\n\t\t}\n\t\t++row;\n\t}\n\n\t_firstItemTopicIndex = row;\n\n\tfor (auto& itemType : _game->getMod()->getItemsList())\n\t{\n\t\tif (!_parent->isProtectedItem(itemType))\n\t\t{\n\t\t\t// items that are not protected at all are irrelevant for the Tech Tree Viewer!\n\t\t\tcontinue;\n\t\t}\n\t\tstd::string itemName = tr(itemType);\n\t\tUnicode::upperCase(itemName);\n\t\tif (searchString == \"SHAZAM\")\n\t\t{\n\t\t\tif (_parent->isProtectedAndDiscoveredItem(itemType))\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\telse if (itemName.find(searchString) == std::string::npos)\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\n\t\t_availableTopics.push_back(itemType);\n\t\tstd::ostringstream ss;\n\t\tss << tr(itemType);\n\t\tss << tr(\"STR_I_FLAG\");\n\t\t_lstTopics->addRow(1, ss.str().c_str());\n\t\tif (!_parent->isProtectedAndDiscoveredItem(itemType))\n\t\t{\n\t\t\t_lstTopics->setRowColor(row, _lstTopics->getSecondaryColor());\n\t\t}\n\t\t++row;\n\t}\n\n\t_firstCraftTopicIndex = row;\n\n\tfor (auto& craftType : _game->getMod()->getCraftsList())\n\t{\n\t\tstd::string craftName = tr(craftType);\n\t\tUnicode::upperCase(craftName);\n\t\tif (searchString == \"SHAZAM\")\n\t\t{\n\t\t\tif (_parent->isDiscoveredCraft(craftType))\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\telse if (craftName.find(searchString) == std::string::npos)\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\n\t\t_availableTopics.push_back(craftType);\n\t\tstd::ostringstream ss;\n\t\tss << tr(craftType);\n\t\tss << tr(\"STR_C_FLAG\");\n\t\t_lstTopics->addRow(1, ss.str().c_str());\n\t\tif (!_parent->isDiscoveredCraft(craftType))\n\t\t{\n\t\t\t_lstTopics->setRowColor(row, _lstTopics->getSecondaryColor());\n\t\t}\n\t\t++row;\n\t}\n}\n\n/**\n* Selects the topic.\n* @param action Pointer to an action.\n*/\nvoid TechTreeSelectState::onSelectTopic(Action *)\n{\n\tsize_t index = _lstTopics->getSelectedRow();\n\tif (index >= _availableTopics.size())\n\t\treturn;\n\n\tconst std::string selectedTopic = _availableTopics[index];\n\n\tTTVMode topicType = TTV_RESEARCH;\n\tif (index >= _firstCraftTopicIndex)\n\t{\n\t\ttopicType = TTV_CRAFTS;\n\t}\n\telse if (index >= _firstItemTopicIndex)\n\t{\n\t\ttopicType = TTV_ITEMS;\n\t}\n\telse if (index >= _firstFacilitiesTopicIndex)\n\t{\n\t\ttopicType = TTV_FACILITIES;\n\t}\n\telse if (index >= _firstManufacturingTopicIndex)\n\t{\n\t\ttopicType = TTV_MANUFACTURING;\n\t}\n\n\t_parent->setSelectedTopic(selectedTopic, topicType);\n\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/TechTreeSelectState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2015 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass TechTreeViewerState;\nclass Window;\nclass Text;\nclass TextButton;\nclass TextEdit;\nclass TextList;\n\n/**\n * Window which allows selecting a topic for the Tech Tree Viewer.\n */\nclass TechTreeSelectState : public State\n{\nprivate:\n\tTechTreeViewerState *_parent;\n\tTextButton *_btnOk;\n\tTextEdit *_btnQuickSearch;\n\tWindow *_window;\n\tText *_txtTitle;\n\tTextList *_lstTopics;\n\tstd::vector<std::string> _availableTopics;\n\tsize_t _firstManufacturingTopicIndex;\n\tsize_t _firstFacilitiesTopicIndex;\n\tsize_t _firstItemTopicIndex;\n\tsize_t _firstCraftTopicIndex;\n\tvoid initLists();\n\tvoid onSelectTopic(Action *action);\npublic:\n\t/// Creates the TechTreeSelect state.\n\tTechTreeSelectState(TechTreeViewerState *parent);\n\t/// Cleans up the TechTreeSelect state\n\t~TechTreeSelectState();\n\t/// Initializes the state.\n\tvoid init() override;\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handlers for Quick Search.\n\tvoid btnQuickSearchToggle(Action *action);\n\tvoid btnQuickSearchApply(Action *action);\n};\n}\n"
  },
  {
    "path": "src/Basescape/TechTreeViewerState.cpp",
    "content": "/*\n * Copyright 2010-2015 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"TechTreeViewerState.h\"\n#include \"TechTreeSelectState.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleArcScript.h\"\n#include \"../Mod/RuleBaseFacility.h\"\n#include \"../Mod/RuleCraft.h\"\n#include \"../Mod/RuleEventScript.h\"\n#include \"../Mod/RuleInterface.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"../Mod/RuleManufacture.h\"\n#include \"../Mod/RuleMissionScript.h\"\n#include \"../Mod/RuleResearch.h\"\n#include \"../Mod/RuleSoldierTransformation.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Savegame/SavedGame.h\"\n#include <algorithm>\n#include <unordered_set>\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements on the UI.\n */\nTechTreeViewerState::TechTreeViewerState(const RuleResearch *r, const RuleManufacture *m, const RuleBaseFacility *f, const RuleCraft *c)\n{\n\tif (r != 0)\n\t{\n\t\t_selectedTopic = r->getName();\n\t\t_selectedFlag = TTV_RESEARCH;\n\t}\n\telse if (m != 0)\n\t{\n\t\t_selectedTopic = m->getName();\n\t\t_selectedFlag = TTV_MANUFACTURING;\n\t}\n\telse if (f != 0)\n\t{\n\t\t_selectedTopic = f->getType();\n\t\t_selectedFlag = TTV_FACILITIES;\n\t}\n\telse if (c != 0)\n\t{\n\t\t_selectedTopic = c->getType();\n\t\t_selectedFlag = TTV_CRAFTS;\n\t}\n\n\t// Create objects\n\t_window = new Window(this, 320, 200, 0, 0);\n\t_txtTitle = new Text(304, 17, 8, 7);\n\t_txtSelectedTopic = new Text(204, 9, 8, 24);\n\t_txtProgress = new Text(100, 9, 212, 24);\n\t_txtCostIndicator = new Text(100, 9, 16, 32); // experimental cost indicator\n\t_lstLeft = new TextList(132, 128, 8, 40);\n\t_lstRight = new TextList(132, 128, 164, 40);\n\t_lstFull = new TextList(288, 128, 8, 40);\n\t_btnNew = new TextButton(148, 16, 8, 176);\n\t_btnOk = new TextButton(148, 16, 164, 176);\n\n\t// Set palette\n\tsetInterface(\"techTreeViewer\");\n\n\t_purple = _game->getMod()->getInterface(\"techTreeViewer\")->getElement(\"list\")->color;\n\t_pink = _game->getMod()->getInterface(\"techTreeViewer\")->getElement(\"list\")->color2;\n\t_blue = _game->getMod()->getInterface(\"techTreeViewer\")->getElement(\"list\")->border;\n\t_white = _game->getMod()->getInterface(\"techTreeViewer\")->getElement(\"listExtended\")->color;\n\t_gold = _game->getMod()->getInterface(\"techTreeViewer\")->getElement(\"listExtended\")->color2;\n\t_grey = _game->getMod()->getInterface(\"techTreeViewer\")->getElement(\"listExtended\")->border;\n\n\tadd(_window, \"window\", \"techTreeViewer\");\n\tadd(_txtTitle, \"text\", \"techTreeViewer\");\n\tadd(_txtSelectedTopic, \"text\", \"techTreeViewer\");\n\tadd(_txtProgress, \"text\", \"techTreeViewer\");\n\tadd(_txtCostIndicator, \"text\", \"techTreeViewer\");\n\tadd(_lstLeft, \"list\", \"techTreeViewer\");\n\tadd(_lstRight, \"list\", \"techTreeViewer\");\n\tadd(_lstFull, \"list\", \"techTreeViewer\");\n\tadd(_btnNew, \"button\", \"techTreeViewer\");\n\tadd(_btnOk, \"button\", \"techTreeViewer\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"techTreeViewer\");\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_TECH_TREE_VIEWER\"));\n\n\t_txtSelectedTopic->setText(tr(\"STR_TOPIC\").arg(\"\"));\n\n\t_lstLeft->setColumns(1, 132);\n\t_lstLeft->setSelectable(true);\n\t_lstLeft->setBackground(_window);\n\t_lstLeft->setWordWrap(true);\n\t_lstLeft->onMouseClick((ActionHandler)&TechTreeViewerState::onSelectLeftTopic);\n\n\t_lstRight->setColumns(1, 132);\n\t_lstRight->setSelectable(true);\n\t_lstRight->setBackground(_window);\n\t_lstRight->setWordWrap(true);\n\t_lstRight->onMouseClick((ActionHandler)&TechTreeViewerState::onSelectRightTopic);\n\n\t_lstFull->setColumns(1, 288);\n\t_lstFull->setSelectable(true);\n\t_lstFull->setBackground(_window);\n\t_lstFull->setWordWrap(true);\n\t_lstFull->onMouseClick((ActionHandler)&TechTreeViewerState::onSelectFullTopic);\n\n\t_btnNew->setText(tr(\"STR_SELECT_TOPIC\"));\n\t_btnNew->onMouseClick((ActionHandler)&TechTreeViewerState::btnNewClick);\n\t_btnNew->onKeyboardPress((ActionHandler)&TechTreeViewerState::btnNewClick, Options::keyToggleQuickSearch);\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&TechTreeViewerState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&TechTreeViewerState::btnOkClick, Options::keyCancel);\n\t_btnOk->onKeyboardPress((ActionHandler)&TechTreeViewerState::btnBackClick, SDLK_BACKSPACE);\n\n\tif (Options::oxceDisableTechTreeViewer)\n\t{\n\t\t_txtTitle->setHeight(_txtTitle->getHeight() * 9);\n\t\t_txtTitle->setWordWrap(true);\n\t\t_txtTitle->setText(tr(\"STR_THIS_FEATURE_IS_DISABLED_1\"));\n\t\t_txtSelectedTopic->setVisible(false);\n\t\t_txtProgress->setVisible(false);\n\t\t_txtCostIndicator->setVisible(false);\n\t\t_lstLeft->setVisible(false);\n\t\t_lstRight->setVisible(false);\n\t\t_lstFull->setVisible(false);\n\t\t_btnNew->setVisible(false);\n\t\treturn;\n\t}\n\n\tint discoveredSum = 0;\n\t// pre-calculate globally\n\tfor (auto* discoveredResearchRule : _game->getSavedGame()->getDiscoveredResearch())\n\t{\n\t\t_alreadyAvailableResearch.insert(discoveredResearchRule->getName());\n\t\tdiscoveredSum += discoveredResearchRule->getCost();\n\t}\n\tfor (auto& info : _game->getSavedGame()->getResearchRuleStatusRaw())\n\t{\n\t\tif (info.second == RuleResearch::RESEARCH_STATUS_DISABLED)\n\t\t{\n\t\t\tauto* rr = _game->getMod()->getResearch(info.first, false);\n\t\t\tif (rr)\n\t\t\t{\n\t\t\t\t_disabledResearch.insert(rr->getName());\n\t\t\t}\n\t\t}\n\t}\n\n\tint totalSum = 0;\n\tRuleResearch *resRule = 0;\n\tfor (auto& resType : _game->getMod()->getResearchList())\n\t{\n\t\tresRule = _game->getMod()->getResearch(resType);\n\t\tif (resRule != 0)\n\t\t{\n\t\t\ttotalSum += resRule->getCost();\n\t\t}\n\t}\n\n\tRuleManufacture *manRule = 0;\n\tfor (auto& manuf : _game->getMod()->getManufactureList())\n\t{\n\t\tmanRule = _game->getMod()->getManufacture(manuf);\n\t\tif (_game->getSavedGame()->isResearched(manRule->getRequirements()))\n\t\t{\n\t\t\t_alreadyAvailableManufacture.insert(manRule->getName());\n\t\t}\n\t}\n\n\tRuleBaseFacility *facRule = 0;\n\tfor (auto& facType : _game->getMod()->getBaseFacilitiesList())\n\t{\n\t\tfacRule = _game->getMod()->getBaseFacility(facType);\n\t\tif (_game->getSavedGame()->isResearched(facRule->getRequirements()))\n\t\t{\n\t\t\t_alreadyAvailableFacilities.insert(facRule->getType());\n\t\t}\n\t}\n\n\tRuleItem *itemRule = 0;\n\tfor (auto& itemType : _game->getMod()->getItemsList())\n\t{\n\t\titemRule = _game->getMod()->getItem(itemType);\n\t\tif (!itemRule->getRequirements().empty() || !itemRule->getBuyRequirements().empty())\n\t\t{\n\t\t\t_protectedItems.insert(itemRule->getType());\n\t\t\tif (_game->getSavedGame()->isResearched(itemRule->getRequirements()) && _game->getSavedGame()->isResearched(itemRule->getBuyRequirements()))\n\t\t\t{\n\t\t\t\t_alreadyAvailableItems.insert(itemRule->getType());\n\t\t\t}\n\t\t}\n\t}\n\n\tRuleCraft *craftRule = 0;\n\tfor (auto& craftType : _game->getMod()->getCraftsList())\n\t{\n\t\tcraftRule = _game->getMod()->getCraft(craftType);\n\t\tif (_game->getSavedGame()->isResearched(craftRule->getRequirements()))\n\t\t{\n\t\t\t_alreadyAvailableCrafts.insert(craftRule->getType());\n\t\t}\n\t}\n\n\t_txtProgress->setAlign(ALIGN_RIGHT);\n\t_txtProgress->setText(tr(\"STR_RESEARCH_PROGRESS\").arg(discoveredSum * 100 / totalSum));\n}\n\n/**\n *\n */\nTechTreeViewerState::~TechTreeViewerState()\n{\n}\n\n/**\n* Initializes the screen (fills the lists).\n*/\nvoid TechTreeViewerState::init()\n{\n\tState::init();\n\n\tif (!Options::oxceDisableTechTreeViewer)\n\t{\n\t\tinitLists();\n\t}\n}\n\n/**\n* Returns to the previous screen.\n* @param action Pointer to an action.\n*/\nvoid TechTreeViewerState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Navigates to the previous topic from the browsing history.\n * @param action Pointer to an action.\n */\nvoid TechTreeViewerState::btnBackClick(Action *)\n{\n\tif (!_history.empty())\n\t{\n\t\t_selectedFlag = _history.back().second;\n\t\t_selectedTopic = _history.back().first;\n\t\t_history.pop_back();\n\t\tinitLists();\n\t}\n}\n\n/**\n* Opens the Select Topic screen.\n* @param action Pointer to an action.\n*/\nvoid TechTreeViewerState::btnNewClick(Action *)\n{\n\t_game->pushState(new TechTreeSelectState(this));\n}\n\n/**\n * Shows the filtered topics.\n */\nvoid TechTreeViewerState::initLists()\n{\n\t// Set topic name\n\t{\n\t\tstd::ostringstream ss;\n\t\tss << tr(_selectedTopic);\n\t\tif (_selectedFlag == TTV_MANUFACTURING)\n\t\t{\n\t\t\tss << tr(\"STR_M_FLAG\");\n\t\t}\n\t\telse if (_selectedFlag == TTV_FACILITIES)\n\t\t{\n\t\t\tss << tr(\"STR_F_FLAG\");\n\t\t}\n\t\telse if (_selectedFlag == TTV_ITEMS)\n\t\t{\n\t\t\tss << tr(\"STR_I_FLAG\");\n\t\t}\n\t\telse if (_selectedFlag == TTV_CRAFTS)\n\t\t{\n\t\t\tss << tr(\"STR_C_FLAG\");\n\t\t}\n\t\t_txtSelectedTopic->setText(tr(\"STR_TOPIC\").arg(ss.str()));\n\t\t_txtCostIndicator->setText(\"\");\n\t}\n\n\t// reset\n\t_leftTopics.clear();\n\t_rightTopics.clear();\n\t_leftFlags.clear();\n\t_rightFlags.clear();\n\t_lstLeft->clearList();\n\t_lstRight->clearList();\n\t_lstFull->clearList();\n\t_lstLeft->setVisible(true);\n\t_lstRight->setVisible(true);\n\t_lstFull->setVisible(false);\n\n\tif (_selectedFlag == TTV_NONE)\n\t{\n\t\treturn;\n\t}\n\telse if (_selectedFlag == TTV_RESEARCH)\n\t{\n\t\tint row = 0;\n\t\tRuleResearch *rule = _game->getMod()->getResearch(_selectedTopic);\n\t\tif (rule == 0)\n\t\t\treturn;\n\n\t\t// Cost indicator\n\t\t{\n\t\t\tstd::ostringstream ss;\n\t\t\tint cost = rule->getCost();\n\t\t\tstd::vector<std::pair<int, std::string>> symbol_values\n\t\t\t\t\t({{100, \"#\"}, {20, \"=\"}, {5, \"-\"}});\n\n\t\t\tfor (const auto& sym : symbol_values)\n\t\t\t{\n\t\t\t\twhile (cost >= std::get<0>(sym))\n\t\t\t\t{\n\t\t\t\t\tcost -= std::get<0>(sym);\n\t\t\t\t\tss << std::get<1>(sym);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (rule->getCost() < 10)\n\t\t\t{\n\t\t\t\twhile (cost >= 1)\n\t\t\t\t{\n\t\t\t\t\tcost -= 1;\n\t\t\t\t\tss << \".\";\n\t\t\t\t}\n\t\t\t}\n\t\t\t_txtCostIndicator->setText(ss.str());\n\t\t}\n\t\t//\n\n\t\tconst std::vector<std::string> &researchList = _game->getMod()->getResearchList();\n\t\tconst std::vector<std::string> &manufactureList = _game->getMod()->getManufactureList();\n\n\t\t// 0. common pre-calculation\n\t\tconst std::vector<const RuleResearch*>& reqs = rule->getRequirements();\n\t\tconst std::vector<const RuleResearch*>& deps = rule->getDependencies();\n\t\tstd::vector<std::string> unlockedBy;\n\t\tstd::vector<std::string> disabledBy;\n\t\tstd::vector<std::string> reenabledBy;\n\t\tstd::vector<std::string> getForFreeFrom;\n\t\tstd::vector<std::string> lookupOf;\n\t\tstd::vector<std::string> requiredByResearch;\n\t\tstd::vector<std::string> requiredByManufacture;\n\t\tstd::vector<std::string> requiredByFacilities;\n\t\tstd::vector<std::string> requiredByItems;\n\t\tstd::vector<std::string> requiredByTransformations;\n\t\tstd::vector<std::string> requiredByCrafts;\n\t\tstd::vector<std::string> leadsTo;\n\t\tconst std::vector<const RuleResearch*>& unlocks = rule->getUnlocked();\n\t\tconst std::vector<const RuleResearch*>& disables = rule->getDisabled();\n\t\tconst std::vector<const RuleResearch*>& reenables = rule->getReenabled();\n\t\tconst std::vector<const RuleResearch*>& free = rule->getGetOneFree();\n\t\tauto& freeProtected = rule->getGetOneFreeProtected();\n\n\t\tfor (auto& j : manufactureList)\n\t\t{\n\t\t\tRuleManufacture *temp = _game->getMod()->getManufacture(j);\n\t\t\tfor (auto& i : temp->getRequirements())\n\t\t\t{\n\t\t\t\tif (i == rule)\n\t\t\t\t{\n\t\t\t\t\trequiredByManufacture.push_back(j);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (auto& f : _game->getMod()->getBaseFacilitiesList())\n\t\t{\n\t\t\tRuleBaseFacility *temp = _game->getMod()->getBaseFacility(f);\n\t\t\tfor (auto& i : temp->getRequirements())\n\t\t\t{\n\t\t\t\tif (i == rule->getName())\n\t\t\t\t{\n\t\t\t\t\trequiredByFacilities.push_back(f);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (auto& item : _game->getMod()->getItemsList())\n\t\t{\n\t\t\tRuleItem *temp = _game->getMod()->getItem(item);\n\t\t\tfor (auto& i : temp->getRequirements())\n\t\t\t{\n\t\t\t\tif (i == rule)\n\t\t\t\t{\n\t\t\t\t\trequiredByItems.push_back(item);\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (auto& i : temp->getBuyRequirements())\n\t\t\t{\n\t\t\t\tif (i == rule)\n\t\t\t\t{\n\t\t\t\t\trequiredByItems.push_back(item);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (auto& transf : _game->getMod()->getSoldierTransformationList())\n\t\t{\n\t\t\tRuleSoldierTransformation* temp = _game->getMod()->getSoldierTransformation(transf);\n\t\t\tfor (auto& i : temp->getRequiredResearch())\n\t\t\t{\n\t\t\t\tif (i == rule->getName())\n\t\t\t\t{\n\t\t\t\t\trequiredByTransformations.push_back(transf);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (auto& c : _game->getMod()->getCraftsList())\n\t\t{\n\t\t\tRuleCraft *temp = _game->getMod()->getCraft(c);\n\t\t\tfor (auto& i : temp->getRequirements())\n\t\t\t{\n\t\t\t\tif (i == rule->getName())\n\t\t\t\t{\n\t\t\t\t\trequiredByCrafts.push_back(c);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (auto& j : researchList)\n\t\t{\n\t\t\tRuleResearch *temp = _game->getMod()->getResearch(j);\n\t\t\tfor (auto& i : temp->getUnlocked())\n\t\t\t{\n\t\t\t\tif (i == rule)\n\t\t\t\t{\n\t\t\t\t\tunlockedBy.push_back(j);\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (auto& i : temp->getDisabled())\n\t\t\t{\n\t\t\t\tif (i == rule)\n\t\t\t\t{\n\t\t\t\t\tdisabledBy.push_back(j);\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (auto& i : temp->getReenabled())\n\t\t\t{\n\t\t\t\tif (i == rule)\n\t\t\t\t{\n\t\t\t\t\treenabledBy.push_back(j);\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (auto& i : temp->getGetOneFree())\n\t\t\t{\n\t\t\t\tif (i == rule)\n\t\t\t\t{\n\t\t\t\t\tgetForFreeFrom.push_back(j);\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (auto& itMap : temp->getGetOneFreeProtected())\n\t\t\t{\n\t\t\t\tfor (auto& i : itMap.second)\n\t\t\t\t{\n\t\t\t\t\tif (i == rule)\n\t\t\t\t\t{\n\t\t\t\t\t\tgetForFreeFrom.push_back(j);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (temp->getLookup())\n\t\t\t{\n\t\t\t\tif (temp->getLookup() == rule)\n\t\t\t\t{\n\t\t\t\t\tlookupOf.push_back(j);\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (auto& i : temp->getRequirements())\n\t\t\t{\n\t\t\t\tif (i == rule)\n\t\t\t\t{\n\t\t\t\t\trequiredByResearch.push_back(j);\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (auto& i : temp->getDependencies())\n\t\t\t{\n\t\t\t\tif (i == rule)\n\t\t\t\t{\n\t\t\t\t\tleadsTo.push_back(j);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// 1. item required\n\t\tif (rule->needItem())\n\t\t{\n\t\t\tif (rule->destroyItem())\n\t\t\t{\n\t\t\t\t_lstLeft->addRow(1, tr(\"STR_ITEM_DESTROYED\").c_str());\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_lstLeft->addRow(1, tr(\"STR_ITEM_REQUIRED\").c_str());\n\t\t\t}\n\t\t\t_lstLeft->setRowColor(row, _blue);\n\t\t\t_leftTopics.push_back(\"-\");\n\t\t\t_leftFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\t\t\tif (rule->getNeededItem())\n\t\t\t{\n\t\t\t\tstd::string itemName = tr(rule->getNeededItem()->getType());\n\t\t\t\titemName.insert(0, \"  \");\n\t\t\t\t_lstLeft->addRow(1, itemName.c_str());\n\t\t\t\t_lstLeft->setRowColor(row, getResearchColor(rule->getNeededItem()->getType()));\n\t\t\t\t_leftTopics.push_back(rule->getNeededItem()->getType());\n\t\t\t\t_leftFlags.push_back(TTV_ITEMS);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tstd::string itemName = \"  -\";\n\t\t\t\t_lstLeft->addRow(1, itemName.c_str());\n\t\t\t\t_lstLeft->setRowColor(row, _white);\n\t\t\t\t_leftTopics.push_back(\"-\");\n\t\t\t\t_leftFlags.push_back(TTV_NONE);\n\t\t\t}\n\t\t\t++row;\n\t\t}\n\n\t\t// 1b. requires services (from base facilities)\n\t\tif (rule->getRequireBaseFunc().any())\n\t\t{\n\t\t\t_lstLeft->addRow(1, tr(\"STR_SERVICES_REQUIRED\").c_str());\n\t\t\t_lstLeft->setRowColor(row, _blue);\n\t\t\t_leftTopics.push_back(\"-\");\n\t\t\t_leftFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\t\t\tfor (const auto& reqServiceType : _game->getMod()->getBaseFunctionNames(rule->getRequireBaseFunc()))\n\t\t\t{\n\t\t\t\tstd::string name = tr(reqServiceType);\n\t\t\t\tname.insert(0, \"  \");\n\t\t\t\t_lstLeft->addRow(1, name.c_str());\n\t\t\t\t_lstLeft->setRowColor(row, _gold);\n\t\t\t\t_leftTopics.push_back(\"-\");\n\t\t\t\t_leftFlags.push_back(TTV_NONE);\n\t\t\t\t++row;\n\t\t\t}\n\t\t}\n\n\t\t// 2. requires\n\t\tif (reqs.size() > 0)\n\t\t{\n\t\t\t_lstLeft->addRow(1, tr(\"STR_REQUIRES\").c_str());\n\t\t\t_lstLeft->setRowColor(row, _blue);\n\t\t\t_leftTopics.push_back(\"-\");\n\t\t\t_leftFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\t\t\tfor (auto* i : reqs)\n\t\t\t{\n\t\t\t\tstd::string name = tr(i->getName());\n\t\t\t\tname.insert(0, \"  \");\n\t\t\t\t_lstLeft->addRow(1, name.c_str());\n\t\t\t\t_lstLeft->setRowColor(row, getResearchColor(i->getName()));\n\t\t\t\t_leftTopics.push_back(i->getName());\n\t\t\t\t_leftFlags.push_back(TTV_RESEARCH);\n\t\t\t\t++row;\n\t\t\t}\n\t\t}\n\n\t\t// 3. depends on\n\t\tif (deps.size() > 0)\n\t\t{\n\t\t\t_lstLeft->addRow(1, tr(\"STR_DEPENDS_ON\").c_str());\n\t\t\t_lstLeft->setRowColor(row, _blue);\n\t\t\t_leftTopics.push_back(\"-\");\n\t\t\t_leftFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\t\t\tfor (auto* i : deps)\n\t\t\t{\n\t\t\t\tif (std::find(unlockedBy.begin(), unlockedBy.end(), i->getName()) != unlockedBy.end())\n\t\t\t\t{\n\t\t\t\t\t// if the same item is also in the \"Unlocked by\" section, skip it\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tstd::string name = tr(i->getName());\n\t\t\t\tname.insert(0, \"  \");\n\t\t\t\t_lstLeft->addRow(1, name.c_str());\n\t\t\t\t_lstLeft->setRowColor(row, getResearchColor(i->getName()));\n\t\t\t\t_leftTopics.push_back(i->getName());\n\t\t\t\t_leftFlags.push_back(TTV_RESEARCH);\n\t\t\t\t++row;\n\t\t\t}\n\t\t}\n\n\t\t// 4a. unlocked by\n\t\tif (unlockedBy.size() > 0)\n\t\t{\n\t\t\t_lstLeft->addRow(1, tr(\"STR_UNLOCKED_BY\").c_str());\n\t\t\t_lstLeft->setRowColor(row, _blue);\n\t\t\t_leftTopics.push_back(\"-\");\n\t\t\t_leftFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\t\t\tfor (const auto& res : unlockedBy)\n\t\t\t{\n\t\t\t\tstd::string name = tr(res);\n\t\t\t\tname.insert(0, \"  \");\n\t\t\t\t_lstLeft->addRow(1, name.c_str());\n\t\t\t\t_lstLeft->setRowColor(row, getResearchColor(res));\n\t\t\t\t_leftTopics.push_back(res);\n\t\t\t\t_leftFlags.push_back(TTV_RESEARCH);\n\t\t\t\t++row;\n\t\t\t}\n\t\t}\n\n\t\t// 4b. disabled by\n\t\tif (disabledBy.size() > 0)\n\t\t{\n\t\t\t_lstLeft->addRow(1, tr(\"STR_DISABLED_BY\").c_str());\n\t\t\t_lstLeft->setRowColor(row, _blue);\n\t\t\t_leftTopics.push_back(\"-\");\n\t\t\t_leftFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\t\t\tfor (const auto& res : disabledBy)\n\t\t\t{\n\t\t\t\tstd::string name = tr(res);\n\t\t\t\tname.insert(0, \"  \");\n\t\t\t\t_lstLeft->addRow(1, name.c_str());\n\t\t\t\t_lstLeft->setRowColor(row, getResearchColor(res));\n\t\t\t\t_leftTopics.push_back(res);\n\t\t\t\t_leftFlags.push_back(TTV_RESEARCH);\n\t\t\t\t++row;\n\t\t\t}\n\t\t}\n\n\t\t// 4c. reenabled by\n\t\tif (reenabledBy.size() > 0)\n\t\t{\n\t\t\t_lstLeft->addRow(1, tr(\"STR_REENABLED_BY\").c_str());\n\t\t\t_lstLeft->setRowColor(row, _blue);\n\t\t\t_leftTopics.push_back(\"-\");\n\t\t\t_leftFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\t\t\tfor (const auto& res : reenabledBy)\n\t\t\t{\n\t\t\t\tstd::string name = tr(res);\n\t\t\t\tname.insert(0, \"  \");\n\t\t\t\t_lstLeft->addRow(1, name.c_str());\n\t\t\t\t_lstLeft->setRowColor(row, getResearchColor(res));\n\t\t\t\t_leftTopics.push_back(res);\n\t\t\t\t_leftFlags.push_back(TTV_RESEARCH);\n\t\t\t\t++row;\n\t\t\t}\n\t\t}\n\n\t\t// 5. get for free from\n\t\tif (getForFreeFrom.size() > 0)\n\t\t{\n\t\t\t_lstLeft->addRow(1, tr(\"STR_GET_FOR_FREE_FROM\").c_str());\n\t\t\t_lstLeft->setRowColor(row, _blue);\n\t\t\t_leftTopics.push_back(\"-\");\n\t\t\t_leftFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\t\t\tfor (const auto& res : getForFreeFrom)\n\t\t\t{\n\t\t\t\tstd::string name = tr(res);\n\t\t\t\tname.insert(0, \"  \");\n\t\t\t\t_lstLeft->addRow(1, name.c_str());\n\t\t\t\t_lstLeft->setRowColor(row, getResearchColor(res));\n\t\t\t\t_leftTopics.push_back(res);\n\t\t\t\t_leftFlags.push_back(TTV_RESEARCH);\n\t\t\t\t++row;\n\t\t\t}\n\t\t}\n\n\t\t// is lookup of\n\t\tif (lookupOf.size() > 0)\n\t\t{\n\t\t\t_lstLeft->addRow(1, tr(\"STR_IS_LOOKUP_OF\").c_str());\n\t\t\t_lstLeft->setRowColor(row, _blue);\n\t\t\t_leftTopics.push_back(\"-\");\n\t\t\t_leftFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\t\t\tfor (const auto& res : lookupOf)\n\t\t\t{\n\t\t\t\tstd::string name = tr(res);\n\t\t\t\tname.insert(0, \"  \");\n\t\t\t\t_lstLeft->addRow(1, name.c_str());\n\t\t\t\t_lstLeft->setRowColor(row, getResearchColor(res));\n\t\t\t\t_leftTopics.push_back(res);\n\t\t\t\t_leftFlags.push_back(TTV_RESEARCH);\n\t\t\t\t++row;\n\t\t\t}\n\t\t}\n\n\t\trow = 0;\n\n\t\t// lookup link\n\t\tif (rule->getLookup())\n\t\t{\n\t\t\t_lstRight->addRow(1, tr(\"STR_LOOKUP\").c_str());\n\t\t\t_lstRight->setRowColor(row, _blue);\n\t\t\t_rightTopics.push_back(\"-\");\n\t\t\t_rightFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\n\t\t\tstd::string name = tr(rule->getLookup()->getName());\n\t\t\tname.insert(0, \"  \");\n\t\t\t_lstRight->addRow(1, name.c_str());\n\t\t\t_lstRight->setRowColor(row, getResearchColor(rule->getLookup()->getName()));\n\t\t\t_rightTopics.push_back(rule->getLookup()->getName());\n\t\t\t_rightFlags.push_back(TTV_RESEARCH);\n\t\t\t++row;\n\t\t}\n\n\t\t// spawned item\n\t\tif (!Mod::isEmptyRuleName(rule->getSpawnedItem()) || !rule->getSpawnedItemList().empty())\n\t\t{\n\t\t\t_lstRight->addRow(1, tr(\"STR_SPAWNED_ITEMS\").c_str());\n\t\t\t_lstRight->setRowColor(row, _blue);\n\t\t\t_rightTopics.push_back(\"-\");\n\t\t\t_rightFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\t\t}\n\t\tif (!Mod::isEmptyRuleName(rule->getSpawnedItem()))\n\t\t{\n\t\t\tstd::string name = tr(rule->getSpawnedItem());\n\t\t\tname.insert(0, \"  \");\n\t\t\tif (rule->getSpawnedItemCount() > 1)\n\t\t\t{\n\t\t\t\tname.append(\" x\");\n\t\t\t\tname.append(std::to_string(rule->getSpawnedItemCount()));\n\t\t\t}\n\t\t\t_lstRight->addRow(1, name.c_str());\n\t\t\t_lstRight->setRowColor(row, _white);\n\t\t\t_rightTopics.push_back(rule->getSpawnedItem());\n\t\t\t_rightFlags.push_back(TTV_ITEMS);\n\t\t\t++row;\n\t\t}\n\t\tfor (auto& sil : rule->getSpawnedItemList())\n\t\t{\n\t\t\tstd::string name = tr(sil);\n\t\t\tname.insert(0, \"  \");\n\t\t\t_lstRight->addRow(1, name.c_str());\n\t\t\t_lstRight->setRowColor(row, _white);\n\t\t\t_rightTopics.push_back(sil);\n\t\t\t_rightFlags.push_back(TTV_ITEMS);\n\t\t\t++row;\n\t\t}\n\n\t\t// spawned event\n\t\tif (!Mod::isEmptyRuleName(rule->getSpawnedEvent()))\n\t\t{\n\t\t\t_lstRight->addRow(1, tr(\"STR_SPAWNED_EVENT\").c_str());\n\t\t\t_lstRight->setRowColor(row, _blue);\n\t\t\t_rightTopics.push_back(\"-\");\n\t\t\t_rightFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\n\t\t\tstd::string name = tr(rule->getSpawnedEvent());\n\t\t\tname.insert(0, \"  \");\n\t\t\t_lstRight->addRow(1, name.c_str());\n\t\t\t_lstRight->setRowColor(row, _white);\n\t\t\t_rightTopics.push_back(\"-\");\n\t\t\t_rightFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\t\t}\n\n\t\t// spawned random events\n\t\tauto& randomEvents = rule->getEventsRaw();\n\t\tif (!randomEvents.empty())\n\t\t{\n\t\t\t_lstRight->addRow(1, tr(\"STR_RANDOM_EVENTS\").c_str());\n\t\t\t_lstRight->setRowColor(row, _blue);\n\t\t\t_rightTopics.push_back(\"-\");\n\t\t\t_rightFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\t\t\tfor (auto& randomEvent : randomEvents.getChoicesRaw())\n\t\t\t{\n\t\t\t\tstd::ostringstream chance;\n\t\t\t\tchance << \"  \" << tr(randomEvent.first) << \": \" << randomEvent.second;\n\t\t\t\t_lstRight->addRow(1, chance.str().c_str());\n\t\t\t\t_lstRight->setRowColor(row, _white);\n\t\t\t\t_rightTopics.push_back(\"-\");\n\t\t\t\t_rightFlags.push_back(TTV_NONE);\n\t\t\t\t++row;\n\t\t\t}\n\t\t}\n\n\t\t// 6. required by\n\t\tif (requiredByResearch.size() > 0 || requiredByManufacture.size() > 0 || requiredByFacilities.size() > 0 || requiredByItems.size() > 0 || requiredByCrafts.size() > 0)\n\t\t{\n\t\t\t_lstRight->addRow(1, tr(\"STR_REQUIRED_BY\").c_str());\n\t\t\t_lstRight->setRowColor(row, _blue);\n\t\t\t_rightTopics.push_back(\"-\");\n\t\t\t_rightFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\t\t}\n\n\t\t// 6a. required by research\n\t\tif (requiredByResearch.size() > 0)\n\t\t{\n\t\t\tfor (const auto& res : requiredByResearch)\n\t\t\t{\n\t\t\t\tstd::string name = tr(res);\n\t\t\t\tname.insert(0, \"  \");\n\t\t\t\t_lstRight->addRow(1, name.c_str());\n\t\t\t\t_lstRight->setRowColor(row, getResearchColor(res));\n\t\t\t\t_rightTopics.push_back(res);\n\t\t\t\t_rightFlags.push_back(TTV_RESEARCH);\n\t\t\t\t++row;\n\t\t\t}\n\t\t}\n\n\t\t// 6b. required by manufacture\n\t\tif (requiredByManufacture.size() > 0)\n\t\t{\n\t\t\tfor (const auto& manuf : requiredByManufacture)\n\t\t\t{\n\t\t\t\tstd::string name = tr(manuf);\n\t\t\t\tname.insert(0, \"  \");\n\t\t\t\tname.append(tr(\"STR_M_FLAG\"));\n\t\t\t\t_lstRight->addRow(1, name.c_str());\n\t\t\t\tif (!isDiscoveredManufacture(manuf))\n\t\t\t\t{\n\t\t\t\t\t_lstRight->setRowColor(row, _pink);\n\t\t\t\t}\n\t\t\t\t_rightTopics.push_back(manuf);\n\t\t\t\t_rightFlags.push_back(TTV_MANUFACTURING);\n\t\t\t\t++row;\n\t\t\t}\n\t\t}\n\n\t\t// 6c. required by facilities\n\t\tif (requiredByFacilities.size() > 0)\n\t\t{\n\t\t\tfor (const auto& facType : requiredByFacilities)\n\t\t\t{\n\t\t\t\tstd::string name = tr(facType);\n\t\t\t\tname.insert(0, \"  \");\n\t\t\t\tname.append(tr(\"STR_F_FLAG\"));\n\t\t\t\t_lstRight->addRow(1, name.c_str());\n\t\t\t\tif (!isDiscoveredFacility(facType))\n\t\t\t\t{\n\t\t\t\t\t_lstRight->setRowColor(row, _pink);\n\t\t\t\t}\n\t\t\t\t_rightTopics.push_back(facType);\n\t\t\t\t_rightFlags.push_back(TTV_FACILITIES);\n\t\t\t\t++row;\n\t\t\t}\n\t\t}\n\n\t\t// 6d. required by items\n\t\tif (requiredByItems.size() > 0)\n\t\t{\n\t\t\tfor (const auto& itemType : requiredByItems)\n\t\t\t{\n\t\t\t\tstd::string name = tr(itemType);\n\t\t\t\tname.insert(0, \"  \");\n\t\t\t\tname.append(tr(\"STR_I_FLAG\"));\n\t\t\t\t_lstRight->addRow(1, name.c_str());\n\t\t\t\tif (!isProtectedAndDiscoveredItem(itemType))\n\t\t\t\t{\n\t\t\t\t\t_lstRight->setRowColor(row, _pink);\n\t\t\t\t}\n\t\t\t\t_rightTopics.push_back(itemType);\n\t\t\t\t_rightFlags.push_back(TTV_ITEMS);\n\t\t\t\t++row;\n\t\t\t}\n\t\t}\n\n\t\t// 6e. required by crafts\n\t\tif (requiredByCrafts.size() > 0)\n\t\t{\n\t\t\tfor (const auto& craftType : requiredByCrafts)\n\t\t\t{\n\t\t\t\tstd::string name = tr(craftType);\n\t\t\t\tname.insert(0, \"  \");\n\t\t\t\tname.append(tr(\"STR_C_FLAG\"));\n\t\t\t\t_lstRight->addRow(1, name.c_str());\n\t\t\t\tif (!isDiscoveredCraft(craftType))\n\t\t\t\t{\n\t\t\t\t\t_lstRight->setRowColor(row, _pink);\n\t\t\t\t}\n\t\t\t\t_rightTopics.push_back(craftType);\n\t\t\t\t_rightFlags.push_back(TTV_CRAFTS);\n\t\t\t\t++row;\n\t\t\t}\n\t\t}\n\n\t\t// 6f. required by transformations\n\t\tif (requiredByTransformations.size() > 0)\n\t\t{\n\t\t\t_lstRight->addRow(1, tr(\"STR_REQUIRED_BY_TRANSFORMATIONS\").c_str());\n\t\t\t_lstRight->setRowColor(row, _blue);\n\t\t\t_rightTopics.push_back(\"-\");\n\t\t\t_rightFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\n\t\t\tfor (const auto& transformationType : requiredByTransformations)\n\t\t\t{\n\t\t\t\tstd::string name = tr(transformationType);\n\t\t\t\tname.insert(0, \"  \");\n\t\t\t\t_lstRight->addRow(1, name.c_str());\n\t\t\t\t_lstRight->setRowColor(row, _white);\n\t\t\t\t_rightTopics.push_back(\"-\");\n\t\t\t\t_rightFlags.push_back(TTV_NONE);\n\t\t\t\t++row;\n\t\t\t}\n\t\t}\n\n\t\t// 7. leads to\n\t\tif (leadsTo.size() > 0)\n\t\t{\n\t\t\t_lstRight->addRow(1, tr(\"STR_LEADS_TO\").c_str());\n\t\t\t_lstRight->setRowColor(row, _blue);\n\t\t\t_rightTopics.push_back(\"-\");\n\t\t\t_rightFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\t\t\tfor (const auto& res : leadsTo)\n\t\t\t{\n\t\t\t\tconst RuleResearch *iTemp = _game->getMod()->getResearch(res);\n\t\t\t\tif (std::find(unlocks.begin(), unlocks.end(), iTemp) != unlocks.end())\n\t\t\t\t{\n\t\t\t\t\t// if the same topic is also in the \"Unlocks\" section, skip it\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tstd::string name = tr(res);\n\t\t\t\tname.insert(0, \"  \");\n\t\t\t\t_lstRight->addRow(1, name.c_str());\n\t\t\t\t_lstRight->setRowColor(row, getResearchColor(res));\n\t\t\t\t_rightTopics.push_back(res);\n\t\t\t\t_rightFlags.push_back(TTV_RESEARCH);\n\t\t\t\t++row;\n\t\t\t}\n\t\t}\n\n\t\t// 8a. unlocks\n\t\tif (unlocks.size() > 0)\n\t\t{\n\t\t\t_lstRight->addRow(1, tr(\"STR_UNLOCKS\").c_str());\n\t\t\t_lstRight->setRowColor(row, _blue);\n\t\t\t_rightTopics.push_back(\"-\");\n\t\t\t_rightFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\t\t\tfor (auto* i : unlocks)\n\t\t\t{\n\t\t\t\tstd::string name = tr(i->getName());\n\t\t\t\tname.insert(0, \"  \");\n\t\t\t\t_lstRight->addRow(1, name.c_str());\n\t\t\t\t_lstRight->setRowColor(row, getResearchColor(i->getName()));\n\t\t\t\t_rightTopics.push_back(i->getName());\n\t\t\t\t_rightFlags.push_back(TTV_RESEARCH);\n\t\t\t\t++row;\n\t\t\t}\n\t\t}\n\n\t\t// 8b. disables\n\t\tif (disables.size() > 0)\n\t\t{\n\t\t\t_lstRight->addRow(1, tr(\"STR_DISABLES\").c_str());\n\t\t\t_lstRight->setRowColor(row, _blue);\n\t\t\t_rightTopics.push_back(\"-\");\n\t\t\t_rightFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\t\t\tfor (auto* i : disables)\n\t\t\t{\n\t\t\t\tstd::string name = tr(i->getName());\n\t\t\t\tname.insert(0, \"  \");\n\t\t\t\t_lstRight->addRow(1, name.c_str());\n\t\t\t\t_lstRight->setRowColor(row, getResearchColor(i->getName()));\n\t\t\t\t_rightTopics.push_back(i->getName());\n\t\t\t\t_rightFlags.push_back(TTV_RESEARCH);\n\t\t\t\t++row;\n\t\t\t}\n\t\t}\n\n\t\t// 8c. reenables\n\t\tif (reenables.size() > 0)\n\t\t{\n\t\t\t_lstRight->addRow(1, tr(\"STR_REENABLES\").c_str());\n\t\t\t_lstRight->setRowColor(row, _blue);\n\t\t\t_rightTopics.push_back(\"-\");\n\t\t\t_rightFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\t\t\tfor (auto* i : reenables)\n\t\t\t{\n\t\t\t\tstd::string name = tr(i->getName());\n\t\t\t\tname.insert(0, \"  \");\n\t\t\t\t_lstRight->addRow(1, name.c_str());\n\t\t\t\t_lstRight->setRowColor(row, getResearchColor(i->getName()));\n\t\t\t\t_rightTopics.push_back(i->getName());\n\t\t\t\t_rightFlags.push_back(TTV_RESEARCH);\n\t\t\t\t++row;\n\t\t\t}\n\t\t}\n\n\t\t// 9. gives one for free\n\t\tif (free.size() > 0 || freeProtected.size() > 0)\n\t\t{\n\t\t\tint remaining = 0;\n\t\t\tint total = 0;\n\t\t\tfor (auto* i : free)\n\t\t\t{\n\t\t\t\tif (getResearchColor(i->getName()) == _pink)\n\t\t\t\t{\n\t\t\t\t\t++remaining;\n\t\t\t\t}\n\t\t\t\t++total;\n\t\t\t}\n\t\t\tfor (auto& itMap : freeProtected)\n\t\t\t{\n\t\t\t\tfor (auto* i : itMap.second)\n\t\t\t\t{\n\t\t\t\t\tif (getResearchColor(i->getName()) == _pink)\n\t\t\t\t\t{\n\t\t\t\t\t\t++remaining;\n\t\t\t\t\t}\n\t\t\t\t\t++total;\n\t\t\t\t}\n\t\t\t}\n\t\t\tstd::ostringstream ssFree;\n\t\t\tif (rule->sequentialGetOneFree())\n\t\t\t{\n\t\t\t\tssFree << tr(\"STR_GIVES_ONE_FOR_FREE_SEQ\");\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tssFree << tr(\"STR_GIVES_ONE_FOR_FREE\");\n\t\t\t}\n\t\t\tssFree << \" \" << remaining << \"/\" << total;\n\t\t\t_lstRight->addRow(1, ssFree.str().c_str());\n\t\t\t_lstRight->setRowColor(row, _blue);\n\t\t\t_rightTopics.push_back(\"-\");\n\t\t\t_rightFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\t\t\tfor (auto* i : free)\n\t\t\t{\n\t\t\t\tstd::string name = tr(i->getName());\n\t\t\t\tname.insert(0, \"  \");\n\t\t\t\t_lstRight->addRow(1, name.c_str());\n\t\t\t\t_lstRight->setRowColor(row, getResearchColor(i->getName()));\n\t\t\t\t_rightTopics.push_back(i->getName());\n\t\t\t\t_rightFlags.push_back(TTV_RESEARCH);\n\t\t\t\t++row;\n\t\t\t}\n\t\t\tfor (auto& itMap : freeProtected)\n\t\t\t{\n\t\t\t\tstd::string name2 = tr(itMap.first->getName());\n\t\t\t\tname2.insert(0, \" \");\n\t\t\t\tname2.append(\":\");\n\t\t\t\t_lstRight->addRow(1, name2.c_str());\n\t\t\t\t_lstRight->setRowColor(row, getAltResearchColor(itMap.first->getName()));\n\t\t\t\t_rightTopics.push_back(itMap.first->getName());\n\t\t\t\t_rightFlags.push_back(TTV_RESEARCH);\n\t\t\t\t++row;\n\t\t\t\tfor (auto* i : itMap.second)\n\t\t\t\t{\n\t\t\t\t\tstd::string name = tr(i->getName());\n\t\t\t\t\tname.insert(0, \"  \");\n\t\t\t\t\t_lstRight->addRow(1, name.c_str());\n\t\t\t\t\t_lstRight->setRowColor(row, getResearchColor(i->getName()));\n\t\t\t\t\t_rightTopics.push_back(i->getName());\n\t\t\t\t\t_rightFlags.push_back(TTV_RESEARCH);\n\t\t\t\t\t++row;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// 10. unlocks/disables alien missions, game arcs or geoscape events\n\t\tstd::unordered_set<std::string> unlocksArcs, disablesArcs;\n\t\tstd::unordered_set<std::string> unlocksEvents, disablesEvents;\n\t\tstd::unordered_set<std::string> unlocksMissions, disablesMissions;\n\t\tbool affectsGameProgression = false;\n\n\t\tfor (auto& arcScriptId : *_game->getMod()->getArcScriptList())\n\t\t{\n\t\t\tauto* arcScript = _game->getMod()->getArcScript(arcScriptId, false);\n\t\t\tif (arcScript)\n\t\t\t{\n\t\t\t\tfor (auto& trigger : arcScript->getResearchTriggers())\n\t\t\t\t{\n\t\t\t\t\tif (trigger.first == _selectedTopic)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (trigger.second)\n\t\t\t\t\t\t\tunlocksArcs.insert(arcScriptId);\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tdisablesArcs.insert(arcScriptId);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfor (auto& eventScriptId : *_game->getMod()->getEventScriptList())\n\t\t{\n\t\t\tauto* eventScript = _game->getMod()->getEventScript(eventScriptId, false);\n\t\t\tif (eventScript)\n\t\t\t{\n\t\t\t\tfor (auto& trigger : eventScript->getResearchTriggers())\n\t\t\t\t{\n\t\t\t\t\tif (trigger.first == _selectedTopic)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (eventScript->getAffectsGameProgression()) affectsGameProgression = true; // remember for later\n\t\t\t\t\t\tif (trigger.second)\n\t\t\t\t\t\t\tunlocksEvents.insert(eventScriptId);\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tdisablesEvents.insert(eventScriptId);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfor (auto& missionScriptId : *_game->getMod()->getMissionScriptList())\n\t\t{\n\t\t\tauto* missionScript = _game->getMod()->getMissionScript(missionScriptId, false);\n\t\t\tif (missionScript)\n\t\t\t{\n\t\t\t\tfor (auto& trigger : missionScript->getResearchTriggers())\n\t\t\t\t{\n\t\t\t\t\tif (trigger.first == _selectedTopic)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (trigger.second)\n\t\t\t\t\t\t\tunlocksMissions.insert(missionScriptId);\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tdisablesMissions.insert(missionScriptId);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tbool showDetails = false;\n\t\tif (Options::isPasswordCorrect() && _game->isAltPressed())\n\t\t{\n\t\t\tshowDetails = true;\n\t\t}\n\t\tif (showDetails)\n\t\t{\n\t\t\tauto addGameProgressionEntry = [&](const std::unordered_set<std::string>& list, const std::string& label)\n\t\t\t{\n\t\t\t\tif (!list.empty())\n\t\t\t\t{\n\t\t\t\t\t_lstRight->addRow(1, tr(label).c_str());\n\t\t\t\t\t_lstRight->setRowColor(row, _blue);\n\t\t\t\t\t_rightTopics.push_back(\"-\");\n\t\t\t\t\t_rightFlags.push_back(TTV_NONE);\n\t\t\t\t\t++row;\n\t\t\t\t\tfor (auto& i : list)\n\t\t\t\t\t{\n\t\t\t\t\t\tstd::ostringstream name;\n\t\t\t\t\t\tname << \"  \" << tr(i);\n\t\t\t\t\t\t_lstRight->addRow(1, name.str().c_str());\n\t\t\t\t\t\t_lstRight->setRowColor(row, _white);\n\t\t\t\t\t\t_rightTopics.push_back(\"-\");\n\t\t\t\t\t\t_rightFlags.push_back(TTV_NONE);\n\t\t\t\t\t\t++row;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\n\t\t\taddGameProgressionEntry(unlocksArcs, \"STR_UNLOCKS_ARCS\");\n\t\t\taddGameProgressionEntry(disablesArcs, \"STR_DISABLES_ARCS\");\n\n\t\t\taddGameProgressionEntry(unlocksMissions, \"STR_UNLOCKS_MISSIONS\");\n\t\t\taddGameProgressionEntry(disablesMissions, \"STR_DISABLES_MISSIONS\");\n\n\t\t\taddGameProgressionEntry(unlocksEvents, \"STR_UNLOCKS_EVENTS\");\n\t\t\taddGameProgressionEntry(disablesEvents, \"STR_DISABLES_EVENTS\");\n\t\t}\n\t\telse\n\t\t{\n\t\t\tint showDisclaimer = 0;\n\t\t\tif (!unlocksMissions.empty() || !disablesMissions.empty() || !unlocksArcs.empty() || !disablesArcs.empty())\n\t\t\t{\n\t\t\t\tshowDisclaimer = 1; // STR_AFFECTS_GAME_PROGRESSION\n\t\t\t}\n\t\t\telse if (!unlocksEvents.empty() || !disablesEvents.empty())\n\t\t\t{\n\t\t\t\tif (affectsGameProgression)\n\t\t\t\t{\n\t\t\t\t\tshowDisclaimer = 1; // STR_AFFECTS_GAME_PROGRESSION\n\t\t\t\t}\n\t\t\t\telse if (Options::isPasswordCorrect())\n\t\t\t\t{\n\t\t\t\t\tshowDisclaimer = 2; // .\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (showDisclaimer > 0)\n\t\t\t{\n\t\t\t\t_lstRight->addRow(1, tr(\"STR_AFFECTS_GAME_PROGRESSION\").c_str());\n\t\t\t\tif (showDisclaimer == 1)\n\t\t\t\t\t_lstRight->setRowColor(row, _gold);\n\t\t\t\telse\n\t\t\t\t\t_lstRight->setRowColor(row, _white);\n\t\t\t\t_rightTopics.push_back(\"-\");\n\t\t\t\t_rightFlags.push_back(TTV_NONE);\n\t\t\t\t++row;\n\t\t\t}\n\t\t}\n\t}\n\telse if (_selectedFlag == TTV_MANUFACTURING)\n\t{\n\t\tint row = 0;\n\t\tRuleManufacture *rule = _game->getMod()->getManufacture(_selectedTopic);\n\t\tif (rule == 0)\n\t\t\treturn;\n\n\t\t// 1. requires\n\t\tconst std::vector<const RuleResearch*> reqs = rule->getRequirements();\n\t\tif (reqs.size() > 0)\n\t\t{\n\t\t\t_lstLeft->addRow(1, tr(\"STR_RESEARCH_REQUIRED\").c_str());\n\t\t\t_lstLeft->setRowColor(row, _blue);\n\t\t\t_leftTopics.push_back(\"-\");\n\t\t\t_leftFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\t\t\tfor (auto* i : reqs)\n\t\t\t{\n\t\t\t\tstd::string name = tr(i->getName());\n\t\t\t\tname.insert(0, \"  \");\n\t\t\t\t_lstLeft->addRow(1, name.c_str());\n\t\t\t\t_lstLeft->setRowColor(row, getResearchColor(i->getName()));\n\t\t\t\t_leftTopics.push_back(i->getName());\n\t\t\t\t_leftFlags.push_back(TTV_RESEARCH);\n\t\t\t\t++row;\n\t\t\t}\n\t\t}\n\n\t\t// 2. requires services (from base facilities)\n\t\tif (rule->getRequireBaseFunc().any())\n\t\t{\n\t\t\t_lstLeft->addRow(1, tr(\"STR_SERVICES_REQUIRED\").c_str());\n\t\t\t_lstLeft->setRowColor(row, _blue);\n\t\t\t_leftTopics.push_back(\"-\");\n\t\t\t_leftFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\t\t\tfor (const auto& requiredServiceType : _game->getMod()->getBaseFunctionNames(rule->getRequireBaseFunc()))\n\t\t\t{\n\t\t\t\tstd::string name = tr(requiredServiceType);\n\t\t\t\tname.insert(0, \"  \");\n\t\t\t\t_lstLeft->addRow(1, name.c_str());\n\t\t\t\t_lstLeft->setRowColor(row, _gold);\n\t\t\t\t_leftTopics.push_back(\"-\");\n\t\t\t\t_leftFlags.push_back(TTV_NONE);\n\t\t\t\t++row;\n\t\t\t}\n\t\t}\n\n\t\t// 3. inputs\n\t\tconst std::map<const RuleCraft*, int> craftInputs = rule->getRequiredCrafts();\n\t\tconst std::map<const RuleItem*, int> inputs = rule->getRequiredItems();\n\t\tif (inputs.size() > 0 || craftInputs.size() > 0)\n\t\t{\n\t\t\t_lstLeft->addRow(1, tr(\"STR_MATERIALS_REQUIRED\").c_str());\n\t\t\t_lstLeft->setRowColor(row, _blue);\n\t\t\t_leftTopics.push_back(\"-\");\n\t\t\t_leftFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\t\t\tfor (auto& i : craftInputs)\n\t\t\t{\n\t\t\t\tstd::ostringstream name;\n\t\t\t\tname << \"  \";\n\t\t\t\tname << tr(i.first->getType());\n\t\t\t\tname << \": \";\n\t\t\t\tname << i.second;\n\t\t\t\t_lstLeft->addRow(1, name.str().c_str());\n\t\t\t\t_lstLeft->setRowColor(row, _white);\n\t\t\t\t_leftTopics.push_back(\"-\");\n\t\t\t\t_leftFlags.push_back(TTV_NONE);\n\t\t\t\t++row;\n\t\t\t}\n\t\t\tfor (auto& i : inputs)\n\t\t\t{\n\t\t\t\tstd::ostringstream name;\n\t\t\t\tname << \"  \";\n\t\t\t\tname << tr(i.first->getType());\n\t\t\t\tname << \": \";\n\t\t\t\tname << i.second;\n\t\t\t\t_lstLeft->addRow(1, name.str().c_str());\n\t\t\t\t_lstLeft->setRowColor(row, _white);\n\t\t\t\t_leftTopics.push_back(i.first->getType());\n\t\t\t\t_leftFlags.push_back(TTV_ITEMS);\n\t\t\t\t++row;\n\t\t\t}\n\t\t}\n\n\t\t// empty line\n\t\t_lstLeft->addRow(1, \"\");\n\t\t_leftTopics.push_back(\"-\");\n\t\t_leftFlags.push_back(TTV_NONE);\n\t\t++row;\n\n\t\t// cost per unit\n\t\tif (rule->getManufactureCost() > 0)\n\t\t{\n\t\t\t_lstLeft->addRow(1, tr(\"STR_TTV_COST_PER_UNIT\").c_str());\n\t\t\t_lstLeft->setRowColor(row, _blue);\n\t\t\t_leftTopics.push_back(\"-\");\n\t\t\t_leftFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\n\t\t\tstd::ostringstream txt;\n\t\t\ttxt << \"  \";\n\t\t\ttxt << Unicode::formatFunding(rule->getManufactureCost());\n\t\t\t_lstLeft->addRow(1, txt.str().c_str());\n\t\t\t_lstLeft->setRowColor(row, _white);\n\t\t\t_leftTopics.push_back(\"-\");\n\t\t\t_leftFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\t\t}\n\t\t// engineer hours\n\t\tif (rule->getManufactureTime() > 0)\n\t\t{\n\t\t\t_lstLeft->addRow(1, tr(\"STR_TTV_ENGINEER_HOURS\").c_str());\n\t\t\t_lstLeft->setRowColor(row, _blue);\n\t\t\t_leftTopics.push_back(\"-\");\n\t\t\t_leftFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\n\t\t\tint days = rule->getManufactureTime() / 24;\n\t\t\tint hours = rule->getManufactureTime() % 24;\n\t\t\tstd::ostringstream txt;\n\t\t\ttxt << \"  \";\n\t\t\ttxt << rule->getManufactureTime();\n\t\t\ttxt << \" (\";\n\t\t\tif (days > 0)\n\t\t\t{\n\t\t\t\ttxt << tr(\"STR_DAY_SHORT\").arg(days);\n\t\t\t}\n\t\t\tif (hours > 0)\n\t\t\t{\n\t\t\t\tif (days > 0)\n\t\t\t\t{\n\t\t\t\t\ttxt << \"/\";\n\t\t\t\t}\n\t\t\t\ttxt << tr(\"STR_HOUR_SHORT\").arg(hours);\n\t\t\t}\n\t\t\ttxt << \")\";\n\t\t\t_lstLeft->addRow(1, txt.str().c_str());\n\t\t\t_lstLeft->setRowColor(row, _white);\n\t\t\t_leftTopics.push_back(\"-\");\n\t\t\t_leftFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\t\t}\n\t\t// work space required\n\t\tif (rule->getRequiredSpace() > 0)\n\t\t{\n\t\t\t_lstLeft->addRow(1, tr(\"STR_TTV_WORK_SPACE_REQUIRED\").c_str());\n\t\t\t_lstLeft->setRowColor(row, _blue);\n\t\t\t_leftTopics.push_back(\"-\");\n\t\t\t_leftFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\n\t\t\tstd::ostringstream txt;\n\t\t\ttxt << \"  \";\n\t\t\ttxt << rule->getRequiredSpace();\n\t\t\t_lstLeft->addRow(1, txt.str().c_str());\n\t\t\t_lstLeft->setRowColor(row, _white);\n\t\t\t_leftTopics.push_back(\"-\");\n\t\t\t_leftFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\t\t}\n\n\t\trow = 0;\n\n\t\t// 4. outputs\n\t\tconst std::map<const RuleItem*, int> outputs = rule->getProducedItems();\n\t\tif (outputs.size() > 0 || rule->getProducedCraft())\n\t\t{\n\t\t\t_lstRight->addRow(1, tr(\"STR_ITEMS_PRODUCED\").c_str());\n\t\t\t_lstRight->setRowColor(row, _blue);\n\t\t\t_rightTopics.push_back(\"-\");\n\t\t\t_rightFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\t\t\tif (rule->getProducedCraft())\n\t\t\t{\n\t\t\t\tstd::ostringstream name;\n\t\t\t\tname << \"  \";\n\t\t\t\tname << tr(rule->getProducedCraft()->getType());\n\t\t\t\tname << \": 1\";\n\t\t\t\t_lstRight->addRow(1, name.str().c_str());\n\t\t\t\t_lstRight->setRowColor(row, _white);\n\t\t\t\t_rightTopics.push_back(\"-\");\n\t\t\t\t_rightFlags.push_back(TTV_NONE);\n\t\t\t\t++row;\n\t\t\t}\n\t\t\tfor (auto& i : outputs)\n\t\t\t{\n\t\t\t\tstd::ostringstream name;\n\t\t\t\tname << \"  \";\n\t\t\t\tname << tr(i.first->getType());\n\t\t\t\tname << \": \";\n\t\t\t\tname << i.second;\n\t\t\t\t_lstRight->addRow(1, name.str().c_str());\n\t\t\t\t_lstRight->setRowColor(row, _white);\n\t\t\t\t_rightTopics.push_back(i.first->getType());\n\t\t\t\t_rightFlags.push_back(TTV_ITEMS);\n\t\t\t\t++row;\n\t\t\t}\n\t\t}\n\n\t\t// 4b. random outputs\n\t\tauto& randomOutputs = rule->getRandomProducedItems();\n\t\tif (randomOutputs.size() > 0)\n\t\t{\n\t\t\t_lstRight->addRow(1, tr(\"STR_RANDOM_PRODUCTION_DISCLAIMER\").c_str());\n\t\t\t_lstRight->setRowColor(row, _blue);\n\t\t\t_rightTopics.push_back(\"-\");\n\t\t\t_rightFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\t\t\tint total = 0;\n\t\t\tfor (auto& n : randomOutputs)\n\t\t\t{\n\t\t\t\ttotal += n.first;\n\t\t\t}\n\t\t\tfor (auto& randomOutput : randomOutputs)\n\t\t\t{\n\t\t\t\tstd::ostringstream chance;\n\t\t\t\tchance << \" \" << randomOutput.first * 100 / total << \"%\";\n\t\t\t\t_lstRight->addRow(1, chance.str().c_str());\n\t\t\t\t_lstRight->setRowColor(row, _gold);\n\t\t\t\t_rightTopics.push_back(\"-\");\n\t\t\t\t_rightFlags.push_back(TTV_NONE);\n\t\t\t\t++row;\n\t\t\t\tfor (auto& i : randomOutput.second)\n\t\t\t\t{\n\t\t\t\t\tstd::ostringstream name;\n\t\t\t\t\tname << \"  \";\n\t\t\t\t\tname << tr(i.first->getType());\n\t\t\t\t\tname << \": \";\n\t\t\t\t\tname << i.second;\n\t\t\t\t\t_lstRight->addRow(1, name.str().c_str());\n\t\t\t\t\t_lstRight->setRowColor(row, _white);\n\t\t\t\t\t_rightTopics.push_back(i.first->getType());\n\t\t\t\t\t_rightFlags.push_back(TTV_ITEMS);\n\t\t\t\t\t++row;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// 4c. random events\n\t\tauto& randomEvents = rule->getEventsRaw();\n\t\tif (!randomEvents.empty())\n\t\t{\n\t\t\t_lstRight->addRow(1, tr(\"STR_RANDOM_EVENTS\").c_str());\n\t\t\t_lstRight->setRowColor(row, _blue);\n\t\t\t_rightTopics.push_back(\"-\");\n\t\t\t_rightFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\t\t\tfor (auto& randomEvent : randomEvents.getChoicesRaw())\n\t\t\t{\n\t\t\t\tstd::ostringstream chance;\n\t\t\t\tchance << \"  \" << tr(randomEvent.first) << \": \" << randomEvent.second;\n\t\t\t\t_lstRight->addRow(1, chance.str().c_str());\n\t\t\t\t_lstRight->setRowColor(row, _white);\n\t\t\t\t_rightTopics.push_back(\"-\");\n\t\t\t\t_rightFlags.push_back(TTV_NONE);\n\t\t\t\t++row;\n\t\t\t}\n\t\t}\n\n\t\t// 5. person joining\n\t\tif (rule->getSpawnedPersonType() != \"\")\n\t\t{\n\t\t\t_lstRight->addRow(1, tr(\"STR_PERSON_RECRUITED\").c_str());\n\t\t\t_lstRight->setRowColor(row, _blue);\n\t\t\t_rightTopics.push_back(\"-\");\n\t\t\t_rightFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\n\t\t\t// person joining\n\t\t\tstd::ostringstream name;\n\t\t\tname << \"  \";\n\t\t\tif (rule->getSpawnedSoldierTemplate().yaml != \"\")\n\t\t\t{\n\t\t\t\tname << \"*\";\n\t\t\t}\n\t\t\tname << tr(rule->getSpawnedPersonName() != \"\" ? rule->getSpawnedPersonName() : rule->getSpawnedPersonType());\n\t\t\t_lstRight->addRow(1, name.str().c_str());\n\t\t\t_lstRight->setRowColor(row, _white);\n\t\t\t_rightTopics.push_back(\"-\");\n\t\t\t_rightFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\t\t}\n\t}\n\telse if (_selectedFlag == TTV_FACILITIES)\n\t{\n\t\tint row = 0;\n\t\tRuleBaseFacility *rule = _game->getMod()->getBaseFacility(_selectedTopic);\n\t\tif (rule == 0)\n\t\t\treturn;\n\n\t\t// 1. requires\n\t\tconst std::vector<std::string> reqs = rule->getRequirements();\n\t\tif (reqs.size() > 0)\n\t\t{\n\t\t\t_lstLeft->addRow(1, tr(\"STR_RESEARCH_REQUIRED\").c_str());\n\t\t\t_lstLeft->setRowColor(row, _blue);\n\t\t\t_leftTopics.push_back(\"-\");\n\t\t\t_leftFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\t\t\tfor (const auto& res : reqs)\n\t\t\t{\n\t\t\t\tstd::string name = tr(res);\n\t\t\t\tname.insert(0, \"  \");\n\t\t\t\t_lstLeft->addRow(1, name.c_str());\n\t\t\t\t_lstLeft->setRowColor(row, getResearchColor(res));\n\t\t\t\t_leftTopics.push_back(res);\n\t\t\t\t_leftFlags.push_back(TTV_RESEARCH);\n\t\t\t\t++row;\n\t\t\t}\n\t\t}\n\n\t\t// 2. requires services (from other base facilities)\n\t\tif (rule->getRequireBaseFunc().any())\n\t\t{\n\t\t\t_lstLeft->addRow(1, tr(\"STR_SERVICES_REQUIRED\").c_str());\n\t\t\t_lstLeft->setRowColor(row, _blue);\n\t\t\t_leftTopics.push_back(\"-\");\n\t\t\t_leftFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\t\t\tfor (const auto& requiredServiceType : _game->getMod()->getBaseFunctionNames(rule->getRequireBaseFunc()))\n\t\t\t{\n\t\t\t\tstd::string name = tr(requiredServiceType);\n\t\t\t\tname.insert(0, \"  \");\n\t\t\t\t_lstLeft->addRow(1, name.c_str());\n\t\t\t\t_lstLeft->setRowColor(row, _gold);\n\t\t\t\t_leftTopics.push_back(\"-\");\n\t\t\t\t_leftFlags.push_back(TTV_NONE);\n\t\t\t\t++row;\n\t\t\t}\n\t\t}\n\n\t\trow = 0;\n\n\t\t// 3. provides services\n\t\tif (rule->getProvidedBaseFunc().any())\n\t\t{\n\t\t\t_lstRight->addRow(1, tr(\"STR_SERVICES_PROVIDED\").c_str());\n\t\t\t_lstRight->setRowColor(row, _blue);\n\t\t\t_rightTopics.push_back(\"-\");\n\t\t\t_rightFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\t\t\tfor (const auto& providedServiceType : _game->getMod()->getBaseFunctionNames(rule->getProvidedBaseFunc()))\n\t\t\t{\n\t\t\t\tstd::string name = tr(providedServiceType);\n\t\t\t\tname.insert(0, \"  \");\n\t\t\t\t_lstRight->addRow(1, name.c_str());\n\t\t\t\t_lstRight->setRowColor(row, _gold);\n\t\t\t\t_rightTopics.push_back(\"-\");\n\t\t\t\t_rightFlags.push_back(TTV_NONE);\n\t\t\t\t++row;\n\t\t\t}\n\t\t}\n\n\t\t// 4. forbids services\n\t\tif (rule->getForbiddenBaseFunc().any())\n\t\t{\n\t\t\t_lstRight->addRow(1, tr(\"STR_SERVICES_FORBIDDEN\").c_str());\n\t\t\t_lstRight->setRowColor(row, _blue);\n\t\t\t_rightTopics.push_back(\"-\");\n\t\t\t_rightFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\t\t\tfor (const auto& forbiddenServiceType : _game->getMod()->getBaseFunctionNames(rule->getForbiddenBaseFunc()))\n\t\t\t{\n\t\t\t\tstd::string name = tr(forbiddenServiceType);\n\t\t\t\tname.insert(0, \"  \");\n\t\t\t\t_lstRight->addRow(1, name.c_str());\n\t\t\t\t_lstRight->setRowColor(row, _white);\n\t\t\t\t_rightTopics.push_back(\"-\");\n\t\t\t\t_rightFlags.push_back(TTV_NONE);\n\t\t\t\t++row;\n\t\t\t}\n\t\t}\n\t}\n\telse if (_selectedFlag == TTV_ITEMS)\n\t{\n\t\t_lstLeft->setVisible(false);\n\t\t_lstRight->setVisible(false);\n\t\t_lstFull->setVisible(true);\n\n\t\tint row = 0;\n\t\tRuleItem *rule = _game->getMod()->getItem(_selectedTopic);\n\t\tif (rule == 0)\n\t\t\treturn;\n\n\t\t// 1. requires to use/equip\n\t\tconst std::vector<const RuleResearch *> reqs = rule->getRequirements();\n\t\tif (reqs.size() > 0)\n\t\t{\n\t\t\t_lstFull->addRow(1, tr(\"STR_RESEARCH_REQUIRED_USE\").c_str());\n\t\t\t_lstFull->setRowColor(row, _blue);\n\t\t\t_leftTopics.push_back(\"-\");\n\t\t\t_leftFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\t\t\tfor (auto* i : reqs)\n\t\t\t{\n\t\t\t\tstd::string name = tr(i->getName());\n\t\t\t\tname.insert(0, \"  \");\n\t\t\t\t_lstFull->addRow(1, name.c_str());\n\t\t\t\t_lstFull->setRowColor(row, getResearchColor(i->getName()));\n\t\t\t\t_leftTopics.push_back(i->getName());\n\t\t\t\t_leftFlags.push_back(TTV_RESEARCH);\n\t\t\t\t++row;\n\t\t\t}\n\t\t}\n\n\t\t// 2. requires to buy\n\t\tconst std::vector<const RuleResearch *> reqsBuy = rule->getBuyRequirements();\n\t\tif (reqsBuy.size() > 0)\n\t\t{\n\t\t\t_lstFull->addRow(1, tr(\"STR_RESEARCH_REQUIRED_BUY\").c_str());\n\t\t\t_lstFull->setRowColor(row, _blue);\n\t\t\t_leftTopics.push_back(\"-\");\n\t\t\t_leftFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\t\t\tfor (auto* i : reqsBuy)\n\t\t\t{\n\t\t\t\tstd::string name = tr(i->getName());\n\t\t\t\tname.insert(0, \"  \");\n\t\t\t\t_lstFull->addRow(1, name.c_str());\n\t\t\t\t_lstFull->setRowColor(row, getResearchColor(i->getName()));\n\t\t\t\t_leftTopics.push_back(i->getName());\n\t\t\t\t_leftFlags.push_back(TTV_RESEARCH);\n\t\t\t\t++row;\n\t\t\t}\n\t\t}\n\n\t\t// 3. services (from base facilities) required to buy\n\t\tif (rule->getRequiresBuyBaseFunc().any())\n\t\t{\n\t\t\tconst std::vector<std::string> servicesBuy = _game->getMod()->getBaseFunctionNames(rule->getRequiresBuyBaseFunc());\n\t\t\t_lstFull->addRow(1, tr(\"STR_SERVICES_REQUIRED_BUY\").c_str());\n\t\t\t_lstFull->setRowColor(row, _blue);\n\t\t\t_leftTopics.push_back(\"-\");\n\t\t\t_leftFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\t\t\tfor (auto& i : servicesBuy)\n\t\t\t{\n\t\t\t\tstd::string name = tr(i);\n\t\t\t\tname.insert(0, \"  \");\n\t\t\t\t_lstFull->addRow(1, name.c_str());\n\t\t\t\t_lstFull->setRowColor(row, _gold);\n\t\t\t\t_leftTopics.push_back(\"-\");\n\t\t\t\t_leftFlags.push_back(TTV_NONE);\n\t\t\t\t++row;\n\t\t\t}\n\t\t}\n\n\t\t// 4. produced by\n\t\tstd::vector<std::string> producedBy;\n\t\tfor (auto& j : _game->getMod()->getManufactureList())\n\t\t{\n\t\t\tRuleManufacture* temp = _game->getMod()->getManufacture(j);\n\t\t\tbool found = false;\n\t\t\tfor (auto& i : temp->getProducedItems())\n\t\t\t{\n\t\t\t\tif (i.first == rule)\n\t\t\t\t{\n\t\t\t\t\tproducedBy.push_back(j);\n\t\t\t\t\tfound = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!found)\n\t\t\t{\n\t\t\t\tfor (auto& itMap : temp->getRandomProducedItems())\n\t\t\t\t{\n\t\t\t\t\tfor (auto& i : itMap.second)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (i.first == rule)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tproducedBy.push_back(j);\n\t\t\t\t\t\t\tfound = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (found) break;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (producedBy.size() > 0)\n\t\t{\n\t\t\t_lstFull->addRow(1, tr(\"STR_PRODUCED_BY\").c_str());\n\t\t\t_lstFull->setRowColor(row, _blue);\n\t\t\t_leftTopics.push_back(\"-\");\n\t\t\t_leftFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\t\t\tfor (const auto& manuf : producedBy)\n\t\t\t{\n\t\t\t\tstd::string name = tr(manuf);\n\t\t\t\tname.insert(0, \"  \");\n\t\t\t\tname.append(tr(\"STR_M_FLAG\"));\n\t\t\t\t_lstFull->addRow(1, name.c_str());\n\t\t\t\tif (!isDiscoveredManufacture(manuf))\n\t\t\t\t{\n\t\t\t\t\t_lstFull->setRowColor(row, _pink);\n\t\t\t\t}\n\t\t\t\t_leftTopics.push_back(manuf);\n\t\t\t\t_leftFlags.push_back(TTV_MANUFACTURING);\n\t\t\t\t++row;\n\t\t\t}\n\t\t}\n\n\t\t// 5. spawned by\n\t\tstd::vector<std::string> spawnedBy;\n\t\tfor (auto& j : _game->getMod()->getResearchList())\n\t\t{\n\t\t\tRuleResearch* temp = _game->getMod()->getResearch(j);\n\t\t\tif (temp->getSpawnedItem() == rule->getType())\n\t\t\t{\n\t\t\t\tspawnedBy.push_back(j);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tfor (auto& sil : temp->getSpawnedItemList())\n\t\t\t\t{\n\t\t\t\t\tif (sil == rule->getType())\n\t\t\t\t\t{\n\t\t\t\t\t\tspawnedBy.push_back(j);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (spawnedBy.size() > 0)\n\t\t{\n\t\t\t_lstFull->addRow(1, tr(\"STR_SPAWNED_BY\").c_str());\n\t\t\t_lstFull->setRowColor(row, _blue);\n\t\t\t_leftTopics.push_back(\"-\");\n\t\t\t_leftFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\t\t\tfor (const auto& res : spawnedBy)\n\t\t\t{\n\t\t\t\tstd::string name = tr(res);\n\t\t\t\tname.insert(0, \"  \");\n\t\t\t\t_lstFull->addRow(1, name.c_str());\n\t\t\t\t_lstFull->setRowColor(row, getResearchColor(res));\n\t\t\t\t_leftTopics.push_back(res);\n\t\t\t\t_leftFlags.push_back(TTV_RESEARCH);\n\t\t\t\t++row;\n\t\t\t}\n\t\t}\n\n\t\t// empty line\n\t\t_lstFull->addRow(1, \"\");\n\t\t_leftTopics.push_back(\"-\");\n\t\t_leftFlags.push_back(TTV_NONE);\n\t\t++row;\n\n\t\t// cost to buy\n\t\tif (rule->getBuyCost() > 0)\n\t\t{\n\t\t\t_lstFull->addRow(1, tr(\"STR_TTV_COST_PER_UNIT\").c_str());\n\t\t\t_lstFull->setRowColor(row, _blue);\n\t\t\t_leftTopics.push_back(\"-\");\n\t\t\t_leftFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\n\t\t\tstd::ostringstream txt;\n\t\t\ttxt << \"  \";\n\t\t\ttxt << Unicode::formatFunding(rule->getBuyCost());\n\t\t\t_lstFull->addRow(1, txt.str().c_str());\n\t\t\t_lstFull->setRowColor(row, _white);\n\t\t\t_leftTopics.push_back(\"-\");\n\t\t\t_leftFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\t\t}\n\t}\n\telse if (_selectedFlag == TTV_CRAFTS)\n\t{\n\t\tint row = 0;\n\t\tRuleCraft *rule = _game->getMod()->getCraft(_selectedTopic);\n\t\tif (rule == 0)\n\t\t\treturn;\n\n\t\t// 1. requires\n\t\tconst std::vector<std::string> reqs = rule->getRequirements();\n\t\tif (reqs.size() > 0)\n\t\t{\n\t\t\t_lstLeft->addRow(1, tr(\"STR_RESEARCH_REQUIRED\").c_str());\n\t\t\t_lstLeft->setRowColor(row, _blue);\n\t\t\t_leftTopics.push_back(\"-\");\n\t\t\t_leftFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\t\t\tfor (const auto& res : reqs)\n\t\t\t{\n\t\t\t\tstd::string name = tr(res);\n\t\t\t\tname.insert(0, \"  \");\n\t\t\t\t_lstLeft->addRow(1, name.c_str());\n\t\t\t\t_lstLeft->setRowColor(row, getResearchColor(res));\n\t\t\t\t_leftTopics.push_back(res);\n\t\t\t\t_leftFlags.push_back(TTV_RESEARCH);\n\t\t\t\t++row;\n\t\t\t}\n\t\t}\n\n\t\t// 2. services (from base facilities) required to buy\n\t\tif (rule->getRequiresBuyBaseFunc().any())\n\t\t{\n\t\t\t_lstLeft->addRow(1, tr(\"STR_SERVICES_REQUIRED_BUY\").c_str());\n\t\t\t_lstLeft->setRowColor(row, _blue);\n\t\t\t_leftTopics.push_back(\"-\");\n\t\t\t_leftFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\t\t\tfor (const auto& serviceReqToBuy : _game->getMod()->getBaseFunctionNames(rule->getRequiresBuyBaseFunc()))\n\t\t\t{\n\t\t\t\tstd::string name = tr(serviceReqToBuy);\n\t\t\t\tname.insert(0, \"  \");\n\t\t\t\t_lstLeft->addRow(1, name.c_str());\n\t\t\t\t_lstLeft->setRowColor(row, _gold);\n\t\t\t\t_leftTopics.push_back(\"-\");\n\t\t\t\t_leftFlags.push_back(TTV_NONE);\n\t\t\t\t++row;\n\t\t\t}\n\t\t}\n\n\t\t// 3. produced by\n\t\tstd::vector<std::string> producedBy;\n\t\tfor (auto& j : _game->getMod()->getManufactureList())\n\t\t{\n\t\t\tRuleManufacture* temp = _game->getMod()->getManufacture(j);\n\t\t\tif (temp->getProducedCraft() == rule)\n\t\t\t{\n\t\t\t\tproducedBy.push_back(j);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (producedBy.size() > 0)\n\t\t{\n\t\t\t_lstLeft->addRow(1, tr(\"STR_PRODUCED_BY\").c_str());\n\t\t\t_lstLeft->setRowColor(row, _blue);\n\t\t\t_leftTopics.push_back(\"-\");\n\t\t\t_leftFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\t\t\tfor (const auto& manuf : producedBy)\n\t\t\t{\n\t\t\t\tstd::string name = tr(manuf);\n\t\t\t\tname.insert(0, \"  \");\n\t\t\t\tname.append(tr(\"STR_M_FLAG\"));\n\t\t\t\t_lstLeft->addRow(1, name.c_str());\n\t\t\t\tif (!isDiscoveredManufacture(manuf))\n\t\t\t\t{\n\t\t\t\t\t_lstLeft->setRowColor(row, _pink);\n\t\t\t\t}\n\t\t\t\t_leftTopics.push_back(manuf);\n\t\t\t\t_leftFlags.push_back(TTV_MANUFACTURING);\n\t\t\t\t++row;\n\t\t\t}\n\t\t}\n\n\t\t// empty line\n\t\t_lstLeft->addRow(1, \"\");\n\t\t_leftTopics.push_back(\"-\");\n\t\t_leftFlags.push_back(TTV_NONE);\n\t\t++row;\n\n\t\t// cost to buy\n\t\tif (rule->getBuyCost() > 0)\n\t\t{\n\t\t\t_lstLeft->addRow(1, tr(\"STR_TTV_COST_PER_UNIT\").c_str());\n\t\t\t_lstLeft->setRowColor(row, _blue);\n\t\t\t_leftTopics.push_back(\"-\");\n\t\t\t_leftFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\n\t\t\tstd::ostringstream txt;\n\t\t\ttxt << \"  \";\n\t\t\ttxt << Unicode::formatFunding(rule->getBuyCost());\n\t\t\t_lstLeft->addRow(1, txt.str().c_str());\n\t\t\t_lstLeft->setRowColor(row, _white);\n\t\t\t_leftTopics.push_back(\"-\");\n\t\t\t_leftFlags.push_back(TTV_NONE);\n\t\t\t++row;\n\t\t}\n\t}\n}\n\n/**\n* Selects the topic.\n* @param action Pointer to an action.\n*/\nvoid TechTreeViewerState::onSelectLeftTopic(Action *)\n{\n\tint index = _lstLeft->getSelectedRow();\n\tif (_leftFlags[index] > TTV_NONE)\n\t{\n\t\t_history.push_back(std::make_pair(_selectedTopic, _selectedFlag));\n\t\t_selectedFlag = _leftFlags[index];\n\t\t_selectedTopic = _leftTopics[index];\n\t\tinitLists();\n\t}\n}\n\n/**\n* Selects the topic.\n* @param action Pointer to an action.\n*/\nvoid TechTreeViewerState::onSelectRightTopic(Action *)\n{\n\tint index = _lstRight->getSelectedRow();\n\tif (_rightFlags[index] > TTV_NONE)\n\t{\n\t\t_history.push_back(std::make_pair(_selectedTopic, _selectedFlag));\n\t\t_selectedFlag = _rightFlags[index];\n\t\t_selectedTopic = _rightTopics[index];\n\t\tinitLists();\n\t}\n}\n\n/**\n * Selects the topic.\n * @param action Pointer to an action.\n */\nvoid TechTreeViewerState::onSelectFullTopic(Action *)\n{\n\tint index = _lstFull->getSelectedRow();\n\tif (_leftFlags[index] > TTV_NONE)\n\t{\n\t\t_history.push_back(std::make_pair(_selectedTopic, _selectedFlag));\n\t\t_selectedFlag = _leftFlags[index];\n\t\t_selectedTopic = _leftTopics[index];\n\t\tinitLists();\n\t}\n}\n\n/**\n* Changes the selected topic.\n*/\nvoid TechTreeViewerState::setSelectedTopic(const std::string &selectedTopic, TTVMode topicType)\n{\n\t_history.push_back(std::make_pair(_selectedTopic, _selectedFlag));\n\t_selectedTopic = selectedTopic;\n\t_selectedFlag = topicType;\n}\n\n/**\n * Gets the color coding for the given research topic.\n */\nUint8 TechTreeViewerState::getResearchColor(const std::string &topic) const\n{\n\tif (_disabledResearch.find(topic) != _disabledResearch.end())\n\t{\n\t\treturn _grey; // disabled\n\t}\n\tif (_alreadyAvailableResearch.find(topic) == _alreadyAvailableResearch.end())\n\t{\n\t\treturn _pink; // not discovered\n\t}\n\treturn _purple; // discovered\n}\n\n/**\n * Gets the alternative color coding for the given research topic.\n */\nUint8 TechTreeViewerState::getAltResearchColor(const std::string &topic) const\n{\n\tif (_disabledResearch.find(topic) != _disabledResearch.end())\n\t{\n\t\treturn _grey; // disabled\n\t}\n\tif (_alreadyAvailableResearch.find(topic) == _alreadyAvailableResearch.end())\n\t{\n\t\treturn _gold; // not discovered\n\t}\n\treturn _white; // discovered\n}\n\n/**\n* Is given research topic discovered/available?\n*/\nbool TechTreeViewerState::isDiscoveredResearch(const std::string &topic) const\n{\n\tif (_alreadyAvailableResearch.find(topic) == _alreadyAvailableResearch.end())\n\t{\n\t\treturn false;\n\t}\n\treturn true;\n}\n\n/**\n* Is given manufacture topic discovered/available?\n*/\nbool TechTreeViewerState::isDiscoveredManufacture(const std::string &topic) const\n{\n\tif (_alreadyAvailableManufacture.find(topic) == _alreadyAvailableManufacture.end())\n\t{\n\t\treturn false;\n\t}\n\treturn true;\n}\n\n/**\n* Is given base facility discovered/available?\n*/\nbool TechTreeViewerState::isDiscoveredFacility(const std::string &topic) const\n{\n\tif (_alreadyAvailableFacilities.find(topic) == _alreadyAvailableFacilities.end())\n\t{\n\t\treturn false;\n\t}\n\treturn true;\n}\n\n/**\n* Is given item protected by any research?\n*/\nbool TechTreeViewerState::isProtectedItem(const std::string &topic) const\n{\n\tif (_protectedItems.find(topic) == _protectedItems.end())\n\t{\n\t\treturn false;\n\t}\n\treturn true;\n}\n\n/**\n* Is given protected item discovered/available for both purchase and usage/equipment?\n*/\nbool TechTreeViewerState::isProtectedAndDiscoveredItem(const std::string &topic) const\n{\n\tif (_alreadyAvailableItems.find(topic) == _alreadyAvailableItems.end())\n\t{\n\t\treturn false;\n\t}\n\treturn true;\n}\n\n/**\n* Is given craft discovered/available?\n*/\nbool TechTreeViewerState::isDiscoveredCraft(const std::string &topic) const\n{\n\tif (_alreadyAvailableCrafts.find(topic) == _alreadyAvailableCrafts.end())\n\t{\n\t\treturn false;\n\t}\n\treturn true;\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/TechTreeViewerState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2015 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include <vector>\n#include <map>\n#include <string>\n#include <unordered_set>\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass TextList;\nclass RuleResearch;\nclass RuleManufacture;\nclass RuleBaseFacility;\nclass RuleCraft;\n\nenum TTVMode { TTV_NONE, TTV_RESEARCH, TTV_MANUFACTURING, TTV_FACILITIES, TTV_ITEMS, TTV_CRAFTS };\n\n/**\n * TechTreeViewer screen, where you can browse the Tech Tree.\n */\nclass TechTreeViewerState : public State\n{\nprivate:\n\tTextButton *_btnOk, *_btnNew;\n\tWindow *_window;\n\tText *_txtTitle, *_txtSelectedTopic, *_txtProgress, *_txtCostIndicator;\n\tTextList *_lstLeft, *_lstRight, *_lstFull;\n\tUint8 _purple, _pink, _blue, _white, _gold, _grey;\n\tstd::string _selectedTopic;\n\tTTVMode _selectedFlag;\n\tstd::vector<std::pair<std::string, TTVMode> > _history;\n\tstd::vector<std::string> _leftTopics, _rightTopics;\n\tstd::vector<TTVMode> _leftFlags, _rightFlags;\n\tstd::unordered_set<std::string> _disabledResearch;\n\tstd::unordered_set<std::string> _alreadyAvailableResearch, _alreadyAvailableManufacture, _alreadyAvailableFacilities, _alreadyAvailableCrafts;\n\tstd::unordered_set<std::string> _protectedItems, _alreadyAvailableItems;\n\tvoid initLists();\n\tvoid onSelectLeftTopic(Action *action);\n\tvoid onSelectRightTopic(Action *action);\n\tvoid onSelectFullTopic(Action *action);\npublic:\n\t/// Creates the Tech Tree Viewer state.\n\tTechTreeViewerState(const RuleResearch *r = 0, const RuleManufacture *m = 0, const RuleBaseFacility *f = 0, const RuleCraft *c = 0);\n\t/// Cleans up the Tech Tree Viewer state.\n\t~TechTreeViewerState();\n\t/// Initializes the state.\n\tvoid init() override;\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the Back button.\n\tvoid btnBackClick(Action *action);\n\t/// Handler for clicking the New button.\n\tvoid btnNewClick(Action *action);\n\t/// Sets the selected topic.\n\tvoid setSelectedTopic(const std::string &selectedTopic, TTVMode topicType);\n\t/// Gets the color coding for the given research topic.\n\tUint8 getResearchColor(const std::string &topic) const;\n\tUint8 getAltResearchColor(const std::string &topic) const;\n\t/// Is given research topic discovered/available?\n\tbool isDiscoveredResearch(const std::string &topic) const;\n\t/// Is given manufacture topic discovered/available?\n\tbool isDiscoveredManufacture(const std::string &topic) const;\n\t/// Is given base facility discovered/available?\n\tbool isDiscoveredFacility(const std::string &topic) const;\n\t/// Is given item protected by any research?\n\tbool isProtectedItem(const std::string &topic) const;\n\t/// Is given protected item discovered/available for both purchase and usage/equipment?\n\tbool isProtectedAndDiscoveredItem(const std::string &topic) const;\n\t/// Is given craft discovered/available for both purchase and usage/equipment?\n\tbool isDiscoveredCraft(const std::string &topic) const;\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/TransferBaseState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"TransferBaseState.h\"\n#include <sstream>\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/Region.h\"\n#include \"../Mod/RuleRegion.h\"\n#include \"TransferItemsState.h\"\n#include \"../Battlescape/DebriefingState.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Select Destination Base window.\n * @param game Pointer to the core game.\n * @param base Pointer to the base to get info from.\n */\nTransferBaseState::TransferBaseState(Base *base, DebriefingState *debriefingState) : _base(base), _debriefingState(debriefingState)\n{\n\t// Create objects\n\t_window = new Window(this, 280, 140, 20, 30);\n\t_btnCancel = new TextButton(264, 16, 28, 146);\n\t_txtTitle = new Text(270, 17, 25, 38);\n\t_txtFunds = new Text(250, 9, 30, 54);\n\t_txtName = new Text(130, 17, 28, 64);\n\t_txtArea = new Text(130, 17, 160, 64);\n\t_lstBases = new TextList(248, 64, 28, 80);\n\n\t// Set palette\n\tsetInterface(\"transferBaseSelect\");\n\n\tadd(_window, \"window\", \"transferBaseSelect\");\n\tadd(_btnCancel, \"button\", \"transferBaseSelect\");\n\tadd(_txtTitle, \"text\", \"transferBaseSelect\");\n\tadd(_txtFunds, \"text\", \"transferBaseSelect\");\n\tadd(_txtName, \"text\", \"transferBaseSelect\");\n\tadd(_txtArea, \"text\", \"transferBaseSelect\");\n\tadd(_lstBases, \"list\", \"transferBaseSelect\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"transferBaseSelect\");\n\n\t_btnCancel->setText(tr(\"STR_CANCEL\"));\n\t_btnCancel->onMouseClick((ActionHandler)&TransferBaseState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&TransferBaseState::btnCancelClick, Options::keyCancel);\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_SELECT_DESTINATION_BASE\"));\n\n\t_txtFunds->setText(tr(\"STR_CURRENT_FUNDS\").arg(Unicode::formatFunding(_game->getSavedGame()->getFunds())));\n\n\t_txtName->setText(tr(\"STR_NAME\"));\n\t_txtName->setBig();\n\n\t_txtArea->setText(tr(\"STR_AREA\"));\n\t_txtArea->setBig();\n\n\t_lstBases->setColumns(2, 130, 116);\n\t_lstBases->setSelectable(true);\n\t_lstBases->setBackground(_window);\n\t_lstBases->setMargin(2);\n\t_lstBases->onMouseClick((ActionHandler)&TransferBaseState::lstBasesClick);\n\n\tint row = 0;\n\tfor (auto* xbase : *_game->getSavedGame()->getBases())\n\t{\n\t\tif (xbase != _base)\n\t\t{\n\t\t\t// Get area\n\t\t\tstd::string area;\n\t\t\tfor (const auto* region : *_game->getSavedGame()->getRegions())\n\t\t\t{\n\t\t\t\tif (region->getRules()->insideRegion(xbase->getLongitude(), xbase->getLatitude()))\n\t\t\t\t{\n\t\t\t\t\tarea = tr(region->getRules()->getType());\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tstd::ostringstream ss;\n\t\t\tss << Unicode::TOK_COLOR_FLIP << area;\n\t\t\t_lstBases->addRow(2, xbase->getName().c_str(), ss.str().c_str());\n\t\t\t_bases.push_back(xbase);\n\t\t\trow++;\n\t\t}\n\t}\n}\n\n/**\n *\n */\nTransferBaseState::~TransferBaseState()\n{\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid TransferBaseState::btnCancelClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Shows the Transfer screen for the selected base.\n * @param action Pointer to an action.\n */\nvoid TransferBaseState::lstBasesClick(Action *)\n{\n\t_game->pushState(new TransferItemsState(_base, _bases[_lstBases->getSelectedRow()], _debriefingState));\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/TransferBaseState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include <vector>\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass TextList;\nclass Base;\nclass DebriefingState;\n\n/**\n * Window that lets the player pick the base\n * to transfer items to.\n */\nclass TransferBaseState : public State\n{\nprivate:\n\tBase *_base;\n\tDebriefingState *_debriefingState;\n\tTextButton *_btnCancel;\n\tWindow *_window;\n\tText *_txtTitle, *_txtFunds, *_txtName, *_txtArea;\n\tTextList *_lstBases;\n\tstd::vector<Base*> _bases;\npublic:\n\t/// Creates the Transfer Base state.\n\tTransferBaseState(Base *base, DebriefingState *debriefingState);\n\t/// Cleans up the Transfer Base state.\n\t~TransferBaseState();\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action *action);\n\t/// Handler for clicking the Bases list.\n\tvoid lstBasesClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/TransferConfirmState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <sstream>\n#include \"TransferConfirmState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Savegame/Base.h\"\n#include \"TransferItemsState.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Confirm Transfer window.\n * @param game Pointer to the core game.\n * @param base Pointer to the destination base.\n * @param state Pointer to the Transfer state.\n */\nTransferConfirmState::TransferConfirmState(Base *base, TransferItemsState *state) : _base(base), _state(state)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 320, 80, 0, 60);\n\t_btnCancel = new TextButton(128, 16, 176, 115);\n\t_btnOk = new TextButton(128, 16, 16, 115);\n\t_txtTitle = new Text(310, 17, 5, 75);\n\t_txtCost = new Text(60, 17, 110, 95);\n\t_txtTotal = new Text(100, 17, 170, 95);\n\n\t// Set palette\n\tsetInterface(\"transferConfirm\");\n\n\tadd(_window, \"window\", \"transferConfirm\");\n\tadd(_btnCancel, \"button\", \"transferConfirm\");\n\tadd(_btnOk, \"button\", \"transferConfirm\");\n\tadd(_txtTitle, \"text\", \"transferConfirm\");\n\tadd(_txtCost, \"text\", \"transferConfirm\");\n\tadd(_txtTotal, \"text\", \"transferConfirm\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"transferConfirm\");\n\n\t_btnCancel->setText(tr(\"STR_CANCEL_UC\"));\n\t_btnCancel->onMouseClick((ActionHandler)&TransferConfirmState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&TransferConfirmState::btnCancelClick, Options::keyCancel);\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&TransferConfirmState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&TransferConfirmState::btnOkClick, Options::keyOk);\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_TRANSFER_ITEMS_TO\").arg(_base->getName()));\n\n\t_txtCost->setBig();\n\t_txtCost->setText(tr(\"STR_COST\"));\n\n\tstd::ostringstream ss;\n\tss << Unicode::TOK_COLOR_FLIP << Unicode::formatFunding(_state->getTotal());\n\n\t_txtTotal->setBig();\n\t_txtTotal->setText(ss.str());\n}\n\n/**\n *\n */\nTransferConfirmState::~TransferConfirmState()\n{\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid TransferConfirmState::btnCancelClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Completes the transfer.\n * @param action Pointer to an action.\n */\nvoid TransferConfirmState::btnOkClick(Action *)\n{\n\t_state->completeTransfer();\n\t_game->popState();\n\t_game->popState();\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/TransferConfirmState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass TransferItemsState;\nclass Base;\n\n/**\n * Window to confirm a transfer between bases.\n */\nclass TransferConfirmState : public State\n{\nprivate:\n\tTextButton *_btnCancel, *_btnOk;\n\tWindow *_window;\n\tText *_txtTitle, *_txtCost, *_txtTotal;\n\tBase *_base;\n\tTransferItemsState *_state;\npublic:\n\t/// Creates the Transfer Confirm state.\n\tTransferConfirmState(Base *base, TransferItemsState *state);\n\t/// Cleans up the Transfer Confirm state.\n\t~TransferConfirmState();\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action *action);\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/TransferItemsState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"TransferItemsState.h\"\n#include \"ItemLocationsState.h\"\n#include \"ManufactureDependenciesTreeState.h\"\n#include <sstream>\n#include <climits>\n#include <algorithm>\n#include <locale>\n#include \"../Engine/CrossPlatform.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextEdit.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Savegame/BaseFacility.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/Soldier.h\"\n#include \"../Savegame/Craft.h\"\n#include \"../Savegame/ItemContainer.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"../Engine/Timer.h\"\n#include \"../Menu/ErrorMessageState.h\"\n#include \"TransferConfirmState.h\"\n#include \"../Engine/Options.h\"\n#include \"../fmath.h\"\n#include \"../Mod/RuleInterface.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Interface/ComboBox.h\"\n#include \"TechTreeViewerState.h\"\n#include \"../Ufopaedia/Ufopaedia.h\"\n#include \"../Battlescape/DebriefingState.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Transfer screen.\n * @param game Pointer to the core game.\n * @param baseFrom Pointer to the source base.\n * @param baseTo Pointer to the destination base.\n */\nTransferItemsState::TransferItemsState(Base *baseFrom, Base *baseTo, DebriefingState *debriefingState) :\n\t_baseFrom(baseFrom), _baseTo(baseTo), _debriefingState(debriefingState),\n\t_sel(0), _total(0), _pQty(0), _cQty(0), _aQty(0), _iQty(0.0), _distance(0.0), _ammoColor(0),\n\t_previousSort(TransferSortDirection::BY_LIST_ORDER), _currentSort(TransferSortDirection::BY_LIST_ORDER), _errorShown(false)\n{\n\t// Create objects\n\t_window = new Window(this, 320, 200, 0, 0);\n\t_btnQuickSearch = new TextEdit(this, 48, 9, 10, 13);\n\t_btnOk = new TextButton(148, 16, 8, 176);\n\t_btnCancel = new TextButton(148, 16, 164, 176);\n\t_txtTitle = new Text(310, 17, 5, 8);\n\t_txtQuantity = new Text(50, 9, 150, 24);\n\t_txtAmountTransfer = new Text(60, 17, 200, 24);\n\t_txtAmountDestination = new Text(60, 17, 260, 24);\n\t_cbxCategory = new ComboBox(this, 120, 16, 10, 24);\n\t_lstItems = new TextList(287, 128, 8, 44);\n\n\ttouchComponentsCreate(_txtTitle);\n\n\t// Set palette\n\tsetInterface(\"transferMenu\");\n\n\t_ammoColor = _game->getMod()->getInterface(\"transferMenu\")->getElement(\"ammoColor\")->color;\n\n\tadd(_window, \"window\", \"transferMenu\");\n\tadd(_btnQuickSearch, \"button\", \"transferMenu\");\n\tadd(_btnOk, \"button\", \"transferMenu\");\n\tadd(_btnCancel, \"button\", \"transferMenu\");\n\tadd(_txtTitle, \"text\", \"transferMenu\");\n\tadd(_txtQuantity, \"text\", \"transferMenu\");\n\tadd(_txtAmountTransfer, \"text\", \"transferMenu\");\n\tadd(_txtAmountDestination, \"text\", \"transferMenu\");\n\tadd(_lstItems, \"list\", \"transferMenu\");\n\tadd(_cbxCategory, \"text\", \"transferMenu\");\n\n\ttouchComponentsAdd(\"button2\", \"transferMenu\", _window);\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"transferMenu\");\n\n\ttouchComponentsConfigure();\n\n\t_btnOk->setText(tr(\"STR_TRANSFER\"));\n\t_btnOk->onMouseClick((ActionHandler)&TransferItemsState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&TransferItemsState::btnOkClick, Options::keyOk);\n\n\t_btnCancel->setText(tr(\"STR_CANCEL\"));\n\t_btnCancel->onMouseClick((ActionHandler)&TransferItemsState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&TransferItemsState::btnCancelClick, Options::keyCancel);\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_TRANSFER\"));\n\n\t_txtQuantity->setText(tr(\"STR_QUANTITY_UC\"));\n\n\t_txtAmountTransfer->setText(tr(\"STR_AMOUNT_TO_TRANSFER\"));\n\t_txtAmountTransfer->setWordWrap(true);\n\n\t_txtAmountDestination->setText(tr(\"STR_AMOUNT_AT_DESTINATION\"));\n\t_txtAmountDestination->setWordWrap(true);\n\n\t_lstItems->setArrowColumn(193, ARROW_VERTICAL);\n\t_lstItems->setColumns(4, 162, 58, 40, 27);\n\t_lstItems->setSelectable(true);\n\t_lstItems->setBackground(_window);\n\t_lstItems->setMargin(2);\n\t_lstItems->onLeftArrowPress((ActionHandler)&TransferItemsState::lstItemsLeftArrowPress);\n\t_lstItems->onLeftArrowRelease((ActionHandler)&TransferItemsState::lstItemsLeftArrowRelease);\n\t_lstItems->onLeftArrowClick((ActionHandler)&TransferItemsState::lstItemsLeftArrowClick);\n\t_lstItems->onRightArrowPress((ActionHandler)&TransferItemsState::lstItemsRightArrowPress);\n\t_lstItems->onRightArrowRelease((ActionHandler)&TransferItemsState::lstItemsRightArrowRelease);\n\t_lstItems->onRightArrowClick((ActionHandler)&TransferItemsState::lstItemsRightArrowClick);\n\t_lstItems->onMousePress((ActionHandler)&TransferItemsState::lstItemsMousePress);\n\n\t_distance = getDistance();\n\n\t_cats.push_back(\"STR_ALL_ITEMS\");\n\t_cats.push_back(\"STR_ITEMS_AT_DESTINATION\");\n\tif (Options::oxceBaseFilterResearchable)\n\t{\n\t\t_cats.push_back(\"STR_FILTER_RESEARCHED\");\n\t\t_cats.push_back(\"STR_FILTER_RESEARCHABLE\");\n\t}\n\n\tfor (auto* soldier : *_baseFrom->getSoldiers())\n\t{\n\t\tif (_debriefingState) break;\n\t\tif (soldier->getCraft() == 0)\n\t\t{\n\t\t\tTransferRow row = { TRANSFER_SOLDIER, soldier, soldier->getName(true), (int)(5 * _distance), 1, 0, 0, -4, 0, 0, (int)(5 * _distance) };\n\t\t\t_items.push_back(row);\n\t\t\tstd::string cat = getCategory(_items.size() - 1);\n\t\t\tif (std::find(_cats.begin(), _cats.end(), cat) == _cats.end())\n\t\t\t{\n\t\t\t\t_cats.push_back(cat);\n\t\t\t}\n\t\t}\n\t}\n\tfor (auto* craft : *_baseFrom->getCrafts())\n\t{\n\t\tif (_debriefingState) break;\n\t\tif (craft->getStatus() != \"STR_OUT\" || (Options::canTransferCraftsWhileAirborne && craft->getFuel() >= craft->getFuelLimit(_baseTo)))\n\t\t{\n\t\t\tTransferRow row = { TRANSFER_CRAFT, craft, craft->getName(_game->getLanguage()),  (int)(25 * _distance), 1, 0, 0, -3, 0, 0, (int)(25 * _distance) };\n\t\t\t_items.push_back(row);\n\t\t\tstd::string cat = getCategory(_items.size() - 1);\n\t\t\tif (std::find(_cats.begin(), _cats.end(), cat) == _cats.end())\n\t\t\t{\n\t\t\t\t_cats.push_back(cat);\n\t\t\t}\n\t\t}\n\t}\n\tif (_baseFrom->getAvailableScientists() > 0 && _debriefingState == 0)\n\t{\n\t\tTransferRow row = { TRANSFER_SCIENTIST, 0, tr(\"STR_SCIENTIST\"),  (int)(5 * _distance), _baseFrom->getAvailableScientists(), _baseTo->getAvailableScientists(), 0, -2, 0, 0, _baseFrom->getAvailableScientists() * (int)(5 * _distance) };\n\t\t_items.push_back(row);\n\t\tstd::string cat = getCategory(_items.size() - 1);\n\t\tif (std::find(_cats.begin(), _cats.end(), cat) == _cats.end())\n\t\t{\n\t\t\t_cats.push_back(cat);\n\t\t}\n\t}\n\tif (_baseFrom->getAvailableEngineers() > 0 && _debriefingState == 0)\n\t{\n\t\tTransferRow row = { TRANSFER_ENGINEER, 0, tr(\"STR_ENGINEER\"),  (int)(5 * _distance), _baseFrom->getAvailableEngineers(), _baseTo->getAvailableEngineers(), 0, -1, 0, 0, _baseFrom->getAvailableEngineers() * (int)(5 * _distance) };\n\t\t_items.push_back(row);\n\t\tstd::string cat = getCategory(_items.size() - 1);\n\t\tif (std::find(_cats.begin(), _cats.end(), cat) == _cats.end())\n\t\t{\n\t\t\t_cats.push_back(cat);\n\t\t}\n\t}\n\tfor (auto& itemType : _game->getMod()->getItemsList())\n\t{\n\t\tRuleItem *rule = _game->getMod()->getItem(itemType, true);\n\t\tint qty = _baseFrom->getStorageItems()->getItem(rule);\n\t\tif (_debriefingState != 0)\n\t\t{\n\t\t\tqty = _debriefingState->getRecoveredItemCount(rule);\n\t\t}\n\t\tif (qty > 0)\n\t\t{\n\t\t\tTransferRow row = { TRANSFER_ITEM, rule, tr(itemType),  (int)(1 * _distance), qty, _baseTo->getStorageItems()->getItem(rule), 0, rule->getListOrder(), rule->getSize(), qty * rule->getSize(), qty * (int)(1 * _distance) };\n\t\t\t_items.push_back(row);\n\t\t\tstd::string cat = getCategory(_items.size() - 1);\n\t\t\tif (std::find(_cats.begin(), _cats.end(), cat) == _cats.end())\n\t\t\t{\n\t\t\t\t_cats.push_back(cat);\n\t\t\t}\n\t\t}\n\t}\n\n\t_vanillaCategories = _cats.size();\n\tif (_game->getMod()->getDisplayCustomCategories() > 0)\n\t{\n\t\tbool hasUnassigned = false;\n\n\t\t// first find all relevant item categories\n\t\tstd::vector<std::string> tempCats;\n\t\tfor (const auto& transferRow : _items)\n\t\t{\n\t\t\tif (transferRow.type == TRANSFER_ITEM)\n\t\t\t{\n\t\t\t\tRuleItem *rule = (RuleItem*)(transferRow.rule);\n\t\t\t\tif (rule->getCategories().empty())\n\t\t\t\t{\n\t\t\t\t\thasUnassigned = true;\n\t\t\t\t}\n\t\t\t\tfor (auto& itemCategoryName : rule->getCategories())\n\t\t\t\t{\n\t\t\t\t\tif (std::find(tempCats.begin(), tempCats.end(), itemCategoryName) == tempCats.end())\n\t\t\t\t\t{\n\t\t\t\t\t\ttempCats.push_back(itemCategoryName);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// then use them nicely in order\n\t\tif (_game->getMod()->getDisplayCustomCategories() == 1)\n\t\t{\n\t\t\t_cats.clear();\n\t\t\t_cats.push_back(\"STR_ALL_ITEMS\");\n\t\t\t_cats.push_back(\"STR_ITEMS_AT_DESTINATION\");\n\t\t\tif (Options::oxceBaseFilterResearchable)\n\t\t\t{\n\t\t\t\t_cats.push_back(\"STR_FILTER_RESEARCHED\");\n\t\t\t\t_cats.push_back(\"STR_FILTER_RESEARCHABLE\");\n\t\t\t}\n\t\t\t_vanillaCategories = _cats.size();\n\t\t}\n\t\tfor (auto& categoryName : _game->getMod()->getItemCategoriesList())\n\t\t{\n\t\t\tif (std::find(tempCats.begin(), tempCats.end(), categoryName) != tempCats.end())\n\t\t\t{\n\t\t\t\t_cats.push_back(categoryName);\n\t\t\t}\n\t\t}\n\t\tif (hasUnassigned)\n\t\t{\n\t\t\t_cats.push_back(\"STR_UNASSIGNED\");\n\t\t}\n\t}\n\n\t_cbxCategory->setOptions(_cats, true);\n\t_cbxCategory->onChange((ActionHandler)&TransferItemsState::cbxCategoryChange);\n\t_cbxCategory->onKeyboardPress((ActionHandler)&TransferItemsState::btnTransferAllClick, Options::keyTransferAll);\n\n\t_btnQuickSearch->setText(\"\"); // redraw\n\t_btnQuickSearch->onEnter((ActionHandler)&TransferItemsState::btnQuickSearchApply);\n\t_btnQuickSearch->setVisible(Options::oxceQuickSearchButton);\n\n\t_btnOk->onKeyboardRelease((ActionHandler)&TransferItemsState::btnQuickSearchToggle, Options::keyToggleQuickSearch);\n\n\tupdateList();\n\n\t_timerInc = new Timer(250);\n\t_timerInc->onTimer((StateHandler)&TransferItemsState::increase);\n\t_timerDec = new Timer(250);\n\t_timerDec->onTimer((StateHandler)&TransferItemsState::decrease);\n}\n\n/**\n *\n */\nTransferItemsState::~TransferItemsState()\n{\n\tdelete _timerInc;\n\tdelete _timerDec;\n}\n\n/**\n * Resets stuff when coming back from other screens.\n */\nvoid TransferItemsState::init()\n{\n\tState::init();\n\n\ttouchComponentsRefresh();\n}\n\n/**\n * Runs the arrow timers.\n */\nvoid TransferItemsState::think()\n{\n\tState::think();\n\n\t_timerInc->think(this, 0);\n\t_timerDec->think(this, 0);\n}\n\n/**\n * Determines the category a row item belongs in.\n * @param sel Selected row.\n * @returns Item category.\n */\nstd::string TransferItemsState::getCategory(int sel) const\n{\n\tRuleItem *rule = 0;\n\tswitch (_items[sel].type)\n\t{\n\tcase TRANSFER_SOLDIER:\n\tcase TRANSFER_SCIENTIST:\n\tcase TRANSFER_ENGINEER:\n\t\treturn \"STR_PERSONNEL\";\n\tcase TRANSFER_CRAFT:\n\t\treturn \"STR_CRAFT_ARMAMENT\";\n\tcase TRANSFER_ITEM:\n\t\trule = (RuleItem*)_items[sel].rule;\n\t\tif (rule->getBattleType() == BT_CORPSE || rule->isAlien())\n\t\t{\n\t\t\tif (rule->getVehicleUnit())\n\t\t\t\treturn \"STR_PERSONNEL\"; // OXCE: critters fighting for us\n\t\t\tif (rule->isAlien())\n\t\t\t\treturn \"STR_PRISONERS\"; // OXCE: live aliens\n\t\t\treturn \"STR_ALIENS\";\n\t\t}\n\t\tif (rule->getBattleType() == BT_NONE)\n\t\t{\n\t\t\tif (_game->getMod()->isCraftWeaponStorageItem(rule))\n\t\t\t\treturn \"STR_CRAFT_ARMAMENT\";\n\t\t\tif (_game->getMod()->isArmorStorageItem(rule))\n\t\t\t\treturn \"STR_ARMORS\"; // OXCE: armors\n\t\t\treturn \"STR_COMPONENTS\";\n\t\t}\n\t\treturn \"STR_EQUIPMENT\";\n\t}\n\treturn \"STR_ALL_ITEMS\";\n}\n\n/**\n * Determines if a row item belongs to a given category.\n * @param sel Selected row.\n * @param cat Category.\n * @returns True if row item belongs to given category, otherwise False.\n */\nbool TransferItemsState::belongsToCategory(int sel, const std::string &cat) const\n{\n\tswitch (_items[sel].type)\n\t{\n\tcase TRANSFER_SOLDIER:\n\tcase TRANSFER_SCIENTIST:\n\tcase TRANSFER_ENGINEER:\n\tcase TRANSFER_CRAFT:\n\t\treturn false;\n\tcase TRANSFER_ITEM:\n\t\tRuleItem *rule = (RuleItem*)_items[sel].rule;\n\t\treturn rule->belongsToCategory(cat);\n\t}\n\treturn false;\n}\n\n/**\n* Quick search toggle.\n* @param action Pointer to an action.\n*/\nvoid TransferItemsState::btnQuickSearchToggle(Action *action)\n{\n\tif (_btnQuickSearch->getVisible())\n\t{\n\t\t_btnQuickSearch->setText(\"\");\n\t\t_btnQuickSearch->setVisible(false);\n\t\tbtnQuickSearchApply(action);\n\t}\n\telse\n\t{\n\t\t_btnQuickSearch->setVisible(true);\n\t\t_btnQuickSearch->setFocus(true);\n\t}\n}\n\n/**\n* Quick search.\n* @param action Pointer to an action.\n*/\nvoid TransferItemsState::btnQuickSearchApply(Action *)\n{\n\tupdateList();\n}\n\n/**\n* Filters the current list of items.\n*/\nvoid TransferItemsState::updateList()\n{\n\tstd::string searchString = _btnQuickSearch->getText();\n\tUnicode::upperCase(searchString);\n\n\t_lstItems->clearList();\n\t_rows.clear();\n\n\tsize_t selCategory = _cbxCategory->getSelected();\n\tconst std::string cat = _cats[selCategory];\n\tbool allItems = (cat == \"STR_ALL_ITEMS\");\n\tbool onlyItemsAtDestination = (cat == \"STR_ITEMS_AT_DESTINATION\");\n\tbool categoryResearched = (cat == \"STR_FILTER_RESEARCHED\");\n\tbool categoryResearchable = (cat == \"STR_FILTER_RESEARCHABLE\");\n\tbool categoryUnassigned = (cat == \"STR_UNASSIGNED\");\n\tbool specialCategory = allItems || onlyItemsAtDestination;\n\n\tif (_previousSort != _currentSort)\n\t{\n\t\tswitch (_currentSort)\n\t\t{\n\t\tcase TransferSortDirection::BY_TOTAL_COST: std::stable_sort(_items.begin(), _items.end(), [](const TransferRow a, const TransferRow b) { return a.totalCost > b.totalCost; }); break;\n\t\tcase TransferSortDirection::BY_UNIT_COST:  std::stable_sort(_items.begin(), _items.end(), [](const TransferRow a, const TransferRow b) { return a.cost > b.cost; }); break;\n\t\tcase TransferSortDirection::BY_TOTAL_SIZE: std::stable_sort(_items.begin(), _items.end(), [](const TransferRow a, const TransferRow b) { return a.totalSize > b.totalSize; }); break;\n\t\tcase TransferSortDirection::BY_UNIT_SIZE:  std::stable_sort(_items.begin(), _items.end(), [](const TransferRow a, const TransferRow b) { return a.size > b.size; }); break;\n\t\tdefault:                                   std::stable_sort(_items.begin(), _items.end(), [](const TransferRow a, const TransferRow b) { return a.listOrder < b.listOrder; }); break;\n\t\t}\n\t}\n\n\tfor (size_t i = 0; i < _items.size(); ++i)\n\t{\n\t\t// filter\n\t\tif (categoryResearched || categoryResearchable)\n\t\t{\n\t\t\tif (_items[i].type == TRANSFER_ITEM)\n\t\t\t{\n\t\t\t\tRuleItem* rule = (RuleItem*)_items[i].rule;\n\t\t\t\tbool isResearchable = _game->getSavedGame()->isResearchable(rule, _game->getMod());\n\t\t\t\tif (categoryResearched && isResearchable) continue;\n\t\t\t\tif (categoryResearchable && !isResearchable) continue;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// don't show non-items (e.g. craft, personnel)\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\telse if (selCategory >= _vanillaCategories)\n\t\t{\n\t\t\tif (categoryUnassigned && _items[i].type == TRANSFER_ITEM)\n\t\t\t{\n\t\t\t\tRuleItem* rule = (RuleItem*)_items[i].rule;\n\t\t\t\tif (!rule->getCategories().empty())\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (!specialCategory && !belongsToCategory(i, cat))\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (!specialCategory && cat != getCategory(i))\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\t// \"items at destination\" filter\n\t\tif (onlyItemsAtDestination && _items[i].qtyDst <= 0)\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\n\t\t// quick search\n\t\tif (!searchString.empty())\n\t\t{\n\t\t\tstd::string projectName = _items[i].name;\n\t\t\tUnicode::upperCase(projectName);\n\t\t\tif (projectName.find(searchString) == std::string::npos)\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\tstd::string name = _items[i].name;\n\t\tbool ammo = false;\n\t\tif (_items[i].type == TRANSFER_ITEM)\n\t\t{\n\t\t\tRuleItem *rule = (RuleItem*)_items[i].rule;\n\t\t\tammo = (rule->getBattleType() == BT_AMMO || (rule->getBattleType() == BT_NONE && rule->getClipSize() > 0));\n\t\t\tif (ammo)\n\t\t\t{\n\t\t\t\tname.insert(0, \"  \");\n\t\t\t}\n\t\t}\n\t\tstd::ostringstream ssQtySrc, ssQtyDst, ssAmount;\n\t\tssQtySrc << _items[i].qtySrc - _items[i].amount;\n\t\tssQtyDst << _items[i].qtyDst;\n\t\tssAmount << _items[i].amount;\n\t\t_lstItems->addRow(4, name.c_str(), ssQtySrc.str().c_str(), ssAmount.str().c_str(), ssQtyDst.str().c_str());\n\t\t_rows.push_back(i);\n\t\tif (_items[i].amount > 0)\n\t\t{\n\t\t\t_lstItems->setRowColor(_rows.size() - 1, _lstItems->getSecondaryColor());\n\t\t}\n\t\telse if (ammo)\n\t\t{\n\t\t\t_lstItems->setRowColor(_rows.size() - 1, _ammoColor);\n\t\t}\n\t}\n}\n\n/**\n * Transfers the selected items.\n * @param action Pointer to an action.\n */\nvoid TransferItemsState::btnOkClick(Action *)\n{\n\tif (Options::storageLimitsEnforced && !AreSame(_iQty, 0.0))\n\t{\n\t\t// check again (because of items with negative size)\n\t\t// But only check the base whose available space is decreasing.\n\t\tdouble freeStoresTo = _baseTo->getAvailableStores() - _baseTo->getUsedStores() - _iQty;\n\t\tdouble freeStoresFrom = _baseFrom->getAvailableStores() - _baseFrom->getUsedStores() + _iQty;\n\t\tif (_iQty > 0.0 ? freeStoresTo < -0.00001 : freeStoresFrom < -0.00001)\n\t\t{\n\t\t\tRuleInterface *menuInterface = _game->getMod()->getInterface(\"transferMenu\");\n\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_NOT_ENOUGH_STORE_SPACE\"), _palette, menuInterface->getElement(\"errorMessage\")->color, \"BACK13.SCR\", menuInterface->getElement(\"errorPalette\")->color));\n\t\t\treturn;\n\t\t}\n\t}\n\n\t_game->pushState(new TransferConfirmState(_baseTo, this));\n}\n\n/**\n * Completes the transfer between bases.\n */\nvoid TransferItemsState::completeTransfer()\n{\n\tint time = (int)floor(6 + _distance / 10.0);\n\t_game->getSavedGame()->setFunds(_game->getSavedGame()->getFunds() - getTotal());\n\tfor (const auto& transferRow : _items)\n\t{\n\t\tif (transferRow.amount > 0)\n\t\t{\n\t\t\tTransfer *t = 0;\n\t\t\tCraft *craft = 0;\n\t\t\tSoldier* soldier = nullptr;\n\t\t\tswitch (transferRow.type)\n\t\t\t{\n\t\t\tcase TRANSFER_SOLDIER:\n\t\t\t\tfor (auto soldierIt = _baseFrom->getSoldiers()->begin(); soldierIt != _baseFrom->getSoldiers()->end(); ++soldierIt)\n\t\t\t\t{\n\t\t\t\t\tsoldier = (*soldierIt);\n\t\t\t\t\tif (soldier == transferRow.rule)\n\t\t\t\t\t{\n\t\t\t\t\t\tsoldier->setPsiTraining(false);\n\t\t\t\t\t\tif (soldier->isInTraining())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsoldier->setReturnToTrainingWhenHealed(true);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tsoldier->setTraining(false);\n\t\t\t\t\t\tt = new Transfer(time);\n\t\t\t\t\t\tt->setSoldier(soldier);\n\t\t\t\t\t\t_baseTo->getTransfers()->push_back(t);\n\t\t\t\t\t\t_baseFrom->getSoldiers()->erase(soldierIt);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase TRANSFER_CRAFT:\n\t\t\t\tcraft = (Craft*)transferRow.rule;\n\t\t\t\t// Transfer soldiers inside craft\n\t\t\t\tfor (auto soldierIt = _baseFrom->getSoldiers()->begin(); soldierIt != _baseFrom->getSoldiers()->end();)\n\t\t\t\t{\n\t\t\t\t\tsoldier = (*soldierIt);\n\t\t\t\t\tif (soldier->getCraft() == craft)\n\t\t\t\t\t{\n\t\t\t\t\t\tsoldier->setPsiTraining(false);\n\t\t\t\t\t\tif (soldier->isInTraining())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsoldier->setReturnToTrainingWhenHealed(true);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tsoldier->setTraining(false);\n\t\t\t\t\t\tif (craft->getStatus() == \"STR_OUT\")\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_baseTo->getSoldiers()->push_back(soldier);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tt = new Transfer(time);\n\t\t\t\t\t\t\tt->setSoldier(soldier);\n\t\t\t\t\t\t\t_baseTo->getTransfers()->push_back(t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tsoldierIt = _baseFrom->getSoldiers()->erase(soldierIt);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t++soldierIt;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Transfer craft\n\t\t\t\t_baseFrom->removeCraft(craft, false);\n\t\t\t\tif (craft->getStatus() == \"STR_OUT\")\n\t\t\t\t{\n\t\t\t\t\tbool returning = (craft->getDestination() == (Target*)craft->getBase());\n\t\t\t\t\t_baseTo->getCrafts()->push_back(craft);\n\t\t\t\t\tcraft->setBase(_baseTo, false);\n\t\t\t\t\tif (craft->getFuel() <= craft->getFuelLimit(_baseTo))\n\t\t\t\t\t{\n\t\t\t\t\t\tcraft->setLowFuel(true);\n\t\t\t\t\t\tcraft->returnToBase();\n\t\t\t\t\t}\n\t\t\t\t\telse if (returning)\n\t\t\t\t\t{\n\t\t\t\t\t\tcraft->setLowFuel(false);\n\t\t\t\t\t\tcraft->returnToBase();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tt = new Transfer(time);\n\t\t\t\t\tt->setCraft(craft);\n\t\t\t\t\t_baseTo->getTransfers()->push_back(t);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase TRANSFER_SCIENTIST:\n\t\t\t\t_baseFrom->setScientists(_baseFrom->getScientists() - transferRow.amount);\n\t\t\t\tt = new Transfer(time);\n\t\t\t\tt->setScientists(transferRow.amount);\n\t\t\t\t_baseTo->getTransfers()->push_back(t);\n\t\t\t\tbreak;\n\t\t\tcase TRANSFER_ENGINEER:\n\t\t\t\t_baseFrom->setEngineers(_baseFrom->getEngineers() - transferRow.amount);\n\t\t\t\tt = new Transfer(time);\n\t\t\t\tt->setEngineers(transferRow.amount);\n\t\t\t\t_baseTo->getTransfers()->push_back(t);\n\t\t\t\tbreak;\n\t\t\tcase TRANSFER_ITEM:\n\t\t\t\tRuleItem *item = (RuleItem*)transferRow.rule;\n\t\t\t\t_baseFrom->getStorageItems()->removeItem(item, transferRow.amount);\n\t\t\t\tt = new Transfer(time);\n\t\t\t\tt->setItems(item, transferRow.amount);\n\t\t\t\t_baseTo->getTransfers()->push_back(t);\n\t\t\t\tif (_debriefingState != 0)\n\t\t\t\t{\n\t\t\t\t\t// remember the decreased amount for next sell/transfer\n\t\t\t\t\t_debriefingState->decreaseRecoveredItemCount(item, transferRow.amount);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (_debriefingState != 0 && _debriefingState->getTotalRecoveredItemCount() <= 0)\n\t{\n\t\t_debriefingState->hideSellTransferButtons();\n\t}\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid TransferItemsState::btnCancelClick(Action *)\n{\n\t_game->popState();\n\t_game->popState();\n}\n\n/**\n * Increase all items to max, i.e. transfer everything.\n * @param action Pointer to an action.\n */\nvoid TransferItemsState::btnTransferAllClick(Action *)\n{\n\tbool allItemsSelected = true;\n\tfor (size_t i = 0; i < _lstItems->getTexts(); ++i)\n\t{\n\t\tif (_items[_rows[i]].type == TRANSFER_ITEM && _items[_rows[i]].amount < _items[_rows[i]].qtySrc)\n\t\t{\n\t\t\tallItemsSelected = false;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tsize_t backup = _sel;\n\t_errorShown = false;\n\tfor (size_t i = 0; i < _lstItems->getTexts(); ++i)\n\t{\n\t\tif (_items[_rows[i]].type == TRANSFER_ITEM)\n\t\t{\n\t\t\t_sel = i;\n\t\t\tallItemsSelected ? decreaseByValue(INT_MAX) : increaseByValue(INT_MAX);\n\t\t\tif (_errorShown)\n\t\t\t{\n\t\t\t\tbreak; // stop on first error\n\t\t\t}\n\t\t}\n\t}\n\t_sel = backup;\n}\n\n/**\n * Starts increasing the item.\n * @param action Pointer to an action.\n */\nvoid TransferItemsState::lstItemsLeftArrowPress(Action *action)\n{\n\t_sel = _lstItems->getSelectedRow();\n\tif (_game->isLeftClick(action, true) && !_timerInc->isRunning()) _timerInc->start();\n}\n\n/**\n * Stops increasing the item.\n * @param action Pointer to an action.\n */\nvoid TransferItemsState::lstItemsLeftArrowRelease(Action *action)\n{\n\tif (_game->isLeftClick(action, true))\n\t{\n\t\t_timerInc->stop();\n\t}\n}\n\n/**\n * Increases the selected item;\n * by one on left-click; to max on right-click.\n * @param action Pointer to an action.\n */\nvoid TransferItemsState::lstItemsLeftArrowClick(Action *action)\n{\n\tif (_game->isRightClick(action, true)) increaseByValue(INT_MAX);\n\tif (_game->isLeftClick(action, true))\n\t{\n\t\tincreaseByValue(_game->getScrollStep());\n\t\t_timerInc->setInterval(250);\n\t\t_timerDec->setInterval(250);\n\t}\n}\n\n/**\n * Starts decreasing the item.\n * @param action Pointer to an action.\n */\nvoid TransferItemsState::lstItemsRightArrowPress(Action *action)\n{\n\t_sel = _lstItems->getSelectedRow();\n\tif (_game->isLeftClick(action, true) && !_timerDec->isRunning()) _timerDec->start();\n}\n\n/**\n * Stops decreasing the item.\n * @param action Pointer to an action.\n */\nvoid TransferItemsState::lstItemsRightArrowRelease(Action *action)\n{\n\tif (_game->isLeftClick(action, true))\n\t{\n\t\t_timerDec->stop();\n\t}\n}\n\n/**\n * Decreases the selected item;\n * by one on left-click; to 0 on right-click.\n * @param action Pointer to an action.\n */\nvoid TransferItemsState::lstItemsRightArrowClick(Action *action)\n{\n\tif (_game->isRightClick(action, true)) decreaseByValue(INT_MAX);\n\tif (_game->isLeftClick(action, true))\n\t{\n\t\tdecreaseByValue(_game->getScrollStep());\n\t\t_timerInc->setInterval(250);\n\t\t_timerDec->setInterval(250);\n\t}\n}\n\n/**\n * Handles the mouse-wheels on the arrow-buttons.\n * @param action Pointer to an action.\n */\nvoid TransferItemsState::lstItemsMousePress(Action *action)\n{\n\t_sel = _lstItems->getSelectedRow();\n\tif (action->getDetails()->button.button == SDL_BUTTON_WHEELUP)\n\t{\n\t\t_timerInc->stop();\n\t\t_timerDec->stop();\n\t\tif (action->getAbsoluteXMouse() >= _lstItems->getArrowsLeftEdge() &&\n\t\t\taction->getAbsoluteXMouse() <= _lstItems->getArrowsRightEdge())\n\t\t{\n\t\t\tincreaseByValue(Options::changeValueByMouseWheel);\n\t\t}\n\t}\n\telse if (action->getDetails()->button.button == SDL_BUTTON_WHEELDOWN)\n\t{\n\t\t_timerInc->stop();\n\t\t_timerDec->stop();\n\t\tif (action->getAbsoluteXMouse() >= _lstItems->getArrowsLeftEdge() &&\n\t\t\taction->getAbsoluteXMouse() <= _lstItems->getArrowsRightEdge())\n\t\t{\n\t\t\tdecreaseByValue(Options::changeValueByMouseWheel);\n\t\t}\n\t}\n\telse if (_game->isRightClick(action, true))\n\t{\n\t\tif (action->getAbsoluteXMouse() >= _lstItems->getArrowsLeftEdge() &&\n\t\t\taction->getAbsoluteXMouse() <= _lstItems->getArrowsRightEdge())\n\t\t{\n\t\t\treturn;\n\t\t}\n\t\tif (getRow().type == TRANSFER_ITEM)\n\t\t{\n\t\t\tRuleItem *rule = (RuleItem*)getRow().rule;\n\t\t\tif (rule != 0)\n\t\t\t{\n\t\t\t\tif (_game->isCtrlPressed(true))\n\t\t\t\t{\n\t\t\t\t\t_game->pushState(new ItemLocationsState(rule));\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t_game->pushState(new ManufactureDependenciesTreeState(rule->getType()));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\telse if (_game->isMiddleClick(action, true))\n\t{\n\t\tif (getRow().type == TRANSFER_ITEM)\n\t\t{\n\t\t\tRuleItem *rule = (RuleItem*)getRow().rule;\n\t\t\tif (rule != 0)\n\t\t\t{\n\t\t\t\tstd::string articleId = rule->getUfopediaType();\n\t\t\t\tif (_game->isCtrlPressed(true))\n\t\t\t\t{\n\t\t\t\t\tUfopaedia::openArticle(_game, articleId);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tconst RuleResearch* selectedTopic = _game->getMod()->getResearch(articleId, false);\n\t\t\t\t\tif (selectedTopic)\n\t\t\t\t\t{\n\t\t\t\t\t\t_game->pushState(new TechTreeViewerState(selectedTopic, 0));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse if (getRow().type == TRANSFER_CRAFT)\n\t\t{\n\t\t\tCraft *rule = (Craft*)getRow().rule;\n\t\t\tif (rule != 0)\n\t\t\t{\n\t\t\t\tstd::string articleId = rule->getRules()->getType();\n\t\t\t\tif (_game->isCtrlPressed(true))\n\t\t\t\t{\n\t\t\t\t\tUfopaedia::openArticle(_game, articleId);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t_game->pushState(new TechTreeViewerState(0, 0, 0, rule->getRules()));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Increases the quantity of the selected item to transfer by one.\n */\nvoid TransferItemsState::increase()\n{\n\t_timerDec->setInterval(50);\n\t_timerInc->setInterval(50);\n\tincreaseByValue(_game->getScrollStep());\n}\n\n/**\n * Increases the quantity of the selected item to transfer by \"change\".\n * @param change How much we want to add.\n */\nvoid TransferItemsState::increaseByValue(int change)\n{\n\tif (0 >= change || getRow().qtySrc <= getRow().amount) return;\n\tstd::string errorMessage;\n\tRuleItem *selItem = 0;\n\tCraft *craft = 0;\n\n\tswitch (getRow().type)\n\t{\n\tcase TRANSFER_SOLDIER:\n\tcase TRANSFER_SCIENTIST:\n\tcase TRANSFER_ENGINEER:\n\t\tif (_pQty + 1 > _baseTo->getAvailableQuarters() - _baseTo->getUsedQuarters())\n\t\t{\n\t\t\terrorMessage = tr(\"STR_NO_FREE_ACCOMODATION\");\n\t\t}\n\t\tbreak;\n\tcase TRANSFER_CRAFT:\n\t\tcraft = (Craft*)getRow().rule;\n\t\tif (_cQty + 1 > _baseTo->getAvailableHangars() - _baseTo->getUsedHangars())\n\t\t{\n\t\t\terrorMessage = tr(\"STR_NO_FREE_HANGARS_FOR_TRANSFER\");\n\t\t}\n\t\telse if (craft->getNumTotalSoldiers() > 0 && _pQty + craft->getNumTotalSoldiers() > _baseTo->getAvailableQuarters() - _baseTo->getUsedQuarters())\n\t\t{\n\t\t\terrorMessage = tr(\"STR_NO_FREE_ACCOMODATION_CREW\");\n\t\t}\n\t\telse if (Options::storageLimitsEnforced)\n\t\t{\n\t\t\tdouble used = craft->getTotalItemStorageSize();\n\t\t\tif (used > 0.0 && _baseTo->storesOverfull(_iQty + used))\n\t\t\t{\n\t\t\t\terrorMessage = tr(\"STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT\");\n\t\t\t}\n\t\t}\n\t\tbreak;\n\tcase TRANSFER_ITEM:\n\t\tselItem = (RuleItem*)getRow().rule;\n\t\tif (selItem->getSize() > 0.0 && _baseTo->storesOverfull(selItem->getSize() + _iQty))\n\t\t{\n\t\t\terrorMessage = tr(\"STR_NOT_ENOUGH_STORE_SPACE\");\n\t\t}\n\t\tif (selItem->isAlien())\n\t\t{\n\t\t\tif (Options::storageLimitsEnforced * _aQty + 1 > _baseTo->getAvailableContainment(selItem->getPrisonType()) - Options::storageLimitsEnforced * _baseTo->getUsedContainment(selItem->getPrisonType()))\n\t\t\t{\n\t\t\t\terrorMessage = trAlt(\"STR_NO_ALIEN_CONTAINMENT_FOR_TRANSFER\", selItem->getPrisonType());\n\t\t\t}\n\t\t}\n\t\tbreak;\n\t}\n\n\tif (errorMessage.empty())\n\t{\n\t\tint freeQuarters = _baseTo->getAvailableQuarters() - _baseTo->getUsedQuarters() - _pQty;\n\t\tswitch (getRow().type)\n\t\t{\n\t\tcase TRANSFER_SOLDIER:\n\t\tcase TRANSFER_SCIENTIST:\n\t\tcase TRANSFER_ENGINEER:\n\t\t\tchange = std::min(std::min(freeQuarters, getRow().qtySrc - getRow().amount), change);\n\t\t\t_pQty += change;\n\t\t\tgetRow().amount += change;\n\t\t\t_total += getRow().cost * change;\n\t\t\tbreak;\n\t\tcase TRANSFER_CRAFT:\n\t\t\t_cQty++;\n\t\t\t_pQty += craft->getNumTotalSoldiers();\n\t\t\t_iQty += craft->getTotalItemStorageSize();\n\t\t\tgetRow().amount++;\n\t\t\tif (!Options::canTransferCraftsWhileAirborne || craft->getStatus() != \"STR_OUT\")\n\t\t\t\t_total += getRow().cost;\n\t\t\tbreak;\n\t\tcase TRANSFER_ITEM:\n\t\t\tif (selItem->isAlien())\n\t\t\t{\n\t\t\t\tint freeContainment = Options::storageLimitsEnforced ? _baseTo->getAvailableContainment(selItem->getPrisonType()) - _baseTo->getUsedContainment(selItem->getPrisonType()) - _aQty : INT_MAX;\n\t\t\t\tchange = std::min(std::min(freeContainment, getRow().qtySrc - getRow().amount), change);\n\t\t\t}\n\t\t\t// both aliens and items\n\t\t\t{\n\t\t\t\tdouble storesNeededPerItem = ((RuleItem*)getRow().rule)->getSize();\n\t\t\t\tdouble freeStores = _baseTo->getAvailableStores() - _baseTo->getUsedStores() - _iQty;\n\t\t\t\tdouble freeStoresForItem = (double)(INT_MAX);\n\t\t\t\tif (!AreSame(storesNeededPerItem, 0.0) && storesNeededPerItem > 0.0)\n\t\t\t\t{\n\t\t\t\t\tfreeStoresForItem = (freeStores + 0.05) / storesNeededPerItem;\n\t\t\t\t}\n\t\t\t\tchange = std::min(std::min((int)freeStoresForItem, getRow().qtySrc - getRow().amount), change);\n\t\t\t\t_iQty += change * storesNeededPerItem;\n\t\t\t}\n\t\t\tif (selItem->isAlien())\n\t\t\t{\n\t\t\t\t_aQty += change;\n\t\t\t}\n\t\t\tgetRow().amount += change;\n\t\t\t_total += getRow().cost * change;\n\t\t\tbreak;\n\t\t}\n\t\tupdateItemStrings();\n\t}\n\telse\n\t{\n\t\t_timerInc->stop();\n\t\tRuleInterface *menuInterface = _game->getMod()->getInterface(\"transferMenu\");\n\t\t_game->pushState(new ErrorMessageState(errorMessage, _palette, menuInterface->getElement(\"errorMessage\")->color, \"BACK13.SCR\", menuInterface->getElement(\"errorPalette\")->color));\n\t\t_errorShown = true;\n\t}\n}\n\n/**\n * Decreases the quantity of the selected item to transfer by one.\n */\nvoid TransferItemsState::decrease()\n{\n\t_timerInc->setInterval(50);\n\t_timerDec->setInterval(50);\n\tdecreaseByValue(_game->getScrollStep());\n}\n\n/**\n * Decreases the quantity of the selected item to transfer by \"change\".\n * @param change How much we want to remove.\n */\nvoid TransferItemsState::decreaseByValue(int change)\n{\n\tif (0 >= change || 0 >= getRow().amount) return;\n\tCraft *craft = 0;\n\tchange = std::min(getRow().amount, change);\n\n\tswitch (getRow().type)\n\t{\n\tcase TRANSFER_SOLDIER:\n\tcase TRANSFER_SCIENTIST:\n\tcase TRANSFER_ENGINEER:\n\t\t_pQty -= change;\n\t\tbreak;\n\tcase TRANSFER_CRAFT:\n\t\tcraft = (Craft*)getRow().rule;\n\t\t_cQty--;\n\t\t_pQty -= craft->getNumTotalSoldiers();\n\t\t_iQty -= craft->getTotalItemStorageSize();\n\t\tbreak;\n\tcase TRANSFER_ITEM:\n\t\tconst RuleItem *selItem = (RuleItem*)getRow().rule;\n\t\t_iQty -= selItem->getSize() * change;\n\t\tif (selItem->isAlien())\n\t\t{\n\t\t\t_aQty -= change;\n\t\t}\n\t\tbreak;\n\t}\n\tgetRow().amount -= change;\n\tif (!Options::canTransferCraftsWhileAirborne || 0 == craft || craft->getStatus() != \"STR_OUT\")\n\t\t_total -= getRow().cost * change;\n\tupdateItemStrings();\n}\n\n/**\n * Updates the quantity-strings of the selected item.\n */\nvoid TransferItemsState::updateItemStrings()\n{\n\tstd::ostringstream ss1, ss2;\n\tss1 << getRow().qtySrc - getRow().amount;\n\tss2 << getRow().amount;\n\t_lstItems->setCellText(_sel, 1, ss1.str());\n\t_lstItems->setCellText(_sel, 2, ss2.str());\n\n\tif (getRow().amount > 0)\n\t{\n\t\t_lstItems->setRowColor(_sel, _lstItems->getSecondaryColor());\n\t}\n\telse\n\t{\n\t\t_lstItems->setRowColor(_sel, _lstItems->getColor());\n\t\tif (getRow().type == TRANSFER_ITEM)\n\t\t{\n\t\t\tRuleItem *rule = (RuleItem*)getRow().rule;\n\t\t\tif (rule->getBattleType() == BT_AMMO || (rule->getBattleType() == BT_NONE && rule->getClipSize() > 0))\n\t\t\t{\n\t\t\t\t_lstItems->setRowColor(_sel, _ammoColor);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Gets the total cost of the current transfer.\n * @return Total cost.\n */\nint TransferItemsState::getTotal() const\n{\n\treturn std::max(1, _total * _game->getMod()->getGlobalTransferCostMultiplier() / _game->getMod()->getGlobalTransferCostDivider());\n}\n\n/**\n * Gets the shortest distance between the two bases.\n * @return Distance.\n */\ndouble TransferItemsState::getDistance() const\n{\n\tdouble x[3], y[3], z[3], r = 51.2;\n\tBase *base = _baseFrom;\n\tfor (int i = 0; i < 2; ++i) {\n\t\tx[i] = r * cos(base->getLatitude()) * cos(base->getLongitude());\n\t\ty[i] = r * cos(base->getLatitude()) * sin(base->getLongitude());\n\t\tz[i] = r * -sin(base->getLatitude());\n\t\tbase = _baseTo;\n\t}\n\tx[2] = x[1] - x[0];\n\ty[2] = y[1] - y[0];\n\tz[2] = z[1] - z[0];\n\treturn sqrt(x[2] * x[2] + y[2] * y[2] + z[2] * z[2]);\n}\n\n/**\n* Updates the production list to match the category filter.\n*/\nvoid TransferItemsState::cbxCategoryChange(Action *)\n{\n\t_previousSort = _currentSort;\n\n\tif (_game->isCtrlPressed(true))\n\t{\n\t\t_currentSort = _game->isShiftPressed(true) ? TransferSortDirection::BY_UNIT_SIZE : TransferSortDirection::BY_TOTAL_SIZE;\n\t}\n\telse if (_game->isAltPressed(true))\n\t{\n\t\t_currentSort = _game->isShiftPressed(true) ? TransferSortDirection::BY_UNIT_COST : TransferSortDirection::BY_TOTAL_COST;\n\t}\n\telse\n\t{\n\t\t_currentSort = TransferSortDirection::BY_LIST_ORDER;\n\t}\n\n\tupdateList();\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/TransferItemsState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/TouchState.h\"\n#include \"../Savegame/Transfer.h\"\n#include <vector>\n#include <string>\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass TextEdit;\nclass TextList;\nclass ComboBox;\nclass Timer;\nclass Base;\nclass DebriefingState;\nclass RuleItem;\n\n/**\n * Transfer screen that lets the player pick\n * what items to transfer between bases.\n */\nclass TransferItemsState : public TouchState\n{\nprivate:\n\tBase *_baseFrom, *_baseTo;\n\tDebriefingState *_debriefingState;\n\tTextButton *_btnOk, *_btnCancel;\n\tTextEdit *_btnQuickSearch;\n\tWindow *_window;\n\tText *_txtTitle, *_txtQuantity, *_txtAmountTransfer, *_txtAmountDestination;\n\tComboBox *_cbxCategory;\n\tTextList *_lstItems;\n\tstd::vector<TransferRow> _items;\n\tstd::vector<int> _rows;\n\tstd::vector<std::string> _cats;\n\tsize_t _vanillaCategories;\n\tsize_t _sel;\n\tint _total, _pQty, _cQty, _aQty;\n\tdouble _iQty;\n\tdouble _distance;\n\tUint8 _ammoColor;\n\tTimer *_timerInc, *_timerDec;\n\tTransferSortDirection _previousSort, _currentSort;\n\tbool _errorShown;\n\n\t/// Gets the category of the current selection.\n\tstd::string getCategory(int sel) const;\n\t/// Determines if the current selection belongs to a given category.\n\tbool belongsToCategory(int sel, const std::string &cat) const;\n\t/// Gets the row of the current selection.\n\tTransferRow &getRow() { return _items[_rows[_sel]]; }\n\t/// Gets distance between bases.\n\tdouble getDistance() const;\npublic:\n\t/// Creates the Transfer Items state.\n\tTransferItemsState(Base *baseFrom, Base *baseTo, DebriefingState *debriefingState);\n\t/// Cleans up the Transfer Items state.\n\t~TransferItemsState();\n\t/// Resets state.\n\tvoid init() override;\n\t/// Runs the timers.\n\tvoid think() override;\n\t/// Updates the item list.\n\tvoid updateList();\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handlers for Quick Search.\n\tvoid btnQuickSearchToggle(Action *action);\n\tvoid btnQuickSearchApply(Action *action);\n\t/// Handler for pressing the \"Transfer all\" hotkey.\n\tvoid btnTransferAllClick(Action *action);\n\t/// Completes the transfer between bases.\n\tvoid completeTransfer();\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action *action);\n\t/// Handler for pressing an Increase arrow in the list.\n\tvoid lstItemsLeftArrowPress(Action *action);\n\t/// Handler for releasing an Increase arrow in the list.\n\tvoid lstItemsLeftArrowRelease(Action *action);\n\t/// Handler for clicking an Increase arrow in the list.\n\tvoid lstItemsLeftArrowClick(Action *action);\n\t/// Handler for pressing a Decrease arrow in the list.\n\tvoid lstItemsRightArrowPress(Action *action);\n\t/// Handler for releasing a Decrease arrow in the list.\n\tvoid lstItemsRightArrowRelease(Action *action);\n\t/// Handler for clicking a Decrease arrow in the list.\n\tvoid lstItemsRightArrowClick(Action *action);\n\t/// Handler for pressing-down a mouse-button in the list.\n\tvoid lstItemsMousePress(Action *action);\n\t/// Increases the quantity of an item by one.\n\tvoid increase();\n\t/// Increases the quantity of an item by the given value.\n\tvoid increaseByValue(int change);\n\t/// Decreases the quantity of an item by one.\n\tvoid decrease();\n\t/// Decreases the quantity of an item by the given value.\n\tvoid decreaseByValue(int change);\n\t/// Updates the quantity-strings of the selected item.\n\tvoid updateItemStrings();\n\t/// Gets the total of the transfer.\n\tint getTotal() const;\n\t/// Handler for changing the category filter.\n\tvoid cbxCategoryChange(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Basescape/TransfersState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"TransfersState.h\"\n#include <sstream>\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/Transfer.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Transfers window.\n * @param game Pointer to the core game.\n * @param base Pointer to the base to get info from.\n */\nTransfersState::TransfersState(Base *base) : _base(base)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 320, 184, 0, 8, POPUP_BOTH);\n\t_btnOk = new TextButton(288, 16, 16, 166);\n\t_txtTitle = new Text(278, 17, 21, 18);\n\t_txtItem = new Text(114, 9, 16, 34);\n\t_txtQuantity = new Text(54, 9, 152, 34);\n\t_txtArrivalTime = new Text(112, 9, 212, 34);\n\t_lstTransfers = new TextList(273, 112, 14, 50);\n\n\t// Set palette\n\tsetInterface(\"transferInfo\");\n\n\tadd(_window, \"window\", \"transferInfo\");\n\tadd(_btnOk, \"button\", \"transferInfo\");\n\tadd(_txtTitle, \"text\", \"transferInfo\");\n\tadd(_txtItem, \"text\", \"transferInfo\");\n\tadd(_txtQuantity, \"text\", \"transferInfo\");\n\tadd(_txtArrivalTime, \"text\", \"transferInfo\");\n\tadd(_lstTransfers, \"list\", \"transferInfo\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"transferInfo\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&TransfersState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&TransfersState::btnOkClick, Options::keyOk);\n\t_btnOk->onKeyboardPress((ActionHandler)&TransfersState::btnOkClick, Options::keyCancel);\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_TRANSFERS\"));\n\n\t_txtItem->setText(tr(\"STR_ITEM\"));\n\n\t_txtQuantity->setText(tr(\"STR_QUANTITY_UC\"));\n\n\t_txtArrivalTime->setText(tr(\"STR_ARRIVAL_TIME_HOURS\"));\n\n\t_lstTransfers->setColumns(3, 155, 75, 46);\n\t_lstTransfers->setSelectable(true);\n\t_lstTransfers->setBackground(_window);\n\t_lstTransfers->setMargin(2);\n\n\tfor (const auto* transfer : *_base->getTransfers())\n\t{\n\t\tstd::ostringstream ss, ss2;\n\t\tss << transfer->getQuantity();\n\t\tss2 << transfer->getHours();\n\t\t_lstTransfers->addRow(3, transfer->getName(_game->getLanguage()).c_str(), ss.str().c_str(), ss2.str().c_str());\n\t}\n}\n\n/**\n *\n */\nTransfersState::~TransfersState()\n{\n\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid TransfersState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Basescape/TransfersState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass Base;\nclass TextButton;\nclass Window;\nclass Text;\nclass TextList;\n\n/**\n * Transfers window that displays all\n * the items currently in-transit to a base.\n */\nclass TransfersState : public State\n{\nprivate:\n\tBase *_base;\n\n\tTextButton *_btnOk;\n\tWindow *_window;\n\tText *_txtTitle, *_txtItem, *_txtQuantity, *_txtArrivalTime;\n\tTextList *_lstTransfers;\npublic:\n\t/// Creates the Transfers state.\n\tTransfersState(Base *base);\n\t/// Cleans up the Transfers state.\n\t~TransfersState();\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/AIModule.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <climits>\n#include <algorithm>\n#include \"AIModule.h\"\n#include \"../Savegame/BattleItem.h\"\n#include \"../Savegame/Node.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"TileEngine.h\"\n#include \"BattlescapeState.h\"\n#include \"../Savegame/Tile.h\"\n#include \"Pathfinding.h\"\n#include \"../Engine/RNG.h\"\n#include \"../Engine/Logger.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"../fmath.h\"\n\nnamespace OpenXcom\n{\n\n\n/**\n * Sets up a BattleAIState.\n * @param save Pointer to the battle game.\n * @param unit Pointer to the unit.\n * @param node Pointer to the node the unit originates from.\n */\nAIModule::AIModule(SavedBattleGame *save, BattleUnit *unit, Node *node) :\n\t_save(save), _unit(unit), _aggroTarget(0), _knownEnemies(0), _visibleEnemies(0), _spottingEnemies(0),\n\t_escapeTUs(0), _ambushTUs(0), _weaponPickedUp(false), _rifle(false), _melee(false), _blaster(false), _grenade(false),\n\t_didPsi(false), _AIMode(AI_PATROL), _closestDist(100), _fromNode(node), _toNode(0), _foundBaseModuleToDestroy(false)\n{\n\t_traceAI = Options::traceAI;\n\n\t_reserve = BA_NONE;\n\t_intelligence = _unit->getIntelligence();\n\t_escapeAction = BattleAction();\n\t_ambushAction = BattleAction();\n\t_attackAction = BattleAction();\n\t_patrolAction = BattleAction();\n\t_psiAction = BattleAction();\n\t_targetFaction = FACTION_PLAYER;\n\tif (_unit->getOriginalFaction() == FACTION_NEUTRAL)\n\t{\n\t\t_targetFaction = FACTION_HOSTILE;\n\t}\n}\n\n/**\n * Deletes the BattleAIState.\n */\nAIModule::~AIModule()\n{\n\n}\n\n/**\n * Sets the target faction.\n */\nvoid AIModule::setTargetFaction(UnitFaction f)\n{\n\t_targetFaction = f;\n}\n\n/**\n * Resets the unsaved AI state.\n */\nvoid AIModule::reset()\n{\n\t// these variables are not saved in save() and also not initiated in think()\n\t_escapeTUs = 0;\n\t_ambushTUs = 0;\n}\n\n/**\n * Loads the AI state from a YAML file.\n * @param node YAML node.\n */\nvoid AIModule::load(const YAML::YamlNodeReader& reader)\n{\n\tint fromNodeID = reader[\"fromNode\"].readVal(-1);\n\tint toNodeID = reader[\"toNode\"].readVal(-1);\n\t_AIMode = reader[\"AIMode\"].readVal(AI_PATROL);\n\treader.tryRead(\"wasHitBy\", _wasHitBy);\n\treader.tryRead(\"weaponPickedUp\", _weaponPickedUp);\n\treader.tryRead(\"targetFaction\", _targetFaction);\n\n\t// TODO: Figure out why AI are sometimes left with junk nodes\n\tif (fromNodeID >= 0 && (size_t)fromNodeID < _save->getNodes()->size())\n\t{\n\t\t_fromNode = _save->getNodes()->at(fromNodeID);\n\t}\n\tif (toNodeID >= 0 && (size_t)toNodeID < _save->getNodes()->size())\n\t{\n\t\t_toNode = _save->getNodes()->at(toNodeID);\n\t}\n}\n\n/**\n * Saves the AI state to a YAML file.\n * @return YAML node.\n */\nvoid AIModule::save(YAML::YamlNodeWriter writer) const\n{\n\twriter.setAsMap();\n\twriter.setFlowStyle();\n\twriter.write(\"fromNode\", _fromNode ? _fromNode->getID() : -1);\n\twriter.write(\"toNode\", _toNode ? _toNode->getID() : -1);\n\twriter.write(\"AIMode\", _AIMode);\n\twriter.write(\"wasHitBy\", _wasHitBy);\n\tif (_weaponPickedUp)\n\t\twriter.write(\"weaponPickedUp\", _weaponPickedUp);\n\tif (_unit->getOriginalFaction() == FACTION_HOSTILE && _unit->getFaction() == FACTION_NEUTRAL && _targetFaction == FACTION_HOSTILE)\n\t{\n\t\twriter.write(\"targetFaction\", _targetFaction);\n\t}\n}\n\n/**\n * Mindless charge strategy. For mindless units.\n * Consists of running around and charging nearest visible enemy.\n * @param action (possible) AI action to execute after thinking is done.\n */\nvoid AIModule::dont_think(BattleAction *action)\n{\n\t_melee = false;\n\taction->weapon = _unit->getUtilityWeapon(BT_MELEE);\n\n\tif (_traceAI)\n\t{\n\t\tLog(LOG_INFO) << \"LEEROY: Unit \" << _unit->getId() << \" of type \" << _unit->getType() << \" is Leeroy...\";\n\t}\n\tif (action->weapon)\n\t{\n\t\tif (action->weapon->getRules()->getBattleType() == BT_MELEE)\n\t\t{\n\t\t\tif (_save->canUseWeapon(action->weapon, _unit, false, BA_HIT))\n\t\t\t{\n\t\t\t\t_melee = true;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\taction->weapon = 0;\n\t\t}\n\t}\n\n\tbool canRun = _melee && _unit->getArmor()->allowsRunning(false) && _unit->getEnergy() > _unit->getBaseStats()->stamina * 0.4f;\n\tint visibleEnemiesToAttack = selectNearestTargetLeeroy(canRun);\n\tif (_traceAI)\n\t{\n\t\tLog(LOG_INFO) << \"LEEROY: visibleEnemiesToAttack: \" << visibleEnemiesToAttack << \" _melee: \" << _melee << (canRun ? \" run\" : \"\");\n\t}\n\tif ((visibleEnemiesToAttack > 0) && _melee)\n\t{\n\t\tif (_traceAI)\n\t\t{\n\t\t\tLog(LOG_INFO) << \"LEEROY: LEEROYIN' at someone!\";\n\t\t}\n\t\tmeleeActionLeeroy(canRun);\n\t\taction->type = _attackAction.type;\n\t\taction->run = _attackAction.run;\n\t\taction->target = _attackAction.target;\n\t\t// if this is a firepoint action, set our facing.\n\t\taction->finalFacing = _attackAction.finalFacing;\n\t\taction->updateTU();\n\t}\n\telse\n\t{\n\t\tif (_traceAI)\n\t\t{\n\t\t\tLog(LOG_INFO) << \"LEEROY: No one to LEEROY!, patrolling...\";\n\t\t}\n\t\tsetupPatrol();\n\t\t_unit->setCharging(0);\n\t\t_reserve = BA_NONE;\n\t\taction->type = _patrolAction.type;\n\t\taction->target = _patrolAction.target;\n\t}\n}\n\n/**\n * Tries to use self-target medikit if needed and desired (used for AI).\n * @return Was it used?\n */\nbool AIModule::medikit_think(BattleMediKitType healOrStim)\n{\n\t// 1. sanity checks, division by zero\n\tBattleUnit* self = _unit;\n\n\tif (self->getBaseStats()->stamina <= 0 || self->getBaseStats()->health <= 0)\n\t{\n\t\treturn false;\n\t}\n\n\t// 2. quick unit checks (without RNG)\n\tint totalWounds = self->getFatalWounds();\n\tint percentHealthLeft = Clamp((self->getHealth() - self->getStunlevel()) * 100 / self->getBaseStats()->health, 0, 100);\n\tint percentEnergyLeft = Clamp(self->getEnergy() * 100 / self->getBaseStats()->stamina, 0, 100);\n\n\tif (healOrStim == BMT_HEAL)\n\t{\n\t\tif (totalWounds <= 0)\n\t\t\treturn false;\n\t}\n\telse if (healOrStim == BMT_STIMULANT)\n\t{\n\t\tif (self->getStunlevel() <= 0 && percentEnergyLeft >= 40)\n\t\t\treturn false;\n\t}\n\telse\n\t{\n\t\t// unsupported medikit type\n\t\treturn false;\n\t}\n\n\t// 3. quick item checks\n\tstd::vector<BattleItem*> usableMedikits;\n\n\tfor (auto* item : *self->getInventory())\n\t{\n\t\tconst RuleItem* itemRule = item->getRules();\n\t\tif (itemRule->getBattleType() == BT_MEDIKIT &&\n\t\t\t(itemRule->getMediKitType() == healOrStim || itemRule->getMediKitType() == BMT_NORMAL) &&\n\t\t\titemRule->getAllowTargetSelf())\n\t\t{\n\t\t\tif (_save->getTurn() < itemRule->getAIUseDelay(_save->getMod()))\n\t\t\t{\n\t\t\t\t// can't use it yet, too soon\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tusableMedikits.push_back(item);\n\t\t}\n\t}\n\tif (usableMedikits.empty())\n\t{\n\t\t// no compatible medikits available\n\t\treturn false;\n\t}\n\n\t// 4. detailed unit checks (with RNG)\n\tbool wantsToHeal = false;\n\tbool wantsToStimStun = false;\n\tbool wantsToStimEnergy = false;\n\n\tif (healOrStim == BMT_HEAL)\n\t{\n\t\tif (totalWounds > 0)\n\t\t{\n\t\t\tif (self->getStunlevel() + totalWounds >= self->getHealth())\n\t\t\t{\n\t\t\t\t// going to die or pass out unless we do something, so do something!\n\t\t\t\twantsToHeal = true;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t//  0% health left = 120% chance to heal\n\t\t\t\t// 15% health left =  60% chance to heal\n\t\t\t\t// 30% health left =   0% chance to heal (actually 5% chance because of random heal wish)\n\t\t\t\tint chanceToHeal = 120 - (percentHealthLeft * 4);\n\t\t\t\tif (chanceToHeal <= 0)\n\t\t\t\t{\n\t\t\t\t\t// 5% for random heal wish (it's not urgent, but you know damage accumulates over time)\n\t\t\t\t\tchanceToHeal = 5;\n\t\t\t\t}\n\t\t\t\twantsToHeal = RNG::percent(chanceToHeal);\n\t\t\t}\n\t\t}\n\t\tif (!wantsToHeal)\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\telse if (healOrStim == BMT_STIMULANT)\n\t{\n\t\t// 1. do we want to decrease stun level?\n\t\tif (self->getStunlevel() > 0)\n\t\t{\n\t\t\tif (self->getStunlevel() + totalWounds >= self->getHealth())\n\t\t\t{\n\t\t\t\t// going to die or pass out unless we do something, so do something!\n\t\t\t\twantsToStimStun = true;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t//  0% health left = 140% chance to stim\n\t\t\t\t// 10% health left =  70% chance to stim\n\t\t\t\t// 20% health left =   0% chance to stim\n\t\t\t\tint chanceToStim1 = 140 - (percentHealthLeft * 7);\n\t\t\t\twantsToStimStun = chanceToStim1 > 0 ? RNG::percent(chanceToStim1) : false;\n\t\t\t}\n\t\t}\n\t\t// 2. do we want to increase energy?\n\t\tif (percentEnergyLeft < 40)\n\t\t{\n\t\t\t//  0% energy left = 120% chance to stim\n\t\t\t// 20% energy left =  60% chance to stim\n\t\t\t// 40% energy left =   0% chance to stim\n\t\t\tint chanceToStim2 = 120 - (percentEnergyLeft * 3);\n\t\t\twantsToStimEnergy = RNG::percent(chanceToStim2);\n\t\t}\n\t\tif (!wantsToStimStun && !wantsToStimEnergy)\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t// 5. let's do it\n\tbool used = false;\n\n\tfor (auto* medikit : usableMedikits)\n\t{\n\t\tconst RuleItem* medikitRule = medikit->getRules();\n\t\t{\n\t\t\tif ((wantsToHeal && medikit->getHealQuantity() > 0) ||\n\t\t\t\t(wantsToStimStun && medikit->getStimulantQuantity() > 0 && medikitRule->getStunRecovery() > 0) ||\n\t\t\t\t(wantsToStimEnergy && medikit->getStimulantQuantity() > 0 && medikitRule->getEnergyRecovery() > 0))\n\t\t\t{\n\t\t\t\tBattleAction medikitAction;\n\t\t\t\t{\n\t\t\t\t\tmedikitAction.weapon = medikit;\n\t\t\t\t\tmedikitAction.type = BA_USE;\n\t\t\t\t\tmedikitAction.actor = self;\n\n\t\t\t\t\tmedikitAction.updateTU();\n\n\t\t\t\t\t// yes, hardcoded 4 TUs\n\t\t\t\t\t// AI throwing grenades does that for decades and nobody cares, so calm down\n\t\t\t\t\t// also, AI pays this cost each time, even if using the same medikit multiple times in a row\n\t\t\t\t\tmedikitAction.Time += 4; // 4TUs for picking up the medikit\n\n\t\t\t\t\t// sigh, modders...\n\t\t\t\t\t//medikitAction.Health = 0;\n\t\t\t\t\t//medikitAction.Stun = 0;\n\t\t\t\t}\n\t\t\t\tif (!medikitAction.spendTU())\n\t\t\t\t{\n\t\t\t\t\t// not enough TUs, try next item\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tswitch (healOrStim)\n\t\t\t\t\t{\n\t\t\t\t\tcase BMT_HEAL:\n\t\t\t\t\t\tif (_traceAI)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tLog(LOG_INFO) << \"  Using medikit (heal). TU*/HP/Stun/Wounds: \" <<\n\t\t\t\t\t\t\t\tself->getTimeUnits() << \"/\" << self->getHealth() << \"/\" << self->getStunlevel() << \"/\" << totalWounds;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfor (int i = 0; i < BODYPART_MAX; ++i)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (self->getFatalWound((UnitBodyPart)i))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t_save->getTileEngine()->medikitUse(&medikitAction, self, BMA_HEAL, (UnitBodyPart)i);\n\t\t\t\t\t\t\t\t_save->getTileEngine()->medikitRemoveIfEmpty(&medikitAction);\n\t\t\t\t\t\t\t\tused = true;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase BMT_STIMULANT:\n\t\t\t\t\t\tif (_traceAI)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (wantsToStimStun)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tLog(LOG_INFO) << \"  Using medikit (-stun). TU*/HP/Stun/Wounds: \" <<\n\t\t\t\t\t\t\t\t\tself->getTimeUnits() << \"/\" << self->getHealth() << \"/\" << self->getStunlevel() << \"/\" << totalWounds;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tLog(LOG_INFO) << \"  Using medikit (+energy). TU*/Energy: \" << self->getTimeUnits() << \"/\" << self->getEnergy();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t_save->getTileEngine()->medikitUse(&medikitAction, self, BMA_STIMULANT, BODYPART_TORSO);\n\t\t\t\t\t\t_save->getTileEngine()->medikitRemoveIfEmpty(&medikitAction);\n\t\t\t\t\t\tused = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase BMT_PAINKILLER:\n\t\t\t\t\tcase BMT_NORMAL:\n\t\t\t\t\t\t// not supported\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (used)\n\t\t{\n\t\t\t// only one use per attempt\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// 6. if we used something, let's try again\n\treturn used;\n}\n\n/**\n * Runs any code the state needs to keep updating every AI cycle.\n * @param action (possible) AI action to execute after thinking is done.\n */\nvoid AIModule::think(BattleAction *action)\n{\n\taction->type = BA_RETHINK;\n\taction->actor = _unit;\n\taction->weapon = _unit->getMainHandWeapon(false);\n\t_attackAction.diff = _save->getBattleState()->getGame()->getSavedGame()->getDifficultyCoefficient();\n\t_attackAction.actor = _unit;\n\t_attackAction.run = false;\n\t_attackAction.weapon = action->weapon;\n\t_attackAction.number = action->number;\n\t_escapeAction.number = action->number;\n\t_knownEnemies = countKnownTargets();\n\t_visibleEnemies = selectNearestTarget();\n\t_spottingEnemies = getSpottingUnits(_unit->getPosition());\n\t_melee = (_unit->getUtilityWeapon(BT_MELEE) != 0);\n\t_rifle = false;\n\t_blaster = false;\n\t_reachable = _save->getPathfinding()->findReachable(_unit, BattleActionCost());\n\t_wasHitBy.clear();\n\t_foundBaseModuleToDestroy = false;\n\n\tif (_unit->getCharging() && _unit->getCharging()->isOut())\n\t{\n\t\t_unit->setCharging(0);\n\t}\n\n\tif (_traceAI)\n\t{\n\t\tif (_unit->getFaction() == FACTION_HOSTILE)\n\t\t{\n\t\t\tLog(LOG_INFO) << \"Unit has \" << _visibleEnemies << \"/\" << _knownEnemies << \" known enemies visible, \" << _spottingEnemies << \" of whom are spotting him. \";\n\t\t}\n\t\telse\n\t\t{\n\t\t\tLog(LOG_INFO) << \"Civilian Unit has \" << _visibleEnemies << \" enemies visible, \" << _spottingEnemies << \" of whom are spotting him. \";\n\t\t}\n\t\tstd::string AIMode;\n\t\tswitch (_AIMode)\n\t\t{\n\t\tcase AI_PATROL:\n\t\t\tAIMode = \"Patrol\";\n\t\t\tbreak;\n\t\tcase AI_AMBUSH:\n\t\t\tAIMode = \"Ambush\";\n\t\t\tbreak;\n\t\tcase AI_COMBAT:\n\t\t\tAIMode = \"Combat\";\n\t\t\tbreak;\n\t\tcase AI_ESCAPE:\n\t\t\tAIMode = \"Escape\";\n\t\t\tbreak;\n\t\t}\n\t\tLog(LOG_INFO) << \"Currently using \" << AIMode << \" behaviour\";\n\t}\n\n\tif (_unit->isLeeroyJenkins())\n\t{\n\t\tdont_think(action);\n\t\treturn;\n\t}\n\n\tif (action->weapon)\n\t{\n\t\tconst RuleItem *rule = action->weapon->getRules();\n\t\tif (_save->canUseWeapon(action->weapon, _unit, false, BA_NONE)) // Note: ammo is not checked here\n\t\t{\n\t\t\tif (rule->getBattleType() == BT_FIREARM)\n\t\t\t{\n\t\t\t\tif (action->weapon->getCurrentWaypoints() != 0)\n\t\t\t\t{\n\t\t\t\t\t_blaster = true;\n\t\t\t\t\t_reachableWithAttack = _save->getPathfinding()->findReachable(_unit, BattleActionCost(BA_AIMEDSHOT, _unit, action->weapon));\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t_rifle = true;\n\t\t\t\t\t_reachableWithAttack = _save->getPathfinding()->findReachable(_unit, BattleActionCost(BA_SNAPSHOT, _unit, action->weapon));\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (rule->getBattleType() == BT_MELEE)\n\t\t\t{\n\t\t\t\t_melee = true;\n\t\t\t\t_reachableWithAttack = _save->getPathfinding()->findReachable(_unit, BattleActionCost(BA_HIT, _unit, action->weapon));\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\taction->weapon = 0;\n\t\t}\n\t}\n\n\tBattleItem *grenadeItem = _unit->getGrenadeFromBelt(_save);\n\t_grenade = grenadeItem != 0;\n\n\tif (_spottingEnemies && !_escapeTUs)\n\t{\n\t\tsetupEscape();\n\t}\n\n\tif (_knownEnemies && !_melee && !_ambushTUs)\n\t{\n\t\tsetupAmbush();\n\t}\n\n\tsetupAttack();\n\tsetupPatrol();\n\n\tif (_psiAction.type != BA_NONE && !_didPsi && _save->getTurn() >= _psiAction.weapon->getRules()->getAIUseDelay(_save->getMod()))\n\t{\n\t\t_didPsi = true;\n\t\taction->type = _psiAction.type;\n\t\taction->target = _psiAction.target;\n\t\taction->number -= 1;\n\t\taction->weapon = _psiAction.weapon;\n\t\taction->updateTU();\n\t\treturn;\n\t}\n\telse\n\t{\n\t\t_didPsi = false;\n\t}\n\n\tbool evaluate = false;\n\n\tswitch (_AIMode)\n\t\t{\n\t\tcase AI_PATROL:\n\t\t\tevaluate = (bool)(_spottingEnemies || _visibleEnemies || _knownEnemies || RNG::percent(10));\n\t\t\tbreak;\n\t\tcase AI_AMBUSH:\n\t\t\tevaluate = (!_rifle || !_ambushTUs || _visibleEnemies);\n\t\t\tbreak;\n\t\tcase AI_COMBAT:\n\t\t\tevaluate = (_attackAction.type == BA_RETHINK);\n\t\t\tbreak;\n\t\tcase AI_ESCAPE:\n\t\t\tevaluate = (!_spottingEnemies || !_knownEnemies);\n\t\t\tbreak;\n\t\t\t}\n\n\tif (_weaponPickedUp)\n\t{\n\t\tevaluate = true;\n\t\t_weaponPickedUp = false;\n\t}\n\telse if (_spottingEnemies > 2\n\t\t|| _unit->getHealth() < 2 * _unit->getBaseStats()->health / 3)\n\t{\n\t\tevaluate = true;\n\t}\n\n\n\tif (_save->isCheating() && _AIMode != AI_COMBAT)\n\t{\n\t\tevaluate = true;\n\t}\n\n\tif (evaluate)\n\t{\n\t\tevaluateAIMode();\n\t\tif (_traceAI)\n\t\t{\n\t\t\tstd::string AIMode;\n\t\t\tswitch (_AIMode)\n\t\t\t{\n\t\t\tcase AI_PATROL:\n\t\t\t\tAIMode = \"Patrol\";\n\t\t\t\tbreak;\n\t\t\tcase AI_AMBUSH:\n\t\t\t\tAIMode = \"Ambush\";\n\t\t\t\tbreak;\n\t\t\tcase AI_COMBAT:\n\t\t\t\tAIMode = \"Combat\";\n\t\t\t\tbreak;\n\t\t\tcase AI_ESCAPE:\n\t\t\t\tAIMode = \"Escape\";\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tLog(LOG_INFO) << \"Re-Evaluated, now using \" << AIMode << \" behaviour\";\n\t\t}\n\t}\n\n\t_reserve = BA_NONE;\n\n\tswitch (_AIMode)\n\t{\n\tcase AI_ESCAPE:\n\t\t_unit->setCharging(0);\n\t\taction->type = _escapeAction.type;\n\t\taction->target = _escapeAction.target;\n\t\t// end this unit's turn.\n\t\taction->finalAction = true;\n\t\t// ignore new targets.\n\t\taction->desperate = true;\n\t\t// if armor allow runing then run way from there.\n\t\taction->run = _escapeAction.run;\n\t\t// spin 180 at the end of your route.\n\t\t_unit->setHiding(true);\n\t\tbreak;\n\tcase AI_PATROL:\n\t\t_unit->setCharging(0);\n\t\tif (action->weapon && action->weapon->getRules()->getBattleType() == BT_FIREARM)\n\t\t{\n\t\t\tswitch (_unit->getAggression())\n\t\t\t{\n\t\t\tcase 0:\n\t\t\t\t_reserve = BA_AIMEDSHOT;\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\t\t_reserve = BA_AUTOSHOT;\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\t_reserve = BA_SNAPSHOT;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\taction->type = _patrolAction.type;\n\t\taction->target = _patrolAction.target;\n\t\tbreak;\n\tcase AI_COMBAT:\n\t\taction->type = _attackAction.type;\n\t\taction->target = _attackAction.target;\n\t\t// this may have changed to a grenade.\n\t\taction->weapon = _attackAction.weapon;\n\t\tif (action->weapon && action->type == BA_THROW && action->weapon->getRules()->isGrenadeOrProxy())\n\t\t{\n\t\t\t_unit->spendCost(_unit->getActionTUs(BA_PRIME, action->weapon));\n\t\t\t_unit->spendTimeUnits(4);\n\t\t}\n\t\t// if this is a firepoint action, set our facing.\n\t\taction->finalFacing = _attackAction.finalFacing;\n\t\taction->updateTU();\n\t\t// if this is a \"find fire point\" action, don't increment the AI counter.\n\t\tif (action->type == BA_WALK && _rifle && _unit->getArmor()->allowsMoving()\n\t\t\t// so long as we can take a shot afterwards.\n\t\t\t&& BattleActionCost(BA_SNAPSHOT, _unit, action->weapon).haveTU())\n\t\t{\n\t\t\taction->number -= 1;\n\t\t}\n\t\telse if (action->type == BA_LAUNCH)\n\t\t{\n\t\t\taction->waypoints = _attackAction.waypoints;\n\t\t}\n\t\telse if (action->type == BA_AIMEDSHOT || action->type == BA_AUTOSHOT)\n\t\t{\n\t\t\taction->kneel = _unit->getArmor()->allowsKneeling(false);\n\t\t}\n\t\tbreak;\n\tcase AI_AMBUSH:\n\t\t_unit->setCharging(0);\n\t\taction->type = _ambushAction.type;\n\t\taction->target = _ambushAction.target;\n\t\t// face where we think our target will appear.\n\t\taction->finalFacing = _ambushAction.finalFacing;\n\t\t// end this unit's turn.\n\t\taction->finalAction = true;\n\t\taction->kneel = _unit->getArmor()->allowsKneeling(false);\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n\n\tif (action->type == BA_WALK)\n\t{\n\t\t// if we're moving, we'll have to re-evaluate our escape/ambush position.\n\t\tif (action->target != _unit->getPosition())\n\t\t{\n\t\t\t_escapeTUs = 0;\n\t\t\t_ambushTUs = 0;\n\t\t}\n\t\telse\n\t\t{\n\t\t\taction->type = BA_NONE;\n\t\t}\n\t}\n}\n\n\n/*\n * sets the \"was hit\" flag to true.\n */\nvoid AIModule::setWasHitBy(BattleUnit *attacker)\n{\n\tif (attacker->getFaction() != _unit->getFaction() && !getWasHitBy(attacker->getId()))\n\t\t_wasHitBy.push_back(attacker->getId());\n}\n\n/*\n * Sets the \"unit picked up a weapon\" flag.\n */\nvoid AIModule::setWeaponPickedUp()\n{\n\t_weaponPickedUp = true;\n}\n\n/*\n * Gets whether the unit was hit.\n * @return if it was hit.\n */\nbool AIModule::getWasHitBy(int attacker) const\n{\n\treturn std::find(_wasHitBy.begin(), _wasHitBy.end(), attacker) != _wasHitBy.end();\n}\n/*\n * Sets up a patrol action.\n * this is mainly going from node to node, moving about the map.\n * handles node selection, and fills out the _patrolAction with useful data.\n */\nvoid AIModule::setupPatrol()\n{\n\t_patrolAction.clearTU();\n\tif (_toNode != 0 && _unit->getPosition() == _toNode->getPosition())\n\t{\n\t\tif (_traceAI)\n\t\t{\n\t\t\tLog(LOG_INFO) << \"Patrol destination reached!\";\n\t\t}\n\t\t// destination reached\n\t\t// head off to next patrol node\n\t\t_fromNode = _toNode;\n\t\tfreePatrolTarget();\n\t\t_toNode = 0;\n\t\t// take a peek through window before walking to the next node\n\t\tint dir = _save->getTileEngine()->faceWindow(_unit->getPosition());\n\t\tif (dir != -1 && dir != _unit->getDirection())\n\t\t{\n\t\t\t_unit->lookAt(dir);\n\t\t\twhile (_unit->getStatus() == STATUS_TURNING)\n\t\t\t{\n\t\t\t\t_unit->turn();\n\t\t\t}\n\t\t}\n\t}\n\n\tif (_fromNode == 0)\n\t{\n\t\t// assume closest node as \"from node\"\n\t\t// on same level to avoid strange things, and the node has to match unit size or it will freeze\n\t\tint closest = 1000000;\n\t\tfor (auto* node : *_save->getNodes())\n\t\t{\n\t\t\tif (node->isDummy())\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tint d = Position::distanceSq(_unit->getPosition(), node->getPosition());\n\t\t\tif (_unit->getPosition().z == node->getPosition().z\n\t\t\t\t&& d < closest\n\t\t\t\t&& (!(node->getType() & Node::TYPE_SMALL) || _unit->getArmor()->getSize() == 1))\n\t\t\t{\n\t\t\t\t_fromNode = node;\n\t\t\t\tclosest = d;\n\t\t\t}\n\t\t}\n\t}\n\tint triesLeft = 5;\n\n\twhile (_toNode == 0 && triesLeft)\n\t{\n\t\ttriesLeft--;\n\t\t// look for a new node to walk towards\n\t\tbool scout = true;\n\t\tif (_save->getMissionType() != \"STR_BASE_DEFENSE\")\n\t\t{\n\t\t\t// after turn 20 or if the morale is low, everyone moves out the UFO and scout\n\t\t\t// also anyone standing in fire should also probably move\n\t\t\tif (_save->isCheating() || !_fromNode || _fromNode->getRank() == 0 ||\n\t\t\t\t(_save->getTile(_unit->getPosition()) && _save->getTile(_unit->getPosition())->getFire()))\n\t\t\t{\n\t\t\t\tscout = true;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tscout = false;\n\t\t\t}\n\t\t}\n\n\t\t// in base defense missions, the smaller aliens walk towards target nodes - or if there, shoot objects around them\n\t\telse if (_unit->getArmor()->getSize() == 1 && _unit->getOriginalFaction() == FACTION_HOSTILE &&\n\t\t\t\t_attackAction.weapon &&\n\t\t\t\t_attackAction.weapon->getRules()->getAccuracySnap() &&\n\t\t\t\t!_attackAction.weapon->getRules()->getArcingShot() &&\n\t\t\t\t_attackAction.weapon->getAmmoForAction(BA_SNAPSHOT) &&\n\t\t\t\t!_attackAction.weapon->getAmmoForAction(BA_SNAPSHOT)->getRules()->getArcingShot() &&\n\t\t\t\t_attackAction.weapon->getAmmoForAction(BA_SNAPSHOT)->getRules()->getDamageType()->isDirect() &&\n\t\t\t\t_attackAction.weapon->getAmmoForAction(BA_SNAPSHOT)->getRules()->getDamageType()->ToTile > 0.01f)\n\t\t{\n\t\t\t// can i shoot an object?\n\t\t\tif (_fromNode->isTarget() &&\n\t\t\t\t_save->canUseWeapon(_attackAction.weapon, _unit, false, BA_SNAPSHOT) &&\n\t\t\t\t_save->getModuleMap()[_fromNode->getPosition().x / 10][_fromNode->getPosition().y / 10].second > 0)\n\t\t\t{\n\t\t\t\t// scan this room for objects to destroy\n\t\t\t\tint x = (_unit->getPosition().x/10)*10;\n\t\t\t\tint y = (_unit->getPosition().y/10)*10;\n\t\t\t\tfor (int i = x; i < x+9; i++)\n\t\t\t\tfor (int j = y; j < y+9; j++)\n\t\t\t\t{\n\t\t\t\t\tMapData *md = _save->getTile(Position(i, j, 1))->getMapData(O_OBJECT);\n\t\t\t\t\tif (md && md->isBaseModule())\n\t\t\t\t\t{\n\t\t\t\t\t\t_patrolAction.actor = _unit;\n\t\t\t\t\t\t_patrolAction.target = Position(i, j, 1);\n\t\t\t\t\t\t_patrolAction.weapon = _attackAction.weapon;\n\t\t\t\t\t\t_patrolAction.type = BA_SNAPSHOT;\n\t\t\t\t\t\t_patrolAction.updateTU();\n\t\t\t\t\t\t_foundBaseModuleToDestroy = _save->getMod()->getAIDestroyBaseFacilities();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// find closest high value target which is not already allocated\n\t\t\t\tint closest = 1000000;\n\t\t\t\tBattleUnit* nodeunit = nullptr;\n\t\t\t\tfor (auto* node : *_save->getNodes())\n\t\t\t\t{\n\t\t\t\t\tif (node->isDummy())\n\t\t\t\t\t{\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tnodeunit = _save->getTile(node->getPosition())->getUnit();\n\t\t\t\t\tif (nodeunit && nodeunit->getFaction() == _unit->getFaction())\n\t\t\t\t\t{\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (node->isTarget() && !node->isAllocated() && _save->getModuleMap()[node->getPosition().x / 10][node->getPosition().y / 10].second > 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tint d = Position::distanceSq(_unit->getPosition(), node->getPosition());\n\t\t\t\t\t\tif (!_toNode ||  (d < closest && node != _fromNode))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_toNode = node;\n\t\t\t\t\t\t\tclosest = d;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (_toNode == 0)\n\t\t{\n\t\t\t_toNode = _save->getPatrolNode(scout, _unit, _fromNode);\n\t\t\tif (_toNode == 0)\n\t\t\t{\n\t\t\t\t_toNode = _save->getPatrolNode(!scout, _unit, _fromNode);\n\t\t\t}\n\t\t}\n\n\t\tif (_toNode != 0)\n\t\t{\n\t\t\t_save->getPathfinding()->calculate(_unit, _toNode->getPosition(), BAM_NORMAL);\n\t\t\tif (_save->getPathfinding()->getStartDirection() == -1)\n\t\t\t{\n\t\t\t\t_toNode = 0;\n\t\t\t}\n\t\t\t_save->getPathfinding()->abortPath();\n\t\t}\n\t}\n\n\tif (_toNode != 0)\n\t{\n\t\t_toNode->allocateNode();\n\t\t_patrolAction.actor = _unit;\n\t\t_patrolAction.type = BA_WALK;\n\t\t_patrolAction.target = _toNode->getPosition();\n\t}\n\telse\n\t{\n\t\t_patrolAction.type = BA_RETHINK;\n\t}\n}\n\n/**\n * Try to set up an ambush action\n * The idea is to check within a 11x11 tile square for a tile which is not seen by our aggroTarget,\n * but that can be reached by him. we then intuit where we will see the target first from our covered\n * position, and set that as our final facing.\n * Fills out the _ambushAction with useful data.\n */\nvoid AIModule::setupAmbush()\n{\n\t_ambushAction.type = BA_RETHINK;\n\tint bestScore = 0;\n\t_ambushTUs = 0;\n\tstd::vector<int> path;\n\n\tif (selectClosestKnownEnemy())\n\t{\n\t\tconst int BASE_SYSTEMATIC_SUCCESS = 100;\n\t\tconst int COVER_BONUS = 25;\n\t\tconst int FAST_PASS_THRESHOLD = 80;\n\t\tPosition origin = _save->getTileEngine()->getSightOriginVoxel(_aggroTarget);\n\n\t\t// we'll use node positions for this, as it gives map makers a good degree of control over how the units will use the environment.\n\t\tfor (const auto* node : *_save->getNodes())\n\t\t{\n\t\t\tif (node->isDummy())\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tPosition pos = node->getPosition();\n\t\t\tTile *tile = _save->getTile(pos);\n\t\t\tif (tile == 0 || Position::distance2d(pos, _unit->getPosition()) > 10 || pos.z != _unit->getPosition().z || tile->getDangerous() ||\n\t\t\t\tstd::find(_reachableWithAttack.begin(), _reachableWithAttack.end(), _save->getTileIndex(pos))  == _reachableWithAttack.end())\n\t\t\t\tcontinue; // just ignore unreachable tiles\n\n\t\t\tif (_traceAI)\n\t\t\t{\n\t\t\t\t// colour all the nodes in range purple.\n\t\t\t\ttile->setPreview(10);\n\t\t\t\ttile->setMarkerColor(13);\n\t\t\t}\n\n\t\t\t// make sure we can't be seen here.\n\t\t\tPosition target;\n\t\t\tif (!_save->getTileEngine()->canTargetUnit(&origin, tile, &target, _aggroTarget, false, _unit) && !getSpottingUnits(pos))\n\t\t\t{\n\t\t\t\t_save->getPathfinding()->calculate(_unit, pos, BAM_NORMAL);\n\t\t\t\tint ambushTUs = _save->getPathfinding()->getTotalTUCost();\n\t\t\t\t// make sure we can move here\n\t\t\t\tif (_save->getPathfinding()->getStartDirection() != -1)\n\t\t\t\t{\n\t\t\t\t\tint score = BASE_SYSTEMATIC_SUCCESS;\n\t\t\t\t\tscore -= ambushTUs;\n\n\t\t\t\t\t// make sure our enemy can reach here too.\n\t\t\t\t\t_save->getPathfinding()->calculate(_aggroTarget, pos, BAM_NORMAL);\n\n\t\t\t\t\tif (_save->getPathfinding()->getStartDirection() != -1)\n\t\t\t\t\t{\n\t\t\t\t\t\t// ideally we'd like to be behind some cover, like say a window or a low wall.\n\t\t\t\t\t\tif (_save->getTileEngine()->faceWindow(pos) != -1)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tscore += COVER_BONUS;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (score > bestScore)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tpath = _save->getPathfinding()->copyPath();\n\t\t\t\t\t\t\tbestScore = score;\n\t\t\t\t\t\t\t_ambushTUs = (pos == _unit->getPosition()) ? 1 : ambushTUs;\n\t\t\t\t\t\t\t_ambushAction.target = pos;\n\t\t\t\t\t\t\tif (bestScore > FAST_PASS_THRESHOLD)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (bestScore > 0)\n\t\t{\n\t\t\t_ambushAction.type = BA_WALK;\n\t\t\t// i should really make a function for this\n\t\t\torigin = _ambushAction.target.toVoxel() +\n\t\t\t\t// 4 because -2 is eyes and 2 below that is the rifle (or at least that's my understanding)\n\t\t\t\tPosition(8,8, _unit->getHeight() + _unit->getFloatHeight() - _save->getTile(_ambushAction.target)->getTerrainLevel() - 4);\n\t\t\tPosition currentPos = _aggroTarget->getPosition();\n\t\t\t_save->getPathfinding()->setUnit(_aggroTarget);\n\t\t\tsize_t tries = path.size();\n\t\t\t// hypothetically walk the target through the path.\n\t\t\twhile (tries > 0)\n\t\t\t{\n\t\t\t\tcurrentPos = _save->getPathfinding()->getTUCost(currentPos, path.back(), _aggroTarget, 0, BAM_NORMAL).pos;\n\t\t\t\tpath.pop_back();\n\t\t\t\tTile *tile = _save->getTile(currentPos);\n\t\t\t\tPosition target;\n\t\t\t\t// do a virtual fire calculation\n\t\t\t\tif (_save->getTileEngine()->canTargetUnit(&origin, tile, &target, _unit, false, _aggroTarget))\n\t\t\t\t{\n\t\t\t\t\t// if we can virtually fire at the hypothetical target, we know which way to face.\n\t\t\t\t\t_ambushAction.finalFacing = _save->getTileEngine()->getDirectionTo(_ambushAction.target, currentPos);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t--tries;\n\t\t\t}\n\t\t\tif (_traceAI)\n\t\t\t{\n\t\t\t\tLog(LOG_INFO) << \"Ambush estimation will move to \" << _ambushAction.target;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t}\n\tif (_traceAI)\n\t{\n\t\tLog(LOG_INFO) << \"Ambush estimation failed\";\n\t}\n}\n\n/**\n * Try to set up a combat action\n * This will either be a psionic, grenade, or weapon attack,\n * or potentially just moving to get a line of sight to a target.\n * Fills out the _attackAction with useful data.\n */\nvoid AIModule::setupAttack()\n{\n\t_attackAction.type = BA_RETHINK;\n\t_psiAction.type = BA_NONE;\n\n\tbool sniperAttack = false;\n\n\t// if enemies are known to us but not necessarily visible, we can attack them with a blaster launcher or psi or a sniper attack.\n\tif (_knownEnemies)\n\t{\n\t\tif (psiAction())\n\t\t{\n\t\t\t// at this point we can save some time with other calculations - the unit WILL make a psionic attack this turn.\n\t\t\treturn;\n\t\t}\n\t\tif (_blaster)\n\t\t{\n\t\t\twayPointAction();\n\t\t}\n\t\telse if (_unit->getUnitRules()) // xcom soldiers (under mind control) lack unit rules!\n\t\t{\n\t\t\t// don't always act on spotter information unless modder says so\n\t\t\tif (RNG::percent(_unit->getUnitRules()->getSniperPercentage()))\n\t\t\t{\n\t\t\t\tsniperAttack = sniperAction();\n\t\t\t}\n\t\t}\n\t}\n\n\t// if we CAN see someone, that makes them a viable target for \"regular\" attacks.\n\t// This is skipped if sniperAction has already chosen an attack action\n\tif (!sniperAttack && selectNearestTarget())\n\t{\n\t\t// if we have both types of weapon, make a determination on which to use.\n\t\tif (_melee && _rifle)\n\t\t{\n\t\t\tselectMeleeOrRanged();\n\t\t}\n\t\tif (_grenade)\n\t\t{\n\t\t\tgrenadeAction();\n\t\t}\n\t\tif (_melee)\n\t\t{\n\t\t\tmeleeAction();\n\t\t}\n\t\tif (_rifle)\n\t\t{\n\t\t\tprojectileAction();\n\t\t}\n\t}\n\n\tif (_attackAction.type != BA_RETHINK)\n\t{\n\t\tif (_traceAI)\n\t\t{\n\t\t\tif (_attackAction.type != BA_WALK)\n\t\t\t{\n\t\t\t\tLog(LOG_INFO) << \"Attack estimation desires to shoot at \" << _attackAction.target;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tLog(LOG_INFO) << \"Attack estimation desires to move to \" << _attackAction.target;\n\t\t\t}\n\t\t}\n\t\treturn;\n\t}\n\telse if (_spottingEnemies || _unit->getAggression() < RNG::generate(0, 3))\n\t{\n\t\t// if enemies can see us, or if we're feeling lucky, we can try to spot the enemy.\n\t\tif (findFirePoint())\n\t\t{\n\t\t\tif (_traceAI)\n\t\t\t{\n\t\t\t\tLog(LOG_INFO) << \"Attack estimation desires to move to \" << _attackAction.target;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t}\n\tif (_traceAI)\n\t{\n\t\tLog(LOG_INFO) << \"Attack estimation failed\";\n\t}\n}\n\n/**\n * Attempts to find cover, and move toward it.\n * The idea is to check within a 11x11 tile square for a tile which is not seen by our aggroTarget.\n * If there is no such tile, we run away from the target.\n * Fills out the _escapeAction with useful data.\n */\nvoid AIModule::setupEscape()\n{\n\tint unitsSpottingMe = getSpottingUnits(_unit->getPosition());\n\tint currentTilePreference = 15;\n\tint tries = -1;\n\tbool coverFound = false;\n\tselectNearestTarget();\n\t_escapeTUs = 0;\n\n\tint dist = _aggroTarget ? Position::distance2d(_unit->getPosition(), _aggroTarget->getPosition()) : 0;\n\n\tint bestTileScore = -100000;\n\tint score = -100000;\n\tPosition bestTile(0, 0, 0);\n\tbool run = false;\n\n\tTile *tile = 0;\n\n\t// weights of various factors in choosing a tile to which to withdraw\n\tconst int EXPOSURE_PENALTY = 10;\n\tconst int FIRE_PENALTY = 40;\n\tconst int BASE_SYSTEMATIC_SUCCESS = 100;\n\tconst int BASE_DESPERATE_SUCCESS = 110;\n\tconst int FAST_PASS_THRESHOLD = 100; // a score that's good enough to quit the while loop early; it's subjective, hand-tuned and may need tweaking\n\n\tstd::vector<Position> randomTileSearch = _save->getTileSearch();\n\tRNG::shuffle(randomTileSearch);\n\n\twhile (tries < 150 && !coverFound)\n\t{\n\t\t_escapeAction.target = _unit->getPosition(); // start looking in a direction away from the enemy\n\t\t_escapeAction.run = _unit->getArmor()->allowsRunning(false) && (tries & 1); // every odd try, i.e. roughly 50%\n\n\t\tif (!_save->getTile(_escapeAction.target))\n\t\t{\n\t\t\t_escapeAction.target = _unit->getPosition(); // cornered at the edge of the map perhaps?\n\t\t}\n\n\t\tscore = 0;\n\n\t\tif (tries == -1)\n\t\t{\n\t\t\t// you know, maybe we should just stay where we are and not risk reaction fire...\n\t\t\t// or maybe continue to wherever we were running to and not risk looking stupid\n\t\t\tif (_save->getTile(_unit->lastCover) != 0)\n\t\t\t{\n\t\t\t\t_escapeAction.target = _unit->lastCover;\n\t\t\t}\n\t\t}\n\t\telse if (tries < 121)\n\t\t{\n\t\t\t// looking for cover\n\t\t\t_escapeAction.target.x += randomTileSearch[tries].x;\n\t\t\t_escapeAction.target.y += randomTileSearch[tries].y;\n\t\t\tscore = BASE_SYSTEMATIC_SUCCESS;\n\t\t\tif (_escapeAction.target == _unit->getPosition())\n\t\t\t{\n\t\t\t\tif (unitsSpottingMe > 0)\n\t\t\t\t{\n\t\t\t\t\t// maybe don't stay in the same spot? move or something if there's any point to it?\n\t\t\t\t\t_escapeAction.target.x += RNG::generate(-20,20);\n\t\t\t\t\t_escapeAction.target.y += RNG::generate(-20,20);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tscore += currentTilePreference;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (tries == 121)\n\t\t\t{\n\t\t\t\tif (_traceAI)\n\t\t\t\t{\n\t\t\t\t\tLog(LOG_INFO) << \"best score after systematic search was: \" << bestTileScore;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tscore = BASE_DESPERATE_SUCCESS; // ruuuuuuun\n\t\t\t_escapeAction.target = _unit->getPosition();\n\t\t\t_escapeAction.target.x += RNG::generate(-10,10);\n\t\t\t_escapeAction.target.y += RNG::generate(-10,10);\n\t\t\t_escapeAction.target.z = _unit->getPosition().z + RNG::generate(-1,1);\n\t\t\tif (_escapeAction.target.z < 0)\n\t\t\t{\n\t\t\t\t_escapeAction.target.z = 0;\n\t\t\t}\n\t\t\telse if (_escapeAction.target.z >= _save->getMapSizeZ())\n\t\t\t{\n\t\t\t\t_escapeAction.target.z = _unit->getPosition().z;\n\t\t\t}\n\t\t}\n\n\t\ttries++;\n\n\t\t// THINK, DAMN YOU\n\t\ttile = _save->getTile(_escapeAction.target);\n\t\tint distanceFromTarget = _aggroTarget ? Position::distance2d(_aggroTarget->getPosition(), _escapeAction.target) : 0;\n\t\tif (dist >= distanceFromTarget)\n\t\t{\n\t\t\tscore -= (distanceFromTarget - dist) * 10;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tscore += (distanceFromTarget - dist) * 10;\n\t\t}\n\t\tint spotters = 0;\n\t\tif (!tile)\n\t\t{\n\t\t\tscore = -100001; // no you can't quit the battlefield by running off the map.\n\t\t}\n\t\telse\n\t\t{\n\t\t\tspotters = getSpottingUnits(_escapeAction.target);\n\t\t\tif (std::find(_reachable.begin(), _reachable.end(), _save->getTileIndex(_escapeAction.target))  == _reachable.end())\n\t\t\t\tcontinue; // just ignore unreachable tiles\n\n\t\t\tif (_spottingEnemies || spotters)\n\t\t\t{\n\t\t\t\tif (_spottingEnemies <= spotters)\n\t\t\t\t{\n\t\t\t\t\tscore -= (1 + spotters - _spottingEnemies) * EXPOSURE_PENALTY; // that's for giving away our position\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tscore += (_spottingEnemies - spotters) * EXPOSURE_PENALTY;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (tile->getFire())\n\t\t\t{\n\t\t\t\tscore -= FIRE_PENALTY;\n\t\t\t}\n\t\t\tif (tile->getDangerous())\n\t\t\t{\n\t\t\t\tscore -= BASE_SYSTEMATIC_SUCCESS;\n\t\t\t}\n\n\t\t\tif (_traceAI)\n\t\t\t{\n\t\t\t\ttile->setMarkerColor(score < 0 ? 3 : (score < FAST_PASS_THRESHOLD/2 ? 8 : (score < FAST_PASS_THRESHOLD ? 9 : 5)));\n\t\t\t\ttile->setPreview(10);\n\t\t\t\ttile->setTUMarker(score);\n\t\t\t}\n\n\t\t}\n\n\t\tif (tile && score > bestTileScore)\n\t\t{\n\t\t\t// calculate TUs to tile; we could be getting this from findReachable() somehow but that would break something for sure...\n\t\t\t_save->getPathfinding()->calculate(_unit, _escapeAction.target, _escapeAction.getMoveType());\n\t\t\tif (_escapeAction.target == _unit->getPosition() || _save->getPathfinding()->getStartDirection() != -1)\n\t\t\t{\n\t\t\t\tbestTileScore = score;\n\t\t\t\tbestTile = _escapeAction.target;\n\t\t\t\trun = _escapeAction.run;\n\t\t\t\t_escapeTUs = _save->getPathfinding()->getTotalTUCost();\n\t\t\t\tif (_escapeAction.target == _unit->getPosition())\n\t\t\t\t{\n\t\t\t\t\t_escapeTUs = 1;\n\t\t\t\t}\n\t\t\t\tif (_traceAI)\n\t\t\t\t{\n\t\t\t\t\ttile->setMarkerColor(score < 0 ? 7 : (score < FAST_PASS_THRESHOLD/2 ? 10 : (score < FAST_PASS_THRESHOLD ? 4 : 5)));\n\t\t\t\t\ttile->setPreview(10);\n\t\t\t\t\ttile->setTUMarker(score);\n\t\t\t\t}\n\t\t\t}\n\t\t\t_save->getPathfinding()->abortPath();\n\t\t\tif (bestTileScore > FAST_PASS_THRESHOLD) coverFound = true; // good enough, gogogo\n\t\t}\n\t}\n\t_escapeAction.target = bestTile;\n\t_escapeAction.run = run;\n\tif (_traceAI)\n\t{\n\t\t_save->getTile(_escapeAction.target)->setMarkerColor(13);\n\t}\n\n\tif (bestTileScore <= -100000)\n\t{\n\t\tif (_traceAI)\n\t\t{\n\t\t\tLog(LOG_INFO) << \"Escape estimation failed.\";\n\t\t}\n\t\t_escapeAction.type = BA_RETHINK; // do something, just don't look dumbstruck :P\n\t\treturn;\n\t}\n\telse\n\t{\n\t\tif (_traceAI)\n\t\t{\n\t\t\tLog(LOG_INFO) << \"Escape estimation completed after \" << tries << \" tries, \" << Position::distance2d(_unit->getPosition(), bestTile) << \" squares or so away.\";\n\t\t}\n\t\t_escapeAction.type = BA_WALK;\n\t}\n}\n\n/**\n * Counts how many targets, both xcom and civilian are known to this unit\n * @return how many targets are known to us.\n */\nint AIModule::countKnownTargets() const\n{\n\tint knownEnemies = 0;\n\n\tif (_unit->getFaction() == FACTION_HOSTILE)\n\t{\n\t\tfor (auto* bu : *_save->getUnits())\n\t\t{\n\t\t\tif (validTarget(bu, true, true))\n\t\t\t{\n\t\t\t\t++knownEnemies;\n\t\t\t}\n\t\t}\n\t}\n\treturn knownEnemies;\n}\n\n/*\n * counts how many enemies (xcom only) are spotting any given position.\n * @param pos the Position to check for spotters.\n * @return spotters.\n */\nint AIModule::getSpottingUnits(const Position& pos) const\n{\n\t// if we don't actually occupy the position being checked, we need to do a virtual LOF check.\n\tbool checking = pos != _unit->getPosition();\n\tint tally = 0;\n\tfor (auto* bu : *_save->getUnits())\n\t{\n\t\tif (validTarget(bu, false, false))\n\t\t{\n\t\t\tint dist = Position::distance2d(pos, bu->getPosition());\n\t\t\tif (dist > 20) continue;\n\t\t\tPosition originVoxel = _save->getTileEngine()->getSightOriginVoxel(bu);\n\t\t\toriginVoxel.z -= 2;\n\t\t\tPosition targetVoxel;\n\t\t\tif (checking)\n\t\t\t{\n\t\t\t\tif (_save->getTileEngine()->canTargetUnit(&originVoxel, _save->getTile(pos), &targetVoxel, bu, false, _unit))\n\t\t\t\t{\n\t\t\t\t\ttally++;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (_save->getTileEngine()->canTargetUnit(&originVoxel, _save->getTile(pos), &targetVoxel, bu, false))\n\t\t\t\t{\n\t\t\t\t\ttally++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn tally;\n}\n\n/**\n * Selects the nearest known living target we can see/reach and returns the number of visible enemies.\n * This function includes civilians as viable targets.\n * @return viable targets.\n */\nint AIModule::selectNearestTarget()\n{\n\tint tally = 0;\n\t_closestDist= 100;\n\t_aggroTarget = 0;\n\tPosition target;\n\tfor (auto* bu : *_save->getUnits())\n\t{\n\t\tif (validTarget(bu, true, true) &&\n\t\t\t_save->getTileEngine()->visible(_unit, bu->getTile()))\n\t\t{\n\t\t\ttally++;\n\t\t\tint dist = Position::distance2d(_unit->getPosition(), bu->getPosition());\n\t\t\tif (dist < _closestDist)\n\t\t\t{\n\t\t\t\tbool valid = false;\n\t\t\t\tif (_rifle || !_melee)\n\t\t\t\t{\n\t\t\t\t\tBattleAction action;\n\t\t\t\t\taction.actor = _unit;\n\t\t\t\t\taction.weapon = _attackAction.weapon;\n\t\t\t\t\taction.target = bu->getPosition();\n\t\t\t\t\tPosition origin = _save->getTileEngine()->getOriginVoxel(action, 0);\n\t\t\t\t\tvalid = _save->getTileEngine()->canTargetUnit(&origin, bu->getTile(), &target, _unit, false);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif (selectPointNearTarget(bu, _unit->getTimeUnits()))\n\t\t\t\t\t{\n\t\t\t\t\t\tint dir = _save->getTileEngine()->getDirectionTo(_attackAction.target, bu->getPosition());\n\t\t\t\t\t\tvalid = _save->getTileEngine()->validMeleeRange(_attackAction.target, dir, _unit, bu, 0);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (valid)\n\t\t\t\t{\n\t\t\t\t\t_closestDist = dist;\n\t\t\t\t\t_aggroTarget = bu;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif (_aggroTarget)\n\t{\n\t\treturn tally;\n\t}\n\n\treturn 0;\n}\n\n/**\n * Selects the nearest known living target we can see/reach and returns the number of visible enemies.\n * This function includes civilians as viable targets.\n * Note: Differs from selectNearestTarget() in calling selectPointNearTargetLeeroy().\n * @return viable targets.\n */\nint AIModule::selectNearestTargetLeeroy(bool canRun)\n{\n\tint tally = 0;\n\t_closestDist = 100;\n\t_aggroTarget = 0;\n\tfor (auto* bu : *_save->getUnits())\n\t{\n\t\tif (validTarget(bu, true, true) &&\n\t\t\t_save->getTileEngine()->visible(_unit, bu->getTile()))\n\t\t{\n\t\t\ttally++;\n\t\t\tint dist = Position::distance2d(_unit->getPosition(), bu->getPosition());\n\t\t\tif (dist < _closestDist)\n\t\t\t{\n\t\t\t\tbool valid = false;\n\t\t\t\tif (selectPointNearTargetLeeroy(bu, canRun))\n\t\t\t\t{\n\t\t\t\t\tint dir = _save->getTileEngine()->getDirectionTo(_attackAction.target, bu->getPosition());\n\t\t\t\t\tvalid = _save->getTileEngine()->validMeleeRange(_attackAction.target, dir, _unit, bu, 0);\n\t\t\t\t}\n\t\t\t\tif (valid)\n\t\t\t\t{\n\t\t\t\t\t_closestDist = dist;\n\t\t\t\t\t_aggroTarget = bu;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif (_aggroTarget)\n\t{\n\t\treturn tally;\n\t}\n\n\treturn 0;\n}\n\n/**\n * Selects the nearest known living Xcom unit.\n * used for ambush calculations\n * @return if we found one.\n */\nbool AIModule::selectClosestKnownEnemy()\n{\n\t_aggroTarget = 0;\n\tint minDist = 255;\n\tfor (auto* bu : *_save->getUnits())\n\t{\n\t\tif (validTarget(bu, true, false))\n\t\t{\n\t\t\tint dist = Position::distance2d(bu->getPosition(), _unit->getPosition());\n\t\t\tif (dist < minDist)\n\t\t\t{\n\t\t\t\tminDist = dist;\n\t\t\t\t_aggroTarget = bu;\n\t\t\t}\n\t\t}\n\t}\n\treturn _aggroTarget != 0;\n}\n\n/**\n * Selects a random known living Xcom or civilian unit.\n * @return if we found one.\n */\nbool AIModule::selectRandomTarget()\n{\n\tint farthest = -100;\n\t_aggroTarget = 0;\n\n\tfor (auto* bu : *_save->getUnits())\n\t{\n\t\tif (validTarget(bu, true, true))\n\t\t{\n\t\t\tint dist = RNG::generate(0,20) - Position::distance2d(_unit->getPosition(), bu->getPosition());\n\t\t\tif (dist > farthest)\n\t\t\t{\n\t\t\t\tfarthest = dist;\n\t\t\t\t_aggroTarget = bu;\n\t\t\t}\n\t\t}\n\t}\n\treturn _aggroTarget != 0;\n}\n\n/**\n * Selects a point near enough to our target to perform a melee attack.\n * @param target Pointer to a target.\n * @param maxTUs Maximum time units the path to the target can cost.\n * @return True if a point was found.\n */\nbool AIModule::selectPointNearTarget(BattleUnit *target, int maxTUs)\n{\n\tint size = _unit->getArmor()->getSize();\n\tint sizeTarget = target->getArmor()->getSize();\n\tint dirTarget = target->getDirection();\n\tfloat dodgeChanceDiff = target->getArmor()->getMeleeDodge(target) * target->getArmor()->getMeleeDodgeBackPenalty() * _attackAction.diff / 160.0f;\n\tbool returnValue = false;\n\tint distance = 1000;\n\tfor (int z = -1; z <= 1; ++z)\n\t{\n\t\tfor (int x = -size; x <= sizeTarget; ++x)\n\t\t{\n\t\t\tfor (int y = -size; y <= sizeTarget; ++y)\n\t\t\t{\n\t\t\t\tif (x || y) // skip the unit itself\n\t\t\t\t{\n\t\t\t\t\tPosition checkPath = target->getPosition() + Position (x, y, z);\n\t\t\t\t\tif (_save->getTile(checkPath) == 0 || std::find(_reachable.begin(), _reachable.end(), _save->getTileIndex(checkPath))  == _reachable.end())\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\tint dir = _save->getTileEngine()->getDirectionTo(checkPath, target->getPosition());\n\t\t\t\t\tbool valid = _save->getTileEngine()->validMeleeRange(checkPath, dir, _unit, target, 0);\n\t\t\t\t\tbool fitHere = _save->setUnitPosition(_unit, checkPath, true);\n\n\t\t\t\t\tif (valid && fitHere && !_save->getTile(checkPath)->getDangerous())\n\t\t\t\t\t{\n\t\t\t\t\t\t_save->getPathfinding()->calculate(_unit, checkPath, BAM_NORMAL, 0, maxTUs);\n\n\t\t\t\t\t\t//for 100% dodge diff and on 4th difficulty it will allow aliens to move 10 squares around to made attack from behind.\n\t\t\t\t\t\tint distanceCurrent = _save->getPathfinding()->getPath().size() - dodgeChanceDiff * _save->getTileEngine()->getArcDirection(dir - 4, dirTarget);\n\t\t\t\t\t\tif (_save->getPathfinding()->getStartDirection() != -1 && distanceCurrent < distance)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_attackAction.target = checkPath;\n\t\t\t\t\t\t\treturnValue = true;\n\t\t\t\t\t\t\tdistance = distanceCurrent;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t_save->getPathfinding()->abortPath();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn returnValue;\n}\n\n/**\n * Selects a point near enough to our target to perform a melee attack.\n * Note: Differs from selectPointNearTarget() in that it doesn't consider:\n *  - remaining TUs (charge even if not enough TUs to attack)\n *  - dangerous tiles (grenades? pfff!)\n *  - melee dodge (not intelligent enough to attack from behind)\n * @param target Pointer to a target.\n * @return True if a point was found.\n */\nbool AIModule::selectPointNearTargetLeeroy(BattleUnit *target, bool canRun)\n{\n\tint size = _unit->getArmor()->getSize();\n\tint targetsize = target->getArmor()->getSize();\n\tbool returnValue = false;\n\tunsigned int distance = 1000;\n\tfor (int z = -1; z <= 1; ++z)\n\t{\n\t\tfor (int x = -size; x <= targetsize; ++x)\n\t\t{\n\t\t\tfor (int y = -size; y <= targetsize; ++y)\n\t\t\t{\n\t\t\t\tif (x || y) // skip the unit itself\n\t\t\t\t{\n\t\t\t\t\tPosition checkPath = target->getPosition() + Position(x, y, z);\n\t\t\t\t\tif (_save->getTile(checkPath) == 0)\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\tint dir = _save->getTileEngine()->getDirectionTo(checkPath, target->getPosition());\n\t\t\t\t\tbool valid = _save->getTileEngine()->validMeleeRange(checkPath, dir, _unit, target, 0);\n\t\t\t\t\tbool fitHere = _save->setUnitPosition(_unit, checkPath, true);\n\n\t\t\t\t\tif (valid && fitHere)\n\t\t\t\t\t{\n\t\t\t\t\t\t_save->getPathfinding()->calculate(_unit, checkPath, canRun ? BAM_RUN : BAM_NORMAL, 0, 100000); // disregard unit's TUs.\n\t\t\t\t\t\tif (_save->getPathfinding()->getStartDirection() != -1 && _save->getPathfinding()->getPath().size() < distance)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_attackAction.target = checkPath;\n\t\t\t\t\t\t\treturnValue = true;\n\t\t\t\t\t\t\tdistance = _save->getPathfinding()->getPath().size();\n\t\t\t\t\t\t}\n\t\t\t\t\t\t_save->getPathfinding()->abortPath();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn returnValue;\n}\n\n/**\n * Selects a target from a list of units seen by spotter units for out-of-LOS actions and populates _attackAction with the relevant data\n * @return True if we have a target selected\n */\nbool AIModule::selectSpottedUnitForSniper()\n{\n\t_aggroTarget = 0;\n\n\t// Create a list of spotted targets and the type of attack we'd like to use on each\n\tstd::vector<std::pair<BattleUnit*, BattleAction>> spottedTargets;\n\n\t// Get the TU costs for each available attack type\n\tBattleActionCost costAuto(BA_AUTOSHOT, _attackAction.actor, _attackAction.weapon);\n\tBattleActionCost costSnap(BA_SNAPSHOT, _attackAction.actor, _attackAction.weapon);\n\tBattleActionCost costAimed(BA_AIMEDSHOT, _attackAction.actor, _attackAction.weapon);\n\n\tBattleActionCost costThrow;\n\t// Only want to check throwing if we have a grenade, the default constructor (line above) conveniently returns false from haveTU()\n\tif (_grenade)\n\t{\n\t\t// We know we have a grenade, now we need to know if we have the TUs to throw it\n\t\tcostThrow.type = BA_THROW;\n\t\tcostThrow.actor = _attackAction.actor;\n\t\tcostThrow.weapon = _unit->getGrenadeFromBelt(_save);\n\t\tcostThrow.updateTU();\n\t\tcostThrow.Time += 4; // Vanilla TUs for AI picking up grenade from belt\n\t\tcostThrow += _attackAction.actor->getActionTUs(BA_PRIME, costThrow.weapon);\n\t}\n\n\tfor (auto* bu : *_save->getUnits())\n\t{\n\t\tif (validTarget(bu, true, true) && bu->getTurnsLeftSpottedForSnipersByFaction(_unit->getFaction()))\n\t\t{\n\t\t\t// Determine which firing mode to use based on how many hits we expect per turn and the unit's intelligence/aggression\n\t\t\t_aggroTarget = bu;\n\t\t\t_attackAction.type = BA_RETHINK;\n\t\t\t_attackAction.target = bu->getPosition();\n\t\t\textendedFireModeChoice(costAuto, costSnap, costAimed, costThrow, true);\n\n\t\t\tBattleAction chosenAction = _attackAction;\n\t\t\tif (chosenAction.type == BA_THROW)\n\t\t\t\tchosenAction.weapon = costThrow.weapon;\n\n\t\t\tif (_attackAction.type != BA_RETHINK)\n\t\t\t{\n\t\t\t\tstd::pair<BattleUnit*, BattleAction> spottedTarget;\n\t\t\t\tspottedTarget = std::make_pair(bu, chosenAction);\n\t\t\t\tspottedTargets.push_back(spottedTarget);\n\t\t\t}\n\t\t}\n\t}\n\n\tint numberOfTargets = static_cast<int>(spottedTargets.size());\n\n\tif (numberOfTargets) // Now that we have a list of valid targets, pick one and return.\n\t{\n\t\tint pick = RNG::generate(0, numberOfTargets - 1);\n\t\t_aggroTarget = spottedTargets.at(pick).first;\n\t\t_attackAction.target = _aggroTarget->getPosition();\n\t\t_attackAction.type = spottedTargets.at(pick).second.type;\n\t\t_attackAction.weapon = spottedTargets.at(pick).second.weapon;\n\t}\n\telse // We didn't find a suitable target\n\t{\n\t\t// Make sure we reset anything we might have changed while testing for targets\n\t\t_aggroTarget = 0;\n\t\t_attackAction.type = BA_RETHINK;\n\t\t_attackAction.weapon = _unit->getMainHandWeapon(false);\n\t}\n\n\treturn _aggroTarget != 0;\n}\n\n/**\n * Scores a firing mode for a particular target based on a accuracy / TUs ratio\n * @param action Pointer to the BattleAction determining the firing mode\n * @param target Pointer to the BattleUnit we're trying to target\n * @param checkLOF Set to true if you want to check for a valid line of fire\n * @return The calculated score\n */\nint AIModule::scoreFiringMode(BattleAction *action, BattleUnit *target, bool checkLOF)\n{\n\t// Sanity check first, if the passed action has no type or weapon, return 0.\n\tif (!action->type || !action->weapon)\n\t{\n\t\treturn 0;\n\t}\n\tauto* weapon = action->weapon->getRules();\n\n\t// Get base accuracy for the action\n\tint accuracy = BattleUnit::getFiringAccuracy(BattleActionAttack::GetBeforeShoot(*action), _save->getMod());\n\tint distanceSq = _unit->distance3dToUnitSq(target);\n\tint distance = (int)std::ceil(sqrt(float(distanceSq)));\n\n\t{\n\t\tint upperLimit, lowerLimit;\n\t\tint dropoff = weapon->calculateLimits(upperLimit, lowerLimit, _save->getDepth(), action->type);\n\n\t\tif (distance > upperLimit)\n\t\t{\n\t\t\taccuracy -= (distance - upperLimit) * dropoff;\n\t\t}\n\t\telse if (distance < lowerLimit)\n\t\t{\n\t\t\taccuracy -= (lowerLimit - distance) * dropoff;\n\t\t}\n\t}\n\n\tbool outOfRange = action->type == BA_THROW\n\t\t? weapon->isOutOfThrowRange(distanceSq, _save->getDepth())\n\t\t: weapon->isOutOfRange(distanceSq);\n\n\tif (outOfRange)\n\t{\n\t\taccuracy = 0;\n\t}\n\n\tint numberOfShots = 1;\n\tif (action->type == BA_AIMEDSHOT)\n\t{\n\t\tnumberOfShots = weapon->getConfigAimed()->shots;\n\t}\n\telse if (action->type == BA_SNAPSHOT)\n\t{\n\t\tnumberOfShots = weapon->getConfigSnap()->shots;\n\t}\n\telse if (action->type == BA_AUTOSHOT)\n\t{\n\t\tnumberOfShots = weapon->getConfigAuto()->shots;\n\t}\n\n\tint tuCost = _unit->getActionTUs(action->type, action->weapon).Time;\n\t// Need to include TU cost of getting grenade from belt + priming if we're checking throwing\n\tif (action->type == BA_THROW && _grenade)\n\t{\n\t\t// FIXME: why not just use action->weapon ?\n\t\tauto* grenadeItem = _unit->getGrenadeFromBelt(_save);\n\t\ttuCost = _unit->getActionTUs(action->type, grenadeItem).Time;\n\t\ttuCost += 4;\n\t\ttuCost += _unit->getActionTUs(BA_PRIME, grenadeItem).Time;\n\t}\n\tint tuTotal = _unit->getBaseStats()->tu;\n\n\t// Return a score of zero if this firing mode doesn't exist for this weapon\n\tif (!tuCost)\n\t{\n\t\treturn 0;\n\t}\n\n\tif (checkLOF)\n\t{\n\t\tPosition origin = _save->getTileEngine()->getOriginVoxel((*action), 0);\n\t\tPosition targetPosition;\n\n\t\tif (action->weapon->getArcingShot(action->type) || action->type == BA_THROW)\n\t\t{\n\t\t\ttargetPosition = target->getPosition().toVoxel() + Position (8,8, (2 + -target->getTile()->getTerrainLevel()));\n\t\t\tif (!_save->getTileEngine()->validateThrow((*action), origin, targetPosition, _save->getDepth()))\n\t\t\t{\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (!_save->getTileEngine()->canTargetUnit(&origin, target->getTile(), &targetPosition, _unit, false, target))\n\t\t\t{\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn accuracy * numberOfShots * tuTotal / tuCost;\n}\n\n/**\n * Selects an AI mode based on a number of factors, some RNG and the results of the rest of the determinations.\n */\nvoid AIModule::evaluateAIMode()\n{\n\tif ((_unit->getCharging() && _attackAction.type != BA_RETHINK))\n\t{\n\t\t_AIMode = AI_COMBAT;\n\t\treturn;\n\t}\n\t// don't try to run away as often if we're a melee type, and really don't try to run away if we have a viable melee target, or we still have 50% or more TUs remaining.\n\tint escapeOdds = 15;\n\tif (_melee)\n\t{\n\t\tescapeOdds = 12;\n\t}\n\tif (_unit->getFaction() == FACTION_HOSTILE && (_unit->getTimeUnits() > _unit->getBaseStats()->tu / 2 || _unit->getCharging()))\n\t{\n\t\tescapeOdds = 5;\n\t}\n\tint ambushOdds = 12;\n\tint combatOdds = 20;\n\t// we're less likely to patrol if we see enemies.\n\tint patrolOdds = _visibleEnemies ? 15 : 30;\n\n\t// the enemy sees us, we should take retreat into consideration, and forget about patrolling for now.\n\tif (_spottingEnemies)\n\t{\n\t\tpatrolOdds = 0;\n\t\tif (_escapeTUs == 0)\n\t\t{\n\t\t\tsetupEscape();\n\t\t}\n\t}\n\n\t// melee/blaster units shouldn't consider ambush\n\tif (!_rifle || _ambushTUs == 0)\n\t{\n\t\tambushOdds = 0;\n\t\tif (_melee)\n\t\t{\n\t\t\tcombatOdds *= 1.3;\n\t\t}\n\t}\n\n\t// if we KNOW there are enemies around...\n\tif (_knownEnemies)\n\t{\n\t\tif (_knownEnemies == 1)\n\t\t{\n\t\t\tcombatOdds *= 1.2;\n\t\t}\n\n\t\tif (_escapeTUs == 0)\n\t\t{\n\t\t\tif (selectClosestKnownEnemy())\n\t\t\t{\n\t\t\t\tsetupEscape();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tescapeOdds = 0;\n\t\t\t}\n\t\t}\n\t}\n\telse if (_unit->getFaction() == FACTION_HOSTILE)\n\t{\n\t\tcombatOdds = 0;\n\t\tescapeOdds = 0;\n\t}\n\n\t// take our current mode into consideration\n\tswitch (_AIMode)\n\t{\n\tcase AI_PATROL:\n\t\tpatrolOdds *= 1.1;\n\t\tbreak;\n\tcase AI_AMBUSH:\n\t\tambushOdds *= 1.1;\n\t\tbreak;\n\tcase AI_COMBAT:\n\t\tcombatOdds *= 1.1;\n\t\tbreak;\n\tcase AI_ESCAPE:\n\t\tescapeOdds *= 1.1;\n\t\tbreak;\n\t}\n\n\t// take our overall health into consideration\n\tif (_unit->getHealth() < _unit->getBaseStats()->health / 3)\n\t{\n\t\tescapeOdds *= 1.7;\n\t\tcombatOdds *= 0.6;\n\t\tambushOdds *= 0.75;\n\t}\n\telse if (_unit->getHealth() < 2 * (_unit->getBaseStats()->health / 3))\n\t{\n\t\tescapeOdds *= 1.4;\n\t\tcombatOdds *= 0.8;\n\t\tambushOdds *= 0.8;\n\t}\n\telse if (_unit->getHealth() < _unit->getBaseStats()->health)\n\t{\n\t\tescapeOdds *= 1.1;\n\t}\n\n\t// take our aggression into consideration\n\tswitch (_unit->getAggression())\n\t{\n\tcase 0:\n\t\tescapeOdds *= 1.4;\n\t\tcombatOdds *= 0.7;\n\t\tbreak;\n\tcase 1:\n\t\tambushOdds *= 1.1;\n\t\tbreak;\n\tcase 2:\n\t\tcombatOdds *= 1.4;\n\t\tescapeOdds *= 0.7;\n\t\tbreak;\n\tdefault:\n\t\tcombatOdds *= Clamp(1.2 + (_unit->getAggression() / 10.0), 0.1, 2.0);\n\t\tescapeOdds *= Clamp(0.9 - (_unit->getAggression() / 10.0), 0.1, 2.0);\n\t\tbreak;\n\t}\n\n\tif (_AIMode == AI_COMBAT)\n\t{\n\t\tambushOdds *= 1.5;\n\t}\n\n\t// factor in the spotters.\n\tif (_spottingEnemies)\n\t{\n\t\tescapeOdds = 10 * escapeOdds * (_spottingEnemies + 10) / 100;\n\t\tcombatOdds = 5 * combatOdds * (_spottingEnemies + 20) / 100;\n\t}\n\telse\n\t{\n\t\tescapeOdds /= 2;\n\t}\n\n\t// factor in visible enemies.\n\tif (_visibleEnemies)\n\t{\n\t\tcombatOdds = 10 * combatOdds * (_visibleEnemies + 10) /100;\n\t\tif (_closestDist < 5)\n\t\t{\n\t\t\tambushOdds = 0;\n\t\t}\n\t}\n\t// make sure we have an ambush lined up, or don't even consider it.\n\tif (_ambushTUs)\n\t{\n\t\tambushOdds *= 1.7;\n\t}\n\telse\n\t{\n\t\tambushOdds = 0;\n\t}\n\n\t// factor in mission type\n\tif (_save->getMissionType() == \"STR_BASE_DEFENSE\")\n\t{\n\t\tescapeOdds *= 0.75;\n\t\tambushOdds *= 0.6;\n\t}\n\n\t// no weapons, not psychic? don't pick combat or ambush\n\tif (!_melee && !_rifle && !_blaster && !_grenade && _unit->getBaseStats()->psiSkill == 0)\n\t{\n\t\tcombatOdds = 0;\n\t\tambushOdds = 0;\n\t}\n\t// generate a random number to represent our decision.\n\tint decision = RNG::generate(1, std::max(1, patrolOdds + ambushOdds + escapeOdds + combatOdds));\n\n\tif (decision > escapeOdds)\n\t{\n\t\tif (decision > escapeOdds + ambushOdds)\n\t\t{\n\t\t\tif (decision > escapeOdds + ambushOdds + combatOdds)\n\t\t\t{\n\t\t\t\t_AIMode = AI_PATROL;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_AIMode = AI_COMBAT;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_AIMode = AI_AMBUSH;\n\t\t}\n\t}\n\telse\n\t{\n\t\t_AIMode = AI_ESCAPE;\n\t}\n\n\t// if the aliens are cheating, or the unit is charging, enforce combat as a priority.\n\tif ((_unit->getFaction() == FACTION_HOSTILE && _save->isCheating()) || _unit->getCharging() != 0)\n\t{\n\t\t_AIMode = AI_COMBAT;\n\t}\n\n\n\t// enforce the validity of our decision, and try fallback behaviour according to priority.\n\tif (_AIMode == AI_COMBAT)\n\t{\n\t\tauto* xtile = _save->getTile(_attackAction.target);\n\t\tbool throwingGrenadeOrProxy = _attackAction.type == BA_THROW && _attackAction.weapon && _attackAction.weapon->getRules()->isGrenadeOrProxy();\n\t\tif (xtile && (xtile->getUnit() || throwingGrenadeOrProxy)) // https://openxcom.org/forum/index.php?topic=12145.0\n\t\t{\n\t\t\tif (_attackAction.type != BA_RETHINK)\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (findFirePoint())\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\telse if (selectRandomTarget() && findFirePoint())\n\t\t{\n\t\t\treturn;\n\t\t}\n\t\t_AIMode = AI_PATROL;\n\t}\n\n\tif (_AIMode == AI_PATROL)\n\t{\n\t\tif (_toNode || _foundBaseModuleToDestroy)\n\t\t{\n\t\t\treturn;\n\t\t}\n\t\t// base defense mission protocol: patrol action becomes an attack action when base modules are sighted\n\t\tif (_patrolAction.type == BA_SNAPSHOT)\n\t\t{\n\t\t\treturn;\n\t\t}\n\t\t_AIMode = AI_AMBUSH;\n\t}\n\n\tif (_AIMode == AI_AMBUSH)\n\t{\n\t\tif (_ambushTUs != 0)\n\t\t{\n\t\t\treturn;\n\t\t}\n\t\t_AIMode = AI_ESCAPE;\n\t}\n}\n\n/**\n * Find a position where we can see our target, and move there.\n * check the 11x11 grid for a position nearby where we can potentially target him.\n * @return True if a possible position was found.\n */\nbool AIModule::findFirePoint()\n{\n\tif (!selectClosestKnownEnemy())\n\t\treturn false;\n\tstd::vector<Position> randomTileSearch = _save->getTileSearch(); // copy!\n\tRNG::shuffle(randomTileSearch);\n\tPosition target;\n\tconst int BASE_SYSTEMATIC_SUCCESS = 100;\n\tconst int FAST_PASS_THRESHOLD = 125;\n\tbool waitIfOutsideWeaponRange = _unit->getGeoscapeSoldier() ? false : _unit->getUnitRules()->waitIfOutsideWeaponRange();\n\tbool extendedFireModeChoiceEnabled = _save->getMod()->getAIExtendedFireModeChoice();\n\tint bestScore = 0;\n\t_attackAction.type = BA_RETHINK;\n\tfor (const auto& randomPosition : randomTileSearch)\n\t{\n\t\tPosition pos = _unit->getPosition() + randomPosition;\n\t\tTile *tile = _save->getTile(pos);\n\t\tif (tile == 0  ||\n\t\t\tstd::find(_reachableWithAttack.begin(), _reachableWithAttack.end(), _save->getTileIndex(pos))  == _reachableWithAttack.end())\n\t\t\tcontinue;\n\t\tint score = 0;\n\t\t// i should really make a function for this\n\t\tPosition origin = pos.toVoxel() +\n\t\t\t// 4 because -2 is eyes and 2 below that is the rifle (or at least that's my understanding)\n\t\t\tPosition(8,8, _unit->getHeight() + _unit->getFloatHeight() - tile->getTerrainLevel() - 4);\n\n\t\tif (_save->getTileEngine()->canTargetUnit(&origin, _aggroTarget->getTile(), &target, _unit, false))\n\t\t{\n\t\t\t_save->getPathfinding()->calculate(_unit, pos, BAM_NORMAL);\n\t\t\t// can move here\n\t\t\tif (_save->getPathfinding()->getStartDirection() != -1)\n\t\t\t{\n\t\t\t\tscore = BASE_SYSTEMATIC_SUCCESS - getSpottingUnits(pos) * 10;\n\t\t\t\tscore += _unit->getTimeUnits() - _save->getPathfinding()->getTotalTUCost();\n\t\t\t\tif (!_aggroTarget->checkViewSector(pos))\n\t\t\t\t{\n\t\t\t\t\tscore += 10;\n\t\t\t\t}\n\n\t\t\t\t// Extended behavior: if we have a limited-range weapon, bump up the score for getting closer to the target, down for further\n\t\t\t\tif (!waitIfOutsideWeaponRange && extendedFireModeChoiceEnabled)\n\t\t\t\t{\n\t\t\t\t\tint distanceToTargetSq = _unit->distance3dToUnitSq(_aggroTarget);\n\t\t\t\t\tint distanceToTarget = (int)std::ceil(sqrt(float(distanceToTargetSq)));\n\t\t\t\t\tif (_attackAction.weapon && _attackAction.weapon->getRules()->isOutOfRange(distanceToTargetSq)) // make sure we can get the ruleset before checking the range\n\t\t\t\t\t{\n\t\t\t\t\t\tint proposedDistance = Position::distance2d(pos, _aggroTarget->getPosition());\n\t\t\t\t\t\tproposedDistance = std::max(proposedDistance, 1);\n\t\t\t\t\t\tscore = score * distanceToTarget / proposedDistance;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (score > bestScore)\n\t\t\t\t{\n\t\t\t\t\tbestScore = score;\n\t\t\t\t\t_attackAction.target = pos;\n\t\t\t\t\t_attackAction.finalFacing = _save->getTileEngine()->getDirectionTo(pos, _aggroTarget->getPosition());\n\t\t\t\t\tif (score > FAST_PASS_THRESHOLD)\n\t\t\t\t\t{\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (bestScore > 70)\n\t{\n\t\t_attackAction.type = BA_WALK;\n\t\tif (_traceAI)\n\t\t{\n\t\t\tLog(LOG_INFO) << \"Firepoint found at \" << _attackAction.target << \", with a score of: \" << bestScore;\n\t\t}\n\t\treturn true;\n\t}\n\tif (_traceAI)\n\t{\n\t\tLog(LOG_INFO) << \"Firepoint failed, best estimation was: \" << _attackAction.target << \", with a score of: \" << bestScore;\n\t}\n\n\treturn false;\n}\n\n/**\n * Decides if it worth our while to create an explosion here.\n * Return value in same range as number affected targets but not equal exactly to that value.\n * @param targetPos The target's position.\n * @param attackingUnit The attacking unit.\n * @param radius How big the explosion will be.\n * @param diff Game difficulty.\n * @param grenade Is the explosion coming from a grenade?\n * @return Value greater than zero if it is worthwhile creating an explosion in the target position. Bigger value better target.\n */\nint AIModule::explosiveEfficacy(Position targetPos, BattleUnit *attackingUnit, int radius, int diff, bool grenade) const\n{\n\tTile *targetTile = _save->getTile(targetPos);\n\n\t// don't throw grenades at flying enemies.\n\tif (grenade && targetPos.z > 0 && targetTile->hasNoFloor(_save))\n\t{\n\t\treturn false;\n\t}\n\n\tif (diff == -1)\n\t{\n\t\tdiff = _save->getBattleState()->getGame()->getSavedGame()->getDifficultyCoefficient();\n\t}\n\tint distance = Position::distance2d(attackingUnit->getPosition(), targetPos);\n\tint injurylevel = attackingUnit->getBaseStats()->health - attackingUnit->getHealth();\n\tint desperation = (100 - attackingUnit->getMorale()) / 10;\n\tint enemiesAffected = 0;\n\t// if we're below 1/3 health, let's assume things are dire, and increase desperation.\n\tif (injurylevel > (attackingUnit->getBaseStats()->health / 3) * 2)\n\t\tdesperation += 3;\n\n\tint efficacy = AIW_SCALE * desperation;\n\n\t// don't go kamikaze unless we're already doomed.\n\tif (abs(attackingUnit->getPosition().z - targetPos.z) <= Options::battleExplosionHeight && distance <= radius)\n\t{\n\t\tefficacy -= AIW_SCALE * 4;\n\t}\n\n\t// allow difficulty to have its influence\n\tefficacy += AIW_SCALE * diff/2;\n\n\t// account for the unit we're targetting\n\tBattleUnit *target = targetTile->getUnit();\n\tif (target && !targetTile->getDangerous())\n\t{\n\t\t++enemiesAffected;\n\t\tefficacy += getTargetAttackWeight(target);\n\t}\n\n\tfor (auto* bu : *_save->getUnits())\n\t{\n\t\t\t// don't grenade dead guys\n\t\tif (!bu->isOut() &&\n\t\t\t// don't count ourself twice\n\t\t\tbu != attackingUnit &&\n\t\t\t// don't count the target twice\n\t\t\tbu != target &&\n\t\t\t// don't count units that probably won't be affected cause they're out of range\n\t\t\tabs(bu->getPosition().z - targetPos.z) <= Options::battleExplosionHeight &&\n\t\t\tPosition::distance2d(bu->getPosition(), targetPos) <= radius)\n\t\t{\n\t\t\tif (bu->getTile()->getDangerous())\n\t\t\t{\n\t\t\t\t// don't count people who were already grenaded this turn\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tauto weight = getTargetAttackWeight(bu);\n\n\t\t\tif (weight == 0)\n\t\t\t{\n\t\t\t\t// AI do not know anything about this unit\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// trace a line from the grenade origin to the unit we're checking against\n\t\t\tPosition voxelPosA = Position (targetPos.toVoxel() + TileEngine::voxelTileCenter);\n\t\t\tPosition voxelPosB = Position (bu->getPosition().toVoxel() + TileEngine::voxelTileCenter);\n\t\t\tstd::vector<Position> traj;\n\t\t\tint collidesWith = _save->getTileEngine()->calculateLineVoxel(voxelPosA, voxelPosB, false, &traj, target, bu);\n\n\t\t\tif (collidesWith == V_UNIT && traj.front().toTile() == bu->getPosition())\n\t\t\t{\n\t\t\t\tif (bu->getFaction() == _targetFaction)\n\t\t\t\t{\n\t\t\t\t\t++enemiesAffected;\n\t\t\t\t}\n\n\t\t\t\tefficacy += weight;\n\t\t\t}\n\t\t}\n\t}\n\t// don't throw grenades at single targets, unless morale is in the danger zone\n\t// or we're halfway towards panicking while bleeding to death.\n\tif (grenade && desperation < 6 && enemiesAffected < 2)\n\t{\n\t\treturn 0;\n\t}\n\n\tif (enemiesAffected >= 10)\n\t{\n\t\t// Ignore loses if we can kill lot of enemies.\n\t\treturn enemiesAffected;\n\t}\n\telse if (efficacy > 0)\n\t{\n\t\t// We kill more enemies than allies. Scale back to number of targets, can round down to zero\n\t\treturn efficacy / AIW_SCALE;\n\t}\n\telse\n\t{\n\t\treturn 0;\n\t}\n}\n\n/**\n * Attempts to take a melee attack/charge an enemy we can see.\n * Melee targetting: we can see an enemy, we can move to it so we're charging blindly toward an enemy.\n */\nvoid AIModule::meleeAction()\n{\n\tBattleActionCost attackCost(BA_HIT, _unit, _unit->getUtilityWeapon(BT_MELEE));\n\tif (!attackCost.haveTU())\n\t{\n\t\t// cannot make a melee attack - consider some other behaviour, like running away, or standing motionless.\n\t\treturn;\n\t}\n\tif (_aggroTarget != 0 && !_aggroTarget->isOut())\n\t{\n\t\tif (_save->getTileEngine()->validMeleeRange(_unit, _aggroTarget, _save->getTileEngine()->getDirectionTo(_unit->getPosition(), _aggroTarget->getPosition())))\n\t\t{\n\t\t\tmeleeAttack();\n\t\t\treturn;\n\t\t}\n\t}\n\tint chargeReserve = std::min(_unit->getTimeUnits() - attackCost.Time, 2 * (_unit->getEnergy() - attackCost.Energy));\n\tint distance = (chargeReserve / 4) + 1;\n\t_aggroTarget = 0;\n\tfor (auto* bu : *_save->getUnits())\n\t{\n\t\tint newDistance = Position::distance2d(_unit->getPosition(), bu->getPosition());\n\t\tif (newDistance > 20 ||\n\t\t\t!validTarget(bu, true, true))\n\t\t\tcontinue;\n\t\t//pick closest living unit that we can move to\n\t\tif ((newDistance < distance || newDistance == 1) && !bu->isOut())\n\t\t{\n\t\t\tif (newDistance == 1 || selectPointNearTarget(bu, chargeReserve))\n\t\t\t{\n\t\t\t\t_aggroTarget = bu;\n\t\t\t\t_attackAction.type = BA_WALK;\n\t\t\t\t_unit->setCharging(_aggroTarget);\n\t\t\t\tdistance = newDistance;\n\t\t\t}\n\n\t\t}\n\t}\n\tif (_aggroTarget != 0)\n\t{\n\t\tif (_save->getTileEngine()->validMeleeRange(_unit, _aggroTarget, _save->getTileEngine()->getDirectionTo(_unit->getPosition(), _aggroTarget->getPosition())))\n\t\t{\n\t\t\tmeleeAttack();\n\t\t}\n\t}\n\tif (_traceAI && _aggroTarget) { Log(LOG_INFO) << \"AIModule::meleeAction:\" << \" [target]: \" << (_aggroTarget->getId()) << \" at: \"  << _attackAction.target; }\n\tif (_traceAI && _aggroTarget) { Log(LOG_INFO) << \"CHARGE!\"; }\n}\n\n/**\n * Attempts to take a melee attack/charge an enemy we can see.\n * Melee targetting: we can see an enemy, we can move to it so we're charging blindly toward an enemy.\n * Note: Differs from meleeAction() in calling selectPointNearTargetLeeroy() and ignoring some more checks.\n */\nvoid AIModule::meleeActionLeeroy(bool canRun)\n{\n\tif (_aggroTarget != 0 && !_aggroTarget->isOut())\n\t{\n\t\tif (_save->getTileEngine()->validMeleeRange(_unit, _aggroTarget, _save->getTileEngine()->getDirectionTo(_unit->getPosition(), _aggroTarget->getPosition())))\n\t\t{\n\t\t\tmeleeAttack();\n\t\t\treturn;\n\t\t}\n\t}\n\tint distance = 1000;\n\t_aggroTarget = 0;\n\tfor (auto* bu : *_save->getUnits())\n\t{\n\t\tint newDistance = Position::distance2d(_unit->getPosition(), bu->getPosition());\n\t\tif (!validTarget(bu, true, true))\n\t\t\tcontinue;\n\t\t//pick closest living unit\n\t\tif ((newDistance < distance || newDistance == 1) && !bu->isOut())\n\t\t{\n\t\t\tif (newDistance == 1 || selectPointNearTargetLeeroy(bu, canRun))\n\t\t\t{\n\t\t\t\t_aggroTarget = bu;\n\t\t\t\t_attackAction.type = BA_WALK;\n\t\t\t\t_attackAction.run = canRun;\n\t\t\t\t_unit->setCharging(_aggroTarget);\n\t\t\t\tdistance = newDistance;\n\t\t\t}\n\n\t\t}\n\t}\n\tif (_aggroTarget != 0)\n\t{\n\t\tif (_save->getTileEngine()->validMeleeRange(_unit, _aggroTarget, _save->getTileEngine()->getDirectionTo(_unit->getPosition(), _aggroTarget->getPosition())))\n\t\t{\n\t\t\tmeleeAttack();\n\t\t}\n\t}\n\tif (_traceAI && _aggroTarget) { Log(LOG_INFO) << \"AIModule::meleeAction:\" << \" [target]: \" << (_aggroTarget->getId()) << \" at: \" << _attackAction.target; }\n\tif (_traceAI && _aggroTarget) { Log(LOG_INFO) << \"CHARGE!\"; }\n}\n\n/**\n * Attempts to fire a waypoint projectile at an enemy we, or one of our teammates sees.\n *\n * Waypoint targeting: pick from any units currently spotted by our allies.\n */\nvoid AIModule::wayPointAction()\n{\n\tBattleActionCost attackCost(BA_LAUNCH, _unit, _attackAction.weapon);\n\tif (!attackCost.haveTU())\n\t{\n\t\t// cannot make a launcher attack - consider some other behaviour, like running away, or standing motionless.\n\t\treturn;\n\t}\n\t_aggroTarget = 0;\n\tfor (auto* bu : *_save->getUnits())\n\t{\n\t\tif (_aggroTarget != 0) break; // loop finished\n\t\tif (!validTarget(bu, true, true))\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\t\t_save->getPathfinding()->calculate(_unit, bu->getPosition(), BAM_MISSILE, bu, -1);\n\t\tBattleItem* ammo = _attackAction.weapon->getAmmoForAction(BA_LAUNCH);\n\t\tif (_save->getPathfinding()->getStartDirection() != -1 &&\n\t\t\texplosiveEfficacy(bu->getPosition(), _unit, ammo->getRules()->getExplosionRadius({ BA_LAUNCH, _unit, _attackAction.weapon, ammo }), _attackAction.diff))\n\t\t{\n\t\t\t_aggroTarget = bu;\n\t\t}\n\t\t_save->getPathfinding()->abortPath();\n\t}\n\n\tif (_aggroTarget != 0)\n\t{\n\t\t_attackAction.type = BA_LAUNCH;\n\t\t_attackAction.updateTU();\n\t\tif (!_attackAction.haveTU())\n\t\t{\n\t\t\t_attackAction.type = BA_RETHINK;\n\t\t\treturn;\n\t\t}\n\t\t_attackAction.waypoints.clear();\n\n\t\tint PathDirection;\n\t\tint CollidesWith;\n\t\tint maxWaypoints = _attackAction.weapon->getCurrentWaypoints();\n\t\tif (maxWaypoints == -1)\n\t\t{\n\t\t\tmaxWaypoints = 6 + (_attackAction.diff * 2);\n\t\t}\n\t\tPosition LastWayPoint = _unit->getPosition();\n\t\tPosition LastPosition = _unit->getPosition();\n\t\tPosition CurrentPosition = _unit->getPosition();\n\t\tPosition DirectionVector;\n\n\t\t_save->getPathfinding()->calculate(_unit, _aggroTarget->getPosition(), BAM_MISSILE, _aggroTarget, -1);\n\t\tPathDirection = _save->getPathfinding()->dequeuePath();\n\t\twhile (PathDirection != -1 && (int)_attackAction.waypoints.size() < maxWaypoints)\n\t\t{\n\t\t\tLastPosition = CurrentPosition;\n\t\t\t_save->getPathfinding()->directionToVector(PathDirection, &DirectionVector);\n\t\t\tCurrentPosition = CurrentPosition + DirectionVector;\n\t\t\tPosition voxelPosA ((CurrentPosition.x * 16)+8, (CurrentPosition.y * 16)+8, (CurrentPosition.z * 24)+16);\n\t\t\tPosition voxelPosb ((LastWayPoint.x * 16)+8, (LastWayPoint.y * 16)+8, (LastWayPoint.z * 24)+16);\n\t\t\tCollidesWith = _save->getTileEngine()->calculateLineVoxel(voxelPosA, voxelPosb, false, nullptr, _unit);\n\t\t\tif (CollidesWith > V_EMPTY && CollidesWith < V_UNIT)\n\t\t\t{\n\t\t\t\t_attackAction.waypoints.push_back(LastPosition);\n\t\t\t\tLastWayPoint = LastPosition;\n\t\t\t}\n\t\t\telse if (CollidesWith == V_UNIT)\n\t\t\t{\n\t\t\t\tBattleUnit* target = _save->getTile(CurrentPosition)->getOverlappingUnit(_save);\n\t\t\t\tif (target == _aggroTarget)\n\t\t\t\t{\n\t\t\t\t\t_attackAction.waypoints.push_back(CurrentPosition);\n\t\t\t\t\tLastWayPoint = CurrentPosition;\n\t\t\t\t}\n\t\t\t}\n\t\t\tPathDirection = _save->getPathfinding()->dequeuePath();\n\t\t}\n\t\t_attackAction.target = _attackAction.waypoints.front();\n\t\tif (LastWayPoint != _aggroTarget->getPosition())\n\t\t{\n\t\t\t_attackAction.type = BA_RETHINK;\n\t\t}\n\t}\n}\n\n/**\n * Attempts to fire at an enemy spotted for us.\n *\n */\nbool AIModule::sniperAction()\n{\n\tif (_traceAI) { Log(LOG_INFO) << \"Attempting sniper action...\"; }\n\n\tif (selectSpottedUnitForSniper())\n\t{\n\t\t_visibleEnemies = std::max(_visibleEnemies, 1); // Make sure we count at least our target as visible, otherwise we might not shoot!\n\n\t\tif (_traceAI) { Log(LOG_INFO) << \"Target for sniper found at (\" << _attackAction.target.x << \",\" << _attackAction.target.y << \",\" << _attackAction.target.z << \").\"; }\n\t\treturn true;\n\t}\n\n\tif (_traceAI) { Log(LOG_INFO) << \"No valid target found or not enough TUs for sniper action.\"; }\n\treturn false;\n}\n\n/**\n * Attempts to fire at an enemy we can see.\n *\n * Regular targeting: we can see an enemy, we have a gun, let's try to shoot.\n */\nvoid AIModule::projectileAction()\n{\n\t_attackAction.target = _aggroTarget->getPosition();\n\tauto testEffect = [&](BattleActionCost& cost)\n\t{\n\t\tif (cost.haveTU())\n\t\t{\n\t\t\tBattleActionAttack attack = BattleActionAttack::GetBeforeShoot(cost);\n\t\t\tif (attack.damage_item == nullptr)\n\t\t\t{\n\t\t\t\tcost.clearTU();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tint radius = attack.damage_item->getRules()->getExplosionRadius(attack);\n\t\t\t\tif (radius != 0 && explosiveEfficacy(_attackAction.target, _unit, radius, _attackAction.diff) == 0)\n\t\t\t\t{\n\t\t\t\t\tcost.clearTU();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\n\tint distance = Position::distance2d(_unit->getPosition(), _attackAction.target);\n\t_attackAction.type = BA_RETHINK;\n\n\tBattleActionCost costAuto(BA_AUTOSHOT, _attackAction.actor, _attackAction.weapon);\n\tBattleActionCost costSnap(BA_SNAPSHOT, _attackAction.actor, _attackAction.weapon);\n\tBattleActionCost costAimed(BA_AIMEDSHOT, _attackAction.actor, _attackAction.weapon);\n\n\ttestEffect(costAuto);\n\ttestEffect(costSnap);\n\ttestEffect(costAimed);\n\n\t// Is the unit willingly waiting outside of weapon's range (e.g. ninja camouflaged in ambush)?\n\tbool waitIfOutsideWeaponRange = _unit->getGeoscapeSoldier() ? false : _unit->getUnitRules()->waitIfOutsideWeaponRange();\n\n\t// Do we want to use the extended firing mode scoring?\n\tbool extendedFireModeChoiceEnabled = _save->getMod()->getAIExtendedFireModeChoice();\n\tif (!waitIfOutsideWeaponRange && extendedFireModeChoiceEnabled)\n\t{\n\t\t// Note: this will also check for the weapon's max range\n\t\tBattleActionCost costThrow; // Not actually checked here, just passed to extendedFireModeChoice as a necessary argument\n\t\textendedFireModeChoice(costAuto, costSnap, costAimed, costThrow, false);\n\t\treturn;\n\t}\n\n\t// Do we want to check if the weapon is in range?\n\tbool aiRespectsMaxRange = _save->getMod()->getAIRespectMaxRange();\n\tif (!waitIfOutsideWeaponRange && aiRespectsMaxRange)\n\t{\n\t\t// If we want to check and it's not in range, perhaps we should re-think shooting\n\t\tint distanceSq = _unit->distance3dToPositionSq(_attackAction.target);\n\t\tif (_attackAction.weapon->getRules()->isOutOfRange(distanceSq))\n\t\t{\n\t\t\treturn;\n\t\t}\n\t}\n\n\t// vanilla\n\tif (distance < 4)\n\t{\n\t\tif (costAuto.haveTU())\n\t\t{\n\t\t\t_attackAction.type = BA_AUTOSHOT;\n\t\t\treturn;\n\t\t}\n\t\tif (!costSnap.haveTU())\n\t\t{\n\t\t\tif (costAimed.haveTU())\n\t\t\t{\n\t\t\t\t_attackAction.type = BA_AIMEDSHOT;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\t_attackAction.type = BA_SNAPSHOT;\n\t\treturn;\n\t}\n\n\n\tif (distance > 12)\n\t{\n\t\tif (costAimed.haveTU())\n\t\t{\n\t\t\t_attackAction.type = BA_AIMEDSHOT;\n\t\t\treturn;\n\t\t}\n\t\tif (distance < 20 && costSnap.haveTU())\n\t\t{\n\t\t\t_attackAction.type = BA_SNAPSHOT;\n\t\t\treturn;\n\t\t}\n\t}\n\n\tif (costSnap.haveTU())\n\t{\n\t\t_attackAction.type = BA_SNAPSHOT;\n\t\treturn;\n\t}\n\tif (costAimed.haveTU())\n\t{\n\t\t_attackAction.type = BA_AIMEDSHOT;\n\t\treturn;\n\t}\n\tif (costAuto.haveTU())\n\t{\n\t\t_attackAction.type = BA_AUTOSHOT;\n\t}\n}\n\nvoid AIModule::extendedFireModeChoice(BattleActionCost& costAuto, BattleActionCost& costSnap, BattleActionCost& costAimed, BattleActionCost& costThrow, bool checkLOF)\n{\n\tstd::vector<BattleActionType> attackOptions = { };\n\tif (costAimed.haveTU())\n\t{\n\t\tattackOptions.push_back(BA_AIMEDSHOT);\n\t}\n\tif (costAuto.haveTU())\n\t{\n\t\tattackOptions.push_back(BA_AUTOSHOT);\n\t}\n\tif (costSnap.haveTU())\n\t{\n\t\tattackOptions.push_back(BA_SNAPSHOT);\n\t}\n\tif (costThrow.haveTU())\n\t{\n\t\tattackOptions.push_back(BA_THROW);\n\t}\n\n\tBattleActionType chosenAction = BA_RETHINK;\n\tBattleAction testAction = _attackAction;\n\tint score = 0;\n\tfor (auto& i : attackOptions)\n\t{\n\t\ttestAction.type = i;\n\t\tif (i == BA_THROW)\n\t\t{\n\t\t\tif (_grenade)\n\t\t\t{\n\t\t\t\ttestAction.weapon = _unit->getGrenadeFromBelt(_save);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\ttestAction.weapon = _attackAction.weapon;\n\t\t}\n\t\tint newScore = scoreFiringMode(&testAction, _aggroTarget, checkLOF);\n\n\t\t// Add a random factor to the firing mode score based on intelligence\n\t\t// An intelligence value of 10 will decrease this random factor to 0\n\t\t// Default values for and intelligence value of 0 will make this a 50% to 150% roll\n\t\tint intelligenceModifier = _save->getMod()->getAIFireChoiceIntelCoeff() * std::max(10 - _unit->getIntelligence(), 0);\n\t\tnewScore = newScore * (100 + RNG::generate(-intelligenceModifier, intelligenceModifier)) / 100;\n\n\t\t// More aggressive units get a modifier to the score for autoshots\n\t\t// Aggression = 0 lowers the score, aggro = 1 is no modifier, aggro > 1 bumps up the score by 5% (configurable) for each increment over 1\n\t\tif (i == BA_AUTOSHOT)\n\t\t{\n\t\t\tnewScore = newScore * (100 + (_unit->getAggression() - 1) * _save->getMod()->getAIFireChoiceAggroCoeff()) / 100;\n\t\t}\n\n\t\tif (newScore > score)\n\t\t{\n\t\t\tscore = newScore;\n\t\t\tchosenAction = i;\n\t\t}\n\n\t\tif (_traceAI)\n\t\t{\n\t\t\tLog(LOG_INFO) << \"Evaluate option \" << (int)i << \", score = \" << newScore;\n\t\t}\n\t}\n\n\t_attackAction.type = chosenAction;\n}\n\n/**\n * Evaluates whether to throw a grenade at an enemy (or group of enemies) we can see.\n */\nvoid AIModule::grenadeAction()\n{\n\t// do we have a grenade on our belt?\n\tBattleItem *grenade = _unit->getGrenadeFromBelt(_save);\n\tBattleAction action;\n\taction.weapon = grenade;\n\taction.type = BA_THROW;\n\taction.actor = _unit;\n\n\taction.updateTU();\n\taction.Time += 4; // 4TUs for picking up the grenade\n\taction += _unit->getActionTUs(BA_PRIME, grenade);\n\t// do we have enough TUs to prime and throw the grenade?\n\tif (action.haveTU())\n\t{\n\t\tint radius = grenade->getRules()->getExplosionRadius(BattleActionAttack::GetBeforeShoot(action));\n\t\tif (explosiveEfficacy(_aggroTarget->getPosition(), _unit, radius, _attackAction.diff, true))\n\t\t{\n\t\t\taction.target = _aggroTarget->getPosition();\n\t\t}\n\t\telse if (!getNodeOfBestEfficacy(&action, radius))\n\t\t{\n\t\t\treturn;\n\t\t}\n\t\tstd::vector<std::pair<Position, int>> shifts;\n\t\tif (grenade->getRules()->getBattleType() == BT_PROXIMITYGRENADE)\n\t\t{\n\t\t\t// let's try to not throw the proxy below xcom's feet, otherwise they'll just throw it straight back :)\n\t\t\tif (action.target.x < _save->getMapSizeX() - 1) shifts.push_back(std::make_pair(Position(1, 0, 0), _unit->distance3dToPositionSq(action.target + Position(1, 0, 0))));\n\t\t\tif (action.target.y < _save->getMapSizeY() - 1) shifts.push_back(std::make_pair(Position(0, 1, 0), _unit->distance3dToPositionSq(action.target + Position(0, 1, 0))));\n\t\t\tif (action.target.x > 0) shifts.push_back(std::make_pair(Position(-1, 0, 0), _unit->distance3dToPositionSq(action.target + Position(-1, 0, 0))));\n\t\t\tif (action.target.y > 0) shifts.push_back(std::make_pair(Position(0, -1, 0), _unit->distance3dToPositionSq(action.target + Position(0, -1, 0))));\n\t\t\t//RNG::shuffle(shifts);\n\t\t\tstd::sort(shifts.begin(), shifts.end(), [](auto& left, auto& right) {\n\t\t\t\treturn left.second < right.second;\n\t\t\t});\n\t\t\t// PS: if someone wants to calculate a better target spot (based on multiple enemies, RNG, day of the week or position of the stars), be my guest\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// normal grenade\n\t\t\tshifts.push_back(std::make_pair(Position(0, 0, 0), 0));\n\t\t}\n\t\tPosition originVoxel = _save->getTileEngine()->getOriginVoxel(action, 0);\n\t\tfor (auto& shift : shifts)\n\t\t{\n\t\t\tPosition targetTile = action.target + shift.first;\n\t\t\tPosition targetVoxel = targetTile.toVoxel() + Position(8,8, (2 + -_save->getTile(targetTile)->getTerrainLevel()));\n\t\t\t// are we within range?\n\t\t\tif (_save->getTileEngine()->validateThrow(action, originVoxel, targetVoxel, _save->getDepth()))\n\t\t\t{\n\t\t\t\t_attackAction.weapon = grenade;\n\t\t\t\t_attackAction.target = targetTile;\n\t\t\t\t_attackAction.type = BA_THROW;\n\t\t\t\t_rifle = false;\n\t\t\t\t_melee = false;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Attempts a psionic attack on an enemy we \"know of\".\n *\n * Psionic targetting: pick from any of the \"exposed\" units.\n * Exposed means they have been previously spotted, and are therefore \"known\" to the AI,\n * regardless of whether we can see them or not, because we're psychic.\n * @return True if a psionic attack is performed.\n */\nbool AIModule::psiAction()\n{\n\tBattleItem *item = _unit->getUtilityWeapon(BT_PSIAMP);\n\tif (!item)\n\t{\n\t\treturn false;\n\t}\n\n\tconst int costLength = 3;\n\tBattleActionCost cost[costLength] =\n\t{\n\t\tBattleActionCost(BA_USE, _unit, item),\n\t\tBattleActionCost(BA_PANIC, _unit, item),\n\t\tBattleActionCost(BA_MINDCONTROL, _unit, item),\n\t};\n\tbool have = false;\n\tfor (int j = 0; j < costLength; ++j)\n\t{\n\t\tif (cost[j].Time > 0)\n\t\t{\n\t\t\tcost[j].Time += _escapeTUs;\n\t\t\tcost[j].Energy += _escapeTUs / 2;\n\t\t\thave |= cost[j].haveTU();\n\t\t}\n\t}\n\tbool LOSRequired = item->getRules()->isLOSRequired();\n\n\t_aggroTarget = 0;\n\t\t// don't let mind controlled soldiers mind control other soldiers.\n\tif (_unit->getOriginalFaction() == _unit->getFaction()\n\t\t// and we have the required 25 TUs and can still make it to cover\n\t\t&& have\n\t\t// and we didn't already do a psi action this round\n\t\t&& !_didPsi)\n\t{\n\t\tint weightToAttack = 0;\n\t\tBattleActionType typeToAttack = BA_NONE;\n\n\t\tfor (auto* bu : *_save->getUnits())\n\t\t{\n\t\t\t// don't target tanks\n\t\t\tif (bu->getArmor()->getSize() == 1 &&\n\t\t\t\tvalidTarget(bu, true, false) &&\n\t\t\t\t// they must be player units\n\t\t\t\tbu->getOriginalFaction() != _unit->getFaction() &&\n\t\t\t\t(!LOSRequired ||\n\t\t\t\tstd::find(_unit->getVisibleUnits()->begin(), _unit->getVisibleUnits()->end(), bu) != _unit->getVisibleUnits()->end()))\n\t\t\t{\n\t\t\t\tBattleUnit *victim = bu;\n\t\t\t\tif (item->getRules()->isOutOfRange(_unit->distance3dToUnitSq(victim)))\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tfor (int j = 0; j < costLength; ++j)\n\t\t\t\t{\n\t\t\t\t\t// can't use this attack.\n\t\t\t\t\tif (!cost[j].haveTU())\n\t\t\t\t\t{\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tint weightToAttackMe = _save->getTileEngine()->psiAttackCalculate({ cost[j].type, _unit, item, item }, victim);\n\n\t\t\t\t\t// low chance we hit this target.\n\t\t\t\t\tif (weightToAttackMe < 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\t// different bonus per attack.\n\t\t\t\t\tif (cost[j].type == BA_MINDCONTROL)\n\t\t\t\t\t{\n\t\t\t\t\t\t// target cannot be mind controlled\n\t\t\t\t\t\tif (victim->getUnitRules() && !victim->getUnitRules()->canBeMindControlled()) continue;\n\n\t\t\t\t\t\tint controlOdds = 40;\n\t\t\t\t\t\tint morale = victim->getMorale();\n\t\t\t\t\t\tint bravery = victim->reduceByBravery(10);\n\t\t\t\t\t\tif (bravery > 6)\n\t\t\t\t\t\t\tcontrolOdds -= 15;\n\t\t\t\t\t\tif (bravery < 4)\n\t\t\t\t\t\t\tcontrolOdds += 15;\n\t\t\t\t\t\tif (morale >= 40)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (morale - 10 * bravery < 50)\n\t\t\t\t\t\t\t\tcontrolOdds -= 15;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcontrolOdds += 15;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!morale)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcontrolOdds = 100;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (RNG::percent(controlOdds))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tweightToAttackMe += 60;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse if (cost[j].type == BA_USE)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (RNG::percent(80 - _attackAction.diff * 10)) // Star gods have mercy on us.\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tBattleActionAttack attack = BattleActionAttack{ BA_USE, _unit, item, item };\n\t\t\t\t\t\tint radius = item->getRules()->getExplosionRadius(attack);\n\t\t\t\t\t\tif (radius > 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tint efficity = explosiveEfficacy(victim->getPosition(), _unit, radius, _attackAction.diff);\n\t\t\t\t\t\t\tif (efficity)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tweightToAttackMe += 2 * efficity * _intelligence; //bonus for boom boom.\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tweightToAttackMe += item->getRules()->getPowerBonus(attack);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse if (cost[j].type == BA_PANIC)\n\t\t\t\t\t{\n\t\t\t\t\t\t// target cannot be panicked\n\t\t\t\t\t\tif (victim->getUnitRules() && !victim->getUnitRules()->canPanic()) continue;\n\n\t\t\t\t\t\tweightToAttackMe += 40;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (weightToAttackMe > weightToAttack)\n\t\t\t\t\t{\n\t\t\t\t\t\ttypeToAttack = cost[j].type;\n\t\t\t\t\t\tweightToAttack = weightToAttackMe;\n\t\t\t\t\t\t_aggroTarget = victim;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (!_aggroTarget || !weightToAttack) return false;\n\n\t\tif (_visibleEnemies && _attackAction.weapon)\n\t\t{\n\t\t\tBattleActionType actions[] = {\n\t\t\t\tBA_AIMEDSHOT,\n\t\t\t\tBA_AUTOSHOT,\n\t\t\t\tBA_SNAPSHOT,\n\t\t\t\tBA_HIT,\n\t\t\t};\n\t\t\tfor (BattleActionType action : actions)\n\t\t\t{\n\t\t\t\tauto* ammo = _attackAction.weapon->getAmmoForAction(action);\n\t\t\t\tif (!ammo)\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tint weightPower = ammo->getRules()->getPowerBonus({ action, _attackAction.actor, _attackAction.weapon, ammo });\n\t\t\t\tif (action == BA_HIT)\n\t\t\t\t{\n\t\t\t\t\t// prefer psi over melee\n\t\t\t\t\tweightPower /= 2;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// prefer machine guns\n\t\t\t\t\tweightPower *= _attackAction.weapon->getActionConf(action)->shots;\n\t\t\t\t}\n\t\t\t\tif (weightPower >= weightToAttack)\n\t\t\t\t{\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse if (RNG::generate(35, 155) >= weightToAttack)\n\t\t{\n\t\t\treturn false;\n\t\t}\n\n\t\tif (_traceAI)\n\t\t{\n\t\t\tLog(LOG_INFO) << \"making a psionic attack this turn\";\n\t\t}\n\n\t\t_psiAction.type = typeToAttack;\n\t\t_psiAction.target = _aggroTarget->getPosition();\n\t\t_psiAction.weapon = item;\n\t\treturn true;\n\t}\n\treturn false;\n}\n\n/**\n * Performs a melee attack action.\n */\nvoid AIModule::meleeAttack()\n{\n\t_unit->lookAt(_aggroTarget->getPosition() + Position(_unit->getArmor()->getSize()-1, _unit->getArmor()->getSize()-1, 0), false);\n\twhile (_unit->getStatus() == STATUS_TURNING)\n\t\t_unit->turn();\n\tif (_traceAI) { Log(LOG_INFO) << \"Attack unit: \" << _aggroTarget->getId(); }\n\t_attackAction.target = _aggroTarget->getPosition();\n\t_attackAction.type = BA_HIT;\n\t_attackAction.weapon = _unit->getUtilityWeapon(BT_MELEE);\n}\n\n\n/**\n *\n * @param target\n * @return\n */\nAIAttackWeight AIModule::getTargetAttackWeight(BattleUnit* target) const\n{\n\tAIAttackWeight weight = AIW_IGNORED;\n\n\tif (target->getFaction() == _unit->getFaction())\n\t{\n\t\t// friendly target have negative weight, used for AoE attacks.\n\t\tweight = target->getAITargetWeightAsFriendly(_save->getMod());\n\t}\n\telse if (\n\t\t_intelligence < target->getTurnsSinceSpottedByFaction(_unit->getFaction()) &&\n\t\t(!_unit->isSniper() || !target->getTurnsLeftSpottedForSnipersByFaction(_unit->getFaction())))\n\t{\n\t\t// ignore units that we don't \"know\" about...\n\t\t// ... unless we are a sniper and the spotters know about them\n\t\tweight = AIW_IGNORED;\n\t}\n\telse if (target->getFaction() == FACTION_HOSTILE || _unit->getFaction() == FACTION_HOSTILE)\n\t{\n\t\tif (target->getFaction() == _targetFaction)\n\t\t{\n\t\t\t// enemy unit, full weight\n\t\t\tweight = target->getAITargetWeightAsHostile(_save->getMod());\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// if its not xcom unit then its civilian, less value that xcom\n\t\t\tweight = target->getAITargetWeightAsHostileCivilians(_save->getMod());\n\t\t}\n\t}\n\telse if (target->getFaction() == FACTION_NEUTRAL || _unit->getFaction() == FACTION_NEUTRAL)\n\t{\n\t\t// if its not alien then its xcom or civilian, humans do not shoot each other, usually...\n\t\tweight = target->getAITargetWeightAsNeutral(_save->getMod());\n\t}\n\n\tweight = (AIAttackWeight)ModScript::scriptFunc2<ModScript::AiCalculateTargetWeight>(\n\t\t_unit->getArmor(),\n\t\tweight, weight,\n\t\t_unit, target, _save\n\t);\n\n\treturn weight;\n}\n\n/**\n * Validates a target.\n * @param target the target we want to validate.\n * @param assessDanger do we care if this unit was previously targetted with a grenade?\n * @param includeCivs do we include civilians in the threat assessment?\n * @return whether this target is someone we would like to kill.\n */\nbool AIModule::validTarget(BattleUnit *target, bool assessDanger, bool includeCivs) const\n{\n\t// ignore units that:\n\t// 1. are dead/unconscious\n\t// 2. are dangerous (they have been grenaded)\n\t// 3. are hostile/neutral units marked as ignored by the AI\n\tif (target->isOut() ||\n\t\t(assessDanger && target->getTile()->getDangerous()) ||\n\t\t(target->getFaction() != FACTION_PLAYER && target->isIgnoredByAI()))\n\t{\n\t\treturn false;\n\t}\n\n\tif (includeCivs)\n\t{\n\t\treturn  getTargetAttackWeight(target) > AIW_IGNORED;\n\t}\n\telse\n\t{\n\t\treturn  getTargetAttackWeight(target) > _save->getMod()->getAITargetWeightThreatThreshold();\n\t}\n}\n\n/**\n * Checks the alien's reservation setting.\n * @return the reserve setting.\n */\nBattleActionType AIModule::getReserveMode()\n{\n\treturn _reserve;\n}\n\n/**\n * We have a dichotomy on our hands: we have a ranged weapon and melee capability.\n * let's make a determination on which one we'll be using this round.\n */\nvoid AIModule::selectMeleeOrRanged()\n{\n\tBattleItem *range = _attackAction.weapon;\n\tBattleItem *melee = _unit->getUtilityWeapon(BT_MELEE);\n\n\tif (!melee || !melee->haveAnyAmmo())\n\t{\n\t\t// no idea how we got here, but melee is definitely out of the question.\n\t\t_melee = false;\n\t\treturn;\n\t}\n\tif (!range || !range->haveAnyAmmo())\n\t{\n\t\t_rifle = false;\n\t\treturn;\n\t}\n\n\tconst RuleItem *meleeRule = melee->getRules();\n\n\tint meleeOdds = 10;\n\n\tint dmg = _aggroTarget->reduceByResistance(meleeRule->getPowerBonus(BattleActionAttack::GetBeforeShoot(BA_HIT, _unit, melee)), meleeRule->getDamageType()->ResistType);\n\n\tif (dmg > 50)\n\t{\n\t\tmeleeOdds += (dmg - 50) / 2;\n\t}\n\tif ( _visibleEnemies > 1 )\n\t{\n\t\tmeleeOdds -= 20 * (_visibleEnemies - 1);\n\t}\n\n\tif (meleeOdds > 0 && _unit->getHealth() >= 2 * _unit->getBaseStats()->health / 3)\n\t{\n\t\tif (_unit->getAggression() == 0)\n\t\t{\n\t\t\tmeleeOdds -= 20;\n\t\t}\n\t\telse if (_unit->getAggression() > 1)\n\t\t{\n\t\t\tmeleeOdds += 10 * _unit->getAggression();\n\t\t}\n\n\t\tif (RNG::percent(meleeOdds))\n\t\t{\n\t\t\t_rifle = false;\n\t\t\t_attackAction.weapon = melee;\n\t\t\t_reachableWithAttack = _save->getPathfinding()->findReachable(_unit, BattleActionCost(BA_HIT, _unit, melee));\n\t\t\treturn;\n\t\t}\n\t}\n\t_melee = false;\n}\n\n/**\n * Checks nearby nodes to see if they'd make good grenade targets\n * @param action contains our details one weapon and user, and we set the target for it here.\n * @return if we found a viable node or not.\n */\nbool AIModule::getNodeOfBestEfficacy(BattleAction *action, int radius)\n{\n\tint bestScore = 2;\n\tPosition originVoxel = _save->getTileEngine()->getSightOriginVoxel(_unit);\n\tPosition targetVoxel;\n\tfor (const auto* node : *_save->getNodes())\n\t{\n\t\tif (node->isDummy())\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\t\tint dist = Position::distance2d(node->getPosition(), _unit->getPosition());\n\t\tif (dist <= 20 && dist > radius &&\n\t\t\t_save->getTileEngine()->canTargetTile(&originVoxel, _save->getTile(node->getPosition()), O_FLOOR, &targetVoxel, _unit, false))\n\t\t{\n\t\t\tint nodePoints = 0;\n\t\t\tfor (auto* bu : *_save->getUnits())\n\t\t\t{\n\t\t\t\tdist = Position::distance2d(node->getPosition(), bu->getPosition());\n\t\t\t\tif (!bu->isOut() && dist < radius)\n\t\t\t\t{\n\t\t\t\t\tPosition targetOriginVoxel = _save->getTileEngine()->getSightOriginVoxel(bu);\n\t\t\t\t\tif (_save->getTileEngine()->canTargetTile(&targetOriginVoxel, _save->getTile(node->getPosition()), O_FLOOR, &targetVoxel, bu, false))\n\t\t\t\t\t{\n\t\t\t\t\t\tif ((_unit->getFaction() == FACTION_HOSTILE && bu->getFaction() != FACTION_HOSTILE) ||\n\t\t\t\t\t\t\t(_unit->getFaction() == FACTION_NEUTRAL && bu->getFaction() == FACTION_HOSTILE))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (bu->getTurnsSinceSpottedByFaction(_unit->getFaction()) <= _intelligence)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tnodePoints++;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tnodePoints -= 2;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (nodePoints > bestScore)\n\t\t\t{\n\t\t\t\tbestScore = nodePoints;\n\t\t\t\taction->target = node->getPosition();\n\t\t\t}\n\t\t}\n\t}\n\treturn bestScore > 2;\n}\n\nBattleUnit* AIModule::getTarget()\n{\n\treturn _aggroTarget;\n}\n\nvoid AIModule::freePatrolTarget()\n{\n\tif (_toNode)\n\t{\n\t\t_toNode->freeNode();\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/AIModule.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/Yaml.h\"\n#include \"BattlescapeGame.h\"\n#include \"Position.h\"\n#include \"../Savegame/BattleUnit.h\"\n#include <vector>\n\n\nnamespace OpenXcom\n{\n\nclass SavedBattleGame;\nclass BattleUnit;\nstruct BattleAction;\nclass BattlescapeState;\nclass Node;\n\nenum AIMode { AI_PATROL, AI_AMBUSH, AI_COMBAT, AI_ESCAPE };\nenum AIAttackWeight : int\n{\n\t/// Base scale of attack weights\n\tAIW_SCALE = 100,\n\tAIW_IGNORED = 0,\n};\n\n/**\n * This class is used by the BattleUnit AI.\n */\nclass AIModule\n{\nprivate:\n\tSavedBattleGame *_save;\n\tBattleUnit *_unit;\n\tBattleUnit *_aggroTarget;\n\tint _knownEnemies, _visibleEnemies, _spottingEnemies;\n\tint _escapeTUs, _ambushTUs;\n\tbool _weaponPickedUp;\n\tbool _rifle, _melee, _blaster, _grenade;\n\tbool _traceAI, _didPsi;\n\tint _AIMode, _intelligence, _closestDist;\n\tNode *_fromNode, *_toNode;\n\tbool _foundBaseModuleToDestroy;\n\tstd::vector<int> _reachable, _reachableWithAttack, _wasHitBy;\n\tBattleActionType _reserve;\n\tUnitFaction _targetFaction;\n\n\tBattleAction _escapeAction, _ambushAction, _attackAction, _patrolAction, _psiAction;\n\n\tbool selectPointNearTargetLeeroy(BattleUnit *target, bool canRun);\n\tint selectNearestTargetLeeroy(bool canRun);\n\tvoid meleeActionLeeroy(bool canRun);\n\tvoid dont_think(BattleAction *action);\npublic:\n\tbool medikit_think(BattleMediKitType healOrStim);\npublic:\n\t/// Creates a new AIModule linked to the game and a certain unit.\n\tAIModule(SavedBattleGame *save, BattleUnit *unit, Node *node);\n\t/// Cleans up the AIModule.\n\t~AIModule();\n\t/// Sets the target faction.\n\tvoid setTargetFaction(UnitFaction f);\n\t/// Resets the unsaved AI state.\n\tvoid reset();\n\t/// Loads the AI Module from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader);\n\t/// Saves the AI Module to YAML.\n\tvoid save(YAML::YamlNodeWriter writer) const;\n\t/// Runs Module functionality every AI cycle.\n\tvoid think(BattleAction *action);\n\t/// Sets the \"unit was hit\" flag true.\n\tvoid setWasHitBy(BattleUnit *attacker);\n\t/// Sets the \"unit picked up a weapon\" flag.\n\tvoid setWeaponPickedUp();\n\t/// Gets whether the unit was hit.\n\tbool getWasHitBy(int attacker) const;\n\t/// Set start node.\n\tvoid setStartNode(Node *node) { _fromNode = node; }\n\t/// setup a patrol objective.\n\tvoid setupPatrol();\n\t/// setup an ambush objective.\n\tvoid setupAmbush();\n\t/// setup a combat objective.\n\tvoid setupAttack();\n\t/// setup an escape objective.\n\tvoid setupEscape();\n\t/// count how many xcom/civilian units are known to this unit.\n\tint countKnownTargets() const;\n\t/// count how many known XCom units are able to see this unit.\n\tint getSpottingUnits(const Position& pos) const;\n\t/// Selects the nearest target we can see, and return the number of viable targets.\n\tint selectNearestTarget();\n\t/// Selects the closest known xcom unit for ambushing.\n\tbool selectClosestKnownEnemy();\n\t/// Selects a random known target.\n\tbool selectRandomTarget();\n\t/// Selects the nearest reachable point relative to a target.\n\tbool selectPointNearTarget(BattleUnit *target, int maxTUs);\n\t/// Selects a target from a list of units seen by spotter units for out-of-LOS actions\n\tbool selectSpottedUnitForSniper();\n\t/// Scores a firing mode action based on distance to target and accuracy.\n\tint scoreFiringMode(BattleAction *action, BattleUnit *target, bool checkLOF);\n\t/// re-evaluate our situation, and make a decision from our available options.\n\tvoid evaluateAIMode();\n\t/// Selects a suitable position from which to attack.\n\tbool findFirePoint();\n\t/// Decides if we should throw a grenade/launch a missile to this position.\n\tint explosiveEfficacy(Position targetPos, BattleUnit *attackingUnit, int radius, int diff, bool grenade = false) const;\n\tbool getNodeOfBestEfficacy(BattleAction *action, int radius);\n\t/// Attempts to take a melee attack/charge an enemy we can see.\n\tvoid meleeAction();\n\t/// Attempts to fire a waypoint projectile at an enemy we, or one of our teammates sees.\n\tvoid wayPointAction();\n\t/// Attempts to fire at an enemy spotted for us.\n\tbool sniperAction();\n\t/// Attempts to fire at an enemy we can see.\n\tvoid projectileAction();\n\t/// Chooses a firing mode for the AI based on expected number of hits per turn\n\tvoid extendedFireModeChoice(BattleActionCost& costAuto, BattleActionCost& costSnap, BattleActionCost& costAimed, BattleActionCost& costThrow, bool checkLOF = false);\n\t/// Attempts to throw a grenade at an enemy (or group of enemies) we can see.\n\tvoid grenadeAction();\n\t/// Performs a psionic attack.\n\tbool psiAction();\n\t/// Performs a melee attack action.\n\tvoid meleeAttack();\n\n\t/// How much given unit is worth as target of attack.\n\tAIAttackWeight getTargetAttackWeight(BattleUnit* target) const;\n\t/// Checks to make sure a target is valid, given the parameters\n\tbool validTarget(BattleUnit* target, bool assessDanger, bool includeCivs) const;\n\n\t/// Checks the alien's TU reservation setting.\n\tBattleActionType getReserveMode();\n\t/// Assuming we have both a ranged and a melee weapon, we have to select one.\n\tvoid selectMeleeOrRanged();\n\t/// Gets the current targetted unit.\n\tBattleUnit* getTarget();\n\t/// Frees up the destination node for another Unit to select\n\tvoid freePatrolTarget();\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/AbortMissionState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"AbortMissionState.h\"\n#include <vector>\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Engine/Action.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"BattlescapeGame.h\"\n#include \"BattlescapeState.h\"\n#include \"../Engine/Options.h\"\n#include \"../Mod/AlienDeployment.h\"\n#include \"../Mod/MapScript.h\"\n#include \"../Mod/RuleCraft.h\"\n#include \"../Savegame/Craft.h\"\n#include \"../Savegame/Tile.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Abort Mission window.\n * @param game Pointer to the core game.\n * @param battleGame Pointer to the saved game.\n * @param state Pointer to the Battlescape state.\n */\nAbortMissionState::AbortMissionState(SavedBattleGame *battleGame, BattlescapeState *state) : _battleGame(battleGame), _state(state), _inEntrance(0), _inExit(0), _outside(0)\n{\n\t// Create objects\n\t_screen = false;\n\t_window = new Window(this, 320, 144, 0, 0);\n\t_txtInEntrance = new Text(304, 17, 16, 20);\n\t_txtInExit = new Text(304, 17, 16, 40);\n\t_txtOutside = new Text(304, 17, 16, 60);\n\t_txtAbort = new Text(320, 17, 0, 80);\n\t_btnOk = new TextButton(120, 16, 16, 110);\n\t_btnCancel = new TextButton(120, 16, 184, 110);\n\n\t// Set palette\n\t_battleGame->setPaletteByDepth(this);\n\n\tadd(_window, \"messageWindowBorder\", \"battlescape\");\n\tadd(_txtInEntrance, \"messageWindows\", \"battlescape\");\n\tadd(_txtInExit, \"messageWindows\", \"battlescape\");\n\tadd(_txtOutside, \"messageWindows\", \"battlescape\");\n\tadd(_txtAbort, \"messageWindows\", \"battlescape\");\n\tadd(_btnOk, \"messageWindowButtons\", \"battlescape\");\n\tadd(_btnCancel, \"messageWindowButtons\", \"battlescape\");\n\n\t// Check available areas (maybe should be cached somewhere)\n\tbool exit = false, craft = true;\n\tAlienDeployment *deployment = _game->getMod()->getDeployment(_battleGame->getMissionType());\n\tif (deployment != 0)\n\t{\n\t\texit = !deployment->getNextStage().empty() || deployment->getEscapeType() == ESCAPE_EXIT || deployment->getEscapeType() == ESCAPE_EITHER;\n\t\tstd::string lastUsedMapScript = _battleGame->getLastUsedMapScript();\n\t\tif (lastUsedMapScript.empty())\n\t\t{\n\t\t\tlastUsedMapScript = deployment->getRandomMapScript(); // don't crash on old saves\n\t\t}\n\t\tconst std::vector<MapScript*> *mapScriptEntries = _game->getMod()->getMapScript(lastUsedMapScript);\n\t\tif (mapScriptEntries != 0)\n\t\t{\n\t\t\tcraft = false;\n\t\t\tfor (const auto* mapScriptEntry : *mapScriptEntries)\n\t\t\t{\n\t\t\t\tif (mapScriptEntry->getType() == MSC_ADDCRAFT)\n\t\t\t\t{\n\t\t\t\t\tcraft = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif (exit)\n\t{\n\t\texit = false;\n\t\tfor (int i = 0; i < _battleGame->getMapSizeXYZ(); ++i)\n\t\t{\n\t\t\tTile *tile = _battleGame->getTile(i);\n\t\t\tif (tile && tile->getFloorSpecialTileType() == END_POINT)\n\t\t\t{\n\t\t\t\texit = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Calculate values\n\tBattlescapeTally tally = _battleGame->isPreview() ? _battleGame->tallyUnitsForPreview() : _battleGame->getBattleGame()->tallyUnits();\n\t_inEntrance = tally.inEntrance;\n\t_inExit = tally.inExit;\n\t_outside = tally.inField;\n\n\tif (!exit && _inExit > 0)\n\t{\n\t\t// FIXME: better would be to correctly decide already at the top (how??), but for now this will do...\n\t\texit = true;\n\t}\n\n\t// Set up objects\n\t_window->setHighContrast(true);\n\t_window->setBackground(_game->getMod()->getSurface(\"TAC00.SCR\"));\n\n\t_txtInEntrance->setBig();\n\t_txtInEntrance->setHighContrast(true);\n\tif (craft)\n\t{\n\t\t_txtInEntrance->setText(tr(\"STR_UNITS_IN_CRAFT\", _inEntrance + tally.vipInEntrance));\n\t}\n\telse\n\t{\n\t\t_txtInEntrance->setText(tr(\"STR_UNITS_IN_ENTRANCE\", _inEntrance + tally.vipInEntrance));\n\t}\n\n\t_txtInExit->setBig();\n\t_txtInExit->setHighContrast(true);\n\t_txtInExit->setText(tr(\"STR_UNITS_IN_EXIT\", _inExit + tally.vipInExit));\n\n\t_txtOutside->setBig();\n\t_txtOutside->setHighContrast(true);\n\t_txtOutside->setText(tr(\"STR_UNITS_OUTSIDE\", _outside + tally.vipInField));\n\n\n\tif (_battleGame->getMissionType() == \"STR_BASE_DEFENSE\")\n\t{\n\t\t_txtInEntrance->setVisible(false);\n\t\t_txtInExit->setVisible(false);\n\t\t_txtOutside->setVisible(false);\n\t}\n\telse if (!exit || _battleGame->isPreview())\n\t{\n\t\t_txtInEntrance->setY(26);\n\t\t_txtOutside->setY(54);\n\t\t_txtInExit->setVisible(false);\n\t}\n\n\t_txtAbort->setBig();\n\t_txtAbort->setAlign(ALIGN_CENTER);\n\t_txtAbort->setHighContrast(true);\n\t_txtAbort->setText(tr(\"STR_ABORT_MISSION_QUESTION\"));\n\tif (_battleGame->isPreview())\n\t{\n\t\t_txtAbort->setText(tr(\"STR_CRAFT_DEPLOYMENT_QUESTION\"));\n\t}\n\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->setHighContrast(true);\n\t_btnOk->onMouseClick((ActionHandler)&AbortMissionState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&AbortMissionState::btnOkClick, Options::keyOk);\n\tif (_battleGame->isPreview() && (_outside > 0 || _inEntrance <= 0))\n\t{\n\t\t_btnOk->setVisible(false);\n\t}\n\n\n\t_btnCancel->setText(tr(\"STR_CANCEL_UC\"));\n\t_btnCancel->setHighContrast(true);\n\t_btnCancel->onMouseClick((ActionHandler)&AbortMissionState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&AbortMissionState::btnCancelClick, Options::keyCancel);\n\t_btnCancel->onKeyboardPress((ActionHandler)&AbortMissionState::btnCancelClick, Options::keyBattleAbort);\n\n\tcenterAllSurfaces();\n}\n\n/**\n *\n */\nAbortMissionState::~AbortMissionState()\n{\n\n}\n\n/**\n * Confirms mission abort.\n * @param action Pointer to an action.\n */\nvoid AbortMissionState::btnOkClick(Action *)\n{\n\tif (_battleGame->isPreview())\n\t{\n\t\tif (_battleGame->getCraftForPreview()->getId() == RuleCraft::DUMMY_CRAFT_ID)\n\t\t{\n\t\t\t// dummy craft, generic deployment schema\n\t\t\t_battleGame->saveDummyCraftDeployment();\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// real craft, real unit deployment\n\t\t\t_battleGame->saveCustomCraftDeployment();\n\t\t}\n\n\t\t_game->popState();\n\t\treturn;\n\t}\n\n\t_game->popState();\n\t_battleGame->setAborted(true);\n\t_state->finishBattle(true, _inExit);\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid AbortMissionState::btnCancelClick(Action *)\n{\n\t_game->popState();\n}\n\n\n}\n"
  },
  {
    "path": "src/Battlescape/AbortMissionState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass Window;\nclass Text;\nclass TextButton;\nclass SavedBattleGame;\nclass BattlescapeState;\n\n/**\n * Screen which asks for confirmation to abort mission.\n */\nclass AbortMissionState : public State\n{\nprivate:\n\tWindow *_window;\n\tText *_txtInEntrance, *_txtInExit, *_txtOutside, *_txtAbort;\n\tTextButton *_btnOk, *_btnCancel;\n\tSavedBattleGame *_battleGame;\n\tBattlescapeState *_state;\n\tint _inEntrance, _inExit, _outside;\npublic:\n\t/// Creates the Abort Mission state.\n\tAbortMissionState(SavedBattleGame *battleGame, BattlescapeState *state);\n\t/// Cleans up the Abort Mission state.\n\t~AbortMissionState();\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action *action);\n\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/ActionMenuItem.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ActionMenuItem.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/Frame.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleInterface.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Sets up an Action menu item.\n * @param id The unique identifier of the menu item.\n * @param game Pointer to the game.\n * @param x Position on the x-axis.\n * @param y Position on the y-axis.\n */\nActionMenuItem::ActionMenuItem(int id, Game *game, int x, int y) : InteractiveSurface(272, 40, x + 24, y - (id*40)), _highlighted(false), _action(BA_NONE), _skill(nullptr), _tu(0)\n{\n\tFont *big = game->getMod()->getFont(\"FONT_BIG\"), *small = game->getMod()->getFont(\"FONT_SMALL\");\n\tLanguage *lang = game->getLanguage();\n\n\tconst Element *actionMenu = game->getMod()->getInterface(\"battlescape\")->getElement(\"actionMenu\");\n\n\t_highlightModifier = actionMenu->TFTDMode ? 12 : 3;\n\n\t_frame = new Frame(getWidth(), getHeight(), 0, 0);\n\t_frame->setHighContrast(true);\n\t_frame->setColor(actionMenu->border);\n\t_frame->setSecondaryColor(actionMenu->color2);\n\t_frame->setThickness(8);\n\n\t_txtDescription = new Text(200, 20, 10, 13);\n\t_txtDescription->initText(big, small, lang);\n\t_txtDescription->setBig();\n\t_txtDescription->setHighContrast(true);\n\t_txtDescription->setColor(actionMenu->color);\n\t_txtDescription->setVisible(true);\n\n\t_txtAcc = new Text(100, 20, 140, 13);\n\t_txtAcc->initText(big, small, lang);\n\t_txtAcc->setBig();\n\t_txtAcc->setHighContrast(true);\n\t_txtAcc->setColor(actionMenu->color);\n\n\t_txtTU = new Text(80, 20, 210, 13);\n\t_txtTU->initText(big, small, lang);\n\t_txtTU->setBig();\n\t_txtTU->setHighContrast(true);\n\t_txtTU->setColor(actionMenu->color);\n}\n\n/**\n * Deletes the ActionMenuItem.\n */\nActionMenuItem::~ActionMenuItem()\n{\n\tdelete _frame;\n\tdelete _txtDescription;\n\tdelete _txtAcc;\n\tdelete _txtTU;\n}\n\n/**\n * Links with an action and fills in the text fields.\n * @param action The battlescape action.\n * @param description The actions description.\n * @param accuracy The actions accuracy, including the Acc> prefix.\n * @param timeunits The timeunits string, including the TUs> prefix.\n * @param tu The timeunits value.\n */\nvoid ActionMenuItem::setAction(BattleActionType action, const std::string &description, const std::string &accuracy, const std::string &timeunits, int tu)\n{\n\t_action = action;\n\t_txtDescription->setText(description);\n\t_txtAcc->setText(accuracy);\n\t_txtTU->setText(timeunits);\n\t_tu = tu;\n\t_redraw = true;\n}\n\n/**\n * Links with a skill.\n * @param skill The linked skill.\n */\nvoid ActionMenuItem::setSkill(const RuleSkill *skill)\n{\n\t_skill = skill;\n}\n\n/**\n * Gets the action that was linked to this menu item.\n * @return Action that was linked to this menu item.\n */\nBattleActionType ActionMenuItem::getAction() const\n{\n\treturn _action;\n}\n\n/**\n * Gets the skill that was linked to this menu item.\n * @return Skill that was linked to this menu item.\n */\nconst RuleSkill* ActionMenuItem::getSkill() const\n{\n\treturn _skill;\n}\n\n/**\n * Gets the action tus that were linked to this menu item.\n * @return The timeunits that were linked to this menu item.\n */\nint ActionMenuItem::getTUs() const\n{\n\treturn _tu;\n}\n\n/**\n * Replaces a certain amount of colors in the surface's palette.\n * @param colors Pointer to the set of colors.\n * @param firstcolor Offset of the first color to replace.\n * @param ncolors Amount of colors to replace.\n */\nvoid ActionMenuItem::setPalette(const SDL_Color *colors, int firstcolor, int ncolors)\n{\n\tSurface::setPalette(colors, firstcolor, ncolors);\n\t_frame->setPalette(colors, firstcolor, ncolors);\n\t_txtDescription->setPalette(colors, firstcolor, ncolors);\n\t_txtAcc->setPalette(colors, firstcolor, ncolors);\n\t_txtTU->setPalette(colors, firstcolor, ncolors);\n}\n\n/**\n * Draws the bordered box.\n */\nvoid ActionMenuItem::draw()\n{\n\t_frame->blit(this->getSurface());\n\t_txtDescription->blit(this->getSurface());\n\t_txtAcc->blit(this->getSurface());\n\t_txtTU->blit(this->getSurface());\n}\n\n/**\n * Processes a mouse hover in event.\n * @param action Pointer to an action.\n * @param state Pointer to a state.\n */\nvoid ActionMenuItem::mouseIn(Action *action, State *state)\n{\n\t_highlighted = true;\n\t_frame->setSecondaryColor(_frame->getSecondaryColor() - _highlightModifier);\n\tdraw();\n\tInteractiveSurface::mouseIn(action, state);\n}\n\n\n/**\n * Processes a mouse hover out event.\n * @param action Pointer to an action.\n * @param state Pointer to a state.\n */\nvoid ActionMenuItem::mouseOut(Action *action, State *state)\n{\n\t_highlighted = false;\n\t_frame->setSecondaryColor(_frame->getSecondaryColor() + _highlightModifier);\n\tdraw();\n\tInteractiveSurface::mouseOut(action, state);\n}\n\n\n}\n"
  },
  {
    "path": "src/Battlescape/ActionMenuItem.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/InteractiveSurface.h\"\n#include \"BattlescapeGame.h\"\n\nnamespace OpenXcom\n{\n\nclass Game;\nclass Font;\nclass Language;\nclass Text;\nclass Frame;\nclass RuleSkill;\n\n/**\n * A class that represents a single box in the action popup menu on the battlescape.\n * It shows the possible actions of an item, their TU cost and accuracy.\n * Mouse over highlights the action, when clicked the action is sent to the parent state.\n */\nclass ActionMenuItem : public InteractiveSurface\n{\nprivate:\n\tbool _highlighted;\n\tBattleActionType _action;\n\tconst RuleSkill* _skill;\n\tint _tu, _highlightModifier;\n\tFrame *_frame;\n\tText *_txtDescription, *_txtAcc, *_txtTU;\npublic:\n\t/// Creates a new ActionMenuItem.\n\tActionMenuItem(int id, Game *game, int x, int y);\n\t/// Cleans up the ActionMenuItem.\n\t~ActionMenuItem();\n\t/// Assigns an action to it.\n\tvoid setAction(BattleActionType action, const std::string &description, const std::string &accuracy, const std::string &timeunits, int tu);\n\tvoid setSkill(const RuleSkill* skill);\n\t/// Gets the assigned action.\n\tBattleActionType getAction() const;\n\t/// Gets the assigned skill.\n\tconst RuleSkill* getSkill() const;\n\t/// Gets the assigned action TUs.\n\tint getTUs() const;\n\t/// Sets the palettes.\n\tvoid setPalette(const SDL_Color *colors, int firstcolor, int ncolors) override;\n\t/// Redraws it.\n\tvoid draw() override;\n\t/// Processes a mouse hover in event.\n\tvoid mouseIn(Action *action, State *state) override;\n\t/// Processes a mouse hover out event.\n\tvoid mouseOut(Action *action, State *state) override;\n\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/ActionMenuState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ActionMenuState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Savegame/BattleUnit.h\"\n#include \"../Savegame/BattleItem.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"ActionMenuItem.h\"\n#include \"PrimeGrenadeState.h\"\n#include \"MedikitState.h\"\n#include \"ScannerState.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"../Savegame/Tile.h\"\n#include \"../Savegame/HitLog.h\"\n#include \"Pathfinding.h\"\n#include \"TileEngine.h\"\n#include \"../Interface/Text.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Default constructor, used by SkillMenuState.\n */\nActionMenuState::ActionMenuState(BattleAction *action) : _action(action)\n{\n}\n\n/**\n * Initializes all the elements in the Action Menu window.\n * @param game Pointer to the core game.\n * @param action Pointer to the action.\n * @param x Position on the x-axis.\n * @param y position on the y-axis.\n */\nActionMenuState::ActionMenuState(BattleAction *action, int x, int y) : _action(action)\n{\n\t_screen = false;\n\n\t// Set palette\n\t_game->getSavedGame()->getSavedBattle()->setPaletteByDepth(this);\n\n\tfor (int i = 0; i < 6; ++i)\n\t{\n\t\t_actionMenu[i] = new ActionMenuItem(i, _game, x, y);\n\t\tadd(_actionMenu[i]);\n\t\t_actionMenu[i]->setVisible(false);\n\t\t_actionMenu[i]->onMouseClick((ActionHandler)&ActionMenuState::btnActionMenuItemClick);\n\t}\n\n\t// Build up the popup menu\n\tint id = 0;\n\tconst RuleItem *weapon = _action->weapon->getRules();\n\n\t// throwing (if not a fixed weapon)\n\tif (!weapon->isFixed() && weapon->getCostThrow().Time > 0)\n\t{\n\t\taddItem(BA_THROW, \"STR_THROW\", &id, Options::keyBattleActionItem5);\n\t}\n\n\tif (weapon->isPsiRequired() && _action->actor->getBaseStats()->psiSkill <= 0)\n\t{\n\t\treturn;\n\t}\n\n\tif (weapon->isManaRequired() && _action->actor->getOriginalFaction() == FACTION_PLAYER)\n\t{\n\t\tif (!_game->getMod()->isManaFeatureEnabled() || !_game->getSavedGame()->isManaUnlocked(_game->getMod()))\n\t\t{\n\t\t\treturn;\n\t\t}\n\t}\n\n\t// priming\n\tif (weapon->getFuseTimerType() != BFT_NONE)\n\t{\n\t\tbool normalWeapon = weapon->getBattleType() != BT_GRENADE && weapon->getBattleType() != BT_FLARE && weapon->getBattleType() != BT_PROXIMITYGRENADE;\n\t\tif (_action->weapon->getFuseTimer() == -1)\n\t\t{\n\t\t\tif (weapon->getCostPrime().Time > 0)\n\t\t\t{\n\t\t\t\taddItem(BA_PRIME, weapon->getPrimeActionName(), &id, normalWeapon ? SDLK_UNKNOWN : Options::keyBattleActionItem1);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (weapon->getCostUnprime().Time > 0 && !weapon->getUnprimeActionName().empty())\n\t\t\t{\n\t\t\t\taddItem(BA_UNPRIME, weapon->getUnprimeActionName(), &id, normalWeapon ? SDLK_UNKNOWN : Options::keyBattleActionItem2);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (weapon->getBattleType() == BT_FIREARM)\n\t{\n\t\tbool isLauncher = _action->weapon->getCurrentWaypoints() != 0;\n\t\tint slotLauncher = _action->weapon->getActionConf(BA_LAUNCH)->ammoSlot;\n\t\tint slotSnap = _action->weapon->getActionConf(BA_SNAPSHOT)->ammoSlot;\n\t\tint slotAuto = _action->weapon->getActionConf(BA_AUTOSHOT)->ammoSlot;\n\n\t\tif ((!isLauncher || slotLauncher != slotAuto) && weapon->getCostAuto().Time > 0)\n\t\t{\n\t\t\taddItem(BA_AUTOSHOT, weapon->getConfigAuto()->name, &id, Options::keyBattleActionItem3);\n\t\t}\n\n\t\tif ((!isLauncher || slotLauncher != slotSnap) && weapon->getCostSnap().Time > 0)\n\t\t{\n\t\t\taddItem(BA_SNAPSHOT,  weapon->getConfigSnap()->name, &id, Options::keyBattleActionItem2);\n\t\t}\n\n\t\tif (isLauncher)\n\t\t{\n\t\t\taddItem(BA_LAUNCH, \"STR_LAUNCH_MISSILE\", &id, Options::keyBattleActionItem1);\n\t\t}\n\t\telse if (weapon->getCostAimed().Time > 0)\n\t\t{\n\t\t\taddItem(BA_AIMEDSHOT,  weapon->getConfigAimed()->name, &id, Options::keyBattleActionItem1);\n\t\t}\n\t}\n\n\tif (weapon->getCostMelee().Time > 0)\n\t{\n\t\tstd::string name = weapon->getConfigMelee()->name;\n\t\tif (name.empty())\n\t\t{\n\t\t\t// stun rod\n\t\t\tif (weapon->getBattleType() == BT_MELEE && weapon->getDamageType()->ResistType == DT_STUN)\n\t\t\t{\n\t\t\t\tname = \"STR_STUN\";\n\t\t\t}\n\t\t\telse\n\t\t\t// melee weapon\n\t\t\t{\n\t\t\t\tname = \"STR_HIT_MELEE\";\n\t\t\t}\n\t\t}\n\t\taddItem(BA_HIT, name, &id, Options::keyBattleActionItem4);\n\t}\n\n\t// special items\n\tif (weapon->getBattleType() == BT_MEDIKIT)\n\t{\n\t\taddItem(BA_USE, weapon->getMedikitActionName(), &id, Options::keyBattleActionItem1);\n\t}\n\telse if (weapon->getBattleType() == BT_SCANNER)\n\t{\n\t\taddItem(BA_USE, weapon->getPsiAttackName().empty() ? \"STR_USE_SCANNER\" : weapon->getPsiAttackName(), &id, Options::keyBattleActionItem1);\n\t}\n\telse if (weapon->getBattleType() == BT_PSIAMP)\n\t{\n\t\tif (weapon->getCostMind().Time > 0)\n\t\t{\n\t\t\taddItem(BA_MINDCONTROL, \"STR_MIND_CONTROL\", &id, Options::keyBattleActionItem3);\n\t\t}\n\t\tif (weapon->getCostPanic().Time > 0)\n\t\t{\n\t\t\taddItem(BA_PANIC, \"STR_PANIC_UNIT\", &id, Options::keyBattleActionItem2);\n\t\t}\n\t\tif (weapon->getCostUse().Time > 0)\n\t\t{\n\t\t\taddItem(BA_USE, weapon->getPsiAttackName(), &id, Options::keyBattleActionItem1);\n\t\t}\n\t}\n\telse if (weapon->getBattleType() == BT_MINDPROBE)\n\t{\n\t\taddItem(BA_USE, weapon->getPsiAttackName().empty() ? \"STR_USE_MIND_PROBE\" : weapon->getPsiAttackName(), &id, Options::keyBattleActionItem1);\n\t}\n\n}\n\n/**\n * Deletes the ActionMenuState.\n */\nActionMenuState::~ActionMenuState()\n{\n\n}\n\n/**\n * Init function.\n */\nvoid ActionMenuState::init()\n{\n\tif (!_actionMenu[0]->getVisible())\n\t{\n\t\t// Item don't have any actions, close popup.\n\t\t_game->popState();\n\t}\n}\n\n/**\n * Adds a new menu item for an action.\n * @param ba Action type.\n * @param name Action description.\n * @param id Pointer to the new item ID.\n */\nvoid ActionMenuState::addItem(BattleActionType ba, const std::string &name, int *id, SDLKey key)\n{\n\tstd::string s1, s2;\n\tint acc = BattleUnit::getFiringAccuracy(BattleActionAttack::GetBeforeShoot(ba, _action->actor, _action->weapon), _game->getMod());\n\tint tu = _action->actor->getActionTUs(ba, _action->weapon).Time;\n\n\tif (ba == BA_THROW || ba == BA_AIMEDSHOT || ba == BA_SNAPSHOT || ba == BA_AUTOSHOT || ba == BA_LAUNCH || ba == BA_HIT)\n\t\ts1 = tr(\"STR_ACCURACY_SHORT\").arg(Unicode::formatPercentage(acc));\n\ts2 = tr(\"STR_TIME_UNITS_SHORT\").arg(tu);\n\t_actionMenu[*id]->setAction(ba, tr(name), s1, s2, tu);\n\t_actionMenu[*id]->setVisible(true);\n\tif (key != SDLK_UNKNOWN)\n\t{\n\t\t_actionMenu[*id]->onKeyboardPress((ActionHandler)&ActionMenuState::btnActionMenuItemClick, key);\n\t}\n\t(*id)++;\n}\n\n/**\n * Closes the window on right-click.\n * @param action Pointer to an action.\n */\nvoid ActionMenuState::handle(Action *action)\n{\n\tState::handle(action);\n\tif (action->getDetails()->type == SDL_MOUSEBUTTONDOWN && _game->isRightClick(action))\n\t{\n\t\t_game->popState();\n\t}\n\telse if (action->getDetails()->type == SDL_KEYDOWN)\n\t{\n\t\tauto key = action->getDetails()->key.keysym.sym;\n\t\tif (key == Options::keyCancel || key == Options::keyBattleUseLeftHand || key == Options::keyBattleUseRightHand)\n\t\t{\n\t\t\tif (key != Options::keyBattleActionItem1 &&\n\t\t\t\tkey != Options::keyBattleActionItem2 &&\n\t\t\t\tkey != Options::keyBattleActionItem3 &&\n\t\t\t\tkey != Options::keyBattleActionItem4 &&\n\t\t\t\tkey != Options::keyBattleActionItem5)\n\t\t\t{\n\t\t\t\t_game->popState();\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Executes the action corresponding to this action menu item.\n * @param action Pointer to an action.\n */\nvoid ActionMenuState::btnActionMenuItemClick(Action *action)\n{\n\t_game->getSavedGame()->getSavedBattle()->getPathfinding()->removePreview();\n\n\tint btnID = -1;\n\n\tif (_game->getSavedGame()->getSavedBattle()->isPreview())\n\t{\n\t\t_action->result = \"STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED\";\n\t\t_game->popState();\n\t\treturn;\n\t}\n\n\t// got to find out which button was pressed\n\tfor (size_t i = 0; i < std::size(_actionMenu) && btnID == -1; ++i)\n\t{\n\t\tif (action->getSender() == _actionMenu[i])\n\t\t{\n\t\t\tbtnID = i;\n\t\t}\n\t}\n\n\tif (btnID != -1)\n\t{\n\t\t_action->type = _actionMenu[btnID]->getAction();\n\t\t_action->skillRules = nullptr;\n\t\t_action->updateTU();\n\n\t\thandleAction();\n\t}\n}\n\nvoid ActionMenuState::handleAction()\n{\n\t// reset potential garbage from the previous action\n\t_action->terrainMeleeTilePart = 0;\n\n\t{\n\t\tconst RuleItem *weapon = _action->weapon->getRules();\n\t\tbool newHitLog = false;\n\t\tstd::string actionResult = \"STR_UNKNOWN\"; // needs a non-empty default/fall-back !\n\n\t\tif (_action->type != BA_THROW &&\n\t\t\t_action->actor->getOriginalFaction() == FACTION_PLAYER &&\n\t\t\t!_game->getSavedGame()->isResearched(weapon->getRequirements()))\n\t\t{\n\t\t\t_action->result = \"STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED\";\n\t\t\t_game->popState();\n\t\t}\n\t\telse if (_action->type != BA_THROW &&\n\t\t\t!_game->getSavedGame()->getSavedBattle()->canUseWeapon(_action->weapon, _action->actor, false, _action->type, &actionResult))\n\t\t{\n\t\t\t_action->result = actionResult;\n\t\t\t_game->popState();\n\t\t}\n\t\telse if (_action->type == BA_PRIME)\n\t\t{\n\t\t\tconst BattleFuseType fuseType = weapon->getFuseTimerType();\n\t\t\tif (fuseType == BFT_SET)\n\t\t\t{\n\t\t\t\t_game->pushState(new PrimeGrenadeState(_action, false, 0));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_action->value = weapon->getFuseTimerDefault();\n\t\t\t\t_game->popState();\n\t\t\t}\n\t\t}\n\t\telse if (_action->type == BA_UNPRIME)\n\t\t{\n\t\t\t_game->popState();\n\t\t}\n\t\telse if (_action->type == BA_USE && weapon->getBattleType() == BT_MEDIKIT)\n\t\t{\n\t\t\tBattleUnit *targetUnit = 0;\n\t\t\tTileEngine *tileEngine = _game->getSavedGame()->getSavedBattle()->getTileEngine();\n\t\t\tfor (auto* bu : *_game->getSavedGame()->getSavedBattle()->getUnits())\n\t\t\t{\n\t\t\t\t// we can heal a unit that is at the same position, unconscious and healable(=woundable)\n\t\t\t\tif (bu->getPosition() == _action->actor->getPosition() &&\n\t\t\t\t\tbu != _action->actor &&\n\t\t\t\t\tbu->getStatus() == STATUS_UNCONSCIOUS &&\n\t\t\t\t\t(bu->isWoundable() || weapon->getAllowTargetImmune()) &&\n\t\t\t\t\tweapon->getAllowTargetGround())\n\t\t\t\t{\n\t\t\t\t\tif (bu->isBigUnit())\n\t\t\t\t\t{\n\t\t\t\t\t\t// never EVER apply anything to 2x2 units on the ground\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tif ((weapon->getAllowTargetFriendGround() && bu->getOriginalFaction() == FACTION_PLAYER) ||\n\t\t\t\t\t\t(weapon->getAllowTargetNeutralGround() && bu->getOriginalFaction() == FACTION_NEUTRAL) ||\n\t\t\t\t\t\t(weapon->getAllowTargetHostileGround() && bu->getOriginalFaction() == FACTION_HOSTILE))\n\t\t\t\t\t{\n\t\t\t\t\t\ttargetUnit = bu;\n\t\t\t\t\t\tbreak; // loop finished\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!targetUnit && weapon->getAllowTargetStanding())\n\t\t\t{\n\t\t\t\tif (tileEngine->validMeleeRange(\n\t\t\t\t\t_action->actor->getPosition(),\n\t\t\t\t\t_action->actor->getDirection(),\n\t\t\t\t\t_action->actor,\n\t\t\t\t\t0, &_action->target, false))\n\t\t\t\t{\n\t\t\t\t\tTile *tile = _game->getSavedGame()->getSavedBattle()->getTile(_action->target);\n\t\t\t\t\tif (tile != 0 && tile->getUnit() && (tile->getUnit()->isWoundable() || weapon->getAllowTargetImmune()))\n\t\t\t\t\t{\n\t\t\t\t\t\tif ((weapon->getAllowTargetFriendStanding() && tile->getUnit()->getOriginalFaction() == FACTION_PLAYER) ||\n\t\t\t\t\t\t\t(weapon->getAllowTargetNeutralStanding() && tile->getUnit()->getOriginalFaction() == FACTION_NEUTRAL) ||\n\t\t\t\t\t\t\t(weapon->getAllowTargetHostileStanding() && tile->getUnit()->getOriginalFaction() == FACTION_HOSTILE))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttargetUnit = tile->getUnit();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!targetUnit && weapon->getAllowTargetSelf())\n\t\t\t{\n\t\t\t\ttargetUnit = _action->actor;\n\t\t\t}\n\t\t\tif (targetUnit)\n\t\t\t{\n\t\t\t\t_game->popState();\n\t\t\t\tBattleMediKitType type = weapon->getMediKitType();\n\t\t\t\tif (type)\n\t\t\t\t{\n\t\t\t\t\tif ((type == BMT_HEAL && _action->weapon->getHealQuantity() > 0) ||\n\t\t\t\t\t\t(type == BMT_STIMULANT && _action->weapon->getStimulantQuantity() > 0) ||\n\t\t\t\t\t\t(type == BMT_PAINKILLER && _action->weapon->getPainKillerQuantity() > 0))\n\t\t\t\t\t{\n\t\t\t\t\t\tif (_action->spendTU(&_action->result))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tswitch (type)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcase BMT_HEAL:\n\t\t\t\t\t\t\t\tif (targetUnit->getFatalWounds())\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tfor (int i = 0; i < BODYPART_MAX; ++i)\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tif (targetUnit->getFatalWound((UnitBodyPart)i))\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\ttileEngine->medikitUse(_action, targetUnit, BMA_HEAL, (UnitBodyPart)i);\n\t\t\t\t\t\t\t\t\t\t\ttileEngine->medikitRemoveIfEmpty(_action);\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\ttileEngine->medikitUse(_action, targetUnit, BMA_HEAL, BODYPART_TORSO);\n\t\t\t\t\t\t\t\t\ttileEngine->medikitRemoveIfEmpty(_action);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase BMT_STIMULANT:\n\t\t\t\t\t\t\t\ttileEngine->medikitUse(_action, targetUnit, BMA_STIMULANT, BODYPART_TORSO);\n\t\t\t\t\t\t\t\ttileEngine->medikitRemoveIfEmpty(_action);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase BMT_PAINKILLER:\n\t\t\t\t\t\t\t\ttileEngine->medikitUse(_action, targetUnit, BMA_PAINKILLER, BODYPART_TORSO);\n\t\t\t\t\t\t\t\ttileEngine->medikitRemoveIfEmpty(_action);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase BMT_NORMAL:\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t_action->result = \"STR_NO_USES_LEFT\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t_game->pushState(new MedikitState(targetUnit, _action, tileEngine));\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_action->result = \"STR_THERE_IS_NO_ONE_THERE\";\n\t\t\t\t_game->popState();\n\t\t\t}\n\t\t}\n\t\telse if (_action->type == BA_USE && weapon->getBattleType() == BT_SCANNER)\n\t\t{\n\t\t\t// spend TUs first, then show the scanner\n\t\t\tif (_action->spendTU(&_action->result))\n\t\t\t{\n\t\t\t\t_game->popState();\n\t\t\t\t_game->pushState (new ScannerState(_action));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_game->popState();\n\t\t\t}\n\t\t}\n\t\telse if (_action->type == BA_LAUNCH)\n\t\t{\n\t\t\t// check beforehand if we have enough time units\n\t\t\tif (!_action->haveTU(&_action->result))\n\t\t\t{\n\t\t\t\t//nothing\n\t\t\t}\n\t\t\telse if (!_action->weapon->getAmmoForAction(BA_LAUNCH, &_action->result))\n\t\t\t{\n\t\t\t\t//nothing\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_action->targeting = true;\n\t\t\t\tnewHitLog = true;\n\t\t\t}\n\t\t\t_game->popState();\n\t\t}\n\t\telse if (_action->type == BA_HIT)\n\t\t{\n\t\t\t// check beforehand if we have enough time units\n\t\t\tif (!_action->haveTU(&_action->result))\n\t\t\t{\n\t\t\t\t//nothing\n\t\t\t}\n\t\t\telse if (!_game->getSavedGame()->getSavedBattle()->getTileEngine()->validMeleeRange(\n\t\t\t\t_action->actor->getPosition(),\n\t\t\t\t_action->actor->getDirection(),\n\t\t\t\t_action->actor,\n\t\t\t\t0, &_action->target))\n\t\t\t{\n\t\t\t\tif (!_game->getSavedGame()->getSavedBattle()->getTileEngine()->validTerrainMeleeRange(_action))\n\t\t\t\t{\n\t\t\t\t\t_action->result = \"STR_THERE_IS_NO_ONE_THERE\";\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tnewHitLog = true;\n\t\t\t}\n\t\t\t_game->popState();\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_action->targeting = true;\n\t\t\tnewHitLog = true;\n\t\t\t_game->popState();\n\t\t}\n\n\t\t// meleeAttackBState won't be available to clear the action type, do it here instead.\n\t\tif (_action->type == BA_HIT && !_action->result.empty())\n\t\t{\n\t\t\t_action->type = BA_NONE;\n\t\t}\n\n\t\tif (newHitLog)\n\t\t{\n\t\t\t_game->getSavedGame()->getSavedBattle()->appendToHitLog(HITLOG_PLAYER_FIRING, FACTION_PLAYER, tr(weapon->getType()));\n\t\t}\n\t}\n}\n\n/**\n * Updates the scale.\n * @param dX delta of X;\n * @param dY delta of Y;\n */\nvoid ActionMenuState::resize(int &dX, int &dY)\n{\n\tState::recenter(dX, dY * 2);\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/ActionMenuState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http:///www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include \"BattlescapeGame.h\"\n\nnamespace OpenXcom\n{\n\nclass ActionMenuItem;\n\n/**\n * Window that allows the player\n * to select a battlescape action.\n */\nclass ActionMenuState : public State\n{\nprotected:\n\tBattleAction *_action;\n\tActionMenuItem *_actionMenu[6];\n\t/// Adds a new menu item for an action.\n\tvoid addItem(BattleActionType ba, const std::string &name, int *id, SDLKey key);\n\t/// Acts on the action instance that has been chosen and set.\n\tvoid handleAction();\npublic:\n\t/// Default constructor, used by SkillMenuState.\n\tActionMenuState(BattleAction *action);\n\t/// Creates the Action Menu state.\n\tActionMenuState(BattleAction *action, int x, int y);\n\t/// Cleans up the Action Menu state.\n\t~ActionMenuState();\n\t/// Init function.\n\tvoid init() override;\n\t/// Handler for right-clicking anything.\n\tvoid handle(Action *action) override;\n\t/// Handler for clicking a action menu item.\n\tvirtual void btnActionMenuItemClick(Action *action);\n\t/// Update the resolution settings, we just resized the window.\n\tvoid resize(int &dX, int &dY) override;\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/AlienInventory.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"AlienInventory.h\"\n#include <cmath>\n#include \"../Engine/Action.h\"\n#include \"../Engine/Font.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Language.h\"\n#include \"../Engine/Screen.h\"\n#include \"../Engine/SurfaceSet.h\"\n#include \"../Engine/Timer.h\"\n#include \"../Interface/Text.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleInventory.h\"\n#include \"../Mod/RuleInterface.h\"\n#include \"../Savegame/BattleUnit.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Ufopaedia/Ufopaedia.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Sets up an inventory with the specified size and position.\n * @param game Pointer to core game.\n * @param width Width in pixels.\n * @param height Height in pixels.\n * @param x X position in pixels.\n * @param y Y position in pixels.\n */\nAlienInventory::AlienInventory(Game *game, int width, int height, int x, int y) : InteractiveSurface(width, height, x, y), _game(game), _selUnit(0), _dynamicOffset(0), _animFrame(0)\n{\n\t_grid = new Surface(width, height, 0, 0);\n\t_items = new Surface(width, height, 0, 0);\n\n\t_animTimer = new Timer(100);\n\t_animTimer->onTimer((SurfaceHandler)&AlienInventory::animate);\n\t_animTimer->start();\n}\n\n/**\n * Deletes inventory surfaces.\n */\nAlienInventory::~AlienInventory()\n{\n\tdelete _grid;\n\tdelete _items;\n\tdelete _animTimer;\n}\n\n/**\n * Replaces a certain amount of colors in the inventory's palette.\n * @param colors Pointer to the set of colors.\n * @param firstcolor Offset of the first color to replace.\n * @param ncolors Amount of colors to replace.\n */\nvoid AlienInventory::setPalette(const SDL_Color *colors, int firstcolor, int ncolors)\n{\n\tSurface::setPalette(colors, firstcolor, ncolors);\n\t_grid->setPalette(colors, firstcolor, ncolors);\n\t_items->setPalette(colors, firstcolor, ncolors);\n}\n\n/**\n * Returns the currently selected (i.e. displayed) unit.\n * @return Pointer to selected unit, or 0 if none.\n */\nBattleUnit *AlienInventory::getSelectedUnit() const\n{\n\treturn _selUnit;\n}\n\n/**\n * Changes the unit to display the inventory of.\n * @param unit Pointer to battle unit.\n */\nvoid AlienInventory::setSelectedUnit(BattleUnit *unit)\n{\n\t_selUnit = unit;\n\t_dynamicOffset = 0;\n\tif (unit && unit->isBigUnit())\n\t{\n\t\t_dynamicOffset = _game->getMod()->getAlienInventoryOffsetBigUnit();\n\t}\n}\n\n/**\n * Draws the inventory elements.\n */\nvoid AlienInventory::draw()\n{\n\tdrawGrid();\n\tdrawItems();\n}\n\n/**\n * Draws the inventory grid.\n */\nvoid AlienInventory::drawGrid()\n{\n\t_grid->clear();\n\tRuleInterface *rule = _game->getMod()->getInterface(\"inventory\");\n\tUint8 color = rule->getElement(\"grid\")->color;\n\n\tfor (const auto& pair : *_game->getMod()->getInventories())\n\t{\n\t\tif (pair.second->getType() == INV_HAND)\n\t\t{\n\t\t\tSDL_Rect r;\n\t\t\tr.x = pair.second->getX();\n\t\t\tr.x += _game->getMod()->getAlienInventoryOffsetX();\n\n\t\t\tif (pair.second->isRightHand())\n\t\t\t\tr.x -= _dynamicOffset;\n\t\t\telse if (pair.second->isLeftHand())\n\t\t\t\tr.x += _dynamicOffset;\n\n\t\t\tr.y = pair.second->getY();\n\t\t\tr.w = RuleInventory::HAND_W * RuleInventory::SLOT_W;\n\t\t\tr.h = RuleInventory::HAND_H * RuleInventory::SLOT_H;\n\t\t\t_grid->drawRect(&r, color);\n\t\t\tr.x++;\n\t\t\tr.y++;\n\t\t\tr.w -= 2;\n\t\t\tr.h -= 2;\n\t\t\t_grid->drawRect(&r, 0);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\t}\n}\n\n/**\n * Draws the items contained in the alien's hands.\n */\nvoid AlienInventory::drawItems()\n{\n\tconst SavedBattleGame* save = _game->getSavedGame()->getSavedBattle();\n\tScriptWorkerBlit work;\n\t_items->clear();\n\tif (_selUnit != 0)\n\t{\n\t\tSurfaceSet *texture = _game->getMod()->getSurfaceSet(\"BIGOBS.PCK\");\n\t\tfor (const auto* item : *_selUnit->getInventory())\n\t\t{\n\t\t\tif (item->getSlot()->getType() == INV_HAND)\n\t\t\t{\n\t\t\t\tconst Surface* frame = item->getBigSprite(texture, save, _animFrame);\n\n\t\t\t\tif (!frame)\n\t\t\t\t\tcontinue;\n\n\t\t\t\tint x = item->getSlot()->getX() + item->getRules()->getHandSpriteOffX();\n\t\t\t\tx += _game->getMod()->getAlienInventoryOffsetX();\n\n\t\t\t\tif (item->getSlot()->isRightHand())\n\t\t\t\t\tx -= _dynamicOffset;\n\t\t\t\telse if (item->getSlot()->isLeftHand())\n\t\t\t\t\tx += _dynamicOffset;\n\n\t\t\t\tint y = item->getSlot()->getY() + item->getRules()->getHandSpriteOffY();\n\n\t\t\t\tBattleItem::ScriptFill(&work, item, save, BODYPART_ITEM_INVENTORY, _animFrame, 0);\n\t\t\t\twork.executeBlit(frame, _items, x, y, 0);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Gets the inventory slot located in the specified mouse position.\n * @param x Mouse X position. Returns the slot's X position.\n * @param y Mouse Y position. Returns the slot's Y position.\n * @return Slot rules, or NULL if none.\n */\nRuleInventory *AlienInventory::getSlotInPosition(int *x, int *y) const\n{\n\tfor (const auto& pair : *_game->getMod()->getInventories())\n\t{\n\t\tif (pair.second->checkSlotInPosition(x, y))\n\t\t{\n\t\t\treturn pair.second;\n\t\t}\n\t}\n\treturn 0;\n}\n\n/**\n * Blits the inventory elements.\n * @param surface Pointer to surface to blit onto.\n */\nvoid AlienInventory::blit(SDL_Surface *surface)\n{\n\tclear();\n\t_grid->blitNShade(this, 0, 0);\n\t_items->blitNShade(this, 0, 0);\n\tSurface::blit(surface);\n}\n\n/**\n * Item info.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid AlienInventory::mouseClick(Action *action, State *state)\n{\n\tif (_game->isLeftClick(action))\n\t{\n\t\t_game->popState();\n\t}\n\telse if (_game->isRightClick(action))\n\t{\n\t\t_game->popState();\n\t}\n\telse if (_game->isMiddleClick(action))\n\t{\n\t\tif (_selUnit == 0)\n\t\t\treturn;\n\n\t\tint x = (int)floor(action->getAbsoluteXMouse()) - getX(),\n\t\t\ty = (int)floor(action->getAbsoluteYMouse()) - getY();\n\n\t\tif (x >= Screen::ORIGINAL_WIDTH / 2)\n\t\t\tx -= _dynamicOffset;\n\t\telse\n\t\t\tx += _dynamicOffset;\n\n\t\tx -= _game->getMod()->getAlienInventoryOffsetX();\n\n\t\tRuleInventory *slot = getSlotInPosition(&x, &y);\n\t\tif (slot != 0)\n\t\t{\n\t\t\tif (slot->getType() == INV_HAND)\n\t\t\t{\n\t\t\t\tBattleItem *item = _selUnit->getItem(slot, x, y);\n\t\t\t\tif (item != 0)\n\t\t\t\t{\n\t\t\t\t\tstd::string articleId = item->getRules()->getUfopediaType();\n\t\t\t\t\tUfopaedia::openArticle(_game, articleId);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tInteractiveSurface::mouseClick(action, state);\n}\n\n/**\n * Handles timers.\n */\nvoid AlienInventory::think()\n{\n\t_animTimer->think(0, this);\n}\n\n/**\n * Animate surface.\n */\nvoid AlienInventory::animate()\n{\n\t_animFrame++;\n\n\tdrawItems();\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/AlienInventory.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/InteractiveSurface.h\"\n\nnamespace OpenXcom\n{\n\nclass RuleInventory;\nclass Game;\nclass BattleUnit;\nclass Timer;\n\n/**\n * View of an alien inventory.\n * Lets the player view alien's equipment (in hand only).\n */\nclass AlienInventory : public InteractiveSurface\n{\nprivate:\n\tGame *_game;\n\tSurface *_grid, *_items;\n\tBattleUnit *_selUnit;\n\tint _dynamicOffset;\n\tint _animFrame;\n\tTimer* _animTimer;\n\t/// Gets the slot in the specified position.\n\tRuleInventory *getSlotInPosition(int *x, int *y) const;\npublic:\n\t/// Creates a new inventory view at the specified position and size.\n\tAlienInventory(Game *game, int width, int height, int x = 0, int y = 0);\n\t/// Cleans up the inventory.\n\t~AlienInventory();\n\t/// Sets the inventory's palette.\n\tvoid setPalette(const SDL_Color *colors, int firstcolor = 0, int ncolors = 256) override;\n\t/// Gets the inventory's selected unit.\n\tBattleUnit *getSelectedUnit() const;\n\t/// Sets the inventory's selected unit.\n\tvoid setSelectedUnit(BattleUnit *unit);\n\t/// Draws the inventory.\n\tvoid draw() override;\n\t/// Draws the inventory grid.\n\tvoid drawGrid();\n\t/// Draws the inventory items.\n\tvoid drawItems();\n\t/// Blits the inventory onto another surface.\n\tvoid blit(SDL_Surface *surface) override;\n\t/// Special handling for mouse clicks.\n\tvoid mouseClick(Action *action, State *state) override;\n\t/// Handles timers.\n\tvoid think() override;\n\t/// Animate surface.\n\tvoid animate();\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/AlienInventoryState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"AlienInventoryState.h\"\n#include \"AlienInventory.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Screen.h\"\n#include \"../Engine/Surface.h\"\n#include \"../Interface/BattlescapeButton.h\"\n#include \"../Interface/Text.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Mod/RuleInterface.h\"\n#include \"../Mod/RuleSoldier.h\"\n#include \"../Ufopaedia/Ufopaedia.h\"\n#include \"../Savegame/BattleUnit.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Battlescape/TileEngine.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the AlienInventory screen.\n * @param unit Pointer to the alien unit.\n */\nAlienInventoryState::AlienInventoryState(BattleUnit *unit)\n{\n\tif (Options::maximizeInfoScreens)\n\t{\n\t\tOptions::baseXResolution = Screen::ORIGINAL_WIDTH;\n\t\tOptions::baseYResolution = Screen::ORIGINAL_HEIGHT;\n\t\t_game->getScreen()->resetDisplay(false);\n\t}\n\n\t// Create objects\n\t_bg = new Surface(320, 200, 0, 0);\n\tint offsetX = _game->getMod()->getAlienInventoryOffsetX();\n\t_soldier = new Surface(320 - offsetX, 200, offsetX, 0);\n\t_txtName = new Text(308, 17, 6, 6);\n\t_txtFatalWounds = new Text(100, 48, 6, 32);\n\t_txtLeftHand = new Text(308, 17, 6, 160);\n\t_txtRightHand = new Text(308, 17, 6, 180);\n\t_btnArmor = new BattlescapeButton(40, 70, 140, 65);\n\t_inv = new AlienInventory(_game, 320, 200, 0, 0);\n\n\t// Set palette\n\tsetStandardPalette(\"PAL_BATTLESCAPE\");\n\n\tadd(_bg);\n\tadd(_soldier);\n\tadd(_txtName, \"textName\", \"inventory\", _bg);\n\tadd(_txtFatalWounds, \"textName\", \"inventory\", _bg);\n\tadd(_txtLeftHand, \"textName\", \"inventory\", _bg);\n\tadd(_txtRightHand, \"textName\", \"inventory\", _bg);\n\tadd(_btnArmor, \"buttonOK\", \"inventory\", _bg);\n\tadd(_inv);\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tSurface *tmp = _game->getMod()->getSurface(\"AlienInventory2\", false);\n\tif (!tmp || !unit->getGeoscapeSoldier())\n\t{\n\t\ttmp = _game->getMod()->getSurface(\"AlienInventory\", false);\n\t}\n\tif (tmp)\n\t{\n\t\ttmp->blitNShade(_bg, 0, 0);\n\t}\n\n\t_txtName->setBig();\n\t_txtName->setHighContrast(true);\n\t_txtName->setAlign(ALIGN_CENTER);\n\n\tif (Options::oxceDisableAlienInventory)\n\t{\n\t\t_txtName->setHeight(_txtName->getHeight() * 9);\n\t\t_txtName->setWordWrap(true);\n\t\t_txtName->setText(tr(\"STR_THIS_FEATURE_IS_DISABLED_5\"));\n\t\t_soldier->setVisible(false);\n\t\t_txtLeftHand->setVisible(false);\n\t\t_txtRightHand->setVisible(false);\n\t\t_btnArmor->onKeyboardPress((ActionHandler)&AlienInventoryState::btnOkClick, Options::keyCancel);\n\t\t_inv->setVisible(false);\n\t\treturn;\n\t}\n\n\tif (unit->getOriginalFaction() == FACTION_NEUTRAL)\n\t{\n\t\t_txtName->setText(tr(unit->getType()));\n\t}\n\telse\n\t{\n\t\tif (unit->getUnitRules())\n\t\t{\n\t\t\tif (unit->getUnitRules()->getShowFullNameInAlienInventory(_game->getMod()))\n\t\t\t{\n\t\t\t\t// e.g. Sectoid Leader\n\t\t\t\t_txtName->setText(unit->getName(_game->getLanguage()));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// e.g. Sectoid\n\t\t\t\t_txtName->setText(tr(unit->getUnitRules()->getRace()));\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// Soldier names\n\t\t\t_txtName->setText(unit->getName(_game->getLanguage()));\n\t\t}\n\t}\n\n\t_txtFatalWounds->setHighContrast(true);\n\n\t_txtLeftHand->setBig();\n\t_txtLeftHand->setHighContrast(true);\n\t_txtLeftHand->setAlign(ALIGN_CENTER);\n\t_txtLeftHand->setVisible(false);\n\n\t_txtRightHand->setBig();\n\t_txtRightHand->setHighContrast(true);\n\t_txtRightHand->setAlign(ALIGN_CENTER);\n\t_txtRightHand->setVisible(false);\n\n\t_btnArmor->onKeyboardPress((ActionHandler)&AlienInventoryState::btnToggleClick, SDLK_F1);\n\t_btnArmor->onKeyboardPress((ActionHandler)&AlienInventoryState::btnOkClick, Options::keyCancel);\n\t_btnArmor->onMouseClick((ActionHandler)&AlienInventoryState::btnArmorClickMiddle, SDL_BUTTON_MIDDLE);\n\n\t_soldier->clear();\n\n\tSoldier *s = unit->getGeoscapeSoldier();\n\tif (s)\n\t{\n\t\tif (s->getArmor()->hasLayersDefinition())\n\t\t{\n\t\t\tfor (const auto& layer : s->getArmorLayers())\n\t\t\t{\n\t\t\t\tauto* surf = _game->getMod()->getSurface(layer, true);\n\t\t\t\tsurf->blitNShade(_soldier->getSurface(), 0, 0);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tconst std::string look = s->getArmor()->getSpriteInventory();\n\t\t\tconst std::string gender = s->getGender() == GENDER_MALE ? \"M\" : \"F\";\n\t\t\tstd::stringstream ss;\n\t\t\tSurface *surf = 0;\n\n\t\t\tfor (int i = 0; i <= RuleSoldier::LookVariantBits; ++i)\n\t\t\t{\n\t\t\t\tss.str(\"\");\n\t\t\t\tss << look;\n\t\t\t\tss << gender;\n\t\t\t\tss << (int)s->getLook() + (s->getLookVariant() & (RuleSoldier::LookVariantMask >> i)) * 4;\n\t\t\t\tss << \".SPK\";\n\t\t\t\tsurf = _game->getMod()->getSurface(ss.str(), false);\n\t\t\t\tif (surf)\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!surf)\n\t\t\t{\n\t\t\t\tss.str(\"\");\n\t\t\t\tss << look;\n\t\t\t\tss << \".SPK\";\n\t\t\t\tsurf = _game->getMod()->getSurface(ss.str(), false);\n\t\t\t}\n\t\t\tif (!surf)\n\t\t\t{\n\t\t\t\tsurf = _game->getMod()->getSurface(look, true);\n\t\t\t}\n\t\t\tsurf->blitNShade(_soldier, 0, 0);\n\t\t}\n\t}\n\telse\n\t{\n\t\tSurface *armorSurface = _game->getMod()->getSurface(unit->getArmor()->getSpriteInventory(), false);\n\t\tif (!armorSurface)\n\t\t{\n\t\t\tarmorSurface = _game->getMod()->getSurface(unit->getArmor()->getSpriteInventory() + \".SPK\", false);\n\t\t}\n\t\tif (!armorSurface)\n\t\t{\n\t\t\tarmorSurface = _game->getMod()->getSurface(unit->getArmor()->getSpriteInventory() + \"M0.SPK\", false);\n\t\t}\n\t\tif (armorSurface)\n\t\t{\n\t\t\tarmorSurface->blitNShade(_soldier, 0, 0);\n\t\t}\n\t}\n\n\t_inv->setSelectedUnit(unit);\n\t_inv->draw();\n\n\t// Bleeding indicator\n\ttmp = _game->getMod()->getSurface(\"BigWoundIndicator\", false);\n\tif (tmp && unit->getFatalWounds() > 0 && unit->indicatorsAreEnabled())\n\t{\n\t\ttmp->blitNShade(_soldier, 32, 32);\n\n\t\tconst Element* element = _game->getMod()->getInterface(\"inventory\")->getElementOptional(\"textName\");\n\t\tif (element && element->custom == 0)\n\t\t{\n\t\t\t// fatally wounded body parts\n\t\t\tstd::ostringstream ss;\n\t\t\tfor (int i = 0; i < BODYPART_MAX; ++i)\n\t\t\t{\n\t\t\t\tif (unit->getFatalWound((UnitBodyPart)i))\n\t\t\t\t{\n\t\t\t\t\tss << _game->getLanguage()->getString(PARTS_STRING[i]);\n\t\t\t\t\tss << \"\\n\";\n\t\t\t\t}\n\t\t\t}\n\t\t\t_txtFatalWounds->setText(ss.str());\n\t\t}\n\t}\n\n\t// Burning indicator\n\ttmp = _game->getMod()->getSurface(\"BigBurnIndicator\", false);\n\tif (tmp && unit->getFire() > 0 && unit->indicatorsAreEnabled())\n\t{\n\t\ttmp->blitNShade(_soldier, 112, 32);\n\t}\n\n\t// --------------------- DEBUG INDICATORS ---------------------\n\tif (!Options::debug)\n\t\treturn;\n\n\tauto* weaponL = unit->getLeftHandWeapon();\n\tif (!weaponL)\n\t{\n\t\tauto typesToCheck = { BT_MELEE, BT_FIREARM };\n\t\tfor (auto& type : typesToCheck)\n\t\t{\n\t\t\tweaponL = unit->getSpecialWeapon(type);\n\t\t\tif (weaponL && weaponL->getRules()->isSpecialUsingEmptyHand())\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tweaponL = nullptr;\n\t\t}\n\t}\n\tif (weaponL)\n\t{\n\t\tif (weaponL->getRules()->getBattleType() == BT_FIREARM)\n\t\t{\n\t\t\tcalculateRangedWeapon(unit, weaponL, _txtLeftHand);\n\t\t}\n\t\telse if (weaponL->getRules()->getBattleType() == BT_MELEE)\n\t\t{\n\t\t\tcalculateMeleeWeapon(unit, weaponL, _txtLeftHand);\n\t\t}\n\t}\n\n\tauto* weaponR = unit->getRightHandWeapon();\n\tif (!weaponR)\n\t{\n\t\tauto typesToCheck = { BT_MELEE, BT_FIREARM };\n\t\tfor (auto& type : typesToCheck)\n\t\t{\n\t\t\tweaponR = unit->getSpecialWeapon(type);\n\t\t\tif (weaponR && weaponR->getRules()->isSpecialUsingEmptyHand())\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tweaponR = nullptr;\n\t\t}\n\t}\n\tif (weaponR)\n\t{\n\t\tif (weaponR->getRules()->getBattleType() == BT_FIREARM)\n\t\t{\n\t\t\tcalculateRangedWeapon(unit, weaponR, _txtRightHand);\n\t\t}\n\t\telse if (weaponR->getRules()->getBattleType() == BT_MELEE)\n\t\t{\n\t\t\tcalculateMeleeWeapon(unit, weaponR, _txtRightHand);\n\t\t}\n\t}\n}\n\n/**\n *\n */\nAlienInventoryState::~AlienInventoryState()\n{\n\tif (Options::maximizeInfoScreens)\n\t{\n\t\tScreen::updateScale(Options::battlescapeScale, Options::baseXBattlescape, Options::baseYBattlescape, true);\n\t\t_game->getScreen()->resetDisplay(false);\n\t}\n}\n\nvoid AlienInventoryState::calculateMeleeWeapon(BattleUnit* unit, BattleItem* weapon, Text* label)\n{\n\tstd::ostringstream ss;\n\n\tTileEngine* tileEngine = _game->getSavedGame()->getSavedBattle()->getTileEngine();\n\n\t// Start by finding the target for the check\n\tint surroundingTilePositions[8][2] = {\n\t\t{0, -1}, // north (-y direction)\n\t\t{1, -1}, // northeast\n\t\t{1, 0}, // east (+ x direction)\n\t\t{1, 1}, // southeast\n\t\t{0, 1}, // south (+y direction)\n\t\t{-1, 1}, // southwest\n\t\t{-1, 0}, // west (-x direction)\n\t\t{-1, -1} }; // northwest\n\n\tPosition tileToCheck = unit->getPosition();\n\tint dir = unit->getDirection();\n\ttileToCheck.x += surroundingTilePositions[dir][0];\n\ttileToCheck.y += surroundingTilePositions[dir][1];\n\tBattleUnit* meleeDodgeTarget = nullptr;\n\tif (_game->getSavedGame()->getSavedBattle()->getTile(tileToCheck)) // Make sure the tile is in bounds\n\t{\n\t\tmeleeDodgeTarget = _game->getSavedGame()->getSavedBattle()->selectUnit(tileToCheck);\n\t}\n\n\tss << tr(weapon->getRules()->getType()) << \" > \";\n\tif (meleeDodgeTarget)\n\t{\n\t\tBattleActionAttack attack;\n\t\tattack.type = BA_HIT;\n\t\tattack.attacker = unit;\n\t\tattack.weapon_item = weapon;\n\t\tattack.damage_item = weapon;\n\t\tattack.skill_rules = nullptr;\n\t\tint hitChance = BattleUnit::getFiringAccuracy(attack, _game->getMod());\n\n\t\tBattleUnit* victim = meleeDodgeTarget;\n\t\tif (victim)\n\t\t{\n\t\t\tint arc = tileEngine->getArcDirection(tileEngine->getDirectionTo(victim->getPositionVexels(), unit->getPositionVexels()), victim->getDirection());\n\t\t\tfloat penalty = 1.0f - arc * victim->getArmor()->getMeleeDodgeBackPenalty() / 4.0f;\n\t\t\tif (penalty > 0)\n\t\t\t{\n\t\t\t\thitChance -= victim->getArmor()->getMeleeDodge(victim) * penalty;\n\t\t\t}\n\t\t}\n\t\tss << \"hitChance \" << hitChance << \"% \";\n\t}\n\telse\n\t{\n\t\tss << \"not facing target \";\n\t}\n\n\tlabel->setText(ss.str());\n}\n\nvoid AlienInventoryState::calculateRangedWeapon(BattleUnit* unit, BattleItem* weapon, Text* label)\n{\n\tstd::ostringstream ss;\n\n\tTileEngine* tileEngine = _game->getSavedGame()->getSavedBattle()->getTileEngine();\n\n\t// Start by finding 'targets' for the check\n\tstd::vector<BattleUnit*> closeQuartersTargetList;\n\tint surroundingTilePositions[8][2] = {\n\t\t{0, -1}, // north (-y direction)\n\t\t{1, -1}, // northeast\n\t\t{1, 0}, // east (+ x direction)\n\t\t{1, 1}, // southeast\n\t\t{0, 1}, // south (+y direction)\n\t\t{-1, 1}, // southwest\n\t\t{-1, 0}, // west (-x direction)\n\t\t{-1, -1} }; // northwest\n\n\tfor (int dir = 0; dir < 8; dir++)\n\t{\n\t\tPosition tileToCheck = unit->getPosition();\n\t\ttileToCheck.x += surroundingTilePositions[dir][0];\n\t\ttileToCheck.y += surroundingTilePositions[dir][1];\n\n\t\tif (_game->getSavedGame()->getSavedBattle()->getTile(tileToCheck)) // Make sure the tile is in bounds\n\t\t{\n\t\t\tBattleUnit* closeQuartersTarget = _game->getSavedGame()->getSavedBattle()->selectUnit(tileToCheck);\n\t\t\t// Variable for LOS check\n\t\t\tint checkDirection = tileEngine->getDirectionTo(tileToCheck, unit->getPosition());\n\t\t\tif (closeQuartersTarget && unit->getFaction() != closeQuartersTarget->getFaction() // Unit must exist and not be same faction\n\t\t\t\t&& closeQuartersTarget->getArmor()->getCreatesMeleeThreat() // Unit must be valid defender, 2x2 default false here\n\t\t\t\t&& closeQuartersTarget->getTimeUnits() >= _game->getMod()->getCloseQuartersTuCostGlobal() // Unit must have enough TUs\n\t\t\t\t&& closeQuartersTarget->getEnergy() >= _game->getMod()->getCloseQuartersEnergyCostGlobal() // Unit must have enough Energy\n\t\t\t\t&& tileEngine->validMeleeRange(closeQuartersTarget, unit, checkDirection) // Unit must be able to see the unit attempting to fire\n\t\t\t\t&& !(unit->getFaction() == FACTION_PLAYER && closeQuartersTarget->getFaction() == FACTION_NEUTRAL) // Civilians don't inhibit player\n\t\t\t\t&& !(unit->getFaction() == FACTION_NEUTRAL && closeQuartersTarget->getFaction() == FACTION_PLAYER)) // Player doesn't inhibit civilians\n\t\t\t{\n\t\t\t\tcloseQuartersTargetList.push_back(closeQuartersTarget);\n\t\t\t}\n\t\t}\n\t}\n\n\tss << tr(weapon->getRules()->getType()) << \" > \";\n\tif (!closeQuartersTargetList.empty())\n\t{\n\t\tfor (const auto* victim : closeQuartersTargetList)\n\t\t{\n\t\t\t{\n\t\t\t\tBattleActionAttack attack;\n\t\t\t\tattack.type = BA_CQB;\n\t\t\t\tattack.attacker = unit;\n\t\t\t\tattack.weapon_item = weapon;\n\t\t\t\tattack.damage_item = weapon;\n\t\t\t\tattack.skill_rules = nullptr;\n\t\t\t\tint hitChance = BattleUnit::getFiringAccuracy(attack, _game->getMod());\n\n\t\t\t\tif (victim)\n\t\t\t\t{\n\t\t\t\t\tint arc = tileEngine->getArcDirection(tileEngine->getDirectionTo(victim->getPositionVexels(), unit->getPositionVexels()), victim->getDirection());\n\t\t\t\t\tfloat penalty = 1.0f - arc * victim->getArmor()->getMeleeDodgeBackPenalty() / 4.0f;\n\t\t\t\t\tif (penalty > 0)\n\t\t\t\t\t{\n\t\t\t\t\t\thitChance -= victim->getArmor()->getMeleeDodge(victim) * penalty;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tss << \"cqcChance \" << hitChance << \"% \";\n\t\t\t}\n\t\t}\n\t}\n\n\tlabel->setText(ss.str());\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid AlienInventoryState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Toggles debug indicators.\n * @param action Pointer to an action.\n */\nvoid AlienInventoryState::btnToggleClick(Action *)\n{\n\t_txtLeftHand->setVisible(!_txtLeftHand->getVisible());\n\t_txtRightHand->setVisible(!_txtRightHand->getVisible());\n}\n\n/**\n * Opens Ufopaedia entry for the corresponding armor.\n * @param action Pointer to an action.\n */\nvoid AlienInventoryState::btnArmorClickMiddle(Action *action)\n{\n\tBattleUnit *unit = _inv->getSelectedUnit();\n\tif (unit != 0)\n\t{\n\t\tstd::string articleId = unit->getArmor()->getUfopediaType();\n\t\tUfopaedia::openArticle(_game, articleId);\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/AlienInventoryState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass Surface;\nclass BattlescapeButton;\nclass AlienInventory;\nclass BattleItem;\nclass BattleUnit;\nclass Text;\n\n/**\n * Screen which displays alien's inventory.\n */\nclass AlienInventoryState : public State\n{\nprivate:\n\tSurface *_bg, *_soldier;\n\tBattlescapeButton *_btnArmor;\n\tText *_txtName;\n\tText *_txtFatalWounds;\n\tText *_txtLeftHand, *_txtRightHand;\n\tAlienInventory *_inv;\n\n\tvoid calculateMeleeWeapon(BattleUnit* unit, BattleItem* weapon, Text* label);\n\tvoid calculateRangedWeapon(BattleUnit* unit, BattleItem* weapon, Text* label);\npublic:\n\t/// Creates the AlienInventory state.\n\tAlienInventoryState(BattleUnit *unit);\n\t/// Cleans up the AlienInventory state.\n\t~AlienInventoryState();\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the [Toggle] button.\n\tvoid btnToggleClick(Action *action);\n\t/// Handler for clicking the Armor button.\n\tvoid btnArmorClickMiddle(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/AliensCrashState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"AliensCrashState.h\"\n#include \"DebriefingState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Engine/Options.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Aliens Crash screen.\n * @param game Pointer to the core game.\n */\nAliensCrashState::AliensCrashState()\n{\n\t// Create objects\n\t_window = new Window(this, 256, 160, 32, 20);\n\t_btnOk = new TextButton(120, 18, 100, 154);\n\t_txtTitle = new Text(246, 80, 37, 50);\n\n\t// Set palette\n\tsetStandardPalette(\"PAL_BATTLESCAPE\");\n\n\tadd(_window, \"messageWindowBorder\", \"battlescape\");\n\tadd(_btnOk, \"messageWindowButtons\", \"battlescape\");\n\tadd(_txtTitle, \"messageWindows\", \"battlescape\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\t_window->setHighContrast(true);\n\t_window->setBackground(_game->getMod()->getSurface(\"TAC00.SCR\"));\n\n\t_btnOk->setHighContrast(true);\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&AliensCrashState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&AliensCrashState::btnOkClick, Options::keyOk);\n\t_btnOk->onKeyboardPress((ActionHandler)&AliensCrashState::btnOkClick, Options::keyCancel);\n\n\t_txtTitle->setHighContrast(true);\n\t_txtTitle->setText(tr(\"STR_ALL_ALIENS_KILLED_IN_CRASH\"));\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setVerticalAlign(ALIGN_MIDDLE);\n\t_txtTitle->setBig();\n\t_txtTitle->setWordWrap(true);\n}\n\n/**\n *\n */\nAliensCrashState::~AliensCrashState()\n{\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid AliensCrashState::btnOkClick(Action *)\n{\n\t_game->popState();\n\t_game->pushState(new DebriefingState);\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/AliensCrashState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\n\n/**\n * Screen shown when all aliens died\n * during a crash site.\n */\nclass AliensCrashState : public State\n{\nprivate:\n\tTextButton *_btnOk;\n\tWindow *_window;\n\tText *_txtTitle;\npublic:\n\t/// Creates the Aliens Crash state.\n\tAliensCrashState();\n\t/// Cleans up the Aliens Crash state.\n\t~AliensCrashState();\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/BattleState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"BattleState.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Sets up a BattleState.\n * @param parent Pointer to the parent state.\n * @param action Struct containing info about the action.\n */\nBattleState::BattleState(BattlescapeGame *parent, BattleAction action) : _parent(parent), _action(action)\n{\n\n}\n\n/**\n * Sets up a BattleState.\n * @param parent Pointer to the parent state.\n */\nBattleState::BattleState(BattlescapeGame *parent) : _parent(parent)\n{\n\t_action.result = \"\";\n\t_action.targeting = false;\n\t_action.clearTU();\n}\n\n\n/**\n * Deletes the BattleState.\n */\nBattleState::~BattleState()\n{\n\n}\n\n/**\n * Start the current BattleState.\n */\nvoid BattleState::init()\n{\n\n}\n\n/**\n * Called when the state gets popped out.\n */\nvoid BattleState::deinit()\n{\n\n}\n\n/**\n * Cancels the current BattleState.\n */\nvoid BattleState::cancel()\n{\n\n}\n\n/**\n * Runs any code the state needs to keep updating every\n * game cycle.\n */\nvoid BattleState::think()\n{\n\n}\n\n/**\n * Gets the action result. Returns error messages or an empty string when everything went fine.\n * @return Error or empty string when everything is fine.\n */\nconst BattleAction& BattleState::getAction() const\n{\n\treturn _action;\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/BattleState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"BattlescapeGame.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * This class sets the battlescape in a certain sub-state.\n * These states can be triggered by the player or the AI.\n */\nclass BattleState\n{\nprotected:\n\tBattlescapeGame *_parent;\n\tBattleAction _action;\npublic:\n\t/// Creates a new BattleState linked to the game.\n\tBattleState(BattlescapeGame *parent, BattleAction action);\n\t/// Creates a new BattleState linked to the game.\n\tBattleState(BattlescapeGame *parent);\n\t/// Cleans up the BattleState.\n\tvirtual ~BattleState();\n\t/// Initializes the state.\n\tvirtual void init();\n\t/// Called when the state gets popped out.\n\tvirtual void deinit();\n\t/// Handles a cancel request.\n\tvirtual void cancel();\n\t/// Runs state functionality every cycle.\n\tvirtual void think();\n\t/// Gets the action.\n\tconst BattleAction& getAction() const;\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/BattlescapeGame.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <sstream>\n#include \"BattlescapeGame.h\"\n#include \"BattlescapeState.h\"\n#include \"Map.h\"\n#include \"Camera.h\"\n#include \"NextTurnState.h\"\n#include \"BattleState.h\"\n#include \"UnitTurnBState.h\"\n#include \"UnitWalkBState.h\"\n#include \"ProjectileFlyBState.h\"\n#include \"MeleeAttackBState.h\"\n#include \"PsiAttackBState.h\"\n#include \"ExplosionBState.h\"\n#include \"TileEngine.h\"\n#include \"UnitInfoState.h\"\n#include \"UnitDieBState.h\"\n#include \"UnitPanicBState.h\"\n#include \"AIModule.h\"\n#include \"Pathfinding.h\"\n#include \"../Mod/AlienDeployment.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Language.h\"\n#include \"../Engine/Sound.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Interface/Cursor.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"../Savegame/Tile.h\"\n#include \"../Savegame/BattleUnit.h\"\n#include \"../Savegame/BattleItem.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"../Mod/RuleInventory.h\"\n#include \"../Mod/RuleSoldier.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/RNG.h\"\n#include \"InfoboxState.h\"\n#include \"InfoboxOKState.h\"\n#include \"UnitFallBState.h\"\n#include \"../Engine/Logger.h\"\n#include \"../Savegame/BattleUnitStatistics.h\"\n#include \"ConfirmEndMissionState.h\"\n#include \"../fmath.h\"\n\nnamespace OpenXcom\n{\n\nbool BattlescapeGame::_debugPlay = false;\n\n/**\n * Update value of TU and Energy\n */\nvoid BattleActionCost::updateTU()\n{\n\tif (actor && skillRules)\n\t{\n\t\t*(RuleItemUseCost*)this = actor->getActionTUs(type, skillRules);\n\t}\n\telse if (actor && weapon)\n\t{\n\t\t*(RuleItemUseCost*)this = actor->getActionTUs(type, weapon);\n\t}\n\telse\n\t{\n\t\tclearTU();\n\t}\n}\n\n/**\n * Clean up action cost.\n */\nvoid BattleActionCost::clearTU()\n{\n\t*(RuleItemUseCost*)this = RuleItemUseCost();\n}\n\n/**\n * Test if action can be performed.\n * @param message optional message with error condition.\n * @return Unit have enough stats to perform action.\n */\nbool BattleActionCost::haveTU(std::string *message)\n{\n\tif (!skillRules && Time <= 0)\n\t{\n\t\t//no action, no message\n\t\treturn false;\n\t}\n\tif (actor->getTimeUnits() < Time)\n\t{\n\t\tif (message)\n\t\t{\n\t\t\t*message = \"STR_NOT_ENOUGH_TIME_UNITS\";\n\t\t}\n\t\treturn false;\n\t}\n\tif (actor->getEnergy() < Energy)\n\t{\n\t\tif (message)\n\t\t{\n\t\t\t*message = \"STR_NOT_ENOUGH_ENERGY\";\n\t\t}\n\t\treturn false;\n\t}\n\tif (actor->getMorale() < Morale)\n\t{\n\t\tif (message)\n\t\t{\n\t\t\t*message = \"STR_NOT_ENOUGH_MORALE\";\n\t\t}\n\t\treturn false;\n\t}\n\tif (actor->getHealth() <= Health)\n\t{\n\t\tif (message)\n\t\t{\n\t\t\t*message = \"STR_NOT_ENOUGH_HEALTH\";\n\t\t}\n\t\treturn false;\n\t}\n\tif (actor->getMana() < Mana)\n\t{\n\t\tif (message)\n\t\t{\n\t\t\t*message = \"STR_NOT_ENOUGH_MANA\";\n\t\t}\n\t\treturn false;\n\t}\n\tif (actor->getHealth() - actor->getStunlevel() <= Stun + Health)\n\t{\n\t\tif (message)\n\t\t{\n\t\t\t*message = \"STR_NOT_ENOUGH_STUN\";\n\t\t}\n\t\treturn false;\n\t}\n\treturn true;\n}\n\n/**\n * Spend cost of action if unit have enough stats.\n * @param message optional message with error condition.\n * @return Action was performed.\n */\nbool BattleActionCost::spendTU(std::string *message)\n{\n\tif (haveTU(message))\n\t{\n\t\tactor->spendCost(*this);\n\t\treturn true;\n\t}\n\treturn false;\n}\n\n/**\n * Initializes all the elements in the Battlescape screen.\n * @param save Pointer to the save game.\n * @param parentState Pointer to the parent battlescape state.\n */\nBattlescapeGame::BattlescapeGame(SavedBattleGame *save, BattlescapeState *parentState) :\n\t_save(save), _parentState(parentState),\n\t_playerPanicHandled(true), _AIActionCounter(0), _AISecondMove(false), _playedAggroSound(false),\n\t_endTurnRequested(false), _endConfirmationHandled(false), _allEnemiesNeutralized(false)\n{\n\tif (_save->isPreview())\n\t{\n\t\t_allEnemiesNeutralized = true; // just in case\n\t}\n\n\t_currentAction.actor = 0;\n\t_currentAction.targeting = false;\n\t_currentAction.type = BA_NONE;\n\t_currentAction.skillRules = nullptr;\n\n\t_debugPlay = false;\n\n\tcheckForCasualties(nullptr, BattleActionAttack{ }, true);\n\tcancelCurrentAction();\n}\n\n\n/**\n * Delete BattlescapeGame.\n */\nBattlescapeGame::~BattlescapeGame()\n{\n\tfor (auto* bs : _states)\n\t{\n\t\tdelete bs;\n\t}\n\tcleanupDeleted();\n}\n\n/**\n * Checks for units panicking or falling and so on.\n */\nint BattlescapeGame::think()\n{\n\tint ret = -1;\n\t// nothing is happening - see if we need some alien AI or units panicking or what have you\n\tif (_states.empty())\n\t{\n\t\tif (_save->getUnitsFalling())\n\t\t{\n\t\t\tstatePushFront(new UnitFallBState(this));\n\t\t\t_save->setUnitsFalling(false);\n\t\t\treturn ret;\n\t\t}\n\t\t// it's a non player side (ALIENS or CIVILIANS)\n\t\tif (_save->getSide() != FACTION_PLAYER)\n\t\t{\n\t\t\tauto sideBackup = _save->getSide();\n\t\t\t_save->resetUnitHitStates();\n\t\t\tif (!_debugPlay)\n\t\t\t{\n\t\t\t\tif (_save->getSelectedUnit())\n\t\t\t\t{\n\t\t\t\t\tif (!handlePanickingUnit(_save->getSelectedUnit()))\n\t\t\t\t\t{\n\t\t\t\t\t\thandleAI(_save->getSelectedUnit());\n\n\t\t\t\t\t\t// calculate AI progress\n\t\t\t\t\t\tint units = 0;\n\t\t\t\t\t\tint total = 0;\n\t\t\t\t\t\tfor (auto* bu : *_save->getUnits())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (bu->getFaction() == sideBackup && !bu->isOut())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tunits++;\n\t\t\t\t\t\t\t\ttotal += (bu->reselectAllowed() && (bu->getBaseStats()->tu > 0)) ? bu->getTimeUnits() * 100 / bu->getBaseStats()->tu : 0;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tret = units > 0 ? total / units : 0;\n\t\t\t\t\t\t//Log(LOG_INFO) << \"units: \" << units << \" total: \" << total << \" ret: \" << ret;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif (_save->selectNextPlayerUnit(true, _AISecondMove) == 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (!_save->getDebugMode())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_endTurnRequested = true;\n\t\t\t\t\t\t\tstatePushBack(0); // end AI turn\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_save->selectNextPlayerUnit();\n\t\t\t\t\t\t\t_debugPlay = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// it's a player side && we have not handled all panicking units\n\t\t\tif (!_playerPanicHandled)\n\t\t\t{\n\t\t\t\t_playerPanicHandled = handlePanickingPlayer();\n\t\t\t\t_save->getBattleState()->updateSoldierInfo();\n\t\t\t}\n\t\t}\n\t}\n\n\treturn ret;\n}\n\n/**\n * Initializes the Battlescape game.\n */\nvoid BattlescapeGame::init()\n{\n\tif (_save->getSide() == FACTION_PLAYER && _save->getTurn() > 1)\n\t{\n\t\t_playerPanicHandled = false;\n\t}\n}\n\n\n/**\n * Handles the processing of the AI states of a unit.\n * @param unit Pointer to a unit.\n */\nvoid BattlescapeGame::handleAI(BattleUnit *unit)\n{\n\tstd::ostringstream ss;\n\n\tif (unit->getTimeUnits() <= 5)\n\t{\n\t\tunit->dontReselect();\n\t}\n\tif (_AIActionCounter >= 2 || !unit->reselectAllowed() || unit->getTurnsSinceStunned() == 0) //stun check for restoring OXC behavior that AI does not attack after waking up even having full TU\n\t{\n\t\tif (_save->selectNextPlayerUnit(true, _AISecondMove) == 0)\n\t\t{\n\t\t\tif (!_save->getDebugMode())\n\t\t\t{\n\t\t\t\t_endTurnRequested = true;\n\t\t\t\tstatePushBack(0); // end AI turn\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_save->selectNextPlayerUnit();\n\t\t\t\t_debugPlay = true;\n\t\t\t}\n\t\t}\n\t\tif (_save->getSelectedUnit())\n\t\t{\n\t\t\t_parentState->updateSoldierInfo();\n\t\t\tgetMap()->getCamera()->centerOnPosition(_save->getSelectedUnit()->getPosition());\n\t\t\tif (_save->getSelectedUnit()->getId() <= unit->getId())\n\t\t\t{\n\t\t\t\t_AISecondMove = true;\n\t\t\t}\n\t\t}\n\t\t_AIActionCounter = 0;\n\t\treturn;\n\t}\n\n\tunit->setVisible(false); //Possible TODO: check number of player unit observers, then hide the unit if no one can see it. Should then be able to skip the next FOV call.\n\n\t_save->getTileEngine()->calculateFOV(unit->getPosition(), 1, false); // might need this populate _visibleUnit for a newly-created alien.\n\t\t// it might also help chryssalids realize they've zombified someone and need to move on\n\t\t// it should also hide units when they've killed the guy spotting them\n\t\t// it's also for good luck\n\n\tAIModule *ai = unit->getAIModule();\n\tif (!ai)\n\t{\n\t\t// for some reason the unit had no AI routine assigned..\n\t\tunit->setAIModule(new AIModule(_save, unit, 0));\n\t\tai = unit->getAIModule();\n\t}\n\t_AIActionCounter++;\n\tif (_AIActionCounter == 1)\n\t{\n\t\t_playedAggroSound = false;\n\t\tunit->setHiding(false);\n\t\tif (Options::traceAI) { Log(LOG_INFO) << \"#\" << unit->getId() << \"--\" << unit->getType(); }\n\t}\n\n\tBattleAction action;\n\taction.actor = unit;\n\taction.number = _AIActionCounter;\n\tunit->think(&action);\n\n\tif (action.type == BA_RETHINK)\n\t{\n\t\t_parentState->debug(\"Rethink\");\n\t\tunit->think(&action);\n\t}\n\n\t_AIActionCounter = action.number;\n\tBattleItem *weapon = unit->getMainHandWeapon();\n\tbool pickUpWeaponsMoreActively = unit->getPickUpWeaponsMoreActively();\n\tbool weaponPickedUp = false;\n\tbool walkToItem = false;\n\tif (!weapon || !weapon->haveAnyAmmo())\n\t{\n\t\tif (unit->getOriginalFaction() != FACTION_PLAYER)\n\t\t{\n\t\t\tif ((unit->getOriginalFaction() == FACTION_HOSTILE && unit->getVisibleUnits()->empty()) || pickUpWeaponsMoreActively)\n\t\t\t{\n\t\t\t\tweaponPickedUp = findItem(&action, pickUpWeaponsMoreActively, walkToItem);\n\t\t\t}\n\t\t}\n\t}\n\tif (pickUpWeaponsMoreActively && weaponPickedUp)\n\t{\n\t\t// you have just picked up a weapon... use it if you can!\n\t\t_parentState->debug(\"Re-Rethink\");\n\t\tunit->getAIModule()->setWeaponPickedUp();\n\t\tunit->think(&action);\n\t}\n\n\tif (unit->getCharging() != 0)\n\t{\n\t\tif (unit->hasAggroSound() && !_playedAggroSound)\n\t\t{\n\t\t\tgetMod()->getSoundByDepth(_save->getDepth(), unit->getRandomAggroSound())->play(-1, getMap()->getSoundAngle(unit->getPosition()));\n\t\t\t_playedAggroSound = true;\n\t\t}\n\t}\n\tif (action.type == BA_WALK)\n\t{\n\t\tss << \"Walking to \" << action.target;\n\t\t_parentState->debug(ss.str());\n\n\t\tauto* targetTile = _save->getTile(action.target);\n\t\tif (targetTile)\n\t\t{\n\t\t\t_save->getPathfinding()->calculate(action.actor, action.target, BAM_NORMAL);\n\t\t}\n\t\tif (_save->getPathfinding()->getStartDirection() != -1)\n\t\t{\n\t\t\tstatePushBack(new UnitWalkBState(this, action));\n\t\t}\n\t\telse if (walkToItem)\n\t\t{\n\t\t\t// impossible to walk to this tile, don't try to pick up an item from there for the rest of the turn\n\t\t\ttargetTile->setDangerous(true);\n\t\t}\n\t}\n\n\tif (action.type == BA_SNAPSHOT || action.type == BA_AUTOSHOT || action.type == BA_AIMEDSHOT || action.type == BA_THROW || action.type == BA_HIT || action.type == BA_MINDCONTROL || action.type == BA_USE || action.type == BA_PANIC || action.type == BA_LAUNCH)\n\t{\n\t\tss.clear();\n\t\tss << \"Attack type=\" << action.type << \" target=\"<< action.target << \" weapon=\" << action.weapon->getRules()->getType();\n\t\t_parentState->debug(ss.str());\n\t\taction.updateTU();\n\t\tif (action.type == BA_MINDCONTROL || action.type == BA_PANIC || action.type == BA_USE)\n\t\t{\n\t\t\tstatePushBack(new PsiAttackBState(this, action));\n\t\t}\n\t\telse\n\t\t{\n\t\t\tstatePushBack(new UnitTurnBState(this, action));\n\t\t\tif (action.type == BA_HIT)\n\t\t\t{\n\t\t\t\tstatePushBack(new MeleeAttackBState(this, action));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tstatePushBack(new ProjectileFlyBState(this, action));\n\t\t\t}\n\t\t}\n\t}\n\n\tif (action.type == BA_NONE)\n\t{\n\t\t_parentState->debug(\"Idle\");\n\t\t_AIActionCounter = 0;\n\t\tif (_save->selectNextPlayerUnit(true, _AISecondMove) == 0)\n\t\t{\n\t\t\tif (!_save->getDebugMode())\n\t\t\t{\n\t\t\t\t_endTurnRequested = true;\n\t\t\t\tstatePushBack(0); // end AI turn\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_save->selectNextPlayerUnit();\n\t\t\t\t_debugPlay = true;\n\t\t\t}\n\t\t}\n\t\tif (_save->getSelectedUnit())\n\t\t{\n\t\t\t_parentState->updateSoldierInfo();\n\t\t\tgetMap()->getCamera()->centerOnPosition(_save->getSelectedUnit()->getPosition());\n\t\t\tif (_save->getSelectedUnit()->getId() <= unit->getId())\n\t\t\t{\n\t\t\t\t_AISecondMove = true;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Toggles the Kneel/Standup status of the unit.\n * @param bu Pointer to a unit.\n * @return If the action succeeded.\n */\nbool BattlescapeGame::kneel(BattleUnit *bu)\n{\n\tint tu = bu->getKneelChangeCost();\n\tif (bu->getArmor()->allowsKneeling(bu->getType() == \"SOLDIER\") && !bu->isFloating() && ((!bu->isKneeled() && _save->getKneelReserved()) || checkReservedTU(bu, tu, 0)))\n\t{\n\t\tBattleAction kneel;\n\t\tkneel.type = BA_KNEEL;\n\t\tkneel.actor = bu;\n\t\tkneel.Time = tu;\n\t\tif (kneel.spendTU())\n\t\t{\n\t\t\tbu->kneel(!bu->isKneeled());\n\t\t\t// kneeling or standing up can reveal new terrain or units. I guess.\n\t\t\tgetTileEngine()->calculateFOV(bu->getPosition(), 1, false); //Update unit FOV for everyone through this position, skip tiles.\n\t\t\t_parentState->updateSoldierInfo(); //This also updates the tile FOV of the unit, hence why it's skipped above.\n\t\t\tgetTileEngine()->checkReactionFire(bu, kneel);\n\t\t\treturn true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_parentState->warning(\"STR_NOT_ENOUGH_TIME_UNITS\");\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Ends the turn.\n */\nvoid BattlescapeGame::endTurn()\n{\n\t_debugPlay = _save->getDebugMode() && _parentState->getGame()->isCtrlPressed() && (_save->getSide() != FACTION_NEUTRAL);\n\t_currentAction.type = BA_NONE;\n\t_currentAction.skillRules = nullptr;\n\tgetMap()->getWaypoints()->clear();\n\t_currentAction.waypoints.clear();\n\t_parentState->showLaunchButton(false);\n\t_currentAction.targeting = false;\n\t_AISecondMove = false;\n\n\tif (_triggerProcessed.tryRun())\n\t{\n\t\tif (_save->getTileEngine()->closeUfoDoors() && Mod::SLIDING_DOOR_CLOSE != -1)\n\t\t{\n\t\t\tgetMod()->getSoundByDepth(_save->getDepth(), Mod::SLIDING_DOOR_CLOSE)->play(); // ufo door closed\n\t\t}\n\n\t\t// if all grenades explode we remove items that expire on that turn too.\n\t\tstd::vector<std::tuple<BattleItem*, ExplosionBState*>> forRemoval;\n\t\tbool exploded = false;\n\n\t\t// check for hot grenades on the ground\n\t\tif (_save->getSide() != FACTION_NEUTRAL && !_save->isPreview())\n\t\t{\n\t\t\tfor (BattleItem *item : *_save->getItems())\n\t\t\t{\n\t\t\t\tif (item->isOwnerIgnored())\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tconst RuleItem *rule = item->getRules();\n\t\t\t\tconst Tile *tile = item->getTile();\n\t\t\t\tBattleUnit *unit = item->getOwner();\n\t\t\t\tif (!tile && unit && item->getFuseTimer() != -1 && !_allEnemiesNeutralized)\n\t\t\t\t{\n\t\t\t\t\tint explodeAnyway = rule->getExplodeInventory(getMod());\n\t\t\t\t\tif (explodeAnyway >= 2 || (explodeAnyway == 1 && item->getSlot()->getType() != INV_HAND))\n\t\t\t\t\t{\n\t\t\t\t\t\ttile = unit->getTile();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (tile)\n\t\t\t\t{\n\t\t\t\t\tif (item->fuseTimeEvent())\n\t\t\t\t\t{\n\t\t\t\t\t\tif (rule->getBattleType() == BT_GRENADE) // it's a grenade to explode now\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tPosition p = tile->getPosition().toVoxel() + Position(8, 8, -tile->getTerrainLevel() + (unit ? unit->getHeight() / 2 : 0));\n\t\t\t\t\t\t\tforRemoval.push_back(std::tuple(nullptr, new ExplosionBState(this, p, BattleActionAttack::GetBeforeShoot(BA_TRIGGER_TIMED_GRENADE, unit, item))));\n\t\t\t\t\t\t\texploded = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tforRemoval.push_back(std::tuple(item, nullptr));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (auto& p : forRemoval)\n\t\t\t{\n\t\t\t\tBattleItem* item = std::get<BattleItem*>(p);\n\t\t\t\tExplosionBState* expl = std::get<ExplosionBState*>(p);\n\t\t\t\tif (expl)\n\t\t\t\t{\n\t\t\t\t\tstatePushNext(expl);\n\t\t\t\t}\n\t\t\t\telse if (item->isSpecialWeapon())\n\t\t\t\t{\n\t\t\t\t\t// we can't remove special weapons, disable the fuse at least\n\t\t\t\t\titem->setFuseTimer(-1);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t_save->removeItem(item);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (exploded)\n\t\t\t{\n\t\t\t\tstatePushBack(0);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\t// check for terrain explosions\n\tTile *t = _save->getTileEngine()->checkForTerrainExplosions();\n\tif (t)\n\t{\n\t\tPosition p = t->getPosition().toVoxel();\n\t\tstatePushNext(new ExplosionBState(this, p, BattleActionAttack{ }, t));\n\t\tstatePushBack(0);\n\t\treturn;\n\t}\n\n\tif (_endTurnProcessed.tryRun())\n\t{\n\t\tif (_save->getSide() != FACTION_NEUTRAL)\n\t\t{\n\t\t\tfor (BattleItem *item : *_save->getItems())\n\t\t\t{\n\t\t\t\tif (item->isOwnerIgnored())\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\titem->fuseEndTurnUpdate();\n\t\t\t}\n\t\t}\n\n\n\t\t_save->endTurn();\n\t\tt = _save->getTileEngine()->checkForTerrainExplosions();\n\t\tif (t)\n\t\t{\n\t\t\tPosition p = t->getPosition().toVoxel();\n\t\t\tstatePushNext(new ExplosionBState(this, p, BattleActionAttack{ }, t));\n\t\t\tstatePushBack(0);\n\t\t\treturn;\n\t\t}\n\t}\n\n\t_triggerProcessed.reset();\n\t_endTurnProcessed.reset();\n\n\tif (_save->getSide() == FACTION_PLAYER)\n\t{\n\t\tsetupCursor();\n\t}\n\telse\n\t{\n\t\tgetMap()->setCursorType(CT_NONE);\n\t}\n\n\tcheckForCasualties(nullptr, BattleActionAttack{ }, false, false);\n\n\t// fires could have been started, stopped or smoke could reveal/conceal units.\n\t_save->getTileEngine()->calculateLighting(LL_FIRE, TileEngine::invalid, 0, true);\n\t_save->getTileEngine()->recalculateFOV();\n\n\t// Calculate values\n\tBattlescapeTally tally = _save->getBattleGame()->tallyUnits();\n\n\t// if all units from either faction are killed - the mission is over.\n\tif (_save->allObjectivesDestroyed() && _save->getObjectiveType() == MUST_DESTROY)\n\t{\n\t\t_parentState->finishBattle(false, tally.liveSoldiers);\n\t\treturn;\n\t}\n\tif (_save->getTurnLimit() > 0 && _save->getTurn() > _save->getTurnLimit())\n\t{\n\t\tswitch (_save->getChronoTrigger())\n\t\t{\n\t\tcase FORCE_ABORT:\n\t\t\t_save->setAborted(true);\n\t\t\t_parentState->finishBattle(true, tally.inExit);\n\t\t\treturn;\n\t\tcase FORCE_WIN:\n\t\tcase FORCE_WIN_SURRENDER:\n\t\t\t_parentState->finishBattle(false, tally.liveSoldiers);\n\t\t\treturn;\n\t\tcase FORCE_LOSE:\n\t\tdefault:\n\t\t\t// force mission failure\n\t\t\t_save->setAborted(true);\n\t\t\t_parentState->finishBattle(false, 0);\n\t\t\treturn;\n\t\t}\n\t}\n\n\tif (tally.liveAliens > 0 && tally.liveSoldiers > 0)\n\t{\n\t\tshowInfoBoxQueue();\n\n\t\t_parentState->updateSoldierInfo();\n\n\t\tif (playableUnitSelected())\n\t\t{\n\t\t\tgetMap()->getCamera()->centerOnPosition(_save->getSelectedUnit()->getPosition());\n\t\t\tsetupCursor();\n\t\t}\n\t}\n\n\t// \"escort the VIPs\" missions don't end when all aliens are neutralized\n\t// objective type MUST_DESTROY was already handled above\n\tbool killingAllAliensIsNotEnough = (_save->getVIPSurvivalPercentage() > 0 && _save->getVIPEscapeType() != ESCAPE_NONE);\n\n\tbool battleComplete = (!killingAllAliensIsNotEnough && tally.liveAliens == 0) || tally.liveSoldiers == 0;\n\n\tif ((_save->getSide() != FACTION_NEUTRAL || battleComplete)\n\t\t&& _endTurnRequested)\n\t{\n\t\t_parentState->getGame()->pushState(new NextTurnState(_save, _parentState));\n\t}\n\t_endTurnRequested = false;\n}\n\n\n/**\n * Checks for casualties and adjusts morale accordingly.\n * @param damageType Need to know this, for a HE explosion there is an instant death.\n * @param attack This is needed for credits for the kill.\n * @param hiddenExplosion Set to true for the explosions of UFO Power sources at start of battlescape.\n * @param terrainExplosion Set to true for the explosions of terrain.\n */\nvoid BattlescapeGame::checkForCasualties(const RuleDamageType *damageType, BattleActionAttack attack, bool hiddenExplosion, bool terrainExplosion)\n{\n\tBattleUnit* origMurderer = attack.attacker;\n\t// If the victim was killed by the murderer's death explosion, fetch who killed the murderer and make HIM the murderer!\n\tif (origMurderer && (origMurderer->getSpecialAbility() == SPECAB_EXPLODEONDEATH || origMurderer->getSpecialAbility() == SPECAB_BURN_AND_EXPLODE)\n\t\t&& origMurderer->getStatus() == STATUS_DEAD && origMurderer->getMurdererId() != 0)\n\t{\n\t\tfor (auto* bu : *_save->getUnits())\n\t\t{\n\t\t\tif (bu->getId() == origMurderer->getMurdererId())\n\t\t\t{\n\t\t\t\torigMurderer = bu;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Fetch the murder weapon\n\tstd::string tempWeapon = \"STR_WEAPON_UNKNOWN\", tempAmmo = \"STR_WEAPON_UNKNOWN\";\n\tif (origMurderer)\n\t{\n\t\tif (attack.weapon_item)\n\t\t{\n\t\t\ttempWeapon = attack.weapon_item->getRules()->getName();\n\t\t}\n\t\tif (attack.damage_item)\n\t\t{\n\t\t\t// If the secondary melee data is used, represent this by setting the ammo to \"__GUNBUTT\".\n\t\t\t// Note: BT_MELEE items use their normal attack data rather than 'melee' data. So their 'ammo' should be the weapon itself.\n\t\t\t// (The following condition should match what is used in ExplosionBState::init to choose the damage power and type.)\n\t\t\tif (attack.type == BA_HIT && attack.damage_item->getRules()->getBattleType() != BT_MELEE)\n\t\t\t{\n\t\t\t\ttempAmmo = \"__GUNBUTT\";\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\ttempAmmo = attack.damage_item->getRules()->getName();\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (auto* victim : *_save->getUnits())\n\t{\n\t\tif (victim->isIgnored()) continue;\n\t\tBattleUnit *murderer = origMurderer;\n\n\t\tBattleUnitKills killStat;\n\t\tkillStat.mission = _parentState->getGame()->getSavedGame()->getMissionStatistics()->size();\n\t\tkillStat.setTurn(_save->getTurn(), _save->getSide());\n\t\tkillStat.setUnitStats(victim);\n\t\tkillStat.faction = victim->getOriginalFaction();\n\t\tkillStat.side = victim->getFatalShotSide();\n\t\tkillStat.bodypart = victim->getFatalShotBodyPart();\n\t\tkillStat.id = victim->getId();\n\t\tkillStat.weapon = tempWeapon;\n\t\tkillStat.weaponAmmo = tempAmmo;\n\n\t\t// Determine murder type\n\t\tif (victim->getStatus() != STATUS_DEAD)\n\t\t{\n\t\t\tif (victim->getHealth() <= 0)\n\t\t\t{\n\t\t\t\tkillStat.status = STATUS_DEAD;\n\t\t\t}\n\t\t\telse if (victim->getStunlevel() >= victim->getHealth() && victim->getStatus() != STATUS_UNCONSCIOUS)\n\t\t\t{\n\t\t\t\tkillStat.status = STATUS_UNCONSCIOUS;\n\t\t\t}\n\t\t}\n\n\t\t// Assume that, in absence of a murderer and an explosion, the laster unit to hit the victim is the murderer.\n\t\t// Possible causes of death: bleed out, fire.\n\t\t// Possible causes of unconsciousness: wounds, smoke.\n\t\t// Assumption : The last person to hit the victim is the murderer.\n\t\tif (!murderer && !terrainExplosion)\n\t\t{\n\t\t\tfor (auto* bu : *_save->getUnits())\n\t\t\t{\n\t\t\t\tif (bu->getId() == victim->getMurdererId())\n\t\t\t\t{\n\t\t\t\t\tmurderer = bu;\n\t\t\t\t\tkillStat.weapon = victim->getMurdererWeapon();\n\t\t\t\t\tkillStat.weaponAmmo = victim->getMurdererWeaponAmmo();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (murderer && killStat.status != STATUS_IGNORE_ME)\n\t\t{\n\t\t\tif (murderer->getFaction() == FACTION_PLAYER && murderer->getOriginalFaction() != FACTION_PLAYER)\n\t\t\t{\n\t\t\t\t// This must be a mind controlled unit. Find out who mind controlled him and award the kill to that unit.\n\t\t\t\tfor (auto* bu : *_save->getUnits())\n\t\t\t\t{\n\t\t\t\t\tif (bu->getId() == murderer->getMindControllerId() && bu->getGeoscapeSoldier())\n\t\t\t\t\t{\n\t\t\t\t\t\tif (!victim->isCosmetic())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tbu->getStatistics()->kills.push_back(new BattleUnitKills(killStat));\n\t\t\t\t\t\t\tif (victim->getFaction() == FACTION_HOSTILE)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tbu->getStatistics()->slaveKills++;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvictim->setMurdererId(bu->getId());\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (!murderer->getStatistics()->duplicateEntry(killStat.status, victim->getId()))\n\t\t\t{\n\t\t\t\tif (!victim->isCosmetic())\n\t\t\t\t{\n\t\t\t\t\tmurderer->getStatistics()->kills.push_back(new BattleUnitKills(killStat));\n\t\t\t\t}\n\t\t\t\tvictim->setMurdererId(murderer->getId());\n\t\t\t}\n\t\t}\n\n\t\tbool noSound = false;\n\t\tif (victim->getStatus() != STATUS_DEAD)\n\t\t{\n\t\t\tif (victim->getHealth() <= 0)\n\t\t\t{\n\t\t\t\tint moraleLossModifierWhenKilled = _save->getMoraleLossModifierWhenKilled(victim);\n\n\t\t\t\tif (murderer)\n\t\t\t\t{\n\t\t\t\t\tmurderer->addKillCount();\n\t\t\t\t\tvictim->killedBy(murderer->getFaction());\n\t\t\t\t\tint modifier = murderer->getFaction() == FACTION_PLAYER ? _save->getFactionMoraleModifier(true) : 100;\n\n\t\t\t\t\t// if there is a known murderer, he will get a morale bonus if he is of a different faction (what with neutral?)\n\t\t\t\t\tif ((victim->getOriginalFaction() == FACTION_PLAYER && murderer->getFaction() == FACTION_HOSTILE) ||\n\t\t\t\t\t\t(victim->getOriginalFaction() == FACTION_HOSTILE && murderer->getFaction() == FACTION_PLAYER))\n\t\t\t\t\t{\n\t\t\t\t\t\tmurderer->moraleChange(20 * modifier / 100);\n\t\t\t\t\t}\n\t\t\t\t\t// murderer will get a penalty with friendly fire\n\t\t\t\t\tif (victim->getOriginalFaction() == murderer->getOriginalFaction())\n\t\t\t\t\t{\n\t\t\t\t\t\t// morale loss by friendly fire\n\t\t\t\t\t\tmurderer->moraleChange(-(2000 * moraleLossModifierWhenKilled / modifier / 100));\n\t\t\t\t\t}\n\t\t\t\t\tif (victim->getOriginalFaction() == FACTION_NEUTRAL)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (murderer->getOriginalFaction() == FACTION_PLAYER)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// morale loss by xcom killing civilians\n\t\t\t\t\t\t\tmurderer->moraleChange(-(1000 * moraleLossModifierWhenKilled / modifier / 100));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tmurderer->moraleChange(10);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (victim->getFaction() != FACTION_NEUTRAL)\n\t\t\t\t{\n\t\t\t\t\tint modifier = _save->getUnitMoraleModifier(victim);\n\t\t\t\t\tint loserMod =  _save->getFactionMoraleModifier(victim->getOriginalFaction() != FACTION_HOSTILE);\n\t\t\t\t\tint winnerMod = _save->getFactionMoraleModifier(victim->getOriginalFaction() == FACTION_HOSTILE);\n\t\t\t\t\tfor (auto* bu : *_save->getUnits())\n\t\t\t\t\t{\n\t\t\t\t\t\tif (!bu->isOut())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// the losing squad all get a morale loss\n\t\t\t\t\t\t\tif (bu->getOriginalFaction() == victim->getOriginalFaction())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// morale loss by losing a team member (not counting mind-controlled units)\n\t\t\t\t\t\t\t\tint bravery = bu->reduceByBravery(10);\n\t\t\t\t\t\t\t\tbu->moraleChange(-(modifier * moraleLossModifierWhenKilled * 200 * bravery / loserMod / 100 / 100));\n\n\t\t\t\t\t\t\t\tif (victim->getFaction() == FACTION_HOSTILE && murderer)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tmurderer->setTurnsSinceSpotted(0);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// the winning squad all get a morale increase\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tbu->moraleChange(10 * winnerMod / 100);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (damageType)\n\t\t\t\t{\n\t\t\t\t\tstatePushNext(new UnitDieBState(this, victim, damageType, noSound));\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif (hiddenExplosion)\n\t\t\t\t\t{\n\t\t\t\t\t\t// this is instant death from UFO power sources, without screaming sounds\n\t\t\t\t\t\tnoSound = true;\n\t\t\t\t\t\tstatePushNext(new UnitDieBState(this, victim, getMod()->getDamageType(DT_HE), noSound));\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tif (terrainExplosion)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// terrain explosion\n\t\t\t\t\t\t\tstatePushNext(new UnitDieBState(this, victim, getMod()->getDamageType(DT_HE), noSound));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// no murderer, and no terrain explosion, must be fatal wounds\n\t\t\t\t\t\t\tstatePushNext(new UnitDieBState(this, victim, getMod()->getDamageType(DT_NONE), noSound));  // DT_NONE = STR_HAS_DIED_FROM_A_FATAL_WOUND\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// one of our own died, record the murderer instead of the victim\n\t\t\t\tif (victim->getGeoscapeSoldier())\n\t\t\t\t{\n\t\t\t\t\tvictim->getStatistics()->KIA = true;\n\t\t\t\t\tBattleUnitKills *deathStat = new BattleUnitKills(killStat);\n\t\t\t\t\tif (murderer)\n\t\t\t\t\t{\n\t\t\t\t\t\tdeathStat->setUnitStats(murderer);\n\t\t\t\t\t\tdeathStat->faction = murderer->getOriginalFaction();\n\t\t\t\t\t}\n\t\t\t\t\t_parentState->getGame()->getSavedGame()->killSoldier(false, victim->getGeoscapeSoldier(), deathStat);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (victim->getStunlevel() >= victim->getHealth() && victim->getStatus() != STATUS_UNCONSCIOUS)\n\t\t\t{\n\t\t\t\t// morale change when an enemy is stunned (only for the first time!)\n\t\t\t\tif (getMod()->getStunningImprovesMorale() && murderer && !victim->getStatistics()->wasUnconcious)\n\t\t\t\t{\n\t\t\t\t\tif ((victim->getOriginalFaction() == FACTION_PLAYER && murderer->getFaction() == FACTION_HOSTILE) ||\n\t\t\t\t\t\t(victim->getOriginalFaction() == FACTION_HOSTILE && murderer->getFaction() == FACTION_PLAYER))\n\t\t\t\t\t{\n\t\t\t\t\t\t// the murderer gets a morale bonus if he is of a different faction (excluding neutrals)\n\t\t\t\t\t\tmurderer->moraleChange(20);\n\n\t\t\t\t\t\tfor (auto* winner : *_save->getUnits())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (!winner->isOut() && winner->getOriginalFaction() == murderer->getOriginalFaction())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// the winning squad gets a morale increase (the losing squad is NOT affected)\n\t\t\t\t\t\t\t\twinner->moraleChange(10);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tvictim->getStatistics()->wasUnconcious = true;\n\t\t\t\tnoSound = true;\n\t\t\t\tstatePushNext(new UnitDieBState(this, victim, getMod()->getDamageType(DT_NONE), noSound)); // no damage type used there\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// piggyback of cleanup after script that change move type\n\t\t\t\tif (victim->haveNoFloorBelow() && victim->getMovementType() != MT_FLY)\n\t\t\t\t{\n\t\t\t\t\t_save->addFallingUnit(victim);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tBattleUnit *bu = _save->getSelectedUnit();\n\tif (_save->getSide() == FACTION_PLAYER)\n\t{\n\t\t_parentState->resetUiButton();\n\n\t\tif (bu && !bu->isOut())\n\t\t{\n\t\t\t_parentState->updateUiButton(bu);\n\t\t}\n\t}\n}\n\n/**\n * Shows the infoboxes in the queue (if any).\n */\nvoid BattlescapeGame::showInfoBoxQueue()\n{\n\tfor (auto* infoboxOKState : _infoboxQueue)\n\t{\n\t\t_parentState->getGame()->pushState(infoboxOKState);\n\t}\n\n\t_infoboxQueue.clear();\n}\n\n/**\n * Sets up a mission complete notification.\n */\nvoid BattlescapeGame::missionComplete()\n{\n\tGame *game = _parentState->getGame();\n\tif (game->getMod()->getDeployment(_save->getMissionType()))\n\t{\n\t\tstd::string missionComplete = game->getMod()->getDeployment(_save->getMissionType())->getObjectivePopup();\n\t\tif (!missionComplete.empty())\n\t\t{\n\t\t\t_infoboxQueue.push_back(new InfoboxOKState(game->getLanguage()->getString(missionComplete)));\n\t\t}\n\t}\n}\n\n/**\n * Handles the result of non target actions, like priming a grenade.\n */\nvoid BattlescapeGame::handleNonTargetAction()\n{\n\tif (!_currentAction.targeting)\n\t{\n\t\tstd::string error;\n\t\t_currentAction.cameraPosition = Position(0,0,-1);\n\t\tif (!_currentAction.result.empty())\n\t\t{\n\t\t\t_parentState->warning(_currentAction.result);\n\t\t\t_currentAction.result = \"\";\n\t\t}\n\t\telse if (_currentAction.type == BA_PRIME && _currentAction.value > -1)\n\t\t{\n\t\t\tif (_currentAction.spendTU(&error))\n\t\t\t{\n\t\t\t\t_parentState->warning(_currentAction.weapon->getRules()->getPrimeActionMessage());\n\t\t\t\t_currentAction.weapon->setFuseTimer(_currentAction.value);\n\t\t\t\tplaySound(_currentAction.weapon->getRules()->getPrimeSound()); // prime sound\n\t\t\t\t_save->getTileEngine()->calculateLighting(LL_UNITS, _currentAction.actor->getPosition());\n\t\t\t\t_save->getTileEngine()->calculateFOV(_currentAction.actor->getPosition(), _currentAction.weapon->getVisibilityUpdateRange(), false);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_parentState->warning(error);\n\t\t\t}\n\t\t}\n\t\telse if (_currentAction.type == BA_UNPRIME)\n\t\t{\n\t\t\tif (_currentAction.spendTU(&error))\n\t\t\t{\n\t\t\t\t_parentState->warning(_currentAction.weapon->getRules()->getUnprimeActionMessage());\n\t\t\t\t_currentAction.weapon->setFuseTimer(-1);\n\t\t\t\tplaySound(_currentAction.weapon->getRules()->getUnprimeSound()); // unprime sound\n\t\t\t\t_save->getTileEngine()->calculateLighting(LL_UNITS, _currentAction.actor->getPosition());\n\t\t\t\t_save->getTileEngine()->calculateFOV(_currentAction.actor->getPosition(), _currentAction.weapon->getVisibilityUpdateRange(), false);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_parentState->warning(error);\n\t\t\t}\n\t\t}\n\t\telse if (_currentAction.type == BA_USE)\n\t\t{\n\t\t\tgetTileEngine()->updateGameStateAfterScript(BattleActionAttack::GetBeforeShoot(_currentAction), TileEngine::invalid);\n\t\t}\n\t\telse if (_currentAction.type == BA_HIT)\n\t\t{\n\t\t\tif (_currentAction.haveTU(&error))\n\t\t\t{\n\t\t\t\tstatePushBack(new MeleeAttackBState(this, _currentAction));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_parentState->warning(error);\n\t\t\t}\n\t\t}\n\t\tif (_currentAction.type != BA_HIT) // don't clear the action type if we're meleeing, let the melee action state take care of that\n\t\t{\n\t\t\t_currentAction.type = BA_NONE;\n\t\t}\n\t\t_parentState->updateSoldierInfo();\n\t}\n\n\tsetupCursor();\n}\n\n/**\n * Sets the cursor according to the selected action.\n */\nvoid BattlescapeGame::setupCursor()\n{\n\tif (_currentAction.targeting)\n\t{\n\t\tif (_currentAction.type == BA_THROW)\n\t\t{\n\t\t\tgetMap()->setCursorType(CT_THROW);\n\t\t}\n\t\telse if (_currentAction.type == BA_MINDCONTROL || _currentAction.type == BA_PANIC || _currentAction.type == BA_USE)\n\t\t{\n\t\t\tgetMap()->setCursorType(CT_PSI);\n\t\t}\n\t\telse if (_currentAction.type == BA_LAUNCH)\n\t\t{\n\t\t\tgetMap()->setCursorType(CT_WAYPOINT);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tgetMap()->setCursorType(CT_AIM);\n\t\t}\n\t}\n\telse if (_currentAction.type != BA_HIT)\n\t{\n\t\t_currentAction.actor = _save->getSelectedUnit();\n\t\tif (_currentAction.actor)\n\t\t{\n\t\t\tgetMap()->setCursorType(CT_NORMAL, _currentAction.actor->getArmor()->getSize());\n\t\t}\n\t\telse\n\t\t{\n\t\t\tgetMap()->setCursorType(CT_NORMAL);\n\t\t}\n\t}\n}\n\n/**\n * Determines whether a playable unit is selected. Normally only player side units can be selected, but in debug mode one can play with aliens too :)\n * Is used to see if stats can be displayed.\n * @return Whether a playable unit is selected.\n */\nbool BattlescapeGame::playableUnitSelected() const\n{\n\treturn _save->getSelectedUnit() != 0 && (_save->getSide() == FACTION_PLAYER || _save->getDebugMode());\n}\n\n/**\n * Gives time slice to the front state.\n */\nvoid BattlescapeGame::handleState()\n{\n\tif (!_states.empty())\n\t{\n\t\t// end turn request?\n\t\tif (_states.front() == 0)\n\t\t{\n\t\t\t_states.pop_front();\n\t\t\tendTurn();\n\t\t\treturn;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_states.front()->think();\n\t\t}\n\t\tgetMap()->invalidate(); // redraw map\n\t}\n}\n\n/**\n * Pushes a state to the front of the queue and starts it.\n * @param bs Battlestate.\n */\nvoid BattlescapeGame::statePushFront(BattleState *bs)\n{\n\t_states.push_front(bs);\n\tbs->init();\n}\n\n/**\n * Pushes a state as the next state after the current one.\n * @param bs Battlestate.\n */\nvoid BattlescapeGame::statePushNext(BattleState *bs)\n{\n\tif (_states.empty())\n\t{\n\t\t_states.push_front(bs);\n\t\tbs->init();\n\t}\n\telse\n\t{\n\t\t_states.insert(++_states.begin(), bs);\n\t}\n\n}\n\n/**\n * Pushes a state to the back.\n * @param bs Battlestate.\n */\nvoid BattlescapeGame::statePushBack(BattleState *bs)\n{\n\tif (_states.empty())\n\t{\n\t\t_states.push_front(bs);\n\t\t// end turn request?\n\t\tif (_states.front() == 0)\n\t\t{\n\t\t\t_states.pop_front();\n\t\t\tendTurn();\n\t\t\treturn;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tbs->init();\n\t\t}\n\t}\n\telse\n\t{\n\t\t_states.push_back(bs);\n\t}\n}\n\n/**\n * Removes the current state.\n *\n * This is a very important function. It is called by a BattleState (walking, projectile is flying, explosions,...) at the moment this state has finished its action.\n * Here we check the result of that action and do all the aftermath.\n * The state is popped off the list.\n */\nvoid BattlescapeGame::popState()\n{\n\tif (Options::traceAI)\n\t{\n\t\tLog(LOG_INFO) << \"BattlescapeGame::popState() #\" << _AIActionCounter << \" with \" << (_save->getSelectedUnit() ? _save->getSelectedUnit()->getTimeUnits() : -9999) << \" TU\";\n\t}\n\tbool actionFailed = false;\n\n\tif (_states.empty()) return;\n\n\tauto* first = _states.front();\n\tBattleAction action = first->getAction();\n\n\tif (action.actor && !action.result.empty() && action.actor->getFaction() == FACTION_PLAYER\n\t\t&& _playerPanicHandled && (_save->getSide() == FACTION_PLAYER || _debugPlay))\n\t{\n\t\t_parentState->warning(action.result);\n\t\tactionFailed = true;\n\t}\n\t_deleted.push_back(first);\n\t_states.pop_front();\n\tfirst->deinit();\n\n\t// handle the end of this unit's actions\n\tif (action.actor && noActionsPending(action.actor))\n\t{\n\t\tif (action.actor->getFaction() == FACTION_PLAYER)\n\t\t{\n\t\t\tif (_save->getSide() == FACTION_PLAYER)\n\t\t\t{\n\t\t\t\t// after throwing the cursor returns to default cursor, after shooting it stays in targeting mode and the player can shoot again in the same mode (autoshot,snap,aimed)\n\t\t\t\tif ((action.type == BA_THROW || action.type == BA_LAUNCH) && !actionFailed)\n\t\t\t\t{\n\t\t\t\t\t// clean up the waypoints\n\t\t\t\t\tif (action.type == BA_LAUNCH)\n\t\t\t\t\t{\n\t\t\t\t\t\t_currentAction.waypoints.clear();\n\t\t\t\t\t}\n\n\t\t\t\t\tcancelCurrentAction(true);\n\t\t\t\t}\n\t\t\t\t_parentState->getGame()->getCursor()->setVisible(true);\n\t\t\t\tsetupCursor();\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (_save->getSide() != FACTION_PLAYER && !_debugPlay)\n\t\t\t{\n\t\t\t\t// AI does three things per unit, before switching to the next, or it got killed before doing the second thing\n\t\t\t\tif (_AIActionCounter > 2 || _save->getSelectedUnit() == 0 || _save->getSelectedUnit()->isOut())\n\t\t\t\t{\n\t\t\t\t\t_AIActionCounter = 0;\n\t\t\t\t\tif (_states.empty() && _save->selectNextPlayerUnit(true) == 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (!_save->getDebugMode())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_endTurnRequested = true;\n\t\t\t\t\t\t\tstatePushBack(0); // end AI turn\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_save->selectNextPlayerUnit();\n\t\t\t\t\t\t\t_debugPlay = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (_save->getSelectedUnit())\n\t\t\t\t\t{\n\t\t\t\t\t\tgetMap()->getCamera()->centerOnPosition(_save->getSelectedUnit()->getPosition());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (_debugPlay)\n\t\t\t{\n\t\t\t\t_parentState->getGame()->getCursor()->setVisible(true);\n\t\t\t\tsetupCursor();\n\t\t\t}\n\t\t}\n\t}\n\n\tif (!_states.empty())\n\t{\n\t\t// end turn request?\n\t\tif (_states.front() == 0)\n\t\t{\n\t\t\twhile (!_states.empty())\n\t\t\t{\n\t\t\t\tif (_states.front() == 0)\n\t\t\t\t\t_states.pop_front();\n\t\t\t\telse\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (_states.empty())\n\t\t\t{\n\t\t\t\tendTurn();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_states.push_back(0);\n\t\t\t}\n\t\t}\n\t\t// init the next state in queue\n\t\t_states.front()->init();\n\t}\n\n\t// the currently selected unit died or became unconscious or disappeared inexplicably\n\tif (_save->getSelectedUnit() == 0 || _save->getSelectedUnit()->isOut())\n\t{\n\t\tcancelCurrentAction();\n\t\tgetMap()->setCursorType(CT_NORMAL, 1);\n\t\t_parentState->getGame()->getCursor()->setVisible(true);\n\t\tif (_save->getSide() == FACTION_PLAYER)\n\t\t\t_save->setSelectedUnit(0);\n\t\telse\n\t\t\t_save->selectNextPlayerUnit(true, true);\n\t}\n\t_parentState->updateSoldierInfo();\n}\n\n/**\n * Determines whether there are any actions pending for the given unit.\n * @param bu BattleUnit.\n * @return True if there are no actions pending.\n */\nbool BattlescapeGame::noActionsPending(BattleUnit *bu)\n{\n\tif (_states.empty()) return true;\n\n\tfor (auto* battleState : _states)\n\t{\n\t\tif (battleState != 0 && battleState->getAction().actor == bu)\n\t\t\treturn false;\n\t}\n\n\treturn true;\n}\n\n/**\n * Sets the timer interval for think() calls of the state.\n * @param interval An interval in ms.\n */\nvoid BattlescapeGame::setStateInterval(Uint32 interval)\n{\n\t_parentState->setStateInterval(interval);\n}\n\n\n/**\n * Checks against reserved time units and energy units.\n * @param bu Pointer to the unit.\n * @param tu Number of time units to check.\n * @param energy Number of energy units to check.\n * @param justChecking True to suppress error messages, false otherwise.\n * @return bool Whether or not we got enough time units.\n */\nbool BattlescapeGame::checkReservedTU(BattleUnit *bu, int tu, int energy, bool justChecking)\n{\n\tBattleActionCost cost;\n\tcost.actor = bu;\n\tcost.type = _save->getTUReserved(); // avoid changing _tuReserved in this method\n\tcost.weapon = bu->getMainHandWeapon(false); // check TUs against slowest weapon if we have two weapons\n\n\tif (_save->getSide() != bu->getFaction() || _save->getSide() == FACTION_NEUTRAL)\n\t{\n\t\treturn tu <= bu->getTimeUnits();\n\t}\n\n\tif (_save->getSide() == FACTION_HOSTILE && !_debugPlay) // aliens reserve TUs as a percentage rather than just enough for a single action.\n\t{\n\t\tAIModule *ai = bu->getAIModule();\n\t\tif (ai)\n\t\t{\n\t\t\tcost.type = ai->getReserveMode();\n\t\t}\n\t\tcost.updateTU();\n\t\tcost.Energy += energy;\n\t\tcost.Time = tu; //override original\n\t\tswitch (cost.type)\n\t\t{\n\t\tcase BA_SNAPSHOT: cost.Time += (bu->getBaseStats()->tu / 3); break; // 33%\n\t\tcase BA_AUTOSHOT: cost.Time += ((bu->getBaseStats()->tu / 5)*2); break; // 40%\n\t\tcase BA_AIMEDSHOT: cost.Time += (bu->getBaseStats()->tu / 2); break; // 50%\n\t\tdefault: break;\n\t\t}\n\t\treturn cost.Time <= 0 || cost.haveTU();\n\t}\n\n\tcost.updateTU();\n\t// if the weapon has no autoshot, reserve TUs for snapshot\n\tif (cost.Time == 0 && cost.type == BA_AUTOSHOT)\n\t{\n\t\tcost.type = BA_SNAPSHOT;\n\t\tcost.updateTU();\n\t}\n\t// likewise, if we don't have a snap shot available, try aimed.\n\tif (cost.Time == 0 && cost.type == BA_SNAPSHOT)\n\t{\n\t\tcost.type = BA_AIMEDSHOT;\n\t\tcost.updateTU();\n\t}\n\tconst int tuKneel = (_save->getKneelReserved() && !bu->isKneeled()  && bu->getArmor()->allowsKneeling(bu->getType() == \"SOLDIER\")) ? bu->getKneelDownCost() : 0;\n\t// no aimed shot available? revert to none.\n\tif (cost.Time == 0 && cost.type == BA_AIMEDSHOT)\n\t{\n\t\tif (tuKneel > 0)\n\t\t{\n\t\t\tcost.type = BA_KNEEL;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t}\n\n\tcost.Time += tuKneel;\n\n\t//current TU is less that required for reserved shoot, we can't reserved anything.\n\tif (!cost.haveTU() && !justChecking)\n\t{\n\t\treturn true;\n\t}\n\n\tcost.Time += tu;\n\tcost.Energy += energy;\n\n\tif ((cost.type != BA_NONE || _save->getKneelReserved()) && !cost.haveTU())\n\t{\n\t\tif (!justChecking)\n\t\t{\n\t\t\tif (tuKneel)\n\t\t\t{\n\t\t\t\tswitch (cost.type)\n\t\t\t\t{\n\t\t\t\tcase BA_KNEEL: _parentState->warning(\"STR_TIME_UNITS_RESERVED_FOR_KNEELING\"); break;\n\t\t\t\tdefault: _parentState->warning(\"STR_TIME_UNITS_RESERVED_FOR_KNEELING_AND_FIRING\");\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tswitch (_save->getTUReserved())\n\t\t\t\t{\n\t\t\t\tcase BA_SNAPSHOT: _parentState->warning(\"STR_TIME_UNITS_RESERVED_FOR_SNAP_SHOT\"); break;\n\t\t\t\tcase BA_AUTOSHOT: _parentState->warning(\"STR_TIME_UNITS_RESERVED_FOR_AUTO_SHOT\"); break;\n\t\t\t\tcase BA_AIMEDSHOT: _parentState->warning(\"STR_TIME_UNITS_RESERVED_FOR_AIMED_SHOT\"); break;\n\t\t\t\tdefault: ;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\n\n\n/**\n * Picks the first soldier that is panicking.\n * @return True when all panicking is over.\n */\nbool BattlescapeGame::handlePanickingPlayer()\n{\n\tfor (auto* bu : *_save->getUnits())\n\t{\n\t\tif (bu->getFaction() == FACTION_PLAYER &&\n\t\t\tbu->getOriginalFaction() == FACTION_PLAYER &&\n\t\t\thandlePanickingUnit(bu))\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n}\n\n/**\n * Common function for handling panicking units.\n * @return False when unit not in panicking mode.\n */\nbool BattlescapeGame::handlePanickingUnit(BattleUnit *unit)\n{\n\tUnitStatus status = unit->getStatus();\n\tif (status != STATUS_PANICKING && status != STATUS_BERSERK) return false;\n\t_save->setSelectedUnit(unit);\n\t_parentState->getMap()->setCursorType(CT_NONE);\n\n\t// play panic/berserk sounds first\n\tbool soundPlayed = false;\n\t{\n\t\tstd::vector<int> sounds;\n\t\tif (unit->getUnitRules())\n\t\t{\n\t\t\t// aliens, civilians, xcom HWPs\n\t\t\tif (status == STATUS_PANICKING)\n\t\t\t\tsounds = unit->getUnitRules()->getPanicSounds();\n\t\t\telse\n\t\t\t\tsounds = unit->getUnitRules()->getBerserkSounds();\n\t\t}\n\t\telse if (unit->getGeoscapeSoldier())\n\t\t{\n\t\t\t// xcom soldiers (male/female)\n\t\t\tif (unit->getGeoscapeSoldier()->getGender() == GENDER_MALE)\n\t\t\t{\n\t\t\t\tif (status == STATUS_PANICKING)\n\t\t\t\t\tsounds = unit->getGeoscapeSoldier()->getRules()->getMalePanicSounds();\n\t\t\t\telse\n\t\t\t\t\tsounds = unit->getGeoscapeSoldier()->getRules()->getMaleBerserkSounds();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (status == STATUS_PANICKING)\n\t\t\t\t\tsounds = unit->getGeoscapeSoldier()->getRules()->getFemalePanicSounds();\n\t\t\t\telse\n\t\t\t\t\tsounds = unit->getGeoscapeSoldier()->getRules()->getFemaleBerserkSounds();\n\t\t\t}\n\t\t}\n\t\tif (!sounds.empty())\n\t\t{\n\t\t\tsoundPlayed = true;\n\t\t\tif (sounds.size() > 1)\n\t\t\t\tplaySound(sounds[RNG::generate(0, sounds.size() - 1)]);\n\t\t\telse\n\t\t\t\tplaySound(sounds.front());\n\t\t}\n\t}\n\n\t// show a little infobox with the name of the unit and \"... is panicking\"\n\tGame *game = _parentState->getGame();\n\tif (unit->getVisible() || !Options::noAlienPanicMessages)\n\t{\n\t\tgetMap()->getCamera()->centerOnPosition(unit->getPosition());\n\t\tif (status == STATUS_PANICKING)\n\t\t{\n\t\t\tgame->pushState(new InfoboxState(game->getLanguage()->getString(\"STR_HAS_PANICKED\", unit->getGender()).arg(unit->getName(game->getLanguage()))));\n\t\t}\n\t\telse\n\t\t{\n\t\t\tgame->pushState(new InfoboxState(game->getLanguage()->getString(\"STR_HAS_GONE_BERSERK\", unit->getGender()).arg(unit->getName(game->getLanguage()))));\n\t\t}\n\t}\n\telse if (soundPlayed)\n\t{\n\t\t// simulate a small pause by using an invisible infobox\n\t\tgame->pushState(new InfoboxState(\"\"));\n\t}\n\n\n\tbool flee = RNG::percent(50);\n\tBattleAction ba;\n\tba.actor = unit;\n\tif (status == STATUS_PANICKING && flee) // 1/2 chance to freeze and 1/2 chance try to flee, STATUS_BERSERK is handled in the panic state.\n\t{\n\t\tBattleItem *item = unit->getRightHandWeapon();\n\t\tif (item)\n\t\t{\n\t\t\tdropItem(unit->getPosition(), item, true);\n\t\t}\n\t\titem = unit->getLeftHandWeapon();\n\t\tif (item)\n\t\t{\n\t\t\tdropItem(unit->getPosition(), item, true);\n\t\t}\n\t\t// let's try a few times to get a tile to run to.\n\t\tfor (int i= 0; i < 20; i++)\n\t\t{\n\t\t\tba.target = Position(unit->getPosition().x + RNG::generate(-5,5), unit->getPosition().y + RNG::generate(-5,5), unit->getPosition().z);\n\n\t\t\tif (i >= 10 && ba.target.z > 0) // if we've had more than our fair share of failures, try going down.\n\t\t\t{\n\t\t\t\tba.target.z--;\n\t\t\t\tif (i >= 15 && ba.target.z > 0) // still failing? try further down.\n\t\t\t\t{\n\t\t\t\t\tba.target.z--;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (_save->getTile(ba.target)) // sanity check the tile.\n\t\t\t{\n\t\t\t\t_save->getPathfinding()->calculate(ba.actor, ba.target, ba.getMoveType());\n\t\t\t\tif (_save->getPathfinding()->getStartDirection() != -1) // sanity check the path.\n\t\t\t\t{\n\t\t\t\t\tstatePushBack(new UnitWalkBState(this, ba));\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t// Time units can only be reset after everything else occurs\n\tstatePushBack(new UnitPanicBState(this, ba.actor));\n\n\treturn true;\n}\n\n/**\n  * Cancels the current action the user had selected (firing, throwing,..)\n  * @param bForce Force the action to be cancelled.\n  * @return Whether an action was cancelled or not.\n  */\nbool BattlescapeGame::cancelCurrentAction(bool bForce)\n{\n\tbool bPreviewed = Options::battleNewPreviewPath != PATH_NONE;\n\n\tif (_save->getPathfinding()->removePreview() && bPreviewed) return true;\n\n\tif (_states.empty() || bForce)\n\t{\n\t\tif (_currentAction.targeting)\n\t\t{\n\t\t\tif (_currentAction.type == BA_LAUNCH && !_currentAction.waypoints.empty())\n\t\t\t{\n\t\t\t\t_currentAction.waypoints.pop_back();\n\t\t\t\tif (!getMap()->getWaypoints()->empty())\n\t\t\t\t{\n\t\t\t\t\tgetMap()->getWaypoints()->pop_back();\n\t\t\t\t}\n\t\t\t\tif (_currentAction.waypoints.empty())\n\t\t\t\t{\n\t\t\t\t\t_parentState->showLaunchButton(false);\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\telse if (_currentAction.type == BA_AUTOSHOT && _currentAction.sprayTargeting && !_currentAction.waypoints.empty())\n\t\t\t{\n\t\t\t\t_currentAction.waypoints.pop_back();\n\t\t\t\tif (!getMap()->getWaypoints()->empty())\n\t\t\t\t{\n\t\t\t\t\tgetMap()->getWaypoints()->pop_back();\n\t\t\t\t}\n\n\t\t\t\tif (_currentAction.waypoints.empty())\n\t\t\t\t{\n\t\t\t\t\t_currentAction.sprayTargeting = false;\n\t\t\t\t\tgetMap()->getWaypoints()->clear();\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (Options::battleConfirmFireMode && !_currentAction.waypoints.empty())\n\t\t\t\t{\n\t\t\t\t\t_currentAction.waypoints.pop_back();\n\t\t\t\t\tgetMap()->getWaypoints()->pop_back();\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\t_currentAction.targeting = false;\n\t\t\t\t_currentAction.type = BA_NONE;\n\t\t\t\t_currentAction.skillRules = nullptr;\n\t\t\t\t_currentAction.result = \"\"; // TODO\n\t\t\t\tsetupCursor();\n\t\t\t\t_parentState->getGame()->getCursor()->setVisible(true);\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\telse if (!_states.empty() && _states.front() != 0)\n\t{\n\t\t_states.front()->cancel();\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\n/**\n  * Cancels all selected user actions.\n  */\nvoid BattlescapeGame::cancelAllActions()\n{\n\t_save->getPathfinding()->removePreview();\n\n\t_currentAction.waypoints.clear();\n\tgetMap()->getWaypoints()->clear();\n\t_parentState->showLaunchButton(false);\n\n\t_currentAction.targeting = false;\n\t_currentAction.type = BA_NONE;\n\t_currentAction.skillRules = nullptr;\n\t_currentAction.result = \"\"; // TODO\n\tsetupCursor();\n\t_parentState->getGame()->getCursor()->setVisible(true);\n}\n\n/**\n * Gets a pointer to access action members directly.\n * @return Pointer to action.\n */\nBattleAction *BattlescapeGame::getCurrentAction()\n{\n\treturn &_currentAction;\n}\n\n/**\n * Determines whether an action is currently going on?\n * @return true or false.\n */\nbool BattlescapeGame::isBusy() const\n{\n\treturn !_states.empty();\n}\n\n/**\n * Activates primary action (left click).\n * @param pos Position on the map.\n */\nvoid BattlescapeGame::primaryAction(Position pos)\n{\n\tbool bPreviewed = Options::battleNewPreviewPath != PATH_NONE;\n\n\tgetMap()->resetObstacles();\n\n\tif (_currentAction.targeting && _save->getSelectedUnit())\n\t{\n\t\tif (_currentAction.type == BA_LAUNCH)\n\t\t{\n\t\t\tint maxWaypoints = _currentAction.weapon->getCurrentWaypoints();\n\t\t\tif ((int)_currentAction.waypoints.size() < maxWaypoints || maxWaypoints == -1)\n\t\t\t{\n\t\t\t\t_parentState->showLaunchButton(true);\n\t\t\t\t_currentAction.waypoints.push_back(pos);\n\t\t\t\tgetMap()->getWaypoints()->push_back(pos);\n\t\t\t}\n\t\t}\n\t\telse if (_currentAction.sprayTargeting) // Special \"spray\" autoshot that allows placing shots between waypoints\n\t\t{\n\t\t\tint maxWaypoints = _currentAction.weapon->getRules()->getSprayWaypoints();\n\t\t\tif ((int)_currentAction.waypoints.size() >= maxWaypoints ||\n\t\t\t\t(_save->isCtrlPressed(true) && _save->isShiftPressed(true)) ||\n\t\t\t\t(!Options::battleConfirmFireMode && (int)_currentAction.waypoints.size() == maxWaypoints - 1))\n\t\t\t{\n\t\t\t\t// If we're firing early, pick one last waypoint.\n\t\t\t\tif ((int)_currentAction.waypoints.size() < maxWaypoints)\n\t\t\t\t{\n\t\t\t\t\t_currentAction.waypoints.push_back(pos);\n\t\t\t\t\tgetMap()->getWaypoints()->push_back(pos);\n\t\t\t\t}\n\n\t\t\t\tgetMap()->setCursorType(CT_NONE);\n\n\t\t\t\t// Populate the action's waypoints with the positions we want to fire at\n\t\t\t\t// Start from the last shot and move to the first, since we'll be using the last element first and then pop_back()\n\t\t\t\tint numberOfShots = _currentAction.weapon->getRules()->getConfigAuto()->shots;\n\t\t\t\tint numberOfWaypoints = _currentAction.waypoints.size();\n\t\t\t\t_currentAction.waypoints.clear();\n\t\t\t\tfor (int i = numberOfShots - 1; i > 0; --i)\n\t\t\t\t{\n\t\t\t\t\t// Evenly space shots along the waypoints according to number of waypoints and the number of shots\n\t\t\t\t\t// Use voxel positions to get more uniform spacing\n\t\t\t\t\t// We add Position(8, 8, 12) to target middle of tile\n\t\t\t\t\tint waypointIndex = std::max(0, std::min(numberOfWaypoints - 1, i * (numberOfWaypoints - 1) / (numberOfShots - 1)));\n\t\t\t\t\tPosition previousWaypoint = getMap()->getWaypoints()->at(waypointIndex).toVoxel() + TileEngine::voxelTileCenter;\n\t\t\t\t\tPosition nextWaypoint = getMap()->getWaypoints()->at(std::min((int)getMap()->getWaypoints()->size() - 1, waypointIndex + 1)).toVoxel() + TileEngine::voxelTileCenter;\n\t\t\t\t\tPosition targetPos;\n\t\t\t\t\ttargetPos.x = previousWaypoint.x + (nextWaypoint.x - previousWaypoint.x) * (i * (numberOfWaypoints - 1) % (numberOfShots - 1)) / (numberOfShots - 1);\n\t\t\t\t\ttargetPos.y = previousWaypoint.y + (nextWaypoint.y - previousWaypoint.y) * (i * (numberOfWaypoints - 1) % (numberOfShots - 1)) / (numberOfShots - 1);\n\t\t\t\t\ttargetPos.z = previousWaypoint.z + (nextWaypoint.z - previousWaypoint.z) * (i * (numberOfWaypoints - 1) % (numberOfShots - 1)) / (numberOfShots - 1);\n\n\t\t\t\t\t_currentAction.waypoints.push_back(targetPos);\n\t\t\t\t}\n\t\t\t\t_currentAction.waypoints.push_back(getMap()->getWaypoints()->front().toVoxel() + TileEngine::voxelTileCenter);\n\t\t\t\t_currentAction.target = _currentAction.waypoints.back().toTile();\n\n\t\t\t\tgetMap()->getWaypoints()->clear();\n\t\t\t\t_parentState->getGame()->getCursor()->setVisible(false);\n\t\t\t\t_currentAction.cameraPosition = getMap()->getCamera()->getMapOffset();\n\t\t\t\t_states.push_back(new ProjectileFlyBState(this, _currentAction));\n\t\t\t\tstatePushFront(new UnitTurnBState(this, _currentAction));\n\t\t\t\t_currentAction.sprayTargeting = false;\n\t\t\t\t_currentAction.waypoints.clear();\n\t\t\t}\n\t\t\telse if ((int)_currentAction.waypoints.size() < maxWaypoints)\n\t\t\t{\n\t\t\t\t_currentAction.waypoints.push_back(pos);\n\t\t\t\tgetMap()->getWaypoints()->push_back(pos);\n\t\t\t}\n\t\t}\n\t\telse if (_currentAction.type == BA_AUTOSHOT &&\n\t\t\t_currentAction.weapon->getRules()->getSprayWaypoints() > 0 &&\n\t\t\t_save->isCtrlPressed(true) &&\n\t\t\t_save->isShiftPressed(true) &&\n\t\t\t_currentAction.waypoints.empty()) // Starts the spray autoshot targeting\n\t\t{\n\t\t\t_currentAction.sprayTargeting = true;\n\t\t\t_currentAction.waypoints.push_back(pos);\n\t\t\tgetMap()->getWaypoints()->push_back(pos);\n\t\t}\n\t\telse if (_currentAction.type == BA_USE && _currentAction.weapon->getRules()->getBattleType() == BT_MINDPROBE)\n\t\t{\n\t\t\tauto* targetUnit = _save->selectUnit(pos);\n\t\t\tif (targetUnit && targetUnit->getFaction() != _save->getSelectedUnit()->getFaction() && targetUnit->getVisible())\n\t\t\t{\n\t\t\t\tif (!_currentAction.weapon->getRules()->isLOSRequired() ||\n\t\t\t\t\t(_currentAction.actor->getFaction() == FACTION_PLAYER && targetUnit->getFaction() != FACTION_HOSTILE) ||\n\t\t\t\t\tstd::find(_currentAction.actor->getVisibleUnits()->begin(), _currentAction.actor->getVisibleUnits()->end(), targetUnit) != _currentAction.actor->getVisibleUnits()->end())\n\t\t\t\t{\n\t\t\t\t\tstd::string error;\n\t\t\t\t\tif (_currentAction.spendTU(&error))\n\t\t\t\t\t{\n\t\t\t\t\t\t_parentState->getGame()->getMod()->getSoundByDepth(_save->getDepth(), _currentAction.weapon->getRules()->getHitSound())->play(-1, getMap()->getSoundAngle(pos));\n\t\t\t\t\t\t_parentState->getGame()->pushState (new UnitInfoState(targetUnit, _parentState, false, true));\n\t\t\t\t\t\tcancelCurrentAction();\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t_parentState->warning(error);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t_parentState->warning(\"STR_LINE_OF_SIGHT_REQUIRED\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse if ((_currentAction.type == BA_PANIC || _currentAction.type == BA_MINDCONTROL || _currentAction.type == BA_USE) && _currentAction.weapon->getRules()->getBattleType() == BT_PSIAMP)\n\t\t{\n\t\t\tauto* targetUnit = _save->selectUnit(pos);\n\t\t\tif (targetUnit)\n\t\t\t{\n\t\t\t\tconst UnitFaction targetFaction = targetUnit->getFaction();\n\t\t\t\tconst UnitFaction attackerFaction = _currentAction.actor->getFaction();\n\n\t\t\t\tbool knowTarget = true;\n\t\t\t\tif (attackerFaction == FACTION_PLAYER || attackerFaction == FACTION_NEUTRAL)\n\t\t\t\t{\n\t\t\t\t\tknowTarget = targetUnit->getVisible();\n\t\t\t\t}\n\t\t\t\telse if (attackerFaction == FACTION_HOSTILE) // for debugging\n\t\t\t\t{\n\t\t\t\t\tif (targetFaction != FACTION_HOSTILE)\n\t\t\t\t\t{\n\t\t\t\t\t\tknowTarget = _currentAction.actor->getAIModule()\n\t\t\t\t\t\t\t? _currentAction.actor->getAIModule()->validTarget(targetUnit, false, true) // different flags than AI used because AI consider strategy\n\t\t\t\t\t\t\t: false;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tknowTarget = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tbool psiTargetAllowed = knowTarget && _currentAction.weapon->getRules()->isTargetAllowed(targetFaction, attackerFaction);\n\t\t\t\tif (_currentAction.type == BA_MINDCONTROL && attackerFaction == targetFaction)\n\t\t\t\t{\n\t\t\t\t\t// no mind controlling allies, unwanted side effects\n\t\t\t\t\tpsiTargetAllowed = false;\n\t\t\t\t}\n\t\t\t\telse if (_currentAction.type == BA_PANIC && targetUnit->getUnitRules() && !targetUnit->getUnitRules()->canPanic())\n\t\t\t\t{\n\t\t\t\t\tpsiTargetAllowed = false;\n\t\t\t\t}\n\t\t\t\telse if (_currentAction.type == BA_MINDCONTROL && targetUnit->getUnitRules() && !targetUnit->getUnitRules()->canBeMindControlled())\n\t\t\t\t{\n\t\t\t\t\tpsiTargetAllowed = false;\n\t\t\t\t}\n\n\t\t\t\tif (psiTargetAllowed)\n\t\t\t\t{\n\t\t\t\t\t_currentAction.updateTU();\n\t\t\t\t\t_currentAction.target = pos;\n\t\t\t\t\tif (!_currentAction.weapon->getRules()->isLOSRequired() ||\n\t\t\t\t\t\t(attackerFaction == FACTION_PLAYER && targetFaction != FACTION_HOSTILE) ||\n\t\t\t\t\t\tstd::find(_currentAction.actor->getVisibleUnits()->begin(), _currentAction.actor->getVisibleUnits()->end(), targetUnit) != _currentAction.actor->getVisibleUnits()->end())\n\t\t\t\t\t{\n\t\t\t\t\t\t// get the sound/animation started\n\t\t\t\t\t\tgetMap()->setCursorType(CT_NONE);\n\t\t\t\t\t\t_parentState->getGame()->getCursor()->setVisible(false);\n\t\t\t\t\t\t_currentAction.cameraPosition = getMap()->getCamera()->getMapOffset();\n\t\t\t\t\t\tstatePushBack(new PsiAttackBState(this, _currentAction));\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t_parentState->warning(\"STR_LINE_OF_SIGHT_REQUIRED\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (knowTarget)\n\t\t\t\t{\n\t\t\t\t\t//TODO: add `warning` that we can't target given unit\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse if (Options::battleConfirmFireMode && (_currentAction.waypoints.empty() || pos != _currentAction.waypoints.front()))\n\t\t{\n\t\t\t_currentAction.waypoints.clear();\n\t\t\t_currentAction.waypoints.push_back(pos);\n\t\t\tgetMap()->getWaypoints()->clear();\n\t\t\tgetMap()->getWaypoints()->push_back(pos);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_currentAction.target = pos;\n\t\t\tgetMap()->setCursorType(CT_NONE);\n\n\t\t\tif (Options::battleConfirmFireMode)\n\t\t\t{\n\t\t\t\t_currentAction.waypoints.clear();\n\t\t\t\tgetMap()->getWaypoints()->clear();\n\t\t\t}\n\n\t\t\t_parentState->getGame()->getCursor()->setVisible(false);\n\t\t\t_currentAction.cameraPosition = getMap()->getCamera()->getMapOffset();\n\t\t\t_states.push_back(new ProjectileFlyBState(this, _currentAction));\n\t\t\tstatePushFront(new UnitTurnBState(this, _currentAction)); // first of all turn towards the target\n\t\t}\n\t}\n\telse\n\t{\n\t\t_currentAction.actor = _save->getSelectedUnit();\n\t\tBattleUnit *unit = _save->selectUnit(pos);\n\t\tif (unit && unit == _save->getSelectedUnit() && (unit->getVisible() || _debugPlay))\n\t\t{\n\t\t\tplayUnitResponseSound(unit, 3); // \"annoyed\" sound\n\t\t}\n\t\tif (unit && unit != _save->getSelectedUnit() && (unit->getVisible() || _debugPlay))\n\t\t{\n\t\t//  -= select unit =-\n\t\t\tif (unit->getFaction() == _save->getSide())\n\t\t\t{\n\t\t\t\t_save->setSelectedUnit(unit);\n\t\t\t\t_parentState->updateSoldierInfo();\n\t\t\t\tcancelCurrentAction();\n\t\t\t\tsetupCursor();\n\t\t\t\t_currentAction.actor = unit;\n\t\t\t\tplayUnitResponseSound(unit, 0); // \"select unit\" sound\n\t\t\t}\n\t\t}\n\t\telse if (playableUnitSelected())\n\t\t{\n\t\t\tbool isCtrlPressed = Options::strafe && _save->isCtrlPressed(true);\n\t\t\tbool isAltPressed = Options::strafe && _save->isAltPressed(true);\n\t\t\tbool isShiftPressed = _save->isShiftPressed(true);\n\t\t\tif (bPreviewed && (\n\t\t\t\t_currentAction.target != pos ||\n\t\t\t\t_save->getPathfinding()->isModifierCtrlUsed() != isCtrlPressed ||\n\t\t\t\t_save->getPathfinding()->isModifierAltUsed() != isAltPressed))\n\t\t\t{\n\t\t\t\t_save->getPathfinding()->removePreview();\n\t\t\t}\n\t\t\t_currentAction.target = pos;\n\t\t\t_save->getPathfinding()->calculate(_currentAction.actor, _currentAction.target, BAM_NORMAL); // precalculate move\n\n\t\t\t_currentAction.strafe = false;\n\t\t\t_currentAction.run = false;\n\t\t\t_currentAction.sneak = false;\n\n\t\t\tif (isCtrlPressed)\n\t\t\t{\n\t\t\t\tif (_save->getPathfinding()->getPath().size() > 1 || isAltPressed)\n\t\t\t\t{\n\t\t\t\t\t_currentAction.run = _save->getSelectedUnit()->getArmor()->allowsRunning(_save->getSelectedUnit()->isSmallUnit());\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t_currentAction.strafe = _save->getSelectedUnit()->getArmor()->allowsStrafing(_save->getSelectedUnit()->isSmallUnit());\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (isAltPressed)\n\t\t\t{\n\t\t\t\t_currentAction.sneak = _save->getSelectedUnit()->getArmor()->allowsSneaking(_save->getSelectedUnit()->isSmallUnit());\n\t\t\t}\n\n\t\t\t// recalculate path after setting new move types\n\t\t\tif (BAM_NORMAL != _currentAction.getMoveType())\n\t\t\t{\n\t\t\t\t_save->getPathfinding()->calculate(_currentAction.actor, _currentAction.target, _currentAction.getMoveType());\n\t\t\t}\n\n\t\t\t// if running or shifting, ignore spotted enemies (i.e. don't stop)\n\t\t\t_currentAction.ignoreSpottedEnemies = (_currentAction.run && Mod::EXTENDED_RUNNING_COST) || isShiftPressed;\n\n\t\t\tif (bPreviewed && !_save->getPathfinding()->previewPath() && _save->getPathfinding()->getStartDirection() != -1)\n\t\t\t{\n\t\t\t\t_save->getPathfinding()->removePreview();\n\t\t\t\tbPreviewed = false;\n\t\t\t}\n\n\t\t\tif (!bPreviewed && _save->getPathfinding()->getStartDirection() != -1)\n\t\t\t{\n\t\t\t\t//  -= start walking =-\n\t\t\t\tgetMap()->setCursorType(CT_NONE);\n\t\t\t\t_parentState->getGame()->getCursor()->setVisible(false);\n\t\t\t\tstatePushBack(new UnitWalkBState(this, _currentAction));\n\t\t\t\tplayUnitResponseSound(_currentAction.actor, 1); // \"start moving\" sound\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Activates secondary action (right click).\n * @param pos Position on the map.\n */\nvoid BattlescapeGame::secondaryAction(Position pos)\n{\n\t//  -= turn to or open door =-\n\t_currentAction.target = pos;\n\t_currentAction.actor = _save->getSelectedUnit();\n\t_currentAction.strafe = Options::strafe && _save->isCtrlPressed(true) && _save->getSelectedUnit()->getTurretType() > -1;\n\tstatePushBack(new UnitTurnBState(this, _currentAction));\n}\n\n/**\n * Handler for the blaster launcher button.\n */\nvoid BattlescapeGame::launchAction()\n{\n\t_parentState->showLaunchButton(false);\n\tgetMap()->getWaypoints()->clear();\n\t_currentAction.target = _currentAction.waypoints.front();\n\tgetMap()->setCursorType(CT_NONE);\n\t_parentState->getGame()->getCursor()->setVisible(false);\n\t_currentAction.cameraPosition = getMap()->getCamera()->getMapOffset();\n\t_states.push_back(new ProjectileFlyBState(this, _currentAction));\n\tstatePushFront(new UnitTurnBState(this, _currentAction)); // first of all turn towards the target\n}\n\n/**\n * Handler for the psi button.\n */\nvoid BattlescapeGame::psiButtonAction()\n{\n\tif (!_currentAction.waypoints.empty()) // in case waypoints were set with a blaster launcher, avoid accidental misclick\n\t\treturn;\n\tBattleItem *item = _save->getSelectedUnit()->getSpecialWeapon(BT_PSIAMP);\n\t_currentAction.type = BA_NONE;\n\tif (item->getRules()->getCostPanic().Time > 0)\n\t{\n\t\t_currentAction.type = BA_PANIC;\n\t}\n\telse if (item->getRules()->getCostUse().Time > 0)\n\t{\n\t\t_currentAction.type = BA_USE;\n\t}\n\tif (_currentAction.type != BA_NONE)\n\t{\n\t\t_currentAction.targeting = true;\n\t\t_currentAction.weapon = item;\n\t\t_currentAction.updateTU();\n\t\tsetupCursor();\n\t}\n}\n\n/**\n * Handler for the psi attack result message.\n */\nvoid BattlescapeGame::psiAttackMessage(BattleActionAttack attack, BattleUnit *victim)\n{\n\tif (victim)\n\t{\n\t\tGame *game = getSave()->getBattleState()->getGame();\n\t\tif (attack.attacker->getFaction() == FACTION_HOSTILE)\n\t\t{\n\t\t\t// show a little infobox with the name of the unit and \"... is under alien control\"\n\t\t\tif (attack.type == BA_MINDCONTROL)\n\t\t\t\tgame->pushState(new InfoboxState(game->getLanguage()->getString(\"STR_IS_UNDER_ALIEN_CONTROL\", victim->getGender()).arg(victim->getName(game->getLanguage()))));\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// show a little infobox if it's successful\n\t\t\tif (attack.type == BA_PANIC)\n\t\t\t\tgame->pushState(new InfoboxState(game->getLanguage()->getString(\"STR_MORALE_ATTACK_SUCCESSFUL\")));\n\t\t\telse if (attack.type == BA_MINDCONTROL)\n\t\t\t{\n\t\t\t\tif (attack.weapon_item->getRules()->convertToCivilian() && victim->getOriginalFaction() == FACTION_HOSTILE)\n\t\t\t\t\tgame->pushState(new InfoboxState(game->getLanguage()->getString(\"STR_MIND_CONTROL_SUCCESSFUL_ALT\")));\n\t\t\t\telse\n\t\t\t\t\tgame->pushState(new InfoboxState(game->getLanguage()->getString(\"STR_MIND_CONTROL_SUCCESSFUL\")));\n\t\t\t}\n\t\t\tgetSave()->getBattleState()->updateSoldierInfo();\n\t\t}\n\t}\n}\n\n\n/**\n * Moves a unit up or down.\n * @param unit The unit.\n * @param dir Direction DIR_UP or DIR_DOWN.\n */\nvoid BattlescapeGame::moveUpDown(BattleUnit *unit, int dir)\n{\n\t_currentAction.target = unit->getPosition();\n\tif (dir == Pathfinding::DIR_UP)\n\t{\n\t\t_currentAction.target.z++;\n\t}\n\telse\n\t{\n\t\t_currentAction.target.z--;\n\t}\n\tgetMap()->setCursorType(CT_NONE);\n\t_parentState->getGame()->getCursor()->setVisible(false);\n\tif (_save->getSelectedUnit()->isKneeled())\n\t{\n\t\tkneel(_save->getSelectedUnit());\n\t}\n\t_save->getPathfinding()->calculate(_currentAction.actor, _currentAction.target, _currentAction.getMoveType());\n\tstatePushBack(new UnitWalkBState(this, _currentAction));\n}\n\n/**\n * Requests the end of the turn (waits for explosions etc to really end the turn).\n */\nvoid BattlescapeGame::requestEndTurn(bool askForConfirmation)\n{\n\tcancelCurrentAction();\n\n\tif (askForConfirmation)\n\t{\n\t\tif (_endConfirmationHandled)\n\t\t\treturn;\n\n\t\t// check for fatal wounds\n\t\tint soldiersWithFatalWounds = 0;\n\t\tfor (const auto* bu : *_save->getUnits())\n\t\t{\n\t\t\tif (bu->getOriginalFaction() == FACTION_PLAYER && bu->getStatus() != STATUS_DEAD && bu->getFatalWounds() > 0)\n\t\t\t\tsoldiersWithFatalWounds++;\n\t\t}\n\n\t\tif (soldiersWithFatalWounds > 0)\n\t\t{\n\t\t\t// confirm end of turn/mission\n\t\t\t_parentState->getGame()->pushState(new ConfirmEndMissionState(_save, soldiersWithFatalWounds, this));\n\t\t\t_endConfirmationHandled = true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (!_endTurnRequested)\n\t\t\t{\n\t\t\t\t_endTurnRequested = true;\n\t\t\t\tstatePushBack(0);\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\tif (!_endTurnRequested)\n\t\t{\n\t\t\t_endTurnRequested = true;\n\t\t\tstatePushBack(0);\n\t\t}\n\t}\n}\n\n/**\n * Sets the TU reserved type.\n * @param tur A BattleActionType.\n * @param player is this requested by the player?\n */\nvoid BattlescapeGame::setTUReserved(BattleActionType tur)\n{\n\t_save->setTUReserved(tur);\n}\n\n/**\n * Drops an item to the floor and affects it with gravity.\n * @param position Position to spawn the item.\n * @param item Pointer to the item.\n * @param newItem Bool whether this is a new item.\n * @param removeItem Bool whether to remove the item from the owner.\n */\nvoid BattlescapeGame::dropItem(Position position, BattleItem *item, bool removeItem, bool updateLight)\n{\n\t_save->getTileEngine()->itemDrop(_save->getTile(position), item, updateLight);\n}\n\n/**\n * Converts a unit into a unit of another type.\n * @param unit The unit to convert.\n * @return Pointer to the new unit.\n */\nBattleUnit *BattlescapeGame::convertUnit(BattleUnit *unit)\n{\n\t_parentState->resetUiButton();\n\n\treturn getSave()->convertUnit(unit);\n}\n\n/**\n * Spawns a new unit mid-battle\n * @param attack BattleActionAttack that calls to spawn the unit\n * @param position Tile position to try and spawn unit on\n */\nvoid BattlescapeGame::spawnNewUnit(BattleItem *item)\n{\n\tspawnNewUnit(BattleActionAttack{ BA_NONE, nullptr, item, item, }, item->getTile()->getPosition());\n}\n\nvoid BattlescapeGame::spawnNewUnit(BattleActionAttack attack, Position position)\n{\n\tif (!attack.damage_item) // no idea how this happened, but make sure we have an item\n\t\treturn;\n\n\tconst RuleItem *item = attack.damage_item->getRules();\n\tconst Unit *type = item->getSpawnUnit();\n\n\tif (!type)\n\t\treturn;\n\n\tint chance = item->getSpawnUnitChance();\n\tif (auto* conf = attack.weapon_item ? attack.weapon_item->getActionConf(attack.type) : nullptr)\n\t{\n\t\tchance = useIntNullable(conf->ammoSpawnUnitChanceOverride, chance);\n\t}\n\n\tif (!RNG::percent(chance))\n\t{\n\t\treturn;\n\t}\n\n\n\tBattleUnit* owner = attack.attacker;\n\tif (owner == nullptr)\n\t{\n\t\towner = attack.damage_item->getOwner();\n\t\tif (owner == nullptr)\n\t\t{\n\t\t\towner = attack.damage_item->getPreviousOwner();\n\t\t}\n\t}\n\n\t// Check which faction the new unit will be\n\tUnitFaction faction;\n\tif (item->getSpawnUnitFaction() == FACTION_NONE && owner)\n\t{\n\t\tfaction = owner->getFaction();\n\t}\n\telse\n\t{\n\t\tswitch (item->getSpawnUnitFaction())\n\t\t{\n\t\t\tcase 0:\n\t\t\t\tfaction = FACTION_PLAYER;\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\t\tfaction = FACTION_HOSTILE;\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\tfaction = FACTION_NEUTRAL;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tfaction = FACTION_HOSTILE;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (_save->isPreview() && faction != FACTION_PLAYER)\n\t{\n\t\treturn;\n\t}\n\n\t// Create the unit\n\tBattleUnit *newUnit = _save->createTempUnit(type, faction);\n\n\t// Validate the position for the unit, checking if there's a surrounding tile if necessary\n\tint checkDirection = attack.attacker ? (attack.attacker->getDirection() + 4) % 8 : 0;\n\tbool positionValid = getTileEngine()->isPositionValidForUnit(position, newUnit, true, checkDirection);\n\tif (positionValid) // Place the unit and initialize it in the battlescape\n\t{\n\t\tint unitDirection = attack.attacker ? attack.attacker->getDirection() : RNG::generate(0, 7);\n\t\t// If this is a tank, arm it with its weapon\n\t\tif (getMod()->getItem(newUnit->getType()) && getMod()->getItem(newUnit->getType())->isFixed())\n\t\t{\n\t\t\tconst RuleItem *newUnitWeapon = getMod()->getItem(newUnit->getType());\n\t\t\tif (!_save->isPreview())\n\t\t\t{\n\t\t\t\t_save->createItemForUnit(newUnitWeapon, newUnit, true);\n\t\t\t\tif (newUnitWeapon->getVehicleClipAmmo())\n\t\t\t\t{\n\t\t\t\t\tconst RuleItem *ammo = newUnitWeapon->getVehicleClipAmmo();\n\t\t\t\t\tBattleItem *ammoItem = _save->createItemForUnit(ammo, newUnit);\n\t\t\t\t\tif (ammoItem)\n\t\t\t\t\t{\n\t\t\t\t\t\tammoItem->setAmmoQuantity(newUnitWeapon->getVehicleClipSize());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tnewUnit->setTurretType(newUnitWeapon->getTurretType());\n\t\t}\n\n\t\t// Pick the item sets if the unit has builtInWeaponSets\n\t\tsize_t itemLevel = (size_t)(getMod()->getAlienItemLevels().at(_save->getAlienItemLevel()).at(RNG::generate(0,9)));\n\n\t\t// Initialize the unit and its position\n\t\tnewUnit->setTile(_save->getTile(position), _save);\n\t\tnewUnit->setPosition(position);\n\t\tnewUnit->setDirection(unitDirection);\n\t\tnewUnit->clearTimeUnits();\n\t\tnewUnit->setPreviousOwner(owner);\n\t\tnewUnit->setVisible(faction == FACTION_PLAYER);\n\t\t_save->getUnits()->push_back(newUnit);\n\t\t_save->initUnit(newUnit, itemLevel);\n\n\t\tgetTileEngine()->applyGravity(newUnit->getTile());\n\t\tgetTileEngine()->calculateFOV(newUnit->getPosition());  //happens fairly rarely, so do a full recalc for units in range to handle the potential unit visible cache issues.\n\t}\n\telse\n\t{\n\t\tdelete newUnit;\n\t}\n}\n\n/**\n * Spawns a new item mid-battle\n * @param attack BattleActionAttack that calls to spawn the item\n * @param position Tile position to try and spawn item on\n */\nvoid BattlescapeGame::spawnNewItem(BattleItem *item)\n{\n\tspawnNewItem(BattleActionAttack{ BA_NONE, nullptr, item, item, }, item->getTile()->getPosition());\n}\n\nvoid BattlescapeGame::spawnNewItem(BattleActionAttack attack, Position position)\n{\n\tif (!attack.damage_item) // no idea how this happened, but make sure we have an item\n\t\treturn;\n\n\tconst RuleItem *item = attack.damage_item->getRules();\n\tconst RuleItem *type = item->getSpawnItem();\n\n\tif (!type)\n\t\treturn;\n\n\tint chance = item->getSpawnItemChance();\n\tif (auto* conf = attack.weapon_item ? attack.weapon_item->getActionConf(attack.type) : nullptr)\n\t{\n\t\tchance = useIntNullable(conf->ammoSpawnItemChanceOverride, chance);\n\t}\n\n\tif (!RNG::percent(chance))\n\t{\n\t\treturn;\n\t}\n\n\tBattleUnit* owner = attack.attacker;\n\tif (owner == nullptr)\n\t{\n\t\towner = attack.damage_item->getOwner();\n\t\tif (owner == nullptr)\n\t\t{\n\t\t\towner = attack.damage_item->getPreviousOwner();\n\t\t}\n\t}\n\n\t// Create the item\n\tauto* newItem = _save->createTempItem(type);\n\n\tauto* tile  = _save->getTile(position);\n\n\tif (tile) // Place the item and initialize it in the battlescape\n\t{\n\t\ttile->addItem(newItem, getMod()->getInventoryGround());\n\t\tnewItem->setPreviousOwner(owner);\n\t\t_save->getItems()->push_back(newItem);\n\t\t_save->initItem(newItem, owner);\n\n\t\tgetTileEngine()->applyGravity(newItem->getTile());\n\t\tif (newItem->getGlow())\n\t\t{\n\t\t\ttile = newItem->getTile(); //item could drop down\n\t\t\tgetTileEngine()->calculateLighting(LL_ITEMS, tile->getPosition());\n\t\t\tgetTileEngine()->calculateFOV(tile->getPosition(), newItem->getVisibilityUpdateRange(), false);\n\t\t}\n\t}\n\telse\n\t{\n\t\tdelete newItem;\n\t}\n}\n\n/**\n * Spawns units from items primed before battle\n */\nvoid BattlescapeGame::spawnFromPrimedItems()\n{\n\tstd::vector<BattleItem*> itemsSpawningUnits;\n\n\tfor (auto* bi : *_save->getItems())\n\t{\n\t\tif (bi->isOwnerIgnored() || !bi->getTile())\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\t\tif ((bi->getRules()->getSpawnUnit() || bi->getRules()->getSpawnItem()) && !bi->getXCOMProperty() && !bi->isSpecialWeapon())\n\t\t{\n\t\t\tif (bi->getRules()->getBattleType() == BT_GRENADE && bi->getFuseTimer() == 0 && bi->isFuseEnabled())\n\t\t\t{\n\t\t\t\titemsSpawningUnits.push_back(bi);\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (auto* item : itemsSpawningUnits)\n\t{\n\t\tspawnNewUnit(item);\n\t\tspawnNewItem(item);\n\t\t_save->removeItem(item);\n\t}\n}\n\n/**\n * Removes spawned units that belong to the player to avoid dealing with recovery\n */\nvoid BattlescapeGame::removeSummonedPlayerUnits()\n{\n\tstd::vector<const Unit*> resummonAsCivilians;\n\n\tauto buIt = _save->getUnits()->begin();\n\twhile (buIt != _save->getUnits()->end())\n\t{\n\t\tauto* bu = (*buIt);\n\t\tif (!bu->isSummonedPlayerUnit())\n\t\t{\n\t\t\t++buIt;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (bu->getStatus() != STATUS_DEAD && bu->getUnitRules())\n\t\t\t{\n\t\t\t\tif (bu->getUnitRules()->isRecoverableAsCivilian())\n\t\t\t\t{\n\t\t\t\t\tresummonAsCivilians.push_back(bu->getUnitRules());\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (bu->getStatus() == STATUS_UNCONSCIOUS || bu->getStatus() == STATUS_DEAD)\n\t\t\t\t_save->removeUnconsciousBodyItem(bu);\n\n\t\t\t//remove all items from unit\n\t\t\tbu->removeSpecialWeapons(_save);\n\t\t\tauto invCopy = *bu->getInventory();\n\t\t\tfor (auto* bi : invCopy)\n\t\t\t{\n\t\t\t\t_save->removeItem(bi);\n\t\t\t}\n\n\t\t\tbu->setTile(nullptr, _save);\n\t\t\t_save->clearUnitSelection(bu);\n\t\t\tdelete bu;\n\t\t\tbuIt = _save->getUnits()->erase(buIt);\n\t\t}\n\t}\n\n\tfor (auto* unitType : resummonAsCivilians)\n\t{\n\t\tBattleUnit *newUnit = new BattleUnit(getMod(),\n\t\t\tunitType,\n\t\t\tFACTION_NEUTRAL,\n\t\t\t_save->getUnits()->back()->getId() + 1,\n\t\t\t_save->getEnviroEffects(),\n\t\t\tunitType->getArmor(),\n\t\t\tnullptr,\n\t\t\tgetDepth(),\n\t\t\t_save->getStartingCondition());\n\n\t\t// just bare minimum, this unit will never be used for anything except recovery (not even for scoring)\n\t\tnewUnit->setTile(nullptr, _save);\n\t\tnewUnit->setPosition(TileEngine::invalid);\n\t\tnewUnit->markAsResummonedFakeCivilian();\n\t\t_save->getUnits()->push_back(newUnit);\n\t}\n}\n\n/**\n * Tally summoned player-controlled VIPs. We may still need to correct this in the Debriefing.\n */\nvoid BattlescapeGame::tallySummonedVIPs()\n{\n\tEscapeType escapeType = _save->getVIPEscapeType();\n\tfor (const auto* unit : *_save->getUnits())\n\t{\n\t\tif (unit->isVIP() && unit->isSummonedPlayerUnit())\n\t\t{\n\t\t\tif (unit->getStatus() == STATUS_DEAD)\n\t\t\t{\n\t\t\t\t_save->addLostVIP(unit->getValue());\n\t\t\t}\n\t\t\telse if (escapeType == ESCAPE_EXIT)\n\t\t\t{\n\t\t\t\tif (unit->isInExitArea(END_POINT))\n\t\t\t\t\t_save->addSavedVIP(unit->getValue());\n\t\t\t\telse\n\t\t\t\t\t_save->addLostVIP(unit->getValue());\n\t\t\t}\n\t\t\telse if (escapeType == ESCAPE_ENTRY)\n\t\t\t{\n\t\t\t\tif (unit->isInExitArea(START_POINT))\n\t\t\t\t\t_save->addSavedVIP(unit->getValue());\n\t\t\t\telse\n\t\t\t\t\t_save->addLostVIP(unit->getValue());\n\t\t\t}\n\t\t\telse if (escapeType == ESCAPE_EITHER)\n\t\t\t{\n\t\t\t\tif (unit->isInExitArea(START_POINT) || unit->isInExitArea(END_POINT))\n\t\t\t\t\t_save->addSavedVIP(unit->getValue());\n\t\t\t\telse\n\t\t\t\t\t_save->addLostVIP(unit->getValue());\n\t\t\t}\n\t\t\telse //if (escapeType == ESCAPE_NONE)\n\t\t\t{\n\t\t\t\tif (unit->isInExitArea(START_POINT))\n\t\t\t\t\t_save->addSavedVIP(unit->getValue()); // waiting in craft, saved even if aborted\n\t\t\t\telse\n\t\t\t\t\t_save->addWaitingOutsideVIP(unit->getValue()); // waiting outside, lost if aborted\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Gets the map.\n * @return map.\n */\nMap *BattlescapeGame::getMap()\n{\n\treturn _parentState->getMap();\n}\n\n/**\n * Gets the save.\n * @return save.\n */\nSavedBattleGame *BattlescapeGame::getSave()\n{\n\treturn _save;\n}\n\n/**\n * Gets the tile engine.\n * @return tile engine.\n */\nTileEngine *BattlescapeGame::getTileEngine()\n{\n\treturn _save->getTileEngine();\n}\n\n/**\n * Gets the pathfinding.\n * @return pathfinding.\n */\nPathfinding *BattlescapeGame::getPathfinding()\n{\n\treturn _save->getPathfinding();\n}\n\n/**\n * Gets the mod.\n * @return mod.\n */\nMod *BattlescapeGame::getMod()\n{\n\treturn _parentState->getGame()->getMod();\n}\n\n\n/**\n * Tries to find an item and pick it up if possible.\n * @return True if an item was picked up, false otherwise.\n */\nbool BattlescapeGame::findItem(BattleAction *action, bool pickUpWeaponsMoreActively, bool& walkToItem)\n{\n\t// terrorists don't have hands.\n\tif (action->actor->getRankString() != \"STR_LIVE_TERRORIST\" || pickUpWeaponsMoreActively)\n\t{\n\t\t// pick the best available item\n\t\tBattleItem *targetItem = surveyItems(action, pickUpWeaponsMoreActively);\n\t\t// make sure it's worth taking\n\t\tif (targetItem && worthTaking(targetItem, action, pickUpWeaponsMoreActively))\n\t\t{\n\t\t\t// if we're already standing on it...\n\t\t\tif (targetItem->getTile()->getPosition() == action->actor->getPosition())\n\t\t\t{\n\t\t\t\t// try to pick it up\n\t\t\t\tif (takeItemFromGround(targetItem, action) == 0)\n\t\t\t\t{\n\t\t\t\t\t// if it isn't loaded or it is ammo\n\t\t\t\t\tif (!targetItem->haveAnyAmmo())\n\t\t\t\t\t{\n\t\t\t\t\t\t// try to load our weapon\n\t\t\t\t\t\taction->actor->reloadAmmo();\n\t\t\t\t\t}\n\t\t\t\t\tif (targetItem->getGlow())\n\t\t\t\t\t{\n\t\t\t\t\t\t_save->getTileEngine()->calculateLighting(LL_ITEMS, action->actor->getPosition());\n\t\t\t\t\t\t_save->getTileEngine()->calculateFOV(action->actor->getPosition(), targetItem->getVisibilityUpdateRange(), false);\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (!targetItem->getTile()->getUnit() || targetItem->getTile()->getUnit()->isOut())\n\t\t\t{\n\t\t\t\t// if we're not standing on it, we should try to get to it.\n\t\t\t\taction->target = targetItem->getTile()->getPosition();\n\t\t\t\taction->type = BA_WALK;\n\t\t\t\twalkToItem = true;\n\t\t\t\tif (pickUpWeaponsMoreActively)\n\t\t\t\t{\n\t\t\t\t\t// don't end the turn after walking 1-2 tiles... pick up a weapon and shoot!\n\t\t\t\t\taction->finalAction = false;\n\t\t\t\t\taction->desperate = false;\n\t\t\t\t\taction->actor->setHiding(false);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\n\n/**\n * Searches through items on the map that were dropped on an alien turn, then picks the most \"attractive\" one.\n * @param action A pointer to the action being performed.\n * @return The item to attempt to take.\n */\nBattleItem *BattlescapeGame::surveyItems(BattleAction *action, bool pickUpWeaponsMoreActively)\n{\n\tstd::vector<BattleItem*> droppedItems;\n\n\t// first fill a vector with items on the ground that were dropped on the alien turn, and have an attraction value.\n\tfor (auto* bi : *_save->getItems())\n\t{\n\t\tif (bi->isOwnerIgnored())\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (bi->getRules()->getAttraction())\n\t\t{\n\t\t\tif (bi->getTurnFlag() || pickUpWeaponsMoreActively)\n\t\t\t{\n\n\t\t\t\tif (bi->getSlot() && bi->getSlot()->getType() == INV_GROUND && bi->getTile() && !bi->getTile()->getDangerous())\n\t\t\t\t{\n\t\t\t\t\tdroppedItems.push_back(bi);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tBattleItem *targetItem = 0;\n\tint maxWorth = 0;\n\n\t// now select the most suitable candidate depending on attractiveness and distance\n\t// (are we still talking about items?)\n\tfor (auto* bi : droppedItems)\n\t{\n\t\tif (bi->getTile()->getDangerous())\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\t\tint currentWorth = bi->getRules()->getAttraction() / ((Position::distance2d(action->actor->getPosition(), bi->getTile()->getPosition()) * 2)+1);\n\t\tif (currentWorth > maxWorth)\n\t\t{\n\t\t\tif (bi->getTile()->getTUCost(O_OBJECT, action->actor->getMovementType()) == 255)\n\t\t\t{\n\t\t\t\t// Note: full pathfinding check will be done later, this is just a small optimisation\n\t\t\t\tbi->getTile()->setDangerous(true);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tmaxWorth = currentWorth;\n\t\t\ttargetItem = bi;\n\t\t}\n\t}\n\n\treturn targetItem;\n}\n\n\n/**\n * Assesses whether this item is worth trying to pick up, taking into account how many units we see,\n * whether or not the Weapon has ammo, and if we have ammo FOR it,\n * or, if it's ammo, checks if we have the weapon to go with it,\n * assesses the attraction value of the item and compares it with the distance to the object,\n * then returns false anyway.\n * @param item The item to attempt to take.\n * @param action A pointer to the action being performed.\n * @return false.\n */\nbool BattlescapeGame::worthTaking(BattleItem* item, BattleAction *action, bool pickUpWeaponsMoreActively)\n{\n\tint worthToTake = 0;\n\n\t// don't even think about making a move for that gun if you can see a target, for some reason\n\t// (maybe this should check for enemies spotting the tile the item is on?)\n\tif (action->actor->getVisibleUnits()->empty() || pickUpWeaponsMoreActively)\n\t{\n\t\t// retrieve an insignificantly low value from the ruleset.\n\t\tworthToTake = item->getRules()->getAttraction();\n\n\t\t// it's always going to be worth while to try and take a blaster launcher, apparently\n\t\tif (item->getRules()->getBattleType() == BT_FIREARM && item->getCurrentWaypoints() == 0)\n\t\t{\n\t\t\t// we only want weapons that HAVE ammo, or weapons that we have ammo FOR\n\t\t\tbool ammoFound = true;\n\t\t\tif (!item->haveAnyAmmo())\n\t\t\t{\n\t\t\t\tammoFound = false;\n\t\t\t\tfor (const auto* bi : *action->actor->getInventory())\n\t\t\t\t{\n\t\t\t\t\tif (bi->getRules()->getBattleType() == BT_AMMO)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (item->getRules()->getSlotForAmmo(bi->getRules()) != -1)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tammoFound = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!ammoFound)\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tif (item->getRules()->getBattleType() == BT_AMMO)\n\t\t{\n\t\t\t// similar to the above, but this time we're checking if the ammo is suitable for a weapon we have.\n\t\t\tbool weaponFound = false;\n\t\t\tfor (const auto* bi : *action->actor->getInventory())\n\t\t\t{\n\t\t\t\tif (bi->getRules()->getBattleType() == BT_FIREARM)\n\t\t\t\t{\n\t\t\t\t\tif (bi->getRules()->getSlotForAmmo(item->getRules()) != -1)\n\t\t\t\t\t{\n\t\t\t\t\t\tweaponFound = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!weaponFound)\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (worthToTake)\n\t{\n\t\t// use bad logic to determine if we'll have room for the item\n\t\tint freeSlots = 25;\n\t\tfor (const auto* bi : *action->actor->getInventory())\n\t\t{\n\t\t\tfreeSlots -= bi->getRules()->getInventoryHeight() * bi->getRules()->getInventoryWidth();\n\t\t}\n\t\tint size = item->getRules()->getInventoryHeight() * item->getRules()->getInventoryWidth();\n\t\tif (freeSlots < size)\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tif (pickUpWeaponsMoreActively)\n\t{\n\t\t// Note: always true, the item must have passed this test already in surveyItems()\n\t\treturn worthToTake > 0;\n\t}\n\n\t// return false for any item that we aren't standing directly on top of with an attraction value less than 6 (aka always)\n\treturn (worthToTake - (Position::distance2d(action->actor->getPosition(), item->getTile()->getPosition())*2)) > 5;\n}\n\n\n/**\n * Picks the item up from the ground.\n *\n * At this point we've decided it's worth our while to grab this item, so we try to do just that.\n * First we check to make sure we have time units, then that we have space (using horrifying logic)\n * then we attempt to actually recover the item.\n * @param item The item to attempt to take.\n * @param action A pointer to the action being performed.\n * @return 0 if successful, 1 for no TUs, 2 for not enough room, 3 for \"won't fit\" and -1 for \"something went horribly wrong\".\n */\nint BattlescapeGame::takeItemFromGround(BattleItem* item, BattleAction *action)\n{\n\tconst int success = 0;\n\tconst int notEnoughTimeUnits = 1;\n\tconst int notEnoughSpace = 2;\n\tconst int couldNotFit = 3;\n\tint freeSlots = 25;\n\n\t// make sure we have time units\n\tif (action->actor->getTimeUnits() < 6)\n\t{\n\t\treturn notEnoughTimeUnits;\n\t}\n\telse\n\t{\n\t\t// check to make sure we have enough space by checking all the sizes of items in our inventory\n\t\tfor (const auto* bi : *action->actor->getInventory())\n\t\t{\n\t\t\tfreeSlots -= bi->getRules()->getInventoryHeight() * bi->getRules()->getInventoryWidth();\n\t\t}\n\t\tif (freeSlots < item->getRules()->getInventoryHeight() * item->getRules()->getInventoryWidth())\n\t\t{\n\t\t\treturn notEnoughSpace;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// check that the item will fit in our inventory, and if so, take it\n\t\t\tif (takeItem(item, action))\n\t\t\t{\n\t\t\t\treturn success;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn couldNotFit;\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/**\n * Tries to fit an item into the unit's inventory, return false if you can't.\n * @param item The item to attempt to take.\n * @param action A pointer to the action being performed.\n * @return Whether or not the item was successfully retrieved.\n */\nbool BattlescapeGame::takeItem(BattleItem* item, BattleAction *action)\n{\n\tbool placed = false;\n\tMod *mod = _parentState->getGame()->getMod();\n\tauto* rightWeapon = action->actor->getRightHandWeapon();\n\tauto* leftWeapon = action->actor->getLeftHandWeapon();\n\tauto* unit = action->actor;\n\n\tauto reloadWeapon = [&unit](BattleItem* weapon, BattleItem* i)\n\t{\n\t\tif (weapon && weapon->isWeaponWithAmmo() && !weapon->haveAllAmmo())\n\t\t{\n\t\t\tint slot = weapon->getRules()->getSlotForAmmo(i->getRules());\n\t\t\tif (slot != -1)\n\t\t\t{\n\t\t\t\tBattleActionCost cost{ unit };\n\t\t\t\tcost.Time += Mod::EXTENDED_ITEM_RELOAD_COST ? i->getMoveToCost(weapon->getSlot()) : 0;\n\t\t\t\tcost.Time += weapon->getRules()->getTULoad(slot);\n\t\t\t\tif (cost.haveTU() && !weapon->getAmmoForSlot(slot))\n\t\t\t\t{\n\t\t\t\t\tweapon->setAmmoForSlot(slot, i);\n\t\t\t\t\tcost.spendTU();\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t};\n\n\tauto equipItem = [&unit](RuleInventory *slot, BattleItem* i)\n\t{\n\t\tBattleActionCost cost{ unit };\n\t\tcost.Time += i->getMoveToCost(slot);\n\t\tif (cost.haveTU() && unit->fitItemToInventory(slot, i))\n\t\t{\n\t\t\tcost.spendTU();\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t};\n\n\tswitch (item->getRules()->getBattleType())\n\t{\n\tcase BT_AMMO:\n\t\t// find equipped weapons that can be loaded with this ammo\n\t\tif (reloadWeapon(rightWeapon, item))\n\t\t{\n\t\t\tplaced = true;\n\t\t}\n\t\telse if (reloadWeapon(leftWeapon, item))\n\t\t{\n\t\t\tplaced = true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tplaced = equipItem(mod->getInventoryBelt(), item);\n\t\t}\n\t\tbreak;\n\tcase BT_GRENADE:\n\tcase BT_PROXIMITYGRENADE:\n\t\tplaced = equipItem(mod->getInventoryBelt(), item);\n\t\tbreak;\n\tcase BT_FIREARM:\n\tcase BT_MELEE:\n\t\tif (!rightWeapon)\n\t\t{\n\t\t\tplaced = equipItem(mod->getInventoryRightHand(), item);\n\t\t}\n\t\tbreak;\n\tcase BT_MEDIKIT:\n\tcase BT_SCANNER:\n\t\tplaced = equipItem(mod->getInventoryBackpack(), item);\n\t\tbreak;\n\tcase BT_MINDPROBE:\n\t\tif (!leftWeapon)\n\t\t{\n\t\t\tplaced = equipItem(mod->getInventoryLeftHand(), item);\n\t\t}\n\t\tbreak;\n\tdefault: break;\n\t}\n\treturn placed;\n}\n\n/**\n * Returns the action type that is reserved.\n * @return The type of action that is reserved.\n */\nBattleActionType BattlescapeGame::getReservedAction()\n{\n\treturn _save->getTUReserved();\n}\n\nbool BattlescapeGame::isSurrendering(BattleUnit* bu)\n{\n\t// if we already decided to surrender this turn, don't change our decision (until next turn)\n\tif (bu->isSurrendering())\n\t{\n\t\treturn true;\n\t}\n\n\tint surrenderMode = getMod()->getSurrenderMode();\n\n\t// auto-surrender (e.g. units, which won't fight without their masters/controllers)\n\tif (surrenderMode > 0 && bu->getUnitRules()->autoSurrender())\n\t{\n\t\tbu->setSurrendering(true);\n\t\treturn true;\n\t}\n\n\t// surrender under certain conditions\n\tif (surrenderMode == 0)\n\t{\n\t\t// turned off, no surrender\n\t}\n\telse if (surrenderMode == 1)\n\t{\n\t\t// all remaining enemy units can surrender and want to surrender now\n\t\tif (bu->getUnitRules()->canSurrender() && (bu->getStatus() == STATUS_PANICKING || bu->getStatus() == STATUS_BERSERK))\n\t\t{\n\t\t\tbu->setSurrendering(true);\n\t\t}\n\t}\n\telse if (surrenderMode == 2)\n\t{\n\t\t// all remaining enemy units can surrender and want to surrender now or wanted to surrender in the past\n\t\tif (bu->getUnitRules()->canSurrender() && bu->wantsToSurrender())\n\t\t{\n\t\t\tbu->setSurrendering(true);\n\t\t}\n\t}\n\telse if (surrenderMode == 3)\n\t{\n\t\t// all remaining enemy units have empty hands and want to surrender now or wanted to surrender in the past\n\t\tif (!bu->getLeftHandWeapon() && !bu->getRightHandWeapon() && bu->wantsToSurrender())\n\t\t{\n\t\t\tbu->setSurrendering(true);\n\t\t}\n\t}\n\n\treturn bu->isSurrendering();\n}\n\n/**\n * Tallies the living units in the game and, if required, converts units into their spawn unit.\n */\nBattlescapeTally BattlescapeGame::tallyUnits()\n{\n\tBattlescapeTally tally = { };\n\n\tfor (auto* bu : *_save->getUnits())\n\t{\n\t\t//TODO: add handling of stunned units for display purposes in AbortMissionState\n\t\tif (!bu->isOut() && (!bu->isOutThresholdExceed() || (bu->getUnitRules() && bu->getUnitRules()->getSpawnUnit())))\n\t\t{\n\t\t\tif (bu->getOriginalFaction() == FACTION_HOSTILE)\n\t\t\t{\n\t\t\t\tif (Options::allowPsionicCapture && bu->getFaction() == FACTION_PLAYER && bu->getCapturable())\n\t\t\t\t{\n\t\t\t\t\t// don't count psi-captured units\n\t\t\t\t}\n\t\t\t\telse if (isSurrendering(bu) && bu->getCapturable())\n\t\t\t\t{\n\t\t\t\t\t// don't count surrendered units\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\ttally.liveAliens++;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (bu->getOriginalFaction() == FACTION_PLAYER)\n\t\t\t{\n\t\t\t\tif (bu->isSummonedPlayerUnit())\n\t\t\t\t{\n\t\t\t\t\tif (bu->isVIP())\n\t\t\t\t\t{\n\t\t\t\t\t\t// used only for display purposes in AbortMissionState\n\t\t\t\t\t\t// count only player-controlled VIPs, not civilian VIPs!\n\t\t\t\t\t\tif (bu->isInExitArea(START_POINT))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttally.vipInEntrance++;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (bu->isInExitArea(END_POINT))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (bu->isBannedInNextStage())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// this guy would (theoretically) go into timeout\n\t\t\t\t\t\t\t\ttally.vipInField++;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttally.vipInExit++;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttally.vipInField++;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (bu->isInExitArea(START_POINT))\n\t\t\t\t{\n\t\t\t\t\ttally.inEntrance++;\n\t\t\t\t}\n\t\t\t\telse if (bu->isInExitArea(END_POINT))\n\t\t\t\t{\n\t\t\t\t\tif (bu->isBannedInNextStage())\n\t\t\t\t\t{\n\t\t\t\t\t\t// this guy will go into timeout\n\t\t\t\t\t\ttally.inField++;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\ttally.inExit++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\ttally.inField++;\n\t\t\t\t}\n\n\t\t\t\tif (bu->getFaction() == FACTION_PLAYER)\n\t\t\t\t{\n\t\t\t\t\ttally.liveSoldiers++;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\ttally.liveAliens++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn tally;\n}\n\nbool BattlescapeGame::convertInfected()\n{\n\tbool retVal = false;\n\tstd::vector<BattleUnit*> forTransform;\n\tfor (auto* bu : *_save->getUnits())\n\t{\n\t\tif (!bu->isOutThresholdExceed() && bu->getRespawn())\n\t\t{\n\t\t\tretVal = true;\n\t\t\tbu->setRespawn(false);\n\t\t\tif (Options::battleNotifyDeath && bu->getFaction() == FACTION_PLAYER)\n\t\t\t{\n\t\t\t\tGame *game = _parentState->getGame();\n\t\t\t\tgame->pushState(new InfoboxState(game->getLanguage()->getString(\"STR_HAS_BEEN_KILLED\", bu->getGender()).arg(bu->getName(game->getLanguage()))));\n\t\t\t}\n\n\t\t\tforTransform.push_back(bu);\n\t\t}\n\t}\n\n\tfor (auto* bu : forTransform)\n\t{\n\t\tconvertUnit(bu);\n\t}\n\treturn retVal;\n}\n\n/**\n * Sets the kneel reservation setting.\n * @param reserved Should we reserve an extra 4 TUs to kneel?\n */\nvoid BattlescapeGame::setKneelReserved(bool reserved)\n{\n\t_save->setKneelReserved(reserved);\n}\n\n/**\n * Gets the kneel reservation setting.\n * @return Kneel reservation setting.\n */\nbool BattlescapeGame::getKneelReserved() const\n{\n\treturn _save->getKneelReserved();\n}\n\n/**\n * Checks if a unit has moved next to a proximity grenade.\n * Checks one tile around the unit in every direction.\n * For a large unit we check every tile it occupies.\n * @param unit Pointer to a unit.\n * @return 2 if a proximity grenade was triggered, 1 if light was changed.\n */\nint BattlescapeGame::checkForProximityGrenades(BattleUnit *unit)\n{\n\tif (_save->isPreview())\n\t{\n\t\treturn 0;\n\t}\n\n\t// death trap?\n\tTile* deathTrapTile = nullptr;\n\tfor (int sx = 0; sx < unit->getArmor()->getSize(); sx++)\n\t{\n\t\tfor (int sy = 0; sy < unit->getArmor()->getSize(); sy++)\n\t\t{\n\t\t\tTile* t = _save->getTile(unit->getPosition() + Position(sx, sy, 0));\n\t\t\tif (!deathTrapTile && t && t->getFloorSpecialTileType() >= DEATH_TRAPS)\n\t\t\t{\n\t\t\t\tdeathTrapTile = t;\n\t\t\t}\n\t\t}\n\t}\n\tif (deathTrapTile)\n\t{\n\t\tstd::ostringstream ss;\n\t\tss << \"STR_DEATH_TRAP_\" << deathTrapTile->getFloorSpecialTileType();\n\t\tauto* deathTrapRule = getMod()->getItem(ss.str());\n\t\tif (deathTrapRule &&\n\t\t\tdeathTrapRule->isTargetAllowed(unit->getOriginalFaction(), FACTION_PLAYER) && // FACTION_PLAYER for backward compatibility reasons\n\t\t\t(deathTrapRule->getBattleType() == BT_PROXIMITYGRENADE || deathTrapRule->getBattleType() == BT_MELEE))\n\t\t{\n\t\t\tBattleItem* deathTrapItem = nullptr;\n\t\t\tfor (auto* item : *deathTrapTile->getInventory())\n\t\t\t{\n\t\t\t\tif (item->getRules() == deathTrapRule)\n\t\t\t\t{\n\t\t\t\t\tdeathTrapItem = item;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!deathTrapItem)\n\t\t\t{\n\t\t\t\tdeathTrapItem = _save->createItemForTile(deathTrapRule, deathTrapTile);\n\t\t\t}\n\t\t\tif (deathTrapRule->getBattleType() == BT_PROXIMITYGRENADE)\n\t\t\t{\n\t\t\t\tdeathTrapItem->setFuseTimer(0);\n\t\t\t\tPosition p = deathTrapTile->getPosition().toVoxel() + Position(8, 8, deathTrapTile->getTerrainLevel());\n\t\t\t\tstatePushNext(new ExplosionBState(this, p, BattleActionAttack::GetBeforeShoot(BA_TRIGGER_PROXY_GRENADE, nullptr, deathTrapItem)));\n\t\t\t\treturn 2;\n\t\t\t}\n\t\t\telse if (deathTrapRule->getBattleType() == BT_MELEE)\n\t\t\t{\n\t\t\t\tPosition p = deathTrapTile->getPosition().toVoxel() + Position(8, 8, 12);\n\t\t\t\t// EXPERIMENTAL: terrainMeleeTilePart = 4 (V_UNIT); no attacker\n\t\t\t\tstatePushNext(new ExplosionBState(this, p, BattleActionAttack::GetBeforeShoot(BA_HIT, nullptr, deathTrapItem), nullptr, false, 0, 0, 4));\n\t\t\t\treturn 2;\n\t\t\t}\n\t\t}\n\t}\n\n\tbool exploded = false;\n\tbool glow = false;\n\tint size = unit->getArmor()->getSize() + 1;\n\tfor (int tx = -1; tx < size; tx++)\n\t{\n\t\tfor (int ty = -1; ty < size; ty++)\n\t\t{\n\t\t\tTile *t = _save->getTile(unit->getPosition() + Position(tx,ty,0));\n\t\t\tif (t)\n\t\t\t{\n\t\t\t\tstd::vector<BattleItem*> forRemoval;\n\t\t\t\tfor (BattleItem *item : *t->getInventory())\n\t\t\t\t{\n\t\t\t\t\tconst RuleItem *ruleItem = item->getRules();\n\t\t\t\t\tbool g = item->getGlow();\n\t\t\t\t\tif (item->fuseProximityEvent())\n\t\t\t\t\t{\n\t\t\t\t\t\tif (ruleItem->getBattleType() == BT_GRENADE || ruleItem->getBattleType() == BT_PROXIMITYGRENADE)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tPosition p = t->getPosition().toVoxel() + Position(8, 8, t->getTerrainLevel());\n\t\t\t\t\t\t\tstatePushNext(new ExplosionBState(this, p, BattleActionAttack::GetBeforeShoot(BA_TRIGGER_PROXY_GRENADE, nullptr, item)));\n\t\t\t\t\t\t\texploded = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tforRemoval.push_back(item);\n\t\t\t\t\t\t\tif (g)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tglow = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tif (g != item->getGlow())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tglow = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfor (BattleItem *item : forRemoval)\n\t\t\t\t{\n\t\t\t\t\t_save->removeItem(item);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn exploded ? 2 : glow ? 1 : 0;\n}\n\n/**\n * Cleans up all the deleted states.\n */\nvoid BattlescapeGame::cleanupDeleted()\n{\n\tfor (auto* bs : _deleted)\n\t{\n\t\tdelete bs;\n\t}\n\t_deleted.clear();\n}\n\n/**\n * Gets the depth of the battlescape.\n * @return the depth of the battlescape.\n */\nint BattlescapeGame::getDepth() const\n{\n\treturn _save->getDepth();\n}\n\n/**\n * Play sound on battlefield (with direction).\n */\nvoid BattlescapeGame::playSound(int sound, const Position &pos)\n{\n\tif (sound != Mod::NO_SOUND)\n\t{\n\t\t_parentState->getGame()->getMod()->getSoundByDepth(_save->getDepth(), sound)->play(-1, _parentState->getMap()->getSoundAngle(pos));\n\t}\n}\n\n/**\n * Play sound on battlefield.\n */\nvoid BattlescapeGame::playSound(int sound)\n{\n\tif (sound != Mod::NO_SOUND)\n\t{\n\t\t_parentState->getGame()->getMod()->getSoundByDepth(_save->getDepth(), sound)->play();\n\t}\n}\n\n/**\n * Play unit response sound on battlefield.\n */\nvoid BattlescapeGame::playUnitResponseSound(BattleUnit *unit, int type)\n{\n\tif (!getMod()->getEnableUnitResponseSounds())\n\t\treturn;\n\n\tif (!Options::oxceEnableUnitResponseSounds)\n\t\treturn;\n\n\tif (!unit)\n\t\treturn;\n\n\tint chance = Mod::UNIT_RESPONSE_SOUNDS_FREQUENCY[type];\n\tif (chance < 100 && RNG::seedless(0, 99) >= chance)\n\t{\n\t\treturn;\n\t}\n\n\tstd::vector<int> sounds;\n\tif (type == 0)\n\t\tsounds = unit->getSelectUnitSounds();\n\telse if (type == 1)\n\t\tsounds = unit->getStartMovingSounds();\n\telse if (type == 2)\n\t\tsounds = unit->getSelectWeaponSounds();\n\telse if (type == 3)\n\t\tsounds = unit->getAnnoyedSounds();\n\n\tint sound = -1;\n\tif (!sounds.empty())\n\t{\n\t\tif (sounds.size() > 1)\n\t\t\tsound = sounds[RNG::seedless(0, sounds.size() - 1)];\n\t\telse\n\t\t\tsound = sounds.front();\n\t}\n\n\tif (sound != Mod::NO_SOUND)\n\t{\n\t\tif (!Mix_Playing(4))\n\t\t{\n\t\t\t// use fixed channel, so that we can check if the unit isn't already/still talking\n\t\t\tgetMod()->getSoundByDepth(_save->getDepth(), sound)->play(4);\n\t\t}\n\t}\n}\n\n\nstd::list<BattleState*> BattlescapeGame::getStates()\n{\n\treturn _states;\n}\n\n/**\n * Ends the turn if auto-end battle is enabled\n * and all mission objectives are completed.\n */\nvoid BattlescapeGame::autoEndBattle()\n{\n\tif (_save->isPreview())\n\t{\n\t\treturn;\n\t}\n\tif (Options::battleAutoEnd)\n\t{\n\t\tif (_save->getVIPSurvivalPercentage() > 0 && _save->getVIPEscapeType() != ESCAPE_NONE)\n\t\t{\n\t\t\treturn; // \"escort the VIPs\" missions don't end when all aliens are neutralized\n\t\t}\n\t\tbool end = false;\n\t\tbool askForConfirmation = false;\n\t\tif (_save->getObjectiveType() == MUST_DESTROY)\n\t\t{\n\t\t\tend = _save->allObjectivesDestroyed();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tBattlescapeTally tally = tallyUnits();\n\t\t\tend = (tally.liveAliens == 0 || tally.liveSoldiers == 0);\n\t\t\tif (tally.liveAliens == 0)\n\t\t\t{\n\t\t\t\t_allEnemiesNeutralized = true; // remember that all aliens were neutralized (and the battle should end no matter what)\n\t\t\t\taskForConfirmation = true;\n\t\t\t}\n\t\t}\n\t\tif (end)\n\t\t{\n\t\t\t_save->setSelectedUnit(0);\n\t\t\tcancelCurrentAction(true);\n\t\t\trequestEndTurn(askForConfirmation);\n\t\t}\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/BattlescapeGame.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http:///www.gnu.org/licenses/>.\n */\n#include \"Position.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"../Engine/HelperMeta.h\"\n#include <string>\n#include <list>\n#include <vector>\n\nnamespace OpenXcom\n{\n\nclass BattleUnit;\nclass SavedBattleGame;\nclass BattleItem;\nclass BattleState;\nclass BattlescapeState;\nclass Map;\nclass TileEngine;\nclass Pathfinding;\nclass Mod;\nclass InfoboxOKState;\nclass SoldierDiary;\nclass RuleSkill;\n\nenum BattleActionMove : char { BAM_NORMAL = 0, BAM_RUN = 1, BAM_STRAFE = 2, BAM_SNEAK = 3, BAM_MISSILE = 4 };\n\nstruct BattleActionCost : RuleItemUseCost\n{\n\tBattleActionType type;\n\tBattleUnit *actor = nullptr;\n\tBattleItem *weapon = nullptr;\n\tconst RuleSkill* skillRules = nullptr; // if defined, this is a skill action\n\n\t/// Default constructor.\n\tBattleActionCost() : type(BA_NONE) { }\n\n\t/// Constructor from unit.\n\tBattleActionCost(BattleUnit *unit) : type(BA_NONE), actor(unit) { }\n\n\t/// Constructor with update.\n\tBattleActionCost(BattleActionType action, BattleUnit *unit, BattleItem *item) : type(action), actor(unit), weapon(item) { updateTU(); }\n\n\t/// Update value of TU based of actor, weapon and type.\n\tvoid updateTU();\n\t/// Set TU to zero.\n\tvoid clearTU();\n\t/// Test if actor have enough TU to perform weapon action.\n\tbool haveTU(std::string *message = 0);\n\t/// Spend TU when actor have enough TU.\n\tbool spendTU(std::string *message = 0);\n};\n\nstruct BattleAction : BattleActionCost\n{\n\tPosition target;\n\tstd::list<Position> waypoints;\n\tbool targeting;\n\tint value;\n\tstd::string result;\n\tbool strafe = false;\n\tbool run = false;\n\tbool sneak = false;\n\tbool ignoreSpottedEnemies = false;\n\tbool kneel = false;\n\tint diff;\n\tint autoShotCounter;\n\tPosition cameraPosition;\n\tbool desperate; // ignoring newly-spotted units\n\tint finalFacing;\n\tbool finalAction;\n\tint number; // first action of turn, second, etc.?\n\tbool sprayTargeting; // Used to separate waypoint checks between confirm firing mode and the \"spray\" autoshot\n\tBattleActionOrigin relativeOrigin = BattleActionOrigin::CENTRE; // preferred origin voxel (centre, left or right)\n\tint terrainMeleeTilePart = 0; // terrain melee\n\n\t/// Default constructor\n\tBattleAction() : target(-1, -1, -1), targeting(false), value(0), diff(0), autoShotCounter(0), cameraPosition(0, 0, -1), desperate(false), finalFacing(-1), finalAction(false), number(0), sprayTargeting(false) { }\n\n\t/// Get move type\n\tBattleActionMove getMoveType() const\n\t{\n\t\treturn strafe ? BAM_STRAFE : run ? BAM_RUN : sneak ? BAM_SNEAK : BAM_NORMAL;\n\t}\n};\n\n\n/**\n * Count of different state of units to determine who wins\n */\nstruct BattlescapeTally\n{\n\t/// number of live enemies (aliens and MC'ed soldiers)\n\tint liveAliens = 0;\n\t/// number of live soldiers (only ones that are not MC'ed, including tanks, but not summoned units)\n\tint liveSoldiers = 0;\n\n\t/// number of live soldiers on entrance tiles\n\tint inEntrance = 0;\n\t/// number of live soldiers on exit tiles.\n\tint inExit = 0;\n\t/// number of live soldiers in the middle of the battlefield.\n\tint inField = 0;\n\n\t/// number of live VIPs on entrance tiles\n\tint vipInEntrance = 0;\n\t/// number of live VIPs on exit tiles.\n\tint vipInExit = 0;\n\t/// number of live VIPs in the middle of the battlefield.\n\tint vipInField = 0;\n};\n\n/**\n * Battlescape game - the core game engine of the battlescape game.\n */\nclass BattlescapeGame\n{\nprivate:\n\tSavedBattleGame *_save;\n\tBattlescapeState *_parentState;\n\tstd::list<BattleState*> _states, _deleted;\n\tbool _playerPanicHandled;\n\tint _AIActionCounter;\n\tBattleAction _currentAction;\n\tbool _AISecondMove, _playedAggroSound;\n\tbool _endTurnRequested;\n\tbool _endConfirmationHandled;\n\tbool _allEnemiesNeutralized;\n\n\thelper::SingleRun _endTurnProcessed;\n\thelper::SingleRun _triggerProcessed;\n\n\t/// Ends the turn.\n\tvoid endTurn();\n\t/// Picks the first soldier that is panicking.\n\tbool handlePanickingPlayer();\n\t/// Common function for handling panicking units.\n\tbool handlePanickingUnit(BattleUnit *unit);\n\t/// Determines whether there are any actions pending for the given unit.\n\tbool noActionsPending(BattleUnit *bu);\n\tstd::vector<InfoboxOKState*> _infoboxQueue;\n\t/// Shows the infoboxes in the queue (if any).\n\tvoid showInfoBoxQueue();\npublic:\n\t/// is debug mode enabled in the battlescape?\n\tstatic bool _debugPlay;\n\n\t/// Creates the BattlescapeGame state.\n\tBattlescapeGame(SavedBattleGame *save, BattlescapeState *parentState);\n\t/// Cleans up the BattlescapeGame state.\n\t~BattlescapeGame();\n\t/// Checks for units panicking or falling and so on.\n\tint think();\n\t/// Initializes the Battlescape game.\n\tvoid init();\n\t/// Determines whether a playable unit is selected.\n\tbool playableUnitSelected() const;\n\t/// Handles states timer.\n\tvoid handleState();\n\t/// Pushes a state to the front of the list.\n\tvoid statePushFront(BattleState *bs);\n\t/// Pushes a state to second on the list.\n\tvoid statePushNext(BattleState *bs);\n\t/// Pushes a state to the back of the list.\n\tvoid statePushBack(BattleState *bs);\n\t/// Handles the result of non target actions, like priming a grenade.\n\tvoid handleNonTargetAction();\n\t/// Removes current state.\n\tvoid popState();\n\t/// Sets state think interval.\n\tvoid setStateInterval(Uint32 interval);\n\t/// Checks for casualties in battle.\n\tvoid checkForCasualties(const RuleDamageType *damageType, BattleActionAttack attack, bool hiddenExplosion = false, bool terrainExplosion = false);\n\t/// Checks reserved tu and energy.\n\tbool checkReservedTU(BattleUnit *bu, int tu, int energy, bool justChecking = false);\n\t/// Handles unit AI.\n\tvoid handleAI(BattleUnit *unit);\n\t/// Drops an item and affects it with gravity.\n\tvoid dropItem(Position position, BattleItem *item, bool removeItem = false, bool updateLight = true);\n\t/// Converts a unit into a unit of another type.\n\tBattleUnit *convertUnit(BattleUnit *unit);\n\t/// Spawns a new unit in the middle of battle.\n\tvoid spawnNewUnit(BattleItem *item);\n\tvoid spawnNewUnit(BattleActionAttack attack, Position position);\n\t/// Spawns a new item in the middle of battle.\n\tvoid spawnNewItem(BattleItem *item);\n\tvoid spawnNewItem(BattleActionAttack attack, Position position);\n\t/// Spawns units from items that explode before battle\n\tvoid spawnFromPrimedItems();\n\t/// Removes spawned units that belong to the player to avoid dealing with recovery\n\tvoid removeSummonedPlayerUnits();\n\t/// Tally summoned player-controlled VIPs. We may still need to correct this in the Debriefing.\n\tvoid tallySummonedVIPs();\n\t/// Handles kneeling action.\n\tbool kneel(BattleUnit *bu);\n\t/// Cancels the current action.\n\tbool cancelCurrentAction(bool bForce = false);\n\t/// Cancels all actions.\n\tvoid cancelAllActions();\n\t/// Gets a pointer to access action members directly.\n\tBattleAction *getCurrentAction();\n\t/// Determines whether there is an action currently going on.\n\tbool isBusy() const;\n\t/// Activates primary action (left click).\n\tvoid primaryAction(Position pos);\n\t/// Activates secondary action (right click).\n\tvoid secondaryAction(Position pos);\n\t/// Handler for the blaster launcher button.\n\tvoid launchAction();\n\t/// Handler for the psi button.\n\tvoid psiButtonAction();\n\t/// Handle psi attack result message.\n\tvoid psiAttackMessage(BattleActionAttack attack, BattleUnit *victim);\n\t/// Moves a unit up or down.\n\tvoid moveUpDown(BattleUnit *unit, int dir);\n\t/// Requests the end of the turn (wait for explosions etc to really end the turn).\n\tvoid requestEndTurn(bool askForConfirmation);\n\t/// Sets the TU reserved type.\n\tvoid setTUReserved(BattleActionType tur);\n\t/// Sets up the cursor taking into account the action.\n\tvoid setupCursor();\n\t/// Gets the map.\n\tMap *getMap();\n\t/// Gets the save.\n\tSavedBattleGame *getSave();\n\t/// Gets the tile engine.\n\tTileEngine *getTileEngine();\n\t/// Gets the pathfinding.\n\tPathfinding *getPathfinding();\n\t/// Gets the mod.\n\tMod *getMod();\n\t/// Returns whether panic has been handled.\n\tbool getPanicHandled() const { return _playerPanicHandled; }\n\t/// Tries to find an item and pick it up if possible.\n\tbool findItem(BattleAction *action, bool pickUpWeaponsMoreActively, bool& walkToItem);\n\t/// Checks through all the items on the ground and picks one.\n\tBattleItem *surveyItems(BattleAction *action, bool pickUpWeaponsMoreActively);\n\t/// Evaluates if it's worthwhile to take this item.\n\tbool worthTaking(BattleItem* item, BattleAction *action, bool pickUpWeaponsMoreActively);\n\t/// Picks the item up from the ground.\n\tint takeItemFromGround(BattleItem* item, BattleAction *action);\n\t/// Assigns the item to a slot (stolen from battlescapeGenerator::addItem()).\n\tbool takeItem(BattleItem* item, BattleAction *action);\n\t/// Returns the type of action that is reserved.\n\tBattleActionType getReservedAction();\n\t/// Tallies the living units, converting them if necessary.\n\tbool isSurrendering(BattleUnit* bu);\n\t/// Check count of units in different state\n\tBattlescapeTally tallyUnits();\n\tbool convertInfected();\n\t/// Sets the kneel reservation setting.\n\tvoid setKneelReserved(bool reserved);\n\t/// Checks the kneel reservation setting.\n\tbool getKneelReserved() const;\n\t/// Checks for and triggers proximity grenades.\n\tint checkForProximityGrenades(BattleUnit *unit);\n\t/// Cleans up all the deleted states.\n\tvoid cleanupDeleted();\n\t/// Get the depth of the saved game.\n\tint getDepth() const;\n\t/// Play sound on battlefield (with direction).\n\tvoid playSound(int sound, const Position &pos);\n\t/// Play sound on battlefield.\n\tvoid playSound(int sound);\n\t/// Play unit response sound on battlefield.\n\tvoid playUnitResponseSound(BattleUnit *unit, int type);\n\t/// Sets up a mission complete notification.\n\tvoid missionComplete();\n\tstd::list<BattleState*> getStates();\n\t/// Auto-end the battle if conditions are met.\n\tvoid autoEndBattle();\n\t/// Were all enemies neutralized?\n\tbool areAllEnemiesNeutralized() const { return _allEnemiesNeutralized; }\n\t/// Resets the flag.\n\tvoid resetAllEnemiesNeutralized() { _allEnemiesNeutralized = false; }\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/BattlescapeGenerator.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <algorithm>\n#include <assert.h>\n#include <sstream>\n#include \"BattlescapeGenerator.h\"\n#include \"TileEngine.h\"\n#include \"Inventory.h\"\n#include \"AIModule.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"../Savegame/Tile.h\"\n#include \"../Savegame/ItemContainer.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/BaseFacility.h\"\n#include \"../Savegame/Soldier.h\"\n#include \"../Savegame/BattleUnit.h\"\n#include \"../Savegame/BattleItem.h\"\n#include \"../Savegame/Ufo.h\"\n#include \"../Savegame/Craft.h\"\n#include \"../Savegame/Node.h\"\n#include \"../Savegame/Vehicle.h\"\n#include \"../Savegame/MissionSite.h\"\n#include \"../Savegame/AlienBase.h\"\n#include \"../Savegame/EquipmentLayoutItem.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/FileMap.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/RNG.h\"\n#include \"../Engine/Exception.h\"\n#include \"../Engine/Logger.h\"\n#include \"../Mod/MapBlock.h\"\n#include \"../Mod/MapDataSet.h\"\n#include \"../Mod/RuleUfo.h\"\n#include \"../Mod/RuleCraft.h\"\n#include \"../Mod/RuleInventory.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/MapData.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Mod/Unit.h\"\n#include \"../Mod/AlienRace.h\"\n#include \"../Mod/RuleEnviroEffects.h\"\n#include \"../Mod/RuleSoldier.h\"\n#include \"../Mod/RuleStartingCondition.h\"\n#include \"../Mod/AlienDeployment.h\"\n#include \"../Mod/RuleBaseFacility.h\"\n#include \"../Mod/Texture.h\"\n#include \"Pathfinding.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Sets up a BattlescapeGenerator.\n * @param game pointer to Game object.\n */\nBattlescapeGenerator::BattlescapeGenerator(Game *game) :\n\t_game(game), _save(game->getSavedGame()->getSavedBattle()), _mod(_game->getMod()),\n\t_craft(0), _craftRules(0), _ufo(0), _base(0), _mission(0), _alienBase(0), _terrain(0), _baseTerrain(0), _globeTerrain(0), _alternateTerrain(0),\n\t_mapsize_x(0), _mapsize_y(0), _mapsize_z(0), _missionTexture(0), _globeTexture(0), _worldShade(0),\n\t_unitSequence(0), _craftInventoryTile(0), _alienCustomDeploy(0), _alienCustomMission(0), _alienItemLevel(0), _ufoDamagePercentage(0),\n\t_baseInventory(false), _generateFuel(true), _craftDeployed(false), _ufoDeployed(false), _craftZ(0), _craftPos(), _markAsReinforcementsBlock(0), _blocksToDo(0), _dummy(0)\n{\n\t_allowAutoLoadout = !Options::disableAutoEquip;\n\tif (_game->getSavedGame()->getDisableSoldierEquipment())\n\t{\n\t\t_allowAutoLoadout = false;\n\t}\n\t_inventorySlotGround = _game->getMod()->getInventoryGround();\n}\n\n/**\n * Deletes the BattlescapeGenerator.\n */\nBattlescapeGenerator::~BattlescapeGenerator()\n{\n\n}\n\n/**\n * Sets up all our various arrays and whatnot according to the size of the map.\n */\nvoid BattlescapeGenerator::init(bool resetTerrain)\n{\n\t_blocks.clear();\n\t_landingzone.clear();\n\t_segments.clear();\n\t_drillMap.clear();\n\t_verticalLevels.clear();\n\t_loadedTerrains.clear();\n\t_verticalLevelSegments.clear();\n\n\t_markAsReinforcementsBlock = 0;\n\t_save->getReinforcementsBlocks().clear();\n\t_save->getReinforcementsBlocks().resize((_mapsize_x / 10), std::vector<int>((_mapsize_y / 10), 0));\n\n\t_save->getFlattenedMapTerrainNames().clear();\n\t_save->getFlattenedMapTerrainNames().resize((_mapsize_x / 10), std::vector<std::string>((_mapsize_y / 10), \"\"));\n\t_save->getFlattenedMapBlockNames().clear();\n\t_save->getFlattenedMapBlockNames().resize((_mapsize_x / 10), std::vector<std::string>((_mapsize_y / 10), \"\"));\n\n\t_blocks.resize((_mapsize_x / 10), std::vector<MapBlock*>((_mapsize_y / 10)));\n\t_landingzone.resize((_mapsize_x / 10), std::vector<bool>((_mapsize_y / 10),false));\n\t_segments.resize((_mapsize_x / 10), std::vector<int>((_mapsize_y / 10),0));\n\t_drillMap.resize((_mapsize_x / 10), std::vector<int>((_mapsize_y / 10),MD_NONE));\n\n\t_blocksToDo = (_mapsize_x / 10) * (_mapsize_y / 10);\n\t// creates the tile objects\n\t_save->initMap(_mapsize_x, _mapsize_y, _mapsize_z, resetTerrain);\n\t_save->initUtilities(_mod);\n}\n\n/**\n * Sets the XCom craft involved in the battle.\n * @param craft Pointer to XCom craft.\n */\nvoid BattlescapeGenerator::setCraft(Craft *craft)\n{\n\t_craft = craft;\n\t_craftRules = _craft->getRules();\n\t_craft->setInBattlescape(true);\n}\n\n/**\n * Sets the ufo involved in the battle.\n * @param ufo Pointer to UFO.\n */\nvoid BattlescapeGenerator::setUfo(Ufo *ufo)\n{\n\t_ufo = ufo;\n\t_ufo->setInBattlescape(true);\n}\n\n/**\n * Sets the world texture where a ufo crashed. This is used to determine the terrain.\n * @param missionTexture Texture id of the polygon on the globe (for UFOs). For mission sites, alien bases, etc. can be something else.\n * @param globeTexture Texture id of the polygon on the globe.\n */\nvoid BattlescapeGenerator::setWorldTexture(Texture *missionTexture, Texture *globeTexture)\n{\n\t_missionTexture = missionTexture;\n\t_globeTexture = globeTexture;\n}\n\n/**\n * Sets the world shade where a ufo crashed. This is used to determine the battlescape light level.\n * @param shade Shade of the polygon on the globe.\n */\nvoid BattlescapeGenerator::setWorldShade(int shade)\n{\n\tif (shade > 15) shade = 15;\n\tif (shade < 0) shade = 0;\n\t_worldShade = shade;\n}\n\n/**\n * Sets the alien race on the mission. This is used to determine the various alien types to spawn.\n * @param alienRace Alien (main) race.\n */\nvoid BattlescapeGenerator::setAlienRace(const std::string &alienRace)\n{\n\t_alienRace = alienRace;\n}\n\n/**\n * Sets the alien item level. This is used to determine how advanced the equipment of the aliens will be.\n * note: this only applies to \"New Battle\" type games. we intentionally don't alter the month for those,\n * because we're using monthsPassed -1 for new battle in other sections of code.\n * - this value should be from 0 to the size of the itemLevel array in the ruleset (default 9).\n * - at a certain number of months higher item levels appear more and more and lower ones will gradually disappear\n * @param alienItemLevel AlienItemLevel.\n */\nvoid BattlescapeGenerator::setAlienItemlevel(int alienItemLevel)\n{\n\t_alienItemLevel = alienItemLevel;\n}\n\n/**\n * Sets the UFO damage percentage. Used to spawn less aliens during base defense.\n * @param ufoDamagePercentage Damage percentage.\n */\nvoid BattlescapeGenerator::setUfoDamagePercentage(int ufoDamagePercentage)\n{\n\t_ufoDamagePercentage = ufoDamagePercentage;\n}\n\n/**\n * Set new weapon deploy for aliens that overrides weapon deploy data from mission type/ufo.\n * @param alienCustomDeploy\n */\nvoid BattlescapeGenerator::setAlienCustomDeploy(const AlienDeployment* alienCustomDeploy, const AlienDeployment* alienCustomMission)\n{\n\t_alienCustomDeploy = alienCustomDeploy;\n\t_alienCustomMission = alienCustomMission;\n}\n\n/**\n * Sets the XCom base involved in the battle.\n * @param base Pointer to XCom base.\n */\nvoid BattlescapeGenerator::setBase(Base *base)\n{\n\t_base = base;\n\t_base->setInBattlescape(true);\n}\n\n/**\n * Sets the mission site involved in the battle.\n * @param mission Pointer to mission site.\n */\nvoid BattlescapeGenerator::setMissionSite(MissionSite *mission)\n{\n\t_mission = mission;\n\t_mission->setInBattlescape(true);\n}\n\n\n/**\n * Switches an existing battlescape savegame to a new stage.\n */\nvoid BattlescapeGenerator::nextStage()\n{\n\t// check if the unit is available in the next stage\n\tauto isUnitStillActive = [](const BattleUnit* u)\n\t{\n\t\treturn !u->isOut() || u->getStatus() == STATUS_UNCONSCIOUS;\n\t};\n\t// check if the unit is on the exit tile\n\tauto isInExit = [s = _save](const BattleUnit* u)\n\t{\n\t\tTile *tmpTile = s->getTile(u->getPosition());\n\t\treturn u->isInExitArea(END_POINT) || u->liesInExitArea(tmpTile, END_POINT);\n\t};\n\n\t// preventively drop all units from soldier's inventory (makes handling easier)\n\t// 1. no alien/civilian living, dead or unconscious is allowed to transition\n\t// 2. no dead xcom unit is allowed to transition\n\t// 3. only living or unconscious xcom units can transition\n\tfor (auto* bu : *_save->getUnits())\n\t{\n\t\tif (bu->getOriginalFaction() == FACTION_PLAYER && !bu->isOut())\n\t\t{\n\t\t\tstd::vector<BattleItem*> unitsToDrop;\n\t\t\tfor (auto* bi : *bu->getInventory())\n\t\t\t{\n\t\t\t\tif (bi->getUnit())\n\t\t\t\t{\n\t\t\t\t\tunitsToDrop.push_back(bi);\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (auto* corpseItem : unitsToDrop)\n\t\t\t{\n\t\t\t\t_save->getTileEngine()->itemDrop(bu->getTile(), corpseItem, false);\n\t\t\t}\n\t\t}\n\n\t\t// scripts (or some bugs in the game) could make aliens or soldiers that have \"unresolved\" stun or death state.\n\t\tif (!bu->isOut() && bu->isOutThresholdExceed())\n\t\t{\n\t\t\tbu->instaFalling();\n\t\t\tif (bu->getTile())\n\t\t\t{\n\t\t\t\t_save->getTileEngine()->itemDropInventory(bu->getTile(), bu);\n\t\t\t}\n\n\t\t\t//spawn corpse/body for unit to recover\n\t\t\tfor (int i = bu->getArmor()->getTotalSize() - 1; i >= 0; --i)\n\t\t\t{\n\t\t\t\tauto* corpse = _save->createItemForTile(bu->getArmor()->getCorpseBattlescape()[i], nullptr, bu);\n\t\t\t\t_save->getTileEngine()->itemDrop(bu->getTile(), corpse, false);\n\t\t\t}\n\t\t}\n\t}\n\n\tint aliensAlive = 0;\n\t// send all enemy units, or those not in endpoint area (if aborted) to time out\n\tfor (auto* bu : *_save->getUnits())\n\t{\n\t\tbu->clearVisibleUnits();\n\t\tbu->clearVisibleTiles();\n\n\t\tif (bu->getStatus() != STATUS_DEAD                              // if they're not dead\n\t\t\t&& ((bu->getOriginalFaction() == FACTION_PLAYER               // and they're a soldier\n\t\t\t&& _save->isAborted()\t\t\t\t\t\t\t\t\t\t\t  // and you aborted\n\t\t\t&& !isInExit(bu))                                                     // and they're not on the exit\n\t\t\t|| bu->getOriginalFaction() != FACTION_PLAYER))               // or they're not a soldier\n\t\t{\n\t\t\tif (bu->getOriginalFaction() == FACTION_HOSTILE && !bu->isOut())\n\t\t\t{\n\t\t\t\tif (bu->getOriginalFaction() == bu->getFaction() && !bu->isSurrendering())\n\t\t\t\t{\n\t\t\t\t\taliensAlive++;\n\t\t\t\t}\n\t\t\t\telse if (bu->getTile())\n\t\t\t\t{\n\t\t\t\t\t_save->getTileEngine()->itemDropInventory(bu->getTile(), bu);\n\t\t\t\t}\n\t\t\t}\n\t\t\tbu->goToTimeOut();\n\t\t\tif (bu->getAIModule())\n\t\t\t{\n\t\t\t\tbu->setAIModule(0);\n\t\t\t}\n\t\t}\n\t\tbu->setFire(0);\n\t\tbu->setTile(nullptr, _save);\n\t\tbu->setPosition(TileEngine::invalid, false);\n\t}\n\n\t// send banned units to timeout\n\tif (_save->getStartingCondition() && !_save->getStartingCondition()->getForbiddenArmorsInNextStage().empty())\n\t{\n\t\tBattleUnit* firstUnitToTimeout = nullptr;\n\t\tbool everybodyInTimeout = true;\n\t\tfor (auto* bu : *_save->getUnits())\n\t\t{\n\t\t\tif (bu->getOriginalFaction() == FACTION_PLAYER && bu->getStatus() != STATUS_DEAD && bu->getStatus() != STATUS_IGNORE_ME)\n\t\t\t{\n\t\t\t\tif (bu->isBannedInNextStage())\n\t\t\t\t{\n\t\t\t\t\tif (firstUnitToTimeout)\n\t\t\t\t\t{\n\t\t\t\t\t\tbu->goToTimeOut();\n\t\t\t\t\t\tbu->setAIModule(0);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tfirstUnitToTimeout = bu;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\teverybodyInTimeout = false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// should all remaining xcom units go to timeout, make one of them unconscious instead (to prevent a crash)\n\t\tif (firstUnitToTimeout)\n\t\t{\n\t\t\tif (everybodyInTimeout)\n\t\t\t{\n\t\t\t\tfirstUnitToTimeout->healStun(-firstUnitToTimeout->getHealth() * 3);\n\t\t\t\t//firstUnitToTimeout->instaFalling(); // don't \"resolve\" the unit status yet (to prevent a crash)\n\t\t\t\t// drop inventory\n\t\t\t\t// spawn corpse\n\t\t\t\t// FIXME: this is basically just an ugly hack, maybe it can be done better? e.g. fail the mission already before calling nextStage() ?\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tfirstUnitToTimeout->goToTimeOut();\n\t\t\t\tfirstUnitToTimeout->setAIModule(0);\n\t\t\t}\n\t\t}\n\t}\n\n\t// remove all items not belonging to our soldiers from the map.\n\t// sort items into two categories:\n\t// the ones that we are guaranteed to be able to take home, barring complete failure (ie: stuff on the ship)\n\t// and the ones that are scattered about on the ground, that will be recovered ONLY on success.\n\t// this does not include items in your soldier's hands.\n\tstd::vector<BattleItem*> *takeHomeGuaranteed = _save->getGuaranteedRecoveredItems();\n\tstd::vector<BattleItem*> *takeHomeConditional = _save->getConditionalRecoveredItems();\n\tstd::vector<BattleItem*> takeToNextStage, carryToNextStage, removeFromGame, dummyForSpecialWeaponsRemovedElsewhere;\n\n\tbool autowin = false;\n\tif (_save->getChronoTrigger() >= FORCE_WIN && _save->getTurn() > _save->getTurnLimit())\n\t{\n\t\tautowin = true;\n\t}\n\n\n\t// this will be `getItems` for next stage, allocate same size plus small buffer for new items\n\tcarryToNextStage.reserve(_save->getItems()->size() + 16);\n\n\t_save->resetTurnCounter();\n\n\tfor (auto* bi : *_save->getItems())\n\t{\n\t\t// first off: don't process ammo loaded into weapons. at least not at this level. ammo will be handled simultaneously.\n\t\tif (!bi->isAmmo())\n\t\t{\n\t\t\tstd::vector<BattleItem*> *toContainer = &removeFromGame;\n\t\t\t// if it's recoverable, and it's not owned by someone\n\t\t\tif (((bi->getUnit() && bi->getUnit()->getGeoscapeSoldier()) || bi->getRules()->isRecoverable()) && !bi->getOwner())\n\t\t\t{\n\t\t\t\t// first off: don't count primed grenades on the floor\n\t\t\t\tif (bi->getFuseTimer() == -1)\n\t\t\t\t{\n\t\t\t\t\t// protocol 1: all defenders dead, recover all items.\n\t\t\t\t\tif (aliensAlive == 0 || autowin)\n\t\t\t\t\t{\n\t\t\t\t\t\t// any corpses or unconscious units get put in the skyranger, as well as any unresearched items\n\t\t\t\t\t\tif ((bi->getUnit() &&\n\t\t\t\t\t\t\t(bi->getUnit()->getOriginalFaction() != FACTION_PLAYER ||\n\t\t\t\t\t\t\tbi->getUnit()->getStatus() == STATUS_DEAD))\n\t\t\t\t\t\t\t|| !_game->getSavedGame()->isResearched(bi->getRules()->getRequirements()))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttoContainer = takeHomeGuaranteed;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// otherwise it comes with us to stage two\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttoContainer = &takeToNextStage;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t// protocol 2: some of the aliens survived, meaning we ran to the exit zone.\n\t\t\t\t\t// recover stuff depending on where it was at the end of the mission.\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tTile *tile = bi->getTile();\n\t\t\t\t\t\tif (tile)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// on a tile at least, so i'll give you the benefit of the doubt on this and give it a conditional recovery at this point\n\t\t\t\t\t\t\ttoContainer = takeHomeConditional;\n\t\t\t\t\t\t\tif (tile->getMapData(O_FLOOR))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// in the skyranger? it goes home.\n\t\t\t\t\t\t\t\tif (tile->getFloorSpecialTileType() == START_POINT)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\ttoContainer = takeHomeGuaranteed;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// on the exit grid? it goes to stage two.\n\t\t\t\t\t\t\t\telse if (tile->getFloorSpecialTileType() == END_POINT)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t// apply similar logic (for units) as in protocol 1\n\t\t\t\t\t\t\t\t\tif (bi->getUnit() &&\n\t\t\t\t\t\t\t\t\t\t(bi->getUnit()->getOriginalFaction() != FACTION_PLAYER ||\n\t\t\t\t\t\t\t\t\t\tbi->getUnit()->getStatus() == STATUS_DEAD))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\ttoContainer = takeHomeConditional;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\ttoContainer = &takeToNextStage;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (bi->isSpecialWeapon())\n\t\t\t{\n\t\t\t\tif (isUnitStillActive(bi->getOwner()))\n\t\t\t\t{\n\t\t\t\t\t// the owner of the weapon is still in the game\n\t\t\t\t\ttoContainer = &carryToNextStage;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// the item will be deleted (moved to the delete list) by the `removeSpecialWeapons` function, skip all operations in this function\n\t\t\t\t\ttoContainer = &dummyForSpecialWeaponsRemovedElsewhere;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (bi->isOwnerIgnored())\n\t\t\t\t{\n\t\t\t\t\t// the unit was set to \"timeout\" in a previous stage or in this stage\n\t\t\t\t\t// in both cases we propagate this item to the next stage even if it will not be accessible\n\t\t\t\t\t// \"timeout\" aliens should have their inventory purged already\n\t\t\t\t\ttoContainer = &carryToNextStage;\n\t\t\t\t}\n\t\t\t\telse if (bi->getOwner() && bi->getOwner()->getFaction() == FACTION_PLAYER)\n\t\t\t\t{\n\t\t\t\t\t// if a soldier is already holding it, let's let him keep it\n\t\t\t\t\ttoContainer = &carryToNextStage;\n\t\t\t\t\t// Note: if a soldier is recovered at the end, his items will be recovered with him (regardless of whether that soldier was in timeout at the end or not)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// at this point, we know what happens with the item, so let's apply it to any ammo as well.\n\t\t\tfor (int slot = 0; slot < RuleItem::AmmoSlotMax; ++slot)\n\t\t\t{\n\t\t\t\tBattleItem *ammo = bi->getAmmoForSlot(slot);\n\t\t\t\tif (ammo && ammo != bi)\n\t\t\t\t{\n\t\t\t\t\t// break any tile links, because all the tiles are about to disappear.\n\t\t\t\t\tammo->setTile(0);\n\t\t\t\t\ttoContainer->push_back(ammo);\n\t\t\t\t}\n\t\t\t}\n\t\t\t// and now the actual item itself.\n\t\t\tbi->setTile(0);\n\t\t\ttoContainer->push_back(bi);\n\t\t}\n\t}\n\n\t// remove special weapons\n\tfor (auto* bu : *_save->getUnits())\n\t{\n\t\tif (!isUnitStillActive(bu))\n\t\t{\n\t\t\tbu->removeSpecialWeapons(_save);\n\t\t}\n\t}\n\n\t// anything in the \"removeFromGame\" vector will now be discarded - they're all dead to us now.\n\tfor (auto* bi : removeFromGame)\n\t{\n\t\t// fixed weapons, or anything that's otherwise \"equipped\" will need to be de-equipped\n\t\t// from their owners to make sure we don't have any null pointers to worry about later\n\t\tbi->moveToOwner(nullptr);\n\t\tdelete bi;\n\t}\n\n\t// rebuild it with only the items we want to keep active in battle for the next stage\n\t// here we add all the items that our soldiers are carrying, and we'll add the items on the\n\t// inventory tile after we've generated our map. everything else will either be in one of the\n\t// recovery arrays, or deleted from existence at this point.\n\tstd::swap(*_save->getItems(), carryToNextStage);\n\n\t_alienCustomDeploy = _game->getMod()->getDeployment(_save->getAlienCustomDeploy());\n\t_alienCustomMission = _game->getMod()->getDeployment(_save->getAlienCustomMission());\n\n\tif (_alienCustomDeploy) _alienCustomDeploy = _game->getMod()->getDeployment(_alienCustomDeploy->getNextStage());\n\tif (_alienCustomMission) _alienCustomMission = _game->getMod()->getDeployment(_alienCustomMission->getNextStage());\n\n\t_save->setAlienCustom(_alienCustomDeploy ? _alienCustomDeploy->getType() : \"\", _alienCustomMission ? _alienCustomMission->getType() : \"\");\n\n\tconst AlienDeployment *ruleDeploy = _alienCustomMission ? _alienCustomMission : _game->getMod()->getDeployment(_save->getMissionType(), true);\n\t_save->setTurnLimit(ruleDeploy->getTurnLimit());\n\t_save->setChronoTrigger(ruleDeploy->getChronoTrigger());\n\t_save->setCheatTurn(ruleDeploy->getCheatTurn());\n\truleDeploy->getDimensions(&_mapsize_x, &_mapsize_y, &_mapsize_z);\n\tsize_t pick = RNG::generate(0, ruleDeploy->getTerrains().size() -1);\n\t_terrain = _game->getMod()->getTerrain(ruleDeploy->getTerrains().at(pick), true);\n\tsetDepth(ruleDeploy, true);\n\t_worldShade = ruleDeploy->getShade();\n\n\tRuleEnviroEffects* enviro = _game->getMod()->getEnviroEffects(_terrain->getEnviroEffects());\n\tRuleEnviroEffects* temp = _game->getMod()->getEnviroEffects(ruleDeploy->getEnviroEffects());\n\tif (temp != 0)\n\t{\n\t\tenviro = temp;\n\t}\n\t_save->applyEnviroEffects(enviro);\n\n\t// enviro effects - armor transformation (no armor replacement! that is done only before the 1st stage)\n\tif (enviro != 0)\n\t{\n\t\tfor (auto* bu : *_save->getUnits())\n\t\t{\n\t\t\tif (bu->getOriginalFaction() == FACTION_PLAYER && bu->getGeoscapeSoldier())\n\t\t\t{\n\t\t\t\tArmor* transformedArmor = enviro->getArmorTransformation(bu->getArmor());\n\t\t\t\tif (transformedArmor)\n\t\t\t\t{\n\t\t\t\t\t// remember the original armor (i.e. only if there were no transformations in earlier stage(s)!)\n\t\t\t\t\tif (!bu->getGeoscapeSoldier()->getTransformedArmor())\n\t\t\t\t\t{\n\t\t\t\t\t\tbu->getGeoscapeSoldier()->setTransformedArmor(_game->getMod()->getArmor(bu->getArmor()->getType()));\n\t\t\t\t\t}\n\t\t\t\t\t// change soldier's armor (needed for inventory view!)\n\t\t\t\t\tbu->getGeoscapeSoldier()->setArmor(transformedArmor);\n\t\t\t\t\t// change battleunit's armor\n\t\t\t\t\tbu->updateArmorFromSoldier(_game->getMod(), bu->getGeoscapeSoldier(), transformedArmor, _save->getDepth(), true, _save->getStartingCondition());\n\t\t\t\t\t// remove old special built-in weapons and replace them with new fresh special built-in weapons\n\t\t\t\t\t// TODO? if this was a limited-use weapon, it will have full ammo again!\n\t\t\t\t\tbu->removeSpecialWeapons(_save);\n\t\t\t\t\tbu->setSpecialWeapon(_save, false);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (bu->getOriginalFaction() == FACTION_PLAYER)\n\t\t\t{\n\t\t\t\t// HWPs\n\t\t\t\tArmor* transformedArmor = enviro->getArmorTransformation(bu->getArmor());\n\t\t\t\tif (transformedArmor)\n\t\t\t\t{\n\t\t\t\t\t// change battleunit's armor\n\t\t\t\t\tbu->updateArmorFromNonSoldier(_game->getMod(), transformedArmor, _save->getDepth(), true, _save->getStartingCondition());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tauto& terrainMapScript = _terrain->getRandomMapScript();\n\tconst std::vector<MapScript*> *script = _game->getMod()->getMapScript(terrainMapScript);\n\t_save->setLastUsedMapScript(terrainMapScript);\n\n\tauto& deployMapScript = ruleDeploy->getRandomMapScript();\n\tif (_game->getMod()->getMapScript(deployMapScript))\n\t{\n\t\tscript = _game->getMod()->getMapScript(deployMapScript);\n\t\t_save->setLastUsedMapScript(deployMapScript);\n\t}\n\telse if (!deployMapScript.empty())\n\t{\n\t\tthrow Exception(\"Map generator encountered an error: \" + deployMapScript + \" script not found.\");\n\t}\n\tif (script == 0)\n\t{\n\t\tthrow Exception(\"Map generator encountered an error: \" + terrainMapScript + \" script not found.\");\n\t}\n\n\t// cleanup before map old map is destroyed\n\tfor (auto* bu : *_save->getUnits())\n\t{\n\t\tbu->clearVisibleTiles();\n\t\tbu->clearVisibleUnits();\n\t}\n\n\tgenerateMap(script, ruleDeploy->getCustomUfoName(), nullptr);\n\n\tsetupObjectives(ruleDeploy);\n\n\tint highestSoldierID = 0;\n\tbool selectedFirstSoldier = false;\n\tint soldiersTotal = 0;\n\tint soldiersPlaced = 0;\n\tfor (auto* bu : *_save->getUnits())\n\t{\n\t\tif (bu->getOriginalFaction() == FACTION_PLAYER)\n\t\t{\n\t\t\tif (!bu->isOut())\n\t\t\t{\n\t\t\t\t++soldiersTotal;\n\t\t\t\tbu->resetTurnsSinceStunned();\n\t\t\t\tbu->resetTurnsSince();\n\t\t\t\tif (!selectedFirstSoldier && bu->getGeoscapeSoldier())\n\t\t\t\t{\n\t\t\t\t\t_save->setSelectedUnit(bu);\n\t\t\t\t\tselectedFirstSoldier = true;\n\t\t\t\t}\n\t\t\t\tNode* node = _save->getSpawnNode(NR_XCOM, bu);\n\t\t\t\tif (node || placeUnitNearFriend(bu))\n\t\t\t\t{\n\t\t\t\t\t++soldiersPlaced;\n\t\t\t\t\tif (node)\n\t\t\t\t\t{\n\t\t\t\t\t\t_save->setUnitPosition(bu, node->getPosition());\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!_craftInventoryTile)\n\t\t\t\t\t{\n\t\t\t\t\t\t_craftInventoryTile = bu->getTile();\n\t\t\t\t\t}\n\n\t\t\t\t\tbu->setInventoryTile(_craftInventoryTile);\n\t\t\t\t\tbu->setVisible(false);\n\t\t\t\t\tif (bu->getId() > highestSoldierID)\n\t\t\t\t\t{\n\t\t\t\t\t\thighestSoldierID = bu->getId();\n\t\t\t\t\t}\n\t\t\t\t\t//reset TUs, regain energy, etc. but don't take damage or go berserk\n\t\t\t\t\tbu->prepareNewTurn(false);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif (soldiersPlaced == 0)\n\t{\n\t\tthrow Exception(\"Map generator encountered an error: no xcom units could be placed on the map.\");\n\t}\n\telse if (soldiersPlaced < soldiersTotal)\n\t{\n\t\tstd::ostringstream oss;\n\t\toss << \"Map generator encountered an error: not all xcom units could be placed on the map. Placed: \" << soldiersPlaced << \" of \" << soldiersTotal << \".\";\n\t\tthrow Exception(oss.str());\n\t}\n\n\tif (_save->getSelectedUnit() == 0 || _save->getSelectedUnit()->isOut() || _save->getSelectedUnit()->getFaction() != FACTION_PLAYER)\n\t{\n\t\t_save->selectNextPlayerUnit();\n\t}\n\tRuleInventory *ground = _inventorySlotGround;\n\n\tfor (auto* bi : takeToNextStage)\n\t{\n\t\t_save->getItems()->push_back(bi);\n\t\tif (bi->getSlot() == ground)\n\t\t{\n\t\t\t_craftInventoryTile->addItem(bi, ground);\n\t\t\tif (bi->getUnit())\n\t\t\t{\n\t\t\t\tbi->getUnit()->setPosition(_craftInventoryTile->getPosition());\n\t\t\t}\n\t\t}\n\t}\n\n\t_unitSequence = _save->getUnits()->back()->getId() + 1;\n\n\t// Let's figure out what race we're up against.\n\t_alienRace = ruleDeploy->getRace();\n\n\tif (_alienRace.empty())\n\t{\n\t\tfor (const auto* missionSite : *_game->getSavedGame()->getMissionSites())\n\t\t{\n\t\t\tif (missionSite->isInBattlescape())\n\t\t\t{\n\t\t\t\t_alienRace = missionSite->getAlienRace();\n\t\t\t\tbreak; // loop finished\n\t\t\t}\n\t\t}\n\t}\n\n\tif (_alienRace.empty())\n\t{\n\t\tfor (const auto* ab : *_game->getSavedGame()->getAlienBases())\n\t\t{\n\t\t\tif (ab->isInBattlescape())\n\t\t\t{\n\t\t\t\t_alienRace = ab->getAlienRace();\n\t\t\t\tbreak; // loop finished\n\t\t\t}\n\t\t}\n\t}\n\n\tint civilianSpawnNodeRank = ruleDeploy->getCivilianSpawnNodeRank();\n\tbool markCiviliansAsVIP = ruleDeploy->getMarkCiviliansAsVIP();\n\n\t// Special case: deploy civilians before aliens\n\tif (civilianSpawnNodeRank > 0)\n\t{\n\t\tdeployCivilians(markCiviliansAsVIP, civilianSpawnNodeRank, ruleDeploy->getCivilians());\n\t\tfor (auto& pair : ruleDeploy->getCiviliansByType())\n\t\t{\n\t\t\tdeployCivilians(markCiviliansAsVIP, civilianSpawnNodeRank, pair.second, true, pair.first);\n\t\t}\n\t}\n\n\tsize_t unitCount = _save->getUnits()->size();\n\n\tdeployAliens(_alienCustomDeploy && !_alienCustomDeploy->getDeploymentData()->empty() ? _alienCustomDeploy : ruleDeploy);\n\n\tif (unitCount == _save->getUnits()->size())\n\t{\n\t\tthrow Exception(\"Map generator encountered an error: no alien units could be placed on the map.\");\n\t}\n\n\t// Normal case: deploy civilians after aliens\n\tif (civilianSpawnNodeRank == 0)\n\t{\n\t\tdeployCivilians(markCiviliansAsVIP, civilianSpawnNodeRank, ruleDeploy->getCivilians());\n\t\tfor (auto& pair : ruleDeploy->getCiviliansByType())\n\t\t{\n\t\t\tdeployCivilians(markCiviliansAsVIP, civilianSpawnNodeRank, pair.second, true, pair.first);\n\t\t}\n\t}\n\n\t_save->setAborted(false);\n\tsetMusic(ruleDeploy, true);\n\t_save->setGlobalShade(_worldShade);\n\t_save->getTileEngine()->calculateLighting(LL_AMBIENT, TileEngine::invalid, 0, true);\n}\n\n/**\n * Starts the generator; it fills up the battlescape savegame with data.\n */\nvoid BattlescapeGenerator::run()\n{\n\tbool isPreview = _save->isPreview();\n\n\t_save->setAlienCustom(_alienCustomDeploy ? _alienCustomDeploy->getType() : \"\", _alienCustomMission ? _alienCustomMission->getType() : \"\");\n\n\t// Note: this considers also fake underwater UFO deployment (via _alienCustomMission)\n\tconst AlienDeployment *ruleDeploy = _alienCustomMission ? _alienCustomMission : _game->getMod()->getDeployment(_ufo?_ufo->getRules()->getType():_save->getMissionType(), true);\n\n\t_save->setTurnLimit(ruleDeploy->getTurnLimit());\n\t_save->setChronoTrigger(ruleDeploy->getChronoTrigger());\n\t_save->setCheatTurn(ruleDeploy->getCheatTurn());\n\truleDeploy->getDimensions(&_mapsize_x, &_mapsize_y, &_mapsize_z);\n\n\t_unitSequence = BattleUnit::MAX_SOLDIER_ID; // geoscape soldier IDs should stay below this number\n\n\tif (_terrain == 0)\n\t{\n\t\tif (_missionTexture == 0 || _missionTexture->getTerrain()->empty() || !ruleDeploy->getTerrains().empty())\n\t\t{\n\t\t\tif (!ruleDeploy->getTerrains().empty())\n\t\t\t{\n\t\t\t\tsize_t pick = RNG::generate(0, ruleDeploy->getTerrains().size() - 1);\n\t\t\t\t_terrain = _game->getMod()->getTerrain(ruleDeploy->getTerrains().at(pick), true);\n\t\t\t}\n\t\t\telse // trouble: no texture and no deployment terrain, most likely scenario is a UFO landing on water: use the first available terrain\n\t\t\t{\n\t\t\t\tLog(LOG_WARNING) << \"Trouble: no texture and no deployment terrain, most likely scenario is a UFO landing on water: using the first available terrain...\";\n\t\t\t\t_terrain = _game->getMod()->getTerrain(_game->getMod()->getTerrainList().front(), true);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tTarget *target = _ufo;\n\t\t\tif (_mission) target = _mission;\n\t\t\t_terrain = _game->getMod()->getTerrain(_missionTexture->getRandomTerrain(target), true);\n\t\t}\n\t}\n\n\tif (_terrain == 0)\n\t{\n\t\tthrow Exception(\"Map generator encountered an error: No valid terrain found.\");\n\t}\n\n\tsetDepth(ruleDeploy, false);\n\n\tif (ruleDeploy->getShade() != -1)\n\t{\n\t\t_worldShade = ruleDeploy->getShade();\n\t}\n\telse if (ruleDeploy->getMinShade() != -1 && _worldShade < ruleDeploy->getMinShade())\n\t{\n\t\t_worldShade = ruleDeploy->getMinShade();\n\t}\n\telse if (ruleDeploy->getMaxShade() != -1 && _worldShade > ruleDeploy->getMaxShade())\n\t{\n\t\t_worldShade = ruleDeploy->getMaxShade();\n\t}\n\n\t{\n\t\tint month;\n\t\tif (_game->getSavedGame()->getMonthsPassed() != -1)\n\t\t{\n\t\t\tmonth =\n\t\t\t((size_t) _game->getSavedGame()->getMonthsPassed()) > _game->getMod()->getAlienItemLevels().size() - 1 ?  // if\n\t\t\t_game->getMod()->getAlienItemLevels().size() - 1 : // then\n\t\t\t_game->getSavedGame()->getMonthsPassed() ;  // else\n\t\t}\n\t\telse\n\t\t{\n\t\t\tmonth = _alienItemLevel;\n\t\t}\n\n\t\t_save->setAlienItemLevel(month);\n\t}\n\n\tauto& terrainMapScript = _terrain->getRandomMapScript();\n\tconst std::vector<MapScript*> *script = _game->getMod()->getMapScript(terrainMapScript);\n\t_save->setLastUsedMapScript(terrainMapScript);\n\n\tauto& deployMapScript = ruleDeploy->getRandomMapScript();\n\tif (_game->getMod()->getMapScript(deployMapScript))\n\t{\n\t\tscript = _game->getMod()->getMapScript(deployMapScript);\n\t\t_save->setLastUsedMapScript(deployMapScript);\n\t}\n\telse if (!deployMapScript.empty())\n\t{\n\t\tthrow Exception(\"Map generator encountered an error: \" + deployMapScript + \" script not found.\");\n\t}\n\tif (script == 0)\n\t{\n\t\tthrow Exception(\"Map generator encountered an error: \" + terrainMapScript + \" script not found.\");\n\t}\n\n\tif (isPreview && _craftRules)\n\t{\n\t\t// resize the map if needed\n\t\tfor (const auto* dims : *_craftRules->getBattlescapeTerrainData()->getMapBlocks())\n\t\t{\n\t\t\tif (dims->getSizeX() > _mapsize_x)\n\t\t\t{\n\t\t\t\t_mapsize_x = dims->getSizeX();\n\t\t\t}\n\t\t\tif (dims->getSizeY() > _mapsize_y)\n\t\t\t{\n\t\t\t\t_mapsize_y = dims->getSizeY();\n\t\t\t}\n\t\t}\n\t}\n\n\tRuleStartingCondition* startingCondition = _game->getMod()->getStartingCondition(ruleDeploy->getStartingCondition());\n\tif (!startingCondition && _missionTexture)\n\t{\n\t\tstartingCondition = _game->getMod()->getStartingCondition(_missionTexture->getStartingCondition());\n\t}\n\t_save->setStartingCondition(startingCondition);\n\n\tgenerateMap(script, ruleDeploy->getCustomUfoName(), startingCondition);\n\n\tif (isPreview && ruleDeploy->isHidden())\n\t{\n\t\t_save->revealMap();\n\t}\n\n\tsetupObjectives(ruleDeploy);\n\n\tRuleEnviroEffects *enviro = _game->getMod()->getEnviroEffects(ruleDeploy->getEnviroEffects());\n\tif (!enviro && _terrain)\n\t{\n\t\tenviro = _game->getMod()->getEnviroEffects(_terrain->getEnviroEffects());\n\t}\n\tdeployXCOM(isPreview ? nullptr : startingCondition, isPreview ? nullptr : enviro);\n\n\tint civilianSpawnNodeRank = ruleDeploy->getCivilianSpawnNodeRank();\n\tbool markCiviliansAsVIP = ruleDeploy->getMarkCiviliansAsVIP();\n\n\t// Special case: deploy civilians before aliens\n\tif (!isPreview && civilianSpawnNodeRank > 0)\n\t{\n\t\tdeployCivilians(markCiviliansAsVIP, civilianSpawnNodeRank, ruleDeploy->getCivilians());\n\t\tfor (auto& pair : ruleDeploy->getCiviliansByType())\n\t\t{\n\t\t\tdeployCivilians(markCiviliansAsVIP, civilianSpawnNodeRank, pair.second, true, pair.first);\n\t\t}\n\t}\n\n\tsize_t unitCount = _save->getUnits()->size();\n\n\tif (!isPreview)\n\t{\n\t\tdeployAliens(_alienCustomDeploy && !_alienCustomDeploy->getDeploymentData()->empty() ? _alienCustomDeploy : ruleDeploy);\n\t}\n\n\tif (!isPreview && unitCount == _save->getUnits()->size())\n\t{\n\t\tthrow Exception(\"Map generator encountered an error: no alien units could be placed on the map.\");\n\t}\n\n\t// Normal case: deploy civilians after aliens\n\tif (!isPreview && civilianSpawnNodeRank == 0)\n\t{\n\t\tdeployCivilians(markCiviliansAsVIP, civilianSpawnNodeRank, ruleDeploy->getCivilians());\n\t\tfor (auto& pair : ruleDeploy->getCiviliansByType())\n\t\t{\n\t\t\tdeployCivilians(markCiviliansAsVIP, civilianSpawnNodeRank, pair.second, true, pair.first);\n\t\t}\n\t}\n\n\tif (!isPreview && _craftInventoryTile && ruleDeploy->getNoWeaponPile())\n\t{\n\t\tsendItemsToLimbo();\n\t}\n\n\tif (!isPreview && _generateFuel)\n\t{\n\t\tfuelPowerSources();\n\t}\n\n\tsetMusic(ruleDeploy, false);\n\t// set shade (alien bases are a little darker, sites depend on world shade)\n\t_save->setGlobalShade(_worldShade);\n\n\t_save->getTileEngine()->calculateLighting(LL_AMBIENT, TileEngine::invalid, 0, true);\n\n\tif (!isPreview && _ufo && _ufo->getStatus() == Ufo::CRASHED)\n\t{\n\t\texplodePowerSources();\n\t}\n\n\tif (!isPreview)\n\t{\n\t\texplodeOtherJunk();\n\t}\n}\n\n/**\n * Deploys all the X-COM units and equipment based on the Geoscape base / craft.\n */\nvoid BattlescapeGenerator::deployXCOM(const RuleStartingCondition* startingCondition, const RuleEnviroEffects* enviro)\n{\n\tbool isPreview = _save->isPreview();\n\n\t_save->applyEnviroEffects(enviro);\n\n\tRuleInventory *ground = _inventorySlotGround;\n\n\tif (_craft != 0)\n\t{\n\t\t_base = _craft->getBase();\n\t\t_craft->resetTemporaryCustomVehicleDeploymentFlags();\n\t}\n\n\t// we will need this during debriefing to show a list of recovered items\n\t// Note: saved info is required only because of base defense missions, other missions could work without a save too\n\t// IMPORTANT: the number of vehicles and their ammo has been messed up by Base::setupDefenses() already :( and will need to be handled separately later\n\tif (!isPreview && _base != 0)\n\t{\n\t\tItemContainer *rememberMe = _save->getBaseStorageItems();\n\t\tfor (const auto& pair : *_base->getStorageItems()->getContents())\n\t\t{\n\t\t\trememberMe->addItem(pair.first, pair.second);\n\t\t}\n\t}\n\n\t// add vehicles that are in the craft - a vehicle is actually an item, which you will never see as it is converted to a unit\n\t// however the item itself becomes the weapon it \"holds\".\n\tif (!_baseInventory)\n\t{\n\t\tif (_craft != 0)\n\t\t{\n\t\t\tfor (auto* vehicle : *_craft->getVehicles())\n\t\t\t{\n\t\t\t\tconst RuleItem *item = vehicle->getRules();\n\t\t\t\tbool hwpDisabled = false;\n\t\t\t\tif (startingCondition)\n\t\t\t\t{\n\t\t\t\t\tif (!startingCondition->isVehiclePermitted(item->getType()))\n\t\t\t\t\t{\n\t\t\t\t\t\thwpDisabled = true; // HWP is disabled\n\t\t\t\t\t}\n\t\t\t\t\telse if (item->getVehicleClipAmmo())\n\t\t\t\t\t{\n\t\t\t\t\t\tif (!startingCondition->isItemPermitted(item->getVehicleClipAmmo()->getType(), _game->getMod(), _craft))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\thwpDisabled = true; // HWP's ammo is disabled\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (hwpDisabled)\n\t\t\t\t{\n\t\t\t\t\t// send disabled vehicles back to base\n\t\t\t\t\t_base->getStorageItems()->addItem(item, 1);\n\t\t\t\t\t// ammo too, if necessary\n\t\t\t\t\tif (item->getVehicleClipAmmo())\n\t\t\t\t\t{\n\t\t\t\t\t\t// Calculate how much ammo needs to be added to the base.\n\t\t\t\t\t\t_base->getStorageItems()->addItem(item->getVehicleClipAmmo(), item->getVehicleClipsLoaded());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (item->getVehicleUnit()->getArmor()->getSize() > 1 || Mod::EXTENDED_HWP_LOAD_ORDER == false)\n\t\t\t\t{\n\t\t\t\t\t// 2x2 HWPs first\n\t\t\t\t\tBattleUnit *unit = addXCOMVehicle(vehicle);\n\t\t\t\t\tif (unit && !_save->getSelectedUnit())\n\t\t\t\t\t\t_save->setSelectedUnit(unit);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse if (_base != 0)\n\t\t{\n\t\t\t// add vehicles that are in the base inventory\n\t\t\tfor (auto* vehicle : *_base->getVehicles())\n\t\t\t{\n\t\t\t\tBattleUnit *unit = addXCOMVehicle(vehicle);\n\t\t\t\tif (unit && !_save->getSelectedUnit())\n\t\t\t\t\t_save->setSelectedUnit(unit);\n\t\t\t}\n\t\t\t// we only add vehicles from the craft in new battle mode,\n\t\t\t// otherwise the base's vehicle vector will already contain these\n\t\t\t// due to the geoscape calling base->setupDefenses()\n\t\t\tif (_game->getSavedGame()->getMonthsPassed() == -1)\n\t\t\t{\n\t\t\t\tfor (auto* craft : *_base->getCrafts())\n\t\t\t\t{\n\t\t\t\t\tfor (auto* vehicle : *craft->getVehicles())\n\t\t\t\t\t{\n\t\t\t\t\t\tBattleUnit *unit = addXCOMVehicle(vehicle);\n\t\t\t\t\t\tif (unit && !_save->getSelectedUnit())\n\t\t\t\t\t\t\t_save->setSelectedUnit(unit);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// enviro effects and starting conditions - armor transformation and replacement\n\tif (startingCondition != 0 || enviro != 0)\n\t{\n\t\tfor (auto* soldier : *_base->getSoldiers())\n\t\t{\n\t\t\tif ((_craft != 0 && soldier->getCraft() == _craft) ||\n\t\t\t\t(_craft == 0 && (soldier->hasFullHealth() || soldier->canDefendBase()) && (soldier->getCraft() == 0 || soldier->getCraft()->getStatus() != \"STR_OUT\")))\n\t\t\t{\n\t\t\t\tArmor* transformedArmor = nullptr;\n\t\t\t\tif (enviro)\n\t\t\t\t\ttransformedArmor = enviro->getArmorTransformation(soldier->getArmor());\n\t\t\t\tif (transformedArmor)\n\t\t\t\t{\n\t\t\t\t\tsoldier->setTransformedArmor(soldier->getArmor());\n\t\t\t\t\tsoldier->setArmor(transformedArmor);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tArmor* replacedArmor = nullptr;\n\t\t\t\t\tif (startingCondition)\n\t\t\t\t\t{\n\t\t\t\t\t\tstd::string replacedArmorType = startingCondition->getArmorReplacement(soldier->getRules()->getType(), soldier->getArmor()->getType());\n\t\t\t\t\t\treplacedArmor = _game->getMod()->getArmor(replacedArmorType, true);\n\t\t\t\t\t\tif (replacedArmor && replacedArmor->getSize() > soldier->getArmor()->getSize())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// cannot switch into a bigger armor size!\n\t\t\t\t\t\t\treplacedArmor = nullptr;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (replacedArmor)\n\t\t\t\t\t{\n\t\t\t\t\t\tsoldier->setReplacedArmor(soldier->getArmor());\n\t\t\t\t\t\tsoldier->setArmor(replacedArmor);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// add soldiers that are in the craft or base (2x2 only)\n\t{\n\t\tfor (auto* soldier : *_base->getSoldiers())\n\t\t{\n\t\t\tif (soldier->getArmor()->getSize() == 1)\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif ((_craft != 0 && soldier->getCraft() == _craft) ||\n\t\t\t\t(_craft == 0 && (soldier->hasFullHealth() || soldier->canDefendBase()) && (soldier->getCraft() == 0 || soldier->getCraft()->getStatus() != \"STR_OUT\")))\n\t\t\t{\n\t\t\t\t// clear the soldier's equipment layout, we want to start fresh\n\t\t\t\tif (_game->getSavedGame()->getDisableSoldierEquipment())\n\t\t\t\t{\n\t\t\t\t\tsoldier->clearEquipmentLayout();\n\t\t\t\t}\n\t\t\t\tBattleUnit *unit = addXCOMUnit(new BattleUnit(_game->getMod() , soldier, _save->getDepth(), _save->getStartingCondition()));\n\t\t\t\tif (unit && !_save->getSelectedUnit())\n\t\t\t\t\t_save->setSelectedUnit(unit);\n\t\t\t}\n\t\t}\n\t}\n\n\t// add remaining 1x1 craft vehicles\n\tif (!_baseInventory && Mod::EXTENDED_HWP_LOAD_ORDER)\n\t{\n\t\tif (_craft != 0)\n\t\t{\n\t\t\tfor (auto* vehicle : *_craft->getVehicles())\n\t\t\t{\n\t\t\t\tconst RuleItem *item = vehicle->getRules();\n\t\t\t\tbool hwpDisabled = false;\n\t\t\t\tif (startingCondition)\n\t\t\t\t{\n\t\t\t\t\tif (!startingCondition->isVehiclePermitted(item->getType()))\n\t\t\t\t\t{\n\t\t\t\t\t\thwpDisabled = true; // HWP is disabled\n\t\t\t\t\t}\n\t\t\t\t\telse if (item->getVehicleClipAmmo())\n\t\t\t\t\t{\n\t\t\t\t\t\tif (!startingCondition->isItemPermitted(item->getVehicleClipAmmo()->getType(), _game->getMod(), _craft))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\thwpDisabled = true; // HWP's ammo is disabled\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (hwpDisabled)\n\t\t\t\t{\n\t\t\t\t\t// skip, already done earlier\n\t\t\t\t}\n\t\t\t\telse if (item->getVehicleUnit()->getArmor()->getSize() == 1)\n\t\t\t\t{\n\t\t\t\t\t// 1x1 HWPs last\n\t\t\t\t\tBattleUnit *unit = addXCOMVehicle(vehicle);\n\t\t\t\t\tif (unit && !_save->getSelectedUnit())\n\t\t\t\t\t\t_save->setSelectedUnit(unit);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// add soldiers that are in the craft or base (1x1 only)\n\t{\n\t\tfor (auto* soldier : *_base->getSoldiers())\n\t\t{\n\t\t\tif (soldier->getArmor()->getSize() > 1)\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif ((_craft != 0 && soldier->getCraft() == _craft) ||\n\t\t\t\t(_craft == 0 && (soldier->hasFullHealth() || soldier->canDefendBase()) && (soldier->getCraft() == 0 || soldier->getCraft()->getStatus() != \"STR_OUT\")))\n\t\t\t{\n\t\t\t\t// clear the soldier's equipment layout, we want to start fresh\n\t\t\t\tif (_game->getSavedGame()->getDisableSoldierEquipment())\n\t\t\t\t{\n\t\t\t\t\tsoldier->clearEquipmentLayout();\n\t\t\t\t}\n\t\t\t\tBattleUnit *unit = addXCOMUnit(new BattleUnit(_game->getMod(), soldier, _save->getDepth(), _save->getStartingCondition()));\n\t\t\t\tif (unit && !_save->getSelectedUnit())\n\t\t\t\t\t_save->setSelectedUnit(unit);\n\t\t\t}\n\t\t}\n\t}\n\n\t// job's done\n\t_game->getSavedGame()->setDisableSoldierEquipment(false);\n\n\t// Corner case: the base has some soldiers, but nowhere to spawn them (e.g. after a previous base defense destroyed everything but access lift)\n\tif (_save->getUnits()->empty() && _save->getMissionType() == \"STR_BASE_DEFENSE\")\n\t{\n\t\t// let's force-spawn a dummy unit and auto-fail the battle\n\t\tstd::string firstRace = _game->getMod()->getAlienRacesList().front();\n\t\tAlienRace* raceRule = _game->getMod()->getAlienRace(firstRace);\n\t\tstd::string firstUnit = raceRule->getMember(0);\n\t\tUnit* unitRule = _game->getMod()->getUnit(firstUnit);\n\t\tBattleUnit* unit = _save->createTempUnit(unitRule, FACTION_PLAYER, _unitSequence++);\n\t\tunit->setSummonedPlayerUnit(true); // auto-fail battle\n\t\t_save->setSelectedUnit(unit);\n\n\t\tTile* firstTile = _save->getTile(0);\n\t\t_save->setUnitPosition(unit, firstTile->getPosition());\n\t\t_save->getUnits()->push_back(unit);\n\t\t_craftInventoryTile = firstTile;\n\t}\n\n\tif (_save->getUnits()->empty())\n\t{\n\t\tthrow Exception(\"Map generator encountered an error: no xcom units could be placed on the map.\");\n\t}\n\n\t// maybe we should assign all units to the first tile of the skyranger before the inventory pre-equip and then reassign them to their correct tile afterwards?\n\t// fix: make them invisible, they are made visible afterwards.\n\tfor (auto* bu : *_save->getUnits())\n\t{\n\t\tif (bu->getFaction() == FACTION_PLAYER)\n\t\t{\n\t\t\tbu->setInventoryTile(_craftInventoryTile);\n\t\t\tbu->setVisible(false);\n\t\t}\n\t}\n\n\tif (isPreview)\n\t{\n\t\t// alright, that's enough\n\t\treturn;\n\t}\n\n\tif (_craft != 0)\n\t{\n\t\t// add items that are in the craft\n\t\tfor (const auto& pair : *_craft->getItems()->getContents())\n\t\t{\n\t\t\tif (startingCondition != 0 && !startingCondition->isItemPermitted(pair.first->getType(), _game->getMod(), _craft))\n\t\t\t{\n\t\t\t\t// send disabled items back to base\n\t\t\t\t_base->getStorageItems()->addItem(pair.first, pair.second);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tfor (int count = 0; count < pair.second; count++)\n\t\t\t\t{\n\t\t\t\t\t_save->createItemForTile(pair.first, _craftInventoryTile);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\t// only use the items in the craft in new battle mode.\n\t\tif (_game->getSavedGame()->getMonthsPassed() != -1)\n\t\t{\n\t\t\t// add items that are in the base\n\t\t\tfor (auto i = _base->getStorageItems()->getContents()->begin(); i != _base->getStorageItems()->getContents()->end();)\n\t\t\t{\n\t\t\t\tconst RuleItem *rule = i->first;\n\t\t\t\tif (\n\t\t\t\t\t// is item allowed in base defense?\n\t\t\t\t\trule->canBeEquippedBeforeBaseDefense() &&\n\t\t\t\t\t// only put items in the battlescape that make sense (when the item got a sprite, it's probably ok)\n\t\t\t\t\trule->isInventoryItem() &&\n\t\t\t\t\t// if item can be equip to craft then you should be able to use it in base defense\n\t\t\t\t\t// in some cases we forbid some items from craft but still allow them in base defense if normally they were available.\n\t\t\t\t\t(rule->isUsefulBattlescapeItem() || rule->canBeEquippedToCraftInventory()) &&\n\t\t\t\t\t// we know how to use this item\n\t\t\t\t\t_game->getSavedGame()->isResearched(rule->getRequirements()))\n\t\t\t\t{\n\t\t\t\t\tfor (int count = 0; count < i->second; count++)\n\t\t\t\t\t{\n\t\t\t\t\t\t_save->createItemForTile(i->first, _craftInventoryTile);\n\t\t\t\t\t}\n\t\t\t\t\tauto tmp = i; // copy\n\t\t\t\t\t++i;\n\t\t\t\t\tif (!_baseInventory)\n\t\t\t\t\t{\n\t\t\t\t\t\t_base->getStorageItems()->removeItem(tmp->first, tmp->second);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t++i;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// add items from crafts in base\n\t\tfor (auto* craft : *_base->getCrafts())\n\t\t{\n\t\t\tif (craft->getStatus() == \"STR_OUT\")\n\t\t\t\tcontinue;\n\t\t\tfor (const auto& pair : *craft->getItems()->getContents())\n\t\t\t{\n\t\t\t\tfor (int count = 0; count < pair.second; count++)\n\t\t\t\t{\n\t\t\t\t\t_save->createItemForTile(pair.first, _craftInventoryTile);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tstd::vector<BattleItem*> tempItemList = *_craftInventoryTile->getInventory();\n\n\t// equip soldiers based on equipment-layout\n\tfor (BattleItem* bi : tempItemList)\n\t{\n\t\t// set all the items on this tile as belonging to the XCOM faction.\n\t\tbi->setXCOMProperty(true);\n\t\t// don't let the soldiers take extra ammo yet\n\t\tif (bi->getRules()->getBattleType() == BT_AMMO && !Options::oxceAlternateCraftEquipmentManagement)\n\t\t\tcontinue;\n\t\tplaceItemByLayout(bi, tempItemList);\n\t}\n\n\t// load fixed weapons based on equipment layout\n\treloadFixedWeaponsByLayout();\n\n\t// refresh list\n\ttempItemList = *_craftInventoryTile->getInventory();\n\n\t// sort it, so that ammo is loaded in a predictable and moddable manner\n\tstd::sort(tempItemList.begin(), tempItemList.end(),\n\t\t[](const BattleItem* a, const BattleItem* b)\n\t\t{\n\t\t\treturn a->getRules()->getLoadOrder() < b->getRules()->getLoadOrder();\n\t\t}\n\t);\n\n\t// load weapons before loadouts take extra clips.\n\tloadWeapons(tempItemList);\n\n\t// refresh list\n\t// (unsorts it again, which is not a problem)\n\ttempItemList = *_craftInventoryTile->getInventory();\n\n\tfor (BattleItem* bi : tempItemList)\n\t{\n\t\t// we only need to distribute extra ammo at this point.\n\t\tif (bi->getRules()->getBattleType() != BT_AMMO)\n\t\t\tcontinue;\n\t\tplaceItemByLayout(bi, tempItemList);\n\t}\n\n\t// refresh list\n\ttempItemList = *_craftInventoryTile->getInventory();\n\n\t// auto-equip soldiers (only soldiers without layout) and clean up moved items\n\tautoEquip(*_save->getUnits(), _game->getMod(), &tempItemList, ground, _worldShade, _allowAutoLoadout, false);\n}\n\nvoid BattlescapeGenerator::autoEquip(std::vector<BattleUnit*> units, Mod *mod, std::vector<BattleItem*> *craftInv,\n\t\tRuleInventory *groundRuleInv, int worldShade, bool allowAutoLoadout, bool overrideEquipmentLayout)\n{\n\tfor (int pass = 0; pass < 4; ++pass)\n\t{\n\t\tBattleItem* bi = nullptr;\n\t\tfor (auto iter = craftInv->begin(); iter != craftInv->end();)\n\t\t{\n\t\t\tbi = (*iter);\n\t\t\tif (bi->getRules()->getInventoryHeight() == 0 || bi->getRules()->getInventoryWidth() == 0)\n\t\t\t{\n\t\t\t\t// don't autoequip hidden items, whatever they are\n\t\t\t\t++iter;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (bi->getSlot() == groundRuleInv)\n\t\t\t{\n\t\t\t\tbool add = false;\n\n\t\t\t\tswitch (pass)\n\t\t\t\t{\n\t\t\t\t// priority 1: rifles.\n\t\t\t\tcase 0:\n\t\t\t\t\tadd = bi->getRules()->isRifle();\n\t\t\t\t\tbreak;\n\t\t\t\t// priority 2: pistols (assuming no rifles were found).\n\t\t\t\tcase 1:\n\t\t\t\t\tadd = bi->getRules()->isPistol();\n\t\t\t\t\tbreak;\n\t\t\t\t// priority 3: ammunition.\n\t\t\t\tcase 2:\n\t\t\t\t\tadd = bi->getRules()->getBattleType() == BT_AMMO;\n\t\t\t\t\tbreak;\n\t\t\t\t// priority 4: leftovers.\n\t\t\t\tcase 3:\n\t\t\t\t\tadd = !bi->getRules()->isPistol() &&\n\t\t\t\t\t\t\t!bi->getRules()->isRifle() &&\n\t\t\t\t\t\t\t(bi->getRules()->getBattleType() != BT_FLARE || worldShade > mod->getMaxDarknessToSeeUnits());\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif (add)\n\t\t\t\t{\n\t\t\t\t\tfor (auto* bu : units)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (!bu->hasInventory() || !bu->getGeoscapeSoldier() || (!overrideEquipmentLayout && !bu->getGeoscapeSoldier()->getEquipmentLayout()->empty()))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// let's not be greedy, we'll only take a second extra clip\n\t\t\t\t\t\t// if everyone else has had a chance to take a first.\n\t\t\t\t\t\tbool allowSecondClip = (pass == 3);\n\t\t\t\t\t\tif (bu->addItem(bi, mod, allowSecondClip, allowAutoLoadout))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\titer = craftInv->erase(iter);\n\t\t\t\t\t\t\tadd = false;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (!add)\n\t\t\t\t\t{\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t++iter;\n\t\t}\n\t}\n}\n\n/**\n * Adds an XCom vehicle to the game.\n * Sets the correct turret depending on the ammo type.\n * @param v Pointer to the Vehicle.\n * @return Pointer to the spawned unit.\n */\nBattleUnit *BattlescapeGenerator::addXCOMVehicle(Vehicle *v)\n{\n\tconst Unit *rule = v->getRules()->getVehicleUnit();\n\tBattleUnit *unit = addXCOMUnit(_save->createTempUnit(rule, FACTION_PLAYER, _unitSequence++));\n\tif (unit)\n\t{\n\t\tif (!_save->isPreview())\n\t\t{\n\t\t\t_save->createItemForUnit(v->getRules(), unit, true);\n\t\t\tif (v->getRules()->getVehicleClipAmmo())\n\t\t\t{\n\t\t\t\tBattleItem *ammoItem = _save->createItemForUnit(v->getRules()->getVehicleClipAmmo(), unit);\n\t\t\t\tif (ammoItem)\n\t\t\t\t{\n\t\t\t\t\tammoItem->setAmmoQuantity(v->getAmmo());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tunit->setTurretType(v->getRules()->getTurretType());\n\t}\n\treturn unit;\n}\n\n/**\n * Adds a soldier to the game and places him on a free spawnpoint.\n * Spawnpoints are either tiles in case of an XCom craft that landed.\n * Or they are map nodes in case there's no craft.\n * @param soldier Pointer to the Soldier.\n * @return Pointer to the spawned unit.\n */\nBattleUnit *BattlescapeGenerator::addXCOMUnit(BattleUnit *unit)\n{\n\tif (_save->isPreview() && !_save->getCraftForPreview())\n\t{\n\t\t// base preview, one standard unit is enough\n\t\tif (_save->getUnits()->size() > 0 && !_save->getUnits()->back()->isSummonedPlayerUnit())\n\t\t{\n\t\t\tdelete unit;\n\t\t\treturn nullptr;\n\t\t}\n\t}\n\n\tif (_baseInventory)\n\t{\n\t\tif (unit->hasInventory())\n\t\t{\n\t\t\t_save->getUnits()->push_back(unit);\n\t\t\t_save->initUnit(unit);\n\t\t\treturn unit;\n\t\t}\n\t}\n\telse\n\t{\n\t\tif (_craft == 0 || !_craftDeployed)\n\t\t{\n\t\t\tsetCustomCraftInventoryTile();\n\n\t\t\tNode* node = _save->getSpawnNode(NR_XCOM, unit);\n\t\t\tif (node)\n\t\t\t{\n\t\t\t\t_save->setUnitPosition(unit, node->getPosition());\n\t\t\t\tif (!_craftInventoryTile)\n\t\t\t\t{\n\t\t\t\t\t_craftInventoryTile = _save->getTile(node->getPosition());\n\t\t\t\t}\n\t\t\t\tunit->setDirection(RNG::generate(0, 7));\n\t\t\t\t_save->getUnits()->push_back(unit);\n\t\t\t\t_save->initUnit(unit);\n\t\t\t\treturn unit;\n\t\t\t}\n\t\t\telse if (_save->getMissionType() != \"STR_BASE_DEFENSE\")\n\t\t\t{\n\t\t\t\tif (placeUnitNearFriend(unit))\n\t\t\t\t{\n\t\t\t\t\tif (!_craftInventoryTile)\n\t\t\t\t\t{\n\t\t\t\t\t\t_craftInventoryTile = _save->getTile(unit->getPosition());\n\t\t\t\t\t}\n\t\t\t\t\tunit->setDirection(RNG::generate(0, 7));\n\t\t\t\t\t_save->getUnits()->push_back(unit);\n\t\t\t\t\t_save->initUnit(unit);\n\t\t\t\t\treturn unit;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse if (_craft && _craft->hasCustomDeployment() && _craft->getRules() == _craftRules)\n\t\t{\n\t\t\tsetCustomCraftInventoryTile();\n\n\t\t\tbool canPlace = false;\n\t\t\tPosition pos;\n\t\t\tint dir = 0;\n\t\t\tif (unit->getGeoscapeSoldier())\n\t\t\t{\n\t\t\t\tauto& depl = _craft->getCustomSoldierDeployment().at(unit->getGeoscapeSoldier()->getId()); // crashes if not found\n\t\t\t\tpos = depl.first + Position(_craftPos.x * 10, _craftPos.y * 10, _craftZ);\n\t\t\t\tdir = depl.second;\n\t\t\t\tcanPlace = true;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tauto& deplVec = _craft->getCustomVehicleDeployment();\n\t\t\t\tfor (auto& depl : deplVec)\n\t\t\t\t{\n\t\t\t\t\tif (depl.type == unit->getType() && !depl.used)\n\t\t\t\t\t{\n\t\t\t\t\t\tpos = depl.pos + Position(_craftPos.x * 10, _craftPos.y * 10, _craftZ);\n\t\t\t\t\t\tdir = depl.dir;\n\t\t\t\t\t\tcanPlace = true;\n\t\t\t\t\t\tdepl.used = true; // mark as used, i.e. don't try the same for the next vehicle unit\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!canPlace)\n\t\t\t{\n\t\t\t\tthrow Exception(\"Unit generator encountered an error: custom craft deployment failed.\");\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tfor (int x = 0; x < unit->getArmor()->getSize(); ++x)\n\t\t\t\t{\n\t\t\t\t\tfor (int y = 0; y < unit->getArmor()->getSize(); ++y)\n\t\t\t\t\t{\n\t\t\t\t\t\tcanPlace = (canPlace && canPlaceXCOMUnit(_save->getTile(pos + Position(x, y, 0))));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (canPlace)\n\t\t\t{\n\t\t\t\tif (_save->setUnitPosition(unit, pos))\n\t\t\t\t{\n\t\t\t\t\t_save->getUnits()->push_back(unit);\n\t\t\t\t\t_save->initUnit(unit);\n\t\t\t\t\tunit->setDirection(dir);\n\t\t\t\t\treturn unit;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse if (_craft && _save->hasCustomDeployment(_craftRules))\n\t\t{\n\t\t\tsetCustomCraftInventoryTile();\n\n\t\t\tauto& deploy = _save->getCustomDeployment(_craftRules);\n\t\t\tfor (auto& vec : deploy)\n\t\t\t{\n\t\t\t\tPosition pos = Position(vec[0] + (_craftPos.x * 10), vec[1] + (_craftPos.y * 10), vec[2] + _craftZ);\n\t\t\t\tint dir = vec[3];\n\t\t\t\tbool canPlace = true;\n\t\t\t\tfor (int x = 0; x < unit->getArmor()->getSize(); ++x)\n\t\t\t\t{\n\t\t\t\t\tfor (int y = 0; y < unit->getArmor()->getSize(); ++y)\n\t\t\t\t\t{\n\t\t\t\t\t\tcanPlace = (canPlace && canPlaceXCOMUnit(_save->getTile(pos + Position(x, y, 0))));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (canPlace)\n\t\t\t\t{\n\t\t\t\t\tif (_save->setUnitPosition(unit, pos))\n\t\t\t\t\t{\n\t\t\t\t\t\t_save->getUnits()->push_back(unit);\n\t\t\t\t\t\t_save->initUnit(unit);\n\t\t\t\t\t\tunit->setDirection(dir);\n\t\t\t\t\t\treturn unit;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tsetCustomCraftInventoryTile();\n\n\t\t\tfor (int i = 0; i < _mapsize_x * _mapsize_y * _mapsize_z; ++i)\n\t\t\t{\n\t\t\t\tif (canPlaceXCOMUnit(_save->getTile(i)))\n\t\t\t\t{\n\t\t\t\t\tif (_save->setUnitPosition(unit, _save->getTile(i)->getPosition()))\n\t\t\t\t\t{\n\t\t\t\t\t\t_save->getUnits()->push_back(unit);\n\t\t\t\t\t\t_save->initUnit(unit);\n\t\t\t\t\t\treturn unit;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tdelete unit;\n\treturn 0;\n}\n\n/**\n * Tries to set a custom craft inventory tile.\n */\nvoid BattlescapeGenerator::setCustomCraftInventoryTile()\n{\n\tif (_craftInventoryTile == 0 && _craft && _craftDeployed && _craftRules)\n\t{\n\t\t// Craft inventory tile position defined in the ruleset\n\t\tconst std::vector<int> coords = _craftRules->getCraftInventoryTile();\n\t\tif (coords.size() >= 3)\n\t\t{\n\t\t\tPosition craftInventoryTilePosition = Position(coords[0] + (_craftPos.x * 10), coords[1] + (_craftPos.y * 10), coords[2] + _craftZ);\n\t\t\tcanPlaceXCOMUnit(_save->getTile(craftInventoryTilePosition));\n\t\t}\n\t}\n\tif (_craftInventoryTile == 0)\n\t{\n\t\t// Mapblock inventory tile position defined in the ruleset\n\t\tif (!_backupInventoryTiles.empty())\n\t\t{\n\t\t\tint pilePick = RNG::generate(0, _backupInventoryTiles.size() - 1);\n\t\t\tTile* pileTile = _backupInventoryTiles[pilePick];\n\t\t\t_craftInventoryTile = pileTile; // no checks\n\t\t}\n\t}\n}\n\n/**\n * Checks if a soldier/tank can be placed on a given tile.\n * @param tile the given tile.\n * @return whether the unit can be placed here.\n */\nbool BattlescapeGenerator::canPlaceXCOMUnit(Tile *tile)\n{\n\t// to spawn an xcom soldier, there has to be a tile, with a floor, with the starting point attribute and no object in the way\n\tif (tile &&\n\t\ttile->getFloorSpecialTileType() == START_POINT &&\n\t\t!tile->getMapData(O_OBJECT) &&\n\t\ttile->getMapData(O_FLOOR) && // for clarity this is checked again, first time was in `getFloorSpecialTileType`\n\t\ttile->getMapData(O_FLOOR)->getTUCost(MT_WALK) != Pathfinding::INVALID_MOVE_COST)\n\t{\n\t\tif (_craftInventoryTile == 0)\n\t\t\t_craftInventoryTile = tile;\n\n\t\treturn true;\n\t}\n\treturn false;\n}\n\n/**\n * Deploys the aliens, according to the alien deployment rules.\n * @param race Pointer to the alien race.\n * @param deployment Pointer to the deployment rules.\n */\nvoid BattlescapeGenerator::deployAliens(const AlienDeployment *deployment)\n{\n\t// race defined by deployment if there is one.\n\tstd::string tmpRace = deployment->getRace();\n\tif (!tmpRace.empty() && _game->getSavedGame()->getMonthsPassed() > -1)\n\t{\n\t\t_alienRace = tmpRace;\n\t}\n\n\tif (_save->getDepth() > 0 && _alienRace.find(\"_UNDERWATER\") == std::string::npos)\n\t{\n\t\t_alienRace = _alienRace + \"_UNDERWATER\";\n\t}\n\n\tAlienRace *race = _game->getMod()->getAlienRace(_alienRace);\n\tif (race == 0)\n\t{\n\t\tthrow Exception(\"Map generator encountered an error: Unknown race: \" + _alienRace + \" defined in deployment: \" + deployment->getType());\n\t}\n\n\t// save for later use\n\t_save->setReinforcementsDeployment(deployment->getType());\n\t_save->setReinforcementsRace(race->getId());\n\t_save->setReinforcementsItemLevel(_save->getAlienItemLevel());\n\t// and reset memory at each stage\n\t_save->getReinforcementsMemory().clear();\n\n\tfor (auto& dd : *deployment->getDeploymentData())\n\t{\n\t\tint quantity;\n\n\t\tswitch (_game->getSavedGame()->getDifficulty())\n\t\t{\n\t\tcase DIFF_BEGINNER:\n\t\t\tquantity = dd.lowQty;\n\t\t\tbreak;\n\t\tcase DIFF_EXPERIENCED:\n\t\t\tquantity = dd.medQty > 0 ? dd.lowQty + ((dd.medQty - dd.lowQty) / 2) : dd.lowQty;\n\t\t\tbreak;\n\t\tcase DIFF_VETERAN:\n\t\t\tquantity = dd.medQty > 0 ? dd.medQty : dd.lowQty + ((dd.highQty - dd.lowQty) / 2);\n\t\t\tbreak;\n\t\tcase DIFF_GENIUS:\n\t\t\tquantity = dd.medQty > 0 ? dd.medQty + ((dd.highQty - dd.medQty) / 2) : dd.lowQty + ((dd.highQty - dd.lowQty) / 2);\n\t\t\tbreak;\n\t\tcase DIFF_SUPERHUMAN:\n\t\tdefault:\n\t\t\tquantity = dd.highQty;\n\t\t}\n\n\t\tquantity += _mod->isDemigod() ? dd.dQty : RNG::generate(0, dd.dQty); // maximium spawns for demigod\n\t\tquantity += _mod->isDemigod() ? dd.extraQty : RNG::generate(0, dd.extraQty);\n\n\t\tfor (int i = 0; i < quantity; ++i)\n\t\t{\n\t\t\t// if the UFO was damaged, each alien (after the first) has a chance to not spawn (during base defense)\n\t\t\tif (_ufoDamagePercentage > 0)\n\t\t\t{\n\t\t\t\tif (i > 0 && RNG::percent(_ufoDamagePercentage))\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tstd::string alienName = dd.customUnitType.empty() ? race->getMember(dd.alienRank) : dd.customUnitType;\n\n\t\t\tbool outside = RNG::percent(dd.percentageOutsideUfo);\n\t\t\tif (_ufo == 0 && !deployment->getForcePercentageOutsideUfo())\n\t\t\t{\n\t\t\t\toutside = false;\n\t\t\t}\n\t\t\tUnit *rule = _game->getMod()->getUnit(alienName, true);\n\t\t\tBattleUnit *unit = addAlien(rule, dd.alienRank, outside);\n\t\t\tsize_t itemLevel = (size_t)(_game->getMod()->getAlienItemLevels().at(_save->getAlienItemLevel()).at(RNG::generate(0,9)));\n\t\t\tif (unit)\n\t\t\t{\n\t\t\t\t_save->initUnit(unit, itemLevel);\n\t\t\t\tif (!rule->isLivingWeapon())\n\t\t\t\t{\n\t\t\t\t\tif (dd.itemSets.empty())\n\t\t\t\t\t{\n\t\t\t\t\t\tthrow Exception(\"Unit generator encountered an error: item set not defined\");\n\t\t\t\t\t}\n\t\t\t\t\tif (itemLevel >= dd.itemSets.size())\n\t\t\t\t\t{\n\t\t\t\t\t\titemLevel = dd.itemSets.size() - 1;\n\t\t\t\t\t}\n\t\t\t\t\tfor (auto& itemType : dd.itemSets.at(itemLevel).items)\n\t\t\t\t\t{\n\t\t\t\t\t\tRuleItem *ruleItem = _game->getMod()->getItem(itemType);\n\t\t\t\t\t\tif (ruleItem)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_save->createItemForUnit(ruleItem, unit);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tfor (auto& iset : dd.extraRandomItems)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (iset.items.empty())\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\tint pick = RNG::generate(0, iset.items.size() - 1);\n\t\t\t\t\t\tRuleItem *ruleItem = _game->getMod()->getItem(iset.items[pick]);\n\t\t\t\t\t\tif (ruleItem)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_save->createItemForUnit(ruleItem, unit);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n\n/**\n * Adds an alien to the game and places him on a free spawnpoint.\n * @param rules Pointer to the Unit which holds info about the alien .\n * @param alienRank The rank of the alien, used for spawn point search.\n * @param outside Whether the alien should spawn outside or inside the UFO.\n * @return Pointer to the created unit.\n */\nBattleUnit *BattlescapeGenerator::addAlien(Unit *rules, int alienRank, bool outside)\n{\n\tBattleUnit *unit = _save->createTempUnit(rules, FACTION_HOSTILE, _unitSequence++);\n\tNode *node = 0;\n\n\t// safety to avoid index out of bounds errors\n\tif (alienRank > 7)\n\t\talienRank = 7;\n\t/* following data is the order in which certain alien ranks spawn on certain node ranks */\n\t/* note that they all can fall back to rank 0 nodes - which is scout (outside ufo) */\n\n\tfor (int i = 0; i < 7 && node == 0; ++i)\n\t{\n\t\tif (outside)\n\t\t\tnode = _save->getSpawnNode(0, unit); // when alien is instructed to spawn outside, we only look for node 0 spawnpoints\n\t\telse\n\t\t\tnode = _save->getSpawnNode(Node::nodeRank[alienRank][i], unit);\n\t}\n\n\tint aliensFacingCraftOdds = 20 * _game->getSavedGame()->getDifficultyCoefficient();\n\t{\n\t\tint diff = _game->getSavedGame()->getDifficulty();\n\t\tauto& custom = _game->getMod()->getAliensFacingCraftOdds();\n\t\tif (custom.size() > (size_t)diff)\n\t\t{\n\t\t\taliensFacingCraftOdds = custom[diff];\n\t\t}\n\t}\n\n\tif (node && _save->setUnitPosition(unit, node->getPosition()))\n\t{\n\t\tunit->getAIModule()->setStartNode(node);\n\t\tunit->setRankInt(alienRank);\n\t\tint dir = _save->getTileEngine()->faceWindow(node->getPosition());\n\t\tPosition craft = _game->getSavedGame()->getSavedBattle()->getUnits()->at(0)->getPosition();\n\t\tif (Position::distance2d(node->getPosition(), craft) <= 20 && RNG::percent(aliensFacingCraftOdds))\n\t\t\tdir = unit->directionTo(craft);\n\t\tif (dir != -1)\n\t\t\tunit->setDirection(dir);\n\t\telse\n\t\t\tunit->setDirection(RNG::generate(0,7));\n\n\t\t// we only add a unit if it has a node to spawn on.\n\t\t// (stops them spawning at 0,0,0)\n\t\t_save->getUnits()->push_back(unit);\n\t}\n\telse\n\t{\n\t\t// DEMIGOD DIFFICULTY: screw the player: spawn as many aliens as possible.\n\t\tif ((_game->getMod()->isDemigod() || Mod::EXTENDED_FORCE_SPAWN) && placeUnitNearFriend(unit))\n\t\t{\n\t\t\tunit->setRankInt(alienRank);\n\t\t\tint dir = _save->getTileEngine()->faceWindow(unit->getPosition());\n\t\t\tPosition craft = _game->getSavedGame()->getSavedBattle()->getUnits()->at(0)->getPosition();\n\t\t\tif (Position::distance2d(unit->getPosition(), craft) <= 20 && RNG::percent(aliensFacingCraftOdds))\n\t\t\t\tdir = unit->directionTo(craft);\n\t\t\tif (dir != -1)\n\t\t\t\tunit->setDirection(dir);\n\t\t\telse\n\t\t\t\tunit->setDirection(RNG::generate(0,7));\n\n\t\t\t_save->getUnits()->push_back(unit);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tdelete unit;\n\t\t\tunit = 0;\n\t\t}\n\t}\n\n\treturn unit;\n}\n\n/**\n * Adds a civilian to the game and places him on a free spawnpoint.\n * @param rules Pointer to the Unit which holds info about the civilian.\n * @return Pointer to the created unit.\n */\nBattleUnit *BattlescapeGenerator::addCivilian(Unit *rules, int nodeRank)\n{\n\tBattleUnit *unit = _save->createTempUnit(rules, FACTION_NEUTRAL, _unitSequence++);\n\tNode *node = _save->getSpawnNode(nodeRank, unit);\n\n\tif (node)\n\t{\n\t\t_save->setUnitPosition(unit, node->getPosition());\n\t\tunit->getAIModule()->setStartNode(node);\n\t\tunit->setDirection(RNG::generate(0,7));\n\n\t\t// we only add a unit if it has a node to spawn on.\n\t\t// (stops them spawning at 0,0,0)\n\t\t_save->getUnits()->push_back(unit);\n\t}\n\telse if (placeUnitNearFriend(unit))\n\t{\n\t\tunit->setDirection(RNG::generate(0,7));\n\t\t_save->getUnits()->push_back(unit);\n\t}\n\telse\n\t{\n\t\tdelete unit;\n\t\tunit = 0;\n\t}\n\treturn unit;\n}\n\n/**\n * Places an item on an XCom soldier based on equipment layout.\n * @param item Pointer to the Item.\n * @return Pointer to the Item.\n */\nbool BattlescapeGenerator::placeItemByLayout(BattleItem *item, const std::vector<BattleItem*> &itemList)\n{\n\tif (item->getSlot() == _inventorySlotGround)\n\t{\n\t\t// find the first soldier with a matching layout-slot\n\t\tfor (auto* unit : *_save->getUnits())\n\t\t{\n\t\t\t// skip the vehicles, we need only X-Com soldiers WITH equipment-layout\n\t\t\tif (!unit->getGeoscapeSoldier() || unit->getGeoscapeSoldier()->getEquipmentLayout()->empty())\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// find the first matching layout-slot which is not already occupied\n\t\t\tfor (const auto* layoutItem : *unit->getGeoscapeSoldier()->getEquipmentLayout())\n\t\t\t{\n\t\t\t\t// fixed items will be handled elsewhere\n\t\t\t\tif (layoutItem->isFixed()) continue;\n\n\t\t\t\tif (item->getRules() != layoutItem->getItemType()) continue;\n\n\t\t\t\t// we need to check all \"slot boxes\" for overlap (not just top left)\n\t\t\t\tbool overlaps = false;\n\t\t\t\tfor (int x = 0; x < item->getRules()->getInventoryWidth(); ++x)\n\t\t\t\t{\n\t\t\t\t\tfor (int y = 0; y < item->getRules()->getInventoryHeight(); ++y)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (!overlaps && unit->getItem(layoutItem->getSlot(), x + layoutItem->getSlotX(), y + layoutItem->getSlotY()))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\toverlaps = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (overlaps) continue;\n\n\t\t\t\tint toLoad = 0;\n\t\t\t\tfor (int slot = 0; slot < RuleItem::AmmoSlotMax; ++slot)\n\t\t\t\t{\n\t\t\t\t\tif (layoutItem->getAmmoItemForSlot(slot) != nullptr)\n\t\t\t\t\t{\n\t\t\t\t\t\t++toLoad;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (toLoad)\n\t\t\t\t{\n\t\t\t\t\t// maybe we find the layout-ammo on the ground to load it with\n\t\t\t\t\tfor (auto* ammo : itemList)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (ammo->getSlot() == _inventorySlotGround)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfor (int slot = 0; slot < RuleItem::AmmoSlotMax; ++slot)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (ammo->getRules() == layoutItem->getAmmoItemForSlot(slot))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tif (item->setAmmoPreMission(ammo))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t--toLoad;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t// even if item was not loaded other slots can't use it either\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (!toLoad)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// only place the weapon onto the soldier when it's loaded with its layout-ammo (if any)\n\t\t\t\tif (!toLoad || item->haveAnyAmmo())\n\t\t\t\t{\n\t\t\t\t\titem->moveToOwner(unit);\n\t\t\t\t\titem->setSlot(layoutItem->getSlot());\n\t\t\t\t\titem->setSlotX(layoutItem->getSlotX());\n\t\t\t\t\titem->setSlotY(layoutItem->getSlotY());\n\t\t\t\t\tif (Options::includePrimeStateInSavedLayout && item->getRules()->getFuseTimerType() != BFT_NONE)\n\t\t\t\t\t{\n\t\t\t\t\t\titem->setFuseTimer(layoutItem->getFuseTimer());\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Reloads fixed weapons on XCom soldiers based on equipment layout.\n */\nvoid BattlescapeGenerator::reloadFixedWeaponsByLayout()\n{\n\t// go through all soldiers\n\tfor (auto* unit : *_save->getUnits())\n\t{\n\t\t// skip the vehicles, we need only X-Com soldiers WITH equipment-layout\n\t\tif (!unit->getGeoscapeSoldier() || unit->getGeoscapeSoldier()->getEquipmentLayout()->empty())\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\n\t\t// find fixed weapons in the layout\n\t\tfor (const auto* layoutItem : *unit->getGeoscapeSoldier()->getEquipmentLayout())\n\t\t{\n\t\t\tif (layoutItem->isFixed() == false) continue;\n\n\t\t\t// find matching fixed weapon in the inventory\n\t\t\tBattleItem* fixedItem = nullptr;\n\t\t\tfor (auto* item : *unit->getInventory())\n\t\t\t{\n\t\t\t\tif (item->getSlot() == layoutItem->getSlot() &&\n\t\t\t\t\titem->getSlotX() == layoutItem->getSlotX() &&\n\t\t\t\t\titem->getSlotY() == layoutItem->getSlotY() &&\n\t\t\t\t\titem->getRules() == layoutItem->getItemType())\n\t\t\t\t{\n\t\t\t\t\tfixedItem = item;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!fixedItem) continue;\n\n\t\t\tint toLoad = 0;\n\t\t\tfor (int slot = 0; slot < RuleItem::AmmoSlotMax; ++slot)\n\t\t\t{\n\t\t\t\tif (layoutItem->getAmmoItemForSlot(slot) != nullptr)\n\t\t\t\t{\n\t\t\t\t\t++toLoad;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (toLoad)\n\t\t\t{\n\t\t\t\t// maybe we find the layout-ammo on the ground to load it with\n\t\t\t\tfor (auto* ammo : *_craftInventoryTile->getInventory())\n\t\t\t\t{\n\t\t\t\t\tif (ammo->getSlot() == _inventorySlotGround)\n\t\t\t\t\t{\n\t\t\t\t\t\tfor (int slot = 0; slot < RuleItem::AmmoSlotMax; ++slot)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (ammo->getRules() == layoutItem->getAmmoItemForSlot(slot))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (fixedItem->setAmmoPreMission(ammo))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t--toLoad;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// even if item was not loaded other slots can't use it either\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!toLoad)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Loads an XCom format MAP file into the tiles of the battlegame.\n * @param mapblock Pointer to MapBlock.\n * @param xoff Mapblock offset in X direction.\n * @param yoff Mapblock offset in Y direction.\n * @param save Pointer to the current SavedBattleGame.\n * @param terrain Pointer to the Terrain rule.\n * @param discovered Whether or not this mapblock is discovered (eg. landing site of the XCom plane).\n * @return int Height of the loaded mapblock (this is needed for spawnpoint calculation...)\n * @sa http://www.ufopaedia.org/index.php?title=MAPS\n * @note Y-axis is in reverse order.\n */\nint BattlescapeGenerator::loadMAP(MapBlock *mapblock, int xoff, int yoff, int zoff, RuleTerrain *terrain, int mapDataSetOffset, bool discovered, bool craft, int ufoIndex)\n{\n\tint sizex, sizey, sizez;\n\tint x = xoff, y = yoff, z = zoff;\n\tchar size[3];\n\tunsigned char value[4];\n\tstd::string filename = \"MAPS/\" + mapblock->getName() + \".MAP\";\n\tunsigned int terrainObjectID;\n\n\t// Load file\n\tauto mapFile = FileMap::getIStream(filename);\n\n\tmapFile->read((char*)&size, sizeof(size));\n\tsizey = (int)size[0];\n\tsizex = (int)size[1];\n\tsizez = (int)size[2];\n\n\tmapblock->setSizeZ(sizez);\n\n\tstd::ostringstream ss;\n\tif (sizez > _save->getMapSizeZ())\n\t{\n\t\tss << \"Height of map \" + filename + \" too big for this mission, block is \" << sizez << \", expected: \" << _save->getMapSizeZ();\n\t\tthrow Exception(ss.str());\n\t}\n\n\tif (sizex != mapblock->getSizeX() ||\n\t\tsizey != mapblock->getSizeY())\n\t{\n\t\tss << \"Map block is not of the size specified \" + filename + \" is \" << sizex << \"x\" << sizey << \" , expected: \" << mapblock->getSizeX() << \"x\" << mapblock->getSizeY();\n\t\tthrow Exception(ss.str());\n\t}\n\n\tz += sizez - 1;\n\n\tfor (int i = _mapsize_z-1; i >0; i--)\n\t{\n\t\t// check if there is already a layer - if so, we have to move Z up\n\t\tMapData *floor = _save->getTile(Position(x, y, i))->getMapData(O_FLOOR);\n\t\tif (floor != 0 && zoff == 0)\n\t\t{\n\t\t\tz += i;\n\t\t\tif (craft && _craftZ == 0)\n\t\t\t{\n\t\t\t\t_craftZ = i;\n\t\t\t}\n\t\t\tif (ufoIndex >= 0 && _ufoZ[ufoIndex] == 0)\n\t\t\t{\n\t\t\t\t_ufoZ[ufoIndex] = i;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (z > (_save->getMapSizeZ()-1))\n\t{\n\t\tif (_save->getMissionType() == \"STR_BASE_DEFENSE\")\n\t\t{\n\t\t\t// we'll already have gone through _base->isOverlappingOrOverflowing() by the time we hit this, possibly multiple times\n\t\t\t// let's just throw an exception and tell them to check the log, it'll have all the detail they'll need.\n\t\t\tthrow Exception(\"Something is wrong with your base, check your log file for additional information.\");\n\t\t}\n\t\tthrow Exception(\"Something is wrong in your map definitions, craft/ufo map is too tall?\");\n\t}\n\n\twhile (mapFile->read((char*)&value, sizeof(value)))\n\t{\n\t\tfor (int part = O_FLOOR; part < O_MAX; ++part)\n\t\t{\n\t\t\tterrainObjectID = ((unsigned char)value[part]);\n\t\t\tif (terrainObjectID>0)\n\t\t\t{\n\t\t\t\tint mapDataSetID = mapDataSetOffset;\n\t\t\t\tunsigned int mapDataID = terrainObjectID;\n\t\t\t\tMapData *md = terrain->getMapData(&mapDataID, &mapDataSetID);\n\t\t\t\tif (mapDataSetOffset > 0) // ie: ufo or craft.\n\t\t\t\t{\n\t\t\t\t\t_save->getTile(Position(x, y, z))->setMapData(0, -1, -1, O_OBJECT);\n\t\t\t\t}\n\t\t\t\tTilePart tp = (TilePart) part;\n\t\t\t\t_save->getTile(Position(x, y, z))->setMapData(md, mapDataID, mapDataSetID, tp);\n\t\t\t}\n\t\t}\n\n\t\t_save->getTile(Position(x, y, z))->setDiscovered((discovered || mapblock->isFloorRevealed(z)), O_FLOOR);\n\n\t\tx++;\n\n\t\tif (x == (sizex + xoff))\n\t\t{\n\t\t\tx = xoff;\n\t\t\ty++;\n\t\t}\n\t\tif (y == (sizey + yoff))\n\t\t{\n\t\t\ty = yoff;\n\t\t\tz--;\n\t\t}\n\t}\n\n\tif (!mapFile->eof())\n\t{\n\t\tthrow Exception(\"Invalid MAP file: \" + filename);\n\t}\n\n\t// Add the craft offset to the positions of the items if we're loading a craft map\n\t// But don't do so if loading a verticalLevel, since the z offset of the craft is handled by that code\n\tif (craft && zoff == 0)\n\t{\n\t\tzoff += _craftZ;\n\t}\n\t// Add the ufo offset to the positions of the items if we're loading a ufo map\n\t// But don't do so if loading a verticalLevel, since the z offset of the ufo is handled by that code\n\tif (ufoIndex >= 0 && zoff == 0)\n\t{\n\t\tzoff += _ufoZ[ufoIndex];\n\t}\n\n\tif (_generateFuel)\n\t{\n\t\t// if one of the mapBlocks has an items array defined, don't deploy fuel algorithmically\n\t\t_generateFuel = mapblock->getItems()->empty();\n\t}\n\tauto primeEnd = mapblock->getItemsFuseTimers()->end();\n\tfor (auto& mapblockItemInfo : *mapblock->getItems())\n\t{\n\t\tauto prime = mapblock->getItemsFuseTimers()->find(mapblockItemInfo.first);\n\t\tRuleItem *rule = _game->getMod()->getItem(mapblockItemInfo.first, true);\n\t\tif (rule->getBattleType() == BT_CORPSE)\n\t\t{\n\t\t\tthrow Exception(\"Placing corpse items (battleType: 11) on the map is not allowed. Item: \" + rule->getType() + \", map block: \" + mapblock->getName());\n\t\t}\n\t\tfor (auto& itemPos : mapblockItemInfo.second)\n\t\t{\n\t\t\tif (itemPos.x >= mapblock->getSizeX() || itemPos.y >= mapblock->getSizeY() || itemPos.z >= mapblock->getSizeZ())\n\t\t\t{\n\t\t\t\tss << \"Item \" << rule->getType() << \" is outside of map block \" << mapblock->getName() << \", position: [\";\n\t\t\t\tss << itemPos.x << \",\" << itemPos.y << \",\" << itemPos.z << \"], block size: [\";\n\t\t\t\tss << mapblock->getSizeX() << \",\" << mapblock->getSizeY() << \",\" << mapblock->getSizeZ() << \"]\";\n\t\t\t\tthrow Exception(ss.str());\n\t\t\t}\n\t\t\tBattleItem *item = _save->createItemForTile(rule, _save->getTile(itemPos + Position(xoff, yoff, zoff)));\n\t\t\tif (prime != primeEnd)\n\t\t\t{\n\t\t\t\titem->setFuseTimer(RNG::generate(prime->second.first, prime->second.second));\n\t\t\t}\n\t\t}\n\t}\n\t// randomized items\n\tfor (auto& rngItems : *mapblock->getRandomizedItems())\n\t{\n\t\tif (rngItems.itemList.size() < 1)\n\t\t{\n\t\t\tcontinue; // skip empty definition\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// mixed = false\n\t\t\tint index = RNG::generate(0, rngItems.itemList.size() - 1);\n\t\t\tRuleItem *rule = _game->getMod()->getItem(rngItems.itemList[index], true);\n\n\t\t\tfor (int j = 0; j < rngItems.amount; ++j)\n\t\t\t{\n\t\t\t\tif (rngItems.mixed)\n\t\t\t\t{\n\t\t\t\t\t// mixed = true\n\t\t\t\t\tindex = RNG::generate(0, rngItems.itemList.size() - 1);\n\t\t\t\t\trule = _game->getMod()->getItem(rngItems.itemList[index], true);\n\t\t\t\t}\n\n\t\t\t\tif (rule->getBattleType() == BT_CORPSE)\n\t\t\t\t{\n\t\t\t\t\tthrow Exception(\"Placing corpse items (battleType: 11) on the map is not allowed. Item: \" + rule->getType() + \", map block: \" + mapblock->getName());\n\t\t\t\t}\n\t\t\t\tif (rngItems.position.x >= mapblock->getSizeX() || rngItems.position.y >= mapblock->getSizeY() || rngItems.position.z >= mapblock->getSizeZ())\n\t\t\t\t{\n\t\t\t\t\tss << \"Random item \" << rule->getType() << \" is outside of map block \" << mapblock->getName() << \", position: [\";\n\t\t\t\t\tss << rngItems.position.x << \",\" << rngItems.position.y << \",\" << rngItems.position.z << \"], block size: [\";\n\t\t\t\t\tss << mapblock->getSizeX() << \",\" << mapblock->getSizeY() << \",\" << mapblock->getSizeZ() << \"]\";\n\t\t\t\t\tthrow Exception(ss.str());\n\t\t\t\t}\n\t\t\t\tBattleItem* newRandItem = _save->createItemForTile(rule, _save->getTile(rngItems.position + Position(xoff, yoff, zoff)));\n\t\t\t\tif (rule->getFuseTimerType() != BFT_NONE && rngItems.fuseTimerMin > -1 && rngItems.fuseTimerMax > -1 && rngItems.fuseTimerMin <= rngItems.fuseTimerMax)\n\t\t\t\t{\n\t\t\t\t\tnewRandItem->setFuseTimer(RNG::generate(rngItems.fuseTimerMin, rngItems.fuseTimerMax));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t// extended items\n\tfor (auto& extItemDef : *mapblock->getExtendedItems())\n\t{\n\t\tRuleItem* extRule = _game->getMod()->getItem(extItemDef.type, true);\n\t\tif (extRule->getBattleType() == BT_CORPSE)\n\t\t{\n\t\t\tthrow Exception(\"Placing corpse items (battleType: 11) on the map is not allowed. Item: \" + extRule->getType() + \", map block: \" + mapblock->getName());\n\t\t}\n\t\tfor (auto& extPos : extItemDef.pos)\n\t\t{\n\t\t\tif (extPos.x >= mapblock->getSizeX() || extPos.y >= mapblock->getSizeY() || extPos.z >= mapblock->getSizeZ())\n\t\t\t{\n\t\t\t\tss << \"Extended item \" << extRule->getType() << \" is outside of map block \" << mapblock->getName() << \", position: [\";\n\t\t\t\tss << extPos.x << \",\" << extPos.y << \",\" << extPos.z << \"], block size: [\";\n\t\t\t\tss << mapblock->getSizeX() << \",\" << mapblock->getSizeY() << \",\" << mapblock->getSizeZ() << \"]\";\n\t\t\t\tthrow Exception(ss.str());\n\t\t\t}\n\t\t\tBattleItem* newExtItem = _save->createItemForTile(extRule, _save->getTile(extPos + Position(xoff, yoff, zoff)));\n\t\t\tif (extItemDef.fuseTimerMin > -1 && extItemDef.fuseTimerMax > -1 && extItemDef.fuseTimerMin <= extItemDef.fuseTimerMax)\n\t\t\t{\n\t\t\t\tnewExtItem->setFuseTimer(RNG::generate(extItemDef.fuseTimerMin, extItemDef.fuseTimerMax));\n\t\t\t}\n\t\t\tfor (auto& extAmmoDef : extItemDef.ammoDef)\n\t\t\t{\n\t\t\t\tRuleItem* extAmmoRule = _game->getMod()->getItem(extAmmoDef.first, true);\n\t\t\t\tif (extAmmoRule)\n\t\t\t\t{\n\t\t\t\t\tif (extAmmoRule->getBattleType() == BT_CORPSE)\n\t\t\t\t\t{\n\t\t\t\t\t\tthrow Exception(\"Placing corpse items (battleType: 11) on the map is not allowed. Ammo item: \" + extAmmoRule->getType() + \", map block: \" + mapblock->getName());\n\t\t\t\t\t}\n\t\t\t\t\tBattleItem* newExtAmmoItem = _save->createItemForTile(extAmmoRule, _save->getTile(extPos + Position(xoff, yoff, zoff)));\n\t\t\t\t\tif (extAmmoDef.second > 0 && extAmmoDef.second < newExtAmmoItem->getAmmoQuantity())\n\t\t\t\t\t{\n\t\t\t\t\t\tnewExtAmmoItem->setAmmoQuantity(extAmmoDef.second);\n\t\t\t\t\t}\n\t\t\t\t\tif (newExtItem->isWeaponWithAmmo())\n\t\t\t\t\t{\n\t\t\t\t\t\tint slotAmmo = extRule->getSlotForAmmo(extAmmoRule);\n\t\t\t\t\t\tif (slotAmmo == -1)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tthrow Exception(\"Ammo is not compatible. Weapon: \" + extRule->getType() + \", ammo: \" + extAmmoRule->getType() + \", map block: \" + mapblock->getName());\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (newExtItem->getAmmoForSlot(slotAmmo) != 0)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tthrow Exception(\"Weapon is already loaded. Weapon: \" + extRule->getType() + \", ammo: \" + extAmmoRule->getType() + \", map block: \" + mapblock->getName());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// Put ammo in weapon\n\t\t\t\t\t\t\t\tnewExtItem->setAmmoForSlot(slotAmmo, newExtAmmoItem);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// ammo is not needed, crash or ignore?\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (mapblock->getCraftInventoryTile().size() >= 3)\n\t{\n\t\tauto& coords = mapblock->getCraftInventoryTile();\n\t\tPosition pilePos = Position(coords[0] + xoff, coords[1] + yoff, coords[2] + zoff);\n\t\tTile* pileTile = _save->getTile(pilePos);\n\t\t_backupInventoryTiles.push_back(pileTile);\n\t}\n\n\treturn sizez;\n}\n\n/**\n * Loads an XCom format RMP file into the spawnpoints of the battlegame.\n * @param mapblock Pointer to MapBlock.\n * @param xoff Mapblock offset in X direction.\n * @param yoff Mapblock offset in Y direction.\n * @param zoff Mapblock vertical offset.\n * @param segment Mapblock segment.\n * @sa http://www.ufopaedia.org/index.php?title=ROUTES\n */\nvoid BattlescapeGenerator::loadRMP(MapBlock *mapblock, int xoff, int yoff, int zoff, int segment)\n{\n\tunsigned char value[24];\n\tstd::string filename = \"ROUTES/\" + mapblock->getName() +\".RMP\";\n\t// Load file\n\tauto mapFile = FileMap::getIStream(filename);\n\n\tsize_t nodeOffset = _save->getNodes()->size();\n\tstd::vector<int> badNodes;\n\tint nodesAdded = 0;\n\twhile (mapFile->read((char*)&value, sizeof(value)))\n\t{\n\t\tint pos_x = value[1];\n\t\tint pos_y = value[0];\n\t\tint pos_z = value[2];\n\t\tNode *node;\n\t\tif (pos_x >= 0 && pos_x < mapblock->getSizeX() &&\n\t\t\tpos_y >= 0 && pos_y < mapblock->getSizeY() &&\n\t\t\tpos_z >= 0 && pos_z < mapblock->getSizeZ())\n\t\t{\n\t\t\tPosition pos = Position(xoff + pos_x, yoff + pos_y, mapblock->getSizeZ() - 1 - pos_z + zoff);\n\t\t\tint type     = value[19];\n\t\t\tint rank     = value[20];\n\t\t\tint flags    = value[21];\n\t\t\tint reserved = value[22];\n\t\t\tint priority = value[23];\n\t\t\tnode = new Node(_save->getNodes()->size(), pos, segment, type, rank, flags, reserved, priority);\n\t\t\tfor (int j = 0; j < 5; ++j)\n\t\t\t{\n\t\t\t\tint connectID = value[4 + j * 3];\n\t\t\t\t// don't touch special values\n\t\t\t\tif (connectID <= 250)\n\t\t\t\t{\n\t\t\t\t\tconnectID += nodeOffset;\n\t\t\t\t}\n\t\t\t\t// 255/-1 = unused, 254/-2 = north, 253/-3 = east, 252/-4 = south, 251/-5 = west\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tconnectID -= 256;\n\t\t\t\t}\n\t\t\t\tnode->getNodeLinks()->push_back(connectID);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// since we use getNodes()->at(n) a lot, we have to push a dummy node into the vector to keep the connections sane,\n\t\t\t// or else convert the node vector to a map, either way is as much work, so i'm sticking with vector for faster operation.\n\t\t\t// this is because the \"built in\" nodeLinks reference each other by number, and it's gonna be implementational hell to try\n\t\t\t// to adjust those numbers retroactively, post-culling. far better to simply mark these culled nodes as dummies, and discount their use\n\t\t\t// that way, all the connections will still line up properly in the array.\n\t\t\tnode = new Node();\n\t\t\tnode->setDummy(true);\n\t\t\tLog(LOG_INFO) << \"Bad node in RMP file: \" << filename << \" Node #\" << nodesAdded << \" is outside map boundaries at X:\" << pos_x << \" Y:\" << pos_y << \" Z:\" << pos_z << \". Culling Node.\";\n\t\t\tbadNodes.push_back(nodesAdded);\n\t\t}\n\t\t_save->getNodes()->push_back(node);\n\t\tnodesAdded++;\n\t}\n\n\tfor (int badNodeId : badNodes)\n\t{\n\t\tint nodeCounter = nodesAdded;\n\t\tfor (std::vector<Node*>::reverse_iterator nodeIt = _save->getNodes()->rbegin(); nodeIt != _save->getNodes()->rend() && nodeCounter > 0; ++nodeIt)\n\t\t{\n\t\t\tif (!(*nodeIt)->isDummy())\n\t\t\t{\n\t\t\t\tfor (int& nodeLink : *(*nodeIt)->getNodeLinks())\n\t\t\t\t{\n\t\t\t\t\tif (nodeLink - nodeOffset == (unsigned)badNodeId)\n\t\t\t\t\t{\n\t\t\t\t\t\tLog(LOG_INFO) << \"RMP file: \" << filename << \" Node #\" << nodeCounter - 1 << \" is linked to Node #\" << badNodeId << \", which was culled. Terminating Link.\";\n\t\t\t\t\t\tnodeLink = -1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tnodeCounter--;\n\t\t}\n\t}\n\n\tif (!mapFile->eof())\n\t{\n\t\tthrow Exception(\"Invalid RMP file: \" + filename);\n\t}\n}\n\n/**\n * Checks if a new terrain is being requested by a command and loads it if necessary\n * @param terrain Pointer to the terrain.\n * @return The MCD offset where the requested terrain begins\n */\nint BattlescapeGenerator::loadExtraTerrain(RuleTerrain *terrain)\n{\n\tint mapDataSetIDOffset;\n\n\tauto it = _loadedTerrains.find(terrain);\n\tif (it != _loadedTerrains.end())\n\t{\n\t\t// Found the terrain in the already-loaded list, get the offset\n\t\tmapDataSetIDOffset = it->second;\n\t}\n\telse\n\t{\n\t\t// Terrain not loaded yet, go ahead and load it\n\t\tmapDataSetIDOffset = _save->getMapDataSets()->size(); // new terrain's offset starts at the end of the already-loaded list\n\n\t\tfor (auto* mds : *terrain->getMapDataSets())\n\t\t{\n\t\t\tmds->loadData(_game->getMod()->getMCDPatch(mds->getName()));\n\t\t\t_save->getMapDataSets()->push_back(mds);\n\t\t}\n\n\t\t_loadedTerrains[terrain] = mapDataSetIDOffset;\n\t}\n\n\treturn mapDataSetIDOffset;\n}\n\n/**\n * Hide the \"weapon pile\".\n */\nvoid BattlescapeGenerator::sendItemsToLimbo()\n{\n\tstd::vector<BattleItem*>* takeHomeGuaranteed = _save->getGuaranteedRecoveredItems();\n\tfor (auto* bi : *_craftInventoryTile->getInventory())\n\t{\n\t\tbi->setTile(0);\n\t\tbi->setFuseTimer(-1);\n\t\ttakeHomeGuaranteed->push_back(bi);\n\n\t\tfor (int slot = 0; slot < RuleItem::AmmoSlotMax; ++slot)\n\t\t{\n\t\t\tBattleItem* ammo = bi->getAmmoForSlot(slot);\n\t\t\tif (ammo && ammo != bi)\n\t\t\t{\n\t\t\t\tammo->setTile(0);\n\t\t\t\tammo->setFuseTimer(-1);\n\t\t\t\ttakeHomeGuaranteed->push_back(ammo);\n\t\t\t}\n\t\t}\n\t}\n\t_craftInventoryTile->getInventory()->clear();\n\n\t// still need to clean up the full item list\n\tstd::vector<BattleItem*>* allItems = _save->getItems();\n\tstd::sort(allItems->begin(), allItems->end(), [](const BattleItem* a, const BattleItem* b) { return a < b; });\n\tstd::sort(takeHomeGuaranteed->begin(), takeHomeGuaranteed->end(), [](const BattleItem* a, const BattleItem* b) { return a < b; });\n\n\tstd::vector<BattleItem*> difference;\n\tstd::set_difference(allItems->begin(), allItems->end(), takeHomeGuaranteed->begin(), takeHomeGuaranteed->end(), std::back_inserter(difference));\n\n\tallItems->swap(difference);\n\n\t// beautify\n\tstd::sort(allItems->begin(), allItems->end(), [](const BattleItem* a, const BattleItem* b) { return a->getId() < b->getId(); });\n\tstd::sort(takeHomeGuaranteed->begin(), takeHomeGuaranteed->end(), [](const BattleItem* a, const BattleItem* b) { return a->getId() < b->getId(); });\n}\n\n/**\n * Fill power sources with an alien fuel object.\n */\nvoid BattlescapeGenerator::fuelPowerSources()\n{\n\tfor (int i = 0; i < _save->getMapSizeXYZ(); ++i)\n\t{\n\t\tif (_save->getTile(i)->getObjectSpecialTileType() == UFO_POWER_SOURCE)\n\t\t{\n\t\t\t_save->createItemForTile(_game->getMod()->getAlienFuelName(), _save->getTile(i));\n\t\t}\n\t}\n}\n\n\n/**\n * When a UFO crashes, there is a 75% chance for each power source to explode.\n */\nvoid BattlescapeGenerator::explodePowerSources()\n{\n\tfor (int i = 0; i < _save->getMapSizeXYZ(); ++i)\n\t{\n\t\tif (_save->getTile(i)->getObjectSpecialTileType() == UFO_POWER_SOURCE && RNG::percent(75))\n\t\t{\n\t\t\tPosition pos;\n\t\t\tpos.x = _save->getTile(i)->getPosition().x*16;\n\t\t\tpos.y = _save->getTile(i)->getPosition().y*16;\n\t\t\tpos.z = (_save->getTile(i)->getPosition().z*24) +12;\n\t\t\t_save->getTileEngine()->explode({ }, pos, 180+RNG::generate(0,70), _save->getMod()->getDamageType(DT_HE), 10);\n\t\t}\n\t}\n\tTile *t = _save->getTileEngine()->checkForTerrainExplosions();\n\twhile (t)\n\t{\n\t\tint power = t->getExplosive();\n\t\tt->setExplosive(0, 0, true);\n\t\tPosition p = t->getPosition().toVoxel() + Position(8,8,0);\n\t\t_save->getTileEngine()->explode({ }, p, power, _game->getMod()->getDamageType(DT_HE), power / 10);\n\t\tt = _save->getTileEngine()->checkForTerrainExplosions();\n\t}\n}\n\n/**\n * Terraforming.\n */\nvoid BattlescapeGenerator::explodeOtherJunk()\n{\n\tstd::vector<BattleItem*> itemsToGoBoom;\n\tstd::vector<std::tuple<Tile*, const RuleItem*> > explosionParams;\n\n\tfor (auto* bi : *_save->getItems())\n\t{\n\t\tif (bi->isOwnerIgnored() || !bi->getTile())\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\t\tif ((!bi->getRules()->getSpawnUnit() && !bi->getRules()->getSpawnItem()) && !bi->getXCOMProperty() && !bi->isSpecialWeapon())\n\t\t{\n\t\t\t// fuseTimer == 0 cannot be used, because it is already used for \"explode after the first player turn\"\n\t\t\t// fuseTimer == -1 is also used, means \"unprimed grenade\"\n\t\t\tif (bi->getRules()->getBattleType() == BT_GRENADE && bi->getFuseTimer() == -2 /* && !bi->isFuseEnabled() */)\n\t\t\t{\n\t\t\t\titemsToGoBoom.push_back(bi);\n\t\t\t\texplosionParams.push_back(std::tuple(bi->getTile(), bi->getRules()));\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (auto* item : itemsToGoBoom)\n\t{\n\t\t_save->removeItem(item);\n\t}\n\n\tfor (auto& params : explosionParams)\n\t{\n\t\tTile* tile = std::get<Tile*>(params);\n\t\tconst RuleItem* rule = std::get<const RuleItem*>(params);\n\n\t\tPosition p = tile->getPosition().toVoxel() + Position(8, 8, -tile->getTerrainLevel());\n\t\t_save->getTileEngine()->explode(\n\t\t\t{ },\n\t\t\tp,\n\t\t\trule->getPower(),\n\t\t\trule->getDamageType(),\n\t\t\trule->getExplosionRadius({ })\n\t\t);\n\t}\n\n\tTile* t = _save->getTileEngine()->checkForTerrainExplosions();\n\twhile (t)\n\t{\n\t\tItemDamageType DT;\n\t\tswitch (t->getExplosiveType())\n\t\t{\n\t\tcase 0:\n\t\t\tDT = DT_HE;\n\t\t\tbreak;\n\t\tcase 5:\n\t\t\tDT = DT_IN;\n\t\t\tbreak;\n\t\tcase 6:\n\t\t\tDT = DT_STUN;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tDT = DT_SMOKE;\n\t\t\tbreak;\n\t\t}\n\t\tint power = t->getExplosive();\n\t\tt->setExplosive(0, 0, true);\n\t\tPosition p = t->getPosition().toVoxel() + Position(8, 8, 0);\n\t\t_save->getTileEngine()->explode({ }, p, power, _game->getMod()->getDamageType(DT), power / 10);\n\t\tt = _save->getTileEngine()->checkForTerrainExplosions();\n\t}\n}\n\n/**\n * Spawns civilians on a terror mission.\n * @param max Maximum number of civilians to spawn.\n */\nvoid BattlescapeGenerator::deployCivilians(bool markAsVIP, int nodeRank, int max, bool roundUp, const std::string &civilianType)\n{\n\tif (max)\n\t{\n\t\t// inevitably someone will point out that ufopaedia says 0-16 civilians.\n\t\t// to that person: this is only partially true;\n\t\t// 0 civilians would only be a possibility if there were already 80 units,\n\t\t// or no spawn nodes for civilians, but it would always try to spawn at least 8.\n\t\tint number = RNG::generate(roundUp ? (max+1)/2 : max/2, max);\n\n\t\tif (number > 0)\n\t\t{\n\t\t\tfor (int i = 0; i < number; ++i)\n\t\t\t{\n\t\t\t\tUnit* rule = 0;\n\t\t\t\tif (civilianType.size() > 0)\n\t\t\t\t{\n\t\t\t\t\trule = _game->getMod()->getUnit(civilianType, true);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tsize_t pick = RNG::generate(0, _terrain->getCivilianTypes().size() - 1);\n\t\t\t\t\trule = _game->getMod()->getUnit(_terrain->getCivilianTypes().at(pick), true);\n\t\t\t\t}\n\t\t\t\tBattleUnit* civ = addCivilian(rule, nodeRank);\n\t\t\t\tif (civ)\n\t\t\t\t{\n\t\t\t\t\tif (markAsVIP) civ->markAsVIP();\n\t\t\t\t\tsize_t itemLevel = (size_t)(_game->getMod()->getAlienItemLevels().at(_save->getAlienItemLevel()).at(RNG::generate(0,9)));\n\t\t\t\t\t// Built in weapons: civilians may have levelled item lists with randomized distribution\n\t\t\t\t\t// following the same basic rules as the alien item levels.\n\t\t\t\t\t_save->initUnit(civ, itemLevel);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Sets the alien base involved in the battle.\n * @param base Pointer to alien base.\n */\nvoid BattlescapeGenerator::setAlienBase(AlienBase *base)\n{\n\t_alienBase = base;\n\t_alienBase->setInBattlescape(true);\n}\n\n/**\n * Places a unit near a friendly unit.\n * @param unit Pointer to the unit in question.\n * @return If we successfully placed the unit.\n */\nbool BattlescapeGenerator::placeUnitNearFriend(BattleUnit *unit)\n{\n\tif (_save->getUnits()->empty())\n\t{\n\t\treturn false;\n\t}\n\tfor (int i = 0; i != 10; ++i)\n\t{\n\t\tPosition entryPoint = TileEngine::invalid;\n\t\tint tries = 100;\n\t\tbool largeUnit = false;\n\t\twhile (entryPoint == TileEngine::invalid && tries)\n\t\t{\n\t\t\tBattleUnit* k = _save->getUnits()->at(RNG::generate(0, _save->getUnits()->size()-1));\n\t\t\tif (k->getFaction() == unit->getFaction() && k->getPosition() != TileEngine::invalid && k->getArmor()->getSize() >= unit->getArmor()->getSize())\n\t\t\t{\n\t\t\t\tentryPoint = k->getPosition();\n\t\t\t\tlargeUnit = k->isBigUnit();\n\t\t\t}\n\t\t\t--tries;\n\t\t}\n\t\tif (tries && _save->placeUnitNearPosition(unit, entryPoint, largeUnit))\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n\n/**\n * Creates a mini-battle-save for managing inventory from the Geoscape.\n * Kids, don't try this at home!\n * @param craft Pointer to craft to manage.\n */\nvoid BattlescapeGenerator::runInventory(Craft *craft)\n{\n\t// we need to fake a map for soldier placement\n\t_baseInventory = true;\n\t_mapsize_x = 2;\n\t_mapsize_y = 2;\n\t_mapsize_z = 1;\n\t_save->initMap(_mapsize_x, _mapsize_y, _mapsize_z);\n\t_save->initUtilities(_mod, true);\n\tMapDataSet *set = new MapDataSet(\"dummy\");\n\tMapData *data = new MapData(set);\n\t_craftInventoryTile = _save->getTile(0);\n\n\t// ok now generate the battle items for inventory\n\tif (craft != 0) setCraft(craft);\n\tdeployXCOM(nullptr, nullptr);\n\tdelete data;\n\tdelete set;\n}\n\n/**\n * Loads all XCom weaponry before anything else is distributed.\n */\nvoid BattlescapeGenerator::loadWeapons(const std::vector<BattleItem*> &itemList)\n{\n\t// let's try to load this weapon, whether we equip it or not.\n\tfor (BattleItem* i : itemList)\n\t{\n\t\tif (i->isWeaponWithAmmo() &&\n\t\t\t!i->haveAllAmmo() &&\n\t\t\t!i->getRules()->isFixed())\n\t\t{\n\t\t\tfor (BattleItem* j : itemList)\n\t\t\t{\n\t\t\t\tif (j->getSlot() == _inventorySlotGround && i->setAmmoPreMission(j))\n\t\t\t\t{\n\t\t\t\t\tif (i->haveAllAmmo())\n\t\t\t\t\t{\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Generates a map (set of tiles) for a new battlescape game.\n * @param script the script to use to build the map.\n * @param customUfoName custom UFO name to use for the dummy/blank 'addUFO' mapscript command.\n */\nvoid BattlescapeGenerator::generateMap(const std::vector<MapScript*> *script, const std::string &customUfoName, const RuleStartingCondition* startingCondition)\n{\n\t_backupInventoryTiles.clear(); // just in case\n\n\t// reset ambient sound\n\t_save->setAmbientSound(Mod::NO_SOUND);\n\t_save->setAmbienceRandom({});\n\n\t// set our ambient sound\n\tif (_terrain->getAmbience() != Mod::NO_SOUND)\n\t{\n\t\t_save->setAmbientSound(_terrain->getAmbience());\n\t}\n\telse\n\t{\n\t\t_save->setAmbienceRandom(_terrain->getAmbienceRandom());\n\t\t_save->setMinAmbienceRandomDelay(_terrain->getMinAmbienceRandomDelay());\n\t\t_save->setMaxAmbienceRandomDelay(_terrain->getMaxAmbienceRandomDelay());\n\t\t_save->resetCurrentAmbienceDelay();\n\t}\n\t_save->setAmbientVolume(_terrain->getAmbientVolume());\n\n\t// set up our map generation vars\n\t_dummy = new MapBlock(\"dummy\");\n\n\tinit(true);\n\n\tMapBlock* craftMap = 0;\n\tstd::vector<MapBlock*> ufoMaps;\n\n\tint mapDataSetIDOffset = 0;\n\tint craftDataSetIDOffset = 0;\n\n\t// create an array to track command success/failure\n\tstd::map<int, bool> conditionals;\n\n\t// Load in the default terrain data\n\tfor (auto* mds : *_terrain->getMapDataSets())\n\t{\n\t\tmds->loadData(_game->getMod()->getMCDPatch(mds->getName()));\n\t\t_save->getMapDataSets()->push_back(mds);\n\t\tmapDataSetIDOffset++;\n\t}\n\n\t_loadedTerrains[_terrain] = 0;\n\n\tRuleTerrain* ufoTerrain = 0;\n\tstd::string consolidatedUfoType;\n\t// lets generate the map now and store it inside the tile objects\n\n\t// determine globe terrain from globe texture\n\t_globeTerrain = _terrain;\n\tif (_globeTexture && _craft)\n\t{\n\t\t// TODO (cosmetic): multiple attempts (e.g. several attacks on the same alien base) may generate different terrains from the same globe texture\n\t\tauto* tmpTerrain  = _game->getMod()->getTerrain(_globeTexture->getRandomTerrain(_craft), false);\n\t\tif (tmpTerrain)\n\t\t{\n\t\t\t_globeTerrain = tmpTerrain;\n\t\t}\n\t}\n\n\t// this mission type is \"hard-coded\" in terms of map layout\n\tuint64_t seed = RNG::getSeed();\n\t_baseTerrain = _terrain;\n\tif (_save->getMissionType() == \"STR_BASE_DEFENSE\")\n\t{\n\t\tif (_mod->getBaseDefenseMapFromLocation() == 1)\n\t\t{\n\t\t\tTarget *target = _base;\n\n\t\t\t// Set RNG to make base generation dependent on base position\n\t\t\tdouble baseLon = target->getLongitude();\n\t\t\tdouble baseLat = target->getLatitude();\n\t\t\tif (baseLon == 0)\n\t\t\t{\n\t\t\t\tbaseLon = 1.0;\n\t\t\t}\n\t\t\tif (baseLat == 0)\n\t\t\t{\n\t\t\t\tbaseLat = 1.0;\n\t\t\t}\n\t\t\tuint64_t baseSeed = baseLon * baseLat * 1e6;\n\t\t\tRNG::setSeed(baseSeed);\n\n\t\t\t_baseTerrain = _game->getMod()->getTerrain(_globeTexture->getRandomBaseTerrain(target), true);\n\t\t\tgenerateBaseMap();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tgenerateBaseMap();\n\t\t}\n\t}\n\n\t//process script\n\tfor (auto* command : *script)\n\t{\n\t\tif (command->getLabel() > 0 && conditionals.find(command->getLabel()) != conditionals.end())\n\t\t{\n\t\t\tthrow Exception(\"Map generator encountered an error: multiple commands are sharing the same label.\");\n\t\t}\n\t\tbool &success = conditionals[command->getLabel()] = false;\n\n\n\t\t// if this command runs conditionally on the failures or successes of previous commands\n\t\tif (!command->getConditionals()->empty())\n\t\t{\n\t\t\tbool execute = true;\n\t\t\t// compare the corresponding entries in the success/failure vector\n\t\t\tfor (int condition : *command->getConditionals())\n\t\t\t{\n\t\t\t\t// positive numbers indicate conditional on success, negative means conditional on failure\n\t\t\t\t// ie: [1, -2] means this command only runs if command 1 succeeded and command 2 failed.\n\t\t\t\tif (conditionals.find(std::abs(condition)) != conditionals.end())\n\t\t\t\t{\n\t\t\t\t\tif ((condition > 0 && !conditionals[condition]) || (condition < 0 && conditionals[std::abs(condition)]))\n\t\t\t\t\t{\n\t\t\t\t\t\texecute = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tthrow Exception(\"Map generator encountered an error: conditional command expected a label that did not exist before this command.\");\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!execute)\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\t// if this command runs conditionally based on deployed craft's groups\n\t\tif (_craftDeployed && _craftRules)\n\t\t{\n\t\t\tif (!command->getCraftGroups().empty())\n\t\t\t{\n\t\t\t\tbool execute = false;\n\t\t\t\t// compare the corresponding entries in the craft rules vector\n\t\t\t\tfor (int grp : command->getCraftGroups())\n\t\t\t\t{\n\t\t\t\t\tif (std::find(_craftRules->getGroups().begin(), _craftRules->getGroups().end(), grp) != _craftRules->getGroups().end())\n\t\t\t\t\t{\n\t\t\t\t\t\texecute = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!execute)\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// if there's a chance a command won't execute by design, take that into account here.\n\t\tif (RNG::percent(command->getChancesOfExecution()))\n\t\t{\n\t\t\t// initialize the block selection arrays\n\t\t\tcommand->init();\n\n\t\t\t// each command can be attempted multiple times, as randomization within the rects may occur\n\t\t\tfor (int j = 0; j < command->getExecutions(); ++j)\n\t\t\t{\n\t\t\t\t_ufoDeployed = false; // reset EACH time\n\t\t\t\t_alternateTerrain = nullptr; // reset\n\n\t\t\t\tint x, y;\n\t\t\t\tMapBlock *block = 0;\n\n\t\t\t\t// Check if the command has vertical levels\n\t\t\t\t_verticalLevels.clear();\n\t\t\t\tbool doLevels = populateVerticalLevels(command);\n\t\t\t\tauto currentLevel = _verticalLevels.begin();\n\t\t\t\t// Special case among verticalLevels, we want to add the blocks using the \"line\" level, not the ground or the first level\n\t\t\t\tif (doLevels && command->getType() == MSC_ADDLINE)\n\t\t\t\t{\n\t\t\t\t\tfor ( ; currentLevel != _verticalLevels.end(); ++currentLevel)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (currentLevel->levelType == VLT_LINE)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// How did you pass the populateVerticalLevels validation???\n\t\t\t\t\tif (currentLevel == _verticalLevels.end())\n\t\t\t\t\t{\n\t\t\t\t\t\tthrow Exception(\"Map generator encountered an error: An addLine command with verticalLevels doesn't contain a level for the line.\");\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Variable for holding positions of blocks added for use in loading vertical levels\n\t\t\t\t_placedBlockRects.clear();\n\n\t\t\t\tRuleTerrain *terrain = _terrain;\n\t\t\t\tif (!command->getRandomAlternateTerrain().empty())\n\t\t\t\t{\n\t\t\t\t\tsize_t pick = RNG::generate(0, command->getRandomAlternateTerrain().size() - 1);\n\t\t\t\t\tterrain = pickTerrain(command->getRandomAlternateTerrain().at(pick));\n\t\t\t\t}\n\t\t\t\t_alternateTerrain = terrain; // backup for later use\n\n\t\t\t\tif (doLevels)\n\t\t\t\t{\n\t\t\t\t\t// initNextLevel() << returns next block for use\n\t\t\t\t\tcommand->initVerticalLevel(*currentLevel);\n\t\t\t\t\tterrain = currentLevel->levelTerrain == \"\" ? terrain : pickTerrain(currentLevel->levelTerrain);\n\t\t\t\t}\n\n\t\t\t\t_markAsReinforcementsBlock = command->markAsReinforcementsBlock() ? 1 : 0;\n\n\t\t\t\tswitch (command->getType())\n\t\t\t\t{\n\t\t\t\tcase MSC_ADDBLOCK:\n\t\t\t\t\tblock = command->getNextBlock(terrain);\n\t\t\t\t\t// select an X and Y position from within the rects, using an even distribution\n\t\t\t\t\tif (block && selectPosition(command->getRects(), x, y, block->getSizeX(), block->getSizeY()))\n\t\t\t\t\t{\n\t\t\t\t\t\tbool blockAdded = addBlock(x, y, block, terrain);\n\t\t\t\t\t\tsuccess = blockAdded || success;\n\n\t\t\t\t\t\tif (blockAdded && doLevels)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tSDL_Rect blockRect;\n\t\t\t\t\t\t\tblockRect.x = x;\n\t\t\t\t\t\t\tblockRect.y = y;\n\t\t\t\t\t\t\tblockRect.w = block->getSizeX();\n\t\t\t\t\t\t\tblockRect.h = block->getSizeY();\n\t\t\t\t\t\t\t_placedBlockRects.push_back(blockRect);\n\n\t\t\t\t\t\t\tloadVerticalLevels(command);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\tcase MSC_ADDLINE:\n\t\t\t\t\tsuccess = addLine((MapDirection)(command->getDirection()), command->getRects(), terrain, command->getVerticalGroup(), command->getHorizontalGroup(), command->getCrossingGroup());\n\n\t\t\t\t\tif (doLevels && success)\n\t\t\t\t\t{\n\t\t\t\t\t\tloadVerticalLevels(command, true);\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\tcase MSC_ADDCRAFT:\n\t\t\t\t\tif (_craft)\n\t\t\t\t\t{\n\t\t\t\t\t\tconst RuleCraft *craftRulesOverride = _save->getMod()->getCraft(command->getCraftName());\n\t\t\t\t\t\tif (startingCondition)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcraftRulesOverride = startingCondition->getCraftReplacement(_craftRules, craftRulesOverride);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (craftRulesOverride != 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_craftRules = craftRulesOverride;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcraftMap = _craftRules->getBattlescapeTerrainData()->getRandomMapBlock(999, 999, 0, false);\n\t\t\t\t\t\tbool craftPlaced = addCraft(craftMap, command, _craftPos, terrain);\n\t\t\t\t\t\t// Note: if label != 0, we assume that this may actually fail and will be handled by subsequent command(s)\n\t\t\t\t\t\tif (!craftPlaced && command->getLabel() == 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tthrow Exception(\"Map generator encountered an error: Craft (MapBlock: \"\n\t\t\t\t\t\t\t\t+ craftMap->getName()\n\t\t\t\t\t\t\t\t+ \") could not be placed on the map. You may try turning on 'save scumming' to work around this issue.\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (craftPlaced)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// by default addCraft adds blocks from group 1.\n\t\t\t\t\t\t\t// this can be overwritten in the command by defining specific groups or blocks\n\t\t\t\t\t\t\t// or this behaviour can be suppressed by leaving group 1 empty\n\t\t\t\t\t\t\t// this is intentional to allow for TFTD's cruise liners/etc\n\t\t\t\t\t\t\t// in this situation, you can end up with ANYTHING under your craft, so be careful\n\t\t\t\t\t\t\tfor (x = _craftPos.x; x < _craftPos.x + _craftPos.w; ++x)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tfor (y = _craftPos.y; y < _craftPos.y + _craftPos.h; ++y)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tif (_blocks[x][y])\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tbool visible = (_save->getMissionType() == \"STR_BASE_DEFENSE\");\n\n\t\t\t\t\t\t\t\t\t\tint terrainMapDataSetIDOffset = loadExtraTerrain(terrain);\n\t\t\t\t\t\t\t\t\t\tloadMAP(_blocks[x][y], x * 10, y * 10, 0, terrain, terrainMapDataSetIDOffset, visible);\n\n\t\t\t\t\t\t\t\t\t\tif (doLevels)\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tSDL_Rect blockRect;\n\t\t\t\t\t\t\t\t\t\t\tblockRect.x = x;\n\t\t\t\t\t\t\t\t\t\t\tblockRect.y = y;\n\t\t\t\t\t\t\t\t\t\t\tblockRect.w = _blocks[x][y]->getSizeX();\n\t\t\t\t\t\t\t\t\t\t\tblockRect.h = _blocks[x][y]->getSizeY();\n\t\t\t\t\t\t\t\t\t\t\t_placedBlockRects.push_back(blockRect);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (doLevels)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tloadVerticalLevels(command, true, craftMap);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t_craftDeployed = true;\n\t\t\t\t\t\t\tsuccess = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase MSC_ADDUFO:\n\t\t\t\t\t// as above, note that the craft and the ufo will never be allowed to overlap.\n\t\t\t\t\t// significant difference here is that we accept a UFOName string here to choose the UFO map\n\t\t\t\t\t// and we store the UFO positions in a vector, which we iterate later when actually loading the\n\t\t\t\t\t// map and route data. this makes it possible to add multiple UFOs to a single map\n\t\t\t\t\t// IMPORTANTLY: all the UFOs must use _exactly_ the same MCD set.\n\t\t\t\t\t// this is fine for most UFOs but it does mean small scouts can't be combined with larger ones\n\t\t\t\t\t// unless some major alterations are done to the MCD sets and maps themselves beforehand\n\t\t\t\t\t// this is because serializing all the MCDs is an implementational nightmare from my perspective,\n\t\t\t\t\t// and modders can take care of all that manually on their end.\n\t\t\t\t\tif (_game->getMod()->getUfo(command->getUFOName()))\n\t\t\t\t\t{\n\t\t\t\t\t\tufoTerrain = _game->getMod()->getUfo(command->getUFOName())->getBattlescapeTerrainData();\n\t\t\t\t\t\tconsolidatedUfoType = command->getUFOName();\n\t\t\t\t\t}\n\t\t\t\t\telse if (_ufo)\n\t\t\t\t\t{\n\t\t\t\t\t\tufoTerrain = _ufo->getRules()->getBattlescapeTerrainData();\n\t\t\t\t\t\tconsolidatedUfoType = _ufo->getRules()->getType();\n\t\t\t\t\t}\n\t\t\t\t\telse if (!customUfoName.empty())\n\t\t\t\t\t{\n\t\t\t\t\t\tauto* customUfoRule = _game->getMod()->getUfo(customUfoName, true); // crash if it doesn't exist, let the modder know what's going on\n\t\t\t\t\t\tufoTerrain = customUfoRule->getBattlescapeTerrainData();\n\t\t\t\t\t\tconsolidatedUfoType = customUfoName;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (ufoTerrain)\n\t\t\t\t\t{\n\t\t\t\t\t\tMapBlock *ufoMap = ufoTerrain->getRandomMapBlock(999, 999, 0, false);\n\t\t\t\t\t\tSDL_Rect ufoPosTemp;\n\t\t\t\t\t\tbool ufoPlaced = addCraft(ufoMap, command, ufoPosTemp, terrain);\n\t\t\t\t\t\t// Note: if label != 0, we assume that this may actually fail and will be handled by subsequent command(s)\n\t\t\t\t\t\tif (!ufoPlaced && command->getLabel() == 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (command->canBeSkipped())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tLog(LOG_INFO) << \"Map generator encountered a recoverable problem: UFO (MapBlock: \" << ufoMap->getName() << \") could not be placed on the map. Command skipped.\";\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tthrow Exception(\"Map generator encountered an error: UFO (MapBlock: \"\n\t\t\t\t\t\t\t\t\t+ ufoMap->getName()\n\t\t\t\t\t\t\t\t\t+ \") could not be placed on the map. You may try turning on 'save scumming' to work around this issue.\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (ufoPlaced)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_ufoPos.push_back(ufoPosTemp);\n\t\t\t\t\t\t\tufoMaps.push_back(ufoMap);\n\t\t\t\t\t\t\tfor (x = ufoPosTemp.x; x < ufoPosTemp.x + ufoPosTemp.w; ++x)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tfor (y = ufoPosTemp.y; y < ufoPosTemp.y + ufoPosTemp.h; ++y)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tif (_blocks[x][y])\n\t\t\t\t\t\t\t\t\t{\n\n\t\t\t\t\t\t\t\t\t\tbool visible = (_save->getMissionType() == \"STR_BASE_DEFENSE\");\n\n\t\t\t\t\t\t\t\t\t\tint terrainMapDataSetIDOffset = loadExtraTerrain(terrain);\n\t\t\t\t\t\t\t\t\t\tloadMAP(_blocks[x][y], x * 10, y * 10, 0, terrain, terrainMapDataSetIDOffset, visible);\n\n\t\t\t\t\t\t\t\t\t\tif (doLevels)\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tSDL_Rect blockRect;\n\t\t\t\t\t\t\t\t\t\t\tblockRect.x = x;\n\t\t\t\t\t\t\t\t\t\t\tblockRect.y = y;\n\t\t\t\t\t\t\t\t\t\t\tblockRect.w = _blocks[x][y]->getSizeX();\n\t\t\t\t\t\t\t\t\t\t\tblockRect.h = _blocks[x][y]->getSizeY();\n\t\t\t\t\t\t\t\t\t\t\t_placedBlockRects.push_back(blockRect);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t_ufoZ.push_back(0);\n\n\t\t\t\t\t\t\tif (doLevels)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tloadVerticalLevels(command, true, ufoMap);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t_ufoDeployed = true;\n\t\t\t\t\t\t\tsuccess = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase MSC_DIGTUNNEL:\n\t\t\t\t\tdrillModules(command->getTunnelData(), command->getRects(), command->getDirection(), terrain);\n\t\t\t\t\tsuccess = true; // this command is fail-proof\n\t\t\t\t\tbreak;\n\t\t\t\tcase MSC_FILLAREA:\n\t\t\t\t\tblock = command->getNextBlock(terrain);\n\t\t\t\t\twhile (block)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (selectPosition(command->getRects(), x, y, block->getSizeX(), block->getSizeY()))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// fill area will succeed if even one block is added\n\t\t\t\t\t\t\tsuccess = addBlock(x, y, block, terrain) || success;\n\n\t\t\t\t\t\t\t// Add to a list of rects for fill area to be able to do verticalLevels\n\t\t\t\t\t\t\tSDL_Rect blockRect;\n\t\t\t\t\t\t\tblockRect.x = x;\n\t\t\t\t\t\t\tblockRect.y = y;\n\t\t\t\t\t\t\tblockRect.w = block->getSizeX();\n\t\t\t\t\t\t\tblockRect.h = block->getSizeY();\n\t\t\t\t\t\t\t_placedBlockRects.push_back(blockRect);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tblock = command->getNextBlock(terrain);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Now load all the vertical levels\n\t\t\t\t\tif(doLevels && _placedBlockRects.size() != 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tloadVerticalLevels(command, true);\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\tcase MSC_CHECKBLOCK:\n\t\t\t\t\tfor (const auto* rect : *command->getRects())\n\t\t\t\t\t{\n\t\t\t\t\t\tif (success) break; // loop finished\n\t\t\t\t\t\tfor (x = rect->x; x != rect->x + rect->w && x != _mapsize_x / 10 && !success; ++x)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfor (y = rect->y; y != rect->y + rect->h && y != _mapsize_y / 10 && !success; ++y)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (!command->getGroups()->empty())\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tfor (int grp : *command->getGroups())\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tif (success) break; // loop finished\n\t\t\t\t\t\t\t\t\t\tsuccess = _blocks[x][y] && _blocks[x][y]->isInGroup(grp);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse if (!command->getBlocks()->empty())\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tfor (int blck : *command->getBlocks())\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tif (success) break; // loop finished\n\t\t\t\t\t\t\t\t\t\tif ((size_t)(blck) < terrain->getMapBlocks()->size())\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tsuccess = (_blocks[x][y] == terrain->getMapBlocks()->at(blck));\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t// wildcard, we don't care what block it is, we just wanna know if there's a block here\n\t\t\t\t\t\t\t\t\tsuccess = (_blocks[x][y] != 0);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase MSC_REMOVE:\n\t\t\t\t\tsuccess = removeBlocks(command);\n\t\t\t\t\tbreak;\n\t\t\t\tcase MSC_RESIZE:\n\t\t\t\t\tif (_save->getMissionType() == \"STR_BASE_DEFENSE\")\n\t\t\t\t\t{\n\t\t\t\t\t\tthrow Exception(\"Map Generator encountered an error: Base defense map cannot be resized.\");\n\t\t\t\t\t}\n\t\t\t\t\tif (_blocksToDo < (_mapsize_x / 10) * (_mapsize_y / 10))\n\t\t\t\t\t{\n\t\t\t\t\t\tthrow Exception(\"Map Generator encountered an error: One does not simply resize the map after adding blocks.\");\n\t\t\t\t\t}\n\n\t\t\t\t\tif (command->getSizeX() > 0 && command->getSizeX() != _mapsize_x / 10)\n\t\t\t\t\t{\n\t\t\t\t\t\t_mapsize_x = command->getSizeX() * 10;\n\t\t\t\t\t}\n\t\t\t\t\tif (command->getSizeY() > 0 && command->getSizeY() != _mapsize_y / 10)\n\t\t\t\t\t{\n\t\t\t\t\t\t_mapsize_y = command->getSizeY() * 10;\n\t\t\t\t\t}\n\t\t\t\t\tif (command->getSizeZ() > 0 && command->getSizeZ() != _mapsize_z)\n\t\t\t\t\t{\n\t\t\t\t\t\t_mapsize_z = command->getSizeZ();\n\t\t\t\t\t}\n\t\t\t\t\tinit(false);\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (_blocksToDo)\n\t{\n\t\tthrow Exception(\"Map failed to fully generate.\");\n\t}\n\n\t// Put the map data set ID offset to the end of the terrains in the save since we may have loaded more than the default\n\tmapDataSetIDOffset = _save->getMapDataSets()->size();\n\n\tloadNodes();\n\n\tif (!ufoMaps.empty() && ufoTerrain)\n\t{\n\t\tfor (auto* mds : *ufoTerrain->getMapDataSets())\n\t\t{\n\t\t\tmds->loadData(_game->getMod()->getMCDPatch(mds->getName()));\n\t\t\t_save->getMapDataSets()->push_back(mds);\n\t\t\tcraftDataSetIDOffset++;\n\t\t}\n\n\t\tfor (size_t i = 0; i < ufoMaps.size(); ++i)\n\t\t{\n\t\t\tloadMAP(ufoMaps[i], _ufoPos[i].x * 10, _ufoPos[i].y * 10, _ufoZ[i], ufoTerrain, mapDataSetIDOffset, false, false, i);\n\t\t\tloadRMP(ufoMaps[i], _ufoPos[i].x * 10, _ufoPos[i].y * 10, _ufoZ[i], Node::UFOSEGMENT);\n\t\t\tfor (int j = 0; j < ufoMaps[i]->getSizeX() / 10; ++j)\n\t\t\t{\n\t\t\t\tfor (int k = 0; k < ufoMaps[i]->getSizeY() / 10; k++)\n\t\t\t\t{\n\t\t\t\t\t_save->getFlattenedMapTerrainNames()[_ufoPos[i].x + j][_ufoPos[i].y + k] = consolidatedUfoType; // UFO name, not terrain name\n\t\t\t\t\t_save->getFlattenedMapBlockNames()[_ufoPos[i].x + j][_ufoPos[i].y + k] = ufoMaps[i]->getName();\n\t\t\t\t\t_segments[_ufoPos[i].x + j][_ufoPos[i].y + k] = Node::UFOSEGMENT;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (craftMap)\n\t{\n\t\t_craftRules->getBattlescapeTerrainData()->refreshMapDataSets(_craft->getSkinIndex(), _game->getMod()); // change skin if needed\n\t\tfor (auto* mds : *_craftRules->getBattlescapeTerrainData()->getMapDataSets())\n\t\t{\n\t\t\tmds->loadData(_game->getMod()->getMCDPatch(mds->getName()));\n\t\t\t_save->getMapDataSets()->push_back(mds);\n\t\t}\n\t\tloadMAP(craftMap, _craftPos.x * 10, _craftPos.y * 10, _craftZ, _craftRules->getBattlescapeTerrainData(), mapDataSetIDOffset + craftDataSetIDOffset, _craftRules->isMapVisible(), true);\n\t\tloadRMP(craftMap, _craftPos.x * 10, _craftPos.y * 10, _craftZ, Node::CRAFTSEGMENT);\n\t\tfor (int i = 0; i < craftMap->getSizeX() / 10; ++i)\n\t\t{\n\t\t\tfor (int j = 0; j < craftMap->getSizeY() / 10; j++)\n\t\t\t{\n\t\t\t\t_save->getFlattenedMapTerrainNames()[_craftPos.x + i][_craftPos.y + j] = _craftRules->getType(); // craft name, not terrain name\n\t\t\t\t_save->getFlattenedMapBlockNames()[_craftPos.x + i][_craftPos.y + j] = craftMap->getName();\n\t\t\t\t_segments[_craftPos.x + i][_craftPos.y + j] = Node::CRAFTSEGMENT;\n\t\t\t}\n\t\t}\n\t\tfor (int i = (_craftPos.x * 10) - 1; i <= (_craftPos.x * 10) + craftMap->getSizeX(); ++i)\n\t\t{\n\t\t\tfor (int j = (_craftPos.y * 10) - 1; j <= (_craftPos.y * 10) + craftMap->getSizeY(); j++)\n\t\t\t{\n\t\t\t\tfor (int k = _mapsize_z - 1; k >= _craftZ; --k)\n\t\t\t\t{\n\t\t\t\t\tif (_save->getTile(Position(i, j, k)))\n\t\t\t\t\t{\n\t\t\t\t\t\t_save->getTile(Position(i, j, k))->setDiscovered(_craftRules->isMapVisible(), O_FLOOR);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tdelete _dummy;\n\n\t// special hacks to fill in empty floors on level 0\n\tfor (int x = 0; x < _mapsize_x; ++x)\n\t{\n\t\tfor (int y = 0; y < _mapsize_y; ++y)\n\t\t{\n\t\t\tif (_save->getTile(Position(x, y, 0))->getMapData(O_FLOOR) == 0)\n\t\t\t{\n\t\t\t\t_save->getTile(Position(x, y, 0))->setMapData(MapDataSet::getScorchedEarthTile(), 1, 0, O_FLOOR);\n\t\t\t}\n\t\t}\n\t}\n\n\tattachNodeLinks();\n\n\tif (_save->getMissionType() == \"STR_BASE_DEFENSE\" && _mod->getBaseDefenseMapFromLocation() == 1)\n\t{\n\t\tRNG::setSeed(seed);\n\t}\n}\n\n/**\n * Generates a map based on the base's layout.\n * this doesn't drill or fill with dirt, the script must do that.\n */\nvoid BattlescapeGenerator::generateBaseMap()\n{\n\t// add modules based on the base's layout\n\tfor (const auto* fac : *_base->getFacilities())\n\t{\n\t\tif (fac->isBuiltOrHadPreviousFacility())\n\t\t{\n\t\t\tint num = 0;\n\t\t\tint xLimit = fac->getX() + fac->getRules()->getSizeX() -1;\n\t\t\tint yLimit = fac->getY() + fac->getRules()->getSizeY() -1;\n\n\t\t\t// Do we use the normal method for placing items on the ground or an explicit definition?\n\t\t\tbool storageCheckerboard = (fac->getRules()->getStorageTiles().size() == 0);\n\n\t\t\t// If the facility has a verticalLevels ruleset definition, load it as if it's an addBlock command\n\t\t\tif (fac->getRules()->getVerticalLevels().size() != 0)\n\t\t\t{\n\t\t\t\t// Create a mapscript command to handle picking blocks for the vertical level\n\t\t\t\tMapScript command;\n\n\t\t\t\t// Get the vertical levels from the facility ruleset and create a list according to map size\n\t\t\t\t_verticalLevels.clear();\n\t\t\t\t_verticalLevels = fac->getRules()->getVerticalLevels();\n\t\t\t\tcommand.setVerticalLevels(_verticalLevels, fac->getRules()->getSizeX(), fac->getRules()->getSizeY());\n\t\t\t\tpopulateVerticalLevels(&command);\n\n\t\t\t\tauto currentLevel = _verticalLevels.begin();\n\t\t\t\tcommand.initVerticalLevel(*currentLevel);\n\t\t\t\tRuleTerrain *terrain;\n\t\t\t\tterrain = currentLevel->levelTerrain == \"\" ? _terrain : pickTerrain(currentLevel->levelTerrain);\n\t\t\t\t_placedBlockRects.clear();\n\n\t\t\t\tMapBlock *block = command.getNextBlock(terrain);\n\t\t\t\tif (block)\n\t\t\t\t{\n\t\t\t\t\tint x = fac->getX();\n\t\t\t\t\tint y = fac->getY();\n\t\t\t\t\taddBlock(x, y, block, terrain);\n\n\t\t\t\t\tSDL_Rect blockRect;\n\t\t\t\t\tblockRect.x = x;\n\t\t\t\t\tblockRect.y = y;\n\t\t\t\t\tblockRect.w = block->getSizeX();\n\t\t\t\t\tblockRect.h = block->getSizeY();\n\t\t\t\t\t_placedBlockRects.push_back(blockRect);\n\n\t\t\t\t\t_alternateTerrain = nullptr; // not used in this case\n\t\t\t\t\tloadVerticalLevels(&command);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tthrow Exception(\"Map generator encountered an error: facility \" + fac->getRules()->getType() + \" has no block on first verticalLevel.\");\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (int y = fac->getY(); y <= yLimit; ++y)\n\t\t\t{\n\t\t\t\tfor (int x = fac->getX(); x <= xLimit; ++x)\n\t\t\t\t{\n\t\t\t\t\t// lots of crazy stuff here, which is for the hangars (or other large base facilities one may create)\n\t\t\t\t\t// TODO: clean this mess up, make the mapNames a vector in the base module defs\n\t\t\t\t\t// also figure out how to do the terrain sets on a per-block basis.\n\n\t\t\t\t\t// Only use the mapName if we didn't load the map by verticalLevels\n\t\t\t\t\tif (fac->getRules()->getVerticalLevels().size() == 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tstd::string mapname = fac->getRules()->getMapName();\n\t\t\t\t\t\tstd::ostringstream newname;\n\t\t\t\t\t\tnewname << mapname.substr(0, mapname.size()-2); // strip of last 2 digits\n\t\t\t\t\t\tint mapnum = atoi(mapname.substr(mapname.size()-2, 2).c_str()); // get number\n\t\t\t\t\t\tmapnum += num;\n\t\t\t\t\t\tif (mapnum < 10) newname << 0;\n\t\t\t\t\t\tnewname << mapnum;\n\t\t\t\t\t\tauto* block = _terrain->getMapBlock(newname.str());\n\t\t\t\t\t\tif (!block)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tthrow Exception(\"Map generator encountered an error: map block \"\n\t\t\t\t\t\t\t\t+ newname.str()\n\t\t\t\t\t\t\t\t+ \" is not defined in terrain \"\n\t\t\t\t\t\t\t\t+ _terrain->getName()\n\t\t\t\t\t\t\t\t+ \".\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\taddBlock(x, y, block, _terrain);\n\t\t\t\t\t}\n\t\t\t\t\t_drillMap[x][y] = MD_NONE;\n\t\t\t\t\tnum++;\n\t\t\t\t\tif (fac->getRules()->getStorage() > 0 && storageCheckerboard)\n\t\t\t\t\t{\n\t\t\t\t\t\tint groundLevel;\n\t\t\t\t\t\tfor (groundLevel = _mapsize_z - 1; groundLevel >= 0; --groundLevel)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (!_save->getTile(Position(x * 10, y * 10, groundLevel))->hasNoFloor(0))\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// general stores - there is where the items are put\n\t\t\t\t\t\tfor (int k = x * 10; k != (x + 1) * 10; ++k)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfor (int l = y * 10; l != (y + 1) * 10; ++l)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// we only want every other tile, giving us a \"checkerboard\" pattern\n\t\t\t\t\t\t\t\tif ((k + l) % 2 == 0)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tTile *t = _save->getTile(Position(k, l, groundLevel));\n\t\t\t\t\t\t\t\t\tTile *tEast = _save->getTile(Position(k + 1, l, groundLevel));\n\t\t\t\t\t\t\t\t\tTile *tSouth = _save->getTile(Position(k, l + 1, groundLevel));\n\t\t\t\t\t\t\t\t\tif (t && t->getMapData(O_FLOOR) && !t->getMapData(O_OBJECT) &&\n\t\t\t\t\t\t\t\t\t\ttEast && !tEast->getMapData(O_WESTWALL) &&\n\t\t\t\t\t\t\t\t\t\ttSouth && !tSouth->getMapData(O_NORTHWALL))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t_save->getStorageSpace().push_back(Position(k, l, groundLevel));\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// let's put the inventory tile on the lower floor, just to be safe.\n\t\t\t\t\t\tif (!_craftInventoryTile)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_craftInventoryTile = _save->getTile(Position((x * 10) + 5, (y * 10) + 5, groundLevel - 1));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Extended handling for placing storage tiles by ruleset definition\n\t\t\tif (fac->getRules()->getStorage() > 0 && !storageCheckerboard)\n\t\t\t{\n\t\t\t\tint x = fac->getX();\n\t\t\t\tint y = fac->getY();\n\t\t\t\tbool validPos = false;\n\t\t\t\tfor (const auto& pos : fac->getRules()->getStorageTiles())\n\t\t\t\t{\n\t\t\t\t\tif (pos == TileEngine::invalid)\n\t\t\t\t\t{\n\t\t\t\t\t\tvalidPos = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (pos.x < 0 || pos.x / 10 > fac->getRules()->getSizeX()\n\t\t\t\t\t\t|| pos.y < 0 || pos.y / 10 > fac->getRules()->getSizeY()\n\t\t\t\t\t\t|| pos.z < 0 || pos.z > _mapsize_z)\n\t\t\t\t\t{\n\t\t\t\t\t\tLog(LOG_ERROR) << \"Tile position \" << pos << \" is outside the facility \" << fac->getRules()->getType() << \", skipping placing items there.\";\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tPosition tilePos = Position((x * 10) + pos.x, (y * 10) + pos.y, pos.z);\n\t\t\t\t\tif (!_save->getTile(tilePos))\n\t\t\t\t\t{\n\t\t\t\t\t\tLog(LOG_ERROR) << \"Tile position \" << tilePos << \", from the facility \" << fac->getRules()->getType() << \", is outside the map; skipping placing items there.\";\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tvalidPos = true;\n\t\t\t\t\t_save->getStorageSpace().push_back(tilePos);\n\n\t\t\t\t\tif (!_craftInventoryTile) // just to be safe, make sure we have a craft inventory tile\n\t\t\t\t\t{\n\t\t\t\t\t\t_craftInventoryTile = _save->getTile(tilePos);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Crash gracefully with some information before we spawn a map where no items could be placed.\n\t\t\t\tif (!validPos)\n\t\t\t\t{\n\t\t\t\t\tthrow Exception(\"Could not place items on given tiles in storage facility \" + fac->getRules()->getType());\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (int x = fac->getX(); x <= xLimit; ++x)\n\t\t\t{\n\t\t\t\t_drillMap[x][yLimit] = MD_VERTICAL;\n\t\t\t}\n\t\t\tfor (int y = fac->getY(); y <= yLimit; ++y)\n\t\t\t{\n\t\t\t\t_drillMap[xLimit][y] = MD_HORIZONTAL;\n\t\t\t}\n\t\t\t_drillMap[xLimit][yLimit] = MD_BOTH;\n\t\t}\n\t}\n\t_save->calculateModuleMap();\n\n}\n\n/**\n * Populates the verticalLevels vector\n * @param command the mapscript command from which to get the size\n * @return whether or not the command has levels\n */\nbool BattlescapeGenerator::populateVerticalLevels(MapScript *command)\n{\n\t_verticalLevels.clear();\n\n\tif (command->getVerticalLevels().size() == 0)\n\t{\n\t\treturn false;\n\t}\n\n\t// First check for ground level\n\tbool levelFound = false;\n\tfor (auto& verticalLevel : command->getVerticalLevels())\n\t{\n\t\tif (verticalLevel.levelType == VLT_GROUND)\n\t\t{\n\t\t\tif (!levelFound)\n\t\t\t{\n\t\t\t\t_verticalLevels.push_back(verticalLevel);\n\t\t\t\t// For consistency with the standard addCraft/addUFO commands, set default groups to 1 (LZ) if not defined\n\t\t\t\tif ((command->getType() == MSC_ADDCRAFT || command->getType() == MSC_ADDUFO) && verticalLevel.levelGroups.size() == 0)\n\t\t\t\t{\n\t\t\t\t\t_verticalLevels.back().levelGroups.push_back(1);\n\t\t\t\t}\n\t\t\t\tlevelFound = true;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tLog(LOG_WARNING) << \"Map generator encountered an error: a 'ground' verticalLevel can only be used once per command.\";\n\t\t\t}\n\t\t}\n\t}\n\n\t// Next, find the \"filler\" levels\n\tlevelFound = false;\n\tfor (auto& verticalLevel : command->getVerticalLevels())\n\t{\n\t\tswitch (verticalLevel.levelType)\n\t\t{\n\t\t\tcase VLT_CRAFT:\n\t\t\t\tif ((command->getType() == MSC_ADDCRAFT || command->getType() == MSC_ADDUFO) && !levelFound)\n\t\t\t\t{\n\t\t\t\t\t_verticalLevels.push_back(verticalLevel);\n\t\t\t\t\t_verticalLevels.back().maxRepeats = 1;\n\t\t\t\t\tlevelFound = true;\n\t\t\t\t}\n\t\t\t\telse if (command->getType() == MSC_ADDCRAFT || command->getType() == MSC_ADDUFO)\n\t\t\t\t{\n\t\t\t\t\tLog(LOG_WARNING) << \"Map generator encountered an error: a 'craft' verticalLevel can only be used once per command.\";\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tLog(LOG_WARNING) << \"Map generator encountered an error: a 'craft' verticalLevel is only valid for addCraft and addUFO commands, skipping level.\";\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\n\t\t\tcase VLT_LINE:\n\t\t\t\tif (command->getType() == MSC_ADDLINE && !levelFound)\n\t\t\t\t{\n\t\t\t\t\t_verticalLevels.push_back(verticalLevel);\n\t\t\t\t\tlevelFound = true;\n\t\t\t\t}\n\t\t\t\telse if (command->getType() == MSC_ADDLINE)\n\t\t\t\t{\n\t\t\t\t\tLog(LOG_WARNING) << \"Map generator encountered an error: a 'line' verticalLevel can only be used once per command.\";\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tLog(LOG_WARNING) << \"Map generator encountered an error: a 'line' verticalLevel is only valid for addLine commands, skipping level.\";\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\n\t\t\tcase VLT_MIDDLE:\n\t\t\tcase VLT_EMPTY:\n\t\t\tcase VLT_DECORATION:\n\t\t\t\t_verticalLevels.push_back(verticalLevel);\n\n\t\t\t\tbreak;\n\n\t\t\tdefault :\n\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t// Finally, add the \"ceiling\" level\n\tlevelFound = false;\n\tfor (auto& verticalLevel : command->getVerticalLevels())\n\t{\n\t\tif (verticalLevel.levelType == VLT_CEILING)\n\t\t{\n\t\t\tif (!levelFound)\n\t\t\t{\n\t\t\t\t_verticalLevels.push_back(verticalLevel);\n\t\t\t\tlevelFound = true;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tLog(LOG_WARNING) << \"Map generator encountered an error: a 'ceiling' verticalLevel can only be used once per command.\";\n\t\t\t}\n\t\t}\n\t}\n\n\treturn true;\n}\n\n/**\n * Gets a terrain from a terrain name for a command or vertical level, validates if there is no terrain name\n * @param terrainName the name of the terrain to look for.\n * @return pointer to the terrain\n */\nRuleTerrain* BattlescapeGenerator::pickTerrain(std::string terrainName)\n{\n\tRuleTerrain *terrain;\n\n\tif (terrainName == \"baseTerrain\")\n\t{\n\t\tterrain = _baseTerrain;\n\t}\n\telse if (terrainName == \"globeTerrain\")\n\t{\n\t\tterrain = _globeTerrain;\n\t}\n\telse if (terrainName != \"\")\n\t{\n\t\t//get the terrain according to the string name\n\t\tterrain = _game->getMod()->getTerrain(terrainName);\n\t\tif (!terrain)\n\t\t{\n\t\t\t// make sure we get a terrain, and put an error in the log, continuing with generation\n\t\t\tLog(LOG_ERROR) << \"Map generator could not find alternate terrain \" << terrainName << \", proceeding with terrain from alienDeployments or Geoscape texture.\";\n\t\t\tterrain = _terrain;\n\t\t}\n\t}\n\telse\n\t{\n\t\t// no alternate terrain in command or verticalLevel, default to deployment terrain\n\t\tterrain = _terrain;\n\t}\n\n\treturn terrain;\n}\n\n/**\n * Loads maps from verticalLevels within a mapscript command\n * @param command the mapScript command.\n * @param terrain pointer to the terrain for the the mapScript command\n */\nvoid BattlescapeGenerator::loadVerticalLevels(MapScript *command, bool repopulateLevels, MapBlock *craftMap)\n{\n\tfor (const auto& rect : _placedBlockRects)\n\t{\n\t\t// If we're using a command that adds multiple blocks per single execution, we need to make sure the _verticalLevels vector gets repopulated after each iteration.\n\t\tif (repopulateLevels)\n\t\t{\n\t\t\tpopulateVerticalLevels(command);\n\t\t}\n\n\t\tint x = rect.x;\n\t\tint y = rect.y;\n\t\tMapBlock *block = _blocks[x][y];\n\n\t\tauto currentLevel = _verticalLevels.begin();\n\t\tRuleTerrain *terrain = _terrain;\n\t\tif (_alternateTerrain)\n\t\t{\n\t\t\tterrain = _alternateTerrain; // alternate terrain defined on the map script command\n\t\t}\n\n\t\tint zOffset = 0;\n\t\tint zLevelsLeft = command->getSizeZ();\n\t\tif (zLevelsLeft < 1)\n\t\t{\n\t\t\tzLevelsLeft = _mapsize_z;\n\t\t}\n\t\telse if (zLevelsLeft > _mapsize_z)\n\t\t{\n\t\t\tLog(LOG_WARNING) << \"Battlescape Generator has encountered an error: a mapscript command has height \" << command->getSizeZ() << \" while the map is only \" << _mapsize_z << \" tiles tall.\";\n\t\t\tLog(LOG_WARNING) << \"Reducing command size to map height\";\n\n\t\t\tzLevelsLeft = _mapsize_z;\n\t\t}\n\n\t\t// Special handling for addline command: we need to check if the line is on ground level. If not, we need to re-load the z = 0 level and load the line later\n\t\tMapBlock *lineBlock = 0;\n\t\tif (command->getType() == MSC_ADDLINE && currentLevel->levelType != VLT_LINE)\n\t\t{\n\t\t\tlineBlock = _blocks[x][y];\n\n\t\t\tclearModule(x*10, y*10, 10, 10);\n\t\t\t++_blocksToDo; // this will be re-added with addBlock\n\t\t\tcommand->initVerticalLevel(*currentLevel);\n\t\t\tRuleTerrain *levelTerrain = pickTerrain(currentLevel->levelTerrain);\n\t\t\tblock = command->getNextBlock(levelTerrain);\n\n\t\t\tif (block)\n\t\t\t{\n\t\t\t\taddBlock(x, y, block, levelTerrain);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tLog(LOG_WARNING) << \"Battlescape Generator has encountered an error: an addLine mapscript command has vertical levels but a mapblock for the ground level could not be loaded.\";\n\t\t\t}\n\t\t}\n\n\t\t// For the first level, \"ground\" or \"line\" should only done once, so remove it. Otherwise, just advance the iterator\n\t\tint z = currentLevel->levelSizeZ == -1 ? block->getSizeZ() : currentLevel->levelSizeZ;\n\t\tzOffset += z;\n\t\tzLevelsLeft -= z;\n\t\tif (currentLevel->levelType == VLT_GROUND || currentLevel->levelType == VLT_LINE)\n\t\t{\n\t\t\tcurrentLevel = _verticalLevels.erase(currentLevel);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t++currentLevel;\n\t\t}\n\n\t\t// Reserve the space for the ceiling level\n\t\tMapBlock *ceilingBlock = 0;\n\t\tRuleTerrain *ceilingTerrain = terrain;\n\t\tif (_verticalLevels.back().levelType == VLT_CEILING)\n\t\t{\n\t\t\tcommand->initVerticalLevel(_verticalLevels.back());\n\t\t\tceilingTerrain = _verticalLevels.back().levelTerrain == \"\" ? terrain : pickTerrain(_verticalLevels.back().levelTerrain);\n\t\t\tceilingBlock = command->getNextBlock(ceilingTerrain);\n\t\t\tif (ceilingBlock)\n\t\t\t{\n\t\t\t\tz = _verticalLevels.back().levelSizeZ == -1 ? ceilingBlock->getSizeZ() : _verticalLevels.back().levelSizeZ;\n\t\t\t\tif (z > zLevelsLeft)\n\t\t\t\t{\n\t\t\t\t\tceilingBlock = 0;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tzLevelsLeft -= z;\n\t\t\t\t\t_verticalLevels.pop_back();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Now load the rest of the levels\n\t\tint tries = 0;\n\t\tint maxTries = 20;\n\n\t\t// If a addLine command for some reason can't fit in the line itself, note this in the log for the modder to fix\n\t\tbool lineAdded = false;\n\n\t\t// Loop over the \"filling\" levels to build up the maps placed at this location\n\t\twhile (_verticalLevels.size() > 0 && zLevelsLeft > 0 && tries <= maxTries)\n\t\t{\n\t\t\t// Since our goal is filling the space between the bottom and the max height, we repeat the list of levels until we're done\n\t\t\tif (currentLevel == _verticalLevels.end())\n\t\t\t\tcurrentLevel = _verticalLevels.begin();\n\n\t\t\t// Determine what we're doing with the current level\n\t\t\tRuleTerrain *levelTerrain = terrain;\n\t\t\tblock = 0;\n\t\t\tz = 0;\n\n\t\t\tswitch (currentLevel->levelType)\n\t\t\t{\n\t\t\t\tcase VLT_CRAFT:\n\t\t\t\t\t// Set the craft height offset if necessary\n\t\t\t\t\tif (command->getType() == MSC_ADDCRAFT && zOffset > _craftZ)\n\t\t\t\t\t{\n\t\t\t\t\t\t_craftZ = zOffset;\n\t\t\t\t\t}\n\t\t\t\t\telse if (command->getType() == MSC_ADDUFO && zOffset > _ufoZ.back())\n\t\t\t\t\t{\n\t\t\t\t\t\t_ufoZ.back() = zOffset;\n\t\t\t\t\t}\n\n\t\t\t\t\tz = currentLevel->levelSizeZ == -1 ? craftMap->getSizeZ() : currentLevel->levelSizeZ;\n\n\t\t\t\t\tif (z > zLevelsLeft)\n\t\t\t\t\t{\n\t\t\t\t\t\tthrow Exception(\"Map Generator has encountered an error: craft or ufo map\"\n\t\t\t\t\t\t\t+ craftMap->getName()\n\t\t\t\t\t\t\t+ \"could not be placed because either the map is too tall or the verticalLevels place it too high.\");\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase VLT_EMPTY:\n\t\t\t\t\t// We're just bumping the zOffset upwards\n\t\t\t\t\tz = currentLevel->levelSizeZ == -1 ? 1 : currentLevel->levelSizeZ;\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\t// All other level types: we're loading a map block\n\t\t\t\t\tif (currentLevel->levelTerrain != \"\")\n\t\t\t\t\t{\n\t\t\t\t\t\tlevelTerrain = pickTerrain(currentLevel->levelTerrain);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (command->getType() == MSC_ADDLINE && currentLevel->levelType == VLT_LINE && lineBlock)\n\t\t\t\t\t{\n\t\t\t\t\t\t// We're re-loading a block for the addLine command\n\t\t\t\t\t\tblock = lineBlock;\n\t\t\t\t\t\tlineAdded = true;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// We're loading a new block\n\t\t\t\t\t\tcommand->initVerticalLevel(*currentLevel);\n\t\t\t\t\t\tblock = command->getNextBlock(levelTerrain);\n\t\t\t\t\t}\n\n\t\t\t\t\tif(block)\n\t\t\t\t\t{\n\t\t\t\t\t\tz = currentLevel->levelSizeZ == -1 ? block->getSizeZ() : currentLevel->levelSizeZ;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t++tries; // we failed to find an appropriate block for a command that must explicitly load one, so don't try too hard to keep finding one\n\t\t\t\t\t\tif(tries > maxTries)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tLog(LOG_WARNING) << \"Battlescape Generator has encountered an error: a mapscript command or base facility with vertical levels cannot find a map block with the right size/terrain/groups. The modder may want to check that the specified terrain or vertical level size/groups is correct.\";\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// Apply the current level if it fits before we reach the max height, otherwise try again with the current level\n\t\t\tif (z <= zLevelsLeft)\n\t\t\t{\n\t\t\t\t// Load a map if that's what we're doing\n\t\t\t\tif (block)\n\t\t\t\t{\n\t\t\t\t\tbool visible = (_save->getMissionType() == \"STR_BASE_DEFENSE\");\n\n\t\t\t\t\tint terrainMapDataSetIDOffset = loadExtraTerrain(levelTerrain);\n\t\t\t\t\tloadMAP(block, x * 10, y * 10, zOffset, levelTerrain, terrainMapDataSetIDOffset, visible);\n\t\t\t\t\t_verticalLevelSegments.push_back(std::make_pair(block, Position(x, y, zOffset)));\n\t\t\t\t}\n\n\t\t\t\tzLevelsLeft -= z;\n\t\t\t\tzOffset += z;\n\n\t\t\t\t// Move to the next level in the list and remove the current one if we've used it up while looping\n\t\t\t\t--currentLevel->maxRepeats;\n\t\t\t\tif (currentLevel->maxRepeats == 0)\n\t\t\t\t{\n\t\t\t\t\tcurrentLevel = _verticalLevels.erase(currentLevel);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t++currentLevel;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t++tries;\n\t\t\t}\n\t\t}\n\n\t\tif (command->getType() == MSC_ADDLINE && !lineAdded)\n\t\t{\n\t\t\tLog(LOG_WARNING) << \"Battlescape Generator has encountered an error: a addLine mapscript command with vertical levels did not load the line itself. The modder may want to reduce the number of levels before the line.\";\n\t\t}\n\n\t\t// Now we can finally load the ceiling level\n\t\tif (ceilingBlock)\n\t\t{\n\t\t\tbool visible = (_save->getMissionType() == \"STR_BASE_DEFENSE\");\n\n\t\t\tint terrainMapDataSetIDOffset = loadExtraTerrain(ceilingTerrain);\n\t\t\tloadMAP(ceilingBlock, x * 10, y * 10, zOffset, ceilingTerrain, terrainMapDataSetIDOffset, visible);\n\t\t\t_verticalLevelSegments.push_back(std::make_pair(ceilingBlock, Position(x, y, zOffset)));\n\t\t}\n\t}\n}\n\n/**\n * Clears a module from the map.\n * @param x the x offset.\n * @param y the y offset.\n * @param sizeX how far along the x axis to clear.\n * @param sizeY how far along the y axis to clear.\n */\nvoid BattlescapeGenerator::clearModule(int x, int y, int sizeX, int sizeY)\n{\n\tfor (int z = 0; z != _mapsize_z; ++z)\n\t{\n\t\tfor (int dx = x; dx != x + sizeX; ++dx)\n\t\t{\n\t\t\tfor (int dy = y; dy != y + sizeY; ++dy)\n\t\t\t{\n\t\t\t\tTile *tile = _save->getTile(Position(dx,dy,z));\n\t\t\t\tfor (int i = O_FLOOR; i < O_MAX; i++)\n\t\t\t\t\ttile->setMapData(0, -1, -1, (TilePart)i);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Loads all the nodes from the map modules.\n */\nvoid BattlescapeGenerator::loadNodes()\n{\n\tint segment = 0;\n\n\t// Loading nodes for ground-level maps\n\tfor (int itY = 0; itY < (_mapsize_y / 10); itY++)\n\t{\n\t\tfor (int itX = 0; itX < (_mapsize_x / 10); itX++)\n\t\t{\n\t\t\t_segments[itX][itY] = segment;\n\t\t\tif (_blocks[itX][itY] != 0 && _blocks[itX][itY] != _dummy)\n\t\t\t{\n\t\t\t\tif (!(_blocks[itX][itY]->isInGroup(MT_LANDINGZONE) && _landingzone[itX][itY] && _craftZ == 0))\n\t\t\t\t{\n\t\t\t\t\tloadRMP(_blocks[itX][itY], itX * 10, itY * 10, 0, segment++);\n\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t// Loading nodes for verticalLevels maps\n\tfor (const auto& pair : _verticalLevelSegments)\n\t{\n\t\tloadRMP(pair.first, pair.second.x * 10, pair.second.y * 10, pair.second.z, segment++);\n\t}\n}\n\n/**\n * Attaches all the nodes together in an intricate web of lies.\n */\nvoid BattlescapeGenerator::attachNodeLinks()\n{\n\t// Since standard vanilla maps are added first, the cutoff between nodes in\n\t// _segments and those loaded in verticalLevels is the largest value of _segements\n\tint lastSegmentsIndex = 0;\n\tfor (int itY = 0; itY < (_mapsize_y / 10); itY++)\n\t{\n\t\tfor (int itX = 0; itX < (_mapsize_x / 10); itX++)\n\t\t{\n\t\t\tif(_segments[itX][itY] > lastSegmentsIndex)\n\t\t\t{\n\t\t\t\tlastSegmentsIndex = _segments[itX][itY];\n\t\t\t}\n\t\t}\n\t}\n\n\t// First pass is original code, connects all ground-level maps\n\tfor (std::vector<Node*>::iterator i = _save->getNodes()->begin(); i != _save->getNodes()->end(); ++i)\n\t{\n\t\tNode* node = (*i);\n\n\t\tif (node->isDummy())\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Did we load this node from a verticalLevel?\n\t\t// If so, it's time to go to the next loop!\n\t\tif (node->getSegment() > lastSegmentsIndex)\n\t\t{\n\t\t\tbreak;\n\t\t}\n\n\t\tint segmentX = node->getPosition().x / 10;\n\t\tint segmentY = node->getPosition().y / 10;\n\t\tint neighbourSegments[4];\n\t\tint neighbourDirections[4] = { -2, -3, -4, -5 };\n\t\tint neighbourDirectionsInverted[4] = { -4, -5, -2, -3 };\n\n\t\tif (segmentX == (_mapsize_x / 10)-1)\n\t\t\tneighbourSegments[0] = -1;\n\t\telse\n\t\t\tneighbourSegments[0] = _segments[segmentX+1][segmentY];\n\t\tif (segmentY == (_mapsize_y / 10)-1)\n\t\t\tneighbourSegments[1] = -1;\n\t\telse\n\t\t\tneighbourSegments[1] = _segments[segmentX][segmentY+1];\n\t\tif (segmentX == 0)\n\t\t\tneighbourSegments[2] = -1;\n\t\telse\n\t\t\tneighbourSegments[2] = _segments[segmentX-1][segmentY];\n\t\tif (segmentY == 0)\n\t\t\tneighbourSegments[3] = -1;\n\t\telse\n\t\t\tneighbourSegments[3] = _segments[segmentX][segmentY-1];\n\n\t\tfor (std::vector<int>::iterator j = node->getNodeLinks()->begin(); j != node->getNodeLinks()->end(); ++j )\n\t\t{\n\t\t\tfor (int n = 0; n < 4; n++)\n\t\t\t{\n\t\t\t\tif (*j == neighbourDirections[n])\n\t\t\t\t{\n\t\t\t\t\tfor (std::vector<Node*>::iterator k = _save->getNodes()->begin(); k != _save->getNodes()->end(); ++k)\n\t\t\t\t\t{\n\t\t\t\t\t\tif ((*k)->isDummy())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ((*k)->getSegment() == neighbourSegments[n])\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfor (std::vector<int>::iterator l = (*k)->getNodeLinks()->begin(); l != (*k)->getNodeLinks()->end(); ++l )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (*l == neighbourDirectionsInverted[n])\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t*l = node->getID();\n\t\t\t\t\t\t\t\t\t*j = (*k)->getID();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Second pass to obfuscate even further by adding an additional layer of connections\n\t// Goes through _segmentsVertical to connect nodes from verticalLevels that would\n\t// be missed in the original code\n\tfor (std::vector<Node*>::iterator i = _save->getNodes()->begin(); i != _save->getNodes()->end(); ++i)\n\t{\n\t\tNode* node = (*i);\n\n\t\t// All the nodes before lastSegmentsIndex were already connected\n\t\t// verticalLevels start for segment values greater than lastSegmentsIndex\n\t\tif (node->isDummy() || node->getSegment() > lastSegmentsIndex)\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\n\t\tint nodeX = node->getPosition().x / 10;\n\t\tint nodeY = node->getPosition().y / 10;\n\t\tint nodeZ = node->getPosition().z;\n\t\tstd::map<int, std::vector<int> > neighbourDirections;\n\n\t\t// Make a list of directions in which to look for neighbouring nodes\n\t\tif (nodeX != 0)\n\t\t{\n\t\t\tstd::vector<int> tempVector;\n\t\t\ttempVector.push_back(-1);\n\t\t\ttempVector.push_back(0);\n\t\t\ttempVector.push_back(0);\n\t\t\tneighbourDirections[-5] = tempVector;\n\t\t}\n\t\tif (nodeX != (_mapsize_x / 10)-1)\n\t\t{\n\t\t\tstd::vector<int> tempVector;\n\t\t\ttempVector.push_back(1);\n\t\t\ttempVector.push_back(0);\n\t\t\ttempVector.push_back(0);\n\t\t\tneighbourDirections[-3] = tempVector;\n\t\t}\n\t\tif (nodeY != 0)\n\t\t{\n\t\t\tstd::vector<int> tempVector;\n\t\t\ttempVector.push_back(0);\n\t\t\ttempVector.push_back(-1);\n\t\t\ttempVector.push_back(0);\n\t\t\tneighbourDirections[-2] = tempVector;\n\t\t}\n\t\tif (nodeY != (_mapsize_y / 10)-1)\n\t\t{\n\t\t\tstd::vector<int> tempVector;\n\t\t\ttempVector.push_back(0);\n\t\t\ttempVector.push_back(1);\n\t\t\ttempVector.push_back(0);\n\t\t\tneighbourDirections[-4] = tempVector;\n\t\t}\n\t\tif (nodeZ != 0)\n\t\t{\n\t\t\tstd::vector<int> tempVector;\n\t\t\ttempVector.push_back(0);\n\t\t\ttempVector.push_back(0);\n\t\t\ttempVector.push_back(-1);\n\t\t\tneighbourDirections[-6] = tempVector;\n\t\t}\n\t\tif (nodeZ != _mapsize_z)\n\t\t{\n\t\t\tstd::vector<int> tempVector;\n\t\t\ttempVector.push_back(0);\n\t\t\ttempVector.push_back(0);\n\t\t\ttempVector.push_back(1);\n\t\t\tneighbourDirections[-1] = tempVector;\n\t\t}\n\n\t\tstd::map<int, int> neighbourDirectionsInverted;\n\t\tneighbourDirectionsInverted[-2] = -4;\n\t\tneighbourDirectionsInverted[-3] = -5;\n\t\tneighbourDirectionsInverted[-4] = -2;\n\t\tneighbourDirectionsInverted[-5] = -3;\n\n\t\tfor (std::map<int, std::vector<int> >::iterator j = neighbourDirections.begin(); j != neighbourDirections.end(); j++)\n\t\t{\n\t\t\tstd::vector<int>::iterator linkDirection;\n\t\t\tlinkDirection = std::find(node->getNodeLinks()->begin(), node->getNodeLinks()->end(), (*j).first);\n\t\t\tif (linkDirection != node->getNodeLinks()->end() || (*j).first == -1 || (*j).first == -6)\n\t\t\t{\n\t\t\t\tfor (std::vector<Node*>::iterator k = _save->getNodes()->begin(); k != _save->getNodes()->end(); ++k)\n\t\t\t\t{\n\t\t\t\t\tif ((*k)->isDummy())\n\t\t\t\t\t{\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tstd::vector<int> currentDirection = (*j).second;\n\t\t\t\t\tint linkX = (*k)->getPosition().x / 10 - currentDirection[0];\n\t\t\t\t\tint linkY = (*k)->getPosition().y / 10 - currentDirection[1];\n\t\t\t\t\tint linkZ = (*k)->getPosition().z - currentDirection[2];\n\n\t\t\t\t\tif (linkX == nodeX && linkY == nodeY && linkZ == nodeZ)\n\t\t\t\t\t{\n\t\t\t\t\t\tfor (std::vector<int>::iterator l = (*k)->getNodeLinks()->begin(); l != (*k)->getNodeLinks()->end(); ++l )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tstd::map<int, int>::iterator invertedDirection = neighbourDirectionsInverted.find((*l));\n\t\t\t\t\t\t\tif (invertedDirection != neighbourDirectionsInverted.end() && !((*j).first == -1 || (*j).first == -6) && (*invertedDirection).second == *linkDirection)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t*l = node->getID();\n\t\t\t\t\t\t\t\t*linkDirection = (*k)->getID();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif ((*j).first == -1 || (*j).first == -6)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// Create a vertical link between nodes only if the nodes are within an x+y distance of 3 and the link isn't already there\n\t\t\t\t\t\t\tint xDistance = abs(node->getPosition().x - (*k)->getPosition().x);\n\t\t\t\t\t\t\tint yDistance = abs(node->getPosition().y - (*k)->getPosition().y);\n\t\t\t\t\t\t\tint xyDistance = xDistance + yDistance;\n\t\t\t\t\t\t\tstd::vector<int>::iterator l;\n\t\t\t\t\t\t\tl = std::find((*k)->getNodeLinks()->begin(), (*k)->getNodeLinks()->end(), node->getID());\n\t\t\t\t\t\t\tif (xyDistance <= 3 && l == (*k)->getNodeLinks()->end())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t(*k)->getNodeLinks()->push_back(node->getID());\n\t\t\t\t\t\t\t\tnode->getNodeLinks()->push_back((*k)->getID());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Selects a position for a map block.\n * @param rects the positions to select from, none meaning the whole map.\n * @param X the x position for the block gets stored in this variable.\n * @param Y the y position for the block gets stored in this variable.\n * @param sizeX the x size of the block we want to add.\n * @param sizeY the y size of the block we want to add.\n * @return if a valid position was selected or not.\n */\nbool BattlescapeGenerator::selectPosition(const std::vector<SDL_Rect *> *rects, int &X, int &Y, int sizeX, int sizeY)\n{\n\tstd::vector<SDL_Rect*> available;\n\tstd::vector<std::pair<int, int> > valid;\n\tSDL_Rect wholeMap;\n\twholeMap.x = 0;\n\twholeMap.y = 0;\n\twholeMap.w = (_mapsize_x / 10);\n\twholeMap.h = (_mapsize_y / 10);\n\tsizeX = (sizeX / 10);\n\tsizeY = (sizeY / 10);\n\tif (rects->empty())\n\t{\n\t\tavailable.push_back(&wholeMap);\n\t}\n\telse\n\t{\n\t\tavailable = *rects;\n\t}\n\tfor (const auto* rect : available)\n\t{\n\t\tif (sizeX > rect->w || sizeY > rect->h)\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\t\tfor (int x = rect->x; x + sizeX <= rect->x + rect->w && x + sizeX <= wholeMap.w; ++x)\n\t\t{\n\t\t\tfor (int y = rect->y; y + sizeY <= rect->y + rect->h && y + sizeY <= wholeMap.h; ++y)\n\t\t\t{\n\t\t\t\tif (std::find(valid.begin(), valid.end(), std::make_pair(x,y)) == valid.end())\n\t\t\t\t{\n\t\t\t\t\tbool add = true;\n\t\t\t\t\tfor (int xCheck = x; xCheck != x + sizeX; ++xCheck)\n\t\t\t\t\t{\n\t\t\t\t\t\tfor (int yCheck = y; yCheck != y + sizeY; ++yCheck)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (_blocks[xCheck][yCheck])\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tadd = false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (add)\n\t\t\t\t\t{\n\t\t\t\t\t\tvalid.push_back(std::make_pair(x,y));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif (valid.empty())\n\t{\n\t\treturn false;\n\t}\n\tstd::pair<int, int> selection = valid.at(RNG::generate(0, valid.size() - 1));\n\tX = selection.first;\n\tY = selection.second;\n\treturn true;\n}\n\n/**\n * Adds a craft (or UFO) to the map, and tries to add a landing zone type block underneath it.\n * @param craftMap the map for the craft in question.\n * @param command the script command to pull info from.\n * @param craftPos the position of the craft is stored here.\n * @return if the craft was placed or not.\n */\nbool BattlescapeGenerator::addCraft(MapBlock *craftMap, MapScript *command, SDL_Rect &craftPos, RuleTerrain *terrain)\n{\n\tcraftPos.w = craftMap->getSizeX();\n\tcraftPos.h = craftMap->getSizeY();\n\tbool placed = false;\n\tint x, y;\n\n\tplaced = selectPosition(command->getRects(), x, y, craftPos.w, craftPos.h);\n\t// if ok, allocate it\n\tif (placed)\n\t{\n\t\tif (_verticalLevels.size() != 0)\n\t\t{\n\t\t\tcommand->initVerticalLevel(_verticalLevels.front());\n\t\t}\n\n\t\tcraftPos.x = x;\n\t\tcraftPos.y = y;\n\t\tcraftPos.w /= 10;\n\t\tcraftPos.h /= 10;\n\t\tfor (x = 0; x < craftPos.w; ++x)\n\t\t{\n\t\t\tfor (y = 0; y < craftPos.h; ++y)\n\t\t\t{\n\t\t\t\t_landingzone[craftPos.x + x][craftPos.y + y] = true;\n\t\t\t\tMapBlock *block = command->getNextBlock(terrain);\n\t\t\t\tif (block && !_blocks[craftPos.x + x][craftPos.y + y])\n\t\t\t\t{\n\t\t\t\t\t_save->getReinforcementsBlocks()[craftPos.x + x][craftPos.y + y] = _markAsReinforcementsBlock;\n\t\t\t\t\t_save->getFlattenedMapTerrainNames()[craftPos.x + x][craftPos.y + y] = terrain->getName();\n\t\t\t\t\t_save->getFlattenedMapBlockNames()[craftPos.x + x][craftPos.y + y] = block->getName();\n\t\t\t\t\t_blocks[craftPos.x + x][craftPos.y + y] = block;\n\t\t\t\t\t_blocksToDo--;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn placed;\n}\n\n/**\n * draws a line along the map either horizontally, vertically or both.\n * @param direction the direction to draw the line\n * @param rects the positions to allow the line to be drawn in.\n * @return if the blocks were added or not.\n */\nbool BattlescapeGenerator::addLine(MapDirection direction, const std::vector<SDL_Rect*> *rects, RuleTerrain *terrain, int verticalGroup, int horizontalGroup, int crossingGroup)\n{\n\tif (direction == MD_BOTH)\n\t{\n\t\tif (addLine(MD_VERTICAL, rects, terrain, verticalGroup, horizontalGroup, crossingGroup))\n\t\t{\n\t\t\taddLine(MD_HORIZONTAL, rects, terrain, verticalGroup, horizontalGroup, crossingGroup);\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tint tries = 0;\n\tbool placed = false;\n\n\tint roadX, roadY = 0;\n\tint *iteratorValue = &roadX;\n\tint comparator = verticalGroup;\n\tint typeToAdd = horizontalGroup;\n\tint limit = _mapsize_x / 10;\n\tif (direction == MD_VERTICAL)\n\t{\n\t\titeratorValue = &roadY;\n\t\tcomparator = horizontalGroup;\n\t\ttypeToAdd = verticalGroup;\n\t\tlimit = _mapsize_y / 10;\n\t}\n\twhile (!placed)\n\t{\n\t\tplaced = selectPosition(rects, roadX, roadY, 10, 10);\n\t\tfor (*iteratorValue = 0; *iteratorValue < limit; *iteratorValue += 1)\n\t\t{\n\t\t\tif (placed && _blocks[roadX][roadY] != 0 && _blocks[roadX][roadY]->isInGroup(comparator) == false)\n\t\t\t{\n\t\t\t\tplaced = false;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (tries++ > 20)\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\t*iteratorValue = 0;\n\twhile (*iteratorValue < limit)\n\t{\n\t\tif (_blocks[roadX][roadY] == 0)\n\t\t{\n\t\t\tMapBlock* randomMapBlock1 = terrain->getRandomMapBlock(10, 10, typeToAdd);\n\t\t\tif (!randomMapBlock1)\n\t\t\t{\n\t\t\t\tstd::ostringstream ss1;\n\t\t\t\tss1 << \"Map script command `addLine` failed (1). Terrain \" + terrain->getName() + \", block group \" << typeToAdd << \", script \" << _save->getLastUsedMapScript();\n\t\t\t\tthrow Exception(ss1.str());\n\t\t\t}\n\t\t\taddBlock(roadX, roadY, randomMapBlock1, terrain);\n\n\t\t\tSDL_Rect blockRect;\n\t\t\tblockRect.x = roadX;\n\t\t\tblockRect.y = roadY;\n\t\t\tblockRect.w = 1;\n\t\t\tblockRect.h = 1;\n\n\t\t\t// Only add unique positions for loading vertical levels\n\t\t\tauto it = std::find_if(_placedBlockRects.begin(), _placedBlockRects.end(), [&](const SDL_Rect& rect) { return rect.x == roadX && rect.y == roadY; });\n\t\t\tif (it == _placedBlockRects.end())\n\t\t\t{\n\t\t\t\t_placedBlockRects.push_back(blockRect);\n\t\t\t}\n\t\t}\n\t\telse if (_blocks[roadX][roadY]->isInGroup(comparator))\n\t\t{\n\t\t\tMapBlock* randomMapBlock2 = terrain->getRandomMapBlock(10, 10, crossingGroup);\n\t\t\tif (!randomMapBlock2)\n\t\t\t{\n\t\t\t\tstd::ostringstream ss2;\n\t\t\t\tss2 << \"Map script command `addLine` failed (2). Terrain \" + terrain->getName() + \", block group \" << crossingGroup << \", script \" << _save->getLastUsedMapScript();\n\t\t\t\tthrow Exception(ss2.str());\n\t\t\t}\n\t\t\t_blocks[roadX][roadY] = randomMapBlock2;\n\t\t\tclearModule(roadX * 10, roadY * 10, 10, 10);\n\t\t\tint terrainMapDataSetIDOffset = loadExtraTerrain(terrain);\n\t\t\tloadMAP(_blocks[roadX][roadY], roadX * 10, roadY * 10, 0, terrain, terrainMapDataSetIDOffset);\n\n\t\t\tSDL_Rect blockRect;\n\t\t\tblockRect.x = roadX;\n\t\t\tblockRect.y = roadY;\n\t\t\tblockRect.w = 1;\n\t\t\tblockRect.h = 1;\n\n\t\t\t// Only add unique positions for loading vertical levels\n\t\t\tauto it = std::find_if(_placedBlockRects.begin(), _placedBlockRects.end(), [&](const SDL_Rect& rect) { return rect.x == roadX && rect.y == roadY; });\n\t\t\tif (it == _placedBlockRects.end())\n\t\t\t{\n\t\t\t\t_placedBlockRects.push_back(blockRect);\n\t\t\t}\n\t\t}\n\t\t*iteratorValue += 1;\n\t}\n\treturn true;\n}\n\n/**\n * Adds a single block to the map.\n * @param x the x position to add the block\n * @param y the y position to add the block\n * @param z the z offset for loading the map\n * @param block the block to add.\n * @param terrain pointer to the terrain for the block.\n * @return if the block was added or not.\n */\nbool BattlescapeGenerator::addBlock(int x, int y, MapBlock *block, RuleTerrain* terrain)\n{\n\tint xSize = (block->getSizeX() - 1) / 10;\n\tint ySize = (block->getSizeY() - 1) / 10;\n\n\tfor (int xd = 0; xd <= xSize; ++xd)\n\t{\n\t\tfor (int yd = 0; yd != ySize; ++yd)\n\t\t{\n\t\t\tif (_blocks[x + xd][y + yd])\n\t\t\t\treturn false;\n\t\t}\n\t}\n\n\tfor (int xd = 0; xd <= xSize; ++xd)\n\t{\n\t\tfor (int yd = 0; yd <= ySize; ++yd)\n\t\t{\n\t\t\t_save->getReinforcementsBlocks()[x + xd][y + yd] = _markAsReinforcementsBlock;\n\t\t\t_save->getFlattenedMapTerrainNames()[x + xd][y + yd] = terrain->getName();\n\t\t\t_save->getFlattenedMapBlockNames()[x + xd][y + yd] = block->getName();\n\t\t\t_blocks[x + xd][y + yd] = _dummy;\n\t\t\t_blocksToDo--;\n\t\t}\n\t}\n\n\t// mark the south edge of the block for drilling\n\tfor (int xd = 0; xd <= xSize; ++xd)\n\t{\n\t\t_drillMap[x+xd][y + ySize] = MD_VERTICAL;\n\t}\n\t// then the east edge\n\tfor (int yd = 0; yd <= ySize; ++yd)\n\t{\n\t\t_drillMap[x + xSize][y+yd] = MD_HORIZONTAL;\n\t}\n\t// then the far corner gets marked for both\n\t// this also marks 1x1 modules\n\t_drillMap[x + xSize][y+ySize] = MD_BOTH;\n\n\t_blocks[x][y] = block;\n\tbool visible = (_save->getMissionType() == \"STR_BASE_DEFENSE\"); // yes, i'm hard coding these, big whoop, wanna fight about it?\n\n\tint terrainMapDataSetIDOffset = loadExtraTerrain(terrain);\n\tloadMAP(_blocks[x][y], x * 10, y * 10, 0, terrain, terrainMapDataSetIDOffset, visible);\n\n\treturn true;\n}\n\n/**\n * Drills a tunnel between existing map modules.\n * note that this drills all modules currently on the map,\n * so it should take place BEFORE the dirt is added in base defenses.\n * @param data the wall replacements and level to dig on.\n * @param rects the length/width of the tunnels themselves.\n * @param dir the direction to drill.\n * @param terrain which terrain to use for the wall replacements.\n */\nvoid BattlescapeGenerator::drillModules(TunnelData* data, const std::vector<SDL_Rect *> *rects, MapDirection dir, RuleTerrain *terrain)\n{\n\t// Make sure the terrain we're going to use for the replacements is loaded\n\tloadExtraTerrain(terrain);\n\n\tconst MCDReplacement *wWall = data->getMCDReplacement(\"westWall\");\n\tconst MCDReplacement *nWall = data->getMCDReplacement(\"northWall\");\n\tconst MCDReplacement *corner = data->getMCDReplacement(\"corner\");\n\tconst MCDReplacement *floor = data->getMCDReplacement(\"floor\");\n\tSDL_Rect rect;\n\trect.x = rect.y = rect.w = rect.h = 3;\n\tif (!rects->empty())\n\t{\n\t\trect = *rects->front();\n\t}\n\n\tfor (int i = 0; i < (_mapsize_x / 10); ++i)\n\t{\n\t\tfor (int j = 0; j < (_mapsize_y / 10); ++j)\n\t\t{\n\t\t\tif (_blocks[i][j] == 0)\n\t\t\t\tcontinue;\n\n\t\t\tMapData *md;\n\n\t\t\tif (dir != MD_VERTICAL)\n\t\t\t{\n\t\t\t\t// drill east\n\t\t\t\tif (i < (_mapsize_x / 10)-1 && (_drillMap[i][j] == MD_HORIZONTAL || _drillMap[i][j] == MD_BOTH) && _blocks[i+1][j] != 0)\n\t\t\t\t{\n\t\t\t\t\tTile *tile;\n\t\t\t\t\t// remove stuff\n\t\t\t\t\tfor (int k = rect.y; k != rect.y + rect.h; ++k)\n\t\t\t\t\t{\n\t\t\t\t\t\ttile = _save->getTile(Position((i*10)+9, (j*10)+k, data->level));\n\t\t\t\t\t\tif (tile)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttile->setMapData(0, -1, -1, O_WESTWALL);\n\t\t\t\t\t\t\ttile->setMapData(0, -1, -1, O_OBJECT);\n\t\t\t\t\t\t\tif (floor)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tmd = terrain->getMapDataSets()->at(floor->set)->getObject(floor->entry);\n\t\t\t\t\t\t\t\ttile->setMapData(md, floor->entry, floor->set, O_FLOOR);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\ttile = _save->getTile(Position((i+1)*10, (j*10)+k, data->level));\n\t\t\t\t\t\t\ttile->setMapData(0, -1, -1, O_WESTWALL);\n\t\t\t\t\t\t\tMapData* obj = tile->getMapData(O_OBJECT);\n\t\t\t\t\t\t\tif (obj && obj->getTUCost(MT_WALK) == 0)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttile->setMapData(0, -1, -1, O_OBJECT);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (nWall)\n\t\t\t\t\t{\n\t\t\t\t\t\tmd = terrain->getMapDataSets()->at(nWall->set)->getObject(nWall->entry);\n\t\t\t\t\t\ttile = _save->getTile(Position((i*10)+9, (j*10)+rect.y, data->level));\n\t\t\t\t\t\ttile->setMapData(md, nWall->entry, nWall->set, O_NORTHWALL);\n\t\t\t\t\t\ttile = _save->getTile(Position((i*10)+9, (j*10)+rect.y+rect.h, data->level));\n\t\t\t\t\t\ttile->setMapData(md, nWall->entry, nWall->set, O_NORTHWALL);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (corner)\n\t\t\t\t\t{\n\t\t\t\t\t\tmd = terrain->getMapDataSets()->at(corner->set)->getObject(corner->entry);\n\t\t\t\t\t\ttile = _save->getTile(Position((i+1)*10, (j*10)+rect.y, data->level));\n\t\t\t\t\t\tif (tile->getMapData(O_NORTHWALL) == 0)\n\t\t\t\t\t\t\ttile->setMapData(md, corner->entry, corner->set, O_NORTHWALL);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (dir != MD_HORIZONTAL)\n\t\t\t{\n\t\t\t\t// drill south\n\t\t\t\tif (j < (_mapsize_y / 10)-1 && (_drillMap[i][j] == MD_VERTICAL || _drillMap[i][j] == MD_BOTH) && _blocks[i][j+1] != 0)\n\t\t\t\t{\n\t\t\t\t\t// remove stuff\n\t\t\t\t\tfor (int k = rect.x; k != rect.x + rect.w; ++k)\n\t\t\t\t\t{\n\t\t\t\t\t\tTile * tile = _save->getTile(Position((i*10)+k, (j*10)+9, data->level));\n\t\t\t\t\t\tif (tile)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttile->setMapData(0, -1, -1, O_NORTHWALL);\n\t\t\t\t\t\t\ttile->setMapData(0, -1, -1, O_OBJECT);\n\t\t\t\t\t\t\tif (floor)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tmd = terrain->getMapDataSets()->at(floor->set)->getObject(floor->entry);\n\t\t\t\t\t\t\t\ttile->setMapData(md, floor->entry, floor->set, O_FLOOR);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\ttile = _save->getTile(Position((i*10)+k, (j+1)*10, data->level));\n\t\t\t\t\t\t\ttile->setMapData(0, -1, -1, O_NORTHWALL);\n\t\t\t\t\t\t\tMapData* obj = tile->getMapData(O_OBJECT);\n\t\t\t\t\t\t\tif (obj && obj->getTUCost(MT_WALK) == 0)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttile->setMapData(0, -1, -1, O_OBJECT);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (wWall)\n\t\t\t\t\t{\n\t\t\t\t\t\tmd = terrain->getMapDataSets()->at(wWall->set)->getObject(wWall->entry);\n\t\t\t\t\t\tTile *tile = _save->getTile(Position((i*10)+rect.x, (j*10)+9, data->level));\n\t\t\t\t\t\ttile->setMapData(md, wWall->entry, wWall->set, O_WESTWALL);\n\t\t\t\t\t\ttile = _save->getTile(Position((i*10)+rect.x+rect.w, (j*10)+9, data->level));\n\t\t\t\t\t\ttile->setMapData(md, wWall->entry, wWall->set, O_WESTWALL);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (corner)\n\t\t\t\t\t{\n\t\t\t\t\t\tmd = terrain->getMapDataSets()->at(corner->set)->getObject(corner->entry);\n\t\t\t\t\t\tTile *tile = _save->getTile(Position((i*10)+rect.x, (j+1)*10, data->level));\n\t\t\t\t\t\tif (tile->getMapData(O_WESTWALL) == 0)\n\t\t\t\t\t\t\ttile->setMapData(md, corner->entry, corner->set, O_WESTWALL);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Removes all blocks within a given set of rects, as defined in the command.\n * @param command contains all the info we need.\n * @return success of the removal.\n * @feel shame for having written this.\n */\nbool BattlescapeGenerator::removeBlocks(MapScript *command)\n{\n\tstd::vector<std::pair<int, int> > deleted;\n\tbool success = false;\n\n\tfor (const auto* rect : *command->getRects())\n\t{\n\t\tfor (int x = rect->x; x != rect->x + rect->w && x != _mapsize_x / 10; ++x)\n\t\t{\n\t\t\tfor (int y = rect->y; y != rect->y + rect->h && y != _mapsize_y / 10; ++y)\n\t\t\t{\n\t\t\t\tif (_blocks[x][y] != 0 && _blocks[x][y] != _dummy)\n\t\t\t\t{\n\t\t\t\t\tstd::pair<int, int> pos(x, y);\n\t\t\t\t\tif (!command->getGroups()->empty())\n\t\t\t\t\t{\n\t\t\t\t\t\tfor (int grp : *command->getGroups())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (_blocks[x][y]->isInGroup(grp))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// the deleted vector should only contain unique entries\n\t\t\t\t\t\t\t\tif (std::find(deleted.begin(), deleted.end(), pos) == deleted.end())\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tdeleted.push_back(pos);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse if (!command->getBlocks()->empty())\n\t\t\t\t\t{\n\t\t\t\t\t\tfor (int blck : *command->getBlocks())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif ((size_t)blck < _terrain->getMapBlocks()->size())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// the deleted vector should only contain unique entries\n\t\t\t\t\t\t\t\tif (std::find(deleted.begin(), deleted.end(), pos) == deleted.end())\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tdeleted.push_back(pos);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// the deleted vector should only contain unique entries\n\t\t\t\t\t\tif (std::find(deleted.begin(), deleted.end(), pos) == deleted.end())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tdeleted.push_back(pos);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tfor (const auto& pair : deleted)\n\t{\n\t\tint x = pair.first;\n\t\tint y = pair.second;\n\t\tclearModule(x * 10, y * 10, _blocks[x][y]->getSizeX(), _blocks[x][y]->getSizeY());\n\n\t\tint delx = (_blocks[x][y]->getSizeX() / 10);\n\t\tint dely = (_blocks[x][y]->getSizeY() / 10);\n\n\t\tfor (int dx = x; dx != x + delx; ++dx)\n\t\t{\n\t\t\tfor (int dy = y; dy != y + dely; ++dy)\n\t\t\t{\n\t\t\t\t_save->getReinforcementsBlocks()[dx][dy] = 0;\n\t\t\t\t_save->getFlattenedMapTerrainNames()[dx][dy] = \"\";\n\t\t\t\t_save->getFlattenedMapBlockNames()[dx][dy] = \"\";\n\t\t\t\t_blocks[dx][dy] = 0;\n\t\t\t\t_blocksToDo++;\n\n\t\t\t\t// Make sure vertical levels segment data is removed too\n\t\t\t\tauto it = _verticalLevelSegments.begin();\n\t\t\t\twhile (it != _verticalLevelSegments.end())\n\t\t\t\t{\n\t\t\t\t\tif (it->second.x == dx && it->second.y == dy)\n\t\t\t\t\t{\n\t\t\t\t\t\tit = _verticalLevelSegments.erase(it);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t++it;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// this command succeeds if even one block is removed.\n\t\tsuccess = true;\n\t}\n\treturn success;\n}\n\n/**\n * Sets the terrain to be used in battle generation.\n * @param terrain Pointer to the terrain rules.\n */\nvoid BattlescapeGenerator::setTerrain(RuleTerrain *terrain)\n{\n\t_terrain = terrain;\n}\n\n\n/**\n * Sets up the objectives for the map.\n * @param ruleDeploy the deployment data we're gleaning data from.\n */\nvoid BattlescapeGenerator::setupObjectives(const AlienDeployment *ruleDeploy)\n{\n\t// reset bug hunt mode (necessary for multi-stage missions)\n\t_save->setBughuntMode(false);\n\t// set global min turn\n\t_save->setBughuntMinTurn(_game->getMod()->getBughuntMinTurn());\n\t// set min turn override per deployment (if defined)\n\tif (ruleDeploy->getBughuntMinTurn() > 0)\n\t{\n\t\t_save->setBughuntMinTurn(ruleDeploy->getBughuntMinTurn());\n\t}\n\n\t// used for \"escort the VIPs\" and \"protect the VIPs\" missions\n\t_save->setVIPSurvivalPercentage(ruleDeploy->getVIPSurvivalPercentage());\n\t_save->setVIPEscapeType(ruleDeploy->getEscapeType());\n\n\tint targetType = ruleDeploy->getObjectiveType();\n\n\tif (targetType > -1)\n\t{\n\t\tint objectives = ruleDeploy->getObjectivesRequired();\n\t\tint actualCount = 0;\n\n\t\tfor (int i = 0; i < _save->getMapSizeXYZ(); ++i)\n\t\t{\n\t\t\tfor (int j = O_FLOOR; j < O_MAX; ++j)\n\t\t\t{\n\t\t\t\tTilePart tp = (TilePart)j;\n\t\t\t\tif (_save->getTile(i)->getMapData(tp) && _save->getTile(i)->getMapData(tp)->getSpecialType() == targetType)\n\t\t\t\t{\n\t\t\t\t\tactualCount++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (actualCount > 0)\n\t\t{\n\t\t\t_save->setObjectiveType(targetType);\n\n\t\t\tif (actualCount < objectives || objectives == 0)\n\t\t\t{\n\t\t\t\t_save->setObjectiveCount(actualCount);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_save->setObjectiveCount(objectives);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n* Sets the depth based on the terrain or the provided AlienDeployment rule.\n* @param ruleDeploy the deployment data we're gleaning data from.\n* @param nextStage whether the mission is progressing to the next stage.\n*/\nvoid BattlescapeGenerator::setDepth(const AlienDeployment* ruleDeploy, bool nextStage)\n{\n\tif (_save->getDepth() > 0 && !nextStage)\n\t{\n\t\t// new battle menu will have set the depth already\n\t\treturn;\n\t}\n\n\tif (ruleDeploy->getMaxDepth() > 0)\n\t{\n\t\t_save->setDepth(RNG::generate(ruleDeploy->getMinDepth(), ruleDeploy->getMaxDepth()));\n\t}\n\telse if (_terrain->getMaxDepth() > 0 || nextStage)\n\t{\n\t\t_save->setDepth(RNG::generate(_terrain->getMinDepth(), _terrain->getMaxDepth()));\n\t}\n}\n\n/**\n* Sets the background music based on the terrain or the provided AlienDeployment rule.\n* @param ruleDeploy the deployment data we're gleaning data from.\n* @param nextStage whether the mission is progressing to the next stage.\n*/\nvoid BattlescapeGenerator::setMusic(const AlienDeployment* ruleDeploy, bool nextStage)\n{\n\tif (!ruleDeploy->getMusic().empty())\n\t{\n\t\t_save->setMusic(ruleDeploy->getMusic().at(RNG::generate(0, ruleDeploy->getMusic().size() - 1)));\n\t}\n\telse if (!_terrain->getMusic().empty())\n\t{\n\t\t_save->setMusic(_terrain->getMusic().at(RNG::generate(0, _terrain->getMusic().size() - 1)));\n\t}\n\telse if (nextStage)\n\t{\n\t\t_save->setMusic(\"\");\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/BattlescapeGenerator.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <vector>\n#include \"../Mod/RuleTerrain.h\"\n#include \"../Mod/MapScript.h\"\n\nnamespace OpenXcom\n{\n\nclass SavedBattleGame;\nclass Mod;\nclass Craft;\nclass RuleCraft;\nclass Ufo;\nclass BattleItem;\nclass MapBlock;\nclass Vehicle;\nclass Tile;\nclass RuleInventory;\nclass RuleItem;\nclass Unit;\nclass AlienRace;\nclass RuleEnviroEffects;\nclass RuleStartingCondition;\nclass AlienDeployment;\nclass Game;\nclass Base;\nclass MissionSite;\nclass AlienBase;\nclass BattleUnit;\nclass Texture;\nclass Position;\n\n/**\n * A utility class that generates the initial battlescape data. Taking into account mission type, craft and ufo involved, terrain type,...\n */\nclass BattlescapeGenerator\n{\nprivate:\n\tGame *_game;\n\tSavedBattleGame *_save;\n\tMod *_mod;\n\tRuleInventory *_inventorySlotGround = nullptr;\n\tCraft *_craft;\n\tconst RuleCraft *_craftRules;\n\tUfo *_ufo;\n\tBase *_base;\n\tMissionSite *_mission;\n\tAlienBase *_alienBase;\n\tRuleTerrain *_terrain, *_baseTerrain, *_globeTerrain, *_alternateTerrain;\n\tint _mapsize_x, _mapsize_y, _mapsize_z;\n\tTexture *_missionTexture, *_globeTexture;\n\tint _worldShade;\n\tint _unitSequence;\n\tTile *_craftInventoryTile;\n\tstd::string _alienRace;\n\tconst AlienDeployment *_alienCustomDeploy, *_alienCustomMission;\n\tint _alienItemLevel;\n\tint _ufoDamagePercentage;\n\tbool _allowAutoLoadout, _baseInventory, _generateFuel, _craftDeployed, _ufoDeployed;\n\tint _craftZ;\n\tSDL_Rect _craftPos;\n\tstd::vector<SDL_Rect> _ufoPos;\n\tstd::vector<int> _ufoZ;\n\tint _markAsReinforcementsBlock;\n\tint _blocksToDo;\n\tstd::vector< std::vector<MapBlock*> > _blocks;\n\tstd::vector< std::vector<bool> > _landingzone;\n\tstd::vector< std::vector<int> > _segments, _drillMap;\n\tMapBlock *_dummy;\n\tstd::vector<SDL_Rect> _placedBlockRects;\n\tstd::vector<VerticalLevel> _verticalLevels;\n\tstd::map<RuleTerrain*, int> _loadedTerrains;\n\tstd::vector<std::pair<MapBlock*, Position> > _verticalLevelSegments;\n\tstd::vector<Tile*> _backupInventoryTiles;\n\n\t/// sets the map size and associated vars\n\tvoid init(bool resetTerrain);\n\t/// Generates a new battlescape map.\n\tvoid generateMap(const std::vector<MapScript*> *script, const std::string &customUfoName, const RuleStartingCondition* startingCondition);\n\t/// Adds a vehicle to the game.\n\tBattleUnit *addXCOMVehicle(Vehicle *v);\n\t/// Adds a soldier to the game.\n\tBattleUnit *addXCOMUnit(BattleUnit *unit);\n\t/// Tries to set a custom craft inventory tile.\n\tvoid setCustomCraftInventoryTile();\n\t/// Adds an alien to the game.\n\tBattleUnit *addAlien(Unit *rules, int alienRank, bool outside);\n\t/// Adds a civilian to the game.\n\tBattleUnit *addCivilian(Unit *rules, int nodeRank);\n\t/// Places an item on a soldier based on equipment layout.\n\tbool placeItemByLayout(BattleItem *item, const std::vector<BattleItem*> &itemList);\n\tvoid reloadFixedWeaponsByLayout();\n\t/// Loads an XCom MAP file.\n\tint loadMAP(MapBlock *mapblock, int xoff, int yoff, int zoff, RuleTerrain *terrain, int objectIDOffset, bool discovered = false, bool craft = false, int ufoIndex = -1);\n\t/// Loads an XCom RMP file.\n\tvoid loadRMP(MapBlock *mapblock, int xoff, int yoff, int zoff, int segment);\n\t/// Checks a terrain requested by a command and loads it if necessary\n\tint loadExtraTerrain(RuleTerrain *terrain);\n\t/// Hide the \"weapon pile\".\n\tvoid sendItemsToLimbo();\n\t/// Fills power sources with an alien fuel object.\n\tvoid fuelPowerSources();\n\t/// Possibly explodes ufo power sources.\n\tvoid explodePowerSources();\n\tvoid explodeOtherJunk();\n\t/// Deploys the XCOM units on the mission.\n\tvoid deployXCOM(const RuleStartingCondition* startingCondition, const RuleEnviroEffects* enviro);\n\t/// Runs necessary checks before physically setting the position.\n\tbool canPlaceXCOMUnit(Tile *tile);\n\t/// Deploys the aliens, according to the alien deployment rules.\n\tvoid deployAliens(const AlienDeployment *deployment);\n\t/// Spawns civilians on a terror mission.\n\tvoid deployCivilians(bool markAsVIP, int nodeRank, int max, bool roundUp = false, const std::string &civilianType = \"\");\n\t/// Finds a spot near a friend to spawn at.\n\tbool placeUnitNearFriend(BattleUnit *unit);\n\t/// Load all Xcom weapons.\n\tvoid loadWeapons(const std::vector<BattleItem*> &itemList);\n\t/// Adds a craft (either a ufo or an xcom craft) somewhere on the map.\n\tbool addCraft(MapBlock *craftMap, MapScript *command, SDL_Rect &craftPos, RuleTerrain *terrain);\n\t/// Adds a line (generally a road) to the map.\n\tbool addLine(MapDirection lineType, const std::vector<SDL_Rect*> *rects, RuleTerrain *terrain, int verticalGroup, int horizontalGroup, int crossingGroup);\n\t/// Adds a single block at a given position.\n\tbool addBlock(int x, int y, MapBlock *block, RuleTerrain *terrain);\n\t/// Load the nodes from the associated map blocks.\n\tvoid loadNodes();\n\t/// Connects all the nodes together.\n\tvoid attachNodeLinks();\n\t/// Selects an unused position on the map of a given size.\n\tbool selectPosition(const std::vector<SDL_Rect *> *rects, int &X, int &Y, int sizeX, int sizeY);\n\t/// Generates a map from base modules.\n\tvoid generateBaseMap();\n\t/// Populates _verticalLevels vector according to a mapscript command and sorts them for use\n\tbool populateVerticalLevels(MapScript *command);\n\t/// Gets a terrain from a terrain name for a command or a vertical level\n\tRuleTerrain* pickTerrain(std::string terrainName);\n\t/// Loads the maps from the _verticalLevels vector\n\tvoid loadVerticalLevels(MapScript *command, bool repopulate = false, MapBlock *craftMap = 0);\n\t/// Clears a module from the map.\n\tvoid clearModule(int x, int y, int sizeX, int sizeY);\n\t/// Drills some tunnels between map blocks.\n\tvoid drillModules(TunnelData* data, const std::vector<SDL_Rect *> *rects, MapDirection dir, RuleTerrain* terrain);\n\t/// Clears all modules in a rect from a command.\n\tbool removeBlocks(MapScript *command);\n\t/// Sets the depth based on the terrain or the provided AlienDeployment rule.\n\tvoid setDepth(const AlienDeployment* ruleDeploy, bool nextStage);\n\t/// Sets the background music based on the terrain or the provided AlienDeployment rule.\n\tvoid setMusic(const AlienDeployment* ruleDeploy, bool nextStage);\npublic:\n\t/// Creates a new BattlescapeGenerator class\n\tBattlescapeGenerator(Game* game);\n\t/// Cleans up the BattlescapeGenerator.\n\t~BattlescapeGenerator();\n\t/// Sets the XCom craft.\n\tvoid setCraft(Craft *craft);\n\t/// Sets the ufo.\n\tvoid setUfo(Ufo* ufo);\n\t/// Sets the polygon texture.\n\tvoid setWorldTexture(Texture *missionTexture, Texture *globeTexture);\n\t/// Sets the polygon shade.\n\tvoid setWorldShade(int shade);\n\t/// Sets the alien race.\n\tvoid setAlienRace(const std::string &alienRace);\n\t/// Sets the alien item level.\n\tvoid setAlienItemlevel(int alienItemLevel);\n\t/// Sets the UFO damage percentage.\n\tvoid setUfoDamagePercentage(int ufoDamagePercentage);\n\t/// Sets the alien weapon deploy items.\n\tvoid setAlienCustomDeploy(const AlienDeployment *alienCustomDeploy = 0, const AlienDeployment* alienCustomBase = 0);\n\t/// Sets the XCom base.\n\tvoid setBase(Base *base);\n\t/// Sets the mission site.\n\tvoid setMissionSite(MissionSite* mission);\n\t/// Sets the alien base\n\tvoid setAlienBase(AlienBase* base);\n\t/// Sets the terrain.\n\tvoid setTerrain(RuleTerrain *terrain);\n\t/// Runs the generator.\n\tvoid run();\n\t/// Gets craft position.\n\tSDL_Rect getCraftPos() const { return _craftPos; }\n\t/// Gets craft elevation.\n\tint getCraftZ() const { return _craftZ; }\n\t/// Sets up the next stage (for Cydonia/TFTD missions).\n\tvoid nextStage();\n\t/// Generates an inventory battlescape.\n\tvoid runInventory(Craft *craft);\n\t/// Sets up the objectives for the map.\n\tvoid setupObjectives(const AlienDeployment *ruleDeploy);\n\t// Auto-equip a set of units\n\tstatic void autoEquip(std::vector<BattleUnit*> units, Mod *mod, std::vector<BattleItem*> *craftInv,\n\t\tRuleInventory *groundRuleInv, int worldShade, bool allowAutoLoadout, bool overrideEquipmentLayout);\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/BattlescapeMessage.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"BattlescapeMessage.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/ProgressBar.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Palette.h\"\n\nnamespace OpenXcom\n{\n\nconst int BattlescapeMessage::HORIZONTAL_OFFSET = 200;\nconst int BattlescapeMessage::VERTICAL_OFFSET = 20;\n\n/**\n * Sets up a blank Battlescape message with the specified size and position.\n * @param width Width in pixels.\n * @param height Height in pixels.\n * @param x X position in pixels.\n * @param y Y position in pixels.\n */\nBattlescapeMessage::BattlescapeMessage(int width, int height, int x, int y) : Surface(width, height, x, y)\n{\n\t_window = new Window(0, width, height, x, y, POPUP_NONE);\n\t_window->setColor(Palette::blockOffset(0)-1);\n\t_window->setHighContrast(true);\n\n\t_text = new Text(width, height, x, y);\n\t_text->setColor(Palette::blockOffset(0)-1);\n\t_text->setAlign(ALIGN_CENTER);\n\t_text->setVerticalAlign(ALIGN_MIDDLE);\n\t_text->setHighContrast(true);\n\n\t_txtThinking = new Text(102, 9, HORIZONTAL_OFFSET, VERTICAL_OFFSET - 10);\n\t_txtThinking->setColor(Palette::blockOffset(0) - 1);\n\t_txtThinking->setAlign(ALIGN_CENTER);\n\t_txtThinking->setHighContrast(true);\n\n\t_progressBar = new ProgressBar(102, 5, HORIZONTAL_OFFSET, VERTICAL_OFFSET);\n\n\tif (Options::oxceDisableThinkingProgressBar)\n\t{\n\t\t_txtThinking->setVisible(false);\n\t\t_progressBar->setVisible(false);\n\t}\n}\n\n/**\n * Deletes surfaces.\n */\nBattlescapeMessage::~BattlescapeMessage()\n{\n\tdelete _window;\n\tdelete _text;\n\tdelete _txtThinking;\n\tdelete _progressBar;\n}\n\n/**\n * Changes the position of the surface in the X axis.\n * @param x X position in pixels.\n */\nvoid BattlescapeMessage::setX(int x)\n{\n\tSurface::setX(x);\n\t_window->setX(x);\n\t_text->setX(x);\n\t_txtThinking->setX(x + HORIZONTAL_OFFSET);\n\t_progressBar->setX(x + HORIZONTAL_OFFSET);\n}\n\n/**\n * Changes the position of the surface in the Y axis.\n * @param y Y position in pixels.\n */\nvoid BattlescapeMessage::setY(int y)\n{\n\tSurface::setY(y);\n\t_window->setY(y);\n\t_text->setY(y);\n\t_txtThinking->setY(y + VERTICAL_OFFSET - 10);\n\t_progressBar->setY(y + VERTICAL_OFFSET);\n}\n\n/**\n * Changes the message background.\n * @param background Pointer to background surface.\n */\nvoid BattlescapeMessage::setBackground(Surface *background)\n{\n\t_window->setBackground(background);\n}\n\n/**\n * Changes the message text.\n * @param message Message string.\n */\nvoid BattlescapeMessage::setText(const std::string &message, const std::string& message2)\n{\n\t_text->setText(message);\n\t_txtThinking->setText(message2);\n}\n\n/**\n * Changes the progress bar value.\n * @param message New value.\n */\nvoid BattlescapeMessage::setProgressValue(int progress)\n{\n\t_progressBar->setValue(progress);\n}\n\n/**\n * Changes the various resources needed for text rendering.\n * The different fonts need to be passed in advance since the\n * text size can change mid-text, and the language affects\n * how the text is rendered.\n * @param big Pointer to large-size font.\n * @param small Pointer to small-size font.\n * @param lang Pointer to current language.\n */\nvoid BattlescapeMessage::initText(Font *big, Font *small, Language *lang)\n{\n\t_text->initText(big, small, lang);\n\t_text->setBig();\n\t_txtThinking->initText(big, small, lang);\n}\n\n/**\n * Replaces a certain amount of colors in the surface's palette.\n * @param colors Pointer to the set of colors.\n * @param firstcolor Offset of the first color to replace.\n * @param ncolors Amount of colors to replace.\n */\nvoid BattlescapeMessage::setPalette(const SDL_Color *colors, int firstcolor, int ncolors)\n{\n\tSurface::setPalette(colors, firstcolor, ncolors);\n\t_window->setPalette(colors, firstcolor, ncolors);\n\t_text->setPalette(colors, firstcolor, ncolors);\n\t_txtThinking->setPalette(colors, firstcolor, ncolors);\n\t_progressBar->setPalette(colors, firstcolor, ncolors);\n}\n\n/**\n * Blits the warning message.\n */\nvoid BattlescapeMessage::blit(SDL_Surface *surface)\n{\n\tSurface::blit(surface);\n\t_window->blit(surface);\n\t_text->blit(surface);\n\t_txtThinking->blit(surface);\n\t_progressBar->blit(surface);\n}\n\n/*\n * Special handling for setting the height of the battlescape message.\n * @param height the new height.\n */\nvoid BattlescapeMessage::setHeight(int height)\n{\n\tSurface::setHeight(height);\n\t_window->setHeight(height);\n\t_text->setHeight(height);\n}\n\n/*\n * Sets the text color of the battlescape message.\n * @param color the new color.\n */\nvoid BattlescapeMessage::setTextColor(Uint8 color)\n{\n\t_text->setColor(color);\n\t_txtThinking->setColor(color);\n}\n\n/*\n * Sets the colors of the progress bar.\n * @param color the new color.\n * @param borderColor the new border color.\n */\nvoid BattlescapeMessage::setProgressBarColor(Uint8 color, Uint8 borderColor)\n{\n\t_progressBar->setColor(color);\n\t_progressBar->setBorderColor(borderColor);\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/BattlescapeMessage.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include \"../Engine/Surface.h\"\n\nnamespace OpenXcom\n{\n\nclass Window;\nclass Text;\nclass Font;\nclass ProgressBar;\n\n/**\n * Generic window used to display messages\n * over the Battlescape map.\n */\nclass BattlescapeMessage : public Surface\n{\nprivate:\n\tstatic const int HORIZONTAL_OFFSET;\n\tstatic const int VERTICAL_OFFSET;\n\n\tWindow *_window;\n\tText *_text;\n\tText *_txtThinking;\n\tProgressBar *_progressBar;\npublic:\n\t/// Creates a new Battlescape message with the specified size and position.\n\tBattlescapeMessage(int width, int height, int x = 0, int y = 0);\n\t/// Cleans up the Battlescape message.\n\t~BattlescapeMessage();\n\t/// Sets the X position of the surface.\n\tvoid setX(int x) override;\n\t/// Sets the Y position of the surface.\n\tvoid setY(int y) override;\n\t/// Sets the Battlescape message's background.\n\tvoid setBackground(Surface *background);\n\t/// Sets the Battlescape message's text.\n\tvoid setText(const std::string &message, const std::string& message2);\n\t/// Sets the progress bar value.\n\tvoid setProgressValue(int progress);\n\t/// Initializes the Battlescape message's resources.\n\tvoid initText(Font *big, Font *small, Language *lang) override;\n\t/// Sets the Battlescape message's palette.\n\tvoid setPalette(const SDL_Color *colors, int firstcolor = 0, int ncolors = 256) override;\n\t/// Blits the warning message.\n\tvoid blit(SDL_Surface *surface) override;\n\t/// Special handling for setting the height of the battlescape message.\n\tvoid setHeight(int height) override;\n\t/// Sets the text color of the battlescape message.\n\tvoid setTextColor(Uint8 color);\n\t/// Sets the colors of the progress bar.\n\tvoid setProgressBarColor(Uint8 color, Uint8 borderColor);\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/BattlescapeState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <algorithm>\n#include <sstream>\n#include <iomanip>\n#include \"../fmath.h\"\n#include <SDL_gfxPrimitives.h>\n#include \"Map.h\"\n#include \"Camera.h\"\n#include \"BattlescapeState.h\"\n#include \"AbortMissionState.h\"\n#include \"TileEngine.h\"\n#include \"ActionMenuState.h\"\n#include \"SkillMenuState.h\"\n#include \"UnitInfoState.h\"\n#include \"InventoryState.h\"\n#include \"AlienInventoryState.h\"\n#include \"Pathfinding.h\"\n#include \"BattlescapeGame.h\"\n#include \"WarningMessage.h\"\n#include \"InfoboxState.h\"\n#include \"NoExperienceState.h\"\n#include \"ExperienceOverviewState.h\"\n#include \"TurnDiaryState.h\"\n#include \"DebriefingState.h\"\n#include \"MiniMapState.h\"\n#include \"BattlescapeGenerator.h\"\n#include \"BriefingState.h\"\n#include \"ExtendedBattlescapeLinksState.h\"\n#include \"../lodepng.h\"\n#include \"../Geoscape/SelectMusicTrackState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Palette.h\"\n#include \"../Engine/Surface.h\"\n#include \"../Engine/SurfaceSet.h\"\n#include \"../Engine/Screen.h\"\n#include \"../Engine/Sound.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Script.h\"\n#include \"../Engine/Logger.h\"\n#include \"../Engine/Timer.h\"\n#include \"../Engine/CrossPlatform.h\"\n#include \"../Interface/Cursor.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/Bar.h\"\n#include \"../Interface/BattlescapeButton.h\"\n#include \"../Interface/NumberText.h\"\n#include \"../Menu/CutsceneState.h\"\n#include \"../Menu/PauseState.h\"\n#include \"../Menu/LoadGameState.h\"\n#include \"../Menu/SaveGameState.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"../Mod/AlienDeployment.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Mod/RuleUfo.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/Craft.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"../Savegame/Tile.h\"\n#include \"../Savegame/BattleUnit.h\"\n#include \"../Savegame/Soldier.h\"\n#include \"../Savegame/BattleItem.h\"\n#include \"../Savegame/HitLog.h\"\n#include \"../Ufopaedia/Ufopaedia.h\"\n#include \"../Savegame/Ufo.h\"\n#include \"../Mod/RuleEnviroEffects.h\"\n#include \"../Mod/RuleInterface.h\"\n#include \"../Mod/RuleInventory.h\"\n#include \"../Mod/RuleSoldier.h\"\n#include \"../Mod/RuleVideo.h\"\n#include <algorithm>\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Battlescape screen.\n * @param game Pointer to the core game.\n */\nBattlescapeState::BattlescapeState() :\n\t_reserve(0), _touchButtonsEnabled(false), _manaBarVisible(false),\n\t_firstInit(true), _paletteResetNeeded(false), _paletteResetRequested(false),\n\t_isMouseScrolling(false), _isMouseScrolled(false),\n\t_xBeforeMouseScrolling(0), _yBeforeMouseScrolling(0),\n\t_totalMouseMoveX(0), _totalMouseMoveY(0), _mouseMovedOverThreshold(0), _mouseOverIcons(false),\n\t_autosave(0),\n\t_numberOfDirectlyVisibleUnits(0), _numberOfEnemiesTotal(0), _numberOfEnemiesTotalPlusWounded(0)\n{\n\t_save = _game->getSavedGame()->getSavedBattle();\n\n\tstd::fill_n(_visibleUnit, 10, (BattleUnit*)(0));\n\n\tconst int screenWidth = Options::baseXResolution;\n\tconst int screenHeight = Options::baseYResolution;\n\tconst int iconsWidth = _game->getMod()->getInterface(\"battlescape\")->getElement(\"icons\")->w;\n\tconst int iconsHeight = _game->getMod()->getInterface(\"battlescape\")->getElement(\"icons\")->h;\n\tconst int visibleMapHeight = screenHeight - iconsHeight;\n\tconst int x = screenWidth/2 - iconsWidth/2;\n\tconst int y = screenHeight - iconsHeight;\n\n\t_indicatorTextColor = _game->getMod()->getInterface(\"battlescape\")->getElement(\"visibleUnits\")->color;\n\t_indicatorGreen = _game->getMod()->getInterface(\"battlescape\")->getElement(\"squadsightUnits\")->color;\n\t_indicatorBlue = _game->getMod()->getInterface(\"battlescape\")->getElement(\"woundedUnits\")->color;\n\t_indicatorPurple = _game->getMod()->getInterface(\"battlescape\")->getElement(\"passingOutUnits\")->color;\n\n\t_twoHandedRed = _game->getMod()->getInterface(\"battlescape\")->getElement(\"twoHandedRed\")->color;\n\t_twoHandedGreen = _game->getMod()->getInterface(\"battlescape\")->getElement(\"twoHandedGreen\")->color;\n\n\t_tooltipDefaultColor = _game->getMod()->getInterface(\"battlescape\")->getElement(\"textTooltip\")->color;\n\n\t_medikitRed = _game->getMod()->getInterface(\"battlescape\")->getElement(\"medikitRed\")->color;\n\t_medikitGreen = _game->getMod()->getInterface(\"battlescape\")->getElement(\"medikitGreen\")->color;\n\t_medikitBlue = _game->getMod()->getInterface(\"battlescape\")->getElement(\"medikitBlue\")->color;\n\t_medikitOrange = _game->getMod()->getInterface(\"battlescape\")->getElement(\"medikitOrange\")->color;\n\n\t// Create buttonbar - this should be on the centerbottom of the screen\n\t_icons = new InteractiveSurface(iconsWidth, iconsHeight, x, y);\n\n\t// Create the battlemap view\n\t// the actual map height is the total height minus the height of the buttonbar\n\t_map = new Map(_game, screenWidth, screenHeight, 0, 0, visibleMapHeight);\n\n\t_numLayers = new NumberText(3, 5, x + 232, y + 6);\n\t_rank = new Surface(26, 23, x + 107, y + 33);\n\n\t// Create buttons\n\t_btnUnitUp = new BattlescapeButton(32, 16, x + 48, y);\n\t_btnUnitDown = new BattlescapeButton(32, 16, x + 48, y + 16);\n\t_btnMapUp = new BattlescapeButton(32, 16, x + 80, y);\n\t_btnMapDown = new BattlescapeButton(32, 16, x + 80, y + 16);\n\t_btnShowMap = new BattlescapeButton(32, 16, x + 112, y);\n\t_btnKneel = new BattlescapeButton(32, 16, x + 112, y + 16);\n\t_btnInventory = new BattlescapeButton(32, 16, x + 144, y);\n\t_btnCenter = new BattlescapeButton(32, 16, x + 144, y + 16);\n\t_btnNextSoldier = new BattlescapeButton(32, 16, x + 176, y);\n\t_btnNextStop = new BattlescapeButton(32, 16, x + 176, y + 16);\n\t_btnShowLayers = new BattlescapeButton(32, 16, x + 208, y);\n\t_btnHelp = new BattlescapeButton(32, 16, x + 208, y + 16);\n\t_btnEndTurn = new BattlescapeButton(32, 16, x + 240, y);\n\t_btnAbort = new BattlescapeButton(32, 16, x + 240, y + 16);\n\t_btnStats = new InteractiveSurface(164, 23, x + 107, y + 33);\n\t_btnReserveNone = new BattlescapeButton(17, 11, x + 60, y + 33);\n\t_btnReserveSnap = new BattlescapeButton(17, 11, x + 78, y + 33);\n\t_btnReserveAimed = new BattlescapeButton(17, 11, x + 60, y + 45);\n\t_btnReserveAuto = new BattlescapeButton(17, 11, x + 78, y + 45);\n\t_btnReserveKneel = new BattlescapeButton(10, 23, x + 96, y + 33);\n\t_btnZeroTUs = new BattlescapeButton(10, 23, x + 49, y + 33);\n\t_btnLeftHandItem = new InteractiveSurface(32, 48, x + 8, y + 4);\n\t_btnRightHandItem = new InteractiveSurface(32, 48, x + 280, y + 4);\n\t_numAmmoLeft.reserve(RuleItem::AmmoSlotMax);\n\t_numAmmoRight.reserve(RuleItem::AmmoSlotMax);\n\tfor (int slot = 0; slot < RuleItem::AmmoSlotMax; ++slot)\n\t{\n\t\t_numAmmoLeft.push_back(new NumberText(30, 5, x + 8, y + 4 + 6 * slot));\n\t\t_numAmmoRight.push_back(new NumberText(30, 5, x + 280, y + 4 + 6 * slot));\n\t}\n\t_numMedikitLeft.reserve(RuleItem::MedikitSlots);\n\t_numMedikitRight.reserve(RuleItem::MedikitSlots);\n\tfor (int slot = 0; slot < RuleItem::MedikitSlots; ++slot)\n\t{\n\t\t_numMedikitLeft.push_back(new NumberText(30, 5, x + 9, y + 32 + 7 * slot));\n\t\t_numMedikitRight.push_back(new NumberText(30, 5, x + 281, y + 32 + 7 * slot));\n\t}\n\t_numTwoHandedIndicatorLeft = new NumberText(10, 5, x + 36, y + 46);\n\t_numTwoHandedIndicatorRight = new NumberText(10, 5, x + 308, y + 46);\n\tconst int visibleUnitX = _game->getMod()->getInterface(\"battlescape\")->getElement(\"visibleUnits\")->x;\n\tconst int visibleUnitY = _game->getMod()->getInterface(\"battlescape\")->getElement(\"visibleUnits\")->y;\n\tfor (int i = 0; i < VISIBLE_MAX; ++i)\n\t{\n\t\t_btnVisibleUnit[i] = new InteractiveSurface(15, 12, x + visibleUnitX, y + visibleUnitY - (i * 13));\n\t\t_numVisibleUnit[i] = new NumberText(15, 12, _btnVisibleUnit[i]->getX() + 6 , _btnVisibleUnit[i]->getY() + 4);\n\t}\n\t_numVisibleUnit[9]->setX(_numVisibleUnit[9]->getX() - 2); // center number 10\n\t_warning = new WarningMessage(224, 24, x + 48, y + 32);\n\t_btnLaunch = new BattlescapeButton(32, 24, screenWidth - 32, 0); // we need screenWidth, because that is independent of the black bars on the screen\n\t_btnLaunch->setVisible(false);\n\t_btnPsi = new BattlescapeButton(32, 24, screenWidth - 32, 25); // we need screenWidth, because that is independent of the black bars on the screen\n\t_btnPsi->setVisible(false);\n\t_btnSpecial = new BattlescapeButton(32, 24, screenWidth - 32, 25); // we need screenWidth, because that is independent of the black bars on the screen\n\t_btnSpecial->setVisible(false);\n\t_btnSkills = new BattlescapeButton(32, 24, screenWidth - 32, 25); // we need screenWidth, because that is independent of the black bars on the screen\n\t_btnSkills->setVisible(false);\n\n\t{\n\t\tint posX = (screenWidth - 32);\n\t\tfor (auto& pos :  _posSpecialActions)\n\t\t{\n\t\t\tpos = posX;\n\t\t\tposX -= 32;\n\t\t}\n\t}\n\n\n\t// Reset touch flags\n\t_game->resetTouchButtonFlags();\n\n\t_btnCtrl = new BattlescapeButton(32, 24, 2, 10);\n\t_btnAlt = new BattlescapeButton(32, 24, 2, 35);\n\t_btnShift = new BattlescapeButton(32, 24, 2, 60);\n\t_btnRMB = new BattlescapeButton(32, 24, 2, 85);\n\t_btnMMB = new BattlescapeButton(32, 24, 2, 110);\n\n\t// Create soldier stats summary\n\t_rankTiny = new Surface(7, 7, x + 135, y + 33);\n\t_txtName = new Text(136, 10, x + 135, y + 32);\n\n\t_manaBarVisible = _game->getMod()->isManaFeatureEnabled()\n\t\t&& _game->getMod()->isManaBarEnabled()\n\t\t&& _game->getSavedGame()->isManaUnlocked(_game->getMod());\n\tint step = _manaBarVisible ? 3 : 4;\n\n\t_numTimeUnits = new NumberText(15, 5, x + 136, y + 42);\n\t_barTimeUnits = new Bar(102, 3, x + 170, y + 41);\n\n\t_numEnergy = new NumberText(15, 5, x + 154, y + 42);\n\t_barEnergy = new Bar(102, 3, x + 170, y + 41 + step);\n\n\t_numHealth = new NumberText(15, 5, x + 136, y + 50);\n\t_barHealth= new Bar(102, 3, x + 170, y + 41 + step*2);\n\n\t_numMorale = new NumberText(15, 5, x + 154, y + 50);\n\t_barMorale = new Bar(102, 3, x + 170, y + 41 + step*3);\n\n\tif (_manaBarVisible)\n\t{\n\t\t_barMana = new Bar(102, 3, x + 170, y + 41 + step*4);\n\t}\n\n\t_txtDebug = new Text(300, 10, 20, 0);\n\t_txtTooltip = new Text(300, 10, x + 2, y - 10);\n\n\t// Palette transformations\n\tauto* enviro = _save->getEnviroEffects();\n\tif (enviro)\n\t{\n\t\tfor (auto& change : enviro->getPaletteTransformations())\n\t\t{\n\t\t\tPalette *origPal = _game->getMod()->getPalette(change.first, false);\n\t\t\tPalette *newPal = _game->getMod()->getPalette(change.second, false);\n\t\t\tif (origPal && newPal)\n\t\t\t{\n\t\t\t\torigPal->copyFrom(newPal);\n\t\t\t\t_paletteResetNeeded = true;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Set palette\n\t_save->setPaletteByDepth(this);\n\n\tif (_game->getMod()->getInterface(\"battlescape\")->getElementOptional(\"pathfinding\"))\n\t{\n\t\tconst Element *pathing = _game->getMod()->getInterface(\"battlescape\")->getElement(\"pathfinding\");\n\n\t\tPathfinding::green = pathing->color;\n\t\tPathfinding::yellow = pathing->color2;\n\t\tPathfinding::red = pathing->border;\n\t}\n\n\tadd(_map);\n\tadd(_icons);\n\n\t// Add in custom reserve buttons\n\tSurface *icons = _game->getMod()->getSurface(\"ICONS.PCK\");\n\tif (_game->getMod()->getSurface(\"TFTDReserve\", false))\n\t{\n\t\tSurface *tftdIcons = _game->getMod()->getSurface(\"TFTDReserve\");\n\t\ttftdIcons->blitNShade(icons, 48, 176);\n\t}\n\n\t// there is some cropping going on here, because the icons image is 320x200 while we only need the bottom of it.\n\tSurfaceCrop crop = icons->getCrop();\n\tcrop.getCrop()->x = 0;\n\tcrop.getCrop()->y = 200 - iconsHeight;\n\tcrop.getCrop()->w = iconsWidth;\n\tcrop.getCrop()->h = iconsHeight;\n\t// we need to blit the icons before we add the battlescape buttons, as they copy the underlying parent surface.\n\tcrop.blit(_icons);\n\n\t// this is a hack to fix the single transparent pixel on TFTD's icon panel.\n\tif (_game->getMod()->getInterface(\"battlescape\")->getElement(\"icons\")->TFTDMode)\n\t{\n\t\t_icons->setPixel(46, 44, 8);\n\t}\n\n\t// custom OXCE links button\n\tif (Options::oxceLinks && _game->getMod()->getSurface(\"oxceLinks\", false))\n\t{\n\t\tSurface* oxceLinks = _game->getMod()->getSurface(\"oxceLinks\");\n\t\toxceLinks->blitNShade(_icons, 208, 0);\n\n\t\t_numLayers->setVisible(false);\n\t}\n\n\tadd(_rank, \"rank\", \"battlescape\", _icons);\n\tadd(_rankTiny, \"rank\", \"battlescape\", _icons);\n\tadd(_btnUnitUp, \"buttonUnitUp\", \"battlescape\", _icons);\n\tadd(_btnUnitDown, \"buttonUnitDown\", \"battlescape\", _icons);\n\tadd(_btnMapUp, \"buttonMapUp\", \"battlescape\", _icons);\n\tadd(_btnMapDown, \"buttonMapDown\", \"battlescape\", _icons);\n\tadd(_btnShowMap, \"buttonShowMap\", \"battlescape\", _icons);\n\tadd(_btnKneel, \"buttonKneel\", \"battlescape\", _icons);\n\tadd(_btnInventory, \"buttonInventory\", \"battlescape\", _icons);\n\tadd(_btnCenter, \"buttonCenter\", \"battlescape\", _icons);\n\tadd(_btnNextSoldier, \"buttonNextSoldier\", \"battlescape\", _icons);\n\tadd(_btnNextStop, \"buttonNextStop\", \"battlescape\", _icons);\n\tadd(_btnShowLayers, \"buttonShowLayers\", \"battlescape\", _icons);\n\tadd(_numLayers, \"numLayers\", \"battlescape\", _icons);\n\tadd(_btnHelp, \"buttonHelp\", \"battlescape\", _icons);\n\tadd(_btnEndTurn, \"buttonEndTurn\", \"battlescape\", _icons);\n\tadd(_btnAbort, \"buttonAbort\", \"battlescape\", _icons);\n\tadd(_btnStats, \"buttonStats\", \"battlescape\", _icons);\n\tadd(_txtName, \"textName\", \"battlescape\", _icons);\n\t// need to do this here, because of TFTD\n\tif (_game->getMod()->getSurface(\"AvatarBackground\", false))\n\t{\n\t\t// put tiny rank icon where name used to be\n\t\t_rankTiny->setX(_txtName->getX());\n\t\t_rankTiny->setY(_txtName->getY() + 1);\n\t\t// move name more to the right\n\t\t_txtName->setWidth(_txtName->getWidth() - 8);\n\t\t_txtName->setX(_txtName->getX() + 8);\n\t}\n\tadd(_numTimeUnits, \"numTUs\", \"battlescape\", _icons);\n\tadd(_numEnergy, \"numEnergy\", \"battlescape\", _icons);\n\tadd(_numHealth, \"numHealth\", \"battlescape\", _icons);\n\tadd(_numMorale, \"numMorale\", \"battlescape\", _icons);\n\tadd(_barTimeUnits, \"barTUs\", \"battlescape\", _icons);\n\tadd(_barEnergy, \"barEnergy\", \"battlescape\", _icons);\n\tadd(_barHealth, \"barHealth\", \"battlescape\", _icons);\n\tadd(_barMorale, \"barMorale\", \"battlescape\", _icons);\n\tif (_manaBarVisible)\n\t{\n\t\tadd(_barMana, \"barMana\", \"battlescape\", _icons);\n\t}\n\tadd(_btnReserveNone, \"buttonReserveNone\", \"battlescape\", _icons);\n\tadd(_btnReserveSnap, \"buttonReserveSnap\", \"battlescape\", _icons);\n\tadd(_btnReserveAimed, \"buttonReserveAimed\", \"battlescape\", _icons);\n\tadd(_btnReserveAuto, \"buttonReserveAuto\", \"battlescape\", _icons);\n\tadd(_btnReserveKneel, \"buttonReserveKneel\", \"battlescape\", _icons);\n\tadd(_btnZeroTUs, \"buttonZeroTUs\", \"battlescape\", _icons);\n\tadd(_btnLeftHandItem, \"buttonLeftHand\", \"battlescape\", _icons);\n\tadd(_btnRightHandItem, \"buttonRightHand\", \"battlescape\", _icons);\n\tfor (int slot = 0; slot < RuleItem::AmmoSlotMax; ++slot)\n\t{\n\t\tadd(_numAmmoLeft[slot], \"numAmmoLeft\", \"battlescape\", _icons);\n\t\tadd(_numAmmoRight[slot], \"numAmmoRight\", \"battlescape\", _icons);\n\t}\n\tfor (int slot = 0; slot < RuleItem::MedikitSlots; ++slot)\n\t{\n\t\tadd(_numMedikitLeft[slot], \"numMedikitLeft\", \"battlescape\", _icons);\n\t\tadd(_numMedikitRight[slot], \"numMedikitRight\", \"battlescape\", _icons);\n\t}\n\tadd(_numTwoHandedIndicatorLeft, \"numTwoHandedIndicatorLeft\", \"battlescape\", _icons);\n\tadd(_numTwoHandedIndicatorRight, \"numTwoHandedIndicatorRight\", \"battlescape\", _icons);\n\tfor (int i = 0; i < VISIBLE_MAX; ++i)\n\t{\n\t\tadd(_btnVisibleUnit[i]);\n\t\tadd(_numVisibleUnit[i]);\n\t}\n\tadd(_warning, \"warning\", \"battlescape\", _icons);\n\tadd(_txtDebug);\n\tadd(_txtTooltip, \"textTooltip\", \"battlescape\", _icons);\n\tadd(_btnLaunch);\n\t_game->getMod()->getSurfaceSet(\"SPICONS.DAT\")->getFrame(0)->blitNShade(_btnLaunch, 0, 0);\n\tadd(_btnPsi);\n\t_game->getMod()->getSurfaceSet(\"SPICONS.DAT\")->getFrame(1)->blitNShade(_btnPsi, 0, 0);\n\tadd(_btnSpecial);\n\t_game->getMod()->getSurfaceSet(\"SPICONS.DAT\")->getFrame(1)->blitNShade(_btnSpecial, 0, 0); // use psi button for default\n\tadd(_btnSkills);\n\t_game->getMod()->getSurfaceSet(\"SPICONS.DAT\")->getFrame(1)->blitNShade(_btnSkills, 0, 0); // use psi button for default\n\n\tadd(_btnCtrl);\n\tadd(_btnAlt);\n\tadd(_btnShift);\n\tadd(_btnRMB);\n\tadd(_btnMMB);\n\n\t_game->getMod()->getSurfaceSet(\"Touch\")->getFrame(0)->blitNShade(_btnCtrl, 0, 0);\n\t_game->getMod()->getSurfaceSet(\"Touch\")->getFrame(2)->blitNShade(_btnAlt, 0, 0);\n\t_game->getMod()->getSurfaceSet(\"Touch\")->getFrame(4)->blitNShade(_btnShift, 0, 0);\n\t_game->getMod()->getSurfaceSet(\"Touch\")->getFrame(6)->blitNShade(_btnRMB, 0, 0);\n\t_game->getMod()->getSurfaceSet(\"Touch\")->getFrame(8)->blitNShade(_btnMMB, 0, 0);\n\n\t_btnCtrl->initSurfaces(_game->getMod()->getSurfaceSet(\"Touch\")->getFrame(1));\n\t_btnAlt->initSurfaces(_game->getMod()->getSurfaceSet(\"Touch\")->getFrame(3));\n\t_btnShift->initSurfaces(_game->getMod()->getSurfaceSet(\"Touch\")->getFrame(5));\n\t_btnRMB->initSurfaces(_game->getMod()->getSurfaceSet(\"Touch\")->getFrame(7));\n\t_btnMMB->initSurfaces(_game->getMod()->getSurfaceSet(\"Touch\")->getFrame(9));\n\n\t// Set up objects\n\t_map->init();\n\t_map->onMouseOver((ActionHandler)&BattlescapeState::mapOver);\n\t_map->onMousePress((ActionHandler)&BattlescapeState::mapPress);\n\t_map->onMouseClick((ActionHandler)&BattlescapeState::mapClick, 0);\n\t_map->onMouseIn((ActionHandler)&BattlescapeState::mapIn);\n\n\t_numLayers->setColor(Palette::blockOffset(1)-2);\n\t_numLayers->setValue(1);\n\n\tfor (int slot = 0; slot < RuleItem::AmmoSlotMax; ++slot)\n\t{\n\t\t_numAmmoLeft[slot]->setValue(999);\n\t\t_numAmmoRight[slot]->setValue(999);\n\t}\n\tfor (int slot = 0; slot < RuleItem::MedikitSlots; ++slot)\n\t{\n\t\t_numMedikitLeft[slot]->setValue(999);\n\t\t_numMedikitRight[slot]->setValue(999);\n\t}\n\t_numTwoHandedIndicatorLeft->setValue(2);\n\t_numTwoHandedIndicatorRight->setValue(2);\n\n\t_icons->onMouseIn((ActionHandler)&BattlescapeState::mouseInIcons);\n\t_icons->onMouseOut((ActionHandler)&BattlescapeState::mouseOutIcons);\n\n\t_btnUnitUp->onMouseClick((ActionHandler)&BattlescapeState::btnUnitUpClick);\n\t_btnUnitUp->onKeyboardPress((ActionHandler)&BattlescapeState::btnUnitUpClick, Options::keyBattleUnitUp);\n\t_btnUnitUp->setTooltip(\"STR_UNIT_LEVEL_ABOVE\");\n\t_btnUnitUp->onMouseIn((ActionHandler)&BattlescapeState::txtTooltipIn);\n\t_btnUnitUp->onMouseOut((ActionHandler)&BattlescapeState::txtTooltipOut);\n\n\t_btnUnitDown->onMouseClick((ActionHandler)&BattlescapeState::btnUnitDownClick);\n\t_btnUnitDown->onKeyboardPress((ActionHandler)&BattlescapeState::btnUnitDownClick, Options::keyBattleUnitDown);\n\t_btnUnitDown->setTooltip(\"STR_UNIT_LEVEL_BELOW\");\n\t_btnUnitDown->onMouseIn((ActionHandler)&BattlescapeState::txtTooltipIn);\n\t_btnUnitDown->onMouseOut((ActionHandler)&BattlescapeState::txtTooltipOut);\n\n\t_btnMapUp->onMouseClick((ActionHandler)&BattlescapeState::btnMapUpClick);\n\t_btnMapUp->onKeyboardPress((ActionHandler)&BattlescapeState::btnMapUpClick, Options::keyBattleLevelUp);\n\t_btnMapUp->setTooltip(\"STR_VIEW_LEVEL_ABOVE\");\n\t_btnMapUp->onMouseIn((ActionHandler)&BattlescapeState::txtTooltipIn);\n\t_btnMapUp->onMouseOut((ActionHandler)&BattlescapeState::txtTooltipOut);\n\n\t_btnMapDown->onMouseClick((ActionHandler)&BattlescapeState::btnMapDownClick);\n\t_btnMapDown->onKeyboardPress((ActionHandler)&BattlescapeState::btnMapDownClick, Options::keyBattleLevelDown);\n\t_btnMapDown->setTooltip(\"STR_VIEW_LEVEL_BELOW\");\n\t_btnMapDown->onMouseIn((ActionHandler)&BattlescapeState::txtTooltipIn);\n\t_btnMapDown->onMouseOut((ActionHandler)&BattlescapeState::txtTooltipOut);\n\n\t_btnShowMap->onMouseClick((ActionHandler)&BattlescapeState::btnShowMapClick);\n\t_btnShowMap->onKeyboardPress((ActionHandler)&BattlescapeState::btnShowMapClick, Options::keyBattleMap);\n\t_btnShowMap->setTooltip(\"STR_MINIMAP\");\n\t_btnShowMap->onMouseIn((ActionHandler)&BattlescapeState::txtTooltipIn);\n\t_btnShowMap->onMouseOut((ActionHandler)&BattlescapeState::txtTooltipOut);\n\n\t_btnKneel->onMouseClick((ActionHandler)&BattlescapeState::btnKneelClick);\n\t_btnKneel->onKeyboardPress((ActionHandler)&BattlescapeState::btnKneelClick, Options::keyBattleKneel);\n\t_btnKneel->setTooltip(\"STR_KNEEL\");\n\t_btnKneel->onMouseIn((ActionHandler)&BattlescapeState::txtTooltipIn);\n\t_btnKneel->onMouseOut((ActionHandler)&BattlescapeState::txtTooltipOut);\n\t_btnKneel->allowToggleInversion();\n\n\t_btnInventory->onMouseClick((ActionHandler)&BattlescapeState::btnInventoryClick);\n\t_btnInventory->onKeyboardPress((ActionHandler)&BattlescapeState::btnInventoryClick, Options::keyBattleInventory);\n\t_btnInventory->setTooltip(\"STR_INVENTORY\");\n\t_btnInventory->onMouseIn((ActionHandler)&BattlescapeState::txtTooltipIn);\n\t_btnInventory->onMouseOut((ActionHandler)&BattlescapeState::txtTooltipOut);\n\n\t_btnCenter->onMouseClick((ActionHandler)&BattlescapeState::btnCenterClick);\n\t_btnCenter->onKeyboardPress((ActionHandler)&BattlescapeState::btnCenterClick, Options::keyBattleCenterUnit);\n\t_btnCenter->setTooltip(\"STR_CENTER_SELECTED_UNIT\");\n\t_btnCenter->onMouseIn((ActionHandler)&BattlescapeState::txtTooltipIn);\n\t_btnCenter->onMouseOut((ActionHandler)&BattlescapeState::txtTooltipOut);\n\n\t_btnNextSoldier->onMouseClick((ActionHandler)&BattlescapeState::btnNextSoldierClick, SDL_BUTTON_LEFT);\n\t_btnNextSoldier->onMouseClick((ActionHandler)&BattlescapeState::btnPrevSoldierClick, SDL_BUTTON_RIGHT);\n\t_btnNextSoldier->onKeyboardPress((ActionHandler)&BattlescapeState::btnNextSoldierClick, Options::keyBattleNextUnit);\n\t_btnNextSoldier->onKeyboardPress((ActionHandler)&BattlescapeState::btnPrevSoldierClick, Options::keyBattlePrevUnit);\n\t_btnNextSoldier->setTooltip(\"STR_NEXT_UNIT\");\n\t_btnNextSoldier->onMouseIn((ActionHandler)&BattlescapeState::txtTooltipIn);\n\t_btnNextSoldier->onMouseOut((ActionHandler)&BattlescapeState::txtTooltipOut);\n\n\tif (Options::oxceSwapDontReselectActions)\n\t{\n\t\t_btnNextStop->onMouseClick((ActionHandler)&BattlescapeState::btnNextStopMClick, SDL_BUTTON_LEFT);\n\t\t_btnNextStop->onMouseClick((ActionHandler)&BattlescapeState::btnNextStopRClick, SDL_BUTTON_RIGHT);\n\t\t_btnNextStop->onMouseClick((ActionHandler)&BattlescapeState::btnNextStopLClick, SDL_BUTTON_MIDDLE);\n\t\t_btnNextStop->onKeyboardPress((ActionHandler)&BattlescapeState::btnNextStopMClick, Options::keyBattleDeselectUnit);\n\t}\n\telse\n\t{\n\t\t_btnNextStop->onMouseClick((ActionHandler)&BattlescapeState::btnNextStopLClick, SDL_BUTTON_LEFT);\n\t\t_btnNextStop->onMouseClick((ActionHandler)&BattlescapeState::btnNextStopRClick, SDL_BUTTON_RIGHT);\n\t\t_btnNextStop->onMouseClick((ActionHandler)&BattlescapeState::btnNextStopMClick, SDL_BUTTON_MIDDLE);\n\t\t_btnNextStop->onKeyboardPress((ActionHandler)&BattlescapeState::btnNextStopLClick, Options::keyBattleDeselectUnit);\n\t}\n\t_btnNextStop->setTooltip(\"STR_DESELECT_UNIT\");\n\t_btnNextStop->onMouseIn((ActionHandler)&BattlescapeState::txtTooltipIn);\n\t_btnNextStop->onMouseOut((ActionHandler)&BattlescapeState::txtTooltipOut);\n\n\t_btnShowLayers->onMouseClick((ActionHandler)&BattlescapeState::btnShowLayersClick);\n\t_btnShowLayers->setTooltip(Options::oxceLinks ? \"STR_EXTENDED_LINKS\" : \"STR_MULTI_LEVEL_VIEW\");\n\t_btnShowLayers->onMouseIn((ActionHandler)&BattlescapeState::txtTooltipIn);\n\t_btnShowLayers->onMouseOut((ActionHandler)&BattlescapeState::txtTooltipOut);\n\t_btnShowLayers->onKeyboardPress((ActionHandler)&BattlescapeState::btnShowLayersClickOrig, Options::keyBattleShowLayers);\n\t_btnShowLayers->onKeyboardPress((ActionHandler)&BattlescapeState::btnUfopaediaClick, Options::keyGeoUfopedia);\n\n\t_btnHelp->onMouseClick((ActionHandler)&BattlescapeState::btnHelpClick);\n\tif (!_save->isPreview())\n\t{\n\t\t_btnHelp->onKeyboardPress((ActionHandler)&BattlescapeState::btnHelpClick, Options::keyBattleOptions);\n\t}\n\t_btnHelp->setTooltip(\"STR_OPTIONS\");\n\t_btnHelp->onMouseIn((ActionHandler)&BattlescapeState::txtTooltipIn);\n\t_btnHelp->onMouseOut((ActionHandler)&BattlescapeState::txtTooltipOut);\n\n\t_btnEndTurn->onMouseClick((ActionHandler)&BattlescapeState::btnEndTurnClick);\n\t_btnEndTurn->onKeyboardPress((ActionHandler)&BattlescapeState::btnEndTurnClick, Options::keyBattleEndTurn);\n\tif (_save->isPreview())\n\t{\n\t\t_btnEndTurn->onKeyboardPress((ActionHandler)&BattlescapeState::btnEndTurnClick, Options::keyBattleOptions); // Esc\n\t}\n\t_btnEndTurn->setTooltip(\"STR_END_TURN\");\n\t_btnEndTurn->onMouseIn((ActionHandler)&BattlescapeState::txtTooltipInEndTurn);\n\t_btnEndTurn->onMouseOut((ActionHandler)&BattlescapeState::txtTooltipOut);\n\n\t_btnAbort->onMouseClick((ActionHandler)&BattlescapeState::btnAbortClick);\n\t_btnAbort->onKeyboardPress((ActionHandler)&BattlescapeState::btnAbortClick, Options::keyBattleAbort);\n\t_btnAbort->setTooltip(\"STR_ABORT_MISSION\");\n\t_btnAbort->onMouseIn((ActionHandler)&BattlescapeState::txtTooltipIn);\n\t_btnAbort->onMouseOut((ActionHandler)&BattlescapeState::txtTooltipOut);\n\n\t_btnStats->onMouseClick((ActionHandler)&BattlescapeState::btnStatsClick);\n\t_btnStats->onMouseClick((ActionHandler)&BattlescapeState::btnStatsClick, SDL_BUTTON_RIGHT);\n\t_btnStats->onKeyboardPress((ActionHandler)&BattlescapeState::btnStatsClick, Options::keyBattleStats);\n\t_btnStats->setTooltip(\"STR_UNIT_STATS\");\n\t_btnStats->onMouseIn((ActionHandler)&BattlescapeState::txtTooltipIn);\n\t_btnStats->onMouseOut((ActionHandler)&BattlescapeState::txtTooltipOut);\n\n\t_btnLeftHandItem->onMouseClick((ActionHandler)&BattlescapeState::btnLeftHandItemClick);\n\t_btnLeftHandItem->onMouseClick((ActionHandler)&BattlescapeState::btnLeftHandItemClick, SDL_BUTTON_RIGHT);\n\t_btnLeftHandItem->onMouseClick((ActionHandler)&BattlescapeState::btnLeftHandItemClick, SDL_BUTTON_MIDDLE);\n\t_btnLeftHandItem->onKeyboardPress((ActionHandler)&BattlescapeState::btnLeftHandItemClick, Options::keyBattleUseLeftHand);\n\t_btnLeftHandItem->setTooltip(\"STR_USE_LEFT_HAND\");\n\t_btnLeftHandItem->onMouseIn((ActionHandler)&BattlescapeState::txtTooltipInExtraLeftHand);\n\t_btnLeftHandItem->onMouseOut((ActionHandler)&BattlescapeState::txtTooltipOut);\n\n\t_btnRightHandItem->onMouseClick((ActionHandler)&BattlescapeState::btnRightHandItemClick);\n\t_btnRightHandItem->onMouseClick((ActionHandler)&BattlescapeState::btnRightHandItemClick, SDL_BUTTON_RIGHT);\n\t_btnRightHandItem->onMouseClick((ActionHandler)&BattlescapeState::btnRightHandItemClick, SDL_BUTTON_MIDDLE);\n\t_btnRightHandItem->onKeyboardPress((ActionHandler)&BattlescapeState::btnRightHandItemClick, Options::keyBattleUseRightHand);\n\t_btnRightHandItem->setTooltip(\"STR_USE_RIGHT_HAND\");\n\t_btnRightHandItem->onMouseIn((ActionHandler)&BattlescapeState::txtTooltipInExtraRightHand);\n\t_btnRightHandItem->onMouseOut((ActionHandler)&BattlescapeState::txtTooltipOut);\n\n\t_btnReserveNone->onMouseClick((ActionHandler)&BattlescapeState::btnReserveClick);\n\t_btnReserveNone->onKeyboardPress((ActionHandler)&BattlescapeState::btnReserveClick, Options::keyBattleReserveNone);\n\t_btnReserveNone->setTooltip(\"STR_DONT_RESERVE_TIME_UNITS\");\n\t_btnReserveNone->onMouseIn((ActionHandler)&BattlescapeState::txtTooltipIn);\n\t_btnReserveNone->onMouseOut((ActionHandler)&BattlescapeState::txtTooltipOut);\n\n\t_btnReserveSnap->onMouseClick((ActionHandler)&BattlescapeState::btnReserveClick);\n\t_btnReserveSnap->onKeyboardPress((ActionHandler)&BattlescapeState::btnReserveClick, Options::keyBattleReserveSnap);\n\t_btnReserveSnap->setTooltip(\"STR_RESERVE_TIME_UNITS_FOR_SNAP_SHOT\");\n\t_btnReserveSnap->onMouseIn((ActionHandler)&BattlescapeState::txtTooltipIn);\n\t_btnReserveSnap->onMouseOut((ActionHandler)&BattlescapeState::txtTooltipOut);\n\n\t_btnReserveAimed->onMouseClick((ActionHandler)&BattlescapeState::btnReserveClick);\n\t_btnReserveAimed->onKeyboardPress((ActionHandler)&BattlescapeState::btnReserveClick, Options::keyBattleReserveAimed);\n\t_btnReserveAimed->setTooltip(\"STR_RESERVE_TIME_UNITS_FOR_AIMED_SHOT\");\n\t_btnReserveAimed->onMouseIn((ActionHandler)&BattlescapeState::txtTooltipIn);\n\t_btnReserveAimed->onMouseOut((ActionHandler)&BattlescapeState::txtTooltipOut);\n\n\t_btnReserveAuto->onMouseClick((ActionHandler)&BattlescapeState::btnReserveClick);\n\t_btnReserveAuto->onKeyboardPress((ActionHandler)&BattlescapeState::btnReserveClick, Options::keyBattleReserveAuto);\n\t_btnReserveAuto->setTooltip(\"STR_RESERVE_TIME_UNITS_FOR_AUTO_SHOT\");\n\t_btnReserveAuto->onMouseIn((ActionHandler)&BattlescapeState::txtTooltipIn);\n\t_btnReserveAuto->onMouseOut((ActionHandler)&BattlescapeState::txtTooltipOut);\n\n\t_btnReserveKneel->onMouseClick((ActionHandler)&BattlescapeState::btnReserveKneelClick);\n\t_btnReserveKneel->onKeyboardPress((ActionHandler)&BattlescapeState::btnReserveKneelClick, Options::keyBattleReserveKneel);\n\t_btnReserveKneel->setTooltip(\"STR_RESERVE_TIME_UNITS_FOR_KNEEL\");\n\t_btnReserveKneel->onMouseIn((ActionHandler)&BattlescapeState::txtTooltipIn);\n\t_btnReserveKneel->onMouseOut((ActionHandler)&BattlescapeState::txtTooltipOut);\n\t_btnReserveKneel->allowToggleInversion();\n\n\t_btnZeroTUs->onMouseClick((ActionHandler)&BattlescapeState::btnZeroTUsClick, SDL_BUTTON_RIGHT);\n\t_btnZeroTUs->onKeyboardPress((ActionHandler)&BattlescapeState::btnZeroTUsClick, Options::keyBattleZeroTUs);\n\t_btnZeroTUs->setTooltip(\"STR_EXPEND_ALL_TIME_UNITS\");\n\t_btnZeroTUs->onMouseIn((ActionHandler)&BattlescapeState::txtTooltipIn);\n\t_btnZeroTUs->onMouseOut((ActionHandler)&BattlescapeState::txtTooltipOut);\n\t_btnZeroTUs->allowClickInversion();\n\n\t// shortcuts without a specific button\n\t_btnStats->onKeyboardPress((ActionHandler)&BattlescapeState::btnReloadClick, Options::keyBattleReload);\n\t_btnStats->onKeyboardPress((ActionHandler)&BattlescapeState::btnSelectMusicTrackClick, Options::keySelectMusicTrack);\n\t_btnStats->onKeyboardPress((ActionHandler)&BattlescapeState::btnPersonalLightingClick, Options::keyBattlePersonalLighting);\n\t_btnStats->onKeyboardPress((ActionHandler)&BattlescapeState::btnNightVisionClick, Options::keyNightVisionToggle);\n\t//_btnStats->onKeyboardPress((ActionHandler)&BattlescapeState::btnTouchButtonsClick, SDLK_t); // for debugging only\n\n\t// automatic night vision\n\tif (_save->getGlobalShade() > Options::oxceAutoNightVisionThreshold)\n\t{\n\t\tbool ignore = (enviro && enviro->ignoreAutoNightVisionUserSetting());\n\t\tif (!ignore)\n\t\t{\n\t\t\t// turn personal lights off\n\t\t\t//_save->getTileEngine()->togglePersonalLighting();\n\t\t\t// turn night vision on\n\t\t\t_map->enableNightVision();\n\t\t}\n\t}\n\n\tSDLKey buttons[] = {Options::keyBattleCenterEnemy1,\n\t\t\t\t\t\tOptions::keyBattleCenterEnemy2,\n\t\t\t\t\t\tOptions::keyBattleCenterEnemy3,\n\t\t\t\t\t\tOptions::keyBattleCenterEnemy4,\n\t\t\t\t\t\tOptions::keyBattleCenterEnemy5,\n\t\t\t\t\t\tOptions::keyBattleCenterEnemy6,\n\t\t\t\t\t\tOptions::keyBattleCenterEnemy7,\n\t\t\t\t\t\tOptions::keyBattleCenterEnemy8,\n\t\t\t\t\t\tOptions::keyBattleCenterEnemy9,\n\t\t\t\t\t\tOptions::keyBattleCenterEnemy10};\n\tfor (int i = 0; i < VISIBLE_MAX; ++i)\n\t{\n\t\tstd::ostringstream tooltip;\n\t\t_btnVisibleUnit[i]->onMouseClick((ActionHandler)&BattlescapeState::btnVisibleUnitClick);\n\t\t_btnVisibleUnit[i]->onMouseClick((ActionHandler)&BattlescapeState::btnVisibleUnitClick, SDL_BUTTON_RIGHT);\n\t\t_btnVisibleUnit[i]->onKeyboardPress((ActionHandler)&BattlescapeState::btnVisibleUnitClick, buttons[i]);\n\t\ttooltip << \"STR_CENTER_ON_ENEMY_\" << (i+1);\n\t\t_txtVisibleUnitTooltip[i] = tooltip.str();\n\t\t_btnVisibleUnit[i]->setTooltip(_txtVisibleUnitTooltip[i]);\n\t\t_btnVisibleUnit[i]->onMouseIn((ActionHandler)&BattlescapeState::txtTooltipIn);\n\t\t_btnVisibleUnit[i]->onMouseOut((ActionHandler)&BattlescapeState::txtTooltipOut);\n\t\t_numVisibleUnit[i]->setColor(_indicatorTextColor);\n\t\t_numVisibleUnit[i]->setValue(i+1);\n\t}\n\t_txtVisibleUnitTooltip[VISIBLE_MAX] = \"STR_CENTER_ON_WOUNDED_FRIEND\";\n\t_txtVisibleUnitTooltip[VISIBLE_MAX+1] = \"STR_CENTER_ON_DIZZY_FRIEND\";\n\n\t_warning->setColor(_game->getMod()->getInterface(\"battlescape\")->getElement(\"warning\")->color2);\n\t_warning->setTextColor(_game->getMod()->getInterface(\"battlescape\")->getElement(\"warning\")->color);\n\t_btnLaunch->onMouseClick((ActionHandler)&BattlescapeState::btnLaunchClick);\n\t_btnPsi->onMouseClick((ActionHandler)&BattlescapeState::btnPsiClick);\n\n\t_btnSpecial->onMouseClick((ActionHandler)&BattlescapeState::btnSpecialClick);\n\t_btnSpecial->onMouseClick((ActionHandler)&BattlescapeState::btnSpecialClick, SDL_BUTTON_MIDDLE);\n\t_btnSpecial->onKeyboardPress((ActionHandler)&BattlescapeState::btnSpecialClick, Options::keyBattleUseSpecial);\n\t_btnSpecial->setTooltip(\"STR_USE_SPECIAL_ITEM\");\n\t_btnSpecial->onMouseIn((ActionHandler)&BattlescapeState::txtTooltipInExtraSpecial);\n\t_btnSpecial->onMouseOut((ActionHandler)&BattlescapeState::txtTooltipOut);\n\n\t_btnSkills->onMouseClick((ActionHandler)&BattlescapeState::btnSkillsClick);\n\t_btnSkills->onKeyboardPress((ActionHandler)&BattlescapeState::btnSkillsClick, Options::keyBattleUseSpecial);\n\n\t_btnCtrl->onMouseClick((ActionHandler)&BattlescapeState::btnCtrlClick);\n\t_btnAlt->onMouseClick((ActionHandler)&BattlescapeState::btnAltClick);\n\t_btnShift->onMouseClick((ActionHandler)&BattlescapeState::btnShiftClick);\n\t_btnRMB->onMouseClick((ActionHandler)&BattlescapeState::btnRMBClick);\n\t_btnMMB->onMouseClick((ActionHandler)&BattlescapeState::btnMMBClick);\n\n\t_btnCtrl->allowToggleInversion();\n\t_btnAlt->allowToggleInversion();\n\t_btnShift->allowToggleInversion();\n\t_btnRMB->allowToggleInversion();\n\t_btnMMB->allowToggleInversion();\n\n\t_btnCtrl->setVisible(false);\n\t_btnAlt->setVisible(false);\n\t_btnShift->setVisible(false);\n\t_btnRMB->setVisible(false);\n\t_btnMMB->setVisible(false);\n\n\t_txtName->setHighContrast(true);\n\n\t_barTimeUnits->setScale(1.0);\n\t_barEnergy->setScale(1.0);\n\t_barHealth->setScale(1.0);\n\t_barMorale->setScale(1.0);\n\tif (_manaBarVisible)\n\t{\n\t\t_barMana->setScale(1.0);\n\t}\n\n\t_txtDebug->setColor(Palette::blockOffset(8));\n\t_txtDebug->setHighContrast(true);\n\n\t_txtTooltip->setHighContrast(true);\n\n\t_btnReserveNone->setGroup(&_reserve);\n\t_btnReserveSnap->setGroup(&_reserve);\n\t_btnReserveAimed->setGroup(&_reserve);\n\t_btnReserveAuto->setGroup(&_reserve);\n\n\t// Set music\n\tif (!Options::oxcePlayBriefingMusicDuringEquipment)\n\t{\n\t\tif (_save->getMusic().empty())\n\t\t{\n\t\t\t_game->getMod()->playMusic(\"GMTACTIC\");\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_game->getMod()->playMusic(_save->getMusic());\n\t\t}\n\t}\n\n\t_animTimer = new Timer(DEFAULT_ANIM_SPEED, true);\n\t_animTimer->onTimer((StateHandler)&BattlescapeState::animate);\n\n\t_gameTimer = new Timer(DEFAULT_ANIM_SPEED, true);\n\t_gameTimer->onTimer((StateHandler)&BattlescapeState::handleState);\n\n\t_battleGame = new BattlescapeGame(_save, this);\n\n\t_barHealthColor = _barHealth->getColor();\n}\n\n\n/**\n * Deletes the battlescapestate.\n */\nBattlescapeState::~BattlescapeState()\n{\n\tdelete _animTimer;\n\tdelete _gameTimer;\n\tdelete _battleGame;\n\n\tresetPalettes();\n}\n\nvoid BattlescapeState::resetPalettes()\n{\n\tif (_paletteResetNeeded)\n\t{\n\t\tfor (auto& origPal : _game->getMod()->getPalettes())\n\t\t{\n\t\t\tif (origPal.first.find(\"PAL_\") == 0)\n\t\t\t{\n\t\t\t\tstd::string backupName = \"BACKUP_\" + origPal.first;\n\t\t\t\tPalette *backupPal = _game->getMod()->getPalette(backupName, false);\n\t\t\t\tif (backupPal)\n\t\t\t\t{\n\t\t\t\t\torigPal.second->copyFrom(backupPal);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t_paletteResetNeeded = false;\n\t}\n}\n\n/**\n * Initializes the battlescapestate.\n */\nvoid BattlescapeState::init()\n{\n\tif (_paletteResetRequested)\n\t{\n\t\t_paletteResetRequested = false;\n\n\t\tresetPalettes();\n\t\t_save->setPaletteByDepth(this);\n\t\tfor (auto* surface : _surfaces)\n\t\t{\n\t\t\tsurface->setPalette(_palette);\n\t\t}\n\t}\n\n\tif (_save->getAmbientSound() != Mod::NO_SOUND)\n\t{\n\t\t_game->getMod()->getSoundByDepth(_save->getDepth(), _save->getAmbientSound())->loop();\n\t\t_game->setVolume(Options::soundVolume, Options::musicVolume, Options::uiVolume);\n\t}\n\n\tState::init();\n\t_animTimer->start();\n\t_gameTimer->start();\n\t_map->setFocus(true);\n\t_map->draw();\n\t_battleGame->init();\n\tupdateSoldierInfo();\n\n\tswitch (_save->getTUReserved())\n\t{\n\tcase BA_SNAPSHOT:\n\t\t_reserve = _btnReserveSnap;\n\t\tbreak;\n\tcase BA_AIMEDSHOT:\n\t\t_reserve = _btnReserveAimed;\n\t\tbreak;\n\tcase BA_AUTOSHOT:\n\t\t_reserve = _btnReserveAuto;\n\t\tbreak;\n\tdefault:\n\t\t_reserve = _btnReserveNone;\n\t\tbreak;\n\t}\n\tif (_firstInit)\n\t{\n\t\t// Set music\n\t\tif (Options::oxcePlayBriefingMusicDuringEquipment)\n\t\t{\n\t\t\tif (_save->getMusic() == \"\")\n\t\t\t{\n\t\t\t\t_game->getMod()->playMusic(\"GMTACTIC\");\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_game->getMod()->playMusic(_save->getMusic());\n\t\t\t}\n\t\t}\n\n\t\tif (!playableUnitSelected())\n\t\t{\n\t\t\tselectNextPlayerUnit();\n\t\t}\n\t\tif (playableUnitSelected())\n\t\t{\n\t\t\t_battleGame->setupCursor();\n\t\t\t_map->getCamera()->centerOnPosition(_save->getSelectedUnit()->getPosition());\n\t\t}\n\t\t_firstInit = false;\n\t\t_btnReserveNone->setGroup(&_reserve);\n\t\t_btnReserveSnap->setGroup(&_reserve);\n\t\t_btnReserveAimed->setGroup(&_reserve);\n\t\t_btnReserveAuto->setGroup(&_reserve);\n\t}\n\t_txtTooltip->setText(\"\");\n\t_btnReserveKneel->toggle(_save->getKneelReserved());\n\t_battleGame->setKneelReserved(_save->getKneelReserved());\n\tif (_autosave > 0 && !_save->isPreview())\n\t{\n\t\tint currentTurn = _autosave;\n\t\t_autosave = 0;\n\t\tif (_game->getSavedGame()->isIronman())\n\t\t{\n\t\t\t_game->pushState(new SaveGameState(OPT_BATTLESCAPE, SAVE_IRONMAN, _palette));\n\t\t}\n\t\telse if (Options::autosave)\n\t\t{\n\t\t\t_game->pushState(new SaveGameState(OPT_BATTLESCAPE, SAVE_AUTO_BATTLESCAPE, _palette, currentTurn));\n\t\t}\n\t}\n}\n\n/**\n * Runs the timers and handles popups.\n */\nvoid BattlescapeState::think()\n{\n\tstatic bool popped = false;\n\n\tif (_gameTimer->isRunning())\n\t{\n\t\tif (_popups.empty())\n\t\t{\n\t\t\tState::think();\n\t\t\tint ret = _battleGame->think();\n\t\t\tif (ret > -1)\n\t\t\t{\n\t\t\t\t_map->refreshAIProgress(100 - ret); // progress = 100 - ret;\n\t\t\t}\n\t\t\t_animTimer->think(this, 0);\n\t\t\t_gameTimer->think(this, 0);\n\t\t\tif (popped)\n\t\t\t{\n\t\t\t\t_battleGame->handleNonTargetAction();\n\t\t\t\tpopped = false;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// Handle popups\n\t\t\t_game->pushState(*_popups.begin());\n\t\t\t_popups.erase(_popups.begin());\n\t\t\tpopped = true;\n\t\t\treturn;\n\t\t}\n\t}\n}\n\n/**\n * Processes any mouse moving over the map.\n * @param action Pointer to an action.\n */\nvoid BattlescapeState::mapOver(Action *action)\n{\n\tif (_isMouseScrolling && action->getDetails()->type == SDL_MOUSEMOTION)\n\t{\n\t\t// The following is the workaround for a rare problem where sometimes\n\t\t// the mouse-release event is missed for any reason.\n\t\t// (checking: is the dragScroll-mouse-button still pressed?)\n\t\t// However if the SDL is also missed the release event, then it is to no avail :(\n\t\tif ((SDL_GetMouseState(0,0)&SDL_BUTTON(Options::battleDragScrollButton)) == 0)\n\t\t{ // so we missed again the mouse-release :(\n\t\t\t// Check if we have to revoke the scrolling, because it was too short in time, so it was a click\n\t\t\tif ((!_mouseMovedOverThreshold) && ((int)(SDL_GetTicks() - _mouseScrollingStartTime) <= (Options::dragScrollTimeTolerance)))\n\t\t\t{\n\t\t\t\t_map->getCamera()->setMapOffset(_mapOffsetBeforeMouseScrolling);\n\t\t\t}\n\t\t\t_isMouseScrolled = _isMouseScrolling = false;\n\t\t\tstopScrolling(action);\n\t\t\treturn;\n\t\t}\n\n\t\t_isMouseScrolled = true;\n\n\t\tif (Options::touchEnabled == false)\n\t\t{\n\t\t\t// Set the mouse cursor back\n\t\t\tSDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);\n\t\t\tSDL_WarpMouse(_game->getScreen()->getWidth() / 2, _game->getScreen()->getHeight() / 2 - _map->getIconHeight() / 2);\n\t\t\tSDL_EventState(SDL_MOUSEMOTION, SDL_ENABLE);\n\t\t}\n\n\t\t// Check the threshold\n\t\t_totalMouseMoveX += action->getDetails()->motion.xrel;\n\t\t_totalMouseMoveY += action->getDetails()->motion.yrel;\n\t\tif (!_mouseMovedOverThreshold)\n\t\t{\n\t\t\t_mouseMovedOverThreshold = ((std::abs(_totalMouseMoveX) > Options::dragScrollPixelTolerance) || (std::abs(_totalMouseMoveY) > Options::dragScrollPixelTolerance));\n\t\t}\n\n\t\t// Scrolling\n\t\tif (Options::battleDragScrollInvert)\n\t\t{\n\t\t\t_map->getCamera()->setMapOffset(_mapOffsetBeforeMouseScrolling);\n\t\t\tint scrollX = -(int)((double)_totalMouseMoveX / action->getXScale());\n\t\t\tint scrollY = -(int)((double)_totalMouseMoveY / action->getYScale());\n\t\t\tPosition delta2 = _map->getCamera()->getMapOffset();\n\t\t\t_map->getCamera()->scrollXY(scrollX, scrollY, true);\n\t\t\tdelta2 = _map->getCamera()->getMapOffset() - delta2;\n\n\t\t\t// Keep the limits...\n\t\t\tif (scrollX != delta2.x || scrollY != delta2.y)\n\t\t\t{\n\t\t\t\t_totalMouseMoveX = -(int) (delta2.x * action->getXScale());\n\t\t\t\t_totalMouseMoveY = -(int) (delta2.y * action->getYScale());\n\t\t\t}\n\n\t\t\tif (Options::touchEnabled == false)\n\t\t\t{\n\t\t\t\taction->getDetails()->motion.x = _xBeforeMouseScrolling;\n\t\t\t\taction->getDetails()->motion.y = _yBeforeMouseScrolling;\n\t\t\t}\n\t\t\t_map->setCursorType(CT_NONE);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tPosition delta = _map->getCamera()->getMapOffset();\n\t\t\t_map->getCamera()->setMapOffset(_mapOffsetBeforeMouseScrolling);\n\t\t\tint scrollX = (int)((double)_totalMouseMoveX / action->getXScale());\n\t\t\tint scrollY = (int)((double)_totalMouseMoveY / action->getYScale());\n\t\t\tPosition delta2 = _map->getCamera()->getMapOffset();\n\t\t\t_map->getCamera()->scrollXY(scrollX, scrollY, true);\n\t\t\tdelta2 = _map->getCamera()->getMapOffset() - delta2;\n\t\t\tdelta = _map->getCamera()->getMapOffset() - delta;\n\n\t\t\t// Keep the limits...\n\t\t\tif (scrollX != delta2.x || scrollY != delta2.y)\n\t\t\t{\n\t\t\t\t_totalMouseMoveX = (int) (delta2.x * action->getXScale());\n\t\t\t\t_totalMouseMoveY = (int) (delta2.y * action->getYScale());\n\t\t\t}\n\n\t\t\tint barWidth = _game->getScreen()->getCursorLeftBlackBand();\n\t\t\tint barHeight = _game->getScreen()->getCursorTopBlackBand();\n\t\t\tint cursorX = _cursorPosition.x + Round(delta.x * action->getXScale());\n\t\t\tint cursorY = _cursorPosition.y + Round(delta.y * action->getYScale());\n\t\t\t_cursorPosition.x = Clamp(cursorX, barWidth, _game->getScreen()->getWidth() - barWidth - (int)(Round(action->getXScale())));\n\t\t\t_cursorPosition.y = Clamp(cursorY, barHeight, _game->getScreen()->getHeight() - barHeight - (int)(Round(action->getYScale())));\n\n\t\t\tif (Options::touchEnabled == false)\n\t\t\t{\n\t\t\t\taction->getDetails()->motion.x = _cursorPosition.x;\n\t\t\t\taction->getDetails()->motion.y = _cursorPosition.y;\n\t\t\t}\n\t\t}\n\n\t\t// We don't want to look the mouse-cursor jumping :)\n\t\t_game->getCursor()->handle(action);\n\t}\n}\n\n/**\n * Processes any presses on the map.\n * @param action Pointer to an action.\n */\nvoid BattlescapeState::mapPress(Action *action)\n{\n\t// don't handle mouseclicks over the buttons (it overlaps with map surface)\n\tif (_mouseOverIcons) return;\n\n\tif (action->getDetails()->button.button == Options::battleDragScrollButton)\n\t{\n\t\t_isMouseScrolling = true;\n\t\t_isMouseScrolled = false;\n\t\tSDL_GetMouseState(&_xBeforeMouseScrolling, &_yBeforeMouseScrolling);\n\t\t_mapOffsetBeforeMouseScrolling = _map->getCamera()->getMapOffset();\n\t\tif (!Options::battleDragScrollInvert && _cursorPosition.z == 0)\n\t\t{\n\t\t\t_cursorPosition.x = action->getDetails()->motion.x;\n\t\t\t_cursorPosition.y = action->getDetails()->motion.y;\n\t\t\t// the Z is irrelevant to our mouse position, but we can use it as a boolean to check if the position is set or not\n\t\t\t_cursorPosition.z = 1;\n\t\t}\n\t\t_totalMouseMoveX = 0; _totalMouseMoveY = 0;\n\t\t_mouseMovedOverThreshold = false;\n\t\t_mouseScrollingStartTime = SDL_GetTicks();\n\t}\n}\n\n/**\n * Processes any clicks on the map to\n * command units.\n * @param action Pointer to an action.\n */\nvoid BattlescapeState::mapClick(Action *action)\n{\n\t// The following is the workaround for a rare problem where sometimes\n\t// the mouse-release event is missed for any reason.\n\t// However if the SDL is also missed the release event, then it is to no avail :(\n\t// (this part handles the release if it is missed and now an other button is used)\n\tif (_isMouseScrolling)\n\t{\n\t\tif (action->getDetails()->button.button != Options::battleDragScrollButton\n\t\t&& (SDL_GetMouseState(0,0)&SDL_BUTTON(Options::battleDragScrollButton)) == 0)\n\t\t{   // so we missed again the mouse-release :(\n\t\t\t// Check if we have to revoke the scrolling, because it was too short in time, so it was a click\n\t\t\tif ((!_mouseMovedOverThreshold) && ((int)(SDL_GetTicks() - _mouseScrollingStartTime) <= (Options::dragScrollTimeTolerance)))\n\t\t\t{\n\t\t\t\t_map->getCamera()->setMapOffset(_mapOffsetBeforeMouseScrolling);\n\t\t\t}\n\t\t\t_isMouseScrolled = _isMouseScrolling = false;\n\t\t\tstopScrolling(action);\n\t\t}\n\t}\n\n\t// DragScroll-Button release: release mouse-scroll-mode\n\tif (_isMouseScrolling)\n\t{\n\t\t// While scrolling, other buttons are ineffective\n\t\tif (action->getDetails()->button.button == Options::battleDragScrollButton)\n\t\t{\n\t\t\t_isMouseScrolling = false;\n\t\t\tstopScrolling(action);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn;\n\t\t}\n\t\t// Check if we have to revoke the scrolling, because it was too short in time, so it was a click\n\t\tif ((!_mouseMovedOverThreshold) && ((int)(SDL_GetTicks() - _mouseScrollingStartTime) <= (Options::dragScrollTimeTolerance)))\n\t\t{\n\t\t\t_isMouseScrolled = false;\n\t\t\tstopScrolling(action);\n\t\t}\n\t\tif (_isMouseScrolled) return;\n\t}\n\n\t// right-click aborts walking state\n\tif (_game->isRightClick(action))\n\t{\n\t\tif (_battleGame->cancelCurrentAction())\n\t\t{\n\t\t\treturn;\n\t\t}\n\t}\n\n\t// don't handle mouseclicks over the buttons (it overlaps with map surface)\n\tif (_mouseOverIcons) return;\n\n\n\t// don't accept leftclicks if there is no cursor or there is an action busy\n\tif (_map->getCursorType() == CT_NONE || _battleGame->isBusy()) return;\n\n\tPosition pos;\n\t_map->getSelectorPosition(&pos);\n\n\tif (_save->getDebugMode())\n\t{\n\t\tstd::ostringstream ss;\n\t\tss << \"Clicked \" << pos;\n\t\tdebug(ss.str());\n\t}\n\n\tif (_save->getTile(pos) != 0) // don't allow to click into void\n\t{\n\t\tif (_game->isRightClick(action, true) && playableUnitSelected())\n\t\t{\n\t\t\t_battleGame->secondaryAction(pos);\n\t\t}\n\t\telse if (_game->isLeftClick(action, true))\n\t\t{\n\t\t\t_battleGame->primaryAction(pos);\n\t\t}\n\t\telse if (_game->isMiddleClick(action, true))\n\t\t{\n\t\t\t_battleGame->cancelCurrentAction();\n\t\t\tBattleUnit *bu = _save->selectUnit(pos);\n\t\t\tif (bu && (bu->getVisible() || _save->getDebugMode()))\n\t\t\t{\n\t\t\t\tif (_save->getDebugMode() && _game->isCtrlPressed())\n\t\t\t\t{\n\t\t\t\t\t// mind probe\n\t\t\t\t\tpopup(new UnitInfoState(bu, this, false, true));\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t_game->pushState(new AlienInventoryState(bu));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Handles mouse entering the map surface.\n * @param action Pointer to an action.\n */\nvoid BattlescapeState::mapIn(Action *)\n{\n\t_isMouseScrolling = false;\n\t_map->setButtonsPressed(Options::battleDragScrollButton, false);\n}\n\n/**\n * Moves the selected unit up.\n * @param action Pointer to an action.\n */\nvoid BattlescapeState::btnUnitUpClick(Action *)\n{\n\tif (playableUnitSelected() && _save->getPathfinding()->validateUpDown(_save->getSelectedUnit(), _save->getSelectedUnit()->getPosition(), Pathfinding::DIR_UP))\n\t{\n\t\t_battleGame->cancelAllActions();\n\t\t_battleGame->moveUpDown(_save->getSelectedUnit(), Pathfinding::DIR_UP);\n\t}\n}\n\n/**\n * Moves the selected unit down.\n * @param action Pointer to an action.\n */\nvoid BattlescapeState::btnUnitDownClick(Action *)\n{\n\tif (playableUnitSelected() && _save->getPathfinding()->validateUpDown(_save->getSelectedUnit(), _save->getSelectedUnit()->getPosition(), Pathfinding::DIR_DOWN))\n\t{\n\t\t_battleGame->cancelAllActions();\n\t\t_battleGame->moveUpDown(_save->getSelectedUnit(), Pathfinding::DIR_DOWN);\n\t}\n}\n\n/**\n * Shows the next map layer.\n * @param action Pointer to an action.\n */\nvoid BattlescapeState::btnMapUpClick(Action *)\n{\n\tif (_save->getSide() == FACTION_PLAYER || _save->getDebugMode())\n\t\t_map->getCamera()->up();\n}\n\n/**\n * Shows the previous map layer.\n * @param action Pointer to an action.\n */\nvoid BattlescapeState::btnMapDownClick(Action *)\n{\n\tif (_save->getSide() == FACTION_PLAYER || _save->getDebugMode())\n\t\t_map->getCamera()->down();\n}\n\n/**\n * Shows the minimap.\n * @param action Pointer to an action.\n */\nvoid BattlescapeState::btnShowMapClick(Action *)\n{\n\t//MiniMapState\n\tif (allowButtons())\n\t\t_game->pushState (new MiniMapState (_map->getCamera(), _save));\n}\n\nvoid BattlescapeState::toggleKneelButton(BattleUnit* unit)\n{\n\tif (_btnKneel->isTFTDMode())\n\t{\n\t\t_btnKneel->toggle(unit && unit->isKneeled());\n\t}\n\telse\n\t{\n\t\t_game->getMod()->getSurfaceSet(\"KneelButton\")->getFrame((unit && unit->isKneeled()) ? 1 : 0)->blitNShade(_btnKneel, 0, 0);\n\t}\n}\n\n/**\n * Toggles the current unit's kneel/standup status.\n * @param action Pointer to an action.\n */\nvoid BattlescapeState::btnKneelClick(Action *)\n{\n\tif (allowButtons())\n\t{\n\t\tBattleUnit *bu = _save->getSelectedUnit();\n\t\tif (bu)\n\t\t{\n\t\t\t_battleGame->kneel(bu);\n\t\t\ttoggleKneelButton(bu);\n\n\t\t\t// update any path preview when unit kneels\n\t\t\tif (_battleGame->getPathfinding()->isPathPreviewed())\n\t\t\t{\n\t\t\t\t_battleGame->getPathfinding()->refreshPath();\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Goes to the soldier info screen.\n * Additionally resets TUs for current side in debug mode.\n * @param action Pointer to an action.\n */\nvoid BattlescapeState::btnInventoryClick(Action *)\n{\n\tif (_save->isPreview())\n\t{\n\t\treturn;\n\t}\n#if 0\n\tif (_save->getDebugMode())\n\t{\n\t\tfor (auto* bi : *_save->getUnits())\n\t\t\tif (bi->getOriginalFaction() == _save->getSide())\n\t\t\t\tbi->prepareNewTurn();\n\t\tupdateSoldierInfo();\n\t}\n#endif\n\tif (playableUnitSelected()\n\t\t&& (_save->getSelectedUnit()->hasInventory() || _save->getDebugMode()))\n\t{\n\t\t_battleGame->cancelAllActions();\n\t\t_game->pushState(new InventoryState(true, this, 0));\n\t}\n}\n\n/**\n * Centers on the currently selected soldier.\n * @param action Pointer to an action.\n */\nvoid BattlescapeState::btnCenterClick(Action *)\n{\n\tif (playableUnitSelected())\n\t{\n\t\t_map->getCamera()->centerOnPosition(_save->getSelectedUnit()->getPosition());\n\t\t_map->refreshSelectorPosition();\n\t}\n}\n\n/**\n * Selects the next soldier.\n * @param action Pointer to an action.\n */\nvoid BattlescapeState::btnNextSoldierClick(Action *action)\n{\n\tif (_game->isRightClick(action, true))\n\t{\n\t\tbtnPrevSoldierClick(action);\n\t\treturn;\n\t}\n\n\tif (allowButtons())\n\t{\n\t\tselectNextPlayerUnit(true, false);\n\t\t_map->refreshSelectorPosition();\n\t}\n}\n\n/**\n * Disables reselection of the current soldier and selects the next soldier.\n * @param action Pointer to an action.\n */\nvoid BattlescapeState::btnNextStopLClick(Action *)\n{\n\tif (allowButtons())\n\t{\n\t\t// vanilla: next by ID + don't reselect\n\t\t_save->setUndoUnit(_save->getSelectedUnit());\n\t\tselectNextPlayerUnit(true, true);\n\t\t_map->refreshSelectorPosition();\n\t}\n}\n\n/**\n * Disables reselection of the current soldier and selects the next soldier (by distance).\n * @param action Pointer to an action.\n */\nvoid BattlescapeState::btnNextStopMClick(Action *)\n{\n\tif (allowButtons())\n\t{\n\t\t// OXCE: next by distance + don't reselect\n\t\t_save->setUndoUnit(_save->getSelectedUnit());\n\t\tselectNextPlayerUnit(true, true, false, true, true);\n\t\t_map->refreshSelectorPosition();\n\t}\n}\n\n/**\n * Selects the previous soldier (last marked as don't reselect).\n * @param action Pointer to an action.\n */\nvoid BattlescapeState::btnNextStopRClick(Action *)\n{\n\tif (allowButtons())\n\t{\n\t\t// OXCE: previous unit (last marked as don't reselect)\n\t\tBattleUnit* candidate = _save->getUndoUnit();\n\t\tif (candidate && candidate->isSelectable(_save->getSide(), false, false))\n\t\t{\n\t\t\tcandidate->allowReselect();\n\t\t\t_save->setSelectedUnit(candidate);\n\t\t\t_save->setUndoUnit(nullptr);\n\n\t\t\tupdateSoldierInfo();\n\t\t\tif (candidate && !_game->isShiftPressed(true)) _map->getCamera()->centerOnPosition(candidate->getPosition());\n\t\t\t_battleGame->cancelAllActions();\n\t\t\t_battleGame->getCurrentAction()->actor = candidate;\n\t\t\t_battleGame->setupCursor();\n\n\t\t\t_map->refreshSelectorPosition();\n\t\t}\n\t}\n}\n\n/**\n * Selects next soldier.\n * @param action Pointer to an action.\n */\nvoid BattlescapeState::btnPrevSoldierClick(Action *)\n{\n\tif (allowButtons())\n\t{\n\t\tselectPreviousPlayerUnit(true);\n\t\t_map->refreshSelectorPosition();\n\t}\n}\n\n/**\n * Selects the next soldier.\n * @param checkReselect When true, don't select a unit that has been previously flagged.\n * @param setReselect When true, flag the current unit first.\n * @param checkInventory When true, don't select a unit that has no inventory.\n */\nvoid BattlescapeState::selectNextPlayerUnit(bool checkReselect, bool setReselect, bool checkInventory, bool checkFOV, bool byDistance)\n{\n\tif (allowButtons())\n\t{\n\t\tBattleUnit *unit = byDistance\n\t\t\t? _save->selectNextPlayerUnitByDistance(checkReselect, setReselect, checkInventory)\n\t\t\t: _save->selectNextPlayerUnit(checkReselect, setReselect, checkInventory);\n\t\tupdateSoldierInfo(checkFOV);\n\t\tif (unit && !_game->isShiftPressed(true)) _map->getCamera()->centerOnPosition(unit->getPosition());\n\t\t_battleGame->cancelAllActions();\n\t\t_battleGame->getCurrentAction()->actor = unit;\n\t\t_battleGame->setupCursor();\n\t}\n}\n\n/**\n * Selects the previous soldier.\n * @param checkReselect When true, don't select a unit that has been previously flagged.\n * @param setReselect When true, flag the current unit first.\n * @param checkInventory When true, don't select a unit that has no inventory.\n */\nvoid BattlescapeState::selectPreviousPlayerUnit(bool checkReselect, bool setReselect, bool checkInventory)\n{\n\tif (allowButtons())\n\t{\n\t\tBattleUnit *unit = _save->selectPreviousPlayerUnit(checkReselect, setReselect, checkInventory);\n\t\tupdateSoldierInfo();\n\t\tif (unit && !_game->isShiftPressed(true)) _map->getCamera()->centerOnPosition(unit->getPosition());\n\t\t_battleGame->cancelAllActions();\n\t\t_battleGame->getCurrentAction()->actor = unit;\n\t\t_battleGame->setupCursor();\n\t}\n}\n\n/**\n * Shows/hides all map layers.\n * @param action Pointer to an action.\n */\nvoid BattlescapeState::btnShowLayersClick(Action *)\n{\n\tif (Options::oxceLinks)\n\t{\n\t\t_game->pushState(new ExtendedBattlescapeLinksState(this, _save));\n\t}\n\telse\n\t{\n\t\tbtnShowLayersClickOrig(nullptr);\n\t}\n}\n\nvoid BattlescapeState::btnShowLayersClickOrig(Action *)\n{\n\t_numLayers->setValue(_map->getCamera()->toggleShowAllLayers());\n}\n\n/**\n * Opens the Ufopaedia.\n * @param action Pointer to an action.\n */\nvoid BattlescapeState::btnUfopaediaClick(Action *)\n{\n\tif (allowButtons())\n\t{\n\t\tUfopaedia::open(_game);\n\t}\n}\n\n/**\n * Shows options.\n * @param action Pointer to an action.\n */\nvoid BattlescapeState::btnHelpClick(Action *)\n{\n\tif (_save->isPreview())\n\t{\n\t\t// Notes for future explorers:\n\t\t// 1. saving makes no sense\n\t\t// 2. loading could be enabled, but needs changes in the Game's _states management; make sure you know what you're doing!\n\t\treturn;\n\t}\n\n\tif (allowButtons(true))\n\t\t_game->pushState(new PauseState(OPT_BATTLESCAPE));\n}\n\n/**\n * Requests the end of turn. This will add a 0 to the end of the state queue,\n * so all ongoing actions, like explosions are finished first before really switching turn.\n * @param action Pointer to an action.\n */\nvoid BattlescapeState::btnEndTurnClick(Action *)\n{\n\tif (allowButtons())\n\t{\n\t\t// Temporarily deactivate the touch buttons at the end of the player's turn\n\t\ttoggleTouchButtons(true, false);\n\n\t\t// PEBCAK\n\t\t_map->getCamera()->stopKeyScrolling();\n\n\t\t_txtTooltip->setText(\"\");\n\t\t_battleGame->requestEndTurn(false);\n\t}\n}\n\n/**\n * Aborts the game.\n * @param action Pointer to an action.\n */\nvoid BattlescapeState::btnAbortClick(Action *)\n{\n\tif (_save->isPreview())\n\t{\n\t\tif (!_save->getCraftForPreview())\n\t\t{\n\t\t\t// base preview\n\t\t\treturn;\n\t\t}\n\t\t// Notes for future explorers:\n\t\t// - there are craft, which can have multiple layouts (one is chosen randomly at the start of a battle)\n\t\t// - these layouts are not forced to be compatible\n\t\t// - thus custom craft deployment for one layout may not be compatible with another layout either\n\t\t// - so instead of having multiple custom deployments per craft, I decided to not support it for such craft at all\n\t\t// - if you want to add partial or full support for it... make sure you don't forget all the corner cases\n\t\tif (_save->getCraftForPreview()->getRules()->getBattlescapeTerrainData()->getMapBlocks()->size() > 1)\n\t\t{\n\t\t\treturn;\n\t\t}\n\t}\n\n\tif (allowButtons())\n\t\t_game->pushState(new AbortMissionState(_save, this));\n}\n\n/**\n * Shows the selected soldier's info.\n * @param action Pointer to an action.\n */\nvoid BattlescapeState::btnStatsClick(Action *action)\n{\n\tif (playableUnitSelected())\n\t{\n\t\tbool scroll = false;\n\t\tif (SCROLL_TRIGGER == Options::battleEdgeScroll &&\n\t\t\tSDL_MOUSEBUTTONUP == action->getDetails()->type && _game->isLeftClick(action))\n\t\t{\n\t\t\tint posX = action->getXMouse();\n\t\t\tint posY = action->getYMouse();\n\t\t\tif ((posX < (Camera::SCROLL_BORDER * action->getXScale()) && posX > 0)\n\t\t\t\t|| (posX > (_map->getWidth() - Camera::SCROLL_BORDER) * action->getXScale())\n\t\t\t\t|| (posY < (Camera::SCROLL_BORDER * action->getYScale()) && posY > 0)\n\t\t\t\t|| (posY > (_map->getHeight() - Camera::SCROLL_BORDER) * action->getYScale()))\n\t\t\t\t// To avoid handling this event as a click\n\t\t\t\t// on the stats button when the mouse is on the scroll-border\n\t\t\t\tscroll = true;\n\t\t}\n\t\tif (!scroll)\n\t\t{\n\t\t\tif (_game->isRightClick(action))\n\t\t\t{\n\t\t\t\t_save->setNameDisplay(!_save->isNameDisplay());\n\t\t\t\tupdateSoldierInfo();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_battleGame->cancelAllActions();\n\t\t\t\tpopup(new UnitInfoState(_save->getSelectedUnit(), this, false, false));\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Shows an action popup menu. When clicked, creates the action.\n * @param action Pointer to an action.\n */\nvoid BattlescapeState::btnLeftHandItemClick(Action *action)\n{\n\tif (playableUnitSelected())\n\t{\n\t\t// concession for touch devices:\n\t\t// click on the item to cancel action, and don't pop up a menu to select a new one\n\t\t// TODO: wrap this in an IFDEF ?\n\t\tif (_battleGame->getCurrentAction()->targeting)\n\t\t{\n\t\t\t_battleGame->cancelCurrentAction();\n\t\t\treturn;\n\t\t}\n\n\t\t_battleGame->cancelCurrentAction();\n\n\t\t_save->getSelectedUnit()->setActiveLeftHand();\n\t\t_map->draw();\n\n\t\tbool rightClick = _game->isRightClick(action, true);\n\t\tif (rightClick)\n\t\t{\n\t\t\tbool isCtrl = _game->isCtrlPressed(true);\n\t\t\t_save->getSelectedUnit()->toggleLeftHandForReactions(isCtrl);\n\t\t\treturn;\n\t\t}\n\n\t\tBattleItem *leftHandItem = _save->getSelectedUnit()->getLeftHandWeapon();\n\t\tif (!leftHandItem)\n\t\t{\n\t\t\tauto typesToCheck = {BT_MELEE, BT_PSIAMP, BT_FIREARM, BT_MEDIKIT, BT_SCANNER, BT_MINDPROBE};\n\t\t\tfor (auto& type : typesToCheck)\n\t\t\t{\n\t\t\t\tleftHandItem = _save->getSelectedUnit()->getSpecialWeapon(type);\n\t\t\t\tif (leftHandItem && leftHandItem->getRules()->isSpecialUsingEmptyHand())\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tleftHandItem = 0;\n\t\t\t}\n\t\t}\n\t\tbool middleClick = _game->isMiddleClick(action, true);\n\t\thandleItemClick(leftHandItem, middleClick);\n\t}\n}\n\n/**\n * Shows an action popup menu. When clicked, create the action.\n * @param action Pointer to an action.\n */\nvoid BattlescapeState::btnRightHandItemClick(Action *action)\n{\n\tif (playableUnitSelected())\n\t{\n\t\t// concession for touch devices:\n\t\t// click on the item to cancel action, and don't pop up a menu to select a new one\n\t\t// TODO: wrap this in an IFDEF ?\n\t\tif (_battleGame->getCurrentAction()->targeting)\n\t\t{\n\t\t\t_battleGame->cancelCurrentAction();\n\t\t\treturn;\n\t\t}\n\n\t\t_battleGame->cancelCurrentAction();\n\n\t\t_save->getSelectedUnit()->setActiveRightHand();\n\t\t_map->draw();\n\n\t\tbool rightClick = _game->isRightClick(action, true);\n\t\tif (rightClick)\n\t\t{\n\t\t\tbool isCtrl = _game->isCtrlPressed(true);\n\t\t\t_save->getSelectedUnit()->toggleRightHandForReactions(isCtrl);\n\t\t\treturn;\n\t\t}\n\n\t\tBattleItem *rightHandItem = _save->getSelectedUnit()->getRightHandWeapon();\n\t\tif (!rightHandItem)\n\t\t{\n\t\t\tauto typesToCheck = {BT_MELEE, BT_PSIAMP, BT_FIREARM, BT_MEDIKIT, BT_SCANNER, BT_MINDPROBE};\n\t\t\tfor (auto& type : typesToCheck)\n\t\t\t{\n\t\t\t\trightHandItem = _save->getSelectedUnit()->getSpecialWeapon(type);\n\t\t\t\tif (rightHandItem && rightHandItem->getRules()->isSpecialUsingEmptyHand())\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\trightHandItem = 0;\n\t\t\t}\n\t\t}\n\t\tbool middleClick = _game->isMiddleClick(action, true);\n\t\thandleItemClick(rightHandItem, middleClick);\n\t}\n}\n\n/**\n * Centers on the unit corresponding to this button.\n * @param action Pointer to an action.\n */\nvoid BattlescapeState::btnVisibleUnitClick(Action *action)\n{\n\tint btnID = -1;\n\n\t// got to find out which button was pressed\n\tfor (int i = 0; i < VISIBLE_MAX && btnID == -1; ++i)\n\t{\n\t\tif (action->getSender() == _btnVisibleUnit[i])\n\t\t{\n\t\t\tbtnID = i;\n\t\t}\n\t}\n\n\tif (btnID != -1 && _game->isRightClick(action, true))\n\t{\n\t\tif (allowButtons())\n\t\t{\n\t\t\tauto* targetUnit = _visibleUnit[btnID];\n\t\t\tstd::vector< std::pair<BattleUnit*, int> > sortSpotters;\n\t\t\tfor (auto* unit : *_save->getUnits())\n\t\t\t{\n\t\t\t\tif (unit->isSelectable(_save->getSide(), false, false) && unit->hasVisibleUnit(targetUnit))\n\t\t\t\t{\n\t\t\t\t\tint tuPercent = unit->getBaseStats()->tu > 0 ? (unit->getTimeUnits() * 100 / unit->getBaseStats()->tu) : 0;\n\t\t\t\t\tsortSpotters.push_back(std::make_pair(unit, tuPercent));\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!sortSpotters.empty())\n\t\t\t{\n\t\t\t\tstd::stable_sort(sortSpotters.begin(), sortSpotters.end(),\n\t\t\t\t\t[](const std::pair<BattleUnit*, int>& a, const std::pair<BattleUnit*, int>& b)\n\t\t\t\t\t{\n\t\t\t\t\t\treturn a.second > b.second;\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t\t// select the first (= with most TU percent left)\n\t\t\t\t_battleGame->cancelAllActions();\n\t\t\t\tPosition position = sortSpotters.front().first->getPosition();\n\t\t\t\t_battleGame->primaryAction(position);\n\t\t\t\t_map->getCamera()->centerOnPosition(position);\n\t\t\t}\n\t\t}\n\t}\n\telse if (btnID != -1)\n\t{\n\t\tPosition position = _visibleUnit[btnID]->getPosition();\n\t\tif (position == TileEngine::invalid)\n\t\t{\n\t\t\tbool found = false;\n\t\t\tfor (auto* unit : *_save->getUnits())\n\t\t\t{\n\t\t\t\tif (!unit->isOut())\n\t\t\t\t{\n\t\t\t\t\tfor (const auto* invItem : *unit->getInventory())\n\t\t\t\t\t{\n\t\t\t\t\t\tif (invItem->getUnit() && invItem->getUnit() == _visibleUnit[btnID])\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tposition = unit->getPosition(); // position of a unit that has the wounded unit in the inventory\n\t\t\t\t\t\t\tfound = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (found) break;\n\t\t\t}\n\t\t}\n\t\t_map->getCamera()->centerOnPosition(position);\n\t}\n\n\taction->getDetails()->type = SDL_NOEVENT; // consume the event\n}\n\n\nvoid BattlescapeState::btnCtrlClick(Action* action)\n{\n\tif (allowButtons())\n\t{\n\t\t_game->toggleCtrlPressedFlag();\n\t\t_btnCtrl->toggle(_game->getCtrlPressedFlag());\n\t}\n\n\taction->getDetails()->type = SDL_NOEVENT; // consume the event\n}\n\nvoid BattlescapeState::btnAltClick(Action* action)\n{\n\tif (allowButtons())\n\t{\n\t\t_game->toggleAltPressedFlag();\n\t\t_btnAlt->toggle(_game->getAltPressedFlag());\n\t}\n\n\taction->getDetails()->type = SDL_NOEVENT; // consume the event\n}\n\nvoid BattlescapeState::btnShiftClick(Action* action)\n{\n\tif (allowButtons())\n\t{\n\t\t_game->toggleShiftPressedFlag();\n\t\t_btnShift->toggle(_game->getShiftPressedFlag());\n\t}\n\n\taction->getDetails()->type = SDL_NOEVENT; // consume the event\n}\n\nvoid BattlescapeState::btnRMBClick(Action* action)\n{\n\tif (allowButtons())\n\t{\n\t\t_game->toggleRMBFlag();\n\t\t_btnRMB->toggle(_game->getRMBFlag());\n\t\tif (_game->getRMBFlag() && _game->getMMBFlag())\n\t\t{\n\t\t\t_game->toggleMMBFlag();\n\t\t\t_btnMMB->toggle(_game->getMMBFlag());\n\t\t}\n\t}\n\n\taction->getDetails()->type = SDL_NOEVENT; // consume the event\n}\n\nvoid BattlescapeState::btnMMBClick(Action* action)\n{\n\tif (allowButtons())\n\t{\n\t\t_game->toggleMMBFlag();\n\t\t_btnMMB->toggle(_game->getMMBFlag());\n\t\tif (_game->getRMBFlag() && _game->getMMBFlag())\n\t\t{\n\t\t\t_game->toggleRMBFlag();\n\t\t\t_btnRMB->toggle(_game->getRMBFlag());\n\t\t}\n\t}\n\n\taction->getDetails()->type = SDL_NOEVENT; // consume the event\n}\n\n/**\n * Toggles touch buttons.\n * @param action Pointer to an action.\n */\nvoid BattlescapeState::btnTouchButtonsClick(Action *)\n{\n\tif (allowButtons())\n\t\ttoggleTouchButtons(false, false);\n}\n\nvoid BattlescapeState::toggleTouchButtons(bool deactivate, bool tryToReactivate)\n{\n\t// Reset touch flags\n\t_game->resetTouchButtonFlags();\n\n\t// Reset touch buttons\n\t_btnCtrl->toggle(_game->getCtrlPressedFlag());\n\t_btnAlt->toggle(_game->getAltPressedFlag());\n\t_btnShift->toggle(_game->getShiftPressedFlag());\n\t_btnRMB->toggle(_game->getRMBFlag());\n\t_btnMMB->toggle(_game->getMMBFlag());\n\n\tif (tryToReactivate)\n\t{\n\t\t_touchButtonsEnabled = Options::oxceBattleTouchButtonsEnabled; // restore\n\t}\n\telse if (deactivate)\n\t{\n\t\tOptions::oxceBattleTouchButtonsEnabled = _touchButtonsEnabled; // backup\n\t\t_touchButtonsEnabled = false;\n\t}\n\telse\n\t{\n\t\t_touchButtonsEnabled = !_touchButtonsEnabled;\n\t\tOptions::oxceBattleTouchButtonsEnabled = _touchButtonsEnabled; // backup\n\t}\n\n\t_btnCtrl->setVisible(_touchButtonsEnabled);\n\t_btnAlt->setVisible(_touchButtonsEnabled);\n\t_btnShift->setVisible(_touchButtonsEnabled);\n\t_btnRMB->setVisible(_touchButtonsEnabled);\n\t_btnMMB->setVisible(_touchButtonsEnabled);\n}\n\n\n/**\n * Launches the blaster bomb.\n * @param action Pointer to an action.\n */\nvoid BattlescapeState::btnLaunchClick(Action *action)\n{\n\t_battleGame->launchAction();\n\taction->getDetails()->type = SDL_NOEVENT; // consume the event\n}\n\n/**\n * Uses psionics.\n * @param action Pointer to an action.\n */\nvoid BattlescapeState::btnPsiClick(Action *action)\n{\n\t_battleGame->psiButtonAction();\n\taction->getDetails()->type = SDL_NOEVENT; // consume the event\n}\n\n/**\n * Shows action menu for special weapons.\n * @param action Pointer to an action.\n */\nvoid BattlescapeState::btnSpecialClick(Action *action)\n{\n\tif (playableUnitSelected())\n\t{\n\t\t// concession for touch devices:\n\t\t// click on the item to cancel action, and don't pop up a menu to select a new one\n\t\t// TODO: wrap this in an IFDEF ?\n\t\tif (_battleGame->getCurrentAction()->targeting)\n\t\t{\n\t\t\t_battleGame->cancelCurrentAction();\n\t\t\treturn;\n\t\t}\n\n\t\t_battleGame->cancelCurrentAction();\n\n\t\tBattleType type;\n\t\tBattleItem *specialItem = _save->getSelectedUnit()->getSpecialIconWeapon(type);\n\t\tif (!specialItem)\n\t\t{\n\t\t\t// Note: this is a hack to access the soldier skills button via the same hotkey as the special weapon button\n\t\t\tif (_btnSkills->getVisible())\n\t\t\t{\n\t\t\t\tbtnSkillsClick(action);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t_map->draw();\n\t\tbool middleClick = _game->isMiddleClick(action, true);\n\t\thandleItemClick(specialItem, middleClick);\n\t}\n\taction->getDetails()->type = SDL_NOEVENT; // consume the event\n}\n\n/**\n * Shows action menu for the skills feature.\n * @param action Pointer to an action.\n */\nvoid BattlescapeState::btnSkillsClick(Action *action)\n{\n\tif (playableUnitSelected() && !_battleGame->isBusy())\n\t{\n\t\tpopup(new SkillMenuState(_battleGame->getCurrentAction(), _icons->getX(), _icons->getY() + 16));\n\t}\n\taction->getDetails()->type = SDL_NOEVENT; // consume the event\n}\n\n/**\n * Reserves time units.\n * @param action Pointer to an action.\n */\nvoid BattlescapeState::btnReserveClick(Action *action)\n{\n\tif (allowButtons())\n\t{\n\t\tSDL_Event ev;\n\t\tev.type = SDL_MOUSEBUTTONDOWN;\n\t\tev.button.button = SDL_BUTTON_LEFT;\n\t\tAction a = Action(&ev, 0.0, 0.0, 0, 0);\n\t\taction->getSender()->mousePress(&a, this);\n\n\t\tif (_reserve == _btnReserveNone)\n\t\t\t_battleGame->setTUReserved(BA_NONE);\n\t\telse if (_reserve == _btnReserveSnap)\n\t\t\t_battleGame->setTUReserved(BA_SNAPSHOT);\n\t\telse if (_reserve == _btnReserveAimed)\n\t\t\t_battleGame->setTUReserved(BA_AIMEDSHOT);\n\t\telse if (_reserve == _btnReserveAuto)\n\t\t\t_battleGame->setTUReserved(BA_AUTOSHOT);\n\n\t\t// update any path preview\n\t\tif (_battleGame->getPathfinding()->isPathPreviewed())\n\t\t{\n\t\t\t_battleGame->getPathfinding()->refreshPath();\n\t\t}\n\t}\n}\n\n/**\n * Reloads the weapon in hand.\n * @param action Pointer to an action.\n */\nvoid BattlescapeState::btnReloadClick(Action *)\n{\n\tif (playableUnitSelected() && _save->getSelectedUnit()->reloadAmmo())\n\t{\n\t\t_game->getMod()->getSoundByDepth(_save->getDepth(), _save->getSelectedUnit()->getReloadSound())->play(-1, getMap()->getSoundAngle(_save->getSelectedUnit()->getPosition()));\n\t\tupdateSoldierInfo();\n\t}\n}\n\n/**\n * Opens the jukebox.\n * @param action Pointer to an action.\n */\nvoid BattlescapeState::btnSelectMusicTrackClick(Action *)\n{\n\tif (allowButtons())\n\t{\n\t\t_game->pushState(new SelectMusicTrackState(SMT_BATTLESCAPE));\n\t}\n}\n\n/**\n * Toggles soldier's personal lighting.\n * @param action Pointer to an action.\n */\nvoid BattlescapeState::btnPersonalLightingClick(Action *)\n{\n\tif (allowButtons())\n\t\t_save->getTileEngine()->togglePersonalLighting();\n}\n\n/**\n * Toggles night vision (purely cosmetic).\n * @param action Pointer to an action.\n */\nvoid BattlescapeState::btnNightVisionClick(Action *action)\n{\n\tif (allowButtons())\n\t\t_map->toggleNightVision();\n}\n\n/**\n * Determines whether a playable unit is selected. Normally only player side units can be selected, but in debug mode one can play with aliens too :)\n * Is used to see if action buttons will work.\n * @return Whether a playable unit is selected.\n */\nbool BattlescapeState::playableUnitSelected()\n{\n\treturn _save->getSelectedUnit() != 0 && allowButtons();\n}\n\n/**\n * Draw hand item with ammo number.\n */\nvoid BattlescapeState::drawItem(BattleItem* item, Surface* hand, std::vector<NumberText*> &ammoText, std::vector<NumberText*> &medikitText, NumberText *twoHandedText, bool drawReactionIndicator, bool drawNoReactionIndicator)\n{\n\thand->clear();\n\tfor (int slot = 0; slot < RuleItem::AmmoSlotMax; ++slot)\n\t{\n\t\tammoText[slot]->setVisible(false);\n\t}\n\tfor (int slot = 0; slot < RuleItem::MedikitSlots; ++slot)\n\t{\n\t\tmedikitText[slot]->setVisible(false);\n\t}\n\ttwoHandedText->setVisible(false);\n\tif (item)\n\t{\n\t\tconst RuleItem *rule = item->getRules();\n\t\trule->drawHandSprite(_game->getMod()->getSurfaceSet(\"BIGOBS.PCK\"), hand, item, _save, _save->getAnimFrame());\n\t\tfor (int slot = 0; slot < RuleItem::AmmoSlotMax; ++slot)\n\t\t{\n\t\t\tif (item->isAmmoVisibleForSlot(slot))\n\t\t\t{\n\t\t\t\tBattleItem* ammo = item->getAmmoForSlot(slot);\n\t\t\t\tif (!ammo)\n\t\t\t\t{\n\t\t\t\t\tammoText[slot]->setVisible(true);\n\t\t\t\t\tammoText[slot]->setValue(0);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tammoText[slot]->setVisible(true);\n\t\t\t\t\tammoText[slot]->setValue(ammo->getAmmoQuantity());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\ttwoHandedText->setVisible(rule->isTwoHanded());\n\t\ttwoHandedText->setColor(rule->isBlockingBothHands() ? _twoHandedRed : _twoHandedGreen);\n\t\tif (rule->getBattleType() == BT_MEDIKIT)\n\t\t{\n\t\t\tmedikitText[0]->setVisible(true);\n\t\t\tmedikitText[0]->setValue(item->getPainKillerQuantity());\n\t\t\tmedikitText[1]->setVisible(true);\n\t\t\tmedikitText[1]->setValue(item->getStimulantQuantity());\n\t\t\tmedikitText[2]->setVisible(true);\n\t\t\tmedikitText[2]->setValue(item->getHealQuantity());\n\t\t}\n\n\t\t// primed grenade indicator (static)\n\t\t/*\n\t\tif (item->getFuseTimer() >= 0)\n\t\t{\n\t\t\tSurface *tempSurface = _game->getMod()->getSurfaceSet(\"SCANG.DAT\")->getFrame(6);\n\t\t\ttempSurface->setX((RuleInventory::HAND_W - rule->getInventoryWidth()) * RuleInventory::SLOT_W / 2);\n\t\t\ttempSurface->setY((RuleInventory::HAND_H - rule->getInventoryHeight()) * RuleInventory::SLOT_H / 2);\n\t\t\ttempSurface->blit(hand);\n\t\t}\n\t\t*/\n\t\t// primed grenade indicator (animated)\n\t\tif (item->getFuseTimer() >= 0)\n\t\t{\n\t\t\tconst int Pulsate[8] = { 0, 1, 2, 3, 4, 3, 2, 1 };\n\t\t\tSurface *tempSurface = _game->getMod()->getSurfaceSet(\"SCANG.DAT\")->getFrame(6);\n\t\t\tint x = (RuleInventory::HAND_W - rule->getInventoryWidth()) * RuleInventory::SLOT_W / 2;\n\t\t\tint y = (RuleInventory::HAND_H - rule->getInventoryHeight()) * RuleInventory::SLOT_H / 2;\n\t\t\ttempSurface->blitNShade(hand, x, y, Pulsate[_save->getAnimFrame() % 8], false, item->isFuseEnabled() ? 0 : 32);\n\t\t}\n\t}\n\tif (drawReactionIndicator)\n\t{\n \t\tif (Surface* reactionIndicator = _game->getMod()->getSurface(\"reactionIndicator\", false))\n\t\t{\n\t\t\treactionIndicator->blitNShade(hand, 0, 0);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tSurface* tempSurface = _game->getMod()->getSurfaceSet(\"SCANG.DAT\")->getFrame(0);\n\t\t\ttempSurface->blitNShade(hand, 28, 0);\n\t\t}\n\t}\n\tif (drawNoReactionIndicator)\n\t{\n\t\tif (Surface* noReactionIndicator = _game->getMod()->getSurface(\"noReactionIndicator\", false))\n\t\t{\n\t\t\tnoReactionIndicator->blitNShade(hand, 0, 0);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tSurface* tempSurface = _game->getMod()->getSurfaceSet(\"SCANG.DAT\")->getFrame(6); // red dot\n\t\t\ttempSurface->blitNShade(hand, 28, 0);\n\t\t}\n\t}\n}\n\n/**\n * Draw both hands sprites.\n */\nvoid BattlescapeState::drawHandsItems()\n{\n\tBattleUnit *battleUnit = _battleGame->playableUnitSelected() ? _save->getSelectedUnit() : nullptr;\n\tbool left = false;\n\tbool right = false;\n\tbool left2 = false;\n\tbool right2 = false;\n\tBattleItem* leftHandItem = nullptr;\n\tBattleItem* rightHandItem = nullptr;\n\tif (battleUnit)\n\t{\n\t\tleft = battleUnit->isLeftHandPreferredForReactions();\n\t\tright = battleUnit->isRightHandPreferredForReactions();\n\t\tleft2 = battleUnit->isLeftHandDisabledForReactions();\n\t\tright2 = battleUnit->isRightHandDisabledForReactions();\n\t\tleftHandItem = battleUnit->getLeftHandWeapon();\n\t\trightHandItem = battleUnit->getRightHandWeapon();\n\t\tif (!leftHandItem || !rightHandItem)\n\t\t{\n\t\t\t// even if both hands are empty, draw the special item just in one hand\n\t\t\tBattleItem** emptyHandItemPtr = leftHandItem ? &rightHandItem : &leftHandItem;\n\t\t\tauto typesToCheck = { BT_MELEE, BT_PSIAMP, BT_FIREARM, BT_MEDIKIT, BT_SCANNER, BT_MINDPROBE };\n\t\t\tfor (auto& type : typesToCheck)\n\t\t\t{\n\t\t\t\t*emptyHandItemPtr = battleUnit->getSpecialWeapon(type);\n\t\t\t\tif (*emptyHandItemPtr && (*emptyHandItemPtr)->getRules()->showSpecialInEmptyHand() && (*emptyHandItemPtr)->getRules()->isSpecialUsingEmptyHand())\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t*emptyHandItemPtr = nullptr;\n\t\t\t}\n\t\t}\n\t}\n\tdrawItem(leftHandItem, _btnLeftHandItem, _numAmmoLeft, _numMedikitLeft, _numTwoHandedIndicatorLeft, left, left2);\n\tdrawItem(rightHandItem, _btnRightHandItem, _numAmmoRight, _numMedikitRight, _numTwoHandedIndicatorRight, right, right2);\n}\n\n/**\n * Updates a soldier's name/rank/tu/energy/health/morale.\n */\nvoid BattlescapeState::updateSoldierInfo(bool checkFOV)\n{\n\tBattleUnit *battleUnit = _save->getSelectedUnit();\n\n\tfor (int i = 0; i < VISIBLE_MAX; ++i)\n\t{\n\t\t_btnVisibleUnit[i]->setVisible(false);\n\t\t_numVisibleUnit[i]->setVisible(false);\n\t\t_visibleUnit[i] = 0;\n\t}\n\n\tbool playableUnit = _battleGame->playableUnitSelected();\n\t_rank->setVisible(playableUnit);\n\t_rankTiny->setVisible(playableUnit);\n\t_numTimeUnits->setVisible(playableUnit);\n\t_barTimeUnits->setVisible(playableUnit);\n\t_barTimeUnits->setVisible(playableUnit);\n\t_numEnergy->setVisible(playableUnit);\n\t_barEnergy->setVisible(playableUnit);\n\t_barEnergy->setVisible(playableUnit);\n\t_numHealth->setVisible(playableUnit);\n\t_barHealth->setVisible(playableUnit);\n\t_barHealth->setVisible(playableUnit);\n\t_numMorale->setVisible(playableUnit);\n\t_barMorale->setVisible(playableUnit);\n\t_barMorale->setVisible(playableUnit);\n\tif (_manaBarVisible)\n\t{\n\t\t_barMana->setVisible(playableUnit);\n\t}\n\t_btnLeftHandItem->setVisible(playableUnit);\n\t_btnRightHandItem->setVisible(playableUnit);\n\n\tdrawHandsItems();\n\n\tif (!playableUnit)\n\t{\n\t\t_txtName->setText(\"\");\n\t\tresetUiButton();\n\t\ttoggleKneelButton(0);\n\t\treturn;\n\t}\n\n\t_txtName->setText(battleUnit->getName(_game->getLanguage(), false));\n\tSoldier *soldier = battleUnit->getGeoscapeSoldier();\n\tif (soldier != 0)\n\t{\n\t\tif (soldier->hasCallsign() && !_save->isNameDisplay())\n\t\t{\n\t\t\t_txtName->setText(soldier->getCallsign());\n\t\t}\n\t\t// presence of custom background determines what should happen\n\t\tSurface *customBg = _game->getMod()->getSurface(\"AvatarBackground\", false);\n\t\tif (customBg == 0)\n\t\t{\n\t\t\t// show rank (vanilla behaviour)\n\t\t\tSurfaceSet *texture = _game->getMod()->getSurfaceSet(\"SMOKE.PCK\");\n\t\t\tauto* frame = texture->getFrame(soldier->getRankSpriteBattlescape());\n\t\t\tif (frame)\n\t\t\t{\n\t\t\t\tframe->blitNShade(_rank, 0, 0);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// show tiny rank (modded)\n\t\t\tSurfaceSet *texture = _game->getMod()->getSurfaceSet(\"TinyRanks\");\n\t\t\tSurface *spr = texture->getFrame(soldier->getRankSpriteTiny());\n\t\t\tif (spr)\n\t\t\t{\n\t\t\t\tspr->blitNShade(_rankTiny, 0, 0);\n\t\t\t}\n\n\t\t\t// use custom background (modded)\n\t\t\tcustomBg->blitNShade(_rank, 0, 0);\n\n\t\t\t// show avatar\n\t\t\tArmor *customArmor = soldier->getArmor();\n\t\t\tif (!soldier->getRules()->getArmorForAvatar().empty())\n\t\t\t{\n\t\t\t\tcustomArmor = _game->getMod()->getArmor(soldier->getRules()->getArmorForAvatar());\n\t\t\t}\n\t\t\tif (customArmor->hasLayersDefinition())\n\t\t\t{\n\t\t\t\tfor (const auto& layer : soldier->getArmorLayers(customArmor))\n\t\t\t\t{\n\t\t\t\t\tSurface* surf = _game->getMod()->getSurface(layer, true);\n\n\t\t\t\t\tSurfaceCrop crop = surf->getCrop();\n\t\t\t\t\tcrop.getCrop()->x = soldier->getRules()->getAvatarOffsetX();\n\t\t\t\t\tcrop.getCrop()->y = soldier->getRules()->getAvatarOffsetY();\n\t\t\t\t\tcrop.getCrop()->w = 26;\n\t\t\t\t\tcrop.getCrop()->h = 23;\n\n\t\t\t\t\tcrop.blit(_rank);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tstd::string look = soldier->getArmor()->getSpriteInventory();\n\t\t\t\tif (!soldier->getRules()->getArmorForAvatar().empty())\n\t\t\t\t{\n\t\t\t\t\tlook = _game->getMod()->getArmor(soldier->getRules()->getArmorForAvatar())->getSpriteInventory();\n\t\t\t\t}\n\t\t\t\tconst std::string gender = soldier->getGender() == GENDER_MALE ? \"M\" : \"F\";\n\t\t\t\tstd::stringstream ss;\n\t\t\t\tSurface *surf = 0;\n\n\t\t\t\tfor (int i = 0; i <= RuleSoldier::LookVariantBits; ++i)\n\t\t\t\t{\n\t\t\t\t\tss.str(\"\");\n\t\t\t\t\tss << look;\n\t\t\t\t\tss << gender;\n\t\t\t\t\tss << (int)soldier->getLook() + (soldier->getLookVariant() & (RuleSoldier::LookVariantMask >> i)) * 4;\n\t\t\t\t\tss << \".SPK\";\n\t\t\t\t\tsurf = _game->getMod()->getSurface(ss.str(), false);\n\t\t\t\t\tif (surf)\n\t\t\t\t\t{\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!surf)\n\t\t\t\t{\n\t\t\t\t\tss.str(\"\");\n\t\t\t\t\tss << look;\n\t\t\t\t\tss << \".SPK\";\n\t\t\t\t\tsurf = _game->getMod()->getSurface(ss.str(), false);\n\t\t\t\t}\n\t\t\t\tif (!surf)\n\t\t\t\t{\n\t\t\t\t\tsurf = _game->getMod()->getSurface(look, true);\n\t\t\t\t}\n\n\t\t\t\t// crop\n\t\t\t\tSurfaceCrop crop = surf->getCrop();\n\t\t\t\tcrop.getCrop()->x = soldier->getRules()->getAvatarOffsetX();\n\t\t\t\tcrop.getCrop()->y = soldier->getRules()->getAvatarOffsetY();\n\t\t\t\tcrop.getCrop()->w = 26;\n\t\t\t\tcrop.getCrop()->h = 23;\n\n\t\t\t\tcrop.blit(_rank);\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\t_rank->clear();\n\t\t_rankTiny->clear();\n\t}\n\t_numTimeUnits->setValue(battleUnit->getTimeUnits());\n\t_barTimeUnits->setMax(battleUnit->getBaseStats()->tu);\n\t_barTimeUnits->setValue(battleUnit->getTimeUnits());\n\t_numEnergy->setValue(battleUnit->getEnergy());\n\t_barEnergy->setMax(battleUnit->getBaseStats()->stamina);\n\t_barEnergy->setValue(battleUnit->getEnergy());\n\t_numHealth->setValue(battleUnit->getHealth());\n\t_barHealth->setMax(battleUnit->getBaseStats()->health);\n\t_barHealth->setValue(battleUnit->getHealth());\n\t_barHealth->setValue2(battleUnit->getStunlevel());\n\t_numMorale->setValue(battleUnit->getMorale());\n\t_barMorale->setMax(100);\n\t_barMorale->setValue(battleUnit->getMorale());\n\tif (_manaBarVisible)\n\t{\n\t\t_barMana->setMax(battleUnit->getBaseStats()->mana);\n\t\t_barMana->setValue(battleUnit->getMana());\n\t}\n\n\ttoggleKneelButton(battleUnit);\n\n\tif (checkFOV)\n\t{\n\t\t_save->getTileEngine()->calculateFOV(_save->getSelectedUnit());\n\t}\n\n\t// go through all units visible to the selected soldier (or other unit, e.g. mind-controlled enemy)\n\tint j = 0;\n\tfor (auto* bu : *battleUnit->getVisibleUnits())\n\t{\n\t\tif (j >= VISIBLE_MAX) break; // loop finished\n\t\t_btnVisibleUnit[j]->setTooltip(_txtVisibleUnitTooltip[j]);\n\t\t_btnVisibleUnit[j]->setVisible(true);\n\t\t_numVisibleUnit[j]->setVisible(true);\n\t\t_visibleUnit[j] = bu;\n\t\t++j;\n\t}\n\n\t// remember where red indicators turn green\n\t_numberOfDirectlyVisibleUnits = j;\n\n\t// go through all units on the map\n\tfor (auto* bu : *_save->getUnits())\n\t{\n\t\tif (j >= VISIBLE_MAX) break; // loop finished\n\t\t// check if they are hostile and visible (by any friendly unit)\n\t\tif (bu->getOriginalFaction() == FACTION_HOSTILE && !bu->isOut() && bu->getVisible())\n\t\t{\n\t\t\tbool alreadyShown = false;\n\t\t\t// check if they are not already shown (e.g. because we see them directly)\n\t\t\tfor (auto* bu2 : *battleUnit->getVisibleUnits())\n\t\t\t{\n\t\t\t\tif (bu->getId() == bu2->getId())\n\t\t\t\t{\n\t\t\t\t\talreadyShown = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!alreadyShown)\n\t\t\t{\n\t\t\t\t_btnVisibleUnit[j]->setTooltip(_txtVisibleUnitTooltip[j]);\n\t\t\t\t_btnVisibleUnit[j]->setVisible(true);\n\t\t\t\t_numVisibleUnit[j]->setVisible(true);\n\t\t\t\t_visibleUnit[j] = bu;\n\t\t\t\t++j;\n\t\t\t}\n\t\t}\n\t}\n\n\t// remember where green indicators turn blue\n\t_numberOfEnemiesTotal = j;\n\n\t{\n\t\t// go through all wounded units under player's control (incl. unconscious)\n\t\tfor (auto* bu : *_save->getUnits())\n\t\t{\n\t\t\tif (j >= VISIBLE_MAX) break; // loop finished\n\t\t\tif (bu->getFaction() == FACTION_PLAYER && bu->getStatus() != STATUS_DEAD && !bu->isIgnored() && bu->indicatorsAreEnabled())\n\t\t\t{\n\t\t\t\tif (bu->getFatalWounds() > 0 || (Options::oxceShowBurningAsWounded && bu->getFire() > 0))\n\t\t\t\t{\n\t\t\t\t\t_btnVisibleUnit[j]->setTooltip(_txtVisibleUnitTooltip[VISIBLE_MAX]);\n\t\t\t\t\t_btnVisibleUnit[j]->setVisible(true);\n\t\t\t\t\t_numVisibleUnit[j]->setVisible(true);\n\t\t\t\t\t_visibleUnit[j] = bu;\n\t\t\t\t\t++j;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// remember where blue indicators turn purple\n\t_numberOfEnemiesTotalPlusWounded = j;\n\n\t{\n\t\t// first show all stunned allies with negative health regen (usually caused by high stun level)\n\t\tfor (auto* bu : *_save->getUnits())\n\t\t{\n\t\t\tif (j >= VISIBLE_MAX) break; // loop finished\n\t\t\tif (bu->getOriginalFaction() == FACTION_PLAYER && bu->getStatus() == STATUS_UNCONSCIOUS && bu->hasNegativeHealthRegen() && bu->indicatorsAreEnabled())\n\t\t\t{\n\t\t\t\t_btnVisibleUnit[j]->setTooltip(_txtVisibleUnitTooltip[VISIBLE_MAX + 1]);\n\t\t\t\t_btnVisibleUnit[j]->setVisible(true);\n\t\t\t\t_numVisibleUnit[j]->setVisible(true);\n\t\t\t\t_visibleUnit[j] = bu;\n\t\t\t\t++j;\n\t\t\t}\n\t\t}\n\n\t\t// then show all standing units under player's control with high stun level\n\t\tfor (auto* bu : *_save->getUnits())\n\t\t{\n\t\t\tif (j >= VISIBLE_MAX) break; // loop finished\n\t\t\tif (bu->getFaction() == FACTION_PLAYER && !(bu->isOut()) && bu->getHealth() > 0 && bu->indicatorsAreEnabled())\n\t\t\t{\n\t\t\t\tif (bu->getStunlevel() * 100 / bu->getHealth() >= 75)\n\t\t\t\t{\n\t\t\t\t\t_btnVisibleUnit[j]->setTooltip(_txtVisibleUnitTooltip[VISIBLE_MAX+1]);\n\t\t\t\t\t_btnVisibleUnit[j]->setVisible(true);\n\t\t\t\t\t_numVisibleUnit[j]->setVisible(true);\n\t\t\t\t\t_visibleUnit[j] = bu;\n\t\t\t\t\t++j;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tupdateUiButton(battleUnit);\n}\n\nvoid BattlescapeState::updateUiButton(const BattleUnit *battleUnit)\n{\n\tBattleItem *psiWeapon = battleUnit->getSpecialWeapon(BT_PSIAMP);\n\n\tBattleType type = BT_NONE;\n\tBattleItem *specialWeapon = battleUnit->getSpecialIconWeapon(type); // updates type!\n\tbool hasSpecialWeapon = specialWeapon && type != BT_NONE && type != BT_AMMO && type != BT_GRENADE && type != BT_PROXIMITYGRENADE && type != BT_FLARE && type != BT_CORPSE;\n\n\t// if we have psi amp with icon then it will show one button only, but if we have two psi amps and one with icon is second (this is important) then we will show both buttons.\n\tbool hasPsiWeapon = psiWeapon != 0 && psiWeapon != specialWeapon;\n\n\tbool hasSkills = battleUnit->getGeoscapeSoldier() && battleUnit->skillMenuCheck();\n\n\tresetUiButton();\n\n\tint offset = 0;\n\tauto show = [&](BattlescapeButton* btn, int spriteIndex)\n\t{\n\t\tif (offset < SPECIAL_BUTTONS_MAX)\n\t\t{\n\t\t\t_game->getMod()->getSurfaceSet(\"SPICONS.DAT\")->getFrame(spriteIndex)->blitNShade(btn, 0, 0);\n\t\t\tbtn->setVisible(true);\n\t\t\tbtn->setX(_posSpecialActions[offset]);\n\t\t\t++offset;\n\t\t}\n\t};\n\n\n\tif (hasSpecialWeapon)\n\t{\n\t\tshow(_btnSpecial, specialWeapon->getRules()->getSpecialIconSprite());\n\t}\n\tif (hasSkills)\n\t{\n\t\tshow(_btnSkills, battleUnit->getGeoscapeSoldier()->getRules()->getSkillIconSprite());\n\t}\n\tif (hasPsiWeapon)\n\t{\n\t\tbool canUsePsiWeapon = (psiWeapon->getRules()->getCostPanic().Time > 0) || (psiWeapon->getRules()->getCostUse().Time > 0);\n\t\tif (canUsePsiWeapon)\n\t\t{\n\t\t\tshow(_btnPsi, 1);\n\t\t}\n\t}\n}\n\nvoid BattlescapeState::resetUiButton()\n{\n\tBattlescapeButton* btns[] = {\n\t\t_btnPsi,\n\t\t_btnSkills,\n\t\t_btnSpecial,\n\t};\n\n\tfor (auto* btn : btns)\n\t{\n\t\tbtn->setVisible(false);\n\t\tbtn->setX(_posSpecialActions[0]);\n\t}\n}\n\n/**\n * Shifts the red colors of the visible unit buttons backgrounds.\n */\nvoid BattlescapeState::blinkVisibleUnitButtons()\n{\n\tstatic int delta = 1, color = 32;\n\n\tfor (int i = 0; i < VISIBLE_MAX;  ++i)\n\t{\n\t\tif (_btnVisibleUnit[i]->getVisible() == true)\n\t\t{\n\t\t\t_btnVisibleUnit[i]->drawRect(0, 0, 15, 12, 15);\n\t\t\tint bgColor = i < _numberOfDirectlyVisibleUnits ? color : i < _numberOfEnemiesTotal ? _indicatorGreen : i < _numberOfEnemiesTotalPlusWounded ? _indicatorBlue : _indicatorPurple;\n\t\t\t_btnVisibleUnit[i]->drawRect(1, 1, 13, 10, bgColor);\n\t\t}\n\t}\n\n\tif (color == 44) delta = -2;\n\tif (color == 32) delta = 1;\n\n\tcolor += delta;\n}\n\n/**\n * Shifts the colors of the health bar when unit has fatal wounds.\n */\nvoid BattlescapeState::blinkHealthBar()\n{\n\tstatic Uint8 color = 0, maxcolor = 3, step = 0;\n\n\tstep = 1 - step;\t// 1, 0, 1, 0, ...\n\tBattleUnit *bu = _save->getSelectedUnit();\n\tif (step == 0 || bu == 0 || !_barHealth->getVisible()) return;\n\n\tif (++color > maxcolor) color = maxcolor - 3;\n\n\tfor (int i = 0; i < BODYPART_MAX; i++)\n\t{\n\t\tif (bu->getFatalWound((UnitBodyPart)i) > 0)\n\t\t{\n\t\t\t_barHealth->setColor(_barHealthColor + color);\n\t\t\treturn;\n\t\t}\n\t}\n\tif (_barHealth->getColor() != _barHealthColor) // avoid redrawing if we don't have to\n\t\t_barHealth->setColor(_barHealthColor);\n}\n\n/**\n * Popups a context sensitive list of actions the user can choose from.\n * Some actions result in a change of gamestate.\n * @param item Item the user clicked on (righthand/lefthand)\n * @param middleClick was it a middle click?\n */\nvoid BattlescapeState::handleItemClick(BattleItem *item, bool middleClick)\n{\n\t// make sure there is an item, and the battlescape is in an idle state\n\tif (item && !_battleGame->isBusy())\n\t{\n\t\tif (middleClick)\n\t\t{\n\t\t\tstd::string articleId = item->getRules()->getUfopediaType();\n\t\t\tUfopaedia::openArticle(_game, articleId);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_battleGame->getCurrentAction()->weapon = item;\n\t\t\tpopup(new ActionMenuState(_battleGame->getCurrentAction(), _icons->getX(), _icons->getY() + 16));\n\t\t\tif (item->getRules()->getBattleType() == BT_FIREARM)\n\t\t\t{\n\t\t\t\t_battleGame->playUnitResponseSound(_battleGame->getCurrentAction()->actor, 2); // \"select weapon\" sound\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Animates map objects on the map, also smoke,fire, ...\n */\nvoid BattlescapeState::animate()\n{\n\t_map->animate(!_battleGame->isBusy());\n\n\tblinkVisibleUnitButtons();\n\tblinkHealthBar();\n\n\tif (!_map->getProjectile())\n\t{\n\t\tdrawHandsItems();\n\t}\n}\n\n/**\n * Handles the battle game state.\n */\nvoid BattlescapeState::handleState()\n{\n\t_battleGame->handleState();\n}\n\n/**\n * Sets the timer interval for think() calls of the state.\n * @param interval An interval in ms.\n */\nvoid BattlescapeState::setStateInterval(Uint32 interval)\n{\n\t_gameTimer->setInterval(interval);\n}\n\n/**\n * Gets pointer to the game. Some states need this info.\n * @return Pointer to game.\n */\nGame *BattlescapeState::getGame() const\n{\n\treturn _game;\n}\n\n/**\n * Gets pointer to the map. Some states need this info.\n * @return Pointer to map.\n */\nMap *BattlescapeState::getMap() const\n{\n\treturn _map;\n}\n\n/**\n * Shows a debug message in the topleft corner.\n * @param message Debug message.\n */\nvoid BattlescapeState::debug(const std::string &message)\n{\n\tif (_save->getDebugMode())\n\t{\n\t\t_txtDebug->setText(message);\n\t}\n}\n\n/**\n* Shows a bug hunt message in the topleft corner.\n*/\nvoid BattlescapeState::bugHuntMessage()\n{\n\tif (_save->getBughuntMode())\n\t{\n\t\t_txtDebug->setText(tr(\"STR_BUG_HUNT_ACTIVATED\"));\n\t}\n}\n\n/**\n * Shows a warning message.\n * @param message Warning message.\n */\nvoid BattlescapeState::warning(const std::string &message)\n{\n\t_warning->showMessage(tr(message));\n}\n\n/**\n * Shows a warning message without automatic translation.\n * @param message Warning message.\n */\nvoid BattlescapeState::warningRaw(const std::string &message)\n{\n\t_warning->showMessage(message);\n}\n\n/**\n * Shows a warning message without automatic translation.\n * @param message Warning message.\n */\nvoid BattlescapeState::warningLongRaw(const std::string &message)\n{\n\t_warning->showMessage(message, 8);\n}\n\n/**\n * Gets melee damage preview.\n * @param actor Selected unit.\n * @param weapon Weapon to use for calculation.\n */\nstd::string BattlescapeState::getMeleeDamagePreview(BattleUnit *actor, BattleItem *weapon) const\n{\n\tif (!weapon)\n\t\treturn \"\";\n\n\tbool discovered = false;\n\tif (_game->getSavedGame()->getMonthsPassed() == -1)\n\t{\n\t\tdiscovered = true; // new battle mode\n\t}\n\telse\n\t{\n\t\tArticleDefinition *article = _game->getMod()->getUfopaediaArticle(weapon->getRules()->getType(), false);\n\t\tif (article && Ufopaedia::isArticleAvailable(_game->getSavedGame(), article))\n\t\t{\n\t\t\tdiscovered = true; // pedia article unlocked\n\t\t}\n\t}\n\n\tstd::ostringstream ss;\n\tif (discovered)\n\t{\n\t\tint totalDamage = 0;\n\t\tconst RuleDamageType *dmgType;\n\t\tBattleActionAttack attack = BattleActionAttack::GetBeforeShoot(BA_HIT, actor, weapon);\n\t\tif (weapon->getRules()->getBattleType() == BT_MELEE)\n\t\t{\n\t\t\ttotalDamage += weapon->getRules()->getPowerBonus(attack);\n\t\t\tdmgType = weapon->getRules()->getDamageType();\n\t\t}\n\t\telse\n\t\t{\n\t\t\ttotalDamage += weapon->getRules()->getMeleeBonus(attack);\n\t\t\tdmgType = weapon->getRules()->getMeleeType();\n\t\t}\n\n\t\tss << tr(weapon->getRules()->getType());\n\t\tss << \"\\n\";\n\t\tss << dmgType->getRandomDamage(totalDamage, 1);\n\t\tss << \"-\";\n\t\tss << dmgType->getRandomDamage(totalDamage, 2);\n\t\tif (dmgType->RandomType == DRT_UFO_WITH_TWO_DICE)\n\t\t\tss << \"*\";\n\t}\n\telse\n\t{\n\t\tss << tr(weapon->getRules()->getType());\n\t\tss << \"\\n?-?\";\n\t}\n\n\treturn ss.str();\n}\n\n/**\n * Takes care of any events from the core game engine.\n * @param action Pointer to an action.\n */\ninline void BattlescapeState::handle(Action *action)\n{\n\tif (!_firstInit)\n\t{\n\t\tif (_game->getCursor()->getVisible() || ((action->getDetails()->type == SDL_MOUSEBUTTONDOWN || action->getDetails()->type == SDL_MOUSEBUTTONUP) && _game->isRightClick(action)))\n\t\t{\n\t\t\tState::handle(action);\n\n\t\t\tif (Options::touchEnabled == false && _isMouseScrolling && !Options::battleDragScrollInvert)\n\t\t\t{\n\t\t\t\t_map->setSelectorPosition((_cursorPosition.x - _game->getScreen()->getCursorLeftBlackBand()) / action->getXScale(), (_cursorPosition.y - _game->getScreen()->getCursorTopBlackBand()) / action->getYScale());\n\t\t\t}\n\n\t\t\tif (Options::oxceThumbButtons && action->getDetails()->type == SDL_MOUSEBUTTONDOWN)\n\t\t\t{\n\t\t\t\tif (action->getDetails()->button.button == SDL_BUTTON_X1)\n\t\t\t\t{\n\t\t\t\t\tbtnNextSoldierClick(action);\n\t\t\t\t}\n\t\t\t\telse if (action->getDetails()->button.button == SDL_BUTTON_X2)\n\t\t\t\t{\n\t\t\t\t\tbtnPrevSoldierClick(action);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (action->getDetails()->type == SDL_KEYDOWN)\n\t\t\t{\n\t\t\t\tSDLKey key = action->getDetails()->key.keysym.sym;\n\t\t\t\tbool ctrlPressed = _game->isCtrlPressed();\n\t\t\t\tbool shiftPressed = _game->isShiftPressed();\n\t\t\t\tbool altPressed = _game->isAltPressed();\n\n\t\t\t\t// \"shift-hotkey\" - select without centering\n\t\t\t\tif (shiftPressed)\n\t\t\t\t{\n\t\t\t\t\tif (key == Options::keyBattleNextUnit)\n\t\t\t\t\t{\n\t\t\t\t\t\tbtnNextSoldierClick(action);\n\t\t\t\t\t}\n\t\t\t\t\telse if (key == Options::keyBattlePrevUnit)\n\t\t\t\t\t{\n\t\t\t\t\t\tbtnPrevSoldierClick(action);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// \"ctrl-b\" - reopen briefing\n\t\t\t\tif (key == SDLK_b && ctrlPressed)\n\t\t\t\t{\n\t\t\t\t\tCraft* ycraft = nullptr;\n\t\t\t\t\tfor (auto* xbase : *_game->getSavedGame()->getBases())\n\t\t\t\t\t{\n\t\t\t\t\t\tfor (auto* xcraft : *xbase->getCrafts())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (xcraft->isInBattlescape())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tycraft = xcraft;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (ycraft) break;\n\t\t\t\t\t}\n\n\t\t\t\t\t_game->pushState(new BriefingState(ycraft, 0, true));\n\t\t\t\t}\n\t\t\t\t// \"ctrl-c\" - camera: toggle show single map level\n\t\t\t\telse if (key == SDLK_c && ctrlPressed)\n\t\t\t\t{\n\t\t\t\t\t_map->getCamera()->toggleShowSingleLayer();\n\n\t\t\t\t\tif (_map->getCamera()->getShowSingleLayer())\n\t\t\t\t\t\twarningLongRaw(tr(\"STR_SINGLE_MAP_LAYER_ACTIVATED\"));\n\t\t\t\t\telse\n\t\t\t\t\t\twarning(\"STR_SINGLE_MAP_LAYER_DEACTIVATED\");\n\t\t\t\t}\n\t\t\t\t// \"ctrl-f\" - show fatal wounds\n\t\t\t\telse if (key == SDLK_f && ctrlPressed)\n\t\t\t\t{\n\t\t\t\t\tif (_save->getSide() == FACTION_PLAYER)\n\t\t\t\t\t{\n\t\t\t\t\t\tauto* bu = _save->getSelectedUnit();\n\t\t\t\t\t\tif (bu)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tstd::ostringstream ss;\n\t\t\t\t\t\t\tss << tr(\"STR_FATAL_WOUNDS\");\n\t\t\t\t\t\t\tss << \"\\n\";\n\t\t\t\t\t\t\tfor (int i = 0; i < BODYPART_MAX; ++i)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (bu->getFatalWound((UnitBodyPart)i))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tss << \"\\n\";\n\t\t\t\t\t\t\t\t\tss << _game->getLanguage()->getString(PARTS_STRING[i]);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t_game->pushState(new InfoboxState(ss.str()));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// \"ctrl-h\" - show hit log\n\t\t\t\telse if (key == SDLK_h && ctrlPressed)\n\t\t\t\t{\n\t\t\t\t\tif (_save->getSide() == FACTION_PLAYER)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (Options::oxceDisableHitLog)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_game->pushState(new InfoboxState(tr(\"STR_THIS_FEATURE_IS_DISABLED_4\")));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (altPressed)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// turn diary\n\t\t\t\t\t\t\t_game->pushState(new TurnDiaryState(_save->getHitLog()));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// hit log\n\t\t\t\t\t\t\tstd::string hitLogText = _save->getHitLog()->getHitLogText();\n\t\t\t\t\t\t\tif (!hitLogText.empty())\n\t\t\t\t\t\t\t\t_game->pushState(new InfoboxState(hitLogText));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// \"ctrl-Home\" - reset default palettes\n\t\t\t\telse if (key == SDLK_HOME && ctrlPressed)\n\t\t\t\t{\n\t\t\t\t\t_paletteResetRequested = true;\n\t\t\t\t\tinit();\n\t\t\t\t}\n\t\t\t\t// \"ctrl-End\" - toggle between various debug vision/brightness modes\n\t\t\t\telse if (key == SDLK_END && ctrlPressed)\n\t\t\t\t{\n\t\t\t\t\t_map->toggleDebugVisionMode();\n\t\t\t\t}\n\t\t\t\t// \"ctrl-shift-Del\" - clear TUs for all allied units\n\t\t\t\telse if (key == SDLK_DELETE && ctrlPressed && shiftPressed)\n\t\t\t\t{\n\t\t\t\t\tfor (auto* bu : *_save->getUnits())\n\t\t\t\t\t{\n\t\t\t\t\t\tif (bu->getFaction() == _save->getSide() && !bu->isOut())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tbu->clearTimeUnits();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tupdateSoldierInfo();\n\t\t\t\t}\n\t\t\t\t// \"ctrl-s\" - switch xcom unit speed to max and back\n\t\t\t\telse if (key == SDLK_s && ctrlPressed)\n\t\t\t\t{\n\t\t\t\t\tif (_save->getSide() == FACTION_PLAYER)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (Options::battleXcomSpeedOrig >= 1 && Options::battleXcomSpeedOrig <= 40)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tOptions::battleXcomSpeed = Options::battleXcomSpeedOrig;\n\t\t\t\t\t\t\tOptions::battleXcomSpeedOrig = -1;\n\t\t\t\t\t\t\twarning(\"STR_QUICK_MODE_DEACTIVATED\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tOptions::battleXcomSpeedOrig = Options::battleXcomSpeed;\n\t\t\t\t\t\t\tOptions::battleXcomSpeed = 1;\n\t\t\t\t\t\t\twarningLongRaw(tr(\"STR_QUICK_MODE_ACTIVATED\"));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tif (Options::battleAlienSpeedOrig >= 1 && Options::battleAlienSpeedOrig <= 40)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tOptions::battleAlienSpeed = Options::battleAlienSpeedOrig;\n\t\t\t\t\t\t\tOptions::battleAlienSpeedOrig = -1;\n\t\t\t\t\t\t\twarning(\"STR_QUICK_MODE_DEACTIVATED\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tOptions::battleAlienSpeedOrig = Options::battleAlienSpeed;\n\t\t\t\t\t\t\tOptions::battleAlienSpeed = 1;\n\t\t\t\t\t\t\twarning(\"STR_QUICK_MODE_ACTIVATED\");\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// \"ctrl-x\" - mute/unmute unit response sounds\n\t\t\t\telse if (key == SDLK_x && ctrlPressed)\n\t\t\t\t{\n\t\t\t\t\tif (_game->getMod()->getEnableUnitResponseSounds())\n\t\t\t\t\t{\n\t\t\t\t\t\tOptions::oxceEnableUnitResponseSounds = !Options::oxceEnableUnitResponseSounds;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// \"ctrl-e\" - experience log\n\t\t\t\telse if (key == SDLK_e && ctrlPressed)\n\t\t\t\t{\n\t\t\t\t\tif (altPressed)\n\t\t\t\t\t{\n\t\t\t\t\t\t_game->pushState(new NoExperienceState());\n\t\t\t\t\t}\n\t\t\t\t\telse if (shiftPressed)\n\t\t\t\t\t{\n\t\t\t\t\t\t_game->pushState(new ExperienceOverviewState(this));\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tstd::ostringstream ss;\n\t\t\t\t\t\tss << tr(\"STR_NO_EXPERIENCE_YET\");\n\t\t\t\t\t\tss << \"\\n\\n\";\n\t\t\t\t\t\tbool first = true;\n\t\t\t\t\t\tfor (auto* bu : *_save->getUnits())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (bu->getOriginalFaction() == FACTION_PLAYER && !bu->isOut())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (bu->getGeoscapeSoldier() && !bu->hasGainedAnyExperience())\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tif (!first) ss << \", \";\n\t\t\t\t\t\t\t\t\tif (bu == _save->getSelectedUnit())\n\t\t\t\t\t\t\t\t\t\tss << Unicode::TOK_COLOR_FLIP << bu->getName(_game->getLanguage()) << Unicode::TOK_COLOR_FLIP;\n\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\tss << bu->getName(_game->getLanguage());\n\t\t\t\t\t\t\t\t\tfirst = false;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t_game->pushState(new InfoboxState(ss.str()));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// \"alt-c\" - custom marker\n\t\t\t\telse if (key == SDLK_c && altPressed)\n\t\t\t\t{\n\t\t\t\t\tBattleUnit* unitUnderTheCursor = nullptr;\n\t\t\t\t\t{\n\t\t\t\t\t\tPosition newPos;\n\t\t\t\t\t\t_map->getSelectorPosition(&newPos);\n\t\t\t\t\t\tTile* tile = _save->getTile(newPos);\n\t\t\t\t\t\tif (tile)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tunitUnderTheCursor = tile->getOverlappingUnit(_save);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t// mark a friendly unit under the cursor\n\t\t\t\t\tif (unitUnderTheCursor && unitUnderTheCursor->getFaction() == FACTION_PLAYER && !unitUnderTheCursor->isOut())\n\t\t\t\t\t{\n\t\t\t\t\t\tunitUnderTheCursor->setCustomMarker((unitUnderTheCursor->getCustomMarker() + 1) % 5); // rotate 4 colors + turned off\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// \"ctrl-m\" - melee damage preview\n\t\t\t\telse if (key == SDLK_m && ctrlPressed)\n\t\t\t\t{\n\t\t\t\t\tBattleUnit *actor = _save->getSelectedUnit();\n\t\t\t\t\tif (actor)\n\t\t\t\t\t{\n\t\t\t\t\t\tBattleItem *leftWeapon = actor->getLeftHandWeapon();\n\n\t\t\t\t\t\tBattleItem *rightWeapon = actor->getRightHandWeapon();\n\n\t\t\t\t\t\tBattleItem *specialWeapon = 0;\n\t\t\t\t\t\tauto typesToCheck = {BT_MELEE, BT_PSIAMP, BT_FIREARM, BT_MEDIKIT, BT_SCANNER, BT_MINDPROBE};\n\t\t\t\t\t\tfor (auto& type : typesToCheck)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tspecialWeapon = actor->getSpecialWeapon(type);\n\t\t\t\t\t\t\tif (specialWeapon && specialWeapon->getRules()->isSpecialUsingEmptyHand())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tspecialWeapon = 0;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tBattleType type;\n\t\t\t\t\t\tBattleItem *anotherSpecialWeapon = actor->getSpecialIconWeapon(type);\n\t\t\t\t\t\tif (anotherSpecialWeapon && anotherSpecialWeapon == specialWeapon)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tanotherSpecialWeapon = 0;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tstd::ostringstream ss;\n\t\t\t\t\t\tbool first = true;\n\t\t\t\t\t\tif (leftWeapon)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tss << getMeleeDamagePreview(actor, leftWeapon);\n\t\t\t\t\t\t\tfirst = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (rightWeapon)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (!first) ss << \"\\n\\n\";\n\t\t\t\t\t\t\tss << getMeleeDamagePreview(actor, rightWeapon);\n\t\t\t\t\t\t\tfirst = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (specialWeapon)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (!first) ss << \"\\n\\n\";\n\t\t\t\t\t\t\tss << getMeleeDamagePreview(actor, specialWeapon);\n\t\t\t\t\t\t\tfirst = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (anotherSpecialWeapon)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (!first) ss << \"\\n\\n\";\n\t\t\t\t\t\t\tss << getMeleeDamagePreview(actor, anotherSpecialWeapon);\n\t\t\t\t\t\t\tfirst = false;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t_game->pushState(new InfoboxState(ss.str()));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// \"ctrl-w\" - warp unit\n\t\t\t\telse if ((_save->getDebugMode() || _save->isPreview()) && key == SDLK_w && ctrlPressed)\n\t\t\t\t{\n\t\t\t\t\tBattleUnit *unit = _save->getSelectedUnit();\n\t\t\t\t\tif (unit)\n\t\t\t\t\t{\n\t\t\t\t\t\tPosition newPos;\n\t\t\t\t\t\t_map->getSelectorPosition(&newPos);\n\t\t\t\t\t\tif (_save->getTileEngine()->isPositionValidForUnit(newPos, unit))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tdebug(\"Beam me up Scotty\");\n\t\t\t\t\t\t\t_save->getPathfinding()->removePreview();\n\n\t\t\t\t\t\t\tunit->setTile(_save->getTile(newPos), _save);\n\t\t\t\t\t\t\tunit->setPosition(newPos);\n\n\t\t\t\t\t\t\t//free refresh as bonus\n\t\t\t\t\t\t\tunit->updateUnitStats(true, false);\n\t\t\t\t\t\t\t_save->getTileEngine()->calculateLighting(LL_UNITS);\n\t\t\t\t\t\t\t_battleGame->handleState();\n\t\t\t\t\t\t\tupdateSoldierInfo(true);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (Options::debug)\n\t\t\t\t{\n\t\t\t\t\t// \"ctrl-d\" - enable debug mode\n\t\t\t\t\tif (key == SDLK_d && ctrlPressed)\n\t\t\t\t\t{\n\t\t\t\t\t\t_save->setDebugMode();\n\t\t\t\t\t\tdebug(\"Debug Mode\");\n\t\t\t\t\t}\n\t\t\t\t\t// \"ctrl-v\" - reset tile visibility\n\t\t\t\t\telse if (_save->getDebugMode() && key == SDLK_v && ctrlPressed)\n\t\t\t\t\t{\n\t\t\t\t\t\tdebug(\"Resetting tile visibility\");\n\t\t\t\t\t\t_save->resetTiles();\n\t\t\t\t\t}\n\t\t\t\t\telse if (_save->getDebugMode() && (key == SDLK_k || key == SDLK_j) && ctrlPressed)\n\t\t\t\t\t{\n\t\t\t\t\t\tbool stunOnly = (key == SDLK_j);\n\t\t\t\t\t\tBattleUnit *unitUnderTheCursor = nullptr;\n\t\t\t\t\t\tif (shiftPressed || altPressed)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tPosition newPos;\n\t\t\t\t\t\t\t_map->getSelectorPosition(&newPos);\n\t\t\t\t\t\t\tTile *tile = _save->getTile(newPos);\n\t\t\t\t\t\t\tif (tile)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tunitUnderTheCursor = tile->getOverlappingUnit(_save);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (shiftPressed)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// kill (ctrl-shift-k) or stun (ctrl-shift-j) just a single unit (under the cursor)\n\t\t\t\t\t\t\tif (unitUnderTheCursor && !unitUnderTheCursor->isOut())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tdebug(\"Bingo!\");\n\t\t\t\t\t\t\t\tunitUnderTheCursor->damage(Position(0, 0, 0), 1000, _game->getMod()->getDamageType(stunOnly ? DT_STUN : DT_MELEE), _save, {});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (stunOnly)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// \"ctrl-j\" - stun all aliens\n\t\t\t\t\t\t\t\tdebug(\"Deploying Celine Dion album\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// \"ctrl-k\" - kill all aliens\n\t\t\t\t\t\t\t\tdebug(\"Influenza bacterium dispersed\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tfor (auto* bu : *_save->getUnits())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (unitUnderTheCursor && unitUnderTheCursor == bu)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t// kill (ctrl-alt-k) or stun (ctrl-alt-j) all aliens EXCEPT the one under the cursor\n\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (bu->getOriginalFaction() == FACTION_HOSTILE && !bu->isOut())\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tbu->damage(Position(0, 0, 0), 1000, _game->getMod()->getDamageType(stunOnly ? DT_STUN : DT_MELEE), _save, { });\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t_battleGame->checkForCasualties(nullptr, BattleActionAttack{}, true, false);\n\t\t\t\t\t\t_battleGame->handleState();\n\t\t\t\t\t}\n\t\t\t\t\telse if (_save->getDebugMode() && (key == SDLK_m || key == SDLK_p) && ctrlPressed && shiftPressed)\n\t\t\t\t\t{\n\t\t\t\t\t\tBattleUnit* unitUnderTheCursor = nullptr;\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tPosition newPos;\n\t\t\t\t\t\t\t_map->getSelectorPosition(&newPos);\n\t\t\t\t\t\t\tTile* tile = _save->getTile(newPos);\n\t\t\t\t\t\t\tif (tile)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tunitUnderTheCursor = tile->getOverlappingUnit(_save);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// mind control (ctrl-shift-m) or panic (ctrl-shift-p) just a single unit (under the cursor)\n\t\t\t\t\t\tif (unitUnderTheCursor && !unitUnderTheCursor->isOut())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (key == SDLK_p)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tint moraleLoss = unitUnderTheCursor->reduceByBravery(100);\n\t\t\t\t\t\t\t\tif (moraleLoss > 0)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tdebug(\"Have you paid your taxes yet?\");\n\t\t\t\t\t\t\t\t\tunitUnderTheCursor->moraleChange(-moraleLoss);\n\t\t\t\t\t\t\t\t\t_game->pushState(new InfoboxState(_game->getLanguage()->getString(\"STR_MORALE_ATTACK_SUCCESSFUL\")));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (unitUnderTheCursor->getFaction() != FACTION_PLAYER)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tdebug(\"My mind to your mind, my thoughts to your thoughts.\");\n\t\t\t\t\t\t\t\t\tunitUnderTheCursor->convertToFaction(FACTION_PLAYER);\n\t\t\t\t\t\t\t\t\t//unitUnderTheCursor->recoverTimeUnits();\n\t\t\t\t\t\t\t\t\tunitUnderTheCursor->allowReselect();\n\t\t\t\t\t\t\t\t\tunitUnderTheCursor->abortTurn(); // resets unit status to STANDING\n\t\t\t\t\t\t\t\t\t_game->pushState(new InfoboxState(_game->getLanguage()->getString(\"STR_MIND_CONTROL_SUCCESSFUL\")));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t// f11 - voxel map dump\n\t\t\t\t\telse if (key == SDLK_F11)\n\t\t\t\t\t{\n\t\t\t\t\t\tsaveVoxelMap();\n\t\t\t\t\t}\n\t\t\t\t\t// f9 - ai\n\t\t\t\t\telse if (key == SDLK_F9 && Options::traceAI)\n\t\t\t\t\t{\n\t\t\t\t\t\tsaveAIMap();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// quick save and quick load\n\t\t\t\tif (!_game->getSavedGame()->isIronman() && !_save->isPreview())\n\t\t\t\t{\n\t\t\t\t\tif (key == Options::keyQuickSave)\n\t\t\t\t\t{\n\t\t\t\t\t\t_game->pushState(new SaveGameState(OPT_BATTLESCAPE, SAVE_QUICK, _palette));\n\t\t\t\t\t}\n\t\t\t\t\telse if (key == Options::keyInstaSave)\n\t\t\t\t\t{\n\t\t\t\t\t\t_game->pushState(new SaveGameState(OPT_BATTLESCAPE, SAVE_INSTA, _palette));\n\t\t\t\t\t}\n\t\t\t\t\telse if (key == Options::keyQuickLoad)\n\t\t\t\t\t{\n\t\t\t\t\t\t_game->pushState(new LoadGameState(OPT_BATTLESCAPE, SAVE_QUICK, _palette));\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// voxel view dump\n\t\t\t\tif (key == Options::keyBattleVoxelView)\n\t\t\t\t{\n\t\t\t\t\tsaveVoxelView();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Saves a map as used by the AI.\n */\nvoid BattlescapeState::saveAIMap()\n{\n\tUint32 start = SDL_GetTicks();\n\tBattleUnit *unit = _save->getSelectedUnit();\n\tif (!unit) return;\n\n\tint w = _save->getMapSizeX();\n\tint h = _save->getMapSizeY();\n\n\tSDL_Surface *img = SDL_AllocSurface(0, w * 8, h * 8, 24, 0xff, 0xff00, 0xff0000, 0);\n\tLog(LOG_INFO) << \"unit = \" << unit->getId();\n\tmemset(img->pixels, 0, img->pitch * img->h);\n\n\tPosition tilePos(unit->getPosition());\n\tSDL_Rect r;\n\tr.h = 8;\n\tr.w = 8;\n\n\tfor (int y = 0; y < h; ++y)\n\t{\n\t\ttilePos.y = y;\n\t\tfor (int x = 0; x < w; ++x)\n\t\t{\n\t\t\ttilePos.x = x;\n\t\t\tTile *t = _save->getTile(tilePos);\n\n\t\t\tif (!t) continue;\n\t\t\tif (!t->isDiscovered(O_FLOOR)) continue;\n\n\t\t}\n\t}\n\n\tfor (int y = 0; y < h; ++y)\n\t{\n\t\ttilePos.y = y;\n\t\tfor (int x = 0; x < w; ++x)\n\t\t{\n\t\t\ttilePos.x = x;\n\t\t\tTile *t = _save->getTile(tilePos);\n\n\t\t\tif (!t) continue;\n\t\t\tif (!t->isDiscovered(O_FLOOR)) continue;\n\n\t\t\tr.x = x * r.w;\n\t\t\tr.y = y * r.h;\n\n\t\t\tif (t->getTUCost(O_FLOOR, MT_FLY) != Pathfinding::INVALID_MOVE_COST && t->getTUCost(O_OBJECT, MT_FLY) != Pathfinding::INVALID_MOVE_COST)\n\t\t\t{\n\t\t\t\tSDL_FillRect(img, &r, SDL_MapRGB(img->format, 255, 0, 0x20));\n\t\t\t\tcharacterRGBA(img, r.x, r.y,'*' , 0x7f, 0x7f, 0x7f, 0x7f);\n\t\t\t} else\n\t\t\t{\n\t\t\t\tif (!t->getUnit()) SDL_FillRect(img, &r, SDL_MapRGB(img->format, 0x50, 0x50, 0x50)); // gray for blocked tile\n\t\t\t}\n\n\t\t\tfor (int z = tilePos.z; z >= 0; --z)\n\t\t\t{\n\t\t\t\tPosition pos(tilePos.x, tilePos.y, z);\n\t\t\t\tt = _save->getTile(pos);\n\t\t\t\tBattleUnit *wat = t->getUnit();\n\t\t\t\tif (wat)\n\t\t\t\t{\n\t\t\t\t\tswitch(wat->getFaction())\n\t\t\t\t\t{\n\t\t\t\t\tcase FACTION_HOSTILE:\n\t\t\t\t\t\t// #4080C0 is Volutar Blue\n\t\t\t\t\t\tcharacterRGBA(img, r.x, r.y, (tilePos.z - z) ? 'a' : 'A', 0x40, 0x80, 0xC0, 0xff);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase FACTION_PLAYER:\n\t\t\t\t\t\tcharacterRGBA(img, r.x, r.y, (tilePos.z - z) ? 'x' : 'X', 255, 255, 127, 0xff);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase FACTION_NEUTRAL:\n\t\t\t\t\t\tcharacterRGBA(img, r.x, r.y, (tilePos.z - z) ? 'c' : 'C', 255, 127, 127, 0xff);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase FACTION_NONE:\n\t\t\t\t\tcase FACTION_MAX:\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tpos.z--;\n\t\t\t\tif (z > 0 && !t->hasNoFloor(_save)) break; // no seeing through floors\n\t\t\t}\n\n\t\t\tif (t->getMapData(O_NORTHWALL) && t->getMapData(O_NORTHWALL)->getTUCost(MT_FLY) == Pathfinding::INVALID_MOVE_COST)\n\t\t\t{\n\t\t\t\tlineRGBA(img, r.x, r.y, r.x+r.w, r.y, 0x50, 0x50, 0x50, 255);\n\t\t\t}\n\n\t\t\tif (t->getMapData(O_WESTWALL) && t->getMapData(O_WESTWALL)->getTUCost(MT_FLY) == Pathfinding::INVALID_MOVE_COST)\n\t\t\t{\n\t\t\t\tlineRGBA(img, r.x, r.y, r.x, r.y+r.h, 0x50, 0x50, 0x50, 255);\n\t\t\t}\n\t\t}\n\t}\n\n\tstd::ostringstream ss;\n\n\tss.str(\"\");\n\tss << \"z = \" << tilePos.z;\n\tstringRGBA(img, 12, 12, ss.str().c_str(), 0, 0, 0, 0x7f);\n\n\tint i = 0;\n\tdo\n\t{\n\t\tss.str(\"\");\n\t\tss << Options::getMasterUserFolder() << \"AIExposure\" << std::setfill('0') << std::setw(3) << i << \".png\";\n\t\ti++;\n\t}\n\twhile (CrossPlatform::fileExists(ss.str()));\n\n\tstd::vector<unsigned char> out;\n\tunsigned error = lodepng::encode(out, (const unsigned char*)img->pixels, img->w, img->h, LCT_RGB);\n\tif (error)\n\t{\n\t\tLog(LOG_ERROR) << \"Saving to PNG failed: \" << lodepng_error_text(error);\n\t}\n\n\tSDL_FreeSurface(img);\n\n\tCrossPlatform::writeFile(ss.str(), out);\n\tLog(LOG_INFO) << \"saveAIMap() completed in \" << SDL_GetTicks() - start << \"ms.\";\n}\n\n/**\n * Saves a first-person voxel view of the battlescape.\n */\nvoid BattlescapeState::saveVoxelView()\n{\n\tstatic const unsigned char pal[30]=\n\t//\t\t\tground\t\twest wall\tnorth wall\t\tobject\t\tenemy unit\t\t\t\t\t\txcom unit\tneutral unit\n\t{0,0,0, 224,224,224,  192,224,255,  255,224,192, 128,255,128, 192,0,255,  0,0,0, 255,255,255,  224,192,0,  255,64,128 };\n\n\tBattleUnit * bu = _save->getSelectedUnit();\n\tif (bu==0) return; //no unit selected\n\tstd::vector<Position> _trajectory;\n\n\tdouble ang_x, ang_y;\n\tbool black;\n\tTile *tile = 0;\n\tstd::ostringstream ss;\n\tstd::vector<unsigned char> image;\n\tint test;\n\tPosition originVoxel = _save->getTileEngine()->getSightOriginVoxel(bu);\n\n\tPosition targetVoxel,hitPos;\n\tdouble dist = 0;\n\tbool _debug = _save->getDebugMode();\n\tdouble dir = ((double)bu->getDirection()+4)/4*M_PI;\n\timage.clear();\n\tfor (int y = -256+32; y < 256+32; ++y)\n\t{\n\t\tang_y = (((double)y) / 640 * M_PI + M_PI / 2);\n\t\tfor (int x = -256; x < 256; ++x)\n\t\t{\n\t\t\tif (Options::oxceFirstPersonViewFisheyeProjection)\n\t\t\t{\n\t\t\t\tang_x = ((double)x / 1024) * M_PI + dir;\n\t\t\t\ttargetVoxel.x = originVoxel.x + (int)(-sin(ang_x) * 1024 * sin(ang_y));\n\t\t\t\ttargetVoxel.y = originVoxel.y + (int)(cos(ang_x) * 1024 * sin(ang_y));\n\t\t\t\ttargetVoxel.z = originVoxel.z + (int)(cos(ang_y) * 1024);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\ttargetVoxel.x = originVoxel.x + (int)(-sin(dir + M_PI_2) * (x * 4) + cos(dir + M_PI_2) * (1024 + 512));\n\t\t\t\ttargetVoxel.y = originVoxel.y + (int)(cos(dir + M_PI_2) * (x * 4) + sin(dir + M_PI_2) * (1024 + 512));\n\t\t\t\ttargetVoxel.z = originVoxel.z + -y * 4;\n\t\t\t}\n\n\t\t\t_trajectory.clear();\n\t\t\ttest = _save->getTileEngine()->calculateLineVoxel(originVoxel, targetVoxel, false, &_trajectory, bu, nullptr, !_debug) +1;\n\t\t\tblack = true;\n\t\t\tif (test!=0 && test!=6)\n\t\t\t{\n\t\t\t\ttile = _save->getTile(_trajectory.at(0).toTile());\n\t\t\t\tif (_debug\n\t\t\t\t\t|| (tile->isDiscovered(O_WESTWALL) && test == 2)\n\t\t\t\t\t|| (tile->isDiscovered(O_NORTHWALL) && test == 3)\n\t\t\t\t\t|| (tile->isDiscovered(O_FLOOR) && (test == 1 || test == 4))\n\t\t\t\t\t|| test==5\n\t\t\t\t\t)\n\t\t\t\t{\n\t\t\t\t\tif (test==5)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (tile->getUnit())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (tile->getUnit()->getFaction()==FACTION_NEUTRAL) test=9;\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\tif (tile->getUnit()->getFaction()==FACTION_PLAYER) test=8;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttile = _save->getBelowTile(tile);\n\t\t\t\t\t\t\tif (tile && tile->getUnit())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (tile->getUnit()->getFaction()==FACTION_NEUTRAL) test=9;\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tif (tile->getUnit()->getFaction()==FACTION_PLAYER) test=8;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\thitPos =_trajectory.at(0);\n\t\t\t\t\tdist = Position::distance(hitPos, originVoxel);\n\t\t\t\t\tblack = false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (black)\n\t\t\t{\n\t\t\t\tdist = 0;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (dist>1000) dist=1000;\n\t\t\t\tif (dist<1) dist=1;\n\t\t\t\tdist=(1000-(log(dist))*140)/700;//140\n\n\t\t\t\tif (hitPos.x%16==15)\n\t\t\t\t{\n\t\t\t\t\tdist*=0.9;\n\t\t\t\t}\n\t\t\t\tif (hitPos.y%16==15)\n\t\t\t\t{\n\t\t\t\t\tdist*=0.9;\n\t\t\t\t}\n\t\t\t\tif (hitPos.z%24==23)\n\t\t\t\t{\n\t\t\t\t\tdist*=0.9;\n\t\t\t\t}\n\t\t\t\tif (dist > 1) dist = 1;\n\t\t\t\tif (tile) dist *= (16 - (double)tile->getShade())/16;\n\t\t\t}\n\n\t\t\timage.push_back((int)((double)(pal[test*3+0])*dist));\n\t\t\timage.push_back((int)((double)(pal[test*3+1])*dist));\n\t\t\timage.push_back((int)((double)(pal[test*3+2])*dist));\n\t\t}\n\t}\n\n\tint i = 0;\n\tdo\n\t{\n\t\tss.str(\"\");\n\t\tss << Options::getMasterUserFolder() << \"fpslook\" << std::setfill('0') << std::setw(3) << i << \".png\";\n\t\ti++;\n\t}\n\twhile (CrossPlatform::fileExists(ss.str()));\n\n\tstd::vector<unsigned char> out;\n\tunsigned error = lodepng::encode(out, image, 512, 512, LCT_RGB);\n\tif (error)\n\t{\n\t\tLog(LOG_ERROR) << \"Saving to PNG failed: \" << lodepng_error_text(error);\n\t}\n\tCrossPlatform::writeFile(ss.str(), out);\n\treturn;\n}\n\n/**\n * Saves each layer of voxels on the bettlescape as a png.\n */\nvoid BattlescapeState::saveVoxelMap()\n{\n\tstd::ostringstream ss;\n\tstd::vector<unsigned char> image;\n\tstatic const unsigned char pal[30]=\n\t{255,255,255, 224,224,224,  128,160,255,  255,160,128, 128,255,128, 192,0,255,  255,255,255, 255,255,255,  224,192,0,  255,64,128 };\n\n\tTile *tile;\n\n\tfor (int z = 0; z < _save->getMapSizeZ()*12; ++z)\n\t{\n\t\timage.clear();\n\n\t\tfor (int y = 0; y < _save->getMapSizeY()*16; ++y)\n\t\t{\n\t\t\tfor (int x = 0; x < _save->getMapSizeX()*16; ++x)\n\t\t\t{\n\t\t\t\tint test = _save->getTileEngine()->voxelCheck(Position(x,y,z*2),0,0) +1;\n\t\t\t\tfloat dist=1;\n\t\t\t\tif (x%16==15)\n\t\t\t\t{\n\t\t\t\t\tdist*=0.9f;\n\t\t\t\t}\n\t\t\t\tif (y%16==15)\n\t\t\t\t{\n\t\t\t\t\tdist*=0.9f;\n\t\t\t\t}\n\n\t\t\t\tif (test == V_OUTOFBOUNDS)\n\t\t\t\t{\n\t\t\t\t\ttile = _save->getTile(Position(x/16, y/16, z/12));\n\t\t\t\t\tif (tile->getUnit())\n\t\t\t\t\t{\n\t\t\t\t\t\tif (tile->getUnit()->getFaction()==FACTION_NEUTRAL) test=9;\n\t\t\t\t\t\telse\n\t\t\t\t\t\tif (tile->getUnit()->getFaction()==FACTION_PLAYER) test=8;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\ttile = _save->getBelowTile(tile);\n\t\t\t\t\t\tif (tile && tile->getUnit())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (tile->getUnit()->getFaction()==FACTION_NEUTRAL) test=9;\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\tif (tile->getUnit()->getFaction()==FACTION_PLAYER) test=8;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\timage.push_back((int)((float)pal[test*3+0]*dist));\n\t\t\t\timage.push_back((int)((float)pal[test*3+1]*dist));\n\t\t\t\timage.push_back((int)((float)pal[test*3+2]*dist));\n\t\t\t}\n\t\t}\n\n\t\tss.str(\"\");\n\t\tss << Options::getMasterUserFolder() << \"voxel\" << std::setfill('0') << std::setw(2) << z << \".png\";\n\t\tstd::vector<unsigned char> out;\n\t\tunsigned error = lodepng::encode(out, image, _save->getMapSizeX()*16, _save->getMapSizeY()*16, LCT_RGB);\n\t\tif (error)\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"Saving to PNG failed: \" << lodepng_error_text(error);\n\t\t}\n\t\tCrossPlatform::writeFile(ss.str(), out);\n\t}\n\treturn;\n}\n\n/**\n * Adds a new popup window to the queue\n * (this prevents popups from overlapping).\n * @param state Pointer to popup state.\n */\nvoid BattlescapeState::popup(State *state)\n{\n\t_popups.push_back(state);\n}\n\n/**\n * Finishes up the current battle, shuts down the battlescape\n * and presents the debriefing screen for the mission.\n * @param abort Was the mission aborted?\n * @param inExitArea Number of soldiers in the exit area OR number of survivors when battle finished due to either all aliens or objective being destroyed.\n */\nvoid BattlescapeState::finishBattle(bool abort, int inExitArea)\n{\n\tbool isPreview = _save->isPreview();\n\n\twhile (!_game->isState(this))\n\t{\n\t\t_game->popState();\n\t}\n\t_game->getCursor()->setVisible(true);\n\tif (_save->getAmbientSound() != Mod::NO_SOUND)\n\t{\n\t\t_game->getMod()->getSoundByDepth(0, _save->getAmbientSound())->stopLoop();\n\t}\n\n\t// reset touch flags\n\t_game->resetTouchButtonFlags();\n\n\t// dear civilians and summoned player units,\n\t// please drop all borrowed xcom equipment now, so that we can recover it\n\t// thank you!\n\tstd::vector<BattleItem*> itemsToDrop;\n\tfor (auto* unit : *_save->getUnits())\n\t{\n\t\tbool relevantUnitType = unit->getOriginalFaction() == FACTION_NEUTRAL || unit->isSummonedPlayerUnit();\n\t\tif (relevantUnitType && !unit->isOut())\n\t\t{\n\t\t\titemsToDrop.clear();\n\t\t\tfor (auto* item : *unit->getInventory())\n\t\t\t{\n\t\t\t\tif (item->getXCOMProperty() || item->getUnit())\n\t\t\t\t{\n\t\t\t\t\titemsToDrop.push_back(item);\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (auto* xcomItem : itemsToDrop)\n\t\t\t{\n\t\t\t\t_save->getTileEngine()->itemDrop(unit->getTile(), xcomItem, false);\n\t\t\t}\n\t\t}\n\t}\n\n\t// let's count summoned player-controlled VIPs before we remove them :)\n\t_battleGame->tallySummonedVIPs();\n\t// this removes player-controlled VIPs (not civilian VIPs)\n\t_battleGame->removeSummonedPlayerUnits();\n\n\tAlienDeployment *ruleDeploy = _game->getMod()->getDeployment(_save->getMissionType());\n\tif (!ruleDeploy)\n\t{\n\t\tfor (auto* ufo : *_game->getSavedGame()->getUfos())\n\t\t{\n\t\t\tif (ufo->isInBattlescape())\n\t\t\t{\n\t\t\t\tstd::string ufoMissionName = ufo->getRules()->getType();\n\t\t\t\tif (!_save->getAlienCustomMission().empty())\n\t\t\t\t{\n\t\t\t\t\t// fake underwater UFO\n\t\t\t\t\tufoMissionName = _save->getAlienCustomMission();\n\t\t\t\t}\n\t\t\t\truleDeploy = _game->getMod()->getDeployment(ufoMissionName);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\tstd::string nextStage;\n\tif (ruleDeploy)\n\t{\n\t\tnextStage = ruleDeploy->getNextStage();\n\t}\n\n\tif (!nextStage.empty() && inExitArea && !isPreview)\n\t{\n\t\t// if there is a next mission stage + we have people in exit area OR we killed all aliens, load the next stage\n\t\t_popups.clear();\n\t\t_save->setMissionType(nextStage);\n\t\tBattlescapeGenerator bgen = BattlescapeGenerator(_game);\n\t\tbgen.nextStage();\n\t\t_game->popState();\n\t\t_game->pushState(new BriefingState(0, 0));\n\t}\n\telse\n\t{\n\t\t_popups.clear();\n\t\t_animTimer->stop();\n\t\t_gameTimer->stop();\n\t\t_game->popState();\n\t\tif (isPreview)\n\t\t{\n\t\t\t// skip Debriefing\n\t\t\tOptions::baseXResolution = Options::baseXGeoscape;\n\t\t\tOptions::baseYResolution = Options::baseYGeoscape;\n\t\t\t_game->getScreen()->resetDisplay(false);\n\n\t\t\t// Restore the cursor in case something weird happened\n\t\t\t_game->getCursor()->setVisible(true);\n\n\t\t\t// delete SavedBattleGame\n\t\t\t_game->getSavedGame()->setBattleGame(0);\n\n\t\t\t// unmark all craft and all bases (current craft would be enough, but better safe than sorry)\n\t\t\tfor (auto* xbase : *_game->getSavedGame()->getBases())\n\t\t\t{\n\t\t\t\txbase->setInBattlescape(false);\n\t\t\t\tfor (auto* craft : *xbase->getCrafts())\n\t\t\t\t{\n\t\t\t\t\tcraft->setInBattlescape(false);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// reset the music\n\t\t\t_game->getMod()->playMusic(\"GMGEO\");\n\t\t\treturn;\n\t\t}\n\t\t_game->pushState(new DebriefingState);\n\t\tstd::string cutscene;\n\t\tif (ruleDeploy)\n\t\t{\n\t\t\tif (abort)\n\t\t\t{\n\t\t\t\tcutscene = ruleDeploy->getAbortCutscene();\n\t\t\t}\n\t\t\telse if (inExitArea == 0)\n\t\t\t{\n\t\t\t\tcutscene = ruleDeploy->getLoseCutscene();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tcutscene = ruleDeploy->getWinCutscene();\n\t\t\t}\n\t\t}\n\t\tif (!cutscene.empty())\n\t\t{\n\t\t\t// if cutscene is \"wingame\" or \"losegame\", then the DebriefingState\n\t\t\t// pushed above will get popped without being shown.  otherwise\n\t\t\t// it will get shown after the cutscene.\n\t\t\t_game->pushState(new CutsceneState(cutscene));\n\n\t\t\tconst RuleVideo *videoRule = _game->getMod()->getVideo(cutscene, true);\n\t\t\tif (videoRule->getWinGame())\n\t\t\t{\n\t\t\t\t_game->getSavedGame()->setEnding(END_WIN);\n\t\t\t}\n\t\t\telse if (videoRule->getLoseGame())\n\t\t\t{\n\t\t\t\t_game->getSavedGame()->setEnding(END_LOSE);\n\t\t\t}\n\t\t\t// Autosave if game is over\n\t\t\tif (_game->getSavedGame()->getEnding() != END_NONE && _game->getSavedGame()->isIronman())\n\t\t\t{\n\t\t\t\t_game->pushState(new SaveGameState(OPT_BATTLESCAPE, SAVE_IRONMAN, _palette));\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Shows the launch button.\n * @param show Show launch button?\n */\nvoid BattlescapeState::showLaunchButton(bool show)\n{\n\t_btnLaunch->setVisible(show);\n}\n\n/**\n * Clears mouse-scrolling state (isMouseScrolling).\n */\nvoid BattlescapeState::clearMouseScrollingState()\n{\n\t_isMouseScrolling = false;\n}\n\n/**\n * Returns a pointer to the battlegame, in case we need its functions.\n */\nBattlescapeGame *BattlescapeState::getBattleGame()\n{\n\treturn _battleGame;\n}\n\n/**\n * Handler for the mouse moving over the icons, disabling the tile selection cube.\n * @param action Pointer to an action.\n */\nvoid BattlescapeState::mouseInIcons(Action *)\n{\n\t_mouseOverIcons = true;\n}\n\n/**\n * Handler for the mouse going out of the icons, enabling the tile selection cube.\n * @param action Pointer to an action.\n */\nvoid BattlescapeState::mouseOutIcons(Action *)\n{\n\t_mouseOverIcons = false;\n}\n\n/**\n * Checks if the mouse is over the icons.\n * @return True, if the mouse is over the icons.\n */\nbool BattlescapeState::getMouseOverIcons() const\n{\n\treturn _mouseOverIcons;\n}\n\n/**\n * Determines whether the player is allowed to press buttons.\n * Buttons are disabled in the middle of a shot, during the alien turn,\n * and while a player's units are panicking.\n * The save button is an exception as we want to still be able to save if something\n * goes wrong during the alien turn, and submit the save file for dissection.\n * @param allowSaving True, if the help button was clicked.\n * @return True if the player can still press buttons.\n */\nbool BattlescapeState::allowButtons(bool allowSaving) const\n{\n\treturn ((allowSaving || _save->getSide() == FACTION_PLAYER || _save->getDebugMode())\n\t\t&& (_battleGame->getPanicHandled() || _firstInit )\n\t\t&& (allowSaving || !_battleGame->isBusy() || _firstInit)\n\t\t&& (_map->getProjectile() == 0));\n}\n\n/**\n * Reserves time units for kneeling.\n * @param action Pointer to an action.\n */\nvoid BattlescapeState::btnReserveKneelClick(Action *action)\n{\n\tif (allowButtons())\n\t{\n\t\tSDL_Event ev;\n\t\tev.type = SDL_MOUSEBUTTONDOWN;\n\t\tev.button.button = SDL_BUTTON_LEFT;\n\t\tAction a = Action(&ev, 0.0, 0.0, 0, 0);\n\t\taction->getSender()->mousePress(&a, this);\n\t\t_battleGame->setKneelReserved(!_battleGame->getKneelReserved());\n\n\t\t_btnReserveKneel->toggle(_battleGame->getKneelReserved());\n\n\t\t// update any path preview\n\t\tif (_battleGame->getPathfinding()->isPathPreviewed())\n\t\t{\n\t\t\t_battleGame->getPathfinding()->refreshPath();\n\t\t}\n\t}\n}\n\n/**\n * Removes all time units.\n * @param action Pointer to an action.\n */\nvoid BattlescapeState::btnZeroTUsClick(Action *action)\n{\n\tif (allowButtons())\n\t{\n\t\tSDL_Event ev;\n\t\tev.type = SDL_MOUSEBUTTONDOWN;\n\t\tev.button.button = SDL_BUTTON_LEFT;\n\t\tAction a = Action(&ev, 0.0, 0.0, 0, 0);\n\t\taction->getSender()->mousePress(&a, this);\n\t\tif (_battleGame->getSave()->getSelectedUnit())\n\t\t{\n\t\t\t_battleGame->getSave()->getSelectedUnit()->clearTimeUnits();\n\t\t\tupdateSoldierInfo();\n\t\t}\n\t}\n}\n\n/**\n* Shows a tooltip with extra information (used for medikit-type equipment).\n* @param action Pointer to an action.\n*/\nvoid BattlescapeState::txtTooltipInExtra(Action *action, bool leftHand, bool special)\n{\n\tif (allowButtons() && Options::battleTooltips)\n\t{\n\t\t// no one selected... do normal tooltip\n\t\tif(!playableUnitSelected())\n\t\t{\n\t\t\t_currentTooltip = action->getSender()->getTooltip();\n\t\t\t_txtTooltip->setText(tr(_currentTooltip));\n\t\t\treturn;\n\t\t}\n\n\t\tBattleUnit *selectedUnit = _save->getSelectedUnit();\n\t\tBattleItem *weapon;\n\t\tif (leftHand)\n\t\t{\n\t\t\tweapon = selectedUnit->getLeftHandWeapon();\n\t\t}\n\t\telse if (special)\n\t\t{\n\t\t\tBattleType type;\n\t\t\tweapon = selectedUnit->getSpecialIconWeapon(type);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tweapon = selectedUnit->getRightHandWeapon();\n\t\t}\n\n\t\t// no weapon selected... do normal tooltip\n\t\tif(!weapon)\n\t\t{\n\t\t\t_currentTooltip = action->getSender()->getTooltip();\n\t\t\t_txtTooltip->setText(tr(_currentTooltip));\n\t\t\treturn;\n\t\t}\n\n\t\tauto* weaponRule = weapon->getRules();\n\n\t\t// find the target unit\n\t\tif (weaponRule->getBattleType() == BT_MEDIKIT)\n\t\t{\n\t\t\tBattleUnit *targetUnit = 0;\n\n\t\t\t// search for target on the ground\n\t\t\tbool onGround = false;\n\t\t\tfor (auto* bu : *_save->getUnits())\n\t\t\t{\n\t\t\t\tif (targetUnit) break; // loop finished\n\t\t\t\t// we can heal a unit that is at the same position, unconscious and healable(=woundable)\n\t\t\t\tif (bu->getPosition() == selectedUnit->getPosition() && bu != selectedUnit && bu->getStatus() == STATUS_UNCONSCIOUS && (bu->isWoundable() || weaponRule->getAllowTargetImmune()) && weaponRule->getAllowTargetGround())\n\t\t\t\t{\n\t\t\t\t\tif (bu->isBigUnit())\n\t\t\t\t\t{\n\t\t\t\t\t\t// never EVER apply anything to 2x2 units on the ground\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tif ((weaponRule->getAllowTargetFriendGround() && bu->getOriginalFaction() == FACTION_PLAYER) ||\n\t\t\t\t\t\t(weaponRule->getAllowTargetNeutralGround() && bu->getOriginalFaction() == FACTION_NEUTRAL) ||\n\t\t\t\t\t\t(weaponRule->getAllowTargetHostileGround() && bu->getOriginalFaction() == FACTION_HOSTILE))\n\t\t\t\t\t{\n\t\t\t\t\t\ttargetUnit = bu;\n\t\t\t\t\t\tonGround = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// search for target in front of the selected unit\n\t\t\tif (!targetUnit && weaponRule->getAllowTargetStanding())\n\t\t\t{\n\t\t\t\tPosition dest;\n\t\t\t\tif (_save->getTileEngine()->validMeleeRange(\n\t\t\t\t\tselectedUnit->getPosition(),\n\t\t\t\t\tselectedUnit->getDirection(),\n\t\t\t\t\tselectedUnit,\n\t\t\t\t\t0, &dest, false))\n\t\t\t\t{\n\t\t\t\t\tTile *tile = _save->getTile(dest);\n\t\t\t\t\tif (tile != 0 && tile->getUnit() && (tile->getUnit()->isWoundable() || weaponRule->getAllowTargetImmune()))\n\t\t\t\t\t{\n\t\t\t\t\t\tif ((weaponRule->getAllowTargetFriendStanding() && tile->getUnit()->getOriginalFaction() == FACTION_PLAYER) ||\n\t\t\t\t\t\t\t(weaponRule->getAllowTargetNeutralStanding() && tile->getUnit()->getOriginalFaction() == FACTION_NEUTRAL) ||\n\t\t\t\t\t\t\t(weaponRule->getAllowTargetHostileStanding() && tile->getUnit()->getOriginalFaction() == FACTION_HOSTILE))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttargetUnit = tile->getUnit();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t_currentTooltip = action->getSender()->getTooltip();\n\t\t\tstd::ostringstream tooltipExtra;\n\t\t\ttooltipExtra << tr(_currentTooltip);\n\n\t\t\t// target unit found\n\t\t\tif (targetUnit)\n\t\t\t{\n\t\t\t\tif (targetUnit->getOriginalFaction() == FACTION_HOSTILE) {\n\t\t\t\t\t_txtTooltip->setColor(Palette::blockOffset(_medikitRed));\n\t\t\t\t\ttooltipExtra << tr(\"STR_TARGET_ENEMY\");\n\t\t\t\t} else if (targetUnit->getOriginalFaction() == FACTION_NEUTRAL) {\n\t\t\t\t\t_txtTooltip->setColor(Palette::blockOffset(_medikitOrange));\n\t\t\t\t\ttooltipExtra << tr(\"STR_TARGET_NEUTRAL\");\n\t\t\t\t} else if (targetUnit->getOriginalFaction() == FACTION_PLAYER) {\n\t\t\t\t\t_txtTooltip->setColor(Palette::blockOffset(_medikitGreen));\n\t\t\t\t\ttooltipExtra << tr(\"STR_TARGET_FRIEND\");\n\t\t\t\t}\n\t\t\t\tif (onGround) tooltipExtra << tr(\"STR_TARGET_ON_THE_GROUND\");\n\t\t\t\t_txtTooltip->setText(tooltipExtra.str());\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// target unit not found => selected unit is the target (if self-heal is possible)\n\t\t\t\tif (weaponRule->getAllowTargetSelf())\n\t\t\t\t{\n\t\t\t\t\ttargetUnit = selectedUnit;\n\t\t\t\t\t_txtTooltip->setColor(Palette::blockOffset(_medikitBlue));\n\t\t\t\t\ttooltipExtra << tr(\"STR_TARGET_YOURSELF\");\n\t\t\t\t\tif (onGround) tooltipExtra << tr(\"STR_TARGET_ON_THE_GROUND\");\n\t\t\t\t\t_txtTooltip->setText(tooltipExtra.str());\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// cannot use the weapon (medikit) on anyone\n\t\t\t\t\t_currentTooltip = action->getSender()->getTooltip();\n\t\t\t\t\t_txtTooltip->setText(tr(_currentTooltip));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// weapon is not of medikit battle type\n\t\t\t_currentTooltip = action->getSender()->getTooltip();\n\t\t\t_txtTooltip->setText(tr(_currentTooltip));\n\t\t}\n\t}\n}\n\n/**\n* Shows a tooltip with extra information (used for medikit-type equipment).\n* @param action Pointer to an action.\n*/\nvoid BattlescapeState::txtTooltipInExtraLeftHand(Action *action)\n{\n\ttxtTooltipInExtra(action, true);\n}\n\n/**\n* Shows a tooltip with extra information (used for medikit-type equipment).\n* @param action Pointer to an action.\n*/\nvoid BattlescapeState::txtTooltipInExtraRightHand(Action *action)\n{\n\ttxtTooltipInExtra(action, false);\n}\n\n/**\n* Shows a tooltip with extra information (used for medikit-type equipment).\n* @param action Pointer to an action.\n*/\nvoid BattlescapeState::txtTooltipInExtraSpecial(Action *action)\n{\n\ttxtTooltipInExtra(action, false, true);\n}\n\n/**\n* Shows a tooltip for the End Turn button.\n* @param action Pointer to an action.\n*/\nvoid BattlescapeState::txtTooltipInEndTurn(Action *action)\n{\n\tif (allowButtons() && Options::battleTooltips)\n\t{\n\t\t_currentTooltip = action->getSender()->getTooltip();\n\n\t\tstd::ostringstream ss;\n\t\tss << tr(_currentTooltip);\n\t\tss << \" \";\n\t\tss << _save->getTurn();\n\t\tif (_save->getTurnLimit() > 0)\n\t\t{\n\t\t\tss << \"/\" << _save->getTurnLimit();\n\t\t}\n\n\t\t_txtTooltip->setText(ss.str().c_str());\n\t}\n}\n\n/**\n* Shows a tooltip for the appropriate button.\n* @param action Pointer to an action.\n*/\nvoid BattlescapeState::txtTooltipIn(Action *action)\n{\n\tif (allowButtons() && Options::battleTooltips)\n\t{\n\t\t_currentTooltip = action->getSender()->getTooltip();\n\t\t_txtTooltip->setText(tr(_currentTooltip));\n\t}\n}\n\n/**\n * Clears the tooltip text.\n * @param action Pointer to an action.\n */\nvoid BattlescapeState::txtTooltipOut(Action *action)\n{\n\t// reset color\n\t_txtTooltip->setColor(_tooltipDefaultColor);\n\n\tif (allowButtons() && Options::battleTooltips)\n\t{\n\t\tif (_currentTooltip == action->getSender()->getTooltip())\n\t\t{\n\t\t\t_txtTooltip->setText(\"\");\n\t\t}\n\t}\n}\n\n/**\n * Updates the scale.\n * @param dX delta of X;\n * @param dY delta of Y;\n */\nvoid BattlescapeState::resize(int &dX, int &dY)\n{\n\tdX = Options::baseXResolution;\n\tdY = Options::baseYResolution;\n\tint divisor = 1;\n\tdouble pixelRatioY = 1.0;\n\n\tif (Options::nonSquarePixelRatio)\n\t{\n\t\tpixelRatioY = 1.2;\n\t}\n\tswitch (Options::battlescapeScale)\n\t{\n\tcase SCALE_SCREEN_DIV_10:\n\t\tdivisor = 10;\n\t\tbreak;\n\tcase SCALE_SCREEN_DIV_8:\n\t\tdivisor = 8;\n\t\tbreak;\n\tcase SCALE_SCREEN_DIV_6:\n\t\tdivisor = 6;\n\t\tbreak;\n\tcase SCALE_SCREEN_DIV_5:\n\t\tdivisor = 5;\n\t\tbreak;\n\tcase SCALE_SCREEN_DIV_4:\n\t\tdivisor = 4;\n\t\tbreak;\n\tcase SCALE_SCREEN_DIV_3:\n\t\tdivisor = 3;\n\t\tbreak;\n\tcase SCALE_SCREEN_DIV_2:\n\t\tdivisor = 2;\n\t\tbreak;\n\tcase SCALE_SCREEN:\n\t\tbreak;\n\tdefault:\n\t\tdX = 0;\n\t\tdY = 0;\n\t\treturn;\n\t}\n\n\tOptions::baseXResolution = std::max(Screen::ORIGINAL_WIDTH, Options::displayWidth / divisor);\n\tOptions::baseYResolution = std::max(Screen::ORIGINAL_HEIGHT, (int)(Options::displayHeight / pixelRatioY / divisor));\n\n\tdX = Options::baseXResolution - dX;\n\tdY = Options::baseYResolution - dY;\n\t_map->setWidth(Options::baseXResolution);\n\t_map->setHeight(Options::baseYResolution);\n\t_map->getCamera()->resize();\n\t_map->getCamera()->jumpXY(dX/2, dY/2);\n\n\tfor (auto* surf : _surfaces)\n\t{\n\t\tif (surf == _btnCtrl || surf == _btnAlt || surf == _btnShift || surf == _btnRMB || surf == _btnMMB)\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\t\tif (surf != _map && surf != _btnPsi && surf != _btnLaunch && surf != _btnSpecial && surf != _btnSkills && surf != _txtDebug)\n\t\t{\n\t\t\tsurf->setX(surf->getX() + dX / 2);\n\t\t\tsurf->setY(surf->getY() + dY);\n\t\t}\n\t\telse if (surf != _map && surf != _txtDebug)\n\t\t{\n\t\t\tsurf->setX(surf->getX() + dX);\n\t\t}\n\t}\n\n\tfor (auto& pos : _posSpecialActions)\n\t{\n\t\tpos += dX;\n\t}\n\n}\n\n/**\n * Move the mouse back to where it started after we finish drag scrolling.\n * @param action Pointer to an action.\n */\nvoid BattlescapeState::stopScrolling(Action *action)\n{\n\tif (Options::battleDragScrollInvert)\n\t{\n\t\tSDL_WarpMouse(_xBeforeMouseScrolling, _yBeforeMouseScrolling);\n\t\taction->setMouseAction(_xBeforeMouseScrolling, _yBeforeMouseScrolling, _map->getX(), _map->getY());\n\t\t_battleGame->setupCursor();\n\t\tif (_battleGame->getCurrentAction()->actor == 0 && (_save->getSide() == FACTION_PLAYER || _save->getDebugMode()))\n\t\t{\n\t\t\tgetMap()->setCursorType(CT_NORMAL);\n\t\t}\n\t}\n\telse\n\t{\n\t\tSDL_WarpMouse(_cursorPosition.x, _cursorPosition.y);\n\t\taction->setMouseAction(_cursorPosition.x, _cursorPosition.y, _map->getX(), _map->getY());\n\t\t_map->setSelectorPosition(action->getAbsoluteXMouse(), action->getAbsoluteYMouse());\n\t}\n\t// reset our \"mouse position stored\" flag\n\t_cursorPosition.z = 0;\n}\n\n/**\n * Autosave the game the next time the battlescape is displayed.\n */\nvoid BattlescapeState::autosave(int currentTurn)\n{\n\t_autosave = currentTurn;\n}\n\n/**\n * Is busy?\n */\nbool BattlescapeState::isBusy() const\n{\n\treturn (_map->getCursorType() == CT_NONE || _battleGame->isBusy());\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/BattlescapeState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http:///www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include \"Position.h\"\n\n#include <vector>\n#include <string>\n\nnamespace OpenXcom\n{\n\nclass Surface;\nclass Map;\nclass ImageButton;\nclass BattlescapeButton;\nclass InteractiveSurface;\nclass Text;\nclass Bar;\nclass NumberText;\nclass BattleUnit;\nclass SavedBattleGame;\nclass BattleItem;\nclass Timer;\nclass WarningMessage;\nclass BattlescapeGame;\n\n/**\n * Battlescape screen which shows the tactical battle.\n */\nclass BattlescapeState : public State\n{\nprivate:\n\tSurface *_rank, *_rankTiny;\n\tInteractiveSurface *_icons;\n\tMap *_map;\n\tBattlescapeButton *_btnUnitUp, *_btnUnitDown, *_btnMapUp, *_btnMapDown, *_btnShowMap, *_btnKneel;\n\tBattlescapeButton *_btnInventory, *_btnCenter, *_btnNextSoldier, *_btnNextStop, *_btnShowLayers, *_btnHelp;\n\tBattlescapeButton *_btnEndTurn, *_btnAbort, *_btnLaunch, *_btnPsi, *_btnSpecial, *_btnSkills, *_reserve;\n\tBattlescapeButton *_btnCtrl, *_btnAlt, *_btnShift, *_btnRMB, *_btnMMB;\n\tbool _touchButtonsEnabled;\n\tInteractiveSurface *_btnStats;\n\tBattlescapeButton *_btnReserveNone, *_btnReserveSnap, *_btnReserveAimed, *_btnReserveAuto, *_btnReserveKneel, *_btnZeroTUs;\n\tInteractiveSurface *_btnLeftHandItem, *_btnRightHandItem;\n\n\tstatic const int SPECIAL_BUTTONS_MAX = 3;\n\tint _posSpecialActions[SPECIAL_BUTTONS_MAX];\n\n\tstatic const int VISIBLE_MAX = 10;\n\tstd::string _txtVisibleUnitTooltip[VISIBLE_MAX+2];\n\tInteractiveSurface *_btnVisibleUnit[VISIBLE_MAX];\n\tNumberText *_numVisibleUnit[VISIBLE_MAX];\n\tBattleUnit *_visibleUnit[VISIBLE_MAX];\n\n\tWarningMessage *_warning;\n\tText *_txtName;\n\tNumberText *_numTimeUnits, *_numEnergy, *_numHealth, *_numMorale, *_numLayers;\n\tstd::vector<NumberText*> _numAmmoLeft, _numAmmoRight;\n\tstd::vector<NumberText*> _numMedikitLeft, _numMedikitRight;\n\tNumberText *_numTwoHandedIndicatorLeft, *_numTwoHandedIndicatorRight;\n\tUint8 _twoHandedRed, _twoHandedGreen;\n\tBar *_barTimeUnits, *_barEnergy, *_barHealth, *_barMorale, *_barMana;\n\tbool _manaBarVisible;\n\tTimer *_animTimer, *_gameTimer;\n\tSavedBattleGame *_save;\n\tText *_txtDebug, *_txtTooltip;\n\tUint8 _tooltipDefaultColor;\n\tUint8 _medikitRed, _medikitGreen, _medikitBlue, _medikitOrange;\n\tstd::vector<State*> _popups;\n\tBattlescapeGame *_battleGame;\n\tbool _firstInit, _paletteResetNeeded, _paletteResetRequested;\n\tbool _isMouseScrolling, _isMouseScrolled;\n\tint _xBeforeMouseScrolling, _yBeforeMouseScrolling;\n\tPosition _mapOffsetBeforeMouseScrolling;\n\tUint32 _mouseScrollingStartTime;\n\tint _totalMouseMoveX, _totalMouseMoveY;\n\tbool _mouseMovedOverThreshold;\n\tbool _mouseOverIcons;\n\tstd::string _currentTooltip;\n\tPosition _cursorPosition;\n\tUint8 _barHealthColor;\n\tint _autosave;\n\tint _numberOfDirectlyVisibleUnits, _numberOfEnemiesTotal, _numberOfEnemiesTotalPlusWounded;\n\tUint8 _indicatorTextColor, _indicatorGreen, _indicatorBlue, _indicatorPurple;\n\t/// Popups a context sensitive list of actions the user can choose from.\n\tvoid handleItemClick(BattleItem *item, bool rightClick);\n\t/// Shifts the red colors of the visible unit buttons backgrounds.\n\tvoid blinkVisibleUnitButtons();\n\t/// Draw hand item with ammo number.\n\tvoid drawItem(BattleItem *item, Surface *hand, std::vector<NumberText*> &ammoText, std::vector<NumberText*> &medikitText, NumberText *twoHandedText, bool drawReactionIndicator, bool drawNoReactionIndicator);\n\t/// Draw both hands sprites.\n\tvoid drawHandsItems();\n\t/// Shifts the colors of the health bar when unit has fatal wounds.\n\tvoid blinkHealthBar();\n\t/// Shows the unit kneel state.\n\tvoid toggleKneelButton(BattleUnit* unit);\npublic:\n\t/// Selects the next soldier.\n\tvoid selectNextPlayerUnit(bool checkReselect = false, bool setReselect = false, bool checkInventory = false, bool checkFOV = true, bool byDistance = false);\n\t/// Selects the previous soldier.\n\tvoid selectPreviousPlayerUnit(bool checkReselect = false, bool setReselect = false, bool checkInventory = false);\n\tstatic const int DEFAULT_ANIM_SPEED = 100;\n\t/// Creates the Battlescape state.\n\tBattlescapeState();\n\t/// Cleans up the Battlescape state.\n\t~BattlescapeState();\n\tvoid resetPalettes();\n\t/// Initializes the battlescapestate.\n\tvoid init() override;\n\t/// Runs the timers and handles popups.\n\tvoid think() override;\n\t/// Handler for moving mouse over the map.\n\tvoid mapOver(Action *action);\n\t/// Handler for pressing the map.\n\tvoid mapPress(Action *action);\n\t/// Handler for clicking the map.\n\tvoid mapClick(Action *action);\n\t/// Handler for entering with mouse to the map surface.\n\tvoid mapIn(Action *action);\n\t/// Handler for clicking the Unit Up button.\n\tvoid btnUnitUpClick(Action *action);\n\t/// Handler for clicking the Unit Down button.\n\tvoid btnUnitDownClick(Action *action);\n\t/// Handler for clicking the Map Up button.\n\tvoid btnMapUpClick(Action *action);\n\t/// Handler for clicking the Map Down button.\n\tvoid btnMapDownClick(Action *action);\n\t/// Handler for clicking the Show Map button.\n\tvoid btnShowMapClick(Action *action);\n\t/// Handler for clicking the Kneel button.\n\tvoid btnKneelClick(Action *action);\n\t/// Handler for clicking the Soldier button.\n\tvoid btnInventoryClick(Action *action);\n\t/// Handler for clicking the Center button.\n\tvoid btnCenterClick(Action *action);\n\t/// Handler for clicking the Next Soldier button.\n\tvoid btnNextSoldierClick(Action *action);\n\t/// Handler for clicking the Next Stop button.\n\tvoid btnNextStopLClick(Action *action);\n\tvoid btnNextStopMClick(Action *action);\n\tvoid btnNextStopRClick(Action *action);\n\t/// Handler for clicking the Previous Soldier button.\n\tvoid btnPrevSoldierClick(Action *action);\n\t/// Handler for clicking the Show Layers button.\n\tvoid btnShowLayersClick(Action *action);\n\tvoid btnShowLayersClickOrig(Action *action);\n\t/// Handler for clicking the Ufopaedia button.\n\tvoid btnUfopaediaClick(Action *action);\n\t/// Handler for clicking the Help button.\n\tvoid btnHelpClick(Action *action);\n\t/// Handler for clicking the End Turn button.\n\tvoid btnEndTurnClick(Action *action);\n\t/// Handler for clicking the Abort button.\n\tvoid btnAbortClick(Action *action);\n\t/// Handler for clicking the stats.\n\tvoid btnStatsClick(Action *action);\n\t/// Handler for clicking the left hand item button.\n\tvoid btnLeftHandItemClick(Action *action);\n\t/// Handler for clicking the right hand item button.\n\tvoid btnRightHandItemClick(Action *action);\n\t/// Handler for clicking a visible unit button.\n\tvoid btnVisibleUnitClick(Action *action);\n\n\t/// Handler for clicking the CTRL touch button.\n\tvoid btnCtrlClick(Action* action);\n\t/// Handler for clicking the ALT touch button.\n\tvoid btnAltClick(Action* action);\n\t/// Handler for clicking the SHIFT touch button.\n\tvoid btnShiftClick(Action* action);\n\t/// Handler for clicking the RMB touch button.\n\tvoid btnRMBClick(Action* action);\n\t/// Handler for clicking the MMB touch button.\n\tvoid btnMMBClick(Action* action);\n\t/// Handler for pressing the toggle touch buttons hotkey.\n\tvoid btnTouchButtonsClick(Action* action);\n\t/// Toggles the touch buttons.\n\tvoid toggleTouchButtons(bool deactivate, bool tryToReactivate);\n\n\t/// Handler for clicking the launch rocket button.\n\tvoid btnLaunchClick(Action *action);\n\t/// Handler for clicking the use psi button.\n\tvoid btnPsiClick(Action *action);\n\t/// Handler for clicking the use special weapon button.\n\tvoid btnSpecialClick(Action *action);\n\t/// Handler for clicking the skills menu button.\n\tvoid btnSkillsClick(Action *action);\n\t/// Handler for clicking a reserved button.\n\tvoid btnReserveClick(Action *action);\n\t/// Handler for clicking the reload button.\n\tvoid btnReloadClick(Action *action);\n\t/// Handler for clicking the [SelectMusicTrack] button.\n\tvoid btnSelectMusicTrackClick(Action *action);\n\t/// Handler for clicking the lighting button.\n\tvoid btnPersonalLightingClick(Action *action);\n\t/// Handler for toggling the \"night vision\" mode.\n\tvoid btnNightVisionClick(Action *action);\n\t/// Determines whether a playable unit is selected.\n\tbool playableUnitSelected();\n\t/// Updates soldier name/rank/tu/energy/health/morale.\n\tvoid updateSoldierInfo(bool checkFOV = true);\n\t/// Updates the special/psi/skill button display based on the battle unit\n\tvoid updateUiButton(const BattleUnit* battleUnit);\n\t/// Animates map objects on the map, also smoke,fire, ...\n\tvoid animate();\n\t/// Handles the battle game state.\n\tvoid handleState();\n\t/// Sets the state timer interval.\n\tvoid setStateInterval(Uint32 interval);\n\t/// Gets game.\n\tGame *getGame() const;\n\t/// Gets map.\n\tMap *getMap() const;\n\t/// Show debug message.\n\tvoid debug(const std::string &message);\n\t/// Show bug hunt message.\n\tvoid bugHuntMessage();\n\t/// Show warning message.\n\tvoid warning(const std::string &message);\n\t/// Show warning message, no translation.\n\tvoid warningRaw(const std::string &message);\n\t/// Show warning message that stay longer on screen, no translation.\n\tvoid warningLongRaw(const std::string &message);\n\t/// Gets melee damage preview.\n\tstd::string getMeleeDamagePreview(BattleUnit *actor, BattleItem *weapon) const;\n\t/// Handles keypresses.\n\tvoid handle(Action *action) override;\n\t/// Displays a popup window.\n\tvoid popup(State *state);\n\t/// Finishes a battle.\n\tvoid finishBattle(bool abort, int inExitArea);\n\t/// Show the launch button.\n\tvoid showLaunchButton(bool show);\n\t/// Reset visiblity of special buttons like psi or skill.\n\tvoid resetUiButton();\n\t/// Clears mouse-scrolling state.\n\tvoid clearMouseScrollingState();\n\t/// Returns a pointer to the battlegame, in case we need its functions.\n\tBattlescapeGame *getBattleGame();\n\t/// Saves a map as used by the AI.\n\tvoid saveAIMap();\n\t/// Saves each layer of voxels on the bettlescape as a png.\n\tvoid saveVoxelMap();\n\t/// Saves a first-person voxel view of the battlescape.\n\tvoid saveVoxelView();\n\t/// Handler for the mouse moving over the icons, disables the tile selection cube.\n\tvoid mouseInIcons(Action *action);\n\t/// Handler for the mouse going out of the icons, enabling the tile selection cube.\n\tvoid mouseOutIcons(Action *action);\n\t/// Checks if the mouse is over the icons.\n\tbool getMouseOverIcons() const;\n\t/// Is the player allowed to press buttons?\n\tbool allowButtons(bool allowSaving = false) const;\n\t/// Handler for clicking the reserve TUs to kneel button.\n\tvoid btnReserveKneelClick(Action *action);\n\t/// Handler for clicking the expend all TUs button.\n\tvoid btnZeroTUsClick(Action *action);\n\t/// Handler for showing tooltip.\n\tvoid txtTooltipIn(Action *action);\n\t/// Handler for showing tooltip with extra information (used for medikit-type equipment)\n\tvoid txtTooltipInExtra(Action *action, bool leftHand, bool special = false);\n\tvoid txtTooltipInExtraLeftHand(Action *action);\n\tvoid txtTooltipInExtraRightHand(Action *action);\n\tvoid txtTooltipInExtraSpecial(Action *action);\n\t/// Handler for showing tooltip with extra information (about current turn)\n\tvoid txtTooltipInEndTurn(Action *action);\n\t/// Handler for hiding tooltip.\n\tvoid txtTooltipOut(Action *action);\n\t/// Update the resolution settings, we just resized the window.\n\tvoid resize(int &dX, int &dY) override;\n\t/// Move the mouse back to where it started after we finish drag scrolling.\n\tvoid stopScrolling(Action *action);\n\t/// Autosave next turn.\n\tvoid autosave(int currentTurn);\n\t/// Is busy?\n\tbool isBusy() const;\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/BriefingLightState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"BriefingLightState.h\"\n#include <vector>\n#include \"../Engine/Game.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Interface/ToggleTextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/AlienDeployment.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Mod/ArticleDefinition.h\"\n#include \"../Mod/RuleStartingCondition.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Screen.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Ufopaedia/Ufopaedia.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the BriefingLight screen.\n * @param deployment Pointer to the mission deployment.\n */\nBriefingLightState::BriefingLightState(AlienDeployment *deployment)\n{\n\t_screen = true;\n\t// Create objects\n\t_window = new Window(this, 320, 200, 0, 0);\n\t_btnOk = new TextButton(140, 18, 164, 164);\n\t_btnArmors = new ToggleTextButton(140, 18, 16, 164);\n\t_txtTitle = new Text(300, 32, 16, 24);\n\t_txtBriefing = new Text(288, 104, 16, 56);\n\t_txtArmors = new Text(288, 25, 16, 56);\n\t_lstArmors = new TextList(288, 80, 8, 81);\n\n\tstd::string title = deployment->getType();\n\tstd::string desc = deployment->getAlertDescription();\n\n\tBriefingData data = deployment->getBriefingData();\n\tsetStandardPalette(\"PAL_GEOSCAPE\", data.palette);\n\t_window->setBackground(_game->getMod()->getSurface(data.background));\n\n\tadd(_window, \"window\", \"briefing\");\n\tadd(_btnOk, \"button\", \"briefing\");\n\tadd(_btnArmors, \"button\", \"briefing\");\n\tadd(_txtTitle, \"text\", \"briefing\");\n\tadd(_txtBriefing, \"text\", \"briefing\");\n\tadd(_txtArmors, \"text\", \"briefing\");\n\tadd(_lstArmors, \"text\", \"briefing\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&BriefingLightState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&BriefingLightState::btnOkClick, Options::keyOk);\n\t_btnOk->onKeyboardPress((ActionHandler)&BriefingLightState::btnOkClick, Options::keyCancel);\n\n\t_btnArmors->setText(tr(\"STR_WHAT_CAN_I_WEAR\"));\n\t_btnArmors->onMouseClick((ActionHandler)&BriefingLightState::btnArmorsClick);\n\t_btnArmors->setVisible(false);\n\n\t_txtTitle->setBig();\n\t_txtTitle->setText(tr(title));\n\n\t_txtBriefing->setWordWrap(true);\n\t_txtBriefing->setText(tr(desc));\n\n\t_txtArmors->setWordWrap(true);\n\t_txtArmors->setVisible(false);\n\n\t_lstArmors->setColumns(2, 148, 132);\n\t_lstArmors->setSelectable(true);\n\t_lstArmors->setBackground(_window);\n\t_lstArmors->setMargin(8);\n\t_lstArmors->setVisible(false);\n\n\tcheckStartingCondition(deployment);\n\n\t_lstArmors->onMouseClick((ActionHandler)&BriefingLightState::lstArmorsClick, SDL_BUTTON_MIDDLE);\n}\n\n/**\n* Checks the starting condition.\n*/\nvoid BriefingLightState::checkStartingCondition(AlienDeployment *deployment)\n{\n\tconst RuleStartingCondition *startingCondition = _game->getMod()->getStartingCondition(deployment->getStartingCondition());\n\tif (startingCondition != 0)\n\t{\n\t\tauto& list = startingCondition->getForbiddenArmors().empty() ? startingCondition->getAllowedArmors() : startingCondition->getForbiddenArmors();\n\t\tconst std::string messageCode = startingCondition->getForbiddenArmors().empty() ? \"STR_STARTING_CONDITION_ARMORS_ALLOWED\" : \"STR_STARTING_CONDITION_ARMORS_FORBIDDEN\";\n\t\tif (!list.empty())\n\t\t{\n\t\t\t_txtArmors->setText(tr(messageCode).arg(\"\")); // passing empty argument, because it is obsolete since a list display was introduced\n\t\t\t_btnArmors->setVisible(true);\n\n\t\t\tfor (auto& armorType : list)\n\t\t\t{\n\t\t\t\tArmor* armor = _game->getMod()->getArmor(armorType, false);\n\t\t\t\tArticleDefinition* article = _game->getMod()->getUfopaediaArticle(armor ? armor->getUfopediaType() : armorType, false);\n\t\t\t\tif (article && Ufopaedia::isArticleAvailable(_game->getSavedGame(), article))\n\t\t\t\t{\n\t\t\t\t\tstd::string translation = tr(armorType);\n\t\t\t\t\t_armorNameList.push_back(std::make_pair(armorType, translation));\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (_armorNameList.empty())\n\t\t\t{\n\t\t\t\t// no suitable armor yet\n\t\t\t\tstd::string translation = tr(\"STR_UNKNOWN\");\n\t\t\t\t_armorNameList.push_back(std::make_pair(\"STR_UNKNOWN\", translation));\n\t\t\t}\n\t\t\tstd::sort(_armorNameList.begin(), _armorNameList.end(), [&](std::pair<std::string, std::string>& a, std::pair<std::string, std::string>& b) { return Unicode::naturalCompare(a.second, b.second); });\n\t\t\tif (_armorNameList.size() % 2 != 0)\n\t\t\t{\n\t\t\t\t_armorNameList.push_back(std::make_pair(\"\", \"\")); // just padding, we want an even number of items in the list\n\t\t\t}\n\t\t\tsize_t halfSize = _armorNameList.size() / 2;\n\t\t\tfor (size_t i = 0; i < halfSize; ++i)\n\t\t\t{\n\t\t\t\t_lstArmors->addRow(2, _armorNameList[i].second.c_str(), _armorNameList[i + halfSize].second.c_str());\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n *\n */\nBriefingLightState::~BriefingLightState()\n{\n\n}\n\n/**\n * Closes the window.\n * @param action Pointer to an action.\n */\nvoid BriefingLightState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Shows allowed armors.\n * @param action Pointer to an action.\n */\nvoid BriefingLightState::btnArmorsClick(Action *)\n{\n\t_txtArmors->setVisible(_btnArmors->getPressed());\n\t_lstArmors->setVisible(_btnArmors->getPressed());\n\t_txtBriefing->setVisible(!_btnArmors->getPressed());\n}\n\n/**\n * Shows corresponding Ufopaedia article.\n * @param action Pointer to an action.\n */\nvoid BriefingLightState::lstArmorsClick(Action* action)\n{\n\tsize_t halfSize = _armorNameList.size() / 2;\n\n\tdouble mx = action->getAbsoluteXMouse();\n\tif (mx < _btnOk->getX())\n\t{\n\t\thalfSize = 0;\n\t}\n\n\tauto idx = halfSize + _lstArmors->getSelectedRow();\n\tconst std::string& armorType = _armorNameList[idx].first;\n\tArmor* armor = _game->getMod()->getArmor(armorType, false);\n\tif (armor)\n\t{\n\t\tstd::string articleId = armor->getUfopediaType();\n\t\tUfopaedia::openArticle(_game, articleId);\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/BriefingLightState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass ToggleTextButton;\nclass Window;\nclass Text;\nclass TextList;\nclass AlienDeployment;\n\n/**\n * Briefing screen which displays basic info\n * about a mission site or an alien base.\n */\nclass BriefingLightState : public State\n{\nprivate:\n\tTextButton *_btnOk;\n\tToggleTextButton *_btnArmors;\n\tWindow *_window;\n\tText *_txtTitle, *_txtBriefing, *_txtArmors;\n\tTextList* _lstArmors;\n\tstd::vector<std::pair<std::string, std::string> > _armorNameList;\n\t// Checks the starting condition\n\tvoid checkStartingCondition(AlienDeployment *deployment);\npublic:\n\t/// Creates the BriefingLight state.\n\tBriefingLightState(AlienDeployment *deployment);\n\t/// Cleans up the BriefingLight state.\n\t~BriefingLightState();\n\t/// Handler for clicking the Ok button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the Armors button.\n\tvoid btnArmorsClick(Action *action);\n\t/// Handler for clicking the Armors list.\n\tvoid lstArmorsClick(Action* action);\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/BriefingState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"BriefingState.h\"\n#include \"BattlescapeState.h\"\n#include \"BattlescapeGame.h\"\n#include \"AliensCrashState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/Window.h\"\n#include \"InventoryState.h\"\n#include \"NextTurnState.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/Craft.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Ufo.h\"\n#include \"../Mod/AlienDeployment.h\"\n#include \"../Mod/RuleUfo.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/RNG.h\"\n#include \"../Engine/Screen.h\"\n#include \"../Menu/CutsceneState.h\"\n#include \"../Savegame/AlienMission.h\"\n#include \"../Mod/RuleAlienMission.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Briefing screen.\n * @param game Pointer to the core game.\n * @param craft Pointer to the craft in the mission.\n * @param base Pointer to the base in the mission.\n * @param infoOnly Only show static info, when briefing is re-opened during the battle.\n * @param customBriefing Pointer to a custom briefing (used for Reinforcements notification).\n */\nBriefingState::BriefingState(Craft *craft, Base *base, bool infoOnly, BriefingData *customBriefing) : _infoOnly(infoOnly), _disableCutsceneAndMusic(false)\n{\n\tOptions::baseXResolution = Options::baseXGeoscape;\n\tOptions::baseYResolution = Options::baseYGeoscape;\n\t_game->getScreen()->resetDisplay(false);\n\n\t_screen = true;\n\t// Create objects\n\t_window = new Window(this, 320, 200, 0, 0);\n\t_btnOk = new TextButton(120, 18, 100, 164);\n\t_txtTitle = new Text(300, 32, 16, 24);\n\t_txtTarget = new Text(300, 17, 16, 40);\n\t_txtCraft = new Text(300, 17, 16, 56);\n\t_txtBriefing = new Text(274, 94, 16, 72);\n\n\tauto* battleSave = _game->getSavedGame()->getSavedBattle();\n\n\tstd::string mission = battleSave->getMissionType();\n\tAlienDeployment *deployment = _game->getMod()->getDeployment(mission);\n\tif (mission == \"STR_BASE_DEFENSE\")\n\t{\n\t\tAlienDeployment* customDeployment = _game->getMod()->getDeployment(battleSave->getAlienCustomDeploy());\n\t\tif (customDeployment && !customDeployment->getBriefingData().desc.empty())\n\t\t{\n\t\t\tdeployment = customDeployment;\n\t\t}\n\t}\n\telse\n\t{\n\t\tUfo* ufo = 0;\n\t\tif (!deployment && craft)\n\t\t{\n\t\t\tufo = dynamic_cast <Ufo*> (craft->getDestination());\n\t\t\tif (ufo) // landing site or crash site.\n\t\t\t{\n\t\t\t\tstd::string ufoMissionName = ufo->getRules()->getType();\n\t\t\t\tif (!battleSave->getAlienCustomMission().empty())\n\t\t\t\t{\n\t\t\t\t\t// fake underwater UFO\n\t\t\t\t\tufoMissionName = battleSave->getAlienCustomMission();\n\t\t\t\t}\n\t\t\t\tdeployment = _game->getMod()->getDeployment(ufoMissionName);\n\t\t\t}\n\t\t}\n\t}\n\n\tstd::string title = mission;\n\tstd::string desc = title + \"_BRIEFING\";\n\tif (!deployment && !customBriefing) // none defined - should never happen, but better safe than sorry i guess.\n\t{\n\t\tsetStandardPalette(\"PAL_GEOSCAPE\", 0);\n\t\t_musicId = \"GMDEFEND\";\n\t\t_window->setBackground(_game->getMod()->getSurface(\"BACK16.SCR\"));\n\t}\n\telse\n\t{\n\t\tBriefingData data = customBriefing ? *customBriefing : deployment->getBriefingData();\n\t\tsetStandardPalette(\"PAL_GEOSCAPE\", data.palette);\n\t\t_window->setBackground(_game->getMod()->getSurface(data.background));\n\t\t_txtCraft->setY(56 + data.textOffset);\n\t\t_txtBriefing->setY(72 + data.textOffset);\n\t\t_txtTarget->setVisible(data.showTarget);\n\t\t_txtCraft->setVisible(data.showCraft);\n\t\t_cutsceneId = data.cutscene;\n\t\t_musicId = data.music;\n\t\tif (!data.title.empty())\n\t\t{\n\t\t\ttitle = data.title;\n\t\t}\n\t\tif (!data.desc.empty())\n\t\t{\n\t\t\tdesc = data.desc;\n\t\t}\n\t}\n\t_disableCutsceneAndMusic = _infoOnly && !customBriefing;\n\n\tadd(_window, \"window\", \"briefing\");\n\tadd(_btnOk, \"button\", \"briefing\");\n\tadd(_txtTitle, \"text\", \"briefing\");\n\tadd(_txtTarget, \"text\", \"briefing\");\n\tadd(_txtCraft, \"text\", \"briefing\");\n\tadd(_txtBriefing, \"text\", \"briefing\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&BriefingState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&BriefingState::btnOkClick, Options::keyOk);\n\t_btnOk->onKeyboardPress((ActionHandler)&BriefingState::btnOkClick, Options::keyCancel);\n\n\t_txtTitle->setBig();\n\t_txtTarget->setBig();\n\t_txtCraft->setBig();\n\n\tif (!_infoOnly)\n\t{\n\t\tstd::string s;\n\t\tif (craft)\n\t\t{\n\t\t\tif (craft->getDestination())\n\t\t\t{\n\t\t\t\ts = craft->getDestination()->getName(_game->getLanguage());\n\t\t\t\tbattleSave->setMissionTarget(s);\n\t\t\t}\n\n\t\t\ts = tr(\"STR_CRAFT_\").arg(craft->getName(_game->getLanguage()));\n\t\t\tbattleSave->setMissionCraftOrBase(s);\n\t\t}\n\t\telse if (base)\n\t\t{\n\t\t\ts = tr(\"STR_BASE_UC_\").arg(base->getName());\n\t\t\tbattleSave->setMissionCraftOrBase(s);\n\t\t}\n\n\t\t// random operation names\n\t\tif (craft || base)\n\t\t{\n\t\t\tif (!_game->getMod()->getOperationNamesFirst().empty())\n\t\t\t{\n\t\t\t\tstd::ostringstream ss;\n\t\t\t\tint pickFirst = RNG::seedless(0, _game->getMod()->getOperationNamesFirst().size() - 1);\n\t\t\t\tss << _game->getMod()->getOperationNamesFirst().at(pickFirst);\n\t\t\t\tif (!_game->getMod()->getOperationNamesLast().empty())\n\t\t\t\t{\n\t\t\t\t\tint pickLast = RNG::seedless(0, _game->getMod()->getOperationNamesLast().size() - 1);\n\t\t\t\t\tss << \" \" << _game->getMod()->getOperationNamesLast().at(pickLast);\n\t\t\t\t}\n\t\t\t\ts = ss.str();\n\t\t\t\tbattleSave->setMissionTarget(s);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (!_game->getMod()->getOperationNamesFirst().empty())\n\t\t_txtTarget->setText(tr(\"STR_OPERATION_UC\").arg(battleSave->getMissionTarget()));\n\telse\n\t\t_txtTarget->setText(battleSave->getMissionTarget());\n\n\t_txtCraft->setText(battleSave->getMissionCraftOrBase());\n\n\t_txtTitle->setText(tr(title));\n\n\tbool isPreview = battleSave->isPreview();\n\tif (isPreview)\n\t{\n\t\tif (battleSave->getCraftForPreview())\n\t\t{\n\t\t\tif (battleSave->getCraftForPreview()->getId() == RuleCraft::DUMMY_CRAFT_ID)\n\t\t\t{\n\t\t\t\t// we're using the same alienDeployment for the real craft preview and for the dummy craft preview,\n\t\t\t\t// but we want to have different briefing texts\n\t\t\t\tdesc = desc + \"_DUMMY\";\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// base preview\n\t\t\tdesc = desc + \"_PREVIEW\";\n\t\t}\n\t}\n\t_txtBriefing->setWordWrap(true);\n\t_txtBriefing->setText(tr(desc));\n\n\tif (_infoOnly) return;\n\n\tif (!isPreview && base && mission == \"STR_BASE_DEFENSE\")\n\t{\n\t\tauto* am = base->getRetaliationMission();\n\n\t\t// And make sure the base is unmarked (but only for vanilla retaliations, not for instant retaliations)\n\t\tif (am)\n\t\t{\n\t\t\tbase->setRetaliationTarget(false);\n\t\t}\n\n\t\tif (am && am->getRules().isMultiUfoRetaliation())\n\t\t{\n\t\t\t// Remember that more UFOs may be coming\n\t\t\tam->setMultiUfoRetaliationInProgress(true);\n\t\t}\n\t}\n}\n\n/**\n *\n */\nBriefingState::~BriefingState()\n{\n\n}\n\nvoid BriefingState::init()\n{\n\tState::init();\n\tif (_disableCutsceneAndMusic) return;\n\n\tif (!_cutsceneId.empty())\n\t{\n\t\t_game->pushState(new CutsceneState(_cutsceneId));\n\n\t\t// don't play the cutscene again when we return to this state\n\t\t_cutsceneId = \"\";\n\t}\n\telse\n\t{\n\t\t_game->getMod()->playMusic(_musicId);\n\t}\n}\n\n/**\n * Closes the window.\n * @param action Pointer to an action.\n */\nvoid BriefingState::btnOkClick(Action *)\n{\n\t_game->popState();\n\tOptions::baseXResolution = Options::baseXBattlescape;\n\tOptions::baseYResolution = Options::baseYBattlescape;\n\t_game->getScreen()->resetDisplay(false);\n\tif (_infoOnly) return;\n\n\tBattlescapeState *bs = new BattlescapeState;\n\tbs->getBattleGame()->spawnFromPrimedItems();\n\tBattlescapeTally tally = bs->getBattleGame()->tallyUnits();\n\tbool isPreview = _game->getSavedGame()->getSavedBattle()->isPreview();\n\tif (tally.liveAliens > 0 || isPreview)\n\t{\n\t\t_game->pushState(bs);\n\t\t_game->getSavedGame()->getSavedBattle()->setBattleState(bs);\n\t\t_game->pushState(new NextTurnState(_game->getSavedGame()->getSavedBattle(), bs));\n\t\tif (isPreview)\n\t\t{\n\t\t\t// skip InventoryState\n\t\t\t_game->getSavedGame()->getSavedBattle()->startFirstTurn();\n\t\t\treturn;\n\t\t}\n\t\t_game->pushState(new InventoryState(false, bs, 0));\n\t}\n\telse\n\t{\n\t\tOptions::baseXResolution = Options::baseXGeoscape;\n\t\tOptions::baseYResolution = Options::baseYGeoscape;\n\t\t_game->getScreen()->resetDisplay(false);\n\t\tdelete bs;\n\t\t_game->pushState(new AliensCrashState);\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/BriefingState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass Craft;\nclass Base;\nstruct BriefingData;\n\n/**\n * Briefing screen which displays info\n * about a Crash Site mission.\n */\nclass BriefingState : public State\n{\nprivate:\n\tTextButton *_btnOk;\n\tWindow *_window;\n\tText *_txtTitle, *_txtTarget, *_txtCraft, *_txtBriefing;\n\tstd::string _cutsceneId, _musicId;\n\tbool _infoOnly;\n\tbool _disableCutsceneAndMusic;\npublic:\n\t/// Creates the Briefing state.\n\tBriefingState(Craft *craft = 0, Base *base = 0, bool infoOnly = false, BriefingData *customBriefing = nullptr);\n\t/// Cleans up the Briefing state.\n\t~BriefingState();\n\t/// Initialization\n\tvoid init() override;\n\t/// Handler for clicking the Ok button.\n\tvoid btnOkClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/Camera.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Camera.h\"\n#include \"Map.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Timer.h\"\n#include \"../fmath.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Sets up a camera.\n * @param spriteWidth Width of map sprite.\n * @param spriteHeight Height of map sprite.\n * @param mapsize_x Current map size in X axis.\n * @param mapsize_y Current map size in Y axis.\n * @param mapsize_z Current map size in Z axis.\n * @param map Pointer to map surface.\n * @param visibleMapHeight Current height the view is at.\n */\nCamera::Camera(int spriteWidth, int spriteHeight, int mapsize_x, int mapsize_y, int mapsize_z, Map *map, int visibleMapHeight) :\n\t_scrollMouseTimer(0), _scrollKeyTimer(0),\n\t_spriteWidth(spriteWidth), _spriteHeight(spriteHeight),\n\t_mapsize_x(mapsize_x), _mapsize_y(mapsize_y), _mapsize_z(mapsize_z),\n\t_screenWidth(map->getWidth()), _screenHeight(map->getHeight()),\n\t_mapOffset(-250,250,0),\n\t_scrollMouseX(0), _scrollMouseY(0), _scrollKeyX(0), _scrollKeyY(0), _scrollTrigger(false),\n\t_visibleMapHeight(visibleMapHeight), _showAllLayers(false), _showSingleLayer(false),\n\t_map(map)\n{\n}\n\n/**\n * Deletes the Camera.\n */\nCamera::~Camera()\n{\n\n}\n\n/**\n * Sets the camera's scrolling timer.\n * @param mouse Pointer to mouse timer.\n * @param key Pointer to key timer.\n */\nvoid Camera::setScrollTimer(Timer *mouse, Timer *key)\n{\n\t_scrollMouseTimer = mouse;\n\t_scrollKeyTimer = key;\n}\n\n/**\n * Handles camera mouse shortcuts.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid Camera::mousePress(Action *action, State *)\n{\n\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT && Options::battleEdgeScroll == SCROLL_TRIGGER)\n\t{\n\t\t_scrollTrigger = true;\n\t\tmouseOver(action, 0);\n\t}\n\telse if (Options::battleDragScrollButton != SDL_BUTTON_MIDDLE || (SDL_GetMouseState(0,0)&SDL_BUTTON(Options::battleDragScrollButton)) == 0)\n\t{\n\t\tif (action->getDetails()->button.button == SDL_BUTTON_WHEELUP)\n\t\t{\n\t\t\tup();\n\t\t}\n\t\telse if (action->getDetails()->button.button == SDL_BUTTON_WHEELDOWN)\n\t\t{\n\t\t\tdown();\n\t\t}\n\t}\n}\n\n/**\n * Handles camera mouse shortcuts.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid Camera::mouseRelease(Action *action, State *)\n{\n\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT && Options::battleEdgeScroll == SCROLL_TRIGGER)\n\t{\n\t\t_scrollMouseX = 0;\n\t\t_scrollMouseY = 0;\n\t\t_scrollMouseTimer->stop();\n\t\t_scrollTrigger = false;\n\t\tint posX = action->getXMouse();\n\t\tint posY = action->getYMouse();\n\t\tif ((posX < (SCROLL_BORDER * action->getXScale()) && posX > 0)\n\t\t\t|| (posX > (_screenWidth - SCROLL_BORDER) * action->getXScale())\n\t\t\t|| (posY < (SCROLL_BORDER * action->getYScale()) && posY > 0)\n\t\t\t|| (posY > (_screenHeight - SCROLL_BORDER) * action->getYScale()))\n\t\t\t// A cheap hack to avoid handling this event as a click\n\t\t\t// on the map when the mouse is on the scroll-border\n\t\t\taction->getDetails()->button.button = 0;\n\t}\n}\n\n/**\n * Handles mouse over events.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid Camera::mouseOver(Action *action, State *)\n{\n\tif (_map->getCursorType() == CT_NONE)\n\t{\n\t\treturn;\n\t}\n\n\tif (Options::battleEdgeScroll == SCROLL_AUTO || _scrollTrigger)\n\t{\n\t\tint posX = action->getXMouse();\n\t\tint posY = action->getYMouse();\n\t\tint scrollSpeed = Options::battleScrollSpeed;\n\n\t\t//left scroll\n\t\tif (posX < (SCROLL_BORDER * action->getXScale()) && posX >= 0)\n\t\t{\n\t\t\t_scrollMouseX = scrollSpeed;\n\t\t\t// if close to top or bottom, also scroll diagonally\n\t\t\t//downleft\n\t\t\tif (posY < (SCROLL_DIAGONAL_EDGE * action->getYScale()) && posY >= 0)\n\t\t\t{\n\t\t\t\t_scrollMouseY = scrollSpeed/2;\n\t\t\t}\n\t\t\t//upleft\n\t\t\telse if (posY > (_screenHeight - SCROLL_DIAGONAL_EDGE) * action->getYScale())\n\t\t\t{\n\t\t\t\t_scrollMouseY = -scrollSpeed/2;\n\t\t\t}\n\t\t\telse _scrollMouseY = 0;\n\t\t}\n\t\t//right scroll\n\t\telse if (posX > (_screenWidth - SCROLL_BORDER) * action->getXScale())\n\t\t{\n\t\t\t_scrollMouseX = -scrollSpeed;\n\t\t\t// if close to top or bottom, also scroll diagonally\n\t\t\t//downright\n\t\t\tif (posY <= (SCROLL_DIAGONAL_EDGE * action->getYScale()) && posY >= 0)\n\t\t\t{\n\t\t\t\t_scrollMouseY = scrollSpeed/2;\n\t\t\t}\n\t\t\t//upright\n\t\t\telse if (posY > (_screenHeight - SCROLL_DIAGONAL_EDGE) * action->getYScale())\n\t\t\t{\n\t\t\t\t_scrollMouseY = -scrollSpeed/2;\n\t\t\t}\n\t\t\telse _scrollMouseY = 0;\n\t\t}\n\t\telse if (posX)\n\t\t{\n\t\t\t_scrollMouseX = 0;\n\t\t}\n\n\t\t//up\n\t\tif (posY < (SCROLL_BORDER * action->getYScale()) && posY >= 0)\n\t\t{\n\t\t\t_scrollMouseY = scrollSpeed;\n\t\t\t// if close to left or right edge, also scroll diagonally\n\t\t\t//up left\n\t\t\tif (posX < (SCROLL_DIAGONAL_EDGE * action->getXScale()) && posX >= 0)\n\t\t\t{\n\t\t\t\t_scrollMouseX = scrollSpeed;\n\t\t\t\t_scrollMouseY /=2;\n\t\t\t}\n\t\t\t//up right\n\t\t\telse if (posX > (_screenWidth - SCROLL_DIAGONAL_EDGE) * action->getXScale())\n\t\t\t{\n\t\t\t\t_scrollMouseX = -scrollSpeed;\n\t\t\t\t_scrollMouseY /=2;\n\t\t\t}\n\t\t}\n\t\t//down\n\t\telse if (posY > (_screenHeight- SCROLL_BORDER) * action->getYScale())\n\t\t{\n\t\t\t_scrollMouseY = -scrollSpeed;\n\t\t\t// if close to left or right edge, also scroll diagonally\n\t\t\t//down left\n\t\t\tif (posX < (SCROLL_DIAGONAL_EDGE * action->getXScale()) && posX >= 0)\n\t\t\t{\n\t\t\t\t_scrollMouseX = scrollSpeed;\n\t\t\t\t_scrollMouseY /=2;\n\t\t\t}\n\t\t\t//down right\n\t\t\telse if (posX > (_screenWidth - SCROLL_DIAGONAL_EDGE) * action->getXScale())\n\t\t\t{\n\t\t\t\t_scrollMouseX = -scrollSpeed;\n\t\t\t\t_scrollMouseY /=2;\n\t\t\t}\n\t\t}\n\t\telse if (posY && _scrollMouseX == 0)\n\t\t{\n\t\t\t_scrollMouseY = 0;\n\t\t}\n\n\t\tif ((_scrollMouseX || _scrollMouseY) && !_scrollMouseTimer->isRunning() && !_scrollKeyTimer->isRunning() && 0==(SDL_GetMouseState(0,0)&SDL_BUTTON(Options::battleDragScrollButton)))\n\t\t{\n\t\t\t_scrollMouseTimer->start();\n\t\t}\n\t\telse if ((!_scrollMouseX && !_scrollMouseY) && _scrollMouseTimer->isRunning())\n\t\t{\n\t\t\t_scrollMouseTimer->stop();\n\t\t}\n\t}\n}\n\n/**\n * Handles camera keyboard shortcuts.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid Camera::keyboardPress(Action *action, State *)\n{\n\tif (_map->getCursorType() == CT_NONE)\n\t{\n\t\treturn;\n\t}\n\n\tint key = action->getDetails()->key.keysym.sym;\n\tint scrollSpeed = Options::battleScrollSpeed;\n\tif (key == Options::keyBattleLeft)\n\t{\n\t\t_scrollKeyX = scrollSpeed;\n\t}\n\telse if (key == Options::keyBattleRight)\n\t{\n\t\t_scrollKeyX = -scrollSpeed;\n\t}\n\telse if (key == Options::keyBattleUp)\n\t{\n\t\t_scrollKeyY = scrollSpeed;\n\t}\n\telse if (key == Options::keyBattleDown)\n\t{\n\t\t_scrollKeyY = -scrollSpeed;\n\t}\n\n\tif ((_scrollKeyX || _scrollKeyY) && !_scrollKeyTimer->isRunning() && !_scrollMouseTimer->isRunning() && 0==(SDL_GetMouseState(0,0)&SDL_BUTTON(Options::battleDragScrollButton)))\n\t{\n\t\t_scrollKeyTimer->start();\n\t}\n\telse if ((!_scrollKeyX && !_scrollKeyY) && _scrollKeyTimer->isRunning())\n\t{\n\t\t_scrollKeyTimer->stop();\n\t}\n}\n\n/**\n * Handles camera keyboard shortcuts.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid Camera::keyboardRelease(Action *action, State *)\n{\n\tif (_map->getCursorType() == CT_NONE)\n\t{\n\t\treturn;\n\t}\n\n\tint key = action->getDetails()->key.keysym.sym;\n\tif (key == Options::keyBattleLeft)\n\t{\n\t\t_scrollKeyX = 0;\n\t}\n\telse if (key == Options::keyBattleRight)\n\t{\n\t\t_scrollKeyX = 0;\n\t}\n\telse if (key == Options::keyBattleUp)\n\t{\n\t\t_scrollKeyY = 0;\n\t}\n\telse if (key == Options::keyBattleDown)\n\t{\n\t\t_scrollKeyY = 0;\n\t}\n\n\tif ((_scrollKeyX || _scrollKeyY) && !_scrollKeyTimer->isRunning() && !_scrollMouseTimer->isRunning() && 0==(SDL_GetMouseState(0,0)&SDL_BUTTON(Options::battleDragScrollButton)))\n\t{\n\t\t_scrollKeyTimer->start();\n\t}\n\telse if ((!_scrollKeyX && !_scrollKeyY) && _scrollKeyTimer->isRunning())\n\t{\n\t\t_scrollKeyTimer->stop();\n\t}\n}\n\n/**\n * Handles mouse-scrolling.\n */\nvoid Camera::scrollMouse()\n{\n\tscrollXY(_scrollMouseX, _scrollMouseY, true);\n}\n\n/**\n * Handles keyboard-scrolling.\n */\nvoid Camera::scrollKey()\n{\n\tscrollXY(_scrollKeyX, _scrollKeyY, true);\n}\n\n/**\n * Handles scrolling with given deviation.\n * @param x X deviation.\n * @param y Y deviation.\n * @param redraw Redraw map or not.\n */\nvoid Camera::scrollXY(int x, int y, bool redraw)\n{\n\t_mapOffset.x += x;\n\t_mapOffset.y += y;\n\n\tdo\n\t{\n\t\tint xx = 0;\n\t\tint yy = 0;\n\t\tconvertScreenToMap((_screenWidth / 2), (_visibleMapHeight / 2), &xx, &yy);\n\t\t_center.x = xx;\n\t\t_center.y = yy;\n\n\t\t// Handling map bounds...\n\t\t// Ok, this is a prototype, it should be optimized.\n\t\t// Actually this should be calculated instead of slow-approximation.\n\t\tif (_center.x < 0)             { _mapOffset.x -= 1; _mapOffset.y -= 1; continue; }\n\t\tif (_center.x > _mapsize_x -1) { _mapOffset.x += 1; _mapOffset.y += 1; continue; }\n\t\tif (_center.y < 0)             { _mapOffset.x += 1; _mapOffset.y -= 1; continue; }\n\t\tif (_center.y > _mapsize_y -1) { _mapOffset.x -= 1; _mapOffset.y += 1; continue; }\n\t\tbreak;\n\t}\n\twhile (true);\n\n\t_map->refreshSelectorPosition();\n\tif (redraw) _map->invalidate();\n}\n\n\n/**\n * Handles jumping with given deviation.\n * @param x X deviation.\n * @param y Y deviation.\n */\nvoid Camera::jumpXY(int x, int y)\n{\n\t_mapOffset.x += x;\n\t_mapOffset.y += y;\n\tint xx = 0;\n\tint yy = 0;\n\tconvertScreenToMap((_screenWidth / 2), (_visibleMapHeight / 2), &xx, &yy);\n\t_center.x = xx;\n\t_center.y = yy;\n}\n\n\n/**\n * Goes one level up.\n */\nvoid Camera::up()\n{\n\tif (_mapOffset.z < _mapsize_z - 1)\n\t{\n\t\t_mapOffset.z++;\n\t\t_mapOffset.y += _spriteHeight * 3 / 5;\n\t\t_map->draw();\n\t}\n}\n\n/**\n * Goes one level down.\n */\nvoid Camera::down()\n{\n\tif (_mapOffset.z > 0)\n\t{\n\t\t_mapOffset.z--;\n\t\t_mapOffset.y -= _spriteHeight * 3 / 5;\n\t\t_map->draw();\n\t}\n}\n\n/**\n * Sets the view level.\n * @param viewlevel New view level.\n */\nvoid Camera::setViewLevel(int viewlevel)\n{\n\t_mapOffset.z = Clamp(viewlevel, 0, _mapsize_z - 1);\n\t_map->draw();\n}\n\n\n/**\n * Centers map on a certain position.\n * @param mapPos Position to center on.\n * @param redraw Redraw map or not.\n */\nvoid Camera::centerOnPosition(Position mapPos, bool redraw)\n{\n\tPosition screenPos;\n\t_center = mapPos;\n\t_center.x = Clamp<int>(_center.x, -1, _mapsize_x);\n\t_center.y = Clamp<int>(_center.y, -1, _mapsize_y);\n\tconvertMapToScreen(_center, &screenPos);\n\n\t_mapOffset.x = -(screenPos.x - (_screenWidth / 2));\n\t_mapOffset.y = -(screenPos.y - (_visibleMapHeight / 2));\n\n\t_mapOffset.z = _center.z;\n\tif (redraw) _map->draw();\n}\n\n/**\n * Gets map's center position.\n * @return Map's center position.\n */\nPosition Camera::getCenterPosition()\n{\n\t_center.z = _mapOffset.z;\n\treturn _center;\n}\n\n/**\n * Converts screen coordinates to map coordinates.\n * @param screenX Screen x position.\n * @param screenY Screen y position.\n * @param mapX Map x position.\n * @param mapY Map y position.\n */\nvoid Camera::convertScreenToMap(int screenX, int screenY, int *mapX, int *mapY) const\n{\n\t// add half a tile height to the mouse position per layer we are above the floor\n\tscreenY += (-_spriteWidth/2) + (_mapOffset.z) * ((_spriteHeight + _spriteWidth / 4) / 2);\n\n\t// calculate the actual x/y pixel position on a diamond shaped map\n\t// taking the view offset into account\n\t*mapY = - screenX + _mapOffset.x + 2 * screenY - 2 * _mapOffset.y;\n\t*mapX = screenY - _mapOffset.y - *mapY / 4 - (_spriteWidth/4);\n\n\t// to get the row & column itself, divide by the size of a tile\n\t*mapX /= (_spriteWidth / 4);\n\t*mapY /= _spriteWidth;\n\n\t*mapX = Clamp(*mapX, -1, _mapsize_x);\n\t*mapY = Clamp(*mapY, -1, _mapsize_y);\n}\n\n/**\n * Converts map coordinates X,Y,Z to screen positions X, Y.\n * @param mapPos X,Y,Z coordinates on the map.\n * @param screenPos Screen position.\n */\nvoid Camera::convertMapToScreen(Position mapPos, Position *screenPos) const\n{\n\tscreenPos->z = 0; // not used\n\tscreenPos->x = mapPos.x * (_spriteWidth / 2) - mapPos.y * (_spriteWidth / 2);\n\tscreenPos->y = mapPos.x * (_spriteWidth / 4) + mapPos.y * (_spriteWidth / 4) - mapPos.z * ((_spriteHeight + _spriteWidth / 4) / 2);\n}\n\n/**\n * Converts voxel coordinates X,Y,Z to screen positions X, Y.\n * @param voxelPos X,Y,Z coordinates of the voxel.\n * @param screenPos Screen position.\n */\nvoid Camera::convertVoxelToScreen(Position voxelPos, Position *screenPos) const\n{\n\tPosition mapPosition = voxelPos.toTile();\n\tconvertMapToScreen(mapPosition, screenPos);\n\tdouble dx = voxelPos.x - (mapPosition.x * 16);\n\tdouble dy = voxelPos.y - (mapPosition.y * 16);\n\tdouble dz = voxelPos.z - (mapPosition.z * 24);\n\tscreenPos->x += (int)(dx - dy) + (_spriteWidth/2);\n\tscreenPos->y += (int)(((_spriteHeight / 2.0)) + (dx / 2.0) + (dy / 2.0) - dz);\n\tscreenPos->x += _mapOffset.x;\n\tscreenPos->y += _mapOffset.y;\n}\n\n/**\n * Gets the displayed level.\n * @return The displayed layer.\n */\nint Camera::getViewLevel() const\n{\n\treturn _mapOffset.z;\n}\n\n/**\n * Gets the map size x.\n * @return The map size x.\n */\nint Camera::getMapSizeX() const\n{\n\treturn _mapsize_x;\n}\n\n/**\n * Gets the map size y.\n * @return The map size y.\n */\nint Camera::getMapSizeY() const\n{\n\treturn _mapsize_y;\n}\n\n/**\n * Gets the map offset.\n * @return The map offset.\n */\nPosition Camera::getMapOffset() const\n{\n\treturn _mapOffset;\n}\n\n/**\n * Sets the map offset.\n * @param pos The map offset.\n */\nvoid Camera::setMapOffset(const Position& pos)\n{\n\t_mapOffset = pos;\n}\n\n/**\n * Toggles showing all map layers.\n * @return New layer setting.\n */\nint Camera::toggleShowAllLayers()\n{\n\t_showAllLayers = !_showAllLayers;\n\treturn _showAllLayers?2:1;\n}\n\n/**\n * Checks if the camera is showing all map layers.\n * @return Current layer setting.\n */\nbool Camera::getShowAllLayers() const\n{\n\treturn _showAllLayers;\n}\n\n/**\n * Checks if map coordinates X,Y,Z are on screen.\n * @param mapPos Coordinates to check.\n * @param unitWalking True to offset coordinates for a unit walking.\n * @param unitSize size of unit (0 - single, 1 - 2x2, etc, used for walking only\n * @param boundary True if it's for caching calculation\n * @return True if the map coordinates are on screen.\n */\nbool Camera::isOnScreen(Position mapPos, const bool unitWalking, const int unitSize, const bool boundary) const\n{\n\tPosition screenPos;\n\tconvertMapToScreen(mapPos, &screenPos);\n\tint posx = _spriteWidth/2, posy = _spriteHeight - _spriteWidth/4;\n\tint sizex = _spriteWidth/2, sizey = _spriteHeight/2;\n\tif (unitSize > 0)\n\t{\n\t\tposy -= _spriteWidth /4;\n\t\tsizex = _spriteWidth*unitSize;\n\t\tsizey = _spriteWidth*unitSize/2;\n\t}\n\tscreenPos.x += _mapOffset.x + posx;\n\tscreenPos.y += _mapOffset.y + posy;\n\tif (unitWalking)\n\t{\n/* pretty hardcoded hack to handle overlapping by icons\n(they are always in the center at the bottom of the screen)\nFree positioned icons would require more complex workaround.\n__________\n|________|\n||      ||\n|| ____ ||\n||_|XX|_||\n|________|\n */\n\t\tif (boundary) //to make sprite updates even being slightly outside of screen\n\t\t{\n\t\t\tsizex += _spriteWidth;\n\t\t\tsizey += _spriteWidth/2;\n\t\t}\n\t\tif ( screenPos.x < 0 - sizex\n\t\t\t|| screenPos.x >= _screenWidth + sizex\n\t\t\t|| screenPos.y < 0 - sizey\n\t\t\t|| screenPos.y >= _screenHeight + sizey ) return false; //totally outside\n\t\tint side = ( _screenWidth - _map->getIconWidth() ) / 2;\n\t\tif ( (screenPos.y < (_screenHeight - _map->getIconHeight()) + sizey) ) return true; //above icons\n\t\tif ( (side > 1) && ( (screenPos.x < side + sizex) || (screenPos.x >= (_screenWidth - side - sizex)) ) ) return true; //at sides (if there are any)\n\t\treturn false;\n\t}\n\telse\n\t{\n\t\treturn screenPos.x >= 0\n\t\t\t&& screenPos.x <= _screenWidth - 10\n\t\t\t&& screenPos.y >= 0\n\t\t\t&& screenPos.y <= _screenHeight - 10;\n\t}\n}\n\n/**\n * Resizes the viewable window of the camera.\n */\nvoid Camera::resize()\n{\n\t_screenWidth = _map->getWidth();\n\t_screenHeight = _map->getHeight();\n\t_visibleMapHeight = _map->getHeight() - _map->getIconHeight();\n}\n\nvoid Camera::stopKeyScrolling()\n{\n\t_scrollKeyTimer->stop();\n}\n\nvoid Camera::stopMouseScrolling()\n{\n\t_scrollMouseTimer->stop();\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/Camera.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Position.h\"\n\nnamespace OpenXcom\n{\n\nclass Action;\nclass State;\nclass Timer;\nclass Map;\n\n/**\n * Class handling camera movement, either by mouse or by events on the battlescape.\n */\nclass Camera\n{\nprivate:\n\tTimer *_scrollMouseTimer, *_scrollKeyTimer;\n\tint _spriteWidth, _spriteHeight;\n\tint _mapsize_x, _mapsize_y, _mapsize_z;\n\tint _screenWidth, _screenHeight;\n\tPosition _mapOffset, _center;\n\tint _scrollMouseX, _scrollMouseY, _scrollKeyX, _scrollKeyY;\n\tbool _scrollTrigger;\n\tint _visibleMapHeight;\n\tbool _showAllLayers;\n\tbool _showSingleLayer;\n\tMap *_map;\npublic:\n\tstatic const int SCROLL_BORDER = 5;\n\tstatic const int SCROLL_DIAGONAL_EDGE = 60;\n\t/// Creates a new camera.\n\tCamera(int spriteWidth, int spriteHeight, int mapsize_x, int mapsize_y, int mapsize_z, Map *map, int visibleMapHeight);\n\t/// Cleans up the camera.\n\t~Camera();\n\t/// Sets the camera's scroll timers.\n\tvoid setScrollTimer(Timer *mouse, Timer *key);\n\t/// Special handling for mouse press.\n\tvoid mousePress(Action *action, State *state);\n\t/// Special handling for mouse release.\n\tvoid mouseRelease(Action *action, State *state);\n\t/// Special handling for mouse over.\n\tvoid mouseOver(Action *action, State *state);\n\t/// Special handling for key presses.\n\tvoid keyboardPress(Action *action, State *state);\n\t/// Special handling for key releases.\n\tvoid keyboardRelease(Action *action, State *state);\n\t/// Scrolls the view for mouse-scrolling.\n\tvoid scrollMouse();\n\t/// Scrolls the view for keyboard-scrolling.\n\tvoid scrollKey();\n\t/// Scrolls the view a certain amount.\n\tvoid scrollXY(int x, int y, bool redraw);\n\t/// Jumps the view (when projectile in motion).\n\tvoid jumpXY(int x, int y);\n\t/// Moves map layer up.\n\tvoid up();\n\t/// Move map layer down.\n\tvoid down();\n\t/// Sets the view level.\n\tvoid setViewLevel(int viewlevel);\n\t/// Converts map coordinates to screen coordinates.\n\tvoid convertMapToScreen(Position mapPos, Position *screenPos) const;\n\t/// Converts voxel coordinates to screen coordinates.\n\tvoid convertVoxelToScreen(Position voxelPos, Position *screenPos) const;\n\t/// Converts screen coordinates to map coordinates.\n\tvoid convertScreenToMap(int screenX, int screenY, int *mapX, int *mapY) const;\n\t/// Center map on a position.\n\tvoid centerOnPosition(Position pos, bool redraw = true);\n\t/// Gets map's center position.\n\tPosition getCenterPosition();\n\t/// Gets the map displayed level.\n\tint getViewLevel() const;\n\t/// Gets the map size x.\n\tint getMapSizeX() const;\n\t/// Gets the map size y.\n\tint getMapSizeY() const;\n\t/// Get the map x/y screen offset.\n\tPosition getMapOffset() const;\n\t/// Sets the map x/y screen offset.\n\tvoid setMapOffset(const Position& pos);\n\t/// Toggles showing all map layers.\n\tint toggleShowAllLayers();\n\t/// Checks if the camera is showing all map layers.\n\tbool getShowAllLayers() const;\n\t/// Toggles showing a single map layer.\n\tvoid toggleShowSingleLayer() { _showSingleLayer = !_showSingleLayer; }\n\t/// Checks if the camera is showing a single map layer.\n\tbool getShowSingleLayer() const { return _showSingleLayer; }\n\t/// Checks if map coordinates X,Y,Z are on screen.\n\tbool isOnScreen(Position mapPos, const bool unitWalking, const int unitSize, const bool boundary) const;\n\t/// Resize the viewable area.\n\tvoid resize();\n\t/// stop key scrolling.\n\tvoid stopKeyScrolling();\n\t/// stop mouse scrolling.\n\tvoid stopMouseScrolling();\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/CannotReequipState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"CannotReequipState.h\"\n#include <sstream>\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Engine/Options.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Basescape/ManufactureState.h\"\n#include \"../Basescape/PurchaseState.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Cannot Reequip screen.\n * @param missingItems List of items still needed for reequip.\n * @param base Relevant xcom base.\n */\nCannotReequipState::CannotReequipState(std::vector<ReequipStat> &missingItems, Base *base) : _missingItems(missingItems), _base(base)\n{\n\t// Create objects\n\t_window = new Window(this, 320, 200, 0, 0);\n\t_btnManufacture = new TextButton(128, 14, 10, 178);\n\t_btnPurchase = new TextButton(128, 14, 144, 178);\n\t_btnOk = new TextButton(34, 14, 278, 178);\n\t_txtTitle = new Text(220, 32, 50, 8);\n\t_txtItem = new Text(142, 9, 10, 50);\n\t_txtQuantity = new Text(88, 9, 152, 50);\n\t_txtCraft = new Text(74, 9, 218, 50);\n\t_lstItems = new TextList(288, 112, 8, 58);\n\n\t// Set palette\n\tsetInterface(\"cannotReequip\");\n\n\tadd(_window, \"window\", \"cannotReequip\");\n\tadd(_btnManufacture, \"button\", \"cannotReequip\");\n\tadd(_btnPurchase, \"button\", \"cannotReequip\");\n\tadd(_btnOk, \"button\", \"cannotReequip\");\n\tadd(_txtTitle, \"heading\", \"cannotReequip\");\n\tadd(_txtItem, \"text\", \"cannotReequip\");\n\tadd(_txtQuantity, \"text\", \"cannotReequip\");\n\tadd(_txtCraft, \"text\", \"cannotReequip\");\n\tadd(_lstItems, \"list\", \"cannotReequip\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"cannotReequip\");\n\n\t_btnManufacture->setText(tr(\"STR_MANUFACTURE\"));\n\t_btnManufacture->onMouseClick((ActionHandler)&CannotReequipState::btnManufactureClick);\n\n\t_btnPurchase->setText(tr(\"STR_PURCHASE_RECRUIT\"));\n\t_btnPurchase->onMouseClick((ActionHandler)&CannotReequipState::btnPurchaseClick);\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&CannotReequipState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&CannotReequipState::btnOkClick, Options::keyOk);\n\t_btnOk->onKeyboardPress((ActionHandler)&CannotReequipState::btnOkClick, Options::keyCancel);\n\n\t_txtTitle->setText(tr(\"STR_NOT_ENOUGH_EQUIPMENT_TO_FULLY_RE_EQUIP_SQUAD\"));\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setBig();\n\t_txtTitle->setWordWrap(true);\n\n\t_txtItem->setText(tr(\"STR_ITEM\"));\n\n\t_txtQuantity->setText(tr(\"STR_QUANTITY_UC\"));\n\n\t_txtCraft->setText(tr(\"STR_CRAFT\"));\n\n\t_lstItems->setColumns(3, 162, 46, 80);\n\t_lstItems->setSelectable(true);\n\t_lstItems->setBackground(_window);\n\t_lstItems->setMargin(2);\n}\n\n/**\n *\n */\nCannotReequipState::~CannotReequipState()\n{\n}\n\n/**\n * Resets stuff when coming back from other screens.\n */\nvoid CannotReequipState::init()\n{\n\tState::init();\n\n\t_lstItems->clearList();\n\n\tfor (const auto& reequipStat : _missingItems)\n\t{\n\t\tif (reequipStat.qty > 0)\n\t\t{\n\t\t\tstd::ostringstream ss;\n\t\t\tss << reequipStat.qty;\n\t\t\t_lstItems->addRow(3, tr(reequipStat.item).c_str(), ss.str().c_str(), reequipStat.craft.c_str());\n\t\t}\n\t}\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid CannotReequipState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Goes to the Manufacture screen.\n * @param action Pointer to an action.\n */\nvoid CannotReequipState::btnManufactureClick(Action *)\n{\n\t_game->pushState(new ManufactureState(_base));\n}\n\n/**\n * Goes to the Purchase screen.\n * @param action Pointer to an action.\n */\nvoid CannotReequipState::btnPurchaseClick(Action *)\n{\n\t_game->pushState(new PurchaseState(_base, this));\n}\n\n/**\n * Gets the list of missing items.\n */\nconst std::vector<ReequipStat>& CannotReequipState::getMissingItems() const\n{\n\treturn _missingItems;\n}\n\n/**\n * Decreases the number of missing items by the bought amount.\n * @param rule Type of item.\n * @param amount Number of items bought.\n */\nvoid CannotReequipState::decreaseMissingItemCount(const RuleItem* rule, int amount)\n{\n\tfor (auto& reequipStat : _missingItems)\n\t{\n\t\tif (reequipStat.item == rule->getType())\n\t\t{\n\t\t\treequipStat.qty = std::max(0, reequipStat.qty - amount);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/CannotReequipState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include \"DebriefingState.h\"\n#include <vector>\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass TextList;\nclass Base;\n\n/**\n * Screen shown when there's not enough equipment\n * to re-equip a craft after a mission.\n */\nclass CannotReequipState : public State\n{\nprivate:\n\tstd::vector<ReequipStat> _missingItems;\n\tBase *_base;\n\n\tTextButton *_btnOk, *_btnManufacture, *_btnPurchase;\n\tWindow *_window;\n\tText *_txtTitle, *_txtItem, *_txtQuantity, *_txtCraft;\n\tTextList *_lstItems;\npublic:\n\t/// Creates the Cannot Reequip state.\n\tCannotReequipState(std::vector<ReequipStat> &missingItems, Base *base);\n\t/// Cleans up the Cannot Reequip state.\n\t~CannotReequipState();\n\t/// Resets state.\n\tvoid init() override;\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the Manufacture button.\n\tvoid btnManufactureClick(Action *action);\n\t/// Handler for clicking the Purchase/Hire button.\n\tvoid btnPurchaseClick(Action *action);\n\t/// Gets the list of missing items.\n\tconst std::vector<ReequipStat>& getMissingItems() const;\n\t// Decreases the number of missing items by the bought amount.\n\tvoid decreaseMissingItemCount(const RuleItem* rule, int amount);\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/CommendationLateState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"CommendationLateState.h\"\n#include <sstream>\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Savegame/Soldier.h\"\n#include \"../Savegame/SoldierDiary.h\"\n#include \"../Engine/Options.h\"\n#include \"../Mod/RuleCommendations.h\"\n#include \"../Ufopaedia/Ufopaedia.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Medals screen.\n * @param soldiersMedalled List of soldiers with medals.\n */\nCommendationLateState::CommendationLateState(std::vector<Soldier*> soldiersMedalled)\n{\n\t// Create object\n\t_window = new Window(this, 320, 200, 0, 0);\n\t_btnOk = new TextButton(288, 16, 16, 176);\n\t_txtTitle = new Text(300, 16, 10, 8);\n\t_lstSoldiers = new TextList(288, 128, 8, 32);\n\n\t// Set palette\n\tsetInterface(\"commendationsLate\");\n\n\tadd(_window, \"window\", \"commendationsLate\");\n\tadd(_btnOk, \"button\", \"commendationsLate\");\n\tadd(_txtTitle, \"text\", \"commendationsLate\");\n\tadd(_lstSoldiers, \"list\", \"commendationsLate\");\n\n\tcenterAllSurfaces();\n\n\t// Set up object\n\tsetWindowBackground(_window, \"commendationsLate\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&CommendationLateState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&CommendationLateState::btnOkClick, Options::keyOk);\n\t_btnOk->onKeyboardPress((ActionHandler)&CommendationLateState::btnOkClick, Options::keyCancel);\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_LOST_IN_SERVICE\"));\n\n\t_lstSoldiers->setColumns(3, 114, 90, 84);\n\t_lstSoldiers->setSelectable(true);\n\t_lstSoldiers->setBackground(_window);\n\t_lstSoldiers->setMargin(8);\n\t_lstSoldiers->setFlooding(true);\n\t_lstSoldiers->onMouseClick((ActionHandler)&CommendationLateState::lstSoldiersMouseClick);\n\n    /***\n\n                                            LOST IN SERVICE\n\n    SOLDIER NAME, RANK: ___, SCORE: ___, KILLS: ___, NUMBER OF MISSIONS: ___, DAYS WOUNDED: ___, TIMES HIT: ___\n      COMMENDATION\n      COMMENDATION\n      COMMENDATION\n      CAUSE OF DEATH: KILLED BY ALIEN_RACE ALIEN_RANK, USING WEAPON\n\n\n    ***/\n\n\tconst auto& commendationsList = _game->getMod()->getCommendationsList();\n\tbool modularCommendation;\n\tstd::string noun;\n\n\n\tint row = 0;\n\t// Loop over dead soldiers\n\tfor (auto* soldier : soldiersMedalled)\n\t{\n\t\t// Establish some base information\n\t\t_lstSoldiers->addRow(3, soldier->getName().c_str(),\n\t\t\t\t\t\t\t\ttr(soldier->getRankString()).c_str(),\n\t\t\t\t\t\t\t\ttr(\"STR_KILLS\").arg(soldier->getDiary()->getKillTotal()).c_str());\n\t\t_lstSoldiers->setRowColor(row, _lstSoldiers->getSecondaryColor());\n\t\t_commendationsNames.push_back(\"\");\n\t\trow++;\n\n\t\t// Loop over all commendation\n\t\tfor (auto commIter = commendationsList.begin(); commIter != commendationsList.end();)\n\t\t{\n\t\t\tconst auto& commType = (*commIter).first;\n\t\t\tconst auto* commRule = (*commIter).second;\n\n\t\t\tstd::ostringstream wssCommendation;\n\t\t\tmodularCommendation = false;\n\t\t\tnoun = \"noNoun\";\n\n\t\t\t// Loop over soldier's commendation\n\t\t\tfor (auto* soldierComm : *soldier->getDiary()->getSoldierCommendations())\n\t\t\t{\n\t\t\t\tif (soldierComm->getType() == commType && soldierComm->isNew() && noun == \"noNoun\")\n\t\t\t\t{\n\t\t\t\t\tsoldierComm->makeOld();\n\n\t\t\t\t\tif (soldierComm->getNoun() != \"noNoun\")\n\t\t\t\t\t{\n\t\t\t\t\t\tnoun = soldierComm->getNoun();\n\t\t\t\t\t\tmodularCommendation = true;\n\t\t\t\t\t}\n\t\t\t\t\t// Decoration level name\n\t\t\t\t\tint skipCounter = 0;\n\t\t\t\t\tint lastInt = -2;\n\t\t\t\t\tint thisInt = -1;\n\t\t\t\t\tint vectorIterator = 0;\n\t\t\t\t\tfor (auto wtf = commRule->getCriteria()->begin()->second.begin(); wtf != commRule->getCriteria()->begin()->second.end(); ++wtf)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (vectorIterator == soldierComm->getDecorationLevelInt() + 1)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthisInt = *wtf;\n\t\t\t\t\t\tif (wtf != commRule->getCriteria()->begin()->second.begin())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t--wtf;\n\t\t\t\t\t\t\tlastInt = *wtf;\n\t\t\t\t\t\t\t++wtf;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (thisInt == lastInt)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tskipCounter++;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvectorIterator++;\n\t\t\t\t\t}\n\t\t\t\t\t// Establish commendation's name\n\t\t\t\t\t// Medal name\n\t\t\t\t\twssCommendation << \"   \";\n\t\t\t\t\tif (modularCommendation)\n\t\t\t\t\t{\n\t\t\t\t\t\twssCommendation << tr(commType).arg(tr(noun));\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\twssCommendation << tr(commType);\n\t\t\t\t\t}\n\t\t\t\t\t_lstSoldiers->addRow(3, wssCommendation.str().c_str(), \"\", tr(soldierComm->getDecorationLevelName(skipCounter)).c_str());\n\t\t\t\t\t_commendationsNames.push_back(commType);\n\t\t\t\t\trow++;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} // END SOLDIER COMMS LOOP\n\n\t\t\tif (noun == \"noNoun\")\n\t\t\t{\n\t\t\t\t++commIter;\n\t\t\t}\n\t\t} // END COMMS LOOPS\n\t\t_lstSoldiers->addRow(3, \"\", \"\", \"\"); // Separator\n\t\t_commendationsNames.push_back(\"\");\n\t\trow++;\n\t} // END SOLDIER LOOP    \n}\n\n/**\n *\n */\nCommendationLateState::~CommendationLateState()\n{\n}\n\n/*\n*\n*/\nvoid CommendationLateState::lstSoldiersMouseClick(Action *)\n{\n\tUfopaedia::openArticle(_game, _commendationsNames[_lstSoldiers->getSelectedRow()]);\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid CommendationLateState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/CommendationLateState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass TextList;\nclass Soldier;\n\n/**\n * Medals screen that displays dead soldier medals.\n */\nclass CommendationLateState : public State\n{\nprivate:\n\tTextButton *_btnOk;\n\tWindow *_window;\n\tText *_txtTitle;\n\tTextList *_lstSoldiers;\n\tstd::vector<std::string> _commendationsNames;\npublic:\n\t/// Creates the Medals state.\n\tCommendationLateState(std::vector<Soldier*> soldiers);\n\t/// Cleans up the Medals state.\n\t~CommendationLateState();\n\t/// Handler for clicking on a medal.\n\tvoid lstSoldiersMouseClick(Action *action);\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/CommendationState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"CommendationState.h\"\n#include <sstream>\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Savegame/Soldier.h\"\n#include \"../Savegame/SoldierDiary.h\"\n#include \"../Engine/Options.h\"\n#include \"../Mod/RuleCommendations.h\"\n#include \"../Ufopaedia/Ufopaedia.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Medals screen.\n * @param soldiersMedalled List of soldiers with medals.\n */\nCommendationState::CommendationState(std::vector<Soldier*> soldiersMedalled)\n{\n\t// Create object\n\t_window = new Window(this, 320, 200, 0, 0);\n\t_btnOk = new TextButton(288, 16, 16, 176);\n\t_txtTitle = new Text(300, 16, 10, 8);\n\t_lstSoldiers = new TextList(288, 128, 8, 32);\n\n\t// Set palette\n\tsetInterface(\"commendations\");\n\n\tadd(_window, \"window\", \"commendations\");\n\tadd(_btnOk, \"button\", \"commendations\");\n\tadd(_txtTitle, \"heading\", \"commendations\");\n\tadd(_lstSoldiers, \"list\", \"commendations\");\n\n\tcenterAllSurfaces();\n\n\t// Set up object\n\tsetWindowBackground(_window, \"commendations\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&CommendationState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&CommendationState::btnOkClick, Options::keyOk);\n\t_btnOk->onKeyboardPress((ActionHandler)&CommendationState::btnOkClick, Options::keyCancel);\n\n\t_txtTitle->setText(tr(\"STR_MEDALS\"));\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setBig();\n\n\t_lstSoldiers->setColumns(2, 204, 84);\n\t_lstSoldiers->setSelectable(true);\n\t_lstSoldiers->setBackground(_window);\n\t_lstSoldiers->setMargin(8);\n\t_lstSoldiers->onMouseClick((ActionHandler)&CommendationState::lstSoldiersMouseClick);\n\n\tint row = 0;\n\tint titleRow = 0;\n\tconst auto& commendationsList = _game->getMod()->getCommendationsList();\n\tbool modularCommendation;\n\tstd::string noun;\n\tbool titleChosen = true;\n\n\tfor (auto commIter = commendationsList.begin(); commIter != commendationsList.end();)\n\t{\n\t\tconst auto& commType = (*commIter).first;\n\t\tconst auto* commRule = (*commIter).second;\n\n\t\tmodularCommendation = false;\n\t\tnoun = \"noNoun\";\n\t\tif (titleChosen)\n\t\t{\n\t\t\t_lstSoldiers->addRow(2, \"\", \"\"); // Blank row, will be filled in later\n\t\t\t_commendationsNames.push_back(\"\");\n\t\t\trow++;\n\t\t}\n\t\ttitleChosen = false;\n\t\ttitleRow = row - 1;\n\n\t\tfor (auto* soldier : soldiersMedalled)\n\t\t{\n\t\t\tfor (auto* soldierComm : *soldier->getDiary()->getSoldierCommendations())\n\t\t\t{\n\t\t\t\tif (soldierComm->getType() == commType && soldierComm->isNew() && noun == \"noNoun\")\n\t\t\t\t{\n\t\t\t\t\tsoldierComm->makeOld();\n\t\t\t\t\trow++;\n\n\t\t\t\t\tif (soldierComm->getNoun() != \"noNoun\")\n\t\t\t\t\t{\n\t\t\t\t\t\tnoun = soldierComm->getNoun();\n\t\t\t\t\t\tmodularCommendation = true;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Soldier name\n\t\t\t\t\tstd::ostringstream wssName;\n\t\t\t\t\twssName << \"   \";\n\t\t\t\t\twssName << soldier->getName();\n\t\t\t\t\t// Decoration level name\n\t\t\t\t\tint skipCounter = 0;\n\t\t\t\t\tint lastInt = -2;\n\t\t\t\t\tint thisInt = -1;\n\t\t\t\t\tint vectorIterator = 0;\n\t\t\t\t\tfor (auto wtf = commRule->getCriteria()->begin()->second.begin(); wtf != commRule->getCriteria()->begin()->second.end(); ++wtf)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (vectorIterator == soldierComm->getDecorationLevelInt() + 1)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthisInt = *wtf;\n\t\t\t\t\t\tif (wtf != commRule->getCriteria()->begin()->second.begin())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t--wtf;\n\t\t\t\t\t\t\tlastInt = *wtf;\n\t\t\t\t\t\t\t++wtf;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (thisInt == lastInt)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tskipCounter++;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvectorIterator++;\n\t\t\t\t\t}\n\t\t\t\t\t_lstSoldiers->addRow(2, wssName.str().c_str(), tr(soldierComm->getDecorationLevelName(skipCounter)).c_str());\n\t\t\t\t\t_commendationsNames.push_back(\"\");\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (titleRow != row - 1)\n\t\t{\n\t\t\t// Medal name\n\t\t\tif (modularCommendation)\n\t\t\t{\n\t\t\t\t_lstSoldiers->setCellText(titleRow, 0, tr(commType).arg(tr(noun)));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_lstSoldiers->setCellText(titleRow, 0, tr(commType));\n\t\t\t}\n\t\t\t_lstSoldiers->setRowColor(titleRow, _lstSoldiers->getSecondaryColor());\n\t\t\t_commendationsNames[titleRow] = commType;\n\t\t\ttitleChosen = true;\n\t\t}\n\t\tif (noun == \"noNoun\")\n\t\t{\n\t\t\t++commIter;\n\t\t}\n\t}\n}\n\n/**\n *\n */\nCommendationState::~CommendationState()\n{\n}\n\n/*\n*\n*/\nvoid CommendationState::lstSoldiersMouseClick(Action *)\n{\n\tUfopaedia::openArticle(_game, _commendationsNames[_lstSoldiers->getSelectedRow()]);\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid CommendationState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/CommendationState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass TextList;\nclass Soldier;\n\n/**\n * Medals screen that displays new soldier medals.\n */\nclass CommendationState : public State\n{\nprivate:\n\tTextButton *_btnOk;\n\tWindow *_window;\n\tText *_txtTitle;\n\tTextList *_lstSoldiers;\n\tstd::vector<std::string> _commendationsNames;\npublic:\n\t/// Creates the Medals state.\n\tCommendationState(std::vector<Soldier*> soldiers);\n\t/// Cleans up the Medals state.\n\t~CommendationState();\n\t/// Handler for clicking on a medal.\n\tvoid lstSoldiersMouseClick(Action *action);\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/ConfirmEndMissionState.cpp",
    "content": "/*\n * Copyright 2010-2015 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ConfirmEndMissionState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Engine/Action.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"BattlescapeState.h\"\n#include \"BattlescapeGame.h\"\n#include \"../Engine/Options.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the ConfirmEndMission window.\n * @param battleGame Pointer to the saved game.\n */\nConfirmEndMissionState::ConfirmEndMissionState(SavedBattleGame *battleGame, int wounded, BattlescapeGame *parent) : _battleGame(battleGame), _wounded(wounded), _parent(parent)\n{\n\t// Create objects\n\t_screen = false;\n\t_window = new Window(this, 320, 144, 0, 0);\n\t_txtTitle = new Text(304, 17, 16, 26);\n\t_txtWounded = new Text(304, 17, 16, 54);\n\t_txtConfirm = new Text(320, 17, 0, 80);\n\t_btnOk = new TextButton(120, 16, 16, 110);\n\t_btnCancel = new TextButton(120, 16, 184, 110);\n\n\t// Set palette\n\t_battleGame->setPaletteByDepth(this);\n\n\tadd(_window, \"messageWindowBorder\", \"battlescape\");\n\tadd(_txtTitle, \"messageWindows\", \"battlescape\");\n\tadd(_txtWounded, \"messageWindows\", \"battlescape\");\n\tadd(_txtConfirm, \"messageWindows\", \"battlescape\");\n\tadd(_btnOk, \"messageWindowButtons\", \"battlescape\");\n\tadd(_btnCancel, \"messageWindowButtons\", \"battlescape\");\n\n\t// Set up objects\n\t_window->setHighContrast(true);\n\t_window->setBackground(_game->getMod()->getSurface(\"TAC00.SCR\"));\n\n\t_txtTitle->setBig();\n\t_txtTitle->setHighContrast(true);\n\t_txtTitle->setText(tr(\"STR_MISSION_OVER\"));\t\t\n\n\t_txtWounded->setBig();\n\t_txtWounded->setHighContrast(true);\n\t_txtWounded->setText(tr(\"STR_UNITS_WITH_FATAL_WOUNDS\", _wounded));\n\n\t_txtConfirm->setBig();\n\t_txtConfirm->setAlign(ALIGN_CENTER);\n\t_txtConfirm->setHighContrast(true);\n\t_txtConfirm->setText(tr(\"STR_END_MISSION_QUESTION\"));\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->setHighContrast(true);\n\t_btnOk->onMouseClick((ActionHandler)&ConfirmEndMissionState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&ConfirmEndMissionState::btnOkClick, Options::keyOk);\n\n\t_btnCancel->setText(tr(\"STR_CANCEL_UC\"));\n\t_btnCancel->setHighContrast(true);\n\t_btnCancel->onMouseClick((ActionHandler)&ConfirmEndMissionState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&ConfirmEndMissionState::btnCancelClick, Options::keyCancel);\n\t_btnCancel->onKeyboardPress((ActionHandler)&ConfirmEndMissionState::btnCancelClick, Options::keyBattleAbort);\n\n\tcenterAllSurfaces();\n}\n\n/**\n *\n */\nConfirmEndMissionState::~ConfirmEndMissionState()\n{\n\n}\n\n/**\n * Confirms mission end.\n * @param action Pointer to an action.\n */\nvoid ConfirmEndMissionState::btnOkClick(Action *)\n{\n\t_game->popState();\n\t_parent->requestEndTurn(false);\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid ConfirmEndMissionState::btnCancelClick(Action *)\n{\n\t_game->popState();\n}\n\n\n}\n"
  },
  {
    "path": "src/Battlescape/ConfirmEndMissionState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2015 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass Window;\nclass Text;\nclass TextButton;\nclass SavedBattleGame;\nclass BattlescapeGame;\n\n/**\n * Screen which asks for confirmation to end the mission.\n * Note: only if auto-end battle option is enabled and if there are still soldiers with fatal wounds\n */\nclass ConfirmEndMissionState : public State\n{\nprivate:\n\tWindow *_window;\n\tText *_txtTitle, *_txtWounded, *_txtConfirm;\n\tTextButton *_btnOk, *_btnCancel;\n\tSavedBattleGame *_battleGame;\n\tint _wounded;\n\tBattlescapeGame *_parent;\npublic:\n\t/// Creates the ConfirmEndMission state.\n\tConfirmEndMissionState(SavedBattleGame *battleGame, int wounded, BattlescapeGame *parent);\n\t/// Cleans up the ConfirmEndMission state.\n\t~ConfirmEndMissionState();\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action *action);\n\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/DebriefingState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <algorithm>\n#include <functional>\n#include <climits>\n#include \"TileEngine.h\"\n#include \"DebriefingState.h\"\n#include \"CannotReequipState.h\"\n#include \"../Geoscape/GeoscapeEventState.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Interface/Window.h\"\n#include \"PromotionsState.h\"\n#include \"CommendationState.h\"\n#include \"CommendationLateState.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleCountry.h\"\n#include \"../Mod/RuleCraft.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"../Mod/RuleRegion.h\"\n#include \"../Mod/RuleSoldier.h\"\n#include \"../Mod/RuleUfo.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Savegame/AlienBase.h\"\n#include \"../Savegame/AlienMission.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/BattleItem.h\"\n#include \"../Savegame/Country.h\"\n#include \"../Savegame/Craft.h\"\n#include \"../Savegame/ItemContainer.h\"\n#include \"../Savegame/Region.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"../Savegame/Soldier.h\"\n#include \"../Savegame/SoldierDiary.h\"\n#include \"../Savegame/MissionSite.h\"\n#include \"../Savegame/Tile.h\"\n#include \"../Savegame/Ufo.h\"\n#include \"../Savegame/Vehicle.h\"\n#include \"../Savegame/BaseFacility.h\"\n#include <sstream>\n#include \"../Menu/ErrorMessageState.h\"\n#include \"../Menu/MainMenuState.h\"\n#include \"../Interface/Cursor.h\"\n#include \"../Engine/Exception.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/RNG.h\"\n#include \"../Basescape/ManageAlienContainmentState.h\"\n#include \"../Basescape/TransferBaseState.h\"\n#include \"../Engine/Screen.h\"\n#include \"../Basescape/SellState.h\"\n#include \"../Menu/SaveGameState.h\"\n#include \"../Mod/AlienDeployment.h\"\n#include \"../Mod/RuleInterface.h\"\n#include \"../Savegame/MissionStatistics.h\"\n#include \"../Savegame/BattleUnitStatistics.h\"\n#include \"../fallthrough.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Debriefing screen.\n * @param game Pointer to the core game.\n */\nDebriefingState::DebriefingState() :\n\t_eventToSpawn(nullptr), _region(0), _country(0),\n\t_positiveScore(true), _destroyBase(false), _promotions(false), _showSellButton(true), _initDone(false),\n\t_pageNumber(0)\n{\n\t_missionStatistics = new MissionStatistics();\n\n\tOptions::baseXResolution = Options::baseXGeoscape;\n\tOptions::baseYResolution = Options::baseYGeoscape;\n\t_game->getScreen()->resetDisplay(false);\n\n\t// Restore the cursor in case something weird happened\n\t_game->getCursor()->setVisible(true);\n\t_limitsEnforced = Options::storageLimitsEnforced ? 1 : 0;\n\n\t// Create objects\n\t_window = new Window(this, 320, 200, 0, 0);\n\t_btnOk = new TextButton(40, 12, 16, 180);\n\t_btnStats = new TextButton(60, 12, 244, 180);\n\t_btnSell = new TextButton(60, 12, 176, 180);\n\t_btnTransfer = new TextButton(80, 12, 88, 180);\n\t_txtTitle = new Text(300, 17, 16, 8);\n\t_txtItem = new Text(180, 9, 16, 24);\n\t_txtQuantity = new Text(60, 9, 200, 24);\n\t_txtScore = new Text(55, 9, 270, 24);\n\t_txtRecovery = new Text(180, 9, 16, 60);\n\t_txtRating = new Text(200, 9, 64, 180);\n\t_lstStats = new TextList(290, 80, 16, 32);\n\t_lstRecovery = new TextList(290, 80, 16, 32);\n\t_lstTotal = new TextList(290, 9, 16, 12);\n\n\t// Second page (soldier stats)\n\t_txtSoldier     = new Text(90, 9,  16, 24); //16..106 = 90\n\t_txtTU          = new Text(18, 9, 106, 24); //106\n\t_txtStamina     = new Text(18, 9, 124, 24); //124\n\t_txtHealth      = new Text(18, 9, 142, 24); //142\n\t_txtBravery     = new Text(18, 9, 160, 24); //160\n\t_txtReactions   = new Text(18, 9, 178, 24); //178\n\t_txtFiring      = new Text(18, 9, 196, 24); //196\n\t_txtThrowing    = new Text(18, 9, 214, 24); //214\n\t_txtMelee       = new Text(18, 9, 232, 24); //232\n\t_txtStrength    = new Text(18, 9, 250, 24); //250\n\t_txtPsiStrength = new Text(18, 9, 268, 24); //268\n\t_txtPsiSkill    = new Text(18, 9, 286, 24); //286..304 = 18\n\n\t_lstSoldierStats = new TextList(288, 144, 16, 32); // 18 rows\n\n\t_txtTooltip = new Text(200, 9, 64, 180);\n\n\t// Third page (recovered items)\n\t_lstRecoveredItems = new TextList(272, 144, 16, 32); // 18 rows\n\n\tapplyVisibility();\n\n\t// Set palette\n\tsetInterface(\"debriefing\");\n\n\t_ammoColor = _game->getMod()->getInterface(\"debriefing\")->getElement(\"totals\")->color;\n\n\tadd(_window, \"window\", \"debriefing\");\n\tadd(_btnOk, \"button\", \"debriefing\");\n\tadd(_btnStats, \"button\", \"debriefing\");\n\tadd(_btnSell, \"button\", \"debriefing\");\n\tadd(_btnTransfer, \"button\", \"debriefing\");\n\tadd(_txtTitle, \"heading\", \"debriefing\");\n\tadd(_txtItem, \"text\", \"debriefing\");\n\tadd(_txtQuantity, \"text\", \"debriefing\");\n\tadd(_txtScore, \"text\", \"debriefing\");\n\tadd(_txtRecovery, \"text\", \"debriefing\");\n\tadd(_txtRating, \"text\", \"debriefing\");\n\tadd(_lstStats, \"list\", \"debriefing\");\n\tadd(_lstRecovery, \"list\", \"debriefing\");\n\tadd(_lstTotal, \"totals\", \"debriefing\");\n\n\tadd(_txtSoldier, \"text\", \"debriefing\");\n\tadd(_txtTU, \"text\", \"debriefing\");\n\tadd(_txtStamina, \"text\", \"debriefing\");\n\tadd(_txtHealth, \"text\", \"debriefing\");\n\tadd(_txtBravery, \"text\", \"debriefing\");\n\tadd(_txtReactions, \"text\", \"debriefing\");\n\tadd(_txtFiring, \"text\", \"debriefing\");\n\tadd(_txtThrowing, \"text\", \"debriefing\");\n\tadd(_txtMelee, \"text\", \"debriefing\");\n\tadd(_txtStrength, \"text\", \"debriefing\");\n\tadd(_txtPsiStrength, \"text\", \"debriefing\");\n\tadd(_txtPsiSkill, \"text\", \"debriefing\");\n\tadd(_lstSoldierStats, \"list\", \"debriefing\");\n\tadd(_txtTooltip, \"text\", \"debriefing\");\n\n\tadd(_lstRecoveredItems, \"list\", \"debriefing\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"debriefing\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&DebriefingState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&DebriefingState::btnOkClick, Options::keyOk);\n\t_btnOk->onKeyboardPress((ActionHandler)&DebriefingState::btnOkClick, Options::keyCancel);\n\n\t_btnStats->onMouseClick((ActionHandler)&DebriefingState::btnStatsClick);\n\n\t_btnSell->setText(tr(\"STR_SELL\"));\n\t_btnSell->onMouseClick((ActionHandler)&DebriefingState::btnSellClick);\n\t_btnTransfer->setText(tr(\"STR_TRANSFER_UC\"));\n\t_btnTransfer->onMouseClick((ActionHandler)&DebriefingState::btnTransferClick);\n\n\t_txtTitle->setBig();\n\n\t_txtItem->setText(tr(\"STR_LIST_ITEM\"));\n\n\t_txtQuantity->setText(tr(\"STR_QUANTITY_UC\"));\n\t_txtQuantity->setAlign(ALIGN_RIGHT);\n\n\t_txtScore->setText(tr(\"STR_SCORE\"));\n\n\t_lstStats->setColumns(3, 224, 30, 64);\n\t_lstStats->setDot(true);\n\n\t_lstRecovery->setColumns(3, 224, 30, 64);\n\t_lstRecovery->setDot(true);\n\n\t_lstTotal->setColumns(2, 254, 64);\n\t_lstTotal->setDot(true);\n\n\t// Second page\n\t_txtSoldier->setText(tr(\"STR_NAME_UC\"));\n\n\t_txtTU->setAlign(ALIGN_CENTER);\n\t_txtTU->setText(tr(\"STR_TIME_UNITS_ABBREVIATION\"));\n\t_txtTU->setTooltip(\"STR_TIME_UNITS\");\n\t_txtTU->onMouseIn((ActionHandler)&DebriefingState::txtTooltipIn);\n\t_txtTU->onMouseOut((ActionHandler)&DebriefingState::txtTooltipOut);\n\n\t_txtStamina->setAlign(ALIGN_CENTER);\n\t_txtStamina->setText(tr(\"STR_STAMINA_ABBREVIATION\"));\n\t_txtStamina->setTooltip(\"STR_STAMINA\");\n\t_txtStamina->onMouseIn((ActionHandler)&DebriefingState::txtTooltipIn);\n\t_txtStamina->onMouseOut((ActionHandler)&DebriefingState::txtTooltipOut);\n\n\t_txtHealth->setAlign(ALIGN_CENTER);\n\t_txtHealth->setText(tr(\"STR_HEALTH_ABBREVIATION\"));\n\t_txtHealth->setTooltip(\"STR_HEALTH\");\n\t_txtHealth->onMouseIn((ActionHandler)&DebriefingState::txtTooltipIn);\n\t_txtHealth->onMouseOut((ActionHandler)&DebriefingState::txtTooltipOut);\n\n\t_txtBravery->setAlign(ALIGN_CENTER);\n\t_txtBravery->setText(tr(\"STR_BRAVERY_ABBREVIATION\"));\n\t_txtBravery->setTooltip(\"STR_BRAVERY\");\n\t_txtBravery->onMouseIn((ActionHandler)&DebriefingState::txtTooltipIn);\n\t_txtBravery->onMouseOut((ActionHandler)&DebriefingState::txtTooltipOut);\n\n\t_txtReactions->setAlign(ALIGN_CENTER);\n\t_txtReactions->setText(tr(\"STR_REACTIONS_ABBREVIATION\"));\n\t_txtReactions->setTooltip(\"STR_REACTIONS\");\n\t_txtReactions->onMouseIn((ActionHandler)&DebriefingState::txtTooltipIn);\n\t_txtReactions->onMouseOut((ActionHandler)&DebriefingState::txtTooltipOut);\n\n\t_txtFiring->setAlign(ALIGN_CENTER);\n\t_txtFiring->setText(tr(\"STR_FIRING_ACCURACY_ABBREVIATION\"));\n\t_txtFiring->setTooltip(\"STR_FIRING_ACCURACY\");\n\t_txtFiring->onMouseIn((ActionHandler)&DebriefingState::txtTooltipIn);\n\t_txtFiring->onMouseOut((ActionHandler)&DebriefingState::txtTooltipOut);\n\n\t_txtThrowing->setAlign(ALIGN_CENTER);\n\t_txtThrowing->setText(tr(\"STR_THROWING_ACCURACY_ABBREVIATION\"));\n\t_txtThrowing->setTooltip(\"STR_THROWING_ACCURACY\");\n\t_txtThrowing->onMouseIn((ActionHandler)&DebriefingState::txtTooltipIn);\n\t_txtThrowing->onMouseOut((ActionHandler)&DebriefingState::txtTooltipOut);\n\n\t_txtMelee->setAlign(ALIGN_CENTER);\n\t_txtMelee->setText(tr(\"STR_MELEE_ACCURACY_ABBREVIATION\"));\n\t_txtMelee->setTooltip(\"STR_MELEE_ACCURACY\");\n\t_txtMelee->onMouseIn((ActionHandler)&DebriefingState::txtTooltipIn);\n\t_txtMelee->onMouseOut((ActionHandler)&DebriefingState::txtTooltipOut);\n\n\t_txtStrength->setAlign(ALIGN_CENTER);\n\t_txtStrength->setText(tr(\"STR_STRENGTH_ABBREVIATION\"));\n\t_txtStrength->setTooltip(\"STR_STRENGTH\");\n\t_txtStrength->onMouseIn((ActionHandler)&DebriefingState::txtTooltipIn);\n\t_txtStrength->onMouseOut((ActionHandler)&DebriefingState::txtTooltipOut);\n\n\t_txtPsiStrength->setAlign(ALIGN_CENTER);\n\tif (_game->getMod()->isManaFeatureEnabled())\n\t{\n\t\t_txtPsiStrength->setText(tr(\"STR_MANA_ABBREVIATION\"));\n\t\t_txtPsiStrength->setTooltip(\"STR_MANA_POOL\");\n\t}\n\telse\n\t{\n\t\t_txtPsiStrength->setText(tr(\"STR_PSIONIC_STRENGTH_ABBREVIATION\"));\n\t\t_txtPsiStrength->setTooltip(\"STR_PSIONIC_STRENGTH\");\n\t}\n\t_txtPsiStrength->onMouseIn((ActionHandler)&DebriefingState::txtTooltipIn);\n\t_txtPsiStrength->onMouseOut((ActionHandler)&DebriefingState::txtTooltipOut);\n\n\t_txtPsiSkill->setAlign(ALIGN_CENTER);\n\t_txtPsiSkill->setText(tr(\"STR_PSIONIC_SKILL_ABBREVIATION\"));\n\t_txtPsiSkill->setTooltip(\"STR_PSIONIC_SKILL\");\n\t_txtPsiSkill->onMouseIn((ActionHandler)&DebriefingState::txtTooltipIn);\n\t_txtPsiSkill->onMouseOut((ActionHandler)&DebriefingState::txtTooltipOut);\n\n\t_lstSoldierStats->setColumns(13, 90, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0);\n\t_lstSoldierStats->setAlign(ALIGN_CENTER);\n\t_lstSoldierStats->setAlign(ALIGN_LEFT, 0);\n\t_lstSoldierStats->setDot(true);\n\n\t// Third page\n\tint firstColumnWidth = Clamp(_game->getMod()->getInterface(\"debriefing\")->getElement(\"list\")->custom, 90, 254);\n\t_lstRecoveredItems->setColumns(2, firstColumnWidth, 18);\n\t_lstRecoveredItems->setAlign(ALIGN_LEFT);\n\t_lstRecoveredItems->setDot(true);\n}\n\n/**\n *\n */\nDebriefingState::~DebriefingState()\n{\n\tfor (auto* ds : _stats)\n\t{\n\t\tdelete ds;\n\t}\n\tfor (auto& pair : _recoveryStats)\n\t{\n\t\tdelete pair.second;\n\t}\n\t_recoveryStats.clear();\n\t_rounds.clear();\n\t_roundsPainKiller.clear();\n\t_roundsStimulant.clear();\n\t_roundsHeal.clear();\n\t_recoveredItems.clear();\n}\n\nstd::string DebriefingState::makeSoldierString(int stat)\n{\n\tif (stat == 0) return \"\";\n\n\tstd::ostringstream ss;\n\tss << Unicode::TOK_COLOR_FLIP << '+' << stat << Unicode::TOK_COLOR_FLIP;\n\treturn ss.str();\n}\n\nvoid DebriefingState::applyVisibility()\n{\n\tbool showScore = _pageNumber == 0;\n\tbool showStats = _pageNumber == 1;\n\tbool showItems = _pageNumber == 2;\n\n\t// First page (scores)\n\t_txtItem->setVisible(showScore || showItems);\n\t_txtQuantity->setVisible(showScore);\n\t_txtScore->setVisible(showScore);\n\t_txtRecovery->setVisible(showScore);\n\t_txtRating->setVisible(showScore);\n\t_lstStats->setVisible(showScore);\n\t_lstRecovery->setVisible(showScore);\n\t_lstTotal->setVisible(showScore);\n\n\t// Second page (soldier stats)\n\t_txtSoldier->setVisible(showStats);\n\t_txtTU->setVisible(showStats);\n\t_txtStamina->setVisible(showStats);\n\t_txtHealth->setVisible(showStats);\n\t_txtBravery->setVisible(showStats);\n\t_txtReactions->setVisible(showStats);\n\t_txtFiring->setVisible(showStats);\n\t_txtThrowing->setVisible(showStats);\n\t_txtMelee->setVisible(showStats);\n\t_txtStrength->setVisible(showStats);\n\t_txtPsiStrength->setVisible(showStats);\n\t_txtPsiSkill->setVisible(showStats);\n\t_lstSoldierStats->setVisible(showStats);\n\t_txtTooltip->setVisible(showStats);\n\n\t// Third page (recovered items)\n\t_lstRecoveredItems->setVisible(showItems);\n\n\t// Set text on toggle button accordingly\n\t_btnSell->setVisible(showItems && _showSellButton);\n\t_btnTransfer->setVisible(showItems && _showSellButton && _game->getSavedGame()->getBases()->size() > 1);\n\tif (showScore)\n\t{\n\t\t_btnStats->setText(tr(\"STR_STATS\"));\n\t}\n\telse if (showStats)\n\t{\n\t\t_btnStats->setText(tr(\"STR_LOOT\"));\n\t}\n\telse if (showItems)\n\t{\n\t\t_btnStats->setText(tr(\"STR_SCORE\"));\n\t}\n}\n\nvoid DebriefingState::init()\n{\n\tState::init();\n\n\tif (_initDone)\n\t{\n\t\treturn;\n\t}\n\t_initDone = true;\n\n\tprepareDebriefing();\n\n\tfor (const auto& sse : _soldierStats)\n\t{\n\t\tauto tmp = sse.second.psiStrength;\n\t\tif (_game->getMod()->isManaFeatureEnabled())\n\t\t{\n\t\t\ttmp = sse.second.mana;\n\t\t}\n\t\t_lstSoldierStats->addRow(13, sse.first.c_str(),\n\t\t\t\tmakeSoldierString(sse.second.tu).c_str(),\n\t\t\t\tmakeSoldierString(sse.second.stamina).c_str(),\n\t\t\t\tmakeSoldierString(sse.second.health).c_str(),\n\t\t\t\tmakeSoldierString(sse.second.bravery).c_str(),\n\t\t\t\tmakeSoldierString(sse.second.reactions).c_str(),\n\t\t\t\tmakeSoldierString(sse.second.firing).c_str(),\n\t\t\t\tmakeSoldierString(sse.second.throwing).c_str(),\n\t\t\t\tmakeSoldierString(sse.second.melee).c_str(),\n\t\t\t\tmakeSoldierString(sse.second.strength).c_str(),\n\t\t\t\tmakeSoldierString(tmp).c_str(),\n\t\t\t\tmakeSoldierString(sse.second.psiSkill).c_str(),\n\t\t\t\t\"\");\n\t\t// note: final dummy element to cause dot filling until the end of the line\n\t}\n\n\t// compare stuff from after and before recovery\n\tif (_base && _showSellButton)\n\t{\n\t\tint row = 0;\n\t\tItemContainer *origBaseItems = _game->getSavedGame()->getSavedBattle()->getBaseStorageItems();\n\t\tfor (auto& itemType : _game->getMod()->getItemsList())\n\t\t{\n\t\t\tRuleItem *rule = _game->getMod()->getItem(itemType);\n\n\t\t\tint qty = _base->getStorageItems()->getItem(rule);\n\t\t\tif (qty > 0 && (Options::canSellLiveAliens || !rule->isAlien()))\n\t\t\t{\n\n\t\t\t\t// IGNORE vehicles and their ammo\n\t\t\t\t// Note: because their number in base has been messed up by Base::setupDefenses() already in geoscape :(\n\t\t\t\tif (rule->getVehicleUnit())\n\t\t\t\t{\n\t\t\t\t\t// if this vehicle requires ammo, remember to ignore it later too\n\t\t\t\t\tif (rule->getVehicleClipAmmo())\n\t\t\t\t\t{\n\t\t\t\t\t\torigBaseItems->addItem(rule->getVehicleClipAmmo(), 1000000);\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tqty -= origBaseItems->getItem(rule);\n\t\t\t\tif (qty > 0)\n\t\t\t\t{\n\t\t\t\t\t_recoveredItems[rule] = qty;\n\n\t\t\t\t\tstd::ostringstream ss;\n\t\t\t\t\tss << Unicode::TOK_COLOR_FLIP << qty << Unicode::TOK_COLOR_FLIP;\n\t\t\t\t\tstd::string item = tr(itemType);\n\t\t\t\t\tif (rule->getBattleType() == BT_AMMO || (rule->getBattleType() == BT_NONE && rule->getClipSize() > 0))\n\t\t\t\t\t{\n\t\t\t\t\t\titem.insert(0, \"  \");\n\t\t\t\t\t\t_lstRecoveredItems->addRow(2, item.c_str(), ss.str().c_str());\n\t\t\t\t\t\t_lstRecoveredItems->setRowColor(row, _ammoColor);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t_lstRecoveredItems->addRow(2, item.c_str(), ss.str().c_str());\n\t\t\t\t\t}\n\t\t\t\t\t++row;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tint total = 0, statsY = 0, recoveryY = 0;\n\tint civiliansSaved = 0, civiliansDead = 0;\n\tint aliensKilled = 0, aliensStunned = 0;\n\tfor (const auto* ds : _stats)\n\t{\n\t\tif (ds->qty == 0)\n\t\t\tcontinue;\n\n\t\tstd::ostringstream ss, ss2;\n\t\tss << Unicode::TOK_COLOR_FLIP << ds->qty << Unicode::TOK_COLOR_FLIP;\n\t\tss2 << Unicode::TOK_COLOR_FLIP << ds->score;\n\t\ttotal += ds->score;\n\t\tif (ds->recovery)\n\t\t{\n\t\t\t_lstRecovery->addRow(3, tr(ds->item).c_str(), ss.str().c_str(), ss2.str().c_str());\n\t\t\trecoveryY += 8;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_lstStats->addRow(3, tr(ds->item).c_str(), ss.str().c_str(), ss2.str().c_str());\n\t\t\tstatsY += 8;\n\t\t}\n\t\tif (ds->item == \"STR_CIVILIANS_SAVED\")\n\t\t{\n\t\t\tciviliansSaved = ds->qty;\n\t\t}\n\t\tif (ds->item == \"STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES\" || ds->item == \"STR_CIVILIANS_KILLED_BY_ALIENS\")\n\t\t{\n\t\t\tciviliansDead += ds->qty;\n\t\t}\n\t\tif (ds->item == \"STR_ALIENS_KILLED\")\n\t\t{\n\t\t\taliensKilled += ds->qty;\n\t\t}\n\t\tif (ds->item == \"STR_LIVE_ALIENS_RECOVERED\")\n\t\t{\n\t\t\taliensStunned += ds->qty;\n\t\t}\n\t}\n\tif (civiliansSaved && !civiliansDead && _missionStatistics->success == true)\n\t{\n\t\t_missionStatistics->valiantCrux = true;\n\t}\n\n\tstd::ostringstream ss3;\n\tss3 << total;\n\t_lstTotal->addRow(2, tr(\"STR_TOTAL_UC\").c_str(), ss3.str().c_str());\n\n\t// add the points to our activity score\n\tif (_region)\n\t{\n\t\t_region->addActivityXcom(total);\n\t}\n\tif (_country)\n\t{\n\t\t_country->addActivityXcom(total);\n\t}\n\n\t// Resize (if needed)\n\tif (statsY > 80) statsY = 80;\n\tif (recoveryY > 80) recoveryY = 80;\n\tif (statsY + recoveryY > 120)\n\t{\n\t\trecoveryY = 120 - statsY;\n\t\tif (recoveryY < 80) _lstRecovery->setHeight(recoveryY);\n\t\tif (recoveryY > 80) recoveryY = 80;\n\t}\n\n\t// Reposition to fit the screen\n\tif (recoveryY > 0)\n\t{\n\t\tif (_txtRecovery->getText().empty())\n\t\t{\n\t\t\t_txtRecovery->setText(tr(\"STR_BOUNTY\"));\n\t\t}\n\t\t_txtRecovery->setY(_lstStats->getY() + statsY + 5);\n\t\t_lstRecovery->setY(_txtRecovery->getY() + 8);\n\t\t_lstTotal->setY(_lstRecovery->getY() + recoveryY + 5);\n\t}\n\telse\n\t{\n\t\t_txtRecovery->setText(\"\");\n\t\t_lstTotal->setY(_lstStats->getY() + statsY + 5);\n\t}\n\n\t// Calculate rating\n\tstd::string rating;\n\tif (total <= -200)\n\t{\n\t\trating = \"STR_RATING_TERRIBLE\";\n\t}\n\telse if (total <= 0)\n\t{\n\t\trating = \"STR_RATING_POOR\";\n\t}\n\telse if (total <= 200)\n\t{\n\t\trating = \"STR_RATING_OK\";\n\t}\n\telse if (total <= 500)\n\t{\n\t\trating = \"STR_RATING_GOOD\";\n\t}\n\telse\n\t{\n\t\trating = \"STR_RATING_EXCELLENT\";\n\t}\n\n\tif (!_game->getMod()->getMissionRatings()->empty())\n\t{\n\t\trating = \"\";\n\t\tint temp = INT_MIN;\n\t\tfor (auto& pair : *_game->getMod()->getMissionRatings())\n\t\t{\n\t\t\tif (pair.first > temp && pair.first <= total)\n\t\t\t{\n\t\t\t\ttemp = pair.first;\n\t\t\t\trating = pair.second;\n\t\t\t}\n\t\t}\n\t}\n\n\t_missionStatistics->rating = rating;\n\t_missionStatistics->score = total;\n\t_txtRating->setText(tr(\"STR_RATING\").arg(tr(rating)));\n\n\tSavedGame *save = _game->getSavedGame();\n\tSavedBattleGame *battle = save->getSavedBattle();\n\n\t_missionStatistics->daylight = save->getSavedBattle()->getGlobalShade();\n\t_missionStatistics->id = _game->getSavedGame()->getMissionStatistics()->size();\n\t_game->getSavedGame()->getMissionStatistics()->push_back(_missionStatistics);\n\n\t// Award Best-of commendations.\n\tint bestScoreID[7] = {0, 0, 0, 0, 0, 0, 0};\n\tint bestScore[7] = {0, 0, 0, 0, 0, 0, 0};\n\tint bestOverallScorersID = 0;\n\tint bestOverallScore = 0;\n\n\t// Check to see if any of the dead soldiers were exceptional.\n\tfor (auto* deadUnit : *battle->getUnits())\n\t{\n\t\tif (!deadUnit->getGeoscapeSoldier() || deadUnit->getStatus() != STATUS_DEAD)\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\n\t\t/// Post-mortem kill award\n\t\tint killTurn = -1;\n\t\tfor (auto* killerUnit : *battle->getUnits())\n\t\t{\n\t\t\tfor (auto* kill : killerUnit->getStatistics()->kills)\n\t\t\t{\n\t\t\t\tif (kill->id == deadUnit->getId())\n\t\t\t\t{\n\t\t\t\t\tkillTurn = kill->turn;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (killTurn != -1)\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tint postMortemKills = 0;\n\t\tif (killTurn != -1)\n\t\t{\n\t\t\tfor (auto* deadUnitKill : deadUnit->getStatistics()->kills)\n\t\t\t{\n\t\t\t\tif (deadUnitKill->turn > killTurn && deadUnitKill->faction == FACTION_HOSTILE)\n\t\t\t\t{\n\t\t\t\t\tpostMortemKills++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tdeadUnit->getGeoscapeSoldier()->getDiary()->awardPostMortemKill(postMortemKills);\n\n\t\tSoldierRank rank = deadUnit->getGeoscapeSoldier()->getRank();\n\t\t// Rookies don't get this next award. No one likes them.\n\t\tif (rank == RANK_ROOKIE)\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\n\t\t/// Best-of awards\n\t\t// Find the best soldier per rank by comparing score.\n\t\tfor (auto* deadSoldier : *_game->getSavedGame()->getDeadSoldiers())\n\t\t{\n\t\t\tint score = deadSoldier->getDiary()->getScoreTotal(_game->getSavedGame()->getMissionStatistics());\n\n\t\t\t// Don't forget this mission's score!\n\t\t\tif (deadSoldier->getId() == deadUnit->getId())\n\t\t\t{\n\t\t\t\tscore += _missionStatistics->score;\n\t\t\t}\n\n\t\t\tif (score > bestScore[rank])\n\t\t\t{\n\t\t\t\tbestScoreID[rank] = deadUnit->getId();\n\t\t\t\tbestScore[rank] = score;\n\t\t\t\tif (score > bestOverallScore)\n\t\t\t\t{\n\t\t\t\t\tbestOverallScorersID = deadUnit->getId();\n\t\t\t\t\tbestOverallScore = score;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t// Now award those soldiers commendations!\n\tfor (auto* deadUnit : *battle->getUnits())\n\t{\n\t\tif (!deadUnit->getGeoscapeSoldier() || deadUnit->getStatus() != STATUS_DEAD)\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\t\tif (deadUnit->getId() == bestScoreID[deadUnit->getGeoscapeSoldier()->getRank()])\n\t\t{\n\t\t\tdeadUnit->getGeoscapeSoldier()->getDiary()->awardBestOfRank(bestScore[deadUnit->getGeoscapeSoldier()->getRank()]);\n\t\t}\n\t\tif (deadUnit->getId() == bestOverallScorersID)\n\t\t{\n\t\t\tdeadUnit->getGeoscapeSoldier()->getDiary()->awardBestOverall(bestOverallScore);\n\t\t}\n\t}\n\n\tfor (auto* bu : *battle->getUnits())\n\t{\n\t\tif (bu->getGeoscapeSoldier())\n\t\t{\n\t\t\tint soldierAlienKills = 0;\n\t\t\tint soldierAlienStuns = 0;\n\t\t\tfor (auto* kill : bu->getStatistics()->kills)\n\t\t\t{\n\t\t\t\tif (kill->faction == FACTION_HOSTILE && kill->status == STATUS_DEAD)\n\t\t\t\t{\n\t\t\t\t\tsoldierAlienKills++;\n\t\t\t\t}\n\t\t\t\tif (kill->faction == FACTION_HOSTILE && kill->status == STATUS_UNCONSCIOUS)\n\t\t\t\t{\n\t\t\t\t\tsoldierAlienStuns++;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbu->getGeoscapeSoldier()->addStunCount(soldierAlienStuns);\n\n\t\t\tif (aliensKilled != 0 && aliensKilled == soldierAlienKills && _missionStatistics->success == true && aliensStunned == soldierAlienStuns)\n\t\t\t{\n\t\t\t\tbu->getStatistics()->nikeCross = true;\n\t\t\t}\n\t\t\tif (aliensStunned != 0 && aliensStunned == soldierAlienStuns && _missionStatistics->success == true && aliensKilled == 0)\n\t\t\t{\n\t\t\t\tbu->getStatistics()->mercyCross = true;\n\t\t\t}\n\t\t\tint daysWoundedTmp = bu->getGeoscapeSoldier()->getWoundRecovery(0.0f, 0.0f);\n\t\t\tbu->getStatistics()->daysWounded = daysWoundedTmp;\n\t\t\tif (daysWoundedTmp != 0)\n\t\t\t{\n\t\t\t\t_missionStatistics->injuryList[bu->getGeoscapeSoldier()->getId()] = daysWoundedTmp;\n\t\t\t}\n\n\t\t\t// Award Martyr Medal\n\t\t\tif (bu->getMurdererId() == bu->getId() && bu->getStatistics()->kills.size() != 0)\n\t\t\t{\n\t\t\t\tint martyrKills = 0; // How many aliens were killed on the same turn?\n\t\t\t\tint martyrTurn = -1;\n\t\t\t\tfor (auto* unitKill : bu->getStatistics()->kills)\n\t\t\t\t{\n\t\t\t\t\tif ( unitKill->id == bu->getId() )\n\t\t\t\t\t{\n\t\t\t\t\t\tmartyrTurn = unitKill->turn;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfor (auto* unitKill : bu->getStatistics()->kills)\n\t\t\t\t{\n\t\t\t\t\tif (unitKill->turn == martyrTurn && unitKill->faction == FACTION_HOSTILE)\n\t\t\t\t\t{\n\t\t\t\t\t\tmartyrKills++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (martyrKills > 0)\n\t\t\t\t{\n\t\t\t\t\tif (martyrKills > 10)\n\t\t\t\t\t{\n\t\t\t\t\t\tmartyrKills = 10;\n\t\t\t\t\t}\n\t\t\t\t\tbu->getStatistics()->martyr = martyrKills;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the UnitStats delta\n\t\t\tbu->getStatistics()->delta = *bu->getGeoscapeSoldier()->getCurrentStats() - *bu->getGeoscapeSoldier()->getInitStats();\n\n\t\t\tbu->getGeoscapeSoldier()->getDiary()->updateDiary(bu->getStatistics(), _game->getSavedGame()->getMissionStatistics(), _game->getMod());\n\t\t\tif (!bu->getStatistics()->MIA && !bu->getStatistics()->KIA &&\n\t\t\t\tbu->getGeoscapeSoldier()->getDiary()->manageCommendations(_game->getMod(), _game->getSavedGame(), bu->getGeoscapeSoldier()))\n\t\t\t{\n\t\t\t\t_soldiersCommended.push_back(bu->getGeoscapeSoldier());\n\t\t\t}\n\t\t\telse if (bu->getStatistics()->MIA || bu->getStatistics()->KIA)\n\t\t\t{\n\t\t\t\tbu->getGeoscapeSoldier()->getDiary()->manageCommendations(_game->getMod(), _game->getSavedGame(), bu->getGeoscapeSoldier());\n\t\t\t\t_deadSoldiersCommended.push_back(bu->getGeoscapeSoldier());\n\t\t\t}\n\t\t}\n\t}\n\n\t_positiveScore = (total > 0);\n\n\tstd::vector<Soldier*> participants;\n\tfor (auto* bu : *_game->getSavedGame()->getSavedBattle()->getUnits())\n\t{\n\t\tif (bu->getGeoscapeSoldier())\n\t\t{\n\t\t\tif (Options::fieldPromotions && !bu->hasGainedAnyExperience())\n\t\t\t{\n\t\t\t\t// Note: difference from OXC, soldier needs to actually have done something during the mission\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tparticipants.push_back(bu->getGeoscapeSoldier());\n\t\t}\n\t}\n\n\tif (Options::oxceAutomaticPromotions)\n\t{\n\t\t_promotions = _game->getSavedGame()->handlePromotions(participants, _game->getMod());\n\t}\n\n\t_game->getSavedGame()->setBattleGame(0);\n\n\tif (_positiveScore)\n\t{\n\t\t_game->getMod()->playMusic(Mod::DEBRIEF_MUSIC_GOOD);\n\t}\n\telse\n\t{\n\t\t_game->getMod()->playMusic(Mod::DEBRIEF_MUSIC_BAD);\n\t}\n}\n\n/**\n* Shows a tooltip for the appropriate text.\n* @param action Pointer to an action.\n*/\nvoid DebriefingState::txtTooltipIn(Action *action)\n{\n\t_currentTooltip = action->getSender()->getTooltip();\n\t_txtTooltip->setText(tr(_currentTooltip));\n}\n\n/**\n* Clears the tooltip text.\n* @param action Pointer to an action.\n*/\nvoid DebriefingState::txtTooltipOut(Action *action)\n{\n\tif (_currentTooltip == action->getSender()->getTooltip())\n\t{\n\t\t_txtTooltip->setText(\"\");\n\t}\n}\n\n/**\n * Displays soldiers' stat increases.\n * @param action Pointer to an action.\n */\nvoid DebriefingState::btnStatsClick(Action *)\n{\n\t_pageNumber = (_pageNumber + 1) % 3;\n\tapplyVisibility();\n}\n\n/**\n* Opens the Sell/Sack UI (for recovered items ONLY).\n* @param action Pointer to an action.\n*/\nvoid DebriefingState::btnSellClick(Action *)\n{\n\tif (!_destroyBase)\n\t{\n\t\t_game->pushState(new SellState(_base, this, OPT_BATTLESCAPE));\n\t}\n}\n\n/**\n * Opens the Transfer UI (for recovered items ONLY).\n * @param action Pointer to an action.\n */\nvoid DebriefingState::btnTransferClick(Action *)\n{\n\tif (!_destroyBase)\n\t{\n\t\t_game->pushState(new TransferBaseState(_base, this));\n\t}\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid DebriefingState::btnOkClick(Action *)\n{\n\t_game->popState();\n\tif (_game->getSavedGame()->getMonthsPassed() == -1)\n\t{\n\t\t_game->setState(new MainMenuState);\n\t}\n\telse\n\t{\n\t\t// Autosave after mission\n\t\tif (_game->getSavedGame()->isIronman())\n\t\t{\n\t\t\t_game->pushState(new SaveGameState(OPT_GEOSCAPE, SAVE_IRONMAN, _palette));\n\t\t}\n\t\telse if (Options::autosave)\n\t\t{\n\t\t\t_game->pushState(new SaveGameState(OPT_GEOSCAPE, SAVE_AUTO_GEOSCAPE, _palette));\n\t\t}\n\n\t\tif (_eventToSpawn)\n\t\t{\n\t\t\tbool canSpawn = _game->getSavedGame()->canSpawnInstantEvent(_eventToSpawn);\n\t\t\tif (canSpawn)\n\t\t\t{\n\t\t\t\t_game->pushState(new GeoscapeEventState(*_eventToSpawn));\n\t\t\t}\n\t\t}\n\t\tif (!_deadSoldiersCommended.empty())\n\t\t{\n\t\t\t_game->pushState(new CommendationLateState(_deadSoldiersCommended));\n\t\t}\n\t\tif (!_soldiersCommended.empty())\n\t\t{\n\t\t\t_game->pushState(new CommendationState(_soldiersCommended));\n\t\t}\n\t\tif (!_destroyBase)\n\t\t{\n\t\t\tif (_promotions)\n\t\t\t{\n\t\t\t\t_game->pushState(new PromotionsState);\n\t\t\t}\n\t\t\tif (!_missingItems.empty())\n\t\t\t{\n\t\t\t\t_game->pushState(new CannotReequipState(_missingItems, _base));\n\t\t\t}\n\t\t\t// remove the wounded soldiers (and their items too if needed); this was moved here from BattleUnit::postMissionProcedures()\n\t\t\tfor (auto* soldier : *_base->getSoldiers())\n\t\t\t{\n\t\t\t\tif (soldier->getCraft() != nullptr && soldier->isWounded())\n\t\t\t\t{\n\t\t\t\t\tsoldier->setCraftAndMoveEquipment(nullptr, _base, _game->getSavedGame()->getMonthsPassed() == -1);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// refresh! (we may have sold some prisoners in the meantime; directly from Debriefing)\n\t\t\tfor (const auto& pair : _containmentStateInfo)\n\t\t\t{\n\t\t\t\tif (pair.second == 2)\n\t\t\t\t{\n\t\t\t\t\tint availableContainment = _base->getAvailableContainment(pair.first);\n\t\t\t\t\tint usedContainment = _base->getUsedContainment(pair.first);\n\t\t\t\t\tint freeContainment = availableContainment - (usedContainment * _limitsEnforced);\n\t\t\t\t\tif (availableContainment > 0 && freeContainment >= 0)\n\t\t\t\t\t{\n\t\t\t\t\t\t_containmentStateInfo[pair.first] = 0; // 0 = OK\n\t\t\t\t\t}\n\t\t\t\t\telse if (usedContainment == 0)\n\t\t\t\t\t{\n\t\t\t\t\t\t_containmentStateInfo[pair.first] = 0; // 0 = OK\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (const auto& pair : _containmentStateInfo)\n\t\t\t{\n\t\t\t\tif (pair.second == 2)\n\t\t\t\t{\n\t\t\t\t\t_game->pushState(new ManageAlienContainmentState(_base, pair.first, OPT_BATTLESCAPE));\n\t\t\t\t\t_game->pushState(new ErrorMessageState(trAlt(\"STR_CONTAINMENT_EXCEEDED\", pair.first).arg(_base->getName()), _palette, _game->getMod()->getInterface(\"debriefing\")->getElement(\"errorMessage\")->color, \"BACK01.SCR\", _game->getMod()->getInterface(\"debriefing\")->getElement(\"errorPalette\")->color));\n\t\t\t\t}\n\t\t\t\telse if (pair.second == 1)\n\t\t\t\t{\n\t\t\t\t\t_game->pushState(new ErrorMessageState(\n\t\t\t\t\t\ttrAlt(\"STR_ALIEN_DIES_NO_ALIEN_CONTAINMENT_FACILITY\", pair.first),\n\t\t\t\t\t\t_palette,\n\t\t\t\t\t\t_game->getMod()->getInterface(\"debriefing\")->getElement(\"errorMessage\")->color,\n\t\t\t\t\t\t\"BACK01.SCR\",\n\t\t\t\t\t\t_game->getMod()->getInterface(\"debriefing\")->getElement(\"errorPalette\")->color));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (Options::storageLimitsEnforced && _base->storesOverfull())\n\t\t\t{\n\t\t\t\t_game->pushState(new SellState(_base, 0, OPT_BATTLESCAPE));\n\t\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_STORAGE_EXCEEDED\").arg(_base->getName()), _palette, _game->getMod()->getInterface(\"debriefing\")->getElement(\"errorMessage\")->color, \"BACK01.SCR\", _game->getMod()->getInterface(\"debriefing\")->getElement(\"errorPalette\")->color));\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Adds to the debriefing stats.\n * @param name The untranslated name of the stat.\n * @param quantity The quantity to add.\n * @param score The score to add.\n */\nvoid DebriefingState::addStat(const std::string &name, int quantity, int score)\n{\n\tfor (auto* ds : _stats)\n\t{\n\t\tif (ds->item == name)\n\t\t{\n\t\t\tds->qty = ds->qty + quantity;\n\t\t\tds->score = ds->score + score;\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n/**\n * Prepares debriefing: gathers Aliens, Corpses, Artefacts, UFO Components.\n * Adds the items to the craft.\n * Also calculates the soldiers experience, and possible promotions.\n * If aborted, only the things on the exit area are recovered.\n */\nvoid DebriefingState::prepareDebriefing()\n{\n\tfor (auto& itemType : _game->getMod()->getItemsList())\n\t{\n\t\tRuleItem *rule = _game->getMod()->getItem(itemType);\n\t\tif (rule->getSpecialType() > 1 && rule->getSpecialType() < DEATH_TRAPS)\n\t\t{\n\t\t\tRecoveryItem *item = new RecoveryItem();\n\t\t\titem->name = itemType;\n\t\t\titem->value = rule->getRecoveryPoints();\n\t\t\t_recoveryStats[rule->getSpecialType()] = item;\n\t\t\t_missionStatistics->lootValue = item->value;\n\t\t}\n\t}\n\n\tSavedGame *save = _game->getSavedGame();\n\tSavedBattleGame *battle = save->getSavedBattle();\n\n\tAlienDeployment *ruleDeploy = _game->getMod()->getDeployment(battle->getMissionType());\n\t// OXCE: Don't forget custom mission overrides\n\tAlienDeployment* alienCustomMission = _game->getMod()->getDeployment(battle->getAlienCustomMission());\n\tif (alienCustomMission)\n\t{\n\t\truleDeploy = alienCustomMission;\n\t}\n\t// OXCE: Don't forget about UFO landings/crash sites\n\tif (!ruleDeploy)\n\t{\n\t\tfor (auto* ufo : *save->getUfos())\n\t\t{\n\t\t\tif (ufo->isInBattlescape())\n\t\t\t{\n\t\t\t\t// Note: fake underwater UFO deployment was already considered above (via alienCustomMission)\n\t\t\t\truleDeploy = _game->getMod()->getDeployment(ufo->getRules()->getType());\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tbool aborted = battle->isAborted();\n\tbool success = !aborted || battle->allObjectivesDestroyed();\n\tCraft *craft = 0;\n\tBase *base = 0;\n\tstd::string target;\n\n\tint playersInExitArea1 = 0; // if playersInExitArea2 stays 0 the craft is lost...\n\tint playersSurvived = 0; // if this stays 0 the craft is lost...\n\tint playersUnconscious = 0;\n\tint playersInEntryArea1 = 0;\n\tint playersMIA = 0;\n\n\t_stats.push_back(new DebriefingStat(\"STR_ALIENS_KILLED\", false));\n\t_stats.push_back(new DebriefingStat(\"STR_ALIEN_CORPSES_RECOVERED\", false));\n\t_stats.push_back(new DebriefingStat(\"STR_LIVE_ALIENS_RECOVERED\", false));\n\t_stats.push_back(new DebriefingStat(\"STR_LIVE_ALIENS_SURRENDERED\", false));\n\t_stats.push_back(new DebriefingStat(\"STR_ALIEN_ARTIFACTS_RECOVERED\", false));\n\n\tstd::string missionCompleteText, missionFailedText;\n\tstd::string objectiveCompleteText, objectiveFailedText;\n\tint objectiveCompleteScore = 0, objectiveFailedScore = 0;\n\tif (ruleDeploy)\n\t{\n\t\tif (ruleDeploy->getObjectiveCompleteInfo(objectiveCompleteText, objectiveCompleteScore, missionCompleteText))\n\t\t{\n\t\t\t_stats.push_back(new DebriefingStat(objectiveCompleteText, false));\n\t\t}\n\t\tif (ruleDeploy->getObjectiveFailedInfo(objectiveFailedText, objectiveFailedScore, missionFailedText))\n\t\t{\n\t\t\t_stats.push_back(new DebriefingStat(objectiveFailedText, false));\n\t\t}\n\t\tif (aborted && ruleDeploy->getAbortPenalty() != 0)\n\t\t{\n\t\t\t_stats.push_back(new DebriefingStat(\"STR_MISSION_ABORTED\", false));\n\t\t\taddStat(\"STR_MISSION_ABORTED\", 1, -ruleDeploy->getAbortPenalty());\n\t\t}\n\t}\n\tif (battle->getVIPSurvivalPercentage() > 0)\n\t{\n\t\t_stats.push_back(new DebriefingStat(\"STR_VIPS_LOST\", false));\n\t\t_stats.push_back(new DebriefingStat(\"STR_VIPS_SAVED\", false));\n\t}\n\n\t_stats.push_back(new DebriefingStat(\"STR_CIVILIANS_KILLED_BY_ALIENS\", false));\n\t_stats.push_back(new DebriefingStat(\"STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES\", false));\n\t_stats.push_back(new DebriefingStat(\"STR_CIVILIANS_SAVED\", false));\n\t_stats.push_back(new DebriefingStat(\"STR_XCOM_OPERATIVES_KILLED\", false));\n\t//_stats.push_back(new DebriefingStat(\"STR_XCOM_OPERATIVES_RETIRED_THROUGH_INJURY\", false));\n\t_stats.push_back(new DebriefingStat(\"STR_XCOM_OPERATIVES_MISSING_IN_ACTION\", false));\n\t_stats.push_back(new DebriefingStat(\"STR_TANKS_DESTROYED\", false));\n\t_stats.push_back(new DebriefingStat(\"STR_XCOM_CRAFT_LOST\", false));\n\n\tfor (const auto& pair : _recoveryStats)\n\t{\n\t\t_stats.push_back(new DebriefingStat(pair.second->name, true));\n\t}\n\n\t_missionStatistics->time = *save->getTime();\n\t_missionStatistics->type = battle->getMissionType();\n\t_stats.push_back(new DebriefingStat(_game->getMod()->getAlienFuelName(), true));\n\n\tfor (auto* xbase : *save->getBases())\n\t{\n\t\t// in case we have a craft - check which craft it is about\n\t\tfor (auto* xcraft : *xbase->getCrafts())\n\t\t{\n\t\t\tif (xcraft->isInBattlescape())\n\t\t\t{\n\t\t\t\tfor (auto* region : *save->getRegions())\n\t\t\t\t{\n\t\t\t\t\tif (region->getRules()->insideRegion(xcraft->getLongitude(), xcraft->getLatitude()))\n\t\t\t\t\t{\n\t\t\t\t\t\t_region = region;\n\t\t\t\t\t\t_missionStatistics->region = _region->getRules()->getType();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfor (auto* country : *save->getCountries())\n\t\t\t\t{\n\t\t\t\t\tif (country->getRules()->insideCountry(xcraft->getLongitude(), xcraft->getLatitude()))\n\t\t\t\t\t{\n\t\t\t\t\t\t_country = country;\n\t\t\t\t\t\t_missionStatistics->country = _country->getRules()->getType();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcraft = xcraft;\n\t\t\t\tbase = xbase;\n\t\t\t\tif (craft->getDestination() != 0)\n\t\t\t\t{\n\t\t\t\t\t_missionStatistics->markerName = craft->getDestination()->getMarkerName();\n\t\t\t\t\t_missionStatistics->markerId = craft->getDestination()->getMarkerId();\n\t\t\t\t\ttarget = craft->getDestination()->getType();\n\t\t\t\t\t// Ignore custom mission names\n\t\t\t\t\tif (dynamic_cast<AlienBase*>(craft->getDestination()))\n\t\t\t\t\t{\n\t\t\t\t\t\ttarget = \"STR_ALIEN_BASE\";\n\t\t\t\t\t}\n\t\t\t\t\telse if (dynamic_cast<MissionSite*>(craft->getDestination()))\n\t\t\t\t\t{\n\t\t\t\t\t\ttarget = \"STR_MISSION_SITE\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcraft->returnToBase();\n\t\t\t\tcraft->setMissionComplete(true);\n\t\t\t\tcraft->setInBattlescape(false);\n\t\t\t\tfor (auto* follower : craft->getCraftFollowers())\n\t\t\t\t{\n\t\t\t\t\tfollower->returnToBase();\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (xcraft->getDestination() != 0)\n\t\t\t{\n\t\t\t\tUfo* u = dynamic_cast<Ufo*>(xcraft->getDestination());\n\t\t\t\tif (u != 0 && u->isInBattlescape())\n\t\t\t\t{\n\t\t\t\t\txcraft->returnToBase();\n\t\t\t\t}\n\t\t\t\tMissionSite* ms = dynamic_cast<MissionSite*>(xcraft->getDestination());\n\t\t\t\tif (ms != 0 && ms->isInBattlescape())\n\t\t\t\t{\n\t\t\t\t\txcraft->returnToBase();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// in case we DON'T have a craft (base defense)\n\t\tif (xbase->isInBattlescape())\n\t\t{\n\t\t\tbase = xbase;\n\t\t\ttarget = base->getType();\n\t\t\tbase->setInBattlescape(false);\n\t\t\tbase->cleanupDefenses(false);\n\t\t\tfor (auto* region : *save->getRegions())\n\t\t\t{\n\t\t\t\tif (region->getRules()->insideRegion(base->getLongitude(), base->getLatitude()))\n\t\t\t\t{\n\t\t\t\t\t_region = region;\n\t\t\t\t\t_missionStatistics->region = _region->getRules()->getType();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (auto* country : *save->getCountries())\n\t\t\t{\n\t\t\t\tif (country->getRules()->insideCountry(base->getLongitude(), base->getLatitude()))\n\t\t\t\t{\n\t\t\t\t\t_country = country;\n\t\t\t\t\t_missionStatistics->country = _country->getRules()->getType();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Loop through the UFOs and see which one is sitting on top of the base... that is probably the one attacking you.\n\t\t\tfor (auto* ufo : *save->getUfos())\n\t\t\t{\n\t\t\t\tif (AreSame(ufo->getLongitude(), base->getLongitude()) && AreSame(ufo->getLatitude(), base->getLatitude()))\n\t\t\t\t{\n\t\t\t\t\t_missionStatistics->ufo = ufo->getRules()->getType(); // no need to check for fake underwater UFOs here\n\t\t\t\t\t_missionStatistics->alienRace = ufo->getAlienRace();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (aborted)\n\t\t\t{\n\t\t\t\t_destroyBase = true;\n\t\t\t}\n\n\t\t\t// This is an overkill, since we may not lose any hangar/craft, but doing it properly requires tons of changes\n\t\t\tsave->stopHuntingXcomCrafts(base);\n\n\t\t\tstd::vector<BaseFacility*> toBeDamaged;\n\t\t\tfor (auto* fac : *base->getFacilities())\n\t\t\t{\n\t\t\t\t// this facility was demolished\n\t\t\t\tif (battle->getModuleMap()[fac->getX()][fac->getY()].second == 0)\n\t\t\t\t{\n\t\t\t\t\ttoBeDamaged.push_back(fac);\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (auto* fac : toBeDamaged)\n\t\t\t{\n\t\t\t\tbase->damageFacility(fac);\n\t\t\t}\n\t\t\t// this may cause the base to become disjointed, destroy the disconnected parts.\n\t\t\tbase->destroyDisconnectedFacilities();\n\t\t}\n\t}\n\n\tif (!base && save->isIronman())\n\t{\n\t\tthrow Exception(\"Your save is corrupted. Try asking someone on the Openxcom forum to fix it for you.\");\n\t}\n\n\t// mission site disappears (even when you abort)\n\tUfo* ignoredUfo = nullptr;\n\tfor (auto msIt = save->getMissionSites()->begin(); msIt != save->getMissionSites()->end(); ++msIt)\n\t{\n\t\tMissionSite* ms = (*msIt);\n\t\tif (ms->isInBattlescape())\n\t\t{\n\t\t\tif (ms->getUfo())\n\t\t\t{\n\t\t\t\tignoredUfo = ms->getUfo();\n\t\t\t\tms->setUfo(nullptr);\n\t\t\t}\n\t\t\t_missionStatistics->alienRace = ms->getAlienRace();\n\t\t\tdelete ms;\n\t\t\tsave->getMissionSites()->erase(msIt);\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// lets see what happens with units\n\n\t// manual update state of all units\n\tfor (auto* unit : *battle->getUnits())\n\t{\n\t\t// scripts (or some bugs in the game) could make aliens or soldiers that have \"unresolved\" stun or death state.\n\t\t// Note: resolves the \"last bleeding alien\" too\n\t\tif (!unit->isOut() && unit->isOutThresholdExceed())\n\t\t{\n\t\t\tunit->instaFalling();\n\t\t\tif (unit->getTile())\n\t\t\t{\n\t\t\t\tbattle->getTileEngine()->itemDropInventory(unit->getTile(), unit);\n\t\t\t}\n\n\t\t\t//spawn corpse/body for unit to recover\n\t\t\tfor (int i = unit->getArmor()->getTotalSize() - 1; i >= 0; --i)\n\t\t\t{\n\t\t\t\tauto* corpse = battle->createItemForTile(unit->getArmor()->getCorpseBattlescape()[i], nullptr, unit);\n\t\t\t\tbattle->getTileEngine()->itemDrop(unit->getTile(), corpse, false);\n\t\t\t}\n\t\t}\n\t}\n\n\t// first, we evaluate how many surviving XCom units there are, and how many are conscious\n\t// and how many have died (to use for commendations)\n\tint deadSoldiers = 0;\n\tfor (auto* bu : *battle->getUnits())\n\t{\n\t\tif (bu->getOriginalFaction() == FACTION_PLAYER && bu->getStatus() != STATUS_DEAD)\n\t\t{\n\t\t\tif (bu->getStatus() == STATUS_UNCONSCIOUS || bu->getFaction() == FACTION_HOSTILE)\n\t\t\t{\n\t\t\t\tplayersUnconscious++;\n\t\t\t}\n\t\t\telse if (bu->isIgnored() && bu->getStunlevel() >= bu->getHealth())\n\t\t\t{\n\t\t\t\t// even for ignored xcom units, we need to know if they're conscious or unconscious\n\t\t\t\tplayersUnconscious++;\n\t\t\t}\n\t\t\telse if (bu->isInExitArea(END_POINT))\n\t\t\t{\n\t\t\t\tplayersInExitArea1++;\n\t\t\t}\n\t\t\telse if (bu->isInExitArea(START_POINT))\n\t\t\t{\n\t\t\t\tplayersInEntryArea1++;\n\t\t\t}\n\t\t\telse if (aborted)\n\t\t\t{\n\t\t\t\t// if aborted, conscious xcom unit that is not on start/end point counts as MIA\n\t\t\t\tplayersMIA++;\n\t\t\t}\n\t\t\tplayersSurvived++;\n\t\t}\n\t\telse if (bu->getOriginalFaction() == FACTION_PLAYER && bu->getStatus() == STATUS_DEAD)\n\t\t{\n\t\t\tdeadSoldiers++;\n\t\t}\n\t}\n\t// if all our men are unconscious, the aliens get to have their way with them.\n\tif (playersUnconscious + playersMIA == playersSurvived)\n\t{\n\t\tplayersSurvived = playersMIA;\n\t\tfor (auto* bu : *battle->getUnits())\n\t\t{\n\t\t\tif (bu->getOriginalFaction() == FACTION_PLAYER && bu->getStatus() != STATUS_DEAD)\n\t\t\t{\n\t\t\t\tif (bu->getStatus() == STATUS_UNCONSCIOUS || bu->getFaction() == FACTION_HOSTILE)\n\t\t\t\t{\n\t\t\t\t\tbu->instaKill();\n\t\t\t\t}\n\t\t\t\telse if (bu->isIgnored() && bu->getStunlevel() >= bu->getHealth())\n\t\t\t\t{\n\t\t\t\t\tbu->instaKill();\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// do nothing, units will be marked MIA later\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// if it's a UFO, let's see what happens to it\n\tfor (auto ufoIt = save->getUfos()->begin(); ufoIt != save->getUfos()->end(); ++ufoIt)\n\t{\n\t\tUfo* ufo = (*ufoIt);\n\t\tif (ufo->isInBattlescape())\n\t\t{\n\t\t\t_missionStatistics->ufo = ufo->getRules()->getType(); // no need to check for fake underwater UFOs here\n\t\t\tif (save->getMonthsPassed() != -1)\n\t\t\t{\n\t\t\t\t_missionStatistics->alienRace = ufo->getAlienRace();\n\t\t\t}\n\t\t\t_txtRecovery->setText(tr(\"STR_UFO_RECOVERY\"));\n\t\t\tufo->setInBattlescape(false);\n\t\t\t// if XCom failed to secure the landing zone, the UFO\n\t\t\t// takes off immediately and proceeds according to its mission directive\n\t\t\tif (ufo->getStatus() == Ufo::LANDED && (aborted || playersSurvived == 0))\n\t\t\t{\n\t\t\t\t ufo->setSecondsRemaining(5);\n\t\t\t}\n\t\t\t// if XCom succeeds, or it's a crash site, the UFO disappears\n\t\t\telse\n\t\t\t{\n\t\t\t\t// Note: just before removing a landed UFO, check for mission interruption (by setting the UFO damage to max)\n\t\t\t\tif (save->getMonthsPassed() > -1)\n\t\t\t\t{\n\t\t\t\t\tif (ufo->getStatus() == Ufo::LANDED)\n\t\t\t\t\t{\n\t\t\t\t\t\tufo->setDamage(ufo->getCraftStats().damageMax, _game->getMod());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tdelete ufo;\n\t\t\t\tsave->getUfos()->erase(ufoIt);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (ruleDeploy && ruleDeploy->getEscapeType() != ESCAPE_NONE)\n\t{\n\t\tif (ruleDeploy->getEscapeType() != ESCAPE_EXIT)\n\t\t{\n\t\t\tsuccess = playersInEntryArea1 > 0;\n\t\t}\n\n\t\tif (ruleDeploy->getEscapeType() != ESCAPE_ENTRY)\n\t\t{\n\t\t\tsuccess = success || playersInExitArea1 > 0;\n\t\t}\n\t}\n\n\tint playersInExitArea2 = 0;\n\n\tif (playersSurvived == 1)\n\t{\n\t\tfor (auto* bu : *battle->getUnits())\n\t\t{\n\t\t\t// if only one soldier survived, give him a medal! (unless he killed all the others...)\n\t\t\tif (bu->getStatus() != STATUS_DEAD && bu->getOriginalFaction() == FACTION_PLAYER && !bu->getStatistics()->hasFriendlyFired() && deadSoldiers != 0)\n\t\t\t{\n\t\t\t\tbu->getStatistics()->loneSurvivor = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t// if only one soldier survived AND none have died, means only one soldier went on the mission...\n\t\t\tif (bu->getStatus() != STATUS_DEAD && bu->getOriginalFaction() == FACTION_PLAYER && deadSoldiers == 0)\n\t\t\t{\n\t\t\t\tbu->getStatistics()->ironMan = true;\n\t\t\t}\n\t\t}\n\t}\n\t// alien base disappears (if you didn't abort)\n\tfor (auto abIt = save->getAlienBases()->begin(); abIt != save->getAlienBases()->end(); ++abIt)\n\t{\n\t\tAlienBase* ab = (*abIt);\n\t\tif (ab->isInBattlescape())\n\t\t{\n\t\t\t_txtRecovery->setText(tr(\"STR_ALIEN_BASE_RECOVERY\"));\n\t\t\tbool destroyAlienBase = true;\n\n\t\t\tif (aborted || playersSurvived == 0)\n\t\t\t{\n\t\t\t\tif (!battle->allObjectivesDestroyed())\n\t\t\t\t\tdestroyAlienBase = false;\n\t\t\t}\n\n\t\t\tif (ruleDeploy && !ruleDeploy->getNextStage().empty())\n\t\t\t{\n\t\t\t\t_missionStatistics->alienRace = ab->getAlienRace();\n\t\t\t\tdestroyAlienBase = false;\n\t\t\t}\n\n\t\t\tsuccess = destroyAlienBase;\n\t\t\tif (destroyAlienBase)\n\t\t\t{\n\t\t\t\tif (!objectiveCompleteText.empty())\n\t\t\t\t{\n\t\t\t\t\taddStat(objectiveCompleteText, 1, objectiveCompleteScore);\n\t\t\t\t}\n\t\t\t\tsave->clearLinksForAlienBase(ab, _game->getMod());\n\t\t\t\tdelete ab;\n\t\t\t\tsave->getAlienBases()->erase(abIt);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tab->setInBattlescape(false);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// transform all zombie-like units to spawned ones\n\tstd::vector<BattleUnit*> waitingTransformations;\n\tfor (auto* bu : *battle->getUnits())\n\t{\n\t\tif (bu->getSpawnUnit() && (!bu->isOut() || bu->isIgnored()))\n\t\t{\n\t\t\tif (bu->getOriginalFaction() == FACTION_HOSTILE)\n\t\t\t{\n\t\t\t\twaitingTransformations.push_back(bu);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t//if unit belong to XCOM or CIVILIANS we leave it as-is\n\t\t\t}\n\t\t}\n\t}\n\tfor (auto* bu : waitingTransformations)\n\t{\n\t\tbool ignore = bu->isIgnored();\n\t\tUnitFaction faction = bu->getFaction();\n\t\t// convert it, and mind control the resulting unit.\n\t\t// reason: zombies don't create unconscious bodies... ever.\n\t\t// the only way we can get into this situation is if psi-capture is enabled.\n\t\t// we can use that knowledge to our advantage to save having to make it unconscious and spawn a body item for it.\n\t\tif (ignore)\n\t\t{\n\t\t\t//simplified handling for unit from previous stage\n\t\t\tBattleUnit *newUnit = battle->createTempUnit(bu->getSpawnUnit(), bu->getSpawnUnitFaction());\n\t\t\tbattle->getUnits()->push_back(newUnit);\n\t\t\tnewUnit->convertToFaction(faction);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tBattleUnit *newUnit = battle->convertUnit(bu);\n\t\t\tnewUnit->convertToFaction(faction);\n\t\t}\n\t\tbu->killedBy(FACTION_HOSTILE); //skip counting as kill\n\t}\n\n\t// time to care for units.\n\tbool psiStrengthEval = (Options::psiStrengthEval && save->isResearched(_game->getMod()->getPsiRequirements()));\n\tbool ignoreLivingCivilians = false;\n\tif (ruleDeploy)\n\t{\n\t\tignoreLivingCivilians = ruleDeploy->getIgnoreLivingCivilians();\n\t}\n\tfor (auto* bunit : *battle->getUnits())\n\t{\n\t\tUnitStatus status = bunit->getStatus();\n\t\tUnitFaction faction = bunit->getFaction();\n\t\tUnitFaction oldFaction = bunit->getOriginalFaction();\n\t\tint value = bunit->getValue();\n\t\tSoldier *soldier = save->getSoldier(bunit->getId());\n\n\t\tif (!bunit->getTile())\n\t\t{\n\t\t\tPosition pos = bunit->getPosition();\n\t\t\tif (pos == TileEngine::invalid)\n\t\t\t{\n\t\t\t\tfor (auto* bi : *battle->getItems())\n\t\t\t\t{\n\t\t\t\t\tif (bi->getUnit() && bi->getUnit() == bunit)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (bi->getOwner())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tpos = bi->getOwner()->getPosition();\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (bi->getTile())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tpos = bi->getTile()->getPosition();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbunit->setInventoryTile(battle->getTile(pos));\n\t\t}\n\n\t\tif (status == STATUS_DEAD)\n\t\t{ // so this is a dead unit\n\t\t\tif (oldFaction == FACTION_HOSTILE && bunit->killedBy() == FACTION_PLAYER)\n\t\t\t{\n\t\t\t\taddStat(\"STR_ALIENS_KILLED\", 1, value);\n\t\t\t}\n\t\t\telse if (oldFaction == FACTION_PLAYER)\n\t\t\t{\n\t\t\t\tif (soldier != 0)\n\t\t\t\t{\n\t\t\t\t\taddStat(\"STR_XCOM_OPERATIVES_KILLED\", 1, -value);\n\t\t\t\t\tbunit->updateGeoscapeStats(soldier);\n\n\t\t\t\t\t// starting conditions: recover armor backup\n\t\t\t\t\tif (soldier->getReplacedArmor())\n\t\t\t\t\t{\n\t\t\t\t\t\tif (soldier->getReplacedArmor()->getStoreItem())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\taddItemsToBaseStores(soldier->getReplacedArmor()->getStoreItem()->getType(), base, 1, false);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tsoldier->setReplacedArmor(0);\n\t\t\t\t\t}\n\t\t\t\t\t// transformed armor doesn't get recovered\n\t\t\t\t\tsoldier->setTransformedArmor(0);\n\n\t\t\t\t\tbunit->getStatistics()->KIA = true;\n\t\t\t\t\tsave->killSoldier(true, soldier); // in case we missed the soldier death on battlescape\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{ // non soldier player = tank\n\t\t\t\t\taddStat(\"STR_TANKS_DESTROYED\", 1, -value);\n\t\t\t\t\tsave->increaseVehiclesLost();\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (oldFaction == FACTION_NEUTRAL)\n\t\t\t{\n\t\t\t\tif (bunit->killedBy() == FACTION_PLAYER)\n\t\t\t\t{\n\t\t\t\t\tif (!bunit->isCosmetic())\n\t\t\t\t\t{\n\t\t\t\t\t\taddStat(\"STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES\", 1, -bunit->getValue() - (2 * (bunit->getValue() / 3)));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse // if civilians happen to kill themselves XCOM shouldn't get penalty for it\n\t\t\t\t{\n\t\t\t\t\tif (!bunit->isCosmetic())\n\t\t\t\t\t{\n\t\t\t\t\t\taddStat(\"STR_CIVILIANS_KILLED_BY_ALIENS\", 1, -bunit->getValue());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{ // so this unit is not dead...\n\t\t\tif (oldFaction == FACTION_PLAYER)\n\t\t\t{\n\t\t\t\tif (\n\t\t\t\t\t((bunit->isInExitArea(START_POINT) || bunit->isIgnored()) && (battle->getMissionType() != \"STR_BASE_DEFENSE\" || success))\n\t\t\t\t\t|| !aborted\n\t\t\t\t\t|| (aborted && bunit->isInExitArea(END_POINT)))\n\t\t\t\t{ // so game is not aborted or aborted and unit is on exit area\n\t\t\t\t\tStatAdjustment statIncrease;\n\t\t\t\t\tbunit->postMissionProcedures(_game->getMod(), save, battle, statIncrease);\n\t\t\t\t\tif (bunit->getGeoscapeSoldier())\n\t\t\t\t\t\t_soldierStats.push_back(std::pair<std::string, UnitStats>(bunit->getGeoscapeSoldier()->getName(), statIncrease.statGrowth));\n\t\t\t\t\tplayersInExitArea2++;\n\n\t\t\t\t\trecoverItems(bunit->getInventory(), base, craft);\n\n\t\t\t\t\tif (soldier != 0)\n\t\t\t\t\t{\n\t\t\t\t\t\t// calculate new statString\n\t\t\t\t\t\tsoldier->calcStatString(_game->getMod()->getStatStrings(), psiStrengthEval);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{ // non soldier player = tank\n\t\t\t\t\t\taddItemsToBaseStores(bunit->getType(), base, 1, false);\n\n\t\t\t\t\t\tauto unloadWeapon = [&](BattleItem *weapon)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (weapon)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tconst RuleItem* primaryWeaponRule = weapon->getRules();\n\t\t\t\t\t\t\t\tconst RuleItem* fixedAmmoRule = primaryWeaponRule->getVehicleClipAmmo();\n\t\t\t\t\t\t\t\tif (primaryWeaponRule->getVehicleUnit() && fixedAmmoRule)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tconst BattleItem* fixedAmmoItem = weapon->getAmmoForSlot(primaryWeaponRule->getVehicleFixedAmmoSlot());\n\t\t\t\t\t\t\t\t\tif (fixedAmmoItem != 0 && fixedAmmoItem->getAmmoQuantity() > 0)\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tint total = fixedAmmoItem->getAmmoQuantity();\n\n\t\t\t\t\t\t\t\t\t\tif (primaryWeaponRule->getClipSize()) // meaning this tank can store multiple clips\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\ttotal /= fixedAmmoItem->getRules()->getClipSize();\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\taddItemsToBaseStores(fixedAmmoRule, base, total, false);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tunloadWeapon(bunit->getRightHandWeapon());\n\t\t\t\t\t\tunloadWeapon(bunit->getLeftHandWeapon());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{ // so game is aborted and unit is not on exit area\n\t\t\t\t\taddStat(\"STR_XCOM_OPERATIVES_MISSING_IN_ACTION\", 1, -value);\n\t\t\t\t\tplayersSurvived--;\n\t\t\t\t\tif (soldier != 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tbunit->updateGeoscapeStats(soldier);\n\n\t\t\t\t\t\t// starting conditions: recover armor backup\n\t\t\t\t\t\tif (soldier->getReplacedArmor())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (soldier->getReplacedArmor()->getStoreItem())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\taddItemsToBaseStores(soldier->getReplacedArmor()->getStoreItem()->getType(), base, 1, false);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tsoldier->setReplacedArmor(0);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// transformed armor doesn't get recovered\n\t\t\t\t\t\tsoldier->setTransformedArmor(0);\n\n\t\t\t\t\t\tbunit->getStatistics()->MIA = true;\n\t\t\t\t\t\tsave->killSoldier(true, soldier);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (oldFaction == FACTION_HOSTILE && (!aborted || bunit->isInExitArea(START_POINT)) && !_destroyBase\n\t\t\t\t// mind controlled units may as well count as unconscious\n\t\t\t\t&& faction == FACTION_PLAYER && (!bunit->isOut() || bunit->isIgnored()))\n\t\t\t{\n\t\t\t\tif (bunit->getTile())\n\t\t\t\t{\n\t\t\t\t\tbattle->getTileEngine()->itemDropInventory(bunit->getTile(), bunit);\n\t\t\t\t}\n\t\t\t\tif (!bunit->getArmor()->getCorpseBattlescape().empty())\n\t\t\t\t{\n\t\t\t\t\tauto* corpseRule = bunit->getArmor()->getCorpseBattlescape().front();\n\t\t\t\t\tif (corpseRule && corpseRule->isRecoverable())\n\t\t\t\t\t{\n\t\t\t\t\t\trecoverAlien(bunit, base, craft);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (oldFaction == FACTION_HOSTILE && !aborted && !_destroyBase\n\t\t\t\t// surrendered units may as well count as unconscious too\n\t\t\t\t&& playersSurvived > 0 && faction != FACTION_PLAYER && (!bunit->isOut() || bunit->isIgnored())\n\t\t\t\t&& (bunit->isSurrendering() || battle->getChronoTrigger() == FORCE_WIN_SURRENDER))\n\t\t\t{\n\t\t\t\tif (bunit->getTile())\n\t\t\t\t{\n\t\t\t\t\tbattle->getTileEngine()->itemDropInventory(bunit->getTile(), bunit);\n\t\t\t\t}\n\t\t\t\tif (!bunit->getArmor()->getCorpseBattlescape().empty())\n\t\t\t\t{\n\t\t\t\t\tauto* corpseRule = bunit->getArmor()->getCorpseBattlescape().front();\n\t\t\t\t\tif (corpseRule && corpseRule->isRecoverable())\n\t\t\t\t\t{\n\t\t\t\t\t\trecoverAlien(bunit, base, craft);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (oldFaction == FACTION_NEUTRAL && !ignoreLivingCivilians)\n\t\t\t{\n\t\t\t\t// if mission fails, all civilians die\n\t\t\t\tif ((aborted && !success) || playersSurvived == 0)\n\t\t\t\t{\n\t\t\t\t\tif (!bunit->isResummonedFakeCivilian() && !bunit->isCosmetic())\n\t\t\t\t\t{\n\t\t\t\t\t\taddStat(\"STR_CIVILIANS_KILLED_BY_ALIENS\", 1, -bunit->getValue());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif (!bunit->isResummonedFakeCivilian() && !bunit->isCosmetic())\n\t\t\t\t\t{\n\t\t\t\t\t\taddStat(\"STR_CIVILIANS_SAVED\", 1, bunit->getValue());\n\t\t\t\t\t}\n\t\t\t\t\trecoverCivilian(bunit, base, craft);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tbool lostCraft = false;\n\tif (craft != 0 && ((playersInExitArea2 == 0 && aborted) || (playersSurvived == 0)))\n\t{\n\t\tif (craft->getRules()->keepCraftAfterFailedMission())\n\t\t{\n\t\t\t// craft was not even on the battlescape (e.g. paratroopers)\n\t\t}\n\t\telse if (ruleDeploy->keepCraftAfterFailedMission())\n\t\t{\n\t\t\t// craft didn't wait for you (e.g. escape/extraction missions)\n\t\t}\n\t\telse\n\t\t{\n\t\t\taddStat(\"STR_XCOM_CRAFT_LOST\", 1, -craft->getRules()->getScore());\n\t\t\t// Since this is not a base defense mission, we can safely erase the craft,\n\t\t\t// without worrying it's vehicles' destructor calling double (on base defense missions\n\t\t\t// all vehicle object in the craft is also referenced by base->getVehicles() !!)\n\t\t\tsave->stopHuntingXcomCraft(craft); // lost during ground mission\n\t\t\tsave->removeAllSoldiersFromXcomCraft(craft); // needed in case some soldiers couldn't spawn\n\t\t\tbase->removeCraft(craft, false);\n\t\t\tdelete craft;\n\t\t\tsave->increaseCraftLostMission();\n\t\t\tcraft = 0; // To avoid a crash down there!!\n\t\t\tlostCraft = true;\n\t\t}\n\t\tplayersSurvived = 0; // assuming you aborted and left everyone behind\n\t\tsuccess = false;\n\t}\n\tif ((aborted || playersSurvived == 0) && target == \"STR_BASE\")\n\t{\n\t\tfor (auto* xcraft : *base->getCrafts())\n\t\t{\n\t\t\taddStat(\"STR_XCOM_CRAFT_LOST\", 1, -xcraft->getRules()->getScore());\n\t\t}\n\t\tplayersSurvived = 0; // assuming you aborted and left everyone behind\n\t\tsuccess = false;\n\t}\n\n\tbool savedEnoughVIPs = true;\n\tif (battle->getVIPSurvivalPercentage() > 0)\n\t{\n\t\tbool retreated = aborted && (playersSurvived > 0);\n\n\t\t// 1. correct our initial assessment if necessary\n\t\tbattle->correctVIPStats(success, retreated);\n\t\tint vipSubtotal = battle->getSavedVIPs() + battle->getLostVIPs();\n\n\t\t// 2. add non-fake civilian VIPs, no scoring\n\t\tfor (auto* unit : *battle->getUnits())\n\t\t{\n\t\t\tif (unit->isVIP() && unit->getOriginalFaction() == FACTION_NEUTRAL && !unit->isResummonedFakeCivilian())\n\t\t\t{\n\t\t\t\tif (unit->getStatus() == STATUS_DEAD)\n\t\t\t\t\tbattle->addLostVIP(0);\n\t\t\t\telse if (success)\n\t\t\t\t\tbattle->addSavedVIP(0);\n\t\t\t\telse\n\t\t\t\t\tbattle->addLostVIP(0);\n\t\t\t}\n\t\t}\n\n\t\t// 3. check if we saved enough VIPs\n\t\tint vipTotal = battle->getSavedVIPs() + battle->getLostVIPs();\n\t\tif (vipTotal > 0)\n\t\t{\n\t\t\tint ratio = battle->getSavedVIPs() * 100 / vipTotal;\n\t\t\tif (ratio < battle->getVIPSurvivalPercentage())\n\t\t\t{\n\t\t\t\tsavedEnoughVIPs = false; // didn't save enough VIPs\n\t\t\t\tsuccess = false;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tsavedEnoughVIPs = false; // nobody to save?\n\t\t\tsuccess = false;\n\t\t}\n\n\t\t// 4. add stats\n\t\tif (vipSubtotal > 0 || (vipTotal > 0 && !savedEnoughVIPs))\n\t\t{\n\t\t\taddStat(\"STR_VIPS_LOST\", battle->getLostVIPs(), battle->getLostVIPsScore());\n\t\t\taddStat(\"STR_VIPS_SAVED\", battle->getSavedVIPs(), battle->getSavedVIPsScore());\n\t\t}\n\t}\n\n\tif ((!aborted || success) && playersSurvived > 0) \t// RECOVER UFO : run through all tiles to recover UFO components and items\n\t{\n\t\tif (target == \"STR_BASE\")\n\t\t{\n\t\t\t_txtTitle->setText(tr(\"STR_BASE_IS_SAVED\"));\n\t\t}\n\t\telse if (target == \"STR_UFO\")\n\t\t{\n\t\t\t_txtTitle->setText(tr(\"STR_UFO_IS_RECOVERED\"));\n\t\t}\n\t\telse if (target == \"STR_ALIEN_BASE\")\n\t\t{\n\t\t\t_txtTitle->setText(tr(\"STR_ALIEN_BASE_DESTROYED\"));\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_txtTitle->setText(tr(\"STR_ALIENS_DEFEATED\"));\n\t\t\tif (!aborted && !savedEnoughVIPs)\n\t\t\t{\n\t\t\t\t// Special case: mission was NOT aborted, all enemies were neutralized, but we couldn't save enough VIPs...\n\t\t\t\tif (!objectiveFailedText.empty())\n\t\t\t\t{\n\t\t\t\t\taddStat(objectiveFailedText, 1, objectiveFailedScore);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (!objectiveCompleteText.empty())\n\t\t\t{\n\t\t\t\tint victoryStat = 0;\n\t\t\t\tif (ruleDeploy->getEscapeType() != ESCAPE_NONE)\n\t\t\t\t{\n\t\t\t\t\tif (ruleDeploy->getEscapeType() != ESCAPE_EXIT)\n\t\t\t\t\t{\n\t\t\t\t\t\tvictoryStat += playersInEntryArea1;\n\t\t\t\t\t}\n\t\t\t\t\tif (ruleDeploy->getEscapeType() != ESCAPE_ENTRY)\n\t\t\t\t\t{\n\t\t\t\t\t\tvictoryStat += playersInExitArea1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tvictoryStat = 1;\n\t\t\t\t}\n\t\t\t\tif (battle->getVIPSurvivalPercentage() > 0)\n\t\t\t\t{\n\t\t\t\t\tvictoryStat = 1; // TODO: maybe show battle->getSavedVIPs() instead? need feedback...\n\t\t\t\t}\n\n\t\t\t\taddStat(objectiveCompleteText, victoryStat, objectiveCompleteScore);\n\t\t\t}\n\t\t}\n\t\tif (!aborted && !savedEnoughVIPs)\n\t\t{\n\t\t\t// Special case: mission was NOT aborted, all enemies were neutralized, but we couldn't save enough VIPs...\n\t\t\tif (!missionFailedText.empty())\n\t\t\t{\n\t\t\t\t_txtTitle->setText(tr(missionFailedText));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_txtTitle->setText(tr(\"STR_TERROR_CONTINUES\"));\n\t\t\t}\n\t\t}\n\t\telse if (!missionCompleteText.empty())\n\t\t{\n\t\t\t_txtTitle->setText(tr(missionCompleteText));\n\t\t}\n\n\t\tif (!aborted)\n\t\t{\n\t\t\t// if this was a 2-stage mission, and we didn't abort (ie: we have time to clean up)\n\t\t\t// we can recover items from the earlier stages as well\n\t\t\trecoverItems(battle->getConditionalRecoveredItems(), base, craft);\n\t\t\tsize_t nonRecoverType = 0;\n\t\t\tif (ruleDeploy && ruleDeploy->getObjectiveType() && !ruleDeploy->allowObjectiveRecovery())\n\t\t\t{\n\t\t\t\tnonRecoverType = ruleDeploy->getObjectiveType();\n\t\t\t}\n\t\t\tfor (int i = 0; i < battle->getMapSizeXYZ(); ++i)\n\t\t\t{\n\t\t\t\t// get recoverable map data objects from the battlescape map\n\t\t\t\tfor (int part = O_FLOOR; part < O_MAX; ++part)\n\t\t\t\t{\n\t\t\t\t\tTilePart tp = (TilePart)part;\n\t\t\t\t\tif (battle->getTile(i)->getMapData(tp))\n\t\t\t\t\t{\n\t\t\t\t\t\tsize_t specialType = battle->getTile(i)->getMapData(tp)->getSpecialType();\n\t\t\t\t\t\tif (specialType != nonRecoverType && specialType < (size_t)DEATH_TRAPS && _recoveryStats.find(specialType) != _recoveryStats.end())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\taddStat(_recoveryStats[specialType]->name, 1, _recoveryStats[specialType]->value);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// recover items from the floor\n\t\t\t\trecoverItems(battle->getTile(i)->getInventory(), base, craft);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tfor (int i = 0; i < battle->getMapSizeXYZ(); ++i)\n\t\t\t{\n\t\t\t\tif (battle->getTile(i)->getFloorSpecialTileType() == START_POINT)\n\t\t\t\t\trecoverItems(battle->getTile(i)->getInventory(), base, craft);\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\tif (lostCraft)\n\t\t{\n\t\t\t_txtTitle->setText(tr(\"STR_CRAFT_IS_LOST\"));\n\t\t}\n\t\telse if (target == \"STR_BASE\")\n\t\t{\n\t\t\t_txtTitle->setText(tr(\"STR_BASE_IS_LOST\"));\n\t\t\t_destroyBase = true;\n\t\t}\n\t\telse if (target == \"STR_UFO\")\n\t\t{\n\t\t\t_txtTitle->setText(tr(\"STR_UFO_IS_NOT_RECOVERED\"));\n\t\t}\n\t\telse if (target == \"STR_ALIEN_BASE\")\n\t\t{\n\t\t\t_txtTitle->setText(tr(\"STR_ALIEN_BASE_STILL_INTACT\"));\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_txtTitle->setText(tr(\"STR_TERROR_CONTINUES\"));\n\t\t\tif (!objectiveFailedText.empty())\n\t\t\t{\n\t\t\t\taddStat(objectiveFailedText, 1, objectiveFailedScore);\n\t\t\t}\n\t\t}\n\t\tif (!missionFailedText.empty())\n\t\t{\n\t\t\t_txtTitle->setText(tr(missionFailedText));\n\t\t}\n\n\t\tif (playersSurvived > 0 && !_destroyBase)\n\t\t{\n\t\t\t// recover items from the craft floor\n\t\t\tfor (int i = 0; i < battle->getMapSizeXYZ(); ++i)\n\t\t\t{\n\t\t\t\tif (battle->getTile(i)->getFloorSpecialTileType() == START_POINT)\n\t\t\t\t\trecoverItems(battle->getTile(i)->getInventory(), base, craft);\n\t\t\t}\n\t\t}\n\t}\n\n\t// recover all our goodies\n\tif (playersSurvived > 0)\n\t{\n\t\tbool alienAlloysExist = (_recoveryStats.find(ALIEN_ALLOYS) != _recoveryStats.end());\n\t\tfor (auto* ds : _stats)\n\t\t{\n\t\t\t// alien alloys recovery values are divided by 10 or divided by 150 in case of an alien base\n\t\t\tint aadivider = 1;\n\t\t\tif (alienAlloysExist && ds->item == _recoveryStats[ALIEN_ALLOYS]->name)\n\t\t\t{\n\t\t\t\t// hardcoded vanilla defaults, in case modders or players fail to install OXCE properly\n\t\t\t\taadivider = (target == \"STR_UFO\") ? 10 : 150;\n\t\t\t}\n\n\t\t\tconst RuleItem *itemRule = _game->getMod()->getItem(ds->item, false);\n\t\t\tif (itemRule)\n\t\t\t{\n\t\t\t\tconst auto& recoveryDividers = itemRule->getRecoveryDividers();\n\t\t\t\tif (!recoveryDividers.empty())\n\t\t\t\t{\n\t\t\t\t\tbool done = false;\n\t\t\t\t\tif (ruleDeploy)\n\t\t\t\t\t{\n\t\t\t\t\t\t// step 1: check deployment\n\t\t\t\t\t\tif (recoveryDividers.find(ruleDeploy->getType()) != recoveryDividers.end())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\taadivider = recoveryDividers.at(ruleDeploy->getType());\n\t\t\t\t\t\t\tdone = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (!done)\n\t\t\t\t\t{\n\t\t\t\t\t\t// step 2: check mission type\n\t\t\t\t\t\tif (recoveryDividers.find(target) != recoveryDividers.end())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\taadivider = recoveryDividers.at(target);\n\t\t\t\t\t\t\tdone = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (!done)\n\t\t\t\t\t{\n\t\t\t\t\t\t// step 3: check global default\n\t\t\t\t\t\tif (recoveryDividers.find(\"STR_OTHER\") != recoveryDividers.end())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\taadivider = recoveryDividers.at(\"STR_OTHER\");\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (aadivider > 1)\n\t\t\t{\n\t\t\t\tds->qty = ds->qty / aadivider;\n\t\t\t\tds->score = ds->score / aadivider;\n\t\t\t}\n\t\t\telse if (aadivider < -1)\n\t\t\t{\n\t\t\t\tds->qty = ds->qty * (-1) * aadivider;\n\t\t\t\tds->score = ds->score * (-1) * aadivider;\n\t\t\t}\n\n\t\t\t// recoverable battlescape tiles are now converted to items and put in base inventory\n\t\t\tif (ds->recovery && ds->qty > 0)\n\t\t\t{\n\t\t\t\taddItemsToBaseStores(ds->item, base, ds->qty, false);\n\t\t\t}\n\t\t}\n\n\t\t// assuming this was a multi-stage mission,\n\t\t// recover everything that was in the craft in the previous stage\n\t\trecoverItems(battle->getGuaranteedRecoveredItems(), base, craft);\n\t}\n\n\t// calculate the clips for each type based on the recovered rounds.\n\tfor (const auto& pair : _rounds)\n\t{\n\t\tint total_clips = 0;\n\t\tif (_game->getMod()->getStatisticalBulletConservation())\n\t\t{\n\t\t\ttotal_clips = (pair.second + RNG::generate(0, (pair.first->getClipSize() - 1))) / pair.first->getClipSize();\n\t\t}\n\t\telse\n\t\t{\n\t\t\ttotal_clips = pair.second / pair.first->getClipSize();\n\t\t}\n\t\tif (total_clips > 0)\n\t\t{\n\t\t\taddItemsToBaseStores(pair.first, base, total_clips, true);\n\t\t}\n\t}\n\n\t// calculate the \"remaining medikit items\" for each type based on the recovered \"clips\".\n\tfor (const auto& pair : _roundsPainKiller)\n\t{\n\t\tint totalRecovered = INT_MAX;\n\t\tif (_game->getMod()->getStatisticalBulletConservation())\n\t\t{\n\t\t\tif (pair.first->getPainKillerQuantity() > 0)\n\t\t\t\ttotalRecovered = std::min(totalRecovered, (pair.second + RNG::generate(0, (pair.first->getPainKillerQuantity() - 1))) / pair.first->getPainKillerQuantity());\n\t\t\tif (pair.first->getStimulantQuantity() > 0)\n\t\t\t\ttotalRecovered = std::min(totalRecovered, (_roundsStimulant[pair.first] + RNG::generate(0, (pair.first->getStimulantQuantity() - 1))) / pair.first->getStimulantQuantity());\n\t\t\tif (pair.first->getHealQuantity() > 0)\n\t\t\t\ttotalRecovered = std::min(totalRecovered, (_roundsHeal[pair.first] + RNG::generate(0, (pair.first->getHealQuantity() - 1))) / pair.first->getHealQuantity());\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (pair.first->getPainKillerQuantity() > 0)\n\t\t\t\ttotalRecovered = std::min(totalRecovered, pair.second / pair.first->getPainKillerQuantity());\n\t\t\tif (pair.first->getStimulantQuantity() > 0)\n\t\t\t\ttotalRecovered = std::min(totalRecovered, _roundsStimulant[pair.first] / pair.first->getStimulantQuantity());\n\t\t\tif (pair.first->getHealQuantity() > 0)\n\t\t\t\ttotalRecovered = std::min(totalRecovered, _roundsHeal[pair.first] / pair.first->getHealQuantity());\n\t\t}\n\n\t\tif (totalRecovered > 0)\n\t\t{\n\t\t\taddItemsToBaseStores(pair.first, base, totalRecovered, true);\n\t\t}\n\t}\n\n\t// reequip craft after a non-base-defense mission (of course only if it's not lost already (that case craft=0))\n\tif (craft)\n\t{\n\t\treequipCraft(base, craft, true);\n\t}\n\telse\n\t{\n\t\tif (target != \"STR_BASE\" || _destroyBase)\n\t\t{\n\t\t\thideSellTransferButtons();\n\t\t}\n\t}\n\n\tif (base && target == \"STR_BASE\")\n\t{\n\t\tAlienMission* am = base->getRetaliationMission();\n\t\tif (!am && _region)\n\t\t{\n\t\t\t// backwards-compatibility\n\t\t\tam = save->findAlienMission(_region->getRules()->getType(), OBJECTIVE_RETALIATION);\n\t\t}\n\t\tif (!_destroyBase && am && am->getRules().isMultiUfoRetaliation())\n\t\t{\n\t\t\t// Remember that more UFOs may be coming (again, just in case)\n\t\t\tam->setMultiUfoRetaliationInProgress(true);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// Delete the mission and any live UFOs\n\t\t\tsave->deleteRetaliationMission(am, base);\n\t\t}\n\n\t\tif (!_destroyBase)\n\t\t{\n\t\t\t// reequip crafts (only those on the base) after a base defense mission\n\t\t\tfor (auto* xcraft : *base->getCrafts())\n\t\t\t{\n\t\t\t\tif (xcraft->getStatus() != \"STR_OUT\")\n\t\t\t\t\treequipCraft(base, xcraft, false);\n\t\t\t}\n\t\t}\n\t\telse if (save->getMonthsPassed() != -1)\n\t\t{\n\t\t\tfor (auto xbaseIt = save->getBases()->begin(); xbaseIt != save->getBases()->end(); ++xbaseIt)\n\t\t\t{\n\t\t\t\tBase* xbase = (*xbaseIt);\n\t\t\t\tif (xbase == base)\n\t\t\t\t{\n\t\t\t\t\tsave->stopHuntingXcomCrafts(xbase); // destroyed together with the base\n\t\t\t\t\tdelete xbase;\n\t\t\t\t\tbase = 0; // To avoid similar (potential) problems as with the deleted craft\n\t\t\t\t\tsave->getBases()->erase(xbaseIt);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (!_destroyBase)\n\t{\n\t\t// clean up remaining armor backups\n\t\t// Note: KIA and MIA soldiers have been handled already, only survivors can have non-empty values\n\t\tfor (auto* soldier : *base->getSoldiers())\n\t\t{\n\t\t\tif (soldier->getReplacedArmor())\n\t\t\t{\n\t\t\t\tsoldier->setArmor(soldier->getReplacedArmor());\n\t\t\t}\n\t\t\telse if (soldier->getTransformedArmor())\n\t\t\t{\n\t\t\t\tsoldier->setArmor(soldier->getTransformedArmor());\n\n\t\t\t}\n\t\t\tsoldier->setReplacedArmor(0);\n\t\t\tsoldier->setTransformedArmor(0);\n\t\t}\n\t}\n\n\t_missionStatistics->success = success;\n\n\tif (success && ruleDeploy && base)\n\t{\n\t\t// Unlock research defined in alien deployment, if the mission was a success\n\t\tconst RuleResearch *research = _game->getMod()->getResearch(ruleDeploy->getUnlockedResearchOnSuccess());\n\t\tsave->handleResearchUnlockedByMissions(research, _game->getMod(), ruleDeploy);\n\n\t\t// Give bounty item defined in alien deployment, if the mission was a success\n\t\tconst RuleItem *bountyItem = _game->getMod()->getItem(ruleDeploy->getMissionBountyItem());\n\t\tif (bountyItem)\n\t\t{\n\t\t\tint bountyQty = std::max(1, ruleDeploy->getMissionBountyItemCount());\n\t\t\taddItemsToBaseStores(bountyItem, base, bountyQty, true);\n\t\t\tint specialType = bountyItem->getSpecialType();\n\t\t\tif (specialType > 1)\n\t\t\t{\n\t\t\t\tif (_recoveryStats.find(specialType) != _recoveryStats.end())\n\t\t\t\t{\n\t\t\t\t\taddStat(_recoveryStats[specialType]->name, bountyQty, bountyQty * _recoveryStats[specialType]->value);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Increase counters\n\t\tsave->increaseCustomCounter(ruleDeploy->getCounterSuccess());\n\t\tsave->increaseCustomCounter(ruleDeploy->getCounterAll());\n\t\t// Decrease counters\n\t\tsave->decreaseCustomCounter(ruleDeploy->getDecreaseCounterSuccess());\n\t\tsave->decreaseCustomCounter(ruleDeploy->getDecreaseCounterAll());\n\n\t\t// Generate a success event\n\t\t_eventToSpawn = _game->getMod()->getEvent(ruleDeploy->chooseSuccessEvent());\n\t}\n\telse if (!success && ruleDeploy)\n\t{\n\t\t// Unlock research defined in alien deployment, if the mission was a failure\n\t\tconst RuleResearch* research = _game->getMod()->getResearch(ruleDeploy->getUnlockedResearchOnFailure());\n\t\tsave->handleResearchUnlockedByMissions(research, _game->getMod(), ruleDeploy);\n\n\t\t// Increase counters\n\t\tsave->increaseCustomCounter(ruleDeploy->getCounterFailure());\n\t\tsave->increaseCustomCounter(ruleDeploy->getCounterAll());\n\t\t// Decrease counters\n\t\tsave->decreaseCustomCounter(ruleDeploy->getDecreaseCounterFailure());\n\t\tsave->decreaseCustomCounter(ruleDeploy->getDecreaseCounterAll());\n\n\t\t// Generate a failure event\n\t\t_eventToSpawn = _game->getMod()->getEvent(ruleDeploy->chooseFailureEvent());\n\t}\n\n\tif (ignoredUfo)\n\t{\n\t\tif (!success || aborted || playersSurvived <= 0)\n\t\t{\n\t\t\t// either \"reactivate\" the corresponding Ufo\n\t\t\tignoredUfo->getMission()->ufoLifting(*ignoredUfo, *save);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// or finally destroy it\n\t\t\tignoredUfo->setStatus(Ufo::DESTROYED);\n\t\t}\n\t}\n\n\t// remember the base for later use (of course only if it's not lost already (in that case base=0))\n\t_base = base;\n}\n\n/**\n * Reequips a craft after a mission.\n * @param base Base to reequip from.\n * @param craft Craft to reequip.\n * @param vehicleItemsCanBeDestroyed Whether we can destroy the vehicles on the craft.\n */\nvoid DebriefingState::reequipCraft(Base *base, Craft *craft, bool vehicleItemsCanBeDestroyed)\n{\n\tauto craftItemsCopy = *craft->getItems()->getContents();\n\tfor (const auto& pair : craftItemsCopy)\n\t{\n\t\tint qty = base->getStorageItems()->getItem(pair.first);\n\t\tif (qty >= pair.second)\n\t\t{\n\t\t\tbase->getStorageItems()->removeItem(pair.first, pair.second);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tint missing = pair.second - qty;\n\t\t\tbase->getStorageItems()->removeItem(pair.first, qty);\n\t\t\tcraft->getItems()->removeItem(pair.first, missing);\n\t\t\tReequipStat stat = {pair.first->getType(), missing, craft->getName(_game->getLanguage()), 0};\n\t\t\t_missingItems.push_back(stat);\n\t\t}\n\t}\n\n\t// Now let's see the vehicles\n\tItemContainer craftVehicles;\n\tfor (auto* vehicle : *craft->getVehicles())\n\t{\n\t\tcraftVehicles.addItem(vehicle->getRules());\n\t}\n\n\t// Now we know how many vehicles (separated by types) we have to read\n\t// Erase the current vehicles, because we have to reAdd them (cause we want to redistribute their ammo)\n\tif (vehicleItemsCanBeDestroyed)\n\t{\n\t\tfor (auto* vehicle : *craft->getVehicles())\n\t\t{\n\t\t\tdelete vehicle;\n\t\t}\n\t}\n\tcraft->getVehicles()->clear();\n\n\t// Ok, now read those vehicles\n\tfor (const auto& pair : *craftVehicles.getContents())\n\t{\n\t\tint qty = base->getStorageItems()->getItem(pair.first);\n\t\tconst RuleItem *tankRule = pair.first;\n\t\tint size = tankRule->getVehicleUnit()->getArmor()->getTotalSize();\n\t\tint canBeAdded = std::min(qty, pair.second);\n\t\tif (qty < pair.second)\n\t\t{ // missing tanks\n\t\t\tint missing = pair.second - qty;\n\t\t\tReequipStat stat = {pair.first->getType(), missing, craft->getName(_game->getLanguage()), 0};\n\t\t\t_missingItems.push_back(stat);\n\t\t}\n\t\tif (tankRule->getVehicleClipAmmo() == nullptr)\n\t\t{ // so this tank does NOT require ammo\n\t\t\tfor (int j = 0; j < canBeAdded; ++j)\n\t\t\t{\n\t\t\t\tcraft->getVehicles()->push_back(new Vehicle(tankRule, tankRule->getVehicleClipSize(), size));\n\t\t\t}\n\t\t\tbase->getStorageItems()->removeItem(pair.first, canBeAdded);\n\t\t}\n\t\telse\n\t\t{ // so this tank requires ammo\n\t\t\tconst RuleItem *ammo = tankRule->getVehicleClipAmmo();\n\t\t\tint ammoPerVehicle = tankRule->getVehicleClipsLoaded();\n\n\t\t\tint baqty = base->getStorageItems()->getItem(ammo); // Ammo Quantity for this vehicle-type on the base\n\t\t\tif (baqty < pair.second * ammoPerVehicle)\n\t\t\t{ // missing ammo\n\t\t\t\tint missing = (pair.second * ammoPerVehicle) - baqty;\n\t\t\t\tReequipStat stat = {ammo->getType(), missing, craft->getName(_game->getLanguage()), 0};\n\t\t\t\t_missingItems.push_back(stat);\n\t\t\t}\n\t\t\tcanBeAdded = std::min(canBeAdded, baqty / ammoPerVehicle);\n\t\t\tif (canBeAdded > 0)\n\t\t\t{\n\t\t\t\tfor (int j = 0; j < canBeAdded; ++j)\n\t\t\t\t{\n\t\t\t\t\tcraft->getVehicles()->push_back(new Vehicle(tankRule, tankRule->getVehicleClipSize(), size));\n\t\t\t\t\tbase->getStorageItems()->removeItem(ammo, ammoPerVehicle);\n\t\t\t\t}\n\t\t\t\tbase->getStorageItems()->removeItem(pair.first, canBeAdded);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Adds item(s) to base stores.\n * @param ruleItem Rule of the item(s) to be recovered.\n * @param base Base to add items to.\n * @param quantity How many items to recover.\n * @param considerTransformations Should the items be transformed before recovery?\n */\nvoid DebriefingState::addItemsToBaseStores(const RuleItem *ruleItem, Base *base, int quantity, bool considerTransformations)\n{\n\tif (!considerTransformations)\n\t{\n\t\tbase->getStorageItems()->addItem(ruleItem, quantity);\n\t}\n\telse\n\t{\n\t\tconst auto& recoveryTransformations = ruleItem->getRecoveryTransformations();\n\t\tif (!recoveryTransformations.empty())\n\t\t{\n\t\t\tfor (auto& pair : recoveryTransformations)\n\t\t\t{\n\t\t\t\tif (pair.second.size() > 1)\n\t\t\t\t{\n\t\t\t\t\tint totalWeight = 0;\n\t\t\t\t\tfor (int it : pair.second)\n\t\t\t\t\t{\n\t\t\t\t\t\ttotalWeight += it;\n\t\t\t\t\t}\n\t\t\t\t\t// roll each item separately\n\t\t\t\t\tfor (int i = 0; i < quantity; ++i)\n\t\t\t\t\t{\n\t\t\t\t\t\tint roll = RNG::generate(1, totalWeight);\n\t\t\t\t\t\tint runningTotal = 0;\n\t\t\t\t\t\tint position = 0;\n\t\t\t\t\t\tfor (int it : pair.second)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\trunningTotal += it;\n\t\t\t\t\t\t\tif (runningTotal >= roll)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tbase->getStorageItems()->addItem(pair.first, position);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t++position;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// no RNG\n\t\t\t\t\tbase->getStorageItems()->addItem(pair.first, quantity * pair.second.front());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tbase->getStorageItems()->addItem(ruleItem, quantity);\n\t\t}\n\t}\n}\n\n/**\n * Adds item(s) to base stores.\n * @param ruleItem Rule of the item(s) to be recovered.\n * @param base Base to add items to.\n * @param quantity How many items to recover.\n * @param considerTransformations Should the items be transformed before recovery?\n */\nvoid DebriefingState::addItemsToBaseStores(const std::string &itemType, Base *base, int quantity, bool considerTransformations)\n{\n\tconst RuleItem *ruleItem = _game->getMod()->getItem(itemType, false);\n\tif (ruleItem == nullptr)\n\t{\n\t\tLog(LOG_ERROR) << \"Failed to add unknown item \" << itemType;\n\t\treturn;\n\t}\n\n\taddItemsToBaseStores(ruleItem, base, quantity, considerTransformations);\n}\n\n/**\n * Recovers items from the battlescape.\n *\n * Converts the battlescape inventory into a geoscape item container.\n * @param from Items recovered from the battlescape.\n * @param base Base to add items to.\n */\nvoid DebriefingState::recoverItems(std::vector<BattleItem*> *from, Base *base, Craft* craft)\n{\n\tauto checkForRecovery = [&](BattleItem* item, const RuleItem *rule)\n\t{\n\t\treturn !rule->isFixed() && rule->isRecoverable() && (!rule->isConsumable() || item->getFuseTimer() < 0);\n\t};\n\n\tauto recoveryAmmo = [&](BattleItem* clip, const RuleItem *rule)\n\t{\n\t\tif (rule->getBattleType() == BT_AMMO && rule->getClipSize() > 0)\n\t\t{\n\t\t\t// It's a clip, count any rounds left.\n\t\t\tif (rule->isAmmoRechargeable())\n\t\t\t\t_rounds[rule] += rule->getClipSize(); // restore 100% of clip capacity (i.e. the clip will be recharged at the base)\n\t\t\telse\n\t\t\t\t_rounds[rule] += clip->getAmmoQuantity();\n\t\t}\n\t\telse\n\t\t{\n\t\t\taddItemsToBaseStores(rule, base, 1, true);\n\t\t}\n\t};\n\n\tauto recoveryAmmoInWeapon = [&](BattleItem* weapon)\n\t{\n\t\t// Don't need case of built-in ammo, since this is a fixed weapon\n\t\tfor (int slot = 0; slot < RuleItem::AmmoSlotMax; ++slot)\n\t\t{\n\t\t\tBattleItem *clip = weapon->getAmmoForSlot(slot);\n\t\t\tif (clip && clip != weapon)\n\t\t\t{\n\t\t\t\tconst RuleItem *rule = clip->getRules();\n\t\t\t\tif (checkForRecovery(clip, rule))\n\t\t\t\t{\n\t\t\t\t\trecoveryAmmo(clip, rule);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\n\tfor (auto* bi : *from)\n\t{\n\t\tconst RuleItem *rule = bi->getRules();\n\t\tif (rule->getName() == _game->getMod()->getAlienFuelName())\n\t\t{\n\t\t\t// special case of an item counted as a stat\n\t\t\taddStat(_game->getMod()->getAlienFuelName(), _game->getMod()->getAlienFuelQuantity(), rule->getRecoveryPoints());\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (rule->isRecoverable() && !bi->getXCOMProperty())\n\t\t\t{\n\t\t\t\tif (rule->getBattleType() == BT_CORPSE)\n\t\t\t\t{\n\t\t\t\t\tBattleUnit *corpseUnit = bi->getUnit();\n\t\t\t\t\tif (corpseUnit->getStatus() == STATUS_DEAD)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (rule->isCorpseRecoverable())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\taddItemsToBaseStores(corpseUnit->getArmor()->getCorpseGeoscape(), base, 1, true);\n\t\t\t\t\t\t\taddStat(\"STR_ALIEN_CORPSES_RECOVERED\", 1, bi->getRules()->getRecoveryPoints());\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse if (corpseUnit->getStatus() == STATUS_UNCONSCIOUS ||\n\t\t\t\t\t\t\t// or it's in timeout because it's unconscious from the previous stage\n\t\t\t\t\t\t\t// units can be in timeout and alive, and we assume they flee.\n\t\t\t\t\t\t\t(corpseUnit->isIgnored() &&\n\t\t\t\t\t\t\tcorpseUnit->getHealth() > 0 &&\n\t\t\t\t\t\t\tcorpseUnit->getHealth() < corpseUnit->getStunlevel()))\n\t\t\t\t\t{\n\t\t\t\t\t\tif (corpseUnit->getOriginalFaction() == FACTION_HOSTILE)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\trecoverAlien(corpseUnit, base, craft);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// only add recovery points for unresearched items\n\t\t\t\telse if (!_game->getSavedGame()->isResearched(rule->getRequirements()))\n\t\t\t\t{\n\t\t\t\t\taddStat(\"STR_ALIEN_ARTIFACTS_RECOVERED\", 1, rule->getRecoveryPoints());\n\t\t\t\t}\n\t\t\t\telse if (_game->getMod()->getGiveScoreAlsoForResearchedArtifacts())\n\t\t\t\t{\n\t\t\t\t\taddStat(\"STR_ALIEN_ARTIFACTS_RECOVERED\", 1, rule->getRecoveryPoints());\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check if the bodies of our dead soldiers were left, even if we don't recover them\n\t\t\t// This is so we can give them a proper burial... or raise the dead!\n\t\t\tif (bi->getUnit() && bi->getUnit()->getStatus() == STATUS_DEAD && bi->getUnit()->getGeoscapeSoldier())\n\t\t\t{\n\t\t\t\tbi->getUnit()->getGeoscapeSoldier()->setCorpseRecovered(true);\n\t\t\t}\n\n\t\t\t// ammo in weapon are handled by weapon itself.\n\t\t\tif (bi->isAmmo())\n\t\t\t{\n\t\t\t\t// noting\n\t\t\t}\n\t\t\t// put items back in the base\n\t\t\telse if (checkForRecovery(bi, rule))\n\t\t\t{\n\t\t\t\tbool recoverWeapon = true;\n\t\t\t\tswitch (rule->getBattleType())\n\t\t\t\t{\n\t\t\t\t\tcase BT_CORPSE: // corpses are handled above, do not process them here.\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase BT_MEDIKIT:\n\t\t\t\t\t\tif (rule->isConsumable())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// Need to remember all three!\n\t\t\t\t\t\t\t_roundsPainKiller[rule] += bi->getPainKillerQuantity();\n\t\t\t\t\t\t\t_roundsStimulant[rule] += bi->getStimulantQuantity();\n\t\t\t\t\t\t\t_roundsHeal[rule] += bi->getHealQuantity();\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// Vanilla behaviour (recover a full medikit).\n\t\t\t\t\t\t\taddItemsToBaseStores(rule, base, 1, true);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase BT_AMMO:\n\t\t\t\t\t\trecoveryAmmo(bi, rule);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase BT_FIREARM:\n\t\t\t\t\tcase BT_MELEE:\n\t\t\t\t\t\t// Special case: built-in ammo (e.g. throwing knives or bamboo stick)\n\t\t\t\t\t\tif (!bi->needsAmmoForSlot(0) && rule->getClipSize() > 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (rule->isAmmoRechargeable())\n\t\t\t\t\t\t\t\t_rounds[rule] += rule->getClipSize(); // restore 100% of clip capacity (i.e. the clip will be recharged at the base)\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t_rounds[rule] += bi->getAmmoQuantity();\n\t\t\t\t\t\t\trecoverWeapon = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// It's a weapon, count any rounds left in the clip.\n\t\t\t\t\t\trecoveryAmmoInWeapon(bi);\n\t\t\t\t\t\t// Fall-through, to recover the weapon itself.\n\t\t\t\t\t\tFALLTHROUGH;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tif (recoverWeapon)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\taddItemsToBaseStores(rule, base, 1, true);\n\t\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (rule->getBattleType() == BT_NONE)\n\t\t\t\t{\n\t\t\t\t\tfor (auto* xcraft : *base->getCrafts())\n\t\t\t\t\t{\n\t\t\t\t\t\txcraft->reuseItem(rule);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// special case of fixed weapons on a soldier's armor (and HWPs, but only non-fixed ammo)\n\t\t\t// makes sure we recover the ammunition from this weapon\n\t\t\telse if (rule->isFixed() && bi->getOwner() && bi->getOwner()->getOriginalFaction() == FACTION_PLAYER)\n\t\t\t{\n\t\t\t\tswitch (rule->getBattleType())\n\t\t\t\t{\n\t\t\t\t\tcase BT_FIREARM:\n\t\t\t\t\tcase BT_MELEE:\n\t\t\t\t\t\tif (bi->getOwner()->getGeoscapeSoldier())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// It's a weapon, count any rounds left in the clip.\n\t\t\t\t\t\t\trecoveryAmmoInWeapon(bi);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tBattleItem* hwpFixedAmmoItem = nullptr;\n\t\t\t\t\t\t\tif (rule->getVehicleUnit() && rule->getVehicleClipAmmo())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// remove fixed ammo (it will be recovered later elsewhere)\n\t\t\t\t\t\t\t\thwpFixedAmmoItem = bi->setAmmoForSlot(rule->getVehicleFixedAmmoSlot(), nullptr);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// recover the rest (i.e. non-fixed ammo)\n\t\t\t\t\t\t\trecoveryAmmoInWeapon(bi);\n\n\t\t\t\t\t\t\tif (hwpFixedAmmoItem)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// put fixed ammo back in\n\t\t\t\t\t\t\t\tbi->setAmmoForSlot(rule->getVehicleFixedAmmoSlot(), hwpFixedAmmoItem);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n* Recovers a live civilian from the battlescape.\n* @param from Battle unit to recover.\n* @param base Base to add items to.\n*/\nvoid DebriefingState::recoverCivilian(BattleUnit *from, Base *base, Craft* craft)\n{\n\tconst Unit* rule = from->getUnitRules();\n\tif (rule->isRecoverableAsCivilian() == false)\n\t{\n\t\treturn;\n\t}\n\tif (rule->isRecoverableAsScientist())\n\t{\n\t\tTransfer *t = new Transfer(24);\n\t\tt->setScientists(1);\n\t\tbase->getTransfers()->push_back(t);\n\t}\n\telse if (rule->isRecoverableAsEngineer())\n\t{\n\t\tTransfer *t = new Transfer(24);\n\t\tt->setEngineers(1);\n\t\tbase->getTransfers()->push_back(t);\n\t}\n\telse\n\t{\n\t\tconst RuleSoldier *ruleSoldier = rule->getCivilianRecoverySoldierType();\n\t\tif (ruleSoldier != 0)\n\t\t{\n\t\t\tTransfer *t = new Transfer(24);\n\t\t\tTarget* target = craft;\n\t\t\tif (!target)\n\t\t\t{\n\t\t\t\ttarget = base;\n\t\t\t}\n\t\t\tint nationality = _game->getSavedGame()->selectSoldierNationalityByLocation(_game->getMod(), ruleSoldier, target);\n\t\t\tSoldier *s = _game->getMod()->genSoldier(_game->getSavedGame(), ruleSoldier, nationality);\n\t\t\tYAML::YamlRootNodeReader reader(from->getUnitRules()->getSpawnedSoldierTemplate(), \"(spawned soldier template)\");\n\t\t\ts->load(reader.toBase(), _game->getMod(), _game->getSavedGame(), _game->getMod()->getScriptGlobal(), true); // load from soldier template\n\t\t\tif (!from->getUnitRules()->getSpawnedPersonName().empty())\n\t\t\t{\n\t\t\t\ts->setName(tr(from->getUnitRules()->getSpawnedPersonName()));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\ts->genName();\n\t\t\t}\n\t\t\tt->setSoldier(s);\n\t\t\tbase->getTransfers()->push_back(t);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tconst RuleItem *ruleItem = rule->getCivilianRecoveryItemType();\n\t\t\tif (ruleItem != 0)\n\t\t\t{\n\t\t\t\tif (!ruleItem->isAlien())\n\t\t\t\t{\n\t\t\t\t\taddItemsToBaseStores(ruleItem, base, 1, true);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tconst RuleItem *ruleLiveAlienItem = ruleItem;\n\t\t\t\t\tbool killPrisonersAutomatically = base->getAvailableContainment(ruleLiveAlienItem->getPrisonType()) == 0;\n\t\t\t\t\tif (killPrisonersAutomatically)\n\t\t\t\t\t{\n\t\t\t\t\t\t// check also other bases, maybe we can transfer/redirect prisoners there\n\t\t\t\t\t\tfor (auto* xbase : *_game->getSavedGame()->getBases())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (xbase->getAvailableContainment(ruleLiveAlienItem->getPrisonType()) > 0)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tkillPrisonersAutomatically = false;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (killPrisonersAutomatically)\n\t\t\t\t\t{\n\t\t\t\t\t\t_containmentStateInfo[ruleLiveAlienItem->getPrisonType()] = 1; // 1 = not available in any base\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\taddItemsToBaseStores(ruleLiveAlienItem, base, 1, false);\n\t\t\t\t\t\tint availableContainment = base->getAvailableContainment(ruleLiveAlienItem->getPrisonType());\n\t\t\t\t\t\tint usedContainment = base->getUsedContainment(ruleLiveAlienItem->getPrisonType());\n\t\t\t\t\t\tint freeContainment = availableContainment - (usedContainment * _limitsEnforced);\n\t\t\t\t\t\t// no capacity, or not enough capacity\n\t\t\t\t\t\tif (availableContainment == 0 || freeContainment < 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_containmentStateInfo[ruleLiveAlienItem->getPrisonType()] = 2; // 2 = overfull\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Recovers a live alien from the battlescape.\n * @param from Battle unit to recover.\n * @param base Base to add items to.\n */\nvoid DebriefingState::recoverAlien(BattleUnit *from, Base *base, Craft* craft)\n{\n\t// Transform a live alien into one or more recovered items?\n\tauto* ruleLiveAlienItem = from->getUnitRules()->getLiveAlienGeoscape();\n\tif (ruleLiveAlienItem && !ruleLiveAlienItem->getRecoveryTransformations().empty())\n\t{\n\t\taddItemsToBaseStores(ruleLiveAlienItem, base, 1, true);\n\n\t\t// Ignore everything else, e.g. no points for live/dead aliens (since you did NOT recover them)\n\t\t// Also no points or anything else for the recovered items\n\t\treturn;\n\t}\n\n\tif (!ruleLiveAlienItem)\n\t{\n\t\tif (from->getUnitRules()->isRecoverableAsCivilian())\n\t\t{\n\t\t\trecoverCivilian(from, base, craft);\n\t\t\treturn;\n\t\t}\n\n\t\t// This ain't good! Let's display at least some useful info before we crash...\n\t\tstd::ostringstream ss;\n\t\tss << \"Live alien item definition is missing. Unit ID = \" << from->getId();\n\t\tss << \"; Type = \" << from->getType();\n\t\tss << \"; Status = \" << from->getStatus();\n\t\tss << \"; Faction = \" << from->getFaction();\n\t\tss << \"; Orig. faction = \" << from->getOriginalFaction();\n\t\tif (from->getSpawnUnit())\n\t\t{\n\t\t\tss << \"; Spawn unit = [\" << from->getSpawnUnit()->getType() << \"]\";\n\t\t}\n\t\tss << \"; isSurrendering = \" << from->isSurrendering();\n\t\tthrow Exception(ss.str());\n\t}\n\n\tbool killPrisonersAutomatically = base->getAvailableContainment(ruleLiveAlienItem->getPrisonType()) == 0;\n\tif (killPrisonersAutomatically)\n\t{\n\t\t// check also other bases, maybe we can transfer/redirect prisoners there\n\t\tfor (auto* xbase : *_game->getSavedGame()->getBases())\n\t\t{\n\t\t\tif (xbase->getAvailableContainment(ruleLiveAlienItem->getPrisonType()) > 0)\n\t\t\t{\n\t\t\t\tkillPrisonersAutomatically = false;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\tif (killPrisonersAutomatically)\n\t{\n\t\t_containmentStateInfo[ruleLiveAlienItem->getPrisonType()] = 1; // 1 = not available in any base\n\n\t\tif (!from->getArmor()->getCorpseBattlescape().empty())\n\t\t{\n\t\t\tauto* corpseRule = from->getArmor()->getCorpseBattlescape().front();\n\t\t\tif (corpseRule && corpseRule->isRecoverable())\n\t\t\t{\n\t\t\t\tif (corpseRule->isCorpseRecoverable())\n\t\t\t\t{\n\t\t\t\t\taddStat(\"STR_ALIEN_CORPSES_RECOVERED\", 1, corpseRule->getRecoveryPoints());\n\t\t\t\t\tauto* corpseItem = from->getArmor()->getCorpseGeoscape();\n\t\t\t\t\taddItemsToBaseStores(corpseItem, base, 1, true);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\tRuleResearch *research = _game->getMod()->getResearch(from->getUnitRules()->getType());\n\t\tbool surrendered = (!from->isOut() || from->isIgnored())\n\t\t\t&& (from->isSurrendering() || _game->getSavedGame()->getSavedBattle()->getChronoTrigger() == FORCE_WIN_SURRENDER);\n\t\tif (research != 0 && !_game->getSavedGame()->isResearched(research))\n\t\t{\n\t\t\t// more points if it's not researched\n\t\t\taddStat(surrendered ? \"STR_LIVE_ALIENS_SURRENDERED\" : \"STR_LIVE_ALIENS_RECOVERED\", 1, from->getValue() * 2);\n\t\t}\n\t\telse if (_game->getMod()->getGiveScoreAlsoForResearchedArtifacts())\n\t\t{\n\t\t\taddStat(surrendered ? \"STR_LIVE_ALIENS_SURRENDERED\" : \"STR_LIVE_ALIENS_RECOVERED\", 1, from->getValue() * 2);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// 10 points for recovery\n\t\t\taddStat(surrendered ? \"STR_LIVE_ALIENS_SURRENDERED\" : \"STR_LIVE_ALIENS_RECOVERED\", 1, 10);\n\t\t}\n\n\t\taddItemsToBaseStores(ruleLiveAlienItem, base, 1, false);\n\t\tint availableContainment = base->getAvailableContainment(ruleLiveAlienItem->getPrisonType());\n\t\tint usedContainment = base->getUsedContainment(ruleLiveAlienItem->getPrisonType());\n\t\tint freeContainment = availableContainment - (usedContainment * _limitsEnforced);\n\t\t// no capacity, or not enough capacity\n\t\tif (availableContainment == 0 || freeContainment < 0)\n\t\t{\n\t\t\t_containmentStateInfo[ruleLiveAlienItem->getPrisonType()] = 2; // 2 = overfull\n\t\t}\n\t}\n}\n\n/**\n * Gets the number of recovered items of certain type.\n * @param rule Type of item.\n */\nint DebriefingState::getRecoveredItemCount(const RuleItem *rule)\n{\n\tauto it = _recoveredItems.find(rule);\n\tif (it != _recoveredItems.end())\n\t\treturn it->second;\n\n\treturn 0;\n}\n\n/**\n * Gets the total number of recovered items.\n */\nint DebriefingState::getTotalRecoveredItemCount()\n{\n\tint total = 0;\n\tfor (const auto& item : _recoveredItems)\n\t{\n\t\ttotal += item.second;\n\t}\n\treturn total;\n}\n\n/**\n * Decreases the number of recovered items by the sold/transferred amount.\n * @param rule Type of item.\n * @param amount Number of items sold or transferred.\n */\nvoid DebriefingState::decreaseRecoveredItemCount(const RuleItem *rule, int amount)\n{\n\tauto it = _recoveredItems.find(rule);\n\tif (it != _recoveredItems.end())\n\t{\n\t\tit->second = std::max(0, it->second - amount);\n\t}\n}\n\n/**\n * Hides the SELL and TRANSFER buttons.\n */\nvoid DebriefingState::hideSellTransferButtons()\n{\n\t_showSellButton = false;\n\t_btnSell->setVisible(_showSellButton);\n\t_btnTransfer->setVisible(_showSellButton);\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/DebriefingState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include <string>\n#include <vector>\n#include <map>\n#include \"../Savegame/SavedGame.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass TextList;\nclass BattleItem;\nclass Craft;\nclass Base;\nclass Region;\nclass Country;\nclass RuleItem;\nclass RuleEvent;\nclass BattleUnit;\nstruct UnitStats;\n\nstruct DebriefingStat {\n\tstd::string item;\n\tint qty;\n\tint score;\n\tbool recovery;\n\n\tDebriefingStat(const std::string &_item, bool _recovery) : item(_item), qty(0), score(0), recovery(_recovery) {};\n\t};\n\nstruct ReequipStat { std::string item; int qty; std::string craft; int listOrder; };\n\nstruct RecoveryItem { std::string name; int value; };\n\n/**\n * Debriefing screen shown after a Battlescape\n * mission that displays the results.\n */\nclass DebriefingState : public State\n{\nprivate:\n\ttypedef std::pair<std::string, UnitStats> SoldierStatsEntry;\n\n\tRuleEvent *_eventToSpawn;\n\tRegion *_region;\n\tCountry *_country;\n\tBase *_base;\n\tstd::vector<DebriefingStat*> _stats;\n\tstd::vector<SoldierStatsEntry> _soldierStats;\n\tTextButton *_btnOk, *_btnStats, *_btnSell, *_btnTransfer;\n\tWindow *_window;\n\tText *_txtTitle, *_txtItem, *_txtQuantity, *_txtScore, *_txtRecovery, *_txtRating;\n\tText *_txtSoldier, *_txtTU, *_txtStamina, *_txtHealth, *_txtBravery, *_txtReactions;\n\tText *_txtFiring, *_txtThrowing, *_txtMelee, *_txtStrength, *_txtPsiStrength, *_txtPsiSkill;\n\tTextList *_lstStats, *_lstRecovery, *_lstTotal, *_lstSoldierStats, *_lstRecoveredItems;\n\tstd::string _currentTooltip;\n\tText *_txtTooltip;\n\tstd::vector<ReequipStat> _missingItems;\n\tstd::map<const RuleItem*, int> _rounds, _roundsPainKiller, _roundsStimulant, _roundsHeal, _recoveredItems;\n\tUint8 _ammoColor;\n\tstd::map<int, RecoveryItem*> _recoveryStats;\n\tbool _positiveScore, _destroyBase, _promotions, _showSellButton, _initDone;\n\tstd::map<int, int>  _containmentStateInfo;\n\tint _limitsEnforced;\n\tMissionStatistics *_missionStatistics;\n\tstd::vector<Soldier*> _soldiersCommended, _deadSoldiersCommended;\n\t/// Adds to the debriefing stats.\n\tvoid addStat(const std::string &name, int quantity, int score);\n\t/// Prepares debriefing.\n\tvoid prepareDebriefing();\n\t/// Adds item(s) to base stores.\n\tvoid addItemsToBaseStores(const RuleItem *ruleItem, Base *base, int quantity, bool considerTransformations);\n\tvoid addItemsToBaseStores(const std::string &itemType, Base *base, int quantity, bool considerTransformations);\n\t/// Recovers items from the battlescape.\n\tvoid recoverItems(std::vector<BattleItem*> *from, Base *base, Craft* craft);\n\t/// Recovers a civilian from the battlescape.\n\tvoid recoverCivilian(BattleUnit *from, Base *base, Craft* craft);\n\t/// Recovers an alien from the battlescape.\n\tvoid recoverAlien(BattleUnit *from, Base *base, Craft* craft);\n\t/// Reequips a craft after a mission.\n\tvoid reequipCraft(Base *base, Craft *craft, bool vehicleItemsCanBeDestroyed);\n\t/// 0 = score, 1 = stat improvement, 2 = recovered items\n\tint _pageNumber;\n\t/// Sets the visibility according to the _pageNumber\n\tvoid applyVisibility();\n\t/// Creates a string for the soldier stats table from a stat difference value\n\tstd::string makeSoldierString(int stat);\npublic:\n\t/// Creates the Debriefing state.\n\tDebriefingState();\n\t/// Cleans up the Debriefing state.\n\t~DebriefingState();\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Prepare debriefing.\n\tvoid init() override;\n\t/// Handler for clicking the STATS button.\n\tvoid btnStatsClick(Action *action);\n\t/// Handler for clicking the SELL button.\n\tvoid btnSellClick(Action *action);\n\t/// Handler for clicking the TRANSFER button.\n\tvoid btnTransferClick(Action *action);\n\t/// Handler for showing tooltip.\n\tvoid txtTooltipIn(Action *action);\n\t/// Handler for hiding tooltip.\n\tvoid txtTooltipOut(Action *action);\n\t// Gets the number of recovered items of certain type.\n\tint getRecoveredItemCount(const RuleItem *rule);\n\t// Gets the total number of recovered items.\n\tint getTotalRecoveredItemCount();\n\t// Decreases the number of recovered items by the sold/transferred amount.\n\tvoid decreaseRecoveredItemCount(const RuleItem *rule, int amount);\n\t// Hides the SELL and TRANSFER buttons.\n\tvoid hideSellTransferButtons();\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/ExperienceOverviewState.cpp",
    "content": "/*\n * Copyright 2010-2015 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <sstream>\n#include \"BattlescapeGame.h\"\n#include \"BattlescapeState.h\"\n#include \"Camera.h\"\n#include \"ExperienceOverviewState.h\"\n#include \"Map.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Language.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Savegame/BattleUnit.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"../Savegame/SavedGame.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Experience Overview screen.\n */\nExperienceOverviewState::ExperienceOverviewState(BattlescapeState* parent) : _parent(parent)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 320, 200, 0, 0);\n\t_txtTitle = new Text(300, 17, 10, 13);\n\t_txtName = new Text(100, 10, 10, 40);\n\t_btnOk = new TextButton(160, 16, 80, 174);\n\t_lstSoldiers = new TextList(286, 112, 8, 52);\n\t_txtBravery = new Text(18, 10, 120 - 3, 40);\n\t_txtReactions = new Text(18, 10, 141 - 3, 40);\n\t_txtFiring = new Text(18, 10, 162 - 3, 40);\n\t_txtThrowing = new Text(18, 10, 183 - 3, 40);\n\t_txtPsiSkill = new Text(18, 10, 204 - 3, 40);\n\t_txtPsiStrength = new Text(18, 10, 225 - 3, 40);\n\t_txtMelee = new Text(18, 10, 246 - 3, 40);\n\t_txtMana = new Text(18, 10, 267 - 3, 40);\n\n\t// Set palette\n\t_game->getSavedGame()->getSavedBattle()->setPaletteByDepth(this);\n\n\tadd(_window, \"messageWindowBorder\", \"battlescape\");\n\tadd(_btnOk, \"messageWindowButtons\", \"battlescape\");\n\tadd(_txtName, \"messageWindows\", \"battlescape\");\n\tadd(_txtTitle, \"messageWindows\", \"battlescape\");\n\tadd(_lstSoldiers, \"optionLists\", \"battlescape\");\n\tadd(_txtBravery, \"messageWindows\", \"battlescape\");\n\tadd(_txtReactions, \"messageWindows\", \"battlescape\");\n\tadd(_txtFiring, \"messageWindows\", \"battlescape\");\n\tadd(_txtThrowing, \"messageWindows\", \"battlescape\");\n\tadd(_txtPsiSkill, \"messageWindows\", \"battlescape\");\n\tadd(_txtPsiStrength, \"messageWindows\", \"battlescape\");\n\tadd(_txtMelee, \"messageWindows\", \"battlescape\");\n\tadd(_txtMana, \"messageWindows\", \"battlescape\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\t_window->setHighContrast(true);\n\t_window->setBackground(_game->getMod()->getSurface(\"TAC00.SCR\"));\n\n\t_btnOk->setHighContrast(true);\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&ExperienceOverviewState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&ExperienceOverviewState::btnOkClick, Options::keyCancel);\n\n\t_txtTitle->setHighContrast(true);\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_EXPERIENCE_OVERVIEW\"));\n\n\t_txtName->setHighContrast(true);\n\t_txtBravery->setHighContrast(true);\n\t_txtReactions->setHighContrast(true);\n\t_txtFiring->setHighContrast(true);\n\t_txtThrowing->setHighContrast(true);\n\t_txtPsiSkill->setHighContrast(true);\n\t_txtPsiStrength->setHighContrast(true);\n\t_txtMelee->setHighContrast(true);\n\t_txtMana->setHighContrast(true);\n\n\t_txtName->setText(tr(\"STR_NAME\"));\n\t_txtBravery->setText(tr(\"STR_BRAVERY_ABBREVIATION\"));\n\t_txtReactions->setText(tr(\"STR_REACTIONS_ABBREVIATION\"));\n\t_txtFiring->setText(tr(\"STR_FIRING_ACCURACY_ABBREVIATION\"));\n\t_txtThrowing->setText(tr(\"STR_THROWING_ACCURACY_ABBREVIATION\"));\n\t_txtPsiSkill->setText(tr(\"STR_PSIONIC_SKILL_ABBREVIATION\"));\n\t_txtPsiStrength->setText(tr(\"STR_PSIONIC_STRENGTH_ABBREVIATION\"));\n\t_txtMelee->setText(tr(\"STR_MELEE_ACCURACY_ABBREVIATION\"));\n\tif (_game->getMod()->isManaFeatureEnabled() && _game->getMod()->isManaTrainingPrimary())\n\t{\n\t\t_txtMana->setText(tr(\"STR_MANA_ABBREVIATION\"));\n\t}\n\n\t_lstSoldiers->setColumns(10, 110, 21, 21, 21, 21, 21, 21, 21, 21, 18);\n\t_lstSoldiers->setSelectable(true);\n\t_lstSoldiers->setHighContrast(true);\n\t_lstSoldiers->setBackground(_window);\n\t_lstSoldiers->setMargin(2);\n\t_lstSoldiers->onMouseClick((ActionHandler)&ExperienceOverviewState::lstSoldiersClick);\n\n\t_lstSoldiers->clearList();\n\tint row = 0;\n\tfor (auto* soldier : *_game->getSavedGame()->getSavedBattle()->getUnits())\n\t{\n\t\tif (!soldier->getGeoscapeSoldier())\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\t\tif (soldier->getStatus() == STATUS_DEAD || soldier->getStatus() == STATUS_IGNORE_ME)\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst UnitStats* stats = soldier->getExpStats();\n\n\t\tstd::ostringstream bravery;\n\t\tbravery << stats->bravery;\n\t\tstd::ostringstream reactions;\n\t\treactions << stats->reactions;\n\t\tstd::ostringstream firing;\n\t\tfiring << stats->firing;\n\t\tstd::ostringstream throwing;\n\t\tthrowing << stats->throwing;\n\t\tstd::ostringstream psiSkill;\n\t\tpsiSkill << stats->psiSkill;\n\t\tstd::ostringstream psiStrength;\n\t\tpsiStrength << stats->psiStrength;\n\t\tstd::ostringstream melee;\n\t\tmelee << stats->melee;\n\t\tstd::ostringstream mana;\n\t\tif (_game->getMod()->isManaFeatureEnabled() && _game->getMod()->isManaTrainingPrimary())\n\t\t{\n\t\t\tmana << stats->mana;\n\t\t}\n\n\t\t_soldiers.push_back(soldier);\n\t\t_lstSoldiers->addRow(10,\n\t\t\tsoldier->getName(_game->getLanguage()).c_str(),\n\t\t\tbravery.str().c_str(),\n\t\t\treactions.str().c_str(),\n\t\t\tfiring.str().c_str(),\n\t\t\tthrowing.str().c_str(),\n\t\t\tpsiSkill.str().c_str(),\n\t\t\tpsiStrength.str().c_str(),\n\t\t\tmelee.str().c_str(),\n\t\t\tmana.str().c_str(),\n\t\t\t\"\");\n\t\tfor (int col = 1; col < 9; ++col)\n\t\t{\n\t\t\tif (_lstSoldiers->getCellText(row, col) != \"0\")\n\t\t\t{\n\t\t\t\t_lstSoldiers->setCellColor(row, col, _lstSoldiers->getSecondaryColor());\n\t\t\t}\n\t\t}\n\t\trow++;\n\t}\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid ExperienceOverviewState::btnOkClick(Action*)\n{\n\t_game->popState();\n}\n\n/**\n * Selects the soldier if possible and returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid ExperienceOverviewState::lstSoldiersClick(Action*)\n{\n\tif (_parent->allowButtons())\n\t{\n\t\tauto index = _lstSoldiers->getSelectedRow();\n\t\tauto* bu = _soldiers.at(index);\n\n\t\tif (bu->isSelectable(_game->getSavedGame()->getSavedBattle()->getSide(), false, false))\n\t\t{\n\t\t\t// select\n\t\t\t_parent->getBattleGame()->cancelAllActions();\n\t\t\t_parent->getBattleGame()->primaryAction(bu->getPosition());\n\t\t}\n\n\t\t// center on position\n\t\t_parent->getMap()->getCamera()->centerOnPosition(bu->getPosition());\n\n\t\t_game->popState();\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/ExperienceOverviewState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2015 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <vector>\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass TextList;\nclass BattlescapeState;\n\n/**\n * Displays a list of soldiers in battlescape and their gained experience.\n */\nclass ExperienceOverviewState : public State\n{\nprivate:\n\tTextButton *_btnOk;\n\tWindow *_window;\n\tText *_txtTitle, *_txtName;\n\tText *_txtBravery, *_txtReactions, *_txtFiring, *_txtThrowing, *_txtPsiSkill, *_txtPsiStrength, *_txtMelee, *_txtMana;\n\tTextList *_lstSoldiers;\n\n\tBattlescapeState* _parent;\n\tstd::vector<BattleUnit*> _soldiers;\npublic:\n\t/// Creates the Experience Overview state.\n\tExperienceOverviewState(BattlescapeState* parent);\n\t/// Cleans up the Experience Overview state.\n\t~ExperienceOverviewState() = default;\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action* action);\n\t/// Handler for clicking the Soldiers list.\n\tvoid lstSoldiersClick(Action* action);\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/Explosion.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Explosion.h\"\n\nnamespace OpenXcom\n{\n\nconst int Explosion::HIT_FRAMES = 4;\nconst int Explosion::EXPLODE_FRAMES = 8;\nconst int Explosion::BULLET_FRAMES = 10;\n/**\n * Sets up a Explosion sprite with the specified size and position.\n * @param position Explosion center position in voxel x/y/z.\n * @param startFrame A start frame - can be used to offset different explosions at different frames.\n * @param big Flag to indicate it is a bullet hit (false), or a real explosion (true).\n * @param hit True for melee and psi attacks.\n * @param frames Override for number of frames in the animation.\n */\nExplosion::Explosion(Position position, int startFrame, int frameDelay, bool big, bool hit, int frames) :\n\t_position(position), _currentFrame(startFrame), _startFrame(startFrame), _frameDelay(frameDelay), _big(big), _hit(hit), _frames(frames)\n{\n\n}\n\n/**\n * Deletes the Explosion.\n */\nExplosion::~Explosion()\n{\n\n}\n\n/**\n * Animates the explosion further.\n * @return false If the animation is finished.\n */\nbool Explosion::animate()\n{\n\tif (_frameDelay > 0)\n\t{\n\t\t_frameDelay--;\n\t\treturn true;\n\t}\n\n\tif (_frames <= 0)\n\t{\n\t\tif (_hit)\n\t\t{\n\t\t\t_frames = HIT_FRAMES;\n\t\t}\n\t\telse if (_big)\n\t\t{\n\t\t\t_frames = EXPLODE_FRAMES;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_frames = BULLET_FRAMES;\n\t\t}\n\t}\n\n\t_currentFrame++;\n\tif (_currentFrame == _startFrame + _frames)\n\t{\n\t\treturn false;\n\t}\n\telse\n\t{\n\t\treturn true;\n\t}\n}\n\n/**\n * Gets the current position in voxel space.\n * @return position in voxel space.\n */\nPosition Explosion::getPosition() const\n{\n\treturn _position;\n}\n\n/**\n * Gets the current frame in the animation.\n * @return frame number.\n */\nint Explosion::getCurrentFrame() const\n{\n\tif (_frameDelay > 0)\n\t\treturn -1;\n\treturn _currentFrame;\n}\n\n/**\n * Returns flag to indicate if it is a bullet hit (false), or a real explosion (true).\n * @return True if it is a real explosion, false if it is a bullet hit.\n */\nbool Explosion::isBig() const\n{\n\treturn _big;\n}\n\n/**\n * Returns flag to indicate if it is a melee or psi hit.\n * @return True if it is a melee hit or psi hit.\n */\nbool Explosion::isHit() const\n{\n\treturn _hit;\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/Explosion.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Position.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * A class that represents an explosion animation. Map is the owner of an instance of this class during its short life.\n * It represents both a bullet hit, as a real explosion animation.\n */\nclass Explosion\n{\nprivate:\n\tPosition _position;\n\tint _currentFrame, _startFrame, _frameDelay;\n\tbool _big, _hit;\n\tint _frames;\npublic:\n\tstatic const int HIT_FRAMES;\n\tstatic const int EXPLODE_FRAMES;\n\tstatic const int BULLET_FRAMES;\n\t/// Creates a new Explosion.\n\tExplosion(Position _position, int startFrame, int frameDelay = 0, bool big = false, bool hit = false, int frames = -1);\n\t/// Cleans up the Explosion.\n\t~Explosion();\n\t/// Moves the Explosion on one frame.\n\tbool animate();\n\t/// Gets the current position in voxel space.\n\tPosition getPosition() const;\n\t/// Gets the current frame.\n\tint getCurrentFrame() const;\n\t/// Checks if this is a real explosion.\n\tbool isBig() const;\n\t/// Checks if this is a melee or psi hit.\n\tbool isHit() const;\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/ExplosionBState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"ExplosionBState.h\"\n#include \"BattlescapeState.h\"\n#include \"Explosion.h\"\n#include \"TileEngine.h\"\n#include \"Map.h\"\n#include \"Camera.h\"\n#include \"../Savegame/BattleUnit.h\"\n#include \"../Savegame/BattleItem.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"../Savegame/Tile.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Engine/RNG.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Sets up an ExplosionBState.\n * @param parent Pointer to the BattleScape.\n * @param center Center position in voxelspace.\n * @param item Item involved in the explosion (eg grenade).\n * @param unit Unit involved in the explosion (eg unit throwing the grenade).\n * @param tile Tile the explosion is on.\n * @param lowerWeapon Whether the unit causing this explosion should now lower their weapon.\n * @param range Distance between weapon and target.\n * @param explosionCounter Counter for chain terrain explosions.\n * @param terrainMeleeTilePart Tile part for terrain melee.\n */\nExplosionBState::ExplosionBState(BattlescapeGame *parent, LastPositions center, BattleActionAttack attack, Tile *tile, bool lowerWeapon, int range, int explosionCounter, int terrainMeleeTilePart) : BattleState(parent),\n\t_explosionCounter(explosionCounter), _terrainMeleeTilePart(terrainMeleeTilePart), _attack(attack), _center(center.last), _before(center.before), _damageType(), _tile(tile), _targetPsiOrHit(nullptr),\n\t_power(0), _radius(6), _range(range), _areaOfEffect(false), _lowerWeapon(lowerWeapon), _hit(false), _psi(false)\n{\n\n}\n\n/**\n * Deletes the ExplosionBState.\n */\nExplosionBState::~ExplosionBState()\n{\n\n}\n\n/**\n * Set new value to reference if new value is not equal -1.\n * @param oldValue old value to change.\n * @param newValue new value to set, but only if is not equal -1.\n */\nvoid ExplosionBState::optValue(int& oldValue, int newValue) const\n{\n\tif (newValue != -1)\n\t{\n\t\toldValue = newValue;\n\t}\n}\n\n/**\n * Initializes the explosion.\n * The animation and sound starts here.\n * If the animation is finished, the actual effect takes place.\n */\nvoid ExplosionBState::init()\n{\n\tBattleType type = BT_NONE;\n\tBattleActionType action = _attack.type;\n\tconst RuleItem* itemRule = 0;\n\tbool miss = false;\n\tif (_attack.damage_item)\n\t{\n\t\titemRule = _attack.damage_item->getRules();\n\t\ttype = itemRule->getBattleType();\n\n\t\t_power = 0;\n\t\t_hit = action == BA_HIT;\n\t\t_psi = type == BT_PSIAMP && action != BA_USE && !_hit;\n\t\tif (_hit && type != BT_MELEE)\n\t\t{\n\t\t\t_power += itemRule->getMeleeBonus(_attack);\n\n\t\t\t_radius = 0;\n\t\t\t_damageType = itemRule->getMeleeType();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (_attack.weapon_item && _attack.weapon_item->getRules()->getIgnoreAmmoPower())\n\t\t\t{\n\t\t\t\t_power += _attack.weapon_item->getRules()->getPowerBonus(_attack);\n\t\t\t\t_power -= _attack.weapon_item->getRules()->getPowerRangeReduction(_range);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_power += itemRule->getPowerBonus(_attack);\n\t\t\t\t_power -= itemRule->getPowerRangeReduction(_range);\n\t\t\t}\n\n\t\t\t_radius = itemRule->getExplosionRadius(_attack);\n\t\t\t_damageType = itemRule->getDamageType();\n\t\t}\n\n\t\tif (type == BT_PSIAMP || _hit)\n\t\t{\n\t\t\tPosition targetPos = _center.toTile();\n\t\t\t_targetPsiOrHit = _parent->getSave()->getTile(targetPos)->getOverlappingUnit(_parent->getSave());\n\t\t}\n\n\t\t//testing if we hit target\n\t\tif (action == BA_SELF_DESTRUCT)\n\t\t{\n\t\t\tif (!RNG::percent(itemRule->getSpecialChance()))\n\t\t\t{\n\t\t\t\t_power = 0;\n\t\t\t}\n\t\t}\n\t\telse if (type == BT_PSIAMP && !_hit)\n\t\t{\n\t\t\tif (action != BA_USE)\n\t\t\t{\n\t\t\t\t_power = 0;\n\t\t\t}\n\t\t\tif (!_parent->getTileEngine()->psiAttack(_attack, _targetPsiOrHit))\n\t\t\t{\n\t\t\t\t_power = 0;\n\t\t\t\tmiss = true;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_parent->psiAttackMessage(_attack, _targetPsiOrHit);\n\t\t\t}\n\t\t}\n\t\telse if (type == BT_MELEE || _hit)\n\t\t{\n\t\t\tif (!_parent->getTileEngine()->meleeAttack(_attack, _targetPsiOrHit, _terrainMeleeTilePart))\n\t\t\t{\n\t\t\t\t_power = 0;\n\t\t\t\tmiss = true;\n\t\t\t}\n\t\t}\n\t\telse if (type == BT_FIREARM)\n\t\t{\n\t\t\tif (_power <= 0)\n\t\t\t{\n\t\t\t\tmiss = true;\n\t\t\t}\n\t\t}\n\n\t\t_areaOfEffect = type != BT_MELEE && _radius != 0 &&\n\t\t\t\t\t\t(type != BT_PSIAMP || action == BA_USE) &&\n\t\t\t\t\t\t!_hit && !miss;\n\t}\n\telse if (_tile)\n\t{\n\t\tItemDamageType DT;\n\t\tswitch (_tile->getExplosiveType())\n\t\t{\n\t\tcase 0:\n\t\t\tDT = DT_HE;\n\t\t\tbreak;\n\t\tcase 5:\n\t\t\tDT = DT_IN;\n\t\t\tbreak;\n\t\tcase 6:\n\t\t\tDT = DT_STUN;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tDT = DT_SMOKE;\n\t\t\tbreak;\n\t\t}\n\t\t_power = _tile->getExplosive();\n\t\t_tile->setExplosive(0, 0, true);\n\t\t_damageType = _parent->getMod()->getDamageType(DT);\n\t\t_radius = _power /10;\n\t\t_areaOfEffect = true;\n\t}\n\telse\n\t{\n\t\t_power = 120;\n\t\t_damageType = _parent->getMod()->getDamageType(DT_HE);\n\t\t_areaOfEffect = true;\n\t}\n\n\n\tbool range = !(_hit || (_attack.weapon_item && _attack.weapon_item->getRules()->getBattleType() == BT_PSIAMP));\n\n\tif (_areaOfEffect)\n\t{\n\t\tif (_power > 0)\n\t\t{\n\t\t\t_parent->getSave()->getTileEngine()->explode(_attack, _center, _power, _damageType, _radius, range);\n\n\t\t\tint powerForAnimation = _power;\n\t\t\tif (itemRule && itemRule->getPowerForAnimation() > 0)\n\t\t\t{\n\t\t\t\tpowerForAnimation = itemRule->getPowerForAnimation();\n\t\t\t}\n\n\t\t\tint frame = Mod::EXPLOSION_OFFSET;\n\t\t\tint frameCount = -1;\n\t\t\tint sound = powerForAnimation <= 80 ? Mod::SMALL_EXPLOSION : Mod::LARGE_EXPLOSION;\n\n\t\t\tif (itemRule)\n\t\t\t{\n\t\t\t\tframe = itemRule->getHitAnimation();\n\t\t\t\tframeCount = itemRule->getHitAnimationFrames();\n\t\t\t\toptValue(sound, itemRule->getExplosionHitSound());\n\t\t\t}\n\t\t\tif (_parent->getDepth() > 0)\n\t\t\t{\n\t\t\t\tframe -= (frameCount > 0 ? frameCount : Explosion::EXPLODE_FRAMES);\n\t\t\t}\n\t\t\tint frameDelay = 0;\n\t\t\tint counter = std::max(1, (powerForAnimation / 5) / 5);\n\t\t\t_parent->getMap()->setBlastFlash(true);\n\t\t\tint lowerLimit = std::max(1, powerForAnimation / 5);\n\t\t\tfor (int i = 0; i < lowerLimit; i++)\n\t\t\t{\n\t\t\t\tint X = RNG::generate(-powerForAnimation / 2, powerForAnimation / 2);\n\t\t\t\tint Y = RNG::generate(-powerForAnimation / 2, powerForAnimation / 2);\n\t\t\t\tPosition p = _center;\n\t\t\t\tp.x += X; p.y += Y;\n\t\t\t\tExplosion *explosion = new Explosion(p, frame, frameDelay, true, false, frameCount);\n\t\t\t\t// add the explosion on the map\n\t\t\t\t_parent->getMap()->getExplosions()->push_back(explosion);\n\t\t\t\tif (i > 0 && i % counter == 0)\n\t\t\t\t{\n\t\t\t\t\tframeDelay++;\n\t\t\t\t}\n\t\t\t}\n\t\t\tint explosionSpeed = BattlescapeState::DEFAULT_ANIM_SPEED/2;\n\t\t\tif (itemRule)\n\t\t\t{\n\t\t\t\texplosionSpeed -= (10 * itemRule->getExplosionSpeed());\n\t\t\t}\n\t\t\tif (_explosionCounter > 6)\n\t\t\t{\n\t\t\t\texplosionSpeed = 1; // maximum animation speed for long chain terrain explosions\n\t\t\t}\n\t\t\t_parent->setStateInterval(std::max(1, explosionSpeed));\n\t\t\t// explosion sound\n\t\t\t_parent->playSound(sound);\n\t\t\tif (_parent->getMap()->getFollowProjectile() || _explosionCounter > 0)\n\t\t\t{\n\t\t\t\t_parent->getMap()->getCamera()->centerOnPosition(_center.toTile(), false);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_parent->popState();\n\t\t}\n\t}\n\telse\n\t// create a bullet hit\n\t{\n\t\t_parent->getSave()->getTileEngine()->hit(_attack, _center, _power, _damageType, range, _terrainMeleeTilePart);\n\n\t\t_parent->setStateInterval(std::max(1, ((BattlescapeState::DEFAULT_ANIM_SPEED/2) - (10 * itemRule->getExplosionSpeed()))));\n\t\tint anim = -1;\n\t\tint animFrames = -1;\n\t\tint sound = -1;\n\n\t\tconst RuleItem *weaponRule = _attack.weapon_item->getRules();\n\t\tconst RuleItem *damageRule = _attack.weapon_item != _attack.damage_item ? itemRule : nullptr;\n\n\t\tif (_hit || _psi)\n\t\t{\n\t\t\tanim = weaponRule->getMeleeAnimation();\n\t\t\tanimFrames = weaponRule->getMeleeAnimationFrames();\n\t\t\tif (_psi)\n\t\t\t{\n\t\t\t\t// psi attack sound is based weapon hit sound\n\t\t\t\tsound = weaponRule->getHitSound();\n\n\t\t\t\toptValue(anim, weaponRule->getPsiAnimation());\n\t\t\t\toptValue(animFrames, weaponRule->getPsiAnimationFrames());\n\t\t\t\toptValue(sound, weaponRule->getPsiSound());\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tsound = weaponRule->getMeleeSound();\n\t\t\t\tif (damageRule)\n\t\t\t\t{\n\t\t\t\t\toptValue(anim, damageRule->getMeleeAnimation());\n\t\t\t\t\toptValue(animFrames, damageRule->getMeleeAnimationFrames());\n\t\t\t\t\toptValue(sound, damageRule->getMeleeSound());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tanim = itemRule->getHitAnimation();\n\t\t\tanimFrames = itemRule->getHitAnimationFrames();\n\t\t\tsound = itemRule->getHitSound();\n\t\t}\n\n\t\tif (miss)\n\t\t{\n\t\t\tif (_hit || _psi)\n\t\t\t{\n\t\t\t\toptValue(anim, weaponRule->getMeleeMissAnimation());\n\t\t\t\toptValue(animFrames, weaponRule->getMeleeMissAnimationFrames());\n\t\t\t\tif (_psi)\n\t\t\t\t{\n\t\t\t\t\t// psi attack sound is based weapon hit sound\n\t\t\t\t\toptValue(sound, weaponRule->getHitMissSound());\n\n\t\t\t\t\toptValue(anim, weaponRule->getPsiMissAnimation());\n\t\t\t\t\toptValue(animFrames, weaponRule->getPsiMissAnimationFrames());\n\t\t\t\t\toptValue(sound, weaponRule->getPsiMissSound());\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\toptValue(sound, weaponRule->getMeleeMissSound());\n\t\t\t\t\tif (damageRule)\n\t\t\t\t\t{\n\t\t\t\t\t\toptValue(anim, damageRule->getMeleeMissAnimation());\n\t\t\t\t\t\toptValue(animFrames, damageRule->getMeleeMissAnimationFrames());\n\t\t\t\t\t\toptValue(sound, damageRule->getMeleeMissSound());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\toptValue(anim, itemRule->getHitMissAnimation());\n\t\t\t\toptValue(animFrames, itemRule->getHitMissAnimationFrames());\n\t\t\t\toptValue(sound, itemRule->getHitMissSound());\n\t\t\t}\n\t\t}\n\n\t\tif (anim != -1)\n\t\t{\n\t\t\tExplosion *explosion = new Explosion(_center, anim, 0, false, (_hit || _psi), animFrames); // Don't burn the tile\n\t\t\t_parent->getMap()->getExplosions()->push_back(explosion);\n\t\t}\n\t\tif (_parent->getMap()->getFollowProjectile())\n\t\t{\n\t\t\t_parent->getMap()->getCamera()->setViewLevel(_center.z / 24);\n\t\t}\n\n\t\tif (_targetPsiOrHit && _parent->getSave()->getSide() == FACTION_HOSTILE && _targetPsiOrHit->getFaction() == FACTION_PLAYER)\n\t\t{\n\t\t\t_parent->getMap()->getCamera()->centerOnPosition(_center.toTile(), false);\n\t\t}\n\t\t// bullet hit sound\n\t\t_parent->playSound(sound, _center.toTile());\n\t}\n\n\tif (_attack.type == BA_SELF_DESTRUCT)\n\t{\n\t\tif (_attack.attacker)\n\t\t{\n\t\t\t_attack.attacker->setAlreadyExploded(false);\n\t\t}\n\t}\n}\n\n/**\n * Animates explosion sprites. If their animation is finished remove them from the list.\n * If the list is empty, this state is finished and the actual calculations take place.\n */\nvoid ExplosionBState::think()\n{\n\tif (!_parent->getMap()->getBlastFlash())\n\t{\n\t\tif (_parent->getMap()->getExplosions()->empty())\n\t\t\texplode();\n\n\t\tfor (auto iter = _parent->getMap()->getExplosions()->begin(); iter != _parent->getMap()->getExplosions()->end();)\n\t\t{\n\t\t\tExplosion* explosion = (*iter);\n\t\t\tif (!explosion->animate())\n\t\t\t{\n\t\t\t\tdelete explosion;\n\t\t\t\titer = _parent->getMap()->getExplosions()->erase(iter);\n\t\t\t\tif (_parent->getMap()->getExplosions()->empty())\n\t\t\t\t{\n\t\t\t\t\texplode();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t++iter;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Explosions cannot be cancelled.\n */\nvoid ExplosionBState::cancel()\n{\n}\n\n/**\n * Calculates the effects of the explosion.\n */\nvoid ExplosionBState::explode()\n{\n\tbool terrainExplosion = false;\n\tSavedBattleGame *save = _parent->getSave();\n\t// last minute adjustment: determine if we actually\n\tif (_hit)\n\t{\n\t\tif (_attack.attacker && !_attack.attacker->isOut())\n\t\t{\n\t\t\t_attack.attacker->aim(false);\n\t\t}\n\n\t\tif (_power <= 0)\n\t\t{\n\t\t\t_parent->popState();\n\t\t\treturn;\n\t\t}\n\n\t\tint sound = _attack.weapon_item->getRules()->getMeleeHitSound();\n\t\tif (_attack.weapon_item != _attack.damage_item)\n\t\t{\n\t\t\t// melee weapon with ammo\n\t\t\toptValue(sound, _attack.damage_item->getRules()->getMeleeHitSound());\n\t\t}\n\t\t_parent->playSound(sound, _center.toTile());\n\t}\n\n\tif (_tile)\n\t{\n\t\tterrainExplosion = true;\n\t}\n\tif (!_tile && !_attack.damage_item)\n\t{\n\t\tterrainExplosion = true;\n\t}\n\n\t// now check for new casualties\n\t_parent->checkForCasualties(_attack.damage_item ? _damageType : nullptr, _attack, false, terrainExplosion);\n\t// revive units if damage could give hp or reduce stun\n\t_parent->getSave()->reviveUnconsciousUnits(true);\n\t// if any unit get infected turn it to zombie\n\t_parent->convertInfected();\n\n\t// if this explosion was caused by a unit shooting, now it's the time to put the gun down\n\tif (_attack.attacker && !_attack.attacker->isOut() && _lowerWeapon)\n\t{\n\t\t_attack.attacker->aim(false);\n\t}\n\n\tif (_attack.damage_item && (_attack.damage_item->getRules()->getBattleType() == BT_GRENADE || _attack.damage_item->getRules()->getBattleType() == BT_PROXIMITYGRENADE))\n\t{\n\t\t_parent->getSave()->removeItem(_attack.damage_item);\n\t}\n\n\t_parent->popState();\n\n\t// check for terrain explosions\n\tTile *t = save->getTileEngine()->checkForTerrainExplosions();\n\tif (t)\n\t{\n\t\tPosition p = t->getPosition().toVoxel();\n\t\tp += Position(8,8,0);\n\t\t_parent->statePushFront(new ExplosionBState(_parent, p, BattleActionAttack{ BA_NONE, _attack.attacker, }, t, false, 0, _explosionCounter + 1));\n\t}\n\n\t// Spawn a unit if the item does that\n\tif (_attack.damage_item)\n\t{\n\t\t_parent->spawnNewUnit(_attack, _before.toTile());\n\t}\n\n\t// Spawn a item if the weapon does that\n\tif (_attack.damage_item)\n\t{\n\t\t_parent->spawnNewItem(_attack, _before.toTile());\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/ExplosionBState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"BattleState.h\"\n#include \"Position.h\"\n\nnamespace OpenXcom\n{\n\nclass BattlescapeGame;\nclass BattleUnit;\nclass BattleItem;\nclass Tile;\nstruct RuleDamageType;\n\n/**\n * Explosion state not only handles explosions, but also bullet impacts!\n * Refactoring tip : ImpactBState.\n */\nclass ExplosionBState : public BattleState\n{\nprivate:\n\tint _explosionCounter;\n\tint _terrainMeleeTilePart;\n\tBattleActionAttack _attack;\n\tPosition _center, _before;\n\tconst RuleDamageType *_damageType;\n\tTile *_tile;\n\tBattleUnit *_targetPsiOrHit;\n\tint _power;\n\tint _radius;\n\tint _range;\n\tbool _areaOfEffect, _lowerWeapon, _hit, _psi;\n\n\t/// Calculates the effects of the explosion.\n\tvoid explode();\n\t/// Set new value to reference if new value is not equal -1.\n\tvoid optValue(int &oldValue, int newValue) const;\npublic:\n\t/// Creates a new ExplosionBState class.\n\tExplosionBState(BattlescapeGame *parent, LastPositions center, BattleActionAttack attack, Tile *tile = 0, bool lowerWeapon = false, int range = 0, int explosionCounter = 0, int terrainMeleeTilePart = 0);\n\t/// Cleans up the ExplosionBState.\n\t~ExplosionBState();\n\t/// Initializes the state.\n\tvoid init() override;\n\t/// Handles a cancel request.\n\tvoid cancel() override;\n\t/// Runs state functionality every cycle.\n\tvoid think() override;\n\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/ExtendedBattlescapeLinksState.cpp",
    "content": "/*\n * Copyright 2010-2021 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"ExtendedBattlescapeLinksState.h\"\n#include \"BattlescapeGame.h\"\n#include \"BattlescapeState.h\"\n#include \"BriefingState.h\"\n#include \"InfoboxState.h\"\n#include \"Map.h\"\n#include \"NoExperienceState.h\"\n#include \"TurnDiaryState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Menu/NotesState.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Savegame/HitLog.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the ExtendedBattlescapeLinksState screen.\n */\nExtendedBattlescapeLinksState::ExtendedBattlescapeLinksState(BattlescapeState* parent, SavedBattleGame* save) : _parent(parent), _save(save)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 256, 180, 32, 10, POPUP_BOTH);\n\t_txtTitle = new Text(220, 17, 50, 33);\n\tif (Options::oxceFatFingerLinks)\n\t{\n\t\t_btnTouch = new TextButton(116, 25, 44, 50);\n\t\t_btnNightVision = new TextButton(116, 25, 161, 50);\n\t\t_btnPersonalLights = new TextButton(116, 25, 44, 76);\n\t\t_btnBrightness = new TextButton(116, 25, 161, 76);\n\t\t_btnTurnDiary = new TextButton(116, 25, 44, 102);\n\t\t_btnBriefing = new TextButton(116, 25, 161, 102);\n\t\t_btnNotes = new TextButton(116, 25, 44, 128);\n\t\t_btnMusic = new TextButton(116, 25, 161, 128);\n\t\t_btnKillAll = new TextButton(116, 25, 44, 154);\n\t\t_btnOk = new TextButton(116, 25, 161, 154);\n\t}\n\telse\n\t{\n\t\t_btnTouch = new TextButton(220, 12, 50, 50);\n\t\t_btnNightVision = new TextButton(220, 12, 50, 63);\n\t\t_btnPersonalLights = new TextButton(220, 12, 50, 76);\n\t\t_btnBrightness = new TextButton(220, 12, 50, 89);\n\t\t_btnTurnDiary = new TextButton(220, 12, 50, 102);\n\t\t_btnBriefing = new TextButton(220, 12, 50, 115);\n\t\t_btnNotes = new TextButton(220, 12, 50, 128);\n\t\t_btnMusic = new TextButton(220, 12, 50, 141);\n\t\t_btnKillAll = new TextButton(220, 12, 50, 154);\n\t\t_btnOk = new TextButton(220, 12, 50, 167);\n\t}\n\n\t// Set palette\n\tsetInterface(\"oxceLinks\", false, _save);\n\n\tadd(_window, \"window\", \"oxceLinks\");\n\tadd(_txtTitle, \"text\", \"oxceLinks\");\n\tadd(_btnOk, \"button\", \"oxceLinks\");\n\n\tadd(_btnTouch, \"button\", \"oxceLinks\");\n\tadd(_btnNightVision, \"button\", \"oxceLinks\");\n\tadd(_btnPersonalLights, \"button\", \"oxceLinks\");\n\tadd(_btnBrightness, \"button\", \"oxceLinks\");\n\tadd(_btnTurnDiary, \"button\", \"oxceLinks\");\n\tadd(_btnBriefing, \"button\", \"oxceLinks\");\n\tadd(_btnNotes, \"button\", \"oxceLinks\");\n\tadd(_btnMusic, \"button\", \"oxceLinks\");\n\tadd(_btnKillAll, \"button\", \"oxceLinks\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"oxceLinks\");\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_EXTENDED_LINKS\"));\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&ExtendedBattlescapeLinksState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&ExtendedBattlescapeLinksState::btnOkClick, Options::keyCancel);\n\n\t_btnTouch->setText(tr(\"STR_TOGGLE_TOUCH_BUTTONS\"));\n\t_btnTouch->onMouseClick((ActionHandler)&ExtendedBattlescapeLinksState::btnTouchClick);\n\n\t_btnNightVision->setText(tr(\"STR_TOGGLE_NIGHT_VISION\"));\n\t_btnNightVision->onMouseClick((ActionHandler)&ExtendedBattlescapeLinksState::btnNightVisionClick);\n\n\t_btnPersonalLights->setText(tr(\"STR_TOGGLE_PERSONAL_LIGHTING\"));\n\t_btnPersonalLights->onMouseClick((ActionHandler)&ExtendedBattlescapeLinksState::btnPersonalLightsClick);\n\n\t_btnBrightness->setText(tr(\"STR_TOGGLE_BRIGHTNESS\"));\n\t_btnBrightness->onMouseClick((ActionHandler)&ExtendedBattlescapeLinksState::btnBrightnessClick);\n\n\t_btnTurnDiary->setText(tr(\"STR_HIT_LOG\"));\n\t_btnTurnDiary->onMouseClick((ActionHandler)&ExtendedBattlescapeLinksState::btnTurnDiaryClick);\n\n\t_btnBriefing->setText(tr(\"STR_BRIEFING\"));\n\t_btnBriefing->onMouseClick((ActionHandler)&ExtendedBattlescapeLinksState::btnBriefingClick);\n\n\t_btnNotes->setText(Options::oxceReplaceNotesLink ? tr(\"STR_NO_EXPERIENCE_YET\") : tr(\"STR_NOTES\"));\n\t_btnNotes->onMouseClick((ActionHandler)&ExtendedBattlescapeLinksState::btnNotesClick);\n\n\t_btnMusic->setText(tr(\"STR_SELECT_MUSIC_TRACK\"));\n\t_btnMusic->onMouseClick((ActionHandler)&ExtendedBattlescapeLinksState::btnMusicClick);\n\n\tif (Options::debug)\n\t{\n\t\t_btnKillAll->setText(_save->getDebugMode() ? tr(\"STR_DEBUG_KILL_ALL_ALIENS\") : tr(\"STR_TOGGLE_DEBUG_MODE\"));\n\t}\n\telse\n\t{\n\t\t_btnKillAll->setText(tr(\"STR_MULTI_LEVEL_VIEW\"));\n\t}\n\t_btnKillAll->onMouseClick((ActionHandler)&ExtendedBattlescapeLinksState::btnKillAllClick);\n\n\tapplyBattlescapeTheme(\"oxceLinks\");\n}\n\nvoid ExtendedBattlescapeLinksState::btnTouchClick(Action *)\n{\n\t_game->popState();\n\t_parent->toggleTouchButtons(false, false);\n}\n\nvoid ExtendedBattlescapeLinksState::btnNightVisionClick(Action *)\n{\n\t_game->popState();\n\t_parent->btnNightVisionClick(nullptr);\n}\n\nvoid ExtendedBattlescapeLinksState::btnPersonalLightsClick(Action *)\n{\n\t_game->popState();\n\t_parent->btnPersonalLightingClick(nullptr);\n}\n\nvoid ExtendedBattlescapeLinksState::btnBrightnessClick(Action *)\n{\n\t_game->popState();\n\t_parent->getMap()->toggleDebugVisionMode();\n}\n\nvoid ExtendedBattlescapeLinksState::btnTurnDiaryClick(Action *)\n{\n\t_game->popState();\n\tif (Options::oxceDisableHitLog)\n\t{\n\t\t_game->pushState(new InfoboxState(tr(\"STR_THIS_FEATURE_IS_DISABLED_4\")));\n\t}\n\telse\n\t{\n\t\t// turn diary\n\t\t_game->pushState(new TurnDiaryState(_save->getHitLog()));\n\t}\n}\n\nvoid ExtendedBattlescapeLinksState::btnBriefingClick(Action *)\n{\n\t_game->popState();\n\t_game->pushState(new BriefingState(0, 0, true));\n}\n\nvoid ExtendedBattlescapeLinksState::btnNotesClick(Action *)\n{\n\t_game->popState();\n\n\tif (Options::oxceReplaceNotesLink)\n\t\t_game->pushState(new NoExperienceState());\n\telse\n\t\t_game->pushState(new NotesState(OPT_BATTLESCAPE));\n}\n\nvoid ExtendedBattlescapeLinksState::btnMusicClick(Action *)\n{\n\t_game->popState();\n\t_parent->btnSelectMusicTrackClick(nullptr);\n}\n\nvoid ExtendedBattlescapeLinksState::btnKillAllClick(Action *)\n{\n\t_game->popState();\n\n\tif (!Options::debug)\n\t{\n\t\t_parent->btnShowLayersClickOrig(nullptr);\n\t\treturn;\n\t}\n\n\tif (_save->getDebugMode())\n\t{\n\t\t// kill all\n\t\t_parent->debug(\"Influenza bacterium dispersed\");\n\t\tfor (auto* unit : *_save->getUnits())\n\t\t{\n\t\t\tif (unit->getOriginalFaction() == FACTION_HOSTILE && !unit->isOut())\n\t\t\t{\n\t\t\t\tunit->damage(Position(0, 0, 0), 1000, _game->getMod()->getDamageType(DT_MELEE), _save, { });\n\t\t\t}\n\t\t}\n\t\t_save->getBattleGame()->checkForCasualties(nullptr, BattleActionAttack{}, true, false);\n\t\t_save->getBattleGame()->handleState();\n\t}\n\telse\n\t{\n\t\t// enable debug mode\n\t\t_save->setDebugMode();\n\t\t_parent->debug(\"Debug Mode\");\n\t}\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid ExtendedBattlescapeLinksState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/ExtendedBattlescapeLinksState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2021 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass BattlescapeState;\nclass SavedBattleGame;\n\n/**\n * A screen with links to the OXCE battlescape functionality.\n */\nclass ExtendedBattlescapeLinksState : public State\n{\nprivate:\n\tTextButton *_btnOk;\n\tTextButton *_btnTouch, *_btnNightVision, *_btnPersonalLights, *_btnBrightness, *_btnTurnDiary, *_btnBriefing, *_btnNotes, *_btnMusic;\n\tTextButton *_btnKillAll;\n\tWindow *_window;\n\tText *_txtTitle;\n\tBattlescapeState *_parent;\n\tSavedBattleGame* _save;\npublic:\n\t/// Creates the ExtendedBattlescapeLinks state.\n\tExtendedBattlescapeLinksState(BattlescapeState* parent, SavedBattleGame* save);\n\t/// Cleans up the ExtendedBattlescapeLinks state.\n\t~ExtendedBattlescapeLinksState() = default;\n\t/// Handlers for clicking the buttons.\n\tvoid btnTouchClick(Action* action);\n\tvoid btnNightVisionClick(Action* action);\n\tvoid btnPersonalLightsClick(Action* action);\n\tvoid btnBrightnessClick(Action* action);\n\tvoid btnTurnDiaryClick(Action* action);\n\tvoid btnBriefingClick(Action* action);\n\tvoid btnNotesClick(Action* action);\n\tvoid btnMusicClick(Action* action);\n\tvoid btnKillAllClick(Action* action);\n\tvoid btnOkClick(Action* action);\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/ExtendedInventoryLinksState.cpp",
    "content": "/*\n * Copyright 2010-2021 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"ExtendedInventoryLinksState.h\"\n#include \"InventoryState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Menu/NotesState.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the ExtendedInventoryLinksState screen.\n */\nExtendedInventoryLinksState::ExtendedInventoryLinksState(InventoryState* parent, SavedBattleGame* save, bool inBase, bool beforeMission) : _parent(parent), _save(save)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 256, inBase ? 180 : 180-14, 32, inBase ? 10 : 10+14, POPUP_BOTH);\n\t_txtTitle = new Text(220, 17, 50, inBase ? 33 : 33+23);\n\tif (Options::oxceFatFingerLinks)\n\t{\n\t\t_btnArmor = new TextButton(116, 25, 44, 50);\n\t\t_btnAvatar = new TextButton(116, 25, 161, 50);\n\t\t_btnEquipmentSave = new TextButton(116, 25, 44, 76);\n\t\t_btnEquipmentLoad = new TextButton(116, 25, 161, 76);\n\t\t_btnPersonalSave = new TextButton(116, 25, 44, 102);\n\t\t_btnPersonalLoad = new TextButton(116, 25, 161, 102);\n\t\t_btnNotes = new TextButton(116, 25, 44, 128);\n\t\t_btnUfopedia = new TextButton(116, 25, 161, 128);\n\t\t_btnAutoEquip = new TextButton(116, 25, 44, 154);\n\t\t_btnOk = new TextButton(116, 25, 161, 154);\n\t}\n\telse\n\t{\n\t\t_btnArmor = new TextButton(220, 12, 50, 50);\n\t\t_btnAvatar = new TextButton(220, 12, 50, 63);\n\t\t_btnEquipmentSave = new TextButton(220, 12, 50, 76);\n\t\t_btnEquipmentLoad = new TextButton(220, 12, 50, 89);\n\t\t_btnPersonalSave = new TextButton(220, 12, 50, 102);\n\t\t_btnPersonalLoad = new TextButton(220, 12, 50, 115);\n\t\t_btnNotes = new TextButton(220, 12, 50, 128);\n\t\t_btnUfopedia = new TextButton(220, 12, 50, 141);\n\t\t_btnAutoEquip = new TextButton(220, 12, 50, 154);\n\t\t_btnOk = new TextButton(220, 12, 50, 167);\n\t}\n\n\t// Set palette\n\tsetInterface(\"oxceLinks\", false, _save);\n\n\tadd(_window, \"window\", \"oxceLinks\");\n\tadd(_txtTitle, \"text\", \"oxceLinks\");\n\tadd(_btnOk, \"button\", \"oxceLinks\");\n\n\tadd(_btnArmor, \"button\", \"oxceLinks\");\n\tadd(_btnAvatar, \"button\", \"oxceLinks\");\n\tadd(_btnEquipmentSave, \"button\", \"oxceLinks\");\n\tadd(_btnEquipmentLoad, \"button\", \"oxceLinks\");\n\tadd(_btnPersonalSave, \"button\", \"oxceLinks\");\n\tadd(_btnPersonalLoad, \"button\", \"oxceLinks\");\n\tadd(_btnNotes, \"button\", \"oxceLinks\");\n\tadd(_btnUfopedia, \"button\", \"oxceLinks\");\n\tadd(_btnAutoEquip, \"button\", \"oxceLinks\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"oxceLinks\");\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_EXTENDED_LINKS\"));\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&ExtendedInventoryLinksState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&ExtendedInventoryLinksState::btnOkClick, Options::keyCancel);\n\n\t_btnArmor->setText(tr(\"STR_INVENTORY_ARMOR\"));\n\t_btnArmor->onMouseClick((ActionHandler)&ExtendedInventoryLinksState::btnArmorClick);\n\t_btnArmor->setVisible(inBase);\n\n\t_btnAvatar->setText(tr(\"STR_INVENTORY_AVATAR\"));\n\t_btnAvatar->onMouseClick((ActionHandler)&ExtendedInventoryLinksState::btnAvatarClick);\n\t_btnAvatar->setVisible(inBase);\n\n\t_btnEquipmentSave->setText(tr(\"STR_SAVE_EQUIPMENT_TEMPLATE\"));\n\t_btnEquipmentSave->onMouseClick((ActionHandler)&ExtendedInventoryLinksState::btnEquipmentSaveClick);\n\t_btnEquipmentSave->setVisible(beforeMission);\n\n\t_btnEquipmentLoad->setText(tr(\"STR_LOAD_EQUIPMENT_TEMPLATE\"));\n\t_btnEquipmentLoad->onMouseClick((ActionHandler)&ExtendedInventoryLinksState::btnEquipmentLoadClick);\n\t_btnEquipmentLoad->setVisible(beforeMission);\n\n\t_btnPersonalSave->setText(tr(\"STR_SAVE_PERSONAL_EQUIPMENT\"));\n\t_btnPersonalSave->onMouseClick((ActionHandler)&ExtendedInventoryLinksState::btnPersonalSaveClick);\n\t_btnPersonalSave->setVisible(beforeMission);\n\n\t_btnPersonalLoad->setText(tr(\"STR_LOAD_PERSONAL_EQUIPMENT\"));\n\t_btnPersonalLoad->onMouseClick((ActionHandler)&ExtendedInventoryLinksState::btnPersonalLoadClick);\n\t_btnPersonalLoad->setVisible(beforeMission);\n\n\t_btnNotes->setText(tr(\"STR_NOTES\"));\n\t_btnNotes->onMouseClick((ActionHandler)&ExtendedInventoryLinksState::btnNotesClick);\n\n\t_btnUfopedia->setText(tr(\"STR_UFOPAEDIA\"));\n\t_btnUfopedia->onMouseClick((ActionHandler)&ExtendedInventoryLinksState::btnUfopediaClick);\n\n\t_btnAutoEquip->setText(tr(\"STR_AUTO_EQUIP\"));\n\t_btnAutoEquip->onMouseClick((ActionHandler)&ExtendedInventoryLinksState::btnAutoEquipClick);\n\t_btnAutoEquip->setVisible(beforeMission);\n\n\tapplyBattlescapeTheme(\"oxceLinks\");\n}\n\nvoid ExtendedInventoryLinksState::btnArmorClick(Action *)\n{\n\t_game->popState();\n\t_parent->btnArmorClick(nullptr);\n}\n\nvoid ExtendedInventoryLinksState::btnAvatarClick(Action *)\n{\n\t_game->popState();\n\t_parent->btnArmorClickRight(nullptr);\n}\n\nvoid ExtendedInventoryLinksState::btnEquipmentSaveClick(Action *)\n{\n\t_game->popState();\n\t_parent->btnInventorySaveClick(nullptr);\n}\n\nvoid ExtendedInventoryLinksState::btnEquipmentLoadClick(Action *)\n{\n\t_game->popState();\n\t_parent->btnInventoryLoadClick(nullptr);\n}\n\nvoid ExtendedInventoryLinksState::btnPersonalSaveClick(Action *)\n{\n\t_game->popState();\n\t_parent->btnCreatePersonalTemplateClick(nullptr);\n}\n\nvoid ExtendedInventoryLinksState::btnPersonalLoadClick(Action *)\n{\n\t_game->popState();\n\t_parent->btnApplyPersonalTemplateClick(nullptr);\n}\n\nvoid ExtendedInventoryLinksState::btnNotesClick(Action *)\n{\n\t_game->popState();\n\t_game->pushState(new NotesState(OPT_BATTLESCAPE));\n}\n\nvoid ExtendedInventoryLinksState::btnUfopediaClick(Action *)\n{\n\t_game->popState();\n\t_parent->btnUfopaediaClick(nullptr);\n}\n\nvoid ExtendedInventoryLinksState::btnAutoEquipClick(Action *)\n{\n\t_game->popState();\n\t_parent->onAutoequip(nullptr);\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid ExtendedInventoryLinksState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/ExtendedInventoryLinksState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2021 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass InventoryState;\nclass SavedBattleGame;\n\n/**\n * A screen with links to the OXCE inventory functionality.\n */\nclass ExtendedInventoryLinksState : public State\n{\nprivate:\n\tTextButton *_btnOk;\n\tTextButton *_btnArmor, *_btnAvatar, *_btnEquipmentSave, *_btnEquipmentLoad, *_btnPersonalSave, *_btnPersonalLoad, *_btnNotes, *_btnUfopedia, *_btnAutoEquip;\n\tWindow *_window;\n\tText *_txtTitle;\n\tInventoryState *_parent;\n\tSavedBattleGame* _save;\npublic:\n\t/// Creates the ExtendedInventoryLinks state.\n\tExtendedInventoryLinksState(InventoryState* parent, SavedBattleGame* save, bool inBase, bool beforeMission);\n\t/// Cleans up the ExtendedInventoryLinks state.\n\t~ExtendedInventoryLinksState() = default;\n\t/// Handlers for clicking the buttons.\n\tvoid btnArmorClick(Action* action);\n\tvoid btnAvatarClick(Action* action);\n\tvoid btnEquipmentSaveClick(Action* action);\n\tvoid btnEquipmentLoadClick(Action* action);\n\tvoid btnPersonalSaveClick(Action* action);\n\tvoid btnPersonalLoadClick(Action* action);\n\tvoid btnNotesClick(Action* action);\n\tvoid btnUfopediaClick(Action* action);\n\tvoid btnAutoEquipClick(Action* action);\n\tvoid btnOkClick(Action* action);\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/InfoboxOKState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"InfoboxOKState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Frame.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/Cursor.h\"\n#include \"../Engine/Options.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements.\n * @param game Pointer to the core game.\n * @param msg Message string.\n */\nInfoboxOKState::InfoboxOKState(const std::string &msg)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_frame = new Frame(261, 89, 30, 48);\n\t_btnOk = new TextButton(120, 18, 100, 112);\n\t_txtTitle = new Text(255, 61, 33, 51);\n\n\t// Set palette\n\t_game->getSavedGame()->getSavedBattle()->setPaletteByDepth(this);\n\n\tadd(_frame, \"infoBoxOK\", \"battlescape\");\n\tadd(_btnOk, \"infoBoxOKButton\", \"battlescape\");\n\tadd(_txtTitle, \"infoBoxOK\", \"battlescape\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\t_frame->setThickness(3);\n\t_frame->setHighContrast(true);\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&InfoboxOKState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&InfoboxOKState::btnOkClick, Options::keyOk);\n\t_btnOk->onKeyboardPress((ActionHandler)&InfoboxOKState::btnOkClick, Options::keyCancel);\n\t_btnOk->setHighContrast(true);\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setVerticalAlign(ALIGN_MIDDLE);\n\t_txtTitle->setHighContrast(true);\n\t_txtTitle->setWordWrap(true);\n\t_txtTitle->setText(msg);\n\n\t_game->getCursor()->setVisible(true);\n}\n\n/**\n *\n */\nInfoboxOKState::~InfoboxOKState()\n{\n\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid InfoboxOKState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/InfoboxOKState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include <string>\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Frame;\nclass Text;\n\n/**\n * Notifies the player about things like soldiers going unconscious or dying from wounds.\n */\nclass InfoboxOKState : public State\n{\nprivate:\n\tTextButton *_btnOk;\n\tFrame *_frame;\n\tText *_txtTitle;\npublic:\n\t/// Creates the InfoboxOKState.\n\tInfoboxOKState(const std::string &msg);\n\t/// Cleans up the InfoboxOKState.\n\t~InfoboxOKState();\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/InfoboxState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"InfoboxState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Timer.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/Frame.h\"\n#include \"../Engine/Action.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements.\n * @param game Pointer to the core game.\n * @param msg Message string.\n */\nInfoboxState::InfoboxState(const std::string &msg)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_frame = new Frame(261, 122, 34, 10);\n\t_text = new Text(251, 112, 39, 15);\n\n\t// Set palette\n\t_game->getSavedGame()->getSavedBattle()->setPaletteByDepth(this);\n\n\tadd(_frame, \"infoBox\", \"battlescape\");\n\tadd(_text, \"infoBoxText\", \"battlescape\");\n\n\tcenterAllSurfaces();\n\n\t_frame->setHighContrast(true);\n\t_frame->setThickness(9);\n\n\t_text->setAlign(ALIGN_CENTER);\n\t_text->setVerticalAlign(ALIGN_MIDDLE);\n\t_text->setBig();\n\t_text->setWordWrap(true);\n\t_text->setText(msg);\n\t_text->setHighContrast(true);\n\n\tint delay = INFOBOX_DELAY;\n\tif (msg.empty())\n\t{\n\t\tdelay = 500;\n\t\t_frame->setVisible(false);\n\t\t_text->setVisible(false);\n\t}\n\n\t_timer = new Timer(delay);\n\t_timer->onTimer((StateHandler)&InfoboxState::close);\n\t_timer->start();\n}\n\n/**\n *\n */\nInfoboxState::~InfoboxState()\n{\n\tdelete _timer;\n}\n\n/**\n * Closes the window.\n * @param action Pointer to an action.\n */\nvoid InfoboxState::handle(Action *action)\n{\n\tState::handle(action);\n\n\tif (action->getDetails()->type == SDL_KEYDOWN || action->getDetails()->type == SDL_MOUSEBUTTONDOWN)\n\t{\n\t\tclose();\n\t}\n}\n\n/**\n * Keeps the animation timers running.\n */\nvoid InfoboxState::think()\n{\n\t_timer->think(this, 0);\n}\n\n/**\n * Closes the window.\n */\nvoid InfoboxState::close()\n{\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/InfoboxState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http:///www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass Text;\nclass Timer;\nclass Frame;\n\n/**\n * Frame that briefly shows some info like : Yasuaki Okamoto Has Panicked. It disappears after 2 seconds.\n */\nclass InfoboxState : public State\n{\nprivate:\n\tText *_text;\n\tFrame *_frame;\n\tTimer *_timer;\npublic:\n\tstatic const int INFOBOX_DELAY = 2000;\n\t/// Creates the Infobox state.\n\tInfoboxState(const std::string &msg);\n\t/// Cleans up the Infobox state.\n\t~InfoboxState();\n\t/// Handler for clicking anything.\n\tvoid handle(Action *action) override;\n\t/// Handles the timers.\n\tvoid think() override;\n\t/// Closes the window.\n\tvoid close();\n\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/Inventory.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Inventory.h\"\n#include <algorithm>\n#include <cmath>\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleInventory.h\"\n#include \"../Mod/RuleInterface.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Timer.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/NumberText.h\"\n#include \"../Engine/Font.h\"\n#include \"../Engine/Language.h\"\n#include \"../Engine/Options.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"../Mod/RuleEnviroEffects.h\"\n#include \"../Engine/SurfaceSet.h\"\n#include \"../Savegame/BattleItem.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"../Mod/RuleItemCategory.h\"\n#include \"../Savegame/BattleUnit.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Sound.h\"\n#include \"../Engine/Script.h\"\n#include \"WarningMessage.h\"\n#include \"../Savegame/Tile.h\"\n#include \"PrimeGrenadeState.h\"\n#include \"../Ufopaedia/Ufopaedia.h\"\n#include <unordered_map>\n#include \"../Engine/Screen.h\"\n#include \"../Engine/CrossPlatform.h\"\n#include \"TileEngine.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Sets up an inventory with the specified size and position.\n * @param game Pointer to core game.\n * @param width Width in pixels.\n * @param height Height in pixels.\n * @param x X position in pixels.\n * @param y Y position in pixels.\n * @param base Is the inventory being called from the basescape?\n */\nInventory::Inventory(Game *game, int width, int height, int x, int y, bool base) : InteractiveSurface(width, height, x, y), _game(game), _selUnit(0), _selItem(0), _tu(true), _base(base), _mouseOverItem(0), _groundOffset(0), _animFrame(0)\n{\n\t_twoHandedRed = _game->getMod()->getInterface(\"battlescape\")->getElement(\"twoHandedRed\")->color;\n\t_twoHandedGreen = _game->getMod()->getInterface(\"battlescape\")->getElement(\"twoHandedGreen\")->color;\n\n\t_depth = _game->getSavedGame()->getSavedBattle()->getDepth();\n\t_grid = new Surface(width, height, 0, 0);\n\t_items = new Surface(width, height, 0, 0);\n\t_gridLabels = new Surface(width, height, 0, 0);\n\t_selection = new Surface(RuleInventory::HAND_W * RuleInventory::SLOT_W, RuleInventory::HAND_H * RuleInventory::SLOT_H, x, y);\n\t_warning = new WarningMessage(224, 24, 48, 176);\n\t_stackNumber = new NumberText(15, 15, 0, 0);\n\t_stackNumber->setBordered(true);\n\n\t_warning->initText(_game->getMod()->getFont(\"FONT_BIG\"), _game->getMod()->getFont(\"FONT_SMALL\"), _game->getLanguage());\n\t_warning->setColor(_game->getMod()->getInterface(\"battlescape\")->getElement(\"warning\")->color2);\n\t_warning->setTextColor(_game->getMod()->getInterface(\"battlescape\")->getElement(\"warning\")->color);\n\n\t_animTimer = new Timer(100);\n\t_animTimer->onTimer((SurfaceHandler)&Inventory::animate);\n\t_animTimer->start();\n\n\t_stunIndicator = _game->getMod()->getSurface(\"BigStunIndicator\", false);\n\t_woundIndicator = _game->getMod()->getSurface(\"BigWoundIndicator\", false);\n\t_burnIndicator = _game->getMod()->getSurface(\"BigBurnIndicator\", false);\n\t_shockIndicator = _game->getMod()->getSurface(\"BigShockIndicator\", false);\n\n\tconst SavedBattleGame *battleSave = _game->getSavedGame()->getSavedBattle();\n\tif (battleSave)\n\t{\n\t\tauto* enviro = battleSave->getEnviroEffects();\n\t\tif (enviro)\n\t\t{\n\t\t\tif (!enviro->getInventoryShockIndicator().empty())\n\t\t\t{\n\t\t\t\t_shockIndicator = _game->getMod()->getSurface(enviro->getInventoryShockIndicator(), false);\n\t\t\t}\n\t\t}\n\t}\n\n\t_inventorySlotRightHand = _game->getMod()->getInventoryRightHand();\n\t_inventorySlotLeftHand = _game->getMod()->getInventoryLeftHand();\n\t_inventorySlotBackPack = _game->getMod()->getInventoryBackpack();\n\t_inventorySlotBelt = _game->getMod()->getInventoryBelt();\n\t_inventorySlotGround = _game->getMod()->getInventoryGround();\n\n\t_groundSlotsX = (Screen::ORIGINAL_WIDTH - _inventorySlotGround->getX()) / RuleInventory::SLOT_W;\n\t_groundSlotsY = (Screen::ORIGINAL_HEIGHT - _inventorySlotGround->getY()) / RuleInventory::SLOT_H;\n\t_xMax = 0;\n\t_occupiedSlotsCache.resize(_groundSlotsY, std::vector<char>(_groundSlotsX * 2, false));\n}\n\n/**\n * Deletes inventory surfaces.\n */\nInventory::~Inventory()\n{\n\tdelete _grid;\n\tdelete _items;\n\tdelete _gridLabels;\n\tdelete _selection;\n\tdelete _warning;\n\tdelete _stackNumber;\n\tdelete _animTimer;\n}\n\n/**\n * Replaces a certain amount of colors in the inventory's palette.\n * @param colors Pointer to the set of colors.\n * @param firstcolor Offset of the first color to replace.\n * @param ncolors Amount of colors to replace.\n */\nvoid Inventory::setPalette(const SDL_Color *colors, int firstcolor, int ncolors)\n{\n\tSurface::setPalette(colors, firstcolor, ncolors);\n\t_grid->setPalette(colors, firstcolor, ncolors);\n\t_items->setPalette(colors, firstcolor, ncolors);\n\t_gridLabels->setPalette(colors, firstcolor, ncolors);\n\t_selection->setPalette(colors, firstcolor, ncolors);\n\t_warning->setPalette(colors, firstcolor, ncolors);\n\t_stackNumber->setPalette(getPalette());\n}\n\n/**\n * Changes the inventory's Time Units mode.\n * When True, inventory actions cost soldier time units (for battle).\n * When False, inventory actions don't cost anything (for pre-equip).\n * @param tu Time Units mode.\n */\nvoid Inventory::setTuMode(bool tu)\n{\n\t_tu = tu;\n}\n\n/**\n * Returns the currently selected (i.e. displayed) unit.\n * @return Pointer to selected unit, or 0 if none.\n */\nBattleUnit *Inventory::getSelectedUnit() const\n{\n\treturn _selUnit;\n}\n\n/**\n * Changes the unit to display the inventory of.\n * @param unit Pointer to battle unit.\n */\nvoid Inventory::setSelectedUnit(BattleUnit *unit, bool resetGroundOffset)\n{\n\t_selUnit = unit;\n\tif (resetGroundOffset)\n\t{\n\t\t_groundOffset = 9999;\n\t\tarrangeGround(1);\n\t}\n}\n\n/**\n * Draws the inventory elements.\n */\nvoid Inventory::draw()\n{\n\tdrawGrid();\n\tdrawItems();\n}\n\n/**\n * Draws the inventory grid for item placement.\n */\nvoid Inventory::drawGrid()\n{\n\t_grid->clear();\n\tRuleInterface *rule = _game->getMod()->getInterface(\"inventory\");\n\tUint8 color = rule->getElement(\"grid\")->color;\n\n\tfor (const auto& invPair : *_game->getMod()->getInventories())\n\t{\n\t\tRuleInventory* ruleInv = invPair.second;\n\n\t\t// Draw grid\n\t\tif (ruleInv->getType() == INV_SLOT)\n\t\t{\n\t\t\tfor (const auto& slotInfo : *ruleInv->getSlots())\n\t\t\t{\n\t\t\t\tSDL_Rect r;\n\t\t\t\tr.x = ruleInv->getX() + RuleInventory::SLOT_W * slotInfo.x;\n\t\t\t\tr.y = ruleInv->getY() + RuleInventory::SLOT_H * slotInfo.y;\n\t\t\t\tr.w = RuleInventory::SLOT_W + 1;\n\t\t\t\tr.h = RuleInventory::SLOT_H + 1;\n\t\t\t\t_grid->drawRect(&r, color);\n\t\t\t\tr.x++;\n\t\t\t\tr.y++;\n\t\t\t\tr.w -= 2;\n\t\t\t\tr.h -= 2;\n\t\t\t\t_grid->drawRect(&r, 0);\n\t\t\t}\n\t\t}\n\t\telse if (ruleInv->getType() == INV_HAND)\n\t\t{\n\t\t\tSDL_Rect r;\n\t\t\tr.x = ruleInv->getX();\n\t\t\tr.y = ruleInv->getY();\n\t\t\tr.w = RuleInventory::HAND_W * RuleInventory::SLOT_W;\n\t\t\tr.h = RuleInventory::HAND_H * RuleInventory::SLOT_H;\n\t\t\t_grid->drawRect(&r, color);\n\t\t\tr.x++;\n\t\t\tr.y++;\n\t\t\tr.w -= 2;\n\t\t\tr.h -= 2;\n\t\t\t_grid->drawRect(&r, 0);\n\t\t}\n\t\telse if (ruleInv->getType() == INV_GROUND)\n\t\t{\n\t\t\tfor (int x = ruleInv->getX(); x <= 320; x += RuleInventory::SLOT_W)\n\t\t\t{\n\t\t\t\tfor (int y = ruleInv->getY(); y <= 200; y += RuleInventory::SLOT_H)\n\t\t\t\t{\n\t\t\t\t\tSDL_Rect r;\n\t\t\t\t\tr.x = x;\n\t\t\t\t\tr.y = y;\n\t\t\t\t\tr.w = RuleInventory::SLOT_W + 1;\n\t\t\t\t\tr.h = RuleInventory::SLOT_H + 1;\n\t\t\t\t\t_grid->drawRect(&r, color);\n\t\t\t\t\tr.x++;\n\t\t\t\t\tr.y++;\n\t\t\t\t\tr.w -= 2;\n\t\t\t\t\tr.h -= 2;\n\t\t\t\t\t_grid->drawRect(&r, 0);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tdrawGridLabels();\n}\n\n/**\n * Draws the inventory grid labels.\n */\nvoid Inventory::drawGridLabels(bool showTuCost)\n{\n\t_gridLabels->clear();\n\n\tText text = Text(90, 9, 0, 0);\n\ttext.setPalette(_gridLabels->getPalette());\n\ttext.initText(_game->getMod()->getFont(\"FONT_BIG\"), _game->getMod()->getFont(\"FONT_SMALL\"), _game->getLanguage());\n\n\tRuleInterface *rule = _game->getMod()->getInterface(\"inventory\");\n\n\ttext.setColor(rule->getElement(\"textSlots\")->color);\n\ttext.setHighContrast(true);\n\n\t// Note: iterating over the (sorted) invs vector instead of invs map, because we want to consider listOrder here\n\tfor (auto& invName : _game->getMod()->getInvsList())\n\t{\n\t\tauto* i = _game->getMod()->getInventory(invName, true);\n\t\t// Draw label\n\t\ttext.setX(i->getX());\n\t\ttext.setY(i->getY() - text.getFont()->getHeight() - text.getFont()->getSpacing());\n\t\tif (showTuCost && _selItem != 0 && _selItem->getSlot() != i)\n\t\t{\n\t\t\tstd::ostringstream ss;\n\t\t\tss << _game->getLanguage()->getString(i->getId()).arg(1 + _groundOffset / _groundSlotsX).arg(1 + _xMax / _groundSlotsX);\n\t\t\tss << \":\";\n\t\t\tss << _selItem->getMoveToCost(i);\n\t\t\ttext.setText(ss.str().c_str());\n\t\t}\n\t\telse\n\t\t{\n\t\t\ttext.setText(_game->getLanguage()->getString(i->getId()).arg(1 + _groundOffset / _groundSlotsX).arg(1 + _xMax / _groundSlotsX));\n\t\t}\n\t\ttext.blit(_gridLabels->getSurface());\n\t}\n}\n\n/**\n * Draws the items contained in the soldier's inventory.\n */\nvoid Inventory::drawItems()\n{\n\tconst int Pulsate[8] = { 0, 1, 2, 3, 4, 3, 2, 1 };\n\tconst SavedBattleGame* save = _game->getSavedGame()->getSavedBattle();\n\tSurface *tempSurface = _game->getMod()->getSurfaceSet(\"SCANG.DAT\")->getFrame(6);\n\tauto primers = [&](int x, int y, bool a)\n\t{\n\t\ttempSurface->blitNShade(_items, x, y, Pulsate[_animFrame % 8], false, a ? 0 : 32);\n\t};\n\tauto indicators = [&](Surface *surf, int x, int y)\n\t{\n\t\tsurf->blitNShade(_items, x, y, Pulsate[_animFrame % 8]);\n\t};\n\n\tScriptWorkerBlit work;\n\t_items->clear();\n\tUint8 color = _game->getMod()->getInterface(\"inventory\")->getElement(\"numStack\")->color;\n\tUint8 color2 = _game->getMod()->getInterface(\"inventory\")->getElement(\"numStack\")->color2;\n\tif (_selUnit != 0)\n\t{\n\t\tSurfaceSet *texture = _game->getMod()->getSurfaceSet(\"BIGOBS.PCK\");\n\t\t// Soldier items\n\t\tfor (auto* invItem : *_selUnit->getInventory())\n\t\t{\n\t\t\tconst Surface *frame = invItem->getBigSprite(texture, save, _animFrame);\n\n\t\t\tif (invItem == _selItem || !frame)\n\t\t\t\tcontinue;\n\n\t\t\tint x, y;\n\t\t\tif (invItem->getSlot()->getType() == INV_SLOT)\n\t\t\t{\n\t\t\t\tx = (invItem->getSlot()->getX() + invItem->getSlotX() * RuleInventory::SLOT_W);\n\t\t\t\ty = (invItem->getSlot()->getY() + invItem->getSlotY() * RuleInventory::SLOT_H);\n\t\t\t}\n\t\t\telse if (invItem->getSlot()->getType() == INV_HAND)\n\t\t\t{\n\t\t\t\tx = (invItem->getSlot()->getX() + invItem->getRules()->getHandSpriteOffX());\n\t\t\t\ty = (invItem->getSlot()->getY() + invItem->getRules()->getHandSpriteOffY());\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tBattleItem::ScriptFill(&work, invItem, save, BODYPART_ITEM_INVENTORY, _animFrame, 0);\n\t\t\twork.executeBlit(frame, _items, x, y, 0);\n\n\t\t\t// two-handed indicator\n\t\t\tif (invItem->getSlot()->getType() == INV_HAND)\n\t\t\t{\n\t\t\t\tif (invItem->getRules()->isTwoHanded() || invItem->getRules()->isBlockingBothHands())\n\t\t\t\t{\n\t\t\t\t\tNumberText text = NumberText(10, 5, 0, 0);\n\t\t\t\t\ttext.setPalette(getPalette());\n\t\t\t\t\ttext.setColor(invItem->getRules()->isBlockingBothHands() ? _twoHandedRed : _twoHandedGreen);\n\t\t\t\t\ttext.setBordered(false);\n\t\t\t\t\ttext.setX(invItem->getSlot()->getX() + RuleInventory::HAND_W * RuleInventory::SLOT_W - 5);\n\t\t\t\t\ttext.setY(invItem->getSlot()->getY() + RuleInventory::HAND_H * RuleInventory::SLOT_H - 7);\n\t\t\t\t\ttext.setValue(2);\n\t\t\t\t\ttext.blit(_items->getSurface());\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// grenade primer indicators\n\t\t\tif (invItem->getFuseTimer() >= 0 && invItem->getRules()->getInventoryWidth() > 0)\n\t\t\t{\n\t\t\t\tprimers(x, y, invItem->isFuseEnabled());\n\t\t\t}\n\t\t}\n\n\t\tSurface stackLayer(getWidth(), getHeight(), 0, 0);\n\t\tstackLayer.setPalette(getPalette());\n\n\t\t// Ground items\n\t\tint fatalWounds = 0;\n\t\tauto& occupiedSlots = *clearOccupiedSlotsCache();\n\t\tfor (auto* groundItem : *_selUnit->getTile()->getInventory())\n\t\t{\n\t\t\tconst Surface *frame = groundItem->getBigSprite(texture, save, _animFrame);\n\t\t\t// note that you can make items invisible by setting their width or height to 0 (for example used with tank corpse items)\n\t\t\tif (groundItem == _selItem || groundItem->getRules()->getInventoryHeight() == 0 || groundItem->getRules()->getInventoryWidth() == 0 || !frame)\n\t\t\t\tcontinue;\n\n\t\t\t// check if item is in visible range\n\t\t\tif (groundItem->getSlotX() < _groundOffset || groundItem->getSlotX() >= _groundOffset + _groundSlotsX)\n\t\t\t\tcontinue;\n\n\t\t\t// check if something was draw here before\n\t\t\tauto& pos = occupiedSlots[groundItem->getSlotY()][groundItem->getSlotX() - _groundOffset];\n\t\t\tif (pos)\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tpos = true;\n\t\t\t}\n\n\t\t\tint x, y;\n\t\t\tx = (groundItem->getSlot()->getX() + (groundItem->getSlotX() - _groundOffset) * RuleInventory::SLOT_W);\n\t\t\ty = (groundItem->getSlot()->getY() + groundItem->getSlotY() * RuleInventory::SLOT_H);\n\t\t\tBattleItem::ScriptFill(&work, groundItem, save, BODYPART_ITEM_INVENTORY, _animFrame, 0);\n\t\t\twork.executeBlit(frame, _items, x, y, 0);\n\n\t\t\t// grenade primer indicators\n\t\t\tif (groundItem->getFuseTimer() >= 0 && groundItem->getRules()->getInventoryWidth() > 0)\n\t\t\t{\n\t\t\t\tprimers(x, y, groundItem->isFuseEnabled());\n\t\t\t}\n\n\t\t\t// fatal wounds\n\t\t\tfatalWounds = 0;\n\t\t\tif (groundItem->getUnit())\n\t\t\t{\n\t\t\t\t// don't show on dead units\n\t\t\t\tif (groundItem->getUnit()->getStatus() == STATUS_UNCONSCIOUS && groundItem->getUnit()->indicatorsAreEnabled())\n\t\t\t\t{\n\t\t\t\t\tfatalWounds = groundItem->getUnit()->getFatalWounds();\n\t\t\t\t\tif (_burnIndicator && groundItem->getUnit()->getFire() > 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tindicators(_burnIndicator, x, y);\n\t\t\t\t\t}\n\t\t\t\t\telse if (_woundIndicator && fatalWounds > 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tindicators(_woundIndicator, x, y);\n\t\t\t\t\t}\n\t\t\t\t\telse if (_shockIndicator && groundItem->getUnit()->hasNegativeHealthRegen())\n\t\t\t\t\t{\n\t\t\t\t\t\tindicators(_shockIndicator, x, y);\n\t\t\t\t\t}\n\t\t\t\t\telse if (_stunIndicator)\n\t\t\t\t\t{\n\t\t\t\t\t\tindicators(_stunIndicator, x, y);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (fatalWounds > 0)\n\t\t\t{\n\t\t\t\t_stackNumber->setX((groundItem->getSlot()->getX() + ((groundItem->getSlotX() + groundItem->getRules()->getInventoryWidth()) - _groundOffset) * RuleInventory::SLOT_W)-4);\n\t\t\t\tif (fatalWounds > 9)\n\t\t\t\t{\n\t\t\t\t\t_stackNumber->setX(_stackNumber->getX()-4);\n\t\t\t\t}\n\t\t\t\t_stackNumber->setY((groundItem->getSlot()->getY() + (groundItem->getSlotY() + groundItem->getRules()->getInventoryHeight()) * RuleInventory::SLOT_H)-6);\n\t\t\t\t_stackNumber->setValue(fatalWounds);\n\t\t\t\t_stackNumber->draw();\n\t\t\t\t_stackNumber->setColor(color2);\n\t\t\t\t_stackNumber->blit(stackLayer.getSurface());\n\t\t\t}\n\n\t\t\t// item stacking\n\t\t\tif (_stackLevel[groundItem->getSlotX()][groundItem->getSlotY()] > 1)\n\t\t\t{\n\t\t\t\t_stackNumber->setX((groundItem->getSlot()->getX() + ((groundItem->getSlotX() + groundItem->getRules()->getInventoryWidth()) - _groundOffset) * RuleInventory::SLOT_W)-4);\n\t\t\t\tif (_stackLevel[groundItem->getSlotX()][groundItem->getSlotY()] > 9)\n\t\t\t\t{\n\t\t\t\t\t_stackNumber->setX(_stackNumber->getX()-4);\n\t\t\t\t}\n\t\t\t\t_stackNumber->setY((groundItem->getSlot()->getY() + (groundItem->getSlotY() + groundItem->getRules()->getInventoryHeight()) * RuleInventory::SLOT_H)-6);\n\t\t\t\t_stackNumber->setValue(_stackLevel[groundItem->getSlotX()][groundItem->getSlotY()]);\n\t\t\t\t_stackNumber->draw();\n\t\t\t\t_stackNumber->setColor(color);\n\t\t\t\t_stackNumber->blit(stackLayer.getSurface());\n\t\t\t}\n\t\t}\n\n\t\tstackLayer.blitNShade(_items, 0, 0);\n\t}\n}\n\n/**\n * Draws the selected item.\n */\nvoid Inventory::drawSelectedItem()\n{\n\tif (_selItem)\n\t{\n\t\t_selection->clear();\n\t\t_selItem->getRules()->drawHandSprite(_game->getMod()->getSurfaceSet(\"BIGOBS.PCK\"), _selection, _selItem, _game->getSavedGame()->getSavedBattle(), _animFrame);\n\t}\n}\n\n/**\n * Clear all occupied slots markers.\n */\nstd::vector<std::vector<char>>* Inventory::clearOccupiedSlotsCache()\n{\n\tfor (auto& v : _occupiedSlotsCache)\n\t{\n\t\tfor (auto& b : v)\n\t\t{\n\t\t\tb = false;\n\t\t}\n\t}\n\treturn &_occupiedSlotsCache;\n}\n\n/**\n * Moves an item to a specified slot in the\n * selected player's inventory.\n * @param item Pointer to battle item.\n * @param slot Inventory slot, or NULL if none.\n * @param x X position in slot.\n * @param y Y position in slot.\n */\nvoid Inventory::moveItem(BattleItem *item, const RuleInventory *slot, int x, int y)\n{\n\t_game->getSavedGame()->getSavedBattle()->getTileEngine()->itemMoveInventory(_selUnit->getTile(), _selUnit, item, slot, x, y);\n}\n\n/**\n * Checks if an item in a certain slot position would\n * overlap with any other inventory item.\n * @param unit Pointer to current unit.\n * @param item Pointer to battle item.\n * @param slot Inventory slot, or NULL if none.\n * @param x X position in slot.\n * @param y Y position in slot.\n * @return If there's overlap.\n */\nbool Inventory::overlapItems(BattleUnit *unit, BattleItem *item, const RuleInventory *slot, int x, int y)\n{\n\tif (slot->getType() != INV_GROUND)\n\t{\n\t\tfor (const auto* bi : *unit->getInventory())\n\t\t{\n\t\t\tif (bi->getSlot() == slot && bi->occupiesSlot(x, y, item))\n\t\t\t{\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\telse if (unit->getTile() != 0)\n\t{\n\t\tfor (const auto* bi : *unit->getTile()->getInventory())\n\t\t{\n\t\t\tif (bi->occupiesSlot(x, y, item))\n\t\t\t{\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Gets the inventory slot located in the specified mouse position.\n * @param x Mouse X position. Returns the slot's X position.\n * @param y Mouse Y position. Returns the slot's Y position.\n * @return Slot rules, or NULL if none.\n */\nRuleInventory *Inventory::getSlotInPosition(int *x, int *y) const\n{\n\tfor (const auto& pair : *_game->getMod()->getInventories())\n\t{\n\t\tif (pair.second->checkSlotInPosition(x, y))\n\t\t{\n\t\t\treturn pair.second;\n\t\t}\n\t}\n\treturn 0;\n}\n\n/**\n * Returns the item currently grabbed by the player.\n * @return Pointer to selected item, or NULL if none.\n */\nBattleItem *Inventory::getSelectedItem() const\n{\n\treturn _selItem;\n}\n\n/**\n * Changes the item currently grabbed by the player.\n * @param item Pointer to selected item, or NULL if none.\n */\nvoid Inventory::setSelectedItem(BattleItem *item)\n{\n\t_selItem = (item && !item->getRules()->isFixed()) ? item : 0;\n\tif (_selItem)\n\t{\n\t\tif (_selItem->getSlot()->getType() == INV_GROUND)\n\t\t{\n\t\t\t_stackLevel[_selItem->getSlotX()][_selItem->getSlotY()] -= 1;\n\t\t}\n\t}\n\telse\n\t{\n\t\t_selection->clear();\n\t}\n\tdrawSelectedItem();\n\tdrawItems();\n\tif (_tu)\n\t{\n\t\tdrawGridLabels(!Options::oxceDisableInventoryTuCost);\n\t}\n}\n\n/**\n* Changes the item currently grabbed by the player.\n* @param item Pointer to selected item, or NULL if none.\n*/\nvoid Inventory::setSearchString(const std::string &searchString)\n{\n\t_searchString = searchString;\n\tUnicode::upperCase(_searchString);\n\tarrangeGround(1);\n}\n\n/**\n * Returns the item currently under mouse cursor.\n * @return Pointer to selected item, or 0 if none.\n */\nBattleItem *Inventory::getMouseOverItem() const\n{\n\treturn _mouseOverItem;\n}\n\n/**\n * Changes the item currently under mouse cursor.\n * @param item Pointer to selected item, or NULL if none.\n */\nvoid Inventory::setMouseOverItem(BattleItem *item)\n{\n\t_mouseOverItem = (item && !(item->getRules()->isFixed() && item->getRules()->getBattleType() == BT_NONE)) ? item : 0;\n}\n\n/**\n * Handles timers.\n */\nvoid Inventory::think()\n{\n\t_warning->think();\n\t_animTimer->think(0,this);\n}\n\n/**\n * Blits the inventory elements.\n * @param surface Pointer to surface to blit onto.\n */\nvoid Inventory::blit(SDL_Surface *surface)\n{\n\tclear();\n\t_grid->blitNShade(this, 0, 0);\n\t_items->blitNShade(this, 0, 0);\n\t_gridLabels->blitNShade(this, 0, 0);\n\t_selection->blitNShade(this, _selection->getX(), _selection->getY());\n\t_warning->blit(this->getSurface());\n\tSurface::blit(surface);\n}\n\n/**\n * Moves the selected item.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid Inventory::mouseOver(Action *action, State *state)\n{\n\t_selection->setX((int)floor(action->getAbsoluteXMouse()) - _selection->getWidth()/2 - getX());\n\t_selection->setY((int)floor(action->getAbsoluteYMouse()) - _selection->getHeight()/2 - getY());\n\tif (_selUnit == 0)\n\t\treturn;\n\n\tint x = (int)floor(action->getAbsoluteXMouse()) - getX(),\n\t\ty = (int)floor(action->getAbsoluteYMouse()) - getY();\n\tRuleInventory *slot = getSlotInPosition(&x, &y);\n\tif (slot != 0)\n\t{\n\t\tif (slot->getType() == INV_GROUND)\n\t\t{\n\t\t\tx += _groundOffset;\n\t\t}\n\t\tBattleItem *item = _selUnit->getItem(slot, x, y);\n\t\tsetMouseOverItem(item);\n\t}\n\telse\n\t{\n\t\tsetMouseOverItem(0);\n\t}\n\n\t_selection->setX((int)floor(action->getAbsoluteXMouse()) - _selection->getWidth()/2 - getX());\n\t_selection->setY((int)floor(action->getAbsoluteYMouse()) - _selection->getHeight()/2 - getY());\n\tInteractiveSurface::mouseOver(action, state);\n}\n\n/**\n * Picks up / drops an item.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid Inventory::mouseClick(Action *action, State *state)\n{\n\tif (_game->isLeftClick(action))\n\t{\n\t\tif (_selUnit == 0)\n\t\t\treturn;\n\t\t// Pickup item\n\t\tif (_selItem == 0)\n\t\t{\n\t\t\tint x = (int)floor(action->getAbsoluteXMouse()) - getX(),\n\t\t\t\ty = (int)floor(action->getAbsoluteYMouse()) - getY();\n\t\t\tRuleInventory *slot = getSlotInPosition(&x, &y);\n\t\t\tif (slot != 0)\n\t\t\t{\n\t\t\t\tif (slot->getType() == INV_GROUND)\n\t\t\t\t{\n\t\t\t\t\tx += _groundOffset;\n\t\t\t\t}\n\t\t\t\tBattleItem *item = _selUnit->getItem(slot, x, y);\n\t\t\t\tif (item != 0)\n\t\t\t\t{\n\t\t\t\t\tif (_game->isShiftPressed())\n\t\t\t\t\t{\n\t\t\t\t\t\tbool quickUnload = false;\n\t\t\t\t\t\tbool allowed = true;\n\t\t\t\t\t\t// Quick-unload check\n\t\t\t\t\t\tif (!_tu)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// Outside of the battlescape, quick-unload:\n\t\t\t\t\t\t\t// - the weapon is never moved from its original slot\n\t\t\t\t\t\t\t// - the ammo always drops on the ground\n\t\t\t\t\t\t\tquickUnload = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (item->getSlot()->getType() != INV_HAND)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// During the battle, only weapons held in hand can be shift-unloaded\n\t\t\t\t\t\t\t\tallowed = false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (allowed)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_selItem = item; // don't worry, we'll unselect it later!\n\t\t\t\t\t\t\tif (unload(quickUnload))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t_game->getMod()->getSoundByDepth(_depth, Mod::ITEM_DROP)->play();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t_selItem = 0; // see, I told you!\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse if (item->getRules()->isFixed())\n\t\t\t\t\t{\n\t\t\t\t\t\t// do nothing!\n\t\t\t\t\t}\n\t\t\t\t\telse if (_game->isCtrlPressed())\n\t\t\t\t\t{\n\t\t\t\t\t\tconst RuleInventory* newSlot = _inventorySlotGround;\n\t\t\t\t\t\tstd::string warning = \"STR_NOT_ENOUGH_SPACE\";\n\t\t\t\t\t\tbool placed = false;\n\n\t\t\t\t\t\tif (slot->getType() == INV_GROUND)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// B1 - default slot by item\n\t\t\t\t\t\t\tif (!placed)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t_stackLevel[item->getSlotX()][item->getSlotY()] -= 1;\n\n\t\t\t\t\t\t\t\tif (item->getRules()->getDefaultInventorySlot() && item->getRules()->getDefaultInventorySlot()->getType() != INV_GROUND)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tnewSlot = item->getRules()->getDefaultInventorySlot();\n\n\t\t\t\t\t\t\t\t\tplaced = fitItem(newSlot, item, warning);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// B2 - slot order by item category\n\t\t\t\t\t\t\tif (!placed)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tauto* cat = item->getRules()->getFirstCategoryWithInvOrder(_game->getMod());\n\t\t\t\t\t\t\t\tif (cat)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tfor (const auto& s : cat->getInvOrder())\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tif (placed)\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tbreak; // loop finished\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tnewSlot = _game->getMod()->getInventory(s);\n\t\t\t\t\t\t\t\t\t\tif (newSlot->getType() == INV_GROUND)\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tplaced = fitItem(newSlot, item, warning);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// A1 - vanilla default attempt\n\t\t\t\t\t\t\tif (!placed)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// reset\n\t\t\t\t\t\t\t\t_stackLevel[item->getSlotX()][item->getSlotY()] += 1;\n\t\t\t\t\t\t\t\tnewSlot = _inventorySlotGround;\n\n\t\t\t\t\t\t\t\tswitch (item->getRules()->getBattleType())\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcase BT_FIREARM:\n\t\t\t\t\t\t\t\t\tnewSlot = _inventorySlotRightHand;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase BT_MINDPROBE:\n\t\t\t\t\t\t\t\tcase BT_PSIAMP:\n\t\t\t\t\t\t\t\tcase BT_MELEE:\n\t\t\t\t\t\t\t\tcase BT_CORPSE:\n\t\t\t\t\t\t\t\t\tnewSlot = _inventorySlotLeftHand;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\tif (item->getRules()->getInventoryHeight() > 2)\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tnewSlot = _inventorySlotBackPack;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tnewSlot = _inventorySlotBelt;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (newSlot->getType() != INV_GROUND)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// A1 - vanilla default attempt\n\t\t\t\t\t\t\tif (!placed)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t_stackLevel[item->getSlotX()][item->getSlotY()] -= 1;\n\n\t\t\t\t\t\t\t\tplaced = fitItem(newSlot, item, warning);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (!placed)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (Mod::EXTENDED_INVENTORY_SLOT_SORTING)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t// B3 - fallback: slot order by listOrder\n\t\t\t\t\t\t\t\t\tfor (const auto& s : _game->getMod()->getInvsList())\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tif (placed)\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tbreak; // loop finished\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tnewSlot = _game->getMod()->getInventory(s);\n\t\t\t\t\t\t\t\t\t\tif (newSlot->getType() == INV_GROUND)\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tplaced = fitItem(newSlot, item, warning);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t// A2 - fallback: vanilla alphabetical slot order\n\t\t\t\t\t\t\t\t\tfor (const auto& wildCard : *_game->getMod()->getInventories())\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tif (placed)\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tbreak; // loop finished\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tnewSlot = wildCard.second;\n\t\t\t\t\t\t\t\t\t\tif (newSlot->getType() == INV_GROUND)\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tplaced = fitItem(newSlot, item, warning);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (!placed)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t_stackLevel[item->getSlotX()][item->getSlotY()] += 1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (!_tu || _selUnit->spendTimeUnits(item->getMoveToCost(newSlot)))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tplaced = true;\n\t\t\t\t\t\t\t\tmoveItem(item, newSlot, 0, 0);\n\t\t\t\t\t\t\t\t_game->getMod()->getSoundByDepth(_depth, Mod::ITEM_DROP)->play();\n\t\t\t\t\t\t\t\tarrangeGround();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\twarning = \"STR_NOT_ENOUGH_TIME_UNITS\";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (!placed)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_warning->showMessage(_game->getLanguage()->getString(warning));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tsetSelectedItem(item);\n\t\t\t\t\t\tif (item->getFuseTimer() >= 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_warning->showMessage(_game->getLanguage()->getString(item->getRules()->getPrimeActionMessage()));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// Drop item\n\t\telse\n\t\t{\n\t\t\tint x = _selection->getX() + (RuleInventory::HAND_W - _selItem->getRules()->getInventoryWidth()) * RuleInventory::SLOT_W/2 + RuleInventory::SLOT_W/2,\n\t\t\t\ty = _selection->getY() + (RuleInventory::HAND_H - _selItem->getRules()->getInventoryHeight()) * RuleInventory::SLOT_H/2 + RuleInventory::SLOT_H/2;\n\t\t\tRuleInventory *slot = getSlotInPosition(&x, &y);\n\t\t\tif (slot != 0)\n\t\t\t{\n\t\t\t\tif (slot->getType() == INV_GROUND)\n\t\t\t\t{\n\t\t\t\t\tx += _groundOffset;\n\t\t\t\t}\n\t\t\t\tBattleItem *item = _selUnit->getItem(slot, x, y);\n\n\t\t\t\tbool canStack = slot->getType() == INV_GROUND && canBeStacked(item, _selItem);\n\n\t\t\t\t// Check if this inventory section supports the item\n\t\t\t\tif (!_selItem->getRules()->canBePlacedIntoInventorySection(slot))\n\t\t\t\t{\n\t\t\t\t\t_warning->showMessage(_game->getLanguage()->getString(\"STR_CANNOT_PLACE_ITEM_INTO_THIS_SECTION\"));\n\t\t\t\t}\n\t\t\t\t// Put item in empty slot, or stack it, if possible.\n\t\t\t\telse if (item == 0 || item == _selItem || canStack)\n\t\t\t\t{\n\t\t\t\t\tif (!overlapItems(_selUnit, _selItem, slot, x, y) && slot->fitItemInSlot(_selItem->getRules(), x, y))\n\t\t\t\t\t{\n\t\t\t\t\t\tif (!_tu || _selUnit->spendTimeUnits(_selItem->getMoveToCost(slot)))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tmoveItem(_selItem, slot, x, y);\n\t\t\t\t\t\t\tif (slot->getType() == INV_GROUND)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t_stackLevel[x][y] += 1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tsetSelectedItem(0);\n\t\t\t\t\t\t\t_game->getMod()->getSoundByDepth(_depth, Mod::ITEM_DROP)->play();\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_warning->showMessage(_game->getLanguage()->getString(\"STR_NOT_ENOUGH_TIME_UNITS\"));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse if (canStack)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (!_tu || _selUnit->spendTimeUnits(_selItem->getMoveToCost(slot)))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tmoveItem(_selItem, slot, item->getSlotX(), item->getSlotY());\n\t\t\t\t\t\t\t_stackLevel[item->getSlotX()][item->getSlotY()] += 1;\n\t\t\t\t\t\t\tsetSelectedItem(0);\n\t\t\t\t\t\t\t_game->getMod()->getSoundByDepth(_depth, Mod::ITEM_DROP)->play();\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_warning->showMessage(_game->getLanguage()->getString(\"STR_NOT_ENOUGH_TIME_UNITS\"));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Put item in weapon\n\t\t\t\telse if (item->isWeaponWithAmmo())\n\t\t\t\t{\n\t\t\t\t\tint slotAmmo = item->getRules()->getSlotForAmmo(_selItem->getRules());\n\t\t\t\t\tif (slotAmmo == -1)\n\t\t\t\t\t{\n\t\t\t\t\t\t_warning->showMessage(_game->getLanguage()->getString(\"STR_WRONG_AMMUNITION_FOR_THIS_WEAPON\"));\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// 4. the cost of loading the weapon with the new ammo (from the offhand)\n\t\t\t\t\t\tint tuCost = item->getRules()->getTULoad(slotAmmo);\n\n\t\t\t\t\t\tif (Mod::EXTENDED_ITEM_RELOAD_COST && _selItem->getSlot()->getType() != INV_HAND)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// 3. the cost of moving the new ammo from the current slot to the offhand\n\t\t\t\t\t\t\t// Note: the cost for left/right hand might *NOT* be the same, but using the right hand \"by definition\"\n\t\t\t\t\t\t\ttuCost += _selItem->getMoveToCost(_inventorySlotRightHand);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tBattleItem *weaponRightHand = _selUnit->getRightHandWeapon();\n\t\t\t\t\t\tBattleItem *weaponLeftHand = _selUnit->getLeftHandWeapon();\n\n\t\t\t\t\t\tauto* oldAmmoGoesTo = _inventorySlotGround;\n\t\t\t\t\t\tif (!weaponRightHand || _selItem == weaponRightHand)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\toldAmmoGoesTo = _inventorySlotRightHand;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (!weaponLeftHand || _selItem == weaponLeftHand)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\toldAmmoGoesTo = _inventorySlotLeftHand;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbool canLoad = true;\n\t\t\t\t\t\tif (item->getAmmoForSlot(slotAmmo) != 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tint tuUnload = item->getRules()->getTUUnload(slotAmmo);\n\t\t\t\t\t\t\tif (_game->isShiftPressed() && (!_tu || tuUnload))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// Quick-swap check\n\t\t\t\t\t\t\t\tif (!_tu)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t// Outside of the battlescape, the old ammo always drops on the ground\n\t\t\t\t\t\t\t\t\toldAmmoGoesTo = _inventorySlotGround;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t// During the battle, only weapons held in hand can use ammo quick-swap\n\t\t\t\t\t\t\t\t\tif (item->getSlot()->getType() != INV_HAND)\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tcanLoad = false;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// 1. the cost of unloading the old ammo (to the offhand)\n\t\t\t\t\t\t\t\ttuCost += tuUnload;\n\t\t\t\t\t\t\t\tif (oldAmmoGoesTo == _inventorySlotGround)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t// 2. the cost of dropping the old ammo on the ground (from the offhand)\n\t\t\t\t\t\t\t\t\t// Note: the cost for left/right hand is (should be) the same, so just using the right hand\n\t\t\t\t\t\t\t\t\ttuCost += _inventorySlotRightHand->getCost(_inventorySlotGround);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcanLoad = false;\n\t\t\t\t\t\t\t\t_warning->showMessage(_game->getLanguage()->getString(\"STR_WEAPON_IS_ALREADY_LOADED\"));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (canLoad)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (!_tu || _selUnit->spendTimeUnits(tuCost))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tbool arrangeFloor = false;\n\t\t\t\t\t\t\t\tauto* oldAmmo = item->setAmmoForSlot(slotAmmo, _selItem);\n\t\t\t\t\t\t\t\tif (oldAmmo)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tmoveItem(oldAmmo, oldAmmoGoesTo, 0, 0);\n\t\t\t\t\t\t\t\t\tif (oldAmmoGoesTo == _inventorySlotGround)\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tarrangeFloor = true;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tint sound = _selItem->getRules()->getReloadSound();\n\t\t\t\t\t\t\t\tif (sound == Mod::NO_SOUND)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tsound = item->getRules()->getReloadSound();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (sound == Mod::NO_SOUND)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tsound = Mod::ITEM_RELOAD;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tsetSelectedItem(0);\n\t\t\t\t\t\t\t\t_game->getMod()->getSoundByDepth(_depth, sound)->play();\n\t\t\t\t\t\t\t\tif (arrangeFloor || item->getSlot()->getType() == INV_GROUND)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tarrangeGround();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t_warning->showMessage(_game->getLanguage()->getString(\"STR_NOT_ENOUGH_TIME_UNITS\"));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// else swap the item positions?\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// try again, using the position of the mouse cursor, not the item (slightly more intuitive for stacking)\n\t\t\t\tx = (int)floor(action->getAbsoluteXMouse()) - getX();\n\t\t\t\ty = (int)floor(action->getAbsoluteYMouse()) - getY();\n\t\t\t\tslot = getSlotInPosition(&x, &y);\n\t\t\t\tif (slot != 0 && slot->getType() == INV_GROUND)\n\t\t\t\t{\n\t\t\t\t\tx += _groundOffset;\n\t\t\t\t\tBattleItem *item = _selUnit->getItem(slot, x, y);\n\t\t\t\t\tif (canBeStacked(item, _selItem))\n\t\t\t\t\t{\n\t\t\t\t\t\tif (!_tu || _selUnit->spendTimeUnits(_selItem->getMoveToCost(slot)))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tmoveItem(_selItem, slot, item->getSlotX(), item->getSlotY());\n\t\t\t\t\t\t\t_stackLevel[item->getSlotX()][item->getSlotY()] += 1;\n\t\t\t\t\t\t\tsetSelectedItem(0);\n\t\t\t\t\t\t\t_game->getMod()->getSoundByDepth(_depth, Mod::ITEM_DROP)->play();\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_warning->showMessage(_game->getLanguage()->getString(\"STR_NOT_ENOUGH_TIME_UNITS\"));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\telse if (_game->isRightClick(action))\n\t{\n\t\tif (_selItem == 0)\n\t\t{\n\t\t\tif (!_base || Options::includePrimeStateInSavedLayout)\n\t\t\t{\n\t\t\t\tif (!_tu)\n\t\t\t\t{\n\t\t\t\t\tint x = (int)floor(action->getAbsoluteXMouse()) - getX(),\n\t\t\t\t\t\ty = (int)floor(action->getAbsoluteYMouse()) - getY();\n\t\t\t\t\tRuleInventory *slot = getSlotInPosition(&x, &y);\n\t\t\t\t\tif (slot != 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (slot->getType() == INV_GROUND)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tx += _groundOffset;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tBattleItem *item = _selUnit->getItem(slot, x, y);\n\t\t\t\t\t\tif (item != 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tconst BattleFuseType fuseType = item->getRules()->getFuseTimerType();\n\t\t\t\t\t\t\tif (fuseType != BFT_NONE)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (item->getFuseTimer() == -1)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tif (item->getRules()->getCostPrime().Time > 0)\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t// Prime that grenade!\n\t\t\t\t\t\t\t\t\t\tif (fuseType == BFT_SET)\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t_game->pushState(new PrimeGrenadeState(0, true, item));\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t_warning->showMessage(_game->getLanguage()->getString(item->getRules()->getPrimeActionMessage()));\n\t\t\t\t\t\t\t\t\t\t\titem->setFuseTimer(item->getRules()->getFuseTimerDefault());\n\t\t\t\t\t\t\t\t\t\t\tarrangeGround();\n\t\t\t\t\t\t\t\t\t\t\tplaySound(item->getRules()->getPrimeSound()); // prime sound\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tif (item->getRules()->getCostUnprime().Time > 0 /* && !item->getRules()->getUnprimeActionName().empty() */ )\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t_warning->showMessage(_game->getLanguage()->getString(item->getRules()->getUnprimeActionMessage()));\n\t\t\t\t\t\t\t\t\t\titem->setFuseTimer(-1);  // Unprime the grenade\n\t\t\t\t\t\t\t\t\t\tarrangeGround();\n\t\t\t\t\t\t\t\t\t\tplaySound(item->getRules()->getUnprimeSound()); // unprime sound\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t_game->popState(); // Closes the inventory window on right-click (if not in preBattle equip screen!)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (_selItem->getSlot()->getType() == INV_GROUND)\n\t\t\t{\n\t\t\t\t_stackLevel[_selItem->getSlotX()][_selItem->getSlotY()] += 1;\n\t\t\t}\n\t\t\t// Return item to original position\n\t\t\tsetSelectedItem(0);\n\t\t}\n\t}\n\telse if (_game->isMiddleClick(action))\n\t{\n\t\tif (_selUnit == 0)\n\t\t\treturn;\n\n\t\tint x = (int)floor(action->getAbsoluteXMouse()) - getX(),\n\t\t\ty = (int)floor(action->getAbsoluteYMouse()) - getY();\n\t\tRuleInventory *slot = getSlotInPosition(&x, &y);\n\t\tif (slot != 0)\n\t\t{\n\t\t\tif (slot->getType() == INV_GROUND)\n\t\t\t{\n\t\t\t\tx += _groundOffset;\n\t\t\t}\n\t\t\tBattleItem *item = _selUnit->getItem(slot, x, y);\n\t\t\tif (item != 0)\n\t\t\t{\n\t\t\t\tstd::string articleId = item->getRules()->getUfopediaType();\n\t\t\t\tUfopaedia::openArticle(_game, articleId);\n\t\t\t}\n\t\t}\n\t}\n\tInteractiveSurface::mouseClick(action, state);\n}\n\n/**\n * Quickly drops the selected item on the ground.\n * @return The success of the item being dropped.\n */\nbool Inventory::quickDrop()\n{\n\tif (_selUnit && _selItem)\n\t{\n\t\tif (!_tu || _selUnit->spendTimeUnits(_selItem->getMoveToCost(_inventorySlotGround)))\n\t\t{\n\t\t\tmoveItem(_selItem, _inventorySlotGround, 0, 0);\n\t\t\tsetSelectedItem(0);\n\t\t\treturn true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_warning->showMessage(_game->getLanguage()->getString(\"STR_NOT_ENOUGH_TIME_UNITS\"));\n\t\t}\n\t}\n\n\treturn false;\n}\n\n/**\n * Unloads the selected weapon, placing the gun\n * on the right hand and the ammo on the left hand.\n * Or if only one hand is free, the gun is placed\n * in the hand and the ammo is placed on the ground.\n * @param quickUnload Quick unload using specific rules (the rules are different in and outside of the battlescape)\n * @return The success of the weapon being unloaded.\n */\nbool Inventory::unload(bool quickUnload)\n{\n\t// Must be holding an item\n\tif (_selItem == 0)\n\t{\n\t\t// mobile support: https://openxcom.org/forum/index.php?topic=12880.0\n\t\tif (Options::oxceInventoryUnloadFixedWeapons)\n\t\t{\n\t\t\tif (!_selUnit) return false;\n\t\t\tauto weapons = { _selUnit->getRightHandWeapon(), _selUnit->getLeftHandWeapon()};\n\t\t\tfor (auto* item : weapons)\n\t\t\t{\n\t\t\t\tif (!item) continue;\n\t\t\t\tif (!item->getRules()->isFixed()) continue;\n\t\t\t\tif (!item->haveAnyAmmo()) continue;\n\t\t\t\t{\n\t\t\t\t\t_selItem = item; // don't worry, we'll unselect it later!\n\t\t\t\t\tbool success = unload(!_tu);\n\t\t\t\t\t_selItem = 0; // see, I told you!\n\t\t\t\t\tif (success) return true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tconst BattleType type = _selItem->getRules()->getBattleType();\n\tconst bool grenade = type == BT_GRENADE || type == BT_PROXIMITYGRENADE;\n\tconst bool weapon = type == BT_FIREARM || type == BT_MELEE;\n\tint slotForAmmoUnload = -1;\n\tint toForAmmoUnload = 0;\n\n\t// Item should be able to unload or unprimed.\n\tif (grenade)\n\t{\n\t\t// Item must be primed\n\t\tif (_selItem->getFuseTimer() == -1)\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t\tif (_selItem->getRules()->getFuseTimerType() == BFT_NONE)\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t\tif (_selItem->getRules()->getCostUnprime().Time == 0 /* || _selItem->getRules()->getUnprimeActionName().empty() */ )\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\telse if (weapon)\n\t{\n\t\t// Item must be loaded\n\t\tbool showError = false;\n\t\tauto checkSlot = [&](int slot)\n\t\t{\n\t\t\tif (!_selItem->needsAmmoForSlot(slot))\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tint tu = _selItem->getRules()->getTUUnload(slot);\n\t\t\tif (tu == 0 && !_tu)\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tauto* ammo = _selItem->getAmmoForSlot(slot);\n\t\t\tif (ammo)\n\t\t\t{\n\t\t\t\ttoForAmmoUnload = tu;\n\t\t\t\tslotForAmmoUnload = slot;\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tshowError = true;\n\t\t\t\treturn false;\n\t\t\t}\n\t\t};\n\t\t// History lesson:\n\t\t// The old shift-unload logic by Yankes (i.e. unload ammo slots in reverse order) was removed from here,\n\t\t// because the new shift-unload logic by Fonzo/Ohartenstein now has a completely different meaning (i.e. quick-unload)\n\t\t{\n\t\t\tfor (int slot = 0; slot < RuleItem::AmmoSlotMax; ++slot)\n\t\t\t{\n\t\t\t\tif (checkSlot(slot))\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (slotForAmmoUnload == -1)\n\t\t{\n\t\t\tif (showError)\n\t\t\t{\n\t\t\t\t_warning->showMessage(_game->getLanguage()->getString(\"STR_NO_AMMUNITION_LOADED\"));\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\t}\n\telse\n\t{\n\t\t// not weapon or grenade, can't use unload button\n\t\treturn false;\n\t}\n\n\t// Simplified logic for quick-unload outside of the battlescape\n\tif (quickUnload && !_tu)\n\t{\n\t\t// noop(); // 1. do not move the weapon at all!\n\t\tif (grenade)\n\t\t{\n\t\t\t_selItem->setFuseTimer(-1);\n\t\t\t_warning->showMessage(_game->getLanguage()->getString(_selItem->getRules()->getUnprimeActionMessage()));\n\t\t\tplaySound(_selItem->getRules()->getUnprimeSound()); // unprime sound\n\t\t\tsetSelectedItem(0);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tauto* oldAmmo = _selItem->setAmmoForSlot(slotForAmmoUnload, nullptr);\n\t\t\tmoveItem(oldAmmo, _inventorySlotGround, 0, 0); // 2. + 3. always drop the ammo on the ground\n\t\t\tsetSelectedItem(0); // calling before arrangeGround() to prevent undesired drawing of TU costs\n\t\t\tarrangeGround();\n\t\t}\n\t\treturn true;\n\t}\n\n\t// Check which hands are free.\n\tRuleInventory *FirstFreeHand = _inventorySlotRightHand;\n\tRuleInventory *SecondFreeHand = _inventorySlotLeftHand;\n\n\tfor (auto* bi : *_selUnit->getInventory())\n\t{\n\t\tif (bi->getSlot()->getType() == INV_HAND && bi != _selItem)\n\t\t{\n\t\t\tif (bi->getSlot() == SecondFreeHand)\n\t\t\t{\n\t\t\t\tSecondFreeHand = nullptr;\n\t\t\t}\n\t\t\tif (bi->getSlot() == FirstFreeHand)\n\t\t\t{\n\t\t\t\tFirstFreeHand = nullptr;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (FirstFreeHand == nullptr)\n\t{\n\t\tFirstFreeHand = SecondFreeHand;\n\t\tSecondFreeHand = nullptr;\n\t}\n\tif (FirstFreeHand == nullptr)\n\t{\n\t\t_warning->showMessage(_game->getLanguage()->getString(\"STR_ONE_HAND_MUST_BE_EMPTY\"));\n\t\treturn false;\n\t}\n\n\tBattleActionCost cost { BA_NONE, _selUnit, _selItem };\n\tif (grenade)\n\t{\n\t\tcost.type = BA_UNPRIME;\n\t\tcost.updateTU();\n\t}\n\telse\n\t{\n\t\t// 2. unload (= move the ammo to the second free hand)\n\t\tcost.Time += toForAmmoUnload;\n\n\t\tif (SecondFreeHand == nullptr)\n\t\t{\n\t\t\t// 3. drop the ammo on the ground (if the second hand is not free)\n\t\t\tcost.Time += FirstFreeHand->getCost(_inventorySlotGround);\n\t\t}\n\t}\n\n\tif (cost.haveTU() && _selItem->getSlot()->getType() != INV_HAND)\n\t{\n\t\t// 1. move the weapon to the first free hand\n\t\tcost.Time += _selItem->getMoveToCost(FirstFreeHand);\n\t}\n\n\tstd::string err;\n\tif (!_tu || cost.spendTU(&err))\n\t{\n\t\tmoveItem(_selItem, FirstFreeHand, 0, 0); // 1.\n\t\tif (grenade)\n\t\t{\n\t\t\t_selItem->setFuseTimer(-1);\n\t\t\t_warning->showMessage(_game->getLanguage()->getString(_selItem->getRules()->getUnprimeActionMessage()));\n\t\t\tplaySound(_selItem->getRules()->getUnprimeSound()); // unprime sound\n\t\t}\n\t\telse\n\t\t{\n\t\t\tauto* oldAmmo = _selItem->setAmmoForSlot(slotForAmmoUnload, nullptr);\n\t\t\tif (SecondFreeHand != nullptr)\n\t\t\t{\n\t\t\t\tmoveItem(oldAmmo, SecondFreeHand, 0, 0); // 2.\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tmoveItem(oldAmmo, _inventorySlotGround, 0, 0); // 2. + 3.\n\t\t\t\tarrangeGround();\n\t\t\t}\n\t\t}\n\t\tsetSelectedItem(0);\n\t\treturn true;\n\t}\n\telse\n\t{\n\t\tif (!err.empty())\n\t\t{\n\t\t\t_warning->showMessage(_game->getLanguage()->getString(err));\n\t\t}\n\t\treturn false;\n\t}\n}\n\n/**\n* Checks whether the given item is visible with the current search string.\n* @param item The item to check.\n* @return True if item should be shown. False otherwise.\n*/\nbool Inventory::isInSearchString(BattleItem *item)\n{\n\tif (!_searchString.length())\n\t{\n\t\t// No active search string.\n\t\treturn true;\n\t}\n\n\tstd::string itemLocalName;\n\tif (!_game->getSavedGame()->isResearched(item->getRules()->getRequirements()))\n\t{\n\t\t// Alien artifact, shouldn't match on the real name.\n\t\titemLocalName = _game->getLanguage()->getString(\"STR_ALIEN_ARTIFACT\");\n\t}\n\telse\n\t{\n\t\titemLocalName = _game->getLanguage()->getString(item->getRules()->getName());\n\t}\n\tUnicode::upperCase(itemLocalName);\n\tif (itemLocalName.find(_searchString) != std::string::npos)\n\t{\n\t\t// Name match.\n\t\treturn true;\n\t}\n\n\t// If present in the Ufopaedia, check categories for a match as well.\n\tArticleDefinition *articleID = _game->getMod()->getUfopaediaArticle(item->getRules()->getType());\n\tif (articleID && Ufopaedia::isArticleAvailable(_game->getSavedGame(), articleID))\n\t{\n\t\tfor (const auto& itemCategoryName : item->getRules()->getCategories())\n\t\t{\n\t\t\tstd::string catLocalName = _game->getLanguage()->getString(itemCategoryName);\n\t\t\tUnicode::upperCase(catLocalName);\n\t\t\tif (catLocalName.find(_searchString) != std::string::npos)\n\t\t\t{\n\t\t\t\t// Category match\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\tfor (int slot = 0; slot < RuleItem::AmmoSlotMax; ++slot)\n\t\t{\n\t\t\tif (item->getAmmoForSlot(slot))\n\t\t\t{\n\t\t\t\tfor (const auto& itemAmmoCategoryName : item->getAmmoForSlot(slot)->getRules()->getCategories())\n\t\t\t\t{\n\t\t\t\t\tstd::string catLocalName = _game->getLanguage()->getString(itemAmmoCategoryName);\n\t\t\t\t\tUnicode::upperCase(catLocalName);\n\t\t\t\t\tif (catLocalName.find(_searchString) != std::string::npos)\n\t\t\t\t\t{\n\t\t\t\t\t\t// Category match\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Arranges items on the ground for the inventory display.\n * Since items on the ground aren't assigned to anyone,\n * they don't actually have permanent slot positions.\n * @param alterOffset Whether to alter the ground offset and in which direction.\n */\nvoid Inventory::arrangeGround(int alterOffset)\n{\n\tRuleInventory *ground = _inventorySlotGround;\n\n\tint slotsX = _groundSlotsX;\n\tint slotsY = _groundSlotsY;\n\tint x = 0;\n\tint y = 0;\n\tbool donePlacing = false;\n\tbool canPlace = false;\n\t_xMax = 0;\n\t_stackLevel.clear();\n\n\tif (_selUnit != 0)\n\t{\n\t\tstd::unordered_map< std::string, std::vector< std::vector<BattleItem*> > > typeItemLists; // Lists of items of the same type\n\t\tstd::vector<BattleItem*> itemListOrder; // Placement order of item type stacks.\n\t\tstd::vector< std::vector<int> > startIndexCacheX; // Cache for skipping to last known available position of a given size.\n\t\t// Create chart of free slots for later rapid lookup.\n\t\tauto& occupiedSlots = *clearOccupiedSlotsCache();\n\n\t\t// Move items out of the way and find which stack they'll end up in within the inventory.\n\t\tfor (auto& bi : *(_selUnit->getTile()->getInventory()))\n\t\t{\n\t\t\t// first move all items out of the way - a big number in X direction\n\t\t\tbi->setSlot(ground);\n\t\t\tbi->setSlotX(1000000);\n\t\t\tbi->setSlotY(0);\n\n\t\t\t// Only handle visible items from this point on.\n\t\t\tif (bi->getRules()->getInventoryWidth())\n\t\t\t{\n\t\t\t\t// Each item type has a list of stacks. Find / create a suitable one for this item.\n\t\t\t\tauto iterItemList = typeItemLists.find(bi->getRules()->getType());\n\t\t\t\tif (iterItemList == typeItemLists.end()) {\n\t\t\t\t\t// New item type, create a list of item stacks for it.\n\t\t\t\t\titerItemList = typeItemLists.insert(std::pair<std::string, std::vector< std::vector<BattleItem*> > >(bi->getRules()->getType(), { { bi } })).first;\n\t\t\t\t\titemListOrder.push_back(bi);\n\t\t\t\t\t// Figure out the largest item size present:\n\t\t\t\t\tx = std::max(x, bi->getRules()->getInventoryWidth());\n\t\t\t\t\ty = std::max(y, bi->getRules()->getInventoryHeight());\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t// With the item type found. Find which stack of this item type to add the item to.\n\t\t\t\t\tbool stacked = false;\n\t\t\t\t\tfor (auto& itemStack : iterItemList->second)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (canBeStacked(bi, itemStack.at(0)))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\titemStack.push_back(bi);\n\t\t\t\t\t\t\tstacked = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (!stacked) {\n\t\t\t\t\t\t// Not able to be stacked with previously placed items of this type. Make a new stack containing only this item.\n\t\t\t\t\t\titerItemList->second.push_back({ bi });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// Create the cache of last placed index for a given item size.\n\t\tstartIndexCacheX.resize(y + 1, std::vector<int>(x + 1, 0));\n\n\t\t// Before we place the items, we should sort the itemListOrder vector using the 'list order' of the items.\n\t\tstd::sort(itemListOrder.begin(), itemListOrder.end(), [](BattleItem* const &a, BattleItem* const &b)\n\t\t\t{\n\t\t\t\treturn a->getRules()->getListOrder() < b->getRules()->getListOrder();\n\t\t\t}\n\t\t);\n\n\t\t// Now for each item type, find the most topleft position that is not occupied and will fit.\n\t\tfor (auto& bi2 : itemListOrder)\n\t\t{\n\t\t\t// Fetch the list of item stacks for this item type. Then place each stack.\n\t\t\tauto iterItemList = typeItemLists.find(bi2->getRules()->getType());\n\t\t\tfor (auto& itemStack : iterItemList->second)\n\t\t\t{\n\t\t\t\tBattleItem* itemTypeSample = itemStack.at(0); // Grab a sample of the stack of item type we're trying to place.\n\t\t\t\tif (!isInSearchString(itemTypeSample))\n\t\t\t\t{\n\t\t\t\t\t// quick search\n\t\t\t\t\t// Not a match with the active search string, skip this item stack. (Will remain outside the visible inventory)\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t// Start searching at the x value where we last placed an item of this size.\n\t\t\t\t// But also don't let more than half a screen behind the furtherst item (because we want to keep similar items together).\n\t\t\t\tx = std::max(_xMax - slotsX/2, startIndexCacheX[itemTypeSample->getRules()->getInventoryHeight()][itemTypeSample->getRules()->getInventoryWidth()]);\n\t\t\t\ty = 0;\n\t\t\t\tdonePlacing = false;\n\t\t\t\twhile (!donePlacing)\n\t\t\t\t{\n\t\t\t\t\tcanPlace = true; // Assume we can put the item type here, if one of the following checks fails, we can't.\n\t\t\t\t\tfor (int xd = 0; xd < itemTypeSample->getRules()->getInventoryWidth() && canPlace; xd++)\n\t\t\t\t\t{\n\t\t\t\t\t\tif ((x + xd) % slotsX < x % slotsX)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcanPlace = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfor (int yd = 0; yd < itemTypeSample->getRules()->getInventoryHeight() && canPlace; yd++)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// If there's room and no item, we can place it here. (No need to check for stackability as nothing stackable has been placed)\n\t\t\t\t\t\t\t\tcanPlace = !occupiedSlots[y + yd][x + xd];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (canPlace) // Found a place for this item stack.\n\t\t\t\t\t{\n\t\t\t\t\t\t_xMax = std::max(_xMax, x + itemTypeSample->getRules()->getInventoryWidth());\n\t\t\t\t\t\tif ( (x + startIndexCacheX[0].size() ) >= occupiedSlots[0].size())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// Filled enough for the widest item to potentially request occupancy checks outside of current cache. Expand slot cache.\n\t\t\t\t\t\t\tsize_t newCacheSize = occupiedSlots[0].size() * 2;\n\t\t\t\t\t\t\tfor (auto j = occupiedSlots.begin(); j != occupiedSlots.end(); ++j) {\n\t\t\t\t\t\t\t\tj->resize(newCacheSize, 0);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Reserve the slots this item will occupy.\n\t\t\t\t\t\tfor (int xd = 0; xd < itemTypeSample->getRules()->getInventoryWidth() && canPlace; xd++)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfor (int yd = 0; yd < itemTypeSample->getRules()->getInventoryHeight() && canPlace; yd++)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\toccupiedSlots[y + yd][x + xd] = 1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Place all items from this stack in the location we just reserved.\n\t\t\t\t\t\tfor (auto& bi3 : itemStack)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tbi3->setSlotX(x);\n\t\t\t\t\t\t\tbi3->setSlotY(y);\n\t\t\t\t\t\t\t_stackLevel[x][y] += 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdonePlacing = true;\n\t\t\t\t\t}\n\t\t\t\t\tif (!donePlacing)\n\t\t\t\t\t{\n\t\t\t\t\t\ty++;\n\t\t\t\t\t\tif (y > slotsY - itemTypeSample->getRules()->getInventoryHeight())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ty = 0;\n\t\t\t\t\t\t\tx++;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Now update the shortcut cache so that items to follow are able to skip a decent chunk of their search,\n\t\t\t\t// as there can be no spot before this x-address with available slots for items that are larger in one or more dimensions.\n\t\t\t\tint firstPossibleX = itemTypeSample->getRules()->getInventoryHeight() * 2 > slotsY ? x + itemTypeSample->getRules()->getInventoryWidth() : x;\n\t\t\t\tfor (size_t offsetY = itemTypeSample->getRules()->getInventoryHeight(); offsetY < startIndexCacheX.size(); ++offsetY)\n\t\t\t\t{\n\t\t\t\t\tfor (size_t offsetX = itemTypeSample->getRules()->getInventoryWidth(); offsetX < startIndexCacheX[offsetY].size(); ++offsetX)\n\t\t\t\t\t{\n\t\t\t\t\t\tstartIndexCacheX[offsetY][offsetX] = std::max(firstPossibleX, startIndexCacheX[offsetY][offsetX]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} // end stacks for this item type\n\t\t} // end of item types\n\t}\n\tif (alterOffset > 0)\n\t{\n\t\tif (_xMax >= _groundOffset + slotsX)\n\t\t{\n\t\t\t_groundOffset += slotsX;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_groundOffset = 0;\n\t\t}\n\t}\n\telse if (alterOffset < 0)\n\t{\n\t\t// one step back\n\t\t_groundOffset -= slotsX;\n\n\t\t// if too much, as many steps forward as possible\n\t\tif (_groundOffset < 0)\n\t\t{\n\t\t\twhile (_xMax >= _groundOffset + slotsX)\n\t\t\t{\n\t\t\t\t_groundOffset += slotsX;\n\t\t\t}\n\t\t}\n\t}\n\tdrawItems();\n\tdrawGridLabels(!Options::oxceDisableInventoryTuCost);\n}\n\n/**\n * Attempts to place the item in the inventory slot.\n * @param newSlot Where to place the item.\n * @param item Item to be placed.\n * @param warning Warning message if item could not be placed.\n * @return True, if the item was successfully placed in the inventory.\n */\nbool Inventory::fitItem(const RuleInventory *newSlot, BattleItem *item, std::string &warning)\n{\n\t// Check if this inventory section supports the item\n\tif (!item->getRules()->canBePlacedIntoInventorySection(newSlot))\n\t{\n\t\twarning = \"STR_CANNOT_PLACE_ITEM_INTO_THIS_SECTION\";\n\t\treturn false;\n\t}\n\n\tbool placed = false;\n\tint maxSlotX = 0;\n\tint maxSlotY = 0;\n\tfor (const auto& slotInfo : *newSlot->getSlots())\n\t{\n\t\tif (slotInfo.x > maxSlotX) maxSlotX = slotInfo.x;\n\t\tif (slotInfo.y > maxSlotY) maxSlotY = slotInfo.y;\n\t}\n\tfor (int y2 = 0; y2 <= maxSlotY && !placed; ++y2)\n\t{\n\t\tfor (int x2 = 0; x2 <= maxSlotX && !placed; ++x2)\n\t\t{\n\t\t\tif (!overlapItems(_selUnit, item, newSlot, x2, y2) && newSlot->fitItemInSlot(item->getRules(), x2, y2))\n\t\t\t{\n\t\t\t\tif (!_tu || _selUnit->spendTimeUnits(item->getMoveToCost(newSlot)))\n\t\t\t\t{\n\t\t\t\t\tplaced = true;\n\t\t\t\t\tmoveItem(item, newSlot, x2, y2);\n\t\t\t\t\t_game->getMod()->getSoundByDepth(_depth, Mod::ITEM_DROP)->play();\n\t\t\t\t\tdrawItems();\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\twarning = \"STR_NOT_ENOUGH_TIME_UNITS\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn placed;\n}\n\n/**\n * Checks if two items can be stacked on one another.\n * @param itemA First item.\n * @param itemB Second item.\n * @return True, if the items can be stacked on one another.\n */\nbool Inventory::canBeStacked(BattleItem *itemA, BattleItem *itemB)\n{\n\t//both items actually exist\n\tif (!itemA || !itemB) return false;\n\n\t//both items have the same ruleset\n\tif (itemA->getRules() != itemB->getRules()) return false;\n\n\tfor (int slot = 0; slot < RuleItem::AmmoSlotMax; ++slot)\n\t{\n\t\tauto* ammoA = itemA->getAmmoForSlot(slot);\n\t\tauto* ammoB = itemB->getAmmoForSlot(slot);\n\t\t// or they both have ammo\n\t\tif (ammoA && ammoB)\n\t\t{\n\t\t\t// and the same ammo type\n\t\t\tif (ammoA->getRules() != ammoB->getRules()) return false;\n\t\t\t// and the same ammo quantity\n\t\t\tif (ammoA->getAmmoQuantity() != ammoB->getAmmoQuantity()) return false;\n\t\t}\n\t\telse if (ammoA || ammoB)\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn (\n\t\t// and neither is set to explode\n\t\titemA->getFuseTimer() == -1 && itemB->getFuseTimer() == -1 &&\n\t\t// and neither is a corpse or unconscious unit\n\t\titemA->getUnit() == 0 && itemB->getUnit() == 0 &&\n\t\t// and if it's a medikit, it has the same number of charges\n\t\titemA->getPainKillerQuantity() == itemB->getPainKillerQuantity() &&\n\t\titemA->getHealQuantity() == itemB->getHealQuantity() &&\n\t\titemA->getStimulantQuantity() == itemB->getStimulantQuantity());\n}\n\n/**\n * Shows a warning message.\n * @param msg The message to show.\n */\nvoid Inventory::showWarning(const std::string &msg)\n{\n\t_warning->showMessage(msg);\n}\n\n/**\n * Animate surface.\n */\nvoid Inventory::animate()\n{\n\tif (_tu)\n\t{\n\t\tSavedBattleGame* save = _game->getSavedGame()->getSavedBattle();\n\t\tsave->nextAnimFrame();\n\t\t_animFrame = save->getAnimFrame();\n\t}\n\telse\n\t{\n\t\t_animFrame++;\n\t}\n\n\tdrawItems();\n\tdrawSelectedItem();\n}\n\n/**\n * Play a sound.\n */\nvoid Inventory::playSound(int sound)\n{\n\tif (sound != Mod::NO_SOUND)\n\t{\n\t\t_game->getMod()->getSoundByDepth(_depth, sound)->play();\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/Inventory.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/InteractiveSurface.h\"\n#include <locale>\n#include <map>\n#include <string>\n\nnamespace OpenXcom\n{\n\nclass RuleInventory;\nclass Game;\nclass WarningMessage;\nclass BattleItem;\nclass BattleUnit;\nclass NumberText;\nclass Timer;\n\n/**\n * Interactive view of an inventory.\n * Lets the player view and manage a soldier's equipment.\n */\nclass Inventory : public InteractiveSurface\n{\nprivate:\n\tGame *_game;\n\tSurface *_grid, *_items, *_gridLabels, *_selection;\n\tUint8 _twoHandedRed, _twoHandedGreen;\n\tWarningMessage *_warning;\n\tBattleUnit *_selUnit;\n\tBattleItem *_selItem;\n\tbool _tu, _base;\n\tBattleItem *_mouseOverItem;\n\tint _groundOffset, _animFrame;\n\tstd::map<int, std::map<int, int> > _stackLevel;\n\tstd::vector<std::vector<char>> _occupiedSlotsCache;\n\tSurface *_stunIndicator, *_woundIndicator, *_burnIndicator, *_shockIndicator;\n\tNumberText *_stackNumber;\n\tstd::string _searchString;\n\tTimer *_animTimer;\n\tint _depth, _groundSlotsX, _groundSlotsY;\n\tint _xMax;\n\tRuleInventory *_inventorySlotRightHand = nullptr;\n\tRuleInventory *_inventorySlotLeftHand = nullptr;\n\tRuleInventory *_inventorySlotBackPack = nullptr;\n\tRuleInventory *_inventorySlotBelt = nullptr;\n\tRuleInventory *_inventorySlotGround = nullptr;\n\n\t/// Clear all occupied slots markers.\n\tstd::vector<std::vector<char>>* clearOccupiedSlotsCache();\n\t/// Moves an item to a specified slot.\n\tvoid moveItem(BattleItem *item, const RuleInventory *slot, int x, int y);\n\t/// Gets the slot in the specified position.\n\tRuleInventory *getSlotInPosition(int *x, int *y) const;\n\t/// Play a sound.\n\tvoid playSound(int sound);\npublic:\n\t/// Creates a new inventory view at the specified position and size.\n\tInventory(Game *game, int width, int height, int x = 0, int y = 0, bool base = false);\n\t/// Cleans up the inventory.\n\t~Inventory();\n\t/// Sets the inventory's palette.\n\tvoid setPalette(const SDL_Color *colors, int firstcolor = 0, int ncolors = 256) override;\n\t/// Sets the inventory's Time Unit mode.\n\tvoid setTuMode(bool tu);\n\t/// Gets the inventory's selected unit.\n\tBattleUnit *getSelectedUnit() const;\n\t/// Sets the inventory's selected unit.\n\tvoid setSelectedUnit(BattleUnit *unit, bool resetGroundOffset);\n\t/// Draws the inventory.\n\tvoid draw() override;\n\t/// Draws the inventory grid.\n\tvoid drawGrid();\n\t/// Draws the inventory grid labels.\n\tvoid drawGridLabels(bool showTuCost = false);\n\t/// Draws the inventory items.\n\tvoid drawItems();\n\t/// Draws the selected item.\n\tvoid drawSelectedItem();\n\t/// Gets the currently selected item.\n\tBattleItem *getSelectedItem() const;\n\t/// Sets the currently selected item.\n\tvoid setSelectedItem(BattleItem *item);\n\t/// Sets the search string.\n\tvoid setSearchString(const std::string &searchString);\n\t/// Gets the mouse over item.\n\tBattleItem *getMouseOverItem() const;\n\t/// Sets the mouse over item.\n\tvoid setMouseOverItem(BattleItem *item);\n\t/// Handles timers.\n\tvoid think() override;\n\t/// Blits the inventory onto another surface.\n\tvoid blit(SDL_Surface *surface) override;\n\t/// Special handling for mouse hovers.\n\tvoid mouseOver(Action *action, State *state) override;\n\t/// Special handling for mouse clicks.\n\tvoid mouseClick(Action *action, State *state) override;\n\t/// Quickly drops the selected item on the ground.\n\tbool quickDrop();\n\t/// Unloads the selected weapon.\n\tbool unload(bool quickUnload = false);\n\t/// Checks whether the given item is visible with the current search string.\n\tbool isInSearchString(BattleItem *item);\n\t/// Arranges items on the ground.\n\tvoid arrangeGround(int alterOffset = 0);\n\t/// Attempts to place an item in an inventory slot.\n\tbool fitItem(const RuleInventory *newSlot, BattleItem *item, std::string &warning);\n\t/// Checks if two items can be stacked on one another.\n\tbool canBeStacked(BattleItem *itemA, BattleItem *itemB);\n\t/// Checks for item overlap.\n\tstatic bool overlapItems(BattleUnit *unit, BattleItem *item, const RuleInventory *slot, int x = 0, int y = 0);\n\t/// Shows a warning message.\n\tvoid showWarning(const std::string &msg);\n\t/// Animate surface.\n\tvoid animate();\n\t/// Get current animation frame for inventory.\n\tint getAnimFrame() const { return _animFrame; }\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/InventoryLoadState.cpp",
    "content": "/*\n* Copyright 2010-2015 OpenXcom Developers.\n*\n* This file is part of OpenXcom.\n*\n* OpenXcom is free software: you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation, either version 3 of the License, or\n* (at your option) any later version.\n*\n* OpenXcom is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*\n* You should have received a copy of the GNU General Public License\n* along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n*/\n#include \"InventoryLoadState.h\"\n#include \"InventoryState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Savegame/SavedGame.h\"\n\nnamespace OpenXcom\n{\n\n/**\n* Initializes all the elements in the Load Inventory window.\n*/\nInventoryLoadState::InventoryLoadState(InventoryState *parent) : _parent(parent)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 240, 136, 40, 36+1, POPUP_BOTH);\n\t_txtTitle = new Text(230, 16, 45, 44+3);\n\t_lstLayout = new TextList(208, 80, 48, 60);\n\t_btnCancel = new TextButton(120, 16, 90, 148);\n\n\tsetStandardPalette(\"PAL_BATTLESCAPE\");\n\n\tadd(_window, \"messageWindowBorder\", \"battlescape\");\n\tadd(_txtTitle, \"messageWindows\", \"battlescape\");\n\tadd(_lstLayout, \"optionLists\", \"battlescape\");\n\tadd(_btnCancel, \"messageWindowButtons\", \"battlescape\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\t_window->setHighContrast(true);\n\t_window->setBackground(_game->getMod()->getSurface(\"TAC00.SCR\"));\n\n\t_txtTitle->setHighContrast(true);\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_LOAD_EQUIPMENT_TEMPLATE\"));\n\n\t_lstLayout->setHighContrast(true);\n\t_lstLayout->setColumns(1, 192);\n\t_lstLayout->setSelectable(true);\n\t_lstLayout->setBackground(_window);\n\t_lstLayout->setMargin(8);\n\t_lstLayout->onMouseClick((ActionHandler)&InventoryLoadState::lstLayoutClick);\n\n\t_btnCancel->setHighContrast(true);\n\t_btnCancel->setText(tr(\"STR_CANCEL_UC\"));\n\t_btnCancel->onMouseClick((ActionHandler)&InventoryLoadState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&InventoryLoadState::btnCancelClick, Options::keyCancel);\n\n\tfor (int i = 0; i < Options::oxceMaxEquipmentLayoutTemplates; ++i)\n\t{\n\t\tstd::vector<EquipmentLayoutItem*> *item = _game->getSavedGame()->getGlobalEquipmentLayout(i);\n\t\tstd::ostringstream ss;\n\t\tconst std::string& armorName = _game->getSavedGame()->getGlobalEquipmentLayoutArmor(i);\n\t\tif (!armorName.empty())\n\t\t{\n\t\t\tss << \"[\" << tr(armorName) << \"] \";\n\t\t}\n\t\tif (item->empty())\n\t\t{\n\t\t\tss << tr(\"STR_EMPTY_SLOT_N\").arg(i + 1);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tconst std::string &itemName = _game->getSavedGame()->getGlobalEquipmentLayoutName(i);\n\t\t\tif (itemName.empty())\n\t\t\t\tss << tr(\"STR_UNNAMED_SLOT_N\").arg(i + 1);\n\t\t\telse\n\t\t\t\tss << itemName;\n\t\t}\n\t\t_lstLayout->addRow(1, ss.str().c_str());\n\t}\n}\n\n/**\n*\n*/\nInventoryLoadState::~InventoryLoadState()\n{\n\n}\n\n/**\n* Returns to the previous screen.\n* @param action Pointer to an action.\n*/\nvoid InventoryLoadState::btnCancelClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n* Loads the template and returns to the previous screen.\n* @param action Pointer to an action.\n*/\nvoid InventoryLoadState::lstLayoutClick(Action *)\n{\n\tauto index = _lstLayout->getSelectedRow();\n\tbool armorChanged = _parent->loadGlobalLayoutArmor(index);\n\t_parent->setGlobalLayoutIndex(index, armorChanged);\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/InventoryLoadState.h",
    "content": "#pragma once\n/*\n* Copyright 2010-2015 OpenXcom Developers.\n*\n* This file is part of OpenXcom.\n*\n* OpenXcom is free software: you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation, either version 3 of the License, or\n* (at your option) any later version.\n*\n* OpenXcom is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*\n* You should have received a copy of the GNU General Public License\n* along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n*/\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass TextList;\nclass EquipmentLayoutItem;\nclass InventoryState;\n\n/**\n* Inventory Load window that allows changing of the equipment on a soldier.\n*/\nclass InventoryLoadState : public State\n{\nprivate:\n\tInventoryState *_parent;\n\tWindow *_window;\n\tText *_txtTitle;\n\tTextList *_lstLayout;\n\tTextButton *_btnCancel;\npublic:\n\t/// Creates the Load Inventory state.\n\tInventoryLoadState(InventoryState *parent);\n\t/// Cleans up the Load Inventory state.\n\t~InventoryLoadState();\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action *action);\n\t/// Handler for clicking the Layout list.\n\tvoid lstLayoutClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/InventoryPersonalState.cpp",
    "content": "/*\n * Copyright 2010-2020 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"InventoryPersonalState.h\"\n#include <algorithm>\n#include \"../Engine/Game.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Interface/Window.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"../Savegame/EquipmentLayoutItem.h\"\n#include \"../Savegame/Soldier.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the InventoryPersonalState.\n */\nInventoryPersonalState::InventoryPersonalState(Soldier* soldier)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 196, 160, 64, 20, POPUP_BOTH);\n\t_txtTitle = new Text(186, 16, 69, 30);\n\t_lstLayout = new TextList(164, 104, 72, 44);\n\t_btnCancel = new TextButton(144, 16, 90, 156);\n\n\tsetStandardPalette(\"PAL_BATTLESCAPE\");\n\n\tadd(_window, \"messageWindowBorder\", \"battlescape\");\n\tadd(_txtTitle, \"messageWindows\", \"battlescape\");\n\tadd(_lstLayout, \"optionLists\", \"battlescape\");\n\tadd(_btnCancel, \"messageWindowButtons\", \"battlescape\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\t_window->setHighContrast(true);\n\t_window->setBackground(_game->getMod()->getSurface(\"TAC00.SCR\"));\n\n\t_txtTitle->setHighContrast(true);\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_PERSONAL_EQUIPMENT\"));\n\n\t_lstLayout->setHighContrast(true);\n\t_lstLayout->setColumns(2, 136, 12);\n\t_lstLayout->setSelectable(true);\n\t_lstLayout->setBackground(_window);\n\t_lstLayout->setMargin(8);\n\n\t_btnCancel->setHighContrast(true);\n\t_btnCancel->setText(tr(\"STR_CANCEL_UC\"));\n\t_btnCancel->onMouseClick((ActionHandler)&InventoryPersonalState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&InventoryPersonalState::btnCancelClick, Options::keyCancel);\n\n\t// 1. tally items\n\tstd::map<const RuleItem*, int> summary;\n\tfor (const auto* layoutItem : *soldier->getPersonalEquipmentLayout())\n\t{\n\t\t// item\n\t\tsummary[layoutItem->getItemType()] += 1;\n\n\t\t// ammo\n\t\tfor (int slot = 0; slot < RuleItem::AmmoSlotMax; ++slot)\n\t\t{\n\t\t\tconst auto* loadedAmmoType = layoutItem->getAmmoItemForSlot(slot);\n\t\t\tif (loadedAmmoType != nullptr)\n\t\t\t{\n\t\t\t\tsummary[loadedAmmoType] += 1;\n\t\t\t}\n\t\t}\n\t}\n\n\t// 2. sort items\n\tstd::vector<const RuleItem*> sorted;\n\tsorted.reserve(summary.size());\n\tfor (auto& info : summary)\n\t{\n\t\tsorted.push_back(info.first);\n\t}\n\tstd::sort(sorted.begin(), sorted.end(), [](const RuleItem* a, const RuleItem* b)\n\t\t{\n\t\t\treturn a->getListOrder() < b->getListOrder();\n\t\t}\n\t);\n\n\t// display armor\n\tif (Options::oxcePersonalLayoutIncludingArmor)\n\t{\n\t\tstd::ostringstream ss1, ss2;\n\t\tauto* armor = soldier->getPersonalEquipmentArmor();\n\t\tif (armor)\n\t\t{\n\t\t\tss1 << tr(armor->getType());\n\t\t}\n\t\t_lstLayout->addRow(2, ss1.str().c_str(), ss2.str().c_str());\n\t}\n\n\t// 3. display items\n\tfor (auto* ruleItem : sorted)\n\t{\n\t\tstd::ostringstream ss1, ss2;\n\t\tif (ruleItem->getBattleType() == BT_AMMO)\n\t\t{\n\t\t\tss1 << \"  \";\n\t\t}\n\t\tss1 << tr(ruleItem->getType());\n\t\tss2 << summary[ruleItem];\n\t\t_lstLayout->addRow(2, ss1.str().c_str(), ss2.str().c_str());\n\t}\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid InventoryPersonalState::btnCancelClick(Action*)\n{\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/InventoryPersonalState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2020 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass TextList;\nclass Soldier;\n\n/**\n * A dialog window that allows viewing the content of the soldier's personal equipment template.\n */\nclass InventoryPersonalState : public State\n{\nprivate:\n\tWindow* _window;\n\tText* _txtTitle;\n\tTextList* _lstLayout;\n\tTextButton* _btnCancel;\npublic:\n\t/// Creates the InventoryPersonalState.\n\tInventoryPersonalState(Soldier* soldier);\n\t/// Cleans up the state.\n\t~InventoryPersonalState() = default;\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action* action);\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/InventorySaveState.cpp",
    "content": "/*\n* Copyright 2010-2015 OpenXcom Developers.\n*\n* This file is part of OpenXcom.\n*\n* OpenXcom is free software: you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation, either version 3 of the License, or\n* (at your option) any later version.\n*\n* OpenXcom is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*\n* You should have received a copy of the GNU General Public License\n* along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n*/\n#include \"InventorySaveState.h\"\n#include \"InventoryState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Language.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextEdit.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Savegame/SavedGame.h\"\n\nnamespace OpenXcom\n{\n\n/**\n* Initializes all the elements in the Save Inventory window.\n*/\nInventorySaveState::InventorySaveState(InventoryState *parent) : _parent(parent), _previousSelectedRow(-1), _selectedRow(-1)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 240, 136, 40, 36 + 1, POPUP_BOTH);\n\t_txtTitle = new Text(230, 16, 45, 44 + 3);\n\t_lstLayout = new TextList(208, 80, 48, 60);\n\t_btnCancel = new TextButton(70, 16, 201, 148);\n\t_btnSave = new TextButton(70, 16, 50, 148);\n\t_btnSaveWithArmor = new TextButton(70, 16, 126, 148);\n\t_edtSave = new TextEdit(this, 188, 9, 0, 0);\n\n\tsetStandardPalette(\"PAL_BATTLESCAPE\");\n\n\tadd(_window, \"messageWindowBorder\", \"battlescape\");\n\tadd(_txtTitle, \"messageWindows\", \"battlescape\");\n\tadd(_lstLayout, \"optionLists\", \"battlescape\");\n\tadd(_btnCancel, \"messageWindowButtons\", \"battlescape\");\n\tadd(_btnSave, \"messageWindowButtons\", \"battlescape\");\n\tadd(_btnSaveWithArmor, \"messageWindowButtons\", \"battlescape\");\n\tadd(_edtSave);\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\t_window->setHighContrast(true);\n\t_window->setBackground(_game->getMod()->getSurface(\"TAC00.SCR\"));\n\n\t_txtTitle->setHighContrast(true);\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_SAVE_EQUIPMENT_TEMPLATE\"));\n\n\t_lstLayout->setHighContrast(true);\n\t_lstLayout->setColumns(1, 192);\n\t_lstLayout->setSelectable(true);\n\t_lstLayout->setBackground(_window);\n\t_lstLayout->setMargin(8);\n\t_lstLayout->onMousePress((ActionHandler)&InventorySaveState::lstLayoutPress);\n\n\t_btnCancel->setHighContrast(true);\n\t_btnCancel->setText(tr(\"STR_CANCEL_UC\"));\n\t_btnCancel->onMouseClick((ActionHandler)&InventorySaveState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&InventorySaveState::btnCancelClick, Options::keyCancel);\n\n\t_btnSave->setHighContrast(true);\n\t_btnSave->setText(tr(\"STR_SAVE_UC\"));\n\t_btnSave->onMouseClick((ActionHandler)&InventorySaveState::btnSaveClick);\n\n\t_btnSaveWithArmor->setHighContrast(true);\n\tstd::string savePlus = tr(\"STR_SAVE_UC\");\n\tsavePlus += \"+\";\n\t_btnSaveWithArmor->setText(savePlus);\n\t_btnSaveWithArmor->onMouseClick((ActionHandler)&InventorySaveState::btnSaveWithArmorClick);\n\n\t_edtSave->setHighContrast(true);\n\t_edtSave->setColor(_lstLayout->getSecondaryColor());\n\t_edtSave->setVisible(false);\n\t_edtSave->onKeyboardPress((ActionHandler)&InventorySaveState::edtSaveKeyPress);\n\n\tfor (int i = 0; i < Options::oxceMaxEquipmentLayoutTemplates; ++i)\n\t{\n\t\tstd::vector<EquipmentLayoutItem*> *item = _game->getSavedGame()->getGlobalEquipmentLayout(i);\n\t\tstd::ostringstream ss;\n\t\tconst std::string& armorName = _game->getSavedGame()->getGlobalEquipmentLayoutArmor(i);\n\t\tif (!armorName.empty())\n\t\t{\n\t\t\tss << \"[\" << tr(armorName) << \"] \";\n\t\t}\n\t\tif (item->empty())\n\t\t{\n\t\t\tss << tr(\"STR_EMPTY_SLOT_N\").arg(i + 1);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tconst std::string &itemName = _game->getSavedGame()->getGlobalEquipmentLayoutName(i);\n\t\t\tif (itemName.empty())\n\t\t\t\tss << tr(\"STR_UNNAMED_SLOT_N\").arg(i + 1);\n\t\t\telse\n\t\t\t\tss << itemName;\n\t\t}\n\t\t_lstLayout->addRow(1, ss.str().c_str());\n\t}\n}\n\n/**\n*\n*/\nInventorySaveState::~InventorySaveState()\n{\n\n}\n\n/**\n* Returns to the previous screen.\n* @param action Pointer to an action.\n*/\nvoid InventorySaveState::btnCancelClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n* Saves the selected template.\n* @param action Pointer to an action.\n*/\nvoid InventorySaveState::btnSaveClick(Action *)\n{\n\tif (_selectedRow != -1)\n\t{\n\t\tsaveTemplate(false);\n\t}\n}\n\n/**\n * Saves the selected template (including the armor).\n * @param action Pointer to an action.\n */\nvoid InventorySaveState::btnSaveWithArmorClick(Action*)\n{\n\tif (_selectedRow != -1)\n\t{\n\t\tsaveTemplate(true);\n\t}\n}\n\n/**\n* Names the selected template.\n* @param action Pointer to an action.\n*/\nvoid InventorySaveState::lstLayoutPress(Action *action)\n{\n\t_previousSelectedRow = _selectedRow;\n\t_selectedRow = _lstLayout->getSelectedRow();\n\tif (_previousSelectedRow > -1)\n\t{\n\t\t_lstLayout->setCellText(_previousSelectedRow, 0, _selected);\n\t}\n\t_selected = _lstLayout->getCellText(_selectedRow, 0);\n\n\tif (_game->isRightClick(action) && _edtSave->isFocused())\n\t{\n\t\t_previousSelectedRow = -1;\n\t\t_selectedRow = -1;\n\n\t\t_edtSave->setText(\"\");\n\t\t_edtSave->setVisible(false);\n\t\t_edtSave->setFocus(false, false);\n\t\t_lstLayout->setScrolling(true);\n\t}\n\tif (_game->isLeftClick(action))\n\t{\n\t\t_lstLayout->setCellText(_selectedRow, 0, \"\");\n\n\t\tstd::size_t pos = _selected.find(\"] \");\n\t\tif (pos != std::string::npos)\n\t\t{\n\t\t\t// cut off the armor info\n\t\t\t_edtSave->setText(_selected.substr(pos + 2));\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_edtSave->setText(_selected);\n\t\t}\n\t\t_edtSave->setX(_lstLayout->getColumnX(0));\n\t\t_edtSave->setY(_lstLayout->getRowY(_selectedRow));\n\t\t_edtSave->setVisible(true);\n\t\t_edtSave->setFocus(true, false);\n\t\t_lstLayout->setScrolling(false);\n\t}\n}\n\n\n/**\n* Saves the selected template.\n* @param action Pointer to an action.\n*/\nvoid InventorySaveState::edtSaveKeyPress(Action *action)\n{\n\tif (action->getDetails()->key.keysym.sym == SDLK_RETURN ||\n\t\taction->getDetails()->key.keysym.sym == SDLK_KP_ENTER)\n\t{\n\t\tsaveTemplate(false);\n\t}\n}\n\n/**\n* Saves the selected template.\n*/\nvoid InventorySaveState::saveTemplate(bool includingArmor)\n{\n\tif (_selectedRow >= 0 && _selectedRow < Options::oxceMaxEquipmentLayoutTemplates)\n\t{\n\t\t_game->getSavedGame()->setGlobalEquipmentLayoutName(_selectedRow, _edtSave->getText());\n\t\t_parent->saveGlobalLayout(_selectedRow, includingArmor);\n\n\t\t_game->popState();\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/InventorySaveState.h",
    "content": "#pragma once\n/*\n* Copyright 2010-2015 OpenXcom Developers.\n*\n* This file is part of OpenXcom.\n*\n* OpenXcom is free software: you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation, either version 3 of the License, or\n* (at your option) any later version.\n*\n* OpenXcom is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*\n* You should have received a copy of the GNU General Public License\n* along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n*/\n#include <string>\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass TextEdit;\nclass TextButton;\nclass Window;\nclass Text;\nclass TextList;\nclass EquipmentLayoutItem;\nclass InventoryState;\n\n/**\n* Inventory Save window that allows saving of the equipment on a soldier to a global template.\n*/\nclass InventorySaveState : public State\n{\nprivate:\n\tInventoryState *_parent;\n\tWindow *_window;\n\tText *_txtTitle;\n\tTextList *_lstLayout;\n\tTextButton *_btnCancel, *_btnSave, *_btnSaveWithArmor;\n\tTextEdit *_edtSave;\n\tstd::string _selected;\n\tint _previousSelectedRow, _selectedRow;\npublic:\n\t/// Creates the Save Inventory state.\n\tInventorySaveState(InventoryState *parent);\n\t/// Cleans up the Save Inventory state.\n\t~InventorySaveState();\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action *action);\n\t/// Handler for clicking the Save button.\n\tvoid btnSaveClick(Action *action);\n\t/// Handler for clicking the SaveWithArmor button.\n\tvoid btnSaveWithArmorClick(Action* action);\n\t/// Handler for clicking the Layout list.\n\tvoid lstLayoutPress(Action *action);\n\t/// Handler for pressing a key on the Save edit.\n\tvoid edtSaveKeyPress(Action *action);\n\t/// Save template.\n\tvoid saveTemplate(bool includingArmor);\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/InventoryState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"InventoryState.h\"\n#include \"InventoryLoadState.h\"\n#include \"InventorySaveState.h\"\n#include \"InventoryPersonalState.h\"\n#include <algorithm>\n#include \"Inventory.h\"\n#include \"../Basescape/SoldierArmorState.h\"\n#include \"../Basescape/SoldierAvatarState.h\"\n#include \"../Basescape/SoldierDiaryLightState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/FileMap.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Screen.h\"\n#include \"../Engine/Palette.h\"\n#include \"../Engine/Surface.h\"\n#include \"../Engine/Collections.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextEdit.h\"\n#include \"../Interface/BattlescapeButton.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/InteractiveSurface.h\"\n#include \"../Engine/Sound.h\"\n#include \"../Engine/SurfaceSet.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Tile.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/BattleUnit.h\"\n#include \"../Savegame/Craft.h\"\n#include \"../Savegame/ItemContainer.h\"\n#include \"../Savegame/Soldier.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"../Mod/RuleInventory.h\"\n#include \"../Mod/RuleSoldier.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Engine/Options.h\"\n#include \"UnitInfoState.h\"\n#include \"BattlescapeState.h\"\n#include \"BattlescapeGenerator.h\"\n#include \"ExtendedInventoryLinksState.h\"\n#include \"TileEngine.h\"\n#include \"../Mod/RuleInterface.h\"\n#include \"../Ufopaedia/Ufopaedia.h\"\n\nnamespace OpenXcom\n{\n\nstatic const int _templateBtnX = 288;\nstatic const int _createTemplateBtnY = 90;\nstatic const int _applyTemplateBtnY  = 113;\n\n/**\n * Initializes all the elements in the Inventory screen.\n * @param game Pointer to the core game.\n * @param tu Does Inventory use up Time Units?\n * @param parent Pointer to parent Battlescape.\n */\nInventoryState::InventoryState(bool tu, BattlescapeState *parent, Base *base, bool noCraft) :\n\t_tu(tu), _noCraft(noCraft), _parent(parent), _base(base),\n\t_resetCustomDeploymentBackup(false), _reloadUnit(false), _globalLayoutIndex(-1)\n{\n\t_battleGame = _game->getSavedGame()->getSavedBattle();\n\n\tif (Options::oxceAlternateCraftEquipmentManagement && !_tu && _base && _noCraft)\n\t{\n\t\t// deassign all soldiers\n\t\tfor (auto* soldier : *_base->getSoldiers())\n\t\t{\n\t\t\t_backup[soldier] = soldier->getCraft();\n\t\t\tif (soldier->getCraft() && soldier->getCraft()->getStatus() != \"STR_OUT\")\n\t\t\t{\n\t\t\t\tsoldier->setCraftAndMoveEquipment(0, _base, _game->getSavedGame()->getMonthsPassed() == -1);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (Options::maximizeInfoScreens)\n\t{\n\t\tOptions::baseXResolution = Screen::ORIGINAL_WIDTH;\n\t\tOptions::baseYResolution = Screen::ORIGINAL_HEIGHT;\n\t\t_game->getScreen()->resetDisplay(false);\n\t}\n\telse if (_battleGame->isBaseCraftInventory())\n\t{\n\t\tScreen::updateScale(Options::battlescapeScale, Options::baseXBattlescape, Options::baseYBattlescape, true);\n\t\t_game->getScreen()->resetDisplay(false);\n\t}\n\n\t// Create objects\n\t_bg = new Surface(320, 200, 0, 0);\n\t_soldier = new Surface(320, 200, 0, 0);\n\t_txtPosition = new Text(70, 9, 65, 95);\n\t_txtNameStatic = new Text(210, 17, 28, 6);\n\t_txtName = new TextEdit(this, 210, 17, 28, 6);\n\t_txtTus = new Text(40, 9, 245, 24);\n\t_txtWeight = new Text(70, 9, 245, 24);\n\t_txtStatLine1 = new Text(70, 9, 245, 32);\n\t_txtStatLine2 = new Text(70, 9, 245, 40);\n\t_txtStatLine3 = new Text(70, 9, 245, 48);\n\t_txtStatLine4 = new Text(70, 9, 245, 56);\n\t_txtItem = new Text(160, 9, 128, 140);\n\t_txtAmmo = new Text(66, 24, 254, 64);\n\t_btnOk = new BattlescapeButton(35, 22, 237, 1);\n\t_btnPrev = new BattlescapeButton(23, 22, 273, 1);\n\t_btnNext = new BattlescapeButton(23, 22, 297, 1);\n\t_btnUnload = new BattlescapeButton(32, 25, 288, 32);\n\t_btnGround = new BattlescapeButton(32, 15, 289, 137);\n\t_btnRank = new BattlescapeButton(26, 23, 0, 0);\n\t_btnArmor = new BattlescapeButton(RuleInventory::PAPERDOLL_W, RuleInventory::PAPERDOLL_H, RuleInventory::PAPERDOLL_X, RuleInventory::PAPERDOLL_Y);\n\t_btnCreateTemplate = new BattlescapeButton(32, 22, _templateBtnX, _createTemplateBtnY);\n\t_btnApplyTemplate = new BattlescapeButton(32, 22, _templateBtnX, _applyTemplateBtnY);\n\tconst Element* pixelShift = _game->getMod()->getInterface(\"inventory\")->getElementOptional(\"buttonLinks\");\n\tif (pixelShift && pixelShift->TFTDMode)\n\t{\n\t\t_btnLinks = new BattlescapeButton(23, 22, 213, 0);\n\t}\n\telse\n\t{\n\t\t_btnLinks = new BattlescapeButton(23, 22, 213, 1);\n\t}\n\t_selAmmo = new Surface(RuleInventory::HAND_W * RuleInventory::SLOT_W, RuleInventory::HAND_H * RuleInventory::SLOT_H, 272, 88);\n\t_inv = new Inventory(_game, 320, 200, 0, 0, _parent == 0);\n\t_btnQuickSearch = new TextEdit(this, 40, 9, 244, 140);\n\n\t// Set palette\n\tsetStandardPalette(\"PAL_BATTLESCAPE\");\n\n\tadd(_bg);\n\n\t// Set up objects\n\t_game->getMod()->getSurface(\"TAC01.SCR\")->blitNShade(_bg, 0, 0);\n\tadd(_btnArmor, \"buttonArmor\", \"inventory\", _bg);\n\n\tadd(_soldier);\n\tadd(_btnQuickSearch, \"textItem\", \"inventory\");\n\tadd(_txtNameStatic, \"textName\", \"inventory\", _bg);\n\tadd(_txtName, \"textName\", \"inventory\", _bg);\n\tadd(_txtTus, \"textTUs\", \"inventory\", _bg);\n\tadd(_txtWeight, \"textWeight\", \"inventory\", _bg);\n\tadd(_txtStatLine1, \"textStatLine1\", \"inventory\", _bg);\n\tadd(_txtStatLine2, \"textStatLine2\", \"inventory\", _bg);\n\tadd(_txtStatLine3, \"textStatLine3\", \"inventory\", _bg);\n\tadd(_txtStatLine4, \"textStatLine4\", \"inventory\", _bg);\n\tadd(_txtItem, \"textItem\", \"inventory\", _bg);\n\tadd(_txtAmmo, \"textAmmo\", \"inventory\", _bg);\n\tadd(_btnOk, \"buttonOK\", \"inventory\", _bg);\n\tadd(_btnPrev, \"buttonPrev\", \"inventory\", _bg);\n\tadd(_btnNext, \"buttonNext\", \"inventory\", _bg);\n\tadd(_btnUnload, \"buttonUnload\", \"inventory\", _bg);\n\tadd(_btnGround, \"buttonGround\", \"inventory\", _bg);\n\tadd(_btnRank, \"rank\", \"inventory\", _bg);\n\tadd(_btnCreateTemplate, \"buttonCreate\", \"inventory\", _bg);\n\tadd(_btnApplyTemplate, \"buttonApply\", \"inventory\", _bg);\n\tadd(_btnLinks, \"buttonLinks\", \"inventory\", _bg);\n\tadd(_selAmmo);\n\tadd(_inv);\n\tadd(_txtPosition, \"textSlot\", \"inventory\", _bg);\n\n\t// move the TU display down to make room for the weight display\n\tif (Options::showMoreStatsInInventoryView)\n\t{\n\t\t_txtTus->setY(_txtTus->getY() + 8);\n\t}\n\n\tcenterAllSurfaces();\n\n\n\t_txtPosition->setHighContrast(true);\n\n\t_txtNameStatic->setBig();\n\t_txtNameStatic->setHighContrast(true);\n\n\t_txtName->setBig();\n\t_txtName->setHighContrast(true);\n\t_txtName->onChange((ActionHandler)&InventoryState::edtSoldierChange);\n\t_txtName->onMousePress((ActionHandler)&InventoryState::edtSoldierPress);\n\n\tif (Options::oxceLinksDisableTextEdit)\n\t{\n\t\t_txtName->setVisible(false);\n\t}\n\telse\n\t{\n\t\t_txtNameStatic->setVisible(false);\n\t}\n\n\t_txtTus->setHighContrast(true);\n\n\t_txtWeight->setHighContrast(true);\n\n\t_txtStatLine1->setHighContrast(true);\n\n\t_txtStatLine2->setHighContrast(true);\n\n\t_txtStatLine3->setHighContrast(true);\n\n\t_txtStatLine4->setHighContrast(true);\n\n\t_txtItem->setHighContrast(true);\n\n\t_txtAmmo->setAlign(ALIGN_CENTER);\n\t_txtAmmo->setHighContrast(true);\n\n\t_btnOk->onMouseClick((ActionHandler)&InventoryState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&InventoryState::btnOkClick, Options::keyCancel);\n\t_btnOk->onKeyboardPress((ActionHandler)&InventoryState::btnOkClick, Options::keyBattleInventory);\n\t_btnOk->onKeyboardPress((ActionHandler)&InventoryState::btnUfopaediaClick, Options::keyGeoUfopedia);\n\t_btnOk->onKeyboardPress((ActionHandler)&InventoryState::btnArmorClick, Options::keyInventoryArmor);\n\t_btnOk->onKeyboardPress((ActionHandler)&InventoryState::btnArmorClickRight, Options::keyInventoryAvatar);\n\t_btnOk->onKeyboardPress((ActionHandler)&InventoryState::btnInventoryLoadClick, Options::keyInventoryLoad);\n\t_btnOk->onKeyboardPress((ActionHandler)&InventoryState::btnInventorySaveClick, Options::keyInventorySave);\n\t_btnOk->onKeyboardPress((ActionHandler)&InventoryState::btnCreatePersonalTemplateClick, Options::keyInvSavePersonalEquipment);\n\t_btnOk->onKeyboardPress((ActionHandler)&InventoryState::btnApplyPersonalTemplateClick, Options::keyInvLoadPersonalEquipment);\n\t_btnOk->onKeyboardPress((ActionHandler)&InventoryState::btnShowPersonalTemplateClick, Options::keyInvShowPersonalEquipment);\n\t_btnOk->onKeyboardPress((ActionHandler)&InventoryState::btnDiaryLightClick, Options::keyInventoryDiaryLight);\n\t_btnOk->setTooltip(\"STR_OK\");\n\t_btnOk->onMouseIn((ActionHandler)&InventoryState::txtTooltipInExtraOK);\n\t_btnOk->onMouseOut((ActionHandler)&InventoryState::txtTooltipOut);\n\t_btnOk->onKeyboardPress((ActionHandler)&InventoryState::invMouseOver, SDLK_LALT);\n\t_btnOk->onKeyboardRelease((ActionHandler)&InventoryState::invMouseOver, SDLK_LALT);\n\t_btnOk->onKeyboardPress((ActionHandler)&InventoryState::invMouseOver, SDLK_RALT);\n\t_btnOk->onKeyboardRelease((ActionHandler)&InventoryState::invMouseOver, SDLK_RALT);\n\n\t_btnPrev->onMouseClick((ActionHandler)&InventoryState::btnPrevClick);\n\t_btnPrev->onKeyboardPress((ActionHandler)&InventoryState::btnPrevClick, Options::keyBattlePrevUnit);\n\t_btnPrev->setTooltip(\"STR_PREVIOUS_UNIT\");\n\t_btnPrev->onMouseIn((ActionHandler)&InventoryState::txtTooltipIn);\n\t_btnPrev->onMouseOut((ActionHandler)&InventoryState::txtTooltipOut);\n\n\t_btnNext->onMouseClick((ActionHandler)&InventoryState::btnNextClick);\n\t_btnNext->onKeyboardPress((ActionHandler)&InventoryState::btnNextClick, Options::keyBattleNextUnit);\n\t_btnNext->setTooltip(\"STR_NEXT_UNIT\");\n\t_btnNext->onMouseIn((ActionHandler)&InventoryState::txtTooltipIn);\n\t_btnNext->onMouseOut((ActionHandler)&InventoryState::txtTooltipOut);\n\n\t_btnUnload->onMouseClick((ActionHandler)&InventoryState::btnUnloadClick);\n\t_btnUnload->setTooltip(\"STR_UNLOAD_WEAPON\");\n\t_btnUnload->onMouseIn((ActionHandler)&InventoryState::txtTooltipIn);\n\t_btnUnload->onMouseOut((ActionHandler)&InventoryState::txtTooltipOut);\n\n\t_btnGround->onMouseClick((ActionHandler)&InventoryState::btnGroundClickForward, SDL_BUTTON_LEFT);\n\t_btnGround->onMouseClick((ActionHandler)&InventoryState::btnGroundClickBackward, SDL_BUTTON_RIGHT);\n\t_btnGround->setTooltip(\"STR_SCROLL_RIGHT\");\n\t_btnGround->onMouseIn((ActionHandler)&InventoryState::txtTooltipIn);\n\t_btnGround->onMouseOut((ActionHandler)&InventoryState::txtTooltipOut);\n\t_btnGround->onKeyboardPress((ActionHandler)&InventoryState::btnGroundClickBackward, Options::keyBattleLeft);\n\t_btnGround->onKeyboardPress((ActionHandler)&InventoryState::btnGroundClickForward, Options::keyBattleRight);\n\n\t_btnRank->onMouseClick((ActionHandler)&InventoryState::btnRankClick);\n\t_btnRank->setTooltip(\"STR_UNIT_STATS\");\n\t_btnRank->onMouseIn((ActionHandler)&InventoryState::txtTooltipIn);\n\t_btnRank->onMouseOut((ActionHandler)&InventoryState::txtTooltipOut);\n\n\tif (!_game->getMod()->getInventoryOverlapsPaperdoll())\n\t{\n\t\t_btnArmor->onMouseClick((ActionHandler)&InventoryState::btnArmorClick);\n\t\t_btnArmor->onMouseClick((ActionHandler)&InventoryState::btnArmorClickRight, SDL_BUTTON_RIGHT);\n\t\t_btnArmor->onMouseClick((ActionHandler)&InventoryState::btnArmorClickMiddle, SDL_BUTTON_MIDDLE);\n\t\t_btnArmor->onMouseIn((ActionHandler)&InventoryState::txtArmorTooltipIn);\n\t\t_btnArmor->onMouseOut((ActionHandler)&InventoryState::txtArmorTooltipOut);\n\t}\n\n\t_btnCreateTemplate->onMouseClick((ActionHandler)&InventoryState::btnCreateTemplateClick);\n\t_btnCreateTemplate->onKeyboardPress((ActionHandler)&InventoryState::btnCreateTemplateClick, Options::keyInvCreateTemplate);\n\t_btnCreateTemplate->setTooltip(\"STR_CREATE_INVENTORY_TEMPLATE\");\n\t_btnCreateTemplate->onMouseIn((ActionHandler)&InventoryState::txtTooltipIn);\n\t_btnCreateTemplate->onMouseOut((ActionHandler)&InventoryState::txtTooltipOut);\n\n\t_btnApplyTemplate->onMouseClick((ActionHandler)&InventoryState::btnApplyTemplateClick);\n\t_btnApplyTemplate->onKeyboardPress((ActionHandler)&InventoryState::btnApplyTemplateClick, Options::keyInvApplyTemplate);\n\t_btnApplyTemplate->onKeyboardPress((ActionHandler)&InventoryState::onClearInventory, Options::keyInvClear);\n\t_btnApplyTemplate->onKeyboardPress((ActionHandler)&InventoryState::onAutoequip, Options::keyInvAutoEquip);\n\t_btnApplyTemplate->setTooltip(\"STR_APPLY_INVENTORY_TEMPLATE\");\n\t_btnApplyTemplate->onMouseIn((ActionHandler)&InventoryState::txtTooltipIn);\n\t_btnApplyTemplate->onMouseOut((ActionHandler)&InventoryState::txtTooltipOut);\n\n\t_btnLinks->onMouseClick((ActionHandler)&InventoryState::btnLinksClick);\n\t_btnLinks->setTooltip(\"STR_EXTENDED_LINKS\");\n\t_btnLinks->onMouseIn((ActionHandler)&InventoryState::txtTooltipIn);\n\t_btnLinks->onMouseOut((ActionHandler)&InventoryState::txtTooltipOut);\n\n\t_btnQuickSearch->setHighContrast(true);\n\t_btnQuickSearch->setText(\"\"); // redraw\n\t_btnQuickSearch->onEnter((ActionHandler)&InventoryState::btnQuickSearchApply);\n\t_btnQuickSearch->setVisible(Options::oxceQuickSearchButton);\n\n\t_btnOk->onKeyboardRelease((ActionHandler)&InventoryState::btnQuickSearchToggle, Options::keyToggleQuickSearch);\n\n\t_game->getMod()->getSurface(\"oxceLinksInv\")->blitNShade(_btnLinks, 0, 0);\n\t_btnLinks->initSurfaces();\n\t_btnLinks->setVisible(Options::oxceLinks);\n\n\t// only use copy/paste buttons in setup (i.e. non-tu) mode\n\tif (_tu)\n\t{\n\t\t_btnCreateTemplate->setVisible(false);\n\t\t_btnApplyTemplate->setVisible(false);\n\t}\n\telse\n\t{\n\t\tupdateTemplateButtons(true);\n\t}\n\n\t_inv->draw();\n\t_inv->setTuMode(_tu);\n\t_inv->setSelectedUnit(_game->getSavedGame()->getSavedBattle()->getSelectedUnit(), true);\n\t_inv->onMouseClick((ActionHandler)&InventoryState::invClick, 0);\n\t_inv->onMouseOver((ActionHandler)&InventoryState::invMouseOver);\n\t_inv->onMouseOut((ActionHandler)&InventoryState::invMouseOut);\n\n\tif (_battleGame->getDebugMode() && _game->isShiftPressed())\n\t{\n\t\t// replenish TUs\n\t\tauto* unit = _inv->getSelectedUnit();\n\t\tif (unit)\n\t\t{\n\t\t\tint missingTUs = unit->getBaseStats()->tu - unit->getTimeUnits();\n\t\t\tunit->spendTimeUnits(-missingTUs);\n\t\t}\n\t}\n\n\t_txtTus->setVisible(_tu);\n\t_txtWeight->setVisible(Options::showMoreStatsInInventoryView);\n\t_txtStatLine1->setVisible(Options::showMoreStatsInInventoryView && !_tu);\n\t_txtStatLine2->setVisible(Options::showMoreStatsInInventoryView && !_tu);\n\t_txtStatLine3->setVisible(Options::showMoreStatsInInventoryView && !_tu);\n\t_txtStatLine4->setVisible(Options::showMoreStatsInInventoryView && !_tu);\n}\n\nstatic void _clearInventoryTemplate(std::vector<EquipmentLayoutItem*> &inventoryTemplate)\n{\n\tCollections::deleteAll(inventoryTemplate);\n}\n\n/**\n *\n */\nInventoryState::~InventoryState()\n{\n\t_clearInventoryTemplate(_curInventoryTemplate);\n\t_clearInventoryTemplate(_tempInventoryTemplate);\n\n\tif (!_battleGame->isBaseCraftInventory())\n\t{\n\t\tif (Options::maximizeInfoScreens)\n\t\t{\n\t\t\tScreen::updateScale(Options::battlescapeScale, Options::baseXBattlescape, Options::baseYBattlescape, true);\n\t\t\t_game->getScreen()->resetDisplay(false);\n\t\t}\n\n\t\t//fix case when scripts could kill unit before inventory is closed\n\t\tif (BattleUnit* unit =_battleGame->getSelectedUnit())\n\t\t{\n\t\t\tTile *inventoryTile = unit->getTile();\n\t\t\t_battleGame->getTileEngine()->applyGravity(inventoryTile);\n\t\t}\n\t\t_battleGame->getTileEngine()->calculateLighting(LL_ITEMS); // dropping/picking up flares\n\t\t_battleGame->getTileEngine()->recalculateFOV();\n\t}\n\telse\n\t{\n\t\tScreen::updateScale(Options::geoscapeScale, Options::baseXGeoscape, Options::baseYGeoscape, true);\n\t\t_game->getScreen()->resetDisplay(false);\n\t}\n}\n\nvoid InventoryState::setGlobalLayoutIndex(int index, bool armorChanged)\n{\n\t_globalLayoutIndex = index;\n\tif (armorChanged)\n\t{\n\t\t_reloadUnit = true;\n\t}\n}\n\n/**\n * Updates all soldier stats when the soldier changes.\n */\nvoid InventoryState::init()\n{\n\tState::init();\n\tBattleUnit *unit = _battleGame->getSelectedUnit();\n\n\t// no selected unit, close inventory\n\tif (unit == 0)\n\t{\n\t\tbtnOkClick(0);\n\t\treturn;\n\t}\n\t// skip to the first unit with inventory\n\tif (!unit->hasInventory())\n\t{\n\t\tif (_parent)\n\t\t{\n\t\t\t_parent->selectNextPlayerUnit(false, false, true, _tu);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_battleGame->selectNextPlayerUnit(false, false, true);\n\t\t}\n\t\t// no available unit, close inventory\n\t\tif (_battleGame->getSelectedUnit() == 0 || !_battleGame->getSelectedUnit()->hasInventory())\n\t\t{\n\t\t\t// starting a mission with just vehicles\n\t\t\tbtnOkClick(0);\n\t\t\treturn;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tunit = _battleGame->getSelectedUnit();\n\t\t}\n\t}\n\n\t_soldier->clear();\n\t_btnRank->clear();\n\n\tif (Options::oxceInventoryShowUnitSlot)\n\t{\n\t\tint unitSlot = 1;\n\t\tint totalSlots = 99;\n\t\tfor (auto* tmpUnit : *_battleGame->getUnits())\n\t\t{\n\t\t\tif (tmpUnit == unit)\n\t\t\t{\n\t\t\t\tif (!_noCraft && _battleGame->getMissionType() != \"STR_BASE_DEFENSE\")\n\t\t\t\t{\n\t\t\t\t\tauto* tmpCraft = unit->getGeoscapeSoldier() ? unit->getGeoscapeSoldier()->getCraft() : nullptr;\n\t\t\t\t\tif (tmpCraft)\n\t\t\t\t\t{\n\t\t\t\t\t\ttotalSlots = tmpCraft->getMaxUnitsClamped();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tunitSlot += tmpUnit->getArmor()->getTotalSize();\n\t\t}\n\t\t_txtPosition->setText(tr(\"STR_SLOT\").arg(unitSlot).arg(totalSlots));\n\t}\n\n\t_txtNameStatic->setBig();\n\t_txtNameStatic->setText(unit->getName(_game->getLanguage()));\n\n\t_txtName->setBig();\n\t_txtName->setText(unit->getName(_game->getLanguage()));\n\n\t_btnLinks->setVisible(Options::oxceLinks);\n\n\tbool resetGroundOffset = _tu;\n\tif (unit->isSummonedPlayerUnit())\n\t{\n\t\tresetGroundOffset = true; // this unit is likely not standing on the shared inventory tile, just re-arrange it every time\n\t}\n\t_inv->setSelectedUnit(unit, resetGroundOffset);\n\tSoldier *s = unit->getGeoscapeSoldier();\n\tif (s)\n\t{\n\t\t// reload necessary after the change of armor\n\t\tif (_reloadUnit)\n\t\t{\n\t\t\tif (Options::oxceAlternateCraftEquipmentManagement && s->getArmor() && unit->getArmor() && s->getArmor()->getSize() > unit->getArmor()->getSize())\n\t\t\t{\n\t\t\t\t_resetCustomDeploymentBackup = true;\n\t\t\t}\n\n\t\t\t// Step 0: update unit's armor\n\t\t\tunit->updateArmorFromSoldier(_game->getMod(), s, s->getArmor(), _battleGame->getDepth(), false, nullptr);\n\n\t\t\t// Step 1: remember the unit's equipment (incl. loaded fixed items)\n\t\t\t_clearInventoryTemplate(_tempInventoryTemplate);\n\t\t\t_createInventoryTemplate(_tempInventoryTemplate);\n\n\t\t\t// Step 2: drop all items (and delete fixed items!!)\n\t\t\tTile *groundTile = unit->getTile();\n\t\t\t_battleGame->getTileEngine()->itemDropInventory(groundTile, unit, true, true);\n\n\t\t\t// Step 3: equip fixed items // Note: the inventory must be *completely* empty before this step\n\t\t\t_battleGame->initUnit(unit);\n\n\t\t\t// Step 4: re-equip original items (unless slots taken by fixed items)\n\t\t\t_applyInventoryTemplate(_tempInventoryTemplate);\n\n\t\t\t// refresh ui\n\t\t\t_inv->arrangeGround(); // calls drawItems() too\n\n\t\t\t// reset armor tooltip\n\t\t\t_currentTooltip = \"\";\n\t\t\t_txtItem->setText(\"\");\n\n\t\t\t// reload done\n\t\t\t_reloadUnit = false;\n\t\t}\n\n\t\tSurfaceSet *texture = _game->getMod()->getSurfaceSet(\"SMOKE.PCK\");\n\t\tauto* frame = texture->getFrame(s->getRankSpriteBattlescape());\n\t\tif (frame)\n\t\t{\n\t\t\tframe->blitNShade(_btnRank, 0, 0);\n\t\t}\n\n\t\tif (s->getArmor()->hasLayersDefinition())\n\t\t{\n\t\t\tfor (const auto& layer : s->getArmorLayers())\n\t\t\t{\n\t\t\t\t_game->getMod()->getSurface(layer, true)->blitNShade(_soldier, 0, 0);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tconst std::string look = s->getArmor()->getSpriteInventory();\n\t\t\tconst std::string gender = s->getGender() == GENDER_MALE ? \"M\" : \"F\";\n\t\t\tSurface *surf = 0;\n\t\t\tstd::stringstream ss;\n\n\t\t\tfor (int i = 0; i <= RuleSoldier::LookVariantBits; ++i)\n\t\t\t{\n\t\t\t\tss.str(\"\");\n\t\t\t\tss << look;\n\t\t\t\tss << gender;\n\t\t\t\tss << (int)s->getLook() + (s->getLookVariant() & (RuleSoldier::LookVariantMask >> i)) * 4;\n\t\t\t\tss << \".SPK\";\n\t\t\t\tsurf = _game->getMod()->getSurface(ss.str(), false);\n\t\t\t\tif (surf)\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!surf)\n\t\t\t{\n\t\t\t\tss.str(\"\");\n\t\t\t\tss << look;\n\t\t\t\tss << \".SPK\";\n\t\t\t\tsurf = _game->getMod()->getSurface(ss.str(), false);\n\t\t\t}\n\t\t\tif (!surf)\n\t\t\t{\n\t\t\t\tsurf = _game->getMod()->getSurface(look, true);\n\t\t\t}\n\t\t\tsurf->blitNShade(_soldier, 0, 0);\n\t\t}\n\t}\n\telse\n\t{\n\t\tSurface *armorSurface = _game->getMod()->getSurface(unit->getArmor()->getSpriteInventory(), false);\n\t\tif (!armorSurface)\n\t\t{\n\t\t\tarmorSurface = _game->getMod()->getSurface(unit->getArmor()->getSpriteInventory() + \".SPK\", false);\n\t\t}\n\t\tif (!armorSurface)\n\t\t{\n\t\t\tarmorSurface = _game->getMod()->getSurface(unit->getArmor()->getSpriteInventory() + \"M0.SPK\", false);\n\t\t}\n\t\tif (armorSurface)\n\t\t{\n\t\t\tarmorSurface->blitNShade(_soldier, 0, 0);\n\t\t}\n\t}\n\n\t// coming from InventoryLoad window...\n\tif (_globalLayoutIndex > -1)\n\t{\n\t\tloadGlobalLayout((_globalLayoutIndex));\n\t\t_globalLayoutIndex = -1;\n\n\t\t// refresh ui\n\t\t_inv->arrangeGround();\n\t}\n\n\tupdateStats();\n\trefreshMouse();\n}\n\n/**\n * Disables the input, if not a soldier. Sets the name without a statstring otherwise.\n * @param action Pointer to an action.\n */\nvoid InventoryState::edtSoldierPress(Action *action)\n{\n\tif (_btnLinks->getVisible())\n\t{\n\t\tdouble mx = action->getAbsoluteXMouse();\n\t\tif (mx >= _btnLinks->getX())\n\t\t{\n\t\t\t_txtName->setFocus(false);\n\t\t\treturn;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_btnLinks->setVisible(false);\n\t\t}\n\t}\n\n\t{\n\t\tBattleUnit *unit = _inv->getSelectedUnit();\n\t\tif (unit != 0)\n\t\t{\n\t\t\tSoldier *s = unit->getGeoscapeSoldier();\n\t\t\tif (s)\n\t\t\t{\n\t\t\t\t// set the soldier's name without a statstring\n\t\t\t\t_txtName->setText(s->getName());\n\t\t\t}\n\n\t\t}\n\t}\n}\n\n/**\n * Changes the soldier's name.\n * @param action Pointer to an action.\n */\nvoid InventoryState::edtSoldierChange(Action *)\n{\n\tBattleUnit *unit = _inv->getSelectedUnit();\n\tif (unit != 0)\n\t{\n\t\tSoldier *s = unit->getGeoscapeSoldier();\n\t\tif (s)\n\t\t{\n\t\t\t// set the soldier's name\n\t\t\ts->setName(_txtName->getText());\n\t\t\t// also set the unit's name (with a statstring)\n\t\t\tunit->setName(s->getName(true));\n\t\t}\n\t}\n}\n\n/**\n * Updates the soldier stats (Weight, TU).\n */\nvoid InventoryState::updateStats()\n{\n\tBattleUnit *unit = _battleGame->getSelectedUnit();\n\n\t_txtTus->setText(tr(\"STR_TIME_UNITS_SHORT\").arg(unit->getTimeUnits()));\n\n\tint weight = unit->getCarriedWeight(_inv->getSelectedItem());\n\t_txtWeight->setText(tr(\"STR_WEIGHT\").arg(weight).arg(unit->getBaseStats()->strength));\n\tif (weight > unit->getBaseStats()->strength)\n\t{\n\t\t_txtWeight->setSecondaryColor(_game->getMod()->getInterface(\"inventory\")->getElement(\"weight\")->color2);\n\t}\n\telse\n\t{\n\t\t_txtWeight->setSecondaryColor(_game->getMod()->getInterface(\"inventory\")->getElement(\"weight\")->color);\n\t}\n\n\tauto psiSkillWithoutAnyBonuses = unit->getBaseStats()->psiSkill;\n\tif (unit->getGeoscapeSoldier())\n\t{\n\t\tpsiSkillWithoutAnyBonuses = unit->getGeoscapeSoldier()->getCurrentStats()->psiSkill;\n\t}\n\tbool showPsiStrength = (psiSkillWithoutAnyBonuses > 0 || (Options::psiStrengthEval && _game->getSavedGame()->isResearched(_game->getMod()->getPsiRequirements())));\n\n\tauto updateStatLine = [&](Text* txtField, const std::string& elementId)\n\t{\n\t\tconst Element *element = _game->getMod()->getInterface(\"inventory\")->getElementOptional(elementId);\n\t\tif (element)\n\t\t{\n\t\t\tswitch (element->custom)\n\t\t\t{\n\t\t\t\tcase 1:\n\t\t\t\t\ttxtField->setText(tr(\"STR_ACCURACY_SHORT\").arg(unit->getBaseStats()->firing));\n\t\t\t\t\tbreak;\n\t\t\t\tcase 2:\n\t\t\t\t\ttxtField->setText(tr(\"STR_REACTIONS_SHORT\").arg(unit->getBaseStats()->reactions));\n\t\t\t\t\tbreak;\n\t\t\t\tcase 3:\n\t\t\t\t\tif (psiSkillWithoutAnyBonuses > 0)\n\t\t\t\t\t\ttxtField->setText(tr(\"STR_PSIONIC_SKILL_SHORT\").arg(unit->getBaseStats()->psiSkill));\n\t\t\t\t\telse\n\t\t\t\t\t\ttxtField->setText(\"\");\n\t\t\t\t\tbreak;\n\t\t\t\tcase 4:\n\t\t\t\t\tif (showPsiStrength)\n\t\t\t\t\t\ttxtField->setText(tr(\"STR_PSIONIC_STRENGTH_SHORT\").arg(unit->getBaseStats()->psiStrength));\n\t\t\t\t\telse\n\t\t\t\t\t\ttxtField->setText(\"\");\n\t\t\t\t\tbreak;\n\t\t\t\tcase 11:\n\t\t\t\t\ttxtField->setText(tr(\"STR_FIRING_SHORT\").arg(unit->getBaseStats()->firing));\n\t\t\t\t\tbreak;\n\t\t\t\tcase 12:\n\t\t\t\t\ttxtField->setText(tr(\"STR_THROWING_SHORT\").arg(unit->getBaseStats()->throwing));\n\t\t\t\t\tbreak;\n\t\t\t\tcase 13:\n\t\t\t\t\ttxtField->setText(tr(\"STR_MELEE_SHORT\").arg(unit->getBaseStats()->melee));\n\t\t\t\t\tbreak;\n\t\t\t\tcase 14:\n\t\t\t\t\tif (showPsiStrength)\n\t\t\t\t\t{\n\t\t\t\t\t\ttxtField->setText(tr(\"STR_PSI_SHORT\")\n\t\t\t\t\t\t\t.arg(unit->getBaseStats()->psiStrength)\n\t\t\t\t\t\t\t.arg(unit->getBaseStats()->psiSkill > 0 ? unit->getBaseStats()->psiSkill : 0));\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\ttxtField->setText(\"\");\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\ttxtField->setText(\"\");\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t};\n\n\tupdateStatLine(_txtStatLine1, \"textStatLine1\");\n\tupdateStatLine(_txtStatLine2, \"textStatLine2\");\n\tupdateStatLine(_txtStatLine3, \"textStatLine3\");\n\tupdateStatLine(_txtStatLine4, \"textStatLine4\");\n}\n\n/**\n * Saves the soldiers' equipment-layout.\n */\nvoid InventoryState::saveEquipmentLayout()\n{\n\tfor (auto* bu : *_battleGame->getUnits())\n\t{\n\t\t// we need X-Com soldiers only\n\t\tif (bu->getGeoscapeSoldier() == 0) continue;\n\n\t\tstd::vector<EquipmentLayoutItem*> *layoutItems = bu->getGeoscapeSoldier()->getEquipmentLayout();\n\n\t\t// clear the previous save\n\t\tif (!layoutItems->empty())\n\t\t{\n\t\t\tfor (auto* equipmentLayoutItem : *layoutItems)\n\t\t\t{\n\t\t\t\tdelete equipmentLayoutItem;\n\t\t\t}\n\t\t\tlayoutItems->clear();\n\t\t}\n\n\t\t// save the soldier's items\n\t\t// note: with using getInventory() we are skipping the ammos loaded, (they're not owned) because we handle the loaded-ammos separately (inside)\n\t\tfor (auto* bi : *bu->getInventory())\n\t\t{\n\t\t\t// skip fixed items\n\t\t\tif (bi->getRules()->isFixed())\n\t\t\t{\n\t\t\t\tbool loaded = bi->needsAmmoForSlot(0) && bi->getAmmoForSlot(0);\n\t\t\t\tif (!loaded) continue;\n\t\t\t}\n\t\t\telse if (!bi->getRules()->canBeEquippedToCraftInventory())\n\t\t\t{\n\t\t\t\t// skip other not-allowed items, which somehow made it here (e.g. were spawned instead of equipped)\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tlayoutItems->push_back(new EquipmentLayoutItem(bi));\n\t\t}\n\t}\n}\n\n/**\n * Opens the Armor Selection GUI\n * @param action Pointer to an action.\n */\nvoid InventoryState::btnArmorClick(Action *action)\n{\n\t// don't accept clicks when moving items\n\tif (_inv->getSelectedItem() != 0)\n\t{\n\t\t// but we can reuse this for quickly dropping an item (as a Ctrl+L-click alternative)\n\t\tif (Options::oxceInventoryDropItemOverPaperdoll)\n\t\t{\n\t\t\tif (_inv->quickDrop())\n\t\t\t{\n\t\t\t\t// hide selected item info\n\t\t\t\tinvMouseOut(action);\n\n\t\t\t\t// refresh ui\n\t\t\t\t_inv->arrangeGround();\n\t\t\t\tupdateStats();\n\t\t\t\trefreshMouse();\n\n\t\t\t\t// give audio feedback\n\t\t\t\t_game->getMod()->getSoundByDepth(_battleGame->getDepth(), Mod::ITEM_DROP)->play();\n\t\t\t}\n\t\t}\n\t\treturn;\n\t}\n\n\t// only allowed during base equipment\n\tif (_base == 0)\n\t{\n\t\treturn;\n\t}\n\n\t// equipment in the base\n\tBattleUnit *unit = _battleGame->getSelectedUnit();\n\tSoldier *s = unit->getGeoscapeSoldier();\n\n\tif (!(s->getCraft() && s->getCraft()->getStatus() == \"STR_OUT\"))\n\t{\n\t\tsize_t soldierIndex = 0;\n\t\tfor (auto soldierIt = _base->getSoldiers()->begin(); soldierIt != _base->getSoldiers()->end(); ++soldierIt)\n\t\t{\n\t\t\tif ((*soldierIt)->getId() == s->getId())\n\t\t\t{\n\t\t\t\tsoldierIndex = soldierIt - _base->getSoldiers()->begin();\n\t\t\t}\n\t\t}\n\n\t\t_reloadUnit = true;\n\t\t_game->pushState(new SoldierArmorState(_base, soldierIndex, SA_BATTLESCAPE));\n\t}\n}\n\n/**\n * Opens the Avatar Selection GUI\n * @param action Pointer to an action.\n */\nvoid InventoryState::btnArmorClickRight(Action *action)\n{\n\t// don't accept clicks when moving items\n\tif (_inv->getSelectedItem() != 0)\n\t{\n\t\treturn;\n\t}\n\n\t// only allowed during base equipment\n\tif (_base == 0)\n\t{\n\t\treturn;\n\t}\n\n\t// equipment in the base\n\tBattleUnit *unit = _battleGame->getSelectedUnit();\n\tSoldier *s = unit->getGeoscapeSoldier();\n\n\tif (!(s->getCraft() && s->getCraft()->getStatus() == \"STR_OUT\"))\n\t{\n\t\tsize_t soldierIndex = 0;\n\t\tfor (auto soldierIt = _base->getSoldiers()->begin(); soldierIt != _base->getSoldiers()->end(); ++soldierIt)\n\t\t{\n\t\t\tif ((*soldierIt)->getId() == s->getId())\n\t\t\t{\n\t\t\t\tsoldierIndex = soldierIt - _base->getSoldiers()->begin();\n\t\t\t}\n\t\t}\n\n\t\t_game->pushState(new SoldierAvatarState(_base, soldierIndex));\n\t}\n}\n\n/**\n * Opens the Soldier Diary Light GUI\n * @param action Pointer to an action.\n */\nvoid InventoryState::btnDiaryLightClick(Action *action)\n{\n\t// don't accept clicks when moving items\n\tif (_inv->getSelectedItem() != 0)\n\t{\n\t\treturn;\n\t}\n\n\tBattleUnit* unit = _battleGame->getSelectedUnit();\n\tSoldier* s = unit->getGeoscapeSoldier();\n\t_game->pushState(new SoldierDiaryLightState(s));\n}\n\n/**\n* Opens Ufopaedia entry for the corresponding armor.\n* @param action Pointer to an action.\n*/\nvoid InventoryState::btnArmorClickMiddle(Action *action)\n{\n\t// don't accept clicks when moving items\n\tif (_inv->getSelectedItem() != 0)\n\t{\n\t\treturn;\n\t}\n\n\tBattleUnit *unit = _inv->getSelectedUnit();\n\tif (unit != 0)\n\t{\n\t\tstd::string articleId = unit->getArmor()->getUfopediaType();\n\t\tUfopaedia::openArticle(_game, articleId);\n\t}\n}\n\nvoid InventoryState::saveGlobalLayout(int index, bool includingArmor)\n{\n\tstd::vector<EquipmentLayoutItem*> *tmpl = _game->getSavedGame()->getGlobalEquipmentLayout(index);\n\n\t// clear current template\n\t_clearInventoryTemplate(*tmpl);\n\n\t// create new template\n\t_createInventoryTemplate(*tmpl);\n\n\t// optionally save armor info too\n\tif (includingArmor && _battleGame->getSelectedUnit()->getGeoscapeSoldier())\n\t{\n\t\t_game->getSavedGame()->setGlobalEquipmentLayoutArmor(index, _battleGame->getSelectedUnit()->getArmor()->getType());\n\t}\n\telse\n\t{\n\t\t_game->getSavedGame()->setGlobalEquipmentLayoutArmor(index, std::string());\n\t}\n}\n\nvoid InventoryState::loadGlobalLayout(int index)\n{\n\tstd::vector<EquipmentLayoutItem*> *tmpl = _game->getSavedGame()->getGlobalEquipmentLayout(index);\n\n\t_applyInventoryTemplate(*tmpl);\n}\n\nbool InventoryState::loadGlobalLayoutArmor(int index)\n{\n\tauto& armorName = _game->getSavedGame()->getGlobalEquipmentLayoutArmor(index);\n\treturn tryArmorChange(armorName);\n}\n\nbool InventoryState::tryArmorChange(const std::string& armorName)\n{\n\tArmor* prev = nullptr;\n\tSoldier* soldier = nullptr;\n\tBattleUnit* unit = _inv->getSelectedUnit();\n\tif (unit)\n\t{\n\t\tsoldier = unit->getGeoscapeSoldier();\n\t\tif (soldier)\n\t\t{\n\t\t\tprev = soldier->getArmor();\n\t\t}\n\t}\n\n\tArmor* next = nullptr;\n\t{\n\t\tnext = _game->getMod()->getArmor(armorName, false);\n\t}\n\n\t// check armor availability\n\tbool armorAvailable = false;\n\tif (prev && next && next != prev && soldier && _base)\n\t{\n\t\tarmorAvailable = true;\n\t\tif (_game->getSavedGame()->getMonthsPassed() != -1)\n\t\t{\n\t\t\t// is the armor physically available?\n\t\t\tif (next->getStoreItem() && prev->getStoreItem() != next->getStoreItem())\n\t\t\t{\n\t\t\t\tif (_base->getStorageItems()->getItem(next->getStoreItem()) <= 0)\n\t\t\t\t{\n\t\t\t\t\tarmorAvailable = false;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// is the armor unlocked?\n\t\t\tif (next->getRequiredResearch() && !_game->getSavedGame()->isResearched(next->getRequiredResearch()))\n\t\t\t{\n\t\t\t\tarmorAvailable = false;\n\t\t\t}\n\t\t}\n\t\tif (armorAvailable)\n\t\t{\n\t\t\t// refresh soldier's _bonusCache, needed below in Armor::getCanBeUsedBy()\n\t\t\t//soldier->getBonuses(_game->getMod());\n\n\t\t\t// does the armor fit on the current unit?\n\t\t\tif (!next->getCanBeUsedBy(soldier))\n\t\t\t{\n\t\t\t\tarmorAvailable = false;\n\t\t\t}\n\t\t}\n\t}\n\n\t// change armor\n\tbool armorChanged = false;\n\tif (armorAvailable)\n\t{\n\t\tCraft* craft = soldier->getCraft();\n\t\tif (craft)\n\t\t{\n\t\t\tif (!craft->validateArmorChange(prev->getSize(), next->getSize()))\n\t\t\t{\n\t\t\t\t// STR_NOT_ENOUGH_CRAFT_SPACE\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\tif (_game->getSavedGame()->getMonthsPassed() != -1)\n\t\t{\n\t\t\tif (prev->getStoreItem())\n\t\t\t{\n\t\t\t\t_base->getStorageItems()->addItem(prev->getStoreItem());\n\t\t\t}\n\t\t\tif (next->getStoreItem())\n\t\t\t{\n\t\t\t\t_base->getStorageItems()->removeItem(next->getStoreItem());\n\t\t\t}\n\t\t}\n\t\tif (Options::oxceAlternateCraftEquipmentManagement && next->getSize() > prev->getSize())\n\t\t{\n\t\t\t_resetCustomDeploymentBackup = true;\n\t\t}\n\t\tsoldier->setArmor(next, true);\n\t\tarmorChanged = true;\n\t}\n\n\treturn armorChanged;\n}\n\n/**\n* Handles global equipment layout actions.\n* @param action Pointer to an action.\n*/\nvoid InventoryState::btnGlobalEquipmentLayoutClick(Action *action)\n{\n\t// cannot use this feature during the mission!\n\tif (_tu)\n\t{\n\t\treturn;\n\t}\n\n\t// don't accept clicks when moving items\n\tif (_inv->getSelectedItem() != 0)\n\t{\n\t\treturn;\n\t}\n\n\t// SDLK_0 = 48, SDLK_1 = 49, SDLK_9 = 57\n\t// SDLK_0 selects the 10-th inventory layout\n\t// by repeating a key you can load a layout from the next decade\n\tconst int sym = action->getDetails()->key.keysym.sym;\n\tconst int layout_no = (sym == 48) ? 10 : sym - 48;\n\n\tif (sym == _prev_key && !_game->isCtrlPressed())\n\t{\n\t\t_key_repeats++;\n\t}\n\telse\n\t{\n\t\t_key_repeats = 0;\n\t}\n\t_prev_key = sym;\n\n\tconst int index = 10 * _key_repeats + layout_no - 1;\n\n\tif (index < 0 || index >= Options::oxceMaxEquipmentLayoutTemplates)\n\t{\n\t\t// do nothing if the layout index is out of bounds\n\t\treturn;\n\t}\n\n\tif (_game->isCtrlPressed())\n\t{\n\t\t// can't save layout >10 this way\n\t\t_prev_key = 0, _key_repeats = 0;\n\t\tsaveGlobalLayout(index, false);\n\n\t\t// give audio feedback\n\t\t_game->getMod()->getSoundByDepth(_battleGame->getDepth(), Mod::ITEM_DROP)->play();\n\t\trefreshMouse();\n\t}\n\telse\n\t{\n\t\t// simulate what happens when loading via the InventoryLoadState dialog\n\t\tbool armorChanged = loadGlobalLayoutArmor(index);\n\t\tsetGlobalLayoutIndex(index, armorChanged);\n\t\tinit();\n\n\t\t// give audio feedback\n\t\t_game->getMod()->getSoundByDepth(_battleGame->getDepth(), Mod::ITEM_DROP)->play();\n\t}\n}\n\n/**\n* Opens the InventoryLoad screen.\n* @param action Pointer to an action.\n*/\nvoid InventoryState::btnInventoryLoadClick(Action *)\n{\n\t// cannot use this feature during the mission!\n\tif (_tu)\n\t{\n\t\treturn;\n\t}\n\n\t// don't accept clicks when moving items\n\tif (_inv->getSelectedItem() != 0)\n\t{\n\t\treturn;\n\t}\n\n\t_game->pushState(new InventoryLoadState(this));\n}\n\n/**\n* Opens the InventorySave screen.\n* @param action Pointer to an action.\n*/\nvoid InventoryState::btnInventorySaveClick(Action *)\n{\n\t// don't accept clicks when moving items\n\tif (_inv->getSelectedItem() != 0)\n\t{\n\t\treturn;\n\t}\n\n\t_game->pushState(new InventorySaveState(this));\n}\n\n/**\n * Opens the Ufopaedia.\n * @param action Pointer to an action.\n */\nvoid InventoryState::btnUfopaediaClick(Action *)\n{\n\t// don't accept clicks when moving items\n\tif (_inv->getSelectedItem() != 0)\n\t{\n\t\treturn;\n\t}\n\n\tUfopaedia::open(_game);\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid InventoryState::btnOkClick(Action *)\n{\n\tif (_inv->getSelectedItem() != 0)\n\t\treturn;\n\t_game->popState();\n\tif (!_tu)\n\t{\n\t\tif (_base || !Options::oxceAlternateCraftEquipmentManagement)\n\t\t{\n\t\t\tsaveEquipmentLayout();\n\t\t}\n\t\tif (Options::oxceAlternateCraftEquipmentManagement && !_tu && _base && _noCraft)\n\t\t{\n\t\t\t// assign all soldiers back, if possible\n\t\t\tfor (auto* soldier : *_base->getSoldiers())\n\t\t\t{\n\t\t\t\tCraft* c = _backup[soldier];\n\t\t\t\tif (!soldier->getCraft() && c && c->getStatus() != \"STR_OUT\")\n\t\t\t\t{\n\t\t\t\t\tint space = c->getSpaceAvailable();\n\t\t\t\t\tif (c->validateAddingSoldier(space, soldier) == CPE_None)\n\t\t\t\t\t{\n\t\t\t\t\t\tsoldier->setCraftAndMoveEquipment(c, _base, _game->getSavedGame()->getMonthsPassed() == -1, _resetCustomDeploymentBackup);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (_parent)\n\t\t{\n\t\t\t_battleGame->startFirstTurn();\n\t\t}\n\t}\n}\n\n/**\n * Selects the previous soldier.\n * @param action Pointer to an action.\n */\nvoid InventoryState::btnPrevClick(Action *)\n{\n\tif (_inv->getSelectedItem() != 0)\n\t{\n\t\treturn;\n\t}\n\n\tif (_parent)\n\t{\n\t\t_parent->selectPreviousPlayerUnit(false, false, true);\n\t}\n\telse\n\t{\n\t\t_battleGame->selectPreviousPlayerUnit(false, false, true);\n\t}\n\tinit();\n}\n\n/**\n * Selects the next soldier.\n * @param action Pointer to an action.\n */\nvoid InventoryState::btnNextClick(Action *)\n{\n\tif (_inv->getSelectedItem() != 0)\n\t{\n\t\treturn;\n\t}\n\tif (_parent)\n\t{\n\t\t_parent->selectNextPlayerUnit(false, false, true);\n\t}\n\telse\n\t{\n\t\t_battleGame->selectNextPlayerUnit(false, false, true);\n\t}\n\tinit();\n}\n\n/**\n * Unloads the selected weapon.\n * @param action Pointer to an action.\n */\nvoid InventoryState::btnUnloadClick(Action *)\n{\n\tif (_inv->unload(false))\n\t{\n\t\t_txtItem->setText(\"\");\n\t\t_txtAmmo->setText(\"\");\n\t\t_selAmmo->clear();\n\t\tupdateStats();\n\t\t_game->getMod()->getSoundByDepth(0, Mod::ITEM_DROP)->play();\n\t}\n}\n\n/**\n* Quick search toggle.\n* @param action Pointer to an action.\n*/\nvoid InventoryState::btnQuickSearchToggle(Action *action)\n{\n\tif (_btnQuickSearch->getVisible())\n\t{\n\t\t_btnQuickSearch->setText(\"\");\n\t\t_btnQuickSearch->setVisible(false);\n\t\tbtnQuickSearchApply(action);\n\t}\n\telse\n\t{\n\t\t_btnQuickSearch->setVisible(true);\n\t\t_btnQuickSearch->setFocus(true);\n\t}\n}\n\n/**\n* Quick search.\n* @param action Pointer to an action.\n*/\nvoid InventoryState::btnQuickSearchApply(Action *)\n{\n\t_inv->setSearchString(_btnQuickSearch->getText());\n}\n\n/**\n * Shows more ground items / rearranges them.\n * @param action Pointer to an action.\n */\nvoid InventoryState::btnGroundClickForward(Action *action)\n{\n\tbool scrollBackwards = _game->isShiftPressed();\n\tif (Options::oxceInventorySplitScrollButton)\n\t{\n\t\tdouble mx = action->getAbsoluteXMouse();\n\t\tif (mx <= _btnGround->getX() + (_btnGround->getWidth() / 2.0))\n\t\t{\n\t\t\t// clicked on the left half of the button\n\t\t\tscrollBackwards = true;\n\t\t}\n\t}\n\n\tif (scrollBackwards)\n\t{\n\t\t// scroll backwards\n\t\t_inv->arrangeGround(-1);\n\t}\n\telse\n\t{\n\t\t// scroll forward\n\t\t_inv->arrangeGround(1);\n\t}\n}\n\n/**\n * Shows more ground items / rearranges them.\n * @param action Pointer to an action.\n */\nvoid InventoryState::btnGroundClickBackward(Action *action)\n{\n\t// scroll backwards\n\t_inv->arrangeGround(-1);\n}\n\n/**\n * Shows the unit info screen.\n * @param action Pointer to an action.\n */\nvoid InventoryState::btnRankClick(Action *)\n{\n\t// don't accept clicks when moving items\n\tif (_inv->getSelectedItem() != 0)\n\t{\n\t\treturn;\n\t}\n\n\t_game->pushState(new UnitInfoState(_battleGame->getSelectedUnit(), _parent, true, false));\n}\n\nvoid InventoryState::_createInventoryTemplate(std::vector<EquipmentLayoutItem*> &inventoryTemplate)\n{\n\t// copy inventory instead of just keeping a pointer to it.  that way\n\t// create/apply can be used as an undo button for a single unit and will\n\t// also work as expected if inventory is modified after 'create' is clicked\n\tfor (const auto* bi : *_battleGame->getSelectedUnit()->getInventory())\n\t{\n\t\t// skip fixed items\n\t\tif (bi->getRules()->isFixed())\n\t\t{\n\t\t\tbool loaded = bi->needsAmmoForSlot(0) && bi->getAmmoForSlot(0);\n\t\t\tif (!loaded) continue;\n\t\t}\n\t\telse if (!bi->getRules()->canBeEquippedToCraftInventory())\n\t\t{\n\t\t\t// skip other not-allowed items, which somehow made it here (e.g. were spawned instead of equipped)\n\t\t\tcontinue;\n\t\t}\n\n\t\tinventoryTemplate.push_back(new EquipmentLayoutItem(bi));\n\t}\n}\n\nvoid InventoryState::btnLinksClick(Action *)\n{\n\t// don't accept clicks when moving items\n\tif (_inv->getSelectedItem() != 0)\n\t{\n\t\t// but we can reuse this for ufopedia (as an M-click alternative)\n\t\tstd::string articleId = _inv->getSelectedItem()->getRules()->getUfopediaType();\n\t\tUfopaedia::openArticle(_game, articleId);\n\n\t\treturn;\n\t}\n\n\t_game->pushState(new ExtendedInventoryLinksState(this, _battleGame, _base, !_tu));\n}\n\nvoid InventoryState::btnCreateTemplateClick(Action *)\n{\n\t// don't accept clicks when moving items\n\tif (_inv->getSelectedItem() != 0)\n\t{\n\t\treturn;\n\t}\n\n\t// clear current template\n\t_clearInventoryTemplate(_curInventoryTemplate);\n\n\t// create new template\n\t_createInventoryTemplate(_curInventoryTemplate);\n\n\t// give audio feedback\n\t_game->getMod()->getSoundByDepth(_battleGame->getDepth(), Mod::ITEM_DROP)->play();\n\trefreshMouse();\n}\n\nvoid InventoryState::btnCreatePersonalTemplateClick(Action *)\n{\n\t// cannot use this feature during the mission!\n\tif (_tu)\n\t{\n\t\treturn;\n\t}\n\n\t// don't accept clicks when moving items\n\tif (_inv->getSelectedItem() != 0)\n\t{\n\t\treturn;\n\t}\n\n\tauto* unit = _battleGame->getSelectedUnit();\n\tif (unit && unit->getGeoscapeSoldier())\n\t{\n\t\tauto& personalTemplate = *unit->getGeoscapeSoldier()->getPersonalEquipmentLayout();\n\n\t\t// clear current personal template\n\t\t_clearInventoryTemplate(personalTemplate);\n\n\t\t// create new personal template\n\t\t_createInventoryTemplate(personalTemplate);\n\n\t\t// optionally save armor info too\n\t\tif (Options::oxcePersonalLayoutIncludingArmor)\n\t\t{\n\t\t\tunit->getGeoscapeSoldier()->setPersonalEquipmentArmor(_battleGame->getSelectedUnit()->getArmor());\n\t\t}\n\t\telse\n\t\t{\n\t\t\tunit->getGeoscapeSoldier()->setPersonalEquipmentArmor(nullptr);\n\t\t}\n\n\t\t// give visual feedback\n\t\t_inv->showWarning(tr(\"STR_PERSONAL_EQUIPMENT_SAVED\"));\n\n\t\t// give audio feedback\n\t\t_game->getMod()->getSoundByDepth(_battleGame->getDepth(), Mod::ITEM_DROP)->play();\n\t\trefreshMouse();\n\t}\n}\n\nvoid InventoryState::_applyInventoryTemplate(std::vector<EquipmentLayoutItem*> &inventoryTemplate)\n{\n\tBattleUnit               *unit          = _battleGame->getSelectedUnit();\n\tTile                     *groundTile    = unit->getTile();\n\tstd::vector<BattleItem*> *groundInv     = groundTile->getInventory();\n\n\t_battleGame->getTileEngine()->itemDropInventory(groundTile, unit, true, false);\n\n\t// attempt to replicate inventory template by grabbing corresponding items\n\t// from the ground.  if any item is not found on the ground, display warning\n\t// message, but continue attempting to fulfill the template as best we can\n\tbool itemMissing = false;\n\tfor (const auto* equipmentLayoutItem : inventoryTemplate)\n\t{\n\t\t// search for template item in ground inventory\n\t\tbool found = false;\n\n\t\tbool needsAmmo[RuleItem::AmmoSlotMax] = { };\n\t\tconst RuleItem* targetAmmo[RuleItem::AmmoSlotMax] = { };\n\t\tBattleItem *matchedWeapon = nullptr;\n\t\tBattleItem *matchedAmmo[RuleItem::AmmoSlotMax] = { };\n\n\t\tfor (int slot = 0; slot < RuleItem::AmmoSlotMax; ++slot)\n\t\t{\n\t\t\ttargetAmmo[slot] = equipmentLayoutItem->getAmmoItemForSlot(slot);\n\t\t\tneedsAmmo[slot] = (targetAmmo[slot] != nullptr);\n\t\t\tmatchedAmmo[slot] = nullptr;\n\t\t}\n\n\t\tfor (BattleItem* groundItem : *groundInv)\n\t\t{\n\t\t\t// if we find the appropriate ammo, remember it for later for if we find\n\t\t\t// the right weapon but with the wrong ammo\n\t\t\tauto* groundItemRule = groundItem->getRules();\n\n\t\t\tbool skipAmmo = false;\n\t\t\tfor (int slot = 0; slot < RuleItem::AmmoSlotMax; ++slot)\n\t\t\t{\n\t\t\t\tif (needsAmmo[slot] && !matchedAmmo[slot] && targetAmmo[slot] == groundItemRule)\n\t\t\t\t{\n\t\t\t\t\tmatchedAmmo[slot] = groundItem;\n\t\t\t\t\tskipAmmo = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (skipAmmo)\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (equipmentLayoutItem->isFixed() == false && equipmentLayoutItem->getItemType() == groundItemRule)\n\t\t\t{\n\t\t\t\t// if the loaded ammo doesn't match the template item's,\n\t\t\t\t// remember the weapon for later and continue scanning\n\t\t\t\tbool skipWeapon = false;\n\t\t\t\tfor (int slot = 0; slot < RuleItem::AmmoSlotMax; ++slot)\n\t\t\t\t{\n\t\t\t\t\tif (!groundItem->needsAmmoForSlot(slot))\n\t\t\t\t\t{\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tBattleItem *loadedAmmo = groundItem->getAmmoForSlot(slot);\n\t\t\t\t\tif ((needsAmmo[slot] && (!loadedAmmo || targetAmmo[slot] != loadedAmmo->getRules()))\n\t\t\t\t\t\t|| (!needsAmmo[slot] && loadedAmmo))\n\t\t\t\t\t{\n\t\t\t\t\t\t// remember the last matched weapon for simplicity (but prefer empty weapons if any are found)\n\t\t\t\t\t\tif (!matchedWeapon || matchedWeapon->getAmmoForSlot(slot))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tmatchedWeapon = groundItem;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tskipWeapon = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!skipWeapon)\n\t\t\t\t{\n\t\t\t\t\tmatchedWeapon = groundItem;\n\t\t\t\t\tfound = true; // found = true, even if not equipped\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (equipmentLayoutItem->isFixed())\n\t\t{\n\t\t\tfor (BattleItem* fixedItem : *unit->getInventory())\n\t\t\t{\n\t\t\t\tif (fixedItem->getRules()->isFixed() == false)\n\t\t\t\t{\n\t\t\t\t\t// this is not a fixed item, continue searching...\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (fixedItem->getSlot() == equipmentLayoutItem->getSlot() &&\n\t\t\t\t\tfixedItem->getSlotX() == equipmentLayoutItem->getSlotX() &&\n\t\t\t\t\tfixedItem->getSlotY() == equipmentLayoutItem->getSlotY() &&\n\t\t\t\t\tfixedItem->getRules() == equipmentLayoutItem->getItemType())\n\t\t\t\t{\n\t\t\t\t\t// if the loaded ammo doesn't match the template item's,\n\t\t\t\t\t// remember the weapon for later and continue scanning\n\t\t\t\t\tbool skipWeapon = false;\n\t\t\t\t\tfor (int slot = 0; slot < RuleItem::AmmoSlotMax; ++slot)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (!fixedItem->needsAmmoForSlot(slot))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tBattleItem* loadedAmmo = fixedItem->getAmmoForSlot(slot);\n\t\t\t\t\t\tif ((needsAmmo[slot] && (!loadedAmmo || targetAmmo[slot] != loadedAmmo->getRules()))\n\t\t\t\t\t\t\t|| (!needsAmmo[slot] && loadedAmmo))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// remember the last matched weapon for simplicity (but prefer empty weapons if any are found)\n\t\t\t\t\t\t\tif (!matchedWeapon || matchedWeapon->getAmmoForSlot(slot))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tmatchedWeapon = fixedItem;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tskipWeapon = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (!skipWeapon)\n\t\t\t\t\t{\n\t\t\t\t\t\tmatchedWeapon = fixedItem;\n\t\t\t\t\t\tfound = true; // found = true, even if not equipped\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// if we failed to find an exact match, but found unloaded ammo and\n\t\t// the right weapon, unload the target weapon, load the right ammo, and use it\n\t\tif (!found && matchedWeapon)\n\t\t{\n\t\t\tfound = true;\n\t\t\tbool allMatch = true;\n\t\t\tfor (int slot = 0; slot < RuleItem::AmmoSlotMax; ++slot)\n\t\t\t{\n\t\t\t\tallMatch &= (needsAmmo[slot] && matchedAmmo[slot]) || (!needsAmmo[slot]);\n\t\t\t}\n\t\t\tif (allMatch)\n\t\t\t{\n\t\t\t\tfor (int slot = 0; slot < RuleItem::AmmoSlotMax; ++slot)\n\t\t\t\t{\n\t\t\t\t\tif (matchedWeapon->needsAmmoForSlot(slot) && (!needsAmmo[slot] || matchedAmmo[slot]))\n\t\t\t\t\t{\n\t\t\t\t\t\t// unload the existing ammo (if any) from the weapon\n\t\t\t\t\t\tBattleItem *loadedAmmo = matchedWeapon->setAmmoForSlot(slot, matchedAmmo[slot]);\n\t\t\t\t\t\tif (loadedAmmo)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_battleGame->getTileEngine()->itemDrop(groundTile, loadedAmmo, false);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// nope we can't do it.\n\t\t\t\tfound = false;\n\t\t\t\tmatchedWeapon = nullptr;\n\t\t\t}\n\t\t}\n\n\t\tif (!found)\n\t\t{\n\t\t\titemMissing = true;\n\t\t}\n\n\t\tif (equipmentLayoutItem->isFixed())\n\t\t{\n\t\t\t// we have loaded the fixed weapon (if possible) and we don't need to do anything else, it's already in the correct slot\n\t\t\tcontinue;\n\t\t}\n\n\t\t// check if the slot is not occupied already (e.g. by a fixed weapon)\n\t\tif (matchedWeapon && !_inv->overlapItems(\n\t\t\tunit,\n\t\t\tmatchedWeapon,\n\t\t\tequipmentLayoutItem->getSlot(),\n\t\t\tequipmentLayoutItem->getSlotX(),\n\t\t\tequipmentLayoutItem->getSlotY()))\n\t\t{\n\t\t\t// move matched item from ground to the appropriate inventory slot\n\t\t\tmatchedWeapon->moveToOwner(unit);\n\t\t\tmatchedWeapon->setSlot(equipmentLayoutItem->getSlot());\n\t\t\tmatchedWeapon->setSlotX(equipmentLayoutItem->getSlotX());\n\t\t\tmatchedWeapon->setSlotY(equipmentLayoutItem->getSlotY());\n\t\t\tmatchedWeapon->setFuseTimer(equipmentLayoutItem->getFuseTimer());\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// let the user know or not? probably not... should be obvious why\n\t\t}\n\t}\n\n\tif (itemMissing)\n\t{\n\t\t_inv->showWarning(tr(\"STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE\"));\n\t}\n}\n\nvoid InventoryState::btnApplyTemplateClick(Action *)\n{\n\t// don't accept clicks when moving items\n\t// it's ok if the template is empty -- it will just result in clearing the\n\t// unit's inventory\n\tif (_inv->getSelectedItem() != 0)\n\t{\n\t\treturn;\n\t}\n\n\t_applyInventoryTemplate(_curInventoryTemplate);\n\n\t// refresh ui\n\t_inv->arrangeGround();\n\tupdateStats();\n\trefreshMouse();\n\n\t// give audio feedback\n\t_game->getMod()->getSoundByDepth(_battleGame->getDepth(), Mod::ITEM_DROP)->play();\n}\n\nvoid InventoryState::btnApplyPersonalTemplateClick(Action *)\n{\n\t// cannot use this feature during the mission!\n\tif (_tu)\n\t{\n\t\treturn;\n\t}\n\n\t// don't accept clicks when moving items\n\tif (_inv->getSelectedItem() != 0)\n\t{\n\t\treturn;\n\t}\n\n\tauto* unit = _battleGame->getSelectedUnit();\n\tif (unit && unit->getGeoscapeSoldier())\n\t{\n\t\t// optionally load armor too\n\t\tif (Options::oxcePersonalLayoutIncludingArmor)\n\t\t{\n\t\t\tauto* newArmor = unit->getGeoscapeSoldier()->getPersonalEquipmentArmor();\n\t\t\tif (newArmor && newArmor != unit->getArmor())\n\t\t\t{\n\t\t\t\tbool success = tryArmorChange(newArmor->getType());\n\n\t\t\t\tif (success)\n\t\t\t\t{\n\t\t\t\t\t_reloadUnit = true;\n\t\t\t\t\tinit();\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// FIXME: a better message? or no message?\n\t\t\t\t\t//_inv->showWarning(tr(\"STR_NOT_ENOUGH_ITEMS_FOR_TEMPLATE\"));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tauto& personalTemplate = *unit->getGeoscapeSoldier()->getPersonalEquipmentLayout();\n\n\t\tif (personalTemplate.empty())\n\t\t{\n\t\t\t_inv->showWarning(tr(\"STR_PERSONAL_EQUIPMENT_NOT_DEFINED\"));\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_applyInventoryTemplate(personalTemplate);\n\t\t}\n\n\t\t// refresh ui\n\t\t_inv->arrangeGround();\n\t\tupdateStats();\n\t\trefreshMouse();\n\n\t\t// give audio feedback\n\t\t_game->getMod()->getSoundByDepth(_battleGame->getDepth(), Mod::ITEM_DROP)->play();\n\t}\n}\n\nvoid InventoryState::btnShowPersonalTemplateClick(Action *)\n{\n\t// don't accept clicks when moving items\n\tif (_inv->getSelectedItem() != 0)\n\t{\n\t\treturn;\n\t}\n\n\tauto* unit = _battleGame->getSelectedUnit();\n\tif (unit && unit->getGeoscapeSoldier())\n\t{\n\t\t_game->pushState(new InventoryPersonalState(unit->getGeoscapeSoldier()));\n\t}\n}\n\nvoid InventoryState::refreshMouse()\n{\n\t// send a mouse motion event to refresh any hover actions\n\tint x, y;\n\tSDL_GetMouseState(&x, &y);\n\tSDL_WarpMouse(x+1, y);\n\n\t// move the mouse back to avoid cursor creep\n\tSDL_WarpMouse(x, y);\n}\n\nvoid InventoryState::onClearInventory(Action *)\n{\n\t// don't act when moving items\n\tif (_inv->getSelectedItem() != 0)\n\t{\n\t\treturn;\n\t}\n\n\tBattleUnit               *unit       = _battleGame->getSelectedUnit();\n\tTile                     *groundTile = unit->getTile();\n\n\t_battleGame->getTileEngine()->itemDropInventory(groundTile, unit, true, false);\n\n\t// refresh ui\n\t_inv->arrangeGround();\n\tupdateStats();\n\trefreshMouse();\n\n\t// give audio feedback\n\t_game->getMod()->getSoundByDepth(_battleGame->getDepth(), Mod::ITEM_DROP)->play();\n}\n\nvoid InventoryState::onAutoequip(Action *)\n{\n\t// don't act when moving items\n\tif (_inv->getSelectedItem() != 0)\n\t{\n\t\treturn;\n\t}\n\n\tBattleUnit               *unit          = _battleGame->getSelectedUnit();\n\tTile                     *groundTile    = unit->getTile();\n\tstd::vector<BattleItem*>  groundInv     = *groundTile->getInventory();\n\tMod                      *mod           = _game->getMod();\n\tRuleInventory            *groundRuleInv = mod->getInventoryGround();\n\tint                       worldShade    = _battleGame->getGlobalShade();\n\n\tstd::vector<BattleUnit*> units;\n\tunits.push_back(unit);\n\tBattlescapeGenerator::autoEquip(units, mod, &groundInv, groundRuleInv, worldShade, true, true);\n\n\t// refresh ui\n\t_inv->arrangeGround();\n\tupdateStats();\n\trefreshMouse();\n\n\t// give audio feedback\n\t_game->getMod()->getSoundByDepth(_battleGame->getDepth(), Mod::ITEM_DROP)->play();\n}\n\n/**\n * Updates item info.\n * @param action Pointer to an action.\n */\nvoid InventoryState::invClick(Action *act)\n{\n\tupdateStats();\n\t_prev_key = 0, _key_repeats = 0;\n}\n\n/**\n * Calculates item damage info.\n */\nvoid InventoryState::calculateCurrentDamageTooltip()\n{\n\t// Differences against battlescape indicator:\n\t// 1. doesn't consider which action (auto/snap/aim/melee) is used... just takes ammo from primary slot\n\t// 2. doesn't show psi success chance (distance is unknown)\n\t// 3. doesn't consider range power reduction (distance is unknown)\n\n\tconst BattleUnit *currentUnit = _inv->getSelectedUnit();\n\n\tif (!currentUnit)\n\t\treturn;\n\n\tif (!_currentDamageTooltipItem)\n\t\treturn;\n\n\tconst BattleItem *damageItem = _currentDamageTooltipItem;\n\tconst RuleItem *weaponRule = _currentDamageTooltipItem->getRules();\n\tconst int PRIMARY_SLOT = 0;\n\n\t// step 1: determine rule\n\tconst RuleItem *rule;\n\tif (weaponRule->getBattleType() == BT_PSIAMP)\n\t{\n\t\trule = weaponRule;\n\t}\n\telse if (_currentDamageTooltipItem->needsAmmoForSlot(PRIMARY_SLOT))\n\t{\n\t\tauto* ammo = _currentDamageTooltipItem->getAmmoForSlot(PRIMARY_SLOT);\n\t\tif (ammo != nullptr)\n\t\t{\n\t\t\tdamageItem = ammo;\n\t\t\trule = ammo->getRules();\n\t\t}\n\t\telse\n\t\t{\n\t\t\trule = 0; // empty weapon = no rule\n\t\t}\n\t}\n\telse\n\t{\n\t\trule = weaponRule;\n\t}\n\n\t// step 2: check if unlocked\n\tif (_game->getSavedGame()->getMonthsPassed() == -1)\n\t{\n\t\t// new battle mode\n\t}\n\telse if (rule)\n\t{\n\t\t// instead of checking the weapon/ammo itself... we're checking their ufopedia articles here\n\t\t// same as for the battlescape indicator\n\t\t// it's arguable if this is the correct approach, but so far this is what we have\n\t\tArticleDefinition *article = _game->getMod()->getUfopaediaArticle(rule->getType(), false);\n\t\tif (article && !Ufopaedia::isArticleAvailable(_game->getSavedGame(), article))\n\t\t{\n\t\t\t// ammo/weapon locked\n\t\t\trule = 0;\n\t\t}\n\t\tif (rule && rule->getType() != weaponRule->getType())\n\t\t{\n\t\t\tarticle = _game->getMod()->getUfopaediaArticle(weaponRule->getType(), false);\n\t\t\tif (article && !Ufopaedia::isArticleAvailable(_game->getSavedGame(), article))\n\t\t\t{\n\t\t\t\t// weapon locked\n\t\t\t\trule = 0;\n\t\t\t}\n\t\t}\n\t}\n\n\t// step 3: calculate and remember\n\tif (rule)\n\t{\n\t\tif (rule->getBattleType() != BT_CORPSE)\n\t\t{\n\t\t\tint totalDamage = 0;\n\t\t\tif (weaponRule->getIgnoreAmmoPower())\n\t\t\t{\n\t\t\t\ttotalDamage += weaponRule->getPowerBonus({ BA_NONE, currentUnit, _currentDamageTooltipItem, damageItem });\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\ttotalDamage += rule->getPowerBonus({ BA_NONE, currentUnit, _currentDamageTooltipItem, damageItem }); //TODO: find what exactly attack we can do\n\t\t\t}\n\t\t\t//totalDamage -= rule->getPowerRangeReduction(distance * 16);\n\t\t\tif (totalDamage < 0) totalDamage = 0;\n\t\t\tstd::ostringstream ss;\n\t\t\tss << rule->getDamageType()->getRandomDamage(totalDamage, 1);\n\t\t\tss << \"-\";\n\t\t\tss << rule->getDamageType()->getRandomDamage(totalDamage, 2);\n\t\t\tif (rule->getDamageType()->RandomType == DRT_UFO_WITH_TWO_DICE)\n\t\t\t\tss << \"*\";\n\t\t\t_currentDamageTooltip = tr(\"STR_DAMAGE_UC_\").arg(ss.str());\n\t\t}\n\t}\n\telse\n\t{\n\t\t_currentDamageTooltip = tr(\"STR_DAMAGE_UC_\").arg(tr(\"STR_UNKNOWN\"));\n\t}\n}\n/**\n * Shows item info.\n * @param action Pointer to an action.\n */\nvoid InventoryState::invMouseOver(Action *)\n{\n\tif (_inv->getSelectedItem() != 0)\n\t{\n\t\treturn;\n\t}\n\n\tbool altPressed = _game->isAltPressed();\n\tbool currentDamageTooltipItemChanged = false;\n\n\tBattleItem *item = _inv->getMouseOverItem();\n\tif (item != _mouseHoverItem)\n\t{\n\t\t_mouseHoverItemFrame = _inv->getAnimFrame();\n\t\t_mouseHoverItem = item;\n\t}\n\tif (altPressed)\n\t{\n\t\tif (item != _currentDamageTooltipItem)\n\t\t{\n\t\t\tcurrentDamageTooltipItemChanged = true;\n\t\t\t_currentDamageTooltipItem = item;\n\t\t\t_currentDamageTooltip = \"\";\n\t\t}\n\t}\n\telse\n\t{\n\t\t_currentDamageTooltipItem = nullptr;\n\t\t_currentDamageTooltip = \"\";\n\t}\n\tif (item != 0)\n\t{\n\t\tstd::string itemName;\n\t\tif (item->getUnit() && item->getUnit()->getStatus() == STATUS_UNCONSCIOUS)\n\t\t{\n\t\t\titemName = item->getUnit()->getName(_game->getLanguage());\n\t\t}\n\t\telse\n\t\t{\n\t\t\tauto* save = _game->getSavedGame();\n\t\t\tif (save->isResearched(item->getRules()->getRequirements()))\n\t\t\t{\n\t\t\t\tstd::string text = tr(item->getRules()->getName());\n\t\t\t\tfor (int slot = 0; slot < RuleItem::AmmoSlotMax; ++slot)\n\t\t\t\t{\n\t\t\t\t\tif (!item->needsAmmoForSlot(slot))\n\t\t\t\t\t{\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tauto* ammo = item->getAmmoForSlot(slot);\n\t\t\t\t\tif (!ammo || !save->isResearched(ammo->getRules()->getRequirements()))\n\t\t\t\t\t{\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst auto& ammoName = ammo->getRules()->getNameAsAmmo();\n\t\t\t\t\tif (!ammoName.empty())\n\t\t\t\t\t{\n\t\t\t\t\t\ttext += \" \";\n\t\t\t\t\t\ttext += tr(ammoName);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (altPressed)\n\t\t\t\t{\n\t\t\t\t\tif (currentDamageTooltipItemChanged)\n\t\t\t\t\t{\n\t\t\t\t\t\tcalculateCurrentDamageTooltip();\n\t\t\t\t\t}\n\t\t\t\t\titemName = _currentDamageTooltip;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\titemName = text;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\titemName = tr(\"STR_ALIEN_ARTIFACT\");\n\t\t\t}\n\t\t}\n\n\t\tif (!altPressed)\n\t\t{\n\t\t\tstd::ostringstream ss;\n\t\t\tss << itemName;\n\t\t\tss << \" [\";\n\t\t\tss << item->getTotalWeight();\n\t\t\tss << \"]\";\n\t\t\t_txtItem->setText(ss.str().c_str());\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_txtItem->setText(itemName);\n\t\t}\n\n\t\t_selAmmo->clear();\n\t\tbool hasSelfAmmo = item->getRules()->getBattleType() != BT_AMMO && item->getRules()->getClipSize() > 0;\n\t\tif ((item->isWeaponWithAmmo() || hasSelfAmmo) && item->haveAnyAmmo())\n\t\t{\n\t\t\tupdateTemplateButtons(false);\n\t\t\t_txtAmmo->setText(\"\");\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_mouseHoverItem = nullptr;\n\t\t\tupdateTemplateButtons(!_tu);\n\t\t\tstd::string s;\n\t\t\tif (item->getRules()->getBattleType() == BT_AMMO && (item->getAmmoQuantity() != 0 || item->getRules()->isAmmoRechargeable()))\n\t\t\t{\n\t\t\t\ts = tr(\"STR_AMMO_ROUNDS_LEFT\").arg(item->getAmmoQuantity());\n\t\t\t}\n\t\t\telse if (item->getRules()->getBattleType() == BT_MEDIKIT)\n\t\t\t{\n\t\t\t\ts = tr(\"STR_MEDI_KIT_QUANTITIES_LEFT\").arg(item->getPainKillerQuantity()).arg(item->getStimulantQuantity()).arg(item->getHealQuantity());\n\t\t\t}\n\t\t\t_txtAmmo->setText(s);\n\t\t}\n\t}\n\telse\n\t{\n\t\tif (_currentTooltip.empty())\n\t\t{\n\t\t\t_txtItem->setText(\"\");\n\t\t}\n\t\t_txtAmmo->setText(\"\");\n\t\t_selAmmo->clear();\n\t\tupdateTemplateButtons(!_tu);\n\t}\n}\n\n/**\n * Hides item info.\n * @param action Pointer to an action.\n */\nvoid InventoryState::invMouseOut(Action *)\n{\n\t_txtItem->setText(\"\");\n\t_txtAmmo->setText(\"\");\n\t_selAmmo->clear();\n\t_inv->setMouseOverItem(0);\n\t_mouseHoverItem = nullptr;\n\t_currentDamageTooltipItem = nullptr;\n\t_currentDamageTooltip = \"\";\n\tupdateTemplateButtons(!_tu);\n}\n\nvoid InventoryState::onMoveGroundInventoryToBase(Action *)\n{\n\t// don't act when moving items\n\tif (_inv->getSelectedItem() != 0)\n\t{\n\t\treturn;\n\t}\n\n\tif (_base == 0)\n\t{\n\t\t// equipment just before the mission (=after briefing) or during the mission\n\t\treturn;\n\t}\n\n\tif (_noCraft)\n\t{\n\t\t// pre-equipping in the base, but *without* a craft\n\t\treturn;\n\t}\n\n\t// ok, which craft?\n\tBattleUnit *unit = _battleGame->getSelectedUnit();\n\tSoldier *s = unit->getGeoscapeSoldier();\n\tCraft *c = s->getCraft();\n\n\tif (c == 0 || c->getStatus() == \"STR_OUT\")\n\t{\n\t\t// we're either not in a craft or not in a hangar (should not happen, but just in case)\n\t\treturn;\n\t}\n\n\tTile                     *groundTile = unit->getTile();\n\tstd::vector<BattleItem*> *groundInv = groundTile->getInventory();\n\n\t// step 1: move stuff from craft to base\n\tfor (auto* bi : *groundInv)\n\t{\n\t\tconst auto& weaponType = bi->getRules();\n\t\t// check all ammo slots first\n\t\tfor (int slot = 0; slot < RuleItem::AmmoSlotMax; ++slot)\n\t\t{\n\t\t\tif (bi->getAmmoForSlot(slot))\n\t\t\t{\n\t\t\t\tconst auto& ammoType = bi->getAmmoForSlot(slot)->getRules();\n\t\t\t\t// only real ammo\n\t\t\t\tif (weaponType != ammoType)\n\t\t\t\t{\n\t\t\t\t\tc->getItems()->removeItem(ammoType);\n\t\t\t\t\t_base->getStorageItems()->addItem(ammoType);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// and the weapon as last\n\t\tc->getItems()->removeItem(weaponType);\n\t\t_base->getStorageItems()->addItem(weaponType);\n\t}\n\n\t// step 2: clear ground\n\tfor (auto itemIt = groundInv->begin(); itemIt != groundInv->end(); )\n\t{\n\t\tBattleItem* item = (*itemIt);\n\t\titem->setOwner(NULL);\n\t\titemIt = groundInv->erase(itemIt);\n\t\t_game->getSavedGame()->getSavedBattle()->removeItem(item);\n\t}\n\n\t// refresh ui\n\t_inv->arrangeGround();\n\tupdateStats();\n\trefreshMouse();\n\n\t// give audio feedback\n\t_game->getMod()->getSoundByDepth(_battleGame->getDepth(), Mod::ITEM_DROP)->play();\n}\n\n/**\n * Takes care of any events from the core game engine.\n * @param action Pointer to an action.\n */\nvoid InventoryState::handle(Action *action)\n{\n\tState::handle(action);\n\n\tif (action->getDetails()->type == SDL_KEYDOWN && !_btnQuickSearch->isFocused() && !_txtName->isFocused())\n\t{\n\t\t// \"ctrl+1..9\" - save equipment\n\t\t// \"1..9\" - load equipment\n\t\tif (action->getDetails()->key.keysym.sym >= SDLK_0 && action->getDetails()->key.keysym.sym <= SDLK_9)\n\t\t{\n\t\t\t{\n\t\t\t\tbtnGlobalEquipmentLayoutClick(action);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_prev_key = 0, _key_repeats = 0;\n\t\t}\n\n\t\tif (action->getDetails()->key.keysym.sym == Options::keyInvClear)\n\t\t{\n\t\t\tif (_game->isCtrlPressed() && _game->isAltPressed())\n\t\t\t{\n\t\t\t\tonMoveGroundInventoryToBase(action);\n\t\t\t}\n\t\t}\n\t}\n\n#ifndef __MORPHOS__\n\tif (Options::oxceThumbButtons && action->getDetails()->type == SDL_MOUSEBUTTONDOWN)\n\t{\n\t\tif (action->getDetails()->button.button == SDL_BUTTON_X1)\n\t\t{\n\t\t\tbtnNextClick(action);\n\t\t}\n\t\telse if (action->getDetails()->button.button == SDL_BUTTON_X2)\n\t\t{\n\t\t\tbtnPrevClick(action);\n\t\t}\n\t}\n#endif\n}\n\n/**\n * Cycle through loaded ammo in hover over item.\n */\nvoid InventoryState::think()\n{\n\tif (_mouseHoverItem)\n\t{\n\t\tint anim = _inv->getAnimFrame();\n\t\tint seq = std::max(((anim - _mouseHoverItemFrame) / 10) - 1, 0); // `-1` cause that first item will be show bit more longer\n\t\tint modulo = 0;\n\t\tfor (int slot = 0; slot < RuleItem::AmmoSlotMax; ++slot)\n\t\t{\n\t\t\tbool showSelfAmmo = slot == 0 && _mouseHoverItem->getRules()->getClipSize() > 0;\n\t\t\tif ((_mouseHoverItem->needsAmmoForSlot(slot) || showSelfAmmo) && _mouseHoverItem->getAmmoForSlot(slot))\n\t\t\t{\n\t\t\t\t++modulo;\n\t\t\t}\n\t\t}\n\t\tif (modulo)\n\t\t{\n\t\t\tseq %= modulo;\n\t\t}\n\n\t\tBattleItem* firstAmmo = nullptr;\n\t\tfor (int slot = 0; slot < RuleItem::AmmoSlotMax; ++slot)\n\t\t{\n\t\t\tbool showSelfAmmo = slot == 0 && _mouseHoverItem->getRules()->getClipSize() > 0;\n\t\t\tif ((_mouseHoverItem->needsAmmoForSlot(slot) || showSelfAmmo) && _mouseHoverItem->getAmmoForSlot(slot))\n\t\t\t{\n\t\t\t\tfirstAmmo = _mouseHoverItem->getAmmoForSlot(slot);\n\t\t\t\tif (slot >= seq)\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// this will skip empty slot\n\t\t\t\t++seq;\n\t\t\t}\n\t\t}\n\t\tif (firstAmmo)\n\t\t{\n\t\t\t_txtAmmo->setText(tr(\"STR_AMMO_ROUNDS_LEFT\").arg(firstAmmo->getAmmoQuantity()));\n\t\t\tSDL_Rect r;\n\t\t\tr.x = 0;\n\t\t\tr.y = 0;\n\t\t\tr.w = RuleInventory::HAND_W * RuleInventory::SLOT_W;\n\t\t\tr.h = RuleInventory::HAND_H * RuleInventory::SLOT_H;\n\t\t\t_selAmmo->drawRect(&r, _game->getMod()->getInterface(\"inventory\")->getElement(\"grid\")->color);\n\t\t\tr.x++;\n\t\t\tr.y++;\n\t\t\tr.w -= 2;\n\t\t\tr.h -= 2;\n\t\t\t_selAmmo->drawRect(&r, Palette::blockOffset(0)+15);\n\t\t\tfirstAmmo->getRules()->drawHandSprite(_game->getMod()->getSurfaceSet(\"BIGOBS.PCK\"), _selAmmo, firstAmmo, _game->getSavedGame()->getSavedBattle(), anim);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_selAmmo->clear();\n\t\t}\n\t}\n\tState::think();\n}\n\n/**\n * Shows a tooltip for the OK button.\n * @param action Pointer to an action.\n */\nvoid InventoryState::txtTooltipInExtraOK(Action *action)\n{\n\tif (_inv->getSelectedItem() == 0 && Options::battleTooltips)\n\t{\n\t\t_currentTooltip = action->getSender()->getTooltip();\n\n\t\tstd::ostringstream ss;\n\t\tss << tr(_currentTooltip);\n\n\t\tif (!_tu && !_base)\n\t\t{\n\t\t\tss << \" - \";\n\n\t\t\tif (_battleGame->getGlobalShade() <= 0)\n\t\t\t{\n\t\t\t\t// day (0)\n\t\t\t\tss << tr(\"STR_DAY\");\n\t\t\t}\n\t\t\telse if (_battleGame->getGlobalShade() > _game->getMod()->getMaxDarknessToSeeUnits())\n\t\t\t{\n\t\t\t\t// night (10-15); note: this is configurable in the ruleset (in OXCE only)\n\t\t\t\tss << tr(\"STR_NIGHT\");\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// dusk/dawn (1-9)\n\t\t\t\tss << tr(\"STR_DAY\");\n\t\t\t\tss << \"*\";\n\t\t\t}\n\t\t}\n\n\t\t_txtItem->setText(ss.str().c_str());\n\t}\n}\n\n\n/**\n * Shows a tooltip for the appropriate button.\n * @param action Pointer to an action.\n */\nvoid InventoryState::txtTooltipIn(Action *action)\n{\n\tif (_inv->getSelectedItem() == 0 && Options::battleTooltips)\n\t{\n\t\t_currentTooltip = action->getSender()->getTooltip();\n\t\t_txtItem->setText(tr(_currentTooltip));\n\t}\n}\n\n/**\n * Clears the tooltip text.\n * @param action Pointer to an action.\n */\nvoid InventoryState::txtTooltipOut(Action *action)\n{\n\tif (_inv->getSelectedItem() == 0 && Options::battleTooltips)\n\t{\n\t\tif (_currentTooltip == action->getSender()->getTooltip())\n\t\t{\n\t\t\t_currentTooltip = \"\";\n\t\t\t_txtItem->setText(\"\");\n\t\t}\n\t}\n}\n\n/**\n* Shows a tooltip for the paperdoll's armor.\n* @param action Pointer to an action.\n*/\nvoid InventoryState::txtArmorTooltipIn(Action *action)\n{\n\tif (_inv->getSelectedItem() == 0)\n\t{\n\t\tBattleUnit *unit = _inv->getSelectedUnit();\n\t\tif (unit != 0)\n\t\t{\n\t\t\taction->getSender()->setTooltip(unit->getArmor()->getType());\n\t\t\t_currentTooltip = action->getSender()->getTooltip();\n\t\t\t{\n\t\t\t\tstd::ostringstream ss;\n\n\t\t\t\tif (unit->getGeoscapeSoldier())\n\t\t\t\t{\n\t\t\t\t\tauto* soldierRules = unit->getGeoscapeSoldier()->getRules();\n\t\t\t\t\tif (soldierRules->getShowTypeInInventory())\n\t\t\t\t\t{\n\t\t\t\t\t\tss << tr(soldierRules->getType());\n\t\t\t\t\t\tss << \": \";\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tss << tr(_currentTooltip);\n\t\t\t\tif (unit->getArmor()->getWeight() != 0)\n\t\t\t\t{\n\t\t\t\t\tss << \" [\";\n\t\t\t\t\tss << unit->getArmor()->getWeight();\n\t\t\t\t\tss << \"]\";\n\t\t\t\t}\n\t\t\t\t_txtItem->setText(ss.str().c_str());\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n* Clears the armor tooltip text.\n* @param action Pointer to an action.\n*/\nvoid InventoryState::txtArmorTooltipOut(Action *action)\n{\n\tif (_inv->getSelectedItem() == 0)\n\t{\n\t\tif (_currentTooltip == action->getSender()->getTooltip())\n\t\t{\n\t\t\t_currentTooltip = \"\";\n\t\t\t_txtItem->setText(\"\");\n\t\t}\n\t}\n}\n\nvoid InventoryState::updateTemplateButtons(bool isVisible)\n{\n\tif (isVisible)\n\t{\n\t\tif (_curInventoryTemplate.empty())\n\t\t{\n\t\t\t// use \"empty template\" icons\n\t\t\t_game->getMod()->getSurface(\"InvCopy\")->blitNShade(_btnCreateTemplate, 0, 0);\n\t\t\t_game->getMod()->getSurface(\"InvPasteEmpty\")->blitNShade(_btnApplyTemplate, 0, 0);\n\t\t\t_btnApplyTemplate->setTooltip(\"STR_CLEAR_INVENTORY\");\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// use \"active template\" icons\n\t\t\t_game->getMod()->getSurface(\"InvCopyActive\")->blitNShade(_btnCreateTemplate, 0, 0);\n\t\t\t_game->getMod()->getSurface(\"InvPaste\")->blitNShade(_btnApplyTemplate, 0, 0);\n\t\t\t_btnApplyTemplate->setTooltip(\"STR_APPLY_INVENTORY_TEMPLATE\");\n\t\t}\n\t\t_btnCreateTemplate->initSurfaces();\n\t\t_btnApplyTemplate->initSurfaces();\n\t}\n\telse\n\t{\n\t\t_btnCreateTemplate->clear();\n\t\t_btnApplyTemplate->clear();\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/InventoryState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <map>\n#include \"../Engine/State.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Savegame/EquipmentLayoutItem.h\"\n\n\nnamespace OpenXcom\n{\n\nclass Surface;\nclass Text;\nclass TextEdit;\nclass NumberText;\nclass InteractiveSurface;\nclass Inventory;\nclass SavedBattleGame;\nclass BattlescapeState;\nclass BattleUnit;\nclass BattlescapeButton;\nclass Base;\n\n/**\n * Screen which displays soldier's inventory.\n */\nclass InventoryState : public State\n{\nprivate:\n\tSurface *_bg, *_soldier;\n\tText *_txtItem, *_txtAmmo, *_txtWeight, *_txtTus, *_txtStatLine1, *_txtStatLine2, *_txtStatLine3, *_txtStatLine4, *_txtPosition;\n\tText *_txtNameStatic;\n\tTextEdit *_txtName;\n\tTextEdit *_btnQuickSearch;\n\tBattlescapeButton *_btnOk, *_btnPrev, *_btnNext, *_btnUnload, *_btnGround, *_btnRank, *_btnArmor;\n\tBattlescapeButton *_btnCreateTemplate, *_btnApplyTemplate;\n\tBattlescapeButton *_btnLinks;\n\tSurface *_selAmmo;\n\tInventory *_inv;\n\tstd::vector<EquipmentLayoutItem*> _curInventoryTemplate, _tempInventoryTemplate;\n\tSavedBattleGame *_battleGame;\n\tconst bool _tu, _noCraft;\n\tBattlescapeState *_parent;\n\tBase *_base;\n\tstd::map<Soldier*, Craft*> _backup;\n\tbool _resetCustomDeploymentBackup;\n\tstd::string _currentTooltip;\n\tstd::string _currentDamageTooltip;\n\tint _mouseHoverItemFrame = 0;\n\tBattleItem *_mouseHoverItem = nullptr;\n\tBattleItem *_currentDamageTooltipItem = nullptr;\n\tbool _reloadUnit;\n\tint _globalLayoutIndex;\n\tint _prev_key = 0, _key_repeats = 0;\n\t/// Helper method for Create Template button\n\tvoid _createInventoryTemplate(std::vector<EquipmentLayoutItem*> &inventoryTemplate);\n\t/// Helper method for Apply Template button\n\tvoid _applyInventoryTemplate(std::vector<EquipmentLayoutItem*> &inventoryTemplate);\npublic:\n\t/// Creates the Inventory state.\n\tInventoryState(bool tu, BattlescapeState *parent, Base *base, bool noCraft = false);\n\t/// Cleans up the Inventory state.\n\t~InventoryState();\n\t/// Updates all soldier info.\n\tvoid setGlobalLayoutIndex(int index, bool armorChanged);\n\tvoid init() override;\n\t/// Handler for pressing on the Name edit.\n\tvoid edtSoldierPress(Action *action);\n\t/// Handler for changing text on the Name edit.\n\tvoid edtSoldierChange(Action *action);\n\t/// Updates the soldier info (Weight, TU).\n\tvoid updateStats();\n\t/// Saves the soldiers' equipment-layout.\n\tvoid saveEquipmentLayout();\n\t/// Handler for clicking the Armor button.\n\tvoid btnArmorClick(Action *action);\n\tvoid btnArmorClickRight(Action *action);\n\tvoid btnDiaryLightClick(Action *action);\n\tvoid btnArmorClickMiddle(Action *action);\n\t/// Methods for handling the global equipment layout save/load hotkeys.\n\tvoid saveGlobalLayout(int index, bool includingArmor);\n\tvoid loadGlobalLayout(int index);\n\tbool loadGlobalLayoutArmor(int index);\n\tbool tryArmorChange(const std::string& armorName);\n\tvoid btnGlobalEquipmentLayoutClick(Action *action);\n\t/// Handler for clicking the Load button.\n\tvoid btnInventoryLoadClick(Action *action);\n\t/// Handler for clicking the Save button.\n\tvoid btnInventorySaveClick(Action *action);\n\t/// Handler for clicking the Ufopaedia button.\n\tvoid btnUfopaediaClick(Action *action);\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handlers for Quick Search.\n\tvoid btnQuickSearchToggle(Action *action);\n\tvoid btnQuickSearchApply(Action *action);\n\t/// Handler for clicking the Previous button.\n\tvoid btnPrevClick(Action *action);\n\t/// Handler for clicking the Next button.\n\tvoid btnNextClick(Action *action);\n\t/// Handler for clicking the Unload button.\n\tvoid btnUnloadClick(Action *action);\n\t/// Handler for clicking on the Ground -> button.\n\tvoid btnGroundClickForward(Action *action);\n\tvoid btnGroundClickBackward(Action *action);\n\t/// Handler for clicking the Rank button.\n\tvoid btnRankClick(Action *action);\n\t/// Handler for clicking the Links button.\n\tvoid btnLinksClick(Action *action);\n\t/// Handler for clicking on the Create Template button.\n\tvoid btnCreateTemplateClick(Action *action);\n\tvoid btnCreatePersonalTemplateClick(Action *action);\n\t/// Handler for clicking the Apply Template button.\n\tvoid btnApplyTemplateClick(Action *action);\n\tvoid btnApplyPersonalTemplateClick(Action *action);\n\tvoid btnShowPersonalTemplateClick(Action *action);\n\t/// Handler for hitting the Clear Inventory hotkey.\n\tvoid onClearInventory(Action *action);\n\t/// Handler for hitting the Auto-equip hotkey.\n\tvoid onAutoequip(Action *action);\n\t/// Handler for clicking on the inventory.\n\tvoid invClick(Action *action);\n\t/// Handler for showing item info.\n\tvoid calculateCurrentDamageTooltip();\n\tvoid invMouseOver(Action *action);\n\t/// Handler for hiding item info.\n\tvoid invMouseOut(Action *action);\n\t/// Handler for hitting the [Move Ground Inventory To Base] hotkey.\n\tvoid onMoveGroundInventoryToBase(Action *action);\n\t/// Handles keypresses.\n\tvoid handle(Action *action) override;\n\t/// Runs state functionality every cycle.\n\tvoid think() override;\n\t/// Handler for showing tooltip with extra information (day/night indicator).\n\tvoid txtTooltipInExtraOK(Action *action);\n\t/// Handler for showing tooltip.\n\tvoid txtTooltipIn(Action *action);\n\t/// Handler for hiding tooltip.\n\tvoid txtTooltipOut(Action *action);\n\t/// Handler for showing armor tooltip.\n\tvoid txtArmorTooltipIn(Action *action);\n\t/// Handler for hiding armor tooltip.\n\tvoid txtArmorTooltipOut(Action *action);\n\nprivate:\n\t/// Update the visibility and icons for the template buttons.\n\tvoid updateTemplateButtons(bool isVisible);\n\t/// Refresh the hover status of the mouse.\n\tvoid refreshMouse();\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/ItemSprite.cpp",
    "content": "/*\n * Copyright 2010-2015 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ItemSprite.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Savegame/BattleUnit.h\"\n#include \"../Savegame/BattleItem.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Sets up a ItemSprite with the specified size and position.\n * @param width Width in pixels.\n * @param height Height in pixels.\n * @param x X position in pixels.\n * @param y Y position in pixels.\n */\nItemSprite::ItemSprite(Surface* dest, const Mod* mod, const SavedBattleGame* save, int frame) :\n\t_itemSurface(const_cast<Mod*>(mod)->getSurfaceSet(\"FLOOROB.PCK\")),\n\t_animationFrame(frame),\n\t_dest(dest),\n\t_save(save)\n{\n\n}\n\n/**\n * Deletes the ItemSprite.\n */\nItemSprite::~ItemSprite()\n{\n\n}\n\n/**\n * Draws a item, using the drawing rules of the item or unit if it's corpse.\n * This function is called by Map, for each item on the screen.\n */\nvoid ItemSprite::draw(const BattleItem* item, int x, int y, int shade)\n{\n\tconst Surface* sprite = item->getFloorSprite(_itemSurface, _save, _animationFrame, shade);\n\tif (sprite)\n\t{\n\t\tScriptWorkerBlit work;\n\t\tBattleItem::ScriptFill(&work, item, _save, BODYPART_ITEM_FLOOR, _animationFrame, shade);\n\t\twork.executeBlit(sprite, _dest, x, y, shade);\n\t}\n}\n\n/**\n * Draws shadow of item.\n */\nvoid ItemSprite::drawShadow(const BattleItem* item, int x, int y)\n{\n\tconst Surface* sprite = item->getFloorSprite(_itemSurface, _save, _animationFrame, 16);\n\tif (sprite)\n\t{\n\t\tsprite->blitNShade(_dest, x, y, 16);\n\t}\n}\n\n} //namespace OpenXcom\n"
  },
  {
    "path": "src/Battlescape/ItemSprite.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2015 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/Surface.h\"\n\nnamespace OpenXcom\n{\n\nclass BattleUnit;\nclass BattleItem;\nclass SavedBattleGame;\nclass SurfaceSet;\nclass Mod;\n\n/**\n * A class that renders a specific unit, given its render rules\n * combining the right frames from the surfaceset.\n */\nclass ItemSprite\n{\nprivate:\n\tconst SurfaceSet *_itemSurface;\n\tint _animationFrame;\n\tSurface *_dest;\n\tconst SavedBattleGame *_save;\n\n\npublic:\n\t/// Creates a new ItemSprite at the specified position and size.\n\tItemSprite(Surface* dest, const Mod* mod, const SavedBattleGame *_save, int frame);\n\t/// Cleans up the ItemSprite.\n\t~ItemSprite();\n\t/// Draws the item.\n\tvoid draw(const BattleItem* item, int x, int y, int shade);\n\t/// Draws the item shadow.\n\tvoid drawShadow(const BattleItem* item, int x, int y);\n};\n\n} //namespace OpenXcom\n"
  },
  {
    "path": "src/Battlescape/Map.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Map.h\"\n#include \"Camera.h\"\n#include \"UnitSprite.h\"\n#include \"ItemSprite.h\"\n#include \"Pathfinding.h\"\n#include \"TileEngine.h\"\n#include \"Projectile.h\"\n#include \"Explosion.h\"\n#include \"BattlescapeState.h\"\n#include \"Particle.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/SurfaceSet.h\"\n#include \"../Engine/Timer.h\"\n#include \"../Engine/Language.h\"\n#include \"../Engine/Palette.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Screen.h\"\n#include \"../Engine/ShaderDraw.h\"\n#include \"../Engine/ShaderMove.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"../Savegame/Tile.h\"\n#include \"../Savegame/BattleUnit.h\"\n#include \"../Savegame/BattleItem.h\"\n#include \"../Ufopaedia/Ufopaedia.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"../Mod/RuleInterface.h\"\n#include \"../Mod/MapDataSet.h\"\n#include \"../Mod/MapData.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Mod/RuleEnviroEffects.h\"\n#include \"BattlescapeMessage.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Interface/NumberText.h\"\n#include \"../Interface/Text.h\"\n#include \"../fmath.h\"\n\n\n/*\n  1) Map origin is top corner.\n  2) X axis goes downright. (width of the map)\n  3) Y axis goes downleft. (length of the map\n  4) Z axis goes up (height of the map)\n\n           0,0\n            /\\\n           /  \\\n        y+ \\  / x+\n            \\/\n\n  Compass directions\n\n         W  /\\  N\n           /  \\\n           \\  /\n         S  \\/  E\n\n  Unit directions\n\n         6  /\\  0\n           /  \\\n           \\  /\n         4  \\/  2\n\n  Big units parts\n\n            /\\\n           /0 \\\n          /\\  /\\\n         /2 \\/1 \\\n         \\  /\\  /\n          \\/3 \\/\n           \\  /\n            \\/\n */\n\nnamespace OpenXcom\n{\n\n/**\n * Sets up a map with the specified size and position.\n * @param game Pointer to the core game.\n * @param width Width in pixels.\n * @param height Height in pixels.\n * @param x X position in pixels.\n * @param y Y position in pixels.\n * @param visibleMapHeight Current visible map height.\n */\nMap::Map(Game *game, int width, int height, int x, int y, int visibleMapHeight) : InteractiveSurface(width, height, x, y),\n\t_game(game), _isTFTD(false), _arrow(0), _anyIndicator(false), _isAltPressed(false), _isCtrlPressed(false),\n\t_selectorX(0), _selectorY(0), _mouseX(0), _mouseY(0), _cursorType(CT_NORMAL), _cursorSize(1), _animFrame(0),\n\t_projectile(0), _followProjectile(true), _projectileInFOV(false), _explosionInFOV(false), _launch(false), _visibleMapHeight(visibleMapHeight),\n\t_unitDying(false), _smoothingEngaged(false), _flashScreen(false), _bgColor(15), _projectileSet(0), _showObstacles(false), _showInfoOnCursor(false)\n{\n\t// TODO: extract to a better place later\n\tfor (const auto& pair : Options::mods)\n\t{\n\t\tif (pair.second)\n\t\t{\n\t\t\tif (pair.first == \"xcom2\")\n\t\t\t{\n\t\t\t\t_isTFTD = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t_iconHeight = _game->getMod()->getInterface(\"battlescape\")->getElement(\"icons\")->h;\n\t_iconWidth = _game->getMod()->getInterface(\"battlescape\")->getElement(\"icons\")->w;\n\t_messageColor = _game->getMod()->getInterface(\"battlescape\")->getElement(\"messageWindows\")->color;\n\n\tauto* itf = _game->getMod()->getInterface(\"battlescape\")->getElement(\"thinkingProgressBar\");\n\t_hostileBarColor = itf->color;\n\t_neutralBarColor = itf->color2;\n\t_borderBarColor = itf->border;\n\n\tPathPreview previewSetting = Options::battleNewPreviewPath;\n\t_smoothCamera = Options::battleSmoothCamera;\n\tif (Options::traceAI)\n\t{\n\t\t// turn everything on because we want to see the markers.\n\t\tpreviewSetting = PATH_ARROW_TU;\n\t}\n\t_previewSettingArrows = previewSetting & PATH_ARROWS;\n\t_previewSettingTu     = previewSetting & PATH_TU_COST;\n\t_previewSettingEnergy = previewSetting & PATH_ENERGY_COST;\n\n\t_save = _game->getSavedGame()->getSavedBattle();\n\tif ((int)(_game->getMod()->getLUTs()->size()) > _save->getDepth())\n\t{\n\t\t_transparencies = &_game->getMod()->getLUTs()->at(_save->getDepth());\n\t}\n\telse\n\t{\n\t\tconst static std::vector<Uint8> dummy;\n\t\t_transparencies = &dummy;\n\t}\n\n\t_spriteWidth = _game->getMod()->getSurfaceSet(\"BLANKS.PCK\")->getFrame(0)->getWidth();\n\t_spriteHeight = _game->getMod()->getSurfaceSet(\"BLANKS.PCK\")->getFrame(0)->getHeight();\n\t_message = new BattlescapeMessage(320, (visibleMapHeight < 200)? visibleMapHeight : 200, 0, 0);\n\t_message->setX(_game->getScreen()->getDX());\n\t_message->setY((visibleMapHeight - _message->getHeight()) / 2);\n\t_message->setTextColor(_messageColor);\n\t_camera = new Camera(_spriteWidth, _spriteHeight, _save->getMapSizeX(), _save->getMapSizeY(), _save->getMapSizeZ(), this, visibleMapHeight);\n\t_scrollMouseTimer = new Timer(SCROLL_INTERVAL);\n\t_scrollMouseTimer->onTimer((SurfaceHandler)&Map::scrollMouse);\n\t_scrollKeyTimer = new Timer(SCROLL_INTERVAL);\n\t_scrollKeyTimer->onTimer((SurfaceHandler)&Map::scrollKey);\n\t_camera->setScrollTimer(_scrollMouseTimer, _scrollKeyTimer);\n\t_obstacleTimer = new Timer(2500);\n\t_obstacleTimer->stop();\n\t_obstacleTimer->onTimer((SurfaceHandler)&Map::disableObstacles);\n\n\t_showInfoOnCursor = (Options::oxceShowAccuracyOnCrosshair == 1 && Options::battleUFOExtenderAccuracy) || Options::oxceShowAccuracyOnCrosshair == 2;\n\t_txtAccuracy = new Text(44, 18, 0, 0);\n\t_txtAccuracy->setSmall();\n\t_txtAccuracy->setPalette(_game->getScreen()->getPalette());\n\t_txtAccuracy->setHighContrast(true);\n\t_txtAccuracy->initText(_game->getMod()->getFont(\"FONT_BIG\"), _game->getMod()->getFont(\"FONT_SMALL\"), _game->getLanguage());\n\t_cacheActiveWeaponUfopediaArticleUnlocked = -1;\n\t_cacheIsCtrlPressed = false;\n\t_cacheCursorPosition = TileEngine::invalid;\n\t_cacheHasLOS = -1;\n\n\t_nightVisionOn = false;\n\tif (Options::oxceToggleNightVisionType == 2)\n\t{\n\t\t// persisted per campaign\n\t\t_nightVisionOn = _game->getSavedGame()->getToggleNightVision();\n\t}\n\telse if (Options::oxceToggleNightVisionType == 1)\n\t{\n\t\t// persisted per battle\n\t\t_nightVisionOn = _save->getToggleNightVision();\n\t}\n\n\t_debugVisionMode = 0;\n\tif (Options::oxceToggleBrightnessType == 2)\n\t{\n\t\t// persisted per campaign\n\t\t_debugVisionMode = _game->getSavedGame()->getToggleBrightness();\n\t}\n\telse if (Options::oxceToggleBrightnessType == 1)\n\t{\n\t\t// persisted per battle\n\t\t_debugVisionMode = _save->getToggleBrightness();\n\t}\n\n\t_save->setToggleNightVisionTemp(false);\n\t_save->setToggleNightVisionColorTemp(0);\n\t_save->setToggleBrightnessTemp(_debugVisionMode);\n\n\t_fadeShade = 16;\n\t_nvColor = 0;\n\t_fadeTimer = new Timer(FADE_INTERVAL);\n\t_fadeTimer->onTimer((SurfaceHandler)&Map::fadeShade);\n\t_fadeTimer->start();\n\n\tauto* enviro = _save->getEnviroEffects();\n\tif (enviro)\n\t{\n\t\t_bgColor = enviro->getMapBackgroundColor();\n\t}\n\n\t_stunIndicator = _game->getMod()->getSurface(\"FloorStunIndicator\", false);\n\t_woundIndicator = _game->getMod()->getSurface(\"FloorWoundIndicator\", false);\n\t_burnIndicator = _game->getMod()->getSurface(\"FloorBurnIndicator\", false);\n\t_shockIndicator = _game->getMod()->getSurface(\"FloorShockIndicator\", false);\n\t_anyIndicator = _stunIndicator || _woundIndicator || _burnIndicator || _shockIndicator;\n\n\tif (enviro)\n\t{\n\t\tif (!enviro->getMapShockIndicator().empty())\n\t\t{\n\t\t\t_shockIndicator = _game->getMod()->getSurface(enviro->getMapShockIndicator(), false);\n\t\t}\n\t}\n\n\t_vaporParticlesInit.resize(_camera->getMapSizeY() * _camera->getMapSizeX());\n\t_vaporParticles.resize(_camera->getMapSizeY() * _camera->getMapSizeX());\n}\n\n/**\n * Deletes the map.\n */\nMap::~Map()\n{\n\tdelete _scrollMouseTimer;\n\tdelete _scrollKeyTimer;\n\tdelete _fadeTimer;\n\tdelete _obstacleTimer;\n\tdelete _arrow;\n\tdelete _message;\n\tdelete _camera;\n\tdelete _txtAccuracy;\n}\n\n/**\n * Initializes the map.\n */\nvoid Map::init()\n{\n\t// load the tiny arrow into a surface\n\tint f = Palette::blockOffset(1); // yellow\n\tint b = 15; // black\n\tint pixels[81] = { 0, 0, b, b, b, b, b, 0, 0,\n\t\t\t\t\t   0, 0, b, f, f, f, b, 0, 0,\n\t\t\t\t\t   0, 0, b, f, f, f, b, 0, 0,\n\t\t\t\t\t   b, b, b, f, f, f, b, b, b,\n\t\t\t\t\t   b, f, f, f, f, f, f, f, b,\n\t\t\t\t\t   0, b, f, f, f, f, f, b, 0,\n\t\t\t\t\t   0, 0, b, f, f, f, b, 0, 0,\n\t\t\t\t\t   0, 0, 0, b, f, b, 0, 0, 0,\n\t\t\t\t\t   0, 0, 0, 0, b, 0, 0, 0, 0 };\n\n\t_arrow = new Surface(9, 9);\n\t_arrow->setPalette(this->getPalette());\n\t_arrow->lock();\n\tfor (int y = 0; y < 9;++y)\n\t\tfor (int x = 0; x < 9; ++x)\n\t\t\t_arrow->setPixel(x, y, pixels[x+(y*9)]);\n\t_arrow->unlock();\n\n\t_projectile = 0;\n\tif (_save->getDepth() == 0)\n\t{\n\t\t_projectileSet = _game->getMod()->getSurfaceSet(\"Projectiles\");\n\t}\n\telse\n\t{\n\t\t_projectileSet = _game->getMod()->getSurfaceSet(\"UnderwaterProjectiles\");\n\t}\n}\n\n/**\n * Keeps the animation timers running.\n */\nvoid Map::think()\n{\n\t_scrollMouseTimer->think(0, this);\n\t_scrollKeyTimer->think(0, this);\n\t_fadeTimer->think(0, this);\n\t_obstacleTimer->think(0, this);\n}\n\n/**\n * Draws the whole map, part by part.\n */\nvoid Map::draw()\n{\n\tif (!_redraw)\n\t{\n\t\treturn;\n\t}\n\n\t// normally we'd call for a Surface::draw();\n\t// but we don't want to clear the background with colour 0, which is transparent (aka black)\n\t// we use colour 15 because that actually corresponds to the colour we DO want in all variations of the xcom and tftd palettes.\n\t// Note: un-hardcoded the color from 15 to ruleset value, default 15\n\t_redraw = false;\n\tShaderDrawFunc(\n\t\t[](Uint8& dest, Uint8 color)\n\t\t{\n\t\t\tdest = color;\n\t\t},\n\t\tShaderSurface(this),\n\t\tShaderScalar<Uint8>(Palette::blockOffset(0) + _bgColor)\n\t);\n\n\tTile *t;\n\n\t_projectileInFOV = _save->getDebugMode();\n\tif (_projectile)\n\t{\n\t\tt = _save->getTile(_projectile->getPosition(0).toTile());\n\t\tif (_save->getSide() == FACTION_PLAYER || (t && t->getVisible()))\n\t\t{\n\t\t\t_projectileInFOV = true;\n\t\t}\n\t}\n\t_explosionInFOV = _save->getDebugMode();\n\tif (!_explosions.empty())\n\t{\n\t\tfor (auto* explosion : _explosions)\n\t\t{\n\t\t\tif (explosion->isBig())\n\t\t\t{\n\t\t\t\t_explosionInFOV = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tt = _save->getTile(explosion->getPosition().toTile());\n\t\t\tif (t && t->getVisible())\n\t\t\t{\n\t\t\t\t_explosionInFOV = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tif ((_save->getSelectedUnit() && _save->getSelectedUnit()->getVisible()) || _unitDying || _save->getSide() == FACTION_PLAYER || _save->getDebugMode() || _projectileInFOV || _explosionInFOV)\n\t{\n\t\tdrawTerrain(this);\n\t}\n\telse\n\t{\n\t\t_message->blit(this->getSurface());\n\t}\n}\n\nvoid Map::refreshAIProgress(int progress)\n{\n\tif (_save->getSide() == FACTION_NEUTRAL)\n\t{\n\t\t_message->setProgressBarColor(_neutralBarColor, _borderBarColor);\n\t}\n\telse\n\t{\n\t\t_message->setProgressBarColor(_hostileBarColor, _borderBarColor);\n\t}\n\t_message->setProgressValue(progress);\n}\n\n/**\n * Replaces a certain amount of colors in the surface's palette.\n * @param colors Pointer to the set of colors.\n * @param firstcolor Offset of the first color to replace.\n * @param ncolors Amount of colors to replace.\n */\nvoid Map::setPalette(const SDL_Color *colors, int firstcolor, int ncolors)\n{\n\tSurface::setPalette(colors, firstcolor, ncolors);\n\tfor (auto* mds : *_save->getMapDataSets())\n\t{\n\t\tmds->getSurfaceset()->setPalette(colors, firstcolor, ncolors);\n\t}\n\t_message->setPalette(colors, firstcolor, ncolors);\n\trefreshHiddenMovementBackground();\n\t_message->initText(_game->getMod()->getFont(\"FONT_BIG\"), _game->getMod()->getFont(\"FONT_SMALL\"), _game->getLanguage());\n\t_message->setText(_game->getLanguage()->getString(\"STR_HIDDEN_MOVEMENT\"), _game->getLanguage()->getString(\"STR_THINKING\"));\n}\n\nvoid Map::refreshHiddenMovementBackground()\n{\n\t_message->setBackground(_game->getMod()->getSurface(_save->getHiddenMovementBackground()));\n}\n\n/**\n * Get shade of wall.\n * @param part For what wall do calculations.\n * @param tileFrot Tile of wall.\n * @return Current shade of wall.\n */\nint Map::getWallShade(TilePart part, Tile* tileFrot)\n{\n\tint shade;\n\tif (tileFrot->isDiscovered(O_FLOOR))\n\t{\n\t\tshade = reShade(tileFrot);\n\t}\n\telse\n\t{\n\t\tshade = 16;\n\t}\n\tif (part)\n\t{\n\t\tif ((tileFrot->isDoor(part) || tileFrot->isUfoDoor(part)) && tileFrot->isDiscovered(part))\n\t\t{\n\t\t\tPosition offset =\n\t\t\t\tpart == O_NORTHWALL ? Position(1,0,0) :\n\t\t\t\tpart == O_WESTWALL ? Position(0,1,0) :\n\t\t\t\t\tthrow Exception(\"Unsupported tile part for wall shade\");\n\n\t\t\tTile *tileBehind = _save->getTile(tileFrot->getPosition() - offset);\n\n\t\t\tshade = std::min(reShade(tileFrot), tileBehind ? tileBehind->getShade() + 5 : 16);\n\t\t}\n\t}\n\treturn shade;\n}\n\n/**\n * Check two positions if have same XY cords\n */\nstatic bool positionHaveSameXY(Position a, Position b)\n{\n\treturn a.x == b.x && a.y == b.y;\n}\n\n/**\n * Check two positions if have same XY cords\n */\nstatic bool positionInRangeXY(Position a, Position b, int diff)\n{\n\treturn std::abs(a.x - b.x) <= diff && std::abs(a.y - b.y) <= diff;\n}\n\nnamespace\n{\n\nstatic const int ArrowBobOffsets[8] = {0,1,2,1,0,1,2,1};\n\nstatic const int ArrowColorsUFO[4]  = { 6,  3, 14, 4 }; // white,    red, blue, green\nstatic const int ArrowColorsTFTD[4] = { 4, 11, 16, 6 }; // white, orange, blue, green\n\nint getArrowBobForFrame(int frame)\n{\n\treturn ArrowBobOffsets[frame % 8];\n}\n\nint getShadePulseForFrame(int shade, int frame)\n{\n\tif (shade > 7) shade = 7;\n\tif (shade < 2) shade = 2;\n\tshade += (ArrowBobOffsets[frame % 8] * 2 - 2);\n\treturn shade;\n}\n\n}\n\n/**\n * Draw part of unit graphic that overlap current tile.\n * @param surface\n * @param unitTile\n * @param currTile\n * @param currTileScreenPosition\n * @param shade\n * @param obstacleShade\n * @param topLayer\n */\nvoid Map::drawUnit(UnitSprite &unitSprite, Tile *unitTile, Tile *currTile, Position currTileScreenPosition, bool topLayer, BattleUnit* movingUnit)\n{\n\tconst int tileFoorWidth = 32;\n\tconst int tileFoorHeight = 16;\n\tconst int tileHeight = 40;\n\n\tif (!unitTile)\n\t{\n\t\treturn;\n\t}\n\tBattleUnit* bu = unitTile->getOverlappingUnit(_save, TUO_ALWAYS);\n\tPosition unitOffset;\n\tbool unitFromBelow = false;\n\tbool unitFromAbove = false;\n\tif (bu)\n\t{\n\t\tif (bu != unitTile->getUnit())\n\t\t{\n\t\t\tunitFromBelow = true;\n\t\t}\n\t}\n\telse if (movingUnit && unitTile == currTile)\n\t{\n\t\tauto* upperTile = _save->getAboveTile(unitTile);\n\t\tif (upperTile && upperTile->hasNoFloor(_save))\n\t\t{\n\t\t\tbu = upperTile->getUnit();\n\t\t}\n\t\tif (bu != movingUnit)\n\t\t{\n\t\t\treturn;\n\t\t}\n\t\tunitFromAbove = true;\n\t}\n\telse\n\t{\n\t\treturn;\n\t}\n\n\tif (!(bu->getVisible() || _save->getDebugMode()))\n\t{\n\t\treturn;\n\t}\n\n\tunitOffset.x = unitTile->getPosition().x - bu->getPosition().x;\n\tunitOffset.y = unitTile->getPosition().y - bu->getPosition().y;\n\tint part = unitOffset.x + unitOffset.y*2;\n\n\tbool moving = bu->getStatus() == STATUS_WALKING || bu->getStatus() == STATUS_FLYING;\n\tint bonusWidth = moving ? 0 : tileFoorWidth;\n\tint topMargin = 0;\n\tint bottomMargin = 0;\n\n\t//if unit is from below then we draw only part that in in tile\n\tif (unitFromBelow)\n\t{\n\t\tbottomMargin = -tileFoorHeight / 2;\n\t\ttopMargin = tileFoorHeight;\n\t}\n\telse if (topLayer)\n\t{\n\t\ttopMargin = 2 * tileFoorHeight;\n\t}\n\telse\n\t{\n\t\tconst Tile *top = _save->getAboveTile(unitTile);\n\t\tif (top && top->getOverlappingUnit(_save, TUO_ALWAYS) == bu)\n\t\t{\n\t\t\ttopMargin = -tileFoorHeight / 2;\n\t\t}\n\t\telse\n\t\t{\n\t\t\ttopMargin = tileFoorHeight;\n\t\t}\n\t}\n\n\tGraphSubset mask = GraphSubset(tileFoorWidth + bonusWidth, tileHeight + topMargin + bottomMargin).offset(currTileScreenPosition.x - bonusWidth / 2, currTileScreenPosition.y - topMargin);\n\n\tif (moving)\n\t{\n\t\tGraphSubset leftMask = mask.offset(-tileFoorWidth/2, 0);\n\t\tGraphSubset rightMask = mask.offset(+tileFoorWidth/2, 0);\n\t\tint direction = bu->getDirection();\n\t\tPosition partCurr = currTile->getPosition();\n\t\tPosition partDest = bu->getDestination() + unitOffset;\n\t\tPosition partLast = bu->getLastPosition() + unitOffset;\n\t\tbool isTileDestPos = positionHaveSameXY(partDest, partCurr);\n\t\tbool isTileLastPos = positionHaveSameXY(partLast, partCurr);\n\n\t\tif (unitFromAbove && partLast != unitTile->getPosition())\n\t\t{\n\t\t\t//this tile is below moving unit and it do not change levels, nothing to draw\n\t\t\treturn;\n\t\t}\n\n\t\t//adjusting mask\n\t\tif (positionHaveSameXY(partLast, partDest))\n\t\t{\n\t\t\tif (currTile == unitTile)\n\t\t\t{\n\t\t\t\t//no change\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t//nothing to draw\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\telse if (isTileDestPos)\n\t\t{\n\t\t\t//unit is moving to this tile\n\t\t\tswitch (direction)\n\t\t\t{\n\t\t\tcase 0:\n\t\t\tcase 1:\n\t\t\t\tmask = GraphSubset::intersection(mask, rightMask);\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\t//no change\n\t\t\t\tbreak;\n\t\t\tcase 3:\n\t\t\t\t//no change\n\t\t\t\tbreak;\n\t\t\tcase 4:\n\t\t\t\t//no change\n\t\t\t\tbreak;\n\t\t\tcase 5:\n\t\t\tcase 6:\n\t\t\t\tmask = GraphSubset::intersection(mask, leftMask);\n\t\t\t\tbreak;\n\t\t\tcase 7:\n\t\t\t\t//nothing to draw\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\telse if (isTileLastPos)\n\t\t{\n\t\t\t//unit is exiting this tile\n\t\t\tswitch (direction)\n\t\t\t{\n\t\t\tcase 0:\n\t\t\t\t//no change\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\tcase 2:\n\t\t\t\tmask = GraphSubset::intersection(mask, leftMask);\n\t\t\t\tbreak;\n\t\t\tcase 3:\n\t\t\t\t//nothing to draw\n\t\t\t\treturn;\n\t\t\tcase 4:\n\t\t\tcase 5:\n\t\t\t\tmask = GraphSubset::intersection(mask, rightMask);\n\t\t\t\tbreak;\n\t\t\tcase 6:\n\t\t\t\t//no change\n\t\t\t\tbreak;\n\t\t\tcase 7:\n\t\t\t\t//no change\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tPosition leftPos = partCurr + Position(-1, 0, 0);\n\t\t\tPosition rightPos = partCurr + Position(0, -1, 0);\n\t\t\tif (!topLayer && (partDest.z > partCurr.z || partLast.z > partCurr.z))\n\t\t\t{\n\t\t\t\t//unit change layers, it will be drawn by upper layer not lower.\n\t\t\t\treturn;\n\t\t\t}\n\t\t\telse if (\n\t\t\t\t(direction == 1 && (partDest == rightPos || partLast == leftPos)) ||\n\t\t\t\t(direction == 5 && (partDest == leftPos || partLast == rightPos)))\n\t\t\t{\n\t\t\t\tmask = GraphSubset(tileFoorWidth, tileHeight + 2 * tileFoorHeight).offset(currTileScreenPosition.x, currTileScreenPosition.y - 2 * tileFoorHeight);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t//unit is not moving close to tile\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\telse if (unitTile != currTile || unitFromAbove)\n\t{\n\t\treturn;\n\t}\n\n\tPosition tileScreenPosition;\n\t_camera->convertMapToScreen(unitTile->getPosition() + Position(0,0, (-unitFromBelow) + (+unitFromAbove)), &tileScreenPosition);\n\ttileScreenPosition += _camera->getMapOffset();\n\n\t//get shade helpers\n\tauto getTileShade = [&](Tile* tile)\n\t{\n\t\treturn tile ? (tile->isDiscovered(O_FLOOR) ? reShade(tile) : 16) : 16;\n\t};\n\tauto getMixedTileShade = [&](Tile* tile, int heightOffset, bool below)\n\t{\n\t\tint shadeLower = 0;\n\t\tint shadeUpper = 0;\n\t\tif (below)\n\t\t{\n\t\t\tshadeLower = getTileShade(_save->getBelowTile(tile));\n\t\t\tshadeUpper = getTileShade(tile);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tshadeLower = getTileShade(tile);\n\t\t\tshadeUpper = getTileShade(_save->getAboveTile(tile));\n\t\t}\n\n\t\treturn Interpolate(shadeLower, shadeUpper, -heightOffset, Position::TileZ);\n\t};\n\n\t// draw unit\n\tint shade = 0;\n\tUnitWalkingOffset offsets = calculateWalkingOffset(bu);\n\tif (moving)\n\t{\n\t\tconst Position start = bu->getPosition();\n\t\tconst Position end = bu->getDestination();\n\t\tconst auto minLevel = std::min(start.z, end.z); // Sint16\n\t\tconst int startShade = getMixedTileShade(_save->getTile(start), start.z == minLevel ? offsets.TerrainLevelOffset : 0, false);\n\t\tconst int endShade = getMixedTileShade(_save->getTile(end), end.z == minLevel ? offsets.TerrainLevelOffset : 0, false);\n\t\tshade = Interpolate(startShade, endShade, offsets.NormalizedMovePhase, 16);\n\t}\n\telse\n\t{\n\t\tshade = getMixedTileShade(currTile, offsets.TerrainLevelOffset, unitFromBelow);\n\t\tif (_showObstacles && unitTile->getObstacle(4))\n\t\t{\n\t\t\tshade = getShadePulseForFrame(shade, _animFrame);\n\t\t}\n\t}\n\tif (_debugVisionMode == 1)\n\t{\n\t\tshade = std::min(+NIGHT_VISION_SHADE, shade);\n\t}\n\tunitSprite.draw(bu, part, tileScreenPosition.x + offsets.ScreenOffset.x, tileScreenPosition.y + offsets.ScreenOffset.y, shade, mask, _isAltPressed && !_isCtrlPressed);\n}\n\n/**\n * Draw the terrain.\n * Keep this function as optimised as possible. It's big to minimise overhead of function calls.\n * @param surface The surface to draw on.\n */\nvoid Map::drawTerrain(Surface *surface)\n{\n\t_isAltPressed = _game->isAltPressed(true);\n\t_isCtrlPressed = _game->isCtrlPressed(true);\n\tint frameNumber = 0;\n\tSurfaceRaw<const Uint8> tmpSurface;\n\tTile *tile;\n\tint beginX = 0, endX = _save->getMapSizeX() - 1;\n\tint beginY = 0, endY = _save->getMapSizeY() - 1;\n\tint beginZ = 0, endZ = _save->getMapSizeZ() - 1;\n\tPosition mapPosition, screenPosition, bulletPositionScreen, movingUnitPosition;\n\tint bulletLowX=16000, bulletLowY=16000, bulletLowZ=16000, bulletHighX=0, bulletHighY=0, bulletHighZ=0;\n\tint dummy;\n\tBattleUnit *movingUnit = _save->getTileEngine()->getMovingUnit();\n\tint tileShade, tileColor, obstacleShade;\n\tUnitSprite unitSprite(surface, _game->getMod(), _save, _animFrame, _save->getDepth() != 0,\n\t\t_isTFTD ? ArrowColorsTFTD[1] : ArrowColorsUFO[1], _isTFTD ? ArrowColorsTFTD[2] : ArrowColorsUFO[2]);\n\tItemSprite itemSprite(surface, _game->getMod(), _save, _animFrame);\n\n\tconst int halfAnimFrame = (_animFrame / 2) % 4;\n\tconst int halfAnimFrameRest = (_animFrame % 2);\n\n\tNumberText *_numWaypid = 0;\n\n\t// if we got bullet, get the highest x and y tiles to draw it on\n\tif (_projectile && _explosions.empty())\n\t{\n\t\tint part = _projectile->getItem() ? 0 : BULLET_SPRITES-1;\n\t\tfor (int i = 0; i <= part; ++i)\n\t\t{\n\t\t\tif (_projectile->getPosition(1-i).x < bulletLowX)\n\t\t\t\tbulletLowX = _projectile->getPosition(1-i).x;\n\t\t\tif (_projectile->getPosition(1-i).y < bulletLowY)\n\t\t\t\tbulletLowY = _projectile->getPosition(1-i).y;\n\t\t\tif (_projectile->getPosition(1-i).z < bulletLowZ)\n\t\t\t\tbulletLowZ = _projectile->getPosition(1-i).z;\n\t\t\tif (_projectile->getPosition(1-i).x > bulletHighX)\n\t\t\t\tbulletHighX = _projectile->getPosition(1-i).x;\n\t\t\tif (_projectile->getPosition(1-i).y > bulletHighY)\n\t\t\t\tbulletHighY = _projectile->getPosition(1-i).y;\n\t\t\tif (_projectile->getPosition(1-i).z > bulletHighZ)\n\t\t\t\tbulletHighZ = _projectile->getPosition(1-i).z;\n\t\t}\n\t\t// divide by 16 to go from voxel to tile position\n\t\tbulletLowX = bulletLowX / 16;\n\t\tbulletLowY = bulletLowY / 16;\n\t\tbulletLowZ = bulletLowZ / 24;\n\t\tbulletHighX = bulletHighX / 16;\n\t\tbulletHighY = bulletHighY / 16;\n\t\tbulletHighZ = bulletHighZ / 24;\n\n\t\t// if the projectile is outside the viewport - center it back on it\n\t\t_camera->convertVoxelToScreen(_projectile->getPosition(), &bulletPositionScreen);\n\n\t\tif (_projectileInFOV && _followProjectile)\n\t\t{\n\t\t\tPosition newCam = _camera->getMapOffset();\n\t\t\tif (newCam.z != bulletHighZ) //switch level\n\t\t\t{\n\t\t\t\tnewCam.z = bulletHighZ;\n\t\t\t\tif (_projectileInFOV)\n\t\t\t\t{\n\t\t\t\t\t_camera->setMapOffset(newCam);\n\t\t\t\t\t_camera->convertVoxelToScreen(_projectile->getPosition(), &bulletPositionScreen);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (_smoothCamera)\n\t\t\t{\n\t\t\t\tif (_launch)\n\t\t\t\t{\n\t\t\t\t\t_launch = false;\n\t\t\t\t\tif ((bulletPositionScreen.x < 1 || bulletPositionScreen.x > surface->getWidth() - 1 ||\n\t\t\t\t\t\tbulletPositionScreen.y < 1 || bulletPositionScreen.y > _visibleMapHeight - 1))\n\t\t\t\t\t{\n\t\t\t\t\t\t_camera->centerOnPosition(Position(bulletLowX, bulletLowY, bulletHighZ), false);\n\t\t\t\t\t\t_camera->convertVoxelToScreen(_projectile->getPosition(), &bulletPositionScreen);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!_smoothingEngaged)\n\t\t\t\t{\n\t\t\t\t\tif (bulletPositionScreen.x < 1 || bulletPositionScreen.x > surface->getWidth() - 1 ||\n\t\t\t\t\t\tbulletPositionScreen.y < 1 || bulletPositionScreen.y > _visibleMapHeight - 1)\n\t\t\t\t\t{\n\t\t\t\t\t\t_smoothingEngaged = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t_camera->jumpXY(surface->getWidth() / 2 - bulletPositionScreen.x, _visibleMapHeight / 2 - bulletPositionScreen.y);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tbool enough;\n\t\t\t\tdo\n\t\t\t\t{\n\t\t\t\t\tenough = true;\n\t\t\t\t\tif (bulletPositionScreen.x < 0)\n\t\t\t\t\t{\n\t\t\t\t\t\t_camera->jumpXY(+surface->getWidth(), 0);\n\t\t\t\t\t\tenough = false;\n\t\t\t\t\t}\n\t\t\t\t\telse if (bulletPositionScreen.x > surface->getWidth())\n\t\t\t\t\t{\n\t\t\t\t\t\t_camera->jumpXY(-surface->getWidth(), 0);\n\t\t\t\t\t\tenough = false;\n\t\t\t\t\t}\n\t\t\t\t\telse if (bulletPositionScreen.y < 0)\n\t\t\t\t\t{\n\t\t\t\t\t\t_camera->jumpXY(0, +_visibleMapHeight);\n\t\t\t\t\t\tenough = false;\n\t\t\t\t\t}\n\t\t\t\t\telse if (bulletPositionScreen.y > _visibleMapHeight)\n\t\t\t\t\t{\n\t\t\t\t\t\t_camera->jumpXY(0, -_visibleMapHeight);\n\t\t\t\t\t\tenough = false;\n\t\t\t\t\t}\n\t\t\t\t\t_camera->convertVoxelToScreen(_projectile->getPosition(), &bulletPositionScreen);\n\t\t\t\t}\n\t\t\t\twhile (!enough);\n\t\t\t}\n\t\t}\n\t}\n\n\t// get corner map coordinates to give rough boundaries in which tiles to redraw are\n\t_camera->convertScreenToMap(0, 0, &beginX, &dummy);\n\t_camera->convertScreenToMap(surface->getWidth(), 0, &dummy, &beginY);\n\t_camera->convertScreenToMap(surface->getWidth() + _spriteWidth, surface->getHeight() + _spriteHeight, &endX, &dummy);\n\t_camera->convertScreenToMap(0, surface->getHeight() + _spriteHeight, &dummy, &endY);\n\tbeginY -= (_camera->getViewLevel() * 2);\n\tbeginX -= (_camera->getViewLevel() * 2);\n\tif (beginX < 0)\n\t\tbeginX = 0;\n\tif (beginY < 0)\n\t\tbeginY = 0;\n\n\tif (!_camera->getShowAllLayers())\n\t{\n\t\tendZ = std::min(endZ, _camera->getViewLevel());\n\t}\n\tif (_camera->getShowSingleLayer())\n\t{\n\t\tbeginZ = _camera->getViewLevel();\n\t\tendZ = _camera->getViewLevel();\n\t}\n\n\n\tbool pathfinderTurnedOn = _save->getPathfinding()->isPathPreviewed();\n\n\tif (!_waypoints.empty() || (pathfinderTurnedOn && (_previewSettingTu || _previewSettingEnergy)))\n\t{\n\t\t_numWaypid = new NumberText(15, 15, 20, 30);\n\t\t_numWaypid->setPalette(getPalette());\n\t\t_numWaypid->setColor(pathfinderTurnedOn ? _messageColor + 1 : Palette::blockOffset(1));\n\t}\n\n\tif (movingUnit)\n\t{\n\t\tmovingUnitPosition = movingUnit->getPosition();\n\t}\n\n\tsurface->lock();\n\tconst Position cameraPos = _camera->getMapOffset();\n\tfor (int itZ = beginZ; itZ <= endZ; itZ++)\n\t{\n\t\tbool topLayer = itZ == endZ;\n\t\tfor (int itY = beginY; itY < endY; itY++)\n\t\t{\n\t\t\tmapPosition = Position(beginX, itY, itZ);\n\t\t\ttile = _save->getTile(mapPosition);\n\t\t\tfor (int itX = beginX; itX < endX; itX++, mapPosition.x++, tile++)\n\t\t\t{\n\t\t\t\t_camera->convertMapToScreen(mapPosition, &screenPosition);\n\t\t\t\tscreenPosition += cameraPos;\n\n\t\t\t\t// only render cells that are inside the surface\n\t\t\t\tif (screenPosition.x > -_spriteWidth && screenPosition.x < surface->getWidth() + _spriteWidth &&\n\t\t\t\t\tscreenPosition.y > -_spriteHeight && screenPosition.y < surface->getHeight() + _spriteHeight )\n\t\t\t\t{\n\t\t\t\t\tbool isUnitMovingNearby = movingUnit && positionInRangeXY(movingUnitPosition, mapPosition, 2);\n\n\t\t\t\t\tif (tile->isDiscovered(O_FLOOR))\n\t\t\t\t\t{\n\t\t\t\t\t\ttileShade = reShade(tile);\n\t\t\t\t\t\tobstacleShade = tileShade;\n\t\t\t\t\t\tif (_showObstacles)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (tile->isObstacle())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tobstacleShade = getShadePulseForFrame(tileShade, _animFrame);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\ttileShade = 16;\n\t\t\t\t\t\tobstacleShade = 16;\n\t\t\t\t\t}\n\n\t\t\t\t\ttileColor = tile->getMarkerColor();\n\n\t\t\t\t\t// Draw floor\n\t\t\t\t\ttmpSurface = tile->getSprite(O_FLOOR);\n\t\t\t\t\tif (tmpSurface)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (tile->getObstacle(O_FLOOR))\n\t\t\t\t\t\t\tSurface::blitRaw(surface, tmpSurface, screenPosition.x, screenPosition.y - tile->getYOffset(O_FLOOR), obstacleShade, false, _nvColor);\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tSurface::blitRaw(surface, tmpSurface, screenPosition.x, screenPosition.y - tile->getYOffset(O_FLOOR), tileShade, false, _nvColor);\n\t\t\t\t\t}\n\n\t\t\t\t\tauto* unit = tile->getUnit();\n\n\t\t\t\t\t// Draw cursor back\n\t\t\t\t\tif (_cursorType != CT_NONE && _selectorX > itX - _cursorSize && _selectorY > itY - _cursorSize && _selectorX < itX+1 && _selectorY < itY+1 && !_save->getBattleState()->getMouseOverIcons())\n\t\t\t\t\t{\n\t\t\t\t\t\tif (_camera->getViewLevel() == itZ)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (_cursorType != CT_AIM)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (unit && (unit->getVisible() || _save->getDebugMode()))\n\t\t\t\t\t\t\t\t\tframeNumber = halfAnimFrameRest; // yellow box\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\tframeNumber = 0; // red box\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (unit && (unit->getVisible() || _save->getDebugMode()))\n\t\t\t\t\t\t\t\t\tframeNumber = 7 + halfAnimFrame; // yellow animated crosshairs\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\tframeNumber = 6; // red static crosshairs\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttmpSurface = _game->getMod()->getSurfaceSet(\"CURSOR.PCK\")->getFrame(frameNumber);\n\t\t\t\t\t\t\tSurface::blitRaw(surface, tmpSurface, screenPosition.x, screenPosition.y, 0);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (_camera->getViewLevel() > itZ)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tframeNumber = 2; // blue box\n\t\t\t\t\t\t\ttmpSurface = _game->getMod()->getSurfaceSet(\"CURSOR.PCK\")->getFrame(frameNumber);\n\t\t\t\t\t\t\tSurface::blitRaw(surface, tmpSurface, screenPosition.x, screenPosition.y, 0);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (isUnitMovingNearby)\n\t\t\t\t\t{\n\t\t\t\t\t\t// special handling for a moving unit in background of tile.\n\t\t\t\t\t\tconstexpr static Position backPos[] =\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tPosition(0, -1, 0),\n\t\t\t\t\t\t\tPosition(-1, -1, 0),\n\t\t\t\t\t\t\tPosition(-1, 0, 0),\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tfor (size_t b = 0; b < std::size(backPos); ++b)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tdrawUnit(unitSprite, _save->getTile(mapPosition + backPos[b]), tile, screenPosition, topLayer);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Draw walls\n\t\t\t\t\t{\n\t\t\t\t\t\t// Draw west wall\n\t\t\t\t\t\ttmpSurface = tile->getSprite(O_WESTWALL);\n\t\t\t\t\t\tif (tmpSurface)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tint wallShade = getWallShade(O_WESTWALL, tile);\n\t\t\t\t\t\t\tif (tile->getObstacle(O_WESTWALL))\n\t\t\t\t\t\t\t\tSurface::blitRaw(surface, tmpSurface, screenPosition.x, screenPosition.y - tile->getYOffset(O_WESTWALL), obstacleShade, false, _nvColor);\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tSurface::blitRaw(surface, tmpSurface, screenPosition.x, screenPosition.y - tile->getYOffset(O_WESTWALL), wallShade, false, _nvColor);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Draw north wall\n\t\t\t\t\t\ttmpSurface = tile->getSprite(O_NORTHWALL);\n\t\t\t\t\t\tif (tmpSurface)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tint wallShade = getWallShade(O_NORTHWALL, tile);\n\t\t\t\t\t\t\tif (tile->getObstacle(O_NORTHWALL))\n\t\t\t\t\t\t\t\tSurface::blitRaw(surface, tmpSurface, screenPosition.x, screenPosition.y - tile->getYOffset(O_NORTHWALL), obstacleShade, bool(tile->getSprite(O_WESTWALL)), _nvColor);\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tSurface::blitRaw(surface, tmpSurface, screenPosition.x, screenPosition.y - tile->getYOffset(O_NORTHWALL), wallShade, bool(tile->getSprite(O_WESTWALL)), _nvColor);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Draw object\n\t\t\t\t\t\ttmpSurface = tile->getSprite(O_OBJECT);\n\t\t\t\t\t\tif (tmpSurface)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (tile->isBackTileObject(O_OBJECT))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (tile->getObstacle(O_OBJECT))\n\t\t\t\t\t\t\t\t\tSurface::blitRaw(surface, tmpSurface, screenPosition.x, screenPosition.y - tile->getYOffset(O_OBJECT), obstacleShade, false, _nvColor);\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\tSurface::blitRaw(surface, tmpSurface, screenPosition.x, screenPosition.y - tile->getYOffset(O_OBJECT), tileShade, false, _nvColor);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// draw an item on top of the floor (if any)\n\t\t\t\t\t\tBattleItem* item = tile->getTopItem();\n\t\t\t\t\t\tif (item)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\titemSprite.draw(item,\n\t\t\t\t\t\t\t\tscreenPosition.x,\n\t\t\t\t\t\t\t\tscreenPosition.y + tile->getTerrainLevel(),\n\t\t\t\t\t\t\t\ttileShade\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tif (_anyIndicator)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tBattleUnit *itemUnit = item->getUnit();\n\t\t\t\t\t\t\t\tif (itemUnit && itemUnit->getStatus() == STATUS_UNCONSCIOUS && itemUnit->indicatorsAreEnabled())\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tif (_burnIndicator && itemUnit->getFire() > 0)\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t_burnIndicator->blitNShade(surface,\n\t\t\t\t\t\t\t\t\t\t\tscreenPosition.x,\n\t\t\t\t\t\t\t\t\t\t\tscreenPosition.y + tile->getTerrainLevel(),\n\t\t\t\t\t\t\t\t\t\t\ttileShade);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse if (_woundIndicator && itemUnit->getFatalWounds() > 0)\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t_woundIndicator->blitNShade(surface,\n\t\t\t\t\t\t\t\t\t\t\tscreenPosition.x,\n\t\t\t\t\t\t\t\t\t\t\tscreenPosition.y + tile->getTerrainLevel(),\n\t\t\t\t\t\t\t\t\t\t\ttileShade);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse if (_shockIndicator && itemUnit->hasNegativeHealthRegen())\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t_shockIndicator->blitNShade(surface,\n\t\t\t\t\t\t\t\t\t\t\tscreenPosition.x,\n\t\t\t\t\t\t\t\t\t\t\tscreenPosition.y + tile->getTerrainLevel(),\n\t\t\t\t\t\t\t\t\t\t\ttileShade);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse if (_stunIndicator)\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t_stunIndicator->blitNShade(surface,\n\t\t\t\t\t\t\t\t\t\t\tscreenPosition.x,\n\t\t\t\t\t\t\t\t\t\t\tscreenPosition.y + tile->getTerrainLevel(),\n\t\t\t\t\t\t\t\t\t\t\ttileShade);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// check if we got bullet && it is in Field Of View\n\t\t\t\t\tif (_projectile && _projectileInFOV)\n\t\t\t\t\t{\n\t\t\t\t\t\ttmpSurface = nullptr;\n\t\t\t\t\t\tBattleItem* item = _projectile->getItem();\n\t\t\t\t\t\tif (item)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tPosition voxelPos = _projectile->getPosition();\n\t\t\t\t\t\t\t// draw shadow on the floor\n\t\t\t\t\t\t\tvoxelPos.z = _save->getTileEngine()->castedShade(voxelPos);\n\t\t\t\t\t\t\tif (voxelPos.x / 16 >= itX &&\n\t\t\t\t\t\t\t\tvoxelPos.y / 16 >= itY &&\n\t\t\t\t\t\t\t\tvoxelPos.x / 16 <= itX+1 &&\n\t\t\t\t\t\t\t\tvoxelPos.y / 16 <= itY+1 &&\n\t\t\t\t\t\t\t\tvoxelPos.z / 24 == itZ &&\n\t\t\t\t\t\t\t\t_save->getTileEngine()->isVoxelVisible(voxelPos))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t_camera->convertVoxelToScreen(voxelPos, &bulletPositionScreen);\n\n\t\t\t\t\t\t\t\titemSprite.drawShadow(item,\n\t\t\t\t\t\t\t\t\tbulletPositionScreen.x - 16,\n\t\t\t\t\t\t\t\t\tbulletPositionScreen.y - 26\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tvoxelPos = _projectile->getPosition();\n\t\t\t\t\t\t\t// draw thrown object\n\t\t\t\t\t\t\tif (voxelPos.x / 16 >= itX &&\n\t\t\t\t\t\t\t\tvoxelPos.y / 16 >= itY &&\n\t\t\t\t\t\t\t\tvoxelPos.x / 16 <= itX+1 &&\n\t\t\t\t\t\t\t\tvoxelPos.y / 16 <= itY+1 &&\n\t\t\t\t\t\t\t\tvoxelPos.z / 24 == itZ &&\n\t\t\t\t\t\t\t\t_save->getTileEngine()->isVoxelVisible(voxelPos))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t_camera->convertVoxelToScreen(voxelPos, &bulletPositionScreen);\n\n\t\t\t\t\t\t\t\titemSprite.draw(item,\n\t\t\t\t\t\t\t\t\tbulletPositionScreen.x - 16,\n\t\t\t\t\t\t\t\t\tbulletPositionScreen.y - 26,\n\t\t\t\t\t\t\t\t\ttileShade\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// draw bullet on the correct tile\n\t\t\t\t\t\t\tif (itX >= bulletLowX && itX <= bulletHighX && itY >= bulletLowY && itY <= bulletHighY)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tint begin = 0;\n\t\t\t\t\t\t\t\tint end = BULLET_SPRITES;\n\t\t\t\t\t\t\t\tint direction = 1;\n\t\t\t\t\t\t\t\tif (_projectile->isReversed())\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tbegin = BULLET_SPRITES - 1;\n\t\t\t\t\t\t\t\t\tend = -1;\n\t\t\t\t\t\t\t\t\tdirection = -1;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tfor (int i = begin; i != end; i += direction)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\ttmpSurface = _projectileSet->getFrame(_projectile->getParticle(i));\n\t\t\t\t\t\t\t\t\tif (tmpSurface)\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tPosition voxelPos = _projectile->getPosition(1-i);\n\t\t\t\t\t\t\t\t\t\t// draw shadow on the floor\n\t\t\t\t\t\t\t\t\t\tvoxelPos.z = _save->getTileEngine()->castedShade(voxelPos);\n\t\t\t\t\t\t\t\t\t\tif (voxelPos.x / 16 == itX &&\n\t\t\t\t\t\t\t\t\t\t\tvoxelPos.y / 16 == itY &&\n\t\t\t\t\t\t\t\t\t\t\tvoxelPos.z / 24 == itZ &&\n\t\t\t\t\t\t\t\t\t\t\t_save->getTileEngine()->isVoxelVisible(voxelPos))\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t_camera->convertVoxelToScreen(voxelPos, &bulletPositionScreen);\n\t\t\t\t\t\t\t\t\t\t\tbulletPositionScreen.x -= tmpSurface.getWidth() / 2;\n\t\t\t\t\t\t\t\t\t\t\tbulletPositionScreen.y -= tmpSurface.getHeight() / 2;\n\t\t\t\t\t\t\t\t\t\t\tSurface::blitRaw(surface, tmpSurface, bulletPositionScreen.x, bulletPositionScreen.y, 16, false, _nvColor);\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t// draw bullet itself\n\t\t\t\t\t\t\t\t\t\tvoxelPos = _projectile->getPosition(1-i);\n\t\t\t\t\t\t\t\t\t\tif (voxelPos.x / 16 == itX &&\n\t\t\t\t\t\t\t\t\t\t\tvoxelPos.y / 16 == itY &&\n\t\t\t\t\t\t\t\t\t\t\tvoxelPos.z / 24 == itZ &&\n\t\t\t\t\t\t\t\t\t\t\t_save->getTileEngine()->isVoxelVisible(voxelPos))\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t_camera->convertVoxelToScreen(voxelPos, &bulletPositionScreen);\n\t\t\t\t\t\t\t\t\t\t\tbulletPositionScreen.x -= tmpSurface.getWidth() / 2;\n\t\t\t\t\t\t\t\t\t\t\tbulletPositionScreen.y -= tmpSurface.getHeight() / 2;\n\t\t\t\t\t\t\t\t\t\t\tSurface::blitRaw(surface, tmpSurface, bulletPositionScreen.x, bulletPositionScreen.y, 0, false, _nvColor);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t//draw particle clouds\n\t\t\t\t\tint pixelMaskArray[] = { 0, 2, 1, 3 };\n\t\t\t\t\tSurfaceRaw<int> pixelMask(pixelMaskArray, 2, 2);\n\t\t\t\t\tconst int vaporScreenOriginX = screenPosition.x + _spriteWidth / 2;\n\t\t\t\t\tconst int vaporScreenOriginY = screenPosition.y + _spriteHeight - _spriteWidth / 2 + tile->getPosition().toVoxel().z;\n\t\t\t\t\tconst Uint8* const transparetPtr = _transparencies->data();\n\n\t\t\t\t\t//draw particle clouds behind solder\n\t\t\t\t\tfor (const Particle& p : getVaporParticle(tile, 0))\n\t\t\t\t\t{\n\t\t\t\t\t\tint vaporX = vaporScreenOriginX + p.getOffsetX();\n\t\t\t\t\t\tint vaporY = vaporScreenOriginY + p.getOffsetY();\n\t\t\t\t\t\tauto transparetOffsets = transparetPtr\n\t\t\t\t\t\t\t+ (p.getColor() * Mod::TransparenciesOpacityLevels * Mod::TransparenciesPaletteColors)\n\t\t\t\t\t\t\t+ (p.getOpacity() * Mod::TransparenciesPaletteColors);\n\n\t\t\t\t\t\tShaderDrawFunc(\n\t\t\t\t\t\t\t[&](Uint8& dest, int size)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (p.getSize() <= size)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tdest = transparetOffsets[dest];\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tShaderSurface(this),\n\t\t\t\t\t\t\tShaderMove(pixelMask, vaporX, vaporY)\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tunit = tile->getUnit();\n\t\t\t\t\t// Draw soldier from this tile, below or above\n\t\t\t\t\tdrawUnit(unitSprite, tile, tile, screenPosition, topLayer, isUnitMovingNearby ? movingUnit : nullptr);\n\n\t\t\t\t\tif (isUnitMovingNearby)\n\t\t\t\t\t{\n\t\t\t\t\t\t// special handling for a moving unit in foreground of tile.\n\t\t\t\t\t\tconstexpr static Position frontPos[] =\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tPosition(-1, +1, 0),\n\t\t\t\t\t\t\tPosition(0, +1, 0),\n\t\t\t\t\t\t\tPosition(+1, +1, 0),\n\t\t\t\t\t\t\tPosition(+1, 0, 0),\n\t\t\t\t\t\t\tPosition(+1, -1, 0),\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tfor (size_t f = 0; f < std::size(frontPos); ++f)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tdrawUnit(unitSprite, _save->getTile(mapPosition + frontPos[f]), tile, screenPosition, topLayer);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Draw smoke/fire\n\t\t\t\t\tif (tile->getSmoke() && tile->isDiscovered(O_FLOOR))\n\t\t\t\t\t{\n\t\t\t\t\t\tframeNumber = 0;\n\t\t\t\t\t\tint shade = 0;\n\t\t\t\t\t\tif (!tile->getFire())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (_save->getDepth() > 0)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tframeNumber += Mod::UNDERWATER_SMOKE_OFFSET;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tframeNumber += Mod::SMOKE_OFFSET;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (Mod::EXTENDED_SMOKE_OFFSET == 0)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tframeNumber += int(floor((tile->getSmoke() / 6.0) - 0.1)); // see http://www.ufopaedia.org/images/c/cb/Smoke.gif\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if (Mod::EXTENDED_SMOKE_OFFSET == 1)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tframeNumber += int(floor((tile->getSmoke() / 6.0) - 0.1)) * 4;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse // if (Mod::EXTENDED_SMOKE_OFFSET == 2)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tframeNumber += (tile->getSmoke() - 1) / 5 * 4;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tshade = tileShade;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (halfAnimFrame + tile->getAnimationOffset() > 3)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tframeNumber += halfAnimFrame + tile->getAnimationOffset() - 4;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tframeNumber += halfAnimFrame + tile->getAnimationOffset();\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttmpSurface = _game->getMod()->getSurfaceSet(\"SMOKE.PCK\")->getFrame(frameNumber);\n\t\t\t\t\t\tSurface::blitRaw(surface, tmpSurface, screenPosition.x, screenPosition.y, shade, false, _nvColor);\n\t\t\t\t\t}\n\n\t\t\t\t\t//draw particle clouds on front of solder\n\t\t\t\t\tfor (const Particle& p : getVaporParticle(tile, topLayer ? 3 : 1))\n\t\t\t\t\t{\n\t\t\t\t\t\tint vaporX = vaporScreenOriginX + p.getOffsetX();\n\t\t\t\t\t\tint vaporY = vaporScreenOriginY + p.getOffsetY();\n\t\t\t\t\t\tauto transparetOffsets = transparetPtr\n\t\t\t\t\t\t\t+ (p.getColor() * Mod::TransparenciesOpacityLevels * Mod::TransparenciesPaletteColors)\n\t\t\t\t\t\t\t+ (p.getOpacity() * Mod::TransparenciesPaletteColors);\n\n\t\t\t\t\t\tShaderDrawFunc(\n\t\t\t\t\t\t\t[&](Uint8& dest, int size)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (p.getSize() <= size)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tdest = transparetOffsets[dest];\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tShaderSurface(this),\n\t\t\t\t\t\t\tShaderMove(pixelMask, vaporX, vaporY)\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Draw Path Preview\n\t\t\t\t\tif (_previewSettingArrows && tile->getPreview() != -1 && tile->isDiscovered(O_FLOOR))\n\t\t\t\t\t{\n\t\t\t\t\t\tif (itZ > 0 && tile->hasNoFloor(_save))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttmpSurface = _game->getMod()->getSurfaceSet(\"Pathfinding\")->getFrame(11);\n\t\t\t\t\t\t\tif (tmpSurface)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tSurface::blitRaw(surface, tmpSurface, screenPosition.x, screenPosition.y+2, 0, false, tile->getMarkerColor());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttmpSurface = _game->getMod()->getSurfaceSet(\"Pathfinding\")->getFrame(tile->getPreview());\n\t\t\t\t\t\tif (tmpSurface)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tSurface::blitRaw(surface, tmpSurface, screenPosition.x, screenPosition.y + tile->getTerrainLevel(), 0, false, tileColor);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t{\n\t\t\t\t\t\t// Draw object\n\t\t\t\t\t\ttmpSurface = tile->getSprite(O_OBJECT);\n\t\t\t\t\t\tif (tmpSurface)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (!tile->isBackTileObject(O_OBJECT))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (tile->getObstacle(O_OBJECT))\n\t\t\t\t\t\t\t\t\tSurface::blitRaw(surface, tmpSurface, screenPosition.x, screenPosition.y - tile->getYOffset(O_OBJECT), obstacleShade, false, _nvColor);\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\tSurface::blitRaw(surface, tmpSurface, screenPosition.x, screenPosition.y - tile->getYOffset(O_OBJECT), tileShade, false, _nvColor);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t// Draw cursor front\n\t\t\t\t\tif (_cursorType != CT_NONE && _selectorX > itX - _cursorSize && _selectorY > itY - _cursorSize && _selectorX < itX+1 && _selectorY < itY+1 && !_save->getBattleState()->getMouseOverIcons())\n\t\t\t\t\t{\n\t\t\t\t\t\tif (_camera->getViewLevel() == itZ)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (_cursorType != CT_AIM)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (unit && (unit->getVisible() || _save->getDebugMode()))\n\t\t\t\t\t\t\t\t\tframeNumber = 3 + halfAnimFrameRest; // yellow box\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\tframeNumber = 3; // red box\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (unit && (unit->getVisible() || _save->getDebugMode()))\n\t\t\t\t\t\t\t\t\tframeNumber = 7 + halfAnimFrame; // yellow animated crosshairs\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\tframeNumber = 6; // red static crosshairs\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttmpSurface = _game->getMod()->getSurfaceSet(\"CURSOR.PCK\")->getFrame(frameNumber);\n\t\t\t\t\t\t\tSurface::blitRaw(surface, tmpSurface, screenPosition.x, screenPosition.y, 0);\n\n\t\t\t\t\t\t\t// UFO extender accuracy: display adjusted accuracy value on crosshair in real-time.\n\t\t\t\t\t\t\tif (_cursorType >= CT_AIM && _showInfoOnCursor && (_cursorType != CT_THROW || !Options::oxceDisableInfoOnThrowCursor))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tBattleAction *action = _save->getBattleGame()->getCurrentAction();\n\t\t\t\t\t\t\t\tconst RuleItem *weapon = action->weapon->getRules();\n\t\t\t\t\t\t\t\tstd::ostringstream ss;\n\t\t\t\t\t\t\t\tBattleActionAttack attack = BattleActionAttack::GetBeforeShoot(*action);\n\t\t\t\t\t\t\t\tint distanceSq = action->actor->distance3dToPositionSq(Position(itX, itY,itZ));\n\t\t\t\t\t\t\t\tint distance = (int)std::ceil(sqrt(float(distanceSq)));\n\n\t\t\t\t\t\t\t\tif (_cursorType == CT_AIM || _cursorType == CT_THROW)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tint accuracy = BattleUnit::getFiringAccuracy(attack, _game->getMod());\n\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tint upperLimit, lowerLimit;\n\t\t\t\t\t\t\t\t\t\tint dropoff = weapon->calculateLimits(upperLimit, lowerLimit, _save->getDepth(), action->type);\n\n\t\t\t\t\t\t\t\t\t\t// at this point, let's assume the shot is adjusted and set the text amber.\n\t\t\t\t\t\t\t\t\t\t_txtAccuracy->setColor(Palette::blockOffset(Pathfinding::yellow - 1) - 1);\n\n\t\t\t\t\t\t\t\t\t\tif (distance > upperLimit)\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\taccuracy -= (distance - upperLimit) * dropoff;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\telse if (distance < lowerLimit)\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\taccuracy -= (lowerLimit - distance) * dropoff;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t// no adjustment made? set it to green.\n\t\t\t\t\t\t\t\t\t\t\t_txtAccuracy->setColor(Palette::blockOffset(Pathfinding::green - 1) - 1);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Include LOS penalty for tiles in the unit's current view range\n\t\t\t\t\t\t\t\t\t// Don't recalculate LOS for outside of the current FOV\n\t\t\t\t\t\t\t\t\tint noLOSAccuracyPenalty = action->weapon->getRules()->getNoLOSAccuracyPenalty(_game->getMod());\n\t\t\t\t\t\t\t\t\tif (noLOSAccuracyPenalty != -1)\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tbool hasLOS = false;\n\t\t\t\t\t\t\t\t\t\tif (Position(itX, itY, itZ) == _cacheCursorPosition && _isCtrlPressed == _cacheIsCtrlPressed && _cacheHasLOS != -1)\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t// use cached result\n\t\t\t\t\t\t\t\t\t\t\thasLOS = (_cacheHasLOS == 1);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t// recalculate\n\t\t\t\t\t\t\t\t\t\t\tif (unit && (unit->getVisible() || _save->getDebugMode()))\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\thasLOS = _save->getTileEngine()->visible(action->actor, tile);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\thasLOS = _save->getTileEngine()->isTileInLOS(action, tile, true);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t// remember\n\t\t\t\t\t\t\t\t\t\t\t_cacheIsCtrlPressed = _isCtrlPressed;\n\t\t\t\t\t\t\t\t\t\t\t_cacheCursorPosition = Position(itX, itY, itZ);\n\t\t\t\t\t\t\t\t\t\t\t_cacheHasLOS = hasLOS ? 1 : 0;\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\tif (!hasLOS)\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\taccuracy = accuracy * noLOSAccuracyPenalty / 100;\n\t\t\t\t\t\t\t\t\t\t\t_txtAccuracy->setColor(Palette::blockOffset(Pathfinding::yellow - 1) - 1);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tbool outOfRange = action->type == BA_THROW\n\t\t\t\t\t\t\t\t\t\t? weapon->isOutOfThrowRange(distanceSq, _save->getDepth())\n\t\t\t\t\t\t\t\t\t\t: weapon->isOutOfRange(distanceSq);\n\n\t\t\t\t\t\t\t\t\t// zero accuracy or out of range: set it red.\n\t\t\t\t\t\t\t\t\tif (accuracy <= 0 || outOfRange)\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\taccuracy = 0;\n\t\t\t\t\t\t\t\t\t\t_txtAccuracy->setColor(Palette::blockOffset(Pathfinding::red - 1) - 1);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tss << accuracy;\n\t\t\t\t\t\t\t\t\tss << \"%\";\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t//TODO: merge this code with `InventoryState::calculateCurrentDamageTooltip` as 90% is same or should be same\n\t\t\t\t\t\t\t\t// display additional damage and psi-effectiveness info\n\t\t\t\t\t\t\t\tif (_isAltPressed)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t// step 1: determine rule\n\t\t\t\t\t\t\t\t\tconst RuleItem *rule;\n\t\t\t\t\t\t\t\t\tif (weapon->getBattleType() == BT_PSIAMP)\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\trule = weapon;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse if (action->weapon->needsAmmoForAction(action->type))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tauto* ammo = attack.damage_item;\n\t\t\t\t\t\t\t\t\t\tif (ammo != nullptr)\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\trule = ammo->getRules();\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\trule = 0; // empty weapon = no rule\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\trule = weapon;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// step 2: check if unlocked\n\t\t\t\t\t\t\t\t\tif (_cacheActiveWeaponUfopediaArticleUnlocked == -1)\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t_cacheActiveWeaponUfopediaArticleUnlocked = 0;\n\t\t\t\t\t\t\t\t\t\tif (_game->getSavedGame()->getMonthsPassed() == -1)\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t_cacheActiveWeaponUfopediaArticleUnlocked = 1; // new battle mode\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\telse if (rule)\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t_cacheActiveWeaponUfopediaArticleUnlocked = 1; // assume unlocked\n\t\t\t\t\t\t\t\t\t\t\tArticleDefinition *article = _game->getMod()->getUfopaediaArticle(rule->getType(), false);\n\t\t\t\t\t\t\t\t\t\t\tif (article && !Ufopaedia::isArticleAvailable(_game->getSavedGame(), article))\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t_cacheActiveWeaponUfopediaArticleUnlocked = 0; // ammo/weapon locked\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tif (rule->getType() != weapon->getType())\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tarticle = _game->getMod()->getUfopaediaArticle(weapon->getType(), false);\n\t\t\t\t\t\t\t\t\t\t\t\tif (article && !Ufopaedia::isArticleAvailable(_game->getSavedGame(), article))\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t_cacheActiveWeaponUfopediaArticleUnlocked = 0; // weapon locked\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// step 3: calculate and draw\n\t\t\t\t\t\t\t\t\tif (rule && _cacheActiveWeaponUfopediaArticleUnlocked == 1)\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tif (rule->getBattleType() == BT_PSIAMP)\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tfloat attackStrength = BattleUnit::getPsiAccuracy(attack);\n\t\t\t\t\t\t\t\t\t\t\tfloat defenseStrength = 30.0f; // indicator ignores: +victim->getArmor()->getPsiDefence(victim);\n\n\t\t\t\t\t\t\t\t\t\t\tfloat dis = Position::distance(action->actor->getPosition().toVoxel(), Position(itX, itY, itZ).toVoxel());\n\t\t\t\t\t\t\t\t\t\t\tint min = attackStrength - defenseStrength - rule->getPsiAccuracyRangeReduction(dis);\n\t\t\t\t\t\t\t\t\t\t\tint max = min + 55;\n\t\t\t\t\t\t\t\t\t\t\tif (max <= 0)\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tss << \"0%\";\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tss << min << \"-\" << max << \"%\";\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tif (rule->getBattleType() != BT_PSIAMP || action->type == BA_USE)\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tint totalDamage = 0;\n\t\t\t\t\t\t\t\t\t\t\tif (weapon->getIgnoreAmmoPower())\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\ttotalDamage += weapon->getPowerBonus(attack);\n\t\t\t\t\t\t\t\t\t\t\t\ttotalDamage -= weapon->getPowerRangeReduction(distance * 16);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\ttotalDamage += rule->getPowerBonus(attack);\n\t\t\t\t\t\t\t\t\t\t\t\ttotalDamage -= rule->getPowerRangeReduction(distance * 16);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tif (totalDamage < 0) totalDamage = 0;\n\t\t\t\t\t\t\t\t\t\t\tif (_cursorType != CT_WAYPOINT)\n\t\t\t\t\t\t\t\t\t\t\t\tss << \"\\n\";\n\t\t\t\t\t\t\t\t\t\t\tss << rule->getDamageType()->getRandomDamage(totalDamage, 1);\n\t\t\t\t\t\t\t\t\t\t\tss << \"-\";\n\t\t\t\t\t\t\t\t\t\t\tss << rule->getDamageType()->getRandomDamage(totalDamage, 2);\n\t\t\t\t\t\t\t\t\t\t\tif (rule->getDamageType()->RandomType == DRT_UFO_WITH_TWO_DICE)\n\t\t\t\t\t\t\t\t\t\t\t\tss << \"*\";\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tss << \"\\n?-?\";\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t_txtAccuracy->setText(ss.str());\n\t\t\t\t\t\t\t\t_txtAccuracy->draw();\n\t\t\t\t\t\t\t\t_txtAccuracy->blitNShade(surface, screenPosition.x, screenPosition.y, 0);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (_camera->getViewLevel() > itZ)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tframeNumber = 5; // blue box\n\t\t\t\t\t\t\ttmpSurface = _game->getMod()->getSurfaceSet(\"CURSOR.PCK\")->getFrame(frameNumber);\n\t\t\t\t\t\t\tSurface::blitRaw(surface, tmpSurface, screenPosition.x, screenPosition.y, 0);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!_isAltPressed && _cursorType > CT_AIM && _camera->getViewLevel() == itZ)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tbool ignore = false;\n\t\t\t\t\t\t\tif (_cursorType == CT_PSI || _cursorType == CT_WAYPOINT)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tBattleAction* action = _save->getBattleGame()->getCurrentAction();\n\t\t\t\t\t\t\t\tint distanceSq = action->actor->distance3dToPositionSq(Position(itX, itY, itZ));\n\t\t\t\t\t\t\t\tif (action->weapon->getRules()->isOutOfRange(distanceSq))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t// weapon doesn't work at this distance, just draw a normal cursor with a red 0% hint text\n\t\t\t\t\t\t\t\t\tignore = true;\n\t\t\t\t\t\t\t\t\t_txtAccuracy->setColor(Palette::blockOffset(Pathfinding::red - 1) - 1);\n\t\t\t\t\t\t\t\t\t_txtAccuracy->setText(\"0%\");\n\t\t\t\t\t\t\t\t\t_txtAccuracy->draw();\n\t\t\t\t\t\t\t\t\t_txtAccuracy->blitNShade(surface, screenPosition.x, screenPosition.y, 0);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (!ignore)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tint frame[6] = { 0, 0, 0, 11, 13, 15 };\n\t\t\t\t\t\t\t\ttmpSurface = _game->getMod()->getSurfaceSet(\"CURSOR.PCK\")->getFrame(frame[_cursorType] + (_animFrame / 4) % 2);\n\t\t\t\t\t\t\t\tSurface::blitRaw(surface, tmpSurface, screenPosition.x, screenPosition.y, 0);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Draw waypoints if any on this tile\n\t\t\t\t\tint waypid = 1;\n\t\t\t\t\tint waypXOff = 2;\n\t\t\t\t\tint waypYOff = 2;\n\n\t\t\t\t\tfor (const auto& waypoint : _waypoints)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (waypoint == mapPosition)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (waypXOff == 2 && waypYOff == 2)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttmpSurface = _game->getMod()->getSurfaceSet(\"CURSOR.PCK\")->getFrame(7);\n\t\t\t\t\t\t\t\tSurface::blitRaw(surface, tmpSurface, screenPosition.x, screenPosition.y, 0);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (_save->getBattleGame()->getCurrentAction()->type == BA_LAUNCH || _save->getBattleGame()->getCurrentAction()->sprayTargeting)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t_numWaypid->setValue(waypid);\n\t\t\t\t\t\t\t\t_numWaypid->setBordered(true); // OXCE, not configurable\n\t\t\t\t\t\t\t\t_numWaypid->draw();\n\t\t\t\t\t\t\t\t_numWaypid->blitNShade(surface, screenPosition.x + waypXOff, screenPosition.y + waypYOff, 0);\n\n\t\t\t\t\t\t\t\twaypXOff += waypid > 9 ? 10 : 6; // OXCE\n\t\t\t\t\t\t\t\tif (waypXOff >= 26)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\twaypXOff = 2;\n\t\t\t\t\t\t\t\t\twaypYOff += 8;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\twaypid++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif (pathfinderTurnedOn)\n\t{\n\t\tif (_numWaypid)\n\t\t{\n\t\t\t_numWaypid->setBordered(true); // give it a border for the pathfinding display, makes it more visible on snow, etc.\n\t\t}\n\t\tfor (int itZ = beginZ; itZ <= endZ; itZ++)\n\t\t{\n\t\t\tfor (int itX = beginX; itX <= endX; itX++)\n\t\t\t{\n\t\t\t\tfor (int itY = beginY; itY <= endY; itY++)\n\t\t\t\t{\n\t\t\t\t\tmapPosition = Position(itX, itY, itZ);\n\t\t\t\t\t_camera->convertMapToScreen(mapPosition, &screenPosition);\n\t\t\t\t\tscreenPosition += _camera->getMapOffset();\n\n\t\t\t\t\t// only render cells that are inside the surface\n\t\t\t\t\tif (screenPosition.x > -_spriteWidth && screenPosition.x < surface->getWidth() + _spriteWidth &&\n\t\t\t\t\t\tscreenPosition.y > -_spriteHeight && screenPosition.y < surface->getHeight() + _spriteHeight )\n\t\t\t\t\t{\n\t\t\t\t\t\ttile = _save->getTile(mapPosition);\n\t\t\t\t\t\tif (!tile || !tile->isDiscovered(O_FLOOR) || tile->getPreview() == -1)\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\tint adjustment = -tile->getTerrainLevel();\n\t\t\t\t\t\tif (_previewSettingArrows)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (itZ > 0 && tile->hasNoFloor(_save))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttmpSurface = _game->getMod()->getSurfaceSet(\"Pathfinding\")->getFrame(23);\n\t\t\t\t\t\t\t\tif (tmpSurface)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tSurface::blitRaw(surface, tmpSurface, screenPosition.x, screenPosition.y+2, 0, false, tile->getMarkerColor());\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tint overlay = tile->getPreview() + 12;\n\t\t\t\t\t\t\ttmpSurface = _game->getMod()->getSurfaceSet(\"Pathfinding\")->getFrame(overlay);\n\t\t\t\t\t\t\tif (tmpSurface)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tSurface::blitRaw(surface, tmpSurface, screenPosition.x, screenPosition.y - adjustment, 0, false, tile->getMarkerColor());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif ((_previewSettingTu || _previewSettingEnergy) && (tile->getTUMarker() > -1 || tile->getEnergyMarker() > -1))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tint off = tile->getTUMarker() > 9 ? 5 : 3;\n\t\t\t\t\t\t\tint offE = tile->getEnergyMarker() > 9 ? 5 : 3;\n\t\t\t\t\t\t\tint mcolor = _previewSettingArrows ? 0 : tile->getMarkerColor();\n\t\t\t\t\t\t\tif (_previewSettingArrows)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tadjustment += 7;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (_save->getSelectedUnit() && _save->getSelectedUnit()->isBigUnit())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tadjustment += 1;\n\t\t\t\t\t\t\t\tif (!_previewSettingArrows)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tadjustment += 7;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (_previewSettingTu)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t_numWaypid->setValue(tile->getTUMarker());\n\t\t\t\t\t\t\t\t_numWaypid->draw();\n\t\t\t\t\t\t\t\tif (_previewSettingEnergy)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t// TU\n\t\t\t\t\t\t\t\t\t_numWaypid->blitNShade(surface, screenPosition.x + 16 - off, screenPosition.y + (22 - adjustment), 0, false, mcolor);\n\t\t\t\t\t\t\t\t\t// and Energy\n\t\t\t\t\t\t\t\t\t_numWaypid->setValue(tile->getEnergyMarker());\n\t\t\t\t\t\t\t\t\t_numWaypid->draw();\n\t\t\t\t\t\t\t\t\t_numWaypid->blitNShade(surface, screenPosition.x + 16 - offE, screenPosition.y + (29 - adjustment), 0, false, mcolor);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t// only TU\n\t\t\t\t\t\t\t\t\t_numWaypid->blitNShade(surface, screenPosition.x + 16 - off, screenPosition.y + (29 - adjustment), 0, false, mcolor);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if (_previewSettingEnergy)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// only Energy\n\t\t\t\t\t\t\t\t_numWaypid->setValue(tile->getEnergyMarker());\n\t\t\t\t\t\t\t\t_numWaypid->draw();\n\t\t\t\t\t\t\t\t_numWaypid->blitNShade(surface, screenPosition.x + 16 - offE, screenPosition.y + (29 - adjustment), 0, false, mcolor);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (_numWaypid)\n\t\t{\n\t\t\t_numWaypid->setBordered(false); // make sure we remove the border in case it's being used for missile waypoints.\n\t\t}\n\t}\n\n\tauto* selectedUnit = _save->getSelectedUnit();\n\tif (selectedUnit && (_save->getSide() == FACTION_PLAYER || _save->getDebugMode()) && selectedUnit->getPosition().z <= _camera->getViewLevel())\n\t{\n\t\t_camera->convertMapToScreen(selectedUnit->getPosition(), &screenPosition);\n\t\tscreenPosition += _camera->getMapOffset();\n\t\tPosition offset = calculateWalkingOffset(selectedUnit).ScreenOffset;\n\t\tif (selectedUnit->isBigUnit())\n\t\t{\n\t\t\toffset.y += 4;\n\t\t}\n\t\toffset.y += Position::TileZ - (selectedUnit->getHeight() + selectedUnit->getFloatHeight());\n\t\tif (selectedUnit->isKneeled())\n\t\t{\n\t\t\toffset.y -= 2;\n\t\t}\n\t\tif (this->getCursorType() != CT_NONE)\n\t\t{\n\t\t\t_arrow->blitNShade(surface, screenPosition.x + offset.x + (_spriteWidth / 2) - (_arrow->getWidth() / 2), screenPosition.y + offset.y - _arrow->getHeight() + getArrowBobForFrame(_animFrame), 0);\n\t\t}\n\t}\n\n\t// Draw motion scanner arrows\n\tif (_isAltPressed && _save->getSide() == FACTION_PLAYER && this->getCursorType() != CT_NONE)\n\t{\n\t\tfor (auto* myUnit : *_save->getUnits())\n\t\t{\n\t\t\tbool motionScan = myUnit->getScannedTurn() == _save->getTurn() && myUnit->getFaction() != FACTION_PLAYER && !myUnit->isOut();\n\t\t\tbool customMarker = myUnit->getCustomMarker() > 0 && myUnit->getFaction() == FACTION_PLAYER && !myUnit->isOut();\n\t\t\tif (motionScan || customMarker)\n\t\t\t{\n\t\t\t\tPosition temp = myUnit->getPosition();\n\t\t\t\ttemp.z = _camera->getViewLevel();\n\t\t\t\t_camera->convertMapToScreen(temp, &screenPosition);\n\t\t\t\tscreenPosition += _camera->getMapOffset();\n\t\t\t\tPosition offset;\n\t\t\t\t//calculateWalkingOffset(myUnit, &offset);\n\t\t\t\tif (myUnit->isBigUnit())\n\t\t\t\t{\n\t\t\t\t\toffset.y += 4;\n\t\t\t\t}\n\t\t\t\tif (motionScan)\n\t\t\t\t{\n\t\t\t\t\toffset.y += Position::TileZ - /*myUnit->getHeight()*/ 21; // no spoilers\n\t\t\t\t}\n\t\t\t\telse if (customMarker)\n\t\t\t\t{\n\t\t\t\t\toffset.y += Position::TileZ - (myUnit->getHeight() + myUnit->getFloatHeight());\n\t\t\t\t}\n\t\t\t\tif (myUnit->isKneeled())\n\t\t\t\t{\n\t\t\t\t\toffset.y -= 2;\n\t\t\t\t}\n\t\t\t\tif (motionScan)\n\t\t\t\t{\n\t\t\t\t\t_arrow->blitNShade(\n\t\t\t\t\t\tsurface,\n\t\t\t\t\t\tscreenPosition.x + offset.x + (_spriteWidth / 2) - (_arrow->getWidth() / 2),\n\t\t\t\t\t\tscreenPosition.y + offset.y - _arrow->getHeight() + getArrowBobForFrame(_animFrame),\n\t\t\t\t\t\t0);\n\t\t\t\t}\n\t\t\t\telse if (customMarker)\n\t\t\t\t{\n\t\t\t\t\tSurface::blitRaw(\n\t\t\t\t\t\tsurface,\n\t\t\t\t\t\t_arrow,\n\t\t\t\t\t\tscreenPosition.x + offset.x + (_spriteWidth / 2) - (_arrow->getWidth() / 2),\n\t\t\t\t\t\tscreenPosition.y + offset.y - _arrow->getHeight() + getArrowBobForFrame(_animFrame),\n\t\t\t\t\t\t0,\n\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t_isTFTD ? ArrowColorsTFTD[myUnit->getCustomMarker() % 4] : ArrowColorsUFO[myUnit->getCustomMarker() % 4]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tdelete _numWaypid;\n\n\t// Draw craft deployment preview arrows\n\tif (_isAltPressed && _save->isPreview() && this->getCursorType() != CT_NONE)\n\t{\n\t\tfor (auto& pos : _save->getCraftTiles())\n\t\t{\n\t\t\tif (pos.z == _camera->getViewLevel())\n\t\t\t{\n\t\t\t\t_camera->convertMapToScreen(pos, &screenPosition);\n\t\t\t\tscreenPosition += _camera->getMapOffset();\n\t\t\t\tscreenPosition.y += 2; // based on vanilla soldier standHeight\n\t\t\t\t_arrow->blitNShade(\n\t\t\t\t\tsurface,\n\t\t\t\t\tscreenPosition.x + (_spriteWidth / 2) - (_arrow->getWidth() / 2),\n\t\t\t\t\tscreenPosition.y - _arrow->getHeight() + getArrowBobForFrame(_animFrame),\n\t\t\t\t\t0);\n\t\t\t}\n\t\t}\n\t}\n\n\t// check if we got big explosions\n\tif (_explosionInFOV)\n\t{\n\t\t// big explosions cause the screen to flash as bright as possible before any explosions are actually drawn.\n\t\t// this causes everything to look like EGA for a single frame.\n\t\tif (_flashScreen)\n\t\t{\n\t\t\tfor (int x = 0, y = 0; x < surface->getWidth() && y < surface->getHeight();)\n\t\t\t{\n\t\t\t\tUint8 pixel = surface->getPixel(x, y);\n\t\t\t\tif (pixel)\n\t\t\t\t{\n\t\t\t\t\tpixel = (pixel & 0xF0) + 1; //avoid 0 pixel\n\t\t\t\t\tsurface->setPixelIterative(&x, &y, pixel);\n\t\t\t\t}\n\t\t\t}\n\t\t\t_flashScreen = false;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tfor (const auto* explosion : _explosions)\n\t\t\t{\n\t\t\t\t_camera->convertVoxelToScreen(explosion->getPosition(), &bulletPositionScreen);\n\t\t\t\tif (explosion->isBig())\n\t\t\t\t{\n\t\t\t\t\tif (explosion->getCurrentFrame() >= 0)\n\t\t\t\t\t{\n\t\t\t\t\t\ttmpSurface = _game->getMod()->getSurfaceSet(\"X1.PCK\")->getFrame(explosion->getCurrentFrame());\n\t\t\t\t\t\tSurface::blitRaw(surface, tmpSurface, bulletPositionScreen.x - (tmpSurface.getWidth() / 2), bulletPositionScreen.y - (tmpSurface.getHeight() / 2), 0, false, _nvColor);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (explosion->isHit())\n\t\t\t\t{\n\t\t\t\t\ttmpSurface = _game->getMod()->getSurfaceSet(\"HIT.PCK\")->getFrame(explosion->getCurrentFrame());\n\t\t\t\t\tSurface::blitRaw(surface, tmpSurface, bulletPositionScreen.x - 15, bulletPositionScreen.y - 25, 0, false, _nvColor);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\ttmpSurface = _game->getMod()->getSurfaceSet(\"SMOKE.PCK\")->getFrame(explosion->getCurrentFrame());\n\t\t\t\t\tSurface::blitRaw(surface, tmpSurface, bulletPositionScreen.x - 15, bulletPositionScreen.y - 15, 0, false, _nvColor);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tsurface->unlock();\n}\n\n/**\n * Handles mouse presses on the map.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid Map::mousePress(Action *action, State *state)\n{\n\tInteractiveSurface::mousePress(action, state);\n\t_camera->mousePress(action, state);\n}\n\n/**\n * Handles mouse releases on the map.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid Map::mouseRelease(Action *action, State *state)\n{\n\tInteractiveSurface::mouseRelease(action, state);\n\t_camera->mouseRelease(action, state);\n}\n\n/**\n * Handles keyboard presses on the map.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid Map::keyboardPress(Action *action, State *state)\n{\n\tInteractiveSurface::keyboardPress(action, state);\n\t_camera->keyboardPress(action, state);\n}\n\n/**\n * Handles map vision toggle mode.\n */\n\nvoid Map::enableNightVision()\n{\n\t_nightVisionOn = true;\n\t_debugVisionMode = 0;\n\tpersistToggles();\n}\n\nvoid Map::toggleNightVision()\n{\n\t_nightVisionOn = !_nightVisionOn;\n\t_debugVisionMode = 0;\n\tpersistToggles();\n}\n\nvoid Map::toggleDebugVisionMode()\n{\n\t_debugVisionMode = (_debugVisionMode + 1) % 3;\n\t_nightVisionOn = false;\n\tpersistToggles();\n}\n\nvoid Map::persistToggles()\n{\n\tif (Options::oxceToggleNightVisionType == 2)\n\t{\n\t\t// persisted per campaign\n\t\t_game->getSavedGame()->setToggleNightVision(_nightVisionOn);\n\t}\n\telse if (Options::oxceToggleNightVisionType == 1)\n\t{\n\t\t// persisted per battle\n\t\t_save->setToggleNightVision(_nightVisionOn);\n\t}\n\n\tif (Options::oxceToggleBrightnessType == 2)\n\t{\n\t\t// persisted per campaign\n\t\t_game->getSavedGame()->setToggleBrightness(_debugVisionMode);\n\t}\n\telse if (Options::oxceToggleBrightnessType == 1)\n\t{\n\t\t// persisted per battle\n\t\t_save->setToggleBrightness(_debugVisionMode);\n\t}\n\n\t_save->setToggleBrightnessTemp(_debugVisionMode);\n}\n\n/**\n * Handles fade-in and fade-out shade modification\n * @param original tile/item/unit shade\n */\n\nint Map::reShade(Tile *tile)\n{\n\t// when modders just don't know where to stop...\n\tif (_debugVisionMode > 0)\n\t{\n\t\tif (_debugVisionMode == 1)\n\t\t{\n\t\t\t// Reaver's tests\n\t\t\treturn tile->getShade() / 2;\n\t\t}\n\t\t// Meridian's debug helper\n\t\treturn 0;\n\t}\n\n\t// no night vision\n\tif (_nvColor == 0)\n\t{\n\t\treturn tile->getShade();\n\t}\n\n\t// already bright enough\n\tif ((tile->getShade() <= NIGHT_VISION_SHADE))\n\t{\n\t\treturn tile->getShade();\n\t}\n\n\t// hybrid night vision (local)\n\tfor (const auto* bu : *_save->getUnits())\n\t{\n\t\tif (bu->getFaction() == FACTION_PLAYER && !bu->isOut())\n\t\t{\n\t\t\tif (Position::distance2dSq(tile->getPosition(), bu->getPosition()) <= bu->getMaxViewDistanceAtDarkSquared())\n\t\t\t{\n\t\t\t\treturn tile->getShade() > _fadeShade ? _fadeShade : tile->getShade();\n\t\t\t}\n\t\t}\n\t}\n\n\t// hybrid night vision (global)\n\treturn std::min(+NIGHT_VISION_MAX_SHADE, tile->getShade());\n}\n\n/**\n * Handles keyboard releases on the map.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid Map::keyboardRelease(Action *action, State *state)\n{\n\tInteractiveSurface::keyboardRelease(action, state);\n\t_camera->keyboardRelease(action, state);\n}\n\n/**\n * Handles mouse over events on the map.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid Map::mouseOver(Action *action, State *state)\n{\n\tInteractiveSurface::mouseOver(action, state);\n\t_camera->mouseOver(action, state);\n\t_mouseX = (int)action->getAbsoluteXMouse();\n\t_mouseY = (int)action->getAbsoluteYMouse();\n\tsetSelectorPosition(_mouseX, _mouseY);\n}\n\n\n/**\n * Sets the selector to a certain tile on the map.\n * @param mx mouse x position.\n * @param my mouse y position.\n */\nvoid Map::setSelectorPosition(int mx, int my)\n{\n\tint oldX = _selectorX, oldY = _selectorY;\n\n\t_camera->convertScreenToMap(mx, my + _spriteHeight/4, &_selectorX, &_selectorY);\n\n\tif (oldX != _selectorX || oldY != _selectorY)\n\t{\n\t\t_redraw = true;\n\t}\n}\n\n/**\n * Handles animating tiles. 8 Frames per animation.\n * @param redraw Redraw the battlescape?\n */\nvoid Map::animate(bool redraw)\n{\n\t_save->nextAnimFrame();\n\t_animFrame = _save->getAnimFrame();\n\n\t// random ambient sounds\n\t{\n\t\tif (!_save->getAmbienceRandom().empty())\n\t\t{\n\t\t\t_save->decreaseCurrentAmbienceDelay();\n\t\t\tif (_save->getCurrentAmbienceDelay() <= 0)\n\t\t\t{\n\t\t\t\t_save->resetCurrentAmbienceDelay();\n\t\t\t\t_save->playRandomAmbientSound();\n\t\t\t}\n\t\t}\n\t}\n\n\t// animate tiles\n\tfor (int i = 0; i < _save->getMapSizeXYZ(); ++i)\n\t{\n\t\t_save->getTile(i)->animate();\n\t}\n\n\t// animate vapor\n\tfor (auto i : Collections::rangeValueLess(_vaporParticles.size()))\n\t{\n\t\tauto& v = _vaporParticles[i];\n\t\tint posX = i % _camera->getMapSizeX();\n\t\tint posY = i / _camera->getMapSizeX();\n\n\t\tCollections::removeIf(\n\t\t\tv,\n\t\t\t[&](Particle& p)\n\t\t\t{\n\t\t\t\tif (p.animate())\n\t\t\t\t{\n\t\t\t\t\tPosition tileOffset = p.updateScreenPosition();\n\t\t\t\t\tif (tileOffset != Position(0,0,0))\n\t\t\t\t\t{\n\t\t\t\t\t\taddVaporParticle(Position(posX,posY,0) + tileOffset, p);\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\t}\n\n\t// init vapor vector\n\tfor (auto i : Collections::rangeValueLess(_vaporParticlesInit.size()))\n\t{\n\t\tauto& vi = _vaporParticlesInit[i];\n\t\tauto& vDest = _vaporParticles[i];\n\t\tif (vi.empty())\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (vDest.empty())\n\t\t{\n\t\t\tvi.swap(vDest);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tvDest.insert(std::begin(vDest), std::begin(vi), std::end(vi));\n\t\t}\n\n\n\t\tCollections::removeAll(vi);\n\t}\n\n\tfor (auto& tilePar : _vaporParticles)\n\t{\n\t\tif (tilePar.empty())\n\t\t{\n\t\t\tCollections::removeAll(tilePar);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tstd::sort(std::begin(tilePar), std::end(tilePar), [](const Particle& a, const Particle& b){ return a.getLayerZ() < b.getLayerZ(); });\n\t\t}\n\t}\n\n\t// animate certain units (large flying units have a propulsion animation)\n\tfor (auto* bu : *_save->getUnits())\n\t{\n\t\tconst Position pos = bu->getPosition();\n\n\t\t// skip units that do not have position\n\t\tif (pos == TileEngine::invalid)\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (_save->getDepth() > 0)\n\t\t{\n\t\t\tbu->setFloorAbove(false);\n\n\t\t\t// make sure this unit isn't obscured by the floor above him, otherwise it looks weird.\n\t\t\tif (_camera->getViewLevel() > pos.z)\n\t\t\t{\n\t\t\t\tfor (int z = std::min(_camera->getViewLevel(), _save->getMapSizeZ() - 1); z != pos.z; --z)\n\t\t\t\t{\n\t\t\t\t\tif (!_save->getTile(Position(pos.x, pos.y, z))->hasNoFloor(0))\n\t\t\t\t\t{\n\t\t\t\t\t\tbu->setFloorAbove(true);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tbu->breathe();\n\t}\n\n\tif (redraw) _redraw = true;\n}\n\n/**\n * Draws the rectangle selector.\n * @param pos Pointer to a position.\n */\nvoid Map::getSelectorPosition(Position *pos) const\n{\n\tpos->x = _selectorX;\n\tpos->y = _selectorY;\n\tpos->z = _camera->getViewLevel();\n}\n\n/**\n * Calculates the offset of a soldier, when it is walking in the middle of 2 tiles.\n * @param unit Pointer to BattleUnit.\n * @param offset Pointer to the offset to return the calculation.\n */\nUnitWalkingOffset Map::calculateWalkingOffset(const BattleUnit *unit) const\n{\n\tUnitWalkingOffset result = { };\n\n\tint offsetX[8] = { 1, 1, 1, 0, -1, -1, -1, 0 };\n\tint offsetY[8] = { 1, 0, -1, -1, -1, 0, 1, 1 };\n\tint phase = unit->getWalkingPhase() + unit->getDiagonalWalkingPhase();\n\tint dir = unit->getDirection();\n\tint midphase = 4 + 4 * (dir % 2);\n\tint endphase = 8 + 8 * (dir % 2);\n\tint size = unit->getArmor()->getSize();\n\n\tresult.ScreenOffset.x = 0;\n\tresult.ScreenOffset.y = 0;\n\n\tif (size > 1)\n\t{\n\t\tif (dir < 1 || dir > 5)\n\t\t\tmidphase = endphase;\n\t\telse if (dir == 5)\n\t\t\tmidphase = 12;\n\t\telse if (dir == 1)\n\t\t\tmidphase = 5;\n\t\telse\n\t\t\tmidphase = 1;\n\t}\n\tif (unit->getVerticalDirection())\n\t{\n\t\tmidphase = 4;\n\t\tendphase = 8;\n\t}\n\telse if ((unit->getStatus() == STATUS_WALKING || unit->getStatus() == STATUS_FLYING))\n\t{\n\t\tif (phase < midphase)\n\t\t{\n\t\t\tresult.ScreenOffset.x = phase * 2 * offsetX[dir];\n\t\t\tresult.ScreenOffset.y = - phase * offsetY[dir];\n\t\t}\n\t\telse\n\t\t{\n\t\t\tresult.ScreenOffset.x = (phase - endphase) * 2 * offsetX[dir];\n\t\t\tresult.ScreenOffset.y = - (phase - endphase) * offsetY[dir];\n\t\t}\n\t}\n\n\tresult.NormalizedMovePhase = endphase == 16 ? phase : phase * 2;\n\n\t// If we are walking in between tiles, interpolate it's terrain level.\n\tif (unit->getStatus() == STATUS_WALKING || unit->getStatus() == STATUS_FLYING)\n\t{\n\t\tconst Position posCurr = unit->getPosition();\n\t\tconst Position posDest = unit->getDestination();\n\t\tconst Position posLast = unit->getLastPosition();\n\t\tif (phase < midphase)\n\t\t{\n\t\t\tint fromLevel = getTerrainLevel(posCurr, size);\n\t\t\tint toLevel = getTerrainLevel(posDest, size);\n\t\t\tif (posCurr.z > posDest.z)\n\t\t\t{\n\t\t\t\t// going down a level, so toLevel 0 becomes +24, -8 becomes  16\n\t\t\t\ttoLevel += Position::TileZ*(posCurr.z - posDest.z);\n\t\t\t}\n\t\t\telse if (posCurr.z < posDest.z)\n\t\t\t{\n\t\t\t\t// going up a level, so toLevel 0 becomes -24, -8 becomes -16\n\t\t\t\ttoLevel = -Position::TileZ*(posDest.z - posCurr.z) + abs(toLevel);\n\t\t\t}\n\t\t\tresult.TerrainLevelOffset = Interpolate(fromLevel, toLevel, phase, endphase);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// from phase 4 onwards the unit behind the scenes already is on the destination tile\n\t\t\t// we have to get it's last position to calculate the correct offset\n\t\t\tint fromLevel = getTerrainLevel(posLast, size);\n\t\t\tint toLevel = getTerrainLevel(posDest, size);\n\t\t\tif (posLast.z > posDest.z)\n\t\t\t{\n\t\t\t\t// going down a level, so fromLevel 0 becomes -24, -8 becomes -32\n\t\t\t\tfromLevel -= Position::TileZ*(posLast.z - posDest.z);\n\t\t\t}\n\t\t\telse if (posLast.z < posDest.z)\n\t\t\t{\n\t\t\t\t// going up a level, so fromLevel 0 becomes +24, -8 becomes 16\n\t\t\t\tfromLevel = Position::TileZ*(posDest.z - posLast.z) - abs(fromLevel);\n\t\t\t}\n\t\t\tresult.TerrainLevelOffset = Interpolate(fromLevel, toLevel, phase, endphase);\n\t\t}\n\t}\n\telse\n\t{\n\t\tresult.TerrainLevelOffset = getTerrainLevel(unit->getPosition(), size);\n\t}\n\tresult.ScreenOffset.y += result.TerrainLevelOffset;\n\treturn result;\n}\n\n\n/**\n  * Terrainlevel goes from 0 to -24. For a larger sized unit, we need to pick the highest terrain level, which is the lowest number...\n  * @param pos Position.\n  * @param size Size of the unit we want to get the level from.\n  * @return terrainlevel.\n  */\nint Map::getTerrainLevel(const Position& pos, int size) const\n{\n\tint lowestlevel = 0;\n\n\tfor (int x = 0; x < size; x++)\n\t{\n\t\tfor (int y = 0; y < size; y++)\n\t\t{\n\t\t\tint l = _save->getTile(pos + Position(x,y,0))->getTerrainLevel();\n\t\t\tif (l < lowestlevel)\n\t\t\t\tlowestlevel = l;\n\t\t}\n\t}\n\n\treturn lowestlevel;\n}\n\n/**\n * Sets the 3D cursor to selection/aim mode.\n * @param type Cursor type.\n * @param size Size of cursor.\n */\nvoid Map::setCursorType(CursorType type, int size)\n{\n\t// reset cursor indicator cache\n\t_cacheActiveWeaponUfopediaArticleUnlocked = -1;\n\t_cacheIsCtrlPressed = false;\n\t_cacheCursorPosition = TileEngine::invalid;\n\t_cacheHasLOS = -1;\n\n\t_cursorType = type;\n\tif (_cursorType == CT_NORMAL)\n\t\t_cursorSize = size;\n\telse\n\t\t_cursorSize = 1;\n}\n\n/**\n * Gets the cursor type.\n * @return cursor type.\n */\nCursorType Map::getCursorType() const\n{\n\treturn _cursorType;\n}\n\n/**\n * Puts a projectile sprite on the map.\n * @param projectile Projectile to place.\n */\nvoid Map::setProjectile(Projectile *projectile)\n{\n\t_projectile = projectile;\n\tif (projectile && Options::battleSmoothCamera)\n\t{\n\t\t_launch = true;\n\t}\n}\n\n/**\n * Gets the current projectile sprite on the map.\n * @return Projectile or 0 if there is no projectile sprite on the map.\n */\nProjectile *Map::getProjectile() const\n{\n\treturn _projectile;\n}\n\n/**\n * Add new vapor particle.\n * @param pos Tile position of particle.\n * @param particle Particle to add.\n */\nvoid Map::addVaporParticle(Position pos, Particle particle)\n{\n\tif ((int)(_transparencies->size()) < (particle.getColor() + 1) * Mod::TransparenciesOpacityLevels * Mod::TransparenciesPaletteColors)\n\t{\n\t\treturn;\n\t}\n\tif (pos.x >= _camera->getMapSizeX() || pos.y >= _camera->getMapSizeY())\n\t{\n\t\treturn;\n\t}\n\tif (pos.x < 0 || pos.y < 0)\n\t{\n\t\treturn;\n\t}\n\n\tauto& v = _vaporParticlesInit[_camera->getMapSizeX() * pos.y + pos.x];\n\n\t// as there will usually be more than one Particle, we prepare more space\n\tif (v.capacity() < 64)\n\t{\n\t\tv.reserve(64);\n\t}\n\n\tv.push_back(particle);\n}\n\n/**\n * Get all vapor for tile.\n * @param tile current tile.\n * @param topLayer if tile is top visible layer, if true then will return particles belongs to upper tiles.\n * @return range of particles that should be drawn.\n */\nCollections::Range<const Particle*> Map::getVaporParticle(const Tile* tile, int topLayer) const\n{\n\tPosition pos = tile->getPosition();\n\tauto& v = _vaporParticles[_camera->getMapSizeX() * pos.y + pos.x];\n\tint startZ = pos.z * Particle::LayerAccuracy + (topLayer & 1);\n\tint endZ = startZ + Particle::LayerAccuracy / 2;\n\tauto* s = std::partition_point(v.data(), v.data() + v.size(), [&](const Particle& a){ return a.getLayerZ() < startZ; });\n\tauto* e = (topLayer & 2) ? v.data() + v.size() : std::partition_point(s, v.data() + v.size(), [&](const Particle& a){ return a.getLayerZ() < endZ; });\n\treturn Collections::Range{ s, e };\n}\n\n/**\n * Gets a list of explosion sprites on the map.\n * @return A list of explosion sprites.\n */\nstd::list<Explosion*> *Map::getExplosions()\n{\n\treturn &_explosions;\n}\n\n/**\n * Gets the pointer to the camera.\n * @return Pointer to camera.\n */\nCamera *Map::getCamera()\n{\n\treturn _camera;\n}\n\n/**\n * Timers only work on surfaces so we have to pass this on to the camera object.\n */\nvoid Map::scrollMouse()\n{\n\t_camera->scrollMouse();\n}\n\n/**\n * Timers only work on surfaces so we have to pass this on to the camera object.\n */\nvoid Map::scrollKey()\n{\n\t_camera->scrollKey();\n}\n\n/**\n * Modify the fade shade level if fade's in progress.\n */\nvoid Map::fadeShade()\n{\n\tbool hold = SDL_GetKeyState(NULL)[Options::keyNightVisionHold];\n\tif ((_nightVisionOn && !hold) || (!_nightVisionOn && hold))\n\t{\n\t\t_nvColor = Options::oxceNightVisionColor;\n\t\t_save->setToggleNightVisionTemp(true);\n\t\t_save->setToggleNightVisionColorTemp(_nvColor);\n\t\tif (_fadeShade > NIGHT_VISION_SHADE) // 0 = max brightness\n\t\t{\n\t\t\t--_fadeShade;\n\t\t}\n\t}\n\telse\n\t{\n\t\tif (_nvColor != 0)\n\t\t{\n\t\t\tif (_fadeShade < _save->getGlobalShade())\n\t\t\t{\n\t\t\t\t// gradually fade away\n\t\t\t\t++_fadeShade;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// and at the end turn off night vision\n\t\t\t\t_nvColor = 0;\n\t\t\t\t_save->setToggleNightVisionTemp(false);\n\t\t\t\t_save->setToggleNightVisionColorTemp(0);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Gets a list of waypoints on the map.\n * @return A list of waypoints.\n */\nstd::vector<Position> *Map::getWaypoints()\n{\n\treturn &_waypoints;\n}\n\n/**\n * Sets mouse-buttons' pressed state.\n * @param button Index of the button.\n * @param pressed The state of the button.\n */\nvoid Map::setButtonsPressed(Uint8 button, bool pressed)\n{\n\tsetButtonPressed(button, pressed);\n}\n\n/**\n * Sets the unitDying flag.\n * @param flag True if the unit is dying.\n */\nvoid Map::setUnitDying(bool flag)\n{\n\t_unitDying = flag;\n}\n\n/**\n * Updates the selector to the last-known mouse position.\n */\nvoid Map::refreshSelectorPosition()\n{\n\tsetSelectorPosition(_mouseX, _mouseY);\n}\n\n/**\n * Special handling for setting the height of the map viewport.\n * @param height the new base screen height.\n */\nvoid Map::setHeight(int height)\n{\n\tSurface::setHeight(height);\n\t_visibleMapHeight = height - _iconHeight;\n\t_message->setHeight((_visibleMapHeight < 200)? _visibleMapHeight : 200);\n\t_message->setY((_visibleMapHeight - _message->getHeight()) / 2);\n}\n\n/**\n * Special handling for setting the width of the map viewport.\n * @param width the new base screen width.\n */\nvoid Map::setWidth(int width)\n{\n\tint dX = width - getWidth();\n\tSurface::setWidth(width);\n\t_message->setX(_message->getX() + dX / 2);\n}\n\n/**\n * Get the hidden movement screen's vertical position.\n * @return the vertical position of the hidden movement window.\n */\nint Map::getMessageY() const\n{\n\treturn _message->getY();\n}\n\n/**\n * Get the icon height.\n */\nint Map::getIconHeight() const\n{\n\treturn _iconHeight;\n}\n\n/**\n * Get the icon width.\n */\nint Map::getIconWidth() const\n{\n\treturn _iconWidth;\n}\n\n/**\n * Returns the angle(left/right balance) of a sound effect,\n * based off a map position.\n * @param pos the map position to calculate the sound angle from.\n * @return the angle of the sound (280 to 440).\n */\nint Map::getSoundAngle(const Position& pos) const\n{\n\tint midPoint = getWidth() / 2;\n\tPosition relativePosition;\n\n\t_camera->convertMapToScreen(pos, &relativePosition);\n\t// cap the position to the screen edges relative to the center,\n\t// negative values indicating a left-shift, and positive values shifting to the right.\n\trelativePosition.x = Clamp((relativePosition.x + _camera->getMapOffset().x) - midPoint, -midPoint, midPoint);\n\n\t// convert the relative distance to a relative increment of an 80 degree angle\n\t// we use +- 80 instead of +- 90, so as not to go ALL the way left or right\n\t// which would effectively mute the sound out of one speaker.\n\t// since Mix_SetPosition uses modulo 360, we can't feed it a negative number, so add 360 instead.\n\treturn 360 + (relativePosition.x / (midPoint / 80.0));\n}\n\n/**\n * Reset the camera smoothing bool.\n */\nvoid Map::resetCameraSmoothing()\n{\n\t_smoothingEngaged = false;\n}\n\n/**\n * Set the \"explosion flash\" bool.\n * @param flash should the screen be rendered in EGA this frame?\n */\nvoid Map::setBlastFlash(bool flash)\n{\n\t_flashScreen = flash;\n\n\t// Meridian: no frikin flashing!!\n\t_flashScreen = false;\n}\n\n/**\n * Checks if the screen is still being rendered in EGA.\n * @return if we are still in EGA mode.\n */\nbool Map::getBlastFlash() const\n{\n\treturn _flashScreen;\n}\n\n/**\n * Resets obstacle markers.\n */\nvoid Map::resetObstacles(void)\n{\n\tfor (int z = 0; z < _save->getMapSizeZ(); z++)\n\t\tfor (int y = 0; y < _save->getMapSizeY(); y++)\n\t\t\tfor (int x = 0; x < _save->getMapSizeX(); x++)\n\t\t\t{\n\t\t\t\tTile *tile = _save->getTile(Position(x, y, z));\n\t\t\t\tif (tile) tile->resetObstacle();\n\t\t\t}\n\t_showObstacles = false;\n}\n\n/**\n * Enables obstacle markers.\n */\nvoid Map::enableObstacles(void)\n{\n\t_showObstacles = true;\n\tif (_obstacleTimer)\n\t{\n\t\t_obstacleTimer->stop();\n\t\t_obstacleTimer->start();\n\t}\n}\n\n/**\n * Disables obstacle markers.\n */\nvoid Map::disableObstacles(void)\n{\n\t_showObstacles = false;\n\tif (_obstacleTimer)\n\t{\n\t\t_obstacleTimer->stop();\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/Map.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/InteractiveSurface.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Collections.h\"\n#include \"../Mod/MapData.h\"\n#include \"Position.h\"\n#include \"Particle.h\"\n#include <vector>\n\nnamespace OpenXcom\n{\n\nclass SavedBattleGame;\nclass Surface;\nclass SurfaceSet;\nclass BattleUnit;\nclass Projectile;\nclass Explosion;\nclass BattlescapeMessage;\nclass Camera;\nclass Timer;\nclass Text;\nclass Tile;\nclass UnitSprite;\n\nenum CursorType { CT_NONE, CT_NORMAL, CT_AIM, CT_PSI, CT_WAYPOINT, CT_THROW };\nenum TilePart : int;\n\n/**\n * Helper class that returns all important data about the unit movement\n */\nstruct UnitWalkingOffset\n{\n\tPosition ScreenOffset;\n\tint NormalizedMovePhase;\n\tint TerrainLevelOffset;\n};\n\n/**\n * Interactive map of the battlescape.\n */\nclass Map : public InteractiveSurface\n{\nprivate:\n\tstatic const int SCROLL_INTERVAL = 15;\n\tstatic const int FADE_INTERVAL = 23;\n\tstatic const int NIGHT_VISION_SHADE = 4;\n\tstatic const int NIGHT_VISION_MAX_SHADE = 8;\n\tstatic const int BULLET_SPRITES = 35;\n\tTimer *_scrollMouseTimer, *_scrollKeyTimer, *_obstacleTimer;\n\tTimer *_fadeTimer;\n\tint _fadeShade;\n\tbool _nightVisionOn;\n\tint _debugVisionMode;\n\tint _nvColor;\n\tGame *_game;\n\tSavedBattleGame *_save;\n\tbool _isTFTD;\n\tSurface *_arrow;\n\tSurface *_stunIndicator, *_woundIndicator, *_burnIndicator, *_shockIndicator;\n\tbool _anyIndicator, _isAltPressed, _isCtrlPressed;\n\tint _spriteWidth, _spriteHeight;\n\tint _selectorX, _selectorY;\n\tint _mouseX, _mouseY;\n\tCursorType _cursorType;\n\tint _cursorSize;\n\tint _cacheActiveWeaponUfopediaArticleUnlocked; // -1 = unknown, 0 = locked, 1 = unlocked\n\tbool _cacheIsCtrlPressed;\n\tPosition _cacheCursorPosition;\n\tint _cacheHasLOS; // -1 = unknown, 0 = no LOS, 1 = has LOS\n\tint _animFrame;\n\tProjectile *_projectile;\n\tbool _followProjectile;\n\tbool _projectileInFOV;\n\tstd::list<Explosion *> _explosions;\n\tstd::vector<std::vector<Particle>> _vaporParticlesInit;\n\tstd::vector<std::vector<Particle>> _vaporParticles;\n\tbool _explosionInFOV, _launch;\n\tBattlescapeMessage *_message;\n\tCamera *_camera;\n\tint _visibleMapHeight;\n\tstd::vector<Position> _waypoints;\n\tbool _unitDying, _smoothCamera, _smoothingEngaged, _flashScreen;\n\tint _bgColor;\n\tbool _previewSettingArrows, _previewSettingTu, _previewSettingEnergy;\n\tText *_txtAccuracy;\n\tSurfaceSet *_projectileSet;\n\n\tvoid drawUnit(UnitSprite &unitSprite, Tile *unitTile, Tile *currTile, Position tileScreenPosition, bool topLayer, BattleUnit* movingUnit = nullptr);\n\tvoid drawTerrain(Surface *surface);\n\tint getTerrainLevel(const Position& pos, int size) const;\n\tint getWallShade(TilePart part, Tile* tileFrot);\n\tint _iconHeight, _iconWidth, _messageColor;\n\tint _hostileBarColor, _neutralBarColor, _borderBarColor;\n\tconst std::vector<Uint8> *_transparencies;\n\tbool _showObstacles;\n\tbool _showInfoOnCursor;\npublic:\n\t/// Creates a new map at the specified position and size.\n\tMap(Game* game, int width, int height, int x, int y, int visibleMapHeight);\n\t/// Cleans up the map.\n\t~Map();\n\t/// Initializes the map.\n\tvoid init();\n\t/// Handles timers.\n\tvoid think() override;\n\t/// Draws the surface.\n\tvoid draw() override;\n\tvoid refreshAIProgress(int progress);\n\t/// Sets the palette.\n\tvoid setPalette(const SDL_Color *colors, int firstcolor = 0, int ncolors = 256) override;\n\tvoid refreshHiddenMovementBackground();\n\t/// Special handling for mouse press.\n\tvoid mousePress(Action *action, State *state) override;\n\t/// Special handling for mouse release.\n\tvoid mouseRelease(Action *action, State *state) override;\n\t/// Special handling for mouse over\n\tvoid mouseOver(Action *action, State *state) override;\n\t/// Special handling for key presses.\n\tvoid keyboardPress(Action *action, State *state) override;\n\t/// Special handling for key releases.\n\tvoid keyboardRelease(Action *action, State *state) override;\n\t/// Rotates the tile frames 0-7\n\tvoid animate(bool redraw);\n\t/// Sets the battlescape selector position relative to mouse position.\n\tvoid setSelectorPosition(int mx, int my);\n\t/// Gets the currently selected position.\n\tvoid getSelectorPosition(Position *pos) const;\n\t/// Calculates the offset of a soldier, when it is walking in the middle of 2 tiles.\n\tUnitWalkingOffset calculateWalkingOffset(const BattleUnit *unit) const;\n\t/// Sets the 3D cursor type.\n\tvoid setCursorType(CursorType type, int size = 1);\n\t/// Gets the 3D cursor type.\n\tCursorType getCursorType() const;\n\n\t/// Sets projectile.\n\tvoid setProjectile(Projectile *projectile);\n\t/// Gets projectile.\n\tProjectile *getProjectile() const;\n\t/// Sets follow projectile flag.\n\tvoid setFollowProjectile(bool followProjectile) { _followProjectile = followProjectile; }\n\t/// Gets follow projectile flag.\n\tbool getFollowProjectile() const { return _followProjectile; }\n\t/// Gets alt pressed flag.\n\tbool isAltPressed() const { return _isAltPressed; }\n\t/// Gets ctrl pressed flag.\n\tbool isCtrlPressed() const { return _isCtrlPressed; }\n\t/// Add new vapor particle.\n\tvoid addVaporParticle(Position pos, Particle particle);\n\t/// Get all vapor for tile.\n\tCollections::Range<const Particle*> getVaporParticle(const Tile* tile, int topLayer) const;\n\t/// Gets explosion set.\n\tstd::list<Explosion*> *getExplosions();\n\n\t/// Gets the pointer to the camera.\n\tCamera *getCamera();\n\t/// Mouse-scrolls the camera.\n\tvoid scrollMouse();\n\t/// Keyboard-scrolls the camera.\n\tvoid scrollKey();\n\t/// fades in/out\n\tvoid fadeShade();\n\t/// Get waypoints vector.\n\tstd::vector<Position> *getWaypoints();\n\t/// Set mouse-buttons' pressed state.\n\tvoid setButtonsPressed(Uint8 button, bool pressed);\n\t/// Sets the unitDying flag.\n\tvoid setUnitDying(bool flag);\n\t/// Refreshes the battlescape selector after scrolling.\n\tvoid refreshSelectorPosition();\n\t/// Special handling for updating map height.\n\tvoid setHeight(int height) override;\n\t/// Special handling for updating map width.\n\tvoid setWidth(int width) override;\n\t/// Get the vertical position of the hidden movement screen.\n\tint getMessageY() const;\n\t/// Get the icon height.\n\tint getIconHeight() const;\n\t/// Get the icon width.\n\tint getIconWidth() const;\n\t/// Convert a map position to a sound angle.\n\tint getSoundAngle(const Position& pos) const;\n\t/// Reset the camera smoothing bool.\n\tvoid resetCameraSmoothing();\n\t/// Set whether the screen should \"flash\" or not.\n\tvoid setBlastFlash(bool flash);\n\t/// Check if the screen is flashing this.\n\tbool getBlastFlash() const;\n\t/// Modify shade for fading\n\tint reShade(Tile *tile);\n\t/// toggle the night-vision mode\n\tvoid enableNightVision();\n\tvoid toggleNightVision();\n\tvoid toggleDebugVisionMode();\n\tvoid persistToggles();\n\t/// Resets obstacle markers.\n\tvoid resetObstacles();\n\t/// Enables obstacle markers.\n\tvoid enableObstacles();\n\t/// Disables obstacle markers.\n\tvoid disableObstacles();\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/MedikitState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"MedikitState.h\"\n#include \"MedikitView.h\"\n#include \"../Engine/InteractiveSurface.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Palette.h\"\n#include \"../Interface/Text.h\"\n#include \"../Engine/Screen.h\"\n#include \"../Savegame/BattleItem.h\"\n#include \"../Savegame/BattleUnit.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"../Mod/Mod.h\"\n#include <sstream>\n#include \"../Engine/Options.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"TileEngine.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Helper function that returns a string representation of a type (mainly used for numbers).\n * @param t The value to stringify.\n * @return A string representation of the value.\n */\ntemplate<typename type>\nstd::string toString (type t)\n{\n\tstd::ostringstream ss;\n\tss << t;\n\treturn ss.str();\n}\n\n/**\n * Helper class for the medikit title.\n */\nclass MedikitTitle : public Text\n{\npublic:\n\t/// Creates a medikit title.\n\tMedikitTitle(int y, const std::string & title);\n};\n\n/**\n * Initializes a Medikit title.\n * @param y The title's y origin.\n * @param title The title.\n */\nMedikitTitle::MedikitTitle (int y, const std::string & title) : Text (73 + 60, 9, 186 - 30, y)\n{\n\tthis->setText(title);\n\tthis->setHighContrast(true);\n\tthis->setAlign(ALIGN_CENTER);\n}\n\n/**\n * Helper class for the medikit value.\n */\nclass MedikitTxt : public Text\n{\npublic:\n\t/// Creates a medikit text.\n\tMedikitTxt(int y);\n};\n\n/**\n * Initializes a Medikit text.\n * @param y The text's y origin.\n */\nMedikitTxt::MedikitTxt(int y) : Text(33, 17, 220, y)\n{\n\t// Note: we can't set setBig here. The needed font is only set when added to State\n\tthis->setColor(Palette::blockOffset(1));\n\tthis->setHighContrast(true);\n\tthis->setAlign(ALIGN_CENTER);\n}\n\n/**\n * Helper class for the medikit button.\n */\nclass MedikitButton : public InteractiveSurface\n{\npublic:\n\t/// Creates a medikit button.\n\tMedikitButton(int y);\n};\n\n/**\n * Initializes a Medikit button.\n * @param y The button's y origin.\n */\nMedikitButton::MedikitButton(int y) : InteractiveSurface(30, 20, 190, y)\n{\n}\n\n/**\n * Initializes the Medikit State.\n * @param game Pointer to the core game.\n * @param targetUnit The wounded unit.\n * @param action The healing action.\n */\nMedikitState::MedikitState (BattleUnit *targetUnit, BattleAction *action, TileEngine *tile) : _targetUnit(targetUnit), _action(action), _tileEngine(tile)\n{\n\tif (Options::maximizeInfoScreens)\n\t{\n\t\tOptions::baseXResolution = Screen::ORIGINAL_WIDTH;\n\t\tOptions::baseYResolution = Screen::ORIGINAL_HEIGHT;\n\t\t_game->getScreen()->resetDisplay(false);\n\t}\n\n\t_item = action->weapon;\n\t_bg = new Surface(320, 200);\n\n\t// Set palette\n\t_game->getSavedGame()->getSavedBattle()->setPaletteByDepth(this);\n\n\tif (_game->getScreen()->getDY() > 50)\n\t{\n\t\t_screen = false;\n\t\t_bg->drawRect(67, 44, 190, 100, Palette::blockOffset(15)+15);\n\t}\n\t_partTxt = new Text(62, 9, 82, 120);\n\t_woundTxt = new Text(14, 9, 145, 120);\n\t_medikitView = new MedikitView(52, 58, 95, 60, _game, _targetUnit, _partTxt, _woundTxt);\n\t_endButton = new InteractiveSurface(20, 20, 220, 140);\n\t_stimulantButton = new MedikitButton(84);\n\t_pkButton = new MedikitButton(48);\n\t_healButton = new MedikitButton(120);\n\t_pkText = new MedikitTxt (52);\n\t_stimulantTxt = new MedikitTxt (88);\n\t_healTxt = new MedikitTxt (124);\n\tadd(_bg);\n\tadd(_medikitView, \"body\", \"medikit\", _bg);\n\tadd(_endButton, \"buttonEnd\", \"medikit\", _bg);\n\tadd(new MedikitTitle (37, tr(_item->getRules()->getPainKillerActionName())), \"textPK\", \"medikit\", _bg);\n\tadd(new MedikitTitle (73, tr(_item->getRules()->getStimulantActionName())), \"textStim\", \"medikit\", _bg);\n\tadd(new MedikitTitle (109, tr(_item->getRules()->getHealActionName())), \"textHeal\", \"medikit\", _bg);\n\tadd(_healButton, \"buttonHeal\", \"medikit\", _bg);\n\tadd(_stimulantButton, \"buttonStim\", \"medikit\", _bg);\n\tadd(_pkButton, \"buttonPK\", \"medikit\", _bg);\n\tadd(_pkText, \"numPK\", \"medikit\", _bg);\n\tadd(_stimulantTxt, \"numStim\", \"medikit\", _bg);\n\tadd(_healTxt, \"numHeal\", \"medikit\", _bg);\n\tadd(_partTxt, \"textPart\", \"medikit\", _bg);\n\tadd(_woundTxt, \"numWounds\", \"medikit\", _bg);\n\n\tcenterAllSurfaces();\n\n\tSurface *backgroundSprite = 0;\n\tif (!_item->getRules()->getMediKitCustomBackground().empty())\n\t{\n\t\tbackgroundSprite = _game->getMod()->getSurface(_item->getRules()->getMediKitCustomBackground(), false);\n\t}\n\tif (!backgroundSprite)\n\t{\n\t\tbackgroundSprite = _game->getMod()->getSurface(\"MEDIBORD.PCK\");\n\t}\n\n\tbackgroundSprite->blitNShade(_bg, 0, 0);\n\t_pkText->setBig();\n\t_stimulantTxt->setBig();\n\t_healTxt->setBig();\n\t_partTxt->setHighContrast(true);\n\t_woundTxt->setHighContrast(true);\n\t_endButton->onMouseClick((ActionHandler)&MedikitState::onEndClick);\n\t_endButton->onKeyboardPress((ActionHandler)&MedikitState::onEndClick, Options::keyCancel);\n\t_healButton->onMouseClick((ActionHandler)&MedikitState::onHealClick);\n\t_healButton->onKeyboardPress((ActionHandler)&MedikitState::onHealClick, SDLK_3);\n\t_stimulantButton->onMouseClick((ActionHandler)&MedikitState::onStimulantClick);\n\t_stimulantButton->onKeyboardPress((ActionHandler)&MedikitState::onStimulantClick, SDLK_2);\n\t_pkButton->onMouseClick((ActionHandler)&MedikitState::onPainKillerClick);\n\t_pkButton->onKeyboardPress((ActionHandler)&MedikitState::onPainKillerClick, SDLK_1);\n\tupdate();\n}\n\n/**\n * Closes the window on right-click.\n * @param action Pointer to an action.\n */\nvoid MedikitState::handle(Action *action)\n{\n\tState::handle(action);\n\tif (action->getDetails()->type == SDL_MOUSEBUTTONDOWN && _game->isRightClick(action))\n\t{\n\t\tonEndClick(0);\n\t}\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid MedikitState::onEndClick(Action *)\n{\n\tif (Options::maximizeInfoScreens)\n\t{\n\t\tScreen::updateScale(Options::battlescapeScale, Options::baseXBattlescape, Options::baseYBattlescape, true);\n\t\t_game->getScreen()->resetDisplay(false);\n\t}\n\t_game->popState();\n\t_tileEngine->medikitRemoveIfEmpty(_action);\n}\n\n/**\n * Handler for clicking on the heal button.\n * @param action Pointer to an action.\n */\nvoid MedikitState::onHealClick(Action *)\n{\n\tif (_item->getHealQuantity() == 0)\n\t{\n\t\treturn;\n\t}\n\n\tif (_action->spendTU(&_action->result))\n\t{\n\t\tbool canContinueHealing = _tileEngine->medikitUse(_action, _targetUnit, BMA_HEAL, (UnitBodyPart)_medikitView->getSelectedPart());\n\t\t_medikitView->updateSelectedPart();\n\t\t_medikitView->invalidate();\n\t\tupdate();\n\t\tif (!canContinueHealing)\n\t\t{\n\t\t\tonEndClick(0);\n\t\t}\n\t}\n\telse\n\t{\n\t\tonEndClick(0);\n\t}\n}\n\n/**\n * Handler for clicking on the stimulant button.\n * @param action Pointer to an action.\n */\nvoid MedikitState::onStimulantClick(Action *)\n{\n\tif (_item->getStimulantQuantity() == 0)\n\t{\n\t\treturn;\n\t}\n\n\tif (_action->spendTU(&_action->result))\n\t{\n\t\tbool canContinueHealing = _tileEngine->medikitUse(_action, _targetUnit, BMA_STIMULANT, BODYPART_TORSO);\n\t\tupdate();\n\t\tif (!canContinueHealing)\n\t\t{\n\t\t\tonEndClick(0);\n\t\t}\n\t}\n\telse\n\t{\n\t\tonEndClick(0);\n\t}\n}\n\n/**\n * Handler for clicking on the pain killer button.\n * @param action Pointer to an action.\n */\nvoid MedikitState::onPainKillerClick(Action *)\n{\n\tif (_item->getPainKillerQuantity() == 0)\n\t{\n\t\treturn;\n\t}\n\n\tif (_action->spendTU(&_action->result))\n\t{\n\t\tbool canContinueHealing = _tileEngine->medikitUse(_action, _targetUnit, BMA_PAINKILLER, BODYPART_TORSO);\n\t\tupdate();\n\t\tif (!canContinueHealing)\n\t\t{\n\t\t\tonEndClick(0);\n\t\t}\n\t}\n\telse\n\t{\n\t\tonEndClick(0);\n\t}\n}\n\n/**\n * Updates the medikit state.\n */\nvoid MedikitState::update()\n{\n\t_pkText->setText(toString(_item->getPainKillerQuantity()));\n\t_stimulantTxt->setText(toString(_item->getStimulantQuantity()));\n\t_healTxt->setText(toString(_item->getHealQuantity()));\n\t_medikitView->invalidate();\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/MedikitState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass InteractiveSurface;\nclass MedikitView;\nclass Text;\nclass BattleItem;\nclass BattleUnit;\nclass TileEngine;\nstruct BattleAction;\n\n/**\n * The Medikit User Interface. Medikit is an item for healing a soldier.\n */\nclass MedikitState : public State\n{\n\tSurface *_bg;\n\tMedikitView *_medikitView;\n\tText *_pkText, *_stimulantTxt,  *_healTxt, *_partTxt, *_woundTxt;\n\tInteractiveSurface *_endButton, *_stimulantButton, *_pkButton, *_healButton;\n\tBattleUnit *_targetUnit;\n\tBattleItem *_item;\n\tBattleAction *_action;\n\tTileEngine *_tileEngine;\n\t/// Handler for the end button.\n\tvoid onEndClick(Action *action);\n\t/// Handler for the heal button.\n\tvoid onHealClick(Action *action);\n\t/// Handler for the stimulant button.\n\tvoid onStimulantClick(Action *action);\n\t/// Handler for the pain killer button.\n\tvoid onPainKillerClick(Action *action);\n\t/// Updates the medikit interface.\n\tvoid update();\npublic:\n\t/// Creates the MedikitState.\n\tMedikitState(BattleUnit *targetUnit, BattleAction *action, TileEngine *tile);\n\t/// Handler for right-clicking anything.\n\tvoid handle(Action *action) override;\n};\n}\n"
  },
  {
    "path": "src/Battlescape/MedikitView.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"MedikitView.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleInterface.h\"\n#include \"../Engine/SurfaceSet.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Language.h\"\n#include \"../Savegame/BattleUnit.h\"\n#include \"../Interface/Text.h\"\n\nnamespace OpenXcom\n{\n/**\n * Initializes the Medikit view.\n * @param w The MinikitView width.\n * @param h The MinikitView height.\n * @param x The MinikitView x origin.\n * @param y The MinikitView y origin.\n * @param game Pointer to the core game.\n * @param unit The wounded unit.\n * @param partTxt A pointer to a Text. Will be updated with the selected body part.\n * @param woundTxt A pointer to a Text. Will be updated with the amount of fatal wound.\n */\nMedikitView::MedikitView (int w, int h, int x, int y, Game * game, BattleUnit *unit, Text *partTxt, Text *woundTxt) : InteractiveSurface(w, h, x, y), _game(game), _selectedPart(0), _unit(unit), _partTxt(partTxt), _woundTxt(woundTxt)\n{\n\tupdateSelectedPart();\n\t_redraw = true;\n}\n\n/**\n * Draws the medikit view.\n */\nvoid MedikitView::draw()\n{\n\tSurfaceSet *set = _game->getMod()->getSurfaceSet(\"MEDIBITS.DAT\");\n\tint fatal_wound = _unit->getFatalWound((UnitBodyPart)_selectedPart);\n\tstd::ostringstream ss, ss1;\n\tint green = 0;\n\tint red = 3;\n\tif (_game->getMod()->getInterface(\"medikit\", false) && _game->getMod()->getInterface(\"medikit\")->getElementOptional(\"body\"))\n\t{\n\t\tgreen = _game->getMod()->getInterface(\"medikit\")->getElement(\"body\")->color;\n\t\tred = _game->getMod()->getInterface(\"medikit\")->getElement(\"body\")->color2;\n\t}\n\tthis->lock();\n\tfor (unsigned int i = 0; i < set->getTotalFrames(); i++)\n\t{\n\t\tint wound = _unit->getFatalWound((UnitBodyPart)i);\n\t\tSurface * surface = set->getFrame (i);\n\t\tint baseColor = wound ? red : green;\n\t\tsurface->blitNShade(this, 0, 0, 0, false, baseColor);\n\t}\n\tthis->unlock();\n\n\t_redraw = false;\n\tif (_selectedPart == -1)\n\t{\n\t\treturn;\n\t}\n\tss << _game->getLanguage()->getString(PARTS_STRING[_selectedPart]);\n\tss1 << fatal_wound;\n\t_partTxt->setText(ss.str());\n\t_woundTxt->setText(ss1.str());\n}\n\n/**\n * Handles clicks on the medikit view.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid MedikitView::mouseClick (Action *action, State *)\n{\n\tSurfaceSet *set = _game->getMod()->getSurfaceSet(\"MEDIBITS.DAT\");\n\tint x = action->getRelativeXMouse() / action->getXScale();\n\tint y = action->getRelativeYMouse() / action->getYScale();\n\tfor (unsigned int i = 0; i < set->getTotalFrames(); i++)\n\t{\n\t\tSurface * surface = set->getFrame (i);\n\t\tif (surface->getPixel(x, y))\n\t\t{\n\t\t\t_selectedPart = i;\n\t\t\t_redraw = true;\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n/**\n * Gets the selected body part.\n * @return The selected body part.\n */\nint MedikitView::getSelectedPart() const\n{\n\treturn _selectedPart;\n}\n\n/**\n * Updates the selected body part.\n * If there is a wounded body part, selects that.\n * Otherwise does not change the selected part.\n */\nvoid MedikitView::updateSelectedPart()\n{\n\tfor (int i = 0; i < BODYPART_MAX; ++i)\n\t{\n\t\tif (_unit->getFatalWound((UnitBodyPart)i))\n\t\t{\n\t\t\t_selectedPart = i;\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/MedikitView.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/InteractiveSurface.h\"\n\nnamespace OpenXcom\n{\n\nclass BattleUnit;\nclass Text;\n\n/**\n * Display a view of unit wounds\n */\nclass MedikitView : public InteractiveSurface\n{\n\tGame * _game;\n\t/// Handles clicking on the body view.\n\tvoid mouseClick (Action *action, State *state) override;\n\tint _selectedPart;\n\tBattleUnit *_unit;\n\tText *_partTxt, *_woundTxt;\npublic:\n\t/// Creates the MedikitView.\n\tMedikitView (int w, int h, int x, int y, Game * game, BattleUnit *unit, Text *partTxt, Text *woundTxt);\n\t/// Draws the body view.\n\tvoid draw() override;\n\t/// Gets the selected body part.\n\tint getSelectedPart() const;\n\t/// Updates the selected body part.\n\tvoid updateSelectedPart();\n};\n}\n"
  },
  {
    "path": "src/Battlescape/MeleeAttackBState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"MeleeAttackBState.h\"\n#include \"ExplosionBState.h\"\n#include \"BattlescapeGame.h\"\n#include \"BattlescapeState.h\"\n#include \"TileEngine.h\"\n#include \"Map.h\"\n#include \"Camera.h\"\n#include \"AIModule.h\"\n#include \"../Savegame/Tile.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"../Savegame/BattleUnit.h\"\n#include \"../Savegame/BattleItem.h\"\n#include \"../Engine/Exception.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"../fmath.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Sets up a MeleeAttackBState.\n */\nMeleeAttackBState::MeleeAttackBState(BattlescapeGame *parent, BattleAction action) : BattleState(parent, action), _unit(0), _target(0), _weapon(0), _ammo(0), _hitNumber(0), _initialized(false), _reaction(false)\n{\n}\n\n/**\n * Deletes the MeleeAttackBState.\n */\nMeleeAttackBState::~MeleeAttackBState()\n{\n}\n\n/**\n * Initializes the sequence.\n * does a lot of validity checking.\n */\nvoid MeleeAttackBState::init()\n{\n\tif (_initialized) return;\n\t_initialized = true;\n\n\tint terrainMeleeTilePart = _action.terrainMeleeTilePart;\n\t_action.terrainMeleeTilePart = 0; // reset!\n\n\t_weapon = _action.weapon;\n\tif (!_weapon) // can't hit without weapon\n\t{\n\t\t_parent->popState();\n\t\treturn;\n\t}\n\n\t_unit = _action.actor;\n\n\tbool reactionShoot = _unit->getFaction() != _parent->getSave()->getSide();\n\t_ammo = _action.weapon->getAmmoForAction(BA_HIT, reactionShoot ? nullptr : &_action.result);\n\tif (!_ammo)\n\t{\n\t\t_parent->popState();\n\t\treturn;\n\t}\n\n\tif (!_parent->getSave()->getTile(_action.target)) // invalid target position\n\t{\n\t\t_parent->popState();\n\t\treturn;\n\t}\n\n\tif (_unit->isOut() || _unit->isOutThresholdExceed())\n\t{\n\t\t// something went wrong - we can't shoot when dead or unconscious, or if we're about to fall over.\n\t\t_parent->popState();\n\t\treturn;\n\t}\n\n\t// reaction fire\n\tif (reactionShoot)\n\t{\n\t\t// no ammo or target is dead: give the time units back and cancel the shot.\n\t\tBattleUnit* target = _parent->getSave()->getTile(_action.target)->getUnit();\n\t\tif (!target || target->isOut() || target->isOutThresholdExceed() || target != _parent->getSave()->getSelectedUnit())\n\t\t{\n\t\t\t_parent->popState();\n\t\t\treturn;\n\t\t}\n\t\t_unit->lookAt(_action.target, _unit->getTurretType() != -1);\n\t\twhile (_unit->getStatus() == STATUS_TURNING)\n\t\t{\n\t\t\t_unit->turn(_unit->getTurretType() != -1);\n\t\t}\n\t}\n\n\t//spend TU\n\tif (!_action.spendTU(&_action.result))\n\t{\n\t\t_parent->popState();\n\t\treturn;\n\t}\n\n\t// terrain melee\n\tif (terrainMeleeTilePart > 0)\n\t{\n\t\t_voxel = _action.target.toVoxel() + Position(8, 8, 12);\n\t\tperformMeleeAttack(terrainMeleeTilePart);\n\t\treturn;\n\t}\n\n\tAIModule *ai = _unit->getAIModule();\n\n\tif (_unit->getFaction() == _parent->getSave()->getSide() &&\n\t\t_unit->getFaction() != FACTION_PLAYER &&\n\t\t_parent->_debugPlay == false &&\n\t\tai && ai->getTarget())\n\t{\n\t\t_target = ai->getTarget();\n\t}\n\telse\n\t{\n\t\t_target = _parent->getSave()->getTile(_action.target)->getUnit();\n\t}\n\n\tif (!_target)\n\t{\n\t\tthrow Exception(\"This is a known (but tricky) bug... still fixing it, sorry. In the meantime, try save scumming option or kill all aliens in debug mode to finish the mission.\");\n\t}\n\n\tint height = _target->getFloatHeight() + (_target->getHeight() / 2) - _parent->getSave()->getTile(_action.target)->getTerrainLevel();\n\t_voxel = _action.target.toVoxel() + Position(8, 8, height);\n\n\tif (!_parent->getSave()->getTile(_voxel.toTile()))\n\t{\n\t\tthrow Exception(\"Melee attack animation overflow: target voxel is outside of the map boundaries.\");\n\t}\n\n\tif (_unit->getFaction() == FACTION_HOSTILE)\n\t{\n\t\t_hitNumber = _weapon->getRules()->getAIMeleeHitCount() - 1;\n\t}\n\n\tperformMeleeAttack();\n}\n\n/**\n * Performs all the overall functions of the state, this code runs AFTER the explosion state pops.\n */\nvoid MeleeAttackBState::think()\n{\n\t_parent->getSave()->getBattleState()->clearMouseScrollingState();\n\tif (_reaction && !_parent->getSave()->getUnitsFalling())\n\t{\n\t\t_reaction = false;\n\t\tif (_parent->getTileEngine()->checkReactionFire(_unit, _action))\n\t\t{\n\t\t\treturn;\n\t\t}\n\t}\n\n\t// if the unit burns floor tiles, burn floor tiles\n\tif (_unit->getSpecialAbility() == SPECAB_BURNFLOOR || _unit->getSpecialAbility() == SPECAB_BURN_AND_EXPLODE)\n\t{\n\t\t_parent->getSave()->getTile(_action.target)->ignite(15);\n\t}\n\tif (_hitNumber > 0 &&\n\t\t// not performing a reaction attack\n\t\t_unit->getFaction() == _parent->getSave()->getSide() &&\n\t\t// whose target is still alive or at least conscious\n\t\t_target && !_target->isOutThresholdExceed() &&\n\t\t// and we still have ammo to make the attack\n\t\t_weapon->getAmmoForAction(BA_HIT) &&\n\t\t// spend the TUs immediately\n\t\t_action.spendTU())\n\t{\n\t\t--_hitNumber;\n\t\tperformMeleeAttack();\n\t}\n\telse\n\t{\n\t\tif (_action.cameraPosition.z != -1)\n\t\t{\n\t\t\t_parent->getMap()->getCamera()->setMapOffset(_action.cameraPosition);\n\t\t\t_parent->getMap()->invalidate();\n\t\t}\n\n\t\tif (_unit->getFaction() == _parent->getSave()->getSide()) // not a reaction attack\n\t\t{\n\t\t\t_parent->getCurrentAction()->type = BA_NONE; // do this to restore cursor\n\t\t}\n\n\t\tif (_parent->getSave()->getSide() == FACTION_PLAYER || _parent->getSave()->getDebugMode())\n\t\t{\n\t\t\t_parent->setupCursor();\n\t\t}\n\t\t_parent->convertInfected();\n\t\t_parent->popState();\n\t}\n}\n\n/**\n * Sets up a melee attack, inserts an explosion into the map and make noises.\n */\nvoid MeleeAttackBState::performMeleeAttack(int terrainMeleeTilePart)\n{\n\t// set the soldier in an aiming position\n\t_unit->aim(true);\n\n\t// use up ammo if applicable\n\t_action.weapon->spendAmmoForAction(BA_HIT, _parent->getSave());\n\t_parent->getMap()->setCursorType(CT_NONE);\n\n\t// offset the damage voxel ever so slightly so that the target knows which side the attack came from\n\tPosition difference = _unit->getPosition() - _action.target;\n\t// large units may cause it to offset too much, so we'll clamp the values.\n\tdifference.x = Clamp<Sint16>(difference.x, -1, 1);\n\tdifference.y = Clamp<Sint16>(difference.y, -1, 1);\n\n\tPosition damagePosition = _voxel + difference;\n\n\n\t// make an explosion action\n\t_parent->statePushFront(new ExplosionBState(_parent, damagePosition, BattleActionAttack::GetAferShoot(_action, _ammo), 0, true, 0, 0, terrainMeleeTilePart));\n\n\n\t_reaction = true;\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/MeleeAttackBState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"BattleState.h\"\n#include \"Position.h\"\n\nnamespace OpenXcom\n{\n\nclass BattlescapeGame;\nclass BattleUnit;\nclass BattleItem;\nclass Tile;\n\n/**\n * A Melee Attack state.\n */\nclass MeleeAttackBState : public BattleState\n{\nprivate:\n\tBattleUnit *_unit, *_target;\n\tBattleItem *_weapon, *_ammo;\n\tPosition _voxel;\n\tint _hitNumber;\n\tbool _initialized;\n\tbool _reaction;\npublic:\n\t/// Creates a new MeleeAttackBState class\n\tMeleeAttackBState(BattlescapeGame *parent, BattleAction action);\n\t/// Cleans up the MeleeAttackBState.\n\t~MeleeAttackBState();\n\t/// Initializes the state.\n\tvoid init() override;\n\t/// Runs state functionality every cycle.\n\tvoid think() override;\n\t/// Performs a melee attack\n\tvoid performMeleeAttack(int terrainMeleeTilePart = 0);\n\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/MiniMapState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"MiniMapState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Screen.h\"\n#include \"../Interface/BattlescapeButton.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Palette.h\"\n#include \"../Interface/Text.h\"\n#include \"MiniMapView.h\"\n#include \"Camera.h\"\n#include \"../Engine/Timer.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Options.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n\nnamespace OpenXcom\n{\n/**\n * Initializes all the elements in the MiniMapState screen.\n * @param game Pointer to the core game.\n * @param camera The Battlescape camera.\n * @param battleGame The Battlescape save.\n */\nMiniMapState::MiniMapState (Camera * camera, SavedBattleGame * battleGame)\n{\n\tif (Options::maximizeInfoScreens)\n\t{\n\t\tOptions::baseXResolution = Screen::ORIGINAL_WIDTH;\n\t\tOptions::baseYResolution = Screen::ORIGINAL_HEIGHT;\n\t\t_game->getScreen()->resetDisplay(false);\n\t}\n\n\t_bg = new Surface(320, 200);\n\t_miniMapView = new MiniMapView(221, 148, 48, 16, _game, camera, battleGame);\n\t_btnLvlUp = new BattlescapeButton(18, 20, 24, 62);\n\t_btnLvlDwn = new BattlescapeButton(18, 20, 24, 88);\n\t_btnOk = new BattlescapeButton(32, 32, 275, 145);\n\t_txtLevel = new Text(28, 16, 281, 75);\n\n\t// Set palette\n\tbattleGame->setPaletteByDepth(this);\n\n\tadd(_bg);\n\t_game->getMod()->getSurface(\"SCANBORD.PCK\")->blitNShade(_bg, 0, 0);\n\tadd(_miniMapView);\n\tadd(_btnLvlUp, \"buttonUp\", \"minimap\", _bg);\n\tadd(_btnLvlDwn, \"buttonDown\", \"minimap\", _bg);\n\tadd(_btnOk, \"buttonOK\", \"minimap\", _bg);\n\tadd(_txtLevel, \"textLevel\", \"minimap\", _bg);\n\n\tcenterAllSurfaces();\n\n\tif (_game->getScreen()->getDY() > 50)\n\t{\n\t\t_screen = false;\n\t\t_bg->drawRect(46, 14, 223, 151, Palette::blockOffset(15)+15);\n\t}\n\n\t_btnLvlUp->onMouseClick((ActionHandler)&MiniMapState::btnLevelUpClick);\n\t_btnLvlDwn->onMouseClick((ActionHandler)&MiniMapState::btnLevelDownClick);\n\t_btnOk->onMouseClick((ActionHandler)&MiniMapState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&MiniMapState::btnOkClick, Options::keyCancel);\n\t_btnOk->onKeyboardPress((ActionHandler)&MiniMapState::btnOkClick, Options::keyBattleMap);\n\t_txtLevel->setBig();\n\t_txtLevel->setHighContrast(true);\n\t_txtLevel->setText(tr(\"STR_LEVEL_SHORT\").arg(camera->getViewLevel()));\n\t_timerAnimate = new Timer(125);\n\t_timerAnimate->onTimer((StateHandler)&MiniMapState::animate);\n\t_timerAnimate->start();\n\t_miniMapView->draw();\n}\n\n/**\n *\n */\nMiniMapState::~MiniMapState()\n{\n\tdelete _timerAnimate;\n}\n\n/**\n * Handles mouse-wheeling.\n * @param action Pointer to an action.\n */\nvoid MiniMapState::handle(Action *action)\n{\n\tState::handle(action);\n\tif (action->getDetails()->type == SDL_MOUSEBUTTONDOWN)\n\t{\n\t\tif (action->getDetails()->button.button == SDL_BUTTON_WHEELUP)\n\t\t{\n\t\t\tbtnLevelUpClick(action);\n\t\t}\n\t\telse if (action->getDetails()->button.button == SDL_BUTTON_WHEELDOWN)\n\t\t{\n\t\t\tbtnLevelDownClick(action);\n\t\t}\n\t}\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid MiniMapState::btnOkClick(Action *)\n{\n\tif (Options::maximizeInfoScreens)\n\t{\n\t\tScreen::updateScale(Options::battlescapeScale, Options::baseXBattlescape, Options::baseYBattlescape, true);\n\t\t_game->getScreen()->resetDisplay(false);\n\t}\n\t_game->popState();\n}\n\n/**\n * Changes the currently displayed minimap level.\n * @param action Pointer to an action.\n */\nvoid MiniMapState::btnLevelUpClick(Action *)\n{\n\t_txtLevel->setText(tr(\"STR_LEVEL_SHORT\").arg(_miniMapView->up()));\n}\n\n/**\n * Changes the currently displayed minimap level.\n * @param action Pointer to an action.\n */\nvoid MiniMapState::btnLevelDownClick(Action *)\n{\n\t_txtLevel->setText(tr(\"STR_LEVEL_SHORT\").arg(_miniMapView->down()));\n}\n\n/**\n * Animation handler. Updates the minimap view animation.\n */\nvoid MiniMapState::animate()\n{\n\t_miniMapView->animate();\n}\n\n/**\n * Handles timers.\n */\nvoid MiniMapState::think()\n{\n\tState::think();\n\t_timerAnimate->think(this, 0);\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/MiniMapState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass Camera;\nclass BattlescapeButton;\nclass Text;\nclass MiniMapView;\nclass Timer;\nclass SavedBattleGame;\n\n/**\n * The MiniMap is a representation of a Battlescape map that allows you to see more of the map.\n */\nclass MiniMapState : public State\n{\n\tSurface * _bg;\n\tMiniMapView *_miniMapView;\n\tBattlescapeButton *_btnLvlUp, *_btnLvlDwn, *_btnOk;\n\tText *_txtLevel;\n\tTimer *_timerAnimate;\n\t/// Handles Minimap animation.\n\tvoid animate();\npublic:\n\t/// Creates the MiniMapState.\n\tMiniMapState (Camera * camera, SavedBattleGame * battleGame);\n\t/// Cleans up the MiniMapState.\n\t~MiniMapState();\n\t/// Handler for the OK button.\n\tvoid btnOkClick (Action * action);\n\t/// Handler for the one level up button.\n\tvoid btnLevelUpClick (Action * action);\n\t/// Handler for the one level down button.\n\tvoid btnLevelDownClick (Action * action);\n\t/// Handler for right-clicking anything.\n\tvoid handle(Action *action) override;\n\t/// Handles timers.\n\tvoid think() override;\n};\n}\n"
  },
  {
    "path": "src/Battlescape/MiniMapView.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../fmath.h\"\n#include \"MiniMapView.h\"\n#include \"MiniMapState.h\"\n#include \"Pathfinding.h\"\n#include \"../Savegame/Tile.h\"\n#include \"../Savegame/BattleItem.h\"\n#include \"../Savegame/BattleUnit.h\"\n#include \"Camera.h\"\n#include \"../Engine/Action.h\"\n#include \"../Interface/Cursor.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/SurfaceSet.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Mod/RuleInterface.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Screen.h\"\n\nnamespace OpenXcom\n{\nconst int CELL_WIDTH = 4;\nconst int CELL_HEIGHT = 4;\nconst int MAX_FRAME = 2;\n\n/**\n * Initializes all the elements in the MiniMapView.\n * @param w The MiniMapView width.\n * @param h The MiniMapView height.\n * @param x The MiniMapView x origin.\n * @param y The MiniMapView y origin.\n * @param game Pointer to the core game.\n * @param camera The Battlescape camera.\n * @param battleGame Pointer to the SavedBattleGame.\n */\nMiniMapView::MiniMapView(int w, int h, int x, int y, Game * game, Camera * camera, SavedBattleGame * battleGame) : InteractiveSurface(w, h, x, y), _game(game), _camera(camera), _battleGame(battleGame), _frame(0), _isMouseScrolling(false), _isMouseScrolled(false), _xBeforeMouseScrolling(0), _yBeforeMouseScrolling(0), _mouseScrollX(0), _mouseScrollY(0), _mouseScrollingStartTime(0), _totalMouseMoveX(0), _totalMouseMoveY(0), _mouseMovedOverThreshold(false)\n{\n\t_set = _game->getMod()->getSurfaceSet(\"SCANG.DAT\");\n\t_emptySpaceIndex = _game->getMod()->getInterface(\"minimap\")->getElement(\"emptySpace\")->color;\n}\n\n/**\n * Draws the minimap.\n */\nvoid MiniMapView::draw()\n{\n\tint _startX = _camera->getCenterPosition().x - ((getWidth() / CELL_WIDTH) / 2);\n\tint _startY = _camera->getCenterPosition().y - ((getHeight() / CELL_HEIGHT) / 2);\n\n\tInteractiveSurface::draw();\n\tif (!_set)\n\t{\n\t\treturn;\n\t}\n\tdrawRect(0, 0, getWidth(), getHeight(), 15);\n\tthis->lock();\n\tSurface * emptySpace = _set->getFrame(_emptySpaceIndex);\n\tbool isAltPressed = _game->isAltPressed(true);\n\tif (Options::isPasswordCorrect())\n\t{\n\t\tisAltPressed = !isAltPressed;\n\t}\n\tfor (int lvl = 0; lvl <= _camera->getCenterPosition().z; lvl++)\n\t{\n\t\tint py = _startY;\n\t\tfor (int y = 0; y < getHeight(); y += CELL_HEIGHT)\n\t\t{\n\t\t\tint px = _startX;\n\t\t\tfor (int x = 0; x < getWidth(); x += CELL_WIDTH)\n\t\t\t{\n\t\t\t\tPosition p(px, py, lvl);\n\t\t\t\tTile *t = _battleGame->getTile(p);\n\t\t\t\tif (!t)\n\t\t\t\t{\n\t\t\t\t\tif (isAltPressed)\n\t\t\t\t\t{\n\t\t\t\t\t\temptySpace->blitNShade(this, x, y, 0);\n\t\t\t\t\t}\n\t\t\t\t\tpx++;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tfor (int i = O_FLOOR; i < O_MAX; i++)\n\t\t\t\t{\n\t\t\t\t\tMapData *data = t->getMapData((TilePart)i);\n\n\t\t\t\t\tif (data && data->getMiniMapIndex())\n\t\t\t\t\t{\n\t\t\t\t\t\tSurface *s = _set->getFrame(data->getMiniMapIndex() + 35);\n\t\t\t\t\t\tif (s)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tint shade = 16;\n\t\t\t\t\t\t\tif (t->isDiscovered(O_FLOOR))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tshade = t->getShade();\n\t\t\t\t\t\t\t\tif (shade > 7) shade = 7; //vanilla\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ts->blitNShade(this, x, y, shade);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// alive units\n\t\t\t\tif (t->getUnit() && (t->getUnit()->getVisible() || _battleGame->getBughuntMode() || _battleGame->getDebugMode()))\n\t\t\t\t{\n\t\t\t\t\tint frame = t->getUnit()->getMiniMapSpriteIndex();\n\t\t\t\t\tint size = t->getUnit()->getArmor()->getSize();\n\t\t\t\t\tframe += (t->getPosition().y - t->getUnit()->getPosition().y) * size;\n\t\t\t\t\tframe += t->getPosition().x - t->getUnit()->getPosition().x;\n\t\t\t\t\tframe += _frame * size * size;\n\t\t\t\t\tSurface * s = _set->getFrame(frame);\n\t\t\t\t\tif (size > 1 && t->getUnit()->getFaction() == FACTION_NEUTRAL)\n\t\t\t\t\t{\n\t\t\t\t\t\ts->blitNShade(this, x, y, 0, false, Pathfinding::red);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\ts->blitNShade(this, x, y, 0);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// perhaps (at least one) item on this tile?\n\t\t\t\tif (t->isDiscovered(O_FLOOR) && !t->getInventory()->empty())\n\t\t\t\t{\n\t\t\t\t\tint frame = 9 + _frame;\n\t\t\t\t\tSurface * s = _set->getFrame(frame);\n\t\t\t\t\tbool allHidden = true;\n\t\t\t\t\tbool atLeastOnePrimed = false;\n\t\t\t\t\tfor (const auto* item : *t->getInventory())\n\t\t\t\t\t{\n\t\t\t\t\t\tif (!item->getRules()->isHiddenOnMinimap())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tallHidden = false;\n\t\t\t\t\t\t\tif (item->getFuseTimer() >= 0)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tatLeastOnePrimed = true;\n\t\t\t\t\t\t\t\tbreak; // no need to search further\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (allHidden)\n\t\t\t\t\t{\n\t\t\t\t\t\t// empty\n\t\t\t\t\t}\n\t\t\t\t\telse if (atLeastOnePrimed)\n\t\t\t\t\t{\n\t\t\t\t\t\t// dye red\n\t\t\t\t\t\ts->blitNShade(this, x, y, 0, false, Pathfinding::red);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// vanilla\n\t\t\t\t\t\ts->blitNShade(this, x, y, 0);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tpx++;\n\t\t\t}\n\t\t\tpy++;\n\t\t}\n\t}\n\tthis->unlock();\n\tint centerX = getWidth() / 2 - 1;\n\tint centerY = getHeight() / 2 - 1;\n\tUint8 color = 1 + _frame * 3;\n\tint xOffset = CELL_WIDTH / 2;\n\tint yOffset = CELL_HEIGHT / 2;\n\tdrawLine(centerX - CELL_WIDTH, centerY - CELL_HEIGHT,\n\t\t centerX - xOffset, centerY - yOffset,\n\t\t color); // top left\n\tdrawLine(centerX + xOffset, centerY - yOffset,\n\t\t centerX + CELL_WIDTH, centerY - CELL_HEIGHT,\n\t\t color); // top right\n\tdrawLine(centerX - CELL_WIDTH, centerY + CELL_HEIGHT,\n\t\t centerX - xOffset, centerY + yOffset,\n\t\t color); // bottom left\n\tdrawLine(centerX + CELL_WIDTH, centerY + CELL_HEIGHT,\n\t\t centerX + xOffset, centerY + yOffset,\n\t\t color); //bottom right\n}\n\n/**\n * Increments the displayed level.\n * @return New display level.\n */\nint MiniMapView::up()\n{\n\t_camera->setViewLevel(_camera->getViewLevel()+1);\n\t_redraw = true;\n\treturn _camera->getViewLevel();\n}\n\n/**\n * Decrements the displayed level.\n * @return New display level.\n */\nint MiniMapView::down()\n{\n\t_camera->setViewLevel(_camera->getViewLevel()-1);\n\t_redraw = true;\n\treturn _camera->getViewLevel();\n}\n\n/**\n * Handles mouse presses on the minimap. Enters mouse-moving mode when the right button is used.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid MiniMapView::mousePress(Action *action, State *state)\n{\n\tInteractiveSurface::mousePress(action, state);\n\n\tif (action->getDetails()->button.button == Options::battleDragScrollButton)\n\t{\n\t\t_isMouseScrolling = true;\n\t\t_isMouseScrolled = false;\n\t\tSDL_GetMouseState(&_xBeforeMouseScrolling, &_yBeforeMouseScrolling);\n\t\t_posBeforeMouseScrolling = _camera->getCenterPosition();\n\t\tif (!Options::battleDragScrollInvert && _cursorPosition.z == 0)\n\t\t{\n\t\t\t_cursorPosition.x = action->getDetails()->motion.x;\n\t\t\t_cursorPosition.y = action->getDetails()->motion.y;\n\t\t\t// the Z is irrelevant to our mouse position, but we can use it as a boolean to check if the position is set or not\n\t\t\t_cursorPosition.z = 1;\n\t\t}\n\t\t_mouseScrollX = 0; _mouseScrollY = 0;\n\t\t_totalMouseMoveX = 0; _totalMouseMoveY = 0;\n\t\t_mouseMovedOverThreshold = false;\n\t\t_mouseScrollingStartTime = SDL_GetTicks();\n\t}\n}\n\n/**\n * Handles mouse clicks on the minimap. Will change the camera center to the clicked point.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid MiniMapView::mouseClick(Action *action, State *state)\n{\n\tInteractiveSurface::mouseClick(action, state);\n\n\t// The following is the workaround for a rare problem where sometimes\n\t// the mouse-release event is missed for any reason.\n\t// However if the SDL is also missed the release event, then it is to no avail :(\n\t// (this part handles the release if it is missed and now an other button is used)\n\tif (_isMouseScrolling) {\n\t\tif (action->getDetails()->button.button != Options::battleDragScrollButton\n\t\t&& 0==(SDL_GetMouseState(0,0)&SDL_BUTTON(Options::battleDragScrollButton))) { // so we missed again the mouse-release :(\n\t\t\t// Check if we have to revoke the scrolling, because it was too short in time, so it was a click\n\t\t\tif ((!_mouseMovedOverThreshold) && ((int)(SDL_GetTicks() - _mouseScrollingStartTime) <= (Options::dragScrollTimeTolerance)))\n\t\t\t\t{ _camera->centerOnPosition(_posBeforeMouseScrolling); _redraw = true; }\n\t\t\t_isMouseScrolled = _isMouseScrolling = false;\n\t\t\tstopScrolling(action);\n\t\t}\n\t}\n\n\t// Drag-Scroll release: release mouse-scroll-mode\n\tif (_isMouseScrolling)\n\t{\n\t\t// While scrolling, other buttons are ineffective\n\t\tif (action->getDetails()->button.button == Options::battleDragScrollButton)\n\t\t{\n\t\t\t_isMouseScrolling = false;\n\t\t\tstopScrolling(action);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn;\n\t\t}\n\t\t// Check if we have to revoke the scrolling, because it was too short in time, so it was a click\n\t\tif ((!_mouseMovedOverThreshold) && ((int)(SDL_GetTicks() - _mouseScrollingStartTime) <= (Options::dragScrollTimeTolerance)))\n\t\t{\n\t\t\t_isMouseScrolled = false;\n\t\t\tstopScrolling(action);\n\t\t\t_camera->centerOnPosition(_posBeforeMouseScrolling);\n\t\t\t_redraw = true;\n\t\t}\n\t\tif (_isMouseScrolled) return;\n\t}\n\n\tif (_game->isRightClick(action))\n\t{\n\t\t((MiniMapState*)(state))->btnOkClick(action);\n\t}\n\n\tif (_game->isLeftClick(action))\n\t{\n\t\tint origX = action->getRelativeXMouse() / action->getXScale();\n\t\tint origY = action->getRelativeYMouse() / action->getYScale();\n\t\t// get offset (in cells) of the click relative to center of screen\n\t\tint xOff = (origX / CELL_WIDTH) - ((getWidth() / 2) / CELL_WIDTH);\n\t\tint yOff = (origY / CELL_HEIGHT) - ((getHeight() / 2) / CELL_HEIGHT);\n\t\t// center the camera on this new position\n\t\tint newX = _camera->getCenterPosition().x + xOff;\n\t\tint newY = _camera->getCenterPosition().y + yOff;\n\t\t_camera->centerOnPosition(Position(newX,newY,_camera->getViewLevel()));\n\t\t_redraw = true;\n\t}\n}\n\n/**\n * Handles moving over the minimap.\n * Will change the camera center when the mouse is moved in mouse-moving mode.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid MiniMapView::mouseOver(Action *action, State *state)\n{\n\tInteractiveSurface::mouseOver(action, state);\n\n\tif (_isMouseScrolling && action->getDetails()->type == SDL_MOUSEMOTION)\n\t{\n\t\t// The following is the workaround for a rare problem where sometimes\n\t\t// the mouse-release event is missed for any reason.\n\t\t// However if the SDL is also missed the release event, then it is to no avail :(\n\t\t// (checking: is the dragScroll-mouse-button still pressed?)\n\t\tif (0==(SDL_GetMouseState(0,0)&SDL_BUTTON(Options::battleDragScrollButton))) { // so we missed again the mouse-release :(\n\t\t\t// Check if we have to revoke the scrolling, because it was too short in time, so it was a click\n\t\t\tif ((!_mouseMovedOverThreshold) && ((int)(SDL_GetTicks() - _mouseScrollingStartTime) <= (Options::dragScrollTimeTolerance)))\n\t\t\t{\n\t\t\t\t\t_camera->centerOnPosition(_posBeforeMouseScrolling);\n\t\t\t\t\t_redraw = true;\n\t\t\t}\n\t\t\t_isMouseScrolled = _isMouseScrolling = false;\n\t\t\tstopScrolling(action);\n\t\t\treturn;\n\t\t}\n\n\t\t_isMouseScrolled = true;\n\n\t\tif (Options::touchEnabled == false)\n\t\t{\n\t\t\t// Set the mouse cursor back\n\t\t\tSDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);\n\t\t\tSDL_WarpMouse(_xBeforeMouseScrolling, _yBeforeMouseScrolling);\n\t\t\tSDL_EventState(SDL_MOUSEMOTION, SDL_ENABLE);\n\t\t}\n\n\t\t// Check the threshold\n\t\t_totalMouseMoveX += action->getDetails()->motion.xrel;\n\t\t_totalMouseMoveY += action->getDetails()->motion.yrel;\n\t\tif (!_mouseMovedOverThreshold)\n\t\t\t_mouseMovedOverThreshold = ((std::abs(_totalMouseMoveX) > Options::dragScrollPixelTolerance) || (std::abs(_totalMouseMoveY) > Options::dragScrollPixelTolerance));\n\n\t\t// Calculate the move\n\t\tint newX, newY;\n\t\tint scrollX, scrollY;\n\n\t\tif (Options::battleDragScrollInvert)\n\t\t{\n\t\t\tscrollX = action->getDetails()->motion.xrel;\n\t\t\tscrollY = action->getDetails()->motion.yrel;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tscrollX = -action->getDetails()->motion.xrel;\n\t\t\tscrollY = -action->getDetails()->motion.yrel;\n\t\t}\n\t\t_mouseScrollX += scrollX;\n\t\t_mouseScrollY += scrollY;\n\t\tnewX = _posBeforeMouseScrolling.x + _mouseScrollX / action->getXScale() / 4;\n\t\tnewY = _posBeforeMouseScrolling.y + _mouseScrollY / action->getYScale() / 4;\n\n\t\t// Keep the limits...\n\t\tif (newX < -1 || _camera->getMapSizeX() < newX)\n\t\t{\n\t\t\t_mouseScrollX -= scrollX;\n\t\t\tnewX = _posBeforeMouseScrolling.x + _mouseScrollX / 4;\n\t\t}\n\t\tif (newY < -1 || _camera->getMapSizeY() < newY)\n\t\t{\n\t\t\t_mouseScrollY -= scrollY;\n\t\t\tnewY = _posBeforeMouseScrolling.y + _mouseScrollY / 4;\n\t\t}\n\n\t\t// Scrolling\n\t\t_camera->centerOnPosition(Position(newX,newY,_camera->getViewLevel()));\n\t\t_redraw = true;\n\n\t\tif (Options::touchEnabled == false)\n\t\t{\n\t\t\t// We don't want to see the mouse-cursor jumping :)\n\t\t\tif (Options::battleDragScrollInvert)\n\t\t\t{\n\t\t\t\taction->getDetails()->motion.x = _xBeforeMouseScrolling;\n\t\t\t\taction->getDetails()->motion.y = _yBeforeMouseScrolling;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tPosition delta(-scrollX, -scrollY, 0);\n\t\t\t\tint barWidth = _game->getScreen()->getCursorLeftBlackBand();\n\t\t\t\tint barHeight = _game->getScreen()->getCursorTopBlackBand();\n\t\t\t\tint cursorX = _cursorPosition.x + delta.x;\n\t\t\t\tint cursorY =_cursorPosition.y + delta.y;\n\t\t\t\t_cursorPosition.x = Clamp(cursorX, (int)Round(getX() * action->getXScale()) + barWidth, (int)Round((getX() + getWidth()) * action->getXScale()) + barWidth);\n\t\t\t\t_cursorPosition.y = Clamp(cursorY, (int)Round(getY() * action->getYScale()) + barHeight, (int)Round((getY() + getHeight()) * action->getYScale()) + barHeight);\n\t\t\t\taction->getDetails()->motion.x = _cursorPosition.x;\n\t\t\t\taction->getDetails()->motion.y = _cursorPosition.y;\n\t\t\t}\n\t\t}\n\t\t_game->getCursor()->handle(action);\n\t}\n}\n\n/**\n * Handles moving into the minimap.\n * Stops the mouse-scrolling mode, if its left on.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid MiniMapView::mouseIn(Action *action, State *state)\n{\n\tInteractiveSurface::mouseIn(action, state);\n\n\t_isMouseScrolling = false;\n\tsetButtonPressed(SDL_BUTTON_RIGHT, false);\n}\n\n/**\n * Updates the minimap animation.\n */\nvoid MiniMapView::animate()\n{\n\t_frame++;\n\tif (_frame > MAX_FRAME)\n\t{\n\t\t_frame = 0;\n\t}\n\t_redraw = true;\n}\n\nvoid MiniMapView::stopScrolling(Action *action)\n{\n\tif (!Options::battleDragScrollInvert)\n\t{\n\t\tSDL_WarpMouse(_cursorPosition.x, _cursorPosition.y);\n\t\taction->setMouseAction(_cursorPosition.x, _cursorPosition.y, getX(), getY());\n\t}\n\t// reset our \"mouse position stored\" flag\n\t_cursorPosition.z = 0;\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/MiniMapView.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/InteractiveSurface.h\"\n#include \"Position.h\"\n\nnamespace OpenXcom\n{\n\nclass Game;\nclass Camera;\nclass SavedBattleGame;\nclass SurfaceSet;\n\n/**\n * MiniMapView is the class used to display the map in the MiniMapState.\n */\nclass MiniMapView : public InteractiveSurface\n{\n\tGame * _game;\n\tCamera * _camera;\n\tSavedBattleGame * _battleGame;\n\tint _frame;\n\tSurfaceSet * _set;\n\tint _emptySpaceIndex;\n\t// these two are required for right-button scrolling on the minimap\n\tbool _isMouseScrolling;\n\tbool _isMouseScrolled;\n\tint _xBeforeMouseScrolling, _yBeforeMouseScrolling;\n\tint _mouseScrollX, _mouseScrollY;\n\tPosition _posBeforeMouseScrolling, _cursorPosition;\n\tUint32 _mouseScrollingStartTime;\n\tint _totalMouseMoveX, _totalMouseMoveY;\n\tbool _mouseMovedOverThreshold;\n\t/// Handles pressing on the MiniMap.\n\tvoid mousePress(Action *action, State *state) override;\n\t/// Handles clicking on the MiniMap.\n\tvoid mouseClick(Action *action, State *state) override;\n\t/// Handles moving mouse over the MiniMap.\n\tvoid mouseOver(Action *action, State *state) override;\n\t/// Handles moving the mouse into the MiniMap surface.\n\tvoid mouseIn(Action *action, State *state) override;\npublic:\n\t/// Creates the MiniMapView.\n\tMiniMapView(int w, int h, int x, int y, Game * game, Camera * camera, SavedBattleGame * battleGame);\n\t/// Draws the minimap.\n\tvoid draw() override;\n\t/// Changes the displayed minimap level.\n\tint up();\n\t/// Changes the displayed minimap level.\n\tint down();\n\t/// Updates the minimap animation.\n\tvoid animate();\n\tvoid stopScrolling(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/NextTurnState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"NextTurnState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Timer.h\"\n#include \"../Engine/RNG.h\"\n#include \"../Engine/Screen.h\"\n#include \"../Mod/AlienRace.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleCraft.h\"\n#include \"../Mod/RuleEnviroEffects.h\"\n#include \"../Mod/RuleInterface.h\"\n#include \"../Mod/RuleTerrain.h\"\n#include \"../Mod/RuleUfo.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Palette.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Engine/Action.h\"\n#include \"../Savegame/BattleUnit.h\"\n#include \"../Savegame/Node.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/HitLog.h\"\n#include \"AIModule.h\"\n#include \"BattlescapeState.h\"\n#include \"BattlescapeGame.h\"\n#include \"BriefingState.h\"\n#include \"Map.h\"\n#include \"TileEngine.h\"\n#include \"Pathfinding.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Next Turn screen.\n * @param game Pointer to the core game.\n * @param battleGame Pointer to the saved game.\n * @param state Pointer to the Battlescape state.\n */\nNextTurnState::NextTurnState(SavedBattleGame *battleGame, BattlescapeState *state) : _battleGame(battleGame), _state(state), _timer(0), _currentTurn(0), _showBriefing(false)\n{\n\tif (_battleGame->isPreview())\n\t{\n\t\t// skip everything, go straight to init()\n\t\treturn;\n\t}\n\n\t// set random hidden movement/next turn background for this turn\n\tif (_battleGame->getSide() == FACTION_PLAYER)\n\t{\n\t\tbool change = false;\n\t\tif (Options::oxceHiddenMovementBackgroundChangeFrequency > 0)\n\t\t{\n\t\t\tif (_battleGame->getTurn() % Options::oxceHiddenMovementBackgroundChangeFrequency == 0)\n\t\t\t{\n\t\t\t\tchange = true;\n\t\t\t}\n\t\t}\n\t\tif (change)\n\t\t{\n\t\t\t_battleGame->setRandomHiddenMovementBackground(_game->getMod());\n\t\t\tstate->getMap()->refreshHiddenMovementBackground();\n\t\t}\n\t}\n\n\t// reset alien/civilian quick mode\n\tif (_battleGame->getSide() == FACTION_PLAYER)\n\t{\n\t\tif (Options::battleAlienSpeedOrig != -1)\n\t\t{\n\t\t\tOptions::battleAlienSpeed = Options::battleAlienSpeedOrig;\n\t\t\tOptions::battleAlienSpeedOrig = -1;\n\t\t}\n\t}\n\n\t_currentTurn = _battleGame->getTurn() < 1 ? 1 : _battleGame->getTurn();\n\n\t// Create objects\n\tint y = state->getMap()->getMessageY();\n\n\t_window = new Window(this, 320, 200, 0, 0);\n\t_txtMessageReinforcements = new Text(320, 33, 0, 8);\n\t_btnBriefingReinforcements = new TextButton(120, 16, 100, 45);\n\t_txtTitle = new Text(320, 17, 0, 68);\n\t_txtTurn = new Text(320, 17, 0, 92);\n\t_txtSide = new Text(320, 17, 0, 108);\n\t_txtMessage = new Text(320, 17, 0, 132);\n\t_txtMessage2 = new Text(320, 33, 0, 156);\n\t_txtMessage3 = new Text(320, 17, 0, 172);\n\t_bg = new Surface(_game->getScreen()->getWidth(), _game->getScreen()->getWidth(), 0, 0);\n\n\t// Set palette\n\tbattleGame->setPaletteByDepth(this);\n\n\tadd(_bg);\n\tadd(_window);\n\tadd(_txtMessageReinforcements, \"messageWindows\", \"battlescape\");\n\tadd(_btnBriefingReinforcements, \"messageWindowButtons\", \"battlescape\");\n\tadd(_txtTitle, \"messageWindows\", \"battlescape\");\n\tadd(_txtTurn, \"messageWindows\", \"battlescape\");\n\tadd(_txtSide, \"messageWindows\", \"battlescape\");\n\tadd(_txtMessage, \"messageWindows\", \"battlescape\");\n\tadd(_txtMessage2, \"messageWindows\", \"battlescape\");\n\tadd(_txtMessage3, \"messageWindows\", \"battlescape\");\n\n\tcenterAllSurfaces();\n\n\t_bg->setX(0);\n\t_bg->setY(0);\n\tSDL_Rect rect;\n\trect.h = _bg->getHeight();\n\trect.w = _bg->getWidth();\n\trect.x = rect.y = 0;\n\n\t// Note: un-hardcoded the color from 15 to ruleset value, default 15\n\tint bgColor = 15;\n\tauto* sc = _battleGame->getEnviroEffects();\n\tif (sc)\n\t{\n\t\tbgColor = sc->getMapBackgroundColor();\n\t}\n\t_bg->drawRect(&rect, Palette::blockOffset(0) + bgColor);\n\t// make this screen line up with the hidden movement screen\n\t_window->setY(y);\n\t_txtMessageReinforcements->setY(y + 8);\n\t_btnBriefingReinforcements->setY(y + 45);\n\t_txtTitle->setY(y + 68);\n\t_txtTurn->setY(y + 92);\n\t_txtSide->setY(y + 108);\n\t_txtMessage->setY(y + 132);\n\t_txtMessage2->setY(y + 156);\n\t_txtMessage3->setY(y + 172);\n\n\t// Set up objects\n\t_window->setColor(Palette::blockOffset(0)-1);\n\t_window->setHighContrast(true);\n\t_window->setBackground(_game->getMod()->getSurface(_battleGame->getHiddenMovementBackground()));\n\n\n\t_txtMessageReinforcements->setBig();\n\t_txtMessageReinforcements->setAlign(ALIGN_CENTER);\n\t_txtMessageReinforcements->setVerticalAlign(ALIGN_BOTTOM);\n\t_txtMessageReinforcements->setWordWrap(true);\n\t_txtMessageReinforcements->setHighContrast(true);\n\t_txtMessageReinforcements->setColor(_game->getMod()->getInterface(\"inventory\")->getElement(\"weight\")->color2); // red\n\n\t_btnBriefingReinforcements->setText(tr(\"STR_TELL_ME_MORE\"));\n\t_btnBriefingReinforcements->setHighContrast(true);\n\t_btnBriefingReinforcements->onMouseClick((ActionHandler)&NextTurnState::btnBriefingReinforcementsClick);\n\t_btnBriefingReinforcements->setVisible(false);\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setHighContrast(true);\n\t_txtTitle->setText(tr(\"STR_OPENXCOM\").arg(Options::getActiveMasterInfo()->getVersionDisplay()));\n\n\n\t_txtTurn->setBig();\n\t_txtTurn->setAlign(ALIGN_CENTER);\n\t_txtTurn->setHighContrast(true);\n\tstd::stringstream ss;\n\tss << tr(\"STR_TURN\").arg(_currentTurn);\n\tif (battleGame->getTurnLimit() > 0)\n\t{\n\t\tss << \"/\" << battleGame->getTurnLimit();\n\t\tif (battleGame->getTurnLimit() - _currentTurn <= 3)\n\t\t{\n\t\t\t// gonna borrow the inventory's \"over weight\" colour when we're down to the last three turns\n\t\t\t_txtTurn->setColor(_game->getMod()->getInterface(\"inventory\")->getElement(\"weight\")->color2);\n\t\t}\n\t}\n\t_txtTurn->setText(ss.str());\n\n\n\t_txtSide->setBig();\n\t_txtSide->setAlign(ALIGN_CENTER);\n\t_txtSide->setHighContrast(true);\n\t_txtSide->setText(tr(\"STR_SIDE\").arg(tr((_battleGame->getSide() == FACTION_PLAYER ? \"STR_XCOM\" : \"STR_ALIENS\"))));\n\n\n\t_txtMessage->setBig();\n\t_txtMessage->setAlign(ALIGN_CENTER);\n\t_txtMessage->setHighContrast(true);\n\t_txtMessage->setText(tr(\"STR_PRESS_BUTTON_TO_CONTINUE\"));\n\n\t_txtMessage2->setBig();\n\t_txtMessage2->setAlign(ALIGN_CENTER);\n\t_txtMessage2->setHighContrast(true);\n\t_txtMessage2->setText(\"\");\n\n\t_txtMessage3->setBig();\n\t_txtMessage3->setAlign(ALIGN_CENTER);\n\t_txtMessage3->setHighContrast(true);\n\t_txtMessage3->setText(\"\");\n\n\t_state->clearMouseScrollingState();\n\n\t// environmental effects\n\tstd::string message;\n\n\tif (sc && !_battleGame->getBattleGame()->areAllEnemiesNeutralized())\n\t{\n\t\tif (_battleGame->getSide() == FACTION_PLAYER)\n\t\t{\n\t\t\t// beginning of player's turn\n\t\t\tEnvironmentalCondition friendly = sc->getEnvironmetalCondition(\"STR_FRIENDLY\");\n\n\t\t\tbool showMessage = applyEnvironmentalConditionToFaction(FACTION_PLAYER, friendly);\n\n\t\t\tif (showMessage)\n\t\t\t{\n\t\t\t\t_txtMessage2->setColor(friendly.color);\n\t\t\t\tmessage = tr(friendly.message);\n\t\t\t\t_txtMessage2->setText(message);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// beginning of alien's and neutral's turn\n\t\t\tbool anyoneStanding = false;\n\t\t\tfor (const auto* bu : *_battleGame->getUnits())\n\t\t\t{\n\t\t\t\tif (bu->getOriginalFaction() == FACTION_HOSTILE && !bu->isOut() && !bu->isOutThresholdExceed())\n\t\t\t\t{\n\t\t\t\t\tanyoneStanding = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (anyoneStanding)\n\t\t\t{\n\t\t\t\tEnvironmentalCondition hostile = sc->getEnvironmetalCondition(\"STR_HOSTILE\");\n\t\t\t\tEnvironmentalCondition neutral = sc->getEnvironmetalCondition(\"STR_NEUTRAL\");\n\n\t\t\t\tbool showMessage = false;\n\t\t\t\tif (applyEnvironmentalConditionToFaction(FACTION_HOSTILE, hostile))\n\t\t\t\t{\n\t\t\t\t\t_txtMessage2->setColor(hostile.color);\n\t\t\t\t\t_txtMessage2->setText(tr(hostile.message));\n\t\t\t\t\tshowMessage = true;\n\t\t\t\t}\n\t\t\t\tif (applyEnvironmentalConditionToFaction(FACTION_NEUTRAL, neutral))\n\t\t\t\t{\n\t\t\t\t\t_txtMessage3->setColor(neutral.color);\n\t\t\t\t\t_txtMessage3->setText(tr(neutral.message));\n\t\t\t\t\tshowMessage = true;\n\t\t\t\t}\n\n\t\t\t\tif (showMessage)\n\t\t\t\t{\n\t\t\t\t\tss.clear();\n\t\t\t\t\tss << tr(hostile.message) << tr(neutral.message);\n\t\t\t\t\tmessage = ss.str();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (message.empty())\n\t{\n\t\t_battleGame->appendToHitLog(HITLOG_NEW_TURN, _battleGame->getSide());\n\t}\n\telse\n\t{\n\t\t_battleGame->appendToHitLog(HITLOG_NEW_TURN_WITH_MESSAGE, _battleGame->getSide(), message);\n\t}\n\n\tif (_battleGame->getSide() == FACTION_PLAYER)\n\t{\n\t\tcheckBugHuntMode();\n\t\t_state->bugHuntMessage();\n\t}\n\n\tstd::string messageReinforcements;\n\tbool allowReinforcements = _battleGame->getSide() == FACTION_HOSTILE && _battleGame->getTurn() > 0;\n\tif (_battleGame->getSide() == FACTION_PLAYER && _battleGame->getTurn() == 0)\n\t{\n\t\tallowReinforcements = true;\n\t}\n\tif (allowReinforcements && !_battleGame->getBattleGame()->areAllEnemiesNeutralized())\n\t{\n\t\tbool showAlert = determineReinforcements();\n\t\tif (showAlert && _battleGame->getTurn() > 0)\n\t\t{\n\t\t\tmessageReinforcements = tr(\"STR_REINFORCEMENTS_ALERT\");\n\t\t\t_txtMessageReinforcements->setText(messageReinforcements);\n\t\t}\n\t}\n\n\tif (Options::skipNextTurnScreen && message.empty() && messageReinforcements.empty())\n\t{\n\t\t_timer = new Timer(NEXT_TURN_DELAY);\n\t\t_timer->onTimer((StateHandler)&NextTurnState::close);\n\t\t_timer->start();\n\t}\n}\n\n/**\n *\n */\nNextTurnState::~NextTurnState()\n{\n\tdelete _timer;\n}\n\nvoid NextTurnState::init()\n{\n\tState::init();\n\n\tif (_battleGame->isPreview())\n\t{\n\t\t_battleGame->getBattleGame()->cleanupDeleted();\n\t\t_game->popState();\n\n\t\tif (_battleGame->getSide() == FACTION_HOSTILE)\n\t\t{\n\t\t\t// end preview\n\t\t\t_state->finishBattle(false, 42);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// start preview\n\t\t\t_state->btnCenterClick(0);\n\n\t\t\t// Try to reactivate the touch buttons at the start of the player's turn\n\t\t\tif (_battleGame->getSide() == FACTION_PLAYER)\n\t\t\t{\n\t\t\t\t_state->toggleTouchButtons(false, true);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n* Checks if bug hunt mode should be activated or not.\n*/\nvoid NextTurnState::checkBugHuntMode()\n{\n\t// too early for bug hunt\n\tif (_currentTurn < _battleGame->getBughuntMinTurn()) return;\n\n\t// bug hunt is already activated\n\tif (_battleGame->getBughuntMode()) return;\n\n\tint count = 0;\n\tfor (const auto* bu : *_battleGame->getUnits())\n\t{\n\t\tif (!bu->isOut())\n\t\t{\n\t\t\tif (bu->getOriginalFaction() == FACTION_HOSTILE)\n\t\t\t{\n\t\t\t\t// we can see them, duh!\n\t\t\t\tif (bu->getVisible()) return;\n\n\t\t\t\t// VIPs are still in the game\n\t\t\t\tif (bu->getRankInt() <= _game->getMod()->getBughuntRank()) return; // AR_COMMANDER = 0, AR_LEADER = 1, ...\n\n\t\t\t\tcount++;\n\t\t\t\t// too many enemies are still in the game\n\t\t\t\tif (count > _game->getMod()->getBughuntMaxEnemies()) return;\n\n\t\t\t\tbool hasWeapon = bu->getLeftHandWeapon() || bu->getRightHandWeapon();\n\t\t\t\tbool hasLowMorale = bu->getMorale() < _game->getMod()->getBughuntLowMorale();\n\t\t\t\tbool hasTooManyTUsLeft = bu->getTimeUnits() > (bu->getUnitRules()->getStats()->tu * _game->getMod()->getBughuntTimeUnitsLeft() / 100);\n\t\t\t\tif (!hasWeapon || hasLowMorale || hasTooManyTUsLeft)\n\t\t\t\t{\n\t\t\t\t\tcontinue; // this unit is powerless, check next unit...\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\treturn; // this unit is OK, no bug hunt yet!\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t_battleGame->setBughuntMode(true); // if we made it this far, turn on the bug hunt!\n}\n\n/**\n* Applies given environmental condition effects to a given faction.\n* @return True, if any unit was affected (even if damage was zero).\n*/\nbool NextTurnState::applyEnvironmentalConditionToFaction(UnitFaction faction, EnvironmentalCondition condition)\n{\n\tif (!_battleGame->getEnvironmentalConditionsEnabled(faction))\n\t{\n\t\treturn false;\n\t}\n\n\t// Killing people before battle starts causes a crash\n\t// Panicking people before battle starts causes endless loop\n\t// Let's just avoid this instead of reworking everything\n\tif (faction == FACTION_PLAYER && _currentTurn <= 1)\n\t{\n\t\treturn false;\n\t}\n\n\t// Note: there are limitations, since we're not using a projectile and nobody is actually shooting\n\t// 1. no power bonus based on shooting unit's stats (nobody is shooting)\n\t// 2. no power range reduction (there is no projectile, range = 0)\n\t// 3. no AOE damage from explosions (targets are damaged directly without affecting anyone/anything)\n\t// 4. no terrain damage\n\n\tbool showMessage = false;\n\n\tif (condition.chancePerTurn > 0 && condition.firstTurn <= _currentTurn && _currentTurn <= condition.lastTurn)\n\t{\n\t\tconst RuleItem *weaponOrAmmo = _game->getMod()->getItem(condition.weaponOrAmmo);\n\t\tconst RuleDamageType *type = weaponOrAmmo->getDamageType();\n\t\tconst int power = weaponOrAmmo->getPower(); // no power bonus, no power range reduction\n\n\t\tUnitSide side = SIDE_FRONT;\n\t\tUnitBodyPart bodypart = BODYPART_TORSO;\n\n\t\tif (condition.side > -1)\n\t\t{\n\t\t\tside = (UnitSide)condition.side;\n\t\t}\n\t\tif (condition.bodyPart > -1)\n\t\t{\n\t\t\tbodypart = (UnitBodyPart)condition.bodyPart;\n\t\t}\n\n\t\tfor (auto* bu : *_battleGame->getUnits())\n\t\t{\n\t\t\tif (bu->getOriginalFaction() == faction && bu->getStatus() != STATUS_DEAD && !bu->isIgnored())\n\t\t\t{\n\t\t\t\tif (RNG::percent(condition.chancePerTurn))\n\t\t\t\t{\n\t\t\t\t\tif (condition.side == -1)\n\t\t\t\t\t{\n\t\t\t\t\t\tside = (UnitSide)RNG::generate((int)SIDE_FRONT, (int)SIDE_UNDER);\n\t\t\t\t\t}\n\t\t\t\t\tif (condition.bodyPart == -1)\n\t\t\t\t\t{\n\t\t\t\t\t\tbodypart = (UnitBodyPart)RNG::generate(BODYPART_HEAD, BODYPART_LEFTLEG);\n\t\t\t\t\t}\n\t\t\t\t\tbu->damage(Position(0, 0, 0), type->getRandomDamage(power), type, _battleGame, { }, side, bodypart);\n\t\t\t\t\tshowMessage = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (showMessage)\n\t{\n\t\t// now check for new casualties\n\t\t_battleGame->getBattleGame()->checkForCasualties(nullptr, BattleActionAttack{ }, true, false);\n\t\t// revive units if damage could give hp or reduce stun\n\t\t//_battleGame->reviveUnconsciousUnits(true);\n\t}\n\n\treturn showMessage;\n}\n\n/**\n * Closes the window.\n * @param action Pointer to an action.\n */\nvoid NextTurnState::handle(Action *action)\n{\n\tState::handle(action);\n\n\tif (_battleGame->isPreview())\n\t{\n\t\t// prevent NPE on Android/iOS\n\t\treturn;\n\t}\n\n\tif (_btnBriefingReinforcements->getVisible() && action->getDetails()->type == SDL_MOUSEBUTTONDOWN)\n\t{\n\t\tdouble mx = action->getAbsoluteXMouse();\n\t\tdouble my = action->getAbsoluteYMouse();\n\t\tif (mx >= _btnBriefingReinforcements->getX() && mx < _btnBriefingReinforcements->getX() + _btnBriefingReinforcements->getWidth() &&\n\t\t\tmy >= _btnBriefingReinforcements->getY() && my < _btnBriefingReinforcements->getY() + _btnBriefingReinforcements->getHeight())\n\t\t{\n\t\t\t// don't close on Briefing button click\n\t\t\treturn;\n\t\t}\n\t}\n\n\tif (action->getDetails()->type == SDL_KEYDOWN || action->getDetails()->type == SDL_MOUSEBUTTONDOWN)\n\t{\n\t\tclose();\n\t}\n}\n\n/**\n * Keeps the timer running.\n */\nvoid NextTurnState::think()\n{\n\tif (_timer)\n\t{\n\t\t_timer->think(this, 0);\n\t}\n}\n\n/**\n * Closes the window.\n */\nvoid NextTurnState::close()\n{\n\t_battleGame->getBattleGame()->cleanupDeleted();\n\t_game->popState();\n\n\tBattlescapeTally tally = _state->getBattleGame()->tallyUnits();\n\n\tif (_battleGame->getBattleGame()->areAllEnemiesNeutralized())\n\t{\n\t\t// we don't care if someone was revived in the meantime, the decision to end the battle was already made!\n\t\ttally.liveAliens = 0;\n\n\t\t// mind control anyone who was revived (needed for correct recovery in the debriefing)\n\t\tfor (auto* bu : *_battleGame->getUnits())\n\t\t{\n\t\t\tif (bu->getOriginalFaction() == FACTION_HOSTILE && !bu->isOut())\n\t\t\t{\n\t\t\t\tbu->convertToFaction(FACTION_PLAYER);\n\t\t\t}\n\t\t}\n\n\t\t// reset needed because of the potential next stage in multi-stage missions\n\t\t_battleGame->getBattleGame()->resetAllEnemiesNeutralized();\n\t}\n\n\t// not \"escort the VIPs\" missions, not the final mission and all aliens dead.\n\tbool killingAllAliensIsNotEnough = _battleGame->getObjectiveType() == MUST_DESTROY || (_battleGame->getVIPSurvivalPercentage() > 0 && _battleGame->getVIPEscapeType() != ESCAPE_NONE);\n\tif ((!killingAllAliensIsNotEnough && tally.liveAliens == 0) || tally.liveSoldiers == 0)\n\t{\n\t\t_state->finishBattle(false, tally.liveSoldiers);\n\t}\n\telse\n\t{\n\t\t_state->btnCenterClick(0);\n\n\t\t// Try to reactivate the touch buttons at the start of the player's turn\n\t\tif (_battleGame->getSide() == FACTION_PLAYER)\n\t\t{\n\t\t\t_state->toggleTouchButtons(false, true);\n\t\t}\n\n\t\t// Autosave every set amount of turns\n\t\tif ((_currentTurn == 1 || _currentTurn % Options::autosaveFrequency == 0) && _battleGame->getSide() == FACTION_PLAYER)\n\t\t{\n\t\t\t_state->autosave(_currentTurn);\n\t\t}\n\t}\n}\n\nvoid NextTurnState::resize(int &dX, int &dY)\n{\n\tState::resize(dX, dY);\n\t_bg->setX(0);\n\t_bg->setY(0);\n}\n\n/**\n * Shows the custom briefing for reinforcements.\n * @param action Pointer to an action.\n */\nvoid NextTurnState::btnBriefingReinforcementsClick(Action*)\n{\n\tif (_showBriefing)\n\t{\n\t\t_game->pushState(new BriefingState(0, 0, true, &_customBriefing));\n\t}\n}\n\n/**\n * Runs reinforcements logic.\n */\nbool NextTurnState::determineReinforcements()\n{\n\tconst AlienDeployment* deployment = _game->getMod()->getDeployment(_battleGame->getReinforcementsDeployment(), true);\n\n\tint currentTurnReinforcements = _battleGame->getTurn();\n\n\tif (!deployment)\n\t{\n\t\t// for backwards-compatibility! this save does not contain the data needed for this functionality...\n\t\treturn false;\n\t}\n\n\tbool showAlert = false;\n\tfor (auto& wave : *deployment->getReinforcementsData())\n\t{\n\t\t// 1. check pre-requisites\n\t\t{\n\t\t\tif (_game->getSavedGame()->getDifficulty() < wave.minDifficulty || _game->getSavedGame()->getDifficulty() > wave.maxDifficulty)\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (wave.objectiveDestroyed)\n\t\t\t{\n\t\t\t\tif (!_battleGame->allObjectivesDestroyed())\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (!wave.turns.empty())\n\t\t\t{\n\t\t\t\tif (std::find(wave.turns.begin(), wave.turns.end(), currentTurnReinforcements) == wave.turns.end())\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (currentTurnReinforcements < wave.minTurn || (wave.maxTurn != -1 && currentTurnReinforcements > wave.maxTurn))\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (wave.executionOdds < 100 && !RNG::percent(wave.executionOdds))\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (wave.maxRuns != -1 && _battleGame->getReinforcementsMemory()[wave.type] >= wave.maxRuns)\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\t// 2a. calculate compliant blocks\n\t\t{\n\t\t\t_compliantBlocksMap.clear();\n\t\t\t_compliantBlocksList.clear();\n\n\t\t\tint sizeX = _battleGame->getMapSizeX() / 10;\n\t\t\tint sizeY = _battleGame->getMapSizeY() / 10;\n\n\t\t\tif (wave.mapBlockFilterType == MFT_BY_MAPSCRIPT)\n\t\t\t{\n\t\t\t\t_compliantBlocksMap = _battleGame->getReinforcementsBlocks(); // we're done\n\t\t\t}\n\t\t\telse if (wave.mapBlockFilterType == MFT_BY_REINFORCEMENTS || wave.mapBlockFilterType == MFT_BY_BOTH_UNION || wave.mapBlockFilterType == MFT_BY_BOTH_INTERSECTION)\n\t\t\t{\n\t\t\t\tif (wave.spawnBlocks.empty())\n\t\t\t\t\t_compliantBlocksMap.resize((sizeX), std::vector<int>((sizeY), 1)); // start with all true\n\t\t\t\telse\n\t\t\t\t\t_compliantBlocksMap.resize((sizeX), std::vector<int>((sizeY), 0)); // start with all false\n\t\t\t}\n\t\t\telse //if (wave.mapBlockFilterType == MFT_NONE)\n\t\t\t{\n\t\t\t\t_compliantBlocksMap.resize((sizeX), std::vector<int>((sizeY), 1)); // all true (and we're done)\n\t\t\t}\n\n\t\t\tif (wave.mapBlockFilterType == MFT_BY_REINFORCEMENTS || wave.mapBlockFilterType == MFT_BY_BOTH_UNION || wave.mapBlockFilterType == MFT_BY_BOTH_INTERSECTION)\n\t\t\t{\n\t\t\t\tif (!wave.spawnBlocks.empty())\n\t\t\t\t{\n\t\t\t\t\tfor (auto& dir : wave.spawnBlocks)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (dir == \"EDGES\")\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfor (int x = 0; x < sizeX; ++x) _compliantBlocksMap[x][0] = 1;\n\t\t\t\t\t\t\tfor (int y = 0; y < sizeY; ++y) _compliantBlocksMap[0][y] = 1;\n\t\t\t\t\t\t\tfor (int x = 0; x < sizeX; ++x) _compliantBlocksMap[x][sizeY - 1] = 1;\n\t\t\t\t\t\t\tfor (int y = 0; y < sizeY; ++y) _compliantBlocksMap[sizeX - 1][y] = 1;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (dir == \"NORTH\")\n\t\t\t\t\t\t\tfor (int x = 0; x < sizeX; ++x) _compliantBlocksMap[x][0] = 1;\n\t\t\t\t\t\telse if (dir == \"WEST\")\n\t\t\t\t\t\t\tfor (int y = 0; y < sizeY; ++y) _compliantBlocksMap[0][y] = 1;\n\t\t\t\t\t\telse if (dir == \"SOUTH\")\n\t\t\t\t\t\t\tfor (int x = 0; x < sizeX; ++x) _compliantBlocksMap[x][sizeY - 1] = 1;\n\t\t\t\t\t\telse if (dir == \"EAST\")\n\t\t\t\t\t\t\tfor (int y = 0; y < sizeY; ++y) _compliantBlocksMap[sizeX - 1][y] = 1;\n\t\t\t\t\t\telse if (dir == \"NW\")\n\t\t\t\t\t\t\t_compliantBlocksMap[0][0] = 1;\n\t\t\t\t\t\telse if (dir == \"NE\")\n\t\t\t\t\t\t\t_compliantBlocksMap[sizeX - 1][0] = 1;\n\t\t\t\t\t\telse if (dir == \"SW\")\n\t\t\t\t\t\t\t_compliantBlocksMap[0][sizeY - 1] = 1;\n\t\t\t\t\t\telse if (dir == \"SE\")\n\t\t\t\t\t\t\t_compliantBlocksMap[sizeX - 1][sizeY - 1] = 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (wave.mapBlockFilterType == MFT_BY_BOTH_UNION)\n\t\t\t\t{\n\t\t\t\t\tauto& toMerge = _battleGame->getReinforcementsBlocks();\n\t\t\t\t\tfor (int x = 0; x < sizeX; ++x)\n\t\t\t\t\t\tfor (int y = 0; y < sizeY; ++y)\n\t\t\t\t\t\t\t_compliantBlocksMap[x][y] = _compliantBlocksMap[x][y] + toMerge[x][y];\n\t\t\t\t}\n\t\t\t\telse if (wave.mapBlockFilterType == MFT_BY_BOTH_INTERSECTION)\n\t\t\t\t{\n\t\t\t\t\tauto& toMerge = _battleGame->getReinforcementsBlocks();\n\t\t\t\t\tfor (int x = 0; x < sizeX; ++x)\n\t\t\t\t\t\tfor (int y = 0; y < sizeY; ++y)\n\t\t\t\t\t\t\t_compliantBlocksMap[x][y] = _compliantBlocksMap[x][y] * toMerge[x][y];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tbool checkGroups = !wave.spawnBlockGroups.empty();\n\n\t\t\t_compliantBlocksList.reserve(sizeX * sizeY);\n\n\t\t\tfor (int x = 0; x < sizeX; ++x)\n\t\t\t{\n\t\t\t\tfor (int y = 0; y < sizeY; ++y)\n\t\t\t\t{\n\t\t\t\t\tif (_compliantBlocksMap[x][y] > 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (checkGroups)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tauto* terrain = _game->getMod()->getTerrain(_battleGame->getFlattenedMapTerrainNames()[x][y], false);\n\t\t\t\t\t\t\tif (!terrain)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tauto* craft = _game->getMod()->getCraft(_battleGame->getFlattenedMapTerrainNames()[x][y], false);\n\t\t\t\t\t\t\t\tif (craft)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tterrain = craft->getBattlescapeTerrainData();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (!terrain)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tauto* ufo = _game->getMod()->getUfo(_battleGame->getFlattenedMapTerrainNames()[x][y], false);\n\t\t\t\t\t\t\t\tif (ufo)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tterrain = ufo->getBattlescapeTerrainData();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (terrain)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tauto* mapblock = terrain->getMapBlock(_battleGame->getFlattenedMapBlockNames()[x][y]);\n\t\t\t\t\t\t\t\tif (mapblock)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tbool groupMatched = false;\n\t\t\t\t\t\t\t\t\tfor (int group : wave.spawnBlockGroups)\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tif (mapblock->isInGroup(group))\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tgroupMatched = true;\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (!groupMatched)\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tcontinue; // don't add this map block into _compliantBlocksList\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t_compliantBlocksList.push_back(Position(x, y, 0));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// synchronize _compliantBlocksList and _compliantBlocksMap\n\t\t{\n\t\t\tfor (int x = 0; x < _battleGame->getMapSizeX() / 10; ++x)\n\t\t\t\tfor (int y = 0; y < _battleGame->getMapSizeY() / 10; ++y)\n\t\t\t\t\t_compliantBlocksMap[x][y] = 0;\n\n\t\t\tfor (const auto& pos : _compliantBlocksList)\n\t\t\t\t_compliantBlocksMap[pos.x][pos.y] = 1;\n\t\t}\n\n\t\t// 2b. calculate compliant nodes\n\t\t_compliantNodesList.clear();\n\t\tif (wave.useSpawnNodes)\n\t\t{\n\t\t\tbool checkBlocks = wave.mapBlockFilterType != MFT_NONE;\n\t\t\tbool checkNodeRanks = !wave.spawnNodeRanks.empty();\n\t\t\tbool checkZLevels = !wave.spawnZLevels.empty();\n\n\t\t\t_compliantNodesList.reserve(_battleGame->getNodes()->size());\n\n\t\t\tfor (auto* node : *_battleGame->getNodes())\n\t\t\t{\n\t\t\t\tif (node->isDummy())\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (checkNodeRanks && std::find(wave.spawnNodeRanks.begin(), wave.spawnNodeRanks.end(), (int)node->getRank()) == wave.spawnNodeRanks.end())\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (checkZLevels && std::find(wave.spawnZLevels.begin(), wave.spawnZLevels.end(), node->getPosition().z) == wave.spawnZLevels.end())\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (checkBlocks && _compliantBlocksMap[node->getPosition().x / 10][node->getPosition().y / 10] == 0)\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tauto* tileToCheck = _battleGame->getTile(node->getPosition());\n\t\t\t\tif (tileToCheck && tileToCheck->getUnit())\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (wave.minDistanceFromXcomUnits > 1)\n\t\t\t\t{\n\t\t\t\t\tbool foundXcomUnitNearby = false;\n\t\t\t\t\tfor (auto* xcomUnit : *_battleGame->getUnits())\n\t\t\t\t\t{\n\t\t\t\t\t\tif (xcomUnit->getOriginalFaction() == FACTION_PLAYER &&\n\t\t\t\t\t\t\t!xcomUnit->isOut() &&\n\t\t\t\t\t\t\tPosition::distanceSq(xcomUnit->getPosition(), node->getPosition()) < wave.minDistanceFromXcomUnits * wave.minDistanceFromXcomUnits)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfoundXcomUnitNearby = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (foundXcomUnitNearby) continue;\n\t\t\t\t}\n\t\t\t\tif (wave.maxDistanceFromBorders > 0 && wave.maxDistanceFromBorders < 10)\n\t\t\t\t{\n\t\t\t\t\tif (node->getPosition().x >= wave.maxDistanceFromBorders &&\n\t\t\t\t\t\tnode->getPosition().x < _battleGame->getMapSizeX() - wave.maxDistanceFromBorders &&\n\t\t\t\t\t\tnode->getPosition().y >= wave.maxDistanceFromBorders &&\n\t\t\t\t\t\tnode->getPosition().y < _battleGame->getMapSizeY() - wave.maxDistanceFromBorders)\n\t\t\t\t\t{\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t_compliantNodesList.push_back(node);\n\t\t\t}\n\n\t\t\t// let's simulate selecting at random even when iterating sequentially\n\t\t\tRNG::shuffle(_compliantNodesList);\n\t\t}\n\n\t\t// 3. deploy units\n\t\tbool success = deployReinforcements(wave);\n\n\t\t// 4. post-processing\n\t\tif (success)\n\t\t{\n\t\t\t// remember success\n\t\t\t_battleGame->getReinforcementsMemory()[wave.type] += 1;\n\n\t\t\tif (!wave.briefing.title.empty())\n\t\t\t{\n\t\t\t\t_customBriefing = wave.briefing;\n\t\t\t\t_showBriefing = true;\n\t\t\t}\n\t\t\tshowAlert = true;\n\t\t}\n\t}\n\tif (_showBriefing)\n\t{\n\t\t_btnBriefingReinforcements->setVisible(true);\n\t}\n\n\treturn showAlert;\n}\n\n/**\n * Deploys the reinforcements, according to the alien reinforcements deployment rules.\n * @param wave Pointer to the reinforcements deployment rules.\n */\nbool NextTurnState::deployReinforcements(const ReinforcementsData &wave)\n{\n\tconst AlienRace* race = _game->getMod()->getAlienRace(_battleGame->getReinforcementsRace(), true);\n\tconst int month = _battleGame->getReinforcementsItemLevel();\n\tbool success = false;\n\n\tfor (const auto& dd : wave.data)\n\t{\n\t\tint quantity;\n\n\t\tswitch (_game->getSavedGame()->getDifficulty())\n\t\t{\n\t\tcase DIFF_BEGINNER:\n\t\t\tquantity = dd.lowQty;\n\t\t\tbreak;\n\t\tcase DIFF_EXPERIENCED:\n\t\t\tquantity = dd.medQty > 0 ? dd.lowQty + ((dd.medQty - dd.lowQty) / 2) : dd.lowQty;\n\t\t\tbreak;\n\t\tcase DIFF_VETERAN:\n\t\t\tquantity = dd.medQty > 0 ? dd.medQty : dd.lowQty + ((dd.highQty - dd.lowQty) / 2);\n\t\t\tbreak;\n\t\tcase DIFF_GENIUS:\n\t\t\tquantity = dd.medQty > 0 ? dd.medQty + ((dd.highQty - dd.medQty) / 2) : dd.lowQty + ((dd.highQty - dd.lowQty) / 2);\n\t\t\tbreak;\n\t\tcase DIFF_SUPERHUMAN:\n\t\tdefault:\n\t\t\tquantity = dd.highQty;\n\t\t}\n\n\t\tquantity += RNG::generate(0, dd.dQty);\n\t\tquantity += RNG::generate(0, dd.extraQty);\n\n\t\tfor (int i = 0; i < quantity; ++i)\n\t\t{\n\t\t\tstd::string alienName = dd.customUnitType.empty() ? race->getMember(dd.alienRank) : dd.customUnitType;\n\t\t\tUnit* rule = _game->getMod()->getUnit(alienName, true);\n\t\t\tbool civilian = dd.percentageOutsideUfo != 0; // small misuse of an unused attribute ;) pls don't kill me\n\t\t\tBattleUnit* unit = addReinforcement(wave, rule, dd.alienRank, civilian);\n\t\t\tsize_t itemLevel = (size_t)(_game->getMod()->getAlienItemLevels().at(month).at(RNG::generate(0, 9)));\n\t\t\tif (unit)\n\t\t\t{\n\t\t\t\tsuccess = true;\n\t\t\t\t_battleGame->initUnit(unit, itemLevel);\n\t\t\t\tif (!rule->isLivingWeapon())\n\t\t\t\t{\n\t\t\t\t\tif (dd.itemSets.empty())\n\t\t\t\t\t{\n\t\t\t\t\t\tthrow Exception(\"Reinforcements generator encountered an error: item set not defined\");\n\t\t\t\t\t}\n\t\t\t\t\tif (itemLevel >= dd.itemSets.size())\n\t\t\t\t\t{\n\t\t\t\t\t\titemLevel = dd.itemSets.size() - 1;\n\t\t\t\t\t}\n\t\t\t\t\tfor (auto& itemType : dd.itemSets.at(itemLevel).items)\n\t\t\t\t\t{\n\t\t\t\t\t\tRuleItem* ruleItem = _game->getMod()->getItem(itemType);\n\t\t\t\t\t\tif (ruleItem)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_battleGame->createItemForUnit(ruleItem, unit);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tfor (auto& iset : dd.extraRandomItems)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (iset.items.empty())\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\tint pick = RNG::generate(0, iset.items.size() - 1);\n\t\t\t\t\t\tRuleItem* ruleItem = _game->getMod()->getItem(iset.items[pick]);\n\t\t\t\t\t\tif (ruleItem)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_battleGame->createItemForUnit(ruleItem, unit);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn success;\n}\n\n/**\n * Adds a reinforcements unit to the game and places him on a free spawnpoint.\n * @param wave Pointer to the reinforcements deployment rules.\n * @param rules Pointer to the Unit which holds info about the alien.\n * @param alienRank The rank of the alien, used for spawn point search.\n * @param civilian Spawn as a civilian?\n * @return Pointer to the created unit.\n */\nBattleUnit* NextTurnState::addReinforcement(const ReinforcementsData &wave, Unit *rules, int alienRank, bool civilian)\n{\n\tBattleUnit* unit = _battleGame->createTempUnit(rules, civilian ? FACTION_NEUTRAL : FACTION_HOSTILE);\n\n\t// 1. try nodes first\n\tbool unitPlaced = false;\n\tif (wave.useSpawnNodes && !_compliantNodesList.empty())\n\t{\n\t\tfor (auto* node : _compliantNodesList)\n\t\t{\n\t\t\tif (_battleGame->setUnitPosition(unit, node->getPosition()))\n\t\t\t{\n\t\t\t\tunit->getAIModule()->setStartNode(node);\n\t\t\t\tunit->setRankInt(alienRank);\n\t\t\t\tunit->setDirection(RNG::generate(0, 7));\n\t\t\t\t_battleGame->getUnits()->push_back(unit);\n\t\t\t\tunitPlaced = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// 2. then try random positions on compliant blocks\n\tif (!unitPlaced && !_compliantBlocksList.empty())\n\t{\n\t\tstd::vector<int> tmpZList = wave.spawnZLevels; // copy\n\t\tif (tmpZList.empty())\n\t\t{\n\t\t\ttmpZList.reserve(_battleGame->getMapSizeZ());\n\t\t\tfor (int z = 0; z < _battleGame->getMapSizeZ(); ++z)\n\t\t\t{\n\t\t\t\ttmpZList.push_back(z);\n\t\t\t}\n\t\t}\n\t\tif (wave.randomizeZLevels)\n\t\t{\n\t\t\tRNG::shuffle(tmpZList);\n\t\t}\n\t\tint tries = 100;\n\t\tint randomX = 0;\n\t\tint randomY = 0;\n\t\tint edgeX = (_battleGame->getMapSizeX() / 10) - 1;\n\t\tint edgeY = (_battleGame->getMapSizeY() / 10) - 1;\n\t\twhile (!unitPlaced && tries)\n\t\t{\n\t\t\tint randomBlockIndex = RNG::generate(0, _compliantBlocksList.size() - 1);\n\t\t\tif (wave.maxDistanceFromBorders > 0 && wave.maxDistanceFromBorders < 10)\n\t\t\t{\n\t\t\t\t// Note: we assume that the modder has done the necessary work and allowed only border blocks to come this far\n\t\t\t\tif (_compliantBlocksList[randomBlockIndex].x == 0)\n\t\t\t\t{\n\t\t\t\t\trandomX = RNG::generate(0, wave.maxDistanceFromBorders - 1);\n\t\t\t\t}\n\t\t\t\telse if (_compliantBlocksList[randomBlockIndex].x == edgeX)\n\t\t\t\t{\n\t\t\t\t\trandomX = RNG::generate(10 - wave.maxDistanceFromBorders, 9);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\trandomX = RNG::generate(0, 9); // modder fail\n\t\t\t\t}\n\t\t\t\tif (_compliantBlocksList[randomBlockIndex].y == 0)\n\t\t\t\t{\n\t\t\t\t\trandomY = RNG::generate(0, wave.maxDistanceFromBorders - 1);\n\t\t\t\t}\n\t\t\t\telse if (_compliantBlocksList[randomBlockIndex].y == edgeY)\n\t\t\t\t{\n\t\t\t\t\trandomY = RNG::generate(10 - wave.maxDistanceFromBorders, 9);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\trandomY = RNG::generate(0, 9); // modder fail\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\trandomX = RNG::generate(0, 9);\n\t\t\t\trandomY = RNG::generate(0, 9);\n\t\t\t}\n\t\t\tPosition randomPos = Position(_compliantBlocksList[randomBlockIndex].x * 10 + randomX, _compliantBlocksList[randomBlockIndex].y * 10 + randomY, 0);\n\n\t\t\tbool foundXcomUnitNearby = false;\n\t\t\tif (wave.minDistanceFromXcomUnits > 1)\n\t\t\t{\n\t\t\t\tfor (auto* xcomUnit : *_battleGame->getUnits())\n\t\t\t\t{\n\t\t\t\t\tif (xcomUnit->getOriginalFaction() == FACTION_PLAYER &&\n\t\t\t\t\t\t!xcomUnit->isOut() &&\n\t\t\t\t\t\tPosition::distanceSq(xcomUnit->getPosition(), randomPos) < wave.minDistanceFromXcomUnits * wave.minDistanceFromXcomUnits)\n\t\t\t\t\t{\n\t\t\t\t\t\tfoundXcomUnitNearby = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!foundXcomUnitNearby)\n\t\t\t{\n\t\t\t\tfor (int tryZ : tmpZList)\n\t\t\t\t{\n\t\t\t\t\tPosition finalPos = randomPos + Position(0, 0, tryZ);\n\t\t\t\t\tif (unit->getMovementType() != MT_FLY)\n\t\t\t\t\t{\n\t\t\t\t\t\tTile* t = _battleGame->getTile(finalPos);\n\t\t\t\t\t\tif (t == 0 || t->getTUCost(O_FLOOR, unit->getMovementType()) == Pathfinding::INVALID_MOVE_COST)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// non-flying units cannot spawn on e.g. a water tile (e.g. in the POLAR terrain)\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (_battleGame->setUnitPosition(unit, finalPos))\n\t\t\t\t\t{\n\t\t\t\t\t\tunit->setRankInt(alienRank);\n\t\t\t\t\t\tunit->setDirection(RNG::generate(0, 7));\n\t\t\t\t\t\t_battleGame->getUnits()->push_back(unit);\n\t\t\t\t\t\tunitPlaced = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t--tries;\n\t\t}\n\t}\n\n\t// 3. finally just place it somewhere\n\tif (!unitPlaced && wave.forceSpawnNearFriend && placeReinforcementNearFriend(unit))\n\t{\n\t\tunit->setRankInt(alienRank);\n\t\tunit->setDirection(RNG::generate(0, 7));\n\t\t_battleGame->getUnits()->push_back(unit);\n\t\tunitPlaced = true;\n\t}\n\n\t// 4. dude, seriously?\n\tif (!unitPlaced)\n\t{\n\t\tdelete unit;\n\t\tunit = nullptr;\n\t}\n\n\treturn unit;\n}\n\n/**\n * Places a unit near a friendly unit.\n * @param unit Pointer to the unit in question.\n * @return If we successfully placed the unit.\n */\nbool NextTurnState::placeReinforcementNearFriend(BattleUnit *unit)\n{\n\tif (_battleGame->getUnits()->empty())\n\t{\n\t\treturn false;\n\t}\n\tfor (int i = 0; i != 10; ++i)\n\t{\n\t\tPosition entryPoint = TileEngine::invalid;\n\t\tint tries = 100;\n\t\tbool largeUnit = false;\n\t\twhile (entryPoint == TileEngine::invalid && tries)\n\t\t{\n\t\t\tBattleUnit* k = _battleGame->getUnits()->at(RNG::generate(0, _battleGame->getUnits()->size() - 1));\n\t\t\tif (k->getFaction() == unit->getFaction() && k->getPosition() != TileEngine::invalid && k->getArmor()->getSize() >= unit->getArmor()->getSize())\n\t\t\t{\n\t\t\t\tentryPoint = k->getPosition();\n\t\t\t\tlargeUnit = k->isBigUnit();\n\t\t\t}\n\t\t\t--tries;\n\t\t}\n\t\tif (tries && _battleGame->placeUnitNearPosition(unit, entryPoint, largeUnit))\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/NextTurnState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include \"../Savegame/BattleUnit.h\"\n#include \"../Mod/AlienDeployment.h\"\n#include \"../Mod/RuleEnviroEffects.h\"\n\nnamespace OpenXcom\n{\n\nclass Window;\nclass Text;\nclass TextButton;\nclass SavedBattleGame;\nclass BattlescapeState;\nclass Timer;\nclass Surface;\nclass Unit;\nclass BattleUnit;\nclass Node;\nclass Position;\n\n/**\n * Screen which announces the next turn.\n */\nclass NextTurnState : public State\n{\nprivate:\n\tstatic const int NEXT_TURN_DELAY = 500;\n\tWindow *_window;\n\tText *_txtTitle, *_txtTurn, *_txtSide, *_txtMessage, *_txtMessage2, *_txtMessage3, *_txtMessageReinforcements;\n\tTextButton *_btnBriefingReinforcements;\n\tSavedBattleGame *_battleGame;\n\tBattlescapeState *_state;\n\tTimer *_timer;\n\tSurface *_bg;\n\tint _currentTurn;\n\tbool _showBriefing;\n\tBriefingData _customBriefing;\n\tstd::vector< std::vector<int> > _compliantBlocksMap;\n\tstd::vector<Node*> _compliantNodesList;\n\tstd::vector<Position> _compliantBlocksList;\n\n\t/// Applies a given environmental condition effects to a given faction.\n\tbool applyEnvironmentalConditionToFaction(UnitFaction faction, EnvironmentalCondition condition);\n\t/// Checks if bug hunt mode should be activated or not.\n\tvoid checkBugHuntMode();\n\n\t/// Runs reinforcements logic.\n\tbool determineReinforcements();\n\t/// Deploys the reinforcements, according to the alien reinforcements deployment rules.\n\tbool deployReinforcements(const ReinforcementsData &wave);\n\t/// Adds a reinforcement unit to the game.\n\tBattleUnit* addReinforcement(const ReinforcementsData &wave, Unit *rules, int alienRank, bool civilian);\n\t/// Finds a spot near a friend to spawn at.\n\tbool placeReinforcementNearFriend(BattleUnit *unit);\npublic:\n\t/// Creates the Next Turn state.\n\tNextTurnState(SavedBattleGame *battleGame, BattlescapeState *state);\n\t/// Cleans up the Next Turn state.\n\t~NextTurnState();\n\t/// Initialization\n\tvoid init() override;\n\t/// Handler for clicking anything.\n\tvoid handle(Action *action) override;\n\t/// Handles the timer.\n\tvoid think() override;\n\t/// Closes the window.\n\tvoid close();\n\tvoid resize(int &dX, int &dY) override;\n\t/// Handler for clicking the Reinforcements Briefing button.\n\tvoid btnBriefingReinforcementsClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/NoExperienceState.cpp",
    "content": "/*\n * Copyright 2010-2019 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"NoExperienceState.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Savegame/BattleUnit.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"../Savegame/SavedGame.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the NoExperience window.\n */\nNoExperienceState::NoExperienceState()\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 216, 160, 52, 20, POPUP_BOTH);\n\t_txtTitle = new Text(206, 17, 57, 32);\n\t_btnCancel = new TextButton(140, 16, 90, 156);\n\t_lstSoldiers = new TextList(180, 96, 65, 52);\n\n\t// Set palette\n\t_game->getSavedGame()->getSavedBattle()->setPaletteByDepth(this);\n\n\tadd(_window, \"messageWindowBorder\", \"battlescape\");\n\tadd(_txtTitle, \"messageWindows\", \"battlescape\");\n\tadd(_btnCancel, \"messageWindowButtons\", \"battlescape\");\n\tadd(_lstSoldiers, \"optionLists\", \"battlescape\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\t_window->setHighContrast(true);\n\t_window->setBackground(_game->getMod()->getSurface(\"TAC00.SCR\"));\n\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setBig();\n\t_txtTitle->setHighContrast(true);\n\t_txtTitle->setText(tr(\"STR_NO_EXPERIENCE_YET\"));\n\n\t_btnCancel->setText(tr(\"STR_CANCEL_UC\"));\n\t_btnCancel->setHighContrast(true);\n\t_btnCancel->onMouseClick((ActionHandler)&NoExperienceState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&NoExperienceState::btnCancelClick, Options::keyCancel);\n\n\t_lstSoldiers->setColumns(1, 172);\n\t_lstSoldiers->setSelectable(true);\n\t_lstSoldiers->setBackground(_window);\n\t_lstSoldiers->setMargin(8);\n\t_lstSoldiers->setAlign(ALIGN_CENTER);\n\t_lstSoldiers->setHighContrast(true);\n\t_lstSoldiers->setWordWrap(true);\n\n\tsize_t row = 0;\n\tfor (auto* bu : *_game->getSavedGame()->getSavedBattle()->getUnits())\n\t{\n\t\tif (bu->getOriginalFaction() == FACTION_PLAYER && !bu->isOut())\n\t\t{\n\t\t\tif (bu->getGeoscapeSoldier() && !bu->hasGainedAnyExperience())\n\t\t\t{\n\t\t\t\t_lstSoldiers->addRow(1, bu->getName(_game->getLanguage()).c_str());\n\t\t\t\tif (row % 2 != 0)\n\t\t\t\t{\n\t\t\t\t\t_lstSoldiers->setRowColor(row, _lstSoldiers->getSecondaryColor());\n\t\t\t\t}\n\t\t\t\t++row;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid NoExperienceState::btnCancelClick(Action *)\n{\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/NoExperienceState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2019 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass Window;\nclass Text;\nclass TextButton;\nclass TextList;\n\n/**\n * NoExperience window that displays a list of soldiers without any experience points gained in the current mission.\n */\nclass NoExperienceState : public State\n{\nprivate:\n\tWindow *_window;\n\tText *_txtTitle;\n\tTextButton *_btnCancel;\n\tTextList *_lstSoldiers;\npublic:\n\t/// Creates the NoExperience state.\n\tNoExperienceState();\n\t/// Cleans up the NoExperience state.\n\t~NoExperienceState() = default;\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/Particle.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include <algorithm>\n#include \"../Engine/RNG.h\"\n#include \"Particle.h\"\n#include \"../Mod/Mod.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Creates a particle.\n * @param xOffset the horizontal offset for this particle (relative to the tile in screen space)\n * @param yOffset the vertical offset for this particle (relative to the tile in screen space)\n * @param density the density of the particle dictates the speed at which it moves upwards, and is inversely proportionate to its size.\n * @param color the color set to use from the transparency LUTs\n * @param opacity another reference for the LUT, this one is divided by 5 for the actual offset to use.\n */\nParticle::Particle(Position voxelPos, Position subVoxelOffset, Position subVoxelVel, Position subVoxelAcc, Uint8 drift, Uint8 color, Uint8 opacity, Uint8 size) : _drift(drift), _color(color), _opacity(opacity), _size(size)\n{\n\t_layerZ = (voxelPos.z / Position::TileZ) << 1;\n\n\t_subVoxelPos = voxelPos.clipVoxel() * SubVoxelAccuracy;\n\t_subVoxelPos += subVoxelOffset;\n\n\t_subVoxelVelocity = subVoxelVel;\n\t_subVoxelAcceleration = subVoxelAcc;\n}\n\n/**\n * Animates the particle.\n * @return if we are done animating this particle yet.\n */\nbool Particle::animate()\n{\n\t_opacity--;\n\n\t_subVoxelPos.x += RNG::seedless(-_drift, _drift);\n\t_subVoxelPos.y += RNG::seedless(-_drift, _drift);\n\t_subVoxelPos.z += RNG::seedless(-_drift, _drift);\n\t_subVoxelPos += _subVoxelVelocity;\n\t_subVoxelVelocity += _subVoxelAcceleration;\n\n\tif ( _opacity == 0 )\n\t{\n\t\treturn false;\n\t}\n\treturn true;\n}\n\n/**\n * Update relative screen position of particle.\n * @return Offset to next tile if particle cross tile boundaries.\n */\nPosition Particle::updateScreenPosition()\n{\n\tstatic constexpr Position one = Position(1, 1, 1);\n\tstatic constexpr Position scale = one.toVoxel() * SubVoxelAccuracy;\n\n\t// this convert postion to -1, 0 or +1 depending if _subVoxelPos is outside current tile\n\tPosition tileOffset = ((_subVoxelPos + scale) /  scale - one);\n\n\t// keep values inside one tile\n\tif (tileOffset.x)\n\t{\n\t\t_subVoxelPos.x -= tileOffset.x * Position::TileXY * SubVoxelAccuracy;\n\t}\n\tif (tileOffset.y)\n\t{\n\t\t_subVoxelPos.y -= tileOffset.y * Position::TileXY * SubVoxelAccuracy;\n\t}\n\tif (tileOffset.z)\n\t{\n\t\t_subVoxelPos.z -= tileOffset.z * Position::TileZ * SubVoxelAccuracy;\n\t\t_layerZ += tileOffset.z * LayerAccuracy;\n\t}\n\n\t// voxel closer to front of screen are consider on higher layer\n\t_layerZ &= 0xFE; //cut smallest bit\n\t_layerZ |= (_subVoxelPos.x + _subVoxelPos.y > Position::TileXY*SubVoxelAccuracy);\n\n\tPosition v = _subVoxelPos / SubVoxelAccuracy;\n\t_screenData.x = v.x - v.y;\n\t_screenData.y = (v.x / 2) + (v.y / 2) - v.z - getTileZ() * Position::TileZ;\n\t_screenData.z = std::min((_opacity + 7) / 10, Mod::TransparenciesOpacityLevels - 1);\n\n\treturn tileOffset;\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/Particle.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <SDL_types.h>\n#include \"Position.h\"\n\nnamespace OpenXcom\n{\n\nclass Particle\n{\npublic:\n\tconstexpr static int SubVoxelAccuracy = 256;\n\tconstexpr static int LayerAccuracy = 2;\n\nprivate:\n\tPosition _subVoxelPos;\n\tPosition _screenData;\n\tPosition _subVoxelVelocity;\n\tPosition _subVoxelAcceleration;\n\tUint8 _drift;\n\tUint8 _layerZ;\n\tUint8 _color, _opacity, _size;\npublic:\n\t/// Create a particle.\n\tParticle(Position voxelPos, Position subVoxelOffset, Position subVoxelVel, Position subVoxelAcc, Uint8 drift, Uint8 color, Uint8 opacity, Uint8 size);\n\t/// Default copy constructor\n\tParticle(const Particle&) = default;\n\t/// Default move constructor\n\tParticle(Particle&&) = default;\n\t/// Copy assignment.\n\tParticle& operator=(const Particle&) = default;\n\t/// Move assignment.\n\tParticle& operator=(Particle&&) = default;\n\t/// Destroy a particle.\n\t~Particle() = default;\n\t/// Animate a particle.\n\tbool animate();\n\t/// Update screen data.\n\tPosition updateScreenPosition();\n\t/// Get the size value.\n\tint getSize() const { return _size; }\n\t/// Get the color.\n\tUint8 getColor() const { return _color; }\n\t/// Get the opacity.\n\tUint8 getOpacity() const { return _screenData.z; }\n\t/// Gets screen offset X relative to tile.\n\tint getOffsetX() const { return _screenData.x; }\n\t/// Gets screen offset Y relative to tile.\n\tint getOffsetY() const { return _screenData.y; }\n\t/// Get layer position of particle.\n\tint getLayerZ() const { return _layerZ; }\n\t/// Get tile position of particle.\n\tint getTileZ() const { return _layerZ / LayerAccuracy; }\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/Pathfinding.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <list>\n#include <algorithm>\n#include \"Pathfinding.h\"\n#include \"PathfindingOpenSet.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"../Savegame/Tile.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Savegame/BattleUnit.h\"\n#include \"../Engine/Options.h\"\n#include \"../fmath.h\"\n#include \"BattlescapeGame.h\"\n\nnamespace OpenXcom\n{\n\nconstexpr int Pathfinding::dir_x[Pathfinding::dir_max];\nconstexpr int Pathfinding::dir_y[Pathfinding::dir_max];\nconstexpr int Pathfinding::dir_z[Pathfinding::dir_max];\n\nint Pathfinding::red = 3;\nint Pathfinding::yellow = 10;\nint Pathfinding::green = 4;\n\n/**\n * Sets up a Pathfinding.\n * @param save pointer to SavedBattleGame object.\n */\nPathfinding::Pathfinding(SavedBattleGame *save) : _save(save), _unit(0), _pathPreviewed(false), _strafeMove(false)\n{\n\t_size = _save->getMapSizeXYZ();\n\t// Initialize one node per tile\n\t_nodes.reserve(_size);\n\tfor (int i = 0; i < _size; ++i)\n\t{\n\t\t_nodes.push_back(PathfindingNode(_save->getTileCoords(i)));\n\t}\n}\n\n/**\n * Deletes the Pathfinding.\n * @internal This is required to be here because it requires the PathfindingNode class definition.\n */\nPathfinding::~Pathfinding()\n{\n\t// Nothing more to do here.\n}\n\n/**\n * Gets the Node on a given position on the map.\n * @param pos Position.\n * @return Pointer to node.\n */\nPathfindingNode *Pathfinding::getNode(Position pos)\n{\n\treturn &_nodes[_save->getTileIndex(pos)];\n}\n\n/**\n * Calculates the shortest path.\n * @param unit Unit taking the path.\n * @param endPosition The position we want to reach.\n * @param missileTarget Target of the path.\n * @param maxTUCost Maximum time units the path can cost.\n */\nvoid Pathfinding::calculate(BattleUnit *unit, Position endPosition, BattleActionMove bam, const BattleUnit *missileTarget, int maxTUCost)\n{\n\t_totalTUCost = {};\n\t_path.clear();\n\n\tconst int size = bam != BAM_MISSILE ? unit->getArmor()->getSize() : 1;\n\n\t// i'm DONE with these out of bounds errors.\n\tif (endPosition.x > _save->getMapSizeX() - size || endPosition.y > _save->getMapSizeY() - size || endPosition.x < 0 || endPosition.y < 0) return;\n\n\tbool sneak = Options::sneakyAI && unit->getFaction() == FACTION_HOSTILE;\n\n\tPosition startPosition = unit->getPosition();\n\tMovementType movementType = getMovementType(unit, missileTarget, bam);\n\tif (missileTarget != 0 && maxTUCost == -1 && bam == BAM_MISSILE)  // pathfinding for missile\n\t{\n\t\tmaxTUCost = 10000;\n\t}\n\t_unit = unit;\n\n\tconst Tile* destinationTile = _save->getTile(endPosition);\n\n\t// check if destination is not blocked\n\tif (isBlocked(_unit, destinationTile, O_FLOOR, bam, missileTarget) || isBlocked(_unit, destinationTile, O_OBJECT, bam, missileTarget)) return;\n\n\t// the following check avoids that the unit walks behind the stairs if we click behind the stairs to make it go up the stairs.\n\t// it only works if the unit is on one of the 2 tiles on the stairs, or on the tile right in front of the stairs.\n\tif (isOnStairs(startPosition, endPosition))\n\t{\n\t\tendPosition.z++;\n\t\tdestinationTile = _save->getTile(endPosition);\n\t}\n\twhile (endPosition.z != _save->getMapSizeZ() && destinationTile->getTerrainLevel() == -24)\n\t{\n\t\tendPosition.z++;\n\t\tdestinationTile = _save->getTile(endPosition);\n\t}\n\t// make sure we didn't just try to adjust the Z of our destination outside the map\n\t// this occurs in rare circumstances where an object has terrainLevel -24 on the top floor\n\t// and is considered passable terrain for whatever reason (usually bigwall type objects)\n\tif (endPosition.z == _save->getMapSizeZ())\n\t{\n\t\treturn; // Icarus is a bad role model for XCom soldiers.\n\t}\n\tif (movementType != MT_FLY && bam != BAM_MISSILE)\n\t{\n\t\t// check if we have floor, else lower destination (for non flying units only, because otherwise they never reached this place)\n\t\twhile (canFallDown(destinationTile, size) && !(size == 1 && destinationTile->hasLadder()))\n\t\t{\n\t\t\tendPosition.z--;\n\t\t\tdestinationTile = _save->getTile(endPosition);\n\t\t}\n\t}\n\t// check if destination is not blocked\n\tif (isBlocked(_unit, destinationTile, O_FLOOR, bam, missileTarget) || isBlocked(_unit, destinationTile, O_OBJECT, bam, missileTarget)) return;\n\n\t// Strafing move allowed only to adjacent squares on same z. \"Same z\" rule mainly to simplify walking render.\n\t_strafeMove = bam == BAM_STRAFE && (startPosition.z == endPosition.z) &&\n\t\t\t\t\t\t\t(abs(startPosition.x - endPosition.x) <= 1) && (abs(startPosition.y - endPosition.y) <= 1);\n\n\tif (_strafeMove)\n\t{\n\t\tint direction = -1;\n\t\tvectorToDirection(endPosition - startPosition, direction);\n\t\tif (direction == -1 || std::min(abs(8 + direction - _unit->getDirection()), std::min( abs(_unit->getDirection() - direction), abs(8 + _unit->getDirection() - direction))) > 2)\n\t\t{\n\t\t\t// Strafing backwards-ish currently unsupported, turn it off and continue.\n\t\t\t_strafeMove = false;\n\t\t}\n\t\telse if (getTUCost(startPosition, direction, _unit, 0, bam).cost.time == INVALID_MOVE_COST)\n\t\t{\n\t\t\t// we can't reach in one step\n\t\t\t_strafeMove = false;\n\t\t}\n\t}\n\n\t// look for a possible fast and accurate bresenham path and skip A*\n\tif (bresenhamPath(startPosition, endPosition, bam, missileTarget, sneak))\n\t{\n\t\tstd::reverse(_path.begin(), _path.end()); //paths are stored in reverse order\n\t\treturn;\n\t}\n\telse\n\t{\n\t\tabortPath(); // if bresenham failed, we shouldn't keep the path it was attempting, in case A* fails too.\n\t}\n\t// Now try through A*.\n\tif (!aStarPath(startPosition, endPosition, bam, missileTarget, sneak, maxTUCost))\n\t{\n\t\tabortPath();\n\t}\n}\n\n/**\n * Calculates the shortest path using a simple A-Star algorithm.\n * The unit information and movement type must have already been set.\n * The path information is set only if a valid path is found.\n * @param startPosition The position to start from.\n * @param endPosition The position we want to reach.\n * @param missileTarget Target of the path.\n * @param sneak Is the unit sneaking?\n * @param maxTUCost Maximum time units the path can cost.\n * @return True if a path exists, false otherwise.\n */\nbool Pathfinding::aStarPath(Position startPosition, Position endPosition, BattleActionMove bam, const BattleUnit *missileTarget, bool sneak, int maxTUCost)\n{\n\t// reset every node, so we have to check them all\n\tfor (auto& pn : _nodes)\n\t{\n\t\tpn.reset();\n\t}\n\n\t// start position is the first one in our \"open\" list\n\tPathfindingNode *start = getNode(startPosition);\n\tstart->connect({}, 0, 0, endPosition);\n\tPathfindingOpenSet openList;\n\topenList.push(start);\n\tbool missile = (bam == BAM_MISSILE);\n\t// if the open list is empty, we've reached the end\n\twhile (!openList.empty())\n\t{\n\t\tPathfindingNode *currentNode = openList.pop();\n\t\tPosition const &currentPos = currentNode->getPosition();\n\t\tcurrentNode->setChecked();\n\t\tif (currentPos == endPosition) // We found our target.\n\t\t{\n\t\t\t_path.clear();\n\t\t\tPathfindingNode *pf = currentNode;\n\t\t\twhile (pf->getPrevNode())\n\t\t\t{\n\t\t\t\t_path.push_back(pf->getPrevDir());\n\t\t\t\tpf = pf->getPrevNode();\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\n\t\t// Try all reachable neighbours.\n\t\tfor (int direction = 0; direction < 10; direction++)\n\t\t{\n\t\t\tPathfindingStep r = getTUCost(currentPos, direction, _unit, missileTarget, bam);\n\t\t\tif (r.cost.time == INVALID_MOVE_COST) // Skip unreachable / blocked\n\t\t\t\tcontinue;\n\n\t\t\tPosition nextPos = r.pos;\n\t\t\tif (sneak && _save->getTile(nextPos)->getVisible()) r.cost.time *= 2; // avoid being seen\n\t\t\tPathfindingNode *nextNode = getNode(nextPos);\n\t\t\tif (nextNode->isChecked()) // Our algorithm means this node is already at minimum cost.\n\t\t\t\tcontinue;\n\t\t\t_totalTUCost = currentNode->getTUCost(missile) + r.cost + r.penalty;\n\t\t\t// If this node is unvisited or has only been visited from inferior paths...\n\t\t\tif ((!nextNode->inOpenSet() || nextNode->getTUCost(missile).time > _totalTUCost.time) && _totalTUCost.time <= maxTUCost)\n\t\t\t{\n\t\t\t\tnextNode->connect(_totalTUCost, currentNode, direction, endPosition);\n\t\t\t\topenList.push(nextNode);\n\t\t\t}\n\t\t}\n\t}\n\t// Unable to reach the target\n\treturn false;\n}\n\n/**\n * Gets the TU cost to move from 1 tile to the other (ONE STEP ONLY).\n * But also updates the endPosition, because it is possible\n * the unit goes upstairs or falls down while walking.\n * @param startPosition The position to start from.\n * @param direction The direction we are facing.\n * @param endPosition The position we want to reach.\n * @param unit The unit moving.\n * @param missileTarget The target unit used for BAM_MISSILE.\n * @param bam What move type is required (one special case is BAM_MISSILE)?\n * @return TU cost or 255 if movement is impossible.\n */\nPathfindingStep Pathfinding::getTUCost(Position startPosition, int direction, const BattleUnit *unit, const BattleUnit *missileTarget, BattleActionMove bam) const\n{\n\tPosition pos;\n\tdirectionToVector(direction, &pos);\n\tpos += startPosition;\n\n\tconst MovementType movementType = getMovementType(unit, missileTarget, bam);\n\tconst Armor* armor =  unit->getArmor();\n\tconst int size = armor->getSize() - 1;\n\tconst int numberOfParts = armor->getTotalSize();\n\tint maskOfPartsGoingUp = 0x0;\n\tint maskOfPartsHoleUp = 0x0;\n\tint maskOfPartsGoingDown = 0x0;\n\tint maskOfPartsFalling = 0x0;\n\tint maskOfPartsFlying = 0x0;\n\tint maskOfPartsGround = 0x0;\n\tint maskOfPartsClimb = 0x0;\n\tint maskArmor = size ? 0xF : 0x1;\n\n\tPosition offsets[4] =\n\t{\n\t\t{ 0, 0, 0 },\n\t\t{ 1, 0, 0 },\n\t\t{ 0, 1, 0 },\n\t\t{ 1, 1, 0 },\n\t};\n\tconst Tile* startTile[4] = { };\n\tconst Tile* aboveStart[4] = { };\n\tconst Tile* belowStart[4] = { };\n\tconst Tile* destinationTile[4] = { };\n\tconst Tile* aboveDestination[4] = { };\n\tconst Tile* belowDestination[4] = { };\n\n\t// init variables\n\tfor (int i = 0; i < numberOfParts; ++i)\n\t{\n\t\tconst Tile* st = _save->getTile(startPosition + offsets[i]);\n\t\tconst Tile* dt = _save->getTile(pos + offsets[i]);\n\t\tif (!st || !dt)\n\t\t{\n\t\t\treturn {{INVALID_MOVE_COST, 0}};\n\t\t}\n\t\tstartTile[i] = st;\n\t\taboveStart[i] = _save->getAboveTile(st);\n\t\tbelowStart[i] = _save->getBelowTile(st);\n\t\tdestinationTile[i] = dt;\n\t\taboveDestination[i] = _save->getAboveTile(dt);\n\t\tbelowDestination[i] = _save->getBelowTile(dt);\n\t}\n\n\t// check move up or down\n\tfor (int i = 0; i < numberOfParts; ++i)\n\t{\n\t\tconst int maskCurrentPart = 1 << i;\n\t\tconst bool checkClimbing = (i == 0) && (numberOfParts == 1) &&  movementType != MT_FLY;\n\n\t\tif (direction < DIR_UP && startTile[i]->getTerrainLevel() > - 16)\n\t\t{\n\t\t\t// check if we can go this way\n\t\t\tif (isBlockedDirection(unit, startTile[i], direction, bam, missileTarget))\n\t\t\t\treturn {{INVALID_MOVE_COST, 0}};\n\t\t\tif (startTile[i]->getTerrainLevel() - destinationTile[i]->getTerrainLevel() > 8)\n\t\t\t\treturn {{INVALID_MOVE_COST, 0}};\n\t\t}\n\n\t\t// if we are on a stairs try to go up a level\n\t\tif (direction < DIR_UP && startTile[i]->getTerrainLevel() <= -16 && aboveDestination[i] && !aboveDestination[i]->hasNoFloor(_save))\n\t\t{\n\t\t\tmaskOfPartsGoingUp |= maskCurrentPart;\n\t\t}\n\t\telse if (direction < DIR_UP && movementType != MT_FLY && belowDestination[i] && canFallDown(destinationTile[i]) && belowDestination[i]->getTerrainLevel() <= -12)\n\t\t{\n\t\t\tmaskOfPartsGoingDown |= maskCurrentPart;\n\t\t}\n\t\telse if (bam != BAM_MISSILE && movementType == MT_FLY)\n\t\t{\n\t\t\t// 2 or more voxels poking into this tile = no go\n\t\t\tBattleUnit* overlaping = destinationTile[i]->getOverlappingUnit(_save, TUO_IGNORE_SMALL);\n\t\t\tif (overlaping && overlaping != unit)\n\t\t\t{\n\t\t\t\treturn {{INVALID_MOVE_COST, 0}};\n\t\t\t}\n\t\t}\n\n\t\tif (aboveStart[i] && aboveStart[i]->hasNoFloor(_save))\n\t\t{\n\t\t\tmaskOfPartsHoleUp |= maskCurrentPart;\n\t\t}\n\t\t// check if we have floor, else fall down\n\t\tif (movementType != MT_FLY && canFallDown(startTile[i]))\n\t\t{\n\t\t\tif (!checkClimbing || (!startTile[i]->hasLadder() && !(direction < DIR_UP && belowStart[i] && belowStart[i]->hasLadder() && !canFallDown(destinationTile[i]))))\n\t\t\t{\n\t\t\t\tmaskOfPartsFalling |= maskCurrentPart;\n\t\t\t}\n\t\t}\n\t\tif (movementType != MT_FLY && checkClimbing && direction >= DIR_UP && startTile[i]->hasLadder())\n\t\t{\n\t\t\t//TODO: need check interaction with GravLift and other corner cases\n\t\t\tmaskOfPartsClimb |= maskCurrentPart;\n\t\t}\n\t\tif (movementType == MT_FLY && (canFallDown(startTile[i]) || canFallDown(destinationTile[i])))\n\t\t{\n\t\t\tmaskOfPartsFlying |= maskCurrentPart;\n\t\t}\n\t\tif (direction != DIR_DOWN && !canFallDown(destinationTile[i]))\n\t\t{\n\t\t\tmaskOfPartsGround |= maskCurrentPart;\n\t\t}\n\t}\n\n\tconst bool triedStairs = (maskOfPartsGoingUp != 0 && ((maskOfPartsGoingUp | maskOfPartsHoleUp) == maskArmor));\n\tconst bool triedStairsDown = (maskOfPartsGround == 0 && ((maskOfPartsGoingDown | maskOfPartsFalling) == maskArmor));\n\tconst bool fallingDown = (maskOfPartsFalling == maskArmor);\n\tconst bool flying =  (maskOfPartsFlying == maskArmor);\n\tconst bool climb = (maskOfPartsClimb == maskArmor) && (bam != BAM_MISSILE);\n\n\tif (movementType != MT_FLY && fallingDown)\n\t{\n\t\tif (direction != DIR_DOWN)\n\t\t{\n\t\t\treturn {{INVALID_MOVE_COST, 0}}; //cannot walk on air\n\t\t}\n\t}\n\n\tfor (int i = 0; i < numberOfParts; ++i)\n\t{\n\t\tif (triedStairs)\n\t\t{\n\t\t\tdestinationTile[i] = aboveDestination[i];\n\t\t}\n\t\telse if (direction != DIR_DOWN && triedStairsDown)\n\t\t{\n\t\t\tdestinationTile[i] = belowDestination[i];\n\t\t}\n\n\t\t// check if the destination tile can be walked over\n\t\tif (isBlocked(unit, destinationTile[i], O_FLOOR, bam, missileTarget) || isBlocked(unit, destinationTile[i], O_OBJECT, bam, missileTarget))\n\t\t{\n\t\t\treturn {{INVALID_MOVE_COST, 0}};\n\t\t}\n\t}\n\n\t// don't let tanks phase through doors.\n\tif (size)\n\t{\n\t\tconst Tile* t = destinationTile[3];\n\t\tif ((t->isDoor(O_NORTHWALL)) ||\n\t\t\t(t->isDoor(O_WESTWALL)))\n\t\t{\n\t\t\treturn {{INVALID_MOVE_COST, 0}};\n\t\t}\n\t}\n\n\t// pre-calculate fire penalty (to make it consistent for 2x2 units)\n\tint firePenaltyCost = 0;\n\tif (unit->getFaction() != FACTION_PLAYER &&\n\t\tunit->avoidsFire())\n\t{\n\t\tfor (int i = 0; i < numberOfParts; ++i)\n\t\t{\n\t\t\tif (destinationTile[i]->getFire() > 0)\n\t\t\t{\n\t\t\t\tfirePenaltyCost = FIRE_PREVIEW_MOVE_COST; // try to find a better path, but don't exclude this path entirely.\n\t\t\t}\n\t\t}\n\t}\n\n\n\t// calculate cost and some final checks\n\tint totalCost = 0;\n\n\tfor (int i = 0; i < numberOfParts; ++i)\n\t{\n\t\tint cost = 0;\n\t\tbool upperLevel = destinationTile[i]->getPosition().z > startTile[i]->getPosition().z;\n\t\tbool sameLevel = destinationTile[i]->getPosition().z == startTile[i]->getPosition().z;\n\t\tif (direction < DIR_UP && sameLevel)\n\t\t{\n\t\t\t// check if we can go this way\n\t\t\tif (isBlockedDirection(unit, startTile[i], direction, bam, missileTarget))\n\t\t\t\treturn {{INVALID_MOVE_COST, 0}};\n\t\t\tif (startTile[i]->getTerrainLevel() - destinationTile[i]->getTerrainLevel() > 8)\n\t\t\t\treturn {{INVALID_MOVE_COST, 0}};\n\t\t}\n\t\telse if (direction >= DIR_UP && !triedStairsDown)\n\t\t{\n\t\t\t// check if we can go up or down through gravlift or fly\n\t\t\tif (validateUpDown(unit, startTile[i]->getPosition(), direction, (bam == BAM_MISSILE)))\n\t\t\t{\n\t\t\t\tif (climb)\n\t\t\t\t{\n\t\t\t\t\tint minCost = INVALID_MOVE_COST;\n\t\t\t\t\tauto calcMin = [&](bool ladder, TilePart p)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (ladder)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tint value = startTile[i]->getTUCost(p, movementType);\n\t\t\t\t\t\t\tminCost = std::min(minCost, value ? value : DEFAULT_MOVE_FLY_COST);\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\tcalcMin(startTile[i]->hasLadderOnObject(), O_OBJECT);\n\t\t\t\t\tcalcMin(startTile[i]->hasLadderOnNorthWall(), O_NORTHWALL);\n\t\t\t\t\tcalcMin(startTile[i]->hasLadderOnWestWall(), O_WESTWALL);\n\n\t\t\t\t\tif (minCost >= INVALID_MOVE_COST)\n\t\t\t\t\t{\n\t\t\t\t\t\treturn {{INVALID_MOVE_COST, 0}};\n\t\t\t\t\t}\n\t\t\t\t\tcost = minCost;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tcost = DEFAULT_MOVE_FLY_COST; // vertical movement by flying suit or grav lift\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn {{INVALID_MOVE_COST, 0}};\n\t\t\t}\n\t\t}\n\t\tif (upperLevel)\n\t\t{\n\t\t\tstartTile[i] = _save->getAboveTile(startTile[i]);\n\n\t\t\tif (direction < DIR_UP)\n\t\t\t{\n\t\t\t\t// check if we can go this way\n\t\t\t\tif (isBlockedDirection(unit, startTile[i], direction, bam, missileTarget))\n\t\t\t\t\treturn {{INVALID_MOVE_COST, 0}};\n\t\t\t\tif (startTile[i]->getTerrainLevel() - destinationTile[i]->getTerrainLevel() > 8)\n\t\t\t\t\treturn {{INVALID_MOVE_COST, 0}};\n\t\t\t}\n\t\t}\n\n\t\tint wallCounter = 0;\n\t\tint wallTmp = 0;\n\t\tint wallcost = 0; // walking through rubble walls, but don't charge for walking diagonally through doors (which is impossible),\n\t\t\t\t\t\t// they're a special case unto themselves, if we can walk past them diagonally, it means we can go around,\n\t\t\t\t\t\t// as there is no wall blocking us.\n\t\tif ((direction == 0 || direction == 7 || direction == 1) && !startTile[i]->hasLadderOnNorthWall())\n\t\t{\n\t\t\twallTmp = startTile[i]->getTUCost(O_NORTHWALL, movementType);\n\t\t\tif (wallTmp > 0)\n\t\t\t{\n\t\t\t\twallcost += wallTmp;\n\t\t\t\twallCounter += 1;\n\t\t\t}\n\t\t}\n\t\tif (!triedStairsDown && (direction == 2 || direction == 1 || direction == 3) && !destinationTile[i]->hasLadderOnWestWall())\n\t\t{\n\t\t\twallTmp = destinationTile[i]->getTUCost(O_WESTWALL, movementType);\n\t\t\tif (wallTmp > 0)\n\t\t\t{\n\t\t\t\twallcost += wallTmp;\n\t\t\t\twallCounter += 1;\n\t\t\t}\n\t\t}\n\t\tif (!triedStairsDown && (direction == 4 || direction == 3 || direction == 5) && !destinationTile[i]->hasLadderOnNorthWall())\n\t\t{\n\t\t\twallTmp = destinationTile[i]->getTUCost(O_NORTHWALL, movementType);\n\t\t\tif (wallTmp > 0)\n\t\t\t{\n\t\t\t\twallcost += wallTmp;\n\t\t\t\twallCounter += 1;\n\t\t\t}\n\t\t}\n\t\tif ((direction == 6 || direction == 5 || direction == 7) && !startTile[i]->hasLadderOnWestWall())\n\t\t{\n\t\t\twallTmp = startTile[i]->getTUCost(O_WESTWALL, movementType);\n\t\t\tif (wallTmp > 0)\n\t\t\t{\n\t\t\t\twallcost += wallTmp;\n\t\t\t\twallCounter += 1;\n\t\t\t}\n\t\t}\n\n\t\t// \"average\" cost: https://openxcom.org/forum/index.php?topic=12589.0\n\t\tif (wallCounter > 0)\n\t\t{\n\t\t\twallcost /= wallCounter;\n\t\t}\n\n\t\t// for backward compatiblity (100 + 100 + 100 > 255) or for (255 + 10 > 255)\n\t\tif (wallcost >= INVALID_MOVE_COST)\n\t\t{\n\t\t\treturn {{INVALID_MOVE_COST, 0}};\n\t\t}\n\n\t\t// if we don't want to fall down and there is no floor, we can't know the TUs so it's default to 4\n\t\tif (direction < DIR_UP && !triedStairsDown && destinationTile[i]->hasNoFloor(0))\n\t\t{\n\t\t\tcost = DEFAULT_MOVE_COST;\n\t\t}\n\n\t\t// calculate the cost by adding floor walk cost and object walk cost\n\t\tif (direction < DIR_UP)\n\t\t{\n\t\t\tcost += destinationTile[i]->getTUCost(O_FLOOR, movementType);\n\t\t\tif (!triedStairsDown && !triedStairs && destinationTile[i]->getMapData(O_OBJECT) && !destinationTile[i]->hasLadderOnObject())\n\t\t\t{\n\t\t\t\tcost += destinationTile[i]->getTUCost(O_OBJECT, movementType);\n\t\t\t}\n\t\t\tif (cost == 0)\n\t\t\t{\n\t\t\t\t// some mods have broken tiles with 0 move cost, as it could be problematic for the engine, we override it to default cost.\n\t\t\t\tcost = DEFAULT_MOVE_COST;\n\t\t\t}\n\t\t\t// climbing up a level costs one extra\n\t\t\tif (upperLevel)\n\t\t\t{\n\t\t\t\tcost++;\n\t\t\t}\n\t\t}\n\n\t\t// diagonal walking (uneven directions) costs 50% more tu's\n\t\tif (direction < DIR_UP && direction & 1)\n\t\t{\n\t\t\tcost = (int)((double)cost * 1.5);\n\t\t}\n\n\t\tcost += wallcost;\n\n\t\t// TFTD thing: underwater tiles on fire or filled with smoke cost 2 TUs more for whatever reason.\n\t\tif (_save->getDepth() > 0 && (destinationTile[i]->getFire() > 0 || destinationTile[i]->getSmoke() > 0))\n\t\t{\n\t\t\tcost += 2;\n\t\t}\n\n\t\tif (missileTarget && destinationTile[i]->getUnit())\n\t\t{\n\t\t\tBattleUnit *unitHere = destinationTile[i]->getUnit();\n\t\t\tif (unitHere != missileTarget && !unitHere->isOut())\n\t\t\t{\n\t\t\t\tif (unitHere->getFaction() == unit->getFaction())\n\t\t\t\t{\n\t\t\t\t\treturn {{INVALID_MOVE_COST, 0}}; // consider any tile occupied by a friendly as being blocked\n\t\t\t\t}\n\t\t\t\telse if (unit->getUnitRules() && unitHere->getTurnsSinceSpottedByFaction(unit->getFaction()) <= unit->getUnitRules()->getIntelligence())\n\t\t\t\t{\n\t\t\t\t\treturn {{INVALID_MOVE_COST, 0}}; // consider any tile occupied by a known unit that isn't our target as being blocked\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Strafing costs +1 for forwards-ish or sidewards, propose +2 for backwards-ish directions\n\t\t// Maybe if flying then it makes no difference?\n\t\tif (_strafeMove && bam == BAM_STRAFE)\n\t\t{\n\t\t\tif (unit->getDirection() != direction)\n\t\t\t{\n\t\t\t\tcost += 1;\n\t\t\t}\n\t\t}\n\n\t\t// cap move cost to given limit\n\t\tcost = std::min(cost, +MAX_MOVE_COST);\n\n\t\ttotalCost += cost;\n\t}\n\n\t// because unit move up or down we adjust final position\n\tif (triedStairs)\n\t{\n\t\tpos.z++;\n\t}\n\telse if (direction != DIR_DOWN && triedStairsDown)\n\t{\n\t\tpos.z--;\n\t}\n\n\t// for bigger sized units, check the path between parts in an X shape at the end position\n\tif (size)\n\t{\n\t\ttotalCost /= numberOfParts;\n\t\tconst Tile *originTile = _save->getTile(pos + Position(1,1,0));\n\t\tconst Tile *finalTile = _save->getTile(pos);\n\t\tint tmpDirection = 7;\n\t\tif (isBlockedDirection(unit, originTile, tmpDirection, bam, missileTarget))\n\t\t\treturn {{INVALID_MOVE_COST, 0}};\n\t\tif (!triedStairsDown && abs(originTile->getTerrainLevel() - finalTile->getTerrainLevel()) > 10)\n\t\t\treturn {{INVALID_MOVE_COST, 0}};\n\t\toriginTile = _save->getTile(pos + Position(1,0,0));\n\t\tfinalTile = _save->getTile(pos + Position(0,1,0));\n\t\ttmpDirection = 5;\n\t\tif (isBlockedDirection(unit, originTile, tmpDirection, bam, missileTarget))\n\t\t\treturn {{INVALID_MOVE_COST, 0}};\n\t\tif (!triedStairsDown && abs(originTile->getTerrainLevel() - finalTile->getTerrainLevel()) > 10)\n\t\t\treturn {{INVALID_MOVE_COST, 0}};\n\t}\n\n\n\tif (bam == BAM_MISSILE)\n\t{\n\t\treturn { { }, { }, pos };\n\t}\n\n\tif (direction == DIR_DOWN && fallingDown)\n\t{\n\t\treturn { { }, { firePenaltyCost, 0 }, pos };\n\t}\n\n\tconst int costDiv = 100 * 100 * 100;\n\tArmorMoveCost cost = { totalCost, totalCost };\n\n\tcost *= unit->getMoveCostBase();\n\n\tif (climb)\n\t{\n\t\tcost *= unit->getMoveCostBaseClimb();\n\t}\n\telse if (flying)\n\t{\n\t\tcost *= unit->getMoveCostBaseFly();\n\t}\n\telse\n\t{\n\t\tcost *= unit->getMoveCostBaseNormal();\n\t}\n\n\tif (direction >= Pathfinding::DIR_UP)\n\t{\n\t\tif (climb)\n\t\t{\n\t\t\tif (direction == Pathfinding::DIR_UP)\n\t\t\t{\n\t\t\t\tcost *= armor->getMoveCostClimbUp();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tcost *= armor->getMoveCostClimbDown();\n\t\t\t}\n\t\t}\n\t\telse if (flying)\n\t\t{\n\t\t\tif (direction == Pathfinding::DIR_UP)\n\t\t\t{\n\t\t\t\tcost *= armor->getMoveCostFlyUp();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tcost *= armor->getMoveCostFlyDown();\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t//unit use GravLift\n\t\t\tcost *= armor->getMoveCostGravLift();\n\t\t}\n\t}\n\telse if (bam == BAM_NORMAL)\n\t{\n\t\tif (flying)\n\t\t{\n\t\t\tcost *= armor->getMoveCostFlyWalk();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tcost *= armor->getMoveCostWalk();\n\t\t}\n\t}\n\telse if (bam == BAM_RUN)\n\t{\n\t\tif (flying)\n\t\t{\n\t\t\tcost *= armor->getMoveCostFlyRun();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tcost *= armor->getMoveCostRun();\n\t\t}\n\t}\n\telse if (bam == BAM_STRAFE)\n\t{\n\t\tif (flying)\n\t\t{\n\t\t\tcost *= armor->getMoveCostFlyStrafe();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tcost *= armor->getMoveCostStrafe();\n\t\t}\n\t}\n\telse if (bam == BAM_SNEAK)\n\t{\n\t\t//no flight\n\t\tcost *= armor->getMoveCostSneak();\n\t}\n\telse\n\t{\n\t\tassert(false && \"Unreachable code in pathfinding cost\");\n\t}\n\n\tconst int timeCost = Mod::EXTENDED_MOVEMENT_COST_ROUNDING == 0 ? (cost.TimePercent) / costDiv :\n\t\t                 Mod::EXTENDED_MOVEMENT_COST_ROUNDING == 1 ? (cost.TimePercent + (costDiv / 2)) / costDiv :\n\t\t                                                             (cost.TimePercent - 1 + (costDiv / 2)) / costDiv;\n\n\tconst int energyCost = Mod::EXTENDED_MOVEMENT_COST_ROUNDING == 0 ? (cost.EnergyPercent) / costDiv :\n\t\t                   Mod::EXTENDED_MOVEMENT_COST_ROUNDING == 1 ? (cost.EnergyPercent + (costDiv / 2)) / costDiv :\n\t\t                                                               (cost.EnergyPercent - 1 + (costDiv / 2)) / costDiv;\n\n\treturn { { Clamp(timeCost, 1, INVALID_MOVE_COST - 1), Clamp(energyCost, 0, INVALID_MOVE_COST) }, { firePenaltyCost, 0 }, pos };\n}\n\n/**\n * Checks whether a path is ready and gives the first direction.\n * @return Direction where the unit needs to go next, -1 if it's the end of the path.\n */\nint Pathfinding::getStartDirection() const\n{\n\tif (_path.empty()) return -1;\n\treturn _path.back();\n}\n\n/**\n * Dequeues the next path direction. Ie returns the direction and removes it from queue.\n * @return Direction where the unit needs to go next, -1 if it's the end of the path.\n */\nint Pathfinding::dequeuePath()\n{\n\tif (_path.empty()) return -1;\n\tint last_element = _path.back();\n\t_path.pop_back();\n\treturn last_element;\n}\n\n/**\n * Aborts the current path. Clears the path vector.\n */\nvoid Pathfinding::abortPath()\n{\n\t_totalTUCost = {};\n\t_path.clear();\n}\n\n/**\n * Gets movement type of unit or movement of missile.\n * @param unit Unit we check path for.\n * @param missileTarget Target of missile in case of `BAM_MISSILE\n * @return `MT_FLY` if we have `missileTarget` other wise `unit` move type.\n */\nMovementType Pathfinding::getMovementType(const BattleUnit *unit, const BattleUnit *missileTarget, BattleActionMove bam) const\n{\n\tif (missileTarget)\n\t{\n\t\treturn MT_FLY;\n\t}\n\telse\n\t{\n\t\tif (bam == BAM_SNEAK)\n\t\t{\n\t\t\treturn MT_WALK;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn unit->getMovementType();\n\t\t}\n\t}\n}\n\n/**\n * Determines whether a certain part of a tile blocks movement.\n * @param tile Specified tile, can be a null pointer.\n * @param part Part of the tile.\n * @param missileTarget Target for a missile.\n * @return True if the movement is blocked.\n */\nbool Pathfinding::isBlocked(const BattleUnit *unit, const Tile *tile, const int part, BattleActionMove bam, const BattleUnit *missileTarget, int bigWallExclusion) const\n{\n\tif (tile == 0) return true; // probably outside the map here\n\n\tMovementType movementType = getMovementType(unit, missileTarget, bam);\n\n\tif (part == O_BIGWALL)\n\t{\n\t\tif (tile->getMapData(O_OBJECT) &&\n\t\t\ttile->getMapData(O_OBJECT)->getBigWall() != 0 &&\n\t\t\ttile->getMapData(O_OBJECT)->getBigWall() <= BIGWALLNWSE &&\n\t\t\ttile->getMapData(O_OBJECT)->getBigWall() != bigWallExclusion)\n\t\t\treturn true; // blocking part\n\t\telse\n\t\t\treturn false;\n\t}\n\tif (part == O_WESTWALL)\n\t{\n\t\tif (tile->getMapData(O_OBJECT) &&\n\t\t\t(tile->getMapData(O_OBJECT)->getBigWall() == BIGWALLWEST ||\n\t\t\ttile->getMapData(O_OBJECT)->getBigWall() == BIGWALLWESTANDNORTH))\n\t\t\treturn true; // blocking part\n\t\tTile *tileWest = _save->getTile(tile->getPosition() + Position(-1, 0, 0));\n\t\tif (!tileWest) return true;\t// do not look outside of map\n\t\tif (tileWest->getMapData(O_OBJECT) &&\n\t\t\t(tileWest->getMapData(O_OBJECT)->getBigWall() == BIGWALLEAST ||\n\t\t\ttileWest->getMapData(O_OBJECT)->getBigWall() == BIGWALLEASTANDSOUTH))\n\t\t\treturn true; // blocking part\n\t}\n\tif (part == O_NORTHWALL)\n\t{\n\t\tif (tile->getMapData(O_OBJECT) &&\n\t\t\t(tile->getMapData(O_OBJECT)->getBigWall() == BIGWALLNORTH ||\n\t\t\t tile->getMapData(O_OBJECT)->getBigWall() == BIGWALLWESTANDNORTH))\n\t\t\treturn true; // blocking part\n\t\tTile *tileNorth = _save->getTile(tile->getPosition() + Position(0, -1, 0));\n\t\tif (!tileNorth)\n\t\t\treturn true; // do not look outside of map\n\t\tif (tileNorth->getMapData(O_OBJECT) &&\n\t\t\t(tileNorth->getMapData(O_OBJECT)->getBigWall() == BIGWALLSOUTH ||\n\t\t\t tileNorth->getMapData(O_OBJECT)->getBigWall() == BIGWALLEASTANDSOUTH))\n\t\t\treturn true; // blocking part\n\t}\n\tif (part == O_FLOOR)\n\t{\n\t\tif (tile->getUnit())\n\t\t{\n\t\t\tBattleUnit *u = tile->getUnit();\n\t\t\tif (u == unit || u == missileTarget || u->isOut())\n\t\t\t\treturn false;\n\t\t\tif (unit)\n\t\t\t{\n\t\t\t\tif (unit->getFaction() == FACTION_PLAYER && u->getVisible())\n\t\t\t\t\treturn true; // player know all visible units\n\t\t\t\tif (unit->getFaction() == u->getFaction())\n\t\t\t\t\treturn true;\n\t\t\t\tif (unit->getFaction() == FACTION_HOSTILE &&\n\t\t\t\t\tstd::find(unit->getUnitsSpottedThisTurn().begin(), unit->getUnitsSpottedThisTurn().end(), u) != unit->getUnitsSpottedThisTurn().end())\n\t\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\telse if (tile->hasNoFloor(0) && movementType != MT_FLY) // this whole section is devoted to making large units not take part in any kind of falling behaviour\n\t\t{\n\t\t\tPosition pos = tile->getPosition();\n\t\t\twhile (pos.z >= 0)\n\t\t\t{\n\t\t\t\tTile *t = _save->getTile(pos);\n\t\t\t\tBattleUnit *u = t->getUnit();\n\n\t\t\t\tif (u != 0 && u != unit)\n\t\t\t\t{\n\t\t\t\t\t// don't let large units fall on other units\n\t\t\t\t\tif (unit && unit->isBigUnit())\n\t\t\t\t\t{\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t\t// don't let any units fall on large units\n\t\t\t\t\tif (u != unit && u != missileTarget && !u->isOut() && u->isBigUnit())\n\t\t\t\t\t{\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// not gonna fall any further, so we can stop checking.\n\t\t\t\tif (!t->hasNoFloor(0))\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tpos.z--;\n\t\t\t}\n\t\t}\n\t}\n\t// missiles can't pathfind through closed doors.\n\t{\n\t\tTilePart tp = (TilePart)part;\n\t\tif (missileTarget != 0 && tile->getMapData(tp) &&\n\t\t\t(tile->isDoor(tp) ||\n\t\t\t(tile->isUfoDoor(tp) &&\n\t\t\t!tile->isUfoDoorOpen(tp))))\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t}\n\tif (tile->getTUCost(part, movementType) == Pathfinding::INVALID_MOVE_COST) return true; // blocking part\n\treturn false;\n}\n\n/**\n * Determines whether going from one tile to another blocks movement.\n * @param unit Unit that move.\n * @param startTile The tile to start from.\n * @param direction The direction we are facing.\n * @param bam Move type.\n * @param missileTarget Target for a missile.\n * @return True if the movement is blocked.\n */\nbool Pathfinding::isBlockedDirection(const BattleUnit *unit, const Tile *startTile, const int direction, BattleActionMove bam, const BattleUnit *missileTarget) const\n{\n\n\t// check if the difference in height between start and destination is not too high\n\t// so we can not jump to the highest part of the stairs from the floor\n\t// stairs terrainlevel goes typically -8 -16 (2 steps) or -4 -12 -20 (3 steps)\n\t// this \"maximum jump height\" is therefore set to 8\n\n\tconst Position currentPosition = startTile->getPosition();\n\tstatic const Position oneTileNorth = Position(0, -1, 0);\n\tstatic const Position oneTileEast = Position(1, 0, 0);\n\tstatic const Position oneTileSouth = Position(0, 1, 0);\n\tstatic const Position oneTileWest = Position(-1, 0, 0);\n\n\tswitch(direction)\n\t{\n\tcase 0:\t// north\n\t\tif (isBlocked(unit, startTile, O_NORTHWALL, bam, missileTarget)) return true;\n\t\tbreak;\n\tcase 1: // north-east\n\t\tif (isBlocked(unit, startTile,O_NORTHWALL, bam, missileTarget)) return true;\n\t\tif (isBlocked(unit, _save->getTile(currentPosition + oneTileNorth + oneTileEast),O_WESTWALL, bam, missileTarget)) return true;\n\t\tif (isBlocked(unit, _save->getTile(currentPosition + oneTileEast),O_WESTWALL, bam, missileTarget)) return true;\n\t\tif (isBlocked(unit, _save->getTile(currentPosition + oneTileEast),O_NORTHWALL, bam, missileTarget)) return true;\n\t\tif (isBlocked(unit, _save->getTile(currentPosition + oneTileEast), O_BIGWALL, bam, missileTarget, BIGWALLNESW)) return true;\n\t\tif (isBlocked(unit, _save->getTile(currentPosition + oneTileNorth), O_BIGWALL, bam, missileTarget, BIGWALLNESW)) return true;\n\t\tbreak;\n\tcase 2: // east\n\t\tif (isBlocked(unit, _save->getTile(currentPosition + oneTileEast), O_WESTWALL, bam, missileTarget)) return true;\n\t\tbreak;\n\tcase 3: // south-east\n\t\tif (isBlocked(unit, _save->getTile(currentPosition + oneTileEast), O_WESTWALL, bam, missileTarget)) return true;\n\t\tif (isBlocked(unit, _save->getTile(currentPosition + oneTileSouth), O_NORTHWALL, bam, missileTarget)) return true;\n\t\tif (isBlocked(unit, _save->getTile(currentPosition + oneTileSouth + oneTileEast), O_NORTHWALL, bam, missileTarget)) return true;\n\t\tif (isBlocked(unit, _save->getTile(currentPosition + oneTileSouth + oneTileEast), O_WESTWALL, bam, missileTarget)) return true;\n\t\tif (isBlocked(unit, _save->getTile(currentPosition + oneTileEast), O_BIGWALL, bam, missileTarget, BIGWALLNWSE)) return true;\n\t\tif (isBlocked(unit, _save->getTile(currentPosition + oneTileSouth), O_BIGWALL, bam, missileTarget, BIGWALLNWSE)) return true;\n\t\tbreak;\n\tcase 4: // south\n\t\tif (isBlocked(unit, _save->getTile(currentPosition + oneTileSouth), O_NORTHWALL, bam, missileTarget)) return true;\n\t\tbreak;\n\tcase 5: // south-west\n\t\tif (isBlocked(unit, startTile, O_WESTWALL, bam, missileTarget)) return true;\n\t\tif (isBlocked(unit, _save->getTile(currentPosition + oneTileSouth), O_WESTWALL, bam, missileTarget)) return true;\n\t\tif (isBlocked(unit, _save->getTile(currentPosition + oneTileSouth), O_NORTHWALL, bam, missileTarget)) return true;\n\t\tif (isBlocked(unit, _save->getTile(currentPosition + oneTileSouth), O_BIGWALL, bam, missileTarget, BIGWALLNESW)) return true;\n\t\tif (isBlocked(unit, _save->getTile(currentPosition + oneTileWest), O_BIGWALL, bam, missileTarget, BIGWALLNESW)) return true;\n\t\tif (isBlocked(unit, _save->getTile(currentPosition + oneTileSouth + oneTileWest), O_NORTHWALL, bam, missileTarget)) return true;\n\t\tbreak;\n\tcase 6: // west\n\t\tif (isBlocked(unit, startTile, O_WESTWALL, bam, missileTarget)) return true;\n\t\tbreak;\n\tcase 7: // north-west\n\t\tif (isBlocked(unit, startTile, O_WESTWALL, bam, missileTarget)) return true;\n\t\tif (isBlocked(unit, startTile, O_NORTHWALL, bam, missileTarget)) return true;\n\t\tif (isBlocked(unit, _save->getTile(currentPosition + oneTileWest), O_NORTHWALL, bam, missileTarget)) return true;\n\t\tif (isBlocked(unit, _save->getTile(currentPosition + oneTileNorth), O_WESTWALL, bam, missileTarget)) return true;\n\t\tif (isBlocked(unit, _save->getTile(currentPosition + oneTileNorth), O_BIGWALL, bam, missileTarget, BIGWALLNWSE)) return true;\n\t\tif (isBlocked(unit, _save->getTile(currentPosition + oneTileWest), O_BIGWALL, bam, missileTarget, BIGWALLNWSE)) return true;\n\t\tbreak;\n\t}\n\n\treturn false;\n}\n\n/**\n * Determines whether going from one tile to another blocks movement.\n * @param unit Unit that move.\n * @param startTile The tile to start from.\n * @param direction The direction we are facing.\n */\nbool Pathfinding::isBlockedDirection(const BattleUnit *unit, Tile *startTile, const int direction) const\n{\n\treturn isBlockedDirection(unit, startTile, direction, BAM_NORMAL, nullptr);\n}\n\n/**\n * Determines whether a unit can fall down from this tile.\n * We can fall down here, if the tile does not exist, the tile has no floor\n * the current position is higher than 0, if there is no unit standing below us.\n * @param here The current tile.\n * @return True if a unit can fall down.\n */\nbool Pathfinding::canFallDown(const Tile *here) const\n{\n\tif (here->getPosition().z == 0)\n\t\treturn false;\n\n\treturn here->hasNoFloor(_save);\n}\n\n/**\n * Determines whether a unit can fall down from this tile.\n * We can fall down here, if the tile does not exist, the tile has no floor\n * the current position is higher than 0, if there is no unit standing below us.\n * @param here The current tile.\n * @param size The size of the unit.\n * @return True if a unit can fall down.\n */\nbool Pathfinding::canFallDown(const Tile *here, int size) const\n{\n\tfor (int x = 0; x != size; ++x)\n\t{\n\t\tfor (int y = 0; y != size; ++y)\n\t\t{\n\t\t\tPosition checkPos = here->getPosition() + Position(x,y,0);\n\t\t\tTile *checkTile = _save->getTile(checkPos);\n\t\t\tif (!canFallDown(checkTile))\n\t\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n/**\n * Determines whether the unit is going up a stairs.\n * @param startPosition The position to start from.\n * @param endPosition The position we wanna reach.\n * @return True if the unit is going up a stairs.\n */\nbool Pathfinding::isOnStairs(Position startPosition, Position endPosition) const\n{\n\t//condition 1 : endposition has to the south a terrainlevel -16 object (upper part of the stairs)\n\tif (_save->getTile(endPosition + Position(0, 1, 0)) && _save->getTile(endPosition + Position(0, 1, 0))->getTerrainLevel() == -16)\n\t{\n\t\t// condition 2 : one position further to the south there has to be a terrainlevel -8 object (lower part of the stairs)\n\t\tif (_save->getTile(endPosition + Position(0, 2, 0)) && _save->getTile(endPosition + Position(0, 2, 0))->getTerrainLevel() != -8)\n\t\t{\n\t\t\treturn false;\n\t\t}\n\n\t\t// condition 3 : the start position has to be on either of the 3 tiles to the south of the endposition\n\t\tif (startPosition == endPosition + Position(0, 1, 0) || startPosition == endPosition + Position(0, 2, 0) || startPosition == endPosition + Position(0, 3, 0))\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t}\n\n\t// same for the east-west oriented stairs.\n\tif (_save->getTile(endPosition + Position(1, 0, 0)) && _save->getTile(endPosition + Position(1, 0, 0))->getTerrainLevel() == -16)\n\t{\n\t\tif (_save->getTile(endPosition + Position(2, 0, 0)) && _save->getTile(endPosition + Position(2, 0, 0))->getTerrainLevel() != -8)\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t\tif (startPosition == endPosition + Position(1, 0, 0) || startPosition == endPosition + Position(2, 0, 0) || startPosition == endPosition + Position(3, 0, 0))\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t}\n\n\t//TFTD stairs 1 : endposition has to the south a terrainlevel -18 object (upper part of the stairs)\n\tif (_save->getTile(endPosition + Position(0, 1, 0)) && _save->getTile(endPosition + Position(0, 1, 0))->getTerrainLevel() == -18)\n\t{\n\t\t// condition 2 : one position further to the south there has to be a terrainlevel -8 object (lower part of the stairs)\n\t\tif (_save->getTile(endPosition + Position(0, 2, 0)) && _save->getTile(endPosition + Position(0, 2, 0))->getTerrainLevel() != -12)\n\t\t{\n\t\t\treturn false;\n\t\t}\n\n\t\t// condition 3 : the start position has to be on either of the 3 tiles to the south of the endposition\n\t\tif (startPosition == endPosition + Position(0, 1, 0) || startPosition == endPosition + Position(0, 2, 0) || startPosition == endPosition + Position(0, 3, 0))\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t}\n\n\t// same for the east-west oriented stairs.\n\tif (_save->getTile(endPosition + Position(1, 0, 0)) && _save->getTile(endPosition + Position(1, 0, 0))->getTerrainLevel() == -18)\n\t{\n\t\tif (_save->getTile(endPosition + Position(2, 0, 0)) && _save->getTile(endPosition + Position(2, 0, 0))->getTerrainLevel() != -12)\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t\tif (startPosition == endPosition + Position(1, 0, 0) || startPosition == endPosition + Position(2, 0, 0) || startPosition == endPosition + Position(3, 0, 0))\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Checks, for the up/down button, if the movement is valid. Either there is a grav lift or the unit can fly and there are no obstructions.\n * @param bu Pointer to unit.\n * @param startPosition Unit starting position.\n * @param direction Up or Down\n * @return bool Whether it's valid.\n */\nbool Pathfinding::validateUpDown(const BattleUnit *bu, const Position& startPosition, const int direction, bool missile) const\n{\n\tPosition endPosition;\n\tdirectionToVector(direction, &endPosition);\n\tendPosition += startPosition;\n\tTile *startTile = _save->getTile(startPosition);\n\tTile *destinationTile = _save->getTile(endPosition);\n\n\tif (!destinationTile)\n\t{\n\t\treturn false;\n\t}\n\n\tif (startTile->hasGravLiftFloor() && destinationTile->hasGravLiftFloor())\n\t{\n\t\tif (missile)\n\t\t{\n\t\t\tif (direction == DIR_UP)\n\t\t\t{\n\t\t\t\tif (destinationTile->getMapData(O_FLOOR)->getLoftID(0) != 0)\n\t\t\t\t\treturn false;\n\t\t\t}\n\t\t\telse if (startTile->getMapData(O_FLOOR)->getLoftID(0) != 0)\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\telse\n\t{\n\t\tif (bu->getMovementType() == MT_FLY || startTile->hasLadder())\n\t\t{\n\t\t\tif ((direction == DIR_UP && destinationTile->hasNoFloor(_save)) // flying up only possible when there is no roof\n\t\t\t\t|| (direction == DIR_DOWN && startTile->hasNoFloor(_save)) // falling down only possible when there is no floor\n\t\t\t\t)\n\t\t\t{\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn false;\n}\n\n/**\n * Marks tiles for the path preview.\n * @param bRemove Remove preview?\n * @return True, if a path is previewed.\n */\nbool Pathfinding::previewPath(bool bRemove)\n{\n\tif (_path.empty())\n\t\treturn false;\n\n\tif (!bRemove && _pathPreviewed)\n\t\treturn false;\n\n\t_pathPreviewed = !bRemove;\n\n\tif (bRemove)\n\t{\n\t\t// use old values, player could unpress buttons.\n\t}\n\telse\n\t{\n\t\t_ctrlUsed = Options::strafe && _save->isCtrlPressed(true);\n\t\t_altUsed = Options::strafe && _save->isAltPressed(true);\n\t}\n\n\trefreshPath();\n\n\treturn true;\n}\n\n/**\n * Unmarks the tiles used for the path preview.\n * @return True, if the previewed path was removed.\n */\nbool Pathfinding::removePreview()\n{\n\tif (!_pathPreviewed)\n\t\treturn false;\n\tpreviewPath(true);\n\treturn true;\n}\n\n/**\n * Refresh the path preview.\n */\nvoid Pathfinding::refreshPath()\n{\n\tPosition pos = _unit->getPosition();\n\n\tint tus = _unit->getTimeUnits();\n\tif (_unit->isKneeled())\n\t{\n\t\ttus -= _unit->getKneelUpCost();\n\t}\n\tint energy = _unit->getEnergy();\n\tint size = _unit->getArmor()->getSize() - 1;\n\tint total = _unit->isKneeled() ? _unit->getKneelUpCost() : 0;\n\tif (_unit->getArmor()->getTurnBeforeFirstStep())\n\t{\n\t\tint dir = getStartDirection();\n\t\tif (dir != -1 && dir != _unit->getDirection())\n\t\t{\n\t\t\tint turnCost = std::abs(_unit->getDirection() - dir);\n\t\t\tif (turnCost > 4)\n\t\t\t{\n\t\t\t\tturnCost = 8 - turnCost;\n\t\t\t}\n\t\t\tturnCost = turnCost * _unit->getTurnCost();\n\n\t\t\ttus -= turnCost;\n\t\t\ttotal += turnCost;\n\t\t}\n\t}\n\tbool switchBack = false;\n\tif (_save->getBattleGame()->getReservedAction() == BA_NONE)\n\t{\n\t\tswitchBack = true;\n\t\t_save->getBattleGame()->setTUReserved(BA_AUTOSHOT);\n\t}\n\n\tconst bool running = _ctrlUsed && _unit->getArmor()->allowsRunning(_unit->isSmallUnit()) && (_path.size() > 1 || _altUsed);\n\tconst bool strafing = !running && _ctrlUsed && _unit->getArmor()->allowsStrafing(_unit->isSmallUnit()) && _path.size() == 1;\n\tconst bool sneaking = !running && _altUsed && _unit->getArmor()->allowsSneaking(_unit->isSmallUnit());\n\n\tconst BattleActionMove bam = strafing ? BAM_STRAFE : running ? BAM_RUN : sneaking ? BAM_SNEAK : BAM_NORMAL;\n\tconst MovementType movementType = getMovementType(_unit, nullptr, bam); //preview always for unit not missiles\n\tfor (std::vector<int>::reverse_iterator i = _path.rbegin(); i != _path.rend(); ++i)\n\t{\n\t\tint dir = *i;\n\t\tPathfindingStep r = getTUCost(pos, dir, _unit, 0, bam);\n\t\tpos = r.pos;\n\t\tenergy -= r.cost.energy;\n\t\ttus -= r.cost.time;\n\t\ttotal += r.cost.time;\n\t\tbool reserve = _save->getBattleGame()->checkReservedTU(_unit, total, _unit->getEnergy() - energy, true);\n\t\tfor (int x = size; x >= 0; x--)\n\t\t{\n\t\t\tfor (int y = size; y >= 0; y--)\n\t\t\t{\n\t\t\t\tTile *tile = _save->getTile(pos + Position(x,y,0));\n\t\t\t\tTile *tileAbove = _save->getTile(pos + Position(x,y,1));\n\t\t\t\tif (_pathPreviewed)\n\t\t\t\t{\n\t\t\t\t\tif (i == _path.rend() - 1)\n\t\t\t\t\t{\n\t\t\t\t\t\ttile->setPreview(10);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tint nextDir = *(i + 1);\n\t\t\t\t\t\ttile->setPreview(nextDir);\n\t\t\t\t\t}\n\t\t\t\t\tif ((x && y) || size == 0)\n\t\t\t\t\t{\n\t\t\t\t\t\ttile->setTUMarker(std::max(0,tus));\n\t\t\t\t\t\ttile->setEnergyMarker(std::max(0,energy));\n\t\t\t\t\t}\n\t\t\t\t\tif (tileAbove && tileAbove->getPreview() == 0 && r.cost.time == 0 && movementType != MT_FLY) //unit fell down, retroactively make the tile above's direction marker to DOWN\n\t\t\t\t\t{\n\t\t\t\t\t\ttileAbove->setPreview(DIR_DOWN);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\ttile->setPreview(-1);\n\t\t\t\t\ttile->setTUMarker(-1);\n\t\t\t\t\ttile->setEnergyMarker(-1);\n\t\t\t\t}\n\t\t\t\ttile->setMarkerColor(!_pathPreviewed ? 0 : ((tus>=0 && energy>=0)?(reserve?Pathfinding::green : Pathfinding::yellow) : Pathfinding::red));\n\t\t\t}\n\t\t}\n\t}\n\tif (switchBack)\n\t{\n\t\t_save->getBattleGame()->setTUReserved(BA_NONE);\n\t}\n}\n\n/**\n * Calculates the shortest path using Bresenham path algorithm.\n * @note This only works in the X/Y plane.\n * @param origin The position to start from.\n * @param target The position we want to reach.\n * @param missileTarget Target of the path.\n * @param sneak Is the unit sneaking?\n * @param maxTUCost Maximum time units the path can cost.\n * @return True if a path exists, false otherwise.\n */\nbool Pathfinding::bresenhamPath(Position origin, Position target, BattleActionMove bam, const BattleUnit *missileTarget, bool sneak, int maxTUCost)\n{\n\tint xd[8] = {0, 1, 1, 1, 0, -1, -1, -1};\n\tint yd[8] = {-1, -1, 0, 1, 1, 1, 0, -1};\n\n\tint x, x0, x1, delta_x, step_x;\n\tint y, y0, y1, delta_y, step_y;\n\tint z, z0, z1, delta_z, step_z;\n\tint swap_xy, swap_xz;\n\tint drift_xy, drift_xz;\n\tint cx, cy, cz;\n\tPosition lastPoint(origin);\n\tint dir;\n\tint lastTUCost = -1;\n\tPosition nextPoint;\n\t_totalTUCost = {};\n\n\t//start and end points\n\tx0 = origin.x;\t x1 = target.x;\n\ty0 = origin.y;\t y1 = target.y;\n\tz0 = origin.z;\t z1 = target.z;\n\n\t//'steep' xy Line, make longest delta x plane\n\tswap_xy = abs(y1 - y0) > abs(x1 - x0);\n\tif (swap_xy)\n\t{\n\t\tstd::swap(x0, y0);\n\t\tstd::swap(x1, y1);\n\t}\n\n\t//do same for xz\n\tswap_xz = abs(z1 - z0) > abs(x1 - x0);\n\tif (swap_xz)\n\t{\n\t\tstd::swap(x0, z0);\n\t\tstd::swap(x1, z1);\n\t}\n\n\t//delta is Length in each plane\n\tdelta_x = abs(x1 - x0);\n\tdelta_y = abs(y1 - y0);\n\tdelta_z = abs(z1 - z0);\n\n\t//drift controls when to step in 'shallow' planes\n\t//starting value keeps Line centred\n\tdrift_xy  = (delta_x / 2);\n\tdrift_xz  = (delta_x / 2);\n\n\t//direction of line\n\tstep_x = 1;  if (x0 > x1) {  step_x = -1; }\n\tstep_y = 1;  if (y0 > y1) {  step_y = -1; }\n\tstep_z = 1;  if (z0 > z1) {  step_z = -1; }\n\n\t//starting point\n\ty = y0;\n\tz = z0;\n\n\t//step through longest delta (which we have swapped to x)\n\tfor (x = x0; x != (x1+step_x); x += step_x)\n\t{\n\t\t//copy position\n\t\tcx = x;\tcy = y;\tcz = z;\n\n\t\t//unswap (in reverse)\n\t\tif (swap_xz) std::swap(cx, cz);\n\t\tif (swap_xy) std::swap(cx, cy);\n\n\t\tif (x != x0 || y != y0 || z != z0)\n\t\t{\n\t\t\tPosition realNextPoint = Position(cx, cy, cz);\n\t\t\t// get direction\n\t\t\tfor (dir = 0; dir < 8; ++dir)\n\t\t\t{\n\t\t\t\tif (xd[dir] == cx-lastPoint.x && yd[dir] == cy-lastPoint.y) break;\n\t\t\t}\n\t\t\tif (dir == 8)\n\t\t\t{\n\t\t\t\tif (cz-lastPoint.z > 0)\n\t\t\t\t{\n\t\t\t\t\tdir = DIR_UP;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tdir = DIR_DOWN;\n\t\t\t\t}\n\t\t\t}\n\t\t\tPathfindingStep r = getTUCost(lastPoint, dir, _unit, missileTarget, bam);\n\t\t\tnextPoint = r.pos;\n\t\t\tint tuCost = r.cost.time + r.penalty.time;\n\n\t\t\tif (sneak && _save->getTile(nextPoint)->getVisible()) return false;\n\n\t\t\t// delete the following\n\t\t\tbool isDiagonal = (dir&1);\n\t\t\tint lastTUCostDiagonal = lastTUCost + lastTUCost / 2;\n\t\t\tint tuCostDiagonal = tuCost + tuCost / 2;\n\t\t\tif (nextPoint == realNextPoint && r.cost.time != INVALID_MOVE_COST && (tuCost == lastTUCost || (isDiagonal && tuCost == lastTUCostDiagonal) || (!isDiagonal && tuCostDiagonal == lastTUCost) || lastTUCost == -1)\n\t\t\t\t&& !isBlockedDirection(_unit, _save->getTile(lastPoint), dir, bam, missileTarget))\n\t\t\t{\n\t\t\t\t_path.push_back(dir);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (missileTarget == 0 && r.cost.time != INVALID_MOVE_COST)\n\t\t\t{\n\t\t\t\tlastTUCost = tuCost;\n\t\t\t\t_totalTUCost = _totalTUCost + r.cost + r.penalty;\n\t\t\t}\n\t\t\tlastPoint = Position(cx, cy, cz);\n\t\t}\n\t\t//update progress in other planes\n\t\tdrift_xy = drift_xy - delta_y;\n\t\tdrift_xz = drift_xz - delta_z;\n\n\t\t//step in y plane\n\t\tif (drift_xy < 0)\n\t\t{\n\t\t\ty = y + step_y;\n\t\t\tdrift_xy = drift_xy + delta_x;\n\t\t}\n\n\t\t//same in z\n\t\tif (drift_xz < 0)\n\t\t{\n\t\t\tz = z + step_z;\n\t\t\tdrift_xz = drift_xz + delta_x;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n/**\n * Locates all tiles reachable to @a *unit with a TU cost no more than @a tuMax.\n * Uses Dijkstra's algorithm.\n * @param unit Pointer to the unit.\n * @param tuMax The maximum cost of the path to each tile.\n * @return An array of reachable tiles, sorted in ascending order of cost. The first tile is the start location.\n */\nstd::vector<int> Pathfinding::findReachable(const BattleUnit *unit, const BattleActionCost &cost)\n{\n\tconst Position start = unit->getPosition();\n\tint tuMax = unit->getTimeUnits() - cost.Time;\n\tint energyMax = unit->getEnergy() - cost.Energy;\n\n\tPathfindingCost costMax = { tuMax, energyMax };\n\n\tfor (auto& pn : _nodes)\n\t{\n\t\tpn.reset();\n\t}\n\tPathfindingNode *startNode = getNode(start);\n\tstartNode->connect({}, 0, 0);\n\tPathfindingOpenSet unvisited;\n\tunvisited.push(startNode);\n\tstd::vector<PathfindingNode*> reachable;\n\twhile (!unvisited.empty())\n\t{\n\t\tPathfindingNode *currentNode = unvisited.pop();\n\t\tPosition const &currentPos = currentNode->getPosition();\n\n\t\t// Try all reachable neighbours.\n\t\tfor (int direction = 0; direction < 10; direction++)\n\t\t{\n\t\t\tPathfindingStep r = getTUCost(currentPos, direction, unit, 0, BAM_NORMAL);\n\t\t\tif (r.cost.time == INVALID_MOVE_COST) // Skip unreachable / blocked\n\t\t\t\tcontinue;\n\t\t\tPathfindingCost totalTuCost = currentNode->getTUCost(false) + r.cost + r.penalty;\n\t\t\tif (!(totalTuCost <= costMax)) // Run out of TUs/Energy\n\t\t\t\tcontinue;\n\t\t\tPathfindingNode *nextNode = getNode(r.pos);\n\t\t\tif (nextNode->isChecked()) // Our algorithm means this node is already at minimum cost.\n\t\t\t\tcontinue;\n\t\t\t// If this node is unvisited or visited from a better path.\n\t\t\tif (!nextNode->inOpenSet() || nextNode->getTUCost(false).time > totalTuCost.time)\n\t\t\t{\n\t\t\t\tnextNode->connect(totalTuCost, currentNode, direction);\n\t\t\t\tunvisited.push(nextNode);\n\t\t\t}\n\t\t}\n\t\tcurrentNode->setChecked();\n\t\treachable.push_back(currentNode);\n\t}\n\tstd::sort(reachable.begin(), reachable.end(), MinNodeCosts());\n\tstd::vector<int> tiles;\n\ttiles.reserve(reachable.size());\n\tfor (auto* pn : reachable)\n\t{\n\t\ttiles.push_back(_save->getTileIndex(pn->getPosition()));\n\t}\n\treturn tiles;\n}\n\n/**\n * Gets the strafe move setting.\n * @return Strafe move.\n */\nbool Pathfinding::getStrafeMove() const\n{\n\treturn _strafeMove;\n}\n\n/**\n * Gets the path preview setting.\n * @return True, if paths are previewed.\n */\nbool Pathfinding::isPathPreviewed() const\n{\n\treturn _pathPreviewed;\n}\n\n/**\n * Sets _unit in order to abuse low-level pathfinding functions from outside the class.\n * @param unit Unit taking the path.\n */\nvoid Pathfinding::setUnit(BattleUnit* unit)\n{\n\t_unit = unit;\n}\n\n/**\n * Gets a reference to the current path.\n * @return the actual path.\n */\nconst std::vector<int> &Pathfinding::getPath() const\n{\n\treturn _path;\n}\n\n/**\n * Makes a copy of the current path.\n * @return a copy of the path.\n */\nstd::vector<int> Pathfinding::copyPath() const\n{\n\treturn _path;\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/Pathfinding.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <vector>\n#include \"Position.h\"\n#include \"PathfindingNode.h\"\n#include \"../Mod/MapData.h\"\n\nnamespace OpenXcom\n{\n\nclass SavedBattleGame;\nclass Tile;\nclass BattleUnit;\nstruct BattleActionCost;\n\nenum BattleActionMove : char;\n\n\n/**\n * A utility class that calculates the shortest path between two points on the battlescape map.\n */\nclass Pathfinding\n{\nprivate:\n\tconstexpr static int dir_max = 10;\n\tconstexpr static int dir_x[dir_max] = {  0, +1, +1, +1,  0, -1, -1, -1,  0,  0};\n\tconstexpr static int dir_y[dir_max] = { -1, -1,  0, +1, +1, +1,  0, -1,  0,  0};\n\tconstexpr static int dir_z[dir_max] = {  0,  0,  0,  0,  0,  0,  0,  0, +1, -1};\n\n\tSavedBattleGame *_save;\n\tstd::vector<PathfindingNode> _nodes;\n\tint _size;\n\tBattleUnit *_unit;\n\tbool _pathPreviewed;\n\tbool _strafeMove;\n\tbool _ctrlUsed = false;\n\tbool _altUsed = false;\n\tPathfindingCost _totalTUCost;\n\n\t/// Gets the node at certain position.\n\tPathfindingNode *getNode(Position pos);\n\n\t/// Gets movement type of unit or movement of missile.\n\tMovementType getMovementType(const BattleUnit *unit, const BattleUnit *missileTarget, BattleActionMove bam) const;\n\t/// Determines whether a tile blocks a certain movementType.\n\tbool isBlocked(const BattleUnit *unit, const Tile *tile, const int part, BattleActionMove bam, const BattleUnit *missileTarget, int bigWallExclusion = -1) const;\n\t/// Determines whether or not movement between start tile and end tile is possible in the direction.\n\tbool isBlockedDirection(const BattleUnit *unit, const Tile *startTile, const int direction, BattleActionMove bam, const BattleUnit *missileTarget) const;\n\t/// Tries to find a straight line path between two positions.\n\tbool bresenhamPath(Position origin, Position target, BattleActionMove bam, const BattleUnit *missileTarget, bool sneak = false, int maxTUCost = 1000);\n\t/// Tries to find a path between two positions.\n\tbool aStarPath(Position origin, Position target, BattleActionMove bam, const BattleUnit *missileTarget, bool sneak = false, int maxTUCost = 1000);\n\t/// Determines whether a unit can fall down from this tile.\n\tbool canFallDown(const Tile *destinationTile) const;\n\t/// Determines whether a unit can fall down from this tile.\n\tbool canFallDown(const Tile *destinationTile, int size) const;\n\tstd::vector<int> _path;\npublic:\n\t/// Determines whether the unit is going up a stairs.\n\tbool isOnStairs(Position startPosition, Position endPosition) const;\n\t/// Determines whether or not movement between start tile and end tile is possible in the direction.\n\tbool isBlockedDirection(const BattleUnit *unit, Tile *startTile, const int direction) const;\n\n\t/// Default move cost for tile that have floor with 0 cost.\n\tstatic constexpr int DEFAULT_MOVE_COST = 4;\n\t/// Default move cost for changing level for fly or gravlift.\n\tstatic constexpr int DEFAULT_MOVE_FLY_COST = 8;\n\t/// How much time units one move can have.\n\tstatic constexpr int MAX_MOVE_COST = 100;\n\t/// Fake cost representing invalid move.\n\tstatic constexpr int INVALID_MOVE_COST = 255;\n\t/// Fire penalty used in path search.\n\tstatic constexpr int FIRE_PREVIEW_MOVE_COST = 32;\n\n\tstatic const int DIR_UP = 8;\n\tstatic const int DIR_DOWN = 9;\n\tenum bigWallTypes\n\t{\n\t\t/**\n\t\t     /###\\\n\t\t W  /#####\\  N\n\t\t   /#######\\\n\t\t  |#########|\n\t\t   \\#######/\n\t\t S  \\#####/  E\n\t\t     \\###/\n\t\t */\n\t\tBLOCK = 1,\n\n\t\t/**\n\t\t     /   \\\n\t\t W  /     \\  N\n\t\t   /#######\\\n\t\t  |#########|\n\t\t   \\#######/\n\t\t S  \\     /  E\n\t\t     \\   /\n\t\t */\n\t\tBIGWALLNESW = 2,\n\n\t\t/**\n\t\t     /###\\\n\t\t W  / ### \\  N\n\t\t   /  ###  \\\n\t\t  |   ###   |\n\t\t   \\  ###  /\n\t\t S  \\ ### /  E\n\t\t     \\###/\n\t\t */\n\t\tBIGWALLNWSE = 3,\n\n\t\t/**\n\t\t     /## \\\n\t\t W  /##   \\  N\n\t\t   /##     \\\n\t\t  |##       |\n\t\t   \\       /\n\t\t S  \\     /  E\n\t\t     \\   /\n\t\t */\n\t\tBIGWALLWEST = 4,\n\n\t\t/**\n\t\t     / ##\\\n\t\t W  /   ##\\  N\n\t\t   /     ##\\\n\t\t  |       ##|\n\t\t   \\       /\n\t\t S  \\     /  E\n\t\t     \\   /\n\t\t */\n\t\tBIGWALLNORTH = 5,\n\n\t\t/**\n\t\t     /   \\\n\t\t W  /     \\  N\n\t\t   /       \\\n\t\t  |       ##|\n\t\t   \\     ##/\n\t\t S  \\   ##/  E\n\t\t     \\ ##/\n\t\t */\n\t\tBIGWALLEAST = 6,\n\n\t\t/**\n\t\t     /   \\\n\t\t W  /     \\  N\n\t\t   /       \\\n\t\t  |##       |\n\t\t   \\##     /\n\t\t S  \\##   /  E\n\t\t     \\## /\n\t\t */\n\t\tBIGWALLSOUTH = 7,\n\n\t\t/**\n\t\t     /   \\\n\t\t W  /     \\  N\n\t\t   /       \\\n\t\t  |##     ##|\n\t\t   \\##   ##/\n\t\t S  \\#####/  E\n\t\t     \\###/\n\t\t */\n\t\tBIGWALLEASTANDSOUTH = 8,\n\n\t\t/**\n\t\t     /###\\\n\t\t W  /#####\\  N\n\t\t   /##   ##\\\n\t\t  |##     ##|\n\t\t   \\       /\n\t\t S  \\     /  E\n\t\t     \\   /\n\t\t */\n\t\tBIGWALLWESTANDNORTH = 9,\n\t};\n\tstatic const int O_BIGWALL = -1;\n\tstatic int red;\n\tstatic int green;\n\tstatic int yellow;\n\n\t/// Creates a new Pathfinding class.\n\tPathfinding(SavedBattleGame *save);\n\t/// Cleans up the Pathfinding.\n\t~Pathfinding();\n\t/// Calculates the shortest path.\n\tvoid calculate(BattleUnit *unit, Position endPosition, BattleActionMove bam, const BattleUnit *missileTarget = 0, int maxTUCost = 1000);\n\n\t/**\n\t * Converts direction to a vector. Direction starts north = 0 and goes clockwise.\n\t * @param direction Source direction.\n\t * @param vector Pointer to a position (which acts as a vector).\n\t */\n\tconstexpr static void directionToVector(int direction, Position *vector)\n\t{\n\t\tvector->x = dir_x[direction];\n\t\tvector->y = dir_y[direction];\n\t\tvector->z = dir_z[direction];\n\t}\n\n\t/**\n\t * Converts direction to a vector. Direction starts north = 0 and goes clockwise.\n\t * @param vector Pointer to a position (which acts as a vector).\n\t * @param dir Resulting direction.\n\t */\n\tconstexpr static void vectorToDirection(Position vector, int &dir)\n\t{\n\t\tdir = vectorToDirection(vector);\n\t}\n\n\t/**\n\t * Converts direction to a vector. Direction starts north = 0 and goes clockwise.\n\t * @param vector Pointer to a position (which acts as a vector).\n\t * @return dir Resulting direction.\n\t */\n\tconstexpr static int vectorToDirection(Position vector)\n\t{\n\t\tfor (int i = 0; i < 8; ++i)\n\t\t{\n\t\t\tif (dir_x[i] == vector.x && dir_y[i] == vector.y)\n\t\t\t{\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\t\treturn -1;\n\t}\n\n\t/// Checks whether a path is ready and gives the first direction.\n\tint getStartDirection() const;\n\t/// Dequeues a direction.\n\tint dequeuePath();\n\t/// Gets the TU cost to move from 1 tile to the other.\n\tPathfindingStep getTUCost(Position startPosition, int direction, const BattleUnit *unit, const BattleUnit *missileTarget, BattleActionMove bam) const;\n\t/// Aborts the current path.\n\tvoid abortPath();\n\t/// Gets the strafe move setting.\n\tbool getStrafeMove() const;\n\t/// Checks, for the up/down button, if the movement is valid.\n\tbool validateUpDown(const BattleUnit *bu, const Position& startPosition, const int direction, bool missile = false) const;\n\n\t/// Previews the path.\n\tbool previewPath(bool bRemove = false);\n\t/// Removes the path preview.\n\tbool removePreview();\n\t/// Refresh the path preview.\n\tvoid refreshPath();\n\n\t/// Sets _unit in order to abuse low-level pathfinding functions from outside the class.\n\tvoid setUnit(BattleUnit *unit);\n\t/// Gets all reachable tiles, based on cost.\n\tstd::vector<int> findReachable(const BattleUnit *unit, const BattleActionCost &cost);\n\t/// Gets _totalTUCost; finds out whether we can hike somewhere in this turn or not.\n\tint getTotalTUCost() const { return _totalTUCost.time; }\n\t/// Gets the path preview setting.\n\tbool isPathPreviewed() const;\n\t/// Gets the modifier setting.\n\tbool isModifierCtrlUsed() const { return _ctrlUsed; }\n\t/// Gets the modifier setting.\n\tbool isModifierAltUsed() const { return _altUsed; }\n\t/// Gets a reference to the path.\n\tconst std::vector<int> &getPath() const;\n\t/// Makes a copy to the path.\n\tstd::vector<int> copyPath() const;\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/PathfindingNode.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"PathfindingNode.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Sets up a PathfindingNode.\n * @param pos Position.\n */\nPathfindingNode::PathfindingNode(Position pos) : _pos(pos), _prevNode(0), _prevDir(0), _tuGuess(0), _checked(0), _openentry(0)\n{\n\n}\n\n/**\n * Deletes the PathfindingNode.\n */\nPathfindingNode::~PathfindingNode()\n{\n\n}\n\n/**\n * Gets the node position.\n * @return Node position.\n */\nPosition PathfindingNode::getPosition() const\n{\n\treturn _pos;\n}\n\n/**\n * Resets the node.\n */\nvoid PathfindingNode::reset()\n{\n\t_checked = false;\n\t_openentry = 0;\n}\n\n/**\n * Gets the checked status of this node.\n * @return True, if this node was checked.\n */\nbool PathfindingNode::isChecked() const\n{\n\treturn _checked;\n}\n\n/**\n * Gets the previous node.\n * @return Pointer to the previous node.\n */\nPathfindingNode* PathfindingNode::getPrevNode() const\n{\n\treturn _prevNode;\n}\n\n/**\n * Gets the previous walking direction for how we got on this node.\n * @return Previous vector.\n */\nint PathfindingNode::getPrevDir() const\n{\n\treturn _prevDir;\n}\n\n/**\n * Connects the node. This will connect the node to the previous node along the path to @a target\n * and update the pathfinding information.\n * @param tuCost The total cost of the path so far.\n * @param prevNode The previous node along the path.\n * @param prevDir The direction FROM the previous node.\n * @param target The target position (used to update our guess cost).\n */\nvoid PathfindingNode::connect(PathfindingCost cost, PathfindingNode* prevNode, int prevDir, Position target)\n{\n\t_tuCost = cost;\n\t_prevNode = prevNode;\n\t_prevDir = prevDir;\n\tif (!inOpenSet()) // Otherwise we have this already.\n\t{\n\t\t_tuGuess = 4 * Position::distance(target, _pos);\n\t}\n}\n\n/**\n * Connects the node. This will connect the node to the previous node along the path.\n * @param tuCost The total cost of the path so far.\n * @param prevNode The previous node along the path.\n * @param prevDir The direction FROM the previous node.\n */\nvoid PathfindingNode::connect(PathfindingCost cost, PathfindingNode* prevNode, int prevDir)\n{\n\t_tuCost = cost;\n\t_prevNode = prevNode;\n\t_prevDir = prevDir;\n\t_tuGuess = 0;\n}\n\n\n}\n"
  },
  {
    "path": "src/Battlescape/PathfindingNode.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Position.h\"\n\nnamespace OpenXcom\n{\n\nclass PathfindingOpenSet;\nstruct OpenSetEntry;\n\n/**\n * Cost of one step.\n * As this is 2d point value it is not totally ordered.\n */\nstruct PathfindingCost\n{\n\tSint16 time = 0;\n\tSint16 energy = 0;\n\n\t/// Default constructor.\n\tPathfindingCost() = default;\n\n\t/// Constructor from ints.\n\tPathfindingCost(int t, int e) : time(t), energy(e) {}\n\n\tPathfindingCost operator+(PathfindingCost c) const\n\t{\n\t\treturn {\n\t\t\tstatic_cast<Sint16>(time + c.time),\n\t\t\tstatic_cast<Sint16>(energy + c.energy),\n\t\t};\n\t}\n\n\tbool operator<=(PathfindingCost c) const\n\t{\n\t\treturn time <= c.time && energy <= c.energy;\n\t}\n\tbool operator>=(PathfindingCost c) const\n\t{\n\t\treturn time >= c.time && energy >= c.energy;\n\t}\n\tbool operator<(PathfindingCost c) const\n\t{\n\t\treturn time < c.time && energy < c.energy;\n\t}\n\tbool operator>(PathfindingCost c) const\n\t{\n\t\treturn time > c.time && energy > c.energy;\n\t}\n};\n\n/**\n * Result of one step in pathfinding algorithm.\n */\nstruct PathfindingStep\n{\n\t/// Real cost of moving one step.\n\tPathfindingCost cost;\n\t/// Pathfinding penalty for given step.\n\tPathfindingCost penalty = { };\n\t/// Final position of one step.\n\tPosition pos = { };\n};\n\n/**\n * A class that holds pathfinding info for a certain node on the map.\n */\nclass PathfindingNode\n{\nprivate:\n\tPosition _pos;\n\tPathfindingCost _tuCost;\n\tPathfindingNode* _prevNode;\n\tint _prevDir;\n\t/// Approximate cost to reach goal position.\n\tSint16 _tuGuess;\n\t/// Is best path find for this tile.\n\tbool _checked;\n\t// Invasive field needed by PathfindingOpenSet\n\tUint8 _openentry;\n\tfriend class PathfindingOpenSet;\npublic:\n\t/// Creates a new PathfindingNode class.\n\tPathfindingNode(Position pos);\n\t/// Cleans up the PathfindingNode.\n\t~PathfindingNode();\n\t/// Gets the node position.\n\tPosition getPosition() const;\n\t/// Resets the node.\n\tvoid reset();\n\t/// Is checked?\n\tbool isChecked() const;\n\t/// Marks the node as checked.\n\tvoid setChecked() { _checked = true; }\n\t/// Gets the TU cost.\n\tPathfindingCost getTUCost(bool missile) const { return missile ? PathfindingCost{} : _tuCost; }\n\t/// Gets the previous node.\n\tPathfindingNode* getPrevNode() const;\n\t/// Gets the previous walking direction.\n\tint getPrevDir() const;\n\t/// Is this node already in a PathfindingOpenSet?\n\tbool inOpenSet() const { return (_openentry != 0); }\n\t/// Gets the approximate cost to reach the target position.\n\tint getTUGuess() const { return _tuGuess; }\n\n\t#ifdef __MORPHOS__\n\t#undef connect\n\t#endif\n\n\t/// Connects to previous node along the path.\n\tvoid connect(PathfindingCost cost, PathfindingNode* prevNode, int prevDir, Position target);\n\t/// Connects to previous node along a visit.\n\tvoid connect(PathfindingCost cost, PathfindingNode* prevNode, int prevDir);\n};\n\n/**\n * Compares PathfindingNode pointers based on TU cost.\n */\nclass MinNodeCosts\n{\npublic:\n\t/**\n\t * Compares nodes @a *a and @a *b.\n\t * @param a Pointer to first node.\n\t * @param b Pointer to second node.\n\t * @return True if node @a *a must come before @a *b.\n\t */\n\tbool operator()(const PathfindingNode *a, const PathfindingNode *b) const\n\t{\n\t\treturn a->getTUCost(false) < b->getTUCost(false);\n\t}\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/PathfindingOpenSet.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <assert.h>\n#include \"PathfindingOpenSet.h\"\n#include \"PathfindingNode.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Cleans up all the entries still in set.\n */\nPathfindingOpenSet::~PathfindingOpenSet()\n{\n\n}\n\n/**\n * Keeps removing all discarded entries that have come to the top of the queue.\n */\nvoid PathfindingOpenSet::removeDiscarded()\n{\n\twhile (!_queue.empty() && _queue.top()._node->_openentry != _queue.top()._openentry)\n\t{\n\t\t_queue.pop();\n\t}\n}\n\n/**\n * Gets the node with the least cost.\n * After this call, the node is no longer in the set. It is an error to call this when the set is empty.\n * @return A pointer to the node which had the least cost.\n */\nPathfindingNode *PathfindingOpenSet::pop()\n{\n\tassert(!empty());\n\n\tPathfindingNode *nd = _queue.top()._node;\n\t_queue.pop();\n\tnd->_openentry = 0;\n\n\t// Discarded entries might be visible now.\n\tremoveDiscarded();\n\treturn nd;\n}\n\n/**\n * Places the node in the set.\n * If the node was already in the set, the previous entry is discarded.\n * It is the caller's responsibility to never re-add a node with a worse cost.\n * @param node A pointer to the node to add.\n */\nvoid PathfindingOpenSet::push(PathfindingNode *node)\n{\n\tassert(node->_openentry != 255u);\n\n\tOpenSetEntry entry = {};\n\tentry._node = node;\n\tentry._cost = node->getTUCost(false).time * 4 + node->getTUGuess(); //HACK: this is not real cost, more rough approximation for algorithm, as bonus `getTUGuess` work more like gravity/potential than normal cost.\n\tentry._openentry = ++node->_openentry; // next unique number, used to check if old recode is still valid.\n\t_queue.push(entry);\n}\n\n\n}\n"
  },
  {
    "path": "src/Battlescape/PathfindingOpenSet.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <queue>\n#include <SDL_stdinc.h>\n\nnamespace OpenXcom\n{\n\nclass PathfindingNode;\n\nstruct OpenSetEntry\n{\n\tPathfindingNode *_node;\n\tSint16 _cost;\n\tUint8 _openentry;\n};\n\n/**\n * Helper class to compare entries through pointers.\n */\nclass EntryCompare\n{\npublic:\n\t/**\n\t * Compares entries @a *a and @a *b.\n\t * @param a Pointer to first entry.\n\t * @param b Pointer to second entry.\n\t * @return True if entry @a *b must come before @a *a.\n\t */\n\tbool operator()(const OpenSetEntry& a, const OpenSetEntry& b) const\n\t{\n\t\treturn b._cost < a._cost;\n\t}\n};\n\n/**\n * A class that holds references to the nodes to be examined in pathfinding.\n */\nclass PathfindingOpenSet\n{\npublic:\n\t/// Cleans up the set and frees allocated memory.\n\t~PathfindingOpenSet();\n\t/// Gets the next node to check.\n\tPathfindingNode *pop();\n\t/// Adds a node to the set.\n\tvoid push(PathfindingNode *node);\n\t/// Is the set empty?\n\tbool empty() const { return _queue.empty(); }\n\nprivate:\n\tstd::priority_queue<OpenSetEntry, std::vector<OpenSetEntry>, EntryCompare> _queue;\n\n\t/// Removes reachable discarded entries.\n\tvoid removeDiscarded();\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/Position.cpp",
    "content": "/*\n * Copyright 2010-2024 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n# include \"Position.h\"\n\nnamespace OpenXcom\n{\n\n// helper overloads for (de)serialization\nbool read(ryml::ConstNodeRef const& n, Position* val)\n{\n\tYAML::YamlNodeReader reader(n);\n\tval->x = reader[0].readVal<Sint16>();\n\tval->y = reader[1].readVal<Sint16>();\n\tval->z = reader[2].readVal<Sint16>();\n\treturn true;\n}\nvoid write(ryml::NodeRef* n, Position const& val)\n{\n\tYAML::YamlNodeWriter writer(*n);\n\twriter.setAsSeq();\n\twriter.setFlowStyle();\n\twriter.write(val.x);\n\twriter.write(val.y);\n\twriter.write(val.z);\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/Position.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/Yaml.h\"\n#include <SDL_types.h>\n#include <cmath>\n#include <ostream>\n\nnamespace OpenXcom\n{\n\n/**\n * Easy handling of X-Y-Z coordinates.\n */\nclass Position\n{\npublic:\n\tconstexpr static int TileXY = 16;\n\tconstexpr static int TileZ = 24;\n\n\tSint16 x, y, z;\n\n\t/// Null position constructor.\n\tconstexpr Position() noexcept : x(0), y(0), z(0) {};\n\t/// X Y Z position constructor.\n\tconstexpr Position(int x_, int y_, int z_) noexcept : x(x_), y(y_), z(z_) {};\n\t/// Copy constructor.\n\tconstexpr Position(const Position& pos) = default;\n\n\t/// Assignment\n\tconstexpr Position& operator=(const Position& pos) = default;\n\n\tconstexpr Position operator+(const Position& pos) const { return Position(x + pos.x, y + pos.y, z + pos.z); }\n\tconstexpr Position& operator+=(const Position& pos) { x+=pos.x; y+=pos.y; z+=pos.z; return *this; }\n\n\tconstexpr Position operator-(const Position& pos) const { return Position(x - pos.x, y - pos.y, z - pos.z); }\n\tconstexpr Position& operator-=(const Position& pos) { x-=pos.x; y-=pos.y; z-=pos.z; return *this; }\n\n\tconstexpr Position operator*(const Position& pos) const { return Position(x * pos.x, y * pos.y, z * pos.z); }\n\tconstexpr Position& operator*=(const Position& pos) { x*=pos.x; y*=pos.y; z*=pos.z; return *this; }\n\tconstexpr Position operator*(const int v) const { return Position(x * v, y * v, z * v); }\n\tconstexpr Position& operator*=(const int v) { x*=v; y*=v; z*=v; return *this; }\n\n\tconstexpr Position operator/(const Position& pos) const { return Position(x / pos.x, y / pos.y, z / pos.z); }\n\tconstexpr Position& operator/=(const Position& pos) { x/=pos.x; y/=pos.y; z/=pos.z; return *this; }\n\n\tconstexpr Position operator/(const int v) const { return Position(x / v, y / v, z / v); }\n\n\t/// == operator\n\tconstexpr bool operator== (const Position& pos) const\n\t{\n\t\treturn x == pos.x && y == pos.y && z == pos.z;\n\t}\n\t/// != operator\n\tconstexpr bool operator!= (const Position& pos) const\n\t{\n\t\treturn x != pos.x || y != pos.y || z != pos.z;\n\t}\n\n\t/// Convert tile position to voxel position.\n\tconstexpr Position toVoxel() const\n\t{\n\t\treturn Position(x * TileXY, y * TileXY, z * TileZ);\n\t}\n\t/// Convert voxel position to tile position.\n\tconstexpr Position toTile() const\n\t{\n\t\treturn Position(x / TileXY, y / TileXY, z / TileZ);\n\t}\n\t/// Clip voxel values to position relative to containing tile.\n\tconstexpr Position clipVoxel() const\n\t{\n\t\treturn Position(x % TileXY, y % TileXY, z % TileZ);\n\t}\n\n\t/// Calculates the distance in 3d.\n\tstatic float distance(Position pos1, Position pos2)\n\t{\n\t\treturn std::sqrt(distanceSq(pos1, pos2));\n\t}\n\n\t/**\n\t * Calculates the distance squared between 2 points in 3d. No sqrt(), not floating point math, and sometimes it's all you need.\n\t * @param pos1 Position of first square.\n\t * @param pos2 Position of second square.\n\t * @return Distance.\n\t */\n\tconstexpr static int distanceSq(Position pos1, Position pos2)\n\t{\n\t\tint x = pos1.x - pos2.x;\n\t\tint y = pos1.y - pos2.y;\n\t\tint z = pos1.z - pos2.z;\n\t\treturn x*x + y*y + z*z;\n\t}\n\n\t/**\n\t * Calculates the distance between 2 points in 2d. Rounded up to first INT.\n\t * @param pos1 Position of first square.\n\t * @param pos2 Position of second square.\n\t * @return Distance.\n\t */\n\tstatic int distance2d(Position pos1, Position pos2)\n\t{\n\t\treturn (int)std::ceil(std::sqrt(distance2dSq(pos1, pos2)));\n\t}\n\n\t/**\n\t * Calculates the distance squared between 2 points in 2d. No sqrt(), not floating point math, and sometimes it's all you need.\n\t * @param pos1 Position of first square.\n\t * @param pos2 Position of second square.\n\t * @return Distance.\n\t */\n\tconstexpr static int distance2dSq(Position pos1, Position pos2)\n\t{\n\t\tint x = pos1.x - pos2.x;\n\t\tint y = pos1.y - pos2.y;\n\t\treturn x*x + y*y;\n\t}\n};\n\ninline std::ostream& operator<<(std::ostream& out, const Position& pos)\n{\n\tout << \"(\" << pos.x << \",\" << pos.y << \",\"<< pos.z << \")\";\n\treturn out;\n}\n\ntypedef Position Vector3i;\n\n\n/**\n * Helper class storing last two position from Projectile\n */\nstruct LastPositions\n{\n\tLastPositions(Position l) : last{l}, before{l} {};\n\tLastPositions(Position l, Position b) : last{l}, before{b} {};\n\n\tPosition last;\n\tPosition before;\n};\n\n// helper overloads for (de)serialization\nbool read(ryml::ConstNodeRef const& n, Position* val);\nvoid write(ryml::NodeRef* n, Position const& val);\n\n}\n"
  },
  {
    "path": "src/Battlescape/PrimeGrenadeState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <sstream>\n#include \"PrimeGrenadeState.h\"\n#include \"BattlescapeGame.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Action.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/Frame.h\"\n#include \"../Engine/InteractiveSurface.h\"\n#include \"../Savegame/BattleItem.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleInterface.h\"\n#include \"../Engine/Sound.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Prime Grenade window.\n * @param game Pointer to the core game.\n * @param action Pointer to the action.\n * @param inInventoryView Called from inventory?\n * @param grenadeInInventory Pointer to associated grenade.\n */\nPrimeGrenadeState::PrimeGrenadeState(BattleAction *action, bool inInventoryView, BattleItem *grenadeInInventory) :\n\t_action(action), _inInventoryView(inInventoryView), _grenadeInInventory(grenadeInInventory)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_title = new Text(192, 24, 65, 44);\n\t_frame = new Frame(192, 27, 65, 37);\n\t_bg = new Surface(192, 93, 65, 45);\n\n\tint x = 67;\n\tint y = 68;\n\tfor (int i = 0; i < 24; ++i)\n\t{\n\t\t_button[i] = new InteractiveSurface(22, 22, x-1+((i%8)*24), y-4+((i/8)*25));\n\t\t_number[i] = new Text(20, 20, x+((i%8)*24), y-1+((i/8)*25));\n\t}\n\n\t// Set palette\n\tif (inInventoryView)\n\t{\n\t\tsetStandardPalette(\"PAL_BATTLESCAPE\");\n\t}\n\telse\n\t{\n\t\t_game->getSavedGame()->getSavedBattle()->setPaletteByDepth(this);\n\t}\n\n\tconst Element *grenadeBackground = _game->getMod()->getInterface(\"battlescape\")->getElement(\"grenadeBackground\");\n\n\t// Set up objects\n\tadd(_bg);\n\t_bg->drawRect(0, 0, _bg->getWidth(), _bg->getHeight(), grenadeBackground->color);\n\n\tadd(_frame, \"grenadeMenu\", \"battlescape\");\n\t_frame->setThickness(3);\n\t_frame->setHighContrast(true);\n\n\tadd(_title, \"grenadeMenu\", \"battlescape\");\n\t_title->setAlign(ALIGN_CENTER);\n\t_title->setBig();\n\t_title->setText(tr(\"STR_SET_TIMER\"));\n\t_title->setHighContrast(true);\n\n\tfor (int i = 0; i < 24; ++i)\n\t{\n\t\tSDL_Rect square;\n\t\tadd(_button[i]);\n\t\t_button[i]->onMouseClick((ActionHandler)&PrimeGrenadeState::btnClick);\n\t\tsquare.x = 0;\n\t\tsquare.y = 0;\n\t\tsquare.w = _button[i]->getWidth();\n\t\tsquare.h = _button[i]->getHeight();\n\t\t_button[i]->drawRect(&square, grenadeBackground->border);\n\t\tsquare.x++;\n\t\tsquare.y++;\n\t\tsquare.w -= 2;\n\t\tsquare.h -= 2;\n\t\t_button[i]->drawRect(&square, grenadeBackground->color2);\n\n\t\tstd::ostringstream ss;\n\t\tss << i;\n\t\tadd(_number[i], \"grenadeMenu\", \"battlescape\");\n\t\t_number[i]->setBig();\n\t\t_number[i]->setText(ss.str());\n\t\t_number[i]->setHighContrast(true);\n\t\t_number[i]->setAlign(ALIGN_CENTER);\n\t\t_number[i]->setVerticalAlign(ALIGN_MIDDLE);\n\t}\n\n\t_button[0]->onKeyboardRelease((ActionHandler)&PrimeGrenadeState::btnClick, SDLK_q); // FIXME: this is just a workaround, fix it better!\n\t_button[0]->onKeyboardPress((ActionHandler)&PrimeGrenadeState::btnClick, SDLK_0);\n\t_button[1]->onKeyboardPress((ActionHandler)&PrimeGrenadeState::btnClick, SDLK_1);\n\t_button[2]->onKeyboardPress((ActionHandler)&PrimeGrenadeState::btnClick, SDLK_2);\n\t_button[3]->onKeyboardPress((ActionHandler)&PrimeGrenadeState::btnClick, SDLK_3);\n\n\tcenterAllSurfaces();\n\tlowerAllSurfaces();\n}\n\n/**\n *\n */\nPrimeGrenadeState::~PrimeGrenadeState()\n{\n\n}\n\n/**\n * Closes the window on right-click.\n * @param action Pointer to an action.\n */\nvoid PrimeGrenadeState::handle(Action *action)\n{\n\tState::handle(action);\n\tif (action->getDetails()->type == SDL_MOUSEBUTTONDOWN && _game->isRightClick(action))\n\t{\n\t\tif (!_inInventoryView) _action->value = -1;\n\t\t_game->popState();\n\t}\n\telse if (action->getDetails()->type == SDL_KEYDOWN && action->getDetails()->key.keysym.sym == Options::keyCancel)\n\t{\n\t\tif (!_inInventoryView) _action->value = -1;\n\t\t_game->popState();\n\t}\n}\n\n\n/**\n * Executes the action corresponding to this action menu item.\n * @param action Pointer to an action.\n */\nvoid PrimeGrenadeState::btnClick(Action *action)\n{\n\tint btnID = -1;\n\n\tif (_game->isRightClick(action))\n\t{\n\t\tif (!_inInventoryView) _action->value = btnID;\n\t\t_game->popState();\n\t\treturn;\n\t}\n\n\t// got to find out which button was pressed\n\tfor (int i = 0; i < 24 && btnID == -1; ++i)\n\t{\n\t\tif (action->getSender() == _button[i])\n\t\t{\n\t\t\tbtnID = i;\n\t\t}\n\t}\n\n\tif (btnID != -1)\n\t{\n\t\tif (_inInventoryView)\n\t\t{\n\t\t\t_grenadeInInventory->setFuseTimer(0 + btnID);\n\t\t\t// prime sound\n\t\t\tint sound = _grenadeInInventory->getRules()->getPrimeSound();\n\t\t\tif (sound != Mod::NO_SOUND)\n\t\t\t{\n\t\t\t\t_game->getMod()->getSoundByDepth(_game->getSavedGame()->getSavedBattle()->getDepth(), sound)->play();\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_action->value = btnID;\n\t\t}\n\t\t_game->popState();\n\t\tif (!_inInventoryView) _game->popState();\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/PrimeGrenadeState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http:///www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass Game;\nclass Text;\nclass InteractiveSurface;\nclass Frame;\nclass Surface;\nclass BattleItem;\nstruct BattleAction;\n\n/**\n * Window that allows the player\n * to set the timer of an explosive.\n */\nclass PrimeGrenadeState : public State\n{\nprivate:\n\tBattleAction *_action;\n\tbool _inInventoryView;\n\tBattleItem *_grenadeInInventory;\n\tText *_number[24];\n\tText *_title;\n\tFrame *_frame;\n\tInteractiveSurface *_button[24];\n\tSurface *_bg;\npublic:\n\t/// Creates the Prime Grenade state.\n\tPrimeGrenadeState(BattleAction *action, bool inInventoryView, BattleItem *grenadeInInventory);\n\t/// Cleans up the Prime Grenade state.\n\t~PrimeGrenadeState();\n\t/// Handler for right-clicking anything.\n\tvoid handle(Action *action) override;\n\t/// Handler for clicking a button.\n\tvoid btnClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/Projectile.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Projectile.h\"\n#include \"TileEngine.h\"\n#include \"Map.h\"\n#include \"Camera.h\"\n#include \"Particle.h\"\n#include \"Pathfinding.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"../Mod/MapData.h\"\n#include \"../Savegame/BattleUnit.h\"\n#include \"../Savegame/BattleItem.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"../Savegame/Tile.h\"\n#include \"../Engine/RNG.h\"\n#include \"../Engine/Options.h\"\n#include \"../fmath.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Sets up a UnitSprite with the specified size and position.\n * @param mod Pointer to mod.\n * @param save Pointer to battle savegame.\n * @param action An action.\n * @param origin Position the projectile originates from.\n * @param targetVoxel Position the projectile is targeting.\n * @param ammo the ammo that produced this projectile, where applicable.\n */\nProjectile::Projectile(Mod *mod, SavedBattleGame *save, BattleAction action, Position origin, Position targetVoxel, BattleItem *ammo) : _mod(mod), _save(save), _action(action), _ammo(ammo), _origin(origin), _targetVoxel(targetVoxel), _position(0), _distance(0.0f), _bulletSprite(-1), _reversed(false), _vaporColor(-1), _vaporDensity(-1), _vaporProbability(5)\n{\n\t// this is the number of pixels the sprite will move between frames\n\t_speed = Options::battleFireSpeed;\n\tif (_action.weapon)\n\t{\n\t\tif (_action.type != BA_THROW)\n\t\t{\n\t\t\tassert(_ammo && \"missing ammo for Projectile\");\n\n\t\t\t// try to get all the required info from the ammo\n\t\t\t_bulletSprite = _ammo->getRules()->getBulletSprite();\n\t\t\t_vaporColor = _ammo->getRules()->getVaporColor(_save->getDepth());\n\t\t\t_vaporDensity = _ammo->getRules()->getVaporDensity(_save->getDepth());\n\t\t\t_vaporProbability = _ammo->getRules()->getVaporProbability(_save->getDepth());\n\t\t\t_speed = std::max(1, _speed + _ammo->getRules()->getBulletSpeed());\n\n\t\t\t// the ammo didn't contain the info we wanted, see what the weapon has on offer.\n\t\t\tif (_bulletSprite == Mod::NO_SURFACE)\n\t\t\t{\n\t\t\t\t_bulletSprite = _action.weapon->getRules()->getBulletSprite();\n\t\t\t}\n\t\t\tif (_vaporColor == -1)\n\t\t\t{\n\t\t\t\t_vaporColor = _action.weapon->getRules()->getVaporColor(_save->getDepth());\n\t\t\t}\n\t\t\tif (_vaporDensity == -1)\n\t\t\t{\n\t\t\t\t_vaporDensity = _action.weapon->getRules()->getVaporDensity(_save->getDepth());\n\t\t\t}\n\t\t\tif (_vaporProbability == 5)\n\t\t\t{\n\t\t\t\t_vaporProbability = _action.weapon->getRules()->getVaporProbability(_save->getDepth());\n\t\t\t}\n\t\t\tif (!ammo || (ammo != _action.weapon || ammo->getRules()->getBulletSpeed() == 0))\n\t\t\t{\n\t\t\t\t_speed = std::max(1, _speed + _action.weapon->getRules()->getBulletSpeed());\n\t\t\t}\n\t\t}\n\t}\n\tif ((targetVoxel.x - origin.x) + (targetVoxel.y - origin.y) >= 0)\n\t{\n\t\t_reversed = true;\n\t}\n}\n\n/**\n * Deletes the Projectile.\n */\nProjectile::~Projectile()\n{\n\n}\n\n/**\n * Calculates the trajectory for a straight path.\n * @param accuracy The unit's accuracy.\n * @return The objectnumber(0-3) or unit(4) or out of map (5) or -1 (no line of fire).\n */\n\nint Projectile::calculateTrajectory(double accuracy)\n{\n\tPosition originVoxel = _save->getTileEngine()->getOriginVoxel(_action, _save->getTile(_origin));\n\treturn calculateTrajectory(accuracy, originVoxel);\n}\n\nint Projectile::calculateTrajectory(double accuracy, const Position& originVoxel, bool excludeUnit)\n{\n\tTile *targetTile = _save->getTile(_action.target);\n\tBattleUnit *bu = _action.actor;\n\n\t_distance = 0.0f;\n\tint test;\n\tif (excludeUnit)\n\t{\n\t\ttest = _save->getTileEngine()->calculateLineVoxel(originVoxel, _targetVoxel, false, &_trajectory, bu);\n\t}\n\telse\n\t{\n\t\ttest = _save->getTileEngine()->calculateLineVoxel(originVoxel, _targetVoxel, false, &_trajectory, nullptr);\n\t}\n\n\tif (test != V_EMPTY &&\n\t\t!_trajectory.empty() &&\n\t\t_action.actor->getFaction() == FACTION_PLAYER &&\n\t\t_action.autoShotCounter == 1 &&\n\t\t(!_save->isCtrlPressed(true) || !Options::forceFire) &&\n\t\t_save->getBattleGame()->getPanicHandled() &&\n\t\t_action.type != BA_LAUNCH &&\n\t\t!_action.sprayTargeting)\n\t{\n\t\tPosition hitPos = _trajectory.at(0).toTile();\n\t\tif (test == V_UNIT && _save->getTile(hitPos) && _save->getTile(hitPos)->getUnit() == 0) //no unit? must be lower\n\t\t{\n\t\t\thitPos = Position(hitPos.x, hitPos.y, hitPos.z-1);\n\t\t}\n\n\t\tif (hitPos != _action.target && _action.result.empty())\n\t\t{\n\t\t\tif (test == V_NORTHWALL)\n\t\t\t{\n\t\t\t\tif (hitPos.y - 1 != _action.target.y)\n\t\t\t\t{\n\t\t\t\t\t_trajectory.clear();\n\t\t\t\t\treturn V_EMPTY;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (test == V_WESTWALL)\n\t\t\t{\n\t\t\t\tif (hitPos.x - 1 != _action.target.x)\n\t\t\t\t{\n\t\t\t\t\t_trajectory.clear();\n\t\t\t\t\treturn V_EMPTY;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (test == V_UNIT)\n\t\t\t{\n\t\t\t\tBattleUnit *hitUnit = _save->getTile(hitPos)->getUnit();\n\t\t\t\tBattleUnit *targetUnit = targetTile->getUnit(); // Note: hitPos could be 1 tile lower and hitUnit could be on both tiles; change in OXC?\n\t\t\t\tif (hitUnit != targetUnit)\n\t\t\t\t{\n\t\t\t\t\t_trajectory.clear();\n\t\t\t\t\treturn V_EMPTY;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_trajectory.clear();\n\t\t\t\treturn V_EMPTY;\n\t\t\t}\n\t\t}\n\t}\n\n\t_trajectory.clear();\n\n\tbool extendLine = true;\n\t// even guided missiles drift, but how much is based on\n\t// the shooter's faction, rather than accuracy.\n\tif (_action.type == BA_LAUNCH)\n\t{\n\t\tif (_action.actor->getFaction() == FACTION_PLAYER)\n\t\t{\n\t\t\taccuracy = 0.60;\n\t\t}\n\t\telse\n\t\t{\n\t\t\taccuracy = 0.55;\n\t\t}\n\t\textendLine = _action.waypoints.size() <= 1;\n\t}\n\n\t// apply some accuracy modifiers.\n\t// This will results in a new target voxel\n\tapplyAccuracy(originVoxel, &_targetVoxel, accuracy, false, extendLine);\n\n\t// finally do a line calculation and store this trajectory.\n\treturn _save->getTileEngine()->calculateLineVoxel(originVoxel, _targetVoxel, true, &_trajectory, bu);\n}\n\n/**\n * Calculates the trajectory for a curved path.\n * @param accuracy The unit's accuracy.\n * @return True when a trajectory is possible.\n */\nint Projectile::calculateThrow(double accuracy)\n{\n\tTile *targetTile = _save->getTile(_action.target);\n\n\tPosition originVoxel = _save->getTileEngine()->getOriginVoxel(_action, 0);\n\tPosition targetVoxel;\n\tstd::vector<Position> targets;\n\tdouble curvature;\n\ttargetVoxel = _action.target.toVoxel() + Position(8,8, (1 + -targetTile->getTerrainLevel()));\n\ttargets.clear();\n\tbool forced = false;\n\n\tif (_action.type == BA_THROW)\n\t{\n\t\ttargets.push_back(targetVoxel);\n\t}\n\telse\n\t{\n\t\tBattleUnit *tu = targetTile->getOverlappingUnit(_save);\n\t\tif (Options::forceFire && _save->isCtrlPressed(true) && _save->getSide() == FACTION_PLAYER)\n\t\t{\n\t\t\ttargets.push_back(_action.target.toVoxel() + Position(0, 0, 12));\n\t\t\tforced = true;\n\t\t}\n\t\telse if (tu && ((_action.actor->getFaction() != FACTION_PLAYER) ||\n\t\t\ttu->getVisible()))\n\t\t{ //unit\n\t\t\ttargetVoxel.z += tu->getFloatHeight(); //ground level is the base\n\t\t\ttargets.push_back(targetVoxel + Position(0, 0, tu->getHeight()/2 + 1));\n\t\t\ttargets.push_back(targetVoxel + Position(0, 0, 2));\n\t\t\ttargets.push_back(targetVoxel + Position(0, 0, tu->getHeight() - 1));\n\t\t}\n\t\telse if (targetTile->getMapData(O_OBJECT) != 0)\n\t\t{\n\t\t\ttargetVoxel = _action.target.toVoxel() + Position(8,8,0);\n\t\t\ttargets.push_back(targetVoxel + Position(0, 0, 13));\n\t\t\ttargets.push_back(targetVoxel + Position(0, 0, 8));\n\t\t\ttargets.push_back(targetVoxel + Position(0, 0, 23));\n\t\t\ttargets.push_back(targetVoxel + Position(0, 0, 2));\n\t\t}\n\t\telse if (targetTile->getMapData(O_NORTHWALL) != 0)\n\t\t{\n\t\t\ttargetVoxel = _action.target.toVoxel() + Position(8,0,0);\n\t\t\ttargets.push_back(targetVoxel + Position(0, 0, 13));\n\t\t\ttargets.push_back(targetVoxel + Position(0, 0, 8));\n\t\t\ttargets.push_back(targetVoxel + Position(0, 0, 20));\n\t\t\ttargets.push_back(targetVoxel + Position(0, 0, 3));\n\t\t}\n\t\telse if (targetTile->getMapData(O_WESTWALL) != 0)\n \t\t{\n\t\t\ttargetVoxel = _action.target.toVoxel() + Position(0,8,0);\n\t\t\ttargets.push_back(targetVoxel + Position(0, 0, 13));\n\t\t\ttargets.push_back(targetVoxel + Position(0, 0, 8));\n\t\t\ttargets.push_back(targetVoxel + Position(0, 0, 20));\n\t\t\ttargets.push_back(targetVoxel + Position(0, 0, 2));\n\t\t}\n\t\telse if (targetTile->getMapData(O_FLOOR) != 0)\n\t\t{\n\t\t\ttargets.push_back(targetVoxel);\n\t\t}\n\t}\n\n\t_distance = 0.0f;\n\tint test = V_OUTOFBOUNDS;\n\tfor (const auto& pos : targets)\n\t{\n\t\ttargetVoxel = pos;\n\t\tif (_save->getTileEngine()->validateThrow(_action, originVoxel, targetVoxel, _save->getDepth(), &curvature, &test, forced))\n\t\t{\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (!forced && test == V_OUTOFBOUNDS) return test; //no line of fire\n\n\ttest = V_OUTOFBOUNDS;\n\tint tries = 0;\n\t// finally do a line calculation and store this trajectory, make sure it's valid.\n\twhile (test == V_OUTOFBOUNDS && tries < 100)\n\t{\n\t\t++tries;\n\t\tPosition deltas = targetVoxel;\n\t\t// apply some accuracy modifiers\n\t\t_trajectory.clear();\n\t\tif (_action.type == BA_THROW)\n\t\t{\n\t\t\tapplyAccuracy(originVoxel, &deltas, accuracy, true, false); //calling for best flavor\n\t\t\tdeltas -= targetVoxel;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tapplyAccuracy(originVoxel, &targetVoxel, accuracy, true, false); //arcing shot deviation\n\t\t\tdeltas = Position(0,0,0);\n\t\t}\n\n\n\t\ttest = _save->getTileEngine()->calculateParabolaVoxel(originVoxel, targetVoxel, true, &_trajectory, _action.actor, curvature, deltas);\n\t\tif (forced) return O_OBJECT; //fake hit\n\t\tPosition endPoint = getPositionFromEnd(_trajectory, ItemDropVoxelOffset).toTile();\n\t\tTile *endTile = _save->getTile(endPoint);\n\t\t// check if the item would land on a tile with a blocking object\n\t\tif (_action.type == BA_THROW\n\t\t\t&& endTile\n\t\t\t&& endTile->getMapData(O_OBJECT)\n\t\t\t&& endTile->getMapData(O_OBJECT)->getTUCost(MT_WALK) == Pathfinding::INVALID_MOVE_COST\n\t\t\t&& !(endTile->isBigWall() && (endTile->getMapData(O_OBJECT)->getBigWall()<1 || endTile->getMapData(O_OBJECT)->getBigWall()>3)))\n\t\t{\n\t\t\ttest = V_OUTOFBOUNDS;\n\t\t}\n\t}\n\treturn test;\n}\n\n/**\n * Calculates the new target in voxel space, based on the given accuracy modifier.\n * @param origin Start position of the trajectory in voxels.\n * @param target Endpoint of the trajectory in voxels.\n * @param accuracy Accuracy modifier.\n * @param keepRange Whether range affects accuracy.\n * @param extendLine should this line get extended to maximum distance?\n */\nvoid Projectile::applyAccuracy(Position origin, Position *target, double accuracy, bool keepRange, bool extendLine)\n{\n\tint xdiff = origin.x - target->x;\n\tint ydiff = origin.y - target->y;\n\tint zdiff = origin.z - target->z;\n\tdouble realDistance = sqrt((double)(xdiff*xdiff)+(double)(ydiff*ydiff)+(double)(zdiff*zdiff));\n\t// maxRange is the maximum range a projectile shall ever travel in voxel space\n\tdouble maxRange = keepRange?realDistance:16*1000; // 1000 tiles\n\tmaxRange = _action.type == BA_HIT?46:maxRange; // up to 2 tiles diagonally (as in the case of reaper v reaper)\n\n\tif (_action.type != BA_HIT)\n\t{\n\t\tint upperLimit, lowerLimit;\n\t\tint dropoff = _action.weapon->getRules()->calculateLimits(upperLimit, lowerLimit, _save->getDepth(), _action.type);\n\n\t\tdouble distance = realDistance / 16; // distance in tiles, but still fractional\n\t\tdouble accuracyLoss = 0.0;\n\t\tif (distance > upperLimit)\n\t\t{\n\t\t\taccuracyLoss = (dropoff * (distance - upperLimit)) / 100;\n\t\t}\n\t\telse if (distance < lowerLimit)\n\t\t{\n\t\t\taccuracyLoss = (dropoff * (lowerLimit - distance)) / 100;\n\t\t}\n\t\taccuracy = std::max(0.0, accuracy - accuracyLoss);\n\t}\n\n\tint xDist = abs(origin.x - target->x);\n\tint yDist = abs(origin.y - target->y);\n\tint zDist = abs(origin.z - target->z);\n\tint xyShift, zShift;\n\n\tif (Options::oxceUniformShootingSpread) // Uniform shooting spread\n\t{\n\t\tif (xDist <= yDist)\n\t\t\txyShift = xDist / 4 + yDist;\n\t\telse\n\t\t\txyShift = xDist + yDist / 4;\n\n\t\txyShift *= 0.839; // Constant to match average xyShift to vanilla\n\t}\n\telse\n\t{\n\t\tif (xDist / 2 <= yDist)\t\t\t\t//yes, we need to add some x/y non-uniformity\n\t\t\txyShift = xDist / 4 + yDist;\t//and don't ask why, please. it's The Commandment\n\t\telse\n\t\t\txyShift = (xDist + yDist) / 2;\t//that's uniform part of spreading\n\t}\n\n\tif (xyShift <= zDist)\t\t\t\t//slight z deviation\n\t\tzShift = xyShift / 2 + zDist;\n\telse\n\t\tzShift = xyShift + zDist / 2;\n\n\t// Apply penalty for having no LOS to target\n\tint noLOSAccuracyPenalty = _action.weapon->getRules()->getNoLOSAccuracyPenalty(_mod);\n\tif (noLOSAccuracyPenalty != -1)\n\t{\n\t\tTile *t = _save->getTile(target->toTile());\n\t\tif (t)\n\t\t{\n\t\t\tbool hasLOS = false;\n\t\t\tBattleUnit *bu = _action.actor;\n\t\t\tBattleUnit *targetUnit = t->getUnit(); // we can call TileEngine::visible() only if the target unit is on the same tile\n\n\t\t\tif (targetUnit)\n\t\t\t{\n\t\t\t\thasLOS = _save->getTileEngine()->visible(bu, t);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\thasLOS = _save->getTileEngine()->isTileInLOS(&_action, t, false);\n\t\t\t}\n\n\t\t\tif (!hasLOS)\n\t\t\t{\n\t\t\t\taccuracy = accuracy * noLOSAccuracyPenalty / 100;\n\t\t\t}\n\t\t}\n\t}\n\n\tint deviation = RNG::generate(0, 100) - (accuracy * 100);\n\n\tif (deviation >= 0)\n\t\tdeviation += 50;\t\t\t\t// add extra spread to \"miss\" cloud\n\telse\n\t\tdeviation += 10;\t\t\t\t//accuracy of 109 or greater will become 1 (tightest spread)\n\n\tdeviation = std::max(1, zShift * deviation / 200);\t//range ratio\n\n\tif (Options::oxceUniformShootingSpread)\n\t{\n\t\t// First, new target point is rolled as usual. Then, if it lies outside of outer circle (in square's corner)\n\t\t// it's rerolled inside inner circle\n\n\t\tconst double SECONDARY_SPREAD_COEFF = 0.85; // Inner spread circle diameter compared to outer\n\n\t\tbool resultShifted = false;\n\t\tint dX, dY;\n\n\t\tfor (int i = 0; i < 10; ++i) // Break from this cycle when proper target is found\n\t\t{\n\t\t\tdX = RNG::generate(0, deviation) - deviation / 2;\n\t\t\tdY = RNG::generate(0, deviation) - deviation / 2;\n\n\t\t\tint radiusSq = dX*dX + dY*dY;\n\t\t\tint deviateRadius = deviation / 2;\n\t\t\tint deviateRadiusSq = deviateRadius * deviateRadius;\n\n\t\t\tif (radiusSq <= deviateRadiusSq) break;  // If we inside of the spread circle - we're done!\n\n\t\t\tif (!resultShifted)\n\t\t\t{\n\t\t\t\tresultShifted = true;\n\t\t\t\tdeviation *= SECONDARY_SPREAD_COEFF; // Change spread radius for second+ attempts\n\t\t\t}\n\t\t}\n\n\t\ttarget->x += dX;\n\t\ttarget->y += dY;\n\t}\n\n\telse // Classic shooting spread\n\t{\n\t\ttarget->x += RNG::generate(0, deviation) - deviation / 2;\n\t\ttarget->y += RNG::generate(0, deviation) - deviation / 2;\n\t}\n\n\ttarget->z += RNG::generate(0, deviation / 2) / 2 - deviation / 8;\n\n\tif (extendLine)\n\t{\n\t\tdouble rotation, tilt;\n\t\trotation = atan2(double(target->y - origin.y), double(target->x - origin.x)) * 180 / M_PI;\n\t\ttilt = atan2(double(target->z - origin.z),\n\t\t\tsqrt(double(target->x - origin.x)*double(target->x - origin.x)+double(target->y - origin.y)*double(target->y - origin.y))) * 180 / M_PI;\n\t\t// calculate new target\n\t\t// this new target can be very far out of the map, but we don't care about that right now\n\t\tdouble cos_fi = cos(Deg2Rad(tilt));\n\t\tdouble sin_fi = sin(Deg2Rad(tilt));\n\t\tdouble cos_te = cos(Deg2Rad(rotation));\n\t\tdouble sin_te = sin(Deg2Rad(rotation));\n\t\ttarget->x = (int)(origin.x + maxRange * cos_te * cos_fi);\n\t\ttarget->y = (int)(origin.y + maxRange * sin_te * cos_fi);\n\t\ttarget->z = (int)(origin.z + maxRange * sin_fi);\n\t}\n}\n\n/**\n * Moves further in the trajectory.\n * @return false if the trajectory is finished - no new position exists in the trajectory.\n */\nbool Projectile::move()\n{\n\tif (_position == 0)\n\t{\n\t\t_distanceMax = 0;\n\t\tfor (std::size_t i = 0; i < _trajectory.size(); ++i)\n\t\t{\n\t\t\t_distanceMax += TileEngine::trajectoryStepSize(_trajectory, i);\n\t\t}\n\t}\n\n\tfor (int i = 0; i < _speed; ++i)\n\t{\n\t\t_position++;\n\t\tif (_position == _trajectory.size())\n\t\t{\n\t\t\t_position--;\n\t\t\treturn false;\n\t\t}\n\n\t\t_distance += TileEngine::trajectoryStepSize(_trajectory, _position);\n\n\t\tif (_vaporColor != -1 && _ammo && _action.type != BA_THROW)\n\t\t{\n\t\t\taddVaporCloud();\n\t\t}\n\t}\n\treturn true;\n}\n\n/**\n * Get Position at offset from start from trajectory vector.\n * @param trajectory Vector that have trajectory.\n * @param pos Offset counted from begining of trajectory.\n * @return Position in voxel space.\n */\nPosition Projectile::getPositionFromStart(const std::vector<Position>& trajectory, int pos)\n{\n\tif (pos >= 0 && pos < (int)trajectory.size())\n\t\treturn trajectory.at(pos);\n\telse if (pos < 0)\n\t\treturn trajectory.at(0);\n\telse\n\t\treturn trajectory.at(trajectory.size() - 1);\n}\n\n/**\n * Get Position at offset from start from trajectory vector.\n * @param trajectory Vector that have trajectory.\n * @param pos Offset counted from ending of trajectory.\n * @return Position in voxel space.\n */\nPosition Projectile::getPositionFromEnd(const std::vector<Position>& trajectory, int pos)\n{\n\treturn getPositionFromStart(trajectory, trajectory.size() + pos - 1);\n}\n\n/**\n * Gets the current position in voxel space.\n * @param offset Offset.\n * @return Position in voxel space.\n */\nPosition Projectile::getPosition(int offset) const\n{\n\treturn getPositionFromStart(_trajectory, (int)_position + offset);\n}\n\n/**\n * Gets a particle reference from the projectile surfaces.\n * @param i Index.\n * @return Particle id.\n */\nint Projectile::getParticle(int i) const\n{\n\tif (_bulletSprite != Mod::NO_SURFACE)\n\t\treturn _bulletSprite + i;\n\telse\n\t\treturn Mod::NO_SURFACE;\n}\n\n/**\n * Gets the project tile item.\n * Returns 0 when there is no item thrown.\n * @return Pointer to BattleItem.\n */\nBattleItem *Projectile::getItem() const\n{\n\tif (_action.type == BA_THROW)\n\t\treturn _action.weapon;\n\telse\n\t\treturn 0;\n}\n\n/**\n * Skips to the end of the trajectory.\n */\nvoid Projectile::skipTrajectory()\n{\n\twhile (move());\n}\n\n/**\n * Gets the Position of origin for the projectile\n * @return origin as a tile position.\n */\nPosition Projectile::getOrigin() const\n{\n\t// instead of using the actor's position, we'll use the voxel origin translated to a tile position\n\t// this is a workaround for large units.\n\treturn _trajectory.front().toTile();\n}\n\n/**\n * Gets the INTENDED target for this projectile\n * it is important to note that we do not use the final position of the projectile here,\n * but rather the targetted tile\n * @return target as a tile position.\n */\nPosition Projectile::getTarget() const\n{\n\treturn _action.target;\n}\n\n/**\n * Gets distances that projectile have traveled until now.\n * @return Returns traveled distance.\n */\nfloat Projectile::getDistance() const\n{\n\treturn _distance;\n}\n\n/**\n * Is this projectile drawn back to front or front to back?\n * @return return if this is to be drawn in reverse order.\n */\nbool Projectile::isReversed() const\n{\n\treturn _reversed;\n}\n\n/**\n * adds a cloud of vapor at the projectile's current position.\n */\nvoid Projectile::addVaporCloud()\n{\n\tRNG::RandomState rng = RNG::globalRandomState().subSequence();\n\tif (rng.percent(_vaporProbability) == false)\n\t{\n\t\treturn;\n\t}\n\n\tPosition subvoxelForwardDirection;\n\tPosition subvoxelRightDirection;\n\tPosition subvoxelUpDirection;\n\n\tauto voxelPos = getPosition();\n\tauto subvoxelPosFrom = getPosition(-4) * Particle::SubVoxelAccuracy;\n\tauto subvoxelPosTo = getPosition(+4) * Particle::SubVoxelAccuracy;\n\tauto subvoxelVector = subvoxelPosTo - subvoxelPosFrom;\n\n\tif (subvoxelVector == Position())\n\t{\n\t\t// strange trajectory, use fixed directions\n\t\tsubvoxelForwardDirection.x = Particle::SubVoxelAccuracy;\n\t\tsubvoxelRightDirection.y = Particle::SubVoxelAccuracy;\n\t\tsubvoxelUpDirection.z = Particle::SubVoxelAccuracy;\n\t}\n\telse if (std::abs(subvoxelVector.x) < 2 &&std::abs(subvoxelVector.y) < 2)\n\t{\n\t\t// straight up trajectory\n\t\tsubvoxelForwardDirection.z = Particle::SubVoxelAccuracy;\n\t\tsubvoxelRightDirection.y = Particle::SubVoxelAccuracy;\n\t\tsubvoxelUpDirection.x = - Particle::SubVoxelAccuracy;\n\t}\n\telse\n\t{\n\t\t// normalize vectors\n\t\tsubvoxelForwardDirection = VectNormalize(subvoxelVector, Particle::SubVoxelAccuracy);\n\n\t\tsubvoxelUpDirection.z = Particle::SubVoxelAccuracy;\n\n\t\tsubvoxelRightDirection = VectNormalize(VectCrossProduct(subvoxelUpDirection, subvoxelForwardDirection, Particle::SubVoxelAccuracy), Particle::SubVoxelAccuracy);\n\n\t\tsubvoxelUpDirection = VectCrossProduct(subvoxelForwardDirection, subvoxelRightDirection, Particle::SubVoxelAccuracy);\n\t}\n\n\tModScript::VaporParticleAmmo::Worker worker {\n\t\t_action.weapon,\n\t\t_ammo,\n\t\t_vaporDensity,\n\t\t(int)(_distance * Particle::SubVoxelAccuracy),\n\t\t(int)(_distanceMax * Particle::SubVoxelAccuracy),\n\t\tsubvoxelForwardDirection,\n\t\tsubvoxelRightDirection,\n\t\tsubvoxelUpDirection,\n\t\t&rng\n\t};\n\n\tauto tilePos = voxelPos.toTile();\n\tfor (int i = 0; i != _vaporDensity; ++i)\n\t{\n\t\tModScript::VaporParticleAmmo::Output arg = {\n\t\t\t_vaporColor, // \"vapor_color\",\n\t\t\tPosition{ }, // \"subvoxel_offset\",\n\t\t\tPosition{ }, // \"subvoxel_velocity\",\n\t\t\tPosition{ }, // \"subvoxel_acceleration\",\n\t\t\tParticle::SubVoxelAccuracy / 2, // \"subvoxel_drift\",\n\t\t\trng.generate(48, 224), // \"particle_density\",\n\t\t\trng.generate(32, 44), // \"particle_lifetime\",\n\t\t\ti, // \"particle_number\",\n\t\t};\n\n\t\tworker.execute(_ammo->getRules()->getScript<ModScript::VaporParticleAmmo>(), arg);\n\t\tworker.execute(_action.weapon->getRules()->getScript<ModScript::VaporParticleWeapon>(), arg);\n\n\t\tauto varporColor = std::get<0>(arg.data);\n\t\tauto subVoxelOffset = std::get<1>(arg.data);\n\t\tauto subVoxelVelocity = std::get<2>(arg.data);\n\t\tauto subVoxelAcceleration = std::get<3>(arg.data);\n\t\tauto drift = std::get<4>(arg.data);\n\t\tauto density = std::get<5>(arg.data);\n\t\tauto particleLifetime = std::get<6>(arg.data);\n\n\t\tUint8 size = 0;\n\t\t//size is initialized at 0\n\t\tif (density < 100)\n\t\t{\n\t\t\tsize = 3;\n\t\t}\n\t\telse if (density < 125)\n\t\t{\n\t\t\tsize = 2;\n\t\t}\n\t\telse if (density < 150)\n\t\t{\n\t\t\tsize = 1;\n\t\t}\n\n\t\tif (varporColor >= 0)\n\t\t{\n\t\t\tParticle particle = Particle(voxelPos, subVoxelOffset, subVoxelVelocity, subVoxelAcceleration, drift, varporColor, particleLifetime, size);\n\t\t\tPosition tileOffset = particle.updateScreenPosition();\n\t\t\t_save->getBattleGame()->getMap()->addVaporParticle(tilePos + tileOffset, particle);\n\t\t}\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/Projectile.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <vector>\n#include \"Position.h\"\n#include \"BattlescapeGame.h\"\n\nnamespace OpenXcom\n{\n\nclass BattleItem;\nclass SavedBattleGame;\nclass Surface;\nclass Tile;\nclass Mod;\n\n/**\n * A class that represents a projectile. Map is the owner of an instance of this class during its short life.\n * It calculates its own trajectory and then moves along this pre-calculated trajectory in voxel space.\n */\nclass Projectile\n{\npublic:\n\t/// Offset of voxel path where item should be drop.\n\tstatic const int ItemDropVoxelOffset = -2;\n\n\t/// Get Position at offset from start from trajectory vector.\n\tstatic Position getPositionFromStart(const std::vector<Position>& trajectory, int pos);\n\t/// Get Position at offset from end from trajectory vector.\n\tstatic Position getPositionFromEnd(const std::vector<Position>& trajectory, int pos);\n\nprivate:\n\tMod *_mod;\n\tSavedBattleGame *_save;\n\tBattleAction _action;\n\tconst BattleItem* _ammo = nullptr;\n\tPosition _origin, _targetVoxel;\n\tstd::vector<Position> _trajectory;\n\tsize_t _position;\n\tfloat _distance;\n\tfloat _distanceMax;\n\tint _speed;\n\tint _bulletSprite;\n\tbool _reversed;\n\tint _vaporColor, _vaporDensity, _vaporProbability;\n\tvoid applyAccuracy(Position origin, Position *target, double accuracy, bool keepRange, bool extendLine);\npublic:\n\t/// Creates a new Projectile.\n\tProjectile(Mod *mod, SavedBattleGame *save, BattleAction action, Position origin, Position target, BattleItem *ammo);\n\t/// Cleans up the Projectile.\n\t~Projectile();\n\t/// Calculates the trajectory for a straight path.\n\tint calculateTrajectory(double accuracy);\n\tint calculateTrajectory(double accuracy, const Position& originVoxel, bool excludeUnit = true);\n\t/// Calculates the trajectory for a curved path.\n\tint calculateThrow(double accuracy);\n\t/// Moves the projectile one step in its trajectory.\n\tbool move();\n\t/// Gets the current position in voxel space.\n\tPosition getPosition(int offset = 0) const;\n\t/// Gets the two last position in voxel space.\n\tLastPositions getLastPositions(int offset = 0) const { return LastPositions(getPosition(offset), getPosition(offset + ItemDropVoxelOffset)); }\n\t/// Gets a particle from the particle array.\n\tint getParticle(int i) const;\n\t/// Gets the item.\n\tBattleItem *getItem() const;\n\t/// Skips the bullet flight.\n\tvoid skipTrajectory();\n\t/// Gets the Position of origin for the projectile.\n\tPosition getOrigin() const;\n\t/// Gets the targetted tile for the projectile.\n\tPosition getTarget() const;\n\t/// Gets the distance that projectile traveled.\n\tfloat getDistance() const;\n\t/// Is this projectile being drawn back-to-front or front-to-back?\n\tbool isReversed() const;\n\t/// adds a cloud of particles at the projectile's location\n\tvoid addVaporCloud();\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/ProjectileFlyBState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <algorithm>\n#include \"ProjectileFlyBState.h\"\n#include \"ExplosionBState.h\"\n#include \"Projectile.h\"\n#include \"TileEngine.h\"\n#include \"Map.h\"\n#include \"../Savegame/BattleUnit.h\"\n#include \"../Savegame/BattleItem.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"../Savegame/Tile.h\"\n#include \"../Savegame/HitLog.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/Sound.h\"\n#include \"../Engine/RNG.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"../Engine/Options.h\"\n#include \"AIModule.h\"\n#include \"Camera.h\"\n#include \"Explosion.h\"\n#include \"BattlescapeState.h\"\n#include \"../Savegame/BattleUnitStatistics.h\"\n#include \"../fmath.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Sets up an ProjectileFlyBState.\n */\nProjectileFlyBState::ProjectileFlyBState(BattlescapeGame *parent, BattleAction action, Position origin, int range) : BattleState(parent, action), _unit(0), _ammo(0), _origin(origin), _originVoxel(-1,-1,-1), _projectileImpact(0), _range(range), _initialized(false), _targetFloor(false)\n{\n}\n\nProjectileFlyBState::ProjectileFlyBState(BattlescapeGame *parent, BattleAction action) : BattleState(parent, action), _unit(0), _ammo(0), _origin(action.actor->getPosition()), _originVoxel(-1,-1,-1), _projectileImpact(0), _range(0), _initialized(false), _targetFloor(false)\n{\n}\n\n/**\n * Deletes the ProjectileFlyBState.\n */\nProjectileFlyBState::~ProjectileFlyBState()\n{\n}\n\n/**\n * Initializes the sequence:\n * - checks if the shot is valid,\n * - calculates the base accuracy.\n */\nvoid ProjectileFlyBState::init()\n{\n\tif (_initialized) return;\n\t_initialized = true;\n\n\tBattleItem *weapon = _action.weapon;\n\n\tif (!weapon) // can't shoot without weapon\n\t{\n\t\t_parent->popState();\n\t\treturn;\n\t}\n\n\tif (!_parent->getSave()->getTile(_action.target)) // invalid target position\n\t{\n\t\t_parent->popState();\n\t\treturn;\n\t}\n\n\t//test TU only on first lunch waypoint or normal shoot\n\tif (_range == 0 && !_action.haveTU(&_action.result))\n\t{\n\t\t_parent->popState();\n\t\treturn;\n\t}\n\n\t_unit = _action.actor;\n\n\tbool reactionShoot = _unit->getFaction() != _parent->getSave()->getSide();\n\tif (_action.type != BA_THROW)\n\t{\n\t\t_ammo = _action.weapon->getAmmoForAction(_action.type, reactionShoot ? nullptr : &_action.result);\n\t\tif (!_ammo)\n\t\t{\n\t\t\t_parent->popState();\n\t\t\treturn;\n\t\t}\n\t}\n\n\tif (_unit->isOut() || _unit->isOutThresholdExceed())\n\t{\n\t\t// something went wrong - we can't shoot when dead or unconscious, or if we're about to fall over.\n\t\t_parent->popState();\n\t\treturn;\n\t}\n\n\t// reaction fire\n\tif (reactionShoot)\n\t{\n\t\tBattleUnit* target = _parent->getSave()->getTile(_action.target)->getUnit();\n\t\t// target is dead: cancel the shot.\n\t\tif (!target || target->isOut() || target->isOutThresholdExceed() || target != _parent->getSave()->getSelectedUnit())\n\t\t{\n\t\t\t_parent->popState();\n\t\t\treturn;\n\t\t}\n\t\t_unit->lookAt(_action.target, _unit->getTurretType() != -1);\n\t\twhile (_unit->getStatus() == STATUS_TURNING)\n\t\t{\n\t\t\t_unit->turn(_unit->getTurretType() != -1);\n\t\t}\n\t}\n\n\tTile *endTile = _parent->getSave()->getTile(_action.target);\n\tint distanceSq = _action.actor->distance3dToPositionSq(_action.target);\n\tbool isPlayer = _parent->getSave()->getSide() == FACTION_PLAYER;\n\tif (isPlayer) _parent->getMap()->resetObstacles();\n\tswitch (_action.type)\n\t{\n\tcase BA_SNAPSHOT:\n\tcase BA_AIMEDSHOT:\n\tcase BA_AUTOSHOT:\n\tcase BA_LAUNCH:\n\t\tif (weapon->getRules()->isOutOfRange(distanceSq))\n\t\t{\n\t\t\t// out of range\n\t\t\t_action.result = \"STR_OUT_OF_RANGE\";\n\t\t\t_parent->popState();\n\t\t\treturn;\n\t\t}\n\t\tbreak;\n\tcase BA_THROW:\n\t\tif (!validThrowRange(&_action, _parent->getTileEngine()->getOriginVoxel(_action, 0), _parent->getSave()->getTile(_action.target), _parent->getSave()->getDepth()))\n\t\t{\n\t\t\t// out of range\n\t\t\t_action.result = \"STR_OUT_OF_RANGE\";\n\t\t\t_parent->popState();\n\t\t\treturn;\n\t\t}\n\t\tif (endTile &&\n\t\t\tendTile->getTerrainLevel() == -24 &&\n\t\t\tendTile->getPosition().z + 1 < _parent->getSave()->getMapSizeZ())\n\t\t{\n\t\t\t_action.target.z += 1;\n\t\t}\n\t\tbreak;\n\tdefault:\n\t\t_parent->popState();\n\t\treturn;\n\t}\n\n\t// Check for close quarters combat\n\tif (_parent->getMod()->getEnableCloseQuartersCombat() && _action.type != BA_THROW && _action.type != BA_LAUNCH && _unit->getTurretType() == -1 && !_unit->getArmor()->getIgnoresMeleeThreat())\n\t{\n\t\t// Start by finding 'targets' for the check\n\t\tstd::vector<BattleUnit*> closeQuartersTargetList;\n\t\tint surroundingTilePositions [8][2] = {\n\t\t\t{0, -1}, // north (-y direction)\n\t\t\t{1, -1}, // northeast\n\t\t\t{1, 0}, // east (+ x direction)\n\t\t\t{1, 1}, // southeast\n\t\t\t{0, 1}, // south (+y direction)\n\t\t\t{-1, 1}, // southwest\n\t\t\t{-1, 0}, // west (-x direction)\n\t\t\t{-1, -1}}; // northwest\n\t\tfor (int dir = 0; dir < 8; dir++)\n\t\t{\n\t\t\tPosition tileToCheck = _origin;\n\t\t\ttileToCheck.x += surroundingTilePositions[dir][0];\n\t\t\ttileToCheck.y += surroundingTilePositions[dir][1];\n\n\t\t\tif (_parent->getSave()->getTile(tileToCheck)) // Make sure the tile is in bounds\n\t\t\t{\n\t\t\t\tBattleUnit* closeQuartersTarget = _parent->getSave()->selectUnit(tileToCheck);\n\t\t\t\t// Variable for LOS check\n\t\t\t\tint checkDirection = _parent->getTileEngine()->getDirectionTo(tileToCheck, _unit->getPosition());\n\t\t\t\tif (closeQuartersTarget && _unit->getFaction() != closeQuartersTarget->getFaction() // Unit must exist and not be same faction\n\t\t\t\t\t&& closeQuartersTarget->getArmor()->getCreatesMeleeThreat() // Unit must be valid defender, 2x2 default false here\n\t\t\t\t\t&& closeQuartersTarget->getTimeUnits() >= _parent->getMod()->getCloseQuartersTuCostGlobal() // Unit must have enough TUs\n\t\t\t\t\t&& closeQuartersTarget->getEnergy() >= _parent->getMod()->getCloseQuartersEnergyCostGlobal() // Unit must have enough Energy\n\t\t\t\t\t&& _parent->getTileEngine()->validMeleeRange(closeQuartersTarget, _unit, checkDirection) // Unit must be able to see the unit attempting to fire\n\t\t\t\t\t&& !(_unit->getFaction() == FACTION_PLAYER && closeQuartersTarget->getFaction() == FACTION_NEUTRAL) // Civilians don't inhibit player\n\t\t\t\t\t&& !(_unit->getFaction() == FACTION_NEUTRAL && closeQuartersTarget->getFaction() == FACTION_PLAYER)) // Player doesn't inhibit civilians\n\t\t\t\t{\n\t\t\t\t\tif (RNG::percent(_parent->getMod()->getCloseQuartersSneakUpGlobal()))\n\t\t\t\t\t{\n\t\t\t\t\t\tif (_unit->getFaction() == FACTION_HOSTILE) // alien attacker (including mind-controlled xcom)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (!closeQuartersTarget->hasVisibleUnit(_unit))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcontinue; // the xcom/civilian victim *DOES NOT SEE* the attacker and cannot defend itself\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse // xcom/civilian attacker (including mind-controlled aliens)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (_unit->getTurnsSinceSpotted() > 1)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcontinue; // the aliens (as a collective) *ARE NOT AWARE* of the attacker and cannot defend themselves\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tcloseQuartersTargetList.push_back(closeQuartersTarget);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (!closeQuartersTargetList.empty())\n\t\t{\n\t\t\tint closeQuartersFailedResults[6] = {\n\t\t\t\t0,   // Fire straight down\n\t\t\t\t0,   // Fire straight up\n\t\t\t\t6,   // Fire left 90 degrees\n\t\t\t\t7,   // Fire left 45 degrees\n\t\t\t\t1,   // Fire right 45 degrees\n\t\t\t\t2 }; // Fire right 90 degrees\n\n\t\t\tfor (auto* bu : closeQuartersTargetList)\n\t\t\t{\n\t\t\t\tBattleActionAttack attack;\n\t\t\t\tattack.type = BA_CQB;\n\t\t\t\tattack.attacker = _action.actor;\n\t\t\t\tattack.weapon_item = _action.weapon;\n\t\t\t\tattack.damage_item = _action.weapon;\n\n\t\t\t\t// Roll for the check\n\t\t\t\tif (!_parent->getTileEngine()->meleeAttack(attack, bu))\n\t\t\t\t{\n\t\t\t\t\t// Failed the check, roll again to see result\n\t\t\t\t\tif (_parent->getSave()->getSide() == FACTION_PLAYER) // Only show message during player's turn\n\t\t\t\t\t{\n\t\t\t\t\t\t_action.result = \"STR_FAILED_CQB_CHECK\";\n\t\t\t\t\t}\n\t\t\t\t\tint rng = RNG::generate(0, 5);\n\t\t\t\t\tPosition closeQuartersFailedNewTarget = _unit->getPosition();\n\t\t\t\t\tif (rng == 1)\n\t\t\t\t\t{\n\t\t\t\t\t\tcloseQuartersFailedNewTarget.z += 1;\n\t\t\t\t\t}\n\t\t\t\t\telse if (rng > 1)\n\t\t\t\t\t{\n\t\t\t\t\t\tint newFacing = (_unit->getDirection() + closeQuartersFailedResults[rng]) % 8;\n\t\t\t\t\t\tcloseQuartersFailedNewTarget.x += surroundingTilePositions[newFacing][0];\n\t\t\t\t\t\tcloseQuartersFailedNewTarget.y += surroundingTilePositions[newFacing][1];\n\t\t\t\t\t}\n\n\t\t\t\t\t// Make sure the new target is in bounds\n\t\t\t\t\tif (!_parent->getSave()->getTile(closeQuartersFailedNewTarget))\n\t\t\t\t\t{\n\t\t\t\t\t\t// Default to firing at our feet\n\t\t\t\t\t\tcloseQuartersFailedNewTarget = _unit->getPosition();\n\t\t\t\t\t}\n\n\t\t\t\t\t// Turn to look at new target\n\t\t\t\t\t_action.target = closeQuartersFailedNewTarget;\n\t\t\t\t\t_unit->lookAt(_action.target, _unit->getTurretType() != -1);\n\t\t\t\t\twhile (_unit->getStatus() == STATUS_TURNING)\n\t\t\t\t\t{\n\t\t\t\t\t\t_unit->turn(_unit->getTurretType() != -1);\n\t\t\t\t\t}\n\n\t\t\t\t\t// We're done, spend TUs and Energy; and don't check remaining CQB candidates anymore\n\t\t\t\t\tbu->spendTimeUnits(_parent->getMod()->getCloseQuartersTuCostGlobal());\n\t\t\t\t\tbu->spendEnergy(_parent->getMod()->getCloseQuartersEnergyCostGlobal());\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tbool forceEnableObstacles = false;\n\tif (_action.type == BA_LAUNCH || (Options::forceFire && _parent->getSave()->isCtrlPressed(true) && isPlayer) || !_parent->getPanicHandled())\n\t{\n\t\t// target nothing, targets the middle of the tile\n\t\t_targetVoxel = _action.target.toVoxel() + TileEngine::voxelTileCenter;\n\t\tif (_action.type == BA_LAUNCH)\n\t\t{\n\t\t\tif (_targetFloor)\n\t\t\t{\n\t\t\t\t// launched missiles with two waypoints placed on the same tile: target the floor.\n\t\t\t\t_targetVoxel.z -= 10;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// launched missiles go slightly higher than the middle.\n\t\t\t\t_targetVoxel.z += 4;\n\t\t\t}\n\t\t}\n\t}\n\telse if (!_action.weapon->getArcingShot(_action.type))\n\t{\n\t\t// determine the target voxel.\n\t\t// aim at the center of the unit, the object, the walls or the floor (in that priority)\n\t\t// if there is no LOF to the center, try elsewhere (more outward).\n\t\t// Store this target voxel.\n\t\tTile *targetTile = _parent->getSave()->getTile(_action.target);\n\t\tPosition originVoxel = _parent->getTileEngine()->getOriginVoxel(_action, _parent->getSave()->getTile(_origin));\n\t\tif (targetTile->getUnit() &&\n\t\t\t((_unit->getFaction() != FACTION_PLAYER) ||\n\t\t\ttargetTile->getUnit()->getVisible()))\n\t\t{\n\t\t\tif (_origin == _action.target || targetTile->getUnit() == _unit)\n\t\t\t{\n\t\t\t\t// don't shoot at yourself but shoot at the floor\n\t\t\t\t_targetVoxel = _action.target.toVoxel() + Position(8, 8, 0);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tbool foundLoF = _parent->getTileEngine()->canTargetUnit(&originVoxel, targetTile, &_targetVoxel, _unit, isPlayer);\n\n\t\t\t\tif (!foundLoF && Options::oxceEnableOffCentreShooting)\n\t\t\t\t{\n\t\t\t\t\t// If we can't target from the standard shooting position, try a bit left and right from the centre.\n\t\t\t\t\tfor (auto& rel_pos : { BattleActionOrigin::LEFT, BattleActionOrigin::RIGHT })\n\t\t\t\t\t{\n\t\t\t\t\t\t_action.relativeOrigin = rel_pos;\n\t\t\t\t\t\toriginVoxel = _parent->getTileEngine()->getOriginVoxel(_action, _parent->getSave()->getTile(_origin));\n\t\t\t\t\t\tfoundLoF = _parent->getTileEngine()->canTargetUnit(&originVoxel, targetTile, &_targetVoxel, _unit, isPlayer);\n\t\t\t\t\t\tif (foundLoF)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (!foundLoF)\n\t\t\t\t{\n\t\t\t\t\t// Failed to find LOF\n\t\t\t\t\t_action.relativeOrigin = BattleActionOrigin::CENTRE; // reset to the normal origin\n\n\t\t\t\t\t_targetVoxel = TileEngine::invalid.toVoxel(); // out of bounds, even after voxel to tile calculation.\n\t\t\t\t\tif (isPlayer)\n\t\t\t\t\t{\n\t\t\t\t\t\tforceEnableObstacles = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse if (targetTile->getMapData(O_OBJECT) != 0)\n\t\t{\n\t\t\tif (!_parent->getTileEngine()->canTargetTile(&originVoxel, targetTile, O_OBJECT, &_targetVoxel, _unit, isPlayer))\n\t\t\t{\n\t\t\t\t_targetVoxel = _action.target.toVoxel() + Position(8, 8, 10);\n\t\t\t}\n\t\t}\n\t\telse if (targetTile->getMapData(O_NORTHWALL) != 0)\n\t\t{\n\t\t\tif (!_parent->getTileEngine()->canTargetTile(&originVoxel, targetTile, O_NORTHWALL, &_targetVoxel, _unit, isPlayer))\n\t\t\t{\n\t\t\t\t_targetVoxel = _action.target.toVoxel() + Position(8, 0, 9);\n\t\t\t}\n\t\t}\n\t\telse if (targetTile->getMapData(O_WESTWALL) != 0)\n\t\t{\n\t\t\tif (!_parent->getTileEngine()->canTargetTile(&originVoxel, targetTile, O_WESTWALL, &_targetVoxel, _unit, isPlayer))\n\t\t\t{\n\t\t\t\t_targetVoxel = _action.target.toVoxel() + Position(0, 8, 9);\n\t\t\t}\n\t\t}\n\t\telse if (targetTile->getMapData(O_FLOOR) != 0)\n\t\t{\n\t\t\tif (!_parent->getTileEngine()->canTargetTile(&originVoxel, targetTile, O_FLOOR, &_targetVoxel, _unit, isPlayer))\n\t\t\t{\n\t\t\t\t_targetVoxel = _action.target.toVoxel() + Position(8, 8, 2);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// dummy attempt (only to highlight obstacles)\n\t\t\t_parent->getTileEngine()->canTargetTile(&originVoxel, targetTile, MapData::O_DUMMY, &_targetVoxel, _unit, isPlayer);\n\n\t\t\t// target nothing, targets the middle of the tile\n\t\t\t_targetVoxel = _action.target.toVoxel() + TileEngine::voxelTileCenter;\n\t\t}\n\t}\n\n\tif (createNewProjectile())\n\t{\n\t\tauto* conf = weapon->getActionConf(_action.type);\n\t\tif (_parent->getMap()->isAltPressed() || (conf && !conf->followProjectiles))\n\t\t{\n\t\t\t// temporarily turn off camera following projectiles to prevent annoying flashing effects (e.g. on minigun-like weapons)\n\t\t\t_parent->getMap()->setFollowProjectile(false);\n\t\t}\n\t\tif (_range == 0) _action.spendTU();\n\t\t_parent->getMap()->setCursorType(CT_NONE);\n\t\t_parent->getMap()->getCamera()->stopMouseScrolling();\n\t\t_parent->getMap()->disableObstacles();\n\t}\n\telse if (isPlayer && (_targetVoxel.z >= 0 || forceEnableObstacles))\n\t{\n\t\t_parent->getMap()->enableObstacles();\n\t}\n}\n\n/**\n * Tries to create a projectile sprite and add it to the map,\n * calculating its trajectory.\n * @return True, if the projectile was successfully created.\n */\nbool ProjectileFlyBState::createNewProjectile()\n{\n\t++_action.autoShotCounter;\n\n\t// Special handling for \"spray\" auto-attack, get target positions from the action's waypoints, starting from the back\n\tif (_action.sprayTargeting)\n\t{\n\t\t// Since we're just spraying, target the middle of the tile\n\t\t_targetVoxel = _action.waypoints.back();\n\t\tPosition targetPosition = _targetVoxel.toTile();\n\n\t\t// The waypoint targeting is possibly out of range of the gun, so move the voxel to the max range of the gun if it is\n\t\tint distanceSq = _action.actor->distance3dToPositionSq(targetPosition);\n\t\tif (_action.weapon->getRules()->isOutOfRange(distanceSq))\n\t\t{\n\t\t\tPosition actorPosition = _action.actor->getPosition();\n\t\t\tint maxRange = _action.weapon->getRules()->getMaxRange();\n\t\t\tint distance = (int)std::ceil(sqrt(float(distanceSq)));\n\t\t\t_targetVoxel = (actorPosition + (targetPosition - actorPosition) * maxRange / distance).toVoxel() + TileEngine::voxelTileCenter;\n\t\t\ttargetPosition = _targetVoxel.toTile();\n\t\t}\n\n\t\t// Turn at the end (to a potentially modified target position)\n\t\t_unit->lookAt(targetPosition, _unit->getTurretType() != -1);\n\t\twhile (_unit->getStatus() == STATUS_TURNING)\n\t\t{\n\t\t\t_unit->turn(_unit->getTurretType() != -1);\n\t\t}\n\n\t\t_action.waypoints.pop_back();\n\t}\n\n\t// create a new projectile\n\tProjectile *projectile = new Projectile(_parent->getMod(), _parent->getSave(), _action, _origin, _targetVoxel, _ammo);\n\n\t// add the projectile on the map\n\t_parent->getMap()->setProjectile(projectile);\n\n\t// set the speed of the state think cycle to 16 ms (roughly one think cycle per frame)\n\t_parent->setStateInterval(1000/60);\n\n\t// let it calculate a trajectory\n\t_projectileImpact = V_EMPTY;\n\n\tdouble accuracyDivider = 100.0;\n\t// berserking units are half as accurate\n\tif (!_parent->getPanicHandled())\n\t{\n\t\taccuracyDivider = 200.0;\n\t}\n\n\tBattleActionAttack attack = BattleActionAttack::GetAferShoot(_action, _ammo);\n\tif (_action.type == BA_THROW)\n\t{\n\t\t_projectileImpact = projectile->calculateThrow(BattleUnit::getFiringAccuracy(attack, _parent->getMod()) / accuracyDivider);\n\t\tconst RuleItem *ruleItem = _action.weapon->getRules();\n\t\tif (_projectileImpact == V_FLOOR || _projectileImpact == V_UNIT || _projectileImpact == V_OBJECT)\n\t\t{\n\t\t\tif (_unit->getFaction() != FACTION_PLAYER && ruleItem->isGrenadeOrProxy())\n\t\t\t{\n\t\t\t\t_action.weapon->setFuseTimer(ruleItem->getFuseTimerDefault());\n\t\t\t}\n\t\t\t_action.weapon->moveToOwner(nullptr);\n\t\t\tif (_action.weapon->getGlow())\n\t\t\t{\n\t\t\t\t_parent->getTileEngine()->calculateLighting(LL_UNITS, _unit->getPosition());\n\t\t\t\t_parent->getTileEngine()->calculateFOV(_unit->getPosition(), _action.weapon->getGlowRange(), false);\n\t\t\t}\n\t\t\t_parent->getMod()->getSoundByDepth(_parent->getDepth(), Mod::ITEM_THROW)->play(-1, _parent->getMap()->getSoundAngle(_unit->getPosition()));\n\t\t\tif (!Mod::EXTENDED_EXPERIENCE_AWARD_SYSTEM)\n\t\t\t{\n\t\t\t\t// vanilla compatibility (throwing anything anywhere gives throwing exp)\n\t\t\t\t_unit->addThrowingExp();\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// unable to throw here\n\t\t\tdelete projectile;\n\t\t\t_parent->getMap()->setProjectile(0);\n\t\t\t_action.result = \"STR_UNABLE_TO_THROW_HERE\";\n\t\t\t_action.clearTU();\n\t\t\t_parent->popState();\n\t\t\treturn false;\n\t\t}\n\t}\n\telse if (_action.weapon->getArcingShot(_action.type)) // special code for the \"spit\" trajectory\n\t{\n\t\t_projectileImpact = projectile->calculateThrow(BattleUnit::getFiringAccuracy(attack, _parent->getMod()) / accuracyDivider);\n\t\tif (_projectileImpact != V_EMPTY && _projectileImpact != V_OUTOFBOUNDS)\n\t\t{\n\t\t\t// set the soldier in an aiming position\n\t\t\t_unit->aim(true);\n\t\t\t// and we have a lift-off\n\t\t\tif (_ammo->getRules()->getFireSound() != Mod::NO_SOUND)\n\t\t\t{\n\t\t\t\t_parent->getMod()->getSoundByDepth(_parent->getDepth(), _ammo->getRules()->getFireSound())->play(-1, _parent->getMap()->getSoundAngle(_unit->getPosition()));\n\t\t\t}\n\t\t\telse if (_action.weapon->getRules()->getFireSound() != Mod::NO_SOUND)\n\t\t\t{\n\t\t\t\t_parent->getMod()->getSoundByDepth(_parent->getDepth(), _action.weapon->getRules()->getFireSound())->play(-1, _parent->getMap()->getSoundAngle(_unit->getPosition()));\n\t\t\t}\n\t\t\tif (_action.type != BA_LAUNCH)\n\t\t\t{\n\t\t\t\t_action.weapon->spendAmmoForAction(_action.type, _parent->getSave());\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// no line of fire\n\t\t\tdelete projectile;\n\t\t\t_parent->getMap()->setProjectile(0);\n\t\t\tif (_parent->getPanicHandled())\n\t\t\t{\n\t\t\t\t_action.result = \"STR_NO_TRAJECTORY\";\n\t\t\t}\n\t\t\t_unit->abortTurn();\n\t\t\t_parent->popState();\n\t\t\treturn false;\n\t\t}\n\t}\n\telse\n\t{\n\t\tif (_originVoxel != TileEngine::invalid)\n\t\t{\n\t\t\t_projectileImpact = projectile->calculateTrajectory(BattleUnit::getFiringAccuracy(attack, _parent->getMod()) / accuracyDivider, _originVoxel, false);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_projectileImpact = projectile->calculateTrajectory(BattleUnit::getFiringAccuracy(attack, _parent->getMod()) / accuracyDivider);\n\t\t}\n\t\tif (_targetVoxel != TileEngine::invalid.toVoxel() && (_projectileImpact != V_EMPTY || _action.type == BA_LAUNCH))\n\t\t{\n\t\t\t// set the soldier in an aiming position\n\t\t\t_unit->aim(true);\n\t\t\t// and we have a lift-off\n\t\t\tif (_ammo->getRules()->getFireSound() != Mod::NO_SOUND)\n\t\t\t{\n\t\t\t\t_parent->getMod()->getSoundByDepth(_parent->getDepth(), _ammo->getRules()->getFireSound())->play(-1, _parent->getMap()->getSoundAngle(projectile->getOrigin()));\n\t\t\t}\n\t\t\telse if (_action.weapon->getRules()->getFireSound() != Mod::NO_SOUND)\n\t\t\t{\n\t\t\t\t_parent->getMod()->getSoundByDepth(_parent->getDepth(), _action.weapon->getRules()->getFireSound())->play(-1, _parent->getMap()->getSoundAngle(projectile->getOrigin()));\n\t\t\t}\n\t\t\tif (_action.type != BA_LAUNCH)\n\t\t\t{\n\t\t\t\t_action.weapon->spendAmmoForAction(_action.type, _parent->getSave());\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// no line of fire\n\t\t\tdelete projectile;\n\t\t\t_parent->getMap()->setProjectile(0);\n\t\t\tif (_parent->getPanicHandled())\n\t\t\t{\n\t\t\t\t_action.result = \"STR_NO_LINE_OF_FIRE\";\n\t\t\t}\n\t\t\t_unit->abortTurn();\n\t\t\t_parent->popState();\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tif (_action.type != BA_THROW && _action.type != BA_LAUNCH)\n\t\t_unit->getStatistics()->shotsFiredCounter++;\n\n\t// hit log - new bullet\n\tif (_action.actor)\n\t{\n\t\t_parent->getSave()->appendToHitLog(HITLOG_NEW_SHOT, _action.actor->getFaction());\n\t}\n\n\treturn true;\n}\n\n/**\n * Deinitialize the state.\n */\nvoid ProjectileFlyBState::deinit()\n{\n\t_parent->getMap()->setFollowProjectile(true); // turn back on when done shooting\n}\n\n/**\n * Animates the projectile (moves to the next point in its trajectory).\n * If the animation is finished the projectile sprite is removed from the map,\n * and this state is finished.\n */\nvoid ProjectileFlyBState::think()\n{\n\t/// checks if a weapon has any more shots to fire.\n\tauto noMoreShotsToShoot = [this]() { return !_action.weapon->haveNextShotsForAction(_action.type, _action.autoShotCounter) || !_action.weapon->getAmmoForAction(_action.type); };\n\n\t_parent->getSave()->getBattleState()->clearMouseScrollingState();\n\t/* TODO refactoring : store the projectile in this state, instead of getting it from the map each time? */\n\tif (_parent->getMap()->getProjectile() == 0)\n\t{\n\t\tbool hasFloor = _action.actor->haveNoFloorBelow() == false;\n\t\tbool unitCanFly = _action.actor->getMovementType() == MT_FLY;\n\n\t\tif (_action.weapon->haveNextShotsForAction(_action.type, _action.autoShotCounter)\n\t\t\t&& !_action.actor->isOut()\n\t\t\t&& _ammo->getAmmoQuantity() != 0\n\t\t\t&& (hasFloor || unitCanFly))\n\t\t{\n\t\t\tcreateNewProjectile();\n\t\t\tif (_action.cameraPosition.z != -1)\n\t\t\t{\n\t\t\t\t_parent->getMap()->getCamera()->setMapOffset(_action.cameraPosition);\n\t\t\t\t_parent->getMap()->invalidate();\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (_action.cameraPosition.z != -1 && _action.waypoints.size() <= 1)\n\t\t\t{\n\t\t\t\t_parent->getMap()->getCamera()->setMapOffset(_action.cameraPosition);\n\t\t\t\t_parent->getMap()->invalidate();\n\t\t\t}\n\t\t\tif (!_parent->getSave()->getUnitsFalling() && _parent->getPanicHandled())\n\t\t\t{\n\t\t\t\t_parent->getTileEngine()->checkReactionFire(_unit, _action);\n\t\t\t}\n\t\t\tif (!_unit->isOut())\n\t\t\t{\n\t\t\t\t_unit->abortTurn();\n\t\t\t}\n\t\t\tif (_parent->getSave()->getSide() == FACTION_PLAYER || _parent->getSave()->getDebugMode())\n\t\t\t{\n\t\t\t\t_parent->setupCursor();\n\t\t\t}\n\t\t\t_parent->convertInfected();\n\t\t\t_parent->popState();\n\t\t}\n\t}\n\telse\n\t{\n\t\tBattleActionAttack attack = BattleActionAttack::GetAferShoot(_action, _ammo);\n\t\tif (_action.type != BA_THROW && _ammo && _ammo->getRules()->getShotgunPellets() != 0)\n\t\t{\n\t\t\t// shotgun pellets move to their terminal location instantly as fast as possible\n\t\t\t_parent->getMap()->getProjectile()->skipTrajectory();\n\t\t}\n\t\tif (!_parent->getMap()->getProjectile()->move())\n\t\t{\n\t\t\t// impact !\n\t\t\tif (_action.type == BA_THROW)\n\t\t\t{\n\t\t\t\t_parent->getMap()->resetCameraSmoothing();\n\t\t\t\tPosition pos = _parent->getMap()->getProjectile()->getPosition(Projectile::ItemDropVoxelOffset).toTile();\n\t\t\t\tif (pos.y > _parent->getSave()->getMapSizeY())\n\t\t\t\t{\n\t\t\t\t\tpos.y--;\n\t\t\t\t}\n\t\t\t\tif (pos.x > _parent->getSave()->getMapSizeX())\n\t\t\t\t{\n\t\t\t\t\tpos.x--;\n\t\t\t\t}\n\n\t\t\t\t_parent->getMod()->getSoundByDepth(_parent->getDepth(), Mod::ITEM_DROP)->play(-1, _parent->getMap()->getSoundAngle(pos));\n\t\t\t\tconst RuleItem *ruleItem = _action.weapon->getRules();\n\t\t\t\tif (_action.weapon->fuseThrowEvent())\n\t\t\t\t{\n\t\t\t\t\tif (ruleItem->getBattleType() == BT_GRENADE || ruleItem->getBattleType() == BT_PROXIMITYGRENADE)\n\t\t\t\t\t{\n\t\t\t\t\t\t// it's a hot grenade to explode immediately\n\t\t\t\t\t\t_parent->statePushFront(new ExplosionBState(_parent, _parent->getMap()->getProjectile()->getLastPositions(Projectile::ItemDropVoxelOffset), attack));\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t_parent->getSave()->removeItem(_action.weapon);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t_parent->dropItem(pos, _action.weapon);\n\t\t\t\t\tif (_unit->getFaction() != FACTION_PLAYER && ruleItem->isGrenadeOrProxy())\n\t\t\t\t\t{\n\t\t\t\t\t\t_parent->getTileEngine()->setDangerZone(pos, ruleItem->getExplosionRadius(attack), _action.actor);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (_action.type == BA_LAUNCH && _action.waypoints.size() > 1 && _projectileImpact == V_EMPTY)\n\t\t\t{\n\t\t\t\t_origin = _action.waypoints.front();\n\t\t\t\t_action.waypoints.pop_front();\n\t\t\t\t_action.target = _action.waypoints.front();\n\t\t\t\t// launch the next projectile in the waypoint cascade\n\t\t\t\tProjectileFlyBState *nextWaypoint = new ProjectileFlyBState(_parent, _action, _origin, _range + _parent->getMap()->getProjectile()->getDistance());\n\t\t\t\tnextWaypoint->setOriginVoxel(_parent->getMap()->getProjectile()->getPosition(-1));\n\t\t\t\tif (_origin == _action.target)\n\t\t\t\t{\n\t\t\t\t\tnextWaypoint->targetFloor();\n\t\t\t\t}\n\t\t\t\t_parent->statePushNext(nextWaypoint);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tauto* tmpUnit = _parent->getSave()->getTile(_action.target)->getUnit();\n\t\t\t\tif (tmpUnit && tmpUnit != _unit)\n\t\t\t\t{\n\t\t\t\t\ttmpUnit->getStatistics()->shotAtCounter++; // Only counts for guns, not throws or launches\n\t\t\t\t}\n\n\t\t\t\t_parent->getMap()->resetCameraSmoothing();\n\t\t\t\tif (_action.type == BA_LAUNCH)\n\t\t\t\t{\n\t\t\t\t\t_action.weapon->spendAmmoForAction(_action.type, _parent->getSave());\n\t\t\t\t}\n\n\t\t\t\tif (_projectileImpact != V_OUTOFBOUNDS)\n\t\t\t\t{\n\t\t\t\t\tbool shotgun = _ammo && _ammo->getRules()->getShotgunPellets() != 0 && _ammo->getRules()->getDamageType()->isDirect();\n\t\t\t\t\tint offset = 0;\n\t\t\t\t\t// explosions impact not inside the voxel but two steps back (projectiles generally move 2 voxels at a time)\n\t\t\t\t\tif (_ammo && _ammo->getRules()->getExplosionRadius(attack) != 0 && _projectileImpact != V_UNIT)\n\t\t\t\t\t{\n\t\t\t\t\t\toffset = -2;\n\t\t\t\t\t}\n\n\t\t\t\t\t_parent->statePushFront(new ExplosionBState(\n\t\t\t\t\t\t_parent, _parent->getMap()->getProjectile()->getLastPositions(offset),\n\t\t\t\t\t\tattack, 0,\n\t\t\t\t\t\tnoMoreShotsToShoot(),\n\t\t\t\t\t\tshotgun ? 0 : _range + _parent->getMap()->getProjectile()->getDistance()\n\t\t\t\t\t));\n\n\t\t\t\t\tif (_projectileImpact == V_UNIT)\n\t\t\t\t\t{\n\t\t\t\t\t\tprojectileHitUnit(_parent->getMap()->getProjectile()->getPosition(offset));\n\t\t\t\t\t}\n\n\t\t\t\t\t// remember unit's original XP values, used for nerfing below\n\t\t\t\t\t_unit->rememberXP();\n\n\t\t\t\t\t// special shotgun behaviour: trace extra projectile paths, and add bullet hits at their termination points.\n\t\t\t\t\tif (shotgun)\n\t\t\t\t\t{\n\t\t\t\t\t\tint behaviorType = _ammo->getRules()->getShotgunBehaviorType();\n\t\t\t\t\t\tint spread = _ammo->getRules()->getShotgunSpread();\n\t\t\t\t\t\tint choke = _action.weapon->getRules()->getShotgunChoke();\n\t\t\t\t\t\tPosition firstPelletImpact = _parent->getMap()->getProjectile()->getPosition(-2);\n\t\t\t\t\t\tPosition originalTarget = _targetVoxel;\n\n\t\t\t\t\t\tint i = 1;\n\t\t\t\t\t\twhile (i != _ammo->getRules()->getShotgunPellets())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (behaviorType == 1)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// use impact location to determine spread (instead of originally targeted voxel), as long as it's not the same as the origin\n\t\t\t\t\t\t\t\tif (firstPelletImpact != _parent->getSave()->getTileEngine()->getOriginVoxel(_action, _parent->getSave()->getTile(_origin)))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t_targetVoxel = firstPelletImpact;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t_targetVoxel = originalTarget;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\n\t\t\t\t\t\t\tProjectile *proj = new Projectile(_parent->getMod(), _parent->getSave(), _action, _origin, _targetVoxel, _ammo);\n\n\t\t\t\t\t\t\t// let it trace to the point where it hits\n\t\t\t\t\t\t\tint secondaryImpact = V_EMPTY;\n\t\t\t\t\t\t\tif (behaviorType == 1)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// pellet spread based on spread and choke values\n\t\t\t\t\t\t\t\tsecondaryImpact = proj->calculateTrajectory(std::max(0.0, (1.0 - spread / 100.0) * choke / 100.0));\n\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// pellet spread based on spread and firing accuracy with diminishing formula\n\t\t\t\t\t\t\t\t// identical with vanilla formula when spread = 100 (default)\n\t\t\t\t\t\t\t\tsecondaryImpact = proj->calculateTrajectory(std::max(0.0, (BattleUnit::getFiringAccuracy(attack, _parent->getMod()) / 100.0) - i * 5.0 * spread / 100.0));\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (secondaryImpact != V_EMPTY)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// as above: skip the shot to the end of it's path\n\t\t\t\t\t\t\t\tproj->skipTrajectory();\n\t\t\t\t\t\t\t\t// insert an explosion and hit\n\t\t\t\t\t\t\t\tif (secondaryImpact != V_OUTOFBOUNDS)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tif (secondaryImpact == V_UNIT)\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tprojectileHitUnit(proj->getPosition(offset));\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tExplosion *explosion = new Explosion(proj->getPosition(offset), _ammo->getRules()->getHitAnimation(), 0, false, false, _ammo->getRules()->getHitAnimationFrames());\n\t\t\t\t\t\t\t\t\tint power = 0;\n\t\t\t\t\t\t\t\t\tif (_action.weapon->getRules()->getIgnoreAmmoPower())\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tpower = _action.weapon->getRules()->getPowerBonus(attack) - _action.weapon->getRules()->getPowerRangeReduction(proj->getDistance());\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tpower = _ammo->getRules()->getPowerBonus(attack) - _ammo->getRules()->getPowerRangeReduction(proj->getDistance());\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t_parent->getMap()->getExplosions()->push_back(explosion);\n\t\t\t\t\t\t\t\t\t_parent->getSave()->getTileEngine()->hit(attack, proj->getPosition(offset), power, _ammo->getRules()->getDamageType());\n\n\t\t\t\t\t\t\t\t\t//do not work yet\n//\t\t\t\t\t\t\t\t\tif (_ammo->getRules()->getExplosionRadius(_unit) != 0)\n//\t\t\t\t\t\t\t\t\t{\n//\t\t\t\t\t\t\t\t\t\t_parent->getTileEngine()->explode({ _action, _ammo }, proj->getPosition(offset), _ammo->getRules()->getPower(), _ammo->getRules()->getDamageType(), _ammo->getRules()->getExplosionRadius(), _unit);\n//\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t++i;\n\t\t\t\t\t\t\tdelete proj;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// reset back for the next shot in the (potential) autoshot sequence\n\t\t\t\t\t\t_targetVoxel = originalTarget;\n\t\t\t\t\t}\n\n\t\t\t\t\t// nerf unit's XP values (gained via extra shotgun bullets)\n\t\t\t\t\t_unit->nerfXP();\n\t\t\t\t}\n\t\t\t\telse if (noMoreShotsToShoot())\n\t\t\t\t{\n\t\t\t\t\t_unit->aim(false);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tdelete _parent->getMap()->getProjectile();\n\t\t\t_parent->getMap()->setProjectile(0);\n\t\t}\n\t}\n}\n\n/**\n * Flying projectiles cannot be cancelled,\n * but they can be \"skipped\".\n */\nvoid ProjectileFlyBState::cancel()\n{\n\tif (_parent->getMap()->getProjectile())\n\t{\n\t\t_parent->getMap()->getProjectile()->skipTrajectory();\n\t\tPosition p = _parent->getMap()->getProjectile()->getPosition().toTile();\n\t\tif (!_parent->getMap()->getCamera()->isOnScreen(p, false, 0, false))\n\t\t\t_parent->getMap()->getCamera()->centerOnPosition(p);\n\t}\n\tif (_parent->areAllEnemiesNeutralized())\n\t{\n\t\t// stop autoshots when battle auto-ends\n\t\t_action.autoShotCounter = 1000;\n\n\t\t// Rationale: if there are any fatally wounded soldiers\n\t\t// the game still allows the player to resume playing the current turn (and heal them)\n\t\t// but we don't want to resume auto-shooting (it just looks silly)\n\t}\n}\n\n/**\n * Validates the throwing range.\n * @param action Pointer to throw action.\n * @param origin Position to throw from.\n * @param target Tile to throw to.\n * @param depth Battlescape depth.\n * @return True when the range is valid.\n */\nbool ProjectileFlyBState::validThrowRange(BattleAction *action, Position origin, Tile *target, int depth)\n{\n\t// note that all coordinates and thus also distances below are in number of tiles (not in voxels).\n\tif (action->type != BA_THROW)\n\t{\n\t\treturn true;\n\t}\n\tint xdiff = action->target.x - action->actor->getPosition().x;\n\tint ydiff = action->target.y - action->actor->getPosition().y;\n\tint realDistanceSq = (xdiff * xdiff) + (ydiff * ydiff);\n\n\tint compatibilityDistanceSq = action->actor->distance3dToPositionSq(action->target); // 3d distance for compatibility with Map::drawTerrain()\n\tif (action->weapon->getRules()->isOutOfThrowRange(compatibilityDistanceSq, depth))\n\t{\n\t\t// if out of item's throw range, stop... no need to check weight- and strength-based range\n\t\treturn false;\n\t}\n\n\tdouble realDistance = sqrt((double)realDistanceSq);\n\n\tint offset = 2;\n\tint zd = (origin.z)-((action->target.z * 24 + offset) - target->getTerrainLevel());\n\tint weight = action->weapon->getTotalWeight();\n\tdouble maxDistance = (getMaxThrowDistance(weight, action->actor->getBaseStats()->strength, zd) + 8) / 16.0;\n\n\tif (depth > 0 && Mod::EXTENDED_UNDERWATER_THROW_FACTOR > 0)\n\t{\n\t\tmaxDistance = maxDistance * (double)Mod::EXTENDED_UNDERWATER_THROW_FACTOR / 100.0;\n\t}\n\n\treturn realDistance <= maxDistance;\n}\n\n/**\n * Validates the throwing range.\n * @param weight the weight of the object.\n * @param strength the strength of the thrower.\n * @param level the difference in height between the thrower and the target.\n * @return the maximum throwing range.\n */\nint ProjectileFlyBState::getMaxThrowDistance(int weight, int strength, int level)\n{\n\tdouble curZ = level + 0.5;\n\tdouble dz = 1.0;\n\tint dist = 0;\n\twhile (dist < 4000) //just in case\n\t{\n\t\tdist += 8;\n\t\tif (dz<-1)\n\t\t\tcurZ -= 8;\n\t\telse\n\t\t\tcurZ += dz * 8;\n\n\t\tif (curZ < 0 && dz < 0) //roll back\n\t\t{\n\t\t\tdz = std::max(dz, -1.0);\n\t\t\tif (std::abs(dz)>1e-10) //rollback horizontal\n\t\t\t\tdist -= curZ / dz;\n\t\t\tbreak;\n\t\t}\n\t\tdz -= (double)(50 * weight / strength)/100;\n\t\tif (dz <= -2.0) //become falling\n\t\t\tbreak;\n\t}\n\treturn dist;\n}\n\n/**\n * Set the origin voxel, used for the blaster launcher.\n * @param pos the origin voxel.\n */\nvoid ProjectileFlyBState::setOriginVoxel(const Position& pos)\n{\n\t_originVoxel = pos;\n}\n\n/**\n * Set the boolean flag to angle a blaster bomb towards the floor.\n */\nvoid ProjectileFlyBState::targetFloor()\n{\n\t_targetFloor = true;\n}\n\nvoid ProjectileFlyBState::projectileHitUnit(Position pos)\n{\n\tBattleUnit *victim = _parent->getSave()->getTile(pos.toTile())->getOverlappingUnit(_parent->getSave());\n\tBattleUnit *targetVictim = _parent->getSave()->getTile(_action.target)->getUnit(); // Who we were aiming at (not necessarily who we hit)\n\tif (victim && !victim->isOut())\n\t{\n\t\tvictim->getStatistics()->hitCounter++;\n\t\tif (_unit->getOriginalFaction() == FACTION_PLAYER && victim->getOriginalFaction() == FACTION_PLAYER)\n\t\t{\n\t\t\tvictim->getStatistics()->shotByFriendlyCounter++;\n\t\t\t_unit->getStatistics()->shotFriendlyCounter++;\n\t\t}\n\t\tif (victim == targetVictim) // Hit our target\n\t\t{\n\t\t\tint distanceSq = _action.actor->distance3dToUnitSq(victim);\n\t\t\tint distance = (int)std::ceil(sqrt(float(distanceSq)));\n\t\t\tint accuracy = BattleUnit::getFiringAccuracy(BattleActionAttack::GetAferShoot(_action, _ammo), _parent->getMod());\n\n\t\t\t{\n\t\t\t\tint upperLimit, lowerLimit;\n\t\t\t\tint dropoff = _action.weapon->getRules()->calculateLimits(upperLimit, lowerLimit, _parent->getSave()->getDepth(), _action.type);\n\n\t\t\t\tif (distance > upperLimit)\n\t\t\t\t{\n\t\t\t\t\taccuracy -= (distance - upperLimit) * dropoff;\n\t\t\t\t}\n\t\t\t\telse if (distance < lowerLimit)\n\t\t\t\t{\n\t\t\t\t\taccuracy -= (lowerLimit - distance) * dropoff;\n\t\t\t\t}\n\t\t\t\tif (accuracy < 0)\n\t\t\t\t{\n\t\t\t\t\taccuracy = 0;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t_unit->getStatistics()->shotsLandedCounter++;\n\t\t\tif (distance > 30)\n\t\t\t{\n\t\t\t\t_unit->getStatistics()->longDistanceHitCounter++;\n\t\t\t}\n\t\t\tif (accuracy < distance)\n\t\t\t{\n\t\t\t\t_unit->getStatistics()->lowAccuracyHitCounter++;\n\t\t\t}\n\t\t}\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/ProjectileFlyBState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <unordered_set>\n#include \"BattleState.h\"\n#include \"Position.h\"\n\nnamespace OpenXcom\n{\n\nclass BattlescapeGame;\nclass BattleUnit;\nclass BattleItem;\nclass Tile;\n\n/**\n * A projectile state.\n */\nclass ProjectileFlyBState : public BattleState\n{\nprivate:\n\tBattleUnit *_unit;\n\tBattleItem *_ammo;\n\tPosition _origin, _targetVoxel, _originVoxel;\n\tint _projectileImpact;\n\tint _range;\n\t/// Tries to create a projectile sprite.\n\tbool createNewProjectile();\n\tbool _initialized, _targetFloor;\n\npublic:\n\t/// Creates a new ProjectileFly class\n\tProjectileFlyBState(BattlescapeGame *parent, BattleAction action);\n\tProjectileFlyBState(BattlescapeGame *parent, BattleAction action, Position origin, int range);\n\t/// Cleans up the ProjectileFly.\n\t~ProjectileFlyBState();\n\t/// Initializes the state.\n\tvoid init() override;\n\t/// Deinitializes the state.\n\tvoid deinit() override;\n\t/// Handles a cancel request.\n\tvoid cancel() override;\n\t/// Runs state functionality every cycle.\n\tvoid think() override;\n\t/// Validates the throwing range.\n\tstatic bool validThrowRange(BattleAction *action, Position origin, Tile *target, int depth);\n\t/// Calculates the maximum throwing range.\n\tstatic int getMaxThrowDistance(int weight, int strength, int level);\n\t/// Set the origin voxel, used for the blaster launcher.\n\tvoid setOriginVoxel(const Position& pos);\n\t/// Set the boolean flag to angle a blaster bomb towards the floor.\n\tvoid targetFloor();\n\tvoid projectileHitUnit(Position pos);\n\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/PromotionsState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"PromotionsState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/Soldier.h\"\n#include \"../Savegame/Transfer.h\"\n#include \"../Engine/Options.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Promotions screen.\n * @param game Pointer to the core game.\n */\nPromotionsState::PromotionsState()\n{\n\t// Create object\n\t_window = new Window(this, 320, 200, 0, 0);\n\t_btnOk = new TextButton(288, 16, 16, 176);\n\t_txtTitle = new Text(300, 17, 10, 8);\n\t_txtName = new Text(114, 9, 16, 32);\n\t_txtRank = new Text(90, 9, 130, 32);\n\t_txtBase = new Text(80, 9, 220, 32);\n\t_lstSoldiers = new TextList(288, 128, 8, 40);\n\n\t// Set palette\n\tsetInterface(\"promotions\");\n\n\tadd(_window, \"window\", \"promotions\");\n\tadd(_btnOk, \"button\", \"promotions\");\n\tadd(_txtTitle, \"heading\", \"promotions\");\n\tadd(_txtName, \"text\", \"promotions\");\n\tadd(_txtRank, \"text\", \"promotions\");\n\tadd(_txtBase, \"text\", \"promotions\");\n\tadd(_lstSoldiers, \"list\", \"promotions\");\n\n\tcenterAllSurfaces();\n\n\t// Set up object\n\tsetWindowBackground(_window, \"promotions\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&PromotionsState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&PromotionsState::btnOkClick, Options::keyOk);\n\t_btnOk->onKeyboardPress((ActionHandler)&PromotionsState::btnOkClick, Options::keyCancel);\n\n\t_txtTitle->setText(tr(\"STR_PROMOTIONS\"));\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setBig();\n\n\t_txtName->setText(tr(\"STR_NAME\"));\n\n\t_txtRank->setText(tr(\"STR_NEW_RANK\"));\n\n\t_txtBase->setText(tr(\"STR_BASE\"));\n\n\t_lstSoldiers->setColumns(3, 114, 90, 84);\n\t_lstSoldiers->setSelectable(true);\n\t_lstSoldiers->setBackground(_window);\n\t_lstSoldiers->setMargin(8);\n\n\tfor (auto* xbase : *_game->getSavedGame()->getBases())\n\t{\n\t\tfor (auto* soldier : *xbase->getSoldiers())\n\t\t{\n\t\t\tif (soldier->isPromoted())\n\t\t\t{\n\t\t\t\t_lstSoldiers->addRow(3, soldier->getName().c_str(), tr(soldier->getRankString()).c_str(), xbase->getName().c_str());\n\t\t\t}\n\t\t}\n\t\tfor (auto* transfer : *xbase->getTransfers())\n\t\t{\n\t\t\tif (transfer->getType() == TRANSFER_SOLDIER)\n\t\t\t{\n\t\t\t\tif (transfer->getSoldier()->isPromoted())\n\t\t\t\t{\n\t\t\t\t\t_lstSoldiers->addRow(3, transfer->getSoldier()->getName().c_str(), tr(transfer->getSoldier()->getRankString()).c_str(), xbase->getName().c_str());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n *\n */\nPromotionsState::~PromotionsState()\n{\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid PromotionsState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/PromotionsState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass TextList;\n\n/**\n * Promotions screen that displays new soldier ranks.\n */\nclass PromotionsState : public State\n{\nprivate:\n\tTextButton *_btnOk;\n\tWindow *_window;\n\tText *_txtTitle, *_txtName, *_txtRank, *_txtBase;\n\tTextList *_lstSoldiers;\npublic:\n\t/// Creates the Promotions state.\n\tPromotionsState();\n\t/// Cleans up the Promotions state.\n\t~PromotionsState();\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/PsiAttackBState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"PsiAttackBState.h\"\n#include \"ExplosionBState.h\"\n#include \"BattlescapeGame.h\"\n#include \"TileEngine.h\"\n#include \"Map.h\"\n#include \"Camera.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"../Savegame/Tile.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Savegame/BattleUnitStatistics.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Sets up a PsiAttackBState.\n */\nPsiAttackBState::PsiAttackBState(BattlescapeGame *parent, BattleAction action) : BattleState(parent, action), _unit(0), _target(0), _item(0), _initialized(false)\n{\n}\n\n/**\n * Deletes the PsiAttackBState.\n */\nPsiAttackBState::~PsiAttackBState()\n{\n}\n\n/**\n * Initializes the sequence:\n * - checks if the action is valid,\n * - adds a psi attack animation to the world.\n * - from that point on, the explode state takes precedence (and perform psi attack).\n * - when that state pops, we'll do our first think()\n */\nvoid PsiAttackBState::init()\n{\n\tif (_initialized) return;\n\t_initialized = true;\n\n\t_item = _action.weapon;\n\n\tif (!_item) // can't make a psi attack without a weapon\n\t{\n\t\t_parent->popState();\n\t\treturn;\n\t}\n\n\tif (!_parent->getSave()->getTile(_action.target)) // invalid target position\n\t{\n\t\t_parent->popState();\n\t\treturn;\n\t}\n\n\t_unit = _action.actor;\n\n\tint distanceSq = _action.actor->distance3dToPositionSq(_action.target);\n\tif (_action.weapon->getRules()->isOutOfRange(distanceSq))\n\t{\n\t\t// out of range\n\t\t_action.result = \"STR_OUT_OF_RANGE\";\n\t\t_parent->popState();\n\t\treturn;\n\t}\n\n\t_target = _parent->getSave()->getTile(_action.target)->getUnit();\n\n\tif (!_target) // invalid target\n\t{\n\t\t_parent->popState();\n\t\treturn;\n\t}\n\n\tif (!_action.spendTU(&_action.result)) // not enough time units\n\t{\n\t\t_parent->popState();\n\t\treturn;\n\t}\n\n\tint height = _target->getFloatHeight() + (_target->getHeight() / 2) - _parent->getSave()->getTile(_action.target)->getTerrainLevel();\n\tPosition voxel = _action.target.toVoxel() + Position(8, 8, height);\n\t_parent->statePushFront(new ExplosionBState(_parent, voxel, BattleActionAttack::GetAferShoot(_action, _action.weapon)));\n}\n\n\n/**\n * After the explosion animation is done doing its thing,\n * restore the camera/cursor.\n */\nvoid PsiAttackBState::think()\n{\n\tif (_action.cameraPosition.z != -1)\n\t{\n\t\t_parent->getMap()->getCamera()->setMapOffset(_action.cameraPosition);\n\t\t_parent->getMap()->invalidate();\n\t}\n\tif (_parent->getSave()->getSide() == FACTION_PLAYER || _parent->getSave()->getDebugMode())\n\t{\n\t\t_parent->setupCursor();\n\t}\n\t_parent->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/PsiAttackBState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"BattleState.h\"\n\nnamespace OpenXcom\n{\n\nclass BattlescapeGame;\nclass BattleUnit;\nclass BattleItem;\nclass Tile;\n\n/**\n * A Psi Attack state.\n */\nclass PsiAttackBState : public BattleState\n{\nprivate:\n\tBattleUnit *_unit, *_target;\n\tBattleItem *_item;\n\tbool _initialized;\npublic:\n\t/// Creates a new PsiAttack state.\n\tPsiAttackBState(BattlescapeGame *parent, BattleAction action);\n\t/// Cleans up the PsiAttack.\n\t~PsiAttackBState();\n\t/// Initializes the state.\n\tvoid init() override;\n\t/// Runs state functionality every cycle.\n\tvoid think() override;\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/ScannerState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ScannerState.h\"\n#include \"ScannerView.h\"\n#include \"BattlescapeGame.h\"\n#include \"../Engine/InteractiveSurface.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Timer.h\"\n#include \"../Engine/Screen.h\"\n#include \"../Engine/Options.h\"\n#include \"../Savegame/BattleUnit.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes the Scanner State.\n * @param game Pointer to the core game.\n * @param action Pointer to an action.\n */\nScannerState::ScannerState (BattleAction *action) : _action(action)\n{\n\tif (Options::maximizeInfoScreens)\n\t{\n\t\tOptions::baseXResolution = Screen::ORIGINAL_WIDTH;\n\t\tOptions::baseYResolution = Screen::ORIGINAL_HEIGHT;\n\t\t_game->getScreen()->resetDisplay(false);\n\t}\n\t_bg = new InteractiveSurface(320, 200);\n\t_scan = new Surface(320, 200);\n\t_scannerView = new ScannerView(152, 152, 56, 24, _game, _action->actor);\n\n\tif (_game->getScreen()->getDY() > 50)\n\t{\n\t\t_screen = false;\n\t}\n\n\t// Set palette\n\t_game->getSavedGame()->getSavedBattle()->setPaletteByDepth(this);\n\n\tadd(_scan);\n\tadd(_scannerView);\n\tadd(_bg);\n\n\tcenterAllSurfaces();\n\n\t_game->getMod()->getSurface(\"DETBORD.PCK\")->blitNShade(_bg, 0, 0);\n\t_game->getMod()->getSurface(\"DETBORD2.PCK\")->blitNShade(_scan, 0, 0);\n\t_bg->onMouseClick((ActionHandler)&ScannerState::exitClick);\n\t_bg->onKeyboardPress((ActionHandler)&ScannerState::exitClick, Options::keyCancel);\n\n\t_timerAnimate = new Timer(125);\n\t_timerAnimate->onTimer((StateHandler)&ScannerState::animate);\n\t_timerAnimate->start();\n\n\tupdate();\n}\n\nScannerState::~ScannerState()\n{\n\tdelete _timerAnimate;\n}\n\n/**\n * Closes the window on right-click.\n * @param action Pointer to an action.\n */\nvoid ScannerState::handle(Action *action)\n{\n\tState::handle(action);\n\tif (action->getDetails()->type == SDL_MOUSEBUTTONDOWN && _game->isRightClick(action))\n\t{\n\t\texitClick(action);\n\t}\n}\n\n/**\n * Updates scanner state.\n */\nvoid ScannerState::update()\n{\n\t//_scannerView->draw();\n}\n\n/**\n * Animation handler. Updates the minimap view animation.\n */\nvoid ScannerState::animate()\n{\n\t_scannerView->animate();\n}\n\n/**\n * Handles timers.\n */\nvoid ScannerState::think()\n{\n\tState::think();\n\t_timerAnimate->think(this, 0);\n}\n\n/**\n * Exits the screen.\n * @param action Pointer to an action.\n */\nvoid ScannerState::exitClick(Action *)\n{\n\tif (Options::maximizeInfoScreens)\n\t{\n\t\tScreen::updateScale(Options::battlescapeScale, Options::baseXBattlescape, Options::baseYBattlescape, true);\n\t\t_game->getScreen()->resetDisplay(false);\n\t}\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/ScannerState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass Surface;\nclass Timer;\nclass ScannerView;\nstruct BattleAction;\n\n/**\n * The Scanner User Interface.\n */\nclass ScannerState : public State\n{\n\tInteractiveSurface *_bg;\n\tSurface *_scan;\n\tScannerView *_scannerView;\n\tBattleAction *_action;\n\t/// Updates scanner interface.\n\tvoid update();\n\tTimer *_timerAnimate;\n\t/// Handles Minimap animation.\n\tvoid animate();\npublic:\n\t/// Creates the ScannerState.\n\tScannerState(BattleAction *action);\n\t~ScannerState();\n\t/// Handler for right-clicking anything.\n\tvoid handle(Action *action) override;\n\t/// Handles timers.\n\tvoid think() override;\n\t/// Handler for exiting the state.\n\tvoid exitClick(Action *action);\n};\n}\n"
  },
  {
    "path": "src/Battlescape/ScannerView.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ScannerView.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/SurfaceSet.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/Action.h\"\n#include \"../Savegame/BattleUnit.h\"\n#include \"../Savegame/Tile.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes the Scanner view.\n * @param w The ScannerView width.\n * @param h The ScannerView height.\n * @param x The ScannerView x origin.\n * @param y The ScannerView y origin.\n * @param game Pointer to the core game.\n * @param unit The current unit.\n */\nScannerView::ScannerView (int w, int h, int x, int y, Game * game, BattleUnit *unit) : InteractiveSurface(w, h, x, y), _game(game), _unit(unit), _frame(0)\n{\n\t_redraw = true;\n}\n\n/**\n * Draws the ScannerView view.\n */\nvoid ScannerView::draw()\n{\n\tSurfaceSet *set = _game->getMod()->getSurfaceSet(\"DETBLOB.DAT\");\n\tSurface *surface = 0;\n\n\tclear();\n\n\tthis->lock();\n\tfor (int x = -9; x < 10; x++)\n\t{\n\t\tfor (int y = -9; y < 10; y++)\n\t\t{\n\t\t\tfor (int z = 0; z < _game->getSavedGame()->getSavedBattle()->getMapSizeZ(); z++)\n\t\t\t{\n\t\t\t\tTile *t = _game->getSavedGame()->getSavedBattle()->getTile(Position(x,y,z) + Position(_unit->getPosition().x, _unit->getPosition().y, 0));\n\t\t\t\tif (t && t->getUnit() && t->getUnit()->getMotionPoints())\n\t\t\t\t{\n\t\t\t\t\tint frame = (t->getUnit()->getMotionPoints() / 5);\n\t\t\t\t\tif (frame >= 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tt->getUnit()->setScannedTurn(_game->getSavedGame()->getSavedBattle()->getTurn());\n\t\t\t\t\t\tif (frame > 5) frame = 5;\n\t\t\t\t\t\tsurface = set->getFrame(frame + _frame);\n\t\t\t\t\t\tsurface->blitNShade(this, ((9+x)*8)-4, ((9+y)*8)-4, 0);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// the arrow of the direction the unit is pointed\n\tsurface = set->getFrame(7 + _unit->getDirection());\n\n\tsurface->blitNShade(this, (9*8)-4, (9*8)-4, 0);\n\tthis->unlock();\n\n\n}\n\n/**\n * Handles clicks on the scanner view.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid ScannerView::mouseClick (Action *, State *)\n{\n}\n\n/**\n * Updates the scanner animation.\n */\nvoid ScannerView::animate()\n{\n\t_frame++;\n\tif (_frame > 1)\n\t{\n\t\t_frame = 0;\n\t}\n\t_redraw = true;\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/ScannerView.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/InteractiveSurface.h\"\n\nnamespace OpenXcom\n{\n\nclass BattleUnit;\nclass Game;\n\n/**\n * Displays a view of units movement.\n */\nclass ScannerView : public InteractiveSurface\n{\n\tGame * _game;\n\t/// Handle clicking\n\tvoid mouseClick (Action *action, State *state) override;\n\tBattleUnit *_unit;\n\tint _frame;\npublic:\n\t/// Create the ScannerView\n\tScannerView (int w, int h, int x, int y, Game * game, BattleUnit *unit);\n\t/// Draw the scanner view\n\tvoid draw() override;\n\tvoid animate();\n};\n}\n"
  },
  {
    "path": "src/Battlescape/SkillMenuState.cpp",
    "content": "/*\n * Copyright 2010-2020 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"SkillMenuState.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleSkill.h\"\n#include \"../Mod/RuleSoldier.h\"\n#include \"../Mod/RuleSoldierBonus.h\"\n#include \"../Savegame/BattleItem.h\"\n#include \"../Savegame/BattleUnit.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"ActionMenuItem.h\"\n#include \"Pathfinding.h\"\n#include \"TileEngine.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Skill Menu window.\n * @param action Pointer to the action.\n * @param x Position on the x-axis.\n * @param y position on the y-axis.\n */\nSkillMenuState::SkillMenuState(BattleAction *action, int x, int y) : ActionMenuState(action)\n{\n\t// Attention: back up the current _action members\n\tBattleActionType currentActionType = _action->type;\n\tBattleItem* currentWeapon = _action->weapon;\n\tconst RuleSkill* currentSkill = _action->skillRules;\n\n\t_screen = false;\n\n\t// Set palette\n\t_game->getSavedGame()->getSavedBattle()->setPaletteByDepth(this);\n\n\tfor (int i = 0; i < (int)std::size(_actionMenu); ++i)\n\t{\n\t\t_actionMenu[i] = new ActionMenuItem(i, _game, x, y);\n\t\tadd(_actionMenu[i]);\n\t\t_actionMenu[i]->setVisible(false);\n\t\t_actionMenu[i]->onMouseClick((ActionHandler)&SkillMenuState::btnActionMenuItemClick);\n\t}\n\n\t// Build up the popup menu\n\tint id = 0;\n\n\tstd::vector<SDLKey> hotkeys = {\n\t\tOptions::keyBattleActionItem5,\n\t\tOptions::keyBattleActionItem4,\n\t\tOptions::keyBattleActionItem3,\n\t\tOptions::keyBattleActionItem2,\n\t\tOptions::keyBattleActionItem1\n\t};\n\tauto* soldier = _action->actor->getGeoscapeSoldier();\n\tfor (auto* skill : soldier->getRules()->getSkills())\n\t{\n\t\tif (!hotkeys.empty()\n\t\t\t&& soldier->hasAllRequiredBonusesForSkill(skill)\n\t\t\t&& (skill->getCost().Time > 0 || skill->getCost().Mana > 0)\n\t\t\t&& (!skill->isPsiRequired() || _action->actor->getBaseStats()->psiSkill > 0))\n\t\t{\n\t\t\t// Attention: we are modifying _action here\n\t\t\t_action->skillRules = skill;\n\t\t\t_action->type = skill->getTargetMode();\n\n\t\t\t// Attention: we are modifying _action->weapon inside!\n\t\t\tchooseWeaponForSkill(_action, skill);\n\n\t\t\t// Attention: here the modified values are consumed\n\t\t\taddItem(skill, &id, hotkeys.back());\n\n\t\t\thotkeys.pop_back();\n\t\t}\n\t}\n\n\t// Attention: restore the original values\n\t_action->type = currentActionType;\n\t_action->weapon = currentWeapon;\n\t_action->skillRules = currentSkill;\n}\n\n/**\n * Deletes the SkillMenuState.\n */\nSkillMenuState::~SkillMenuState()\n{\n\n}\n\n/**\n * Adds a new menu item for an action.\n * @param ba Action type.\n * @param name Action description.\n * @param id Pointer to the new item ID.\n */\nvoid SkillMenuState::addItem(const RuleSkill* skill, int *id, SDLKey key)\n{\n\tBattleActionType ba = skill->getTargetMode();\n\n\tstd::string s1, s2;\n\tRuleItemUseCost cost = _action->actor->getActionTUs(ba, _action->skillRules);\n\n\tif (_action->weapon)\n\t{\n\t\tint acc = BattleUnit::getFiringAccuracy(BattleActionAttack::GetBeforeShoot(ba, _action->actor, _action->weapon, _action->skillRules), _game->getMod());\n\t\tif (ba == BA_THROW || ba == BA_AIMEDSHOT || ba == BA_SNAPSHOT || ba == BA_AUTOSHOT || ba == BA_LAUNCH || ba == BA_HIT)\n\t\t\ts1 = tr(\"STR_ACCURACY_SHORT\").arg(Unicode::formatPercentage(acc));\n\t}\n\n\tif (cost.Time > 0)\n\t{\n\t\ts2 = tr(\"STR_TIME_UNITS_SHORT\").arg(cost.Time);\n\t}\n\telse if (cost.Mana > 0)\n\t{\n\t\ts2 = tr(\"STR_MANA_SHORT\").arg(cost.Mana);\n\t}\n\n\t_actionMenu[*id]->setAction(ba, tr(skill->getType()), s1, s2, cost.Time);\n\t_actionMenu[*id]->setSkill(skill);\n\t_actionMenu[*id]->setVisible(true);\n\n\tif (key != SDLK_UNKNOWN)\n\t{\n\t\t_actionMenu[*id]->onKeyboardPress((ActionHandler)&SkillMenuState::btnActionMenuItemClick, key);\n\t}\n\t(*id)++;\n}\n\n\n/**\n * Executes the action corresponding to this action menu item.\n * @param action Pointer to an action.\n */\nvoid SkillMenuState::btnActionMenuItemClick(Action *action)\n{\n\t_game->getSavedGame()->getSavedBattle()->getPathfinding()->removePreview();\n\n\tint btnID = -1;\n\n\tif (_game->getSavedGame()->getSavedBattle()->isPreview())\n\t{\n\t\t_action->result = \"STR_UNABLE_TO_USE_ALIEN_ARTIFACT_UNTIL_RESEARCHED\";\n\t\t_game->popState();\n\t\treturn;\n\t}\n\n\t// got to find out which button was pressed\n\tfor (size_t i = 0; i < std::size(_actionMenu) && btnID == -1; ++i)\n\t{\n\t\tif (action->getSender() == _actionMenu[i])\n\t\t{\n\t\t\tbtnID = i;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (btnID != -1)\n\t{\n\t\tTileEngine *tileEngine = _game->getSavedGame()->getSavedBattle()->getTileEngine();\n\t\tconst RuleSkill *selectedSkill = _actionMenu[btnID]->getSkill();\n\t\t_action->skillRules = selectedSkill;\n\t\t_action->type = _actionMenu[btnID]->getAction();\n\t\tchooseWeaponForSkill(_action, selectedSkill);\n\t\t_action->updateTU();\n\n\t\tbool continueAction = tileEngine->skillUse(_action, selectedSkill);\n\n\t\tif (!continueAction || _action->type == BA_NONE)\n\t\t{\n\t\t\t_action->targeting = false;\n\t\t\t_action->type = BA_NONE;\n\t\t\t_action->skillRules = nullptr;\n\t\t\t_game->popState();\n\t\t\treturn;\n\t\t}\n\n\t\t// check if the skill needs an item, if so check if an item was found\n\t\tBattleItem *item = _action->weapon;\n\t\tif (_action->type != BA_NONE)\n\t\t{\n\t\t\tif (!item)\n\t\t\t{\n\t\t\t\t_action->result = \"STR_SKILL_NEEDS_ITEM\";\n\t\t\t\tif (_action->type == BA_HIT) _action->type = BA_NONE; // OXC merge\n\t\t\t\t_game->popState();\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tif (_action->type == BA_THROW && _action->weapon->getRules()->getBattleType() == BT_GRENADE)\n\t\t{\n\t\t\t// instant grenades\n\t\t\t_action->weapon->setFuseTimer(0);\n\t\t\t_action->weapon->setFuseEnabled(true);\n\t\t}\n\t\telse if (_action->type == BA_PRIME || _action->type == BA_UNPRIME)\n\t\t{\n\t\t\t// nothing, skill menu only supports instant grenades for now\n\t\t\t_game->popState();\n\t\t\treturn;\n\t\t}\n\n\t\t// default handling from here on...\n\t\tActionMenuState::handleAction();\n\t}\n}\n\nvoid SkillMenuState::chooseWeaponForSkill(BattleAction* action, const RuleSkill* skillRules)\n{\n\tauto* unit = action->actor;\n\taction->weapon = nullptr;\n\n\tif (action->type == BA_NONE)\n\t{\n\t\treturn;\n\t}\n\n\t// 1. choose by weapon's name\n\tif (!skillRules->getCompatibleWeapons().empty())\n\t{\n\t\tfor (auto* itemRule : skillRules->getCompatibleWeapons())\n\t\t{\n\t\t\t// check both hands, right first\n\t\t\tif (unit->getRightHandWeapon() && unit->getRightHandWeapon()->getRules() == itemRule)\n\t\t\t{\n\t\t\t\taction->weapon = unit->getRightHandWeapon();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\telse if (unit->getLeftHandWeapon() && unit->getLeftHandWeapon()->getRules() == itemRule)\n\t\t\t{\n\t\t\t\taction->weapon = unit->getLeftHandWeapon();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!skillRules->checkHandsOnly())\n\t\t\t{\n\t\t\t\t// check special weapons\n\t\t\t\tBattleItem *item = unit->getSpecialWeapon(itemRule);\n\t\t\t\tif (item)\n\t\t\t\t{\n\t\t\t\t\taction->weapon = item;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t// check inventory\n\t\t\t\tfor (auto* invItem : *unit->getInventory())\n\t\t\t\t{\n\t\t\t\t\tif (invItem->getRules() == itemRule)\n\t\t\t\t\t{\n\t\t\t\t\t\taction->weapon = invItem;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// 2. if not found, try by weapon's battle type\n\tif (skillRules->getCompatibleBattleType() != BT_NONE)\n\t{\n\t\t// check both hands, right first\n\t\tif (unit->getRightHandWeapon() && unit->getRightHandWeapon()->getRules()->getBattleType() == skillRules->getCompatibleBattleType())\n\t\t{\n\t\t\taction->weapon = unit->getRightHandWeapon();\n\t\t\treturn;\n\t\t}\n\t\telse if (unit->getLeftHandWeapon() && unit->getLeftHandWeapon()->getRules()->getBattleType() == skillRules->getCompatibleBattleType())\n\t\t{\n\t\t\taction->weapon = unit->getLeftHandWeapon();\n\t\t\treturn;\n\t\t}\n\t\tif (!skillRules->checkHandsOnly2())\n\t\t{\n\t\t\t// check special weapons\n\t\t\tBattleItem* item = unit->getSpecialWeapon(skillRules->getCompatibleBattleType());\n\t\t\tif (item)\n\t\t\t{\n\t\t\t\taction->weapon = item;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// check inventory\n\t\t\tfor (auto* invItem : *unit->getInventory())\n\t\t\t{\n\t\t\t\tif (invItem->getRules()->getBattleType() == skillRules->getCompatibleBattleType())\n\t\t\t\t{\n\t\t\t\t\taction->weapon = invItem;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/SkillMenuState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2020 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http:///www.gnu.org/licenses/>.\n */\n#include \"ActionMenuState.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Window that allows the player\n * to select a battlescape action.\n */\nclass SkillMenuState : public ActionMenuState\n{\nprivate:\n\t/// Adds a new menu item for an action.\n\tvoid addItem(const RuleSkill* skill, int *id, SDLKey key);\n\t/// Choose an action weapon based on given parameters.\n\tvoid chooseWeaponForSkill(BattleAction* action, const RuleSkill* skillRules);\npublic:\n\t/// Creates the Skill Menu state.\n\tSkillMenuState(BattleAction *action, int x, int y);\n\t/// Cleans up the Skill Menu state.\n\t~SkillMenuState();\n\t/// Handler for clicking a skill menu item.\n\tvoid btnActionMenuItemClick(Action *action) override;\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/TileEngine.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <assert.h>\n#include <set>\n#include \"TileEngine.h\"\n#include \"AIModule.h\"\n#include \"Map.h\"\n#include \"Camera.h\"\n#include \"Projectile.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"../Savegame/Tile.h\"\n#include \"../Savegame/BattleItem.h\"\n#include \"../Savegame/BattleUnit.h\"\n#include \"../Savegame/BattleUnitStatistics.h\"\n#include \"../Savegame/HitLog.h\"\n#include \"../Engine/RNG.h\"\n#include \"../Engine/GraphSubset.h\"\n#include \"BattlescapeState.h\"\n#include \"../Mod/MapDataSet.h\"\n#include \"../Mod/Unit.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Mod/RuleSkill.h\"\n#include \"Pathfinding.h\"\n#include \"../Engine/Options.h\"\n#include \"ProjectileFlyBState.h\"\n#include \"MeleeAttackBState.h\"\n#include \"../fmath.h\"\n\nnamespace OpenXcom\n{\nnamespace\n{\n\n/**\n * Calculates a line trajectory, using bresenham algorithm in 3D.\n * @param origin Origin.\n * @param target Target.\n * @param posFunc Function call for each step in primary direction of line.\n * @param driftFunc Function call for each side step of line.\n */\ntemplate<typename FuncNewPosition, typename FuncDrift>\nbool calculateLineHelper(const Position& origin, const Position& target, FuncNewPosition posFunc, FuncDrift driftFunc)\n{\n\tint x, x0, x1, delta_x, step_x;\n\tint y, y0, y1, delta_y, step_y;\n\tint z, z0, z1, delta_z, step_z;\n\tint swap_xy, swap_xz;\n\tint drift_xy, drift_xz;\n\tint cx, cy, cz;\n\n\t//start and end points\n\tx0 = origin.x;\t x1 = target.x;\n\ty0 = origin.y;\t y1 = target.y;\n\tz0 = origin.z;\t z1 = target.z;\n\n\t//'steep' xy Line, make longest delta x plane\n\tswap_xy = abs(y1 - y0) > abs(x1 - x0);\n\tif (swap_xy)\n\t{\n\t\tstd::swap(x0, y0);\n\t\tstd::swap(x1, y1);\n\t}\n\n\t//do same for xz\n\tswap_xz = abs(z1 - z0) > abs(x1 - x0);\n\tif (swap_xz)\n\t{\n\t\tstd::swap(x0, z0);\n\t\tstd::swap(x1, z1);\n\t}\n\n\t//delta is Length in each plane\n\tdelta_x = abs(x1 - x0);\n\tdelta_y = abs(y1 - y0);\n\tdelta_z = abs(z1 - z0);\n\n\t//drift controls when to step in 'shallow' planes\n\t//starting value keeps Line centred\n\tdrift_xy  = (delta_x / 2);\n\tdrift_xz  = (delta_x / 2);\n\n\t//direction of line\n\tstep_x = 1;  if (x0 > x1) {  step_x = -1; }\n\tstep_y = 1;  if (y0 > y1) {  step_y = -1; }\n\tstep_z = 1;  if (z0 > z1) {  step_z = -1; }\n\n\t//starting point\n\ty = y0;\n\tz = z0;\n\n\t//step through longest delta (which we have swapped to x)\n\tfor (x = x0; ; x += step_x)\n\t{\n\t\t//copy position\n\t\tcx = x;\tcy = y;\tcz = z;\n\n\t\t//unswap (in reverse)\n\t\tif (swap_xz) std::swap(cx, cz);\n\t\tif (swap_xy) std::swap(cx, cy);\n\t\tif (posFunc(Position(cx, cy, cz)))\n\t\t{\n\t\t\treturn true;\n\t\t}\n\n\t\tif (x == x1) break;\n\n\t\t//update progress in other planes\n\t\tdrift_xy = drift_xy - delta_y;\n\t\tdrift_xz = drift_xz - delta_z;\n\n\t\t//step in y plane\n\t\tif (drift_xy < 0)\n\t\t{\n\t\t\ty = y + step_y;\n\t\t\tdrift_xy = drift_xy + delta_x;\n\n\t\t\tcx = x;\tcz = z; cy = y;\n\t\t\tif (swap_xz) std::swap(cx, cz);\n\t\t\tif (swap_xy) std::swap(cx, cy);\n\t\t\tif (driftFunc(Position(cx, cy, cz)))\n\t\t\t{\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\t//same in z\n\t\tif (drift_xz < 0)\n\t\t{\n\t\t\tz = z + step_z;\n\t\t\tdrift_xz = drift_xz + delta_x;\n\n\t\t\tcx = x;\tcz = z; cy = y;\n\t\t\tif (swap_xz) std::swap(cx, cz);\n\t\t\tif (swap_xy) std::swap(cx, cy);\n\t\t\tif (driftFunc(Position(cx, cy, cz)))\n\t\t\t{\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\ntemplate<typename FuncNewPosition>\nbool calculateParabolaHelper(const Position& origin, const Position& target, double curvature, const Position& delta, FuncNewPosition posFunc)\n{\n\tdouble ro = Position::distance(target, origin);\n\n\tif (AreSame(ro, 0.0)) return false;\n\n\tdouble fi = acos((double)(target.z - origin.z) / ro);\n\tdouble te = atan2((double)(target.y - origin.y), (double)(target.x - origin.x));\n\n\tte += (delta.x / ro) / 2 * M_PI; //horizontal magic value\n\tfi += ((delta.z + delta.y) / ro) / 14 * M_PI * curvature; //another magic value (vertical), to make it in line with fire spread\n\n\tdouble zA = sqrt(ro)*curvature;\n\tdouble zK = 4.0 * zA / ro / ro;\n\n\tint x = origin.x;\n\tint y = origin.y;\n\tint z = origin.z;\n\tint i = 8;\n\n\twhile (z > 0)\n\t{\n\t\tx = (int)((double)origin.x + (double)i * cos(te) * sin(fi));\n\t\ty = (int)((double)origin.y + (double)i * sin(te) * sin(fi));\n\t\tz = (int)((double)origin.z + (double)i * cos(fi) - zK * ((double)i - ro / 2.0) * ((double)i - ro / 2.0) + zA);\n\n\t\tif (posFunc(Position(x,y,z)))\n\t\t{\n\t\t\treturn true;\n\t\t}\n\n\t\t++i;\n\t}\n\n\treturn false;\n}\n\n/**\n * Iterate through some subset of map tiles.\n * @param save Map data.\n * @param gs Square subset of map area.\n * @param func Call back.\n */\ntemplate<typename TileFunc>\nvoid iterateTiles(SavedBattleGame* save, MapSubset gs, TileFunc func)\n{\n\tconst auto totalSizeX = save->getMapSizeX();\n\tconst auto totalSizeY = save->getMapSizeY();\n\tconst auto totalSizeZ = save->getMapSizeZ();\n\n\tgs = MapSubset::intersection(gs, MapSubset{ totalSizeX, totalSizeY });\n\tif (gs)\n\t{\n\t\tfor (int z = 0; z < totalSizeZ; ++z)\n\t\t{\n\t\t\tauto posStart = Position{ gs.beg_x, gs.beg_y, z };\n\t\t\tauto rowStart = save->getTile(posStart);\n\t\t\tauto indexStart = save->getTileIndex(posStart);\n\t\t\tfor (auto stepsY = gs.size_y(); stepsY != 0; --stepsY, rowStart += totalSizeX, indexStart += totalSizeX)\n\t\t\t{\n\t\t\t\tauto curr = rowStart;\n\t\t\t\tauto index = indexStart;\n\t\t\t\tfor (auto stepX = gs.size_x(); stepX != 0; --stepX, curr += 1, index += 1)\n\t\t\t\t{\n\t\t\t\t\tif constexpr (std::is_invocable_v<TileFunc, Tile*, int>)\n\t\t\t\t\t{\n\t\t\t\t\t\tfunc(curr, index);\n\t\t\t\t\t}\n\t\t\t\t\telse if constexpr (std::is_invocable_v<TileFunc, int>)\n\t\t\t\t\t{\n\t\t\t\t\t\tfunc(index);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tstatic_assert(std::is_invocable_v<TileFunc, Tile*>, \"unsupported callback for iterateTiles\");\n\t\t\t\t\t\tfunc(curr);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Generate square subset of map using position and radius.\n * @param position Starting position.\n * @param radius Radius of area.\n * @return Subset of map.\n */\nMapSubset mapArea(Position position, int radius)\n{\n\treturn { std::make_pair(position.x - radius, position.x + radius + 1), std::make_pair(position.y - radius, position.y + radius + 1) };\n}\n\nMapSubset mapAreaExpand(MapSubset gs, int radius)\n{\n\treturn { std::make_pair(gs.beg_x - radius, gs.end_x + radius), std::make_pair(gs.beg_y - radius, gs.end_y + radius) };\n}\n\n\n\nconstexpr static Uint32 MaskBlockDirMul = 9;\nconstexpr static Uint32 MaskBlockDirOffset = MaskBlockDirMul + 1;\n\n/**\n * Calculate byte mask that is used to access cached data.\n * @param dir Direction for 0 to 7 or -1 as no direction when we check direct up or down direction.\n * @param z Value +1 as up, -1 as down, 0 as same level\n * @return Mask corresponding given direction and level.\n */\nconstexpr static Uint32 selectBit(int dir, int z)\n{\n\treturn 1u << (MaskBlockDirOffset + MaskBlockDirMul * z + dir);\n}\n\nconstexpr static Uint32 MaskBlockDown = selectBit(-1, -1);\nconstexpr static Uint32 MaskBlockUp = selectBit(-1, +1);\n\nconstexpr static Uint32 MaskFire = selectBit(+7, +1) << 1;\nconstexpr static Uint32 MaskSmoke =  selectBit(+7, +1) << 2;\n\n\n\ntemplate<typename T>\nUint32 getBlockDir(const T& td)\n{\n\treturn td.blockDir;\n}\nUint32 getBlockDir(Uint32 td)\n{\n\treturn td;\n}\ntemplate<typename T>\nbool getBlockDir(const T& td, int dir, int z)\n{\n\treturn td.blockDir & selectBit(dir, z);\n}\ntemplate<typename T>\nvoid addBlockDir(T& td, int dir, int z, bool p)\n{\n\ttd.blockDir |= p * selectBit(dir, z);\n}\n\ntemplate<typename T>\nbool getBlockUp(const T& td)\n{\n\treturn td.blockDir & MaskBlockUp;\n}\ntemplate<typename T>\nvoid addBlockUp(T& td, bool p)\n{\n\ttd.blockDir |= p * MaskBlockUp;\n}\n\ntemplate<typename T>\nbool getBlockDown(const T& td)\n{\n\treturn td.blockDir & MaskBlockDown;\n}\ntemplate<typename T>\nvoid addBlockDown(T& td,bool p)\n{\n\ttd.blockDir |= p * MaskBlockDown;\n}\n\ntemplate<typename T>\nbool getFire(const T& td)\n{\n\treturn td.blockDir & MaskFire;\n}\ntemplate<typename T>\nvoid addFire(T& td, bool p)\n{\n\ttd.blockDir |= p * MaskFire;\n}\n\ntemplate<typename T>\nbool getSmoke(const T& td)\n{\n\treturn td.blockDir & MaskSmoke;\n}\ntemplate<typename T>\nvoid addSmoke(T& td, bool p)\n{\n\ttd.blockDir |= p * MaskSmoke;\n}\n\ntemplate<typename T>\nbool getBigWallDir(const T& td, int dir)\n{\n\treturn td.bigWall & (1u << dir);\n}\ntemplate<typename T>\nvoid addBigWallDir(T& td, int dir, bool p)\n{\n\ttd.bigWall |= p * (1u << dir);\n}\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tlight propagation\n////////////////////////////////////////////////////////////\n\n/**\n * Index to component of Pos\n */\nenum Axis : signed char\n{\n\tX = 0,\n\tY = 1,\n\tZ = 2,\n\n\tAxisMax = 3,\n\tAxisInvalid = -1,\n};\n\n/**\n * Index to component of Box\n */\nenum BoxAxis : signed char\n{\n\tB_X = X,\n\tB_Y = Y,\n\tB_Z = Z,\n\n\tE_X = AxisMax + X,\n\tE_Y = AxisMax + Y,\n\tE_Z = AxisMax + Z,\n\n\tBoxAxisMax = AxisMax + AxisMax,\n\tBoxAxisInvalid = AxisInvalid,\n};\n\n/**\n * Index to vertex of box\n */\nenum BoxVertex : char\n{\n\tV_000 = 0b000,\n\tV_001 = 0b001,\n\tV_010 = 0b010,\n\tV_011 = 0b011,\n\tV_100 = 0b100,\n\tV_101 = 0b101,\n\tV_110 = 0b110,\n\tV_111 = 0b111,\n\tBoxVertexMax = 8,\n};\n\n/**\n * 3d position, similar to `Position` but optimized for uniformed processing\n */\nusing Pos = std::array<int, AxisMax>;\n\n/**\n * 3d Box, effective contains two `Pos`.\n * Both ends will be visited iterated if is end point.\n * But algorithm will skip first step in iteration.\n */\nusing Box = std::array<int, BoxAxisMax>;\n\nconstexpr Box fromPos(Pos a, Pos b)\n{\n\treturn {\n\t\ta[X],\n\t\ta[Y],\n\t\ta[Z],\n\t\tb[X],\n\t\tb[Y],\n\t\tb[Z],\n\t};\n}\nconstexpr Pos add(Pos a, Pos b)\n{\n\tfor (int i = 0; i < AxisMax; ++i)\n\t{\n\t\ta[i] += b[i];\n\t}\n\treturn a;\n}\n\nbool isIntersectingWith(const Box& target, const Box& limit)\n{\n\tfor (int i = 0; i < AxisMax; ++i)\n\t{\n\t\tif ((target[i] > limit[i + AxisMax]) || (limit[i] > target[i + AxisMax]))\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n/**\n * Crop first argument to second, both need not empty intersection others wise it will return wrong answer.\n * @param target\n * @param limit\n */\nvoid intersectWithUnchecked(Box& target, const Box& limit)\n{\n\tfor (int i = 0; i < AxisMax; ++i)\n\t{\n\t\ttarget[i] = std::max(target[i], limit[i]);\n\t\ttarget[i + AxisMax] = std::min(target[i + AxisMax], limit[i + AxisMax]);\n\t}\n}\n\nvoid expand(Box& box)\n{\n\tconstexpr static Box diff = { -1, -1, -1, 1, 1, 1 };\n\tfor (int i = 0; i < BoxAxisMax; ++i)\n\t{\n\t\tbox[i] += diff[i];\n\t}\n}\n\nconstexpr std::array diffToAxis =\n{\n\tAxisInvalid,\n\tX,  // 0b001\n\tY,  // 0b010\n\tAxisInvalid,\n\tZ,  // 0b100\n\tAxisInvalid,\n\tAxisInvalid,\n\tAxisInvalid,\n};\n\n\nstruct ConfigSide\n{\n\tconstexpr static ConfigSide fill(BoxVertex start, BoxVertex ii, BoxVertex jj)\n\t{\n\t\t// `kk` is determined as vertex that lie on orthogonal line to surface defined by vertexes `start`, `ii` and `jj`.\n\t\tconst auto kk = BoxVertex(start ^ (V_111 - (start ^ jj) - (start ^ ii)));\n\n\t\treturn ConfigSide\n\t\t{\n\t\t\tDirection::fill(start, ii),\n\t\t\tDirection::fill(start, jj),\n\t\t\tDirection::fill(start, kk),\n\t\t};\n\t}\n\n\tstruct Direction\n\t{\n\t\tAxis axis = {};\n\t\tSint8 dir = {};\n\t\tBoxAxis first = {};\n\t\tBoxAxis last = {};\n\n\t\tconstexpr static Sint8 Plus = +1;\n\t\tconstexpr static Sint8 Minus = -1;\n\n\t\tconstexpr static Direction fill(BoxVertex from, BoxVertex to)\n\t\t{\n\t\t\tconst bool asc = from < to;\n\t\t\tconst Axis axis = diffToAxis[from ^ to];\n\n\t\t\treturn Direction\n\t\t\t{\n\t\t\t\taxis,\n\t\t\t\tasc ? Plus : Minus,\n\t\t\t\tBoxAxis(axis + (asc ? 0 : AxisMax)),\n\t\t\t\tBoxAxis(axis + (asc ? AxisMax : 0)),\n\t\t\t};\n\t\t}\n\t};\n\n\tDirection i, j, k;\n};\n\nconstexpr auto SquareLoopSize = 4;\nusing SquareLoop = std::array<BoxVertex, SquareLoopSize>;\n\n/**\n * Object with definition of operation order\n */\nconstexpr std::array propagationSequence = ([]\n{\n\tstd::array<ConfigSide, 24> s = {};\n\n\tauto up = [](BoxVertex e) -> BoxVertex\n\t{\n\t\treturn BoxVertex(e + V_100);\n\t};\n\tauto curr = [](const SquareLoop& a, int x)\n\t{\n\t\treturn a[x];\n\t};\n\tauto next = [](const SquareLoop& a, int x)\n\t{\n\t\treturn a[(x + 1) % SquareLoopSize];\n\t};\n\tauto prev = [](const SquareLoop& a, int x)\n\t{\n\t\treturn a[(x - 1 + SquareLoopSize) % SquareLoopSize];\n\t};\n\n\tint total = 0;\n\n\tconst SquareLoop floor_loop =\n\t{\n\t\tV_000,\n\t\tV_001,\n\t\tV_011,\n\t\tV_010,\n\t};\n\tfor (int j = 0; j < SquareLoopSize; ++j, ++total)\n\t{\n\t\ts[total] = ConfigSide::fill(\n\t\t\tcurr(floor_loop, j),\n\t\t\tnext(floor_loop, j),\n\t\t\tprev(floor_loop, j)\n\t\t);\n\t}\n\tfor (int j = 0; j < SquareLoopSize; ++j, ++total)\n\t{\n\t\ts[total] = ConfigSide::fill(\n\t\t\tup(curr(floor_loop, j)),\n\t\t\tup(next(floor_loop, j)),\n\t\t\tup(prev(floor_loop, j))\n\t\t);\n\t}\n\tfor (int i = 0; i < SquareLoopSize; ++i)\n\t{\n\t\tSquareLoop side =\n\t\t{\n\t\t\tcurr(floor_loop, i),\n\t\t\tnext(floor_loop, i),\n\t\t\tup(next(floor_loop, i)),\n\t\t\tup(curr(floor_loop, i)),\n\t\t};\n\t\tfor (int j = 0; j < SquareLoopSize; ++j, ++total)\n\t\t{\n\t\t\ts[total] = ConfigSide::fill(\n\t\t\t\tcurr(side, j),\n\t\t\t\tnext(side, j),\n\t\t\t\tprev(side, j)\n\t\t\t);\n\t\t}\n\t}\n\n\treturn s;\n}());\n\n\ntemplate<typename F>\nvoid iterateEdge(const Box& b, const Box& e, const ConfigSide::Direction d, F&& f)\n{\n\tauto begin = b[d.first];\n\tauto end = e[d.last];\n\tfor (int i = begin; i != end; i += d.dir)\n\t{\n\t\tf(i);\n\t}\n}\n\ntemplate<typename F>\nvoid iterateSide(int k, const Box& b, const Box& e, const ConfigSide c, F&& f)\n{\n\tPos p = {};\n\n\tp[c.k.axis] = k;\n\titerateEdge(b, e, c.j,\n\t\t[&](int pj)\n\t\t{\n\t\t\tp[c.j.axis] = pj;\n\t\t\titerateEdge(b, e, c.i,\n\t\t\t\t[&](int pi)\n\t\t\t\t{\n\t\t\t\t\tp[c.i.axis] = pi;\n\t\t\t\t\tf(p);\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t);\n}\n\ntemplate<typename F>\nvoid iterateSurface(Box& box, const Box& limit, F&& f)\n{\n\tBox beginBox = box;\n\n\texpand(box);\n\n\tBox crop = box;\n\tBox endBox = box;\n\n\texpand(endBox);\n\n\tintersectWithUnchecked(crop, limit);\n\tintersectWithUnchecked(beginBox, limit);\n\tintersectWithUnchecked(endBox, limit);\n\n\tfor (auto& c : propagationSequence)\n\t{\n\t\t//check if plane of side is inside of limit box\n\t\tif (box[c.k.first] == crop[c.k.first])\n\t\t{\n\t\t\titerateSide(box[c.k.first], beginBox, endBox, c, f);\n\t\t}\n\t}\n}\ntemplate<typename F>\nvoid iterateVolume(Pos start, int eventRadius, int range, MapSubset gs, int end_z, F&& f)\n{\n\tauto b = fromPos(start, start);\n\tconst auto limit = Box{ gs.beg_x, gs.beg_y, 0, gs.end_x - 1, gs.end_y - 1, end_z - 1 };\n\n\t//check that make sure that `intersectWithUnchecked` is guarantee to work correctly\n\tif (!isIntersectingWith(b, limit))\n\t{\n\t\treturn;\n\t}\n\n\tif (eventRadius == 0)\n\t{\n\t\tf(start);\n\t}\n\telse\n\t{\n\t\t//expanding range without update as it should be already updated, only edge need processing, this is why we \"transfer\" one step to next loop.\n\t\trange++;\n\t\teventRadius--;\n\t\twhile (eventRadius-- > 0)\n\t\t{\n\t\t\texpand(b);\n\t\t}\n\t}\n\n\twhile (range-- > 0)\n\t{\n\t\titerateSurface(b, limit, f);\n\t}\n}\n\nconstexpr static int dir_max = 9;\nconstexpr static int dir_x[dir_max] = { 0,  0, +1, +1, +1,  0, -1, -1, -1, };\nconstexpr static int dir_y[dir_max] = { 0, -1, -1,  0, +1, +1, +1,  0, -1, };\nconstexpr static int dir_z[dir_max] = { 0,  0,  0,  0,  0,  0,  0,  0,  0, };\n\nconstexpr static int dir_level_max = 3;\nconstexpr static int dir_level_x[dir_level_max] = {  0,  0,  0};\nconstexpr static int dir_level_y[dir_level_max] = {  0,  0,  0};\nconstexpr static int dir_level_z[dir_level_max] = { -1,  0, +1};\n\nconstexpr auto getPosOffsetByDirections(int dir)\n{\n\treturn Pos\n\t{\n\t\tdir_x[dir + 1],\n\t\tdir_y[dir + 1],\n\t\tdir_z[dir + 1],\n\t};\n}\nconstexpr auto getPosUpDown(int dir)\n{\n\treturn Pos\n\t{\n\t\tdir_level_x[dir + 1],\n\t\tdir_level_y[dir + 1],\n\t\tdir_level_z[dir + 1],\n\t};\n}\n\nstruct DirConfig\n{\n\tsigned char level;\n\tsigned char dir;\n\tPos offset;\n\tunsigned int mask;\n\tunsigned int next;\n};\n\nconstexpr bool isSameCubFace(Pos a, Pos b)\n{\n\tfor (int i = 0; i < AxisMax; ++i)\n\t{\n\t\tif (a[i] != 0 && a[i] == b[i])\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Work around for lack of `constexpr std::max` in some supported compilers\n */\nconstexpr int getMax(int a, int b)\n{\n\treturn a > b ? a : b;\n}\n\n/**\n * Work around for lack of `constexpr std::abs` in some supported compilers\n */\nconstexpr int getAbs(int a)\n{\n\treturn a >= 0 ? a : -a;\n}\n\nconstexpr int getChebyshevDistance(Pos a, Pos b)\n{\n\tint dis = 0;\n\tfor (int i = 0; i < AxisMax; ++i)\n\t{\n\t\tdis = getMax(getAbs(a[i]-b[i]), dis);\n\t}\n\treturn dis;\n}\n\nconstexpr int dir3dMax = dir_level_max * dir_max;\nconstexpr int dir3dStartMask = (1 << dir3dMax) - 1;\n\n/**\n * Object with definition of directions to check\n */\nconstexpr auto directions = ([]\n{\n\tauto array = std::array<DirConfig, dir3dMax>{};\n\n\tfor (int i = 0; i < dir3dMax; ++i)\n\t{\n\t\tauto& a = array[i];\n\t\ta.level = (i / dir_max) - 1;\n\t\ta.dir = (i % dir_max) - 1;\n\t\ta.offset = add(getPosOffsetByDirections(a.dir), getPosUpDown(a.level));\n\t\ta.mask = selectBit(a.dir, a.level);\n\t}\n\n\tfor (int i = 0; i < dir3dMax; ++i)\n\t{\n\t\tauto& a = array[i];\n\t\tfor (int j = 0; j < dir3dMax; ++j)\n\t\t{\n\t\t\tconst auto& b = array[j];\n\n\t\t\tif (isSameCubFace(a.offset, b.offset) && getChebyshevDistance(a.offset, b.offset) <= 1)\n\t\t\t{\n\t\t\t\ta.next |= b.mask;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn array;\n}());\n\n/**\n * Iterate through some subset of map tiles.\n * @param save Map data.\n */\ntemplate<typename TileWorkSet, typename TileBlockCache>\nvoid iterateTilesLightMaxBound(SavedBattleGame* save, Position position, int eventRadius, int maxRange, MapSubset gsMap, TileWorkSet& work, const TileBlockCache& blockCache)\n{\n\tif (position == TileEngine::invalid)\n\t{\n\t\titerateTiles(save, gsMap,\n\t\t\t[&](int idx)\n\t\t\t{\n\t\t\t\twork[idx] = dir3dStartMask;\n\t\t\t}\n\t\t);\n\n\t\treturn;\n\t}\n\n\titerateTiles(save, gsMap,\n\t\t[&](int idx)\n\t\t{\n\t\t\twork[idx] = 0x0;\n\t\t}\n\t);\n\titerateTiles(save, mapArea(position, eventRadius),\n\t\t[&](Tile* tile, int idx)\n\t\t{\n\t\t\t//TODO: on multi level maps we skip far levels to speed calculations,\n\t\t\t// but sometimes we could skip even more levels, for `position` and `eventRadius` we lose\n\t\t\t// detailed info what tiles were in reality affected,\n\t\t\t// in most cases most updates are limited to one level.\n\t\t\tif (std::abs(tile->getPosition().z - position.z) <= eventRadius)\n\t\t\t{\n\t\t\t\twork[idx] = dir3dStartMask;\n\t\t\t}\n\t\t}\n\t);\n\n\n\tconst int map_mul_y = save->getMapSizeX();\n\tconst int map_mul_z = map_mul_y * save->getMapSizeY();\n\tauto index = [map_mul_y, map_mul_z](Pos pp)\n\t{\n\t\treturn pp[X] + pp[Y] * map_mul_y + pp[Z] * map_mul_z;\n\t};\n\tauto callback = [&](Pos pp)\n\t{\n\t\tconst auto idx = index(pp);\n\t\tconst auto c = work[idx];\n\n\t\tconst auto check = c & ~getBlockDir(blockCache[idx]);\n\t\tif (check)\n\t\t{\n\t\t\tfor (const auto& d : directions)\n\t\t\t{\n\t\t\t\tif (d.mask & check)\n\t\t\t\t{\n\t\t\t\t\twork[index(add(pp, d.offset))] |= c & d.next;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\n\n\titerateVolume(Pos{position.x, position.y, position.z}, eventRadius, maxRange, gsMap, save->getMapSizeZ(), callback);\n}\n\n} // namespace\n\nconstexpr int TileEngine::heightFromCenter[11];\n\n\nconstexpr Position TileEngine::invalid;\nconstexpr Position TileEngine::voxelTileSize;\nconstexpr Position TileEngine::voxelTileCenter;\n\n/**\n * Sets up a TileEngine.\n * @param save Pointer to SavedBattleGame object.\n * @param voxelData List of voxel data.\n * @param maxViewDistance Max view distance in tiles.\n * @param maxDarknessToSeeUnits Threshold of darkness for LoS calculation.\n */\nTileEngine::TileEngine(SavedBattleGame *save, Mod *mod) :\n\t_save(save), _voxelData(mod->getVoxelData()), _inventorySlotGround(mod->getInventoryGround()), _personalLighting(true), _cacheTile(0), _cacheTileBelow(0),\n\t_maxViewDistance(mod->getMaxViewDistance()), _maxViewDistanceSq(_maxViewDistance * _maxViewDistance),\n\t_maxVoxelViewDistance(_maxViewDistance * 16), _maxDarknessToSeeUnits(mod->getMaxDarknessToSeeUnits()),\n\t_maxStaticLightDistance(mod->getMaxStaticLightDistance()), _maxDynamicLightDistance(mod->getMaxDynamicLightDistance()),\n\t_enhancedLighting(mod->getEnhancedLighting())\n{\n\t_blockVisibility.resize(save->getMapSizeXYZ());\n\t_lightPropagationTerrainBlocking.resize(save->getMapSizeXYZ());\n\t_lightPropagationTempNeedUpdate.resize(save->getMapSizeXYZ());\n\t_cacheTilePos = invalid;\n\n\tif (Options::oxceTogglePersonalLightType == 2)\n\t{\n\t\t// persisted per campaign\n\t\tSavedGame* geosave = _save->getGeoscapeSave();\n\t\tif (geosave)\n\t\t{\n\t\t\t_personalLighting = geosave->getTogglePersonalLight();\n\t\t}\n\t}\n\telse if (Options::oxceTogglePersonalLightType == 1)\n\t{\n\t\t// persisted per battle\n\t\t_personalLighting = _save->getTogglePersonalLight();\n\t}\n\n\t_save->setTogglePersonalLightTemp(_personalLighting);\n}\n\n/**\n * Deletes the TileEngine.\n */\nTileEngine::~TileEngine()\n{\n\n}\n\n/**\n  * Calculates sun shading for the whole terrain.\n  */\nvoid TileEngine::calculateSunShading(MapSubset gs)\n{\n\tint power = 15 - _save->getGlobalShade();\n\n\titerateTiles(\n\t\t_save,\n\t\tgs,\n\t\t[&](Tile* tile)\n\t\t{\n\t\t\tint currLight = power;\n\n\t\t\t// At night/dusk sun isn't dropping shades blocked by roofs\n\t\t\tif (_save->getGlobalShade() <= 4)\n\t\t\t{\n\t\t\t\tint block = 0;\n\t\t\t\tint x = tile->getPosition().x;\n\t\t\t\tint y = tile->getPosition().y;\n\t\t\t\tfor (int z = _save->getMapSizeZ()-1; z > tile->getPosition().z ; z--)\n\t\t\t\t{\n\t\t\t\t\tblock += blockage(_save->getTile(Position(x, y, z)), O_FLOOR, DT_NONE);\n\t\t\t\t\tblock += blockage(_save->getTile(Position(x, y, z)), O_OBJECT, DT_NONE, Pathfinding::DIR_DOWN);\n\t\t\t\t}\n\t\t\t\tif (block>0)\n\t\t\t\t{\n\t\t\t\t\tcurrLight -= 2;\n\t\t\t\t}\n\t\t\t}\n\t\t\ttile->addLight(currLight, LL_AMBIENT);\n\t\t}\n\t);\n}\n\n/// amount of light a fire generates from tile\nconst int fireLightPower = 15;\n\n/// amount of light a fire generates from unit\nconst int unitFireLightPower = 15;\n\n///  amount of light a fire generates from stunned unit\nconst int unitFireLightPowerStunned = 10;\n\n/**\n  * Recalculates lighting for the terrain: fire.\n  */\nvoid TileEngine::calculateTerrainBackground(MapSubset gs)\n{\n\t// add lighting of fire\n\titerateTiles(\n\t\t_save,\n\t\tmapAreaExpand(gs, getMaxStaticLightDistance() - 1),\n\t\t[&](Tile* tile)\n\t\t{\n\t\t\tint currLight = 0;\n\n\t\t\tif (tile->getMapData(O_FLOOR))\n\t\t\t{\n\t\t\t\tcurrLight = std::max(currLight, tile->getMapData(O_FLOOR)->getLightSource());\n\t\t\t}\n\t\t\tif (tile->getMapData(O_OBJECT))\n\t\t\t{\n\t\t\t\tcurrLight = std::max(currLight, tile->getMapData(O_OBJECT)->getLightSource());\n\t\t\t}\n\t\t\tif (tile->getMapData(O_WESTWALL))\n\t\t\t{\n\t\t\t\tcurrLight = std::max(currLight, tile->getMapData(O_WESTWALL)->getLightSource());\n\t\t\t}\n\t\t\tif (tile->getMapData(O_NORTHWALL))\n\t\t\t{\n\t\t\t\tcurrLight = std::max(currLight, tile->getMapData(O_NORTHWALL)->getLightSource());\n\t\t\t}\n\n\t\t\t// fires\n\t\t\tif (tile->getFire())\n\t\t\t{\n\t\t\t\tcurrLight = std::max(currLight, unitFireLightPower);\n\t\t\t}\n\n\t\t\tif (currLight >= getMaxStaticLightDistance())\n\t\t\t{\n\t\t\t\tcurrLight = getMaxStaticLightDistance() - 1;\n\t\t\t}\n\t\t\taddLight(gs, tile->getPosition(), currLight, LL_FIRE);\n\t\t}\n\t);\n}\n\n/**\n  * Recalculates lighting for the terrain: objects,items.\n  */\nvoid TileEngine::calculateTerrainItems(MapSubset gs)\n{\n\t// add lighting of terrain\n\titerateTiles(\n\t\t_save,\n\t\tmapAreaExpand(gs, getMaxDynamicLightDistance() - 1),\n\t\t[&](Tile* tile)\n\t\t{\n\t\t\tint currLight = 0;\n\n\t\t\tfor (const auto* bi : *tile->getInventory())\n\t\t\t{\n\t\t\t\tif (bi->getGlow())\n\t\t\t\t{\n\t\t\t\t\tcurrLight = std::max(currLight, bi->getGlowRange());\n\t\t\t\t}\n\n\t\t\t\tauto* bu = bi->getUnit();\n\t\t\t\tif (bu && bu->getFire())\n\t\t\t\t{\n\t\t\t\t\tcurrLight = std::max(currLight, unitFireLightPowerStunned);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (currLight >= getMaxDynamicLightDistance())\n\t\t\t{\n\t\t\t\tcurrLight = getMaxDynamicLightDistance() - 1;\n\t\t\t}\n\t\t\taddLight(gs, tile->getPosition(), currLight, LL_ITEMS);\n\t\t}\n\t);\n}\n\n/**\n  * Recalculates lighting for the units.\n  */\nvoid TileEngine::calculateUnitLighting(MapSubset gs)\n{\n\tfor (BattleUnit *unit : *_save->getUnits())\n\t{\n\t\tif (unit->isOut())\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\n\t\tint currLight = 0;\n\t\t// add lighting of unit\n\t\tif (unit->getFaction() == FACTION_PLAYER)\n\t\t{\n\t\t\tcurrLight = std::max(currLight, _personalLighting ? unit->getArmor()->getPersonalLightFriend() : 0);\n\t\t}\n\t\telse if (unit->getFaction() == FACTION_HOSTILE)\n\t\t{\n\t\t\tcurrLight = std::max(currLight, unit->getArmor()->getPersonalLightHostile());\n\t\t}\n\t\telse if (unit->getFaction() == FACTION_NEUTRAL)\n\t\t{\n\t\t\tcurrLight = std::max(currLight, unit->getArmor()->getPersonalLightNeutral());\n\t\t}\n\n\t\tconst BattleItem *handWeapons[] = { unit->getLeftHandWeapon(), unit->getRightHandWeapon() };\n\t\tfor (const BattleItem *w : handWeapons)\n\t\t{\n\t\t\tif (!w) continue;\n\n\t\t\tif (w->getGlow())\n\t\t\t{\n\t\t\t\tcurrLight = std::max(currLight, w->getGlowRange());\n\t\t\t}\n\n\t\t\tauto* u = w->getUnit();\n\t\t\tif (u && u->getFire())\n\t\t\t{\n\t\t\t\tcurrLight = std::max(currLight, unitFireLightPowerStunned);\n\t\t\t}\n\t\t}\n\t\t// add lighting of units on fire\n\t\tif (unit->getFire())\n\t\t{\n\t\t\tcurrLight = std::max(currLight, unitFireLightPower);\n\t\t}\n\n\t\tif (currLight >= getMaxDynamicLightDistance())\n\t\t{\n\t\t\tcurrLight = getMaxDynamicLightDistance() - 1;\n\t\t}\n\t\tconst auto size = unit->getArmor()->getSize();\n\t\tconst auto pos = unit->getPosition();\n\t\tfor (int x = 0; x < size; ++x)\n\t\t{\n\t\t\tfor (int y = 0; y < size; ++y)\n\t\t\t{\n\t\t\t\taddLight(gs, pos + Position(x, y, 0), currLight, LL_UNITS);\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid TileEngine::calculateLighting(LightLayers layer, Position position, int eventRadius, bool terrianChanged)\n{\n\tconst auto gsMap = MapSubset{ _save->getMapSizeX(), _save->getMapSizeY() };\n\tauto gsDynamic = gsMap;\n\tauto gsStatic = gsDynamic;\n\n\tif (position != invalid)\n\t{\n\t\tgsDynamic = mapArea(position, eventRadius + getMaxDynamicLightDistance());\n\t\tgsStatic = mapArea(position, eventRadius + getMaxStaticLightDistance());\n\t}\n\n\tif (terrianChanged)\n\t{\n\t\titerateTiles(\n\t\t\t_save,\n\t\t\tposition != invalid ? mapArea(position, eventRadius + 1) : gsMap,\n\t\t\t[&](Tile* tile)\n\t\t\t{\n\t\t\t\tconst auto currPos = tile->getPosition();\n\t\t\t\tconst auto index = _save->getTileIndex(currPos);\n\t\t\t\tconst auto* mapData = tile->getMapData(O_OBJECT);\n\t\t\t\tauto& cache = _blockVisibility[index];\n\n\t\t\t\tcache = {};\n\t\t\t\tcache.height = -tile->getTerrainLevel();\n\t\t\t\tif (mapData)\n\t\t\t\t{\n\t\t\t\t\tif (mapData->getTUCost(MT_WALK) == Pathfinding::INVALID_MOVE_COST)\n\t\t\t\t\t{\n\t\t\t\t\t\tcache.height = 24;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\taddSmoke(cache, tile->getSmoke() > 0);\n\t\t\t\taddFire(cache, tile->getFire() > 0);\n\t\t\t\taddBlockUp(cache, verticalBlockage(tile, _save->getAboveTile(tile), DT_NONE) > 127);\n\t\t\t\taddBlockDown(cache, verticalBlockage(tile, _save->getBelowTile(tile), DT_NONE) > 127);\n\t\t\t\tfor (int dir = 0; dir < 8; ++dir)\n\t\t\t\t{\n\t\t\t\t\tPosition pos = {};\n\t\t\t\t\tPathfinding::directionToVector(dir, &pos);\n\t\t\t\t\tauto* tileNext = _save->getTile(currPos + pos);\n\t\t\t\t\tauto result = 0;\n\n\t\t\t\t\tresult = horizontalBlockage(tile, tileNext, DT_NONE, true);\n\t\t\t\t\taddBigWallDir(cache, dir, (result == -1));\n\n\t\t\t\t\tresult = horizontalBlockage(tile, tileNext, DT_NONE);\n\t\t\t\t\taddBlockDir(cache, dir, 0, (result > 127 || result == -1));\n\n\t\t\t\t\ttileNext = _save->getTile(currPos + pos + Position{ 0, 0, 1 });\n\t\t\t\t\taddBlockDir(cache, dir, 1, verticalBlockage(tile, tileNext, DT_NONE) > 127);\n\n\t\t\t\t\ttileNext = _save->getTile(currPos + pos + Position{ 0, 0, -1 });\n\t\t\t\t\taddBlockDir(cache, dir, -1, verticalBlockage(tile, tileNext, DT_NONE) > 127);\n\t\t\t\t}\n\n\t\t\t\t_lightPropagationTerrainBlocking[index] = getBlockDir(cache);\n\t\t\t\t//HACK: some times light can lit wall objects even if its can't propagate through them,\n\t\t\t\t// for simplicity we consider them transparent.\n\t\t\t\t// But if is already big wall then next step to big wall is blocked.\n\t\t\t\tif (tile->getMapData(O_OBJECT) == nullptr || tile->getMapData(O_OBJECT)->getBigWall())\n\t\t\t\t{\n\t\t\t\t\tfor (int dir = 0; dir < 8; ++dir)\n\t\t\t\t\t{\n\t\t\t\t\t\tPosition pos = {};\n\t\t\t\t\t\tPathfinding::directionToVector(dir, &pos);\n\t\t\t\t\t\tauto* tileNext = _save->getTile(currPos + pos);\n\t\t\t\t\t\tauto result = 0;\n\n\t\t\t\t\t\tresult = horizontalBlockage(tile, tileNext, DT_NONE, true);\n\t\t\t\t\t\tif (result == -1)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_lightPropagationTerrainBlocking[index] &= ~selectBit(dir, 0);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\t}\n\n\titerateTilesLightMaxBound(_save, position, eventRadius, getMaxDynamicLightDistance(), gsMap, _lightPropagationTempNeedUpdate, _lightPropagationTerrainBlocking);\n\n\tif (layer <= LL_FIRE)\n\t{\n\t\titerateTiles(\n\t\t\t_save,\n\t\t\tgsStatic,\n\t\t\t[&](Tile* tile, int index)\n\t\t\t{\n\t\t\t\tif (_lightPropagationTempNeedUpdate[index]) tile->resetLightMulti(layer);\n\t\t\t}\n\t\t);\n\t}\n\n\titerateTiles(\n\t\t_save,\n\t\tgsDynamic,\n\t\t[&](Tile* tile, int index)\n\t\t{\n\t\t\tif (_lightPropagationTempNeedUpdate[index]) tile->resetLightMulti(std::max(layer, LL_ITEMS));\n\t\t}\n\t);\n\n\tif (layer <= LL_AMBIENT) calculateSunShading(gsStatic);\n\tif (layer <= LL_FIRE) calculateTerrainBackground(gsStatic);\n\tif (layer <= LL_ITEMS) calculateTerrainItems(gsDynamic);\n\tif (layer <= LL_UNITS) calculateUnitLighting(gsDynamic);\n}\n\n/**\n * Adds circular light pattern starting from center and losing power with distance travelled.\n * @param center Center.\n * @param power Power.\n * @param layer Light is separated in 4 layers: Ambient, Tiles, Items, Units.\n */\nvoid TileEngine::addLight(MapSubset gs, Position center, int power, LightLayers layer)\n{\n\tif (power <= 0)\n\t{\n\t\treturn;\n\t}\n\n\tconst auto fire = layer == LL_FIRE;\n\tconst auto items = layer == LL_ITEMS;\n\tconst auto units = layer == LL_UNITS;\n\tconst auto ground = items || fire;\n\tconst auto tileHeight = _save->getTile(center)->getTerrainLevel();\n\tconst auto divide = (fire ? 8 : 4);\n\tconst auto accuracy = TileEngine::voxelTileSize / divide;\n\tconst auto offsetCenter = (accuracy / 2 + Position(-1, -1, (ground ? 0 : accuracy.z/4) - tileHeight * accuracy.z / 24));\n\tconst auto offsetTarget = (accuracy / 2 + Position(-1, -1, 0));\n\tconst auto clasicLighting = !(getEnhancedLighting() & ((fire ? 1 : 0) | (items ? 2 : 0) | (units ? 4 : 0)));\n\tconst auto topTargetVoxel = static_cast<Sint16>(_save->getMapSizeZ() * accuracy.z - 1);\n\tconst auto topCenterVoxel = static_cast<Sint16>((getBlockUp(_blockVisibility[_save->getTileIndex(center)]) ? (center.z + 1) : _save->getMapSizeZ()) * accuracy.z - 1);\n\tconst auto maxFirePower = std::min(15, getMaxStaticLightDistance() - 1);\n\tconst auto gsInter = MapSubset::intersection(gs, mapArea(center, power - 1));\n\n\titerateTiles(\n\t\t_save,\n\t\tgsInter,\n\t\t[&](Tile* tile, int idx)\n\t\t{\n\t\t\tconst auto target = tile->getPosition();\n\t\t\tconst auto diff = target - center;\n\t\t\tconst auto distance = (int)Round(Position::distance(target.toVoxel(), center.toVoxel()) / Position::TileXY);\n\t\t\tconst auto targetLight = tile->getLightMulti(layer);\n\t\t\tauto currLight = power - distance;\n\n\t\t\tif (currLight <= targetLight)\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (clasicLighting)\n\t\t\t{\n\t\t\t\ttile->addLight(currLight, layer);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (_lightPropagationTempNeedUpdate[idx] == 0)\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tPosition startVoxel = (center * accuracy) + offsetCenter;\n\t\t\tPosition endVoxel = (target * accuracy) + offsetTarget + Position(0, 0, std::max(0, (_blockVisibility[_save->getTileIndex(target)].height - 1) / (2 * divide)));\n\t\t\tPosition offsetA{ 1, 0, 0 };\n\t\t\tPosition offsetB{ -1, 1, 0 };\n\t\t\tif ((diff.x > 0) ^ (diff.y > 0))\n\t\t\t{\n\t\t\t\toffsetA = { 1, 1, 0 };\n\t\t\t\toffsetB = { -1, -1, 0 };\n\t\t\t}\n\n\t\t\tstartVoxel += offsetA;\n\t\t\tendVoxel += offsetA;\n\t\t\tPosition lastTileA = center;\n\t\t\tPosition lastTileB = center;\n\t\t\tauto stepsA = 0;\n\t\t\tauto stepsB = 0;\n\t\t\tauto lightA = currLight;\n\t\t\tauto lightB = currLight;\n\n\t\t\t//Do not peek out your head outside map\n\t\t\tstartVoxel.z = std::min(startVoxel.z, topCenterVoxel);\n\t\t\tendVoxel.z = std::min(endVoxel.z, topTargetVoxel);\n\n\t\t\tauto calculateBlock = [&](Position point, Position &lastPoint, int &light, int &steps)\n\t\t\t{\n\t\t\t\tconst auto height = (point.z % accuracy.z) * divide;\n\t\t\t\tpoint = point / accuracy;\n\t\t\t\tif (light <= 0)\n\t\t\t\t{\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tif (point == lastPoint)\n\t\t\t\t{\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tconst auto difference = point - lastPoint;\n\t\t\t\tconst auto dir = Pathfinding::vectorToDirection(difference);\n\t\t\t\tconst auto& cache = _blockVisibility[_save->getTileIndex(lastPoint)];\n\n\t\t\t\tauto result = getBlockDir(cache, dir, difference.z);\n\t\t\t\tif (result && difference.z == 0 && getBigWallDir(cache, dir))\n\t\t\t\t{\n\t\t\t\t\tif (point == target)\n\t\t\t\t\t{\n\t\t\t\t\t\tresult = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (steps > 1)\n\t\t\t\t{\n\t\t\t\t\tif (getFire(cache) && fire && light <= maxFirePower) //some tile on path have fire, skip further calculation because destination tile should be lighted by this fire.\n\t\t\t\t\t{\n\t\t\t\t\t\tresult = true;\n\t\t\t\t\t}\n\t\t\t\t\telse if (getSmoke(cache))\n\t\t\t\t\t{\n\t\t\t\t\t\tlight -= 1;\n\t\t\t\t\t}\n\t\t\t\t\tif (height < cache.height)\n\t\t\t\t\t{\n\t\t\t\t\t\tlight -= 2;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t++steps;\n\t\t\t\tlastPoint = point;\n\t\t\t\tif (result || light < targetLight)\n\t\t\t\t{\n\t\t\t\t\tlight = 0;\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t};\n\n\t\t\tcalculateLineHelper(startVoxel, endVoxel,\n\t\t\t\t[&](Position voxel)\n\t\t\t\t{\n\t\t\t\t\tauto resultA = calculateBlock(voxel, lastTileA, lightA, stepsA);\n\t\t\t\t\tauto resultB = calculateBlock(voxel + offsetB, lastTileB, lightB, stepsB);\n\t\t\t\t\treturn resultA && resultB;\n\t\t\t\t},\n\t\t\t\t[&](Position voxel)\n\t\t\t\t{\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t);\n\n\t\t\tcurrLight = (lightA + lightB) / 2;\n\t\t\tif (currLight > targetLight)\n\t\t\t{\n\t\t\t\ttile->addLight(currLight, layer);\n\t\t\t}\n\t\t}\n\t);\n}\n\n/**\n * Setups the internal event visibility search space reduction system. This system defines a narrow circle sector around\n * a given event as viewed from an external observer. This allows narrowing down which tiles/units may need to be updated for\n * the observer based on the event affecting visibility at the event itself and beyond it in its direction.\n * Imagines a circle around the event of eventRadius, calculates its tangents, and places points at the circle's tangent\n * intersections for later bounds checking.\n * @param observerPos Position of the observer of this event.\n * @param eventPos The centre of the event. Ie a moving unit's position, centre of explosion, a single destroyed tile, etc.\n * @param eventRadius Radius big enough to fully envelop the event. Ie for a single tile change, set radius to 1.\n * @return true if area is unlimited.\n *\n*/\nbool TileEngine::setupEventVisibilitySector(const Position &observerPos, const Position &eventPos, const int &eventRadius)\n{\n\tif (eventRadius == 0 || eventPos == Position(-1, -1, -1) || Position::distance2dSq(observerPos, eventPos) <= eventRadius * eventRadius)\n\t{\n\t\t_eventVisibilityObserverPos = Position{ -1, -1, -1 };\n\t\treturn true;\n\t}\n\telse\n\t{\n\t\t//Use search space reduction by updating within a narrow circle sector covering the event and any\n\t\t//units beyond it (they can now be hidden or revealed based on what occurred at the event position)\n\t\t//So, with a circle at eventPos of radius eventRadius, define its tangent points as viewed from this unit.\n\t\tPosition posDiff = eventPos - observerPos;\n\t\tfloat a = asinf(eventRadius / sqrtf(posDiff.x * posDiff.x + posDiff.y * posDiff.y));\n\t\tfloat b = atan2f(posDiff.y, posDiff.x);\n\t\tfloat t1 = b - a;\n\t\tfloat t2 = b + a;\n\t\t//Define the points where the lines tangent to the circle intersect it. Note: resulting positions are relative to observer, not in direct tile space.\n\t\t_eventVisibilitySectorL.x = roundf(eventPos.x + eventRadius * sinf(t1)) - observerPos.x;\n\t\t_eventVisibilitySectorL.y = roundf(eventPos.y - eventRadius * cosf(t1)) - observerPos.y;\n\t\t_eventVisibilitySectorR.x = roundf(eventPos.x - eventRadius * sinf(t2)) - observerPos.x;\n\t\t_eventVisibilitySectorR.y = roundf(eventPos.y + eventRadius * cosf(t2)) - observerPos.y;\n\t\t_eventVisibilityObserverPos = observerPos;\n\t\treturn false;\n\t}\n}\n\n/**\n * Checks whether toCheck is within a previously setup eventVisibilitySector. See setupEventVisibilitySector(...).\n * May be used to rapidly reduce the search space when updating unit and tile visibility.\n * @param toCheck The position to check.\n * @return true if within the circle sector.\n */\ninline bool TileEngine::inEventVisibilitySector(const Position &toCheck) const\n{\n\tif (_eventVisibilityObserverPos != Position{ -1, -1, -1 })\n\t{\n\t\tPosition posDiff = toCheck - _eventVisibilityObserverPos;\n\t\t//Is toCheck within the arc as defined by the two tangent points?\n\t\treturn (!(-_eventVisibilitySectorL.x * posDiff.y + _eventVisibilitySectorL.y * posDiff.x > 0) &&\n\t\t\t(-_eventVisibilitySectorR.x * posDiff.y + _eventVisibilitySectorR.y * posDiff.x > 0));\n\t}\n\telse\n\t{\n\t\treturn true;\n\t}\n}\n\n/**\n* Updates line of sight of a single soldier in a narrow arc around a given event position.\n* @param unit Unit to check line of sight of.\n* @param eventPos The centre of the event which necessitated the FOV update. Used to optimize which tiles to update.\n* @param eventRadius The radius of a circle able to fully encompass the event, in tiles. Hence: 1 for a single tile event.\n* @return True when new aliens are spotted.\n*/\nbool TileEngine::calculateUnitsInFOV(BattleUnit* unit, const Position eventPos, const int eventRadius)\n{\n\tsize_t oldNumVisibleUnits = unit->getUnitsSpottedThisTurn().size();\n\tbool useTurretDirection = false;\n\tif (Options::strafe && (unit->getTurretType() > -1)) {\n\t\tuseTurretDirection = true;\n\t}\n\n\tif (unit->isOut())\n\t\treturn false;\n\n\tPosition posSelf = unit->getPosition();\n\tif (setupEventVisibilitySector(posSelf, eventPos, eventRadius))\n\t{\n\t\t//Asked to do a full check. Or the event is overlapping our tile. Better check everything.\n\t\tunit->clearVisibleUnits();\n\t}\n\n\t//Loop through all units specified and figure out which ones we can actually see.\n\tfor (auto* bu : *_save->getUnits())\n\t{\n\t\tPosition posOther = bu->getPosition();\n\t\tif (!bu->isOut() && (unit->getId() != bu->getId()))\n\t\t{\n\t\t\tint sizeOther = bu->getArmor()->getSize();\n\t\t\tfor (int x = 0; x < sizeOther; ++x)\n\t\t\t{\n\t\t\t\tfor (int y = 0; y < sizeOther; ++y)\n\t\t\t\t{\n\t\t\t\t\tPosition posToCheck = posOther + Position(x, y, 0);\n\t\t\t\t\t//If we can now find any unit within the arc defined by the event tangent points, its visibility may have been affected by the event.\n\t\t\t\t\tif (inEventVisibilitySector(posToCheck))\n\t\t\t\t\t{\n\t\t\t\t\t\tif (!unit->checkViewSector(posToCheck, useTurretDirection))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t//Unit within arc, but not in view sector. If it just walked out we need to remove it.\n\t\t\t\t\t\t\tunit->removeFromVisibleUnits(bu);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (visible(unit, _save->getTile(posToCheck))) // (distance is checked here)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t//Unit (or part thereof) visible to one or more eyes of this unit.\n\t\t\t\t\t\t\tif (unit->getFaction() == FACTION_PLAYER)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tbu->setVisible(true);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif ((( bu->getFaction() == FACTION_HOSTILE && unit->getFaction() == FACTION_PLAYER )\n\t\t\t\t\t\t\t\t|| ( bu->getFaction() != FACTION_HOSTILE && unit->getFaction() == FACTION_HOSTILE ))\n\t\t\t\t\t\t\t\t&& !unit->hasVisibleUnit(bu))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tunit->addToVisibleUnits(bu);\n\t\t\t\t\t\t\t\tunit->addToVisibleTiles(bu->getTile());\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (unit->getFaction() != bu->getFaction())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tbu->setTurnsSinceSpottedByFaction(unit->getFaction(), 0);\n\t\t\t\t\t\t\t\tbu->setTurnsLeftSpottedForSnipersByFaction(\n\t\t\t\t\t\t\t\t\tunit->getFaction(),\n\t\t\t\t\t\t\t\t\tstd::max(unit->getSpotterDuration(), bu->getTurnsLeftSpottedForSnipersByFaction(unit->getFaction()))\n\t\t\t\t\t\t\t\t); // defaults to 0 = no information given to snipers\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tx = y = sizeOther; //If a unit's tile is visible there's no need to check the others: break the loops.\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t//Within arc, but not visible. Need to check to see if whatever happened at eventPos blocked a previously seen unit.\n\t\t\t\t\t\t\tunit->removeFromVisibleUnits(bu);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t// we only react when there are at least the same amount of visible units as before AND the checksum is different\n\t// this way we stop if there are the same amount of visible units, but a different unit is seen\n\t// or we stop if there are more visible units seen\n\tif (unit->getUnitsSpottedThisTurn().size() > oldNumVisibleUnits && !unit->getVisibleUnits()->empty())\n\t{\n\t\treturn true;\n\t}\n\treturn false;\n}\n\n/**\n* Calculates line of sight of tiles for a player controlled soldier.\n* If supplied with an event position differing from the soldier's position, it will only\n* calculate tiles within a narrow arc.\n* @param unit Unit to check line of sight of.\n* @param eventPos The centre of the event which necessitated the FOV update. Used to optimize which tiles to update.\n* @param eventRadius The radius of a circle able to fully encompass the event, in tiles. Hence: 1 for a single tile event.\n*/\nvoid TileEngine::calculateTilesInFOV(BattleUnit *unit, const Position eventPos, const int eventRadius)\n{\n\tbool useTurretDirection = false;\n\tbool skipNarrowArcTest = false;\n\tint direction;\n\tif (Options::strafe && (unit->getTurretType() > -1)) {\n\t\tdirection = unit->getTurretDirection();\n\t\tuseTurretDirection = true;\n\t}\n\telse\n\t{\n\t\tdirection = unit->getDirection();\n\t}\n\tif (unit->getFaction() != FACTION_PLAYER || (eventRadius == 1 && !unit->checkViewSector(eventPos, useTurretDirection)))\n\t{\n\t\t//The event wasn't meant for us and/or visible for us.\n\t\treturn;\n\t}\n\telse if (unit->isOut())\n\t{\n\t\tunit->clearVisibleTiles();\n\t\treturn;\n\t}\n\tPosition posSelf = unit->getPosition();\n\tif (setupEventVisibilitySector(posSelf, eventPos, eventRadius))\n\t{\n\t\t//Asked to do a full check. Or unit within event. Should update all.\n\t\tunit->clearVisibleTiles();\n\t\tskipNarrowArcTest = true;\n\t}\n\n\t//Only recalculate bresenham lines to tiles that are at the event or further away.\n\tconst int distanceSqrMin = skipNarrowArcTest ? 0 : std::max(Position::distance2dSq(posSelf, eventPos) - eventRadius * eventRadius, 0);\n\n\t//Variables for finding the tiles to test based on the view direction.\n\tPosition posTest;\n\tstd::vector<Position> _trajectory;\n\tbool swap = (direction == 0 || direction == 4);\n\tconst int signX[8] = { +1, +1, +1, +1, -1, -1, -1, -1 };\n\tconst int signY[8] = { -1, -1, -1, +1, +1, +1, -1, -1 };\n\tint y1, y2;\n\n\tif ((unit->getHeight() + unit->getFloatHeight() + -_save->getTile(unit->getPosition())->getTerrainLevel()) >= 24 + 4)\n\t{\n\t\tTile *tileAbove = _save->getTile(posSelf + Position(0, 0, 1));\n\t\tif (tileAbove && tileAbove->hasNoFloor(0))\n\t\t{\n\t\t\t++posSelf.z;\n\t\t}\n\t}\n\t//Test all tiles within view cone for visibility.\n\tfor (int x = 0; x <= getMaxViewDistance(); ++x) //TODO: Possible improvement: find the intercept points of the arc at max view distance and choose a more intelligent sweep of values when an event arc is defined.\n\t{\n\t\tif (direction & 1)\n\t\t{\n\t\t\ty1 = 0;\n\t\t\ty2 = getMaxViewDistance();\n\t\t}\n\t\telse\n\t\t{\n\t\t\ty1 = -x;\n\t\t\ty2 = x;\n\t\t}\n\t\tfor (int y = y1; y <= y2; ++y) //TODO: Possible improvement: find the intercept points of the arc at max view distance and choose a more intelligent sweep of values when an event arc is defined.\n\t\t{\n\t\t\tconst int distanceSqr = x*x + y*y;\n\t\t\tif (distanceSqr <= getMaxViewDistanceSq() && distanceSqr >= distanceSqrMin)\n\t\t\t{\n\t\t\t\tposTest.x = posSelf.x + signX[direction] * (swap ? y : x);\n\t\t\t\tposTest.y = posSelf.y + signY[direction] * (swap ? x : y);\n\t\t\t\t//Only continue if the column of tiles at (x,y) is within the narrow arc of interest (if enabled)\n\t\t\t\tif (inEventVisibilitySector(posTest))\n\t\t\t\t{\n\t\t\t\t\tfor (int z = 0; z < _save->getMapSizeZ(); z++)\n\t\t\t\t\t{\n\t\t\t\t\t\tposTest.z = z;\n\n\t\t\t\t\t\tif (_save->getTile(posTest)) //inside map?\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// this sets tiles to discovered if they are in LOS - tile visibility is not calculated in voxelspace but in tilespace\n\t\t\t\t\t\t\t// large units have \"4 pair of eyes\"\n\t\t\t\t\t\t\tint size = unit->getArmor()->getSize();\n\t\t\t\t\t\t\tfor (int xo = 0; xo < size; xo++)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tfor (int yo = 0; yo < size; yo++)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tPosition poso = posSelf + Position(xo, yo, 0);\n\t\t\t\t\t\t\t\t\t_trajectory.clear();\n\t\t\t\t\t\t\t\t\tint tst = calculateLineTile(poso, posTest, _trajectory);\n\t\t\t\t\t\t\t\t\tif (tst > 127)\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t//Vision impacted something before reaching posTest. Throw away the impact point.\n\t\t\t\t\t\t\t\t\t\t_trajectory.pop_back();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t//Reveal all tiles along line of vision. Note: needed due to width of bresenham stroke.\n\t\t\t\t\t\t\t\t\tfor (const auto& posVisited : _trajectory)\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t//Add tiles to the visible list only once. BUT we still need to calculate the whole trajectory as\n\t\t\t\t\t\t\t\t\t\t// this bresenham line's period might be different from the one that originally revealed the tile.\n\t\t\t\t\t\t\t\t\t\tif (!unit->hasVisibleTile(_save->getTile(posVisited)))\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tunit->addToVisibleTiles(_save->getTile(posVisited));\n\t\t\t\t\t\t\t\t\t\t\t_save->getTile(posVisited)->setVisible(+1);\n\t\t\t\t\t\t\t\t\t\t\t_save->getTile(posVisited)->setDiscovered(true, O_FLOOR);\n\n\t\t\t\t\t\t\t\t\t\t\t// walls to the east or south of a visible tile, we see that too\n\t\t\t\t\t\t\t\t\t\t\tTile* t = _save->getTile(Position(posVisited.x + 1, posVisited.y, posVisited.z));\n\t\t\t\t\t\t\t\t\t\t\tif (t) t->setDiscovered(true, O_WESTWALL);\n\t\t\t\t\t\t\t\t\t\t\tt = _save->getTile(Position(posVisited.x, posVisited.y + 1, posVisited.z));\n\t\t\t\t\t\t\t\t\t\t\tif (t) t->setDiscovered(true, O_NORTHWALL);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n* Recalculates line of sight of a soldier.\n* @param unit Unit to check line of sight of.\n* @param doTileRecalc True (default) to recalculate the visible tiles for this unit.\n* @param doUnitRecalc True (default) to recalculate the visible units for this unit.\n* @return True when new aliens are spotted.\n*/\nbool TileEngine::calculateFOV(BattleUnit *unit, bool doTileRecalc, bool doUnitRecalc)\n{\n\t//Force a full FOV recheck for this unit.\n\tif (doTileRecalc) calculateTilesInFOV(unit);\n\treturn doUnitRecalc ? calculateUnitsInFOV(unit) : false;\n}\n\n/**\n * Gets the origin voxel of a unit's eyesight\n * @param currentUnit The watcher.\n * @return Approximately an eyeball voxel.\n */\nPosition TileEngine::getSightOriginVoxel(BattleUnit *currentUnit)\n{\n\tconst Position pos = currentUnit->getPosition();\n\tauto* tile = currentUnit->getTile();\n\n\t// determine the origin and target voxels for the raytrace\n\tPosition originVoxel;\n\toriginVoxel = pos.toVoxel() + Position(8, 8, 0);\n\toriginVoxel.z += -tile->getTerrainLevel();\n\toriginVoxel.z += currentUnit->getHeight() + currentUnit->getFloatHeight() - 1; //one voxel lower (eye level)\n\tTile *tileAbove = _save->getAboveTile(tile);\n\tif (currentUnit->isBigUnit())\n\t{\n\t\toriginVoxel.x += 8;\n\t\toriginVoxel.y += 8;\n\t\toriginVoxel.z += 1; //topmost voxel\n\t}\n\tif (originVoxel.z >= (pos.z + 1)*Position::TileZ && (!tileAbove || !tileAbove->hasNoFloor(0)))\n\t{\n\t\twhile (originVoxel.z >= (pos.z + 1)*Position::TileZ)\n\t\t{\n\t\t\toriginVoxel.z--;\n\t\t}\n\t}\n\n\treturn originVoxel;\n}\n\nnamespace\n{\n\n/**\n * Calculate max visible distance.\n * @param te TileEngine\n * @param tile Target tile that is look at\n * @param currentUnit Unit that look on tile or unit\n * @param targetUnit Unit that is look at\n * @return Tuple of get<0>: effective visible distance that consider camouflage and shade, get<1>: max unit visibility distance in tiles independent of target darkness\n */\nstd::tuple<int, int> getVisibleDistanceMaxHelper(TileEngine* te, const Tile* tile, const BattleUnit* currentUnit, const BattleUnit *targetUnit)\n{\n\tbool targetIsDark = tile->getShade() > te->getMaxDarknessToSeeUnits();\n\tbool targetOnFire = (targetUnit && targetUnit->getFire() > 0);\n\tif (targetOnFire)\n\t{\n\t\t// Note: fire cancels enemy's camouflage\n\t\ttargetUnit = nullptr;\n\t\ttargetIsDark = false;\n\t}\n\n\tconst int viewDistanceAtDarkTiles = currentUnit->getMaxViewDistanceAtDark(targetUnit);\n\tconst int viewDistanceAtDayTiles = currentUnit->getMaxViewDistanceAtDay(targetUnit);\n\n\t// global max distance, independent of unit\n\tconst int visibleDistanceGlobalMaxVoxel = te->getMaxVoxelViewDistance();\n\t// max distance, affected by target unit too\n\tint visibleDistanceMaxVoxel = visibleDistanceGlobalMaxVoxel;\n\t// unit max distance, mix of dark and day range\n\tint visibleDistanceUnitMaxTile = std::min(\n\t\tte->getMaxViewDistance(),\n\t\tstd::max(\n\t\t\tviewDistanceAtDarkTiles,\n\t\t\tviewDistanceAtDayTiles\n\t\t)\n\t);\n\n\t// during dark aliens can see 20 tiles, xcom can see 9 by default... unless overridden by armor\n\tif (targetIsDark)\n\t{\n\t\tvisibleDistanceMaxVoxel = std::min(\n\t\t\tvisibleDistanceGlobalMaxVoxel,\n\t\t\tviewDistanceAtDarkTiles * Position::TileXY\n\t\t);\n\t}\n\t// during day (or if enough other light) both see 20 tiles ... unless overridden by armor\n\telse\n\t{\n\t\tvisibleDistanceMaxVoxel = std::min(\n\t\t\tvisibleDistanceGlobalMaxVoxel,\n\t\t\tviewDistanceAtDayTiles * Position::TileXY\n\t\t);\n\t}\n\n\t// small buffer that allow for very short visibility distance still work in smoke or some diagonal directions still be visible\n\tvisibleDistanceMaxVoxel += Position::TileXY / 4;\n\n\treturn std::make_tuple(visibleDistanceMaxVoxel, visibleDistanceUnitMaxTile);\n}\n\n/**\n * Get data for given trajectory\n * @param te TileEngine\n * @param save SavedBattleGame for\n * @param currentUnit Unit that look on tile or unit\n * @param originVoxel Start trajectory voxel\n * @param scanVoxel End trajectory voxel\n * @return Tuple of get<0>: visibleDistanceVoxels, get<1>: densityOfSmoke, get<2>: densityOfFire\n */\nstd::tuple<int, int, int, int, int> getTrajectoryDataHelper(TileEngine* te, const SavedBattleGame* save, const BattleUnit* currentUnit, Position originVoxel, Position scanVoxel)\n{\n\tstd::vector<Position> _trajectory;\n\n\t// predict used distance to avoid multiple allocations\n\tPosition diff = (originVoxel - scanVoxel);\n\t_trajectory.reserve(std::max({std::abs(diff.x), std::abs(diff.y), std::abs(diff.z)}) + 1);\n\n\t// now check if we really see it taking into account smoke tiles\n\t// initial smoke \"density\" of a smoke grenade is around 15 per tile\n\t// we do density/3 to get the decay of visibility\n\t// so in fresh smoke we should only have 4 tiles of visibility\n\t// this is traced in voxel space, with smoke affecting visibility every step of the way\n\tte->calculateLineVoxel(originVoxel, scanVoxel, true, &_trajectory, const_cast<BattleUnit*>(currentUnit));\n\tconst int trajectorySize = _trajectory.size();\n\tfloat densityOfSmoke = 0;\n\tfloat densityOfFire = 0;\n\tfloat densityOfSmokeNearUnit = 0;\n\tfloat densityOfFireeNearUnit = 0;\n\tfloat visibleDistanceVoxels = 0;\n\tPosition trackTile(-1, -1, -1);\n\tconst Tile *t = 0;\n\n\tfor (int i = 0; i < trajectorySize; i++)\n\t{\n\t\tauto posTile =  _trajectory.at(i).toTile();\n\t\tauto step = te->trajectoryStepSize(_trajectory, i);\n\t\tif (trackTile != posTile)\n\t\t{\n\t\t\ttrackTile = posTile;\n\t\t\tt = save->getTile(trackTile);\n\t\t}\n\t\tvisibleDistanceVoxels += step;\n\t\tif (t->getFire() == 0)\n\t\t{\n\t\t\tdensityOfSmoke += step * t->getSmoke();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tdensityOfFire += step * t->getSmoke(); // this boost fire blocking visibility for thermo vision as usually smoke value is bigger\n\t\t}\n\t\tif (visibleDistanceVoxels < Position::TileXY*2)\n\t\t{\n\t\t\tif (t->getFire() == 0)\n\t\t\t{\n\t\t\t\tdensityOfSmokeNearUnit += step * t->getSmoke();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tdensityOfFireeNearUnit += step * t->getSmoke(); // this boost fire blocking visibility for thermo vision as usually smoke value is bigger\n\t\t\t}\n\t\t}\n\t}\n\n\treturn std::make_tuple((int)visibleDistanceVoxels, (int)densityOfSmoke, (int)densityOfFire, (int)densityOfSmokeNearUnit, (int)densityOfFireeNearUnit);\n}\n\n}\n\n\n/**\n * Checks for an opposing unit on this tile.\n * @param currentUnit The watcher.\n * @param tile The tile to check for\n * @return True if visible.\n */\nbool TileEngine::visible(BattleUnit *currentUnit, Tile *tile)\n{\n\t// if there is no tile or no unit, we can't see it\n\tif (!tile || !tile->getUnit())\n\t{\n\t\treturn false;\n\t}\n\n\t// friendlies are always seen\n\tif (currentUnit->getFaction() == tile->getUnit()->getFaction()) return true;\n\n\t// if beyond global max. range, nobody can see anyone\n\tint currentDistanceSq = Position::distance2dSq(currentUnit->getPosition(), tile->getPosition());\n\tif (currentDistanceSq > getMaxViewDistanceSq())\n\t{\n\t\treturn false;\n\t}\n\n\t// psi vision\n\tint psiVisionDistance = currentUnit->getPsiVision();\n\tbool fearImmune = tile->getUnit()->getArmor()->getFearImmune();\n\tif (psiVisionDistance > 0 && !fearImmune)\n\t{\n\t\tint psiCamo = tile->getUnit()->getArmor()->getPsiCamouflage();\n\t\tif (psiCamo > 0)\n\t\t{\n\t\t\tpsiVisionDistance = std::min(psiVisionDistance, psiCamo);\n\t\t}\n\t\telse if (psiCamo < 0)\n\t\t{\n\t\t\tpsiVisionDistance = std::max(0, psiVisionDistance + psiCamo);\n\t\t}\n\t\tif (currentDistanceSq <= (psiVisionDistance * psiVisionDistance))\n\t\t{\n\t\t\treturn true; // we already sense the unit, no need to check obstacles or smoke\n\t\t}\n\t}\n\n\tconst auto [visibleDistanceMaxVoxel, visibleDistanceUnitMaxTile] = getVisibleDistanceMaxHelper(this, tile, currentUnit, tile->getUnit());\n\n\tPosition originVoxel = getSightOriginVoxel(currentUnit);\n\n\tPosition scanVoxel;\n\tbool unitSeen = canTargetUnit(&originVoxel, tile, &scanVoxel, currentUnit, false);\n\n\t// heat vision 100% = smoke effectiveness 0%\n\tint smokeDensityFactor = 100 - Clamp(currentUnit->getVisibilityThroughSmoke(), 0, 100);\n\tint fireDensityFactor = 100 - Clamp(currentUnit->getVisibilityThroughFire(), 0, 100);\n\n\tif (unitSeen)\n\t{\n\t\tconst auto [visibleDistanceVoxels, densityOfSmoke, densityOfFire, densityOfSmokeNearUnit, densityOfFireeNearUnit] = getTrajectoryDataHelper(this, _save, currentUnit, originVoxel, scanVoxel);\n\n\t\t// 3  - coefficient of calculation (see getTrajectoryDataHelper).\n\t\t// 20 - maximum view distance in vanilla Xcom.\n\t\t// 100 - % for smokeDensityFactor.\n\t\t// 16 - for voxel scale calculation.\n\t\t// Even if MaxViewDistance will be increased via ruleset, smoke will keep effect.\n\t\tint visibilityQuality = visibleDistanceMaxVoxel - visibleDistanceVoxels - ((densityOfSmoke - densityOfSmokeNearUnit / 2) * smokeDensityFactor + (densityOfFire - densityOfFireeNearUnit / 2) * fireDensityFactor) * visibleDistanceMaxVoxel/(3 * 20 * 100 * 16);\n\t\tModScript::VisibilityUnit::Output arg{ visibilityQuality, visibilityQuality, ScriptTag<BattleUnitVisibility>::getNullTag() };\n\t\tModScript::VisibilityUnit::Worker worker{ currentUnit, tile->getUnit(), tile, visibleDistanceVoxels, visibleDistanceMaxVoxel, visibleDistanceUnitMaxTile, densityOfSmoke, densityOfFire, densityOfSmokeNearUnit, densityOfFireeNearUnit };\n\t\tworker.execute(currentUnit->getArmor()->getScript<ModScript::VisibilityUnit>(), arg);\n\t\tunitSeen = 0 < arg.getFirst();\n\t}\n\treturn unitSeen;\n}\n\n/**\n * Checks to see if a tile is visible through darkness, obstacles and smoke.\n * Note: psi vision, camouflage/anti-camouflage are intentionally removed.\n * @param action Current battle action.\n * @param tile The tile to check for.\n * @return True if visible.\n */\nbool TileEngine::isTileInLOS(BattleAction *action, Tile *tile, bool drawing)\n{\n\t// if there is no tile, we can't see it\n\tif (!tile)\n\t{\n\t\treturn false;\n\t}\n\n\tBattleUnit *currentUnit = action->actor;\n\n\t// if beyond global max. range, nobody can see anything\n\tint currentDistanceSq = Position::distance2dSq(currentUnit->getPosition(), tile->getPosition());\n\tif (currentDistanceSq > getMaxViewDistanceSq())\n\t{\n\t\treturn false;\n\t}\n\n\tconst auto [visibleDistanceMaxVoxel, visibleDistanceUnitMaxTile] = getVisibleDistanceMaxHelper(this, tile, currentUnit, /*targetUnit*/ nullptr);\n\n\t// We MUST build a temp action, because current action doesn't yet have updated target (when only aiming)\n\tBattleAction tempAction;\n\ttempAction.actor = currentUnit;\n\ttempAction.type = action->type;\n\ttempAction.target = tile->getPosition();\n\n\tPosition originVoxel = getOriginVoxel(tempAction, currentUnit->getTile());\n\tPosition scanVoxel;\n\tstd::vector<Position> _trajectory;\n\tbool seen = false;\n\n\tbool forceFire = Options::forceFire && _save->isCtrlPressed(true) && _save->getSide() == FACTION_PLAYER;\n\n\t// Primary LOF check\n\tif (forceFire)\n\t{\n\t\t// if force-firing, always aim at the center of the target tile\n\t\tscanVoxel = tile->getPosition().toVoxel() + TileEngine::voxelTileCenter;\n\t}\n\telse if (tile->getMapData(O_OBJECT) != 0)\n\t{\n\t\tif (canTargetTile(&originVoxel, tile, O_OBJECT, &scanVoxel, currentUnit, false))\n\t\t{\n\t\t\tseen = true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tscanVoxel = tile->getPosition().toVoxel() + Position(8, 8, 10);\n\t\t}\n\t}\n\telse if (tile->getMapData(O_NORTHWALL) != 0)\n\t{\n\t\tif (canTargetTile(&originVoxel, tile, O_NORTHWALL, &scanVoxel, currentUnit, false))\n\t\t{\n\t\t\tseen = true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tscanVoxel = tile->getPosition().toVoxel() + Position(8, 0, 9);\n\t\t}\n\t}\n\telse if (tile->getMapData(O_WESTWALL) != 0)\n\t{\n\t\tif (canTargetTile(&originVoxel, tile, O_WESTWALL, &scanVoxel, currentUnit, false))\n\t\t{\n\t\t\tseen = true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tscanVoxel = tile->getPosition().toVoxel() + Position(0, 8, 9);\n\t\t}\n\t}\n\telse if (tile->getMapData(O_FLOOR) != 0)\n\t{\n\t\tif (canTargetTile(&originVoxel, tile, O_FLOOR, &scanVoxel, currentUnit, false))\n\t\t{\n\t\t\tseen = true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tscanVoxel = tile->getPosition().toVoxel() + Position(8, 8, 2);\n\t\t}\n\t}\n\telse\n\t{\n\t\tscanVoxel = tile->getPosition().toVoxel() + Position(8, 8, 12);\n\t}\n\n\t// Secondary LOF check\n\tif (!seen)\n\t{\n\t\tint test = calculateLineVoxel(originVoxel, scanVoxel, false, &_trajectory, currentUnit);\n\t\tif (test == V_EMPTY)\n\t\t{\n\t\t\t// We have hit nothing at all, LOF is clear (Note: _trajectory is empty)\n\t\t\tseen = true;\n\t\t}\n\t\telse if (test == V_OUTOFBOUNDS)\n\t\t{\n\t\t\t// FIXME/TESTME\n\t\t\tseen = false;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// Let's assume we hit and double-check\n\t\t\tseen = true;\n\n\t\t\t// inspired by Projectile::calculateTrajectory()\n\t\t\tPosition hitPos = _trajectory.at(0).toTile();\n\t\t\tif (test == V_UNIT && _save->getTile(hitPos) && _save->getTile(hitPos)->getUnit() == 0) //no unit? must be lower\n\t\t\t{\n\t\t\t\thitPos = Position(hitPos.x, hitPos.y, hitPos.z - 1);\n\t\t\t}\n\n\t\t\tif (hitPos != tempAction.target /*&& tempAction.result.empty()*/)\n\t\t\t{\n\t\t\t\tif (test == V_NORTHWALL)\n\t\t\t\t{\n\t\t\t\t\tif (hitPos.y - 1 != tempAction.target.y)\n\t\t\t\t\t{\n\t\t\t\t\t\tseen = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (test == V_WESTWALL)\n\t\t\t\t{\n\t\t\t\t\tif (hitPos.x - 1 != tempAction.target.x)\n\t\t\t\t\t{\n\t\t\t\t\t\tseen = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (test == V_UNIT)\n\t\t\t\t{\n\t\t\t\t\tBattleUnit *hitUnit = _save->getTile(hitPos)->getUnit();\n\t\t\t\t\tBattleUnit *targetUnit = drawing ? tile->getUnit() : tile->getOverlappingUnit(_save);\n\t\t\t\t\tif (hitUnit != targetUnit)\n\t\t\t\t\t{\n\t\t\t\t\t\tseen = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tseen = false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// LOS check uses sight origin voxel (LOF check uses origin voxel)\n\toriginVoxel = getSightOriginVoxel(currentUnit);\n\n\t// heat vision 100% = smoke effectiveness 0%\n\tint smokeDensityFactor = 100 - Clamp(currentUnit->getVisibilityThroughSmoke(), 0, 100);\n\tint fireDensityFactor = 100 - Clamp(currentUnit->getVisibilityThroughFire(), 0, 100);\n\n\tif (seen)\n\t{\n\t\tconst auto [visibleDistanceVoxels, densityOfSmoke, densityOfFire, densityOfSmokeNearUnit, densityOfFireeNearUnit] = getTrajectoryDataHelper(this, _save, currentUnit, originVoxel, scanVoxel);\n\n\t\t// 3  - coefficient of calculation (see getTrajectoryDataHelper).\n\t\t// 20 - maximum view distance in vanilla Xcom.\n\t\t// 100 - % for smokeDensityFactor.\n\t\t// 16 - for voxel scale calculation.\n\t\t// Even if MaxViewDistance will be increased via ruleset, smoke will keep effect.\n\t\tint visibilityQuality = visibleDistanceMaxVoxel - visibleDistanceVoxels - ((densityOfSmoke - densityOfSmokeNearUnit / 2) * smokeDensityFactor + (densityOfFire - densityOfFireeNearUnit / 2) * fireDensityFactor) * visibleDistanceMaxVoxel/(3 * 20 * 100 * 16);\n\t\tModScript::VisibilityUnit::Output arg{ visibilityQuality, visibilityQuality, ScriptTag<BattleUnitVisibility>::getNullTag() };\n\t\tModScript::VisibilityUnit::Worker worker{ currentUnit, /*targetUnit*/ nullptr, tile, visibleDistanceVoxels, visibleDistanceMaxVoxel, visibleDistanceUnitMaxTile, densityOfSmoke, densityOfFire, densityOfSmokeNearUnit, densityOfFireeNearUnit };\n\t\tworker.execute(currentUnit->getArmor()->getScript<ModScript::VisibilityUnit>(), arg);\n\t\tseen = 0 < arg.getFirst();\n\t}\n\treturn seen;\n}\n\n/**\n * Checks for how exposed unit is for another unit.\n * @param originVoxel Voxel of trace origin (eye or gun's barrel).\n * @param tile The tile to check for.\n * @param excludeUnit Is self (not to hit self).\n * @param excludeAllBut [Optional] is unit which is the only one to be considered for ray hits.\n * @return Degree of exposure (as percent).\n */\nint TileEngine::checkVoxelExposure(Position *originVoxel, Tile *tile, BattleUnit *excludeUnit, BattleUnit *excludeAllBut)\n{\n\tPosition targetVoxel = tile->getPosition().toVoxel() + Position(8, 8, 0);\n\tPosition scanVoxel;\n\tstd::vector<Position> _trajectory;\n\tBattleUnit *otherUnit = tile->getUnit();\n\tif (otherUnit == 0) return 0; //no unit in this tile, even if it elevated and appearing in it.\n\tif (otherUnit == excludeUnit) return 0; //skip self\n\n\tint targetMinHeight = targetVoxel.z - tile->getTerrainLevel();\n\tif (otherUnit)\n\t\t targetMinHeight += otherUnit->getFloatHeight();\n\n\t// if there is an other unit on target tile, we assume we want to check against this unit's height\n\tint heightRange;\n\n\tint unitRadius = otherUnit->getLoftemps(); //width == loft in default loftemps set\n\tif (otherUnit->isBigUnit())\n\t{\n\t\tunitRadius = 3;\n\t}\n\n\t// vector manipulation to make scan work in view-space\n\tPosition relPos = targetVoxel - *originVoxel;\n\tfloat normal = unitRadius/sqrt((float)(relPos.x*relPos.x + relPos.y*relPos.y));\n\tint relX = floor(((float)relPos.y)*normal+0.5);\n\tint relY = floor(((float)-relPos.x)*normal+0.5);\n\n\tint sliceTargets[] = {0,0, relX,relY, -relX,-relY};\n\n\tif (!otherUnit->isOut())\n\t{\n\t\theightRange = otherUnit->getHeight();\n\t}\n\telse\n\t{\n\t\theightRange = 12;\n\t}\n\n\tint targetMaxHeight=targetMinHeight+heightRange;\n\t// scan ray from top to bottom  plus different parts of target cylinder\n\tint total=0;\n\tint visible=0;\n\tfor (int i = heightRange; i >=0; i-=2)\n\t{\n\t\t++total;\n\t\tscanVoxel.z=targetMinHeight+i;\n\t\tfor (int j = 0; j < 3; ++j)\n\t\t{\n\t\t\tscanVoxel.x=targetVoxel.x + sliceTargets[j*2];\n\t\t\tscanVoxel.y=targetVoxel.y + sliceTargets[j*2+1];\n\t\t\t_trajectory.clear();\n\t\t\tint test = calculateLineVoxel(*originVoxel, scanVoxel, false, &_trajectory, excludeUnit, excludeAllBut);\n\t\t\tif (test == V_UNIT)\n\t\t\t{\n\t\t\t\t//voxel of hit must be inside of scanned box\n\t\t\t\tif (_trajectory.at(0).x/16 == scanVoxel.x/16 &&\n\t\t\t\t\t_trajectory.at(0).y/16 == scanVoxel.y/16 &&\n\t\t\t\t\t_trajectory.at(0).z >= targetMinHeight &&\n\t\t\t\t\t_trajectory.at(0).z <= targetMaxHeight)\n\t\t\t\t{\n\t\t\t\t\t++visible;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn (visible*100)/total;\n}\n\n/**\n * Checks for another unit available for targeting and what particular voxel.\n * @param originVoxel Voxel of trace origin (eye or gun's barrel).\n * @param tile The tile to check for.\n * @param scanVoxel is returned coordinate of hit.\n * @param excludeUnit is self (not to hit self).\n * @param rememberObstacles Remember obstacles for no LOF indicator?\n * @param potentialUnit is a hypothetical unit to draw a virtual line of fire for AI. if left blank, this function behaves normally.\n * @return True if the unit can be targetted.\n */\nbool TileEngine::canTargetUnit(Position *originVoxel, Tile *tile, Position *scanVoxel, BattleUnit *excludeUnit, bool rememberObstacles, BattleUnit *potentialUnit)\n{\n\tPosition targetVoxel = tile->getPosition().toVoxel() + Position(8, 8, 0);\n\tstd::vector<Position> _trajectory;\n\tbool hypothetical = potentialUnit != 0;\n\tif (potentialUnit == 0)\n\t{\n\t\tpotentialUnit = tile->getUnit();\n\t\tif (potentialUnit == 0) return false; //no unit in this tile, even if it elevated and appearing in it.\n\t}\n\n\tif (potentialUnit == excludeUnit) return false; //skip self\n\n\tint targetMinHeight = targetVoxel.z - tile->getTerrainLevel();\n\ttargetMinHeight += potentialUnit->getFloatHeight();\n\n\tint targetMaxHeight = targetMinHeight;\n\tint targetCenterHeight;\n\t// if there is an other unit on target tile, we assume we want to check against this unit's height\n\tint heightRange;\n\n\tint unitRadius = potentialUnit->getLoftemps(); //width == loft in default loftemps set\n\tint targetSize = potentialUnit->getArmor()->getSize() - 1;\n\tint xOffset = potentialUnit->getPosition().x - tile->getPosition().x;\n\tint yOffset = potentialUnit->getPosition().y - tile->getPosition().y;\n\tif (targetSize > 0)\n\t{\n\t\tunitRadius = 3;\n\t}\n\t// vector manipulation to make scan work in view-space\n\tPosition relPos = targetVoxel - *originVoxel;\n\tfloat normal = unitRadius/sqrt((float)(relPos.x*relPos.x + relPos.y*relPos.y));\n\tint relX = floor(((float)relPos.y)*normal+0.5);\n\tint relY = floor(((float)-relPos.x)*normal+0.5);\n\n\tint sliceTargets[] = {0,0, relX,relY, -relX,-relY, relY,-relX, -relY,relX};\n\n\tif (!potentialUnit->isOut())\n\t{\n\t\theightRange = potentialUnit->getHeight();\n\t}\n\telse\n\t{\n\t\theightRange = 12;\n\t}\n\n\ttargetMaxHeight += heightRange;\n\ttargetCenterHeight=(targetMaxHeight+targetMinHeight)/2;\n\theightRange/=2;\n\tif (heightRange>10) heightRange=10;\n\tif (heightRange<=0) heightRange=0;\n\n\t// scan ray from top to bottom  plus different parts of target cylinder\n\tfor (int i = 0; i <= heightRange; ++i)\n\t{\n\t\tscanVoxel->z=targetCenterHeight+heightFromCenter[i];\n\t\tfor (int j = 0; j < 5; ++j)\n\t\t{\n\t\t\tif (i < (heightRange-1) && j>2) break; //skip unnecessary checks\n\t\t\tscanVoxel->x=targetVoxel.x + sliceTargets[j*2];\n\t\t\tscanVoxel->y=targetVoxel.y + sliceTargets[j*2+1];\n\t\t\t_trajectory.clear();\n\t\t\tint test = calculateLineVoxel(*originVoxel, *scanVoxel, false, &_trajectory, excludeUnit);\n\t\t\tif (test == V_UNIT)\n\t\t\t{\n\t\t\t\tfor (int x = 0; x <= targetSize; ++x)\n\t\t\t\t{\n\t\t\t\t\tfor (int y = 0; y <= targetSize; ++y)\n\t\t\t\t\t{\n\t\t\t\t\t\t//voxel of hit must be inside of scanned box\n\t\t\t\t\t\tif (_trajectory.at(0).x/16 == (scanVoxel->x/16) + x + xOffset &&\n\t\t\t\t\t\t\t_trajectory.at(0).y/16 == (scanVoxel->y/16) + y + yOffset &&\n\t\t\t\t\t\t\t_trajectory.at(0).z >= targetMinHeight &&\n\t\t\t\t\t\t\t_trajectory.at(0).z <= targetMaxHeight)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (test == V_EMPTY && hypothetical && !_trajectory.empty())\n\t\t\t{\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tif (rememberObstacles && _trajectory.size()>0)\n\t\t\t{\n\t\t\t\tTile *tileObstacle = _save->getTile(_trajectory.at(0).toTile());\n\t\t\t\tif (tileObstacle) tileObstacle->setObstacle(test);\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Checks for a tile part available for targeting and what particular voxel.\n * @param originVoxel Voxel of trace origin (gun's barrel).\n * @param tile The tile to check for.\n * @param part Tile part to check for.\n * @param scanVoxel Is returned coordinate of hit.\n * @param excludeUnit Is self (not to hit self).\n * @param rememberObstacles Remember obstacles for no LOF indicator?\n * @return True if the tile can be targetted.\n */\nbool TileEngine::canTargetTile(Position *originVoxel, Tile *tile, int part, Position *scanVoxel, BattleUnit *excludeUnit, bool rememberObstacles)\n{\n\tstatic int sliceObjectSpiral[82] = {8,8, 8,6, 10,6, 10,8, 10,10, 8,10, 6,10, 6,8, 6,6, //first circle\n\t\t8,4, 10,4, 12,4, 12,6, 12,8, 12,10, 12,12, 10,12, 8,12, 6,12, 4,12, 4,10, 4,8, 4,6, 4,4, 6,4, //second circle\n\t\t8,1, 12,1, 15,1, 15,4, 15,8, 15,12, 15,15, 12,15, 8,15, 4,15, 1,15, 1,12, 1,8, 1,4, 1,1, 4,1}; //third circle\n\tstatic int westWallSpiral[14] = {0,7, 0,9, 0,6, 0,11, 0,4, 0,13, 0,2};\n\tstatic int northWallSpiral[14] = {7,0, 9,0, 6,0, 11,0, 4,0, 13,0, 2,0};\n\n\tPosition targetVoxel = Position((tile->getPosition().x * 16), (tile->getPosition().y * 16), tile->getPosition().z * 24);\n\tstd::vector<Position> _trajectory;\n\n\tint *spiralArray;\n\tint spiralCount;\n\n\tint minZ = 0, maxZ = 0;\n\tbool minZfound = false, maxZfound = false;\n\tbool dummy = false;\n\n\tif (part == O_OBJECT)\n\t{\n\t\tspiralArray = sliceObjectSpiral;\n\t\tspiralCount = 41;\n\t}\n\telse\n\tif (part == O_NORTHWALL)\n\t{\n\t\tspiralArray = northWallSpiral;\n\t\tspiralCount = 7;\n\t}\n\telse\n\tif (part == O_WESTWALL)\n\t{\n\t\tspiralArray = westWallSpiral;\n\t\tspiralCount = 7;\n\t}\n\telse if (part == O_FLOOR)\n\t{\n\t\tspiralArray = sliceObjectSpiral;\n\t\tspiralCount = 41;\n\t\tminZfound = true; minZ=0;\n\t\tmaxZfound = true; maxZ=0;\n\t}\n\telse if (part == MapData::O_DUMMY) // used only for no line of fire indicator\n\t{\n\t\tspiralArray = sliceObjectSpiral;\n\t\tspiralCount = 41;\n\t\tminZfound = true; minZ = 12;\n\t\tmaxZfound = true; maxZ = 12;\n\t}\n\telse\n\t{\n\t\treturn false;\n\t}\n\tvoxelCheckFlush();\n// find out height range\n\n\tif (!minZfound)\n\t{\n\t\tfor (int j = 1; j < 12; ++j)\n\t\t{\n\t\t\tif (minZfound) break;\n\t\t\tfor (int i = 0; i < spiralCount; ++i)\n\t\t\t{\n\t\t\t\tint tX = spiralArray[i*2];\n\t\t\t\tint tY = spiralArray[i*2+1];\n\t\t\t\tif (voxelCheck(Position(targetVoxel.x + tX, targetVoxel.y + tY, targetVoxel.z + j*2),0,true) == part) //bingo\n\t\t\t\t{\n\t\t\t\t\tif (!minZfound)\n\t\t\t\t\t{\n\t\t\t\t\t\tminZ = j*2;\n\t\t\t\t\t\tminZfound = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (!minZfound)\n\t{\n\t\tif (rememberObstacles)\n\t\t{\n\t\t\t// dummy attempt (only to highlight obstacles)\n\t\t\tminZfound = true;\n\t\t\tminZ = 10;\n\t\t\tdummy = true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn false;//empty object!!!\n\t\t}\n\t}\n\n\tif (!maxZfound)\n\t{\n\t\tfor (int j = 10; j >= 0; --j)\n\t\t{\n\t\t\tif (maxZfound) break;\n\t\t\tfor (int i = 0; i < spiralCount; ++i)\n\t\t\t{\n\t\t\t\tint tX = spiralArray[i*2];\n\t\t\t\tint tY = spiralArray[i*2+1];\n\t\t\t\tif (voxelCheck(Position(targetVoxel.x + tX, targetVoxel.y + tY, targetVoxel.z + j*2),0,true) == part) //bingo\n\t\t\t\t{\n\t\t\t\t\tif (!maxZfound)\n\t\t\t\t\t{\n\t\t\t\t\t\tmaxZ = j*2;\n\t\t\t\t\t\tmaxZfound = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (!maxZfound)\n\t{\n\t\tif (rememberObstacles)\n\t\t{\n\t\t\t// dummy attempt (only to highlight obstacles)\n\t\t\tmaxZfound = true;\n\t\t\tmaxZ = 10;\n\t\t\tdummy = true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn false;//it's impossible to get there\n\t\t}\n\t}\n\n\tif (minZ > maxZ) minZ = maxZ;\n\tint rangeZ = maxZ - minZ;\n\tif (rangeZ>10) rangeZ = 10; //as above, clamping height range to prevent buffer overflow\n\tint centerZ = (maxZ + minZ)/2;\n\n\tfor (int j = 0; j <= rangeZ; ++j)\n\t{\n\t\tscanVoxel->z = targetVoxel.z + centerZ + heightFromCenter[j];\n\t\tfor (int i = 0; i < spiralCount; ++i)\n\t\t{\n\t\t\tscanVoxel->x = targetVoxel.x + spiralArray[i*2];\n\t\t\tscanVoxel->y = targetVoxel.y + spiralArray[i*2+1];\n\t\t\t_trajectory.clear();\n\t\t\tint test = calculateLineVoxel(*originVoxel, *scanVoxel, false, &_trajectory, excludeUnit);\n\t\t\tif (test == part && !dummy) //bingo\n\t\t\t{\n\t\t\t\tif (_trajectory.at(0).x/16 == scanVoxel->x/16 &&\n\t\t\t\t\t_trajectory.at(0).y/16 == scanVoxel->y/16 &&\n\t\t\t\t\t_trajectory.at(0).z/24 == scanVoxel->z/24)\n\t\t\t\t{\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (rememberObstacles && _trajectory.size()>0)\n\t\t\t{\n\t\t\t\tTile *tileObstacle = _save->getTile(_trajectory.at(0).toTile());\n\t\t\t\tif (tileObstacle) tileObstacle->setObstacle(test);\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Calculates line of sight of a soldiers within range of the Position\n * (used when terrain has changed, which can reveal new parts of terrain or units).\n * @param position Position of the changed terrain.\n * @param eventRadius Radius of circle big enough to encompass the event.\n * @param updateTiles true to do an update of visible tiles.\n * @param appendToTileVisibility true to append only new tiles and skip previously seen ones.\n */\nvoid TileEngine::calculateFOV(Position position, int eventRadius, const bool updateTiles, const bool appendToTileVisibility)\n{\n\tint updateRadius;\n\tif (eventRadius == -1)\n\t{\n\t\teventRadius = getMaxViewDistance();\n\t\tupdateRadius = getMaxViewDistanceSq();\n\t}\n\telse\n\t{\n\t\t//Need to grab units which are out of range of the centre of the event, but can still see the edge of the effect.\n\t\tupdateRadius = getMaxViewDistance() + (eventRadius > 0 ? eventRadius : 0);\n\t\tupdateRadius *= updateRadius;\n\t}\n\tfor (auto* bu : *_save->getUnits())\n\t{\n\t\tif (Position::distance2dSq(position, bu->getPosition()) <= updateRadius) //could this unit have observed the event?\n\t\t{\n\t\t\tif (updateTiles)\n\t\t\t{\n\t\t\t\tif (!appendToTileVisibility)\n\t\t\t\t{\n\t\t\t\t\tbu->clearVisibleTiles();\n\t\t\t\t}\n\t\t\t\tcalculateTilesInFOV(bu, position, eventRadius);\n\t\t\t}\n\n\t\t\tcalculateUnitsInFOV(bu, position, eventRadius);\n\t\t}\n\t}\n}\n\n/**\n * Checks if a sniper from the opposing faction sees this unit. The unit with the highest reaction score will be compared with the current unit's reaction score.\n * If it's higher, a shot is fired when enough time units, a weapon and ammo are available.\n * @param unit The unit to check reaction fire upon.\n * @return True if reaction fire took place.\n */\nbool TileEngine::checkReactionFire(BattleUnit *unit, const BattleAction &originalAction)\n{\n\tif (_save->isPreview())\n\t{\n\t\treturn false;\n\t}\n\n\t// reaction fire only triggered when the actioning unit is of the currently playing side, and is still on the map (alive)\n\tif (unit->getFaction() != _save->getSide() || unit->getTile() == 0)\n\t{\n\t\treturn false;\n\t}\n\n\tstd::vector<ReactionScore> spotters = getSpottingUnits(unit);\n\tbool result = false;\n\n\t// not mind controlled, or controlled by the player\n\tif (unit->getFaction() == unit->getOriginalFaction()\n\t\t|| unit->getFaction() != FACTION_HOSTILE)\n\t{\n\t\t// get the first man up to bat.\n\t\tReactionScore *reactor = getReactor(spotters, unit);\n\t\t// start iterating through the possible reactors until the current unit is the one with the highest score.\n\t\twhile (reactor != 0)\n\t\t{\n\t\t\tif (reactor->count > 10 || !tryReaction(reactor, unit, originalAction))\n\t\t\t{\n\t\t\t\tfor (std::vector<ReactionScore>::iterator i = spotters.begin(); i != spotters.end(); ++i)\n\t\t\t\t{\n\t\t\t\t\tif (&(*i) == reactor)\n\t\t\t\t\t{\n\t\t\t\t\t\tspotters.erase(i);\n\t\t\t\t\t\treactor = 0;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// can't make a reaction snapshot for whatever reason, boot this guy from the vector.\n\t\t\t\t// avoid setting result to true, but carry on, just cause one unit can't react doesn't mean the rest of the units in the vector (if any) can't\n\t\t\t\treactor = getReactor(spotters, unit);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// nice shot, kid. don't get cocky.\n\t\t\tresult = true;\n\t\t\treactor->reactionScore -= reactor->reactionReduction;\n\t\t\treactor->count += 1;\n\t\t\treactor = getReactor(spotters, unit);\n\t\t}\n\t}\n\treturn result;\n}\n\n/**\n * Creates a vector of units that can spot this unit.\n * @param unit The unit to check for spotters of.\n * @return A vector of units that can see this unit.\n */\nstd::vector<TileEngine::ReactionScore> TileEngine::getSpottingUnits(BattleUnit* unit)\n{\n\tstd::vector<TileEngine::ReactionScore> spotters;\n\tTile *tile = unit->getTile();\n\tint threshold = unit->getReactionScore();\n\t// no reaction on civilian turn.\n\tif (_save->getSide() != FACTION_NEUTRAL)\n\t{\n\t\tfor (auto* bu : *_save->getUnits())\n\t\t{\n\t\t\t\t// not dead/unconscious\n\t\t\tif (!bu->isOut() &&\n\t\t\t\t// not dying or not about to pass out\n\t\t\t\t!bu->isOutThresholdExceed() &&\n\t\t\t\t// have any chances for reacting\n\t\t\t\tbu->getReactionScore() >= threshold &&\n\t\t\t\t// not a friend\n\t\t\t\tbu->getFaction() != _save->getSide() &&\n\t\t\t\t// not a civilian, or a civilian shooting at bad non-ignored guys\n\t\t\t\t(bu->getFaction() != FACTION_NEUTRAL || (unit->getFaction() == FACTION_HOSTILE && !unit->isIgnoredByAI())) &&\n\t\t\t\t// closer than 20 tiles\n\t\t\t\tPosition::distance2dSq(unit->getPosition(), bu->getPosition()) <= getMaxViewDistanceSq())\n\t\t\t{\n\t\t\t\tBattleAction falseAction;\n\t\t\t\tfalseAction.type = BA_SNAPSHOT;\n\t\t\t\tfalseAction.actor = bu;\n\t\t\t\tfalseAction.target = unit->getPosition();\n\t\t\t\tPosition originVoxel = getOriginVoxel(falseAction, 0);\n\t\t\t\tPosition targetVoxel;\n\t\t\t\tAIModule *ai = bu->getAIModule();\n\n\t\t\t\t// Inquisitor's note regarding 'gotHit' variable\n\t\t\t\t// in vanilla, the 'hitState' flag is the only part of this equation that comes into play.\n\t\t\t\t// any time a unit takes damage, this flag is set, then it would be reset by a call to\n\t\t\t\t// a function analogous to SavedBattleGame::resetUnitHitStates(), any time:\n\t\t\t\t// 1: a unit was selected by being clicked on.\n\t\t\t\t// 2: either \"next unit\" button was pressed.\n\t\t\t\t// 3: the inventory screen was accessed. (i didn't look too far into this one, it's possible it's only called in the pre-mission equip screen)\n\t\t\t\t// 4: the same place where we call it, immediately before every move the AI makes.\n\t\t\t\t// this flag is responsible for units turning around to respond to hits, and is in keeping with the details listed on http://www.ufopaedia.org/index.php/Reaction_fire_triggers\n\t\t\t\t// we've gone for a slightly different implementation: AI units keep a list of which units have hit them and don't forget until the end of the player's turn.\n\t\t\t\t// this method is in keeping with the spirit of the original feature, but much less exploitable by players.\n\t\t\t\t// the hitState flag in our implementation allows player units to turn and react as they did in the original, (which is far less cumbersome than giving them all an AI module)\n\t\t\t\t// we don't extend the same \"enhanced aggressor memory\" courtesy to players, because in the original, they could only turn and react to damage immediately after it happened.\n\t\t\t\t// this is because as much as we want the player's soldiers dead, we don't want them to feel like we're being unfair about it.\n\n\t\t\t\tbool gotHit = (ai != 0 && ai->getWasHitBy(unit->getId())) || (ai == 0 && bu->getHitState());\n\n\t\t\t\tif (!gotHit && Mod::EXTENDED_MELEE_REACTIONS == 2)\n\t\t\t\t{\n\t\t\t\t\t// to allow melee reactions when attacked from any side, not just from the front\n\t\t\t\t\tgotHit = bu->wasMeleeAttackedBy(unit->getId());\n\t\t\t\t}\n\n\t\t\t\t\t// can actually see the target Tile, or we got hit\n\t\t\t\tif ((bu->checkViewSector(unit->getPosition()) || gotHit) &&\n\t\t\t\t\t// can actually target the unit\n\t\t\t\t\tcanTargetUnit(&originVoxel, tile, &targetVoxel, bu, false) &&\n\t\t\t\t\t// can actually see the unit\n\t\t\t\t\tvisible(bu, tile))\n\t\t\t\t{\n\t\t\t\t\tif (bu->getFaction() == FACTION_PLAYER)\n\t\t\t\t\t{\n\t\t\t\t\t\tunit->setVisible(true);\n\t\t\t\t\t}\n\t\t\t\t\tbu->addToVisibleUnits(unit);\n\t\t\t\t\tReactionScore rs = determineReactionType(bu, unit);\n\t\t\t\t\tif (rs.attackType != BA_NONE)\n\t\t\t\t\t{\n\t\t\t\t\t\tint reactionFireThreshold = _save->getBattleGame()->getMod()->getReactionFireThreshold(bu->getFaction());\n\t\t\t\t\t\tif (reactionFireThreshold > 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tBattleItem *weapon = rs.weapon;\n\t\t\t\t\t\t\tint accuracy = BattleUnit::getFiringAccuracy(BattleActionAttack::GetBeforeShoot(rs.attackType, rs.unit, weapon), _save->getBattleGame()->getMod());\n\t\t\t\t\t\t\tint distanceSq = unit->distance3dToUnitSq(bu);\n\t\t\t\t\t\t\tint distance = (int)std::ceil(sqrt(float(distanceSq)));\n\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tint upperLimit, lowerLimit;\n\t\t\t\t\t\t\t\tint dropoff = weapon->getRules()->calculateLimits(upperLimit, lowerLimit, _save->getDepth(), rs.attackType);\n\n\t\t\t\t\t\t\t\tif (distance > upperLimit)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\taccuracy -= (distance - upperLimit) * dropoff;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse if (distance < lowerLimit)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\taccuracy -= (lowerLimit - distance) * dropoff;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tbool outOfRange = weapon->getRules()->isOutOfRange(distanceSq);\n\n\t\t\t\t\t\t\tif (accuracy >= reactionFireThreshold && !outOfRange)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tspotters.push_back(rs);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tspotters.push_back(rs);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn spotters;\n}\n\n/**\n * Gets the unit with the highest reaction score from the spotter vector.\n * @param spotters The vector of spotting units.\n * @param unit The unit to check scores against.\n * @return The unit with the highest reactions.\n */\nTileEngine::ReactionScore *TileEngine::getReactor(std::vector<TileEngine::ReactionScore> &spotters, BattleUnit *unit)\n{\n\tReactionScore *best = 0;\n\tfor (std::vector<ReactionScore>::iterator i = spotters.begin(); i != spotters.end(); ++i)\n\t{\n\t\tif (!(*i).unit->isOut() && !(*i).unit->getRespawn() && (!best || (*i).reactionScore > best->reactionScore))\n\t\t{\n\t\t\tbest = &(*i);\n\t\t}\n\t}\n\tif (best &&(unit->getReactionScore() <= best->reactionScore))\n\t{\n\t\tif (best->unit->getOriginalFaction() == FACTION_PLAYER)\n\t\t{\n\t\t\tbest->unit->addReactionExp();\n\t\t}\n\t}\n\telse\n\t{\n\t\tbest = 0;\n\t}\n\treturn best;\n}\n\n/**\n * Checks the validity of a snap shot performed here.\n * @param unit The unit to check sight from.\n * @param target The unit to check sight TO.\n * @return True if the target is valid.\n */\nTileEngine::ReactionScore TileEngine::determineReactionType(BattleUnit *unit, BattleUnit *target)\n{\n\tReactionScore reaction =\n\t{\n\t\tunit,\n\t\tnullptr,\n\t\tBA_NONE,\n\t\tunit->getReactionScore(),\n\t\t0.0,\n\t\t1,\n\t};\n\n\t// to avoid 0 that cause infinite loop we set minimal reaction handled by logic, should correctly handle units with 1 point in reaction and 1/1000 TU\n\tif (reaction.reactionScore <= 0.001)\n\t{\n\t\treturn reaction;\n\t}\n\n\tauto setReaction = [](ReactionScore& re, BattleActionType type, BattleItem* weapon)\n\t{\n\t\tre.attackType = type;\n\t\tre.weapon = weapon;\n\t\tre.reactionReduction = 1.0 * BattleActionCost(type, re.unit, weapon).Time * re.unit->getBaseStats()->reactions / re.unit->getBaseStats()->tu;\n\t};\n\n\tstd::vector<BattleItem*> reactionWeapons;\n\t// 1. first try the preferred weapon (player units only... to prevent abuse)\n\tbool isPlayer = (unit->getFaction() == FACTION_PLAYER);\n\tif (isPlayer)\n\t{\n\t\tif (BattleItem* preferredWeapon = unit->getWeaponForReactions())\n\t\t{\n\t\t\treactionWeapons.push_back(preferredWeapon);\n\t\t}\n\t}\n\t// 2. then prioritize melee\n\tif (BattleItem* meleeWeapon = unit->getUtilityWeapon(BT_MELEE))\n\t{\n\t\treactionWeapons.push_back(meleeWeapon);\n\t}\n\t// 3. then the rest (AI: quickest weapon, Player: last selected/main weapon)\n\tif (BattleItem* otherWeapon = unit->getMainHandWeapon(!isPlayer, true))\n\t{\n\t\treactionWeapons.push_back(otherWeapon);\n\t}\n\n\tint tempDirection = unit->getDirection();\n\tif (Mod::EXTENDED_MELEE_REACTIONS == 2)\n\t{\n\t\t// temporarily face the target to allow melee reactions when attacked from any side, not just from the front\n\t\ttempDirection = getDirectionTo(unit->getPosition(), target->getPosition());\n\t}\n\n\tBattleItem* disabledLeft = nullptr;\n\tBattleItem* disabledRight = nullptr;\n\t// player units only... to prevent abuse\n\tif (isPlayer)\n\t{\n\t\tBattleItem* leftHandItem = unit->getLeftHandWeapon();\n\t\tBattleItem* rightHandItem = unit->getRightHandWeapon();\n\t\tBattleItem* emptyHandItem = nullptr;\n\t\tif ((!leftHandItem && unit->isLeftHandDisabledForReactions()) || (!rightHandItem && unit->isRightHandDisabledForReactions()))\n\t\t{\n\t\t\tauto typesToCheck = { BT_MELEE, BT_PSIAMP, BT_FIREARM/*, BT_MEDIKIT, BT_SCANNER, BT_MINDPROBE*/ };\n\t\t\tfor (auto& type : typesToCheck)\n\t\t\t{\n\t\t\t\temptyHandItem = unit->getSpecialWeapon(type);\n\t\t\t\tif (emptyHandItem && emptyHandItem->getRules()->isSpecialUsingEmptyHand())\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\temptyHandItem = nullptr;\n\t\t\t}\n\t\t}\n\t\tdisabledLeft = unit->isLeftHandDisabledForReactions() ? (leftHandItem ? leftHandItem : emptyHandItem) : nullptr;\n\t\tdisabledRight = unit->isRightHandDisabledForReactions() ? (rightHandItem ? rightHandItem : emptyHandItem) : nullptr;\n\t}\n\n\tfor (auto* weapon : reactionWeapons)\n\t{\n\t\tif (weapon == disabledLeft || weapon == disabledRight)\n\t\t{\n\t\t\t// the player doesn't want to react with this weapon\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (_save->canUseWeapon(weapon, unit, false, BA_HIT))\n\t\t{\n\t\t\t// has a weapon capable of melee and is in melee range\n\t\t\tif (validMeleeRange(unit, target, tempDirection) &&\n\t\t\t\tweapon->getAmmoForAction(BA_HIT) &&\n\t\t\t\tBattleActionCost(BA_HIT, unit, weapon).haveTU())\n\t\t\t{\n\t\t\t\tsetReaction(reaction, BA_HIT, weapon);\n\t\t\t\treturn reaction;\n\t\t\t}\n\t\t}\n\t\tif (_save->canUseWeapon(weapon, unit, false, BA_SNAPSHOT))\n\t\t{\n\t\t\t// has a gun capable of snap shot with ammo\n\t\t\tif (weapon->getRules()->getBattleType() == BT_FIREARM &&\n\t\t\t\t!weapon->getRules()->isOutOfRange(unit->distance3dToUnitSq(target)) &&\n\t\t\t\tweapon->getAmmoForAction(BA_SNAPSHOT) &&\n\t\t\t\tBattleActionCost(BA_SNAPSHOT, unit, weapon).haveTU())\n\t\t\t{\n\t\t\t\tsetReaction(reaction, BA_SNAPSHOT, weapon);\n\t\t\t\treturn reaction;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn reaction;\n}\n\n/**\n * Attempts to perform a reaction snap shot.\n * @param unit The unit to check sight from.\n * @param target The unit to check sight TO.\n * @return True if the action should (theoretically) succeed.\n */\nbool TileEngine::tryReaction(ReactionScore *reaction, BattleUnit *target, const BattleAction &originalAction)\n{\n\tBattleAction action;\n\taction.cameraPosition = _save->getBattleState()->getMap()->getCamera()->getMapOffset();\n\taction.actor = reaction->unit;\n\taction.weapon = reaction->weapon;\n\taction.type = reaction->attackType;\n\n\tif (!_save->canUseWeapon(action.weapon, action.actor, false, action.type))\n\t{\n\t\treturn false;\n\t}\n\n\taction.target = target->getPosition();\n\taction.updateTU();\n\n\tauto* unit = action.actor;\n\tauto* ammo = action.weapon->getAmmoForAction(action.type);\n\tif (ammo && action.haveTU())\n\t{\n\t\taction.targeting = true;\n\n\t\t// hostile units will go into an \"aggro\" state when they react.\n\t\tif (unit->getFaction() == FACTION_HOSTILE)\n\t\t{\n\t\t\tAIModule *ai = unit->getAIModule();\n\t\t\tif (ai == 0)\n\t\t\t{\n\t\t\t\t// should not happen, but just in case...\n\t\t\t\tai = new AIModule(_save, unit, 0);\n\t\t\t\tunit->setAIModule(ai);\n\t\t\t}\n\n\t\t\tint radius = ammo->getRules()->getExplosionRadius({ action.type, action.actor, action.weapon, ammo });\n\t\t\tif (action.type != BA_HIT && radius > 0 &&\n\t\t\t\tai->explosiveEfficacy(action.target, unit, radius, -1) == 0)\n\t\t\t{\n\t\t\t\taction.targeting = false;\n\t\t\t}\n\t\t}\n\n\t\tif (action.targeting)\n\t\t{\n\t\t\tint moveType = originalAction.getMoveType();\n\t\t\tint meleeReactionChance = Mod::EXTENDED_MELEE_REACTIONS > 0 ? 100 : 0;\n\t\t\tint reactionChance = BA_HIT != originalAction.type ? 100 : meleeReactionChance;\n\t\t\tint dist = Position::distance2d(unit->getPositionVexels(), target->getPositionVexels());\n\t\t\tint arc = getArcDirection(getDirectionTo(unit->getPositionVexels(), target->getPositionVexels()), unit->getDirection());\n\t\t\tauto* origTarg = _save->getTile(originalAction.target) ? _save->getTile(originalAction.target)->getUnit() : nullptr;\n\n\t\t\tModScript::ReactionCommon::Output arg{ reactionChance, dist };\n\t\t\tModScript::ReactionCommon::Worker worker{ target, unit, action.weapon, action.type, reaction->count, originalAction.weapon, originalAction.skillRules, originalAction.type, origTarg, moveType, arc, _save };\n\t\t\tif (originalAction.weapon)\n\t\t\t{\n\t\t\t\tworker.execute(originalAction.weapon->getRules()->getScript<ModScript::ReactionWeaponAction>(), arg);\n\t\t\t}\n\n\t\t\tworker.execute(target->getArmor()->getScript<ModScript::ReactionUnitAction>(), arg);\n\n\t\t\tworker.execute(unit->getArmor()->getScript<ModScript::ReactionUnitReaction>(), arg);\n\n\t\t\tif (RNG::percent(arg.getFirst()))\n\t\t\t{\n\t\t\t\t_save->appendToHitLog(HITLOG_REACTION_FIRE, unit->getFaction());\n\n\t\t\t\tif (action.type == BA_HIT)\n\t\t\t\t{\n\t\t\t\t\t_save->getBattleGame()->statePushBack(new MeleeAttackBState(_save->getBattleGame(), action));\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t_save->getBattleGame()->statePushBack(new ProjectileFlyBState(_save->getBattleGame(), action));\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Handling of hitting tile.\n * @param tile targeted tile.\n * @param damage power of hit.\n * @param type damage type of hit.\n * @return whether a smoke (1) or fire (2) effect was produced\n */\nint TileEngine::hitTile(Tile* tile, int damage, const RuleDamageType* type)\n{\n\tif (damage >= type->SmokeThreshold)\n\t{\n\t\t// smoke from explosions always stay 6 to 14 turns - power of a smoke grenade is 60\n\t\tif (tile->getSmoke() < _save->getBattleGame()->getMod()->getTooMuchSmokeThreshold() && tile->getTerrainLevel() > -24)\n\t\t{\n\t\t\ttile->setFire(0);\n\t\t\tif (damage >= type->SmokeThreshold * 2)\n\t\t\t\ttile->setSmoke(RNG::generate(7, 15)); // for SmokeThreshold == 0\n\t\t\telse\n\t\t\t\ttile->setSmoke(RNG::generate(7, 15) * (damage - type->SmokeThreshold) / type->SmokeThreshold);\n\t\t\treturn 1;\n\t\t}\n\t}\n\telse if (damage >= type->FireThreshold)\n\t{\n\t\tif (!tile->isVoid())\n\t\t{\n\t\t\tif (tile->getFire() == 0 && (tile->getMapData(O_FLOOR) || tile->getMapData(O_OBJECT)))\n\t\t\t{\n\t\t\t\tif (damage >= type->FireThreshold * 2)\n\t\t\t\t\ttile->setFire(tile->getFuel() + 1); // for FireThreshold == 0\n\t\t\t\telse\n\t\t\t\t\ttile->setFire(tile->getFuel() * (damage - type->FireThreshold) / type->FireThreshold + 1);\n\t\t\t\ttile->setSmoke(std::max(1, std::min(15 - (tile->getFlammability() / 10), 12)));\n\t\t\t\treturn 2;\n\t\t\t}\n\t\t}\n\t}\n\treturn 0;\n}\n\n/**\n * Handling of experience training.\n * @param unit hitter.\n * @param weapon weapon causing the damage.\n * @param target targeted unit.\n * @param rangeAtack is ranged attack or not?\n * @return Was experience awarded or not?\n */\nbool TileEngine::awardExperience(BattleActionAttack attack, BattleUnit *target, bool rangeAtack)\n{\n\tif (_save->isPreview())\n\t{\n\t\treturn false;\n\t}\n\n\tauto* unit = attack.attacker;\n\tauto* weapon = attack.weapon_item;\n\n\tif (!target)\n\t{\n\t\treturn false;\n\t}\n\n\tif (!weapon)\n\t{\n\t\treturn false;\n\t}\n\n\t// Mana experience - this is a temporary/experimental approach, can be improved later after modder feedback\n\tunit->addManaExp(weapon->getRules()->getManaExperience());\n\n\tusing upExpType = void (BattleUnit::*)();\n\n\tExperienceTrainingMode expType = weapon->getRules()->getExperienceTrainingMode();\n\tupExpType expFuncA = nullptr;\n\tupExpType expFuncB = nullptr;\n\tint expMultiply = 100;\n\n\tif (expType > ETM_DEFAULT)\n\t{\n\t\t// can train psi strength and psi skill only if psi skill is already > 0\n\t\tif (expType >= ETM_PSI_STRENGTH && expType <= ETM_PSI_STRENGTH_OR_SKILL_2X)\n\t\t{\n\t\t\t// cannot use \"unit->getBaseStats()->psiSkill\", because armor can give +psiSkill bonus\n\t\t\tif (unit->getGeoscapeSoldier() && unit->getGeoscapeSoldier()->getCurrentStats()->psiSkill <= 0)\n\t\t\t\treturn false;\n\t\t}\n\n\t\tswitch (weapon->getRules()->getExperienceTrainingMode())\n\t\t{\n\t\tcase ETM_MELEE_100: expFuncA = &BattleUnit::addMeleeExp; break;\n\t\tcase ETM_MELEE_50: expMultiply = 50; expFuncA = &BattleUnit::addMeleeExp; break;\n\t\tcase ETM_MELEE_33: expMultiply = 33; expFuncA = &BattleUnit::addMeleeExp; break;\n\t\tcase ETM_FIRING_100: expFuncA = &BattleUnit::addFiringExp; break;\n\t\tcase ETM_FIRING_50: expMultiply = 50; expFuncA = &BattleUnit::addFiringExp; break;\n\t\tcase ETM_FIRING_33: expMultiply = 33; expFuncA = &BattleUnit::addFiringExp; break;\n\t\tcase ETM_THROWING_100: expFuncA = &BattleUnit::addThrowingExp; break;\n\t\tcase ETM_THROWING_50: expMultiply = 50; expFuncA = &BattleUnit::addThrowingExp; break;\n\t\tcase ETM_THROWING_33: expMultiply = 33; expFuncA = &BattleUnit::addThrowingExp; break;\n\t\tcase ETM_FIRING_AND_THROWING: expFuncA = &BattleUnit::addFiringExp; expFuncB = &BattleUnit::addThrowingExp; break;\n\t\tcase ETM_FIRING_OR_THROWING: if (RNG::percent(50)) { expFuncA = &BattleUnit::addFiringExp; } else { expFuncA = &BattleUnit::addThrowingExp; } break;\n\t\tcase ETM_REACTIONS: expMultiply = 100; expFuncA = &BattleUnit::addReactionExp; break;\n\t\tcase ETM_REACTIONS_AND_MELEE: expFuncA = &BattleUnit::addReactionExp; expFuncB = &BattleUnit::addMeleeExp; break;\n\t\tcase ETM_REACTIONS_AND_FIRING: expFuncA = &BattleUnit::addReactionExp; expFuncB = &BattleUnit::addFiringExp; break;\n\t\tcase ETM_REACTIONS_AND_THROWING: expFuncA = &BattleUnit::addReactionExp; expFuncB = &BattleUnit::addThrowingExp; break;\n\t\tcase ETM_REACTIONS_OR_MELEE: if (RNG::percent(50)) { expFuncA = &BattleUnit::addReactionExp; } else { expFuncA = &BattleUnit::addMeleeExp; } break;\n\t\tcase ETM_REACTIONS_OR_FIRING: if (RNG::percent(50)) { expFuncA = &BattleUnit::addReactionExp; } else { expFuncA = &BattleUnit::addFiringExp; } break;\n\t\tcase ETM_REACTIONS_OR_THROWING: if (RNG::percent(50)) { expFuncA = &BattleUnit::addReactionExp; } else { expFuncA = &BattleUnit::addThrowingExp; } break;\n\t\tcase ETM_BRAVERY: expFuncA = &BattleUnit::addBraveryExp; break;\n\t\tcase ETM_BRAVERY_2X: expMultiply = 200; expFuncA = &BattleUnit::addBraveryExp; break;\n\t\tcase ETM_BRAVERY_AND_REACTIONS: expFuncA = &BattleUnit::addBraveryExp; expFuncB = &BattleUnit::addReactionExp; break;\n\t\tcase ETM_BRAVERY_OR_REACTIONS: if (RNG::percent(50)) { expFuncA = &BattleUnit::addBraveryExp; } else { expFuncA = &BattleUnit::addReactionExp; } break;\n\t\tcase ETM_BRAVERY_OR_REACTIONS_2X: expMultiply = 200; if (RNG::percent(50)) { expFuncA = &BattleUnit::addBraveryExp; } else { expFuncA = &BattleUnit::addReactionExp; } break;\n\t\tcase ETM_PSI_STRENGTH: expFuncA = &BattleUnit::addPsiStrengthExp; break;\n\t\tcase ETM_PSI_STRENGTH_2X: expMultiply = 200; expFuncA = &BattleUnit::addPsiStrengthExp; break;\n\t\tcase ETM_PSI_SKILL: expFuncA = &BattleUnit::addPsiSkillExp; break;\n\t\tcase ETM_PSI_SKILL_2X: expMultiply = 200; expFuncA = &BattleUnit::addPsiSkillExp; break;\n\t\tcase ETM_PSI_STRENGTH_AND_SKILL: expFuncA = &BattleUnit::addPsiStrengthExp; expFuncB = &BattleUnit::addPsiSkillExp; break;\n\t\tcase ETM_PSI_STRENGTH_AND_SKILL_2X: expMultiply = 200; expFuncA = &BattleUnit::addPsiStrengthExp; expFuncB = &BattleUnit::addPsiSkillExp; break;\n\t\tcase ETM_PSI_STRENGTH_OR_SKILL: if (RNG::percent(50)) { expFuncA = &BattleUnit::addPsiStrengthExp; } else { expFuncA = &BattleUnit::addPsiSkillExp; } break;\n\t\tcase ETM_PSI_STRENGTH_OR_SKILL_2X: expMultiply = 200; if (RNG::percent(50)) { expFuncA = &BattleUnit::addPsiStrengthExp; } else { expFuncA = &BattleUnit::addPsiSkillExp; } break;\n\t\tcase ETM_NOTHING:\n\t\tdefault:\n\t\t\treturn false;\n\t\t}\n\t}\n\telse\n\t{\n\t\t// GRENADES AND PROXIES\n\t\tif (weapon->getRules()->getBattleType() == BT_GRENADE || weapon->getRules()->getBattleType() == BT_PROXIMITYGRENADE)\n\t\t{\n\t\t\tif (Mod::EXTENDED_EXPERIENCE_AWARD_SYSTEM)\n\t\t\t{\n\t\t\t\texpType = ETM_THROWING_100;\n\t\t\t\texpFuncA = &BattleUnit::addThrowingExp; // e.g. acid grenade, stun grenade, HE grenade, smoke grenade, proxy grenade, ...\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\texpType = ETM_FIRING_100;\n\t\t\t\texpFuncA = &BattleUnit::addFiringExp; // vanilla compatibility\n\t\t\t}\n\t\t}\n\t\t// MELEE\n\t\telse if (weapon->getRules()->getBattleType() == BT_MELEE)\n\t\t{\n\t\t\texpType = ETM_MELEE_100;\n\t\t\texpFuncA = &BattleUnit::addMeleeExp; // e.g. cattle prod, cutlass, rope, ...\n\t\t}\n\t\t// MEDIKITS\n\t\telse if (weapon->getRules()->getBattleType() == BT_MEDIKIT)\n\t\t{\n\t\t\t// medikits don't train anything by default\n\t\t\treturn false;\n\t\t}\n\t\t// FIREARMS and other\n\t\telse\n\t\t{\n\t\t\tif (!rangeAtack)\n\t\t\t{\n\t\t\t\texpType = ETM_MELEE_100;\n\t\t\t\texpFuncA = &BattleUnit::addMeleeExp; // e.g. rifle/shotgun gun butt, ...\n\t\t\t}\n\t\t\telse if (!Mod::EXTENDED_EXPERIENCE_AWARD_SYSTEM)\n\t\t\t{\n\t\t\t\texpType = ETM_FIRING_100;\n\t\t\t\texpFuncA = &BattleUnit::addFiringExp; // vanilla compatibility\n\t\t\t}\n\t\t\telse if (weapon->getArcingShot(attack.type))\n\t\t\t{\n\t\t\t\texpType = ETM_THROWING_100;\n\t\t\t\texpFuncA = &BattleUnit::addThrowingExp; // e.g. flamethrower, javelins, combat bow, grenade launcher, black powder bomb, stick grenade, acid flask, apple, ...\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tint maxRange = weapon->getRules()->getMaxRange();\n\t\t\t\tif (maxRange > 10)\n\t\t\t\t{\n\t\t\t\t\texpType = ETM_FIRING_100;\n\t\t\t\t\texpFuncA = &BattleUnit::addFiringExp; // e.g. harpoon gun, shotgun, assault rifle, rocket launcher, small launcher, heavy cannon, blaster launcher, ...\n\t\t\t\t}\n\t\t\t\telse if (maxRange > 1)\n\t\t\t\t{\n\t\t\t\t\texpType = ETM_THROWING_100;\n\t\t\t\t\texpFuncA = &BattleUnit::addThrowingExp; // e.g. throwing knives, zapper, ...\n\t\t\t\t}\n\t\t\t\telse if (maxRange == 1)\n\t\t\t\t{\n\t\t\t\t\texpType = ETM_MELEE_100;\n\t\t\t\t\texpFuncA = &BattleUnit::addMeleeExp; // e.g. hammer, chainsaw, fusion torch, ...\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\treturn false; // what is this? no training!\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (weapon->getRules()->getBattleType() != BT_MEDIKIT)\n\t{\n\t\t// only enemies count, not friends or neutrals\n\t\tif (target->getOriginalFaction() != FACTION_HOSTILE) expMultiply = 0;\n\n\t\tif (Mod::EXTENDED_EXPERIENCE_AWARD_SYSTEM)\n\t\t{\n\t\t\t// mind-controlled enemies don't count though!\n\t\t\tif (target->getFaction() != FACTION_HOSTILE) expMultiply = 0;\n\t\t}\n\t}\n\n\texpMultiply = ModScript::scriptFunc2<ModScript::AwardExperience>(\n\t\ttarget->getArmor(),\n\t\texpMultiply, expType,\n\t\tunit, target, weapon, attack.type\n\t);\n\n\tfor (int i = expMultiply / 100; i > 0; --i)\n\t{\n\t\tif (expFuncA) (unit->*expFuncA)();\n\t\tif (expFuncB) (unit->*expFuncB)();\n\t}\n\tif (RNG::percent(expMultiply % 100))\n\t{\n\t\tif (expFuncA) (unit->*expFuncA)();\n\t\tif (expFuncB) (unit->*expFuncB)();\n\t}\n\n\treturn true;\n}\n\n/**\n * Handling of hitting unit.\n * @param unit hitter.\n * @param clipOrWeapon clip or weapon causing the damage.\n * @param target targeted unit.\n * @param relative angle of hit.\n * @param damage power of hit.\n * @param type damage type of hit.\n * @return Did unit get hit?\n */\nbool TileEngine::hitUnit(BattleActionAttack attack, BattleUnit *target, const Position &relative, int damage, const RuleDamageType *type, bool rangeAtack)\n{\n\tif (_save->isPreview())\n\t{\n\t\treturn false;\n\t}\n\tif (!target || target->getHealth() <= 0)\n\t{\n\t\treturn false;\n\t}\n\n\tconst int healthOrig = target->getHealth();\n\tconst int stunLevelOrig = target->getStunlevel();\n\n\ttarget->damage(relative, damage, type, _save, attack);\n\n\tconst int healthDamage = healthOrig - target->getHealth();\n\tconst int stunDamage = target->getStunlevel() - stunLevelOrig;\n\n\t// hit log\n\tif (attack.attacker)\n\t{\n\t\tif (healthDamage > 0 || stunDamage > 0)\n\t\t{\n\t\t\tint damagePercent = ((healthDamage + stunDamage) * 100) / target->getBaseStats()->health;\n\t\t\tif (damagePercent <= 20)\n\t\t\t{\n\t\t\t\t_save->appendToHitLog(HITLOG_SMALL_DAMAGE, attack.attacker->getFaction());\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_save->appendToHitLog(HITLOG_BIG_DAMAGE, attack.attacker->getFaction());\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_save->appendToHitLog(HITLOG_NO_DAMAGE, attack.attacker->getFaction());\n\t\t}\n\t}\n\n\t// single place for firing/throwing/melee experience training\n\tif (attack.attacker && attack.attacker->getOriginalFaction() == FACTION_PLAYER)\n\t{\n\t\tawardExperience(attack, target, rangeAtack);\n\t}\n\n\t// Use case: an xcom soldier throwing a smoke grenade on a dying unit should not override the previously remembered murderer\n\tbool isRelevant = true;\n\tif (attack.attacker\n\t\t&& healthDamage <= 0\n\t\t&& target->getMurdererId() > 0\n\t\t&& (target->getFire() > 0 || target->getFatalWounds() > 0 || target->hasNegativeHealthRegen()))\n\t{\n\t\tisRelevant = false;\n\t}\n\n\tif (isRelevant && attack.attacker)\n\t{\n\t\t// Record the last unit to hit our victim. If a victim dies without warning*, this unit gets the credit.\n\t\t// *Because the unit died in a fire or bled out.\n\t\ttarget->setMurdererId(attack.attacker->getId());\n\t\ttarget->setMurdererWeapon(\"STR_WEAPON_UNKNOWN\");\n\t\ttarget->setMurdererWeaponAmmo(\"STR_WEAPON_UNKNOWN\");\n\t\tif (attack.weapon_item)\n\t\t{\n\t\t\ttarget->setMurdererWeapon(attack.weapon_item->getRules()->getName());\n\t\t}\n\t\tif (attack.damage_item)\n\t\t{\n\t\t\ttarget->setMurdererWeaponAmmo(attack.damage_item->getRules()->getName());\n\t\t}\n\t}\n\n\treturn true;\n}\n\n/**\n * Handles bullet/weapon hits.\n *\n * A bullet/weapon hits a voxel.\n * @param center Center of the explosion in voxelspace.\n * @param power Power of the explosion.\n * @param type The damage type of the explosion.\n * @param unit The unit that caused the explosion.\n * @param clipOrWeapon clip or weapon causing the damage.\n */\nvoid TileEngine::hit(BattleActionAttack attack, Position center, int power, const RuleDamageType *type, bool rangeAtack, int terrainMeleeTilePart)\n{\n\tbool terrainChanged = false; //did the hit destroy a tile thereby changing line of sight?\n\tint effectGenerated = 0; //did the hit produce smoke (1), fire/light (2) or disabled a unit (3) ?\n\tPosition tilePos = center.toTile();\n\tTile *tile = _save->getTile(tilePos);\n\tif (!tile || power <= 0)\n\t{\n\t\treturn;\n\t}\n\n\tvoxelCheckFlush();\n\tconst VoxelType part = (terrainMeleeTilePart > 0) ? (VoxelType)terrainMeleeTilePart : voxelCheck(center, attack.attacker);\n\tconst int damage = type->getRandomDamage(power);\n\tconst int tileFinalDamage = type->getTileFinalDamage(type->getRandomDamageForTile(power, damage));\n\tif (part >= V_FLOOR && part <= V_OBJECT)\n\t{\n\t\tbool nothing = true;\n\t\tif (terrainMeleeTilePart == 0 && (part == V_FLOOR || part == V_OBJECT))\n\t\t{\n\t\t\tfor (auto* bi : *tile->getInventory())\n\t\t\t{\n\t\t\t\tif (hitUnit(attack, bi->getUnit(), Position(0,0,0), damage, type, rangeAtack))\n\t\t\t\t{\n\t\t\t\t\tif (bi->getGlow()) effectGenerated = 2; //Any glowing corpses?\n\t\t\t\t\tnothing = false;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (nothing)\n\t\t{\n\t\t\tconst TilePart tp = static_cast<TilePart>(part);\n\t\t\t//Do we need to update the visibility of units due to smoke/fire?\n\t\t\teffectGenerated = hitTile(tile, damage, type);\n\t\t\t//If a tile was destroyed we may have revealed new areas for one or more observers\n\t\t\tif (tileFinalDamage >= tile->getMapData(tp)->getArmor()) terrainChanged = true;\n\n\t\t\tif (part == V_OBJECT && _save->getMissionType() == \"STR_BASE_DEFENSE\")\n\t\t\t{\n\t\t\t\tif (tileFinalDamage >= tile->getMapData(O_OBJECT)->getArmor() && tile->getMapData(O_OBJECT)->isBaseModule())\n\t\t\t\t{\n\t\t\t\t\t_save->getModuleMap()[(center.x/16)/10][(center.y/16)/10].second--;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (tile->damage(tp, tileFinalDamage, _save->getObjectiveType()))\n\t\t\t{\n\t\t\t\t_save->addDestroyedObjective();\n\t\t\t}\n\t\t}\n\t}\n\telse if (part == V_UNIT)\n\t{\n\t\tBattleUnit *bu = tile->getOverlappingUnit(_save);\n\t\tif (bu && bu->getHealth() > 0)\n\t\t{\n\t\t\tint verticaloffset = 0;\n\t\t\tif (bu != tile->getUnit())\n\t\t\t{\n\t\t\t\tverticaloffset = 24;\n\t\t\t}\n\t\t\tconst int sz = bu->getArmor()->getSize() * 8;\n\t\t\tconst Position target = bu->getPosition().toVoxel() + Position(sz,sz, bu->getFloatHeight() - tile->getTerrainLevel());\n\t\t\tconst Position relative = (center - target) - Position(0,0,verticaloffset);\n\n\t\t\thitUnit(attack, bu, relative, damage, type, rangeAtack);\n\t\t\tif (bu->getFire())\n\t\t\t{\n\t\t\t\teffectGenerated = 2;\n\t\t\t}\n\t\t}\n\t}\n\t//Recalculate relevant item/unit locations and visibility depending on what happened during the hit\n\tif (terrainChanged || effectGenerated)\n\t{\n\t\tapplyGravity(tile);\n\t\tLightLayers layer = LL_ITEMS;\n\t\tif (part == V_FLOOR && _save->getTile(tilePos - Position(0, 0, 1)))\n\t\t{\n\t\t\tlayer = LL_AMBIENT; // roof destroyed, update sunlight in this tile column\n\t\t}\n\t\telse if (terrainChanged || effectGenerated)\n\t\t{\n\t\t\tlayer = LL_FIRE; // spawned fire or smoke that can block light.\n\t\t}\n\t\tcalculateLighting(layer, tilePos, 1, true);\n\t\tcalculateFOV(tilePos, 1, true, terrainChanged); //append any new units or tiles revealed by the terrain change\n\t}\n\telse\n\t{\n\t\t// script could affect visibility of units, fast check if something is changed.\n\t\tcalculateFOV(tilePos, 1, false); //skip updating of tiles\n\t}\n\t//Note: If bu was knocked out this will have no effect on unit visibility quite yet, as it is not marked as out\n\t//and will continue to block visibility at this point in time.\n}\n\n/**\n * Handles explosions.\n *\n * HE, smoke and fire explodes in a circular pattern on 1 level only. HE however damages floor tiles of the above level. Not the units on it.\n * HE destroys an object if its armor is lower than the explosive power, then it's HE blockage is applied for further propagation.\n * See http://www.ufopaedia.org/index.php?title=Explosions for more info.\n * @param center Center of the explosion in voxelspace.\n * @param power Power of the explosion.\n * @param type The damage type of the explosion.\n * @param maxRadius The maximum radius of the explosion.\n * @param unit The unit that caused the explosion.\n * @param clipOrWeapon The clip or weapon that caused the explosion.\n */\nvoid TileEngine::explode(BattleActionAttack attack, Position center, int power, const RuleDamageType *type, int maxRadius, bool rangeAtack)\n{\n\tconst Position centetTile = center.toTile();\n\tint hitSide = 0;\n\tint diagonalWall = 0;\n\tint power_;\n\tstd::map<Tile*, int> tilesAffected;\n\tstd::vector<BattleItem*> toRemove;\n\tstd::pair<std::map<Tile*, int>::iterator, bool> ret;\n\n\tif (type->FireBlastCalc)\n\t{\n\t\tpower /= 2;\n\t}\n\n\tint exHeight = Clamp(Options::battleExplosionHeight, 0, 3);\n\tint vertdec = 1000; //default flat explosion\n\n\tswitch (exHeight)\n\t{\n\tcase 1:\n\t\tvertdec = 3.0f * type->RadiusReduction;\n\t\tbreak;\n\tcase 2:\n\t\tvertdec = 1.0f * type->RadiusReduction;\n\t\tbreak;\n\tcase 3:\n\t\tvertdec = 0.5f * type->RadiusReduction;\n\t}\n\n\tTile *origin = _save->getTile(Position(centetTile));\n\tTile *dest = nullptr;\n\tif (origin->isBigWall()) //pre-calculations for bigwall deflection\n\t{\n\t\tdiagonalWall = origin->getMapData(O_OBJECT)->getBigWall();\n\t\tif (diagonalWall == Pathfinding::BIGWALLNWSE) //  3 |\n\t\t\thitSide = (center.x % 16 - center.y % 16) > 0 ? 1 : -1;\n\t\tif (diagonalWall == Pathfinding::BIGWALLNESW) //  2 --\n\t\t\thitSide = (center.x % 16 + center.y % 16 - 15) > 0 ? 1 : -1;\n\t}\n\n\tfor (int fi = -90; fi <= 90; fi += 5)\n\t{\n\t\t// raytrace every 3 degrees makes sure we cover all tiles in a circle.\n\t\tfor (int te = 0; te <= 360; te += 3)\n\t\t{\n\t\t\tdouble cos_te = cos(Deg2Rad(te));\n\t\t\tdouble sin_te = sin(Deg2Rad(te));\n\t\t\tdouble sin_fi = sin(Deg2Rad(fi));\n\t\t\tdouble cos_fi = cos(Deg2Rad(fi));\n\n\t\t\torigin = _save->getTile(centetTile);\n\t\t\tdest = origin;\n\t\t\tdouble l = 0;\n\t\t\tint tileX, tileY, tileZ;\n\t\t\tpower_ = power;\n\t\t\twhile (power_ > 0 && l <= maxRadius)\n\t\t\t{\n\t\t\t\tif (power_ > 0)\n\t\t\t\t{\n\t\t\t\t\tret = tilesAffected.insert(std::make_pair(dest, 0)); // check if we had this tile already affected\n\n\t\t\t\t\tconst int tileDmg = type->getTileFinalDamage(power_);\n\t\t\t\t\tif (tileDmg > ret.first->second)\n\t\t\t\t\t{\n\t\t\t\t\t\tret.first->second = tileDmg;\n\t\t\t\t\t}\n\t\t\t\t\tif (ret.second)\n\t\t\t\t\t{\n\t\t\t\t\t\tconst int damage = type->getRandomDamage(power_);\n\t\t\t\t\t\tBattleUnit *bu = dest->getOverlappingUnit(_save);\n\n\t\t\t\t\t\ttoRemove.clear();\n\t\t\t\t\t\tif (bu)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (dest->getPosition() == centetTile)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// direct hit, similar to ground zero but AI will remember attacker, done for compatibility\n\t\t\t\t\t\t\t\thitUnit(attack, bu, Position(0, 0, 0), damage, type, rangeAtack);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if (\n\t\t\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\t\t\tPosition::distance2dSq(dest->getPosition(), centetTile) < 4\n\t\t\t\t\t\t\t\t\t\t&& dest->getPosition().z == centetTile.z\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t|| dest->getPosition().z > centetTile.z\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// ground zero effect is in effect, or unit is above explosion\n\t\t\t\t\t\t\t\thitUnit(attack, bu, Position(0, 0, -1), damage, type, rangeAtack);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// directional damage relative to explosion position.\n\t\t\t\t\t\t\t\t// units above the explosion will be hit in the legs, units lateral to or below will be hit in the torso\n\t\t\t\t\t\t\t\thitUnit(attack, bu, centetTile + Position(0, 0, 5) - dest->getPosition(), damage, type, rangeAtack);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Affect all items and units in inventory\n\t\t\t\t\t\t\tconst int itemDamage = bu->getOverKillDamage();\n\t\t\t\t\t\t\tif (itemDamage > 0)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tfor (auto* bi : *bu->getInventory())\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tif (!hitUnit(attack, bi->getUnit(), Position(0, 0, 0), itemDamage, type, rangeAtack) && type->getItemFinalDamage(itemDamage) > bi->getRules()->getArmor())\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\ttoRemove.push_back(bi);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Affect all items and units on ground\n\t\t\t\t\t\tfor (auto* bi : *dest->getInventory())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (!hitUnit(attack, bi->getUnit(), Position(0, 0, 0), damage, type) && type->getItemFinalDamage(damage) > bi->getRules()->getArmor())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttoRemove.push_back(bi);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfor (auto* bi : toRemove)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_save->removeItem(bi);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\thitTile(dest, damage, type);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tl += 1.0;\n\n\t\t\t\ttileX = int(floor(centetTile.x + 0.5 + l * sin_te * cos_fi));\n\t\t\t\ttileY = int(floor(centetTile.y + 0.5 + l * cos_te * cos_fi));\n\t\t\t\ttileZ = int(floor(centetTile.z + 0.5 + l * sin_fi));\n\n\t\t\t\torigin = dest;\n\t\t\t\tdest = _save->getTile(Position(tileX, tileY, tileZ));\n\n\t\t\t\tif (!dest) break; // out of map!\n\n\t\t\t\t// blockage by terrain is deducted from the explosion power\n\t\t\t\tpower_ -= type->RadiusReduction; // explosive damage decreases by 10 per tile\n\t\t\t\tif (origin->getPosition().z != tileZ)\n\t\t\t\t\tpower_ -= vertdec; //3d explosion factor\n\n\t\t\t\tif (type->FireBlastCalc)\n\t\t\t\t{\n\t\t\t\t\tint dir;\n\t\t\t\t\tPathfinding::vectorToDirection(origin->getPosition() - dest->getPosition(), dir);\n\t\t\t\t\tif (dir != -1 && dir %2) power_ -= 0.5f * type->RadiusReduction; // diagonal movement costs an extra 50% for fire.\n\t\t\t\t}\n\t\t\t\tif (l > 0.5) {\n\t\t\t\t\tif ( l > 1.5)\n\t\t\t\t\t{\n\t\t\t\t\t\tpower_ -= verticalBlockage(origin, dest, type->ResistType, false) * 2;\n\t\t\t\t\t\tpower_ -= horizontalBlockage(origin, dest, type->ResistType, false) * 2;\n\t\t\t\t\t}\n\t\t\t\t\telse //tricky bigwall deflection /Volutar\n\t\t\t\t\t{\n\t\t\t\t\t\tbool skipObject = diagonalWall == 0;\n\t\t\t\t\t\tif (diagonalWall == Pathfinding::BIGWALLNESW) // --\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (hitSide<0 && te >= 135 && te < 315)\n\t\t\t\t\t\t\t\tskipObject = true;\n\t\t\t\t\t\t\tif (hitSide>0 && ( te < 135 || te > 315))\n\t\t\t\t\t\t\t\tskipObject = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (diagonalWall == Pathfinding::BIGWALLNWSE) // |\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (hitSide>0 && te >= 45 && te < 225)\n\t\t\t\t\t\t\t\tskipObject = true;\n\t\t\t\t\t\t\tif (hitSide<0 && ( te < 45 || te > 225))\n\t\t\t\t\t\t\t\tskipObject = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tpower_ -= verticalBlockage(origin, dest, type->ResistType, skipObject) * 2;\n\t\t\t\t\t\tpower_ -= horizontalBlockage(origin, dest, type->ResistType, skipObject) * 2;\n\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// now detonate the tiles affected by explosion\n\tif (type->ToTile > 0.0f)\n\t{\n\t\tfor (auto& pair : tilesAffected)\n\t\t{\n\t\t\tif (detonate(pair.first, pair.second))\n\t\t\t{\n\t\t\t\t_save->addDestroyedObjective();\n\t\t\t}\n\t\t\tapplyGravity(pair.first);\n\t\t\tTile *j = _save->getTile(pair.first->getPosition() + Position(0,0,1));\n\t\t\tif (j)\n\t\t\t\tapplyGravity(j);\n\t\t}\n\t}\n\tcalculateLighting(LL_AMBIENT, centetTile, maxRadius + 1, true); // roofs could have been destroyed and fires could have been started\n\tcalculateFOV(centetTile, maxRadius + 1, true, true);\n\tif (attack.attacker && Position::distance2d(centetTile, attack.attacker->getPosition()) > maxRadius + 1)\n\t{\n\t\t// unit is away from blast but its visibility can be affected by scripts.\n\t\tcalculateFOV(centetTile, 1, false);\n\t}\n}\n\n/**\n * Applies the explosive power to the tile parts. This is where the actual destruction takes place.\n * Must affect 9 objects (6 box sides and the object inside plus 2 outer walls).\n * @param tile Tile affected.\n * @return True if the objective was destroyed.\n */\nbool TileEngine::detonate(Tile* tile, int explosive)\n{\n\tif (explosive == 0) return false; // no damage applied for this tile\n\tbool objective = false;\n\tTile* tiles[9];\n\tstatic const TilePart parts[9]={O_FLOOR,O_WESTWALL,O_NORTHWALL,O_FLOOR,O_WESTWALL,O_NORTHWALL,O_OBJECT,O_OBJECT,O_OBJECT}; //6th is the object of current\n\tPosition pos = tile->getPosition();\n\n\ttiles[0] = _save->getTile(Position(pos.x, pos.y, pos.z+1)); //ceiling\n\ttiles[1] = _save->getTile(Position(pos.x+1, pos.y, pos.z)); //east wall\n\ttiles[2] = _save->getTile(Position(pos.x, pos.y+1, pos.z)); //south wall\n\ttiles[3] = tiles[4] = tiles[5] = tiles[6] = tile;\n\ttiles[7] = _save->getTile(Position(pos.x, pos.y-1, pos.z)); //north bigwall\n\ttiles[8] = _save->getTile(Position(pos.x-1, pos.y, pos.z)); //west bigwall\n\n\tint remainingPower, fireProof, fuel;\n\tbool destroyed, bigwalldestroyed = true, skipnorthwest = false;\n\tfor (int i = 8; i >=0; --i)\n\t{\n\t\tif (!tiles[i] || !tiles[i]->getMapData(parts[i]))\n\t\t\tcontinue; //skip out of map and emptiness\n\t\tint bigwall = tiles[i]->getMapData(parts[i])->getBigWall();\n\t\tif (i > 6 && !( (bigwall==1) || (bigwall==8) || (i==8 && bigwall==6) || (i==7 && bigwall==7)))\n\t\t\tcontinue;\n\t\tif ((bigwall!=0)) skipnorthwest = true;\n\t\tif (!bigwalldestroyed && i<6) //when ground shouldn't be destroyed\n\t\t\tcontinue;\n\t\tif (skipnorthwest && (i == 2 || i == 1)) continue;\n\t\tremainingPower = explosive;\n\t\tdestroyed = false;\n\t\tint volume = 0;\n\t\tTilePart currentpart = parts[i], currentpart2;\n\t\tint diemcd;\n\t\tfireProof = tiles[i]->getFlammability(currentpart);\n\t\tfuel = tiles[i]->getFuel(currentpart) + 1;\n\t\t// get the volume of the object by checking it's loftemps objects.\n\t\tfor (int j = 0; j < 12; j++)\n\t\t{\n\t\t\tif (tiles[i]->getMapData(currentpart)->getLoftID(j) != 0)\n\t\t\t\t++volume;\n\t\t}\n\t\tif ( i == 6 &&\n\t\t\t(bigwall == 2 || bigwall == 3) && //diagonals\n\t\t\ttiles[i]->getMapData(currentpart)->getArmor() > remainingPower) //not enough to destroy\n\t\t{\n\t\t\tbigwalldestroyed = false;\n\t\t}\n\t\t// iterate through tile armor and destroy if can\n\t\twhile (\ttiles[i]->getMapData(currentpart) &&\n\t\t\t\ttiles[i]->getMapData(currentpart)->getArmor() <= remainingPower &&\n\t\t\t\ttiles[i]->getMapData(currentpart)->getArmor() != 255)\n\t\t{\n\t\t\tif ( i == 6 && (bigwall == 2 || bigwall == 3)) //diagonals for the current tile\n\t\t\t{\n\t\t\t\tbigwalldestroyed = true;\n\t\t\t}\n\t\t\tif ( i == 6 && (bigwall == 6 || bigwall == 7 || bigwall == 8)) //n/w/nw\n\t\t\t{\n\t\t\t\tskipnorthwest = false;\n\t\t\t}\n\t\t\tremainingPower -= tiles[i]->getMapData(currentpart)->getArmor();\n\t\t\tdestroyed = true;\n\t\t\tif (_save->getMissionType() == \"STR_BASE_DEFENSE\" &&\n\t\t\t\ttiles[i]->getMapData(currentpart)->isBaseModule())\n\t\t\t{\n\t\t\t\t_save->getModuleMap()[tile->getPosition().x/10][tile->getPosition().y/10].second--;\n\t\t\t}\n\t\t\t//this trick is to follow transformed object parts (object can become a ground)\n\t\t\tdiemcd = tiles[i]->getMapData(currentpart)->getDieMCD();\n\t\t\tif (diemcd!=0)\n\t\t\t\tcurrentpart2 = tiles[i]->getMapData(currentpart)->getDataset()->getObject(diemcd)->getObjectType();\n\t\t\telse\n\t\t\t\tcurrentpart2 = currentpart;\n\t\t\tif (tiles[i]->destroy(currentpart, _save->getObjectiveType()))\n\t\t\t\tobjective = true;\n\t\t\tcurrentpart =  currentpart2;\n\t\t\tif (tiles[i]->getMapData(currentpart)) // take new values\n\t\t\t{\n\t\t\t\tfireProof = tiles[i]->getFlammability(currentpart);\n\t\t\t\tfuel = tiles[i]->getFuel(currentpart) + 1;\n\t\t\t}\n\t\t}\n\t\t// set tile on fire\n\t\tif (fireProof < remainingPower)\n\t\t{\n\t\t\tif (tiles[i]->getMapData(O_FLOOR) || tiles[i]->getMapData(O_OBJECT))\n\t\t\t{\n\t\t\t\ttiles[i]->setFire(fuel);\n\t\t\t\ttiles[i]->setSmoke(Clamp(15 - (fireProof / 10), 1, 12));\n\t\t\t}\n\t\t}\n\t\t// add some smoke if tile was destroyed and not set on fire\n\t\tif (destroyed)\n\t\t{\n\t\t\tif (tiles[i]->getFire() && !tiles[i]->getMapData(O_FLOOR) && !tiles[i]->getMapData(O_OBJECT))\n\t\t\t{\n\t\t\t\ttiles[i]->setFire(0);// if the object set the floor on fire, and the floor was subsequently destroyed, the fire needs to go out\n\t\t\t}\n\n\t\t\tif (!tiles[i]->getFire())\n\t\t\t{\n\t\t\t\tint smoke = RNG::generate(1, (volume / 2) + 3) + (volume / 2);\n\t\t\t\tif (smoke > tiles[i]->getSmoke())\n\t\t\t\t{\n\t\t\t\t\ttiles[i]->setSmoke(Clamp(smoke, 0, 15));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn objective;\n}\n\n/**\n * Checks for chained explosions.\n *\n * Chained explosions are explosions which occur after an explosive map object is destroyed.\n * May be due a direct hit, other explosion or fire.\n * @return tile on which a explosion occurred\n */\nTile *TileEngine::checkForTerrainExplosions()\n{\n\tif (_save->isPreview())\n\t{\n\t\treturn 0;\n\t}\n\n\tfor (int i = 0; i < _save->getMapSizeXYZ(); ++i)\n\t{\n\t\tif (_save->getTile(i)->getExplosive())\n\t\t{\n\t\t\treturn _save->getTile(i);\n\t\t}\n\t}\n\treturn 0;\n}\n\n/**\n * Calculates the amount of power that is blocked going from one tile to another on a different level.\n * @param startTile The tile where the power starts.\n * @param endTile The adjacent tile where the power ends.\n * @param type The type of power/damage.\n * @return Amount of blockage of this power.\n */\nint TileEngine::verticalBlockage(Tile *startTile, Tile *endTile, ItemDamageType type, bool skipObject)\n{\n\tint block = 0;\n\n\t// safety check\n\tif (startTile == 0 || endTile == 0) return 255;\n\n\tPosition startPos = startTile->getPosition();\n\tPosition endPos = endTile->getPosition();\n\tint direction = endPos.z - startPos.z;\n\n\tif (direction == 0 ) return 0;\n\n\tTile *tmpTile = nullptr;\n\tif (direction < 0) // down\n\t{\n\t\ttmpTile = startTile;\n\t\tblock += blockage(tmpTile, O_FLOOR, type);\n\t\tif (!skipObject)\n\t\t\tblock += blockage(tmpTile, O_OBJECT, type, Pathfinding::DIR_DOWN);\n\t\tif (startPos.x != endPos.x || startPos.y != endPos.y)\n\t\t{\n\t\t\ttmpTile = _save->getTile(Position(endPos.x, endPos.y, startPos.z));\n\t\t\tblock += horizontalBlockage(startTile, tmpTile, type, skipObject);\n\t\t\tblock += blockage(tmpTile, O_FLOOR, type);\n\t\t\tif (!skipObject)\n\t\t\t\tblock += blockage(tmpTile, O_OBJECT, type, Pathfinding::DIR_DOWN);\n\t\t}\n\t}\n\telse if (direction > 0) // up\n\t{\n\t\ttmpTile = _save->getTile(Position(startPos.x, startPos.y, startPos.z + 1));\n\t\tblock += blockage(tmpTile, O_FLOOR, type);\n\t\tif (!skipObject)\n\t\t\tblock += blockage(tmpTile, O_OBJECT, type, Pathfinding::DIR_UP);\n\t\tif (startPos.x != endPos.x || startPos.y != endPos.y)\n\t\t{\n\t\t\ttmpTile = _save->getTile(Position(endPos.x, endPos.y, startPos.z + 1));\n\t\t\tblock += horizontalBlockage(startTile, tmpTile, type, skipObject);\n\t\t\tblock += blockage(tmpTile, O_FLOOR, type);\n\t\t\tif (!skipObject)\n\t\t\t\tblock += blockage(tmpTile, O_OBJECT, type, Pathfinding::DIR_UP);\n\t\t}\n\t}\n\n\treturn block;\n}\n\n/**\n * Calculates the amount of power that is blocked going from one tile to another on the same level.\n * @param startTile The tile where the power starts.\n * @param endTile The adjacent tile where the power ends.\n * @param type The type of power/damage.\n * @return Amount of blockage.\n */\nint TileEngine::horizontalBlockage(Tile *startTile, Tile *endTile, ItemDamageType type, bool skipObject)\n{\n\tconst Position oneTileNorth = Position(0, -1, 0);\n\tconst Position oneTileEast = Position(1, 0, 0);\n\tconst Position oneTileSouth = Position(0, 1, 0);\n\tconst Position oneTileWest = Position(-1, 0, 0);\n\n\t// safety check\n\tif (startTile == 0 || endTile == 0) return 255;\n\n\tPosition startPos = startTile->getPosition();\n\tPosition endPos = endTile->getPosition();\n\tif (startPos.z != endPos.z) return 0;\n\tTile *tmpTile = nullptr;\n\n\tint direction;\n\tPathfinding::vectorToDirection(endPos - startPos, direction);\n\tif (direction == -1) return 0;\n\tint block = 0;\n\n\tswitch(direction)\n\t{\n\tcase 0:\t// north\n\t\tblock = blockage(startTile, O_NORTHWALL, type);\n\t\tbreak;\n\tcase 1: // north east\n\t\tif (type == DT_NONE) //this is two-way diagonal visibility check, used in original game\n\t\t{\n\t\t\tblock = blockage(startTile, O_NORTHWALL, type) + blockage(endTile, O_WESTWALL, type); //up+right\n\n\t\t\ttmpTile = _save->getTile(startPos + oneTileNorth);\n\t\t\tif (tmpTile && tmpTile->getMapData(O_OBJECT) && tmpTile->getMapData(O_OBJECT)->getBigWall() != Pathfinding::BIGWALLNESW)\n\t\t\t\tblock += blockage(tmpTile, O_OBJECT, type, 3);\n\n\t\t\tif (block == 0) break; //this way is opened\n\n\t\t\ttmpTile = _save->getTile(startPos + oneTileEast);\n\t\t\tblock = blockage(tmpTile, O_NORTHWALL, type)\n\t\t\t\t+ blockage(tmpTile, O_WESTWALL, type); //right+up\n\t\t\tif (tmpTile && tmpTile->getMapData(O_OBJECT) && tmpTile->getMapData(O_OBJECT)->getBigWall() != Pathfinding::BIGWALLNESW)\n\t\t\t\tblock += blockage(tmpTile, O_OBJECT, type, 7);\n\t\t}\n\t\telse\n\t\t{\n\t\t\ttmpTile = _save->getTile(startPos + oneTileEast);\n\t\t\tblock = (blockage(startTile, O_NORTHWALL, type) + blockage(endTile,O_WESTWALL, type))/2\n\t\t\t\t+ (blockage(tmpTile, O_WESTWALL, type)\n\t\t\t\t+ blockage(tmpTile, O_NORTHWALL, type))/2;\n\n\t\t\ttmpTile = _save->getTile(startPos + oneTileNorth);\n\t\t\tblock += (blockage(tmpTile, O_OBJECT, type, 4)\n\t\t\t\t+ blockage(tmpTile, O_OBJECT, type, 6))/2;\n\t\t}\n\t\tbreak;\n\tcase 2: // east\n\t\tblock = blockage(endTile, O_WESTWALL, type);\n\t\tbreak;\n\tcase 3: // south east\n\t\tif (type == DT_NONE)\n\t\t{\n\t\t\ttmpTile = _save->getTile(startPos + oneTileSouth);\n\t\t\tblock = blockage(tmpTile, O_NORTHWALL, type)\n\t\t\t\t+ blockage(endTile, O_WESTWALL, type); //down+right\n\t\t\tif (tmpTile && tmpTile->getMapData(O_OBJECT) && tmpTile->getMapData(O_OBJECT)->getBigWall() != Pathfinding::BIGWALLNWSE)\n\t\t\t\tblock += blockage(tmpTile, O_OBJECT, type, 1);\n\n\t\t\tif (block == 0) break; //this way is opened\n\n\t\t\ttmpTile = _save->getTile(startPos + oneTileEast);\n\t\t\tblock = blockage(tmpTile, O_WESTWALL, type)\n\t\t\t\t+ blockage(endTile, O_NORTHWALL, type); //right+down\n\t\t\tif (tmpTile && tmpTile->getMapData(O_OBJECT) && tmpTile->getMapData(O_OBJECT)->getBigWall() != Pathfinding::BIGWALLNWSE)\n\t\t\t\tblock += blockage(tmpTile, O_OBJECT, type, 5);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tblock = (blockage(endTile, O_WESTWALL, type) + blockage(endTile, O_NORTHWALL, type))/2\n\t\t\t\t+ (blockage(_save->getTile(startPos + oneTileEast), O_WESTWALL, type)\n\t\t\t\t+ blockage(_save->getTile(startPos + oneTileSouth), O_NORTHWALL, type))/2;\n\t\t\tblock += (blockage(_save->getTile(startPos + oneTileSouth), O_OBJECT, type, 0)\n\t\t\t\t+ blockage(_save->getTile(startPos + oneTileEast), O_OBJECT, type, 6))/2;\n\t\t}\n\t\tbreak;\n\tcase 4: // south\n\t\tblock = blockage(endTile,O_NORTHWALL, type);\n\t\tbreak;\n\tcase 5: // south west\n\t\tif (type == DT_NONE)\n\t\t{\n\t\t\ttmpTile = _save->getTile(startPos + oneTileSouth);\n\t\t\tblock = blockage(tmpTile, O_NORTHWALL, type)\n\t\t\t\t+ blockage(tmpTile, O_WESTWALL, type); //down+left\n\t\t\tif (tmpTile && tmpTile->getMapData(O_OBJECT) && tmpTile->getMapData(O_OBJECT)->getBigWall() != Pathfinding::BIGWALLNESW)\n\t\t\t\tblock += blockage(tmpTile, O_OBJECT, type, 7);\n\n\t\t\tif (block == 0) break; //this way is opened\n\n\t\t\tblock = blockage(startTile, O_WESTWALL, type) + blockage(endTile, O_NORTHWALL, type); //left+down\n\t\t\ttmpTile = _save->getTile(startPos + oneTileWest);\n\t\t\tif (tmpTile && tmpTile->getMapData(O_OBJECT) && tmpTile->getMapData(O_OBJECT)->getBigWall() != Pathfinding::BIGWALLNESW)\n\t\t\t\tblock += blockage(tmpTile, O_OBJECT, type, 3);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tblock = (blockage(endTile,O_NORTHWALL, type) + blockage(startTile,O_WESTWALL, type))/2\n\t\t\t\t+ (blockage(_save->getTile(startPos + oneTileSouth),O_WESTWALL, type)\n\t\t\t\t+ blockage(_save->getTile(startPos + oneTileSouth),O_NORTHWALL, type))/2;\n\t\t\tblock += (blockage(_save->getTile(startPos + oneTileSouth),O_OBJECT, type, 0)\n\t\t\t\t+ blockage(_save->getTile(startPos + oneTileWest),O_OBJECT, type, 2))/2;\n\t\t}\n\t\tbreak;\n\tcase 6: // west\n\t\tblock = blockage(startTile,O_WESTWALL, type);\n\t\tbreak;\n\tcase 7: // north west\n\n\t\tif (type == DT_NONE)\n\t\t{\n\t\t\ttmpTile = _save->getTile(startPos + oneTileNorth);\n\t\t\tblock = blockage(startTile, O_NORTHWALL, type)\n\t\t\t\t+ blockage(tmpTile, O_WESTWALL, type); //up+left\n\t\t\tif (tmpTile && tmpTile->getMapData(O_OBJECT) && tmpTile->getMapData(O_OBJECT)->getBigWall() != Pathfinding::BIGWALLNWSE)\n\t\t\t\tblock += blockage(tmpTile, O_OBJECT, type, 5);\n\n\t\t\tif (block == 0) break; //this way is opened\n\n\t\t\ttmpTile = _save->getTile(startPos + oneTileWest);\n\t\t\tblock = blockage(startTile, O_WESTWALL, type)\n\t\t\t\t+ blockage(tmpTile, O_NORTHWALL, type); //left+up\n\t\t\tif (tmpTile && tmpTile->getMapData(O_OBJECT) && tmpTile->getMapData(O_OBJECT)->getBigWall() != Pathfinding::BIGWALLNWSE)\n\t\t\t\tblock += blockage(tmpTile, O_OBJECT, type, 1);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tblock = (blockage(startTile,O_WESTWALL, type) + blockage(startTile,O_NORTHWALL, type))/2\n\t\t\t\t+ (blockage(_save->getTile(startPos + oneTileNorth),O_WESTWALL, type)\n\t\t\t\t+ blockage(_save->getTile(startPos + oneTileWest),O_NORTHWALL, type))/2;\n\t\t\tblock += (blockage(_save->getTile(startPos + oneTileNorth),O_OBJECT, type, 4)\n\t\t\t\t+ blockage(_save->getTile(startPos + oneTileWest),O_OBJECT, type, 2))/2;\n\t\t}\n\t\tbreak;\n\t}\n\n\tif (!skipObject || (type==DT_NONE && startTile->isBigWall()) )\n\t\tblock += blockage(startTile,O_OBJECT, type, direction);\n\n\tif (type != DT_NONE)\n\t{\n\t\t// not too sure about removing this line,\n\t\t// i have a sneaking suspicion we might end up blocking things that we shouldn't\n\n\t\t//if (skipObject) return block;\n\n\t\tdirection += 4;\n\t\tif (direction > 7)\n\t\t\tdirection -= 8;\n\t\tif (endTile->isBigWall())\n\t\t\tblock += blockage(endTile,O_OBJECT, type, direction, true);\n\t}\n\telse\n\t{\n\t\tif ( block <= 127 )\n\t\t{\n\t\t\tdirection += 4;\n\t\t\tif (direction > 7)\n\t\t\t\tdirection -= 8;\n\t\t\tif (blockage(endTile,O_OBJECT, type, direction, true) > 127){\n\t\t\t\treturn -1; //hit bigwall, reveal bigwall tile\n\t\t\t}\n\t\t}\n\t}\n\n\treturn block;\n}\n\n/**\n * Calculates the amount this certain wall or floor-part of the tile blocks.\n * @param startTile The tile where the power starts.\n * @param part The part of the tile the power needs to go through.\n * @param type The type of power/damage.\n * @param direction Direction the power travels.\n * @return Amount of blockage.\n */\nint TileEngine::blockage(Tile *tile, const TilePart part, ItemDamageType type, int direction, bool checkingFromOrigin)\n{\n\tint blockage = 0;\n\n\tif (tile == 0) return 255; // probably outside the map here\n\n\tMapData *mapData = tile->getMapData(part);\n\tif (mapData)\n\t{\n\t\tbool check = true;\n\t\tint wall = -1;\n\t\tif (direction != -1)\n\t\t{\n\t\t\twall = tile->getMapData(O_OBJECT)->getBigWall();\n\n\t\t\tif (type != DT_SMOKE &&\n\t\t\t\tcheckingFromOrigin &&\n\t\t\t\t(wall == Pathfinding::BIGWALLNESW ||\n\t\t\t\twall == Pathfinding::BIGWALLNWSE))\n\t\t\t{\n\t\t\t\tcheck = false;\n\t\t\t}\n\t\t\tswitch (direction)\n\t\t\t{\n\t\t\tcase 0: // north\n\t\t\t\tif (wall == Pathfinding::BIGWALLWEST ||\n\t\t\t\t\twall == Pathfinding::BIGWALLEAST ||\n\t\t\t\t\twall == Pathfinding::BIGWALLSOUTH ||\n\t\t\t\t\twall == Pathfinding::BIGWALLEASTANDSOUTH)\n\t\t\t\t{\n\t\t\t\t\tcheck = false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 1: // north east\n\t\t\t\tif (wall == Pathfinding::BIGWALLWEST ||\n\t\t\t\t\twall == Pathfinding::BIGWALLSOUTH)\n\t\t\t\t{\n\t\t\t\t\tcheck = false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 2: // east\n\t\t\t\tif (wall == Pathfinding::BIGWALLNORTH ||\n\t\t\t\t\twall == Pathfinding::BIGWALLSOUTH ||\n\t\t\t\t\twall == Pathfinding::BIGWALLWEST ||\n\t\t\t\t\twall == Pathfinding::BIGWALLWESTANDNORTH)\n\t\t\t\t{\n\t\t\t\t\tcheck = false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 3: // south east\n\t\t\t\tif (wall == Pathfinding::BIGWALLNORTH ||\n\t\t\t\t\twall == Pathfinding::BIGWALLWEST ||\n\t\t\t\t\twall == Pathfinding::BIGWALLWESTANDNORTH)\n\t\t\t\t{\n\t\t\t\t\tcheck = false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 4: // south\n\t\t\t\tif (wall == Pathfinding::BIGWALLWEST ||\n\t\t\t\t\twall == Pathfinding::BIGWALLEAST ||\n\t\t\t\t\twall == Pathfinding::BIGWALLNORTH ||\n\t\t\t\t\twall == Pathfinding::BIGWALLWESTANDNORTH)\n\t\t\t\t{\n\t\t\t\t\tcheck = false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 5: // south west\n\t\t\t\tif (wall == Pathfinding::BIGWALLNORTH ||\n\t\t\t\t\twall == Pathfinding::BIGWALLEAST)\n\t\t\t\t{\n\t\t\t\t\tcheck = false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 6: // west\n\t\t\t\tif (wall == Pathfinding::BIGWALLNORTH ||\n\t\t\t\t\twall == Pathfinding::BIGWALLSOUTH ||\n\t\t\t\t\twall == Pathfinding::BIGWALLEAST ||\n\t\t\t\t\twall == Pathfinding::BIGWALLEASTANDSOUTH)\n\t\t\t\t{\n\t\t\t\t\tcheck = false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 7: // north west\n\t\t\t\tif (wall == Pathfinding::BIGWALLSOUTH ||\n\t\t\t\t\twall == Pathfinding::BIGWALLEAST ||\n\t\t\t\t\twall == Pathfinding::BIGWALLEASTANDSOUTH)\n\t\t\t\t{\n\t\t\t\t\tcheck = false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 8: // up\n\t\t\tcase 9: // down\n\t\t\t\tif (wall != 0 && wall != Pathfinding::BLOCK)\n\t\t\t\t{\n\t\t\t\t\tcheck = false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\telse if (part == O_FLOOR &&\n\t\t\t\t\tmapData->getBlock(type) == 0)\n\t\t{\n\t\t\tif (type != DT_NONE)\n\t\t\t{\n\t\t\t\tblockage += mapData->getArmor();\n\t\t\t}\n\t\t\telse if (!mapData->isNoFloor())\n\t\t\t{\n\t\t\t\treturn 256;\n\t\t\t}\n\t\t}\n\n\t\tif (check)\n\t\t{\n\t\t\t// -1 means we have a regular wall, and anything over 0 means we have a bigwall.\n\t\t\tif (type == DT_SMOKE && wall != 0 && !tile->isUfoDoorOpen(part))\n\t\t\t{\n\t\t\t\treturn 256;\n\t\t\t}\n\t\t\tblockage += mapData->getBlock(type);\n\t\t}\n\t}\n\n\t// open ufo doors are actually still closed behind the scenes\n\t// so a special trick is needed to see if they are open, if they are, they obviously don't block anything\n\tif (tile->isUfoDoorOpen(part))\n\t\tblockage = 0;\n\n\treturn blockage;\n}\n\n/**\n * Opens a door (if any) by rightclick, or by walking through it. The unit has to face in the right direction.\n * @param unit Unit.\n * @param rClick Whether the player right clicked.\n * @param dir Direction.\n * @return -1 there is no door, you can walk through;\n *\t\t  0 normal door opened, make a squeaky sound and you can walk through;\n *\t\t  1 ufo door is starting to open, make a whoosh sound, don't walk through;\n *\t\t  3 ufo door is still opening, don't walk through it yet. (have patience, futuristic technology...)\n *\t\t  4 not enough TUs\n *\t\t  5 would contravene fire reserve\n */\nint TileEngine::unitOpensDoor(BattleUnit *unit, bool rClick, int dir)\n{\n\tint door = -1;\n\tint TUCost = 0;\n\tint size = unit->getArmor()->getSize();\n\tint z = unit->getTile()->getTerrainLevel() < -12 ? 1 : 0; // if we're standing on stairs, check the tile above instead.\n\tint doorsOpened = 0;\n\tPosition doorCentre;\n\n\tif (dir == -1)\n\t{\n\t\tdir = unit->getDirection();\n\t}\n\tTile *tile;\n\tfor (int x = 0; x < size && door == -1; x++)\n\t{\n\t\tfor (int y = 0; y < size && door == -1; y++)\n\t\t{\n\t\t\tstd::vector<std::pair<Position, TilePart> > checkPositions;\n\t\t\ttile = _save->getTile(unit->getPosition() + Position(x,y,z));\n\t\t\tif (!tile) continue;\n\n\t\t\tswitch (dir)\n\t\t\t{\n\t\t\tcase 0: // north\n\t\t\t\tcheckPositions.push_back(std::make_pair(Position(0, 0, 0), O_NORTHWALL)); // origin\n\t\t\t\tif (x != 0)\n\t\t\t\t{\n\t\t\t\t\tcheckPositions.push_back(std::make_pair(Position(0, -1, 0), O_WESTWALL)); // one tile north\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 1: // north east\n\t\t\t\tcheckPositions.push_back(std::make_pair(Position(0, 0, 0), O_NORTHWALL)); // origin\n\t\t\t\tcheckPositions.push_back(std::make_pair(Position(1, -1, 0), O_WESTWALL)); // one tile north-east\n\t\t\t\tif (rClick)\n\t\t\t\t{\n\t\t\t\t\tcheckPositions.push_back(std::make_pair(Position(1, 0, 0), O_WESTWALL)); // one tile east\n\t\t\t\t\tcheckPositions.push_back(std::make_pair(Position(1, 0, 0), O_NORTHWALL)); // one tile east\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 2: // east\n\t\t\t\tcheckPositions.push_back(std::make_pair(Position(1, 0, 0), O_WESTWALL)); // one tile east\n\t\t\t\tbreak;\n\t\t\tcase 3: // south-east\n\t\t\t\tif (!y)\n\t\t\t\t\tcheckPositions.push_back(std::make_pair(Position(1, 1, 0), O_WESTWALL)); // one tile south-east\n\t\t\t\tif (!x)\n\t\t\t\t\tcheckPositions.push_back(std::make_pair(Position(1, 1, 0), O_NORTHWALL)); // one tile south-east\n\t\t\t\tif (rClick)\n\t\t\t\t{\n\t\t\t\t\tcheckPositions.push_back(std::make_pair(Position(1, 0, 0), O_WESTWALL)); // one tile east\n\t\t\t\t\tcheckPositions.push_back(std::make_pair(Position(0, 1, 0), O_NORTHWALL)); // one tile south\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 4: // south\n\t\t\t\tcheckPositions.push_back(std::make_pair(Position(0, 1, 0), O_NORTHWALL)); // one tile south\n\t\t\t\tbreak;\n\t\t\tcase 5: // south-west\n\t\t\t\tcheckPositions.push_back(std::make_pair(Position(0, 0, 0), O_WESTWALL)); // origin\n\t\t\t\tcheckPositions.push_back(std::make_pair(Position(-1, 1, 0), O_NORTHWALL)); // one tile south-west\n\t\t\t\tif (rClick)\n\t\t\t\t{\n\t\t\t\t\tcheckPositions.push_back(std::make_pair(Position(0, 1, 0), O_WESTWALL)); // one tile south\n\t\t\t\t\tcheckPositions.push_back(std::make_pair(Position(0, 1, 0), O_NORTHWALL)); // one tile south\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 6: // west\n\t\t\t\tcheckPositions.push_back(std::make_pair(Position(0, 0, 0), O_WESTWALL)); // origin\n\t\t\t\tif (y != 0)\n\t\t\t\t{\n\t\t\t\t\tcheckPositions.push_back(std::make_pair(Position(-1, 0, 0), O_NORTHWALL)); // one tile west\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 7: // north-west\n\t\t\t\tcheckPositions.push_back(std::make_pair(Position(0, 0, 0), O_WESTWALL)); // origin\n\t\t\t\tcheckPositions.push_back(std::make_pair(Position(0, 0, 0), O_NORTHWALL)); // origin\n\t\t\t\tif (x)\n\t\t\t\t{\n\t\t\t\t\tcheckPositions.push_back(std::make_pair(Position(-1, -1, 0), O_WESTWALL)); // one tile north\n\t\t\t\t}\n\t\t\t\tif (y)\n\t\t\t\t{\n\t\t\t\t\tcheckPositions.push_back(std::make_pair(Position(-1, -1, 0), O_NORTHWALL)); // one tile north\n\t\t\t\t}\n\t\t\t\tif (rClick)\n\t\t\t\t{\n\t\t\t\t\tcheckPositions.push_back(std::make_pair(Position(0, -1, 0), O_WESTWALL)); // one tile north\n\t\t\t\t\tcheckPositions.push_back(std::make_pair(Position(-1, 0, 0), O_NORTHWALL)); // one tile west\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tTilePart part = O_FLOOR;\n\t\t\tfor (const auto& pair : checkPositions)\n\t\t\t{\n\t\t\t\tif (door != -1)\n\t\t\t\t{\n\t\t\t\t\tbreak; // loop finished\n\t\t\t\t}\n\t\t\t\ttile = _save->getTile(unit->getPosition() + Position(x,y,z) + pair.first);\n\t\t\t\tif (tile)\n\t\t\t\t{\n\t\t\t\t\tdoor = tile->openDoor(pair.second, unit, _save->getBattleGame()->getReservedAction(), rClick);\n\t\t\t\t\tif (door != -1)\n\t\t\t\t\t{\n\t\t\t\t\t\tpart = pair.second;\n\t\t\t\t\t\tif (door == 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t++doorsOpened;\n\t\t\t\t\t\t\tdoorCentre = unit->getPosition() + Position(x, y, z) + pair.first;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (door == 1)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tstd::pair<int, Position> adjacentDoors = checkAdjacentDoors(unit->getPosition() + Position(x,y,z) + pair.first, pair.second);\n\t\t\t\t\t\t\tdoorsOpened += adjacentDoors.first + 1;\n\t\t\t\t\t\t\tdoorCentre = adjacentDoors.second;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (door == 0 && rClick)\n\t\t\t{\n\t\t\t\tif (part == O_WESTWALL)\n\t\t\t\t{\n\t\t\t\t\tpart = O_NORTHWALL;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tpart = O_WESTWALL;\n\t\t\t\t}\n\t\t\t\tTUCost = tile->getTUCost(part, unit->getMovementType());\n\t\t\t}\n\t\t\telse if (door == 1 || door == 4)\n\t\t\t{\n\t\t\t\tTUCost = tile->getTUCost(part, unit->getMovementType());\n\t\t\t}\n\t\t}\n\t}\n\n\tif (door == 0 || door == 1)\n\t{\n\t\tif (_save->getBattleGame()->checkReservedTU(unit, TUCost, 0))\n\t\t{\n\t\t\tif (unit->spendTimeUnits(TUCost))\n\t\t\t{\n\t\t\t\tcalculateLighting(LL_FIRE, doorCentre, doorsOpened, true);\n\t\t\t\t// Update FOV through the doorway.\n\t\t\t\tcalculateFOV(doorCentre, doorsOpened, true, true);\n\t\t\t}\n\t\t\telse return 4;\n\t\t}\n\t\telse return 5;\n\t}\n\n\treturn door;\n}\n\n/**\n * Opens any doors connected to this part at this position,\n * Keeps processing till it hits a non-ufo-door.\n * @param pos The starting position\n * @param part The part to open, defines which direction to check.\n * @return <The number of adjacent doors opened, Position of door centre>\n */\nstd::pair<int, Position> TileEngine::checkAdjacentDoors(Position pos, TilePart part)\n{\n\tPosition offset;\n\tint adjacentDoorsOpened = 0;\n\tint doorOffset = 0;\n\tbool westSide = (part == O_WESTWALL);\n\tfor (int i = 1;; ++i)\n\t{\n\t\toffset = westSide ? Position(0,i,0):Position(i,0,0);\n\t\tTile *tile = _save->getTile(pos + offset);\n\t\tif (tile && tile->isUfoDoor(part))\n\t\t{\n\t\t\tint doorAdj = tile->openDoor(part);\n\t\t\tif (doorAdj == 1) //only expecting ufo doors\n\t\t\t{\n\t\t\t\tadjacentDoorsOpened++;\n\t\t\t\tdoorOffset++;\n\t\t\t}\n\t\t}\n\t\telse break;\n\t}\n\tfor (int i = -1;; --i)\n\t{\n\t\toffset = westSide ? Position(0,i,0):Position(i,0,0);\n\t\tTile *tile = _save->getTile(pos + offset);\n\t\tif (tile && tile->isUfoDoor(part))\n\t\t{\n\t\t\tint doorAdj = tile->openDoor(part);\n\t\t\tif (doorAdj == 1)\n\t\t\t{\n\t\t\t\tadjacentDoorsOpened++;\n\t\t\t\tdoorOffset--;\n\t\t\t}\n\t\t}\n\t\telse break;\n\t}\n\tdoorOffset /= 2; //Find ~centre of door\n\treturn {adjacentDoorsOpened, pos + (westSide ? Position(0, doorOffset, 0) : Position(doorOffset, 0, 0))};\n}\n\n/**\n * Closes ufo doors.\n * @return Whether doors are closed.\n */\nint TileEngine::closeUfoDoors()\n{\n\tint doorsclosed = 0;\n\n\t// prepare a list of tiles on fire/smoke & close any ufo doors\n\tfor (int i = 0; i < _save->getMapSizeXYZ(); ++i)\n\t{\n\t\tif (_save->getTile(i)->getUnit() && _save->getTile(i)->getUnit()->isBigUnit())\n\t\t{\n\t\t\tBattleUnit *bu = _save->getTile(i)->getUnit();\n\t\t\tTile *tile = _save->getTile(i);\n\t\t\tTile *oneTileNorth = _save->getTile(tile->getPosition() + Position(0, -1, 0));\n\t\t\tTile *oneTileWest = _save->getTile(tile->getPosition() + Position(-1, 0, 0));\n\t\t\tif ((tile->isUfoDoorOpen(O_NORTHWALL) && oneTileNorth && oneTileNorth->getUnit() && oneTileNorth->getUnit() == bu) ||\n\t\t\t\t(tile->isUfoDoorOpen(O_WESTWALL) && oneTileWest && oneTileWest->getUnit() && oneTileWest->getUnit() == bu))\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\tdoorsclosed += _save->getTile(i)->closeUfoDoor();\n\t}\n\n\treturn doorsclosed;\n}\n\n/**\n * Calculates a line trajectory, using bresenham algorithm in 3D.\n * @param origin Origin tile.\n * @param target Target tile.\n * @param trajectory A vector of positions in which the trajectory is stored.\n * @return 0 or some value greater than .\n */\nint TileEngine::calculateLineTile(Position origin, Position target, std::vector<Position> &trajectory)\n{\n\tPosition lastPoint = origin;\n\tint steps = 0;\n\n\tbool hit = calculateLineHelper(origin, target,\n\t\t[&](Position point)\n\t\t{\n\t\t\ttrajectory.push_back(point);\n\n\t\t\tconst Position difference = point - lastPoint;\n\t\t\tconst int dir = Pathfinding::vectorToDirection(difference);\n\t\t\tconst auto& cache = _blockVisibility[_save->getTileIndex(lastPoint)];\n\n\t\t\tbool result = getBlockDir(cache, dir, difference.z);\n\t\t\tif (result && difference.z == 0 && getBigWallDir(cache, dir))\n\t\t\t{\n\t\t\t\tif (point == target)\n\t\t\t\t{\n\t\t\t\t\tresult = false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tsteps++;\n\t\t\tlastPoint = point;\n\t\t\treturn result;\n\t\t},\n\t\t[&](Position point)\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t);\n\tif (hit)\n\t{\n\t\treturn 256;\n\t}\n\treturn 0;\n}\n\n/**\n * Calculates a line trajectory, using bresenham algorithm in 3D.\n * @param origin Origin in voxel.\n * @param target Target in voxel.\n * @param storeTrajectory True will store the whole trajectory - otherwise it just stores the last position.\n * @param trajectory A vector of positions in which the trajectory is stored.\n * @param excludeUnit Excludes this unit in the collision detection.\n * @param onlyVisible Skip invisible units? used in FPS view.\n * @param excludeAllBut [Optional] The only unit to be considered for ray hits.\n * @return the objectnumber(0-3) or unit(4) or out of map (5) or -1(hit nothing).\n */\nVoxelType TileEngine::calculateLineVoxel(Position origin, Position target, bool storeTrajectory, std::vector<Position> *trajectory, BattleUnit *excludeUnit, BattleUnit *excludeAllBut, bool onlyVisible)\n{\n\tVoxelType result;\n\tbool excludeAllUnits = false;\n\tif (_save->isBeforeGame())\n\t{\n\t\texcludeAllUnits = true; // don't start unit spotting before pre-game inventory stuff (large units on the craftInventory tile will cause a crash if they're \"spotted\")\n\t}\n\n\tbool hit = calculateLineHelper(origin, target,\n\t\t[&](Position point)\n\t\t{\n\t\t\tif (storeTrajectory && trajectory)\n\t\t\t{\n\t\t\t\ttrajectory->push_back(point);\n\t\t\t}\n\n\t\t\tresult = voxelCheck(point, excludeUnit, excludeAllUnits, onlyVisible, excludeAllBut);\n\t\t\tif (result != V_EMPTY)\n\t\t\t{\n\t\t\t\tif (trajectory)\n\t\t\t\t{ // store the position of impact\n\t\t\t\t\ttrajectory->push_back(point);\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn false;\n\t\t},\n\t\t[&](Position point)\n\t\t{\n\t\t\t//check for xy diagonal intermediate voxel step\n\t\t\tresult = voxelCheck(point, excludeUnit, excludeAllUnits, onlyVisible, excludeAllBut);\n\t\t\tif (result != V_EMPTY)\n\t\t\t{\n\t\t\t\tif (trajectory != 0)\n\t\t\t\t{ // store the position of impact\n\t\t\t\t\ttrajectory->push_back(point);\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\t);\n\tif (hit)\n\t{\n\t\treturn result;\n\t}\n\treturn V_EMPTY;\n}\n\n/**\n * Calculates a parabola trajectory, used for throwing items.\n * @param origin Origin in voxelspace.\n * @param target Target in voxelspace.\n * @param storeTrajectory True will store the whole trajectory - otherwise it just stores the last position.\n * @param trajectory A vector of positions in which the trajectory is stored.\n * @param excludeUnit Makes sure the trajectory does not hit the shooter itself.\n * @param curvature How high the parabola goes: 1.0 is almost straight throw, 3.0 is a very high throw, to throw over a fence for example.\n * @param delta Is the deviation of the angles it should take into account, 0,0,0 is perfection.\n * @return The objectnumber(0-3) or unit(4) or out of map (5) or -1(hit nothing).\n */\nint TileEngine::calculateParabolaVoxel(Position origin, Position target, bool storeTrajectory, std::vector<Position> *trajectory, BattleUnit *excludeUnit, double curvature, const Position delta)\n{\n\tif (target == origin) return V_EMPTY;//just in case\n\n\tint result = V_EMPTY;\n\tPosition lastPosition = origin;\n\tPosition nextPosition = lastPosition;\n\n\tif (storeTrajectory && trajectory)\n\t{\n\t\t//initla value for small hack to glue `calculateLineVoxel` into one continuous arc\n\t\ttrajectory->push_back(lastPosition);\n\t}\n\n\tcalculateParabolaHelper(origin, target, curvature, delta,\n\t\t[&](Position p)\n\t\t{\n\t\t\t//passes through this point?\n\t\t\tnextPosition = p;\n\n\t\t\tif (storeTrajectory && trajectory)\n\t\t\t{\n\t\t\t\t//remove end point of previous trajectory part, because next one will add this point again\n\t\t\t\ttrajectory->pop_back();\n\t\t\t}\n\t\t\tresult = calculateLineVoxel(lastPosition, nextPosition, storeTrajectory, storeTrajectory ? trajectory : nullptr, excludeUnit);\n\t\t\tif (result != V_EMPTY)\n\t\t\t{\n\t\t\t\tif (!storeTrajectory && trajectory)\n\t\t\t\t{\n\t\t\t\t\tresult = calculateLineVoxel(lastPosition, nextPosition, false, trajectory, excludeUnit); //pick the INSIDE position of impact\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tlastPosition = nextPosition;\n\t\t\treturn false;\n\t\t}\n\t);\n\n\treturn result;\n}\n\n/**\n * Calculates z \"grounded\" value for a particular voxel (used for projectile shadow).\n * @param voxel The voxel to trace down.\n * @return z coord of \"ground\".\n */\nint TileEngine::castedShade(Position voxel)\n{\n\tint zstart = voxel.z;\n\tPosition tmpCoord = voxel.toTile();\n\tTile *t = _save->getTile(tmpCoord);\n\twhile (t && t->isVoid() && !t->getUnit())\n\t{\n\t\tzstart = tmpCoord.z* 24;\n\t\t--tmpCoord.z;\n\t\tt = _save->getTile(tmpCoord);\n\t}\n\n\tPosition tmpVoxel = voxel;\n\tint z;\n\n\tvoxelCheckFlush();\n\tfor (z = zstart; z>0; z--)\n\t{\n\t\ttmpVoxel.z = z;\n\t\tif (voxelCheck(tmpVoxel, 0) != V_EMPTY) break;\n\t}\n\treturn z;\n}\n\n/**\n * Traces voxel visibility.\n * @param voxel Voxel coordinates.\n * @return True if visible.\n */\n\nbool TileEngine::isVoxelVisible(Position voxel)\n{\n\tint zstart = voxel.z+3; // slight Z adjust\n\tif ((zstart/24)!=(voxel.z/24))\n\t\treturn true; // visible!\n\tPosition tmpVoxel = voxel;\n\tint zend = (zstart/24)*24 +24;\n\n\tvoxelCheckFlush();\n\tfor (int z = zstart; z<zend; z++)\n\t{\n\t\ttmpVoxel.z=z;\n\t\t// only OBJECT can cause additional occlusion (because of any shape)\n\t\tif (voxelCheck(tmpVoxel, 0) == V_OBJECT) return false;\n\t\t++tmpVoxel.x;\n\t\tif (voxelCheck(tmpVoxel, 0) == V_OBJECT) return false;\n\t\t++tmpVoxel.y;\n\t\tif (voxelCheck(tmpVoxel, 0) == V_OBJECT) return false;\n\t}\n\treturn true;\n}\n\n/**\n * Checks if we hit a voxel.\n * @param voxel The voxel to check.\n * @param excludeUnit Don't do checks on this unit.\n * @param excludeAllUnits Don't do checks on any unit.\n * @param onlyVisible Whether to consider only visible units.\n * @param excludeAllBut If set, the only unit to be considered for ray hits.\n * @return The objectnumber(0-3) or unit(4) or out of map (5) or -1 (hit nothing).\n */\nVoxelType TileEngine::voxelCheck(Position voxel, BattleUnit *excludeUnit, bool excludeAllUnits, bool onlyVisible, BattleUnit *excludeAllBut)\n{\n\tif (voxel.x < 0 || voxel.y < 0 || voxel.z < 0) //preliminary out of map\n\t{\n\t\treturn V_OUTOFBOUNDS;\n\t}\n\tPosition pos = voxel.toTile();\n\tTile *tile, *tileBelow;\n\tif (_cacheTilePos == pos)\n\t{\n\t\ttile = _cacheTile;\n\t\ttileBelow = _cacheTileBelow;\n\t}\n\telse\n\t{\n\t\ttile = _save->getTile(pos);\n\t\tif (!tile) // check if we are not out of the map\n\t\t{\n\t\t\treturn V_OUTOFBOUNDS; //not even cache\n\t\t}\n\t\ttileBelow = _save->getBelowTile(tile);\n\t\t_cacheTilePos = pos;\n\t\t_cacheTile = tile;\n\t\t_cacheTileBelow = tileBelow;\n \t}\n\n\tif (tile->isVoid() && tile->getUnit() == 0 && (!tileBelow || tileBelow->getUnit() == 0))\n\t{\n\t\treturn V_EMPTY;\n\t}\n\n\tif (tile->hasGravLiftFloor() && (voxel.z % 24 == 0 || voxel.z % 24 == 1))\n\t{\n\t\tif (!(tileBelow && tileBelow->hasGravLiftFloor()))\n\t\t{\n\t\t\treturn V_FLOOR;\n\t\t}\n\t}\n\n\t// first we check terrain voxel data, not to allow 2x2 units stick through walls\n\tfor (int i = V_FLOOR; i <= V_OBJECT; ++i)\n\t{\n\t\tTilePart tp = (TilePart)i;\n\t\tMapData *mp = tile->getMapData(tp);\n\t\tif (((tp == O_WESTWALL) || (tp == O_NORTHWALL)) && tile->isUfoDoorOpen(tp))\n\t\t\tcontinue;\n\t\tif (mp != 0)\n\t\t{\n\t\t\tint x = 15 - voxel.x%16;\n\t\t\tint y = voxel.y%16;\n\t\t\tint idx = (mp->getLoftID((voxel.z%24)/2)*16) + y;\n\t\t\tif (_voxelData->at(idx) & (1 << x))\n\t\t\t{\n\t\t\t\treturn (VoxelType)i;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (!excludeAllUnits)\n\t{\n\t\tBattleUnit *unit = tile->getOverlappingUnit(_save);\n\n\t\tif (unit != 0 && !unit->isOut() && unit != excludeUnit && (!excludeAllBut || unit == excludeAllBut) && (!onlyVisible || unit->getVisible() ) )\n\t\t{\n\t\t\tPosition tilepos;\n\t\t\tPosition unitpos = unit->getPosition();\n\t\t\tint terrainHeight = 0;\n\t\t\tfor (int x = 0; x < unit->getArmor()->getSize(); ++x)\n\t\t\t{\n\t\t\t\tfor (int y = 0; y < unit->getArmor()->getSize(); ++y)\n\t\t\t\t{\n\t\t\t\t\tTile *tempTile = _save->getTile(unitpos + Position(x,y,0));\n\t\t\t\t\tif (tempTile->getTerrainLevel() < terrainHeight)\n\t\t\t\t\t{\n\t\t\t\t\t\tterrainHeight = tempTile->getTerrainLevel();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tint tz = unitpos.z*24 + unit->getFloatHeight() - terrainHeight; //bottom most voxel, terrain heights are negative, so we subtract.\n\t\t\tif ((voxel.z > tz) && (voxel.z <= tz + unit->getHeight()) )\n\t\t\t{\n\t\t\t\tint x = 15 - voxel.x%16;\n\t\t\t\tint y = voxel.y%16;\n\t\t\t\tint part = 0;\n\t\t\t\tif (unit->isBigUnit())\n\t\t\t\t{\n\t\t\t\t\ttilepos = tile->getPosition();\n\t\t\t\t\tconst static int parts[] = {1,0,3,2}; // Change order 0,1,2,3 -> 1,0,3,2  (read commit description)\n\t\t\t\t\tpart = parts[tilepos.x - unitpos.x + (tilepos.y - unitpos.y)*2];\n\t\t\t\t}\n\t\t\t\tint idx = (unit->getLoftemps(part) * 16) + y;\n\t\t\t\tif (_voxelData->at(idx) & (1 << x))\n\t\t\t\t{\n\t\t\t\t\treturn V_UNIT;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn V_EMPTY;\n}\n\nvoid TileEngine::voxelCheckFlush()\n{\n\t_cacheTilePos = invalid;\n\t_cacheTile = 0;\n\t_cacheTileBelow = 0;\n}\n\n/**\n * Toggles personal lighting on / off.\n */\nvoid TileEngine::togglePersonalLighting()\n{\n\t_personalLighting = !_personalLighting;\n\n\tif (Options::oxceTogglePersonalLightType == 2)\n\t{\n\t\t// persisted per campaign\n\t\tSavedGame* geosave = _save->getGeoscapeSave();\n\t\tif (geosave)\n\t\t{\n\t\t\tgeosave->setTogglePersonalLight(_personalLighting);\n\t\t}\n\t}\n\telse if (Options::oxceTogglePersonalLightType == 1)\n\t{\n\t\t// persisted per battle\n\t\t_save->setTogglePersonalLight(_personalLighting);\n\t}\n\n\t_save->setTogglePersonalLightTemp(_personalLighting);\n\tcalculateLighting(LL_UNITS);\n\trecalculateFOV();\n}\n\n/**\n * Calculate strength of psi attack based on range and victim.\n * @param type Type of attack.\n * @param attacker Unit attacking.\n * @param victim Attacked unit.\n * @param weapon Attack item.\n * @return Value greater than zero mean successful attack.\n */\nint TileEngine::psiAttackCalculate(BattleActionAttack::ReadOnly attack, const BattleUnit *victim)\n{\n\tif (!victim)\n\t\treturn 0;\n\n\tBattleActionType type = attack.type;\n\tauto* attacker = attack.attacker;\n\tauto* weapon = attack.weapon_item;\n\n\tint attackStrength = BattleUnit::getPsiAccuracy(attack);\n\tint defenseStrength = 30 + victim->getArmor()->getPsiDefence(victim);\n\n\tfloat dis = Position::distance(attacker->getPosition().toVoxel(), victim->getPosition().toVoxel());\n\n\tauto rng = RNG::globalRandomState().subSequence();\n\tint psiAttackResult = 0;\n\n\tpsiAttackResult = ModScript::scriptFunc1<ModScript::TryPsiAttackItem>(\n\t\tweapon->getRules(),\n\t\tpsiAttackResult,\n\t\tweapon, attacker, victim, attack.skill_rules, attackStrength, defenseStrength, type, &rng, (int)dis, (int)weapon->getRules()->getPsiAccuracyRangeReduction(dis),\n\t\t_save\n\t);\n\n\tpsiAttackResult =  ModScript::scriptFunc1<ModScript::TryPsiAttackUnit>(\n\t\tvictim->getArmor(),\n\t\tpsiAttackResult,\n\t\tweapon, attacker, victim, attack.skill_rules, attackStrength, defenseStrength, type,\n\t\t_save\n\t);\n\n\treturn psiAttackResult;\n}\n\n/**\n * Attempts a panic or mind control action.\n * @param action Pointer to an action.\n * @return Whether it failed or succeeded.\n */\nbool TileEngine::psiAttack(BattleActionAttack attack, BattleUnit *victim)\n{\n\tif (_save->isPreview())\n\t{\n\t\treturn false;\n\t}\n\n\tif (!victim)\n\t\treturn false;\n\n\t// Mana experience - this is a temporary/experimental approach, can be improved later after modder feedback\n\tattack.attacker->addManaExp(attack.weapon_item->getRules()->getManaExperience());\n\n\tbool isDefaultExpTrainingMode = (attack.weapon_item->getRules()->getExperienceTrainingMode() == ETM_DEFAULT);\n\tbool isNaturallyPsiCapable = true;\n\tif (attack.attacker->getGeoscapeSoldier() && attack.attacker->getGeoscapeSoldier()->getCurrentStats()->psiSkill <= 0)\n\t{\n\t\tisNaturallyPsiCapable = false;\n\t}\n\tbool isPsiRequired = attack.weapon_item->getRules()->isPsiRequired();\n\n\tif (isDefaultExpTrainingMode)\n\t{\n\t\tif (isNaturallyPsiCapable)\n\t\t{\n\t\t\tattack.attacker->addPsiSkillExp();\n\t\t}\n\t}\n\tif (Options::allowPsiStrengthImprovement && isPsiRequired)\n\t{\n\t\tvictim->addPsiStrengthExp(); // experience for the victim, not the attacker\n\t}\n\n\tif (psiAttackCalculate(attack, victim) > 0)\n\t{\n\t\tif (isDefaultExpTrainingMode)\n\t\t{\n\t\t\tif (isNaturallyPsiCapable)\n\t\t\t{\n\t\t\t\tattack.attacker->addPsiSkillExp();\n\t\t\t\tattack.attacker->addPsiSkillExp();\n\t\t\t}\n\t\t}\n\t\telse if (attack.type == BA_PANIC || attack.type == BA_MINDCONTROL)\n\t\t{\n\t\t\t// Note: BA_USE is handled elsewhere\n\t\t\tawardExperience(attack, victim, false);\n\t\t}\n\n\t\tBattleUnitKills killStat;\n\t\tkillStat.setUnitStats(victim);\n\t\tkillStat.setTurn(_save->getTurn(), _save->getSide());\n\t\tkillStat.weapon = attack.weapon_item->getRules()->getName();\n\t\tkillStat.weaponAmmo = attack.weapon_item->getRules()->getName(); //Psi weapons got no ammo, just filling up the field\n\t\tkillStat.faction = victim->getOriginalFaction();\n\t\tkillStat.mission = _save->getGeoscapeSave()->getMissionStatistics()->size();\n\t\tkillStat.id = victim->getId();\n\n\t\tif (attack.type == BA_PANIC)\n\t\t{\n\t\t\tint moraleLoss = victim->reduceByBravery(100);\n\t\t\tif (moraleLoss > 0)\n\t\t\t\tvictim->moraleChange(-moraleLoss);\n\t\t\tvictim->setMindControllerId(attack.attacker->getId());\n\n\t\t\t// Award Panic battle unit kill\n\t\t\tif (!attack.attacker->getStatistics()->duplicateEntry(STATUS_PANICKING, victim->getId()))\n\t\t\t{\n\t\t\t\tkillStat.status = STATUS_PANICKING;\n\t\t\t\tif (!victim->isCosmetic())\n\t\t\t\t{\n\t\t\t\t\tattack.attacker->getStatistics()->kills.push_back(new BattleUnitKills(killStat));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse if (attack.type == BA_MINDCONTROL)\n\t\t{\n\t\t\t// Award MC battle unit kill\n\t\t\tif (!attack.attacker->getStatistics()->duplicateEntry(STATUS_TURNING, victim->getId()))\n\t\t\t{\n\t\t\t\tkillStat.status = STATUS_TURNING;\n\t\t\t\tif (!victim->isCosmetic())\n\t\t\t\t{\n\t\t\t\t\tattack.attacker->getStatistics()->kills.push_back(new BattleUnitKills(killStat));\n\t\t\t\t}\n\t\t\t}\n\t\t\tvictim->setMindControllerId(attack.attacker->getId());\n\t\t\tif (attack.weapon_item->getRules()->convertToCivilian() && victim->getOriginalFaction() == FACTION_HOSTILE)\n\t\t\t{\n\t\t\t\tvictim->convertToFaction(FACTION_NEUTRAL);\n\t\t\t\tif (victim->getAIModule())\n\t\t\t\t{\n\t\t\t\t\t// rewire them to attack hostiles\n\t\t\t\t\tvictim->getAIModule()->setTargetFaction(FACTION_HOSTILE);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tvictim->convertToFaction(attack.attacker->getFaction());\n\t\t\t\tcalculateLighting(LL_UNITS, victim->getPosition());\n\t\t\t\tcalculateFOV(victim->getPosition()); //happens fairly rarely, so do a full recalc for units in range to handle the potential unit visible cache issues.\n\t\t\t}\n\t\t\tvictim->recoverTimeUnits();\n\t\t\tvictim->allowReselect();\n\t\t\tvictim->abortTurn(); // resets unit status to STANDING\n\t\t\t// if all units from either faction are mind controlled - auto-end the mission.\n\t\t\tif (_save->getSide() == FACTION_PLAYER && Options::allowPsionicCapture)\n\t\t\t{\n\t\t\t\t_save->getBattleGame()->autoEndBattle();\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\telse\n\t{\n\t\tif (Options::allowPsiStrengthImprovement && isPsiRequired)\n\t\t{\n\t\t\tvictim->addPsiStrengthExp(); // experience for the victim, not the attacker\n\t\t}\n\t\treturn false;\n\t}\n}\n\n/**\n * Calculate success rate of melee attack action.\n */\nint TileEngine::meleeAttackCalculate(BattleActionAttack::ReadOnly attack, const BattleUnit *victim)\n{\n\tif (!victim)\n\t\treturn 0;\n\n\tint attackStrength = BattleUnit::getFiringAccuracy(attack, _save->getBattleGame()->getMod());\n\tint defenseStrength = victim->getArmor()->getMeleeDodge(victim);\n\tint arc = getArcDirection(getDirectionTo(victim->getPositionVexels(), attack.attacker->getPositionVexels()), victim->getDirection());\n\tint defenseStrengthPenalty = Clamp((int)(defenseStrength * (arc * victim->getArmor()->getMeleeDodgeBackPenalty() / 4.0f)), 0, std::max(0, defenseStrength));\n\n\tBattleActionType type = attack.type;\n\tauto* attacker = attack.attacker;\n\tauto* weapon = attack.weapon_item;\n\n\tauto rng = RNG::globalRandomState().subSequence();\n\n\tint meleeAttackResult = 0;\n\n\tmeleeAttackResult = ModScript::scriptFunc1<ModScript::TryMeleeAttackItem>(\n\t\tweapon->getRules(),\n\t\tmeleeAttackResult,\n\t\tweapon, attacker, victim, attack.skill_rules, attackStrength, defenseStrength, type, &rng, arc, defenseStrengthPenalty,\n\t\t_save\n\t);\n\n\tmeleeAttackResult =  ModScript::scriptFunc1<ModScript::TryMeleeAttackUnit>(\n\t\tvictim->getArmor(),\n\t\tmeleeAttackResult,\n\t\tweapon, attacker, victim, attack.skill_rules, attackStrength, defenseStrength, type,\n\t\t_save\n\t);\n\n\n\treturn meleeAttackResult;\n}\n\n/**\n *  Attempts a melee attack action.\n * @param action Pointer to an action.\n * @return Whether it failed or succeeded.\n */\nbool TileEngine::meleeAttack(BattleActionAttack attack, BattleUnit *victim, int terrainMeleeTilePart)\n{\n\tif (terrainMeleeTilePart > 0)\n\t{\n\t\t// terrain melee doesn't miss\n\t\treturn true;\n\t}\n\tif (attack.type != BA_CQB)\n\t{\n\t\t// hit log - new melee attack\n\t\t_save->appendToHitLog(HITLOG_NEW_SHOT, attack.attacker->getFaction());\n\n\t\t// to allow melee reactions when attacked from any side, not just from the front\n\t\tif (victim && Mod::EXTENDED_MELEE_REACTIONS == 2)\n\t\t{\n\t\t\tvictim->setMeleeAttackedBy(attack.attacker->getId());\n\t\t}\n\t}\n\n\treturn meleeAttackCalculate(attack, victim) > 0;\n}\n\n/**\n * Remove the medikit from the game if consumable and empty.\n * @param action\n */\nvoid TileEngine::medikitRemoveIfEmpty(BattleAction *action)\n{\n\t// remove item if completely used up\n\tif (action->weapon->getRules()->isConsumable())\n\t{\n\t\tif (action->weapon->getPainKillerQuantity() == 0 && action->weapon->getStimulantQuantity() == 0 && action->weapon->getHealQuantity() == 0)\n\t\t{\n\t\t\t_save->removeItem(action->weapon);\n\t\t}\n\t}\n}\n\nbool TileEngine::medikitUse(BattleAction *action, BattleUnit *target, BattleMediKitAction originalMedikitAction, UnitBodyPart bodyPart)\n{\n\tif (_save->isPreview())\n\t{\n\t\treturn false;\n\t}\n\n\tBattleActionAttack attack;\n\tattack.type = action->type;\n\tattack.attacker = action->actor;\n\tattack.weapon_item = action->weapon;\n\tattack.damage_item = action->weapon;\n\n\tbool canContinueHealing = true;\n\n\tconst RuleItem *rule = action->weapon->getRules();\n\n\tBattleMediKitType type = rule->getMediKitType();\n\n\tconstexpr int medikitActionKey = 0;\n\tconstexpr int bodyPartKey = 1;\n\tconstexpr int woundRecoveryKey = 2;\n\tconstexpr int healthRecoveryKey = 3;\n\tconstexpr int energyRecoveryKey = 4;\n\tconstexpr int stunRecoveryKey = 5;\n\tconstexpr int manaRecoveryKey = 6;\n\tconstexpr int moraleRecoveryKey = 7;\n\tconstexpr int painkillerRecoveryKey = 8;\n\n\taction->weapon->spendHealingItemUse(originalMedikitAction);\n\n\tModScript::HealUnit::Output args { };\n\n\tstd::get<medikitActionKey>(args.data) += originalMedikitAction;\n\tstd::get<bodyPartKey>(args.data) += (int)bodyPart;\n\tstd::get<woundRecoveryKey>(args.data) += rule->getWoundRecovery();\n\tstd::get<healthRecoveryKey>(args.data) += rule->getHealthRecovery();\n\tstd::get<energyRecoveryKey>(args.data) += rule->getEnergyRecovery();\n\tstd::get<stunRecoveryKey>(args.data) += rule->getStunRecovery();\n\tstd::get<manaRecoveryKey>(args.data) += rule->getManaRecovery();\n\tstd::get<moraleRecoveryKey>(args.data) += rule->getMoraleRecovery();\n\tstd::get<painkillerRecoveryKey>(args.data) += (int)(rule->getPainKillerRecovery() * 100.0f);\n\n\tModScript::HealUnit::Worker work { action->actor, action->weapon, _save, target, action->type };\n\n\twork.execute(target->getArmor()->getScript<ModScript::HealUnit>(), args);\n\n\tint medikitAction = std::get<medikitActionKey>(args.data);\n\tbodyPart = (UnitBodyPart)std::get<bodyPartKey>(args.data);\n\tint healthRecovery = std::get<healthRecoveryKey>(args.data);\n\tint woundRecovery = std::get<woundRecoveryKey>(args.data);\n\tint energyRecovery = std::get<energyRecoveryKey>(args.data);\n\tint stunRecovery = std::get<stunRecoveryKey>(args.data);\n\tint manaRecovery = std::get<manaRecoveryKey>(args.data);\n\tint moraleRecovery = std::get<moraleRecoveryKey>(args.data);\n\tfloat painkillerRecovery = std::get<painkillerRecoveryKey>(args.data) / 100.0f;\n\n\t// 0 = normal, 1 = heal, 2 = stim, 4 = pain\n\tif (medikitAction & BMA_PAINKILLER)\n\t{\n\t\ttarget->painKillers(moraleRecovery, painkillerRecovery);\n\t}\n\n\tif (medikitAction & BMA_STIMULANT)\n\t{\n\t\ttarget->stimulant(energyRecovery, stunRecovery, manaRecovery);\n\t}\n\n\tif (medikitAction & BMA_HEAL)\n\t{\n\t\tif (target->getFatalWound(bodyPart))\n\t\t{\n\t\t\t// award experience only if healed body part has a fatal wound (to prevent abuse)\n\t\t\tawardExperience(attack, target, false);\n\t\t}\n\n\t\ttarget->heal(bodyPart, woundRecovery, healthRecovery);\n\t}\n\n\t_save->getBattleGame()->playSound(action->weapon->getRules()->getHitSound());\n\n\tif (type == BMT_NORMAL) // normal medikit usage, track statistics\n\t{\n\t\tif (medikitAction & BMA_PAINKILLER)\n\t\t{\n\t\t\taction->actor->getStatistics()->appliedPainKill++;\n\t\t}\n\t\tif (medikitAction & BMA_STIMULANT)\n\t\t{\n\t\t\taction->actor->getStatistics()->appliedStimulant++;\n\t\t}\n\t\tif (medikitAction & BMA_HEAL)\n\t\t{\n\t\t\taction->actor->getStatistics()->woundsHealed++;\n\t\t}\n\n\t\tif (target->getStatus() == STATUS_UNCONSCIOUS && !target->isOutThresholdExceed())\n\t\t{\n\t\t\tif(target->getOriginalFaction() == FACTION_PLAYER)\n\t\t\t{\n\t\t\t\taction->actor->getStatistics()->revivedSoldier++;\n\t\t\t}\n\t\t\telse if(target->getOriginalFaction() == FACTION_HOSTILE)\n\t\t\t{\n\t\t\t\taction->actor->getStatistics()->revivedHostile++;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\taction->actor->getStatistics()->revivedNeutral++;\n\t\t\t}\n\t\t\t// if the unit has revived and has no more wounds, we cannot continue healing\n\t\t\tif (target->getFatalWounds() == 0)\n\t\t\t{\n\t\t\t\tcanContinueHealing = false;\n\t\t\t}\n\t\t}\n\t}\n\n\t// check for casualties, revive unconscious unit (+ change status), re-calc fov & lighting\n\tupdateGameStateAfterScript(attack, action->actor->getPosition());\n\n\treturn canContinueHealing;\n}\n\n/**\n * Executes the skillUseUnit script hook and determines further steps.\n * @return True if the current action should be continued, false if the action should be cancelled (usually because the script took care of any effects itself).\n */\nbool TileEngine::skillUse(BattleAction *action, const RuleSkill *skill)\n{\n\tif (_save->isPreview())\n\t{\n\t\treturn false;\n\t}\n\n\tbool continueAction = true;\n\tbool spendTu = false;\n\tstd::string message;\n\tBattleUnit *actor = action->actor;\n\tbool hasTu = action->haveTU(&message);\n\n\tModScript::SkillUseUnit::Output args { continueAction, spendTu };\n\tModScript::SkillUseUnit::Worker work { actor, action->weapon, _save, skill, action->type, hasTu };\n\n\twork.execute(skill->getScript<ModScript::SkillUseUnit>(), args);\n\n\tcontinueAction = args.getFirst();\n\tspendTu = args.getSecond();\n\n\tif (spendTu)\n\t{\n\t\taction->actor->spendCost(static_cast<const RuleItemUseCost&>(*action));\n\t}\n\n\tif (!hasTu && !message.empty())\n\t{\n\t\taction->result = message;\n\t}\n\n\treturn continueAction;\n}\n\n/**\n * Tries to conceal a unit. Only works if no unit of another faction is watching.\n */\nbool TileEngine::tryConcealUnit(BattleUnit* unit)\n{\n\tfor (const auto* bu : *_save->getUnits())\n\t{\n\t\tif (bu->getFaction() != unit->getFaction() && bu->hasVisibleUnit(unit))\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tunit->setTurnsSinceSpotted(255);\n\tunit->setTurnsLeftSpottedForSnipers(0);\n\n\treturn true;\n}\n\n/**\n * Applies gravity to a tile. Causes items and units to drop.\n * @param t Tile.\n * @return Tile where the items end up in eventually.\n */\nTile *TileEngine::applyGravity(Tile *t)\n{\n\tif (!t || (t->getInventory()->empty() && !t->getUnit())) return t; // skip this if there are no items\n\n\tBattleUnit *occupant = t->getUnit();\n\n\tif (occupant)\n\t{\n\t\toccupant->updateTileFloorState(_save);\n\t\tif (occupant->haveNoFloorBelow())\n\t\t{\n\t\t\tif (!occupant->isOutThresholdExceed())\n\t\t\t{\n\t\t\t\tif (occupant->getMovementType() == MT_FLY)\n\t\t\t\t{\n\t\t\t\t\t// move to the position you're already in. this will unset the kneeling flag, set the floating flag, etc.\n\t\t\t\t\toccupant->startWalking(occupant->getDirection(), occupant->getPosition(), _save);\n\t\t\t\t\t// and set our status to standing (rather than walking or flying) to avoid weirdness.\n\t\t\t\t\toccupant->abortTurn();\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\toccupant->setPosition(occupant->getPosition()); // this is necessary to set the unit up for falling correctly, updating their \"lastPos\"\n\t\t\t\t\t_save->addFallingUnit(occupant);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tTile *rt = t;\n\twhile (rt->getPosition().z > 0 && rt->hasNoFloor(_save))\n\t{\n\t\trt = _save->getBelowTile(rt);\n\t}\n\n\tfor (auto* bi : *t->getInventory())\n\t{\n\t\tif (bi->getUnit() && t->getPosition() == bi->getUnit()->getPosition())\n\t\t{\n\t\t\tbi->getUnit()->setPosition(rt->getPosition());\n\t\t}\n\t\tif (t != rt)\n\t\t{\n\t\t\trt->addItem(bi, bi->getSlot());\n\t\t}\n\t}\n\n\tif (t != rt)\n\t{\n\t\t// clear tile\n\t\tt->getInventory()->clear();\n\t}\n\n\treturn rt;\n}\n\n/**\n * Drop item on ground.\n */\nvoid TileEngine::itemDrop(Tile *t, BattleItem *item, bool updateLight)\n{\n\t// don't spawn anything outside of bounds\n\tif (t == 0)\n\t\treturn;\n\n\tPosition p = t->getPosition();\n\n\t// don't ever drop fixed items\n\tif (item->getRules()->isFixed())\n\t\treturn;\n\n\tif (_save->getSide() != FACTION_PLAYER)\n\t{\n\t\titem->setTurnFlag(true);\n\t}\n\n\titemMoveInventory(t, nullptr, item, _inventorySlotGround, 0, 0);\n\n\tapplyGravity(t);\n\n\tif (updateLight)\n\t{\n\t\tcalculateLighting(LL_ITEMS, p);\n\t\tcalculateFOV(p, item->getVisibilityUpdateRange(), false);\n\t}\n}\n\n/**\n * Drop all unit items on ground.\n */\nvoid TileEngine::itemDropInventory(Tile *t, BattleUnit *unit, bool unprimeItems, bool deleteFixedItems)\n{\n\tCollections::removeIf(*unit->getInventory(),\n\t\t[&](BattleItem* i)\n\t\t{\n\t\t\tif (!i->getRules()->isFixed())\n\t\t\t{\n\t\t\t\ti->setOwner(nullptr);\n\t\t\t\tif (unprimeItems && i->getRules()->getFuseTimerType() != BFT_NONE)\n\t\t\t\t{\n\t\t\t\t\tif (i->getRules()->getCostUnprime().Time > 0 /* && !i->getRules()->getUnprimeActionName().empty() */ )\n\t\t\t\t\t{\n\t\t\t\t\t\ti->setFuseTimer(-1); // unprime explosives before dropping them\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tt->addItem(i, _inventorySlotGround);\n\t\t\t\tif (i->getUnit() && i->getUnit()->getStatus() == STATUS_UNCONSCIOUS)\n\t\t\t\t{\n\t\t\t\t\ti->getUnit()->setPosition(t->getPosition());\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (deleteFixedItems)\n\t\t\t\t{\n\t\t\t\t\t// first unload all ammo\n\t\t\t\t\tfor (int slot = 0; slot < RuleItem::AmmoSlotMax; ++slot)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (i->needsAmmoForSlot(slot) && i->getAmmoForSlot(slot))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// unload the existing ammo (if any) from the weapon\n\t\t\t\t\t\t\tBattleItem* oldAmmo = i->setAmmoForSlot(slot, nullptr);\n\t\t\t\t\t\t\tif (oldAmmo)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\titemDrop(t, oldAmmo, false);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// delete fixed items completely (e.g. when changing armor)\n\t\t\t\t\ti->setOwner(nullptr);\n\t\t\t\t\t_save->removeItem(i);\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// do nothing, fixed items cannot be moved (individually by the player)!\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t);\n\n\t// handle special built-in items\n\tif (deleteFixedItems)\n\t{\n\t\tunit->removeSpecialWeapons(_save);\n\t}\n}\n\n/**\n * Move item to other place in inventory or ground.\n */\nvoid TileEngine::itemMoveInventory(Tile *t, BattleUnit *unit, BattleItem *item, const RuleInventory *slot, int x, int y)\n{\n\t// Handle dropping from/to ground.\n\tif (slot != item->getSlot())\n\t{\n\t\tif (slot == _inventorySlotGround)\n\t\t{\n\t\t\titem->moveToOwner(nullptr);\n\t\t\tt->addItem(item, slot);\n\t\t\tif (item->getUnit() && item->getUnit()->getStatus() == STATUS_UNCONSCIOUS)\n\t\t\t{\n\t\t\t\titem->getUnit()->setPosition(t->getPosition());\n\t\t\t}\n\t\t}\n\t\telse if (item->getSlot() == 0 || item->getSlot() == _inventorySlotGround)\n\t\t{\n\t\t\titem->moveToOwner(unit);\n\t\t\titem->setTurnFlag(false);\n\t\t\tif (item->getUnit() && item->getUnit()->getStatus() == STATUS_UNCONSCIOUS)\n\t\t\t{\n\t\t\t\titem->getUnit()->setPosition(invalid);\n\t\t\t}\n\t\t}\n\t}\n\titem->setSlot(slot);\n\titem->setSlotX(x);\n\titem->setSlotY(y);\n}\n\n/**\n * Add moving unit.\n */\nvoid TileEngine::addMovingUnit(BattleUnit* unit)\n{\n\tif (_movingUnit != nullptr)\n\t{\n\t\t_movingUnitPrev.push_back(_movingUnit);\n\t}\n\t_movingUnit = unit;\n}\n\n/**\n * Add moving unit.\n */\nvoid TileEngine::removeMovingUnit(BattleUnit* unit)\n{\n\tif (_movingUnit != unit)\n\t{\n\t\tthrow Exception(\"Wrong unit is removed from TileEngine movingUnit\");\n\t}\n\tif (_movingUnitPrev.empty())\n\t{\n\t\t_movingUnit = nullptr;\n\t}\n\telse\n\t{\n\t\t_movingUnit = _movingUnitPrev.back();\n\t\t_movingUnitPrev.pop_back();\n\t}\n}\n\n/**\n * Get current moving unit.\n */\nBattleUnit* TileEngine::getMovingUnit()\n{\n\treturn _movingUnit;\n}\n\n/**\n * Validates the melee range between two units.\n * @param attacker The attacking unit.\n * @param target The unit we want to attack.\n * @param dir Direction to check.\n * @return True when the range is valid.\n */\nbool TileEngine::validMeleeRange(BattleUnit *attacker, BattleUnit *target, int dir)\n{\n\treturn validMeleeRange(attacker->getPosition(), dir, attacker, target, 0);\n}\n\n/**\n * Validates the melee range between a tile and a unit.\n * @param pos Position to check from.\n * @param direction Direction to check.\n * @param attacker The attacking unit.\n * @param target The unit we want to attack, 0 for any unit.\n * @param dest Destination position.\n * @return True when the range is valid.\n */\nbool TileEngine::validMeleeRange(Position pos, int direction, BattleUnit *attacker, BattleUnit *target, Position *dest, bool preferEnemy)\n{\n\tif (direction < 0 || direction > 7)\n\t{\n\t\treturn false;\n\t}\n\tstd::vector<BattleUnit*> potentialTargets;\n\tBattleUnit *chosenTarget = 0;\n\tPosition p;\n\tint size = attacker->getArmor()->getSize() - 1;\n\tint meleeOriginVoxelVerticalOffset = attacker->getArmor()->getMeleeOriginVoxelVerticalOffset(); // add some sanity checks or trust the modders?\n\tPathfinding::directionToVector(direction, &p);\n\tfor (int x = 0; x <= size; ++x)\n\t{\n\t\tfor (int y = 0; y <= size; ++y)\n\t\t{\n\t\t\tTile *origin (_save->getTile(Position(pos + Position(x, y, 0))));\n\t\t\tTile *targetTile (_save->getTile(Position(pos + Position(x, y, 0) + p)));\n\n\t\t\tif (targetTile && origin)\n\t\t\t{\n\t\t\t\tTile *aboveTargetTile = _save->getAboveTile(targetTile);\n\t\t\t\tTile *belowTargetTile = _save->getBelowTile(targetTile);\n\n\t\t\t\tif (origin->getTerrainLevel() <= -16 && aboveTargetTile && !aboveTargetTile->hasNoFloor(_save))\n\t\t\t\t{\n\t\t\t\t\ttargetTile = aboveTargetTile;\n\t\t\t\t}\n\t\t\t\telse if (belowTargetTile && targetTile->hasNoFloor(_save) && !targetTile->getUnit() && belowTargetTile->getTerrainLevel() <= -16)\n\t\t\t\t{\n\t\t\t\t\ttargetTile = belowTargetTile;\n\t\t\t\t}\n\t\t\t\tif (targetTile->getUnit())\n\t\t\t\t{\n\t\t\t\t\tif (target == 0 || targetTile->getUnit() == target)\n\t\t\t\t\t{\n\t\t\t\t\t\tPosition originVoxel = Position(origin->getPosition().toVoxel())\n\t\t\t\t\t\t\t+ Position(8,8,attacker->getHeight() + attacker->getFloatHeight() - 4 -origin->getTerrainLevel() + meleeOriginVoxelVerticalOffset);\n\t\t\t\t\t\tPosition targetVoxel;\n\t\t\t\t\t\tif (canTargetUnit(&originVoxel, targetTile, &targetVoxel, attacker, false))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (dest)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t*dest = targetTile->getPosition();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (target != 0)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tpotentialTargets.push_back(targetTile->getUnit());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (auto* bu : potentialTargets)\n\t{\n\t\t// if there's actually something THERE, we'll chalk this up as a success.\n\t\tif (!chosenTarget)\n\t\t{\n\t\t\tchosenTarget = bu;\n\t\t}\n\t\t// but if there's a target of a different faction, we'll prioritize them.\n\t\telse if ((preferEnemy && bu->getFaction() != attacker->getFaction())\n\t\t// or, if we're using a medikit, prioritize whichever friend is wounded the most.\n\t\t|| (!preferEnemy && bu->getFaction() == attacker->getFaction() &&\n\t\tbu->getFatalWounds() > chosenTarget->getFatalWounds()))\n\t\t{\n\t\t\tchosenTarget = bu;\n\t\t}\n\t}\n\n\tif (dest && chosenTarget)\n\t{\n\t\t*dest = chosenTarget->getPosition();\n\t}\n\n\treturn chosenTarget != 0;\n}\n\n/**\n * Validates the terrain melee range.\n */\nbool TileEngine::validTerrainMeleeRange(BattleAction* action)\n{\n\tif (Mod::EXTENDED_TERRAIN_MELEE <= 0)\n\t{\n\t\t// turned off\n\t\treturn false;\n\t}\n\n\taction->terrainMeleeTilePart = 0;\n\n\tif (action->weapon)\n\t{\n\t\tauto* wRule = action->weapon->getRules();\n\t\tif (wRule->getBattleType() == BT_MELEE)\n\t\t{\n\t\t\t// check primary damage type\n\t\t\tif (wRule->getDamageType()->ToTile == 0.0) return false;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// check secondary damage type\n\t\t\tif (wRule->getMeleeType()->ToTile == 0.0) return false;\n\t\t}\n\t}\n\n\tPosition pos = action->actor->getPosition();\n\tint direction = action->actor->getDirection();\n\tBattleUnit* attacker = action->actor;\n\n\tif (direction < 0 || direction > 7)\n\t{\n\t\treturn false;\n\t}\n\tif (direction % 2 != 0)\n\t{\n\t\t// diagonal directions are not supported\n\t\treturn false;\n\t}\n\tPosition p;\n\tPathfinding::directionToVector(direction, &p);\n\n\tTile* originTile = _save->getTile(pos);\n\tTile* originTile2 = originTile;\n\tif (originTile && originTile->getTerrainLevel() <= -16)\n\t{\n\t\t// if we are on the upper part of stairs, target one tile above\n\t\tpos += Position(0, 0, 1);\n\t\toriginTile = _save->getTile(pos);\n\t}\n\tTile* neighbouringTile = _save->getTile(pos + p);\n\tTile* neighbouringTile2 = nullptr;\n\tint size = attacker->getArmor()->getSize();\n\tif (size > 1)\n\t{\n\t\tif (direction == 0)\n\t\t{\n\t\t\t// North\n\t\t\toriginTile2 = _save->getTile(pos + Position(1, 0, 0));\n\t\t\tneighbouringTile2 = _save->getTile(pos + p + Position(1, 0, 0));\n\t\t}\n\t\telse if (direction == 2)\n\t\t{\n\t\t\t// East\n\t\t\tneighbouringTile =  _save->getTile(pos + p + Position(1, 0, 0));\n\t\t\tneighbouringTile2 = _save->getTile(pos + p + Position(1, 1, 0));\n\t\t}\n\t\telse if (direction == 4)\n\t\t{\n\t\t\t// South\n\t\t\tneighbouringTile =  _save->getTile(pos + p + Position(0, 1, 0));\n\t\t\tneighbouringTile2 = _save->getTile(pos + p + Position(1, 1, 0));\n\t\t}\n\t\telse if (direction == 6)\n\t\t{\n\t\t\t// West\n\t\t\toriginTile2 = _save->getTile(pos + Position(0, 1, 0));\n\t\t\tneighbouringTile2 = _save->getTile(pos + p + Position(0, 1, 0));\n\t\t}\n\t\tif (!neighbouringTile2 || !originTile2)\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\tif (originTile && neighbouringTile)\n\t{\n\t\tauto setTarget = [](Tile* tt, TilePart tp, BattleAction* aa, int dir = -1) -> bool\n\t\t{\n\t\t\tMapData* obj = tt->getMapData(tp);\n\t\t\tif (obj)\n\t\t\t{\n\t\t\t\tif (dir > -1 && tp == O_OBJECT)\n\t\t\t\t{\n\t\t\t\t\tint bigWall = obj->getBigWall();\n\t\t\t\t\tif (dir == 0 /*north*/ && bigWall != Pathfinding::BIGWALLNORTH && bigWall != Pathfinding::BIGWALLWESTANDNORTH) return false;\n\t\t\t\t\tif (dir == 2 /*east */ && bigWall != Pathfinding::BIGWALLEAST  && bigWall != Pathfinding::BIGWALLEASTANDSOUTH) return false;\n\t\t\t\t\tif (dir == 4 /*south*/ && bigWall != Pathfinding::BIGWALLSOUTH && bigWall != Pathfinding::BIGWALLEASTANDSOUTH) return false;\n\t\t\t\t\tif (dir == 6 /*west */ && bigWall != Pathfinding::BIGWALLWEST  && bigWall != Pathfinding::BIGWALLWESTANDNORTH) return false;\n\t\t\t\t}\n\t\t\t\tif (tp != O_OBJECT && !obj->isDoor() && !obj->isUFODoor() && tt->getTUCost(tp, MT_WALK) != Pathfinding::INVALID_MOVE_COST)\n\t\t\t\t{\n\t\t\t\t\t// it is possible to walk through this (rubble) wall... no need to attack it\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbool isHighEnough = false;\n\t\t\t\tfor (int i = Mod::EXTENDED_TERRAIN_MELEE; i < 12; ++i)\n\t\t\t\t{\n\t\t\t\t\tif (obj->getLoftID(i) > 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tisHighEnough = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (isHighEnough)\n\t\t\t\t{\n\t\t\t\t\taa->target = tt->getPosition();\n\t\t\t\t\taa->terrainMeleeTilePart = tp;\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t};\n\n\t\tif (setTarget(originTile, O_OBJECT, action, direction))\n\t\t{\n\t\t\t// All directions: target the object (marked as big wall) on the current tile\n\t\t\treturn true;\n\t\t}\n\t\tif (size > 1)\n\t\t{\n\t\t\tif (setTarget(originTile2, O_OBJECT, action, direction))\n\t\t\t{\n\t\t\t\t// All directions\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\tif (direction == 0 && setTarget(originTile, O_NORTHWALL, action))\n\t\t{\n\t\t\t// North: target the north wall of the same tile\n\t\t\treturn true;\n\t\t}\n\t\telse if (direction == 2 && setTarget(neighbouringTile, O_WESTWALL, action))\n\t\t{\n\t\t\t// East: target the west wall of the neighbouring tile\n\t\t\treturn true;\n\t\t}\n\t\telse if (direction == 4 && setTarget(neighbouringTile, O_NORTHWALL, action))\n\t\t{\n\t\t\t// South: target the north wall of the neighbouring tile\n\t\t\treturn true;\n\t\t}\n\t\telse if (direction == 6 && setTarget(originTile, O_WESTWALL, action))\n\t\t{\n\t\t\t// West: target the west wall of the same tile\n\t\t\treturn true;\n\t\t}\n\t\tif (size > 1)\n\t\t{\n\t\t\tif (direction == 0 && setTarget(originTile2, O_NORTHWALL, action))\n\t\t\t{\n\t\t\t\t// North\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\telse if (direction == 2 && setTarget(neighbouringTile2, O_WESTWALL, action))\n\t\t\t{\n\t\t\t\t// East\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\telse if (direction == 4 && setTarget(neighbouringTile2, O_NORTHWALL, action))\n\t\t\t{\n\t\t\t\t// South\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\telse if (direction == 6 && setTarget(originTile2, O_WESTWALL, action))\n\t\t\t{\n\t\t\t\t// West\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\tif (setTarget(neighbouringTile, O_OBJECT, action))\n\t\t{\n\t\t\t// All directions: target the object on the neighbouring tile\n\t\t\treturn true;\n\t\t}\n\t\tif (size > 1)\n\t\t{\n\t\t\tif (setTarget(neighbouringTile2, O_OBJECT, action))\n\t\t\t{\n\t\t\t\t// All directions\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn false;\n}\n\n/**\n * Gets the AI to look through a window.\n * @param position Current position.\n * @return Direction or -1 when no window found.\n */\nint TileEngine::faceWindow(Position position)\n{\n\tstatic const Position oneTileEast = Position(1, 0, 0);\n\tstatic const Position oneTileSouth = Position(0, 1, 0);\n\n\tTile *tile = _save->getTile(position);\n\tif (tile && tile->getMapData(O_NORTHWALL) && tile->getMapData(O_NORTHWALL)->getBlock(DT_NONE)==0) return 0;\n\ttile = _save->getTile(position + oneTileEast);\n\tif (tile && tile->getMapData(O_WESTWALL) && tile->getMapData(O_WESTWALL)->getBlock(DT_NONE)==0) return 2;\n\ttile = _save->getTile(position + oneTileSouth);\n\tif (tile && tile->getMapData(O_NORTHWALL) && tile->getMapData(O_NORTHWALL)->getBlock(DT_NONE)==0) return 4;\n\ttile = _save->getTile(position);\n\tif (tile && tile->getMapData(O_WESTWALL) && tile->getMapData(O_WESTWALL)->getBlock(DT_NONE)==0) return 6;\n\n\treturn -1;\n}\n\n/**\n * Validates a throw action.\n * @param action The action to validate.\n * @param originVoxel The origin point of the action.\n * @param targetVoxel The target point of the action.\n * @param depth Battlescape depth.\n * @param curve The curvature of the throw.\n * @param voxelType The type of voxel at which this parabola terminates.\n * @return Validity of action.\n */\nbool TileEngine::validateThrow(BattleAction &action, Position originVoxel, Position targetVoxel, int depth, double *curve, int *voxelType, bool forced)\n{\n\tbool foundCurve = false;\n\tdouble curvature = 0.5;\n\tif (action.type == BA_THROW)\n\t{\n\t\tcurvature = std::max(0.48, 1.73 / sqrt(sqrt((double)(action.actor->getBaseStats()->strength) / (double)(action.weapon->getTotalWeight()))) + (action.actor->isKneeled()? 0.1 : 0.0));\n\t}\n\telse\n\t{\n\t\t// arcing projectile weapons assume a fixed strength and weight.(70 and 10 respectively)\n\t\t// curvature should be approximately 1.06358350461 at this point.\n\t\tcurvature = 1.73 / sqrt(sqrt(70.0 / 10.0)) + (action.actor->isKneeled()? 0.1 : 0.0);\n\t}\n\n\tTile *targetTile = _save->getTile(action.target);\n\tPosition targetPos = targetVoxel.toTile();\n\t// object blocking - can't throw here\n\tif (action.type == BA_THROW\n\t\t&& targetTile\n\t\t&& targetTile->getMapData(O_OBJECT)\n\t\t&& targetTile->getMapData(O_OBJECT)->getTUCost(MT_WALK) == Pathfinding::INVALID_MOVE_COST\n\t\t&& !(targetTile->isBigWall()\n\t\t&& (targetTile->getMapData(O_OBJECT)->getBigWall()<1\n\t\t|| targetTile->getMapData(O_OBJECT)->getBigWall()>3)))\n\t{\n\t\treturn false;\n\t}\n\t// out of range - can't throw here\n\tif (ProjectileFlyBState::validThrowRange(&action, originVoxel, targetTile, depth) == false)\n\t{\n\t\treturn false;\n\t}\n\n\tstd::vector<Position> trajectory;\n\t// thows should be around 10 tiles far, make one allocation that fit 99% cases with some margin\n\ttrajectory.resize(16*20);\n\t// we try 8 different curvatures to try and reach our goal.\n\tint test = V_OUTOFBOUNDS;\n\twhile (!foundCurve && curvature < 5.0)\n\t{\n\t\ttrajectory.clear();\n\t\ttest = calculateParabolaVoxel(originVoxel, targetVoxel, true, &trajectory, action.actor, curvature, Position(0,0,0));\n\t\t//position that item hit\n\t\tPosition hitPos = (trajectory.back() + Position(0,0,1)).toTile();\n\t\t//position where item will land\n\t\tPosition tilePos = Projectile::getPositionFromEnd(trajectory, Projectile::ItemDropVoxelOffset).toTile();\n\t\tif (forced || (test != V_OUTOFBOUNDS && tilePos == targetPos))\n\t\t{\n\t\t\tif (voxelType)\n\t\t\t{\n\t\t\t\t*voxelType = test;\n\t\t\t}\n\t\t\tfoundCurve = true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tcurvature += 0.5;\n\t\t\tif (test != V_OUTOFBOUNDS && action.actor->getFaction() == FACTION_PLAYER) //obstacle indicator is only for player\n\t\t\t{\n\t\t\t\tTile* hitTile = _save->getTile(hitPos);\n\t\t\t\tif (hitTile)\n\t\t\t\t{\n\t\t\t\t\thitTile->setObstacle(test);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif (curvature >= 5.0)\n\t{\n\t\treturn false;\n\t}\n\tif (curve)\n\t{\n\t\t*curve = curvature;\n\t}\n\n\treturn true;\n}\n\n/**\n * Recalculates FOV of all units in-game.\n */\nvoid TileEngine::recalculateFOV()\n{\n\tfor (auto* bu : *_save->getUnits())\n\t{\n\t\tif (bu->getTile() != 0)\n\t\t{\n\t\t\tcalculateFOV(bu);\n\t\t}\n\t}\n}\n\n/**\n * Returns the direction from origin to target.\n * @param origin The origin point of the action.\n * @param target The target point of the action.\n * @return direction.\n */\nint TileEngine::getDirectionTo(Position origin, Position target) const\n{\n\tdouble ox = target.x - origin.x;\n\tdouble oy = target.y - origin.y;\n\tdouble angle = atan2(ox, -oy);\n\t// divide the pie in 4 angles each at 1/8th before each quarter\n\tdouble pie[4] = {(M_PI_4 * 4.0) - M_PI_4 / 2.0, (M_PI_4 * 3.0) - M_PI_4 / 2.0, (M_PI_4 * 2.0) - M_PI_4 / 2.0, (M_PI_4 * 1.0) - M_PI_4 / 2.0};\n\tint dir = 0;\n\n\tif (angle > pie[0] || angle < -pie[0])\n\t{\n\t\tdir = 4;\n\t}\n\telse if (angle > pie[1])\n\t{\n\t\tdir = 3;\n\t}\n\telse if (angle > pie[2])\n\t{\n\t\tdir = 2;\n\t}\n\telse if (angle > pie[3])\n\t{\n\t\tdir = 1;\n\t}\n\telse if (angle < -pie[1])\n\t{\n\t\tdir = 5;\n\t}\n\telse if (angle < -pie[2])\n\t{\n\t\tdir = 6;\n\t}\n\telse if (angle < -pie[3])\n\t{\n\t\tdir = 7;\n\t}\n\telse if (angle < pie[0])\n\t{\n\t\tdir = 0;\n\t}\n\treturn dir;\n}\n\n/**\n * Calculate arc between two unit directions.\n * e.g. Arc of 7 and 3 is 4. Arc of 0 and 7 is 1.\n * @param directionA Value of 0 to 7\n * @param directionB Value of 0 to 7\n * @return Value in range of 0 - 4\n */\nint TileEngine::getArcDirection(int directionA, int directionB) const\n{\n\treturn std::abs((((directionA - directionB) + 12) % 8) - 4);\n}\n\n/**\n * Gets the origin voxel of a certain action.\n * @param action Battle action.\n * @param tile Pointer to the action tile.\n * @return origin position.\n */\nPosition TileEngine::getOriginVoxel(BattleAction &action, Tile *tile)\n{\n\tconst int dirYshift[8] = {1, 1, 8, 15,15,15,8, 1};\n\tconst int dirXshift[8] = {8, 14,15,15,8, 1, 1, 1};\n\tif (!tile)\n\t{\n\t\ttile = action.actor->getTile();\n\t}\n\n\tPosition origin = tile->getPosition();\n\tTile *tileAbove = _save->getTile(origin + Position(0,0,1));\n\tPosition originVoxel = Position(origin.x*16, origin.y*16, origin.z*24);\n\n\t// take into account soldier height and terrain level if the projectile is launched from a soldier\n\tif (action.actor->getPosition() == origin || action.type != BA_LAUNCH)\n\t{\n\t\t// calculate offset of the starting point of the projectile\n\t\toriginVoxel.z += -tile->getTerrainLevel();\n\n\t\toriginVoxel.z += action.actor->getHeight() + action.actor->getFloatHeight();\n\n\t\tif (action.type == BA_THROW)\n\t\t{\n\t\t\toriginVoxel.z -= 3;\n\t\t}\n\t\telse\n\t\t{\n\t\t\toriginVoxel.z -= 4;\n\t\t}\n\n\t\tif (originVoxel.z >= (origin.z + 1)*24)\n\t\t{\n\t\t\tif (tileAbove && tileAbove->hasNoFloor(0))\n\t\t\t{\n\t\t\t\torigin.z++;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\twhile (originVoxel.z >= (origin.z + 1)*24)\n\t\t\t\t{\n\t\t\t\t\toriginVoxel.z--;\n\t\t\t\t}\n\t\t\t\toriginVoxel.z -= 4;\n\t\t\t}\n\t\t}\n\t\tint direction = getDirectionTo(origin, action.target);\n\n\t\t// Offset for different relativeOrigin values\n\t\tswitch (action.relativeOrigin)\n\t\t{\n\t\tcase BattleActionOrigin::CENTRE:\n\t\t\t// Standard offset.\n\t\t\toriginVoxel.x += dirXshift[direction] * action.actor->getArmor()->getSize();\n\t\t\toriginVoxel.y += dirYshift[direction] * action.actor->getArmor()->getSize();\n\t\t\tbreak;\n\n\t\t\t// 2:1 Weighted average of the standard offset and a rotation, either left or right.\n\t\tcase BattleActionOrigin::LEFT:\n\t\t\toriginVoxel.x += ((2 * dirXshift[direction] + dirXshift[(direction + 7) % 8]) * action.actor->getArmor()->getSize() + 1) / 3;\n\t\t\toriginVoxel.y += ((2 * dirYshift[direction] + dirYshift[(direction + 7) % 8]) * action.actor->getArmor()->getSize() + 1) / 3;\n\t\t\tbreak;\n\n\t\tcase BattleActionOrigin::RIGHT:\n\t\t\toriginVoxel.x += ((2 * dirXshift[direction] + dirXshift[(direction + 1) % 8]) * action.actor->getArmor()->getSize() + 1) / 3;\n\t\t\toriginVoxel.y += ((2 * dirYshift[direction] + dirYshift[(direction + 1) % 8]) * action.actor->getArmor()->getSize() + 1) / 3;\n\t\t\tbreak;\n\t\t};\n\t}\n\telse\n\t{\n\t\t// don't take into account soldier height and terrain level if the projectile is not launched from a soldier(from a waypoint)\n\t\toriginVoxel.x += 8;\n\t\toriginVoxel.y += 8;\n\t\toriginVoxel.z += 16;\n\t}\n\treturn originVoxel;\n}\n\n/**\n * mark a region of the map as \"dangerous\" for a turn.\n * @param pos is the epicenter of the explosion.\n * @param radius how far to spread out.\n * @param unit the unit that is triggering this action.\n */\nvoid TileEngine::setDangerZone(Position pos, int radius, BattleUnit *unit)\n{\n\tTile *tile = _save->getTile(pos);\n\tif (!tile)\n\t{\n\t\treturn;\n\t}\n\t// set the epicenter as dangerous\n\ttile->setDangerous(true);\n\tPosition originVoxel = pos.toVoxel() + Position(8,8,12 + -tile->getTerrainLevel());\n\tPosition targetVoxel;\n\tfor (int x = -radius; x != radius; ++x)\n\t{\n\t\tfor (int y = -radius; y != radius; ++y)\n\t\t{\n\t\t\t// we can skip the epicenter\n\t\t\tif (x != 0 || y != 0)\n\t\t\t{\n\t\t\t\t// make sure we're within the radius\n\t\t\t\tif ((x*x)+(y*y) <= (radius*radius))\n\t\t\t\t{\n\t\t\t\t\ttile = _save->getTile(pos + Position(x,y,0));\n\t\t\t\t\tif (tile)\n\t\t\t\t\t{\n\t\t\t\t\t\ttargetVoxel = ((pos + Position(x,y,0)).toVoxel()) + Position(8,8,12 + -tile->getTerrainLevel());\n\t\t\t\t\t\tstd::vector<Position> trajectory;\n\t\t\t\t\t\t// we'll trace a line here, ignoring all units, to check if the explosion will reach this point\n\t\t\t\t\t\t// granted this won't properly account for explosions tearing through walls, but then we can't really\n\t\t\t\t\t\t// know that kind of information before the fact, so let's have the AI assume that the wall (or tree)\n\t\t\t\t\t\t// is enough to protect them.\n\t\t\t\t\t\tif (calculateLineVoxel(originVoxel, targetVoxel, false, &trajectory, unit, unit) == V_EMPTY)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (trajectory.size() && (trajectory.back().toTile()) == pos + Position(x,y,0))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttile->setDangerous(true);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Checks if a position is a valid place for a unit to be placed\n * @param position Pointer to the position to check\n * @param unit Pointer to the unit\n * @param checkSurrounding Do we need to check the 8 tiles around the selected one? (default false)\n * @param startSurroundingCheckDirection Which direction should we start the check? (default 0 = north)\n * @return true if we found a valid position and stored it in the pointer passed to the function\n */\nbool TileEngine::isPositionValidForUnit(Position &position, BattleUnit *unit, bool checkSurrounding, int startSurroundingCheckDirection)\n{\n\tint unitSize = unit->getArmor()->getSize();\n\tstd::vector<Position > positionsToCheck;\n\tpositionsToCheck.push_back(position);\n\tif (checkSurrounding)\n\t{\n\t\t// Look up the surrounding directions\n\t\tint surroundingTilePositions [8][2] = {\n\t\t\t{0, -1}, // north (-y direction)\n\t\t\t{1, -1}, // northeast\n\t\t\t{1, 0}, // east (+ x direction)\n\t\t\t{1, 1}, // southeast\n\t\t\t{0, 1}, // south (+y direction)\n\t\t\t{-1, 1}, // southwest\n\t\t\t{-1, 0}, // west (-x direction)\n\t\t\t{-1, -1}}; // northwest\n\t\tfor (int i = 0; i < 8; i++)\n\t\t{\n\t\t\tpositionsToCheck.push_back(position + Position(surroundingTilePositions[(startSurroundingCheckDirection + i) % 8][0] * unitSize, surroundingTilePositions[(startSurroundingCheckDirection + i) % 8][1] * unitSize, 0));\n\t\t}\n\t}\n\n\tfor (const auto& pos : positionsToCheck)\n\t{\n\t\tbool passedCheck = true;\n\n\t\tfor (int x = unitSize - 1; x >= 0; x--)\n\t\t{\n\t\t\tfor (int y = unitSize - 1; y >= 0; y--)\n\t\t\t{\n\t\t\t\t// Make sure the location is in bounds and nothing blocks being there\n\t\t\t\tPosition positionToCheck = pos + Position(x, y, 0);\n\t\t\t\tTile* tileToCheck = _save->getTile(positionToCheck);\n\t\t\t\tif (!tileToCheck || (tileToCheck->getUnit() && tileToCheck->getUnit() != unit) ||\n\t\t\t\t\ttileToCheck->getTUCost(O_OBJECT, unit->getMovementType()) == Pathfinding::INVALID_MOVE_COST ||\n\t\t\t\t\t(tileToCheck->getMapData(O_OBJECT) && tileToCheck->getMapData(O_OBJECT)->getBigWall() && tileToCheck->getMapData(O_OBJECT)->getBigWall() <= 3))\n\t\t\t\t{\n\t\t\t\t\tpassedCheck = false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Extra test for large units\n\t\tif (passedCheck && unitSize > 1)\n\t\t{\n\t\t\t_save->getPathfinding()->setUnit(unit); //TODO: remove as was required by `isBlockedDirection`\n\t\t\tfor (int dir = 2; dir <= 4; ++dir)\n\t\t\t{\n\t\t\t\tif (_save->getPathfinding()->isBlockedDirection(unit, _save->getTile(pos), dir))\n\t\t\t\t{\n\t\t\t\t\tpassedCheck = false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (passedCheck)\n\t\t{\n\t\t\tposition = pos;\n\t\t\treturn true;\n\t\t}\n\t}\n\n\treturn false;\n}\n\n/**\n * Update game state after script hook execution. We need check state of units\n * and handle special cases like deaths or unit tranformation.\n * For now we assume that Light and FOV is affected only in small area,\n * this mean we could glitch if multiple units are affected by script logic.\n * @param battleActionAttack Data of action that triggeted script hook.\n * @param pos Postion to update light and Fov, can be invalid if we do not update light\n */\nvoid TileEngine::updateGameStateAfterScript(BattleActionAttack battleActionAttack, Position pos)\n{\n\t_save->getBattleGame()->checkForCasualties(nullptr, battleActionAttack, false, false);\n\n\t_save->reviveUnconsciousUnits(true);\n\n\t_save->getBattleGame()->convertInfected();\n\n\tif (pos != TileEngine::invalid)\n\t{\n\t\t// limit area of the following calls to the Position pos\n\t\tcalculateLighting(LL_ITEMS, pos, 2, true);\n\t\tcalculateFOV(pos, 1, false);\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/TileEngine.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <vector>\n#include \"Position.h\"\n#include \"BattlescapeGame.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"../Mod/MapData.h\"\n\nnamespace OpenXcom\n{\n\nclass SavedBattleGame;\nclass BattleUnit;\nclass BattleItem;\nclass Tile;\nclass RuleSkill;\nstruct BattleAction;\ntemplate<typename Tag, typename DataType> struct AreaSubset;\n\nenum UnitBodyPart : int;\n\n/**\n * Define some part of map\n */\nusing MapSubset = AreaSubset<Position, Sint16>;\nenum BattleActionType : Uint8;\nenum LightLayers : Uint8;\n\n\n/**\n * A utility class that modifies tile properties on a battlescape map. This includes lighting, destruction, smoke, fire, fog of war.\n * Note that this function does not handle any sounds or animations.\n */\nclass TileEngine\n{\npublic:\n\t/// Value representing non-existing position.\n\tstatic constexpr Position invalid = { -1, -1, -1 };\n\n\t/// Size of tile in voxels\n\tstatic constexpr Position voxelTileSize = { Position::TileXY, Position::TileXY, Position::TileZ };\n\t/// Half of size of tile in voxels\n\tstatic constexpr Position voxelTileCenter = { Position::TileXY / 2, Position::TileXY / 2, Position::TileZ / 2 };\n\n\t/// Calculate distance of each step of trajectory.\n\tstatic float trajectoryStepSize(const std::vector<Position>& voxelPath, size_t pos)\n\t{\n\t\tif (pos < voxelPath.size())\n\t\t{\n\t\t\tif (pos > 2)\n\t\t\t{\n\t\t\t\treturn 0.5f * Position::distance(voxelPath[pos], voxelPath[pos - 2]);\n\t\t\t}\n\t\t\telse if (pos)\n\t\t\t{\n\t\t\t\treturn Position::distance(voxelPath[1], voxelPath[0]);\n\t\t\t}\n\t\t}\n\t\treturn 0.0f;\n\t}\n\nprivate:\n\t/**\n\t * Helper class storing cached visibility blockage data.\n\t */\n\tstruct VisibilityBlockCache\n\t{\n\t\tUint32 blockDir;\n\n\t\tUint8 bigWall;\n\n\t\tUint8 height;\n\t};\n\n\t/**\n\t * Helper class storing reaction data.\n\t */\n\tstruct ReactionScore\n\t{\n\t\tBattleUnit *unit;\n\t\tBattleItem *weapon;\n\t\tBattleActionType attackType;\n\t\tdouble reactionScore;\n\t\tdouble reactionReduction;\n\t\tint count;\n\t};\n\n\tSavedBattleGame *_save;\n\tconst std::vector<Uint16> *_voxelData;\n\n\t/// Cache for tile visibility and light propagation.\n\tstd::vector<VisibilityBlockCache> _blockVisibility;\n\t/// Cache dedicated for speedup for light propagation calculation.\n\tstd::vector<Uint32> _lightPropagationTerrainBlocking;\n\t/// Cache for marking tiles that need light updated.\n\tstd::vector<Uint32> _lightPropagationTempNeedUpdate;\n\n\tconst RuleInventory *_inventorySlotGround;\n\tconstexpr static int heightFromCenter[11] = {0,-2,+2,-4,+4,-6,+6,-8,+8,-12,+12};\n\tbool _personalLighting;\n\tTile *_cacheTile;\n\tTile *_cacheTileBelow;\n\tPosition _cacheTilePos;\n\tconst int _maxViewDistance;        // 20 tiles by default\n\tconst int _maxViewDistanceSq;      // 20 * 20\n\tconst int _maxVoxelViewDistance;   // maxViewDistance * 16\n\tconst int _maxDarknessToSeeUnits;  // 9 by default\n\tconst int _maxStaticLightDistance;\n\tconst int _maxDynamicLightDistance;\n\tconst int _enhancedLighting;\n\tPosition _eventVisibilitySectorL, _eventVisibilitySectorR, _eventVisibilityObserverPos;\n\tstd::vector<BattleUnit*> _movingUnitPrev;\n\tBattleUnit* _movingUnit = nullptr;\n\n\t/// Add light source.\n\tvoid addLight(MapSubset gs, Position center, int power, LightLayers layer);\n\t/// Calculate blockage amount.\n\tint blockage(Tile *tile, const TilePart part, ItemDamageType type, int direction = -1, bool checkingFromOrigin = false);\n\n\tbool setupEventVisibilitySector(const Position &observerPos, const Position &eventPos, const int &eventRadius);\n\tinline bool inEventVisibilitySector(const Position &toCheck) const;\n\n\t/// Calculates sun shading of the whole map.\n\tvoid calculateSunShading(MapSubset gs);\n\t/// Recalculates lighting of the battlescape for terrain.\n\tvoid calculateTerrainBackground(MapSubset gs);\n\t/// Recalculates lighting of the battlescape for terrain.\n\tvoid calculateTerrainItems(MapSubset gs);\n\t/// Recalculates lighting of the battlescape for units.\n\tvoid calculateUnitLighting(MapSubset gs);\n\n\t/// Checks validity of a snap shot to this position.\n\tReactionScore determineReactionType(BattleUnit *unit, BattleUnit *target);\n\t/// Creates a vector of units that can spot this unit.\n\tstd::vector<ReactionScore> getSpottingUnits(BattleUnit* unit);\n\t/// Given a vector of spotters, and a unit, picks the spotter with the highest reaction score.\n\tReactionScore *getReactor(std::vector<ReactionScore> &spotters, BattleUnit *unit);\n\t/// Tries to perform a reaction snap shot to this location.\n\tbool tryReaction(ReactionScore *reaction, BattleUnit *target, const BattleAction &originalAction);\npublic:\n\t/// Creates a new TileEngine class.\n\tTileEngine(SavedBattleGame *save, Mod *mod);\n\t/// Cleans up the TileEngine.\n\t~TileEngine();\n\n\t/// Get max distance that fire light can reach.\n\tint getMaxStaticLightDistance() const { return _maxStaticLightDistance; }\n\t/// Get max distance that light can reach.\n\tint getMaxDynamicLightDistance() const { return _maxDynamicLightDistance; }\n\t/// Get flags for enhanced lighting.\n\tint getEnhancedLighting() const { return _enhancedLighting; }\n\t/// Get max view distance.\n\tint getMaxViewDistance() const { return _maxViewDistance; }\n\t/// Get square of max view distance.\n\tint getMaxViewDistanceSq() const { return _maxViewDistanceSq; }\n\t/// Get max view distance in voxel space.\n\tint getMaxVoxelViewDistance() const { return _maxVoxelViewDistance; }\n\t/// Get threshold of darkness for LoS calculation.\n\tint getMaxDarknessToSeeUnits() const { return _maxDarknessToSeeUnits; }\n\n\t/// Calculates visible tiles within the field of view. Supply an eventPosition to do an update limited to a small slice of the view sector.\n\tvoid calculateTilesInFOV(BattleUnit *unit, const Position eventPos = invalid, const int eventRadius = 0);\n\t/// Calculates visible units within the field of view. Supply an eventPosition to do an update limited to a small slice of the view sector.\n\tbool calculateUnitsInFOV(BattleUnit* unit, const Position eventPos = invalid, const int eventRadius = 0);\n\t/// Calculates the field of view from a units view point.\n\tbool calculateFOV(BattleUnit *unit, bool doTileRecalc = true, bool doUnitRecalc = true);\n\t/// Calculates the field of view within range of a certain position.\n\tvoid calculateFOV(Position position, int eventRadius = -1, const bool updateTiles = true, const bool appendToTileVisibility = false);\n\t/// Checks reaction fire.\n\tbool checkReactionFire(BattleUnit *unit, const BattleAction &originalAction);\n\t/// Recalculate all lighting in some area.\n\tvoid calculateLighting(LightLayers layer, Position position = invalid, int eventRadius = 0, bool terrianChanged = false);\n\t/// Handles tile hit.\n\tint hitTile(Tile *tile, int damage, const RuleDamageType* type);\n\t/// Handles experience training.\n\tbool awardExperience(BattleActionAttack attack, BattleUnit *target, bool rangeAtack);\n\t/// Handles unit hit.\n\tbool hitUnit(BattleActionAttack attack, BattleUnit *target, const Position &relative, int damage, const RuleDamageType *type, bool rangeAtack = true);\n\t/// Handles bullet/weapon hits.\n\tvoid hit(BattleActionAttack attack, Position center, int power, const RuleDamageType *type, bool rangeAtack = true, int terrainMeleeTilePart = 0);\n\t/// Handles explosions.\n\tvoid explode(BattleActionAttack attack, Position center, int power, const RuleDamageType *type, int maxRadius, bool rangeAtack = true);\n\t/// Checks if a destroyed tile starts an explosion.\n\tTile *checkForTerrainExplosions();\n\t/// Unit opens door?\n\tint unitOpensDoor(BattleUnit *unit, bool rClick = false, int dir = -1);\n\t/// Closes ufo doors.\n\tint closeUfoDoors();\n\t/// Calculates a line trajectory in tile space.\n\tint calculateLineTile(Position origin, Position target, std::vector<Position> &trajectory);\n\t/// Calculates a line trajectory in voxel space.\n\tVoxelType calculateLineVoxel(Position origin, Position target, bool storeTrajectory, std::vector<Position> *trajectory, BattleUnit *excludeUnit, BattleUnit *excludeAllBut = 0, bool onlyVisible = false);\n\t/// Calculates a parabola trajectory.\n\tint calculateParabolaVoxel(Position origin, Position target, bool storeTrajectory, std::vector<Position> *trajectory, BattleUnit *excludeUnit, double curvature, const Position delta);\n\t/// Gets the origin voxel of a unit's eyesight.\n\tPosition getSightOriginVoxel(BattleUnit *currentUnit);\n\t/// Checks visibility of a unit on this tile.\n\tbool visible(BattleUnit *currentUnit, Tile *tile);\n\t/// Checks visibility of a tile.\n\tbool isTileInLOS(BattleAction *action, Tile *tile, bool drawing);\n\t/// Turn XCom soldier's personal lighting on or off.\n\tvoid togglePersonalLighting();\n\t/// Checks the horizontal blockage of a tile.\n\tint horizontalBlockage(Tile *startTile, Tile *endTile, ItemDamageType type, bool skipObject = false);\n\t/// Checks the vertical blockage of a tile.\n\tint verticalBlockage(Tile *startTile, Tile *endTile, ItemDamageType type, bool skipObject = false);\n\n\t/// Calculate success rate of psi attack.\n\tint psiAttackCalculate(BattleActionAttack::ReadOnly attack, const BattleUnit *victim);\n\t/// Attempts a panic or mind control action.\n\tbool psiAttack(BattleActionAttack attack, BattleUnit *victim);\n\t/// Calculate success rate of melee attack action.\n\tint meleeAttackCalculate(BattleActionAttack::ReadOnly attack, const BattleUnit *victim);\n\t/// Attempts a melee attack action.\n\tbool meleeAttack(BattleActionAttack attack, BattleUnit *victim, int terrainMeleeTilePart = 0);\n\n\t/// Remove the medikit from the game if consumable and empty.\n\tvoid medikitRemoveIfEmpty(BattleAction *action);\n\t/// Try using medikit heal ability.\n\tbool medikitUse(BattleAction *action, BattleUnit *target, BattleMediKitAction medikitAction, UnitBodyPart bodyPart);\n\t/// Try using a skill.\n\tbool skillUse(BattleAction *action, const RuleSkill *skill);\n\t/// Try to conceal a unit.\n\tbool tryConcealUnit(BattleUnit* unit);\n\t/// Applies gravity to anything that occupy this tile.\n\tTile *applyGravity(Tile *t);\n\n\t/// Drop item on ground.\n\tvoid itemDrop(Tile *t, BattleItem *item, bool updateLight);\n\t/// Drop all unit items on ground.\n\tvoid itemDropInventory(Tile *t, BattleUnit *unit, bool unprimeItems = false, bool deleteFixedItems = false);\n\t/// Move item to other place in inventory or ground.\n\tvoid itemMoveInventory(Tile *t, BattleUnit *unit, BattleItem *item, const RuleInventory *slot, int x, int y);\n\n\t/// Add moving unit.\n\tvoid addMovingUnit(BattleUnit* unit);\n\t/// Add moving unit.\n\tvoid removeMovingUnit(BattleUnit* unit);\n\t/// Get current moving unit.\n\tBattleUnit* getMovingUnit();\n\n\t/// Returns melee validity between two units.\n\tbool validMeleeRange(BattleUnit *attacker, BattleUnit *target, int dir);\n\t/// Returns validity of a melee attack from a given position.\n\tbool validMeleeRange(Position pos, int direction, BattleUnit *attacker, BattleUnit *target, Position *dest, bool preferEnemy = true);\n\tbool validTerrainMeleeRange(BattleAction* action);\n\t/// Gets the AI to look through a window.\n\tint faceWindow(Position position);\n\t/// Checks a unit's % exposure on a tile.\n\tint checkVoxelExposure(Position *originVoxel, Tile *tile, BattleUnit *excludeUnit, BattleUnit *excludeAllBut);\n\t/// Checks validity for targetting a unit.\n\tbool canTargetUnit(Position *originVoxel, Tile *tile, Position *scanVoxel, BattleUnit *excludeUnit, bool rememberObstacles, BattleUnit *potentialUnit = 0);\n\t/// Check validity for targetting a tile.\n\tbool canTargetTile(Position *originVoxel, Tile *tile, int part, Position *scanVoxel, BattleUnit *excludeUnit, bool rememberObstacles);\n\t/// Calculates the z voxel for shadows.\n\tint castedShade(Position voxel);\n\t/// Checks the visibility of a given voxel.\n\tbool isVoxelVisible(Position voxel);\n\t/// Checks what type of voxel occupies this space.\n\tVoxelType voxelCheck(Position voxel, BattleUnit *excludeUnit, bool excludeAllUnits = false, bool onlyVisible = false, BattleUnit *excludeAllBut = 0);\n\t/// Flushes cache of voxel check\n\tvoid voxelCheckFlush();\n\t/// Blows this tile up.\n\tbool detonate(Tile* tile, int power);\n\t/// Validates a throwing action.\n\tbool validateThrow(BattleAction &action, Position originVoxel, Position targetVoxel, int depth, double *curve = 0, int *voxelType = 0, bool forced = false);\n\t/// Opens any doors this door is connected to.\n\tstd::pair<int, Position> checkAdjacentDoors(Position pos, TilePart part);\n\t/// Recalculates FOV of all units in-game.\n\tvoid recalculateFOV();\n\t/// Get direction to a certain point\n\tint getDirectionTo(Position origin, Position target) const;\n\t/// Get arc between two direction.\n\tint getArcDirection(int directionA, int directionB) const;\n\t/// determine the origin voxel of a given action.\n\tPosition getOriginVoxel(BattleAction &action, Tile *tile);\n\t/// mark a region of the map as \"dangerous\" for a turn.\n\tvoid setDangerZone(Position pos, int radius, BattleUnit *unit);\n\t/// Checks if a position is valid for a unit, used for spawning and forced movement.\n\tbool isPositionValidForUnit(Position &position, BattleUnit *unit, bool checkSurrounding = false, int startSurroundingCheckDirection = 0);\n\t/// Update game state after script hook execution.\n\tvoid updateGameStateAfterScript(BattleActionAttack battleActionAttack, Position pos);\n\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/TurnDiaryState.cpp",
    "content": "/*\n * Copyright 2010-2019 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"TurnDiaryState.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Savegame/HitLog.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"../Savegame/SavedGame.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Turn Diary window.\n */\nTurnDiaryState::TurnDiaryState(const HitLog *hitLog)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 216, 160, 52, 20, POPUP_BOTH);\n\t_txtTitle = new Text(206, 17, 57, 32);\n\t_btnCancel = new TextButton(140, 16, 90, 156);\n\t_lstTurnDiary = new TextList(180, 96, 65, 52);\n\n\t// Set palette\n\t_game->getSavedGame()->getSavedBattle()->setPaletteByDepth(this);\n\n\tadd(_window, \"messageWindowBorder\", \"battlescape\");\n\tadd(_txtTitle, \"messageWindows\", \"battlescape\");\n\tadd(_btnCancel, \"messageWindowButtons\", \"battlescape\");\n\tadd(_lstTurnDiary, \"optionLists\", \"battlescape\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\t_window->setHighContrast(true);\n\t_window->setBackground(_game->getMod()->getSurface(\"TAC00.SCR\"));\n\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setBig();\n\t_txtTitle->setHighContrast(true);\n\t_txtTitle->setText(tr(\"STR_HIT_LOG\"));\n\n\t_btnCancel->setText(tr(\"STR_CANCEL_UC\"));\n\t_btnCancel->setHighContrast(true);\n\t_btnCancel->onMouseClick((ActionHandler)&TurnDiaryState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&TurnDiaryState::btnCancelClick, Options::keyCancel);\n\n\t_lstTurnDiary->setColumns(1, 172);\n\t_lstTurnDiary->setSelectable(true);\n\t_lstTurnDiary->setBackground(_window);\n\t_lstTurnDiary->setMargin(8);\n\t_lstTurnDiary->setAlign(ALIGN_CENTER);\n\t_lstTurnDiary->setHighContrast(true);\n\t_lstTurnDiary->setWordWrap(true);\n\n\t// in reverse order\n\t_lstTurnDiary->addRow(1, hitLog->getHitLogText(true).c_str());\n\tsize_t row = 1;\n\tfor (std::vector<std::string>::const_reverse_iterator i = hitLog->getTurnDiary().rbegin(); i != hitLog->getTurnDiary().rend(); ++i)\n\t{\n\t\t_lstTurnDiary->addRow(1, (*i).c_str());\n\t\tif (row % 2 != 0)\n\t\t{\n\t\t\t_lstTurnDiary->setRowColor(row, _lstTurnDiary->getSecondaryColor());\n\t\t}\n\t\t++row;\n\t}\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid TurnDiaryState::btnCancelClick(Action *)\n{\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/TurnDiaryState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2019 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass Window;\nclass Text;\nclass TextButton;\nclass TextList;\nclass HitLog;\n\n/**\n * Turn Diary window that displays the hit log history (for the current turn).\n */\nclass TurnDiaryState : public State\n{\nprivate:\n\tWindow *_window;\n\tText *_txtTitle;\n\tTextButton *_btnCancel;\n\tTextList *_lstTurnDiary;\npublic:\n\t/// Creates the Turn Diary state.\n\tTurnDiaryState(const HitLog *hitLog);\n\t/// Cleans up the Turn Diary state.\n\t~TurnDiaryState() = default;\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/UnitDieBState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"UnitDieBState.h\"\n#include \"TileEngine.h\"\n#include \"BattlescapeState.h\"\n#include \"Map.h\"\n#include \"../Engine/Game.h\"\n#include \"../Savegame/BattleItem.h\"\n#include \"../Savegame/BattleUnit.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"../Savegame/Tile.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/Sound.h\"\n#include \"../Engine/RNG.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Language.h\"\n#include \"../Mod/Armor.h\"\n#include \"InfoboxOKState.h\"\n#include \"InfoboxState.h\"\n#include \"../Savegame/Node.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Sets up an UnitDieBState.\n * @param parent Pointer to the Battlescape.\n * @param unit Dying unit.\n * @param damageType Type of damage that caused the death.\n * @param noSound Whether to disable the death sound.\n */\nUnitDieBState::UnitDieBState(BattlescapeGame *parent, BattleUnit *unit, const RuleDamageType* damageType, bool noSound) : BattleState(parent),\n\t_unit(unit), _damageType(damageType), _noSound(noSound), _extraFrame(0), _overKill(unit->getOverKillDamage())\n{\n\t// don't show the \"fall to death\" animation when a unit is blasted with explosives or he is already unconscious\n\tif (!_damageType->isDirect() || _unit->getStatus() == STATUS_UNCONSCIOUS)\n\t{\n\n\t\t/********************************************************\n\t\tProclamation from Lord Xenu:\n\n\t\tany unit that is going to skip its death pirouette\n\t\tMUST have its direction set to 3 first.\n\n\t\tFailure to comply is treason, and treason is punishable\n\t\tby death. (after being correctly oriented)\n\n\t\t********************************************************/\n\t\t_unit->setDirection(3);\n\n\n\t\t_unit->instaFalling();\n\t\tif (_parent->getSave()->isBeforeGame())\n\t\t{\n\t\t\tconvertUnitToCorpse();\n\t\t\t_extraFrame = 3; // shortcut to popState()\n\t\t}\n\t}\n\telse\n\t{\n\t\tif (_unit->getFaction() == FACTION_PLAYER)\n\t\t{\n\t\t\t_parent->getMap()->setUnitDying(true);\n\t\t}\n\t\t_parent->setStateInterval(BattlescapeState::DEFAULT_ANIM_SPEED);\n\t\tif (_unit->getDirection() != 3)\n\t\t{\n\t\t\t_parent->setStateInterval(BattlescapeState::DEFAULT_ANIM_SPEED / 3);\n\t\t}\n\t}\n\n\t_unit->clearVisibleTiles();\n\t_unit->clearVisibleUnits();\n\t_unit->freePatrolTarget();\n\n\tif (!_parent->getSave()->isBeforeGame() && _unit->getFaction() == FACTION_HOSTILE)\n\t{\n\t\tstd::vector<Node *> *nodes = _parent->getSave()->getNodes();\n\t\tif (!nodes) return; // this better not happen.\n\n\t\tfor (auto* node : *nodes)\n\t\t{\n\t\t\tif (!node->isDummy() && Position::distanceSq(node->getPosition(), _unit->getPosition()) < 4)\n\t\t\t{\n\t\t\t\tnode->setType(node->getType() | Node::TYPE_DANGEROUS);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Deletes the UnitDieBState.\n */\nUnitDieBState::~UnitDieBState()\n{\n\n}\n\nvoid UnitDieBState::init()\n{\n\t// check for presence of battlestate to ensure that we're not pre-battle\n\t// check for the unit's tile to make sure we're not trying to kill a dead guy\n\tif (_parent->getSave()->getBattleState() && !_unit->getTile())\n\t{\n\t\tif (_unit->getOriginalFaction() == FACTION_PLAYER)\n\t\t{\n\t\t\tif (_unit->getNotificationShown() == 2)\n\t\t\t{\n\t\t\t\t// skip completely\n\t\t\t\t_parent->popState();\n\t\t\t}\n\t\t\telse if (_unit->getNotificationShown() == 1)\n\t\t\t{\n\t\t\t\t// can't skip this (there could still be a death notification), but at least speed it up\n\t\t\t\t_parent->setStateInterval(1);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_parent->popState();\n\t\t}\n\t}\n}\n\n/**\n * Runs state functionality every cycle.\n * Progresses the death, displays any messages, checks if the mission is over, ...\n */\nvoid UnitDieBState::think()\n{\n\tif (_extraFrame == 3)\n\t{\n\t\t_parent->popState();\n\t\treturn;\n\t}\n\tif (_unit->getDirection() != 3 && _damageType->isDirect())\n\t{\n\t\tint dir = _unit->getDirection() + 1;\n\t\tif (dir == 8)\n\t\t{\n\t\t\tdir = 0;\n\t\t}\n\t\t_unit->lookAt(dir);\n\t\t_unit->turn();\n\t\tif (dir == 3)\n\t\t{\n\t\t\t_parent->setStateInterval(BattlescapeState::DEFAULT_ANIM_SPEED);\n\t\t}\n\t}\n\telse if (_unit->getStatus() == STATUS_COLLAPSING)\n\t{\n\t\t_unit->keepFalling();\n\t}\n\telse if (!_unit->isOut())\n\t{\n\t\t_unit->startFalling();\n\n\t\tif (!_noSound)\n\t\t{\n\t\t\tplayDeathSound();\n\t\t}\n\t\tif (_unit->getRespawn())\n\t\t{\n\t\t\twhile (_unit->getStatus() == STATUS_COLLAPSING)\n\t\t\t{\n\t\t\t\t_unit->keepFalling();\n\t\t\t}\n\t\t}\n\t}\n\tif (_extraFrame == 2)\n\t{\n\t\t_parent->getMap()->setUnitDying(false);\n\t\t_parent->getTileEngine()->calculateLighting(LL_ITEMS, _unit->getPosition(), _unit->getArmor()->getSize());\n\t\t_parent->getTileEngine()->calculateFOV(_unit->getPosition(), _unit->getArmor()->getSize(), false); //Update FOV for anyone that can see me\n\t\t_parent->popState();\n\t\tif (_unit->getOriginalFaction() == FACTION_PLAYER)\n\t\t{\n\t\t\tGame *game = _parent->getSave()->getBattleState()->getGame();\n\t\t\tif (_unit->getStatus() == STATUS_DEAD)\n\t\t\t{\n\t\t\t\tif (_damageType->ResistType == DT_NONE && !_unit->getSpawnUnit())\n\t\t\t\t{\n\t\t\t\t\t// Note: yes, this condition is necessary, init() will filter out most duplicates, but not everything\n\t\t\t\t\tif (_unit->getNotificationShown() < 2)\n\t\t\t\t\t{\n\t\t\t\t\t\t_unit->setNotificationShown(2);\n\t\t\t\t\t\tgame->pushState(new InfoboxOKState(game->getLanguage()->getString(\"STR_HAS_DIED_FROM_A_FATAL_WOUND\", _unit->getGender()).arg(_unit->getName(game->getLanguage()))));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (Options::battleNotifyDeath && _unit->getGeoscapeSoldier() != 0)\n\t\t\t\t{\n\t\t\t\t\t// Note: yes, this condition is necessary, init() will filter out most duplicates, but not everything\n\t\t\t\t\tif (_unit->getNotificationShown() < 2)\n\t\t\t\t\t{\n\t\t\t\t\t\t_unit->setNotificationShown(2);\n\t\t\t\t\t\tgame->pushState(new InfoboxState(game->getLanguage()->getString(\"STR_HAS_BEEN_KILLED\", _unit->getGender()).arg(_unit->getName(game->getLanguage()))));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (_unit->indicatorsAreEnabled())\n\t\t\t{\n\t\t\t\tif (_unit->getNotificationShown() < 1)\n\t\t\t\t{\n\t\t\t\t\t_unit->setNotificationShown(1);\n\t\t\t\t\tgame->pushState(new InfoboxOKState(game->getLanguage()->getString(\"STR_HAS_BECOME_UNCONSCIOUS\", _unit->getGender()).arg(_unit->getName(game->getLanguage()))));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// if all units from either faction are killed - auto-end the mission.\n\t\tif (_parent->getSave()->getSide() == FACTION_PLAYER)\n\t\t{\n\t\t\t_parent->autoEndBattle();\n\t\t}\n\t}\n\telse if (_extraFrame == 1)\n\t{\n\t\t_extraFrame++;\n\t}\n\telse if (_unit->isOut())\n\t{\n\t\t_extraFrame = 1;\n\t\tif (!_noSound && !_damageType->isDirect() && _unit->getStatus() != STATUS_UNCONSCIOUS)\n\t\t{\n\t\t\tplayDeathSound();\n\t\t}\n\t\tif (_unit->getStatus() == STATUS_UNCONSCIOUS && !_unit->getCapturable())\n\t\t{\n\t\t\t_unit->instaKill();\n\t\t}\n\t\t_unit->resetTurnsSince();\n\t\tif (_unit->getSpawnUnit() && !_overKill)\n\t\t{\n\t\t\tif (!_unit->getAlreadyRespawned())\n\t\t\t{\n\t\t\t\t// converts the dead zombie to a chryssalid\n\t\t\t\t_parent->convertUnit(_unit);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tconvertUnitToCorpse();\n\t\t}\n\n\t\t_parent->getSave()->clearUnitSelection(_unit);\n\t}\n\n}\n\n/**\n * Unit falling cannot be cancelled.\n */\nvoid UnitDieBState::cancel()\n{\n}\n\n/**\n * Converts unit to a corpse (item).\n */\nvoid UnitDieBState::convertUnitToCorpse()\n{\n\tPosition lastPosition = _unit->getPosition();\n\tint size = _unit->getArmor()->getSize();\n\tbool dropItems = (_unit->hasInventory() &&\n\t\t(!Options::weaponSelfDestruction ||\n\t\t(_unit->getOriginalFaction() != FACTION_HOSTILE || _unit->getStatus() == STATUS_UNCONSCIOUS)));\n\n\tif (!_noSound)\n\t{\n\t\t_parent->getSave()->getBattleState()->resetUiButton();\n\t}\n\t// remove the unconscious body item corresponding to this unit, and if it was being carried, keep track of what slot it was in\n\tif (lastPosition != TileEngine::invalid)\n\t{\n\t\t_parent->getSave()->removeUnconsciousBodyItem(_unit);\n\t}\n\n\t// move inventory from unit to the ground\n\tif (dropItems && _unit->getTile())\n\t{\n\t\t_parent->getTileEngine()->itemDropInventory(_unit->getTile(), _unit);\n\t}\n\n\t// remove unit-tile link\n\t_unit->setTile(nullptr, _parent->getSave());\n\n\tif (lastPosition == TileEngine::invalid) // we're being carried\n\t{\n\t\tif (_overKill)\n\t\t{\n\t\t\t_parent->getSave()->removeUnconsciousBodyItem(_unit);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// replace the unconscious body item with a corpse in the carrying unit's inventory\n\t\t\tfor (auto* bi : *_parent->getSave()->getItems())\n\t\t\t{\n\t\t\t\tif (bi->getUnit() == _unit)\n\t\t\t\t{\n\t\t\t\t\tauto* corpseRules = _unit->getArmor()->getCorpseBattlescape()[0]; // we're in an inventory, so we must be a 1x1 unit\n\t\t\t\t\tbi->convertToCorpse(corpseRules);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\tif (!_overKill)\n\t\t{\n\t\t\tint i = size * size - 1;\n\t\t\tfor (int y = size - 1; y >= 0; --y)\n\t\t\t{\n\t\t\t\tfor (int x = size - 1; x >= 0; --x)\n\t\t\t\t{\n\t\t\t\t\tBattleItem *corpse = _parent->getSave()->createItemForTile(_unit->getArmor()->getCorpseBattlescape()[i], nullptr, _unit);\n\t\t\t\t\t_parent->dropItem(lastPosition + Position(x,y,0), corpse, false);\n\t\t\t\t\t--i;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_parent->getSave()->getTileEngine()->applyGravity(_parent->getSave()->getTile(lastPosition));\n\t\t}\n\t}\n}\n\n/**\n * Plays the death sound.\n */\nvoid UnitDieBState::playDeathSound()\n{\n\tconst std::vector<int> &sounds = _unit->getDeathSounds();\n\tif (!sounds.empty())\n\t{\n\t\tint i = sounds[RNG::generate(0, sounds.size() - 1)];\n\t\tif (i >= 0)\n\t\t{\n\t\t\t_parent->getMod()->getSoundByDepth(_parent->getDepth(), i)->play(-1, _parent->getMap()->getSoundAngle(_unit->getPosition()));\n\t\t}\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/UnitDieBState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"BattleState.h\"\n#include \"../Mod/RuleItem.h\"\n\nnamespace OpenXcom\n{\n\nclass BattlescapeGame;\nclass BattleUnit;\n\n/* Refactoring tip : UnitDieBState */\n/**\n * State for dying units.\n */\nclass UnitDieBState : public BattleState\n{\nprivate:\n\tBattleUnit *_unit;\n\tconst RuleDamageType *_damageType;\n\tbool _noSound;\n\tint _extraFrame;\n\tbool _overKill;\npublic:\n\t/// Creates a new UnitDieBState class\n\tUnitDieBState(BattlescapeGame *parent, BattleUnit *unit, const RuleDamageType *damageType, bool noSound);\n\t/// Cleans up the UnitDieBState.\n\t~UnitDieBState();\n\t/// Initializes the state.\n\tvoid init() override;\n\t/// Handles a cancels request.\n\tvoid cancel() override;\n\t/// Runs state functionality every cycle.\n\tvoid think() override;\n\t/// Converts a unit to a corpse.\n\tvoid convertUnitToCorpse();\n\t/// Plays the death sound.\n\tvoid playDeathSound();\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/UnitFallBState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include <algorithm>\n#include \"UnitFallBState.h\"\n#include <algorithm>\n#include \"TileEngine.h\"\n#include \"Pathfinding.h\"\n#include \"../Savegame/BattleUnit.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"../Savegame/Tile.h\"\n#include \"../Engine/Options.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Mod/Mod.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Sets up an UnitFallBState.\n * @param parent Pointer to the Battlescape.\n */\nUnitFallBState::UnitFallBState(BattlescapeGame *parent) : BattleState(parent), _terrain(0)\n{\n\n}\n\n/**\n * Deletes the UnitWalkBState.\n */\nUnitFallBState::~UnitFallBState()\n{\n\n}\n\n/**\n * Initializes the state.\n */\nvoid UnitFallBState::init()\n{\n\t_terrain = _parent->getTileEngine();\n\tif (_parent->getSave()->getSide() == FACTION_PLAYER)\n\t\t_parent->setStateInterval(Options::battleXcomSpeed);\n\telse\n\t\t_parent->setStateInterval(Options::battleAlienSpeed);\n\n}\n\n/**\n * Runs state functionality every cycle.\n * Progresses the fall, updates the battlescape, ...\n */\nvoid UnitFallBState::think()\n{\n\tfor (auto unitIt = _parent->getSave()->getFallingUnits()->begin(); unitIt != _parent->getSave()->getFallingUnits()->end();)\n\t{\n\t\tBattleUnit* unit = (*unitIt);\n\n\t\t// I ain't got time to panic\n\t\tif (unit->getStatus() == STATUS_TURNING || unit->getStatus() == STATUS_PANICKING || unit->getStatus() == STATUS_BERSERK)\n\t\t{\n\t\t\tunit->abortTurn();\n\t\t}\n\t\tbool falling = true;\n\t\tint size = unit->getArmor()->getSize() - 1;\n\t\tif (unit->isOutThresholdExceed())\n\t\t{\n\t\t\tunitIt = _parent->getSave()->getFallingUnits()->erase(unitIt);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (unit->getStatus() == STATUS_WALKING || unit->getStatus() == STATUS_FLYING)\n\t\t{\n\t\t\tunit->keepWalking(_parent->getSave(), true); // advances the phase\n\n\t\t\t++unitIt;\n\t\t\tcontinue;\n\t\t}\n\n\t\tfalling = unit->haveNoFloorBelow()\n\t\t\t&& unit->getPosition().z != 0\n\t\t\t&& unit->getMovementType() != MT_FLY\n\t\t\t&& unit->getWalkingPhase() == 0;\n\n\t\tif (falling)\n\t\t{\n\t\t\t// Tile(s) unit is falling into.\n\t\t\tfor (int x = size; x >= 0; --x)\n\t\t\t{\n\t\t\t\tfor (int y = size; y >= 0; --y)\n\t\t\t\t{\n\t\t\t\t\tTile *tileTarget = _parent->getSave()->getTile(unit->getPosition() + Position(x,y,-1));\n\t\t\t\t\ttilesToFallInto.push_back(tileTarget);\n\t\t\t\t}\n\t\t\t}\n\t\t\tstd::list<BattleUnit*> *fallingUnits = _parent->getSave()->getFallingUnits();\n\t\t\t// Check each tile for units that need moving out of the way.\n\t\t\tfor (auto* tile : tilesToFallInto)\n\t\t\t{\n\t\t\t\tBattleUnit *unitBelow = tile->getUnit();\n\t\t\t\tif (unitBelow\n\t\t\t\t\t&& !(std::find(fallingUnits->begin(), fallingUnits->end(), unitBelow) != fallingUnits->end())  // ignore falling units (including self)\n\t\t\t\t\t&& !(std::find(unitsToMove.begin(), unitsToMove.end(), unitBelow) != unitsToMove.end()))       // ignore already added units\n\t\t\t\t{\n\t\t\t\t\tunitsToMove.push_back(unitBelow);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// we are just standing around, we are done falling.\n\t\tif (unit->getStatus() == STATUS_STANDING)\n\t\t{\n\t\t\tif (falling)\n\t\t\t{\n\t\t\t\tPosition destination = unit->getPosition() + Position(0,0,-1);\n\t\t\t\tunit->startWalking(Pathfinding::DIR_DOWN, destination, _parent->getSave());\n\t\t\t\t++unit;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// if the unit burns floor tiles, burn floor tiles\n\t\t\t\tif (unit->getSpecialAbility() == SPECAB_BURNFLOOR || unit->getSpecialAbility() == SPECAB_BURN_AND_EXPLODE)\n\t\t\t\t{\n\t\t\t\t\tunit->getTile()->ignite(1);\n\t\t\t\t\tPosition groundVoxel = (unit->getPosition().toVoxel()) + Position(8,8,-(unit->getTile()->getTerrainLevel()));\n\t\t\t\t\t_parent->getTileEngine()->hit(BattleActionAttack{ BA_NONE, unit, }, groundVoxel, unit->getBaseStats()->strength, _parent->getMod()->getDamageType(DT_IN), false);\n\n\t\t\t\t\tif (unit->getStatus() != STATUS_STANDING) // ie: we burned a hole in the floor and fell through it\n\t\t\t\t\t{\n\t\t\t\t\t\t_parent->getPathfinding()->abortPath();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// move our personal lighting with us\n\t\t\t\tint change = _parent->checkForProximityGrenades(unit);\n\t\t\t\t_terrain->calculateLighting(change ? LL_ITEMS : LL_UNITS, unit->getPosition(), 2);\n\t\t\t\t_terrain->calculateFOV(unit->getPosition(), 2, false); //update everyone else to see this unit, as well as all this unit's visible units.\n\t\t\t\t_terrain->calculateFOV(unit, true, false); //update tiles\n\t\t\t\tif (unit->getStatus() == STATUS_STANDING)\n\t\t\t\t{\n\t\t\t\t\tBattleAction fall;\n\t\t\t\t\tfall.type = BA_WALK;\n\t\t\t\t\tfall.actor = unit;\n\t\t\t\t\tif (_parent->getTileEngine()->checkReactionFire(unit, fall))\n\t\t\t\t\t\t_parent->getPathfinding()->abortPath();\n\t\t\t\t\tunitIt = _parent->getSave()->getFallingUnits()->erase(unitIt);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t++unitIt;\n\t\t}\n\t}\n\n\t// Find somewhere to move the unit(s) In danger of being squashed.\n\tif (!unitsToMove.empty())\n\t{\n\t\tstd::vector<Tile*> escapeTiles;\n\t\tfor (auto ubIt = unitsToMove.begin(); ubIt < unitsToMove.end(); )\n\t\t{\n\t\t\tBattleUnit *unitBelow = (*ubIt);\n\t\t\tbool escapeFound = false;\n\n\t\t\t// We need to move all sections of the unit out of the way.\n\t\t\tconst int bodyTotalSize = unitBelow->getArmor()->getTotalSize();\n\t\t\tconst Position bodyOffsets[4] =\n\t\t\t{\n\t\t\t\t{ 0, 0, 0 },\n\t\t\t\t{ 1, 0, 0 },\n\t\t\t\t{ 0, 1, 0 },\n\t\t\t\t{ 1, 1, 0 },\n\t\t\t};\n\n\t\t\t// Check in each compass direction.\n\t\t\tfor (int dir = 0; dir < Pathfinding::DIR_UP && !escapeFound; dir++)\n\t\t\t{\n\t\t\t\tPosition offset;\n\t\t\t\tPathfinding::directionToVector(dir, &offset);\n\n\t\t\t\t_parent->getSave()->getPathfinding()->setUnit(unitBelow); //TODO: remove as was done by `getTUCost`\n\t\t\t\tPathfindingStep r = _parent->getSave()->getPathfinding()->getTUCost(unitBelow->getPosition(), dir, unitBelow, 0, BAM_NORMAL);\n\t\t\t\tif (r.cost.time == Pathfinding::INVALID_MOVE_COST)\n\t\t\t\t{\n\t\t\t\t\t// can't move this way, try another direction\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tfor (auto bs = 0; bs < bodyTotalSize; )\n\t\t\t\t{\n\t\t\t\t\tPosition originalPosition = unitBelow->getPosition() + bodyOffsets[bs];\n\t\t\t\t\tPosition endPosition = originalPosition + offset;\n\n\t\t\t\t\tTile *t = _parent->getSave()->getTile(endPosition);\n\t\t\t\t\tif (t == nullptr)\n\t\t\t\t\t{\n\t\t\t\t\t\t// Try next direction.\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tbool aboutToBeOccupiedFromAbove = std::find(tilesToFallInto.begin(), tilesToFallInto.end(), t) != tilesToFallInto.end();\n\t\t\t\t\tbool alreadyTaken = std::find(escapeTiles.begin(), escapeTiles.end(), t) != escapeTiles.end();\n\t\t\t\t\tbool alreadyOccupied = t->getUnit() && (t->getUnit() != unitBelow);\n\t\t\t\t\tbool hasFloor = !t->hasNoFloor(_parent->getSave());\n\t\t\t\t\tbool unitCanFly = unitBelow->getMovementType() == MT_FLY;\n\n\t\t\t\t\tbool canMoveToTile = !alreadyOccupied && !alreadyTaken && !aboutToBeOccupiedFromAbove && (hasFloor || unitCanFly);\n\t\t\t\t\tif (canMoveToTile)\n\t\t\t\t\t{\n\t\t\t\t\t\t// Check next section of the unit.\n\t\t\t\t\t\t++bs;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// Try next direction.\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\t// If all sections of the fallen onto unit can be moved, then we move it.\n\t\t\t\t\tif (bs == bodyTotalSize)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (_parent->getSave()->addFallingUnit(unitBelow))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tescapeFound = true;\n\t\t\t\t\t\t\t// Now ensure no other unit escapes to here too.\n\t\t\t\t\t\t\tfor (int x = unitBelow->getArmor()->getSize() - 1; x >= 0; --x)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tfor (int y = unitBelow->getArmor()->getSize() - 1; y >= 0; --y)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tTile *et = _parent->getSave()->getTile(t->getPosition() + Position(x,y,0));\n\t\t\t\t\t\t\t\t\tescapeTiles.push_back(et);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tunitBelow->startWalking(dir, unitBelow->getPosition() + offset, _parent->getSave());\n\t\t\t\t\t\t\tubIt = unitsToMove.erase(ubIt);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!escapeFound)\n\t\t\t{\n\t\t\t\t// STOMP THAT GOOMBA!\n\t\t\t\tunitBelow->knockOut(_parent);\n\t\t\t\tubIt = unitsToMove.erase(ubIt);\n\t\t\t}\n\t\t}\n\t\t_parent->checkForCasualties(nullptr, BattleActionAttack{ BA_NONE, nullptr });\n\t}\n\n\tif (_parent->getSave()->getFallingUnits()->empty())\n\t{\n\t\ttilesToFallInto.clear();\n\t\tunitsToMove.clear();\n\t\t_parent->popState();\n\t\treturn;\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/UnitFallBState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"BattleState.h\"\n\nnamespace OpenXcom\n{\n\nclass BattlescapeGame;\nclass TileEngine;\nclass Tile;\nclass BattleUnit;\n\n/**\n * State for falling units.\n */\nclass UnitFallBState : public BattleState\n{\nprivate:\n\tTileEngine *_terrain;\n\tstd::vector<Tile*> tilesToFallInto;\n\tstd::vector<BattleUnit*> unitsToMove;\npublic:\n\t/// Creates a new UnitWalkBState class\n\tUnitFallBState(BattlescapeGame *parent);\n\t/// Cleans up the UnitWalkBState.\n\t~UnitFallBState();\n\t/// Initializes the state.\n\tvoid init() override;\n\t/// Runs state functionality every cycle. Returns when finished.\n\tvoid think() override;\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/UnitInfoState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"UnitInfoState.h\"\n#include <sstream>\n#include \"../Savegame/BattleUnit.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Screen.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/Bar.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Engine/InteractiveSurface.h\"\n#include \"../Mod/Unit.h\"\n#include \"../Engine/Options.h\"\n#include \"BattlescapeGame.h\"\n#include \"BattlescapeState.h\"\n#include \"../Mod/RuleInterface.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Unit Info screen.\n * @param game Pointer to the core game.\n * @param unit Pointer to the selected unit.\n * @param parent Pointer to parent Battlescape.\n * @param fromInventory Is player coming from the inventory?\n * @param mindProbe Is player using a Mind Probe?\n */\nUnitInfoState::UnitInfoState(BattleUnit *unit, BattlescapeState *parent, bool fromInventory, bool mindProbe) : _unit(unit), _parent(parent), _fromInventory(fromInventory), _mindProbe(mindProbe)\n{\n\tif (Options::maximizeInfoScreens)\n\t{\n\t\tOptions::baseXResolution = Screen::ORIGINAL_WIDTH;\n\t\tOptions::baseYResolution = Screen::ORIGINAL_HEIGHT;\n\t\t_game->getScreen()->resetDisplay(false);\n\t}\n\t_battleGame = _game->getSavedGame()->getSavedBattle();\n\n\t// Create objects\n\t_bg = new Surface(320, 200, 0, 0);\n\t_exit = new InteractiveSurface(320, 180, 0, 20);\n\t_txtName = new Text(288, 17, 16, 4);\n\n\tint yPos = 38;\n\tint step = 9;\n\tif (_game->getMod()->isManaFeatureEnabled())\n\t{\n\t\tyPos = 30;\n\t}\n\n\t_txtTimeUnits = new Text(140, 9, 8, yPos);\n\t_numTimeUnits = new Text(18, 9, 150, yPos);\n\t_barTimeUnits = new Bar(150, 5, 170, yPos + 1);\n\tyPos += step;\n\n\t_txtEnergy = new Text(140, 9, 8, yPos);\n\t_numEnergy = new Text(18, 9, 150, yPos);\n\t_barEnergy = new Bar(150, 5, 170, yPos + 1);\n\tyPos += step;\n\n\t_txtHealth = new Text(140, 9, 8, yPos);\n\t_numHealth = new Text(18, 9, 150, yPos);\n\t_barHealth = new Bar(150, 5, 170, yPos + 1);\n\t{\n\t\tint numMaxHealthPosX = _game->getMod()->getInterface(\"stats\")->getElement(\"numMaxHealth\")->x;\n\t\t_numMaxHealth = new Text(40, 9, numMaxHealthPosX, yPos);\n\t}\n\tyPos += step;\n\n\t_txtFatalWounds = new Text(140, 9, 8, yPos);\n\t_numFatalWounds = new Text(18, 9, 150, yPos);\n\t_barFatalWounds = new Bar(150, 5, 170, yPos + 1);\n\tyPos += step;\n\n\t_txtBravery = new Text(140, 9, 8, yPos);\n\t_numBravery = new Text(18, 9, 150, yPos);\n\t_barBravery = new Bar(150, 5, 170, yPos + 1);\n\tyPos += step;\n\n\t_txtMorale = new Text(140, 9, 8, yPos);\n\t_numMorale = new Text(18, 9, 150, yPos);\n\t_barMorale = new Bar(150, 5, 170, yPos + 1);\n\tyPos += step;\n\n\t_txtReactions = new Text(140, 9, 8, yPos);\n\t_numReactions = new Text(18, 9, 150, yPos);\n\t_barReactions = new Bar(150, 5, 170, yPos + 1);\n\tyPos += step;\n\n\t_txtFiring = new Text(140, 9, 8, yPos);\n\t_numFiring = new Text(18, 9, 150, yPos);\n\t_barFiring = new Bar(150, 5, 170, yPos + 1);\n\tyPos += step;\n\n\t_txtThrowing = new Text(140, 9, 8, yPos);\n\t_numThrowing = new Text(18, 9, 150, yPos);\n\t_barThrowing = new Bar(150, 5, 170, yPos + 1);\n\tyPos += step;\n\n\t_txtMelee = new Text(140, 9, 8, yPos);\n\t_numMelee = new Text(18, 9, 150, yPos);\n\t_barMelee = new Bar(150, 5, 170, yPos + 1);\n\tyPos += step;\n\n\t_txtStrength = new Text(140, 9, 8, yPos);\n\t_numStrength = new Text(18, 9, 150, yPos);\n\t_barStrength = new Bar(150, 5, 170, yPos + 1);\n\tyPos += step;\n\n\tif (_game->getMod()->isManaFeatureEnabled())\n\t{\n\t\t_txtMana = new Text(140, 9, 8, yPos);\n\t\t_numMana = new Text(18, 9, 150, yPos);\n\t\t_barMana = new Bar(150, 5, 170, yPos + 1);\n\t\tyPos += step;\n\t}\n\n\t_txtPsiStrength = new Text(140, 9, 8, yPos);\n\t_numPsiStrength = new Text(18, 9, 150, yPos);\n\t_barPsiStrength = new Bar(150, 5, 170, yPos + 1);\n\tyPos += step;\n\n\t_txtPsiSkill = new Text(140, 9, 8, yPos);\n\t_numPsiSkill = new Text(18, 9, 150, yPos);\n\t_barPsiSkill = new Bar(150, 5, 170, yPos + 1);\n\tyPos += step;\n\n\t_txtFrontArmor = new Text(140, 9, 8, yPos);\n\t_numFrontArmor= new Text(18, 9, 150, yPos);\n\t_barFrontArmor = new Bar(150, 5, 170, yPos + 1);\n\tyPos += step;\n\n\t_txtLeftArmor = new Text(140, 9, 8, yPos);\n\t_numLeftArmor = new Text(18, 9, 150, yPos);\n\t_barLeftArmor = new Bar(150, 5, 170, yPos + 1);\n\tyPos += step;\n\n\t_txtRightArmor = new Text(140, 9, 8, yPos);\n\t_numRightArmor = new Text(18, 9, 150, yPos);\n\t_barRightArmor = new Bar(150, 5, 170, yPos + 1);\n\tyPos += step;\n\n\t_txtRearArmor = new Text(140, 9, 8, yPos);\n\t_numRearArmor = new Text(18, 9, 150, yPos);\n\t_barRearArmor = new Bar(150, 5, 170, yPos + 1);\n\tyPos += step;\n\n\t_txtUnderArmor = new Text(140, 9, 8, yPos);\n\t_numUnderArmor = new Text(18, 9, 150, yPos);\n\t_barUnderArmor = new Bar(150, 5, 170, yPos + 1);\n\n\tif (!_mindProbe)\n\t{\n\t\t_btnPrev = new TextButton(14, 18, 2, 2);\n\t\t_btnNext = new TextButton(14, 18, 304, 2);\n\t}\n\n\t// Set palette\n\tsetStandardPalette(\"PAL_BATTLESCAPE\");\n\n\tadd(_bg);\n\tadd(_exit);\n\tadd(_txtName, \"textName\", \"stats\", 0);\n\n\tadd(_txtTimeUnits);\n\tadd(_numTimeUnits);\n\tadd(_barTimeUnits, \"barTUs\", \"stats\", 0);\n\n\tadd(_txtEnergy);\n\tadd(_numEnergy);\n\tadd(_barEnergy, \"barEnergy\", \"stats\", 0);\n\n\tadd(_txtHealth);\n\tadd(_numHealth);\n\tadd(_barHealth, \"barHealth\", \"stats\", 0);\n\tadd(_numMaxHealth, \"numMaxHealth\", \"stats\", 0);\n\n\tadd(_txtFatalWounds);\n\tadd(_numFatalWounds);\n\tadd(_barFatalWounds, \"barWounds\", \"stats\", 0);\n\n\tadd(_txtBravery);\n\tadd(_numBravery);\n\tadd(_barBravery, \"barBravery\", \"stats\", 0);\n\n\tadd(_txtMorale);\n\tadd(_numMorale);\n\tadd(_barMorale, \"barMorale\", \"stats\", 0);\n\n\tadd(_txtReactions);\n\tadd(_numReactions);\n\tadd(_barReactions, \"barReactions\", \"stats\", 0);\n\n\tadd(_txtFiring);\n\tadd(_numFiring);\n\tadd(_barFiring, \"barFiring\", \"stats\", 0);\n\n\tadd(_txtThrowing);\n\tadd(_numThrowing);\n\tadd(_barThrowing, \"barThrowing\", \"stats\", 0);\n\n\tadd(_txtMelee);\n\tadd(_numMelee);\n\tadd(_barMelee, \"barMelee\", \"stats\", 0);\n\n\tadd(_txtStrength);\n\tadd(_numStrength);\n\tadd(_barStrength, \"barStrength\", \"stats\", 0);\n\n\tif (_game->getMod()->isManaFeatureEnabled())\n\t{\n\t\tadd(_txtMana);\n\t\tadd(_numMana);\n\t\tadd(_barMana, \"barMana\", \"stats\", 0);\n\t}\n\n\tadd(_txtPsiStrength);\n\tadd(_numPsiStrength);\n\tadd(_barPsiStrength, \"barPsiStrength\", \"stats\", 0);\n\n\tadd(_txtPsiSkill);\n\tadd(_numPsiSkill);\n\tadd(_barPsiSkill, \"barPsiSkill\", \"stats\", 0);\n\n\tadd(_txtFrontArmor);\n\tadd(_numFrontArmor);\n\tadd(_barFrontArmor, \"barFrontArmor\", \"stats\", 0);\n\n\tadd(_txtLeftArmor);\n\tadd(_numLeftArmor);\n\tadd(_barLeftArmor, \"barLeftArmor\", \"stats\", 0);\n\n\tadd(_txtRightArmor);\n\tadd(_numRightArmor);\n\tadd(_barRightArmor, \"barRightArmor\", \"stats\", 0);\n\n\tadd(_txtRearArmor);\n\tadd(_numRearArmor);\n\tadd(_barRearArmor, \"barRearArmor\", \"stats\", 0);\n\n\tadd(_txtUnderArmor);\n\tadd(_numUnderArmor);\n\tadd(_barUnderArmor, \"barUnderArmor\", \"stats\", 0);\n\n\tif (!_mindProbe)\n\t{\n\t\tadd(_btnPrev, \"button\", \"stats\");\n\t\tadd(_btnNext, \"button\", \"stats\");\n\t}\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\t_game->getMod()->getSurface(\"UNIBORD.PCK\")->blitNShade(_bg, 0, 0);\n\n\t_exit->onMouseClick((ActionHandler)&UnitInfoState::exitClick);\n\t_exit->onKeyboardPress((ActionHandler)&UnitInfoState::exitClick, Options::keyCancel);\n\t_exit->onKeyboardPress((ActionHandler)&UnitInfoState::exitClick, Options::keyBattleStats);\n\n\tUint8 color = _game->getMod()->getInterface(\"stats\")->getElement(\"text\")->color;\n\tUint8 color2 = _game->getMod()->getInterface(\"stats\")->getElement(\"text\")->color2;\n\n\t_txtName->setAlign(ALIGN_CENTER);\n\t_txtName->setBig();\n\t_txtName->setHighContrast(true);\n\n\t_txtTimeUnits->setColor(color);\n\t_txtTimeUnits->setHighContrast(true);\n\t_txtTimeUnits->setText(tr(\"STR_TIME_UNITS\"));\n\n\t_numTimeUnits->setColor(color2);\n\t_numTimeUnits->setHighContrast(true);\n\n\t_barTimeUnits->setScale(1.0);\n\n\t_txtEnergy->setColor(color);\n\t_txtEnergy->setHighContrast(true);\n\t_txtEnergy->setText(tr(\"STR_ENERGY\"));\n\n\t_numEnergy->setColor(color2);\n\t_numEnergy->setHighContrast(true);\n\n\t_barEnergy->setScale(1.0);\n\n\t_txtHealth->setColor(color);\n\t_txtHealth->setHighContrast(true);\n\t_txtHealth->setText(tr(\"STR_HEALTH\"));\n\n\t_numHealth->setColor(color2);\n\t_numHealth->setHighContrast(true);\n\n\t_numMaxHealth->setHighContrast(true);\n\t_numMaxHealth->setAlign(ALIGN_RIGHT);\n\n\t_barHealth->setScale(1.0);\n\n\t_txtFatalWounds->setColor(color);\n\t_txtFatalWounds->setHighContrast(true);\n\t_txtFatalWounds->setText(tr(\"STR_FATAL_WOUNDS\"));\n\n\t_numFatalWounds->setColor(color2);\n\t_numFatalWounds->setHighContrast(true);\n\n\t_barFatalWounds->setScale(1.0);\n\n\t_txtBravery->setColor(color);\n\t_txtBravery->setHighContrast(true);\n\t_txtBravery->setText(tr(\"STR_BRAVERY\"));\n\n\t_numBravery->setColor(color2);\n\t_numBravery->setHighContrast(true);\n\n\t_barBravery->setScale(1.0);\n\n\t_txtMorale->setColor(color);\n\t_txtMorale->setHighContrast(true);\n\t_txtMorale->setText(tr(\"STR_MORALE\"));\n\n\t_numMorale->setColor(color2);\n\t_numMorale->setHighContrast(true);\n\n\t_barMorale->setScale(1.0);\n\n\t_txtReactions->setColor(color);\n\t_txtReactions->setHighContrast(true);\n\t_txtReactions->setText(tr(\"STR_REACTIONS\"));\n\n\t_numReactions->setColor(color2);\n\t_numReactions->setHighContrast(true);\n\n\t_barReactions->setScale(1.0);\n\n\t_txtFiring->setColor(color);\n\t_txtFiring->setHighContrast(true);\n\t_txtFiring->setText(tr(\"STR_FIRING_ACCURACY\"));\n\n\t_numFiring->setColor(color2);\n\t_numFiring->setHighContrast(true);\n\n\t_barFiring->setScale(1.0);\n\n\t_txtThrowing->setColor(color);\n\t_txtThrowing->setHighContrast(true);\n\t_txtThrowing->setText(tr(\"STR_THROWING_ACCURACY\"));\n\n\t_numThrowing->setColor(color2);\n\t_numThrowing->setHighContrast(true);\n\n\t_barThrowing->setScale(1.0);\n\n\t_txtMelee->setColor(color);\n\t_txtMelee->setHighContrast(true);\n\t_txtMelee->setText(tr(\"STR_MELEE_ACCURACY\"));\n\n\t_numMelee->setColor(color2);\n\t_numMelee->setHighContrast(true);\n\n\t_barMelee->setScale(1.0);\n\n\t_txtStrength->setColor(color);\n\t_txtStrength->setHighContrast(true);\n\t_txtStrength->setText(tr(\"STR_STRENGTH\"));\n\n\t_numStrength->setColor(color2);\n\t_numStrength->setHighContrast(true);\n\n\t_barStrength->setScale(1.0);\n\n\tif (_game->getMod()->isManaFeatureEnabled())\n\t{\n\t\t_txtMana->setColor(color);\n\t\t_txtMana->setHighContrast(true);\n\t\t_txtMana->setText(tr(\"STR_MANA\"));\n\n\t\t_numMana->setColor(color2);\n\t\t_numMana->setHighContrast(true);\n\n\t\t_barMana->setScale(1.0);\n\t}\n\n\t_txtPsiStrength->setColor(color);\n\t_txtPsiStrength->setHighContrast(true);\n\t_txtPsiStrength->setText(tr(\"STR_PSIONIC_STRENGTH\"));\n\n\t_numPsiStrength->setColor(color2);\n\t_numPsiStrength->setHighContrast(true);\n\n\t_barPsiStrength->setScale(1.0);\n\n\t_txtPsiSkill->setColor(color);\n\t_txtPsiSkill->setHighContrast(true);\n\t_txtPsiSkill->setText(tr(\"STR_PSIONIC_SKILL\"));\n\n\t_numPsiSkill->setColor(color2);\n\t_numPsiSkill->setHighContrast(true);\n\n\t_barPsiSkill->setScale(1.0);\n\n\t_txtFrontArmor->setColor(color);\n\t_txtFrontArmor->setHighContrast(true);\n\t_txtFrontArmor->setText(tr(\"STR_FRONT_ARMOR_UC\"));\n\n\t_numFrontArmor->setColor(color2);\n\t_numFrontArmor->setHighContrast(true);\n\n\t_barFrontArmor->setScale(1.0);\n\n\t_txtLeftArmor->setColor(color);\n\t_txtLeftArmor->setHighContrast(true);\n\t_txtLeftArmor->setText(tr(\"STR_LEFT_ARMOR_UC\"));\n\n\t_numLeftArmor->setColor(color2);\n\t_numLeftArmor->setHighContrast(true);\n\n\t_barLeftArmor->setScale(1.0);\n\n\t_txtRightArmor->setColor(color);\n\t_txtRightArmor->setHighContrast(true);\n\t_txtRightArmor->setText(tr(\"STR_RIGHT_ARMOR_UC\"));\n\n\t_numRightArmor->setColor(color2);\n\t_numRightArmor->setHighContrast(true);\n\n\t_barRightArmor->setScale(1.0);\n\n\t_txtRearArmor->setColor(color);\n\t_txtRearArmor->setHighContrast(true);\n\t_txtRearArmor->setText(tr(\"STR_REAR_ARMOR_UC\"));\n\n\t_numRearArmor->setColor(color2);\n\t_numRearArmor->setHighContrast(true);\n\n\t_barRearArmor->setScale(1.0);\n\n\t_txtUnderArmor->setColor(color);\n\t_txtUnderArmor->setHighContrast(true);\n\t_txtUnderArmor->setText(tr(\"STR_UNDER_ARMOR_UC\"));\n\n\t_numUnderArmor->setColor(color2);\n\t_numUnderArmor->setHighContrast(true);\n\n\t_barUnderArmor->setScale(1.0);\n\n\tif (!_mindProbe)\n\t{\n\t\t_btnPrev->setText(\"<<\");\n\t\t_btnPrev->onMouseClick((ActionHandler)&UnitInfoState::btnPrevClick);\n\t\t_btnPrev->onKeyboardPress((ActionHandler)&UnitInfoState::btnPrevClick, Options::keyBattlePrevUnit);\n\t\t_btnNext->setText(\">>\");\n\t\t_btnNext->onMouseClick((ActionHandler)&UnitInfoState::btnNextClick);\n\t\t_btnNext->onKeyboardPress((ActionHandler)&UnitInfoState::btnNextClick, Options::keyBattleNextUnit);\n\t}\n\n}\n\n/**\n *\n */\nUnitInfoState::~UnitInfoState()\n{\n\n}\n\n/**\n * Updates unit info which can change\n * after going into other screens.\n */\nvoid UnitInfoState::init()\n{\n\tState::init();\n\tstd::ostringstream ss;\n\tss << _unit->getTimeUnits();\n\t_numTimeUnits->setText(ss.str());\n\t_barTimeUnits->setMax(_unit->getBaseStats()->tu);\n\t_barTimeUnits->setValue(_unit->getTimeUnits());\n\n\tss.str(\"\");\n\t// aliens have their rank in their \"name\", soldiers don't\n\tif (_unit->getType() == \"SOLDIER\")\n\t{\n\t\tss << tr(_unit->getRankString());\n\t\tss << \" \";\n\t}\n\tss << _unit->getName(_game->getLanguage(), BattlescapeGame::_debugPlay);\n\t_txtName->setBig();\n\t_txtName->setText(ss.str());\n\n\tss.str(\"\");\n\tss << _unit->getEnergy();\n\t_numEnergy->setText(ss.str());\n\t_barEnergy->setMax(_unit->getBaseStats()->stamina);\n\t_barEnergy->setValue(_unit->getEnergy());\n\n\tss.str(\"\");\n\tss << _unit->getHealth();\n\t_numHealth->setText(ss.str());\n\t_barHealth->setMax(_unit->getBaseStats()->health);\n\t_barHealth->setValue(_unit->getHealth());\n\t_barHealth->setValue2(_unit->getStunlevel());\n\n\t_numMaxHealth->setText(\"\");\n\tif (_unit->getBaseStats()->health >= 147)\n\t{\n\t\tauto* numMaxHealthElement = _game->getMod()->getInterface(\"stats\")->getElement(\"numMaxHealth\");\n\t\tif ((numMaxHealthElement->custom & 1) || _unit->getHealth() != _unit->getBaseStats()->health)\n\t\t{\n\t\t\tss.str(\"\");\n\t\t\tif (numMaxHealthElement->custom & 2)\n\t\t\t{\n\t\t\t\tss << \"/\";\n\t\t\t}\n\t\t\tss << _unit->getBaseStats()->health;\n\t\t\t_numMaxHealth->setText(ss.str());\n\t\t}\n\t}\n\n\tss.str(\"\");\n\tss << _unit->getFatalWounds();\n\t_numFatalWounds->setText(ss.str());\n\t_barFatalWounds->setMax(_unit->getFatalWounds());\n\t_barFatalWounds->setValue(_unit->getFatalWounds());\n\n\tss.str(\"\");\n\tss << _unit->getBaseStats()->bravery;\n\t_numBravery->setText(ss.str());\n\t_barBravery->setMax(_unit->getBaseStats()->bravery);\n\t_barBravery->setValue(_unit->getBaseStats()->bravery);\n\n\tss.str(\"\");\n\tss << _unit->getMorale();\n\t_numMorale->setText(ss.str());\n\t_barMorale->setMax(100);\n\t_barMorale->setValue(_unit->getMorale());\n\n\tss.str(\"\");\n\tss << _unit->getBaseStats()->reactions;\n\t_numReactions->setText(ss.str());\n\t_barReactions->setMax(_unit->getBaseStats()->reactions);\n\t_barReactions->setValue(_unit->getBaseStats()->reactions);\n\n\t// more info: http://ufopaedia.org/index.php?title=Accuracy_formula#Stat_Screen_Accuracy\n\tint healthModifier = 75 + ((25 * _unit->getHealth()) / _unit->getBaseStats()->health);\n\n\tss.str(\"\");\n\tss << (int)((_unit->getBaseStats()->firing * healthModifier) / 100);\n\t_numFiring->setText(ss.str());\n\t_barFiring->setMax(_unit->getBaseStats()->firing);\n\t_barFiring->setValue((_unit->getBaseStats()->firing * healthModifier) / 100);\n\n\tss.str(\"\");\n\tss << (int)((_unit->getBaseStats()->throwing * healthModifier) / 100);\n\t_numThrowing->setText(ss.str());\n\t_barThrowing->setMax(_unit->getBaseStats()->throwing);\n\t_barThrowing->setValue((_unit->getBaseStats()->throwing * healthModifier) / 100);\n\n\tss.str(\"\");\n\tss << (int)((_unit->getBaseStats()->melee * healthModifier) / 100);\n\t_numMelee->setText(ss.str());\n\t_barMelee->setMax(_unit->getBaseStats()->melee);\n\t_barMelee->setValue((_unit->getBaseStats()->melee * healthModifier) / 100);\n\t// end of healthModifier usage\n\n\tss.str(\"\");\n\tss << _unit->getBaseStats()->strength;\n\t_numStrength->setText(ss.str());\n\t_barStrength->setMax(_unit->getBaseStats()->strength);\n\t_barStrength->setValue(_unit->getBaseStats()->strength);\n\n\tif (_game->getMod()->isManaFeatureEnabled())\n\t{\n\t\tif (_game->getSavedGame()->isManaUnlocked(_game->getMod()))\n\t\t{\n\t\t\tss.str(\"\");\n\t\t\tss << _unit->getMana();\n\t\t\t_numMana->setText(ss.str());\n\t\t\t_barMana->setMax(_unit->getBaseStats()->mana);\n\t\t\t_barMana->setValue(_unit->getMana());\n\n\t\t\t_txtMana->setVisible(true);\n\t\t\t_numMana->setVisible(true);\n\t\t\t_barMana->setVisible(true);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_txtMana->setVisible(false);\n\t\t\t_numMana->setVisible(false);\n\t\t\t_barMana->setVisible(false);\n\t\t}\n\t}\n\n\tauto psiSkillWithoutAnyBonuses = _unit->getBaseStats()->psiSkill;\n\tif (_unit->getGeoscapeSoldier())\n\t{\n\t\tpsiSkillWithoutAnyBonuses = _unit->getGeoscapeSoldier()->getCurrentStats()->psiSkill;\n\t}\n\tif (psiSkillWithoutAnyBonuses > 0 || (Options::psiStrengthEval && _game->getSavedGame()->isResearched(_game->getMod()->getPsiRequirements())))\n\t{\n\t\tss.str(\"\");\n\t\tss << _unit->getBaseStats()->psiStrength;\n\t\t_numPsiStrength->setText(ss.str());\n\t\t_barPsiStrength->setMax(_unit->getBaseStats()->psiStrength);\n\t\t_barPsiStrength->setValue(_unit->getBaseStats()->psiStrength);\n\n\t\t_txtPsiStrength->setVisible(true);\n\t\t_numPsiStrength->setVisible(true);\n\t\t_barPsiStrength->setVisible(true);\n\t}\n\telse\n\t{\n\t\t_txtPsiStrength->setVisible(false);\n\t\t_numPsiStrength->setVisible(false);\n\t\t_barPsiStrength->setVisible(false);\n\t}\n\n\tif (psiSkillWithoutAnyBonuses > 0)\n\t{\n\t\tss.str(\"\");\n\t\tss << _unit->getBaseStats()->psiSkill;\n\t\t_numPsiSkill->setText(ss.str());\n\t\t_barPsiSkill->setMax(_unit->getBaseStats()->psiSkill);\n\t\t_barPsiSkill->setValue(_unit->getBaseStats()->psiSkill);\n\n\t\t_txtPsiSkill->setVisible(true);\n\t\t_numPsiSkill->setVisible(true);\n\t\t_barPsiSkill->setVisible(true);\n\t}\n\telse\n\t{\n\t\t_txtPsiSkill->setVisible(false);\n\t\t_numPsiSkill->setVisible(false);\n\t\t_barPsiSkill->setVisible(false);\n\t}\n\n\tss.str(\"\");\n\tss << _unit->getArmor(SIDE_FRONT);\n\t_numFrontArmor->setText(ss.str());\n\t_barFrontArmor->setMax(_unit->getMaxArmor(SIDE_FRONT));\n\t_barFrontArmor->setValue(_unit->getArmor(SIDE_FRONT));\n\n\tss.str(\"\");\n\tss << _unit->getArmor(SIDE_LEFT);\n\t_numLeftArmor->setText(ss.str());\n\t_barLeftArmor->setMax(_unit->getMaxArmor(SIDE_LEFT));\n\t_barLeftArmor->setValue(_unit->getArmor(SIDE_LEFT));\n\n\tss.str(\"\");\n\tss << _unit->getArmor(SIDE_RIGHT);\n\t_numRightArmor->setText(ss.str());\n\t_barRightArmor->setMax(_unit->getMaxArmor(SIDE_RIGHT));\n\t_barRightArmor->setValue(_unit->getArmor(SIDE_RIGHT));\n\n\tss.str(\"\");\n\tss << _unit->getArmor(SIDE_REAR);\n\t_numRearArmor->setText(ss.str());\n\t_barRearArmor->setMax(_unit->getMaxArmor(SIDE_REAR));\n\t_barRearArmor->setValue(_unit->getArmor(SIDE_REAR));\n\n\tss.str(\"\");\n\tss << _unit->getArmor(SIDE_UNDER);\n\t_numUnderArmor->setText(ss.str());\n\t_barUnderArmor->setMax(_unit->getMaxArmor(SIDE_UNDER));\n\t_barUnderArmor->setValue(_unit->getArmor(SIDE_UNDER));\n}\n\n\n/**\n * Closes the window on right-click.\n * @param action Pointer to an action.\n */\nvoid UnitInfoState::handle(Action *action)\n{\n\tState::handle(action);\n\tif (action->getDetails()->type == SDL_MOUSEBUTTONDOWN)\n\t{\n\t\tif (_game->isRightClick(action))\n\t\t{\n\t\t\texitClick(action);\n\t\t\treturn;\n\t\t}\n\t\tif (Options::oxceThumbButtons)\n\t\t{\n\t\t\tif (action->getDetails()->button.button == SDL_BUTTON_X1)\n\t\t\t{\n\t\t\t\tif (!_mindProbe) btnNextClick(action);\n\t\t\t}\n\t\t\telse if (action->getDetails()->button.button == SDL_BUTTON_X2)\n\t\t\t{\n\t\t\t\tif (!_mindProbe) btnPrevClick(action);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Selects the previous unit.\n * @param action Pointer to an action.\n */\nvoid UnitInfoState::btnPrevClick(Action *action)\n{\n\tif (_parent)\n\t{ // so we are here from a Battlescape Game\n\t\t_parent->selectPreviousPlayerUnit(false, false, _fromInventory);\n\t}\n\telse\n\t{ // so we are here from the Craft Equipment screen\n\t\t_battleGame->selectPreviousPlayerUnit(false, false, true);\n\t}\n\t_unit = _battleGame->getSelectedUnit();\n\tif (_unit != 0)\n\t{\n\t\tinit();\n\t}\n\telse\n\t{\n\t\texitClick(action);\n\t}\n}\n\n/**\n * Selects the next unit.\n * @param action Pointer to an action.\n */\nvoid UnitInfoState::btnNextClick(Action *action)\n{\n\tif (_parent)\n\t{ // so we are here from a Battlescape Game\n\t\t_parent->selectNextPlayerUnit(false, false, _fromInventory);\n\t}\n\telse\n\t{ // so we are here from the Craft Equipment screen\n\t\t_battleGame->selectNextPlayerUnit(false, false, true);\n\t}\n\t_unit = _battleGame->getSelectedUnit();\n\tif (_unit != 0)\n\t{\n\t\tinit();\n\t}\n\telse\n\t{\n\t\texitClick(action);\n\t}\n}\n\n/**\n * Exits the screen.\n * @param action Pointer to an action.\n */\nvoid UnitInfoState::exitClick(Action *)\n{\n\tif (!_fromInventory && Options::maximizeInfoScreens)\n\t{\n\t\tScreen::updateScale(Options::battlescapeScale, Options::baseXBattlescape, Options::baseYBattlescape, true);\n\t\t_game->getScreen()->resetDisplay(false);\n\t}\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/UnitInfoState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass BattleUnit;\nclass Text;\nclass TextButton;\nclass Bar;\nclass Surface;\nclass SavedBattleGame;\nclass BattlescapeState;\n\n/**\n * Unit Info screen that shows all the\n * info of a specific unit.\n */\nclass UnitInfoState : public State\n{\nprivate:\n\tSavedBattleGame *_battleGame;\n\n\tBattleUnit *_unit;\n\tBattlescapeState *_parent;\n\n\tbool _fromInventory, _mindProbe;\n\n\tSurface *_bg;\n\tInteractiveSurface *_exit;\n\tText *_txtName;\n\n\tText *_txtTimeUnits, *_txtEnergy, *_txtHealth, *_txtFatalWounds, *_txtBravery, *_txtMorale, *_txtReactions, *_txtFiring, *_txtThrowing, *_txtMelee, *_txtStrength;\n\tText *_txtPsiStrength,  *_txtPsiSkill, *_txtMana;\n\tText *_numTimeUnits, *_numEnergy, *_numHealth, *_numFatalWounds, *_numBravery, *_numMorale, *_numReactions, *_numFiring, *_numThrowing, *_numMelee, *_numStrength;\n\tText *_numPsiStrength, *_numPsiSkill, *_numMana;\n\tText *_numMaxHealth;\n\tBar *_barTimeUnits, *_barEnergy, *_barHealth, *_barFatalWounds, *_barBravery, *_barMorale, *_barReactions, *_barFiring, *_barThrowing, *_barMelee, *_barStrength;\n\tBar *_barPsiStrength, *_barPsiSkill, *_barMana;\n\n\tText *_txtFrontArmor, *_txtLeftArmor, *_txtRightArmor, *_txtRearArmor, *_txtUnderArmor;\n\tText *_numFrontArmor, *_numLeftArmor, *_numRightArmor, *_numRearArmor, *_numUnderArmor;\n\tBar *_barFrontArmor, *_barLeftArmor, *_barRightArmor, *_barRearArmor, *_barUnderArmor;\n\tTextButton *_btnPrev, *_btnNext;\npublic:\n\t/// Creates the Unit Info state.\n\tUnitInfoState(BattleUnit *unit, BattlescapeState *parent, bool fromInventory, bool mindProbe);\n\t/// Cleans up the Unit Info state.\n\t~UnitInfoState();\n\t/// Updates the unit info.\n\tvoid init() override;\n\t/// Handler for clicking the button.\n\tvoid handle(Action *action) override;\n\t/// Handler for clicking the Previous button.\n\tvoid btnPrevClick(Action *action);\n\t/// Handler for clicking the Next button.\n\tvoid btnNextClick(Action *action);\n\t/// Handler for exiting the state.\n\tvoid exitClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/UnitPanicBState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"UnitPanicBState.h\"\n#include \"UnitTurnBState.h\"\n#include \"ProjectileFlyBState.h\"\n#include \"TileEngine.h\"\n#include \"../Savegame/BattleUnit.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"../Engine/RNG.h\"\n#include \"BattlescapeGame.h\"\n#include \"../Mod/Mod.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Sets up an UnitPanicBState.\n * @param parent Pointer to the Battlescape.\n * @param unit Panicking unit.\n */\nUnitPanicBState::UnitPanicBState(BattlescapeGame *parent, BattleUnit *unit) : BattleState(parent), _unit(unit), _shotsFired(0)\n{\n\t_berserking = _unit->getStatus() == STATUS_BERSERK;\n\tunit->abortTurn(); //makes the unit go to status STANDING :p\n}\n\n/**\n * Deletes the UnitPanicBState.\n */\nUnitPanicBState::~UnitPanicBState()\n{\n}\n\nvoid UnitPanicBState::init()\n{\n}\n\n/**\n * Runs state functionality every cycle.\n * Ends the panicking when done.\n */\nvoid UnitPanicBState::think()\n{\n\tif (_unit)\n\t{\n\t\t// berserking requires handling here, as the target selection isn't completely random\n\t\t// and needs updating between shots.\n\t\tif (!_unit->isOut() && _shotsFired < 10 && _berserking)\n\t\t{\n\t\t\t_shotsFired++;\n\t\t\tBattleAction ba;\n\t\t\tba.actor = _unit;\n\t\t\tba.weapon = _unit->getMainHandWeapon();\n\t\t\t{\n\t\t\t\t// make autoshots if possible.\n\t\t\t\tba.type = BA_AUTOSHOT;\n\t\t\t\tba.updateTU();\n\t\t\t\tbool canShoot = ba.haveTU() && _parent->getSave()->canUseWeapon(ba.weapon, ba.actor, _berserking, ba.type);\n\n\t\t\t\tif (!canShoot)\n\t\t\t\t{\n\t\t\t\t\tba.type = BA_SNAPSHOT;\n\t\t\t\t\tba.updateTU();\n\t\t\t\t\tcanShoot = ba.haveTU() && _parent->getSave()->canUseWeapon(ba.weapon, ba.actor, _berserking, ba.type);\n\t\t\t\t}\n\n\t\t\t\tif (!canShoot && Mod::EXTENDED_BERSERK_WITH_AIMED > 0)\n\t\t\t\t{\n\t\t\t\t\tif (Mod::EXTENDED_BERSERK_WITH_AIMED == 1 && ba.weapon->getCurrentWaypoints() != 0)\n\t\t\t\t\t{\n\t\t\t\t\t\t// can use BA_AIMEDSHOT, but cannot use BA_LAUNCH\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tba.type = BA_AIMEDSHOT;\n\t\t\t\t\t\tba.updateTU();\n\t\t\t\t\t\tcanShoot = ba.haveTU() && _parent->getSave()->canUseWeapon(ba.weapon, ba.actor, _berserking, ba.type);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (canShoot)\n\t\t\t\t{\n\t\t\t\t\t// if we see enemies, shoot at the closest living one.\n\t\t\t\t\tif (!_unit->getVisibleUnits()->empty())\n\t\t\t\t\t{\n\t\t\t\t\t\tint dist = 255;\n\t\t\t\t\t\tfor (auto* bu : *_unit->getVisibleUnits())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tint newDist = Position::distance2d(_unit->getPosition(), bu->getPosition());\n\t\t\t\t\t\t\tif (newDist < dist)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tba.target = bu->getPosition();\n\t\t\t\t\t\t\t\tdist = newDist;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse // otherwise shoot randomly\n\t\t\t\t\t{\n\t\t\t\t\t\tba.target = Position(_unit->getPosition().x + RNG::generate(-6,6), _unit->getPosition().y + RNG::generate(-6,6), _unit->getPosition().z);\n\t\t\t\t\t}\n\t\t\t\t\t// include the cost for facing our target\n\t\t\t\t\tint turnCost = std::abs(_unit->getDirection() - _unit->directionTo(ba.target));\n\t\t\t\t\tif (turnCost > 4)\n\t\t\t\t\t{\n\t\t\t\t\t\tturnCost = 8-turnCost;\n\t\t\t\t\t}\n\t\t\t\t\tturnCost = turnCost * _unit->getTurnCost();\n\n\t\t\t\t\t_unit->spendTimeUnits(turnCost);\n\t\t\t\t\t_parent->statePushFront(new UnitTurnBState(_parent, ba, false));\n\t\t\t\t\t// even if we don't have enough TUs to turn AND shoot, we still want to turn.\n\t\t\t\t\tif (ba.haveTU())\n\t\t\t\t\t{\n\t\t\t\t\t\t_parent->statePushNext(new ProjectileFlyBState(_parent, ba));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (!_unit->isOut())\n\t\t{\n\t\t\t_unit->abortTurn(); // set the unit status to standing in case it wasn't otherwise changed from berserk/panicked\n\t\t}\n\t\t// reset the unit's time units when all panicking is done\n\t\t_unit->clearTimeUnits();\n\t\t_unit->moraleChange(+15);\n\t}\n\t_parent->popState();\n\t_parent->setupCursor();\n}\n\n/**\n * Panicking cannot be cancelled.\n */\nvoid UnitPanicBState::cancel()\n{\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/UnitPanicBState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"BattleState.h\"\n\nnamespace OpenXcom\n{\n\nclass BattleUnit;\n\n/**\n * State for panicking units.\n */\nclass UnitPanicBState : public BattleState\n{\nprivate:\n\tBattleUnit *_unit;\n\tbool _berserking;\n\tint _shotsFired;\npublic:\n\t/// Creates a new UnitPanicBState class\n\tUnitPanicBState(BattlescapeGame *parent, BattleUnit *unit);\n\t/// Cleans up the UnitPanicBState.\n\t~UnitPanicBState();\n\t/// Initializes the state.\n\tvoid init() override;\n\t/// Handles a cancels request.\n\tvoid cancel() override;\n\t/// Runs state functionality every cycle.\n\tvoid think() override;\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/UnitSprite.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"UnitSprite.h\"\n#include \"../Engine/SurfaceSet.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Savegame/BattleUnit.h\"\n#include \"../Savegame/BattleItem.h\"\n#include \"../Savegame/Soldier.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"../Mod/RuleInventory.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/Exception.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Sets up a UnitSprite with the specified size and position.\n * @param width Width in pixels.\n * @param height Height in pixels.\n * @param x X position in pixels.\n * @param y Y position in pixels.\n */\nUnitSprite::UnitSprite(Surface* dest, const Mod* mod, const SavedBattleGame* save, int frame, bool helmet, int red, int blue) :\n\t_unit(0), _itemR(0), _itemL(0),\n\t_unitSurface(0),\n\t_itemSurface(const_cast<Mod*>(mod)->getSurfaceSet(\"HANDOB.PCK\")),\n\t_fireSurface(const_cast<Mod*>(mod)->getSurfaceSet(\"SMOKE.PCK\")),\n\t_breathSurface(const_cast<Mod*>(mod)->getSurfaceSet(\"BREATH-1.PCK\", false)),\n\t_facingArrowSurface(const_cast<Mod*>(mod)->getSurfaceSet(\"DETBLOB.DAT\")),\n\t_dest(dest), _save(save), _mod(mod),\n\t_part(0), _animationFrame(frame), _drawingRoutine(0),\n\t_helmet(helmet),\n\t_red(red), _blue(blue),\n\t_x(0), _y(0), _shade(0), _burn(0),\n\t_mask(0, 0)\n{\n\n}\n\n/**\n * Deletes the UnitSprite.\n */\nUnitSprite::~UnitSprite()\n{\n\n}\n\nnamespace\n{\n\n/**\n * Placeholder for surface index for body part not used by normal OpenXcom.\n */\nconst int InvalidSpriteIndex = -256;\n\n/**\n * Get item if can be visible on sprite.\n */\nconst BattleItem *getIfVisible(const BattleItem *item)\n{\n\tif (item && (!item->getRules()->isFixed() || item->getRules()->getFixedShow()))\n\t{\n\t\treturn item;\n\t}\n\treturn 0;\n}\n\n} //namespace\n\n/**\n * Get item sprite for item.\n * @param item item what we want draw.\n * @return Graphic part.\n */\nvoid UnitSprite::selectItem(Part& p, const BattleItem *item, int dir)\n{\n\tconst auto* rule = item->getRules();\n\tint index = item->getRules()->getHandSprite();\n\n\t//enforce compatibility with basic version\n\tif (!_itemSurface->getFrame(index + dir))\n\t{\n\t\tthrow Exception(\"Frame(s) missing in 'HANDOB.PCK' for item '\" + item->getRules()->getType() + \"'\");\n\t}\n\n\tint result = ModScript::scriptFunc2<ModScript::SelectItemSprite>(\n\t\trule,\n\t\tindex, dir,\n\t\titem, _save, p.bodyPart, _animationFrame, _shade\n\t);\n\n\tp.src = _itemSurface->getFrame(result);\n}\n\n/**\n * Get item sprite for unit body part.\n * @param index index of item sprite.\n * @return Graphic part.\n */\nvoid UnitSprite::selectUnit(Part& p, int index, int dir)\n{\n\tconst auto* armor = _unit->getArmor();\n\n\t//enforce compatibility with basic version\n\tif (InvalidSpriteIndex != index && !_unitSurface->getFrame(index + dir))\n\t{\n\t\tthrow Exception(\"Frame(s) missing in '\" + armor->getSpriteSheet() + \"' for armor '\" + armor->getType() + \"'\");\n\t}\n\n\tint result = ModScript::scriptFunc2<ModScript::SelectUnitSprite>(\n\t\tarmor,\n\t\tindex, dir,\n\t\t_unit, _save, p.bodyPart, _animationFrame, _shade\n\t);\n\n\tp.src = _unitSurface->getFrame(result);\n}\n\n/**\n * Blit item sprite onto surface.\n * @param item item sprite, can be null.\n */\nvoid UnitSprite::blitItem(Part& item)\n{\n\tif (!item.src)\n\t{\n\t\treturn;\n\t}\n\tScriptWorkerBlit work;\n\tBattleItem::ScriptFill(&work, (item.bodyPart == BODYPART_ITEM_RIGHTHAND ? _itemR : _itemL), _save, item.bodyPart, _animationFrame, _shade);\n\n\t_dest->lock();\n\n\twork.executeBlit(item.src, _dest,  _x + item.offX, _y + item.offY, _shade, _mask);\n\n\t_dest->unlock();\n}\n\n/**\n * Blit body sprite onto surface with optional recoloring.\n * @param body body part sprite, can be null.\n */\nvoid UnitSprite::blitBody(Part& body)\n{\n\tif (!body.src)\n\t{\n\t\treturn;\n\t}\n\tScriptWorkerBlit work;\n\tBattleUnit::ScriptFill(&work, _unit, _save, body.bodyPart, _animationFrame, _shade, _burn);\n\n\t_dest->lock();\n\n\twork.executeBlit(body.src, _dest,  _x + body.offX, _y + body.offY, _shade, _mask);\n\n\t_dest->unlock();\n}\n\n/**\n * Draws a unit, using the drawing rules of the unit.\n * This function is called by Map, for each unit on the screen.\n */\nvoid UnitSprite::draw(const BattleUnit* unit, int part, int x, int y, int shade, GraphSubset mask, bool drawFacingIndicator)\n{\n\t_x = x;\n\t_y = y;\n\n\t_unit = unit;\n\t_part = part;\n\t_shade = shade;\n\t_mask = mask;\n\n\tif (_unit->isOut())\n\t{\n\t\t// unit is drawn as an item\n\t\treturn;\n\t}\n\n\tauto* armor = _unit->getArmor();\n\n\t_itemR = getIfVisible(_unit->getRightHandWeapon());\n\t_itemL = getIfVisible(_unit->getLeftHandWeapon());\n\n\t_unitSurface = const_cast<Mod*>(_mod)->getSurfaceSet(armor->getSpriteSheet());\n\n\t_drawingRoutine = armor->getDrawingRoutine();\n\n\t_burn = 0;\n\tint overkill = _unit->getOverKillDamage();\n\tint maxHp = _unit->getBaseStats()->health;\n\tif (overkill)\n\t{\n\t\tif (overkill > maxHp)\n\t\t{\n\t\t\t_burn = 16 * (_unit->getFallingPhase() + 1) / armor->getDeathFrames();\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_burn = 16 * overkill * (_unit->getFallingPhase() + 1) / armor->getDeathFrames() / maxHp;\n\t\t}\n\t}\n\n\t// Array of drawing routines\n\tvoid (UnitSprite::*routines[])() =\n\t{\n\t\t&UnitSprite::drawRoutine0,\n\t\t&UnitSprite::drawRoutine1,\n\t\t&UnitSprite::drawRoutine2,\n\t\t&UnitSprite::drawRoutine3,\n\t\t&UnitSprite::drawRoutine4,\n\t\t&UnitSprite::drawRoutine5,\n\t\t&UnitSprite::drawRoutine6,\n\t\t&UnitSprite::drawRoutine7,\n\t\t&UnitSprite::drawRoutine8,\n\t\t&UnitSprite::drawRoutine9,\n\t\t&UnitSprite::drawRoutine0,\n\t\t&UnitSprite::drawRoutine11,\n\t\t&UnitSprite::drawRoutine12,\n\t\t&UnitSprite::drawRoutine0,\n\t\t&UnitSprite::drawRoutine0,\n\t\t&UnitSprite::drawRoutine0,\n\t\t&UnitSprite::drawRoutine16,\n\t\t&UnitSprite::drawRoutine4,\n\t\t&UnitSprite::drawRoutine4,\n\t\t&UnitSprite::drawRoutine19,\n\t\t&UnitSprite::drawRoutine20,\n\t\t&UnitSprite::drawRoutine21,\n\t\t&UnitSprite::drawRoutine3,\n\t};\n\t// Call the matching routine\n\t(this->*(routines[_drawingRoutine]))();\n\t// draw fire\n\tif (unit->getFire() > 0)\n\t{\n\t\t_fireSurface->getFrame(4 + (_animationFrame / 2) % 4)->blitNShade(_dest, _x, _y, 0, _mask);\n\t}\n\tif (_breathSurface && _helmet && unit->getBreathExhaleFrame() >= 0 && armor->drawBubbles() && !unit->getFloorAbove())\n\t{\n\t\tauto* tmpSurface = _breathSurface->getFrame(unit->getBreathExhaleFrame());\n\t\tif (tmpSurface)\n\t\t{\n\t\t\t// lower the bubbles for shorter or kneeling units.\n\t\t\ttmpSurface->blitNShade(_dest, _x, _y- 30 + (22 - unit->getHeight()), shade, _mask);\n\t\t}\n\t}\n\tif (drawFacingIndicator && part == 0)\n\t{\n\t\t// draw unit facing indicator\n\t\tauto* tmpSurface = _facingArrowSurface->getFrame(7 + ((unit->getDirection() + 1) % 8));\n\t\tif (unit->getOriginalFaction() == FACTION_PLAYER)\n\t\t{\n\t\t\ttmpSurface->blitNShade(_dest, _x, _y, 0);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tSurface::blitRaw(_dest, tmpSurface, _x, _y, 0, false, unit->getOriginalFaction() == FACTION_HOSTILE ? _blue : _red);\n\t\t}\n\t}\n}\n\n/**\n * Drawing routine for XCom soldiers in overalls, sectoids (routine 0),\n * mutons (routine 10),\n * aquanauts (routine 13),\n * calcinites, deep ones, gill men, lobster men, tasoths (routine 14),\n * aquatoids (routine 15) (this one is no different, it just precludes breathing animations.\n */\nvoid UnitSprite::drawRoutine0()\n{\n\tPart torso{ BODYPART_TORSO }, legs{ BODYPART_LEGS }, leftArm{ BODYPART_LEFTARM }, rightArm{ BODYPART_RIGHTARM }, itemR { BODYPART_ITEM_RIGHTHAND }, itemL { BODYPART_ITEM_LEFTHAND };\n\t// magic numbers\n\tconst int legsStand = 16, legsKneel = 24;\n\tint maleTorso, femaleTorso, die, rarm1H, larm2H, rarm2H, rarmShoot, legsFloat, torsoHandsWeaponY = 0;\n\tif (_drawingRoutine <= 10)\n\t{\n\t\tdie = 264; // ufo:eu death frame\n\t\tmaleTorso = 32;\n\t\tfemaleTorso = 267;\n\t\trarm1H = 232;\n\t\tlarm2H = 240;\n\t\trarm2H = 248;\n\t\trarmShoot = 256;\n\t\tlegsFloat = 275;\n\t}\n\telse if (_drawingRoutine == 13)\n\t{\n\t\tif (_helmet)\n\t\t{\n\t\t\tdie = 259; // aquanaut underwater death frame\n\t\t\tmaleTorso = 32; // aquanaut underwater ion armour torso\n\n\t\t\tif (_unit->getArmor()->getForcedTorso() == TORSO_USE_GENDER)\n\t\t\t{\n\t\t\t\tfemaleTorso = 32; // aquanaut underwater plastic aqua armour torso\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tfemaleTorso = 286; // aquanaut underwater magnetic ion armour torso\n\t\t\t}\n\t\t\trarm1H = 248;\n\t\t\tlarm2H = 232;\n\t\t\trarm2H = rarmShoot = 240;\n\t\t\tlegsFloat = 294;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tdie = 256; // aquanaut land death frame\n\t\t\t// aquanaut land torso\n\t\t\tmaleTorso = 270;\n\t\t\tfemaleTorso = 262;\n\t\t\trarm1H = 248;\n\t\t\tlarm2H = 232;\n\t\t\trarm2H = rarmShoot = 240;\n\t\t\tlegsFloat = 294;\n\t\t}\n\t}\n\telse\n\t{\n\t\tdie = 256; // tftd unit death frame\n\t\t// tftd unit torso\n\t\tmaleTorso = 32;\n\t\tfemaleTorso = 262;\n\t\trarm1H = 248;\n\t\tlarm2H = 232;\n\t\trarm2H = rarmShoot = 240;\n\t\tlegsFloat = 294;\n\t}\n\tconst int larmStand = 0, rarmStand = 8;\n\tconst int legsWalk = 56;\n\tconst int larmWalk = 40;\n\tconst int rarmWalk = 48;\n\tconst int YoffWalk[8] = {1, 0, -1, 0, 1, 0, -1, 0}; // bobbing up and down\n\tconst int mutonYoffWalk[8] = {1, 1, 0, 0, 1, 1, 0, 0}; // bobbing up and down (muton)\n\tconst int aquatoidYoffWalk[8] = {1, 0, 0, 1, 2, 1, 0, 0}; // bobbing up and down (aquatoid)\n\tconst int offX[8] = { 8, 10, 7, 4, -9, -11, -7, -3 }; // for the weapons\n\tconst int offY[8] = { -6, -3, 0, 2, 0, -4, -7, -9 }; // for the weapons\n\tconst int offX2[8] = { -8, 3, 5, 12, 6, -1, -5, -13 }; // for the left handed weapons\n\tconst int offY2[8] = { 1, -4, -2, 0, 3, 3, 5, 0 }; // for the left handed weapons\n\tconst int offX3[8] = { 0, 0, 2, 2, 0, 0, 0, 0 }; // for the weapons (muton)\n\tconst int offY3[8] = { -3, -3, -1, -1, -1, -3, -3, -2 }; // for the weapons (muton)\n\tconst int offX4[8] = { -8, 2, 7, 14, 7, -2, -4, -8 }; // for the left handed weapons\n\tconst int offY4[8] = { -3, -3, -1, 0, 3, 3, 0, 1 }; // for the left handed weapons\n\tconst int offX5[8] = { -1, 1, 1, 2, 0, -1, 0, 0 }; // for the weapons (muton)\n\tconst int offY5[8] = { 1, -1, -1, -1, -1, -1, -3, 0 }; // for the weapons (muton)\n\tconst int offX6[8] = { 0, 6, 6, 12, -4, -5, -5, -13 }; // for the left handed rifles\n\tconst int offY6[8] = { -4, -4, -1, 0, 5, 0, 1, 0 }; // for the left handed rifles\n\tconst int offX7[8] = { 0, 6, 8, 12, 2, -5, -5, -13 }; // for the left handed rifles (muton)\n\tconst int offY7[8] = { -4, -6, -1, 0, 3, 0, 1, 0 }; // for the left handed rifles (muton)\n\tconst int offYKneel = 4;\n\tconst int offXAiming = 0;\n\tconst int soldierHeight = 22;\n\n\tconst int unitDir = _unit->getDirection();\n\tconst int walkPhase = _unit->getWalkingPhase();\n\n\tif (_unit->getStatus() == STATUS_COLLAPSING)\n\t{\n\t\tPart coll{ BODYPART_COLLAPSING };\n\t\tselectUnit(coll, die, _unit->getFallingPhase());\n\t\tblitBody(coll);\n\t\treturn;\n\t}\n\tif (_drawingRoutine == 0 || _helmet)\n\t{\n\t\tif ((_unit->getGender() == GENDER_FEMALE && _unit->getArmor()->getForcedTorso() != TORSO_ALWAYS_MALE)\n\t\t\t|| _unit->getArmor()->getForcedTorso() == TORSO_ALWAYS_FEMALE)\n\t\t{\n\t\t\tselectUnit(torso, femaleTorso, unitDir);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tselectUnit(torso, maleTorso, unitDir);\n\t\t}\n\t}\n\telse\n\t{\n\t\tif (_unit->getGender() == GENDER_FEMALE)\n\t\t{\n\t\t\tselectUnit(torso, femaleTorso, unitDir);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tselectUnit(torso, maleTorso, unitDir);\n\t\t}\n\t}\n\n\n\t// when walking, torso(fixed sprite) has to be animated up/down\n\tif (_unit->getStatus() == STATUS_WALKING)\n\t{\n\t\tif (_drawingRoutine == 10)\n\t\t\ttorsoHandsWeaponY = mutonYoffWalk[walkPhase];\n\t\telse if (_drawingRoutine == 13 || _drawingRoutine == 14)\n\t\t\ttorsoHandsWeaponY = YoffWalk[walkPhase]+1;\n\t\telse if (_drawingRoutine == 15)\n\t\t\ttorsoHandsWeaponY = aquatoidYoffWalk[walkPhase];\n\t\telse\n\t\t\ttorsoHandsWeaponY = YoffWalk[walkPhase];\n\t\ttorso.offY = (torsoHandsWeaponY);\n\t\tselectUnit(legs, legsWalk, 24 * unitDir + walkPhase);\n\t\tselectUnit(leftArm, larmWalk, 24 * unitDir + walkPhase);\n\t\tselectUnit(rightArm, rarmWalk, 24 * unitDir + walkPhase);\n\t\tif (_drawingRoutine == 10 && unitDir == 3)\n\t\t{\n\t\t\tleftArm.offY = (-1);\n\t\t}\n\t}\n\telse\n\t{\n\t\tif (_unit->isKneeled())\n\t\t{\n\t\t\tselectUnit(legs, legsKneel, unitDir);\n\t\t}\n\t\telse if (_unit->isFloating() && _unit->getMovementType() == MT_FLY)\n\t\t{\n\t\t\tselectUnit(legs, legsFloat, unitDir);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tselectUnit(legs, legsStand, unitDir);\n\t\t}\n\t\tselectUnit(leftArm, larmStand, unitDir);\n\t\tselectUnit(rightArm, rarmStand, unitDir);\n\t}\n\n\tsortRifles();\n\n\t// holding an item\n\tif (_itemR)\n\t{\n\t\t// draw handob item\n\t\tif (_unit->getStatus() == STATUS_AIMING && _itemR->getRules()->isTwoHanded())\n\t\t{\n\t\t\tint dir = (unitDir + 2)%8;\n\t\t\tselectItem(itemR, _itemR, dir);\n\t\t\titemR.offX = (offX[unitDir]);\n\t\t\titemR.offY = (offY[unitDir]);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tselectItem(itemR, _itemR, unitDir);\n\t\t\tif (_drawingRoutine == 10)\n\t\t\t{\n\t\t\t\tif (_itemR->getRules()->isTwoHanded())\n\t\t\t\t{\n\t\t\t\t\titemR.offX = (offX3[unitDir]);\n\t\t\t\t\titemR.offY = (offY3[unitDir]);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\titemR.offX = (offX5[unitDir]);\n\t\t\t\t\titemR.offY = (offY5[unitDir]);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\titemR.offX = (0);\n\t\t\t\titemR.offY = (0);\n\t\t\t}\n\t\t}\n\n\t\t// draw arms holding the item\n\t\tif (_itemR->getRules()->isTwoHanded())\n\t\t{\n\t\t\tselectUnit(leftArm, larm2H, unitDir);\n\t\t\tif (_unit->getStatus() == STATUS_AIMING)\n\t\t\t{\n\t\t\t\tselectUnit(rightArm, rarmShoot, unitDir);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tselectUnit(rightArm, rarm2H, unitDir);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (_drawingRoutine == 10)\n\t\t\t\tselectUnit(rightArm, rarm2H, unitDir);\n\t\t\telse\n\t\t\t\tselectUnit(rightArm, rarm1H, unitDir);\n\t\t}\n\n\n\t\t// the fixed arm(s) have to be animated up/down when walking\n\t\tif (_unit->getStatus() == STATUS_WALKING)\n\t\t{\n\t\t\titemR.offY = (itemR.offY + torsoHandsWeaponY);\n\t\t\trightArm.offY = (torsoHandsWeaponY);\n\t\t\tif (_itemR->getRules()->isTwoHanded())\n\t\t\t\tleftArm.offY = (torsoHandsWeaponY);\n\t\t}\n\t}\n\t//if we are left handed or dual wielding...\n\tif (_itemL)\n\t{\n\t\tselectUnit(leftArm, larm2H, unitDir);\n\t\tselectItem(itemL, _itemL, unitDir);\n\t\tif (!_itemL->getRules()->isTwoHanded())\n\t\t{\n\t\t\tif (_drawingRoutine == 10)\n\t\t\t{\n\t\t\t\titemL.offX = (offX4[unitDir]);\n\t\t\t\titemL.offY = (offY4[unitDir]);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\titemL.offX = (offX2[unitDir]);\n\t\t\t\titemL.offY = (offY2[unitDir]);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\titemL.offX = (0);\n\t\t\titemL.offY = (0);\n\t\t\tselectUnit(rightArm, rarm2H, unitDir);\n\t\t}\n\n\t\tif (_unit->getStatus() == STATUS_AIMING && _itemL->getRules()->isTwoHanded())\n\t\t{\n\t\t\tint dir = (unitDir + 2)%8;\n\t\t\tselectItem(itemL, _itemL, dir);\n\t\t\tif (_drawingRoutine == 10)\n\t\t\t{\n\t\t\t\titemL.offX = (offX7[unitDir]);\n\t\t\t\titemL.offY = (offY7[unitDir]);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\titemL.offX = (offX6[unitDir]);\n\t\t\t\titemL.offY = (offY6[unitDir]);\n\t\t\t}\n\t\t\tselectUnit(rightArm, rarmShoot, unitDir);\n\t\t}\n\n\t\tif (_unit->getStatus() == STATUS_WALKING)\n\t\t{\n\t\t\titemL.offY = (itemL.offY + torsoHandsWeaponY);\n\t\t\tleftArm.offY = (torsoHandsWeaponY);\n\t\t\tif (_itemL->getRules()->isTwoHanded())\n\t\t\t\trightArm.offY = (torsoHandsWeaponY);\n\t\t}\n\t}\n\t// offset everything but legs when kneeled\n\tif (_unit->isKneeled())\n\t{\n\t\tint offsetTFTD = (_drawingRoutine == 13) ? 1 : 0; // tftd torsos are stubby.\n\t\tleftArm.offY = (offYKneel + offsetTFTD);\n\t\trightArm.offY = (offYKneel + offsetTFTD);\n\t\ttorso.offY = (offYKneel + offsetTFTD);\n\t\titemR.offY = (itemR.offY + offYKneel + offsetTFTD);\n\t\titemL.offY = (itemL.offY + offYKneel + offsetTFTD);\n\t}\n\telse if (_unit->getStatus() != STATUS_WALKING)\n\t{\n\t\tleftArm.offY = (0);\n\t\trightArm.offY = (0);\n\t\ttorso.offY = (0);\n\t}\n\n\t// items are calculated for soldier height (22) - some aliens are smaller, so item is drawn lower.\n\tif (itemR)\n\t{\n\t\titemR.offY = (itemR.offY + (soldierHeight - _unit->getStandHeight()));\n\t}\n\tif (itemL)\n\t{\n\t\titemL.offY = (itemL.offY + (soldierHeight - _unit->getStandHeight()));\n\t}\n\n\tif (_unit->getStatus() == STATUS_AIMING)\n\t{\n\t\ttorso.offX = (offXAiming);\n\t\tlegs.offX = (offXAiming);\n\t\tleftArm.offX = (offXAiming);\n\t\trightArm.offX = (offXAiming);\n\t\tif (itemR)\n\t\t\titemR.offX = (itemR.offX + offXAiming);\n\t\tif (itemL)\n\t\t\titemL.offX = (itemL.offX + offXAiming);\n\t}\n\telse if (!itemR && _drawingRoutine == 10 && _unit->getStatus() == STATUS_WALKING && unitDir == 2)\n\t{\n\t\trightArm.offX = (-6);\n\t}\n\n\t// blit order depends on unit direction, and whether we are holding a 2 handed weapon.\n\tswitch (unitDir)\n\t{\n\tcase 0: blitItem(itemR); blitItem(itemL); blitBody(leftArm); blitBody(legs); blitBody(torso); blitBody(rightArm); break;\n\tcase 1: blitBody(leftArm); blitBody(legs); blitItem(itemL); blitBody(torso); blitItem(itemR); blitBody(rightArm); break;\n\tcase 2: blitBody(leftArm); blitBody(legs); blitBody(torso); blitItem(itemL); blitItem(itemR); blitBody(rightArm); break;\n\tcase 3:\n\t\tif (_unit->getStatus() != STATUS_AIMING  && ((_itemR && _itemR->getRules()->isTwoHanded()) || (_itemL && _itemL->getRules()->isTwoHanded())))\n\t\t{\n\t\t\tblitBody(legs); blitBody(torso); blitBody(leftArm); blitItem(itemR); blitItem(itemL); blitBody(rightArm);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tblitBody(legs); blitBody(torso); blitBody(leftArm); blitBody(rightArm); blitItem(itemR); blitItem(itemL);\n\t\t}\n\t\tbreak;\n\tcase 4:\tblitBody(legs); blitBody(rightArm); blitBody(torso); blitBody(leftArm); blitItem(itemR); blitItem(itemL);\tbreak;\n\tcase 5:\n\t\tif (_unit->getStatus() != STATUS_AIMING  && ((_itemR && _itemR->getRules()->isTwoHanded()) || (_itemL && _itemL->getRules()->isTwoHanded())))\n\t\t{\n\t\t\tblitBody(rightArm); blitBody(legs); blitBody(torso); blitBody(leftArm); blitItem(itemR); blitItem(itemL);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tblitBody(rightArm); blitBody(legs); blitItem(itemR); blitItem(itemL); blitBody(torso); blitBody(leftArm);\n\t\t}\n\t\tbreak;\n\tcase 6: blitBody(rightArm); blitItem(itemR); blitItem(itemL); blitBody(legs); blitBody(torso); blitBody(leftArm); break;\n\tcase 7:\n\t\tif (_unit->getStatus() != STATUS_AIMING  && ((_itemR && _itemR->getRules()->isTwoHanded()) || (_itemL && _itemL->getRules()->isTwoHanded())))\n\t\t{\n\t\t\tblitBody(rightArm); blitItem(itemR); blitItem(itemL); blitBody(leftArm); blitBody(legs); blitBody(torso);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tblitItem(itemR); blitItem(itemL); blitBody(leftArm); blitBody(rightArm); blitBody(legs); blitBody(torso);\n\t\t}\n\t\tbreak;\n\t}\n}\n\n\n/**\n * Drawing routine for floaters.\n */\nvoid UnitSprite::drawRoutine1()\n{\n\tPart torso{ BODYPART_TORSO }, leftArm{ BODYPART_LEFTARM }, rightArm{ BODYPART_RIGHTARM }, itemR{ BODYPART_ITEM_RIGHTHAND }, itemL{ BODYPART_ITEM_LEFTHAND };\n\t// magic numbers\n\tconstexpr static int stand = 16, walk = 24, die = 64;\n\tconstexpr static int larm = 8, rarm = 0, larm2H = 67, rarm2H = 75, rarmShoot = 83, rarm1H= 91; // note that arms are switched vs \"normal\" sheets\n\tconstexpr static int yoffWalk[8] = {0, 0, 0, 0, 0, 0, 0, 0}; // bobbing up and down\n\tconstexpr static int offX[8] = { 8, 10, 7, 4, -9, -11, -7, -3 }; // for the weapons\n\tconstexpr static int offY[8] = { -6, -3, 0, 2, 0, -4, -7, -9 }; // for the weapons\n\tconstexpr static int offX2[8] = { -8, 3, 7, 13, 6, -3, -5, -13 }; // for the weapons\n\tconstexpr static int offY2[8] = { 1, -4, -1, 0, 3, 3, 5, 0 }; // for the weapons\n\tconstexpr static int offX3[8] = { 0, 6, 6, 12, -4, -5, -5, -13 }; // for the left handed rifles\n\tconstexpr static int offY3[8] = { -4, -4, -1, 0, 5, 0, 1, 0 }; // for the left handed rifles\n\tconstexpr static int offXAiming = 0;\n\n\tif (_unit->getStatus() == STATUS_COLLAPSING)\n\t{\n\t\tPart coll{ BODYPART_COLLAPSING };\n\t\tselectUnit(coll, die, _unit->getFallingPhase());\n\t\tblitBody(coll);\n\t\treturn;\n\t}\n\n\tconst int unitDir = _unit->getDirection();\n\tconst int walkPhase = _unit->getWalkingPhase();\n\n\tselectUnit(leftArm, larm, unitDir);\n\tselectUnit(rightArm, rarm, unitDir);\n\t// when walking, torso(fixed sprite) has to be animated up/down\n\tif (_unit->getStatus() == STATUS_WALKING)\n\t{\n\t\tselectUnit(torso, walk, (5 * unitDir) + (walkPhase / 1.6)); // floater only has 5 walk animations instead of 8\n\t\ttorso.offY = (yoffWalk[walkPhase]);\n\t}\n\telse\n\t{\n\t\tselectUnit(torso, stand, unitDir);\n\t}\n\n\tsortRifles();\n\n\t// holding an item\n\tif (_itemR)\n\t{\n\t\t// draw handob item\n\t\tif (_unit->getStatus() == STATUS_AIMING && _itemR->getRules()->isTwoHanded())\n\t\t{\n\t\t\tint dir = (_unit->getDirection() + 2)%8;\n\t\t\tselectItem(itemR, _itemR, dir);\n\t\t\titemR.offX = (offX[unitDir]);\n\t\t\titemR.offY = (offY[unitDir]);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tselectItem(itemR, _itemR, unitDir);\n\t\t\titemR.offX = (0);\n\t\t\titemR.offY = (0);\n\t\t}\n\t\t// draw arms holding the item\n\t\tif (_itemR->getRules()->isTwoHanded())\n\t\t{\n\t\t\tselectUnit(leftArm, larm2H, unitDir);\n\t\t\tif (_unit->getStatus() == STATUS_AIMING)\n\t\t\t{\n\t\t\t\tselectUnit(rightArm, rarmShoot, unitDir);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tselectUnit(rightArm, rarm2H, unitDir);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tselectUnit(rightArm, rarm1H, unitDir);\n\t\t}\n\t}\n\n\t//if we are left handed or dual wielding...\n\tif (_itemL)\n\t{\n\t\tselectUnit(leftArm, larm2H, unitDir);\n\t\tselectItem(itemL, _itemL, unitDir);\n\t\tif (!_itemL->getRules()->isTwoHanded())\n\t\t{\n\t\t\titemL.offX = (offX2[unitDir]);\n\t\t\titemL.offY = (offY2[unitDir]);\n\t\t}\n\t\telse\n\t\t{\n\t\t\titemL.offX = (0);\n\t\t\titemL.offY = (0);\n\t\t\tselectUnit(rightArm, rarm2H, unitDir);\n\t\t}\n\n\t\tif (_unit->getStatus() == STATUS_AIMING && _itemL->getRules()->isTwoHanded())\n\t\t{\n\t\t\tint dir = (unitDir + 2)%8;\n\t\t\tselectItem(itemL, _itemL, dir);\n\t\t\titemL.offX = (offX3[unitDir]);\n\t\t\titemL.offY = (offY3[unitDir]);\n\t\t\tselectUnit(rightArm, rarmShoot, unitDir);\n\t\t}\n\n\t\tif (_unit->getStatus() == STATUS_WALKING)\n\t\t{\n\t\t\tleftArm.offY = (yoffWalk[walkPhase]);\n\t\t\titemL.offY = (itemL.offY + yoffWalk[walkPhase]);\n\t\t\tif (_itemL->getRules()->isTwoHanded())\n\t\t\t\trightArm.offY = (yoffWalk[walkPhase]);\n\t\t}\n\t}\n\n\tif (_unit->getStatus() != STATUS_WALKING)\n\t{\n\t\tleftArm.offY = (0);\n\t\trightArm.offY = (0);\n\t\ttorso.offY = (0);\n\t}\n\tif (_unit->getStatus() == STATUS_AIMING)\n\t{\n\t\ttorso.offX = (offXAiming);\n\t\tleftArm.offX = (offXAiming);\n\t\trightArm.offX = (offXAiming);\n\t\tif (itemR)\n\t\t\titemR.offX = (itemR.offX + offXAiming);\n\t\tif (itemL)\n\t\t\titemL.offX = (itemL.offX + offXAiming);\n\t}\n\t// blit order depends on unit direction.\n\tswitch (unitDir)\n\t{\n\tcase 0: blitItem(itemR); blitItem(itemL); blitBody(leftArm); blitBody(torso); blitBody(rightArm); break;\n\tcase 1: blitBody(leftArm); blitBody(torso); blitBody(rightArm); blitItem(itemR); blitItem(itemL); break;\n\tcase 2: blitBody(leftArm); blitBody(torso); blitBody(rightArm); blitItem(itemR); blitItem(itemL); break;\n\tcase 3: blitBody(torso); blitBody(leftArm); blitBody(rightArm); blitItem(itemR); blitItem(itemL); break;\n\tcase 4: blitBody(torso); blitBody(leftArm); blitBody(rightArm); blitItem(itemR); blitItem(itemL); break;\n\tcase 5: blitBody(rightArm); blitBody(torso); blitBody(leftArm); blitItem(itemR); blitItem(itemL); break;\n\tcase 6: blitBody(rightArm); blitItem(itemR); blitItem(itemL); blitBody(torso); blitBody(leftArm); break;\n\tcase 7: blitBody(rightArm); blitItem(itemR); blitItem(itemL); blitBody(leftArm); blitBody(torso); break;\n\t}\n}\n\n/**\n * Drawing routine for XCom tanks.\n */\nvoid UnitSprite::drawRoutine2()\n{\n\tconstexpr static int offX[8] = { -2, -7, -5, 0, 5, 7, 2, 0 }; // hovertank offsets\n\tconstexpr static int offy[8] = { -1, -3, -4, -5, -4, -3, -1, -1 }; // hovertank offsets\n\n\tPart s{ BODYPART_LARGE_TORSO + _part };\n\n\tconst int hoverTank = _unit->getOriginalMovementType() == MT_FLY ? 32 : 0;\n\tconst int turret = _unit->getTurretType();\n\n\t// draw the animated propulsion below the hwp\n\tif (hoverTank != 0)\n\t{\n\t\tif (_part > 0)\n\t\t{\n\t\t\tPart p{ BODYPART_LARGE_PROPULSION + _part };\n\t\t\tselectUnit(p, 104 + ((_part-1) * 8), _animationFrame % 8);\n\t\t\tblitBody(p);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// draw nothing, can be override by script\n\t\t\tPart p{ BODYPART_LARGE_PROPULSION + _part };\n\t\t\tselectUnit(p, InvalidSpriteIndex, _animationFrame % 8);\n\t\t\tblitBody(p);\n\t\t}\n\t}\n\n\t// draw the tank itself\n\tselectUnit(s, hoverTank + (_part * 8), _unit->getDirection());\n\tblitBody(s);\n\n\t// draw the turret, together with the last part\n\tif (_part == 3 && turret != -1)\n\t{\n\t\tPart t{ BODYPART_LARGE_TURRET };\n\t\tselectUnit(t, 64 + (turret * 8), _unit->getTurretDirection());\n\t\tint turretOffsetX = 0;\n\t\tint turretOffsetY = -4;\n\t\tif (hoverTank)\n\t\t{\n\t\t\tturretOffsetX += offX[_unit->getDirection()];\n\t\t\tturretOffsetY += offy[_unit->getDirection()];\n\t\t}\n\t\tt.offX = (turretOffsetX);\n\t\tt.offY = (turretOffsetY);\n\t\tblitBody(t);\n\t}\n\n}\n\n/**\n * Drawing routine for cyberdiscs. (3)\n * and helicopters (22)\n */\nvoid UnitSprite::drawRoutine3()\n{\n\tPart s{ BODYPART_LARGE_TORSO + _part };\n\n\t// draw the animated propulsion below the hwp\n\tif (_drawingRoutine == 3)\n\t{\n\t\tif (_part > 0)\n\t\t{\n\t\t\tPart p{ BODYPART_LARGE_PROPULSION + _part };\n\t\t\tselectUnit(p, 32 + ((_part-1) * 8), _animationFrame % 8);\n\t\t\tblitBody(p);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// draw nothing, can be override by script\n\t\t\tPart p{ BODYPART_LARGE_PROPULSION + _part };\n\t\t\tselectUnit(p, InvalidSpriteIndex, _animationFrame % 8);\n\t\t\tblitBody(p);\n\t\t}\n\t}\n\n\tselectUnit(s, (_part * 8), _unit->getDirection());\n\n\tblitBody(s);\n\n\t// draw the animated propulsion above the hwp\n\tif (_drawingRoutine == 22)\n\t{\n\t\tif (_part > 0)\n\t\t{\n\t\t\tPart p{ BODYPART_LARGE_PROPULSION + _part };\n\t\t\tselectUnit(p, 32 + ((_part-1) * 8), _animationFrame % 8);\n\t\t\tblitBody(p);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// draw nothing, can be override by script\n\t\t\tPart p{ BODYPART_LARGE_PROPULSION + _part };\n\t\t\tselectUnit(p, InvalidSpriteIndex, _animationFrame % 8);\n\t\t\tblitBody(p);\n\t\t}\n\t}\n}\n\n/**\n * Drawing routine for civilians, ethereals, zombies (routine 4),\n * tftd civilians, tftd zombies (routine 17), more tftd civilians (routine 18).\n * Very easy: first 8 is standing positions, then 8 walking sequences of 8, finally death sequence of 3\n */\nvoid UnitSprite::drawRoutine4()\n{\n\tPart s{ BODYPART_TORSO }, itemR{ BODYPART_ITEM_RIGHTHAND }, itemL{ BODYPART_ITEM_LEFTHAND };\n\tint stand = 0, walk = 8, die = 72;\n\tconstexpr static int offX[8] = { 8, 10, 7, 4, -9, -11, -7, -3 }; // for the weapons\n\tconstexpr static int offY[8] = { -6, -3, 0, 2, 0, -4, -7, -9 }; // for the weapons\n\tconstexpr static int offX2[8] = { -8, 3, 5, 12, 6, -1, -5, -13 }; // for the weapons\n\tconstexpr static int offY2[8] = { 1, -4, -2, 0, 3, 3, 5, 0 }; // for the weapons\n\tconstexpr static int offX3[8] = { 0, 6, 6, 12, -4, -5, -5, -13 }; // for the left handed rifles\n\tconstexpr static int offY3[8] = { -4, -4, -1, 0, 5, 0, 1, 0 }; // for the left handed rifles\n\tconstexpr static int standConvert[8] = { 3, 2, 1, 0, 7, 6, 5, 4 }; // array for converting stand frames for some tftd civilians\n\tconstexpr static int offXAiming = 0;\n\n\tif (_drawingRoutine == 17) // tftd civilian - first set\n\t{\n\t\tstand = 64;\n\t\twalk = 0;\n\t}\n\telse if (_drawingRoutine == 18) // tftd civilian - second set\n\t{\n\t\tstand = 140;\n\t\twalk = 76;\n\t\tdie = 148;\n\t}\n\n\tconst int unitDir = _unit->getDirection();\n\n\tif (_unit->getStatus() == STATUS_COLLAPSING)\n\t{\n\t\tPart coll{ BODYPART_COLLAPSING };\n\t\tselectUnit(coll, die, _unit->getFallingPhase());\n\t\tblitBody(coll);\n\t\treturn;\n\t}\n\telse if (_unit->getStatus() == STATUS_WALKING)\n\t{\n\t\tselectUnit(s, walk, (8 * unitDir) + _unit->getWalkingPhase());\n\t}\n\telse if (_drawingRoutine != 17)\n\t{\n\t\tselectUnit(s, stand, unitDir);\n\t}\n\telse\n\t{\n\t\tselectUnit(s, stand, standConvert[unitDir]);\n\t}\n\n\tsortRifles();\n\n\tif (_itemR && !_itemR->getRules()->isFixed())\n\t{\n\t\t// draw handob item\n\t\tif (_unit->getStatus() == STATUS_AIMING && _itemR->getRules()->isTwoHanded())\n\t\t{\n\t\t\tint dir = (unitDir + 2)%8;\n\t\t\tselectItem(itemR, _itemR, dir);\n\t\t\titemR.offX = (offX[unitDir]);\n\t\t\titemR.offY = (offY[unitDir]);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (_itemR->getSlot()->isRightHand())\n\t\t\t{\n\t\t\t\tselectItem(itemR, _itemR, unitDir);\n\t\t\t\titemR.offX = (0);\n\t\t\t\titemR.offY = (0);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tselectItem(itemR, _itemR, unitDir);\n\t\t\t\titemR.offX = (offX2[unitDir]);\n\t\t\t\titemR.offY = (offY2[unitDir]);\n\t\t\t}\n\t\t}\n\t}\n\n\t//if we are dual wielding...\n\tif (_itemL && !_itemL->getRules()->isFixed())\n\t{\n\t\tselectItem(itemL, _itemL, unitDir);\n\t\tif (!_itemL->getRules()->isTwoHanded())\n\t\t{\n\t\t\titemL.offX = (offX2[unitDir]);\n\t\t\titemL.offY = (offY2[unitDir]);\n\t\t}\n\t\telse\n\t\t{\n\t\t\titemL.offX = (0);\n\t\t\titemL.offY = (0);\n\t\t}\n\n\t\tif (_unit->getStatus() == STATUS_AIMING && _itemL->getRules()->isTwoHanded())\n\t\t{\n\t\t\tint dir = (unitDir + 2)%8;\n\t\t\tselectItem(itemL, _itemL, dir);\n\t\t\titemL.offX = (offX3[unitDir]);\n\t\t\titemL.offY = (offY3[unitDir]);\n\t\t}\n\t}\n\n\tif (_unit->getStatus() == STATUS_AIMING)\n\t{\n\t\ts.offX = (offXAiming);\n\t\tif (itemR)\n\t\t\titemR.offX = (itemR.offX + offXAiming);\n\t\tif (itemL)\n\t\t\titemL.offX = (itemL.offX + offXAiming);\n\t}\n\tswitch (unitDir)\n\t{\n\tcase 0: blitItem(itemL); blitItem(itemR); blitBody(s); break;\n\tcase 1: blitItem(itemL); blitBody(s); blitItem(itemR); break;\n\tcase 2: blitBody(s); blitItem(itemL); blitItem(itemR); break;\n\tcase 3: blitBody(s); blitItem(itemR); blitItem(itemL); break;\n\tcase 4: blitBody(s); blitItem(itemR); blitItem(itemL); break;\n\tcase 5: blitItem(itemR); blitBody(s); blitItem(itemL); break;\n\tcase 6: blitItem(itemR); blitBody(s); blitItem(itemL); break;\n\tcase 7: blitItem(itemR); blitItem(itemL); blitBody(s); break;\n\t}\n}\n\n/**\n * Drawing routine for sectopods and reapers.\n */\nvoid UnitSprite::drawRoutine5()\n{\n\tPart s{ BODYPART_LARGE_TORSO + _part };\n\n\tif (_unit->getStatus() == STATUS_WALKING)\n\t{\n\t\tselectUnit(s, 32 + (_part * 4), (_unit->getDirection() * 16) + ((_unit->getWalkingPhase() / 2) % 4));\n\t}\n\telse\n\t{\n\t\tselectUnit(s, 0 + (_part * 8), _unit->getDirection());\n\t}\n\n\tblitBody(s);\n}\n\n/**\n * Drawing routine for snakemen.\n */\nvoid UnitSprite::drawRoutine6()\n{\n\tPart torso{ BODYPART_TORSO }, legs{ BODYPART_LEGS }, leftArm{ BODYPART_LEFTARM }, rightArm{ BODYPART_RIGHTARM }, itemR{ BODYPART_ITEM_RIGHTHAND }, itemL{ BODYPART_ITEM_LEFTHAND };\n\t// magic numbers\n\tconstexpr static int Torso = 24, legsStand = 16, die = 96;\n\tconstexpr static int larmStand = 0, rarmStand = 8, rarm1H = 99, larm2H = 107, rarm2H = 115, rarmShoot = 123;\n\tconstexpr static int legsWalk = 32;\n\tconstexpr static int yoffWalk[8] = {3, 3, 2, 1, 0, 0, 1, 2}; // bobbing up and down\n\tconstexpr static int xoffWalka[8] = {0, 0, 1, 2, 3, 3, 2, 1};\n\tconstexpr static int xoffWalkb[8] = {0, 0, -1, -2, -3, -3, -2, -1};\n\tconstexpr static int yoffStand[8] = {2, 1, 1, 0, 0, 0, 0, 0};\n\tconstexpr static int offX[8] = { 8, 10, 5, 2, -8, -10, -5, -2 }; // for the weapons\n\tconstexpr static int offY[8] = { -6, -3, 0, 0, 2, -3, -7, -9 }; // for the weapons\n\tconstexpr static int offX2[8] = { -8, 2, 7, 13, 7, 0, -3, -15 }; // for the weapons\n\tconstexpr static int offY2[8] = { 1, -4, -2, 0, 3, 3, 5, 0 }; // for the weapons\n\tconstexpr static int offX3[8] = { 0, 6, 6, 12, -4, -5, -5, -13 }; // for the left handed rifles\n\tconstexpr static int offY3[8] = { -4, -4, -1, 0, 5, 0, 1, 0 }; // for the left handed rifles\n\tconstexpr static int offXAiming = 0;\n\n\tif (_unit->getStatus() == STATUS_COLLAPSING)\n\t{\n\t\tPart coll{ BODYPART_COLLAPSING };\n\t\tselectUnit(coll, die, _unit->getFallingPhase());\n\t\tblitBody(coll);\n\t\treturn;\n\t}\n\n\tconst int unitDir = _unit->getDirection();\n\tconst int walkPhase = _unit->getWalkingPhase();\n\n\tselectUnit(torso, Torso, unitDir);\n\tselectUnit(leftArm, larmStand, unitDir);\n\tselectUnit(rightArm, rarmStand, unitDir);\n\n\n\t// when walking, torso(fixed sprite) has to be animated up/down\n\tif (_unit->getStatus() == STATUS_WALKING)\n\t{\n\t\tint xoffWalk = 0;\n\t\tif (unitDir < 3)\n\t\t\txoffWalk = xoffWalka[walkPhase];\n\t\tif (unitDir < 7 && unitDir > 3)\n\t\t\txoffWalk = xoffWalkb[walkPhase];\n\t\ttorso.offY = (yoffWalk[walkPhase]);\n\t\ttorso.offX = (xoffWalk);\n\t\tselectUnit(legs, legsWalk, 8 * unitDir + walkPhase);\n\t\trightArm.offY = (yoffWalk[walkPhase]);\n\t\tleftArm.offY = (yoffWalk[walkPhase]);\n\t\trightArm.offX = (xoffWalk);\n\t\tleftArm.offX = (xoffWalk);\n\t}\n\telse\n\t{\n\t\tselectUnit(legs, legsStand, unitDir);\n\t}\n\n\tsortRifles();\n\n\t// holding an item\n\tif (_itemR)\n\t{\n\t\t// draw handob item\n\t\tif (_unit->getStatus() == STATUS_AIMING && _itemR->getRules()->isTwoHanded())\n\t\t{\n\t\t\tint dir = (unitDir + 2)%8;\n\t\t\tselectItem(itemR, _itemR, dir);\n\t\t\titemR.offX = (offX[unitDir]);\n\t\t\titemR.offY = (offY[unitDir]);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tselectItem(itemR, _itemR, unitDir);\n\t\t\titemR.offX = (0);\n\t\t\titemR.offY = (0);\n\t\t\tif (!_itemR->getRules()->isTwoHanded())\n\t\t\t{\n\t\t\t\titemR.offY = (yoffStand[unitDir]);\n\t\t\t}\n\t\t}\n\n\n\t\t// draw arms holding the item\n\t\tif (_itemR->getRules()->isTwoHanded())\n\t\t{\n\t\t\tselectUnit(leftArm, larm2H, unitDir);\n\t\t\tif (_unit->getStatus() == STATUS_AIMING)\n\t\t\t{\n\t\t\t\tselectUnit(rightArm, rarmShoot, unitDir);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tselectUnit(rightArm, rarm2H, unitDir);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tselectUnit(rightArm, rarm1H, unitDir);\n\t\t}\n\n\n\t\t// the fixed arm(s) have to be animated up/down when walking\n\t\tif (_unit->getStatus() == STATUS_WALKING)\n\t\t{\n\t\t\titemR.offY = (yoffWalk[walkPhase]);\n\t\t\trightArm.offY = (yoffWalk[walkPhase]);\n\t\t\tif (_itemR->getRules()->isTwoHanded())\n\t\t\t\tleftArm.offY = (yoffWalk[walkPhase]);\n\t\t}\n\t}\n\t//if we are left handed or dual wielding...\n\tif (_itemL)\n\t{\n\t\tselectUnit(leftArm, larm2H, unitDir);\n\t\tselectItem(itemL, _itemL, unitDir);\n\t\tif (!_itemL->getRules()->isTwoHanded())\n\t\t{\n\t\t\titemL.offX = (offX2[unitDir]);\n\t\t\titemL.offY = (offY2[unitDir]);\n\t\t}\n\t\telse\n\t\t{\n\t\t\titemL.offX = (0);\n\t\t\titemL.offY = (0);\n\t\t\tif (!_itemL->getRules()->isTwoHanded())\n\t\t\t{\n\t\t\t\titemL.offY = (yoffStand[unitDir]);\n\t\t\t}\n\t\t\tselectUnit(rightArm, rarm2H, unitDir);\n\t\t}\n\n\t\tif (_unit->getStatus() == STATUS_AIMING && _itemL->getRules()->isTwoHanded())\n\t\t{\n\t\t\tint dir = (unitDir + 2)%8;\n\t\t\tselectItem(itemL, _itemL, dir);\n\t\t\titemL.offX = (offX3[unitDir]);\n\t\t\titemL.offY = (offY3[unitDir]);\n\t\t\tselectUnit(rightArm, rarmShoot, unitDir);\n\t\t}\n\n\t\tif (_unit->getStatus() == STATUS_WALKING)\n\t\t{\n\t\t\tleftArm.offY = (yoffWalk[walkPhase]);\n\t\t\titemL.offY = (offY2[unitDir] + yoffWalk[walkPhase]);\n\t\t\tif (_itemL->getRules()->isTwoHanded())\n\t\t\t\trightArm.offY = (yoffWalk[walkPhase]);\n\t\t}\n\t}\n\t// offset everything but legs when kneeled\n\tif (_unit->getStatus() != STATUS_WALKING)\n\t{\n\t\tleftArm.offY = (0);\n\t\trightArm.offY = (0);\n\t\ttorso.offY = (0);\n\t}\n\tif (_unit->getStatus() == STATUS_AIMING)\n\t{\n\t\ttorso.offX = (offXAiming);\n\t\tlegs.offX = (offXAiming);\n\t\tleftArm.offX = (offXAiming);\n\t\trightArm.offX = (offXAiming);\n\t\tif (itemR)\n\t\t\titemR.offX = (itemR.offX + offXAiming);\n\t\tif (itemL)\n\t\t\titemL.offX = (itemL.offX + offXAiming);\n\t}\n\n\t// blit order depends on unit direction.\n\tswitch (unitDir)\n\t{\n\tcase 0: blitItem(itemR); blitItem(itemL); blitBody(leftArm); blitBody(legs); blitBody(torso); blitBody(rightArm); break;\n\tcase 1: blitBody(leftArm); blitBody(legs); blitItem(itemL); blitBody(torso); blitItem(itemR); blitBody(rightArm); break;\n\tcase 2: blitBody(leftArm); blitBody(legs); blitBody(torso); blitBody(rightArm); blitItem(itemR); blitItem(itemL); break;\n\tcase 3: blitBody(legs); blitBody(torso); blitBody(leftArm); blitBody(rightArm); blitItem(itemR); blitItem(itemL); break;\n\tcase 4: blitBody(rightArm); blitBody(legs); blitBody(torso); blitBody(leftArm); blitItem(itemR); blitItem(itemL); break;\n\tcase 5: blitBody(rightArm); blitBody(legs); blitBody(torso); blitBody(leftArm); blitItem(itemR); blitItem(itemL); break;\n\tcase 6: blitBody(rightArm); blitBody(legs); blitItem(itemR); blitItem(itemL); blitBody(torso); blitBody(leftArm); break;\n\tcase 7: blitItem(itemR); blitItem(itemL); blitBody(leftArm); blitBody(rightArm); blitBody(legs); blitBody(torso); break;\n\t}\n}\n\n/**\n * Drawing routine for chryssalid.\n */\nvoid UnitSprite::drawRoutine7()\n{\n\tPart torso{ BODYPART_TORSO }, legs{ BODYPART_LEGS }, leftArm{ BODYPART_LEFTARM }, rightArm{ BODYPART_RIGHTARM };\n\t// magic numbers\n\tconstexpr static int Torso = 24, legsStand = 16, die = 224;\n\tconstexpr static int larmStand = 0, rarmStand = 8;\n\tconstexpr static int legsWalk = 48;\n\tconstexpr static int larmWalk = 32;\n\tconstexpr static int rarmWalk = 40;\n\tconstexpr static int yoffWalk[8] = {1, 0, -1, 0, 1, 0, -1, 0}; // bobbing up and down\n\n\tif (_unit->getStatus() == STATUS_COLLAPSING)\n\t{\n\t\tPart coll{ BODYPART_COLLAPSING };\n\t\tselectUnit(coll, die, _unit->getFallingPhase());\n\t\tblitBody(coll);\n\t\treturn;\n\t}\n\n\tconst int unitDir = _unit->getDirection();\n\tconst int walkPhase = _unit->getWalkingPhase();\n\n\tselectUnit(torso, Torso, unitDir);\n\n\n\t// when walking, torso(fixed sprite) has to be animated up/down\n\tif (_unit->getStatus() == STATUS_WALKING)\n\t{\n\t\ttorso.offY = (yoffWalk[walkPhase]);\n\t\tselectUnit(legs, legsWalk, 24 * unitDir + walkPhase);\n\t\tselectUnit(leftArm, larmWalk, 24 * unitDir + walkPhase);\n\t\tselectUnit(rightArm, rarmWalk, 24 * unitDir + walkPhase);\n\t}\n\telse\n\t{\n\n\t\tselectUnit(legs, legsStand, unitDir);\n\t\tselectUnit(leftArm, larmStand, unitDir);\n\t\tselectUnit(rightArm, rarmStand, unitDir);\n\t\tleftArm.offY = (0);\n\t\trightArm.offY = (0);\n\t\ttorso.offY = (0);\n\t}\n\n\t// blit order depends on unit direction\n\tswitch (unitDir)\n\t{\n\tcase 0: blitBody(leftArm); blitBody(legs); blitBody(torso); blitBody(rightArm); break;\n\tcase 1: blitBody(leftArm); blitBody(legs); blitBody(torso); blitBody(rightArm); break;\n\tcase 2: blitBody(leftArm); blitBody(legs); blitBody(torso); blitBody(rightArm); break;\n\tcase 3: blitBody(legs); blitBody(torso); blitBody(leftArm); blitBody(rightArm); break;\n\tcase 4: blitBody(rightArm); blitBody(legs); blitBody(torso); blitBody(leftArm); break;\n\tcase 5: blitBody(rightArm); blitBody(legs); blitBody(torso); blitBody(leftArm); break;\n\tcase 6: blitBody(rightArm); blitBody(legs); blitBody(torso); blitBody(leftArm); break;\n\tcase 7: blitBody(leftArm); blitBody(rightArm); blitBody(legs); blitBody(torso); break;\n\t}\n}\n\n/**\n * Drawing routine for silacoids.\n */\nvoid UnitSprite::drawRoutine8()\n{\n\tPart legs{ BODYPART_TORSO };\n\t// magic numbers\n\tconstexpr static int Body = 0, aim = 5, die = 6;\n\tconstexpr static int Pulsate[8] = { 0, 1, 2, 3, 4, 3, 2, 1 };\n\n\tselectUnit(legs, Body, Pulsate[_animationFrame % 8]);\n\n\tif (_unit->getStatus() == STATUS_COLLAPSING)\n\t{\n\t\tPart coll{ BODYPART_COLLAPSING };\n\t\tselectUnit(coll, die, _unit->getFallingPhase());\n\t\tblitBody(coll);\n\t\treturn;\n\t}\n\n\tif (_unit->getStatus() == STATUS_AIMING)\n\t\tselectUnit(legs, aim, 0);\n\n\tblitBody(legs);\n}\n\n/**\n * Drawing routine for celatids.\n */\nvoid UnitSprite::drawRoutine9()\n{\n\tPart torso{ BODYPART_TORSO };\n\t// magic numbers\n\tconstexpr static int Body = 0, die = 25;\n\n\tselectUnit(torso, Body, _animationFrame % 8);\n\n\tif (_unit->getStatus() == STATUS_COLLAPSING)\n\t{\n\t\tPart coll{ BODYPART_COLLAPSING };\n\t\tselectUnit(coll, die, _unit->getFallingPhase());\n\t\tblitBody(coll);\n\t\treturn;\n\t}\n\n\tblitBody(torso);\n}\n\n/**\n * Drawing routine for tftd tanks.\n */\nvoid UnitSprite::drawRoutine11()\n{\n\t// magic numbers\n\tconstexpr static int offTurretX[8] = { -2, -6, -5, 0, 5, 6, 2, 0 }; // turret offsets\n\tconstexpr static int offTurretYAbove[8] = { 5, 3, 0, 0, 0, 3, 5, 4 }; // turret offsets\n\tconstexpr static int offTurretYBelow[8] = { -11, -13, -16, -16, -16, -13, -11, -12 }; // turret offsets\n\n\tint body = 0;\n\tint animFrame = _unit->getWalkingPhase() % 4;\n\tif (_unit->getOriginalMovementType() == MT_FLY)\n\t{\n\t\tbody = 128;\n\t\tanimFrame = _animationFrame % 4;\n\t}\n\n\tPart s{ BODYPART_LARGE_TORSO + _part };\n\tselectUnit(s, body + (_part * 4), 16 * _unit->getDirection() + animFrame);\n\ts.offY = (4);\n\tblitBody(s);\n\n\tint turret = _unit->getTurretType();\n\t// draw the turret, overlapping all 4 parts\n\tif ((_part == 3 || _part == 0) && turret != -1 && !_unit->getFloorAbove())\n\t{\n\t\tPart t{ BODYPART_LARGE_TURRET };\n\t\tselectUnit(t, 256 + (turret * 8), _unit->getTurretDirection());\n\t\tt.offX = (offTurretX[_unit->getDirection()]);\n\t\tif (_part == 3)\n\t\t\tt.offY = (offTurretYBelow[_unit->getDirection()]);\n\t\telse\n\t\t\tt.offY = (offTurretYAbove[_unit->getDirection()]);\n\t\tblitBody(t);\n\t}\n\n}\n\n/**\n * Drawing routine for hallucinoids.\n */\nvoid UnitSprite::drawRoutine12()\n{\n\tPart s{ BODYPART_LARGE_TORSO + _part };\n\n\tselectUnit(s, (_part * 8), _animationFrame % 8);\n\n\tblitBody(s);\n}\n\n/**\n* Drawing routine for biodrones.\n*/\nvoid UnitSprite::drawRoutine16()\n{\n\tPart s{ BODYPART_TORSO };\n\t// magic numbers\n\tconstexpr static int die = 8;\n\n\tselectUnit(s, 0, _animationFrame % 8);\n\n\tif ( (_unit->getStatus() == STATUS_COLLAPSING))\n\t{\n\t\tPart coll{ BODYPART_COLLAPSING };\n\t\tselectUnit(coll, die, _unit->getFallingPhase());\n\t\tblitBody(coll);\n\t\treturn;\n\t}\n\n\tblitBody(s);\n}\n\n/**\n * Drawing routine for tentaculats.\n */\nvoid UnitSprite::drawRoutine19()\n{\n\tPart s{ BODYPART_TORSO };\n\t// magic numbers\n\tconstexpr static int stand = 0, move = 8, die = 16;\n\n\tif (_unit->getStatus() == STATUS_COLLAPSING)\n\t{\n\t\tPart coll{ BODYPART_COLLAPSING };\n\t\tselectUnit(coll, die, _unit->getFallingPhase());\n\t\tblitBody(coll);\n\t\treturn;\n\t}\n\telse if (_unit->getStatus() == STATUS_WALKING)\n\t{\n\t\tselectUnit(s, move, _unit->getDirection());\n\t}\n\telse\n\t{\n\t\tselectUnit(s, stand, _unit->getDirection());\n\t}\n\n\tblitBody(s);\n}\n\n/**\n * Drawing routine for triscenes.\n */\nvoid UnitSprite::drawRoutine20()\n{\n\tPart s{ BODYPART_LARGE_TORSO + _part };\n\n\tif (_unit->getStatus() == STATUS_WALKING)\n\t{\n\t\tselectUnit(s, (_part * 5), (_unit->getWalkingPhase()/2%4) + 5 * (4 * _unit->getDirection()));\n\t}\n\telse\n\t{\n\t\tselectUnit(s, (_part * 5), 5 * (4 * _unit->getDirection()));\n\t}\n\n\tblitBody(s);\n}\n\n/**\n * Drawing routine for xarquids.\n */\nvoid UnitSprite::drawRoutine21()\n{\n\tPart s{ BODYPART_LARGE_TORSO + _part };\n\n\tselectUnit(s, (_part * 4), (_unit->getDirection() * 16) + (_animationFrame % 4));\n\n\tblitBody(s);\n}\n\n/**\n * Determines which weapons to display in the case of two-handed weapons.\n */\nvoid UnitSprite::sortRifles()\n{\n\tif (_itemR && _itemR->getRules()->isTwoHanded())\n\t{\n\t\tif (_itemL && _itemL->getRules()->isTwoHanded())\n\t\t{\n\t\t\t_itemR = _unit->getActiveHand(_itemL, _itemR);\n\t\t\t_itemL = 0;\n\t\t}\n\t\telse if (_unit->getStatus() != STATUS_AIMING)\n\t\t{\n\t\t\t_itemL = 0;\n\t\t}\n\t}\n\telse if (_itemL && _itemL->getRules()->isTwoHanded())\n\t{\n\t\tif (_unit->getStatus() != STATUS_AIMING)\n\t\t{\n\t\t\t_itemR = 0;\n\t\t}\n\t}\n}\n\n} //namespace OpenXcom\n"
  },
  {
    "path": "src/Battlescape/UnitSprite.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/Surface.h\"\n#include \"../Engine/Script.h\"\n\nnamespace OpenXcom\n{\n\nclass BattleUnit;\nclass BattleItem;\nclass SavedBattleGame;\nclass SurfaceSet;\nclass Mod;\n\n/**\n * A class that renders a specific unit, given its render rules\n * combining the right frames from the surfaceset.\n */\nclass UnitSprite\n{\nprivate:\n\tstruct Part\n\t{\n\t\tconst Surface *src;\n\t\tint bodyPart;\n\t\tint offX;\n\t\tint offY;\n\n\t\tPart(int body, const Surface *s = nullptr) : src{ s }, bodyPart{ body }, offX{ 0 }, offY{ 0 } { }\n\n\t\tvoid operator=(const Surface *s) { src = s; }\n\t\texplicit operator bool() { return src; }\n\t};\n\n\tconst BattleUnit *_unit;\n\tconst BattleItem *_itemR, *_itemL;\n\tconst SurfaceSet *_unitSurface, *_itemSurface, *_fireSurface, *_breathSurface, *_facingArrowSurface;\n\tSurface *_dest;\n\tconst SavedBattleGame *_save;\n\tconst Mod *_mod;\n\tint _part, _animationFrame, _drawingRoutine;\n\tbool _helmet;\n\tint _red, _blue;\n\tint _x, _y, _shade, _burn;\n\tGraphSubset _mask;\n\n\t/// Drawing routine for XCom soldiers in overalls, sectoids (routine 0),\n\t/// mutons (routine 10),\n\t/// aquanauts (routine 13),\n\t/// aquatoids, calcinites, deep ones, gill men, lobster men, tasoths (routine 14).\n\tvoid drawRoutine0();\n\t/// Drawing routine for floaters.\n\tvoid drawRoutine1();\n\t/// Drawing routine for XCom tanks.\n\tvoid drawRoutine2();\n\t/// Drawing routine for cyberdiscs.\n\tvoid drawRoutine3();\n\t/// Drawing routine for civilians, ethereals, zombies (routine 4),\n\t/// tftd civilians, tftd zombies (routine 16), more tftd civilians (routine 17).\n\tvoid drawRoutine4();\n\t/// Drawing routine for sectopods and reapers.\n\tvoid drawRoutine5();\n\t/// Drawing routine for snakemen.\n\tvoid drawRoutine6();\n\t/// Drawing routine for chryssalid.\n\tvoid drawRoutine7();\n\t/// Drawing routine for silacoids.\n\tvoid drawRoutine8();\n\t/// Drawing routine for celatids.\n\tvoid drawRoutine9();\n\t/// Drawing routine for TFTD tanks.\n\tvoid drawRoutine11();\n\t/// Drawing routine for hallucinoids.\n\tvoid drawRoutine12();\n\t/// Drawing routine for biodrones.\n\tvoid drawRoutine16();\n\t/// Drawing routine for tentaculats.\n\tvoid drawRoutine19();\n\t/// Drawing routine for triscenes.\n\tvoid drawRoutine20();\n\t/// Drawing routine for xarquids.\n\tvoid drawRoutine21();\n\t/// Sort two handed sprites out.\n\tvoid sortRifles();\n\t/// Get graphic for unit part.\n\tvoid selectUnit(Part& p, int index, int offset);\n\t/// Get graphic for item part.\n\tvoid selectItem(Part& p, const BattleItem *item, int offset);\n\t/// Blit weapon sprite.\n\tvoid blitItem(Part& item);\n\t/// Blit body sprite.\n\tvoid blitBody(Part& body);\npublic:\n\t/// Creates a new UnitSprite at the specified position and size.\n\tUnitSprite(Surface* dest, const Mod* mod, const SavedBattleGame* save, int frame, bool helmet, int red, int blue);\n\t/// Cleans up the UnitSprite.\n\t~UnitSprite();\n\t/// Draws the unit.\n\tvoid draw(const BattleUnit* unit, int part, int x, int y, int shade, GraphSubset mask, bool drawFacingIndicator);\n};\n\n} //namespace OpenXcom\n\n"
  },
  {
    "path": "src/Battlescape/UnitTurnBState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"UnitTurnBState.h\"\n#include \"TileEngine.h\"\n#include \"Map.h\"\n#include \"../Savegame/BattleUnit.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/Sound.h\"\n#include \"../Engine/Options.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Sets up an UnitTurnBState.\n * @param parent Pointer to the Battlescape.\n * @param action Pointer to an action.\n */\nUnitTurnBState::UnitTurnBState(BattlescapeGame *parent, BattleAction action, bool chargeTUs) : BattleState(parent, action), _unit(0), _turret(false), _chargeTUs(chargeTUs)\n{\n\n}\n\n/**\n * Deletes the UnitTurnBState.\n */\nUnitTurnBState::~UnitTurnBState()\n{\n\n}\n\n/**\n * Initializes the state.\n */\nvoid UnitTurnBState::init()\n{\n\t_unit = _action.actor;\n\tif (_unit->isOut())\n\t{\n\t\t_parent->popState();\n\t\treturn;\n\t}\n\t_action.clearTU();\n\tif (_unit->getFaction() == FACTION_PLAYER)\n\t\t_parent->setStateInterval(Options::battleXcomSpeed);\n\telse\n\t\t_parent->setStateInterval(Options::battleAlienSpeed);\n\n\t// if the unit has a turret and we are turning during targeting, then only the turret turns\n\t_turret = _unit->getTurretType() != -1 && (_action.targeting || _action.strafe);\n\n\t_unit->lookAt(_action.target, _turret);\n\n\tif (_chargeTUs && _unit->getStatus() != STATUS_TURNING)\n\t{\n\t\tif (_action.type == BA_NONE)\n\t\t{\n\t\t\t// try to open a door\n\t\t\tint door = _parent->getTileEngine()->unitOpensDoor(_unit, true);\n\t\t\tif (door == 0)\n\t\t\t{\n\t\t\t\t_parent->getMod()->getSoundByDepth(_parent->getDepth(), Mod::DOOR_OPEN)->play(-1, _parent->getMap()->getSoundAngle(_unit->getPosition())); // normal door\n\t\t\t}\n\t\t\tif (door == 1)\n\t\t\t{\n\t\t\t\t_parent->getMod()->getSoundByDepth(_parent->getDepth(), Mod::SLIDING_DOOR_OPEN)->play(-1, _parent->getMap()->getSoundAngle(_unit->getPosition())); // ufo door\n\t\t\t}\n\t\t\tif (door == 4)\n\t\t\t{\n\t\t\t\t_action.result = \"STR_NOT_ENOUGH_TIME_UNITS\";\n\t\t\t}\n\t\t}\n\t\t_parent->popState();\n\t}\n}\n\n/**\n * Runs state functionality every cycle.\n */\nvoid UnitTurnBState::think()\n{\n\tconst int tu = _chargeTUs ? (_turret ? 1 :_unit->getTurnCost()) : 0;\n\n\tif (_chargeTUs && _unit->getFaction() == _parent->getSave()->getSide() && _parent->getPanicHandled() && !_action.targeting && !_parent->checkReservedTU(_unit, tu, 0))\n\t{\n\t\t_unit->abortTurn();\n\t\t_parent->popState();\n\t\treturn;\n\t}\n\n\tif (_unit->spendTimeUnits(tu))\n\t{\n\t\tsize_t unitSpotted = _unit->getUnitsSpottedThisTurn().size();\n\t\t_unit->turn(_turret);\n\t\t_parent->getTileEngine()->calculateFOV(_unit);\n\t\tif (_chargeTUs && _unit->getFaction() == _parent->getSave()->getSide() && _parent->getPanicHandled() && _action.type == BA_NONE && _unit->getUnitsSpottedThisTurn().size() > unitSpotted)\n\t\t{\n\t\t\t_unit->abortTurn();\n\t\t\t_parent->popState();\n\t\t}\n\t\telse if (_unit->getStatus() == STATUS_STANDING)\n\t\t{\n\t\t\t_parent->popState();\n\n\t\t\tif (_action.kneel && !_unit->isFloating() && !_unit->isKneeled())\n\t\t\t{\n\t\t\t\tBattleAction kneel;\n\t\t\t\tkneel.type = BA_KNEEL;\n\t\t\t\tkneel.actor = _unit;\n\t\t\t\tkneel.Time = _unit->getKneelChangeCost();\n\t\t\t\tif (kneel.spendTU())\n\t\t\t\t{\n\t\t\t\t\t_unit->kneel(!_unit->isKneeled());\n\t\t\t\t\t// kneeling or standing up can reveal new terrain or units. I guess.\n\t\t\t\t\t_parent->getTileEngine()->calculateFOV(_unit->getPosition(), 1, false); //Update unit FOV for everyone through this position, skip tiles.\n\t\t\t\t\t_parent->getTileEngine()->checkReactionFire(_unit, kneel);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\telse if (_parent->getPanicHandled())\n\t{\n\t\t_action.result = \"STR_NOT_ENOUGH_TIME_UNITS\";\n\t\t_unit->abortTurn();\n\t\t_parent->popState();\n\t}\n}\n\n/**\n * Unit turning cannot be cancelled.\n */\nvoid UnitTurnBState::cancel()\n{\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/UnitTurnBState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"BattleState.h\"\n\nnamespace OpenXcom\n{\n\nclass BattleUnit;\n\n/**\n * State for turning units.\n */\nclass UnitTurnBState : public BattleState\n{\nprivate:\n\tBattleUnit *_unit;\n\tbool _turret, _chargeTUs;\npublic:\n\t/// Creates a new UnitTurnBState class\n\tUnitTurnBState(BattlescapeGame *parent, BattleAction action, bool chargeTUs = true);\n\t/// Cleans up the UnitTurnBState.\n\t~UnitTurnBState();\n\t/// Initializes the state.\n\tvoid init() override;\n\t/// Handles a cancels request.\n\tvoid cancel() override;\n\t/// Runs state functionality every cycle.\n\tvoid think() override;\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/UnitWalkBState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"UnitWalkBState.h\"\n#include \"MeleeAttackBState.h\"\n#include \"TileEngine.h\"\n#include \"Pathfinding.h\"\n#include \"BattlescapeState.h\"\n#include \"Map.h\"\n#include \"Camera.h\"\n#include \"../Savegame/BattleUnit.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"../Savegame/Tile.h\"\n#include \"../Engine/Sound.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Logger.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Mod/Mod.h\"\n#include \"UnitFallBState.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Sets up an UnitWalkBState.\n * @param parent Pointer to the Battlescape.\n * @param action Pointer to an action.\n */\nUnitWalkBState::UnitWalkBState(BattlescapeGame *parent, BattleAction action) : BattleState(parent, action), _unit(0), _pf(0), _terrain(0), _beforeFirstStep(false), _numUnitsSpotted(0), _preMovementCost(0)\n{\n\n}\n\n/**\n * Deletes the UnitWalkBState.\n */\nUnitWalkBState::~UnitWalkBState()\n{\n\n}\n\n/**\n * Initializes the state.\n */\nvoid UnitWalkBState::init()\n{\n\t_unit = _action.actor;\n\t_numUnitsSpotted = _unit->getUnitsSpottedThisTurn().size();\n\tsetNormalWalkSpeed();\n\t_pf = _parent->getPathfinding();\n\t_terrain = _parent->getTileEngine();\n\t_target = _action.target;\n\tif (Options::traceAI) { Log(LOG_INFO) << \"Walking from: \" << _unit->getPosition() << \",\" << \" to \" << _target;}\n\tint dir = _pf->getStartDirection();\n\tif (!_action.strafe && dir != -1 && dir != _unit->getDirection())\n\t{\n\t\t_beforeFirstStep = true;\n\t}\n\t_terrain->addMovingUnit(_unit);\n}\n\n/**\n * Deinitalize the state.\n */\nvoid UnitWalkBState::deinit()\n{\n\t_terrain->removeMovingUnit(_unit);\n}\n\n/**\n * Runs state functionality every cycle.\n */\nvoid UnitWalkBState::think()\n{\n\tif (!_unit->getArmor()->allowsMoving())\n\t{\n\t\t_pf->abortPath();\n\t\t_parent->popState();\n\t\treturn;\n\t}\n\n\tbool unitSpotted = false;\n\tint size = _unit->getArmor()->getSize() - 1;\n\tbool onScreen = (_unit->getVisible() && _parent->getMap()->getCamera()->isOnScreen(_unit->getPosition(), true, size, false));\n\tif (_unit->isKneeled())\n\t{\n\t\tif (_parent->kneel(_unit))\n\t\t{\n\t\t\treturn;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (_parent->getPanicHandled())\n\t\t\t{\n\t\t\t\t_action.result = \"STR_NOT_ENOUGH_TIME_UNITS\";\n\t\t\t}\n\t\t\t_pf->abortPath();\n\t\t\t_parent->popState();\n\t\t\treturn;\n\t\t}\n\t}\n\n\n\tif (_unit->isOut())\n\t{\n\t\t_pf->abortPath();\n\t\t_parent->popState();\n\t\treturn;\n\t}\n\n\tauto cancelCurentMove = [&]\n\t{\n\t\tif (_fallingWhenStopped && !_falling)\n\t\t{\n\t\t\t_falling = true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_pf->abortPath();\n\t\t\t_parent->popState();\n\t\t}\n\t};\n\n\tif (_unit->getStatus() == STATUS_WALKING || _unit->getStatus() == STATUS_FLYING)\n\t{\n\t\tif ((_parent->getSave()->getTile(_unit->getDestination())->getUnit() == 0) || // next tile must be not occupied\n\t\t\t(_parent->getSave()->getTile(_unit->getDestination())->getUnit() == _unit))\n\t\t{\n\t\t\tbool onScreenBoundary = (_unit->getVisible() && _parent->getMap()->getCamera()->isOnScreen(_unit->getPosition(), true, size, true));\n\t\t\t_unit->keepWalking(_parent->getSave(), onScreenBoundary); // advances the phase\n\t\t\tplayMovementSound();\n\t\t\tif (_parent->getSave()->isPreview())\n\t\t\t{\n\t\t\t\t_unit->resetTimeUnitsAndEnergy();\n\t\t\t}\n\t\t}\n\t\telse if (!_falling)\n\t\t{\n\t\t\t_unit->lookAt(_unit->getDestination(), (_unit->getTurretType() != -1));\t// turn to undiscovered unit\n\t\t\t_pf->abortPath();\n\t\t}\n\n\t\t// unit moved from one tile to the other, update the tiles\n\t\tif (_unit->getPosition() != _unit->getLastPosition())\n\t\t{\n\t\t\tauto* belowTile = _parent->getSave()->getBelowTile(_unit->getTile());\n\t\t\t_fallingWhenStopped = _unit->haveNoFloorBelow() && _unit->getPosition().z != 0 && _unit->getMovementType() != MT_FLY && _unit->getWalkingPhase() == 0;\n\t\t\t_falling = _fallingWhenStopped && !(\n\t\t\t\tbelowTile && belowTile->hasLadder() && // we do not have any footing but \"jump\" from ladder to reach ledge\n\t\t\t\t_unit->getPosition() == _unit->getLastPosition()+Position(0,0,1) && // only vertical move from ladder below\n\t\t\t\t_pf->getStartDirection() != -1 // move is not canceled, when you cancel \"jump\" you should fallback to ladder below\n\t\t\t);\n\n\t\t\tif (_falling)\n\t\t\t{\n\t\t\t\tfor (int x = size; x >= 0; --x)\n\t\t\t\t{\n\t\t\t\t\tfor (int y = size; y >= 0; --y)\n\t\t\t\t\t{\n\t\t\t\t\t\tTile *otherTileBelow = _parent->getSave()->getTile(_unit->getPosition() + Position(x,y,-1));\n\t\t\t\t\t\tif (otherTileBelow && otherTileBelow->getUnit())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_falling = false;\n\t\t\t\t\t\t\t_fallingWhenStopped = false;\n\t\t\t\t\t\t\t_pf->dequeuePath();\n\t\t\t\t\t\t\t_parent->getSave()->addFallingUnit(_unit);\n\t\t\t\t\t\t\t_parent->statePushFront(new UnitFallBState(_parent));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!_parent->getMap()->getCamera()->isOnScreen(_unit->getPosition(), true, size, false) && _unit->getFaction() != FACTION_PLAYER && _unit->getVisible())\n\t\t\t\t_parent->getMap()->getCamera()->centerOnPosition(_unit->getPosition());\n\t\t\t// if the unit changed level, camera changes level with\n\t\t\t_parent->getMap()->getCamera()->setViewLevel(_unit->getPosition().z);\n\t\t}\n\n\t\t// is the step finished?\n\t\tif (_unit->getStatus() == STATUS_STANDING)\n\t\t{\n\t\t\t// update the TU display\n\t\t\t_parent->getSave()->getBattleState()->updateSoldierInfo();\n\t\t\t// if the unit burns floor tiles, burn floor tiles as long as we're not falling\n\t\t\tif (!_falling && (_unit->getSpecialAbility() == SPECAB_BURNFLOOR || _unit->getSpecialAbility() == SPECAB_BURN_AND_EXPLODE))\n\t\t\t{\n\t\t\t\t_unit->getTile()->ignite(1);\n\t\t\t\tPosition posHere = _unit->getPosition();\n\t\t\t\tPosition voxelHere = posHere.toVoxel() + Position(8,8,-(_unit->getTile()->getTerrainLevel()));\n\t\t\t\t_parent->getTileEngine()->hit(BattleActionAttack{ BA_NONE, _unit, }, voxelHere, _unit->getBaseStats()->strength, _parent->getMod()->getDamageType(DT_IN), false);\n\n\t\t\t\tif (_unit->getStatus() != STATUS_STANDING) // ie: we burned a hole in the floor and fell through it\n\t\t\t\t{\n\t\t\t\t\t_pf->abortPath();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (_unit->getFaction() != FACTION_PLAYER)\n\t\t\t{\n\t\t\t\t_unit->setVisible(false);\n\t\t\t}\n\n\t\t\tint change = _parent->checkForProximityGrenades(_unit);\n\t\t\t// move our personal lighting with us\n\t\t\t_terrain->calculateLighting(change ? LL_ITEMS : LL_UNITS, _unit->getPosition(), 2);\n\t\t\t_terrain->calculateFOV(_unit->getPosition(), 2, false); //update unit visibility for all units which can see last and current position.\n\t\t\t//tile visibility for this unit is handled later.\n\t\t\tunitSpotted = (!_action.ignoreSpottedEnemies && !_falling && !_action.desperate && _parent->getPanicHandled() && _numUnitsSpotted != _unit->getUnitsSpottedThisTurn().size());\n\n\t\t\tif (change > 1)\n\t\t\t{\n\t\t\t\t_parent->popState();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (unitSpotted)\n\t\t\t{\n\t\t\t\treturn cancelCurentMove();\n\t\t\t}\n\t\t\t// check for reaction fire\n\t\t\tif (!_falling && !_fallingWhenStopped)\n\t\t\t{\n\t\t\t\tif (_terrain->checkReactionFire(_unit, _action))\n\t\t\t\t{\n\t\t\t\t\t// unit got fired upon - stop walking\n\t\t\t\t\treturn cancelCurentMove();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse if (onScreen)\n\t\t{\n\t\t\t// make sure the unit sprites are up to date\n\t\t\tif (_pf->getStrafeMove())\n\t\t\t{\n\t\t\t\t// This is where we fake out the strafe movement direction so the unit \"moonwalks\"\n\t\t\t\tint dirTemp = _unit->getDirection();\n\t\t\t\t_unit->setDirection(_unit->getFaceDirection());\n\t\t\t\t//TODO fix moonwalk\n\t\t\t\t_unit->setDirection(dirTemp);\n\t\t\t}\n\t\t}\n\t}\n\n\t// we are just standing around, shouldn't we be walking?\n\tif (_unit->getStatus() == STATUS_STANDING || _unit->getStatus() == STATUS_PANICKING || _unit->getStatus() == STATUS_BERSERK)\n\t{\n\t\t// check if we did spot new units\n\t\tif (unitSpotted && !_action.desperate && _unit->getCharging() == 0 && !_falling)\n\t\t{\n\t\t\tif (Options::traceAI) { Log(LOG_INFO) << \"Uh-oh! Company!\"; }\n\t\t\t_unit->setHiding(false); // clearly we're not hidden now\n\t\t\tpostPathProcedures();\n\t\t\treturn;\n\t\t}\n\n\t\tif (onScreen || _parent->getSave()->getDebugMode())\n\t\t{\n\t\t\tsetNormalWalkSpeed();\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_parent->setStateInterval(0);\n\t\t}\n\t\tint dir = _pf->getStartDirection();\n\t\tif (_falling)\n\t\t{\n\t\t\tdir = Pathfinding::DIR_DOWN;\n\t\t}\n\n\t\tif (dir != -1)\n\t\t{\n\t\t\tif (_pf->getStrafeMove())\n\t\t\t{\n\t\t\t\t_unit->setFaceDirection(_unit->getDirection());\n\t\t\t}\n\n\t\t\t_pf->setUnit(_unit); //TODO: remove as was done by `getTUCost`\n\t\t\tPathfindingStep r = _pf->getTUCost(_unit->getPosition(), dir, _unit, 0, _action.getMoveType());\n\n\t\t\tint tu = r.cost.time;\n\t\t\tint energy = r.cost.energy;\n\t\t\tPosition destination = r.pos;\n\n\t\t\tif (tu == Pathfinding::INVALID_MOVE_COST)\n\t\t\t{\n\t\t\t\treturn cancelCurentMove();\n\t\t\t}\n\n\t\t\tif (tu > _unit->getTimeUnits())\n\t\t\t{\n\t\t\t\tif (_parent->getPanicHandled())\n\t\t\t\t{\n\t\t\t\t\t_action.result = \"STR_NOT_ENOUGH_TIME_UNITS\";\n\t\t\t\t}\n\t\t\t\treturn cancelCurentMove();\n\t\t\t}\n\n\t\t\tif (energy > _unit->getEnergy())\n\t\t\t{\n\t\t\t\tif (_parent->getPanicHandled())\n\t\t\t\t{\n\t\t\t\t\t_action.result = \"STR_NOT_ENOUGH_ENERGY\";\n\t\t\t\t}\n\t\t\t\treturn cancelCurentMove();\n\t\t\t}\n\n\t\t\tif (_parent->getPanicHandled() && !_falling && _parent->checkReservedTU(_unit, tu, energy) == false)\n\t\t\t{\n\t\t\t\treturn cancelCurentMove();\n\t\t\t}\n\n\t\t\t// we are looking in the wrong way, turn first (unless strafing)\n\t\t\t// we are not using the turn state, because turning during walking costs no tu\n\t\t\tif (dir != _unit->getDirection() && dir < Pathfinding::DIR_UP && !_pf->getStrafeMove())\n\t\t\t{\n\t\t\t\t_unit->lookAt(dir);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// now open doors (if any)\n\t\t\tif (dir < Pathfinding::DIR_UP)\n\t\t\t{\n\t\t\t\tint door = _terrain->unitOpensDoor(_unit, false, dir);\n\t\t\t\tif (door == 3)\n\t\t\t\t{\n\t\t\t\t\treturn; // don't start walking yet, wait for the ufo door to open\n\t\t\t\t}\n\t\t\t\tif (door == 0)\n\t\t\t\t{\n\t\t\t\t\t_parent->getMod()->getSoundByDepth(_parent->getDepth(), Mod::DOOR_OPEN)->play(-1, _parent->getMap()->getSoundAngle(_unit->getPosition())); // normal door\n\t\t\t\t}\n\t\t\t\tif (door == 1)\n\t\t\t\t{\n\t\t\t\t\t_parent->getMod()->getSoundByDepth(_parent->getDepth(), Mod::SLIDING_DOOR_OPEN)->play(-1, _parent->getMap()->getSoundAngle(_unit->getPosition())); // ufo door\n\t\t\t\t\treturn; // don't start walking yet, wait for the ufo door to open\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (int x = size; x >= 0; --x)\n\t\t\t{\n\t\t\t\tfor (int y = size; y >= 0; --y)\n\t\t\t\t{\n\t\t\t\t\tBattleUnit* unitInMyWay = _parent->getSave()->getTile(destination + Position(x,y,0))->getOverlappingUnit(_parent->getSave(), TUO_IGNORE_SMALL);  // 2+ voxels poking into the tile above, we don't kick people in the head here at XCom.\n\t\t\t\t\t// can't walk into units in this tile, or on top of other units sticking their head into this tile\n\t\t\t\t\tif (!_falling && unitInMyWay && unitInMyWay != _unit)\n\t\t\t\t\t{\n\t\t\t\t\t\t_action.clearTU();\n\t\t\t\t\t\treturn cancelCurentMove();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// now start moving\n\t\t\tdir = _pf->dequeuePath();\n\t\t\tif (_falling)\n\t\t\t{\n\t\t\t\tdir = Pathfinding::DIR_DOWN;\n\t\t\t}\n\n\t\t\tif (_unit->spendTimeUnits(tu))\n\t\t\t{\n\t\t\t\tif (_unit->spendEnergy(energy))\n\t\t\t\t{\n\t\t\t\t\t_unit->startWalking(dir, destination, _parent->getSave());\n\t\t\t\t\t_beforeFirstStep = false;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// make sure the unit sprites are up to date\n\t\t\tif (onScreen)\n\t\t\t{\n\t\t\t\tif (_pf->getStrafeMove())\n\t\t\t\t{\n\t\t\t\t\t// This is where we fake out the strafe movement direction so the unit \"moonwalks\"\n\t\t\t\t\tint dirTemp = _unit->getDirection();\n\t\t\t\t\t_unit->setDirection(_unit->getFaceDirection());\n\t\t\t\t\t_unit->setDirection(dirTemp);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tpostPathProcedures();\n\t\t\treturn;\n\t\t}\n\t}\n\n\t// turning during walking costs no tu\n\tif (_unit->getStatus() == STATUS_TURNING)\n\t{\n\t\t// except before the first step.\n\t\tif (_beforeFirstStep)\n\t\t{\n\t\t\tif (_unit->getArmor()->getTurnBeforeFirstStep())\n\t\t\t{\n\t\t\t\t_unit->spendTimeUnits(_unit->getTurnCost());\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_preMovementCost++;\n\t\t\t}\n\t\t}\n\n\t\t_unit->turn();\n\n\t\t// calculateFOV is unreliable for setting the unitSpotted bool, as it can be called from various other places\n\t\t// in the code, ie: doors opening, and this messes up the result.\n\t\t_terrain->calculateFOV(_unit);\n\t\tunitSpotted = (!_action.ignoreSpottedEnemies && !_falling && !_action.desperate && _parent->getPanicHandled() && _numUnitsSpotted != _unit->getUnitsSpottedThisTurn().size());\n\n\t\tif (unitSpotted && !_action.desperate && !_unit->getCharging() && !_falling)\n\t\t{\n\t\t\tif (_beforeFirstStep)\n\t\t\t{\n\t\t\t\t_preMovementCost = _preMovementCost * _unit->getTurnCost();\n\t\t\t\t_unit->spendTimeUnits(_preMovementCost);\n\t\t\t}\n\t\t\tif (Options::traceAI) { Log(LOG_INFO) << \"Egads! A turn reveals new units! I must pause!\"; }\n\t\t\t_unit->setHiding(false); // not hidden, are we...\n\t\t\t_unit->abortTurn(); //revert to a standing state.\n\t\t\treturn cancelCurentMove();\n\t\t}\n\t}\n}\n\n/**\n * Aborts unit walking.\n */\nvoid UnitWalkBState::cancel()\n{\n\tif (_beforeFirstStep)\n\t{\n\t\t// cancel here would allow turning without spending any TUs\n\t\treturn;\n\t}\n\n\tif (_parent->getSave()->getSide() == FACTION_PLAYER && _parent->getPanicHandled())\n\t_pf->abortPath();\n}\n\n/**\n * Handles some calculations when the path is finished.\n */\nvoid UnitWalkBState::postPathProcedures()\n{\n\t_action.clearTU();\n\tif (_unit->getFaction() != FACTION_PLAYER)\n\t{\n\t\tint dir = _action.finalFacing;\n\t\tif (_action.finalAction)\n\t\t{\n\t\t\t_unit->dontReselect();\n\t\t}\n\t\tif (_unit->getCharging() != 0)\n\t\t{\n\t\t\tdir = _parent->getTileEngine()->getDirectionTo(_unit->getPosition(), _unit->getCharging()->getPosition());\n\t\t\tif (_parent->getTileEngine()->validMeleeRange(_unit, _action.actor->getCharging(), dir))\n\t\t\t{\n\t\t\t\tBattleAction action;\n\t\t\t\taction.actor = _unit;\n\t\t\t\taction.target = _unit->getCharging()->getPosition();\n\t\t\t\taction.weapon = _unit->getUtilityWeapon(BT_MELEE);\n\t\t\t\taction.type = BA_HIT;\n\t\t\t\taction.targeting = true;\n\t\t\t\taction.updateTU();\n\t\t\t\t_unit->setCharging(0);\n\t\t\t\t_parent->statePushBack(new MeleeAttackBState(_parent, action));\n\t\t\t}\n\t\t}\n\t\telse if (_unit->isHiding())\n\t\t{\n\t\t\tdir = _unit->getDirection() + 4;\n\t\t\t_unit->setHiding(false);\n\t\t\t_unit->dontReselect();\n\t\t}\n\t\tif (dir != -1)\n\t\t{\n\t\t\tif (dir >= 8)\n\t\t\t{\n\t\t\t\tdir -= 8;\n\t\t\t}\n\t\t\t_unit->lookAt(dir);\n\t\t\twhile (_unit->getStatus() == STATUS_TURNING)\n\t\t\t{\n\t\t\t\t_unit->turn();\n\t\t\t\t_parent->getTileEngine()->calculateFOV(_unit);\n\t\t\t}\n\t\t}\n\t}\n\telse if (!_parent->getPanicHandled())\n\t{\n\t\t//todo: set the unit to aggrostate and try to find cover?\n\t\t_unit->clearTimeUnits();\n\t}\n\n\t_terrain->calculateLighting(LL_UNITS, _unit->getPosition());\n\t_terrain->calculateFOV(_unit);\n\tif (!_falling)\n\t\t_parent->popState();\n}\n\n/**\n * Handles some calculations when the walking is finished.\n */\nvoid UnitWalkBState::setNormalWalkSpeed()\n{\n\tif (_unit->getFaction() == FACTION_PLAYER)\n\t\t_parent->setStateInterval(Options::battleXcomSpeed);\n\telse\n\t\t_parent->setStateInterval(Options::battleAlienSpeed);\n}\n\n\n/**\n * Handles the stepping sounds.\n */\nvoid UnitWalkBState::playMovementSound()\n{\n\tint size = _unit->getArmor()->getSize() - 1;\n\tif ((!_unit->getVisible() && !_parent->getSave()->getDebugMode()) || !_parent->getMap()->getCamera()->isOnScreen(_unit->getPosition(), true, size, false)) return;\n\n\tTile *tile = _unit->getTile();\n\tint sound = -1;\n\tint unitSound = _unit->getMoveSound();\n\tint tileSoundOffset = tile->getFootstepSound(_parent->getSave()->getBelowTile(tile));\n\tint tileSound = Mod::NO_SOUND;\n\tif (tileSoundOffset > -1)\n\t{\n\t\t// play footstep sound 1\n\t\tif (_unit->getWalkingPhase() == 3)\n\t\t{\n\t\t\ttileSound = Mod::WALK_OFFSET + (tileSoundOffset*2);\n\t\t}\n\t\t// play footstep sound 2\n\t\tif (_unit->getWalkingPhase() == 7)\n\t\t{\n\t\t\ttileSound = Mod::WALK_OFFSET + (tileSoundOffset*2) + 1;\n\t\t}\n\t}\n\tif (unitSound != Mod::NO_SOUND)\n\t{\n\t\t// if a sound is configured in the ruleset, play that one\n\t\tif (_unit->getWalkingPhase() == 0)\n\t\t{\n\t\t\tsound = unitSound;\n\t\t}\n\t}\n\telse\n\t{\n\t\tif (_unit->getStatus() == STATUS_WALKING)\n\t\t{\n\t\t\tif (tileSound > Mod::NO_SOUND) //TODO: it should be `!=` but its possbile that offset could get negative is based on mod data\n\t\t\t{\n\t\t\t\tsound = tileSound;\n\t\t\t}\n\t\t}\n\t\telse if (_unit->getMovementType() == MT_FLY)\n\t\t{\n\t\t\t// play default flying sound\n\t\t\tif (_unit->getWalkingPhase() == 1)\n\t\t\t{\n\t\t\t\tsound = Mod::FLYING_SOUND;\n\t\t\t}\n\t\t}\n\t}\n\n\tsound = ModScript::scriptFunc1<ModScript::SelectMoveSoundUnit>(\n\t\t_unit->getArmor(),\n\t\tsound,\n\t\t_unit, _unit->getWalkingPhase(), unitSound, tileSound, Mod::WALK_OFFSET, tileSoundOffset, Mod::FLYING_SOUND, _action.getMoveType()\n\t);\n\tif (sound >= 0)\n\t{\n\t\t_parent->getMod()->getSoundByDepth(_parent->getDepth(), sound)->play(-1, _parent->getMap()->getSoundAngle(_unit->getPosition()));\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/UnitWalkBState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"BattleState.h\"\n#include \"BattlescapeGame.h\"\n#include \"Position.h\"\n\nnamespace OpenXcom\n{\n\nclass BattleUnit;\nclass Pathfinding;\nclass TileEngine;\n\n/**\n * State for walking units.\n */\nclass UnitWalkBState : public BattleState\n{\nprivate:\n\tPosition _target;\n\tBattleUnit *_unit;\n\tPathfinding *_pf;\n\tTileEngine *_terrain;\n\n\t/// Unit will fall down always.\n\tbool _falling = false;\n\t/// Allow to move over some tiles that normally should fall down.\n\tbool _fallingWhenStopped = false;\n\n\tbool _beforeFirstStep;\n\t/// Handles some calculations when the path is finished.\n\tvoid postPathProcedures();\n\t/// Handles some calculations when the walking is finished.\n\tvoid setNormalWalkSpeed();\n\t/// Handles the stepping sounds.\n\tvoid playMovementSound();\n\tstd::size_t _numUnitsSpotted;\n\tint _preMovementCost;\npublic:\n\t/// Creates a new UnitWalkBState class.\n\tUnitWalkBState(BattlescapeGame *parent, BattleAction _action);\n\t/// Cleans up the UnitWalkBState.\n\t~UnitWalkBState();\n\t/// Initializes the state.\n\tvoid init() override;\n\t/// Deinitializes the state.\n\tvoid deinit() override;\n\t/// Handles a cancels request.\n\tvoid cancel() override;\n\t/// Runs state functionality every cycle.\n\tvoid think() override;\n};\n\n}\n"
  },
  {
    "path": "src/Battlescape/WarningMessage.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"WarningMessage.h\"\n#include <SDL.h>\n#include <string>\n#include \"../fmath.h\"\n#include \"../Engine/Timer.h\"\n#include \"../Interface/Text.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Sets up a blank warning message with the specified size and position.\n * @param width Width in pixels.\n * @param height Height in pixels.\n * @param x X position in pixels.\n * @param y Y position in pixels.\n */\nWarningMessage::WarningMessage(int width, int height, int x, int y) : Surface(width, height, x, y), _color(0), _fade(0)\n{\n\t_text = new Text(width, height, 0, 0);\n\t_text->setHighContrast(true);\n\t_text->setAlign(ALIGN_CENTER);\n\t_text->setVerticalAlign(ALIGN_MIDDLE);\n\t_text->setWordWrap(true);\n\n\t_timer = new Timer(50);\n\t_timer->onTimer((SurfaceHandler)&WarningMessage::fade);\n\n\tsetVisible(false);\n}\n\n/**\n * Deletes timers.\n */\nWarningMessage::~WarningMessage()\n{\n\tdelete _timer;\n\tdelete _text;\n}\n\n/**\n * Changes the color for the message background.\n * @param color Color value.\n */\nvoid WarningMessage::setColor(Uint8 color)\n{\n\t_color = color;\n}\n\n/**\n * Changes the color for the message text.\n * @param color Color value.\n */\nvoid WarningMessage::setTextColor(Uint8 color)\n{\n\t_text->setColor(color);\n}\n\n/**\n * Changes the various resources needed for text rendering.\n * The different fonts need to be passed in advance since the\n * text size can change mid-text, and the language affects\n * how the text is rendered.\n * @param big Pointer to large-size font.\n * @param small Pointer to small-size font.\n * @param lang Pointer to current language.\n */\nvoid WarningMessage::initText(Font *big, Font *small, Language *lang)\n{\n\t_text->initText(big, small, lang);\n}\n\n/**\n * Replaces a certain amount of colors in the surface's palette.\n * @param colors Pointer to the set of colors.\n * @param firstcolor Offset of the first color to replace.\n * @param ncolors Amount of colors to replace.\n */\nvoid WarningMessage::setPalette(const SDL_Color *colors, int firstcolor, int ncolors)\n{\n\tSurface::setPalette(colors, firstcolor, ncolors);\n\t_text->setPalette(colors, firstcolor, ncolors);\n}\n\n/**\n * Displays the warning message.\n * @param msg Message string.\n * @param time How long message will be visible.\n */\nvoid WarningMessage::showMessage(const std::string &msg, int time)\n{\n\t_text->setText(msg);\n\t_fade = time * 12;\n\t_redraw = true;\n\tsetVisible(true);\n\t_timer->start();\n}\n\n/**\n * Keeps the animation timers running.\n */\nvoid WarningMessage::think()\n{\n\t_timer->think(0, this);\n}\n\n/**\n * Plays the message fade animation.\n */\nvoid WarningMessage::fade()\n{\n\t_fade--;\n\t_redraw = true;\n\tif (_fade == 0)\n\t{\n\t\tsetVisible(false);\n\t\t_timer->stop();\n\t}\n}\n\n/**\n * Draws the warning message.\n */\nvoid WarningMessage::draw()\n{\n\tSurface::draw();\n\tdrawRect(0, 0, getWidth(), getHeight(), _color + Clamp(24 - _fade, 0, 12));\n\t_text->blit(this->getSurface());\n}\n\n}\n"
  },
  {
    "path": "src/Battlescape/WarningMessage.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/Surface.h\"\n\nnamespace OpenXcom\n{\n\nclass Text;\nclass Timer;\nclass Font;\n\n/**\n * Coloured box with text inside that fades out after it is displayed.\n * Used to display warning/error messages on the Battlescape.\n */\nclass WarningMessage : public Surface\n{\nprivate:\n\tText *_text;\n\tTimer *_timer;\n\tUint8 _color, _fade;\npublic:\n\t/// Creates a new warning message with the specified size and position.\n\tWarningMessage(int width, int height, int x = 0, int y = 0);\n\t/// Cleans up the warning message.\n\t~WarningMessage();\n\t/// Sets the color for the warning message.\n\tvoid setColor(Uint8 color) override;\n\t/// Sets the text color for the warning message.\n\tvoid setTextColor(Uint8 color);\n\t/// Initializes the warning message's resources.\n\tvoid initText(Font *big, Font *small, Language *lang) override;\n\t/// Sets the warning message's palette.\n\tvoid setPalette(const SDL_Color *colors, int firstcolor = 0, int ncolors = 256) override;\n\t/// Shows the warning message.\n\tvoid showMessage(const std::string &msg, int time = 2);\n\t/// Handles the timers.\n\tvoid think() override;\n\t/// Fades the message.\n\tvoid fade();\n\t/// Draws the message.\n\tvoid draw() override;\n};\n\n}\n"
  },
  {
    "path": "src/CMakeLists.txt",
    "content": "\nset ( root_src\n  lodepng.cpp\n  main.cpp\n  md5.cpp\n)\nset ( basescape_src\n  Basescape/BaseInfoState.cpp\n  Basescape/BasescapeState.cpp\n  Basescape/BaseView.cpp\n  Basescape/BuildFacilitiesState.cpp\n  Basescape/CraftArmorState.cpp\n  Basescape/CraftEquipmentLoadState.cpp\n  Basescape/CraftEquipmentSaveState.cpp\n  Basescape/CraftEquipmentState.cpp\n  Basescape/CraftInfoState.cpp\n  Basescape/CraftPilotSelectState.cpp\n  Basescape/CraftPilotsState.cpp\n  Basescape/CraftSoldiersState.cpp\n  Basescape/CraftsState.cpp\n  Basescape/CraftWeaponsState.cpp\n  Basescape/DismantleFacilityState.cpp\n  Basescape/GlobalAlienContainmentState.cpp\n  Basescape/GlobalManufactureState.cpp\n  Basescape/GlobalResearchDiaryState.cpp\n  Basescape/GlobalResearchState.cpp\n  Basescape/ItemLocationsState.cpp\n  Basescape/ManageAlienContainmentState.cpp\n  Basescape/ManufactureDependenciesTreeState.cpp\n  Basescape/ManufactureInfoState.cpp\n  Basescape/ManufactureStartState.cpp\n  Basescape/ManufactureState.cpp\n  Basescape/MiniBaseView.cpp\n  Basescape/MonthlyCostsState.cpp\n  Basescape/NewManufactureListState.cpp\n  Basescape/NewResearchListState.cpp\n  Basescape/PlaceFacilityState.cpp\n  Basescape/PlaceLiftState.cpp\n  Basescape/PlaceStartFacilityState.cpp\n  Basescape/PurchaseState.cpp\n  Basescape/ResearchInfoState.cpp\n  Basescape/ResearchState.cpp\n  Basescape/SackSoldierState.cpp\n  Basescape/SelectStartFacilityState.cpp\n  Basescape/SellState.cpp\n  Basescape/SoldierArmorState.cpp\n  Basescape/SoldierAvatarState.cpp\n  Basescape/SoldierBonusState.cpp\n  Basescape/SoldierDiaryLightState.cpp\n  Basescape/SoldierDiaryMissionState.cpp\n  Basescape/SoldierDiaryOverviewState.cpp\n  Basescape/SoldierDiaryPerformanceState.cpp\n  Basescape/SoldierInfoState.cpp\n  Basescape/SoldierMemorialState.cpp\n  Basescape/SoldierRankState.cpp\n  Basescape/SoldierSortUtil.cpp\n  Basescape/SoldiersState.cpp\n  Basescape/SoldierTransformationState.cpp\n  Basescape/SoldierTransformationListState.cpp\n  Basescape/SoldierTransformState.cpp\n  Basescape/StoresState.cpp\n  Basescape/TechTreeSelectState.cpp\n  Basescape/TechTreeViewerState.cpp\n  Basescape/TransferBaseState.cpp\n  Basescape/TransferConfirmState.cpp\n  Basescape/TransferItemsState.cpp\n  Basescape/TransfersState.cpp\n)\n\nset ( battlescape_src\n  Battlescape/AbortMissionState.cpp\n  Battlescape/ActionMenuItem.cpp\n  Battlescape/ActionMenuState.cpp\n  Battlescape/AIModule.cpp\n  Battlescape/AlienInventory.cpp\n  Battlescape/AlienInventoryState.cpp\n  Battlescape/AliensCrashState.cpp\n  Battlescape/BattlescapeGame.cpp\n  Battlescape/BattlescapeGenerator.cpp\n  Battlescape/BattlescapeMessage.cpp\n  Battlescape/BattlescapeState.cpp\n  Battlescape/BattleState.cpp\n  Battlescape/BriefingLightState.cpp\n  Battlescape/BriefingState.cpp\n  Battlescape/Camera.cpp\n  Battlescape/CannotReequipState.cpp\n  Battlescape/CommendationLateState.cpp\n  Battlescape/CommendationState.cpp\n  Battlescape/ConfirmEndMissionState.cpp\n  Battlescape/DebriefingState.cpp\n  Battlescape/ExperienceOverviewState.cpp\n  Battlescape/Explosion.cpp\n  Battlescape/ExplosionBState.cpp\n  Battlescape/ExtendedBattlescapeLinksState.cpp\n  Battlescape/ExtendedInventoryLinksState.cpp\n  Battlescape/InfoboxOKState.cpp\n  Battlescape/InfoboxState.cpp\n  Battlescape/Inventory.cpp\n  Battlescape/InventoryLoadState.cpp\n  Battlescape/InventoryPersonalState.cpp\n  Battlescape/InventorySaveState.cpp\n  Battlescape/InventoryState.cpp\n  Battlescape/ItemSprite.cpp\n  Battlescape/Map.cpp\n  Battlescape/MedikitState.cpp\n  Battlescape/MedikitView.cpp\n  Battlescape/MeleeAttackBState.cpp\n  Battlescape/MiniMapState.cpp\n  Battlescape/MiniMapView.cpp\n  Battlescape/NextTurnState.cpp\n  Battlescape/NoExperienceState.cpp\n  Battlescape/Particle.cpp\n  Battlescape/Pathfinding.cpp\n  Battlescape/PathfindingNode.cpp\n  Battlescape/PathfindingOpenSet.cpp\n  Battlescape/Position.cpp\n  Battlescape/PrimeGrenadeState.cpp\n  Battlescape/Projectile.cpp\n  Battlescape/ProjectileFlyBState.cpp\n  Battlescape/PromotionsState.cpp\n  Battlescape/PsiAttackBState.cpp\n  Battlescape/ScannerState.cpp\n  Battlescape/ScannerView.cpp\n  Battlescape/SkillMenuState.cpp\n  Battlescape/TileEngine.cpp\n  Battlescape/TurnDiaryState.cpp\n  Battlescape/UnitDieBState.cpp\n  Battlescape/UnitFallBState.cpp\n  Battlescape/UnitInfoState.cpp\n  Battlescape/UnitPanicBState.cpp\n  Battlescape/UnitSprite.cpp\n  Battlescape/UnitTurnBState.cpp\n  Battlescape/UnitWalkBState.cpp\n  Battlescape/WarningMessage.cpp\n)\n\nset ( engine_src\n  Engine/Action.cpp\n  Engine/Adlib/adlplayer.cpp\n  Engine/Adlib/fmopl.cpp\n  Engine/AdlibMusic.cpp\n  Engine/CatFile.cpp\n  Engine/CrossPlatform.cpp\n  Engine/FastLineClip.cpp\n  Engine/FileMap.cpp\n  Engine/FlcPlayer.cpp\n  Engine/Font.cpp\n  Engine/Game.cpp\n  Engine/GMCat.cpp\n  Engine/InteractiveSurface.cpp\n  Engine/Language.cpp\n  Engine/LanguagePlurality.cpp\n  Engine/LocalizedText.cpp\n  Engine/ModInfo.cpp\n  Engine/Music.cpp\n  Engine/OpenGL.cpp\n  Engine/OptionInfo.cpp\n  Engine/Options.cpp\n  Engine/Palette.cpp\n  Engine/RNG.cpp\n  Engine/Scalers/hq2x.cpp\n  Engine/Scalers/hq3x.cpp\n  Engine/Scalers/hq4x.cpp\n  Engine/Scalers/init.cpp\n  Engine/Scalers/scale2x.cpp\n  Engine/Scalers/scale3x.cpp\n  Engine/Scalers/scalebit.cpp\n  Engine/Scalers/xbrz.cpp\n  Engine/Screen.cpp\n  Engine/Script.cpp\n  Engine/Sound.cpp\n  Engine/SoundSet.cpp\n  Engine/State.cpp\n  Engine/Surface.cpp\n  Engine/SurfaceSet.cpp\n  Engine/Timer.cpp\n  Engine/TouchState.cpp\n  Engine/Unicode.cpp\n  Engine/Yaml.cpp\n  Engine/Zoom.cpp\n)\n\nset ( geoscape_src\n  Geoscape/AlienBaseState.cpp\n  Geoscape/AllocatePsiTrainingState.cpp\n  Geoscape/AllocateTrainingState.cpp\n  Geoscape/BaseDefenseState.cpp\n  Geoscape/BaseDestroyedState.cpp\n  Geoscape/BaseNameState.cpp\n  Geoscape/BuildNewBaseState.cpp\n  Geoscape/ConfirmCydoniaState.cpp\n  Geoscape/ConfirmDestinationState.cpp\n  Geoscape/ConfirmLandingState.cpp\n  Geoscape/ConfirmNewBaseState.cpp\n  Geoscape/CraftErrorState.cpp\n  Geoscape/CraftNotEnoughPilotsState.cpp\n  Geoscape/CraftPatrolState.cpp\n  Geoscape/DogfightErrorState.cpp\n  Geoscape/DogfightExperienceState.cpp\n  Geoscape/DogfightState.cpp\n  Geoscape/ExtendedGeoscapeLinksState.cpp\n  Geoscape/FundingState.cpp\n  Geoscape/GeoscapeCraftState.cpp\n  Geoscape/GeoscapeEventState.cpp\n  Geoscape/GeoscapeState.cpp\n  Geoscape/Globe.cpp\n  Geoscape/GraphsState.cpp\n  Geoscape/InterceptState.cpp\n  Geoscape/ItemsArrivingState.cpp\n  Geoscape/LowFuelState.cpp\n  Geoscape/MissionDetectedState.cpp\n  Geoscape/MonthlyReportState.cpp\n  Geoscape/MultipleTargetsState.cpp\n  Geoscape/NewPossibleCraftState.cpp\n  Geoscape/NewPossibleFacilityState.cpp\n  Geoscape/NewPossibleManufactureState.cpp\n  Geoscape/NewPossiblePurchaseState.cpp\n  Geoscape/NewPossibleResearchState.cpp\n  Geoscape/ProductionCompleteState.cpp\n  Geoscape/PsiTrainingState.cpp\n  Geoscape/ResearchCompleteState.cpp\n  Geoscape/ResearchRequiredState.cpp\n  Geoscape/SelectDestinationState.cpp\n  Geoscape/SelectMusicTrackState.cpp\n  Geoscape/TargetInfoState.cpp\n  Geoscape/TrainingFinishedState.cpp\n  Geoscape/TrainingState.cpp\n  Geoscape/UfoDetectedState.cpp\n  Geoscape/UfoLostState.cpp\n  Geoscape/UfoTrackerState.cpp\n)\n\nset ( interface_src\n  Interface/ArrowButton.cpp\n  Interface/Bar.cpp\n  Interface/BattlescapeButton.cpp\n  Interface/ComboBox.cpp\n  Interface/Cursor.cpp\n  Interface/FpsCounter.cpp\n  Interface/Frame.cpp\n  Interface/ImageButton.cpp\n  Interface/NumberText.cpp\n  Interface/ProgressBar.cpp\n  Interface/ScrollBar.cpp\n  Interface/Slider.cpp\n  Interface/Text.cpp\n  Interface/TextButton.cpp\n  Interface/TextEdit.cpp\n  Interface/TextList.cpp\n  Interface/ToggleTextButton.cpp\n  Interface/Window.cpp\n)\n\nset ( menu_src\n  Menu/AbandonGameState.cpp\n  Menu/ConfirmLoadState.cpp\n  Menu/CutsceneState.cpp\n  Menu/DeleteGameState.cpp\n  Menu/ErrorMessageState.cpp\n  Menu/ListGamesState.cpp\n  Menu/ListLoadOriginalState.cpp\n  Menu/ListLoadState.cpp\n  Menu/ListSaveState.cpp\n  Menu/LoadGameState.cpp\n  Menu/MainMenuState.cpp\n  Menu/NewBattleState.cpp\n  Menu/NewGameState.cpp\n  Menu/NotesState.cpp\n  Menu/OptionsAdvancedState.cpp\n  Menu/OptionsAudioState.cpp\n  Menu/OptionsBaseState.cpp\n  Menu/OptionsBattlescapeState.cpp\n  Menu/OptionsConfirmState.cpp\n  Menu/OptionsControlsState.cpp\n  Menu/OptionsDefaultsState.cpp\n  Menu/OptionsFoldersState.cpp\n  Menu/OptionsGeoscapeState.cpp\n  Menu/ModConfirmExtendedState.cpp\n  Menu/ModListState.cpp\n  Menu/OptionsNoAudioState.cpp\n  Menu/OptionsVideoState.cpp\n  Menu/PauseState.cpp\n  Menu/SaveGameState.cpp\n  Menu/SetWindowedRootState.cpp\n  Menu/SlideshowState.cpp\n  Menu/StartState.cpp\n  Menu/StatisticsState.cpp\n  Menu/TestPaletteState.cpp\n  Menu/TestState.cpp\n  Menu/VideoState.cpp\n)\n\nset ( mod_src\n  Mod/AlienDeployment.cpp\n  Mod/AlienRace.cpp\n  Mod/Armor.cpp\n  Mod/ArticleDefinition.cpp\n  Mod/City.cpp\n  Mod/CustomPalettes.cpp\n  Mod/ExtraSounds.cpp\n  Mod/ExtraSprites.cpp\n  Mod/ExtraStrings.cpp\n  Mod/MapBlock.cpp\n  Mod/MapData.cpp\n  Mod/MapDataSet.cpp\n  Mod/MapScript.cpp\n  Mod/MCDPatch.cpp\n  Mod/Mod.cpp\n  Mod/Polygon.cpp\n  Mod/Polyline.cpp\n  Mod/RuleAlienMission.cpp\n  Mod/RuleArcScript.cpp\n  Mod/RuleBaseFacility.cpp\n  Mod/RuleCommendations.cpp\n  Mod/RuleConverter.cpp\n  Mod/RuleCountry.cpp\n  Mod/RuleCraft.cpp\n  Mod/RuleCraftWeapon.cpp\n  Mod/RuleDamageType.cpp\n  Mod/RuleEnviroEffects.cpp\n  Mod/RuleEvent.cpp\n  Mod/RuleEventScript.cpp\n  Mod/RuleGlobe.cpp\n  Mod/RuleInterface.cpp\n  Mod/RuleInventory.cpp\n  Mod/RuleItem.cpp\n  Mod/RuleItemCategory.cpp\n  Mod/RuleManufacture.cpp\n  Mod/RuleManufactureShortcut.cpp\n  Mod/RuleMissionScript.cpp\n  Mod/RuleMusic.cpp\n  Mod/RuleRegion.cpp\n  Mod/RuleResearch.cpp\n  Mod/RuleSkill.cpp\n  Mod/RuleSoldier.cpp\n  Mod/RuleSoldierBonus.cpp\n  Mod/RuleSoldierTransformation.cpp\n  Mod/RuleStartingCondition.cpp\n  Mod/RuleStatBonus.cpp\n  Mod/RuleTerrain.cpp\n  Mod/RuleUfo.cpp\n  Mod/RuleVideo.cpp\n  Mod/RuleWeaponSet.cpp\n  Mod/SoldierNamePool.cpp\n  Mod/SoundDefinition.cpp\n  Mod/StatString.cpp\n  Mod/StatStringCondition.cpp\n  Mod/Texture.cpp\n  Mod/UfoTrajectory.cpp\n  Mod/Unit.cpp\n)\n\nset ( savegame_src\n  Savegame/AlienBase.cpp\n  Savegame/AlienMission.cpp\n  Savegame/AlienStrategy.cpp\n  Savegame/Base.cpp\n  Savegame/BaseFacility.cpp\n  Savegame/BattleItem.cpp\n  Savegame/BattleUnit.cpp\n  Savegame/Country.cpp\n  Savegame/Craft.cpp\n  Savegame/CraftWeapon.cpp\n  Savegame/CraftWeaponProjectile.cpp\n  Savegame/EquipmentLayoutItem.cpp\n  Savegame/GameTime.cpp\n  Savegame/GeoscapeEvent.cpp\n  Savegame/HitLog.cpp\n  Savegame/ItemContainer.cpp\n  Savegame/MissionSite.cpp\n  Savegame/MovingTarget.cpp\n  Savegame/Node.cpp\n  Savegame/Production.cpp\n  Savegame/RankCount.cpp\n  Savegame/Region.cpp\n  Savegame/ResearchProject.cpp\n  Savegame/SaveConverter.cpp\n  Savegame/SavedBattleGame.cpp\n  Savegame/SavedGame.cpp\n  Savegame/SerializationHelper.cpp\n  Savegame/Soldier.cpp\n  Savegame/SoldierAvatar.cpp\n  Savegame/SoldierDeath.cpp\n  Savegame/SoldierDiary.cpp\n  Savegame/Target.cpp\n  Savegame/Tile.cpp\n  Savegame/Transfer.cpp\n  Savegame/Ufo.cpp\n  Savegame/Vehicle.cpp\n  Savegame/Waypoint.cpp\n  Savegame/WeightedOptions.cpp\n)\n\nset ( ufopedia_src\n  Ufopaedia/ArticleState.cpp\n  Ufopaedia/ArticleStateArmor.cpp\n  Ufopaedia/ArticleStateBaseFacility.cpp\n  Ufopaedia/ArticleStateCraft.cpp\n  Ufopaedia/ArticleStateCraftWeapon.cpp\n  Ufopaedia/ArticleStateItem.cpp\n  Ufopaedia/ArticleStateSoldier.cpp\n  Ufopaedia/ArticleStateText.cpp\n  Ufopaedia/ArticleStateTextImage.cpp\n  Ufopaedia/ArticleStateTFTD.cpp\n  Ufopaedia/ArticleStateTFTDArmor.cpp\n  Ufopaedia/ArticleStateTFTDCraft.cpp\n  Ufopaedia/ArticleStateTFTDCraftWeapon.cpp\n  Ufopaedia/ArticleStateTFTDFacility.cpp\n  Ufopaedia/ArticleStateTFTDItem.cpp\n  Ufopaedia/ArticleStateTFTDUso.cpp\n  Ufopaedia/ArticleStateTFTDVehicle.cpp\n  Ufopaedia/ArticleStateUfo.cpp\n  Ufopaedia/ArticleStateUnit.cpp\n  Ufopaedia/ArticleStateVehicle.cpp\n  Ufopaedia/StatsForNerdsState.cpp\n  Ufopaedia/Ufopaedia.cpp\n  Ufopaedia/UfopaediaSelectState.cpp\n  Ufopaedia/UfopaediaStartState.cpp\n)\n\nset ( rapidyaml_src\n  ../libs/rapidyaml/c4/base64.cpp\n  ../libs/rapidyaml/c4/char_traits.cpp\n  ../libs/rapidyaml/c4/error.cpp\n  ../libs/rapidyaml/c4/format.cpp\n  ../libs/rapidyaml/c4/language.cpp\n  ../libs/rapidyaml/c4/memory_resource.cpp\n  ../libs/rapidyaml/c4/memory_util.cpp\n  ../libs/rapidyaml/c4/utf.cpp\n  ../libs/rapidyaml/c4/yml/common.cpp\n  ../libs/rapidyaml/c4/yml/node.cpp\n  ../libs/rapidyaml/c4/yml/node_type.cpp\n  ../libs/rapidyaml/c4/yml/parse.cpp\n  ../libs/rapidyaml/c4/yml/preprocess.cpp\n  ../libs/rapidyaml/c4/yml/reference_resolver.cpp\n  ../libs/rapidyaml/c4/yml/tag.cpp\n  ../libs/rapidyaml/c4/yml/tree.cpp\n  ../libs/rapidyaml/c4/yml/version.cpp\n\n)\n\nset ( cxx_src\n    ${root_src}\n    ${basescape_src}\n    ${battlescape_src}\n    ${engine_src}\n    ${geoscape_src}\n    ${interface_src}\n    ${menu_src}\n    ${mod_src}\n    ${savegame_src}\n    ${ufopedia_src}\n    ${rapidyaml_src}\n)\n\nset ( c_src\n  ../libs/miniz/miniz.c\n)\nset_property ( SOURCE ${c_src} APPEND PROPERTY COMPILE_DEFINITIONS MINIZ_NO_STDIO )\nset_property ( SOURCE Engine/Scalers/xbrz.cpp APPEND_STRING PROPERTY COMPILE_FLAGS -Wno-unused\\ )\n\nset ( data_install_dir bin )\nif ( \"${CMAKE_CXX_COMPILER_ID}\" STREQUAL \"GNU\" AND \"${CMAKE_BUILD_TYPE}\" STREQUAL \"Debug\" )\n  set_property ( SOURCE Engine/Options.cpp APPEND PROPERTY COMPILE_DEFINITIONS _DEBUG )\n  set_property ( SOURCE OpenXcom.rc APPEND PROPERTY COMPILE_DEFINITIONS _DEBUG )\nendif ()\nif ( \"${CMAKE_CXX_COMPILER_ID}\" STREQUAL \"GNU\" )\n  # attempt to limit the executable size\n  set_property ( SOURCE ${cxx_src} APPEND_STRING PROPERTY COMPILE_FLAGS -femit-struct-debug-reduced\\ )\nendif ()\nif ( \"${CMAKE_CXX_COMPILER_ID}\" STREQUAL \"GNU\" OR CMAKE_CXX_COMPILER_ID MATCHES \"Clang\" )\n  # C++ - only warnings\n  # C and C++ warnings\n  set_property ( SOURCE ${cxx_src} ${c_src} APPEND_STRING PROPERTY COMPILE_FLAGS -Wall\\ )\n  set_property ( SOURCE ${cxx_src} ${c_src} APPEND_STRING PROPERTY COMPILE_FLAGS -Wextra\\ )\n  set_property ( SOURCE ${cxx_src} ${c_src} APPEND_STRING PROPERTY COMPILE_FLAGS -Winit-self\\ )\n  set_property ( SOURCE ${cxx_src} ${c_src} APPEND_STRING PROPERTY COMPILE_FLAGS -Wmissing-include-dirs\\ )\n  set_property ( SOURCE ${cxx_src} ${c_src} APPEND_STRING PROPERTY COMPILE_FLAGS -Wunknown-pragmas\\ )\n  set_property ( SOURCE ${cxx_src} ${c_src} APPEND_STRING PROPERTY COMPILE_FLAGS -Wmissing-format-attribute\\ )\n  set_property ( SOURCE ${cxx_src} ${c_src} APPEND_STRING PROPERTY COMPILE_FLAGS -Wredundant-decls\\ )\n  set_property ( SOURCE ${cxx_src} ${c_src} APPEND_STRING PROPERTY COMPILE_FLAGS -Wformat-security\\ )\n  set_property ( SOURCE ${cxx_src} ${c_src} APPEND_STRING PROPERTY COMPILE_FLAGS -Wtype-limits\\ )\n  set_property ( SOURCE ${cxx_src} ${c_src} APPEND_STRING PROPERTY COMPILE_FLAGS -Wempty-body\\ )\n  set_property ( SOURCE ${cxx_src} ${c_src} APPEND_STRING PROPERTY COMPILE_FLAGS -Wuninitialized\\ )\n  set_property ( SOURCE ${cxx_src} ${c_src} APPEND_STRING PROPERTY COMPILE_FLAGS -Wignored-qualifiers\\ )\n  set_property ( SOURCE ${cxx_src} ${c_src} APPEND_STRING PROPERTY COMPILE_FLAGS -Wno-unused-parameter\\ )\n  set_property ( SOURCE ${cxx_src} ${c_src} APPEND_STRING PROPERTY COMPILE_FLAGS -Wno-inline\\ )\n  if ( \"${CMAKE_CXX_COMPILER_ID}\" STREQUAL \"GNU\" )\n    # apple clang 11.0 goes crazy with -Wshadow on the yaml-cpp source code\n    set_property ( SOURCE ${cxx_src} ${c_src} APPEND_STRING PROPERTY COMPILE_FLAGS -Wshadow\\ )\n    # add warning flags recognized by g++ but not by clang\n    set_property ( SOURCE ${cxx_src} APPEND_STRING PROPERTY COMPILE_FLAGS -Wsuggest-override\\ )\n    set_property ( SOURCE ${cxx_src} ${c_src} APPEND_STRING PROPERTY COMPILE_FLAGS -Wclobbered\\ )\n    set_property ( SOURCE ${cxx_src} ${c_src} APPEND_STRING PROPERTY COMPILE_FLAGS -Wlogical-op\\ )\n  elseif ( CMAKE_CXX_COMPILER_ID MATCHES \"Clang\" )\n    # add warning flags recognized by clang but not by g++\n  endif ()\n  if ( FATAL_WARNING )\n    set_property ( SOURCE ${cxx_src} ${c_src} APPEND_STRING PROPERTY COMPILE_FLAGS -Werror\\ )\n  endif ()\nendif ()\n\nif ( CMAKE_CXX_COMPILER_ID MATCHES \"Clang\" )\n  set_property ( SOURCE ${cxx_src} ${c_src} APPEND_STRING PROPERTY COMPILE_FLAGS -Qunused-arguments\\ )\n  set_property ( SOURCE ${cxx_src} ${c_src} APPEND_STRING PROPERTY COMPILE_FLAGS -pipe\\ )\n  if ( ENABLE_CLANG_ANALYSIS )\n    set_property ( SOURCE ${cxx_src} ${c_src} APPEND_STRING PROPERTY COMPILE_FLAGS --analyze\\ )\n  endif ()\nendif ()\n\nif ( MSVC )\n  # Set warning levels for Debug and Release with debug info\n  set ( CMAKE_CXX_FLAGS_DEBUG \"${CMAKE_CXX_FLAGS_DEBUG} /W${MSVC_WARNING_LEVEL}\" )\n  set ( CMAKE_CXX_FLAGS_RELWITHDEBINFO \"${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /W${MSVC_WARNING_LEVEL}\" )\n  if ( FATAL_WARNING )\n    add_compile_options ( /WX )\n  endif ( FATAL_WARNING )\n  set ( CMAKE_EXE_LINKER_FLAGS \"/manifest:no\" )\n  set ( CMAKE_MODULE_LINKER_FLAGS \"/manifest:no\" )\n  set ( CMAKE_SHARED_LINKER_FLAGS=\"/manifest:no\" )\nendif ()\n\nif ( DUMP_CORE )\n  set_property ( SOURCE main.cpp APPEND PROPERTY COMPILE_DEFINITIONS DUMP_CORE )\nendif ()\n\nif ( EMBED_ASSETS )\n  set_property ( SOURCE OpenXcom.rc APPEND PROPERTY COMPILE_DEFINITIONS EMBED_ASSETS )\n  set_property ( SOURCE Engine/CrossPlatform.cpp APPEND PROPERTY COMPILE_DEFINITIONS EMBED_ASSETS )\n  set_property ( SOURCE Engine/Options.cpp APPEND PROPERTY COMPILE_DEFINITIONS EMBED_ASSETS )\n  add_custom_command ( OUTPUT \"${CMAKE_BINARY_DIR}/common.zip\" COMMAND zip -r -FS \"${CMAKE_BINARY_DIR}/common.zip\" .\n                        WORKING_DIRECTORY \"${PROJECT_SOURCE_DIR}/bin/common\" )\n  add_custom_command ( OUTPUT \"${CMAKE_BINARY_DIR}/standard.zip\" COMMAND zip -r -FS \"${CMAKE_BINARY_DIR}/standard.zip\" .\n                        WORKING_DIRECTORY \"${PROJECT_SOURCE_DIR}/bin/standard\" )\n  add_custom_target ( zips DEPENDS \"${CMAKE_BINARY_DIR}/common.zip\" \"${CMAKE_BINARY_DIR}/standard.zip\" )\nendif ()\n\nif ( WIN32 )\n  set ( application_type WIN32 )\n  set ( openxcom_icon OpenXcom.rc )\nendif ()\n\nif ( UNIX AND EMBED_ASSETS )\n  enable_language(ASM)\n  set ( embed_src OpenXcom.s )\n  set_property ( SOURCE OpenXcom.s PROPERTY COMPILE_FLAGS -I${CMAKE_BINARY_DIR} )\nendif ()\n\nset ( openxcom_src ${c_src} ${cxx_src} ${embed_src} )\nset ( install_dest RUNTIME )\nset ( set_exec_path ON )\nset ( install_dest_dir bin )\nif ( NOT \"${DATADIR}\" STREQUAL \"\" )\n  add_definitions( -DDATADIR=\"${DATADIR}\" )\nendif ()\nif ( UNIX AND NOT APPLE )\n  set ( data_install_dir \"${CMAKE_INSTALL_FULL_DATADIR}/openxcom\" )\n  set_property ( SOURCE main.cpp APPEND PROPERTY COMPILE_DEFINITIONS INSTALLDIR=\"${data_install_dir}/\" )\nendif ()\nif ( APPLE )\n  set ( sdl_src \"${MACOS_SDLMAIN_M_PATH}\" )\n  set ( openxcom_src ${openxcom_src} ${sdl_src} )\n  set ( openxcom_icon \"${PROJECT_SOURCE_DIR}/res/mac/AppIcon.icns\" )\n  if ( CREATE_BUNDLE )\n    set ( application_type MACOSX_BUNDLE )\n    set_source_files_properties( ${openxcom_icon} PROPERTIES MACOSX_PACKAGE_LOCATION Resources )\n    set ( MACOSX_BUNDLE_ICON_FILE \"AppIcon.icns\" )\n    set ( MACOSX_BUNDLE_INFO_STRING ${CPACK_PACKAGE_VENDOR} )\n    set ( MACOSX_BUNDLE_GUI_IDENTIFIER \"SupSuper.openxcom\" )\n    set ( MACOSX_BUNDLE_LONG_VERSION_STRING ${CPACK_PACKAGE_VERSION} )\n    set ( MACOSX_BUNDLE_SHORT_VERSION_STRING \"${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}\" )\n    set ( MACOSX_BUNDLE_COPYRIGHT \"Copyright © 2018 OpenXcom Developers. All rights reserved.\" )\n    set ( EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR} )\n    set ( install_dest BUNDLE )\n    set ( set_exec_path OFF )\n    set ( install_dest_dir \"\" )\n    set ( data_install_dir bin )\n    if ( \"${CMAKE_GENERATOR}\" STREQUAL \"Xcode\" )\n      set ( bundle_path \"${EXECUTABLE_OUTPUT_PATH}/${CMAKE_BUILD_TYPE}/openxcom.app\" )\n    else ()\n      set ( bundle_path \"${EXECUTABLE_OUTPUT_PATH}/openxcom.app\" )\n    endif ()\n  else ()\n    set ( data_install_dir \"${CMAKE_INSTALL_FULL_DATADIR}/openxcom\" )\n    add_definitions( -DINSTALLDIR=\"${data_install_dir}/\" )\n  endif ()\nendif ()\nif ( set_exec_path )\n  set ( EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin )\nendif ()\n\nif ( FORCE_INSTALL_DATA_TO_BIN )\n  set ( data_install_dir bin )\nendif ()\n\nif (( APPLE AND CREATE_BUNDLE ) OR CPACK_GENERATOR STREQUAL \"7Z\" )\n  set ( CMAKE_INSTALL_BINDIR \".\" )\nendif ()\n\nadd_executable ( openxcom  ${application_type} ${openxcom_src} ${openxcom_icon} )\n\nif ( EMBED_ASSETS )\n  add_dependencies(openxcom zips)\nendif ()\n\ninstall ( TARGETS openxcom ${install_dest} DESTINATION ${CMAKE_INSTALL_BINDIR} )\n# Extra link flags for Windows. They need to be set before the SDL/YAML link flags, otherwise you will get strange link errors ('Undefined reference to WinMain@16')\nif ( WIN32 )\n  set ( basic_windows_libs advapi32.lib shell32.lib shlwapi.lib wininet.lib urlmon.lib )\n  if ( MINGW )\n    set ( basic_windows_libs ${basic_windows_libs} mingw32 -mwindows )\n    set ( static_flags  -static )\n    set ( SDLMIXER_LIBRARY \"${SDLMIXER_LIBRARY} -lwinmm\" )\n  endif ()\n  set ( system_libs ${basic_windows_libs} SDLmain ${static_flags} )\nendif ()\n\n# backtrace(3) requires libexecinfo on some *BSD systems\nif (${CMAKE_SYSTEM_NAME} MATCHES FreeBSD OR ${CMAKE_SYSTEM_NAME} MATCHES NetBSD OR ${CMAKE_SYSTEM_NAME} MATCHES OpenBSD)\n  set ( system_libs -lexecinfo )\nendif ()\n\nif (WIN32)\n  set(CMAKE_EXE_LINKER_FLAGS -Wl,--export-all-symbols)\n  set(WIN32_LIBS imagehlp dbghelp)\nendif(WIN32)\n\ntarget_link_libraries ( openxcom ${system_libs} ${PKG_DEPS_LDFLAGS} ${EXTRA_XCOM_LIBS} ${WIN32_LIBS} )\n\n# Pack libraries into bundle and link executable appropriately\nif ( APPLE AND CREATE_BUNDLE )\n  include ( PostprocessBundle )\n  postprocess_bundle ( openxcom ${bundle_path} )\nendif ()\n\nif ( NOT EMBED_ASSETS )\n  set ( bin_data_dirs TFTD UFO common standard )\n  foreach ( binpath ${bin_data_dirs} )\n    if ( APPLE AND CREATE_BUNDLE )\n      add_custom_command ( TARGET openxcom\n        POST_BUILD\n        COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/bin/${binpath} ${bundle_path}/Contents/Resources/${binpath}\n\t    VERBATIM )\n    else ()\n      add_custom_command ( TARGET openxcom\n        POST_BUILD\n        COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/bin/${binpath} ${EXECUTABLE_OUTPUT_PATH}/${binpath}\n\t    VERBATIM )\n      install ( DIRECTORY ${CMAKE_SOURCE_DIR}/bin/${binpath} DESTINATION ${data_install_dir} )\n    endif ()\n  endforeach ()\nendif ()\n\n# Copy Windows DLLs to bin folder\nif ( WIN32 )\n  if ( CMAKE_CL_64 )\n    file ( GLOB Windows_dll \"${DEPS_DIR}/lib/x64/*.dll\" )\n  else ( )\n    file ( GLOB Windows_dll \"${DEPS_DIR}/lib/Win32/*.dll\" )\n  endif()\n  foreach ( dll ${Windows_dll} )\n    add_custom_command ( TARGET openxcom\n      POST_BUILD\n      COMMAND ${CMAKE_COMMAND} -E copy ${dll} ${EXECUTABLE_OUTPUT_PATH}\n\t  VERBATIM )\n    install ( FILES ${dll} DESTINATION bin)\n  endforeach()\nendif ()\n\n#Setup source groups for IDE\nif ( MSVC OR \"${CMAKE_GENERATOR}\" STREQUAL \"Xcode\" )\n  source_group ( \"Basescape\" FILES ${basescape_src} )\n  source_group ( \"Battlescape\" FILES ${battlescape_src} )\n  source_group ( \"Engine\" FILES ${engine_src} )\n  source_group ( \"Geoscape\" FILES ${geoscape_src} )\n  source_group ( \"Interface\" FILES ${interface_src} )\n  source_group ( \"Menu\" FILES ${menu_src} )\n  source_group ( \"Mod\" FILES ${mod_src} )\n  source_group ( \"Savegame\" FILES ${savegame_src} )\n  source_group ( \"Ufopedia\" FILES ${ufopedia_src} )\n  if ( APPLE )\n    source_group ( \"SDL\" FILES ${sdl_src} )\n  endif ()\nendif ()\n"
  },
  {
    "path": "src/Engine/Action.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"Action.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Creates a new action.\n * @param scaleX Screen's X scaling factor.\n * @param scaleY Screen's Y scaling factor.\n * @param topBlackBand Screen's top black band height.\n * @param leftBlackBand Screen's left black band width.\n * @param ev Pointer to SDL_event.\n */\nAction::Action(SDL_Event *ev, double scaleX, double scaleY, int topBlackBand, int leftBlackBand) : _ev(ev), _scaleX(scaleX), _scaleY(scaleY), _topBlackBand(topBlackBand), _leftBlackBand(leftBlackBand), _mouseX(-1), _mouseY(-1), _surfaceX(-1), _surfaceY(-1), _sender(0)\n{\n}\n\nAction::~Action()\n{\n}\n\n/**\n * Returns the X scaling factor used by the screen\n * when this action was fired (used to correct mouse input).\n * @return Screen's X scaling factor.\n */\ndouble Action::getXScale() const\n{\n\treturn _scaleX;\n}\n\n/**\n * Returns the Y scaling factor used by the screen\n * when this action was fired (used to correct mouse input).\n * @return Screen's Y scaling factor.\n */\ndouble Action::getYScale() const\n{\n\treturn _scaleY;\n}\n\n/**\n * Sets this action as a mouse action with\n * the respective mouse properties.\n * @param mouseX Mouse's X position.\n * @param mouseY Mouse's Y position.\n * @param surfaceX Surface's X position.\n * @param surfaceY Surface's Y position.\n */\nvoid Action::setMouseAction(int mouseX, int mouseY, int surfaceX, int surfaceY)\n{\n\t_mouseX = mouseX - _leftBlackBand;\n\t_mouseY = mouseY - _topBlackBand;\n\t_surfaceX = surfaceX;\n\t_surfaceY = surfaceY;\n}\n\n/**\n * Gets if the action is a mouse action.\n */\nbool Action::isMouseAction() const\n{\n\treturn (_mouseX != -1);\n}\n\n/**\n * Returns the height in pixel of the\n * top black band if any.\n * @return Screen's top black band.\n */\nint Action::getTopBlackBand() const\n{\n\treturn _topBlackBand;\n}\n\n/**\n * Returns the width in pixel of the\n * left black band if any.\n * @return Screen's left black band.\n */\nint Action::getLeftBlackBand() const\n{\n\treturn _leftBlackBand;\n}\n\n/**\n * Returns the X position of the\n * mouse cursor relative to the game window,\n * or -1 if this isn't a mouse-related action.\n * @return Mouse's X position.\n */\nint Action::getXMouse() const\n{\n\treturn _mouseX;\n}\n\n/**\n * Returns the Y position of the\n * mouse cursor relative to the game window,\n * or -1 if this isn't a mouse-related action.\n * @return Mouse's Y position.\n */\nint Action::getYMouse() const\n{\n\treturn _mouseY;\n}\n\n/**\n * Returns the absolute X position of the\n * mouse cursor relative to the game window,\n * corrected for screen scaling.\n * @return Mouse's absolute X position.\n */\ndouble Action::getAbsoluteXMouse() const\n{\n\tif (_mouseX == -1)\n\t\treturn -1;\n\treturn _mouseX / _scaleX;\n}\n\n/**\n * Returns the absolute Y position of the\n * mouse cursor relative to the game window,\n * corrected for screen scaling.\n * @return Mouse's absolute Y position.\n */\ndouble Action::getAbsoluteYMouse() const\n{\n\tif (_mouseY == -1)\n\t\treturn -1;\n\treturn _mouseY / _scaleY;\n}\n\n/**\n * Returns the relative X position of the\n * mouse cursor relative to the surface that\n * triggered the action, corrected for screen scaling.\n * @return Mouse's relative X position.\n */\ndouble Action::getRelativeXMouse() const\n{\n\tif (_mouseX == -1)\n\t\treturn -1;\n\treturn _mouseX - _surfaceX * _scaleX;\n}\n\n/**\n * Returns the relative Y position of the\n * mouse cursor relative to the surface that\n * triggered the action, corrected for screen scaling.\n * @return Mouse's relative Y position.\n */\ndouble Action::getRelativeYMouse() const\n{\n\tif (_mouseY == -1)\n\t\treturn -1;\n\treturn _mouseY - _surfaceY * _scaleY;\n}\n\n/**\n * Returns the interactive surface that triggered\n * this action (the sender).\n * @return Pointer to interactive surface.\n */\nInteractiveSurface *Action::getSender() const\n{\n\treturn _sender;\n}\n\n/**\n * Changes the interactive surface that triggered\n * this action (the sender).\n * @param sender Pointer to interactive surface.\n */\nvoid Action::setSender(InteractiveSurface *sender)\n{\n\t_sender = sender;\n}\n\n/**\n * Returns the details about this action.\n * @return Pointer to SDL_event.\n */\nSDL_Event *Action::getDetails() const\n{\n\treturn _ev;\n}\n\n}\n"
  },
  {
    "path": "src/Engine/Action.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <SDL.h>\n\nnamespace OpenXcom\n{\n\nclass InteractiveSurface;\n\n/**\n * Container for all the information associated with a\n * given user action, like mouse clicks, key presses, etc.\n * @note Called action because event is reserved.\n */\nclass Action\n{\nprivate:\n\tSDL_Event *_ev;\n\tdouble _scaleX, _scaleY;\n\tint _topBlackBand, _leftBlackBand, _mouseX, _mouseY, _surfaceX, _surfaceY;\n\tInteractiveSurface *_sender;\npublic:\n\t/// Creates an action with given event data.\n\tAction(SDL_Event *ev, double scaleX, double scaleY, int topBlackBand, int leftBlackBand);\n\t/// Cleans up the action.\n\t~Action();\n\t/// Gets the screen's X scale.\n\tdouble getXScale() const;\n\t/// Gets the screen's Y scale.\n\tdouble getYScale() const;\n\t/// Sets the action as a mouse action.\n\tvoid setMouseAction(int mouseX, int mouseY, int surfaceX, int surfaceY);\n\t/// Gets if the action is a mouse action.\n\tbool isMouseAction() const;\n\t/// Gets the top black band height.\n\tint getTopBlackBand() const;\n\t/// Gets the left black band width.\n\tint getLeftBlackBand() const;\n\t/// Gets the mouse's X position.\n\tint getXMouse() const;\n\t/// Gets the mouse's Y position.\n\tint getYMouse() const;\n\t/// Gets the mouse's absolute X position.\n\tdouble getAbsoluteXMouse() const;\n\t/// Gets the mouse's absolute Y position.\n\tdouble getAbsoluteYMouse() const;\n\t/// Gets the mouse's relative X position.\n\tdouble getRelativeXMouse() const;\n\t/// Gets the mouse's relative Y position.\n\tdouble getRelativeYMouse() const;\n\t/// Gets the sender of the action.\n\tInteractiveSurface *getSender() const;\n\t/// Sets the sender of the action.\n\tvoid setSender(InteractiveSurface *sender);\n\t/// Gets the details of the action.\n\tSDL_Event *getDetails() const;\n};\n\n}\n"
  },
  {
    "path": "src/Engine/Adlib/adlplayer.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n/*\n * X-COM Adlib Player by Volutar\n */\n\n#include <stdint.h>\n#include <cmath>\n#include <memory.h>\n#include \"fmopl.h\"\n\n/* Reading a 2-byte value from an unaligned address requires byte-copies on some\n * systems, which the system-memcpy takes care of for us */\nstatic inline unsigned short peek_u16(const unsigned char *ptr)\n{\n\tunsigned short value;\n\tmemcpy(&value, ptr, sizeof(value));\n\treturn value;\n}\n\nconst int16_t adl_gv_freq_table[] = { // 9 * 12 -- notes frequency\n\t0x0B5,0x0C0,0x0CC,0x0D8,0x0E5,0x0F2,0x101,0x110,0x120,0x131,0x143,0x157,\n\t0x16B,0x181,0x198,0x1B0,0x1CA,0x1E5,0x202,0x220,0x241,0x263,0x287,0x2AE,\n\t0x16B,0x181,0x198,0x1B0,0x1CA,0x1E5,0x202,0x220,0x241,0x263,0x287,0x2AE,\n\t0x16B,0x181,0x198,0x1B0,0x1CA,0x1E5,0x202,0x220,0x241,0x263,0x287,0x2AE,\n\t0x16B,0x181,0x198,0x1B0,0x1CA,0x1E5,0x202,0x220,0x241,0x263,0x287,0x2AE,\n\t0x16B,0x181,0x198,0x1B0,0x1CA,0x1E5,0x202,0x220,0x241,0x263,0x287,0x2AE,\n\t0x16B,0x181,0x198,0x1B0,0x1CA,0x1E5,0x202,0x220,0x241,0x263,0x287,0x2AE,\n\t0x16B,0x181,0x198,0x1B0,0x1CA,0x1E5,0x202,0x220,0x241,0x263,0x287,0x2AE,\n\t0x16B,0x181,0x198,0x1B0,0x1CA,0x1E5,0x202,0x220,0x241,0x263,0x287,0x2AE};\n\nconst int8_t adl_gv_octave_table[] = { // 9 * 12 -- octaves of notes\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n\t2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\n\t3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,\n\t4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,\n\t5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,\n\t6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,\n\t7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7};\n\nconst int8_t adl_gv_detune_table[] = { // 9 * 12 -- pitch bend scale values depending on note\n\t3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5,\n\t3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5,\n\t3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5,\n\t3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5,\n\t3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5,\n\t3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5,\n\t3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5,\n\t3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5,\n\t3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5};\n\n/*\nconst uint8_t percus_samples[] = { // 16 * 11  //there was another 13 bytes of 0\n\t0x0F,0x42,0x3F,0x3F,0xFA,0xFA,0x41,0x44,2,3,0x0F,\n\t0x0F,0x02,0x3F,0x3F,0xFA,0xFA,0x51,0x44,2,3,0x0F,\n\t0x0F,0x04,0x3F,0x3F,0xE7,0xDC,0x51,0x46,2,0,0x0F,\n\t0x10,0x00,0x3E,0x3F,0xF8,0xD5,0xFF,0xFF,0,0,0x09,\n\t0x10,0x01,0x32,0x3F,0xF8,0xD5,0x96,0x86,0,0,0x0D,\n\t0x11,0x10,0x3F,0x3F,0x8F,0xC8,0xB4,0x4A,3,0,0x0D,\n\t0x08,0x0F,0x3F,0x3F,0xF1,0xF7,0xFF,0xFF,0,0,0x0F,\n\t0x0F,0x02,0x3F,0x3F,0xEA,0xDA,0x51,0x46,0,3,0x0F,\n\t0x0F,0x02,0x3F,0x3F,0xEA,0xDA,0x51,0x44,0,3,0x0F,\n\t0x02,0x00,0x3C,0x3F,0xF5,0xF8,0x15,0x47,0,0,0x0F,\n\t0x02,0x01,0x39,0x3F,0xF5,0xF8,0x10,0x46,0,0,0x0F,\n\t0x28,0x2F,0x3F,0x3F,0xFA,0xF8,0xF7,0xF4,0,0,0x0F,\n\t0x10,0x01,0x32,0x3F,0xF8,0xD5,0x96,0x86,0,0,0x0F,\n\t0x10,0x00,0x3F,0x3F,0xE9,0xD7,0xD4,0xC5,3,0,0x07,\n\t0x10,0x10,0x32,0x3F,0xF8,0xD7,0x96,0x86,0,0,0x0F,\n\t0x10,0x10,0x32,0x3F,0xF8,0xD4,0x96,0x86,0,0,0x0F,\n\t0x00,0x10,0x32,0x3F,0xF8,0xD4,0x96,0x86,2,0,0x0F};\n\nconst uint8_t percus_mapping[] = { // 32 * 3 -- percussion channel 9 map of buildin adlib samples\n\t0x03,0x15,0x64, 0x03,0x17,0x64, 0x05,0x31,0x64, 0x0A,0x1C,0x55,\n\t0x06,0x28,0x4D, 0x09,0x18,0x55, 0x04,0x1C,0x64, 0x07,0x52,0x4D,\n\t0x04,0x1F,0x64, 0x07,0x52,0x4D, 0x0C,0x21,0x64, 0x08,0x52,0x4D,\n\t0x0C,0x25,0x64, 0x0C,0x28,0x64, 0x00,0x3E,0x64, 0x0C,0x2C,0x50,\n\t0x01,0x3E,0x4D, 0x00,0x3E,0x64, 0x01,0x3F,0x4D, 0x02,0x3E,0x4D,\n\t0x00,0x41,0x64, 0x0B,0x0C,0x4D, 0x00,0x3E,0x64, 0xFF,0xFF,0xFF,\n\t0x01,0x3F,0x4D, 0x0D,0x43,0x55, 0x0D,0x3D,0x55, 0x0E,0x3E,0x64,\n\t0x0F,0x31,0x64, 0x0F,0x2C,0x55, 0x10,0x36,0x4D, 0x10,0x31,0x4D};\n*/\n\nconst int8_t adl_gv_instr_order[] = {0,1,2,3,4,5,6,7,8,10,11,12,13,14,15,9};\n\nconst int8_t adl_gv_operators1[] = {0,1,2, 8,9,10, 16,17,18, 24,25,26};\n\nstatic const int8_t slot_array[32]=\n{\n\t 0, 2, 4, 1, 3, 5,-1,-1,\n\t 6, 8,10, 7, 9,11,-1,-1,\n\t12,14,16,13,15,17,-1,-1,\n\t18,20,22,19,21,23,-1,-1\n};\n\nstruct struc_adlib_channels {\n\tunsigned char\tcur_note;\n\tunsigned char\tcur_instrument;\n\tunsigned char\tcur_sample;\n\tunsigned char\tcur_freq;\n\tunsigned char\thifreq;\n\tunsigned char\tcur_volume;\n\tint\t\t\t\tduration;\n\tint\t\t\t\tpan;\n} adlib_channels[12];\n\nstruct struc_instruments{\n\tunsigned char\tsample_id;\n\tunsigned char\tprev_cmd;\n\tunsigned char\tvolume;\n\tsigned short\tcur_pitchbend;\n\tint\t\t\t\tcur_delay;\n\tunsigned char*\tcur_address;\n\tunsigned char*\tstart_address;\n\tunsigned char*\treturn_address;\n} instruments[16];\n\nstruct struc_sample{\n\tunsigned char\treg20_op1;\n\tunsigned char\treg20_op2;\n\tunsigned char\treg40_op1;\n\tunsigned char\treg40_op2;\n\tunsigned char\treg60_op1;\n\tunsigned char\treg60_op2;\n\tunsigned char\treg80_op1;\n\tunsigned char\treg80_op2;\n\tunsigned char\tregE0_op1;\n\tunsigned char\tregE0_op2;\n\tunsigned char\tregC0;\n};\n\nint adl_gv_master_music_volume = 127;\nint adl_gv_tmp_music_volume = 127;\nbool adl_gv_want_fade = false;\nbool adl_gv_music_playing = false;\nint adl_gv_tempo = 120;\nint adl_gv_tempo_run = 60;\nint adl_gv_tempo_inc = 70;\nunsigned char* adl_gv_samples_addr = 0;\nunsigned char* adl_gv_subtracks[128];\nunsigned int adl_gv_instruments_count = 0;\nunsigned int adl_gv_subtracks_count = 0;\nint adl_gv_polyphony_level = 0;\nunsigned char adl_gv_chorus_instruments[16];\nint adl_gv_FORMAT = 0;//0 = without title, 1=with title\nUINT8 iFMReg[256];\nUINT8 iTweakedFMReg[256];\nUINT8 iCurrentTweakedBlock[12];\nUINT8 iCurrentFNum[12];\nstruc_instruments saved_instruments[2][16];\n\nFM_OPL* opl[2] = {0, 0};\n\n#define NEWBLOCK_LIMIT  32\n#define FREQ_OFFSET 128.0//128.0//96.0\n\n\nvoid Transpose(int reg, int val, int*val2, int *reg3, int*val3)\n{\n\t// Transpose the other channel to produce the harmonic effect\n\tint iChannel = -1;\n\tint iRegister = reg; // temp\n\tint iValue = val; // temp\n\tif ((iRegister >> 4 == 0xA) || (iRegister >> 4 == 0xB)) iChannel = iRegister & 0x0F;\n\n\t// Remember the FM state, so that the harmonic effect can access\n\t// previously assigned register values.\n\t/*if (((iRegister >> 4 == 0xB) && (iValue & 0x20) && !(this->iFMReg[iRegister] & 0x20)) ||\n\t\t(iRegister == 0xBD) && (\n\t\t\t((iValue & 0x01) && !(this->iFMReg[0xBD] & 0x01))\n\t\t)) {\n\t\tthis->iFMReg[iRegister] = iValue;\n\t}*/\n\tiFMReg[iRegister] = iValue;\n\n\tif ((iChannel >= 0 && iChannel < 12)) {// && (i == 1)) {\n\t\tUINT8  iBlock = (iFMReg[0xB0 + iChannel] >> 2) & 0x07;\n\t\tUINT16 iFNum = ((iFMReg[0xB0 + iChannel] & 0x03) << 8) | iFMReg[0xA0 + iChannel];\n\t\t//double dbOriginalFreq = 50000.0 * (double)iFNum * pow(2, iBlock - 20);\n\t\tdouble dbOriginalFreq = 49716.0 * (double)iFNum / pow((double)2, (20 - iBlock));\n\n\t\tUINT8  iNewBlock = iBlock;\n\t\tUINT16 iNewFNum;\n\n\t\t// Adjust the frequency and calculate the new FNum\n\t\t//double dbNewFNum = (dbOriginalFreq+(dbOriginalFreq/FREQ_OFFSET)) / (50000.0 * pow(2, iNewBlock - 20));\n\t\t//#define calcFNum() ((dbOriginalFreq+(dbOriginalFreq/FREQ_OFFSET)) / (50000.0 * pow(2, iNewBlock - 20)))\n\t\t#define calcFNum() ((dbOriginalFreq+(dbOriginalFreq/FREQ_OFFSET)) / (49716.0 / pow(2.0f, 20 - iNewBlock)))\n\t\tdouble dbNewFNum = calcFNum();\n\n\t\t// Make sure it's in range for the OPL chip\n\t\tif (dbNewFNum > 1023 - NEWBLOCK_LIMIT) {\n\t\t\t// It's too high, so move up one block (octave) and recalculate\n\n\t\t\tif (iNewBlock > 6) {\n\t\t\t\t// Uh oh, we're already at the highest octave!\n\t\t\t\t// The best we can do here is to just play the same note out of the second OPL, so at least it shouldn't\n\t\t\t\t// sound *too* bad (hopefully it will just miss out on the nice harmonic.)\n\t\t\t\tiNewBlock = iBlock;\n\t\t\t\tiNewFNum = iFNum;\n\t\t\t} else {\n\t\t\t\tiNewBlock++;\n\t\t\t\tiNewFNum = (UINT16)calcFNum();\n\t\t\t}\n\t\t} else if (dbNewFNum < 0 + NEWBLOCK_LIMIT) {\n\t\t\t// It's too low, so move down one block (octave) and recalculate\n\n\t\t\tif (iNewBlock == 0) {\n\t\t\t\t// Uh oh, we're already at the lowest octave!\n\t\t\t\t// The best we can do here is to just play the same note out of the second OPL, so at least it shouldn't\n\t\t\t\t// sound *too* bad (hopefully it will just miss out on the nice harmonic.)\n\t\t\t\tiNewBlock = iBlock;\n\t\t\t\tiNewFNum = iFNum;\n\t\t\t} else {\n\t\t\t\tiNewBlock--;\n\t\t\t\tiNewFNum = (UINT16)calcFNum();\n\t\t\t}\n\t\t} else {\n\t\t\t// Original calculation is within range, use that\n\t\t\tiNewFNum = (UINT16)dbNewFNum;\n\t\t}\n\n\t\t// Sanity check\n\t\tif (iNewFNum > 1023) {\n\t\t\t// Uh oh, the new FNum is still out of range! (This shouldn't happen)\n\t\t\t// The best we can do here is to just play the same note out of the second OPL, so at least it shouldn't\n\t\t\t// sound *too* bad (hopefully it will just miss out on the nice harmonic.)\n\t\t\tiNewBlock = iBlock;\n\t\t\tiNewFNum = iFNum;\n\t\t}\n\n\t\tif ((iRegister >= 0xB0) && (iRegister <= 0xBC)) {\n\n\t\t\t// Overwrite the supplied value with the new F-Number and Block.\n\t\t\tiValue = (iValue & ~0x1F) | (iNewBlock << 2) | ((iNewFNum >> 8) & 0x03);\n\n\t\t\tiCurrentTweakedBlock[iChannel] = iNewBlock; // save it so we don't have to update register 0xB0 later on\n\t\t\tiCurrentFNum[iChannel] = iNewFNum;\n\n\t\t\tif (iTweakedFMReg[0xA0 + iChannel] != (iNewFNum & 0xFF)) {\n\t\t\t\t// Need to write out low bits\n\t\t\t\tUINT8  iAdditionalReg = 0xA0 + iChannel;\n\t\t\t\tUINT8  iAdditionalValue = iNewFNum & 0xFF;\n\t\t\t\t*reg3 = iAdditionalReg;\n\t\t\t\t*val3 = iAdditionalValue;\n\t\t\t\tiTweakedFMReg[iAdditionalReg] = iAdditionalValue;\n\t\t\t}\n\t\t} else if ((iRegister >= 0xA0) && (iRegister <= 0xAC)) {\n\n\t\t\t// Overwrite the supplied value with the new F-Number.\n\t\t\tiValue = iNewFNum & 0xFF;\n\n\t\t\t// See if we need to update the block number, which is stored in a different register\n\t\t\tUINT8  iNewB0Value = (iFMReg[0xB0 + iChannel] & ~0x1F) | (iNewBlock << 2) | ((iNewFNum >> 8) & 0x03);\n\t\t\tif (\n\t\t\t\t(iNewB0Value & 0x20) && // but only update if there's a note currently playing (otherwise we can just wait\n\t\t\t\t(iTweakedFMReg[0xB0 + iChannel] != iNewB0Value)   // until the next noteon and update it then)\n\t\t\t) {\n\t\t\t\t\t// The note is already playing, so we need to adjust the upper bits too\n\t\t\t\t\tUINT8  iAdditionalReg = 0xB0 + iChannel;\n\t\t\t\t\t*reg3 = iAdditionalReg;\n\t\t\t\t\t*val3 = iNewB0Value;\n\t\t\t\t\tiTweakedFMReg[iAdditionalReg] = iNewB0Value;\n\t\t\t} // else the note is not playing, the upper bits will be set when the note is next played\n\n\t\t} // if (register 0xB0 or 0xA0)\n\n\t} // if (a register we're interested in)\n\n\t// Now write to the original register with a possibly modified value\n\t*val2=iValue;\n\tiTweakedFMReg[iRegister] = iValue;\n};\n\n/*\nvoid adlib_reg(int i, int v)\n{\n//\tadlib0(i,v);\n\tOPLWrite(opl[0],0,i);\n\tOPLWrite(opl[0],1,v);\n\n//\tif (i==1) v=0x20;\n\tif (i==0xbd) v=0x00;\n\tOPLWrite(opl[1],0,i);\n\tOPLWrite(opl[1],1,v);\n//\tYM3812Write(0, 0, i);\n//\tYM3812Write(0, 1, v);\n}\n*/\n\nvoid adlib_reg(int i, int v)\n{\n\tif (opl[0]==0) return;\n\tint v2, i3, v3;\n\ti3 = -1;\n\tTranspose(i, v, &v2, &i3, &v3);\n\n\tOPLWrite(opl[0], 0, i);\n\tOPLWrite(opl[0], 1, v);\n\tOPLWrite(opl[1], 0, i);\n\tif (i >= 0x20 && i <= 0x3f) //no tremolo/vibrato\n\t\tv2 = (v2 & 0x3F);\n\tif (i >= 0xE0 && i <= 0xFC)\n\t{\n\t\tif ((slot_array[i & 0x1f] & 1) == 1) //wave form\n\t\t\tv2 = v2 & 0x02;\n\t}\n\t// if ((i >= 0x60 && i <= 0x7F) && ((slot_array[i & 0x1f] & 1) == 1)) //altered attack/decoy\n\t//\tv2 = v2 ^ 0x20;\n\tOPLWrite(opl[1], 1, v2);\n\tif (i3 != -1)\n\t{\n\t\tOPLWrite(opl[1], 0, i3);\n\t\tOPLWrite(opl[1], 1, v3);\n\t}\n}\n\n\n// initialises adlib parameters\nvoid adlib_init()\n{\n\tfor (int i=1; i<0xf5; ++i) adlib_reg(i,0);\n\tadlib_reg(0x04, 0x60); //set both timers\n\tadlib_reg(0x04, 0x80); //reset timers\n\tadlib_reg(0x01, 0x20); //bit5 defines any wave form\n\tadlib_reg(0xa8, 0x01); //last channel freq -??\n\tadlib_reg(0x08, 0x40); //note mode\n\tadlib_reg(0xbd, 0xC0); // vibrato/AM depth\n}\n\n\n// sets voice amplitude for particular adlib channel\nvoid adlib_set_amplitude(int channel, int value)\n{\n\tadlib_reg(0x43+adl_gv_operators1[channel],  ~(value>>1) & 0x3f);\n}\n\n// clear channel notes and samples\nvoid clear_channels()\n{\n\tfor (int i=0; i<12; ++i)\n\t{\n\t\tadlib_channels[i].cur_sample = 0xff;\n\t\tadlib_channels[i].cur_note = 0;\n\t}\n}\n\n// resets (clears) adlib channels\nvoid adlib_reset_channels()\n{\n\tclear_channels();\n\tfor (int i=0; i<12; ++i)\n\t{\n\t\tadlib_reg(0xB0+i, 0);\n\t\tadlib_set_amplitude(i, 0);\n\t}\n}\n\n// returns note frequency with pitch wheel value applied\nint get_pitched_freq_instr(int note, int instrument)\n{\n\tint pitch = instruments[instrument].cur_pitchbend;\n\tif (pitch==0)\n\t\treturn adl_gv_freq_table[note];\n\telse if (pitch>0)\n\t\treturn adl_gv_freq_table[note] + adl_gv_detune_table[note]*pitch;\n\telse\n\t\treturn adl_gv_freq_table[note] + adl_gv_detune_table[note-1]*pitch;\n}\n\n// sets pitch for particular instrument\n// apply for adlib channels with same instrument\n// !!! probably should also apply pitch for CHORUS instrument !!!\nvoid adlib_set_instrument_pitch(int instrument, int pitch)\n{\n\tinstruments[instrument].cur_pitchbend = pitch;\n\tfor (int i=0; i<12; ++i) //search through active adlib channels\n\t{\n\t\tint note = adlib_channels[i].cur_note;\n\t\tif (note != 0 && adlib_channels[i].cur_instrument == instrument)\n\t\t{\n\t\t\tint freq = get_pitched_freq_instr(note, instrument);\n\t\t\tadlib_channels[i].cur_freq = freq;\n\t\t\tadlib_reg(0xA0+i, freq & 0xff);\n\t\t\tint hf=((freq>>8) & 0x03) | (adl_gv_octave_table[note]<<2);\n\t\t\tadlib_channels[i].hifreq = hf;\n\t\t\tadlib_reg(0xB0+i, hf | 0x20);\n\t\t}\n\t}\n}\n\n// gets unused adlib channel and checks if old sample is the same\nint adlib_get_unused_channel(int sample_id, bool* same_sample)\n{\n\tint maxchan=0, maxdur=0, i;\n\t//bool empty=false;\n\n\tfor (i=0; i<12; ++i)\n\t\t++adlib_channels[i].duration;\n\n\tfor (i=0; i<12; ++i) //12/9\n\t{\n\t\tif (adlib_channels[i].duration > maxdur)\n\t\t{\n\t\t\tmaxdur = adlib_channels[i].duration;\n\t\t\tmaxchan = i;\n\t\t}\n\t\tif (adlib_channels[i].cur_note == 0) //empty channel\n\t\t{\n\t\t\tmaxchan = i;\n\t\t\t//empty = true;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t//if (!empty) printf(\"   POLYPHONY - channel %d replaced\\n\", maxchan);\n\tif (adlib_channels[maxchan].cur_sample == sample_id)\n\t\t*same_sample = true;\n\telse\n\t\tadlib_channels[maxchan].cur_sample = sample_id;\n\tadlib_channels[maxchan].duration = 0;\n\treturn maxchan;\n}\n\n//starts playing note of particular instrument\nvoid adlib_play_note(int note, int volume, int instrument)\n{\n\tstruc_sample* cur_sample;\n\tint sample_id = instruments[instrument].sample_id;\n\tint channel;\n\tint ampl;\n\tint op1;\n\tbool same_sample = false;\n/*\tif (instrument == 9) //percussion instrument?\n\t{\n\t\tif (note>65 || note<35) return;// skip if out of range\n\t\tsample_id = note-35;\n\t\tif (percus_mapping[sample_id*3]==0xff) return;\n\t\tcur_sample = (struc_sample*)&( percus_samples[(percus_mapping[sample_id*3])*11] );\n\t\tnote = percus_mapping[sample_id*3+1];\n\t\tsample_id += 128; //percussion sample is beyond ordinary (for compare purpose)\n\t}\n\telse //ordinary sample\n*/\t{\n\t\tcur_sample = (struc_sample*)(adl_gv_samples_addr + sample_id*24);\n\t}\n\tnote--;\n\tif (volume == 0) //stop note\n\t{\n\t\tfor(int i=0; i<12; ++i)\n\t\t{\n\t\t\tif (adlib_channels[i].cur_note == note &&\n\t\t\t\tadlib_channels[i].cur_instrument == instrument)\n\t\t\t{\n\t\t\t\tadlib_channels[i].cur_note = 0; //clear channel\n\t\t\t\tadlib_reg(0xB0+i, adlib_channels[i].hifreq); //mute note\n\t\t\t}\n\t\t}\n\t\treturn;\n\t}\n\tif (volume>127) volume=127;\n\tchannel = adlib_get_unused_channel(sample_id, &same_sample);\n\tadlib_channels[channel].cur_volume = volume;\n\tadlib_channels[channel].cur_note = note;\n\tadlib_channels[channel].cur_instrument = instrument;\n\top1 = adl_gv_operators1[channel];\n\tif (!same_sample)\n\t{\n\t\tadlib_reg(0x20+op1, cur_sample->reg20_op1); //amp mod / vibrato / eg type\n\t\tadlib_reg(0x23+op1, cur_sample->reg20_op2); //key scaling / multiple\n\t\tampl = cur_sample->reg40_op1;\n\t\tadlib_reg(0x40+op1, ((~ampl) & 0x3f) | (ampl & 0xc0)); // amplitude op1\n\t}\n\n\tadlib_reg(0xB0+channel, adlib_channels[channel].hifreq);  // reinit note\n\tadlib_reg(0x43+op1, (~((adl_gv_tmp_music_volume*volume)>>8))&0x3f); //amplitude op2\n\n\tif (!same_sample)\n\t{\n\t\tadlib_reg(0x60+op1, cur_sample->reg60_op1); //attack rate/decay rate\n\t\tadlib_reg(0x63+op1, cur_sample->reg60_op2);\n\t\tadlib_reg(0x80+op1, cur_sample->reg80_op1); //sustain level / release rate\n\t\tadlib_reg(0x83+op1, cur_sample->reg80_op2);\n\t\tadlib_reg(0xE0+op1, cur_sample->regE0_op1); //wave select\n\t\tadlib_reg(0xE3+op1, cur_sample->regE0_op2);\n\t\tadlib_reg(0xC0+channel, cur_sample->regC0 ^ 0x01); //feedback strength / connection type\n\t}\n\n\tint freq = get_pitched_freq_instr(note, instrument);\n\tadlib_channels[channel].cur_freq = freq;\n\tadlib_reg(0xA0+channel, freq & 0xff);\n\tint hf=(freq>>8) | (adl_gv_octave_table[note]<<2);\n\tadlib_channels[channel].hifreq = hf;\n\tadlib_reg(0xB0+channel, hf | 0x20); //reinit note\n}\n\n//reads running-length value from data stream\nint get_numseq(unsigned char** mus_ptr)\n{\n\tunsigned char c;\n\tint v=0;\n\tdo {\n\t\tc = *(*(unsigned char**)mus_ptr);\n\t\tv = (v<<7) + (c & 0x7f);\n\t\t(*((unsigned char**)mus_ptr))++;\n\t} while (c&0x80);\n\treturn v;\n}\n\n//MAIN FUNCTION - instantly stops music\nvoid func_mute()\n{\n\tadl_gv_polyphony_level = 0;\n\tadl_gv_music_playing = false;\n\tadlib_reset_channels();\n}\n\n//decrease volume until 0 with each call, and then stops music\nvoid fade_volume_if_need()\n{\n\tif (!adl_gv_want_fade) return;\n\tif (--adl_gv_tmp_music_volume == 0)\n\t{\n\t\tfunc_mute();\n\t\tadl_gv_want_fade = false;\n\t\tadl_gv_tmp_music_volume = adl_gv_master_music_volume;\n\t\treturn;\n\t}\n\tfor (int i=0; i<12; ++i)\n\t{\n\t\tadlib_set_amplitude(i, (adlib_channels[i].cur_volume*adl_gv_tmp_music_volume)>>7);\n\t}\n}\n\n// checks if there are unused adlib channels\nbool free_channel_available()\n{\n\n\tfor (int i=0; i<12; ++i)\n\t{\n\t\tif (adlib_channels[i].cur_note==0)\n\t\t\treturn true;\n\t}\n\treturn false;\n}\n\n// main decode function - reads data from stream and decodes it accordingly\nint decode_op(int instrument, bool* another_loop)\n{\n//\tconst track=2;\n\tstruc_instruments* instr1 = &instruments[instrument];\n\tstruc_instruments* instr2;\n\tunsigned char* music_ptr = instr1->cur_address;\n\tunsigned char opcode,arg1,arg2;\n\tint delay = 0;\n\n\tdo {\n\t\topcode = *(music_ptr++);\n\t\tif (opcode == 0xfe) //call for subtrack\n\t\t{\n\t\t\targ1 = *(music_ptr++);\n\t\t\t\t//printf(\"Call for subtrack [%d] %d\\n\",instrument,arg1);\n\t\t\tinstr1->return_address = music_ptr;\n\t\t\tmusic_ptr = adl_gv_subtracks[arg1];\n\t\t}\n\t\telse if (opcode == 0xfd) //return from subtrack\n\t\t{\n\t\t\tif (instr1->return_address == 0)\n\t\t\t{\n\t\t\t\t//printf(\"Return from subtrack [%d] -> DOUBLE RETURN - ERROR\\n\",instrument);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tmusic_ptr = instr1->return_address;\n\t\t\t\t\t//printf(\"Return from subtrack [%d] -> %x\\n\",instrument,instr1->return_address);\n\t\t\t\tinstr1->return_address = 0;\n\t\t\t}\n\t\t}\n\t\telse if (opcode == 0xff) //finishing track\n\t\t{\n\t\t\t\t//printf(\"Track finish [%d]\\n\",instrument);\n\t\t\tadl_gv_music_playing = false;\n\t\t\tdelay = 0;\n\t\t\tbreak;\n\t\t}\n\t\telse if (opcode >= 0x80) //opcode\n\t\t{\n\t\t\tinstr1->prev_cmd = opcode;\n\t\t\t\t//printf(\"Opcode [%d]: %02Xh\\n\", instrument, opcode);\n\t\t\topcode = *(music_ptr++); //read \"repeated\" opcode which goes to arg\n\t\t}\n\n\t\tif (opcode<0x80) //can be not a opcode, just the repeated command\n\t\t{\n\t\t\targ1 = opcode;\n\t\t\topcode = instr1->prev_cmd;\n\t\t\tswitch (opcode & 0xf0) {\n\t\t\tcase 0x80: //note off\n\t\t\t\targ2 = *(music_ptr++);\n\t\t\t\t\t//printf(\"Opcode [%d] NOTE OFF: %d\\n\", instrument, arg1);\n\t\t\t\tadlib_play_note(arg1,0,instrument);\n\t\t\t\t--adl_gv_polyphony_level;\n\t\t\t\tif (adl_gv_chorus_instruments[instrument] != 0)\n\t\t\t\t{\n\t\t\t\t\tadlib_play_note(arg1,0,adl_gv_chorus_instruments[instrument]);\n\t\t\t\t\t--adl_gv_polyphony_level;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 0x90: //note on\n\t\t\t\targ2 = *(music_ptr++);\n\t\t\t\tif (arg2 == 0) //volume==0 - note off\n\t\t\t\t{\n\t\t\t\t\t\t//printf(\"Opcode [%d] NOTE off: %d, volume=%d\\n\", instrument, arg1, arg2);\n\t\t\t\t\tadlib_play_note(arg1,0,instrument);\n\t\t\t\t\t--adl_gv_polyphony_level;\n\t\t\t\t\tif (adl_gv_chorus_instruments[instrument] != 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tadlib_play_note(arg1,0,adl_gv_chorus_instruments[instrument]);\n\t\t\t\t\t\t--adl_gv_polyphony_level;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t\t//printf(\"Opcode [%d] NOTE ON: %d, volume=%d\\n\", instrument, arg1, arg2);\n\t\t\t\t\tint vol = (arg2*instr1->volume)>>7;\n\t\t\t\t\tif (adl_gv_chorus_instruments[instrument] != 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (free_channel_available())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tinstr2 = &instruments[adl_gv_chorus_instruments[instrument]];\n\t\t\t\t\t\t\tinstr2->sample_id = instr1->sample_id;\n\t\t\t\t\t\t\tinstr2->cur_pitchbend = instr1->cur_pitchbend-1;\n\t\t\t\t\t\t\tadlib_play_note(arg1,vol,adl_gv_chorus_instruments[instrument]);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t++adl_gv_polyphony_level; //increase it nevertheless, because it SHOULD play\n\t\t\t\t\t}\n\t\t\t\t\tadlib_play_note(arg1,vol,instrument);\n\t\t\t\t\t++adl_gv_polyphony_level;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 0xB0: //set controller\n\t\t\t\targ2 = *(music_ptr++);\n\t\t\t\t\t//printf(\"Opcode [%d] CONTROLLER: %02Xh, %d\\n\", instrument, arg1, arg2);\n\t\t\t\tif (arg1 == 0 && arg2 != 0) //tempo change\n\t\t\t\t\tadl_gv_tempo = arg2 * 0.8;\n\t\t\t\telse if (arg1 == 7) //channel volume change\n\t\t\t\t{\n\t\t\t\t\tinstr1->volume = arg2;\n/*\t\t\t\t\tfor (i=0; i<9; ++i)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (instrument == adlib_channels[i].cur_instrument)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tadlib_channels[i].cur_volume = arg2;\n\t\t\t\t\t\t\tadlib_set_amplitude(i, (arg2*adl_gv_tmp_music_volume)>>7);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n*/\t\t\t\t}\n\t\t\t\telse if (arg1 == 0x7e) //setting up chorus (slave) instrument\n\t\t\t\t\tadl_gv_chorus_instruments[instrument] = arg2-1;\n\t\t\t\telse if (arg1 == 0x7f) //clearing chorus (slave) instrument\n\t\t\t\t\tadl_gv_chorus_instruments[instrument] = 0;\n\n\t\t\t\tbreak;\n\t\t\tcase 0xC0: //set sample\n\t\t\t\tif (arg1 == 0x7E)\n\t\t\t\t{\n\t\t\t\t\t*another_loop = 1;\n\t\t\t\t\t\t//printf(\"Opcode [%d] LOOP\\n\",instrument);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t\t//printf(\"Opcode [%d] SAMPLE: %d\\n\",instrument, arg1);\n\t\t\t\t\tinstr1->sample_id = arg1;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 0xE0: //pitch bend\n\t\t\t\t\t//printf(\"Opcode [%d] PITCH BEND: %d\\n\", instrument, arg1-16);\n\t\t\t\tinstr1->cur_pitchbend = arg1-16; // no need???\n\t\t\t\tadlib_set_instrument_pitch(instrument, arg1-16);\n\t\t\t\tif (adl_gv_chorus_instruments[instrument] != 0)\n\t\t\t\t\tadlib_set_instrument_pitch(adl_gv_chorus_instruments[instrument], arg1-17);\n\t\t\t}\n\t\t}\n\t\tdelay = get_numseq(&music_ptr);\n\t} while (delay==0);\n\tinstr1->cur_address = music_ptr;\n\t//if (delay!=0) printf(\"* Delay[%d] = %d\\n\", instrument, delay);\n\treturn delay;\n}\n\n// music initialization function, sets up subblock array,\n// tempo, instrument addresses and samples\nvoid init_music_data(unsigned char* music_ptr,int length)\n{\n\tunsigned int i, to_add, j;\n\tunsigned char* start=music_ptr;\n\tfor (i=0; i<16; ++i)\n\t{\n\t\tinstruments[i].start_address = 0;\n\t}\n\tadl_gv_subtracks_count = 0;\n\n\ti = *music_ptr;\n\tif (i>56) adl_gv_FORMAT=0; //switch to old\n\telse  adl_gv_FORMAT=1;\n\tif (adl_gv_FORMAT==1) music_ptr += (*music_ptr )+1; //skip name\n\tadl_gv_tempo = *(music_ptr++);\n\tadl_gv_samples_addr = music_ptr+1; //samples\n\tmusic_ptr += ((*music_ptr) * 24) +1; //moving to next section - subtracks\n\tadl_gv_subtracks_count = *(music_ptr++);\n\tfor(i=0; i<adl_gv_subtracks_count; ++i)\n\t{\n\t\tto_add = peek_u16(music_ptr); //reading 16bit length\n\t\tadl_gv_subtracks[i] = music_ptr+4; //store subtrack pointers\n\t\tmusic_ptr += to_add;\n\t}\n\tadl_gv_instruments_count = *(music_ptr++);\n\tfor (i=0; i<adl_gv_instruments_count; ++i)\n\t{\n\t\tto_add = peek_u16(music_ptr); //reading 16bit length\n\t\tif (adl_gv_FORMAT==1)\n\t\t{\n\t\t\tj = *(music_ptr+4);\n\t\t\tif (j>15) j=15;\n\t\t\tinstruments[j].start_address = music_ptr+5;\n\t\t}\n\t\telse\n\t\tif (adl_gv_FORMAT==0)\n\t\t{\n\t\t\tj = i;\n\t\t\tinstruments[j].start_address = music_ptr+4; //old format, without title\n\t\t}\n\t\tmusic_ptr += to_add;\n\t\tif (music_ptr-start>=length)\n\t\t{\n\t\t\t//printf(\"DATA ERROR: track number %d has a length of %d, and gone to offset %d\\n\",i,to_add,music_ptr-start);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n\n//initialize music tracks, prepare for playing\nvoid init_music()\n{\n\tfor (int i=0; i<16; ++i)\n\t{\n\t\tinstruments[i].cur_pitchbend = 0;\n\t\tadl_gv_chorus_instruments[i] = 0;\n\t\tif (instruments[i].start_address != 0)\n\t\t{\n\t\t\tinstruments[i].cur_address = instruments[i].start_address;\n\t\t\tinstruments[i].cur_delay = get_numseq(&instruments[i].cur_address);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tinstruments[i].cur_address = 0;\n\t\t\tinstruments[i].cur_delay = 0;\n\t\t}\n\t}\n}\n\n//save music state\nvoid func_save_music_state(int i)\n{\n\tmemcpy(&saved_instruments[i], &instruments, sizeof(instruments));\n}\n//load music state\nvoid func_load_music_state(int i)\n{\n\tadlib_reset_channels();\n\tmemcpy(&instruments, &saved_instruments[i], sizeof(instruments));\n}\n\n\n//MAIN FUNCTION - runs 1 tick of music according tempo\nvoid func_play_tick()\n{\n\tbool another_loop;\n\n\tif (!adl_gv_music_playing) return;\n\tfade_volume_if_need();\n\tadl_gv_tempo_run -= adl_gv_tempo;\n\tif (adl_gv_tempo_run>0) return;\n\tadl_gv_tempo_run += adl_gv_tempo_inc;\n\n\tdo {\n\t\tanother_loop = false;\n\t\tfor (int i=0; i<16; ++i)\n\t\t{\n\t\t\tint instr = adl_gv_instr_order[i];\n//\t\t\tif (instr!=10) continue;\n\t\t\tif (instruments[instr].cur_address == 0) continue;\n\t\t\tif (instruments[instr].cur_delay == 0)\n\t\t\t{\n\t\t\t\tinstruments[instr].cur_delay = decode_op(instr,&another_loop);\n\t\t\t\tif (!adl_gv_music_playing) break;\n\t\t\t}\n\t\t\t--instruments[instr].cur_delay;\n\t\t}\n\t\tif (!another_loop && adl_gv_music_playing) break;\n\t\tinit_music();\n\t\tclear_channels();\n\t} while (another_loop);\n}\n\n//MAIN FUNCTION - setup music for playing\nvoid func_setup_music(unsigned char* music_ptr, int length)\n{\n\tadl_gv_music_playing = false;\n\tfunc_mute();\n\tadl_gv_polyphony_level = 0;\n\tadl_gv_want_fade = false;\n\tadl_gv_tmp_music_volume = adl_gv_master_music_volume;\n\tinit_music_data(music_ptr,length);\n\tinit_music();\n\tadlib_init();\n\tadlib_reset_channels();\n\tadl_gv_tempo *= 0.4;\n\tadl_gv_tempo_run = adl_gv_tempo;\n\tadl_gv_music_playing = true;\n}\n\n//MAIN FUNCTION - initialize fade procedure\nvoid func_fade()\n{\n\tif (adl_gv_tmp_music_volume == 0)\n\t{\n\t\tfunc_mute();\n\t}\n\telse\n\t{\n\t\tadl_gv_want_fade = true;\n\t}\n}\n\n//MAIN FUNCTION - check if music finished\nbool func_is_music_playing()\n{\n\treturn adl_gv_music_playing;\n}\n\nvoid func_set_music_tempo(int value)\n{\n\tadl_gv_tempo_inc = value;\n}\n\nvoid func_set_music_volume(int value)\n{\n\tadl_gv_master_music_volume = value;\n\tadl_gv_tmp_music_volume = adl_gv_master_music_volume;\n\n\tfor (int i=0; i<12; ++i)\n\t{\n\t\tadlib_set_amplitude(i, (adlib_channels[i].cur_volume*adl_gv_tmp_music_volume)>>7);\n\t}\n}\n\nint func_get_polyphony()\n{\n\treturn adl_gv_polyphony_level;\n}\n"
  },
  {
    "path": "src/Engine/Adlib/adlplayer.h",
    "content": "#pragma once\n/* ADLPLAYER.H\n *\n * player functions for midi-like adlib music\n *\n */\n\n//MAIN FUNCTION - instantly stops music\nvoid func_mute();\n//MAIN FUNCTION - runs 1 tick of music according tempo\nvoid func_play_tick();\n//MAIN FUNCTION - setup music for playing\nvoid func_setup_music(unsigned char* music_ptr, int length);\n//MAIN FUNCTION - initialize fade procedure\nvoid func_fade();\nbool func_is_music_playing();\nvoid func_set_music_tempo(int value);\nvoid func_set_music_volume(int value);\nint func_get_polyphony();\nvoid func_save_music_state(int i);\nvoid func_load_music_state(int i);\n"
  },
  {
    "path": "src/Engine/Adlib/fmopl.cpp",
    "content": "/*\n**\n** File: fmopl.c -- software implementation of FM sound generator\n**\n** Copyright (C) 1999,2000 Tatsuyuki Satoh , MultiArcadeMachineEmurator development\n**\n** Version 0.37a\n**\n*/\n\n/*\n * Modified version for X-COM (increased polyphony) by Volutar\n*/\n\n/* This version of fmopl.c is a fork of the MAME one, relicensed under the LGPL.\n *\n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\n */\n\n#if defined(_MSC_VER) && (_MSC_VER < 1900)\n#define INLINE\t\t__inline\n#else\n#define INLINE\t\tstatic inline\n#endif\n#define HAS_YM3812\t1\n\n#include <stdlib.h>\n#include <string.h>\n#include <cmath>\n//#include \"driver.h\"\t\t/* use M.A.M.E. */\n#include \"fmopl.h\"\n#include \"../RNG.h\"\n\n#ifndef PI\n#define PI 3.14159265358979323846\n#endif\n\n/* -------------------- for debug --------------------- */\n/* #define OPL_OUTPUT_LOG */\n#ifdef OPL_OUTPUT_LOG\n#include <stdio.h>\nstatic FILE *opl_dbg_fp = NULL;\nstatic FM_OPL *opl_dbg_opl[16];\nstatic int opl_dbg_maxchip,opl_dbg_chip;\n#endif\n\n/* -------------------- preliminary define section --------------------- */\n/* attack/decay rate time rate */\n#define OPL_ARRATE     141280  /* RATE 4 =  2826.24ms @ 3.6MHz */\n#define OPL_DRRATE    1956000  /* RATE 4 = 39280.64ms @ 3.6MHz */\n\n#define DELTAT_MIXING_LEVEL (1) /* DELTA-T ADPCM MIXING LEVEL */\n\n#define FREQ_BITS 24\t\t\t/* frequency turn          */\n\n/* counter bits = 20 , octerve 7 */\n#define FREQ_RATE   (1<<(FREQ_BITS-20))\n#define TL_BITS    (FREQ_BITS+2)\n\n/* final output shift , limit minimum and maximum */\n#define OPL_OUTSB   (TL_BITS+1-16)\t\t/* OPL output final shift 16bit */\n#define OPL_MAXOUT (0x7fff<<OPL_OUTSB)\n#define OPL_MINOUT (-(0x8000<<OPL_OUTSB))\n\n/* -------------------- quality selection --------------------- */\n\n/* sinwave entries */\n/* used static memory = SIN_ENT * 4 (byte) */\n#define SIN_ENT 2048\n\n/* output level entries (envelope,sinwave) */\n/* envelope counter lower bits */\n#define ENV_BITS 16\n/* envelope output entries */\n#define EG_ENT   4096\n/* used dynamic memory = EG_ENT*4*4(byte)or EG_ENT*6*4(byte) */\n/* used static  memory = EG_ENT*4 (byte)                     */\n\n#define EG_OFF   ((2*EG_ENT)<<ENV_BITS)  /* OFF          */\n#define EG_DED   EG_OFF\n#define EG_DST   (EG_ENT<<ENV_BITS)      /* DECAY  START */\n#define EG_AED   EG_DST\n#define EG_AST   0                       /* ATTACK START */\n\n#define EG_STEP (96.0/EG_ENT) /* OPL is 0.1875 dB step  */\n\n/* LFO table entries */\n#define VIB_ENT 512\n#define VIB_SHIFT (32-9)\n#define AMS_ENT 512\n#define AMS_SHIFT (32-9)\n\n#define VIB_RATE 256\n\n/* -------------------- local defines , macros --------------------- */\n\n/* register number to channel number , slot offset */\n#define SLOT1 0\n#define SLOT2 1\n\n/* envelope phase */\n#define ENV_MOD_RR  0x00\n#define ENV_MOD_DR  0x01\n#define ENV_MOD_AR  0x02\n\n/* -------------------- tables --------------------- */\nstatic const int slot_array[32]=\n{\n\t 0, 2, 4, 1, 3, 5,-1,-1,\n\t 6, 8,10, 7, 9,11,-1,-1,\n\t12,14,16,13,15,17,-1,-1,\n\t18,20,22,19,21,23,-1,-1\n};\n\n/* key scale level */\n/* table is 3dB/OCT , DV converts this in TL step at 6dB/OCT */\n#define DV (EG_STEP/2)\n#define U(x) ((UINT32)(x))\nstatic const UINT32 KSL_TABLE[8*16]=\n{\n\t/* OCT 0 */\n\tU( 0.000/DV),U( 0.000/DV),U( 0.000/DV),U( 0.000/DV),\n\tU( 0.000/DV),U( 0.000/DV),U( 0.000/DV),U( 0.000/DV),\n\tU( 0.000/DV),U( 0.000/DV),U( 0.000/DV),U( 0.000/DV),\n\tU( 0.000/DV),U( 0.000/DV),U( 0.000/DV),U( 0.000/DV),\n\t/* OCT 1 */\n\tU( 0.000/DV),U( 0.000/DV),U( 0.000/DV),U( 0.000/DV),\n\tU( 0.000/DV),U( 0.000/DV),U( 0.000/DV),U( 0.000/DV),\n\tU( 0.000/DV),U( 0.750/DV),U( 1.125/DV),U( 1.500/DV),\n\tU( 1.875/DV),U( 2.250/DV),U( 2.625/DV),U( 3.000/DV),\n\t/* OCT 2 */\n\tU( 0.000/DV),U( 0.000/DV),U( 0.000/DV),U( 0.000/DV),\n\tU( 0.000/DV),U( 1.125/DV),U( 1.875/DV),U( 2.625/DV),\n\tU( 3.000/DV),U( 3.750/DV),U( 4.125/DV),U( 4.500/DV),\n\tU( 4.875/DV),U( 5.250/DV),U( 5.625/DV),U( 6.000/DV),\n\t/* OCT 3 */\n\tU( 0.000/DV),U( 0.000/DV),U( 0.000/DV),U( 1.875/DV),\n\tU( 3.000/DV),U( 4.125/DV),U( 4.875/DV),U( 5.625/DV),\n\tU( 6.000/DV),U( 6.750/DV),U( 7.125/DV),U( 7.500/DV),\n\tU( 7.875/DV),U( 8.250/DV),U( 8.625/DV),U( 9.000/DV),\n\t/* OCT 4 */\n\tU( 0.000/DV),U( 0.000/DV),U( 3.000/DV),U( 4.875/DV),\n\tU( 6.000/DV),U( 7.125/DV),U( 7.875/DV),U( 8.625/DV),\n\tU( 9.000/DV),U( 9.750/DV),U(10.125/DV),U(10.500/DV),\n\tU(10.875/DV),U(11.250/DV),U(11.625/DV),U(12.000/DV),\n\t/* OCT 5 */\n\tU( 0.000/DV),U( 3.000/DV),U( 6.000/DV),U( 7.875/DV),\n\tU( 9.000/DV),U(10.125/DV),U(10.875/DV),U(11.625/DV),\n\tU(12.000/DV),U(12.750/DV),U(13.125/DV),U(13.500/DV),\n\tU(13.875/DV),U(14.250/DV),U(14.625/DV),U(15.000/DV),\n\t/* OCT 6 */\n\tU( 0.000/DV),U( 6.000/DV),U( 9.000/DV),U(10.875/DV),\n\tU(12.000/DV),U(13.125/DV),U(13.875/DV),U(14.625/DV),\n\tU(15.000/DV),U(15.750/DV),U(16.125/DV),U(16.500/DV),\n\tU(16.875/DV),U(17.250/DV),U(17.625/DV),U(18.000/DV),\n\t/* OCT 7 */\n\tU( 0.000/DV),U( 9.000/DV),U(12.000/DV),U(13.875/DV),\n\tU(15.000/DV),U(16.125/DV),U(16.875/DV),U(17.625/DV),\n\tU(18.000/DV),U(18.750/DV),U(19.125/DV),U(19.500/DV),\n\tU(19.875/DV),U(20.250/DV),U(20.625/DV),U(21.000/DV)\n};\n#undef U\n#undef DV\n\n/* sustain level table (3db per step) */\n/* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/\n#define SC(db) (INT32)((db*((3/EG_STEP)*(1<<ENV_BITS)))+EG_DST)\nstatic const INT32 SL_TABLE[16]={\n SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7),\n SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31)\n};\n#undef SC\n\n#define TL_MAX (EG_ENT*2) /* limit(tl + ksr + envelope) + sinwave */\n/* TotalLevel : 48 24 12  6  3 1.5 0.75 (dB) */\n/* TL_TABLE[ 0      to TL_MAX          ] : plus  section */\n/* TL_TABLE[ TL_MAX to TL_MAX+TL_MAX-1 ] : minus section */\nstatic INT32 *TL_TABLE;\n\n/* pointers to TL_TABLE with sinwave output offset */\nstatic INT32 **SIN_TABLE;\n\n/* LFO table */\nstatic INT32 *AMS_TABLE;\nstatic INT32 *VIB_TABLE;\n\n/* envelope output curve table */\n/* attack + decay + OFF */\nstatic INT32 ENV_CURVE[2*EG_ENT+1];\n\n/* multiple table */\n#define ML 2\nstatic const UINT32 MUL_TABLE[16]= {\n/* 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15 */\n   ML/2, 1*ML, 2*ML, 3*ML, 4*ML, 5*ML, 6*ML, 7*ML,\n   8*ML, 9*ML,10*ML,10*ML,12*ML,12*ML,15*ML,15*ML\n};\n#undef ML\n\n/* dummy attack / decay rate ( when rate == 0 ) */\nstatic INT32 RATE_0[16]=\n{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};\n\n/* -------------------- static state --------------------- */\n\n/* lock level of common table */\nstatic int num_lock = 0;\n\n/* work table */\nstatic void *cur_chip = NULL;\t/* current chip point */\n/* current chip state */\n/* static OPLSAMPLE  *bufL,*bufR; */\nstatic OPL_CH *S_CH;\nstatic OPL_CH *E_CH;\nOPL_SLOT *SLOT7_1,*SLOT7_2,*SLOT8_1,*SLOT8_2;\n\nstatic INT32 outd[1];\nstatic INT32 ams;\nstatic INT32 vib;\nINT32  *ams_table;\nINT32  *vib_table;\nstatic INT32 amsIncr;\nstatic INT32 vibIncr;\nstatic INT32 feedback2;\t\t/* connect for SLOT 2 */\n\n/* log output level */\n#define LOG_ERR  3      /* ERROR       */\n#define LOG_WAR  2      /* WARNING     */\n#define LOG_INF  1      /* INFORMATION */\n\n//#define LOG_LEVEL LOG_INF\n#define LOG_LEVEL\tLOG_ERR\n\n//#define LOG(n,x) if( (n)>=LOG_LEVEL ) logerror x\n#define LOG(n,x)\n\n/* --------------------- subroutines  --------------------- */\n\nINLINE int Limit( int val, int max, int min ) {\n\tif ( val > max )\n\t\tval = max;\n\telse if ( val < min )\n\t\tval = min;\n\n\treturn val;\n}\n\n/* status set and IRQ handling */\nINLINE void OPL_STATUS_SET(FM_OPL *OPL,int flag)\n{\n\t/* set status flag */\n\tOPL->status |= flag;\n\tif(!(OPL->status & 0x80))\n\t{\n\t\tif(OPL->status & OPL->statusmask)\n\t\t{\t/* IRQ on */\n\t\t\tOPL->status |= 0x80;\n\t\t\t/* callback user interrupt handler (IRQ is OFF to ON) */\n\t\t\tif(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,1);\n\t\t}\n\t}\n}\n\n/* status reset and IRQ handling */\nINLINE void OPL_STATUS_RESET(FM_OPL *OPL,int flag)\n{\n\t/* reset status flag */\n\tOPL->status &=~flag;\n\tif((OPL->status & 0x80))\n\t{\n\t\tif (!(OPL->status & OPL->statusmask) )\n\t\t{\n\t\t\tOPL->status &= 0x7f;\n\t\t\t/* callback user interrupt handler (IRQ is ON to OFF) */\n\t\t\tif(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,0);\n\t\t}\n\t}\n}\n\n/* IRQ mask set */\nINLINE void OPL_STATUSMASK_SET(FM_OPL *OPL,int flag)\n{\n\tOPL->statusmask = flag;\n\t/* IRQ handling check */\n\tOPL_STATUS_SET(OPL,0);\n\tOPL_STATUS_RESET(OPL,0);\n}\n\n/* ----- key on  ----- */\nINLINE void OPL_KEYON(OPL_SLOT *SLOT)\n{\n\t/* sin wave restart */\n\tSLOT->Cnt = 0;\n\t/* set attack */\n\tSLOT->evm = ENV_MOD_AR;\n\tSLOT->evs = SLOT->evsa;\n\tSLOT->evc = EG_AST;\n\tSLOT->eve = EG_AED;\n}\n/* ----- key off ----- */\nINLINE void OPL_KEYOFF(OPL_SLOT *SLOT)\n{\n\tif( SLOT->evm > ENV_MOD_RR)\n\t{\n\t\t/* set envelope counter from envelope output */\n\t\tSLOT->evm = ENV_MOD_RR;\n\t\tif( !(SLOT->evc&EG_DST) )\n\t\t\tSLOT->evc = (ENV_CURVE[SLOT->evc>>ENV_BITS]<<ENV_BITS) + EG_DST;\n//\t\t\tSLOT->evc = EG_DST;\n\t\tSLOT->eve = EG_DED;\n\t\tSLOT->evs = SLOT->evsr;\n\t}\n}\n\n/* ---------- calcrate Envelope Generator & Phase Generator ---------- */\n/* return : envelope output */\nINLINE UINT32 OPL_CALC_SLOT( OPL_SLOT *SLOT )\n{\n\t/* calcrate envelope generator */\n\tif( (SLOT->evc+=SLOT->evs) >= SLOT->eve )\n\t{\n\t\tswitch( SLOT->evm ){\n\t\tcase ENV_MOD_AR: /* ATTACK -> DECAY1 */\n\t\t\t/* next DR */\n\t\t\tSLOT->evm = ENV_MOD_DR;\n\t\t\tSLOT->evc = EG_DST;\n\t\t\tSLOT->eve = SLOT->SL;\n\t\t\tSLOT->evs = SLOT->evsd;\n\t\t\tbreak;\n\t\tcase ENV_MOD_DR: /* DECAY -> SL or RR */\n\t\t\tSLOT->evc = SLOT->SL;\n\t\t\tSLOT->eve = EG_DED;\n\t\t\tif(SLOT->eg_typ)\n\t\t\t{\n\t\t\t\tSLOT->evs = 0;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tSLOT->evm = ENV_MOD_RR;\n\t\t\t\tSLOT->evs = SLOT->evsr;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase ENV_MOD_RR: /* RR -> OFF */\n\t\t\tSLOT->evc = EG_OFF;\n\t\t\tSLOT->eve = EG_OFF+1;\n\t\t\tSLOT->evs = 0;\n\t\t\tbreak;\n\t\t}\n\t}\n\t/* calcrate envelope */\n\treturn SLOT->TLL+ENV_CURVE[SLOT->evc>>ENV_BITS]+(SLOT->ams ? ams : 0);\n}\n\n/* set algorithm connection */\nstatic void set_algorythm( OPL_CH *CH)\n{\n\tINT32 *carrier = &outd[0];\n\tCH->connect1 = CH->CON ? carrier : &feedback2;\n\tCH->connect2 = carrier;\n}\n\n/* ---------- frequency counter for operator update ---------- */\nINLINE void CALC_FCSLOT(OPL_CH *CH,OPL_SLOT *SLOT)\n{\n\tint ksr;\n\n\t/* frequency step counter */\n\tSLOT->Incr = CH->fc * SLOT->mul;\n\tksr = CH->kcode >> SLOT->KSR;\n\n\tif( SLOT->ksr != ksr )\n\t{\n\t\tSLOT->ksr = ksr;\n\t\t/* attack , decay rate recalcration */\n\t\tSLOT->evsa = SLOT->AR[ksr];\n\t\tSLOT->evsd = SLOT->DR[ksr];\n\t\tSLOT->evsr = SLOT->RR[ksr];\n\t}\n\tSLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);\n}\n\n/* set multi,am,vib,EG-TYP,KSR,mul */\nINLINE void set_mul(FM_OPL *OPL,int slot,int v)\n{\n\tOPL_CH   *CH   = &OPL->P_CH[slot/2];\n\tOPL_SLOT *SLOT = &CH->SLOT[slot&1];\n\n\tSLOT->mul    = MUL_TABLE[v&0x0f];\n\tSLOT->KSR    = (v&0x10) ? 0 : 2;\n\tSLOT->eg_typ = (v&0x20)>>5;\n\tSLOT->vib    = (v&0x40);\n\tSLOT->ams    = (v&0x80);\n\tCALC_FCSLOT(CH,SLOT);\n}\n\n/* set ksl & tl */\nINLINE void set_ksl_tl(FM_OPL *OPL,int slot,int v)\n{\n\tOPL_CH   *CH   = &OPL->P_CH[slot/2];\n\tOPL_SLOT *SLOT = &CH->SLOT[slot&1];\n\tint ksl = v>>6; /* 0 / 1.5 / 3 / 6 db/OCT */\n\n\tSLOT->ksl = ksl ? 3-ksl : 31;\n\tSLOT->TL  = (v&0x3f)*(0.75/EG_STEP); /* 0.75db step */\n\n\tif( !(OPL->mode&0x80) )\n\t{\t/* not CSM latch total level */\n\t\tSLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);\n\t}\n}\n\n/* set attack rate & decay rate  */\nINLINE void set_ar_dr(FM_OPL *OPL,int slot,int v)\n{\n\tOPL_CH   *CH   = &OPL->P_CH[slot/2];\n\tOPL_SLOT *SLOT = &CH->SLOT[slot&1];\n\tint ar = v>>4;\n\tint dr = v&0x0f;\n\n\tSLOT->AR = ar ? &OPL->AR_TABLE[ar<<2] : RATE_0;\n\tSLOT->evsa = SLOT->AR[SLOT->ksr];\n\tif( SLOT->evm == ENV_MOD_AR ) SLOT->evs = SLOT->evsa;\n\n\tSLOT->DR = dr ? &OPL->DR_TABLE[dr<<2] : RATE_0;\n\tSLOT->evsd = SLOT->DR[SLOT->ksr];\n\tif( SLOT->evm == ENV_MOD_DR ) SLOT->evs = SLOT->evsd;\n}\n\n/* set sustain level & release rate */\nINLINE void set_sl_rr(FM_OPL *OPL,int slot,int v)\n{\n\tOPL_CH   *CH   = &OPL->P_CH[slot/2];\n\tOPL_SLOT *SLOT = &CH->SLOT[slot&1];\n\tint sl = v>>4;\n\tint rr = v & 0x0f;\n\n\tSLOT->SL = SL_TABLE[sl];\n\tif( SLOT->evm == ENV_MOD_DR ) SLOT->eve = SLOT->SL;\n\tSLOT->RR = &OPL->DR_TABLE[rr<<2];\n\tSLOT->evsr = SLOT->RR[SLOT->ksr];\n\tif( SLOT->evm == ENV_MOD_RR ) SLOT->evs = SLOT->evsr;\n}\n\n/* operator output calcrator */\n#define OP_OUT(slot,env,con)   slot->wavetable[((slot->Cnt+con)/(0x1000000/SIN_ENT))&(SIN_ENT-1)][env]\n/* ---------- calcrate one of channel ---------- */\nINLINE void OPL_CALC_CH( OPL_CH *CH )\n{\n\tUINT32 env_out;\n\tOPL_SLOT *SLOT;\n\n\tfeedback2 = 0;\n\t/* SLOT 1 */\n\tSLOT = &CH->SLOT[SLOT1];\n\tenv_out=OPL_CALC_SLOT(SLOT);\n\tif( env_out < EG_ENT-1 )\n\t{\n\t\t/* PG */\n\t\tif(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE);\n\t\telse          SLOT->Cnt += SLOT->Incr;\n\t\t/* connection */\n\t\tif(CH->FB)\n\t\t{\n\t\t\tint feedback1 = (CH->op1_out[0]+CH->op1_out[1])>>CH->FB;\n\t\t\tCH->op1_out[1] = CH->op1_out[0];\n\t\t\t*CH->connect1 += CH->op1_out[0] = OP_OUT(SLOT,env_out,feedback1);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t*CH->connect1 += OP_OUT(SLOT,env_out,0);\n\t\t}\n\t}else\n\t{\n\t\tCH->op1_out[1] = CH->op1_out[0];\n\t\tCH->op1_out[0] = 0;\n\t}\n\t/* SLOT 2 */\n\tSLOT = &CH->SLOT[SLOT2];\n\tenv_out=OPL_CALC_SLOT(SLOT);\n\tif( env_out < EG_ENT-1 )\n\t{\n\t\t/* PG */\n\t\tif(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE);\n\t\telse          SLOT->Cnt += SLOT->Incr;\n\t\t/* connection */\n\t\toutd[0] += OP_OUT(SLOT,env_out, feedback2);\n\t}\n}\n\n/* ---------- calcrate rythm block ---------- */\n#define WHITE_NOISE_db 6.0\nINLINE void OPL_CALC_RH( OPL_CH *CH )\n{\n\tUINT32 env_tam,env_sd,env_top,env_hh;\n\tint whitenoise = (OpenXcom::RNG::seedless(0, 1))*(WHITE_NOISE_db/EG_STEP);\n\tINT32 tone8;\n\n\tOPL_SLOT *SLOT;\n\tint env_out;\n\n\t/* BD : same as FM serial mode and output level is large */\n\tfeedback2 = 0;\n\t/* SLOT 1 */\n\tSLOT = &CH[6].SLOT[SLOT1];\n\tenv_out=OPL_CALC_SLOT(SLOT);\n\tif( env_out < EG_ENT-1 )\n\t{\n\t\t/* PG */\n\t\tif(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE);\n\t\telse          SLOT->Cnt += SLOT->Incr;\n\t\t/* connection */\n\t\tif(CH[6].FB)\n\t\t{\n\t\t\tint feedback1 = (CH[6].op1_out[0]+CH[6].op1_out[1])>>CH[6].FB;\n\t\t\tCH[6].op1_out[1] = CH[6].op1_out[0];\n\t\t\tfeedback2 = CH[6].op1_out[0] = OP_OUT(SLOT,env_out,feedback1);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tfeedback2 = OP_OUT(SLOT,env_out,0);\n\t\t}\n\t}else\n\t{\n\t\tfeedback2 = 0;\n\t\tCH[6].op1_out[1] = CH[6].op1_out[0];\n\t\tCH[6].op1_out[0] = 0;\n\t}\n\t/* SLOT 2 */\n\tSLOT = &CH[6].SLOT[SLOT2];\n\tenv_out=OPL_CALC_SLOT(SLOT);\n\tif( env_out < EG_ENT-1 )\n\t{\n\t\t/* PG */\n\t\tif(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE);\n\t\telse          SLOT->Cnt += SLOT->Incr;\n\t\t/* connection */\n\t\toutd[0] += OP_OUT(SLOT,env_out, feedback2)*2;\n\t}\n\n\t// SD  (17) = mul14[fnum7] + white noise\n\t// TAM (15) = mul15[fnum8]\n\t// TOP (18) = fnum6(mul18[fnum8]+whitenoise)\n\t// HH  (14) = fnum7(mul18[fnum8]+whitenoise) + white noise\n\tenv_sd =OPL_CALC_SLOT(SLOT7_2) + whitenoise;\n\tenv_tam=OPL_CALC_SLOT(SLOT8_1);\n\tenv_top=OPL_CALC_SLOT(SLOT8_2);\n\tenv_hh =OPL_CALC_SLOT(SLOT7_1) + whitenoise;\n\n\t/* PG */\n\tif(SLOT7_1->vib) SLOT7_1->Cnt += (2*SLOT7_1->Incr*vib/VIB_RATE);\n\telse             SLOT7_1->Cnt += 2*SLOT7_1->Incr;\n\tif(SLOT7_2->vib) SLOT7_2->Cnt += ((CH[7].fc*8)*vib/VIB_RATE);\n\telse             SLOT7_2->Cnt += (CH[7].fc*8);\n\tif(SLOT8_1->vib) SLOT8_1->Cnt += (SLOT8_1->Incr*vib/VIB_RATE);\n\telse             SLOT8_1->Cnt += SLOT8_1->Incr;\n\tif(SLOT8_2->vib) SLOT8_2->Cnt += ((CH[8].fc*48)*vib/VIB_RATE);\n\telse             SLOT8_2->Cnt += (CH[8].fc*48);\n\n\ttone8 = OP_OUT(SLOT8_2,whitenoise,0 );\n\n\t/* SD */\n\tif( env_sd < EG_ENT-1 )\n\t\toutd[0] += OP_OUT(SLOT7_1,env_sd, 0)*8;\n\t/* TAM */\n\tif( env_tam < EG_ENT-1 )\n\t\toutd[0] += OP_OUT(SLOT8_1,env_tam, 0)*2;\n\t/* TOP-CY */\n\tif( env_top < EG_ENT-1 )\n\t\toutd[0] += OP_OUT(SLOT7_2,env_top,tone8)*2;\n\t/* HH */\n\tif( env_hh  < EG_ENT-1 )\n\t\toutd[0] += OP_OUT(SLOT7_2,env_hh,tone8)*2;\n}\n\n/* ----------- initialize time tables ----------- */\nstatic void init_timetables( FM_OPL *OPL , int ARRATE , int DRRATE )\n{\n\tint i;\n\tdouble rate;\n\n\t/* make attack rate & decay rate tables */\n\tfor (i = 0;i < 4;i++) OPL->AR_TABLE[i] = OPL->DR_TABLE[i] = 0;\n\tfor (i = 4;i <= 60;i++){\n\t\trate  = OPL->freqbase;\t\t\t\t\t\t/* frequency rate */\n\t\tif( i < 60 ) rate *= 1.0+(i&3)*0.25;\t\t/* b0-1 : x1 , x1.25 , x1.5 , x1.75 */\n\t\trate *= 1<<((i>>2)-1);\t\t\t\t\t\t/* b2-5 : shift bit */\n\t\trate *= (double)(EG_ENT<<ENV_BITS);\n\t\tOPL->AR_TABLE[i] = rate / ARRATE;\n\t\tOPL->DR_TABLE[i] = rate / DRRATE;\n\t}\n\tfor (i = 60;i < 75;i++)\n\t{\n\t\tOPL->AR_TABLE[i] = EG_AED-1;\n\t\tOPL->DR_TABLE[i] = OPL->DR_TABLE[60];\n\t}\n#if 0\n\tfor (i = 0;i < 64 ;i++){\t/* make for overflow area */\n\t\tLOG(LOG_WAR,(\"rate %2d , ar %f ms , dr %f ms \\n\",i,\n\t\t\t((double)(EG_ENT<<ENV_BITS) / OPL->AR_TABLE[i]) * (1000.0 / OPL->rate),\n\t\t\t((double)(EG_ENT<<ENV_BITS) / OPL->DR_TABLE[i]) * (1000.0 / OPL->rate) ));\n\t}\n#endif\n}\n\n/* ---------- generic table initialize ---------- */\nstatic int OPLOpenTable( void )\n{\n\tint s,t;\n\tdouble rate;\n\tint i,j;\n\tdouble pom;\n\n\t/* allocate dynamic tables */\n\tif( (TL_TABLE = (INT32 *)malloc(TL_MAX*2*sizeof(INT32))) == NULL)\n\t\treturn 0;\n\tif( (SIN_TABLE = (INT32 **)malloc(SIN_ENT*4 *sizeof(INT32 *))) == NULL)\n\t{\n\t\tfree(TL_TABLE);\n\t\treturn 0;\n\t}\n\tif( (AMS_TABLE = (INT32 *)malloc(AMS_ENT*2 *sizeof(INT32))) == NULL)\n\t{\n\t\tfree(TL_TABLE);\n\t\tfree(SIN_TABLE);\n\t\treturn 0;\n\t}\n\tif( (VIB_TABLE = (INT32 *)malloc(VIB_ENT*2 *sizeof(INT32))) == NULL)\n\t{\n\t\tfree(TL_TABLE);\n\t\tfree(SIN_TABLE);\n\t\tfree(AMS_TABLE);\n\t\treturn 0;\n\t}\n\t/* make total level table */\n\tfor (t = 0;t < EG_ENT-1 ;t++){\n\t\trate = ((1<<TL_BITS)-1)/pow(10,EG_STEP*t/20);\t/* dB -> voltage */\n\t\tTL_TABLE[       t] =  (int)rate;\n\t\tTL_TABLE[TL_MAX+t] = -TL_TABLE[t];\n/*\t\tLOG(LOG_INF,(\"TotalLevel(%3d) = %x\\n\",t,TL_TABLE[t]));*/\n\t}\n\t/* fill volume off area */\n\tfor ( t = EG_ENT-1; t < TL_MAX ;t++){\n\t\tTL_TABLE[t] = TL_TABLE[TL_MAX+t] = 0;\n\t}\n\n\t/* make sinwave table (total level offset) */\n\t/* degree 0 = degree 180                   = off */\n\tSIN_TABLE[0] = SIN_TABLE[SIN_ENT/2]         = &TL_TABLE[EG_ENT-1];\n\tfor (s = 1;s <= SIN_ENT/4;s++){\n\t\tpom = sin(2*PI*s/SIN_ENT); /* sin     */\n\t\tpom = 20*log10(1/pom);\t   /* decibel */\n\t\tj = pom / EG_STEP;         /* TL_TABLE steps */\n\n        /* degree 0   -  90    , degree 180 -  90 : plus section */\n\t\tSIN_TABLE[          s] = SIN_TABLE[SIN_ENT/2-s] = &TL_TABLE[j];\n        /* degree 180 - 270    , degree 360 - 270 : minus section */\n\t\tSIN_TABLE[SIN_ENT/2+s] = SIN_TABLE[SIN_ENT  -s] = &TL_TABLE[TL_MAX+j];\n/*\t\tLOG(LOG_INF,(\"sin(%3d) = %f:%f db\\n\",s,pom,(double)j * EG_STEP));*/\n\t}\n\tfor (s = 0;s < SIN_ENT;s++)\n\t{\n\t\tSIN_TABLE[SIN_ENT*1+s] = s<(SIN_ENT/2) ? SIN_TABLE[s] : &TL_TABLE[EG_ENT];\n\t\tSIN_TABLE[SIN_ENT*2+s] = SIN_TABLE[s % (SIN_ENT/2)];\n\t\tSIN_TABLE[SIN_ENT*3+s] = (s/(SIN_ENT/4))&1 ? &TL_TABLE[EG_ENT] : SIN_TABLE[SIN_ENT*2+s];\n\t}\n\n\t/* envelope counter -> envelope output table */\n\tfor (i=0; i<EG_ENT; i++)\n\t{\n\t\t/* ATTACK curve */\n\t\tpom = pow( ((double)(EG_ENT-1-i)/EG_ENT) , 8 ) * EG_ENT;\n\t\t/* if( pom >= EG_ENT ) pom = EG_ENT-1; */\n\t\tENV_CURVE[i] = (int)pom;\n\t\t/* DECAY ,RELEASE curve */\n\t\tENV_CURVE[(EG_DST>>ENV_BITS)+i]= i;\n\t}\n\t/* off */\n\tENV_CURVE[EG_OFF>>ENV_BITS]= EG_ENT-1;\n\t/* make LFO ams table */\n\tfor (i=0; i<AMS_ENT; i++)\n\t{\n\t\tpom = (1.0+sin(2*PI*i/AMS_ENT))/2; /* sin */\n\t\tAMS_TABLE[i]         = (1.0/EG_STEP)*pom; /* 1dB   */\n\t\tAMS_TABLE[AMS_ENT+i] = (4.8/EG_STEP)*pom; /* 4.8dB */\n\t}\n\t/* make LFO vibrate table */\n\tfor (i=0; i<VIB_ENT; i++)\n\t{\n\t\t/* 100cent = 1seminote = 6% ?? */\n\t\tpom = (double)VIB_RATE*0.06*sin(2*PI*i/VIB_ENT); /* +-100sect step */\n\t\tVIB_TABLE[i]         = VIB_RATE + (pom*0.07); /* +- 7cent */\n\t\tVIB_TABLE[VIB_ENT+i] = VIB_RATE + (pom*0.14); /* +-14cent */\n\t\t/* LOG(LOG_INF,(\"vib %d=%d\\n\",i,VIB_TABLE[VIB_ENT+i])); */\n\t}\n\treturn 1;\n}\n\n\nstatic void OPLCloseTable( void )\n{\n\tfree(TL_TABLE);\n\tfree(SIN_TABLE);\n\tfree(AMS_TABLE);\n\tfree(VIB_TABLE);\n}\n\n/* CSM Key Control */\nINLINE void CSMKeyControl(OPL_CH *CH)\n{\n\tOPL_SLOT *slot1 = &CH->SLOT[SLOT1];\n\tOPL_SLOT *slot2 = &CH->SLOT[SLOT2];\n\t/* all key off */\n\tOPL_KEYOFF(slot1);\n\tOPL_KEYOFF(slot2);\n\t/* total level latch */\n\tslot1->TLL = slot1->TL + (CH->ksl_base>>slot1->ksl);\n\tslot1->TLL = slot1->TL + (CH->ksl_base>>slot1->ksl);\n\t/* key on */\n\tCH->op1_out[0] = CH->op1_out[1] = 0;\n\tOPL_KEYON(slot1);\n\tOPL_KEYON(slot2);\n}\n\n/* ---------- opl initialize ---------- */\nstatic void OPL_initalize(FM_OPL *OPL)\n{\n\tint fn;\n\n\t/* frequency base */\n\tOPL->freqbase = (OPL->rate) ? ((double)OPL->clock / OPL->rate) / 72  : 0;\n\t/* Timer base time */\n\tOPL->TimerBase = 1.0/((double)OPL->clock / 72.0 );\n\t/* make time tables */\n\tinit_timetables( OPL , OPL_ARRATE , OPL_DRRATE );\n\t/* make fnumber -> increment counter table */\n\tfor( fn=0 ; fn < 1024 ; fn++ )\n\t{\n\t\tOPL->FN_TABLE[fn] = OPL->freqbase * fn * FREQ_RATE * (1<<7) / 2;\n\t}\n\t/* LFO freq.table */\n\tOPL->amsIncr = OPL->rate ? (double)AMS_ENT*(1<<AMS_SHIFT) / OPL->rate * 3.7 * ((double)OPL->clock/3600000) : 0;\n\tOPL->vibIncr = OPL->rate ? (double)VIB_ENT*(1<<VIB_SHIFT) / OPL->rate * 6.4 * ((double)OPL->clock/3600000) : 0;\n}\n\n/* ---------- write a OPL registers ---------- */\nstatic void OPLWriteReg(FM_OPL *OPL, int r, int v)\n{\n\tOPL_CH *CH;\n\tint slot;\n\tint block_fnum;\n\n\tswitch(r&0xe0)\n\t{\n\tcase 0x00: /* 00-1f:control */\n\t\tswitch(r&0x1f)\n\t\t{\n\t\tcase 0x01:\n\t\t\t/* wave selector enable */\n\t\t\tif(OPL->type&OPL_TYPE_WAVESEL)\n\t\t\t{\n\t\t\t\tOPL->wavesel = v&0x20;\n\t\t\t\tif(!OPL->wavesel)\n\t\t\t\t{\n\t\t\t\t\t/* preset compatible mode */\n\t\t\t\t\tint c;\n\t\t\t\t\tfor(c=0;c<OPL->max_ch;c++)\n\t\t\t\t\t{\n\t\t\t\t\t\tOPL->P_CH[c].SLOT[SLOT1].wavetable = &SIN_TABLE[0];\n\t\t\t\t\t\tOPL->P_CH[c].SLOT[SLOT2].wavetable = &SIN_TABLE[0];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\tcase 0x02:\t/* Timer 1 */\n\t\t\tOPL->T[0] = (256-v)*4;\n\t\t\tbreak;\n\t\tcase 0x03:\t/* Timer 2 */\n\t\t\tOPL->T[1] = (256-v)*16;\n\t\t\treturn;\n\t\tcase 0x04:\t/* IRQ clear / mask and Timer enable */\n\t\t\tif(v&0x80)\n\t\t\t{\t/* IRQ flag clear */\n\t\t\t\tOPL_STATUS_RESET(OPL,0x7f);\n\t\t\t}\n\t\t\telse\n\t\t\t{\t/* set IRQ mask ,timer enable*/\n\t\t\t\tUINT8 st1 = v&1;\n\t\t\t\tUINT8 st2 = (v>>1)&1;\n\t\t\t\t/* IRQRST,T1MSK,t2MSK,EOSMSK,BRMSK,x,ST2,ST1 */\n\t\t\t\tOPL_STATUS_RESET(OPL,v&0x78);\n\t\t\t\tOPL_STATUSMASK_SET(OPL,((~v)&0x78)|0x01);\n\t\t\t\t/* timer 2 */\n\t\t\t\tif(OPL->st[1] != st2)\n\t\t\t\t{\n\t\t\t\t\tdouble interval = st2 ? (double)OPL->T[1]*OPL->TimerBase : 0.0;\n\t\t\t\t\tOPL->st[1] = st2;\n\t\t\t\t\tif (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+1,interval);\n\t\t\t\t}\n\t\t\t\t/* timer 1 */\n\t\t\t\tif(OPL->st[0] != st1)\n\t\t\t\t{\n\t\t\t\t\tdouble interval = st1 ? (double)OPL->T[0]*OPL->TimerBase : 0.0;\n\t\t\t\t\tOPL->st[0] = st1;\n\t\t\t\t\tif (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+0,interval);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n#if BUILD_Y8950\n\t\tcase 0x06:\t\t/* Key Board OUT */\n\t\t\tif(OPL->type&OPL_TYPE_KEYBOARD)\n\t\t\t{\n\t\t\t\tif(OPL->keyboardhandler_w)\n\t\t\t\t\tOPL->keyboardhandler_w(OPL->keyboard_param,v);\n\t\t\t\telse\n\t\t\t\t\tLOG(LOG_WAR,(\"OPL:write unmapped KEYBOARD port\\n\"));\n\t\t\t}\n\t\t\treturn;\n\t\tcase 0x07:\t/* DELTA-T control : START,REC,MEMDATA,REPT,SPOFF,x,x,RST */\n\t\t\tif(OPL->type&OPL_TYPE_ADPCM)\n\t\t\t\tYM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v);\n\t\t\treturn;\n\t\tcase 0x08:\t/* MODE,DELTA-T : CSM,NOTESEL,x,x,smpl,da/ad,64k,rom */\n\t\t\tOPL->mode = v;\n\t\t\tv&=0x1f;\t/* for DELTA-T unit */\n\t\tcase 0x09:\t\t/* START ADD */\n\t\tcase 0x0a:\n\t\tcase 0x0b:\t\t/* STOP ADD  */\n\t\tcase 0x0c:\n\t\tcase 0x0d:\t\t/* PRESCALE   */\n\t\tcase 0x0e:\n\t\tcase 0x0f:\t\t/* ADPCM data */\n\t\tcase 0x10: \t\t/* DELTA-N    */\n\t\tcase 0x11: \t\t/* DELTA-N    */\n\t\tcase 0x12: \t\t/* EG-CTRL    */\n\t\t\tif(OPL->type&OPL_TYPE_ADPCM)\n\t\t\t\tYM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v);\n\t\t\treturn;\n#if 0\n\t\tcase 0x15:\t\t/* DAC data    */\n\t\tcase 0x16:\n\t\tcase 0x17:\t\t/* SHIFT    */\n\t\t\treturn;\n\t\tcase 0x18:\t\t/* I/O CTRL (Direction) */\n\t\t\tif(OPL->type&OPL_TYPE_IO)\n\t\t\t\tOPL->portDirection = v&0x0f;\n\t\t\treturn;\n\t\tcase 0x19:\t\t/* I/O DATA */\n\t\t\tif(OPL->type&OPL_TYPE_IO)\n\t\t\t{\n\t\t\t\tOPL->portLatch = v;\n\t\t\t\tif(OPL->porthandler_w)\n\t\t\t\t\tOPL->porthandler_w(OPL->port_param,v&OPL->portDirection);\n\t\t\t}\n\t\t\treturn;\n\t\tcase 0x1a:\t\t/* PCM data */\n\t\t\treturn;\n#endif\n#endif\n\t\t}\n\t\tbreak;\n\tcase 0x20:\t/* am,vib,ksr,eg type,mul */\n\t\tslot = slot_array[r&0x1f];\n\t\tif(slot == -1) return;\n\t\tset_mul(OPL,slot,v);\n\t\treturn;\n\tcase 0x40:\n\t\tslot = slot_array[r&0x1f];\n\t\tif(slot == -1) return;\n\t\tset_ksl_tl(OPL,slot,v);\n\t\treturn;\n\tcase 0x60:\n\t\tslot = slot_array[r&0x1f];\n\t\tif(slot == -1) return;\n\t\tset_ar_dr(OPL,slot,v);\n\t\treturn;\n\tcase 0x80:\n\t\tslot = slot_array[r&0x1f];\n\t\tif(slot == -1) return;\n\t\tset_sl_rr(OPL,slot,v);\n\t\treturn;\n\tcase 0xa0:\n\t\tswitch(r)\n\t\t{\n\t\tcase 0xbd:\n\t\t\t/* amsep,vibdep,r,bd,sd,tom,tc,hh */\n\t\t\t{\n\t\t\tUINT8 rkey = OPL->rythm^v;\n\t\t\tOPL->ams_table = &AMS_TABLE[v&0x80 ? AMS_ENT : 0];\n\t\t\tOPL->vib_table = &VIB_TABLE[v&0x40 ? VIB_ENT : 0];\n\t\t\tOPL->rythm  = v&0x3f;\n\t\t\tif(OPL->rythm&0x20)\n\t\t\t{\n#if 0\n\t\t\t\tusrintf_showmessage(\"OPL Rythm mode select\");\n#endif\n\t\t\t\t/* BD key on/off */\n\t\t\t\tif(rkey&0x10)\n\t\t\t\t{\n\t\t\t\t\tif(v&0x10)\n\t\t\t\t\t{\n\t\t\t\t\t\tOPL->P_CH[6].op1_out[0] = OPL->P_CH[6].op1_out[1] = 0;\n\t\t\t\t\t\tOPL_KEYON(&OPL->P_CH[6].SLOT[SLOT1]);\n\t\t\t\t\t\tOPL_KEYON(&OPL->P_CH[6].SLOT[SLOT2]);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tOPL_KEYOFF(&OPL->P_CH[6].SLOT[SLOT1]);\n\t\t\t\t\t\tOPL_KEYOFF(&OPL->P_CH[6].SLOT[SLOT2]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t/* SD key on/off */\n\t\t\t\tif(rkey&0x08)\n\t\t\t\t{\n\t\t\t\t\tif(v&0x08) OPL_KEYON(&OPL->P_CH[7].SLOT[SLOT2]);\n\t\t\t\t\telse       OPL_KEYOFF(&OPL->P_CH[7].SLOT[SLOT2]);\n\t\t\t\t}/* TAM key on/off */\n\t\t\t\tif(rkey&0x04)\n\t\t\t\t{\n\t\t\t\t\tif(v&0x04) OPL_KEYON(&OPL->P_CH[8].SLOT[SLOT1]);\n\t\t\t\t\telse       OPL_KEYOFF(&OPL->P_CH[8].SLOT[SLOT1]);\n\t\t\t\t}\n\t\t\t\t/* TOP-CY key on/off */\n\t\t\t\tif(rkey&0x02)\n\t\t\t\t{\n\t\t\t\t\tif(v&0x02) OPL_KEYON(&OPL->P_CH[8].SLOT[SLOT2]);\n\t\t\t\t\telse       OPL_KEYOFF(&OPL->P_CH[8].SLOT[SLOT2]);\n\t\t\t\t}\n\t\t\t\t/* HH key on/off */\n\t\t\t\tif(rkey&0x01)\n\t\t\t\t{\n\t\t\t\t\tif(v&0x01) OPL_KEYON(&OPL->P_CH[7].SLOT[SLOT1]);\n\t\t\t\t\telse       OPL_KEYOFF(&OPL->P_CH[7].SLOT[SLOT1]);\n\t\t\t\t}\n\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\t/* keyon,block,fnum */\n\t\tif( (r&0x0f) > 11) return; //8\n\t\tCH = &OPL->P_CH[r&0x0f];\n\t\tif(!(r&0x10))\n\t\t{\t/* a0-a8 */\n\t\t\tblock_fnum  = (CH->block_fnum&0x1f00) | v;\n\t\t}\n\t\telse\n\t\t{\t/* b0-b8 */\n\t\t\tint keyon = (v>>5)&1;\n\t\t\tblock_fnum = ((v&0x1f)<<8) | (CH->block_fnum&0xff);\n\t\t\tif(CH->keyon != keyon)\n\t\t\t{\n\t\t\t\tif( (CH->keyon=keyon) )\n\t\t\t\t{\n\t\t\t\t\tCH->op1_out[0] = CH->op1_out[1] = 0;\n\t\t\t\t\tOPL_KEYON(&CH->SLOT[SLOT1]);\n\t\t\t\t\tOPL_KEYON(&CH->SLOT[SLOT2]);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tOPL_KEYOFF(&CH->SLOT[SLOT1]);\n\t\t\t\t\tOPL_KEYOFF(&CH->SLOT[SLOT2]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t/* update */\n\t\tif((int)CH->block_fnum != block_fnum)\n\t\t{\n\t\t\tint blockRv = 7-(block_fnum>>10);\n\t\t\tint fnum   = block_fnum&0x3ff;\n\t\t\tCH->block_fnum = block_fnum;\n\n\t\t\tCH->ksl_base = KSL_TABLE[block_fnum>>6];\n\t\t\tCH->fc = OPL->FN_TABLE[fnum]>>blockRv;\n\t\t\tCH->kcode = CH->block_fnum>>9;\n\t\t\tif( (OPL->mode&0x40) && CH->block_fnum&0x100) CH->kcode |=1;\n\t\t\tCALC_FCSLOT(CH,&CH->SLOT[SLOT1]);\n\t\t\tCALC_FCSLOT(CH,&CH->SLOT[SLOT2]);\n\t\t}\n\t\treturn;\n\tcase 0xc0:\n\t\t/* FB,C */\n\t\tif( (r&0x0f) > 11) return;//8\n\t\tCH = &OPL->P_CH[r&0x0f];\n\t\t{\n\t\tint feedback = (v>>1)&7;\n\t\tCH->FB   = feedback ? (8+1) - feedback : 0;\n\t\tCH->CON = v&1;\n\t\tset_algorythm(CH);\n\t\t}\n\t\treturn;\n\tcase 0xe0: /* wave type */\n\t\tslot = slot_array[r&0x1f];\n\t\tif(slot == -1) return;\n\t\tCH = &OPL->P_CH[slot/2];\n\t\tif(OPL->wavesel)\n\t\t{\n\t\t\t/* LOG(LOG_INF,(\"OPL SLOT %d wave select %d\\n\",slot,v&3)); */\n\t\t\tCH->SLOT[slot&1].wavetable = &SIN_TABLE[(v&0x03)*SIN_ENT];\n\t\t}\n\t\treturn;\n\t}\n}\n\n/* lock/unlock for common table */\nstatic int OPL_LockTable(void)\n{\n\tnum_lock++;\n\tif(num_lock>1) return 0;\n\t/* first time */\n\tcur_chip = NULL;\n\t/* allocate total level table (128kb space) */\n\tif( !OPLOpenTable() )\n\t{\n\t\tnum_lock--;\n\t\treturn -1;\n\t}\n\treturn 0;\n}\n\nstatic void OPL_UnLockTable(void)\n{\n\tif(num_lock) num_lock--;\n\tif(num_lock) return;\n\t/* last time */\n\tcur_chip = NULL;\n\tOPLCloseTable();\n}\n\n#if (BUILD_YM3812 || BUILD_YM3526)\n/*******************************************************************************/\n/*\t\tYM3812 local section                                                   */\n/*******************************************************************************/\n\n/* ---------- update one of chip ----------- */\nvoid YM3812UpdateOne(FM_OPL *OPL, INT16 *buffer, int length, int stripe, float volume)\n{\n    int i;\n\tint data;\n\tOPLSAMPLE *buf = buffer;\n\tUINT32 amsCnt  = OPL->amsCnt;\n\tUINT32 vibCnt  = OPL->vibCnt;\n\tUINT8 rythm = OPL->rythm&0x20;\n\tOPL_CH *CH,*R_CH;\n\n\tif( (void *)OPL != cur_chip ){\n\t\tcur_chip = (void *)OPL;\n\t\t/* channel pointers */\n\t\tS_CH = OPL->P_CH;\n\t\tE_CH = &S_CH[9];\n\t\t/* rythm slot */\n\t\tSLOT7_1 = &S_CH[7].SLOT[SLOT1];\n\t\tSLOT7_2 = &S_CH[7].SLOT[SLOT2];\n\t\tSLOT8_1 = &S_CH[8].SLOT[SLOT1];\n\t\tSLOT8_2 = &S_CH[8].SLOT[SLOT2];\n\t\t/* LFO state */\n\t\tamsIncr = OPL->amsIncr;\n\t\tvibIncr = OPL->vibIncr;\n\t\tams_table = OPL->ams_table;\n\t\tvib_table = OPL->vib_table;\n\t}\n\tR_CH = rythm ? &S_CH[6] : E_CH;\n    for( i=0; i < length ; i+=stripe )\n\t{\n\t\t/*            channel A         channel B         channel C      */\n\t\t/* LFO */\n\t\tams = ams_table[(amsCnt+=amsIncr)>>AMS_SHIFT];\n\t\tvib = vib_table[(vibCnt+=vibIncr)>>VIB_SHIFT];\n\t\toutd[0] = 0;\n\t\t/* FM part */\n\t\tfor(CH=S_CH ; CH < R_CH ; CH++)\n\t\t\tOPL_CALC_CH(CH);\n\t\t/* Rythm part */\n\t\tif(rythm)\n\t\t\tOPL_CALC_RH(S_CH);\n\t\toutd[0] *= volume;\n\t\t/* limit check */\n\t\tdata = Limit( outd[0] , OPL_MAXOUT, OPL_MINOUT );\n\t\t/* store to sound buffer */\n\t\tbuf[i] = data >> OPL_OUTSB;\n\t}\n\n\tOPL->amsCnt = amsCnt;\n\tOPL->vibCnt = vibCnt;\n#ifdef OPL_OUTPUT_LOG\n\tif(opl_dbg_fp)\n\t{\n\t\tfor(opl_dbg_chip=0;opl_dbg_chip<opl_dbg_maxchip;opl_dbg_chip++)\n\t\t\tif( opl_dbg_opl[opl_dbg_chip] == OPL) break;\n\t\tfprintf(opl_dbg_fp,\"%c%c%c\",0x20+opl_dbg_chip,length&0xff,length/256);\n\t}\n#endif\n}\n#endif /* (BUILD_YM3812 || BUILD_YM3526) */\n\n#if BUILD_Y8950\n\nvoid Y8950UpdateOne(FM_OPL *OPL, INT16 *buffer, int length)\n{\n    int i;\n\tint data;\n\tOPLSAMPLE *buf = buffer;\n\tUINT32 amsCnt  = OPL->amsCnt;\n\tUINT32 vibCnt  = OPL->vibCnt;\n\tUINT8 rythm = OPL->rythm&0x20;\n\tOPL_CH *CH,*R_CH;\n\tYM_DELTAT *DELTAT = OPL->deltat;\n\n\t/* setup DELTA-T unit */\n\tYM_DELTAT_DECODE_PRESET(DELTAT);\n\n\tif( (void *)OPL != cur_chip ){\n\t\tcur_chip = (void *)OPL;\n\t\t/* channel pointers */\n\t\tS_CH = OPL->P_CH;\n\t\tE_CH = &S_CH[9];\n\t\t/* rythm slot */\n\t\tSLOT7_1 = &S_CH[7].SLOT[SLOT1];\n\t\tSLOT7_2 = &S_CH[7].SLOT[SLOT2];\n\t\tSLOT8_1 = &S_CH[8].SLOT[SLOT1];\n\t\tSLOT8_2 = &S_CH[8].SLOT[SLOT2];\n\t\t/* LFO state */\n\t\tamsIncr = OPL->amsIncr;\n\t\tvibIncr = OPL->vibIncr;\n\t\tams_table = OPL->ams_table;\n\t\tvib_table = OPL->vib_table;\n\t}\n\tR_CH = rythm ? &S_CH[6] : E_CH;\n    for( i=0; i < length ; i++ )\n\t{\n\t\t/*            channel A         channel B         channel C      */\n\t\t/* LFO */\n\t\tams = ams_table[(amsCnt+=amsIncr)>>AMS_SHIFT];\n\t\tvib = vib_table[(vibCnt+=vibIncr)>>VIB_SHIFT];\n\t\toutd[0] = 0;\n\t\t/* deltaT ADPCM */\n\t\tif( DELTAT->portstate )\n\t\t\tYM_DELTAT_ADPCM_CALC(DELTAT);\n\t\t/* FM part */\n\t\tfor(CH=S_CH ; CH < R_CH ; CH++)\n\t\t\tOPL_CALC_CH(CH);\n\t\t/* Rythm part */\n\t\tif(rythm)\n\t\t\tOPL_CALC_RH(S_CH);\n\t\t/* limit check */\n\t\tdata = Limit( outd[0] , OPL_MAXOUT, OPL_MINOUT );\n\t\t/* store to sound buffer */\n\t\tbuf[i] = data >> OPL_OUTSB;\n\t}\n\tOPL->amsCnt = amsCnt;\n\tOPL->vibCnt = vibCnt;\n\t/* deltaT START flag */\n\tif( !DELTAT->portstate )\n\t\tOPL->status &= 0xfe;\n}\n#endif\n\n/* ---------- reset one of chip ---------- */\nvoid OPLResetChip(FM_OPL *OPL)\n{\n\tint c,s;\n\tint i;\n\n\t/* reset chip */\n\tOPL->mode   = 0;\t/* normal mode */\n\tOPL_STATUS_RESET(OPL,0x7f);\n\t/* reset with register write */\n\tOPLWriteReg(OPL,0x01,0); /* wabesel disable */\n\tOPLWriteReg(OPL,0x02,0); /* Timer1 */\n\tOPLWriteReg(OPL,0x03,0); /* Timer2 */\n\tOPLWriteReg(OPL,0x04,0); /* IRQ mask clear */\n\tfor(i = 0xff ; i >= 0x20 ; i-- ) OPLWriteReg(OPL,i,0);\n\t/* reset OPerator parameter */\n\tfor( c = 0 ; c < OPL->max_ch ; c++ )\n\t{\n\t\tOPL_CH *CH = &OPL->P_CH[c];\n\t\t/* OPL->P_CH[c].PAN = OPN_CENTER; */\n\t\tfor(s = 0 ; s < 2 ; s++ )\n\t\t{\n\t\t\t/* wave table */\n\t\t\tCH->SLOT[s].wavetable = &SIN_TABLE[0];\n\t\t\t/* CH->SLOT[s].evm = ENV_MOD_RR; */\n\t\t\tCH->SLOT[s].evc = EG_OFF;\n\t\t\tCH->SLOT[s].eve = EG_OFF+1;\n\t\t\tCH->SLOT[s].evs = 0;\n\t\t}\n\t}\n#if BUILD_Y8950\n\tif(OPL->type&OPL_TYPE_ADPCM)\n\t{\n\t\tYM_DELTAT *DELTAT = OPL->deltat;\n\n\t\tDELTAT->freqbase = OPL->freqbase;\n\t\tDELTAT->output_pointer = outd;\n\t\tDELTAT->portshift = 5;\n\t\tDELTAT->output_range = DELTAT_MIXING_LEVEL<<TL_BITS;\n\t\tYM_DELTAT_ADPCM_Reset(DELTAT,0);\n\t}\n#endif\n}\n\n/* ----------  Create one of virtual YM3812 ----------       */\n/* 'rate'  is sampling rate and 'bufsiz' is the size of the  */\nFM_OPL *OPLCreate(int type, int clock, int rate)\n{\n\tchar *ptr;\n\tFM_OPL *OPL;\n\tint state_size;\n\tint max_ch = 12; /* normally 9 channels */\n\n\tif( OPL_LockTable() ==-1) return NULL;\n\t/* allocate OPL state space */\n\tstate_size  = sizeof(FM_OPL);\n\tstate_size += sizeof(OPL_CH)*max_ch;\n#if BUILD_Y8950\n\tif(type&OPL_TYPE_ADPCM) state_size+= sizeof(YM_DELTAT);\n#endif\n\t/* allocate memory block */\n\tptr = (char*)malloc(state_size);\n\tif(ptr==NULL) return NULL;\n\t/* clear */\n\tmemset(ptr,0,state_size);\n\tOPL        = (FM_OPL *)ptr; ptr+=sizeof(FM_OPL);\n\tOPL->P_CH  = (OPL_CH *)ptr; ptr+=sizeof(OPL_CH)*max_ch;\n#if BUILD_Y8950\n\tif(type&OPL_TYPE_ADPCM) OPL->deltat = (YM_DELTAT *)ptr; ptr+=sizeof(YM_DELTAT);\n#endif\n\t/* set channel state pointer */\n\tOPL->type  = type;\n\tOPL->clock = clock;\n\tOPL->rate  = rate;\n\tOPL->max_ch = max_ch;\n\t/* init global tables */\n\tOPL_initalize(OPL);\n\t/* reset chip */\n\tOPLResetChip(OPL);\n#ifdef OPL_OUTPUT_LOG\n\tif(!opl_dbg_fp)\n\t{\n\t\topl_dbg_fp = fopen(\"opllog.opl\",\"wb\");\n\t\topl_dbg_maxchip = 0;\n\t}\n\tif(opl_dbg_fp)\n\t{\n\t\topl_dbg_opl[opl_dbg_maxchip] = OPL;\n\t\tfprintf(opl_dbg_fp,\"%c%c%c%c%c%c\",0x00+opl_dbg_maxchip,\n\t\t\ttype,\n\t\t\tclock&0xff,\n\t\t\t(clock/0x100)&0xff,\n\t\t\t(clock/0x10000)&0xff,\n\t\t\t(clock/0x1000000)&0xff);\n\t\topl_dbg_maxchip++;\n\t}\n#endif\n\treturn OPL;\n}\n\n/* ----------  Destroy one of virtual YM3812 ----------       */\nvoid OPLDestroy(FM_OPL *OPL)\n{\n\tif(!OPL)\n\t{\n\t\treturn;\n\t}\n#ifdef OPL_OUTPUT_LOG\n\tif(opl_dbg_fp)\n\t{\n\t\tfclose(opl_dbg_fp);\n\t\topl_dbg_fp = NULL;\n\t}\n#endif\n\tOPL_UnLockTable();\n\tfree(OPL);\n}\n\n/* ----------  Option handlers ----------       */\n\nvoid OPLSetTimerHandler(FM_OPL *OPL,OPL_TIMERHANDLER TimerHandler,int channelOffset)\n{\n\tOPL->TimerHandler   = TimerHandler;\n\tOPL->TimerParam = channelOffset;\n}\nvoid OPLSetIRQHandler(FM_OPL *OPL,OPL_IRQHANDLER IRQHandler,int param)\n{\n\tOPL->IRQHandler     = IRQHandler;\n\tOPL->IRQParam = param;\n}\nvoid OPLSetUpdateHandler(FM_OPL *OPL,OPL_UPDATEHANDLER UpdateHandler,int param)\n{\n\tOPL->UpdateHandler = UpdateHandler;\n\tOPL->UpdateParam = param;\n}\n#if BUILD_Y8950\nvoid OPLSetPortHandler(FM_OPL *OPL,OPL_PORTHANDLER_W PortHandler_w,OPL_PORTHANDLER_R PortHandler_r,int param)\n{\n\tOPL->porthandler_w = PortHandler_w;\n\tOPL->porthandler_r = PortHandler_r;\n\tOPL->port_param = param;\n}\n\nvoid OPLSetKeyboardHandler(FM_OPL *OPL,OPL_PORTHANDLER_W KeyboardHandler_w,OPL_PORTHANDLER_R KeyboardHandler_r,int param)\n{\n\tOPL->keyboardhandler_w = KeyboardHandler_w;\n\tOPL->keyboardhandler_r = KeyboardHandler_r;\n\tOPL->keyboard_param = param;\n}\n#endif\n/* ---------- YM3812 I/O interface ---------- */\nint OPLWrite(FM_OPL *OPL,int a,int v)\n{\n\tif( !(a&1) )\n\t{\t/* address port */\n\t\tOPL->address = v & 0xff;\n\t}\n\telse\n\t{\t/* data port */\n\t\tif(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam,0);\n#ifdef OPL_OUTPUT_LOG\n\tif(opl_dbg_fp)\n\t{\n\t\tfor(opl_dbg_chip=0;opl_dbg_chip<opl_dbg_maxchip;opl_dbg_chip++)\n\t\t\tif( opl_dbg_opl[opl_dbg_chip] == OPL) break;\n\t\tfprintf(opl_dbg_fp,\"%c%c%c\",0x10+opl_dbg_chip,OPL->address,v);\n\t}\n#endif\n\t\tOPLWriteReg(OPL,OPL->address,v);\n\t}\n\treturn OPL->status>>7;\n}\n\nunsigned char OPLRead(FM_OPL *OPL,int a)\n{\n\tif( !(a&1) )\n\t{\t/* status port */\n\t\treturn OPL->status & (OPL->statusmask|0x80);\n\t}\n\t/* data port */\n\tswitch(OPL->address)\n\t{\n\tcase 0x05: /* KeyBoard IN */\n\t\tif(OPL->type&OPL_TYPE_KEYBOARD)\n\t\t{\n\t\t\tif(OPL->keyboardhandler_r)\n\t\t\t{\n\t\t\t\treturn OPL->keyboardhandler_r(OPL->keyboard_param);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tLOG(LOG_WAR,(\"OPL:read unmapped KEYBOARD port\\n\"));\n\t\t\t}\n\t\t}\n\t\treturn 0;\n#if 0\n\tcase 0x0f: /* ADPCM-DATA  */\n\t\treturn 0;\n#endif\n\tcase 0x19: /* I/O DATA    */\n\t\tif(OPL->type&OPL_TYPE_IO)\n\t\t{\n\t\t\tif(OPL->porthandler_r)\n\t\t\t{\n\t\t\t\treturn OPL->porthandler_r(OPL->port_param);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tLOG(LOG_WAR,(\"OPL:read unmapped I/O port\\n\"));\n\t\t\t}\n\t\t}\n\t\treturn 0;\n\tcase 0x1a: /* PCM-DATA    */\n\t\treturn 0;\n\t}\n\treturn 0;\n}\n\nint OPLTimerOver(FM_OPL *OPL,int c)\n{\n\tif( c )\n\t{\t/* Timer B */\n\t\tOPL_STATUS_SET(OPL,0x20);\n\t}\n\telse\n\t{\t/* Timer A */\n\t\tOPL_STATUS_SET(OPL,0x40);\n\t\t/* CSM mode key,TL control */\n\t\tif( OPL->mode & 0x80 )\n\t\t{\t/* CSM mode total level latch and auto key on */\n\t\t\tint ch;\n\t\t\tif(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam,0);\n\t\t\tfor(ch=0;ch<9;ch++)\n\t\t\t\tCSMKeyControl( &OPL->P_CH[ch] );\n\t\t}\n\t}\n\t/* reload timer */\n\tif (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+c,(double)OPL->T[c]*OPL->TimerBase);\n\treturn OPL->status>>7;\n}\n"
  },
  {
    "path": "src/Engine/Adlib/fmopl.h",
    "content": "#pragma once\n\n/* --- select emulation chips --- */\n#define BUILD_YM3812 (HAS_YM3812)\n//#define BUILD_YM3526 (HAS_YM3526)\n//#define BUILD_Y8950  (HAS_Y8950)\n\n/* --- system optimize --- */\n/* select bit size of output : 8 or 16 */\n#define OPL_OUTPUT_BIT 16\n\n/* compiler dependence */\n#ifndef OSD_CPU_H\n#define OSD_CPU_H\ntypedef unsigned char\tUINT8;   /* unsigned  8bit */\ntypedef unsigned short\tUINT16;  /* unsigned 16bit */\ntypedef unsigned int\tUINT32;  /* unsigned 32bit */\ntypedef signed char\t\tINT8;    /* signed  8bit   */\ntypedef signed short\tINT16;   /* signed 16bit   */\ntypedef signed int\t\tINT32;   /* signed 32bit   */\n#endif\n\n#if (OPL_OUTPUT_BIT==16)\ntypedef INT16 OPLSAMPLE;\n#endif\n#if (OPL_OUTPUT_BIT==8)\ntypedef unsigned char  OPLSAMPLE;\n#endif\n\n\n#if BUILD_Y8950\n#include \"ymdeltat.h\"\n#endif\n\ntypedef void (*OPL_TIMERHANDLER)(int channel,double interval_Sec);\ntypedef void (*OPL_IRQHANDLER)(int param,int irq);\ntypedef void (*OPL_UPDATEHANDLER)(int param,int min_interval_us);\ntypedef void (*OPL_PORTHANDLER_W)(int param,unsigned char data);\ntypedef unsigned char (*OPL_PORTHANDLER_R)(int param);\n\n/* !!!!! here is private section , do not access there member direct !!!!! */\n\n#define OPL_TYPE_WAVESEL   0x01  /* waveform select    */\n#define OPL_TYPE_ADPCM     0x02  /* DELTA-T ADPCM unit */\n#define OPL_TYPE_KEYBOARD  0x04  /* keyboard interface */\n#define OPL_TYPE_IO        0x08  /* I/O port */\n\n/* Saving is necessary for member of the 'R' mark for suspend/resume */\n/* ---------- OPL one of slot  ---------- */\ntypedef struct fm_opl_slot {\n\tINT32 TL;\t\t/* total level     :TL << 8            */\n\tINT32 TLL;\t\t/* adjusted now TL                     */\n\tUINT8  KSR;\t\t/* key scale rate  :(shift down bit)   */\n\tINT32 *AR;\t\t/* attack rate     :&AR_TABLE[AR<<2]   */\n\tINT32 *DR;\t\t/* decay rate      :&DR_TALBE[DR<<2]   */\n\tINT32 SL;\t\t/* sustin level    :SL_TALBE[SL]       */\n\tINT32 *RR;\t\t/* release rate    :&DR_TABLE[RR<<2]   */\n\tUINT8 ksl;\t\t/* keyscale level  :(shift down bits)  */\n\tUINT8 ksr;\t\t/* key scale rate  :kcode>>KSR         */\n\tUINT32 mul;\t\t/* multiple        :ML_TABLE[ML]       */\n\tUINT32 Cnt;\t\t/* frequency count :                   */\n\tUINT32 Incr;\t/* frequency step  :                   */\n\t/* envelope generator state */\n\tUINT8 eg_typ;\t/* envelope type flag                  */\n\tUINT8 evm;\t\t/* envelope phase                      */\n\tINT32 evc;\t\t/* envelope counter                    */\n\tINT32 eve;\t\t/* envelope counter end point          */\n\tINT32 evs;\t\t/* envelope counter step               */\n\tINT32 evsa;\t/* envelope step for AR :AR[ksr]           */\n\tINT32 evsd;\t/* envelope step for DR :DR[ksr]           */\n\tINT32 evsr;\t/* envelope step for RR :RR[ksr]           */\n\t/* LFO */\n\tUINT8 ams;\t\t/* ams flag                            */\n\tUINT8 vib;\t\t/* vibrate flag                        */\n\t/* wave selector */\n\tINT32 **wavetable;\n}OPL_SLOT;\n\n/* ---------- OPL one of channel  ---------- */\ntypedef struct fm_opl_channel {\n\tOPL_SLOT SLOT[2];\n\tUINT8 CON;\t\t\t/* connection type                     */\n\tUINT8 FB;\t\t\t/* feed back       :(shift down bit)   */\n\tINT32 *connect1;\t/* slot1 output pointer                */\n\tINT32 *connect2;\t/* slot2 output pointer                */\n\tINT32 op1_out[2];\t/* slot1 output for selfeedback        */\n\t/* phase generator state */\n\tUINT32  block_fnum;\t/* block+fnum      :                   */\n\tUINT8 kcode;\t\t/* key code        : KeyScaleCode      */\n\tUINT32  fc;\t\t\t/* Freq. Increment base                */\n\tUINT32  ksl_base;\t/* KeyScaleLevel Base step             */\n\tUINT8 keyon;\t\t/* key on/off flag                     */\n} OPL_CH;\n\n/* OPL state */\ntypedef struct fm_opl_f {\n\tUINT8 type;\t\t\t/* chip type                         */\n\tint clock;\t\t\t/* master clock  (Hz)                */\n\tint rate;\t\t\t/* sampling rate (Hz)                */\n\tdouble freqbase;\t/* frequency base                    */\n\tdouble TimerBase;\t/* Timer base time (==sampling time) */\n\tUINT8 address;\t\t/* address register                  */\n\tUINT8 status;\t\t/* status flag                       */\n\tUINT8 statusmask;\t/* status mask                       */\n\tUINT32 mode;\t\t/* Reg.08 : CSM , notesel,etc.       */\n\t/* Timer */\n\tint T[2];\t\t\t/* timer counter                     */\n\tUINT8 st[2];\t\t/* timer enable                      */\n\t/* FM channel slots */\n\tOPL_CH *P_CH;\t\t/* pointer of CH                     */\n\tint\tmax_ch;\t\t\t/* maximum channel                   */\n\t/* Rythm sention */\n\tUINT8 rythm;\t\t/* Rythm mode , key flag */\n#if BUILD_Y8950\n\t/* Delta-T ADPCM unit (Y8950) */\n\tYM_DELTAT *deltat;\t\t\t/* DELTA-T ADPCM       */\n#endif\n\t/* Keyboard / I/O interface unit (Y8950) */\n\tUINT8 portDirection;\n\tUINT8 portLatch;\n\tOPL_PORTHANDLER_R porthandler_r;\n\tOPL_PORTHANDLER_W porthandler_w;\n\tint port_param;\n\tOPL_PORTHANDLER_R keyboardhandler_r;\n\tOPL_PORTHANDLER_W keyboardhandler_w;\n\tint keyboard_param;\n\t/* time tables */\n\tINT32 AR_TABLE[75];\t/* attack rate tables */\n\tINT32 DR_TABLE[75];\t/* decay rate tables   */\n\tUINT32 FN_TABLE[1024];  /* fnumber -> increment counter */\n\t/* LFO */\n\tINT32 *ams_table;\n\tINT32 *vib_table;\n\tINT32 amsCnt;\n\tINT32 amsIncr;\n\tINT32 vibCnt;\n\tINT32 vibIncr;\n\t/* wave selector enable flag */\n\tUINT8 wavesel;\n\t/* external event callback handler */\n\tOPL_TIMERHANDLER  TimerHandler;\t\t/* TIMER handler   */\n\tint TimerParam;\t\t\t\t\t\t/* TIMER parameter */\n\tOPL_IRQHANDLER    IRQHandler;\t\t/* IRQ handler    */\n\tint IRQParam;\t\t\t\t\t\t/* IRQ parameter  */\n\tOPL_UPDATEHANDLER UpdateHandler;\t/* stream update handler   */\n\tint UpdateParam;\t\t\t\t\t/* stream update parameter */\n} FM_OPL;\n\n/* ---------- Generic interface section ---------- */\n#define OPL_TYPE_YM3526 (0)\n#define OPL_TYPE_YM3812 (OPL_TYPE_WAVESEL)\n#define OPL_TYPE_Y8950  (OPL_TYPE_ADPCM|OPL_TYPE_KEYBOARD|OPL_TYPE_IO)\n\nFM_OPL *OPLCreate(int type, int clock, int rate);\nvoid OPLDestroy(FM_OPL *OPL);\nvoid OPLSetTimerHandler(FM_OPL *OPL,OPL_TIMERHANDLER TimerHandler,int channelOffset);\nvoid OPLSetIRQHandler(FM_OPL *OPL,OPL_IRQHANDLER IRQHandler,int param);\nvoid OPLSetUpdateHandler(FM_OPL *OPL,OPL_UPDATEHANDLER UpdateHandler,int param);\n/* Y8950 port handlers */\nvoid OPLSetPortHandler(FM_OPL *OPL,OPL_PORTHANDLER_W PortHandler_w,OPL_PORTHANDLER_R PortHandler_r,int param);\nvoid OPLSetKeyboardHandler(FM_OPL *OPL,OPL_PORTHANDLER_W KeyboardHandler_w,OPL_PORTHANDLER_R KeyboardHandler_r,int param);\n\nvoid OPLResetChip(FM_OPL *OPL);\nint OPLWrite(FM_OPL *OPL,int a,int v);\nunsigned char OPLRead(FM_OPL *OPL,int a);\nint OPLTimerOver(FM_OPL *OPL,int c);\n\n/* YM3626/YM3812 local section */\nvoid YM3812UpdateOne(FM_OPL *OPL, INT16 *buffer, int length, int stripe, float volume);\n\nvoid Y8950UpdateOne(FM_OPL *OPL, INT16 *buffer, int length);\n"
  },
  {
    "path": "src/Engine/AdlibMusic.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"AdlibMusic.h\"\n#include <algorithm>\n#include \"Options.h\"\n#include \"Logger.h\"\n#include \"Game.h\"\n#include \"SDL2Helpers.h\"\n#include \"FileMap.h\"\n#include \"Adlib/fmopl.h\"\n#include \"Adlib/adlplayer.h\"\n\nextern FM_OPL* opl[2];\n\nnamespace OpenXcom\n{\n\nint AdlibMusic::delay = 0;\nint AdlibMusic::rate = 0;\nstd::map<int, int> AdlibMusic::delayRates;\n\n/**\n * Initializes a new music track.\n * @param volume Music volume modifier (1.0 = 100%).\n */\nAdlibMusic::AdlibMusic(float volume) : Music(), _data(0), _size(0), _volume(volume)\n{\n\trate = Options::audioSampleRate;\n\tif (!opl[0])\n\t{\n\t\topl[0] = OPLCreate(OPL_TYPE_YM3812, 3579545, rate);\n\t}\n\tif (!opl[1])\n\t{\n\t\topl[1] = OPLCreate(OPL_TYPE_YM3812, 3579545, rate);\n\t}\n\t// magic value - length of 1 tick per sample rate\n\tif (delayRates.empty())\n\t{\n\t\tdelayRates[8000] = 114 * 4;\n\t\tdelayRates[11025] = 157 * 4;\n\t\tdelayRates[16000] = 228 * 4;\n\t\tdelayRates[22050] = 314 * 4;\n\t\tdelayRates[32000] = 456 * 4;\n\t\tdelayRates[44100] = 629 * 4;\n\t\tdelayRates[48000] = 685 * 4;\n\t}\n}\n\n/**\n * Deletes the loaded music content.\n */\nAdlibMusic::~AdlibMusic()\n{\n\tif (opl[0])\n\t{\n\t\tstop();\n\t\tOPLDestroy(opl[0]);\n\t\topl[0] = 0;\n\t}\n\tif (opl[1])\n\t{\n\t\tOPLDestroy(opl[1]);\n\t\topl[1] = 0;\n\t}\n\tif (_data)\n\t{\n\t\tSDL_free(_data);\n\t}\n}\n\n/**\n * Loads a music file from a specified filename.\n * @param filename Filename of the music file.\n */\nvoid AdlibMusic::load(const std::string &filename)\n{\n\tload(FileMap::getRWops(filename));\n}\n\n/**\n * Loads a music file from a specified rwops.\n * @param rwops rwops of the music data.\n */\nvoid AdlibMusic::load(SDL_RWops *rwops)\n{\n\t_data = (char *)SDL_LoadFile_RW(rwops, &_size, SDL_TRUE);\n}\n\n/**\n * Plays the contained music track.\n * @param loop Amount of times to loop the track. -1 = infinite\n */\nvoid AdlibMusic::play(int) const\n{\n#ifndef __NO_MUSIC\n\tif (!Options::mute)\n\t{\n\t\tstop();\n\t\tfunc_setup_music((unsigned char*)_data, _size);\n\t\tfunc_set_music_volume(127 * _volume);\n\t\tMix_HookMusic(player, (void*)this);\n\t}\n#endif\n}\n\n/**\n * Custom audio player.\n * @param udata User data to send to the player.\n * @param stream Raw audio to output.\n * @param len Length of audio to output.\n */\nvoid AdlibMusic::player(void *udata, Uint8 *stream, int len)\n{\n#ifndef __NO_MUSIC\n\t// Check SDL volume for Background Mute functionality\n\tif (Options::musicVolume == 0 || Mix_VolumeMusic(-1) == 0)\n\t\treturn;\n\tif (Options::musicAlwaysLoop && !func_is_music_playing())\n\t{\n\t\tAdlibMusic *music = (AdlibMusic*)udata;\n\t\tmusic->play();\n\t\treturn;\n\t}\n\twhile (len != 0)\n\t{\n\t\tif (!opl[0] || !opl[1])\n\t\t\treturn;\n\t\tint i = std::min(delay, len);\n\t\tif (i)\n\t\t{\n\t\t\tfloat volume = Game::volumeExponent(Options::musicVolume);\n\t\t\tYM3812UpdateOne(opl[0], (INT16*)stream, i / 2, 2, volume);\n\t\t\tYM3812UpdateOne(opl[1], ((INT16*)stream) + 1, i / 2, 2, volume);\n\t\t\tstream += i;\n\t\t\tdelay -= i;\n\t\t\tlen -= i;\n\t\t}\n\t\tif (!len)\n\t\t\treturn;\n\t\tfunc_play_tick();\n\n\t\tdelay = delayRates[rate];\n\t}\n#endif\n}\n\nbool AdlibMusic::isPlaying()\n{\n#ifndef __NO_MUSIC\n\tif (!Options::mute)\n\t{\n\t\treturn func_is_music_playing();\n\t}\n#endif\n\treturn false;\n}\n\n}\n"
  },
  {
    "path": "src/Engine/AdlibMusic.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Music.h\"\n#include <map>\n#include <string>\n\nnamespace OpenXcom\n{\n\n/**\n * Container for Adlib music tracks.\n * Uses a custom YM3812 music player passed to SDL_mixer.\n */\nclass AdlibMusic : public Music\n{\nprivate:\n\tchar *_data;\n\tsize_t _size;\n\tfloat _volume;\n\tstatic int delay, rate;\n\tstatic std::map<int, int> delayRates;\npublic:\n\t/// Creates a blank music track.\n\tAdlibMusic(float volume = 1.0f);\n\t/// Cleans up the music track.\n\t~AdlibMusic();\n\t/// Loads music from the specified file.\n\tvoid load(const std::string &filename) override;\n\t/// Loads music from the specified rwops.\n\tvoid load(SDL_RWops *rwops) override;\n\t/// Plays the music.\n\tvoid play(int loop = -1) const override;\n\t/// Adlib music player.\n\tstatic void player(void *udata, Uint8 *stream, int len);\n\tbool isPlaying();\n};\n\n}\n"
  },
  {
    "path": "src/Engine/CatFile.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"CatFile.h\"\n#include \"Logger.h\"\n#include \"FileMap.h\"\n#include \"SDL2Helpers.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Creates a CAT file stream. A CAT file starts with an index of the\n * offset and size of every file contained within. Each file consists\n * of a filename followed by its contents.\n * @param rw SDL_RWops of the CAT file.\n */\nCatFile::CatFile(const std::string& filename) : _data(0), _items()\n{\n\t// Get amount of files\n\n\t/* File format is: {offset_le32, size_le32}[N] ;  bytes[]\n\t * the first offset effectively determines the offset/size table size\n\t * which is N = offset/8 units.\n\t *\n\t * Size may or may not include the name \"chunk\" size, or there might\n\t * not be such a chunk. True item size has to be calculated based\n\t * on offsets only.\n\t *\n\t * The \"name\" chunk format is { int8_t size, char[size] name }\n\t *\n\t * \t\tSOUND/INTRO.CAT  : records do not contain names : offset+size = next offset or EOF\n\t *\t\tSOUND/RINTRO.CAT\n\t * \t\tSOUND/ROLAND.CAT\n\t * \t\tSOUND/AINTRO.CAT\n\t *\t\tSOUND/ADLIB.CAT\n\t *\n\t * \t\tSOUND/SOUND.CAT  : size does include name : offset+size = next offset or EOF\n\t * \t\tSOUND/SOUND1.CAT\n\t * \t\tSOUND/SOUND2.CAT\n\t *\n\t * \t\tSOUND/GM.CAT     : size does not include name : offset+size+namelen+1 = next offset or EOF\n\t * \t\tSOUND/SAMPLE.CAT\n\t * \t\tSOUND/SAMPLE2.CAT\n\t * \t\tSOUND/SAMPLE2.CAT\n\t *\t\tTFTD/SOUND/SAMPLE.CAT\n\t *\n\t * Given an rwops object, this reads it and sets up rwops instances\n\t * for each chunk.\n\t *\n\t * The original rwops object is consumed here.\n\t */\n\t_filename = filename;\n\tauto rwops = FileMap::getRWops(filename);\n\tauto offset0 = SDL_ReadLE32(rwops); // read the first offset; 8 is the sizeof(item) of the header\n\tSDL_RWseek(rwops, 0, RW_SEEK_SET);  // reset the rwops pointer back\n\tsize_t filesize;\n\t_data = (Uint8 *)SDL_LoadFile_RW(rwops, &filesize, SDL_FALSE); // read all of the file\n\tSDL_RWseek(rwops, 0, RW_SEEK_SET);  // and again reset the rwops pointer back\n\n\tif (offset0 >= filesize) {\n\t\tLog(LOG_WARNING) << \"Catfile(\" << filename << \"): first offset \" << offset0 << \">= file size \" << filesize << \", not parsing.\";\n\t\tSDL_RWclose(rwops);\n\t\treturn;\n\t}\n\tfor (Uint32 i = 0; i < offset0 / 8; ++i) {\n\t\tauto offset = SDL_ReadLE32(rwops);\n\t\tSDL_ReadLE32(rwops); // ignore size;\n\t\t// reject bad data\n\t\tif (offset >= filesize) {\n\t\t\tLog(LOG_WARNING) << \"Catfile(\"<<filename<<\"): item \"<<i<<\" outside of the file: offset=\"<<offset<<\" \"<<\" filesize=\"<<filesize;\n\t\t\tcontinue;\n\t\t}\n\t\t_items.push_back(std::make_tuple(_data + offset, offset));\n\t}\n\tUint32 last_offset = filesize;\n\tfor ( auto it = _items.rbegin(); it != _items.rend(); ++it) {\n\t\tauto this_offset = std::get<1>(*it);\n\t\tstd::get<1>(*it) = last_offset - this_offset;\n\t\tlast_offset = this_offset;\n\t}\n\tSDL_RWclose(rwops);\n}\n\n/**\n * Frees associated memory.\n */\nCatFile::~CatFile()\n{\n\tif (_data) { SDL_free(_data); }\n}\n\n/**\n * Creates and returns an rwops for an item.\n * @param i Object number to load.\n * @param keepname Don't strip internal file name (needed for adlib).\n * @return SDL_RWops for the object data.\n */\nSDL_RWops *CatFile::getRWops(Uint32 i) {\n\tif (i >= _items.size()) {\n\t\tLog(LOG_ERROR) << \"Catfile<\" << _filename << \">::getRWops(\"<<i<<\"): >= size \" << _items.size();\n\t\treturn NULL;\n\t}\n\treturn SDL_RWFromConstMem(std::get<0>(_items[i]), std::get<1>(_items[i]));\n}\n\n}\n"
  },
  {
    "path": "src/Engine/CatFile.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <vector>\n#include <string>\n#include <tuple>\n#include <SDL_rwops.h>\n\n\nnamespace OpenXcom\n{\n\n/**\n * Handles CAT files\n */\nclass CatFile\n{\nprivate:\n\tstd::string _filename;\n\tUint8 *_data;\n\tstd::vector<std::tuple<void *, size_t>> _items;\n\npublic:\n\t/// Creates a CAT file stream.\n\tCatFile(const std::string& filename);\n\t/// Cleans up the stream.\n\t~CatFile();\n\t/// Get amount of objects.\n\tsize_t size() const { return _items.size(); }\n\t/// Return a pointer to the object data.\n\tSDL_RWops *getRWops(Uint32 i);\n\t/// Return the original file name\n\tconst std::string& fileName() const { return _filename; }\n};\n\n}\n"
  },
  {
    "path": "src/Engine/Collections.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <vector>\n#include <list>\n#include <unordered_map>\n#include <algorithm>\n#include \"Exception.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Helper class for managing object collections\n */\nclass Collections\n{\npublic:\n\n\t////////////////////////////////////////////////////////////\n\t//\t\t\t\t\tHelper algorithms\n\t////////////////////////////////////////////////////////////\n\n\t/**\n\t * Delete can be only used on owning pointers, to make clear difference to removeAll we reject case when it is used on collection without pointers.\n\t * @param p\n\t */\n\ttemplate<typename T>\n\tstatic void deleteAll(const T& p)\n\t{\n\t\tstatic_assert(sizeof(T) == 0, \"deleteAll can be only used on pointers and collection of pointers\");\n\t}\n\ttemplate<typename T>\n\tstatic void deleteAll(T* p)\n\t{\n\t\tdelete p;\n\t}\n\ttemplate<typename K, typename V>\n\tstatic void deleteAll(std::pair<const K, V>& p)\n\t{\n\t\tdeleteAll(p.second);\n\t}\n\n\t/**\n\t * Delete all pointers from container, it can be nested.\n\t * SFINAE, valid only if type look like container.\n\t */\n\ttemplate<typename C, typename = decltype(std::declval<C>().begin()), typename = decltype(std::declval<C>().end())>\n\tstatic void deleteAll(C& colection)\n\t{\n\t\tfor (auto p : colection)\n\t\t{\n\t\t\tdeleteAll(p);\n\t\t}\n\t\tremoveAll(colection);\n\t}\n\n\t/**\n\t * Remove and delete (if pointer) items from collection with limit.\n\t * @param collection Collection from which to remove items\n\t * @param numberToRemove Limit of removal\n\t * @param func Test what should be removed, can modify everything except this collection\n\t * @return Number of values left to remove\n\t */\n\ttemplate<typename C, typename F>\n\tstatic int deleteIf(C& colection, int numberToRemove, F&& func)\n\t{\n\t\treturn removeIf(colection, numberToRemove,\n\t\t\t[&](typename C::reference t)\n\t\t\t{\n\t\t\t\tif (func(t))\n\t\t\t\t{\n\t\t\t\t\tdeleteAll(t);\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\t}\n\n\t/**\n\t * Remove and delete (if pointer) items from collection.\n\t * @param collection Collection from which to remove items\n\t * @param func Test what should be removed, can modify everything except this collection\n\t * @return Number of values left in collection\n\t */\n\ttemplate<typename C, typename F>\n\tstatic int deleteIf(C& colection, F&& func)\n\t{\n\t\treturn deleteIf(colection, colection.size(), std::forward<F>(func));\n\t}\n\n\t/**\n\t * Clear vector. It set capacity to zero too.\n\t * @param vec\n\t */\n\ttemplate<typename T>\n\tstatic void removeAll(std::vector<T>& vec)\n\t{\n\t\tstd::vector<T>{}.swap(vec);\n\t}\n\n\t/**\n\t * Clear container.\n\t * @param collection\n\t */\n\ttemplate<typename C>\n\tstatic void removeAll(C& colection)\n\t{\n\t\tcolection.clear();\n\t}\n\n\t/**\n\t * Remove items from vector with limit.\n\t * Similar to `std::remove_if` but `std` do not allow modify anything in `func`, this function do allow.\n\t * @param vec Vector from witch remove items\n\t * @param numberToRemove Limit of removal\n\t * @param func Test what should be removed, can modify everything except this vector\n\t * @return Number of values left to remove\n\t */\n\ttemplate<typename T, typename F>\n\tstatic int removeIf(std::vector<T>& vec, int numberToRemove, F&& func)\n\t{\n\t\tif (numberToRemove <= 0)\n\t\t{\n\t\t\treturn 0;\n\t\t}\n\t\tauto begin = vec.begin();\n\t\tauto newEnd = vec.begin();\n\n\t\t// initial scan for the first element to remove\n\t\tfor (; begin != vec.end(); ++begin, ++newEnd)\n\t\t{\n\t\t\tif (func(*begin))\n\t\t\t{\n\t\t\t\t++begin;\n\t\t\t\t--numberToRemove;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// remove elements and shift not removed\n\t\tfor (auto it = begin; it != vec.end(); ++it)\n\t\t{\n\t\t\tauto& value = *it;\n\t\t\tif (numberToRemove > 0 && func(value))\n\t\t\t{\n\t\t\t\t--numberToRemove;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t*newEnd = std::move(value);\n\t\t\t\t++newEnd;\n\t\t\t}\n\t\t}\n\t\tvec.erase(newEnd, vec.end());\n\t\treturn numberToRemove;\n\t}\n\n\t/**\n\t * Remove items from collection with limit.\n\t * @param list List from witch remove items\n\t * @param numberToRemove Limit of removal\n\t * @param func Test what should be removed, can modify everything except this collection\n\t * @return Number of values left to remove\n\t */\n\ttemplate<typename C, typename F>\n\tstatic int removeIf(C& colection, int numberToRemove, F&& func)\n\t{\n\t\tif (numberToRemove <= 0)\n\t\t{\n\t\t\treturn 0;\n\t\t}\n\t\tfor (auto it = colection.begin(); it != colection.end(); )\n\t\t{\n\t\t\tauto& value = *it;\n\t\t\tif (func(value))\n\t\t\t{\n\t\t\t\tit = colection.erase(it);\n\t\t\t\tif (--numberToRemove == 0)\n\t\t\t\t{\n\t\t\t\t\treturn 0;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t++it;\n\t\t\t}\n\t\t}\n\t\treturn numberToRemove;\n\t}\n\n\t/**\n\t * Remove items from collection.\n\t * @param list List from witch remove items\n\t * @param func Test what should be removed, can modify everything except this collection\n\t * @return Number of values left in collection\n\t */\n\ttemplate<typename C, typename F>\n\tstatic int removeIf(C& colection, F&& func)\n\t{\n\t\treturn removeIf(colection, colection.size(), std::forward<F>(func));\n\t}\n\n\ttemplate<typename C, typename Predicate, typename Callback>\n\tstatic void untilLastIf(C& colection, Predicate&& p, Callback&& f)\n\t{\n\t\tint countLimit = 0;\n\t\tint curr = 0;\n\t\tfor (auto &v : colection)\n\t\t{\n\t\t\t++curr;\n\t\t\tif (p(v)) countLimit = curr;\n\t\t}\n\t\tfor (auto &v : colection)\n\t\t{\n\t\t\tif (countLimit)\n\t\t\t{\n\t\t\t\tf(v);\n\t\t\t\t--countLimit;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Sort vector using `std::less`.\n\t */\n\ttemplate<typename T>\n\tstatic void sortVector(std::vector<T>& vec)\n\t{\n\t\tstd::sort(vec.begin(), vec.end(), std::less<>());\n\t}\n\n\t/**\n\t * Check for value in sorted vector by `std::less`.\n\t */\n\ttemplate<typename T>\n\tstatic bool sortVectorHave(const std::vector<T>& vec, T v)\n\t{\n\t\treturn std::binary_search(vec.begin(), vec.end(), v, std::less<>());\n\t}\n\t/**\n\t * Remove duplicates from sort vector.\n\t */\n\ttemplate<typename T>\n\tstatic void sortVectorMakeUnique(std::vector<T>& vec)\n\t{\n\t\tvec.erase(std::unique(vec.begin(), vec.end()), vec.end());\n\t}\n\n\t////////////////////////////////////////////////////////////\n\t//\t\t\t\t\t\tRange\n\t////////////////////////////////////////////////////////////\n\n\ttemplate<typename T>\n\tstruct ValueIterator\n\t{\n\t\tT value;\n\n\t\tT operator*()\n\t\t{\n\t\t\treturn value;\n\t\t}\n\n\t\tvoid operator++()\n\t\t{\n\t\t\t++value;\n\t\t}\n\n\t\tvoid operator--()\n\t\t{\n\t\t\t--value;\n\t\t}\n\n\t\tbool operator!=(const ValueIterator& r)\n\t\t{\n\t\t\treturn value != r.value;\n\t\t}\n\t};\n\n\ttemplate<typename ItA, typename ItB>\n\tstruct ZipIterator\n\t{\n\t\tItA first;\n\t\tItB second;\n\n\t\tauto operator*() -> decltype(std::make_pair(*first, *second))\n\t\t{\n\t\t\treturn std::make_pair(*first, *second);\n\t\t}\n\n\t\tvoid operator++()\n\t\t{\n\t\t\t++first;\n\t\t\t++second;\n\t\t}\n\n\t\tbool operator!=(const ZipIterator& r)\n\t\t{\n\t\t\treturn first != r.first && second != r.second; //zip will stop when one of ranges ends, this is why `&&` instead of `||`\n\t\t}\n\t};\n\n\ttemplate<typename ItA, typename ItB>\n\tstruct ZipTieIterator\n\t{\n\t\tItA first;\n\t\tItB second;\n\n\t\tauto operator*() -> decltype(std::tie(*first, *second))\n\t\t{\n\t\t\tstatic_assert(std::is_reference_v<decltype(*first)>, \"First type need be reference\");\n\t\t\tstatic_assert(std::is_reference_v<decltype(*second)>, \"Second type need be reference\");\n\t\t\treturn std::tie(*first, *second);\n\t\t}\n\n\t\tvoid operator++()\n\t\t{\n\t\t\t++first;\n\t\t\t++second;\n\t\t}\n\n\t\tbool operator!=(const ZipTieIterator& r)\n\t\t{\n\t\t\treturn first != r.first && second != r.second; //zip will stop when one of ranges ends, this is why `&&` instead of `||`\n\t\t}\n\t};\n\n\ttemplate<typename It, typename Filter>\n\tclass FilterIterator\n\t{\n\t\tIt _curr;\n\t\tIt _end;\n\t\tFilter _filter;\n\n\tpublic:\n\n\t\tFilterIterator(It curr, It end, Filter filter) :\n\t\t\t_curr { std::move(curr)},\n\t\t\t_end { std::move(end)},\n\t\t\t_filter { std::move(filter)}\n\t\t{\n\n\t\t}\n\n\t\tauto operator*() -> decltype(*_curr)\n\t\t{\n\t\t\treturn *_curr;\n\t\t}\n\n\t\tvoid operator++()\n\t\t{\n\t\t\t++_curr;\n\t\t\twhile (_curr != _end && !_filter(*_curr))\n\t\t\t{\n\t\t\t\t++_curr;\n\t\t\t}\n\t\t}\n\n\t\tbool operator!=(const FilterIterator& r)\n\t\t{\n\t\t\treturn _curr != r._curr;\n\t\t}\n\t};\n\n\ttemplate<typename It>\n\tstruct ReverseIterator\n\t{\n\t\tIt _curr;\n\n\tpublic:\n\n\t\tReverseIterator(It curr) :\n\t\t\t_curr{ std::move(curr) }\n\t\t{\n\n\t\t}\n\n\t\tauto operator*() -> decltype(*_curr)\n\t\t{\n\t\t\tauto copy = _curr;\n\t\t\t--copy;\n\t\t\treturn *copy;\n\t\t}\n\n\t\tvoid operator++()\n\t\t{\n\t\t\t--_curr;\n\t\t}\n\n\t\tbool operator!=(const ReverseIterator& r)\n\t\t{\n\t\t\treturn _curr != r._curr;\n\t\t}\n\t};\n\n\ttemplate<typename It>\n\tclass Range\n\t{\n\t\tIt _begin;\n\t\tIt _end;\n\tpublic:\n\n\t\tRange(It begin, It end) :\n\t\t\t_begin { std::move(begin) },\n\t\t\t_end { std::move(end) }\n\t\t{\n\t\t}\n\n\t\tIt begin()\n\t\t{\n\t\t\treturn _begin;\n\t\t}\n\t\tIt end()\n\t\t{\n\t\t\treturn _end;\n\t\t}\n\t};\n\n\t/**\n\t * Create range from `min` to `max` (excluding), require that `max >= min`.\n\t * @param min minimum value of range\n\t * @param max maximum value of range\n\t * @return\n\t */\n\ttemplate<typename T>\n\tstatic Range<ValueIterator<T>> rangeValueUncheck(T begin, T end)\n\t{\n\t\treturn { ValueIterator<T>{ begin }, ValueIterator<T>{ end } };\n\t}\n\n\t/**\n\t * Create range from `min` to `max` (excluding), if `min > max` it return empty range.\n\t * @param min minimum value of range\n\t * @param max maximum value of range\n\t * @return\n\t */\n\ttemplate<typename T>\n\tstatic Range<ValueIterator<T>> rangeValue(T begin, T end)\n\t{\n\t\tif (begin < end)\n\t\t{\n\t\t\treturn rangeValueUncheck(begin, end);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn rangeValueUncheck(end, end);\n\t\t}\n\t}\n\n\t/**\n\t * Create range from zero to less than `end`\n\t * @param end\n\t * @return\n\t */\n\ttemplate<typename T>\n\tstatic Range<ValueIterator<T>> rangeValueLess(T end)\n\t{\n\t\treturn rangeValue(T{}, end);\n\t}\n\n\ttemplate<typename It>\n\tstatic Range<It> range(It begin, It end)\n\t{\n\t\treturn { begin, end };\n\t}\n\n\ttemplate<typename C>\n\tstatic auto range(C& collection) -> Range<decltype(std::data(collection))>\n\t{\n\t\treturn { std::data(collection), std::data(collection) + std::size(collection) };\n\t}\n\n\ttemplate<typename ItA, typename ItB>\n\tstatic Range<ZipIterator<ItA, ItB>> zip(Range<ItA> a, Range<ItB> b)\n\t{\n\t\treturn { { a.begin(), b.begin() }, { a.end(), b.end() } };\n\t}\n\n\ttemplate<typename ItA, typename ItB>\n\tstatic Range<ZipTieIterator<ItA, ItB>> zipTie(Range<ItA> a, Range<ItB> b)\n\t{\n\t\treturn { { a.begin(), b.begin() }, { a.end(), b.end() } };\n\t}\n\n\ttemplate<typename It>\n\tstatic Range<ReverseIterator<It>> reverse(Range<It> a)\n\t{\n\t\treturn { a.end(), a.begin() };\n\t}\n\n\ttemplate<typename It>\n\tstatic Range<It> reverse(Range<ReverseIterator<It>> a)\n\t{\n\t\treturn { a.end().curr, a.begin().curr };\n\t}\n\n\ttemplate<typename It, typename Filter>\n\tstatic Range<FilterIterator<It, Filter>> filter(Range<It> a, Filter f)\n\t{\n\t\tauto begin = a.begin();\n\t\tauto end = a.end();\n\t\tif (begin != end)\n\t\t{\n\t\t\tauto fbegin = FilterIterator<It, Filter>{ begin, end, f };\n\t\t\tif (!f(*begin))\n\t\t\t{\n\t\t\t\t++fbegin;\n\t\t\t}\n\t\t\treturn { fbegin, { end, end, f } };\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn { { end, end, f }, { end, end, f } };\n\t\t}\n\t}\n\n\ttemplate<typename It>\n\tstatic Range<ValueIterator<It>> nonDeref(Range<It> a)\n\t{\n\t\treturn { { a.begin() }, { a.end() } };\n\t}\n\n\n\t////////////////////////////////////////////////////////////\n\t//\t\t\t\t\tCustom Containers\n\t////////////////////////////////////////////////////////////\n\n\n\t/**\n\t * Helper providing conversion from some unique strings to indexes.\n\t */\n\tclass NamesToIndex\n\t{\n\t\tstd::unordered_map<std::string, size_t> _usedValues;\n\t\tstd::unordered_map<size_t, std::string> _usedNames{ { 0, \"\" } };\n\t\tsize_t _last = 1; //zero is reserved for \"empty\"\n\n\tpublic:\n\n\t\t/**\n\t\t * Return an index for a given name\n\t\t * @param name New name or old already added name\n\t\t * @param max How many unique names we can hold\n\t\t * @return Index assigned to a name.\n\t\t */\n\t\tsize_t addName(const std::string& name, size_t max)\n\t\t{\n\t\t\tauto& ref = _usedValues[name];\n\t\t\tif (ref)\n\t\t\t{\n\t\t\t\treturn ref;\n\t\t\t}\n\t\t\tif (_last == max)\n\t\t\t{\n\t\t\t\tthrow Exception(\"Number of unique names reached limit because of name '\" + name + \"'\");\n\t\t\t}\n\t\t\tref = _last++;\n\t\t\t_usedNames[ref] = name;\n\t\t\treturn ref;\n\t\t}\n\n\t\t/**\n\t\t * Get name based on index\n\t\t * @param i Index\n\t\t * @return name or empty string if index is not assigned\n\t\t */\n\t\tconst std::string& getName(size_t i) const\n\t\t{\n\t\t\tauto f = _usedNames.find(i);\n\t\t\tif (f != _usedNames.end())\n\t\t\t{\n\t\t\t\treturn f->second;\n\t\t\t}\n\t\t\treturn _usedNames.find(0)->second;\n\t\t}\n\t};\n};\n\n}\n"
  },
  {
    "path": "src/Engine/CrossPlatform.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#ifdef _MSC_VER\n#define _CRT_SECURE_NO_WARNINGS\n#endif\n#include \"CrossPlatform.h\"\n#include <exception>\n#include <algorithm>\n#include <sstream>\n#include <fstream>\n#include <string>\n#include <list>\n#include <stdint.h>\n#include <time.h>\n#include <signal.h>\n#include <sys/stat.h>\n#include <assert.h>\n#include \"Logger.h\"\n#include \"Exception.h\"\n#include \"Options.h\"\n#include \"Unicode.h\"\n#ifdef _WIN32\n#ifndef NOMINMAX\n#define NOMINMAX\n#endif\n#define WIN32_LEAN_AND_MEAN\n#include <windows.h>\n#include <shlobj.h>\n#include <shlwapi.h>\n#include <shellapi.h>\n#include <wininet.h>\n#include <urlmon.h>\n#ifndef __NO_DBGHELP\n#include <dbghelp.h>\n#endif\n#ifdef __MINGW32__\n#include <cxxabi.h>\n#endif\n#define EXCEPTION_CODE_CXX 0xe06d7363\n#ifndef __GNUC__\n#pragma comment(lib, \"advapi32.lib\")\n#pragma comment(lib, \"shell32.lib\")\n#pragma comment(lib, \"shlwapi.lib\")\n#pragma comment(lib, \"wininet.lib\")\n#pragma comment(lib, \"urlmon.lib\")\n#ifndef __NO_DBGHELP\n#pragma comment(lib, \"dbghelp.lib\")\n#endif\n#endif\n#else\t\t/* #ifdef _WIN32 */\n#include <iostream>\n#include <fstream>\n#include <locale>\n#include <SDL_image.h>\n#include <cstring>\n#include <cstdio>\n#include <cstdlib>\n#include <unistd.h>\n#include <sys/param.h>\n#include <sys/types.h>\n#include <pwd.h>\n#ifndef __CYGWIN__\n#include <execinfo.h>\n#endif\n#include <cxxabi.h>\n#include <dlfcn.h>\n#include <dirent.h>\n#include \"Unicode.h\"\n#endif\t\t/* #ifdef _WIN32 */\n#include <SDL.h>\n#include <SDL_syswm.h>\n#ifdef __HAIKU__\n#include <FindDirectory.h>\n#include <StorageDefs.h>\n#endif\n#include \"FileMap.h\"\n#include \"SDL2Helpers.h\"\n#include \"../version.h\"\n\nnamespace OpenXcom\n{\nnamespace CrossPlatform\n{\n\tstd::string errorDlg;\n\n/**\n * Determines the available Linux error dialogs.\n */\nvoid getErrorDialog()\n{\n#ifndef _WIN32\n\tif (system(NULL))\n\t{\n\t\tif (getenv(\"KDE_SESSION_UID\") && system(\"which kdialog > /dev/null 2>&1\") == 0)\n\t\t\terrorDlg = \"kdialog --error \";\n\t\telse if (system(\"which zenity > /dev/null 2>&1\") == 0)\n\t\t\terrorDlg = \"zenity --no-wrap --error --text=\";\n\t\telse if (system(\"which kdialog > /dev/null 2>&1\") == 0)\n\t\t\terrorDlg = \"kdialog --error \";\n\t\telse if (system(\"which gdialog > /dev/null 2>&1\") == 0)\n\t\t\terrorDlg = \"gdialog --msgbox \";\n\t\telse if (system(\"which xdialog > /dev/null 2>&1\") == 0)\n\t\t\terrorDlg = \"xdialog --msgbox \";\n\t}\n#endif\n}\n\n\n#ifdef _WIN32\n/**\n * Takes a Windows multibyte filesystem path and converts it to a UTF-8 string.\n * Also converts the path separator.\n * @param pathW Filesystem path.\n * @return UTF-8 string.\n */\nstatic std::string pathFromWindows(const wchar_t *pathW) {\n\tint sizeW = lstrlenW(pathW);\n\tint sizeU8 = WideCharToMultiByte(CP_UTF8, 0, pathW, sizeW, NULL, 0, NULL, NULL);\n\tstd::string pathU8(sizeU8, 0);\n\tWideCharToMultiByte(CP_UTF8, 0, pathW, sizeW, &pathU8[0], sizeU8, NULL, NULL);\n\tstd::replace(pathU8.begin(), pathU8.end(), '\\\\', '/');\n\treturn pathU8;\n}\n\n/**\n * Takes a UTF-8 string and converts it to a Windows\n * multibyte filesystem path.\n * Also converts the path separator.\n * @param path UTF-8 string.\n * @param reslash Convert forward slashes to back ones.\n * @return Filesystem path.\n */\nstatic std::wstring pathToWindows(const std::string& path, bool reslash = true) {\n\tstd::string src = path;\n\tif (reslash) {\n\t\tstd::replace(src.begin(), src.end(), '/', '\\\\');\n\t}\n\tint sizeW = MultiByteToWideChar(CP_UTF8, 0, &src[0], (int)src.size(), NULL, 0);\n\tstd::wstring pathW(sizeW, 0);\n\tMultiByteToWideChar(CP_UTF8, 0, &src[0], (int)src.size(), &pathW[0], sizeW);\n\treturn pathW;\n}\n#endif\n\nstatic std::vector<std::string> args;\n\n/**\n * Converts command-line args to UTF-8 on windows\n */\nvoid processArgs (int argc, char *argv[])\n{\n\targs.clear();\n#ifdef _WIN32\n\tauto cmdlineW = GetCommandLineW();\n\tint numArgs;\n\tauto argvW = CommandLineToArgvW(cmdlineW, &numArgs);\n\tfor (int i=0; i< numArgs; ++i) { args.push_back(pathFromWindows(argvW[i])); }\n#else\n\tfor (int i=0; i< argc; ++i) { args.push_back(argv[i]); }\n#endif\n}\n\n/// Returns the command-line arguments\nconst std::vector<std::string>& getArgs() { return args; }\n\n/**\n * Displays a message box with an error message.\n * @param error Error message.\n */\nvoid showError(const std::string &error)\n{\n#ifdef _WIN32\n\tauto titleW = pathToWindows(\"OpenXcom Error\", false);\n\tauto errorW = pathToWindows(error, false);\n\tMessageBoxW(NULL, errorW.c_str(), titleW.c_str(), MB_ICONERROR | MB_OK);\n#else\n\tif (errorDlg.empty())\n\t{\n\t\tstd::cerr << error << std::endl;\n\t}\n\telse\n\t{\n\t\tstd::string nError = '\"' + error + '\"';\n\t\tUnicode::replace(nError, \"\\n\", \"\\\\n\");\n\t\tstd::string cmd = errorDlg + nError;\n\t\tif (system(cmd.c_str()) != 0)\n\t\t\tstd::cerr << error << std::endl;\n\t}\n#endif\n\tLog(LOG_FATAL) << error;\n}\n\n#ifndef _WIN32\n/**\n * Gets the user's home folder according to the system.\n * @return Absolute path to home folder.\n */\nstatic char const *getHome()\n{\n\tchar const *home = getenv(\"HOME\");\n\tif (!home)\n\t{\n\t\tstruct passwd *const pwd = getpwuid(getuid());\n\t\thome = pwd->pw_dir;\n\t}\n\treturn home;\n}\n#endif\n\n/**\n * Builds a list of predefined paths for the Data folder\n * according to the running system.\n * @return List of data paths.\n */\nstd::vector<std::string> findDataFolders()\n{\n\tstd::vector<std::string> list;\n#ifdef __MORPHOS__\n\tlist.push_back(\"PROGDIR:\");\n\treturn list;\n#endif\n\n#ifdef _WIN32\n\tstd::unordered_set<std::string> seen; // avoid dups in case cwd = dirname(exe)\n\twchar_t pathW[MAX_PATH+1];\n\tconst std::wstring oxconst = pathToWindows(\"OpenXcom/\");\n\t// Get Documents folder\n\tif (SHGetSpecialFolderPathW(NULL, pathW, CSIDL_PERSONAL, FALSE))\n\t{\n\t\tPathAppendW(pathW, oxconst.c_str());\n\t\tauto path = pathFromWindows(pathW);\n\t\tLog(LOG_DEBUG) << \"findDataFolders(): SHGetSpecialFolderPathW: \" << path;\n\t\tif (seen.end() == seen.find(path)) { seen.insert(path); list.push_back(path); }\n\t}\n#ifdef DATADIR\n\tsnprintf(path, MAX_PATH, \"%s\\\\\", DATADIR);\n\tlist.push_back(path);\n#endif\n\t// Get binary directory\n\tif (GetModuleFileNameW(NULL, pathW, MAX_PATH) != 0)\n\t{\n\t\tPathRemoveFileSpecW(pathW);\n\t\tauto path = pathFromWindows(pathW);\n\t\tpath.push_back('/');\n\t\tLog(LOG_DEBUG) << \"findDataFolders(): GetModuleFileNameW/PathRemoveFileSpecW: \" << path;\n\t\tif (seen.end() == seen.find(path)) { seen.insert(path); list.push_back(path); }\n\t}\n\n\t// Get working directory\n\tif (GetCurrentDirectoryW(MAX_PATH, pathW) != 0)\n\t{\n\t\tauto path = pathFromWindows(pathW);\n\t\tpath.push_back('/');\n\t\tLog(LOG_DEBUG) << \"findDataFolders(): GetCurrentDirectoryW: \" << path;\n\t\tif (seen.end() == seen.find(path)) { seen.insert(path); list.push_back(path); }\n\t}\n#else\n\tchar const *home = getHome();\n#ifdef __HAIKU__\n\tchar data_path[B_PATH_NAME_LENGTH];\n\tfind_directory(B_SYSTEM_SETTINGS_DIRECTORY, 0, true, data_path, sizeof(data_path)-strlen(\"/OpenXcom/\"));\n\tstrcat(data_path,\"/OpenXcom/\");\n\tlist.push_back(data_path);\n#endif\n\tchar path[MAXPATHLEN];\n\n\t// Get user-specific data folders\n\tchar const *const xdg_data_home = getenv(\"XDG_DATA_HOME\");\n\tif (xdg_data_home && *xdg_data_home)\n \t{\n\t\tsnprintf(path, MAXPATHLEN, \"%s/openxcom/\", xdg_data_home);\n \t}\n \telse\n \t{\n#ifdef __APPLE__\n\t\tsnprintf(path, MAXPATHLEN, \"%s/Library/Application Support/OpenXcom/\", home);\n#else\n\t\tsnprintf(path, MAXPATHLEN, \"%s/.local/share/openxcom/\", home);\n#endif\n \t}\n \tlist.push_back(path);\n#ifdef DATADIR\n\tsnprintf(path, MAXPATHLEN, \"%s/\" DATADIR);\n\tlist.push_back(path);\n#endif\n\t// Get global data folders\n\tchar const *const xdg_data_dirs = getenv(\"XDG_DATA_DIRS\");\n\tif (xdg_data_dirs && *xdg_data_dirs)\n\t{\n\t\tchar xdg_data_dirs_copy[strlen(xdg_data_dirs)+1];\n\t\tstrcpy(xdg_data_dirs_copy, xdg_data_dirs);\n\t\tchar *dir = strtok(xdg_data_dirs_copy, \":\");\n\t\twhile (dir != 0)\n\t\t{\n\t\t\tsnprintf(path, MAXPATHLEN, \"%s/openxcom/\", dir);\n\t\t\tlist.push_back(path);\n\t\t\tdir = strtok(0, \":\");\n\t\t}\n\t}\n\telse\n\t{\n#ifdef __APPLE__\n\t\tlist.push_back(\"/Users/Shared/OpenXcom/\");\n#else\n\t\tlist.push_back(\"/usr/local/share/openxcom/\");\n\t\tlist.push_back(\"/usr/share/openxcom/\");\n#endif\n\t}\n#ifdef INSTALLDIR\n\tsnprintf(path, MAXPATHLEN, \"%s\", INSTALLDIR);\n\tlist.push_back(path);\n#endif\n\n#ifdef __linux\n\t{\n\t\tchar buffer[PATH_MAX];\n\t\tconst ssize_t count = readlink(\"/proc/self/exe\", buffer, PATH_MAX);\n\t\t// Get absolute executable path\n\t\tif (count != 0) {\n\t\t\tconst std::string exe_path = std::string(buffer, count);\n\t\t\t// Get folder path\n\t\t\tconst size_t dir_pos = exe_path.find_last_of(\"/\");\n\t\t\tif (dir_pos != std::string::npos) {\n\t\t\t\tstd::string dir = exe_path.substr(0, dir_pos);\n\t\t\t\tlist.push_back( dir.append(\"/\") );\n\t\t\t\tlist.push_back( dir.append(\"/../share/openxcom/\") ); // Relative FHS\n\t\t\t}\n\t\t}\n\t}\n#endif\n\t// Get working directory\n\tlist.push_back(\"./\");\n#endif\n\n\treturn list;\n}\n\n/**\n * Builds a list of predefined paths for the User folder\n * according to the running system.\n * @return List of data paths.\n */\nstd::vector<std::string> findUserFolders()\n{\n\tstd::vector<std::string> list;\n\n#ifdef __MORPHOS__\n\tlist.push_back(\"PROGDIR:\");\n\treturn list;\n#endif\n\n#ifdef _WIN32\n\tstd::unordered_set<std::string> seen;\n\twchar_t pathW[MAX_PATH+1];\n\tconst std::wstring oxconst = pathToWindows(\"OpenXcom/\");\n\tconst std::wstring usconst = pathToWindows(\"user/\");\n\n\t// Get Documents folder\n\tif (SHGetSpecialFolderPathW(NULL, pathW, CSIDL_PERSONAL, FALSE))\n\t{\n\t\tPathAppendW(pathW, oxconst.c_str());\n\t\tauto path = pathFromWindows(pathW);\n\t\tLog(LOG_DEBUG) << \"findUserFolders(): SHGetSpecialFolderPathW: \" << path;\n\t\tif (seen.end() == seen.find(path)) { seen.insert(path); list.push_back(path); }\n\t}\n\n\t// Get binary directory\n\tif (GetModuleFileNameW(NULL, pathW, MAX_PATH) != 0)\n\t{\n\t\tPathRemoveFileSpecW(pathW);\n\t\tPathAppendW(pathW, usconst.c_str());\n\t\tauto path = pathFromWindows(pathW);\n\t\tLog(LOG_DEBUG) << \"findUserFolders(): GetModuleFileNameW/PathRemoveFileSpecW: \" << path;\n\t\tif (seen.end() == seen.find(path)) { seen.insert(path); list.push_back(path); }\n\t}\n\n\t// Get working directory\n\tif (GetCurrentDirectoryW(MAX_PATH, pathW) != 0)\n\t{\n\t\tPathAppendW(pathW, usconst.c_str());\n\t\tauto path = pathFromWindows(pathW);\n\t\tLog(LOG_DEBUG) << \"findUserFolders(): GetCurrentDirectoryW: \" << path;\n\t\tif (seen.end() == seen.find(path)) { seen.insert(path); list.push_back(path); }\n\t}\n#else\n#ifdef __HAIKU__\n\tchar user_path[B_PATH_NAME_LENGTH];\n\tfind_directory(B_USER_SETTINGS_DIRECTORY, 0, true, user_path, sizeof(user_path)-strlen(\"/OpenXcom/\"));\n\tstrcat(user_path,\"/OpenXcom/\");\n\tlist.push_back(user_path);\n#endif\n\tchar const *home = getHome();\n\tchar path[MAXPATHLEN];\n\n\t// Get user folders\n\tif (char const *const xdg_data_home = getenv(\"XDG_DATA_HOME\"))\n \t{\n\t\tsnprintf(path, MAXPATHLEN, \"%s/openxcom/\", xdg_data_home);\n \t}\n \telse\n \t{\n#ifdef __APPLE__\n\t\tsnprintf(path, MAXPATHLEN, \"%s/Library/Application Support/OpenXcom/\", home);\n#else\n\t\tsnprintf(path, MAXPATHLEN, \"%s/.local/share/openxcom/\", home);\n#endif\n \t}\n\tlist.push_back(path);\n\n\t// Get old-style folder\n\tsnprintf(path, MAXPATHLEN, \"%s/.openxcom/\", home);\n\tlist.push_back(path);\n\n\t// Get working directory\n\tlist.push_back(\"./user/\");\n#endif\n\n\treturn list;\n}\n\n/**\n * Finds the Config folder according to the running system.\n * @return Config path.\n */\nstd::string findConfigFolder()\n{\n#ifdef __MORPHOS__\n\treturn \"PROGDIR:\";\n#endif\n\n#if defined(_WIN32) || defined(__APPLE__)\n\treturn \"\";\n#elif defined (__HAIKU__)\n\tchar settings_path[B_PATH_NAME_LENGTH];\n\tfind_directory(B_USER_SETTINGS_DIRECTORY, 0, true, settings_path, sizeof(settings_path)-strlen(\"/OpenXcom/\"));\n\tstrcat(settings_path,\"/OpenXcom/\");\n\treturn settings_path;\n#else\n\tchar const *home = getHome();\n\tchar path[MAXPATHLEN];\n\t// Get config folders\n\tif (char const *const xdg_config_home = getenv(\"XDG_CONFIG_HOME\"))\n\t{\n\t\tsnprintf(path, MAXPATHLEN, \"%s/openxcom/\", xdg_config_home);\n\t\treturn path;\n\t}\n\telse\n\t{\n\t\tsnprintf(path, MAXPATHLEN, \"%s/.config/openxcom/\", home);\n\t\treturn path;\n\t}\n#endif\n}\n\nstd::string searchDataFile(const std::string &filename)\n{\n\t// Correct folder separator\n\tstd::string name = filename;\n\n\t// Check current data path\n\tstd::string path = Options::getDataFolder() + name;\n\tif (fileExists(path))\n\t{\n\t\treturn path;\n\t}\n\n\t// Check every other path\n\tfor (auto& dataPath : Options::getDataList())\n\t{\n\t\tpath = dataPath + name;\n\t\tif (fileExists(path))\n\t\t{\n\t\t\treturn path;\n\t\t}\n\t}\n\n\t// Give up\n\treturn filename;\n}\n\nstd::string searchDataFolder(const std::string &foldername, std::size_t size)\n{\n\t// Correct folder separator\n\tstd::string name = foldername;\n\tstd::string path;\n\n\t// Set miminum possible of dirs\n\tstd::size_t minNumOfElementsInFolder = (\n\t\tfoldername == \"TFTD\" || foldername == \"UFO\" ? 9 : // At least 9 dictionaries with original data data\n\t\tfoldername == \"common\" ? 6 : // Files: \"Language/\", \"Palettes/\", \"Resources/\", \"Shaders/\", \"SoldierName/\", \"openxcom.png\"\n\t\tfoldername == \"standard\" ? 20 : // Now 48 mods, some buffer if some decide to drop some mods\n\t\tsize\n\t);\n\n\tif (Options::getDataFolder() != \"\")\n\t{\n\t\t// Check current data path\n\t\tpath = Options::getDataFolder() + name;\n\t\tif (folderMinSize(path, minNumOfElementsInFolder))\n\t\t{\n\t\t\treturn path;\n\t\t}\n\t}\n\n\t// Check every other path\n\tfor (auto& dataPath : Options::getDataList())\n\t{\n\t\tpath = dataPath + name;\n\t\tif (folderMinSize(path, minNumOfElementsInFolder))\n\t\t{\n\t\t\treturn path;\n\t\t}\n\t}\n\n\t// Give up\n\treturn foldername;\n}\n\n/**\n * Creates a folder at the specified path.\n * @note Only creates the last folder on the path.\n * @param path Full path.\n * @return Folder created or not.\n */\nbool createFolder(const std::string &path)\n{\n#ifdef _WIN32\n\tauto pathW = pathToWindows(path);\n\tint result = CreateDirectoryW(pathW.c_str(), 0);\n\tif (result == 0)\n\t\treturn false;\n\telse\n\t\treturn true;\n#else\n\tmode_t process_mask = umask(0);\n\tint result = mkdir(path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);\n\tumask(process_mask);\n\tif (result == 0)\n\t\treturn true;\n\telse\n\t\treturn false;\n#endif\n}\n\n/**\n * Adds an ending slash to a path if necessary.\n * @param path Folder path.\n * @return Terminated path.\n */\nstd::string convertPath(const std::string &path)\n{\n\tif (!path.empty() && path.at(path.size()-1) != '/')\n\t\treturn path + '/';\n\treturn path;\n}\n#ifdef _WIN32\nstatic time_t FILETIME2mtime(FILETIME& ft) {\n\tconst long long int TICKS_PER_SECOND = 10000000;\n\tconst long long int EPOCH_DIFFERENCE = 11644473600LL;\n\tlong long int input = 0, temp = 0;\n\n\tinput = ((long long int)ft.dwHighDateTime)<<32;\n\tinput += ft.dwLowDateTime;\n\ttemp = input / TICKS_PER_SECOND;\n\ttemp = temp - EPOCH_DIFFERENCE;\n\treturn (time_t) temp;\n}\n#endif\n/**\n * Gets the name of all the files\n * contained in a certain folder.\n * @param path Full path to folder.\n * @param ext Extension of files (\"\" if it doesn't matter).\n * @return Ordered list of all the files in the form of tuple(filename, is_folder, mtime).\n */\nstd::vector<std::tuple<std::string, bool, time_t>> getFolderContents(const std::string &path, const std::string &ext)\n{\n\tstd::vector<std::tuple<std::string, bool, time_t>> files;\n#ifdef _WIN32\n\tauto search_path = path + \"/*\";\n\tif (!ext.empty()) { search_path += \".\" + ext; }\n\tLog(LOG_VERBOSE) << \"getFolderContents(\"<<path<<\", \"<<ext<<\") -> \" << search_path;\n\tauto pathW = pathToWindows(search_path);\n\tWIN32_FIND_DATAW ffd;\n\tauto handle = FindFirstFileW(pathW.c_str(), &ffd);\n\tif (handle == INVALID_HANDLE_VALUE) {\n\t\tLog(LOG_VERBOSE) << \"getFolderContents(\"<<path<<\", \"<<ext<<\"): fail outright.\";\n\t\treturn files;\n\t}\n\tdo  {\n\t\tauto filename = pathFromWindows(ffd.cFileName);\n\t\tif ((filename == \".\") || (filename == \"..\")) { continue; }\n\t\ttime_t mtime = FILETIME2mtime(ffd.ftLastWriteTime);\n\t\tbool is_folder = ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;\n\t\tfiles.push_back(std::make_tuple(filename, is_folder, mtime));\n\t\tLog(LOG_VERBOSE) << \"getFolderContents(\"<<path<<\", \"<<ext<<\"): got '\"<<filename<<\"'\";\n\t} while (FindNextFileW(handle, &ffd) != 0);\n\tFindClose(handle);\n\tLog(LOG_VERBOSE) << \"getFolderContents(\"<<path<<\", \"<<ext<<\"): total \"<<files.size();\n#else\n\tDIR *dp = opendir(path.c_str());\n\n\tif (dp == 0)\n\t{\n\t#ifdef __MORPHOS__\n\t\treturn files;\n\t#else\n\t\tstd::string errorMessage(\"Failed to open directory: \" + path);\n\t\tthrow Exception(errorMessage);\n\t#endif\n\t}\n\tstruct dirent *dirp;\n\twhile ((dirp = readdir(dp)) != 0) {\n\t\tstd::string filename = dirp->d_name;\n\t\tif (filename[0] == '.') //allowed by C++11 for empty string as it equal '\\0'\n\t\t{\n\t\t\t//skip \".\", \"..\", \".git\", \".svn\", \".bashrc\", \".ssh\" etc.\n\t\t\tcontinue;\n\t\t}\n\t\tif (!compareExt(filename, ext))\t{ continue; }\n\t\tstd::string fullpath = path + \"/\" + filename;\n\t\tbool is_directory = folderExists(fullpath);\n\t\ttime_t mtime = getDateModified(fullpath);\n\t\tfiles.push_back(std::make_tuple(filename, is_directory, mtime));\n\t}\n\tclosedir(dp);\n#endif\n\treturn files;\n}\n\n/**\n * Gets the contents of a folder and checks\n * if they meet a required minimum size.\n * @param path Full path to folder.\n * @param size Size of the folder (number of contents).\n * @return False if the folder doesn't exist or doesn't meet the size.\n */\nbool folderMinSize(const std::string &path, std::size_t size)\n{\n\tif (!folderExists(path))\n\t{\n\t\treturn false;\n\t}\n\tif (size == 0)\n\t{\n\t\treturn true;\n\t}\n\n\treturn (getFolderContents(path).size() >= size);\n}\n\n/**\n * Checks if a certain path exists and is a folder.\n * @param path Full path to folder.\n * @return Does it exist?\n */\nbool folderExists(const std::string &path)\n{\n#ifdef _WIN32\n\tauto pathW = pathToWindows(path);\n\tbool rv = (PathIsDirectoryW(pathW.c_str()) != FALSE);\n\tLog(LOG_VERBOSE) << \"folderExists(\"<<path<<\")? \" << (rv ? \"yeah\" : \"nope\");\n\treturn rv;\n#elif __MORPHOS__\n\tBPTR l = Lock( path.c_str(), SHARED_LOCK );\n\tif ( l != NULL )\n\t{\n\t\tUnLock( l );\n\t\treturn 1;\n\t}\n\treturn 0;\n#else\n\tstruct stat info;\n\treturn (stat(path.c_str(), &info) == 0 && S_ISDIR(info.st_mode));\n#endif\n}\n\n/**\n * Checks if a certain path exists and is a file.\n * @param path Full path to file.\n * @return Does it exist?\n */\nbool fileExists(const std::string &path)\n{\n#ifdef _WIN32\n\tauto pathW = pathToWindows(path);\n\tbool rv = (PathFileExistsW(pathW.c_str()) != FALSE);\n\tLog(LOG_VERBOSE) << \"fileExists(\"<<path<<\")? \" << (rv?\"yeah\":\"nope\");\n\treturn rv;\n#elif __MORPHOS__\n\tBPTR l = Lock( path.c_str(), SHARED_LOCK );\n\tif ( l != NULL )\n\t{\n\t\tUnLock( l );\n\t\treturn 1;\n\t}\n\treturn 0;\n#else\n\tstruct stat info;\n\treturn (stat(path.c_str(), &info) == 0 && S_ISREG(info.st_mode));\n#endif\n}\n\n/**\n * Removes a file from the specified path.\n * @param path Full path to file.\n * @return True if the operation succeeded, False otherwise.\n */\nbool deleteFile(const std::string &path)\n{\n#ifdef _WIN32\n\tauto pathW = pathToWindows(path);\n\treturn (DeleteFileW(pathW.c_str()) != 0);\n#else\n\treturn (remove(path.c_str()) == 0);\n#endif\n}\n\n/**\n * Returns only the filename from a specified path.\n * @param path Full path.\n * @return Filename component.\n */\nstd::string baseFilename(const std::string &path)\n{\n\tsize_t sep = path.find_last_of('/');\n\tstd::string filename;\n\tif (sep == std::string::npos)\n\t{\n\t\tfilename = path;\n\t}\n\telse if (sep == path.size() - 1)\n\t{\n\t\treturn baseFilename(path.substr(0, path.size() - 1));\n\t}\n\telse\n\t{\n\t\tfilename = path.substr(sep + 1);\n\t}\n\treturn filename;\n}\n\n/**\n * Returns the directory from a specified path.\n * @param path Full path.\n * @return Directory component.\n */\nstd::string dirFilename(const std::string &path)\n{\n\tsize_t sep = path.find_last_of('/');\n\tstd::string filename;\n\tif (sep == std::string::npos)\n\t{\n\t\tfilename = \"\";\n\t}\n\telse if (sep == path.size() - 1)\n\t{\n\t\treturn dirFilename(path.substr(0, path.size() - 1));\n\t}\n\telse\n\t{\n\t\tfilename = path.substr(0, sep + 1);\n\t}\n\treturn filename;\n}\n\n/**\n * Replaces invalid filesystem characters with _.\n * @param filename Original filename.\n * @return Filename without invalid characters.\n */\nstd::string sanitizeFilename(const std::string &filename)\n{\n\tstd::string newFilename = filename;\n\tfor (std::string::iterator i = newFilename.begin(); i != newFilename.end(); ++i)\n\t{\n\t\tif ((*i) == '<' ||\n\t\t\t(*i) == '>' ||\n\t\t\t(*i) == ':' ||\n\t\t\t(*i) == '*' ||\n\t\t\t(*i) == '|' ||\n\t\t\t(*i) == '\"' ||\n\t\t\t(*i) == '\\'' ||\n\t\t\t(*i) == '/' ||\n\t\t\t(*i) == '?'||\n\t\t\t(*i) == '\\0'||\n\t\t\t(*i) == '\\\\')\n\t\t{\n\t\t\t*i = '_';\n\t\t}\n\t}\n\treturn newFilename;\n}\n\n/**\n * Removes the extension from a filename. Only the\n * last dot is considered.\n * @param filename Original filename.\n * @return Filename without the extension.\n */\nstd::string noExt(const std::string &filename)\n{\n\tsize_t dot = filename.find_last_of('.');\n\tif (dot == std::string::npos)\n\t{\n\t\treturn filename;\n\t}\n\treturn filename.substr(0, dot);\n}\n\n/**\n * Returns the extension from a filename. Only the\n * last dot is considered.\n * @param filename Original filename.\n * @return Extension component, includes dot.\n */\nstd::string getExt(const std::string &filename)\n{\n\tsize_t dot = filename.find_last_of('.');\n\tif (dot == std::string::npos)\n\t{\n\t\treturn \"\";\n\t}\n\treturn filename.substr(dot);\n}\n\n/**\n * Compares the extension in a filename (case-insensitive).\n * @param filename Filename to compare.\n * @param extension Extension to compare to.\n * @return If the extensions match.\n */\nbool compareExt(const std::string &filename, const std::string &extension)\n{\n\tif (extension.empty())\n\t\treturn true;\n\tint j = filename.length() - extension.length();\n\tif (j <= 0)\n\t\treturn false;\n\tif (filename[j - 1] != '.')\n\t\treturn false;\n\tfor (size_t i = 0; i < extension.length(); ++i)\n\t{\n\t\tif (::tolower(filename[j + i]) != ::tolower(extension[i]))\n\t\t\treturn false;\n\t}\n\treturn true;\n}\n\n/**\n * Gets the current locale of the system in language-COUNTRY format.\n * @return Locale string.\n */\nstd::string getLocale()\n{\n#ifdef _WIN32\n\tchar language[9], country[9];\n\n\tGetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SISO639LANGNAME, language, 9);\n\tGetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SISO3166CTRYNAME, country, 9);\n\n\tstd::ostringstream locale;\n\tlocale << language << \"-\" << country;\n\treturn locale.str();\n#else\n\tstd::locale l;\n\ttry\n\t{\n\t\tl = std::locale(\"\");\n\t}\n\tcatch (const std::runtime_error &)\n\t{\n\t\treturn \"x-\";\n\t}\n\tstd::string name = l.name();\n\tsize_t dash = name.find_first_of('_'), dot = name.find_first_of('.');\n\tif (dot != std::string::npos)\n\t{\n\t\tname = name.substr(0, dot - 1);\n\t}\n\tif (dash != std::string::npos)\n\t{\n\t\tstd::string language = name.substr(0, dash - 1);\n\t\tstd::string country = name.substr(dash - 1);\n\t\tstd::ostringstream locale;\n\t\tlocale << language << \"-\" << country;\n\t\treturn locale.str();\n\t}\n\telse\n\t{\n\t\treturn name + \"-\";\n\t}\n#endif\n}\n\n/**\n * Checks if the system's default quit shortcut was pressed.\n * @param ev SDL event.\n * @return Is quitting necessary?\n */\nbool isQuitShortcut(const SDL_Event &ev)\n{\n#ifdef _WIN32\n\t// Alt + F4\n\treturn (ev.type == SDL_KEYDOWN && ev.key.keysym.sym == SDLK_F4 && ev.key.keysym.mod & KMOD_ALT);\n#elif __APPLE__\n\t// Command + Q\n\treturn (ev.type == SDL_KEYDOWN && ev.key.keysym.sym == SDLK_q && ev.key.keysym.mod & KMOD_LMETA);\n#else\n\t//TODO add other OSs shortcuts.\n    (void)ev;\n\treturn false;\n#endif\n}\n/**\n * Gets the last modified date of a file.\n * @param path Full path to file.\n * @return The timestamp in integral format.\n */\ntime_t getDateModified(const std::string &path)\n{\n#ifdef _WIN32\n\ttime_t rv = 0;\n\tauto pathW = pathToWindows(path);\n\tauto fh = CreateFileW(pathW.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);\n\tif (fh == INVALID_HANDLE_VALUE) {\n\t\treturn 0;\n\t}\n\tFILETIME ftCreate, ftAccess, ftWrite;\n\tif (GetFileTime(fh, &ftCreate, &ftAccess, &ftWrite)) {\n\t\trv = FILETIME2mtime(ftWrite);\n\t}\n\tCloseHandle(fh);\n\treturn rv;\n#else\n\tstruct stat info;\n\tif (stat(path.c_str(), &info) == 0)\n\t{\n\t\treturn info.st_mtime;\n\t}\n\telse\n\t{\n\t\treturn 0;\n\t}\n#endif\n}\n\n/**\n * Converts a date/time into a human-readable string\n * using the ISO 8601 standard.\n * @param time Value in timestamp format.\n * @return String pair with date and time.\n */\nstd::pair<std::string, std::string> timeToString(time_t time)\n{\n\tchar localDate[25], localTime[25];\n\n/*#ifdef _WIN32\n\tLARGE_INTEGER li;\n\tli.QuadPart = time;\n\tFILETIME ft;\n\tft.dwHighDateTime = li.HighPart;\n\tft.dwLowDateTime = li.LowPart;\n\tSYSTEMTIME st;\n\tFileTimeToLocalFileTime(&ft, &ft);\n\tFileTimeToSystemTime(&ft, &st);\n\n\tGetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, localDate, 25);\n\tGetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, localTime, 25);\n#endif*/\n\n\tstruct tm *timeinfo = localtime(&(time));\n\tstrftime(localDate, 25, \"%Y-%m-%d\", timeinfo);\n\tstrftime(localTime, 25, \"%H:%M\", timeinfo);\n\n\treturn std::make_pair(localDate, localTime);\n}\n\n/**\n * Moves a file from one path to another,\n * replacing any existing file.\n * @param src Source path.\n * @param dest Destination path.\n * @return True if the operation succeeded, False otherwise.\n */\nbool moveFile(const std::string &src, const std::string &dest)\n{\n#ifdef _WIN32\n\tauto srcW = pathToWindows(src);\n\tauto dstW = pathToWindows(dest);\n\treturn (MoveFileExW(srcW.c_str(), dstW.c_str(), MOVEFILE_REPLACE_EXISTING) != 0);\n#else\n\t// TODO In fact all remaining uses of this are renaming files inside a single directory\n\t// so we may as well uncomment the rename() and drop the rest.\n\t//return (rename(src.c_str(), dest.c_str()) == 0);\n\tstd::ifstream srcStream;\n\tstd::ofstream destStream;\n\tsrcStream.exceptions(std::ifstream::failbit | std::ifstream::badbit);\n\tdestStream.exceptions(std::ofstream::failbit | std::ofstream::badbit);\n\ttry\n\t{\n\t\tsrcStream.open(src.c_str(), std::ios::binary);\n\t\tdestStream.open(dest.c_str(), std::ios::binary);\n\t\tdestStream << srcStream.rdbuf();\n\t\tsrcStream.close();\n\t\tdestStream.close();\n\t}\n\tcatch (const std::fstream::failure &)\n\t{\n\t\treturn false;\n\t}\n\treturn deleteFile(src);\n#endif\n}\n\n/**\n * Copies a file from one path to another,\n * replacing any existing file.\n * @param src Source path.\n * @param dest Destination path.\n * @return True if the operation succeeded, False otherwise.\n */\nbool copyFile(const std::string& src, const std::string& dest)\n{\n#ifdef _WIN32\n\tauto srcW = pathToWindows(src);\n\tauto dstW = pathToWindows(dest);\n\treturn (CopyFileW(srcW.c_str(), dstW.c_str(), false) != 0);\n#endif\n\treturn false;\n}\n\n/**\n * Writes a file.\n * @param filename - where to writeFile\n * @param data - what to writeFile\n * @return if we did write it.\n */\nbool writeFile(const std::string& filename, const std::string& data) {\n\t// Even SDL1 file IO accepts UTF-8 file names on windows.\n\tSDL_RWops *rwops = SDL_RWFromFile(filename.c_str(), \"w\");\n\tif (!rwops) {\n\t\tLog(LOG_ERROR) << \"Failed to write \" << filename << \": \" << SDL_GetError();\n\t\treturn false;\n\t}\n\tif (1 != SDL_RWwrite(rwops, data.c_str(), data.size(), 1)) {\n\t\tLog(LOG_ERROR) << \"Failed to write \" << filename << \": \" << SDL_GetError();\n\t\tSDL_RWclose(rwops);\n\t\treturn false;\n\t}\n\tSDL_RWclose(rwops);\n\treturn true;\n}\n\n/**\n * Writes a file.\n * @param filename - where to writeFile\n * @param data - what to writeFile\n * @return if we did write it.\n */\nbool writeFile(const std::string& filename, const std::vector<unsigned char>& data) {\n\t// Even SDL1 file IO accepts UTF-8 file names on windows.\n\tSDL_RWops *rwops = SDL_RWFromFile(filename.c_str(), \"wb\");\n\tif (!rwops) {\n\t\tLog(LOG_ERROR) << \"Failed to write \" << filename << \": \" << SDL_GetError();\n\t\treturn false;\n\t}\n\tif (1 != SDL_RWwrite(rwops, data.data(), data.size(), 1)) {\n\t\tLog(LOG_ERROR) << \"Failed to write \" << filename << \": \" << SDL_GetError();\n\t\tSDL_RWclose(rwops);\n\t\treturn false;\n\t}\n\tSDL_RWclose(rwops);\n\treturn true;\n}\n\n/**\n * Fully reads a file and returns a stream\n * @param filename - what to readFile\n * @return the istream\n */\nstd::unique_ptr<std::istream> readFile(const std::string& filename)\n{\n\treturn std::unique_ptr<std::istream>(new StreamData(readFileRaw(filename)));\n}\n\n/**\n * Fully reads a file and returns a pointer to the data\n * @param filename - what to readFile\n * @param pSize - returned data size\n * @return pointer to file data\n */\nRawData readFileRaw(const std::string& filename)\n{\n\tSDL_RWops* rwops = SDL_RWFromFile(filename.c_str(), \"r\");\n\tif (!rwops)\n\t{\n\t\tstd::string err = \"Failed to read \" + filename + \": \" + SDL_GetError();\n\t\tLog(LOG_ERROR) << err;\n\t\tthrow Exception(err);\n\t}\n\tsize_t s;\n\tchar* data = (char*)SDL_LoadFile_RW(rwops, &s, SDL_TRUE);\n\tif (data == NULL)\n\t{\n\t\tstd::string err = \"Failed to read \" + filename + \": \" + SDL_GetError();\n\t\tLog(LOG_ERROR) << err;\n\t\tthrow Exception(err);\n\t}\n\treturn RawData(data, s, SDL_free);\n}\n\n/**\n * Gets an istream to a file's bytes at least up to and including first \"\\n---\" sequence.\n * To be used only for savegames.\n * @param filename - what to read\n * @return the istream\n */\nstd::unique_ptr<std::istream> getYamlSaveHeader(const std::string& filename)\n{\n\treturn std::unique_ptr<std::istream>(new StreamData(getYamlSaveHeaderRaw(filename)));\n}\n\n/**\n * Reads a file up to and including first \"\\n---\" sequence.\n * To be used only for savegames.\n * @param filename - what to read\n * @param pSize - returned data size\n * @return pointer to file data\n */\nRawData getYamlSaveHeaderRaw(const std::string& filename)\n{\n\tSDL_RWops* rwops = SDL_RWFromFile(filename.c_str(), \"r\");\n\tif (!rwops)\n\t{\n\t\tstd::string err = \"Failed to read \" + filename + \": \" + SDL_GetError();\n\t\tLog(LOG_ERROR) << err;\n\t\tthrow Exception(err);\n\t}\n\tconst size_t chunksize = 4096;\n\tsize_t size = 0;\n\tsize_t offs = 0;\n\tchar* data = (char*)SDL_malloc(chunksize + 1);\n\tif (data == NULL)\n\t{\n\t\tstd::string err(SDL_GetError());\n\t\tLog(LOG_ERROR) << err;\n\t\tthrow Exception(err);\n\t}\n\twhile (true)\n\t{\n\t\tauto actually_read = SDL_RWread(rwops, data + offs, 1, chunksize);\n\t\tif (actually_read == 0 || actually_read == -1)\n\t\t{\n\t\t\tbreak;\n\t\t}\n\t\tsize += actually_read;\n\t\tdata[size] = 0;\n\t\tsize_t search_from = offs > 4 ? offs - 4 : 0;\n\t\tif (NULL != strstr(data + search_from, \"\\n---\"))\n\t\t{\n\t\t\tbreak;\n\t\t}\n\t\tchar* newdata = (char*)SDL_realloc(data, size + chunksize + 1);\n\t\tif (newdata == NULL)\n\t\t{\n\t\t\tstd::string err(SDL_GetError());\n\t\t\tLog(LOG_ERROR) << err;\n\t\t\tthrow Exception(err);\n\t\t}\n\t\tdata = newdata;\n\t\toffs = size;\n\t}\n\tSDL_RWclose(rwops);\n\treturn RawData(data, size, SDL_free);\n}\n\n/**\n * Notifies the user that maybe he should have a look.\n */\nvoid flashWindow()\n{\n#ifdef _WIN32\n\tSDL_SysWMinfo wminfo;\n\tSDL_VERSION(&wminfo.version)\n\tif (SDL_GetWMInfo(&wminfo))\n\t{\n\t\tHWND hwnd = wminfo.window;\n\t\tFlashWindow(hwnd, true);\n\t}\n#endif\n}\n\n/**\n * Gets the executable path in DOS-style (short) form.\n * For non-Windows systems, just use a dummy path.\n * @return Executable path.\n */\nstd::string getDosPath()\n{\n#ifdef _WIN32\n\tstd::string path, bufstr;\n\tchar buf[MAX_PATH];\n\tif (GetModuleFileNameA(0, buf, MAX_PATH) != 0)\n\t{\n\t\tbufstr = buf;\n\t\tsize_t c1 = bufstr.find_first_of('\\\\');\n\t\tpath += bufstr.substr(0, c1+1);\n\t\tsize_t c2 = bufstr.find_first_of('\\\\', c1+1);\n\t\twhile (c2 != std::string::npos)\n\t\t{\n\t\t\tstd::string dirname = bufstr.substr(c1+1, c2-c1-1);\n\t\t\tif (dirname == \"..\")\n\t\t\t{\n\t\t\t\tpath = path.substr(0, path.find_last_of('\\\\', path.length()-2));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (dirname.length() > 8)\n\t\t\t\t\tdirname = dirname.substr(0, 6) + \"~1\";\n\t\t\t\tstd::transform(dirname.begin(), dirname.end(), dirname.begin(), toupper);\n\t\t\t\tpath += dirname;\n\t\t\t}\n\t\t\tc1 = c2;\n\t\t\tc2 = bufstr.find_first_of('\\\\', c1+1);\n\t\t\tif (c2 != std::string::npos)\n\t\t\t\tpath += '\\\\';\n\t\t}\n\t}\n\telse\n\t{\n\t\tpath = \"C:\\\\GAMES\\\\OPENXCOM\";\n\t}\n\treturn path;\n#else\n\treturn \"C:\\\\GAMES\\\\OPENXCOM\";\n#endif\n}\n\n/**\n * Sets the window titlebar icon.\n * For Windows, use the embedded resource icon.\n * For other systems, use a PNG icon.\n * @param winResource ID for Windows icon.\n * @param unixPath Path to PNG icon for Unix.\n */\n#ifdef _WIN32\nvoid setWindowIcon(int winResource, const std::string &)\n{\n\tHINSTANCE handle = GetModuleHandle(NULL);\n\tHICON icon = LoadIcon(handle, MAKEINTRESOURCE(winResource));\n\n\tSDL_SysWMinfo wminfo;\n\tSDL_VERSION(&wminfo.version)\n\tif (SDL_GetWMInfo(&wminfo))\n\t{\n\t\tHWND hwnd = wminfo.window;\n\t\tSetClassLongPtr(hwnd, GCLP_HICON, (LONG_PTR)icon);\n\t}\n}\n#else\nvoid setWindowIcon(int, const std::string &unixPath)\n{\n\tSDL_Surface *icon = IMG_Load_RW(FileMap::getRWops(unixPath), SDL_TRUE);\n\tif (icon != 0)\n\t{\n\t\tSDL_WM_SetIcon(icon, NULL);\n\t\tSDL_FreeSurface(icon);\n\t}\n}\n#endif\n\n/**\n * Logs the stack back trace leading up to this function call.\n * @param ctx Pointer to stack context (PCONTEXT on Windows), NULL to use current context.\n */\nvoid stackTrace(void *ctx)\n{\n#ifdef _WIN32\n# ifndef __NO_DBGHELP\n\tconst int MAX_SYMBOL_LENGTH = 1024;\n\tCONTEXT context;\n\tif (ctx != 0)\n\t{\n\t\tcontext = *((PCONTEXT)ctx);\n\t}\n\telse\n\t{\n#  ifdef _M_IX86\n\t\tmemset(&context, 0, sizeof(CONTEXT));\n\t\tcontext.ContextFlags = CONTEXT_CONTROL;\n#   ifdef __MINGW32__\n\t\tasm(\"Label:\\n\\t\"\n\t\t\t\"movl %%ebp,%0;\\n\\t\"\n\t\t\t\"movl %%esp,%1;\\n\\t\"\n\t\t\t\"movl $Label,%%eax;\\n\\t\"\n\t\t\t\"movl %%eax,%2;\\n\\t\"\n\t\t\t: \"=r\" (context.Ebp), \"=r\" (context.Esp), \"=r\" (context.Eip)\n\t\t\t: //no input\n\t\t\t: \"eax\");\n#   else\n\t\t_asm {\n\t\tLabel:\n\t\t\tmov[context.Ebp], ebp;\n\t\t\tmov[context.Esp], esp;\n\t\t\tmov eax, [Label];\n\t\t\tmov[context.Eip], eax;\n\t\t}\n#   endif\n#  else /* no  _M_IX86 */\n\t\tRtlCaptureContext(&context);\n#  endif\n\t}\n\tHANDLE thread = GetCurrentThread();\n\tHANDLE process = GetCurrentProcess();\n\tSTACKFRAME64 frame;\n\tmemset(&frame, 0, sizeof(STACKFRAME64));\n\tDWORD image;\n#  ifdef _M_IX86\n\timage = IMAGE_FILE_MACHINE_I386;\n\tframe.AddrPC.Offset = context.Eip;\n\tframe.AddrPC.Mode = AddrModeFlat;\n\tframe.AddrFrame.Offset = context.Ebp;\n\tframe.AddrFrame.Mode = AddrModeFlat;\n\tframe.AddrStack.Offset = context.Esp;\n\tframe.AddrStack.Mode = AddrModeFlat;\n#  elif _M_X64\n\timage = IMAGE_FILE_MACHINE_AMD64;\n\tframe.AddrPC.Offset = context.Rip;\n\tframe.AddrPC.Mode = AddrModeFlat;\n\tframe.AddrFrame.Offset = context.Rbp;\n\tframe.AddrFrame.Mode = AddrModeFlat;\n\tframe.AddrStack.Offset = context.Rsp;\n\tframe.AddrStack.Mode = AddrModeFlat;\n#  elif _M_IA64\n\timage = IMAGE_FILE_MACHINE_IA64;\n\tframe.AddrPC.Offset = context.StIIP;\n\tframe.AddrPC.Mode = AddrModeFlat;\n\tframe.AddrFrame.Offset = context.IntSp;\n\tframe.AddrFrame.Mode = AddrModeFlat;\n\tframe.AddrBStore.Offset = context.RsBSP;\n\tframe.AddrBStore.Mode = AddrModeFlat;\n\tframe.AddrStack.Offset = context.IntSp;\n\tframe.AddrStack.Mode = AddrModeFlat;\n#  else\n\tLog(LOG_FATAL) << \"Unfortunately, no stack trace information is available\";\n\treturn;\n#  endif\n\tSYMBOL_INFO *symbol = (SYMBOL_INFO *)malloc(sizeof(SYMBOL_INFO) + (MAX_SYMBOL_LENGTH - 1) * sizeof(TCHAR));\n\tsymbol->MaxNameLen = MAX_SYMBOL_LENGTH;\n\tsymbol->SizeOfStruct = sizeof(SYMBOL_INFO);\n\tIMAGEHLP_LINE64 *line = (IMAGEHLP_LINE64 *)malloc(sizeof(IMAGEHLP_LINE64));\n\tline->SizeOfStruct = sizeof(IMAGEHLP_LINE64);\n\tDWORD displacement;\n\tSymInitialize(process, NULL, TRUE);\n\twhile (StackWalk64(image, process, thread, &frame, &context, NULL, NULL, NULL, NULL))\n\t{\n\t\tif (SymFromAddr(process, frame.AddrPC.Offset, NULL, symbol))\n\t\t{\n\t\t\tstd::string symname = symbol->Name;\n#  ifdef __MINGW32__\n\t\t\tsymname = \"_\" + symname;\n\t\t\tint status = 0;\n\t\t\tsize_t outSz = 0;\n\t\t\tchar* demangled = abi::__cxa_demangle(symname.c_str(), 0, &outSz, &status);\n\t\t\tif (status == 0)\n\t\t\t{\n\t\t\t\tsymname = demangled;\n\t\t\t\tif (outSz > 0)\n\t\t\t\t\tfree(demangled);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tsymname = symbol->Name;\n\t\t\t}\n#  endif\n\t\t\tif (SymGetLineFromAddr64(process, frame.AddrPC.Offset, &displacement, line))\n\t\t\t{\n\t\t\t\tstd::string filename = line->FileName;\n\t\t\t\tsize_t n = filename.find_last_of('\\\\');\n\t\t\t\tif (n != std::string::npos)\n\t\t\t\t{\n\t\t\t\t\tfilename = filename.substr(n + 1);\n\t\t\t\t}\n\t\t\t\tLog(LOG_FATAL) << \"0x\" << std::hex << symbol->Address << std::dec << \" \" << symname << \" (\" << filename << \":\" << line->LineNumber << \")\";\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tLog(LOG_FATAL) << \"0x\" << std::hex << symbol->Address << std::dec << \" \" << symname;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tLog(LOG_FATAL) << \"??\";\n\t\t}\n\t}\n\tDWORD err = GetLastError();\n\tif (err)\n\t{\n\t\tLog(LOG_FATAL) << \"Unfortunately, no stack trace information is available\";\n\t}\n\tSymCleanup(process);\n# else /* __NO_DBGHELP */\n\tLog(LOG_FATAL) << \"Unfortunately, no stack trace information is available\";\n# endif\n#elif __CYGWIN__\n\tLog(LOG_FATAL) << \"Unfortunately, no stack trace information is available\";\n#else    /* not _WIN32 or __CYGWIN__ */\n\tvoid *frames[32];\n\tchar buf[1024];\n\tint  frame_count = backtrace(frames, 32);\n\tchar *demangled = NULL;\n\tconst char *mangled = NULL;\n\tint status;\n\tsize_t sym_offset;\n\n\tfor (int i = 0; i < frame_count; i++) {\n\t\tDl_info dl_info;\n\t\tif (dladdr(frames[i], &dl_info )) {\n\t\t\tdemangled = NULL;\n\t\t\tmangled = dl_info.dli_sname;\n\t\t\tif ( mangled != NULL) {\n\t\t\t\tsym_offset = (char *)frames[i] - (char *)dl_info.dli_saddr;\n\t\t\t\tdemangled = abi::__cxa_demangle( dl_info.dli_sname, NULL, 0, &status);\n\t\t\t\tsnprintf(buf, sizeof(buf), \"%s(%s+0x%zx) [%p]\",\n\t\t\t\t\t\tdl_info.dli_fname,\n\t\t\t\t\t\tstatus == 0 ? demangled : mangled,\n\t\t\t\t\t\tsym_offset, frames[i] );\n\t\t\t} else { // symbol not found\n\t\t\t\tsym_offset = (char *)frames[i] - (char *)dl_info.dli_fbase;\n\t\t\t\tsnprintf(buf, sizeof(buf), \"%s(+0x%zx) [%p]\", dl_info.dli_fname, sym_offset, frames[i]);\n\t\t\t}\n\t\t\tfree(demangled);\n\t\t\tLog(LOG_FATAL) << buf;\n\t\t} else { // object not found\n\t\t\tsnprintf(buf, sizeof(buf), \"? ? [%p]\", frames[i]);\n\t\t\tLog(LOG_FATAL) << buf;\n\t\t}\n\t}\n#endif\n\tctx = (void*)ctx;\n}\n\n/**\n * Generates a timestamp of the current time.\n * @return String in D-M-Y_H-M-S format.\n */\nstd::string now()\n{\n\tconst int MAX_LEN = 25, MAX_RESULT = 80;\n\tchar result[MAX_RESULT] = { 0 };\n#ifdef _WIN32\n\tchar date[MAX_LEN], time[MAX_LEN];\n\tif (GetDateFormatA(LOCALE_INVARIANT, 0, 0, \"dd'-'MM'-'yyyy\", date, MAX_LEN) == 0)\n\t\treturn \"00-00-0000\";\n\tif (GetTimeFormatA(LOCALE_INVARIANT, TIME_FORCE24HOURFORMAT, 0, \"HH'-'mm'-'ss\", time, MAX_LEN) == 0)\n\t\treturn \"00-00-00\";\n\tsprintf(result, \"%s_%s\", date, time);\n#else\n\tchar buffer[MAX_LEN];\n\ttime_t rawtime;\n\tstruct tm *timeinfo;\n\ttime(&rawtime);\n\ttimeinfo = localtime(&rawtime);\n\tstrftime(buffer, MAX_LEN, \"%d-%m-%Y_%H-%M-%S\", timeinfo);\n\tsprintf(result, \"%s\", buffer);\n#endif\n\treturn result;\n}\n\n/**\n * Logs the details of this crash and shows an error.\n * @param ex Pointer to exception data (PEXCEPTION_POINTERS on Windows, signal int on Unix)\n * @param err Exception message, if any.\n */\nvoid crashDump(void *ex, const std::string &err)\n{\n\tstd::ostringstream error;\n#ifdef _MSC_VER\n\tPEXCEPTION_POINTERS exception = (PEXCEPTION_POINTERS)ex;\n\tstd::exception *cppException = 0;\n\tswitch (exception->ExceptionRecord->ExceptionCode)\n\t{\n\tcase EXCEPTION_CODE_CXX:\n\t\tcppException = (std::exception *)exception->ExceptionRecord->ExceptionInformation[1];\n\t\terror << cppException->what();\n\t\tbreak;\n\tcase EXCEPTION_ACCESS_VIOLATION:\n\t\terror << \"Memory access violation.\";\n\t\tbreak;\n\tdefault:\n\t\terror << \"code 0x\" << std::hex << exception->ExceptionRecord->ExceptionCode;\n\t\tbreak;\n\t}\n\tLog(LOG_FATAL) << \"A fatal error has occurred: \" << error.str();\n\tif (ex)\n\t{\n\t\tstackTrace(exception->ContextRecord);\n\t}\n\tstd::string dumpName = Options::getUserFolder();\n\tdumpName += now() + \".dmp\";\n\tHANDLE dumpFile = CreateFileA(dumpName.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);\n\tMINIDUMP_EXCEPTION_INFORMATION exceptionInformation;\n\texceptionInformation.ThreadId = GetCurrentThreadId();\n\texceptionInformation.ExceptionPointers = exception;\n\texceptionInformation.ClientPointers = FALSE;\n\tif (MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), dumpFile, MiniDumpNormal, exception ? &exceptionInformation : NULL, NULL, NULL))\n\t{\n\t\tLog(LOG_FATAL) << \"Crash dump generated at \" << dumpName;\n\t}\n\telse\n\t{\n\t\tLog(LOG_FATAL) << \"No crash dump generated: \" << GetLastError();\n\t}\n#else\n\tif (ex == 0)\n\t{\n\t\terror << err;\n\t}\n\telse\n\t{\n\t\tint signal = *((int*)ex);\n\t\tswitch (signal)\n\t\t{\n\t\tcase SIGSEGV:\n\t\t\terror << \"Segmentation fault.\";\n\t\t\tbreak;\n\t\tdefault:\n\t\t\terror << \"signal \" << signal;\n\t\t\tbreak;\n\t\t}\n\t}\n\tLog(LOG_FATAL) << \"A fatal error has occurred: \" << error.str();\n\tstackTrace(0);\n#endif\n\tstd::ostringstream msg;\n\tmsg << \"OpenXcom has crashed: \" << error.str() << std::endl;\n\tmsg << \"Log file: \" << getLogFileName() << std::endl;\n\tmsg << \"If this error was unexpected, please report it on the OpenXcom forum (OXCE board).\" << std::endl;\n\tmsg << \"The following can help us solve the problem:\" << std::endl;\n\tmsg << \"1. a saved game from just before the crash (helps 98%)\" << std::endl;\n\tmsg << \"2. a detailed description how to reproduce the crash (helps 80%)\" << std::endl;\n\tmsg << \"3. a log file (helps 10%)\" << std::endl;\n\tmsg << \"4. a screenshot of this error message (helps 5%)\";\n\tshowError(msg.str());\n}\n\n/**\n * Opens a file or web path in the system default browser.\n */\nbool openExplorer(const std::string &url)\n{\n#ifdef _WIN32\n\tHINSTANCE ret = ShellExecuteW(NULL, L\"open\", Unicode::convMbToWc(url, CP_UTF8).c_str(), NULL, NULL, SW_SHOWNORMAL);\n\t// The return value is not a true HINSTANCE. If the function succeeds, it returns a value greater than 32.\n\treturn (static_cast<int>(reinterpret_cast<uintptr_t>(ret)) > 32);\n#elif __MOBILE__\n\treturn false;\n#elif __APPLE__\n\tstd::string cmd = \"open \\\"\" + url + \"\\\"\";\n\treturn (system(cmd.c_str()) == 0);\n#else\n\tstd::string cmd = \"xdg-open \\\"\" + url + \"\\\"\";\n\treturn (system(cmd.c_str()) == 0);\n#endif\n}\n\n\n/**\n * Appends a file, logs nothing to avoid recursion.\n * @param filename - where to writeFile\n * @param data - what to writeFile\n * @return if we did write it.\n */\nstatic bool logToFile(const std::string& filename, const std::string& data) {\n\t// Even SDL1 file IO accepts UTF-8 file names on windows.\n\tSDL_RWops *rwops = SDL_RWFromFile(filename.c_str(), \"a+\");\n\tif (rwops) {\n\t\tauto rv = SDL_RWwrite(rwops, data.c_str(), data.size(), 1);\n\t\tSDL_RWclose(rwops);\n\t\treturn rv == 1;\n\t}\n\treturn false;\n}\n\nstatic const size_t LOG_BUFFER_LIMIT = 1<<10;\nstatic std::list<std::pair<int, std::string>> logBuffer;\nstatic std::string logFileName;\nconst std::string& getLogFileName() { return logFileName; }\n\n/**\n * Setting the log file name and setting the effective reportingLevel\n * to not LOG_UNCENSORED turns off buffering of the log messages,\n * and turns on writing them to the actual log (and flushes the buffer).\n */\nvoid setLogFileName(const std::string& name) {\n\tdeleteFile(name);\n\tsize_t sz = logBuffer.size();\n\tLog(LOG_DEBUG) << \"setLogFileName(\"<<name<<\") was '\"<<logFileName<<\"'; \"<<sz<<\" in buffer\";\n\tlogFileName = name;\n}\nvoid log(int level, const std::ostringstream& baremsgstream) {\n\tstd::ostringstream msgstream;\n\tmsgstream << \"[\" << CrossPlatform::now() << \"]\" << \"\\t\"\n\t\t\t  << \"[\" << Logger::toString(level) << \"]\" << \"\\t\"\n\t\t\t  << baremsgstream.str() << std::endl;\n\tauto msg = msgstream.str();\n\n\tint effectiveLevel = Logger::reportingLevel();\n\tif (effectiveLevel >= LOG_DEBUG) {\n\t\tfwrite(msg.c_str(), msg.size(), 1, stderr);\n\t\tfflush(stderr);\n\t}\n\tif (logBuffer.size() > LOG_BUFFER_LIMIT) { // drop earliest message so as to not eat all memory\n\t\tlogBuffer.pop_front();\n\t}\n\tif (logFileName.empty() || effectiveLevel == LOG_UNCENSORED) { // no log file; accumulate.\n\t\tlogBuffer.push_back(std::make_pair(level, msg));\n\t\treturn;\n\t}\n\t// attempt to flush the buffer\n\tbool failed = false;\n\twhile (!logBuffer.empty()) {\n\t\tif (effectiveLevel >= logBuffer.front().first) {\n\t\t\tif (!logToFile(logFileName, logBuffer.front().second)) {\n\t\t\t\tstd::string err = \"Failed to append to '\" + logFileName + \"': \" + SDL_GetError();\n\t\t\t\tlogBuffer.push_back(std::make_pair(LOG_ERROR, err));\n\t\t\t\tfailed = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tlogBuffer.pop_front();\n\t}\n\t// retain the current message if write fails.\n\tif (failed || !logToFile(logFileName, msg)) {\n\t\tlogBuffer.push_back(std::make_pair(level, msg));\n\t}\n}\n\n#if defined(EMBED_ASSETS)\n# if defined(_WIN32)\n# include \"../resource.h\"\nstatic void *CommonZipAssetPtr = 0;\nstatic size_t CommonZipAssetSize = 0;\nstatic void *StandardZipAssetPtr = 0;\nstatic size_t StandardZipAssetSize = 0;\nstatic void *getWindowsResource(int res_id, size_t *size) {\n    HMODULE handle = GetModuleHandle(NULL);\n    HRSRC rc = FindResource(handle, MAKEINTRESOURCE(res_id), MAKEINTRESOURCE(10));\n\tif (!rc) { return NULL; }\n    HGLOBAL rcData = LoadResource(handle, rc);\n\tif (!rcData) { return NULL; }\n    *size = SizeofResource(handle, rc);\n    return LockResource(rcData);\n}\n# elif defined(__MOBILE__)\n/* This space is intentionally left blank */\n# else\nextern \"C\" {\n\textern uint8_t common_zip[];\n\textern int common_zip_size;\n\textern uint8_t standard_zip[];\n\textern int standard_zip_size;\n}\n# endif\n#endif\nSDL_RWops *getEmbeddedAsset(const std::string& assetName) {\n\tstd::string log_ctx = \"getEmbeddedAsset('\" + assetName + \"'): \";\n\tif (assetName.size() == 0 || assetName[0] == '/') {\n\t\tLog(LOG_WARNING) << log_ctx << \"ignoring bogus asset name\";\n\t\treturn NULL;\n\t}\n#if defined(EMBED_ASSETS)\n\tSDL_RWops *rv = NULL;\n# if defined(_WIN32)\n\tif (assetName == \"common.zip\") {\n\t\tif (!CommonZipAssetPtr) {\n\t\t\tCommonZipAssetPtr = getWindowsResource(IDZ_COMMON_ZIP, &CommonZipAssetSize);\n\t\t}\n\t\tif (CommonZipAssetPtr) {\n\t\t\trv = SDL_RWFromConstMem(CommonZipAssetPtr, CommonZipAssetSize);\n\t\t}\n\t} else if (assetName == \"standard.zip\") {\n\t\tif (!StandardZipAssetPtr) {\n\t\t\tStandardZipAssetPtr = getWindowsResource(IDZ_STANDARD_ZIP, &StandardZipAssetSize);\n\t\t}\n\t\tif (StandardZipAssetPtr) {\n\t\t\trv = SDL_RWFromConstMem(StandardZipAssetPtr, StandardZipAssetSize);\n\t\t}\n\t}\n# elif defined(__MOBILE__)\n\trv = SDL_RWFromFile(assetName, \"rb\");\n# else\n\tif (assetName == \"common.zip\") {\n\t\trv = SDL_RWFromConstMem(common_zip, common_zip_size);\n\t} else if (assetName == \"standard.zip\") {\n\t\trv = SDL_RWFromConstMem(standard_zip, standard_zip_size);\n\t}\n# endif\n\tif (rv == NULL) {\n\t\tLog(LOG_ERROR) << log_ctx << \"embedded asset not found: \"<< SDL_GetError();\n\t}\n\treturn rv;\n#else\n\t/* Asset embedding disabled. */\n\tLog(LOG_VERBOSE) << log_ctx << \"assets were not embedded.\";\n\treturn NULL;\n#endif\n}\n\n/**\n * Tests the internet connection.\n * @param url URL to test.\n * @return True if the operation succeeded, False otherwise.\n */\nbool testInternetConnection(const std::string& url)\n{\n#ifdef _WIN32\n\tauto urlW = pathToWindows(url, false);\n\tbool bConnect = InternetCheckConnectionW(urlW.c_str(), FLAG_ICC_FORCE_CONNECTION, 0);\n\treturn bConnect;\n#else\n\treturn false;\n#endif\n}\n\n/**\n * Downloads a file from a given URL to the filesystem.\n * @param url Source URL.\n * @param filename Destination file name.\n * @return True if the operation succeeded, False otherwise.\n */\nbool downloadFile(const std::string& url, const std::string& filename)\n{\n#ifdef _WIN32\n\tauto urlW = pathToWindows(url, false);\n\tauto filenameW = pathToWindows(filename, true);\n\tDeleteUrlCacheEntryW(urlW.c_str());\n\tHRESULT hr = URLDownloadToFileW(NULL, urlW.c_str(), filenameW.c_str(), 0, NULL);\n\treturn SUCCEEDED(hr);\n#else\n\treturn false;\n#endif\n}\n\n/**\n * Parse string with version number.\n */\nstd::array<int, 4> parseVersion(const std::string& newVersion)\n{\n\tstd::array<int, 4> newOxceVersion = {};\n\n\tstd::string each;\n\tchar split_char = '.';\n\tstd::istringstream ss(newVersion);\n\tstd::size_t j = 0;\n\twhile (std::getline(ss, each, split_char)) {\n\t\tif (j == newOxceVersion.size())\n\t\t{\n\t\t\tbreak;\n\t\t}\n\n\t\ttry {\n\t\t\tint i = std::stoi(each);\n\t\t\tnewOxceVersion[j] = i;\n\t\t}\n\t\tcatch (...) {\n\n\t\t}\n\t\t++j;\n\t}\n\treturn newOxceVersion;\n}\n\n/**\n * Is the given version number higher than the current version number?\n * @param newVersion Version to compare.\n * @return True if given version is higher than current version.\n */\nbool isHigherThanCurrentVersion(const std::string& newVersion)\n{\n\treturn isHigherThanCurrentVersion(parseVersion(newVersion), { OPENXCOM_VERSION_NUMBER });\n}\n\n/**\n * Is the given version number higher than the given version number?\n * @param newVersion Version to compare.\n * @param ver Given available version.\n * @return True if given version is higher than given version.\n */\nbool isHigherThanCurrentVersion(const std::array<int, 4>& newOxceVersion, const int (&ver)[4])\n{\n\tbool isHigher = false;\n\n\tfor (size_t k = 0; k < std::size(ver); ++k)\n\t{\n\t\tif (newOxceVersion[k] > ver[k])\n\t\t{\n\t\t\tisHigher = true;\n\t\t\tbreak;\n\t\t}\n\t\telse if (newOxceVersion[k] < ver[k])\n\t\t{\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn isHigher;\n}\n\n/**\n * Is the given version number lower than the minimum required version number?\n * @param dataVersion Version to compare.\n * @return True if the given version number is lower than the minimum required version number.\n */\nbool isLowerThanRequiredVersion(const std::string& dataVersion)\n{\n\treturn isLowerThanRequiredVersion(parseVersion(dataVersion), { MIN_REQUIRED_RULESET_VERSION_NUMBER });\n}\n\n/**\n * Is the first version number lower than the second version number?\n * @param dataVersion Version to compare.\n * @param ver Minimum required version.\n * @return True if the first version number is lower than the second version number.\n */\nbool isLowerThanRequiredVersion(const std::array<int, 4>& dataVersion, const int(&ver)[4])\n{\n\tbool isLower = false;\n\n\tfor (size_t k = 0; k < std::size(ver); ++k)\n\t{\n\t\tif (dataVersion[k] < ver[k])\n\t\t{\n\t\t\tisLower = true;\n\t\t\tbreak;\n\t\t}\n\t\telse if (dataVersion[k] > ver[k])\n\t\t{\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn isLower;\n}\n\n/**\n * Gets the path to the executable file.\n * @return Path to the EXE file.\n */\nstd::string getExeFolder()\n{\n#ifdef _WIN32\n\twchar_t dest[MAX_PATH + 1];\n\tif (GetModuleFileNameW(NULL, dest, MAX_PATH) != 0)\n\t{\n\t\tPathRemoveFileSpecW(dest);\n\t\tauto ret = pathFromWindows(dest) + \"/\";\n\t\treturn ret;\n\t}\n#endif\n\treturn std::string();\n}\n\n/**\n * Gets the file name of the executable file.\n * @param includingPath Including full path or just the file name?\n * @return Name of the EXE file.\n */\nstd::string getExeFilename(bool includingPath)\n{\n#ifdef _WIN32\n\twchar_t dest[MAX_PATH + 1];\n\tif (GetModuleFileNameW(NULL, dest, MAX_PATH) != 0)\n\t{\n\t\tif (includingPath)\n\t\t{\n\t\t\tauto ret = pathFromWindows(dest);\n\t\t\treturn ret;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tauto filename = PathFindFileNameW(dest);\n\t\t\tauto ret = pathFromWindows(filename);\n\t\t\treturn ret;\n\t\t}\n\t}\n#endif\n\treturn std::string();\n}\n\n/**\n * Starts the update process.\n */\nvoid startUpdateProcess()\n{\n#ifdef _WIN32\n\tauto operationW = pathToWindows(\"open\", false);\n\tauto fileW = pathToWindows(\"oxce-upd.bat\", false);\n\tShellExecuteW(NULL, operationW.c_str(), fileW.c_str(), NULL, NULL, SW_SHOWNORMAL);\n#endif\n}\n\n\n\n#ifndef NDEBUG\n\nstatic auto dummy = ([]\n{\n\tauto create = [](int i, int j, int k, int l)\n\t{\n\t\treturn std::array<int, 4>{{i, j, k, l}};\n\t};\n\n\tassert(parseVersion(\"0.0.0.0\") == create(0, 0, 0, 0));\n\tassert(parseVersion(\"1.0.0.0\") == create(1, 0, 0, 0));\n\tassert(parseVersion(\"1.2.0.0\") == create(1, 2, 0, 0));\n\tassert(parseVersion(\"1.2.3.4\") == create(1, 2, 3, 4));\n\tassert(parseVersion(\"1.2.3.4.5\") == create(1, 2, 3, 4));\n\tassert(parseVersion(\"1.2.3\") == create(1, 2, 3, 0));\n\tassert(parseVersion(\"1.2\") == create(1, 2, 0, 0));\n\tassert(parseVersion(\"1.A.2\") == create(1, 0, 2, 0));\n\tassert(parseVersion(\".2\") == create(0, 2, 0, 0));\n\n\n\tassert(isHigherThanCurrentVersion(create(1, 2, 0, 0), {1, 1, 0, 0}));\n\tassert(isHigherThanCurrentVersion(create(1, 2, 1, 3), {1, 2, 0, 4}));\n\tassert(isHigherThanCurrentVersion(create(1, 2, 1, 3), {1, 2, 1, 2}));\n\tassert(!isHigherThanCurrentVersion(create(1, 2, 1, 3), {1, 2, 1, 3}));\n\tassert(!isHigherThanCurrentVersion(create(1, 2, 1, 3), {1, 2, 1, 4}));\n\tassert(!isHigherThanCurrentVersion(create(1, 2, 1, 3), {1, 2, 2, 2}));\n\tassert(!isHigherThanCurrentVersion(create(1, 2, 1, 3), {1, 3, 1, 2}));\n\n\treturn 0;\n})();\n\nstatic auto dummyPaths = ([]\n{\n\tassert(CrossPlatform::baseFilename(\"aaa/bbb/ccc\") == \"ccc\");\n\tassert(CrossPlatform::baseFilename(\"aaa/bbb/ccc/\") == \"ccc\");\n\tassert(CrossPlatform::baseFilename(\"aaa/bbb/ccc//\") == \"ccc\");\n\tassert(CrossPlatform::baseFilename(\"/ccc\") == \"ccc\");\n\tassert(CrossPlatform::baseFilename(\"ccc\") == \"ccc\");\n\n\tassert(CrossPlatform::dirFilename(\"aaa/bbb/ccc\") == \"aaa/bbb/\");\n\tassert(CrossPlatform::dirFilename(\"aaa/bbb/ccc/\") == \"aaa/bbb/\");\n\tassert(CrossPlatform::dirFilename(\"aaa/bbb/ccc//\") == \"aaa/bbb/\");\n\tassert(CrossPlatform::dirFilename(\"/ccc\") == \"/\");\n\tassert(CrossPlatform::dirFilename(\"ccc\") == \"\");\n\treturn 0;\n})();\n\nstatic auto dummyRawFile = ([]\n{\n\t{\n\t\tchar text[] = \"test\";\n\t\tStreamData raw(RawData{text, std::strlen(text), +[](void*){}});\n\n\t\tassert(raw.get() == 't');\n\t\tassert(raw.get() == 'e');\n\t\tassert(raw.get() == 's');\n\t\tassert(raw.get() == 't');\n\t\tassert(raw.get() == std::char_traits<char>::eof());\n\t}\n\n\t{\n\t\tchar text[] = \"test123\";\n\t\tStreamData raw(RawData{text, std::strlen(text), +[](void*){}});\n\n\t\tchar dummy1[10] = { };\n\t\tassert(raw.read(dummy1, 4) && std::strcmp(dummy1, \"test\") == 0);\n\n\t\tchar dummy2[10] = { };\n\t\tassert(raw.read(dummy2, 3) && std::strcmp(dummy2, \"123\") == 0);\n\n\t}\n\n\t{\n\t\tchar text[] = \"test123\";\n\t\tStreamData raw(RawData{text, std::strlen(text), +[](void*){}});\n\n\t\tchar dummy1[10] = { };\n\t\tassert(!raw.read(dummy1, 10) && std::strcmp(dummy1, \"test123\") == 0);\n\t}\n\n\t{\n\t\tchar text[] = \"test123\";\n\t\tStreamData raw(RawData{text, std::strlen(text), +[](void*){}});\n\n\t\traw.seekg(0, std::ios::end);\n\t\tstd::streamoff end = raw.tellg();\n\t\traw.seekg(0, std::ios::beg);\n\t\tstd::streamoff begin = raw.tellg();\n\n\t\tassert(end-begin == (int)std::strlen(text));\n\t}\n\n\t{\n\t\tchar text[] = \"test123\\0ErrorErrorErrorErrorErrorError\";\n\t\tStreamData raw(RawData{text, std::strlen(text), +[](void*){}});\n\n\t\tchar dummy1[11] = { };\n\n\t\traw.clear();\n\t\traw.seekg(std::strlen(text), std::ios::beg);\n\t\tassert(!!raw);\n\t\tassert(!raw.read(dummy1, 10));\n\n\t\traw.clear();\n\t\traw.seekg(20, std::ios::beg);\n\t\tassert(!raw);\n\t\tassert(!raw.read(dummy1, 10));\n\n\t\traw.clear();\n\t\traw.seekg(-5, std::ios::beg);\n\t\tassert(!raw);\n\t\tassert(!raw.read(dummy1, 10));\n\n\t\traw.clear();\n\t\traw.seekg(0, std::ios::beg);\n\t\tassert(!!raw);\n\t\tassert(raw.read(dummy1, 5));\n\t}\n\n\t{\n\t\tstatic int calledDelete = 0;\n\t\tchar text[] = \"test123\";\n\t\tStreamData raw(RawData{text, std::strlen(text), +[](void*){ ++calledDelete; }});\n\n\t\tassert(raw.get() == 't');\n\n\t\traw.extractRawData();\n\n\t\tassert(raw.get() == std::char_traits<char>::eof());\n\t\tassert(calledDelete == 1);\n\t}\n\n\t{\n\t\tstatic int calledDelete = 0;\n\t\tchar text[] = \"0123\";\n\t\tStreamData raw(RawData{text, std::strlen(text), +[](void*){ ++calledDelete; }});\n\n\n\t\tassert(raw.get() == '0');\n\n\t\tStreamData raw2 = std::move(raw);\n\n\t\tassert(raw.get() ==  std::char_traits<char>::eof());\n\t\tassert(!!raw2);\n\t\tassert(raw2.get() == '1');\n\n\t\traw = std::move(raw2);\n\n\t\tassert(raw.get() == '2');\n\t\tassert(raw2.get() == std::char_traits<char>::eof());\n\n\t\tassert(raw.get() == '3');\n\t\tassert(!!raw);\n\t\tassert(raw.get() == std::char_traits<char>::eof());\n\t\tassert(!raw);\n\n\t\t{\n\t\t\tStreamData raw3 = std::move(raw);\n\t\t\tassert(!raw3);\n\n\t\t\tassert(calledDelete == 0);\n\t\t}\n\n\t\tassert(calledDelete == 1);\n\t}\n\n\treturn 0;\n})();\n#endif\n\n\n\n}\n}\n"
  },
  {
    "path": "src/Engine/CrossPlatform.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <istream>\n#include <SDL.h>\n#include <string>\n#include <vector>\n#include <array>\n#include <memory>\n#include <utility>\n\nnamespace OpenXcom\n{\n\nusing RawDataDeleteFun = void(*)(void*);\n\n/**\n * Unique pointer with size to raw data buffer.\n */\nclass RawData\n{\n\tstd::unique_ptr<void, RawDataDeleteFun> _data;\n\tstd::size_t _size;\n\n\npublic:\n\n\t/// Default constructor.\n\tRawData() : _data{ nullptr, +[](void*){} }, _size{ }\n\t{\n\n\t}\n\n\t/// Create data from pointer and size.\n\tRawData(void* data, std::size_t size, RawDataDeleteFun del) : _data{ data, del }, _size{ size }\n\t{\n\n\t}\n\n\t/// Move constructor.\n\tRawData(RawData&& d) : RawData()\n\t{\n\t\t*this = std::move(d);\n\t}\n\n\t/// Move assignment.\n\tRawData& operator=(RawData&& d)\n\t{\n\t\t_data = std::exchange(d._data, std::unique_ptr<void, RawDataDeleteFun>{ nullptr, +[](void*){} });\n\t\t_size = std::exchange(d._size, 0u);\n\n\t\treturn *this;\n\t}\n\n\n\t/// Size of buffer.\n\tstd::size_t size() const { return _size; }\n\n\t/// Data of buffer.\n\tconst void* data() const { return _data.get(); }\n\n\t/// Data of buffer.\n\tvoid* data() { return _data.get(); }\n};\n\n/**\n * Stream to raw data buffer, owning its data buffer.\n */\nclass StreamData : public std::istream, private std::streambuf\n{\n\tRawData _data;\n\n\npublic:\n\n\t/// Default constructor.\n\tStreamData() : std::istream(nullptr)\n\t{\n\t\tthis->rdbuf(this);\n\t}\n\n\t/// Constructor from raw data.\n\tStreamData(RawData data) : StreamData()\n\t{\n\t\tinsertRawData(std::move(data));\n\t}\n\n\t/// Move constructor, move whole state to new object.\n\tStreamData(StreamData&& f) : StreamData()\n\t{\n\t\t*this = std::move(f);\n\t}\n\n\t/// Move assignment, move whole state to new object.\n\tStreamData& operator=(StreamData&& f)\n\t{\n\t\tauto state = f.rdstate();\n\t\tauto pos = f.tellg();\n\t\tinsertRawData(f.extractRawData());\n\t\tthis->seekg(pos);\n\t\tthis->clear(state);\n\n\t\treturn *this;\n\t}\n\n\n\t/// Move out raw data from object.\n\tRawData extractRawData()\n\t{\n\t\tthis->setg(nullptr, nullptr, nullptr);\n\t\treturn std::move(_data);\n\t}\n\n\t/// Insert raw data into object.\n\tvoid insertRawData(RawData data)\n\t{\n\t\t_data = std::move(data);\n\t\tthis->setg((char*)_data.data(), (char*)_data.data(), (char*)_data.data() + _data.size());\n\t\tthis->clear();\n\t}\n\n\nprotected:\n\n\t/// https://stackoverflow.com/questions/35066207/how-to-implement-custom-stdstreambufs-seekoff\n\tvirtual  std::streambuf::pos_type seekoff(\n\t\tstd::streambuf::off_type off, std::ios_base::seekdir dir,\n\t\tstd::ios_base::openmode) override\n\t{\n\t\tauto pos = gptr();\n\t\tif (dir == std::ios_base::cur)\n\t\t\tpos += off;\n\t\telse if (dir == std::ios_base::end)\n\t\t\tpos = egptr() + off;\n\t\telse if (dir == std::ios_base::beg)\n\t\t\tpos = eback() + off;\n\n\t\t// check for invalid moves\n\t\tif (pos < eback())\n\t\t\treturn std::streambuf::pos_type(-1);\n\t\telse if (pos > egptr())\n\t\t\treturn std::streambuf::pos_type(-1);\n\n\t\tsetg(eback(), pos, egptr());\n\t\treturn gptr() - eback();\n\t}\n\n\t/// https://stackoverflow.com/a/46069245/1938348\n\tvirtual std::streambuf::pos_type seekpos(\n\t\tstd::streambuf::pos_type pos,\n\t\tstd::ios_base::openmode which) override\n\t{\n\t\treturn seekoff(pos - std::streambuf::pos_type(std::streambuf::off_type(0)), std::ios_base::beg, which);\n\t}\n};\n\n/**\n * Generic purpose functions that need different\n * implementations for different platforms.\n */\nnamespace CrossPlatform\n{\n\t/// Retrieve and decode command-line arguments\n\tvoid processArgs (int argc, char *argv[]);\n\t/// Returns the command-line arguments\n\tconst std::vector<std::string>& getArgs();\n\t/// Gets the available error dialog.\n\tvoid getErrorDialog();\n\t/// Displays an error message.\n\tvoid showError(const std::string &error);\n\t/// Finds the game's data folders in the system.\n\tstd::vector<std::string> findDataFolders();\n\t/// Finds the game's user folders in the system.\n\tstd::vector<std::string> findUserFolders();\n\t/// Finds the game's config folder in the system.\n\tstd::string findConfigFolder();\n\t/// Searches the data folders and returns the full path for a data file\n\t/// when given a relative path, like \"units/zombie.pck\".  returns the passed-in\n\t/// filename if the file is not found\n\tstd::string searchDataFile(const std::string &filename);\n\t/// Searches the data folders and returns the full path for a folder\n\t/// when given a relative path, like \"common\".  returns the passed-in\n\t/// dir name if the folder is not found\n\tstd::string searchDataFolder(const std::string &foldername, std::size_t size = 0);\n\t/// Creates a folder.\n\tbool createFolder(const std::string &path);\n\t/// Terminates a path.\n\tstd::string convertPath(const std::string &path);\n\t/// Returns the list of files in a folder as a vector of tuples (filename, id_dir, mtime)\n\tstd::vector<std::tuple<std::string, bool, time_t>> getFolderContents(const std::string &path, const std::string &ext = \"\");\n\t/// Checks if the path has a minimum size (number of contents, not bytes).\n\tbool folderMinSize(const std::string &path, std::size_t size);\n\t/// Checks if the path is an existing folder.\n\tbool folderExists(const std::string &path);\n\t/// Checks if the path is an existing file.\n\tbool fileExists(const std::string &path);\n\t/// Deletes the specified file.\n\tbool deleteFile(const std::string &path);\n\t/// Gets the pathless filename of a file.\n\tstd::string baseFilename(const std::string &path);\n\t/// Gets the pathless dir of a file.\n\tstd::string dirFilename(const std::string &path);\n\t/// Sanitizes the characters in a filename.\n\tstd::string sanitizeFilename(const std::string &filename);\n\t/// Removes the extension from a filename.\n\tstd::string noExt(const std::string &file);\n\t/// Gets the extension from a filename.\n\tstd::string getExt(const std::string &file);\n\t/// Compares the extension of a filename.\n\tbool compareExt(const std::string &file, const std::string &extension);\n\t/// Gets the system locale.\n\tstd::string getLocale();\n\t/// Checks if an event is a quit shortcut.\n\tbool isQuitShortcut(const SDL_Event &ev);\n\t/// Gets the modified date of a file.\n\ttime_t getDateModified(const std::string &path);\n\t/// Converts a timestamp to a string.\n\tstd::pair<std::string, std::string> timeToString(time_t time);\n\t/// Move/rename a file between paths.\n\tbool moveFile(const std::string &src, const std::string &dest);\n\t/// Copy a file between paths.\n\tbool copyFile(const std::string &src, const std::string &dest);\n\t/// Writes out a file\n\tbool writeFile(const std::string& filename, const std::string& data);\n\tbool writeFile(const std::string& filename, const std::vector<unsigned char>& data);\n\t/// Reads in a file\n\tstd::unique_ptr<std::istream> readFile(const std::string& filename);\n\t/// Reads in a file\n\tRawData readFileRaw(const std::string& filename);\n\t/// Reads file until \"\\n---\" sequence is met or to the end. To be used only for savegames.\n\tstd::unique_ptr<std::istream> getYamlSaveHeader (const std::string& filename);\n\t/// Reads file until \"\\n---\" sequence is met or to the end. To be used only for savegames.\n\tRawData getYamlSaveHeaderRaw(const std::string& filename);\n\t/// Flashes the game window.\n\tvoid flashWindow();\n\t/// Gets the DOS-style executable path.\n\tstd::string getDosPath();\n\t/// Sets the window icon.\n\tvoid setWindowIcon(int winResource, const std::string &unixPath);\n\t/// Produces a stack trace.\n\tvoid stackTrace(void *ctx);\n\t/// Produces a quick timestamp.\n\tstd::string now();\n\t/// Produces a crash dump.\n\tvoid crashDump(void *ex, const std::string &err);\n\t/// Opens a URL.\n\tbool openExplorer(const std::string &url);\n\t/// Log something.\n\tvoid log(int, const std::ostringstream& msg);\n\t/// The log file name\n\tvoid setLogFileName(const std::string &path);\n\tconst std::string& getLogFileName();\n\t/// Get an SDL_RWops to an embedded asset. NULL if not there.\n\tSDL_RWops *getEmbeddedAsset(const std::string& assetName);\n\t/// Tests the internet connection.\n\tbool testInternetConnection(const std::string& url);\n\t/// Downloads a file from a given URL to the filesystem.\n\tbool downloadFile(const std::string& url, const std::string& filename);\n\t/// Parse string with version number.\n\tstd::array<int, 4> parseVersion(const std::string& newVersion);\n\t/// Is the given version number higher than the current version number?\n\tbool isHigherThanCurrentVersion(const std::string& newVersion);\n\t/// Is the given version number higher than the given version number?\n\tbool isHigherThanCurrentVersion(const std::array<int, 4>& newVersion, const int (&ver)[4]);\n\t/// Is the given version number lower than the minimum required version number?\n\tbool isLowerThanRequiredVersion(const std::string& dataVersion);\n\t/// Is the first version number lower than the second version number?\n\tbool isLowerThanRequiredVersion(const std::array<int, 4>& dataVersion, const int(&ver)[4]);\n\t/// Gets the path to the executable file.\n\tstd::string getExeFolder();\n\t/// Gets the file name of the executable file.\n\tstd::string getExeFilename(bool includingPath);\n\t/// Starts the update process.\n\tvoid startUpdateProcess();\n}\n\n}\n"
  },
  {
    "path": "src/Engine/DosFont.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#define DOSFONT_SIZE 1790\nunsigned char dosFont[DOSFONT_SIZE] = {\n0x42,0x4D,0xFE,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x28,0x00,\n0x00,0x00,0x20,0x01,0x00,0x00,0x30,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,\n0x00,0x00,0x00,0x00,0x00,0x00,0xC3,0x0E,0x00,0x00,0xC3,0x0E,0x00,0x00,0x00,0x00,\n0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,\n0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x0F,0x00,0x00,\n0x00,0x00,0x00,0x00,0xF0,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,\n0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x98,0x00,\n0x00,0x19,0x80,0x00,0x00,0x00,0x00,0x00,0x60,0x06,0x00,0x00,0x00,0x00,0x00,0x00,\n0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n0x00,0x00,0x18,0x00,0x00,0x19,0x80,0x00,0x00,0x00,0x00,0x00,0x60,0x06,0x00,0x00,\n0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3B,\n0x1F,0x0F,0x87,0x63,0xE3,0xC0,0xF8,0xE6,0x1E,0x01,0x9C,0xC3,0xC6,0xD9,0x98,0xF8,\n0x7C,0x3E,0x3C,0x0F,0x81,0xC3,0xB0,0x60,0xCC,0xC3,0x3F,0x3F,0x81,0xC1,0x83,0x80,\n0x00,0x00,0x00,0x66,0x19,0x98,0xCC,0xC6,0x31,0x81,0x98,0x66,0x0C,0x01,0x8C,0xC1,\n0x86,0xD9,0x99,0x8C,0x66,0x66,0x18,0x18,0xC3,0x66,0x60,0xF1,0xFE,0x66,0x63,0x31,\n0x83,0x01,0x80,0xC0,0x01,0xFC,0x00,0x66,0x19,0x98,0x0C,0xC6,0x01,0x81,0x98,0x66,\n0x0C,0x01,0x8D,0x81,0x86,0xD9,0x99,0x8C,0x66,0x66,0x18,0x01,0x83,0x06,0x61,0x99,\n0xB6,0x3C,0x63,0x18,0x03,0x01,0x80,0xC0,0x01,0x8C,0x00,0x66,0x19,0x98,0x0C,0xC6,\n0x01,0x81,0x98,0x66,0x0C,0x01,0x8F,0x01,0x86,0xD9,0x99,0x8C,0x66,0x66,0x18,0x07,\n0x03,0x06,0x63,0x0D,0xB6,0x18,0x63,0x0C,0x03,0x01,0x80,0xC0,0x01,0x8C,0x00,0x3E,\n0x19,0x98,0x0C,0xC7,0xF1,0x81,0x98,0x66,0x0C,0x01,0x8F,0x01,0x86,0xD9,0x99,0x8C,\n0x66,0x66,0x19,0x8C,0x03,0x06,0x63,0x0D,0x86,0x3C,0x63,0x06,0x03,0x01,0x80,0xC0,\n0x01,0x8C,0x00,0x06,0x1B,0x18,0xC6,0xC6,0x33,0xC1,0x98,0x76,0x0C,0x01,0x8D,0x81,\n0x87,0xF9,0x99,0x8C,0x66,0x66,0x1D,0x98,0xC3,0x06,0x63,0x0D,0x86,0x66,0x63,0x33,\n0x0E,0x00,0x00,0x70,0x00,0xD8,0x00,0x3C,0x1E,0x0F,0x83,0xC3,0xE1,0x80,0xEC,0x6C,\n0x1C,0x03,0x8C,0xC1,0x87,0x33,0x70,0xF8,0xDC,0x3B,0x37,0x0F,0x8F,0xC6,0x63,0x0D,\n0x86,0xC3,0x63,0x3F,0x83,0x01,0x80,0xC0,0x00,0x70,0x00,0x00,0x18,0x00,0x00,0xC0,\n0x01,0x90,0x00,0x60,0x00,0x00,0x0C,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x01,0x80,0xC0,0x00,0x20,0x00,0x00,\n0x18,0x00,0x00,0xC0,0x01,0xB0,0x00,0x60,0x0C,0x01,0x8C,0x01,0x80,0x00,0x00,0x00,\n0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x01,0x80,0xC3,\n0x70,0x00,0x18,0x00,0x38,0x00,0x01,0xC0,0x00,0xE0,0x00,0xE0,0x0C,0x01,0x9C,0x03,\n0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n0x01,0xC1,0x83,0x81,0xD8,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,\n0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,\n0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,\n0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x00,\n0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x63,\n0x3F,0x07,0x8F,0x87,0xF3,0xC0,0x74,0xC6,0x1E,0x1E,0x1C,0xCF,0xE6,0x1B,0x18,0xF8,\n0xF0,0x3E,0x39,0x8F,0x83,0xC3,0xE0,0x60,0xCC,0xC3,0x1E,0x3F,0xC7,0x80,0x21,0xE0,\n0x00,0x00,0xC0,0x63,0x19,0x8C,0xC6,0xC3,0x31,0x80,0xCC,0xC6,0x0C,0x33,0x0C,0xC6,\n0x66,0x1B,0x19,0x8C,0x60,0x6F,0x19,0x98,0xC1,0x86,0x30,0xF0,0xCC,0xC3,0x0C,0x30,\n0xC6,0x00,0x60,0x60,0x00,0x00,0xDC,0x63,0x19,0x98,0x46,0x63,0x11,0x81,0x8C,0xC6,\n0x0C,0x33,0x0C,0xC6,0x26,0x1B,0x19,0x8C,0x60,0x6B,0x19,0x98,0xC1,0x86,0x31,0x99,\n0xFE,0x66,0x0C,0x30,0x46,0x00,0xE0,0x60,0x00,0x00,0xDE,0x63,0x19,0x98,0x06,0x63,\n0x01,0x81,0x8C,0xC6,0x0C,0x33,0x0D,0x86,0x06,0x1B,0x19,0x8C,0x60,0x63,0x19,0x80,\n0xC1,0x86,0x33,0x0D,0xB6,0x3C,0x0C,0x18,0x06,0x01,0xC0,0x60,0x00,0x00,0xDE,0x7F,\n0x19,0x98,0x06,0x63,0x41,0xA1,0xBC,0xC6,0x0C,0x03,0x0F,0x06,0x06,0x1B,0x39,0x8C,\n0x60,0x63,0x1B,0x01,0x81,0x86,0x33,0x0D,0xB6,0x18,0x0C,0x0C,0x06,0x03,0x80,0x60,\n0x00,0x00,0xDE,0x63,0x1F,0x18,0x06,0x63,0xC1,0xE1,0x80,0xFE,0x0C,0x03,0x0F,0x06,\n0x06,0xDB,0x79,0x8C,0x7C,0x63,0x1F,0x07,0x01,0x86,0x33,0x0D,0x86,0x18,0x1E,0x06,\n0x06,0x07,0x00,0x60,0x00,0x00,0xC6,0x63,0x19,0x98,0x06,0x63,0x41,0xA1,0x80,0xC6,\n0x0C,0x03,0x0D,0x86,0x07,0xFB,0xF9,0x8C,0x66,0x63,0x19,0x8C,0x01,0x86,0x33,0x0D,\n0x86,0x3C,0x33,0x03,0x06,0x0E,0x00,0x60,0x00,0x00,0xC6,0x36,0x19,0x98,0x46,0x63,\n0x11,0x89,0x84,0xC6,0x0C,0x03,0x0C,0xC6,0x07,0xFB,0xD9,0x8C,0x66,0x63,0x19,0x98,\n0xC9,0x96,0x33,0x0D,0x86,0x66,0x61,0xA1,0x86,0x0C,0x00,0x60,0x00,0x00,0x7C,0x1C,\n0x19,0x8C,0xC6,0xC3,0x31,0x98,0xCC,0xC6,0x0C,0x03,0x0C,0xC6,0x07,0x3B,0x99,0x8C,\n0x66,0x63,0x19,0x98,0xCD,0xB6,0x33,0x0D,0x86,0xC3,0x61,0xB0,0xC6,0x08,0x00,0x63,\n0x18,0x00,0x00,0x08,0x3F,0x07,0x8F,0x87,0xF3,0xF8,0x78,0xC6,0x1E,0x07,0x9C,0xCF,\n0x06,0x1B,0x18,0xF8,0xFC,0x3E,0x3F,0x0F,0x8F,0xF6,0x33,0x0D,0x86,0xC3,0x61,0xBF,\n0xC7,0x80,0x01,0xE1,0xB0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,\n0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x00,0x00,0x00,0x00,\n0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,\n0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,\n0x00,0x0D,0x87,0xC4,0x31,0xD8,0x00,0x0C,0x18,0x00,0x00,0x01,0x80,0x00,0x61,0x00,\n0x3C,0x3F,0x3F,0x8F,0x81,0xE3,0xE1,0xF0,0x60,0x7C,0x3C,0x00,0x06,0x00,0x60,0x01,\n0x80,0x30,0x00,0x0C,0x00,0x0D,0x8C,0x66,0x33,0x30,0x00,0x18,0x0C,0x00,0x00,0x01,\n0x80,0x00,0x61,0x80,0x66,0x0C,0x31,0x98,0xC0,0xC6,0x33,0x18,0x60,0xC6,0x06,0x06,\n0x03,0x00,0xC0,0x00,0xC0,0x30,0x00,0x00,0x00,0x1F,0xC8,0x63,0x03,0x30,0x00,0x30,\n0x06,0x19,0x83,0x01,0x80,0x00,0x00,0xC0,0xC3,0x0C,0x30,0x00,0xC0,0xC0,0x33,0x18,\n0x60,0xC6,0x03,0x06,0x03,0x01,0x80,0x00,0x60,0x00,0x00,0x0C,0x00,0x0D,0x80,0x61,\n0x83,0x30,0x00,0x30,0x06,0x0F,0x03,0x00,0x00,0x00,0x00,0x60,0xC3,0x0C,0x18,0x00,\n0xC0,0xC0,0x33,0x18,0x60,0xC6,0x03,0x00,0x00,0x03,0x03,0xF0,0x30,0x30,0x00,0x0C,\n0x00,0x0D,0x80,0x60,0xC3,0x70,0x00,0x30,0x06,0x3F,0xCF,0xC0,0x07,0xF0,0x00,0x30,\n0xDB,0x0C,0x0C,0x00,0xCF,0xE0,0x33,0x18,0x30,0xC6,0x03,0x00,0x00,0x06,0x00,0x00,\n0x18,0x30,0x00,0x0C,0x00,0x0D,0x87,0xC0,0x61,0xD8,0x00,0x30,0x06,0x0F,0x03,0x00,\n0x00,0x00,0x00,0x18,0xDB,0x0C,0x06,0x07,0x8C,0xC7,0xE3,0xF0,0x18,0x7C,0x3F,0x00,\n0x00,0x03,0x00,0x00,0x30,0x30,0x00,0x1E,0x00,0x1F,0xCC,0x06,0x30,0xE0,0x00,0x30,\n0x06,0x19,0x83,0x00,0x00,0x00,0x00,0x0C,0xC3,0x0C,0x03,0x00,0xC6,0xC6,0x03,0x00,\n0x0C,0xC6,0x63,0x06,0x03,0x01,0x83,0xF0,0x60,0x18,0x00,0x1E,0x09,0x0D,0x8C,0x26,\n0x11,0xB0,0xC0,0x30,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0xC3,0x3C,0x01,0x80,\n0xC3,0xC6,0x03,0x00,0x0C,0xC6,0x63,0x06,0x03,0x00,0xC0,0x00,0xC1,0x8C,0x00,0x1E,\n0x19,0x8D,0x8C,0x60,0x01,0xB0,0x60,0x18,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n0x66,0x1C,0x31,0x98,0xC1,0xC6,0x01,0x81,0x8C,0xC6,0x63,0x00,0x00,0x00,0x60,0x01,\n0x81,0x8C,0x00,0x0C,0x19,0x80,0x07,0xC0,0x00,0xE0,0x60,0x0C,0x18,0x00,0x00,0x00,\n0x00,0x00,0x00,0x00,0x3C,0x0C,0x1F,0x0F,0x80,0xC7,0xF0,0xE1,0xFC,0x7C,0x3E,0x00,\n0x00,0x00,0x00,0x00,0x00,0xF8,0x00,0x00,0x19,0x80,0x01,0x80,0x00,0x00,0x60,0x00,\n0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,\n0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};\n"
  },
  {
    "path": "src/Engine/Exception.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <stdexcept>\n#include <string>\n\nnamespace OpenXcom\n{\n\n/**\n * Basic exception class to distinguish\n * OpenXcom exceptions from the rest.\n */\nclass Exception : public std::runtime_error\n{\npublic:\n\tException(const std::string &msg);\n};\n\n}\n"
  },
  {
    "path": "src/Engine/FastLineClip.cpp",
    "content": "/*--------------------------------------------------- V_FCclip\n *  Realization of line clipping algorithm FC (Fast Clipping)\n *  Sobkow-Pospisil-Yang, with line encoding\n *\n * int LineClip (double *x0, double *y0, double *x1, double *y1)\n *\n * Clips the line defined with (x0,y0)-(x1,y1), by clipping\n * window defined with global scalars Wxlef, Wytop, Wxrig, Wybot\n * (top of screen is 0)\n *\n * Returns:\n * -1 - clipping window error\n *  0 - line is invisible\n *  1 - line is visible\n */\n#include \"FastLineClip.h\"\n\n\nnamespace OpenXcom\n{\n\nvoid FastLineClip::Clip0_Bottom(void)\n{\n\tFC_xn = FC_xn + (FC_xk-FC_xn)*(Wybot-FC_yn)/(FC_yk-FC_yn);\n\tFC_yn = Wybot;\n}\n\nvoid FastLineClip::Clip0_Top(void)\n{\n\tFC_xn = FC_xn + (FC_xk-FC_xn)*(Wytop-FC_yn)/(FC_yk-FC_yn);\n\tFC_yn = Wytop;\n}\n\nvoid FastLineClip::Clip0_Right(void)\n{\n\tFC_yn = FC_yn + (FC_yk-FC_yn)*(Wxrig-FC_xn)/(FC_xk-FC_xn);\n\tFC_xn = Wxrig;\n}\n\nvoid FastLineClip::Clip0_Left(void)\n{\n\tFC_yn = FC_yn + (FC_yk-FC_yn)*(Wxlef-FC_xn)/(FC_xk-FC_xn);\n\tFC_xn = Wxlef;\n}\n\nvoid FastLineClip::Clip1_Bottom(void)\n{\n\tFC_xk = FC_xk + (FC_xn-FC_xk)*(Wybot-FC_yk)/(FC_yn-FC_yk);\n\tFC_yk = Wybot;\n}\n\nvoid FastLineClip::Clip1_Top(void)\n{\n\tFC_xk = FC_xk + (FC_xn-FC_xk)*(Wytop-FC_yk)/(FC_yn-FC_yk);\n\tFC_yk = Wytop;\n}\n\nvoid FastLineClip::Clip1_Right(void)\n{\n\tFC_yk = FC_yk + (FC_yn-FC_yk)*(Wxrig-FC_xk)/(FC_xn-FC_xk);\n\tFC_xk = Wxrig;\n}\n\nvoid FastLineClip::Clip1_Left(void)\n{\n\tFC_yk = FC_yk + (FC_yn-FC_yk)*(Wxlef-FC_xk)/(FC_xn-FC_xk);\n\tFC_xk = Wxlef;\n}\n\n\n\n\n\nint FastLineClip::LineClip(double *x0, double *y0, double *x1, double *y1)\n{\n\tint  Code= 0;\n\tint  visible= 0;             // visible state\n\n\tFC_xn= *x0;  FC_yn= *y0;\n\tFC_xk= *x1;  FC_yk= *y1;\n\n\n// \"Code\" evaluation - bits 0..3 - end point, bits 4..7 - start point.\n\n\t\t\t\t\t//start point is\n   if (FC_yk > Wybot) Code|= 0x08; else //lower\n   if (FC_yk < Wytop) Code|= 0x04; \t//higher\n\n   if (FC_xk > Wxrig) Code|= 0x02; else //righter\n   if (FC_xk < Wxlef) Code|= 0x01;\t//lefter\n\n\t\t\t\t\t//end point is\n   if (FC_yn > Wybot) Code|= 0x80; else //lower\n   if (FC_yn < Wytop) Code|= 0x40;\t//higher\n\n   if (FC_xn > Wxrig) Code|= 0x20; else\t//righter\n   if (FC_xn < Wxlef) Code|= 0x10;\t//lefter\n\n// Clipping for each of 81 cases.\n   switch (Code) {\n\n\t // From center\n\n\t case 0x00: ++visible;  break;\n\t case 0x01: Clip1_Left() ;   ++visible;  break;\n\t case 0x02: Clip1_Right();  ++visible;  break;\n\t case 0x04: Clip1_Top(); ++visible;  break;\n\t case 0x05: Clip1_Left() ;\n\t\t\t\tif (FC_yk < Wytop) Clip1_Top();\n\t\t\t\t++visible;  break;\n\t case 0x06: Clip1_Right();\n\t\t\t\tif (FC_yk < Wytop) Clip1_Top();\n\t\t\t\t++visible;  break;\n\t case 0x08: Clip1_Bottom();    ++visible;  break;\n\t case 0x09: Clip1_Left() ;\n\t\t\t\tif (FC_yk > Wybot) Clip1_Bottom();\n\t\t\t\t++visible;  break;\n\t case 0x0A: Clip1_Right();\n\t\t\t\tif (FC_yk > Wybot) Clip1_Bottom();\n\t\t\t\t++visible;  break;\n\n\n\n\n\n\t //From left\n\n\t case 0x10: Clip0_Left();   ++visible;\n\t case 0x11: break;\n\t case 0x12: Clip0_Left();   Clip1_Right();\n\t\t\t\t++visible;  break;\n\t case 0x14: Clip0_Left();\n\t\t\t\tif (FC_yn < Wytop) break;\n\t\t\t\tClip1_Top();\n\t\t\t\t++visible;\n\t case 0x15: break;\n\t case 0x16: Clip0_Left();\n\t\t\t\tif (FC_yn < Wytop) break;\n\t\t\t\tClip1_Top();\n\t\t\t\tif (FC_xk > Wxrig) Clip1_Right();\n\t\t\t\t++visible;\n\t\t\t\tbreak;\n\t case 0x18: Clip0_Left();\n\t\t\t\tif (FC_yn > Wybot) break;\n\t\t\t\tClip1_Bottom();\n\t\t\t\t++visible;\n\t case 0x19: break;\n\t case 0x1A: Clip0_Left();\n\t\t\t\tif (FC_yn > Wybot) break;\n\t\t\t\tClip1_Bottom();\n\t\t\t\tif (FC_xk > Wxrig) Clip1_Right();\n\t\t\t\t++visible;\n\t\t\t\tbreak;\n\n\n\n\n\n\t // From right\n\n\t case 0x20: Clip0_Right(); ++visible;  break;\n\t case 0x21: Clip0_Right(); Clip1_Left(); ++visible;\n\t case 0x22: break;\n\t case 0x24: Clip0_Right();\n\t\t\t\tif (FC_yn < Wytop) break;\n\t\t\t\tClip1_Top();\n\t\t\t\t++visible;\n\t\t\t\tbreak;\n\t case 0x25: Clip0_Right();\n\t\t\t\tif (FC_yn < Wytop) break;\n\t\t\t\tClip1_Top();\n\t\t\t\tif (FC_xk < Wxlef) Clip1_Left();\n\t\t\t\t++visible;\n\t case 0x26: break;\n\t case 0x28: Clip0_Right();\n\t\t\t\tif (FC_yn > Wybot) break;\n\t\t\t\tClip1_Bottom();\n\t\t\t\t++visible;\n\t\t\t\tbreak;\n\t case 0x29: Clip0_Right();\n\t\t\t\tif (FC_yn > Wybot) break;\n\t\t\t\tClip1_Bottom();\n\t\t\t\tif (FC_xk < Wxlef) Clip1_Left();\n\t\t\t\t++visible;\n\t case 0x2A: break;\n\n\n\n\n\n\t // From down\n\n\t case 0x40: Clip0_Top(); ++visible;  break;\n\t case 0x41: Clip0_Top();\n\t\t\t\tif (FC_xn < Wxlef) break;\n\t\t\t\tClip1_Left() ;\n\t\t\t\tif (FC_yk < Wytop) Clip1_Top();\n\t\t\t\t++visible;\n\t\t\t\tbreak;\n\t case 0x42: Clip0_Top();\n\t\t\t\tif (FC_xn > Wxrig) break;\n\t\t\t\tClip1_Right();\n\t\t\t\t++visible;\n\t case 0x44:\n\t case 0x45:\n\t case 0x46: break;\n\t case 0x48: Clip0_Top();\n\t\t\t\tClip1_Bottom();\n\t\t\t\t++visible;\n\t\t\t\tbreak;\n\t case 0x49: Clip0_Top();\n\t\t\t\tif (FC_xn < Wxlef) break;\n\t\t\t\tClip1_Left() ;\n\t\t\t\tif (FC_yk > Wybot) Clip1_Bottom();\n\t\t\t\t++visible;\n\t\t\t\tbreak;\n\t case 0x4A: Clip0_Top();\n\t\t\t\tif (FC_xn > Wxrig) break;\n\t\t\t\tClip1_Right();\n\t\t\t\tif (FC_yk > Wybot) Clip1_Bottom();\n\t\t\t\t++visible;\n\t\t\t\tbreak;\n\n\n\n\n\n\t // From bottom-left\n\n\t case 0x50: Clip0_Left();\n\t\t\t\tif (FC_yn < Wytop) Clip0_Top();\n\t\t\t\t++visible;\n\t case 0x51: break;\n\t case 0x52: Clip1_Right();\n\t\t\t\tif (FC_yk < Wytop) break;\n\t\t\t\tClip0_Top();\n\t\t\t\tif (FC_xn < Wxlef) Clip0_Left();\n\t\t\t\t++visible;\n\t case 0x54:\n\t case 0x55:\n\t case 0x56: break;\n\t case 0x58: Clip1_Bottom();\n\t\t\t\tif (FC_xk < Wxlef) break;\n\t\t\t\tClip0_Top();\n\t\t\t\tif (FC_xn < Wxlef) Clip0_Left();\n\t\t\t\t++visible;\n\t case 0x59: break;\n\t case 0x5A: Clip0_Left();\n\t\t\t\tif (FC_yn > Wybot) break;\n\t\t\t\tClip1_Right();\n\t\t\t\tif (FC_yk < Wytop) break;\n\t\t\t\tif (FC_yn < Wytop) Clip0_Top();\n\t\t\t\tif (FC_yk > Wybot) Clip1_Bottom();\n\t\t\t\t++visible;\n\t\t\t\tbreak;\n\n\n\n\n\n\t // From bottom-right\n\n\t case 0x60: Clip0_Right();\n\t\t\t\tif (FC_yn < Wytop) Clip0_Top();\n\t\t\t\t++visible;\n\t\t\t\tbreak;\n\t case 0x61: Clip1_Left() ;\n\t\t\t\tif (FC_yk < Wytop) break;\n\t\t\t\tClip0_Top();\n\t\t\t\tif (FC_xn > Wxrig) Clip0_Right();\n\t\t\t\t++visible;\n\t case 0x62:\n\t case 0x64:\n\t case 0x65:\n\t case 0x66: break;\n\t case 0x68: Clip1_Bottom();\n\t\t\t\tif (FC_xk > Wxrig) break;\n\t\t\t\tClip0_Right();\n\t\t\t\tif (FC_yn < Wytop) Clip0_Top();\n\t\t\t\t++visible;\n\t\t\t\tbreak;\n\t case 0x69: Clip1_Left() ;\n\t\t\t\tif (FC_yk < Wytop) break;\n\t\t\t\tClip0_Right();\n\t\t\t\tif (FC_yn > Wybot) break;\n\t\t\t\tif (FC_yk > Wybot) Clip1_Bottom();\n\t\t\t\tif (FC_yn < Wytop) Clip0_Top();\n\t\t\t\t++visible;\n\t case 0x6A: break;\n\n\n\n\n\n\t // From top\n\n\t case 0x80: Clip0_Bottom();\n\t\t\t\t++visible;\n\t\t\t\tbreak;\n\t case 0x81: Clip0_Bottom();\n\t\t\t\tif (FC_xn < Wxlef) break;\n\t\t\t\tClip1_Left() ;\n\t\t\t\t++visible;\n\t\t\t\tbreak;\n\t case 0x82: Clip0_Bottom();\n\t\t\t\tif (FC_xn > Wxrig) break;\n\t\t\t\tClip1_Right();\n\t\t\t\t++visible;\n\t\t\t\tbreak;\n\t case 0x84: Clip0_Bottom();\n\t\t\t\tClip1_Top();\n\t\t\t\t++visible;\n\t\t\t\tbreak;\n\t case 0x85: Clip0_Bottom();\n\t\t\t\tif (FC_xn < Wxlef) break;\n\t\t\t\tClip1_Left() ;\n\t\t\t\tif (FC_yk < Wytop) Clip1_Top();\n\t\t\t\t++visible;\n\t\t\t\tbreak;\n\t case 0x86: Clip0_Bottom();\n\t\t\t\tif (FC_xn > Wxrig) break;\n\t\t\t\tClip1_Right();\n\t\t\t\tif (FC_yk < Wytop) Clip1_Top();\n\t\t\t\t++visible;\n\t case 0x88:\n\t case 0x89:\n\t case 0x8A: break;\n\n\n\n\n\n\t // From top-left\n\n\t case 0x90: Clip0_Left();\n\t\t\t\tif (FC_yn > Wybot) Clip0_Bottom();\n\t\t\t\t++visible;\n\t case 0x91: break;\n\t case 0x92: Clip1_Right();\n\t\t\t\tif (FC_yk > Wybot) break;\n\t\t\t\tClip0_Bottom();\n\t\t\t\tif (FC_xn < Wxlef) Clip0_Left();\n\t\t\t\t++visible;\n\t\t\t\tbreak;\n\t case 0x94: Clip1_Top();\n\t\t\t\tif (FC_xk < Wxlef) break;\n\t\t\t\tClip0_Left();\n\t\t\t\tif (FC_yn > Wybot) Clip0_Bottom();\n\t\t\t\t++visible;\n\t case 0x95: break;\n\t case 0x96: Clip0_Left();\n\t\t\t\tif (FC_yn < Wytop) break;\n\t\t\t\tClip1_Right();\n\t\t\t\tif (FC_yk > Wybot) break;\n\t\t\t\tif (FC_yn > Wybot) Clip0_Bottom();\n\t\t\t\tif (FC_yk < Wytop) Clip1_Top();\n\t\t\t\t++visible;\n\t case 0x98:\n\t case 0x99:\n\t case 0x9A: break;\n\n\n\n\n\n\t // From top-right\n\n\t case 0xA0: Clip0_Right();\n\t\t\t\tif (FC_yn > Wybot) Clip0_Bottom();\n\t\t\t\t++visible;\n\t\t\t\tbreak;\n\t case 0xA1: Clip1_Left() ;\n\t\t\t\tif (FC_yk > Wybot) break;\n\t\t\t\tClip0_Bottom();\n\t\t\t\tif (FC_xn > Wxrig) Clip0_Right();\n\t\t\t\t++visible;\n\t case 0xA2: break;\n\t case 0xA4: Clip1_Top();\n\t\t\t\tif (FC_xk > Wxrig) break;\n\t\t\t\tClip0_Right();\n\t\t\t\tif (FC_yn > Wybot) Clip0_Bottom();\n\t\t\t\t++visible;\n\t\t\t\tbreak;\n\t case 0xA5: Clip1_Left() ;\n\t\t\t\tif (FC_yk > Wybot) break;\n\t\t\t\tClip0_Right();\n\t\t\t\tif (FC_yn < Wytop) break;\n\t\t\t\tif (FC_yk < Wytop) Clip1_Top();\n\t\t\t\tif (FC_yn > Wybot) Clip0_Bottom();\n\t\t\t\t++visible;\n\t case 0xA6:\n\t case 0xA8:\n\t case 0xA9:\n\t case 0xAA: break;\n\n\n\n\n\t // Error\n\n\t default:   visible= -1;\n\t\t\t\tbreak;\n   }  //Switch\n\n   if (visible > 0) {\n\t  *x0= FC_xn;  *y0= FC_yn;\n\t  *x1= FC_xk;  *y1= FC_yk;\n   }\n   return (visible);\n}\n\n\n}\n"
  },
  {
    "path": "src/Engine/FastLineClip.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\nnamespace OpenXcom\n{\n/**\n * Fast line clip.\n */\nclass FastLineClip\n{\nprivate:\n\tdouble FC_xn, FC_yn, FC_xk, FC_yk;\n\tvoid Clip0_Top(void);\n\tvoid Clip0_Bottom(void);\n\tvoid Clip0_Right(void);\n\tvoid Clip0_Left(void);\n\tvoid Clip1_Top(void);\n\tvoid Clip1_Bottom(void);\n\tvoid Clip1_Right(void);\n\tvoid Clip1_Left(void);\npublic:\n\tdouble Wxlef, Wxrig, Wytop, Wybot;\n\t/// Creates a fastlineclip.\n\tFastLineClip(double Wxl, double Wxr, double Wyt, double Wyb) : FC_xn(0), FC_yn(0), FC_xk(0), FC_yk(0)\n\t{\n\t\tWxlef = Wxl;\n\t\tWxrig = Wxr;\n\t\tWytop = Wyt;\n\t\tWybot = Wyb;\n\t};\n\t/// Cleans up the fastlineclip.\n\t~FastLineClip() {};\n\t/// LineClip itself.\n\tint LineClip(double *x0, double *y0, double *x1, double *y1);\n};\n\n}\n"
  },
  {
    "path": "src/Engine/FileMap.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n/*\n * Rules re resource/ruleset file records\n *\n * 1. mods are either directories under standard / user/mods\n *    or zip files in those directories.\n * 2. metadata.yml is required.\n * 3. zipfiles can either contain a single mod (metadata.yml at top level) or\n *    multiple mods (metadata.yml one level down).\n * 4. in both cases zipfile [sub]directory structure is what a mod dir structure is.\n * 5. mod directory can not contain zip files.\n * 6. same goes for subdirectories.\n * 7. the loader considers actual files in a directory tree with the same modId\n *    to override the zipped files from a mod with the modId.\n * 8. no more than a single .zip or a single directory is allowed for a modId.\n * 9. zipfile name does not matter, but if a directory happens to get scanned insert_before\n *    a zipfile with the same modId, the zipfile would be ignored.\n * A. somename.zip is always scanned before somename/ directory.\n */\n\n#include <string>\n#include <sstream>\n#include <istream>\n#include <unordered_map>\n#include <unordered_set>\n\n#include \"FileMap.h\"\n#include \"Unicode.h\"\n#include \"Logger.h\"\n#include \"CrossPlatform.h\"\n#include \"Options.h\"\n#include \"Exception.h\"\n\n#define MINIZ_NO_STDIO\n#include \"../../libs/miniz/miniz.h\"\n\nextern \"C\"\n{\n\nint mzops_close(struct SDL_RWops *context) {\n\tif (context) {\n\t\tif (context->hidden.mem.base) {\n\t\t\tmz_free(context->hidden.mem.base);\n\t\t}\n\t\tSDL_FreeRW(context);\n\t}\n\treturn 0;\n}\nSDL_RWops *SDL_RWFromMZ(mz_zip_archive *zip, mz_uint file_index) {\n\tsize_t size;\n\tvoid *data = mz_zip_reader_extract_to_heap(zip, file_index, &size, 0);\n\tif (data == NULL) {\n\t\tSDL_SetError(\"miniz extract: %s\", mz_zip_get_error_string(mz_zip_get_last_error(zip)));\n\t\treturn NULL;\n\t}\n\tSDL_RWops *rv = SDL_RWFromConstMem(data, size);\n\trv->close = mzops_close;\n\treturn rv;\n}\n\n/* helpers that are already present in SDL2 */\n#if !SDL_VERSION_ATLEAST(2,0,0)\nUint8 SDL_ReadU8(SDL_RWops *src) {\n\tUint8 px = 0;\n\tSDL_RWread(src, &px, 1, 1);\n\treturn px;\n}\nSint64 SDL_RWsize(SDL_RWops *src) {\n\tauto curpos = SDL_RWtell(src);\n\tauto rv = SDL_RWseek(src, 0, RW_SEEK_END);\n\tSDL_RWseek(src, curpos, RW_SEEK_SET);\n\treturn rv;\n}\n#endif\n#if !SDL_VERSION_ATLEAST(2,0,6)\nvoid *SDL_LoadFile_RW(SDL_RWops *src, size_t *datasize, int freesrc)\n{\n\tconst int FILE_CHUNK_SIZE = 1024;\n\tSint64 size;\n\tSint64 size_read, size_total;\n\tvoid *data = NULL, *newdata;\n\tif (!src) {\n\t\tSDL_SetError(\"SDL_LoadFile_RW(): src==NULL\");\n\t\treturn NULL;\n\t}\n\n\tsize = SDL_RWsize(src);\n\tif (size < 0) {\n\t\tsize = FILE_CHUNK_SIZE;\n\t}\n\tdata = SDL_malloc((size_t)(size + 1));\n\n\tsize_total = 0;\n\tfor (;;) {\n\t\tif ((((Sint64)size_total) + FILE_CHUNK_SIZE) > size) {\n\t\t\tsize = (size_total + FILE_CHUNK_SIZE);\n\t\t\tnewdata = SDL_realloc(data, (size_t)(size + 1));\n\t\t\tif (!newdata) {\n\t\t\t\tSDL_free(data);\n\t\t\t\tdata = NULL;\n\t\t\t\tSDL_OutOfMemory();\n\t\t\t\tgoto done;\n\t\t\t}\n\t\tdata = newdata;\n\t}\n\n\tsize_read = SDL_RWread(src, (char *)data+size_total, 1, (size_t)(size-size_total));\n\tif (size_read == 0) {\n\t\t\tbreak;\n\t\t}\n\t\t\tif (size_read == -1) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\tsize_total += size_read;\n\t}\n\n\tif (datasize) {\n\t\t*datasize = size_total;\n\t}\n\t((char *)data)[size_total] = '\\0';\n\n\tdone:\n\tif (freesrc && src) {\n\t\tSDL_RWclose(src);\n\t}\n\treturn data;\n}\n#endif\n\n/* miniz to SDL_rwops helpers */\n\nstatic size_t mz_rwops_read_func(void *vops, mz_uint64 file_ofs, void *pBuf, size_t n) {\n\tSDL_RWops *rwops = (SDL_RWops *)vops;\n\tSint64 size_seek = SDL_RWseek(rwops, file_ofs, SEEK_SET);\n\tif (size_seek != (Sint64)file_ofs) { return 0; }\n\tint size_read = SDL_RWread(rwops, pBuf, 1, n);\n\treturn size_read;\n}\nstatic mz_bool mz_zip_reader_init_rwops(mz_zip_archive *pZip, SDL_RWops *rwops) {\n\tif (!rwops) { return false; }\n\tSint64 size = SDL_RWsize(rwops);\n\tmz_zip_zero_struct(pZip);\n\tpZip->m_pRead = mz_rwops_read_func;\n\tpZip->m_pIO_opaque = rwops;\n\treturn mz_zip_reader_init(pZip, size, 0);\n}\nstatic mz_bool mz_zip_reader_end_rwops(mz_zip_archive *pZip) {\n\tif (!pZip) { return false; }\n\tif (!pZip->m_pIO_opaque) { return false; }\n\tSDL_RWclose((SDL_RWops *)(pZip->m_pIO_opaque));\n\treturn mz_zip_reader_end(pZip);\n}\n\n}\n\nnamespace OpenXcom\n{\nnamespace FileMap\n{\n\nstatic inline std::string concatPaths(const std::string& basePath, const std::string& relativePath)\n{\n\tif(basePath.size() == 0) throw Exception(\"Need correct basePath\");\n\tif(relativePath.size() == 0) throw Exception(\"Need correct relativePath\");\n\tif (basePath[basePath.size() - 1] == '/')\n\t{\n\t\treturn basePath + relativePath;\n\t}\n\telse\n\t{\n\t\treturn basePath + \"/\" + relativePath;\n\t}\n}\nstatic inline std::string concatOptionalPaths(const std::string& basePath, const std::string& relativePath)\n{\n\tif (basePath.size() == 0)\n\t{\n\t\treturn relativePath;\n\t}\n\telse if (relativePath.size() == 0)\n\t{\n\t\treturn basePath;\n\t}\n\telse\n\t{\n\t\treturn concatPaths(basePath, relativePath);\n\t}\n}\n\nFileRecord::FileRecord() : fullpath(\"\"), zip(NULL), findex(0) { }\n\nSDL_RWops *FileRecord::getRWops() const\n{\n\tSDL_RWops *rv;\n\tif (zip != NULL) {\n\t\trv = SDL_RWFromMZ((mz_zip_archive *)zip, findex);\n\t} else {\n\t\trv = SDL_RWFromFile(fullpath.c_str(), \"rb\");\n\t}\n\tif (!rv) { Log(LOG_ERROR) << \"FileRecord::getRWops(): err=\" << SDL_GetError(); }\n\treturn rv;\n}\n\nSDL_RWops *FileRecord::getRWopsReadAll() const\n{\n\tSDL_RWops *rv;\n\tif (zip != NULL)\n\t{\n\t\trv = SDL_RWFromMZ((mz_zip_archive *)zip, findex);\n\t}\n\telse\n\t{\n\t\trv = SDL_RWFromFile(fullpath.c_str(), \"rb\");\n\t\tif (rv)\n\t\t{\n\t\t\tsize_t size = 0;\n\t\t\tauto data = SDL_LoadFile_RW(rv, &size, SDL_TRUE);\n\t\t\tif (data)\n\t\t\t{\n\t\t\t\trv = SDL_RWFromConstMem(data, size);\n\n\t\t\t\t//close callback\n\t\t\t\trv->close = [](struct SDL_RWops *context)\n\t\t\t\t{\n\t\t\t\t\tif (context)\n\t\t\t\t\t{\n\t\t\t\t\t\t//HACK: technically speaking `hidden` is an implementation detail, but we need to use it to deallocate memory (similar to `mzops_close`)\n\t\t\t\t\t\tif (context->hidden.mem.base)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tSDL_free(context->hidden.mem.base);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tSDL_FreeRW(context);\n\t\t\t\t\t}\n\t\t\t\t\treturn 0;\n\t\t\t\t};\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\trv = nullptr;\n\t\t\t}\n\t\t}\n\t}\n\tif (!rv) { Log(LOG_ERROR) << \"FileRecord::getRWopsReadAll(): err=\" << SDL_GetError(); }\n\treturn rv;\n}\n\nstd::unique_ptr<std::istream> FileRecord::getIStream() const\n{\n\tif (zip != NULL) {\n\t\treturn std::unique_ptr<std::istream>(new StreamData(getUnzippedData()));\n\t} else {\n\t\treturn CrossPlatform::readFile(fullpath);\n\t}\n}\n\nRawData FileRecord::getUnzippedData() const\n{\n\tsize_t size;\n\tvoid* data = mz_zip_reader_extract_to_heap((mz_zip_archive*)zip, findex, &size, 0);\n\tif (data == NULL)\n\t{\n\t\tauto err = \"FileRecord::getIStream(): failed to decompress \" + fullpath + \": \";\n\t\terr += mz_zip_get_error_string(mz_zip_get_last_error((mz_zip_archive*)zip));\n\t\tLog(LOG_FATAL) << err;\n\t\tthrow Exception(err);\n\t}\n\treturn RawData(data, size, mz_free);\n}\n\nYAML::YamlRootNodeReader FileRecord::getYAML() const\n{\n\ttry\n\t{\n\t\tRawData data = zip != NULL ? getUnzippedData() : CrossPlatform::readFileRaw(fullpath);\n\t\treturn YAML::YamlRootNodeReader(data, fullpath);\n\t}\n\tcatch(...)\n\t{\n\t\tLog(LOG_FATAL) << \"Error loading file '\" << fullpath << \"'\";\n\t\tthrow;\n\t}\n}\n\nstd::vector<YAML::YamlNodeReader> FileRecord::getAllYAML() const\n{\n\tLog(LOG_FATAL) << \"Error loading file '\" << fullpath << \"'\";\n\tthrow Exception(\"getAllYAML(): Not implemented\");\n\t/*\n\tThe function would have to load a file, parse it, then emit each document child separately, and parse each child again.\n\tThis obviously doesn't make sense. Just use a normal getYAML() and handle multiple yaml documents accordingly\n\t*/\n}\n\n\n/**\n * Find out somehow if it's well-formed UTF8.\n * Since we can't know the code page used at compression time, we just return false,\n * which means crash, but note the .zip filename.\n *\n * And also convert slashes to forward.\n */\nstatic bool sanitizeZipEntryName(std::string& zefname) {\n\tif (!Unicode::isValidUTF8(zefname)) { return false; }\n\tUnicode::replace(zefname,\"\\\\\",\"/\");\n\treturn true;\n}\nstatic std::string hexDumpBogusData(const std::string& bogus) {\n\tstd::vector<char> buf(bogus.size()*3 + 1, 0);\n\tchar *p = buf.data();\n\tfor (auto c : bogus) { p += sprintf(p, \"%02hhx \", c); }\n\treturn std::string(buf.data());\n}\n/* recursively list a directory */\ntypedef std::vector<std::pair<std::string, std::string>> dirlist_t; // <dirname, basename>\nstatic bool ls_r(const std::string &basePath, const std::string &relPath, dirlist_t& dlist) {\n\tauto fullDir = concatOptionalPaths(basePath, relPath);\n\tauto files = CrossPlatform::getFolderContents(fullDir);\n\t//Log(LOG_VERBOSE) << \"ls_r: listing \"<<fullDir<<\" count=\"<<files.size();\n\tfor (auto i = files.begin(); i != files.end(); ++i) {\n\t\tif (std::get<1>(*i)) { // it's a subfolder\n\t\t\tauto fullpath = concatPaths(fullDir, std::get<0>(*i));\n\t\t\tif (CrossPlatform::folderExists(fullpath)) {\n\t\t\t\tauto nextRelPath = concatOptionalPaths(relPath, std::get<0>(*i));\n\t\t\t\tls_r(basePath, nextRelPath, dlist);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t} else {\n\t\t\tdlist.push_back(std::make_pair(relPath, std::get<0>(*i)));\n\t\t}\n\t}\n\treturn true;\n}\nstatic bool isRuleset(const std::string& fname)\n{\n\tif (fname.size() < 4) { return false; }\n\tconstexpr Uint32 dotRul =           '.' << 0 |  'r' << 8 |  'u' << 16 |  'l' << 24;\n\tconstexpr Uint32 toLowerCaseMask = 0x00 << 0 | 0x20 << 8 | 0x20 << 16 | 0x20 << 24;\n\tUint32 last4; // Pack last 4 chars into Uint32\n\tstd::memcpy(&last4, fname.data() + fname.size() - 4, 4); // Need memcpy because unaligned ptr\n\treturn (last4 | toLowerCaseMask) == dotRul;\n}\n\ntypedef std::unordered_map<std::string, FileRecord> FileSet;\nstatic const NameSet emptySet;\nstatic mz_zip_archive *newZipContext(const std::string& log_ctx, SDL_RWops *rwops);\n\nstruct VFSLayer {\n\tstd::string fullpath;\t\t\t\t// the origin\n\tFileSet resources; \t\t\t\t\t// relpath -> frec.\n\tstd::vector<FileRecord> rulesets;  \t// keeps FileRecord copies ala hard links\n\tstd::unordered_map<std::string, NameSet> vdirs;\n\tbool mapped;\t\t \t\t\t\t// once mapped all this is immutable\n\n\tVFSLayer(const std::string& path) : fullpath(path), resources(), rulesets(), vdirs(),\n\t\t\t\t\t\t\t\t\t\tmapped(false) { }\n\t~VFSLayer() { }\n\tconst FileRecord *at(const std::string& relpath) {\n\t\tauto crelpath = canonicalize(relpath);\n\t\tauto it = resources.find(crelpath);\n\t\treturn  (it == resources.end()) ? NULL : &it->second;\n\t}\n\tconst NameSet& ls(const std::string& relpath) {\n\t\tauto crelpath = canonicalize(relpath);\n\t\twhile (crelpath.size() > 0 && crelpath[crelpath.size() - 1] == '/') {\n\t\t\tcrelpath.resize(crelpath.size() - 1);\n\t\t}\n\t\tauto it = vdirs.find(crelpath);\n\t\treturn (it == vdirs.end()) ? emptySet : it->second;\n\t}\n\tconst std::vector<FileRecord>& get_rulesets() { return rulesets; }\n\n\tvoid insert(const std::string& relpath, FileRecord frec) {\n\t\tauto crelpath = canonicalize(relpath);\n\n\t\tif (isRuleset(crelpath)) {\n\t\t\trulesets.push_back(frec);\n\t\t\treturn;\n\t\t}\n\t\t// shouldn't happen, but overwrite nevertheless\n\t\tauto existing = resources.find(crelpath);\n\t\tif (existing != resources.end()) { resources.erase(existing); }\n\t\t// actually insert\n\t\tresources.insert(std::make_pair(crelpath, frec));\n\n\t\t// update corresponding vdir\n\t\tstd::string basename = crelpath;\n\t\tstd::string dirname = \"\";\n\t\tauto const pos = crelpath.find_last_of('/');\n\t\tif (pos != crelpath.npos) {\n\t\t\tbasename = crelpath.substr(pos + 1);\n\t\t\tdirname = crelpath.substr(0, pos);\n\t\t}\n\t\tauto existing_vd = vdirs.find(dirname);\n\t\tif (existing_vd == vdirs.end()) {\n\t\t\tvdirs.insert(std::pair<std::string, NameSet>(dirname, NameSet()));\n\t\t}\n\t\tvdirs.at(dirname).insert(basename);\n\t}\n\t/** maps a zipped moddir from filesystem\n\t* @param zippath - path to the .zip\n\t* @param prefix - prefix in the .zip in case there are multiple mods in a single .zip. Has to have the trailing slash.\n\t* @param ignore_ruls - skip rulesets\n\t* @return - did we map anything (false, i.e if failed to unzip)\n\t*/\n\tbool mapZipFile(const std::string& zippath, const std::string& prefix, bool ignore_ruls = false) {\n\t\tstd::string log_ctx = \"mapZipFile(\" + zippath + \",  '\" + prefix + \"',  '\" + (ignore_ruls ? \"true\" : \"false\") + \"'): \";\n\t\tSDL_RWops *rwops = SDL_RWFromFile(zippath.c_str(), \"r\");\n\t\tif (!rwops) {\n\t\t\tLog(LOG_WARNING) << log_ctx << \"Ignoring zip '\" << zippath << \"': \" << SDL_GetError();\n\t\t\treturn false;\n\t\t}\n\t\treturn mapZipFileRW(rwops, zippath, prefix, ignore_ruls);\n\t}\n\t/** maps a zipped moddir from an SDL_RWops\n\t* @param rwops - SDL_RWops with the zip data\n\t* @param zipppath - the file path to associate this with\n\t* @param prefix - prefix in the .zip in case there are multiple mods in a single .zip. Has to have the trailing slash.\n\t* @param ignore_ruls - skip rulesets\n\t* @return - did we map anything (false, i.e if failed to unzip)\n\t*/\n\tbool mapZipFileRW(SDL_RWops *rwops, const std::string& zippath, const std::string& prefix, bool ignore_ruls = false) {\n\t\tstd::string log_ctx = \"mapZipFileRW(rwops, '\" + zippath + \"', '\" + prefix + \"',  '\" + (ignore_ruls ? \"true\" : \"false\") + \"'): \";\n\t\tmz_zip_archive *zip = newZipContext(log_ctx, rwops);\n\t\tif (!zip) { return false; }\n\t\treturn mapZip(zip, zippath, prefix, ignore_ruls);\n\t}\n\n\t/** maps a zipped moddir from filesystem\n\t* @param zippath - the file path to associate this with\n\t* @param prefix - prefix in the .zip in case there are multiple mods in a single .zip. Has to have the trailing slash.\n\t* @param ignore_ruls - skip rulesets\n\t* @return - did we map anything (false, i.e if failed to unzip)\n\t*/\n\tbool mapZip(mz_zip_archive *zip, const std::string& zippath, const std::string& prefix, bool ignore_ruls = false) {\n\t\tstd::string log_ctx = \"mapZip(zip, '\" + zippath + \"', '\" + prefix + \"',  '\" + (ignore_ruls ? \"true\" : \"false\") + \"'): \";\n\t\tif (mapped) {\n\t\t\tauto err=  log_ctx + \"Fatal: already mapped.\";\n\t\t\tLog(LOG_FATAL) << err;\n\t\t\tthrow Exception(err);\n\t\t}\n\t\tauto prefixlen = prefix.size();\n\t\tif ((prefixlen) > 0 && (prefix[prefixlen-1] != '/')) {\n\t\t\tauto err = log_ctx + \"Bogus prefix of '\" + prefix;\n\t\t\tLog(LOG_FATAL) << err;\n\t\t\tthrow Exception(err);\n\t\t}\n\t\tmapped = true;\n\t\tfullpath = zippath;\n\t\tmz_uint filecount = mz_zip_reader_get_num_files(zip);\n\n\t\tFileRecord frec;\n\t\tfrec.zip = zip;\n\n\t\tmz_uint mapped_count = 0;\n\t\tfor (mz_uint fi = 0; fi < filecount; ++fi) {\n\t\t\tmz_zip_archive_file_stat fistat;\n\t\t\tmz_zip_reader_file_stat(zip, fi, &fistat);\n\n\t\t\tstd::string fname = fistat.m_filename;\n\t\t\tif (!sanitizeZipEntryName(fname)) {\n\t\t\t\tLog(LOG_WARNING) << \"Bogus filename \" << hexDumpBogusData(fname) << \" in \" << zippath << \", ignoring.\";\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tstd::string relfname = fname;\n\t\t\tif (fistat.m_is_encrypted || !fistat.m_is_supported) { continue; }\n\t\t\tif (fistat.m_is_directory) { continue; }\n\t\t\tif (fname.size() <= prefixlen) { continue; }\n\t\t\tif (prefixlen > 0) { // well, cut out the prefix to get the real relfname.\n\t\t\t\tauto tprefix = fname.substr(0, prefixlen);\n\t\t\t\tif (tprefix != prefix) { continue; }\n\t\t\t\trelfname = fname.substr(prefixlen, fname.npos);\n\t\t\t}\n\t\t\tfrec.findex = fi;\n\t\t\tfrec.fullpath = concatPaths(fullpath, fname);\n\n\t\t\tif (isRuleset(relfname) && ignore_ruls) { continue; }\n\t\t\tinsert(relfname, frec);\n\t\t\tmapped_count ++;\n\t\t}\n\t\tLog(LOG_VERBOSE) << log_ctx << \"mapped_count=\" << mapped_count;\n\t\treturn mapped_count > 1;\n\t}\n\tbool mapPlainDir(const std::string& dirpath, bool ignore_ruls = false) {\n\t\tstd::string log_ctx = \"mapPlainDir(\" + dirpath + \", \" + (ignore_ruls ? \"true\" : \"false\") + \"): \";\n\t\tif (mapped) {\n\t\t\tauto err = log_ctx + \"fatal: already mapped.\";\n\t\t\tLog(LOG_FATAL) << err;\n\t\t\tthrow Exception(err);\n\t\t}\n\t\tdirlist_t dlist;\n\t\tif (!ls_r(dirpath, \"\", dlist)) {\n\t\t\treturn false;\n\t\t}\n\t\tfullpath = dirpath;\n\t\tFileRecord frec;\n\t\tfrec.zip = NULL;\n\t\tstd::string relpath;\n\t\tint mapped_count = 0;\n\t\tfor (auto i = dlist.cbegin(); i != dlist.cend(); ++i) {\n\t\t\trelpath = concatOptionalPaths(i->first, i->second);\n\t\t\tfrec.fullpath = concatPaths(fullpath, relpath);\n\t\t\tif (isRuleset(i->second) && ignore_ruls) { continue; }\n\t\t\tinsert(relpath, frec);\n\t\t\tmapped_count ++;\n\t\t}\n\t\treturn mapped_count > 1;\n\t}\n\tvoid dump(std::ostream &out, const std::string &prefix, bool verbose) {\n\t\tout << prefix << \"origin: \" << fullpath << \"; \" << resources.size()\n\t\t\t\t\t\t << \" resources, \" << rulesets.size() << \" rulesets\";\n\t\tif (verbose) {\n\t\t\tfor (auto l = resources.begin(); l != resources.end(); ++l) {\n\t\t\t\tout << prefix << \"    \" << l->first << \" -> \" << l->second.fullpath;\n\t\t\t}\n\t\t}\n\t}\n};\nstruct VFSLayerStack {\n\tstd::vector<VFSLayer *> layers;\n\tFileSet resources;\n\tstd::vector<FileRecord> rulesets;\n\tstd::unordered_map<std::string, NameSet> vdirs;\n\n\tVFSLayerStack() : layers(), resources(), rulesets(), vdirs() { }\n\n\tvoid clear() {\n\t\tlayers.clear(); \t// not deleting them, they're owned by VFSLayerSet\n\t\tresources.clear();\n\t\trulesets.clear();\n\t\tvdirs.clear();\n\t}\n\tvoid _merge_vdirs(VFSLayer *src) {\n\t\tauto src_vdirs = src->vdirs;\n\t\tfor (auto i = src_vdirs.begin(); i != src_vdirs.end(); ++i) {\n\t\t\tauto vdi = vdirs.find(i->first);\n\t\t\tif (vdi == vdirs.end()) {\n\t\t\t\tvdirs.insert(*i);\n\t\t\t} else {\n\t\t\t\tfor (auto ni = i->second.begin(); ni != i->second.end(); ++ni) {\n\t\t\t\t\tvdi->second.insert(*ni);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tvoid _merge_resources(VFSLayer *src, bool reverse) {\n\t\tfor (auto ri = src->resources.begin(); ri != src->resources.end(); ++ri) {\n\t\t\tauto crelpath = ri->first;\n\t\t\tauto frec = ri->second;\n\t\t\tauto existing = resources.find(crelpath);\n\t\t\tif ((!reverse) && (existing != resources.end())) { resources.erase(existing); }\n\t\t\tresources.insert(std::make_pair(crelpath, frec));\n\t\t}\n\t}\n\tvoid push_back(VFSLayer *layer) {\n\t\tlayers.push_back(layer);\n\t\tauto ruls = layer->rulesets;\n\t\tfor (auto i = ruls.begin(); i != ruls.end(); ++i) {\n\t\t\trulesets.push_back(*i);\n\t\t}\n\t\t_merge_vdirs(layer);\n\t\t_merge_resources(layer, false);\n\t}\n\tvoid push_front(VFSLayer *layer) {\n\t\tlayers.insert(layers.begin(), layer);\n\t\tauto ruls = layer->rulesets;\n\t\tfor (auto i = ruls.rbegin(); i != ruls.rend(); ++i) {\n\t\t\trulesets.insert(rulesets.begin(), *i);\n\t\t}\n\t\t_merge_vdirs(layer);\n\t\t_merge_resources(layer, true);\n\t}\n\tconst FileRecord *at(const std::string& relpath) {\n\t\tauto crelpath = canonicalize(relpath);\n\t\tauto it = resources.find(crelpath);\n\t\treturn (it == resources.end()) ? NULL : &it->second;\n\t}\n\tconst NameSet& ls(const std::string& relpath) {\n\t\tauto crelpath = canonicalize(relpath);\n\t\twhile (crelpath.size() > 0 && crelpath[crelpath.size() - 1] == '/') {\n\t\t\tcrelpath.resize(crelpath.size() - 1);\n\t\t}\n\t\tauto it = vdirs.find(crelpath);\n\t\treturn (it == vdirs.end()) ? emptySet : it->second;\n\t}\n\tconst std::vector<const FileRecord *> get_slice(const std::string& relpath) {\n\t\tstd::vector<const FileRecord *> rv;\n\t\tauto crelpath = canonicalize(relpath);\n\t\tfor (auto si = layers.begin(); si != layers.end(); ++si) {\n\t\t\trv.push_back((*si)->at(crelpath));\n\t\t}\n\t\treturn rv;\n\t}\n\tconst std::vector<FileRecord> &getRulesets() { return rulesets; }\n\tvoid dump(std::ostream& out, const std::string& prefix, bool verbose) {\n\t\tfor (size_t i = 0; i < layers.size(); ++i) {\n\t\t\tstd::ostringstream subprefix;\n\t\t\tsubprefix << prefix << \"    layer \" << i << \": \";\n\t\t\tlayers[i]->dump(out, subprefix.str(), verbose);\n\t\t}\n\t}\n};\n// each mod is also a (sub)set of layers\nstruct ModRecord {\n\tModInfo modInfo;\n\tVFSLayerStack stack;\n\n\tModRecord(const std::string& somepath) : modInfo(somepath), stack() { }\n\tvoid push_back(VFSLayer *layer) { stack.push_back(layer); }\n\tvoid push_front(VFSLayer *layer) { stack.push_front(layer); }\n\tconst FileRecord *at(const std::string& relpath) { return stack.at(relpath); }\n\tconst NameSet& ls(const std::string& relpath) { return stack.ls(relpath); }\n\tconst std::vector<FileRecord> &getRulesets() { return stack.getRulesets(); }\n\tvoid dump(std::ostream& out, const std::string& prefix, bool verbose) {\n\t\tout << \"  modId=\" << modInfo.getId() << \"; \" << stack.layers.size() << \" layers\";\n\t\tstack.dump(out, prefix, verbose);\n\t}\n};\n\nstatic bool mapExtResources(ModRecord *, const std::string&, bool embeddedOnly);\n\n// the final VFS view is a set of layers too.\nstruct VFS {\n\tstd::vector<ModRecord *> mods;\n\tVFSLayerStack stack;\n\tRSOrder rsorder;\n\n\tVFS() : mods(), stack(), rsorder() { }\n\tconst RSOrder &get_rulesets() { return rsorder; }\n\tconst std::vector<const FileRecord *> get_slice(const std::string& relpath) { return stack.get_slice(relpath); }\n\tconst FileRecord *at(const std::string& relpath) { return stack.at(relpath); }\n\tconst NameSet& ls(const std::string& relpath) { return stack.ls(relpath); }\n\tconst NameSet& lslayer(const std::string& relpath, size_t level) {\n\t\tif (level >= stack.layers.size()) { level = stack.layers.size() - 1; }\n\t\treturn stack.layers[level]->ls(relpath);\n\t}\n\tvoid push_back(ModRecord *mod) {\n\t\tmods.push_back(mod);\n\t\tauto layers = mod->stack.layers;\n\t\tfor (auto i = layers.begin(); i != layers.end(); ++i) {\n\t\t\tstack.push_back(*i);\n\t\t}\n\t\tauto rulesets = mod->getRulesets();\n\t\tauto modId = mod->modInfo.getId();\n\t\t// \ttypedef std::vector<std::pair<std::string, std::vector<FileRecord *>>> RSOrder;\n\t\trsorder.push_back(std::make_pair(modId, rulesets));\n\t}\n\tvoid map_common(bool embeddedOnly) {\n\t\tauto mrec = std::make_unique<ModRecord>(\"common\");\n\t\tif (!mapExtResources(mrec.get(), \"common\", embeddedOnly)) {\n\t\t\tLog(LOG_ERROR) << \"VFS::map_common(): failed to map 'common'\";\n\t\t\treturn;\n\t\t}\n\t\tfor (auto layer: mrec->stack.layers) {\n\t\t\tstack.push_back(layer);\n\t\t}\n\t}\n\tvoid clear() {\n\t\trsorder.clear();\n\t\tmods.clear();\n\t\tstack.clear();\n\t}\n\tvoid dump(std::ostream& out, const std::string& prefix, bool verbose) {\n\t\tstack.dump(out, prefix, verbose);\n\t}\n};\n\nstatic std::unordered_map<std::string, ModRecord *> ModsAvailable;\nstatic std::unordered_set<VFSLayer *> MappedVFSLayers; // owned here so we can have some sense of their lifetime\n\t\t\t\t\t\t\t\t\t\t\t\t\t   // only the layers that get dropped on FileMap::clear()\nstatic std::vector<mz_zip_archive *> ZipContexts;\t   // zip decompression contexts shared between layers that came from\n\t\t\t\t\t\t\t\t\t\t\t\t\t   // the same .zip. this makes the whole thing very thread-unsafe\nstatic VFS TheVFS;\n\nstatic VFSLayer* MappedVFSLayersAdd(std::unique_ptr<VFSLayer>&& layer)\n{\n\tauto [it, ok] = MappedVFSLayers.insert(layer.get());\n\tif (ok) {\n\t\treturn layer.release();\n\t}\n\n\tthrow Exception(\"MappedVFSLayersAdd(): fail\");\n}\nstatic void ModsAvailableAdd(std::unique_ptr<ModRecord>&& mrec)\n{\n\tauto [it, ok] = ModsAvailable.insert(std::make_pair(mrec->modInfo.getId(), mrec.get()));\n\tif (ok) {\n\t\tmrec.release();\n\t\treturn;\n\t}\n\n\tthrow Exception(\"ModsAvailableAdd(): fail\");\n}\n\nconst RSOrder &getRulesets() { return TheVFS.get_rulesets(); }\n\nstatic mz_zip_archive *newZipContext(const std::string& log_ctx, SDL_RWops *rwops) {\n\tmz_zip_archive *zip = (mz_zip_archive *) SDL_malloc(sizeof(mz_zip_archive));\n\tif (!zip) {\n\t\tLog(LOG_FATAL) << log_ctx << \": \" << SDL_GetError();\n\t\tthrow Exception(\"Out of memory\");\n\t}\n\tif (!mz_zip_reader_init_rwops(zip, rwops)) {\n\t\t// whoa, no opening the file\n\t\tLog(LOG_WARNING) << log_ctx << \"Ignoring zip: \" << mz_zip_get_error_string(mz_zip_get_last_error(zip));\n\t\tSDL_RWclose(rwops);\n\t\tSDL_free(zip);\n\t\treturn NULL;\n\t}\n\tZipContexts.push_back(zip);\n\treturn zip;\n}\n\nvoid clear(bool clearOnly, bool embeddedOnly) {\n\tTheVFS.clear();\n\tfor (auto i : ModsAvailable ) { delete i.second; }\n\tModsAvailable.clear();\n\tfor (auto i : MappedVFSLayers ) { delete i; }\n\tMappedVFSLayers.clear();\n\tfor (auto i : ZipContexts) { mz_zip_reader_end_rwops(i); SDL_free(i); }\n\tZipContexts.clear();\n\tif (!clearOnly)\n\t{\n\t\tLog(LOG_VERBOSE) << \"FileMap::clear(): mapping 'common'\";\n\t\tTheVFS.map_common(embeddedOnly);\n\t\tif (LOG_VERBOSE <= Logger::reportingLevel()) {\n\t\t\tTheVFS.dump(Logger().get(LOG_VERBOSE), \"\\nFileMap::clear():\", Options::oxceListVFSContents);\n\t\t}\n\t}\n}\n/**\n * This maps mods and their dependencies.\n * Dependencies' existence is checked in checkModsDependencies()\n * @param active - mods that are to be loaded.\n * \t\tit is supposedly the list of enabled mods in the order they\n * \t\tappear in the options screen. and with only a single master.\n * \t\twhich nonetheless can itself depend on another master and so on.\n*/\nvoid setup(const std::vector<const ModInfo* >& active, bool embeddedOnly)\n{\n\tTheVFS.clear();\n\tTheVFS.map_common(embeddedOnly);\n\tstd::string log_ctx = \"FileMap::setup(): \";\n\n\tLog(LOG_VERBOSE) << log_ctx << \"Active mods per options:\";\n\tfor (auto i = active.cbegin(); i != active.cend(); ++i) {\n\t\tLog(LOG_VERBOSE) << log_ctx << \"    \" << (*i)->getId();\n\t}\n\t// expand the mod list into map order\n\t// listing all the mod dependencies\n\tstd::vector<std::string> map_order;\n\tfor (auto i = active.begin(); i != active.end(); ++i) {\n\t\tstd::string currentId = (*i)-> getId();\n\t\tstd::string masterId;\n\t\tauto insert_before = map_order.end();\n\t\twhile (true) {\n\t\t\tinsert_before = map_order.insert(insert_before, currentId);\n\t\t\tmasterId = ModsAvailable.find(currentId)->second->modInfo.getMaster();\n\t\t\tif (masterId.empty()) { break; }\n\t\t\tcurrentId = masterId;\n\t\t}\n\t}\n\t// map the mods skipping duplicates\n\t// this will preserve the order.\n\tstd::unordered_set<std::string> mods_seen;\n\tfor (auto i = map_order.begin(); i !=  map_order.end(); ++i) {\n\t\tif (mods_seen.find(*i) != mods_seen.end()) { continue; }\n\t\tmods_seen.insert(*i);\n\t\tTheVFS.push_back( ModsAvailable.at(*i));\n\t}\n\tLog(LOG_VERBOSE) << log_ctx << \"Active VFS stack:\";\n\tif (LOG_VERBOSE <= Logger::reportingLevel()) {\n\t\tTheVFS.dump(Logger().get(LOG_VERBOSE), \"\\n\" + log_ctx, Options::oxceListVFSContents);\n\t}\n}\n[[gnu::unused]]\nstatic void dump_mods_layers(std::ostream &out, const std::string& prefix, bool verbose) {\n\tout << prefix << ModsAvailable.size() << \" mods mapped:\";\n\tfor (auto i = ModsAvailable.begin(); i != ModsAvailable.end(); ++i) {\n\t\ti->second->dump(out, prefix + \"  \", verbose);\n\t}\n\tout << prefix << MappedVFSLayers.size() << \" layers mapped:\";\n\tfor (auto i = MappedVFSLayers.begin(); i != MappedVFSLayers.end(); ++i) {\n\t\t(*i)->dump(out, prefix + \"  \", verbose);\n\t}\n}\n/**\n * Attempts to map extResources and insert the resulting layers into a mod\n * @param mrec - ModRec of a mod\n * @param basename - extRes name to map (from userDir/dataDir)\n */\nstatic bool mapExtResources(ModRecord *mrec, const std::string& basename, bool embeddedOnly) {\n\tauto modId = mrec->modInfo.getId();\n\tstd::string log_ctx = \"FileMap::mapExtResources(\" + modId + \", \" + basename + \"): \";\n\tbool mapped_anything = false;\n\tstd::string zipname = basename + \".zip\";\n\tSDL_RWops *embedded_rwops = NULL;\n\tif (zipname == \"common.zip\" || zipname == \"standard.zip\") {\n\t\tembedded_rwops = CrossPlatform::getEmbeddedAsset(zipname);\n\t}\n\t// first try finding a directory (ass-backwards since we got to push this into front re layers.\n\tif (!embedded_rwops || ! embeddedOnly) {\n\t\tstd::string fullname = Options::getUserFolder() + basename;\n\t\tif (!CrossPlatform::folderExists(fullname)) {\n\t\t\tfullname = CrossPlatform::searchDataFolder(basename);\n\t\t}\n\t\tif (CrossPlatform::folderExists(fullname)) {\n\t\t\tLog(LOG_VERBOSE) << log_ctx << \"found dir (\"<<fullname<<\")\";\n\t\t\tauto layer = std::make_unique<VFSLayer>(fullname);\n\t\t\tif (layer->mapPlainDir(fullname, true)) {\n\t\t\t\tmrec->push_front(MappedVFSLayersAdd(std::move(layer)));\n\t\t\t\tmapped_anything = true;\n\t\t\t}\n\t\t} else {\n\t\t\tLog(LOG_VERBOSE) << log_ctx << \"dir not found (\"<<fullname<<\")\";\n\t\t}\n\t}\n\t// then try finding a zipfile\n\tif (!embedded_rwops || ! embeddedOnly) {\n\t\tstd::string fullname = Options::getUserFolder() + zipname;\n\t\tif (!CrossPlatform::fileExists(fullname)) {\n\t\t\tfullname = CrossPlatform::searchDataFile(zipname);\n\t\t}\n\t\tif (CrossPlatform::fileExists(fullname)) {\n\t\t\tLog(LOG_VERBOSE) << log_ctx << \"found zip (\"<<fullname<<\")\";\n\t\t\tauto layer = std::make_unique<VFSLayer>(fullname);\n\t\t\tauto mapped = layer->mapZipFile(fullname, basename + \"/\", true);\n\t\t\tif (!mapped) {\n\t\t\t\t// some garbage can stay in `layer` after failed mapping, clean up and try different path\n\t\t\t\tlayer = std::make_unique<VFSLayer>(fullname);\n\t\t\t\tmapped = layer->mapZipFile(fullname, \"\", true);\n\t\t\t}\n\t\t\tif (mapped) {\n\t\t\t\tmrec->push_front(MappedVFSLayersAdd(std::move(layer)));\n\t\t\t\tmapped_anything = true;\n\t\t\t}\n\t\t} else {\n\t\t\tLog(LOG_VERBOSE) << log_ctx << \"zip not found (\"<<fullname<<\")\";\n\t\t}\n\t}\n\t// now try the embedded zip\n\t{\n\t\tif (embedded_rwops) {\n\t\t\tLog(LOG_VERBOSE) << log_ctx << \"found embedded asset (\"<<zipname<<\")\";\n\t\t\tstd::string ezipname = \"exe:\" + zipname;\n\t\t\tauto layer = std::make_unique<VFSLayer>(ezipname);\n\t\t\tif (layer->mapZipFileRW(embedded_rwops, ezipname, \"\", true)) {\n\t\t\t\tmrec->push_front(MappedVFSLayersAdd(std::move(layer)));\n\t\t\t\tmapped_anything = true;\n\t\t\t}\n\t\t} else {\n\t\t\tLog(LOG_VERBOSE) << log_ctx << \"embedded asset not found (\"<<zipname<<\")\";\n\t\t}\n\t}\n\tif (!mapped_anything) { // well, nothing found. say so.\n\t\tLog(LOG_INFO) << log_ctx << \"external resources not found.\";\n\t}\n\treturn mapped_anything;\n}\n/** Map a mod in a given .zip with a given prefix\n * @param zipfname  - full path to the .zip_open\n * @param prefix    - prefix (subdir) in the .zip if any\n */\nstatic void mapZippedMod(mz_zip_archive *zip, const std::string& zipfname, const std::string& prefix) {\n\tstd::string log_ctx = \"mapZippedMod(\" + zipfname + \", '\" + prefix + \"'): \";\n\tauto layer = std::make_unique<VFSLayer>(concatPaths(zipfname, prefix));\n\tif (!layer->mapZip(zip, zipfname, prefix)) {\n\t\tLog(LOG_WARNING) << log_ctx << \"Failed to map, skipping.\";\n\t\treturn;\n\t}\n\tauto frec = layer->at(\"metadata.yml\");\n\tif (frec == NULL) { // whoa, no metadata\n\t\tLog(LOG_WARNING) << log_ctx << \"No metadata.yml found, skipping.\";\n\t\treturn;\n\t}\n\tauto modpath = concatOptionalPaths(zipfname, prefix);\n\tconst auto& reader = frec->getYAML();\n\tif (!reader.isMap()) {\n\t\tLog(LOG_WARNING) << log_ctx << \"Bad metadata.yml found, skipping.\";\n\t\treturn;\n\t}\n\tauto mrec = std::make_unique<ModRecord>(modpath);\n\tmrec->modInfo.load(reader);\n\tauto mri = ModsAvailable.find(mrec->modInfo.getId());\n\tif (mri != ModsAvailable.end()) {\n\t\tLog(LOG_ERROR) << log_ctx << \"modId \" << mrec->modInfo.getId() << \" already mapped in, skipping \" << modpath;\n\t\treturn;\n\t}\n\tLog(LOG_VERBOSE) << log_ctx << \"mapped mod '\" << mrec->modInfo.getId() << \"' from \" << modpath\n\t\t\t\t\t << \" master=\" << mrec->modInfo.getMaster() << \" version=\" << mrec->modInfo.getVersion();\n\tmrec->push_back(MappedVFSLayersAdd(std::move(layer)));\n\tModsAvailableAdd(std::move(mrec));\n}\n/** now this scans a zip of mods or of a single mod\n * @param rwops - SDL_RWops to the zip data\n * @param fullpath - full path to associate with the .zip.\n */\nvoid scanModZipRW(SDL_RWops *rwops, const std::string& fullpath) {\n\tstd::string log_ctx = \"scanModZipRW(rwops, \" + fullpath + \"): \";\n\tmz_zip_archive *mzip = newZipContext(log_ctx, rwops);\n\n\tif (!mzip) { return; }\n\t// check if this is maybe a zip of a single mod (metadata.yml at the top level)\n\tif (mz_zip_reader_locate_file_v2(mzip, \"metadata.yml\", NULL, 0, NULL)) {\n\t\tLog(LOG_VERBOSE) << log_ctx << \"retrying as a single-mod .zip\";\n\t\t// FIXME: this doesn't seem to work at all... do we support this?\n\t\tmapZippedMod(mzip, fullpath, \"\");\n\t\treturn;\n\t}\n\tmz_uint filecount = mz_zip_reader_get_num_files(mzip);\n\tfor (mz_uint fi = 0; fi < filecount; ++fi) {\n\t\tmz_zip_archive_file_stat fistat;\n\t\tmz_zip_reader_file_stat(mzip, fi, &fistat);\n\t\tif (fistat.m_is_encrypted || !fistat.m_is_supported) { continue; }\n\t\tif (!fistat.m_is_directory) { continue; } // skip files, we're only interested in toplevel dirs.\n\t\tstd::string prefix = fistat.m_filename;\n\t\tif (!sanitizeZipEntryName(prefix)) {\n\t\t\tLog(LOG_WARNING) << \"Bogus dirname \" << hexDumpBogusData(prefix) << \" in \" << fullpath << \", ignoring.\";\n\t\t\tcontinue;\n\t\t}\n\t\tauto slashpos = prefix.find_first_of(\"/\"); // miniz returns dirnames with trailing slashes\n\t\tif (slashpos != prefix.size() - 1) { continue; } // not top-level: skip.\n\t\t// FIXME: if Microsoft Windows \"Send to > Compressed (zipped) folder\" is used to create the ZIP archive,\n\t\t// this will never be called, because the top-level directory is NOT on the file list... yes, seriously, I'm not kidding!\n\t\t// Do we want to handle this somehow or do we just call it unsupported?\n\t\tmapZippedMod(mzip, fullpath, prefix);\n\t}\n}\n/** Filesystem wrapper for scanModZipRW()\n * @param fullpath - full path to the .zip.\n */\nvoid scanModZip(const std::string& fullpath) {\n\tstd::string log_ctx = \"scanModZip(\" + fullpath + \"): \";\n\tSDL_RWops *rwops = SDL_RWFromFile(fullpath.c_str(), \"r\");\n\tif (!rwops) {\n\t\tLog(LOG_WARNING) << log_ctx << \"Ignoring zip: \" << SDL_GetError();\n\t\treturn;\n\t}\n\tscanModZipRW(rwops, fullpath);\n}\n/**\n * Extracts a single file to an ConstMem RWops object\n * @param rwops - .zip file\n * @param fullpath - what to extract, case and slash - insensitive\n */\nSDL_RWops *zipGetFileByName(const std::string& zipfile, const std::string& fullpath) {\n\tstd::string log_ctx = \"zipGetFileByName(rwops, \" + zipfile + \", \" + fullpath + \"): \";\n\tstd::string sanpath = fullpath;\n\tif (!sanitizeZipEntryName(sanpath)) {\n\t\tLog(LOG_ERROR) << log_ctx << \"Bogus fullpath given: '\" << fullpath << \"': \" << hexDumpBogusData(sanpath);\n\t\treturn NULL;\n\t}\n\tUnicode::lowerCase(sanpath);\n\tSDL_RWops *rwops = SDL_RWFromFile(zipfile.c_str(), \"rb\");\n\tif (!rwops) {\n\t\tLog(LOG_ERROR) << log_ctx << \"SDL_RWFromFile(): \" << SDL_GetError();\n\t\treturn NULL;\n\t}\n\tmz_zip_archive *mzip = (mz_zip_archive *) SDL_malloc(sizeof(mz_zip_archive));\n\tif (!mzip) {\n\t\tLog(LOG_FATAL) << log_ctx << \": \" << SDL_GetError();\n\t\tthrow Exception(\"Out of memory\");\n\t}\n\tif (!mz_zip_reader_init_rwops(mzip, rwops)) {\n\t\tLog(LOG_ERROR) << log_ctx << \"Bad zip: \" << mz_zip_get_error_string(mz_zip_get_last_error(mzip));\n\t\tSDL_RWclose(rwops);\n\t\tSDL_free(mzip);\n\t\treturn NULL;\n\t}\n\tmz_uint filecount = mz_zip_reader_get_num_files(mzip);\n\tfor (mz_uint fi = 0; fi < filecount; ++fi) {\n\t\tmz_zip_archive_file_stat fistat;\n\t\tmz_zip_reader_file_stat (mzip, fi, &fistat);\n\t\tif (fistat.m_is_encrypted || !fistat.m_is_supported) {\n\t\t\tcontinue;\n\t\t}\n\t\tif (fistat.m_is_directory) {\n\t\t\tcontinue;    // skip directories\n\t\t}\n\t\tstd::string somepath = fistat.m_filename;\n\t\tif ( !sanitizeZipEntryName ( somepath ) ) {\n\t\t\tLog(LOG_WARNING) << \"Bogus filename '\" << somepath << \"' \"\n\t\t\t\t\t\t\t << hexDumpBogusData(somepath) << \" in the .zip, ignoring.\";\n\t\t\tcontinue;\n\t\t}\n\t\tUnicode::lowerCase(somepath);\n\t\tif (sanpath == somepath) { // gotcha\n\t\t\tSDL_RWops *rv = SDL_RWFromMZ(mzip, fi);\n\t\t\tif (!rv) {\n\t\t\t\tLog(LOG_ERROR) << log_ctx << \"Unzip failed: \" << SDL_GetError();\n\t\t\t}\n\t\t\tmz_zip_reader_end(mzip);\n\t\t\tSDL_RWclose(rwops);\n\t\t\tSDL_free(mzip);\n\t\t\treturn rv;\n\t\t}\n\t}\n\tLog ( LOG_ERROR ) << log_ctx << \"File not found in the .zip\";\n\tmz_zip_reader_end(mzip);\n\tSDL_RWclose(rwops);\n\tSDL_free(mzip);\n\treturn NULL;\n}\n/**\n * this scans a mod dir.\n * which by definition is either a .zip\n * or a directory of zips and dirs.\n *\n * @param dirname - is either the datadir or the userdir\n * @param basename is then either 'standard' or 'mods'\n *\n * yes you can have mods.zip in userdir.\n * you can also have multimod zips in user/mods (and standard/mods too)\n *\n * and yes this has to parse the metadata.yml for the modId.\n *\n */\nvoid scanModDir(const std::string& dirname, const std::string& basename, bool protectedLocation) {\n\n\t// \"standard\" directory is for built-in mods only! otherwise automatic updates would delete user data\n\tconst static std::set<std::string> standardMods = {\n\t\t\"Aliens_Pick_Up_Weapons\",\n\t\t\"Aliens_Pick_Up_Weapons_TFTD\",\n\t\t\"Demigod_Difficulty\",\n\t\t\"Demigod_Difficulty_TFTD\",\n\t\t\"Limit_Craft_Item_Capacities\",\n\t\t\"Limit_Craft_Item_Capacities_TFTD\",\n\t\t\"OpenXCom_Unlimited_Waypoints\",\n\t\t\"OpenXCom_Unlimited_Waypoints_TFTD\",\n\t\t\"PSX_Static_Cydonia_Map\",\n\t\t\"Smarter_Equip\",\n\t\t\"Smarter_Equip_TFTD\",\n\t\t\"StrategyCore_Swap_Small_USOs_TFTD\",\n\t\t\"TFTD_Damage\",\n\t\t\"UFOextender_Gun_Melee\",\n\t\t\"UFOextender_Gun_Melee_TFTD\",\n\t\t\"UFOextender_Psionic_Line_Of_Fire\",\n\t\t\"UFOextender_Psionic_Line_Of_Fire_TFTD\",\n\t\t\"UFOextender_Starting_Avalanches\",\n\t\t\"xcom1\",\n\t\t\"xcom2\",\n\t\t\"XcomUtil_Always_Daytime\",\n\t\t\"XcomUtil_Always_Daytime_TFTD\",\n\t\t\"XcomUtil_Always_Nighttime\",\n\t\t\"XcomUtil_Always_Nighttime_TFTD\",\n\t\t\"XcomUtil_Fighter_Transports\",\n\t\t\"XcomUtil_Fighter_Transports_TFTD\",\n\t\t\"XcomUtil_High_Explosive_Damage\",\n\t\t\"XcomUtil_High_Explosive_Damage_TFTD\",\n\t\t\"XcomUtil_Improved_Gauss\",\n\t\t\"XcomUtil_Improved_Ground_Tanks\",\n\t\t\"XcomUtil_Improved_Heavy_Laser\",\n\t\t\"XcomUtil_Infinite_Gauss\",\n\t\t\"XcomUtil_No_Psionics\",\n\t\t\"XcomUtil_No_Psionics_TFTD\",\n\t\t\"XcomUtil_Pistol_Auto_Shot\",\n\t\t\"XcomUtil_Pistol_Auto_Shot_TFTD\",\n\t\t\"XcomUtil_Skyranger_Weapon_Slot\",\n\t\t\"XcomUtil_Starting_Defensive_Base\",\n\t\t\"XcomUtil_Starting_Defensive_Base_TFTD\",\n\t\t\"XcomUtil_Starting_Defensive_Improved_Base\",\n\t\t\"XcomUtil_Starting_Defensive_Improved_Base_TFTD\",\n\t\t\"XcomUtil_Starting_Improved_Base\",\n\t\t\"XcomUtil_Starting_Improved_Base_TFTD\",\n\t\t\"XcomUtil_Statstrings\",\n\t\t\"XcomUtil_Statstrings_TFTD\",\n\t\t\"XcomUtil_Triton_Weapon_Slot\",\n\t\t\"XCOM_Damage\"\n\t};\n\n\tstd::string log_ctx = \"scanModDir('\" + dirname + \"', '\" + basename + \"'): \";\n\t// first check for a .zip\n\tstd::string fullname = dirname + basename + \".zip\";\n\tif (CrossPlatform::fileExists(fullname)) {\n\t\tLog(LOG_VERBOSE) << log_ctx << \"scanning zip \" << fullname;\n\t\tscanModZip(fullname);\n\t} else {\n\t\tLog(LOG_VERBOSE) << log_ctx << \"no zip \" << fullname;\n\t}\n\t// then check for a dir\n\tfullname = dirname  + basename;\n\tif (!CrossPlatform::folderExists(fullname)) {\n\t\tLog(LOG_VERBOSE) << log_ctx << \"no dir \" << fullname;\n\t\treturn;\n\t}\n\tLog(LOG_VERBOSE) << log_ctx << \"scanning dir \" << fullname;\n\n\t// now this dir can contain both moddirs and modzips.\n\t// first scan for modzips : that is, anything but a directory\n\tauto contents = CrossPlatform::getFolderContents(fullname);\n\tstd::vector<std::string> dirlist;\n\tfor (auto zi = contents.begin(); zi != contents.end(); ++zi) {\n\t\tauto is_dir =  std::get<1>(*zi);\n\t\tif (is_dir) {\n\t\t\tif (protectedLocation)\n\t\t\t{\n\t\t\t\tif (standardMods.find(std::get<0>(*zi)) == standardMods.end())\n\t\t\t\t{\n\t\t\t\t\tLog(LOG_ERROR) << \"Invalid standard mod '\" << std::get<0>(*zi) << \"', skipping.\";\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\tdirlist.push_back(std::get<0>(*zi)); // stash for later\n\t\t\tcontinue;\n\t\t}\n\t\tif (protectedLocation)\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"Invalid standard mod '\" << std::get<0>(*zi) << \"', skipping.\";\n\t\t\tcontinue;\n\t\t}\n\t\tauto subpath = concatPaths(fullname, std::get<0>(*zi));\n\t\tscanModZip(subpath);\n\t}\n\tfor (auto di = dirlist.begin(); di != dirlist.end(); ++di) {\n\t\tauto mp_basename = *di;\n\t\tauto modpath = concatPaths(fullname, mp_basename);\n\t\t// map dat dir! (if it has metadata.yml, naturally)\n\t\tauto layer = std::make_unique<VFSLayer>(modpath);\n\t\tif (!layer->mapPlainDir(modpath)) {\n\t\t\tLog(LOG_WARNING) << log_ctx << \"Can't scan \" << mp_basename << \", skipping.\";\n\t\t\tcontinue;\n\t\t}\n\t\tauto frec = layer->at(\"metadata.yml\");\n\t\tif (frec == NULL) { // whoa, no metadata\n\t\t\tLog(LOG_WARNING) << log_ctx << \"No metadata.yml in \" << mp_basename << \", skipping.\";\n\t\t\tcontinue;\n\t\t}\n\t\tconst auto& reader = frec->getYAML();\n\t\tif (!reader.isMap()) {\n\t\t\tLog(LOG_WARNING) << log_ctx << \"Bad metadata.yml \" << mp_basename << \", skipping.\";\n\t\t\treturn;\n\t\t}\n\t\tauto mrec = std::make_unique<ModRecord>(modpath);\n\t\tmrec->modInfo.load(reader);\n\t\tauto mri = ModsAvailable.find(mrec->modInfo.getId());\n\t\tif (mri != ModsAvailable.end()) {\n\t\t\tLog(LOG_ERROR) << log_ctx << \"modId \" << mrec->modInfo.getId() << \" already mapped in, skipping \" << mp_basename;\n\t\t\tcontinue;\n\t\t}\n\t\tLog(LOG_VERBOSE) << log_ctx << \"modId \" << mrec->modInfo.getId() << \" mapped in from \" << mp_basename;\n\t\tmrec->push_back(MappedVFSLayersAdd(std::move(layer)));\n\t\tModsAvailableAdd(std::move(mrec));\n\t}\n}\n/**\n * A helper that drops listed mods and dependent ones.\n * @param log_ctx ~\n * @param drop_list mods to drop (mutated and then cleared)\n */\nstatic void drop_mods(const std::string& log_ctx, std::unordered_set<std::string>& drop_list) {\n\tbool dropped_something = true;\n\twhile(dropped_something) {\n\t\tdropped_something = false;\n\t\tfor (auto mri = ModsAvailable.begin(); mri != ModsAvailable.end(); ++mri) {\n\t\t\tauto modId = mri->first;\n\t\t\tauto mrec = mri->second;\n\t\t\tif (drop_list.find(modId) != drop_list.end()) { // already dropped.\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tauto masterId = mrec->modInfo.getMaster();\n\t\t\tif (drop_list.find(masterId) != drop_list.end()) {\n\t\t\t\tLog(LOG_DEBUG) << log_ctx << \"Dropping mod \" << modId << \": depends \" << masterId;\n\t\t\t\tdrop_list.insert(modId);\n\t\t\t\tdropped_something = true;\n\t\t\t}\n\t\t}\n\t}\n\tfor (auto ki = drop_list.begin(); ki != drop_list.end(); ++ki) {\n\t\tdelete ModsAvailable.at(*ki);\n\t\tModsAvailable.erase(*ki);\n\t}\n\tdrop_list.clear();\n}\n/**\n * Enforces mod list sanity:\n * \t- breaks circular dependency loops\n *  - removes mods that miss their extResources or masters\n */\nvoid checkModsDependencies() {\n\tstd::string log_ctx = \"checkModsDependencies(): \";\n\tLog(LOG_VERBOSE) << log_ctx << \"called.\";\n\tstd::unordered_set<std::string> drop_list;\n\n\t// break circular dependency loops.\n\tfor (auto mri = ModsAvailable.begin(); mri != ModsAvailable.end(); ++mri) {\n\t\tauto started_at = mri->first;\n\t\tauto current = started_at;\n\t\twhile(true) {\n\t\t\tauto masterId = ModsAvailable.at(current)->modInfo.getMaster();\n\t\t\tif (masterId.empty()) { break; } \t\t\t\t\t\t\t// no loop here, move along.\n\t\t\tif (drop_list.find(masterId) != drop_list.end()) { break; } // this loop is already broken\n\t\t\tif ( ModsAvailable.find(masterId) == ModsAvailable.end()) {\t\t\t\t// master missing\n\t\t\t\tLog(LOG_WARNING) << log_ctx << current << \": missing master mod \" << masterId;\n\t\t\t\tdrop_list.insert(started_at);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (masterId == started_at) { \t\t\t\t\t\t\t\t// whoa, loop detected\n\t\t\t\tLog(LOG_WARNING) << log_ctx << current << \": dependency loop detected for \" << masterId;\n\t\t\t\tdrop_list.insert(started_at);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcurrent = masterId;\n\t\t}\n\t}\n\t// at this point all loops are broken, let's drop mods involved\n\t// and anything that depends on them\n\tdrop_mods(log_ctx, drop_list);\n\n\t// now let's attempt mapping extResources for all the remaining mods\n\t// and drop any mod where this fails.\n\tfor (auto mri = ModsAvailable.begin(); mri != ModsAvailable.end(); ++mri) {\n\t\tauto modId = mri->first;\n\t\tauto mrec = mri->second;\n\t\tauto resdirs = mrec->modInfo.getExternalResourceDirs();\n\t\tfor (auto eri = resdirs.begin(); eri != resdirs.end(); ++eri) {\n\t\t\tif (!mapExtResources(mrec, *eri, false)) {\n\t\t\t\tLog(LOG_DEBUG) << log_ctx << \"dropping mod \" << modId << \": extResources '\" << *eri << \"' not found.\";\n\t\t\t\tdrop_list.insert(modId);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\tdrop_mods(log_ctx, drop_list);\n}\n// returns currently mapped bunch of mods.\nstd::map<std::string, ModInfo> getModInfos() {\n\tstd::map<std::string, ModInfo> rv;\n\tfor (auto mri = ModsAvailable.begin(); mri != ModsAvailable.end(); ++mri) {\n\t\trv.insert(std::make_pair(mri->first, mri->second->modInfo));\n\t}\n\treturn rv;\n}\n\nconst FileRecord* getModRuleFile(const ModInfo* modInfo, const std::string& relpath)\n{\n\tif (!relpath.empty())\n\t{\n\t\tauto fullPath = concatPaths(modInfo->getPath(), relpath);\n\t\tfor (auto& r : ModsAvailable.at(modInfo->getId())->stack.rulesets)\n\t\t{\n\t\t\tif (r.fullpath == fullPath)\n\t\t\t{\n\t\t\t\treturn &r;\n\t\t\t}\n\t\t}\n\t\tLog(LOG_WARNING) << \"mod \" << modInfo->getId() << \": unknown rulefile '\" << relpath <<\"'.\";\n\t}\n\treturn nullptr;\n}\n\nstd::string canonicalize(const std::string &in)\n{\n\tstd::string ret = in;\n\tUnicode::lowerCase(ret);\n\treturn ret;\n}\nbool fileExists(const std::string &relativeFilePath) {\n\treturn ( TheVFS.at(relativeFilePath) != NULL);\n}\nconst FileRecord *at(const std::string &relativeFilePath) {\n\tauto frec = TheVFS.at(relativeFilePath);\n\tif (frec == NULL) {\n\t\tstd::string fail = \"FileRecord::at(\" + relativeFilePath + \"): requested file not found.\";\n\t\tLog(LOG_FATAL) << fail;\n\t\tthrow Exception(fail);\n\t}\n\treturn frec;\n}\n\nSDL_RWops *getRWops(const std::string &relativeFilePath)\n{\n\treturn at(relativeFilePath)->getRWops();\n}\nSDL_RWops *getRWopsReadAll(const std::string &relativeFilePath)\n{\n\treturn at(relativeFilePath)->getRWopsReadAll();\n}\n\nstd::unique_ptr<std::istream> getIStream(const std::string &relativeFilePath) {\n\treturn at(relativeFilePath)->getIStream();\n}\nYAML::YamlRootNodeReader getYAML(const std::string &relativeFilePath) {\n\treturn at(relativeFilePath)->getYAML();\n}\nstd::vector<YAML::YamlNodeReader> getAllYAML(const std::string& relativeFilePath)\n{\n\treturn at(relativeFilePath)->getAllYAML();\n}\nconst std::vector<const FileRecord *> getSlice(const std::string &relativeFilePath) {\n\treturn TheVFS.get_slice(relativeFilePath);\n}\nconst NameSet &getVFolderContents(const std::string &relativePath) {\n\treturn TheVFS.ls(relativePath);\n}\nconst NameSet &getVFolderContents(const std::string &relativePath, size_t level) {\n\treturn TheVFS.lslayer(relativePath, level);\n}\ntemplate <typename T>\nNameSet _filterFiles(const T &files, const std::string &ext)\n{\n\tNameSet ret;\n\tsize_t extLen = ext.length() + 1; // +1 for the '.'\n\tstd::string canonicalExt = canonicalize(ext);\n\tfor (typename T::const_iterator i = files.begin(); i != files.end(); ++i)\n\t{\n\t\t// less-than not less-than-or-equal since we should have at least\n\t\t// one character in the filename that is not part of the extension\n\t\tif (extLen < i->length() && 0 == canonicalize(i->substr(i->length() - (extLen - 1))).compare(canonicalExt))\n\t\t{\n\t\t\tret.insert(*i);\n\t\t}\n\t}\n\treturn ret;\n}\n\nNameSet filterFiles(const std::vector<std::string> &files, const std::string &ext) { return _filterFiles(files, ext); }\nNameSet filterFiles(const std::set<std::string>    &files, const std::string &ext) { return _filterFiles(files, ext); }\nNameSet filterFiles(const NameSet                  &files, const std::string &ext) { return _filterFiles(files, ext); }\n\n}\n\n}\n"
  },
  {
    "path": "src/Engine/FileMap.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include <set>\n#include <string>\n#include <vector>\n#include <istream>\n#include <memory>\n#include <unordered_set>\n#include \"../Engine/Yaml.h\"\n#include \"../Engine/CrossPlatform.h\"\n#include <SDL_rwops.h>\n#include \"ModInfo.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Maps canonical names to file paths and maintains the virtual file system\n * for resource files.\n */\nnamespace FileMap\n{\n\tstruct FileRecord {\n\t\tstd::string fullpath; \t// includes zip file name if any\n\n\t\tvoid *zip; \t\t\t\t// borrowed reference/weakref. NOTNULL:\n\t\tsize_t findex;       \t// file index in the zipfile.\n\n\t\tFileRecord();\n\n\t\t/// Open file warped in RWops.\n\t\tSDL_RWops *getRWops() const;\n\t\t/// Read the whole file to memory and warp in RWops.\n\t\tSDL_RWops *getRWopsReadAll() const;\n\n\t\tstd::unique_ptr<std::istream> getIStream() const;\n\t\tRawData getUnzippedData() const;\n\t\tYAML::YamlRootNodeReader getYAML() const;\n\t\tstd::vector<YAML::YamlNodeReader> getAllYAML() const;\n\t};\n\n\t/// For common operations on bunches of filenames\n\ttypedef std::unordered_set<std::string> NameSet;\n\n\t/// Get FileRecord for the fullpath ..\n\tconst FileRecord *at(const std::string &relativeFilePath);\n\n\t/// Gets SDL_RWops for the file data of a data file blah blah read above.\n\tSDL_RWops *getRWops(const std::string &relativeFilePath);\n\n\t/// Gets SDL_RWops for the file data of a data file blah blah read above. Reads the whole file to memory.\n\tSDL_RWops *getRWopsReadAll(const std::string &relativeFilePath);\n\n\t/// Gets an std::istream interface to the file data. Has to be deleted on the caller's end.\n\tstd::unique_ptr<std::istream>getIStream(const std::string &relativeFilePath);\n\n\t/// Gets a 'vertical slice' through all the VFS layers for a given file name. (used for langs)\n\t/// Beware of NULLs for the layers that miss the relpath.\n\tconst std::vector<const FileRecord *> getSlice(const std::string &relativeFilePath);\n\n\t/// Returns parsed YAML for a filename\n\tYAML::YamlRootNodeReader getYAML(const std::string &relativeFilePath);\n\tstd::vector<YAML::YamlNodeReader> getAllYAML(const std::string& relativeFilePath);\n\n\t/// if we have the file\n\tbool fileExists(const std::string &relativeFilePath);\n\n\t/// Returns the set of files in a virtual folder.  The virtual folder contains files from all active mods\n\t/// that are in similarly-named subdirectories.\n\t/// level select the layer in the VFS cake. Useful value is 0 for the bottommost aka 'dataFolder/common'\n\t/// Does not include rulesets (*.rul).\n\tconst NameSet &getVFolderContents(const std::string &relativePath);\n\tconst NameSet &getVFolderContents(const std::string &relativePath, size_t level);\n\n\t/// Returns the subset of the given files that matches the given extension\n\tNameSet filterFiles(const std::vector<std::string> &files, const std::string &ext);\n\tNameSet filterFiles(const std::set<std::string>    &files, const std::string &ext);\n\tNameSet filterFiles(const NameSet &files, const std::string &ext);\n\n\t/// Returns the ruleset files found, grouped by mod, while mapping resources.  The highest-priority mod\n\t/// will be last in the returned vector.\n\n\ttypedef std::vector<std::pair<std::string, std::vector<FileRecord>>> RSOrder;\n\tconst RSOrder &getRulesets();\n\n\t/// absolutely clears FileMap state and maps common resources (dataDir/common)\n\tvoid clear(bool clearOnly, bool embeddedOnly);\n\n\t/// sets up VFS according to the mod sequence given (rescans common resources). does call clear().\n\tvoid setup(const std::vector<const ModInfo *>& active, bool embeddedOnly);\n\n\t/// lowercase it\n\tstd::string canonicalize(const std::string& fname);\n\n\t/// scans a moddir for mods, (privately) maps them.\n\tvoid scanModDir(const std::string& dirname, const std::string& basename, bool protectedLocation);\n\n\t/// scans a .zip from the rwops for mods\n\tvoid scanModZipRW(SDL_RWops *rwops, const std::string& fullpath);\n\n\t/// removes mods that lack extResourses, depend on missing mods\n\t/// or participate in dependency loops\n\tvoid checkModsDependencies();\n\n\t/// returns a list of mods that are loadable.\n\tstd::map<std::string, ModInfo> getModInfos();\n\n\t/// Get mod file based on mod info.\n\tconst FileRecord* getModRuleFile(const ModInfo* modInfo, const std::string& relpath);\n\n\t/// Unzip a file from a .zip into memory.\n\tSDL_RWops *zipGetFileByName(const std::string& zipfile, const std::string& fullpath);\n\n}\n\n}\n"
  },
  {
    "path": "src/Engine/FlcPlayer.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n/*\n * Based on http://www.libsdl.org/projects/flxplay/\n * See also https://github.com/aseprite/flic\n */\n#ifdef _MSC_VER\n#ifndef _SCL_SECURE_NO_WARNINGS\n#define _SCL_SECURE_NO_WARNINGS\n#endif\n#endif\n#include \"FlcPlayer.h\"\n#include <algorithm>\n#include <cassert>\n#include <string.h>\n#include <SDL_mixer.h>\n#include \"FileMap.h\"\n#include \"Logger.h\"\n#include \"Screen.h\"\n#include \"Options.h\"\n#include \"Game.h\"\n\nnamespace OpenXcom\n{\n\n\n// Taken from: http://www.compuphase.com/flic.htm\nenum FileTypes\n{\n\tFLI_TYPE = 0xAF11,\n\tFLC_TYPE = 0xAF12,\n};\n\n\nenum ChunkTypes\n{\n\tCOLOR_256 = 0x04,\n\tFLI_SS2 = 0x07, // or DELTA_FLC\n\tCOLOR_64 = 0x0B,\n\tFLI_LC = 0x0C, // or DELTA_FLI\n\tBLACK = 0x0D,\n\tFLI_BRUN = 0x0F, // or BYTE_RUN\n\tFLI_COPY = 0x10,\n\n\tAUDIO_CHUNK = 0xAAAA, // This is the only exception, it's from TFTD\n\tPREFIX_CHUNK = 0xF100,\n\tFRAME_TYPE = 0xF1FA,\n};\n\nenum ChunkOpcodes\n{\n\tPACKETS_COUNT = 0x0000, // 0000000000000000\n\tLAST_PIXEL = 0x8000, // 1000000000000000\n\tSKIP_LINES = 0xc000, // 1100000000000000\n\tMASK = SKIP_LINES\n};\n\nenum PlayingState\n{\n\tPLAYING,\n\tFINISHED,\n\tSKIPPED\n};\n\nFlcPlayer::FlcPlayer() : _fileBuf(0), _mainScreen(0), _realScreen(0), _game(0)\n{\n\t_volume = Game::volumeExponent(Options::musicVolume);\n}\n\nFlcPlayer::~FlcPlayer()\n{\n\tdeInit();\n}\n\n/**\n * Initialize data structures needed buy the player and read the whole file into memory\n * @param filename Video file name\n * @param frameCallback Function to call each video frame\n * @param game Pointer to the Game instance\n * @param dx An offset on the x axis for the video to be rendered\n * @param dy An offset on the y axis for the video to be rendered\n */\nbool FlcPlayer::init(const char *filename, void(*frameCallBack)(), Game *game, bool useInternalAudio, int dx, int dy)\n{\n\tif (_fileBuf != 0)\n\t{\n\t\tLog(LOG_ERROR) << \"Trying to init a video player that is already initialized\";\n\t\treturn false;\n\t}\n\n\t_frameCallBack = frameCallBack;\n\t_realScreen = game->getScreen();\n\t_realScreen->clear();\n\t_game = game;\n\t_useInternalAudio = useInternalAudio;\n\t_dx = dx;\n\t_dy = dy;\n\n\t_fileSize = 0;\n\t_frameCount = 0;\n\t_audioFrameData = 0;\n\t_hasAudio = false;\n\t_audioData.loadingBuffer = 0;\n\t_audioData.playingBuffer = 0;\n\n\tauto file = FileMap::getIStream(filename);\n\tfile->seekg(0, std::istream::end);\n\tauto size = file->tellg();\n\tfile->seekg(0, std::istream::beg);\n\t_fileBuf = new Uint8[size];\n\t_fileSize = size;\n\tfile->read((char *)_fileBuf, size);\n\n\t_audioFrameData = _fileBuf + 128;\n\n\t// Let's read the first 128 bytes\n\treadFileHeader();\n\n\t// If it's a FLC or FLI file, it's ok\n\tif (_headerType == SDL_SwapLE16(FLI_TYPE) || (_headerType == SDL_SwapLE16(FLC_TYPE)))\n\t{\n\t\t_screenWidth = _headerWidth;\n\t\t_screenHeight = _headerHeight;\n\t\t_screenDepth = 8;\n\n\t\tLog(LOG_INFO) << \"Playing flx, \" << _screenWidth << \"x\" << _screenHeight << \", \" << _headerFrames << \" frames\";\n\t}\n\telse\n\t{\n\t\tLog(LOG_ERROR) << \"Flx file failed header check.\";\n\t\treturn false;\n\t}\n\tif (_screenWidth > _realScreen->getSurface()->w && Options::displayWidth >= _screenWidth)\n\t{\n\t\t// base resolution of video is higher than our surface width\n\t\t// and our display resolution allows a hi-res video\n\t\t// set base resolution to video resolution\n\t\tOptions::baseXResolution = _screenWidth;\n\t\tOptions::baseYResolution = _screenHeight;\n\t\t_realScreen->resetDisplay();\n\t}\n\t// If the current surface used is at 8bpp use it\n\tif (_realScreen->getSurface()->format->BitsPerPixel == 8)\n\t{\n\t\t_mainScreen = _realScreen->getSurface();\n\t}\n\telse // Otherwise create a new one\n\t{\n\t\t_mainScreen = SDL_AllocSurface(SDL_SWSURFACE, _realScreen->getSurface()->w, _realScreen->getSurface()->h, 8, 0, 0, 0, 0);\n\t}\n\n\treturn true;\n}\n\nvoid FlcPlayer::deInit()\n{\n\tif (_mainScreen != 0 && _realScreen != 0)\n\t{\n\t\tif (_mainScreen != _realScreen->getSurface())\n\t\t\tSDL_FreeSurface(_mainScreen);\n\n\t\t_mainScreen = 0;\n\t}\n\n\tif (_fileBuf != 0)\n\t{\n\t\tdelete[] _fileBuf;\n\t\t_fileBuf = 0;\n\n\t\tdeInitAudio();\n\t}\n}\n\n/**\n * Starts decoding and playing the FLI/FLC file\n */\nvoid FlcPlayer::play(bool skipLastFrame)\n{\n\t_playingState = PLAYING;\n\n\t// Vertically center the video\n\t_dy = (_mainScreen->h - _headerHeight) / 2;\n\n\t_offset = _dy * _mainScreen->pitch + _mainScreen->format->BytesPerPixel * _dx;\n\n\t// Skip file header\n\t_videoFrameData = _fileBuf + 128;\n\t_audioFrameData = _videoFrameData;\n\n\twhile (!shouldQuit())\n\t{\n\t\tif (_frameCallBack)\n\t\t\t(*_frameCallBack)();\n\t\telse // TODO: support both, in the case the callback is not some audio?\n\t\t\tdecodeAudio(2);\n\n\t\tif (!shouldQuit())\n\t\t\tdecodeVideo(skipLastFrame);\n\n\t\tif(!shouldQuit())\n\t\t\tSDLPolling();\n\t}\n\n}\n\nvoid FlcPlayer::delay(Uint32 milliseconds)\n{\n\tUint32 pauseStart = SDL_GetTicks();\n\twhile(_playingState != SKIPPED && SDL_GetTicks() < (pauseStart + milliseconds))\n\t{\n\t\tSDLPolling();\n\t}\n}\nvoid FlcPlayer::SDLPolling()\n{\n\tSDL_Event event;\n\twhile (SDL_PollEvent(&event))\n\t{\n\t\tswitch (event.type)\n\t\t{\n\t\tcase SDL_MOUSEBUTTONDOWN:\n\t\tcase SDL_KEYDOWN:\n\t\t\t_playingState = SKIPPED;\n\t\t\tbreak;\n\t\tcase SDL_VIDEORESIZE:\n\t\t\tif (Options::allowResize)\n\t\t\t{\n\t\t\t\tOptions::newDisplayWidth = Options::displayWidth = std::max(Screen::ORIGINAL_WIDTH, event.resize.w);\n\t\t\t\tOptions::newDisplayHeight = Options::displayHeight = std::max(Screen::ORIGINAL_HEIGHT, event.resize.h);\n\t\t\t\tif (_mainScreen != _realScreen->getSurface())\n\t\t\t\t{\n\t\t\t\t\t_realScreen->resetDisplay();\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t_realScreen->resetDisplay();\n\t\t\t\t\t_mainScreen = _realScreen->getSurface();\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tcase SDL_QUIT:\n\t\t\texit(0);\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nbool FlcPlayer::shouldQuit()\n{\n\treturn _playingState == FINISHED || _playingState == SKIPPED;\n}\n\nvoid FlcPlayer::readFileHeader()\n{\n\treadU32(_headerSize, _fileBuf);\n\treadU16(_headerType, _fileBuf + 4);\n\treadU16(_headerFrames, _fileBuf + 6);\n\treadU16(_headerWidth, _fileBuf + 8);\n\treadU16(_headerHeight, _fileBuf + 10);\n\treadU16(_headerDepth, _fileBuf + 12);\n\treadU16(_headerSpeed, _fileBuf + 16);\n}\n\nbool FlcPlayer::isValidFrame(Uint8 *frameHeader, Uint32 &frameSize, Uint16 &frameType)\n{\n\treadU32(frameSize, frameHeader);\n\treadU16(frameType, frameHeader + 4);\n\n\treturn (frameType == FRAME_TYPE || frameType == AUDIO_CHUNK || frameType == PREFIX_CHUNK);\n}\n\nvoid FlcPlayer::decodeAudio(int frames)\n{\n\n\tint audioFramesFound = 0;\n\n\twhile (audioFramesFound < frames && !isEndOfFile(_audioFrameData))\n\t{\n\t\tif (!isValidFrame(_audioFrameData, _audioFrameSize, _audioFrameType))\n\t\t{\n\t\t\t_playingState = FINISHED;\n\t\t\tbreak;\n\t\t}\n\n\t\tswitch (_audioFrameType)\n\t\t{\n\t\t\tcase FRAME_TYPE:\n\t\t\tcase PREFIX_CHUNK:\n\t\t\t\t_audioFrameData += _audioFrameSize;\n\t\t\t\tbreak;\n\t\t\tcase AUDIO_CHUNK:\n\t\t\t\tUint16 sampleRate;\n\n\t\t\t\treadU16(sampleRate, _audioFrameData + 8);\n\n\t\t\t\t_chunkData = _audioFrameData + 16;\n\n\t\t\t\tplayAudioFrame(sampleRate);\n\n\t\t\t\t_audioFrameData += _audioFrameSize + 16;\n\n\t\t\t\t++audioFramesFound;\n\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n\nvoid FlcPlayer::decodeVideo(bool skipLastFrame)\n{\n\tbool videoFrameFound = false;\n\n\twhile (!videoFrameFound)\n\t{\n\t\tif (!isValidFrame(_videoFrameData, _videoFrameSize, _videoFrameType))\n\t\t{\n\t\t\t_playingState = FINISHED;\n\t\t\tbreak;\n\t\t}\n\n\t\tswitch (_videoFrameType)\n\t\t{\n\t\tcase FRAME_TYPE:\n\n\t\t\tUint32 delay;\n\n\t\t\treadU16(_frameChunks, _videoFrameData + 6);\n\t\t\treadU16(_delayOverride, _videoFrameData + 8);\n\n\t\t\tif (_headerType == FLI_TYPE)\n\t\t\t{\n\t\t\t\tdelay = _delayOverride > 0 ? _delayOverride : _headerSpeed * (1000.0 / 70.0);\n\t\t\t}\n\t\t\telse if (_useInternalAudio && !_frameCallBack) // this means TFTD videos are playing\n\t\t\t{\n\t\t\t\tdelay = _videoDelay;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tdelay = _headerSpeed;\n\t\t\t}\n\n\t\t\twaitForNextFrame(delay);\n\n\t\t\t// Skip the frame header, we are not interested in the rest\n\t\t\t_chunkData = _videoFrameData + 16;\n\n\t\t\t_videoFrameData += _videoFrameSize;\n\t\t\t// If this frame is the last one, don't play it\n\t\t\tif(isEndOfFile(_videoFrameData))\n\t\t\t\t_playingState = FINISHED;\n\n\t\t\tif(!shouldQuit() || !skipLastFrame)\n\t\t\t\tplayVideoFrame();\n\n\t\t\tvideoFrameFound = true;\n\n\t\t\tbreak;\n\t\tcase AUDIO_CHUNK:\n\t\t\t_videoFrameData += _videoFrameSize + 16;\n\t\t\tbreak;\n\t\tcase PREFIX_CHUNK:\n\t\t\t// Just skip it\n\t\t\t_videoFrameData += _videoFrameSize;\n\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nvoid FlcPlayer::playVideoFrame()\n{\n\t++_frameCount;\n\tif (SDL_LockSurface(_mainScreen) < 0)\n\t\treturn;\n\tint chunkCount = _frameChunks;\n\n\tfor (int i = 0; i < chunkCount; ++i)\n\t{\n\t\treadU32(_chunkSize, _chunkData);\n\t\treadU16(_chunkType, _chunkData + 4);\n\n\t\tswitch (_chunkType)\n\t\t{\n\t\t\tcase COLOR_256:\n\t\t\t\tcolor256();\n\t\t\t\tbreak;\n\t\t\tcase FLI_SS2:\n\t\t\t\tfliSS2();\n\t\t\t\tbreak;\n\t\t\tcase COLOR_64:\n\t\t\t\tcolor64();\n\t\t\t\tbreak;\n\t\t\tcase FLI_LC:\n\t\t\t\tfliLC();\n\t\t\t\tbreak;\n\t\t\tcase BLACK:\n\t\t\t\tblack();\n\t\t\t\tbreak;\n\t\t\tcase FLI_BRUN:\n\t\t\t\tfliBRun();\n\t\t\t\tbreak;\n\t\t\tcase FLI_COPY:\n\t\t\t\tfliCopy();\n\t\t\t\tbreak;\n\t\t\tcase 18:\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tLog(LOG_WARNING) << \"Ieek an non implemented chunk type:\" << _chunkType;\n\t\t\t\tbreak;\n\t\t}\n\n\t\t_chunkData += _chunkSize;\n\t}\n\n\tSDL_UnlockSurface(_mainScreen);\n\n\t/* TODO: Track which rectangles have really changed */\n\t//SDL_UpdateRect(_mainScreen, 0, 0, 0, 0);\n\tif (_mainScreen != _realScreen->getSurface())\n\t\tSDL_BlitSurface(_mainScreen, 0, _realScreen->getSurface(), 0);\n\n\t_realScreen->flip();\n}\n\nvoid FlcPlayer::playAudioFrame(Uint16 sampleRate)\n{\n\t/* TFTD audio header (10 bytes)\n\t* Uint16 unknown1 - always 0\n\t* Uint16 sampleRate\n\t* Uint16 unknown2 - always 1 (Channels? bytes per sample?)\n\t* Uint16 unknown3 - always 10 (No idea)\n\t* Uint16 unknown4 - always 0\n\t* Uint8[] unsigned 1-byte 1-channel PCM data of length _chunkSize_ (so the total chunk is _chunkSize_ + 6-byte flc header + 10 byte audio header */\n\n\tif (_useInternalAudio)\n\t{\n\t\tif (!_hasAudio)\n\t\t{\n\t\t\t_audioData.sampleRate = sampleRate;\n\t\t\t_hasAudio = true;\n\t\t\tinitAudio(AUDIO_S16SYS, 1);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t/* Cannot change sample rate mid-video */\n\t\t\tassert(sampleRate == _audioData.sampleRate);\n\t\t}\n\n\t\tSDL_SemWait(_audioData.sharedLock);\n\t\tAudioBuffer *loadingBuff = _audioData.loadingBuffer;\n\t\tassert(loadingBuff->currSamplePos == 0);\n\t\tint newSize = (_audioFrameSize + loadingBuff->sampleCount )*2;\n\t\tif (newSize > loadingBuff->sampleBufSize)\n\t\t{\n\t\t\t/* If the sample count has changed, we need to reallocate (Handles initial state\n\t\t\t* of '0' sample count too, as realloc(NULL, size) == malloc(size) */\n\t\t\tloadingBuff->samples = (Sint16*)realloc(loadingBuff->samples, newSize);\n\t\t\tloadingBuff->sampleBufSize = newSize;\n\t\t}\n\n\t\tfor (unsigned int i = 0; i < _audioFrameSize; i++)\n\t\t{\n\t\t\tloadingBuff->samples[loadingBuff->sampleCount + i] = (float)((_chunkData[i]) -128) * 240 * _volume;\n\t\t}\n\t\tloadingBuff->sampleCount += _audioFrameSize;\n\n\t\tSDL_SemPost(_audioData.sharedLock);\n\t}\n\telse\n\t{\n\t\t_audioData.sampleRate = sampleRate; // this is used to keep the framerate correct\n\t}\n}\n\nvoid FlcPlayer::color256()\n{\n\tUint8 *pSrc;\n\tUint16 numColorPackets;\n\tUint16 numColors = 0;\n\tUint8 numColorsSkip;\n\n\tpSrc = _chunkData + 6;\n\treadU16(numColorPackets, pSrc);\n\tpSrc += 2;\n\n\twhile (numColorPackets--)\n\t{\n\t\tnumColorsSkip = *(pSrc++) + numColors;\n\t\tnumColors = *(pSrc++);\n\t\tif (numColors == 0)\n\t\t{\n\t\t\tnumColors = 256;\n\t\t}\n\n\t\tfor (int i = 0; i < numColors; ++i)\n\t\t{\n\t\t\t_colors[i].r = *(pSrc++);\n\t\t\t_colors[i].g = *(pSrc++);\n\t\t\t_colors[i].b = *(pSrc++);\n\t\t}\n\n\t\tif (_mainScreen != _realScreen->getSurface())\n\t\t\tSDL_SetColors(_mainScreen, _colors, numColorsSkip, numColors);\n\t\t_realScreen->setPalette(_colors, numColorsSkip, numColors, true);\n\n\t\tif (numColorPackets >= 1)\n\t\t{\n\t\t\t++numColors;\n\t\t}\n\t}\n}\n\nvoid FlcPlayer::fliSS2()\n{\n\tUint8 *pSrc, *pDst, *pTmpDst;\n\tSint8 countData;\n\tUint8 columSkip, fill1, fill2;\n\tUint16 lines;\n\tSint16 count;\n\tbool setLastByte = false;\n\tUint8 lastByte = 0;\n\n\tpSrc = _chunkData + 6;\n\tpDst = (Uint8*)_mainScreen->pixels + _offset;\n\treadU16(lines, pSrc);\n\n\tpSrc += 2;\n\n\twhile (lines--)\n\t{\n\t\treadS16(count, (Sint8 *)pSrc);\n\t\tpSrc += 2;\n\n\t\tif ((count & MASK) == SKIP_LINES)\n\t\t{\n\t\t\tpDst += (-count)*_mainScreen->pitch;\n\t\t\t++lines;\n\t\t\tcontinue;\n\t\t}\n\n\t\telse if ((count & MASK) == LAST_PIXEL)\n\t\t{\n\t\t\tsetLastByte = true;\n\t\t\tlastByte = (count & 0x00FF);\n\t\t\treadS16(count, (Sint8 *)pSrc);\n\t\t\tpSrc += 2;\n\t\t}\n\n\t\tif ((count & MASK) == PACKETS_COUNT)\n\t\t{\n\t\t\tpTmpDst = pDst;\n\t\t\twhile (count--)\n\t\t\t{\n\t\t\t\tcolumSkip = *(pSrc++);\n\t\t\t\tpTmpDst += columSkip;\n\t\t\t\tcountData = *(pSrc++);\n\n\t\t\t\tif (countData > 0)\n\t\t\t\t{\n\t\t\t\t\tstd::copy(pSrc, pSrc + (2 * countData), pTmpDst);\n\t\t\t\t\tpTmpDst += (2 * countData);\n\t\t\t\t\tpSrc += (2 * countData);\n\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif (countData < 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tcountData = -countData;\n\n\t\t\t\t\t\tfill1 = *(pSrc++);\n\t\t\t\t\t\tfill2 = *(pSrc++);\n\t\t\t\t\t\twhile (countData--)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t*(pTmpDst++) = fill1;\n\t\t\t\t\t\t\t*(pTmpDst++) = fill2;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (setLastByte)\n\t\t\t{\n\t\t\t\tsetLastByte = false;\n\t\t\t\t*(pDst + _mainScreen->pitch - 1) = lastByte;\n\t\t\t}\n\t\t\tpDst += _mainScreen->pitch;\n\t\t}\n\t}\n}\n\nvoid FlcPlayer::fliBRun()\n{\n\tUint8 *pSrc, *pDst, *pTmpDst, fill;\n\tSint8 countData;\n\tint heightCount;\n\n\theightCount = _headerHeight;\n\tpSrc = _chunkData + 6; // Skip chunk header\n\tpDst = (Uint8*)_mainScreen->pixels + _offset;\n\n\twhile (heightCount--)\n\t{\n\t\tpTmpDst = pDst;\n\t\t++pSrc; // Read and skip the packet count value\n\n\t\tint pixels = 0;\n\t\twhile (pixels != _headerWidth)\n\t\t{\n\t\t\tcountData = *(pSrc++);\n\t\t\tif (countData > 0)\n\t\t\t{\n\t\t\t\tfill = *(pSrc++);\n\n\t\t\t\tstd::fill_n(pTmpDst, countData, fill);\n\t\t\t\tpTmpDst += countData;\n\t\t\t\tpixels += countData;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (countData < 0)\n\t\t\t\t{\n\t\t\t\t\tcountData = -countData;\n\n\t\t\t\t\tstd::copy(pSrc, pSrc + countData, pTmpDst);\n\t\t\t\t\tpTmpDst += countData;\n\t\t\t\t\tpSrc += countData;\n\t\t\t\t\tpixels += countData;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tpDst += _mainScreen->pitch;\n\t}\n}\n\n\nvoid FlcPlayer::fliLC()\n{\n\tUint8 *pSrc, *pDst, *pTmpDst;\n\tSint8 countData;\n\tUint8 countSkip;\n\tUint8 fill;\n\tUint16 lines, tmp;\n\tint packetsCount;\n\n\tpSrc = _chunkData + 6;\n\tpDst = (Uint8*)_mainScreen->pixels + _offset;\n\n\treadU16(tmp, pSrc);\n\tpSrc += 2;\n\tpDst += tmp*_mainScreen->pitch;\n\treadU16(lines, pSrc);\n\tpSrc += 2;\n\n\twhile (lines--)\n\t{\n\t\tpTmpDst = pDst;\n\t\tpacketsCount = *(pSrc++);\n\n\t\twhile (packetsCount--)\n\t\t{\n\t\t\tcountSkip = *(pSrc++);\n\t\t\tpTmpDst += countSkip;\n\t\t\tcountData = *(pSrc++);\n\t\t\tif (countData > 0)\n\t\t\t{\n\t\t\t\twhile (countData--)\n\t\t\t\t{\n\t\t\t\t\t*(pTmpDst++) = *(pSrc++);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (countData < 0)\n\t\t\t\t{\n\t\t\t\t\tcountData = -countData;\n\n\t\t\t\t\tfill = *(pSrc++);\n\t\t\t\t\twhile (countData--)\n\t\t\t\t\t{\n\t\t\t\t\t\t*(pTmpDst++) = fill;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tpDst += _mainScreen->pitch;\n\t}\n}\n\nvoid FlcPlayer::color64()\n{\n\tUint8 *pSrc;\n\tUint16 NumColors, NumColorPackets;\n\tUint8 NumColorsSkip;\n\n\tpSrc = _chunkData + 6;\n\treadU16(NumColorPackets, pSrc);\n\tpSrc += 2;\n\n\twhile (NumColorPackets--)\n\t{\n\t\tNumColorsSkip = *(pSrc++);\n\t\tNumColors = *(pSrc++);\n\n\t\tif (NumColors == 0)\n\t\t{\n\t\t\tNumColors = 256;\n\t\t}\n\n\t\tfor (int i = 0; i < NumColors; ++i)\n\t\t{\n\t\t\t_colors[i].r = *(pSrc++) << 2;\n\t\t\t_colors[i].g = *(pSrc++) << 2;\n\t\t\t_colors[i].b = *(pSrc++) << 2;\n\t\t}\n\n\t\tif (_mainScreen != _realScreen->getSurface())\n\t\t\tSDL_SetColors(_mainScreen, _colors, NumColorsSkip, NumColors);\n\t\t_realScreen->setPalette(_colors, NumColorsSkip, NumColors, true);\n\t}\n}\n\nvoid FlcPlayer::fliCopy()\n{\n\tUint8 *pSrc, *pDst;\n\tint Lines = _screenHeight;\n\tpSrc = _chunkData + 6;\n\tpDst = (Uint8*)_mainScreen->pixels + _offset;\n\n\twhile (Lines--)\n\t{\n\t\tmemcpy(pDst, pSrc, _screenWidth);\n\t\tpSrc += _screenWidth;\n\t\tpDst += _mainScreen->pitch;\n\t}\n}\n\nvoid FlcPlayer::black()\n{\n\tUint8 *pDst;\n\tint Lines = _screenHeight;\n\tpDst = (Uint8*)_mainScreen->pixels + _offset;\n\n\twhile (Lines-- > 0)\n\t{\n\t\tmemset(pDst, 0, _screenHeight);\n\t\tpDst += _mainScreen->pitch;\n\t}\n}\n\nvoid FlcPlayer::audioCallback(void *userData, Uint8 *stream, int len)\n{\n\tAudioData *audio = (AudioData*)userData;\n\n\tAudioBuffer *playBuff = audio->playingBuffer;\n\n\twhile (len > 0)\n\t{\n\t\tif (playBuff->sampleCount > 0)\n\t\t{\n\t\t\tint bytesToCopy = std::min(len, playBuff->sampleCount * 2);\n\t\t\tmemcpy(stream, playBuff->samples + playBuff->currSamplePos, bytesToCopy);\n\n\t\t\tplayBuff->currSamplePos += bytesToCopy / 2;\n\t\t\tplayBuff->sampleCount -= bytesToCopy / 2;\n\t\t\tlen -= bytesToCopy;\n\n\t\t\tassert(playBuff->sampleCount >= 0);\n\t\t}\n\n\t\tif (len > 0)\n\t\t{\n\t\t\t/* Need to swap buffers */\n\t\t\tplayBuff->currSamplePos = 0;\n\t\t\tSDL_SemWait(audio->sharedLock);\n\t\t\tAudioBuffer *tempBuff = playBuff;\n\t\t\taudio->playingBuffer = playBuff = audio->loadingBuffer;\n\t\t\taudio->loadingBuffer = tempBuff;\n\t\t\tSDL_SemPost(audio->sharedLock);\n\n\t\t\tif (playBuff->sampleCount == 0)\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n\nvoid FlcPlayer::initAudio(Uint16 format, Uint8 channels)\n{\n\t_videoDelay = 1000 / (_audioData.sampleRate / _audioFrameSize );\n\tif (_useInternalAudio)\n\t{\n\t\tif (!Options::mute)\n\t\t{\n\t\t\tif (Mix_OpenAudio(_audioData.sampleRate, format, channels, _audioFrameSize * 2) != 0)\n\t\t\t{\n\t\t\t\tLog(LOG_ERROR) << Mix_GetError();\n\t\t\t\tLog(LOG_WARNING) << \"Failed to init cutscene audio\";\n\t\t\t\tOptions::mute = true;\n\t\t\t}\n\t\t}\n\n\t\t/* Start runnable */\n\t\t_audioData.sharedLock = SDL_CreateSemaphore(1);\n\n\t\t_audioData.loadingBuffer = new AudioBuffer();\n\t\t_audioData.loadingBuffer->currSamplePos = 0;\n\t\t_audioData.loadingBuffer->sampleCount = 0;\n\t\t_audioData.loadingBuffer->samples = (Sint16 *)malloc(_audioFrameSize * 2);\n\t\t_audioData.loadingBuffer->sampleBufSize = _audioFrameSize * 2;\n\n\t\t_audioData.playingBuffer = new AudioBuffer();\n\t\t_audioData.playingBuffer->currSamplePos = 0;\n\t\t_audioData.playingBuffer->sampleCount = 0;\n\t\t_audioData.playingBuffer->samples = (Sint16 *)malloc(_audioFrameSize * 2);\n\t\t_audioData.playingBuffer->sampleBufSize = _audioFrameSize * 2;\n\n\t\tif (!Options::mute)\n\t\t{\n\t\t\tMix_HookMusic(FlcPlayer::audioCallback, &_audioData);\n\t\t}\n\t}\n}\n\nvoid FlcPlayer::deInitAudio()\n{\n\tif (_game)\n\t{\n\t\tif (!Options::mute)\n\t\t{\n\t\t\tMix_HookMusic(NULL, NULL);\n\t\t\tMix_CloseAudio();\n\t\t\t_game->initAudio();\n\t\t}\n\t}\n\telse if (_audioData.sharedLock)\n\t\tSDL_DestroySemaphore(_audioData.sharedLock);\n\n\tif (_audioData.loadingBuffer)\n\t{\n\t\tfree(_audioData.loadingBuffer->samples);\n\t\tdelete _audioData.loadingBuffer;\n\t\t_audioData.loadingBuffer = 0;\n\t}\n\n\tif (_audioData.playingBuffer)\n\t{\n\t\tfree(_audioData.playingBuffer->samples);\n\t\tdelete _audioData.playingBuffer;\n\t\t_audioData.playingBuffer = 0;\n\t}\n\n}\n\nvoid FlcPlayer::stop()\n{\n\t_playingState = FINISHED;\n}\n\nbool FlcPlayer::isEndOfFile(Uint8 *pos)\n{\n\treturn (pos - _fileBuf) == (int)(_fileSize); // should be Sint64, but let's assume the videos won't be 2gb\n}\n\nint FlcPlayer::getFrameCount()\n{\n\treturn _frameCount;\n}\n\nvoid FlcPlayer::setHeaderSpeed(int speed)\n{\n\t_headerSpeed = speed;\n}\n\nbool FlcPlayer::wasSkipped()\n{\n\treturn _playingState == SKIPPED;\n}\n\nvoid FlcPlayer::waitForNextFrame(Uint32 delay)\n{\n\tstatic Uint32 oldTick = 0;\n\tint newTick;\n\tint currentTick;\n\n\tcurrentTick = SDL_GetTicks();\n\tif (oldTick == 0)\n\t{\n\t\toldTick = currentTick;\n\t\tnewTick = oldTick;\n\t}\n\telse\n\t\tnewTick = oldTick + delay;\n\n\tif (_hasAudio)\n\t{\n\t\twhile (currentTick < newTick)\n\t\t{\n\t\t\twhile ((newTick - currentTick) > 10 && !isEndOfFile(_audioFrameData))\n\t\t\t{\n\t\t\t\tdecodeAudio(1);\n\t\t\t\tcurrentTick = SDL_GetTicks();\n\t\t\t}\n\t\t\tSDL_Delay(1);\n\t\t\tcurrentTick = SDL_GetTicks();\n\t\t}\n\t}\n\telse\n\t{\n\t\twhile (currentTick < newTick)\n\t\t{\n\t\t\tSDL_Delay(1);\n\t\t\tcurrentTick = SDL_GetTicks();\n\t\t}\n\t}\n\toldTick = SDL_GetTicks();\n}\n\n#if SDL_BYTEORDER == SDL_BIG_ENDIAN\ninline void FlcPlayer::readU16(Uint16 &dst, const Uint8 * const src)\n{\n\tdst = (src[0] << 8) | src[1];\n}\ninline void FlcPlayer::readU32(Uint32 &dst, const Uint8 * const src)\n{\n\tdst = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];\n}\ninline void FlcPlayer::readS16(Sint16 &dst, const Sint8 * const src)\n{\n\tdst = (src[0] << 8) | src[1];\n}\ninline void FlcPlayer::readS32(Sint32 &dst, const Sint8 * const src)\n{\n\tdst = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];\n}\n#else\ninline void FlcPlayer::readU16(Uint16 &dst, const Uint8 * const src)\n{\n\tdst = (src[1] << 8) | src[0];\n}\ninline void FlcPlayer::readU32(Uint32 &dst, const Uint8 * const src)\n{\n\tdst = (src[3] << 24) | (src[2] << 16) | (src[1] << 8) | src[0];\n}\ninline void FlcPlayer::readS16(Sint16 &dst, const Sint8 * const src)\n{\n\tdst = (src[1] << 8) | src[0];\n}\ninline void FlcPlayer::readS32(Sint32 &dst, const Sint8 * const src)\n{\n\tdst = (src[3] << 24) | (src[2] << 16) | (src[1] << 8) | src[0];\n}\n#endif\n\n}\n"
  },
  {
    "path": "src/Engine/FlcPlayer.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n/*\n * Based on http://www.libsdl.org/projects/flxplay/\n */\n#include <SDL.h>\n\nnamespace OpenXcom\n{\n\nclass Screen;\nclass Game;\n\nclass FlcPlayer\n{\nprivate:\n\n\tUint8 *_fileBuf;\n\tUint32 _fileSize;\n\tUint8 *_videoFrameData;\n\tUint8 *_chunkData;\n\tUint8 *_audioFrameData;\n\tUint16 _frameCount;    /* Frame Counter */\n\tUint32 _headerSize;    /* Fli file size */\n\tUint16 _headerType;    /* Fli header check */\n\tUint16 _headerFrames;  /* Number of frames in flic */\n\tUint16 _headerWidth;   /* Fli width */\n\tUint16 _headerHeight;  /* Fli height */\n\tUint16 _headerDepth;   /* Color depth */\n\tUint16 _headerSpeed;   /* Number of video ticks between frame */\n\tUint32 _videoFrameSize;     /* Frame size in bytes */\n\tUint16 _videoFrameType;\n\tUint16 _frameChunks;   /* Number of chunks in frame */\n\tUint32 _chunkSize;     /* Size of chunk */\n\tUint16 _chunkType;     /* Type of chunk */\n\tUint16 _delayOverride; /* FRAME_TYPE extension */\n\tUint32 _audioFrameSize;\n\tUint16 _audioFrameType;\n\n\tvoid (*_frameCallBack)();\n\n\tSDL_Surface *_mainScreen;\n\tScreen *_realScreen;\n\tSDL_Color _colors[256];\n\tint _screenWidth;\n\tint _screenHeight;\n\tint _screenDepth;\n\tint _dx, _dy;\n\tint _offset;\n\tint _playingState;\n\tbool _hasAudio, _useInternalAudio;\n\tint _videoDelay;\n\tdouble _volume;\n\n\ttypedef struct AudioBuffer\n\t{\n\t\tSint16 *samples;\n\t\tint sampleCount;\n\t\tint sampleBufSize;\n\t\tint currSamplePos;\n\t}AudioBuffer;\n\n\n\ttypedef struct AudioData\n\t{\n\t\tint sampleRate;\n\t\tAudioBuffer *loadingBuffer;\n\t\tAudioBuffer *playingBuffer;\n\t\tSDL_sem *sharedLock;\n\n\t}AudioData;\n\n\tAudioData _audioData;\n\n\tGame *_game;\n\n\tvoid readU16(Uint16 &dst, const Uint8 *const src);\n\tvoid readU32(Uint32 &dst, const Uint8 *const src);\n\tvoid readS16(Sint16 &dst, const Sint8 *const src);\n\tvoid readS32(Sint32 &dst, const Sint8 *const src);\n\tvoid readFileHeader();\n\n\tbool isValidFrame(Uint8 *frameHeader, Uint32 &frameSize, Uint16 &frameType);\n\tvoid decodeVideo(bool skipLastFrame);\n\tvoid decodeAudio(int frames);\n\tvoid waitForNextFrame(Uint32 delay);\n\tvoid SDLPolling();\n\tbool shouldQuit();\n\n\tvoid playVideoFrame();\n\tvoid color256();\n\tvoid fliBRun();\n\tvoid fliCopy();\n\tvoid fliSS2();\n\tvoid fliLC();\n\tvoid color64();\n\tvoid black();\n\n\tvoid playAudioFrame(Uint16 sampleRate);\n\tvoid initAudio(Uint16 format, Uint8 channels);\n\tvoid deInitAudio();\n\n\tbool isEndOfFile(Uint8 *pos);\n\n\tstatic void audioCallback(void *userData, Uint8 *stream, int len);\n\npublic:\n\n\tFlcPlayer();\n\t~FlcPlayer();\n\n\t/// Open FLC or FLI file, read header, prepare to play it\n\tbool init(const char *filename, void(*frameCallBack)(), Game *game, bool useAudio, int dx, int dy);\n\t/// Play the loaded file; set flc.mainScreen first!\n\tvoid play(bool skipLastFrame);\n\t/// Free memory, free love, etc.\n\tvoid deInit();\n\t// Stop FLC Player\n\tvoid stop();\n\t/// Delay player at the end\n\tvoid delay(Uint32 milliseconds);\n\tvoid setHeaderSpeed(int speed);\n\tint getFrameCount();\n\tbool wasSkipped();\n};\n\n}\n"
  },
  {
    "path": "src/Engine/Font.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Font.h\"\n#include \"DosFont.h\"\n#include \"Surface.h\"\n#include \"FileMap.h\"\n#include \"Unicode.h\"\n\nnamespace OpenXcom\n{\n\nconst SDL_Color Font::TerminalColors[2] = {{0, 0, 0, 0}, {185, 185, 185, 255}};\n\n/**\n * Initializes the font with a blank surface.\n */\nFont::Font() : _monospace(false)\n{\n}\n\n/**\n * Deletes the font's surface.\n */\nFont::~Font()\n{\n\tfor (auto& fontImage : _images)\n\t{\n\t\tdelete fontImage.surface;\n\t}\n}\n\n/**\n * Loads the font from a YAML file.\n * @param node YAML node.\n */\nvoid Font::load(const YAML::YamlNodeReader& reader)\n{\n\tint width = reader[\"width\"].readVal(0);\n\tint height = reader[\"height\"].readVal(0);\n\tint spacing = reader[\"spacing\"].readVal(0);\n\t_monospace = reader[\"monospace\"].readVal(_monospace);\n\tfor (const auto& imageReader : reader[\"images\"].children())\n\t{\n\t\tFontImage image;\n\t\timage.width = imageReader[\"width\"].readVal(width);\n\t\timage.height = imageReader[\"height\"].readVal(height);\n\t\timage.spacing = imageReader[\"spacing\"].readVal(spacing);\n\t\tstd::string file = \"Language/\" + imageReader[\"file\"].readVal<std::string>();\n\t\tUString chars = Unicode::convUtf8ToUtf32(imageReader[\"chars\"].readVal<std::string>());\n\t\timage.surface = new Surface(image.width, image.height);\n\t\timage.surface->loadImage(file);\n\t\t_images.push_back(image);\n\t\tinit(_images.size() - 1, chars);\n\t}\n}\n\n/**\n * Generates a pre-defined Codepage 437 (MS-DOS terminal) font.\n */\nvoid Font::loadTerminal()\n{\n\tFontImage image;\n\timage.width = 9;\n\timage.height = 16;\n\timage.spacing = 0;\n\t_monospace = true;\n\n\tSDL_RWops *rw = SDL_RWFromConstMem(dosFont, DOSFONT_SIZE);\n\tSDL_Surface *s = SDL_LoadBMP_RW(rw, SDL_TRUE);\n\timage.surface = new Surface(s->w, s->h);\n\timage.surface->setPalette(TerminalColors, 0, std::size(TerminalColors));\n\tSDL_BlitSurface(s, 0, image.surface->getSurface(), 0);\n\tSDL_FreeSurface(s);\n\t_images.push_back(image);\n\n\tUString chars = Unicode::convUtf8ToUtf32(\" !\\\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\");\n\tinit(_images.size() - 1, chars);\n}\n\n\n/**\n * Calculates the real size and position of each character in\n * the surface and stores them in SDL_Rect's for future use\n * by other classes.\n * @param index The index of the surface to use.\n * @param str A string of characters to map to the surface.\n */\nvoid Font::init(size_t index, const UString &str)\n{\n\tFontImage *image = &_images[index];\n\tSurface *surface = image->surface;\n\tsurface->lock();\n\tint length = (surface->getWidth() / image->width);\n\n\t_chars.reserve(_chars.size() + str.size());\n\n\tif (_monospace)\n\t{\n\t\tfor (size_t i = 0; i < str.length(); ++i)\n\t\t{\n\t\t\tSDL_Rect rect;\n\t\t\tint startX = i % length * image->width;\n\t\t\tint startY = i / length * image->height;\n\t\t\trect.x = startX;\n\t\t\trect.y = startY;\n\t\t\trect.w = image->width;\n\t\t\trect.h = image->height;\n\t\t\t_chars[str[i]] = std::make_pair(index, rect);\n\t\t}\n\t}\n\telse\n\t{\n\t\tfor (size_t i = 0; i < str.length(); ++i)\n\t\t{\n\t\t\tSDL_Rect rect;\n\t\t\tint left = -1, right = -1;\n\t\t\tint startX = i % length * image->width;\n\t\t\tint startY = i / length * image->height;\n\t\t\tfor (int x = startX; x < startX + image->width; ++x)\n\t\t\t{\n\t\t\t\tfor (int y = startY; y < startY + image->height && left == -1; ++y)\n\t\t\t\t{\n\t\t\t\t\tUint8 pixel = surface->getPixel(x, y);\n\t\t\t\t\tif (pixel != 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tleft = x;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (int x = startX + image->width - 1; x >= startX; --x)\n\t\t\t{\n\t\t\t\tfor (int y = startY + image->height; y-- != startY && right == -1;)\n\t\t\t\t{\n\t\t\t\t\tUint8 pixel = surface->getPixel(x, y);\n\t\t\t\t\tif (pixel != 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tright = x;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\trect.x = left;\n\t\t\trect.y = startY;\n\t\t\trect.w = right - left + 1;\n\t\t\trect.h = image->height;\n\n\t\t\t_chars[str[i]] = std::make_pair(index, rect);\n\t\t}\n\t}\n\tsurface->unlock();\n}\n\n/**\n * Returns a particular character from the set stored in the font.\n * @param c Character to use for size/position.\n * @return Pointer to the font's surface with the respective\n * cropping rectangle set up.\n */\nSurfaceCrop Font::getChar(UCode c) const\n{\n\tauto f = _chars.find(c);\n\tif (f == _chars.end())\n\t\tf = _chars.find('?');\n\tauto surfaceCrop = _images[f->second.first].surface->getCrop();\n\t*surfaceCrop.getCrop() = f->second.second;\n\treturn surfaceCrop;\n}\n\n/**\n * Returns the maximum width for any character in the font.\n * @return Width in pixels.\n */\nint Font::getWidth() const\n{\n\treturn _images[0].width;\n}\n\n/**\n * Returns the maximum height for any character in the font.\n * @return Height in pixels.\n */\nint Font::getHeight() const\n{\n\treturn _images[0].height;\n}\n\n/**\n * Returns the spacing between any character in the font.\n * @return Spacing in pixels.\n * @note This does not refer to character spacing within the surface,\n * but to the spacing used between successive characters in a line.\n */\nint Font::getSpacing() const\n{\n\treturn _images[0].spacing;\n}\n\n/**\n * Returns the dimensions of a particular character in the font.\n * @param c Font character.\n * @return Width and Height dimensions (X and Y are ignored).\n */\nSDL_Rect Font::getCharSize(UCode c) const\n{\n\tSDL_Rect size = { 0, 0, 0, 0 };\n\tif (Unicode::isPrintable(c))\n\t{\n\t\tauto f = _chars.find(c);\n\t\tif (f == _chars.end())\n\t\t\tf = _chars.find('?');\n\n\t\tconst FontImage *image = &_images[f->second.first];\n\t\tsize.w = f->second.second.w + image->spacing;\n\t\tsize.h = f->second.second.h + image->spacing;\n\t}\n\telse\n\t{\n\t\tif (_monospace)\n\t\t\tsize.w = getWidth() + getSpacing();\n\t\telse if (c == Unicode::TOK_NBSP)\n\t\t\tsize.w = getWidth() / 4;\n\t\telse if (c == '\\t')\n\t\t\tsize.w = getWidth() * 3 / 4;\n\t\telse\n\t\t\tsize.w = getWidth() / 2;\n\t\tsize.h = getHeight() + getSpacing();\n\t}\n\t// In case anyone mixes them up\n\tsize.x = size.w;\n\tsize.y = size.h;\n\treturn size;\n}\n\n}\n"
  },
  {
    "path": "src/Engine/Font.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <unordered_map>\n#include <vector>\n#include <utility>\n#include <SDL.h>\n#include \"../Engine/Yaml.h\"\n#include \"Unicode.h\"\n\n#include \"Surface.h\"\n\nnamespace OpenXcom\n{\n\nclass Surface;\nclass Palette;\n\nstruct FontImage\n{\n\tint width, height, spacing;\n\tSurface *surface;\n};\n\n/**\n * Takes care of loading and storing each character in a sprite font.\n * Sprite fonts consist of a set of characters split in fixed-size regions.\n * @note The characters don't all need to be the same size, they can\n * have blank space and will be automatically lined up properly.\n */\nclass Font\n{\nprivate:\n\tstd::vector<FontImage> _images;\n\tstd::unordered_map< UCode, std::pair<size_t, SDL_Rect> > _chars;\n\tbool _monospace;\n\t/// Determines the size and position of each character in the font.\n\tvoid init(size_t index, const UString &str);\npublic:\n\n\t/// Default palette for terminal text.\n\tstatic const SDL_Color TerminalColors[2];\n\n\t/// Creates a blank font.\n\tFont();\n\t/// Cleans up the font.\n\t~Font();\n\t/// Loads the font from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader);\n\t/// Generate the terminal font.\n\tvoid loadTerminal();\n\t/// Gets a particular character from the font, with its real size.\n\tSurfaceCrop getChar(UCode c) const;\n\t/// Gets the font's character width.\n\tint getWidth() const;\n\t/// Gets the font's character height.\n\tint getHeight() const;\n\t/// Gets the spacing between characters.\n\tint getSpacing() const;\n\t/// Gets the size of a particular character;\n\tSDL_Rect getCharSize(UCode c) const;\n};\n\n}\n"
  },
  {
    "path": "src/Engine/Functions.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <functional>\n\n\n\nnamespace OpenXcom\n{\n\n/**\n * Low overhead callback.\n *\n * Base template, not defined anywhere.\n */\ntemplate<typename T>\nclass FuncRef;\n\n/**\n * Low overhead callback.\n */\ntemplate<typename Ret, typename... Args>\nclass FuncRef<Ret(Args...)>\n{\npublic:\n\tusing ApiFunc = Ret(*)(Args...);\n\tusing InternalFunc = Ret(*)(Args..., void*);\n\n\t/**\n\t * A constructor that takes a reference to some temporary callable object.\n\t */\n\ttemplate<typename F>\n\tFuncRef(F&& f) :FuncRef{ +[](Args... args, void* p){ return std::invoke(*static_cast<std::remove_reference_t<F>*>(p), std::forward<Args>(args)...); }, &f }\n\t{\n\n\t}\n\n\t/**\n\t * Copy constructor.\n\t * @param f\n\t */\n\tFuncRef(const FuncRef& f) = default;\n\n\t/**\n\t * Move constructor.\n\t * @param f\n\t */\n\tFuncRef(FuncRef&& f) = default;\n\n\t/**\n\t * A constructor that takes a pointer to some callable object.\n\t */\n\ttemplate<typename P>\n\tconstexpr FuncRef(P* f) : FuncRef{ +[](Args... args, void* p){ return std::invoke(*reinterpret_cast<P*>(p), std::forward<Args>(args)...); }, reinterpret_cast<void*>(f) }\n\t{\n\t\tstatic_assert(sizeof(f) == sizeof(_data), \"This code works only if a void pointer has the same size as the given pointer (in special case function pointer)\");\n\t}\n\n\t/**\n\t * Invalid constructor from empty pointer.\n\t */\n\tFuncRef(std::nullptr_t) = delete;\n\n\t/**\n\t * Helper constructor for minimum overhead functions.\n\t * @param func Internal function to call.\n\t * @param data State that is passed to the internal function call.\n\t */\n\tconstexpr FuncRef(InternalFunc func, void* data) : _func{ func }, _data{ data }\n\t{\n\n\t}\n\n\t/**\n\t * Call operator.\n\t */\n\tconstexpr Ret operator()(Args... args) const\n\t{\n\t\treturn _func(std::forward<Args>(args)..., _data);\n\t}\n\n\t/**\n\t * bool operator\n\t * @return always true as it can't be empty.\n\t */\n\tconstexpr explicit operator bool()\n\t{\n\t\treturn true;\n\t}\n\nprivate:\n\n\tInternalFunc _func;\n\tvoid* _data;\n};\n\n\n} //namespace OpenXcom\n"
  },
  {
    "path": "src/Engine/GMCat.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"GMCat.h\"\n#include <vector>\n#include \"Music.h\"\n#include \"Logger.h\"\n#include \"SDL2Helpers.h\"\n\nnamespace OpenXcom\n{\n\nstatic inline unsigned read_uint32_le (const unsigned char *p)\n{\nreturn ((unsigned) p[0]) + (((unsigned) p[1]) << 8)\n\t+ (((unsigned) p[2]) << 16) + (((unsigned) p[3]) << 24);\n}\n\n/// MIDI sequence.\nstruct seq {\n\tunsigned size;\n\tconst unsigned char *data;\n};\n\n/// MIDI track.\nstruct track {\n\tstruct seq seq;\n\tunsigned channel;\n};\n\n/// MIDI stream.\nstruct gmstream {\n\tint tempo, nsubs, ntracks;\n\tstruct seq subs [256];\n\tstruct track tracks [256];\n};\n\nstatic int gmext_read_stream (struct gmstream *p,\n\tunsigned int n, const unsigned char *data)\n{\n\tif (!n--)\n\t\treturn -1;\n\tp->tempo = *data++;\n\n\t// subsequences\n\tif (!n--)\n\t\treturn -1;\n\tp->nsubs = *data++;\n\n\tfor (int i=0; i<p->nsubs; ++i) {\n\t\tif (n < 4)\n\t\t\treturn -1;\n\t\tunsigned int s = read_uint32_le(data);\n\t\tif (s < 4)\n\t\t\treturn -1;\n\t\tp->subs[i].size = s - 4;\n\t\tp->subs[i].data = data + 4;\n\t\tn -= s;\n\t\tdata += s;\n\t}\n\n\t// tracks\n\tif (!n--)\n\t\treturn -1;\n\tp->ntracks = *data++;\n\n\tfor (int i=0; i<p->ntracks; ++i) {\n\t\tif (n-- < 5)\n\t\t\treturn -1;\n\t\tp->tracks[i].channel = *data++;\n\t\tunsigned int s = read_uint32_le(data);\n\t\tif (s < 4)\n\t\t\treturn -1;\n\t\tp->tracks[i].seq.size = s - 4;\n\t\tp->tracks[i].seq.data = data + 4;\n\t\tn -= s;\n\t\tdata += s;\n\t}\n\n\treturn n ? -1 : 0;\n}\n\nstatic inline void gmext_write_int16 (std::vector<unsigned char> &midi,\n\tunsigned int n)\n{\n\tmidi.push_back(n >> 8);\n\tmidi.push_back(n);\n}\n\nstatic inline void gmext_write_delta (std::vector<unsigned char> &midi,\n\tunsigned int delta)\n{\n\tunsigned char data[4];\n\tunsigned int i = 0;\n\n\tdelta &= ((1<<28)-1);\n\tdo {\n\t\tdata[i++] = delta & 0x7F;\n\t\tdelta >>= 7;\n\t} while (delta > 0 && i <= 3);\n\n#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Warray-bounds\"\n\twhile (--i)\n\t\tmidi.push_back(data[i] | 0x80);\n#pragma GCC diagnostic pop\n\n\tmidi.push_back(data[0]);\n}\n\nstatic inline void gmext_write_tempo_ev (std::vector<unsigned char> &midi,\n\tunsigned int tempo)\n{\n\tmidi.push_back(0xFF);\n\tmidi.push_back(0x51);\n\tmidi.push_back(3);\n\ttempo = 60000000 / tempo;\n\tmidi.push_back(tempo >> 16);\n\tmidi.push_back(tempo >> 8);\n\tmidi.push_back(tempo);\n}\n\nstatic inline void gmext_write_end_ev (std::vector<unsigned char> &midi)\n{\n\tmidi.push_back(0xFF);\n\tmidi.push_back(0x2F);\n\tmidi.push_back(0);\n}\n\nstatic const unsigned int volume [0x80] = {\n\t100,100,100,100,100, 90,100,100,100,100,100, 90,100,100,100,100,\n\t100,100, 85,100,100,100,100,100,100,100,100,100, 90,90, 110, 80,\n\t100,100,100, 90, 70,100,100,100,100,100,100,100,100,100,100,100,\n\t100,100, 90,100,100,100,100,100,100,120,100,100,100,120,100,127,\n\t100,100, 90,100,100,100,100,100,100, 95,100,100,100,100,100,100,\n\t100,100,100,100,100,100,100,115,100,100,100,100,100,100,100,100,\n\t100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,\n\t100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,\n};\n\n/// Output status.\nstruct output_status {\n\tunsigned int delta;\n\tunsigned int patch;\n\tunsigned char prevcmd;\n};\n\nstatic int gmext_write_sequence (std::vector<unsigned char> &midi,\n\tconst struct gmstream *stream, unsigned int channel,\n\tconst struct seq *seq, struct output_status *status)\n{\n\tconst unsigned char *data = seq->data;\n\tunsigned int left = seq->size;\n\n\tunsigned char cmd = -1;\n\n\twhile (left) {\n\n\t\t// read delta\n\t\tunsigned int ndelta = 0;\n\n\t\tfor (int i=0; ; ) {\n\t\t\tunsigned char c = *data++;\n\t\t\tleft--;\n\t\t\tndelta += c & 0x7F;\n\t\t\tif (!(c & 0x80))\n\t\t\t\tbreak;\n\t\t\tif ((++i == 4) || !left)\n\t\t\t\treturn -1;\n\t\t\tndelta <<= 7;\n\t\t}\n\n\t\tstatus->delta += ndelta;\n\n\t\t// read cmd byte\n\t\tif (!left)\n\t\t\treturn -1;\n\n\t\tif (*data & 0x80) {\n\t\t\t// actual cmd byte\n\t\t\tcmd = *data++;\n\t\t\tleft--;\n\t\t\tswitch (cmd) {\n\t\t\t\tcase 0xFF:\t  // end track\n\t\t\t\tcase 0xFD:\t  // end subsequence\n\t\t\t\t\treturn 0;\n\t\t\t\tcase 0xFE:\t  // insert subsequence\n\t\t\t\t\tif (!left--)\n\t\t\t\t\t\treturn -1;\n\t\t\t\t\tif (*data >= stream->nsubs)\n\t\t\t\t\t\t// invalid subsequence\n\t\t\t\t\t\treturn -1;\n\t\t\t\t\tif (gmext_write_sequence(midi,\n\t\t\t\t\t\tstream, channel,\n\t\t\t\t\t\t&stream->subs[*data++], status)\n\t\t\t\t\t\t\t== -1)\n\t\t\t\t\t\treturn -1;\n\t\t\t\t\tcmd = 0;\n\t\t\t\t\tcontinue;\n\t\t\t\tdefault:\n\t\t\t\t\tcmd &= 0xF0;\n\t\t\t}\n\t\t} else if (cmd == 0)\n\t\t\treturn -1;\t  // invalid running mode\n\n\t\tif (!left--)\n\t\t\treturn -1;\n\t\tunsigned char data1 = *data++;\n\n\t\tswitch (cmd) {\n\n\t\t\tcase 0x80:\n\t\t\tcase 0x90: {\n\t\t\t\tif (!left--)\n\t\t\t\t\treturn -1;\n\t\t\t\tunsigned char data2 = *data++;\n\t\t\t\tif (data2)\n\t\t\t\t\tdata2 = (unsigned int) data2 *\n\t\t\t\t\t\t(channel==9 ? 80 : volume[status->patch]) >> 7;\n\t\t\t\tgmext_write_delta(midi, status->delta);\n\t\t\t\tmidi.push_back(cmd | channel);\n\t\t\t\tmidi.push_back(data1);\n\t\t\t\tmidi.push_back(data2);\n\t\t\t\t} break;\n\n\t\t\tcase 0xC0:\n\t\t\t\tif (data1 == 0x7E)\n\t\t\t\t\treturn 0;\t   // restart stream\n\t\t\t\tstatus->patch = data1;\n\t\t\t\tif ((data1 == 0x57) || (data1 == 0x3F))\n\t\t\t\t\tdata1 = 0x3E;\n\t\t\t\tgmext_write_delta(midi, status->delta);\n\t\t\t\tmidi.push_back(cmd | channel);\n\t\t\t\tmidi.push_back(data1);\n\t\t\t\tbreak;\n\n\t\t\tcase 0xB0: {\n\t\t\t\tif (!left--)\n\t\t\t\t\treturn -1;\n\t\t\t\tunsigned char data2 = *data++;\n\t\t\t\tif (data1 == 0x7E)\n\t\t\t\t\tcontinue;\n\t\t\t\tif (!data1) {\n\t\t\t\t\tif (!data2)\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\tgmext_write_delta(midi, status->delta);\n\t\t\t\t\tgmext_write_tempo_ev(midi, 2*data2);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (data1 == 0x5B)\n\t\t\t\t\tdata2 = 0x1E;\n\t\t\t\tgmext_write_delta(midi, status->delta);\n\t\t\t\tmidi.push_back(cmd | channel);\n\t\t\t\tmidi.push_back(data1);\n\t\t\t\tmidi.push_back(data2);\n\t\t\t\t} break;\n\n\t\t\tcase 0xE0: {\n\t\t\t\tif (!left--)\n\t\t\t\t\treturn -1;\n\t\t\t\tunsigned char data2 = *data++;\n\t\t\t\tgmext_write_delta(midi, status->delta);\n\t\t\t\tmidi.push_back(cmd | channel);\n\t\t\t\tmidi.push_back(data1);\n\t\t\t\tmidi.push_back(data2);\n\t\t\t\t} break;\n\n\t\t\tdefault:\t\t// unhandled cmd byte\n\t\t\t\treturn -1;\n\t\t}\n\n\t\tstatus->delta = 0;\n\t}\n\n\treturn 0;\n}\n\nstatic int gmext_write_midi (const struct gmstream *stream,\n\tstd::vector<unsigned char> &midi)\n{\n\t// write MIDI file header\n\tstatic const unsigned char midi_file_signature[8] =\n\t\t{ 'M','T','h','d',0,0,0,6 };\n\tfor (int i=0; i<8; ++i)\n\t\tmidi.push_back(midi_file_signature[i]);\n\tgmext_write_int16(midi, 1);\n\tgmext_write_int16(midi, stream->ntracks + 1);\n\tgmext_write_int16(midi, 24);\n\n\t// write global tempo track\n\tstatic const unsigned char midi_track_header[8] =\n\t\t{ 'M','T','r','k',0,0,0,11 };\n\tfor (int i=0; i<8; ++i)\n\t\tmidi.push_back(midi_track_header[i]);\n\tgmext_write_delta(midi, 0);\n\tgmext_write_tempo_ev(midi, stream->tempo);\n\tgmext_write_delta(midi, 0);\n\tgmext_write_end_ev(midi);\n\n\t// write tracks\n\tfor (int j=0; j<stream->ntracks; ++j) {\n\n\t\t// header\n\t\tfor (int i=0; i<4; ++i)\n\t\t\tmidi.push_back(midi_track_header[i]);\n\n\t\tsize_t loffset = midi.size();\n\t\tfor (int i=0; i<4; ++i)\n\t\t\tmidi.push_back(0);\n\n\t\t// initial data\n\t\tstatic const unsigned char midi_track_init[8] =\n\t\t\t{ /* 0, 0xB0, */ 0x78, 0, 0, 0x79, 0, 0, 0x7B, 0 };\n\t\tmidi.push_back(0);\n\t\tmidi.push_back(0xB0 | stream->tracks[j].channel);\n\t\tfor (int i=0; i<8; ++i)\n\t\t\tmidi.push_back(midi_track_init[i]);\n\n\t\t// body\n\t\tstruct output_status status = { 0, 0, 0 };\n\t\tif (gmext_write_sequence(midi, stream,\n\t\t\t\tstream->tracks[j].channel,\n\t\t\t\t&stream->tracks[j].seq, &status) == -1)\n\t\t\treturn -1;\n\n\t\t// end of track\n\t\tgmext_write_delta(midi, status.delta);\n\t\tgmext_write_end_ev(midi);\n\n\t\t// rewrite track length\n\t\tunsigned char *p = &midi[loffset];\n\t\tsize_t length = midi.size() - loffset - 4;\n\t\tp[0] = length >> 24;\n\t\tp[1] = length >> 16;\n\t\tp[2] = length >> 8;\n\t\tp[3] = length;\n\t}\n\n\treturn 0;\n}\n\n/**\n * Loads a MIDI object into memory.\n * @param i Music number to load.\n * @return Pointer to the loaded music.\n */\nMusic *GMCatFile::loadMIDI(unsigned int i)\n{\n\tMusic *music = new Music;\n\tauto cat_rwops = getRWops(i);\n\n\tif (!cat_rwops) { throw(\"Can't get GMcat object\"); }\n\n\t// stream info\n\tstruct gmstream stream;\n\tmemset(&stream, 0, sizeof(stream));\n\tsize_t size;\n\tauto nameskip = SDL_ReadU8(cat_rwops) + 1;\n\tSDL_RWseek(cat_rwops, RW_SEEK_SET, 0);\n\tauto data = (unsigned char *)SDL_LoadFile_RW(cat_rwops, &size, SDL_TRUE);\n\tif (gmext_read_stream(&stream, size - nameskip, data + nameskip) == -1) {\n\t\tLog(LOG_ERROR) << \"GMCatFile::loadMIDI(\"<<fileName()<<\", \"<<i<<\"): Error reading MIDI stream\";\n\t\treturn music;\n\t}\n\n\tstd::vector<unsigned char> midi;\n\tmidi.reserve(65536);\t// FIXME: well... what is this\n\n\tif (gmext_write_midi(&stream, midi) == -1) {\n\t\tLog(LOG_ERROR) << \"GMCatFile::loadMIDI(\"<<fileName()<<\", \"<<i<<\"): Error writing MIDI stream\";\n\t} else {\n\t\tmusic->load(SDL_RWFromConstMem(midi.data(), midi.size()));\n\t}\n\tLog(LOG_VERBOSE) << \"GMCatFile::loadMIDI(\"<<fileName()<<\", \"<<i<<\"): loaded ok.\";\n\tSDL_free(data);\n\treturn music;\n}\n}\n"
  },
  {
    "path": "src/Engine/GMCat.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"CatFile.h\"\n\nnamespace OpenXcom\n{\n\nclass Music;\n\n/**\n * Subclass of CatFile to handle gm.cat files\n * that contain MIDI music streams.\n */\nclass GMCatFile : public CatFile\n{\npublic:\n\t/// Inherit constructor.\n\tGMCatFile(const std::string& filename) : CatFile(filename) { }\n\t/// Loads a stream as a MIDI file.\n\tMusic *loadMIDI(unsigned int i);\n};\n\n}\n"
  },
  {
    "path": "src/Engine/Game.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Game.h\"\n#include \"../resource.h\"\n#include <algorithm>\n#include <cmath>\n#include <sstream>\n#include <SDL_mixer.h>\n#include \"State.h\"\n#include \"Screen.h\"\n#include \"Sound.h\"\n#include \"Music.h\"\n#include \"Language.h\"\n#include \"Logger.h\"\n#include \"../Interface/Cursor.h\"\n#include \"../Interface/FpsCounter.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"Action.h\"\n#include \"Exception.h\"\n#include \"Options.h\"\n#include \"CrossPlatform.h\"\n#include \"FileMap.h\"\n#include \"Unicode.h\"\n#include \"../Ufopaedia/UfopaediaStartState.h\"\n#include \"../Menu/NotesState.h\"\n#include \"../Geoscape/GeoscapeState.h\"\n#include \"../Menu/TestState.h\"\n#include <algorithm>\n#include \"../fallthrough.h\"\n\nnamespace OpenXcom\n{\n\nconst double Game::VOLUME_GRADIENT = 10.0;\n\n/**\n * Starts up all the SDL subsystems,\n * creates the display screen and sets up the cursor.\n * @param title Title of the game window.\n */\nGame::Game(const std::string &title) : _screen(0), _cursor(0), _lang(0), _save(0), _mod(0), _quit(false), _init(false), _update(false),  _mouseActive(true), _timeUntilNextFrame(0),\n\t_ctrl(false), _alt(false), _shift(false), _rmb(false), _mmb(false), _scrollStep(1)\n{\n\tOptions::reload = false;\n\tOptions::mute = false;\n\n\t// Initialize SDL\n\tif (SDL_Init(SDL_INIT_VIDEO) < 0)\n\t{\n\t\tLog(LOG_ERROR) << SDL_GetError();\n\t\tLog(LOG_WARNING) << \"No video detected, quit.\";\n\t\tthrow Exception(SDL_GetError());\n\t}\n\tLog(LOG_INFO) << \"SDL initialized successfully.\";\n\n\t// Initialize SDL_mixer\n\tinitAudio();\n\n\t// trap the mouse inside the window\n\tSDL_WM_GrabInput(Options::captureMouse);\n\n\t// Set the window icon\n\tCrossPlatform::setWindowIcon(IDI_ICON1, \"openxcom.png\");\n\n\t// Set the window caption\n\tSDL_WM_SetCaption(title.c_str(), 0);\n\n\t// Set up unicode\n\tSDL_EnableUNICODE(1);\n\tUnicode::getUtf8Locale();\n\n\t// Create display\n\t_screen = new Screen();\n\n\t// Create cursor\n\t_cursor = new Cursor(9, 13);\n\n\t// Create invisible hardware cursor to workaround bug with absolute positioning pointing devices\n\tSDL_ShowCursor(SDL_ENABLE);\n\tUint8 cursor = 0;\n\tSDL_SetCursor(SDL_CreateCursor(&cursor, &cursor, 1,1,0,0));\n\n\t// Create fps counter\n\t_fpsCounter = new FpsCounter(15, 5, 0, 0);\n\n\t// Create blank language\n\t_lang = new Language();\n\n\t_timeOfLastFrame = 0;\n}\n\n/**\n * Deletes the display screen, cursor, states and shuts down all the SDL subsystems.\n */\nGame::~Game()\n{\n\tSound::stop();\n\tMusic::stop();\n\n\tfor (auto* state : _states)\n\t{\n\t\tdelete state;\n\t}\n\n\tSDL_FreeCursor(SDL_GetCursor());\n\n\tdelete _cursor;\n\tdelete _lang;\n\tdelete _save;\n\tdelete _mod;\n\tdelete _screen;\n\tdelete _fpsCounter;\n\n\tMix_CloseAudio();\n\n\tSDL_Quit();\n}\n\n/**\n * The state machine takes care of passing all the events from SDL to the\n * active state, running any code within and blitting all the states and\n * cursor to the screen. This is run indefinitely until the game quits.\n */\nvoid Game::run()\n{\n\tenum ApplicationState { RUNNING = 0, SLOWED = 1, PAUSED = 2 } runningState = RUNNING;\n\tstatic const ApplicationState kbFocusRun[4] = { RUNNING, RUNNING, SLOWED, PAUSED };\n\tstatic const ApplicationState stateRun[4] = { SLOWED, PAUSED, PAUSED, PAUSED };\n\t// this will avoid processing SDL's resize event on startup, workaround for the heap allocation error it causes.\n\tbool startupEvent = Options::allowResize;\n\tUint32 lastMouseMoveEvent = 0;\n\tSint16 xrel = 0;\n\tSint16 yrel = 0;\n\n\twhile (!_quit)\n\t{\n\t\t// Clean up states\n\t\twhile (!_deleted.empty())\n\t\t{\n\t\t\tdelete _deleted.back();\n\t\t\t_deleted.pop_back();\n\t\t}\n\n\t\t// Initialize active state\n\t\tif (!_init)\n\t\t{\n\t\t\t_init = true;\n\t\t\t_states.back()->init();\n\n\t\t\t// Unpress buttons\n\t\t\t_states.back()->resetAll();\n\n\t\t\t// Refresh mouse position\n\t\t\tSDL_Event ev;\n\t\t\tint x, y;\n\t\t\tSDL_GetMouseState(&x, &y);\n\t\t\tev.type = SDL_MOUSEMOTION;\n\t\t\tev.motion.x = x;\n\t\t\tev.motion.y = y;\n\t\t\tAction action = Action(&ev, _screen->getXScale(), _screen->getYScale(), _screen->getCursorTopBlackBand(), _screen->getCursorLeftBlackBand());\n\t\t\t_states.back()->handle(&action);\n\t\t}\n\n\t\t// Process events\n\t\twhile (SDL_PollEvent(&_event))\n\t\t{\n\t\t\tif (CrossPlatform::isQuitShortcut(_event))\n\t\t\t\t_event.type = SDL_QUIT;\n\t\t\tswitch (_event.type)\n\t\t\t{\n\t\t\t\tcase SDL_QUIT:\n\t\t\t\t\tquit();\n\t\t\t\t\tbreak;\n\t\t\t\tcase SDL_ACTIVEEVENT:\n\t\t\t\t\t// An event other than SDL_APPMOUSEFOCUS change happened.\n\t\t\t\t\tif (reinterpret_cast<SDL_ActiveEvent*>(&_event)->state & ~SDL_APPMOUSEFOCUS)\n\t\t\t\t\t{\n\t\t\t\t\t\tUint8 currentState = SDL_GetAppState();\n\t\t\t\t\t\t// Game is minimized\n\t\t\t\t\t\tif (!(currentState & SDL_APPACTIVE))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\trunningState = stateRun[Options::pauseMode];\n\t\t\t\t\t\t\tif (Options::backgroundMute)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tsetVolume(0, 0, 0);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Game is not minimized but has no keyboard focus.\n\t\t\t\t\t\telse if (!(currentState & SDL_APPINPUTFOCUS))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\trunningState = kbFocusRun[Options::pauseMode];\n\t\t\t\t\t\t\tif (Options::backgroundMute)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tsetVolume(0, 0, 0);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Game has keyboard focus.\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\trunningState = RUNNING;\n\t\t\t\t\t\t\tif (Options::backgroundMute)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tsetVolume(Options::soundVolume, Options::musicVolume, Options::uiVolume);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase SDL_VIDEORESIZE:\n\t\t\t\t\tif (Options::allowResize)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (!startupEvent)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tOptions::newDisplayWidth = Options::displayWidth = std::max(Screen::ORIGINAL_WIDTH, _event.resize.w);\n\t\t\t\t\t\t\tOptions::newDisplayHeight = Options::displayHeight = std::max(Screen::ORIGINAL_HEIGHT, _event.resize.h);\n\t\t\t\t\t\t\tint dX = 0, dY = 0;\n\t\t\t\t\t\t\tScreen::updateScale(Options::battlescapeScale, Options::baseXBattlescape, Options::baseYBattlescape, false);\n\t\t\t\t\t\t\tScreen::updateScale(Options::geoscapeScale, Options::baseXGeoscape, Options::baseYGeoscape, false);\n\t\t\t\t\t\t\tfor (auto* state : _states)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tstate->resize(dX, dY);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t_screen->resetDisplay();\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tstartupEvent = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase SDL_MOUSEMOTION:\n\t\t\t\t\tif (Options::oxceThrottleMouseMoveEvent > 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tUint32 last = SDL_GetTicks();\n\t\t\t\t\t\tif (0 == lastMouseMoveEvent)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlastMouseMoveEvent = last;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (last - lastMouseMoveEvent < (Uint32)Options::oxceThrottleMouseMoveEvent)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\txrel += _event.motion.xrel;\n\t\t\t\t\t\t\tyrel += _event.motion.yrel;\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tlastMouseMoveEvent = 0;\n\t\t\t\t\t\t_event.motion.xrel += std::exchange(xrel, 0);\n\t\t\t\t\t\t_event.motion.yrel += std::exchange(yrel, 0);\n\t\t\t\t\t}\n\t\t\t\t\tFALLTHROUGH;\n\t\t\t\tcase SDL_MOUSEBUTTONDOWN:\n\t\t\t\tcase SDL_MOUSEBUTTONUP:\n\t\t\t\t\t// Skip mouse events if they're disabled\n\t\t\t\t\tif (!_mouseActive) continue;\n\t\t\t\t\t// re-gain focus on mouse-over or keypress.\n\t\t\t\t\trunningState = RUNNING;\n\t\t\t\t\t// Go on, feed the event to others\n\t\t\t\t\tFALLTHROUGH;\n\t\t\t\tdefault:\n\t\t\t\t\tAction action = Action(&_event, _screen->getXScale(), _screen->getYScale(), _screen->getCursorTopBlackBand(), _screen->getCursorLeftBlackBand());\n\t\t\t\t\t_screen->handle(&action);\n\t\t\t\t\t_cursor->handle(&action);\n\t\t\t\t\t_fpsCounter->handle(&action);\n\t\t\t\t\tif (action.getDetails()->type == SDL_KEYDOWN)\n\t\t\t\t\t{\n\t\t\t\t\t\t// \"ctrl-g\" grab input\n\t\t\t\t\t\tif (action.getDetails()->key.keysym.sym == SDLK_g && isCtrlPressed())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tOptions::captureMouse = (SDL_GrabMode)(!Options::captureMouse);\n\t\t\t\t\t\t\tSDL_WM_GrabInput(Options::captureMouse);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// \"ctrl-n\" notes UI\n\t\t\t\t\t\telse if (action.getDetails()->key.keysym.sym == SDLK_n && isCtrlPressed() && !isAltPressed())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (_save && !containsNotesState())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (_save->getSavedBattle())\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tif (!_save->getSavedBattle()->isBattlescapeStateBusy())\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tpushState(new NotesState(OPT_BATTLESCAPE));\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tpushState(new NotesState(OPT_GEOSCAPE));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (Options::debug)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (action.getDetails()->key.keysym.sym == SDLK_t && isCtrlPressed())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tpushState(new TestState);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// \"ctrl-u\" debug UI\n\t\t\t\t\t\t\telse if (action.getDetails()->key.keysym.sym == SDLK_u && isCtrlPressed())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tOptions::debugUi = !Options::debugUi;\n\t\t\t\t\t\t\t\t_states.back()->redrawText();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t_states.back()->handle(&action);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (!_init)\n\t\t\t{\n\t\t\t\t// States stack was changed, break the loop so new state\n\t\t\t\t// can be initialized before processing new events\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// Process rendering\n\t\tif (runningState != PAUSED)\n\t\t{\n\t\t\t// Process logic\n\t\t\t_states.back()->think();\n\t\t\t_fpsCounter->think();\n\t\t\tif (Options::FPS > 0 && !(Options::useOpenGL && Options::vSyncForOpenGL))\n\t\t\t{\n\t\t\t\t// Update our FPS delay time based on the time of the last draw.\n\t\t\t\tint fps = SDL_GetAppState() & SDL_APPINPUTFOCUS ? Options::FPS : Options::FPSInactive;\n\n\t\t\t\t_timeUntilNextFrame = (1000.0f / fps) - (SDL_GetTicks() - _timeOfLastFrame);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_timeUntilNextFrame = 0;\n\t\t\t}\n\n\t\t\tif (_init && _timeUntilNextFrame <= 0)\n\t\t\t{\n\t\t\t\t// make a note of when this frame update occurred.\n\t\t\t\t_timeOfLastFrame = SDL_GetTicks();\n\t\t\t\t_fpsCounter->addFrame();\n\t\t\t\t_screen->clear();\n\t\t\t\tstd::list<State*>::iterator i = _states.end();\n\t\t\t\tdo\n\t\t\t\t{\n\t\t\t\t\t--i;\n\t\t\t\t}\n\t\t\t\twhile (i != _states.begin() && !(*i)->isScreen());\n\n\t\t\t\tfor (; i != _states.end(); ++i)\n\t\t\t\t{\n\t\t\t\t\t(*i)->blit();\n\t\t\t\t}\n\t\t\t\t_fpsCounter->blit(_screen->getSurface());\n\t\t\t\t_cursor->blit(_screen->getSurface());\n\t\t\t\t_screen->flip();\n\t\t\t}\n\t\t}\n\n\t\t// Save on CPU\n\t\tswitch (runningState)\n\t\t{\n\t\t\tcase RUNNING:\n\t\t\t\tSDL_Delay(1); //Save CPU from going 100%\n\t\t\t\tbreak;\n\t\t\tcase SLOWED: case PAUSED:\n\t\t\t\tSDL_Delay(100); break; //More slowing down.\n\t\t}\n\t}\n\n\tOptions::save();\n}\n\n/**\n * Stops the state machine and the game is shut down.\n */\nvoid Game::quit()\n{\n\t// Hard-learned lesson: there's a billion+ situations, where this causes a corrupted save and subsequent crashes. It's not worth it!\n#if 0\n\t// Always save ironman\n\tif (_save != 0 && _save->isIronman() && !_save->getName().empty())\n\t{\n\t\tstd::string filename = CrossPlatform::sanitizeFilename(_save->getName()) + \".sav\";\n\t\t_save->save(filename, _mod);\n\t}\n#endif\n\t_quit = true;\n}\n\n/**\n * Changes the audio volume of the music and\n * sound effect channels.\n * @param sound Sound volume, from 0 to MIX_MAX_VOLUME.\n * @param music Music volume, from 0 to MIX_MAX_VOLUME.\n * @param ui UI volume, from 0 to MIX_MAX_VOLUME.\n */\nvoid Game::setVolume(int sound, int music, int ui)\n{\n\tif (!Options::mute)\n\t{\n\t\tif (sound >= 0)\n\t\t{\n\t\t\tsound = volumeExponent(sound) * (double)SDL_MIX_MAXVOLUME;\n\t\t\tMix_Volume(-1, sound);\n\t\t\tif (_save && _save->getSavedBattle())\n\t\t\t{\n\t\t\t\tMix_Volume(3, sound * _save->getSavedBattle()->getAmbientVolume());\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// channel 3: reserved for ambient sound effect.\n\t\t\t\tMix_Volume(3, sound / 2);\n\t\t\t}\n\t\t\t// channel 4: reserved for unit responses\n\t\t\tMix_Volume(4, sound);\n\t\t}\n\t\tif (music >= 0)\n\t\t{\n\t\t\tmusic = volumeExponent(music) * (double)SDL_MIX_MAXVOLUME;\n\t\t\tMix_VolumeMusic(music);\n\t\t}\n\t\tif (ui >= 0)\n\t\t{\n\t\t\tui = volumeExponent(ui) * (double)SDL_MIX_MAXVOLUME;\n\t\t\tMix_Volume(1, ui);\n\t\t\tMix_Volume(2, ui);\n\t\t}\n\t}\n}\n\ndouble Game::volumeExponent(int volume)\n{\n\treturn (exp(log(Game::VOLUME_GRADIENT + 1.0) * volume / (double)SDL_MIX_MAXVOLUME) -1.0 ) / Game::VOLUME_GRADIENT;\n}\n\n/**\n * Pops all the states currently in stack and pushes in the new state.\n * A shortcut for cleaning up all the old states when they're not necessary\n * like in one-way transitions.\n * @param state Pointer to the new state.\n */\nvoid Game::setState(State *state)\n{\n\twhile (!_states.empty())\n\t{\n\t\tpopState();\n\t}\n\tpushState(state);\n\t_init = false;\n}\n\n/**\n * Pushes a new state into the top of the stack and initializes it.\n * The new state will be used once the next game cycle starts.\n * @param state Pointer to the new state.\n */\nvoid Game::pushState(State *state)\n{\n\t_states.push_back(state);\n\t_init = false;\n}\n\n/**\n * Pops the last state from the top of the stack. Since states\n * can't actually be deleted mid-cycle, it's moved into a separate queue\n * which is cleared at the start of every cycle, so the transition\n * is seamless.\n */\nvoid Game::popState()\n{\n\t_deleted.push_back(_states.back());\n\t_states.pop_back();\n\t_init = false;\n}\n\n/**\n * Sets a new saved game for the game to use.\n * @param save Pointer to the saved game.\n */\nvoid Game::setSavedGame(SavedGame *save)\n{\n\tdelete _save;\n\t_save = save;\n}\n\n/**\n * Loads the mods specified in the game options.\n */\nvoid Game::loadMods()\n{\n\tMod::resetGlobalStatics();\n\tdelete _mod;\n\t_mod = new Mod();\n\t_mod->loadAll();\n}\n\n/**\n * Sets whether the mouse is activated.\n * If it is, mouse events are processed, otherwise\n * they are ignored and the cursor is hidden.\n * @param active Is mouse activated?\n */\nvoid Game::setMouseActive(bool active)\n{\n\t_mouseActive = active;\n\t_cursor->setVisible(active);\n}\n\n/**\n * Returns whether current state is *state\n * @param state The state to test against the stack state\n * @return Is state the current state?\n */\nbool Game::isState(State *state) const\n{\n\treturn !_states.empty() && _states.back() == state;\n}\n\n/**\n * Returns whether a UfopaediaStartState is in the background.\n * @return Is there a UfopaediaStartState in the background?\n */\nbool Game::containsUfopaediaStartState() const\n{\n\tfor (auto* state : _states)\n\t{\n\t\tauto* pedia = dynamic_cast<UfopaediaStartState*>(state);\n\t\tif (pedia)\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Returns whether a NotesState is in the background.\n * @return Is there a NotesState in the background?\n */\nbool Game::containsNotesState() const\n{\n\tfor (auto* state : _states)\n\t{\n\t\tauto* notes = dynamic_cast<NotesState*>(state);\n\t\tif (notes)\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Returns the GeoscapeState from the background (if available).\n * @return Pointer to GeoscapeState, or nullptr if not available.\n */\nGeoscapeState* Game::getGeoscapeState() const\n{\n\tfor (auto* state : _states)\n\t{\n\t\tauto* geoscape = dynamic_cast<GeoscapeState*>(state);\n\t\tif (geoscape)\n\t\t{\n\t\t\treturn geoscape;\n\t\t}\n\t}\n\treturn nullptr;\n}\n\n/**\n * Checks if the game is currently quitting.\n * @return whether the game is shutting down or not.\n */\nbool Game::isQuitting() const\n{\n\treturn _quit;\n}\n\n/**\n * Loads the most appropriate languages\n * given current system and game options.\n */\nvoid Game::loadLanguages()\n{\n\tconst std::string defaultLang = \"en-US\";\n\tstd::string currentLang = defaultLang;\n\n\t// No language set, detect based on system\n\tif (Options::language.empty())\n\t{\n\t\tstd::string locale = CrossPlatform::getLocale();\n\t\tstd::string lang = locale.substr(0, locale.find_first_of('-'));\n\t\t// Try to load full locale\n\t\tif (Language::isSupported(locale) && FileMap::fileExists(\"Language/\" + locale + \".yml\"))\n\t\t{\n\t\t\tcurrentLang = locale;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// Try to load language locale\n\t\t\tif (Language::isSupported(lang) && FileMap::fileExists(\"Language/\" + lang + \".yml\"))\n\t\t\t{\n\t\t\t\tcurrentLang = lang;\n\t\t\t}\n\t\t\t// Give up, use default\n\t\t\telse\n\t\t\t{\n\t\t\t\tcurrentLang = defaultLang;\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\t// Use options language\n\t\tif (FileMap::fileExists(\"Language/\" + Options::language + \".yml\"))\n\t\t{\n\t\t\tcurrentLang = Options::language;\n\t\t}\n\t\t// Language not found, use default\n\t\telse\n\t\t{\n\t\t\tcurrentLang = defaultLang;\n\t\t}\n\t}\n\tOptions::language = currentLang;\n\n\tdelete _lang;\n\t_lang = new Language();\n\n\tconst std::string dirLanguage = \"Language/\";\n\tconst std::string dirLanguageAndroid = \"Language/Android/\";\n\tconst std::string dirLanguageOXCE = \"Language/OXCE/\";\n\tconst std::string dirLanguageTechnical = \"Language/Technical/\";\n\n\tconst std::string defaultLangYml = defaultLang + \".yml\";\n\tconst std::string currentLangYml = currentLang + \".yml\";\n\n\t// get vertical VFS map slices for the four filenames,\n\t// then submit frecs in lockstep to the _lang->loadFile().\n\n\tauto slice = FileMap::getSlice(dirLanguage + defaultLangYml);\n\tauto sliceAndroid = FileMap::getSlice(dirLanguageAndroid + defaultLangYml);\n\tauto sliceOXCE = FileMap::getSlice(dirLanguageOXCE + defaultLangYml);\n\tauto sliceTechnical = FileMap::getSlice(dirLanguageTechnical + defaultLangYml);\n\n\tauto slice2 = FileMap::getSlice(dirLanguage + currentLangYml);\n\tauto sliceAndroid2 = FileMap::getSlice(dirLanguageAndroid + currentLangYml);\n\tauto sliceOXCE2 = FileMap::getSlice(dirLanguageOXCE + currentLangYml);\n\tauto sliceTechnical2 = FileMap::getSlice(dirLanguageTechnical + currentLangYml);\n\n\tbool twoLangs = currentLang != defaultLang;\n\tfor (size_t i = 0; i < slice.size(); ++i) {\n\t\tif (slice[i]) { _lang->loadFile(slice[i]); }\n\t\tif (twoLangs && slice2[i]) { _lang->loadFile(slice2[i]); }\n\t\tif (sliceAndroid[i]) { _lang->loadFile(sliceAndroid[i]); }\n\t\tif (twoLangs && sliceAndroid2[i]) { _lang->loadFile(sliceAndroid2[i]); }\n\t\tif (sliceOXCE[i]) { _lang->loadFile(sliceOXCE[i]); }\n\t\tif (twoLangs && sliceOXCE2[i]) { _lang->loadFile(sliceOXCE2[i]); }\n\t\tif (sliceTechnical[i]) { _lang->loadFile(sliceTechnical[i]); }\n\t\tif (twoLangs && sliceTechnical2[i]) { _lang->loadFile(sliceTechnical2[i]); }\n\t}\n\n\t_lang->loadRule(_mod->getExtraStrings(), defaultLang);\n\tif (twoLangs)\n\t\t_lang->loadRule(_mod->getExtraStrings(), currentLang);\n}\n\n/**\n * Initializes the audio subsystem.\n */\nvoid Game::initAudio()\n{\n\tif (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)\n\t{\n\t\tLog(LOG_ERROR) << SDL_GetError();\n\t\tLog(LOG_WARNING) << \"No sound device detected, audio disabled.\";\n\t\tOptions::mute = true;\n\t\treturn;\n\t}\n\n\tUint16 format = MIX_DEFAULT_FORMAT;\n\tif (Options::audioBitDepth == 8)\n\t\tformat = AUDIO_S8;\n\n\tif (Options::audioSampleRate % 11025 != 0)\n\t{\n\t\tLog(LOG_WARNING) << \"Custom sample rate \" << Options::audioSampleRate << \"Hz, audio that doesn't match will be distorted!\";\n\t\tLog(LOG_WARNING) << \"SDL_mixer only supports multiples of 11025Hz.\";\n\t}\n\tint minChunk = Options::audioSampleRate / 11025 * 512;\n\tOptions::audioChunkSize = std::max(minChunk, Options::audioChunkSize);\n\n\tif (Mix_OpenAudio(Options::audioSampleRate, format, MIX_DEFAULT_CHANNELS, Options::audioChunkSize) != 0)\n\t{\n\t\tLog(LOG_ERROR) << Mix_GetError();\n\t\tLog(LOG_WARNING) << \"Sound device failed, audio disabled.\";\n\t\tOptions::mute = true;\n\t}\n\telse\n\t{\n\t\tMix_AllocateChannels(16);\n\t\t// Set up reserved channels:\n\t\t// 0 = not used?\n\t\t// 1-2 = UI\n\t\t// 3 = ambient\n\t\t// 4 = unit responses (OXCE only)\n\t\tMix_ReserveChannels(5);\n\t\tMix_GroupChannels(1, 2, 0);\n\t\tLog(LOG_INFO) << \"SDL_mixer initialized successfully.\";\n\t\tsetVolume(Options::soundVolume, Options::musicVolume, Options::uiVolume);\n\t}\n}\n\n/**\n * Is CTRL pressed?\n */\nbool Game::isCtrlPressed(bool considerTouchButtons) const\n{\n\tif (considerTouchButtons && _ctrl)\n\t{\n\t\treturn true;\n\t}\n\treturn (SDL_GetModState() & KMOD_CTRL) != 0;\n}\n\n/**\n * Is ALT pressed?\n */\nbool Game::isAltPressed(bool considerTouchButtons) const\n{\n\tif (considerTouchButtons && _alt)\n\t{\n\t\treturn true;\n\t}\n\treturn (SDL_GetModState() & KMOD_ALT) != 0;\n}\n\n/**\n * Is SHIFT pressed?\n */\nbool Game::isShiftPressed(bool considerTouchButtons) const\n{\n\tif (considerTouchButtons && _shift)\n\t{\n\t\treturn true;\n\t}\n\treturn (SDL_GetModState() & KMOD_SHIFT) != 0;\n}\n\n/**\n * Is LMB pressed?\n */\nbool Game::isLeftClick(Action* action, bool considerTouchButtons) const\n{\n\tif (considerTouchButtons)\n\t{\n\t\treturn (action->getDetails()->button.button == SDL_BUTTON_LEFT) && !_rmb && !_mmb;\n\t}\n\treturn (action->getDetails()->button.button == SDL_BUTTON_LEFT);\n}\n\n/**\n * Is RMB pressed?\n */\nbool Game::isRightClick(Action* action, bool considerTouchButtons) const\n{\n\tif (considerTouchButtons)\n\t{\n\t\treturn (action->getDetails()->button.button == SDL_BUTTON_RIGHT) || ((action->getDetails()->button.button == SDL_BUTTON_LEFT) && _rmb);\n\t}\n\treturn (action->getDetails()->button.button == SDL_BUTTON_RIGHT);\n}\n\n/**\n * Is MMB pressed?\n */\nbool Game::isMiddleClick(Action* action, bool considerTouchButtons) const\n{\n\tif (considerTouchButtons)\n\t{\n\t\treturn (action->getDetails()->button.button == SDL_BUTTON_MIDDLE) || ((action->getDetails()->button.button == SDL_BUTTON_LEFT) && _mmb);\n\t}\n\treturn (action->getDetails()->button.button == SDL_BUTTON_MIDDLE);\n}\n\n/**\n * Resets the touch button flags.\n */\nvoid Game::resetTouchButtonFlags()\n{\n\t_ctrl = false;\n\t_alt = false;\n\t_shift = false;\n\t_rmb = false;\n\t_mmb = false;\n\t_scrollStep = 1;\n}\n\n}\n"
  },
  {
    "path": "src/Engine/Game.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <list>\n#include <string>\n#include <SDL.h>\n\nnamespace OpenXcom\n{\n\nclass State;\nclass Screen;\nclass Cursor;\nclass Language;\nclass SavedGame;\nclass Mod;\nclass ModInfo;\nclass FpsCounter;\nclass Action;\nclass GeoscapeState;\n\n/**\n * The core of the game engine, manages the game's entire contents and structure.\n * Takes care of encapsulating all the core SDL commands, provides access to all\n * the game's resources and contains a stack state machine to handle all the\n * initializations, events and blits of each state, as well as transitions.\n */\nclass Game\n{\nprivate:\n\tSDL_Event _event;\n\tScreen *_screen;\n\tCursor *_cursor;\n\tLanguage *_lang;\n\tstd::list<State*> _states, _deleted;\n\tSavedGame *_save;\n\tMod *_mod;\n\tbool _quit, _init, _update;\n\tFpsCounter *_fpsCounter;\n\tbool _mouseActive;\n\tunsigned int _timeOfLastFrame;\n\tint _timeUntilNextFrame;\n\tbool _ctrl, _alt, _shift, _rmb, _mmb;\n\tint _scrollStep;\n\tstatic const double VOLUME_GRADIENT;\n\npublic:\n\t/// Creates a new game and initializes SDL.\n\tGame(const std::string &title);\n\t/// Cleans up all the game's resources and shuts down SDL.\n\t~Game();\n\t/// Starts the game's state machine.\n\tvoid run();\n\t/// Quits the game.\n\tvoid quit();\n\t/// Sets the game's audio volume.\n\tvoid setVolume(int sound, int music, int ui);\n\t/// Adjusts a linear volume level to an exponential one.\n\tstatic double volumeExponent(int volume);\n\t/// Gets the game's display screen.\n\tScreen *getScreen() const { return _screen; }\n\t/// Gets the game's cursor.\n\tCursor *getCursor() const { return _cursor; }\n\t/// Gets the FpsCounter.\n\tFpsCounter *getFpsCounter() const { return _fpsCounter; }\n\t/// Resets the state stack to a new state.\n\tvoid setState(State *state);\n\t/// Pushes a new state into the state stack.\n\tvoid pushState(State *state);\n\t/// Pops the last state from the state stack.\n\tvoid popState();\n\t/// Gets the currently loaded language.\n\tLanguage *getLanguage() const { return _lang; }\n\t/// Gets the currently loaded saved game.\n\tSavedGame *getSavedGame() const { return _save; }\n\t/// Sets a new saved game for the game.\n\tvoid setSavedGame(SavedGame *save);\n\t/// Gets the currently loaded mod.\n\tMod *getMod() const { return _mod; }\n\t/// Loads the mods specified in the game options.\n\tvoid loadMods();\n\t/// Sets whether the mouse cursor is activated.\n\tvoid setMouseActive(bool active);\n\t/// Returns whether current state is the param state\n\tbool isState(State *state) const;\n\t/// Returns whether a UfopaediaStartState is in the background.\n\tbool containsUfopaediaStartState() const;\n\t/// Returns whether a NotesState is in the background.\n\tbool containsNotesState() const;\n\t/// Returns the GeoscapeState from the background (if available).\n\tGeoscapeState* getGeoscapeState() const;\n\t/// Returns whether the game is shutting down.\n\tbool isQuitting() const;\n\t/// Loads the default and current language.\n\tvoid loadLanguages();\n\t/// Sets up the audio.\n\tvoid initAudio();\n\t/// Sets the update flag.\n\tvoid setUpdateFlag(bool update) { _update = update; }\n\t/// Returns the update flag.\n\tbool getUpdateFlag() const { return _update; }\n\n\t/// Is CTRL pressed?\n\tbool isCtrlPressed(bool considerTouchButtons = false) const;\n\t/// Is ALT pressed?\n\tbool isAltPressed(bool considerTouchButtons = false) const;\n\t/// Is SHIFT pressed?\n\tbool isShiftPressed(bool considerTouchButtons = false) const;\n\n\t/// Is LMB pressed?\n\tbool isLeftClick(Action* action, bool considerTouchButtons = false) const;\n\t/// Is RMB pressed?\n\tbool isRightClick(Action* action, bool considerTouchButtons = false) const;\n\t/// Is MMB pressed?\n\tbool isMiddleClick(Action* action, bool considerTouchButtons = false) const;\n\n\t/// Resets the touch button flags.\n\tvoid resetTouchButtonFlags();\n\n\t/// Sets the _ctrl flag.\n\tvoid setCtrlPressedFlag(bool newValue) { _ctrl = newValue; }\n\tvoid toggleCtrlPressedFlag() { _ctrl = !_ctrl; }\n\t/// Sets the _alt flag.\n\tvoid setAltPressedFlag(bool newValue) { _alt = newValue; }\n\tvoid toggleAltPressedFlag() { _alt = !_alt; }\n\t/// Sets the _shift flag.\n\tvoid setShiftPressedFlag(bool newValue) { _shift = newValue; }\n\tvoid toggleShiftPressedFlag() { _shift = !_shift; }\n\n\t/// Gets the _ctrl flag.\n\tbool getCtrlPressedFlag() const { return _ctrl; }\n\t/// Gets the _alt flag.\n\tbool getAltPressedFlag() const { return _alt; }\n\t/// Gets the _shift flag.\n\tbool getShiftPressedFlag() const { return _shift; }\n\n\t/// Sets the _rmb flag.\n\tvoid setRMBFlag(bool newValue) { _rmb = newValue; }\n\tvoid toggleRMBFlag() { _rmb = !_rmb; }\n\t/// Sets the _mmb flag.\n\tvoid setMMBFlag(bool newValue) { _mmb = newValue; }\n\tvoid toggleMMBFlag() { _mmb = !_mmb; }\n\n\t/// Gets the _rmb flag.\n\tbool getRMBFlag() const { return _rmb; }\n\t/// Gets the _mmb flag.\n\tbool getMMBFlag() const { return _mmb; }\n\n\t/// Sets the scroll step value.\n\tvoid setScrollStep(int newValue) { _scrollStep = newValue; }\n\n\t/// Gets the scroll step value.\n\tint getScrollStep() const { return _scrollStep; }\n};\n\n}\n"
  },
  {
    "path": "src/Engine/GraphSubset.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <utility>\n#include <algorithm>\n\nnamespace OpenXcom\n{\n\n/**\n * Generic class that represents some subset of 2d space\n */\ntemplate<typename Tag, typename DataType>\nstruct AreaSubset\n{\n\n\t//define part of surface\n\tDataType beg_x, end_x;\n\tDataType beg_y, end_y;\n\n\tAreaSubset():\n\t\t\tbeg_x(0), end_x(0),\n\t\t\tbeg_y(0), end_y(0)\n\t{\n\n\t}\n\n\tAreaSubset(int max_x, int max_y):\n\t\t\tbeg_x(0), end_x(max_x),\n\t\t\tbeg_y(0), end_y(max_y)\n\t{\n\n\t}\n\n\n\tAreaSubset(std::pair<int, int> range_x, std::pair<int, int> range_y):\n\t\t\tbeg_x(range_x.first), end_x(range_x.second),\n\t\t\tbeg_y(range_y.first), end_y(range_y.second)\n\t{\n\n\t}\n\n\tAreaSubset(const AreaSubset& r) = default;\n\n\tAreaSubset& operator=(const AreaSubset& r) = default;\n\n\tinline AreaSubset offset(int x, int y) const\n\t{\n\t\tAreaSubset ret = *this;\n\t\tret.beg_x += x;\n\t\tret.end_x += x;\n\t\tret.beg_y += y;\n\t\tret.end_y += y;\n\t\treturn ret;\n\t}\n\n\tinline int size_x() const\n\t{\n\t\treturn end_x - beg_x;\n\t}\n\n\tinline int size_y() const\n\t{\n\t\treturn end_y - beg_y;\n\t}\n\n\t/**\n\t * Check if area is empty.\n\t * @return True if have non-zero area.\n\t */\n\texplicit operator bool() const\n\t{\n\t\treturn size_x() && size_y();\n\t}\n\n\t/**\n\t * Check if two areas are same.\n\t */\n\tbool operator==(const AreaSubset& other) const\n\t{\n\t\treturn\n\t\t\tbeg_x == other.beg_x &&\n\t\t\tend_x == other.end_x &&\n\n\t\t\tbeg_y == other.beg_y &&\n\t\t\tend_y == other.end_y &&\n\n\t\t\ttrue;\n\t}\n\n\t/**\n\t * Check if two areas are not same.\n\t */\n\tbool operator!=(const AreaSubset& other) const\n\t{\n\t\treturn !(*this == other);\n\t}\n\n\tstatic inline void intersectionRange(DataType& begin_a, DataType& end_a, const DataType& begin_b, const DataType& end_b)\n\t{\n\t\tif (begin_a >= end_b || begin_b >= end_a)\n\t\t{\n\t\t\t//intersection is empty\n\t\t\tend_a = begin_a;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tbegin_a = std::max(begin_a, begin_b);\n\t\t\tend_a = std::min(end_a, end_b);\n\t\t}\n\t}\n\tstatic inline void boundBoxRange(DataType& begin_a, DataType& end_a, const DataType& begin_b, const DataType& end_b)\n\t{\n\t\tif (begin_b < end_b && begin_a < end_a)\n\t\t{\n\t\t\tbegin_a = std::min(begin_a, begin_b);\n\t\t\tend_a = std::max(end_a, end_b);\n\t\t}\n\t\telse if (begin_b < end_b)\n\t\t{\n\t\t\tbegin_a = begin_b;\n\t\t\tend_a = end_b;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t//keep first range same\n\t\t}\n\t}\n\n\tstatic inline AreaSubset intersection(const AreaSubset& a, const AreaSubset& b)\n\t{\n\t\tAreaSubset ret = a;\n\t\tintersectionRange(ret.beg_x, ret.end_x, b.beg_x, b.end_x);\n\t\tintersectionRange(ret.beg_y, ret.end_y, b.beg_y, b.end_y);\n\t\treturn ret;\n\t}\n\tstatic inline AreaSubset intersection(const AreaSubset& a, const AreaSubset& b, const AreaSubset& c)\n\t{\n\t\tAreaSubset ret = intersection(a, b);\n\t\tintersectionRange(ret.beg_x, ret.end_x, c.beg_x, c.end_x);\n\t\tintersectionRange(ret.beg_y, ret.end_y, c.beg_y, c.end_y);\n\t\treturn ret;\n\t}\n\tstatic inline AreaSubset intersection(const AreaSubset& a, const AreaSubset& b, const AreaSubset& c, const AreaSubset& d)\n\t{\n\t\tAreaSubset ret = intersection(a, b, c);\n\t\tintersectionRange(ret.beg_x, ret.end_x, d.beg_x, d.end_x);\n\t\tintersectionRange(ret.beg_y, ret.end_y, d.beg_y, d.end_y);\n\t\treturn ret;\n\t}\n\tstatic inline AreaSubset boundBox(const AreaSubset& a, const AreaSubset& b)\n\t{\n\t\tAreaSubset ret = a;\n\t\tboundBoxRange(ret.beg_x, ret.end_x, b.beg_x, b.end_x);\n\t\tboundBoxRange(ret.beg_y, ret.end_y, b.beg_y, b.end_y);\n\t\treturn ret;\n\t}\n\tstatic inline AreaSubset boundBox(const AreaSubset& a, const AreaSubset& b, const AreaSubset& c)\n\t{\n\t\tAreaSubset ret = boundBox(a, b);\n\t\tboundBoxRange(ret.beg_x, ret.end_x, c.beg_x, c.end_x);\n\t\tboundBoxRange(ret.beg_y, ret.end_y, c.beg_y, c.end_y);\n\t\treturn ret;\n\t}\n\n\n\n\tstatic inline AreaSubset fromPoint(int x, int y)\n\t{\n\t\treturn AreaSubset{ 1, 1 }.offset(x, y);\n\t}\n};\n\n/**\n * Subset of graphic surface\n */\nusing GraphSubset = AreaSubset<void, int>;\n\n}//namespace OpenXcom\n"
  },
  {
    "path": "src/Engine/HelperMeta.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2015 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\nnamespace OpenXcom\n{\n\nnamespace helper\n{\n\n/**\n * Tag class used for function tag dispatch based on type.\n */\ntemplate<typename T>\nstruct TypeTag\n{\n\tusing type = T;\n};\n\n/**\n * Tag class used for function tag dispatch based on int value.\n */\ntemplate<int I>\nstruct PosTag\n{\n\tstatic constexpr int value = I;\n};\n\n/**\n * Tag class with list of integers.\n */\ntemplate<int... I>\nstruct ListTag\n{\n\tstatic constexpr int size = sizeof...(I);\n};\n\n/**\n * Implementation used to create ListTag.\n */\ntemplate<typename PT>\nstruct ImplMakeListTagAdd;\n\n/**\n * Implementation used to create ListTag.\n */\ntemplate<int... I>\nstruct ImplMakeListTagAdd<ListTag<I...>>\n{\n\tusing type = ListTag<I..., sizeof...(I)>;\n};\n\n/**\n * Implementation used to create ListTag.\n */\ntemplate<int I>\nstruct ImplMakeListTag\n{\n\tusing type = typename ImplMakeListTagAdd<typename ImplMakeListTag<I - 1>::type>::type;\n};\n\n/**\n * Implementation used to create ListTag.\n */\ntemplate<>\nstruct ImplMakeListTag<0>\n{\n\tusing type = ListTag<>;\n};\n\n/**\n * Create ListTag with template parameters starting from `0` to `I - 1`.\n */\ntemplate<int I>\nusing MakeListTag = typename ImplMakeListTag<I>::type;\n\n/**\n * Remove all cv like const or volatile\n */\ntemplate<typename T>\nusing Decay = typename std::decay<T>::type;\n\n/**\n * Helper used to delay static assertion error test.\n */\ntemplate<typename>\nstruct StaticError\n{\n\tstatic constexpr bool value = false;\n};\n\n/**\n * Helper for making some code run only once\n */\nclass SingleRun\n{\n\tbool _done = false;\n\npublic:\n\n\t/**\n\t * Check if this function was already ran.\n\t * @return True if this is first time, False if any other until reseted.\n\t */\n\tbool tryRun()\n\t{\n\t\tif (_done)\n\t\t{\n\t\t\treturn false;\n\t\t}\n\n\t\t_done = true;\n\t\treturn true;\n\t}\n\n\t/**\n\t * Reset stat to starting condition.\n\t */\n\tvoid reset()\n\t{\n\t\t_done = false;\n\t}\n};\n\n\n} //namespace helper\n\n} //namespace OpenXcom\n"
  },
  {
    "path": "src/Engine/InteractiveSurface.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"InteractiveSurface.h\"\n#include \"Action.h\"\n\nnamespace OpenXcom\n{\n\nconst SDLKey InteractiveSurface::SDLK_ANY = (SDLKey)-1; // using an unused keycode to represent an \"any key\"\n\n/**\n * Sets up a blank interactive surface with the specified size and position.\n * @param width Width in pixels.\n * @param height Height in pixels.\n * @param x X position in pixels.\n * @param y Y position in pixels.\n */\nInteractiveSurface::InteractiveSurface(int width, int height, int x, int y) : Surface(width, height, x, y), _buttonsPressed(0), _in(0), _over(0), _out(0), _isHovered(false), _isFocused(true), _listButton(false), _tftdMode(false)\n{\n}\n\n/**\n *\n */\nInteractiveSurface::~InteractiveSurface()\n{\n}\n\nbool InteractiveSurface::isButtonHandled(Uint8 button)\n{\n\tbool handled = (_click.find(0) != _click.end() ||\n\t\t\t\t\t_press.find(0) != _press.end() ||\n\t\t\t\t\t_release.find(0) != _release.end());\n\tif (!handled && button != 0)\n\t{\n\t\thandled = (_click.find(button) != _click.end() ||\n\t\t\t\t   _press.find(button) != _press.end() ||\n\t\t\t\t   _release.find(button) != _release.end());\n\t}\n\treturn handled;\n}\n\nbool InteractiveSurface::isButtonPressed(Uint8 button) const\n{\n\tif (button == 0)\n\t{\n\t\treturn (_buttonsPressed != 0);\n\t}\n\telse\n\t{\n\t\treturn (_buttonsPressed & SDL_BUTTON(button)) != 0;\n\t}\n}\n\nvoid InteractiveSurface::setButtonPressed(Uint8 button, bool pressed)\n{\n\tif (pressed)\n\t{\n\t\t_buttonsPressed |= SDL_BUTTON(button);\n\t}\n\telse\n\t{\n\t\t_buttonsPressed &= (~SDL_BUTTON(button));\n\t}\n}\n\n/**\n * Changes the visibility of the surface. A hidden surface\n * isn't blitted nor receives events.\n * @param visible New visibility.\n */\nvoid InteractiveSurface::setVisible(bool visible)\n{\n\tSurface::setVisible(visible);\n\t// Unpress button if it was hidden\n\tif (!_visible)\n\t{\n\t\tunpress(0);\n\t}\n}\n\n/**\n * Called whenever an action occurs, and processes it to\n * check if it's relevant to the surface and convert it\n * into a meaningful interaction like a \"click\", calling\n * the respective handlers.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid InteractiveSurface::handle(Action *action, State *state)\n{\n\tif (!_visible || _hidden)\n\t\treturn;\n\n\taction->setSender(this);\n\n\tif (action->getDetails()->type == SDL_MOUSEBUTTONUP || action->getDetails()->type == SDL_MOUSEBUTTONDOWN)\n\t{\n\t\taction->setMouseAction(action->getDetails()->button.x, action->getDetails()->button.y, getX(), getY());\n\t}\n\telse if (action->getDetails()->type == SDL_MOUSEMOTION)\n\t{\n\t\taction->setMouseAction(action->getDetails()->motion.x, action->getDetails()->motion.y, getX(), getY());\n\t}\n\n\tif (action->isMouseAction())\n\t{\n\t\tif ((action->getAbsoluteXMouse() >= getX() && action->getAbsoluteXMouse() < getX() + getWidth()) &&\n\t\t\t(action->getAbsoluteYMouse() >= getY() && action->getAbsoluteYMouse() < getY() + getHeight()))\n\t\t{\n\t\t\tif (!_isHovered)\n\t\t\t{\n\t\t\t\t_isHovered = true;\n\t\t\t\tmouseIn(action, state);\n\t\t\t}\n\t\t\tif (_listButton && action->getDetails()->type == SDL_MOUSEMOTION)\n\t\t\t{\n\t\t\t\t_buttonsPressed = SDL_GetMouseState(0, 0);\n\t\t\t\tfor (Uint8 i = 1; i <= NUM_BUTTONS; ++i)\n\t\t\t\t{\n\t\t\t\t\tif (isButtonPressed(i))\n\t\t\t\t\t{\n\t\t\t\t\t\taction->getDetails()->button.button = i;\n\t\t\t\t\t\tmousePress(action, state);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tmouseOver(action, state);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (_isHovered)\n\t\t\t{\n\t\t\t\t_isHovered = false;\n\t\t\t\tmouseOut(action, state);\n\t\t\t\tif (_listButton && action->getDetails()->type == SDL_MOUSEMOTION)\n\t\t\t\t{\n\t\t\t\t\tfor (Uint8 i = 1; i <= NUM_BUTTONS; ++i)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (isButtonPressed(i))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsetButtonPressed(i, false);\n\t\t\t\t\t\t}\n\t\t\t\t\t\taction->getDetails()->button.button = i;\n\t\t\t\t\t\tmouseRelease(action, state);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (action->getDetails()->type == SDL_MOUSEBUTTONDOWN)\n\t{\n\t\tif (_isHovered && !isButtonPressed(action->getDetails()->button.button))\n\t\t{\n\t\t\tsetButtonPressed(action->getDetails()->button.button, true);\n\t\t\tmousePress(action, state);\n\t\t}\n\t}\n\telse if (action->getDetails()->type == SDL_MOUSEBUTTONUP)\n\t{\n\t\tif (isButtonPressed(action->getDetails()->button.button))\n\t\t{\n\t\t\tsetButtonPressed(action->getDetails()->button.button, false);\n\t\t\tmouseRelease(action, state);\n\t\t\tif (_isHovered)\n\t\t\t{\n\t\t\t\tmouseClick(action, state);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (_isFocused)\n\t{\n\t\tif (action->getDetails()->type == SDL_KEYDOWN)\n\t\t{\n\t\t\tkeyboardPress(action, state);\n\t\t}\n\t\telse if (action->getDetails()->type == SDL_KEYUP)\n\t\t{\n\t\t\tkeyboardRelease(action, state);\n\t\t}\n\t}\n}\n\n/**\n * Changes the surface's focus. Surfaces will only receive\n * keyboard events if focused.\n * @param focus Is it focused?\n */\nvoid InteractiveSurface::setFocus(bool focus, bool modal)\n{\n\t_isFocused = focus;\n}\n\n/**\n * Returns the surface's focus. Surfaces will only receive\n * keyboard events if focused.\n * @return Is it focused?\n */\nbool InteractiveSurface::isFocused() const\n{\n\treturn _isFocused;\n}\n\n/**\n * Simulates a \"mouse button release\". Used in circumstances\n * where the surface is unpressed without user input.\n * @param state Pointer to running state.\n */\nvoid InteractiveSurface::unpress(State *state)\n{\n\tif (isButtonPressed())\n\t{\n\t\t_buttonsPressed = 0;\n\t\tSDL_Event ev;\n\t\tev.type = SDL_MOUSEBUTTONUP;\n\t\tev.button.button = SDL_BUTTON_LEFT;\n\t\tAction a = Action(&ev, 0.0, 0.0, 0, 0);\n\t\tmouseRelease(&a, state);\n\t}\n}\n\n/**\n * Called every time there's a mouse press over the surface.\n * Allows the surface to have custom functionality for this action,\n * and can be called externally to simulate the action.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid InteractiveSurface::mousePress(Action *action, State *state)\n{\n\tauto allHandler = _press.find(0);\n\tauto oneHandler = _press.find(action->getDetails()->button.button);\n\tif (allHandler != _press.end())\n\t{\n\t\tActionHandler handler = allHandler->second;\n\t\t(state->*handler)(action);\n\t}\n\tif (oneHandler != _press.end())\n\t{\n\t\tActionHandler handler = oneHandler->second;\n\t\t(state->*handler)(action);\n\t}\n}\n\n/**\n * Called every time there's a mouse release over the surface.\n * Allows the surface to have custom functionality for this action,\n * and can be called externally to simulate the action.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid InteractiveSurface::mouseRelease(Action *action, State *state)\n{\n\tauto allHandler = _release.find(0);\n\tauto oneHandler = _release.find(action->getDetails()->button.button);\n\tif (allHandler != _release.end())\n\t{\n\t\tActionHandler handler = allHandler->second;\n\t\t(state->*handler)(action);\n\t}\n\tif (oneHandler != _release.end())\n\t{\n\t\tActionHandler handler = oneHandler->second;\n\t\t(state->*handler)(action);\n\t}\n}\n\n/**\n * Called every time there's a mouse click on the surface.\n * Allows the surface to have custom functionality for this action,\n * and can be called externally to simulate the action.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid InteractiveSurface::mouseClick(Action *action, State *state)\n{\n\tauto allHandler = _click.find(0);\n\tauto oneHandler = _click.find(action->getDetails()->button.button);\n\tif (allHandler != _click.end())\n\t{\n\t\tActionHandler handler = allHandler->second;\n\t\t(state->*handler)(action);\n\t}\n\tif (oneHandler != _click.end())\n\t{\n\t\tActionHandler handler = oneHandler->second;\n\t\t(state->*handler)(action);\n\t}\n}\n\n/**\n * Called every time the mouse moves into the surface.\n * Allows the surface to have custom functionality for this action,\n * and can be called externally to simulate the action.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid InteractiveSurface::mouseIn(Action *action, State *state)\n{\n\tif (_in != 0)\n\t{\n\t\t(state->*_in)(action);\n\t}\n}\n\n/**\n * Called every time the mouse moves over the surface.\n * Allows the surface to have custom functionality for this action,\n * and can be called externally to simulate the action.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid InteractiveSurface::mouseOver(Action *action, State *state)\n{\n\tif (_over != 0)\n\t{\n\t\t(state->*_over)(action);\n\t}\n}\n\n/**\n * Called every time the mouse moves out of the surface.\n * Allows the surface to have custom functionality for this action,\n * and can be called externally to simulate the action.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid InteractiveSurface::mouseOut(Action *action, State *state)\n{\n\tif (_out != 0)\n\t{\n\t\t(state->*_out)(action);\n\t}\n}\n\n/**\n * Called every time there's a keyboard press when the surface is focused.\n * Allows the surface to have custom functionality for this action,\n * and can be called externally to simulate the action.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid InteractiveSurface::keyboardPress(Action *action, State *state)\n{\n\tauto allHandler = _keyPress.find(SDLK_ANY);\n\tauto oneHandler = _keyPress.find(action->getDetails()->key.keysym.sym);\n\tif (allHandler != _keyPress.end())\n\t{\n\t\tActionHandler handler = allHandler->second;\n\t\t(state->*handler)(action);\n\t}\n\t// Check if Ctrl, Alt and Shift aren't pressed\n\tbool mod = ((action->getDetails()->key.keysym.mod & (KMOD_CTRL|KMOD_ALT|KMOD_SHIFT)) != 0);\n\tif (oneHandler != _keyPress.end() && !mod)\n\t{\n\t\tActionHandler handler = oneHandler->second;\n\t\t(state->*handler)(action);\n\t}\n}\n\n/**\n * Called every time there's a keyboard release over the surface.\n * Allows the surface to have custom functionality for this action,\n * and can be called externally to simulate the action.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid InteractiveSurface::keyboardRelease(Action *action, State *state)\n{\n\tauto allHandler = _keyRelease.find(SDLK_ANY);\n\tauto oneHandler = _keyRelease.find(action->getDetails()->key.keysym.sym);\n\tif (allHandler != _keyRelease.end())\n\t{\n\t\tActionHandler handler = allHandler->second;\n\t\t(state->*handler)(action);\n\t}\n\t// Check if Ctrl, Alt and Shift aren't pressed\n\tbool mod = ((action->getDetails()->key.keysym.mod & (KMOD_CTRL|KMOD_ALT|KMOD_SHIFT)) != 0);\n\tif (oneHandler != _keyRelease.end() && !mod)\n\t{\n\t\tActionHandler handler = oneHandler->second;\n\t\t(state->*handler)(action);\n\t}\n}\n\n/**\n * Sets a function to be called every time the surface is mouse clicked.\n * @param handler Action handler.\n * @param button Mouse button to check for. Set to 0 for any button.\n */\nvoid InteractiveSurface::onMouseClick(ActionHandler handler, Uint8 button)\n{\n\tif (handler != 0)\n\t{\n\t\t_click[button] = handler;\n\t}\n\telse\n\t{\n\t\t_click.erase(button);\n\t}\n}\n\n/**\n * Sets a function to be called every time the surface is mouse pressed.\n * @param handler Action handler.\n * @param button Mouse button to check for. Set to 0 for any button.\n */\nvoid InteractiveSurface::onMousePress(ActionHandler handler, Uint8 button)\n{\n\tif (handler != 0)\n\t{\n\t\t_press[button] = handler;\n\t}\n\telse\n\t{\n\t\t_press.erase(button);\n\t}\n}\n\n/**\n * Sets a function to be called every time the surface is mouse released.\n * @param handler Action handler.\n * @param button Mouse button to check for. Set to 0 for any button.\n */\nvoid InteractiveSurface::onMouseRelease(ActionHandler handler, Uint8 button)\n{\n\tif (handler != 0)\n\t{\n\t\t_release[button] = handler;\n\t}\n\telse\n\t{\n\t\t_release.erase(button);\n\t}\n}\n\n/**\n * Sets a function to be called every time the mouse moves into the surface.\n * @param handler Action handler.\n */\nvoid InteractiveSurface::onMouseIn(ActionHandler handler)\n{\n\t_in = handler;\n}\n\n/**\n * Sets a function to be called every time the mouse moves over the surface.\n * @param handler Action handler.\n */\nvoid InteractiveSurface::onMouseOver(ActionHandler handler)\n{\n\t_over = handler;\n}\n\n/**\n * Sets a function to be called every time the mouse moves out of the surface.\n * @param handler Action handler.\n */\nvoid InteractiveSurface::onMouseOut(ActionHandler handler)\n{\n\t_out = handler;\n}\n\n/**\n * Sets a function to be called every time a key is pressed when the surface is focused.\n * @param handler Action handler.\n * @param key Keyboard button to check for (note: ignores key modifiers). Set to SDLK_ANY for any key.\n */\nvoid InteractiveSurface::onKeyboardPress(ActionHandler handler, SDLKey key)\n{\n\tif (key == SDLK_UNKNOWN)\n\t{\n\t\t// Ignore unknown keys\n\t\treturn;\n\t}\n\tif (handler != 0)\n\t{\n\t\t_keyPress[key] = handler;\n\t}\n\telse\n\t{\n\t\t_keyPress.erase(key);\n\t}\n}\n\n/**\n * Sets a function to be called every time a key is released when the surface is focused.\n * @param handler Action handler.\n * @param key Keyboard button to check for (note: ignores key modifiers). Set to SDLK_ANY for any key.\n */\nvoid InteractiveSurface::onKeyboardRelease(ActionHandler handler, SDLKey key)\n{\n\tif (key == SDLK_UNKNOWN)\n\t{\n\t\t// Ignore unknown keys\n\t\treturn;\n\t}\n\tif (handler != 0)\n\t{\n\t\t_keyRelease[key] = handler;\n\t}\n\telse\n\t{\n\t\t_keyRelease.erase(key);\n\t}\n}\n\n/**\n * Sets a flag for this button to say \"i'm a member of a textList\" to true.\n */\nvoid InteractiveSurface::setListButton()\n{\n\t_listButton = true;\n}\n\n/**\n * Returns the help description of this surface,\n * for example for showing in tooltips.\n * @return String ID.\n */\nstd::string InteractiveSurface::getTooltip() const\n{\n\treturn _tooltip;\n}\n\n/**\n * Changes the help description of this surface,\n * for example for showing in tooltips.\n * @param tooltip String ID.\n */\nvoid InteractiveSurface::setTooltip(const std::string &tooltip)\n{\n\t_tooltip = tooltip;\n}\n\n/**\n * TFTD mode: much like click inversion, but does a colour swap rather than a palette shift.\n * @param mode set TFTD mode to this.\n */\nvoid InteractiveSurface::setTFTDMode(bool mode)\n{\n\t_tftdMode = mode;\n}\n\n/**\n * checks TFTD mode.\n * @return TFTD mode.\n */\nbool InteractiveSurface::isTFTDMode() const\n{\n\treturn _tftdMode;\n}\n\n}\n"
  },
  {
    "path": "src/Engine/InteractiveSurface.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <SDL.h>\n#include <map>\n#include \"Surface.h\"\n#include \"State.h\"\n\nnamespace OpenXcom\n{\n\ntypedef void (State::* ActionHandler)(Action*);\n\n/**\n * Surface that the user can interact with.\n * Specialized version of the standard Surface that\n * processes all the various SDL events and turns\n * them into useful interactions with the Surface,\n * so specialized subclasses don't need to worry about it.\n */\nclass InteractiveSurface : public Surface\n{\nprivate:\n\tstatic const int NUM_BUTTONS = 7;\n\tstatic const SDLKey SDLK_ANY;\n\tUint8 _buttonsPressed;\n\tstd::string _tooltip;\n\nprotected:\n\tstd::map<Uint8, ActionHandler> _click, _press, _release;\n\tActionHandler _in, _over, _out;\n\tstd::map<SDLKey, ActionHandler> _keyPress, _keyRelease;\n\tbool _isHovered, _isFocused, _listButton, _tftdMode;\n\n\t/// Is this mouse button pressed?\n\tbool isButtonPressed(Uint8 button = 0) const;\n\t/// Is this mouse button event handled?\n\tvirtual bool isButtonHandled(Uint8 button = 0);\n\t/// Set a mouse button's internal state.\n\tvoid setButtonPressed(Uint8 button, bool pressed);\npublic:\n\t/// Creates a new interactive surface with the specified size and position.\n\tInteractiveSurface(int width, int height, int x = 0, int y = 0);\n\t/// Cleans up the interactive surface.\n\tvirtual ~InteractiveSurface();\n\t/// Sets the surface's visibility.\n\tvoid setVisible(bool visible) override;\n\t/// Processes any pending events.\n\tvirtual void handle(Action *action, State *state);\n\t/// Sets the focus of this surface.\n\tvirtual void setFocus(bool focus, bool modal = false);\n\t/// Gets the focus of this surface.\n\tbool isFocused() const;\n\t/// Unpresses the surface.\n\tvirtual void unpress(State *state);\n\t/// Hooks an action handler to a mouse click on the surface.\n\tvoid onMouseClick(ActionHandler handler, Uint8 button = SDL_BUTTON_LEFT);\n\t/// Hooks an action handler to a mouse press over the surface.\n\tvoid onMousePress(ActionHandler handler, Uint8 button = 0);\n\t/// Hooks an action handler to a mouse release over the surface.\n\tvoid onMouseRelease(ActionHandler handler, Uint8 button = 0);\n\t/// Hooks an action handler to moving the mouse into the surface.\n\tvoid onMouseIn(ActionHandler handler);\n\t/// Hooks an action handler to moving the mouse over the surface.\n\tvoid onMouseOver(ActionHandler handler);\n\t/// Hooks an action handler to moving the mouse out of the surface.\n\tvoid onMouseOut(ActionHandler handler);\n\t/// Hooks an action handler to pressing a key when the surface is focused.\n\tvoid onKeyboardPress(ActionHandler handler, SDLKey key = SDLK_ANY);\n\t/// Hooks an action handler to releasing a key when the surface is focused.\n\tvoid onKeyboardRelease(ActionHandler handler, SDLKey key = SDLK_ANY);\n\t/// Processes a mouse button press event.\n\tvirtual void mousePress(Action *action, State *state);\n\t/// Processes a mouse button release event.\n\tvirtual void mouseRelease(Action *action, State *state);\n\t/// Processes a mouse click event.\n\tvirtual void mouseClick(Action *action, State *state);\n\t/// Processes a mouse hover in event.\n\tvirtual void mouseIn(Action *action, State *state);\n\t/// Processes a mouse hover event.\n\tvirtual void mouseOver(Action *action, State *state);\n\t/// Processes a mouse hover out event.\n\tvirtual void mouseOut(Action *action, State *state);\n\t/// Processes a keyboard key press event.\n\tvirtual void keyboardPress(Action *action, State *state);\n\t/// Processes a keyboard key release event.\n\tvirtual void keyboardRelease(Action *action, State *state);\n\t/// Check this surface to see if it's a textlist button.\n\tvoid setListButton();\n\t/// Gets the tooltip of the surface.\n\tstd::string getTooltip() const;\n\t/// Sets the tooltip of the surface.\n\tvoid setTooltip(const std::string &tooltip);\n\t/// Sets this button to use a colour lookup table instead of inversion for its alternate form.\n\tvoid setTFTDMode(bool mode);\n\t/// checks if this is a TFTD mode surface.\n\tbool isTFTDMode() const;\n};\n\n}\n"
  },
  {
    "path": "src/Engine/Language.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"Language.h\"\n#include <algorithm>\n#include <cassert>\n#include <set>\n#include <climits>\n#include <algorithm>\n#include \"CrossPlatform.h\"\n#include \"Logger.h\"\n#include \"Options.h\"\n#include \"LanguagePlurality.h\"\n#include \"Unicode.h\"\n#include \"../Mod/ExtraStrings.h\"\n#include \"../Savegame/Soldier.h\"\n#include \"FileMap.h\"\n\nnamespace OpenXcom\n{\n\nstd::map<std::string, std::string> Language::_names;\nstd::vector<std::string> Language::_rtl, Language::_cjk;\n\n/**\n * Initializes an empty language file.\n */\nLanguage::Language() : _handler(0), _direction(DIRECTION_LTR), _wrap(WRAP_WORDS)\n{\n\t// maps don't have initializers :(\n\tif (_names.empty())\n\t{\n\t\t_names[\"en-US\"] = \"English (US)\";\n\t\t_names[\"en-GB\"] = \"English (UK)\";\n\t\t// _names[\"ar\"] = \"العربية\"; needs fonts\n\t\t_names[\"bg\"] = \"Български\";\n\t\t_names[\"ca-ES\"] = \"Català\";\n\t\t_names[\"cs\"] = \"Česky\";\n\t\t_names[\"cy\"] = \"Cymraeg\";\n\t\t_names[\"da\"] = \"Dansk\";\n\t\t_names[\"de\"] = \"Deutsch\";\n\t\t_names[\"el\"] = \"Ελληνικά\";\n\t\t_names[\"et\"] = \"Eesti\";\n\t\t_names[\"es-ES\"] = \"Español (ES)\";\n\t\t_names[\"es-419\"] = \"Español (AL)\";\n\t\t_names[\"fr\"] = \"Français (FR)\";\n\t\t_names[\"fr-CA\"] = \"Français (CA)\";\n\t\t_names[\"fi\"] = \"Suomi\";\n\t\t_names[\"ga\"] = \"Gaeilge\";\n\t\t_names[\"hr\"] = \"Hrvatski\";\n\t\t_names[\"hu\"] = \"Magyar\";\n\t\t_names[\"it\"] = \"Italiano\";\n\t\t_names[\"is\"] = \"Íslenska\";\n\t\t_names[\"ja\"] = \"日本語\";\n\t\t_names[\"ko\"] = \"한국어\";\n\t\t_names[\"lb\"] = \"Lëtzebuergesch\";\n\t\t_names[\"lv\"] = \"Latviešu\";\n\t\t_names[\"nl\"] = \"Nederlands\";\n\t\t_names[\"no\"] = \"Norsk\";\n\t\t_names[\"pl\"] = \"Polski\";\n\t\t_names[\"pt-BR\"] = \"Português (BR)\";\n\t\t_names[\"pt-PT\"] = \"Português (PT)\";\n\t\t_names[\"ro\"] = \"Română\";\n\t\t_names[\"ru\"] = \"Русский\";\n\t\t_names[\"sk\"] = \"Slovenčina\";\n\t\t_names[\"sl\"] = \"Slovenščina\";\n\t\t_names[\"sv\"] = \"Svenska\";\n\t\t// _names[\"th\"] = \"ไทย\"; needs fonts\n\t\t_names[\"tr\"] = \"Türkçe\";\n\t\t_names[\"uk\"] = \"Українська\";\n\t\t_names[\"vi\"] = \"Tiếng Việt\";\n\t\t_names[\"zh-CN\"] = \"中文\";\n\t\t_names[\"zh-TW\"] = \"文言\";\n\t}\n\tif (_rtl.empty())\n\t{\n\t\t//_rtl.push_back(\"he\"); needs translation\n\t}\n\tif (_cjk.empty())\n\t{\n\t\t_cjk.push_back(\"ja\");\n\t\t_cjk.push_back(\"ko\");\n\t\t_cjk.push_back(\"zh-CN\");\n\t\t_cjk.push_back(\"zh-TW\");\n\t}\n\n\tstd::string id = Options::language;\n\t_handler = LanguagePlurality::create(id);\n\tif (std::find(_rtl.begin(), _rtl.end(), id) == _rtl.end())\n\t{\n\t\t_direction = DIRECTION_LTR;\n\t}\n\telse\n\t{\n\t\t_direction = DIRECTION_RTL;\n\t}\n\tif (Options::wordwrap == WRAP_AUTO)\n\t{\n\t\tif (std::find(_cjk.begin(), _cjk.end(), id) == _cjk.end())\n\t\t{\n\t\t\t_wrap = WRAP_WORDS;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_wrap = WRAP_LETTERS;\n\t\t}\n\t}\n\telse\n\t{\n\t\t_wrap = Options::wordwrap;\n\t}\n}\n\n/**\n *\n */\nLanguage::~Language()\n{\n\tdelete _handler;\n}\n\n/**\n * Extracts language id from a filename\n * @param  fileName some filename\n * @return 'pt' or 'en-US' or the like\n */\nstatic std::string fileNameToId(const std::string& fileName) {\n\tauto noExtName = CrossPlatform::noExt(CrossPlatform::baseFilename(fileName));\n\tauto found = noExtName.find_first_of('-');\n\tif (found != noExtName.npos) {\n\t\t// uppercase it after dash\n\t\tfor (found += 1; found < noExtName.size(); ++found) {\n\t\t\tnoExtName[found] = toupper(noExtName[found]);\n\t\t}\n\t}\n\treturn noExtName;\n}\n\n/**\n * Gets all the languages found in the\n * Data folder and returns their properties.\n * @param ids List of language ids.\n * @param names List of language human-readable names.\n */\nvoid Language::getList(std::vector<std::string> &ids, std::vector<std::string> &names)\n{\n\tauto nset = FileMap::filterFiles(FileMap::getVFolderContents(\"Language\", 0), \"yml\");\n\tids.clear();\n\tfor (const auto& filename : nset) {\n\t\tids.push_back(fileNameToId(filename));\n\t}\n\tstd::sort(ids.begin(), ids.end());\n\tnames.clear();\n\n\tfor (const auto& id: ids)\n\t{\n\t\tif (_names.find(id) != _names.end()) {\n\t\t\tnames.push_back(_names[id]);\n\t\t} else {\n\t\t\tnames.push_back(id);\n\t\t}\n\t}\n}\n\n/**\n * Loads a language file in Ruby-on-Rails YAML format.\n * Not that this has anything to do with Ruby, but since it's a\n * widely-supported format and we already have YAML, it was convenient.\n * @param filename Filename of the YAML file.\n */\nvoid Language::loadFile(const FileMap::FileRecord *frec)\n{\n\tconst YAML::YamlRootNodeReader& reader = frec->getYAML();\n\tYAML::YamlNodeReader langMap = reader[0].isMap() ? reader[0] : reader.toBase();\n\n\tfor (const auto& langReader : langMap.children())\n\t{\n\t\t// Regular strings\n\t\tif (langReader.hasVal())\n\t\t{\n\t\t\tstd::string value = langReader.readVal<std::string>();\n\t\t\tif (!value.empty())\n\t\t\t{\n\t\t\t\tstd::string key = langReader.readKey<std::string>();\n\t\t\t\t_strings[key] = loadString(value);\n\t\t\t}\n\t\t}\n\t\t// Strings with plurality\n\t\telse if (langReader.isMap())\n\t\t{\n\t\t\tfor (const auto& pluralityReader : langReader.children())\n\t\t\t{\n\t\t\t\tstd::string value = pluralityReader.readVal<std::string>(\"\");\n\t\t\t\tif (!value.empty())\n\t\t\t\t{\n\t\t\t\t\tstd::string key = langReader.readKey<std::string>() + \"_\" + pluralityReader.readKey<std::string>();\n\t\t\t\t\t_strings[key] = loadString(value);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Loads a language file from a mod's ExtraStrings.\n * @param extraStrings List of ExtraStrings.\n * @param id Language ID.\n */\nvoid Language::loadRule(const std::map<std::string, ExtraStrings*> &extraStrings, const std::string &id)\n{\n\tauto it = extraStrings.find(id);\n\tif (it != extraStrings.end())\n\t{\n\t\tfor (const auto& pair : *it->second->getStrings())\n\t\t{\n\t\t\t_strings[pair.first] = loadString(pair.second);\n\t\t}\n\t}\n}\n\n/**\n * Replaces all special string markers with the appropriate characters.\n * @param string Original string.\n * @return New converted string.\n */\nstd::string Language::loadString(const std::string &string) const\n{\n\tstd::string s = string;\n\tUnicode::replace(s, \"{NEWLINE}\", \"\\n\");\n\tUnicode::replace(s, \"{SMALLLINE}\", \"\\x02\"); // Unicode::TOK_NL_SMALL\n\tUnicode::replace(s, \"{ALT}\", \"\\x01\"); // Unicode::TOK_COLOR_FLIP\n\treturn s;\n}\n\n/**\n * Returns the localized text with the specified ID.\n * If it's not found, just returns the ID.\n * @param id ID of the string.\n * @return String with the requested ID.\n */\nLocalizedText Language::getString(const std::string &id) const\n{\n\tif (id.empty())\n\t{\n\t\treturn id;\n\t}\n\tauto s = _strings.find(id);\n\t// Check if translation strings recently learned pluralization.\n\tif (s == _strings.end())\n\t{\n\t\treturn getString(id, UINT_MAX);\n\t}\n\telse\n\t{\n\t\treturn s->second;\n\t}\n}\n\n/**\n * Returns the localized text with the specified ID, in the proper form for @a n.\n * The substitution of @a n has already happened in the returned LocalizedText.\n * If it's not found, just returns the ID.\n * @param id ID of the string.\n * @param n Number to use to decide the proper form.\n * @return String with the requested ID.\n */\nLocalizedText Language::getString(const std::string &id, unsigned n) const\n{\n\tassert(!id.empty());\n\tstatic std::set<std::string> notFoundIds;\n\tauto s = _strings.end();\n\t// Try specialized form.\n\tif (n == 0)\n\t{\n\t\ts = _strings.find(id + \"_zero\");\n\t}\n\t// Try proper form by language\n\tif (s == _strings.end())\n\t{\n\t\ts = _strings.find(id + _handler->getSuffix(n));\n\t}\n\t// Try default form\n\tif (s == _strings.end())\n\t{\n\t\ts = _strings.find(id + \"_other\");\n\t}\n\t// Give up\n\tif (s == _strings.end())\n\t{\n\t\tif (notFoundIds.end() == notFoundIds.find(id))\n\t\t{\n\t\t\tnotFoundIds.insert(id);\n\t\t\tLog(LOG_WARNING) << id << \" not found in \" << Options::language;\n\t\t}\n\t\treturn id;\n\t}\n\tif (n == UINT_MAX) // Special case\n\t{\n\t\tif (notFoundIds.end() == notFoundIds.find(id))\n\t\t{\n\t\t\tnotFoundIds.insert(id);\n\t\t\tLog(LOG_WARNING) << id << \" has plural format in ``\" << Options::language << \"``. Code assumes singular format.\";\n//\t\tHint: Change ``getstring(ID).arg(value)`` to ``getString(ID, value)`` in appropriate files.\n\t\t}\n\t\treturn s->second;\n\t}\n\telse\n\t{\n\t\tstd::ostringstream ss;\n\t\tss << n;\n\t\tstd::string marker(\"{N}\"), val(ss.str()), txt(s->second);\n\t\tUnicode::replace(txt, marker, val);\n\t\treturn txt;\n\t}\n\n}\n\n/**\n * Returns the localized text with the specified ID, in the proper form for the gender.\n * If it's not found, just returns the ID.\n * @param id ID of the string.\n * @param gender Current soldier gender.\n * @return String with the requested ID.\n */\nLocalizedText Language::getString(const std::string &id, SoldierGender gender) const\n{\n\tstd::string genderId;\n\tif (gender == GENDER_MALE)\n\t{\n\t\tgenderId = id + \"_MALE\";\n\t}\n\telse\n\t{\n\t\tgenderId = id + \"_FEMALE\";\n\t}\n\treturn getString(genderId);\n}\n\n/**\n * Outputs all the language IDs and strings\n * to an HTML table.\n * @param filename HTML file.\n */\nvoid Language::toHtml(const std::string &filename) const\n{\n\tstd::stringstream htmlFile;\n\thtmlFile << \"<table border=\\\"1\\\" width=\\\"100%\\\">\" << std::endl;\n\thtmlFile << \"<tr><th>ID String</th><th>English String</th></tr>\" << std::endl;\n\tfor (auto& pair : _strings)\n\t{\n\t\thtmlFile << \"<tr><td>\" << pair.first << \"</td><td>\";\n\t\tstd::string s = pair.second;\n\t\tfor (std::string::const_iterator j = s.begin(); j != s.end(); ++j)\n\t\t{\n\t\t\tif (*j == Unicode::TOK_NL_SMALL || *j == '\\n')\n\t\t\t{\n\t\t\t\thtmlFile << \"<br />\";\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\thtmlFile << *j;\n\t\t\t}\n\t\t}\n\t\thtmlFile << \"</td></tr>\" << std::endl;\n\t}\n\thtmlFile << \"</table>\" << std::endl;\n\tCrossPlatform::writeFile(filename, htmlFile.str());\n}\n\n/**\n * Returns the direction to use for rendering\n * text in this language.\n * @return Text direction.\n */\nTextDirection Language::getTextDirection() const\n{\n\treturn _direction;\n}\n\n/**\n * Returns the wrapping rules to use for rendering\n * text in this language.\n * @return Text wrapping.\n */\nTextWrapping Language::getTextWrapping() const\n{\n\treturn _wrap;\n}\n\n}\n\n/** @page LanguageFiles Format of the language files.\n\nLanguage files are formatted as YAML (.yml) containing UTF-8 (no BOM) text.\nThe first line in a language file is the language's identifier.\nThe rest of the file are key-value pairs. The key of each pair\ncontains the ID string (dictionary key), and the value contains the localized\ntext for the given key in quotes.\n\nThe localized text may contain the following special markers:\n<table>\n<tr>\n <td><tt>{</tt><i>0, 1, 2, ...</i> <tt>}</tt></td>\n <td>These markers will be replaced by programmer-supplied values before the\n message is displayed.</td></tr>\n<tr>\n <td><tt>{ALT}</tt></td>\n <td>The rest of the text will be in an alternate color. Using this again will\n switch back to the primary color.</td></tr>\n<tr>\n <td><tt>{NEWLINE}</tt></td>\n <td>It will be replaced with a line break in the game.</td></tr>\n<tr>\n <td><tt>{SMALLLINE}</tt></td>\n <td>The rest of the text will be in a small font.</td></tr>\n</table>\n\nThere is an additional marker sequence, that should only appear in texts that\ndepend on a number. This marker <tt>{N}</tt> will be replaced by the actual\nnumber used. The keys for texts that depend on numbers also have special\nsuffixes, that depend on the language. For all languages, a suffix of\n<tt>_zero</tt> is tried if the number is zero, before trying the actual key\naccording to the language rules. The rest of the suffixes depend on the language,\nas described <a href=\"http://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html\">here</a>.\n\nSo, you would write (for English):\n<pre>\nSTR_ENEMIES:\n  zero:  \"There are no enemies left.\"\n  one:   \"There is a single enemy left.\"\n  other: \"There are {N} enemies left.\"\n</pre>\n\n */\n"
  },
  {
    "path": "src/Engine/Language.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *e\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <map>\n#include <vector>\n#include <string>\n#include \"LocalizedText.h\"\n#include \"FileMap.h\"\n\nnamespace OpenXcom\n{\nenum TextDirection { DIRECTION_LTR, DIRECTION_RTL };\nenum TextWrapping { WRAP_AUTO, WRAP_WORDS, WRAP_LETTERS };\n\nclass TextList;\nclass ExtraStrings;\nclass LanguagePlurality;\n\nenum SoldierGender : char;\n\n/**\n * Contains strings used throughout the game for localization.\n * Languages are just a set of strings identified by an ID string.\n */\nclass Language\n{\nprivate:\n\tstd::map<std::string, LocalizedText> _strings;\n\tLanguagePlurality *_handler;\n\tTextDirection _direction;\n\tTextWrapping _wrap;\n\n\tstatic std::map<std::string, std::string> _names;\n\tstatic std::vector<std::string> _rtl, _cjk;\n\n\t/// Parses a text string loaded from an external file.\n\tstd::string loadString(const std::string &s) const;\npublic:\n\t/// Creates a blank language.\n\tLanguage();\n\t/// Cleans up the language.\n\t~Language();\n\t/// Gets list of available languages.\n\tstatic void getList(std::vector<std::string> &ids, std::vector<std::string> &names);\n\t/// Checks if a language is in the supported name list.\n\tstatic bool isSupported(const std::string& lang) { return _names.find(lang) != _names.end(); }\n\t/// Loads the language from an external file.\n\tvoid loadFile(const FileMap::FileRecord *frec);\n\t/// Loads the language from a ruleset file.\n\tvoid loadRule(const std::map<std::string, ExtraStrings*> &extraStrings, const std::string &id);\n\t/// Outputs the language to a HTML file.\n\tvoid toHtml(const std::string &filename) const;\n\t/// Get a localized text.\n\tLocalizedText getString(const std::string &id) const;\n\t/// Get a quantity-depended localized text.\n\tLocalizedText getString(const std::string &id, unsigned n) const;\n\t/// Get a gender-depended localized text.\n\tLocalizedText getString(const std::string &id, SoldierGender gender) const;\n\t/// Gets the direction of text in this language.\n\tTextDirection getTextDirection() const;\n\t/// Gets the wrapping of text in this language.\n\tTextWrapping getTextWrapping() const;\n};\n\n}\n"
  },
  {
    "path": "src/Engine/LanguagePlurality.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"LanguagePlurality.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Default plurality rules.\n * Provide rules for languages where 1 is singular and everything else is plural.\n * @note one = 1; other = ...\n */\nclass OneSingular: public LanguagePlurality\n{\npublic:\n\tvirtual const char *getSuffix(unsigned n) const override;\n\tstatic LanguagePlurality *create() { return new OneSingular; }\n};\n\nconst char *OneSingular::getSuffix(unsigned n) const\n{\n\tif (n == 1)\n\t{\n\t\treturn \"_one\";\n\t}\n\treturn \"_other\";\n}\n\n/**\n * Plurality rules where 0 is also singular.\n * Provide rules for languages where 0 and 1 are singular and everything else is plural.\n * @note one = 0-1; other = ...\n */\nclass ZeroOneSingular : public LanguagePlurality\n{\npublic:\n\tvirtual const char *getSuffix(unsigned n) const override;\n\tstatic LanguagePlurality *create() { return new ZeroOneSingular; }\n};\n\nconst char *ZeroOneSingular::getSuffix(unsigned n) const\n{\n\tif (n == 0 || n == 1)\n\t{\n\t\treturn \"_one\";\n\t}\n\treturn \"_other\";\n}\n\n/**\n * Plurality rules where there is no singular.\n * Provide rules for languages where everything is plural.\n * @note other = ...\n */\nclass NoSingular : public LanguagePlurality\n{\npublic:\n\tvirtual const char *getSuffix(unsigned n) const override;\n\tstatic LanguagePlurality *create() { return new NoSingular; }\n};\n\nconst char *NoSingular::getSuffix(unsigned) const\n{\n\treturn \"_other\";\n}\n\n/**\n * Plurality rules for Cyrillic languages (Russian, Ukrainian, etc.)\n * @note one = 1, 21, 31...; few = 2-4, 22-24, 32-34...; many = 0, 5-20, 25-30, 35-40...; other = ...\n */\nclass CyrillicPlurality : public LanguagePlurality\n{\npublic:\n\tvirtual const char *getSuffix(unsigned n) const override;\n\tstatic LanguagePlurality *create() { return new CyrillicPlurality; }\n};\n\nconst char *CyrillicPlurality::getSuffix(unsigned n) const\n{\n\tif (n % 10 == 1 && n % 100 != 11)\n\t{\n\t\treturn \"_one\";\n\t}\n\telse if ((n % 10 >= 2 && n % 10 <= 4) &&\n\t\t\t!(n % 100 >= 12 && n % 100 <= 14))\n\t{\n\t\treturn \"_few\";\n\t}\n\telse if (n % 10 == 0 ||\n\t\t\t(n % 10 >= 5 && n % 10 <= 9) ||\n\t\t\t(n % 100 >= 11 && n % 100 <= 14))\n\t{\n\t\treturn \"_many\";\n\t}\n\treturn \"_other\";\n}\n\n/**\n * Plurality rules for Czech and Slovak languages.\n * @note one = 1; few = 2-4; other = ...\n */\nclass CzechPlurality : public LanguagePlurality\n{\npublic:\n\tvirtual const char *getSuffix(unsigned n) const override;\n\tstatic LanguagePlurality *create() { return new CzechPlurality; }\n};\n\nconst char *CzechPlurality::getSuffix(unsigned n) const\n{\n\tif (n == 1)\n\t{\n\t\treturn \"_one\";\n\t}\n\telse if (n >= 2 && n <= 4)\n\t{\n\t\treturn \"_few\";\n\t}\n\treturn \"_other\";\n}\n\n/**\n * Plurality rules for the Polish language.\n * @note one = 1; few = 2-4, 22-24, 32-34...; many = 0, 5-21, 25-31, 35-41, ...; other = ...\n */\nclass PolishPlurality : public LanguagePlurality\n{\npublic:\n\tvirtual const char *getSuffix(unsigned n) const override;\n\tstatic LanguagePlurality *create() { return new PolishPlurality; }\n};\n\nconst char *PolishPlurality::getSuffix(unsigned n) const\n{\n\tif (n == 1)\n\t{\n\t\treturn \"_one\";\n\t}\n\telse if ((n % 10 >= 2 && n % 10 <= 4) &&\n\t\t\t!(n % 100 >= 12 && n % 100 <= 14))\n\t{\n\t\treturn \"_few\";\n\t}\n\telse if ((n % 10 <= 1) ||\n\t\t\t(n % 10 >= 5 && n % 10 <= 9) ||\n\t\t\t(n % 100 >= 12 && n % 100 <= 14))\n\t{\n\t\treturn \"_many\";\n\t}\n\treturn \"_other\";\n}\n\n/**\n * Plurality rules for Romanian and Moldavian languages.\n * @note one = 1; few = 0, 2-19, 101-119...; other = ...\n */\nclass RomanianPlurality : public LanguagePlurality\n{\npublic:\n\tvirtual const char *getSuffix(unsigned n) const override;\n\tstatic LanguagePlurality *create() { return new RomanianPlurality; }\n};\n\nconst char *RomanianPlurality::getSuffix(unsigned n) const\n{\n\tif (n == 1)\n\t{\n\t\treturn \"_one\";\n\t}\n\telse if (n == 0 ||\n\t\t\t(n % 100 >= 1 && n % 100 <= 19))\n\t{\n\t\treturn \"_few\";\n\t}\n\treturn \"_other\";\n}\n\n/**\n * Plurality rules for Croatian and Serbian languages.\n * @note one = 1, 21, 31...; few = 2-4, 22-24, 32-34, ...; other = ...\n */\nclass CroatianPlurality : public LanguagePlurality\n{\npublic:\n\tvirtual const char *getSuffix(unsigned n) const override;\n\tstatic LanguagePlurality *create() { return new CroatianPlurality; }\n};\n\nconst char *CroatianPlurality::getSuffix(unsigned n) const\n{\n\tif (n % 10 == 1 && n % 100 != 11)\n\t{\n\t\treturn \"_one\";\n\t}\n\telse if ((n % 10 >= 2 && n % 10 <= 4) &&\n\t\t\t!(n % 100 >= 12 && n % 100 <= 14))\n\t{\n\t\treturn \"_few\";\n\t}\n\treturn \"_other\";\n}\n\n/** A mapping of language to plurality rules.\n * It is populated the first time plurality rules are requested.\n * @see LanguagePlurality::create\n */\nstd::map<std::string, LanguagePlurality::PFCreate> LanguagePlurality::s_factoryFunctions;\n\n/**\n * Search and create a handler for the plurality rules of @a language.\n * If the language was not found, a default with the same rules as English is returned.\n * @param language The target language.\n * @return A newly created LanguagePlurality instance for the given language.\n * @internal The first time this is called, we populate the language => rules mapping.\n */\nLanguagePlurality *LanguagePlurality::create(const std::string &language)\n{\n\t// Populate factory the first time we are called.\n\tif (s_factoryFunctions.empty())\n\t{\n\t\ts_factoryFunctions.insert(std::make_pair(\"fr\", &ZeroOneSingular::create));\n\t\ts_factoryFunctions.insert(std::make_pair(\"fr-CA\", &ZeroOneSingular::create));\n\t\ts_factoryFunctions.insert(std::make_pair(\"hu\", &NoSingular::create));\n\t\ts_factoryFunctions.insert(std::make_pair(\"tr\", &NoSingular::create));\n\t\ts_factoryFunctions.insert(std::make_pair(\"cs\", &CzechPlurality::create));\n\t\ts_factoryFunctions.insert(std::make_pair(\"pl\", &PolishPlurality::create));\n\t\ts_factoryFunctions.insert(std::make_pair(\"ro\", &RomanianPlurality::create));\n\t\ts_factoryFunctions.insert(std::make_pair(\"ru\", &CyrillicPlurality::create));\n\t\ts_factoryFunctions.insert(std::make_pair(\"sk\", &CzechPlurality::create));\n\t\ts_factoryFunctions.insert(std::make_pair(\"uk\", &CyrillicPlurality::create));\n\t\ts_factoryFunctions.insert(std::make_pair(\"ja\", &NoSingular::create));\n\t\ts_factoryFunctions.insert(std::make_pair(\"ko\", &NoSingular::create));\n\t\ts_factoryFunctions.insert(std::make_pair(\"zh-CN\", &NoSingular::create));\n\t\ts_factoryFunctions.insert(std::make_pair(\"zh-TW\", &NoSingular::create));\n\t\ts_factoryFunctions.insert(std::make_pair(\"hr\", &CroatianPlurality::create));\n\t}\n\tPFCreate creator = &OneSingular::create;\n\tauto found = s_factoryFunctions.find(language);\n\tif (found != s_factoryFunctions.end())\n\t{\n\t\tcreator = found->second;\n\t}\n\treturn (*creator)();\n}\n\n}\n"
  },
  {
    "path": "src/Engine/LanguagePlurality.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *e\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include <map>\n\nnamespace OpenXcom\n{\n\n/**\n * This class is the interface used to find plural forms for the different languages.\n * Derived classes implement getSuffix() according to the specific language's rules.\n */\nclass LanguagePlurality\n{\npublic:\n\t/// Allow proper destruction through base pointer.\n\tvirtual ~LanguagePlurality() { /* Empty by design. */ }\n\t/// Get dictionary key suffix for value of @a n.\n\t/**\n\t * @param n The number controlling the plurality.\n\t * @return Pointer to the zero-terminated suffix string.\n\t*/\n\tvirtual const char *getSuffix(unsigned n) const = 0;\n\t/// Create a concrete instance for a given language.\n\t/**\n\t * @param language Locale of the language.\n\t * @return Plurality rules for that language.\n\t */\n\tstatic LanguagePlurality *create(const std::string &language);\n\nprotected:\n\tLanguagePlurality() { /* Empty by design. */ }\nprivate:\n\ttypedef LanguagePlurality *(*PFCreate)();\n\tstatic std::map<std::string, PFCreate> s_factoryFunctions;\n};\n}\n"
  },
  {
    "path": "src/Engine/LocalizedText.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"LocalizedText.h\"\n#include \"Language.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Replace the next argument placeholder with @a val.\n * @param val The value to place in the next placeholder's position.\n * @return A translated string with all occurrences of the marker replaced by @a val.\n */\nLocalizedText LocalizedText::arg(const std::string &val) const\n{\n\tstd::ostringstream os;\n\tos << '{' << _nextArg << '}';\n\tstd::string marker(os.str());\n\tsize_t pos = _text.find(marker);\n\tif (std::string::npos == pos)\n\t\treturn *this;\n\tstd::string ntext(_text);\n\tfor (/*empty*/ ; std::string::npos != pos; pos = ntext.find(marker, pos + val.length()))\n\t{\n\t\tntext.replace(pos, marker.length(), val);\n\t}\n\treturn LocalizedText(ntext, _nextArg);\n}\n\n/**\n * Replace the next argument placeholder with @a val.\n * @param val The value to place in the next placeholder's position.\n * @return The translated string with all occurrences of the marker replaced by @a val.\n */\nLocalizedText &LocalizedText::arg(const std::string &val)\n{\n\tstd::ostringstream os;\n\tos << '{' << _nextArg << '}';\n\tstd::string marker(os.str());\n\tsize_t pos = _text.find(marker);\n\tif (std::string::npos != pos)\n\t{\n\t\tfor (/*empty*/ ; std::string::npos != pos; pos = _text.find(marker, pos + val.length()))\n\t\t{\n\t\t\t_text.replace(pos, marker.length(), val);\n\t\t}\n\t}\n\t++_nextArg;\n\treturn *this;\n}\n\n}\n"
  },
  {
    "path": "src/Engine/LocalizedText.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include <sstream>\n\n/// @file\n\n/** @def OX_REQUIRED_RESULT\n * This is used to enable warning of unused results, to warn the user of costly function calls.\n */\n\n#ifndef OX_REQUIRED_RESULT\n#  if defined(__GNUC_) && !defined(__INTEL_COMPILER) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1))\n#    define OX_REQUIRED_RESULT __attribute__ ((warn_unused_result))\n#  else\n#    define OX_REQUIRED_RESULT\n#  endif\n#endif\nnamespace OpenXcom\n{\n\n/**\n * A string that is already translated.\n * Using this class allows argument substitution in the translated strings.\n */\nclass LocalizedText\n{\npublic:\n\t/// Create from existing string.\n\tLocalizedText(const std::string &);\n\t/// Create the empty string.\n\tLocalizedText() : _nextArg(1) { /* Empty by design. */ }\n\t/// Return constant string.\n\toperator std::string const&() const OX_REQUIRED_RESULT;\n\t/// Get a pointer to underlying char data.\n\tconst char *c_str() const OX_REQUIRED_RESULT { return _text.c_str(); }\n\n\t// Argument substitution.\n\t/// Replace next argument.\n\tLocalizedText arg(const std::string &) const OX_REQUIRED_RESULT;\n\tLocalizedText &arg(const std::string &) OX_REQUIRED_RESULT;\n\ttemplate <typename T> LocalizedText arg(T) const OX_REQUIRED_RESULT;\n\ttemplate <typename T> LocalizedText &arg(T) OX_REQUIRED_RESULT;\nprivate:\n\tstd::string _text; ///< The actual localized text.\n\tunsigned _nextArg; ///< The next argument ID.\n\tLocalizedText(const std::string &, unsigned);\n};\n\n/**\n * Create a LocalizedText from a localized std::string.\n */\ninline LocalizedText::LocalizedText(const std::string &text)\n  : _text(text), _nextArg(0)\n{\n\t// Empty by design.\n}\n\n/**\n * Create a LocalizedText with some arguments already replaced.\n */\ninline LocalizedText::LocalizedText(const std::string &text, unsigned replaced)\n  : _text(text), _nextArg(replaced + 1)\n{\n\t// Empty by design.\n}\n\n/**\n * Typecast to constant std::string reference.\n * This is used to avoid copying when the string will not change.\n */\ninline LocalizedText::operator std::string const&() const\n{\n\treturn _text;\n}\n\n/**\n * Replace the next argument placeholder with @a val.\n * @tparam T The type of the replacement value. It should be streamable to std::owstringstream.\n * @param val The value to place in the next placeholder's position.\n * @return A translated string with all occurrences of the marker replaced by @a val.\n */\ntemplate <typename T>\nLocalizedText LocalizedText::arg(T val) const\n{\n\tstd::ostringstream os;\n\tos << '{' << _nextArg << '}';\n\tstd::string marker(os.str());\n\tsize_t pos = _text.find(marker);\n\tif (std::string::npos == pos)\n\t\treturn *this;\n\tstd::string ntext(_text);\n\tos.str(\"\");\n\tos << val;\n\tstd::string tval(os.str());\n\tfor (/*empty*/ ; std::string::npos != pos; pos = ntext.find(marker, pos + tval.length()))\n\t{\n\t\tntext.replace(pos, marker.length(), tval);\n\t}\n\treturn LocalizedText(ntext, _nextArg);\n}\n\n/**\n * Replace the next argument placeholder with @a val.\n * @tparam T The type of the replacement value. It should be streamable to std::owstringstream.\n * @param val The value to place in the next placeholder's position.\n * @return The translated string with all occurrences of the marker replaced by @a val.\n */\ntemplate <typename T>\nLocalizedText &LocalizedText::arg(T val)\n{\n\tstd::ostringstream os;\n\tos << '{' << _nextArg << '}';\n\tstd::string marker(os.str());\n\tsize_t pos = _text.find(marker);\n\tif (std::string::npos != pos)\n\t{\n\t\tos.str(\"\");\n\t\tos << val;\n\t\tstd::string tval(os.str());\n\t\tfor (/*empty*/ ; std::string::npos != pos; pos = _text.find(marker, pos + tval.length()))\n\t\t{\n\t\t\t_text.replace(pos, marker.length(), tval);\n\t\t}\n\t}\n\t++_nextArg;\n\treturn *this;\n}\n\n/// Allow streaming of LocalizedText objects.\ninline std::ostream &operator<<(std::ostream &os, const LocalizedText &txt)\n{\n\tos << static_cast<std::string const &>(txt);\n\treturn os;\n}\n\n}\n"
  },
  {
    "path": "src/Engine/Logger.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <sstream>\n#include <string>\n#include \"CrossPlatform.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Defines the various severity levels of\n * information logged by the game.\n */\nenum SeverityLevel\n{\n\tLOG_FATAL,\t\t/**< Something horrible has happened and the game is going to die! */\n\tLOG_ERROR,\t\t/**< Something bad happened but we can still move on. */\n\tLOG_WARNING,\t/**< Something weird happened, nothing special but it's good to know. */\n\tLOG_INFO,\t\t/**< Useful information for users/developers to help debug and figure stuff out. */\n\tLOG_DEBUG,\t\t/**< Purely test stuff to help developers implement, not really relevant to users. */\n\tLOG_VERBOSE,\t/**< Extra details that even developers won't really need 90% of the time. */\n\n\tLOG_UNCENSORED  /**< Makes sure everything makes it into log buffer until there's a logfile set up */\n};\n\n/**\n * A basic logging and debugging class, prints output to stdout/files.\n * @note Wasn't really satisfied with any of the libraries around\n * so I rolled my own. Based on http://www.drdobbs.com/cpp/logging-in-c/201804215\n */\nclass Logger\n{\npublic:\n\tLogger() : _level(LOG_INFO) { };\n\tvirtual ~Logger() { CrossPlatform::log(_level, os); };\n\tstd::ostringstream& get(SeverityLevel level = LOG_INFO) { _level = level; return os; };\n\n\tstatic SeverityLevel& reportingLevel() {\n\t\tstatic SeverityLevel reportingLevel = LOG_UNCENSORED;\n\t\treturn reportingLevel;\n\t};\n\tstatic const std::string& toString(int level) {\n\t\tstatic const std::string buffer[] = { \"FATAL\", \"ERROR\", \"WARN\", \"INFO\", \"DEBUG\", \"VERB\", \"ALL\" };\n\t\treturn buffer[level];\n\t};\nprivate:\n\tLogger(const Logger&);\n\tSeverityLevel _level;\n\tstd::ostringstream os;\n};\n\n#define Log(level) if (level > Logger::reportingLevel()) { } else Logger().get(level)\n\n}\n"
  },
  {
    "path": "src/Engine/ModInfo.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"../version.h\"\n#include \"ModInfo.h\"\n#include \"CrossPlatform.h\"\n#include \"Exception.h\"\n#include \"Logger.h\"\n#include \"../Engine/Yaml.h\"\n#include <sstream>\n#include <assert.h>\n\nnamespace OpenXcom\n{\n\nnamespace\n{\n\nModInfoVersion normalizeModVersion(const std::string& parent, const std::string& ver)\n{\n\tconst int prefix_num_min = 0;\n\tconst int prefix_num_max = 10;\n\tconst int prefix_text = 11;\n\n\tconst int was_nothing = 0;\n\tconst int was_num = 1;\n\tconst int was_text = 2;\n\tconst int was_dot = 3;\n\n\n\tint state = was_nothing;\n\tsize_t last_prefix_num = 0;\n\n\tModInfoNormalizedVersion normalized;\n\n\tfor (std::string::const_iterator it = ver.begin(); it != ver.end(); ++it)\n\t{\n\t\tchar curr = *it;\n\t\tif (curr >= 'a' && curr <= 'z')\n\t\t{\n\t\t\tcurr += 'A' - 'a'; // make case-insensitive\n\t\t}\n\n\t\tif (curr >= 'A' && curr <= 'Z')\n\t\t{\n\t\t\tswitch (state)\n\t\t\t{\n\t\t\t\tcase was_nothing:\n\t\t\t\tcase was_dot:\n\t\t\t\tcase was_num:\n\t\t\t\t{\n\t\t\t\t\tstate = was_text;\n\t\t\t\t\tnormalized.push_back(prefix_text);\n\t\t\t\t\tnormalized.push_back(curr);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tcase was_text:\n\t\t\t\t{\n\t\t\t\t\tnormalized.push_back(curr);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse if (curr >= '0' && curr <= '9')\n\t\t{\n\t\t\tswitch (state)\n\t\t\t{\n\t\t\t\tcase was_nothing:\n\t\t\t\tcase was_dot:\n\t\t\t\tcase was_text:\n\t\t\t\t{\n\t\t\t\t\tstate = was_num;\n\t\t\t\t\tlast_prefix_num = normalized.size();\n\t\t\t\t\tnormalized.push_back(prefix_num_min);\n\t\t\t\t\tif (curr > '0')\n\t\t\t\t\t{\n\t\t\t\t\t\t++normalized[last_prefix_num];\n\t\t\t\t\t\tnormalized.push_back(curr);\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tcase was_num:\n\t\t\t\t{\n\t\t\t\t\tint temp = normalized[last_prefix_num];\n\t\t\t\t\tif (temp == prefix_num_max)\n\t\t\t\t\t{\n\t\t\t\t\t\tLog(LOG_WARNING) << \"Error in version number in mod '\" << parent << \"': unsupported number length\";\n\t\t\t\t\t\treturn std::make_pair(ver, ModInfoNormalizedVersion());\n\t\t\t\t\t}\n\t\t\t\t\tif (temp != prefix_num_min || curr > '0')\n\t\t\t\t\t{\n\t\t\t\t\t\t++normalized[last_prefix_num];\n\t\t\t\t\t\tnormalized.push_back(curr);\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse if (curr == '.')\n\t\t{\n\t\t\tif (was_dot == state)\n\t\t\t{\n\t\t\t\tLog(LOG_WARNING) << \"Error in version number in mod '\" << parent << \"': duplicated dots\";\n\t\t\t\treturn std::make_pair(ver, ModInfoNormalizedVersion());\n\t\t\t}\n\t\t\tstate = was_dot;\n\t\t\tcontinue;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tLog(LOG_WARNING) << \"Error in version number in mod '\" << parent << \"': unexpected symbol\";\n\t\t\treturn std::make_pair(ver, ModInfoNormalizedVersion());\n\t\t}\n\t\tassert(false && \"invalid move version parser state\");\n\t}\n\n\t// version could be ends with chain of \"0.0.0.0.0\", trim to last not zero\n\tstd::string::size_type last = normalized.find_last_not_of(ModInfoNormalizedVersion::value_type(0));\n\tif (last != std::string::npos)\n\t{\n\t\tnormalized.erase(last + 1);\n\t}\n\telse if (normalized.size())\n\t{\n\t\t// version is only \"0\" leave first \"0\" and remove rest\n\t\tnormalized.erase(1);\n\t}\n\n\treturn std::make_pair(ver, normalized);\n}\n\nbool compareVersions(const ModInfoVersion& provided, const ModInfoVersion& required)\n{\n\treturn provided.first == required.first || provided.second >= required.second;\n}\n\nconst ModInfoVersion defaultModVersion = normalizeModVersion(\"def\", \"1.0\");\n\n\n} //namespace\n\nModInfo::ModInfo(const std::string &path) :\n\t _path(path), _name(CrossPlatform::baseFilename(path)),\n\t_desc(\"No description.\"), _author(\"unknown author\"),\n\t_id(_name), _master(\"xcom1\"),\n\t_versionDisplay(\"1.0\"),\n\t_version(defaultModVersion),\n\t_isMaster(false), _reservedSpace(1),\n\t_engineOk(false)\n{\n\t// empty\n}\n\nnamespace\n{\n\nstruct EngineData\n{\n\tstd::string name;\n\tint version[4];\n};\n\n/**\n * List of engines that current version support.\n */\nconst EngineData supportedEngines[] = {\n\t{ OPENXCOM_VERSION_ENGINE, { OPENXCOM_VERSION_NUMBER }},\n\t{ \"\", { 0, 0, 0, 0 } }, // assume that every engine support mods from base game, remove if its not true.\n};\n\ntemplate<int I>\nbool findCompatibleEngine(const EngineData (&l)[I], const std::string& e, const std::array<int, 4>& version)\n{\n\tfor (auto& d : supportedEngines)\n\t{\n\t\tif (d.name == e)\n\t\t{\n\t\t\treturn !CrossPlatform::isHigherThanCurrentVersion(version, d.version);\n\t\t}\n\t}\n\treturn false;\n}\n\n} //namespace\n\nvoid ModInfo::load(const YAML::YamlNodeReader& reader)\n{\n\treader.tryRead(\"id\", _id);\n\treader.tryRead(\"name\", _name);\n\treader.tryRead(\"description\", _desc);\n\tif (const auto& ver = reader[\"version\"])\n\t{\n\t\t_version  = normalizeModVersion(_id, ver.readVal<std::string>());\n\t\t_versionDisplay = _version.first;\n\t}\n\treader.tryRead(\"versionDisplay\", _versionDisplay);\n\treader.tryRead(\"author\", _author);\n\treader.tryRead(\"isMaster\", _isMaster);\n\treader.tryRead(\"reservedSpace\", _reservedSpace);\n\n\tif (reader.tryRead(\"requiredExtendedVersion\", _requiredExtendedVersion))\n\t\t_requiredExtendedEngine = \"Extended\"; // for backward compatibility\n\treader.tryRead(\"requiredExtendedEngine\", _requiredExtendedEngine);\n\n\t_engineOk = findCompatibleEngine(supportedEngines, _requiredExtendedEngine, CrossPlatform::parseVersion(_requiredExtendedVersion));\n\n\tif (_reservedSpace < 1)\n\t{\n\t\t_reservedSpace = 1;\n\t}\n\telse if (_reservedSpace > 100)\n\t{\n\t\t_reservedSpace = 100;\n\t}\n\n\tif (_isMaster)\n\t{\n\t\t// default a master's master to none.  masters can still have\n\t\t// masters, but they must be explicitly declared.\n\t\t_master = \"\";\n\t}\n\treader.tryRead(\"resourceConfig\", _resourceConfigFile);\n\n\treader.tryRead(\"master\", _master);\n\tif (_master == \"*\")\n\t{\n\t\t_master = \"\";\n\t}\n\n\tif (_isMaster && _master.empty())\n\t{\n\t\t// only top-level masters can load external resource dirs\n\t\treader.tryRead(\"loadResources\", _externalResourceDirs);\n\t}\n\n\tif (const auto& req = reader[\"requiredMasterModVersion\"])\n\t{\n\t\tif (_master.empty())\n\t\t{\n\t\t\tLog(LOG_WARNING) << \"Mod '\" << _id << \"' without master can't have 'requiredMasterModVersion'.\";\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_requiredMasterModVersion = normalizeModVersion(_id, req.readVal<std::string>());\n\t\t}\n\t}\n}\n\nconst std::string &ModInfo::getPath()                    const { return _path;                    }\nconst std::string &ModInfo::getName()                    const { return _name;                    }\nconst std::string &ModInfo::getDescription()             const { return _desc;                    }\nconst std::string &ModInfo::getVersion()                 const { return _version.first;           }\nconst std::string &ModInfo::getVersionDisplay()          const { return _versionDisplay;          }\nconst std::string &ModInfo::getAuthor()                  const { return _author;                  }\nconst std::string &ModInfo::getId()                      const { return _id;                      }\nconst std::string &ModInfo::getMaster()                  const { return _master;                  }\nconst std::string &ModInfo::getRequiredMasterVersion()   const { return _requiredMasterModVersion.first; }\nbool               ModInfo::isMaster()                   const { return _isMaster;                }\nbool               ModInfo::isEngineOk()                 const { return _engineOk;                }\nconst std::string &ModInfo::getRequiredExtendedEngine()  const { return _requiredExtendedEngine;  }\nconst std::string &ModInfo::getRequiredExtendedVersion() const { return _requiredExtendedVersion; }\nconst std::string &ModInfo::getResourceConfigFile()      const { return _resourceConfigFile;      }\nint                ModInfo::getReservedSpace()           const { return _reservedSpace;           }\n\n/**\n * Is parent mod is in required version?\n */\nbool ModInfo::isParentMasterOk(const ModInfo* parentMod) const\n{\n\treturn _requiredMasterModVersion.first == \"\" || compareVersions(parentMod->_version, _requiredMasterModVersion);\n}\n\n/**\n * Checks if a given mod can be activated.\n * It must either be:\n * - a Master mod\n * - a standalone mod (no master)\n * - depend on the current Master mod\n * @param curMaster Id of the active master mod.\n * @return True if it's activable, false otherwise.\n*/\nbool ModInfo::canActivate(const std::string &curMaster) const\n{\n\treturn (isMaster() || getMaster().empty() || getMaster() == curMaster);\n}\n\n\nconst std::vector<std::string> &ModInfo::getExternalResourceDirs() const { return _externalResourceDirs; }\n\n\n\n#ifndef NDEBUG\n\nstatic auto dummy = ([]\n{\n\tauto create = [](int i, int j, int k, int l)\n\t{\n\t\treturn std::array<int, 4>{{i, j, k, l}};\n\t};\n\n\tassert(findCompatibleEngine(supportedEngines, \"Extended\", create(OPENXCOM_VERSION_NUMBER)));\n\tassert(findCompatibleEngine(supportedEngines, \"Extended\", create(1, 0, 0, 0)));\n\tassert(findCompatibleEngine(supportedEngines, \"\", create(0, 0, 0, 0)));\n\tassert(!findCompatibleEngine(supportedEngines, \"Extended\", create(OPENXCOM_VERSION_NUMBER + 1)));\n\tassert(!findCompatibleEngine(supportedEngines, \"XYZ\", create(OPENXCOM_VERSION_NUMBER)));\n\tassert(!findCompatibleEngine(supportedEngines, \"XYZ\", create(0, 0, 0, 0)));\n\n\n\tauto check = [](const std::string& a, const std::string& b)\n\t{\n\t\tModInfoVersion aa = normalizeModVersion(\"x\", a);\n\t\tModInfoVersion bb = normalizeModVersion(\"x\", b);\n\n\t\tassert(aa.second != ModInfoNormalizedVersion());\n\t\tassert(bb.second != ModInfoNormalizedVersion());\n\n\t\treturn compareVersions(aa, bb);\n\t};\n\n\tassert(normalizeModVersion(\"x\", \"\") == ModInfoVersion());\n\n\tassert(check(\"A\", \"1\"));\n\tassert(!check(\"1\", \"A\"));\n\n\tassert(check(\"A0\", \"A.0\"));\n\tassert(check(\"A.0\", \"A0\"));\n\n\tassert(check(\"A1\", \"A.0\"));\n\tassert(!check(\"A.0\", \"A1\"));\n\n\tassert(check(\"A0.0\", \"A.0\"));\n\n\tassert(check(\"B\", \"A.0\"));\n\tassert(!check(\"A.0\", \"B\"));\n\n\tassert(check(\"BA\", \"B\"));\n\n\tassert(check(\"A11\", \"A2\"));\n\n\tassert(!check(\"0000\", \"0001\"));\n\tassert(check(\"0001\", \"0000\"));\n\tassert(check(\"0001\", \"0000000\"));\n\tassert(check(\"1\", \"0000000\"));\n\n\tassert(check(\"1\", \"0000001\"));\n\tassert(check(\"0001\", \"0000001\"));\n\tassert(check(\"0001\", \"1\"));\n\n\tassert(check(\"A1\", \"A0000001\"));\n\tassert(check(\"A0001\", \"A0000001\"));\n\tassert(check(\"A0001\", \"A1\"));\n\n\tassert(check(\"10001\", \"0000\"));\n\tassert(!check(\"0000\", \"10001\"));\n\n\tassert(check(\"1.0\", \"1\"));\n\tassert(check(\"1\", \"1.0\"));\n\tassert(check(\"1\", \"1.0.0.0\"));\n\tassert(check(\"1\", \"1.0.000.0\"));\n\n\n\tassert(!check(\"1\", \"1.0.000.0.1\"));\n\n\treturn 0;\n})();\n#endif\n\n}\n"
  },
  {
    "path": "src/Engine/ModInfo.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include <map>\n#include <vector>\n#include \"../Engine/Yaml.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * String with normalized version number\n */\nstruct ModInfoNormalizedVersion : std::string\n{\n\tModInfoNormalizedVersion() = default;\n\tModInfoNormalizedVersion(ModInfoNormalizedVersion&&) = default;\n\tModInfoNormalizedVersion(const ModInfoNormalizedVersion&) = default;\n\n\tModInfoNormalizedVersion& operator=(ModInfoNormalizedVersion&&) = default;\n\tModInfoNormalizedVersion& operator=(const ModInfoNormalizedVersion&) = default;\n};\n\n/**\n * Version number with normalized value.\n */\ntypedef std::pair<std::string, ModInfoNormalizedVersion> ModInfoVersion;\n\n/**\n * Represents mod metadata\n */\nclass ModInfo\n{\nprivate:\n\tconst std::string _path;\n\tstd::string _name, _desc, _author, _url, _id, _master;\n\tstd::string _versionDisplay;\n\tModInfoVersion _version;\n\tbool _isMaster;\n\tint _reservedSpace;\n\tbool _engineOk;\n\tstd::string _requiredExtendedEngine;\n\tstd::string _requiredExtendedVersion;\n\n\tModInfoVersion _requiredMasterModVersion;\n\n\tstd::string _resourceConfigFile;\n\tstd::vector<std::string> _externalResourceDirs;\npublic:\n\t/// Creates default metadata for a mod at the specified path.\n\tModInfo(const std::string &path);\n\t/// Loads the metadata from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader);\n\t/// Gets the path where this mod resides on disk.\n\tconst std::string &getPath() const;\n\t/// Gets the name of this mod.\n\tconst std::string &getName() const;\n\t/// Gets the description for this mod.\n\tconst std::string &getDescription() const;\n\t/// Gets the version of this mod.\n\tconst std::string &getVersion() const;\n\t/// Gets the version for display of this mod.\n\tconst std::string &getVersionDisplay() const;\n\t/// Gets the author of this mod.\n\tconst std::string &getAuthor() const;\n\t/// Gets the id for this mod.\n\tconst std::string &getId() const;\n\n\t/// Gets the master this mod can load under.  If it can load under any\n\t/// master (or if this mod is a master itself FIXME: this is wrong), the return value is empty.\n\tconst std::string &getMaster() const;\n\t/// Gets required version of master mod.\n\tconst std::string &getRequiredMasterVersion() const;\n\n\t/// Gets whether this mod is a master (i.e. a vanilla game/total conversion)\n\tbool isMaster() const;\n\t/// Is parent mod is in required version?\n\tbool isParentMasterOk(const ModInfo* parentMod) const;\n\n\t/// Gets whether this mod can be activated.\n\tbool canActivate(const std::string &curMaster) const;\n\t/// Gets size of mod, bigger mod reserve more values in common collections/surfacesets.\n\tint getReservedSpace() const;\n\n\t/// Is mod compatible with current OXCE engine aka \"fork\", check too whether the current OXCE version is equal to (or higher than) the required OXCE version.\n\tbool isEngineOk() const;\n\t/// Gets the OXCE engine (like \"FtA\" or \"Extended\") required by this mod.\n\tconst std::string &getRequiredExtendedEngine() const;\n\t/// Gets the OXCE version required by this mod.\n\tconst std::string &getRequiredExtendedVersion() const;\n\n\t/// Gets ruleset file where are defined based resources like required original game data.\n\tconst std::string &getResourceConfigFile() const;\n\t/// Gets the list of external resource dirs to load for this mod.\n\tconst std::vector<std::string> &getExternalResourceDirs() const;\n};\n\n}\n"
  },
  {
    "path": "src/Engine/Music.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Music.h\"\n#include \"Exception.h\"\n#include \"Options.h\"\n#include \"Logger.h\"\n#include \"Unicode.h\"\n#include \"FileMap.h\"\n#include \"SDL2Helpers.h\"\n#include \"Adlib/adlplayer.h\"\n#include \"AdlibMusic.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes a new music track.\n */\nMusic::Music() : _music(0), _rwops(0)\n{\n}\n\n/**\n * Deletes the loaded music content.\n */\nMusic::~Music()\n{\n#ifndef __NO_MUSIC\n\tstop();\n\tif (_music)\tMix_FreeMusic(_music);\n\tif (_rwops) SDL_RWclose(_rwops);\n#endif\n}\n\n/**\n * Loads a music file from a specified filename.\n * @param filename Filename of the music file.\n */\nvoid Music::load(const std::string &filename)\n{\n#ifndef __NO_MUSIC\n\tload(FileMap::getRWops(filename));\n\tLog(LOG_VERBOSE)<<\"Music::load('\" << filename << \"')\";\n#endif\n}\n\n/**\n * Loads a music file from a specified rwops.\n * @param filename Filename of the music file.\n */\nvoid Music::load(SDL_RWops *rwops)\n{\n#ifndef __NO_MUSIC\n\t_rwops = rwops;\n\t_music = Mix_LoadMUS_RW(_rwops);\n\n\tif (_music == 0)\n\t{\n\t\tthrow Exception(Mix_GetError());\n\t}\n#endif\n}\n\n/**\n * Plays the contained music track.\n * @param loop Amount of times to loop the track. -1 = infinite\n */\nvoid Music::play(int loop) const\n{\n#ifndef __NO_MUSIC\n\tif (!Options::mute)\n\t{\n\t\tif (_music != 0)\n\t\t{\n\t\t\tstop();\n\t\t\tif (Mix_PlayMusic(_music, loop) == -1)\n\t\t\t{\n\t\t\t\tLog(LOG_WARNING) << Mix_GetError();\n\t\t\t}\n\t\t}\n\t}\n#endif\n}\n\n/**\n * Stops all music playing.\n */\nvoid Music::stop()\n{\n#ifndef __NO_MUSIC\n\tif (!Options::mute)\n\t{\n\t\tfunc_mute();\n\t\tMix_HookMusic(NULL, NULL);\n\t\tMix_HaltMusic();\n\t}\n#endif\n}\n\n/**\n * Pauses music playback when game loses focus.\n */\nvoid Music::pause()\n{\n#ifndef __NO_MUSIC\n\tif (!Options::mute)\n\t{\n\t\tMix_PauseMusic();\n\t\tif (Mix_GetMusicType(0) == MUS_NONE)\n\t\t\tMix_HookMusic(NULL, NULL);\n\t}\n#endif\n}\n\n/**\n * Resumes music playback when game gains focus.\n */\nvoid Music::resume()\n{\n#ifndef __NO_MUSIC\n\tif (!Options::mute)\n\t{\n\t\tMix_ResumeMusic();\n\t\tif (Mix_GetMusicType(0) == MUS_NONE)\n\t\t\tMix_HookMusic(AdlibMusic::player, NULL);\n\t}\n#endif\n}\n\n/**\n * Checks if any music is playing.\n */\nbool Music::isPlaying()\n{\n#ifndef __NO_MUSIC\n\tif (!Options::mute)\n\t{\n\t\treturn Mix_Playing(-1) != 0;\n\t}\n#endif\n\treturn false;\n}\n\n}\n"
  },
  {
    "path": "src/Engine/Music.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include <SDL_mixer.h>\n\nnamespace OpenXcom\n{\n\n/**\n * Container for music tracks.\n * Handles loading and playing various formats through SDL_mixer.\n */\nclass Music\n{\nprivate:\n\tMix_Music *_music;\n\tSDL_RWops *_rwops;\npublic:\n\t/// Creates a blank music track.\n\tMusic();\n\t/// Cleans up the music track.\n\tvirtual ~Music();\n\t/// Loads music from the specified file.\n\tvirtual void load(const std::string &filename);\n\t/// Loads music from the specified rwops.\n\tvirtual void load(SDL_RWops *rwops);\n\t/// Plays the music.\n\tvirtual void play(int loop = -1) const;\n\t/// Stops all music.\n\tstatic void stop();\n\t/// Pauses all music.\n\tstatic void pause();\n\t/// Resumes all music.\n\tstatic void resume();\n\t/// Checks if music is playing.\n\tstatic bool isPlaying();\n};\n\n}\n"
  },
  {
    "path": "src/Engine/NullableValue.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2025 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include <SDL_stdinc.h>\n#include <limits>\n\n\nnamespace OpenXcom\n{\n\n\n/**\n * Simpler version of std::optional, that sacrifice one possible value for null\n */\ntemplate<typename T>\nclass NullableValue\n{\n\tT value;\n\npublic:\n\t/// Default constructor.\n\tNullableValue() : value{ std::numeric_limits<T>::min() }\n\t{\n\n\t}\n\t/// Constructor.\n\tNullableValue(T t) : value{ t }\n\t{\n\n\t}\n\n\t/// Current value is null.\n\tbool isNull() const\n\t{\n\t\treturn value == std::numeric_limits<T>::min();\n\t}\n\t/// Have value.\n\tbool isValue() const\n\t{\n\t\treturn !isNull();\n\t}\n\n\n\t/// Set new value.\n\tvoid setValue(T t)\n\t{\n\t\tvalue = t;\n\t}\n\t/// Set null.\n\tvoid setNull()\n\t{\n\t\tvalue = std::numeric_limits<T>::min();\n\t}\n\n\t/// Get value of default.\n\tT getValueOrDefualt() const\n\t{\n\t\treturn isNull() ? T{ } : value;\n\t}\n\n\t/// Get value or fallback value.\n\tT getValueOr(T fallback) const\n\t{\n\t\treturn isNull() ? fallback : value;\n\t}\n};\n\n/**\n * Simpler version of std::optional, optimized for `bool`\n */\ntemplate<>\nclass NullableValue<bool>\n{\n\tSint8 value;\n\npublic:\n\t/// Default constructor.\n\tNullableValue() : value{ -1 }\n\t{\n\n\t}\n\t/// Constructor.\n\tNullableValue(bool t) : value{ t }\n\t{\n\n\t}\n\n\t/// Current value is null.\n\tbool isNull() const\n\t{\n\t\treturn value == -1;\n\t}\n\t/// Have value.\n\tbool isValue() const\n\t{\n\t\treturn !isNull();\n\t}\n\n\n\t/// Set new value.\n\tvoid setValue(bool t)\n\t{\n\t\tvalue = t;\n\t}\n\t/// Set null.\n\tvoid setNull()\n\t{\n\t\tvalue = -1;\n\t}\n\n\t/// Get value of default.\n\tbool getValueOrDefualt() const\n\t{\n\t\treturn isNull() ? false : value;\n\t}\n};\n\ntemplate<typename T, typename... Rest>\nT coalesceNullValues(NullableValue<T> t, Rest... rest)\n{\n\tif constexpr (sizeof...(rest) > 0)\n\t{\n\t\tif (t.isNull())\n\t\t{\n\t\t\treturn coalesceNullValues(rest...);\n\t\t}\n\t}\n\n\treturn t.getValueOrDefualt();\n}\n\n\n\n} //namespace OpenXcom\n"
  },
  {
    "path": "src/Engine/OpenGL.cpp",
    "content": "// This file was copied from the bsnes project.\n\n// This is the license info, from ruby.hpp:\n\n/*\n  ruby\n  version: 0.08 (2011-11-25)\n  license: public domain\n */\n\n#ifndef __NO_OPENGL\n\n#include \"OpenGL.h\"\n#include <SDL.h>\n#include \"../Engine/Yaml.h\"\n\n#include \"Logger.h\"\n#include \"Surface.h\"\n#include \"FileMap.h\"\n\nnamespace OpenXcom\n{\n\nbool OpenGL::checkErrors = true;\n\nstd::string strGLError(GLenum glErr)\n{\n\tstd::string err;\n\n\tswitch(glErr)\n\t{\n\tcase GL_INVALID_ENUM:\n\t\terr = \"GL_INVALID_ENUM\";\n\t\tbreak;\n\tcase GL_INVALID_VALUE:\n\t\terr = \"GL_INVALID_VALUE\";\n\t\tbreak;\n\tcase GL_INVALID_OPERATION:\n\t\terr = \"GL_INVALID_OPERATION\";\n\t\tbreak;\n\tcase GL_STACK_OVERFLOW:\n\t\terr = \"GL_STACK_OVERFLOW\";\n\t\tbreak;\n\tcase GL_STACK_UNDERFLOW:\n\t\terr = \"GL_STACK_UNDERFLOW\";\n\t\tbreak;\n\tcase GL_OUT_OF_MEMORY:\n\t\terr = \"GL_OUT_OF_MEMORY\";\n\t\tbreak;\n\tcase GL_NO_ERROR:\n\t\terr = \"No error! How did you even reach this code?\";\n\t\tbreak;\n\tdefault:\n\t\terr = \"Unknown error code!\";\n\t\tbreak;\n\t}\n\n\treturn err;\n}\n\n/* Helper types to convert between object pointers and function pointers.\n   Although ignored by some compilers, this conversion is an extension\n   and not guaranteed to be sane for every architecture.\n */\ntypedef void (*GenericFunctionPointer)();\ntypedef union\n{\n\tGenericFunctionPointer FunctionPointer;\n\tvoid *ObjectPointer;\n} UnsafePointerContainer;\n\ninline static GenericFunctionPointer glGetProcAddress(const char *name)\n{\n\tUnsafePointerContainer pc;\n\tpc.ObjectPointer = SDL_GL_GetProcAddress(name);\n\treturn pc.FunctionPointer;\n}\n\n#ifndef __APPLE__\nPFNGLCREATEPROGRAMPROC glCreateProgram = 0;\nPFNGLDELETEPROGRAMPROC glDeleteProgram = 0;\nPFNGLUSEPROGRAMPROC glUseProgram = 0;\nPFNGLISPROGRAMPROC glIsProgram = 0;\nPFNGLISSHADERPROC glIsShader = 0;\nPFNGLCREATESHADERPROC glCreateShader = 0;\nPFNGLDELETESHADERPROC glDeleteShader = 0;\nPFNGLSHADERSOURCEPROC glShaderSource = 0;\nPFNGLCOMPILESHADERPROC glCompileShader = 0;\nPFNGLATTACHSHADERPROC glAttachShader = 0;\nPFNGLDETACHSHADERPROC glDetachShader = 0;\nPFNGLGETATTACHEDSHADERSPROC glGetAttachedShaders = 0;\nPFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog = 0;\nPFNGLGETPROGRAMIVPROC glGetProgramiv = 0;\nPFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog = 0;\nPFNGLGETSHADERIVPROC glGetShaderiv = 0;\nPFNGLLINKPROGRAMPROC glLinkProgram = 0;\nPFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation = 0;\nPFNGLUNIFORM1IPROC glUniform1i = 0;\nPFNGLUNIFORM2FVPROC glUniform2fv = 0;\nPFNGLUNIFORM4FVPROC glUniform4fv = 0;\n#endif\n\nvoid * (APIENTRYP glXGetCurrentDisplay)() = 0;\nUint32 (APIENTRYP glXGetCurrentDrawable)() = 0;\nvoid (APIENTRYP glXSwapIntervalEXT)(void *display, Uint32 GLXDrawable, int interval);\n\nUint32 (APIENTRYP wglSwapIntervalEXT)(int interval);\n\n\n\nvoid OpenGL::resize(unsigned width, unsigned height)\n{\n\tif (gltexture == 0)\n\t{\n\t\tglGenTextures(1, &gltexture);\n\t\tglErrorCheck();\n\t}\n\n\tiwidth = width;\n\tiheight = height;\n\n\tstd::tie(buffer_surface, surface) =  Surface::NewPair32Bit(iwidth, iheight);\n\n\tbuffer = (uint32_t*) buffer_surface.get();\n\n\tglBindTexture(GL_TEXTURE_2D, gltexture);\n\tglErrorCheck();\n\tglPixelStorei(GL_UNPACK_ROW_LENGTH, surface->pitch / surface->format->BytesPerPixel);\n\tglErrorCheck();\n\tglTexImage2D(GL_TEXTURE_2D,\n\t\t/* mip-map level = */ 0, /* internal format = */ GL_RGB16_EXT,\n\t\twidth, height, /* border = */ 0, /* format = */ GL_BGRA,\n\t\tiformat, buffer);\n\tglErrorCheck();\n\n}\n\nbool OpenGL::lock(uint32_t *&data, unsigned &pitch)\n{\n\tpitch = iwidth * ibpp;\n\treturn (data = buffer);\n}\n\nvoid OpenGL::clear() {\n\t//memset(buffer, 0, iwidth * iheight * ibpp);\n\tglClearColor(0.0, 0.0, 0.0, 1.0);\n\tglErrorCheck();\n\tglClear(GL_COLOR_BUFFER_BIT);\n\tglErrorCheck();\n}\n\nvoid OpenGL::refresh(bool smooth, unsigned inwidth, unsigned inheight, unsigned outwidth, unsigned outheight, int topBlackBand, int bottomBlackBand, int leftBlackBand, int rightBlackBand)\n{\n\twhile (glGetError() != GL_NO_ERROR); // clear possible error from who knows where\n\tclear();\n\tif (shader_support && glprogram)\n\t{\n\t\tglUseProgram(glprogram);\n\t\tglErrorCheck();\n\t\tGLint location;\n\n\t\tfloat inputSize[2] = { (float)inwidth, (float)inheight };\n\t\tlocation = glGetUniformLocation(glprogram, \"rubyInputSize\");\n\t\tglUniform2fv(location, 1, inputSize);\n\n\t\tfloat outputSize[2] = { (float)outwidth, (float)outheight };\n\t\tlocation = glGetUniformLocation(glprogram, \"rubyOutputSize\");\n\t\tglUniform2fv(location, 1, outputSize);\n\n\t\tfloat textureSize[2] = { (float)iwidth, (float)iheight };\n\t\tlocation = glGetUniformLocation(glprogram, \"rubyTextureSize\");\n\t\tglUniform2fv(location, 1, textureSize);\n\t\tglErrorCheck();\n    }\n\n\tglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);\n\tglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);\n\tglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, smooth ? GL_LINEAR : GL_NEAREST);\n\tglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, smooth ? GL_LINEAR : GL_NEAREST);\n\n\tglErrorCheck();\n\n\tglMatrixMode(GL_PROJECTION);\n\tglLoadIdentity();\n\tglOrtho(0, outwidth, 0, outheight, -1.0, 1.0);\n\tglViewport(0, 0, outwidth, outheight);\n\n\tglMatrixMode(GL_MODELVIEW);\n\tglLoadIdentity();\n\n\tglErrorCheck();\n\n\tglPixelStorei(GL_UNPACK_ROW_LENGTH, surface->pitch / surface->format->BytesPerPixel);\n\n\tglErrorCheck();\n\n\tglTexSubImage2D(GL_TEXTURE_2D,\n\t\t/* mip-map level = */ 0, /* x = */ 0, /* y = */ 0,\n\t\tiwidth, iheight, GL_BGRA, iformat, buffer);\n\n\n\t//OpenGL projection sets 0,0 as *bottom-left* of screen.\n\t//therefore, below vertices flip image to support top-left source.\n\t//texture range = x1:0.0, y1:0.0, x2:1.0, y2:1.0\n\t//vertex range = x1:0, y1:0, x2:width, y2:height\n\tif (leftBlackBand + rightBlackBand + topBlackBand + bottomBlackBand == 0)\n\t{\n\t\tdouble w = double(inwidth)  / double(iwidth)  * 2;\n\t\tdouble h = double(inheight) / double(iheight) * 2;\n\t\tint u1 = 0;\n\t\tint u2 = outwidth * 2;\n\t\tint v1 = outheight;\n\t\tint v2 = - outheight;\n\n\t\tglBegin(GL_TRIANGLES);\n\t\tglTexCoord2f(0, 0); glVertex3i(u1, v1, 0);\n\t\tglTexCoord2f(w, 0); glVertex3i(u2, v1, 0);\n\t\tglTexCoord2f(0, h); glVertex3i(u1, v2, 0);\n\t\tglEnd();\n\t}\n\telse\n\t{\n\t\tdouble w = double(inwidth)  / double(iwidth);\n\t\tdouble h = double(inheight) / double(iheight);\n\t\tint u1 = leftBlackBand;\n\t\tint u2 = outwidth - rightBlackBand;\n\t\tint v1 = outheight - topBlackBand;\n\t\tint v2 = bottomBlackBand;\n\n\t\tglBegin(GL_TRIANGLE_STRIP);\n\t\tglTexCoord2f(0, 0); glVertex3i(u1, v1, 0);\n\t\tglTexCoord2f(w, 0); glVertex3i(u2, v1, 0);\n\t\tglTexCoord2f(0, h); glVertex3i(u1, v2, 0);\n\t\tglTexCoord2f(w, h); glVertex3i(u2, v2, 0);\n\t\tglEnd();\n\t}\n\tglErrorCheck();\n\n    if (shader_support)\n\t{\n\t\tglUseProgram(0);\n\t\tglErrorCheck();\n\t}\n}\n\nbool OpenGL::set_shader(const char *source_yaml_filename)\n{\n\tif (!shader_support) return false;\n\n\tif (glprogram)\n\t{\n\t\tglDeleteProgram(glprogram);\n\t\tglprogram = 0;\n\t}\n\n\tif (source_yaml_filename && source_yaml_filename[0] != '\\0')\n\t{\n\t\tglprogram = glCreateProgram();\n\t\tif (glprogram == 0)\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"Failed to create GLSL shader program\";\n\t\t\treturn false;\n\t\t}\n\t\t{\n\t\t\tauto reader = FileMap::getYAML(source_yaml_filename);\n\n\t\t\tbool is_glsl;\n\t\t\tstd::string language = reader[\"language\"].readVal<std::string>();\n\t\t\tis_glsl = (language == \"GLSL\");\n\n\n\t\t\tlinear = reader[\"linear\"].readVal(false); // some shaders want texture linear interpolation and some don't\n\t\t\tstd::string fragment_source = reader[\"fragment\"].readVal<std::string>(\"\");\n\t\t\tstd::string vertex_source = reader[\"vertex\"].readVal<std::string>(\"\");\n\n\t\t\tif (is_glsl)\n\t\t\t{\n\t\t\t\tif (!fragment_source.empty()) set_fragment_shader(fragment_source.c_str());\n\t\t\t\tif (!vertex_source.empty()) set_vertex_shader(vertex_source.c_str());\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tLog(LOG_ERROR) << \"Unexpected shader language \\\"\" << language << \"\\\"\";\n\t\t\t}\n\t\t}\n\t\tglLinkProgram(glprogram);\n\t\tglErrorCheck();\n\t\tGLint linkStatus;\n\t\tglGetProgramiv(glprogram, GL_LINK_STATUS, &linkStatus);\n\t\tglErrorCheck();\n\t\tif (linkStatus != GL_TRUE)\n\t\t{\n\t\t\tGLint infoLogLength;\n\t\t\tglGetProgramiv(glprogram, GL_INFO_LOG_LENGTH, &infoLogLength);\n\t\t\tglErrorCheck();\n\t\t\tif (infoLogLength == 0)\n\t\t\t{\n\t\t\t\tLog(LOG_ERROR) << \"OpenGL shader link failed: No log returned from driver\";\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tGLchar *infoLog = new GLchar[infoLogLength];\n\t\t\t\tglGetProgramInfoLog(glprogram, infoLogLength, NULL, infoLog);\n\t\t\t\tglErrorCheck();\n\n\t\t\t\tLog(LOG_ERROR) << \"OpenGL shader link failed \\\"\" << infoLog << \"\\\"\";\n\n\t\t\t\tdelete[] infoLog;\n\t\t\t}\n\t\t\tglDeleteProgram(glprogram);\n\t\t\tglErrorCheck();\n\t\t\tglprogram = 0;\n\t\t}\n\t}\n\treturn glprogram != 0;\n}\n\nstatic GLuint createShader(GLenum type, const char *source)\n{\n\tGLuint shader = glCreateShader(type);\n\tglErrorCheck();\n\tglShaderSource(shader, 1, &source, 0);\n\tglErrorCheck();\n\tglCompileShader(shader);\n\tglErrorCheck();\n\n\tGLint compileSuccess;\n\tglGetShaderiv(shader, GL_COMPILE_STATUS, &compileSuccess);\n\tglErrorCheck();\n\tif (compileSuccess != GL_TRUE)\n\t{\n\t\tGLint infoLogLength;\n\t\tglGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);\n\t\tglErrorCheck();\n\t\tif (infoLogLength == 0)\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"OpenGL shader compilation failed: No log returned from driver\";\n\t\t}\n\t\telse\n\t\t{\n\t\t\tGLchar *infoLog = new GLchar[infoLogLength];\n\t\t\tglGetShaderInfoLog(shader, infoLogLength, NULL, infoLog);\n\t\t\tglErrorCheck();\n\n\t\t\tLog(LOG_ERROR) << \"OpenGL shader compilation failed: \\\"\" << infoLog << \"\\\"\";\n\n\t\t\tdelete[] infoLog;\n\t\t}\n\t\tglDeleteShader(shader);\n\t\tglErrorCheck();\n\t\tshader = 0;\n\t}\n\n\treturn shader;\n}\n\nvoid OpenGL::set_fragment_shader(const char *source)\n{\n\tGLint fragmentshader = createShader(GL_FRAGMENT_SHADER, source);\n\tif (fragmentshader)\n\t{\n\t\tglAttachShader(glprogram, fragmentshader);\n\t\tglErrorCheck();\n\t\tglDeleteShader(fragmentshader);\n\t}\n}\n\nvoid OpenGL::set_vertex_shader(const char *source)\n{\n\tGLint vertexshader = createShader(GL_VERTEX_SHADER, source);\n\tif (vertexshader)\n\t{\n\t\tglAttachShader(glprogram, vertexshader);\n\t\tglErrorCheck();\n\t\tglDeleteShader(vertexshader);\n\t}\n}\n\nvoid OpenGL::init(int w, int h)\n{\n\t//disable unused features\n\tglDisable(GL_ALPHA_TEST);\n\tglDisable(GL_BLEND);\n\tglDisable(GL_DEPTH_TEST);\n\tglDisable(GL_POLYGON_SMOOTH);\n\tglDisable(GL_STENCIL_TEST);\n\tglErrorCheck();\n\n\t//enable useful and required features\n\tglEnable(GL_DITHER);\n\tglEnable(GL_TEXTURE_2D);\n\tglErrorCheck();\n\n    //bind shader functions\n#ifndef __APPLE__\n\tglCreateProgram = (PFNGLCREATEPROGRAMPROC)glGetProcAddress(\"glCreateProgram\");\n\tglDeleteProgram = (PFNGLDELETEPROGRAMPROC)glGetProcAddress(\"glDeleteProgram\");\n\tglUseProgram = (PFNGLUSEPROGRAMPROC)glGetProcAddress(\"glUseProgram\");\n\tglIsProgram = (PFNGLISPROGRAMPROC)glGetProcAddress(\"glIsProgram\");\n\tglIsShader = (PFNGLISSHADERPROC)glGetProcAddress(\"glIsShader\");\n\tglCreateShader = (PFNGLCREATESHADERPROC)glGetProcAddress(\"glCreateShader\");\n\tglDeleteShader = (PFNGLDELETESHADERPROC)glGetProcAddress(\"glDeleteShader\");\n\tglShaderSource = (PFNGLSHADERSOURCEPROC)glGetProcAddress(\"glShaderSource\");\n\tglCompileShader = (PFNGLCOMPILESHADERPROC)glGetProcAddress(\"glCompileShader\");\n\tglAttachShader = (PFNGLATTACHSHADERPROC)glGetProcAddress(\"glAttachShader\");\n\tglDetachShader = (PFNGLDETACHSHADERPROC)glGetProcAddress(\"glDetachShader\");\n\tglGetAttachedShaders = (PFNGLGETATTACHEDSHADERSPROC)glGetProcAddress(\"glGetAttachedShaders\");\n\tglGetProgramiv = (PFNGLGETPROGRAMIVPROC)glGetProcAddress(\"glGetProgramiv\");\n\tglGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC)glGetProcAddress(\"glGetProgramInfoLog\");\n\tglGetShaderiv = (PFNGLGETSHADERIVPROC)glGetProcAddress(\"glGetShaderiv\");\n\tglGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)glGetProcAddress(\"glGetShaderInfoLog\");\n\tglLinkProgram = (PFNGLLINKPROGRAMPROC)glGetProcAddress(\"glLinkProgram\");\n\tglGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC)glGetProcAddress(\"glGetUniformLocation\");\n\tglUniform1i = (PFNGLUNIFORM1IPROC)glGetProcAddress(\"glUniform1i\");\n\tglUniform2fv = (PFNGLUNIFORM2FVPROC)glGetProcAddress(\"glUniform2fv\");\n\tglUniform4fv = (PFNGLUNIFORM4FVPROC)glGetProcAddress(\"glUniform4fv\");\n\n\tshader_support = glCreateProgram && glDeleteProgram && glUseProgram && glCreateShader\n\t&& glDeleteShader && glShaderSource && glCompileShader && glAttachShader\n\t&& glDetachShader && glLinkProgram && glGetUniformLocation && glIsProgram && glIsShader\n\t&& glUniform1i && glUniform2fv && glUniform4fv && glGetAttachedShaders\n\t&& glGetShaderiv && glGetShaderInfoLog && glGetProgramiv && glGetProgramInfoLog;\n#else\n\tshader_support = true;\n#endif\n\tglXGetCurrentDisplay = (void* (APIENTRYP)())glGetProcAddress(\"glXGetCurrentDisplay\");\n\tglXGetCurrentDrawable = (Uint32 (APIENTRYP)())glGetProcAddress(\"glXGetCurrentDrawable\");\n\tglXSwapIntervalEXT = (void (APIENTRYP)(void*, Uint32, int))glGetProcAddress(\"glXSwapIntervalEXT\");\n\n\twglSwapIntervalEXT = (Uint32 (APIENTRYP)(int))glGetProcAddress(\"wglSwapIntervalEXT\");\n\n\tif (shader_support)\n\t{\n\t\tif (glprogram) {\n\t\t\tif (glIsProgram(glprogram))\n\t\t\t{\n\t\t\t\tglDeleteProgram(glprogram);\n\t\t\t\tglErrorCheck();\n\t\t\t}\n\t\t}\n\t\tglprogram = glCreateProgram();\n\t\tglErrorCheck();\n\t}\n\n\t//create surface texture\n\tresize(w, h);\n}\n\nvoid OpenGL::setVSync(bool sync)\n{\n\tconst int interval = sync ? 1 : 0;\n\tif (glXGetCurrentDisplay && glXGetCurrentDrawable && glXSwapIntervalEXT)\n\t{\n\t\tvoid *dpy = glXGetCurrentDisplay();\n\t\tglErrorCheck();\n\t\tUint32 drawable = glXGetCurrentDrawable();\n\t\tglErrorCheck();\n\n\t\tif (drawable) {\n\t\t\tglXSwapIntervalEXT(dpy, drawable, interval);\n\t\t\tglErrorCheck();\n\t\t\t// Log(LOG_INFO) << \"Made an attempt to set vsync via GLX.\";\n\t\t}\n\t} else if (wglSwapIntervalEXT)\n\t{\n\t\twglSwapIntervalEXT(interval);\n\t\tglErrorCheck();\n\t\t// Log(LOG_INFO) << \"Made an attempt to set vsync via WGL.\";\n\t}\n}\n\nvoid OpenGL::term()\n{\n\tif (gltexture) {\n\t\tglDeleteTextures(1, &gltexture);\n\t\tglErrorCheck();\n\t\tgltexture = 0;\n\t}\n\n\tif (glprogram) {\n\t\tglDeleteProgram(glprogram);\n\t\tglprogram = 0;\n\t}\n\n\tif (buffer) {\n\t\tbuffer = 0;\n\t\tiwidth = 0;\n\t\tiheight = 0;\n\t}\n}\n\n  OpenGL::OpenGL() : gltexture(0), glprogram(0), linear(false), shader_support(false),\n                     buffer(NULL), iwidth(0), iheight(0),\n                     iformat(GL_UNSIGNED_INT_8_8_8_8_REV), // this didn't seem to be set anywhere before...\n                     ibpp(32)                              // ...nor this\n  { }\n\n  OpenGL::~OpenGL()\n\t{\n\t\tterm();\n\t}\n\n}\n\n#endif\n"
  },
  {
    "path": "src/Engine/OpenGL.h",
    "content": "// This file was copied from the bsnes project.\n\n// This is the license info, from ruby.hpp:\n\n/*\n  ruby\n  version: 0.08 (2011-11-25)\n  license: public domain\n */\n#pragma once\n\n#ifndef __NO_OPENGL\n\n#ifdef __APPLE__\n#define GL_SILENCE_DEPRECATION\n#endif\n\n#include <SDL_opengl.h>\n#include <string>\n\n#include \"Surface.h\"\n\nnamespace OpenXcom\n{\n\nclass Surface;\n\nstd::string strGLError(GLenum glErr);\n\n#define glErrorCheck() {\\\n\tstatic bool reported = false;\\\n\tGLenum glErr;\\\n\tif (OpenGL::checkErrors && !reported && (glErr = glGetError()) != GL_NO_ERROR)\\\n\t{\\\n\t\treported = true;\\\n\t\t\\\n\t\tdo \\\n\t\t{ \\\n\t\t\tLog(LOG_WARNING) << __FILE__ << \":\" << __LINE__ << \": glGetError() complaint: \" << strGLError(glErr);\\\n\t\t} while (((glErr = glGetError()) != GL_NO_ERROR));\\\n\t}\\\n}\n\n\nclass OpenGL {\npublic:\n  GLuint gltexture;\n  GLuint glprogram;\n  bool linear;\n  bool shader_support;\n\n  uint32_t *buffer;\n  Surface::UniqueBufferPtr buffer_surface;\n  Surface::UniqueSurfacePtr surface;\n  unsigned iwidth, iheight, iformat, ibpp;\n\n  static bool checkErrors;\n\n  /// call to resize internal buffer; internal use\n  void resize(unsigned width, unsigned height);\n  /// actually returns pointer to data buffer where one is to write the image\n  bool lock(uint32_t *&data, unsigned &pitch);\n  /// make all the pixels go away\n  void clear();\n  /// make the buffer show up on screen\n  void refresh(bool smooth, unsigned inwidth, unsigned inheight, unsigned outwidth, unsigned outheight, int topBlackBand, int bottomBlackBand, int leftBlackBand, int rightBlackBand);\n  /// set a shader! but what kind?\n  bool set_shader(const char *source);\n  /// same but for fragment shader?\n  void set_fragment_shader(const char *source);\n  /// and vertex?\n  void set_vertex_shader(const char *source);\n  /// init(), because we're too cool to initialize everything in the constructor\n  void init(int width, int height);\n  /// more like exit, because destructors are for uncool people\n  void term();\n  /// Try to set VSync!\n  void setVSync(bool sync);\n  /// constructor -- like we said, we're too cool to actually construct things\n  OpenGL();\n  ~OpenGL();\n};\n\n}\n\n#else\n\nnamespace OpenXcom { class OpenGL {}; }\n\n#endif\n"
  },
  {
    "path": "src/Engine/OptionInfo.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <algorithm>\n#include \"OptionInfo.h\"\n#include \"Exception.h\"\n#include <sstream>\n\nnamespace OpenXcom\n{\n\n/**\n * Creates info for a boolean option.\n * @param owner Owner ID.\n * @param id String ID used in serializing.\n * @param option Pointer to the option.\n * @param def Default option value.\n * @param desc Language ID for the option description (if any).\n * @param cat Language ID for the option category (if any).\n */\nOptionInfo::OptionInfo(OptionOwner owner, const std::string &id, bool *option, bool def, const std::string &desc, const std::string &cat) :\n\t_id(id), _desc(desc), _cat(cat), _type(OPTION_BOOL), _owner(owner)\n{\n\t_ref.b = option;\n\t_def.b = def;\n}\n\n/**\n * Creates info for an integer option.\n * @param owner Owner ID.\n * @param id String ID used in serializing.\n * @param option Pointer to the option.\n * @param def Default option value.\n * @param desc Language ID for the option description (if any).\n * @param cat Language ID for the option category (if any).\n */\nOptionInfo::OptionInfo(OptionOwner owner, const std::string &id, int *option, int def, const std::string &desc, const std::string &cat) :\n\t_id(id), _desc(desc), _cat(cat), _type(OPTION_INT), _owner(owner)\n{\n\t_ref.i = option;\n\t_def.i = def;\n}\n\n/**\n * Creates info for a keyboard shortcut option.\n * @param owner Owner ID.\n * @param id String ID used in serializing.\n * @param option Pointer to the option.\n * @param def Default option value.\n * @param desc Language ID for the option description (if any).\n * @param cat Language ID for the option category (if any).\n */\nOptionInfo::OptionInfo(OptionOwner owner, const std::string &id, SDLKey *option, SDLKey def, const std::string &desc, const std::string &cat) :\n\t_id(id), _desc(desc), _cat(cat), _type(OPTION_KEY), _owner(owner)\n{\n\t_ref.k = option;\n\t_def.k = def;\n}\n\n/**\n * Creates info for a string option.\n * @param owner Owner ID.\n * @param id String ID used in serializing.\n * @param option Pointer to the option.\n * @param def Default option value.\n * @param desc Language ID for the option description (if any).\n * @param cat Language ID for the option category (if any).\n */\nOptionInfo::OptionInfo(OptionOwner owner, const std::string &id, std::string *option, const char *def, const std::string &desc, const std::string &cat) :\n\t_id(id), _desc(desc), _cat(cat), _type(OPTION_STRING), _owner(owner)\n{\n\t_ref.s = option;\n\t_def.s = def;\n}\n\n/**\n * Loads an option value from the corresponding YAML.\n * @param node Options YAML node.\n */\nvoid OptionInfo::load(const YAML::YamlNodeReader& reader) const\n{\n\tswitch (_type)\n\t{\n\tcase OPTION_BOOL:\n\t\t*(_ref.b) = reader[ryml::to_csubstr(_id)].readVal(_def.b);\n\t\tbreak;\n\tcase OPTION_INT:\n\t\t*(_ref.i) = reader[ryml::to_csubstr(_id)].readVal(_def.i);\n\t\tbreak;\n\tcase OPTION_KEY:\n\t\t*(_ref.k) = (SDLKey)reader[ryml::to_csubstr(_id)].readVal((int)_def.k);\n\t\tif (*(_ref.k) == SDLK_LSHIFT || *(_ref.k) == SDLK_LALT || *(_ref.k) == SDLK_LCTRL ||\n\t\t\t*(_ref.k) == SDLK_RSHIFT || *(_ref.k) == SDLK_RALT || *(_ref.k) == SDLK_RCTRL)\n\t\t{\n\t\t\t*(_ref.k) = SDLK_UNKNOWN;\n\t\t}\n\t\tbreak;\n\tcase OPTION_STRING:\n\t\t*(_ref.s) = reader[ryml::to_csubstr(_id)].readVal<std::string>(_def.s);\n\t\tbreak;\n\t}\n}\n\n/**\n * Loads an option value from the corresponding map\n * (eg. for command-line options).\n * @param map Options map.\n */\nvoid OptionInfo::load(const std::map<std::string, std::string> &map, bool makeLowercase) const\n{\n\tstd::string id = _id;\n\tif (makeLowercase)\n\t{\n\t\tstd::transform(id.begin(), id.end(), id.begin(), ::tolower);\n\t}\n\tauto it = map.find(id);\n\tif (it != map.end())\n\t{\n\t\tstd::string value = it->second;\n\t\tstd::stringstream ss;\n\t\tbool b;\n\t\tint i;\n\t\tswitch (_type)\n\t\t{\n\t\tcase OPTION_BOOL:\n\t\t\tss << std::boolalpha << value;\n\t\t\tss >> std::boolalpha >> b;\n\t\t\t*(_ref.b) = b;\n\t\t\tbreak;\n\t\tcase OPTION_INT:\n\t\t\tss << std::dec << value;\n\t\t\tss >> std::dec >> i;\n\t\t\t*(_ref.i) = i;\n\t\t\tbreak;\n\t\tcase OPTION_KEY:\n\t\t\tss << std::dec << value;\n\t\t\tss >> std::dec >> i;\n\t\t\t*(_ref.k) = (SDLKey)i;\n\t\t\tbreak;\n\t\tcase OPTION_STRING:\n\t\t\t*(_ref.s) = value;\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n/**\n * Saves an option value to the corresponding YAML.\n * @param node Options YAML node.\n */\nvoid OptionInfo::save(YAML::YamlNodeWriter writer) const\n{\n\tswitch (_type)\n\t{\n\tcase OPTION_BOOL:\n\t\twriter.write(writer.saveString(_id), *(_ref.b));\n\t\tbreak;\n\tcase OPTION_INT:\n\t\twriter.write(writer.saveString(_id), *(_ref.i));\n\t\tbreak;\n\tcase OPTION_KEY:\n\t\twriter.write(writer.saveString(_id), (int)*(_ref.k));\n\t\tbreak;\n\tcase OPTION_STRING:\n\t\twriter.write(writer.saveString(_id), *(_ref.s));\n\t\tbreak;\n\t}\n}\n\n/**\n * Resets an option back to its default value.\n */\nvoid OptionInfo::reset() const\n{\n\tswitch (_type)\n\t{\n\tcase OPTION_BOOL:\n\t\t*(_ref.b) = _def.b;\n\t\tbreak;\n\tcase OPTION_INT:\n\t\t*(_ref.i) = _def.i;\n\t\tbreak;\n\tcase OPTION_KEY:\n\t\t*(_ref.k) = _def.k;\n\t\tbreak;\n\tcase OPTION_STRING:\n\t\t*(_ref.s) = _def.s;\n\t\tbreak;\n\t}\n}\n\n/**\n * Returns the pointer to the boolean option,\n * or throws an exception if it's not a boolean.\n * @return Pointer to the option.\n */\nbool *OptionInfo::asBool() const\n{\n\tif (_type != OPTION_BOOL)\n\t{\n\t\tthrow Exception(_id + \" is not a boolean!\");\n\t}\n\treturn _ref.b;\n}\n\n/**\n * Returns the pointer to the integer option,\n * or throws an exception if it's not a integer.\n * @return Pointer to the option.\n */\nint *OptionInfo::asInt() const\n{\n\tif (_type != OPTION_INT)\n\t{\n\t\tthrow Exception(_id + \" is not an integer!\");\n\t}\n\treturn _ref.i;\n}\n\n/**\n * Returns the pointer to the key option,\n * or throws an exception if it's not a key.\n * @return Pointer to the option.\n */\nSDLKey *OptionInfo::asKey() const\n{\n\tif (_type != OPTION_KEY)\n\t{\n\t\tthrow Exception(_id + \" is not a key!\");\n\t}\n\treturn _ref.k;\n}\n\n/**\n * Returns the pointer to the string option,\n * or throws an exception if it's not a string.\n * @return Pointer to the option.\n */\nstd::string *OptionInfo::asString() const\n{\n\tif (_type != OPTION_STRING)\n\t{\n\t\tthrow Exception(_id + \" is not a string!\");\n\t}\n\treturn _ref.s;\n}\n\n}\n"
  },
  {
    "path": "src/Engine/OptionInfo.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/Yaml.h\"\n#include <string>\n#include <map>\n#include <SDL.h>\n\nnamespace OpenXcom\n{\n\nenum OptionType { OPTION_BOOL, OPTION_INT, OPTION_STRING, OPTION_KEY };\nenum OptionOwner { OPTION_OXC, OPTION_OXCE, OPTION_OTHER, OPTION_OWNER_MAX };\n\n/**\n * Helper class that ties metadata to particular options to help in serializing\n * and stuff. The option variable must already exist, this info just points to it.\n * Does some special shenanigans to be able to be tied to different variable types.\n */\nclass OptionInfo\n{\nprivate:\n\tstd::string _id, _desc, _cat;\n\tOptionType _type;\n\tOptionOwner _owner;\n\tunion { bool *b; int *i; std::string *s; SDLKey *k; } _ref;\n\tunion { bool b; int i; const char *s; SDLKey k; } _def; // can't put strings in unions\npublic:\n\t/// Creates a bool option.\n\tOptionInfo(OptionOwner owner, const std::string &id, bool *option, bool def, const std::string &desc = \"\", const std::string &cat = \"\");\n\t/// Creates a int option.\n\tOptionInfo(OptionOwner owner, const std::string &id, int *option, int def, const std::string &desc = \"\", const std::string &cat = \"\");\n\t/// Creates a key option.\n\tOptionInfo(OptionOwner owner, const std::string &id, SDLKey *option, SDLKey def, const std::string &desc = \"\", const std::string &cat = \"\");\n\t/// Creates a string option.\n\tOptionInfo(OptionOwner owner, const std::string &id, std::string *option, const char *def, const std::string &desc = \"\", const std::string &cat = \"\");\n\t/// Gets a bool option pointer.\n\tbool *asBool() const;\n\t/// Gets an int option pointer.\n\tint *asInt() const;\n\t/// Gets a string option pointer.\n\tstd::string *asString() const;\n\t/// Gets a key option pointer.\n\tSDLKey *asKey() const;\n\t/// Loads the option from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader) const;\n\t/// Loads the option from a map.\n\tvoid load(const std::map<std::string, std::string> &map, bool makeLowercase) const;\n\t/// Saves the option to YAML.\n\tvoid save(YAML::YamlNodeWriter writer) const;\n\t/// Resets the option to default.\n\tvoid reset() const;\n\t/// Gets the option ID.\n\tconst std::string& id() const { return _id; }\n\t/// Gets the option type.\n\tOptionType type() const { return _type; }\n\t/// Gets the option owner.\n\tOptionOwner owner() const { return _owner; }\n\t/// Gets the option description.\n\tconst std::string& description() const { return _desc; }\n\t/// Gets the option category.\n\tconst std::string& category() const { return _cat; }\n};\n\n}\n"
  },
  {
    "path": "src/Engine/Options.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"Options.h\"\n#include \"../version.h\"\n#include \"../md5.h\"\n#include <SDL.h>\n#include <SDL_keysym.h>\n#include <SDL_mixer.h>\n#include <map>\n#include <sstream>\n#include <iostream>\n#include <algorithm>\n#include \"../Engine/Yaml.h\"\n#include \"Exception.h\"\n#include \"Logger.h\"\n#include \"CrossPlatform.h\"\n#include \"../Menu/ModConfirmExtendedState.h\"\n#include \"FileMap.h\"\n#include \"Screen.h\"\n\nnamespace OpenXcom\n{\n\nnamespace Options\n{\n#define OPT\n#include \"Options.inc.h\"\n#undef OPT\n\nstd::string _dataFolder;\nstd::vector<std::string> _dataList;\nstd::string _userFolder;\nstd::string _configFolder;\nstd::vector<std::string> _userList;\nstd::map<std::string, std::string> _commandLine;\nstd::vector<OptionInfo> _info;\nstd::map<std::string, ModInfo> _modInfos;\nstd::string _masterMod;\nint _passwordCheck = -1;\nbool _loadLastSave = false;\nstd::string _loadThisSave = \"\";\nbool _loadLastSaveExpended = false;\n\n/**\n * Sets up the options by creating their OptionInfo metadata.\n */\nvoid create()\n{\n\tif (!_info.empty()) { _info.clear(); }\n\n\t////////////////////////////////////////////////////////////\n\t//\t\t\t\t\tOXC - OpenXcom\n\t////////////////////////////////////////////////////////////\n\n\tcreateOptionsOXC();\n\tcreateAdvancedOptionsOXC();\n\tcreateControlsOXC();\n\n\t////////////////////////////////////////////////////////////\n\t//\t\t\t\t\tOXCE - OpenXcom Extended\n\t////////////////////////////////////////////////////////////\n\n\tcreateOptionsOXCE();\n\tcreateAdvancedOptionsOXCE();\n\tcreateControlsOXCE();\n\n\t////////////////////////////////////////////////////////////\n\t//\t\t\t\t\tOTHER - your fork name here\n\t////////////////////////////////////////////////////////////\n\n\tcreateOptionsOTHER();\n\tcreateAdvancedOptionsOTHER();\n\tcreateControlsOTHER();\n}\n\nvoid createOptionsOXC()\n{\n#ifdef DINGOO\n\t_info.push_back(OptionInfo(OPTION_OXC, \"displayWidth\", &displayWidth, Screen::ORIGINAL_WIDTH));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"displayHeight\", &displayHeight, Screen::ORIGINAL_HEIGHT));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"fullscreen\", &fullscreen, true));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"asyncBlit\", &asyncBlit, false));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyboardMode\", (int*)&keyboardMode, KEYBOARD_OFF));\n#else\n\t_info.push_back(OptionInfo(OPTION_OXC, \"displayWidth\", &displayWidth, Screen::ORIGINAL_WIDTH*2));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"displayHeight\", &displayHeight, Screen::ORIGINAL_HEIGHT*2));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"fullscreen\", &fullscreen, false));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"asyncBlit\", &asyncBlit, true));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyboardMode\", (int*)&keyboardMode, KEYBOARD_ON));\n#endif\n\n#ifdef __MOBILE__\n\t_info.push_back(OptionInfo(OPTION_OXC, \"maxFrameSkip\", &maxFrameSkip, 0, \"STR_FRAMESKIP\", \"STR_GENERAL\"));\n#else\n\t_info.push_back(OptionInfo(OPTION_OXC, \"maxFrameSkip\", &maxFrameSkip, 0));\n#endif\n\t_info.push_back(OptionInfo(OPTION_OXC, \"traceAI\", &traceAI, false));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"verboseLogging\", &verboseLogging, false));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"StereoSound\", &StereoSound, true));\n\t//_info.push_back(OptionInfo(OPTION_OXC, \"baseXResolution\", &baseXResolution, Screen::ORIGINAL_WIDTH));\n\t//_info.push_back(OptionInfo(OPTION_OXC, \"baseYResolution\", &baseYResolution, Screen::ORIGINAL_HEIGHT));\n\t//_info.push_back(OptionInfo(OPTION_OXC, \"baseXGeoscape\", &baseXGeoscape, Screen::ORIGINAL_WIDTH));\n\t//_info.push_back(OptionInfo(OPTION_OXC, \"baseYGeoscape\", &baseYGeoscape, Screen::ORIGINAL_HEIGHT));\n\t//_info.push_back(OptionInfo(OPTION_OXC, \"baseXBattlescape\", &baseXBattlescape, Screen::ORIGINAL_WIDTH));\n\t//_info.push_back(OptionInfo(OPTION_OXC, \"baseYBattlescape\", &baseYBattlescape, Screen::ORIGINAL_HEIGHT));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"geoscapeScale\", &geoscapeScale, 0));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"battlescapeScale\", &battlescapeScale, 0));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"useScaleFilter\", &useScaleFilter, false));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"useHQXFilter\", &useHQXFilter, false));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"useXBRZFilter\", &useXBRZFilter, false));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"useOpenGL\", &useOpenGL, false));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"checkOpenGLErrors\", &checkOpenGLErrors, false));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"useOpenGLShader\", &useOpenGLShader, \"Shaders/Raw.OpenGL.shader\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"useOpenGLSmoothing\", &useOpenGLSmoothing, true));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"debug\", &debug, false));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"debugUi\", &debugUi, false));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"soundVolume\", &soundVolume, 2*(MIX_MAX_VOLUME/3)));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"musicVolume\", &musicVolume, 2*(MIX_MAX_VOLUME/3)));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"uiVolume\", &uiVolume, MIX_MAX_VOLUME/3));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"language\", &language, \"\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"battleScrollSpeed\", &battleScrollSpeed, 8));\n#ifdef __MOBILE__\n\t_info.push_back(OptionInfo(OPTION_OXC, \"battleEdgeScroll\", (int*)&battleEdgeScroll, SCROLL_NONE));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"battleDragScrollButton\", &battleDragScrollButton, SDL_BUTTON_LEFT));\n#else\n\t_info.push_back(OptionInfo(OPTION_OXC, \"battleEdgeScroll\", (int*)&battleEdgeScroll, SCROLL_AUTO));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"battleDragScrollButton\", &battleDragScrollButton, 0)); // different default in OXCE\n#endif\n\t_info.push_back(OptionInfo(OPTION_OXC, \"dragScrollTimeTolerance\", &dragScrollTimeTolerance, 300)); // miliSecond\n\t_info.push_back(OptionInfo(OPTION_OXC, \"dragScrollPixelTolerance\", &dragScrollPixelTolerance, 10)); // count of pixels\n\t_info.push_back(OptionInfo(OPTION_OXC, \"battleFireSpeed\", &battleFireSpeed, 6));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"battleXcomSpeed\", &battleXcomSpeed, 30));\n\tbattleXcomSpeedOrig = -1;\n\tbattleAlienSpeedOrig = -1;\n\t_info.push_back(OptionInfo(OPTION_OXC, \"battleAlienSpeed\", &battleAlienSpeed, 30));\n#ifdef __MOBILE__\n\t_info.push_back(OptionInfo(OPTION_OXC, \"battleNewPreviewPath\", (int*)&battleNewPreviewPath, PATH_FULL)); // for android, set full preview by default\n#else\n\t_info.push_back(OptionInfo(OPTION_OXC, \"battleNewPreviewPath\", (int*)&battleNewPreviewPath, PATH_NONE)); // requires double-click to confirm moves\n#endif\n\t_info.push_back(OptionInfo(OPTION_OXC, \"fpsCounter\", &fpsCounter, false));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"globeDetail\", &globeDetail, true));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"globeRadarLines\", &globeRadarLines, true));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"globeFlightPaths\", &globeFlightPaths, true));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"globeAllRadarsOnBaseBuild\", &globeAllRadarsOnBaseBuild, true));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"audioSampleRate\", &audioSampleRate, 22050));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"audioBitDepth\", &audioBitDepth, 16));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"audioChunkSize\", &audioChunkSize, 1024));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"pauseMode\", &pauseMode, 0));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"battleNotifyDeath\", &battleNotifyDeath, false));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"showFundsOnGeoscape\", &showFundsOnGeoscape, false));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"allowResize\", &allowResize, false));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"windowedModePositionX\", &windowedModePositionX, 0));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"windowedModePositionY\", &windowedModePositionY, 0));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"borderless\", &borderless, false));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"captureMouse\", (bool*)&captureMouse, false));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"battleTooltips\", &battleTooltips, true));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keepAspectRatio\", &keepAspectRatio, true));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"nonSquarePixelRatio\", &nonSquarePixelRatio, false));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"cursorInBlackBandsInFullscreen\", &cursorInBlackBandsInFullscreen, false));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"cursorInBlackBandsInWindow\", &cursorInBlackBandsInWindow, true));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"cursorInBlackBandsInBorderlessWindow\", &cursorInBlackBandsInBorderlessWindow, false));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"saveOrder\", (int*)&saveOrder, SORT_DATE_DESC));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"geoClockSpeed\", &geoClockSpeed, 80));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"dogfightSpeed\", &dogfightSpeed, 30));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"geoScrollSpeed\", &geoScrollSpeed, 20));\n#ifdef __MOBILE__\n\t_info.push_back(OptionInfo(OPTION_OXC, \"geoDragScrollButton\", &geoDragScrollButton, SDL_BUTTON_LEFT));\n#else\n\t_info.push_back(OptionInfo(OPTION_OXC, \"geoDragScrollButton\", &geoDragScrollButton, SDL_BUTTON_MIDDLE));\n#endif\n\t_info.push_back(OptionInfo(OPTION_OXC, \"preferredMusic\", (int*)&preferredMusic, MUSIC_AUTO));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"preferredSound\", (int*)&preferredSound, SOUND_AUTO));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"preferredVideo\", (int*)&preferredVideo, VIDEO_FMV));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"wordwrap\", (int*)&wordwrap, WRAP_AUTO));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"musicAlwaysLoop\", &musicAlwaysLoop, false));\n#ifdef __MOBILE\n\t_info.push_back(OptionInfo(OPTION_OXC, \"touchEnabled\", &touchEnabled, true));\n#else\n\t_info.push_back(OptionInfo(OPTION_OXC, \"touchEnabled\", &touchEnabled, false));\n#endif\n\t_info.push_back(OptionInfo(OPTION_OXC, \"rootWindowedMode\", &rootWindowedMode, false));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"backgroundMute\", &backgroundMute, false));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"soldierDiaries\", &soldierDiaries, true));\n}\n\nvoid createAdvancedOptionsOXC()\n{\n\t// advanced options\n\t_info.push_back(OptionInfo(OPTION_OXC, \"playIntro\", &playIntro, true, \"STR_PLAYINTRO\", \"STR_GENERAL\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"autosave\", &autosave, true, \"STR_AUTOSAVE\", \"STR_GENERAL\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"autosaveFrequency\", &autosaveFrequency, 5, \"STR_AUTOSAVE_FREQUENCY\", \"STR_GENERAL\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"newSeedOnLoad\", &newSeedOnLoad, false, \"STR_NEWSEEDONLOAD\", \"STR_GENERAL\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"lazyLoadResources\", &lazyLoadResources, true, \"STR_LAZY_LOADING\", \"STR_GENERAL\")); // exposed in OXCE\n\t_info.push_back(OptionInfo(OPTION_OXC, \"mousewheelSpeed\", &mousewheelSpeed, 3, \"STR_MOUSEWHEEL_SPEED\", \"STR_GENERAL\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"changeValueByMouseWheel\", &changeValueByMouseWheel, 0, \"STR_CHANGEVALUEBYMOUSEWHEEL\", \"STR_GENERAL\"));\n\n// this should probably be any small screen touch-device, i don't know the defines for all of them so i'll cover android and IOS as i imagine they're more common\n#ifdef __MOBILE__\n\t_info.push_back(OptionInfo(OPTION_OXC, \"maximizeInfoScreens\", &maximizeInfoScreens, true, \"STR_MAXIMIZE_INFO_SCREENS\", \"STR_GENERAL\"));\n#elif __APPLE__\n\t// todo: ask grussel how badly i messed this up.\n\t#include \"TargetConditionals.h\"\n\t#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE\n\t\t_info.push_back(OptionInfo(OPTION_OXC, \"maximizeInfoScreens\", &maximizeInfoScreens, true, \"STR_MAXIMIZE_INFO_SCREENS\", \"STR_GENERAL\"));\n\t#else\n\t\t_info.push_back(OptionInfo(OPTION_OXC, \"maximizeInfoScreens\", &maximizeInfoScreens, false, \"STR_MAXIMIZE_INFO_SCREENS\", \"STR_GENERAL\"));\n\t#endif\n#else\n\t_info.push_back(OptionInfo(OPTION_OXC, \"maximizeInfoScreens\", &maximizeInfoScreens, false, \"STR_MAXIMIZE_INFO_SCREENS\", \"STR_GENERAL\"));\n#endif\n\n#ifdef __MORPHOS__\n\t_info.push_back(OptionInfo(OPTION_OXC, \"FPS\", &FPS, 15, \"STR_FPS_LIMIT\", \"STR_GENERAL\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"FPSInactive\", &FPSInactive, 15, \"STR_FPS_INACTIVE_LIMIT\", \"STR_GENERAL\"));\n#else\n\t_info.push_back(OptionInfo(OPTION_OXC, \"FPS\", &FPS, 60, \"STR_FPS_LIMIT\", \"STR_GENERAL\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"FPSInactive\", &FPSInactive, 30, \"STR_FPS_INACTIVE_LIMIT\", \"STR_GENERAL\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"vSyncForOpenGL\", &vSyncForOpenGL, true, \"STR_VSYNC_FOR_OPENGL\", \"STR_GENERAL\")); // exposed in OXCE\n#endif\n\n\t_info.push_back(OptionInfo(OPTION_OXC, \"geoDragScrollInvert\", &geoDragScrollInvert, false, \"STR_DRAGSCROLLINVERT\", \"STR_GEOSCAPE\")); // true drags away from the cursor, false drags towards (like a grab)\n\t_info.push_back(OptionInfo(OPTION_OXC, \"aggressiveRetaliation\", &aggressiveRetaliation, false, \"STR_AGGRESSIVERETALIATION\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"customInitialBase\", &customInitialBase, false, \"STR_CUSTOMINITIALBASE\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"allowBuildingQueue\", &allowBuildingQueue, false, \"STR_ALLOWBUILDINGQUEUE\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"craftLaunchAlways\", &craftLaunchAlways, false, \"STR_CRAFTLAUNCHALWAYS\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"storageLimitsEnforced\", &storageLimitsEnforced, false, \"STR_STORAGELIMITSENFORCED\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"canSellLiveAliens\", &canSellLiveAliens, false, \"STR_CANSELLLIVEALIENS\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"anytimePsiTraining\", &anytimePsiTraining, false, \"STR_ANYTIMEPSITRAINING\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"globeSeasons\", &globeSeasons, false, \"STR_GLOBESEASONS\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"globeSurfaceCache\", &globeSurfaceCache, true)); //hidden for now\n\t_info.push_back(OptionInfo(OPTION_OXC, \"psiStrengthEval\", &psiStrengthEval, false, \"STR_PSISTRENGTHEVAL\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"canTransferCraftsWhileAirborne\", &canTransferCraftsWhileAirborne, false, \"STR_CANTRANSFERCRAFTSWHILEAIRBORNE\", \"STR_GEOSCAPE\")); // When the craft can reach the destination base with its fuel\n\t_info.push_back(OptionInfo(OPTION_OXC, \"retainCorpses\", &retainCorpses, false, \"STR_RETAINCORPSES\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"fieldPromotions\", &fieldPromotions, false, \"STR_FIELDPROMOTIONS\", \"STR_GEOSCAPE\"));\n\t//_info.push_back(OptionInfo(OPTION_OXC, \"meetingPoint\", &meetingPoint, false, \"STR_MEETINGPOINT\", \"STR_GEOSCAPE\")); // intentionally disabled in OXCE\n\n\t_info.push_back(OptionInfo(OPTION_OXC, \"battleDragScrollInvert\", &battleDragScrollInvert, false, \"STR_DRAGSCROLLINVERT\", \"STR_BATTLESCAPE\")); // true drags away from the cursor, false drags towards (like a grab)\n\t_info.push_back(OptionInfo(OPTION_OXC, \"sneakyAI\", &sneakyAI, false, \"STR_SNEAKYAI\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"battleUFOExtenderAccuracy\", &battleUFOExtenderAccuracy, false, \"STR_BATTLEUFOEXTENDERACCURACY\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"showMoreStatsInInventoryView\", &showMoreStatsInInventoryView, false, \"STR_SHOWMORESTATSININVENTORYVIEW\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"battleHairBleach\", &battleHairBleach, true, \"STR_BATTLEHAIRBLEACH\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"battleInstantGrenade\", &battleInstantGrenade, false, \"STR_BATTLEINSTANTGRENADE\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"includePrimeStateInSavedLayout\", &includePrimeStateInSavedLayout, false, \"STR_INCLUDE_PRIMESTATE_IN_SAVED_LAYOUT\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"battleExplosionHeight\", &battleExplosionHeight, 0, \"STR_BATTLEEXPLOSIONHEIGHT\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"battleAutoEnd\", &battleAutoEnd, false, \"STR_BATTLEAUTOEND\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"battleSmoothCamera\", &battleSmoothCamera, false, \"STR_BATTLESMOOTHCAMERA\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"disableAutoEquip\", &disableAutoEquip, false, \"STR_DISABLEAUTOEQUIP\", \"STR_BATTLESCAPE\"));\n#ifdef __MOBILE__\n\t_info.push_back(OptionInfo(OPTION_OXC, \"battleConfirmFireMode\", &battleConfirmFireMode, true, \"STR_BATTLECONFIRMFIREMODE\", \"STR_BATTLESCAPE\"));\n#else\n\t_info.push_back(OptionInfo(OPTION_OXC, \"battleConfirmFireMode\", &battleConfirmFireMode, false, \"STR_BATTLECONFIRMFIREMODE\", \"STR_BATTLESCAPE\"));\n#endif\n\t_info.push_back(OptionInfo(OPTION_OXC, \"weaponSelfDestruction\", &weaponSelfDestruction, false, \"STR_WEAPONSELFDESTRUCTION\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"allowPsionicCapture\", &allowPsionicCapture, false, \"STR_ALLOWPSIONICCAPTURE\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"allowPsiStrengthImprovement\", &allowPsiStrengthImprovement, false, \"STR_ALLOWPSISTRENGTHIMPROVEMENT\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"strafe\", &strafe, false, \"STR_STRAFE\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"forceFire\", &forceFire, true, \"STR_FORCE_FIRE\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"skipNextTurnScreen\", &skipNextTurnScreen, false, \"STR_SKIPNEXTTURNSCREEN\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"noAlienPanicMessages\", &noAlienPanicMessages, false, \"STR_NOALIENPANICMESSAGES\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"alienBleeding\", &alienBleeding, false, \"STR_ALIENBLEEDING\", \"STR_BATTLESCAPE\"));\n}\n\nvoid createControlsOXC()\n{\n\t// controls\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyOk\", &keyOk, SDLK_RETURN, \"STR_OK\", \"STR_GENERAL\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyCancel\", &keyCancel, SDLK_ESCAPE, \"STR_CANCEL\", \"STR_GENERAL\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyScreenshot\", &keyScreenshot, SDLK_F12, \"STR_SCREENSHOT\", \"STR_GENERAL\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyFps\", &keyFps, SDLK_F7, \"STR_FPS_COUNTER\", \"STR_GENERAL\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyQuickSave\", &keyQuickSave, SDLK_F5, \"STR_QUICK_SAVE\", \"STR_GENERAL\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyQuickLoad\", &keyQuickLoad, SDLK_F9, \"STR_QUICK_LOAD\", \"STR_GENERAL\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyGeoLeft\", &keyGeoLeft, SDLK_LEFT, \"STR_ROTATE_LEFT\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyGeoRight\", &keyGeoRight, SDLK_RIGHT, \"STR_ROTATE_RIGHT\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyGeoUp\", &keyGeoUp, SDLK_UP, \"STR_ROTATE_UP\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyGeoDown\", &keyGeoDown, SDLK_DOWN, \"STR_ROTATE_DOWN\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyGeoZoomIn\", &keyGeoZoomIn, SDLK_PLUS, \"STR_ZOOM_IN\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyGeoZoomOut\", &keyGeoZoomOut, SDLK_MINUS, \"STR_ZOOM_OUT\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyGeoSpeed1\", &keyGeoSpeed1, SDLK_1, \"STR_5_SECONDS\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyGeoSpeed2\", &keyGeoSpeed2, SDLK_2, \"STR_1_MINUTE\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyGeoSpeed3\", &keyGeoSpeed3, SDLK_3, \"STR_5_MINUTES\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyGeoSpeed4\", &keyGeoSpeed4, SDLK_4, \"STR_30_MINUTES\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyGeoSpeed5\", &keyGeoSpeed5, SDLK_5, \"STR_1_HOUR\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyGeoSpeed6\", &keyGeoSpeed6, SDLK_6, \"STR_1_DAY\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyGeoIntercept\", &keyGeoIntercept, SDLK_i, \"STR_INTERCEPT\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyGeoBases\", &keyGeoBases, SDLK_b, \"STR_BASES\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyGeoGraphs\", &keyGeoGraphs, SDLK_g, \"STR_GRAPHS\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyGeoUfopedia\", &keyGeoUfopedia, SDLK_u, \"STR_UFOPAEDIA_UC\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyGeoOptions\", &keyGeoOptions, SDLK_ESCAPE, \"STR_OPTIONS_UC\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyGeoFunding\", &keyGeoFunding, SDLK_f, \"STR_FUNDING_UC\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyGeoToggleDetail\", &keyGeoToggleDetail, SDLK_TAB, \"STR_TOGGLE_COUNTRY_DETAIL\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyGeoToggleRadar\", &keyGeoToggleRadar, SDLK_r, \"STR_TOGGLE_RADAR_RANGES\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBaseSelect1\", &keyBaseSelect1, SDLK_1, \"STR_SELECT_BASE_1\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBaseSelect2\", &keyBaseSelect2, SDLK_2, \"STR_SELECT_BASE_2\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBaseSelect3\", &keyBaseSelect3, SDLK_3, \"STR_SELECT_BASE_3\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBaseSelect4\", &keyBaseSelect4, SDLK_4, \"STR_SELECT_BASE_4\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBaseSelect5\", &keyBaseSelect5, SDLK_5, \"STR_SELECT_BASE_5\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBaseSelect6\", &keyBaseSelect6, SDLK_6, \"STR_SELECT_BASE_6\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBaseSelect7\", &keyBaseSelect7, SDLK_7, \"STR_SELECT_BASE_7\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBaseSelect8\", &keyBaseSelect8, SDLK_8, \"STR_SELECT_BASE_8\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBattleLeft\", &keyBattleLeft, SDLK_LEFT, \"STR_SCROLL_LEFT\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBattleRight\", &keyBattleRight, SDLK_RIGHT, \"STR_SCROLL_RIGHT\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBattleUp\", &keyBattleUp, SDLK_UP, \"STR_SCROLL_UP\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBattleDown\", &keyBattleDown, SDLK_DOWN, \"STR_SCROLL_DOWN\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBattleLevelUp\", &keyBattleLevelUp, SDLK_PAGEUP, \"STR_VIEW_LEVEL_ABOVE\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBattleLevelDown\", &keyBattleLevelDown, SDLK_PAGEDOWN, \"STR_VIEW_LEVEL_BELOW\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBattleCenterUnit\", &keyBattleCenterUnit, SDLK_HOME, \"STR_CENTER_SELECTED_UNIT\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBattlePrevUnit\", &keyBattlePrevUnit, SDLK_UNKNOWN, \"STR_PREVIOUS_UNIT\", \"STR_BATTLESCAPE\")); // different default in OXCE\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBattleNextUnit\", &keyBattleNextUnit, SDLK_TAB, \"STR_NEXT_UNIT\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBattleDeselectUnit\", &keyBattleDeselectUnit, SDLK_BACKSLASH, \"STR_DESELECT_UNIT\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBattleUseLeftHand\", &keyBattleUseLeftHand, SDLK_q, \"STR_USE_LEFT_HAND\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBattleUseRightHand\", &keyBattleUseRightHand, SDLK_e, \"STR_USE_RIGHT_HAND\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBattleInventory\", &keyBattleInventory, SDLK_i, \"STR_INVENTORY\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBattleMap\", &keyBattleMap, SDLK_m, \"STR_MINIMAP\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBattleOptions\", &keyBattleOptions, SDLK_ESCAPE, \"STR_OPTIONS\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBattleEndTurn\", &keyBattleEndTurn, SDLK_BACKSPACE, \"STR_END_TURN\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBattleAbort\", &keyBattleAbort, SDLK_a, \"STR_ABORT_MISSION\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBattleStats\", &keyBattleStats, SDLK_s, \"STR_UNIT_STATS\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBattleKneel\", &keyBattleKneel, SDLK_k, \"STR_KNEEL\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBattleReload\", &keyBattleReload, SDLK_r, \"STR_RELOAD\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBattlePersonalLighting\", &keyBattlePersonalLighting, SDLK_l, \"STR_TOGGLE_PERSONAL_LIGHTING\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBattleReserveNone\", &keyBattleReserveNone, SDLK_F1, \"STR_DONT_RESERVE_TIME_UNITS\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBattleReserveSnap\", &keyBattleReserveSnap, SDLK_F2, \"STR_RESERVE_TIME_UNITS_FOR_SNAP_SHOT\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBattleReserveAimed\", &keyBattleReserveAimed, SDLK_F3, \"STR_RESERVE_TIME_UNITS_FOR_AIMED_SHOT\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBattleReserveAuto\", &keyBattleReserveAuto, SDLK_F4, \"STR_RESERVE_TIME_UNITS_FOR_AUTO_SHOT\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBattleReserveKneel\", &keyBattleReserveKneel, SDLK_j, \"STR_RESERVE_TIME_UNITS_FOR_KNEEL\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBattleZeroTUs\", &keyBattleZeroTUs, SDLK_DELETE, \"STR_EXPEND_ALL_TIME_UNITS\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBattleCenterEnemy1\", &keyBattleCenterEnemy1, SDLK_1, \"STR_CENTER_ON_ENEMY_1\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBattleCenterEnemy2\", &keyBattleCenterEnemy2, SDLK_2, \"STR_CENTER_ON_ENEMY_2\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBattleCenterEnemy3\", &keyBattleCenterEnemy3, SDLK_3, \"STR_CENTER_ON_ENEMY_3\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBattleCenterEnemy4\", &keyBattleCenterEnemy4, SDLK_4, \"STR_CENTER_ON_ENEMY_4\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBattleCenterEnemy5\", &keyBattleCenterEnemy5, SDLK_5, \"STR_CENTER_ON_ENEMY_5\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBattleCenterEnemy6\", &keyBattleCenterEnemy6, SDLK_6, \"STR_CENTER_ON_ENEMY_6\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBattleCenterEnemy7\", &keyBattleCenterEnemy7, SDLK_7, \"STR_CENTER_ON_ENEMY_7\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBattleCenterEnemy8\", &keyBattleCenterEnemy8, SDLK_8, \"STR_CENTER_ON_ENEMY_8\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBattleCenterEnemy9\", &keyBattleCenterEnemy9, SDLK_9, \"STR_CENTER_ON_ENEMY_9\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBattleCenterEnemy10\", &keyBattleCenterEnemy10, SDLK_0, \"STR_CENTER_ON_ENEMY_10\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyBattleVoxelView\", &keyBattleVoxelView, SDLK_F10, \"STR_SAVE_VOXEL_VIEW\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyInvCreateTemplate\", &keyInvCreateTemplate, SDLK_c, \"STR_CREATE_INVENTORY_TEMPLATE\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyInvApplyTemplate\", &keyInvApplyTemplate, SDLK_v, \"STR_APPLY_INVENTORY_TEMPLATE\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyInvClear\", &keyInvClear, SDLK_x, \"STR_CLEAR_INVENTORY\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXC, \"keyInvAutoEquip\", &keyInvAutoEquip, SDLK_z, \"STR_AUTO_EQUIP\", \"STR_BATTLESCAPE\"));\n}\n\nvoid createOptionsOXCE()\n{\n\t// OXCE hidden\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceModValidationLevel\", &oxceModValidationLevel, (int)LOG_WARNING));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceRawScreenShots\", &oxceRawScreenShots, false));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceFirstPersonViewFisheyeProjection\", &oxceFirstPersonViewFisheyeProjection, false));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceThumbButtons\", &oxceThumbButtons, true));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceThrottleMouseMoveEvent\", &oxceThrottleMouseMoveEvent, 0));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceDisableThinkingProgressBar\", &oxceDisableThinkingProgressBar, false));\n\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceEmbeddedOnly\", &oxceEmbeddedOnly, true));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceListVFSContents\", &oxceListVFSContents, false));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceEnablePaletteFlickerFix\", &oxceEnablePaletteFlickerFix, false));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceRecommendedOptionsWereSet\", &oxceRecommendedOptionsWereSet, false));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"password\", &password, \"secret\"));\n\n\t// OXCE hidden but moddable\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceStartUpTextMode\", &oxceStartUpTextMode, 0, \"\", \"HIDDEN\"));\n\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceGeoscapeDebugLogMaxEntries\", &oxceGeoscapeDebugLogMaxEntries, 1000, \"\", \"HIDDEN\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceGeoSlowdownFactor\", &oxceGeoSlowdownFactor, 1, \"\", \"HIDDEN\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceGeoShowScoreInsteadOfFunds\", &oxceGeoShowScoreInsteadOfFunds, false)); // debug only\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceGeoEnableTrainingIndicator\", &oxceGeoEnableTrainingIndicator, false, \"\", \"HIDDEN\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceGeoSuppressRedundantHKAlert\", &oxceGeoSuppressRedundantHKAlert, true, \"\", \"HIDDEN\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceGeoSuppressLandingWithoutEquipment\", &oxceGeoSuppressLandingWithoutEquipment, false, \"\", \"HIDDEN\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceGeoGoToNearestBase\", &oxceGeoGoToNearestBase, false, \"\", \"HIDDEN\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceGeoSortCraftByDistanceToTarget\", &oxceGeoSortCraftByDistanceToTarget, false, \"\", \"HIDDEN\"));\n\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceBaseInfoDefenseScaleMultiplier\", &oxceBaseInfoDefenseScaleMultiplier, 100, \"\", \"HIDDEN\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceBaseSoldierTransformationShowOnlyEligible\", &oxceBaseSoldierTransformationShowOnlyEligible, false, \"\", \"HIDDEN\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceBaseFilterResearchable\", &oxceBaseFilterResearchable, false, \"\", \"HIDDEN\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceBaseResearchReorder\", &oxceBaseResearchReorder, false, \"\", \"HIDDEN\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceBaseManufactureFallbackButton\", &oxceBaseManufactureFallbackButton, false, \"\", \"HIDDEN\"));\n#ifdef __MOBILE__\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceBaseManufactureInfinityButton\", &oxceBaseManufactureInfinityButton, true, \"\", \"HIDDEN\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceBaseTouchButtons\", &oxceBaseTouchButtons, true, \"\", \"HIDDEN\"));\n#else\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceBaseManufactureInfinityButton\", &oxceBaseManufactureInfinityButton, false, \"\", \"HIDDEN\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceBaseTouchButtons\", &oxceBaseTouchButtons, false, \"\", \"HIDDEN\"));\n#endif\n\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceDisableAlienInventory\", &oxceDisableAlienInventory, false, \"\", \"HIDDEN\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceDisableHitLog\", &oxceDisableHitLog, false, \"\", \"HIDDEN\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceDisableInventoryTuCost\", &oxceDisableInventoryTuCost, false, \"\", \"HIDDEN\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceDisableProductionDependencyTree\", &oxceDisableProductionDependencyTree, false, \"\", \"HIDDEN\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceDisableStatsForNerds\", &oxceDisableStatsForNerds, false, \"\", \"HIDDEN\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceDisableTechTreeViewer\", &oxceDisableTechTreeViewer, false, \"\", \"HIDDEN\"));\n\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceTogglePersonalLightType\", &oxceTogglePersonalLightType, 1, \"\", \"HIDDEN\")); // per battle\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceToggleNightVisionType\", &oxceToggleNightVisionType, 1, \"\", \"HIDDEN\"));     // per battle\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceToggleBrightnessType\", &oxceToggleBrightnessType, 0, \"\", \"HIDDEN\"));       // not persisted\n\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceShowBurningAsWounded\", &oxceShowBurningAsWounded, false, \"\", \"HIDDEN\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceDisableInfoOnThrowCursor\", &oxceDisableInfoOnThrowCursor, false, \"\", \"HIDDEN\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceSwapDontReselectActions\", &oxceSwapDontReselectActions, false, \"\", \"HIDDEN\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceEnableUnitResponseSounds\", &oxceEnableUnitResponseSounds, true, \"\", \"HIDDEN\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceHiddenMovementBackgroundChangeFrequency\", &oxceHiddenMovementBackgroundChangeFrequency, 1, \"\", \"HIDDEN\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceInventoryShowUnitSlot\", &oxceInventoryShowUnitSlot, false, \"\", \"HIDDEN\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceReplaceNotesLink\", &oxceReplaceNotesLink, false, \"\", \"HIDDEN\"));\n\n#ifdef __MOBILE__\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceInventorySplitScrollButton\", &oxceInventorySplitScrollButton, true, \"\", \"HIDDEN\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceInventoryDropItemOverPaperdoll\", &oxceInventoryDropItemOverPaperdoll, true, \"\", \"HIDDEN\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceInventoryUnloadFixedWeapons\", &oxceInventoryUnloadFixedWeapons, true, \"\", \"HIDDEN\"));\n#else\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceInventorySplitScrollButton\", &oxceInventorySplitScrollButton, false, \"\", \"HIDDEN\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceInventoryDropItemOverPaperdoll\", &oxceInventoryDropItemOverPaperdoll, false, \"\", \"HIDDEN\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceInventoryUnloadFixedWeapons\", &oxceInventoryUnloadFixedWeapons, false, \"\", \"HIDDEN\"));\n#endif\n\n\t// TODO: needs restart (or code change) to work properly\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceMaxEquipmentLayoutTemplates\", &oxceMaxEquipmentLayoutTemplates, 20, \"\", \"HIDDEN\"));\n}\n\nvoid createAdvancedOptionsOXCE()\n{\n\t// OXCE options general\n#ifdef _WIN32\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceUpdateCheck\", &oxceUpdateCheck, false, \"STR_UPDATE_CHECK\", \"STR_GENERAL\"));\n#endif\n\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"autosaveSlots\", &autosaveSlots, 1, \"STR_AUTOSAVE_SLOTS\", \"STR_GENERAL\")); // OXCE only\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceGeoAutosaveFrequency\", &oxceGeoAutosaveFrequency, 0, \"STR_GEO_AUTOSAVE_FREQUENCY\", \"STR_GENERAL\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceGeoAutosaveSlots\", &oxceGeoAutosaveSlots, 1, \"STR_GEO_AUTOSAVE_SLOTS\", \"STR_GENERAL\"));\n\n#ifdef __MOBILE__\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceLinks\", &oxceLinks, true, \"STR_OXCE_LINKS\", \"STR_GENERAL\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceLinksDisableTextEdit\", &oxceLinksDisableTextEdit, true, \"\", \"HIDDEN\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceFatFingerLinks\", &oxceFatFingerLinks, true, \"\", \"HIDDEN\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceBattleTouchButtonsEnabled\", &oxceBattleTouchButtonsEnabled, true, \"\", \"HIDDEN\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceQuickSearchButton\", &oxceQuickSearchButton, true, \"\", \"HIDDEN\"));\n#else\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceLinks\", &oxceLinks, false, \"STR_OXCE_LINKS\", \"STR_GENERAL\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceLinksDisableTextEdit\", &oxceLinksDisableTextEdit, false, \"\", \"HIDDEN\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceFatFingerLinks\", &oxceFatFingerLinks, false, \"\", \"HIDDEN\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceBattleTouchButtonsEnabled\", &oxceBattleTouchButtonsEnabled, false, \"\", \"HIDDEN\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceQuickSearchButton\", &oxceQuickSearchButton, false, \"\", \"HIDDEN\"));\n#endif\n\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceHighlightNewTopics\", &oxceHighlightNewTopics, true, \"STR_HIGHLIGHT_NEW\", \"STR_GENERAL\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxcePediaShowClipSize\", &oxcePediaShowClipSize, false, \"STR_PEDIA_SHOW_CLIP_SIZE\", \"STR_GENERAL\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxcePediaSortResistances\", &oxcePediaSortResistances, 0, \"STR_PEDIA_SORT_RESISTANCES\", \"HIDDEN\"));\n\n\t// OXCE options geoscape\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceInterceptTableSize\", &oxceInterceptTableSize, 8, \"STR_INTERCEPT_TABLE_SIZE\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceEnableSlackingIndicator\", &oxceEnableSlackingIndicator, true, \"STR_SHOW_SLACKING_INDICATOR\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceInterceptGuiMaintenanceTime\", &oxceInterceptGuiMaintenanceTime, 2, \"STR_SHOW_MAINTENANCE_TIME\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceShowETAMode\", &oxceShowETAMode, 0, \"STR_SHOW_ETA\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceUfoLandingAlert\", &oxceUfoLandingAlert, false, \"STR_UFO_LANDING_ALERT\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceRememberDisabledCraftWeapons\", &oxceRememberDisabledCraftWeapons, false, \"STR_REMEMBER_DISABLED_CRAFT_WEAPONS\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceGeoscapeEventsInstantDelivery\", &oxceGeoscapeEventsInstantDelivery, true, \"STR_GEO_EVENT_INSTANT_DELIVERY\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceShowBaseNameInPopups\", &oxceShowBaseNameInPopups, false, \"STR_SHOW_BASE_NAME_IN_POPUPS\", \"STR_GEOSCAPE\"));\n\n\t// OXCE options basescape\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceAlternateCraftEquipmentManagement\", &oxceAlternateCraftEquipmentManagement, false, \"STR_ALTERNATE_CRAFT_EQUIPMENT_MANAGEMENT\", \"STR_BASESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceBaseInfoScaleEnabled\", &oxceBaseInfoScaleEnabled, false, \"STR_BASE_INFO_SCALE\", \"STR_BASESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceResearchScrollSpeed\", &oxceResearchScrollSpeed, 1, \"STR_RESEARCH_SCROLL_SPEED\", \"STR_BASESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceResearchScrollSpeedWithCtrl\", &oxceResearchScrollSpeedWithCtrl, 10, \"STR_RESEARCH_SCROLL_SPEED_CTRL\", \"STR_BASESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceManufactureFilterSuppliesOK\", &oxceManufactureFilterSuppliesOK, false, \"STR_MANUFACTURE_FILTER_SUPPLIES_OK\", \"STR_BASESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceManufactureScrollSpeed\", &oxceManufactureScrollSpeed, 1, \"STR_MANUFACTURE_SCROLL_SPEED\", \"STR_BASESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceManufactureScrollSpeedWithCtrl\", &oxceManufactureScrollSpeedWithCtrl, 10, \"STR_MANUFACTURE_SCROLL_SPEED_CTRL\", \"STR_BASESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxcePersonalLayoutIncludingArmor\", &oxcePersonalLayoutIncludingArmor, true, \"STR_PERSONAL_LAYOUT_INCLUDING_ARMOR\", \"STR_BASESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceManualPromotions\", &oxceManualPromotions, false, \"STR_MANUALPROMOTIONS\", \"STR_BASESCAPE\"));\n\n\t// OXCE options battlescape\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceWoundedDefendBaseIf\", &oxceWoundedDefendBaseIf, 100, \"STR_WOUNDED_DEFEND_BASE_IF\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxcePlayBriefingMusicDuringEquipment\", &oxcePlayBriefingMusicDuringEquipment, false, \"STR_PLAY_BRIEFING_MUSIC_DURING_EQUIPMENT\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceNightVisionColor\", &oxceNightVisionColor, 5, \"STR_NIGHT_VISION_COLOR\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceAutoNightVisionThreshold\", &oxceAutoNightVisionThreshold, 15, \"STR_AUTO_NIGHT_VISION_THRESHOLD\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceShowAccuracyOnCrosshair\", &oxceShowAccuracyOnCrosshair, 1, \"STR_SHOW_ACCURACY_ON_CROSSHAIR\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceReactionFireThreshold\", &oxceReactionFireThreshold, 0, \"STR_REACTION_FIRE_THRESHOLD\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceAutoSell\", &oxceAutoSell, false, \"STR_AUTO_SELL\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceAutomaticPromotions\", &oxceAutomaticPromotions, true, \"STR_AUTOMATICPROMOTIONS\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceEnableOffCentreShooting\", &oxceEnableOffCentreShooting, false, \"STR_OFF_CENTRE_SHOOTING\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceUniformShootingSpread\", &oxceUniformShootingSpread, false, \"STR_UNIFORM_SHOOTING_SPREAD\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"oxceCrashedOrLanded\", &oxceCrashedOrLanded, 0, \"STR_CRASHED_OR_LANDED\", \"STR_BATTLESCAPE\"));\n}\n\nvoid createControlsOXCE()\n{\n\t// OXCE controls general\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyToggleQuickSearch\", &keyToggleQuickSearch, SDLK_q, \"STR_TOGGLE_QUICK_SEARCH\", \"STR_GENERAL\")); //\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyInstaSave\", &keyInstaSave, SDLK_F6, \"STR_INSTA_SAVE\", \"STR_GENERAL\"));\n\n\t// OXCE controls geoscape\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyGeoUfoTracker\", &keyGeoUfoTracker, SDLK_t, \"STR_UFO_TRACKER\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyGeoTechTreeViewer\", &keyGeoTechTreeViewer, SDLK_q, \"STR_TECH_TREE_VIEWER\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyGeoGlobalProduction\", &keyGeoGlobalProduction, SDLK_p, \"STR_PRODUCTION_OVERVIEW\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyGeoGlobalResearch\", &keyGeoGlobalResearch, SDLK_c, \"STR_RESEARCH_OVERVIEW\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyGeoGlobalAlienContainment\", &keyGeoGlobalAlienContainment, SDLK_j, \"STR_PRISONER_OVERVIEW\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyGeoDailyPilotExperience\", &keyGeoDailyPilotExperience, SDLK_e, \"STR_DAILY_PILOT_EXPERIENCE\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyGraphsZoomIn\", &keyGraphsZoomIn, SDLK_KP_PLUS, \"STR_GRAPHS_ZOOM_IN\", \"STR_GEOSCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyGraphsZoomOut\", &keyGraphsZoomOut, SDLK_KP_MINUS, \"STR_GRAPHS_ZOOM_OUT\", \"STR_GEOSCAPE\"));\n\n\t// OXCE controls basescape\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyBasescapeBuildNewBase\", &keyBasescapeBuildNewBase, SDLK_n, \"STR_BUILD_NEW_BASE_UC\", \"STR_BASESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyBasescapeBaseInformation\", &keyBasescapeBaseInfo, SDLK_i, \"STR_BASE_INFORMATION\", \"STR_BASESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyBasescapeSoldiers\", &keyBasescapeSoldiers, SDLK_s, \"STR_SOLDIERS_UC\", \"STR_BASESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyBasescapeEquipCraft\", &keyBasescapeCrafts, SDLK_e, \"STR_EQUIP_CRAFT\", \"STR_BASESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyBasescapeBuildFacilities\", &keyBasescapeFacilities, SDLK_f, \"STR_BUILD_FACILITIES\", \"STR_BASESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyBasescapeResearch\", &keyBasescapeResearch, SDLK_r, \"STR_RESEARCH\", \"STR_BASESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyBasescapeManufacture\", &keyBasescapeManufacture, SDLK_m, \"STR_MANUFACTURE\", \"STR_BASESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyBasescapeTransfer\", &keyBasescapeTransfer, SDLK_t, \"STR_TRANSFER_UC\", \"STR_BASESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyBasescapePurchase\", &keyBasescapePurchase, SDLK_p, \"STR_PURCHASE_RECRUIT\", \"STR_BASESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyBasescapeSell\", &keyBasescapeSell, SDLK_l, \"STR_SELL_SACK_UC\", \"STR_BASESCAPE\"));\n\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyRemoveSoldiersFromTraining\", &keyRemoveSoldiersFromTraining, SDLK_x, \"STR_REMOVE_SOLDIERS_FROM_TRAINING\", \"STR_BASESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyAddSoldiersToTraining\", &keyAddSoldiersToTraining, SDLK_z, \"STR_ADD_SOLDIERS_TO_TRAINING\", \"STR_BASESCAPE\"));\n\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyCraftLoadoutSave\", &keyCraftLoadoutSave, SDLK_F5, \"STR_SAVE_CRAFT_LOADOUT_TEMPLATE\", \"STR_BASESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyCraftLoadoutLoad\", &keyCraftLoadoutLoad, SDLK_F9, \"STR_LOAD_CRAFT_LOADOUT_TEMPLATE\", \"STR_BASESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyRemoveSoldiersFromAllCrafts\", &keyRemoveSoldiersFromAllCrafts, SDLK_x, \"STR_REMOVE_SOLDIERS_FROM_ALL_CRAFTS\", \"STR_BASESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyRemoveSoldiersFromCraft\", &keyRemoveSoldiersFromCraft, SDLK_z, \"STR_REMOVE_SOLDIERS_FROM_CRAFT\", \"STR_BASESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyRemoveEquipmentFromCraft\", &keyRemoveEquipmentFromCraft, SDLK_x, \"STR_REMOVE_EQUIPMENT_FROM_CRAFT\", \"STR_BASESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyRemoveArmorFromAllCrafts\", &keyRemoveArmorFromAllCrafts, SDLK_x, \"STR_REMOVE_ARMOR_FROM_ALL_CRAFTS\", \"STR_BASESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyRemoveArmorFromCraft\", &keyRemoveArmorFromCraft, SDLK_z, \"STR_REMOVE_ARMOR_FROM_CRAFT\", \"STR_BASESCAPE\"));\n\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyInventorySave\", &keyInventorySave, SDLK_F5, \"STR_SAVE_EQUIPMENT_TEMPLATE\", \"STR_BASESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyInventoryLoad\", &keyInventoryLoad, SDLK_F9, \"STR_LOAD_EQUIPMENT_TEMPLATE\", \"STR_BASESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyInvSavePersonalEquipment\", &keyInvSavePersonalEquipment, SDLK_s, \"STR_SAVE_PERSONAL_EQUIPMENT\", \"STR_BASESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyInvLoadPersonalEquipment\", &keyInvLoadPersonalEquipment, SDLK_l, \"STR_LOAD_PERSONAL_EQUIPMENT\", \"STR_BASESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyInvShowPersonalEquipment\", &keyInvShowPersonalEquipment, SDLK_p, \"STR_PERSONAL_EQUIPMENT\", \"STR_BASESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyInventoryArmor\", &keyInventoryArmor, SDLK_a, \"STR_INVENTORY_ARMOR\", \"STR_BASESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyInventoryAvatar\", &keyInventoryAvatar, SDLK_m, \"STR_INVENTORY_AVATAR\", \"STR_BASESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyInventoryDiaryLight\", &keyInventoryDiaryLight, SDLK_d, \"STR_INVENTORY_DIARY_LIGHT\", \"STR_BASESCAPE\"));\n\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keySellAll\", &keySellAll, SDLK_x, \"STR_SELL_ALL\", \"STR_BASESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keySellAllButOne\", &keySellAllButOne, SDLK_z, \"STR_SELL_ALL_BUT_ONE\", \"STR_BASESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyTransferAll\", &keyTransferAll, SDLK_x, \"STR_TRANSFER_ALL\", \"STR_BASESCAPE\"));\n\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyMarkAllAsSeen\", &keyMarkAllAsSeen, SDLK_x, \"STR_MARK_ALL_AS_SEEN\", \"STR_BASESCAPE\"));\n\n\t// OXCE controls battlescape\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyBattleUnitUp\", &keyBattleUnitUp, SDLK_UNKNOWN, \"STR_UNIT_LEVEL_ABOVE\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyBattleUnitDown\", &keyBattleUnitDown, SDLK_UNKNOWN, \"STR_UNIT_LEVEL_BELOW\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyBattleShowLayers\", &keyBattleShowLayers, SDLK_UNKNOWN, \"STR_MULTI_LEVEL_VIEW\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyBattleUseSpecial\", &keyBattleUseSpecial, SDLK_w, \"STR_USE_SPECIAL_ITEM\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyBattleActionItem1\", &keyBattleActionItem1, SDLK_1, \"STR_ACTION_ITEM_1\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyBattleActionItem2\", &keyBattleActionItem2, SDLK_2, \"STR_ACTION_ITEM_2\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyBattleActionItem3\", &keyBattleActionItem3, SDLK_3, \"STR_ACTION_ITEM_3\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyBattleActionItem4\", &keyBattleActionItem4, SDLK_4, \"STR_ACTION_ITEM_4\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyBattleActionItem5\", &keyBattleActionItem5, SDLK_5, \"STR_ACTION_ITEM_5\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyNightVisionToggle\", &keyNightVisionToggle, SDLK_SCROLLOCK, \"STR_TOGGLE_NIGHT_VISION\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keyNightVisionHold\", &keyNightVisionHold, SDLK_SPACE, \"STR_HOLD_NIGHT_VISION\", \"STR_BATTLESCAPE\"));\n\t_info.push_back(OptionInfo(OPTION_OXCE, \"keySelectMusicTrack\", &keySelectMusicTrack, SDLK_END, \"STR_SELECT_MUSIC_TRACK\", \"STR_BATTLESCAPE\"));\n}\n\nvoid createOptionsOTHER()\n{\n\t// your fork's hidden options here\n}\n\nvoid createAdvancedOptionsOTHER()\n{\n\t// your fork's advanced options here\n}\n\nvoid createControlsOTHER()\n{\n\t// your fork's controls here\n}\n\n\n// we can get fancier with these detection routines, but for now just look for\n// *something* in the data folders.  case sensitivity can make actually verifying\n// that the *correct* files are there complex.\nstatic bool _gameIsInstalled(const std::string &gameName)\n{\n\t// look for game data in either the data or user directories\n\tstd::string dataGameFolder = CrossPlatform::searchDataFolder(gameName, 8);\n\tstd::string dataGameZipFile = CrossPlatform::searchDataFile(gameName + \".zip\");\n\tstd::string userGameFolder = _userFolder + gameName;\n\tstd::string userGameZipFile = _userFolder + gameName + \".zip\";\n\treturn (CrossPlatform::folderMinSize(dataGameFolder, 8))\n\t    || (CrossPlatform::folderMinSize(userGameFolder, 8))\n\t\t||  CrossPlatform::fileExists( dataGameZipFile )\n\t\t||  CrossPlatform::fileExists( userGameZipFile );\n}\n\nstatic bool _ufoIsInstalled()\n{\n\treturn _gameIsInstalled(\"UFO\");\n}\n\nstatic bool _tftdIsInstalled()\n{\n\treturn _gameIsInstalled(\"TFTD\");\n}\n\nstatic void _setDefaultMods()\n{\n\tbool haveUfo = _ufoIsInstalled();\n\tif (haveUfo)\n\t{\n\t\tmods.push_back(std::pair<std::string, bool>(\"xcom1\", true));\n\t}\n\n\tif (_tftdIsInstalled())\n\t{\n\t\tmods.push_back(std::pair<std::string, bool>(\"xcom2\", !haveUfo));\n\t}\n}\n\n/**\n * Resets the options back to their defaults.\n * @param includeMods Reset mods to default as well.\n */\nvoid resetDefault(bool includeMods)\n{\n\tfor (auto& optionInfo : _info)\n\t{\n\t\toptionInfo.reset();\n\t}\n\tbackupDisplay();\n\n\tif (includeMods)\n\t{\n\t\tmods.clear();\n\t\tif (!_dataList.empty())\n\t\t{\n\t\t\t_setDefaultMods();\n\t\t}\n\t}\n}\n\n/**\n * Loads options from a set of command line arguments,\n * in the format \"-option value\".\n * @param argc Number of arguments.\n * @param argv Array of argument strings.\n */\nstatic void loadArgs()\n{\n\tauto& argv = CrossPlatform::getArgs();\n\tfor (size_t i = 1; i < argv.size(); ++i)\n\t{\n\t\tauto& arg = argv[i];\n\t\tif ((arg[0] == '-' || arg[0] == '/') && arg.length() > 1)\n\t\t{\n\t\t\tif (arg == \"--\")\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tstd::string argname;\n\t\t\tif (arg[1] == '-' && arg.length() > 2)\n\t\t\t\targname = arg.substr(2, arg.length()-1);\n\t\t\telse\n\t\t\t\targname = arg.substr(1, arg.length()-1);\n\t\t\tstd::transform(argname.begin(), argname.end(), argname.begin(), ::tolower);\n\t\t\tif (argname == \"cont\" || argname == \"continue\")\n\t\t\t{\n\t\t\t\t_loadLastSave = true;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (argv.size() > i + 1)\n\t\t\t{\n\t\t\t\t++i; // we'll be consuming the next argument too\n\t\t\t\tLog(LOG_DEBUG) << \"loadArgs(): \"<< argname <<\" -> \" << argv[i];\n\t\t\t\tif (argname == \"data\")\n\t\t\t\t{\n\t\t\t\t\t_dataFolder = argv[i];\n\t\t\t\t\tif (_dataFolder.size() > 1 && _dataFolder[_dataFolder.size() - 1] != '/') {\n\t\t\t\t\t\t_dataFolder.push_back('/');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (argname == \"user\")\n\t\t\t\t{\n\t\t\t\t\t_userFolder = argv[i];\n\t\t\t\t\tif (_userFolder.size() > 1 && _userFolder[_userFolder.size() - 1] != '/') {\n\t\t\t\t\t\t_userFolder.push_back('/');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (argname == \"cfg\" || argname == \"config\")\n\t\t\t\t{\n\t\t\t\t\t_configFolder = argv[i];\n\t\t\t\t\tif (_configFolder.size() > 1 && _configFolder[_configFolder.size() - 1] != '/') {\n\t\t\t\t\t\t_configFolder.push_back('/');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (argname == \"master\")\n\t\t\t\t{\n\t\t\t\t\t_masterMod = argv[i];\n\t\t\t\t}\n\t\t\t\telse if (argname == \"load\")\n\t\t\t\t{\n\t\t\t\t\t_loadLastSave = true;\n\t\t\t\t\t_loadThisSave = argv[i];\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t//save this command line option for now, we will apply it later\n\t\t\t\t\t_commandLine[argname] = argv[i];\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tLog(LOG_WARNING) << \"Unknown option: \" << argname;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/*\n * Displays command-line help when appropriate.\n * @param argc Number of arguments.\n * @param argv Array of argument strings.\n */\nstatic bool showHelp()\n{\n\tstd::ostringstream help;\n\thelp << \"OpenXcom \" << OPENXCOM_VERSION_SHORT << std::endl;\n\thelp << \"Usage: openxcom [OPTION]...\" << std::endl << std::endl;\n\thelp << \"-data PATH\" << std::endl;\n\thelp << \"        use PATH as the default Data Folder instead of auto-detecting\" << std::endl << std::endl;\n\thelp << \"-user PATH\" << std::endl;\n\thelp << \"        use PATH as the default User Folder instead of auto-detecting\" << std::endl << std::endl;\n\thelp << \"-cfg PATH  or  -config PATH\" << std::endl;\n\thelp << \"        use PATH as the default Config Folder instead of auto-detecting\" << std::endl << std::endl;\n\thelp << \"-master MOD\" << std::endl;\n\thelp << \"        set MOD to the current master mod (eg. -master xcom2)\" << std::endl << std::endl;\n\thelp << \"-KEY VALUE\" << std::endl;\n\thelp << \"        override option KEY with VALUE (eg. -displayWidth 640)\" << std::endl << std::endl;\n\thelp << \"-continue\" << std::endl;\n\thelp << \"        load last save\" << std::endl << std::endl;\n\thelp << \"-load FILENAME\" << std::endl;\n\thelp << \"        load the specified FILENAME (from the corresponding master mod subfolder)\" << std::endl << std::endl;\n\thelp << \"-version\" << std::endl;\n\thelp << \"        show version number\" << std::endl << std::endl;\n\thelp << \"-help\" << std::endl;\n\thelp << \"-?\" << std::endl;\n\thelp << \"        show command-line help\" << std::endl;\n\tauto& argv = CrossPlatform::getArgs();\n\tfor (size_t i = 1; i < argv.size(); ++i)\n\t{\n\t\tauto& arg = argv[i];\n\t\tif ((arg[0] == '-' || arg[0] == '/') && arg.length() > 1)\n\t\t{\n\t\t\tif (arg == \"--\")\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tstd::string argname;\n\t\t\tif (arg[1] == '-' && arg.length() > 2)\n\t\t\t\targname = arg.substr(2, arg.length()-1);\n\t\t\telse\n\t\t\t\targname = arg.substr(1, arg.length()-1);\n\t\t\tstd::transform(argname.begin(), argname.end(), argname.begin(), ::tolower);\n\t\t\tif (argname == \"help\" || argname == \"?\")\n\t\t\t{\n\t\t\t\tstd::cout << help.str();\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tif (argname == \"version\")\n\t\t\t{\n\t\t\t\tstd::cout << OPENXCOM_VERSION_SHORT << OPENXCOM_VERSION_GIT << std::endl;\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tif (argname == \"cont\" || argname == \"continue\")\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// skip next option argument, only couple options do not have it.\n\t\t\t++i;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tstd::cerr << \"Unknown parameter '\" << arg << \"'\" << std::endl;\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\nconst std::map<std::string, ModInfo> &getModInfos() { return _modInfos; }\n\n/**\n * Splits the game's User folder by master mod,\n * creating a subfolder for each one.\n * Moving the saves from userFolder into subfolders\n * has been removed.\n */\nstatic void userSplitMasters()\n{\n\tfor (const auto& pair : _modInfos) {\n\t\tif (pair.second.isMaster()) {\n\t\t\tstd::string masterFolder = _userFolder + pair.first;\n\t\t\tif (!CrossPlatform::folderExists(masterFolder)) {\n\t\t\t\tCrossPlatform::createFolder(masterFolder);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Handles the initialization of setting up default options\n * and finding and loading any existing ones.\n * @param argc Number of arguments.\n * @param argv Array of argument strings.\n * @return Do we start the game?\n */\nbool init()\n{\n\tif (showHelp())\n\t\treturn false;\n\tcreate();\n\tresetDefault(true);\n\tloadArgs();\n\tsetFolders();\n\t_setDefaultMods();\n\tupdateOptions();\n\n\t// set up the logging reportingLevel\n#ifndef NDEBUG\n\tLogger::reportingLevel() = LOG_DEBUG;\n#else\n\tLogger::reportingLevel() = LOG_INFO;\n#endif\n\n\tif (Options::verboseLogging)\n\t\tLogger::reportingLevel() = LOG_VERBOSE;\n\n\t// this enables writes to the log file and filters already emitted messages\n\tCrossPlatform::setLogFileName(getUserFolder() + \"openxcom.log\");\n\n\tLog(LOG_INFO) << \"OpenXcom Version: \" << OPENXCOM_VERSION_SHORT << OPENXCOM_VERSION_GIT;\n#ifdef _WIN64\n\tLog(LOG_INFO) << \"Platform: Windows 64 bit\";\n#elif _WIN32\n\tLog(LOG_INFO) << \"Platform: Windows 32 bit\";\n#elif __APPLE__\n\tLog(LOG_INFO) << \"Platform: OSX\";\n#elif  __ANDROID_API__\n\tLog(LOG_INFO) << \"Platform: Android \" << __ANDROID_API__;\n#elif __linux__\n\tLog(LOG_INFO) << \"Platform: Linux\";\n#else\n\tLog(LOG_INFO) << \"Platform: Unix-like\";\n#endif\n\n\tLog(LOG_INFO) << \"Data folder is: \" << _dataFolder;\n\tLog(LOG_INFO) << \"Data search is: \";\n\tfor (const auto& dataPath : _dataList)\n\t{\n\t\tLog(LOG_INFO) << \"- \" << dataPath;\n\t}\n\tLog(LOG_INFO) << \"User folder is: \" << _userFolder;\n\tLog(LOG_INFO) << \"Config folder is: \" << _configFolder;\n\tLog(LOG_INFO) << \"Options loaded successfully.\";\n\n\tFileMap::clear(false, Options::oxceEmbeddedOnly);\n\treturn true;\n}\n\n// called from the dos screen state (StartState)\nvoid refreshMods()\n{\n\tif (Options::reload)\n\t{\n\t\t_masterMod = \"\";\n\t}\n\n\t_modInfos.clear();\n\tSDL_RWops *rwops = CrossPlatform::getEmbeddedAsset(\"standard.zip\");\n\tif (rwops) {\n\t\tLog(LOG_INFO) << \"Scanning embedded standard mods...\";\n\t\tFileMap::scanModZipRW(rwops, \"exe:standard.zip\");\n\t}\n\tif (Options::oxceEmbeddedOnly && rwops) {\n\t\tLog(LOG_INFO) << \"Modding embedded resources is disabled, set 'oxceEmbeddedOnly: false' in options.cfg to enable.\";\n\t} else {\n\t\tLog(LOG_INFO) << \"Scanning standard mods in '\" << getDataFolder() << \"'...\";\n\t\tFileMap::scanModDir(getDataFolder(), \"standard\", true);\n\t}\n\tLog(LOG_INFO) << \"Scanning user mods in '\" << getUserFolder() << \"'...\";\n\tFileMap::scanModDir(getUserFolder(), \"mods\", false);\n#ifdef __MOBILE__\n\tif (getDataFolder() == getUserFolder())\n\t{\n\t\tLog(LOG_INFO) << \"Skipped scanning user mods in the data folder, because it's the same folder as the user folder.\";\n\t}\n\telse\n\t{\n\t\tLog(LOG_INFO) << \"Scanning user mods in '\" << getDataFolder() << \"'...\";\n\t\tFileMap::scanModDir(getDataFolder(), \"mods\", false);\n\t}\n#endif\n\n\t// Check mods' dependencies on other mods and extResources (UFO, TFTD, etc),\n\t// also breaks circular dependency loops.\n\tFileMap::checkModsDependencies();\n\n\t// Now we can get the list of ModInfos from the FileMap -\n\t// those are the mods that can possibly be loaded.\n\t_modInfos = FileMap::getModInfos();\n\n\t// remove mods from list that no longer exist\n\tbool nonMasterModFound = false;\n\tstd::map<std::string, bool> corruptedMasters;\n\tfor (auto i = mods.begin(); i != mods.end();)\n\t{\n\t\tauto modIt = _modInfos.find(i->first);\n\t\tif (_modInfos.end() == modIt)\n\t\t{\n\t\t\tLog(LOG_VERBOSE) << \"removing references to missing mod: \" << i->first;\n\t\t\ti = mods.erase(i);\n\t\t\tcontinue;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif ((*modIt).second.isMaster())\n\t\t\t{\n\t\t\t\tif (nonMasterModFound)\n\t\t\t\t{\n\t\t\t\t\tLog(LOG_ERROR) << \"Removing master mod '\" << i->first << \"' from the list, because it is on a wrong position. It will be re-added automatically.\";\n\t\t\t\t\tcorruptedMasters[i->first] = i->second;\n\t\t\t\t\ti = mods.erase(i);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tnonMasterModFound = true;\n\t\t\t}\n\t\t}\n\t\t++i;\n\t}\n\t// re-insert corrupted masters at the beginning of the list\n\tfor (const auto& pair : corruptedMasters)\n\t{\n\t\tstd::pair<std::string, bool> newMod(pair.first, pair.second);\n\t\tmods.insert(mods.begin(), newMod);\n\t}\n\n\t// add in any new mods picked up from the scan and ensure there is but a single\n\t// master active\n\tstd::string activeMaster;\n\tstd::string inactiveMaster;\n\tfor (auto i = _modInfos.cbegin(); i != _modInfos.cend(); ++i)\n\t{\n\t\tbool found = false;\n\t\tfor (auto j = mods.begin(); j != mods.end(); ++j)\n\t\t{\n\t\t\tif (i->first == j->first)\n\t\t\t{\n\t\t\t\tfound = true;\n\t\t\t\tif (i->second.isMaster())\n\t\t\t\t{\n\t\t\t\t\tif (!_masterMod.empty())\n\t\t\t\t\t{\n\t\t\t\t\t\tj->second = (_masterMod == j->first);\n\t\t\t\t\t}\n\t\t\t\t\tif (j->second)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (!activeMaster.empty())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tLog(LOG_WARNING) << \"Too many active masters detected; turning off \" << j->first;\n\t\t\t\t\t\t\tj->second = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tactiveMaster = j->first;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// prefer activating standard masters over a possibly broken\n\t\t\t\t\t\t// third party master\n\t\t\t\t\t\tif (inactiveMaster.empty() || j->first == \"xcom1\" || j->first == \"xcom2\")\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tinactiveMaster = j->first;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (found)\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\n\t\t// not active by default\n\t\tstd::pair<std::string, bool> newMod(i->first, false);\n\t\tif (i->second.isMaster())\n\t\t{\n\t\t\t// it doesn't matter what order the masters are in since\n\t\t\t// only one can be active at a time anyway\n\t\t\tmods.insert(mods.begin(), newMod);\n\n\t\t\tif (inactiveMaster.empty())\n\t\t\t{\n\t\t\t\tinactiveMaster = i->first;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tmods.push_back(newMod);\n\t\t}\n\t}\n\n\tif (activeMaster.empty())\n\t{\n\t\tif (inactiveMaster.empty())\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"no mod masters available\";\n\t\t\tthrow Exception(\"No X-COM installations found\");\n\t\t}\n\t\telse\n\t\t{\n\t\t\tLog(LOG_INFO) << \"no master already active; activating \" << inactiveMaster;\n\t\t\tstd::find(mods.begin(), mods.end(), std::pair<std::string, bool>(inactiveMaster, false))->second = true;\n\t\t\t_masterMod = inactiveMaster;\n\t\t}\n\t}\n\telse\n\t{\n\t\t_masterMod = activeMaster;\n\t}\n\tsave();\n}\n\nvoid updateMods()\n{\n\tsetDataFolder(CrossPlatform::dirFilename(CrossPlatform::searchDataFolder(\"common\")));\n\n\t// pick up stuff in common before-hand\n\tFileMap::clear(false, Options::oxceEmbeddedOnly);\n\n\trefreshMods();\n\n\t// check active mods that don't meet the enforced OXCE requirements\n\tauto* masterInf = getActiveMasterInfo();\n\tauto activeModsList = getActiveMods();\n\tbool forceQuit = false;\n\tfor (auto* modInf : activeModsList)\n\t{\n\t\tif (ModConfirmExtendedState::isModNotValid(modInf, masterInf))\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"- \" << modInf->getId() << \" v\" << modInf->getVersion();\n\t\t\tif (!modInf->isEngineOk())\n\t\t\t{\n\t\t\t\tforceQuit = true;\n\t\t\t\tif (modInf->getRequiredExtendedEngine() != OPENXCOM_VERSION_ENGINE)\n\t\t\t\t{\n\t\t\t\t\tLog(LOG_ERROR) << \"Mod '\" << modInf->getName() << \"' require OXC \" << modInf->getRequiredExtendedEngine() << \" engine to run\";\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tLog(LOG_ERROR) << \"Mod '\" << modInf->getName() << \"' enforces at least OXC \" << OPENXCOM_VERSION_ENGINE << \" v\" << modInf->getRequiredExtendedVersion();\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!modInf->isParentMasterOk(masterInf))\n\t\t\t{\n\t\t\t\tLog(LOG_ERROR) << \"Mod '\" << modInf->getName() << \"' require version \" << modInf->getRequiredMasterVersion() << \" of master mod to run (current one is \" << masterInf->getVersion() << \")\";\n\t\t\t}\n\t\t}\n\t}\n\tif (forceQuit)\n\t{\n\t\tthrow Exception(\"Incompatible mods are active. Please upgrade OpenXcom.\");\n\t}\n\n\tFileMap::setup(activeModsList, Options::oxceEmbeddedOnly);\n\tuserSplitMasters();\n\n\tLog(LOG_INFO) << \"Active mods:\";\n\tauto activeMods = getActiveMods();\n\tfor (auto* modInf : activeMods)\n\t{\n\t\tLog(LOG_INFO) << \"- \" << modInf->getId() << \" v\" << modInf->getVersion();\n\t}\n}\n\n/**\n * Is the password correct?\n * @return Mostly false.\n */\nbool isPasswordCorrect()\n{\n\tif (_passwordCheck < 0)\n\t{\n\t\tstd::string md5hash = md5(Options::password);\n\t\tif (md5hash == \"52bd8e15118862c40fc0d6107e197f42\")\n\t\t\t_passwordCheck = 1;\n\t\telse\n\t\t\t_passwordCheck = 0;\n\t}\n\n\treturn _passwordCheck > 0;\n}\n\n/**\n * Gets the currently active master mod.\n * @return Mod id.\n */\nstd::string getActiveMaster()\n{\n\treturn _masterMod;\n}\n\n/**\n * Gets the master mod info.\n */\nconst ModInfo* getActiveMasterInfo()\n{\n\treturn &_modInfos.at(_masterMod);\n}\n\n/**\n * Gets the xcom ruleset info.\n */\nconst ModInfo* getXcomRulesetInfo()\n{\n\tif (_modInfos.find(\"xcom1\") != _modInfos.end())\n\t\treturn &_modInfos.at(\"xcom1\");\n\telse if (_modInfos.find(\"xcom2\") != _modInfos.end())\n\t\treturn &_modInfos.at(\"xcom2\");\n\telse return nullptr;\n}\n\nbool getLoadLastSave()\n{\n\treturn _loadLastSave && !_loadLastSaveExpended;\n}\n\nconst std::string& getLoadThisSave()\n{\n\treturn _loadThisSave;\n}\n\nvoid expendLoadLastSave()\n{\n\t_loadLastSaveExpended = true;\n}\n\n/**\n * Sets up the game's Data folder where the data files\n * are loaded from and the User folder and Config\n * folder where settings and saves are stored in.\n */\nvoid setFolders()\n{\n\t_dataList = CrossPlatform::findDataFolders();\n\tif (!_dataFolder.empty())\n\t{\n\t\t_dataList.insert(_dataList.begin(), _dataFolder);\n\t\tLog(LOG_DEBUG) << \"setFolders(): inserting \" << _dataFolder;\n\t}\n\tif (_userFolder.empty())\n\t{\n\t\tstd::vector<std::string> user = CrossPlatform::findUserFolders();\n\n\t\tif (_configFolder.empty())\n\t\t{\n\t\t\t_configFolder = CrossPlatform::findConfigFolder();\n\t\t}\n\n\t\t// Look for an existing user folder\n\t\tfor (std::vector<std::string>::reverse_iterator i = user.rbegin(); i != user.rend(); ++i)\n\t\t{\n\t\t\tif (CrossPlatform::folderExists(*i))\n\t\t\t{\n\t\t\t\t_userFolder = *i;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// Set up folders\n\t\tif (_userFolder.empty())\n\t\t{\n\t\t\tfor (const auto& userFolder : user)\n\t\t\t{\n\t\t\t\tif (CrossPlatform::createFolder(userFolder))\n\t\t\t\t{\n\t\t\t\t\t_userFolder = userFolder;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif (!_userFolder.empty())\n\t{\n\t\t// create mod folder if it doesn't already exist\n\t\tCrossPlatform::createFolder(_userFolder + \"mods\");\n\t}\n\n\tif (_configFolder.empty())\n\t{\n\t\t_configFolder = _userFolder;\n\t}\n}\n\n/**\n * Updates the game's options with those in the configuration\n * file, if it exists yet, and any supplied on the command line.\n */\nvoid updateOptions()\n{\n\t// Load existing options\n\tif (CrossPlatform::folderExists(_configFolder))\n\t{\n\t\tif (CrossPlatform::fileExists(_configFolder + \"options.cfg\"))\n\t\t{\n\t\t\tload();\n#ifndef EMBED_ASSETS\n\t\t\tOptions::oxceEmbeddedOnly = false;\n#endif\n\t\t}\n\t\telse\n\t\t{\n\t\t\tsave();\n\t\t}\n\t}\n\t// Create config folder and save options\n\telse\n\t{\n\t\tCrossPlatform::createFolder(_configFolder);\n\t\tsave();\n\t}\n\n\t// now apply options set on the command line, overriding defaults and those loaded from config file\n\t//if (!_commandLine.empty())\n\tfor (auto& optionInfo : _info)\n\t{\n\t\toptionInfo.load(_commandLine, true);\n\t}\n}\n\n/**\n * Loads options from a YAML file.\n * @param filename YAML filename.\n * @return Was the loading successful?\n */\nbool load(const std::string &filename)\n{\n\tstd::string s = _configFolder + filename + \".cfg\";\n\ttry\n\t{\n\t\tYAML::YamlRootNodeReader reader(s);\n\t\t// Ignore old options files\n\t\tif (reader[\"options\"][\"NewBattleMission\"])\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t\tfor (auto& optionInfo : _info)\n\t\t{\n\t\t\toptionInfo.load(reader[\"options\"]);\n\t\t}\n\n\t\tmods.clear();\n\t\tfor (const auto& mod : reader[\"mods\"].children())\n\t\t{\n\t\t\tstd::string id = mod[\"id\"].readVal<std::string>();\n\t\t\tbool active = mod[\"active\"].readVal(false);\n\t\t\tmods.push_back(std::pair<std::string, bool>(id, active));\n\t\t}\n\t\tif (mods.empty())\n\t\t{\n\t\t\t_setDefaultMods();\n\t\t}\n\t}\n\tcatch (YAML::Exception &e)\n\t{\n\t\tLog(LOG_WARNING) << e.what();\n\t\treturn false;\n\t}\n\treturn true;\n}\n\n/**\n * Saves options to a YAML file.\n * @param filename YAML filename.\n * @return Was the saving successful?\n */\nbool save(bool reset, const std::string& filename)\n{\n\tstd::string yaml;\n\tstd::string filepath = _configFolder + filename + \".cfg\";\n\ttry\n\t{\n\t\tYAML::YamlRootNodeWriter writer;\n\t\twriter.setAsMap();\n\t\tauto modsWriter = writer[\"mods\"];\n\t\tmodsWriter.setAsSeq();\n\t\tfor (const auto& pair : mods)\n\t\t{\n\t\t\tauto modWriter = modsWriter.write();\n\t\t\tmodWriter.setAsMap();\n\t\t\tmodWriter.write(\"active\", pair.second);\n\t\t\tmodWriter.write(\"id\", pair.first);\n\t\t}\n\t\tauto optionsWriter = writer[\"options\"];\n\t\toptionsWriter.setAsMap();\n\t\tauto sortedInfo = _info;\n\t\tstd::sort(sortedInfo.begin(), sortedInfo.end(), [](const OptionInfo& a, const OptionInfo& b) { return a.id() < b.id(); });\n\t\tfor (const auto& optionInfo : sortedInfo)\n\t\t{\n\t\t\toptionInfo.save(optionsWriter);\n\t\t}\n\t\tif (!reset && CrossPlatform::fileExists(filepath))\n\t\t{\n\t\t\t// Preserve any undefined options, because they could be from a different fork\n\t\t\tYAML::YamlRootNodeReader old(filepath);\n\t\t\tconst YAML::YamlNodeReader& currentOptions = optionsWriter.toReader();\n\t\t\tstd::string oldKey, oldVal;\n\t\t\tfor (const auto& oldOption : old[\"options\"].children())\n\t\t\t\tif (!currentOptions[oldOption.readKey<ryml::csubstr>()])\n\t\t\t\t\toptionsWriter.write(optionsWriter.saveString(oldKey.assign(oldOption.key())), oldVal.assign(oldOption.val()));\n\t\t}\n\t\tyaml = writer.emit().yaml;\n\t}\n\tcatch (YAML::Exception &e)\n\t{\n\t\tLog(LOG_WARNING) << e.what();\n\t\treturn false;\n\t}\n\tif (!CrossPlatform::writeFile(filepath, yaml + \"\\n\"))\n\t{\n\t\tLog(LOG_WARNING) << \"Failed to save \" << filepath;\n\t\treturn false;\n\t}\n\treturn true;\n}\n\n/**\n * Returns the game's current Data folder where resources\n * and X-Com files are loaded from.\n * @return Full path to Data folder.\n */\nstd::string getDataFolder()\n{\n\treturn _dataFolder;\n}\n\n/**\n * Changes the game's current Data folder where resources\n * and X-Com files are loaded from.\n * @param folder Full path to Data folder.\n */\nvoid setDataFolder(const std::string &folder)\n{\n\t_dataFolder = folder;\n\tLog(LOG_DEBUG) << \"setDataFolder(\" << folder <<\");\";\n}\n\n/**\n * Returns the game's list of possible Data folders.\n * @return List of Data paths.\n */\nconst std::vector<std::string> &getDataList()\n{\n\treturn _dataList;\n}\n\n/**\n * Returns the game's User folder where\n * saves are stored in.\n * @return Full path to User folder.\n */\nstd::string getUserFolder()\n{\n\treturn _userFolder;\n}\n\n/**\n * Returns the game's Config folder where\n * settings are stored in. Normally the same\n * as the User folder.\n * @return Full path to Config folder.\n */\nstd::string getConfigFolder()\n{\n\treturn _configFolder;\n}\n\n/**\n * Returns the game's User folder for the\n * currently loaded master mod.\n * @return Full path to User folder.\n */\nstd::string getMasterUserFolder()\n{\n\treturn _userFolder + _masterMod + \"/\";\n}\n\n/**\n * Returns the game's list of all available option information.\n * @return List of OptionInfo's.\n */\nconst std::vector<OptionInfo> &getOptionInfo()\n{\n\treturn _info;\n}\n\n/**\n * Returns a list of currently active mods.\n * They must be enabled and activable.\n * @sa ModInfo::canActivate\n * @return List of info for the active mods.\n */\nstd::vector<const ModInfo *> getActiveMods()\n{\n\tstd::vector<const ModInfo*> activeMods;\n\tfor (const auto& pair : mods)\n\t{\n\t\tif (pair.second)\n\t\t{\n\t\t\tconst ModInfo *info = &_modInfos.at(pair.first);\n\t\t\tif (info->canActivate(_masterMod))\n\t\t\t{\n\t\t\t\tactiveMods.push_back(info);\n\t\t\t}\n\t\t}\n\t}\n\treturn activeMods;\n}\n\n/**\n * Saves display settings temporarily to be able\n * to revert to old ones.\n */\nvoid backupDisplay()\n{\n\tOptions::newDisplayWidth = Options::displayWidth;\n\tOptions::newDisplayHeight = Options::displayHeight;\n\tOptions::newBattlescapeScale = Options::battlescapeScale;\n\tOptions::newGeoscapeScale = Options::geoscapeScale;\n\tOptions::newOpenGL = Options::useOpenGL;\n\tOptions::newScaleFilter = Options::useScaleFilter;\n\tOptions::newHQXFilter = Options::useHQXFilter;\n\tOptions::newOpenGLShader = Options::useOpenGLShader;\n\tOptions::newXBRZFilter = Options::useXBRZFilter;\n\tOptions::newRootWindowedMode = Options::rootWindowedMode;\n\tOptions::newWindowedModePositionX = Options::windowedModePositionX;\n\tOptions::newWindowedModePositionY = Options::windowedModePositionY;\n\tOptions::newFullscreen = Options::fullscreen;\n\tOptions::newAllowResize = Options::allowResize;\n\tOptions::newBorderless = Options::borderless;\n}\n\n/**\n * Switches old/new display options for temporarily\n * testing a new display setup.\n */\nvoid switchDisplay()\n{\n\tstd::swap(displayWidth, newDisplayWidth);\n\tstd::swap(displayHeight, newDisplayHeight);\n\tstd::swap(useOpenGL, newOpenGL);\n\tstd::swap(useScaleFilter, newScaleFilter);\n\tstd::swap(battlescapeScale, newBattlescapeScale);\n\tstd::swap(geoscapeScale, newGeoscapeScale);\n\tstd::swap(useHQXFilter, newHQXFilter);\n\tstd::swap(useOpenGLShader, newOpenGLShader);\n\tstd::swap(useXBRZFilter, newXBRZFilter);\n\tstd::swap(rootWindowedMode, newRootWindowedMode);\n\tstd::swap(windowedModePositionX, newWindowedModePositionX);\n\tstd::swap(windowedModePositionY, newWindowedModePositionY);\n\tstd::swap(fullscreen, newFullscreen);\n\tstd::swap(allowResize, newAllowResize);\n\tstd::swap(borderless, newBorderless);\n}\n\n}\n\n}\n"
  },
  {
    "path": "src/Engine/Options.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include <vector>\n#include \"OptionInfo.h\"\n#include \"ModInfo.h\"\n#include \"Language.h\"\n\nnamespace OpenXcom\n{\n\n/// Battlescape drag scrolling types.\nenum ScrollType { SCROLL_NONE, SCROLL_TRIGGER, SCROLL_AUTO };\n/// Keyboard input modes.\nenum KeyboardType { KEYBOARD_OFF, KEYBOARD_ON, KEYBOARD_VIRTUAL };\n/// Savegame sorting modes.\nenum SaveSort { SORT_NAME_ASC, SORT_NAME_DESC, SORT_DATE_ASC, SORT_DATE_DESC };\n/// Music format preferences.\nenum MusicFormat { MUSIC_AUTO, MUSIC_FLAC, MUSIC_OGG, MUSIC_MP3, MUSIC_MOD, MUSIC_WAV, MUSIC_ADLIB, MUSIC_GM, MUSIC_MIDI };\n/// Sound format preferences.\nenum SoundFormat { SOUND_AUTO, SOUND_14, SOUND_10 };\n/// Video format preferences.\nenum VideoFormat { VIDEO_FMV, VIDEO_SLIDE };\n/// Path preview modes (can be OR'd together).\nenum PathPreview {\n\tPATH_NONE         = 0x00, // 0000 (must always be zero)\n\tPATH_ARROWS       = 0x01, // 0001\n\tPATH_TU_COST      = 0x02, // 0010\n\tPATH_ARROW_TU     = 0x03, // 0011\n\tPATH_ENERGY_COST  = 0x04, // 0100\n\tPATH_ARROW_ENERGY = 0x05, // 0101\n\tPATH_TU_ENERGY    = 0x06, // 0110\n\tPATH_FULL         = 0x07  // 0111 (must always be all values combined)\n};\n\nenum ScaleType\n{\n\tSCALE_ORIGINAL,\n\tSCALE_15X,\n\tSCALE_2X,\n\tSCALE_SCREEN_DIV_3,\n\tSCALE_SCREEN_DIV_2,\n\tSCALE_SCREEN,\n\tSCALE_SCREEN_DIV_4,\n\tSCALE_SCREEN_DIV_5,\n\tSCALE_SCREEN_DIV_6,\n\tSCALE_SCREEN_DIV_8,\n\tSCALE_SCREEN_DIV_10\n};\n/**\n * Container for all the various global game options\n * and customizable settings.\n */\nnamespace Options\n{\n#define OPT extern\n#include \"Options.inc.h\"\n#undef OPT\n\n\t/// Creates the options info.\n\tvoid create();\n\tvoid createOptionsOXC();\n\tvoid createAdvancedOptionsOXC();\n\tvoid createControlsOXC();\n\tvoid createOptionsOXCE();\n\tvoid createAdvancedOptionsOXCE();\n\tvoid createControlsOXCE();\n\tvoid createOptionsOTHER();\n\tvoid createAdvancedOptionsOTHER();\n\tvoid createControlsOTHER();\n\t/// Restores default options.\n\tvoid resetDefault(bool includeMods);\n\t/// Initializes the options settings.\n\tbool init();\n\t/// Loads options from YAML.\n\tbool load(const std::string &filename = \"options\");\n\t/// Saves options to YAML.\n\tbool save(bool reset = false, const std::string &filename = \"options\");\n\t/// Gets the game's data folder.\n\tstd::string getDataFolder();\n\t/// Sets the game's data folder.\n\tvoid setDataFolder(const std::string &folder);\n\t/// Gets the game's data list.\n\tconst std::vector<std::string> &getDataList();\n\t/// Gets the game's user folder.\n\tstd::string getUserFolder();\n\t/// Gets the game's config folder.\n\tstd::string getConfigFolder();\n\t/// Gets the game's master mod user folder.\n\tstd::string getMasterUserFolder();\n\t/// Gets the game's options.\n\tconst std::vector<OptionInfo> &getOptionInfo();\n\t/// Sets the game's data, user and config folders.\n\tvoid setFolders();\n\t/// Update game options from config file and command line.\n\tvoid updateOptions();\n\t/// Backup display options.\n\tvoid backupDisplay();\n\t/// Switches display options.\n\tvoid switchDisplay();\n\t/// Is the password correct?\n\tbool isPasswordCorrect();\n\t/// returns the id of the active master mod\n\tstd::string getActiveMaster();\n\t/// Gets the master mod info.\n\tconst ModInfo* getActiveMasterInfo();\n\t/// Gets the xcom ruleset info.\n\tconst ModInfo* getXcomRulesetInfo();\n\t/// Gets the map of mod ids to mod infos\n\tconst std::map<std::string, ModInfo> &getModInfos();\n\t/// Refreshes the mods.\n\tvoid refreshMods();\n\t/// Refreshes the mods and filemaps.\n\tvoid updateMods();\n\t/// Gets the list of currently active mods.\n\tstd::vector<const ModInfo*> getActiveMods();\n\t/// If we should skip the main menu and just load the last save\n\tbool getLoadLastSave();\n\t/// If we should skip the main menu and just load the specified save\n\tconst std::string& getLoadThisSave();\n\t/// And do it only at startup\n\tvoid expendLoadLastSave();\n}\n\n}\n"
  },
  {
    "path": "src/Engine/Options.inc.h",
    "content": "// Don't worry about Intellisense errors here, as this file is only used in conjunction with Options.h/Options.cpp\n// To add a new option, add a new variable entry and a corresponding OptionInfo in Options.cpp\n\n// General options\nOPT int displayWidth, displayHeight, maxFrameSkip, baseXResolution, baseYResolution, baseXGeoscape, baseYGeoscape, baseXBattlescape, baseYBattlescape,\n\tsoundVolume, musicVolume, uiVolume, audioSampleRate, audioBitDepth, audioChunkSize, pauseMode, windowedModePositionX, windowedModePositionY, FPS, FPSInactive,\n\tchangeValueByMouseWheel, dragScrollTimeTolerance, dragScrollPixelTolerance, mousewheelSpeed, autosaveFrequency;\nOPT bool fullscreen, asyncBlit, playIntro, useScaleFilter, useHQXFilter, useXBRZFilter, useOpenGL, checkOpenGLErrors, vSyncForOpenGL, useOpenGLSmoothing,\n\tautosave, allowResize, borderless, debug, debugUi, fpsCounter, newSeedOnLoad, keepAspectRatio, nonSquarePixelRatio,\n\tcursorInBlackBandsInFullscreen, cursorInBlackBandsInWindow, cursorInBlackBandsInBorderlessWindow, maximizeInfoScreens, musicAlwaysLoop, StereoSound, verboseLogging, soldierDiaries, touchEnabled,\n\trootWindowedMode, lazyLoadResources, backgroundMute;\nOPT std::string language, useOpenGLShader;\nOPT KeyboardType keyboardMode;\nOPT SaveSort saveOrder;\nOPT MusicFormat preferredMusic;\nOPT SoundFormat preferredSound;\nOPT VideoFormat preferredVideo;\nOPT SDL_GrabMode captureMouse;\nOPT TextWrapping wordwrap;\nOPT SDLKey keyOk, keyCancel, keyScreenshot, keyFps, keyQuickLoad, keyQuickSave;\n\n// Geoscape options\nOPT int geoClockSpeed, dogfightSpeed, geoScrollSpeed, geoDragScrollButton, geoscapeScale;\nOPT bool includePrimeStateInSavedLayout, anytimePsiTraining, weaponSelfDestruction, retainCorpses, craftLaunchAlways,\n\tglobeSurfaceCache, globeSeasons, globeDetail, globeRadarLines, globeFlightPaths, globeAllRadarsOnBaseBuild,\n\tstorageLimitsEnforced, canSellLiveAliens, canTransferCraftsWhileAirborne, customInitialBase, aggressiveRetaliation, geoDragScrollInvert,\n\tallowBuildingQueue, showFundsOnGeoscape, psiStrengthEval, allowPsiStrengthImprovement, fieldPromotions, meetingPoint;\nOPT SDLKey keyGeoLeft, keyGeoRight, keyGeoUp, keyGeoDown, keyGeoZoomIn, keyGeoZoomOut, keyGeoSpeed1, keyGeoSpeed2, keyGeoSpeed3, keyGeoSpeed4, keyGeoSpeed5, keyGeoSpeed6,\n\tkeyGeoIntercept, keyGeoBases, keyGeoGraphs, keyGeoUfopedia, keyGeoOptions, keyGeoFunding, keyGeoToggleDetail, keyGeoToggleRadar,\n\tkeyBaseSelect1, keyBaseSelect2, keyBaseSelect3, keyBaseSelect4, keyBaseSelect5, keyBaseSelect6, keyBaseSelect7, keyBaseSelect8;\n\n// Battlescape options\nOPT ScrollType battleEdgeScroll;\nOPT PathPreview battleNewPreviewPath;\nOPT int battleScrollSpeed, battleDragScrollButton, battleFireSpeed, battleXcomSpeed, battleAlienSpeed, battleExplosionHeight, battlescapeScale;\nOPT bool traceAI, sneakyAI, battleInstantGrenade, battleNotifyDeath, battleTooltips, battleHairBleach, battleAutoEnd,\n\tstrafe, forceFire, showMoreStatsInInventoryView, allowPsionicCapture, skipNextTurnScreen, disableAutoEquip, battleDragScrollInvert,\n\tbattleUFOExtenderAccuracy, battleConfirmFireMode, battleSmoothCamera, noAlienPanicMessages, alienBleeding;\nOPT SDLKey keyBattleLeft, keyBattleRight, keyBattleUp, keyBattleDown, keyBattleLevelUp, keyBattleLevelDown, keyBattleCenterUnit, keyBattlePrevUnit, keyBattleNextUnit, keyBattleDeselectUnit,\nkeyBattleUseLeftHand, keyBattleUseRightHand, keyBattleInventory, keyBattleMap, keyBattleOptions, keyBattleEndTurn, keyBattleAbort, keyBattleStats, keyBattleKneel,\nkeyBattleReserveKneel, keyBattleReload, keyBattlePersonalLighting, keyBattleReserveNone, keyBattleReserveSnap, keyBattleReserveAimed, keyBattleReserveAuto,\nkeyBattleCenterEnemy1, keyBattleCenterEnemy2, keyBattleCenterEnemy3, keyBattleCenterEnemy4, keyBattleCenterEnemy5, keyBattleCenterEnemy6, keyBattleCenterEnemy7, keyBattleCenterEnemy8,\nkeyBattleCenterEnemy9, keyBattleCenterEnemy10, keyBattleVoxelView, keyBattleZeroTUs, keyInvCreateTemplate, keyInvApplyTemplate, keyInvClear, keyInvAutoEquip;\n\n// Extra hotkeys (OXCE)\nOPT SDLKey keyGeoDailyPilotExperience, keyGeoUfoTracker, keyGeoTechTreeViewer, keyGeoGlobalResearch, keyGeoGlobalProduction, keyGeoGlobalAlienContainment,\n\tkeyGraphsZoomIn, keyGraphsZoomOut,\n\tkeyToggleQuickSearch, keyInstaSave,\n\tkeyCraftLoadoutSave, keyCraftLoadoutLoad,\n\tkeyMarkAllAsSeen,\n\tkeySellAll, keySellAllButOne,\n\tkeyTransferAll,\n\tkeyRemoveSoldiersFromCraft, keyRemoveSoldiersFromAllCrafts,\n\tkeyRemoveEquipmentFromCraft,\n\tkeyRemoveArmorFromCraft, keyRemoveArmorFromAllCrafts,\n\tkeyRemoveSoldiersFromTraining, keyAddSoldiersToTraining,\n\tkeyInventoryArmor, keyInventoryAvatar, keyInventoryDiaryLight, keyInventorySave, keyInventoryLoad,\n\tkeyInvSavePersonalEquipment, keyInvLoadPersonalEquipment, keyInvShowPersonalEquipment,\n\tkeyBattleUnitUp, keyBattleUnitDown,\n\tkeyBattleShowLayers,\n\tkeyBattleUseSpecial,\n\tkeyBattleActionItem1, keyBattleActionItem2, keyBattleActionItem3, keyBattleActionItem4, keyBattleActionItem5,\n\tkeyNightVisionToggle, keyNightVisionHold, keySelectMusicTrack;\nOPT SDLKey keyBasescapeBuildNewBase, keyBasescapeBaseInfo, keyBasescapeSoldiers, keyBasescapeCrafts,\n\tkeyBasescapeFacilities, keyBasescapeResearch, keyBasescapeManufacture, keyBasescapeTransfer,\n\tkeyBasescapePurchase, keyBasescapeSell;\n\n// OXCE, accessible via GUI\nOPT bool oxceUpdateCheck;\nOPT int autosaveSlots;\nOPT int oxceGeoAutosaveFrequency;\nOPT int oxceGeoAutosaveSlots;\nOPT bool oxceLinks;\nOPT bool oxceLinksDisableTextEdit;\nOPT bool oxceFatFingerLinks;\nOPT bool oxceBattleTouchButtonsEnabled;\nOPT bool oxceQuickSearchButton;\nOPT bool oxceHighlightNewTopics;\nOPT bool oxcePediaShowClipSize;\nOPT int oxcePediaSortResistances; // hidden, unhide if becomes popular?\n\nOPT int oxceInterceptTableSize;\nOPT bool oxceEnableSlackingIndicator;\nOPT int oxceInterceptGuiMaintenanceTime;\nOPT int oxceShowETAMode;\nOPT bool oxceUfoLandingAlert;\nOPT bool oxceRememberDisabledCraftWeapons;\nOPT bool oxceGeoscapeEventsInstantDelivery;\nOPT bool oxceShowBaseNameInPopups;\n\nOPT bool oxceAlternateCraftEquipmentManagement;\nOPT bool oxceBaseInfoScaleEnabled;\nOPT int oxceResearchScrollSpeed;\nOPT int oxceResearchScrollSpeedWithCtrl;\nOPT bool oxceManufactureFilterSuppliesOK;\nOPT int oxceManufactureScrollSpeed;\nOPT int oxceManufactureScrollSpeedWithCtrl;\nOPT bool oxcePersonalLayoutIncludingArmor;\nOPT bool oxceManualPromotions;\n\nOPT int oxceWoundedDefendBaseIf;\nOPT bool oxcePlayBriefingMusicDuringEquipment;\nOPT int oxceNightVisionColor;\nOPT int oxceAutoNightVisionThreshold;\nOPT int oxceShowAccuracyOnCrosshair;\nOPT int oxceReactionFireThreshold;\nOPT bool oxceAutoSell;\nOPT bool oxceAutomaticPromotions;\nOPT bool oxceEnableOffCentreShooting;\nOPT bool oxceUniformShootingSpread;\nOPT int oxceCrashedOrLanded;\n\n// OXCE hidden, accessible only via options.cfg\n/**\n * Verification level of mod data.\n * Same levels supported as `SeverityLevel`.\n */\nOPT int oxceModValidationLevel;\nOPT bool oxceRawScreenShots;\nOPT bool oxceFirstPersonViewFisheyeProjection;\nOPT bool oxceThumbButtons;\nOPT int oxceThrottleMouseMoveEvent;\nOPT bool oxceDisableThinkingProgressBar;\n\nOPT bool oxceEmbeddedOnly;\nOPT bool oxceListVFSContents;\nOPT bool oxceEnablePaletteFlickerFix;\nOPT bool oxceRecommendedOptionsWereSet;\nOPT std::string password;\n\n// OXCE hidden, but moddable via fixedUserOptions and/or recommendedUserOptions\nOPT int oxceStartUpTextMode;\n\nOPT int oxceGeoscapeDebugLogMaxEntries;\nOPT int oxceGeoSlowdownFactor;\nOPT bool oxceGeoShowScoreInsteadOfFunds;\nOPT bool oxceGeoEnableTrainingIndicator;\nOPT bool oxceGeoSuppressRedundantHKAlert;\nOPT bool oxceGeoSuppressLandingWithoutEquipment;\nOPT bool oxceGeoGoToNearestBase;\nOPT bool oxceGeoSortCraftByDistanceToTarget;\n\nOPT int oxceBaseInfoDefenseScaleMultiplier;\nOPT bool oxceBaseSoldierTransformationShowOnlyEligible;\nOPT bool oxceBaseFilterResearchable;\nOPT bool oxceBaseResearchReorder;\nOPT bool oxceBaseManufactureFallbackButton;\nOPT bool oxceBaseManufactureInfinityButton;\nOPT bool oxceBaseTouchButtons;\n\nOPT bool oxceDisableAlienInventory;\nOPT bool oxceDisableHitLog;\nOPT bool oxceDisableInventoryTuCost;\nOPT bool oxceDisableProductionDependencyTree;\nOPT bool oxceDisableStatsForNerds;\nOPT bool oxceDisableTechTreeViewer;\n\n// 0 = not persisted; 1 = persisted per battle; 2 = persisted per campaign\nOPT int oxceTogglePersonalLightType;\nOPT int oxceToggleNightVisionType;\nOPT int oxceToggleBrightnessType;\n\nOPT bool oxceShowBurningAsWounded;\nOPT bool oxceDisableInfoOnThrowCursor;\nOPT bool oxceSwapDontReselectActions;\nOPT bool oxceEnableUnitResponseSounds;\nOPT int oxceHiddenMovementBackgroundChangeFrequency;\nOPT bool oxceInventoryShowUnitSlot;\nOPT bool oxceReplaceNotesLink;\n\nOPT bool oxceInventorySplitScrollButton;\nOPT bool oxceInventoryDropItemOverPaperdoll;\nOPT bool oxceInventoryUnloadFixedWeapons;\n\nOPT int oxceMaxEquipmentLayoutTemplates;\n\n// Flags and other stuff that don't need OptionInfo's.\nOPT bool mute, reload, newOpenGL, newScaleFilter, newHQXFilter, newXBRZFilter, newRootWindowedMode, newFullscreen, newAllowResize, newBorderless;\nOPT int newDisplayWidth, newDisplayHeight, newBattlescapeScale, newGeoscapeScale, newWindowedModePositionX, newWindowedModePositionY;\nOPT std::string newOpenGLShader;\nOPT std::vector< std::pair<std::string, bool> > mods; // ordered list of available mods (lowest priority to highest) and whether they are active\nOPT SoundFormat currentSound;\n\nOPT int battleXcomSpeedOrig;\nOPT int battleAlienSpeedOrig;\n"
  },
  {
    "path": "src/Engine/Palette.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Palette.h\"\n#include <sstream>\n#include \"CrossPlatform.h\"\n#include \"Exception.h\"\n#include \"FileMap.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes a brand new palette.\n */\nPalette::Palette() : _colors(0), _count(0)\n{\n}\n\n/**\n * Deletes any colors contained within.\n */\nPalette::~Palette()\n{\n\tdelete[] _colors;\n}\n\n/**\n * Loads an X-Com palette from a file. X-Com palettes are just a set\n * of RGB colors in a row, on a 0-63 scale, which have to be adjusted\n * for modern computers (0-255 scale).\n * @param filename Filename of the palette.\n * @param ncolors Number of colors in the palette.\n * @param offset Position of the palette in the file (in bytes).\n * @sa http://www.ufopaedia.org/index.php?title=PALETTES.DAT\n */\nvoid Palette::loadDat(const std::string &filename, int ncolors, int offset)\n{\n\tauto palFile = FileMap::getIStream(filename);\n\tif (_colors != 0)\n\t\tthrow Exception(\"loadDat can be run only once\");\n\t_count = ncolors;\n\t_colors = new SDL_Color[_count];\n\tmemset(_colors, 0, sizeof(SDL_Color) * _count);\n\n\t// Move pointer to proper palette\n\tpalFile->seekg(offset, std::ios::beg);\n\n\tUint8 value[3];\n\n\tfor (int i = 0; i < _count && palFile->read((char*)value, 3); ++i)\n\t{\n\t\t// Correct X-Com colors to RGB colors\n\t\t_colors[i].r = value[0] * 4;\n\t\t_colors[i].g = value[1] * 4;\n\t\t_colors[i].b = value[2] * 4;\n\t\t_colors[i].unused = 255;\n\t}\n\t_colors[0].unused = 0;\n}\n\n/**\n * Initializes an all-black palette.\n */\nvoid Palette::initBlack()\n{\n\tif (_colors != 0)\n\t\tthrow Exception(\"initBlack can be run only once\");\n\t_count = 256;\n\t_colors = new SDL_Color[_count];\n\tmemset(_colors, 0, sizeof(SDL_Color) * _count);\n\n\tfor (int i = 0; i < _count; ++i)\n\t{\n\t\t_colors[i].r = 0;\n\t\t_colors[i].g = 0;\n\t\t_colors[i].b = 0;\n\t\t_colors[i].unused = 255;\n\t}\n\t_colors[0].unused = 0;\n}\n\n/**\n * Loads the colors from an existing palette.\n */\nvoid Palette::copyFrom(Palette *srcPal)\n{\n\tfor (int i = 0; i < srcPal->getColorCount(); i++)\n\t{\n\t\tsetColor(i, srcPal->getColors(i)->r, srcPal->getColors(i)->g, srcPal->getColors(i)->b);\n\t}\n}\n\n/**\n * Provides access to colors contained in the palette.\n * @param offset Offset to a specific color.\n * @return Pointer to the requested SDL_Color.\n */\nSDL_Color *Palette::getColors(int offset) const\n{\n\treturn _colors + offset;\n}\n\n/**\n * Converts an SDL_Color struct into an hexadecimal RGBA color value.\n * Mostly used for operations with SDL_gfx that require colors in this format.\n * @param pal Requested palette.\n * @param color Requested color in the palette.\n * @return Hexadecimal RGBA value.\n */\nUint32 Palette::getRGBA(SDL_Color* pal, Uint8 color)\n{\n\treturn ((Uint32) pal[color].r << 24) | ((Uint32) pal[color].g << 16) | ((Uint32) pal[color].b << 8) | (Uint32) 0xFF;\n}\n\nvoid Palette::savePal(const std::string &file) const\n{\n\tstd::stringstream out;\n\tshort count = _count;\n\n\t// RIFF header\n\tout << \"RIFF\";\n\tint length = 4 + 4 + 4 + 4 + 2 + 2 + count * 4;\n\tout.write((char*) &length, sizeof(length));\n\tout << \"PAL \";\n\n\t// Data chunk\n\tout << \"data\";\n\tint data = count * 4 + 4;\n\tout.write((char*) &data, sizeof(data));\n\tshort version = 0x0300;\n\tout.write((char*) &version, sizeof(version));\n\tout.write((char*) &count, sizeof(count));\n\n\t// Colors\n\tSDL_Color *color = getColors();\n\tfor (short i = 0; i < count; ++i)\n\t{\n\t\tchar c = 0;\n\t\tout.write((char*) &color->r, 1);\n\t\tout.write((char*) &color->g, 1);\n\t\tout.write((char*) &color->b, 1);\n\t\tout.write(&c, 1);\n\t\tcolor++;\n\t}\n\tCrossPlatform::writeFile(file, out.str());\n}\n\nvoid Palette::savePalMod(const std::string &file, const std::string &type, const std::string &target) const\n{\n\tstd::stringstream out;\n\tshort count = _count;\n\n\t// header\n\tout << \"customPalettes:\\n\";\n\tout << \"  - type: \" << type << \"\\n\";\n\tout << \"    target: \" << target << \"\\n\";\n\tout << \"    palette:\\n\";\n\n\t// Colors\n\tfor (int i = 0; i < count; ++i)\n\t{\n\t\tout << \"      \";\n\t\tout << std::to_string(i);\n\t\tout << \": [\";\n\t\tout << std::to_string(_colors[i].r);\n\t\tout << \",\";\n\t\tout << std::to_string(_colors[i].g);\n\t\tout << \",\";\n\t\tout << std::to_string(_colors[i].b);\n\t\tout << \"]\\n\";\n\t}\n\tCrossPlatform::writeFile(file, out.str());\n}\n\nvoid Palette::savePalJasc(const std::string &file) const\n{\n\tstd::stringstream out;\n\tshort count = _count;\n\n\t// header\n\tout << \"JASC-PAL\\n\";\n\tout << \"0100\\n\";\n\tout << \"256\\n\";\n\n\t// Colors\n\tfor (int i = 0; i < count; ++i)\n\t{\n\t\tout << std::to_string(_colors[i].r);\n\t\tout << \" \";\n\t\tout << std::to_string(_colors[i].g);\n\t\tout << \" \";\n\t\tout << std::to_string(_colors[i].b);\n\t\tout << \"\\n\";\n\t}\n\tCrossPlatform::writeFile(file, out.str());\n}\n\nvoid Palette::setColors(SDL_Color* pal, int ncolors)\n{\n\tif (_colors != 0)\n\t\tthrow Exception(\"setColors can be run only once\");\n\t_count = ncolors;\n\t_colors = new SDL_Color[_count];\n\tmemset(_colors, 0, sizeof(SDL_Color) * _count);\n\n\tfor (int i = 0; i < _count; ++i)\n\t{\n\t\t// TFTD's LBM colors are good the way they are - no need for adjustment here, except...\n\t\t_colors[i].r = pal[i].r;\n\t\t_colors[i].g = pal[i].g;\n\t\t_colors[i].b = pal[i].b;\n\t\t_colors[i].unused = 255;\n\t\tif (i > 15 && _colors[i].r == _colors[0].r &&\n\t\t\t_colors[i].g == _colors[0].g &&\n\t\t\t_colors[i].b == _colors[0].b)\n\t\t{\n\t\t\t// SDL \"optimizes\" surfaces by using RGB colour matching to reassign pixels to an \"earlier\" matching colour in the palette,\n\t\t\t// meaning any pixels in a surface that are meant to be black will be reassigned as colour 0, rendering them transparent.\n\t\t\t// avoid this eventuality by altering the \"later\" colours just enough to disambiguate them without causing them to look significantly different.\n\t\t\t// SDL 2.0 has some functionality that should render this hack unnecessary.\n\t\t\t_colors[i].r++;\n\t\t\t_colors[i].g++;\n\t\t\t_colors[i].b++;\n\t\t}\n\t}\n\t_colors[0].unused = 0;\n}\n\nvoid Palette::setColor(int index, int r, int g, int b)\n{\n\t_colors[index].r = r;\n\t_colors[index].g = g;\n\t_colors[index].b = b;\n\tif (index > 15 && _colors[index].r == _colors[0].r &&\n\t\t_colors[index].g == _colors[0].g &&\n\t\t_colors[index].b == _colors[0].b)\n\t{\n\t\t// SDL \"optimizes\" surfaces by using RGB colour matching to reassign pixels to an \"earlier\" matching colour in the palette,\n\t\t// meaning any pixels in a surface that are meant to be black will be reassigned as colour 0, rendering them transparent.\n\t\t// avoid this eventuality by altering the \"later\" colours just enough to disambiguate them without causing them to look significantly different.\n\t\t// SDL 2.0 has some functionality that should render this hack unnecessary.\n\t\t_colors[index].r++;\n\t\t_colors[index].g++;\n\t\t_colors[index].b++;\n\t}\n}\n\nvoid Palette::copyColor(int index, int r, int g, int b)\n{\n\t_colors[index].r = r;\n\t_colors[index].g = g;\n\t_colors[index].b = b;\n}\n\n}\n"
  },
  {
    "path": "src/Engine/Palette.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include <SDL.h>\n\nnamespace OpenXcom\n{\n\n/**\n * Container for palettes (sets of 8bpp colors).\n * Works as an encapsulation for SDL's SDL_Color struct and\n * provides shortcuts for common tasks to make code more readable.\n */\nclass Palette\n{\nprivate:\n\tSDL_Color *_colors;\n\tint _count;\npublic:\n\t/// Creates a blank palette.\n\tPalette();\n\t/// Cleans up the palette.\n\t~Palette();\n\t/// Loads the colors from an X-Com palette.\n\tvoid loadDat(const std::string &filename, int ncolors, int offset = 0);\n\t/// Initializes an all-black palette.\n\tvoid initBlack();\n\t/// Loads the colors from an existing palette.\n\tvoid copyFrom(Palette *srcPal);\n\t// Gets a certain color from the palette.\n\tSDL_Color *getColors(int offset = 0) const;\n\t// Gets a number of colors in the palette.\n\tint getColorCount() const { return _count; }\n\n\tvoid savePal(const std::string &file) const;\n\tvoid savePalMod(const std::string &file, const std::string &type, const std::string &target) const;\n\tvoid savePalJasc(const std::string &file) const;\n\tvoid setColors(SDL_Color* pal, int ncolors);\n\tvoid setColor(int index, int r, int g, int b);\n\tvoid copyColor(int index, int r, int g, int b);\n\t/// Converts a given color into a RGBA color value.\n\tstatic Uint32 getRGBA(SDL_Color* pal, Uint8 color);\n\t/// Gets the position of a given palette.\n\t/**\n\t * Returns the position of a palette inside an X-Com palette file (each is a 768-byte chunks).\n\t * Handy for loading the palettes from the game files.\n\t * @param palette Requested palette.\n\t * @return Palette position in bytes.\n\t */\n\tstatic inline int palOffset(int palette) { return palette*(768+6); }\n\t/// Gets the position of a certain color block in a palette.\n\t/**\n\t * Returns the position of a certain color block in an X-Com palette (they're usually split in 16-color gradients).\n\t * Makes setting element colors a lot easier than determining the exact color position.\n\t * @param block Requested block.\n\t * @return Color position.\n\t */\n\tstatic inline Uint8 blockOffset(Uint8 block) { return block*16; }\n\t/// Position of the background colors block in an X-Com palette (used for background images in screens).\n\tstatic const int backPos = 224;\n};\n\n}\n"
  },
  {
    "path": "src/Engine/RNG.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"RNG.h\"\n#include <time.h>\n#ifndef UINT64_MAX\n#define UINT64_MAX 0xffffffffffffffffULL\n#endif\n\nnamespace OpenXcom\n{\nnamespace RNG\n{\n\n/*  Written in 2014 by Sebastiano Vigna (vigna@acm.org)\n\nTo the extent possible under law, the author has dedicated all copyright\nand related and neighboring rights to this software to the public domain\nworldwide. This software is distributed without any warranty.\n\nSee <http://creativecommons.org/publicdomain/zero/1.0/>. */\n\n/* This is a good generator if you're short on memory, but otherwise we\n   rather suggest to use a xorshift128+ (for maximum speed) or\n   xorshift1024* (for speed and very long period) generator. */\n\nstatic uint64_t nextImpl(uint64_t& state)\n{\n\tstate ^= state >> 12; // a\n\tstate ^= state << 25; // b\n\tstate ^= state >> 27; // c\n\treturn state * 2685821657736338717ULL;\n}\n\n\n\n\n/**\n * Default constructor initializing the seed by time and this type address.\n */\nRandomState::RandomState()\n{\n\t_seedState = time(0) ^ (~(uint64_t)&_seedState);\n}\n\n/**\n * Constructor from predefined seed.\n */\nRandomState::RandomState(uint64_t seed) : _seedState(seed)\n{\n\n}\n\n/**\n * Returns the current seed in use by the generator.\n * @return Current seed.\n */\nuint64_t RandomState::getSeed() const\n{\n\treturn _seedState;\n}\n\n/**\n * Get next random number.\n * @return Random number.\n */\nuint64_t RandomState::next()\n{\n\treturn nextImpl(_seedState);\n}\n\n/**\n * Generates a random integer number, inclusive.\n */\nint RandomState::generate(int min, int max)\n{\n\treturn (int)(next() % (max - min + 1) + min);\n}\n\n\n\n/**\n * State for game random number generator. Do not use during other variable static initialization because: https://isocpp.org/wiki/faq/ctors#static-init-order-on-first-use-members\n */\nRandomState x;\n\n/**\n * Separate state for some auxiliary random numbers that do not affect game state. Do not use during other variable static initialization because: https://isocpp.org/wiki/faq/ctors#static-init-order-on-first-use-members\n */\nRandomState x_seedless;\n\n\n\n\n/**\n * Returns the current seed in use by the generator.\n * @return Current seed.\n */\nuint64_t getSeed()\n{\n\treturn x.getSeed();\n}\n\n/**\n * Changes the current seed in use by the generator.\n * @param n New seed.\n */\nvoid setSeed(uint64_t n)\n{\n\tx = RandomState(n);\n}\n\n/**\n * State\n */\nRandomState& globalRandomState()\n{\n\treturn x;\n}\n\n/**\n * Generates a random integer number within a certain range.\n * @param min Minimum number, inclusive.\n * @param max Maximum number, inclusive.\n * @return Generated number.\n */\nint generate(int min, int max)\n{\n\treturn x.generate(min, max);\n}\n\n/**\n * Generates a random decimal number within a certain range.\n * @param min Minimum number.\n * @param max Maximum number.\n * @return Generated number.\n */\ndouble generate(double min, double max)\n{\n\tdouble num = x.next();\n\treturn (num / ((double)UINT64_MAX / (max - min)) + min);\n}\n\n/**\n * Generates a random integer number within a certain range.\n * Distinct from \"generate\" in that it doesn't touch the seed.\n * @param min Minimum number, inclusive.\n * @param max Maximum number, inclusive.\n * @return Generated number.\n */\nint seedless(int min, int max)\n{\n\treturn x_seedless.generate(min, max);\n}\n\n/**\n * Generates a random percent chance of an event occurring,\n * and returns the result\n * @param value Value percentage (0-100%)\n * @return True if the chance succeeded.\n */\nbool percent(int value)\n{\n\treturn x.percent(value);\n}\n\n}\n\n}\n"
  },
  {
    "path": "src/Engine/RNG.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <algorithm>\n#include <vector>\n#define __STDC_LIMIT_MACROS\n#include <stdint.h>\n\nnamespace OpenXcom\n{\n\n/**\n * Random Number Generator used throughout the game\n * for all your randomness needs. Uses a 64-bit xorshift\n * pseudorandom number generator.\n */\nnamespace RNG\n{\n\tclass RandomState\n\t{\n\t\t uint64_t _seedState;\n\n\tpublic:\n\t\t/// Default constructor initializing the seed by time and this type address.\n\t\tRandomState();\n\t\t/// Constructor from predefined seed.\n\t\texplicit RandomState(uint64_t seed);\n\t\t/// Get current seed.\n\t\tuint64_t getSeed() const;\n\n\t\t/// Get next random number.\n\t\tuint64_t next();\n\t\t/// Generates a random integer number, inclusive.\n\t\tint generate(int min, int max);\n\t\t///  Generates a percentage chance.\n\t\tbool percent(int value)\n\t\t{\n\t\t\treturn generate(0, 99) < value;\n\t\t}\n\t\t/// Get new random-sub-sequence, that depends on current seed but each time it creates a different sequence.\n\t\tRandomState subSequence()\n\t\t{\n\t\t\treturn RandomState{ next() ^ 0x055e3ac3461280cful}; //random value to have different new seed but still deterministic values when game run again.\n\t\t}\n\t};\n\n\t/// Gets the seed in use.\n\tuint64_t getSeed();\n\t/// Sets the seed in use.\n\tvoid setSeed(uint64_t n);\n\t/// Get state.\n\tRandomState& globalRandomState();\n\t/// Generates a random integer number, inclusive.\n\tint generate(int min, int max);\n\t/// Generates a random floating-point number.\n\tdouble generate(double min, double max);\n\t/// Generates a random integer number, inclusive (non-seed version).\n\tint seedless(int min, int max);\n\t/// Generates a percentage chance.\n\tbool percent(int value);\n\t/// Shuffles a list randomly.\n\t/**\n\t * Randomly changes the orders of the elements in a list.\n\t * @param list The container to randomize.\n\t */\n\ttemplate <typename T>\n\tvoid shuffle(std::vector<T> &list)\n\t{\n\t\tif (list.empty())\n\t\t\treturn;\n\t\tfor (size_t i = list.size() - 1; i > 0; --i)\n\t\t\tstd::swap(list[i], list[generate(0, i)]);\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Engine/SDL2Helpers.h",
    "content": "#pragma once\n#include <SDL_version.h>\n#include <SDL_rwops.h>\n\n/*\n * Bits of SDL2 API that are missing from SDL1\n * Implementations are in FileMap.cpp\n * To be removed with transition to SDL2\n */\n# if !SDL_VERSION_ATLEAST(2,0,0)\nextern \"C\"\n{\nUint8 SDL_ReadU8(SDL_RWops *src);\nSint64 SDL_RWsize(SDL_RWops *src);\n}\n# endif\n#if !SDL_VERSION_ATLEAST(2,0,6)\nextern \"C\"\n{\nvoid *SDL_LoadFile_RW(SDL_RWops *src, size_t *datasize, int freesrc);\n}\n#endif\n"
  },
  {
    "path": "src/Engine/Scalers/common.h",
    "content": "/*\n * Copyright (C) 2003 Maxim Stepin ( maxst@hiend3d.com )\n *\n * Copyright (C) 2010 Cameron Zemek ( grom@zeminvaders.net)\n * Copyright (C) 2011 Francois Gannaz <mytskine@gmail.com>\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n */\n\n#ifndef __HQX_COMMON_H_\n#define __HQX_COMMON_H_\n\n#include <stdlib.h>\n#include <stdint.h>\n\n#define MASK_2     0x0000FF00\n#define MASK_13    0x00FF00FF\n#define MASK_RGB   0x00FFFFFF\n#define MASK_ALPHA 0xFF000000\n\n#define Ymask 0x00FF0000\n#define Umask 0x0000FF00\n#define Vmask 0x000000FF\n#define trY   0x00300000\n#define trU   0x00000700\n#define trV   0x00000006\n\n/* RGB to YUV lookup table */\nextern uint32_t RGBtoYUV[16777216];\n\nstatic inline uint32_t rgb_to_yuv(uint32_t c)\n{\n    // Mask against MASK_RGB to discard the alpha channel\n    return RGBtoYUV[MASK_RGB & c];\n}\n\n\n/* Test if there is difference in color */\nstatic inline int yuv_diff(uint32_t yuv1, uint32_t yuv2) {\n    return (( abs((int)((yuv1 & Ymask) - (yuv2 & Ymask))) > trY ) ||\n            ( abs((int)((yuv1 & Umask) - (yuv2 & Umask))) > trU ) ||\n            ( abs((int)((yuv1 & Vmask) - (yuv2 & Vmask))) > trV ) );\n}\n\nstatic inline int Diff(uint32_t c1, uint32_t c2)\n{\n    return yuv_diff(rgb_to_yuv(c1), rgb_to_yuv(c2));\n}\n\n/* Interpolate functions */\nstatic inline uint32_t Interpolate_2(uint32_t c1, int w1, uint32_t c2, int w2, int s)\n{\n    if (c1 == c2)\n    {\n        return c1;\n    }\n    return\n        (((((c1 & MASK_ALPHA) >> 24) * w1 + ((c2 & MASK_ALPHA) >> 24) * w2) << (24-s)) & MASK_ALPHA) +\n        ((((c1 & MASK_2) * w1 + (c2 & MASK_2) * w2) >> s) & MASK_2)\t+\n        ((((c1 & MASK_13) * w1 + (c2 & MASK_13) * w2) >> s) & MASK_13);\n}\n\nstatic inline uint32_t Interpolate_3(uint32_t c1, int w1, uint32_t c2, int w2, uint32_t c3, int w3, int s)\n{\n    return\n        (((((c1 & MASK_ALPHA) >> 24) * w1 + ((c2 & MASK_ALPHA) >> 24) * w2 + ((c3 & MASK_ALPHA) >> 24) * w3) << (24-s)) & MASK_ALPHA) +\n        ((((c1 & MASK_2) * w1 + (c2 & MASK_2) * w2 + (c3 & MASK_2) * w3) >> s) & MASK_2) +\n        ((((c1 & MASK_13) * w1 + (c2 & MASK_13) * w2 + (c3 & MASK_13) * w3) >> s) & MASK_13);\n}\n\nstatic inline uint32_t Interp1(uint32_t c1, uint32_t c2)\n{\n    //(c1*3+c2) >> 2;\n    return Interpolate_2(c1, 3, c2, 1, 2);\n}\n\nstatic inline uint32_t Interp2(uint32_t c1, uint32_t c2, uint32_t c3)\n{\n    //(c1*2+c2+c3) >> 2;\n    return Interpolate_3(c1, 2, c2, 1, c3, 1, 2);\n}\n\nstatic inline uint32_t Interp3(uint32_t c1, uint32_t c2)\n{\n    //(c1*7+c2)/8;\n    return Interpolate_2(c1, 7, c2, 1, 3);\n}\n\nstatic inline uint32_t Interp4(uint32_t c1, uint32_t c2, uint32_t c3)\n{\n    //(c1*2+(c2+c3)*7)/16;\n    return Interpolate_3(c1, 2, c2, 7, c3, 7, 4);\n}\n\nstatic inline uint32_t Interp5(uint32_t c1, uint32_t c2)\n{\n    //(c1+c2) >> 1;\n    return Interpolate_2(c1, 1, c2, 1, 1);\n}\n\nstatic inline uint32_t Interp6(uint32_t c1, uint32_t c2, uint32_t c3)\n{\n    //(c1*5+c2*2+c3)/8;\n    return Interpolate_3(c1, 5, c2, 2, c3, 1, 3);\n}\n\nstatic inline uint32_t Interp7(uint32_t c1, uint32_t c2, uint32_t c3)\n{\n    //(c1*6+c2+c3)/8;\n    return Interpolate_3(c1, 6, c2, 1, c3, 1, 3);\n}\n\nstatic inline uint32_t Interp8(uint32_t c1, uint32_t c2)\n{\n    //(c1*5+c2*3)/8;\n    return Interpolate_2(c1, 5, c2, 3, 3);\n}\n\nstatic inline uint32_t Interp9(uint32_t c1, uint32_t c2, uint32_t c3)\n{\n    //(c1*2+(c2+c3)*3)/8;\n    return Interpolate_3(c1, 2, c2, 3, c3, 3, 3);\n}\n\nstatic inline uint32_t Interp10(uint32_t c1, uint32_t c2, uint32_t c3)\n{\n    //(c1*14+c2+c3)/16;\n    return Interpolate_3(c1, 14, c2, 1, c3, 1, 4);\n}\n\n#endif\n"
  },
  {
    "path": "src/Engine/Scalers/config.h",
    "content": "// ****************************************************************************\n// * This file is part of the HqMAME project. It is distributed under         *\n// * GNU General Public License: http://www.gnu.org/licenses/gpl-3.0          *\n// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved          *\n// *                                                                          *\n// * Additionally and as a special exception, the author gives permission     *\n// * to link the code of this program with the MAME library (or with modified *\n// * versions of MAME that use the same license as MAME), and distribute      *\n// * linked combinations including the two. You must obey the GNU General     *\n// * Public License in all respects for all of the code used other than MAME. *\n// * If you modify this file, you may extend this exception to your version   *\n// * of the file, but you are not obligated to do so. If you do not wish to   *\n// * do so, delete this exception statement from your version.                *\n// ****************************************************************************\n\n#ifndef XBRZ_CONFIG_HEADER_284578425345\n#define XBRZ_CONFIG_HEADER_284578425345\n\n//do NOT include any headers here! used by xBRZ_dll!!!\n\nnamespace xbrz\n{\nstruct ScalerCfg\n{\n    ScalerCfg() :\n        luminanceWeight(1),\n        equalColorTolerance(30),\n        dominantDirectionThreshold(3.6),\n        steepDirectionThreshold(2.2),\n        newTestAttribute(0) {}\n\n    double luminanceWeight;\n    double equalColorTolerance;\n    double dominantDirectionThreshold;\n    double steepDirectionThreshold;\n    double newTestAttribute; //unused; test new parameters\n};\n}\n\n#endif\n"
  },
  {
    "path": "src/Engine/Scalers/hq2x.cpp",
    "content": "/*\n * Copyright (C) 2003 Maxim Stepin ( maxst@hiend3d.com )\n *\n * Copyright (C) 2010 Cameron Zemek ( grom@zeminvaders.net)\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n */\n\n#include <stdint.h>\n#include \"common.h\"\n#include \"hqx.h\"\n\n#define PIXEL00_0     *dp = w[5];\n#define PIXEL00_10    *dp = Interp1(w[5], w[1]);\n#define PIXEL00_11    *dp = Interp1(w[5], w[4]);\n#define PIXEL00_12    *dp = Interp1(w[5], w[2]);\n#define PIXEL00_20    *dp = Interp2(w[5], w[4], w[2]);\n#define PIXEL00_21    *dp = Interp2(w[5], w[1], w[2]);\n#define PIXEL00_22    *dp = Interp2(w[5], w[1], w[4]);\n#define PIXEL00_60    *dp = Interp6(w[5], w[2], w[4]);\n#define PIXEL00_61    *dp = Interp6(w[5], w[4], w[2]);\n#define PIXEL00_70    *dp = Interp7(w[5], w[4], w[2]);\n#define PIXEL00_90    *dp = Interp9(w[5], w[4], w[2]);\n#define PIXEL00_100   *dp = Interp10(w[5], w[4], w[2]);\n#define PIXEL01_0     *(dp+1) = w[5];\n#define PIXEL01_10    *(dp+1) = Interp1(w[5], w[3]);\n#define PIXEL01_11    *(dp+1) = Interp1(w[5], w[2]);\n#define PIXEL01_12    *(dp+1) = Interp1(w[5], w[6]);\n#define PIXEL01_20    *(dp+1) = Interp2(w[5], w[2], w[6]);\n#define PIXEL01_21    *(dp+1) = Interp2(w[5], w[3], w[6]);\n#define PIXEL01_22    *(dp+1) = Interp2(w[5], w[3], w[2]);\n#define PIXEL01_60    *(dp+1) = Interp6(w[5], w[6], w[2]);\n#define PIXEL01_61    *(dp+1) = Interp6(w[5], w[2], w[6]);\n#define PIXEL01_70    *(dp+1) = Interp7(w[5], w[2], w[6]);\n#define PIXEL01_90    *(dp+1) = Interp9(w[5], w[2], w[6]);\n#define PIXEL01_100   *(dp+1) = Interp10(w[5], w[2], w[6]);\n#define PIXEL10_0     *(dp+dpL) = w[5];\n#define PIXEL10_10    *(dp+dpL) = Interp1(w[5], w[7]);\n#define PIXEL10_11    *(dp+dpL) = Interp1(w[5], w[8]);\n#define PIXEL10_12    *(dp+dpL) = Interp1(w[5], w[4]);\n#define PIXEL10_20    *(dp+dpL) = Interp2(w[5], w[8], w[4]);\n#define PIXEL10_21    *(dp+dpL) = Interp2(w[5], w[7], w[4]);\n#define PIXEL10_22    *(dp+dpL) = Interp2(w[5], w[7], w[8]);\n#define PIXEL10_60    *(dp+dpL) = Interp6(w[5], w[4], w[8]);\n#define PIXEL10_61    *(dp+dpL) = Interp6(w[5], w[8], w[4]);\n#define PIXEL10_70    *(dp+dpL) = Interp7(w[5], w[8], w[4]);\n#define PIXEL10_90    *(dp+dpL) = Interp9(w[5], w[8], w[4]);\n#define PIXEL10_100   *(dp+dpL) = Interp10(w[5], w[8], w[4]);\n#define PIXEL11_0     *(dp+dpL+1) = w[5];\n#define PIXEL11_10    *(dp+dpL+1) = Interp1(w[5], w[9]);\n#define PIXEL11_11    *(dp+dpL+1) = Interp1(w[5], w[6]);\n#define PIXEL11_12    *(dp+dpL+1) = Interp1(w[5], w[8]);\n#define PIXEL11_20    *(dp+dpL+1) = Interp2(w[5], w[6], w[8]);\n#define PIXEL11_21    *(dp+dpL+1) = Interp2(w[5], w[9], w[8]);\n#define PIXEL11_22    *(dp+dpL+1) = Interp2(w[5], w[9], w[6]);\n#define PIXEL11_60    *(dp+dpL+1) = Interp6(w[5], w[8], w[6]);\n#define PIXEL11_61    *(dp+dpL+1) = Interp6(w[5], w[6], w[8]);\n#define PIXEL11_70    *(dp+dpL+1) = Interp7(w[5], w[6], w[8]);\n#define PIXEL11_90    *(dp+dpL+1) = Interp9(w[5], w[6], w[8]);\n#define PIXEL11_100   *(dp+dpL+1) = Interp10(w[5], w[6], w[8]);\n\nHQX_API void HQX_CALLCONV hq2x_32_rb(const uint32_t* sp, uint32_t srb, uint32_t* dp, uint32_t drb, int Xres, int Yres )\n{\n    int  i, j, k;\n    int  prevline, nextline;\n    uint32_t  w[10];\n    int dpL = (drb >> 2);\n    int spL = (srb >> 2);\n    const uint8_t* sRowP = (const uint8_t*) sp;\n    const uint8_t* dRowP = (const uint8_t*) dp;\n    uint32_t yuv1, yuv2;\n\n    //   +----+----+----+\n    //   |    |    |    |\n    //   | w1 | w2 | w3 |\n    //   +----+----+----+\n    //   |    |    |    |\n    //   | w4 | w5 | w6 |\n    //   +----+----+----+\n    //   |    |    |    |\n    //   | w7 | w8 | w9 |\n    //   +----+----+----+\n\n    for (j=0; j<Yres; j++)\n    {\n        if (j>0)      prevline = -spL;\n        else prevline = 0;\n        if (j<Yres-1) nextline =  spL;\n        else nextline = 0;\n\n        for (i=0; i<Xres; i++)\n        {\n            w[2] = *(sp + prevline);\n            w[5] = *sp;\n            w[8] = *(sp + nextline);\n\n            if (i>0)\n            {\n                w[1] = *(sp + prevline - 1);\n                w[4] = *(sp - 1);\n                w[7] = *(sp + nextline - 1);\n            }\n            else\n            {\n                w[1] = w[2];\n                w[4] = w[5];\n                w[7] = w[8];\n            }\n\n            if (i<Xres-1)\n            {\n                w[3] = *(sp + prevline + 1);\n                w[6] = *(sp + 1);\n                w[9] = *(sp + nextline + 1);\n            }\n            else\n            {\n                w[3] = w[2];\n                w[6] = w[5];\n                w[9] = w[8];\n            }\n\n            int pattern = 0;\n            int flag = 1;\n\n            yuv1 = rgb_to_yuv(w[5]);\n\n            for (k=1; k<=9; k++)\n            {\n                if (k==5) continue;\n\n                if ( w[k] != w[5] )\n                {\n                    yuv2 = rgb_to_yuv(w[k]);\n                    if (yuv_diff(yuv1, yuv2))\n                        pattern |= flag;\n                }\n                flag <<= 1;\n            }\n\n            switch (pattern)\n            {\n                case 0:\n                case 1:\n                case 4:\n                case 32:\n                case 128:\n                case 5:\n                case 132:\n                case 160:\n                case 33:\n                case 129:\n                case 36:\n                case 133:\n                case 164:\n                case 161:\n                case 37:\n                case 165:\n                {\n                    PIXEL00_20\n                    PIXEL01_20\n                    PIXEL10_20\n                    PIXEL11_20\n                    break;\n                }\n                case 2:\n                case 34:\n                case 130:\n                case 162:\n                {\n                    PIXEL00_22\n                    PIXEL01_21\n                    PIXEL10_20\n                    PIXEL11_20\n                    break;\n                }\n                case 16:\n                case 17:\n                case 48:\n                case 49:\n                {\n                    PIXEL00_20\n                    PIXEL01_22\n                    PIXEL10_20\n                    PIXEL11_21\n                    break;\n                }\n                case 64:\n                case 65:\n                case 68:\n                case 69:\n                {\n                    PIXEL00_20\n                    PIXEL01_20\n                    PIXEL10_21\n                    PIXEL11_22\n                    break;\n                }\n                case 8:\n                case 12:\n                case 136:\n                case 140:\n                {\n                    PIXEL00_21\n                    PIXEL01_20\n                    PIXEL10_22\n                    PIXEL11_20\n                    break;\n                }\n                case 3:\n                case 35:\n                case 131:\n                case 163:\n                {\n                    PIXEL00_11\n                    PIXEL01_21\n                    PIXEL10_20\n                    PIXEL11_20\n                    break;\n                }\n                case 6:\n                case 38:\n                case 134:\n                case 166:\n                {\n                    PIXEL00_22\n                    PIXEL01_12\n                    PIXEL10_20\n                    PIXEL11_20\n                    break;\n                }\n                case 20:\n                case 21:\n                case 52:\n                case 53:\n                {\n                    PIXEL00_20\n                    PIXEL01_11\n                    PIXEL10_20\n                    PIXEL11_21\n                    break;\n                }\n                case 144:\n                case 145:\n                case 176:\n                case 177:\n                {\n                    PIXEL00_20\n                    PIXEL01_22\n                    PIXEL10_20\n                    PIXEL11_12\n                    break;\n                }\n                case 192:\n                case 193:\n                case 196:\n                case 197:\n                {\n                    PIXEL00_20\n                    PIXEL01_20\n                    PIXEL10_21\n                    PIXEL11_11\n                    break;\n                }\n                case 96:\n                case 97:\n                case 100:\n                case 101:\n                {\n                    PIXEL00_20\n                    PIXEL01_20\n                    PIXEL10_12\n                    PIXEL11_22\n                    break;\n                }\n                case 40:\n                case 44:\n                case 168:\n                case 172:\n                {\n                    PIXEL00_21\n                    PIXEL01_20\n                    PIXEL10_11\n                    PIXEL11_20\n                    break;\n                }\n                case 9:\n                case 13:\n                case 137:\n                case 141:\n                {\n                    PIXEL00_12\n                    PIXEL01_20\n                    PIXEL10_22\n                    PIXEL11_20\n                    break;\n                }\n                case 18:\n                case 50:\n                {\n                    PIXEL00_22\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_10\n                    }\n                    else\n                    {\n                        PIXEL01_20\n                    }\n                    PIXEL10_20\n                    PIXEL11_21\n                    break;\n                }\n                case 80:\n                case 81:\n                {\n                    PIXEL00_20\n                    PIXEL01_22\n                    PIXEL10_21\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL11_10\n                    }\n                    else\n                    {\n                        PIXEL11_20\n                    }\n                    break;\n                }\n                case 72:\n                case 76:\n                {\n                    PIXEL00_21\n                    PIXEL01_20\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_10\n                    }\n                    else\n                    {\n                        PIXEL10_20\n                    }\n                    PIXEL11_22\n                    break;\n                }\n                case 10:\n                case 138:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_10\n                    }\n                    else\n                    {\n                        PIXEL00_20\n                    }\n                    PIXEL01_21\n                    PIXEL10_22\n                    PIXEL11_20\n                    break;\n                }\n                case 66:\n                {\n                    PIXEL00_22\n                    PIXEL01_21\n                    PIXEL10_21\n                    PIXEL11_22\n                    break;\n                }\n                case 24:\n                {\n                    PIXEL00_21\n                    PIXEL01_22\n                    PIXEL10_22\n                    PIXEL11_21\n                    break;\n                }\n                case 7:\n                case 39:\n                case 135:\n                {\n                    PIXEL00_11\n                    PIXEL01_12\n                    PIXEL10_20\n                    PIXEL11_20\n                    break;\n                }\n                case 148:\n                case 149:\n                case 180:\n                {\n                    PIXEL00_20\n                    PIXEL01_11\n                    PIXEL10_20\n                    PIXEL11_12\n                    break;\n                }\n                case 224:\n                case 228:\n                case 225:\n                {\n                    PIXEL00_20\n                    PIXEL01_20\n                    PIXEL10_12\n                    PIXEL11_11\n                    break;\n                }\n                case 41:\n                case 169:\n                case 45:\n                {\n                    PIXEL00_12\n                    PIXEL01_20\n                    PIXEL10_11\n                    PIXEL11_20\n                    break;\n                }\n                case 22:\n                case 54:\n                {\n                    PIXEL00_22\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_0\n                    }\n                    else\n                    {\n                        PIXEL01_20\n                    }\n                    PIXEL10_20\n                    PIXEL11_21\n                    break;\n                }\n                case 208:\n                case 209:\n                {\n                    PIXEL00_20\n                    PIXEL01_22\n                    PIXEL10_21\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL11_0\n                    }\n                    else\n                    {\n                        PIXEL11_20\n                    }\n                    break;\n                }\n                case 104:\n                case 108:\n                {\n                    PIXEL00_21\n                    PIXEL01_20\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_0\n                    }\n                    else\n                    {\n                        PIXEL10_20\n                    }\n                    PIXEL11_22\n                    break;\n                }\n                case 11:\n                case 139:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                    }\n                    else\n                    {\n                        PIXEL00_20\n                    }\n                    PIXEL01_21\n                    PIXEL10_22\n                    PIXEL11_20\n                    break;\n                }\n                case 19:\n                case 51:\n                {\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL00_11\n                        PIXEL01_10\n                    }\n                    else\n                    {\n                        PIXEL00_60\n                        PIXEL01_90\n                    }\n                    PIXEL10_20\n                    PIXEL11_21\n                    break;\n                }\n                case 146:\n                case 178:\n                {\n                    PIXEL00_22\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_10\n                        PIXEL11_12\n                    }\n                    else\n                    {\n                        PIXEL01_90\n                        PIXEL11_61\n                    }\n                    PIXEL10_20\n                    break;\n                }\n                case 84:\n                case 85:\n                {\n                    PIXEL00_20\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL01_11\n                        PIXEL11_10\n                    }\n                    else\n                    {\n                        PIXEL01_60\n                        PIXEL11_90\n                    }\n                    PIXEL10_21\n                    break;\n                }\n                case 112:\n                case 113:\n                {\n                    PIXEL00_20\n                    PIXEL01_22\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL10_12\n                        PIXEL11_10\n                    }\n                    else\n                    {\n                        PIXEL10_61\n                        PIXEL11_90\n                    }\n                    break;\n                }\n                case 200:\n                case 204:\n                {\n                    PIXEL00_21\n                    PIXEL01_20\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_10\n                        PIXEL11_11\n                    }\n                    else\n                    {\n                        PIXEL10_90\n                        PIXEL11_60\n                    }\n                    break;\n                }\n                case 73:\n                case 77:\n                {\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL00_12\n                        PIXEL10_10\n                    }\n                    else\n                    {\n                        PIXEL00_61\n                        PIXEL10_90\n                    }\n                    PIXEL01_20\n                    PIXEL11_22\n                    break;\n                }\n                case 42:\n                case 170:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_10\n                        PIXEL10_11\n                    }\n                    else\n                    {\n                        PIXEL00_90\n                        PIXEL10_60\n                    }\n                    PIXEL01_21\n                    PIXEL11_20\n                    break;\n                }\n                case 14:\n                case 142:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_10\n                        PIXEL01_12\n                    }\n                    else\n                    {\n                        PIXEL00_90\n                        PIXEL01_61\n                    }\n                    PIXEL10_22\n                    PIXEL11_20\n                    break;\n                }\n                case 67:\n                {\n                    PIXEL00_11\n                    PIXEL01_21\n                    PIXEL10_21\n                    PIXEL11_22\n                    break;\n                }\n                case 70:\n                {\n                    PIXEL00_22\n                    PIXEL01_12\n                    PIXEL10_21\n                    PIXEL11_22\n                    break;\n                }\n                case 28:\n                {\n                    PIXEL00_21\n                    PIXEL01_11\n                    PIXEL10_22\n                    PIXEL11_21\n                    break;\n                }\n                case 152:\n                {\n                    PIXEL00_21\n                    PIXEL01_22\n                    PIXEL10_22\n                    PIXEL11_12\n                    break;\n                }\n                case 194:\n                {\n                    PIXEL00_22\n                    PIXEL01_21\n                    PIXEL10_21\n                    PIXEL11_11\n                    break;\n                }\n                case 98:\n                {\n                    PIXEL00_22\n                    PIXEL01_21\n                    PIXEL10_12\n                    PIXEL11_22\n                    break;\n                }\n                case 56:\n                {\n                    PIXEL00_21\n                    PIXEL01_22\n                    PIXEL10_11\n                    PIXEL11_21\n                    break;\n                }\n                case 25:\n                {\n                    PIXEL00_12\n                    PIXEL01_22\n                    PIXEL10_22\n                    PIXEL11_21\n                    break;\n                }\n                case 26:\n                case 31:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                    }\n                    else\n                    {\n                        PIXEL00_20\n                    }\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_0\n                    }\n                    else\n                    {\n                        PIXEL01_20\n                    }\n                    PIXEL10_22\n                    PIXEL11_21\n                    break;\n                }\n                case 82:\n                case 214:\n                {\n                    PIXEL00_22\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_0\n                    }\n                    else\n                    {\n                        PIXEL01_20\n                    }\n                    PIXEL10_21\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL11_0\n                    }\n                    else\n                    {\n                        PIXEL11_20\n                    }\n                    break;\n                }\n                case 88:\n                case 248:\n                {\n                    PIXEL00_21\n                    PIXEL01_22\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_0\n                    }\n                    else\n                    {\n                        PIXEL10_20\n                    }\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL11_0\n                    }\n                    else\n                    {\n                        PIXEL11_20\n                    }\n                    break;\n                }\n                case 74:\n                case 107:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                    }\n                    else\n                    {\n                        PIXEL00_20\n                    }\n                    PIXEL01_21\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_0\n                    }\n                    else\n                    {\n                        PIXEL10_20\n                    }\n                    PIXEL11_22\n                    break;\n                }\n                case 27:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                    }\n                    else\n                    {\n                        PIXEL00_20\n                    }\n                    PIXEL01_10\n                    PIXEL10_22\n                    PIXEL11_21\n                    break;\n                }\n                case 86:\n                {\n                    PIXEL00_22\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_0\n                    }\n                    else\n                    {\n                        PIXEL01_20\n                    }\n                    PIXEL10_21\n                    PIXEL11_10\n                    break;\n                }\n                case 216:\n                {\n                    PIXEL00_21\n                    PIXEL01_22\n                    PIXEL10_10\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL11_0\n                    }\n                    else\n                    {\n                        PIXEL11_20\n                    }\n                    break;\n                }\n                case 106:\n                {\n                    PIXEL00_10\n                    PIXEL01_21\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_0\n                    }\n                    else\n                    {\n                        PIXEL10_20\n                    }\n                    PIXEL11_22\n                    break;\n                }\n                case 30:\n                {\n                    PIXEL00_10\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_0\n                    }\n                    else\n                    {\n                        PIXEL01_20\n                    }\n                    PIXEL10_22\n                    PIXEL11_21\n                    break;\n                }\n                case 210:\n                {\n                    PIXEL00_22\n                    PIXEL01_10\n                    PIXEL10_21\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL11_0\n                    }\n                    else\n                    {\n                        PIXEL11_20\n                    }\n                    break;\n                }\n                case 120:\n                {\n                    PIXEL00_21\n                    PIXEL01_22\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_0\n                    }\n                    else\n                    {\n                        PIXEL10_20\n                    }\n                    PIXEL11_10\n                    break;\n                }\n                case 75:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                    }\n                    else\n                    {\n                        PIXEL00_20\n                    }\n                    PIXEL01_21\n                    PIXEL10_10\n                    PIXEL11_22\n                    break;\n                }\n                case 29:\n                {\n                    PIXEL00_12\n                    PIXEL01_11\n                    PIXEL10_22\n                    PIXEL11_21\n                    break;\n                }\n                case 198:\n                {\n                    PIXEL00_22\n                    PIXEL01_12\n                    PIXEL10_21\n                    PIXEL11_11\n                    break;\n                }\n                case 184:\n                {\n                    PIXEL00_21\n                    PIXEL01_22\n                    PIXEL10_11\n                    PIXEL11_12\n                    break;\n                }\n                case 99:\n                {\n                    PIXEL00_11\n                    PIXEL01_21\n                    PIXEL10_12\n                    PIXEL11_22\n                    break;\n                }\n                case 57:\n                {\n                    PIXEL00_12\n                    PIXEL01_22\n                    PIXEL10_11\n                    PIXEL11_21\n                    break;\n                }\n                case 71:\n                {\n                    PIXEL00_11\n                    PIXEL01_12\n                    PIXEL10_21\n                    PIXEL11_22\n                    break;\n                }\n                case 156:\n                {\n                    PIXEL00_21\n                    PIXEL01_11\n                    PIXEL10_22\n                    PIXEL11_12\n                    break;\n                }\n                case 226:\n                {\n                    PIXEL00_22\n                    PIXEL01_21\n                    PIXEL10_12\n                    PIXEL11_11\n                    break;\n                }\n                case 60:\n                {\n                    PIXEL00_21\n                    PIXEL01_11\n                    PIXEL10_11\n                    PIXEL11_21\n                    break;\n                }\n                case 195:\n                {\n                    PIXEL00_11\n                    PIXEL01_21\n                    PIXEL10_21\n                    PIXEL11_11\n                    break;\n                }\n                case 102:\n                {\n                    PIXEL00_22\n                    PIXEL01_12\n                    PIXEL10_12\n                    PIXEL11_22\n                    break;\n                }\n                case 153:\n                {\n                    PIXEL00_12\n                    PIXEL01_22\n                    PIXEL10_22\n                    PIXEL11_12\n                    break;\n                }\n                case 58:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_10\n                    }\n                    else\n                    {\n                        PIXEL00_70\n                    }\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_10\n                    }\n                    else\n                    {\n                        PIXEL01_70\n                    }\n                    PIXEL10_11\n                    PIXEL11_21\n                    break;\n                }\n                case 83:\n                {\n                    PIXEL00_11\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_10\n                    }\n                    else\n                    {\n                        PIXEL01_70\n                    }\n                    PIXEL10_21\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL11_10\n                    }\n                    else\n                    {\n                        PIXEL11_70\n                    }\n                    break;\n                }\n                case 92:\n                {\n                    PIXEL00_21\n                    PIXEL01_11\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_10\n                    }\n                    else\n                    {\n                        PIXEL10_70\n                    }\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL11_10\n                    }\n                    else\n                    {\n                        PIXEL11_70\n                    }\n                    break;\n                }\n                case 202:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_10\n                    }\n                    else\n                    {\n                        PIXEL00_70\n                    }\n                    PIXEL01_21\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_10\n                    }\n                    else\n                    {\n                        PIXEL10_70\n                    }\n                    PIXEL11_11\n                    break;\n                }\n                case 78:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_10\n                    }\n                    else\n                    {\n                        PIXEL00_70\n                    }\n                    PIXEL01_12\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_10\n                    }\n                    else\n                    {\n                        PIXEL10_70\n                    }\n                    PIXEL11_22\n                    break;\n                }\n                case 154:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_10\n                    }\n                    else\n                    {\n                        PIXEL00_70\n                    }\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_10\n                    }\n                    else\n                    {\n                        PIXEL01_70\n                    }\n                    PIXEL10_22\n                    PIXEL11_12\n                    break;\n                }\n                case 114:\n                {\n                    PIXEL00_22\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_10\n                    }\n                    else\n                    {\n                        PIXEL01_70\n                    }\n                    PIXEL10_12\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL11_10\n                    }\n                    else\n                    {\n                        PIXEL11_70\n                    }\n                    break;\n                }\n                case 89:\n                {\n                    PIXEL00_12\n                    PIXEL01_22\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_10\n                    }\n                    else\n                    {\n                        PIXEL10_70\n                    }\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL11_10\n                    }\n                    else\n                    {\n                        PIXEL11_70\n                    }\n                    break;\n                }\n                case 90:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_10\n                    }\n                    else\n                    {\n                        PIXEL00_70\n                    }\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_10\n                    }\n                    else\n                    {\n                        PIXEL01_70\n                    }\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_10\n                    }\n                    else\n                    {\n                        PIXEL10_70\n                    }\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL11_10\n                    }\n                    else\n                    {\n                        PIXEL11_70\n                    }\n                    break;\n                }\n                case 55:\n                case 23:\n                {\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL00_11\n                        PIXEL01_0\n                    }\n                    else\n                    {\n                        PIXEL00_60\n                        PIXEL01_90\n                    }\n                    PIXEL10_20\n                    PIXEL11_21\n                    break;\n                }\n                case 182:\n                case 150:\n                {\n                    PIXEL00_22\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_0\n                        PIXEL11_12\n                    }\n                    else\n                    {\n                        PIXEL01_90\n                        PIXEL11_61\n                    }\n                    PIXEL10_20\n                    break;\n                }\n                case 213:\n                case 212:\n                {\n                    PIXEL00_20\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL01_11\n                        PIXEL11_0\n                    }\n                    else\n                    {\n                        PIXEL01_60\n                        PIXEL11_90\n                    }\n                    PIXEL10_21\n                    break;\n                }\n                case 241:\n                case 240:\n                {\n                    PIXEL00_20\n                    PIXEL01_22\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL10_12\n                        PIXEL11_0\n                    }\n                    else\n                    {\n                        PIXEL10_61\n                        PIXEL11_90\n                    }\n                    break;\n                }\n                case 236:\n                case 232:\n                {\n                    PIXEL00_21\n                    PIXEL01_20\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_0\n                        PIXEL11_11\n                    }\n                    else\n                    {\n                        PIXEL10_90\n                        PIXEL11_60\n                    }\n                    break;\n                }\n                case 109:\n                case 105:\n                {\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL00_12\n                        PIXEL10_0\n                    }\n                    else\n                    {\n                        PIXEL00_61\n                        PIXEL10_90\n                    }\n                    PIXEL01_20\n                    PIXEL11_22\n                    break;\n                }\n                case 171:\n                case 43:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                        PIXEL10_11\n                    }\n                    else\n                    {\n                        PIXEL00_90\n                        PIXEL10_60\n                    }\n                    PIXEL01_21\n                    PIXEL11_20\n                    break;\n                }\n                case 143:\n                case 15:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                        PIXEL01_12\n                    }\n                    else\n                    {\n                        PIXEL00_90\n                        PIXEL01_61\n                    }\n                    PIXEL10_22\n                    PIXEL11_20\n                    break;\n                }\n                case 124:\n                {\n                    PIXEL00_21\n                    PIXEL01_11\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_0\n                    }\n                    else\n                    {\n                        PIXEL10_20\n                    }\n                    PIXEL11_10\n                    break;\n                }\n                case 203:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                    }\n                    else\n                    {\n                        PIXEL00_20\n                    }\n                    PIXEL01_21\n                    PIXEL10_10\n                    PIXEL11_11\n                    break;\n                }\n                case 62:\n                {\n                    PIXEL00_10\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_0\n                    }\n                    else\n                    {\n                        PIXEL01_20\n                    }\n                    PIXEL10_11\n                    PIXEL11_21\n                    break;\n                }\n                case 211:\n                {\n                    PIXEL00_11\n                    PIXEL01_10\n                    PIXEL10_21\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL11_0\n                    }\n                    else\n                    {\n                        PIXEL11_20\n                    }\n                    break;\n                }\n                case 118:\n                {\n                    PIXEL00_22\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_0\n                    }\n                    else\n                    {\n                        PIXEL01_20\n                    }\n                    PIXEL10_12\n                    PIXEL11_10\n                    break;\n                }\n                case 217:\n                {\n                    PIXEL00_12\n                    PIXEL01_22\n                    PIXEL10_10\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL11_0\n                    }\n                    else\n                    {\n                        PIXEL11_20\n                    }\n                    break;\n                }\n                case 110:\n                {\n                    PIXEL00_10\n                    PIXEL01_12\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_0\n                    }\n                    else\n                    {\n                        PIXEL10_20\n                    }\n                    PIXEL11_22\n                    break;\n                }\n                case 155:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                    }\n                    else\n                    {\n                        PIXEL00_20\n                    }\n                    PIXEL01_10\n                    PIXEL10_22\n                    PIXEL11_12\n                    break;\n                }\n                case 188:\n                {\n                    PIXEL00_21\n                    PIXEL01_11\n                    PIXEL10_11\n                    PIXEL11_12\n                    break;\n                }\n                case 185:\n                {\n                    PIXEL00_12\n                    PIXEL01_22\n                    PIXEL10_11\n                    PIXEL11_12\n                    break;\n                }\n                case 61:\n                {\n                    PIXEL00_12\n                    PIXEL01_11\n                    PIXEL10_11\n                    PIXEL11_21\n                    break;\n                }\n                case 157:\n                {\n                    PIXEL00_12\n                    PIXEL01_11\n                    PIXEL10_22\n                    PIXEL11_12\n                    break;\n                }\n                case 103:\n                {\n                    PIXEL00_11\n                    PIXEL01_12\n                    PIXEL10_12\n                    PIXEL11_22\n                    break;\n                }\n                case 227:\n                {\n                    PIXEL00_11\n                    PIXEL01_21\n                    PIXEL10_12\n                    PIXEL11_11\n                    break;\n                }\n                case 230:\n                {\n                    PIXEL00_22\n                    PIXEL01_12\n                    PIXEL10_12\n                    PIXEL11_11\n                    break;\n                }\n                case 199:\n                {\n                    PIXEL00_11\n                    PIXEL01_12\n                    PIXEL10_21\n                    PIXEL11_11\n                    break;\n                }\n                case 220:\n                {\n                    PIXEL00_21\n                    PIXEL01_11\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_10\n                    }\n                    else\n                    {\n                        PIXEL10_70\n                    }\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL11_0\n                    }\n                    else\n                    {\n                        PIXEL11_20\n                    }\n                    break;\n                }\n                case 158:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_10\n                    }\n                    else\n                    {\n                        PIXEL00_70\n                    }\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_0\n                    }\n                    else\n                    {\n                        PIXEL01_20\n                    }\n                    PIXEL10_22\n                    PIXEL11_12\n                    break;\n                }\n                case 234:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_10\n                    }\n                    else\n                    {\n                        PIXEL00_70\n                    }\n                    PIXEL01_21\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_0\n                    }\n                    else\n                    {\n                        PIXEL10_20\n                    }\n                    PIXEL11_11\n                    break;\n                }\n                case 242:\n                {\n                    PIXEL00_22\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_10\n                    }\n                    else\n                    {\n                        PIXEL01_70\n                    }\n                    PIXEL10_12\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL11_0\n                    }\n                    else\n                    {\n                        PIXEL11_20\n                    }\n                    break;\n                }\n                case 59:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                    }\n                    else\n                    {\n                        PIXEL00_20\n                    }\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_10\n                    }\n                    else\n                    {\n                        PIXEL01_70\n                    }\n                    PIXEL10_11\n                    PIXEL11_21\n                    break;\n                }\n                case 121:\n                {\n                    PIXEL00_12\n                    PIXEL01_22\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_0\n                    }\n                    else\n                    {\n                        PIXEL10_20\n                    }\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL11_10\n                    }\n                    else\n                    {\n                        PIXEL11_70\n                    }\n                    break;\n                }\n                case 87:\n                {\n                    PIXEL00_11\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_0\n                    }\n                    else\n                    {\n                        PIXEL01_20\n                    }\n                    PIXEL10_21\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL11_10\n                    }\n                    else\n                    {\n                        PIXEL11_70\n                    }\n                    break;\n                }\n                case 79:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                    }\n                    else\n                    {\n                        PIXEL00_20\n                    }\n                    PIXEL01_12\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_10\n                    }\n                    else\n                    {\n                        PIXEL10_70\n                    }\n                    PIXEL11_22\n                    break;\n                }\n                case 122:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_10\n                    }\n                    else\n                    {\n                        PIXEL00_70\n                    }\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_10\n                    }\n                    else\n                    {\n                        PIXEL01_70\n                    }\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_0\n                    }\n                    else\n                    {\n                        PIXEL10_20\n                    }\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL11_10\n                    }\n                    else\n                    {\n                        PIXEL11_70\n                    }\n                    break;\n                }\n                case 94:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_10\n                    }\n                    else\n                    {\n                        PIXEL00_70\n                    }\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_0\n                    }\n                    else\n                    {\n                        PIXEL01_20\n                    }\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_10\n                    }\n                    else\n                    {\n                        PIXEL10_70\n                    }\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL11_10\n                    }\n                    else\n                    {\n                        PIXEL11_70\n                    }\n                    break;\n                }\n                case 218:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_10\n                    }\n                    else\n                    {\n                        PIXEL00_70\n                    }\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_10\n                    }\n                    else\n                    {\n                        PIXEL01_70\n                    }\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_10\n                    }\n                    else\n                    {\n                        PIXEL10_70\n                    }\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL11_0\n                    }\n                    else\n                    {\n                        PIXEL11_20\n                    }\n                    break;\n                }\n                case 91:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                    }\n                    else\n                    {\n                        PIXEL00_20\n                    }\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_10\n                    }\n                    else\n                    {\n                        PIXEL01_70\n                    }\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_10\n                    }\n                    else\n                    {\n                        PIXEL10_70\n                    }\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL11_10\n                    }\n                    else\n                    {\n                        PIXEL11_70\n                    }\n                    break;\n                }\n                case 229:\n                {\n                    PIXEL00_20\n                    PIXEL01_20\n                    PIXEL10_12\n                    PIXEL11_11\n                    break;\n                }\n                case 167:\n                {\n                    PIXEL00_11\n                    PIXEL01_12\n                    PIXEL10_20\n                    PIXEL11_20\n                    break;\n                }\n                case 173:\n                {\n                    PIXEL00_12\n                    PIXEL01_20\n                    PIXEL10_11\n                    PIXEL11_20\n                    break;\n                }\n                case 181:\n                {\n                    PIXEL00_20\n                    PIXEL01_11\n                    PIXEL10_20\n                    PIXEL11_12\n                    break;\n                }\n                case 186:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_10\n                    }\n                    else\n                    {\n                        PIXEL00_70\n                    }\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_10\n                    }\n                    else\n                    {\n                        PIXEL01_70\n                    }\n                    PIXEL10_11\n                    PIXEL11_12\n                    break;\n                }\n                case 115:\n                {\n                    PIXEL00_11\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_10\n                    }\n                    else\n                    {\n                        PIXEL01_70\n                    }\n                    PIXEL10_12\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL11_10\n                    }\n                    else\n                    {\n                        PIXEL11_70\n                    }\n                    break;\n                }\n                case 93:\n                {\n                    PIXEL00_12\n                    PIXEL01_11\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_10\n                    }\n                    else\n                    {\n                        PIXEL10_70\n                    }\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL11_10\n                    }\n                    else\n                    {\n                        PIXEL11_70\n                    }\n                    break;\n                }\n                case 206:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_10\n                    }\n                    else\n                    {\n                        PIXEL00_70\n                    }\n                    PIXEL01_12\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_10\n                    }\n                    else\n                    {\n                        PIXEL10_70\n                    }\n                    PIXEL11_11\n                    break;\n                }\n                case 205:\n                case 201:\n                {\n                    PIXEL00_12\n                    PIXEL01_20\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_10\n                    }\n                    else\n                    {\n                        PIXEL10_70\n                    }\n                    PIXEL11_11\n                    break;\n                }\n                case 174:\n                case 46:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_10\n                    }\n                    else\n                    {\n                        PIXEL00_70\n                    }\n                    PIXEL01_12\n                    PIXEL10_11\n                    PIXEL11_20\n                    break;\n                }\n                case 179:\n                case 147:\n                {\n                    PIXEL00_11\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_10\n                    }\n                    else\n                    {\n                        PIXEL01_70\n                    }\n                    PIXEL10_20\n                    PIXEL11_12\n                    break;\n                }\n                case 117:\n                case 116:\n                {\n                    PIXEL00_20\n                    PIXEL01_11\n                    PIXEL10_12\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL11_10\n                    }\n                    else\n                    {\n                        PIXEL11_70\n                    }\n                    break;\n                }\n                case 189:\n                {\n                    PIXEL00_12\n                    PIXEL01_11\n                    PIXEL10_11\n                    PIXEL11_12\n                    break;\n                }\n                case 231:\n                {\n                    PIXEL00_11\n                    PIXEL01_12\n                    PIXEL10_12\n                    PIXEL11_11\n                    break;\n                }\n                case 126:\n                {\n                    PIXEL00_10\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_0\n                    }\n                    else\n                    {\n                        PIXEL01_20\n                    }\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_0\n                    }\n                    else\n                    {\n                        PIXEL10_20\n                    }\n                    PIXEL11_10\n                    break;\n                }\n                case 219:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                    }\n                    else\n                    {\n                        PIXEL00_20\n                    }\n                    PIXEL01_10\n                    PIXEL10_10\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL11_0\n                    }\n                    else\n                    {\n                        PIXEL11_20\n                    }\n                    break;\n                }\n                case 125:\n                {\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL00_12\n                        PIXEL10_0\n                    }\n                    else\n                    {\n                        PIXEL00_61\n                        PIXEL10_90\n                    }\n                    PIXEL01_11\n                    PIXEL11_10\n                    break;\n                }\n                case 221:\n                {\n                    PIXEL00_12\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL01_11\n                        PIXEL11_0\n                    }\n                    else\n                    {\n                        PIXEL01_60\n                        PIXEL11_90\n                    }\n                    PIXEL10_10\n                    break;\n                }\n                case 207:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                        PIXEL01_12\n                    }\n                    else\n                    {\n                        PIXEL00_90\n                        PIXEL01_61\n                    }\n                    PIXEL10_10\n                    PIXEL11_11\n                    break;\n                }\n                case 238:\n                {\n                    PIXEL00_10\n                    PIXEL01_12\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_0\n                        PIXEL11_11\n                    }\n                    else\n                    {\n                        PIXEL10_90\n                        PIXEL11_60\n                    }\n                    break;\n                }\n                case 190:\n                {\n                    PIXEL00_10\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_0\n                        PIXEL11_12\n                    }\n                    else\n                    {\n                        PIXEL01_90\n                        PIXEL11_61\n                    }\n                    PIXEL10_11\n                    break;\n                }\n                case 187:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                        PIXEL10_11\n                    }\n                    else\n                    {\n                        PIXEL00_90\n                        PIXEL10_60\n                    }\n                    PIXEL01_10\n                    PIXEL11_12\n                    break;\n                }\n                case 243:\n                {\n                    PIXEL00_11\n                    PIXEL01_10\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL10_12\n                        PIXEL11_0\n                    }\n                    else\n                    {\n                        PIXEL10_61\n                        PIXEL11_90\n                    }\n                    break;\n                }\n                case 119:\n                {\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL00_11\n                        PIXEL01_0\n                    }\n                    else\n                    {\n                        PIXEL00_60\n                        PIXEL01_90\n                    }\n                    PIXEL10_12\n                    PIXEL11_10\n                    break;\n                }\n                case 237:\n                case 233:\n                {\n                    PIXEL00_12\n                    PIXEL01_20\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_0\n                    }\n                    else\n                    {\n                        PIXEL10_100\n                    }\n                    PIXEL11_11\n                    break;\n                }\n                case 175:\n                case 47:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                    }\n                    else\n                    {\n                        PIXEL00_100\n                    }\n                    PIXEL01_12\n                    PIXEL10_11\n                    PIXEL11_20\n                    break;\n                }\n                case 183:\n                case 151:\n                {\n                    PIXEL00_11\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_0\n                    }\n                    else\n                    {\n                        PIXEL01_100\n                    }\n                    PIXEL10_20\n                    PIXEL11_12\n                    break;\n                }\n                case 245:\n                case 244:\n                {\n                    PIXEL00_20\n                    PIXEL01_11\n                    PIXEL10_12\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL11_0\n                    }\n                    else\n                    {\n                        PIXEL11_100\n                    }\n                    break;\n                }\n                case 250:\n                {\n                    PIXEL00_10\n                    PIXEL01_10\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_0\n                    }\n                    else\n                    {\n                        PIXEL10_20\n                    }\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL11_0\n                    }\n                    else\n                    {\n                        PIXEL11_20\n                    }\n                    break;\n                }\n                case 123:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                    }\n                    else\n                    {\n                        PIXEL00_20\n                    }\n                    PIXEL01_10\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_0\n                    }\n                    else\n                    {\n                        PIXEL10_20\n                    }\n                    PIXEL11_10\n                    break;\n                }\n                case 95:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                    }\n                    else\n                    {\n                        PIXEL00_20\n                    }\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_0\n                    }\n                    else\n                    {\n                        PIXEL01_20\n                    }\n                    PIXEL10_10\n                    PIXEL11_10\n                    break;\n                }\n                case 222:\n                {\n                    PIXEL00_10\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_0\n                    }\n                    else\n                    {\n                        PIXEL01_20\n                    }\n                    PIXEL10_10\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL11_0\n                    }\n                    else\n                    {\n                        PIXEL11_20\n                    }\n                    break;\n                }\n                case 252:\n                {\n                    PIXEL00_21\n                    PIXEL01_11\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_0\n                    }\n                    else\n                    {\n                        PIXEL10_20\n                    }\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL11_0\n                    }\n                    else\n                    {\n                        PIXEL11_100\n                    }\n                    break;\n                }\n                case 249:\n                {\n                    PIXEL00_12\n                    PIXEL01_22\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_0\n                    }\n                    else\n                    {\n                        PIXEL10_100\n                    }\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL11_0\n                    }\n                    else\n                    {\n                        PIXEL11_20\n                    }\n                    break;\n                }\n                case 235:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                    }\n                    else\n                    {\n                        PIXEL00_20\n                    }\n                    PIXEL01_21\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_0\n                    }\n                    else\n                    {\n                        PIXEL10_100\n                    }\n                    PIXEL11_11\n                    break;\n                }\n                case 111:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                    }\n                    else\n                    {\n                        PIXEL00_100\n                    }\n                    PIXEL01_12\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_0\n                    }\n                    else\n                    {\n                        PIXEL10_20\n                    }\n                    PIXEL11_22\n                    break;\n                }\n                case 63:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                    }\n                    else\n                    {\n                        PIXEL00_100\n                    }\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_0\n                    }\n                    else\n                    {\n                        PIXEL01_20\n                    }\n                    PIXEL10_11\n                    PIXEL11_21\n                    break;\n                }\n                case 159:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                    }\n                    else\n                    {\n                        PIXEL00_20\n                    }\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_0\n                    }\n                    else\n                    {\n                        PIXEL01_100\n                    }\n                    PIXEL10_22\n                    PIXEL11_12\n                    break;\n                }\n                case 215:\n                {\n                    PIXEL00_11\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_0\n                    }\n                    else\n                    {\n                        PIXEL01_100\n                    }\n                    PIXEL10_21\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL11_0\n                    }\n                    else\n                    {\n                        PIXEL11_20\n                    }\n                    break;\n                }\n                case 246:\n                {\n                    PIXEL00_22\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_0\n                    }\n                    else\n                    {\n                        PIXEL01_20\n                    }\n                    PIXEL10_12\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL11_0\n                    }\n                    else\n                    {\n                        PIXEL11_100\n                    }\n                    break;\n                }\n                case 254:\n                {\n                    PIXEL00_10\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_0\n                    }\n                    else\n                    {\n                        PIXEL01_20\n                    }\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_0\n                    }\n                    else\n                    {\n                        PIXEL10_20\n                    }\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL11_0\n                    }\n                    else\n                    {\n                        PIXEL11_100\n                    }\n                    break;\n                }\n                case 253:\n                {\n                    PIXEL00_12\n                    PIXEL01_11\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_0\n                    }\n                    else\n                    {\n                        PIXEL10_100\n                    }\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL11_0\n                    }\n                    else\n                    {\n                        PIXEL11_100\n                    }\n                    break;\n                }\n                case 251:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                    }\n                    else\n                    {\n                        PIXEL00_20\n                    }\n                    PIXEL01_10\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_0\n                    }\n                    else\n                    {\n                        PIXEL10_100\n                    }\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL11_0\n                    }\n                    else\n                    {\n                        PIXEL11_20\n                    }\n                    break;\n                }\n                case 239:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                    }\n                    else\n                    {\n                        PIXEL00_100\n                    }\n                    PIXEL01_12\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_0\n                    }\n                    else\n                    {\n                        PIXEL10_100\n                    }\n                    PIXEL11_11\n                    break;\n                }\n                case 127:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                    }\n                    else\n                    {\n                        PIXEL00_100\n                    }\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_0\n                    }\n                    else\n                    {\n                        PIXEL01_20\n                    }\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_0\n                    }\n                    else\n                    {\n                        PIXEL10_20\n                    }\n                    PIXEL11_10\n                    break;\n                }\n                case 191:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                    }\n                    else\n                    {\n                        PIXEL00_100\n                    }\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_0\n                    }\n                    else\n                    {\n                        PIXEL01_100\n                    }\n                    PIXEL10_11\n                    PIXEL11_12\n                    break;\n                }\n                case 223:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                    }\n                    else\n                    {\n                        PIXEL00_20\n                    }\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_0\n                    }\n                    else\n                    {\n                        PIXEL01_100\n                    }\n                    PIXEL10_10\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL11_0\n                    }\n                    else\n                    {\n                        PIXEL11_20\n                    }\n                    break;\n                }\n                case 247:\n                {\n                    PIXEL00_11\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_0\n                    }\n                    else\n                    {\n                        PIXEL01_100\n                    }\n                    PIXEL10_12\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL11_0\n                    }\n                    else\n                    {\n                        PIXEL11_100\n                    }\n                    break;\n                }\n                case 255:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                    }\n                    else\n                    {\n                        PIXEL00_100\n                    }\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_0\n                    }\n                    else\n                    {\n                        PIXEL01_100\n                    }\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_0\n                    }\n                    else\n                    {\n                        PIXEL10_100\n                    }\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL11_0\n                    }\n                    else\n                    {\n                        PIXEL11_100\n                    }\n                    break;\n                }\n            }\n            sp++;\n            dp += 2;\n        }\n\n        sRowP += srb;\n        sp = (const uint32_t*) sRowP;\n\n        dRowP += drb * 2;\n        dp = (uint32_t*) dRowP;\n    }\n}\n\nHQX_API void HQX_CALLCONV hq2x_32(const uint32_t* sp, uint32_t* dp, int Xres, int Yres )\n{\n    uint32_t rowBytesL = Xres * 4;\n    hq2x_32_rb(sp, rowBytesL, dp, rowBytesL * 2, Xres, Yres);\n}\n"
  },
  {
    "path": "src/Engine/Scalers/hq3x.cpp",
    "content": "/*\n * Copyright (C) 2003 Maxim Stepin ( maxst@hiend3d.com )\n *\n * Copyright (C) 2010 Cameron Zemek ( grom@zeminvaders.net)\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n */\n\n#include <stdint.h>\n#include \"common.h\"\n#include \"hqx.h\"\n\n#define PIXEL00_1M  *dp = Interp1(w[5], w[1]);\n#define PIXEL00_1U  *dp = Interp1(w[5], w[2]);\n#define PIXEL00_1L  *dp = Interp1(w[5], w[4]);\n#define PIXEL00_2   *dp = Interp2(w[5], w[4], w[2]);\n#define PIXEL00_4   *dp = Interp4(w[5], w[4], w[2]);\n#define PIXEL00_5   *dp = Interp5(w[4], w[2]);\n#define PIXEL00_C   *dp   = w[5];\n\n#define PIXEL01_1   *(dp+1) = Interp1(w[5], w[2]);\n#define PIXEL01_3   *(dp+1) = Interp3(w[5], w[2]);\n#define PIXEL01_6   *(dp+1) = Interp1(w[2], w[5]);\n#define PIXEL01_C   *(dp+1) = w[5];\n\n#define PIXEL02_1M  *(dp+2) = Interp1(w[5], w[3]);\n#define PIXEL02_1U  *(dp+2) = Interp1(w[5], w[2]);\n#define PIXEL02_1R  *(dp+2) = Interp1(w[5], w[6]);\n#define PIXEL02_2   *(dp+2) = Interp2(w[5], w[2], w[6]);\n#define PIXEL02_4   *(dp+2) = Interp4(w[5], w[2], w[6]);\n#define PIXEL02_5   *(dp+2) = Interp5(w[2], w[6]);\n#define PIXEL02_C   *(dp+2) = w[5];\n\n#define PIXEL10_1   *(dp+dpL) = Interp1(w[5], w[4]);\n#define PIXEL10_3   *(dp+dpL) = Interp3(w[5], w[4]);\n#define PIXEL10_6   *(dp+dpL) = Interp1(w[4], w[5]);\n#define PIXEL10_C   *(dp+dpL) = w[5];\n\n#define PIXEL11     *(dp+dpL+1) = w[5];\n\n#define PIXEL12_1   *(dp+dpL+2) = Interp1(w[5], w[6]);\n#define PIXEL12_3   *(dp+dpL+2) = Interp3(w[5], w[6]);\n#define PIXEL12_6   *(dp+dpL+2) = Interp1(w[6], w[5]);\n#define PIXEL12_C   *(dp+dpL+2) = w[5];\n\n#define PIXEL20_1M  *(dp+dpL+dpL) = Interp1(w[5], w[7]);\n#define PIXEL20_1D  *(dp+dpL+dpL) = Interp1(w[5], w[8]);\n#define PIXEL20_1L  *(dp+dpL+dpL) = Interp1(w[5], w[4]);\n#define PIXEL20_2   *(dp+dpL+dpL) = Interp2(w[5], w[8], w[4]);\n#define PIXEL20_4   *(dp+dpL+dpL) = Interp4(w[5], w[8], w[4]);\n#define PIXEL20_5   *(dp+dpL+dpL) = Interp5(w[8], w[4]);\n#define PIXEL20_C   *(dp+dpL+dpL) = w[5];\n\n#define PIXEL21_1   *(dp+dpL+dpL+1) = Interp1(w[5], w[8]);\n#define PIXEL21_3   *(dp+dpL+dpL+1) = Interp3(w[5], w[8]);\n#define PIXEL21_6   *(dp+dpL+dpL+1) = Interp1(w[8], w[5]);\n#define PIXEL21_C   *(dp+dpL+dpL+1) = w[5];\n\n#define PIXEL22_1M  *(dp+dpL+dpL+2) = Interp1(w[5], w[9]);\n#define PIXEL22_1D  *(dp+dpL+dpL+2) = Interp1(w[5], w[8]);\n#define PIXEL22_1R  *(dp+dpL+dpL+2) = Interp1(w[5], w[6]);\n#define PIXEL22_2   *(dp+dpL+dpL+2) = Interp2(w[5], w[6], w[8]);\n#define PIXEL22_4   *(dp+dpL+dpL+2) = Interp4(w[5], w[6], w[8]);\n#define PIXEL22_5   *(dp+dpL+dpL+2) = Interp5(w[6], w[8]);\n#define PIXEL22_C   *(dp+dpL+dpL+2) = w[5];\n\nHQX_API void HQX_CALLCONV hq3x_32_rb(const uint32_t* sp, uint32_t srb, uint32_t* dp, uint32_t drb, int Xres, int Yres )\n{\n    int  i, j, k;\n    int  prevline, nextline;\n    uint32_t  w[10];\n    int dpL = (drb >> 2);\n    int spL = (srb >> 2);\n    const uint8_t* sRowP = (const uint8_t*) sp;\n    const uint8_t* dRowP = (const uint8_t*) dp;\n    uint32_t yuv1, yuv2;\n\n    //   +----+----+----+\n    //   |    |    |    |\n    //   | w1 | w2 | w3 |\n    //   +----+----+----+\n    //   |    |    |    |\n    //   | w4 | w5 | w6 |\n    //   +----+----+----+\n    //   |    |    |    |\n    //   | w7 | w8 | w9 |\n    //   +----+----+----+\n\n    for (j=0; j<Yres; j++)\n    {\n        if (j>0)      prevline = -spL;\n        else prevline = 0;\n        if (j<Yres-1) nextline =  spL;\n        else nextline = 0;\n\n        for (i=0; i<Xres; i++)\n        {\n            w[2] = *(sp + prevline);\n            w[5] = *sp;\n            w[8] = *(sp + nextline);\n\n            if (i>0)\n            {\n                w[1] = *(sp + prevline - 1);\n                w[4] = *(sp - 1);\n                w[7] = *(sp + nextline - 1);\n            }\n            else\n            {\n                w[1] = w[2];\n                w[4] = w[5];\n                w[7] = w[8];\n            }\n\n            if (i<Xres-1)\n            {\n                w[3] = *(sp + prevline + 1);\n                w[6] = *(sp + 1);\n                w[9] = *(sp + nextline + 1);\n            }\n            else\n            {\n                w[3] = w[2];\n                w[6] = w[5];\n                w[9] = w[8];\n            }\n\n            int pattern = 0;\n            int flag = 1;\n\n            yuv1 = rgb_to_yuv(w[5]);\n\n            for (k=1; k<=9; k++)\n            {\n                if (k==5) continue;\n\n                if ( w[k] != w[5] )\n                {\n                    yuv2 = rgb_to_yuv(w[k]);\n                    if (yuv_diff(yuv1, yuv2))\n                        pattern |= flag;\n                }\n                flag <<= 1;\n            }\n\n            switch (pattern)\n            {\n                case 0:\n                case 1:\n                case 4:\n                case 32:\n                case 128:\n                case 5:\n                case 132:\n                case 160:\n                case 33:\n                case 129:\n                case 36:\n                case 133:\n                case 164:\n                case 161:\n                case 37:\n                case 165:\n                {\n                    PIXEL00_2\n                    PIXEL01_1\n                    PIXEL02_2\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL12_1\n                    PIXEL20_2\n                    PIXEL21_1\n                    PIXEL22_2\n                    break;\n                }\n                case 2:\n                case 34:\n                case 130:\n                case 162:\n                {\n                    PIXEL00_1M\n                    PIXEL01_C\n                    PIXEL02_1M\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL12_1\n                    PIXEL20_2\n                    PIXEL21_1\n                    PIXEL22_2\n                    break;\n                }\n                case 16:\n                case 17:\n                case 48:\n                case 49:\n                {\n                    PIXEL00_2\n                    PIXEL01_1\n                    PIXEL02_1M\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL12_C\n                    PIXEL20_2\n                    PIXEL21_1\n                    PIXEL22_1M\n                    break;\n                }\n                case 64:\n                case 65:\n                case 68:\n                case 69:\n                {\n                    PIXEL00_2\n                    PIXEL01_1\n                    PIXEL02_2\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL12_1\n                    PIXEL20_1M\n                    PIXEL21_C\n                    PIXEL22_1M\n                    break;\n                }\n                case 8:\n                case 12:\n                case 136:\n                case 140:\n                {\n                    PIXEL00_1M\n                    PIXEL01_1\n                    PIXEL02_2\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL12_1\n                    PIXEL20_1M\n                    PIXEL21_1\n                    PIXEL22_2\n                    break;\n                }\n                case 3:\n                case 35:\n                case 131:\n                case 163:\n                {\n                    PIXEL00_1L\n                    PIXEL01_C\n                    PIXEL02_1M\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL12_1\n                    PIXEL20_2\n                    PIXEL21_1\n                    PIXEL22_2\n                    break;\n                }\n                case 6:\n                case 38:\n                case 134:\n                case 166:\n                {\n                    PIXEL00_1M\n                    PIXEL01_C\n                    PIXEL02_1R\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL12_1\n                    PIXEL20_2\n                    PIXEL21_1\n                    PIXEL22_2\n                    break;\n                }\n                case 20:\n                case 21:\n                case 52:\n                case 53:\n                {\n                    PIXEL00_2\n                    PIXEL01_1\n                    PIXEL02_1U\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL12_C\n                    PIXEL20_2\n                    PIXEL21_1\n                    PIXEL22_1M\n                    break;\n                }\n                case 144:\n                case 145:\n                case 176:\n                case 177:\n                {\n                    PIXEL00_2\n                    PIXEL01_1\n                    PIXEL02_1M\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL12_C\n                    PIXEL20_2\n                    PIXEL21_1\n                    PIXEL22_1D\n                    break;\n                }\n                case 192:\n                case 193:\n                case 196:\n                case 197:\n                {\n                    PIXEL00_2\n                    PIXEL01_1\n                    PIXEL02_2\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL12_1\n                    PIXEL20_1M\n                    PIXEL21_C\n                    PIXEL22_1R\n                    break;\n                }\n                case 96:\n                case 97:\n                case 100:\n                case 101:\n                {\n                    PIXEL00_2\n                    PIXEL01_1\n                    PIXEL02_2\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL12_1\n                    PIXEL20_1L\n                    PIXEL21_C\n                    PIXEL22_1M\n                    break;\n                }\n                case 40:\n                case 44:\n                case 168:\n                case 172:\n                {\n                    PIXEL00_1M\n                    PIXEL01_1\n                    PIXEL02_2\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL12_1\n                    PIXEL20_1D\n                    PIXEL21_1\n                    PIXEL22_2\n                    break;\n                }\n                case 9:\n                case 13:\n                case 137:\n                case 141:\n                {\n                    PIXEL00_1U\n                    PIXEL01_1\n                    PIXEL02_2\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL12_1\n                    PIXEL20_1M\n                    PIXEL21_1\n                    PIXEL22_2\n                    break;\n                }\n                case 18:\n                case 50:\n                {\n                    PIXEL00_1M\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_C\n                        PIXEL02_1M\n                        PIXEL12_C\n                    }\n                    else\n                    {\n                        PIXEL01_3\n                        PIXEL02_4\n                        PIXEL12_3\n                    }\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL20_2\n                    PIXEL21_1\n                    PIXEL22_1M\n                    break;\n                }\n                case 80:\n                case 81:\n                {\n                    PIXEL00_2\n                    PIXEL01_1\n                    PIXEL02_1M\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL20_1M\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL12_C\n                        PIXEL21_C\n                        PIXEL22_1M\n                    }\n                    else\n                    {\n                        PIXEL12_3\n                        PIXEL21_3\n                        PIXEL22_4\n                    }\n                    break;\n                }\n                case 72:\n                case 76:\n                {\n                    PIXEL00_1M\n                    PIXEL01_1\n                    PIXEL02_2\n                    PIXEL11\n                    PIXEL12_1\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_C\n                        PIXEL20_1M\n                        PIXEL21_C\n                    }\n                    else\n                    {\n                        PIXEL10_3\n                        PIXEL20_4\n                        PIXEL21_3\n                    }\n                    PIXEL22_1M\n                    break;\n                }\n                case 10:\n                case 138:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_1M\n                        PIXEL01_C\n                        PIXEL10_C\n                    }\n                    else\n                    {\n                        PIXEL00_4\n                        PIXEL01_3\n                        PIXEL10_3\n                    }\n                    PIXEL02_1M\n                    PIXEL11\n                    PIXEL12_1\n                    PIXEL20_1M\n                    PIXEL21_1\n                    PIXEL22_2\n                    break;\n                }\n                case 66:\n                {\n                    PIXEL00_1M\n                    PIXEL01_C\n                    PIXEL02_1M\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL12_1\n                    PIXEL20_1M\n                    PIXEL21_C\n                    PIXEL22_1M\n                    break;\n                }\n                case 24:\n                {\n                    PIXEL00_1M\n                    PIXEL01_1\n                    PIXEL02_1M\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL12_C\n                    PIXEL20_1M\n                    PIXEL21_1\n                    PIXEL22_1M\n                    break;\n                }\n                case 7:\n                case 39:\n                case 135:\n                {\n                    PIXEL00_1L\n                    PIXEL01_C\n                    PIXEL02_1R\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL12_1\n                    PIXEL20_2\n                    PIXEL21_1\n                    PIXEL22_2\n                    break;\n                }\n                case 148:\n                case 149:\n                case 180:\n                {\n                    PIXEL00_2\n                    PIXEL01_1\n                    PIXEL02_1U\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL12_C\n                    PIXEL20_2\n                    PIXEL21_1\n                    PIXEL22_1D\n                    break;\n                }\n                case 224:\n                case 228:\n                case 225:\n                {\n                    PIXEL00_2\n                    PIXEL01_1\n                    PIXEL02_2\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL12_1\n                    PIXEL20_1L\n                    PIXEL21_C\n                    PIXEL22_1R\n                    break;\n                }\n                case 41:\n                case 169:\n                case 45:\n                {\n                    PIXEL00_1U\n                    PIXEL01_1\n                    PIXEL02_2\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL12_1\n                    PIXEL20_1D\n                    PIXEL21_1\n                    PIXEL22_2\n                    break;\n                }\n                case 22:\n                case 54:\n                {\n                    PIXEL00_1M\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_C\n                        PIXEL02_C\n                        PIXEL12_C\n                    }\n                    else\n                    {\n                        PIXEL01_3\n                        PIXEL02_4\n                        PIXEL12_3\n                    }\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL20_2\n                    PIXEL21_1\n                    PIXEL22_1M\n                    break;\n                }\n                case 208:\n                case 209:\n                {\n                    PIXEL00_2\n                    PIXEL01_1\n                    PIXEL02_1M\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL20_1M\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL12_C\n                        PIXEL21_C\n                        PIXEL22_C\n                    }\n                    else\n                    {\n                        PIXEL12_3\n                        PIXEL21_3\n                        PIXEL22_4\n                    }\n                    break;\n                }\n                case 104:\n                case 108:\n                {\n                    PIXEL00_1M\n                    PIXEL01_1\n                    PIXEL02_2\n                    PIXEL11\n                    PIXEL12_1\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_C\n                        PIXEL20_C\n                        PIXEL21_C\n                    }\n                    else\n                    {\n                        PIXEL10_3\n                        PIXEL20_4\n                        PIXEL21_3\n                    }\n                    PIXEL22_1M\n                    break;\n                }\n                case 11:\n                case 139:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_C\n                        PIXEL01_C\n                        PIXEL10_C\n                    }\n                    else\n                    {\n                        PIXEL00_4\n                        PIXEL01_3\n                        PIXEL10_3\n                    }\n                    PIXEL02_1M\n                    PIXEL11\n                    PIXEL12_1\n                    PIXEL20_1M\n                    PIXEL21_1\n                    PIXEL22_2\n                    break;\n                }\n                case 19:\n                case 51:\n                {\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL00_1L\n                        PIXEL01_C\n                        PIXEL02_1M\n                        PIXEL12_C\n                    }\n                    else\n                    {\n                        PIXEL00_2\n                        PIXEL01_6\n                        PIXEL02_5\n                        PIXEL12_1\n                    }\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL20_2\n                    PIXEL21_1\n                    PIXEL22_1M\n                    break;\n                }\n                case 146:\n                case 178:\n                {\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_C\n                        PIXEL02_1M\n                        PIXEL12_C\n                        PIXEL22_1D\n                    }\n                    else\n                    {\n                        PIXEL01_1\n                        PIXEL02_5\n                        PIXEL12_6\n                        PIXEL22_2\n                    }\n                    PIXEL00_1M\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL20_2\n                    PIXEL21_1\n                    break;\n                }\n                case 84:\n                case 85:\n                {\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL02_1U\n                        PIXEL12_C\n                        PIXEL21_C\n                        PIXEL22_1M\n                    }\n                    else\n                    {\n                        PIXEL02_2\n                        PIXEL12_6\n                        PIXEL21_1\n                        PIXEL22_5\n                    }\n                    PIXEL00_2\n                    PIXEL01_1\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL20_1M\n                    break;\n                }\n                case 112:\n                case 113:\n                {\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL12_C\n                        PIXEL20_1L\n                        PIXEL21_C\n                        PIXEL22_1M\n                    }\n                    else\n                    {\n                        PIXEL12_1\n                        PIXEL20_2\n                        PIXEL21_6\n                        PIXEL22_5\n                    }\n                    PIXEL00_2\n                    PIXEL01_1\n                    PIXEL02_1M\n                    PIXEL10_1\n                    PIXEL11\n                    break;\n                }\n                case 200:\n                case 204:\n                {\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_C\n                        PIXEL20_1M\n                        PIXEL21_C\n                        PIXEL22_1R\n                    }\n                    else\n                    {\n                        PIXEL10_1\n                        PIXEL20_5\n                        PIXEL21_6\n                        PIXEL22_2\n                    }\n                    PIXEL00_1M\n                    PIXEL01_1\n                    PIXEL02_2\n                    PIXEL11\n                    PIXEL12_1\n                    break;\n                }\n                case 73:\n                case 77:\n                {\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL00_1U\n                        PIXEL10_C\n                        PIXEL20_1M\n                        PIXEL21_C\n                    }\n                    else\n                    {\n                        PIXEL00_2\n                        PIXEL10_6\n                        PIXEL20_5\n                        PIXEL21_1\n                    }\n                    PIXEL01_1\n                    PIXEL02_2\n                    PIXEL11\n                    PIXEL12_1\n                    PIXEL22_1M\n                    break;\n                }\n                case 42:\n                case 170:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_1M\n                        PIXEL01_C\n                        PIXEL10_C\n                        PIXEL20_1D\n                    }\n                    else\n                    {\n                        PIXEL00_5\n                        PIXEL01_1\n                        PIXEL10_6\n                        PIXEL20_2\n                    }\n                    PIXEL02_1M\n                    PIXEL11\n                    PIXEL12_1\n                    PIXEL21_1\n                    PIXEL22_2\n                    break;\n                }\n                case 14:\n                case 142:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_1M\n                        PIXEL01_C\n                        PIXEL02_1R\n                        PIXEL10_C\n                    }\n                    else\n                    {\n                        PIXEL00_5\n                        PIXEL01_6\n                        PIXEL02_2\n                        PIXEL10_1\n                    }\n                    PIXEL11\n                    PIXEL12_1\n                    PIXEL20_1M\n                    PIXEL21_1\n                    PIXEL22_2\n                    break;\n                }\n                case 67:\n                {\n                    PIXEL00_1L\n                    PIXEL01_C\n                    PIXEL02_1M\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL12_1\n                    PIXEL20_1M\n                    PIXEL21_C\n                    PIXEL22_1M\n                    break;\n                }\n                case 70:\n                {\n                    PIXEL00_1M\n                    PIXEL01_C\n                    PIXEL02_1R\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL12_1\n                    PIXEL20_1M\n                    PIXEL21_C\n                    PIXEL22_1M\n                    break;\n                }\n                case 28:\n                {\n                    PIXEL00_1M\n                    PIXEL01_1\n                    PIXEL02_1U\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL12_C\n                    PIXEL20_1M\n                    PIXEL21_1\n                    PIXEL22_1M\n                    break;\n                }\n                case 152:\n                {\n                    PIXEL00_1M\n                    PIXEL01_1\n                    PIXEL02_1M\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL12_C\n                    PIXEL20_1M\n                    PIXEL21_1\n                    PIXEL22_1D\n                    break;\n                }\n                case 194:\n                {\n                    PIXEL00_1M\n                    PIXEL01_C\n                    PIXEL02_1M\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL12_1\n                    PIXEL20_1M\n                    PIXEL21_C\n                    PIXEL22_1R\n                    break;\n                }\n                case 98:\n                {\n                    PIXEL00_1M\n                    PIXEL01_C\n                    PIXEL02_1M\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL12_1\n                    PIXEL20_1L\n                    PIXEL21_C\n                    PIXEL22_1M\n                    break;\n                }\n                case 56:\n                {\n                    PIXEL00_1M\n                    PIXEL01_1\n                    PIXEL02_1M\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL12_C\n                    PIXEL20_1D\n                    PIXEL21_1\n                    PIXEL22_1M\n                    break;\n                }\n                case 25:\n                {\n                    PIXEL00_1U\n                    PIXEL01_1\n                    PIXEL02_1M\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL12_C\n                    PIXEL20_1M\n                    PIXEL21_1\n                    PIXEL22_1M\n                    break;\n                }\n                case 26:\n                case 31:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_C\n                        PIXEL10_C\n                    }\n                    else\n                    {\n                        PIXEL00_4\n                        PIXEL10_3\n                    }\n                    PIXEL01_C\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_C\n                        PIXEL12_C\n                    }\n                    else\n                    {\n                        PIXEL02_4\n                        PIXEL12_3\n                    }\n                    PIXEL11\n                    PIXEL20_1M\n                    PIXEL21_1\n                    PIXEL22_1M\n                    break;\n                }\n                case 82:\n                case 214:\n                {\n                    PIXEL00_1M\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_C\n                        PIXEL02_C\n                    }\n                    else\n                    {\n                        PIXEL01_3\n                        PIXEL02_4\n                    }\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL12_C\n                    PIXEL20_1M\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL21_C\n                        PIXEL22_C\n                    }\n                    else\n                    {\n                        PIXEL21_3\n                        PIXEL22_4\n                    }\n                    break;\n                }\n                case 88:\n                case 248:\n                {\n                    PIXEL00_1M\n                    PIXEL01_1\n                    PIXEL02_1M\n                    PIXEL11\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_C\n                        PIXEL20_C\n                    }\n                    else\n                    {\n                        PIXEL10_3\n                        PIXEL20_4\n                    }\n                    PIXEL21_C\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL12_C\n                        PIXEL22_C\n                    }\n                    else\n                    {\n                        PIXEL12_3\n                        PIXEL22_4\n                    }\n                    break;\n                }\n                case 74:\n                case 107:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_C\n                        PIXEL01_C\n                    }\n                    else\n                    {\n                        PIXEL00_4\n                        PIXEL01_3\n                    }\n                    PIXEL02_1M\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL12_1\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_C\n                        PIXEL21_C\n                    }\n                    else\n                    {\n                        PIXEL20_4\n                        PIXEL21_3\n                    }\n                    PIXEL22_1M\n                    break;\n                }\n                case 27:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_C\n                        PIXEL01_C\n                        PIXEL10_C\n                    }\n                    else\n                    {\n                        PIXEL00_4\n                        PIXEL01_3\n                        PIXEL10_3\n                    }\n                    PIXEL02_1M\n                    PIXEL11\n                    PIXEL12_C\n                    PIXEL20_1M\n                    PIXEL21_1\n                    PIXEL22_1M\n                    break;\n                }\n                case 86:\n                {\n                    PIXEL00_1M\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_C\n                        PIXEL02_C\n                        PIXEL12_C\n                    }\n                    else\n                    {\n                        PIXEL01_3\n                        PIXEL02_4\n                        PIXEL12_3\n                    }\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL20_1M\n                    PIXEL21_C\n                    PIXEL22_1M\n                    break;\n                }\n                case 216:\n                {\n                    PIXEL00_1M\n                    PIXEL01_1\n                    PIXEL02_1M\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL20_1M\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL12_C\n                        PIXEL21_C\n                        PIXEL22_C\n                    }\n                    else\n                    {\n                        PIXEL12_3\n                        PIXEL21_3\n                        PIXEL22_4\n                    }\n                    break;\n                }\n                case 106:\n                {\n                    PIXEL00_1M\n                    PIXEL01_C\n                    PIXEL02_1M\n                    PIXEL11\n                    PIXEL12_1\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_C\n                        PIXEL20_C\n                        PIXEL21_C\n                    }\n                    else\n                    {\n                        PIXEL10_3\n                        PIXEL20_4\n                        PIXEL21_3\n                    }\n                    PIXEL22_1M\n                    break;\n                }\n                case 30:\n                {\n                    PIXEL00_1M\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_C\n                        PIXEL02_C\n                        PIXEL12_C\n                    }\n                    else\n                    {\n                        PIXEL01_3\n                        PIXEL02_4\n                        PIXEL12_3\n                    }\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL20_1M\n                    PIXEL21_1\n                    PIXEL22_1M\n                    break;\n                }\n                case 210:\n                {\n                    PIXEL00_1M\n                    PIXEL01_C\n                    PIXEL02_1M\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL20_1M\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL12_C\n                        PIXEL21_C\n                        PIXEL22_C\n                    }\n                    else\n                    {\n                        PIXEL12_3\n                        PIXEL21_3\n                        PIXEL22_4\n                    }\n                    break;\n                }\n                case 120:\n                {\n                    PIXEL00_1M\n                    PIXEL01_1\n                    PIXEL02_1M\n                    PIXEL11\n                    PIXEL12_C\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_C\n                        PIXEL20_C\n                        PIXEL21_C\n                    }\n                    else\n                    {\n                        PIXEL10_3\n                        PIXEL20_4\n                        PIXEL21_3\n                    }\n                    PIXEL22_1M\n                    break;\n                }\n                case 75:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_C\n                        PIXEL01_C\n                        PIXEL10_C\n                    }\n                    else\n                    {\n                        PIXEL00_4\n                        PIXEL01_3\n                        PIXEL10_3\n                    }\n                    PIXEL02_1M\n                    PIXEL11\n                    PIXEL12_1\n                    PIXEL20_1M\n                    PIXEL21_C\n                    PIXEL22_1M\n                    break;\n                }\n                case 29:\n                {\n                    PIXEL00_1U\n                    PIXEL01_1\n                    PIXEL02_1U\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL12_C\n                    PIXEL20_1M\n                    PIXEL21_1\n                    PIXEL22_1M\n                    break;\n                }\n                case 198:\n                {\n                    PIXEL00_1M\n                    PIXEL01_C\n                    PIXEL02_1R\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL12_1\n                    PIXEL20_1M\n                    PIXEL21_C\n                    PIXEL22_1R\n                    break;\n                }\n                case 184:\n                {\n                    PIXEL00_1M\n                    PIXEL01_1\n                    PIXEL02_1M\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL12_C\n                    PIXEL20_1D\n                    PIXEL21_1\n                    PIXEL22_1D\n                    break;\n                }\n                case 99:\n                {\n                    PIXEL00_1L\n                    PIXEL01_C\n                    PIXEL02_1M\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL12_1\n                    PIXEL20_1L\n                    PIXEL21_C\n                    PIXEL22_1M\n                    break;\n                }\n                case 57:\n                {\n                    PIXEL00_1U\n                    PIXEL01_1\n                    PIXEL02_1M\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL12_C\n                    PIXEL20_1D\n                    PIXEL21_1\n                    PIXEL22_1M\n                    break;\n                }\n                case 71:\n                {\n                    PIXEL00_1L\n                    PIXEL01_C\n                    PIXEL02_1R\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL12_1\n                    PIXEL20_1M\n                    PIXEL21_C\n                    PIXEL22_1M\n                    break;\n                }\n                case 156:\n                {\n                    PIXEL00_1M\n                    PIXEL01_1\n                    PIXEL02_1U\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL12_C\n                    PIXEL20_1M\n                    PIXEL21_1\n                    PIXEL22_1D\n                    break;\n                }\n                case 226:\n                {\n                    PIXEL00_1M\n                    PIXEL01_C\n                    PIXEL02_1M\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL12_1\n                    PIXEL20_1L\n                    PIXEL21_C\n                    PIXEL22_1R\n                    break;\n                }\n                case 60:\n                {\n                    PIXEL00_1M\n                    PIXEL01_1\n                    PIXEL02_1U\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL12_C\n                    PIXEL20_1D\n                    PIXEL21_1\n                    PIXEL22_1M\n                    break;\n                }\n                case 195:\n                {\n                    PIXEL00_1L\n                    PIXEL01_C\n                    PIXEL02_1M\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL12_1\n                    PIXEL20_1M\n                    PIXEL21_C\n                    PIXEL22_1R\n                    break;\n                }\n                case 102:\n                {\n                    PIXEL00_1M\n                    PIXEL01_C\n                    PIXEL02_1R\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL12_1\n                    PIXEL20_1L\n                    PIXEL21_C\n                    PIXEL22_1M\n                    break;\n                }\n                case 153:\n                {\n                    PIXEL00_1U\n                    PIXEL01_1\n                    PIXEL02_1M\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL12_C\n                    PIXEL20_1M\n                    PIXEL21_1\n                    PIXEL22_1D\n                    break;\n                }\n                case 58:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_1M\n                    }\n                    else\n                    {\n                        PIXEL00_2\n                    }\n                    PIXEL01_C\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_1M\n                    }\n                    else\n                    {\n                        PIXEL02_2\n                    }\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL12_C\n                    PIXEL20_1D\n                    PIXEL21_1\n                    PIXEL22_1M\n                    break;\n                }\n                case 83:\n                {\n                    PIXEL00_1L\n                    PIXEL01_C\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_1M\n                    }\n                    else\n                    {\n                        PIXEL02_2\n                    }\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL12_C\n                    PIXEL20_1M\n                    PIXEL21_C\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL22_1M\n                    }\n                    else\n                    {\n                        PIXEL22_2\n                    }\n                    break;\n                }\n                case 92:\n                {\n                    PIXEL00_1M\n                    PIXEL01_1\n                    PIXEL02_1U\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL12_C\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_1M\n                    }\n                    else\n                    {\n                        PIXEL20_2\n                    }\n                    PIXEL21_C\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL22_1M\n                    }\n                    else\n                    {\n                        PIXEL22_2\n                    }\n                    break;\n                }\n                case 202:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_1M\n                    }\n                    else\n                    {\n                        PIXEL00_2\n                    }\n                    PIXEL01_C\n                    PIXEL02_1M\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL12_1\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_1M\n                    }\n                    else\n                    {\n                        PIXEL20_2\n                    }\n                    PIXEL21_C\n                    PIXEL22_1R\n                    break;\n                }\n                case 78:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_1M\n                    }\n                    else\n                    {\n                        PIXEL00_2\n                    }\n                    PIXEL01_C\n                    PIXEL02_1R\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL12_1\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_1M\n                    }\n                    else\n                    {\n                        PIXEL20_2\n                    }\n                    PIXEL21_C\n                    PIXEL22_1M\n                    break;\n                }\n                case 154:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_1M\n                    }\n                    else\n                    {\n                        PIXEL00_2\n                    }\n                    PIXEL01_C\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_1M\n                    }\n                    else\n                    {\n                        PIXEL02_2\n                    }\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL12_C\n                    PIXEL20_1M\n                    PIXEL21_1\n                    PIXEL22_1D\n                    break;\n                }\n                case 114:\n                {\n                    PIXEL00_1M\n                    PIXEL01_C\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_1M\n                    }\n                    else\n                    {\n                        PIXEL02_2\n                    }\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL12_C\n                    PIXEL20_1L\n                    PIXEL21_C\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL22_1M\n                    }\n                    else\n                    {\n                        PIXEL22_2\n                    }\n                    break;\n                }\n                case 89:\n                {\n                    PIXEL00_1U\n                    PIXEL01_1\n                    PIXEL02_1M\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL12_C\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_1M\n                    }\n                    else\n                    {\n                        PIXEL20_2\n                    }\n                    PIXEL21_C\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL22_1M\n                    }\n                    else\n                    {\n                        PIXEL22_2\n                    }\n                    break;\n                }\n                case 90:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_1M\n                    }\n                    else\n                    {\n                        PIXEL00_2\n                    }\n                    PIXEL01_C\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_1M\n                    }\n                    else\n                    {\n                        PIXEL02_2\n                    }\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL12_C\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_1M\n                    }\n                    else\n                    {\n                        PIXEL20_2\n                    }\n                    PIXEL21_C\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL22_1M\n                    }\n                    else\n                    {\n                        PIXEL22_2\n                    }\n                    break;\n                }\n                case 55:\n                case 23:\n                {\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL00_1L\n                        PIXEL01_C\n                        PIXEL02_C\n                        PIXEL12_C\n                    }\n                    else\n                    {\n                        PIXEL00_2\n                        PIXEL01_6\n                        PIXEL02_5\n                        PIXEL12_1\n                    }\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL20_2\n                    PIXEL21_1\n                    PIXEL22_1M\n                    break;\n                }\n                case 182:\n                case 150:\n                {\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_C\n                        PIXEL02_C\n                        PIXEL12_C\n                        PIXEL22_1D\n                    }\n                    else\n                    {\n                        PIXEL01_1\n                        PIXEL02_5\n                        PIXEL12_6\n                        PIXEL22_2\n                    }\n                    PIXEL00_1M\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL20_2\n                    PIXEL21_1\n                    break;\n                }\n                case 213:\n                case 212:\n                {\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL02_1U\n                        PIXEL12_C\n                        PIXEL21_C\n                        PIXEL22_C\n                    }\n                    else\n                    {\n                        PIXEL02_2\n                        PIXEL12_6\n                        PIXEL21_1\n                        PIXEL22_5\n                    }\n                    PIXEL00_2\n                    PIXEL01_1\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL20_1M\n                    break;\n                }\n                case 241:\n                case 240:\n                {\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL12_C\n                        PIXEL20_1L\n                        PIXEL21_C\n                        PIXEL22_C\n                    }\n                    else\n                    {\n                        PIXEL12_1\n                        PIXEL20_2\n                        PIXEL21_6\n                        PIXEL22_5\n                    }\n                    PIXEL00_2\n                    PIXEL01_1\n                    PIXEL02_1M\n                    PIXEL10_1\n                    PIXEL11\n                    break;\n                }\n                case 236:\n                case 232:\n                {\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_C\n                        PIXEL20_C\n                        PIXEL21_C\n                        PIXEL22_1R\n                    }\n                    else\n                    {\n                        PIXEL10_1\n                        PIXEL20_5\n                        PIXEL21_6\n                        PIXEL22_2\n                    }\n                    PIXEL00_1M\n                    PIXEL01_1\n                    PIXEL02_2\n                    PIXEL11\n                    PIXEL12_1\n                    break;\n                }\n                case 109:\n                case 105:\n                {\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL00_1U\n                        PIXEL10_C\n                        PIXEL20_C\n                        PIXEL21_C\n                    }\n                    else\n                    {\n                        PIXEL00_2\n                        PIXEL10_6\n                        PIXEL20_5\n                        PIXEL21_1\n                    }\n                    PIXEL01_1\n                    PIXEL02_2\n                    PIXEL11\n                    PIXEL12_1\n                    PIXEL22_1M\n                    break;\n                }\n                case 171:\n                case 43:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_C\n                        PIXEL01_C\n                        PIXEL10_C\n                        PIXEL20_1D\n                    }\n                    else\n                    {\n                        PIXEL00_5\n                        PIXEL01_1\n                        PIXEL10_6\n                        PIXEL20_2\n                    }\n                    PIXEL02_1M\n                    PIXEL11\n                    PIXEL12_1\n                    PIXEL21_1\n                    PIXEL22_2\n                    break;\n                }\n                case 143:\n                case 15:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_C\n                        PIXEL01_C\n                        PIXEL02_1R\n                        PIXEL10_C\n                    }\n                    else\n                    {\n                        PIXEL00_5\n                        PIXEL01_6\n                        PIXEL02_2\n                        PIXEL10_1\n                    }\n                    PIXEL11\n                    PIXEL12_1\n                    PIXEL20_1M\n                    PIXEL21_1\n                    PIXEL22_2\n                    break;\n                }\n                case 124:\n                {\n                    PIXEL00_1M\n                    PIXEL01_1\n                    PIXEL02_1U\n                    PIXEL11\n                    PIXEL12_C\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_C\n                        PIXEL20_C\n                        PIXEL21_C\n                    }\n                    else\n                    {\n                        PIXEL10_3\n                        PIXEL20_4\n                        PIXEL21_3\n                    }\n                    PIXEL22_1M\n                    break;\n                }\n                case 203:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_C\n                        PIXEL01_C\n                        PIXEL10_C\n                    }\n                    else\n                    {\n                        PIXEL00_4\n                        PIXEL01_3\n                        PIXEL10_3\n                    }\n                    PIXEL02_1M\n                    PIXEL11\n                    PIXEL12_1\n                    PIXEL20_1M\n                    PIXEL21_C\n                    PIXEL22_1R\n                    break;\n                }\n                case 62:\n                {\n                    PIXEL00_1M\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_C\n                        PIXEL02_C\n                        PIXEL12_C\n                    }\n                    else\n                    {\n                        PIXEL01_3\n                        PIXEL02_4\n                        PIXEL12_3\n                    }\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL20_1D\n                    PIXEL21_1\n                    PIXEL22_1M\n                    break;\n                }\n                case 211:\n                {\n                    PIXEL00_1L\n                    PIXEL01_C\n                    PIXEL02_1M\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL20_1M\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL12_C\n                        PIXEL21_C\n                        PIXEL22_C\n                    }\n                    else\n                    {\n                        PIXEL12_3\n                        PIXEL21_3\n                        PIXEL22_4\n                    }\n                    break;\n                }\n                case 118:\n                {\n                    PIXEL00_1M\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_C\n                        PIXEL02_C\n                        PIXEL12_C\n                    }\n                    else\n                    {\n                        PIXEL01_3\n                        PIXEL02_4\n                        PIXEL12_3\n                    }\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL20_1L\n                    PIXEL21_C\n                    PIXEL22_1M\n                    break;\n                }\n                case 217:\n                {\n                    PIXEL00_1U\n                    PIXEL01_1\n                    PIXEL02_1M\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL20_1M\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL12_C\n                        PIXEL21_C\n                        PIXEL22_C\n                    }\n                    else\n                    {\n                        PIXEL12_3\n                        PIXEL21_3\n                        PIXEL22_4\n                    }\n                    break;\n                }\n                case 110:\n                {\n                    PIXEL00_1M\n                    PIXEL01_C\n                    PIXEL02_1R\n                    PIXEL11\n                    PIXEL12_1\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_C\n                        PIXEL20_C\n                        PIXEL21_C\n                    }\n                    else\n                    {\n                        PIXEL10_3\n                        PIXEL20_4\n                        PIXEL21_3\n                    }\n                    PIXEL22_1M\n                    break;\n                }\n                case 155:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_C\n                        PIXEL01_C\n                        PIXEL10_C\n                    }\n                    else\n                    {\n                        PIXEL00_4\n                        PIXEL01_3\n                        PIXEL10_3\n                    }\n                    PIXEL02_1M\n                    PIXEL11\n                    PIXEL12_C\n                    PIXEL20_1M\n                    PIXEL21_1\n                    PIXEL22_1D\n                    break;\n                }\n                case 188:\n                {\n                    PIXEL00_1M\n                    PIXEL01_1\n                    PIXEL02_1U\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL12_C\n                    PIXEL20_1D\n                    PIXEL21_1\n                    PIXEL22_1D\n                    break;\n                }\n                case 185:\n                {\n                    PIXEL00_1U\n                    PIXEL01_1\n                    PIXEL02_1M\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL12_C\n                    PIXEL20_1D\n                    PIXEL21_1\n                    PIXEL22_1D\n                    break;\n                }\n                case 61:\n                {\n                    PIXEL00_1U\n                    PIXEL01_1\n                    PIXEL02_1U\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL12_C\n                    PIXEL20_1D\n                    PIXEL21_1\n                    PIXEL22_1M\n                    break;\n                }\n                case 157:\n                {\n                    PIXEL00_1U\n                    PIXEL01_1\n                    PIXEL02_1U\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL12_C\n                    PIXEL20_1M\n                    PIXEL21_1\n                    PIXEL22_1D\n                    break;\n                }\n                case 103:\n                {\n                    PIXEL00_1L\n                    PIXEL01_C\n                    PIXEL02_1R\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL12_1\n                    PIXEL20_1L\n                    PIXEL21_C\n                    PIXEL22_1M\n                    break;\n                }\n                case 227:\n                {\n                    PIXEL00_1L\n                    PIXEL01_C\n                    PIXEL02_1M\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL12_1\n                    PIXEL20_1L\n                    PIXEL21_C\n                    PIXEL22_1R\n                    break;\n                }\n                case 230:\n                {\n                    PIXEL00_1M\n                    PIXEL01_C\n                    PIXEL02_1R\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL12_1\n                    PIXEL20_1L\n                    PIXEL21_C\n                    PIXEL22_1R\n                    break;\n                }\n                case 199:\n                {\n                    PIXEL00_1L\n                    PIXEL01_C\n                    PIXEL02_1R\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL12_1\n                    PIXEL20_1M\n                    PIXEL21_C\n                    PIXEL22_1R\n                    break;\n                }\n                case 220:\n                {\n                    PIXEL00_1M\n                    PIXEL01_1\n                    PIXEL02_1U\n                    PIXEL10_C\n                    PIXEL11\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_1M\n                    }\n                    else\n                    {\n                        PIXEL20_2\n                    }\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL12_C\n                        PIXEL21_C\n                        PIXEL22_C\n                    }\n                    else\n                    {\n                        PIXEL12_3\n                        PIXEL21_3\n                        PIXEL22_4\n                    }\n                    break;\n                }\n                case 158:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_1M\n                    }\n                    else\n                    {\n                        PIXEL00_2\n                    }\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_C\n                        PIXEL02_C\n                        PIXEL12_C\n                    }\n                    else\n                    {\n                        PIXEL01_3\n                        PIXEL02_4\n                        PIXEL12_3\n                    }\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL20_1M\n                    PIXEL21_1\n                    PIXEL22_1D\n                    break;\n                }\n                case 234:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_1M\n                    }\n                    else\n                    {\n                        PIXEL00_2\n                    }\n                    PIXEL01_C\n                    PIXEL02_1M\n                    PIXEL11\n                    PIXEL12_1\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_C\n                        PIXEL20_C\n                        PIXEL21_C\n                    }\n                    else\n                    {\n                        PIXEL10_3\n                        PIXEL20_4\n                        PIXEL21_3\n                    }\n                    PIXEL22_1R\n                    break;\n                }\n                case 242:\n                {\n                    PIXEL00_1M\n                    PIXEL01_C\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_1M\n                    }\n                    else\n                    {\n                        PIXEL02_2\n                    }\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL20_1L\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL12_C\n                        PIXEL21_C\n                        PIXEL22_C\n                    }\n                    else\n                    {\n                        PIXEL12_3\n                        PIXEL21_3\n                        PIXEL22_4\n                    }\n                    break;\n                }\n                case 59:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_C\n                        PIXEL01_C\n                        PIXEL10_C\n                    }\n                    else\n                    {\n                        PIXEL00_4\n                        PIXEL01_3\n                        PIXEL10_3\n                    }\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_1M\n                    }\n                    else\n                    {\n                        PIXEL02_2\n                    }\n                    PIXEL11\n                    PIXEL12_C\n                    PIXEL20_1D\n                    PIXEL21_1\n                    PIXEL22_1M\n                    break;\n                }\n                case 121:\n                {\n                    PIXEL00_1U\n                    PIXEL01_1\n                    PIXEL02_1M\n                    PIXEL11\n                    PIXEL12_C\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_C\n                        PIXEL20_C\n                        PIXEL21_C\n                    }\n                    else\n                    {\n                        PIXEL10_3\n                        PIXEL20_4\n                        PIXEL21_3\n                    }\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL22_1M\n                    }\n                    else\n                    {\n                        PIXEL22_2\n                    }\n                    break;\n                }\n                case 87:\n                {\n                    PIXEL00_1L\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_C\n                        PIXEL02_C\n                        PIXEL12_C\n                    }\n                    else\n                    {\n                        PIXEL01_3\n                        PIXEL02_4\n                        PIXEL12_3\n                    }\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL20_1M\n                    PIXEL21_C\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL22_1M\n                    }\n                    else\n                    {\n                        PIXEL22_2\n                    }\n                    break;\n                }\n                case 79:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_C\n                        PIXEL01_C\n                        PIXEL10_C\n                    }\n                    else\n                    {\n                        PIXEL00_4\n                        PIXEL01_3\n                        PIXEL10_3\n                    }\n                    PIXEL02_1R\n                    PIXEL11\n                    PIXEL12_1\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_1M\n                    }\n                    else\n                    {\n                        PIXEL20_2\n                    }\n                    PIXEL21_C\n                    PIXEL22_1M\n                    break;\n                }\n                case 122:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_1M\n                    }\n                    else\n                    {\n                        PIXEL00_2\n                    }\n                    PIXEL01_C\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_1M\n                    }\n                    else\n                    {\n                        PIXEL02_2\n                    }\n                    PIXEL11\n                    PIXEL12_C\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_C\n                        PIXEL20_C\n                        PIXEL21_C\n                    }\n                    else\n                    {\n                        PIXEL10_3\n                        PIXEL20_4\n                        PIXEL21_3\n                    }\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL22_1M\n                    }\n                    else\n                    {\n                        PIXEL22_2\n                    }\n                    break;\n                }\n                case 94:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_1M\n                    }\n                    else\n                    {\n                        PIXEL00_2\n                    }\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_C\n                        PIXEL02_C\n                        PIXEL12_C\n                    }\n                    else\n                    {\n                        PIXEL01_3\n                        PIXEL02_4\n                        PIXEL12_3\n                    }\n                    PIXEL10_C\n                    PIXEL11\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_1M\n                    }\n                    else\n                    {\n                        PIXEL20_2\n                    }\n                    PIXEL21_C\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL22_1M\n                    }\n                    else\n                    {\n                        PIXEL22_2\n                    }\n                    break;\n                }\n                case 218:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_1M\n                    }\n                    else\n                    {\n                        PIXEL00_2\n                    }\n                    PIXEL01_C\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_1M\n                    }\n                    else\n                    {\n                        PIXEL02_2\n                    }\n                    PIXEL10_C\n                    PIXEL11\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_1M\n                    }\n                    else\n                    {\n                        PIXEL20_2\n                    }\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL12_C\n                        PIXEL21_C\n                        PIXEL22_C\n                    }\n                    else\n                    {\n                        PIXEL12_3\n                        PIXEL21_3\n                        PIXEL22_4\n                    }\n                    break;\n                }\n                case 91:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_C\n                        PIXEL01_C\n                        PIXEL10_C\n                    }\n                    else\n                    {\n                        PIXEL00_4\n                        PIXEL01_3\n                        PIXEL10_3\n                    }\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_1M\n                    }\n                    else\n                    {\n                        PIXEL02_2\n                    }\n                    PIXEL11\n                    PIXEL12_C\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_1M\n                    }\n                    else\n                    {\n                        PIXEL20_2\n                    }\n                    PIXEL21_C\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL22_1M\n                    }\n                    else\n                    {\n                        PIXEL22_2\n                    }\n                    break;\n                }\n                case 229:\n                {\n                    PIXEL00_2\n                    PIXEL01_1\n                    PIXEL02_2\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL12_1\n                    PIXEL20_1L\n                    PIXEL21_C\n                    PIXEL22_1R\n                    break;\n                }\n                case 167:\n                {\n                    PIXEL00_1L\n                    PIXEL01_C\n                    PIXEL02_1R\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL12_1\n                    PIXEL20_2\n                    PIXEL21_1\n                    PIXEL22_2\n                    break;\n                }\n                case 173:\n                {\n                    PIXEL00_1U\n                    PIXEL01_1\n                    PIXEL02_2\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL12_1\n                    PIXEL20_1D\n                    PIXEL21_1\n                    PIXEL22_2\n                    break;\n                }\n                case 181:\n                {\n                    PIXEL00_2\n                    PIXEL01_1\n                    PIXEL02_1U\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL12_C\n                    PIXEL20_2\n                    PIXEL21_1\n                    PIXEL22_1D\n                    break;\n                }\n                case 186:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_1M\n                    }\n                    else\n                    {\n                        PIXEL00_2\n                    }\n                    PIXEL01_C\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_1M\n                    }\n                    else\n                    {\n                        PIXEL02_2\n                    }\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL12_C\n                    PIXEL20_1D\n                    PIXEL21_1\n                    PIXEL22_1D\n                    break;\n                }\n                case 115:\n                {\n                    PIXEL00_1L\n                    PIXEL01_C\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_1M\n                    }\n                    else\n                    {\n                        PIXEL02_2\n                    }\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL12_C\n                    PIXEL20_1L\n                    PIXEL21_C\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL22_1M\n                    }\n                    else\n                    {\n                        PIXEL22_2\n                    }\n                    break;\n                }\n                case 93:\n                {\n                    PIXEL00_1U\n                    PIXEL01_1\n                    PIXEL02_1U\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL12_C\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_1M\n                    }\n                    else\n                    {\n                        PIXEL20_2\n                    }\n                    PIXEL21_C\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL22_1M\n                    }\n                    else\n                    {\n                        PIXEL22_2\n                    }\n                    break;\n                }\n                case 206:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_1M\n                    }\n                    else\n                    {\n                        PIXEL00_2\n                    }\n                    PIXEL01_C\n                    PIXEL02_1R\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL12_1\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_1M\n                    }\n                    else\n                    {\n                        PIXEL20_2\n                    }\n                    PIXEL21_C\n                    PIXEL22_1R\n                    break;\n                }\n                case 205:\n                case 201:\n                {\n                    PIXEL00_1U\n                    PIXEL01_1\n                    PIXEL02_2\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL12_1\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_1M\n                    }\n                    else\n                    {\n                        PIXEL20_2\n                    }\n                    PIXEL21_C\n                    PIXEL22_1R\n                    break;\n                }\n                case 174:\n                case 46:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_1M\n                    }\n                    else\n                    {\n                        PIXEL00_2\n                    }\n                    PIXEL01_C\n                    PIXEL02_1R\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL12_1\n                    PIXEL20_1D\n                    PIXEL21_1\n                    PIXEL22_2\n                    break;\n                }\n                case 179:\n                case 147:\n                {\n                    PIXEL00_1L\n                    PIXEL01_C\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_1M\n                    }\n                    else\n                    {\n                        PIXEL02_2\n                    }\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL12_C\n                    PIXEL20_2\n                    PIXEL21_1\n                    PIXEL22_1D\n                    break;\n                }\n                case 117:\n                case 116:\n                {\n                    PIXEL00_2\n                    PIXEL01_1\n                    PIXEL02_1U\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL12_C\n                    PIXEL20_1L\n                    PIXEL21_C\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL22_1M\n                    }\n                    else\n                    {\n                        PIXEL22_2\n                    }\n                    break;\n                }\n                case 189:\n                {\n                    PIXEL00_1U\n                    PIXEL01_1\n                    PIXEL02_1U\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL12_C\n                    PIXEL20_1D\n                    PIXEL21_1\n                    PIXEL22_1D\n                    break;\n                }\n                case 231:\n                {\n                    PIXEL00_1L\n                    PIXEL01_C\n                    PIXEL02_1R\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL12_1\n                    PIXEL20_1L\n                    PIXEL21_C\n                    PIXEL22_1R\n                    break;\n                }\n                case 126:\n                {\n                    PIXEL00_1M\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_C\n                        PIXEL02_C\n                        PIXEL12_C\n                    }\n                    else\n                    {\n                        PIXEL01_3\n                        PIXEL02_4\n                        PIXEL12_3\n                    }\n                    PIXEL11\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_C\n                        PIXEL20_C\n                        PIXEL21_C\n                    }\n                    else\n                    {\n                        PIXEL10_3\n                        PIXEL20_4\n                        PIXEL21_3\n                    }\n                    PIXEL22_1M\n                    break;\n                }\n                case 219:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_C\n                        PIXEL01_C\n                        PIXEL10_C\n                    }\n                    else\n                    {\n                        PIXEL00_4\n                        PIXEL01_3\n                        PIXEL10_3\n                    }\n                    PIXEL02_1M\n                    PIXEL11\n                    PIXEL20_1M\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL12_C\n                        PIXEL21_C\n                        PIXEL22_C\n                    }\n                    else\n                    {\n                        PIXEL12_3\n                        PIXEL21_3\n                        PIXEL22_4\n                    }\n                    break;\n                }\n                case 125:\n                {\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL00_1U\n                        PIXEL10_C\n                        PIXEL20_C\n                        PIXEL21_C\n                    }\n                    else\n                    {\n                        PIXEL00_2\n                        PIXEL10_6\n                        PIXEL20_5\n                        PIXEL21_1\n                    }\n                    PIXEL01_1\n                    PIXEL02_1U\n                    PIXEL11\n                    PIXEL12_C\n                    PIXEL22_1M\n                    break;\n                }\n                case 221:\n                {\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL02_1U\n                        PIXEL12_C\n                        PIXEL21_C\n                        PIXEL22_C\n                    }\n                    else\n                    {\n                        PIXEL02_2\n                        PIXEL12_6\n                        PIXEL21_1\n                        PIXEL22_5\n                    }\n                    PIXEL00_1U\n                    PIXEL01_1\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL20_1M\n                    break;\n                }\n                case 207:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_C\n                        PIXEL01_C\n                        PIXEL02_1R\n                        PIXEL10_C\n                    }\n                    else\n                    {\n                        PIXEL00_5\n                        PIXEL01_6\n                        PIXEL02_2\n                        PIXEL10_1\n                    }\n                    PIXEL11\n                    PIXEL12_1\n                    PIXEL20_1M\n                    PIXEL21_C\n                    PIXEL22_1R\n                    break;\n                }\n                case 238:\n                {\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_C\n                        PIXEL20_C\n                        PIXEL21_C\n                        PIXEL22_1R\n                    }\n                    else\n                    {\n                        PIXEL10_1\n                        PIXEL20_5\n                        PIXEL21_6\n                        PIXEL22_2\n                    }\n                    PIXEL00_1M\n                    PIXEL01_C\n                    PIXEL02_1R\n                    PIXEL11\n                    PIXEL12_1\n                    break;\n                }\n                case 190:\n                {\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_C\n                        PIXEL02_C\n                        PIXEL12_C\n                        PIXEL22_1D\n                    }\n                    else\n                    {\n                        PIXEL01_1\n                        PIXEL02_5\n                        PIXEL12_6\n                        PIXEL22_2\n                    }\n                    PIXEL00_1M\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL20_1D\n                    PIXEL21_1\n                    break;\n                }\n                case 187:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_C\n                        PIXEL01_C\n                        PIXEL10_C\n                        PIXEL20_1D\n                    }\n                    else\n                    {\n                        PIXEL00_5\n                        PIXEL01_1\n                        PIXEL10_6\n                        PIXEL20_2\n                    }\n                    PIXEL02_1M\n                    PIXEL11\n                    PIXEL12_C\n                    PIXEL21_1\n                    PIXEL22_1D\n                    break;\n                }\n                case 243:\n                {\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL12_C\n                        PIXEL20_1L\n                        PIXEL21_C\n                        PIXEL22_C\n                    }\n                    else\n                    {\n                        PIXEL12_1\n                        PIXEL20_2\n                        PIXEL21_6\n                        PIXEL22_5\n                    }\n                    PIXEL00_1L\n                    PIXEL01_C\n                    PIXEL02_1M\n                    PIXEL10_1\n                    PIXEL11\n                    break;\n                }\n                case 119:\n                {\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL00_1L\n                        PIXEL01_C\n                        PIXEL02_C\n                        PIXEL12_C\n                    }\n                    else\n                    {\n                        PIXEL00_2\n                        PIXEL01_6\n                        PIXEL02_5\n                        PIXEL12_1\n                    }\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL20_1L\n                    PIXEL21_C\n                    PIXEL22_1M\n                    break;\n                }\n                case 237:\n                case 233:\n                {\n                    PIXEL00_1U\n                    PIXEL01_1\n                    PIXEL02_2\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL12_1\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_C\n                    }\n                    else\n                    {\n                        PIXEL20_2\n                    }\n                    PIXEL21_C\n                    PIXEL22_1R\n                    break;\n                }\n                case 175:\n                case 47:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_C\n                    }\n                    else\n                    {\n                        PIXEL00_2\n                    }\n                    PIXEL01_C\n                    PIXEL02_1R\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL12_1\n                    PIXEL20_1D\n                    PIXEL21_1\n                    PIXEL22_2\n                    break;\n                }\n                case 183:\n                case 151:\n                {\n                    PIXEL00_1L\n                    PIXEL01_C\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_C\n                    }\n                    else\n                    {\n                        PIXEL02_2\n                    }\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL12_C\n                    PIXEL20_2\n                    PIXEL21_1\n                    PIXEL22_1D\n                    break;\n                }\n                case 245:\n                case 244:\n                {\n                    PIXEL00_2\n                    PIXEL01_1\n                    PIXEL02_1U\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL12_C\n                    PIXEL20_1L\n                    PIXEL21_C\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL22_C\n                    }\n                    else\n                    {\n                        PIXEL22_2\n                    }\n                    break;\n                }\n                case 250:\n                {\n                    PIXEL00_1M\n                    PIXEL01_C\n                    PIXEL02_1M\n                    PIXEL11\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_C\n                        PIXEL20_C\n                    }\n                    else\n                    {\n                        PIXEL10_3\n                        PIXEL20_4\n                    }\n                    PIXEL21_C\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL12_C\n                        PIXEL22_C\n                    }\n                    else\n                    {\n                        PIXEL12_3\n                        PIXEL22_4\n                    }\n                    break;\n                }\n                case 123:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_C\n                        PIXEL01_C\n                    }\n                    else\n                    {\n                        PIXEL00_4\n                        PIXEL01_3\n                    }\n                    PIXEL02_1M\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL12_C\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_C\n                        PIXEL21_C\n                    }\n                    else\n                    {\n                        PIXEL20_4\n                        PIXEL21_3\n                    }\n                    PIXEL22_1M\n                    break;\n                }\n                case 95:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_C\n                        PIXEL10_C\n                    }\n                    else\n                    {\n                        PIXEL00_4\n                        PIXEL10_3\n                    }\n                    PIXEL01_C\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_C\n                        PIXEL12_C\n                    }\n                    else\n                    {\n                        PIXEL02_4\n                        PIXEL12_3\n                    }\n                    PIXEL11\n                    PIXEL20_1M\n                    PIXEL21_C\n                    PIXEL22_1M\n                    break;\n                }\n                case 222:\n                {\n                    PIXEL00_1M\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_C\n                        PIXEL02_C\n                    }\n                    else\n                    {\n                        PIXEL01_3\n                        PIXEL02_4\n                    }\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL12_C\n                    PIXEL20_1M\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL21_C\n                        PIXEL22_C\n                    }\n                    else\n                    {\n                        PIXEL21_3\n                        PIXEL22_4\n                    }\n                    break;\n                }\n                case 252:\n                {\n                    PIXEL00_1M\n                    PIXEL01_1\n                    PIXEL02_1U\n                    PIXEL11\n                    PIXEL12_C\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_C\n                        PIXEL20_C\n                    }\n                    else\n                    {\n                        PIXEL10_3\n                        PIXEL20_4\n                    }\n                    PIXEL21_C\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL22_C\n                    }\n                    else\n                    {\n                        PIXEL22_2\n                    }\n                    break;\n                }\n                case 249:\n                {\n                    PIXEL00_1U\n                    PIXEL01_1\n                    PIXEL02_1M\n                    PIXEL10_C\n                    PIXEL11\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_C\n                    }\n                    else\n                    {\n                        PIXEL20_2\n                    }\n                    PIXEL21_C\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL12_C\n                        PIXEL22_C\n                    }\n                    else\n                    {\n                        PIXEL12_3\n                        PIXEL22_4\n                    }\n                    break;\n                }\n                case 235:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_C\n                        PIXEL01_C\n                    }\n                    else\n                    {\n                        PIXEL00_4\n                        PIXEL01_3\n                    }\n                    PIXEL02_1M\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL12_1\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_C\n                    }\n                    else\n                    {\n                        PIXEL20_2\n                    }\n                    PIXEL21_C\n                    PIXEL22_1R\n                    break;\n                }\n                case 111:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_C\n                    }\n                    else\n                    {\n                        PIXEL00_2\n                    }\n                    PIXEL01_C\n                    PIXEL02_1R\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL12_1\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_C\n                        PIXEL21_C\n                    }\n                    else\n                    {\n                        PIXEL20_4\n                        PIXEL21_3\n                    }\n                    PIXEL22_1M\n                    break;\n                }\n                case 63:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_C\n                    }\n                    else\n                    {\n                        PIXEL00_2\n                    }\n                    PIXEL01_C\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_C\n                        PIXEL12_C\n                    }\n                    else\n                    {\n                        PIXEL02_4\n                        PIXEL12_3\n                    }\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL20_1D\n                    PIXEL21_1\n                    PIXEL22_1M\n                    break;\n                }\n                case 159:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_C\n                        PIXEL10_C\n                    }\n                    else\n                    {\n                        PIXEL00_4\n                        PIXEL10_3\n                    }\n                    PIXEL01_C\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_C\n                    }\n                    else\n                    {\n                        PIXEL02_2\n                    }\n                    PIXEL11\n                    PIXEL12_C\n                    PIXEL20_1M\n                    PIXEL21_1\n                    PIXEL22_1D\n                    break;\n                }\n                case 215:\n                {\n                    PIXEL00_1L\n                    PIXEL01_C\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_C\n                    }\n                    else\n                    {\n                        PIXEL02_2\n                    }\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL12_C\n                    PIXEL20_1M\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL21_C\n                        PIXEL22_C\n                    }\n                    else\n                    {\n                        PIXEL21_3\n                        PIXEL22_4\n                    }\n                    break;\n                }\n                case 246:\n                {\n                    PIXEL00_1M\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_C\n                        PIXEL02_C\n                    }\n                    else\n                    {\n                        PIXEL01_3\n                        PIXEL02_4\n                    }\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL12_C\n                    PIXEL20_1L\n                    PIXEL21_C\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL22_C\n                    }\n                    else\n                    {\n                        PIXEL22_2\n                    }\n                    break;\n                }\n                case 254:\n                {\n                    PIXEL00_1M\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_C\n                        PIXEL02_C\n                    }\n                    else\n                    {\n                        PIXEL01_3\n                        PIXEL02_4\n                    }\n                    PIXEL11\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_C\n                        PIXEL20_C\n                    }\n                    else\n                    {\n                        PIXEL10_3\n                        PIXEL20_4\n                    }\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL12_C\n                        PIXEL21_C\n                        PIXEL22_C\n                    }\n                    else\n                    {\n                        PIXEL12_3\n                        PIXEL21_3\n                        PIXEL22_2\n                    }\n                    break;\n                }\n                case 253:\n                {\n                    PIXEL00_1U\n                    PIXEL01_1\n                    PIXEL02_1U\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL12_C\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_C\n                    }\n                    else\n                    {\n                        PIXEL20_2\n                    }\n                    PIXEL21_C\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL22_C\n                    }\n                    else\n                    {\n                        PIXEL22_2\n                    }\n                    break;\n                }\n                case 251:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_C\n                        PIXEL01_C\n                    }\n                    else\n                    {\n                        PIXEL00_4\n                        PIXEL01_3\n                    }\n                    PIXEL02_1M\n                    PIXEL11\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL10_C\n                        PIXEL20_C\n                        PIXEL21_C\n                    }\n                    else\n                    {\n                        PIXEL10_3\n                        PIXEL20_2\n                        PIXEL21_3\n                    }\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL12_C\n                        PIXEL22_C\n                    }\n                    else\n                    {\n                        PIXEL12_3\n                        PIXEL22_4\n                    }\n                    break;\n                }\n                case 239:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_C\n                    }\n                    else\n                    {\n                        PIXEL00_2\n                    }\n                    PIXEL01_C\n                    PIXEL02_1R\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL12_1\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_C\n                    }\n                    else\n                    {\n                        PIXEL20_2\n                    }\n                    PIXEL21_C\n                    PIXEL22_1R\n                    break;\n                }\n                case 127:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_C\n                        PIXEL01_C\n                        PIXEL10_C\n                    }\n                    else\n                    {\n                        PIXEL00_2\n                        PIXEL01_3\n                        PIXEL10_3\n                    }\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_C\n                        PIXEL12_C\n                    }\n                    else\n                    {\n                        PIXEL02_4\n                        PIXEL12_3\n                    }\n                    PIXEL11\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_C\n                        PIXEL21_C\n                    }\n                    else\n                    {\n                        PIXEL20_4\n                        PIXEL21_3\n                    }\n                    PIXEL22_1M\n                    break;\n                }\n                case 191:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_C\n                    }\n                    else\n                    {\n                        PIXEL00_2\n                    }\n                    PIXEL01_C\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_C\n                    }\n                    else\n                    {\n                        PIXEL02_2\n                    }\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL12_C\n                    PIXEL20_1D\n                    PIXEL21_1\n                    PIXEL22_1D\n                    break;\n                }\n                case 223:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_C\n                        PIXEL10_C\n                    }\n                    else\n                    {\n                        PIXEL00_4\n                        PIXEL10_3\n                    }\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL01_C\n                        PIXEL02_C\n                        PIXEL12_C\n                    }\n                    else\n                    {\n                        PIXEL01_3\n                        PIXEL02_2\n                        PIXEL12_3\n                    }\n                    PIXEL11\n                    PIXEL20_1M\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL21_C\n                        PIXEL22_C\n                    }\n                    else\n                    {\n                        PIXEL21_3\n                        PIXEL22_4\n                    }\n                    break;\n                }\n                case 247:\n                {\n                    PIXEL00_1L\n                    PIXEL01_C\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_C\n                    }\n                    else\n                    {\n                        PIXEL02_2\n                    }\n                    PIXEL10_1\n                    PIXEL11\n                    PIXEL12_C\n                    PIXEL20_1L\n                    PIXEL21_C\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL22_C\n                    }\n                    else\n                    {\n                        PIXEL22_2\n                    }\n                    break;\n                }\n                case 255:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_C\n                    }\n                    else\n                    {\n                        PIXEL00_2\n                    }\n                    PIXEL01_C\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_C\n                    }\n                    else\n                    {\n                        PIXEL02_2\n                    }\n                    PIXEL10_C\n                    PIXEL11\n                    PIXEL12_C\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_C\n                    }\n                    else\n                    {\n                        PIXEL20_2\n                    }\n                    PIXEL21_C\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL22_C\n                    }\n                    else\n                    {\n                        PIXEL22_2\n                    }\n                    break;\n                }\n            }\n            sp++;\n            dp += 3;\n        }\n\n        sRowP += srb;\n        sp = (const uint32_t*) sRowP;\n\n        dRowP += drb * 3;\n        dp = (uint32_t*) dRowP;\n    }\n}\n\nHQX_API void HQX_CALLCONV hq3x_32(const uint32_t* sp, uint32_t* dp, int Xres, int Yres )\n{\n    uint32_t rowBytesL = Xres * 4;\n    hq3x_32_rb(sp, rowBytesL, dp, rowBytesL * 3, Xres, Yres);\n}\n"
  },
  {
    "path": "src/Engine/Scalers/hq4x.cpp",
    "content": "/*\n * Copyright (C) 2003 Maxim Stepin ( maxst@hiend3d.com )\n *\n * Copyright (C) 2010 Cameron Zemek ( grom@zeminvaders.net)\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n */\n\n#include <stdint.h>\n#include \"common.h\"\n#include \"hqx.h\"\n\n#define PIXEL00_0     *dp = w[5];\n#define PIXEL00_11    *dp = Interp1(w[5], w[4]);\n#define PIXEL00_12    *dp = Interp1(w[5], w[2]);\n#define PIXEL00_20    *dp = Interp2(w[5], w[2], w[4]);\n#define PIXEL00_50    *dp = Interp5(w[2], w[4]);\n#define PIXEL00_80    *dp = Interp8(w[5], w[1]);\n#define PIXEL00_81    *dp = Interp8(w[5], w[4]);\n#define PIXEL00_82    *dp = Interp8(w[5], w[2]);\n#define PIXEL01_0     *(dp+1) = w[5];\n#define PIXEL01_10    *(dp+1) = Interp1(w[5], w[1]);\n#define PIXEL01_12    *(dp+1) = Interp1(w[5], w[2]);\n#define PIXEL01_14    *(dp+1) = Interp1(w[2], w[5]);\n#define PIXEL01_21    *(dp+1) = Interp2(w[2], w[5], w[4]);\n#define PIXEL01_31    *(dp+1) = Interp3(w[5], w[4]);\n#define PIXEL01_50    *(dp+1) = Interp5(w[2], w[5]);\n#define PIXEL01_60    *(dp+1) = Interp6(w[5], w[2], w[4]);\n#define PIXEL01_61    *(dp+1) = Interp6(w[5], w[2], w[1]);\n#define PIXEL01_82    *(dp+1) = Interp8(w[5], w[2]);\n#define PIXEL01_83    *(dp+1) = Interp8(w[2], w[4]);\n#define PIXEL02_0     *(dp+2) = w[5];\n#define PIXEL02_10    *(dp+2) = Interp1(w[5], w[3]);\n#define PIXEL02_11    *(dp+2) = Interp1(w[5], w[2]);\n#define PIXEL02_13    *(dp+2) = Interp1(w[2], w[5]);\n#define PIXEL02_21    *(dp+2) = Interp2(w[2], w[5], w[6]);\n#define PIXEL02_32    *(dp+2) = Interp3(w[5], w[6]);\n#define PIXEL02_50    *(dp+2) = Interp5(w[2], w[5]);\n#define PIXEL02_60    *(dp+2) = Interp6(w[5], w[2], w[6]);\n#define PIXEL02_61    *(dp+2) = Interp6(w[5], w[2], w[3]);\n#define PIXEL02_81    *(dp+2) = Interp8(w[5], w[2]);\n#define PIXEL02_83    *(dp+2) = Interp8(w[2], w[6]);\n#define PIXEL03_0     *(dp+3) = w[5];\n#define PIXEL03_11    *(dp+3) = Interp1(w[5], w[2]);\n#define PIXEL03_12    *(dp+3) = Interp1(w[5], w[6]);\n#define PIXEL03_20    *(dp+3) = Interp2(w[5], w[2], w[6]);\n#define PIXEL03_50    *(dp+3) = Interp5(w[2], w[6]);\n#define PIXEL03_80    *(dp+3) = Interp8(w[5], w[3]);\n#define PIXEL03_81    *(dp+3) = Interp8(w[5], w[2]);\n#define PIXEL03_82    *(dp+3) = Interp8(w[5], w[6]);\n#define PIXEL10_0     *(dp+dpL) = w[5];\n#define PIXEL10_10    *(dp+dpL) = Interp1(w[5], w[1]);\n#define PIXEL10_11    *(dp+dpL) = Interp1(w[5], w[4]);\n#define PIXEL10_13    *(dp+dpL) = Interp1(w[4], w[5]);\n#define PIXEL10_21    *(dp+dpL) = Interp2(w[4], w[5], w[2]);\n#define PIXEL10_32    *(dp+dpL) = Interp3(w[5], w[2]);\n#define PIXEL10_50    *(dp+dpL) = Interp5(w[4], w[5]);\n#define PIXEL10_60    *(dp+dpL) = Interp6(w[5], w[4], w[2]);\n#define PIXEL10_61    *(dp+dpL) = Interp6(w[5], w[4], w[1]);\n#define PIXEL10_81    *(dp+dpL) = Interp8(w[5], w[4]);\n#define PIXEL10_83    *(dp+dpL) = Interp8(w[4], w[2]);\n#define PIXEL11_0     *(dp+dpL+1) = w[5];\n#define PIXEL11_30    *(dp+dpL+1) = Interp3(w[5], w[1]);\n#define PIXEL11_31    *(dp+dpL+1) = Interp3(w[5], w[4]);\n#define PIXEL11_32    *(dp+dpL+1) = Interp3(w[5], w[2]);\n#define PIXEL11_70    *(dp+dpL+1) = Interp7(w[5], w[4], w[2]);\n#define PIXEL12_0     *(dp+dpL+2) = w[5];\n#define PIXEL12_30    *(dp+dpL+2) = Interp3(w[5], w[3]);\n#define PIXEL12_31    *(dp+dpL+2) = Interp3(w[5], w[2]);\n#define PIXEL12_32    *(dp+dpL+2) = Interp3(w[5], w[6]);\n#define PIXEL12_70    *(dp+dpL+2) = Interp7(w[5], w[6], w[2]);\n#define PIXEL13_0     *(dp+dpL+3) = w[5];\n#define PIXEL13_10    *(dp+dpL+3) = Interp1(w[5], w[3]);\n#define PIXEL13_12    *(dp+dpL+3) = Interp1(w[5], w[6]);\n#define PIXEL13_14    *(dp+dpL+3) = Interp1(w[6], w[5]);\n#define PIXEL13_21    *(dp+dpL+3) = Interp2(w[6], w[5], w[2]);\n#define PIXEL13_31    *(dp+dpL+3) = Interp3(w[5], w[2]);\n#define PIXEL13_50    *(dp+dpL+3) = Interp5(w[6], w[5]);\n#define PIXEL13_60    *(dp+dpL+3) = Interp6(w[5], w[6], w[2]);\n#define PIXEL13_61    *(dp+dpL+3) = Interp6(w[5], w[6], w[3]);\n#define PIXEL13_82    *(dp+dpL+3) = Interp8(w[5], w[6]);\n#define PIXEL13_83    *(dp+dpL+3) = Interp8(w[6], w[2]);\n#define PIXEL20_0     *(dp+dpL+dpL) = w[5];\n#define PIXEL20_10    *(dp+dpL+dpL) = Interp1(w[5], w[7]);\n#define PIXEL20_12    *(dp+dpL+dpL) = Interp1(w[5], w[4]);\n#define PIXEL20_14    *(dp+dpL+dpL) = Interp1(w[4], w[5]);\n#define PIXEL20_21    *(dp+dpL+dpL) = Interp2(w[4], w[5], w[8]);\n#define PIXEL20_31    *(dp+dpL+dpL) = Interp3(w[5], w[8]);\n#define PIXEL20_50    *(dp+dpL+dpL) = Interp5(w[4], w[5]);\n#define PIXEL20_60    *(dp+dpL+dpL) = Interp6(w[5], w[4], w[8]);\n#define PIXEL20_61    *(dp+dpL+dpL) = Interp6(w[5], w[4], w[7]);\n#define PIXEL20_82    *(dp+dpL+dpL) = Interp8(w[5], w[4]);\n#define PIXEL20_83    *(dp+dpL+dpL) = Interp8(w[4], w[8]);\n#define PIXEL21_0     *(dp+dpL+dpL+1) = w[5];\n#define PIXEL21_30    *(dp+dpL+dpL+1) = Interp3(w[5], w[7]);\n#define PIXEL21_31    *(dp+dpL+dpL+1) = Interp3(w[5], w[8]);\n#define PIXEL21_32    *(dp+dpL+dpL+1) = Interp3(w[5], w[4]);\n#define PIXEL21_70    *(dp+dpL+dpL+1) = Interp7(w[5], w[4], w[8]);\n#define PIXEL22_0     *(dp+dpL+dpL+2) = w[5];\n#define PIXEL22_30    *(dp+dpL+dpL+2) = Interp3(w[5], w[9]);\n#define PIXEL22_31    *(dp+dpL+dpL+2) = Interp3(w[5], w[6]);\n#define PIXEL22_32    *(dp+dpL+dpL+2) = Interp3(w[5], w[8]);\n#define PIXEL22_70    *(dp+dpL+dpL+2) = Interp7(w[5], w[6], w[8]);\n#define PIXEL23_0     *(dp+dpL+dpL+3) = w[5];\n#define PIXEL23_10    *(dp+dpL+dpL+3) = Interp1(w[5], w[9]);\n#define PIXEL23_11    *(dp+dpL+dpL+3) = Interp1(w[5], w[6]);\n#define PIXEL23_13    *(dp+dpL+dpL+3) = Interp1(w[6], w[5]);\n#define PIXEL23_21    *(dp+dpL+dpL+3) = Interp2(w[6], w[5], w[8]);\n#define PIXEL23_32    *(dp+dpL+dpL+3) = Interp3(w[5], w[8]);\n#define PIXEL23_50    *(dp+dpL+dpL+3) = Interp5(w[6], w[5]);\n#define PIXEL23_60    *(dp+dpL+dpL+3) = Interp6(w[5], w[6], w[8]);\n#define PIXEL23_61    *(dp+dpL+dpL+3) = Interp6(w[5], w[6], w[9]);\n#define PIXEL23_81    *(dp+dpL+dpL+3) = Interp8(w[5], w[6]);\n#define PIXEL23_83    *(dp+dpL+dpL+3) = Interp8(w[6], w[8]);\n#define PIXEL30_0     *(dp+dpL+dpL+dpL) = w[5];\n#define PIXEL30_11    *(dp+dpL+dpL+dpL) = Interp1(w[5], w[8]);\n#define PIXEL30_12    *(dp+dpL+dpL+dpL) = Interp1(w[5], w[4]);\n#define PIXEL30_20    *(dp+dpL+dpL+dpL) = Interp2(w[5], w[8], w[4]);\n#define PIXEL30_50    *(dp+dpL+dpL+dpL) = Interp5(w[8], w[4]);\n#define PIXEL30_80    *(dp+dpL+dpL+dpL) = Interp8(w[5], w[7]);\n#define PIXEL30_81    *(dp+dpL+dpL+dpL) = Interp8(w[5], w[8]);\n#define PIXEL30_82    *(dp+dpL+dpL+dpL) = Interp8(w[5], w[4]);\n#define PIXEL31_0     *(dp+dpL+dpL+dpL+1) = w[5];\n#define PIXEL31_10    *(dp+dpL+dpL+dpL+1) = Interp1(w[5], w[7]);\n#define PIXEL31_11    *(dp+dpL+dpL+dpL+1) = Interp1(w[5], w[8]);\n#define PIXEL31_13    *(dp+dpL+dpL+dpL+1) = Interp1(w[8], w[5]);\n#define PIXEL31_21    *(dp+dpL+dpL+dpL+1) = Interp2(w[8], w[5], w[4]);\n#define PIXEL31_32    *(dp+dpL+dpL+dpL+1) = Interp3(w[5], w[4]);\n#define PIXEL31_50    *(dp+dpL+dpL+dpL+1) = Interp5(w[8], w[5]);\n#define PIXEL31_60    *(dp+dpL+dpL+dpL+1) = Interp6(w[5], w[8], w[4]);\n#define PIXEL31_61    *(dp+dpL+dpL+dpL+1) = Interp6(w[5], w[8], w[7]);\n#define PIXEL31_81    *(dp+dpL+dpL+dpL+1) = Interp8(w[5], w[8]);\n#define PIXEL31_83    *(dp+dpL+dpL+dpL+1) = Interp8(w[8], w[4]);\n#define PIXEL32_0     *(dp+dpL+dpL+dpL+2) = w[5];\n#define PIXEL32_10    *(dp+dpL+dpL+dpL+2) = Interp1(w[5], w[9]);\n#define PIXEL32_12    *(dp+dpL+dpL+dpL+2) = Interp1(w[5], w[8]);\n#define PIXEL32_14    *(dp+dpL+dpL+dpL+2) = Interp1(w[8], w[5]);\n#define PIXEL32_21    *(dp+dpL+dpL+dpL+2) = Interp2(w[8], w[5], w[6]);\n#define PIXEL32_31    *(dp+dpL+dpL+dpL+2) = Interp3(w[5], w[6]);\n#define PIXEL32_50    *(dp+dpL+dpL+dpL+2) = Interp5(w[8], w[5]);\n#define PIXEL32_60    *(dp+dpL+dpL+dpL+2) = Interp6(w[5], w[8], w[6]);\n#define PIXEL32_61    *(dp+dpL+dpL+dpL+2) = Interp6(w[5], w[8], w[9]);\n#define PIXEL32_82    *(dp+dpL+dpL+dpL+2) = Interp8(w[5], w[8]);\n#define PIXEL32_83    *(dp+dpL+dpL+dpL+2) = Interp8(w[8], w[6]);\n#define PIXEL33_0     *(dp+dpL+dpL+dpL+3) = w[5];\n#define PIXEL33_11    *(dp+dpL+dpL+dpL+3) = Interp1(w[5], w[6]);\n#define PIXEL33_12    *(dp+dpL+dpL+dpL+3) = Interp1(w[5], w[8]);\n#define PIXEL33_20    *(dp+dpL+dpL+dpL+3) = Interp2(w[5], w[8], w[6]);\n#define PIXEL33_50    *(dp+dpL+dpL+dpL+3) = Interp5(w[8], w[6]);\n#define PIXEL33_80    *(dp+dpL+dpL+dpL+3) = Interp8(w[5], w[9]);\n#define PIXEL33_81    *(dp+dpL+dpL+dpL+3) = Interp8(w[5], w[6]);\n#define PIXEL33_82    *(dp+dpL+dpL+dpL+3) = Interp8(w[5], w[8]);\n\nHQX_API void HQX_CALLCONV hq4x_32_rb(const uint32_t* sp, uint32_t srb, uint32_t* dp, uint32_t drb, int Xres, int Yres )\n{\n    int  i, j, k;\n    int  prevline, nextline;\n    uint32_t w[10];\n    int dpL = (drb >> 2);\n    int spL = (srb >> 2);\n    const uint8_t* sRowP = (const uint8_t*) sp;\n    const uint8_t* dRowP = (const uint8_t*) dp;\n    uint32_t yuv1, yuv2;\n\n    //   +----+----+----+\n    //   |    |    |    |\n    //   | w1 | w2 | w3 |\n    //   +----+----+----+\n    //   |    |    |    |\n    //   | w4 | w5 | w6 |\n    //   +----+----+----+\n    //   |    |    |    |\n    //   | w7 | w8 | w9 |\n    //   +----+----+----+\n\n    for (j=0; j<Yres; j++)\n    {\n        if (j>0)      prevline = -spL;\n        else prevline = 0;\n        if (j<Yres-1) nextline =  spL;\n        else nextline = 0;\n\n        for (i=0; i<Xres; i++)\n        {\n            w[2] = *(sp + prevline);\n            w[5] = *sp;\n            w[8] = *(sp + nextline);\n\n            if (i>0)\n            {\n                w[1] = *(sp + prevline - 1);\n                w[4] = *(sp - 1);\n                w[7] = *(sp + nextline - 1);\n            }\n            else\n            {\n                w[1] = w[2];\n                w[4] = w[5];\n                w[7] = w[8];\n            }\n\n            if (i<Xres-1)\n            {\n                w[3] = *(sp + prevline + 1);\n                w[6] = *(sp + 1);\n                w[9] = *(sp + nextline + 1);\n            }\n            else\n            {\n                w[3] = w[2];\n                w[6] = w[5];\n                w[9] = w[8];\n            }\n\n            int pattern = 0;\n            int flag = 1;\n\n            yuv1 = rgb_to_yuv(w[5]);\n\n            for (k=1; k<=9; k++)\n            {\n                if (k==5) continue;\n\n                if ( w[k] != w[5] )\n                {\n                    yuv2 = rgb_to_yuv(w[k]);\n                    if (yuv_diff(yuv1, yuv2))\n                        pattern |= flag;\n                }\n                flag <<= 1;\n            }\n\n            switch (pattern)\n            {\n                case 0:\n                case 1:\n                case 4:\n                case 32:\n                case 128:\n                case 5:\n                case 132:\n                case 160:\n                case 33:\n                case 129:\n                case 36:\n                case 133:\n                case 164:\n                case 161:\n                case 37:\n                case 165:\n                {\n                    PIXEL00_20\n                    PIXEL01_60\n                    PIXEL02_60\n                    PIXEL03_20\n                    PIXEL10_60\n                    PIXEL11_70\n                    PIXEL12_70\n                    PIXEL13_60\n                    PIXEL20_60\n                    PIXEL21_70\n                    PIXEL22_70\n                    PIXEL23_60\n                    PIXEL30_20\n                    PIXEL31_60\n                    PIXEL32_60\n                    PIXEL33_20\n                    break;\n                }\n                case 2:\n                case 34:\n                case 130:\n                case 162:\n                {\n                    PIXEL00_80\n                    PIXEL01_10\n                    PIXEL02_10\n                    PIXEL03_80\n                    PIXEL10_61\n                    PIXEL11_30\n                    PIXEL12_30\n                    PIXEL13_61\n                    PIXEL20_60\n                    PIXEL21_70\n                    PIXEL22_70\n                    PIXEL23_60\n                    PIXEL30_20\n                    PIXEL31_60\n                    PIXEL32_60\n                    PIXEL33_20\n                    break;\n                }\n                case 16:\n                case 17:\n                case 48:\n                case 49:\n                {\n                    PIXEL00_20\n                    PIXEL01_60\n                    PIXEL02_61\n                    PIXEL03_80\n                    PIXEL10_60\n                    PIXEL11_70\n                    PIXEL12_30\n                    PIXEL13_10\n                    PIXEL20_60\n                    PIXEL21_70\n                    PIXEL22_30\n                    PIXEL23_10\n                    PIXEL30_20\n                    PIXEL31_60\n                    PIXEL32_61\n                    PIXEL33_80\n                    break;\n                }\n                case 64:\n                case 65:\n                case 68:\n                case 69:\n                {\n                    PIXEL00_20\n                    PIXEL01_60\n                    PIXEL02_60\n                    PIXEL03_20\n                    PIXEL10_60\n                    PIXEL11_70\n                    PIXEL12_70\n                    PIXEL13_60\n                    PIXEL20_61\n                    PIXEL21_30\n                    PIXEL22_30\n                    PIXEL23_61\n                    PIXEL30_80\n                    PIXEL31_10\n                    PIXEL32_10\n                    PIXEL33_80\n                    break;\n                }\n                case 8:\n                case 12:\n                case 136:\n                case 140:\n                {\n                    PIXEL00_80\n                    PIXEL01_61\n                    PIXEL02_60\n                    PIXEL03_20\n                    PIXEL10_10\n                    PIXEL11_30\n                    PIXEL12_70\n                    PIXEL13_60\n                    PIXEL20_10\n                    PIXEL21_30\n                    PIXEL22_70\n                    PIXEL23_60\n                    PIXEL30_80\n                    PIXEL31_61\n                    PIXEL32_60\n                    PIXEL33_20\n                    break;\n                }\n                case 3:\n                case 35:\n                case 131:\n                case 163:\n                {\n                    PIXEL00_81\n                    PIXEL01_31\n                    PIXEL02_10\n                    PIXEL03_80\n                    PIXEL10_81\n                    PIXEL11_31\n                    PIXEL12_30\n                    PIXEL13_61\n                    PIXEL20_60\n                    PIXEL21_70\n                    PIXEL22_70\n                    PIXEL23_60\n                    PIXEL30_20\n                    PIXEL31_60\n                    PIXEL32_60\n                    PIXEL33_20\n                    break;\n                }\n                case 6:\n                case 38:\n                case 134:\n                case 166:\n                {\n                    PIXEL00_80\n                    PIXEL01_10\n                    PIXEL02_32\n                    PIXEL03_82\n                    PIXEL10_61\n                    PIXEL11_30\n                    PIXEL12_32\n                    PIXEL13_82\n                    PIXEL20_60\n                    PIXEL21_70\n                    PIXEL22_70\n                    PIXEL23_60\n                    PIXEL30_20\n                    PIXEL31_60\n                    PIXEL32_60\n                    PIXEL33_20\n                    break;\n                }\n                case 20:\n                case 21:\n                case 52:\n                case 53:\n                {\n                    PIXEL00_20\n                    PIXEL01_60\n                    PIXEL02_81\n                    PIXEL03_81\n                    PIXEL10_60\n                    PIXEL11_70\n                    PIXEL12_31\n                    PIXEL13_31\n                    PIXEL20_60\n                    PIXEL21_70\n                    PIXEL22_30\n                    PIXEL23_10\n                    PIXEL30_20\n                    PIXEL31_60\n                    PIXEL32_61\n                    PIXEL33_80\n                    break;\n                }\n                case 144:\n                case 145:\n                case 176:\n                case 177:\n                {\n                    PIXEL00_20\n                    PIXEL01_60\n                    PIXEL02_61\n                    PIXEL03_80\n                    PIXEL10_60\n                    PIXEL11_70\n                    PIXEL12_30\n                    PIXEL13_10\n                    PIXEL20_60\n                    PIXEL21_70\n                    PIXEL22_32\n                    PIXEL23_32\n                    PIXEL30_20\n                    PIXEL31_60\n                    PIXEL32_82\n                    PIXEL33_82\n                    break;\n                }\n                case 192:\n                case 193:\n                case 196:\n                case 197:\n                {\n                    PIXEL00_20\n                    PIXEL01_60\n                    PIXEL02_60\n                    PIXEL03_20\n                    PIXEL10_60\n                    PIXEL11_70\n                    PIXEL12_70\n                    PIXEL13_60\n                    PIXEL20_61\n                    PIXEL21_30\n                    PIXEL22_31\n                    PIXEL23_81\n                    PIXEL30_80\n                    PIXEL31_10\n                    PIXEL32_31\n                    PIXEL33_81\n                    break;\n                }\n                case 96:\n                case 97:\n                case 100:\n                case 101:\n                {\n                    PIXEL00_20\n                    PIXEL01_60\n                    PIXEL02_60\n                    PIXEL03_20\n                    PIXEL10_60\n                    PIXEL11_70\n                    PIXEL12_70\n                    PIXEL13_60\n                    PIXEL20_82\n                    PIXEL21_32\n                    PIXEL22_30\n                    PIXEL23_61\n                    PIXEL30_82\n                    PIXEL31_32\n                    PIXEL32_10\n                    PIXEL33_80\n                    break;\n                }\n                case 40:\n                case 44:\n                case 168:\n                case 172:\n                {\n                    PIXEL00_80\n                    PIXEL01_61\n                    PIXEL02_60\n                    PIXEL03_20\n                    PIXEL10_10\n                    PIXEL11_30\n                    PIXEL12_70\n                    PIXEL13_60\n                    PIXEL20_31\n                    PIXEL21_31\n                    PIXEL22_70\n                    PIXEL23_60\n                    PIXEL30_81\n                    PIXEL31_81\n                    PIXEL32_60\n                    PIXEL33_20\n                    break;\n                }\n                case 9:\n                case 13:\n                case 137:\n                case 141:\n                {\n                    PIXEL00_82\n                    PIXEL01_82\n                    PIXEL02_60\n                    PIXEL03_20\n                    PIXEL10_32\n                    PIXEL11_32\n                    PIXEL12_70\n                    PIXEL13_60\n                    PIXEL20_10\n                    PIXEL21_30\n                    PIXEL22_70\n                    PIXEL23_60\n                    PIXEL30_80\n                    PIXEL31_61\n                    PIXEL32_60\n                    PIXEL33_20\n                    break;\n                }\n                case 18:\n                case 50:\n                {\n                    PIXEL00_80\n                    PIXEL01_10\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_10\n                        PIXEL03_80\n                        PIXEL12_30\n                        PIXEL13_10\n                    }\n                    else\n                    {\n                        PIXEL02_50\n                        PIXEL03_50\n                        PIXEL12_0\n                        PIXEL13_50\n                    }\n                    PIXEL10_61\n                    PIXEL11_30\n                    PIXEL20_60\n                    PIXEL21_70\n                    PIXEL22_30\n                    PIXEL23_10\n                    PIXEL30_20\n                    PIXEL31_60\n                    PIXEL32_61\n                    PIXEL33_80\n                    break;\n                }\n                case 80:\n                case 81:\n                {\n                    PIXEL00_20\n                    PIXEL01_60\n                    PIXEL02_61\n                    PIXEL03_80\n                    PIXEL10_60\n                    PIXEL11_70\n                    PIXEL12_30\n                    PIXEL13_10\n                    PIXEL20_61\n                    PIXEL21_30\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL22_30\n                        PIXEL23_10\n                        PIXEL32_10\n                        PIXEL33_80\n                    }\n                    else\n                    {\n                        PIXEL22_0\n                        PIXEL23_50\n                        PIXEL32_50\n                        PIXEL33_50\n                    }\n                    PIXEL30_80\n                    PIXEL31_10\n                    break;\n                }\n                case 72:\n                case 76:\n                {\n                    PIXEL00_80\n                    PIXEL01_61\n                    PIXEL02_60\n                    PIXEL03_20\n                    PIXEL10_10\n                    PIXEL11_30\n                    PIXEL12_70\n                    PIXEL13_60\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_10\n                        PIXEL21_30\n                        PIXEL30_80\n                        PIXEL31_10\n                    }\n                    else\n                    {\n                        PIXEL20_50\n                        PIXEL21_0\n                        PIXEL30_50\n                        PIXEL31_50\n                    }\n                    PIXEL22_30\n                    PIXEL23_61\n                    PIXEL32_10\n                    PIXEL33_80\n                    break;\n                }\n                case 10:\n                case 138:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_80\n                        PIXEL01_10\n                        PIXEL10_10\n                        PIXEL11_30\n                    }\n                    else\n                    {\n                        PIXEL00_50\n                        PIXEL01_50\n                        PIXEL10_50\n                        PIXEL11_0\n                    }\n                    PIXEL02_10\n                    PIXEL03_80\n                    PIXEL12_30\n                    PIXEL13_61\n                    PIXEL20_10\n                    PIXEL21_30\n                    PIXEL22_70\n                    PIXEL23_60\n                    PIXEL30_80\n                    PIXEL31_61\n                    PIXEL32_60\n                    PIXEL33_20\n                    break;\n                }\n                case 66:\n                {\n                    PIXEL00_80\n                    PIXEL01_10\n                    PIXEL02_10\n                    PIXEL03_80\n                    PIXEL10_61\n                    PIXEL11_30\n                    PIXEL12_30\n                    PIXEL13_61\n                    PIXEL20_61\n                    PIXEL21_30\n                    PIXEL22_30\n                    PIXEL23_61\n                    PIXEL30_80\n                    PIXEL31_10\n                    PIXEL32_10\n                    PIXEL33_80\n                    break;\n                }\n                case 24:\n                {\n                    PIXEL00_80\n                    PIXEL01_61\n                    PIXEL02_61\n                    PIXEL03_80\n                    PIXEL10_10\n                    PIXEL11_30\n                    PIXEL12_30\n                    PIXEL13_10\n                    PIXEL20_10\n                    PIXEL21_30\n                    PIXEL22_30\n                    PIXEL23_10\n                    PIXEL30_80\n                    PIXEL31_61\n                    PIXEL32_61\n                    PIXEL33_80\n                    break;\n                }\n                case 7:\n                case 39:\n                case 135:\n                {\n                    PIXEL00_81\n                    PIXEL01_31\n                    PIXEL02_32\n                    PIXEL03_82\n                    PIXEL10_81\n                    PIXEL11_31\n                    PIXEL12_32\n                    PIXEL13_82\n                    PIXEL20_60\n                    PIXEL21_70\n                    PIXEL22_70\n                    PIXEL23_60\n                    PIXEL30_20\n                    PIXEL31_60\n                    PIXEL32_60\n                    PIXEL33_20\n                    break;\n                }\n                case 148:\n                case 149:\n                case 180:\n                {\n                    PIXEL00_20\n                    PIXEL01_60\n                    PIXEL02_81\n                    PIXEL03_81\n                    PIXEL10_60\n                    PIXEL11_70\n                    PIXEL12_31\n                    PIXEL13_31\n                    PIXEL20_60\n                    PIXEL21_70\n                    PIXEL22_32\n                    PIXEL23_32\n                    PIXEL30_20\n                    PIXEL31_60\n                    PIXEL32_82\n                    PIXEL33_82\n                    break;\n                }\n                case 224:\n                case 228:\n                case 225:\n                {\n                    PIXEL00_20\n                    PIXEL01_60\n                    PIXEL02_60\n                    PIXEL03_20\n                    PIXEL10_60\n                    PIXEL11_70\n                    PIXEL12_70\n                    PIXEL13_60\n                    PIXEL20_82\n                    PIXEL21_32\n                    PIXEL22_31\n                    PIXEL23_81\n                    PIXEL30_82\n                    PIXEL31_32\n                    PIXEL32_31\n                    PIXEL33_81\n                    break;\n                }\n                case 41:\n                case 169:\n                case 45:\n                {\n                    PIXEL00_82\n                    PIXEL01_82\n                    PIXEL02_60\n                    PIXEL03_20\n                    PIXEL10_32\n                    PIXEL11_32\n                    PIXEL12_70\n                    PIXEL13_60\n                    PIXEL20_31\n                    PIXEL21_31\n                    PIXEL22_70\n                    PIXEL23_60\n                    PIXEL30_81\n                    PIXEL31_81\n                    PIXEL32_60\n                    PIXEL33_20\n                    break;\n                }\n                case 22:\n                case 54:\n                {\n                    PIXEL00_80\n                    PIXEL01_10\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_0\n                        PIXEL03_0\n                        PIXEL13_0\n                    }\n                    else\n                    {\n                        PIXEL02_50\n                        PIXEL03_50\n                        PIXEL13_50\n                    }\n                    PIXEL10_61\n                    PIXEL11_30\n                    PIXEL12_0\n                    PIXEL20_60\n                    PIXEL21_70\n                    PIXEL22_30\n                    PIXEL23_10\n                    PIXEL30_20\n                    PIXEL31_60\n                    PIXEL32_61\n                    PIXEL33_80\n                    break;\n                }\n                case 208:\n                case 209:\n                {\n                    PIXEL00_20\n                    PIXEL01_60\n                    PIXEL02_61\n                    PIXEL03_80\n                    PIXEL10_60\n                    PIXEL11_70\n                    PIXEL12_30\n                    PIXEL13_10\n                    PIXEL20_61\n                    PIXEL21_30\n                    PIXEL22_0\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL23_0\n                        PIXEL32_0\n                        PIXEL33_0\n                    }\n                    else\n                    {\n                        PIXEL23_50\n                        PIXEL32_50\n                        PIXEL33_50\n                    }\n                    PIXEL30_80\n                    PIXEL31_10\n                    break;\n                }\n                case 104:\n                case 108:\n                {\n                    PIXEL00_80\n                    PIXEL01_61\n                    PIXEL02_60\n                    PIXEL03_20\n                    PIXEL10_10\n                    PIXEL11_30\n                    PIXEL12_70\n                    PIXEL13_60\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_0\n                        PIXEL30_0\n                        PIXEL31_0\n                    }\n                    else\n                    {\n                        PIXEL20_50\n                        PIXEL30_50\n                        PIXEL31_50\n                    }\n                    PIXEL21_0\n                    PIXEL22_30\n                    PIXEL23_61\n                    PIXEL32_10\n                    PIXEL33_80\n                    break;\n                }\n                case 11:\n                case 139:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                        PIXEL01_0\n                        PIXEL10_0\n                    }\n                    else\n                    {\n                        PIXEL00_50\n                        PIXEL01_50\n                        PIXEL10_50\n                    }\n                    PIXEL02_10\n                    PIXEL03_80\n                    PIXEL11_0\n                    PIXEL12_30\n                    PIXEL13_61\n                    PIXEL20_10\n                    PIXEL21_30\n                    PIXEL22_70\n                    PIXEL23_60\n                    PIXEL30_80\n                    PIXEL31_61\n                    PIXEL32_60\n                    PIXEL33_20\n                    break;\n                }\n                case 19:\n                case 51:\n                {\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL00_81\n                        PIXEL01_31\n                        PIXEL02_10\n                        PIXEL03_80\n                        PIXEL12_30\n                        PIXEL13_10\n                    }\n                    else\n                    {\n                        PIXEL00_12\n                        PIXEL01_14\n                        PIXEL02_83\n                        PIXEL03_50\n                        PIXEL12_70\n                        PIXEL13_21\n                    }\n                    PIXEL10_81\n                    PIXEL11_31\n                    PIXEL20_60\n                    PIXEL21_70\n                    PIXEL22_30\n                    PIXEL23_10\n                    PIXEL30_20\n                    PIXEL31_60\n                    PIXEL32_61\n                    PIXEL33_80\n                    break;\n                }\n                case 146:\n                case 178:\n                {\n                    PIXEL00_80\n                    PIXEL01_10\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_10\n                        PIXEL03_80\n                        PIXEL12_30\n                        PIXEL13_10\n                        PIXEL23_32\n                        PIXEL33_82\n                    }\n                    else\n                    {\n                        PIXEL02_21\n                        PIXEL03_50\n                        PIXEL12_70\n                        PIXEL13_83\n                        PIXEL23_13\n                        PIXEL33_11\n                    }\n                    PIXEL10_61\n                    PIXEL11_30\n                    PIXEL20_60\n                    PIXEL21_70\n                    PIXEL22_32\n                    PIXEL30_20\n                    PIXEL31_60\n                    PIXEL32_82\n                    break;\n                }\n                case 84:\n                case 85:\n                {\n                    PIXEL00_20\n                    PIXEL01_60\n                    PIXEL02_81\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL03_81\n                        PIXEL13_31\n                        PIXEL22_30\n                        PIXEL23_10\n                        PIXEL32_10\n                        PIXEL33_80\n                    }\n                    else\n                    {\n                        PIXEL03_12\n                        PIXEL13_14\n                        PIXEL22_70\n                        PIXEL23_83\n                        PIXEL32_21\n                        PIXEL33_50\n                    }\n                    PIXEL10_60\n                    PIXEL11_70\n                    PIXEL12_31\n                    PIXEL20_61\n                    PIXEL21_30\n                    PIXEL30_80\n                    PIXEL31_10\n                    break;\n                }\n                case 112:\n                case 113:\n                {\n                    PIXEL00_20\n                    PIXEL01_60\n                    PIXEL02_61\n                    PIXEL03_80\n                    PIXEL10_60\n                    PIXEL11_70\n                    PIXEL12_30\n                    PIXEL13_10\n                    PIXEL20_82\n                    PIXEL21_32\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL22_30\n                        PIXEL23_10\n                        PIXEL30_82\n                        PIXEL31_32\n                        PIXEL32_10\n                        PIXEL33_80\n                    }\n                    else\n                    {\n                        PIXEL22_70\n                        PIXEL23_21\n                        PIXEL30_11\n                        PIXEL31_13\n                        PIXEL32_83\n                        PIXEL33_50\n                    }\n                    break;\n                }\n                case 200:\n                case 204:\n                {\n                    PIXEL00_80\n                    PIXEL01_61\n                    PIXEL02_60\n                    PIXEL03_20\n                    PIXEL10_10\n                    PIXEL11_30\n                    PIXEL12_70\n                    PIXEL13_60\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_10\n                        PIXEL21_30\n                        PIXEL30_80\n                        PIXEL31_10\n                        PIXEL32_31\n                        PIXEL33_81\n                    }\n                    else\n                    {\n                        PIXEL20_21\n                        PIXEL21_70\n                        PIXEL30_50\n                        PIXEL31_83\n                        PIXEL32_14\n                        PIXEL33_12\n                    }\n                    PIXEL22_31\n                    PIXEL23_81\n                    break;\n                }\n                case 73:\n                case 77:\n                {\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL00_82\n                        PIXEL10_32\n                        PIXEL20_10\n                        PIXEL21_30\n                        PIXEL30_80\n                        PIXEL31_10\n                    }\n                    else\n                    {\n                        PIXEL00_11\n                        PIXEL10_13\n                        PIXEL20_83\n                        PIXEL21_70\n                        PIXEL30_50\n                        PIXEL31_21\n                    }\n                    PIXEL01_82\n                    PIXEL02_60\n                    PIXEL03_20\n                    PIXEL11_32\n                    PIXEL12_70\n                    PIXEL13_60\n                    PIXEL22_30\n                    PIXEL23_61\n                    PIXEL32_10\n                    PIXEL33_80\n                    break;\n                }\n                case 42:\n                case 170:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_80\n                        PIXEL01_10\n                        PIXEL10_10\n                        PIXEL11_30\n                        PIXEL20_31\n                        PIXEL30_81\n                    }\n                    else\n                    {\n                        PIXEL00_50\n                        PIXEL01_21\n                        PIXEL10_83\n                        PIXEL11_70\n                        PIXEL20_14\n                        PIXEL30_12\n                    }\n                    PIXEL02_10\n                    PIXEL03_80\n                    PIXEL12_30\n                    PIXEL13_61\n                    PIXEL21_31\n                    PIXEL22_70\n                    PIXEL23_60\n                    PIXEL31_81\n                    PIXEL32_60\n                    PIXEL33_20\n                    break;\n                }\n                case 14:\n                case 142:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_80\n                        PIXEL01_10\n                        PIXEL02_32\n                        PIXEL03_82\n                        PIXEL10_10\n                        PIXEL11_30\n                    }\n                    else\n                    {\n                        PIXEL00_50\n                        PIXEL01_83\n                        PIXEL02_13\n                        PIXEL03_11\n                        PIXEL10_21\n                        PIXEL11_70\n                    }\n                    PIXEL12_32\n                    PIXEL13_82\n                    PIXEL20_10\n                    PIXEL21_30\n                    PIXEL22_70\n                    PIXEL23_60\n                    PIXEL30_80\n                    PIXEL31_61\n                    PIXEL32_60\n                    PIXEL33_20\n                    break;\n                }\n                case 67:\n                {\n                    PIXEL00_81\n                    PIXEL01_31\n                    PIXEL02_10\n                    PIXEL03_80\n                    PIXEL10_81\n                    PIXEL11_31\n                    PIXEL12_30\n                    PIXEL13_61\n                    PIXEL20_61\n                    PIXEL21_30\n                    PIXEL22_30\n                    PIXEL23_61\n                    PIXEL30_80\n                    PIXEL31_10\n                    PIXEL32_10\n                    PIXEL33_80\n                    break;\n                }\n                case 70:\n                {\n                    PIXEL00_80\n                    PIXEL01_10\n                    PIXEL02_32\n                    PIXEL03_82\n                    PIXEL10_61\n                    PIXEL11_30\n                    PIXEL12_32\n                    PIXEL13_82\n                    PIXEL20_61\n                    PIXEL21_30\n                    PIXEL22_30\n                    PIXEL23_61\n                    PIXEL30_80\n                    PIXEL31_10\n                    PIXEL32_10\n                    PIXEL33_80\n                    break;\n                }\n                case 28:\n                {\n                    PIXEL00_80\n                    PIXEL01_61\n                    PIXEL02_81\n                    PIXEL03_81\n                    PIXEL10_10\n                    PIXEL11_30\n                    PIXEL12_31\n                    PIXEL13_31\n                    PIXEL20_10\n                    PIXEL21_30\n                    PIXEL22_30\n                    PIXEL23_10\n                    PIXEL30_80\n                    PIXEL31_61\n                    PIXEL32_61\n                    PIXEL33_80\n                    break;\n                }\n                case 152:\n                {\n                    PIXEL00_80\n                    PIXEL01_61\n                    PIXEL02_61\n                    PIXEL03_80\n                    PIXEL10_10\n                    PIXEL11_30\n                    PIXEL12_30\n                    PIXEL13_10\n                    PIXEL20_10\n                    PIXEL21_30\n                    PIXEL22_32\n                    PIXEL23_32\n                    PIXEL30_80\n                    PIXEL31_61\n                    PIXEL32_82\n                    PIXEL33_82\n                    break;\n                }\n                case 194:\n                {\n                    PIXEL00_80\n                    PIXEL01_10\n                    PIXEL02_10\n                    PIXEL03_80\n                    PIXEL10_61\n                    PIXEL11_30\n                    PIXEL12_30\n                    PIXEL13_61\n                    PIXEL20_61\n                    PIXEL21_30\n                    PIXEL22_31\n                    PIXEL23_81\n                    PIXEL30_80\n                    PIXEL31_10\n                    PIXEL32_31\n                    PIXEL33_81\n                    break;\n                }\n                case 98:\n                {\n                    PIXEL00_80\n                    PIXEL01_10\n                    PIXEL02_10\n                    PIXEL03_80\n                    PIXEL10_61\n                    PIXEL11_30\n                    PIXEL12_30\n                    PIXEL13_61\n                    PIXEL20_82\n                    PIXEL21_32\n                    PIXEL22_30\n                    PIXEL23_61\n                    PIXEL30_82\n                    PIXEL31_32\n                    PIXEL32_10\n                    PIXEL33_80\n                    break;\n                }\n                case 56:\n                {\n                    PIXEL00_80\n                    PIXEL01_61\n                    PIXEL02_61\n                    PIXEL03_80\n                    PIXEL10_10\n                    PIXEL11_30\n                    PIXEL12_30\n                    PIXEL13_10\n                    PIXEL20_31\n                    PIXEL21_31\n                    PIXEL22_30\n                    PIXEL23_10\n                    PIXEL30_81\n                    PIXEL31_81\n                    PIXEL32_61\n                    PIXEL33_80\n                    break;\n                }\n                case 25:\n                {\n                    PIXEL00_82\n                    PIXEL01_82\n                    PIXEL02_61\n                    PIXEL03_80\n                    PIXEL10_32\n                    PIXEL11_32\n                    PIXEL12_30\n                    PIXEL13_10\n                    PIXEL20_10\n                    PIXEL21_30\n                    PIXEL22_30\n                    PIXEL23_10\n                    PIXEL30_80\n                    PIXEL31_61\n                    PIXEL32_61\n                    PIXEL33_80\n                    break;\n                }\n                case 26:\n                case 31:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                        PIXEL01_0\n                        PIXEL10_0\n                    }\n                    else\n                    {\n                        PIXEL00_50\n                        PIXEL01_50\n                        PIXEL10_50\n                    }\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_0\n                        PIXEL03_0\n                        PIXEL13_0\n                    }\n                    else\n                    {\n                        PIXEL02_50\n                        PIXEL03_50\n                        PIXEL13_50\n                    }\n                    PIXEL11_0\n                    PIXEL12_0\n                    PIXEL20_10\n                    PIXEL21_30\n                    PIXEL22_30\n                    PIXEL23_10\n                    PIXEL30_80\n                    PIXEL31_61\n                    PIXEL32_61\n                    PIXEL33_80\n                    break;\n                }\n                case 82:\n                case 214:\n                {\n                    PIXEL00_80\n                    PIXEL01_10\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_0\n                        PIXEL03_0\n                        PIXEL13_0\n                    }\n                    else\n                    {\n                        PIXEL02_50\n                        PIXEL03_50\n                        PIXEL13_50\n                    }\n                    PIXEL10_61\n                    PIXEL11_30\n                    PIXEL12_0\n                    PIXEL20_61\n                    PIXEL21_30\n                    PIXEL22_0\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL23_0\n                        PIXEL32_0\n                        PIXEL33_0\n                    }\n                    else\n                    {\n                        PIXEL23_50\n                        PIXEL32_50\n                        PIXEL33_50\n                    }\n                    PIXEL30_80\n                    PIXEL31_10\n                    break;\n                }\n                case 88:\n                case 248:\n                {\n                    PIXEL00_80\n                    PIXEL01_61\n                    PIXEL02_61\n                    PIXEL03_80\n                    PIXEL10_10\n                    PIXEL11_30\n                    PIXEL12_30\n                    PIXEL13_10\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_0\n                        PIXEL30_0\n                        PIXEL31_0\n                    }\n                    else\n                    {\n                        PIXEL20_50\n                        PIXEL30_50\n                        PIXEL31_50\n                    }\n                    PIXEL21_0\n                    PIXEL22_0\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL23_0\n                        PIXEL32_0\n                        PIXEL33_0\n                    }\n                    else\n                    {\n                        PIXEL23_50\n                        PIXEL32_50\n                        PIXEL33_50\n                    }\n                    break;\n                }\n                case 74:\n                case 107:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                        PIXEL01_0\n                        PIXEL10_0\n                    }\n                    else\n                    {\n                        PIXEL00_50\n                        PIXEL01_50\n                        PIXEL10_50\n                    }\n                    PIXEL02_10\n                    PIXEL03_80\n                    PIXEL11_0\n                    PIXEL12_30\n                    PIXEL13_61\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_0\n                        PIXEL30_0\n                        PIXEL31_0\n                    }\n                    else\n                    {\n                        PIXEL20_50\n                        PIXEL30_50\n                        PIXEL31_50\n                    }\n                    PIXEL21_0\n                    PIXEL22_30\n                    PIXEL23_61\n                    PIXEL32_10\n                    PIXEL33_80\n                    break;\n                }\n                case 27:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                        PIXEL01_0\n                        PIXEL10_0\n                    }\n                    else\n                    {\n                        PIXEL00_50\n                        PIXEL01_50\n                        PIXEL10_50\n                    }\n                    PIXEL02_10\n                    PIXEL03_80\n                    PIXEL11_0\n                    PIXEL12_30\n                    PIXEL13_10\n                    PIXEL20_10\n                    PIXEL21_30\n                    PIXEL22_30\n                    PIXEL23_10\n                    PIXEL30_80\n                    PIXEL31_61\n                    PIXEL32_61\n                    PIXEL33_80\n                    break;\n                }\n                case 86:\n                {\n                    PIXEL00_80\n                    PIXEL01_10\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_0\n                        PIXEL03_0\n                        PIXEL13_0\n                    }\n                    else\n                    {\n                        PIXEL02_50\n                        PIXEL03_50\n                        PIXEL13_50\n                    }\n                    PIXEL10_61\n                    PIXEL11_30\n                    PIXEL12_0\n                    PIXEL20_61\n                    PIXEL21_30\n                    PIXEL22_30\n                    PIXEL23_10\n                    PIXEL30_80\n                    PIXEL31_10\n                    PIXEL32_10\n                    PIXEL33_80\n                    break;\n                }\n                case 216:\n                {\n                    PIXEL00_80\n                    PIXEL01_61\n                    PIXEL02_61\n                    PIXEL03_80\n                    PIXEL10_10\n                    PIXEL11_30\n                    PIXEL12_30\n                    PIXEL13_10\n                    PIXEL20_10\n                    PIXEL21_30\n                    PIXEL22_0\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL23_0\n                        PIXEL32_0\n                        PIXEL33_0\n                    }\n                    else\n                    {\n                        PIXEL23_50\n                        PIXEL32_50\n                        PIXEL33_50\n                    }\n                    PIXEL30_80\n                    PIXEL31_10\n                    break;\n                }\n                case 106:\n                {\n                    PIXEL00_80\n                    PIXEL01_10\n                    PIXEL02_10\n                    PIXEL03_80\n                    PIXEL10_10\n                    PIXEL11_30\n                    PIXEL12_30\n                    PIXEL13_61\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_0\n                        PIXEL30_0\n                        PIXEL31_0\n                    }\n                    else\n                    {\n                        PIXEL20_50\n                        PIXEL30_50\n                        PIXEL31_50\n                    }\n                    PIXEL21_0\n                    PIXEL22_30\n                    PIXEL23_61\n                    PIXEL32_10\n                    PIXEL33_80\n                    break;\n                }\n                case 30:\n                {\n                    PIXEL00_80\n                    PIXEL01_10\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_0\n                        PIXEL03_0\n                        PIXEL13_0\n                    }\n                    else\n                    {\n                        PIXEL02_50\n                        PIXEL03_50\n                        PIXEL13_50\n                    }\n                    PIXEL10_10\n                    PIXEL11_30\n                    PIXEL12_0\n                    PIXEL20_10\n                    PIXEL21_30\n                    PIXEL22_30\n                    PIXEL23_10\n                    PIXEL30_80\n                    PIXEL31_61\n                    PIXEL32_61\n                    PIXEL33_80\n                    break;\n                }\n                case 210:\n                {\n                    PIXEL00_80\n                    PIXEL01_10\n                    PIXEL02_10\n                    PIXEL03_80\n                    PIXEL10_61\n                    PIXEL11_30\n                    PIXEL12_30\n                    PIXEL13_10\n                    PIXEL20_61\n                    PIXEL21_30\n                    PIXEL22_0\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL23_0\n                        PIXEL32_0\n                        PIXEL33_0\n                    }\n                    else\n                    {\n                        PIXEL23_50\n                        PIXEL32_50\n                        PIXEL33_50\n                    }\n                    PIXEL30_80\n                    PIXEL31_10\n                    break;\n                }\n                case 120:\n                {\n                    PIXEL00_80\n                    PIXEL01_61\n                    PIXEL02_61\n                    PIXEL03_80\n                    PIXEL10_10\n                    PIXEL11_30\n                    PIXEL12_30\n                    PIXEL13_10\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_0\n                        PIXEL30_0\n                        PIXEL31_0\n                    }\n                    else\n                    {\n                        PIXEL20_50\n                        PIXEL30_50\n                        PIXEL31_50\n                    }\n                    PIXEL21_0\n                    PIXEL22_30\n                    PIXEL23_10\n                    PIXEL32_10\n                    PIXEL33_80\n                    break;\n                }\n                case 75:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                        PIXEL01_0\n                        PIXEL10_0\n                    }\n                    else\n                    {\n                        PIXEL00_50\n                        PIXEL01_50\n                        PIXEL10_50\n                    }\n                    PIXEL02_10\n                    PIXEL03_80\n                    PIXEL11_0\n                    PIXEL12_30\n                    PIXEL13_61\n                    PIXEL20_10\n                    PIXEL21_30\n                    PIXEL22_30\n                    PIXEL23_61\n                    PIXEL30_80\n                    PIXEL31_10\n                    PIXEL32_10\n                    PIXEL33_80\n                    break;\n                }\n                case 29:\n                {\n                    PIXEL00_82\n                    PIXEL01_82\n                    PIXEL02_81\n                    PIXEL03_81\n                    PIXEL10_32\n                    PIXEL11_32\n                    PIXEL12_31\n                    PIXEL13_31\n                    PIXEL20_10\n                    PIXEL21_30\n                    PIXEL22_30\n                    PIXEL23_10\n                    PIXEL30_80\n                    PIXEL31_61\n                    PIXEL32_61\n                    PIXEL33_80\n                    break;\n                }\n                case 198:\n                {\n                    PIXEL00_80\n                    PIXEL01_10\n                    PIXEL02_32\n                    PIXEL03_82\n                    PIXEL10_61\n                    PIXEL11_30\n                    PIXEL12_32\n                    PIXEL13_82\n                    PIXEL20_61\n                    PIXEL21_30\n                    PIXEL22_31\n                    PIXEL23_81\n                    PIXEL30_80\n                    PIXEL31_10\n                    PIXEL32_31\n                    PIXEL33_81\n                    break;\n                }\n                case 184:\n                {\n                    PIXEL00_80\n                    PIXEL01_61\n                    PIXEL02_61\n                    PIXEL03_80\n                    PIXEL10_10\n                    PIXEL11_30\n                    PIXEL12_30\n                    PIXEL13_10\n                    PIXEL20_31\n                    PIXEL21_31\n                    PIXEL22_32\n                    PIXEL23_32\n                    PIXEL30_81\n                    PIXEL31_81\n                    PIXEL32_82\n                    PIXEL33_82\n                    break;\n                }\n                case 99:\n                {\n                    PIXEL00_81\n                    PIXEL01_31\n                    PIXEL02_10\n                    PIXEL03_80\n                    PIXEL10_81\n                    PIXEL11_31\n                    PIXEL12_30\n                    PIXEL13_61\n                    PIXEL20_82\n                    PIXEL21_32\n                    PIXEL22_30\n                    PIXEL23_61\n                    PIXEL30_82\n                    PIXEL31_32\n                    PIXEL32_10\n                    PIXEL33_80\n                    break;\n                }\n                case 57:\n                {\n                    PIXEL00_82\n                    PIXEL01_82\n                    PIXEL02_61\n                    PIXEL03_80\n                    PIXEL10_32\n                    PIXEL11_32\n                    PIXEL12_30\n                    PIXEL13_10\n                    PIXEL20_31\n                    PIXEL21_31\n                    PIXEL22_30\n                    PIXEL23_10\n                    PIXEL30_81\n                    PIXEL31_81\n                    PIXEL32_61\n                    PIXEL33_80\n                    break;\n                }\n                case 71:\n                {\n                    PIXEL00_81\n                    PIXEL01_31\n                    PIXEL02_32\n                    PIXEL03_82\n                    PIXEL10_81\n                    PIXEL11_31\n                    PIXEL12_32\n                    PIXEL13_82\n                    PIXEL20_61\n                    PIXEL21_30\n                    PIXEL22_30\n                    PIXEL23_61\n                    PIXEL30_80\n                    PIXEL31_10\n                    PIXEL32_10\n                    PIXEL33_80\n                    break;\n                }\n                case 156:\n                {\n                    PIXEL00_80\n                    PIXEL01_61\n                    PIXEL02_81\n                    PIXEL03_81\n                    PIXEL10_10\n                    PIXEL11_30\n                    PIXEL12_31\n                    PIXEL13_31\n                    PIXEL20_10\n                    PIXEL21_30\n                    PIXEL22_32\n                    PIXEL23_32\n                    PIXEL30_80\n                    PIXEL31_61\n                    PIXEL32_82\n                    PIXEL33_82\n                    break;\n                }\n                case 226:\n                {\n                    PIXEL00_80\n                    PIXEL01_10\n                    PIXEL02_10\n                    PIXEL03_80\n                    PIXEL10_61\n                    PIXEL11_30\n                    PIXEL12_30\n                    PIXEL13_61\n                    PIXEL20_82\n                    PIXEL21_32\n                    PIXEL22_31\n                    PIXEL23_81\n                    PIXEL30_82\n                    PIXEL31_32\n                    PIXEL32_31\n                    PIXEL33_81\n                    break;\n                }\n                case 60:\n                {\n                    PIXEL00_80\n                    PIXEL01_61\n                    PIXEL02_81\n                    PIXEL03_81\n                    PIXEL10_10\n                    PIXEL11_30\n                    PIXEL12_31\n                    PIXEL13_31\n                    PIXEL20_31\n                    PIXEL21_31\n                    PIXEL22_30\n                    PIXEL23_10\n                    PIXEL30_81\n                    PIXEL31_81\n                    PIXEL32_61\n                    PIXEL33_80\n                    break;\n                }\n                case 195:\n                {\n                    PIXEL00_81\n                    PIXEL01_31\n                    PIXEL02_10\n                    PIXEL03_80\n                    PIXEL10_81\n                    PIXEL11_31\n                    PIXEL12_30\n                    PIXEL13_61\n                    PIXEL20_61\n                    PIXEL21_30\n                    PIXEL22_31\n                    PIXEL23_81\n                    PIXEL30_80\n                    PIXEL31_10\n                    PIXEL32_31\n                    PIXEL33_81\n                    break;\n                }\n                case 102:\n                {\n                    PIXEL00_80\n                    PIXEL01_10\n                    PIXEL02_32\n                    PIXEL03_82\n                    PIXEL10_61\n                    PIXEL11_30\n                    PIXEL12_32\n                    PIXEL13_82\n                    PIXEL20_82\n                    PIXEL21_32\n                    PIXEL22_30\n                    PIXEL23_61\n                    PIXEL30_82\n                    PIXEL31_32\n                    PIXEL32_10\n                    PIXEL33_80\n                    break;\n                }\n                case 153:\n                {\n                    PIXEL00_82\n                    PIXEL01_82\n                    PIXEL02_61\n                    PIXEL03_80\n                    PIXEL10_32\n                    PIXEL11_32\n                    PIXEL12_30\n                    PIXEL13_10\n                    PIXEL20_10\n                    PIXEL21_30\n                    PIXEL22_32\n                    PIXEL23_32\n                    PIXEL30_80\n                    PIXEL31_61\n                    PIXEL32_82\n                    PIXEL33_82\n                    break;\n                }\n                case 58:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_80\n                        PIXEL01_10\n                        PIXEL10_10\n                        PIXEL11_30\n                    }\n                    else\n                    {\n                        PIXEL00_20\n                        PIXEL01_12\n                        PIXEL10_11\n                        PIXEL11_0\n                    }\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_10\n                        PIXEL03_80\n                        PIXEL12_30\n                        PIXEL13_10\n                    }\n                    else\n                    {\n                        PIXEL02_11\n                        PIXEL03_20\n                        PIXEL12_0\n                        PIXEL13_12\n                    }\n                    PIXEL20_31\n                    PIXEL21_31\n                    PIXEL22_30\n                    PIXEL23_10\n                    PIXEL30_81\n                    PIXEL31_81\n                    PIXEL32_61\n                    PIXEL33_80\n                    break;\n                }\n                case 83:\n                {\n                    PIXEL00_81\n                    PIXEL01_31\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_10\n                        PIXEL03_80\n                        PIXEL12_30\n                        PIXEL13_10\n                    }\n                    else\n                    {\n                        PIXEL02_11\n                        PIXEL03_20\n                        PIXEL12_0\n                        PIXEL13_12\n                    }\n                    PIXEL10_81\n                    PIXEL11_31\n                    PIXEL20_61\n                    PIXEL21_30\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL22_30\n                        PIXEL23_10\n                        PIXEL32_10\n                        PIXEL33_80\n                    }\n                    else\n                    {\n                        PIXEL22_0\n                        PIXEL23_11\n                        PIXEL32_12\n                        PIXEL33_20\n                    }\n                    PIXEL30_80\n                    PIXEL31_10\n                    break;\n                }\n                case 92:\n                {\n                    PIXEL00_80\n                    PIXEL01_61\n                    PIXEL02_81\n                    PIXEL03_81\n                    PIXEL10_10\n                    PIXEL11_30\n                    PIXEL12_31\n                    PIXEL13_31\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_10\n                        PIXEL21_30\n                        PIXEL30_80\n                        PIXEL31_10\n                    }\n                    else\n                    {\n                        PIXEL20_12\n                        PIXEL21_0\n                        PIXEL30_20\n                        PIXEL31_11\n                    }\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL22_30\n                        PIXEL23_10\n                        PIXEL32_10\n                        PIXEL33_80\n                    }\n                    else\n                    {\n                        PIXEL22_0\n                        PIXEL23_11\n                        PIXEL32_12\n                        PIXEL33_20\n                    }\n                    break;\n                }\n                case 202:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_80\n                        PIXEL01_10\n                        PIXEL10_10\n                        PIXEL11_30\n                    }\n                    else\n                    {\n                        PIXEL00_20\n                        PIXEL01_12\n                        PIXEL10_11\n                        PIXEL11_0\n                    }\n                    PIXEL02_10\n                    PIXEL03_80\n                    PIXEL12_30\n                    PIXEL13_61\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_10\n                        PIXEL21_30\n                        PIXEL30_80\n                        PIXEL31_10\n                    }\n                    else\n                    {\n                        PIXEL20_12\n                        PIXEL21_0\n                        PIXEL30_20\n                        PIXEL31_11\n                    }\n                    PIXEL22_31\n                    PIXEL23_81\n                    PIXEL32_31\n                    PIXEL33_81\n                    break;\n                }\n                case 78:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_80\n                        PIXEL01_10\n                        PIXEL10_10\n                        PIXEL11_30\n                    }\n                    else\n                    {\n                        PIXEL00_20\n                        PIXEL01_12\n                        PIXEL10_11\n                        PIXEL11_0\n                    }\n                    PIXEL02_32\n                    PIXEL03_82\n                    PIXEL12_32\n                    PIXEL13_82\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_10\n                        PIXEL21_30\n                        PIXEL30_80\n                        PIXEL31_10\n                    }\n                    else\n                    {\n                        PIXEL20_12\n                        PIXEL21_0\n                        PIXEL30_20\n                        PIXEL31_11\n                    }\n                    PIXEL22_30\n                    PIXEL23_61\n                    PIXEL32_10\n                    PIXEL33_80\n                    break;\n                }\n                case 154:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_80\n                        PIXEL01_10\n                        PIXEL10_10\n                        PIXEL11_30\n                    }\n                    else\n                    {\n                        PIXEL00_20\n                        PIXEL01_12\n                        PIXEL10_11\n                        PIXEL11_0\n                    }\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_10\n                        PIXEL03_80\n                        PIXEL12_30\n                        PIXEL13_10\n                    }\n                    else\n                    {\n                        PIXEL02_11\n                        PIXEL03_20\n                        PIXEL12_0\n                        PIXEL13_12\n                    }\n                    PIXEL20_10\n                    PIXEL21_30\n                    PIXEL22_32\n                    PIXEL23_32\n                    PIXEL30_80\n                    PIXEL31_61\n                    PIXEL32_82\n                    PIXEL33_82\n                    break;\n                }\n                case 114:\n                {\n                    PIXEL00_80\n                    PIXEL01_10\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_10\n                        PIXEL03_80\n                        PIXEL12_30\n                        PIXEL13_10\n                    }\n                    else\n                    {\n                        PIXEL02_11\n                        PIXEL03_20\n                        PIXEL12_0\n                        PIXEL13_12\n                    }\n                    PIXEL10_61\n                    PIXEL11_30\n                    PIXEL20_82\n                    PIXEL21_32\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL22_30\n                        PIXEL23_10\n                        PIXEL32_10\n                        PIXEL33_80\n                    }\n                    else\n                    {\n                        PIXEL22_0\n                        PIXEL23_11\n                        PIXEL32_12\n                        PIXEL33_20\n                    }\n                    PIXEL30_82\n                    PIXEL31_32\n                    break;\n                }\n                case 89:\n                {\n                    PIXEL00_82\n                    PIXEL01_82\n                    PIXEL02_61\n                    PIXEL03_80\n                    PIXEL10_32\n                    PIXEL11_32\n                    PIXEL12_30\n                    PIXEL13_10\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_10\n                        PIXEL21_30\n                        PIXEL30_80\n                        PIXEL31_10\n                    }\n                    else\n                    {\n                        PIXEL20_12\n                        PIXEL21_0\n                        PIXEL30_20\n                        PIXEL31_11\n                    }\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL22_30\n                        PIXEL23_10\n                        PIXEL32_10\n                        PIXEL33_80\n                    }\n                    else\n                    {\n                        PIXEL22_0\n                        PIXEL23_11\n                        PIXEL32_12\n                        PIXEL33_20\n                    }\n                    break;\n                }\n                case 90:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_80\n                        PIXEL01_10\n                        PIXEL10_10\n                        PIXEL11_30\n                    }\n                    else\n                    {\n                        PIXEL00_20\n                        PIXEL01_12\n                        PIXEL10_11\n                        PIXEL11_0\n                    }\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_10\n                        PIXEL03_80\n                        PIXEL12_30\n                        PIXEL13_10\n                    }\n                    else\n                    {\n                        PIXEL02_11\n                        PIXEL03_20\n                        PIXEL12_0\n                        PIXEL13_12\n                    }\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_10\n                        PIXEL21_30\n                        PIXEL30_80\n                        PIXEL31_10\n                    }\n                    else\n                    {\n                        PIXEL20_12\n                        PIXEL21_0\n                        PIXEL30_20\n                        PIXEL31_11\n                    }\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL22_30\n                        PIXEL23_10\n                        PIXEL32_10\n                        PIXEL33_80\n                    }\n                    else\n                    {\n                        PIXEL22_0\n                        PIXEL23_11\n                        PIXEL32_12\n                        PIXEL33_20\n                    }\n                    break;\n                }\n                case 55:\n                case 23:\n                {\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL00_81\n                        PIXEL01_31\n                        PIXEL02_0\n                        PIXEL03_0\n                        PIXEL12_0\n                        PIXEL13_0\n                    }\n                    else\n                    {\n                        PIXEL00_12\n                        PIXEL01_14\n                        PIXEL02_83\n                        PIXEL03_50\n                        PIXEL12_70\n                        PIXEL13_21\n                    }\n                    PIXEL10_81\n                    PIXEL11_31\n                    PIXEL20_60\n                    PIXEL21_70\n                    PIXEL22_30\n                    PIXEL23_10\n                    PIXEL30_20\n                    PIXEL31_60\n                    PIXEL32_61\n                    PIXEL33_80\n                    break;\n                }\n                case 182:\n                case 150:\n                {\n                    PIXEL00_80\n                    PIXEL01_10\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_0\n                        PIXEL03_0\n                        PIXEL12_0\n                        PIXEL13_0\n                        PIXEL23_32\n                        PIXEL33_82\n                    }\n                    else\n                    {\n                        PIXEL02_21\n                        PIXEL03_50\n                        PIXEL12_70\n                        PIXEL13_83\n                        PIXEL23_13\n                        PIXEL33_11\n                    }\n                    PIXEL10_61\n                    PIXEL11_30\n                    PIXEL20_60\n                    PIXEL21_70\n                    PIXEL22_32\n                    PIXEL30_20\n                    PIXEL31_60\n                    PIXEL32_82\n                    break;\n                }\n                case 213:\n                case 212:\n                {\n                    PIXEL00_20\n                    PIXEL01_60\n                    PIXEL02_81\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL03_81\n                        PIXEL13_31\n                        PIXEL22_0\n                        PIXEL23_0\n                        PIXEL32_0\n                        PIXEL33_0\n                    }\n                    else\n                    {\n                        PIXEL03_12\n                        PIXEL13_14\n                        PIXEL22_70\n                        PIXEL23_83\n                        PIXEL32_21\n                        PIXEL33_50\n                    }\n                    PIXEL10_60\n                    PIXEL11_70\n                    PIXEL12_31\n                    PIXEL20_61\n                    PIXEL21_30\n                    PIXEL30_80\n                    PIXEL31_10\n                    break;\n                }\n                case 241:\n                case 240:\n                {\n                    PIXEL00_20\n                    PIXEL01_60\n                    PIXEL02_61\n                    PIXEL03_80\n                    PIXEL10_60\n                    PIXEL11_70\n                    PIXEL12_30\n                    PIXEL13_10\n                    PIXEL20_82\n                    PIXEL21_32\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL22_0\n                        PIXEL23_0\n                        PIXEL30_82\n                        PIXEL31_32\n                        PIXEL32_0\n                        PIXEL33_0\n                    }\n                    else\n                    {\n                        PIXEL22_70\n                        PIXEL23_21\n                        PIXEL30_11\n                        PIXEL31_13\n                        PIXEL32_83\n                        PIXEL33_50\n                    }\n                    break;\n                }\n                case 236:\n                case 232:\n                {\n                    PIXEL00_80\n                    PIXEL01_61\n                    PIXEL02_60\n                    PIXEL03_20\n                    PIXEL10_10\n                    PIXEL11_30\n                    PIXEL12_70\n                    PIXEL13_60\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_0\n                        PIXEL21_0\n                        PIXEL30_0\n                        PIXEL31_0\n                        PIXEL32_31\n                        PIXEL33_81\n                    }\n                    else\n                    {\n                        PIXEL20_21\n                        PIXEL21_70\n                        PIXEL30_50\n                        PIXEL31_83\n                        PIXEL32_14\n                        PIXEL33_12\n                    }\n                    PIXEL22_31\n                    PIXEL23_81\n                    break;\n                }\n                case 109:\n                case 105:\n                {\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL00_82\n                        PIXEL10_32\n                        PIXEL20_0\n                        PIXEL21_0\n                        PIXEL30_0\n                        PIXEL31_0\n                    }\n                    else\n                    {\n                        PIXEL00_11\n                        PIXEL10_13\n                        PIXEL20_83\n                        PIXEL21_70\n                        PIXEL30_50\n                        PIXEL31_21\n                    }\n                    PIXEL01_82\n                    PIXEL02_60\n                    PIXEL03_20\n                    PIXEL11_32\n                    PIXEL12_70\n                    PIXEL13_60\n                    PIXEL22_30\n                    PIXEL23_61\n                    PIXEL32_10\n                    PIXEL33_80\n                    break;\n                }\n                case 171:\n                case 43:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                        PIXEL01_0\n                        PIXEL10_0\n                        PIXEL11_0\n                        PIXEL20_31\n                        PIXEL30_81\n                    }\n                    else\n                    {\n                        PIXEL00_50\n                        PIXEL01_21\n                        PIXEL10_83\n                        PIXEL11_70\n                        PIXEL20_14\n                        PIXEL30_12\n                    }\n                    PIXEL02_10\n                    PIXEL03_80\n                    PIXEL12_30\n                    PIXEL13_61\n                    PIXEL21_31\n                    PIXEL22_70\n                    PIXEL23_60\n                    PIXEL31_81\n                    PIXEL32_60\n                    PIXEL33_20\n                    break;\n                }\n                case 143:\n                case 15:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                        PIXEL01_0\n                        PIXEL02_32\n                        PIXEL03_82\n                        PIXEL10_0\n                        PIXEL11_0\n                    }\n                    else\n                    {\n                        PIXEL00_50\n                        PIXEL01_83\n                        PIXEL02_13\n                        PIXEL03_11\n                        PIXEL10_21\n                        PIXEL11_70\n                    }\n                    PIXEL12_32\n                    PIXEL13_82\n                    PIXEL20_10\n                    PIXEL21_30\n                    PIXEL22_70\n                    PIXEL23_60\n                    PIXEL30_80\n                    PIXEL31_61\n                    PIXEL32_60\n                    PIXEL33_20\n                    break;\n                }\n                case 124:\n                {\n                    PIXEL00_80\n                    PIXEL01_61\n                    PIXEL02_81\n                    PIXEL03_81\n                    PIXEL10_10\n                    PIXEL11_30\n                    PIXEL12_31\n                    PIXEL13_31\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_0\n                        PIXEL30_0\n                        PIXEL31_0\n                    }\n                    else\n                    {\n                        PIXEL20_50\n                        PIXEL30_50\n                        PIXEL31_50\n                    }\n                    PIXEL21_0\n                    PIXEL22_30\n                    PIXEL23_10\n                    PIXEL32_10\n                    PIXEL33_80\n                    break;\n                }\n                case 203:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                        PIXEL01_0\n                        PIXEL10_0\n                    }\n                    else\n                    {\n                        PIXEL00_50\n                        PIXEL01_50\n                        PIXEL10_50\n                    }\n                    PIXEL02_10\n                    PIXEL03_80\n                    PIXEL11_0\n                    PIXEL12_30\n                    PIXEL13_61\n                    PIXEL20_10\n                    PIXEL21_30\n                    PIXEL22_31\n                    PIXEL23_81\n                    PIXEL30_80\n                    PIXEL31_10\n                    PIXEL32_31\n                    PIXEL33_81\n                    break;\n                }\n                case 62:\n                {\n                    PIXEL00_80\n                    PIXEL01_10\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_0\n                        PIXEL03_0\n                        PIXEL13_0\n                    }\n                    else\n                    {\n                        PIXEL02_50\n                        PIXEL03_50\n                        PIXEL13_50\n                    }\n                    PIXEL10_10\n                    PIXEL11_30\n                    PIXEL12_0\n                    PIXEL20_31\n                    PIXEL21_31\n                    PIXEL22_30\n                    PIXEL23_10\n                    PIXEL30_81\n                    PIXEL31_81\n                    PIXEL32_61\n                    PIXEL33_80\n                    break;\n                }\n                case 211:\n                {\n                    PIXEL00_81\n                    PIXEL01_31\n                    PIXEL02_10\n                    PIXEL03_80\n                    PIXEL10_81\n                    PIXEL11_31\n                    PIXEL12_30\n                    PIXEL13_10\n                    PIXEL20_61\n                    PIXEL21_30\n                    PIXEL22_0\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL23_0\n                        PIXEL32_0\n                        PIXEL33_0\n                    }\n                    else\n                    {\n                        PIXEL23_50\n                        PIXEL32_50\n                        PIXEL33_50\n                    }\n                    PIXEL30_80\n                    PIXEL31_10\n                    break;\n                }\n                case 118:\n                {\n                    PIXEL00_80\n                    PIXEL01_10\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_0\n                        PIXEL03_0\n                        PIXEL13_0\n                    }\n                    else\n                    {\n                        PIXEL02_50\n                        PIXEL03_50\n                        PIXEL13_50\n                    }\n                    PIXEL10_61\n                    PIXEL11_30\n                    PIXEL12_0\n                    PIXEL20_82\n                    PIXEL21_32\n                    PIXEL22_30\n                    PIXEL23_10\n                    PIXEL30_82\n                    PIXEL31_32\n                    PIXEL32_10\n                    PIXEL33_80\n                    break;\n                }\n                case 217:\n                {\n                    PIXEL00_82\n                    PIXEL01_82\n                    PIXEL02_61\n                    PIXEL03_80\n                    PIXEL10_32\n                    PIXEL11_32\n                    PIXEL12_30\n                    PIXEL13_10\n                    PIXEL20_10\n                    PIXEL21_30\n                    PIXEL22_0\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL23_0\n                        PIXEL32_0\n                        PIXEL33_0\n                    }\n                    else\n                    {\n                        PIXEL23_50\n                        PIXEL32_50\n                        PIXEL33_50\n                    }\n                    PIXEL30_80\n                    PIXEL31_10\n                    break;\n                }\n                case 110:\n                {\n                    PIXEL00_80\n                    PIXEL01_10\n                    PIXEL02_32\n                    PIXEL03_82\n                    PIXEL10_10\n                    PIXEL11_30\n                    PIXEL12_32\n                    PIXEL13_82\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_0\n                        PIXEL30_0\n                        PIXEL31_0\n                    }\n                    else\n                    {\n                        PIXEL20_50\n                        PIXEL30_50\n                        PIXEL31_50\n                    }\n                    PIXEL21_0\n                    PIXEL22_30\n                    PIXEL23_61\n                    PIXEL32_10\n                    PIXEL33_80\n                    break;\n                }\n                case 155:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                        PIXEL01_0\n                        PIXEL10_0\n                    }\n                    else\n                    {\n                        PIXEL00_50\n                        PIXEL01_50\n                        PIXEL10_50\n                    }\n                    PIXEL02_10\n                    PIXEL03_80\n                    PIXEL11_0\n                    PIXEL12_30\n                    PIXEL13_10\n                    PIXEL20_10\n                    PIXEL21_30\n                    PIXEL22_32\n                    PIXEL23_32\n                    PIXEL30_80\n                    PIXEL31_61\n                    PIXEL32_82\n                    PIXEL33_82\n                    break;\n                }\n                case 188:\n                {\n                    PIXEL00_80\n                    PIXEL01_61\n                    PIXEL02_81\n                    PIXEL03_81\n                    PIXEL10_10\n                    PIXEL11_30\n                    PIXEL12_31\n                    PIXEL13_31\n                    PIXEL20_31\n                    PIXEL21_31\n                    PIXEL22_32\n                    PIXEL23_32\n                    PIXEL30_81\n                    PIXEL31_81\n                    PIXEL32_82\n                    PIXEL33_82\n                    break;\n                }\n                case 185:\n                {\n                    PIXEL00_82\n                    PIXEL01_82\n                    PIXEL02_61\n                    PIXEL03_80\n                    PIXEL10_32\n                    PIXEL11_32\n                    PIXEL12_30\n                    PIXEL13_10\n                    PIXEL20_31\n                    PIXEL21_31\n                    PIXEL22_32\n                    PIXEL23_32\n                    PIXEL30_81\n                    PIXEL31_81\n                    PIXEL32_82\n                    PIXEL33_82\n                    break;\n                }\n                case 61:\n                {\n                    PIXEL00_82\n                    PIXEL01_82\n                    PIXEL02_81\n                    PIXEL03_81\n                    PIXEL10_32\n                    PIXEL11_32\n                    PIXEL12_31\n                    PIXEL13_31\n                    PIXEL20_31\n                    PIXEL21_31\n                    PIXEL22_30\n                    PIXEL23_10\n                    PIXEL30_81\n                    PIXEL31_81\n                    PIXEL32_61\n                    PIXEL33_80\n                    break;\n                }\n                case 157:\n                {\n                    PIXEL00_82\n                    PIXEL01_82\n                    PIXEL02_81\n                    PIXEL03_81\n                    PIXEL10_32\n                    PIXEL11_32\n                    PIXEL12_31\n                    PIXEL13_31\n                    PIXEL20_10\n                    PIXEL21_30\n                    PIXEL22_32\n                    PIXEL23_32\n                    PIXEL30_80\n                    PIXEL31_61\n                    PIXEL32_82\n                    PIXEL33_82\n                    break;\n                }\n                case 103:\n                {\n                    PIXEL00_81\n                    PIXEL01_31\n                    PIXEL02_32\n                    PIXEL03_82\n                    PIXEL10_81\n                    PIXEL11_31\n                    PIXEL12_32\n                    PIXEL13_82\n                    PIXEL20_82\n                    PIXEL21_32\n                    PIXEL22_30\n                    PIXEL23_61\n                    PIXEL30_82\n                    PIXEL31_32\n                    PIXEL32_10\n                    PIXEL33_80\n                    break;\n                }\n                case 227:\n                {\n                    PIXEL00_81\n                    PIXEL01_31\n                    PIXEL02_10\n                    PIXEL03_80\n                    PIXEL10_81\n                    PIXEL11_31\n                    PIXEL12_30\n                    PIXEL13_61\n                    PIXEL20_82\n                    PIXEL21_32\n                    PIXEL22_31\n                    PIXEL23_81\n                    PIXEL30_82\n                    PIXEL31_32\n                    PIXEL32_31\n                    PIXEL33_81\n                    break;\n                }\n                case 230:\n                {\n                    PIXEL00_80\n                    PIXEL01_10\n                    PIXEL02_32\n                    PIXEL03_82\n                    PIXEL10_61\n                    PIXEL11_30\n                    PIXEL12_32\n                    PIXEL13_82\n                    PIXEL20_82\n                    PIXEL21_32\n                    PIXEL22_31\n                    PIXEL23_81\n                    PIXEL30_82\n                    PIXEL31_32\n                    PIXEL32_31\n                    PIXEL33_81\n                    break;\n                }\n                case 199:\n                {\n                    PIXEL00_81\n                    PIXEL01_31\n                    PIXEL02_32\n                    PIXEL03_82\n                    PIXEL10_81\n                    PIXEL11_31\n                    PIXEL12_32\n                    PIXEL13_82\n                    PIXEL20_61\n                    PIXEL21_30\n                    PIXEL22_31\n                    PIXEL23_81\n                    PIXEL30_80\n                    PIXEL31_10\n                    PIXEL32_31\n                    PIXEL33_81\n                    break;\n                }\n                case 220:\n                {\n                    PIXEL00_80\n                    PIXEL01_61\n                    PIXEL02_81\n                    PIXEL03_81\n                    PIXEL10_10\n                    PIXEL11_30\n                    PIXEL12_31\n                    PIXEL13_31\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_10\n                        PIXEL21_30\n                        PIXEL30_80\n                        PIXEL31_10\n                    }\n                    else\n                    {\n                        PIXEL20_12\n                        PIXEL21_0\n                        PIXEL30_20\n                        PIXEL31_11\n                    }\n                    PIXEL22_0\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL23_0\n                        PIXEL32_0\n                        PIXEL33_0\n                    }\n                    else\n                    {\n                        PIXEL23_50\n                        PIXEL32_50\n                        PIXEL33_50\n                    }\n                    break;\n                }\n                case 158:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_80\n                        PIXEL01_10\n                        PIXEL10_10\n                        PIXEL11_30\n                    }\n                    else\n                    {\n                        PIXEL00_20\n                        PIXEL01_12\n                        PIXEL10_11\n                        PIXEL11_0\n                    }\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_0\n                        PIXEL03_0\n                        PIXEL13_0\n                    }\n                    else\n                    {\n                        PIXEL02_50\n                        PIXEL03_50\n                        PIXEL13_50\n                    }\n                    PIXEL12_0\n                    PIXEL20_10\n                    PIXEL21_30\n                    PIXEL22_32\n                    PIXEL23_32\n                    PIXEL30_80\n                    PIXEL31_61\n                    PIXEL32_82\n                    PIXEL33_82\n                    break;\n                }\n                case 234:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_80\n                        PIXEL01_10\n                        PIXEL10_10\n                        PIXEL11_30\n                    }\n                    else\n                    {\n                        PIXEL00_20\n                        PIXEL01_12\n                        PIXEL10_11\n                        PIXEL11_0\n                    }\n                    PIXEL02_10\n                    PIXEL03_80\n                    PIXEL12_30\n                    PIXEL13_61\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_0\n                        PIXEL30_0\n                        PIXEL31_0\n                    }\n                    else\n                    {\n                        PIXEL20_50\n                        PIXEL30_50\n                        PIXEL31_50\n                    }\n                    PIXEL21_0\n                    PIXEL22_31\n                    PIXEL23_81\n                    PIXEL32_31\n                    PIXEL33_81\n                    break;\n                }\n                case 242:\n                {\n                    PIXEL00_80\n                    PIXEL01_10\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_10\n                        PIXEL03_80\n                        PIXEL12_30\n                        PIXEL13_10\n                    }\n                    else\n                    {\n                        PIXEL02_11\n                        PIXEL03_20\n                        PIXEL12_0\n                        PIXEL13_12\n                    }\n                    PIXEL10_61\n                    PIXEL11_30\n                    PIXEL20_82\n                    PIXEL21_32\n                    PIXEL22_0\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL23_0\n                        PIXEL32_0\n                        PIXEL33_0\n                    }\n                    else\n                    {\n                        PIXEL23_50\n                        PIXEL32_50\n                        PIXEL33_50\n                    }\n                    PIXEL30_82\n                    PIXEL31_32\n                    break;\n                }\n                case 59:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                        PIXEL01_0\n                        PIXEL10_0\n                    }\n                    else\n                    {\n                        PIXEL00_50\n                        PIXEL01_50\n                        PIXEL10_50\n                    }\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_10\n                        PIXEL03_80\n                        PIXEL12_30\n                        PIXEL13_10\n                    }\n                    else\n                    {\n                        PIXEL02_11\n                        PIXEL03_20\n                        PIXEL12_0\n                        PIXEL13_12\n                    }\n                    PIXEL11_0\n                    PIXEL20_31\n                    PIXEL21_31\n                    PIXEL22_30\n                    PIXEL23_10\n                    PIXEL30_81\n                    PIXEL31_81\n                    PIXEL32_61\n                    PIXEL33_80\n                    break;\n                }\n                case 121:\n                {\n                    PIXEL00_82\n                    PIXEL01_82\n                    PIXEL02_61\n                    PIXEL03_80\n                    PIXEL10_32\n                    PIXEL11_32\n                    PIXEL12_30\n                    PIXEL13_10\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_0\n                        PIXEL30_0\n                        PIXEL31_0\n                    }\n                    else\n                    {\n                        PIXEL20_50\n                        PIXEL30_50\n                        PIXEL31_50\n                    }\n                    PIXEL21_0\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL22_30\n                        PIXEL23_10\n                        PIXEL32_10\n                        PIXEL33_80\n                    }\n                    else\n                    {\n                        PIXEL22_0\n                        PIXEL23_11\n                        PIXEL32_12\n                        PIXEL33_20\n                    }\n                    break;\n                }\n                case 87:\n                {\n                    PIXEL00_81\n                    PIXEL01_31\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_0\n                        PIXEL03_0\n                        PIXEL13_0\n                    }\n                    else\n                    {\n                        PIXEL02_50\n                        PIXEL03_50\n                        PIXEL13_50\n                    }\n                    PIXEL10_81\n                    PIXEL11_31\n                    PIXEL12_0\n                    PIXEL20_61\n                    PIXEL21_30\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL22_30\n                        PIXEL23_10\n                        PIXEL32_10\n                        PIXEL33_80\n                    }\n                    else\n                    {\n                        PIXEL22_0\n                        PIXEL23_11\n                        PIXEL32_12\n                        PIXEL33_20\n                    }\n                    PIXEL30_80\n                    PIXEL31_10\n                    break;\n                }\n                case 79:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                        PIXEL01_0\n                        PIXEL10_0\n                    }\n                    else\n                    {\n                        PIXEL00_50\n                        PIXEL01_50\n                        PIXEL10_50\n                    }\n                    PIXEL02_32\n                    PIXEL03_82\n                    PIXEL11_0\n                    PIXEL12_32\n                    PIXEL13_82\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_10\n                        PIXEL21_30\n                        PIXEL30_80\n                        PIXEL31_10\n                    }\n                    else\n                    {\n                        PIXEL20_12\n                        PIXEL21_0\n                        PIXEL30_20\n                        PIXEL31_11\n                    }\n                    PIXEL22_30\n                    PIXEL23_61\n                    PIXEL32_10\n                    PIXEL33_80\n                    break;\n                }\n                case 122:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_80\n                        PIXEL01_10\n                        PIXEL10_10\n                        PIXEL11_30\n                    }\n                    else\n                    {\n                        PIXEL00_20\n                        PIXEL01_12\n                        PIXEL10_11\n                        PIXEL11_0\n                    }\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_10\n                        PIXEL03_80\n                        PIXEL12_30\n                        PIXEL13_10\n                    }\n                    else\n                    {\n                        PIXEL02_11\n                        PIXEL03_20\n                        PIXEL12_0\n                        PIXEL13_12\n                    }\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_0\n                        PIXEL30_0\n                        PIXEL31_0\n                    }\n                    else\n                    {\n                        PIXEL20_50\n                        PIXEL30_50\n                        PIXEL31_50\n                    }\n                    PIXEL21_0\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL22_30\n                        PIXEL23_10\n                        PIXEL32_10\n                        PIXEL33_80\n                    }\n                    else\n                    {\n                        PIXEL22_0\n                        PIXEL23_11\n                        PIXEL32_12\n                        PIXEL33_20\n                    }\n                    break;\n                }\n                case 94:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_80\n                        PIXEL01_10\n                        PIXEL10_10\n                        PIXEL11_30\n                    }\n                    else\n                    {\n                        PIXEL00_20\n                        PIXEL01_12\n                        PIXEL10_11\n                        PIXEL11_0\n                    }\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_0\n                        PIXEL03_0\n                        PIXEL13_0\n                    }\n                    else\n                    {\n                        PIXEL02_50\n                        PIXEL03_50\n                        PIXEL13_50\n                    }\n                    PIXEL12_0\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_10\n                        PIXEL21_30\n                        PIXEL30_80\n                        PIXEL31_10\n                    }\n                    else\n                    {\n                        PIXEL20_12\n                        PIXEL21_0\n                        PIXEL30_20\n                        PIXEL31_11\n                    }\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL22_30\n                        PIXEL23_10\n                        PIXEL32_10\n                        PIXEL33_80\n                    }\n                    else\n                    {\n                        PIXEL22_0\n                        PIXEL23_11\n                        PIXEL32_12\n                        PIXEL33_20\n                    }\n                    break;\n                }\n                case 218:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_80\n                        PIXEL01_10\n                        PIXEL10_10\n                        PIXEL11_30\n                    }\n                    else\n                    {\n                        PIXEL00_20\n                        PIXEL01_12\n                        PIXEL10_11\n                        PIXEL11_0\n                    }\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_10\n                        PIXEL03_80\n                        PIXEL12_30\n                        PIXEL13_10\n                    }\n                    else\n                    {\n                        PIXEL02_11\n                        PIXEL03_20\n                        PIXEL12_0\n                        PIXEL13_12\n                    }\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_10\n                        PIXEL21_30\n                        PIXEL30_80\n                        PIXEL31_10\n                    }\n                    else\n                    {\n                        PIXEL20_12\n                        PIXEL21_0\n                        PIXEL30_20\n                        PIXEL31_11\n                    }\n                    PIXEL22_0\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL23_0\n                        PIXEL32_0\n                        PIXEL33_0\n                    }\n                    else\n                    {\n                        PIXEL23_50\n                        PIXEL32_50\n                        PIXEL33_50\n                    }\n                    break;\n                }\n                case 91:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                        PIXEL01_0\n                        PIXEL10_0\n                    }\n                    else\n                    {\n                        PIXEL00_50\n                        PIXEL01_50\n                        PIXEL10_50\n                    }\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_10\n                        PIXEL03_80\n                        PIXEL12_30\n                        PIXEL13_10\n                    }\n                    else\n                    {\n                        PIXEL02_11\n                        PIXEL03_20\n                        PIXEL12_0\n                        PIXEL13_12\n                    }\n                    PIXEL11_0\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_10\n                        PIXEL21_30\n                        PIXEL30_80\n                        PIXEL31_10\n                    }\n                    else\n                    {\n                        PIXEL20_12\n                        PIXEL21_0\n                        PIXEL30_20\n                        PIXEL31_11\n                    }\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL22_30\n                        PIXEL23_10\n                        PIXEL32_10\n                        PIXEL33_80\n                    }\n                    else\n                    {\n                        PIXEL22_0\n                        PIXEL23_11\n                        PIXEL32_12\n                        PIXEL33_20\n                    }\n                    break;\n                }\n                case 229:\n                {\n                    PIXEL00_20\n                    PIXEL01_60\n                    PIXEL02_60\n                    PIXEL03_20\n                    PIXEL10_60\n                    PIXEL11_70\n                    PIXEL12_70\n                    PIXEL13_60\n                    PIXEL20_82\n                    PIXEL21_32\n                    PIXEL22_31\n                    PIXEL23_81\n                    PIXEL30_82\n                    PIXEL31_32\n                    PIXEL32_31\n                    PIXEL33_81\n                    break;\n                }\n                case 167:\n                {\n                    PIXEL00_81\n                    PIXEL01_31\n                    PIXEL02_32\n                    PIXEL03_82\n                    PIXEL10_81\n                    PIXEL11_31\n                    PIXEL12_32\n                    PIXEL13_82\n                    PIXEL20_60\n                    PIXEL21_70\n                    PIXEL22_70\n                    PIXEL23_60\n                    PIXEL30_20\n                    PIXEL31_60\n                    PIXEL32_60\n                    PIXEL33_20\n                    break;\n                }\n                case 173:\n                {\n                    PIXEL00_82\n                    PIXEL01_82\n                    PIXEL02_60\n                    PIXEL03_20\n                    PIXEL10_32\n                    PIXEL11_32\n                    PIXEL12_70\n                    PIXEL13_60\n                    PIXEL20_31\n                    PIXEL21_31\n                    PIXEL22_70\n                    PIXEL23_60\n                    PIXEL30_81\n                    PIXEL31_81\n                    PIXEL32_60\n                    PIXEL33_20\n                    break;\n                }\n                case 181:\n                {\n                    PIXEL00_20\n                    PIXEL01_60\n                    PIXEL02_81\n                    PIXEL03_81\n                    PIXEL10_60\n                    PIXEL11_70\n                    PIXEL12_31\n                    PIXEL13_31\n                    PIXEL20_60\n                    PIXEL21_70\n                    PIXEL22_32\n                    PIXEL23_32\n                    PIXEL30_20\n                    PIXEL31_60\n                    PIXEL32_82\n                    PIXEL33_82\n                    break;\n                }\n                case 186:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_80\n                        PIXEL01_10\n                        PIXEL10_10\n                        PIXEL11_30\n                    }\n                    else\n                    {\n                        PIXEL00_20\n                        PIXEL01_12\n                        PIXEL10_11\n                        PIXEL11_0\n                    }\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_10\n                        PIXEL03_80\n                        PIXEL12_30\n                        PIXEL13_10\n                    }\n                    else\n                    {\n                        PIXEL02_11\n                        PIXEL03_20\n                        PIXEL12_0\n                        PIXEL13_12\n                    }\n                    PIXEL20_31\n                    PIXEL21_31\n                    PIXEL22_32\n                    PIXEL23_32\n                    PIXEL30_81\n                    PIXEL31_81\n                    PIXEL32_82\n                    PIXEL33_82\n                    break;\n                }\n                case 115:\n                {\n                    PIXEL00_81\n                    PIXEL01_31\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_10\n                        PIXEL03_80\n                        PIXEL12_30\n                        PIXEL13_10\n                    }\n                    else\n                    {\n                        PIXEL02_11\n                        PIXEL03_20\n                        PIXEL12_0\n                        PIXEL13_12\n                    }\n                    PIXEL10_81\n                    PIXEL11_31\n                    PIXEL20_82\n                    PIXEL21_32\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL22_30\n                        PIXEL23_10\n                        PIXEL32_10\n                        PIXEL33_80\n                    }\n                    else\n                    {\n                        PIXEL22_0\n                        PIXEL23_11\n                        PIXEL32_12\n                        PIXEL33_20\n                    }\n                    PIXEL30_82\n                    PIXEL31_32\n                    break;\n                }\n                case 93:\n                {\n                    PIXEL00_82\n                    PIXEL01_82\n                    PIXEL02_81\n                    PIXEL03_81\n                    PIXEL10_32\n                    PIXEL11_32\n                    PIXEL12_31\n                    PIXEL13_31\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_10\n                        PIXEL21_30\n                        PIXEL30_80\n                        PIXEL31_10\n                    }\n                    else\n                    {\n                        PIXEL20_12\n                        PIXEL21_0\n                        PIXEL30_20\n                        PIXEL31_11\n                    }\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL22_30\n                        PIXEL23_10\n                        PIXEL32_10\n                        PIXEL33_80\n                    }\n                    else\n                    {\n                        PIXEL22_0\n                        PIXEL23_11\n                        PIXEL32_12\n                        PIXEL33_20\n                    }\n                    break;\n                }\n                case 206:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_80\n                        PIXEL01_10\n                        PIXEL10_10\n                        PIXEL11_30\n                    }\n                    else\n                    {\n                        PIXEL00_20\n                        PIXEL01_12\n                        PIXEL10_11\n                        PIXEL11_0\n                    }\n                    PIXEL02_32\n                    PIXEL03_82\n                    PIXEL12_32\n                    PIXEL13_82\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_10\n                        PIXEL21_30\n                        PIXEL30_80\n                        PIXEL31_10\n                    }\n                    else\n                    {\n                        PIXEL20_12\n                        PIXEL21_0\n                        PIXEL30_20\n                        PIXEL31_11\n                    }\n                    PIXEL22_31\n                    PIXEL23_81\n                    PIXEL32_31\n                    PIXEL33_81\n                    break;\n                }\n                case 205:\n                case 201:\n                {\n                    PIXEL00_82\n                    PIXEL01_82\n                    PIXEL02_60\n                    PIXEL03_20\n                    PIXEL10_32\n                    PIXEL11_32\n                    PIXEL12_70\n                    PIXEL13_60\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_10\n                        PIXEL21_30\n                        PIXEL30_80\n                        PIXEL31_10\n                    }\n                    else\n                    {\n                        PIXEL20_12\n                        PIXEL21_0\n                        PIXEL30_20\n                        PIXEL31_11\n                    }\n                    PIXEL22_31\n                    PIXEL23_81\n                    PIXEL32_31\n                    PIXEL33_81\n                    break;\n                }\n                case 174:\n                case 46:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_80\n                        PIXEL01_10\n                        PIXEL10_10\n                        PIXEL11_30\n                    }\n                    else\n                    {\n                        PIXEL00_20\n                        PIXEL01_12\n                        PIXEL10_11\n                        PIXEL11_0\n                    }\n                    PIXEL02_32\n                    PIXEL03_82\n                    PIXEL12_32\n                    PIXEL13_82\n                    PIXEL20_31\n                    PIXEL21_31\n                    PIXEL22_70\n                    PIXEL23_60\n                    PIXEL30_81\n                    PIXEL31_81\n                    PIXEL32_60\n                    PIXEL33_20\n                    break;\n                }\n                case 179:\n                case 147:\n                {\n                    PIXEL00_81\n                    PIXEL01_31\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_10\n                        PIXEL03_80\n                        PIXEL12_30\n                        PIXEL13_10\n                    }\n                    else\n                    {\n                        PIXEL02_11\n                        PIXEL03_20\n                        PIXEL12_0\n                        PIXEL13_12\n                    }\n                    PIXEL10_81\n                    PIXEL11_31\n                    PIXEL20_60\n                    PIXEL21_70\n                    PIXEL22_32\n                    PIXEL23_32\n                    PIXEL30_20\n                    PIXEL31_60\n                    PIXEL32_82\n                    PIXEL33_82\n                    break;\n                }\n                case 117:\n                case 116:\n                {\n                    PIXEL00_20\n                    PIXEL01_60\n                    PIXEL02_81\n                    PIXEL03_81\n                    PIXEL10_60\n                    PIXEL11_70\n                    PIXEL12_31\n                    PIXEL13_31\n                    PIXEL20_82\n                    PIXEL21_32\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL22_30\n                        PIXEL23_10\n                        PIXEL32_10\n                        PIXEL33_80\n                    }\n                    else\n                    {\n                        PIXEL22_0\n                        PIXEL23_11\n                        PIXEL32_12\n                        PIXEL33_20\n                    }\n                    PIXEL30_82\n                    PIXEL31_32\n                    break;\n                }\n                case 189:\n                {\n                    PIXEL00_82\n                    PIXEL01_82\n                    PIXEL02_81\n                    PIXEL03_81\n                    PIXEL10_32\n                    PIXEL11_32\n                    PIXEL12_31\n                    PIXEL13_31\n                    PIXEL20_31\n                    PIXEL21_31\n                    PIXEL22_32\n                    PIXEL23_32\n                    PIXEL30_81\n                    PIXEL31_81\n                    PIXEL32_82\n                    PIXEL33_82\n                    break;\n                }\n                case 231:\n                {\n                    PIXEL00_81\n                    PIXEL01_31\n                    PIXEL02_32\n                    PIXEL03_82\n                    PIXEL10_81\n                    PIXEL11_31\n                    PIXEL12_32\n                    PIXEL13_82\n                    PIXEL20_82\n                    PIXEL21_32\n                    PIXEL22_31\n                    PIXEL23_81\n                    PIXEL30_82\n                    PIXEL31_32\n                    PIXEL32_31\n                    PIXEL33_81\n                    break;\n                }\n                case 126:\n                {\n                    PIXEL00_80\n                    PIXEL01_10\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_0\n                        PIXEL03_0\n                        PIXEL13_0\n                    }\n                    else\n                    {\n                        PIXEL02_50\n                        PIXEL03_50\n                        PIXEL13_50\n                    }\n                    PIXEL10_10\n                    PIXEL11_30\n                    PIXEL12_0\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_0\n                        PIXEL30_0\n                        PIXEL31_0\n                    }\n                    else\n                    {\n                        PIXEL20_50\n                        PIXEL30_50\n                        PIXEL31_50\n                    }\n                    PIXEL21_0\n                    PIXEL22_30\n                    PIXEL23_10\n                    PIXEL32_10\n                    PIXEL33_80\n                    break;\n                }\n                case 219:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                        PIXEL01_0\n                        PIXEL10_0\n                    }\n                    else\n                    {\n                        PIXEL00_50\n                        PIXEL01_50\n                        PIXEL10_50\n                    }\n                    PIXEL02_10\n                    PIXEL03_80\n                    PIXEL11_0\n                    PIXEL12_30\n                    PIXEL13_10\n                    PIXEL20_10\n                    PIXEL21_30\n                    PIXEL22_0\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL23_0\n                        PIXEL32_0\n                        PIXEL33_0\n                    }\n                    else\n                    {\n                        PIXEL23_50\n                        PIXEL32_50\n                        PIXEL33_50\n                    }\n                    PIXEL30_80\n                    PIXEL31_10\n                    break;\n                }\n                case 125:\n                {\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL00_82\n                        PIXEL10_32\n                        PIXEL20_0\n                        PIXEL21_0\n                        PIXEL30_0\n                        PIXEL31_0\n                    }\n                    else\n                    {\n                        PIXEL00_11\n                        PIXEL10_13\n                        PIXEL20_83\n                        PIXEL21_70\n                        PIXEL30_50\n                        PIXEL31_21\n                    }\n                    PIXEL01_82\n                    PIXEL02_81\n                    PIXEL03_81\n                    PIXEL11_32\n                    PIXEL12_31\n                    PIXEL13_31\n                    PIXEL22_30\n                    PIXEL23_10\n                    PIXEL32_10\n                    PIXEL33_80\n                    break;\n                }\n                case 221:\n                {\n                    PIXEL00_82\n                    PIXEL01_82\n                    PIXEL02_81\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL03_81\n                        PIXEL13_31\n                        PIXEL22_0\n                        PIXEL23_0\n                        PIXEL32_0\n                        PIXEL33_0\n                    }\n                    else\n                    {\n                        PIXEL03_12\n                        PIXEL13_14\n                        PIXEL22_70\n                        PIXEL23_83\n                        PIXEL32_21\n                        PIXEL33_50\n                    }\n                    PIXEL10_32\n                    PIXEL11_32\n                    PIXEL12_31\n                    PIXEL20_10\n                    PIXEL21_30\n                    PIXEL30_80\n                    PIXEL31_10\n                    break;\n                }\n                case 207:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                        PIXEL01_0\n                        PIXEL02_32\n                        PIXEL03_82\n                        PIXEL10_0\n                        PIXEL11_0\n                    }\n                    else\n                    {\n                        PIXEL00_50\n                        PIXEL01_83\n                        PIXEL02_13\n                        PIXEL03_11\n                        PIXEL10_21\n                        PIXEL11_70\n                    }\n                    PIXEL12_32\n                    PIXEL13_82\n                    PIXEL20_10\n                    PIXEL21_30\n                    PIXEL22_31\n                    PIXEL23_81\n                    PIXEL30_80\n                    PIXEL31_10\n                    PIXEL32_31\n                    PIXEL33_81\n                    break;\n                }\n                case 238:\n                {\n                    PIXEL00_80\n                    PIXEL01_10\n                    PIXEL02_32\n                    PIXEL03_82\n                    PIXEL10_10\n                    PIXEL11_30\n                    PIXEL12_32\n                    PIXEL13_82\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_0\n                        PIXEL21_0\n                        PIXEL30_0\n                        PIXEL31_0\n                        PIXEL32_31\n                        PIXEL33_81\n                    }\n                    else\n                    {\n                        PIXEL20_21\n                        PIXEL21_70\n                        PIXEL30_50\n                        PIXEL31_83\n                        PIXEL32_14\n                        PIXEL33_12\n                    }\n                    PIXEL22_31\n                    PIXEL23_81\n                    break;\n                }\n                case 190:\n                {\n                    PIXEL00_80\n                    PIXEL01_10\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_0\n                        PIXEL03_0\n                        PIXEL12_0\n                        PIXEL13_0\n                        PIXEL23_32\n                        PIXEL33_82\n                    }\n                    else\n                    {\n                        PIXEL02_21\n                        PIXEL03_50\n                        PIXEL12_70\n                        PIXEL13_83\n                        PIXEL23_13\n                        PIXEL33_11\n                    }\n                    PIXEL10_10\n                    PIXEL11_30\n                    PIXEL20_31\n                    PIXEL21_31\n                    PIXEL22_32\n                    PIXEL30_81\n                    PIXEL31_81\n                    PIXEL32_82\n                    break;\n                }\n                case 187:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                        PIXEL01_0\n                        PIXEL10_0\n                        PIXEL11_0\n                        PIXEL20_31\n                        PIXEL30_81\n                    }\n                    else\n                    {\n                        PIXEL00_50\n                        PIXEL01_21\n                        PIXEL10_83\n                        PIXEL11_70\n                        PIXEL20_14\n                        PIXEL30_12\n                    }\n                    PIXEL02_10\n                    PIXEL03_80\n                    PIXEL12_30\n                    PIXEL13_10\n                    PIXEL21_31\n                    PIXEL22_32\n                    PIXEL23_32\n                    PIXEL31_81\n                    PIXEL32_82\n                    PIXEL33_82\n                    break;\n                }\n                case 243:\n                {\n                    PIXEL00_81\n                    PIXEL01_31\n                    PIXEL02_10\n                    PIXEL03_80\n                    PIXEL10_81\n                    PIXEL11_31\n                    PIXEL12_30\n                    PIXEL13_10\n                    PIXEL20_82\n                    PIXEL21_32\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL22_0\n                        PIXEL23_0\n                        PIXEL30_82\n                        PIXEL31_32\n                        PIXEL32_0\n                        PIXEL33_0\n                    }\n                    else\n                    {\n                        PIXEL22_70\n                        PIXEL23_21\n                        PIXEL30_11\n                        PIXEL31_13\n                        PIXEL32_83\n                        PIXEL33_50\n                    }\n                    break;\n                }\n                case 119:\n                {\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL00_81\n                        PIXEL01_31\n                        PIXEL02_0\n                        PIXEL03_0\n                        PIXEL12_0\n                        PIXEL13_0\n                    }\n                    else\n                    {\n                        PIXEL00_12\n                        PIXEL01_14\n                        PIXEL02_83\n                        PIXEL03_50\n                        PIXEL12_70\n                        PIXEL13_21\n                    }\n                    PIXEL10_81\n                    PIXEL11_31\n                    PIXEL20_82\n                    PIXEL21_32\n                    PIXEL22_30\n                    PIXEL23_10\n                    PIXEL30_82\n                    PIXEL31_32\n                    PIXEL32_10\n                    PIXEL33_80\n                    break;\n                }\n                case 237:\n                case 233:\n                {\n                    PIXEL00_82\n                    PIXEL01_82\n                    PIXEL02_60\n                    PIXEL03_20\n                    PIXEL10_32\n                    PIXEL11_32\n                    PIXEL12_70\n                    PIXEL13_60\n                    PIXEL20_0\n                    PIXEL21_0\n                    PIXEL22_31\n                    PIXEL23_81\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL30_0\n                    }\n                    else\n                    {\n                        PIXEL30_20\n                    }\n                    PIXEL31_0\n                    PIXEL32_31\n                    PIXEL33_81\n                    break;\n                }\n                case 175:\n                case 47:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                    }\n                    else\n                    {\n                        PIXEL00_20\n                    }\n                    PIXEL01_0\n                    PIXEL02_32\n                    PIXEL03_82\n                    PIXEL10_0\n                    PIXEL11_0\n                    PIXEL12_32\n                    PIXEL13_82\n                    PIXEL20_31\n                    PIXEL21_31\n                    PIXEL22_70\n                    PIXEL23_60\n                    PIXEL30_81\n                    PIXEL31_81\n                    PIXEL32_60\n                    PIXEL33_20\n                    break;\n                }\n                case 183:\n                case 151:\n                {\n                    PIXEL00_81\n                    PIXEL01_31\n                    PIXEL02_0\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL03_0\n                    }\n                    else\n                    {\n                        PIXEL03_20\n                    }\n                    PIXEL10_81\n                    PIXEL11_31\n                    PIXEL12_0\n                    PIXEL13_0\n                    PIXEL20_60\n                    PIXEL21_70\n                    PIXEL22_32\n                    PIXEL23_32\n                    PIXEL30_20\n                    PIXEL31_60\n                    PIXEL32_82\n                    PIXEL33_82\n                    break;\n                }\n                case 245:\n                case 244:\n                {\n                    PIXEL00_20\n                    PIXEL01_60\n                    PIXEL02_81\n                    PIXEL03_81\n                    PIXEL10_60\n                    PIXEL11_70\n                    PIXEL12_31\n                    PIXEL13_31\n                    PIXEL20_82\n                    PIXEL21_32\n                    PIXEL22_0\n                    PIXEL23_0\n                    PIXEL30_82\n                    PIXEL31_32\n                    PIXEL32_0\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL33_0\n                    }\n                    else\n                    {\n                        PIXEL33_20\n                    }\n                    break;\n                }\n                case 250:\n                {\n                    PIXEL00_80\n                    PIXEL01_10\n                    PIXEL02_10\n                    PIXEL03_80\n                    PIXEL10_10\n                    PIXEL11_30\n                    PIXEL12_30\n                    PIXEL13_10\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_0\n                        PIXEL30_0\n                        PIXEL31_0\n                    }\n                    else\n                    {\n                        PIXEL20_50\n                        PIXEL30_50\n                        PIXEL31_50\n                    }\n                    PIXEL21_0\n                    PIXEL22_0\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL23_0\n                        PIXEL32_0\n                        PIXEL33_0\n                    }\n                    else\n                    {\n                        PIXEL23_50\n                        PIXEL32_50\n                        PIXEL33_50\n                    }\n                    break;\n                }\n                case 123:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                        PIXEL01_0\n                        PIXEL10_0\n                    }\n                    else\n                    {\n                        PIXEL00_50\n                        PIXEL01_50\n                        PIXEL10_50\n                    }\n                    PIXEL02_10\n                    PIXEL03_80\n                    PIXEL11_0\n                    PIXEL12_30\n                    PIXEL13_10\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_0\n                        PIXEL30_0\n                        PIXEL31_0\n                    }\n                    else\n                    {\n                        PIXEL20_50\n                        PIXEL30_50\n                        PIXEL31_50\n                    }\n                    PIXEL21_0\n                    PIXEL22_30\n                    PIXEL23_10\n                    PIXEL32_10\n                    PIXEL33_80\n                    break;\n                }\n                case 95:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                        PIXEL01_0\n                        PIXEL10_0\n                    }\n                    else\n                    {\n                        PIXEL00_50\n                        PIXEL01_50\n                        PIXEL10_50\n                    }\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_0\n                        PIXEL03_0\n                        PIXEL13_0\n                    }\n                    else\n                    {\n                        PIXEL02_50\n                        PIXEL03_50\n                        PIXEL13_50\n                    }\n                    PIXEL11_0\n                    PIXEL12_0\n                    PIXEL20_10\n                    PIXEL21_30\n                    PIXEL22_30\n                    PIXEL23_10\n                    PIXEL30_80\n                    PIXEL31_10\n                    PIXEL32_10\n                    PIXEL33_80\n                    break;\n                }\n                case 222:\n                {\n                    PIXEL00_80\n                    PIXEL01_10\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_0\n                        PIXEL03_0\n                        PIXEL13_0\n                    }\n                    else\n                    {\n                        PIXEL02_50\n                        PIXEL03_50\n                        PIXEL13_50\n                    }\n                    PIXEL10_10\n                    PIXEL11_30\n                    PIXEL12_0\n                    PIXEL20_10\n                    PIXEL21_30\n                    PIXEL22_0\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL23_0\n                        PIXEL32_0\n                        PIXEL33_0\n                    }\n                    else\n                    {\n                        PIXEL23_50\n                        PIXEL32_50\n                        PIXEL33_50\n                    }\n                    PIXEL30_80\n                    PIXEL31_10\n                    break;\n                }\n                case 252:\n                {\n                    PIXEL00_80\n                    PIXEL01_61\n                    PIXEL02_81\n                    PIXEL03_81\n                    PIXEL10_10\n                    PIXEL11_30\n                    PIXEL12_31\n                    PIXEL13_31\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_0\n                        PIXEL30_0\n                        PIXEL31_0\n                    }\n                    else\n                    {\n                        PIXEL20_50\n                        PIXEL30_50\n                        PIXEL31_50\n                    }\n                    PIXEL21_0\n                    PIXEL22_0\n                    PIXEL23_0\n                    PIXEL32_0\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL33_0\n                    }\n                    else\n                    {\n                        PIXEL33_20\n                    }\n                    break;\n                }\n                case 249:\n                {\n                    PIXEL00_82\n                    PIXEL01_82\n                    PIXEL02_61\n                    PIXEL03_80\n                    PIXEL10_32\n                    PIXEL11_32\n                    PIXEL12_30\n                    PIXEL13_10\n                    PIXEL20_0\n                    PIXEL21_0\n                    PIXEL22_0\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL23_0\n                        PIXEL32_0\n                        PIXEL33_0\n                    }\n                    else\n                    {\n                        PIXEL23_50\n                        PIXEL32_50\n                        PIXEL33_50\n                    }\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL30_0\n                    }\n                    else\n                    {\n                        PIXEL30_20\n                    }\n                    PIXEL31_0\n                    break;\n                }\n                case 235:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                        PIXEL01_0\n                        PIXEL10_0\n                    }\n                    else\n                    {\n                        PIXEL00_50\n                        PIXEL01_50\n                        PIXEL10_50\n                    }\n                    PIXEL02_10\n                    PIXEL03_80\n                    PIXEL11_0\n                    PIXEL12_30\n                    PIXEL13_61\n                    PIXEL20_0\n                    PIXEL21_0\n                    PIXEL22_31\n                    PIXEL23_81\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL30_0\n                    }\n                    else\n                    {\n                        PIXEL30_20\n                    }\n                    PIXEL31_0\n                    PIXEL32_31\n                    PIXEL33_81\n                    break;\n                }\n                case 111:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                    }\n                    else\n                    {\n                        PIXEL00_20\n                    }\n                    PIXEL01_0\n                    PIXEL02_32\n                    PIXEL03_82\n                    PIXEL10_0\n                    PIXEL11_0\n                    PIXEL12_32\n                    PIXEL13_82\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_0\n                        PIXEL30_0\n                        PIXEL31_0\n                    }\n                    else\n                    {\n                        PIXEL20_50\n                        PIXEL30_50\n                        PIXEL31_50\n                    }\n                    PIXEL21_0\n                    PIXEL22_30\n                    PIXEL23_61\n                    PIXEL32_10\n                    PIXEL33_80\n                    break;\n                }\n                case 63:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                    }\n                    else\n                    {\n                        PIXEL00_20\n                    }\n                    PIXEL01_0\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_0\n                        PIXEL03_0\n                        PIXEL13_0\n                    }\n                    else\n                    {\n                        PIXEL02_50\n                        PIXEL03_50\n                        PIXEL13_50\n                    }\n                    PIXEL10_0\n                    PIXEL11_0\n                    PIXEL12_0\n                    PIXEL20_31\n                    PIXEL21_31\n                    PIXEL22_30\n                    PIXEL23_10\n                    PIXEL30_81\n                    PIXEL31_81\n                    PIXEL32_61\n                    PIXEL33_80\n                    break;\n                }\n                case 159:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                        PIXEL01_0\n                        PIXEL10_0\n                    }\n                    else\n                    {\n                        PIXEL00_50\n                        PIXEL01_50\n                        PIXEL10_50\n                    }\n                    PIXEL02_0\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL03_0\n                    }\n                    else\n                    {\n                        PIXEL03_20\n                    }\n                    PIXEL11_0\n                    PIXEL12_0\n                    PIXEL13_0\n                    PIXEL20_10\n                    PIXEL21_30\n                    PIXEL22_32\n                    PIXEL23_32\n                    PIXEL30_80\n                    PIXEL31_61\n                    PIXEL32_82\n                    PIXEL33_82\n                    break;\n                }\n                case 215:\n                {\n                    PIXEL00_81\n                    PIXEL01_31\n                    PIXEL02_0\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL03_0\n                    }\n                    else\n                    {\n                        PIXEL03_20\n                    }\n                    PIXEL10_81\n                    PIXEL11_31\n                    PIXEL12_0\n                    PIXEL13_0\n                    PIXEL20_61\n                    PIXEL21_30\n                    PIXEL22_0\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL23_0\n                        PIXEL32_0\n                        PIXEL33_0\n                    }\n                    else\n                    {\n                        PIXEL23_50\n                        PIXEL32_50\n                        PIXEL33_50\n                    }\n                    PIXEL30_80\n                    PIXEL31_10\n                    break;\n                }\n                case 246:\n                {\n                    PIXEL00_80\n                    PIXEL01_10\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_0\n                        PIXEL03_0\n                        PIXEL13_0\n                    }\n                    else\n                    {\n                        PIXEL02_50\n                        PIXEL03_50\n                        PIXEL13_50\n                    }\n                    PIXEL10_61\n                    PIXEL11_30\n                    PIXEL12_0\n                    PIXEL20_82\n                    PIXEL21_32\n                    PIXEL22_0\n                    PIXEL23_0\n                    PIXEL30_82\n                    PIXEL31_32\n                    PIXEL32_0\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL33_0\n                    }\n                    else\n                    {\n                        PIXEL33_20\n                    }\n                    break;\n                }\n                case 254:\n                {\n                    PIXEL00_80\n                    PIXEL01_10\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_0\n                        PIXEL03_0\n                        PIXEL13_0\n                    }\n                    else\n                    {\n                        PIXEL02_50\n                        PIXEL03_50\n                        PIXEL13_50\n                    }\n                    PIXEL10_10\n                    PIXEL11_30\n                    PIXEL12_0\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_0\n                        PIXEL30_0\n                        PIXEL31_0\n                    }\n                    else\n                    {\n                        PIXEL20_50\n                        PIXEL30_50\n                        PIXEL31_50\n                    }\n                    PIXEL21_0\n                    PIXEL22_0\n                    PIXEL23_0\n                    PIXEL32_0\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL33_0\n                    }\n                    else\n                    {\n                        PIXEL33_20\n                    }\n                    break;\n                }\n                case 253:\n                {\n                    PIXEL00_82\n                    PIXEL01_82\n                    PIXEL02_81\n                    PIXEL03_81\n                    PIXEL10_32\n                    PIXEL11_32\n                    PIXEL12_31\n                    PIXEL13_31\n                    PIXEL20_0\n                    PIXEL21_0\n                    PIXEL22_0\n                    PIXEL23_0\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL30_0\n                    }\n                    else\n                    {\n                        PIXEL30_20\n                    }\n                    PIXEL31_0\n                    PIXEL32_0\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL33_0\n                    }\n                    else\n                    {\n                        PIXEL33_20\n                    }\n                    break;\n                }\n                case 251:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                        PIXEL01_0\n                        PIXEL10_0\n                    }\n                    else\n                    {\n                        PIXEL00_50\n                        PIXEL01_50\n                        PIXEL10_50\n                    }\n                    PIXEL02_10\n                    PIXEL03_80\n                    PIXEL11_0\n                    PIXEL12_30\n                    PIXEL13_10\n                    PIXEL20_0\n                    PIXEL21_0\n                    PIXEL22_0\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL23_0\n                        PIXEL32_0\n                        PIXEL33_0\n                    }\n                    else\n                    {\n                        PIXEL23_50\n                        PIXEL32_50\n                        PIXEL33_50\n                    }\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL30_0\n                    }\n                    else\n                    {\n                        PIXEL30_20\n                    }\n                    PIXEL31_0\n                    break;\n                }\n                case 239:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                    }\n                    else\n                    {\n                        PIXEL00_20\n                    }\n                    PIXEL01_0\n                    PIXEL02_32\n                    PIXEL03_82\n                    PIXEL10_0\n                    PIXEL11_0\n                    PIXEL12_32\n                    PIXEL13_82\n                    PIXEL20_0\n                    PIXEL21_0\n                    PIXEL22_31\n                    PIXEL23_81\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL30_0\n                    }\n                    else\n                    {\n                        PIXEL30_20\n                    }\n                    PIXEL31_0\n                    PIXEL32_31\n                    PIXEL33_81\n                    break;\n                }\n                case 127:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                    }\n                    else\n                    {\n                        PIXEL00_20\n                    }\n                    PIXEL01_0\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL02_0\n                        PIXEL03_0\n                        PIXEL13_0\n                    }\n                    else\n                    {\n                        PIXEL02_50\n                        PIXEL03_50\n                        PIXEL13_50\n                    }\n                    PIXEL10_0\n                    PIXEL11_0\n                    PIXEL12_0\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL20_0\n                        PIXEL30_0\n                        PIXEL31_0\n                    }\n                    else\n                    {\n                        PIXEL20_50\n                        PIXEL30_50\n                        PIXEL31_50\n                    }\n                    PIXEL21_0\n                    PIXEL22_30\n                    PIXEL23_10\n                    PIXEL32_10\n                    PIXEL33_80\n                    break;\n                }\n                case 191:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                    }\n                    else\n                    {\n                        PIXEL00_20\n                    }\n                    PIXEL01_0\n                    PIXEL02_0\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL03_0\n                    }\n                    else\n                    {\n                        PIXEL03_20\n                    }\n                    PIXEL10_0\n                    PIXEL11_0\n                    PIXEL12_0\n                    PIXEL13_0\n                    PIXEL20_31\n                    PIXEL21_31\n                    PIXEL22_32\n                    PIXEL23_32\n                    PIXEL30_81\n                    PIXEL31_81\n                    PIXEL32_82\n                    PIXEL33_82\n                    break;\n                }\n                case 223:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                        PIXEL01_0\n                        PIXEL10_0\n                    }\n                    else\n                    {\n                        PIXEL00_50\n                        PIXEL01_50\n                        PIXEL10_50\n                    }\n                    PIXEL02_0\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL03_0\n                    }\n                    else\n                    {\n                        PIXEL03_20\n                    }\n                    PIXEL11_0\n                    PIXEL12_0\n                    PIXEL13_0\n                    PIXEL20_10\n                    PIXEL21_30\n                    PIXEL22_0\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL23_0\n                        PIXEL32_0\n                        PIXEL33_0\n                    }\n                    else\n                    {\n                        PIXEL23_50\n                        PIXEL32_50\n                        PIXEL33_50\n                    }\n                    PIXEL30_80\n                    PIXEL31_10\n                    break;\n                }\n                case 247:\n                {\n                    PIXEL00_81\n                    PIXEL01_31\n                    PIXEL02_0\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL03_0\n                    }\n                    else\n                    {\n                        PIXEL03_20\n                    }\n                    PIXEL10_81\n                    PIXEL11_31\n                    PIXEL12_0\n                    PIXEL13_0\n                    PIXEL20_82\n                    PIXEL21_32\n                    PIXEL22_0\n                    PIXEL23_0\n                    PIXEL30_82\n                    PIXEL31_32\n                    PIXEL32_0\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL33_0\n                    }\n                    else\n                    {\n                        PIXEL33_20\n                    }\n                    break;\n                }\n                case 255:\n                {\n                    if (Diff(w[4], w[2]))\n                    {\n                        PIXEL00_0\n                    }\n                    else\n                    {\n                        PIXEL00_20\n                    }\n                    PIXEL01_0\n                    PIXEL02_0\n                    if (Diff(w[2], w[6]))\n                    {\n                        PIXEL03_0\n                    }\n                    else\n                    {\n                        PIXEL03_20\n                    }\n                    PIXEL10_0\n                    PIXEL11_0\n                    PIXEL12_0\n                    PIXEL13_0\n                    PIXEL20_0\n                    PIXEL21_0\n                    PIXEL22_0\n                    PIXEL23_0\n                    if (Diff(w[8], w[4]))\n                    {\n                        PIXEL30_0\n                    }\n                    else\n                    {\n                        PIXEL30_20\n                    }\n                    PIXEL31_0\n                    PIXEL32_0\n                    if (Diff(w[6], w[8]))\n                    {\n                        PIXEL33_0\n                    }\n                    else\n                    {\n                        PIXEL33_20\n                    }\n                    break;\n                }\n            }\n            sp++;\n            dp += 4;\n        }\n\n        sRowP += srb;\n        sp = (const uint32_t*) sRowP;\n\n        dRowP += drb * 4;\n        dp = (uint32_t*) dRowP;\n    }\n}\n\nHQX_API void HQX_CALLCONV hq4x_32(const uint32_t* sp, uint32_t* dp, int Xres, int Yres )\n{\n    uint32_t rowBytesL = Xres * 4;\n    hq4x_32_rb(sp, rowBytesL, dp, rowBytesL * 4, Xres, Yres);\n}\n"
  },
  {
    "path": "src/Engine/Scalers/hqx.h",
    "content": "/*\n * Copyright (C) 2003 Maxim Stepin ( maxst@hiend3d.com )\n *\n * Copyright (C) 2010 Cameron Zemek ( grom@zeminvaders.net)\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n */\n\n#ifndef __HQX_H_\n#define __HQX_H_\n\n#include <stdint.h>\n\n#if 0 /*defined( __GNUC__ )*/\n#ifdef __MINGW32__\n#define HQX_CALLCONV __stdcall\n#else\n#define HQX_CALLCONV\n#endif\n#else\n#define HQX_CALLCONV\n#endif\n\n#if 0 /*defined(_WIN32)*/\n#ifdef DLL_EXPORT\n#define HQX_API __declspec(dllexport)\n#else\n#define HQX_API __declspec(dllimport)\n#endif\n#else\n#define HQX_API\n#endif\n\nHQX_API void HQX_CALLCONV hqxInit(void);\nHQX_API void HQX_CALLCONV hq2x_32(const uint32_t* src, uint32_t* dest, int width, int height );\nHQX_API void HQX_CALLCONV hq3x_32(const uint32_t* src, uint32_t* dest, int width, int height );\nHQX_API void HQX_CALLCONV hq4x_32(const uint32_t* src, uint32_t* dest, int width, int height );\n\nHQX_API void HQX_CALLCONV hq2x_32_rb(const uint32_t* src, uint32_t src_rowBytes, uint32_t* dest, uint32_t dest_rowBytes, int width, int height );\nHQX_API void HQX_CALLCONV hq3x_32_rb(const uint32_t* src, uint32_t src_rowBytes, uint32_t* dest, uint32_t dest_rowBytes, int width, int height );\nHQX_API void HQX_CALLCONV hq4x_32_rb(const uint32_t* src, uint32_t src_rowBytes, uint32_t* dest, uint32_t dest_rowBytes, int width, int height );\n\n#endif\n"
  },
  {
    "path": "src/Engine/Scalers/init.cpp",
    "content": "/*\n * Copyright (C) 2010 Cameron Zemek ( grom@zeminvaders.net)\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n */\n\n#include <stdint.h>\n#include \"hqx.h\"\n\nuint32_t   RGBtoYUV[16777216];\nuint32_t   YUV1, YUV2;\n\nHQX_API void HQX_CALLCONV hqxInit(void)\n{\n    /* Initialize RGB to YUV lookup table */\n    uint32_t c, r, g, b, y, u, v;\n    for (c = 0; c < 16777215; c++) {\n        r = (c & 0xFF0000) >> 16;\n        g = (c & 0x00FF00) >> 8;\n        b = c & 0x0000FF;\n        y = (uint32_t)(0.299*r + 0.587*g + 0.114*b);\n        u = (uint32_t)(-0.169*r - 0.331*g + 0.5*b) + 128;\n        v = (uint32_t)(0.5*r - 0.419*g - 0.081*b) + 128;\n        RGBtoYUV[c] = (y << 16) + (u << 8) + v;\n    }\n}\n"
  },
  {
    "path": "src/Engine/Scalers/scale2x.cpp",
    "content": "/*\n * This file is part of the Scale2x project.\n *\n * Copyright (C) 2001, 2002, 2003, 2004 Andrea Mazzoleni\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n */\n\n/*\n * This file contains a C and MMX implementation of the Scale2x effect.\n *\n * You can find an high level description of the effect at :\n *\n * http://scale2x.sourceforge.net/\n */\n\n#if HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include \"scale2x.h\"\n\n#include <assert.h>\n\n#if (_MSC_VER >= 1400)\n#define restrict __restrict\n#else\n#define restrict\n#endif\n\n#ifdef _WIN32\n#ifndef __GNUC__\n#pragma optimize(\"a\", on)\n#endif\n#endif\n\n\n/***************************************************************************/\n/* Scale2x C implementation */\n\n/**\n * Define the macro USE_SCALE_RANDOMWRITE to enable\n * an optimized version which writes memory in random order.\n * This version is a little faster if you write in system memory.\n * But it's a lot slower if you write in video memory.\n * So, enable it only if you are sure to never write directly in video memory.\n */\n/* #define USE_SCALE_RANDOMWRITE */\n\nstatic inline void scale2x_8_def_border(scale2x_uint8* restrict dst, const scale2x_uint8* restrict src0, const scale2x_uint8* restrict src1, const scale2x_uint8* restrict src2, unsigned count)\n{\n\tassert(count >= 2);\n\n\t/* first pixel */\n\tif (src0[0] != src2[0] && src1[0] != src1[1]) {\n\t\tdst[0] = src1[0] == src0[0] ? src0[0] : src1[0];\n\t\tdst[1] = src1[1] == src0[0] ? src0[0] : src1[0];\n\t} else {\n\t\tdst[0] = src1[0];\n\t\tdst[1] = src1[0];\n\t}\n\t++src0;\n\t++src1;\n\t++src2;\n\tdst += 2;\n\n\t/* central pixels */\n\tcount -= 2;\n\twhile (count) {\n\t\tif (src0[0] != src2[0] && src1[-1] != src1[1]) {\n\t\t\tdst[0] = src1[-1] == src0[0] ? src0[0] : src1[0];\n\t\t\tdst[1] = src1[1] == src0[0] ? src0[0] : src1[0];\n\t\t} else {\n\t\t\tdst[0] = src1[0];\n\t\t\tdst[1] = src1[0];\n\t\t}\n\n\t\t++src0;\n\t\t++src1;\n\t\t++src2;\n\t\tdst += 2;\n\t\t--count;\n\t}\n\n\t/* last pixel */\n\tif (src0[0] != src2[0] && src1[-1] != src1[0]) {\n\t\tdst[0] = src1[-1] == src0[0] ? src0[0] : src1[0];\n\t\tdst[1] = src1[0] == src0[0] ? src0[0] : src1[0];\n\t} else {\n\t\tdst[0] = src1[0];\n\t\tdst[1] = src1[0];\n\t}\n}\n\nstatic inline void scale2x_8_def_center(scale2x_uint8* restrict dst, const scale2x_uint8* restrict src0, const scale2x_uint8* restrict src1, const scale2x_uint8* restrict src2, unsigned count)\n{\n\tassert(count >= 2);\n\n\t/* first pixel */\n\tif (src0[0] != src2[0] && src1[0] != src1[1]) {\n\t\tdst[0] = src1[0];\n\t\tdst[1] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];\n\t} else {\n\t\tdst[0] = src1[0];\n\t\tdst[1] = src1[0];\n\t}\n\t++src0;\n\t++src1;\n\t++src2;\n\tdst += 2;\n\n\t/* central pixels */\n\tcount -= 2;\n\twhile (count) {\n\t\tif (src0[0] != src2[0] && src1[-1] != src1[1]) {\n\t\t\tdst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];\n\t\t\tdst[1] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];\n\t\t} else {\n\t\t\tdst[0] = src1[0];\n\t\t\tdst[1] = src1[0];\n\t\t}\n\n\t\t++src0;\n\t\t++src1;\n\t\t++src2;\n\t\tdst += 2;\n\t\t--count;\n\t}\n\n\t/* last pixel */\n\tif (src0[0] != src2[0] && src1[-1] != src1[0]) {\n\t\tdst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];\n\t\tdst[1] = src1[0];\n\t} else {\n\t\tdst[0] = src1[0];\n\t\tdst[1] = src1[0];\n\t}\n}\n\nstatic inline void scale2x_16_def_border(scale2x_uint16* restrict dst, const scale2x_uint16* restrict src0, const scale2x_uint16* restrict src1, const scale2x_uint16* restrict src2, unsigned count)\n{\n\tassert(count >= 2);\n\n\t/* first pixel */\n\tif (src0[0] != src2[0] && src1[0] != src1[1]) {\n\t\tdst[0] = src1[0] == src0[0] ? src0[0] : src1[0];\n\t\tdst[1] = src1[1] == src0[0] ? src0[0] : src1[0];\n\t} else {\n\t\tdst[0] = src1[0];\n\t\tdst[1] = src1[0];\n\t}\n\t++src0;\n\t++src1;\n\t++src2;\n\tdst += 2;\n\n\t/* central pixels */\n\tcount -= 2;\n\twhile (count) {\n\t\tif (src0[0] != src2[0] && src1[-1] != src1[1]) {\n\t\t\tdst[0] = src1[-1] == src0[0] ? src0[0] : src1[0];\n\t\t\tdst[1] = src1[1] == src0[0] ? src0[0] : src1[0];\n\t\t} else {\n\t\t\tdst[0] = src1[0];\n\t\t\tdst[1] = src1[0];\n\t\t}\n\n\t\t++src0;\n\t\t++src1;\n\t\t++src2;\n\t\tdst += 2;\n\t\t--count;\n\t}\n\n\t/* last pixel */\n\tif (src0[0] != src2[0] && src1[-1] != src1[0]) {\n\t\tdst[0] = src1[-1] == src0[0] ? src0[0] : src1[0];\n\t\tdst[1] = src1[0] == src0[0] ? src0[0] : src1[0];\n\t} else {\n\t\tdst[0] = src1[0];\n\t\tdst[1] = src1[0];\n\t}\n}\n\nstatic inline void scale2x_16_def_center(scale2x_uint16* restrict dst, const scale2x_uint16* restrict src0, const scale2x_uint16* restrict src1, const scale2x_uint16* restrict src2, unsigned count)\n{\n\tassert(count >= 2);\n\n\t/* first pixel */\n\tif (src0[0] != src2[0] && src1[0] != src1[1]) {\n\t\tdst[0] = src1[0];\n\t\tdst[1] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];\n\t} else {\n\t\tdst[0] = src1[0];\n\t\tdst[1] = src1[0];\n\t}\n\t++src0;\n\t++src1;\n\t++src2;\n\tdst += 2;\n\n\t/* central pixels */\n\tcount -= 2;\n\twhile (count) {\n\t\tif (src0[0] != src2[0] && src1[-1] != src1[1]) {\n\t\t\tdst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];\n\t\t\tdst[1] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];\n\t\t} else {\n\t\t\tdst[0] = src1[0];\n\t\t\tdst[1] = src1[0];\n\t\t}\n\n\t\t++src0;\n\t\t++src1;\n\t\t++src2;\n\t\tdst += 2;\n\t\t--count;\n\t}\n\n\t/* last pixel */\n\tif (src0[0] != src2[0] && src1[-1] != src1[0]) {\n\t\tdst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];\n\t\tdst[1] = src1[0];\n\t} else {\n\t\tdst[0] = src1[0];\n\t\tdst[1] = src1[0];\n\t}\n}\n\nstatic inline void scale2x_32_def_border(scale2x_uint32* restrict dst, const scale2x_uint32* restrict src0, const scale2x_uint32* restrict src1, const scale2x_uint32* restrict src2, unsigned count)\n{\n\tassert(count >= 2);\n\n\t/* first pixel */\n\tif (src0[0] != src2[0] && src1[0] != src1[1]) {\n\t\tdst[0] = src1[0] == src0[0] ? src0[0] : src1[0];\n\t\tdst[1] = src1[1] == src0[0] ? src0[0] : src1[0];\n\t} else {\n\t\tdst[0] = src1[0];\n\t\tdst[1] = src1[0];\n\t}\n\t++src0;\n\t++src1;\n\t++src2;\n\tdst += 2;\n\n\t/* central pixels */\n\tcount -= 2;\n\twhile (count) {\n\t\tif (src0[0] != src2[0] && src1[-1] != src1[1]) {\n\t\t\tdst[0] = src1[-1] == src0[0] ? src0[0] : src1[0];\n\t\t\tdst[1] = src1[1] == src0[0] ? src0[0] : src1[0];\n\t\t} else {\n\t\t\tdst[0] = src1[0];\n\t\t\tdst[1] = src1[0];\n\t\t}\n\n\t\t++src0;\n\t\t++src1;\n\t\t++src2;\n\t\tdst += 2;\n\t\t--count;\n\t}\n\n\t/* last pixel */\n\tif (src0[0] != src2[0] && src1[-1] != src1[0]) {\n\t\tdst[0] = src1[-1] == src0[0] ? src0[0] : src1[0];\n\t\tdst[1] = src1[0] == src0[0] ? src0[0] : src1[0];\n\t} else {\n\t\tdst[0] = src1[0];\n\t\tdst[1] = src1[0];\n\t}\n}\n\nstatic inline void scale2x_32_def_center(scale2x_uint32* restrict dst, const scale2x_uint32* restrict src0, const scale2x_uint32* restrict src1, const scale2x_uint32* restrict src2, unsigned count)\n{\n\tassert(count >= 2);\n\n\t/* first pixel */\n\tif (src0[0] != src2[0] && src1[0] != src1[1]) {\n\t\tdst[0] = src1[0];\n\t\tdst[1] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];\n\t} else {\n\t\tdst[0] = src1[0];\n\t\tdst[1] = src1[0];\n\t}\n\t++src0;\n\t++src1;\n\t++src2;\n\tdst += 2;\n\n\t/* central pixels */\n\tcount -= 2;\n\twhile (count) {\n\t\tif (src0[0] != src2[0] && src1[-1] != src1[1]) {\n\t\t\tdst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];\n\t\t\tdst[1] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];\n\t\t} else {\n\t\t\tdst[0] = src1[0];\n\t\t\tdst[1] = src1[0];\n\t\t}\n\n\t\t++src0;\n\t\t++src1;\n\t\t++src2;\n\t\tdst += 2;\n\t\t--count;\n\t}\n\n\t/* last pixel */\n\tif (src0[0] != src2[0] && src1[-1] != src1[0]) {\n\t\tdst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];\n\t\tdst[1] = src1[0];\n\t} else {\n\t\tdst[0] = src1[0];\n\t\tdst[1] = src1[0];\n\t}\n}\n\n/**\n * Scale by a factor of 2 a row of pixels of 8 bits.\n * The function is implemented in C.\n * The pixels over the left and right borders are assumed of the same color of\n * the pixels on the border.\n * Note that the implementation is optimized to write data sequentially to\n * maximize the bandwidth on video memory.\n * \\param src0 Pointer at the first pixel of the previous row.\n * \\param src1 Pointer at the first pixel of the current row.\n * \\param src2 Pointer at the first pixel of the next row.\n * \\param count Length in pixels of the src0, src1 and src2 rows.\n * It must be at least 2.\n * \\param dst0 First destination row, double length in pixels.\n * \\param dst1 Second destination row, double length in pixels.\n */\nvoid scale2x_8_def(scale2x_uint8* dst0, scale2x_uint8* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count)\n{\n#ifdef USE_SCALE_RANDOMWRITE\n\tscale2x_8_def_whole(dst0, dst1, src0, src1, src2, count);\n#else\n\tscale2x_8_def_border(dst0, src0, src1, src2, count);\n\tscale2x_8_def_border(dst1, src2, src1, src0, count);\n#endif\n}\n\n/**\n * Scale by a factor of 2 a row of pixels of 16 bits.\n * This function operates like scale2x_8_def() but for 16 bits pixels.\n * \\param src0 Pointer at the first pixel of the previous row.\n * \\param src1 Pointer at the first pixel of the current row.\n * \\param src2 Pointer at the first pixel of the next row.\n * \\param count Length in pixels of the src0, src1 and src2 rows.\n * It must be at least 2.\n * \\param dst0 First destination row, double length in pixels.\n * \\param dst1 Second destination row, double length in pixels.\n */\nvoid scale2x_16_def(scale2x_uint16* dst0, scale2x_uint16* dst1, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count)\n{\n#ifdef USE_SCALE_RANDOMWRITE\n\tscale2x_16_def_whole(dst0, dst1, src0, src1, src2, count);\n#else\n\tscale2x_16_def_border(dst0, src0, src1, src2, count);\n\tscale2x_16_def_border(dst1, src2, src1, src0, count);\n#endif\n}\n\n/**\n * Scale by a factor of 2 a row of pixels of 32 bits.\n * This function operates like scale2x_8_def() but for 32 bits pixels.\n * \\param src0 Pointer at the first pixel of the previous row.\n * \\param src1 Pointer at the first pixel of the current row.\n * \\param src2 Pointer at the first pixel of the next row.\n * \\param count Length in pixels of the src0, src1 and src2 rows.\n * It must be at least 2.\n * \\param dst0 First destination row, double length in pixels.\n * \\param dst1 Second destination row, double length in pixels.\n */\nvoid scale2x_32_def(scale2x_uint32* dst0, scale2x_uint32* dst1, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count)\n{\n#ifdef USE_SCALE_RANDOMWRITE\n\tscale2x_32_def_whole(dst0, dst1, src0, src1, src2, count);\n#else\n\tscale2x_32_def_border(dst0, src0, src1, src2, count);\n\tscale2x_32_def_border(dst1, src2, src1, src0, count);\n#endif\n}\n\n/**\n * Scale by a factor of 2x3 a row of pixels of 8 bits.\n * \\note Like scale2x_8_def();\n */\nvoid scale2x3_8_def(scale2x_uint8* dst0, scale2x_uint8* dst1, scale2x_uint8* dst2, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count)\n{\n#ifdef USE_SCALE_RANDOMWRITE\n\tscale2x_8_def_whole(dst0, dst2, src0, src1, src2, count);\n\tscale2x_8_def_center(dst1, src0, src1, src2, count);\n#else\n\tscale2x_8_def_border(dst0, src0, src1, src2, count);\n\tscale2x_8_def_center(dst1, src0, src1, src2, count);\n\tscale2x_8_def_border(dst2, src2, src1, src0, count);\n#endif\n}\n\n/**\n * Scale by a factor of 2x3 a row of pixels of 16 bits.\n * \\note Like scale2x_16_def();\n */\nvoid scale2x3_16_def(scale2x_uint16* dst0, scale2x_uint16* dst1, scale2x_uint16* dst2, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count)\n{\n#ifdef USE_SCALE_RANDOMWRITE\n\tscale2x_16_def_whole(dst0, dst2, src0, src1, src2, count);\n\tscale2x_16_def_center(dst1, src0, src1, src2, count);\n#else\n\tscale2x_16_def_border(dst0, src0, src1, src2, count);\n\tscale2x_16_def_center(dst1, src0, src1, src2, count);\n\tscale2x_16_def_border(dst2, src2, src1, src0, count);\n#endif\n}\n\n/**\n * Scale by a factor of 2x3 a row of pixels of 32 bits.\n * \\note Like scale2x_32_def();\n */\nvoid scale2x3_32_def(scale2x_uint32* dst0, scale2x_uint32* dst1, scale2x_uint32* dst2, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count)\n{\n#ifdef USE_SCALE_RANDOMWRITE\n\tscale2x_32_def_whole(dst0, dst2, src0, src1, src2, count);\n\tscale2x_32_def_center(dst1, src0, src1, src2, count);\n#else\n\tscale2x_32_def_border(dst0, src0, src1, src2, count);\n\tscale2x_32_def_center(dst1, src0, src1, src2, count);\n\tscale2x_32_def_border(dst2, src2, src1, src0, count);\n#endif\n}\n\n/**\n * Scale by a factor of 2x4 a row of pixels of 8 bits.\n * \\note Like scale2x_8_def();\n */\nvoid scale2x4_8_def(scale2x_uint8* dst0, scale2x_uint8* dst1, scale2x_uint8* dst2, scale2x_uint8* dst3, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count)\n{\n#ifdef USE_SCALE_RANDOMWRITE\n\tscale2x_8_def_whole(dst0, dst3, src0, src1, src2, count);\n\tscale2x_8_def_center(dst1, src0, src1, src2, count);\n\tscale2x_8_def_center(dst2, src0, src1, src2, count);\n#else\n\tscale2x_8_def_border(dst0, src0, src1, src2, count);\n\tscale2x_8_def_center(dst1, src0, src1, src2, count);\n\tscale2x_8_def_center(dst2, src0, src1, src2, count);\n\tscale2x_8_def_border(dst3, src2, src1, src0, count);\n#endif\n}\n\n/**\n * Scale by a factor of 2x4 a row of pixels of 16 bits.\n * \\note Like scale2x_16_def();\n */\nvoid scale2x4_16_def(scale2x_uint16* dst0, scale2x_uint16* dst1, scale2x_uint16* dst2, scale2x_uint16* dst3, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count)\n{\n#ifdef USE_SCALE_RANDOMWRITE\n\tscale2x_16_def_whole(dst0, dst3, src0, src1, src2, count);\n\tscale2x_16_def_center(dst1, src0, src1, src2, count);\n\tscale2x_16_def_center(dst2, src0, src1, src2, count);\n#else\n\tscale2x_16_def_border(dst0, src0, src1, src2, count);\n\tscale2x_16_def_center(dst1, src0, src1, src2, count);\n\tscale2x_16_def_center(dst2, src0, src1, src2, count);\n\tscale2x_16_def_border(dst3, src2, src1, src0, count);\n#endif\n}\n\n/**\n * Scale by a factor of 2x4 a row of pixels of 32 bits.\n * \\note Like scale2x_32_def();\n */\nvoid scale2x4_32_def(scale2x_uint32* dst0, scale2x_uint32* dst1, scale2x_uint32* dst2, scale2x_uint32* dst3, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count)\n{\n#ifdef USE_SCALE_RANDOMWRITE\n\tscale2x_32_def_whole(dst0, dst3, src0, src1, src2, count);\n\tscale2x_32_def_center(dst1, src0, src1, src2, count);\n\tscale2x_32_def_center(dst2, src0, src1, src2, count);\n#else\n\tscale2x_32_def_border(dst0, src0, src1, src2, count);\n\tscale2x_32_def_center(dst1, src0, src1, src2, count);\n\tscale2x_32_def_center(dst2, src0, src1, src2, count);\n\tscale2x_32_def_border(dst3, src2, src1, src0, count);\n#endif\n}\n\n/***************************************************************************/\n/* Scale2x MMX implementation */\n\n#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))\n\n/*\n * Apply the Scale2x effect at a single row.\n * This function must be called only by the other scale2x functions.\n *\n * Considering the pixel map :\n *\n *      ABC (src0)\n *      DEF (src1)\n *      GHI (src2)\n *\n * this functions compute 2 new pixels in substitution of the source pixel E\n * like this map :\n *\n *      ab (dst)\n *\n * with these variables :\n *\n *      &current -> E\n *      &current_left -> D\n *      &current_right -> F\n *      &current_upper -> B\n *      &current_lower -> H\n *\n *      %0 -> current_upper\n *      %1 -> current\n *      %2 -> current_lower\n *      %3 -> dst\n *      %4 -> counter\n *\n *      %mm0 -> *current_left\n *      %mm1 -> *current_next\n *      %mm2 -> tmp0\n *      %mm3 -> tmp1\n *      %mm4 -> tmp2\n *      %mm5 -> tmp3\n *      %mm6 -> *current_upper\n *      %mm7 -> *current\n */\nstatic inline void scale2x_8_mmx_border(scale2x_uint8* dst, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count)\n{\n\tassert(count >= 16);\n\tassert(count % 8 == 0);\n\n\t/* always do the first and last run */\n\tcount -= 2*8;\n\n\t__asm__ __volatile__(\n/* first run */\n\t\t/* set the current, current_pre, current_next registers */\n\t\t\"movq 0(%1), %%mm0\\n\"\n\t\t\"movq 0(%1), %%mm7\\n\"\n\t\t\"movq 8(%1), %%mm1\\n\"\n\t\t\"psllq $56, %%mm0\\n\"\n\t\t\"psllq $56, %%mm1\\n\"\n\t\t\"psrlq $56, %%mm0\\n\"\n\t\t\"movq %%mm7, %%mm2\\n\"\n\t\t\"movq %%mm7, %%mm3\\n\"\n\t\t\"psllq $8, %%mm2\\n\"\n\t\t\"psrlq $8, %%mm3\\n\"\n\t\t\"por %%mm2, %%mm0\\n\"\n\t\t\"por %%mm3, %%mm1\\n\"\n\n\t\t/* current_upper */\n\t\t\"movq (%0), %%mm6\\n\"\n\n\t\t/* compute the upper-left pixel for dst on %%mm2 */\n\t\t/* compute the upper-right pixel for dst on %%mm4 */\n\t\t\"movq %%mm0, %%mm2\\n\"\n\t\t\"movq %%mm1, %%mm4\\n\"\n\t\t\"movq %%mm0, %%mm3\\n\"\n\t\t\"movq %%mm1, %%mm5\\n\"\n\t\t\"pcmpeqb %%mm6, %%mm2\\n\"\n\t\t\"pcmpeqb %%mm6, %%mm4\\n\"\n\t\t\"pcmpeqb (%2), %%mm3\\n\"\n\t\t\"pcmpeqb (%2), %%mm5\\n\"\n\t\t\"pandn %%mm2, %%mm3\\n\"\n\t\t\"pandn %%mm4, %%mm5\\n\"\n\t\t\"movq %%mm0, %%mm2\\n\"\n\t\t\"movq %%mm1, %%mm4\\n\"\n\t\t\"pcmpeqb %%mm1, %%mm2\\n\"\n\t\t\"pcmpeqb %%mm0, %%mm4\\n\"\n\t\t\"pandn %%mm3, %%mm2\\n\"\n\t\t\"pandn %%mm5, %%mm4\\n\"\n\t\t\"movq %%mm2, %%mm3\\n\"\n\t\t\"movq %%mm4, %%mm5\\n\"\n\t\t\"pand %%mm6, %%mm2\\n\"\n\t\t\"pand %%mm6, %%mm4\\n\"\n\t\t\"pandn %%mm7, %%mm3\\n\"\n\t\t\"pandn %%mm7, %%mm5\\n\"\n\t\t\"por %%mm3, %%mm2\\n\"\n\t\t\"por %%mm5, %%mm4\\n\"\n\n\t\t/* set *dst */\n\t\t\"movq %%mm2, %%mm3\\n\"\n\t\t\"punpcklbw %%mm4, %%mm2\\n\"\n\t\t\"punpckhbw %%mm4, %%mm3\\n\"\n\t\t\"movq %%mm2, (%3)\\n\"\n\t\t\"movq %%mm3, 8(%3)\\n\"\n\n\t\t/* next */\n\t\t\"add $8, %0\\n\"\n\t\t\"add $8, %1\\n\"\n\t\t\"add $8, %2\\n\"\n\t\t\"add $16, %3\\n\"\n\n/* central runs */\n\t\t\"shr $3, %4\\n\"\n\t\t\"jz 1f\\n\"\n\n\t\t\"0:\\n\"\n\n\t\t/* set the current, current_pre, current_next registers */\n\t\t\"movq -8(%1), %%mm0\\n\"\n\t\t\"movq (%1), %%mm7\\n\"\n\t\t\"movq 8(%1), %%mm1\\n\"\n\t\t\"psrlq $56, %%mm0\\n\"\n\t\t\"psllq $56, %%mm1\\n\"\n\t\t\"movq %%mm7, %%mm2\\n\"\n\t\t\"movq %%mm7, %%mm3\\n\"\n\t\t\"psllq $8, %%mm2\\n\"\n\t\t\"psrlq $8, %%mm3\\n\"\n\t\t\"por %%mm2, %%mm0\\n\"\n\t\t\"por %%mm3, %%mm1\\n\"\n\n\t\t/* current_upper */\n\t\t\"movq (%0), %%mm6\\n\"\n\n\t\t/* compute the upper-left pixel for dst on %%mm2 */\n\t\t/* compute the upper-right pixel for dst on %%mm4 */\n\t\t\"movq %%mm0, %%mm2\\n\"\n\t\t\"movq %%mm1, %%mm4\\n\"\n\t\t\"movq %%mm0, %%mm3\\n\"\n\t\t\"movq %%mm1, %%mm5\\n\"\n\t\t\"pcmpeqb %%mm6, %%mm2\\n\"\n\t\t\"pcmpeqb %%mm6, %%mm4\\n\"\n\t\t\"pcmpeqb (%2), %%mm3\\n\"\n\t\t\"pcmpeqb (%2), %%mm5\\n\"\n\t\t\"pandn %%mm2, %%mm3\\n\"\n\t\t\"pandn %%mm4, %%mm5\\n\"\n\t\t\"movq %%mm0, %%mm2\\n\"\n\t\t\"movq %%mm1, %%mm4\\n\"\n\t\t\"pcmpeqb %%mm1, %%mm2\\n\"\n\t\t\"pcmpeqb %%mm0, %%mm4\\n\"\n\t\t\"pandn %%mm3, %%mm2\\n\"\n\t\t\"pandn %%mm5, %%mm4\\n\"\n\t\t\"movq %%mm2, %%mm3\\n\"\n\t\t\"movq %%mm4, %%mm5\\n\"\n\t\t\"pand %%mm6, %%mm2\\n\"\n\t\t\"pand %%mm6, %%mm4\\n\"\n\t\t\"pandn %%mm7, %%mm3\\n\"\n\t\t\"pandn %%mm7, %%mm5\\n\"\n\t\t\"por %%mm3, %%mm2\\n\"\n\t\t\"por %%mm5, %%mm4\\n\"\n\n\t\t/* set *dst */\n\t\t\"movq %%mm2, %%mm3\\n\"\n\t\t\"punpcklbw %%mm4, %%mm2\\n\"\n\t\t\"punpckhbw %%mm4, %%mm3\\n\"\n\t\t\"movq %%mm2, (%3)\\n\"\n\t\t\"movq %%mm3, 8(%3)\\n\"\n\n\t\t/* next */\n\t\t\"add $8, %0\\n\"\n\t\t\"add $8, %1\\n\"\n\t\t\"add $8, %2\\n\"\n\t\t\"add $16, %3\\n\"\n\n\t\t\"dec %4\\n\"\n\t\t\"jnz 0b\\n\"\n\t\t\"1:\\n\"\n\n/* final run */\n\t\t/* set the current, current_pre, current_next registers */\n\t\t\"movq (%1), %%mm1\\n\"\n\t\t\"movq (%1), %%mm7\\n\"\n\t\t\"movq -8(%1), %%mm0\\n\"\n\t\t\"psrlq $56, %%mm1\\n\"\n\t\t\"psrlq $56, %%mm0\\n\"\n\t\t\"psllq $56, %%mm1\\n\"\n\t\t\"movq %%mm7, %%mm2\\n\"\n\t\t\"movq %%mm7, %%mm3\\n\"\n\t\t\"psllq $8, %%mm2\\n\"\n\t\t\"psrlq $8, %%mm3\\n\"\n\t\t\"por %%mm2, %%mm0\\n\"\n\t\t\"por %%mm3, %%mm1\\n\"\n\n\t\t/* current_upper */\n\t\t\"movq (%0), %%mm6\\n\"\n\n\t\t/* compute the upper-left pixel for dst on %%mm2 */\n\t\t/* compute the upper-right pixel for dst on %%mm4 */\n\t\t\"movq %%mm0, %%mm2\\n\"\n\t\t\"movq %%mm1, %%mm4\\n\"\n\t\t\"movq %%mm0, %%mm3\\n\"\n\t\t\"movq %%mm1, %%mm5\\n\"\n\t\t\"pcmpeqb %%mm6, %%mm2\\n\"\n\t\t\"pcmpeqb %%mm6, %%mm4\\n\"\n\t\t\"pcmpeqb (%2), %%mm3\\n\"\n\t\t\"pcmpeqb (%2), %%mm5\\n\"\n\t\t\"pandn %%mm2, %%mm3\\n\"\n\t\t\"pandn %%mm4, %%mm5\\n\"\n\t\t\"movq %%mm0, %%mm2\\n\"\n\t\t\"movq %%mm1, %%mm4\\n\"\n\t\t\"pcmpeqb %%mm1, %%mm2\\n\"\n\t\t\"pcmpeqb %%mm0, %%mm4\\n\"\n\t\t\"pandn %%mm3, %%mm2\\n\"\n\t\t\"pandn %%mm5, %%mm4\\n\"\n\t\t\"movq %%mm2, %%mm3\\n\"\n\t\t\"movq %%mm4, %%mm5\\n\"\n\t\t\"pand %%mm6, %%mm2\\n\"\n\t\t\"pand %%mm6, %%mm4\\n\"\n\t\t\"pandn %%mm7, %%mm3\\n\"\n\t\t\"pandn %%mm7, %%mm5\\n\"\n\t\t\"por %%mm3, %%mm2\\n\"\n\t\t\"por %%mm5, %%mm4\\n\"\n\n\t\t/* set *dst */\n\t\t\"movq %%mm2, %%mm3\\n\"\n\t\t\"punpcklbw %%mm4, %%mm2\\n\"\n\t\t\"punpckhbw %%mm4, %%mm3\\n\"\n\t\t\"movq %%mm2, (%3)\\n\"\n\t\t\"movq %%mm3, 8(%3)\\n\"\n\n\t\t: \"+r\" (src0), \"+r\" (src1), \"+r\" (src2), \"+r\" (dst), \"+r\" (count)\n\t\t:\n\t\t: \"cc\"\n\t);\n}\n\nstatic inline void scale2x_16_mmx_border(scale2x_uint16* dst, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count)\n{\n\tassert(count >= 8);\n\tassert(count % 4 == 0);\n\n\t/* always do the first and last run */\n\tcount -= 2*4;\n\n\t__asm__ __volatile__(\n/* first run */\n\t\t/* set the current, current_pre, current_next registers */\n\t\t\"movq 0(%1), %%mm0\\n\"\n\t\t\"movq 0(%1), %%mm7\\n\"\n\t\t\"movq 8(%1), %%mm1\\n\"\n\t\t\"psllq $48, %%mm0\\n\"\n\t\t\"psllq $48, %%mm1\\n\"\n\t\t\"psrlq $48, %%mm0\\n\"\n\t\t\"movq %%mm7, %%mm2\\n\"\n\t\t\"movq %%mm7, %%mm3\\n\"\n\t\t\"psllq $16, %%mm2\\n\"\n\t\t\"psrlq $16, %%mm3\\n\"\n\t\t\"por %%mm2, %%mm0\\n\"\n\t\t\"por %%mm3, %%mm1\\n\"\n\n\t\t/* current_upper */\n\t\t\"movq (%0), %%mm6\\n\"\n\n\t\t/* compute the upper-left pixel for dst on %%mm2 */\n\t\t/* compute the upper-right pixel for dst on %%mm4 */\n\t\t\"movq %%mm0, %%mm2\\n\"\n\t\t\"movq %%mm1, %%mm4\\n\"\n\t\t\"movq %%mm0, %%mm3\\n\"\n\t\t\"movq %%mm1, %%mm5\\n\"\n\t\t\"pcmpeqw %%mm6, %%mm2\\n\"\n\t\t\"pcmpeqw %%mm6, %%mm4\\n\"\n\t\t\"pcmpeqw (%2), %%mm3\\n\"\n\t\t\"pcmpeqw (%2), %%mm5\\n\"\n\t\t\"pandn %%mm2, %%mm3\\n\"\n\t\t\"pandn %%mm4, %%mm5\\n\"\n\t\t\"movq %%mm0, %%mm2\\n\"\n\t\t\"movq %%mm1, %%mm4\\n\"\n\t\t\"pcmpeqw %%mm1, %%mm2\\n\"\n\t\t\"pcmpeqw %%mm0, %%mm4\\n\"\n\t\t\"pandn %%mm3, %%mm2\\n\"\n\t\t\"pandn %%mm5, %%mm4\\n\"\n\t\t\"movq %%mm2, %%mm3\\n\"\n\t\t\"movq %%mm4, %%mm5\\n\"\n\t\t\"pand %%mm6, %%mm2\\n\"\n\t\t\"pand %%mm6, %%mm4\\n\"\n\t\t\"pandn %%mm7, %%mm3\\n\"\n\t\t\"pandn %%mm7, %%mm5\\n\"\n\t\t\"por %%mm3, %%mm2\\n\"\n\t\t\"por %%mm5, %%mm4\\n\"\n\n\t\t/* set *dst */\n\t\t\"movq %%mm2, %%mm3\\n\"\n\t\t\"punpcklwd %%mm4, %%mm2\\n\"\n\t\t\"punpckhwd %%mm4, %%mm3\\n\"\n\t\t\"movq %%mm2, (%3)\\n\"\n\t\t\"movq %%mm3, 8(%3)\\n\"\n\n\t\t/* next */\n\t\t\"add $8, %0\\n\"\n\t\t\"add $8, %1\\n\"\n\t\t\"add $8, %2\\n\"\n\t\t\"add $16, %3\\n\"\n\n/* central runs */\n\t\t\"shr $2, %4\\n\"\n\t\t\"jz 1f\\n\"\n\n\t\t\"0:\\n\"\n\n\t\t/* set the current, current_pre, current_next registers */\n\t\t\"movq -8(%1), %%mm0\\n\"\n\t\t\"movq (%1), %%mm7\\n\"\n\t\t\"movq 8(%1), %%mm1\\n\"\n\t\t\"psrlq $48, %%mm0\\n\"\n\t\t\"psllq $48, %%mm1\\n\"\n\t\t\"movq %%mm7, %%mm2\\n\"\n\t\t\"movq %%mm7, %%mm3\\n\"\n\t\t\"psllq $16, %%mm2\\n\"\n\t\t\"psrlq $16, %%mm3\\n\"\n\t\t\"por %%mm2, %%mm0\\n\"\n\t\t\"por %%mm3, %%mm1\\n\"\n\n\t\t/* current_upper */\n\t\t\"movq (%0), %%mm6\\n\"\n\n\t\t/* compute the upper-left pixel for dst on %%mm2 */\n\t\t/* compute the upper-right pixel for dst on %%mm4 */\n\t\t\"movq %%mm0, %%mm2\\n\"\n\t\t\"movq %%mm1, %%mm4\\n\"\n\t\t\"movq %%mm0, %%mm3\\n\"\n\t\t\"movq %%mm1, %%mm5\\n\"\n\t\t\"pcmpeqw %%mm6, %%mm2\\n\"\n\t\t\"pcmpeqw %%mm6, %%mm4\\n\"\n\t\t\"pcmpeqw (%2), %%mm3\\n\"\n\t\t\"pcmpeqw (%2), %%mm5\\n\"\n\t\t\"pandn %%mm2, %%mm3\\n\"\n\t\t\"pandn %%mm4, %%mm5\\n\"\n\t\t\"movq %%mm0, %%mm2\\n\"\n\t\t\"movq %%mm1, %%mm4\\n\"\n\t\t\"pcmpeqw %%mm1, %%mm2\\n\"\n\t\t\"pcmpeqw %%mm0, %%mm4\\n\"\n\t\t\"pandn %%mm3, %%mm2\\n\"\n\t\t\"pandn %%mm5, %%mm4\\n\"\n\t\t\"movq %%mm2, %%mm3\\n\"\n\t\t\"movq %%mm4, %%mm5\\n\"\n\t\t\"pand %%mm6, %%mm2\\n\"\n\t\t\"pand %%mm6, %%mm4\\n\"\n\t\t\"pandn %%mm7, %%mm3\\n\"\n\t\t\"pandn %%mm7, %%mm5\\n\"\n\t\t\"por %%mm3, %%mm2\\n\"\n\t\t\"por %%mm5, %%mm4\\n\"\n\n\t\t/* set *dst */\n\t\t\"movq %%mm2, %%mm3\\n\"\n\t\t\"punpcklwd %%mm4, %%mm2\\n\"\n\t\t\"punpckhwd %%mm4, %%mm3\\n\"\n\t\t\"movq %%mm2, (%3)\\n\"\n\t\t\"movq %%mm3, 8(%3)\\n\"\n\n\t\t/* next */\n\t\t\"add $8, %0\\n\"\n\t\t\"add $8, %1\\n\"\n\t\t\"add $8, %2\\n\"\n\t\t\"add $16, %3\\n\"\n\n\t\t\"dec %4\\n\"\n\t\t\"jnz 0b\\n\"\n\t\t\"1:\\n\"\n\n/* final run */\n\t\t/* set the current, current_pre, current_next registers */\n\t\t\"movq (%1), %%mm1\\n\"\n\t\t\"movq (%1), %%mm7\\n\"\n\t\t\"movq -8(%1), %%mm0\\n\"\n\t\t\"psrlq $48, %%mm1\\n\"\n\t\t\"psrlq $48, %%mm0\\n\"\n\t\t\"psllq $48, %%mm1\\n\"\n\t\t\"movq %%mm7, %%mm2\\n\"\n\t\t\"movq %%mm7, %%mm3\\n\"\n\t\t\"psllq $16, %%mm2\\n\"\n\t\t\"psrlq $16, %%mm3\\n\"\n\t\t\"por %%mm2, %%mm0\\n\"\n\t\t\"por %%mm3, %%mm1\\n\"\n\n\t\t/* current_upper */\n\t\t\"movq (%0), %%mm6\\n\"\n\n\t\t/* compute the upper-left pixel for dst on %%mm2 */\n\t\t/* compute the upper-right pixel for dst on %%mm4 */\n\t\t\"movq %%mm0, %%mm2\\n\"\n\t\t\"movq %%mm1, %%mm4\\n\"\n\t\t\"movq %%mm0, %%mm3\\n\"\n\t\t\"movq %%mm1, %%mm5\\n\"\n\t\t\"pcmpeqw %%mm6, %%mm2\\n\"\n\t\t\"pcmpeqw %%mm6, %%mm4\\n\"\n\t\t\"pcmpeqw (%2), %%mm3\\n\"\n\t\t\"pcmpeqw (%2), %%mm5\\n\"\n\t\t\"pandn %%mm2, %%mm3\\n\"\n\t\t\"pandn %%mm4, %%mm5\\n\"\n\t\t\"movq %%mm0, %%mm2\\n\"\n\t\t\"movq %%mm1, %%mm4\\n\"\n\t\t\"pcmpeqw %%mm1, %%mm2\\n\"\n\t\t\"pcmpeqw %%mm0, %%mm4\\n\"\n\t\t\"pandn %%mm3, %%mm2\\n\"\n\t\t\"pandn %%mm5, %%mm4\\n\"\n\t\t\"movq %%mm2, %%mm3\\n\"\n\t\t\"movq %%mm4, %%mm5\\n\"\n\t\t\"pand %%mm6, %%mm2\\n\"\n\t\t\"pand %%mm6, %%mm4\\n\"\n\t\t\"pandn %%mm7, %%mm3\\n\"\n\t\t\"pandn %%mm7, %%mm5\\n\"\n\t\t\"por %%mm3, %%mm2\\n\"\n\t\t\"por %%mm5, %%mm4\\n\"\n\n\t\t/* set *dst */\n\t\t\"movq %%mm2, %%mm3\\n\"\n\t\t\"punpcklwd %%mm4, %%mm2\\n\"\n\t\t\"punpckhwd %%mm4, %%mm3\\n\"\n\t\t\"movq %%mm2, (%3)\\n\"\n\t\t\"movq %%mm3, 8(%3)\\n\"\n\n\t\t: \"+r\" (src0), \"+r\" (src1), \"+r\" (src2), \"+r\" (dst), \"+r\" (count)\n\t\t:\n\t\t: \"cc\"\n\t);\n}\n\nstatic inline void scale2x_32_mmx_border(scale2x_uint32* dst, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count)\n{\n\tassert(count >= 4);\n\tassert(count % 2 == 0);\n\n\t/* always do the first and last run */\n\tcount -= 2*2;\n\n\t__asm__ __volatile__(\n/* first run */\n\t\t/* set the current, current_pre, current_next registers */\n\t\t\"movq 0(%1), %%mm0\\n\"\n\t\t\"movq 0(%1), %%mm7\\n\"\n\t\t\"movq 8(%1), %%mm1\\n\"\n\t\t\"psllq $32, %%mm0\\n\"\n\t\t\"psllq $32, %%mm1\\n\"\n\t\t\"psrlq $32, %%mm0\\n\"\n\t\t\"movq %%mm7, %%mm2\\n\"\n\t\t\"movq %%mm7, %%mm3\\n\"\n\t\t\"psllq $32, %%mm2\\n\"\n\t\t\"psrlq $32, %%mm3\\n\"\n\t\t\"por %%mm2, %%mm0\\n\"\n\t\t\"por %%mm3, %%mm1\\n\"\n\n\t\t/* current_upper */\n\t\t\"movq (%0), %%mm6\\n\"\n\n\t\t/* compute the upper-left pixel for dst on %%mm2 */\n\t\t/* compute the upper-right pixel for dst on %%mm4 */\n\t\t\"movq %%mm0, %%mm2\\n\"\n\t\t\"movq %%mm1, %%mm4\\n\"\n\t\t\"movq %%mm0, %%mm3\\n\"\n\t\t\"movq %%mm1, %%mm5\\n\"\n\t\t\"pcmpeqd %%mm6, %%mm2\\n\"\n\t\t\"pcmpeqd %%mm6, %%mm4\\n\"\n\t\t\"pcmpeqd (%2), %%mm3\\n\"\n\t\t\"pcmpeqd (%2), %%mm5\\n\"\n\t\t\"pandn %%mm2, %%mm3\\n\"\n\t\t\"pandn %%mm4, %%mm5\\n\"\n\t\t\"movq %%mm0, %%mm2\\n\"\n\t\t\"movq %%mm1, %%mm4\\n\"\n\t\t\"pcmpeqd %%mm1, %%mm2\\n\"\n\t\t\"pcmpeqd %%mm0, %%mm4\\n\"\n\t\t\"pandn %%mm3, %%mm2\\n\"\n\t\t\"pandn %%mm5, %%mm4\\n\"\n\t\t\"movq %%mm2, %%mm3\\n\"\n\t\t\"movq %%mm4, %%mm5\\n\"\n\t\t\"pand %%mm6, %%mm2\\n\"\n\t\t\"pand %%mm6, %%mm4\\n\"\n\t\t\"pandn %%mm7, %%mm3\\n\"\n\t\t\"pandn %%mm7, %%mm5\\n\"\n\t\t\"por %%mm3, %%mm2\\n\"\n\t\t\"por %%mm5, %%mm4\\n\"\n\n\t\t/* set *dst */\n\t\t\"movq %%mm2, %%mm3\\n\"\n\t\t\"punpckldq %%mm4, %%mm2\\n\"\n\t\t\"punpckhdq %%mm4, %%mm3\\n\"\n\t\t\"movq %%mm2, (%3)\\n\"\n\t\t\"movq %%mm3, 8(%3)\\n\"\n\n\t\t/* next */\n\t\t\"add $8, %0\\n\"\n\t\t\"add $8, %1\\n\"\n\t\t\"add $8, %2\\n\"\n\t\t\"add $16, %3\\n\"\n\n/* central runs */\n\t\t\"shr $1, %4\\n\"\n\t\t\"jz 1f\\n\"\n\n\t\t\"0:\\n\"\n\n\t\t/* set the current, current_pre, current_next registers */\n\t\t\"movq -8(%1), %%mm0\\n\"\n\t\t\"movq (%1), %%mm7\\n\"\n\t\t\"movq 8(%1), %%mm1\\n\"\n\t\t\"psrlq $32, %%mm0\\n\"\n\t\t\"psllq $32, %%mm1\\n\"\n\t\t\"movq %%mm7, %%mm2\\n\"\n\t\t\"movq %%mm7, %%mm3\\n\"\n\t\t\"psllq $32, %%mm2\\n\"\n\t\t\"psrlq $32, %%mm3\\n\"\n\t\t\"por %%mm2, %%mm0\\n\"\n\t\t\"por %%mm3, %%mm1\\n\"\n\n\t\t/* current_upper */\n\t\t\"movq (%0), %%mm6\\n\"\n\n\t\t/* compute the upper-left pixel for dst on %%mm2 */\n\t\t/* compute the upper-right pixel for dst on %%mm4 */\n\t\t\"movq %%mm0, %%mm2\\n\"\n\t\t\"movq %%mm1, %%mm4\\n\"\n\t\t\"movq %%mm0, %%mm3\\n\"\n\t\t\"movq %%mm1, %%mm5\\n\"\n\t\t\"pcmpeqd %%mm6, %%mm2\\n\"\n\t\t\"pcmpeqd %%mm6, %%mm4\\n\"\n\t\t\"pcmpeqd (%2), %%mm3\\n\"\n\t\t\"pcmpeqd (%2), %%mm5\\n\"\n\t\t\"pandn %%mm2, %%mm3\\n\"\n\t\t\"pandn %%mm4, %%mm5\\n\"\n\t\t\"movq %%mm0, %%mm2\\n\"\n\t\t\"movq %%mm1, %%mm4\\n\"\n\t\t\"pcmpeqd %%mm1, %%mm2\\n\"\n\t\t\"pcmpeqd %%mm0, %%mm4\\n\"\n\t\t\"pandn %%mm3, %%mm2\\n\"\n\t\t\"pandn %%mm5, %%mm4\\n\"\n\t\t\"movq %%mm2, %%mm3\\n\"\n\t\t\"movq %%mm4, %%mm5\\n\"\n\t\t\"pand %%mm6, %%mm2\\n\"\n\t\t\"pand %%mm6, %%mm4\\n\"\n\t\t\"pandn %%mm7, %%mm3\\n\"\n\t\t\"pandn %%mm7, %%mm5\\n\"\n\t\t\"por %%mm3, %%mm2\\n\"\n\t\t\"por %%mm5, %%mm4\\n\"\n\n\t\t/* set *dst */\n\t\t\"movq %%mm2, %%mm3\\n\"\n\t\t\"punpckldq %%mm4, %%mm2\\n\"\n\t\t\"punpckhdq %%mm4, %%mm3\\n\"\n\t\t\"movq %%mm2, (%3)\\n\"\n\t\t\"movq %%mm3, 8(%3)\\n\"\n\n\t\t/* next */\n\t\t\"add $8, %0\\n\"\n\t\t\"add $8, %1\\n\"\n\t\t\"add $8, %2\\n\"\n\t\t\"add $16, %3\\n\"\n\n\t\t\"dec %4\\n\"\n\t\t\"jnz 0b\\n\"\n\t\t\"1:\\n\"\n\n/* final run */\n\t\t/* set the current, current_pre, current_next registers */\n\t\t\"movq (%1), %%mm1\\n\"\n\t\t\"movq (%1), %%mm7\\n\"\n\t\t\"movq -8(%1), %%mm0\\n\"\n\t\t\"psrlq $32, %%mm1\\n\"\n\t\t\"psrlq $32, %%mm0\\n\"\n\t\t\"psllq $32, %%mm1\\n\"\n\t\t\"movq %%mm7, %%mm2\\n\"\n\t\t\"movq %%mm7, %%mm3\\n\"\n\t\t\"psllq $32, %%mm2\\n\"\n\t\t\"psrlq $32, %%mm3\\n\"\n\t\t\"por %%mm2, %%mm0\\n\"\n\t\t\"por %%mm3, %%mm1\\n\"\n\n\t\t/* current_upper */\n\t\t\"movq (%0), %%mm6\\n\"\n\n\t\t/* compute the upper-left pixel for dst on %%mm2 */\n\t\t/* compute the upper-right pixel for dst on %%mm4 */\n\t\t\"movq %%mm0, %%mm2\\n\"\n\t\t\"movq %%mm1, %%mm4\\n\"\n\t\t\"movq %%mm0, %%mm3\\n\"\n\t\t\"movq %%mm1, %%mm5\\n\"\n\t\t\"pcmpeqd %%mm6, %%mm2\\n\"\n\t\t\"pcmpeqd %%mm6, %%mm4\\n\"\n\t\t\"pcmpeqd (%2), %%mm3\\n\"\n\t\t\"pcmpeqd (%2), %%mm5\\n\"\n\t\t\"pandn %%mm2, %%mm3\\n\"\n\t\t\"pandn %%mm4, %%mm5\\n\"\n\t\t\"movq %%mm0, %%mm2\\n\"\n\t\t\"movq %%mm1, %%mm4\\n\"\n\t\t\"pcmpeqd %%mm1, %%mm2\\n\"\n\t\t\"pcmpeqd %%mm0, %%mm4\\n\"\n\t\t\"pandn %%mm3, %%mm2\\n\"\n\t\t\"pandn %%mm5, %%mm4\\n\"\n\t\t\"movq %%mm2, %%mm3\\n\"\n\t\t\"movq %%mm4, %%mm5\\n\"\n\t\t\"pand %%mm6, %%mm2\\n\"\n\t\t\"pand %%mm6, %%mm4\\n\"\n\t\t\"pandn %%mm7, %%mm3\\n\"\n\t\t\"pandn %%mm7, %%mm5\\n\"\n\t\t\"por %%mm3, %%mm2\\n\"\n\t\t\"por %%mm5, %%mm4\\n\"\n\n\t\t/* set *dst */\n\t\t\"movq %%mm2, %%mm3\\n\"\n\t\t\"punpckldq %%mm4, %%mm2\\n\"\n\t\t\"punpckhdq %%mm4, %%mm3\\n\"\n\t\t\"movq %%mm2, (%3)\\n\"\n\t\t\"movq %%mm3, 8(%3)\\n\"\n\n\t\t: \"+r\" (src0), \"+r\" (src1), \"+r\" (src2), \"+r\" (dst), \"+r\" (count)\n\t\t:\n\t\t: \"cc\"\n\t);\n}\n\n/**\n * Scale by a factor of 2 a row of pixels of 8 bits.\n * This is a very fast MMX implementation.\n * The implementation uses a combination of cmp/and/not operations to\n * completely remove the need of conditional jumps. This trick give the\n * major speed improvement.\n * Also, using the 8 bytes MMX registers more than one pixel are computed\n * at the same time.\n * Before calling this function you must ensure that the currenct CPU supports\n * the MMX instruction set. After calling it you must be sure to call the EMMS\n * instruction before any floating-point operation.\n * The pixels over the left and right borders are assumed of the same color of\n * the pixels on the border.\n * Note that the implementation is optimized to write data sequentially to\n * maximize the bandwidth on video memory.\n * \\param src0 Pointer at the first pixel of the previous row.\n * \\param src1 Pointer at the first pixel of the current row.\n * \\param src2 Pointer at the first pixel of the next row.\n * \\param count Length in pixels of the src0, src1 and src2 rows. It must\n * be at least 16 and a multiple of 8.\n * \\param dst0 First destination row, double length in pixels.\n * \\param dst1 Second destination row, double length in pixels.\n */\nvoid scale2x_8_mmx(scale2x_uint8* dst0, scale2x_uint8* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count)\n{\n\tif (count % 8 != 0 || count < 16) {\n\t\tscale2x_8_def(dst0, dst1, src0, src1, src2, count);\n\t} else {\n\t\tscale2x_8_mmx_border(dst0, src0, src1, src2, count);\n\t\tscale2x_8_mmx_border(dst1, src2, src1, src0, count);\n\t}\n}\n\n/**\n * Scale by a factor of 2 a row of pixels of 16 bits.\n * This function operates like scale2x_8_mmx() but for 16 bits pixels.\n * \\param src0 Pointer at the first pixel of the previous row.\n * \\param src1 Pointer at the first pixel of the current row.\n * \\param src2 Pointer at the first pixel of the next row.\n * \\param count Length in pixels of the src0, src1 and src2 rows. It must\n * be at least 8 and a multiple of 4.\n * \\param dst0 First destination row, double length in pixels.\n * \\param dst1 Second destination row, double length in pixels.\n */\nvoid scale2x_16_mmx(scale2x_uint16* dst0, scale2x_uint16* dst1, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count)\n{\n\tif (count % 4 != 0 || count < 8) {\n\t\tscale2x_16_def(dst0, dst1, src0, src1, src2, count);\n\t} else {\n\t\tscale2x_16_mmx_border(dst0, src0, src1, src2, count);\n\t\tscale2x_16_mmx_border(dst1, src2, src1, src0, count);\n\t}\n}\n\n/**\n * Scale by a factor of 2 a row of pixels of 32 bits.\n * This function operates like scale2x_8_mmx() but for 32 bits pixels.\n * \\param src0 Pointer at the first pixel of the previous row.\n * \\param src1 Pointer at the first pixel of the current row.\n * \\param src2 Pointer at the first pixel of the next row.\n * \\param count Length in pixels of the src0, src1 and src2 rows. It must\n * be at least 4 and a multiple of 2.\n * \\param dst0 First destination row, double length in pixels.\n * \\param dst1 Second destination row, double length in pixels.\n */\nvoid scale2x_32_mmx(scale2x_uint32* dst0, scale2x_uint32* dst1, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count)\n{\n\tif (count % 2 != 0 || count < 4) {\n\t\tscale2x_32_def(dst0, dst1, src0, src1, src2, count);\n\t} else {\n\t\tscale2x_32_mmx_border(dst0, src0, src1, src2, count);\n\t\tscale2x_32_mmx_border(dst1, src2, src1, src0, count);\n\t}\n}\n\n/**\n * Scale by a factor of 2x3 a row of pixels of 8 bits.\n * This function operates like scale2x_8_mmx() but with an expansion\n * factor of 2x3 instead of 2x2.\n */\nvoid scale2x3_8_mmx(scale2x_uint8* dst0, scale2x_uint8* dst1, scale2x_uint8* dst2, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count)\n{\n\tif (count % 8 != 0 || count < 16) {\n\t\tscale2x3_8_def(dst0, dst1, dst2, src0, src1, src2, count);\n\t} else {\n\t\tscale2x_8_mmx_border(dst0, src0, src1, src2, count);\n\t\tscale2x_8_def_center(dst1, src0, src1, src2, count);\n\t\tscale2x_8_mmx_border(dst2, src2, src1, src0, count);\n\t}\n}\n\n/**\n * Scale by a factor of 2x3 a row of pixels of 16 bits.\n * This function operates like scale2x_16_mmx() but with an expansion\n * factor of 2x3 instead of 2x2.\n */\nvoid scale2x3_16_mmx(scale2x_uint16* dst0, scale2x_uint16* dst1, scale2x_uint16* dst2, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count)\n{\n\tif (count % 4 != 0 || count < 8) {\n\t\tscale2x3_16_def(dst0, dst1, dst2, src0, src1, src2, count);\n\t} else {\n\t\tscale2x_16_mmx_border(dst0, src0, src1, src2, count);\n\t\tscale2x_16_def_center(dst1, src0, src1, src2, count);\n\t\tscale2x_16_mmx_border(dst2, src2, src1, src0, count);\n\t}\n}\n\n/**\n * Scale by a factor of 2x3 a row of pixels of 32 bits.\n * This function operates like scale2x_32_mmx() but with an expansion\n * factor of 2x3 instead of 2x2.\n */\nvoid scale2x3_32_mmx(scale2x_uint32* dst0, scale2x_uint32* dst1, scale2x_uint32* dst2, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count)\n{\n\tif (count % 2 != 0 || count < 4) {\n\t\tscale2x3_32_def(dst0, dst1, dst2, src0, src1, src2, count);\n\t} else {\n\t\tscale2x_32_mmx_border(dst0, src0, src1, src2, count);\n\t\tscale2x_32_def_center(dst1, src0, src1, src2, count);\n\t\tscale2x_32_mmx_border(dst2, src2, src1, src0, count);\n\t}\n}\n\n/**\n * Scale by a factor of 2x4 a row of pixels of 8 bits.\n * This function operates like scale2x_8_mmx() but with an expansion\n * factor of 2x4 instead of 2x2.\n */\nvoid scale2x4_8_mmx(scale2x_uint8* dst0, scale2x_uint8* dst1, scale2x_uint8* dst2, scale2x_uint8* dst3, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count)\n{\n\tif (count % 8 != 0 || count < 16) {\n\t\tscale2x4_8_def(dst0, dst1, dst2, dst3, src0, src1, src2, count);\n\t} else {\n\t\tscale2x_8_mmx_border(dst0, src0, src1, src2, count);\n\t\tscale2x_8_def_center(dst1, src0, src1, src2, count);\n\t\tscale2x_8_def_center(dst2, src0, src1, src2, count);\n\t\tscale2x_8_mmx_border(dst3, src2, src1, src0, count);\n\t}\n}\n\n/**\n * Scale by a factor of 2x4 a row of pixels of 16 bits.\n * This function operates like scale2x_16_mmx() but with an expansion\n * factor of 2x4 instead of 2x2.\n */\nvoid scale2x4_16_mmx(scale2x_uint16* dst0, scale2x_uint16* dst1, scale2x_uint16* dst2, scale2x_uint16* dst3, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count)\n{\n\tif (count % 4 != 0 || count < 8) {\n\t\tscale2x4_16_def(dst0, dst1, dst2, dst3, src0, src1, src2, count);\n\t} else {\n\t\tscale2x_16_mmx_border(dst0, src0, src1, src2, count);\n\t\tscale2x_16_def_center(dst1, src0, src1, src2, count);\n\t\tscale2x_16_def_center(dst2, src0, src1, src2, count);\n\t\tscale2x_16_mmx_border(dst3, src2, src1, src0, count);\n\t}\n}\n\n/**\n * Scale by a factor of 2x4 a row of pixels of 32 bits.\n * This function operates like scale2x_32_mmx() but with an expansion\n * factor of 2x4 instead of 2x2.\n */\nvoid scale2x4_32_mmx(scale2x_uint32* dst0, scale2x_uint32* dst1, scale2x_uint32* dst2, scale2x_uint32* dst3, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count)\n{\n\tif (count % 2 != 0 || count < 4) {\n\t\tscale2x4_32_def(dst0, dst1, dst2, dst3, src0, src1, src2, count);\n\t} else {\n\t\tscale2x_32_mmx_border(dst0, src0, src1, src2, count);\n\t\tscale2x_32_def_center(dst1, src0, src1, src2, count);\n\t\tscale2x_32_def_center(dst2, src0, src1, src2, count);\n\t\tscale2x_32_mmx_border(dst3, src2, src1, src0, count);\n\t}\n}\n\n#endif\n\n"
  },
  {
    "path": "src/Engine/Scalers/scale2x.h",
    "content": "/*\n * This file is part of the Scale2x project.\n *\n * Copyright (C) 2001, 2002, 2003, 2004 Andrea Mazzoleni\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n */\n\n#ifndef __SCALE2X_H\n#define __SCALE2X_H\n\ntypedef unsigned char scale2x_uint8;\ntypedef unsigned short scale2x_uint16;\ntypedef unsigned scale2x_uint32;\n\nvoid scale2x_8_def(scale2x_uint8* dst0, scale2x_uint8* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count);\nvoid scale2x_16_def(scale2x_uint16* dst0, scale2x_uint16* dst1, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count);\nvoid scale2x_32_def(scale2x_uint32* dst0, scale2x_uint32* dst1, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count);\n\nvoid scale2x3_8_def(scale2x_uint8* dst0, scale2x_uint8* dst1, scale2x_uint8* dst2, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count);\nvoid scale2x3_16_def(scale2x_uint16* dst0, scale2x_uint16* dst1, scale2x_uint16* dst2, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count);\nvoid scale2x3_32_def(scale2x_uint32* dst0, scale2x_uint32* dst1, scale2x_uint32* dst2, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count);\n\nvoid scale2x4_8_def(scale2x_uint8* dst0, scale2x_uint8* dst1, scale2x_uint8* dst2, scale2x_uint8* dst3, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count);\nvoid scale2x4_16_def(scale2x_uint16* dst0, scale2x_uint16* dst1, scale2x_uint16* dst2, scale2x_uint16* dst3, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count);\nvoid scale2x4_32_def(scale2x_uint32* dst0, scale2x_uint32* dst1, scale2x_uint32* dst2, scale2x_uint32* dst3, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count);\n\n#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))\n\nvoid scale2x_8_mmx(scale2x_uint8* dst0, scale2x_uint8* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count);\nvoid scale2x_16_mmx(scale2x_uint16* dst0, scale2x_uint16* dst1, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count);\nvoid scale2x_32_mmx(scale2x_uint32* dst0, scale2x_uint32* dst1, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count);\n\nvoid scale2x3_8_mmx(scale2x_uint8* dst0, scale2x_uint8* dst1, scale2x_uint8* dst2, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count);\nvoid scale2x3_16_mmx(scale2x_uint16* dst0, scale2x_uint16* dst1, scale2x_uint16* dst2, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count);\nvoid scale2x3_32_mmx(scale2x_uint32* dst0, scale2x_uint32* dst1, scale2x_uint32* dst2, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count);\n\nvoid scale2x4_8_mmx(scale2x_uint8* dst0, scale2x_uint8* dst1, scale2x_uint8* dst2, scale2x_uint8* dst3, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count);\nvoid scale2x4_16_mmx(scale2x_uint16* dst0, scale2x_uint16* dst1, scale2x_uint16* dst2, scale2x_uint16* dst3, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count);\nvoid scale2x4_32_mmx(scale2x_uint32* dst0, scale2x_uint32* dst1, scale2x_uint32* dst2, scale2x_uint32* dst3, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count);\n\n/**\n * End the use of the MMX instructions.\n * This function must be called before using any floating-point operations.\n */\nstatic inline void scale2x_mmx_emms(void)\n{\n\t__asm__ __volatile__ (\n\t\t\"emms\"\n\t);\n}\n\n#endif\n\n#endif\n\n"
  },
  {
    "path": "src/Engine/Scalers/scale3x.cpp",
    "content": "/*\n * This file is part of the Scale2x project.\n *\n * Copyright (C) 2001, 2002, 2003, 2004 Andrea Mazzoleni\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n */\n\n/*\n * This file contains a C and MMX implementation of the Scale2x effect.\n *\n * You can find an high level description of the effect at :\n *\n * http://scale2x.sourceforge.net/\n */\n\n#if HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include \"scale3x.h\"\n\n#include <assert.h>\n\n#if (_MSC_VER >= 1400)\n#define restrict __restrict\n#else\n#define restrict\n#endif\n\n#ifdef _WIN32\n#ifndef __GNUC__\n#pragma optimize(\"a\", on)\n#endif\n#endif\n\n\n/***************************************************************************/\n/* Scale3x C implementation */\n\n/**\n * Define the macro USE_SCALE_RANDOMWRITE to enable\n * an optimized version which writes memory in random order.\n * This version is a little faster if you write in system memory.\n * But it's a lot slower if you write in video memory.\n * So, enable it only if you are sure to never write directly in video memory.\n */\n/* #define USE_SCALE_RANDOMWRITE */\n\nstatic inline void scale3x_8_def_border(scale3x_uint8* restrict dst, const scale3x_uint8* restrict src0, const scale3x_uint8* restrict src1, const scale3x_uint8* restrict src2, unsigned count)\n{\n\tassert(count >= 2);\n\n\t/* first pixel */\n\tif (src0[0] != src2[0] && src1[0] != src1[1]) {\n\t\tdst[0] = src1[0];\n\t\tdst[1] = (src1[0] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[0]) ? src0[0] : src1[0];\n\t\tdst[2] = src1[1] == src0[0] ? src1[1] : src1[0];\n\t} else {\n\t\tdst[0] = src1[0];\n\t\tdst[1] = src1[0];\n\t\tdst[2] = src1[0];\n\t}\n\t++src0;\n\t++src1;\n\t++src2;\n\tdst += 3;\n\n\t/* central pixels */\n\tcount -= 2;\n\twhile (count) {\n\t\tif (src0[0] != src2[0] && src1[-1] != src1[1]) {\n\t\t\tdst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];\n\t\t\tdst[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];\n\t\t\tdst[2] = src1[1] == src0[0] ? src1[1] : src1[0];\n\t\t} else {\n\t\t\tdst[0] = src1[0];\n\t\t\tdst[1] = src1[0];\n\t\t\tdst[2] = src1[0];\n\t\t}\n\n\t\t++src0;\n\t\t++src1;\n\t\t++src2;\n\t\tdst += 3;\n\t\t--count;\n\t}\n\n\t/* last pixel */\n\tif (src0[0] != src2[0] && src1[-1] != src1[0]) {\n\t\tdst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];\n\t\tdst[1] = (src1[-1] == src0[0] && src1[0] != src0[0]) || (src1[0] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];\n\t\tdst[2] = src1[0];\n\t} else {\n\t\tdst[0] = src1[0];\n\t\tdst[1] = src1[0];\n\t\tdst[2] = src1[0];\n\t}\n}\n\nstatic inline void scale3x_8_def_center(scale3x_uint8* restrict dst, const scale3x_uint8* restrict src0, const scale3x_uint8* restrict src1, const scale3x_uint8* restrict src2, unsigned count)\n{\n\tassert(count >= 2);\n\n\t/* first pixel */\n\tif (src0[0] != src2[0] && src1[0] != src1[1]) {\n\t\tdst[0] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0];\n\t\tdst[1] = src1[0];\n\t\tdst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];\n\t} else {\n\t\tdst[0] = src1[0];\n\t\tdst[1] = src1[0];\n\t\tdst[2] = src1[0];\n\t}\n\t++src0;\n\t++src1;\n\t++src2;\n\tdst += 3;\n\n\t/* central pixels */\n\tcount -= 2;\n\twhile (count) {\n\t\tif (src0[0] != src2[0] && src1[-1] != src1[1]) {\n\t\t\tdst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];\n\t\t\tdst[1] = src1[0];\n\t\t\tdst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];\n\t\t} else {\n\t\t\tdst[0] = src1[0];\n\t\t\tdst[1] = src1[0];\n\t\t\tdst[2] = src1[0];\n\t\t}\n\n\t\t++src0;\n\t\t++src1;\n\t\t++src2;\n\t\tdst += 3;\n\t\t--count;\n\t}\n\n\t/* last pixel */\n\tif (src0[0] != src2[0] && src1[-1] != src1[0]) {\n\t\tdst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];\n\t\tdst[1] = src1[0];\n\t\tdst[2] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0];\n\t} else {\n\t\tdst[0] = src1[0];\n\t\tdst[1] = src1[0];\n\t\tdst[2] = src1[0];\n\t}\n}\n\nstatic inline void scale3x_16_def_border(scale3x_uint16* restrict dst, const scale3x_uint16* restrict src0, const scale3x_uint16* restrict src1, const scale3x_uint16* restrict src2, unsigned count)\n{\n\tassert(count >= 2);\n\n\t/* first pixel */\n\tif (src0[0] != src2[0] && src1[0] != src1[1]) {\n\t\tdst[0] = src1[0];\n\t\tdst[1] = (src1[0] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[0]) ? src0[0] : src1[0];\n\t\tdst[2] = src1[1] == src0[0] ? src1[1] : src1[0];\n\t} else {\n\t\tdst[0] = src1[0];\n\t\tdst[1] = src1[0];\n\t\tdst[2] = src1[0];\n\t}\n\t++src0;\n\t++src1;\n\t++src2;\n\tdst += 3;\n\n\t/* central pixels */\n\tcount -= 2;\n\twhile (count) {\n\t\tif (src0[0] != src2[0] && src1[-1] != src1[1]) {\n\t\t\tdst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];\n\t\t\tdst[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];\n\t\t\tdst[2] = src1[1] == src0[0] ? src1[1] : src1[0];\n\t\t} else {\n\t\t\tdst[0] = src1[0];\n\t\t\tdst[1] = src1[0];\n\t\t\tdst[2] = src1[0];\n\t\t}\n\n\t\t++src0;\n\t\t++src1;\n\t\t++src2;\n\t\tdst += 3;\n\t\t--count;\n\t}\n\n\t/* last pixel */\n\tif (src0[0] != src2[0] && src1[-1] != src1[0]) {\n\t\tdst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];\n\t\tdst[1] = (src1[-1] == src0[0] && src1[0] != src0[0]) || (src1[0] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];\n\t\tdst[2] = src1[0];\n\t} else {\n\t\tdst[0] = src1[0];\n\t\tdst[1] = src1[0];\n\t\tdst[2] = src1[0];\n\t}\n}\n\nstatic inline void scale3x_16_def_center(scale3x_uint16* restrict dst, const scale3x_uint16* restrict src0, const scale3x_uint16* restrict src1, const scale3x_uint16* restrict src2, unsigned count)\n{\n\tassert(count >= 2);\n\n\t/* first pixel */\n\tif (src0[0] != src2[0] && src1[0] != src1[1]) {\n\t\tdst[0] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0];\n\t\tdst[1] = src1[0];\n\t\tdst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];\n\t} else {\n\t\tdst[0] = src1[0];\n\t\tdst[1] = src1[0];\n\t\tdst[2] = src1[0];\n\t}\n\t++src0;\n\t++src1;\n\t++src2;\n\tdst += 3;\n\n\t/* central pixels */\n\tcount -= 2;\n\twhile (count) {\n\t\tif (src0[0] != src2[0] && src1[-1] != src1[1]) {\n\t\t\tdst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];\n\t\t\tdst[1] = src1[0];\n\t\t\tdst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];\n\t\t} else {\n\t\t\tdst[0] = src1[0];\n\t\t\tdst[1] = src1[0];\n\t\t\tdst[2] = src1[0];\n\t\t}\n\n\t\t++src0;\n\t\t++src1;\n\t\t++src2;\n\t\tdst += 3;\n\t\t--count;\n\t}\n\n\t/* last pixel */\n\tif (src0[0] != src2[0] && src1[-1] != src1[0]) {\n\t\tdst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];\n\t\tdst[1] = src1[0];\n\t\tdst[2] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0];\n\t} else {\n\t\tdst[0] = src1[0];\n\t\tdst[1] = src1[0];\n\t\tdst[2] = src1[0];\n\t}\n}\n\nstatic inline void scale3x_32_def_border(scale3x_uint32* restrict dst, const scale3x_uint32* restrict src0, const scale3x_uint32* restrict src1, const scale3x_uint32* restrict src2, unsigned count)\n{\n\tassert(count >= 2);\n\n\t/* first pixel */\n\tif (src0[0] != src2[0] && src1[0] != src1[1]) {\n\t\tdst[0] = src1[0];\n\t\tdst[1] = (src1[0] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[0]) ? src0[0] : src1[0];\n\t\tdst[2] = src1[1] == src0[0] ? src1[1] : src1[0];\n\t} else {\n\t\tdst[0] = src1[0];\n\t\tdst[1] = src1[0];\n\t\tdst[2] = src1[0];\n\t}\n\t++src0;\n\t++src1;\n\t++src2;\n\tdst += 3;\n\n\t/* central pixels */\n\tcount -= 2;\n\twhile (count) {\n\t\tif (src0[0] != src2[0] && src1[-1] != src1[1]) {\n\t\t\tdst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];\n\t\t\tdst[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];\n\t\t\tdst[2] = src1[1] == src0[0] ? src1[1] : src1[0];\n\t\t} else {\n\t\t\tdst[0] = src1[0];\n\t\t\tdst[1] = src1[0];\n\t\t\tdst[2] = src1[0];\n\t\t}\n\n\t\t++src0;\n\t\t++src1;\n\t\t++src2;\n\t\tdst += 3;\n\t\t--count;\n\t}\n\n\t/* last pixel */\n\tif (src0[0] != src2[0] && src1[-1] != src1[0]) {\n\t\tdst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];\n\t\tdst[1] = (src1[-1] == src0[0] && src1[0] != src0[0]) || (src1[0] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];\n\t\tdst[2] = src1[0];\n\t} else {\n\t\tdst[0] = src1[0];\n\t\tdst[1] = src1[0];\n\t\tdst[2] = src1[0];\n\t}\n}\n\nstatic inline void scale3x_32_def_center(scale3x_uint32* restrict dst, const scale3x_uint32* restrict src0, const scale3x_uint32* restrict src1, const scale3x_uint32* restrict src2, unsigned count)\n{\n\tassert(count >= 2);\n\n\t/* first pixel */\n\tif (src0[0] != src2[0] && src1[0] != src1[1]) {\n\t\tdst[0] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0];\n\t\tdst[1] = src1[0];\n\t\tdst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];\n\t} else {\n\t\tdst[0] = src1[0];\n\t\tdst[1] = src1[0];\n\t\tdst[2] = src1[0];\n\t}\n\t++src0;\n\t++src1;\n\t++src2;\n\tdst += 3;\n\n\t/* central pixels */\n\tcount -= 2;\n\twhile (count) {\n\t\tif (src0[0] != src2[0] && src1[-1] != src1[1]) {\n\t\t\tdst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];\n\t\t\tdst[1] = src1[0];\n\t\t\tdst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];\n\t\t} else {\n\t\t\tdst[0] = src1[0];\n\t\t\tdst[1] = src1[0];\n\t\t\tdst[2] = src1[0];\n\t\t}\n\n\t\t++src0;\n\t\t++src1;\n\t\t++src2;\n\t\tdst += 3;\n\t\t--count;\n\t}\n\n\t/* last pixel */\n\tif (src0[0] != src2[0] && src1[-1] != src1[0]) {\n\t\tdst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];\n\t\tdst[1] = src1[0];\n\t\tdst[2] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0];\n\t} else {\n\t\tdst[0] = src1[0];\n\t\tdst[1] = src1[0];\n\t\tdst[2] = src1[0];\n\t}\n}\n\n/**\n * Scale by a factor of 3 a row of pixels of 8 bits.\n * The function is implemented in C.\n * The pixels over the left and right borders are assumed of the same color of\n * the pixels on the border.\n * \\param src0 Pointer at the first pixel of the previous row.\n * \\param src1 Pointer at the first pixel of the current row.\n * \\param src2 Pointer at the first pixel of the next row.\n * \\param count Length in pixels of the src0, src1 and src2 rows.\n * It must be at least 2.\n * \\param dst0 First destination row, triple length in pixels.\n * \\param dst1 Second destination row, triple length in pixels.\n * \\param dst2 Third destination row, triple length in pixels.\n */\nvoid scale3x_8_def(scale3x_uint8* dst0, scale3x_uint8* dst1, scale3x_uint8* dst2, const scale3x_uint8* src0, const scale3x_uint8* src1, const scale3x_uint8* src2, unsigned count)\n{\n#ifdef USE_SCALE_RANDOMWRITE\n\tscale3x_8_def_whole(dst0, dst1, dst2, src0, src1, src2, count);\n#else\n\tscale3x_8_def_border(dst0, src0, src1, src2, count);\n\tscale3x_8_def_center(dst1, src0, src1, src2, count);\n\tscale3x_8_def_border(dst2, src2, src1, src0, count);\n#endif\n}\n\n/**\n * Scale by a factor of 3 a row of pixels of 16 bits.\n * This function operates like scale3x_8_def() but for 16 bits pixels.\n * \\param src0 Pointer at the first pixel of the previous row.\n * \\param src1 Pointer at the first pixel of the current row.\n * \\param src2 Pointer at the first pixel of the next row.\n * \\param count Length in pixels of the src0, src1 and src2 rows.\n * It must be at least 2.\n * \\param dst0 First destination row, triple length in pixels.\n * \\param dst1 Second destination row, triple length in pixels.\n * \\param dst2 Third destination row, triple length in pixels.\n */\nvoid scale3x_16_def(scale3x_uint16* dst0, scale3x_uint16* dst1, scale3x_uint16* dst2, const scale3x_uint16* src0, const scale3x_uint16* src1, const scale3x_uint16* src2, unsigned count)\n{\n#ifdef USE_SCALE_RANDOMWRITE\n\tscale3x_16_def_whole(dst0, dst1, dst2, src0, src1, src2, count);\n#else\n\tscale3x_16_def_border(dst0, src0, src1, src2, count);\n\tscale3x_16_def_center(dst1, src0, src1, src2, count);\n\tscale3x_16_def_border(dst2, src2, src1, src0, count);\n#endif\n}\n\n/**\n * Scale by a factor of 3 a row of pixels of 32 bits.\n * This function operates like scale3x_8_def() but for 32 bits pixels.\n * \\param src0 Pointer at the first pixel of the previous row.\n * \\param src1 Pointer at the first pixel of the current row.\n * \\param src2 Pointer at the first pixel of the next row.\n * \\param count Length in pixels of the src0, src1 and src2 rows.\n * It must be at least 2.\n * \\param dst0 First destination row, triple length in pixels.\n * \\param dst1 Second destination row, triple length in pixels.\n * \\param dst2 Third destination row, triple length in pixels.\n */\nvoid scale3x_32_def(scale3x_uint32* dst0, scale3x_uint32* dst1, scale3x_uint32* dst2, const scale3x_uint32* src0, const scale3x_uint32* src1, const scale3x_uint32* src2, unsigned count)\n{\n#ifdef USE_SCALE_RANDOMWRITE\n\tscale3x_32_def_whole(dst0, dst1, dst2, src0, src1, src2, count);\n#else\n\tscale3x_32_def_border(dst0, src0, src1, src2, count);\n\tscale3x_32_def_center(dst1, src0, src1, src2, count);\n\tscale3x_32_def_border(dst2, src2, src1, src0, count);\n#endif\n}\n\n"
  },
  {
    "path": "src/Engine/Scalers/scale3x.h",
    "content": "/*\n * This file is part of the Scale2x project.\n *\n * Copyright (C) 2001, 2002, 2003, 2004 Andrea Mazzoleni\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n */\n\n#ifndef __SCALE3X_H\n#define __SCALE3X_H\n\ntypedef unsigned char scale3x_uint8;\ntypedef unsigned short scale3x_uint16;\ntypedef unsigned scale3x_uint32;\n\nvoid scale3x_8_def(scale3x_uint8* dst0, scale3x_uint8* dst1, scale3x_uint8* dst2, const scale3x_uint8* src0, const scale3x_uint8* src1, const scale3x_uint8* src2, unsigned count);\nvoid scale3x_16_def(scale3x_uint16* dst0, scale3x_uint16* dst1, scale3x_uint16* dst2, const scale3x_uint16* src0, const scale3x_uint16* src1, const scale3x_uint16* src2, unsigned count);\nvoid scale3x_32_def(scale3x_uint32* dst0, scale3x_uint32* dst1, scale3x_uint32* dst2, const scale3x_uint32* src0, const scale3x_uint32* src1, const scale3x_uint32* src2, unsigned count);\n\n#endif\n\n"
  },
  {
    "path": "src/Engine/Scalers/scalebit.cpp",
    "content": "/*\n * This file is part of the Scale2x project.\n *\n * Copyright (C) 2003, 2004 Andrea Mazzoleni\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n */\n\n/*\n * This file contains an example implementation of the Scale effect\n * applied to a generic bitmap.\n *\n * You can find an high level description of the effect at :\n *\n * http://scale2x.sourceforge.net/\n */\n\n#if HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include \"scale2x.h\"\n#include \"scale3x.h\"\n\n#if HAVE_ALLOCA_H\n#include <alloca.h>\n#endif\n\n#include <assert.h>\n#include <stdlib.h>\n\n#define SSDST(bits, num) (scale2x_uint##bits *)dst##num\n#define SSSRC(bits, num) (const scale2x_uint##bits *)src##num\n\n/**\n * Apply the Scale2x effect on a group of rows. Used internally.\n */\nstatic inline void stage_scale2x(void* dst0, void* dst1, const void* src0, const void* src1, const void* src2, unsigned pixel, unsigned pixel_per_row)\n{\n\tswitch (pixel) {\n#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))\n\t\tcase 1 : scale2x_8_mmx(SSDST(8,0), SSDST(8,1), SSSRC(8,0), SSSRC(8,1), SSSRC(8,2), pixel_per_row); break;\n\t\tcase 2 : scale2x_16_mmx(SSDST(16,0), SSDST(16,1), SSSRC(16,0), SSSRC(16,1), SSSRC(16,2), pixel_per_row); break;\n\t\tcase 4 : scale2x_32_mmx(SSDST(32,0), SSDST(32,1), SSSRC(32,0), SSSRC(32,1), SSSRC(32,2), pixel_per_row); break;\n#else\n\t\tcase 1 : scale2x_8_def(SSDST(8,0), SSDST(8,1), SSSRC(8,0), SSSRC(8,1), SSSRC(8,2), pixel_per_row); break;\n\t\tcase 2 : scale2x_16_def(SSDST(16,0), SSDST(16,1), SSSRC(16,0), SSSRC(16,1), SSSRC(16,2), pixel_per_row); break;\n\t\tcase 4 : scale2x_32_def(SSDST(32,0), SSDST(32,1), SSSRC(32,0), SSSRC(32,1), SSSRC(32,2), pixel_per_row); break;\n#endif\n\t}\n}\n\n/**\n * Apply the Scale2x3 effect on a group of rows. Used internally.\n */\nstatic inline void stage_scale2x3(void* dst0, void* dst1, void* dst2, const void* src0, const void* src1, const void* src2, unsigned pixel, unsigned pixel_per_row)\n{\n\tswitch (pixel) {\n#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))\n\t\tcase 1 : scale2x3_8_mmx(SSDST(8,0), SSDST(8,1), SSDST(8,2), SSSRC(8,0), SSSRC(8,1), SSSRC(8,2), pixel_per_row); break;\n\t\tcase 2 : scale2x3_16_mmx(SSDST(16,0), SSDST(16,1), SSDST(16,2), SSSRC(16,0), SSSRC(16,1), SSSRC(16,2), pixel_per_row); break;\n\t\tcase 4 : scale2x3_32_mmx(SSDST(32,0), SSDST(32,1), SSDST(32,2), SSSRC(32,0), SSSRC(32,1), SSSRC(32,2), pixel_per_row); break;\n#else\n\t\tcase 1 : scale2x3_8_def(SSDST(8,0), SSDST(8,1), SSDST(8,2), SSSRC(8,0), SSSRC(8,1), SSSRC(8,2), pixel_per_row); break;\n\t\tcase 2 : scale2x3_16_def(SSDST(16,0), SSDST(16,1), SSDST(16,2), SSSRC(16,0), SSSRC(16,1), SSSRC(16,2), pixel_per_row); break;\n\t\tcase 4 : scale2x3_32_def(SSDST(32,0), SSDST(32,1), SSDST(32,2), SSSRC(32,0), SSSRC(32,1), SSSRC(32,2), pixel_per_row); break;\n#endif\n\t}\n}\n\n/**\n * Apply the Scale2x4 effect on a group of rows. Used internally.\n */\nstatic inline void stage_scale2x4(void* dst0, void* dst1, void* dst2, void* dst3, const void* src0, const void* src1, const void* src2, unsigned pixel, unsigned pixel_per_row)\n{\n\tswitch (pixel) {\n#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))\n\t\tcase 1 : scale2x4_8_mmx(SSDST(8,0), SSDST(8,1), SSDST(8,2), SSDST(8,3), SSSRC(8,0), SSSRC(8,1), SSSRC(8,2), pixel_per_row); break;\n\t\tcase 2 : scale2x4_16_mmx(SSDST(16,0), SSDST(16,1), SSDST(16,2), SSDST(16,3), SSSRC(16,0), SSSRC(16,1), SSSRC(16,2), pixel_per_row); break;\n\t\tcase 4 : scale2x4_32_mmx(SSDST(32,0), SSDST(32,1), SSDST(32,2), SSDST(32,3), SSSRC(32,0), SSSRC(32,1), SSSRC(32,2), pixel_per_row); break;\n#else\n\t\tcase 1 : scale2x4_8_def(SSDST(8,0), SSDST(8,1), SSDST(8,2), SSDST(8,3), SSSRC(8,0), SSSRC(8,1), SSSRC(8,2), pixel_per_row); break;\n\t\tcase 2 : scale2x4_16_def(SSDST(16,0), SSDST(16,1), SSDST(16,2), SSDST(16,3), SSSRC(16,0), SSSRC(16,1), SSSRC(16,2), pixel_per_row); break;\n\t\tcase 4 : scale2x4_32_def(SSDST(32,0), SSDST(32,1), SSDST(32,2), SSDST(32,3), SSSRC(32,0), SSSRC(32,1), SSSRC(32,2), pixel_per_row); break;\n#endif\n\t}\n}\n\n/**\n * Apply the Scale3x effect on a group of rows. Used internally.\n */\nstatic inline void stage_scale3x(void* dst0, void* dst1, void* dst2, const void* src0, const void* src1, const void* src2, unsigned pixel, unsigned pixel_per_row)\n{\n\tswitch (pixel) {\n\t\tcase 1 : scale3x_8_def(SSDST(8,0), SSDST(8,1), SSDST(8,2), SSSRC(8,0), SSSRC(8,1), SSSRC(8,2), pixel_per_row); break;\n\t\tcase 2 : scale3x_16_def(SSDST(16,0), SSDST(16,1), SSDST(16,2), SSSRC(16,0), SSSRC(16,1), SSSRC(16,2), pixel_per_row); break;\n\t\tcase 4 : scale3x_32_def(SSDST(32,0), SSDST(32,1), SSDST(32,2), SSSRC(32,0), SSSRC(32,1), SSSRC(32,2), pixel_per_row); break;\n\t}\n}\n\n/**\n * Apply the Scale4x effect on a group of rows. Used internally.\n */\nstatic inline void stage_scale4x(void* dst0, void* dst1, void* dst2, void* dst3, const void* src0, const void* src1, const void* src2, const void* src3, unsigned pixel, unsigned pixel_per_row)\n{\n\tstage_scale2x(dst0, dst1, src0, src1, src2, pixel, 2 * pixel_per_row);\n\tstage_scale2x(dst2, dst3, src1, src2, src3, pixel, 2 * pixel_per_row);\n}\n\n#define SCDST(i) (dst+(i)*dst_slice)\n#define SCSRC(i) (src+(i)*src_slice)\n#define SCMID(i) (mid[(i)])\n\n/**\n * Apply the Scale2x effect on a bitmap.\n * The destination bitmap is filled with the scaled version of the source bitmap.\n * The source bitmap isn't modified.\n * The destination bitmap must be manually allocated before calling the function,\n * note that the resulting size is exactly 2x2 times the size of the source bitmap.\n * \\param void_dst Pointer at the first pixel of the destination bitmap.\n * \\param dst_slice Size in bytes of a destination bitmap row.\n * \\param void_src Pointer at the first pixel of the source bitmap.\n * \\param src_slice Size in bytes of a source bitmap row.\n * \\param pixel Bytes per pixel of the source and destination bitmap.\n * \\param width Horizontal size in pixels of the source bitmap.\n * \\param height Vertical size in pixels of the source bitmap.\n */\nstatic void scale2x(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height)\n{\n\tunsigned char* dst = (unsigned char*)void_dst;\n\tconst unsigned char* src = (const unsigned char*)void_src;\n\tunsigned count;\n\n\tassert(height >= 2);\n\n\tcount = height;\n\n\tstage_scale2x(SCDST(0), SCDST(1), SCSRC(0), SCSRC(0), SCSRC(1), pixel, width);\n\n\tdst = SCDST(2);\n\n\tcount -= 2;\n\twhile (count) {\n\t\tstage_scale2x(SCDST(0), SCDST(1), SCSRC(0), SCSRC(1), SCSRC(2), pixel, width);\n\n\t\tdst = SCDST(2);\n\t\tsrc = SCSRC(1);\n\n\t\t--count;\n\t}\n\n\tstage_scale2x(SCDST(0), SCDST(1), SCSRC(0), SCSRC(1), SCSRC(1), pixel, width);\n\n#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))\n\tscale2x_mmx_emms();\n#endif\n}\n\n/**\n * Apply the Scale2x3 effect on a bitmap.\n * The destination bitmap is filled with the scaled version of the source bitmap.\n * The source bitmap isn't modified.\n * The destination bitmap must be manually allocated before calling the function,\n * note that the resulting size is exactly 2x3 times the size of the source bitmap.\n * \\param void_dst Pointer at the first pixel of the destination bitmap.\n * \\param dst_slice Size in bytes of a destination bitmap row.\n * \\param void_src Pointer at the first pixel of the source bitmap.\n * \\param src_slice Size in bytes of a source bitmap row.\n * \\param pixel Bytes per pixel of the source and destination bitmap.\n * \\param width Horizontal size in pixels of the source bitmap.\n * \\param height Vertical size in pixels of the source bitmap.\n */\nstatic void scale2x3(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height)\n{\n\tunsigned char* dst = (unsigned char*)void_dst;\n\tconst unsigned char* src = (const unsigned char*)void_src;\n\tunsigned count;\n\n\tassert(height >= 2);\n\n\tcount = height;\n\n\tstage_scale2x3(SCDST(0), SCDST(1), SCDST(2), SCSRC(0), SCSRC(0), SCSRC(1), pixel, width);\n\n\tdst = SCDST(3);\n\n\tcount -= 2;\n\twhile (count) {\n\t\tstage_scale2x3(SCDST(0), SCDST(1), SCDST(2), SCSRC(0), SCSRC(1), SCSRC(2), pixel, width);\n\n\t\tdst = SCDST(3);\n\t\tsrc = SCSRC(1);\n\n\t\t--count;\n\t}\n\n\tstage_scale2x3(SCDST(0), SCDST(1), SCDST(2), SCSRC(0), SCSRC(1), SCSRC(1), pixel, width);\n\n#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))\n\tscale2x_mmx_emms();\n#endif\n}\n\n/**\n * Apply the Scale2x4 effect on a bitmap.\n * The destination bitmap is filled with the scaled version of the source bitmap.\n * The source bitmap isn't modified.\n * The destination bitmap must be manually allocated before calling the function,\n * note that the resulting size is exactly 2x4 times the size of the source bitmap.\n * \\param void_dst Pointer at the first pixel of the destination bitmap.\n * \\param dst_slice Size in bytes of a destination bitmap row.\n * \\param void_src Pointer at the first pixel of the source bitmap.\n * \\param src_slice Size in bytes of a source bitmap row.\n * \\param pixel Bytes per pixel of the source and destination bitmap.\n * \\param width Horizontal size in pixels of the source bitmap.\n * \\param height Vertical size in pixels of the source bitmap.\n */\nstatic void scale2x4(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height)\n{\n\tunsigned char* dst = (unsigned char*)void_dst;\n\tconst unsigned char* src = (const unsigned char*)void_src;\n\tunsigned count;\n\n\tassert(height >= 2);\n\n\tcount = height;\n\n\tstage_scale2x4(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCSRC(0), SCSRC(0), SCSRC(1), pixel, width);\n\n\tdst = SCDST(4);\n\n\tcount -= 2;\n\twhile (count) {\n\t\tstage_scale2x4(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCSRC(0), SCSRC(1), SCSRC(2), pixel, width);\n\n\t\tdst = SCDST(4);\n\t\tsrc = SCSRC(1);\n\n\t\t--count;\n\t}\n\n\tstage_scale2x4(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCSRC(0), SCSRC(1), SCSRC(1), pixel, width);\n\n#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))\n\tscale2x_mmx_emms();\n#endif\n}\n\n/**\n * Apply the Scale3x effect on a bitmap.\n * The destination bitmap is filled with the scaled version of the source bitmap.\n * The source bitmap isn't modified.\n * The destination bitmap must be manually allocated before calling the function,\n * note that the resulting size is exactly 3x3 times the size of the source bitmap.\n * \\param void_dst Pointer at the first pixel of the destination bitmap.\n * \\param dst_slice Size in bytes of a destination bitmap row.\n * \\param void_src Pointer at the first pixel of the source bitmap.\n * \\param src_slice Size in bytes of a source bitmap row.\n * \\param pixel Bytes per pixel of the source and destination bitmap.\n * \\param width Horizontal size in pixels of the source bitmap.\n * \\param height Vertical size in pixels of the source bitmap.\n */\nstatic void scale3x(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height)\n{\n\tunsigned char* dst = (unsigned char*)void_dst;\n\tconst unsigned char* src = (const unsigned char*)void_src;\n\tunsigned count;\n\n\tassert(height >= 2);\n\n\tcount = height;\n\n\tstage_scale3x(SCDST(0), SCDST(1), SCDST(2), SCSRC(0), SCSRC(0), SCSRC(1), pixel, width);\n\n\tdst = SCDST(3);\n\n\tcount -= 2;\n\twhile (count) {\n\t\tstage_scale3x(SCDST(0), SCDST(1), SCDST(2), SCSRC(0), SCSRC(1), SCSRC(2), pixel, width);\n\n\t\tdst = SCDST(3);\n\t\tsrc = SCSRC(1);\n\n\t\t--count;\n\t}\n\n\tstage_scale3x(SCDST(0), SCDST(1), SCDST(2), SCSRC(0), SCSRC(1), SCSRC(1), pixel, width);\n}\n\n/**\n * Apply the Scale4x effect on a bitmap.\n * The destination bitmap is filled with the scaled version of the source bitmap.\n * The source bitmap isn't modified.\n * The destination bitmap must be manually allocated before calling the function,\n * note that the resulting size is exactly 4x4 times the size of the source bitmap.\n * \\note This function requires also a small buffer bitmap used internally to store\n * intermediate results. This bitmap must have at least an horizontal size in bytes of 2*width*pixel,\n * and a vertical size of 6 rows. The memory of this buffer must not be allocated\n * in video memory because it's also read and not only written. Generally\n * a heap (malloc) or a stack (alloca) buffer is the best choice.\n * \\param void_dst Pointer at the first pixel of the destination bitmap.\n * \\param dst_slice Size in bytes of a destination bitmap row.\n * \\param void_mid Pointer at the first pixel of the buffer bitmap.\n * \\param mid_slice Size in bytes of a buffer bitmap row.\n * \\param void_src Pointer at the first pixel of the source bitmap.\n * \\param src_slice Size in bytes of a source bitmap row.\n * \\param pixel Bytes per pixel of the source and destination bitmap.\n * \\param width Horizontal size in pixels of the source bitmap.\n * \\param height Vertical size in pixels of the source bitmap.\n */\nstatic void scale4x_buf(void* void_dst, unsigned dst_slice, void* void_mid, unsigned mid_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height)\n{\n\tunsigned char* dst = (unsigned char*)void_dst;\n\tconst unsigned char* src = (const unsigned char*)void_src;\n\tunsigned count;\n\tunsigned char* mid[6];\n\n\tassert(height >= 4);\n\n\tcount = height;\n\n\t/* set the 6 buffer pointers */\n\tmid[0] = (unsigned char*)void_mid;\n\tmid[1] = mid[0] + mid_slice;\n\tmid[2] = mid[1] + mid_slice;\n\tmid[3] = mid[2] + mid_slice;\n\tmid[4] = mid[3] + mid_slice;\n\tmid[5] = mid[4] + mid_slice;\n\n\tstage_scale2x(SCMID(-2+6), SCMID(-1+6), SCSRC(0), SCSRC(0), SCSRC(1), pixel, width);\n\tstage_scale2x(SCMID(0), SCMID(1), SCSRC(0), SCSRC(1), SCSRC(2), pixel, width);\n\tstage_scale2x(SCMID(2), SCMID(3), SCSRC(1), SCSRC(2), SCSRC(3), pixel, width);\n\tstage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(-2+6), SCMID(-2+6), SCMID(-1+6), SCMID(0), pixel, width);\n\n\tdst = SCDST(4);\n\n\tstage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(-1+6), SCMID(0), SCMID(1), SCMID(2), pixel, width);\n\n\tdst = SCDST(4);\n\n\tcount -= 4;\n\twhile (count) {\n\t\tunsigned char* tmp;\n\n\t\tstage_scale2x(SCMID(4), SCMID(5), SCSRC(2), SCSRC(3), SCSRC(4), pixel, width);\n\t\tstage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(1), SCMID(2), SCMID(3), SCMID(4), pixel, width);\n\n\t\tdst = SCDST(4);\n\t\tsrc = SCSRC(1);\n\n\t\ttmp = SCMID(0); /* shift by 2 position */\n\t\tSCMID(0) = SCMID(2);\n\t\tSCMID(2) = SCMID(4);\n\t\tSCMID(4) = tmp;\n\t\ttmp = SCMID(1);\n\t\tSCMID(1) = SCMID(3);\n\t\tSCMID(3) = SCMID(5);\n\t\tSCMID(5) = tmp;\n\n\t\t--count;\n\t}\n\n\tstage_scale2x(SCMID(4), SCMID(5), SCSRC(2), SCSRC(3), SCSRC(3), pixel, width);\n\tstage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(1), SCMID(2), SCMID(3), SCMID(4), pixel, width);\n\n\tdst = SCDST(4);\n\n\tstage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(3), SCMID(4), SCMID(5), SCMID(5), pixel, width);\n\n#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))\n\tscale2x_mmx_emms();\n#endif\n}\n\n/**\n * Apply the Scale4x effect on a bitmap.\n * The destination bitmap is filled with the scaled version of the source bitmap.\n * The source bitmap isn't modified.\n * The destination bitmap must be manually allocated before calling the function,\n * note that the resulting size is exactly 4x4 times the size of the source bitmap.\n * \\note This function operates like ::scale4x_buf() but the intermediate buffer is\n * automatically allocated in the stack.\n * \\param void_dst Pointer at the first pixel of the destination bitmap.\n * \\param dst_slice Size in bytes of a destination bitmap row.\n * \\param void_src Pointer at the first pixel of the source bitmap.\n * \\param src_slice Size in bytes of a source bitmap row.\n * \\param pixel Bytes per pixel of the source and destination bitmap.\n * \\param width Horizontal size in pixels of the source bitmap.\n * \\param height Vertical size in pixels of the source bitmap.\n */\nstatic void scale4x(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height)\n{\n\tunsigned mid_slice;\n\tvoid* mid;\n\n\tmid_slice = 2 * pixel * width; /* required space for 1 row buffer */\n\n\tmid_slice = (mid_slice + 0x7) & ~0x7; /* align to 8 bytes */\n\n#if HAVE_ALLOCA\n\tmid = alloca(6 * mid_slice); /* allocate space for 6 row buffers */\n\n\tassert(mid != 0); /* alloca should never fails */\n#else\n\tmid = malloc(6 * mid_slice); /* allocate space for 6 row buffers */\n\n\tif (!mid)\n\t\treturn;\n#endif\n\n\tscale4x_buf(void_dst, dst_slice, mid, mid_slice, void_src, src_slice, pixel, width, height);\n\n#if !HAVE_ALLOCA\n\tfree(mid);\n#endif\n}\n\n/**\n * Check if the scale implementation is applicable at the given arguments.\n * \\param scale Scale factor. 2, 203 (fox 2x3), 204 (for 2x4), 3 or 4.\n * \\param pixel Bytes per pixel of the source and destination bitmap.\n * \\param width Horizontal size in pixels of the source bitmap.\n * \\param height Vertical size in pixels of the source bitmap.\n * \\return\n *   - -1 on precondition violated.\n *   - 0 on success.\n */\nint scale_precondition(unsigned scale, unsigned pixel, unsigned width, unsigned height)\n{\n\tif (pixel != 1 && pixel != 2 && pixel != 4)\n\t\treturn -1;\n\n\tswitch (scale) {\n\tcase 202 :\n\tcase 203 :\n\tcase 204 :\n\tcase 2 :\n\tcase 303 :\n\tcase 3 :\n\t\tif (height < 2)\n\t\t\treturn -1;\n\t\tbreak;\n\tcase 404 :\n\tcase 4 :\n\t\tif (height < 4)\n\t\t\treturn -1;\n\t\tbreak;\n\tdefault:\n\t\treturn -1;\n\t}\n\n\tif (width < 2)\n\t\treturn -1;\n\n\treturn 0;\n}\n\n/**\n * Apply the Scale effect on a bitmap.\n * This function is simply a common interface for ::scale2x(), ::scale3x() and ::scale4x().\n * \\param scale Scale factor. 2, 203 (fox 2x3), 204 (for 2x4), 3 or 4.\n * \\param void_dst Pointer at the first pixel of the destination bitmap.\n * \\param dst_slice Size in bytes of a destination bitmap row.\n * \\param void_src Pointer at the first pixel of the source bitmap.\n * \\param src_slice Size in bytes of a source bitmap row.\n * \\param pixel Bytes per pixel of the source and destination bitmap.\n * \\param width Horizontal size in pixels of the source bitmap.\n * \\param height Vertical size in pixels of the source bitmap.\n */\nvoid scale(unsigned scale, void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height)\n{\n\tswitch (scale) {\n\tcase 202 :\n\tcase 2 :\n\t\tscale2x(void_dst, dst_slice, void_src, src_slice, pixel, width, height);\n\t\tbreak;\n\tcase 203 :\n\t\tscale2x3(void_dst, dst_slice, void_src, src_slice, pixel, width, height);\n\t\tbreak;\n\tcase 204 :\n\t\tscale2x4(void_dst, dst_slice, void_src, src_slice, pixel, width, height);\n\t\tbreak;\n\tcase 303 :\n\tcase 3 :\n\t\tscale3x(void_dst, dst_slice, void_src, src_slice, pixel, width, height);\n\t\tbreak;\n\tcase 404 :\n\tcase 4 :\n\t\tscale4x(void_dst, dst_slice, void_src, src_slice, pixel, width, height);\n\t\tbreak;\n\t}\n}\n\n"
  },
  {
    "path": "src/Engine/Scalers/scalebit.h",
    "content": "/*\n * This file is part of the Scale2x project.\n *\n * Copyright (C) 2003 Andrea Mazzoleni\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n */\n\n/*\n * This file contains an example implementation of the Scale effect\n * applied to a generic bitmap.\n *\n * You can find an high level description of the effect at :\n *\n * http://scale2x.sourceforge.net/\n */\n\n#ifndef __SCALEBIT_H\n#define __SCALEBIT_H\n\nint scale_precondition(unsigned scale, unsigned pixel, unsigned width, unsigned height);\nvoid scale(unsigned scale, void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height);\n\n#endif\n\n"
  },
  {
    "path": "src/Engine/Scalers/xbrz.cpp",
    "content": "// ****************************************************************************\n// * This file is part of the HqMAME project. It is distributed under         *\n// * GNU General Public License: http://www.gnu.org/licenses/gpl-3.0          *\n// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved          *\n// *                                                                          *\n// * Additionally and as a special exception, the author gives permission     *\n// * to link the code of this program with the MAME library (or with modified *\n// * versions of MAME that use the same license as MAME), and distribute      *\n// * linked combinations including the two. You must obey the GNU General     *\n// * Public License in all respects for all of the code used other than MAME. *\n// * If you modify this file, you may extend this exception to your version   *\n// * of the file, but you are not obligated to do so. If you do not wish to   *\n// * do so, delete this exception statement from your version.                *\n// ****************************************************************************\n\n#include \"xbrz.h\"\n#include <cassert>\n#include <cmath>\n#include <algorithm>\n#include <vector>\n\nnamespace\n{\ntemplate <uint32_t N> inline\nunsigned char getByte(uint32_t val) { return static_cast<unsigned char>((val >> (8 * N)) & 0xff); }\n\ninline unsigned char getAlpha(uint32_t pix) { return getByte<3>(pix); }\ninline unsigned char getRed  (uint32_t pix) { return getByte<2>(pix); }\ninline unsigned char getGreen(uint32_t pix) { return getByte<1>(pix); }\ninline unsigned char getBlue (uint32_t pix) { return getByte<0>(pix); }\n\ninline uint32_t makePixel(                 unsigned char r, unsigned char g, unsigned char b) { return             (r << 16) | (g << 8) | b; }\ninline uint32_t makePixel(unsigned char a, unsigned char r, unsigned char g, unsigned char b) { return (a << 24) | (r << 16) | (g << 8) | b; }\n\n#define calcColor(colFront, colBack) static_cast<unsigned char>((colFront * weightFront + colBack * weightBack) / weightSum)\n\ntemplate <unsigned int M, unsigned int N> inline\nuint32_t gradientRGB(uint32_t pixFront, uint32_t pixBack) //blend front color with opacity M / N over opaque background: http://en.wikipedia.org/wiki/Alpha_compositing#Alpha_blending\n{\n    //static_assert(0 < M && M < N && N <= 1000, \"\");\n\n\tconst unsigned int weightFront = M;\n\tconst unsigned int weightBack = (N - M);\n\tconst unsigned int weightSum = N;\n\n    return makePixel(calcColor(getRed  (pixFront), getRed  (pixBack)),\n                     calcColor(getGreen(pixFront), getGreen(pixBack)),\n                     calcColor(getBlue (pixFront), getBlue (pixBack)));\n}\n\n\ntemplate <unsigned int M, unsigned int N> inline\nuint32_t gradientARGB(uint32_t pixFront, uint32_t pixBack) //find intermediate color between two colors with alpha channels (=> NO alpha blending!!!)\n{\n    //static_assert(0 < M && M < N && N <= 1000, \"\");\n\n    const unsigned int weightFront = getAlpha(pixFront) * M;\n    const unsigned int weightBack  = getAlpha(pixBack) * (N - M);\n    const unsigned int weightSum   = weightFront + weightBack;\n    if (weightSum == 0)\n        return 0;\n\n    return makePixel(static_cast<unsigned char>(weightSum / N),\n                     calcColor(getRed  (pixFront), getRed  (pixBack)),\n                     calcColor(getGreen(pixFront), getGreen(pixBack)),\n                     calcColor(getBlue (pixFront), getBlue (pixBack)));\n}\n\n\n//inline\n//double fastSqrt(double n)\n//{\n//    __asm //speeds up xBRZ by about 9% compared to std::sqrt which internally uses the same assembler instructions but adds some \"fluff\"\n//    {\n//        fld n\n//        fsqrt\n//    }\n//}\n//\n\n\nuint32_t*       byteAdvance(      uint32_t* ptr, int bytes) { return reinterpret_cast<      uint32_t*>(reinterpret_cast<      char*>(ptr) + bytes); }\nconst uint32_t* byteAdvance(const uint32_t* ptr, int bytes) { return reinterpret_cast<const uint32_t*>(reinterpret_cast<const char*>(ptr) + bytes); }\n\n\n//fill block  with the given color\ninline\nvoid fillBlock(uint32_t* trg, int pitch, uint32_t col, int blockWidth, int blockHeight)\n{\n    //for (int y = 0; y < blockHeight; ++y, trg = byteAdvance(trg, pitch))\n    //    std::fill(trg, trg + blockWidth, col);\n\n    for (int y = 0; y < blockHeight; ++y, trg = byteAdvance(trg, pitch))\n        for (int x = 0; x < blockWidth; ++x)\n            trg[x] = col;\n}\n\ninline\nvoid fillBlock(uint32_t* trg, int pitch, uint32_t col, int n) { fillBlock(trg, pitch, col, n, n); }\n\n\n#ifdef _MSC_VER\n    #define FORCE_INLINE __forceinline\n#elif defined __GNUC__\n    #define FORCE_INLINE __attribute__((always_inline)) inline\n#else\n    #define FORCE_INLINE inline\n#endif\n\n\nenum RotationDegree //clock-wise\n{\n    ROT_0,\n    ROT_90,\n    ROT_180,\n    ROT_270\n};\n\n//calculate input matrix coordinates after rotation at compile time\ntemplate <RotationDegree rotDeg, size_t I, size_t J, size_t N>\nstruct MatrixRotation;\n\ntemplate <size_t I, size_t J, size_t N>\nstruct MatrixRotation<ROT_0, I, J, N>\n{\n    static const size_t I_old = I;\n    static const size_t J_old = J;\n};\n\ntemplate <RotationDegree rotDeg, size_t I, size_t J, size_t N> //(i, j) = (row, col) indices, N = size of (square) matrix\nstruct MatrixRotation\n{\n    static const size_t I_old = N - 1 - MatrixRotation<static_cast<RotationDegree>(rotDeg - 1), I, J, N>::J_old; //old coordinates before rotation!\n    static const size_t J_old =         MatrixRotation<static_cast<RotationDegree>(rotDeg - 1), I, J, N>::I_old; //\n};\n\n\ntemplate <size_t N, RotationDegree rotDeg>\nclass OutputMatrix\n{\npublic:\n    OutputMatrix(uint32_t* out, int outWidth) : //access matrix area, top-left at position \"out\" for image with given width\n        out_(out),\n        outWidth_(outWidth) {}\n\n    template <size_t I, size_t J>\n    uint32_t& ref() const\n    {\n        static const size_t I_old = MatrixRotation<rotDeg, I, J, N>::I_old;\n        static const size_t J_old = MatrixRotation<rotDeg, I, J, N>::J_old;\n        return *(out_ + J_old + I_old * outWidth_);\n    }\n\nprivate:\n    uint32_t* out_;\n    const int outWidth_;\n};\n\n\ntemplate <class T> inline\nT square(T value) { return value * value; }\n\n\n/*\ninline\ndouble distRGB(uint32_t pix1, uint32_t pix2)\n{\n    const double r_diff = static_cast<int>(getRed  (pix1)) - getRed  (pix2);\n    const double g_diff = static_cast<int>(getGreen(pix1)) - getGreen(pix2);\n    const double b_diff = static_cast<int>(getBlue (pix1)) - getBlue (pix2);\n\n    //euklidean RGB distance\n    return std::sqrt(square(r_diff) + square(g_diff) + square(b_diff));\n}\n\n\ninline\ndouble distYCbCr(uint32_t pix1, uint32_t pix2, double lumaWeight)\n{\n    //http://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.601_conversion\n    //YCbCr conversion is a matrix multiplication => take advantage of linearity by subtracting first!\n    const int r_diff = static_cast<int>(getRed  (pix1)) - getRed  (pix2); //we may delay division by 255 to after matrix multiplication\n    const int g_diff = static_cast<int>(getGreen(pix1)) - getGreen(pix2); //\n    const int b_diff = static_cast<int>(getBlue (pix1)) - getBlue (pix2); //substraction for int is noticeable faster than for double!\n\n    //const double k_b = 0.0722; //ITU-R BT.709 conversion\n    //const double k_r = 0.2126; //\n    const double k_b = 0.0593; //ITU-R BT.2020 conversion\n    const double k_r = 0.2627; //\n    const double k_g = 1 - k_b - k_r;\n\n    const double scale_b = 0.5 / (1 - k_b);\n    const double scale_r = 0.5 / (1 - k_r);\n\n    const double y   = k_r * r_diff + k_g * g_diff + k_b * b_diff; //[!], analog YCbCr!\n    const double c_b = scale_b * (b_diff - y);\n    const double c_r = scale_r * (r_diff - y);\n\n    //we skip division by 255 to have similar range like other distance functions\n    return std::sqrt(square(lumaWeight * y) + square(c_b) + square(c_r));\n}\n*/\n\nstruct DistYCbCrBuffer //30% perf boost compared to distYCbCr()!\n{\npublic:\n    static double dist(uint32_t pix1, uint32_t pix2)\n    {\n//#if defined _MSC_VER && _MSC_VER < 1900\n//#error function scope static initialization is not yet thread-safe!\n//#endif\n        static const DistYCbCrBuffer inst;\n        return inst.distImpl(pix1, pix2);\n    }\n\nprivate:\n    DistYCbCrBuffer() : buffer(256 * 256 * 256)\n    {\n        for (uint32_t i = 0; i < 256 * 256 * 256; ++i) //startup time: 114 ms on Intel Core i5 (four cores)\n        {\n            const int r_diff = getByte<2>(i) * 2 - 255;\n            const int g_diff = getByte<1>(i) * 2 - 255;\n            const int b_diff = getByte<0>(i) * 2 - 255;\n\n            const double k_b = 0.0593; //ITU-R BT.2020 conversion\n            const double k_r = 0.2627; //\n            const double k_g = 1 - k_b - k_r;\n\n            const double scale_b = 0.5 / (1 - k_b);\n            const double scale_r = 0.5 / (1 - k_r);\n\n            const double y   = k_r * r_diff + k_g * g_diff + k_b * b_diff; //[!], analog YCbCr!\n            const double c_b = scale_b * (b_diff - y);\n            const double c_r = scale_r * (r_diff - y);\n\n            buffer[i] = static_cast<float>(std::sqrt(square(y) + square(c_b) + square(c_r)));\n        }\n    }\n\n    double distImpl(uint32_t pix1, uint32_t pix2) const\n    {\n        //if (pix1 == pix2) -> 8% perf degradation!\n        //    return 0;\n        //if (pix1 > pix2)\n        //\t  std::swap(pix1, pix2); -> 30% perf degradation!!!\n\n        const int r_diff = static_cast<int>(getRed  (pix1)) - getRed  (pix2);\n        const int g_diff = static_cast<int>(getGreen(pix1)) - getGreen(pix2);\n        const int b_diff = static_cast<int>(getBlue (pix1)) - getBlue (pix2);\n\n        return buffer[(((r_diff + 255) / 2) << 16) | //slightly reduce precision (division by 2) to squeeze value into single byte\n                      (((g_diff + 255) / 2) <<  8) |\n                      (( b_diff + 255) / 2)];\n    }\n\n    std::vector<float> buffer; //consumes 64 MB memory; using double is only 2% faster, but takes 128 MB\n};\n\n\nenum BlendType\n{\n    BLEND_NONE = 0,\n    BLEND_NORMAL,   //a normal indication to blend\n    BLEND_DOMINANT //a strong indication to blend\n    //attention: BlendType must fit into the value range of 2 bit!!!\n};\n\nstruct BlendResult\n{\n    BlendType\n    /**/blend_f, blend_g,\n    /**/blend_j, blend_k;\n};\n\n\nstruct Kernel_4x4 //kernel for preprocessing step\n{\n    uint32_t\n    /**/a, b, c, d,\n    /**/e, f, g, h,\n    /**/i, j, k, l,\n    /**/m, n, o, p;\n};\n\n#define _eq(pix1, pix2) (ColorDistance::dist(pix1, pix2, cfg.luminanceWeight) < cfg.equalColorTolerance)\n#define _dist(pix1, pix2) ColorDistance::dist(pix1, pix2, cfg.luminanceWeight)\n\n/*\ninput kernel area naming convention:\n-----------------\n| A | B | C | D |\n----|---|---|---|\n| E | F | G | H |   //evaluate the four corners between F, G, J, K\n----|---|---|---|   //input pixel is at position F\n| I | J | K | L |\n----|---|---|---|\n| M | N | O | P |\n-----------------\n*/\ntemplate <class ColorDistance>\nFORCE_INLINE //detect blend direction\nBlendResult preProcessCorners(const Kernel_4x4& ker, const xbrz::ScalerCfg& cfg) //result: F, G, J, K corners of \"GradientType\"\n{\n    BlendResult result = {};\n\n    if ((ker.f == ker.g &&\n         ker.j == ker.k) ||\n        (ker.f == ker.j &&\n         ker.g == ker.k))\n        return result;\n\n    const int weight = 4;\n    double jg = _dist(ker.i, ker.f) + _dist(ker.f, ker.c) + _dist(ker.n, ker.k) + _dist(ker.k, ker.h) + weight * _dist(ker.j, ker.g);\n    double fk = _dist(ker.e, ker.j) + _dist(ker.j, ker.o) + _dist(ker.b, ker.g) + _dist(ker.g, ker.l) + weight * _dist(ker.f, ker.k);\n\n    if (jg < fk) //test sample: 70% of values max(jg, fk) / min(jg, fk) are between 1.1 and 3.7 with median being 1.8\n    {\n        const bool dominantGradient = cfg.dominantDirectionThreshold * jg < fk;\n        if (ker.f != ker.g && ker.f != ker.j)\n            result.blend_f = dominantGradient ? BLEND_DOMINANT : BLEND_NORMAL;\n\n        if (ker.k != ker.j && ker.k != ker.g)\n            result.blend_k = dominantGradient ? BLEND_DOMINANT : BLEND_NORMAL;\n    }\n    else if (fk < jg)\n    {\n        const bool dominantGradient = cfg.dominantDirectionThreshold * fk < jg;\n        if (ker.j != ker.f && ker.j != ker.k)\n            result.blend_j = dominantGradient ? BLEND_DOMINANT : BLEND_NORMAL;\n\n        if (ker.g != ker.f && ker.g != ker.k)\n            result.blend_g = dominantGradient ? BLEND_DOMINANT : BLEND_NORMAL;\n    }\n    return result;\n}\n\nstruct Kernel_3x3\n{\n    uint32_t\n    /**/a,  b,  c,\n    /**/d,  e,  f,\n    /**/g,  h,  i;\n};\n\n#define DEF_GETTER(x) template <RotationDegree rotDeg> uint32_t inline get_##x(const Kernel_3x3& ker) { return ker.x; }\n//we cannot and NEED NOT write \"ker.##x\" since ## concatenates preprocessor tokens but \".\" is not a token\nDEF_GETTER(a) DEF_GETTER(b) DEF_GETTER(c)\nDEF_GETTER(d) DEF_GETTER(e) DEF_GETTER(f)\nDEF_GETTER(g) DEF_GETTER(h) DEF_GETTER(i)\n#undef DEF_GETTER\n\n#define DEF_GETTER(x, y) template <> inline uint32_t get_##x<ROT_90>(const Kernel_3x3& ker) { return ker.y; }\nDEF_GETTER(a, g) DEF_GETTER(b, d) DEF_GETTER(c, a)\nDEF_GETTER(d, h) DEF_GETTER(e, e) DEF_GETTER(f, b)\nDEF_GETTER(g, i) DEF_GETTER(h, f) DEF_GETTER(i, c)\n#undef DEF_GETTER\n\n#define DEF_GETTER(x, y) template <> inline uint32_t get_##x<ROT_180>(const Kernel_3x3& ker) { return ker.y; }\nDEF_GETTER(a, i) DEF_GETTER(b, h) DEF_GETTER(c, g)\nDEF_GETTER(d, f) DEF_GETTER(e, e) DEF_GETTER(f, d)\nDEF_GETTER(g, c) DEF_GETTER(h, b) DEF_GETTER(i, a)\n#undef DEF_GETTER\n\n#define DEF_GETTER(x, y) template <> inline uint32_t get_##x<ROT_270>(const Kernel_3x3& ker) { return ker.y; }\nDEF_GETTER(a, c) DEF_GETTER(b, f) DEF_GETTER(c, i)\nDEF_GETTER(d, b) DEF_GETTER(e, e) DEF_GETTER(f, h)\nDEF_GETTER(g, a) DEF_GETTER(h, d) DEF_GETTER(i,\tg)\n#undef DEF_GETTER\n\n\n//compress four blend types into a single byte\ninline BlendType getTopL   (unsigned char b) { return static_cast<BlendType>(0x3 & b); }\ninline BlendType getTopR   (unsigned char b) { return static_cast<BlendType>(0x3 & (b >> 2)); }\ninline BlendType getBottomR(unsigned char b) { return static_cast<BlendType>(0x3 & (b >> 4)); }\ninline BlendType getBottomL(unsigned char b) { return static_cast<BlendType>(0x3 & (b >> 6)); }\n\ninline void setTopL   (unsigned char& b, BlendType bt) { b |= bt; } //buffer is assumed to be initialized before preprocessing!\ninline void setTopR   (unsigned char& b, BlendType bt) { b |= (bt << 2); }\ninline void setBottomR(unsigned char& b, BlendType bt) { b |= (bt << 4); }\ninline void setBottomL(unsigned char& b, BlendType bt) { b |= (bt << 6); }\n\ninline bool blendingNeeded(unsigned char b) { return b != 0; }\n\ntemplate <RotationDegree rotDeg> inline\nunsigned char rotateBlendInfo(unsigned char b) { return b; }\ntemplate <> inline unsigned char rotateBlendInfo<ROT_90 >(unsigned char b) { return ((b << 2) | (b >> 6)) & 0xff; }\ntemplate <> inline unsigned char rotateBlendInfo<ROT_180>(unsigned char b) { return ((b << 4) | (b >> 4)) & 0xff; }\ntemplate <> inline unsigned char rotateBlendInfo<ROT_270>(unsigned char b) { return ((b << 6) | (b >> 2)) & 0xff; }\n\n\n\n\n/*\ninput kernel area naming convention:\n-------------\n| A | B | C |\n----|---|---|\n| D | E | F | //input pixel is at position E\n----|---|---|\n| G | H | I |\n-------------\n*/\ntemplate <class Scaler, class ColorDistance, RotationDegree rotDeg>\nFORCE_INLINE //perf: quite worth it!\nvoid blendPixel(const Kernel_3x3& ker,\n                uint32_t* target, int trgWidth,\n                unsigned char blendInfo, //result of preprocessing all four corners of pixel \"e\"\n                const xbrz::ScalerCfg& cfg)\n{\n#define a get_a<rotDeg>(ker)\n#define b get_b<rotDeg>(ker)\n#define c get_c<rotDeg>(ker)\n#define d get_d<rotDeg>(ker)\n#define e get_e<rotDeg>(ker)\n#define f get_f<rotDeg>(ker)\n#define g get_g<rotDeg>(ker)\n#define h get_h<rotDeg>(ker)\n#define i get_i<rotDeg>(ker)\n\n\n    const unsigned char blend = rotateBlendInfo<rotDeg>(blendInfo);\n\n    if (getBottomR(blend) >= BLEND_NORMAL)\n    {\n\t\tbool doLineBlend = true;\n\n        if (getBottomR(blend) >= BLEND_DOMINANT)\n\t\t\tdoLineBlend = true;\n\n        //make sure there is no second blending in an adjacent rotation for this pixel: handles insular pixels, mario eyes\n        else if (getTopR(blend) != BLEND_NONE && !_eq(e, g)) //but support double-blending for 90 corners\n\t\t\tdoLineBlend = false;\n        else if (getBottomL(blend) != BLEND_NONE && !_eq(e, c))\n\t\t\tdoLineBlend = false;\n\n        //no full blending for L-shapes; blend corner only (handles \"mario mushroom eyes\")\n        else if (!_eq(e, i) && _eq(g, h) && _eq(h , i) && _eq(i, f) && _eq(f, c))\n\t\t\tdoLineBlend = false;\n\n        const uint32_t px = _dist(e, f) <= _dist(e, h) ? f : h; //choose most similar color\n\n        OutputMatrix<Scaler::scale, rotDeg> out(target, trgWidth);\n\n        if (doLineBlend)\n        {\n            const double fg = _dist(f, g); //test sample: 70% of values max(fg, hc) / min(fg, hc) are between 1.1 and 3.7 with median being 1.9\n            const double hc = _dist(h, c); //\n\n            const bool haveShallowLine = cfg.steepDirectionThreshold * fg <= hc && e != g && d != g;\n            const bool haveSteepLine   = cfg.steepDirectionThreshold * hc <= fg && e != c && b != c;\n\n            if (haveShallowLine)\n            {\n                if (haveSteepLine)\n                    Scaler::blendLineSteepAndShallow(px, out);\n                else\n                    Scaler::blendLineShallow(px, out);\n            }\n            else\n            {\n                if (haveSteepLine)\n                    Scaler::blendLineSteep(px, out);\n                else\n                    Scaler::blendLineDiagonal(px,out);\n            }\n        }\n        else\n            Scaler::blendCorner(px, out);\n    }\n\n#undef a\n#undef b\n#undef c\n#undef d\n#undef e\n#undef f\n#undef g\n#undef h\n#undef i\n}\n\n\ntemplate <class Scaler, class ColorDistance> //scaler policy: see \"Scaler2x\" reference implementation\nvoid scaleImage(const uint32_t* src, uint32_t* trg, int srcWidth, int srcHeight, const xbrz::ScalerCfg& cfg, int yFirst, int yLast)\n{\n    yFirst = std::max(yFirst, 0);\n    yLast  = std::min(yLast, srcHeight);\n    if (yFirst >= yLast || srcWidth <= 0)\n        return;\n\n    const int trgWidth = srcWidth * Scaler::scale;\n\n    //\"use\" space at the end of the image as temporary buffer for \"on the fly preprocessing\": we even could use larger area of\n    //\"sizeof(uint32_t) * srcWidth * (yLast - yFirst)\" bytes without risk of accidental overwriting before accessing\n    const int bufferSize = srcWidth;\n    unsigned char* preProcBuffer = reinterpret_cast<unsigned char*>(trg + yLast * Scaler::scale * trgWidth) - bufferSize;\n    std::fill(preProcBuffer, preProcBuffer + bufferSize, 0);\n    //static_assert(BLEND_NONE == 0, \"\");\n\n    //initialize preprocessing buffer for first row of current stripe: detect upper left and right corner blending\n    //this cannot be optimized for adjacent processing stripes; we must not allow for a memory race condition!\n    if (yFirst > 0)\n    {\n        const int y = yFirst - 1;\n\n        const uint32_t* s_m1 = src + srcWidth * std::max(y - 1, 0);\n        const uint32_t* s_0  = src + srcWidth * y; //center line\n        const uint32_t* s_p1 = src + srcWidth * std::min(y + 1, srcHeight - 1);\n        const uint32_t* s_p2 = src + srcWidth * std::min(y + 2, srcHeight - 1);\n\n        for (int x = 0; x < srcWidth; ++x)\n        {\n            const int x_m1 = std::max(x - 1, 0);\n            const int x_p1 = std::min(x + 1, srcWidth - 1);\n            const int x_p2 = std::min(x + 2, srcWidth - 1);\n\n            Kernel_4x4 ker = {}; //perf: initialization is negligible\n            ker.a = s_m1[x_m1]; //read sequentially from memory as far as possible\n            ker.b = s_m1[x];\n            ker.c = s_m1[x_p1];\n            ker.d = s_m1[x_p2];\n\n            ker.e = s_0[x_m1];\n            ker.f = s_0[x];\n            ker.g = s_0[x_p1];\n            ker.h = s_0[x_p2];\n\n            ker.i = s_p1[x_m1];\n            ker.j = s_p1[x];\n            ker.k = s_p1[x_p1];\n            ker.l = s_p1[x_p2];\n\n            ker.m = s_p2[x_m1];\n            ker.n = s_p2[x];\n            ker.o = s_p2[x_p1];\n            ker.p = s_p2[x_p2];\n\n            const BlendResult res = preProcessCorners<ColorDistance>(ker, cfg);\n            /*\n            preprocessing blend result:\n            ---------\n            | F | G |   //evalute corner between F, G, J, K\n            ----|---|   //input pixel is at position F\n            | J | K |\n            ---------\n            */\n            setTopR(preProcBuffer[x], res.blend_j);\n\n            if (x + 1 < bufferSize)\n                setTopL(preProcBuffer[x + 1], res.blend_k);\n        }\n    }\n    //------------------------------------------------------------------------------------\n\n    for (int y = yFirst; y < yLast; ++y)\n    {\n        uint32_t* out = trg + Scaler::scale * y * trgWidth; //consider MT \"striped\" access\n\n        const uint32_t* s_m1 = src + srcWidth * std::max(y - 1, 0);\n        const uint32_t* s_0  = src + srcWidth * y; //center line\n        const uint32_t* s_p1 = src + srcWidth * std::min(y + 1, srcHeight - 1);\n        const uint32_t* s_p2 = src + srcWidth * std::min(y + 2, srcHeight - 1);\n\n        unsigned char blend_xy1 = 0; //corner blending for current (x, y + 1) position\n\n        for (int x = 0; x < srcWidth; ++x, out += Scaler::scale)\n        {\n            //all those bounds checks have only insignificant impact on performance!\n            const int x_m1 = std::max(x - 1, 0); //perf: prefer array indexing to additional pointers!\n            const int x_p1 = std::min(x + 1, srcWidth - 1);\n            const int x_p2 = std::min(x + 2, srcWidth - 1);\n\n            Kernel_4x4 ker4 = {}; //perf: initialization is negligible\n\n            ker4.a = s_m1[x_m1]; //read sequentially from memory as far as possible\n            ker4.b = s_m1[x];\n            ker4.c = s_m1[x_p1];\n            ker4.d = s_m1[x_p2];\n\n            ker4.e = s_0[x_m1];\n            ker4.f = s_0[x];\n            ker4.g = s_0[x_p1];\n            ker4.h = s_0[x_p2];\n\n            ker4.i = s_p1[x_m1];\n            ker4.j = s_p1[x];\n            ker4.k = s_p1[x_p1];\n            ker4.l = s_p1[x_p2];\n\n            ker4.m = s_p2[x_m1];\n            ker4.n = s_p2[x];\n            ker4.o = s_p2[x_p1];\n            ker4.p = s_p2[x_p2];\n\n            //evaluate the four corners on bottom-right of current pixel\n            unsigned char blend_xy = 0; //for current (x, y) position\n            {\n                const BlendResult res = preProcessCorners<ColorDistance>(ker4, cfg);\n                /*\n                preprocessing blend result:\n                ---------\n                | F | G |   //evalute corner between F, G, J, K\n                ----|---|   //current input pixel is at position F\n                | J | K |\n                ---------\n                */\n                blend_xy = preProcBuffer[x];\n                setBottomR(blend_xy, res.blend_f); //all four corners of (x, y) have been determined at this point due to processing sequence!\n\n                setTopR(blend_xy1, res.blend_j); //set 2nd known corner for (x, y + 1)\n                preProcBuffer[x] = blend_xy1; //store on current buffer position for use on next row\n\n                blend_xy1 = 0;\n                setTopL(blend_xy1, res.blend_k); //set 1st known corner for (x + 1, y + 1) and buffer for use on next column\n\n                if (x + 1 < bufferSize) //set 3rd known corner for (x + 1, y)\n                    setBottomL(preProcBuffer[x + 1], res.blend_g);\n            }\n\n            //fill block of size scale * scale with the given color\n            fillBlock(out, trgWidth * sizeof(uint32_t), ker4.f, Scaler::scale); //place *after* preprocessing step, to not overwrite the results while processing the the last pixel!\n\n            //blend four corners of current pixel\n            if (blendingNeeded(blend_xy)) //good 5% perf-improvement\n            {\n                Kernel_3x3 ker3 = {}; //perf: initialization is negligible\n\n                ker3.a = ker4.a;\n                ker3.b = ker4.b;\n                ker3.c = ker4.c;\n\n                ker3.d = ker4.e;\n                ker3.e = ker4.f;\n                ker3.f = ker4.g;\n\n                ker3.g = ker4.i;\n                ker3.h = ker4.j;\n                ker3.i = ker4.k;\n\n                blendPixel<Scaler, ColorDistance, ROT_0  >(ker3, out, trgWidth, blend_xy, cfg);\n                blendPixel<Scaler, ColorDistance, ROT_90 >(ker3, out, trgWidth, blend_xy, cfg);\n                blendPixel<Scaler, ColorDistance, ROT_180>(ker3, out, trgWidth, blend_xy, cfg);\n                blendPixel<Scaler, ColorDistance, ROT_270>(ker3, out, trgWidth, blend_xy, cfg);\n            }\n        }\n    }\n}\n\n//------------------------------------------------------------------------------------\n\ntemplate <class ColorGradient>\nstruct Scaler2x : public ColorGradient\n{\n    static const int scale = 2;\n\n    template <unsigned int M, unsigned int N> //bring template function into scope for GCC\n    static void alphaGrad(uint32_t& pixBack, uint32_t pixFront) { ColorGradient::template alphaGrad<M, N>(pixBack, pixFront); }\n\n\n    template <class OutputMatrix>\n    static void blendLineShallow(uint32_t col, OutputMatrix& out)\n    {\n        alphaGrad<1, 4>(out.template ref<scale - 1, 0>(), col);\n        alphaGrad<3, 4>(out.template ref<scale - 1, 1>(), col);\n    }\n\n    template <class OutputMatrix>\n    static void blendLineSteep(uint32_t col, OutputMatrix& out)\n    {\n        alphaGrad<1, 4>(out.template ref<0, scale - 1>(), col);\n        alphaGrad<3, 4>(out.template ref<1, scale - 1>(), col);\n    }\n\n    template <class OutputMatrix>\n    static void blendLineSteepAndShallow(uint32_t col, OutputMatrix& out)\n    {\n        alphaGrad<1, 4>(out.template ref<1, 0>(), col);\n        alphaGrad<1, 4>(out.template ref<0, 1>(), col);\n        alphaGrad<5, 6>(out.template ref<1, 1>(), col); //[!] fixes 7/8 used in xBR\n    }\n\n    template <class OutputMatrix>\n    static void blendLineDiagonal(uint32_t col, OutputMatrix& out)\n    {\n        alphaGrad<1, 2>(out.template ref<1, 1>(), col);\n    }\n\n    template <class OutputMatrix>\n    static void blendCorner(uint32_t col, OutputMatrix& out)\n    {\n        //model a round corner\n        alphaGrad<21, 100>(out.template ref<1, 1>(), col); //exact: 1 - pi/4 = 0.2146018366\n    }\n};\n\n\ntemplate <class ColorGradient>\nstruct Scaler3x : public ColorGradient\n{\n    static const int scale = 3;\n\n    template <unsigned int M, unsigned int N> //bring template function into scope for GCC\n    static void alphaGrad(uint32_t& pixBack, uint32_t pixFront) { ColorGradient::template alphaGrad<M, N>(pixBack, pixFront); }\n\n\n    template <class OutputMatrix>\n    static void blendLineShallow(uint32_t col, OutputMatrix& out)\n    {\n        alphaGrad<1, 4>(out.template ref<scale - 1, 0>(), col);\n        alphaGrad<1, 4>(out.template ref<scale - 2, 2>(), col);\n\n        alphaGrad<3, 4>(out.template ref<scale - 1, 1>(), col);\n        out.template ref<scale - 1, 2>() = col;\n    }\n\n    template <class OutputMatrix>\n    static void blendLineSteep(uint32_t col, OutputMatrix& out)\n    {\n        alphaGrad<1, 4>(out.template ref<0, scale - 1>(), col);\n        alphaGrad<1, 4>(out.template ref<2, scale - 2>(), col);\n\n        alphaGrad<3, 4>(out.template ref<1, scale - 1>(), col);\n        out.template ref<2, scale - 1>() = col;\n    }\n\n    template <class OutputMatrix>\n    static void blendLineSteepAndShallow(uint32_t col, OutputMatrix& out)\n    {\n        alphaGrad<1, 4>(out.template ref<2, 0>(), col);\n        alphaGrad<1, 4>(out.template ref<0, 2>(), col);\n        alphaGrad<3, 4>(out.template ref<2, 1>(), col);\n        alphaGrad<3, 4>(out.template ref<1, 2>(), col);\n        out.template ref<2, 2>() = col;\n    }\n\n    template <class OutputMatrix>\n    static void blendLineDiagonal(uint32_t col, OutputMatrix& out)\n    {\n        alphaGrad<1, 8>(out.template ref<1, 2>(), col); //conflict with other rotations for this odd scale\n        alphaGrad<1, 8>(out.template ref<2, 1>(), col);\n        alphaGrad<7, 8>(out.template ref<2, 2>(), col); //\n    }\n\n    template <class OutputMatrix>\n    static void blendCorner(uint32_t col, OutputMatrix& out)\n    {\n        //model a round corner\n        alphaGrad<45, 100>(out.template ref<2, 2>(), col); //exact: 0.4545939598\n        //alphaGrad<7, 256>(out.template ref<2, 1>(), col); //0.02826017254 -> negligible + avoid conflicts with other rotations for this odd scale\n        //alphaGrad<7, 256>(out.template ref<1, 2>(), col); //0.02826017254\n    }\n};\n\n\ntemplate <class ColorGradient>\nstruct Scaler4x : public ColorGradient\n{\n    static const int scale = 4;\n\n    template <unsigned int M, unsigned int N> //bring template function into scope for GCC\n    static void alphaGrad(uint32_t& pixBack, uint32_t pixFront) { ColorGradient::template alphaGrad<M, N>(pixBack, pixFront); }\n\n\n    template <class OutputMatrix>\n    static void blendLineShallow(uint32_t col, OutputMatrix& out)\n    {\n        alphaGrad<1, 4>(out.template ref<scale - 1, 0>(), col);\n        alphaGrad<1, 4>(out.template ref<scale - 2, 2>(), col);\n\n        alphaGrad<3, 4>(out.template ref<scale - 1, 1>(), col);\n        alphaGrad<3, 4>(out.template ref<scale - 2, 3>(), col);\n\n        out.template ref<scale - 1, 2>() = col;\n        out.template ref<scale - 1, 3>() = col;\n    }\n\n    template <class OutputMatrix>\n    static void blendLineSteep(uint32_t col, OutputMatrix& out)\n    {\n        alphaGrad<1, 4>(out.template ref<0, scale - 1>(), col);\n        alphaGrad<1, 4>(out.template ref<2, scale - 2>(), col);\n\n        alphaGrad<3, 4>(out.template ref<1, scale - 1>(), col);\n        alphaGrad<3, 4>(out.template ref<3, scale - 2>(), col);\n\n        out.template ref<2, scale - 1>() = col;\n        out.template ref<3, scale - 1>() = col;\n    }\n\n    template <class OutputMatrix>\n    static void blendLineSteepAndShallow(uint32_t col, OutputMatrix& out)\n    {\n        alphaGrad<3, 4>(out.template ref<3, 1>(), col);\n        alphaGrad<3, 4>(out.template ref<1, 3>(), col);\n        alphaGrad<1, 4>(out.template ref<3, 0>(), col);\n        alphaGrad<1, 4>(out.template ref<0, 3>(), col);\n\n        alphaGrad<1, 3>(out.template ref<2, 2>(), col); //[!] fixes 1/4 used in xBR\n\n        out.template ref<3, 3>() = col;\n        out.template ref<3, 2>() = col;\n        out.template ref<2, 3>() = col;\n    }\n\n    template <class OutputMatrix>\n    static void blendLineDiagonal(uint32_t col, OutputMatrix& out)\n    {\n        alphaGrad<1, 2>(out.template ref<scale - 1, scale / 2    >(), col);\n        alphaGrad<1, 2>(out.template ref<scale - 2, scale / 2 + 1>(), col);\n        out.template ref<scale - 1, scale - 1>() = col;\n    }\n\n    template <class OutputMatrix>\n    static void blendCorner(uint32_t col, OutputMatrix& out)\n    {\n        //model a round corner\n        alphaGrad<68, 100>(out.template ref<3, 3>(), col); //exact: 0.6848532563\n        alphaGrad< 9, 100>(out.template ref<3, 2>(), col); //0.08677704501\n        alphaGrad< 9, 100>(out.template ref<2, 3>(), col); //0.08677704501\n    }\n};\n\n\ntemplate <class ColorGradient>\nstruct Scaler5x : public ColorGradient\n{\n    static const int scale = 5;\n\n    template <unsigned int M, unsigned int N> //bring template function into scope for GCC\n    static void alphaGrad(uint32_t& pixBack, uint32_t pixFront) { ColorGradient::template alphaGrad<M, N>(pixBack, pixFront); }\n\n\n    template <class OutputMatrix>\n    static void blendLineShallow(uint32_t col, OutputMatrix& out)\n    {\n        alphaGrad<1, 4>(out.template ref<scale - 1, 0>(), col);\n        alphaGrad<1, 4>(out.template ref<scale - 2, 2>(), col);\n        alphaGrad<1, 4>(out.template ref<scale - 3, 4>(), col);\n\n        alphaGrad<3, 4>(out.template ref<scale - 1, 1>(), col);\n        alphaGrad<3, 4>(out.template ref<scale - 2, 3>(), col);\n\n        out.template ref<scale - 1, 2>() = col;\n        out.template ref<scale - 1, 3>() = col;\n        out.template ref<scale - 1, 4>() = col;\n        out.template ref<scale - 2, 4>() = col;\n    }\n\n    template <class OutputMatrix>\n    static void blendLineSteep(uint32_t col, OutputMatrix& out)\n    {\n        alphaGrad<1, 4>(out.template ref<0, scale - 1>(), col);\n        alphaGrad<1, 4>(out.template ref<2, scale - 2>(), col);\n        alphaGrad<1, 4>(out.template ref<4, scale - 3>(), col);\n\n        alphaGrad<3, 4>(out.template ref<1, scale - 1>(), col);\n        alphaGrad<3, 4>(out.template ref<3, scale - 2>(), col);\n\n        out.template ref<2, scale - 1>() = col;\n        out.template ref<3, scale - 1>() = col;\n        out.template ref<4, scale - 1>() = col;\n        out.template ref<4, scale - 2>() = col;\n    }\n\n    template <class OutputMatrix>\n    static void blendLineSteepAndShallow(uint32_t col, OutputMatrix& out)\n    {\n        alphaGrad<1, 4>(out.template ref<0, scale - 1>(), col);\n        alphaGrad<1, 4>(out.template ref<2, scale - 2>(), col);\n        alphaGrad<3, 4>(out.template ref<1, scale - 1>(), col);\n\n        alphaGrad<1, 4>(out.template ref<scale - 1, 0>(), col);\n        alphaGrad<1, 4>(out.template ref<scale - 2, 2>(), col);\n        alphaGrad<3, 4>(out.template ref<scale - 1, 1>(), col);\n\n        alphaGrad<2, 3>(out.template ref<3, 3>(), col);\n\n        out.template ref<2, scale - 1>() = col;\n        out.template ref<3, scale - 1>() = col;\n        out.template ref<4, scale - 1>() = col;\n\n        out.template ref<scale - 1, 2>() = col;\n        out.template ref<scale - 1, 3>() = col;\n    }\n\n    template <class OutputMatrix>\n    static void blendLineDiagonal(uint32_t col, OutputMatrix& out)\n    {\n        alphaGrad<1, 8>(out.template ref<scale - 1, scale / 2    >(), col); //conflict with other rotations for this odd scale\n        alphaGrad<1, 8>(out.template ref<scale - 2, scale / 2 + 1>(), col);\n        alphaGrad<1, 8>(out.template ref<scale - 3, scale / 2 + 2>(), col); //\n\n        alphaGrad<7, 8>(out.template ref<4, 3>(), col);\n        alphaGrad<7, 8>(out.template ref<3, 4>(), col);\n\n        out.template ref<4, 4>() = col;\n    }\n\n    template <class OutputMatrix>\n    static void blendCorner(uint32_t col, OutputMatrix& out)\n    {\n        //model a round corner\n        alphaGrad<86, 100>(out.template ref<4, 4>(), col); //exact: 0.8631434088\n        alphaGrad<23, 100>(out.template ref<4, 3>(), col); //0.2306749731\n        alphaGrad<23, 100>(out.template ref<3, 4>(), col); //0.2306749731\n        //alphaGrad<1, 64>(out.template ref<4, 2>(), col); //0.01676812367 -> negligible + avoid conflicts with other rotations for this odd scale\n        //alphaGrad<1, 64>(out.template ref<2, 4>(), col); //0.01676812367\n    }\n};\n\n\ntemplate <class ColorGradient>\nstruct Scaler6x : public ColorGradient\n{\n    static const int scale = 6;\n\n    template <unsigned int M, unsigned int N> //bring template function into scope for GCC\n    static void alphaGrad(uint32_t& pixBack, uint32_t pixFront) { ColorGradient::template alphaGrad<M, N>(pixBack, pixFront); }\n\n\n    template <class OutputMatrix>\n    static void blendLineShallow(uint32_t col, OutputMatrix& out)\n    {\n        alphaGrad<1, 4>(out.template ref<scale - 1, 0>(), col);\n        alphaGrad<1, 4>(out.template ref<scale - 2, 2>(), col);\n        alphaGrad<1, 4>(out.template ref<scale - 3, 4>(), col);\n\n        alphaGrad<3, 4>(out.template ref<scale - 1, 1>(), col);\n        alphaGrad<3, 4>(out.template ref<scale - 2, 3>(), col);\n        alphaGrad<3, 4>(out.template ref<scale - 3, 5>(), col);\n\n        out.template ref<scale - 1, 2>() = col;\n        out.template ref<scale - 1, 3>() = col;\n        out.template ref<scale - 1, 4>() = col;\n        out.template ref<scale - 1, 5>() = col;\n\n        out.template ref<scale - 2, 4>() = col;\n        out.template ref<scale - 2, 5>() = col;\n    }\n\n    template <class OutputMatrix>\n    static void blendLineSteep(uint32_t col, OutputMatrix& out)\n    {\n        alphaGrad<1, 4>(out.template ref<0, scale - 1>(), col);\n        alphaGrad<1, 4>(out.template ref<2, scale - 2>(), col);\n        alphaGrad<1, 4>(out.template ref<4, scale - 3>(), col);\n\n        alphaGrad<3, 4>(out.template ref<1, scale - 1>(), col);\n        alphaGrad<3, 4>(out.template ref<3, scale - 2>(), col);\n        alphaGrad<3, 4>(out.template ref<5, scale - 3>(), col);\n\n        out.template ref<2, scale - 1>() = col;\n        out.template ref<3, scale - 1>() = col;\n        out.template ref<4, scale - 1>() = col;\n        out.template ref<5, scale - 1>() = col;\n\n        out.template ref<4, scale - 2>() = col;\n        out.template ref<5, scale - 2>() = col;\n    }\n\n    template <class OutputMatrix>\n    static void blendLineSteepAndShallow(uint32_t col, OutputMatrix& out)\n    {\n        alphaGrad<1, 4>(out.template ref<0, scale - 1>(), col);\n        alphaGrad<1, 4>(out.template ref<2, scale - 2>(), col);\n        alphaGrad<3, 4>(out.template ref<1, scale - 1>(), col);\n        alphaGrad<3, 4>(out.template ref<3, scale - 2>(), col);\n\n        alphaGrad<1, 4>(out.template ref<scale - 1, 0>(), col);\n        alphaGrad<1, 4>(out.template ref<scale - 2, 2>(), col);\n        alphaGrad<3, 4>(out.template ref<scale - 1, 1>(), col);\n        alphaGrad<3, 4>(out.template ref<scale - 2, 3>(), col);\n\n        out.template ref<2, scale - 1>() = col;\n        out.template ref<3, scale - 1>() = col;\n        out.template ref<4, scale - 1>() = col;\n        out.template ref<5, scale - 1>() = col;\n\n        out.template ref<4, scale - 2>() = col;\n        out.template ref<5, scale - 2>() = col;\n\n        out.template ref<scale - 1, 2>() = col;\n        out.template ref<scale - 1, 3>() = col;\n    }\n\n    template <class OutputMatrix>\n    static void blendLineDiagonal(uint32_t col, OutputMatrix& out)\n    {\n        alphaGrad<1, 2>(out.template ref<scale - 1, scale / 2    >(), col);\n        alphaGrad<1, 2>(out.template ref<scale - 2, scale / 2 + 1>(), col);\n        alphaGrad<1, 2>(out.template ref<scale - 3, scale / 2 + 2>(), col);\n\n        out.template ref<scale - 2, scale - 1>() = col;\n        out.template ref<scale - 1, scale - 1>() = col;\n        out.template ref<scale - 1, scale - 2>() = col;\n    }\n\n    template <class OutputMatrix>\n    static void blendCorner(uint32_t col, OutputMatrix& out)\n    {\n        //model a round corner\n        alphaGrad<97, 100>(out.template ref<5, 5>(), col); //exact: 0.9711013910\n        alphaGrad<42, 100>(out.template ref<4, 5>(), col); //0.4236372243\n        alphaGrad<42, 100>(out.template ref<5, 4>(), col); //0.4236372243\n        alphaGrad< 6, 100>(out.template ref<5, 3>(), col); //0.05652034508\n        alphaGrad< 6, 100>(out.template ref<3, 5>(), col); //0.05652034508\n    }\n};\n\n//------------------------------------------------------------------------------------\n\nstruct ColorDistanceRGB\n{\n    static double dist(uint32_t pix1, uint32_t pix2, double /*luminanceWeight*/)\n    {\n        return DistYCbCrBuffer::dist(pix1, pix2);\n\n        //if (pix1 == pix2) //about 4% perf boost\n        //    return 0;\n        //return distYCbCr(pix1, pix2, luminanceWeight);\n    }\n};\n\nstruct ColorDistanceARGB\n{\n    static double dist(uint32_t pix1, uint32_t pix2, double /*luminanceWeight*/)\n    {\n        const double a1 = getAlpha(pix1) / 255.0 ;\n        const double a2 = getAlpha(pix2) / 255.0 ;\n        /*\n        Requirements for a color distance handling alpha channel: with a1, a2 in [0, 1]\n\n        \t1. if a1 = a2, distance should be: a1 * distYCbCr()\n        \t2. if a1 = 0,  distance should be: a2 * distYCbCr(black, white) = a2 * 255\n        \t3. if a1 = 1,  ??? maybe: 255 * (1 - a2) + a2 * distYCbCr()\n        */\n\n        //return std::min(a1, a2) * DistYCbCrBuffer::dist(pix1, pix2) + 255 * abs(a1 - a2);\n        //=> following code is 15% faster:\n        const double d = DistYCbCrBuffer::dist(pix1, pix2);\n        if (a1 < a2)\n            return a1 * d + 255 * (a2 - a1);\n        else\n            return a2 * d + 255 * (a1 - a2);\n\n        //alternative? return std::sqrt(a1 * a2 * square(DistYCbCrBuffer::dist(pix1, pix2)) + square(255 * (a1 - a2)));\n    }\n};\n\n\nstruct ColorGradientRGB\n{\n    template <unsigned int M, unsigned int N>\n    static void alphaGrad(uint32_t& pixBack, uint32_t pixFront)\n    {\n        pixBack = gradientRGB<M, N>(pixFront, pixBack);\n    }\n};\n\nstruct ColorGradientARGB\n{\n    template <unsigned int M, unsigned int N>\n    static void alphaGrad(uint32_t& pixBack, uint32_t pixFront)\n    {\n        pixBack = gradientARGB<M, N>(pixFront, pixBack);\n    }\n};\n}\n\n\nvoid xbrz::scale(size_t factor, const uint32_t* src, uint32_t* trg, int srcWidth, int srcHeight, ColorFormat colFmt, const xbrz::ScalerCfg& cfg, int yFirst, int yLast)\n{\n    switch (colFmt)\n    {\n        case ARGB:\n            switch (factor)\n            {\n                case 2:\n                    return scaleImage<Scaler2x<ColorGradientARGB>, ColorDistanceARGB>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);\n                case 3:\n                    return scaleImage<Scaler3x<ColorGradientARGB>, ColorDistanceARGB>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);\n                case 4:\n                    return scaleImage<Scaler4x<ColorGradientARGB>, ColorDistanceARGB>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);\n                case 5:\n                    return scaleImage<Scaler5x<ColorGradientARGB>, ColorDistanceARGB>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);\n                case 6:\n                    return scaleImage<Scaler6x<ColorGradientARGB>, ColorDistanceARGB>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);\n            }\n            break;\n\n        case RGB:\n            switch (factor)\n            {\n                case 2:\n                    return scaleImage<Scaler2x<ColorGradientRGB>, ColorDistanceRGB>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);\n                case 3:\n                    return scaleImage<Scaler3x<ColorGradientRGB>, ColorDistanceRGB>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);\n                case 4:\n                    return scaleImage<Scaler4x<ColorGradientRGB>, ColorDistanceRGB>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);\n                case 5:\n                    return scaleImage<Scaler5x<ColorGradientRGB>, ColorDistanceRGB>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);\n                case 6:\n                    return scaleImage<Scaler6x<ColorGradientRGB>, ColorDistanceRGB>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);\n            }\n            break;\n    }\n    assert(false);\n}\n\n\nbool xbrz::equalColorTest(uint32_t col1, uint32_t col2, ColorFormat colFmt, double luminanceWeight, double equalColorTolerance)\n{\n    switch (colFmt)\n    {\n        case ARGB:\n            return ColorDistanceARGB::dist(col1, col2, luminanceWeight) < equalColorTolerance;\n\n        case RGB:\n            return ColorDistanceRGB::dist(col1, col2, luminanceWeight) < equalColorTolerance;\n    }\n    assert(false);\n    return false;\n}\n\n\nvoid xbrz::nearestNeighborScale(const uint32_t* src, int srcWidth, int srcHeight, int srcPitch,\n                                uint32_t* trg, int trgWidth, int trgHeight, int trgPitch,\n                                SliceType st, int yFirst, int yLast)\n{\n    if (srcPitch < srcWidth * static_cast<int>(sizeof(uint32_t))  ||\n        trgPitch < trgWidth * static_cast<int>(sizeof(uint32_t)))\n    {\n        assert(false);\n        return;\n    }\n\n    switch (st)\n    {\n        case NN_SCALE_SLICE_SOURCE:\n            //nearest-neighbor (going over source image - fast for upscaling, since source is read only once\n            yFirst = std::max(yFirst, 0);\n            yLast  = std::min(yLast, srcHeight);\n            if (yFirst >= yLast || trgWidth <= 0 || trgHeight <= 0) return;\n\n            for (int y = yFirst; y < yLast; ++y)\n            {\n                //mathematically: ySrc = floor(srcHeight * yTrg / trgHeight)\n                // => search for integers in: [ySrc, ySrc + 1) * trgHeight / srcHeight\n\n                //keep within for loop to support MT input slices!\n                const int yTrg_first = ( y      * trgHeight + srcHeight - 1) / srcHeight; //=ceil(y * trgHeight / srcHeight)\n                const int yTrg_last  = ((y + 1) * trgHeight + srcHeight - 1) / srcHeight; //=ceil(((y + 1) * trgHeight) / srcHeight)\n                const int blockHeight = yTrg_last - yTrg_first;\n\n                if (blockHeight > 0)\n                {\n                    const uint32_t* srcLine = byteAdvance(src, y * srcPitch);\n                    uint32_t* trgLine  = byteAdvance(trg, yTrg_first * trgPitch);\n                    int xTrg_first = 0;\n\n                    for (int x = 0; x < srcWidth; ++x)\n                    {\n                        int xTrg_last = ((x + 1) * trgWidth + srcWidth - 1) / srcWidth;\n                        const int blockWidth = xTrg_last - xTrg_first;\n                        if (blockWidth > 0)\n                        {\n                            xTrg_first = xTrg_last;\n                            fillBlock(trgLine, trgPitch, srcLine[x], blockWidth, blockHeight);\n                            trgLine += blockWidth;\n                        }\n                    }\n                }\n            }\n            break;\n\n        case NN_SCALE_SLICE_TARGET:\n            //nearest-neighbor (going over target image - slow for upscaling, since source is read multiple times missing out on cache! Fast for similar image sizes!)\n            yFirst = std::max(yFirst, 0);\n            yLast  = std::min(yLast, trgHeight);\n            if (yFirst >= yLast || srcHeight <= 0 || srcWidth <= 0) return;\n\n            for (int y = yFirst; y < yLast; ++y)\n            {\n                uint32_t* trgLine = byteAdvance(trg, y * trgPitch);\n                const int ySrc = srcHeight * y / trgHeight;\n                const uint32_t* srcLine = byteAdvance(src, ySrc * srcPitch);\n                for (int x = 0; x < trgWidth; ++x)\n                {\n                    const int xSrc = srcWidth * x / trgWidth;\n                    trgLine[x] = srcLine[xSrc];\n                }\n            }\n            break;\n    }\n}\n"
  },
  {
    "path": "src/Engine/Scalers/xbrz.h",
    "content": "// ****************************************************************************\n// * This file is part of the HqMAME project. It is distributed under         *\n// * GNU General Public License: http://www.gnu.org/licenses/gpl-3.0          *\n// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved          *\n// *                                                                          *\n// * Additionally and as a special exception, the author gives permission     *\n// * to link the code of this program with the MAME library (or with modified *\n// * versions of MAME that use the same license as MAME), and distribute      *\n// * linked combinations including the two. You must obey the GNU General     *\n// * Public License in all respects for all of the code used other than MAME. *\n// * If you modify this file, you may extend this exception to your version   *\n// * of the file, but you are not obligated to do so. If you do not wish to   *\n// * do so, delete this exception statement from your version.                *\n// ****************************************************************************\n\n#ifndef XBRZ_HEADER_3847894708239054\n#define XBRZ_HEADER_3847894708239054\n\n#include <cstddef> //size_t\n#include <stdint.h> //uint32_t\n#include <limits>\n#include \"config.h\"\n\nnamespace xbrz\n{\n/*\n-------------------------------------------------------------------------\n| xBRZ: \"Scale by rules\" - high quality image upscaling filter by Zenju |\n-------------------------------------------------------------------------\nusing a modified approach of xBR:\nhttp://board.byuu.org/viewtopic.php?f=10&t=2248\n- new rule set preserving small image features\n- highly optimized for performance\n- support alpha channel\n- support multithreading\n- support 64-bit architectures\n- support processing image slices\n- support scaling up to 6xBRZ\n*/\n\nenum ColorFormat //from high bits -> low bits, 8 bit per channel\n{\n    RGB,  //8 bit for each red, green, blue, upper 8 bits unused\n    ARGB, //including alpha channel, BGRA byte order on little-endian machines\n};\n\n/*\n-> map source (srcWidth * srcHeight) to target (scale * width x scale * height) image, optionally processing a half-open slice of rows [yFirst, yLast) only\n-> support for source/target pitch in bytes!\n-> if your emulator changes only a few image slices during each cycle (e.g. DOSBox) then there's no need to run xBRZ on the complete image:\n   Just make sure you enlarge the source image slice by 2 rows on top and 2 on bottom (this is the additional range the xBRZ algorithm is using during analysis)\n   Caveat: If there are multiple changed slices, make sure they do not overlap after adding these additional rows in order to avoid a memory race condition\n   in the target image data if you are using multiple threads for processing each enlarged slice!\n\nTHREAD-SAFETY: - parts of the same image may be scaled by multiple threads as long as the [yFirst, yLast) ranges do not overlap!\n               - there is a minor inefficiency for the first row of a slice, so avoid processing single rows only; suggestion: process 8-16 rows at least\n*/\nvoid scale(size_t factor, //valid range: 2 - 6\n           const uint32_t* src, uint32_t* trg, int srcWidth, int srcHeight,\n           ColorFormat colFmt,\n           const ScalerCfg& cfg = ScalerCfg(),\n           int yFirst = 0, int yLast = std::numeric_limits<int>::max()); //slice of source image\n\nvoid nearestNeighborScale(const uint32_t* src, int srcWidth, int srcHeight,\n                          uint32_t* trg, int trgWidth, int trgHeight);\n\nenum SliceType\n{\n    NN_SCALE_SLICE_SOURCE,\n    NN_SCALE_SLICE_TARGET,\n};\nvoid nearestNeighborScale(const uint32_t* src, int srcWidth, int srcHeight, int srcPitch, //pitch in bytes!\n                          uint32_t* trg, int trgWidth, int trgHeight, int trgPitch,\n                          SliceType st, int yFirst, int yLast);\n\n//parameter tuning\nbool equalColorTest(uint32_t col1, uint32_t col2, ColorFormat colFmt, double luminanceWeight, double equalColorTolerance);\n\n\n\n\n\n//########################### implementation ###########################\ninline\nvoid nearestNeighborScale(const uint32_t* src, int srcWidth, int srcHeight,\n                          uint32_t* trg, int trgWidth, int trgHeight)\n{\n    nearestNeighborScale(src, srcWidth, srcHeight, srcWidth * sizeof(uint32_t),\n                         trg, trgWidth, trgHeight, trgWidth * sizeof(uint32_t),\n                         NN_SCALE_SLICE_TARGET, 0, trgHeight);\n}\n}\n\n#endif\n"
  },
  {
    "path": "src/Engine/Screen.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Screen.h\"\n#include <algorithm>\n#include <sstream>\n#include <cmath>\n#include <iomanip>\n#include <climits>\n#include <cstdio>\n#include \"../lodepng.h\"\n#include \"Exception.h\"\n#include \"Surface.h\"\n#include \"Logger.h\"\n#include \"Action.h\"\n#include \"Options.h\"\n#include \"CrossPlatform.h\"\n#include \"FileMap.h\"\n#include \"Zoom.h\"\n#include \"Timer.h\"\n#include <SDL.h>\n#include <algorithm>\n\nnamespace OpenXcom\n{\n\nconst int Screen::ORIGINAL_WIDTH = 320;\nconst int Screen::ORIGINAL_HEIGHT = 200;\n\nstatic const int VIDEO_WINDOW_POS_LEN = 40;\nstatic char VIDEO_WINDOW_POS[VIDEO_WINDOW_POS_LEN];\n\nstatic const char* SDL_VIDEO_CENTERED_UNSET = \"SDL_VIDEO_CENTERED=\";\nstatic const char* SDL_VIDEO_CENTERED_CENTER = \"SDL_VIDEO_CENTERED=center\";\nstatic const char* SDL_VIDEO_WINDOW_POS_UNSET = \"SDL_VIDEO_WINDOW_POS=\";\n\n/**\n * Sets up all the internal display flags depending on\n * the current video settings.\n */\nvoid Screen::makeVideoFlags()\n{\n\t_flags = SDL_HWSURFACE|SDL_DOUBLEBUF|SDL_HWPALETTE;\n\tif (Options::asyncBlit)\n\t{\n\t\t_flags |= SDL_ASYNCBLIT;\n\t}\n\tif (useOpenGL())\n\t{\n\t\t_flags = SDL_OPENGL;\n\t\tSDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );\n\t\tSDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 );\n\t\tSDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );\n\t\tSDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );\n\t\tSDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );\n\t}\n\tif (Options::allowResize)\n\t{\n\t\t_flags |= SDL_RESIZABLE;\n\t}\n\n\t// Handle window positioning\n\tif (!Options::fullscreen && Options::rootWindowedMode)\n\t{\n\t\tsnprintf(VIDEO_WINDOW_POS, VIDEO_WINDOW_POS_LEN, \"SDL_VIDEO_WINDOW_POS=%d,%d\", Options::windowedModePositionX, Options::windowedModePositionY);\n\t\tSDL_putenv(VIDEO_WINDOW_POS);\n\t\tSDL_putenv((char *)SDL_VIDEO_CENTERED_UNSET);\n\t}\n\telse if (Options::borderless)\n\t{\n\t\tSDL_putenv((char *)SDL_VIDEO_WINDOW_POS_UNSET);\n\t\tSDL_putenv((char *)SDL_VIDEO_CENTERED_CENTER);\n\t}\n\telse\n\t{\n\t\tSDL_putenv((char *)SDL_VIDEO_WINDOW_POS_UNSET);\n\t\tSDL_putenv((char *)SDL_VIDEO_CENTERED_UNSET);\n\t}\n\n\t// Handle display mode\n\tif (Options::fullscreen)\n\t{\n\t\t_flags |= SDL_FULLSCREEN;\n\t}\n\tif (Options::borderless)\n\t{\n\t\t_flags |= SDL_NOFRAME;\n\t}\n\n\t_bpp = (use32bitScaler() || useOpenGL()) ? 32 : 8;\n\t_baseWidth = Options::baseXResolution;\n\t_baseHeight = Options::baseYResolution;\n}\n\n\n/**\n * Initializes a new display screen for the game to render contents to.\n * The screen is set up based on the current options.\n */\nScreen::Screen() : _baseWidth(ORIGINAL_WIDTH), _baseHeight(ORIGINAL_HEIGHT), _scaleX(1.0), _scaleY(1.0), _flags(0), _numColors(0), _firstColor(0), _pushPalette(false), _flickerFix(false)\n{\n\t_flickerFix = Options::oxceEnablePaletteFlickerFix;\n\n\tresetDisplay();\n\tmemset(deferredPalette, 0, 256*sizeof(SDL_Color));\n}\n\n/**\n * Deletes the buffer from memory. The display screen itself\n * is automatically freed once SDL shuts down.\n */\nScreen::~Screen()\n{\n\n}\n\n/**\n * Returns the screen's internal buffer surface. Any\n * contents that need to be shown will be blitted to this.\n * @return Pointer to the buffer surface.\n */\nSDL_Surface *Screen::getSurface()\n{\n\t_pushPalette = true;\n\treturn _surface.get();\n}\n\n/**\n * Handles screen key shortcuts.\n * @param action Pointer to an action.\n */\nvoid Screen::handle(Action *action)\n{\n\tif (Options::debug)\n\t{\n\t\tif (action->getDetails()->type == SDL_KEYDOWN && action->getDetails()->key.keysym.sym == SDLK_F8 && (SDL_GetModState() & KMOD_ALT) != 0)\n\t\t{\n\t\t\tswitch(Timer::gameSlowSpeed)\n\t\t\t{\n\t\t\t\tcase 1: Timer::gameSlowSpeed = 5; break;\n\t\t\t\tcase 5: Timer::gameSlowSpeed = 15; break;\n\t\t\t\tdefault: Timer::gameSlowSpeed = 1; break;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (action->getDetails()->type == SDL_KEYDOWN && action->getDetails()->key.keysym.sym == SDLK_RETURN && (SDL_GetModState() & KMOD_ALT) != 0)\n\t{\n\t\tOptions::fullscreen = !Options::fullscreen;\n\t\tresetDisplay();\n\t}\n\telse if (action->getDetails()->type == SDL_KEYDOWN && action->getDetails()->key.keysym.sym == Options::keyScreenshot)\n\t{\n\t\tstd::ostringstream ss;\n\t\tint i = 0;\n\t\tdo\n\t\t{\n\t\t\tss.str(\"\");\n\t\t\tss << Options::getMasterUserFolder() << \"screen\" << std::setfill('0') << std::setw(3) << i << \".png\";\n\t\t\ti++;\n\t\t}\n\t\twhile (CrossPlatform::fileExists(ss.str()));\n\t\tscreenshot(ss.str());\n\t\treturn;\n\t}\n}\n\n\n/**\n * Renders the buffer's contents onto the screen, applying\n * any necessary filters or conversions in the process.\n * If the scaling factor is bigger than 1, the entire contents\n * of the buffer are resized by that factor (eg. 2 = doubled)\n * before being put on screen.\n */\nvoid Screen::flip()\n{\n\t// perform any requested palette update\n\tif (_flickerFix && _pushPalette && _numColors && _screen->format->BitsPerPixel == 8)\n\t{\n\t\tif (_screen->format->BitsPerPixel == 8 && SDL_SetColors(_screen, &(deferredPalette[_firstColor]), _firstColor, _numColors) == 0)\n\t\t{\n\t\t\tLog(LOG_DEBUG) << \"Display palette doesn't match requested palette\";\n\t\t}\n\t\t_numColors = 0;\n\t\t_pushPalette = false;\n\t}\n\n\tif (getWidth() != _baseWidth || getHeight() != _baseHeight || useOpenGL())\n\t{\n\t\tZoom::flipWithZoom(_surface.get(), _screen, _topBlackBand, _bottomBlackBand, _leftBlackBand, _rightBlackBand, &glOutput);\n\t}\n\telse\n\t{\n\t\tSDL_BlitSurface(_surface.get(), 0, _screen, 0);\n\t}\n\n\t// perform any requested palette update\n\tif (!_flickerFix && _pushPalette && _numColors && _screen->format->BitsPerPixel == 8)\n\t{\n\t\tif (_screen->format->BitsPerPixel == 8 && SDL_SetColors(_screen, &(deferredPalette[_firstColor]), _firstColor, _numColors) == 0)\n\t\t{\n\t\t\tLog(LOG_DEBUG) << \"Display palette doesn't match requested palette\";\n\t\t}\n\t\t_numColors = 0;\n\t\t_pushPalette = false;\n\t}\n\n\n\n\tif (SDL_Flip(_screen) == -1)\n\t{\n\t\tthrow Exception(SDL_GetError());\n\t}\n}\n\n/**\n * Clears all the contents out of the internal buffer.\n */\nvoid Screen::clear()\n{\n\tSurface::CleanSdlSurface(_surface.get());\n\tSurface::CleanSdlSurface(_screen);\n}\n\n/**\n * Changes the 8bpp palette used to render the screen's contents.\n * @param colors Pointer to the set of colors.\n * @param firstcolor Offset of the first color to replace.\n * @param ncolors Amount of colors to replace.\n * @param immediately Apply palette changes immediately, otherwise wait for next blit.\n */\nvoid Screen::setPalette(const SDL_Color* colors, int firstcolor, int ncolors, bool immediately)\n{\n\tif (_numColors && (_numColors != ncolors) && (_firstColor != firstcolor))\n\t{\n\t\t// an initial palette setup has not been committed to the screen yet\n\t\t// just update it with whatever colors are being sent now\n\t\tmemmove(&(deferredPalette[firstcolor]), colors, sizeof(SDL_Color)*ncolors);\n\t\t_numColors = 256; // all the use cases are just a full palette with 16-color follow-ups\n\t\t_firstColor = 0;\n\t}\n\telse\n\t{\n\t\tmemmove(&(deferredPalette[firstcolor]), colors, sizeof(SDL_Color) * ncolors);\n\t\t_numColors = ncolors;\n\t\t_firstColor = firstcolor;\n\t}\n\n\tSDL_SetColors(_surface.get(), const_cast<SDL_Color *>(colors), firstcolor, ncolors);\n\n\t// defer actual update of screen until SDL_Flip()\n\tif (immediately && _screen->format->BitsPerPixel == 8 && SDL_SetColors(_screen, const_cast<SDL_Color *>(colors), firstcolor, ncolors) == 0)\n\t{\n\t\tLog(LOG_DEBUG) << \"Display palette doesn't match requested palette\";\n\t}\n\n\t// Sanity check\n\t/*\n\tSDL_Color *newcolors = _screen->format->palette->colors;\n\tfor (int i = firstcolor, j = 0; i < firstcolor + ncolors; i++, j++)\n\t{\n\t\tLog(LOG_DEBUG) << (int)newcolors[i].r << \" - \" << (int)newcolors[i].g << \" - \" << (int)newcolors[i].b;\n\t\tLog(LOG_DEBUG) << (int)colors[j].r << \" + \" << (int)colors[j].g << \" + \" << (int)colors[j].b;\n\t\tif (newcolors[i].r != colors[j].r ||\n\t\t\tnewcolors[i].g != colors[j].g ||\n\t\t\tnewcolors[i].b != colors[j].b)\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"Display palette doesn't match requested palette\";\n\t\t\tbreak;\n\t\t}\n\t}\n\t*/\n}\n\n/**\n * Returns the screen's 8bpp palette.\n * @return Pointer to the palette's colors.\n */\nSDL_Color *Screen::getPalette() const\n{\n\treturn (SDL_Color*)deferredPalette;\n}\n\n/**\n * Returns the width of the screen.\n * @return Width in pixels.\n */\nint Screen::getWidth() const\n{\n\treturn _screen->w;\n}\n\n/**\n * Returns the height of the screen.\n * @return Height in pixels\n */\nint Screen::getHeight() const\n{\n\treturn _screen->h;\n}\n\n/**\n * Resets the screen surfaces based on the current display options,\n * as they don't automatically take effect.\n * @param resetVideo Reset display surface.\n */\nvoid Screen::resetDisplay(bool resetVideo, bool noShaders)\n{\n#if defined __linux__ || defined _WIN32 || defined  __CYGWIN__\n\tUint32 oldFlags = _flags;\n#endif\n\n\tint width = Options::displayWidth;\n\tint height = Options::displayHeight;\n\tmakeVideoFlags();\n\n\tif (!_surface || (_surface->format->BitsPerPixel != _bpp ||\n\t\t_surface->w != _baseWidth ||\n\t\t_surface->h != _baseHeight)) // don't reallocate _surface if not necessary, it's a waste of CPU cycles\n\t{\n\t\tif (_bpp == 32)\n\t\t{\n\t\t\tstd::tie(_buffer, _surface) = Surface::NewPair32Bit(_baseWidth, _baseHeight);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tstd::tie(_buffer, _surface) = Surface::NewPair8Bit(_baseWidth, _baseHeight);\n\t\t}\n\n\t\tif (_surface->format->BitsPerPixel == 8)\n\t\t{\n\t\t\tSDL_SetColors(_surface.get(), deferredPalette, 0, 255);\n\t\t}\n\t}\n\tSDL_SetColorKey(_surface.get(), 0, 0); // turn off color key!\n\n\tif (resetVideo || _screen->format->BitsPerPixel != _bpp)\n\t{\n\t\tLog(LOG_INFO) << \"Attempting to set display to \" << width << \"x\" << height << \"x\" << _bpp << \"...\";\n\n#if defined __linux__ || defined _WIN32 || defined  __CYGWIN__\n\t\t// Workaround for segfault when switching to opengl\n\t\tif ((oldFlags & SDL_OPENGL) != (_flags & SDL_OPENGL))\n\t\t{\n\t\t\tUint8 cursor = 0;\n\t\t\tchar *_oldtitle = 0;\n\t\t\tSDL_WM_GetCaption(&_oldtitle, NULL);\n\t\t\tstd::string title(_oldtitle);\n\t\t\tSDL_QuitSubSystem(SDL_INIT_VIDEO);\n\t\t\tSDL_InitSubSystem(SDL_INIT_VIDEO);\n\n\t\t\t// recreate operations done by `Game::Game` constructor\n\t\t\tSDL_ShowCursor(SDL_ENABLE);\n\t\t\tSDL_EnableUNICODE(1);\n\t\t\tSDL_WM_SetCaption(title.c_str(), 0);\n\t\t\tSDL_WM_GrabInput(Options::captureMouse);\n\t\t\tSDL_SetCursor(SDL_CreateCursor(&cursor, &cursor, 1,1,0,0));\n\t\t}\n#endif\n\t\t_screen = SDL_SetVideoMode(width, height, _bpp, _flags);\n\t\tif (_screen == 0)\n\t\t{\n\t\t\tLog(LOG_ERROR) << SDL_GetError();\n\t\t\tLog(LOG_INFO) << \"Attempting to set display to default resolution...\";\n\t\t\t_screen = SDL_SetVideoMode(640, 400, _bpp, _flags);\n\t\t\tif (_screen == 0)\n\t\t\t{\n\t\t\t\tif (_flags & SDL_OPENGL)\n\t\t\t\t{\n\t\t\t\t\tOptions::useOpenGL = false;\n\t\t\t\t}\n\t\t\t\tthrow Exception(SDL_GetError());\n\t\t\t}\n\t\t}\n\t\tLog(LOG_INFO) << \"Display set to \" << getWidth() << \"x\" << getHeight() << \"x\" << (int)_screen->format->BitsPerPixel << \".\";\n\t}\n\telse\n\t{\n\t\tclear();\n\t}\n\n\tOptions::displayWidth = getWidth();\n\tOptions::displayHeight = getHeight();\n\t_scaleX = getWidth() / (double)_baseWidth;\n\t_scaleY = getHeight() / (double)_baseHeight;\n\n\tdouble pixelRatioY = 1.0;\n\tif (Options::nonSquarePixelRatio && !Options::allowResize)\n\t{\n\t\tpixelRatioY = 1.2;\n\t}\n\tbool cursorInBlackBands;\n\tif (!Options::keepAspectRatio)\n\t{\n\t\tcursorInBlackBands = false;\n\t}\n\telse if (Options::fullscreen)\n\t{\n\t\tcursorInBlackBands = Options::cursorInBlackBandsInFullscreen;\n\t}\n\telse if (!Options::borderless)\n\t{\n\t\tcursorInBlackBands = Options::cursorInBlackBandsInWindow;\n\t}\n\telse\n\t{\n\t\tcursorInBlackBands = Options::cursorInBlackBandsInBorderlessWindow;\n\t}\n\n\tif (_scaleX > _scaleY && Options::keepAspectRatio)\n\t{\n\t\tint targetWidth = (int)floor(_scaleY * (double)_baseWidth);\n\t\t_topBlackBand = _bottomBlackBand = 0;\n\t\t_leftBlackBand = (getWidth() - targetWidth) / 2;\n\t\tif (_leftBlackBand < 0)\n\t\t{\n\t\t\t_leftBlackBand = 0;\n\t\t}\n\t\t_rightBlackBand = getWidth() - targetWidth - _leftBlackBand;\n\t\t_cursorTopBlackBand = 0;\n\n\t\tif (cursorInBlackBands)\n\t\t{\n\t\t\t_scaleX = _scaleY;\n\t\t\t_cursorLeftBlackBand = _leftBlackBand;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_cursorLeftBlackBand = 0;\n\t\t}\n\t}\n\telse if (_scaleY > _scaleX && Options::keepAspectRatio)\n\t{\n\t\tint targetHeight = (int)floor(_scaleX * (double)_baseHeight * pixelRatioY);\n\t\t_topBlackBand = (getHeight() - targetHeight) / 2;\n\t\tif (_topBlackBand < 0)\n\t\t{\n\t\t\t_topBlackBand = 0;\n\t\t}\n\t\t_bottomBlackBand = getHeight() - targetHeight - _topBlackBand;\n\t\tif (_bottomBlackBand < 0)\n\t\t{\n\t\t\t_bottomBlackBand = 0;\n\t\t}\n\t\t_leftBlackBand = _rightBlackBand = 0;\n\t\t_cursorLeftBlackBand = 0;\n\n\t\tif (cursorInBlackBands)\n\t\t{\n\t\t\t_scaleY = _scaleX;\n\t\t\t_cursorTopBlackBand = _topBlackBand;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_cursorTopBlackBand = 0;\n\t\t}\n\t}\n\telse\n\t{\n\t\t_topBlackBand = _bottomBlackBand = _leftBlackBand = _rightBlackBand = _cursorTopBlackBand = _cursorLeftBlackBand = 0;\n\t}\n\n\tif (useOpenGL())\n\t{\n#ifndef __NO_OPENGL\n\t\tOpenGL::checkErrors = Options::checkOpenGLErrors;\n\t\tglOutput.init(_baseWidth, _baseHeight);\n\t\tglOutput.linear = Options::useOpenGLSmoothing; // setting from shader file will override this, though\n\t\tif (!noShaders && FileMap::fileExists(Options::useOpenGLShader))\n\t\t{\n\t\t\tif (!glOutput.set_shader(Options::useOpenGLShader.c_str()))\n\t\t\t{\n\t\t\t\tOptions::useOpenGLShader = \"\";\n\t\t\t}\n\t\t}\n\t\tglOutput.setVSync(Options::vSyncForOpenGL);\n#endif\n\t}\n\n\tif (_screen->format->BitsPerPixel == 8)\n\t{\n\t\tsetPalette(getPalette());\n\t}\n}\n\n/**\n * Returns the screen's X scale.\n * @return Scale factor.\n */\ndouble Screen::getXScale() const\n{\n\treturn _scaleX;\n}\n\n/**\n * Returns the screen's Y scale.\n * @return Scale factor.\n */\ndouble Screen::getYScale() const\n{\n\treturn _scaleY;\n}\n\n/**\n * Returns the screen's top black forbidden to cursor band's height.\n * @return Height in pixel.\n */\nint Screen::getCursorTopBlackBand() const\n{\n\treturn _cursorTopBlackBand;\n}\n\n/**\n * Returns the screen's left black forbidden to cursor band's width.\n * @return Width in pixel.\n */\nint Screen::getCursorLeftBlackBand() const\n{\n\treturn _cursorLeftBlackBand;\n}\n\n/**\n * Saves a screenshot of the screen's contents.\n * @param filename Filename of the PNG file.\n */\nvoid Screen::screenshot(const std::string &filename) const\n{\n\tSDL_Surface *screenshot = SDL_AllocSurface(0, getWidth() - getWidth()%4, getHeight(), 24, 0xff, 0xff00, 0xff0000, 0);\n\n\tif (useOpenGL())\n\t{\n#ifndef __NO_OPENGL\n\t\tGLenum format = GL_RGB;\n\n\t\tfor (int y = 0; y < getHeight(); ++y)\n\t\t{\n\t\t\tglReadPixels(0, getHeight()-(y+1), getWidth() - getWidth()%4, 1, format, GL_UNSIGNED_BYTE, ((Uint8*)screenshot->pixels) + y*screenshot->pitch);\n\t\t}\n\t\tglErrorCheck();\n#endif\n\t}\n\telse\n\t{\n\t\tSDL_BlitSurface(_screen, 0, screenshot, 0);\n\t}\n\tstd::vector<unsigned char> out;\n\tif (_screen->format->BitsPerPixel == 8 && Options::oxceRawScreenShots)\n\t{\n\t\tSDL_Color *palette = getPalette();\n\t\tlodepng::State state;\n\t\tfor (size_t i = 0; i < 256; ++i)\n\t\t{\n\t\t\tSDL_Color color = palette[i];\n\t\t\tlodepng_palette_add(&state.info_png.color, color.r, color.g, color.b, 255);\n\t\t\tlodepng_palette_add(&state.info_raw, color.r, color.g, color.b, 255);\n\t\t}\n\t\tstate.info_png.color.colortype = LCT_PALETTE; //if you comment this line, and create the above palette in info_raw instead, then you get the same image in a RGBA PNG.\n\t\tstate.info_png.color.bitdepth = 8;\n\t\tstate.info_raw.colortype = LCT_PALETTE;\n\t\tstate.info_raw.bitdepth = 8;\n\t\tstate.encoder.auto_convert = 0; //we specify ourselves exactly what output PNG color mode we want\n\t\tunsigned error = lodepng::encode(out, (const unsigned char *)(_surface->pixels), _surface->w, _surface->h, state);\n\t\tif (error)\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"Saving to PNG failed: \" << lodepng_error_text(error);\n\t\t}\n\t}\n\telse\n\t{\n\t\tunsigned error = lodepng::encode(out, (const unsigned char *)(screenshot->pixels), getWidth() - getWidth()%4, getHeight(), LCT_RGB);\n\t\tif (error)\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"Saving to PNG failed: \" << lodepng_error_text(error);\n\t\t}\n\t}\n\n\tSDL_FreeSurface(screenshot);\n\n\tCrossPlatform::writeFile(filename, out);\n}\n\n\n/**\n * Check whether a 32bpp scaler has been selected.\n * @return if it is enabled with a compatible resolution.\n */\nbool Screen::use32bitScaler()\n{\n\tint w = Options::displayWidth;\n\tint h = Options::displayHeight;\n\tint baseW = Options::baseXResolution;\n\tint baseH = Options::baseYResolution;\n\tint maxScale = 0;\n\n\tif (Options::useHQXFilter)\n\t{\n\t\tmaxScale = 4;\n\t}\n\telse if (Options::useXBRZFilter)\n\t{\n\t\tmaxScale = 6;\n\t}\n\n\tfor (int i = 2; i <= maxScale; i++)\n\t{\n\t\tif (w == baseW * i && h == baseH * i)\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Check if OpenGL is enabled.\n * @return if it is enabled.\n */\nbool Screen::useOpenGL()\n{\n#ifdef __NO_OPENGL\n\treturn false;\n#else\n\treturn Options::useOpenGL;\n#endif\n}\n\n/**\n * Gets the Horizontal offset from the mid-point of the screen, in pixels.\n * @return the horizontal offset.\n */\nint Screen::getDX() const\n{\n\treturn (_baseWidth - ORIGINAL_WIDTH) / 2;\n}\n\n/**\n * Gets the Vertical offset from the mid-point of the screen, in pixels.\n * @return the vertical offset.\n */\nint Screen::getDY() const\n{\n\treturn (_baseHeight - ORIGINAL_HEIGHT) / 2;\n}\n\n/**\n * Changes a given scale, and if necessary, switch the current base resolution.\n * @param type the new scale level.\n * @param width reference to which x scale to adjust.\n * @param height reference to which y scale to adjust.\n * @param change should we change the current scale.\n */\nvoid Screen::updateScale(int type, int &width, int &height, bool change)\n{\n\tdouble pixelRatioY = 1.0;\n\n\tif (Options::nonSquarePixelRatio)\n\t{\n\t\tpixelRatioY = 1.2;\n\t}\n\n\tswitch (type)\n\t{\n\tcase SCALE_15X:\n\t\twidth = Screen::ORIGINAL_WIDTH * 1.5;\n\t\theight = Screen::ORIGINAL_HEIGHT * 1.5;\n\t\tbreak;\n\tcase SCALE_2X:\n\t\twidth = Screen::ORIGINAL_WIDTH * 2;\n\t\theight = Screen::ORIGINAL_HEIGHT * 2;\n\t\tbreak;\n\tcase SCALE_SCREEN_DIV_10:\n\t\twidth = Options::displayWidth / 10.0;\n\t\theight = Options::displayHeight / pixelRatioY / 10.0;\n\t\tbreak;\n\tcase SCALE_SCREEN_DIV_8:\n\t\twidth = Options::displayWidth / 8.0;\n\t\theight = Options::displayHeight / pixelRatioY / 8.0;\n\t\tbreak;\n\tcase SCALE_SCREEN_DIV_6:\n\t\twidth = Options::displayWidth / 6.0;\n\t\theight = Options::displayHeight / pixelRatioY / 6.0;\n\t\tbreak;\n\tcase SCALE_SCREEN_DIV_5:\n\t\twidth = Options::displayWidth / 5.0;\n\t\theight = Options::displayHeight / pixelRatioY / 5.0;\n\t\tbreak;\n\tcase SCALE_SCREEN_DIV_4:\n\t\twidth = Options::displayWidth / 4.0;\n\t\theight = Options::displayHeight / pixelRatioY / 4.0;\n\t\tbreak;\n\tcase SCALE_SCREEN_DIV_3:\n\t\twidth = Options::displayWidth / 3.0;\n\t\theight = Options::displayHeight / pixelRatioY / 3.0;\n\t\tbreak;\n\tcase SCALE_SCREEN_DIV_2:\n\t\twidth = Options::displayWidth / 2.0;\n\t\theight = Options::displayHeight / pixelRatioY  / 2.0;\n\t\tbreak;\n\tcase SCALE_SCREEN:\n\t\twidth = Options::displayWidth;\n\t\theight = Options::displayHeight / pixelRatioY;\n\t\tbreak;\n\tcase SCALE_ORIGINAL:\n\tdefault:\n\t\twidth = Screen::ORIGINAL_WIDTH;\n\t\theight = Screen::ORIGINAL_HEIGHT;\n\t\tbreak;\n\t}\n\n\t// don't go under minimum resolution... it's bad, mmkay?\n\twidth = std::max(width, Screen::ORIGINAL_WIDTH);\n\theight = std::max(height, Screen::ORIGINAL_HEIGHT);\n\n\tif (change && (Options::baseXResolution != width || Options::baseYResolution != height))\n\t{\n\t\tOptions::baseXResolution = width;\n\t\tOptions::baseYResolution = height;\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Engine/Screen.h",
    "content": "\t#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <SDL.h>\n#include <string>\n#include \"OpenGL.h\"\n#include \"Surface.h\"\n\nnamespace OpenXcom\n{\n\nclass Surface;\nclass Action;\n\n/**\n * A display screen, handles rendering onto the game window.\n * In SDL a Screen is treated like a Surface, so this is just\n * a specialized version of a Surface with functionality more\n * relevant for display screens. Contains a Surface buffer\n * where all the contents are kept, so any filters or conversions\n * can be applied before rendering the screen.\n */\nclass Screen\n{\nprivate:\n\tSDL_Surface *_screen;\n\tint _bpp;\n\tint _baseWidth, _baseHeight;\n\tdouble _scaleX, _scaleY;\n\tint _topBlackBand, _bottomBlackBand, _leftBlackBand, _rightBlackBand, _cursorTopBlackBand, _cursorLeftBlackBand;\n\tUint32 _flags;\n\tSDL_Color deferredPalette[256];\n\tint _numColors, _firstColor;\n\tbool _pushPalette;\n\tbool _flickerFix;\n\tOpenGL glOutput;\n\tSurface::UniqueBufferPtr _buffer;\n\tSurface::UniqueSurfacePtr _surface;\n\t/// Sets the _flags and _bpp variables based on game options; needed in more than one place now\n\tvoid makeVideoFlags();\npublic:\n\tstatic const int ORIGINAL_WIDTH;\n\tstatic const int ORIGINAL_HEIGHT;\n\n\t/// Creates a new display screen.\n\tScreen();\n\t/// Cleans up the display screen.\n\t~Screen();\n\t/// Get horizontal offset.\n\tint getDX() const;\n\t/// Get vertical offset.\n\tint getDY() const;\n\t/// Gets the internal buffer.\n\tSDL_Surface *getSurface();\n\t/// Handles keyboard events.\n\tvoid handle(Action *action);\n\t/// Renders the screen onto the game window.\n\tvoid flip();\n\t/// Clears the screen.\n\tvoid clear();\n\t/// Sets the screen's 8bpp palette.\n\tvoid setPalette(const SDL_Color *colors, int firstcolor = 0, int ncolors = 256, bool immediately = false);\n\t/// Gets the screen's 8bpp palette.\n\tSDL_Color *getPalette() const;\n\t/// Gets the screen's width.\n\tint getWidth() const;\n\t/// Gets the screen's height.\n\tint getHeight() const;\n\t/// Resets the screen display.\n\tvoid resetDisplay(bool resetVideo = true, bool noShaders = false);\n\t/// Gets the screen's X scale.\n\tdouble getXScale() const;\n\t/// Gets the screen's Y scale.\n\tdouble getYScale() const;\n\t/// Gets the screen's top black forbidden to cursor band's height.\n\tint getCursorTopBlackBand() const;\n\t/// Gets the screen's left black forbidden to cursor band's width.\n\tint getCursorLeftBlackBand() const;\n\t/// Takes a screenshot.\n\tvoid screenshot(const std::string &filename) const;\n\t/// Checks whether a 32bit scaler is requested and works for the selected resolution\n\tstatic bool use32bitScaler();\n\t/// Checks whether OpenGL output is requested\n\tstatic bool useOpenGL();\n\t/// update the game scale as required.\n\tstatic void updateScale(int type, int &width, int &height, bool change);\n};\n\n}\n"
  },
  {
    "path": "src/Engine/Script.cpp",
    "content": "/*\n * Copyright 2010-2015 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include <iomanip>\n#include <tuple>\n#include <algorithm>\n#include \"../fmath.h\"\n#include <bitset>\n#include <array>\n#include <numeric>\n#include <climits>\n\n#include \"Logger.h\"\n#include \"Options.h\"\n#include \"Script.h\"\n#include \"ScriptBind.h\"\n#include \"Surface.h\"\n#include \"ShaderDraw.h\"\n#include \"ShaderMove.h\"\n#include \"Exception.h\"\n#include \"../fallthrough.h\"\n#include \"Collections.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Script execution counter.\n */\nenum class ProgPos : size_t\n{\n\tUnknown = (size_t)-1,\n\tStart = (size_t)RetEnum::RetSize,\n};\n\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\t\tconst definition\n////////////////////////////////////////////////////////////\n\nconstexpr ScriptRef KnowNamesPrefix[] = {\n\tScriptRef{ \"ModList\" },\n\tScriptRef{ \"Tag\" },\n};\n\nconstexpr bool isKnowNamePrefix(ScriptRef name)\n{\n\tfor (ScriptRef r : KnowNamesPrefix)\n\t{\n\t\tif (r == name)\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\t\targ definition\n////////////////////////////////////////////////////////////\n#define MACRO_QUOTE(...) __VA_ARGS__\n\n#define MACRO_COPY_4(Func, Pos) \\\n\tFunc((Pos) + 0x0) \\\n\tFunc((Pos) + 0x1) \\\n\tFunc((Pos) + 0x2) \\\n\tFunc((Pos) + 0x3)\n#define MACRO_COPY_16(Func, Pos) \\\n\tMACRO_COPY_4(Func, (Pos) + 0x00) \\\n\tMACRO_COPY_4(Func, (Pos) + 0x04) \\\n\tMACRO_COPY_4(Func, (Pos) + 0x08) \\\n\tMACRO_COPY_4(Func, (Pos) + 0x0C)\n#define MACRO_COPY_64(Func, Pos) \\\n\tMACRO_COPY_16(Func, (Pos) + 0x00) \\\n\tMACRO_COPY_16(Func, (Pos) + 0x10) \\\n\tMACRO_COPY_16(Func, (Pos) + 0x20) \\\n\tMACRO_COPY_16(Func, (Pos) + 0x30)\n#define MACRO_COPY_256(Func, Pos) \\\n\tMACRO_COPY_64(Func, (Pos) + 0x00) \\\n\tMACRO_COPY_64(Func, (Pos) + 0x40) \\\n\tMACRO_COPY_64(Func, (Pos) + 0x80) \\\n\tMACRO_COPY_64(Func, (Pos) + 0xC0)\n\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\t\tproc definition\n////////////////////////////////////////////////////////////\n[[gnu::always_inline]]\nstatic inline void addShade_h(int& reg, const int& var)\n{\n\tconst int newShade = (reg & 0xF) + var;\n\tif (newShade > 0xF)\n\t{\n\t\t// so dark it would flip over to another color - make it black instead\n\t\treg = 0xF;\n\t\treturn;\n\t}\n\telse if (newShade > 0)\n\t{\n\t\treg = (reg & 0xF0) | newShade;\n\t\treturn;\n\t}\n\treg &= 0xF0;\n\t//prevent overflow to 0 or another color - make it white instead\n\tif (!reg || newShade < 0)\n\t\treg = 0x01;\n}\n\n[[gnu::always_inline]]\nstatic inline RetEnum mulAddMod_h(int& reg, const int& mul, const int& add, const int& mod)\n{\n\tconst int64_t a = ((int64_t)reg) * mul + add;\n\tif (mod)\n\t{\n\t\treg = (a % mod + mod) % mod;\n\t\treturn RetContinue;\n\t}\n\treturn RetError;\n}\n\n[[gnu::always_inline]]\nstatic inline RetEnum mulDiv_h(int& reg, const int& mul, const int& div)\n{\n\tif (div)\n\t{\n\t\treg = (((int64_t)reg) * mul) / div;\n\t\treturn RetContinue;\n\t}\n\treturn RetError;\n}\n\n[[gnu::always_inline]]\nstatic inline RetEnum wavegen_rect_h(int& reg, const int& period, const int& size, const int& max)\n{\n\tif (period <= 0)\n\t\treturn RetError;\n\treg %= period;\n\tif (reg < 0)\n\t\treg += period;\n\tif (reg > size)\n\t\treg = 0;\n\telse\n\t\treg = max;\n\treturn RetContinue;\n}\n\n[[gnu::always_inline]]\nstatic inline RetEnum wavegen_saw_h(int& reg, const int& period, const int& size, const int& max)\n{\n\tif (period <= 0)\n\t\treturn RetError;\n\treg %= period;\n\tif (reg < 0)\n\t\treg += period;\n\tif (reg > size)\n\t\treg = 0;\n\telse if (reg > max)\n\t\treg = max;\n\treturn RetContinue;\n}\n\n[[gnu::always_inline]]\nstatic inline RetEnum wavegen_tri_h(int& reg, const int& period, const int& size, const int& max)\n{\n\tif (period <= 0)\n\t\treturn RetError;\n\treg %= period;\n\tif (reg < 0)\n\t\treg += period;\n\tif (reg > size)\n\t\treg = 0;\n\telse\n\t{\n\t\tif (reg > size/2)\n\t\t\treg = size - reg;\n\t\tif (reg > max)\n\t\t\treg = max;\n\t}\n\treturn RetContinue;\n}\n\n[[gnu::always_inline]]\nstatic inline RetEnum wavegen_sin_h(int& reg, const int& period, const int& size)\n{\n\tif (period <= 0)\n\t\treturn RetError;\n\treg = size * std::sin(2.0 * M_PI *  reg / period);\n\treturn RetContinue;\n}\n\n[[gnu::always_inline]]\nstatic inline RetEnum wavegen_cos_h(int& reg, const int& period, const int& size)\n{\n\tif (period <= 0)\n\t\treturn RetError;\n\treg = size * std::cos(2.0 * M_PI *  reg  / period);\n\treturn RetContinue;\n}\n\n[[gnu::always_inline]]\nstatic inline RetEnum call_func_h(ScriptWorkerBase& c, ScriptFunc func, const Uint8* d, ProgPos& p)\n{\n\tauto t = p;\n\tauto r = func(c, d, t);\n\tp = t;\n\treturn r;\n}\n\n[[gnu::always_inline]]\nstatic inline RetEnum bit_popcount_h(int& reg)\n{\n\tconstexpr size_t minBitsetSize = 8*sizeof(std::bitset<1>);\n\tconstexpr size_t minRequiredSize = 8*sizeof(int);\n\tconstexpr size_t optimalSize = minRequiredSize < minBitsetSize ? minRequiredSize : minBitsetSize;\n\tstd::bitset<optimalSize> set = reg; //bitset with optimal size and without overhead\n\treg = set.count();\n\treturn RetContinue;\n}\n\n\n/**\n * Main macro defining all available operation in script engine.\n * @param IMPL macro function that access data. Take 3 args: Name, definition of operation and declaration of it's arguments.\n */\n#define MACRO_PROC_DEFINITION(IMPL) \\\n\t/*\tName,\t\tImplementation,\t\t\t\t\t\t\t\t\t\t\t\t\tEnd execution,\t\t\t\tArgs,\t\t\t\t\tDescription */ \\\n\tIMPL(exit,\t\tMACRO_QUOTE({\t\t\t\t\t\t\t\t\t\t\t\t\treturn RetEnd;\t\t}),\t\t(ScriptWorkerBase&),\t\"\") \\\n\t\\\n\tIMPL(goto,\t\tMACRO_QUOTE({ Prog = Label1;\t\t\t\t\t\t\t\t\treturn RetContinue; }),\t\t(ScriptWorkerBase& c, ProgPos& Prog, ProgPos Label1),\t\"\") \\\n\t\\\n\tIMPL(set,\t\tMACRO_QUOTE({ Reg0 = Data1;\t\t\t\t\t\t\t\t\t\treturn RetContinue; }),\t\t(ScriptWorkerBase& c, int& Reg0, int Data1),\t\"arg1 = arg2\") \\\n\t\\\n\tIMPL(clear,\t\tMACRO_QUOTE({ Reg0 = 0;\t\t\t\t\t\t\t\t\t\t\treturn RetContinue; }),\t\t(ScriptWorkerBase& c, int& Reg0),\t\t\t\t\"arg1 = 0\") \\\n\t\\\n\tIMPL(test_le,\tMACRO_QUOTE({ Prog = (A <= B) ? LabelTrue : LabelFalse;\t\t\treturn RetContinue; }),\t\t(ProgPos& Prog, int A, int B, ProgPos LabelTrue, ProgPos LabelFalse),\t\"\") \\\n\tIMPL(test_eq,\tMACRO_QUOTE({ Prog = (A == B) ? LabelTrue : LabelFalse;\t\t\treturn RetContinue; }),\t\t(ProgPos& Prog, int A, int B, ProgPos LabelTrue, ProgPos LabelFalse),\t\"\") \\\n\t\\\n\tIMPL(swap,\t\tMACRO_QUOTE({ std::swap(Reg0, Reg1);\t\t\t\t\t\t\treturn RetContinue; }),\t\t(int& Reg0, int& Reg1),\t\t\t\t\"Swap value of arg1 and arg2\") \\\n\tIMPL(add,\t\tMACRO_QUOTE({ Reg0 += Data1;\t\t\t\t\t\t\t\t\treturn RetContinue; }),\t\t(int& Reg0, int Data1),\t\t\t\t\"arg1 = arg1 + arg2\") \\\n\tIMPL(sub,\t\tMACRO_QUOTE({ Reg0 -= Data1;\t\t\t\t\t\t\t\t\treturn RetContinue; }),\t\t(int& Reg0, int Data1),\t\t\t\t\"arg1 = arg1 - arg2\") \\\n\tIMPL(mul,\t\tMACRO_QUOTE({ Reg0 *= Data1;\t\t\t\t\t\t\t\t\treturn RetContinue; }),\t\t(int& Reg0, int Data1),\t\t\t\t\"arg1 = arg1 * arg2\") \\\n\t\\\n\tIMPL(aggregate,\tMACRO_QUOTE({ Reg0 = Reg0 + Data1 * Data2;\t\t\t\t\t\treturn RetContinue; }),\t\t(int& Reg0, int Data1, int Data2),\t\t\t\"arg1 = arg1 + (arg2 * arg3)\") \\\n\tIMPL(offset,\tMACRO_QUOTE({ Reg0 = Reg0 * Data1 + Data2;\t\t\t\t\t\treturn RetContinue; }),\t\t(int& Reg0, int Data1, int Data2),\t\t\t\"arg1 = (arg1 * arg2) + arg3\") \\\n\tIMPL(offsetmod,\tMACRO_QUOTE({ return mulAddMod_h(Reg0, Mul1, Add2, Mod3);\t\t\t\t\t\t\t}),\t\t(int& Reg0, int Mul1, int Add2, int Mod3),\t\"arg1 = ((arg1 * arg2) + arg3) % arg4\") \\\n\t\\\n\tIMPL(div,\t\tMACRO_QUOTE({ if (!Data1) return RetError; Reg0 /= Data1;\t\treturn RetContinue; }),\t\t(int& Reg0, int Data1),\t\t\"arg1 = arg1 / arg2\") \\\n\tIMPL(mod,\t\tMACRO_QUOTE({ if (!Data1) return RetError; Reg0 %= Data1;\t\treturn RetContinue; }),\t\t(int& Reg0, int Data1),\t\t\"arg1 = arg1 % arg2\") \\\n\tIMPL(muldiv,\tMACRO_QUOTE({ return mulDiv_h(Reg0, Data1, Data2);\t\t\t\t\t\t\t\t\t}),\t\t(int& Reg0, int Data1, int Data2),\t\"arg1 = (arg1 * arg2) / arg3\") \\\n\t\\\n\tIMPL(shl,\t\tMACRO_QUOTE({ Reg0 <<= Data1;\t\t\t\t\t\t\t\t\treturn RetContinue; }),\t\t(int& Reg0, int Data1),\t\t\"Left bit shift of arg1 by arg2\") \\\n\tIMPL(shr,\t\tMACRO_QUOTE({ Reg0 >>= Data1;\t\t\t\t\t\t\t\t\treturn RetContinue; }),\t\t(int& Reg0, int Data1),\t\t\"Right bit shift of arg1 by arg2\") \\\n\t\\\n\tIMPL(bit_and,\t\tMACRO_QUOTE({ Reg0 = Reg0 & Data1;\t\t\t\t\t\t\t\treturn RetContinue; }),\t\t(int& Reg0, int Data1),\t\t\"Bit And of arg1 and arg2\") \\\n\tIMPL(bit_or,\t\tMACRO_QUOTE({ Reg0 = Reg0 | Data1;\t\t\t\t\t\t\t\treturn RetContinue; }),\t\t(int& Reg0, int Data1),\t\t\"Bit Or of arg1 and arg2\") \\\n\tIMPL(bit_xor,\t\tMACRO_QUOTE({ Reg0 = Reg0 ^ Data1;\t\t\t\t\t\t\t\treturn RetContinue; }),\t\t(int& Reg0, int Data1),\t\t\"Bit Xor of arg1 and arg2\") \\\n\tIMPL(bit_not,\t\tMACRO_QUOTE({ Reg0 = ~Reg0;\t\t\t\t\t\t\t\t\t\treturn RetContinue; }),\t\t(int& Reg0),\t\t\t\t\"Bit Not of arg1\") \\\n\tIMPL(bit_count,\t\tMACRO_QUOTE({ return bit_popcount_h(Reg0);\t\t\t\t\t\t\t\t\t\t\t }),\t(int& Reg0),\t\t\t\t\"Count number of set bits of arg1\") \\\n\t\\\n\tIMPL(pow,\t\t\tMACRO_QUOTE({ Reg0 = std::pow(Reg0, std::max(0, Data1));\t\treturn RetContinue; }),\t\t(int& Reg0, int Data1),\t\t\"Power of arg1 to arg2\") \\\n\tIMPL(sqrt,\t\t\tMACRO_QUOTE({ Reg0 = Reg0 > 0 ? std::sqrt(Reg0) : 0;\t\t\treturn RetContinue; }),\t\t(int& Reg0),\t\t\t\t\"Square root of arg1\") \\\n\t\\\n\tIMPL(abs,\t\t\tMACRO_QUOTE({ Reg0 = std::abs(Reg0);\t\t\t\t\t\t\treturn RetContinue; }),\t\t(int& Reg0),\t\t\t\t\t\t\"Absolute value of arg1\") \\\n\tIMPL(limit,\t\t\tMACRO_QUOTE({ Reg0 = std::max(std::min(Reg0, Data2), Data1);\treturn RetContinue; }),\t\t(int& Reg0, int Data1, int Data2),\t\"Correct value in arg1 that is always between arg2 and arg3\") \\\n\tIMPL(limit_upper,\tMACRO_QUOTE({ Reg0 = std::min(Reg0, Data1);\t\t\t\t\t\treturn RetContinue; }),\t\t(int& Reg0, int Data1),\t\t\t\t\"Correct value in arg1 that is always lesser than arg2\") \\\n\tIMPL(limit_lower,\tMACRO_QUOTE({ Reg0 = std::max(Reg0, Data1);\t\t\t\t\t\treturn RetContinue; }),\t\t(int& Reg0, int Data1),\t\t\t\t\"Correct value in arg1 that is always greater than arg2\") \\\n\t\\\n\tIMPL(wavegen_rect,\tMACRO_QUOTE({ return wavegen_rect_h(Reg0, Period1, Size2, Max3);\t\t\t\t}),\t\t(int& Reg0, int Period1, int Size2, int Max3),\t\t\"Square wave function, arg1 - argument and result, arg2 - period, arg3 - length of square, arg4 - height of square\") \\\n\tIMPL(wavegen_saw,\tMACRO_QUOTE({ return wavegen_saw_h(Reg0, Period1, Size2, Max3);\t\t\t\t\t}),\t\t(int& Reg0, int Period1, int Size2, int Max3),\t\t\"Saw wave function, arg1 - argument and result, arg2 - period, arg3 - size of saw, arg4 - cap value\") \\\n\tIMPL(wavegen_tri,\tMACRO_QUOTE({ return wavegen_tri_h(Reg0, Period1, Size2, Max3);\t\t\t\t\t}),\t\t(int& Reg0, int Period1, int Size2, int Max3),\t\t\"Triangle wave function, arg1 - argument and result, arg2 - period, arg3 - size of triangle, arg4 - cap value\") \\\n\tIMPL(wavegen_sin,\tMACRO_QUOTE({ return wavegen_sin_h(Reg0, Period1, Size2);\t\t\t\t\t\t}),\t\t(int& Reg0, int Period1, int Size2),\t\t\t\t\"Sin wave function, arg1 - argument and result, arg2 - period, arg3 - size of amplitude\") \\\n\tIMPL(wavegen_cos,\tMACRO_QUOTE({ return wavegen_cos_h(Reg0, Period1, Size2);\t\t\t\t\t\t}),\t\t(int& Reg0, int Period1, int Size2),\t\t\t\t\"Cos wave function, arg1 - argument and result, arg2 - period, arg3 - size of amplitude\") \\\n\t\\\n\tIMPL(get_color,\t\tMACRO_QUOTE({ Reg0 = Data1 >> 4;\t\t\t\t\t\t\treturn RetContinue; }),\t\t(int& Reg0, int Data1),\t\t\"Get color part to arg1 of pixel color in arg2\") \\\n\tIMPL(set_color,\t\tMACRO_QUOTE({ Reg0 = (Reg0 & 0xF) | (Data1 << 4);\t\t\treturn RetContinue; }),\t\t(int& Reg0, int Data1),\t\t\"Set color part to pixel color in arg1\") \\\n\tIMPL(get_shade,\t\tMACRO_QUOTE({ Reg0 = Data1 & 0xF;\t\t\t\t\t\t\treturn RetContinue; }),\t\t(int& Reg0, int Data1),\t\t\"Get shade part to arg1 of pixel color in arg2\") \\\n\tIMPL(set_shade,\t\tMACRO_QUOTE({ Reg0 = (Reg0 & 0xF0) | (Data1 & 0xF);\t\t\treturn RetContinue; }),\t\t(int& Reg0, int Data1),\t\t\"Set color part to pixel color in arg1\") \\\n\tIMPL(add_shade,\t\tMACRO_QUOTE({ addShade_h(Reg0, Data1);\t\t\t\t\t\treturn RetContinue; }),\t\t(int& Reg0, int Data1),\t\t\"Add value of shade to pixel color in arg1\") \\\n\t\\\n\tIMPL(call,\t\t\tMACRO_QUOTE({ return call_func_h(c, func, d, p);\t\t\t\t\t\t\t\t}),\t\t(ScriptFunc func, const Uint8* d, ScriptWorkerBase& c, ProgPos& p),\t\t\"\") \\\n\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tfunction definition\n////////////////////////////////////////////////////////////\n\nnamespace\n{\n\n/**\n * Macro returning name of function\n */\n#define MACRO_FUNC_ID(id) Func_##id\n\n/**\n * Macro used for creating functions from MACRO_PROC_DEFINITION\n */\n#define MACRO_CREATE_FUNC(NAME, Impl, Args, ...) \\\n\tstruct MACRO_FUNC_ID(NAME) \\\n\t{ \\\n\t\t[[gnu::always_inline]] \\\n\t\tstatic RetEnum func Args \\\n\t\t\tImpl \\\n\t};\n\nMACRO_PROC_DEFINITION(MACRO_CREATE_FUNC)\n\n#undef MACRO_CREATE_FUNC\n\n\nstruct Func_test_eq_null\n{\n\t[[gnu::always_inline]]\n\tstatic RetEnum func (ProgPos& Prog, std::nullptr_t, std::nullptr_t, ProgPos LabelTrue, ProgPos)\n\t{\n\t\tProg = LabelTrue;\n\t\treturn RetContinue;\n\t}\n};\n\nstruct Func_debug_impl_int\n{\n\t[[gnu::always_inline]]\n\tstatic RetEnum func (ScriptWorkerBase& c, int i)\n\t{\n\t\tauto f = [&]{ return std::to_string(i); };\n\t\tc.log_buffer_add(&f);\n\t\treturn RetContinue;\n\t}\n};\n\nstruct Func_debug_impl_text\n{\n\t[[gnu::always_inline]]\n\tstatic RetEnum func (ScriptWorkerBase& c, ScriptText p)\n\t{\n\t\tauto f = [&]{ return std::string(p); };\n\t\tc.log_buffer_add(&f);\n\t\treturn RetContinue;\n\t}\n};\n\nstruct Func_debug_flush\n{\n\t[[gnu::always_inline]]\n\tstatic RetEnum func (ScriptWorkerBase& c, ProgPos& p)\n\t{\n\t\tc.log_buffer_flush(p);\n\t\treturn RetContinue;\n\t}\n};\n\nstruct Func_set_text\n{\n\t[[gnu::always_inline]]\n\tstatic RetEnum func (ScriptWorkerBase& c, ScriptText& a, ScriptText b)\n\t{\n\t\ta = b;\n\t\treturn RetContinue;\n\t}\n};\n\nstruct Func_clear_text\n{\n\t[[gnu::always_inline]]\n\tstatic RetEnum func (ScriptWorkerBase& c, ScriptText& a)\n\t{\n\t\ta = ScriptText::empty;\n\t\treturn RetContinue;\n\t}\n};\n\nstruct Func_test_eq_text\n{\n\t[[gnu::always_inline]]\n\tstatic RetEnum func (ProgPos& prog, ScriptText a, ScriptText b, ProgPos labelTrue, ProgPos labelFalse)\n\t{\n\t\tif (a.ptr == nullptr && b.ptr == nullptr)\n\t\t{\n\t\t\tprog = labelTrue;\n\t\t}\n\t\telse if (a.ptr == nullptr || b.ptr == nullptr)\n\t\t{\n\t\t\tprog = labelFalse;\n\t\t}\n\t\telse if (strcmp(a.ptr, b.ptr) == 0)\n\t\t{\n\t\t\tprog = labelTrue;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tprog = labelFalse;\n\t\t}\n\t\treturn RetContinue;\n\t}\n};\n\n} //namespace\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tProc_Enum definition\n////////////////////////////////////////////////////////////\n\n/**\n * Macro returning enum from ProcEnum\n */\n#define MACRO_PROC_ID(id) Proc_##id\n\n/**\n * Macro used for creating ProcEnum from MACRO_PROC_DEFINITION\n */\n#define MACRO_CREATE_PROC_ENUM(NAME, ...) \\\n\tMACRO_PROC_ID(NAME), \\\n\tProc_##NAME##_end = MACRO_PROC_ID(NAME) + helper::FuncGroup<MACRO_FUNC_ID(NAME)>::ver() - 1,\n\n/**\n * Enum storing id of all available operations in script engine\n */\nenum ProcEnum : Uint8\n{\n\tMACRO_PROC_DEFINITION(MACRO_CREATE_PROC_ENUM)\n\tProc_EnumMax,\n};\n\n#undef MACRO_CREATE_PROC_ENUM\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tcore loop function\n////////////////////////////////////////////////////////////\n\n/**\n * Core function in script engine used to executing scripts\n * @param proc array storing operation of script\n * @return Result of executing script\n */\nstatic inline void scriptExe(ScriptWorkerBase& data, const Uint8* proc)\n{\n\tProgPos curr = ProgPos::Start;\n\tconst Uint8* curr_proc = proc + (int)curr;\n\t//--------------------------------------------------\n\t//\t\t\thelper macros for this function\n\t//--------------------------------------------------\n\t#define MACRO_FUNC_ARRAY(NAME, ...) + helper::FuncGroup<MACRO_FUNC_ID(NAME)>::FuncList{}\n\t#define MACRO_FUNC_ARRAY_LOOP(POS) \\\n\t\tcase (POS): \\\n\t\t{ \\\n\t\t\tif constexpr (POS == 0) \\\n\t\t\t{ \\\n\t\t\t\tbreak; \\\n\t\t\t} \\\n\t\t\telse \\\n\t\t\t{ \\\n\t\t\t\tusing currType = helper::GetType<func, POS>; \\\n\t\t\t\tconst auto p = (int)curr; \\\n\t\t\t\tcurr += (currType::offset + ProcOpSize); \\\n\t\t\t\tcurrType::funcDirect(data, curr_proc, curr); \\\n\t\t\t\tcurr_proc += (int)curr - p; \\\n\t\t\t} \\\n\t\t\tcontinue; \\\n\t\t}\n\t//--------------------------------------------------\n\n\tusing func = decltype(MACRO_PROC_DEFINITION(MACRO_FUNC_ARRAY));\n\n\twhile (true)\n\t{\n\t\tswitch (*curr_proc)\n\t\t{\n\t\tMACRO_COPY_256(MACRO_FUNC_ARRAY_LOOP, 0)\n\t\t}\n\n\t\tbreak; // macro before should have `continue` only if `switch` not continued then loop stop here\n\t}\n\n\t//--------------------------------------------------\n\t//\t\t\tremoving helper macros\n\t//--------------------------------------------------\n\t#undef MACRO_FUNC_ARRAY_LOOP\n\t#undef MACRO_FUNC_ARRAY\n\t//--------------------------------------------------\n\n\tif (curr < ProgPos::Start)\n\t{\n\t\tconst auto ret = static_cast<RetEnum>(curr);\n\t\tstatic int bugCount = 0;\n\t\tswitch (ret)\n\t\t{\n\t\t\tcase RetContinue:\n\t\t\tcase RetEnd:\n\t\t\t\t// normal end of script execution\n\t\t\t\treturn;\n\n\t\t\tcase RetError:\n\t\t\tdefault:\n\t\t\t\tif (++bugCount < 100)\n\t\t\t\t{\n\t\t\t\t\tLog(LOG_ERROR) << \"Invalid script operation\";\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t}\n\t}\n}\n\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\t\tScript class\n////////////////////////////////////////////////////////////\n\nvoid ScriptWorkerBlit::executeBlit(const Surface* src, Surface* dest, int x, int y, int shade)\n{\n\texecuteBlit(src, dest, x, y, shade, GraphSubset{ dest->getWidth(), dest->getHeight() } );\n}\n/**\n * Blitting one surface to another using script.\n * @param src source surface.\n * @param dest destination surface.\n * @param x x offset of source surface.\n * @param y y offset of source surface.\n */\nvoid ScriptWorkerBlit::executeBlit(const Surface* src, Surface* dest, int x, int y, int shade, GraphSubset mask)\n{\n\tShaderMove<const Uint8> srcShader(src, x, y);\n\tShaderMove<Uint8> destShader(dest, 0, 0);\n\n\tdestShader.setDomain(mask);\n\n\tif (_proc)\n\t{\n\t\tif (_events)\n\t\t{\n\t\t\tShaderDrawFunc(\n\t\t\t\t[&](Uint8& destStuff, const Uint8& srcStuff)\n\t\t\t\t{\n\t\t\t\t\tif (srcStuff)\n\t\t\t\t\t{\n\t\t\t\t\t\tScriptWorkerBlit::Output arg = { srcStuff, destStuff };\n\t\t\t\t\t\tset(arg);\n\t\t\t\t\t\tauto ptr = _events;\n\t\t\t\t\t\twhile (*ptr)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treset(arg);\n\t\t\t\t\t\t\tscriptExe(*this, ptr->data());\n\t\t\t\t\t\t\t++ptr;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t++ptr;\n\n\t\t\t\t\t\treset(arg);\n\t\t\t\t\t\tscriptExe(*this, _proc);\n\n\t\t\t\t\t\twhile (*ptr)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treset(arg);\n\t\t\t\t\t\t\tscriptExe(*this, ptr->data());\n\t\t\t\t\t\t\t++ptr;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t++ptr;\n\n\t\t\t\t\t\tget(arg);\n\t\t\t\t\t\tif (arg.getFirst()) destStuff = arg.getFirst();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tdestShader,\n\t\t\t\tsrcShader\n\t\t\t);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tShaderDrawFunc(\n\t\t\t\t[&](Uint8& destStuff, const Uint8& srcStuff)\n\t\t\t\t{\n\t\t\t\t\tif (srcStuff)\n\t\t\t\t\t{\n\t\t\t\t\t\tScriptWorkerBlit::Output arg = { srcStuff, destStuff };\n\t\t\t\t\t\tset(arg);\n\t\t\t\t\t\tscriptExe(*this, _proc);\n\t\t\t\t\t\tget(arg);\n\t\t\t\t\t\tif (arg.getFirst()) destStuff = arg.getFirst();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tdestShader,\n\t\t\t\tsrcShader\n\t\t\t);\n\t\t}\n\t}\n\telse\n\t{\n\t\tShaderDraw<helper::StandardShade>(destShader, srcShader, ShaderScalar(shade));\n\t}\n}\n\n/**\n * Execute script with two arguments.\n * @return Result value from script.\n */\nvoid ScriptWorkerBase::executeBase(const Uint8* proc)\n{\n\tif (proc)\n\t{\n\t\tscriptExe(*this, proc);\n\t}\n}\n\nconstexpr int log_buffer_limit_max = 500;\nstatic int log_buffer_limit_count = 0;\n\n/**\n * Add text to log buffer.\n */\nvoid ScriptWorkerBase::log_buffer_add(FuncRef<std::string()> func)\n{\n\tif (log_buffer_limit_count > log_buffer_limit_max)\n\t{\n\t\treturn;\n\t}\n\tif (!log_buffer.empty())\n\t{\n\t\tlog_buffer += \" \";\n\t}\n\tlog_buffer += func();\n}\n\n/**\n * Flush buffer to log file.\n */\nvoid ScriptWorkerBase::log_buffer_flush(ProgPos& p)\n{\n\tif (++log_buffer_limit_count < log_buffer_limit_max)\n\t{\n\t\tLogger log;\n\t\tlog.get(LOG_DEBUG) << \"Script debug log: \" << log_buffer;\n\t\tlog_buffer.clear();\n\t}\n\telse if (log_buffer_limit_count == log_buffer_limit_max)\n\t{\n\t\tLogger log;\n\t\tlog.get(LOG_DEBUG) << \"Script debug log limit reach\";\n\t\tlog_buffer.clear();\n\t}\n}\n\n\n////////////////////////////////////////////////////////////\n//\t\t\t\tParserWriter helpers\n////////////////////////////////////////////////////////////\n\n/**\n * Token type\n */\nenum TokenEnum\n{\n\tTokenNone,\n\tTokenInvalid,\n\tTokenColon,\n\tTokenSemicolon,\n\tTokenSymbol,\n\tTokenNumber,\n\tTokenText,\n};\n\n/**\n * Struct represents position of token in input string\n */\nclass SelectedToken : public ScriptRef\n{\n\t/// type of this token.\n\tTokenEnum _type;\n\t/// line where token start.\n\tsize_t _linePos;\n\npublic:\n\n\t/// Default constructor.\n\tSelectedToken() : ScriptRef{ }, _type{ TokenNone }, _linePos{ 0 }\n\t{\n\n\t}\n\n\t/// Constructor from range.\n\tSelectedToken(TokenEnum type, ScriptRef range, size_t linePos) : ScriptRef{ range }, _type{ type }, _linePos{linePos}\n\t{\n\n\t}\n\n\t/// Get token type.\n\tTokenEnum getType() const\n\t{\n\t\treturn _type;\n\t}\n\n\t/// Get token line postion in script.\n\tsize_t getLinePos() const\n\t{\n\t\treturn _linePos;\n\t}\n\n\t/// Convert token to script ref.\n\tScriptRefData parse(const ParserWriter& ph) const\n\t{\n\t\tif (getType() == TokenNumber)\n\t\t{\n\t\t\tc4::csubstr str(this->begin(), this->end());\n\t\t\tif (str.begins_with('+'))\n\t\t\t\tstr = str.sub(1);\n\t\t\tint val = 0;\n\t\t\tif (c4::from_chars(str, &val))\n\t\t\t\treturn ScriptRefData{*this, ArgInt, val};\n\t\t}\n\t\telse if (getType() == TokenSymbol)\n\t\t{\n\t\t\tauto ref = ph.getReferece(*this);\n\t\t\tif (ref)\n\t\t\t\treturn ref;\n\n\t\t\tauto type = ArgUnknowSimple;\n\n\t\t\tfor (auto& c : *this)\n\t\t\t{\n\t\t\t\tif (c == '.')\n\t\t\t\t{\n\t\t\t\t\t// look like `abc.def`\n\t\t\t\t\ttype = std::max(type, ArgUnknowSegment);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn ScriptRefData{ *this, type };\n\t\t}\n\t\telse if (getType() == TokenText)\n\t\t{\n\t\t\treturn ScriptRefData{ *this, ArgText, static_cast<const ScriptRef&>(*this) };\n\t\t}\n\t\treturn ScriptRefData{ *this, ArgInvalid };\n\t}\n\n};\n\nclass ScriptRefTokens : public ScriptRef\n{\n\t/// Current line position.\n\tsize_t _linePos = 1;\n\npublic:\n\t/// Using default constructors.\n\tusing ScriptRef::ScriptRef;\n\n\t/// Extract new token from current object.\n\tSelectedToken getNextToken(TokenEnum excepted = TokenNone);\n};\n\n/**\n * ScriptRef that is glue from independent parts.\n * First empty ref mean end of list.\n */\nclass ScriptRefCompound\n{\n\npublic:\n\n\tstd::array<ScriptRef, 4> parts;\n\n\t/// Default constructor.\n\tconstexpr ScriptRefCompound() = default;\n\n\t/// Constructor from one ref.\n\tconstexpr ScriptRefCompound(ScriptRef r) : parts{ r }\n\t{\n\n\t}\n\n\n\ttemplate<typename Callback>\n\tconstexpr void interateMutate(Callback&& f)\n\t{\n\t\tfor (auto& p : parts)\n\t\t{\n\t\t\tif constexpr (std::is_invocable_r_v<bool, Callback, ScriptRef&>)\n\t\t\t{\n\t\t\t\tif (!f(p))\n\t\t\t\t{\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tf(p);\n\t\t\t}\n\t\t}\n\t}\n\n\ttemplate<typename Callback>\n\tconstexpr void interate(Callback&& f) const\n\t{\n\t\tfor (const auto& p : parts)\n\t\t{\n\t\t\tif (!p)\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tf(p);\n\t\t}\n\t}\n\n\n\tconstexpr bool tryPopBack()\n\t{\n\t\tScriptRef* prev = nullptr;\n\t\tinterateMutate(\n\t\t\t[&](ScriptRef& r)\n\t\t\t{\n\t\t\t\tif (r)\n\t\t\t\t{\n\t\t\t\t\tprev = &r;\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\t\tif (prev) *prev = {};\n\t\treturn prev;\n\t}\n\n\tconstexpr bool tryPushBack(ScriptRef n)\n\t{\n\t\tScriptRef* prev = nullptr;\n\t\tinterateMutate(\n\t\t\t[&](ScriptRef& r)\n\t\t\t{\n\t\t\t\tif (r)\n\t\t\t\t{\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tprev = &r;\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\t\tif (prev) *prev = n;\n\t\treturn prev;\n\t}\n\n\tconstexpr void clear()\n\t{\n\t\tinterateMutate(\n\t\t\t[&](ScriptRef& r)\n\t\t\t{\n\t\t\t\tr = {};\n\t\t\t}\n\t\t);\n\t}\n\n\n\tconstexpr bool haveParts() const\n\t{\n\t\treturn !!parts[1];\n\t}\n\n\tconstexpr size_t sizeParts() const\n\t{\n\t\tsize_t s = 0;\n\t\tinterate([&](const ScriptRef& r){ s += 1; });\n\t\treturn s;\n\t}\n\n\tconstexpr size_t size() const\n\t{\n\t\tsize_t s = 0;\n\t\tinterate([&](const ScriptRef& r){ s += r.size(); });\n\t\treturn s;\n\t}\n\n\tconstexpr ScriptRef last() const\n\t{\n\t\tScriptRef l;\n\t\tinterate([&](const ScriptRef& r){ l = r; });\n\t\treturn l;\n\t}\n\n\tstd::string toString() const\n\t{\n\t\tstd::string s;\n\t\ts.reserve(size());\n\t\tinterate([&](const ScriptRef& r){ s.append(r.begin(), r.size()); });\n\t\treturn s;\n\t}\n\n\n\tconstexpr explicit operator bool() const\n\t{\n\t\treturn !!parts[0];\n\t}\n\n\tconstexpr operator ScriptRange<ScriptRef>() const\n\t{\n\t\treturn { parts.data(), parts.data() + parts.size() };\n\t}\n};\n\nclass ScriptRefOperation\n{\npublic:\n\tScriptRange<ScriptProcData> procList;\n\tScriptRefCompound procName;\n\n\tScriptRefData argRef;\n\tScriptRef argName;\n\n\t/// Check if whole object is correct\n\texplicit operator bool() const\n\t{\n\t\treturn\n\t\t\t(procName && procList) && // have function name and have related overload set\n\t\t\t(!argName || (argRef && procName.haveParts())) // have optional argument embedded in original operation name\n\t\t;\n\t}\n\n\tbool haveProc() const\n\t{\n\t\treturn !!procName;\n\t}\n\n\tbool haveArg() const\n\t{\n\t\treturn !!argName;\n\t}\n};\n\nclass ScriptArgList\n{\n\tsize_t argsLength = 0;\n\tScriptRefData args[ScriptMaxArg] = { };\n\npublic:\n\t/// Default constructor.\n\tScriptArgList() = default;\n\n\n\t/// Add one arg to list.\n\tconstexpr bool tryPushBack(const ScriptRefData& d)\n\t{\n\t\tif (argsLength < std::size(args))\n\t\t{\n\t\t\targs[argsLength++] = d;\n\t\t\treturn true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/// Add arg range to list.\n\tconstexpr bool tryPushBack(ScriptRange<ScriptRefData> l)\n\t{\n\t\tif (l.size() + argsLength <= std::size(args))\n\t\t{\n\t\t\tfor (const auto& d : l)\n\t\t\t{\n\t\t\t\targs[argsLength++] = d;\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/// Add arg range to list.\n\tconstexpr bool tryPushBack(const ScriptRefData* b, const ScriptRefData* e)\n\t{\n\t\treturn tryPushBack(ScriptRange<ScriptRefData>{b, e});\n\t}\n\n\n\n\tconstexpr size_t size() const\n\t{\n\t\treturn argsLength;\n\t}\n\n\tconstexpr const ScriptRefData* begin() const\n\t{\n\t\treturn std::begin(args);\n\t}\n\n\tconstexpr const ScriptRefData* end() const\n\t{\n\t\treturn std::begin(args) + argsLength;\n\t}\n\n\tconstexpr operator ScriptRange<ScriptRefData>() const\n\t{\n\t\treturn { begin(), end() };\n\t}\n};\n\n\n/**\n * Function extracting token from range\n * @param excepted what token type we expecting now\n * @return extracted token\n */\nSelectedToken ScriptRefTokens::getNextToken(TokenEnum excepted)\n{\n\t//groups of different types of ASCII characters\n\tusing CharClasses = Uint8;\n\tstruct Array // workaround for MSVC v19.20 bug where `std::array` is not `constexpr`\n\t{\n\t\tCharClasses arr[256];\n\n\t\tconstexpr CharClasses& operator[](size_t t) { return arr[t]; }\n\t\tconstexpr const CharClasses& operator[](size_t t) const { return arr[t]; }\n\t};\n\tstatic constexpr CharClasses CC_none = 0x1;\n\tstatic constexpr CharClasses CC_spec = 0x2;\n\tstatic constexpr CharClasses CC_digit = 0x4;\n\tstatic constexpr CharClasses CC_digitHex = 0x8;\n\tstatic constexpr CharClasses CC_charRest = 0x10;\n\tstatic constexpr CharClasses CC_digitSign = 0x20;\n\tstatic constexpr CharClasses CC_digitPrefix = 0x40;\n\tstatic constexpr CharClasses CC_quote = 0x80;\n\n\tstatic constexpr Array charDecoder = (\n\t\t[]\n\t\t{\n\t\t\tArray r = { };\n\t\t\tfor (int i = 0; i < 256; ++i)\n\t\t\t{\n\t\t\t\tif (i == '#' || i == ' ' || i == '\\r' || i == '\\n' || i == '\\t')\tr[i] |= CC_none;\n\t\t\t\tif (i == ':' || i == ';')\tr[i] |= CC_spec;\n\n\t\t\t\tif (i == '+' || i == '-')\tr[i] |= CC_digitSign;\n\t\t\t\tif (i >= '0' && i <= '9')\tr[i] |= CC_digit;\n\t\t\t\tif (i >= 'A' && i <= 'F')\tr[i] |= CC_digitHex;\n\t\t\t\tif (i >= 'a' && i <= 'f')\tr[i] |= CC_digitHex;\n\n\t\t\t\tif (i == 'x' || i == 'X')\tr[i] |= CC_digitPrefix;\n\t\t\t\tif (i == 'b' || i == 'B')\tr[i] |= CC_digitPrefix;\n\t\t\t\tif (i == 'o' || i == 'O')\tr[i] |= CC_digitPrefix;\n\n\t\t\t\tif (i >= 'A' && i <= 'Z')\tr[i] |= CC_charRest;\n\t\t\t\tif (i >= 'a' && i <= 'z')\tr[i] |= CC_charRest;\n\t\t\t\tif (i == '_' || i == '.')\tr[i] |= CC_charRest;\n\n\t\t\t\tif (i == '\"')\t\t\t\tr[i] |= CC_quote;\n\t\t\t}\n\t\t\treturn r;\n\t\t}\n\t)();\n\n\tstruct NextSymbol\n\t{\n\t\tchar c;\n\t\tCharClasses decode;\n\n\t\t/// Is valid symbol\n\t\texplicit operator bool() const { return c; }\n\n\t\t/// Check type of symbol\n\t\tbool is(CharClasses t) const { return decode & t; }\n\n\t\t/// Is this symbol starting next token?\n\t\tbool isStartOfNextToken() const { return c == 0 || is(CC_spec | CC_none); }\n\t};\n\n\tauto peekCharacter = [&]() -> NextSymbol const\n\t{\n\t\tif (_begin != _end)\n\t\t{\n\t\t\tconst auto c = *_begin;\n\t\t\treturn NextSymbol{ c, charDecoder[(Uint8)c] };\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn NextSymbol{ 0, 0 };\n\t\t}\n\t};\n\n\tauto readCharacter = [&]() -> NextSymbol const\n\t{\n\t\tauto curr = peekCharacter();\n\t\t//it will stop on `\\0` character\n\t\tif (curr)\n\t\t{\n\t\t\tif (*_begin == '\\n') ++_linePos;\n\t\t\t++_begin;\n\t\t}\n\t\treturn curr;\n\t};\n\n\tauto backCharacter = [&]()\n\t{\n\t\t--_begin;\n\t\tif (*_begin == '\\n') --_linePos;\n\t};\n\n\t//end of sequence, quit.\n\tif (_begin == _end)\n\t{\n\t\treturn SelectedToken{ };\n\t}\n\n\t//find first no whitespace character.\n\tif (peekCharacter().is(CC_none))\n\t{\n\t\twhile(const auto next = readCharacter())\n\t\t{\n\t\t\tif (next.c == '#')\n\t\t\t{\n\t\t\t\twhile(const auto comment = readCharacter())\n\t\t\t\t{\n\t\t\t\t\tif (comment.c == '\\n')\n\t\t\t\t\t{\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\telse if (next.is(CC_none))\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t//not empty character, put it back\n\t\t\t\tbackCharacter();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (!peekCharacter())\n\t\t{\n\t\t\treturn SelectedToken{ };\n\t\t}\n\t}\n\n\n\t//start of new token of unknown type\n\tauto type = TokenInvalid;\n\tauto begin = _begin;\n\tconst auto first = readCharacter();\n\n\t//text like `\"abcdef\"`\n\tif (first.is(CC_quote))\n\t{\n\t\ttype = TokenText;\n\t\twhile (const auto next = readCharacter())\n\t\t{\n\t\t\tif (next.c == first.c)\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\telse if (next.c == '\\\\')\n\t\t\t{\n\t\t\t\tconst auto escapedChar = readCharacter();\n\t\t\t\tif (escapedChar.c == first.c)\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\telse if (escapedChar.c == '\\\\')\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\ttype = TokenInvalid;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\telse if (next.c == '\\n')\n\t\t\t{\n\t\t\t\ttype = TokenInvalid;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t//eat all other chars\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\tif (!peekCharacter().isStartOfNextToken())\n\t\t{\n\t\t\ttype = TokenInvalid;\n\t\t}\n\n\t}\n\t//special symbol like `;` or `:`\n\telse if (first.is(CC_spec))\n\t{\n\t\tif (first.c == ':')\n\t\t{\n\t\t\ttype = excepted == TokenColon ? TokenColon : TokenInvalid;\n\t\t}\n\t\telse if (first.c == ';')\n\t\t{\n\t\t\t//semicolon wait for his turn, returning empty token\n\t\t\tif (excepted != TokenSemicolon)\n\t\t\t{\n\t\t\t\tbackCharacter();\n\t\t\t\ttype = TokenNone;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\ttype = TokenSemicolon;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\ttype = TokenInvalid;\n\t\t}\n\t}\n\t//number like `0x1234` or `5432` or `+232`\n\telse if (first.is(CC_digitSign | CC_digit))\n\t{\n\t\tauto firstDigit = first;\n\t\t//sign\n\t\tif (firstDigit.is(CC_digitSign))\n\t\t{\n\t\t\tfirstDigit = readCharacter();\n\t\t}\n\t\tif (firstDigit.is(CC_digit))\n\t\t{\n\t\t\tconst auto prefix = peekCharacter();\n\t\t\tconst auto havePrefix = firstDigit.c == '0' && prefix.is(CC_digitPrefix);\n\t\t\tconst auto hex = havePrefix && (prefix.c == 'x' || prefix.c == 'X');\n\n\t\t\tif (havePrefix)\n\t\t\t{\n\t\t\t\t//eat `x` or `o` or `b`\n\t\t\t\treadCharacter();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t//at least we have already one digit\n\t\t\t\ttype = TokenNumber;\n\t\t\t}\n\n\t\t\tconst CharClasses serachClass = hex ? (CC_digitHex | CC_digit) : CC_digit;\n\n\t\t\twhile (const auto next = readCharacter())\n\t\t\t{\n\t\t\t\t//end of symbol\n\t\t\t\tif (next.isStartOfNextToken())\n\t\t\t\t{\n\t\t\t\t\tbackCharacter();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\telse if (next.is(serachClass))\n\t\t\t\t{\n\t\t\t\t\ttype = TokenNumber;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\ttype = TokenInvalid;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t//symbol like `abcd` or `p12345`\n\telse if (first.is(CC_charRest))\n\t{\n\t\ttype = TokenSymbol;\n\t\twhile (const auto next = readCharacter())\n\t\t{\n\t\t\t//end of symbol\n\t\t\tif (next.isStartOfNextToken())\n\t\t\t{\n\t\t\t\tbackCharacter();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\telse if (!next.is(CC_charRest | CC_digit))\n\t\t\t{\n\t\t\t\ttype = TokenInvalid;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t}\n\tauto end = _begin;\n\treturn SelectedToken{ type, ScriptRef{ begin, end }, _linePos };\n}\n\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tHelper functions\n////////////////////////////////////////////////////////////\n\n\nnamespace\n{\n\n\n////////////////////////////////////////////////////////////\n//\t\t\tHandle of overload arguments\n////////////////////////////////////////////////////////////\n\n\n/**\n * Test for validity of arguments.\n */\nbool validOverloadProc(const ScriptRange<ScriptRange<ArgEnum>>& overload)\n{\n\tfor (auto& p : overload)\n\t{\n\t\tfor (auto& pp : p)\n\t\t{\n\t\t\tif (pp == ArgInvalid)\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t}\n\treturn true;\n}\n\nstd::string displayType(const ScriptParserBase* spb, ArgEnum type)\n{\n\tstd::string result = \"\";\n\tresult += \"[\";\n\tresult += spb->getTypePrefix(type);\n\tresult += spb->getTypeName(type).toString();\n\tresult += \"]\";\n\treturn result;\n}\n\n/**\n * Display arguments\n */\ntemplate<typename T, typename F>\nstd::string displayArgs(const ScriptParserBase* spb, const ScriptRange<T>& range, F getType)\n{\n\tstd::string result = \"\";\n\tfor (auto& p : range)\n\t{\n\t\tauto type = getType(p);\n\t\tif (type != ArgInvalid)\n\t\t{\n\t\t\tresult += \"[\";\n\t\t\tresult += spb->getTypePrefix(type);\n\t\t\tresult += spb->getTypeName(type).toString();\n\t\t\tresult += \"] \";\n\t\t}\n\t}\n\tif (!result.empty())\n\t{\n\t\tresult.pop_back();\n\t}\n\treturn result;\n}\n\n/**\n * Display arguments\n */\nstd::string displayOverloadProc(const ScriptParserBase* spb, const ScriptRange<ScriptRange<ArgEnum>>& overload)\n{\n\treturn displayArgs(spb, overload, [](const ScriptRange<ArgEnum>& o) { return o ? *o.begin() : ArgInvalid; });\n}\n\n/**\n * Accept all arguments.\n */\nint overloadBuildinProc(const ScriptProcData& spd, const ScriptRefData* begin, const ScriptRefData* end)\n{\n\treturn 1;\n}\n\n/**\n * Reject all arguments.\n */\nint overloadInvalidProc(const ScriptProcData& spd, const ScriptRefData* begin, const ScriptRefData* end)\n{\n\treturn 0;\n}\n\n/**\n * Verify arguments.\n */\nint overloadCustomProc(const ScriptProcData& spd, const ScriptRefData* begin, const ScriptRefData* end)\n{\n\tauto tempSorce = 255;\n\tauto curr = begin;\n\tfor (auto& currOver : spd.overloadArg)\n\t{\n\t\tif (curr == end)\n\t\t{\n\t\t\treturn 0;\n\t\t}\n\t\tconst auto size = currOver.size();\n\t\tif (size)\n\t\t{\n\t\t\tif (ArgBase(curr->type) != ArgInvalid)\n\t\t\t{\n\t\t\t\tint oneArgTempScore = 0;\n\t\t\t\tfor (auto& o : currOver)\n\t\t\t\t{\n\t\t\t\t\toneArgTempScore = std::max(oneArgTempScore, ArgCompatible(o, curr->type, size - 1));\n\t\t\t\t}\n\t\t\t\ttempSorce = std::min(tempSorce, oneArgTempScore);\n\t\t\t}\n\t\t\t++curr;\n\t\t}\n\t}\n\tif (curr != end)\n\t{\n\t\treturn 0;\n\t}\n\treturn tempSorce;\n}\n\n/**\n * Return public argument number of given function.\n */\nint getOverloadArgSize(ScriptRange<ScriptRange<ArgEnum>> over)\n{\n\tint argSize = 0;\n\n\tfor (auto& currOver : over)\n\t{\n\t\tif (currOver)\n\t\t{\n\t\t\targSize += 1;\n\t\t}\n\t}\n\n\treturn argSize;\n}\n\n/**\n * Return public argument number of given function.\n */\n[[maybe_unused]]\nint getOverloadArgSize(const ScriptProcData& spd)\n{\n\treturn getOverloadArgSize(spd.overloadArg);\n}\n\n/**\n * Return type of public argument of given function.\n */\nScriptRange<ArgEnum> getOverloadArgType(ScriptRange<ScriptRange<ArgEnum>> over, int argPos)\n{\n\tfor (auto& currOver : over)\n\t{\n\t\tif (currOver)\n\t\t{\n\t\t\tif (argPos == 0)\n\t\t\t{\n\t\t\t\treturn currOver;\n\t\t\t}\n\t\t\t--argPos;\n\t\t}\n\t}\n\n\treturn {};\n}\n\n/**\n * Return type of public argument of given function.\n */\n[[maybe_unused]]\nScriptRange<ArgEnum> getOverloadArgType(const ScriptProcData& spd, int argPos)\n{\n\treturn getOverloadArgType(spd.overloadArg, argPos);\n}\n\n/**\n * Return tail type list of public arguments of given function.\n */\nScriptRange<ScriptRange<ArgEnum>> getOverloadArgTypeTail(ScriptRange<ScriptRange<ArgEnum>> over, int argPos)\n{\n\tfor (auto& currOver : over)\n\t{\n\t\tif (currOver)\n\t\t{\n\t\t\tif (argPos == 0)\n\t\t\t{\n\t\t\t\treturn { &currOver, over.end() };\n\t\t\t}\n\t\t\t--argPos;\n\t\t}\n\t}\n\n\treturn {};\n}\n\n/**\n * Return tail type list of public arguments of given function.\n */\nScriptRange<ScriptRange<ArgEnum>> getOverloadArgTypeTail(const ScriptProcData& spd, int argPos)\n{\n\treturn getOverloadArgTypeTail(spd.overloadArg, argPos);\n}\n\nstd::tuple<int, const ScriptProcData*> findBestOverloadProc(const ScriptRange<ScriptProcData>& proc, const ScriptRefData* begin, const ScriptRefData* end)\n{\n\tint bestSorce = 0;\n\tconst ScriptProcData* bestValue = nullptr;\n\tfor (auto& p : proc)\n\t{\n\t\tint tempSorce = p.overload(p, begin, end);\n\t\tif (tempSorce)\n\t\t{\n\t\t\tif (tempSorce == bestSorce)\n\t\t\t{\n\t\t\t\tbestValue = nullptr;\n\t\t\t}\n\t\t\telse if (tempSorce > bestSorce)\n\t\t\t{\n\t\t\t\tbestSorce = tempSorce;\n\t\t\t\tbestValue = &p;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn std::make_tuple(bestSorce, bestValue);\n}\n\nScriptRefOperation findOperationAndArg(const ParserWriter& ph, ScriptRef op)\n{\n\tScriptRefOperation result;\n\n\tresult.procName = op;\n\tresult.procList = ph.parser.getProc(op);\n\tif (!result)\n\t{\n\t\tauto first_dot = op.find('.');\n\t\tif (first_dot == std::string::npos)\n\t\t{\n\t\t\treturn result;\n\t\t}\n\n\t\tresult.argName = op.head(first_dot);\n\t\tresult.argRef = ph.getReferece(result.argName);\n\t\tif (!result.argRef)\n\t\t{\n\t\t\tauto origArgName = result.argName;\n\n\t\t\t++first_dot; //skip '.'\n\t\t\tauto second_dot = op.tail(first_dot).find('.');\n\t\t\tif (second_dot == std::string::npos)\n\t\t\t{\n\t\t\t\treturn result;\n\t\t\t}\n\t\t\tsecond_dot += first_dot;\n\t\t\tresult.argName = op.head(second_dot);\n\t\t\tresult.argRef = ph.getReferece(result.argName);\n\t\t\tif (!result.argRef)\n\t\t\t{\n\t\t\t\t// restore initial name for error propose, but only if is unknown. Other wise typo should be in next part\n\t\t\t\tif (isKnowNamePrefix(origArgName) == false)\n\t\t\t\t{\n\t\t\t\t\tresult.argName = origArgName;\n\t\t\t\t}\n\t\t\t\treturn result;\n\t\t\t}\n\t\t\tfirst_dot = second_dot;\n\t\t}\n\n\t\tauto name = ph.parser.getTypeName(result.argRef.type);\n\t\tif (result.argRef.type < ArgMax || !name)\n\t\t{\n\t\t\treturn result;\n\t\t}\n\n\t\tresult.procName.parts = { name, op.tail(first_dot) };\n\t\tresult.procList = ph.parser.getProc(result.procName);\n\t}\n\n\treturn result;\n}\n\nScriptRefOperation replaceOperation(const ParserWriter& ph, const ScriptRefOperation& op, ScriptRef from, ScriptRef to)\n{\n\tScriptRefOperation result = op;\n\n\tbool correct = false;\n\tif (result.procName.size())\n\t{\n\t\tauto last = result.procName.last();\n\t\tauto lastHead = last.headFromEnd(from.size());\n\t\tauto lastTail = last.tailFromEnd(from.size());\n\t\tif (lastHead == from)\n\t\t{\n\t\t\tcorrect = true;\n\t\t\tcorrect &= result.procName.tryPopBack();\n\t\t\tif (lastTail)\n\t\t\t{\n\t\t\t\tcorrect &= result.procName.tryPushBack(lastTail);\n\t\t\t}\n\t\t\tcorrect &= result.procName.tryPushBack(to);\n\t\t\tcorrect &= bool(result.procList = ph.parser.getProc(result.procName));\n\t\t}\n\t}\n\n\tif (correct)\n\t{\n\t\treturn result;\n\t}\n\telse\n\t{\n\t\treturn {};\n\t}\n}\n\nvoid logErrorOnOperationArg(const ScriptRefOperation& op)\n{\n\tif (op)\n\t{\n\t\treturn;\n\t}\n\n\tif (op.haveArg())\n\t{\n\t\tif (op.argRef)\n\t\t{\n\t\t\tif (op.procName.haveParts())\n\t\t\t{\n\t\t\t\tLog(LOG_ERROR) << \"Unknown operation name '\" << op.procName.toString() << \"' for variable '\" << op.argName.toString() << \"'\";\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tLog(LOG_ERROR) << \"Unsupported type for variable '\" << op.argName.toString() << \"'\";\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"Unknown variable name '\" << op.argName.toString() << \"'\";\n\t\t}\n\t}\n}\n\n////////////////////////////////////////////////////////////\n//\t\t\tPushing operation on proc vector\n////////////////////////////////////////////////////////////\n\n\n/**\n * Helper choosing correct overload function to call.\n */\nbool parseOverloadProc(ParserWriter& ph, const ScriptRange<ScriptProcData>& proc, const ScriptRefData* begin, const ScriptRefData* end)\n{\n\tif (!proc)\n\t{\n\t\treturn false;\n\t}\n\tif ((size_t)std::distance(begin, end) > ScriptMaxArg)\n\t{\n\t\treturn false;\n\t}\n\n\tint bestSorce = 0;\n\tconst ScriptProcData* bestValue = nullptr;\n\n\tstd::tie(bestSorce, bestValue) = findBestOverloadProc(proc, begin, end);\n\n\tif (bestSorce)\n\t{\n\t\tif (bestValue)\n\t\t{\n\t\t\tif ((*bestValue)(ph, begin, end) == false)\n\t\t\t{\n\t\t\t\tLog(LOG_ERROR) << \"Error in matching arguments for operator '\" + proc.begin()->name.toString() + \"'\";\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"Conflicting overloads for operator '\" + proc.begin()->name.toString() + \"' for:\";\n\t\t\tLog(LOG_ERROR) << \"  \" << displayArgs(&ph.parser, ScriptRange<ScriptRefData>{ begin, end }, [](const ScriptRefData& r){ return r.type; });\n\t\t\tLog(LOG_ERROR) << \"Expected:\";\n\t\t\tfor (auto& p : proc)\n\t\t\t{\n\t\t\t\tif (p.parserArg != nullptr && p.overloadArg)\n\t\t\t\t{\n\t\t\t\t\tLog(LOG_ERROR) << \"  \" << displayOverloadProc(&ph.parser, p.overloadArg);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\t}\n\telse\n\t{\n\t\tLog(LOG_ERROR) << \"Can't match overload for operator '\" + proc.begin()->name.toString() + \"' for:\";\n\t\tLog(LOG_ERROR) << \"  \" << displayArgs(&ph.parser, ScriptRange<ScriptRefData>{ begin, end }, [](const ScriptRefData& r){ return r.type; });\n\t\tLog(LOG_ERROR) << \"Expected:\";\n\t\tfor (auto& p : proc)\n\t\t{\n\t\t\tif (p.parserArg != nullptr && p.overloadArg)\n\t\t\t{\n\t\t\t\tLog(LOG_ERROR) << \"  \" << displayOverloadProc(&ph.parser, p.overloadArg);\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n}\n\n/**\n * Helper used to parse line for build in function.\n */\ntemplate<Uint8 procId, typename FuncGroup>\nbool parseBuildinProc(const ScriptProcData& spd, ParserWriter& ph, const ScriptRefData* begin, const ScriptRefData* end)\n{\n\tauto opPos = ph.pushProc(procId);\n\tint ver = FuncGroup::parse(ph, begin, end);\n\tif (ver >= 0)\n\t{\n\t\tph.updateProc(opPos, ver);\n\t\treturn true;\n\t}\n\telse\n\t{\n\t\treturn false;\n\t}\n}\n\n/**\n * Helper used to parse line for custom functions.\n */\nbool parseCustomProc(const ScriptProcData& spd, ParserWriter& ph, const ScriptRefData* begin, const ScriptRefData* end)\n{\n\tusing argFunc = typename helper::ArgSelector<ScriptFunc>::type;\n\tusing argRaw = typename helper::ArgSelector<const Uint8*>::type;\n\tstatic_assert(helper::FuncGroup<Func_call>::ver() == argRaw::ver(), \"Invalid size\");\n\tstatic_assert(std::is_same<helper::GetType<helper::FuncGroup<Func_call>, 0>, argFunc>::value, \"Invalid first argument\");\n\tstatic_assert(std::is_same<helper::GetType<helper::FuncGroup<Func_call>, 1>, argRaw>::value, \"Invalid second argument\");\n\n\tauto opPos = ph.pushProc(Proc_call);\n\n\tauto funcPos = ph.pushReserved<ScriptFunc>();\n\tauto argPosBegin = ph.getCurrPos();\n\n\tauto argType = spd.parserArg(ph, begin, end);\n\n\tif (argType < 0)\n\t{\n\t\treturn false;\n\t}\n\n\tauto argPosEnd = ph.getCurrPos();\n\tph.updateReserved<ScriptFunc>(funcPos, spd.parserGet(argType));\n\n\tsize_t diff = ph.getDiffPos(argPosBegin, argPosEnd);\n\tfor (int i = 0; i < argRaw::ver(); ++i)\n\t{\n\t\tsize_t off = argRaw::offset(i);\n\t\tif (off >= diff)\n\t\t{\n\t\t\t//align proc to fit fixed size.\n\t\t\tph.push(off-diff);\n\t\t\tph.updateProc(opPos, i);\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n\n////////////////////////////////////////////////////////////\n//\t\tCustom parsers of operation arguments\n////////////////////////////////////////////////////////////\n\n\nconstexpr size_t ConditionSize = 6;\nconstexpr ScriptRef ConditionNames[ConditionSize] =\n{\n\tScriptRef{ \"eq\" }, ScriptRef{ \"neq\" },\n\tScriptRef{ \"le\" }, ScriptRef{ \"gt\" },\n\tScriptRef{ \"ge\" }, ScriptRef{ \"lt\" },\n};\n\nconstexpr size_t ConditionSpecialSize = 2;\nconstexpr ScriptRef ConditionSpecNames[ConditionSpecialSize] =\n{\n\tScriptRef{ \"or\" },\n\tScriptRef{ \"and\" },\n};\n\n\n/**\n * Helper used of condition operations.\n */\nbool parseConditionImpl(ParserWriter& ph, ScriptRefData truePos, ScriptRefData falsePos, const ScriptRefData* begin, const ScriptRefData* end)\n{\n\tconstexpr size_t TempArgsSize = 4;\n\n\tif (std::distance(begin, end) != 3)\n\t{\n\t\tLog(LOG_ERROR) << \"Invalid length of condition arguments\";\n\t\treturn false;\n\t}\n\n\tScriptRefData conditionArgs[TempArgsSize] =\n\t{\n\t\tbegin[1],\n\t\tbegin[2],\n\t\ttruePos, //success\n\t\tfalsePos, //failure\n\t};\n\n\tbool equalFunc = false;\n\tsize_t i = 0;\n\tfor (; i < ConditionSize; ++i)\n\t{\n\t\tif (begin[0].name == ConditionNames[i])\n\t\t{\n\t\t\tif (i < 2) equalFunc = true;\n\t\t\tif (i & 1) std::swap(conditionArgs[2], conditionArgs[3]); //negate condition result\n\t\t\tif (i >= 4) std::swap(conditionArgs[0], conditionArgs[1]); //swap condition args\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (i == ConditionSize)\n\t{\n\t\tLog(LOG_ERROR) << \"Unknown condition: '\" + begin[0].name.toString() + \"'\";\n\t\treturn false;\n\t}\n\n\tconst auto proc = ph.parser.getProc(equalFunc ? ScriptRef{ \"test_eq\" } : ScriptRef{ \"test_le\" });\n\tif (parseOverloadProc(ph, proc, std::begin(conditionArgs), std::end(conditionArgs)) == false)\n\t{\n\t\tLog(LOG_ERROR) << \"Unsupported operator: '\" + begin[0].name.toString() + \"'\";\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\n/**\n * Parse `or` or `and` conditions.\n */\nbool parseFullConditionImpl(ParserWriter& ph, ScriptRefData falsePos, const ScriptRefData* begin, const ScriptRefData* end)\n{\n\tif (std::distance(begin, end) <= 1)\n\t{\n\t\tLog(LOG_ERROR) << \"Invalid length of condition arguments\";\n\t\treturn false;\n\t}\n\n\t// each operation can fail, we can't prevent\n\tauto correct = true;\n\n\tconst auto truePos = ph.addLabel();\n\tconst auto orFunc = begin[0].name == ConditionSpecNames[0];\n\tconst auto andFunc = begin[0].name == ConditionSpecNames[1];\n\tif (orFunc || andFunc)\n\t{\n\t\t++begin;\n\t\tfor (; std::distance(begin, end) > 3; begin += 3)\n\t\t{\n\t\t\tauto temp = ph.addLabel();\n\t\t\tif (orFunc)\n\t\t\t{\n\t\t\t\tcorrect &= parseConditionImpl(ph, truePos, temp, begin, begin + 3);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tcorrect &= parseConditionImpl(ph, temp, falsePos, begin, begin + 3);\n\t\t\t}\n\t\t\tcorrect &= ph.setLabel(temp, ph.getCurrPos());\n\t\t}\n\t}\n\tcorrect &= parseConditionImpl(ph, truePos, falsePos, begin, end);\n\n\tcorrect &= ph.setLabel(truePos, ph.getCurrPos());\n\treturn correct;\n}\n\n/**\n * Helper used of variable operation declaration.\n */\nbool parseVariableImpl(ParserWriter& ph, ScriptRefData reg, ScriptRefData val = {})\n{\n\tif (!ArgIsReg(reg.type))\n\t{\n\t\tLog(LOG_ERROR) << \"Invalid register\";\n\t\treturn false;\n\t}\n\n\tif (val)\n\t{\n\t\tScriptRefData setArgs[] =\n\t\t{\n\t\t\treg,\n\t\t\tval,\n\t\t};\n\t\tconst auto proc = ph.parser.getProc(ScriptRef{ \"set\" });\n\t\treturn parseOverloadProc(ph, proc, std::begin(setArgs), std::end(setArgs));\n\t}\n\telse\n\t{\n\t\tScriptRefData setArgs[] =\n\t\t{\n\t\t\treg,\n\t\t};\n\t\tconst auto proc = ph.parser.getProc(ScriptRef{ \"clear\" });\n\t\treturn parseOverloadProc(ph, proc, std::begin(setArgs), std::end(setArgs));\n\t}\n}\n\n/**\n * Parser of `if` operation.\n */\nbool parseIf(const ScriptProcData& spd, ParserWriter& ph, const ScriptRefData* begin, const ScriptRefData* end)\n{\n\tauto& block = ph.pushScopeBlock(BlockIf);\n\tblock.nextLabel = ph.addLabel();\n\tblock.finalLabel = ph.addLabel();\n\n\treturn parseFullConditionImpl(ph, block.nextLabel, begin, end);\n}\n\n/**\n * Parser of `else` operation.\n */\nbool parseElse(const ScriptProcData& spd, ParserWriter& ph, const ScriptRefData* begin, const ScriptRefData* end)\n{\n\tif (ph.codeBlocks.back().type != BlockIf)\n\t{\n\t\tLog(LOG_ERROR) << \"Unexpected 'else'\";\n\t\treturn false;\n\t}\n\n\t// each operation can fail, we can't prevent\n\tauto correct = true;\n\n\tauto& block = ph.clearScopeBlock();\n\n\tph.pushProc(Proc_goto);\n\tcorrect &= ph.pushLabelTry(block.finalLabel);\n\n\tcorrect &= ph.setLabel(block.nextLabel, ph.getCurrPos());\n\tif (std::distance(begin, end) == 0)\n\t{\n\t\tblock.nextLabel = block.finalLabel;\n\t\tblock.type = BlockElse;\n\t}\n\telse\n\t{\n\t\tblock.nextLabel = ph.addLabel();\n\t\tcorrect &= parseFullConditionImpl(ph, block.nextLabel, begin, end);\n\t}\n\n\n\tif (correct)\n\t{\n\t\treturn true;\n\t}\n\telse\n\t{\n\t\tLog(LOG_ERROR) << \"Error in processing 'else'\";\n\t\treturn false;\n\t}\n}\n\n/**\n * Parser of `begin` operation.\n */\nbool parseBegin(const ScriptProcData& spd, ParserWriter& ph, const ScriptRefData* begin, const ScriptRefData* end)\n{\n\tif (std::distance(begin, end) != 0)\n\t{\n\t\tLog(LOG_ERROR) << \"Unexpected symbols after 'begin'\";\n\t\treturn false;\n\t}\n\n\tph.pushScopeBlock(BlockBegin);\n\n\treturn true;\n}\n\n/**\n * Parser of `loop` operation.\n */\nbool parseLoop(const ScriptProcData& spd, ParserWriter& ph, const ScriptRefData* begin, const ScriptRefData* end)\n{\n\tif (std::distance(begin, end) < 3)\n\t{\n\t\tLog(LOG_ERROR) << \"Missing symbols after 'loop'\";\n\t\treturn false;\n\t}\n\tif (begin[0].name != ScriptRef{ \"var\" })\n\t{\n\t\tLog(LOG_ERROR) << \"After 'loop' should be 'var'\";\n\t\treturn false;\n\t}\n\n\t// each operation can fail, we can't prevent\n\tauto correct = true;\n\n\t// we support simple `loop var x 100;` or complex like `loop var x obj.getInv.list \"BIG_GUN\";`\n\tconst auto functionPostfix = ScriptRef{ \".list\" };\n\tconst auto functionName = begin[2].name;\n\tconst auto functionArgSep = ph.getReferece(ScriptRef{ \"__\" });\n\tconst auto functionArgPh = ph.getReferece(ScriptRef{ \"_\" });\n\n\tassert(!!functionArgSep);\n\tassert(!!functionArgPh);\n\n\tif (functionName.headFromEnd(functionPostfix.size()) == functionPostfix && !isKnowNamePrefix(functionName.tailFromEnd(functionPostfix.size())))\n\t{\n\t\tauto& loop = ph.pushScopeBlock(BlockLoop);\n\t\tloop.nextLabel = ph.addLabel();\n\t\tloop.finalLabel = ph.addLabel();\n\n\t\tScriptArgList loopArgs = {};\n\n\t\tauto getProcAndRegTypes = [&](const ScriptRefOperation& proc, size_t placeHolders) -> std::tuple<const ScriptProcData*, ScriptRange<ScriptRange<ArgEnum>>>\n\t\t{\n\t\t\tScriptArgList temp;\n\t\t\ttemp.tryPushBack(loopArgs);\n\t\t\tsize_t org = temp.size();\n\t\t\tfor (size_t i = 0; i < placeHolders; ++i)\n\t\t\t{\n\t\t\t\tif (!temp.tryPushBack(functionArgPh))\n\t\t\t\t{\n\t\t\t\t\treturn {};\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tauto bestOverload = std::get<const ScriptProcData*>(findBestOverloadProc(proc.procList, std::begin(temp), std::end(temp)));\n\t\t\tif (!bestOverload)\n\t\t\t{\n\t\t\t\tLog(LOG_ERROR) << \"Conflicting overloads for operator '\" + proc.procList.begin()->name.toString() + \"' for:\";\n\t\t\t\tLog(LOG_ERROR) << \"  \" << displayArgs(&ph.parser, ScriptRange<ScriptRefData>{ temp }, [](const ScriptRefData& r){ return r.type; });\n\t\t\t\tLog(LOG_ERROR) << \"Expected:\";\n\t\t\t\tfor (auto& p : proc.procList)\n\t\t\t\t{\n\t\t\t\t\tif (p.parserArg != nullptr && p.overloadArg)\n\t\t\t\t\t{\n\t\t\t\t\t\tLog(LOG_ERROR) << \"  \" << displayOverloadProc(&ph.parser, p.overloadArg);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn {};\n\t\t\t}\n\n\t\t\treturn std::make_tuple(bestOverload, getOverloadArgTypeTail(*bestOverload, org));\n\t\t};\n\n\t\tauto parseReg = [&](ScriptRef name, ScriptRange<ArgEnum> types) -> ScriptRefData\n\t\t{\n\t\t\tif (types.size() != 1)\n\t\t\t{\n\t\t\t\treturn {};\n\t\t\t}\n\n\t\t\tauto c = true;\n\t\t\tauto r = ph.addReg(name, ArgSpecAdd(*types.begin(), ArgSpecVar));\n\t\t\tc &= !!r;\n\t\t\tc &= loopArgs.tryPushBack(r);\n\t\t\tc &= parseVariableImpl(ph, r);\n\t\t\tif (c)\n\t\t\t{\n\t\t\t\treturn r;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn {};\n\t\t\t}\n\t\t};\n\n\n\t\t// now we known that parameter look like `obj.foo.list` but not like `Tag.list`\n\t\tauto loopFunction = findOperationAndArg(ph, functionName);\n\t\tauto initFunction = replaceOperation(ph, loopFunction, functionPostfix, ScriptRef{\".init\"});\n\n\n\t\tif (!loopFunction)\n\t\t{\n\t\t\tlogErrorOnOperationArg(loopFunction);\n\t\t\tLog(LOG_ERROR) << \"Unsupported function '\" << functionName.toString() << \"' for 'loop'\";\n\t\t\treturn false;\n\t\t}\n\n\t\tif (!initFunction)\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"Unsupported function '\" << functionName.toString() << \"' for 'loop'\";\n\t\t\treturn false;\n\t\t}\n\n\t\tcorrect &= loopArgs.tryPushBack(loopFunction.argRef);\n\t\tcorrect &= loopArgs.tryPushBack(begin + 3, end);\n\t\tcorrect &= loopArgs.tryPushBack(functionArgSep);\n\n\t\t// init part of loop, try parse arg types of control registers\n\t\tauto [initBestProc, initBestOverload] = getProcAndRegTypes(initFunction, 2);\n\t\tif (!correct || getOverloadArgSize(initBestOverload) != 2)\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"Error in processing init of 'loop'\";\n\t\t\treturn false;\n\t\t}\n\t\tauto curr = parseReg({}, getOverloadArgType(initBestOverload, 0));\n\t\tauto limit = parseReg({}, getOverloadArgType(initBestOverload, 1));\n\t\tcorrect &= !!curr;\n\t\tcorrect &= !!limit;\n\t\tcorrect &= parseCustomProc(*initBestProc, ph, std::begin(loopArgs), std::end(loopArgs));\n\n\n\t\t// check part of loop, break if control register are equal\n\t\tcorrect &= ph.setLabel(loop.nextLabel, ph.getCurrPos());\n\t\tScriptRefData breakCond[] =\n\t\t{\n\t\t\tScriptRefData { ScriptRef{ \"lt\" }, ArgInvalid },\n\t\t\tcurr,\n\t\t\tlimit,\n\t\t};\n\t\tcorrect &= parseFullConditionImpl(ph, loop.finalLabel, std::begin(breakCond), std::end(breakCond));\n\n\n\t\t// increment part and getting current element of loop\n\t\tcorrect &= loopArgs.tryPushBack(functionArgSep);\n\t\tauto [loopBestProc, loopBestOverload] = getProcAndRegTypes(loopFunction, 1);\n\t\tif (!correct || getOverloadArgSize(loopBestOverload) != 1)\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"Error in processing step of 'loop'\";\n\t\t\treturn false;\n\t\t}\n\n\t\tauto var = parseReg(begin[1].name, getOverloadArgType(loopBestOverload, 0));\n\t\tcorrect &= !!var;\n\t\tcorrect &= parseCustomProc(*loopBestProc, ph, std::begin(loopArgs), std::end(loopArgs));\n\t}\n\telse\n\t{\n\t\tauto& loop = ph.pushScopeBlock(BlockLoop);\n\t\tloop.nextLabel = ph.addLabel();\n\t\tloop.finalLabel = ph.addLabel();\n\n\t\tauto limit = ph.addReg({}, ArgSpecAdd(ArgInt, ArgSpecVar));\n\t\tauto curr = ph.addReg({}, ArgSpecAdd(ArgInt, ArgSpecVar));\n\t\tauto var = ph.addReg(begin[1].name, ArgSpecAdd(ArgInt, ArgSpecVar));\n\n\t\tcorrect &= !!limit;\n\t\tcorrect &= !!curr;\n\t\tcorrect &= !!var;\n\n\t\tcorrect &= parseVariableImpl(ph, limit, begin[2]);\n\t\tcorrect &= parseVariableImpl(ph, curr);\n\n\t\tcorrect &= ph.setLabel(loop.nextLabel, ph.getCurrPos());\n\n\t\tScriptRefData breakCond[] =\n\t\t{\n\t\t\tScriptRefData { ScriptRef{ \"lt\" }, ArgInvalid },\n\t\t\tcurr,\n\t\t\tlimit,\n\t\t};\n\t\tcorrect &= parseFullConditionImpl(ph, loop.finalLabel, std::begin(breakCond), std::end(breakCond));\n\n\t\tcorrect &= parseVariableImpl(ph, var, curr);\n\n\t\tScriptRefData addArgs[] =\n\t\t{\n\t\t\tcurr,\n\t\t\t{ {}, ArgInt, 1 },\n\t\t};\n\t\tcorrect &= parseOverloadProc(ph, ph.parser.getProc(ScriptRef{ \"add\" }), std::begin(addArgs), std::end(addArgs));\n\t}\n\n\tif (correct)\n\t{\n\t\treturn true;\n\t}\n\telse\n\t{\n\t\tLog(LOG_ERROR) << \"Error in processing 'loop'\";\n\t\treturn false;\n\t}\n}\n\n/**\n * Get first outer scope of given type.\n * @param ph Script writer\n * @param type Type of block\n * @return Pointer to block or null if there is not bock of given type.\n */\nParserWriter::Block* getTopBlockOfType(ParserWriter& ph, BlockEnum type)\n{\n\tfor (auto& b : Collections::reverse(Collections::range(ph.codeBlocks)))\n\t{\n\t\tif (b.type == type)\n\t\t{\n\t\t\treturn &b;\n\t\t}\n\t}\n\treturn nullptr;\n}\n\n/**\n * Parser of `break` operation.\n */\nbool parseBreak(const ScriptProcData& spd, ParserWriter& ph, const ScriptRefData* begin, const ScriptRefData* end)\n{\n\tif (std::distance(begin, end) != 0)\n\t{\n\t\tLog(LOG_ERROR) << \"Unexpected symbols after 'break'\";\n\t\treturn false;\n\t}\n\n\tauto* loopBlock = getTopBlockOfType(ph, BlockLoop);\n\tif (!loopBlock)\n\t{\n\t\tLog(LOG_ERROR) << \"Operation 'break' outside 'loop'\";\n\t\treturn false;\n\t}\n\n\t// each operation can fail, we can't prevent\n\tauto correct = true;\n\n\tph.pushProc(Proc_goto);\n\tcorrect &= ph.pushLabelTry(loopBlock->finalLabel);\n\n\t//TODO: add handling similar to `break eq x y;`\n\n\n\tif (correct)\n\t{\n\t\treturn true;\n\t}\n\telse\n\t{\n\t\tLog(LOG_ERROR) << \"Error in processing 'break'\";\n\t\treturn false;\n\t}\n}\n\n/**\n * Parser of `continue` operation.\n */\nbool parseContinue(const ScriptProcData& spd, ParserWriter& ph, const ScriptRefData* begin, const ScriptRefData* end)\n{\n\tif (std::distance(begin, end) != 0)\n\t{\n\t\tLog(LOG_ERROR) << \"Unexpected symbols after 'continue'\";\n\t\treturn false;\n\t}\n\n\tauto* loopBlock = getTopBlockOfType(ph, BlockLoop);\n\tif (!loopBlock)\n\t{\n\t\tLog(LOG_ERROR) << \"Operation 'continue' outside 'loop'\";\n\t\treturn false;\n\t}\n\n\t// each operation can fail, we can't prevent\n\tauto correct = true;\n\n\tph.pushProc(Proc_goto);\n\tcorrect &= ph.pushLabelTry(loopBlock->nextLabel);\n\n\t//TODO: add handling similar to `continue eq x y;`\n\n\n\tif (correct)\n\t{\n\t\treturn true;\n\t}\n\telse\n\t{\n\t\tLog(LOG_ERROR) << \"Error in processing 'continue'\";\n\t\treturn false;\n\t}\n}\n\n/**\n * Parser of `end` operation.\n */\nbool parseEnd(const ScriptProcData& spd, ParserWriter& ph, const ScriptRefData* begin, const ScriptRefData* end)\n{\n\tif (ph.codeBlocks.back().type == BlockMain)\n\t{\n\t\tLog(LOG_ERROR) << \"Unexpected 'end'\";\n\t\treturn false;\n\t}\n\tif (std::distance(begin, end) != 0)\n\t{\n\t\tLog(LOG_ERROR) << \"Unexpected symbols after 'end'\";\n\t\treturn false;\n\t}\n\n\t// each operation can fail, we can't prevent\n\tauto correct = true;\n\n\tauto block = ph.popScopeBlock();\n\n\tswitch (block.type)\n\t{\n\tcase BlockIf:\n\tcase BlockElse:\n\t\tif (block.nextLabel.value != block.finalLabel.value)\n\t\t{\n\t\t\tcorrect &= ph.setLabel(block.nextLabel, ph.getCurrPos());\n\t\t}\n\t\tcorrect &= ph.setLabel(block.finalLabel, ph.getCurrPos());\n\t\tbreak;\n\n\tcase BlockBegin:\n\t\t// nothing\n\t\tbreak;\n\n\tcase BlockLoop:\n\t\tph.pushProc(Proc_goto);\n\t\tcorrect &= ph.pushLabelTry(block.nextLabel);\n\n\t\tcorrect &= ph.setLabel(block.finalLabel, ph.getCurrPos());\n\t\tbreak;\n\n\tdefault:\n\t\tthrow Exception(\"Unsuported block type\");\n\t}\n\n\n\tif (correct)\n\t{\n\t\treturn true;\n\t}\n\telse\n\t{\n\t\tLog(LOG_ERROR) << \"Error in processing 'end'\";\n\t\treturn false;\n\t}\n}\n\n/**\n * Parser of `var` operation that define local variables.\n */\nbool parseVar(const ScriptProcData& spd, ParserWriter& ph, const ScriptRefData* begin, const ScriptRefData* end)\n{\n\tauto spec = ArgSpecVar;\n\tif (begin != end)\n\t{\n\t\tif (begin[0].name == ScriptRef{ \"ptr\" })\n\t\t{\n\t\t\tspec = spec | ArgSpecPtr;\n\t\t\t++begin;\n\t\t}\n\t\telse if (begin[0].name == ScriptRef{ \"ptre\" })\n\t\t{\n\t\t\tspec = spec | ArgSpecPtrE;\n\t\t\t++begin;\n\t\t}\n\t}\n\tauto size = std::distance(begin, end);\n\tif (size < 2 || 3 < size)\n\t{\n\t\tLog(LOG_ERROR) << \"Invalid length of 'var' definition\";\n\t\treturn false;\n\t}\n\n\t// adding new custom variables of type selected type.\n\tauto type_curr = ph.parser.getType(begin[0].name);\n\tif (!type_curr)\n\t{\n\t\tLog(LOG_ERROR) << \"Invalid type '\" << begin[0].name.toString() << \"'\";\n\t\treturn false;\n\t}\n\n\tif (type_curr->meta.size == 0 && !(spec & ArgSpecPtr))\n\t{\n\t\tLog(LOG_ERROR) << \"Can't create variable of type '\" << begin[0].name.toString() << \"', require 'ptr'\";\n\t\treturn false;\n\t}\n\n\t++begin;\n\tif (begin[0].type != ArgUnknowSimple || !begin[0].name)\n\t{\n\t\tLog(LOG_ERROR) << \"Invalid variable name '\" << begin[0].name.toString() << \"'\";\n\t\treturn false;\n\t}\n\tif (ph.parser.getType(begin[0].name))\n\t{\n\t\tLog(LOG_ERROR) << \"Invalid variable name '\" << begin[0].name.toString() << \"' same as existing type\";\n\t\treturn false;\n\t}\n\tif (ph.parser.getProc(begin[0].name))\n\t{\n\t\tLog(LOG_ERROR) << \"Invalid variable name '\" << begin[0].name.toString() << \"' same as existing function\";\n\t\treturn false;\n\t}\n\n\tauto reg = ph.addReg(begin[0].name, ArgSpecAdd(type_curr->type, spec));\n\tif (!reg)\n\t{\n\t\tLog(LOG_ERROR) << \"Invalid type for variable '\" << begin[0].name.toString() << \"'\";\n\t\treturn false;\n\t}\n\n\t// each operation can fail, we can't prevent\n\tauto correct = true;\n\n\tif (size == 2)\n\t{\n\t\tcorrect &= parseVariableImpl(ph, reg);\n\t}\n\telse\n\t{\n\t\tcorrect &= parseVariableImpl(ph, reg, begin[1]);\n\t}\n\n\n\tif (correct)\n\t{\n\t\treturn true;\n\t}\n\telse\n\t{\n\t\tLog(LOG_ERROR) << \"Error in processing 'var'\";\n\t\treturn false;\n\t}\n}\n\n/**\n * Parser of `const` operation that define local variables.\n */\nbool parseConst(const ScriptProcData& spd, ParserWriter& ph, const ScriptRefData* begin, const ScriptRefData* end)\n{\n\tauto spec = ArgSpecNone;\n\tif (begin != end)\n\t{\n\t\tif (begin[0].name == ScriptRef{ \"ptr\" })\n\t\t{\n\t\t\tspec = spec | ArgSpecPtr;\n\t\t\t++begin;\n\t\t}\n\t\telse if (begin[0].name == ScriptRef{ \"ptre\" })\n\t\t{\n\t\t\tspec = spec | ArgSpecPtrE;\n\t\t\t++begin;\n\t\t}\n\t}\n\tauto size = std::distance(begin, end);\n\tif (3 != size)\n\t{\n\t\tLog(LOG_ERROR) << \"Invalid length of 'const' definition\";\n\t\treturn false;\n\t}\n\n\t// adding new custom variables of type selected type.\n\tauto type_curr = ph.parser.getType(begin[0].name);\n\tif (!type_curr)\n\t{\n\t\tLog(LOG_ERROR) << \"Invalid type '\" << begin[0].name.toString() << \"'\";\n\t\treturn false;\n\t}\n\n\tif (type_curr->meta.size == 0 && !(spec & ArgSpecPtr))\n\t{\n\t\tLog(LOG_ERROR) << \"Can't create const of type '\" << begin[0].name.toString() << \"', require 'ptr'\";\n\t\treturn false;\n\t}\n\n\t++begin;\n\tif (begin[0].type != ArgUnknowSimple || !begin[0].name)\n\t{\n\t\tLog(LOG_ERROR) << \"Invalid const name '\" << begin[0].name.toString() << \"'\";\n\t\treturn false;\n\t}\n\tif (ph.parser.getType(begin[0].name))\n\t{\n\t\tLog(LOG_ERROR) << \"Invalid variable name '\" << begin[0].name.toString() << \"' same as existing type\";\n\t\treturn false;\n\t}\n\tif (ph.parser.getProc(begin[0].name))\n\t{\n\t\tLog(LOG_ERROR) << \"Invalid variable name '\" << begin[0].name.toString() << \"' same as existing function\";\n\t\treturn false;\n\t}\n\n\tauto type =  ArgSpecAdd(type_curr->type, spec);\n\n\tif (type != begin[1].type)\n\t{\n\t\tLog(LOG_ERROR) << \"Invalid value '\"<< begin[1].name.toString() << \"' for const type '\" << begin[0].name.toString() << \"'\";\n\t\treturn false;\n\t}\n\n\tauto reg = ph.addConst(begin[0].name, type, begin[1].value);\n\tif (!reg)\n\t{\n\t\tLog(LOG_ERROR) << \"Invalid type for const '\" << begin[0].name.toString() << \"'\";\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\n/**\n * Parse return statement.\n */\nbool parseReturn(const ScriptProcData& spd, ParserWriter& ph, const ScriptRefData* begin, const ScriptRefData* end)\n{\n\tconst auto size = std::distance(begin, end);\n\tconst auto returnSize = ph.parser.haveEmptyReturn() ? 0 : ph.parser.getParamSize();\n\tif (returnSize != size)\n\t{\n\t\tLog(LOG_ERROR) << \"Invalid length of returns arguments\";\n\t\treturn false;\n\t}\n\n\tScriptRefData outputRegsData[ScriptMaxOut] = { };\n\tRegEnum currValueIndex[ScriptMaxOut] = { };\n\tRegEnum newValueIndex[ScriptMaxOut] = { };\n\n\tfor (int i = 0; i < size; ++i)\n\t{\n\t\toutputRegsData[i] = *ph.parser.getParamData(i);\n\t\tif (begin[i].isValueType<RegEnum>() && !ArgCompatible(outputRegsData[i].type, begin[i].type, 1))\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"Invalid return argument '\" + begin[i].name.toString() + \"'\";\n\t\t\treturn false;\n\t\t}\n\t\tcurrValueIndex[i] = outputRegsData[i].getValue<RegEnum>();\n\t\tnewValueIndex[i] = begin[i].getValueOrDefulat<RegEnum>(RegInvalid);\n\t\tif (currValueIndex[i] == newValueIndex[i])\n\t\t{\n\t\t\tcurrValueIndex[i] = RegInvalid;\n\t\t}\n\t}\n\n\t// matching return arguments to return register,\n\t// sometimes current value in one register is needed in another.\n\t// we need find order of assignments that will not lose any value.\n\tauto any_changed = true;\n\tauto all_free = false;\n\twhile (!all_free && any_changed)\n\t{\n\t\tall_free = true;\n\t\tany_changed = false;\n\t\tfor (int i = 0; i < size; ++i)\n\t\t{\n\t\t\tif (currValueIndex[i] == RegInvalid)\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tauto free = true;\n\t\t\tfor (int j = 0; j < size; ++j)\n\t\t\t{\n\t\t\t\tif (i != j && currValueIndex[i] == newValueIndex[j])\n\t\t\t\t{\n\t\t\t\t\tfree = false;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (free)\n\t\t\t{\n\t\t\t\tany_changed = true;\n\t\t\t\tcurrValueIndex[i] = RegInvalid;\n\t\t\t\tScriptRefData temp[] = { outputRegsData[i], begin[i] };\n\n\t\t\t\tconst auto proc = ph.parser.getProc(ScriptRef{ \"set\" });\n\t\t\t\tif (!parseOverloadProc(ph, proc, std::begin(temp), std::end(temp)))\n\t\t\t\t{\n\t\t\t\t\tLog(LOG_ERROR) << \"Invalid return argument '\" + begin[i].name.toString() + \"'\";\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tall_free = false;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (!all_free)\n\t{\n\t\t// now we can have only cases where return register have circular dependencies:\n\t\t// e.g. A need B, B need C and C need A.\n\t\t// using swap we can fix circular dependencies.\n\t\tfor (int i = 0; i < size; ++i)\n\t\t{\n\t\t\tif (currValueIndex[i] == RegInvalid)\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tfor (int j = 0; j < size; ++j)\n\t\t\t{\n\t\t\t\tif (i != j && newValueIndex[i] == currValueIndex[j])\n\t\t\t\t{\n\t\t\t\t\tScriptRefData temp[] = { outputRegsData[i], outputRegsData[j] };\n\n\t\t\t\t\tconst auto proc = ph.parser.getProc(ScriptRef{ \"swap\" });\n\t\t\t\t\tif (!parseOverloadProc(ph, proc, std::begin(temp), std::end(temp)))\n\t\t\t\t\t{\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\n\t\t\t\t\t// now value from 'i' is in 'j'\n\t\t\t\t\tcurrValueIndex[j] = currValueIndex[i];\n\t\t\t\t\tcurrValueIndex[i] = RegInvalid;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tph.pushProc(Proc_exit);\n\treturn true;\n}\n\n/**\n * Parse `debug_log` operator.\n */\nbool parseDebugLog(const ScriptProcData& spd, ParserWriter& ph, const ScriptRefData* begin, const ScriptRefData* end)\n{\n\tif (!Options::debug)\n\t{\n\t\treturn true;\n\t}\n\n\tfor (auto i = begin; i != end; ++i)\n\t{\n\t\tconst auto proc = ph.parser.getProc(ScriptRef{ \"debug_impl\" });\n\t\tif (!parseOverloadProc(ph, proc, i, std::next(i)))\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"Invalid debug argument '\" + i->name.toString() + \"'\";\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tconst auto proc = ph.parser.getProc(ScriptRef{ \"debug_flush\" });\n\treturn proc.size() == 1 && (*proc.begin())(ph, nullptr, nullptr);\n}\n\n/**\n * Dummy operation.\n */\nbool parseDummy(const ScriptProcData& spd, ParserWriter& ph, const ScriptRefData* begin, const ScriptRefData* end)\n{\n\tLog(LOG_ERROR) << \"Reserved operation for future use\";\n\treturn false;\n}\n\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tSort helpers\n////////////////////////////////////////////////////////////\n\n\n/**\n * Add new value to sorted vector by name.\n * @param vec Vector with data.\n * @param name Name of new data.\n * @param value Data to add.\n */\ntemplate<typename R>\nvoid addSortHelper(std::vector<R>& vec, R value)\n{\n\t// skip some early allocations that will be overridden right after\n\tif (vec.capacity() == 0)\n\t\tvec.reserve(100);\n\tvec.insert(std::partition_point(vec.begin(), vec.end(), [&](const R& a) { return ScriptRef::compare(a.name, value.name) <= 0; }), value);\n}\n\ntemplate<bool upper, typename R>\nauto boundSortHelper(R* begin, R* end, ScriptRange<ScriptRef> than)\n{\n\tconstexpr int limit = upper ? 1 : 0;\n\tconst auto total_size = std::accumulate(than.begin(), than.end(), size_t{}, [](size_t acc, ScriptRef r) { return acc + r.size(); });\n\tconst auto last_empty = std::find_if(than.begin(), than.end(), [](ScriptRef r){ return !r; });\n\n\t// some garbage, should not happened, for avoiding unexpected results make check for it\n\tassert(std::all_of(last_empty, than.end(), [](ScriptRef r){ return !r; }));\n\n\tconst auto final_range = ScriptRange{ than.begin(), last_empty };\n\n\treturn std::partition_point(begin, end,\n\t\t[&](const R& a)\n\t\t{\n\t\t\tconst auto curr = a.name.size();\n\t\t\tif (curr < total_size)\n\t\t\t{\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\telse if (curr == total_size)\n\t\t\t{\n\t\t\t\tScriptRef head = {};\n\t\t\t\tScriptRef tail = a.name;\n\t\t\t\tauto comp = 0;\n\t\t\t\tfor (ScriptRef r : final_range)\n\t\t\t\t{\n\t\t\t\t\tauto s = r.size();\n\t\t\t\t\thead = tail.head(s);\n\t\t\t\t\ttail = tail.tail(s);\n\t\t\t\t\tcomp = ScriptRef::compare(head, r);\n\t\t\t\t\tif (comp < 0)\n\t\t\t\t\t{\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t\telse if (comp > 0)\n\t\t\t\t\t{\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\telse // comp == 0\n\t\t\t\t\t{\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn comp < limit;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t);\n}\n\n/**\n * Get bound of value, upper or lower based on template parameter.\n * @param begin begin of sorted range.\n * @param end end of sorted range.\n * @param prefix First part of name.\n * @param postfix Second part of name.\n * @return Found iterator or end iterator.\n */\ntemplate<bool upper, typename R>\nR* boundSortHelper(R* begin, R* end, ScriptRef prefix, ScriptRef postfix = {})\n{\n\tconstexpr int limit = upper ? 1 : 0;\n\tif (postfix)\n\t{\n\t\tconst auto size = prefix.size();\n\t\tconst auto total_size = size + postfix.size();\n\t\treturn std::partition_point(begin, end,\n\t\t\t[&](const R& a)\n\t\t\t{\n\t\t\t\tconst auto curr = a.name.size();\n\t\t\t\tif (curr < total_size)\n\t\t\t\t{\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\telse if (curr == total_size)\n\t\t\t\t{\n\t\t\t\t\tconst auto comp  = ScriptRef::compare(a.name.substr(0, size), prefix);\n\t\t\t\t\treturn comp < 0 || (comp == 0 && ScriptRef::compare(a.name.substr(size), postfix) < limit);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\t}\n\telse\n\t{\n\t\treturn std::partition_point(begin, end, [&](const R& a){ return ScriptRef::compare(a.name, prefix) < limit; });\n\t}\n}\n\n/**\n * Helper function finding data by name (that can be merge from multiple parts).\n * @param begin begin of sorted range.\n * @param end end of sorted range.\n * @param name Name split to parts.\n * @return Found data or null.\n */\ntemplate<typename R, typename... Args>\nR* findSortHelper(R* begin, R* end, Args... args)\n{\n\tauto f = boundSortHelper<false>(begin, end, args...);\n\tif (f != end)\n\t{\n\t\t// check upper bound, if is different than lower, its mean we have hit\n\t\tif (f != boundSortHelper<true>(f, f + 1, args...))\n\t\t{\n\t\t\treturn &*f;\n\t\t}\n\t}\n\treturn nullptr;\n}\n\n/**\n * Helper function finding data by name (that can be merge from multiple parts).\n * @param begin begin of sorted range.\n * @param end end of sorted range.\n * @param name Name split to parts.\n * @return Found data or null.\n */\ntemplate<typename R>\nconst R* findSortHelper(const std::vector<R>& vec, ScriptRange<ScriptRef> name)\n{\n\treturn findSortHelper(vec.data(), vec.data() + vec.size(), name);\n}\n\n/**\n * Helper function finding data by name (that can be merge from multiple parts).\n * @param begin begin of sorted range.\n * @param end end of sorted range.\n * @param name Name split to parts.\n * @return Found data or null.\n */\ntemplate<typename R>\nR* findSortHelper(std::vector<R>& vec, ScriptRange<ScriptRef> name)\n{\n\treturn findSortHelper(vec.data(), vec.data() + vec.size(), name);\n}\n\n/**\n * Helper function finding data by name (that can be merge from two parts).\n * @param vec Vector with values.\n * @param prefix First part of name.\n * @param postfix Second part of name.\n * @return Found data or null.\n */\ntemplate<typename R>\nconst R* findSortHelper(const std::vector<R>& vec, ScriptRef prefix, ScriptRef postfix = {})\n{\n\treturn findSortHelper(vec.data(), vec.data() + vec.size(), prefix, postfix);\n}\n\n/**\n * Helper function finding data by name (that can be merge from two parts).\n * @param vec Vector with values.\n * @param prefix First part of name.\n * @param postfix Second part of name.\n * @return Found data or null.\n */\ntemplate<typename R>\nR* findSortHelper(std::vector<R>& vec, ScriptRef prefix, ScriptRef postfix = {})\n{\n\treturn findSortHelper(vec.data(), vec.data() + vec.size(), prefix, postfix);\n}\n\n/**\n * Calculate space used by reg of that type.\n * @param parser\n * @param type\n * @return Type meta data.\n */\nTypeInfo getRegMeta(const ScriptParserBase& parser, ArgEnum type)\n{\n\tauto t = parser.getType(type);\n\tif (t == nullptr)\n\t{\n\t\treturn { };\n\t}\n\telse\n\t{\n\t\treturn ArgIsPtr(type) ? TypeInfo::getPtrTypeInfo() : t->meta;\n\t}\n}\n\n/**\n * Add new string to collection and return reference to it.\n * @param list List where strings are stored.\n * @param s New string to add.\n * @return Reference to stored string.\n */\nScriptRef addString(std::vector<std::vector<char>>& list, const std::string& s)\n{\n\tstd::vector<char> refData;\n\trefData.assign(s.begin(), s.end());\n\tScriptRef ref{ refData.data(), refData.data() + refData.size() };\n\n\t//we need use char vector because its guaranteed that pointer in ref will not get invalidated when names list grown.\n\tlist.push_back(std::move(refData));\n\treturn ref;\n}\n\n} //namespace\n\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tParserWriter class\n////////////////////////////////////////////////////////////\n\n/**\n * Constructor\n * @param regUsed current used reg space.\n * @param c container that will be fill with script data.\n * @param d parser having all meta data.\n */\nParserWriter::ParserWriter(\n\t\tsize_t regUsed,\n\t\tScriptContainerBase& c,\n\t\tconst ScriptParserBase& d) :\n\tcontainer(c),\n\tparser(d),\n\tregIndexUsed(static_cast<RegEnum>(regUsed))\n{\n\tpushScopeBlock(BlockMain);\n\tpush(static_cast<size_t>(ProgPos::Start));\n}\n\n/**\n * Function finalizing parsing of script\n */\nvoid ParserWriter::relese()\n{\n\tpushProc(Proc_exit);\n\trefLabels.forEachPosition(\n\t\t[&](auto pos, ProgPos value)\n\t\t{\n\t\t\tif (value == ProgPos::Unknown)\n\t\t\t{\n\t\t\t\tthrow Exception(\"Incorrect label position reference\");\n\t\t\t}\n\t\t\tupdateReserved<ProgPos>(pos, value);\n\t\t}\n\t);\n\n\tauto textTotalSize = 0u;\n\trefTexts.forEachPosition(\n\t\t[&](auto pos, ScriptRef value)\n\t\t{\n\t\t\ttextTotalSize += value.size() + 1;\n\t\t}\n\t);\n\tauto charPtr = [&](ProgPos pos)\n\t{\n\t\treturn (char*)&container._proc[static_cast<size_t>(pos)];\n\t};\n\t//preallocate space in vector to have stable pointers to strings\n\tauto currentText = push(textTotalSize);\n\trefTexts.forEachPosition(\n\t\t[&](auto pos, ScriptRef value)\n\t\t{\n\t\t\tauto start = currentText;\n\n\t\t\t//check beginning of string\n\t\t\tauto begin = value.begin();\n\t\t\tif (begin == value.end() || *begin != '\"')\n\t\t\t{\n\t\t\t\tthrow Exception(\"Invalid Text: >>\" + value.toString() + \"<<\");\n\t\t\t}\n\n\t\t\t//check end of string\n\t\t\tauto end = value.end() - 1;\n\t\t\tif (begin == end || *end != '\"')\n\t\t\t{\n\t\t\t\tthrow Exception(\"Invalid Text: >>\" + value.toString() + \"<<\");\n\t\t\t}\n\n\t\t\t++begin;\n\t\t\tbool escape = false;\n\t\t\twhile (begin != end)\n\t\t\t{\n\t\t\t\tif (escape == true)\n\t\t\t\t{\n\t\t\t\t\tescape = false;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif (*begin == '\\\\')\n\t\t\t\t\t{\n\t\t\t\t\t\tescape = true;\n\t\t\t\t\t\t++begin;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t*charPtr(currentText) = *begin;\n\t\t\t\t++currentText;\n\t\t\t\t++begin;\n\t\t\t}\n\t\t\t++currentText;\n\n\t\t\tupdateReserved<ScriptText>(pos, ScriptText{ charPtr(start) });\n\t\t}\n\t);\n}\n\n/**\n * Returns reference based on name.\n * @param s name of reference.\n * @return reference data.\n */\nScriptRefData ParserWriter::getReferece(const ScriptRef& s) const\n{\n\tconst ScriptRefData* ptr = nullptr;\n\tfor (const auto& r : regStack)\n\t{\n\t\tif (r.name == s)\n\t\t{\n\t\t\tptr = &r;\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (ptr == nullptr)\n\t{\n\t\tptr = parser.getRef(s);\n\t}\n\tif (ptr == nullptr)\n\t{\n\t\tptr = parser.getGlobal()->getRef(s);\n\t}\n\tif (ptr == nullptr)\n\t{\n\t\treturn ScriptRefData{ };\n\t}\n\treturn *ptr;\n}\n\n/**\n * Get current position in proc vector.\n * @return Position in proc vector.\n */\nProgPos ParserWriter::getCurrPos() const\n{\n\treturn static_cast<ProgPos>(container._proc.size());\n}\n\n/**\n * Get distance between two positions in proc vector.\n */\nsize_t ParserWriter::getDiffPos(ProgPos begin, ProgPos end) const\n{\n\tif (begin > end)\n\t{\n\t\tthrow Exception(\"Invalid ProgPos distance\");\n\t}\n\treturn static_cast<size_t>(end) - static_cast<size_t>(begin);\n}\n\n/**\n * Push zeros to fill empty space.\n * @param s Size of empty space.\n */\nProgPos ParserWriter::push(size_t s)\n{\n\tauto curr = getCurrPos();\n\tcontainer._proc.insert(container._proc.end(), s, 0);\n\treturn static_cast<ProgPos>(curr);\n}\n\n/**\n * Update part of proc vector.\n * @param pos position to update.\n * @param data data to write.\n * @param s size of data.\n */\nvoid ParserWriter::update(ProgPos pos, void* data, size_t s)\n{\n\tmemcpy(&container._proc[static_cast<size_t>(pos)], data, s);\n}\n\n/**\n * Push custom value on proc vector.\n * @param p pointer to value.\n * @param size size of value.\n */\nvoid ParserWriter::pushValue(ScriptValueData v)\n{\n\tupdate(push(v.size), &v.data, v.size);\n}\n\n/**\n * Pushing proc operation id on proc vector.\n */\nParserWriter::ReservedPos<ParserWriter::ProcOp> ParserWriter::pushProc(Uint8 procId)\n{\n\tstatic_assert(sizeof(procId) == ProcOpSize, \"procId should have same size as ProcOpSize\");\n\tauto curr = getCurrPos();\n\tcontainer._proc.push_back(procId);\n\treturn { curr };\n}\n\n/**\n * Updating previously added proc operation id.\n * @param pos Position of operation.\n * @param procOffset Offset value.\n */\nvoid ParserWriter::updateProc(ReservedPos<ProcOp> pos, int procOffset)\n{\n\tcontainer._proc[static_cast<size_t>(pos.getPos())] += procOffset;\n}\n\n/**\n * Try pushing label arg on proc vector.\n * @param s name of label.\n * @return true if label was successfully added.\n */\nbool ParserWriter::pushLabelTry(const ScriptRefData& data)\n{\n\tauto temp = data;\n\tif (!temp && temp.name)\n\t{\n//\t\ttemp = addReferece(addLabel(data.name));\n\t\treturn false;\n\t}\n\tif (temp.type != ArgLabel)\n\t{\n\t\treturn false;\n\t}\n\n\t// Can't use this to create loop back named label.\n\tif (temp.name && refLabels.getValue(temp.value) != ProgPos::Unknown)\n\t{\n\t\treturn false;\n\t}\n\trefLabels.pushPosition(*this, temp.value);\n\treturn true;\n}\n\n/**\n * Create new label definition for proc vector.\n * @return index of new label.\n */\nScriptRefData ParserWriter::addLabel(const ScriptRef& name)\n{\n\treturn ScriptRefData{ name, ArgLabel, refLabels.addValue(ProgPos::Unknown) };\n}\n\n/**\n * Setting offset of label on proc vector.\n * @param s name of label\n * @param offset set value where label is pointing\n * @return true if operation success\n */\nbool ParserWriter::setLabel(const ScriptRefData& data, ProgPos offset)\n{\n\tauto temp = data;\n\tif (!temp && temp.name)\n\t{\n//\t\ttemp = addReferece(addLabel(data.name));\n\t\treturn false;\n\t}\n\tif (temp.type != ArgLabel)\n\t{\n\t\treturn false;\n\t}\n\n\tif (refLabels.getValue(temp.value) != ProgPos::Unknown)\n\t{\n\t\treturn false;\n\t}\n\trefLabels.setValue(temp.value, offset);\n\treturn true;\n}\n\n/**\n * Try pushing text literal arg on proc vector.\n */\nbool ParserWriter::pushTextTry(const ScriptRefData& data)\n{\n\tif (data && data.type == ArgText)\n\t{\n\t\trefTexts.pushPosition(*this, refTexts.addValue(data.getValue<ScriptRef>()));\n\t\treturn true;\n\t}\n\treturn false;\n}\n\n/**\n * Try pushing data arg on proc vector.\n * @param s name of data\n * @return true if data exists and is valid\n */\nbool ParserWriter::pushConstTry(const ScriptRefData& data, ArgEnum type)\n{\n\tif (data && data.type == type && !ArgIsReg(data.type) && data.value.type == type)\n\t{\n\t\tpushValue(data.value);\n\t\treturn true;\n\t}\n\treturn false;\n}\n\n/**\n * Try pushing reg arg on proc vector.\n * @param s name of reg\n * @return true if reg exists and is valid\n */\nbool ParserWriter::pushRegTry(const ScriptRefData& data, ArgEnum type)\n{\n\ttype = ArgSpecAdd(type, ArgSpecReg);\n\tif (data && ArgCompatible(type, data.type, 0) && data.getValue<RegEnum>() != RegInvalid)\n\t{\n\t\tpushValue(data.getValue<RegEnum>());\n\t\treturn true;\n\t}\n\treturn false;\n}\n\n/**\n * Add new reg arg definition.\n * @param s optional name of reg\n * @param type type of reg\n * @return Reg data\n */\nScriptRefData ParserWriter::addReg(const ScriptRef& s, ArgEnum type)\n{\n\tif (s && getReferece(s))\n\t{\n\t\treturn {};\n\t}\n\n\ttype = ArgSpecAdd(type, ArgSpecReg);\n\tauto meta = getRegMeta(parser, type);\n\tif (!meta)\n\t{\n\t\treturn {};\n\t}\n\tif (meta.needRegSpace(regIndexUsed) > ScriptMaxReg)\n\t{\n\t\treturn {};\n\t}\n\tScriptRefData data = { s, type, static_cast<RegEnum>(meta.nextRegPos(regIndexUsed)) };\n\tif (s)\n\t{\n\t\tregStack.push_back(data);\n\t}\n\tregIndexUsed = static_cast<RegEnum>(meta.needRegSpace(regIndexUsed));\n\treturn data;\n}\n\n/**\n * Add new local const definition.\n * @param s optional name of const\n * @param type type of reg\n * @return Reg data\n */\nScriptRefData ParserWriter::addConst(const ScriptRef& s, ArgEnum type, ScriptValueData value)\n{\n\tif (!s)\n\t{\n\t\treturn {};\n\t}\n\n\tif (getReferece(s))\n\t{\n\t\treturn {};\n\t}\n\n\tif (ArgIsReg(type))\n\t{\n\t\treturn {};\n\t}\n\n\tauto meta = getRegMeta(parser, type);\n\tif (!meta)\n\t{\n\t\treturn {};\n\t}\n\n\tScriptRefData data = { s, type, value };\n\n\tregStack.push_back(data);\n\n\treturn data;\n}\n\n/**\n * Add new code scope.\n * @return Reference to new block.\n */\nParserWriter::Block& ParserWriter::pushScopeBlock(BlockEnum type)\n{\n\treturn codeBlocks.emplace_back(ParserWriter::Block{ type, regStack.size(), regIndexUsed });\n}\n\n/**\n * Clear values in code scope.\n * @return Reference to current block.\n */\nParserWriter::Block& ParserWriter::clearScopeBlock()\n{\n\tauto& current = codeBlocks.back();\n\tregStack.resize(current.regStackSizeFrom);\n\tregIndexUsed = current.regIndexUsedFrom;\n\treturn current;\n}\n\n/**\n * Pop code scope.\n * @return Copy of old block.\n */\nParserWriter::Block ParserWriter::popScopeBlock()\n{\n\tif (codeBlocks.back().type == BlockMain)\n\t{\n\t\tthrow Exception(\"Invalid stack popup\");\n\t}\n\n\tauto prev = clearScopeBlock();\n\tcodeBlocks.pop_back();\n\treturn prev;\n}\n\n/// Dump to log error info about ref.\nvoid ParserWriter::logDump(const ScriptRefData& ref) const\n{\n\tif (ref)\n\t{\n\t\tLog(LOG_ERROR) << \"Incorrect type of argument '\"<< ref.name.toString() <<\"' of type \"<< displayType(&parser, ref.type);\n\t}\n\telse\n\t{\n\t\tLog(LOG_ERROR) << \"Unknown argument '\"<< ref.name.toString() <<\"'\";\n\t}\n}\n\n////////////////////////////////////////////////////////////\n//\t\t\t\tScriptParserBase class\n////////////////////////////////////////////////////////////\n\n/**\n * Constructor.\n */\nScriptParserBase::ScriptParserBase(ScriptGlobal* shared, const std::string& name) :\n\t_shared{ shared },\n\t_emptyReturn{ false },\n\t_regUsedSpace{ RegStartPos },\n\t_regOutSize{ 0 }, _regOutName{ },\n\t_name{ name }\n{\n\t//--------------------------------------------------\n\t//\t\t\t\t\top_data init\n\t//--------------------------------------------------\n\t#define MACRO_ALL_INIT(NAME, IMPL, ARGS, DESC) \\\n\t\taddParserBase(#NAME, DESC, nullptr, helper::FuncGroup<MACRO_FUNC_ID(NAME)>::overloadType(), &parseBuildinProc<MACRO_PROC_ID(NAME), helper::FuncGroup<MACRO_FUNC_ID(NAME)>>, nullptr, nullptr);\n\n\tMACRO_PROC_DEFINITION(MACRO_ALL_INIT)\n\n\t#undef MACRO_ALL_INIT\n\n\tauto buildin = [&](const std::string& s, ScriptProcData::parserFunc func)\n\t{\n\t\taddParserBase(s, {}, &overloadBuildinProc, {}, func, nullptr, nullptr);\n\t};\n\n\tbuildin(\"if\", &parseIf);\n\tbuildin(\"else\", &parseElse);\n\tbuildin(\"end\", &parseEnd);\n\tbuildin(\"var\", &parseVar);\n\tbuildin(\"const\", &parseConst);\n\tbuildin(\"debug_log\", &parseDebugLog);\n\tbuildin(\"debug_assert\", &parseDummy);\n\tbuildin(\"loop\", &parseLoop);\n\tbuildin(\"break\", &parseBreak);\n\tbuildin(\"continue\", &parseContinue);\n\tbuildin(\"return\", &parseReturn);\n\tbuildin(\"begin\", &parseBegin);\n\n\taddParser<helper::FuncGroup<Func_test_eq_null>>(\"test_eq\", \"\");\n\taddParser<helper::FuncGroup<Func_debug_impl_int>>(\"debug_impl\", \"\");\n\taddParser<helper::FuncGroup<Func_debug_impl_text>>(\"debug_impl\", \"\");\n\taddParser<helper::FuncGroup<Func_debug_flush>>(\"debug_flush\", \"\");\n\n\taddParser<helper::FuncGroup<Func_set_text>>(\"set\", \"\");\n\taddParser<helper::FuncGroup<Func_clear_text>>(\"clear\", \"\");\n\taddParser<helper::FuncGroup<Func_test_eq_text>>(\"test_eq\", \"\");\n\n\taddType<ScriptInt>(\"int\");\n\taddType<ScriptText>(\"text\");\n\taddType<ScriptArgSeparator>(\"__\");\n\n\tauto labelName = addNameRef(\"label\");\n\tauto nullName = addNameRef(\"null\");\n\tauto phName = addNameRef(\"_\");\n\tauto seperatorName = addNameRef(\"__\");\n\tauto varName = addNameRef(\"var\");\n\tauto constName = addNameRef(\"const\");\n\n\taddSortHelper(_typeList, { labelName, ArgLabel, { } });\n\taddSortHelper(_typeList, { nullName, ArgNull, { } });\n\taddSortHelper(_refList, { nullName, ArgNull });\n\taddSortHelper(_refList, { phName, ArgPlaceholder });\n\taddSortHelper(_refList, { seperatorName, ArgSep });\n\taddSortHelper(_refList, { varName, ArgInvalid });\n\taddSortHelper(_refList, { constName, ArgInvalid });\n\n\t_shared->initParserGlobals(this);\n}\n\n/**\n * Destructor\n */\nScriptParserBase::~ScriptParserBase()\n{\n\n}\n\n/**\n * Test if that name is already in use.\n */\nbool ScriptParserBase::haveNameRef(const std::string& s) const\n{\n\tauto ref = ScriptRef{ s.data(), s.data() + s.size() };\n\tif (findSortHelper(_refList, ref) != nullptr)\n\t{\n\t\treturn true;\n\t}\n\tif (findSortHelper(_procList, ref) != nullptr)\n\t{\n\t\treturn true;\n\t}\n\tif (findSortHelper(_typeList, ref) != nullptr)\n\t{\n\t\treturn true;\n\t}\n\tfor (auto& r : ConditionNames)\n\t{\n\t\tif (ref == r)\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t}\n\tfor (auto& r : ConditionSpecNames)\n\t{\n\t\tif (ref == r)\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Store new name reference for future use.\n */\nScriptRef ScriptParserBase::addNameRef(const std::string& s)\n{\n\treturn addString(_strings, s);\n}\n\n/**\n * Add new function parsing arguments of script operation.\n * @param s function name\n * @param parser parsing function\n */\nvoid ScriptParserBase::addParserBase(const std::string& s, const std::string& description, ScriptProcData::overloadFunc overload, ScriptRange<ScriptRange<ArgEnum>> overloadArg, ScriptProcData::parserFunc parser, ScriptProcData::argFunc arg, ScriptProcData::getFunc get)\n{\n\tif (haveNameRef(s))\n\t{\n\t\tauto procs = getProc(ScriptRef{ s.data(), s.data() + s.size() });\n\t\tif (!procs)\n\t\t{\n\t\t\tthrow Exception(\"Function name '\" + s + \"' already used\");\n\t\t}\n\t}\n\tif (!parser)\n\t{\n\t\tparser = &parseCustomProc;\n\t}\n\tif (!overload)\n\t{\n\t\toverload = validOverloadProc(overloadArg) ? &overloadCustomProc : &overloadInvalidProc;\n\t}\n\taddSortHelper(_procList, { addNameRef(s), addNameRef(description), overload, overloadArg, parser, arg, get });\n}\n\n/**\n * Add new type to parser.\n * @param s Type name.\n * @param type\n * @param size\n */\nvoid ScriptParserBase::addTypeBase(const std::string& s, ArgEnum type, TypeInfo meta)\n{\n\tif (haveNameRef(s))\n\t{\n\t\tthrow Exception(\"Type name '\" + s + \"' already used\");\n\t}\n\n\taddSortHelper(_typeList, { addNameRef(s), ArgBase(type), meta });\n}\n\n/**\n * Test if type is already used.\n */\nbool ScriptParserBase::haveTypeBase(ArgEnum type)\n{\n\ttype = ArgBase(type);\n\tfor (auto& v : _typeList)\n\t{\n\t\tif (v.type == type)\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Set name for custom script parameter.\n * @param s name for custom parameter.\n * @param type type of custom parameter.\n * @param outputReg is this reg used for script output.\n */\nvoid ScriptParserBase::addScriptReg(const std::string& s, ArgEnum type, bool writableReg, bool outputReg)\n{\n\tif (writableReg || outputReg)\n\t{\n\t\tif (outputReg && _regOutSize >= ScriptMaxOut)\n\t\t{\n\t\t\tthrow Exception(\"Custom output reg limit reach for: '\" + s + \"'\");\n\t\t}\n\t\ttype = ArgSpecAdd(type, ArgSpecVar);\n\t}\n\telse\n\t{\n\t\ttype = ArgSpecAdd(ArgSpecRemove(type, ArgSpecVar), ArgSpecReg);\n\t}\n\tauto t = getType(type);\n\tif (t == nullptr)\n\t{\n\t\tthrow Exception(\"Invalid type for reg: '\" + s + \"'\");\n\t}\n\tauto meta = getRegMeta(*this, type);\n\tif (!meta)\n\t{\n\t\tthrow Exception(\"Invalid use of type '\" + t->name.toString() + \"' for reg: '\" + s + \"'\");\n\t}\n\tif (meta.needRegSpace(_regUsedSpace) <= ScriptMaxReg)\n\t{\n\t\tif (haveNameRef(s))\n\t\t{\n\t\t\tthrow Exception(\"Reg name '\" + s + \"' already used\");\n\t\t}\n\n\t\tauto name = addNameRef(s);\n\t\tif (outputReg)\n\t\t{\n\t\t\t_regOutName[_regOutSize++] = name;\n\t\t}\n\t\tauto old = meta.nextRegPos(_regUsedSpace);\n\t\t_regUsedSpace = meta.needRegSpace(_regUsedSpace);\n\t\taddSortHelper(_refList, { name, type, static_cast<RegEnum>(old) });\n\t}\n\telse\n\t{\n\t\tthrow Exception(\"Custom reg limit reach for: '\" + s + \"'\");\n\t}\n}\n\n/**\n * Add const value to script.\n * @param s name for const.\n * @param i value.\n */\nvoid ScriptParserBase::addConst(const std::string& s, ScriptValueData i)\n{\n\tif (haveNameRef(s))\n\t{\n\t\tthrow Exception(\"Const name '\" + s + \"' already used\");\n\t}\n\n\taddSortHelper(_refList, { addNameRef(s), i.type, i });\n}\n\n/**\n * Update const value in script.\n * @param s name for const.\n * @param i new value.\n */\nvoid ScriptParserBase::updateConst(const std::string& s, ScriptValueData i)\n{\n\tScriptRefData* f = findSortHelper(_refList, ScriptRef{ s.data(), s.data() + s.size() });\n\tif (!f)\n\t{\n\t\tthrow Exception(\"Unknown const with name '\" + s + \"' to update\");\n\t}\n\tif (f->type != i.type)\n\t{\n\t\tthrow Exception(\"Incompatible const with name '\" + s + \"' to update\");\n\t}\n\tf->value = i;\n}\n/**\n * Get name of type\n * @param type Type id.\n */\nScriptRef ScriptParserBase::getTypeName(ArgEnum type) const\n{\n\tauto p = getType(type);\n\tif (p)\n\t{\n\t\treturn p->name;\n\t}\n\telse\n\t{\n\t\treturn ScriptRef{ };\n\t}\n}\n\n/**\n * Get full name of type.\n * @param type\n * @return Full name with e.g. `var` or `ptr`.\n */\nstd::string ScriptParserBase::getTypePrefix(ArgEnum type) const\n{\n\tstd::string prefix;\n\tif (ArgIsVar(type))\n\t{\n\t\tprefix = \"var \";\n\t}\n\tif (ArgIsPtr(type))\n\t{\n\t\tif (ArgIsPtrE(type))\n\t\t{\n\t\t\tprefix += \"ptre \";\n\t\t}\n\t\telse\n\t\t{\n\t\t\tprefix += \"ptr \";\n\t\t}\n\t}\n\treturn prefix;\n}\n\n/**\n * Get type data.\n * @param type Type id.\n */\nconst ScriptTypeData* ScriptParserBase::getType(ArgEnum type) const\n{\n\tArgEnum base = ArgBase(type);\n\tfor (auto& t : _typeList)\n\t{\n\t\tif (t.type == base)\n\t\t{\n\t\t\treturn &t;\n\t\t}\n\t}\n\treturn nullptr;\n}\n\n/**\n * Get type data with name equal prefix + postfix.\n * @param name Name split in parts.\n * @return Pointer to data or null if not find.\n */\nconst ScriptTypeData* ScriptParserBase::getType(ScriptRange<ScriptRef> name) const\n{\n\treturn findSortHelper(_typeList, name);\n}\n\n/**\n * Get function data with name equal prefix + postfix.\n * @param name Name split in parts.\n * @return Pointer to data or null if not find.\n */\nScriptRange<ScriptProcData> ScriptParserBase::getProc(ScriptRange<ScriptRef> name) const\n{\n\tauto lower = _procList.data();\n\tauto upper = _procList.data() + _procList.size();\n\tlower = boundSortHelper<false>(lower, upper, name);\n\tupper = boundSortHelper<true>(lower, upper, name);\n\n\treturn { lower, upper };\n}\n\n/**\n * Get arguments data with name equal prefix + postfix.\n * @param name Name split in parts.\n * @return Pointer to data or null if not find.\n */\nconst ScriptRefData* ScriptParserBase::getRef(ScriptRange<ScriptRef> name) const\n{\n\treturn findSortHelper(_refList, name);\n}\n\n/**\n * Parse string and write script to ScriptBase\n * @param src struct where final script is write to\n * @param src_code string with script\n * @return true if string have valid script\n */\nbool ScriptParserBase::parseBase(ScriptContainerBase& destScript, const std::string& parentName, const std::string& srcCode) const\n{\n\tScriptContainerBase tempScript;\n\tstd::string err = \"Error in parsing script '\" + _name + \"' for '\" + parentName + \"': \";\n\tParserWriter help(\n\t\t_regUsedSpace,\n\t\ttempScript,\n\t\t*this\n\t);\n\n\tbool haveLastReturn = false;\n\tbool haveCodeNormal = false;\n\tScriptRefTokens range = ScriptRefTokens{ srcCode.data(), srcCode.data() + srcCode.size() };\n\tif (!range)\n\t{\n\t\treturn false;\n\t}\n\n\twhile (true)\n\t{\n\t\tSelectedToken op = range.getNextToken();\n\t\tif (!op)\n\t\t{\n//\t\t\tfor (auto i = help.refListCurr.begin(); i != help.refListCurr.end(); ++i)\n//\t\t\t{\n//\t\t\t\tif (i->type == ArgLabel && help.refLabels.getValue(i->value) == ProgPos::Unknown)\n//\t\t\t\t{\n//\t\t\t\t\tLog(LOG_ERROR) << err << \"invalid use of label: '\" << i->name.toString() << \"' without declaration\";\n//\t\t\t\t\treturn false;\n//\t\t\t\t}\n//\t\t\t}\n\t\t\tif (help.codeBlocks.size() > 1)\n\t\t\t{\n\t\t\t\tLog(LOG_ERROR) << err << \"script have missed 'end;'\";\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (!haveLastReturn)\n\t\t\t{\n\t\t\t\tLog(LOG_ERROR) << err << \"script need to end with return statement\";\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\thelp.relese();\n\t\t\tdestScript = std::move(tempScript);\n\t\t\treturn true;\n\t\t}\n\n\t\tauto line_begin = op.begin();\n\t\tSelectedToken label = { };\n\t\tSelectedToken args[ScriptMaxArg];\n\t\targs[0] = range.getNextToken(TokenColon);\n\t\tif (args[0].getType() == TokenColon)\n\t\t{\n\t\t\tstd::swap(op, label);\n\t\t\top = range.getNextToken();\n\t\t\targs[0] = range.getNextToken();\n\t\t}\n\n\t\tScriptRefOperation op_curr = findOperationAndArg(help, op);\n\t\tif (!op_curr)\n\t\t{\n\t\t\tlogErrorOnOperationArg(op_curr);\n\t\t\tLog(LOG_ERROR) << \"Invalid operation '\" << op.toString() << \"'\";\n\t\t}\n\n\t\t// change form of `Reg.Function` to `Type.Function Reg`.\n\t\tif (op_curr.haveArg())\n\t\t{\n\t\t\t// we already loaded op_curr = \"Reg.Function\", args[0] = \"X\"\n\t\t\t// then switch it to op_curr = \"Type.Function\", args[0] = \"Reg\", args[1] = \"X\"\n\t\t\targs[1] = args[0];\n\t\t\targs[0] = { TokenSymbol, op_curr.argName, op.getLinePos() };\n\t\t}\n\n\t\tfor (size_t i = (op_curr.haveArg() ? 2 : 1); i < ScriptMaxArg; ++i)\n\t\t\targs[i] = range.getNextToken();\n\t\tSelectedToken f = range.getNextToken(TokenSemicolon);\n\n\t\t//validation\n\t\tbool valid = true;\n\t\tvalid &= label.getType() == TokenSymbol || label.getType() == TokenNone;\n\t\tvalid &= op.getType() == TokenSymbol;\n\t\tfor (size_t i = 0; i < ScriptMaxArg; ++i)\n\t\t\tvalid &= args[i].getType() != TokenInvalid;\n\t\tvalid &= f.getType() == TokenSemicolon;\n\n\t\tif (!valid)\n\t\t{\n\t\t\tauto line_end = range.begin();\n\t\t\tif (f.getType() != TokenSemicolon)\n\t\t\t{\n\t\t\t\t// fixing `line_end` position.\n\t\t\t\twhile(line_end != range.end() && *line_end != ';')\n\t\t\t\t\t++line_end;\n\t\t\t\tif (line_end != range.end())\n\t\t\t\t\t++line_end;\n\t\t\t}\n\n\t\t\tfor (size_t i = 0; i < ScriptMaxArg; ++i)\n\t\t\t{\n\t\t\t\tif (args[i].getType() == TokenInvalid)\n\t\t\t\t{\n\t\t\t\t\tLog(LOG_ERROR) << err << \"invalid argument '\"<<  args[i].toString() <<\"' in line: '\" << std::string(line_begin, line_end) << \"' (at \" + std::to_string(op.getLinePos()) + \")\";\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tLog(LOG_ERROR) << err << \"invalid line: '\" << std::string(line_begin, line_end) << \"' (at \" + std::to_string(op.getLinePos()) + \")\";\n\t\t\treturn false;\n\t\t}\n\n\t\tScriptRef line = ScriptRef{ line_begin, range.begin() };\n\n\t\t// test validity of operation positions\n\t\tauto isReturn = (op == ScriptRef{ \"return\" });\n\t\tauto isVarDef = (op == ScriptRef{ \"var\" }) || (op == ScriptRef{ \"const\" });\n\t\tauto isBegin = (op == ScriptRef{ \"if\" }) || (op == ScriptRef{ \"else\" }) || (op == ScriptRef{ \"begin\" }) || (op == ScriptRef{ \"loop\" });\n\t\tauto isEnd = (op == ScriptRef{ \"end\" }) || (op == ScriptRef{ \"else\" }); // `else;` is begin and end of scope\n\t\tauto isBreak = (op == ScriptRef{ \"continue\" } || op == ScriptRef{ \"break\" });\n\n\t\tif (haveLastReturn && !isEnd)\n\t\t{\n\t\t\tLog(LOG_ERROR) << err << \"unreachable code after return in line: '\" << line.toString() << \"' (at \" + std::to_string(op.getLinePos()) + \")\";\n\t\t\treturn false;\n\t\t}\n\t\tif (haveCodeNormal && isVarDef)\n\t\t{\n\t\t\tLog(LOG_ERROR) << err << \"invalid variable definition after other operations in line: '\" << line.toString() << \"' (at \" + std::to_string(op.getLinePos()) + \")\";\n\t\t\treturn false;\n\t\t}\n\t\tif (label && isVarDef)\n\t\t{\n\t\t\tLog(LOG_ERROR) << err << \"label can't be before variable definition in line: '\" << line.toString() << \"' (at \" + std::to_string(op.getLinePos()) + \")\";\n\t\t\treturn false;\n\t\t}\n\n\t\thaveLastReturn = isReturn || isBreak;\n\t\thaveCodeNormal = !(isVarDef || isBegin); // we can have `var` only on begining of new scope\n\n\n\t\t// matching args from operation definition with args available in string\n\t\tScriptArgList argData = { };\n\t\tfor (const SelectedToken& t : args)\n\t\t{\n\t\t\tif (t.getType() == TokenNone)\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif (!argData.tryPushBack(t.parse(help)))\n\t\t\t{\n\t\t\t\tLog(LOG_ERROR) << err << \"too many arguments in line: '\" << line.toString() << \"' (at \" + std::to_string(op.getLinePos()) + \")\";\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tif (label && !help.setLabel(label.parse(help), help.getCurrPos()))\n\t\t{\n\t\t\tLog(LOG_ERROR) << err << \"invalid label '\"<< label.toString() <<\"' in line: '\" << line.toString() << \"' (at \" + std::to_string(op.getLinePos()) + \")\";\n\t\t\treturn false;\n\t\t}\n\n\t\t// create normal proc call\n\t\tif (parseOverloadProc(help, op_curr.procList, std::begin(argData), std::end(argData)) == false)\n\t\t{\n\t\t\tLog(LOG_ERROR) << err << \"invalid operation in line: '\" << line.toString() << \"' (at \" + std::to_string(op.getLinePos()) + \")\";\n\t\t\treturn false;\n\t\t}\n\t}\n}\n\n/**\n * Parse node and return new script.\n */\nvoid ScriptParserBase::parseNode(ScriptContainerBase& container, const std::string& parentName, const YAML::YamlNodeReader& reader) const\n{\n\tif(const YAML::YamlNodeReader& scripts = reader[\"scripts\"])\n\t{\n\t\tif (const YAML::YamlNodeReader& curr = scripts[ryml::to_csubstr(getName())])\n\t\t{\n\t\t\tif (false == parseBase(container, parentName, curr.readVal<std::string>()))\n\t\t\t{\n\t\t\t\tLog(LOG_ERROR) << \"    for node with code at line \" << reader.getLocationInFile().line << \" in \" << getGlobal()->getCurrentFile();\n\t\t\t\tLog(LOG_ERROR) << \"\"; // dummy line to separate similar errors\n\t\t\t}\n\t\t}\n\t}\n\tif (!container && !getDefault().empty())\n\t{\n\t\tif (false == parseBase(container, parentName, getDefault()))\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"\"; // dummy line to separate similar errors\n\t\t}\n\t}\n}\n\n/**\n * Parse string and return new script.\n */\nvoid ScriptParserBase::parseCode(ScriptContainerBase& container, const std::string& parentName, const std::string& srcCode) const\n{\n\tif (!srcCode.empty())\n\t{\n\t\tif (false == parseBase(container, parentName, srcCode))\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"    for code in \" << getGlobal()->getCurrentFile();\n\t\t\tLog(LOG_ERROR) << \"\"; // dummy line to separate similar errors\n\t\t}\n\t}\n\tif (!container && !getDefault().empty())\n\t{\n\t\tif (false == parseBase(container, parentName, getDefault()))\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"\"; // dummy line to separate similar errors\n\t\t}\n\t}\n}\n\n/**\n * Print all metadata\n */\nvoid ScriptParserBase::logScriptMetadata(bool haveEvents, const std::string& groupName) const\n{\n\tif (Options::debug && Options::verboseLogging)\n\t{\n\t\tauto argType = [&](ArgEnum type) -> std::string\n\t\t{\n\t\t\treturn getTypeName(type).toString();\n\t\t};\n\n\t\tconst int tabSize = 8;\n\t\tstatic bool printOp = true;\n\t\tif (printOp)\n\t\t{\n\t\t\tsize_t offset = 0;\n\t\t\tprintOp = false;\n\t\t\tLogger opLog;\n\t\t\t#define MACRO_STRCAT(...) #__VA_ARGS__\n\t\t\t#define MACRO_ALL_LOG(NAME, Impl, Args, Desc, ...) \\\n\t\t\t\tif (validOverloadProc(helper::FuncGroup<MACRO_FUNC_ID(NAME)>::overloadType()) && strlen(Desc) != 0) opLog.get(LOG_DEBUG) \\\n\t\t\t\t\t<< \"Op:   \" << std::setw(tabSize*2) << #NAME \\\n\t\t\t\t\t<< \"OpId: \" << std::setw(tabSize/2) << offset << \" .. \" <<  std::setw(tabSize) << (offset + helper::FuncGroup<MACRO_FUNC_ID(NAME)>::ver() - 1) \\\n\t\t\t\t\t<< \"Args: \" << std::setw(tabSize*5) << displayOverloadProc(this, helper::FuncGroup<MACRO_FUNC_ID(NAME)>::overloadType()) \\\n\t\t\t\t\t<< \"Desc: \" << Desc \\\n\t\t\t\t\t<< \"\\n\"; \\\n\t\t\t\toffset += helper::FuncGroup<MACRO_FUNC_ID(NAME)>::ver();\n\n\t\t\topLog.get(LOG_DEBUG) << \"Available built-in script operations:\\n\" << std::left << std::hex << std::showbase;\n\t\t\tMACRO_PROC_DEFINITION(MACRO_ALL_LOG)\n\n\t\t\t#undef MACRO_ALL_LOG\n\t\t\t#undef MACRO_STRCAT\n\n\t\t\topLog.get(LOG_DEBUG) << \"Total size: \" << offset << \"\\n\";\n\t\t}\n\n\t\tLogger refLog;\n\t\trefLog.get(LOG_DEBUG) << \"Script info for:  '\" << _name << \"'  in group:  '\" << groupName << \"'\\n\" << std::left;\n\t\trefLog.get(LOG_DEBUG) << \"\\n\";\n\t\tif (haveEvents)\n\t\t{\n\t\t\trefLog.get(LOG_DEBUG) << \"Have global events\\n\";\n\t\t\trefLog.get(LOG_DEBUG) << \"\\n\";\n\t\t}\n\t\tif (!_description.empty())\n\t\t{\n\t\t\trefLog.get(LOG_DEBUG) << \"Description:\\n\";\n\t\t\trefLog.get(LOG_DEBUG) << _description << \"\\n\";\n\t\t\trefLog.get(LOG_DEBUG) << \"\\n\";\n\t\t}\n\t\tif (!_defaultScript.empty())\n\t\t{\n\t\t\trefLog.get(LOG_DEBUG) << \"Script default implementation:\\n\";\n\t\t\trefLog.get(LOG_DEBUG) << _defaultScript << \"\\n\";\n\t\t\trefLog.get(LOG_DEBUG) << \"\\n\";\n\t\t}\n\t\tif (_regOutSize > 0)\n\t\t{\n\t\t\trefLog.get(LOG_DEBUG) << \"Script return values:\\n\";\n\t\t\tfor (size_t i = 0; i < _regOutSize; ++i)\n\t\t\t{\n\t\t\t\tauto ref = getRef(_regOutName[i]);\n\t\t\t\tif (ref)\n\t\t\t\t{\n\t\t\t\t\trefLog.get(LOG_DEBUG) << \"Name: \" << std::setw(40) << ref->name.toString() << std::setw(9) << getTypePrefix(ref->type) << \" \" << std::setw(9) << argType(ref->type) << \"\\n\";\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (_emptyReturn)\n\t\t\t{\n\t\t\t\trefLog.get(LOG_DEBUG) << \"In this script 'return' statement is empty, script returning values are edited directly\\n\";\n\t\t\t}\n\t\t\trefLog.get(LOG_DEBUG) << \"\\n\";\n\t\t}\n\t\trefLog.get(LOG_DEBUG) << \"Script data:\\n\";\n\t\tauto temp = _refList;\n\t\tstd::sort(temp.begin(), temp.end(),\n\t\t\t[](const ScriptRefData& a, const ScriptRefData& b)\n\t\t\t{\n\t\t\t\treturn std::lexicographical_compare(a.name.begin(), a.name.end(), b.name.begin(), b.name.end());\n\t\t\t}\n\t\t);\n\t\tfor (auto& r : temp)\n\t\t{\n\t\t\tif ((!ArgIsReg(r.type) && !ArgIsPtr(r.type) && Logger::reportingLevel() != LOG_VERBOSE) || ArgBase(r.type) == ArgInvalid)\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (ArgBase(r.type) == ArgInt && !ArgIsReg(r.type))\n\t\t\t{\n\t\t\t\trefLog.get(LOG_DEBUG) << \"Name: \" << std::setw(40) << r.name.toString() << std::setw(9) << getTypePrefix(r.type) << \" \" << std::setw(9) << argType(r.type) << \" \" << r.value.getValue<int>() << \"\\n\";\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\trefLog.get(LOG_DEBUG) << \"Name: \" << std::setw(40) << r.name.toString() << std::setw(9) << getTypePrefix(r.type) << \" \" << std::setw(9) << argType(r.type) << \"\\n\";\n\t\t\t}\n\t\t}\n\t\tif (Logger::reportingLevel() != LOG_VERBOSE)\n\t\t{\n\t\t\trefLog.get(LOG_DEBUG) << \"To see const values and custom operations use 'verboseLogging'\\n\";\n\t\t}\n\t\telse\n\t\t{\n\t\t\tauto tmp = _procList;\n\t\t\tstd::sort(tmp.begin(), tmp.end(),\n\t\t\t\t[](const ScriptProcData& a, const ScriptProcData& b)\n\t\t\t\t{\n\t\t\t\t\treturn std::lexicographical_compare(a.name.begin(), a.name.end(), b.name.begin(), b.name.end());\n\t\t\t\t}\n\t\t\t);\n\n\t\t\trefLog.get(LOG_DEBUG) << \"\\n\";\n\t\t\trefLog.get(LOG_DEBUG) << \"Script operations:\\n\";\n\t\t\tfor (const auto& p : tmp)\n\t\t\t{\n\t\t\t\tif (p.parserArg != nullptr && p.overloadArg && p.description != ScriptRef{ BindBase::functionInvisible })\n\t\t\t\t{\n\t\t\t\t\tconst auto tabStop = 4; // alignment of next part\n\t\t\t\t\tconst auto minSpace = 2; // min space to next part\n\n\t\t\t\t\tauto name = p.name.toString();\n\t\t\t\t\tauto nameTab = std::max(\n\t\t\t\t\t\t(((int)name.size() + minSpace + tabStop - 1) & -tabStop),\n\t\t\t\t\t\t40\n\t\t\t\t\t);\n\n\t\t\t\t\tauto args = displayOverloadProc(this, p.overloadArg);\n\t\t\t\t\tauto argsTab = std::max(\n\t\t\t\t\t\t(((int)args.size() + minSpace + tabStop - 1) & -tabStop),\n\t\t\t\t\t\t48\n\t\t\t\t\t);\n\n\t\t\t\t\trefLog.get(LOG_DEBUG) << \"Name: \" << std::setw(nameTab) << name << \"Args: \" << std::setw(argsTab) << args << (p.description != ScriptRef{ BindBase::functionWithoutDescription } ? std::string(\"Desc: \") + p.description.toString() + \"\\n\" : \"\\n\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n////////////////////////////////////////////////////////////\n//\t\t\t\tScriptParserEventsBase class\n////////////////////////////////////////////////////////////\n\n/**\n * Constructor.\n */\nScriptParserEventsBase::ScriptParserEventsBase(ScriptGlobal* shared, const std::string& name) : ScriptParserBase(shared, name)\n{\n\t_events.reserve(EventsMax);\n\t_eventsData.push_back({ 0, {}, {} });\n}\n\n/**\n * Parse node and return new script.\n */\nvoid ScriptParserEventsBase::parseNode(ScriptContainerEventsBase& container, const std::string& type, const YAML::YamlNodeReader& reader) const\n{\n\tScriptParserBase::parseNode(container._current, type, reader);\n\tcontainer._events = getEvents();\n}\n\n/**\n * Parse string and return new script.\n */\nvoid ScriptParserEventsBase::parseCode(ScriptContainerEventsBase& container, const std::string& type, const std::string& srcCode) const\n{\n\tScriptParserBase::parseCode(container._current, type, srcCode);\n\tcontainer._events = getEvents();\n}\n\n/**\n * Load global data from YAML.\n */\nvoid ScriptParserEventsBase::loadEvents(const YAML::YamlNodeReader& scripts)\n{\n\t// helper functions to get position in data vector\n\tauto findPos = [&](const std::string& n)\n\t{\n\t\treturn std::find_if(std::begin(_eventsData), std::end(_eventsData), [&](const EventData& p) { return p.name == n; });\n\t};\n\tauto havePos = [&](std::vector<EventData>::iterator it)\n\t{\n\t\treturn it != std::end(_eventsData);\n\t};\n\tauto removePos = [&](std::vector<EventData>::iterator it)\n\t{\n\t\t_eventsData.erase(it);\n\t};\n\n\tauto getNode = [&](const YAML::YamlNodeReader& i, const std::string& nodeName)\n\t{\n\t\tauto n = i[ryml::to_csubstr(nodeName)];\n\t\treturn std::make_tuple(nodeName, std::move(n), !!n);\n\t};\n\tauto haveNode = [&](const std::tuple<std::string, YAML::YamlNodeReader, bool>& nn)\n\t{\n\t\treturn std::get<bool>(nn);\n\t};\n\tauto getLineFromNode = [&](const YAML::YamlNodeReader& n)\n\t{\n\t\treturn std::to_string(n.getLocationInFile().line);\n\t};\n\tauto getDescriptionNode = [&](const std::tuple<std::string, YAML::YamlNodeReader, bool>& nn)\n\t{\n\t\treturn std::string(\"'\") + std::get<std::string>(nn) + \"' at line \" + getLineFromNode(std::get<YAML::YamlNodeReader>(nn));\n\t};\n\tauto getNameFromNode = [&](const std::tuple<std::string, YAML::YamlNodeReader, bool>& nn)\n\t{\n\t\tauto name = std::get<YAML::YamlNodeReader>(nn).readVal<std::string>();\n\t\tif (name.empty())\n\t\t{\n\t\t\tthrow Exception(\"Invalid name for \" + getDescriptionNode(nn));\n\t\t}\n\t\treturn name;\n\t};\n\n\tif (scripts)\n\t{\n\t\tfor (const YAML::YamlNodeReader& i : scripts.children())\n\t\t{\n\t\t\tconst auto deleteNode = getNode(i, \"delete\");\n\t\t\tconst auto newNode = getNode(i, \"new\");\n\t\t\tconst auto overrideNode = getNode(i, \"override\");\n\t\t\tconst auto updateNode = getNode(i, \"update\");\n\t\t\tconst auto ignoreNode = getNode(i, \"ignore\");\n\n\t\t\t// default name for case when use don't define node with name\n\t\t\tauto name = std::string{ };\n\n\t\t\t{\n\t\t\t\t// check for duplicates\n\t\t\t\tconst std::tuple<std::string, YAML::YamlNodeReader, bool>* last = nullptr;\n\t\t\t\tfor (auto* p : { &deleteNode, &newNode, &updateNode, &overrideNode, &ignoreNode })\n\t\t\t\t{\n\t\t\t\t\tif (haveNode(*p))\n\t\t\t\t\t{\n\t\t\t\t\t\tif (last)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tthrow Exception(\"Conflict of \" + getDescriptionNode(*last) + \" and \" + getDescriptionNode(*p));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlast = p;\n\t\t\t\t\t\t\tname = getNameFromNode(*p);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (haveNode(deleteNode))\n\t\t\t{\n\t\t\t\tauto it = findPos(name);\n\t\t\t\tif (havePos(it))\n\t\t\t\t{\n\t\t\t\t\tremovePos(it);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tLog(LOG_WARNING) << \"Unknown script name '\" + name  + \"' for \" + getDescriptionNode(deleteNode);\n\t\t\t\t\tLog(LOG_WARNING) << \"    in \" << getGlobal()->getCurrentFile();\n\t\t\t\t\tLog(LOG_WARNING) << \"\"; // dummy line to separate similar errors\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tint offset = 0;\n\t\t\t\tScriptContainerBase scp;\n\n\n\t\t\t\toffset = i[\"offset\"].readVal<double>(0) * OffsetScale;\n\t\t\t\tif (offset == 0 || offset >= (int)OffsetMax || offset <= -(int)OffsetMax)\n\t\t\t\t{\n\t\t\t\t\t//TODO: make it a exception\n\t\t\t\t\tLog(LOG_ERROR) << \"Invalid offset for '\" << getName() << \"' equal: '\" << i[\"offset\"].readVal<std::string>() << \"'\";\n\t\t\t\t\tLog(LOG_ERROR) << \"    for node at line \" << getLineFromNode(i[\"offset\"]) << \" in \" << getGlobal()->getCurrentFile();\n\t\t\t\t\tLog(LOG_ERROR) << \"\"; // dummy line to separate similar errors\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t{\n\t\t\t\t\tauto nameWithPrefix = name.size() ? \"Global:\" + name : \"Global off: \" + i[\"offset\"].readVal<std::string>();\n\t\t\t\t\tif (false == parseBase(scp, nameWithPrefix, i[\"code\"].readVal<std::string>(\"\")))\n\t\t\t\t\t{\n\t\t\t\t\t\tLog(LOG_ERROR) << \"    for node with code at line \" << getLineFromNode(i[\"code\"]) << \" in \" << getGlobal()->getCurrentFile();\n\t\t\t\t\t\tLog(LOG_ERROR) << \"\"; // dummy line to separate similar errors\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\n\t\t\t\tif (haveNode(updateNode))\n\t\t\t\t{\n\t\t\t\t\tauto it = findPos(name);\n\t\t\t\t\tif (havePos(it))\n\t\t\t\t\t{\n\t\t\t\t\t\tit->offset = offset;\n\t\t\t\t\t\tit->script = std::move(scp);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tLog(LOG_WARNING) << \"Unknown script name '\" + name + \"' for \" + getDescriptionNode(updateNode);\n\t\t\t\t\t\tLog(LOG_WARNING) << \"    in \" << getGlobal()->getCurrentFile();\n\t\t\t\t\t\tLog(LOG_WARNING) << \"\"; // dummy line to separate similar errors\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (haveNode(overrideNode))\n\t\t\t\t{\n\t\t\t\t\tauto it = findPos(name);\n\t\t\t\t\tif (havePos(it))\n\t\t\t\t\t{\n\t\t\t\t\t\tit->offset = offset;\n\t\t\t\t\t\tit->script = std::move(scp);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tthrow Exception(\"Unknown script name '\" + name + \"' for \" + getDescriptionNode(overrideNode));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (haveNode(ignoreNode))\n\t\t\t\t{\n\t\t\t\t\t// nothing to see there...\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif (haveNode(newNode))\n\t\t\t\t\t{\n\t\t\t\t\t\tauto it = findPos(name);\n\t\t\t\t\t\tif (havePos(it))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tthrow Exception(\"Script script name '\" + name + \"' already used for \" + getDescriptionNode(newNode));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tEventData data = EventData{};\n\t\t\t\t\tdata.name = name;\n\t\t\t\t\tdata.offset = offset;\n\t\t\t\t\tdata.script = std::move(scp);\n\t\t\t\t\t_eventsData.push_back(std::move(data));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Get pointer to events.\n */\nconst ScriptContainerBase* ScriptParserEventsBase::getEvents() const\n{\n\treturn _events.data();\n}\n\n/**\n * Release event data.\n */\nstd::vector<ScriptContainerBase> ScriptParserEventsBase::releseEvents()\n{\n\tstd::sort(std::begin(_eventsData), std::end(_eventsData), [](const EventData& a, const EventData& b) { return a.offset < b.offset; });\n\tfor (auto& e : _eventsData)\n\t{\n\t\tconst auto reservedSpaceForZero = e.offset < 0;\n\t\tif (_events.size() + (reservedSpaceForZero ?  2 : 1) < EventsMax)\n\t\t{\n\t\t\t_events.push_back(std::move(e.script));\n\t\t}\n\t\telse\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"Error in script parser '\" << getName() << \"': global script limit reach\";\n\t\t\tif (reservedSpaceForZero)\n\t\t\t{\n\t\t\t\t_events.emplace_back();\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n\t_events.emplace_back();\n\treturn std::move(_events);\n}\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tScriptValuesBase class\n////////////////////////////////////////////////////////////\n\n/**\n * Set value.\n */\nvoid ScriptValuesBase::setBase(size_t t, int i)\n{\n\tif (t)\n\t{\n\t\tif (t > values.size())\n\t\t{\n\t\t\tvalues.resize(t);\n\t\t}\n\t\tvalues[t - 1u] = i;\n\t}\n}\n\n/**\n * Get value.\n */\nint ScriptValuesBase::getBase(size_t t) const\n{\n\tif (t && t <= values.size())\n\t{\n\t\treturn values[t - 1u];\n\t}\n\treturn 0;\n}\n\n/**\n * Load values from yaml file.\n */\nvoid ScriptValuesBase::loadBase(const YAML::YamlNodeReader& reader, const ScriptGlobal* shared, ArgEnum type, const std::string& nodeName)\n{\n\tif (const YAML::YamlNodeReader& tags = reader[ryml::to_csubstr(nodeName)])\n\t{\n\t\tif (tags.isMap())\n\t\t{\n\t\t\tfor (const YAML::YamlNodeReader& tag : tags.children())\n\t\t\t{\n\t\t\t\tsize_t i = shared->getTag(type, ScriptRef::tempFrom(\"Tag.\" + tag.readKey<std::string>()));\n\t\t\t\tif (i)\n\t\t\t\t{\n\t\t\t\t\tauto temp = 0;\n\t\t\t\t\tauto data = shared->getTagValueData(type, i);\n\t\t\t\t\tshared->getTagValueTypeData(data.valueType).load(shared, temp, tag);\n\t\t\t\t\tsetBase(i, temp);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tLog(LOG_ERROR) << \"Error in tags: '\" << tag.readKey<std::string>() << \"' unknown tag name not defined in current file\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Save values to yaml file.\n */\nvoid ScriptValuesBase::saveBase(YAML::YamlNodeWriter& writer, const ScriptGlobal* shared, ArgEnum type, const std::string& nodeName) const\n{\n\tbool hasTags = false; // We have to know whether the object has any tags before creating a \"tags\" child node in the yaml\n\tfor (size_t i = values.size(); i > 0 &&!hasTags; --i) // It's usually the last one\n\t\tif (getBase(i))\n\t\t\thasTags = true;\n\tif (!hasTags)\n\t\treturn;\n\tYAML::YamlNodeWriter tags = writer[writer.saveString(nodeName)];\n\ttags.setAsMap();\n\tfor (size_t i = 1; i <= values.size(); ++i)\n\t{\n\t\tif (int v = getBase(i))\n\t\t{\n\t\t\tScriptGlobal::TagValueData data = shared->getTagValueData(type, i);\n\t\t\tstd::string tagName = data.name.substr(data.name.find('.') + 1u).toString();\n\t\t\tYAML::YamlNodeWriter temp = tags[tags.saveString(tagName)];\n\t\t\tshared->getTagValueTypeData(data.valueType).save(shared, v, temp);\n\t\t}\n\t}\n}\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tScriptGlobal class\n////////////////////////////////////////////////////////////\n\n/**\n * Default constructor.\n */\nScriptGlobal::ScriptGlobal()\n{\n\taddTagValueTypeBase(\n\t\t\"int\",\n\t\t[](const ScriptGlobal* s, int& value, const YAML::YamlNodeReader& reader)\n\t\t{\n\t\t\tif (reader)\n\t\t\t{\n\t\t\t\tvalue = reader.readVal<int>();\n\t\t\t}\n\t\t},\n\t\t[](const ScriptGlobal* s, const int& value, YAML::YamlNodeWriter& writer)\n\t\t{\n\t\t\twriter.setValue(value);\n\t\t}\n\t);\n}\n\n/**\n * Destructor.\n */\nScriptGlobal::~ScriptGlobal()\n{\n\n}\n\n/**\n * Get tag value.\n */\nsize_t ScriptGlobal::getTag(ArgEnum type, ScriptRef s) const\n{\n\tauto data = _tagNames.find(type);\n\tif (data != _tagNames.end())\n\t{\n\t\tfor (size_t i = 0; i < data->second.values.size(); ++i)\n\t\t{\n\t\t\tauto &name = data->second.values[i].name;\n\t\t\tif (name == s)\n\t\t\t{\n\t\t\t\treturn i + 1;\n\t\t\t}\n\t\t}\n\t}\n\treturn 0;\n}\n\n/**\n * Get name of tag value.\n */\nScriptGlobal::TagValueData ScriptGlobal::getTagValueData(ArgEnum type, size_t i) const\n{\n\tauto data = _tagNames.find(type);\n\tif (data != _tagNames.end())\n\t{\n\t\tif (i && i <= data->second.values.size())\n\t\t{\n\t\t\treturn data->second.values[i - 1];\n\t\t}\n\t}\n\treturn {};\n}\n\n/**\n * Get tag value type data.\n */\nScriptGlobal::TagValueType ScriptGlobal::getTagValueTypeData(size_t valueType) const\n{\n\tif (valueType < _tagValueTypes.size())\n\t{\n\t\treturn _tagValueTypes[valueType];\n\t}\n\treturn {};\n}\n\n/**\n * Get tag value type id.\n */\nsize_t ScriptGlobal::getTagValueTypeId(ScriptRef s) const\n{\n\tfor (size_t i = 0; i < _tagValueTypes.size(); ++i)\n\t{\n\t\tif (_tagValueTypes[i].name == s)\n\t\t{\n\t\t\treturn i;\n\t\t}\n\t}\n\treturn (size_t)-1;\n}\n\n/**\n * Add new tag name.\n */\nsize_t ScriptGlobal::addTag(ArgEnum type, ScriptRef s, size_t valueType)\n{\n\tauto data = _tagNames.find(type);\n\tif (data == _tagNames.end())\n\t{\n\t\tthrow Exception(\"Unknown tag type\");\n\t}\n\tauto tag = getTag(type, s);\n\tif (tag == 0)\n\t{\n\t\t// is tag used for other tag type?\n\t\tif (findSortHelper(_refList, s))\n\t\t{\n\t\t\treturn 0;\n\t\t}\n\t\t// is tag type valid?\n\t\tif (valueType >= _tagValueTypes.size())\n\t\t{\n\t\t\treturn 0;\n\t\t}\n\t\t// test to prevent warp of index value\n\t\tif (data->second.values.size() < data->second.limit)\n\t\t{\n\t\t\tdata->second.values.push_back(TagValueData{ s, valueType });\n\t\t\taddSortHelper(_refList, { s, type, data->second.crate(data->second.values.size()) });\n\t\t\treturn data->second.values.size();\n\t\t}\n\t\treturn 0;\n\t}\n\telse\n\t{\n\t\treturn tag;\n\t}\n}\n\n/**\n * Store new name reference for future use.\n */\nScriptRef ScriptGlobal::addNameRef(const std::string& s)\n{\n\treturn addString(_strings, s);\n}\n\n/**\n * Store parser.\n */\nvoid ScriptGlobal::pushParser(const std::string& groupName, ScriptParserBase* parser)\n{\n\tparser->logScriptMetadata(false, groupName);\n\t_parserNames.insert(std::make_pair(parser->getName(), parser));\n}\n\n/**\n * Store parser with events.\n */\nvoid ScriptGlobal::pushParser(const std::string& groupName, ScriptParserEventsBase* parser)\n{\n\tparser->logScriptMetadata(true, groupName);\n\t_parserNames.insert(std::make_pair(parser->getName(), parser));\n\t_parserEvents.insert(std::make_pair(std::string_view(parser->getName()), parser));\n}\n\n/**\n * Add new const value.\n */\nvoid ScriptGlobal::addConst(const std::string& name, ScriptValueData i)\n{\n\tfor (auto& p : _parserNames)\n\t{\n\t\tp.second->addConst(name, i);\n\t}\n}\n\n/**\n * Update const value.\n */\nvoid ScriptGlobal::updateConst(const std::string& name, ScriptValueData i)\n{\n\tfor (auto& p : _parserNames)\n\t{\n\t\tp.second->updateConst(name, i);\n\t}\n}\n\n/**\n * Get global ref data.\n */\nconst ScriptRefData* ScriptGlobal::getRef(ScriptRef name, ScriptRef postfix) const\n{\n\treturn findSortHelper(_refList, name, postfix);\n}\n\n/**\n * Prepare for loading data.\n */\nvoid ScriptGlobal::beginLoad()\n{\n\n}\n\n/**\n * Prepare for loading file from mod.\n */\nvoid ScriptGlobal::fileLoad(const std::string& path)\n{\n\t_currFile = path;\n}\n\n/**\n * Finishing loading data.\n */\nvoid ScriptGlobal::endLoad()\n{\n\tfor (auto& p : _parserEvents)\n\t{\n\t\t_events.push_back(p.second->releseEvents());\n\t}\n\t_parserNames.clear();\n\t_parserEvents.clear();\n\t_currFile = \"After-load validation\";\n}\n\n/**\n * Load global data from YAML.\n */\nvoid ScriptGlobal::load(const YAML::YamlNodeReader& reader)\n{\n\tif (const YAML::YamlNodeReader& t = reader[\"tags\"])\n\t{\n\t\tfor (auto& p : _tagNames)\n\t\t{\n\t\t\tconst auto nodeName = p.second.name.toString();\n\t\t\tconst YAML::YamlNodeReader& tags = t[ryml::to_csubstr(nodeName)];\n\t\t\tif (tags && tags.isMap())\n\t\t\t{\n\t\t\t\tfor (const YAML::YamlNodeReader& tag : tags.children())\n\t\t\t\t{\n\t\t\t\t\tauto type = tag.readVal<std::string>();\n\t\t\t\t\tauto name = tag.readKey<std::string>();\n\t\t\t\t\tauto invalidType = _tagValueTypes.size();\n\t\t\t\t\tauto valueType = invalidType;\n\t\t\t\t\tfor (size_t typei = 0; typei < invalidType; ++typei)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (ScriptRef::tempFrom(type) == _tagValueTypes[typei].name)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tvalueType = typei;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (valueType != invalidType)\n\t\t\t\t\t{\n\t\t\t\t\t\tauto namePrefix = \"Tag.\" + name;\n\t\t\t\t\t\tauto ref = getRef(ScriptRef::tempFrom(namePrefix));\n\t\t\t\t\t\tif (ref && ref->type != p.first)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tLog(LOG_ERROR) << \"Script variable '\" + name + \"' already used in '\" + _tagNames[ref->type].name.toString() + \"'.\";\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tauto tagOffset = getTag(p.first, ScriptRef::tempFrom(namePrefix));\n\t\t\t\t\t\tif (tagOffset)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tauto data = getTagValueData(p.first, tagOffset);\n\t\t\t\t\t\t\tif (valueType != data.valueType)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tLog(LOG_ERROR) << \"Script variable '\" + name + \"' have wrong type '\" << _tagValueTypes[valueType].name.toString() << \"' instead of '\" << _tagValueTypes[data.valueType].name.toString() << \"' in '\" + nodeName + \"'.\";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttagOffset = addTag(p.first, addNameRef(namePrefix), valueType);\n\t\t\t\t\t\tif (!tagOffset)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tLog(LOG_ERROR) << \"Script variable '\" + name + \"' exceeds limit of \" << (int)p.second.limit << \" available variables in '\" + nodeName + \"'.\";\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tLog(LOG_ERROR) << \"Invalid type def '\" + type + \"' for script variable '\" + name + \"' in '\" + nodeName +\"'.\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif (const YAML::YamlNodeReader& scripts = reader[\"scripts\"])\n\t{\n\t\tif (scripts.hasNullVal() == false && scripts.isMap() == false)\n\t\t{\n\t\t\tthrow Exception(\"Wrong type of 'scripts' node at line \" + std::to_string(scripts.getLocationInFile().line));\n\t\t}\n\n\t\tfor (const auto& p : scripts.children())\n\t\t{\n\t\t\tauto key = p.key();\n\t\t\tif (key.length() > 0 && key.back() == '#')\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tauto event = _parserEvents.find(p.key());\n\t\t\tif (event == _parserEvents.end())\n\t\t\t{\n\t\t\t\tthrow Exception(\"Unknown '\" + std::string(p.key()) + \"' node in 'scripts' at line \" + std::to_string(p.getLocationInFile().line));\n\t\t\t}\n\n\t\t\tevent->second->loadEvents(p);\n\t\t}\n\t}\n}\n\n\n\n\n#ifndef NDEBUG\n\nnamespace\n{\n\n\nstruct Func_test_a\n{\n\t[[gnu::always_inline]]\n\tstatic RetEnum func (ScriptWorkerBase& c, int p, int& b)\n\t{\n\n\t\treturn RetContinue;\n\t}\n};\n\nstruct Func_test_b\n{\n\t[[gnu::always_inline]]\n\tstatic RetEnum func (int p, int& b)\n\t{\n\n\t\treturn RetContinue;\n\t}\n};\n\nstruct Func_test_c\n{\n\t[[gnu::always_inline]]\n\tstatic RetEnum func (int p, int& b, ScriptWorkerBase& c)\n\t{\n\n\t\treturn RetContinue;\n\t}\n};\n\n[[maybe_unused]]\nstatic auto dummyTestScriptOverload = ([]\n{\n\tScriptProcData data_a {\t};\n\tdata_a.overload = &overloadCustomProc;\n\tdata_a.overloadArg = helper::FuncGroup<Func_test_a>::overloadType();\n\n\tScriptProcData data_b {\t};\n\tdata_b.overload = &overloadCustomProc;\n\tdata_b.overloadArg = helper::FuncGroup<Func_test_b>::overloadType();\n\n\tScriptProcData data_c {\t};\n\tdata_c.overload = &overloadCustomProc;\n\tdata_c.overloadArg = helper::FuncGroup<Func_test_c>::overloadType();\n\n\n\tauto arg_any = ArgInvalid;\n\tauto arg_int = ArgInt;\n\tauto arg_int_ref = ArgSpecAdd(ArgInt, ArgSpecReg);\n\tauto arg_int_var = ArgSpecAdd(ArgInt, ArgSpecVar);\n\n\tauto test_overload = [](const ScriptProcData& a, std::initializer_list<ArgEnum> ref)\n\t{\n\t\tstd::array<ScriptRefData, 10> arr = {};\n\t\tint i = 0;\n\t\tfor (auto& p : ref)\n\t\t{\n\t\t\tarr[i++] = { {}, p };\n\t\t}\n\t\treturn overloadCustomProc(a, arr.data(), arr.data() + ref.size());\n\t};\n\n\tassert(3 == data_a.overloadArg.size());\n\tassert(2 == data_b.overloadArg.size());\n\tassert(3 == data_c.overloadArg.size());\n\n\tassert(2 == getOverloadArgSize(data_a));\n\tassert(2 == getOverloadArgSize(data_b));\n\tassert(2 == getOverloadArgSize(data_c));\n\n\tassert(0 == test_overload(data_a, { }));\n\n\tassert(0 == test_overload(data_a, { arg_any, }));\n\n\tassert(255 == test_overload(data_a, { arg_any, arg_any, }));\n\n\tassert(255 - 1 == test_overload(data_a, { arg_int, arg_any, }));\n\n\tassert(0 == test_overload(data_a, { arg_int, arg_int, }));\n\n\tassert(255 - 1 == test_overload(data_a, { arg_int, arg_int_var, }));\n\n\tassert(255 == test_overload(data_a, { arg_any, arg_int_var, }));\n\n\tassert(0 == test_overload(data_a, { arg_any, arg_int_var, arg_any, }));\n\n\tassert(255 - 64 - 1 == test_overload(data_a, { arg_int_var, arg_any, }));\n\n\tassert(255 - 64 - 1 == test_overload(data_a, { arg_int_var, arg_int_var, }));\n\n\tauto test_arg = [](const ScriptProcData& a, int i, std::initializer_list<ArgEnum> ref)\n\t{\n\t\tauto args = getOverloadArgType(a, i);\n\t\treturn std::equal(\n\t\t\tstd::begin(args), std::end(args),\n\t\t\tstd::begin(ref), std::end(ref)\n\t\t);\n\t};\n\n\tassert(test_arg(data_a, 0, { arg_int, arg_int_ref }));\n\tassert(test_arg(data_a, 1, { arg_int_var }));\n\tassert(test_arg(data_a, 2, { }));\n\n\tassert(test_arg(data_b, 0, { arg_int, arg_int_ref }));\n\tassert(test_arg(data_b, 1, { arg_int_var }));\n\tassert(test_arg(data_b, 2, { }));\n\n\tassert(test_arg(data_c, 0, { arg_int, arg_int_ref }));\n\tassert(test_arg(data_c, 1, { arg_int_var }));\n\tassert(test_arg(data_c, 2, { }));\n\n\treturn 0;\n})();\n\n\nstruct ScriptParserTest : ScriptParserBase\n{\n\tScriptParserTest(ScriptGlobal* g) : ScriptParserBase(g, \"X\")\n\t{\n\n\t}\n};\nstruct DummyClass\n{\n\t/// Name of class used in script.\n\tstatic constexpr const char *ScriptName = \"DummyClass\";\n\t/// Register all useful function used by script.\n\tstatic void ScriptRegister(ScriptParserBase* parser);\n};\nvoid dummyFunctionInt(int i, int j)\n{\n\n}\nvoid dummyFunctionClass(const DummyClass* c)\n{\n\n}\n\nstruct TestEnv\n{\n\tScriptGlobal g = { };\n\tScriptParserTest f = { &g };\n\tScriptContainerBase tempScript = { };\n\tParserWriter help = { 0, tempScript, f };\n};\n\n\n[[maybe_unused]]\nstatic auto dummyTestScriptFunctionParser = ([]\n{\n\tTestEnv env;\n\tScriptParserTest& f = env.f;\n\n\tf.addType<DummyClass*>(\"DummyClass\");\n\n\tBind<DummyClass> bind{ &f };\n\tbind.addCustomFunc<helper::BindFunc<MACRO_CLANG_AUTO_HACK(&dummyFunctionInt)>>(\"test1\");\n\tbind.add<&dummyFunctionClass>(\"test2\");\n\tbind.add<&dummyFunctionClass>(\"test3\");\n\n\n\tParserWriter& help = env.help;\n\thelp.addReg<DummyClass*&>(ScriptRef{\"foo\"});\n\thelp.addReg<DummyClass*&>(ScriptRef{\"bar.a\"});\n\thelp.addReg<DummyClass*&>(ScriptRef{\"bar.b\"});\n\thelp.addReg<DummyClass*&>(ScriptRef{\"Tag.foo\"});\n\n\n\t{\n\t\tauto r = help.getReferece(ScriptRef{\"foo\"});\n\t\tassert(!!r && \"reg 'foo'\");\n\t}\n\n\t{\n\t\tauto r = help.getReferece(ScriptRef{\"bar.a\"});\n\t\tassert(!!r && \"reg 'bar.a'\");\n\t}\n\n\t{\n\t\tauto r = help.getReferece(ScriptRef{\"bar.b\"});\n\t\tassert(!!r && \"reg 'bar.b'\");\n\t}\n\n\t{\n\t\tauto r = help.getReferece(ScriptRef{\"Tag.foo\"});\n\t\tassert(!!r && \"reg 'Tag.foo'\");\n\t}\n\n\n\n\t{\n\t\tauto getProcFromParser = [&](std::initializer_list<ScriptRef> l)\n\t\t{\n\t\t\treturn !!help.parser.getProc(ScriptRange{ l.begin(), l.end() });\n\t\t};\n\t\tassert(getProcFromParser({ ScriptRef{\"DummyClass.test2\"} }));\n\t\tassert(getProcFromParser({ ScriptRef{\"DummyClass.test3\"} }));\n\t\tassert(getProcFromParser({ ScriptRef{\"DummyClass\"}, ScriptRef{\".test2\"} }));\n\t\tassert(getProcFromParser({ ScriptRef{\"DummyClass\"}, ScriptRef{\".\"} , ScriptRef{\"test2\"} }));\n\t\tassert(getProcFromParser({ ScriptRef{\"DummyClass\"}, ScriptRef{\".\"} , ScriptRef{\"te\"} , ScriptRef{\"st2\"} }));\n\t\tassert(!getProcFromParser({ ScriptRef{\"DummyClass.test1\"} }));\n\t}\n\n\n\n\t{\n\t\tauto r = findOperationAndArg(help, ScriptRef{\"if\"});\n\t\tassert(!!r && \"func 'if'\");\n\t\tassert(r.haveArg() == false && \"func 'if'\");\n\t\tassert(r.haveProc() == true && \"func 'if'\");\n\t}\n\n\t{\n\t\tauto r = findOperationAndArg(help, ScriptRef{\"test1\"});\n\t\tassert(!!r && \"func 'test1'\");\n\t\tassert(r.haveArg() == false && \"func 'test1'\");\n\t\tassert(r.haveProc() == true && \"func 'test1'\");\n\t}\n\n\t{\n\t\tauto r = findOperationAndArg(help, ScriptRef{\"DummyClass.test2\"});\n\t\tassert(!!r && \"func 'DummyClass.test2'\");\n\t\tassert(r.haveArg() == false && \"func 'DummyClass.test2'\");\n\t\tassert(r.haveProc() == true && \"func 'DummyClass.test2'\");\n\t}\n\n\t{\n\t\tauto r = findOperationAndArg(help, ScriptRef{\"foo.test2\"});\n\t\tassert(!!r && \"func 'foo.test2'\");\n\t\tassert(r.haveArg() == true && \"func 'foo.test2'\");\n\t\tassert(r.argName == ScriptRef{\"foo\"} && \"func 'foo.test2'\");\n\t\tassert(r.haveProc() == true && \"func 'foo.test2'\");\n\t}\n\n\t{\n\t\tauto r = findOperationAndArg(help, ScriptRef{\"bar.a.test2\"});\n\t\tassert(!!r && \"func 'bar.a.test2'\");\n\t\tassert(r.haveArg() == true && \"func 'bar.a.test2'\");\n\t\tassert(r.argName == ScriptRef{\"bar.a\"} && \"func 'bar.a.test2'\");\n\t\tassert(r.haveProc() == true && \"func 'bar.a.test2'\");\n\t}\n\n\t{\n\t\tauto r = findOperationAndArg(help, ScriptRef{\"Tag.foo.test2\"});\n\t\tassert(!!r && \"func 'Tag.foo.test2'\");\n\t\tassert(r.haveArg() == true && \"func 'Tag.foo.test2'\");\n\t\tassert(r.argName == ScriptRef{\"Tag.foo\"} && \"func 'Tag.foo.test2'\");\n\t\tassert(r.haveProc() == true && \"func 'Tag.foo.test2'\");\n\t}\n\n\t{\n\t\tauto r = findOperationAndArg(help, ScriptRef{\"bar.a2.test2\"});\n\t\tassert(!r && \"func 'bar.a2.test2'\");\n\t\tassert(r.haveArg() == true && \"func 'bar.a2.test2'\");\n\t\tassert(r.argName == ScriptRef{\"bar\"} && \"func 'bar.a2.test2'\");\n\t}\n\n\t{\n\t\tauto r = findOperationAndArg(help, ScriptRef{\"Tag.foo2.test2\"});\n\t\tassert(!r && \"func 'Tag.foo.test2'\");\n\t\tassert(r.haveArg() == true && \"func 'Tag.foo2.test2'\");\n\t\tassert(r.argName == ScriptRef{\"Tag.foo2\"} && \"func 'Tag.foo2.test2'\");\n\t}\n\n\n\t{\n\t\tauto r = findOperationAndArg(help, ScriptRef{\"Tag.foo.test2\"});\n\t\tassert(!!r && \"func 'Tag.foo.test2'\");\n\n\t\t{\n\t\t\tauto u = replaceOperation(help, r, ScriptRef{\"test2\"}, ScriptRef{\"test3\"});\n\t\t\tassert(!!u && \"updated 'test2' to 'Tag.foo.test3'\");\n\t\t}\n\n\t\t{\n\t\t\tauto u = replaceOperation(help, r, ScriptRef{\"2\"}, ScriptRef{\"3\"});\n\t\t\tassert(!!u && \"updated '2' to 'Tag.foo.test1'\");\n\t\t}\n\n\t\t{\n\t\t\tauto u = replaceOperation(help, r, ScriptRef{\"test3\"}, ScriptRef{\"test3\"});\n\t\t\tassert(!u && \"updated 'test3' to 'Tag.foo.test3'\");\n\t\t}\n\t}\n\n\treturn 0;\n})();\n\n\nvoid dummyFunctionSeperator0(int& i, int& j, int& k)\n{\n\ti = 0;\n}\nvoid dummyFunctionSeperator1(int& i, ScriptArgSeparator, int& j, int& k)\n{\n\ti = 1;\n}\nvoid dummyFunctionSeperator2(int& i, int& j, ScriptArgSeparator, int& k)\n{\n\ti = 2;\n}\nvoid dummyFunctionSeperator3(int& i, int& j, int& k, ScriptArgSeparator)\n{\n\ti = 3;\n}\n\n[[maybe_unused]]\nstatic auto dummyTestScriptOverloadSeperator = ([]\n{\n\tTestEnv env;\n\tScriptParserTest& f = env.f;\n\n\tBind<DummyClass> bind{ &f };\n\tbind.addCustomFunc<helper::BindFunc<MACRO_CLANG_AUTO_HACK(&dummyFunctionSeperator0)>>(\"funcSep\");\n\tbind.addCustomFunc<helper::BindFunc<MACRO_CLANG_AUTO_HACK(&dummyFunctionSeperator1)>>(\"funcSep\");\n\tbind.addCustomFunc<helper::BindFunc<MACRO_CLANG_AUTO_HACK(&dummyFunctionSeperator2)>>(\"funcSep\");\n\tbind.addCustomFunc<helper::BindFunc<MACRO_CLANG_AUTO_HACK(&dummyFunctionSeperator3)>>(\"funcSep\");\n\n\n\tParserWriter& help = env.help;\n\tauto arg_x = help.addReg<int&>(ScriptRef{\"x\"});\n\tauto arg_y = help.addReg<int&>(ScriptRef{\"y\"});\n\tauto arg_z = help.addReg<int&>(ScriptRef{\"z\"});\n\tauto arg_sep = help.getReferece(ScriptRef{\"__\"});\n\n\tassert(arg_x);\n\tassert(arg_y);\n\tassert(arg_z);\n\tassert(arg_sep);\n\n\tauto callFunc = [&](std::tuple<int, const ScriptProcData*> t, const ScriptRefData* begin, const ScriptRefData* end)\n\t{\n\t\tauto p = std::get<const ScriptProcData*>(t);\n\t\tif (p == nullptr)\n\t\t{\n\t\t\treturn -1;\n\t\t}\n\t\tfor (auto arg : p->overloadArg)\n\t\t{\n\t\t\tassert(arg.size() == 1);\n\t\t}\n\t\tauto func = p->parserGet(0);\n\n\t\tUint8 dummy[64] = { };\n\t\tScriptWorkerBase wb;\n\t\tProgPos pos;\n\n\t\twb.ref<int>(arg_x.getValue<RegEnum>()) = -1;\n\t\tfunc(wb, dummy, pos);\n\t\treturn wb.ref<int>(arg_x.getValue<RegEnum>());\n\t};\n\n\tauto r = findOperationAndArg(help, ScriptRef{\"funcSep\"});\n\tassert(!!r && \"func 'funcSep'\");\n\n\t{\n\t\tScriptRefData args[] = { arg_x, arg_y, arg_z };\n\t\tauto o = findBestOverloadProc(r.procList, std::begin(args), std::end(args));\n\t\tassert(std::get<int>(o) && \"args 'funcSep x y z'\");\n\t\tassert(callFunc(o, std::begin(args), std::end(args)) == 0);\n\t}\n\n\t{\n\t\tScriptRefData args[] = { arg_x, arg_sep, arg_y, arg_z };\n\t\tauto o = findBestOverloadProc(r.procList, std::begin(args), std::end(args));\n\t\tassert(std::get<int>(o) && \"args 'funcSep x __ y z'\");\n\t\tassert(callFunc(o, std::begin(args), std::end(args)) == 1);\n\t}\n\n\t{\n\t\tScriptRefData args[] = { arg_x, arg_y, arg_sep, arg_z };\n\t\tauto o = findBestOverloadProc(r.procList, std::begin(args), std::end(args));\n\t\tassert(std::get<int>(o) && \"args 'funcSep x y __ z'\");\n\t\tassert(callFunc(o, std::begin(args), std::end(args)) == 2);\n\t}\n\n\t{\n\t\tScriptRefData args[] = { arg_x, arg_y, arg_z, arg_sep };\n\t\tauto o = findBestOverloadProc(r.procList, std::begin(args), std::end(args));\n\t\tassert(std::get<int>(o) && \"args 'funcSep x y z __'\");\n\t\tassert(callFunc(o, std::begin(args), std::end(args)) == 3);\n\t}\n\n\treturn 0;\n})();\n\n\n[[maybe_unused]]\nstatic auto dummyTestScriptRefTokens = ([]\n{\n\t{\n\t\tScriptRefTokens srt{\"aaaa bb\"};\n\t\t{\n\t\t\tSelectedToken next = srt.getNextToken();\n\t\t\tassert(next == ScriptRef{\"aaaa\"} && next.getType() == TokenSymbol);\n\t\t}\n\t\t{\n\t\t\tSelectedToken next = srt.getNextToken();\n\t\t\tassert(next == ScriptRef{\"bb\"} && next.getType() == TokenSymbol);\n\t\t}\n\t\t{\n\t\t\tSelectedToken next = srt.getNextToken();\n\t\t\tassert(next.getType() == TokenNone);\n\t\t}\n\t}\n\n\t{\n\t\tTestEnv env;\n\t\tScriptRefTokens srt{\"0x10 1234 0b100 0o10 0x0f 0xAb\"};\n\t\t{\n\t\t\tSelectedToken next = srt.getNextToken();\n\t\t\tassert(next == ScriptRef{\"0x10\"} && next.getType() == TokenNumber);\n\n\t\t\tauto r = next.parse(env.help);\n\t\t\tassert(r.type == ArgInt);\n\t\t\tassert(r.getValue<int>() == 0x10);\n\t\t}\n\t\t{\n\t\t\tSelectedToken next = srt.getNextToken();\n\t\t\tassert(next == ScriptRef{\"1234\"} && next.getType() == TokenNumber);\n\n\t\t\tauto r = next.parse(env.help);\n\t\t\tassert(r.type == ArgInt);\n\t\t\tassert(r.getValue<int>() == 1234);\n\t\t}\n\t\t{\n\t\t\tSelectedToken next = srt.getNextToken();\n\t\t\tassert(next == ScriptRef{\"0b100\"} && next.getType() == TokenNumber);\n\n\t\t\tauto r = next.parse(env.help);\n\t\t\tassert(r.type == ArgInt);\n\t\t\tassert(r.getValue<int>() == 4);\n\t\t}\n\t\t{\n\t\t\tSelectedToken next = srt.getNextToken();\n\t\t\tassert(next == ScriptRef{\"0o10\"} && next.getType() == TokenNumber);\n\n\t\t\tauto r = next.parse(env.help);\n\t\t\tassert(r.type == ArgInt);\n\t\t\tassert(r.getValue<int>() == 8);\n\t\t}\n\t\t{\n\t\t\tSelectedToken next = srt.getNextToken();\n\t\t\tassert(next == ScriptRef{\"0x0f\"} && next.getType() == TokenNumber);\n\n\t\t\tauto r = next.parse(env.help);\n\t\t\tassert(r.type == ArgInt);\n\t\t\tassert(r.getValue<int>() == 15);\n\t\t}\n\t\t{\n\t\t\tSelectedToken next = srt.getNextToken();\n\t\t\tassert(next == ScriptRef{\"0xAb\"} && next.getType() == TokenNumber);\n\n\t\t\tauto r = next.parse(env.help);\n\t\t\tassert(r.type == ArgInt);\n\t\t\tassert(r.getValue<int>() == 0xAB);\n\t\t}\n\t\t{\n\t\t\tSelectedToken next = srt.getNextToken();\n\t\t\tassert(next.getType() == TokenNone);\n\t\t}\n\t}\n\n\tauto getType = [](ScriptRef ref, TokenEnum next = TokenNone)\n\t{\n\t\tScriptRefTokens srt{ref.begin(), ref.end()};\n\t\treturn srt.getNextToken(next).getType();\n\t};\n\n\tassert(getType(ScriptRef{\":\"}) == TokenInvalid);\n\tassert(getType(ScriptRef{\":\"}, TokenColon) == TokenColon);\n\tassert(getType(ScriptRef{\";\"}) == TokenNone);\n\tassert(getType(ScriptRef{\";\"}, TokenSemicolon) == TokenSemicolon);\n\tassert(getType(ScriptRef{\"\\\"aaa\\\"\"}) == TokenText);\n\tassert(getType(ScriptRef{\"0x1\"}) == TokenNumber);\n\tassert(getType(ScriptRef{\"\"}) == TokenNone);\n\tassert(getType(ScriptRef{\" \"}) == TokenNone);\n\tassert(getType(ScriptRef{\"#aaaaa\"}) == TokenNone);\n\tassert(getType(ScriptRef{\"  #  1235\"}) == TokenNone);\n\tassert(getType(ScriptRef{\"  #  \\n1235\"}) == TokenNumber);\n\tassert(getType(ScriptRef{\" a\"}) == TokenSymbol);\n\tassert(getType(ScriptRef{\" \\na\"}) == TokenSymbol);\n\tassert(getType(ScriptRef{\"a111\"}) == TokenSymbol);\n\n\n\tassert(getType(ScriptRef{\"0x\"}) == TokenInvalid);\n\tassert(getType(ScriptRef{\"0xk\"}) == TokenInvalid);\n\n\treturn 0;\n})();\n\n\n[[maybe_unused]]\nstatic auto dummyTestScriptStringRef = ([]\n{\n\tassert(ScriptRef{\"foo\"} == ScriptRef{\"foo\"}.substr(0));\n\tassert(ScriptRef{\"oo\"} == ScriptRef{\"foo\"}.substr(1));\n\tassert(ScriptRef{\"o\"} == ScriptRef{\"foo\"}.substr(2));\n\tassert(ScriptRef{\"\"} == ScriptRef{\"foo\"}.substr(3));\n\tassert(ScriptRef{\"\"} == ScriptRef{\"foo\"}.substr(4));\n\n\tassert(ScriptRef{\"\"} == ScriptRef{\"foo1234\"}.substr(3, 0));\n\tassert(ScriptRef{\"1\"} == ScriptRef{\"foo1234\"}.substr(3, 1));\n\tassert(ScriptRef{\"12\"} == ScriptRef{\"foo1234\"}.substr(3, 2));\n\tassert(ScriptRef{\"123\"} == ScriptRef{\"foo1234\"}.substr(3, 3));\n\tassert(ScriptRef{\"1234\"} == ScriptRef{\"foo1234\"}.substr(3, 4));\n\tassert(ScriptRef{\"1234\"} == ScriptRef{\"foo1234\"}.substr(3, 5));\n\n\tassert(ScriptRef{\"\"} == ScriptRef{\"12345\"}.head(0));\n\tassert(ScriptRef{\"1\"} == ScriptRef{\"12345\"}.head(1));\n\tassert(ScriptRef{\"12\"} == ScriptRef{\"12345\"}.head(2));\n\tassert(ScriptRef{\"123\"} == ScriptRef{\"12345\"}.head(3));\n\tassert(ScriptRef{\"1234\"} == ScriptRef{\"12345\"}.head(4));\n\tassert(ScriptRef{\"12345\"} == ScriptRef{\"12345\"}.head(5));\n\tassert(ScriptRef{\"12345\"} == ScriptRef{\"12345\"}.head(6));\n\n\tassert(ScriptRef{\"12345\"} == ScriptRef{\"12345\"}.tail(0));\n\tassert(ScriptRef{\"2345\"} == ScriptRef{\"12345\"}.tail(1));\n\tassert(ScriptRef{\"345\"} == ScriptRef{\"12345\"}.tail(2));\n\tassert(ScriptRef{\"45\"} == ScriptRef{\"12345\"}.tail(3));\n\tassert(ScriptRef{\"5\"} == ScriptRef{\"12345\"}.tail(4));\n\tassert(ScriptRef{\"\"} == ScriptRef{\"12345\"}.tail(5));\n\tassert(ScriptRef{\"\"} == ScriptRef{\"12345\"}.tail(6));\n\n\tassert(ScriptRef{\"\"} == ScriptRef{\"12345\"}.headFromEnd(0));\n\tassert(ScriptRef{\"5\"} == ScriptRef{\"12345\"}.headFromEnd(1));\n\tassert(ScriptRef{\"45\"} == ScriptRef{\"12345\"}.headFromEnd(2));\n\tassert(ScriptRef{\"345\"} == ScriptRef{\"12345\"}.headFromEnd(3));\n\tassert(ScriptRef{\"2345\"} == ScriptRef{\"12345\"}.headFromEnd(4));\n\tassert(ScriptRef{\"12345\"} == ScriptRef{\"12345\"}.headFromEnd(5));\n\tassert(ScriptRef{\"12345\"} == ScriptRef{\"12345\"}.headFromEnd(6));\n\n\tassert(ScriptRef{\"12345\"} == ScriptRef{\"12345\"}.tailFromEnd(0));\n\tassert(ScriptRef{\"1234\"} == ScriptRef{\"12345\"}.tailFromEnd(1));\n\tassert(ScriptRef{\"123\"} == ScriptRef{\"12345\"}.tailFromEnd(2));\n\tassert(ScriptRef{\"12\"} == ScriptRef{\"12345\"}.tailFromEnd(3));\n\tassert(ScriptRef{\"1\"} == ScriptRef{\"12345\"}.tailFromEnd(4));\n\tassert(ScriptRef{\"\"} == ScriptRef{\"12345\"}.tailFromEnd(5));\n\tassert(ScriptRef{\"\"} == ScriptRef{\"12345\"}.tailFromEnd(6));\n\n\treturn 0;\n})();\n\n\n[[maybe_unused]]\nstatic auto dummyTestScriptRefCompound = ([]\n{\n\tScriptRefCompound t;\n\tassert(t.toString() == \"\");\n\tassert(t.tryPushBack(ScriptRef{\"f1\"}));\n\tassert(t.toString() == \"f1\");\n\tassert(t.tryPushBack(ScriptRef{\"f2\"}));\n\tassert(t.toString() == \"f1f2\");\n\tassert(t.tryPushBack(ScriptRef{\"f3\"}));\n\tassert(t.toString() == \"f1f2f3\");\n\tassert(t.tryPushBack(ScriptRef{\"f4\"}));\n\tassert(t.toString() == \"f1f2f3f4\");\n\tassert(!t.tryPushBack(ScriptRef{\"f5\"}));\n\tassert(t.toString() == \"f1f2f3f4\");\n\tassert(t.tryPopBack());\n\tassert(t.toString() == \"f1f2f3\");\n\tassert(t.tryPopBack());\n\tassert(t.toString() == \"f1f2\");\n\tassert(t.tryPopBack());\n\tassert(t.toString() == \"f1\");\n\tassert(t.tryPopBack());\n\tassert(t.toString() == \"\");\n\tassert(!t.tryPopBack());\n\tassert(t.toString() == \"\");\n\tassert(t.tryPushBack(ScriptRef{\"f6\"}));\n\tassert(t.toString() == \"f6\");\n\treturn 0;\n})();\n\n\n[[maybe_unused]]\nstatic auto dummyTestScriptArgList = ([]\n{\n\tScriptArgList list1;\n\tScriptArgList list2;\n\tScriptArgList list3;\n\tScriptRefData arg_a = { ScriptRef{ \"a\" }, ArgInvalid };\n\tScriptRefData arg_b = { ScriptRef{ \"b\" }, ArgInvalid };\n\n\tassert(list1.tryPushBack(arg_a));\n\tassert(list1.tryPushBack(arg_b));\n\tassert(list1.size() == 2);\n\tassert(list2.tryPushBack(list1));\n\tassert(list2.tryPushBack(list1));\n\tassert(list2.size() == 4);\n\tassert(list3.tryPushBack(list2));\n\tassert(list3.tryPushBack(list2));\n\tassert(list3.size() == 8);\n\tassert(list3.tryPushBack(list3));\n\tassert(list3.size() == 16);\n\tassert(!list3.tryPushBack(list3));\n\tassert(list3.size() == 16);\n\tassert(!list3.tryPushBack(arg_a));\n\tassert(list3.size() == 16);\n\n\treturn 0;\n})();\n\n\n[[maybe_unused]]\nstatic auto dummyTestFunctions = ([]\n{\n\tauto call_mulDiv_h = [](int reg, int mul, int div)\n\t{\n\t\tmulDiv_h(reg, mul, div);\n\t\treturn reg;\n\t};\n\n\tassert(1 == call_mulDiv_h(1, 100, 100));\n\tassert(1 == call_mulDiv_h(2, 50, 100));\n\tassert(INT_MAX == call_mulDiv_h(INT_MAX, 100, 100));\n\tassert(INT_MAX / 2 == call_mulDiv_h(INT_MAX, 50, 100));\n\n\tauto call_mulAddMod_h = [](int reg, int mul, int add, int div)\n\t{\n\t\tmulAddMod_h(reg, mul, add, div);\n\t\treturn reg;\n\t};\n\n\tassert(1 == call_mulAddMod_h(100, 100, 1, 100));\n\tassert(1 == call_mulAddMod_h(INT_MAX, 100, 1, 100));\n\n\n\treturn 0;\n})();\n\n\n[[maybe_unused]]\nstatic auto dummyTestScriptLowerBound = ([]\n{\n\tstd::vector<ScriptTypeData> test;\n\taddSortHelper(test, ScriptTypeData{ ScriptRef{ \"b\" }  });\n\taddSortHelper(test, ScriptTypeData{ ScriptRef{ \"bb\" }  });\n\taddSortHelper(test, ScriptTypeData{ ScriptRef{ \"bbb\" }  });\n\taddSortHelper(test, ScriptTypeData{ ScriptRef{ \"bbbb\" }  });\n\taddSortHelper(test, ScriptTypeData{ ScriptRef{ \"c\" }  });\n\taddSortHelper(test, ScriptTypeData{ ScriptRef{ \"cc\" }  });\n\taddSortHelper(test, ScriptTypeData{ ScriptRef{ \"ccc\" }  });\n\taddSortHelper(test, ScriptTypeData{ ScriptRef{ \"a\" }  });\n\taddSortHelper(test, ScriptTypeData{ ScriptRef{ \"aa\" }  });\n\taddSortHelper(test, ScriptTypeData{ ScriptRef{ \"aaa\" }  });\n\taddSortHelper(test, ScriptTypeData{ ScriptRef{ \"aaaa\" }  });\n\taddSortHelper(test, ScriptTypeData{ ScriptRef{ \"aaab\" }  });\n\taddSortHelper(test, ScriptTypeData{ ScriptRef{ \"aaaba\" }  });\n\taddSortHelper(test, ScriptTypeData{ ScriptRef{ \"aaaaa\" }  });\n\taddSortHelper(test, ScriptTypeData{ ScriptRef{ \"abcde\" }  });\n\taddSortHelper(test, ScriptTypeData{ ScriptRef{ \"abcdf\" }  });\n\n\tauto pairRange = [&](const auto &pr, const auto &po)\n\t{\n\t\tScriptRef prefix{ pr };\n\t\tScriptRef postfix{ po };\n\t\tauto lower = test.data();\n\t\tauto upper = test.data() + test.size();\n\t\tlower = boundSortHelper<false>(lower, upper, prefix, postfix);\n\t\tupper = boundSortHelper<true>(lower, upper, prefix, postfix);\n\t\treturn std::make_pair(lower, upper);\n\t};\n\tauto listRange = [&](std::initializer_list<const char*> l)\n\t{\n\t\tScriptRef prefix[64] = { };\n\t\tint i = 0;\n\t\tfor (auto* p : l)\n\t\t{\n\t\t\tprefix[i] = ScriptRef{ p, p + std::strlen(p) };\n\t\t\t++i;\n\t\t}\n\t\tauto lower = test.data();\n\t\tauto upper = test.data() + test.size();\n\t\tlower = boundSortHelper<false>(lower, upper, ScriptRange{ prefix, prefix + i });\n\t\tupper = boundSortHelper<true>(lower, upper, ScriptRange{ prefix, prefix + i });\n\t\treturn std::make_pair(lower, upper);\n\t};\n\tauto foundSomething = [](std::pair<const ScriptTypeData*, const ScriptTypeData*> p)\n\t{\n\t\treturn p.first != p.second;\n\t};\n\n\tassert(true == foundSomething(pairRange(\"aa\", \"\")));\n\tassert(true == foundSomething(pairRange(\"aaaa\", \"\")));\n\tassert(true == foundSomething(pairRange(\"aa\", \"aa\")));\n\tassert((pairRange(\"aaaa\", \"\")) == (pairRange(\"aa\", \"aa\")));\n\tassert((pairRange(\"abcde\", \"\")) == (pairRange(\"abc\", \"de\")));\n\tassert((pairRange(\"abcde\", \"\")) == (pairRange(\"ab\", \"cde\")));\n\n\tassert(false == foundSomething(listRange({\"www\"})));\n\tassert(false == foundSomething(listRange({\"www\", \"\"})));\n\tassert(true == foundSomething(listRange({\"aa\"})));\n\tassert(true == foundSomething(listRange({\"aa\", \"\"})));\n\tassert(true == foundSomething(listRange({\"aaaa\", \"\"})));\n\tassert(true == foundSomething(listRange({\"aa\", \"aa\"})));\n\tassert((listRange({\"aaaa\", \"\"})) == (listRange({\"aa\", \"aa\"})));\n\tassert((listRange({\"abcde\", \"\"})) == (listRange({\"abc\", \"de\"})));\n\tassert((listRange({\"abcde\", \"\"})) == (listRange({\"ab\", \"cde\"})));\n\tassert((listRange({\"abcde\", \"\"})) == (listRange({\"a\", \"b\", \"cde\"})));\n\tassert((listRange({\"abcde\", \"\"})) == (listRange({\"a\", \"b\", \"c\", \"d\", \"e\"})));\n\tassert(false == foundSomething(listRange({\"www\", \"\"})));\n\n\tassert((pairRange(\"abcde\", \"\")) == (listRange({\"a\", \"b\", \"cde\"})));\n\n\tassert((pairRange(\"aaaba\", \"\").second) == (pairRange(\"abcde\", \"\").first));\n\tassert((pairRange(\"abcde\", \"\").second) == (pairRange(\"ab\", \"cdf\").first));\n\n\treturn 0;\n})();\n\n\n} //namespace\n\n\n#endif\n\n} //namespace OpenXcom\n"
  },
  {
    "path": "src/Engine/Script.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2015 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <map>\n#include <unordered_map>\n#include <limits>\n#include <vector>\n#include <string>\n#include <cstring>\n#include \"../Engine/Yaml.h\"\n#include <SDL_stdinc.h>\n#include <cassert>\n#include <unordered_set>\n\n#include \"HelperMeta.h\"\n#include \"Logger.h\"\n#include \"Exception.h\"\n#include \"GraphSubset.h\"\n#include \"Functions.h\"\n\n\nnamespace OpenXcom\n{\n//for Surface.h\nclass Surface;\n\n//for Script.h\nclass ScriptGlobal;\nclass ScriptParserBase;\nclass ScriptParserEventsBase;\nclass ScriptContainerBase;\nclass ScriptContainerEventsBase;\n\nstruct ParserWriter;\nclass SelectedToken;\nclass ScriptWorkerBase;\nclass ScriptWorkerBlit;\ntemplate<typename, typename...> class ScriptWorker;\ntemplate<typename, typename> struct ScriptTag;\ntemplate<typename, typename> class ScriptValues;\n\nenum RegEnum : Uint16;\nenum RetEnum : Uint8;\nenum class ProgPos : size_t;\n\n//for ScriptBind.h\nstruct BindBase;\ntemplate<typename T> struct Bind;\ntemplate<typename T, typename N, N T::*X> struct BindNested;\n\nnamespace helper\n{\n\ntemplate<typename T>\nstruct ArgSelector;\n\ntemplate<typename Z>\nstruct ArgName\n{\n\tArgName(const char *n) : name{ n } { }\n\n\tconst char *name;\n};\n\n}\n\nconstexpr size_t ScriptMaxOut = 9;\nconstexpr size_t ScriptMaxArg = 16;\nconstexpr size_t ScriptMaxReg = 64*sizeof(void*);\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tscript base types\n////////////////////////////////////////////////////////////\n\n/**\n * Script null type, alias to std nullptr.\n */\nusing ScriptNull = std::nullptr_t;\n\n/**\n * Script numeric type, alias to int.\n */\nusing ScriptInt = Sint32;\n\n/**\n * Script const text, always zero terminated.\n */\nstruct ScriptText\n{\n\tconst char* ptr;\n\n\toperator std::string()\n\t{\n\t\treturn ptr ? ptr : \"\";\n\t}\n\n\tconst static ScriptText empty;\n};\n\nconst inline ScriptText ScriptText::empty = { \"\" };\n\n\nusing ScriptFunc = RetEnum (*)(ScriptWorkerBase&, const Uint8*, ProgPos&);\n\ninline ProgPos& operator+=(ProgPos& pos, int offset)\n{\n\tpos = static_cast<ProgPos>(static_cast<size_t>(pos) + offset);\n\treturn pos;\n}\ninline ProgPos& operator++(ProgPos& pos)\n{\n\tpos += 1;\n\treturn pos;\n}\ninline ProgPos operator++(ProgPos& pos, int)\n{\n\tProgPos old = pos;\n\t++pos;\n\treturn old;\n}\n\n/**\n * Dummy type used to separate function args groups.\n */\nclass ScriptArgSeparator\n{\n};\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tenum definitions\n////////////////////////////////////////////////////////////\n\n/**\n * Base type for Arg enum.\n */\nusing ArgEnumBase = Uint16;\n\n/**\n * Args special types.\n */\nenum ArgSpecEnum : ArgEnumBase\n{\n\tArgSpecNone = 0x0,\n\tArgSpecReg = 0x1,\n\tArgSpecVar = 0x2 + ArgSpecReg,\n\tArgSpecPtr = 0x4,\n\tArgSpecPtrE = 0x8 + ArgSpecPtr,\n\tArgSpecSize = 0x10,\n};\nconstexpr ArgSpecEnum operator|(ArgSpecEnum a, ArgSpecEnum b)\n{\n\treturn static_cast<ArgSpecEnum>(static_cast<ArgEnumBase>(a) | static_cast<ArgEnumBase>(b));\n}\nconstexpr ArgSpecEnum operator&(ArgSpecEnum a, ArgSpecEnum b)\n{\n\treturn static_cast<ArgSpecEnum>(static_cast<ArgEnumBase>(a) & static_cast<ArgEnumBase>(b));\n}\nconstexpr ArgSpecEnum operator^(ArgSpecEnum a, ArgSpecEnum b)\n{\n\treturn static_cast<ArgSpecEnum>(static_cast<ArgEnumBase>(a) ^ static_cast<ArgEnumBase>(b));\n}\n\n/**\n * Args types.\n */\nenum ArgEnum : ArgEnumBase\n{\n\tArgInvalid = ArgSpecSize * 0,\n\tArgPlaceholder,\n\tArgUnknowSimple,\n\tArgUnknowSegment,\n\tArgInvalidMax,\n\n\tArgNull = ArgSpecSize * 1,\n\tArgInt = ArgSpecSize * 2,\n\tArgLabel = ArgSpecSize * 3,\n\tArgText = ArgSpecSize * 4,\n\tArgSep = ArgSpecSize * 5,\n\n\tArgMax = ArgSpecSize * 6,\n};\n\nstatic_assert(ArgInvalidMax < ArgNull, \"Overlap of different ranges\");\n\n/**\n * Next available value for arg type.\n */\nconstexpr ArgEnum ArgNext(ArgEnum arg)\n{\n\treturn static_cast<ArgEnum>(static_cast<ArgEnumBase>(arg) + static_cast<ArgEnumBase>(ArgSpecSize));\n}\n\n/**\n * Base version of argument type.\n */\nconstexpr ArgEnum ArgBase(ArgEnum arg)\n{\n\treturn static_cast<ArgEnum>((static_cast<ArgEnumBase>(arg) & ~(static_cast<ArgEnumBase>(ArgSpecSize) - 1)));\n}\n/**\n * Specialized version of argument type.\n */\nconstexpr ArgEnum ArgSpecAdd(ArgEnum arg, ArgSpecEnum spec)\n{\n\treturn ArgBase(arg) != ArgInvalid ? static_cast<ArgEnum>(static_cast<ArgEnumBase>(arg) | static_cast<ArgEnumBase>(spec)) : arg;\n}\n/**\n * Remove specialization from argument type.\n */\nconstexpr ArgEnum ArgSpecRemove(ArgEnum arg, ArgSpecEnum spec)\n{\n\treturn ArgBase(arg) != ArgInvalid ? static_cast<ArgEnum>(static_cast<ArgEnumBase>(arg) & ~static_cast<ArgEnumBase>(spec)) : arg;\n}\n/**\n * Test if argument type is register (readonly or writeable).\n */\nconstexpr bool ArgIsReg(ArgEnum arg)\n{\n\treturn ArgBase(arg) != ArgInvalid && (static_cast<ArgEnumBase>(arg) & static_cast<ArgEnumBase>(ArgSpecReg)) == static_cast<ArgEnumBase>(ArgSpecReg);\n}\n/**\n * Test if argument type is variable (writeable register).\n */\nconstexpr bool ArgIsVar(ArgEnum arg)\n{\n\treturn ArgBase(arg) != ArgInvalid && (static_cast<ArgEnumBase>(arg) & static_cast<ArgEnumBase>(ArgSpecVar)) == static_cast<ArgEnumBase>(ArgSpecVar);\n}\n/**\n * Test if argument type is pointer.\n */\nconstexpr bool ArgIsPtr(ArgEnum arg)\n{\n\treturn ArgBase(arg) != ArgInvalid && (static_cast<ArgEnumBase>(arg) & static_cast<ArgEnumBase>(ArgSpecPtr)) == static_cast<ArgEnumBase>(ArgSpecPtr);\n}\n/**\n * Test if argument type is editable pointer.\n */\nconstexpr bool ArgIsPtrE(ArgEnum arg)\n{\n\treturn ArgBase(arg) != ArgInvalid && (static_cast<ArgEnumBase>(arg) & static_cast<ArgEnumBase>(ArgSpecPtrE)) == static_cast<ArgEnumBase>(ArgSpecPtrE);\n}\n/**\n * Compatibility between operation argument type and variable type. Greater numbers mean bigger compatibility.\n * @param argType Type of operation argument.\n * @param varType Type of variable/value we try pass to operation.\n * @return Zero if incompatible, 255 if both types are same.\n */\nconstexpr int ArgCompatible(ArgEnum argType, ArgEnum varType, size_t overloadSize)\n{\n\treturn\n\t\tArgBase(argType) == ArgInvalid ? 0 :\n\t\tArgIsVar(argType) && argType != varType ? 0 :\n\t\tArgBase(argType) != ArgBase(varType) ? 0 :\n\t\tArgIsReg(argType) != ArgIsReg(varType) ? 0 :\n\t\tArgIsPtr(argType) != ArgIsPtr(varType) ? 0 :\n\t\tArgIsPtrE(argType) && !ArgIsPtrE(varType) ? 0 :\n\t\t\t255 - (ArgIsPtrE(argType) != ArgIsPtrE(varType) ? 128 : 0) - (ArgIsVar(argType) != ArgIsVar(varType) ? 64 : 0) - (overloadSize > 8 ? 8 : overloadSize);\n}\n\n/**\n * Function returning next unique value for ArgEnum.\n */\ninline ArgEnum ArgNextUniqueValue()\n{\n\tstatic ArgEnum curr = ArgMax;\n\tArgEnum old = curr;\n\tcurr = ArgNext(curr);\n\treturn old;\n}\n\n/**\n * Function matching some Type to ArgEnum.\n */\ntemplate<typename T>\ninline ArgEnum ArgRegisteType()\n{\n\tstatic_assert(std::is_same<T, std::remove_pointer_t<std::decay_t<T>>>::value, \"Only simple types are allowed\");\n\n\tif (std::is_same<T, ScriptInt>::value)\n\t{\n\t\treturn ArgInt;\n\t}\n\telse if (std::is_same<T, ScriptNull>::value)\n\t{\n\t\treturn ArgNull;\n\t}\n\telse if (std::is_same<T, ScriptText>::value)\n\t{\n\t\treturn ArgText;\n\t}\n\telse if (std::is_same<T, ProgPos>::value)\n\t{\n\t\treturn ArgLabel;\n\t}\n\telse if (std::is_same<T, ScriptArgSeparator>::value)\n\t{\n\t\treturn ArgSep;\n\t}\n\telse\n\t{\n\t\tstatic ArgEnum curr = ArgNextUniqueValue();\n\t\treturn curr;\n\t}\n}\n\n/**\n * Available regs.\n */\nenum RegEnum : Uint16\n{\n\tRegInvalid = (Uint16)-1,\n\n\tRegStartPos = 0,\n};\n\nstatic_assert(ScriptMaxReg < RegInvalid, \"RegInvalid could be interpreted as correct register\");\n\n/**\n * Return value from script operation.\n */\nenum RetEnum : Uint8\n{\n\tRetContinue = 0,\n\tRetEnd,\n\tRetError,\n\n\tRetSize,\n};\n\n/**\n * Common type meta data.\n */\nstruct TypeInfo\n{\n\tsize_t size;\n\tsize_t alignment;\n\n\t/// is type valid?\n\tconstexpr explicit operator bool() const { return size; }\n\n\t/// get next valid position for type\n\tconstexpr size_t nextRegPos(size_t prev) const\n\t{\n\t\treturn ((prev + alignment - 1) & ~(alignment - 1));\n\t}\n\t/// get total space used by this type with considering alignment\n\tconstexpr size_t needRegSpace(size_t prev) const\n\t{\n\t\treturn nextRegPos(prev) + size;\n\t}\n\n\t/// default value for pointers\n\tconstexpr static TypeInfo getPtrTypeInfo()\n\t{\n\t\treturn TypeInfo\n\t\t{\n\t\t\tsizeof(void*),\n\t\t\talignof(void*),\n\t\t};\n\t}\n};\n\n////////////////////////////////////////////////////////////\n//\t\t\t\tcontainers definitions\n////////////////////////////////////////////////////////////\n\n/**\n * Common base of script execution.\n */\nclass ScriptContainerBase\n{\n\tfriend struct ParserWriter;\n\tstd::vector<Uint8> _proc;\n\npublic:\n\t/// Constructor.\n\tScriptContainerBase() = default;\n\t/// Copy constructor.\n\tScriptContainerBase(const ScriptContainerBase&) = delete;\n\t/// Move constructor.\n\tScriptContainerBase(ScriptContainerBase&&) = default;\n\n\t/// Destructor.\n\t~ScriptContainerBase() = default;\n\n\t/// Copy.\n\tScriptContainerBase &operator=(const ScriptContainerBase&) = delete;\n\t/// Move.\n\tScriptContainerBase &operator=(ScriptContainerBase&&) = default;\n\n\t/// Test if is any script there.\n\texplicit operator bool() const\n\t{\n\t\treturn !_proc.empty();\n\t}\n\n\t/// Get pointer to proc data.\n\tconst Uint8* data() const\n\t{\n\t\treturn *this ? _proc.data() : nullptr;\n\t}\n};\n\n/**\n * Strong typed script.\n */\ntemplate<typename Parent, typename... Args>\nclass ScriptContainer : public ScriptContainerBase\n{\npublic:\n\t/// Load code from string in YAML node.\n\tvoid loadContainer(const std::string& parentName, const YAML::YamlNodeReader& reader, const Parent& parent)\n\t{\n\t\tparent.parseNode(*this, parentName, reader);\n\t}\n\t/// Load data from string.\n\tvoid loadContainer(const std::string& parentName, const std::string& srcCode, const Parent& parent)\n\t{\n\t\tparent.parseCode(*this, parentName, srcCode);\n\t}\n};\n\n/**\n * Common base of typed script with events.\n */\nclass ScriptContainerEventsBase\n{\n\tfriend class ScriptParserEventsBase;\n\tScriptContainerBase _current;\n\tconst ScriptContainerBase* _events = nullptr;\n\npublic:\n\t/// Test if is any script there.\n\texplicit operator bool() const\n\t{\n\t\treturn true;\n\t}\n\n\t/// Get pointer to proc data.\n\tconst Uint8* data() const\n\t{\n\t\treturn _current.data();\n\t}\n\t/// Get pointer to proc data.\n\tconst ScriptContainerBase* dataEvents() const\n\t{\n\t\treturn _events;\n\t}\n};\n\n/**\n * Strong typed script with events.\n */\ntemplate<typename Parent, typename... Args>\nclass ScriptContainerEvents : public ScriptContainerEventsBase\n{\npublic:\n\t/// Load code from string in YAML node.\n\tvoid loadContainer(const std::string& parentName, const YAML::YamlNodeReader& reader, const Parent& parent)\n\t{\n\t\tparent.parseNode(*this, parentName, reader);\n\t}\n\t/// Load data from string.\n\tvoid loadContainer(const std::string& parentName, const std::string& srcCode, const Parent& parent)\n\t{\n\t\tparent.parseCode(*this, parentName, srcCode);\n\t}\n};\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tworker definition\n////////////////////////////////////////////////////////////\n\nnamespace helper\n{\n\ntemplate<int I, typename Tuple, bool valid = ((size_t)I < std::tuple_size<Tuple>::value)>\nstruct GetTupleImpl\n{\n\tusing type = typename std::tuple_element<I, Tuple>::type;\n\tstatic type get(Tuple& t) { return std::get<I>(t); }\n};\n\ntemplate<int I, typename Tuple>\nstruct GetTupleImpl<I, Tuple, false>\n{\n\tusing type = void;\n\tstatic type get(Tuple& t) { }\n};\n\ntemplate<int I, typename Tuple>\nusing GetTupleType = typename GetTupleImpl<I, Tuple>::type;\n\ntemplate<int I, typename Tuple>\nGetTupleType<I, Tuple> GetTupleValue(Tuple& t) { return GetTupleImpl<I, Tuple>::get(t); }\n\n\n/**\n * Helper class extracting needed data from type T\n */\ntemplate<typename T>\nstruct TypeInfoImpl\n{\n\tusing t1 = typename std::decay<T>::type;\n\tusing t2 = typename std::remove_pointer<t1>::type;\n\tusing t3 = typename std::decay<t2>::type;\n\n\tstatic constexpr bool isRef = std::is_reference<T>::value;\n\tstatic constexpr bool isOutput = isRef && !std::is_const<T>::value;\n\tstatic constexpr bool isPtr = std::is_pointer<t1>::value;\n\tstatic constexpr bool isEditable = isPtr && !std::is_const<t2>::value;\n\n\tenum\n\t{\n\t\tmetaIsSimple = std::is_trivially_copyable_v<t3> && std::is_nothrow_default_constructible_v<t3> && std::is_trivially_destructible_v<t3>,\n\t\tmetaDestSize = metaIsSimple ? sizeof(t3) : 0,\n\t\tmetaDestAlign = metaIsSimple ? alignof(t3) : 0\n\t};\n\n\t/// meta data of destination type (without pointer), invalid if type is not POD\n\tstatic constexpr TypeInfo metaDest =\n\t{\n\t\tmetaDestSize,\n\t\tmetaDestAlign,\n\t};\n\t/// meta data of base type (with pointer if it is)\n\tstatic constexpr TypeInfo metaBase =\n\t{\n\t\tsizeof(t1),\n\t\talignof(t1),\n\t};\n\n\tstatic_assert(+metaDestSize || isPtr, \"Type need to be POD to be used as reg or const value.\");\n\tstatic_assert((alignof(t1) & (alignof(t1) - 1)) == 0, \"Type alignment is not power of two\");\n};\n\ntemplate<typename T>\nconstexpr TypeInfo TypeInfoImpl<T>::metaDest;\ntemplate<typename T>\nconstexpr TypeInfo TypeInfoImpl<T>::metaBase;\n\n} //namespace helper\n\n/**\n * Raw memory used by scripts.\n */\ntemplate<int size>\nusing ScriptRawMemory = typename std::aligned_storage<size, alignof(void*)>::type;\n\n/**\n * Script output and input arguments.\n */\ntemplate<typename... OutputArgs>\nstruct ScriptOutputArgs\n{\n\tstd::tuple<helper::Decay<OutputArgs>...> data;\n\n\t/// Default constructor.\n\tScriptOutputArgs() : data{ }\n\t{\n\n\t}\n\n\t/// Constructor.\n\tScriptOutputArgs(const helper::Decay<OutputArgs>&... args) : data{ args... }\n\t{\n\n\t}\n\n\t/// Getter for first element.\n\tauto getFirst() -> helper::GetTupleType<0, decltype(data)> { return helper::GetTupleValue<0>(data); }\n\t/// Getter for second element.\n\tauto getSecond() -> helper::GetTupleType<1, decltype(data)> { return helper::GetTupleValue<1>(data); }\n\t/// Getter for third element.\n\tauto getThird() -> helper::GetTupleType<2, decltype(data)> { return helper::GetTupleValue<2>(data); }\n};\n\n/**\n * Specialization of script output and input arguments.\n */\ntemplate<>\nstruct ScriptOutputArgs<>\n{\n\tstd::tuple<> data;\n\n\t/// Default constructor.\n\tScriptOutputArgs() : data{ }\n\t{\n\n\t}\n};\n\n/**\n * Class execute scripts and store its data.\n */\nclass ScriptWorkerBase\n{\n\tstd::string log_buffer;\n\tScriptRawMemory<ScriptMaxReg> reg;\n\n\tstatic constexpr int RegSet = 1;\n\tstatic constexpr int RegNone = 0;\n\tstatic constexpr int RegGet = -1;\n\n\n\ttemplate<typename>\n\tusing SetAllRegs = helper::PosTag<RegSet>;\n\n\ttemplate<typename T>\n\tusing GetWritableRegs = helper::PosTag<helper::TypeInfoImpl<T>::isOutput ? RegGet : RegNone>;\n\n\ttemplate<typename T>\n\tusing SetReadonlyRegs = helper::PosTag<!helper::TypeInfoImpl<T>::isOutput ? RegSet : RegNone>;\n\n\ttemplate<size_t BaseOffset, int I, typename... Args, typename T>\n\tvoid forRegImplLoop(helper::PosTag<RegSet>, const T& arg)\n\t{\n\t\tusing CurrentType =helper::Decay<typename std::tuple_element<I, T>::type>;\n\t\tconstexpr int CurrentOffset = offset<void, Args...>(I, BaseOffset);\n\n\t\tref<CurrentType>(CurrentOffset) = std::get<I>(arg);\n\t}\n\ttemplate<size_t BaseOffset, int I, typename... Args, typename T>\n\tvoid forRegImplLoop(helper::PosTag<RegNone>, const T& arg)\n\t{\n\t\t// nothing\n\t}\n\ttemplate<size_t BaseOffset, int I, typename... Args, typename T>\n\tvoid forRegImplLoop(helper::PosTag<RegGet>, T& arg)\n\t{\n\t\tusing CurrentType = helper::Decay<typename std::tuple_element<I, T>::type>;\n\t\tconstexpr size_t CurrentOffset = offset<void, Args...>(I, BaseOffset);\n\n\t\tstd::get<I>(arg) = ref<CurrentType>(CurrentOffset);\n\t}\n\n\ttemplate<size_t BaseOffset, template<typename> class Filter, typename... Args, typename T, int... I>\n\tvoid forRegImpl(T&& arg, helper::ListTag<I...>)\n\t{\n\t\t(forRegImplLoop<BaseOffset, I, Args...>(Filter<Args>{}, std::forward<T>(arg)), ...);\n\t}\n\n\ttemplate<size_t BaseOffset, template<typename> class Filter, typename... Args, typename T>\n\tvoid forReg(T&& arg)\n\t{\n\t\tforRegImpl<BaseOffset, Filter, Args...>(std::forward<T>(arg), helper::MakeListTag<sizeof...(Args)>{});\n\t}\n\n\t/// Count offset.\n\ttemplate<typename, typename First, typename... Rest>\n\tstatic constexpr size_t offset(int i, size_t prevOffset)\n\t{\n\t\tusing typeInfoImp = typename helper::TypeInfoImpl<First>;\n\t\treturn offset<void, Rest...>(\n\t\t\ti - 1,\n\t\t\t(i > 0 ? typeInfoImp::metaBase.needRegSpace(prevOffset) :\n\t\t\ti == 0 ? typeInfoImp::metaBase.nextRegPos(prevOffset) :\n\t\t\t\tprevOffset)\n\t\t);\n\t}\n\t/// Final function of counting offset.\n\ttemplate<typename>\n\tstatic constexpr size_t offset(int i, size_t prevOffset)\n\t{\n\t\treturn prevOffset;\n\t}\n\n\ttemplate<typename... Args>\n\tstatic constexpr size_t offsetOutput(helper::TypeTag<ScriptOutputArgs<Args...>>)\n\t{\n\t\treturn offset<void, Args...>(sizeof...(Args), 0);\n\t}\n\nprotected:\n\t/// Update values in script.\n\ttemplate<typename Output, typename... Args>\n\tvoid updateBase(Args... args)\n\t{\n\t\tmemset(&reg, 0, ScriptMaxReg);\n\t\tforReg<offsetOutput(helper::TypeTag<Output>{}), SetAllRegs, Args...>(std::tie(args...));\n\t}\n\n\ttemplate<typename... Args>\n\tvoid set(const ScriptOutputArgs<Args...>& arg)\n\t{\n\t\tforReg<0, SetAllRegs, Args...>(arg.data);\n\t}\n\ttemplate<typename... Args>\n\tvoid get(ScriptOutputArgs<Args...>& arg)\n\t{\n\t\tforReg<0, GetWritableRegs, Args...>(arg.data);\n\t}\n\ttemplate<typename... Args>\n\tvoid reset(const ScriptOutputArgs<Args...>& arg)\n\t{\n\t\tforReg<0, SetReadonlyRegs, Args...>(arg.data);\n\t}\n\n\t/// Call script.\n\tvoid executeBase(const Uint8* proc);\n\npublic:\n\t/// Default constructor.\n\tScriptWorkerBase()\n\t{\n\n\t}\n\n\t/// Get value from reg.\n\ttemplate<typename T>\n\tT& ref(size_t off)\n\t{\n\t\treturn *reinterpret_cast<typename std::decay<T>::type*>(reinterpret_cast<char*>(&reg) + off);\n\t}\n\t/// Get value from proc vector.\n\ttemplate<typename T>\n\tT const_val(const Uint8 *ptr, size_t off = 0)\n\t{\n\t\tT ret;\n\t\tstd::memcpy(&ret, ptr + off, sizeof(T));\n\t\treturn ret;\n\t}\n\n\t/// Add text to log buffer.\n\tvoid log_buffer_add(FuncRef<std::string()> func);\n\t/// Flush buffer to log file.\n\tvoid log_buffer_flush(ProgPos& p);\n};\n\n/**\n * Strong typed script executor base template.\n */\ntemplate<typename Output, typename... Args>\nclass ScriptWorker;\n\n/**\n * Strong typed script executor.\n */\ntemplate<typename... OutputArgs, typename... Args>\nclass ScriptWorker<ScriptOutputArgs<OutputArgs...>, Args...> : public ScriptWorkerBase\n{\npublic:\n\t/// Type of output value from script.\n\tusing Output = ScriptOutputArgs<OutputArgs...>;\n\n\t/// Default constructor.\n\tScriptWorker(Args... args) : ScriptWorkerBase()\n\t{\n\t\tupdateBase<Output>(args...);\n\t}\n\n\t/// Execute standard script.\n\ttemplate<typename Parent>\n\tvoid execute(const ScriptContainer<Parent, Args...>& c, Output& arg)\n\t{\n\t\tstatic_assert(std::is_same<typename Parent::Output, Output>::value, \"Incompatible script output type\");\n\n\t\tset(arg);\n\t\texecuteBase(c.data());\n\t\tget(arg);\n\t}\n\n\t/// Execute standard script with global events.\n\ttemplate<typename Parent>\n\tvoid execute(const ScriptContainerEvents<Parent, Args...>& c, Output& arg)\n\t{\n\t\tstatic_assert(std::is_same<typename Parent::Output, Output>::value, \"Incompatible script output type\");\n\n\t\tset(arg);\n\t\tauto ptr = c.dataEvents();\n\t\tif (ptr)\n\t\t{\n\t\t\twhile (*ptr)\n\t\t\t{\n\t\t\t\treset(arg);\n\t\t\t\texecuteBase(ptr->data());\n\t\t\t\t++ptr;\n\t\t\t}\n\t\t\t++ptr;\n\t\t}\n\t\treset(arg);\n\t\texecuteBase(c.data());\n\t\tif (ptr)\n\t\t{\n\t\t\twhile (*ptr)\n\t\t\t{\n\t\t\t\treset(arg);\n\t\t\t\texecuteBase(ptr->data());\n\t\t\t\t++ptr;\n\t\t\t}\n\t\t}\n\t\tget(arg);\n\t}\n};\n\n/**\n * Strong typed blit script executor.\n */\nclass ScriptWorkerBlit : public ScriptWorkerBase\n{\n\t/// Current script set in worker.\n\tconst Uint8* _proc;\n\tconst ScriptContainerBase* _events;\n\npublic:\n\t/// Type of output value from script.\n\tusing Output = ScriptOutputArgs<int&, int>;\n\n\t/// Default constructor.\n\tScriptWorkerBlit() : ScriptWorkerBase(), _proc(nullptr), _events(nullptr)\n\t{\n\n\t}\n\n\t/// Update data from container script.\n\ttemplate<typename Parent, typename... Args>\n\tvoid update(const ScriptContainer<Parent, Args...>& c, helper::Decay<Args>... args)\n\t{\n\t\tstatic_assert(std::is_same<typename Parent::Output, Output>::value, \"Incompatible script output type\");\n\t\tclear();\n\t\tif (c)\n\t\t{\n\t\t\t_proc = c.data();\n\t\t\t_events = nullptr;\n\t\t\tupdateBase<Output>(args...);\n\t\t}\n\t}\n\n\t/// Update data from container script.\n\ttemplate<typename Parent, typename... Args>\n\tvoid update(const ScriptContainerEvents<Parent, Args...>& c, helper::Decay<Args>... args)\n\t{\n\t\tstatic_assert(std::is_same<typename Parent::Output, Output>::value, \"Incompatible script output type\");\n\t\tclear();\n\t\tif (c)\n\t\t{\n\t\t\t_proc = c.data();\n\t\t\t_events = c.dataEvents();\n\t\t\tupdateBase<Output>(args...);\n\t\t}\n\t}\n\n\t/// Programmable blitting using script.\n\tvoid executeBlit(const Surface* src, Surface* dest, int x, int y, int shade);\n\t/// Programmable blitting using script.\n\tvoid executeBlit(const Surface* src, Surface* dest, int x, int y, int shade, GraphSubset mask);\n\n\t/// Clear all worker data.\n\tvoid clear()\n\t{\n\t\t_proc = nullptr;\n\t\t_events = nullptr;\n\t}\n};\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tobjects ranges\n////////////////////////////////////////////////////////////\n\n/**\n * Range of values.\n */\ntemplate<typename T>\nclass ScriptRange\n{\nprotected:\n\tusing ptr = const T*;\n\n\t/// Pointer pointing place of first element.\n\tptr _begin;\n\t/// pointer pointing place past of last element.\n\tptr _end;\n\npublic:\n\t/// Default constructor.\n\tconstexpr ScriptRange() noexcept : _begin{ nullptr }, _end{ nullptr }\n\t{\n\n\t}\n\t/// Constructor.\n\tconstexpr ScriptRange(ptr b, ptr e) noexcept : _begin{ b }, _end{ e }\n\t{\n\n\t}\n\n\t/// Beginning of string range.\n\tconstexpr ptr begin() const\n\t{\n\t\treturn _begin;\n\t}\n\t/// End of string range.\n\tconstexpr ptr end() const\n\t{\n\t\treturn _end;\n\t}\n\t/// Size of string range.\n\tconstexpr size_t size() const\n\t{\n\t\treturn _end - _begin;\n\t}\n\t/// Bool operator.\n\tconstexpr explicit operator bool() const\n\t{\n\t\treturn _begin != _end;\n\t}\n};\n\n/**\n * Symbol in script.\n */\nclass ScriptRef : public ScriptRange<char>\n{\npublic:\n\t/// Default constructor.\n\tconstexpr ScriptRef() noexcept = default;\n\n\t/// Copy constructor.\n\tconstexpr ScriptRef(const ScriptRef&) noexcept = default;\n\n\t/// Constructor from char array.\n\ttemplate<int I>\n\tconstexpr explicit ScriptRef(const char (&p)[I]) noexcept : ScriptRange{ p , p + I - 1 }\n\t{\n\n\t}\n\n\t/// Constructor from range of pointers.\n\tconstexpr ScriptRef(ptr b, ptr e) noexcept : ScriptRange{ b, e }\n\t{\n\n\t}\n\n\t/// Copy assignment.\n\tconstexpr ScriptRef& operator=(const ScriptRef& r) noexcept = default;\n\n\n\n\t/// Find first occurrence of character in string range.\n\tconstexpr size_t find(char c) const\n\t{\n\t\tfor (auto &curr : *this)\n\t\t{\n\t\t\tif (curr == c)\n\t\t\t{\n\t\t\t\treturn &curr - _begin;\n\t\t\t}\n\t\t}\n\t\treturn std::string::npos;\n\t}\n\n\t/// Return sub range of current range.\n\tconstexpr ScriptRef substr(size_t p, size_t s = std::string::npos) const\n\t{\n\t\tconst size_t totalSize = size();\n\t\tif (p >= totalSize)\n\t\t{\n\t\t\treturn ScriptRef{ };\n\t\t}\n\n\t\tconst auto b = _begin + p;\n\t\tif (s > totalSize - p)\n\t\t{\n\t\t\treturn ScriptRef{ b, _end };\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn ScriptRef{ b, b + s };\n\t\t}\n\t}\n\n\tconstexpr ScriptRef head(size_t p) const\n\t{\n\t\treturn substr(0, p);\n\t}\n\n\tconstexpr ScriptRef tail(size_t p) const\n\t{\n\t\treturn substr(p);\n\t}\n\n\tconstexpr ScriptRef headFromEnd(size_t p) const\n\t{\n\t\tconst size_t totalSize = size();\n\t\tif (p >= totalSize)\n\t\t{\n\t\t\treturn *this;\n\t\t}\n\n\t\treturn substr(totalSize - p);\n\t}\n\n\tconstexpr ScriptRef tailFromEnd(size_t p) const\n\t{\n\t\tconst size_t totalSize = size();\n\t\tif (p >= totalSize)\n\t\t{\n\t\t\treturn ScriptRef{ };\n\t\t}\n\n\t\treturn substr(0, totalSize - p);\n\t}\n\n\t/// Create string based on current range.\n\tstd::string toString() const\n\t{\n\t\treturn *this ? std::string(_begin, _end) : std::string{ };\n\t}\n\n\t/// Create temporary ref based on script.\n\tstatic ScriptRef tempFrom(const std::string& s)\n\t{\n\t\treturn { s.data(), s.data() + s.size() };\n\t}\n\n\t/// Create pernamet ref based on script.\n\tconstexpr static ScriptRef staticFrom(ptr p)\n\t{\n\t\treturn { p, p + std::char_traits<char>::length(p) };\n\t}\n\n\t/// Compare two ranges.\n\tconstexpr static int compare(ScriptRef a, ScriptRef b)\n\t{\n\t\tconst auto size_a = a.size();\n\t\tconst auto size_b = b.size();\n\n\t\tif (size_a == size_b)\n\t\t{\n\t\t\t//check for GCC warnings, it thinks that we try use extremely long strings there...\n\t\t\tassert(size_a < SIZE_MAX/2);\n\n\t\t\treturn memcmp(a._begin, b._begin, size_a);\n\t\t}\n\t\telse if (size_a < size_b)\n\t\t{\n\t\t\treturn -1;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn 1;\n\t\t}\n\t}\n\n\t/// Equal operator.\n\tconstexpr bool operator==(const ScriptRef& s) const\n\t{\n\t\treturn compare(*this, s) == 0;\n\t}\n\n\t/// Not-equal operator.\n\tconstexpr bool operator!=(const ScriptRef& s) const\n\t{\n\t\treturn compare(*this, s) != 0;\n\t}\n\n\t/// Less operator.\n\tconstexpr bool operator<(const ScriptRef& s) const\n\t{\n\t\treturn compare(*this, s) < 0;\n\t}\n};\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tparser definitions\n////////////////////////////////////////////////////////////\n\n/**\n * Struct storing script type data.\n */\nstruct ScriptTypeData\n{\n\tScriptRef name;\n\tArgEnum type;\n\tTypeInfo meta;\n};\n\n/**\n * Struct storing value used by script.\n */\nstruct ScriptValueData\n{\n\tScriptRawMemory<2*sizeof(void*)> data = { };\n\tArgEnum type = ArgInvalid;\n\tUint8 size = 0;\n\n\t/// Copy constructor.\n\ttemplate<typename T>\n\tinline ScriptValueData(const T& t);\n\t/// Copy constructor.\n\tinline ScriptValueData(const ScriptValueData& t);\n\t/// Default constructor.\n\tinline ScriptValueData() { }\n\n\t/// Assign operator.\n\ttemplate<typename T>\n\tinline ScriptValueData& operator=(const T& t);\n\t/// Assign operator.\n\tinline ScriptValueData& operator=(const ScriptValueData& t);\n\n\t/// Test if value have have selected type.\n\ttemplate<typename T>\n\tinline bool isValueType() const;\n\t/// Get current stored value.\n\ttemplate<typename T>\n\tinline const T& getValue() const;\n\n\tbool operator==(const ScriptValueData& other) const\n\t{\n\t\treturn type == other.type && memcmp(&data, &other.data, size) == 0;\n\t}\n\tbool operator!=(const ScriptValueData& other) const\n\t{\n\t\treturn !(*this == other);\n\t}\n};\n\n/**\n * Struct used to store named definition used by script.\n */\nstruct ScriptRefData\n{\n\tScriptRef name;\n\tArgEnum type = ArgInvalid;\n\tScriptValueData value;\n\n\t/// Default constructor.\n\tScriptRefData() { }\n\t/// Constructor.\n\tScriptRefData(ScriptRef n, ArgEnum t) : name{ n }, type{ t } {  }\n\t/// Constructor.\n\tScriptRefData(ScriptRef n, ArgEnum t, ScriptValueData v) : name{ n }, type{ t }, value{ v } {  }\n\n\t/// Get true if this valid reference.\n\texplicit operator bool() const\n\t{\n\t\treturn type != ArgInvalid;\n\t}\n\n\ttemplate<typename T>\n\tbool isValueType() const\n\t{\n\t\treturn value.isValueType<T>();\n\t}\n\t/// Get current stored value.\n\ttemplate<typename T>\n\tconst T& getValue() const\n\t{\n\t\treturn value.getValue<T>();\n\t}\n\t/// Get current stored value if have that type or default value otherwise.\n\ttemplate<typename T>\n\tconst T& getValueOrDefulat(const T& def) const\n\t{\n\t\treturn value.isValueType<T>() ? value.getValue<T>() : def;\n\t}\n};\n\n/**\n * Struct storing available operation to scripts.\n */\nstruct ScriptProcData\n{\n\tusing argFunc = int (*)(ParserWriter& ph, const ScriptRefData* begin, const ScriptRefData* end);\n\tusing getFunc = ScriptFunc (*)(int version);\n\tusing parserFunc = bool (*)(const ScriptProcData& spd, ParserWriter& ph, const ScriptRefData* begin, const ScriptRefData* end);\n\tusing overloadFunc = int (*)(const ScriptProcData& spd, const ScriptRefData* begin, const ScriptRefData* end);\n\n\tScriptRef name;\n\tScriptRef description;\n\n\toverloadFunc overload;\n\tScriptRange<ScriptRange<ArgEnum>> overloadArg;\n\n\tparserFunc parser;\n\targFunc parserArg;\n\tgetFunc parserGet;\n\n\tbool operator()(ParserWriter& ph, const ScriptRefData* begin, const ScriptRefData* end) const\n\t{\n\t\treturn parser(*this, ph, begin, end);\n\t}\n};\n\n/**\n * Common base of script parser.\n */\nclass ScriptParserBase\n{\n\tScriptGlobal* _shared;\n\tbool _emptyReturn;\n\tsize_t _regUsedSpace;\n\tUint8 _regOutSize;\n\tScriptRef _regOutName[ScriptMaxOut];\n\tstd::string _name;\n\tstd::string _defaultScript;\n\tstd::string _description;\n\tstd::vector<std::vector<char>> _strings;\n\tstd::vector<ScriptTypeData> _typeList;\n\tstd::vector<ScriptProcData> _procList;\n\tstd::vector<ScriptRefData> _refList;\n\nprotected:\n\ttemplate<typename First, typename... Rest>\n\tvoid addRegImpl(bool writable, helper::ArgName<First>& n, Rest&... t)\n\t{\n\t\taddTypeImpl(helper::TypeTag<helper::Decay<First>>{});\n\t\taddScriptReg(n.name, ScriptParserBase::getArgType<First>(), writable, helper::TypeInfoImpl<First>::isOutput);\n\t\taddRegImpl(writable, t...);\n\t}\n\tvoid addRegImpl(bool writable)\n\t{\n\t\t//end loop\n\t}\n\n\t/// Function for SFINAE, type need to have ScriptRegister function.\n\ttemplate<typename First, typename = decltype(&First::ScriptRegister)>\n\tvoid addTypeImpl(helper::TypeTag<First*>)\n\t{\n\t\tregisterPointerType<First>();\n\t}\n\t/// Function for SFINAE, type need to have ScriptRegister function.\n\ttemplate<typename First, typename = decltype(&First::ScriptRegister)>\n\tvoid addTypeImpl(helper::TypeTag<const First*>)\n\t{\n\t\tregisterPointerType<First>();\n\t}\n\t/// Function for SFINAE, type need to have ScriptRegister function.\n\ttemplate<typename First, typename Index, typename = decltype(&First::ScriptRegister)>\n\tvoid addTypeImpl(helper::TypeTag<ScriptTag<First, Index>>)\n\t{\n\t\tregisterPointerType<First>();\n\t}\n\t/// Basic version.\n\ttemplate<typename First>\n\tvoid addTypeImpl(helper::TypeTag<First>)\n\t{\n\t\t//nothing to do for rest\n\t}\n\n\t/// Default constructor.\n\tScriptParserBase(ScriptGlobal* shared, const std::string& name);\n\t/// Destructor.\n\t~ScriptParserBase();\n\n\t/// Common typeless part of parsing string.\n\tbool parseBase(ScriptContainerBase& scr, const std::string& parentName, const std::string& srcCode) const;\n\n\t/// Parse node and return new script.\n\tvoid parseNode(ScriptContainerBase& container, const std::string& parentName, const YAML::YamlNodeReader& reader) const;\n\n\t/// Parse string and return new script.\n\tvoid parseCode(ScriptContainerBase& container, const std::string& parentName, const std::string& srcCode) const;\n\n\t/// Test if name is free.\n\tbool haveNameRef(const std::string& s) const;\n\t/// Add new name that can be used in data lists.\n\tScriptRef addNameRef(const std::string& s);\n\n\t/// Add name for custom parameter.\n\tvoid addScriptReg(const std::string& s, ArgEnum type, bool writableReg, bool outputReg);\n\t/// Add parsing function.\n\tvoid addParserBase(const std::string& s, const std::string& description, ScriptProcData::overloadFunc overload, ScriptRange<ScriptRange<ArgEnum>> overloadArg, ScriptProcData::parserFunc parser, ScriptProcData::argFunc parserArg, ScriptProcData::getFunc parserGet);\n\t/// Add new type implementation.\n\tvoid addTypeBase(const std::string& s, ArgEnum type, TypeInfo meta);\n\t/// Test if type was added implementation.\n\tbool haveTypeBase(ArgEnum type);\n\t/// Set default script for type.\n\tvoid setDefault(const std::string& s) { _defaultScript = s; }\n\t/// Set description for script.\n\tvoid setDescription(const std::string& s) { _description = s; }\n\t/// Set mode where return does not accept any value.\n\tvoid setEmptyReturn() { _emptyReturn = true; }\n\npublic:\n\t/// Register type to get run time value representing it.\n\ttemplate<typename T>\n\tstatic ArgEnum getArgType()\n\t{\n\t\tusing info = helper::TypeInfoImpl<T>;\n\t\tusing t3 = typename info::t3;\n\n\t\tauto spec = ArgSpecNone;\n\n\t\tif (info::isRef) spec = spec | ArgSpecVar;\n\t\tif (info::isPtr) spec = spec | ArgSpecPtr;\n\t\tif (info::isEditable) spec = spec | ArgSpecPtrE;\n\n\t\treturn ArgSpecAdd(ArgRegisteType<t3>(), spec);\n\t}\n\t/// Add const value.\n\tvoid addConst(const std::string& s, ScriptValueData i);\n\t/// Update const value.\n\tvoid updateConst(const std::string& s, ScriptValueData i);\n\t/// Add line parsing function.\n\ttemplate<typename T>\n\tvoid addParser(const std::string& s, const std::string& description)\n\t{\n\t\taddParserBase(s, description, nullptr, T::overloadType(), nullptr, &T::parse, &T::getDynamic);\n\t}\n\t/// Test if type was already added.\n\ttemplate<typename T>\n\tbool haveType()\n\t{\n\t\treturn haveTypeBase(getArgType<T>());\n\t}\n\t/// Add new type.\n\ttemplate<typename T>\n\tvoid addType(const std::string& s)\n\t{\n\t\tusing info = helper::TypeInfoImpl<T>;\n\t\tusing t3 = typename info::t3;\n\n\t\taddTypeBase(s, ArgRegisteType<t3>(), info::metaDest);\n\t}\n\n\t/// Register pointer type in parser.\n\ttemplate<typename P>\n\tvoid registerPointerType()\n\t{\n\t\tif (!haveType<P*>())\n\t\t{\n\t\t\taddType<P*>(P::ScriptName);\n\t\t\tP::ScriptRegister(this);\n\t\t}\n\t}\n\t/// Register pointer type with name in parser but without any automatic registrations.\n\ttemplate<typename P>\n\tvoid registerRawPointerType(const std::string& s)\n\t{\n\t\tif (!haveType<P*>())\n\t\t{\n\t\t\taddType<P*>(s);\n\t\t}\n\t}\n\t/// Register value type with name in parser but without any automatic registrations.\n\ttemplate<typename P>\n\tvoid registerRawValueType(const std::string& s)\n\t{\n\t\tif (!haveType<P>())\n\t\t{\n\t\t\taddType<P>(s);\n\t\t}\n\t}\n\n\t/// Show all script informations.\n\tvoid logScriptMetadata(bool haveEvents, const std::string& groupName) const;\n\n\t/// Get name of script.\n\tconst std::string& getName() const { return _name; }\n\t/// Get default script.\n\tconst std::string& getDefault() const { return _defaultScript; }\n\n\t/// Get number of parameters.\n\tUint8 getParamSize() const { return _regOutSize; }\n\t/// Get parameter data.\n\tconst ScriptRefData* getParamData(Uint8 i) const { return getRef(_regOutName[i]); }\n\n\t/// Get name of type.\n\tScriptRef getTypeName(ArgEnum type) const;\n\t/// Get full name of type.\n\tstd::string getTypePrefix(ArgEnum type) const;\n\t/// Get type data.\n\tconst ScriptTypeData* getType(ArgEnum type) const;\n\t/// Get type data.\n\tconst ScriptTypeData* getType(ScriptRef name) const\n\t{\n\t\tScriptRef r[] = { name };\n\t\treturn getType({ std::begin(r), std::end(r)});\n\t}\n\t/// Get function data.\n\tScriptRange<ScriptProcData> getProc(ScriptRef name) const\n\t{\n\t\tScriptRef r[] = { name };\n\t\treturn getProc({ std::begin(r), std::end(r)});\n\t}\n\t/// Get arguments data.\n\tconst ScriptRefData* getRef(ScriptRef name) const\n\t{\n\t\tScriptRef r[] = { name };\n\t\treturn getRef({ std::begin(r), std::end(r)});\n\t}\n\t/// Get type data.\n\tconst ScriptTypeData* getType(ScriptRange<ScriptRef> name) const;\n\t/// Get function data.\n\tScriptRange<ScriptProcData> getProc(ScriptRange<ScriptRef> name) const;\n\t/// Get arguments data.\n\tconst ScriptRefData* getRef(ScriptRange<ScriptRef> name) const;\n\n\t/// Get script shared data.\n\tScriptGlobal* getGlobal() { return _shared; }\n\t/// Get script shared data.\n\tconst ScriptGlobal* getGlobal() const { return _shared; }\n\t/// Get true if return does not accept any arguments.\n\tbool haveEmptyReturn() const { return _emptyReturn; }\n};\n\n/**\n * Copy constructor from pod type.\n */\ntemplate<typename T>\ninline ScriptValueData::ScriptValueData(const T& t)\n{\n\tstatic_assert(sizeof(T) <= sizeof(data), \"Value have too big size!\");\n\ttype = ScriptParserBase::getArgType<T>();\n\tsize = sizeof(T);\n\tmemcpy(&data, &t, sizeof(T));\n}\n\n/**\n * Copy constructor.\n */\ninline ScriptValueData::ScriptValueData(const ScriptValueData& t)\n{\n\t*this = t;\n}\n\n/**\n * Assign operator from pod type.\n */\ntemplate<typename T>\ninline ScriptValueData& ScriptValueData::operator=(const T& t)\n{\n\t*this = ScriptValueData{ t };\n\treturn *this;\n}\n\n/**\n * Assign operator.\n */\ninline ScriptValueData& ScriptValueData::operator=(const ScriptValueData& t)\n{\n\ttype = t.type;\n\tsize = t.size;\n\tmemcpy(&data, &t.data, sizeof(data));\n\treturn *this;\n}\n\n/**\n * Test if value have have selected type.\n */\ntemplate<typename T>\ninline bool ScriptValueData::isValueType() const\n{\n\treturn type == ScriptParserBase::getArgType<T>();\n}\n\n/**\n * Get current stored value.\n */\ntemplate<typename T>\ninline const T& ScriptValueData::getValue() const\n{\n\tif (!isValueType<T>())\n\t{\n\t\tthrow Exception(\"Invalid cast of value\");\n\t}\n\treturn *reinterpret_cast<const T*>(&data);\n}\n\n/**\n * Base template of strong typed parser.\n */\ntemplate<typename OutputPar, typename... Args>\nclass ScriptParser\n{\npublic:\n\tusing Container = ScriptContainerEvents<ScriptParser, Args...>;\n\tusing Output = OutputPar;\n\tusing Worker = ScriptWorker<Output, Args...>;\n\n\tstatic_assert(helper::StaticError<ScriptParser>::value, \"Invalid parameters to template\");\n};\n\n/**\n * Strong typed parser.\n */\ntemplate<typename... OutputArgs, typename... Args>\nclass ScriptParser<ScriptOutputArgs<OutputArgs...>, Args...> : public ScriptParserBase\n{\npublic:\n\tusing Container = ScriptContainer<ScriptParser, Args...>;\n\tusing Output = ScriptOutputArgs<OutputArgs...>;\n\tusing Worker = ScriptWorker<Output, Args...>;\n\tfriend Container;\n\n\t/// Constructor.\n\tScriptParser(ScriptGlobal* shared, const std::string& name, helper::ArgName<OutputArgs>... argOutputNames, helper::ArgName<Args>... argNames) : ScriptParserBase(shared, name)\n\t{\n\t\taddRegImpl(true, argOutputNames...);\n\t\taddRegImpl(false, argNames...);\n\t}\n};\n\n/**\n * Common base for strong typed event parser.\n */\nclass ScriptParserEventsBase : public ScriptParserBase\n{\n\tconstexpr static size_t EventsMax = 256;\n\tconstexpr static size_t OffsetScale = 100;\n\tconstexpr static size_t OffsetMax = 100 * OffsetScale;\n\n\tstruct EventData\n\t{\n\t\tint offset;\n\t\tstd::string name;\n\t\tScriptContainerBase script;\n\t};\n\n\t/// Final list of events.\n\tstd::vector<ScriptContainerBase> _events;\n\t/// Meta data of events.\n\tstd::vector<EventData> _eventsData;\n\nprotected:\n\t/// Parse node and return new script.\n\tvoid parseNode(ScriptContainerEventsBase& container, const std::string& type, const YAML::YamlNodeReader& reader) const;\n\t/// Parse string and return new script.\n\tvoid parseCode(ScriptContainerEventsBase& container, const std::string& type, const std::string& srcCode) const;\n\npublic:\n\t/// Constructor.\n\tScriptParserEventsBase(ScriptGlobal* shared, const std::string& name);\n\n\t/// Load global data from YAML.\n\tvoid loadEvents(const YAML::YamlNodeReader& reader);\n\t/// Get pointer to events.\n\tconst ScriptContainerBase* getEvents() const;\n\t/// Release event data.\n\tstd::vector<ScriptContainerBase> releseEvents();\n};\n\n/**\n * Base template of strong typed event parser.\n */\ntemplate<typename OutputPar, typename... Args>\nclass ScriptParserEvents\n{\npublic:\n\tusing Container = ScriptContainerEvents<ScriptParserEvents, Args...>;\n\tusing Output = OutputPar;\n\tusing Worker = ScriptWorker<Output, Args...>;\n\n\tstatic_assert(helper::StaticError<ScriptParserEvents>::value, \"Invalid parameters to template\");\n};\n\n/**\n * Strong typed event parser.\n */\ntemplate<typename... OutputArgs, typename... Args>\nclass ScriptParserEvents<ScriptOutputArgs<OutputArgs...>, Args...> : public ScriptParserEventsBase\n{\npublic:\n\tusing Container = ScriptContainerEvents<ScriptParserEvents, Args...>;\n\tusing Output = ScriptOutputArgs<OutputArgs...>;\n\tusing Worker = ScriptWorker<Output, Args...>;\n\tfriend Container;\n\n\t// Constructor.\n\tScriptParserEvents(ScriptGlobal* shared, const std::string& name, helper::ArgName<OutputArgs>... argOutputNames, helper::ArgName<Args>... argNames) : ScriptParserEventsBase(shared, name)\n\t{\n\t\taddRegImpl(true, argOutputNames...);\n\t\taddRegImpl(false, argNames...);\n\t}\n};\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\ttags definitions\n////////////////////////////////////////////////////////////\n\n/**\n * Strong typed tag.\n */\ntemplate<typename T, typename I = Uint16>\nstruct ScriptTag\n{\n\tstatic_assert(!std::numeric_limits<I>::is_signed, \"Type should be unsigned\");\n\tstatic_assert(sizeof(I) <= sizeof(size_t), \"Type need be smaller than size_t\");\n\n\tusing Parent = T;\n\n\t/// Index that identify value in ScriptValues.\n\tI index;\n\n\t/// Get value.\n\tconstexpr size_t get() const { return static_cast<size_t>(index); }\n\t/// Test if tag have valid value.\n\tconstexpr explicit operator bool() const { return this->index; }\n\t/// Equal operator.\n\tconstexpr bool operator==(ScriptTag t) const\n\t{\n\t\treturn index == t.index;\n\t}\n\t/// Not-equal operator.\n\tconstexpr bool operator!=(ScriptTag t) const\n\t{\n\t\treturn !(*this == t);\n\t}\n\n\t/// Get run time value for type.\n\tstatic ArgEnum type() { return ScriptParserBase::getArgType<ScriptTag<T, I>>(); }\n\t/// Test if value can be used.\n\tstatic constexpr bool isValid(size_t i) { return i && i <= limit(); }\n\t/// Fake constructor.\n\tstatic constexpr ScriptTag make(size_t i) { return { static_cast<I>(i) }; }\n\t/// Max supported value.\n\tstatic constexpr size_t limit() { return static_cast<size_t>(std::numeric_limits<I>::max()); }\n\t/// Null value.\n\tstatic constexpr ScriptTag getNullTag() { return make(0); }\n};\n\n/**\n * Global data shared by all scripts.\n */\nclass ScriptGlobal\n{\nprotected:\n\tusing LoadFunc = void (*)(const ScriptGlobal*, int&, const YAML::YamlNodeReader&);\n\tusing SaveFunc = void (*)(const ScriptGlobal*, const int&, YAML::YamlNodeWriter&);\n\tusing CrateFunc = ScriptValueData (*)(size_t i);\n\n\tfriend class ScriptValuesBase;\n\n\tstruct TagValueType\n\t{\n\t\tScriptRef name;\n\t\tLoadFunc load;\n\t\tSaveFunc save;\n\t};\n\tstruct TagValueData\n\t{\n\t\tScriptRef name;\n\t\tsize_t valueType;\n\t};\n\tstruct TagData\n\t{\n\t\tScriptRef name;\n\t\tsize_t limit;\n\t\tCrateFunc crate;\n\t\tstd::vector<TagValueData> values;\n\t};\n\n\ttemplate <typename ThisType, void (ThisType::*LoadValue)(int&, const YAML::YamlNodeReader&) const>\n\tstatic void loadHelper(const ScriptGlobal* base, int& value, const YAML::YamlNodeReader& reader)\n\t{\n\t\t(static_cast<const ThisType*>(base)->*LoadValue)(value, reader);\n\t}\n\ttemplate <typename ThisType, void (ThisType::*SaveValue)(const int&, YAML::YamlNodeWriter&) const>\n\tstatic void saveHelper(const ScriptGlobal* base, const int& value, YAML::YamlNodeWriter& writer)\n\t{\n\t\t(static_cast<const ThisType*>(base)->*SaveValue)(value, writer);\n\t}\n\n\tvoid addTagValueTypeBase(const std::string& name, LoadFunc loadFunc, SaveFunc saveFunc)\n\t{\n\t\t_tagValueTypes.push_back(TagValueType{ addNameRef(name), loadFunc, saveFunc });\n\t}\n\ttemplate <typename ThisType, void (ThisType::*LoadValue)(int&, const YAML::YamlNodeReader&) const, void (ThisType::*SaveValue)(const int&, YAML::YamlNodeWriter&) const>\n\tvoid addTagValueType(const std::string& name)\n\t{\n\t\tstatic_assert(std::is_base_of<ScriptGlobal, ThisType>::value, \"Type must be derived\");\n\t\taddTagValueTypeBase(name, &loadHelper<ThisType, LoadValue>, &saveHelper<ThisType, SaveValue>);\n\t}\n\nprivate:\n\tstd::string _currFile;\n\tstd::vector<std::vector<char>> _strings;\n\tstd::vector<std::vector<ScriptContainerBase>> _events;\n\tstd::map<std::string, ScriptParserBase*> _parserNames;\n\tstd::unordered_map<std::string_view, ScriptParserEventsBase*> _parserEvents;\n\tstd::map<ArgEnum, TagData> _tagNames;\n\tstd::vector<TagValueType> _tagValueTypes;\n\tstd::vector<ScriptRefData> _refList;\n\n\t/// Get tag value.\n\tsize_t getTag(ArgEnum type, ScriptRef s) const;\n\t/// Get data of tag value.\n\tTagValueData getTagValueData(ArgEnum type, size_t i) const;\n\t/// Get tag value type data.\n\tTagValueType getTagValueTypeData(size_t valueType) const;\n\t/// Get tag value type id.\n\tsize_t getTagValueTypeId(ScriptRef s) const;\n\t/// Add new tag name.\n\tsize_t addTag(ArgEnum type, ScriptRef s, size_t valueType);\n\t/// Add new name ref.\n\tScriptRef addNameRef(const std::string& s);\n\npublic:\n\t/// Default constructor.\n\tScriptGlobal();\n\t/// Destructor.\n\tvirtual ~ScriptGlobal();\n\n\t/// Store parser.\n\tvoid pushParser(const std::string& groupName, ScriptParserBase* parser);\n\t/// Store parser.\n\tvoid pushParser(const std::string& groupName, ScriptParserEventsBase* parser);\n\n\t/// Add new const value.\n\tvoid addConst(const std::string& name, ScriptValueData i);\n\t/// Update const value.\n\tvoid updateConst(const std::string& name, ScriptValueData i);\n\n\t/// Get global ref data.\n\tconst ScriptRefData* getRef(ScriptRef name, ScriptRef postfix = {}) const;\n\n\t/// Get all tag names\n\tconst std::map<ArgEnum, TagData> &getTagNames() const { return _tagNames; }\n\n\t/// Get tag based on it name.\n\ttemplate<typename Tag>\n\tTag getTag(ScriptRef s) const\n\t{\n\t\treturn Tag::make(getTag(Tag::type(), s));\n\t}\n\t/// Get tag based on it name.\n\ttemplate<typename Tag>\n\tTag getTag(const std::string& s) const\n\t{\n\t\treturn getTag<Tag>(ScriptRef::tempFrom(s));\n\t}\n\t/// Add new tag name.\n\ttemplate<typename Tag>\n\tTag addTag(const std::string& s, const std::string& valueTypeName)\n\t{\n\t\treturn Tag::make(addTag(Tag::type(), addNameRef(s), getTagValueTypeId(ScriptRef::tempFrom(valueTypeName))));\n\t}\n\t/// Add new type of tag.\n\ttemplate<typename Tag>\n\tvoid addTagType()\n\t{\n\t\tif (_tagNames.find(Tag::type()) == _tagNames.end())\n\t\t{\n\t\t\t_tagNames.insert(\n\t\t\t\tstd::make_pair(\n\t\t\t\t\tTag::type(),\n\t\t\t\t\tTagData\n\t\t\t\t\t{\n\t\t\t\t\t\tScriptRef::staticFrom(Tag::Parent::ScriptName),\n\t\t\t\t\t\tTag::limit(),\n\t\t\t\t\t\t[](size_t i) { return ScriptValueData{ Tag::make(i) }; },\n\t\t\t\t\t\tstd::vector<TagValueData>{},\n\t\t\t\t\t}\n\t\t\t\t)\n\t\t\t);\n\t\t}\n\t}\n\n\t/// Get current file that is loaded.\n\tconst std::string& getCurrentFile() const { return _currFile; }\n\n\t/// Initialize shared globals like types.\n\tvirtual void initParserGlobals(ScriptParserBase* parser) { }\n\t/// Prepare for loading data.\n\tvirtual void beginLoad();\n\t/// Prepare for loading file.\n\tvirtual void fileLoad(const std::string& path);\n\t/// Finishing loading data.\n\tvirtual void endLoad();\n\n\t/// Load global data from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader);\n};\n\n/**\n * Collection of values for script usage.\n */\nclass ScriptValuesBase\n{\n\t/// Vector with all available values for script.\n\tstd::vector<int> values;\n\nprotected:\n\t/// Get all values\n\tconst std::vector<int> &getValues() const { return values; }\n\t/// Set value.\n\tvoid setBase(size_t t, int i);\n\t/// Get value.\n\tint getBase(size_t t) const;\n\t/// Load values from yaml file.\n\tvoid loadBase(const YAML::YamlNodeReader& reader, const ScriptGlobal* shared, ArgEnum type, const std::string& nodeName);\n\t/// Save values to yaml file.\n\tvoid saveBase(YAML::YamlNodeWriter& writer, const ScriptGlobal* shared, ArgEnum type, const std::string& nodeName) const;\n};\n\n/**\n * Strong typed collection of values for script.\n */\ntemplate<typename T, typename I = Uint16>\nclass ScriptValues : ScriptValuesBase\n{\npublic:\n\tusing Tag = ScriptTag<T, I>;\n\tusing Parent = T;\n\n\t/// Load values from yaml file.\n\tvoid load(const YAML::YamlNodeReader& reader, const ScriptGlobal* shared, const std::string& nodeName = \"tags\")\n\t{\n\t\tloadBase(reader, shared, Tag::type(), nodeName);\n\t}\n\t/// Save values to yaml file.\n\tvoid save(YAML::YamlNodeWriter writer, const ScriptGlobal* shared, const std::string& nodeName = \"tags\") const\n\t{\n\t\tsaveBase(writer, shared, Tag::type(), nodeName);\n\t}\n\n\t/// Get value.\n\tint get(Tag t) const\n\t{\n\t\treturn getBase(t.get());\n\t}\n\t/// Set value.\n\tvoid set(Tag t, int i)\n\t{\n\t\treturn setBase(t.get(), i);\n\t}\n\t/// Get all values\n\tconst std::vector<int> &getValuesRaw() const { return getValues(); }\n};\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tscript groups\n////////////////////////////////////////////////////////////\n\ntemplate<typename Parent, typename... Parsers>\nclass ScriptGroupContainer : public Parsers::ContainerWarper...\n{\npublic:\n\t/// Get container by type.\n\ttemplate<typename SelectedParser>\n\ttypename SelectedParser::Container& get()\n\t{\n\t\treturn *static_cast<typename SelectedParser::ContainerWarper*>(this);\n\t}\n\n\t/// Get container by type.\n\ttemplate<typename SelectedParser>\n\tconst typename SelectedParser::Container& get() const\n\t{\n\t\treturn *static_cast<const typename SelectedParser::ContainerWarper*>(this);\n\t}\n\n\t/// Load scripts.\n\tvoid load(const std::string& type, const YAML::YamlNodeReader& reader, const Parent& parsers)\n\t{\n\t\tif (const YAML::YamlNodeReader& scripts = reader[\"scripts\"])\n\t\t{\n\t\t\tif (scripts.hasNullVal() == false && scripts.isMap() == false)\n\t\t\t{\n\t\t\t\tthrow Exception(\"Wrong type of 'scripts' node at line \" + std::to_string(scripts.getLocationInFile().line));\n\t\t\t}\n\n\t\t\tfor (auto& p : scripts.children())\n\t\t\t{\n\t\t\t\tauto key = p.key();\n\t\t\t\tif (key.length() > 0 && key.back() == '#')\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (parsers.isKnowParserName(key) == false)\n\t\t\t\t{\n\t\t\t\t\tthrow Exception(\"Unknown '\" + std::string(p.key()) + \"' node in 'scripts' at line \" + std::to_string(p.getLocationInFile().line));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t(get<Parsers>().loadContainer(type, reader, parsers.template get<Parsers>()), ...); //TODO: some scripts need called even if \"scripts\" is not present\n\t}\n};\n\ntemplate<typename Parser, char... NameChars>\nclass ScriptGroupNamedParser : public Parser\n{\n\ttemplate<typename... C>\n\tstatic constexpr unsigned length(unsigned curr, char head, C... tail)\n\t{\n\t\treturn head ? length(curr + 1, tail...) : curr;\n\t}\n\tstatic constexpr unsigned length(unsigned curr, char head)\n\t{\n\t\treturn head ? throw \"Script name too long!\" : curr;\n\t}\n\n\tstatic constexpr unsigned nameLenght = length(0, NameChars...);\n\npublic:\n\tusing BaseType = Parser;\n\tstruct ContainerWarper : Parser::Container\n\t{\n\n\t};\n\n\ttemplate<typename Master>\n\tScriptGroupNamedParser(ScriptGlobal* shared, Master* master) : Parser{ shared, std::string{ { NameChars... }, 0, nameLenght, }, master, }\n\t{\n\n\t}\n\n\tBaseType& getBase() { return *this; }\n};\n\ntemplate<typename Master, typename... Parsers>\nclass ScriptGroup : Parsers...\n{\n\tstd::unordered_set<std::string_view> _allParserNames;\n\npublic:\n\tusing Container = ScriptGroupContainer<ScriptGroup, Parsers...>;\n\n\t/// Constructor.\n\tScriptGroup(ScriptGlobal* shared, Master* master, const std::string& groupName) : Parsers{ shared, master, }...\n\t{\n\t\t(void)master;\n\t\t(void)groupName;\n\t\t(shared->pushParser(groupName, &get<Parsers>()), ...);\n\t\t(_allParserNames.insert(get<Parsers>().getName()), ...);\n\t}\n\n\t/// Get parser by type.\n\ttemplate<typename SelectedParser>\n\ttypename SelectedParser::BaseType& get()\n\t{\n\t\treturn *static_cast<SelectedParser*>(this);\n\t}\n\n\t/// Get parser by type.\n\ttemplate<typename SelectedParser>\n\tconst typename SelectedParser::BaseType& get() const\n\t{\n\t\treturn *static_cast<const SelectedParser*>(this);\n\t}\n\n\t/// Check if exists parser for given name\n\tbool isKnowParserName(std::string_view view) const\n\t{\n\t\treturn _allParserNames.find(view) != _allParserNames.end();\n\t}\n};\n\n#define MACRO_GET_STRING_1(str, i) \\\n\t(sizeof(str) > (i) ? str[(i)] : 0)\n\n#define MACRO_GET_STRING_4(str, i) \\\n\tMACRO_GET_STRING_1(str, i+0),  \\\n\tMACRO_GET_STRING_1(str, i+1),  \\\n\tMACRO_GET_STRING_1(str, i+2),  \\\n\tMACRO_GET_STRING_1(str, i+3)\n\n#define MACRO_GET_STRING_16(str, i) \\\n\tMACRO_GET_STRING_4(str, i+0),   \\\n\tMACRO_GET_STRING_4(str, i+4),   \\\n\tMACRO_GET_STRING_4(str, i+8),   \\\n\tMACRO_GET_STRING_4(str, i+12)\n\n#define MACRO_NAMED_SCRIPT(nameString, type) ScriptGroupNamedParser<type, MACRO_GET_STRING_16(nameString, 0), MACRO_GET_STRING_16(nameString, 16), MACRO_GET_STRING_16(nameString, 32)>\n\n} //namespace OpenXcom\n"
  },
  {
    "path": "src/Engine/ScriptBind.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2015 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Script.h\"\n#include \"Exception.h\"\n#include \"Logger.h\"\n#include <functional>\n#include <utility>\n\nnamespace OpenXcom\n{\n\n\n/**\n * Hack needed by Clang 6.0 to properly transfer `auto` template parameters,\n * This need be macro because GCC 7.4 fail on this hack,\n * VS look it could handle both cases\n */\n#ifdef __clang__\ntemplate<auto T>\nstatic constexpr decltype(T) _clang_auto_hack()\n{\n\treturn T;\n}\n#define MACRO_CLANG_AUTO_HACK(T) _clang_auto_hack<T>()\n#else\n#define MACRO_CLANG_AUTO_HACK(T) T\n#endif\n\n\n/**\n * Type of code block\n */\nenum BlockEnum\n{\n\t/// Block that represents whole body of script\n\tBlockMain,\n\t/// Normal block\n\tBlockBegin,\n\t/// Conditional block\n\tBlockIf,\n\t/// Else block of conditional block\n\tBlockElse,\n\t/// Iteraion block\n\tBlockLoop,\n};\n\n/**\n * Size in bytes of operation id\n */\nconstexpr size_t ProcOpSize = sizeof(Uint8);\n\n/**\n * Helper structure used by ScriptParser::parse\n */\nstruct ParserWriter\n{\n\tstruct Block\n\t{\n\t\tBlockEnum type;\n\t\tsize_t regStackSizeFrom;\n\t\tRegEnum regIndexUsedFrom;\n\t\tScriptRefData nextLabel = { };\n\t\tScriptRefData finalLabel = { };\n\t};\n\n\ttemplate<typename T, typename = typename std::enable_if_t<std::is_pod<T>::value>>\n\tclass ReservedPos\n\t{\n\t\tProgPos _pos;\n\t\tReservedPos(ProgPos pos) : _pos{ pos }\n\t\t{\n\n\t\t}\n\t\tProgPos getPos()\n\t\t{\n\t\t\treturn _pos;\n\t\t}\n\n\t\tfriend struct ParserWriter;\n\t};\n\n\t/// Tag type representing position script operation id in proc vector.\n\tclass ProcOp { };\n\n\t/// List of all places in proc vector where we need have same values\n\ttemplate<typename T, typename CompType = T>\n\tclass ReservedCrossRefrenece\n\t{\n\t\tenum Ref : std::size_t { };\n\n\t\t/// list of places of usage.\n\t\tstd::vector<std::pair<ReservedPos<T>, Ref>> positions;\n\t\t/// list of final values.\n\t\tstd::vector<CompType> values;\n\tpublic:\n\n\t\tReservedCrossRefrenece() {}\n\n\t\tScriptValueData addValue(CompType defaultValue)\n\t\t{\n\t\t\tauto index = static_cast<Ref>(values.size());\n\t\t\tvalues.push_back(defaultValue);\n\t\t\treturn index;\n\t\t}\n\n\t\tCompType getValue(ScriptValueData data)\n\t\t{\n\t\t\tauto index = data.getValue<Ref>();\n\t\t\treturn values[index];\n\t\t}\n\n\t\tvoid setValue(ScriptValueData data, CompType value)\n\t\t{\n\t\t\tauto index = data.getValue<Ref>();\n\t\t\tvalues[index] = value;\n\t\t}\n\n\t\tvoid pushPosition(ParserWriter& pw, ScriptValueData data)\n\t\t{\n\t\t\tauto index = data.getValue<Ref>();\n\t\t\tpositions.push_back(std::make_pair(pw.pushReserved<T>(), index));\n\t\t}\n\n\t\ttemplate<typename Func>\n\t\tvoid forEachPosition(Func&& f)\n\t\t{\n\t\t\tfor (const auto& pos : positions)\n\t\t\t{\n\t\t\t\tf(pos.first, values[static_cast<std::size_t>(pos.second)]);\n\t\t\t}\n\t\t}\n\t};\n\n\t/// member pointer accessing script operations.\n\tScriptContainerBase& container;\n\t/// all available data for script.\n\tconst ScriptParserBase& parser;\n\t/// list of labels.\n\tReservedCrossRefrenece<ProgPos> refLabels;\n\t/// list of texts.\n\tReservedCrossRefrenece<ScriptText, ScriptRef> refTexts;\n\n\t/// index of used script registers.\n\tRegEnum regIndexUsed;\n\n\t/// Stack of registers limited to code blocks.\n\tstd::vector<ScriptRefData> regStack;\n\t/// Store position of blocks of code like \"if\" or \"while\".\n\tstd::vector<Block> codeBlocks;\n\n\n\n\t/// Constructor.\n\tParserWriter(\n\t\t\tsize_t regUsed,\n\t\t\tScriptContainerBase& c,\n\t\t\tconst ScriptParserBase& d);\n\n\t/// Final fixes of data.\n\tvoid relese();\n\n\t/// Get reference based on name.\n\tScriptRefData getReferece(const ScriptRef& s) const;\n\n\t/// Get current position in proc vector.\n\tProgPos getCurrPos() const;\n\t/// Get distance between two positions in proc vector.\n\tsize_t getDiffPos(ProgPos begin, ProgPos end) const;\n\n\n\t/// Push zeros to fill empty space.\n\tProgPos push(size_t s);\n\t/// Update space on proc vector.\n\tvoid update(ProgPos pos, void* data, size_t s);\n\n\t/// Preparing place and position on proc vector for some value and return position of it.\n\ttemplate<typename T>\n\tReservedPos<T> pushReserved()\n\t{\n\t\treturn { ParserWriter::push(sizeof(T)) };\n\t}\n\t/// Setting previously prepared place with value.\n\ttemplate<typename T>\n\tvoid updateReserved(ReservedPos<T> pos, T value)\n\t{\n\t\tupdate(pos.getPos(), &value, sizeof(T));\n\t}\n\n\n\t/// Push custom value on proc vector.\n\tvoid pushValue(ScriptValueData v);\n\n\t/// Pushing proc operation id on proc vector.\n\tReservedPos<ProcOp> pushProc(Uint8 procId);\n\n\t/// Updating previously added proc operation id.\n\tvoid updateProc(ReservedPos<ProcOp> pos, int procOffset);\n\n\t/// Try pushing label arg on proc vector. Can't use this to create loop back label.\n\tbool pushLabelTry(const ScriptRefData& data);\n\n\t/// Create new label for proc vector.\n\tScriptRefData addLabel(const ScriptRef& data = {});\n\n\t/// Setting offset of label on proc vector.\n\tbool setLabel(const ScriptRefData& data, ProgPos offset);\n\n\t/// Try pushing text literal arg on proc vector.\n\tbool pushTextTry(const ScriptRefData& data);\n\n\t/// Try pushing reg arg on proc vector.\n\ttemplate<typename T>\n\tbool pushConstTry(const ScriptRefData& data)\n\t{\n\t\treturn pushConstTry(data, ScriptParserBase::getArgType<T>());\n\t}\n\n\t/// Try pushing data arg on proc vector.\n\tbool pushConstTry(const ScriptRefData& data, ArgEnum type);\n\n\t/// Try pushing reg arg on proc vector.\n\ttemplate<typename T>\n\tbool pushRegTry(const ScriptRefData& data)\n\t{\n\t\treturn pushRegTry(data, ScriptParserBase::getArgType<T>());\n\t}\n\n\t/// Try pushing reg arg on proc vector.\n\tbool pushRegTry(const ScriptRefData& data, ArgEnum type);\n\n\t/// Add new reg arg.\n\ttemplate<typename T>\n\tScriptRefData addReg(const ScriptRef& s)\n\t{\n\t\treturn addReg(s, ScriptParserBase::getArgType<T>());\n\t}\n\n\t/// Add new reg arg.\n\tScriptRefData addReg(const ScriptRef& s, ArgEnum type);\n\n\t/// Add new local const.\n\tScriptRefData addConst(const ScriptRef& s, ArgEnum type, ScriptValueData value);\n\n\n\n\t/// Add new code scope.\n\tBlock& pushScopeBlock(BlockEnum type);\n\t/// Clear values in code scope.\n\tBlock& clearScopeBlock();\n\t/// Pop code scope.\n\tBlock popScopeBlock();\n\n\n\n\t/// Dump to log error info about ref.\n\tvoid logDump(const ScriptRefData&) const;\n\n}; //struct ParserWriter\n\n\n////////////////////////////////////////////////////////////\n//\t\t\t\tMata helper classes\n////////////////////////////////////////////////////////////\n\nnamespace helper\n{\n\ntemplate<typename T, int P>\nusing GetType = decltype(T::typeFunc(PosTag<P>{}));\n\n\ntemplate<int MaxSize, typename... T>\nstruct SumListIndexImpl;\n\ntemplate<int MaxSize, typename T1, typename... T>\nstruct SumListIndexImpl<MaxSize, T1, T...> : SumListIndexImpl<MaxSize, T...>\n{\n\tusing tag = PosTag<MaxSize - (1 + sizeof...(T))>;\n\n\tusing SumListIndexImpl<MaxSize, T...>::typeFunc;\n\tstatic T1 typeFunc(tag);\n\n\tstatic constexpr ScriptFunc getDynamic(int i)\n\t{\n\t\treturn tag::value == i ? T1::funcDynamic : SumListIndexImpl<MaxSize, T...>::getDynamic(i);\n\t}\n};\n\ntemplate<int MaxSize>\nstruct SumListIndexImpl<MaxSize>\n{\n\tstruct End\n\t{\n\t\tstatic constexpr int offset = 0;\n\n\t\t[[gnu::always_inline]]\n\t\tstatic RetEnum funcDynamic(ScriptWorkerBase &, const Uint8 *, ProgPos &)\n\t\t{\n\t\t\treturn RetError;\n\t\t}\n\n\t\t[[gnu::always_inline]]\n\t\tstatic void funcDirect(ScriptWorkerBase &, const Uint8 *, ProgPos& curr)\n\t\t{\n\t\t\tcurr = static_cast<ProgPos>(RetError);\n\t\t}\n\t};\n\tstatic End typeFunc(...);\n\tstatic constexpr ScriptFunc getDynamic(int i)\n\t{\n\t\treturn End::funcDynamic;\n\t}\n};\n\ntemplate<typename... V>\nstruct SumList : SumListIndexImpl<sizeof...(V), V...>\n{\n\tstatic constexpr size_t size = sizeof...(V);\n\n\tusing SumListIndexImpl<sizeof...(V), V...>::typeFunc;\n\tusing SumListIndexImpl<sizeof...(V), V...>::getDynamic;\n\n\ttemplate<typename... F2>\n\tconstexpr SumList<V..., F2...> operator+(SumList<F2...>) const { return {}; }\n\tconstexpr SumList<V...> operator+() const { return {}; }\n};\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\t\tArg class\n////////////////////////////////////////////////////////////\n\ntemplate<typename... A>\nstruct Arg;\n\ntemplate<typename A1, typename... A2>\nstruct Arg<A1, A2...> : public Arg<A2...>\n{\n\tusing next = Arg<A2...>;\n\tusing tag = PosTag<sizeof...(A2)>;\n\n\tstatic constexpr int offset(int i)\n\t{\n\t\treturn i == tag::value ? A1::size : next::offset(i);\n\t}\n\tstatic constexpr int ver()\n\t{\n\t\treturn tag::value + 1;\n\t}\n\n\tusing next::typeFunc;\n\tstatic A1 typeFunc(tag);\n\n\tstatic int parse(ParserWriter& ph, const ScriptRefData* t)\n\t{\n\t\tif (A1::parse(ph, *t))\n\t\t{\n\t\t\treturn tag::value;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn next::parse(ph, t);\n\t\t}\n\t}\n\tstatic int parse(ParserWriter& ph, const ScriptRefData** begin, const ScriptRefData* end)\n\t{\n\t\tif (*begin == end)\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"Not enough args in operation\";\n\t\t\treturn -1;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tint curr = parse(ph, *begin);\n\t\t\tif (curr < 0)\n\t\t\t{\n\t\t\t\tph.logDump(**begin);\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t\t++*begin;\n\t\t\treturn curr;\n\t\t}\n\t}\n\ttemplate<typename A>\n\tstatic ArgEnum typeHelper()\n\t{\n\t\treturn A::type();\n\t}\n\tstatic ScriptRange<ArgEnum> argTypes()\n\t{\n\t\tenum\n\t\t{\n\t\t\tver_temp = ver()\n\t\t};\n\t\tconst static ArgEnum types[ver_temp] = { typeHelper<A1>(), typeHelper<A2>()... };\n\t\treturn { std::begin(types), std::end(types) };\n\t}\n};\n\ntemplate<>\nstruct Arg<>\n{\n\tstatic constexpr int offset(int i)\n\t{\n\t\treturn 0;\n\t}\n\tstatic constexpr int ver() = delete;\n\tstatic void typeFunc() = delete;\n\n\tstatic int parse(ParserWriter& ph, const ScriptRefData* begin)\n\t{\n\t\treturn -1;\n\t}\n\tstatic ScriptRange<ArgEnum> argTypes()\n\t{\n\t\treturn { };\n\t}\n};\n\ntemplate<typename T>\nstruct ArgInternal\n{\n\tusing tag = PosTag<0>;\n\n\tstatic constexpr int offset(int i)\n\t{\n\t\treturn 0;\n\t}\n\tstatic constexpr int ver()\n\t{\n\t\treturn 1;\n\t};\n\n\tstatic T typeFunc(tag);\n\n\tstatic int parse(ParserWriter& ph, const ScriptRefData** begin, const ScriptRefData* end)\n\t{\n\t\treturn 0;\n\t}\n\tstatic ScriptRange<ArgEnum> argTypes()\n\t{\n\t\treturn { };\n\t}\n};\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tArgColection class\n////////////////////////////////////////////////////////////\n\ntemplate<int MaxSize, typename... T>\nstruct ArgColection;\n\ntemplate<int MaxSize, typename T1, typename... T2>\nstruct ArgColection<MaxSize, T1, T2...> : public ArgColection<MaxSize, T2...>\n{\n\tusing next = ArgColection<MaxSize, T2...>;\n\tusing tag = PosTag<MaxSize - (sizeof...(T2) + 1)>;\n\n\tstatic constexpr int pos(int ver, int pos)\n\t{\n\t\treturn (pos == tag::value ? ver % T1::ver() : next::pos(ver / T1::ver(), pos));\n\t}\n\tstatic constexpr int offset(int ver, int pos)\n\t{\n\t\treturn (pos > tag::value ? T1::offset(ver % T1::ver()) : 0) + next::offset(ver / T1::ver(), pos);\n\t}\n\tstatic constexpr int ver()\n\t{\n\t\treturn T1::ver() * next::ver();\n\t}\n\tstatic constexpr int arg()\n\t{\n\t\treturn MaxSize;\n\t}\n\tstatic int parse(ParserWriter& ph, const ScriptRefData* begin, const ScriptRefData* end)\n\t{\n\t\tint curr = T1::parse(ph, &begin, end);\n\t\tif (curr < 0)\n\t\t{\n\t\t\treturn -1;\n\t\t}\n\t\tint lower = next::parse(ph, begin, end);\n\t\tif (lower < 0)\n\t\t{\n\t\t\treturn -1;\n\t\t}\n\t\treturn lower * T1::ver() + curr;\n\t}\n\ttemplate<typename T>\n\tstatic ScriptRange<ArgEnum> argHelper()\n\t{\n\t\treturn T::argTypes();\n\t}\n\tstatic ScriptRange<ScriptRange<ArgEnum>> overloadType()\n\t{\n\t\tconst static ScriptRange<ArgEnum> types[MaxSize] =\n\t\t{\n\t\t\targHelper<T1>(),\n\t\t\targHelper<T2>()...,\n\t\t};\n\t\treturn { std::begin(types), std::end(types) };\n\t}\n\n\tusing next::typeFunc;\n\tstatic T1 typeFunc(tag);\n};\n\ntemplate<int MaxSize>\nstruct ArgColection<MaxSize>\n{\n\tusing tag = PosTag<-1>;\n\n\tstatic constexpr int pos(int ver, int pos)\n\t{\n\t\treturn 0;\n\t}\n\tstatic constexpr int offset(int ver, int pos)\n\t{\n\t\treturn 0;\n\t}\n\tstatic constexpr int ver()\n\t{\n\t\treturn 1;\n\t}\n\tstatic constexpr int arg()\n\t{\n\t\treturn 0;\n\t}\n\tstatic int parse(ParserWriter& ph, const ScriptRefData* begin, const ScriptRefData* end)\n\t{\n\t\t//we should have used all available tokens.\n\t\tif (begin == end)\n\t\t{\n\t\t\treturn 0;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"Too many args in operation\";\n\t\t\treturn -1;\n\t\t}\n\t}\n\tstatic ScriptRange<ScriptRange<ArgEnum>> overloadType()\n\t{\n\t\treturn { };\n\t}\n\tstatic void typeFunc() = delete;\n};\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\t\tArguments implementation\n////////////////////////////////////////////////////////////\n\nstruct ArgContextDef : ArgInternal<ArgContextDef>\n{\n\tusing ReturnType = ScriptWorkerBase&;\n\tstatic constexpr size_t size = 0;\n\tstatic ReturnType get(ScriptWorkerBase& sw, const Uint8* arg, ProgPos& curr)\n\t{\n\t\treturn sw;\n\t}\n};\n\nstruct ArgProgDef : ArgInternal<ArgProgDef>\n{\n\tusing ReturnType = ProgPos&;\n\tstatic constexpr size_t size = 0;\n\tstatic ReturnType get(ScriptWorkerBase& sw, const Uint8* arg, ProgPos& curr)\n\t{\n\t\treturn curr;\n\t}\n};\n\ntemplate<typename T>\nstruct ArgRegDef\n{\n\tusing ReturnType = T;\n\tstatic constexpr size_t size = sizeof(RegEnum);\n\tstatic ReturnType get(ScriptWorkerBase& sw, const Uint8* arg, ProgPos& curr)\n\t{\n\t\treturn sw.ref<ReturnType>(sw.const_val<RegEnum>(arg));\n\t}\n\n\tstatic bool parse(ParserWriter& ph, const ScriptRefData& t)\n\t{\n\t\treturn ph.pushRegTry<ReturnType>(t);\n\t}\n\n\tstatic ArgEnum type()\n\t{\n\t\treturn ArgSpecAdd(ScriptParserBase::getArgType<ReturnType>(), ArgSpecReg);\n\t}\n};\ntemplate<typename T>\nstruct ArgValueDef\n{\n\tusing ReturnType = T;\n\tstatic constexpr size_t size = sizeof(T);\n\tstatic ReturnType get(ScriptWorkerBase& sw, const Uint8* arg, ProgPos& curr)\n\t{\n\t\treturn sw.const_val<ReturnType>(arg);\n\t}\n\n\tstatic bool parse(ParserWriter& ph, const ScriptRefData& t)\n\t{\n\t\treturn ph.pushConstTry<ReturnType>(t);\n\t}\n\n\tstatic ArgEnum type()\n\t{\n\t\treturn ScriptParserBase::getArgType<ReturnType>();\n\t}\n};\n\nstruct ArgLabelDef\n{\n\tusing ReturnType = ProgPos;\n\tstatic constexpr size_t size = sizeof(ReturnType);\n\tstatic ReturnType get(ScriptWorkerBase& sw, const Uint8* arg, ProgPos& curr)\n\t{\n\t\treturn sw.const_val<ReturnType>(arg);\n\t}\n\n\tstatic bool parse(ParserWriter& ph, const ScriptRefData& t)\n\t{\n\t\treturn ph.pushLabelTry(t);\n\t}\n\n\tstatic ArgEnum type()\n\t{\n\t\treturn ArgLabel;\n\t}\n};\n\nstruct ArgTextDef\n{\n\tusing ReturnType = ScriptText;\n\tstatic constexpr size_t size = sizeof(ReturnType);\n\tstatic ReturnType get(ScriptWorkerBase& sw, const Uint8* arg, ProgPos& curr)\n\t{\n\t\treturn sw.const_val<ReturnType>(arg);\n\t}\n\n\tstatic bool parse(ParserWriter& ph, const ScriptRefData& t)\n\t{\n\t\treturn ph.pushTextTry(t);\n\t}\n\n\tstatic ArgEnum type()\n\t{\n\t\treturn ArgText;\n\t}\n};\n\nstruct ArgFuncDef\n{\n\tusing ReturnType = ScriptFunc;\n\tstatic constexpr size_t size = sizeof(ReturnType);\n\tstatic ReturnType get(ScriptWorkerBase& sw, const Uint8* arg, ProgPos& curr)\n\t{\n\t\treturn sw.const_val<ReturnType>(arg);\n\t}\n\n\tstatic bool parse(ParserWriter& ph, const ScriptRefData& t)\n\t{\n\t\treturn false;\n\t}\n\n\tstatic ArgEnum type()\n\t{\n\t\treturn ArgInvalid;\n\t}\n};\n\ntemplate<int Size>\nstruct ArgRawDef\n{\n\tusing ReturnType = const Uint8*;\n\tstatic constexpr size_t size = Size;\n\tstatic ReturnType get(ScriptWorkerBase& sw, const Uint8* arg, ProgPos& curr)\n\t{\n\t\treturn arg;\n\t}\n\n\tstatic bool parse(ParserWriter& ph, const ScriptRefData& t)\n\t{\n\t\treturn false;\n\t}\n\n\tstatic ArgEnum type()\n\t{\n\t\treturn ArgInvalid;\n\t}\n};\n\ntemplate<typename T>\nstruct ArgNullDef\n{\n\tusing ReturnType = T;\n\tstatic constexpr size_t size = 0;\n\tstatic ReturnType get(ScriptWorkerBase& sw, const Uint8* arg, ProgPos& curr)\n\t{\n\t\treturn ReturnType{};\n\t}\n\n\tstatic bool parse(ParserWriter& ph, const ScriptRefData& t)\n\t{\n\t\treturn t.type == ArgNull;\n\t}\n\n\tstatic ArgEnum type()\n\t{\n\t\treturn ArgNull;\n\t}\n};\n\nstruct ArgSepDef\n{\n\tusing ReturnType = ScriptArgSeparator;\n\tstatic constexpr size_t size = 0;\n\tstatic ReturnType get(ScriptWorkerBase& sw, const Uint8* arg, ProgPos& curr)\n\t{\n\t\treturn ReturnType{};\n\t}\n\n\tstatic bool parse(ParserWriter& ph, const ScriptRefData& t)\n\t{\n\t\treturn t.type == ArgSep;\n\t}\n\n\tstatic ArgEnum type()\n\t{\n\t\treturn ArgSep;\n\t}\n};\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tArgSelector class\n////////////////////////////////////////////////////////////\n\n\n\ntemplate<typename T>\nstruct ArgSelector\n{\n\tusing type = Arg<ArgRegDef<T>, ArgValueDef<T>>;\n};\n\ntemplate<typename T>\nstruct ArgSelector<T&>\n{\n\tusing type = Arg<ArgRegDef<T&>>;\n};\n\ntemplate<typename T>\nstruct ArgSelector<const T&>\n{\n\tusing type = Arg<ArgRegDef<T>, ArgValueDef<T>>;\n};\n\n\n\ntemplate<>\nstruct ArgSelector<ScriptWorkerBase&>\n{\n\tusing type = ArgContextDef;\n};\n\n\n\ntemplate<>\nstruct ArgSelector<ScriptInt&>\n{\n\tusing type = Arg<ArgRegDef<ScriptInt&>>;\n};\n\ntemplate<>\nstruct ArgSelector<ScriptInt>\n{\n\tusing type = Arg<ArgValueDef<ScriptInt>, ArgRegDef<ScriptInt>>;\n};\n\ntemplate<>\nstruct ArgSelector<const ScriptInt&> : ArgSelector<ScriptInt>\n{\n\n};\n\ntemplate<>\nstruct ArgSelector<bool>\n{\n\tusing type = Arg<ArgValueDef<ScriptInt>, ArgRegDef<ScriptInt>>;\n};\n\n\n\ntemplate<>\nstruct ArgSelector<ScriptText&>\n{\n\tusing type = Arg<ArgRegDef<ScriptText&>>;\n};\n\ntemplate<>\nstruct ArgSelector<ScriptText>\n{\n\tusing type = Arg<ArgTextDef, ArgRegDef<ScriptText>>;\n};\n\ntemplate<>\nstruct ArgSelector<const std::string&>\n{\n\tusing type = Arg<ArgTextDef, ArgRegDef<ScriptText>>;\n};\n\n\n\ntemplate<typename T, typename I>\nstruct ArgSelector<ScriptTag<T, I>>\n{\n\tusing type = Arg<ArgValueDef<ScriptTag<T, I>>, ArgRegDef<ScriptTag<T, I>>, ArgNullDef<ScriptTag<T, I>>>;\n};\n\ntemplate<typename T, typename I>\nstruct ArgSelector<ScriptTag<T, I>&>\n{\n\tusing type = Arg<ArgRegDef<ScriptTag<T, I>&>>;\n};\n\ntemplate<typename T, typename I>\nstruct ArgSelector<const ScriptTag<T, I>&> : ArgSelector<ScriptTag<T, I>>\n{\n\n};\n\n\n\n\ntemplate<>\nstruct ArgSelector<ProgPos&>\n{\n\tusing type = ArgProgDef;\n};\n\ntemplate<>\nstruct ArgSelector<ProgPos>\n{\n\tusing type = Arg<ArgLabelDef>;\n};\n\n\n\n\ntemplate<>\nstruct ArgSelector<ScriptFunc>\n{\n\tusing type = Arg<ArgFuncDef>;\n};\n\n\ntemplate<>\nstruct ArgSelector<const Uint8*>\n{\n\tusing type = Arg<ArgRawDef<64>, ArgRawDef<32>, ArgRawDef<16>, ArgRawDef<8>, ArgRawDef<4>, ArgRawDef<0>>;\n};\n\n\ntemplate<typename T>\nstruct ArgSelector<T*>\n{\n\tusing type = Arg<ArgRegDef<T*>, ArgValueDef<T*>, ArgNullDef<T*>>;\n};\n\ntemplate<typename T>\nstruct ArgSelector<T*&>\n{\n\tusing type = Arg<ArgRegDef<T*&>>;\n};\n\ntemplate<typename T>\nstruct ArgSelector<const T*>\n{\n\tusing type = Arg<ArgRegDef<const T*>, ArgValueDef<const T*>, ArgNullDef<const T*>>;\n};\n\ntemplate<typename T>\nstruct ArgSelector<const T*&>\n{\n\tusing type = Arg<ArgRegDef<const T*&>>;\n};\n\n\ntemplate<>\nstruct ArgSelector<ScriptNull>\n{\n\tusing type = Arg<ArgNullDef<ScriptNull>>;\n};\n\ntemplate<>\nstruct ArgSelector<ScriptArgSeparator>\n{\n\tusing type = Arg<ArgSepDef>;\n};\n\n\n\ntemplate<typename T>\nstruct GetArgsImpl;\n\ntemplate<typename... Args>\nstruct GetArgsImpl<RetEnum(Args...)>\n{\n\tusing type = ArgColection<sizeof...(Args), typename ArgSelector<Args>::type...>;\n};\n\ntemplate<typename Func>\nusing GetArgs = typename GetArgsImpl<decltype(Func::func)>::type;\n\n////////////////////////////////////////////////////////////\n//\t\t\t\tFuncVer and FuncGroup class\n////////////////////////////////////////////////////////////\n\ntemplate<typename Func, int Ver, typename PosList = MakeListTag<GetArgs<Func>::arg()>>\nstruct FuncVer;\n\ntemplate<typename Func, int Ver, int... Pos>\nstruct FuncVer<Func, Ver, ListTag<Pos...>>\n{\n\tusing Args = GetArgs<Func>;\n\tstatic constexpr int offset = Args::offset(Ver, Args::arg());\n\n\ttemplate<int CurrPos>\n\tusing GetTypeAt = GetType<GetType<Args, CurrPos>, Args::pos(Ver, CurrPos)>;\n\n\ttemplate<int CurrPos>\n\t[[gnu::always_inline]]\n\tstatic typename GetTypeAt<CurrPos>::ReturnType getArgForDynamic(ScriptWorkerBase& sw, const Uint8* procArgs, ProgPos& curr)\n\t{\n\t\tconstexpr int offs = Args::offset(Ver, CurrPos);\n\t\treturn GetTypeAt<CurrPos>::get(sw, procArgs + offs, curr);\n\t}\n\n\ttemplate<int CurrPos>\n\t[[gnu::always_inline]]\n\tstatic typename GetTypeAt<CurrPos>::ReturnType getArgForDirect(ScriptWorkerBase& sw, const Uint8* procArgs, ProgPos& curr)\n\t{\n\t\tconstexpr int offs = Args::offset(Ver, CurrPos) + ProcOpSize;\n\t\treturn GetTypeAt<CurrPos>::get(sw, procArgs + offs, curr);\n\t}\n\n\t[[gnu::always_inline]]\n\tstatic RetEnum funcDynamic(ScriptWorkerBase& sw, const Uint8* procArgs, ProgPos& curr)\n\t{\n\t\treturn Func::func(getArgForDynamic<Pos>(sw, procArgs, curr)...);\n\t}\n\n\t[[gnu::always_inline]]\n\tstatic void funcDirect(ScriptWorkerBase& sw, const Uint8* procArgs, ProgPos& curr)\n\t{\n\t\tconst RetEnum ret = Func::func(getArgForDirect<Pos>(sw, procArgs, curr)...);\n\t\tif (ret != RetEnum::RetContinue)\n\t\t{\n\t\t\tcurr = static_cast<ProgPos>(ret);\n\t\t}\n\t}\n};\n\ntemplate<typename Func, typename VerList = MakeListTag<GetArgs<Func>::ver()>>\nstruct FuncGroup;\n\ntemplate<typename Func, int... Ver>\nstruct FuncGroup<Func, ListTag<Ver...>> : GetArgs<Func>\n{\n\tusing FuncList = SumList<FuncVer<Func, Ver>...>;\n\tusing GetArgs<Func>::ver;\n\tusing GetArgs<Func>::arg;\n\tusing GetArgs<Func>::parse;\n\tusing GetArgs<Func>::overloadType;\n\n\tstatic constexpr ScriptFunc getDynamic(int i) { return FuncList::getDynamic(i); }\n};\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tBind helper classes\n////////////////////////////////////////////////////////////\n\ntemplate<auto F>\nstruct WarpValue\n{\n\t/// Default case, not normal pointer, pass without change\n\ttemplate<typename T>\n\tstatic auto optDeref(T t) { return t; }\n\n\t/// We have normal pointer, dereference it to get value\n\ttemplate<typename T>\n\tstatic auto optDeref(T* t) -> T& { return *t; }\n\n\t/// Get value from template parameter\n\tconstexpr static auto val() { return optDeref(F); }\n\n\t/// Type of returned value\n\tusing Type = decltype(val());\n};\n\ntemplate<typename Ptr, typename... Rest>\nstruct BindMemberInvokeImpl //Work araound ICC 19.0.1 bug\n{\n\ttemplate<typename T, typename... TRest>\n\tstatic auto f(T&& a, TRest&&... b) -> decltype(auto)\n\t{\n\t\tif constexpr (sizeof...(Rest) > 0)\n\t\t{\n\t\t\treturn BindMemberInvokeImpl<Rest...>::f(\n\t\t\t\tstd::invoke(Ptr::val(), std::forward<T>(a), std::forward<TRest>(b)...)\n\t\t\t);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn std::invoke(Ptr::val(), std::forward<T>(a), std::forward<TRest>(b)...);\n\t\t}\n\t}\n};\n\ntemplate<auto... Rest>\nstruct BindMemberInvoke : BindMemberInvokeImpl<WarpValue<Rest>...>\n{\n\n};\n\ntemplate<typename T, auto... Rest>\nusing BindMemberFinalType = std::decay_t<decltype(BindMemberInvoke<Rest...>::f(std::declval<T>()))>;\n\n\n\n\ntemplate<typename T>\nstruct BindMemberOverrideUnsuportedTypeImpl\n{\n\tusing Type = T;\n};\n\ntemplate<>\nstruct BindMemberOverrideUnsuportedTypeImpl<bool>\n{\n\tusing Type = int;\n};\n\ntemplate<>\nstruct BindMemberOverrideUnsuportedTypeImpl<Uint8>\n{\n\tusing Type = int;\n};\n\ntemplate<>\nstruct BindMemberOverrideUnsuportedTypeImpl<Sint8>\n{\n\tusing Type = int;\n};\n\ntemplate<>\nstruct BindMemberOverrideUnsuportedTypeImpl<Uint16>\n{\n\tusing Type = int;\n};\n\ntemplate<>\nstruct BindMemberOverrideUnsuportedTypeImpl<Sint16>\n{\n\tusing Type = int;\n};\n\ntemplate<typename T>\nusing BindMemberOverrideUnsuportedType = typename BindMemberOverrideUnsuportedTypeImpl<T>::Type;\n\n\n\n\ntemplate<typename T, typename... Args>\nstruct BindConstructor\n{\n\tstatic RetEnum func(T& t, Args... args)\n\t{\n\t\tt = T{ std::forward<Args>(args)... };\n\t\treturn RetContinue;\n\t}\n};\n\ntemplate<typename T>\nstruct BindSet\n{\n\tstatic RetEnum func(T& t, T r)\n\t{\n\t\tt = r;\n\t\treturn RetContinue;\n\t}\n};\ntemplate<typename T>\nstruct BindSwap\n{\n\tstatic RetEnum func(T& t, T& r)\n\t{\n\t\tstd::swap(t, r);\n\t\treturn RetContinue;\n\t}\n};\ntemplate<typename T>\nstruct BindEq\n{\n\tstatic RetEnum func(ProgPos& Prog, T t1, T t2, ProgPos LabelTrue, ProgPos LabelFalse)\n\t{\n\t\tProg = (t1 == t2) ? LabelTrue : LabelFalse;\n\t\treturn RetContinue;\n\t}\n};\ntemplate<typename T>\nstruct BindClear\n{\n\tstatic RetEnum func(T& t)\n\t{\n\t\tt = T{};\n\t\treturn RetContinue;\n\t}\n};\n\n\ntemplate<typename T, auto... X>\nstruct BindPropGet\n{\n\tstatic RetEnum func(const T* t, BindMemberOverrideUnsuportedType<BindMemberFinalType<T, X...>>& p)\n\t{\n\t\tif (t) p = BindMemberInvoke<X...>::f(t); else p = {};\n\t\treturn RetContinue;\n\t}\n};\ntemplate<typename T, auto... X>\nstruct BindPropSet\n{\n\tstatic RetEnum func(T* t, BindMemberOverrideUnsuportedType<BindMemberFinalType<T, X...>> p)\n\t{\n\t\tif (t) BindMemberInvoke<X...>::f(t) = p;\n\t\treturn RetContinue;\n\t}\n};\ntemplate<typename T, auto... X>\nstruct BindPropAdd\n{\n\tstatic RetEnum func(T* t, BindMemberOverrideUnsuportedType<BindMemberFinalType<T, X...>> p)\n\t{\n\t\tif (t) BindMemberInvoke<X...>::f(t) += p;\n\t\treturn RetContinue;\n\t}\n};\n\n\ntemplate<typename T, auto... X>\nstruct BindValuePropGet\n{\n\tstatic RetEnum func(T t, BindMemberOverrideUnsuportedType<BindMemberFinalType<T, X...>>& p)\n\t{\n\t\tp = BindMemberInvoke<X...>::f(&t);\n\t\treturn RetContinue;\n\t}\n};\ntemplate<typename T, auto... X>\nstruct BindValuePropSet\n{\n\tstatic RetEnum func(T& t, BindMemberOverrideUnsuportedType<BindMemberFinalType<T, X...>> p)\n\t{\n\t\tBindMemberInvoke<X...>::f(&t) = p;\n\t\treturn RetContinue;\n\t}\n};\ntemplate<typename T, auto... X>\nstruct BindValuePropAdd\n{\n\tstatic RetEnum func(T& t, BindMemberOverrideUnsuportedType<BindMemberFinalType<T, X...>> p)\n\t{\n\t\tBindMemberInvoke<X...>::f(&t) += p;\n\t\treturn RetContinue;\n\t}\n};\n\n\ntemplate<typename T, auto... X>\nstruct BindPropCustomGet\n{\n\tstatic RetEnum func(const T* t, int& p, typename BindMemberFinalType<T, X...>::Tag st)\n\t{\n\t\tif (t) p = BindMemberInvoke<X...>::f(t).get(st); else p = int{};\n\t\treturn RetContinue;\n\t}\n};\ntemplate<typename T, auto... X>\nstruct BindPropCustomSet\n{\n\tstatic RetEnum func(T* t, typename BindMemberFinalType<T, X...>::Tag st, int p)\n\t{\n\t\tif (t) BindMemberInvoke<X...>::f(t).set(st, p);\n\t\treturn RetContinue;\n\t}\n};\n\ntemplate<typename T, typename P, P I>\nstruct BindConst\n{\n\tstatic RetEnum func(T* t, P& p)\n\t{\n\t\tif (t) p = I; else p = P{};\n\t\treturn RetContinue;\n\t}\n};\n\n\n\n\ntemplate<typename T, std::string (*X)(const T*)>\nstruct BindDebugDisplay\n{\n\tstatic RetEnum func(ScriptWorkerBase& swb, const T* t)\n\t{\n\t\tauto f = std::bind(X, t);\n\t\tswb.log_buffer_add(&f);\n\t\treturn RetContinue;\n\t}\n};\n\ntemplate<typename T, std::string (*X)(const T*)>\nstruct BindValueDebugDisplay\n{\n\tstatic RetEnum func(ScriptWorkerBase& swb, T t)\n\t{\n\t\tauto f = std::bind(X, &t);\n\t\tswb.log_buffer_add(&f);\n\t\treturn RetContinue;\n\t}\n};\n\n\n\n\ntemplate<typename T, T X>\nstruct BindFuncImpl;\n\ntemplate<typename... Args, void(*X)(Args...)>\nstruct BindFuncImpl<void(*)(Args...), X>\n{\n\tstatic RetEnum func(Args... a)\n\t{\n\t\tX(std::forward<Args>(a)...);\n\t\treturn RetContinue;\n\t}\n};\n\ntemplate<typename T, typename... Args, bool(T::*X)(Args...)>\nstruct BindFuncImpl<bool(T::*)(Args...), X>\n{\n\tstatic RetEnum func(T* t, int& r, Args... a)\n\t{\n\t\tif (t) r = (t->*X)(std::forward<Args>(a)...); else r = 0;\n\t\treturn RetContinue;\n\t}\n};\n\ntemplate<typename T, typename... Args, bool(T::*X)(Args...) const>\nstruct BindFuncImpl<bool(T::*)(Args...) const, X>\n{\n\tstatic RetEnum func(const T* t, int& r, Args... a)\n\t{\n\t\tif (t) r = (t->*X)(std::forward<Args>(a)...); else r = 0;\n\t\treturn RetContinue;\n\t}\n};\n\ntemplate<typename T, typename R, typename... Args, R(T::*X)(Args...)>\nstruct BindFuncImpl<R(T::*)(Args...), X>\n{\n\tstatic RetEnum func(T* t, R& r, Args... a)\n\t{\n\t\tif (t) r = (t->*X)(std::forward<Args>(a)...); else r = {};\n\t\treturn RetContinue;\n\t}\n};\n\ntemplate<typename T, typename R, typename... Args, R(T::*X)(Args...) const>\nstruct BindFuncImpl<R(T::*)(Args...) const, X>\n{\n\tstatic RetEnum func(const T* t, R& r, Args... a)\n\t{\n\t\tif (t) r = (t->*X)(std::forward<Args>(a)...); else r = {};\n\t\treturn RetContinue;\n\t}\n};\n\ntemplate<typename T, typename P, typename... Args, P*(T::*X)(Args...)>\nstruct BindFuncImpl<P*(T::*)(Args...), X>\n{\n\tstatic RetEnum func(T* t, P*& r, Args... a)\n\t{\n\t\tif (t) r = (t->*X)(std::forward<Args>(a)...); else r = {};\n\t\treturn RetContinue;\n\t}\n};\n\ntemplate<typename T, typename P, typename... Args, P*(T::*X)(Args...) const>\nstruct BindFuncImpl<P*(T::*)(Args...) const, X>\n{\n\tstatic RetEnum func(const T* t, const P*& r, Args... a)\n\t{\n\t\tif (t) r = (t->*X)(std::forward<Args>(a)...); else r = {};\n\t\treturn RetContinue;\n\t}\n};\n\ntemplate<typename T, typename... Args, void(T::*X)(Args...)>\nstruct BindFuncImpl<void(T::*)(Args...), X>\n{\n\tstatic RetEnum func(T* t, Args... a)\n\t{\n\t\tif (t) (t->*X)(std::forward<Args>(a)...);\n\t\treturn RetContinue;\n\t}\n};\n\ntemplate<auto F>\nstruct BindFunc : BindFuncImpl<decltype(F), F> //Work araound ICC 19.0.1 bug\n{\n\n};\n\n\ntemplate<typename T, auto Func, auto... X>\nstruct BindListInitImpl\n{\n\tstatic RetEnum func() = delete;\n};\n\ntemplate<typename T, typename V, typename... Args, auto... X, bool (*Func)(T*, V* v, Args...)>\nstruct BindListInitImpl<bool (*)(T*, V* v, Args...), Func, X...>\n{\n\tstatic RetEnum func(T* t, Args... args, ScriptArgSeparator, int& curr, int& limit)\n\t{\n\t\tif (t)\n\t\t{\n\t\t\tauto& obj = BindMemberInvoke<X...>::f(t);\n\t\t\tcurr = 0;\n\t\t\tlimit = std::size(obj);\n\t\t\tfor (auto* u : obj)\n\t\t\t{\n\t\t\t\tif (Func(t, u, std::forward<Args>(args)...))\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t++curr;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tcurr = 0;\n\t\t\tlimit = 0;\n\t\t}\n\t\treturn RetContinue;\n\t}\n};\ntemplate<auto Func, auto... X>\nstruct BindListInit : BindListInitImpl<decltype(Func), Func, X...>\n{\n\n};\n\ntemplate<typename T, auto Func, auto... X>\nstruct BindListLoopImpl\n{\n\tstatic RetEnum func() = delete;\n};\n\ntemplate<typename T, typename V, typename... Args, auto... X, bool (*Func)(T*, V* v, Args...)>\nstruct BindListLoopImpl<bool (*)(T*, V* v, Args...), Func, X...>\n{\n\tstatic RetEnum func(T* t, Args... args, ScriptArgSeparator, int& curr, int& limit, ScriptArgSeparator, V*& r)\n\t{\n\t\tif (t)\n\t\t{\n\t\t\tauto& obj = BindMemberInvoke<X...>::f(t);\n\t\t\tsize_t l = std::size(obj);\n\t\t\tif ((size_t)curr < l)\n\t\t\t{\n\t\t\t\tr = obj[curr];\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tr = nullptr;\n\t\t\t}\n\t\t\t++curr;\n\t\t\tfor (;(size_t)curr < l; ++curr)\n\t\t\t{\n\t\t\t\tif (Func(t, obj[curr], std::forward<Args>(args)...))\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tr = nullptr;\n\t\t\tcurr = 0;\n\t\t\tlimit = 0;\n\t\t}\n\t\treturn RetContinue;\n\t}\n};\n\ntemplate<auto Func, auto... X>\nstruct BindListLoop : BindListLoopImpl<decltype(Func), Func, X...>\n{\n\n};\n\n\n\n\ntemplate<typename T, T X>\nstruct BindValueFuncImpl;\n\ntemplate<typename... Args, void(*X)(Args...)>\nstruct BindValueFuncImpl<void(*)(Args...), X>\n{\n\tstatic RetEnum func(Args... a)\n\t{\n\t\tX(std::forward<Args>(a)...);\n\t\treturn RetContinue;\n\t}\n};\n\ntemplate<typename T, typename... Args, bool(T::*X)(Args...)>\nstruct BindValueFuncImpl<bool(T::*)(Args...), X>\n{\n\tstatic RetEnum func(T& t, int& r, Args... a)\n\t{\n\t\tr = (t.*X)(std::forward<Args>(a)...);\n\t\treturn RetContinue;\n\t}\n};\n\ntemplate<typename T, typename... Args, bool(T::*X)(Args...) const>\nstruct BindValueFuncImpl<bool(T::*)(Args...) const, X>\n{\n\tstatic RetEnum func(T t, int& r, Args... a)\n\t{\n\t\tr = (t.*X)(std::forward<Args>(a)...);\n\t\treturn RetContinue;\n\t}\n};\n\ntemplate<typename T, typename R, typename... Args, R(T::*X)(Args...)>\nstruct BindValueFuncImpl<R(T::*)(Args...), X>\n{\n\tstatic RetEnum func(T& t, R& r, Args... a)\n\t{\n\t\tr = (t.*X)(std::forward<Args>(a)...);\n\t\treturn RetContinue;\n\t}\n};\n\ntemplate<typename T, typename R, typename... Args, R(T::*X)(Args...) const>\nstruct BindValueFuncImpl<R(T::*)(Args...) const, X>\n{\n\tstatic RetEnum func(T t, R& r, Args... a)\n\t{\n\t\tr = (t.*X)(std::forward<Args>(a)...);\n\t\treturn RetContinue;\n\t}\n};\n\ntemplate<typename T, typename P, typename... Args, P*(T::*X)(Args...)>\nstruct BindValueFuncImpl<P*(T::*)(Args...), X>\n{\n\t/// Value should not return any pointers, this would allow dangling pointers\n\tstatic RetEnum func(T& t, P*& r, Args... a) = delete;\n};\n\ntemplate<typename T, typename P, typename... Args, P*(T::*X)(Args...) const>\nstruct BindValueFuncImpl<P*(T::*)(Args...) const, X>\n{\n\t/// Value should not return any pointers, this would allow dangling pointers\n\tstatic RetEnum func(T t, const P*& r, Args... a) = delete;\n};\n\ntemplate<typename T, typename... Args, void(T::*X)(Args...)>\nstruct BindValueFuncImpl<void(T::*)(Args...), X>\n{\n\tstatic RetEnum func(T& t, Args... a)\n\t{\n\t\t(t.*X)(std::forward<Args>(a)...);\n\t\treturn RetContinue;\n\t}\n};\n\ntemplate<auto F>\nstruct BindValueFunc : BindValueFuncImpl<decltype(F), F> //Work araound ICC 19.0.1 bug\n{\n\n};\n\n} //namespace helper\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\t\tBind class\n////////////////////////////////////////////////////////////\n\nstruct BindBase\n{\n\tconstexpr static const char functionWithoutDescription[] = \"-\";\n\tconstexpr static const char functionInvisible[] = \"\";\n\n\t/// Tag type to choose allowed operations\n\tstruct SetAndGet{};\n\t/// Tag type to choose allowed operations\n\tstruct OnlyGet{};\n\t/// Tag type to skip adding default operations\n\tstruct ExtensionBinding{ explicit ExtensionBinding() = default; };\n\n\tScriptParserBase* parser;\n\tBindBase(ScriptParserBase* p) : parser{ p }\n\t{\n\n\t}\n\n\ttemplate<typename X>\n\tvoid addCustomFunc(const std::string& name, const std::string& description = functionWithoutDescription)\n\t{\n\t\tparser->addParser<helper::FuncGroup<X>>(name, description);\n\t}\n\tvoid addCustomConst(const std::string& name, int i)\n\t{\n\t\tparser->addConst(name, i);\n\t}\n\ttemplate<typename T>\n\tvoid addCustomPtr(const std::string& name, T* p)\n\t{\n\t\tparser->addConst(name, p);\n\t}\n};\n\ntemplate<typename T>\nstruct Bind : BindBase\n{\n\tusing Type = T;\n\n\tstd::string prefix;\n\n\tBind(ScriptParserBase* p) : Bind{ p, T::ScriptName }\n\t{\n\n\t}\n\n\tBind(ScriptParserBase* p, ExtensionBinding e) : Bind{ p, T::ScriptName, e }\n\t{\n\n\t}\n\n\tBind(ScriptParserBase* p, std::string r) : BindBase{ p }, prefix{ std::move(r) }\n\t{\n\t\tparser->addParser<helper::FuncGroup<helper::BindSet<T*>>>(\"set\", BindBase::functionInvisible);\n\t\tparser->addParser<helper::FuncGroup<helper::BindSet<const T*>>>(\"set\", BindBase::functionInvisible);\n\t\tparser->addParser<helper::FuncGroup<helper::BindSwap<T*>>>(\"swap\", BindBase::functionInvisible);\n\t\tparser->addParser<helper::FuncGroup<helper::BindSwap<const T*>>>(\"swap\", BindBase::functionInvisible);\n\t\tparser->addParser<helper::FuncGroup<helper::BindClear<T*>>>(\"clear\", BindBase::functionInvisible);\n\t\tparser->addParser<helper::FuncGroup<helper::BindClear<const T*>>>(\"clear\", BindBase::functionInvisible);\n\t\tparser->addParser<helper::FuncGroup<helper::BindEq<const T*>>>(\"test_eq\", BindBase::functionInvisible);\n\t}\n\n\tBind(ScriptParserBase* p, std::string r, ExtensionBinding) : BindBase{ p }, prefix{ std::move(r) }\n\t{\n\t\t// no default operations defined!\n\t}\n\n\n\tstd::string getName(const std::string& s)\n\t{\n\t\treturn prefix + \".\" + s;\n\t}\n\n\n\ttemplate<typename X>\n\tvoid addFunc(const std::string& name)\n\t{\n\t\taddCustomFunc<X>(getName(name));\n\t}\n\ttemplate<typename X>\n\tvoid addFunc(const std::string& name, const std::string& description)\n\t{\n\t\taddCustomFunc<X>(getName(name), description);\n\t}\n\n\n\ttemplate<auto MemPtr0, auto... MemPtrR>\n\tvoid addField(const std::string& getFuncName)\n\t{\n\t\taddCustomFunc<helper::BindPropGet<T, MACRO_CLANG_AUTO_HACK(MemPtr0), MACRO_CLANG_AUTO_HACK(MemPtrR)...>>(getName(getFuncName), \"Get field of \" + prefix);\n\t}\n\ttemplate<auto MemPtr0, auto... MemPtrR>\n\tvoid addField(const std::string& getFuncName, const std::string& setFuncName)\n\t{\n\t\taddField<MemPtr0, MemPtrR...>(getFuncName);\n\t\taddCustomFunc<helper::BindPropSet<T, MACRO_CLANG_AUTO_HACK(MemPtr0), MACRO_CLANG_AUTO_HACK(MemPtrR)...>>(getName(setFuncName), \"Set field of \" + prefix);\n\t}\n\ttemplate<auto MemPtr0, auto... MemPtrR>\n\tvoid addField(const std::string& getFuncName, const std::string& setFuncName, const std::string& addFuncName)\n\t{\n\t\taddField<MemPtr0, MemPtrR...>(getFuncName, setFuncName);\n\t\taddCustomFunc<helper::BindPropAdd<T, MACRO_CLANG_AUTO_HACK(MemPtr0), MACRO_CLANG_AUTO_HACK(MemPtrR)...>>(getName(addFuncName), \"Add to field of \" + prefix);\n\t}\n\n\n\ttemplate<typename TagValues = ScriptValues<T>, typename Parent = typename TagValues::Parent*>\n\tvoid addScriptTag()\n\t{\n\t\tusing Tag = typename TagValues::Tag;\n\t\tparser->getGlobal()->addTagType<Tag>();\n\t\tif (!parser->haveType<Tag>())\n\t\t{\n\t\t\tconst ScriptTypeData* conf = parser->getType(ScriptParserBase::getArgType<Parent>());\n\t\t\tif (conf == nullptr)\n\t\t\t{\n\t\t\t\tthrow Exception(\"Errow with adding script tag to unknown type\");\n\t\t\t}\n\t\t\tparser->addType<Tag>(conf->name.toString() + \".Tag\");\n\t\t\tparser->addParser<helper::FuncGroup<helper::BindSet<Tag>>>(\"set\", BindBase::functionInvisible);\n\t\t\tparser->addParser<helper::FuncGroup<helper::BindSwap<Tag>>>(\"swap\", BindBase::functionInvisible);\n\t\t\tparser->addParser<helper::FuncGroup<helper::BindClear<Tag>>>(\"clear\", BindBase::functionInvisible);\n\t\t\tparser->addParser<helper::FuncGroup<helper::BindEq<Tag>>>(\"test_eq\", BindBase::functionInvisible);\n\t\t}\n\t}\n\ttemplate<auto MemPtr0, auto... MemPtrR>\n\tvoid addScriptValue()\n\t{\n\t\treturn addScriptValue<BindBase::SetAndGet, MemPtr0, MemPtrR...>();\n\t}\n\ttemplate<typename canEdit, auto MemPtr0, auto... MemPtrR>\n\tvoid addScriptValue()\n\t{\n\t\tusing TagValues = helper::BindMemberFinalType<T, MACRO_CLANG_AUTO_HACK(MemPtr0), MACRO_CLANG_AUTO_HACK(MemPtrR)...>;\n\t\taddScriptTag<TagValues>();\n\t\taddCustomFunc<helper::BindPropCustomGet<T, MACRO_CLANG_AUTO_HACK(MemPtr0), MACRO_CLANG_AUTO_HACK(MemPtrR)...>>(getName(\"getTag\"), \"Get tag of \" + prefix);\n\t\tif constexpr (std::is_same_v<canEdit, BindBase::SetAndGet>)\n\t\t{\n\t\t\taddCustomFunc<helper::BindPropCustomSet<T, MACRO_CLANG_AUTO_HACK(MemPtr0), MACRO_CLANG_AUTO_HACK(MemPtrR)...>>(getName(\"setTag\"), \"Set tag of \" + prefix);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tstatic_assert(std::is_same_v<canEdit, BindBase::OnlyGet>, \"You can only use OnlyGet or SetAndGet types\");\n\t\t}\n\t}\n\n\ttemplate<std::string (*X)(const T*)>\n\tvoid addDebugDisplay()\n\t{\n\t\taddCustomFunc<helper::BindDebugDisplay<T, X>>(\"debug_impl\", BindBase::functionInvisible);\n\t}\n\n\ttemplate<auto X>\n\tvoid addFreeFunction(const std::string& func, const std::string& description = BindBase::functionWithoutDescription)\n\t{\n\t\taddCustomFunc<helper::BindFunc<MACRO_CLANG_AUTO_HACK(X)>>(func, description);\n\t}\n\n\ttemplate<int X>\n\tvoid addFake(const std::string& get)\n\t{\n\t\taddCustomFunc<helper::BindConst<T, int, X>>(getName(get), \"Get int field of \" + prefix);\n\t}\n\n\ttemplate<typename P, P* (T::*X)(), const P* (T::*Y)() const>\n\tvoid addPair(const std::string& get)\n\t{\n\t\tadd<X>(get);\n\t\tadd<Y>(get);\n\t}\n\ttemplate<typename P, void (*X)(T*, P*&), void (*Y)(const T*, const P*&)>\n\tvoid addPair(const std::string& get)\n\t{\n\t\tadd<X>(get);\n\t\tadd<Y>(get);\n\t}\n\n\ttemplate<typename P, const P* (T::*Y)() const>\n\tvoid addRules(const std::string& get)\n\t{\n\t\tadd<Y>(get);\n\t}\n\n\ttemplate<auto Func, auto... MemPtrR>\n\tvoid addList(const std::string& name, const std::string& description = BindBase::functionWithoutDescription)\n\t{\n\t\taddCustomFunc<helper::BindListInit<MACRO_CLANG_AUTO_HACK(Func), MACRO_CLANG_AUTO_HACK(MemPtrR)...>>(getName(name) + \".init\", BindBase::functionInvisible);\n\t\taddCustomFunc<helper::BindListLoop<MACRO_CLANG_AUTO_HACK(Func), MACRO_CLANG_AUTO_HACK(MemPtrR)...>>(getName(name) + \".list\", description);\n\t}\n\n\ttemplate<auto X>\n\tvoid add(const std::string& func, const std::string& description = BindBase::functionWithoutDescription)\n\t{\n\t\taddCustomFunc<helper::BindFunc<MACRO_CLANG_AUTO_HACK(X)>>(getName(func), description);\n\t}\n\ttemplate<typename TX, TX X>\n\tvoid add(const std::string& func, const std::string& description = BindBase::functionWithoutDescription)\n\t{\n\t\taddCustomFunc<helper::BindFunc<MACRO_CLANG_AUTO_HACK(X)>>(getName(func), description);\n\t}\n\ttemplate<auto MemPtr0, auto MemPtr1, auto... MemPtrR>\n\tvoid add(const std::string& func, const std::string& description = BindBase::functionWithoutDescription)\n\t{\n\t\taddCustomFunc<helper::BindPropGet<T, MACRO_CLANG_AUTO_HACK(MemPtr0), MACRO_CLANG_AUTO_HACK(MemPtr1), MACRO_CLANG_AUTO_HACK(MemPtrR)...>>(getName(func), description);\n\t}\n};\n\ntemplate<typename T>\nstruct BindValue : BindBase\n{\n\tusing Type = T;\n\n\tstd::string prefix;\n\n\tBindValue(ScriptParserBase* p) : BindValue{ p, T::ScriptName }\n\t{\n\n\t}\n\n\tBindValue(ScriptParserBase* p, ExtensionBinding e) : BindValue{ p, T::ScriptName, e }\n\t{\n\n\t}\n\n\tBindValue(ScriptParserBase* p, std::string r) : BindBase{ p }, prefix{ std::move(r) }\n\t{\n\t\tparser->addParser<helper::FuncGroup<helper::BindSet<T>>>(\"set\", BindBase::functionInvisible);\n\t\tparser->addParser<helper::FuncGroup<helper::BindSwap<T>>>(\"swap\", BindBase::functionInvisible);\n\t\tparser->addParser<helper::FuncGroup<helper::BindClear<T>>>(\"clear\", BindBase::functionInvisible);\n\n\t\tparser->addParser<helper::FuncGroup<helper::BindEq<T>>>(\"test_eq\", BindBase::functionInvisible);\n\t}\n\n\tBindValue(ScriptParserBase* p, std::string r, ExtensionBinding) : BindBase{ p }, prefix{ std::move(r) }\n\t{\n\t\t// no default operations defined!\n\t}\n\n\n\tstd::string getName(const std::string& s)\n\t{\n\t\treturn prefix + \".\" + s;\n\t}\n\n\n\ttemplate<typename X>\n\tvoid addFunc(const std::string& name)\n\t{\n\t\taddCustomFunc<X>(getName(name));\n\t}\n\ttemplate<typename X>\n\tvoid addFunc(const std::string& name, const std::string& description)\n\t{\n\t\taddCustomFunc<X>(getName(name), description);\n\t}\n\n\n\ttemplate<auto MemPtr0, auto... MemPtrR>\n\tvoid addField(const std::string& getFuncName)\n\t{\n\t\taddCustomFunc<helper::BindValuePropGet<T, MACRO_CLANG_AUTO_HACK(MemPtr0), MACRO_CLANG_AUTO_HACK(MemPtrR)...>>(getName(getFuncName), \"Get field of \" + prefix);\n\t}\n\ttemplate<auto MemPtr0, auto... MemPtrR>\n\tvoid addField(const std::string& getFuncName, const std::string& setFuncName)\n\t{\n\t\taddField<MemPtr0, MemPtrR...>(getFuncName);\n\t\taddCustomFunc<helper::BindValuePropSet<T, MACRO_CLANG_AUTO_HACK(MemPtr0),  MACRO_CLANG_AUTO_HACK(MemPtrR)...>>(getName(setFuncName), \"Set field of \" + prefix);\n\t}\n\ttemplate<auto MemPtr0, auto... MemPtrR>\n\tvoid addField(const std::string& getFuncName, const std::string& setFuncName, const std::string& addFuncName)\n\t{\n\t\taddField<MemPtr0, MemPtrR...>(getFuncName, setFuncName);\n\t\taddCustomFunc<helper::BindValuePropAdd<T, MACRO_CLANG_AUTO_HACK(MemPtr0), MACRO_CLANG_AUTO_HACK(MemPtrR)...>>(getName(addFuncName), \"Add to field of \" + prefix);\n\t}\n\n\n\ttemplate<std::string (*X)(const T*)>\n\tvoid addDebugValueDisplay()\n\t{\n\t\taddCustomFunc<helper::BindValueDebugDisplay<T, X>>(\"debug_impl\", BindBase::functionInvisible);\n\t}\n\n\ttemplate<auto X>\n\tvoid addFreeFunction(const std::string& func, const std::string& description = BindBase::functionWithoutDescription)\n\t{\n\t\taddCustomFunc<helper::BindValueFunc<MACRO_CLANG_AUTO_HACK(X)>>(func, description);\n\t}\n\n\ttemplate<auto X>\n\tvoid add(const std::string& func, const std::string& description = BindBase::functionWithoutDescription)\n\t{\n\t\taddCustomFunc<helper::BindValueFunc<MACRO_CLANG_AUTO_HACK(X)>>(getName(func), description);\n\t}\n\ttemplate<typename TX, TX X>\n\tvoid add(const std::string& func, const std::string& description = BindBase::functionWithoutDescription)\n\t{\n\t\taddCustomFunc<helper::BindValueFunc<MACRO_CLANG_AUTO_HACK(X)>>(getName(func), description);\n\t}\n\n\ttemplate<typename... Args>\n\tvoid addConstructor(const std::string& description = BindBase::functionWithoutDescription)\n\t{\n\t\taddCustomFunc<helper::BindConstructor<T, Args...>>(\"set\", description);\n\t}\n};\n\n} //namespace OpenXcom\n"
  },
  {
    "path": "src/Engine/ShaderDraw.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ShaderDrawHelper.h\"\n#include <tuple>\n\nnamespace OpenXcom\n{\n\ntemplate<typename First, typename... Rest>\nstatic inline First&& GetFirst(First&& f, Rest&&... r)\n{\n\treturn std::forward<First>(f);\n}\n\n/**\n * Universal blit function implementation.\n * @param f called function.\n * @param src source surfaces control objects.\n */\ntemplate<typename Func, typename... SrcType>\nstatic inline void ShaderDrawImpl(Func&& f, helper::controler<SrcType>... src)\n{\n\t//get basic draw range in 2d space\n\tGraphSubset end_temp = GetFirst(src...).get_range();\n\n\t//intersections with src ranges\n\t(src.mod_range(end_temp), ...);\n\n\tconst GraphSubset end = end_temp;\n\tif (!end)\n\t\treturn;\n\n\t//set final draw range in 2d space\n\t(src.set_range(end), ...);\n\n\n\tint begin_y = 0, end_y = end.size_y();\n\n\t//determining iteration range in y-axis\n\t(src.mod_y(begin_y, end_y), ...);\n\n\tif(begin_y>=end_y)\n\t\treturn;\n\n\t//set final iteration range\n\t(src.set_y(begin_y, end_y), ...);\n\n\t//iteration on y-axis\n\tfor (int y = end_y-begin_y; y>0; --y, (src.inc_y(), ...))\n\t{\n\t\tint begin_x = 0, end_x = end.size_x();\n\n\t\t//determining iteration range in x-axis\n\t\t(src.mod_x(begin_x, end_x), ...);\n\n\t\tif (begin_x>=end_x)\n\t\t\tcontinue;\n\n\t\t//set final iteration range\n\t\t(src.set_x(begin_x, end_x), ...);\n\n\t\tint size_x = end_x-begin_x;\n\t\t//iteration on x-axis\n\t\tfor (int x = size_x / 4; x>0; --x)\n\t\t{\n\t\t\tf(src.get_ref()...); (src.inc_x(), ...);\n\t\t\tf(src.get_ref()...); (src.inc_x(), ...);\n\t\t\tf(src.get_ref()...); (src.inc_x(), ...);\n\t\t\tf(src.get_ref()...); (src.inc_x(), ...);\n\t\t}\n\t\tif (size_x & 2)\n\t\t{\n\t\t\tf(src.get_ref()...); (src.inc_x(), ...);\n\t\t\tf(src.get_ref()...); (src.inc_x(), ...);\n\t\t}\n\t\tif (size_x & 1)\n\t\t{\n\t\t\tf(src.get_ref()...); (src.inc_x(), ...);\n\t\t}\n\t}\n\n};\n\n/**\n * Universal blit function.\n * @tparam ColorFunc class that contains static function `func`.\n * function is used to modify these arguments.\n * @param src_frame destination and source surfaces modified by function.\n */\ntemplate<typename ColorFunc, typename... SrcType>\nstatic inline void ShaderDraw(const SrcType&... src_frame)\n{\n\tShaderDrawImpl([](auto&&... a){ ColorFunc::func(std::forward<decltype(a)>(a)...); }, helper::controler<SrcType>(src_frame)...);\n}\n\n/**\n * Universal blit function.\n * @param f function that modify other arguments.\n * @param src_frame destination and source surfaces modified by function.\n */\ntemplate<typename Func, typename... SrcType>\nstatic inline void ShaderDrawFunc(Func&& f, const SrcType&... src_frame)\n{\n\tShaderDrawImpl(std::forward<Func>(f), helper::controler<SrcType>(src_frame)...);\n}\n\nnamespace helper\n{\n\nconst Uint8 ColorGroup = 0xF0;\nconst Uint8 ColorShade = 0x0F;\n\n/**\n * help class used for Surface::blitNShade\n */\nstruct ColorReplace\n{\n\t/**\n\t* Function used by ShaderDraw in Surface::blitNShade\n\t* set shade and replace color in that surface\n\t* @param dest destination pixel\n\t* @param src source pixel\n\t* @param shade value of shade of this surface\n\t* @param newColor new color to set (it should be offset by 4)\n\t*/\n\tstatic inline void func(Uint8& dest, const Uint8& src, const int& shade, const int& newColor)\n\t{\n#ifdef OXCE_VECTORIZATION_FRIENDLY\n\t\t//more vectorization friendly code\n\t\tauto n = dest;\n\t\tif (src)\n\t\t{\n\t\t\tconst Uint8 newShade = (src & ColorShade) + shade;\n\t\t\tif (newShade & ColorGroup)\n\t\t\t\t// so dark it would flip over to another color - make it black instead\n\t\t\t\tn = ColorShade;\n\t\t\telse\n\t\t\t\tn = newColor | newShade;\n\t\t}\n\t\tdest = n;\n#else\n\t\tif (src)\n\t\t{\n\t\t\tconst Uint8 newShade = (src & ColorShade) + shade;\n\t\t\tif (newShade & ColorGroup)\n\t\t\t\t// so dark it would flip over to another color - make it black instead\n\t\t\t\tdest = ColorShade;\n\t\t\telse\n\t\t\t\tdest = newColor | newShade;\n\t\t}\n#endif\n\t}\n\n};\n\n/**\n * help class used for Surface::blitNShade\n */\nstruct StandardShade\n{\n\t/**\n\t* Function used by ShaderDraw in Surface::blitNShade\n\t* set shade\n\t* @param dest destination pixel\n\t* @param src source pixel\n\t* @param shade value of shade of this surface\n\t* @param not used\n\t* @param not used\n\t*/\n\tstatic inline void func(Uint8& dest, const Uint8& src, const int& shade)\n\t{\n#ifdef OXCE_VECTORIZATION_FRIENDLY\n\t\t//more vectorization friendly code\n\t\tauto n = dest;\n\t\tif (src)\n\t\t{\n\t\t\tconst Uint8 newShade = src + shade;\n\t\t\tif ((newShade ^ src) & ColorGroup)\n\t\t\t\t// so dark it would flip over to another color - make it black instead\n\t\t\t\tn = ColorShade;\n\t\t\telse\n\t\t\t\tn = newShade;\n\t\t}\n\t\tdest = n;\n#else\n\t\tif (src)\n\t\t{\n\t\t\tconst Uint8 newShade = src + shade;\n\t\t\tif ((newShade ^ src) & ColorGroup)\n\t\t\t\t// so dark it would flip over to another color - make it black instead\n\t\t\t\tdest = ColorShade;\n\t\t\telse\n\t\t\t\tdest = newShade;\n\t\t}\n#endif\n\t}\n\n};\n/**\n * helper class used for blitting dying unit with overkill\n */\nstruct BurnShade\n{\n\tstatic inline void func(Uint8& dest, const Uint8& src, const int& burn, const int& shade)\n\t{\n\t\tauto n = dest;\n\t\tif (src)\n\t\t{\n\t\t\tif (burn)\n\t\t\t{\n\t\t\t\tconst Uint8 tempBurn = (src & ColorShade) + burn;\n\t\t\t\tif (tempBurn > 26)\n\t\t\t\t{\n\t\t\t\t\t//nothing\n\t\t\t\t}\n\t\t\t\telse if (tempBurn > 15)\n\t\t\t\t{\n\t\t\t\t\tStandardShade::func(n, ColorShade, shade);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tStandardShade::func(n, (src & ColorGroup) + tempBurn, shade);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tStandardShade::func(n, src, shade);\n\t\t\t}\n\t\t}\n\t\tdest = n;\n\t}\n};\n\n}//namespace helper\n\ntemplate<typename T>\nstatic inline helper::Scalar<T> ShaderScalar(T& t)\n{\n\treturn helper::Scalar<T>(t);\n}\ntemplate<typename T>\nstatic inline helper::Scalar<const T> ShaderScalar(const T& t)\n{\n\treturn helper::Scalar<const T>(t);\n}\n\n/**\n * Create warper from vector\n * @param s vector\n * @return\n */\ntemplate<typename Pixel>\ninline helper::ShaderBase<Pixel> ShaderSurface(std::vector<Pixel>& s, int max_x, int max_y)\n{\n\treturn helper::ShaderBase<Pixel>(s, max_x, max_y);\n}\n\n/**\n * Create warper from array\n * @param s array\n * @return\n */\ntemplate<typename Pixel, int Size>\ninline helper::ShaderBase<Pixel> ShaderSurface(Pixel(&s)[Size], int max_x, int max_y)\n{\n\treturn helper::ShaderBase<Pixel>(s, max_x, max_y, max_x*sizeof(Pixel));\n}\n\n}//namespace OpenXcom\n"
  },
  {
    "path": "src/Engine/ShaderDrawHelper.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Surface.h\"\n#include \"GraphSubset.h\"\n\nnamespace OpenXcom\n{\n\nnamespace helper\n{\n\n/***\n * Calculate pointer offset using bytes\n */\ntemplate<typename Ptr>\nPtr* pointerByteOffset(Ptr* base, int offset)\n{\n\treturn reinterpret_cast<Ptr*>(reinterpret_cast<unsigned char*>(base) + offset);\n}\n\n/***\n * Calculate pointer offset using bytes\n */\ntemplate<typename Ptr>\nconst Ptr* pointerByteOffset(const Ptr* base, int offset)\n{\n\treturn reinterpret_cast<const Ptr*>(reinterpret_cast<const unsigned char*>(base) + offset);\n}\n\n/**\n * This is scalar argument to `ShaderDraw`.\n * when used in `ShaderDraw` return value of `t` to `ColorFunc::func` for every pixel\n */\ntemplate<typename T>\nclass Scalar\n{\npublic:\n\tT& ref;\n\tinline Scalar(T& t) : ref(t)\n\t{\n\n\t}\n};\n\n/**\n * 2d offset, return offset of given pixel to some predetermined position in 2d space.\n */\nclass Offset\n{\npublic:\n\tint x;\n\tint y;\n\n\tinline Offset(int xx, int yy) : x(xx), y(yy)\n\t{\n\n\t}\n};\n\n/**\n * This is surface argument to `ShaderDraw`.\n * every pixel of this surface will have type `Pixel`.\n * Modify pixels of this surface, that will modifying original data.\n */\ntemplate<typename Pixel>\nclass ShaderBase\n{\npublic:\n\ttypedef Pixel* PixelPtr;\n\ttypedef Pixel& PixelRef;\n\nprotected:\n\tconst PixelPtr _orgin;\n\tconst GraphSubset _range_base;\n\tGraphSubset _range_domain;\n\tconst int _pitch;\n\npublic:\n\t/// copy constructor\n\tinline ShaderBase(const ShaderBase& s):\n\t\t_orgin(s.ptr()),\n\t\t_range_base(s._range_base),\n\t\t_range_domain(s.getDomain()),\n\t\t_pitch(s.pitch())\n\t{\n\n\t}\n\n\t/// copy constructor\n\ttemplate<typename = std::enable_if<std::is_const<Pixel>::value, void>>\n\tinline ShaderBase(const ShaderBase<typename std::remove_const<Pixel>::type>& s):\n\t\t_orgin(s.ptr()),\n\t\t_range_base(s.getBaseDomain()),\n\t\t_range_domain(s.getDomain()),\n\t\t_pitch(s.pitch())\n\t{\n\n\t}\n\n\t/**\n\t * create surface using raw surface `s` as data source.\n\t * surface will have same dimensions as `s`.\n\t * Attention: after use of this constructor you change size of surface `s`\n\t * then `_orgin` will be invalid and use of this object will cause memory exception.\n     * @param s Raw Surface\n     */\n\tinline ShaderBase(SurfaceRaw<Pixel> s):\n\t\t_orgin(s.getBuffer()),\n\t\t_range_base(s.getWidth(), s.getHeight()),\n\t\t_range_domain(s.getWidth(), s.getHeight()),\n\t\t_pitch(s.getPitch())\n\t{\n\n\t}\n\n\t/// Get pointer to beginning of surface\n\tinline PixelPtr ptr() const\n\t{\n\t\treturn _orgin;\n\t}\n\n\t/// Get real distance between lines in bytes\n\tinline int pitch() const\n\t{\n\t\treturn _pitch;\n\t}\n\n\tinline void setDomain(const GraphSubset& g)\n\t{\n\t\t_range_domain = GraphSubset::intersection(g, _range_base);\n\t}\n\tinline const GraphSubset& getDomain() const\n\t{\n\t\treturn _range_domain;\n\t}\n\tinline const GraphSubset& getBaseDomain() const\n\t{\n\t\treturn _range_base;\n\t}\n\n\tinline const GraphSubset& getImage() const\n\t{\n\t\treturn _range_domain;\n\t}\n};\n\n\n/// helper class for handling implementation differences in different surfaces types\n/// Used in function `ShaderDraw`.\ntemplate<typename SurfaceType>\nstruct controler\n{\n\t//NOT IMPLEMENTED ANYWHERE!\n\t//you need create your own specification or use different type, no default version\n\n\t/**\n\t * function used only when `SurfaceType` can be used as destination surface\n\t * if that type should not be used as `dest` don't implement this.\n\t * @return start drawing range\n\t */\n\tinline const GraphSubset& get_range() = delete;\n\t/**\n\t * function used only when `SurfaceType` is used as source surface.\n\t * function reduce drawing range.\n\t * @param g modify drawing range\n\t */\n\tinline void mod_range(GraphSubset& g) = delete;\n\t/**\n\t * set final drawing range.\n\t * @param g drawing range\n\t */\n\tinline void set_range(const GraphSubset& g) = delete;\n\n\tinline void mod_y(int& begin, int& end) = delete;\n\tinline void set_y(const int& begin, const int& end) = delete;\n\tinline void inc_y() = delete;\n\n\n\tinline void mod_x(int& begin, int& end) = delete;\n\tinline void set_x(const int& begin, const int& end) = delete;\n\tinline void inc_x() = delete;\n\n\tinline int& get_ref() = delete;\n};\n\n/// implementation for scalars types aka `int`, `double`, `float`\ntemplate<typename T>\nstruct controler<Scalar<T> >\n{\n\tT& ref;\n\n\tinline controler(const Scalar<T>& s) : ref(s.ref)\n\t{\n\n\t}\n\n\t//cant use this function\n\t//inline GraphSubset get_range()\n\n\tinline void mod_range(GraphSubset&)\n\t{\n\t\t//nothing\n\t}\n\tinline void set_range(const GraphSubset&)\n\t{\n\t\t//nothing\n\t}\n\n\tinline void mod_y(int&, int&)\n\t{\n\t\t//nothing\n\t}\n\tinline void set_y(const int&, const int&)\n\t{\n\t\t//nothing\n\t}\n\tinline void inc_y()\n\t{\n\t\t//nothing\n\t}\n\n\n\tinline void mod_x(int&, int&)\n\t{\n\t\t//nothing\n\t}\n\tinline void set_x(const int&, const int&)\n\t{\n\t\t//nothing\n\t}\n\tinline void inc_x()\n\t{\n\t\t//nothing\n\t}\n\n\tinline T& get_ref()\n\t{\n\t\treturn ref;\n\t}\n};\n\n/// implementation for offset\ntemplate<>\nstruct controler<Offset>\n{\n\tconst Offset off;\n\tint pos_x;\n\tint pos_y;\n\tint start_x;\n\tint start_y;\n\n\tinline controler(Offset s) : off(s),\n\t\tpos_x(), pos_y(),\n\t\tstart_x(), start_y()\n\t{\n\n\t}\n\n\t//cant use this function\n\t//inline GraphSubset get_range()\n\n\tinline void mod_range(GraphSubset&)\n\t{\n\t\t//nothing\n\t}\n\n\tinline void set_range(const GraphSubset& r)\n\t{\n\t\tstart_x = r.beg_x - off.x;\n\t\tstart_y = r.beg_y - off.y;\n\t}\n\n\tinline void mod_y(int&, int&)\n\t{\n\t\tpos_y = start_y;\n\t}\n\tinline void set_y(const int& begin, const int&)\n\t{\n\t\tpos_y += begin;\n\t}\n\tinline void inc_y()\n\t{\n\t\tpos_y += 1;\n\t}\n\n\n\tinline void mod_x(int&, int&)\n\t{\n\t\tpos_x = start_x;\n\t}\n\tinline void set_x(const int& begin, const int&)\n\t{\n\t\tpos_x += begin;\n\t}\n\tinline void inc_x()\n\t{\n\t\tpos_x += 1;\n\t}\n\n\tinline Offset get_ref()\n\t{\n\t\treturn Offset(pos_x, pos_y);\n\t}\n};\n\ntemplate<typename PixelPtr, typename PixelRef>\nstruct controler_base\n{\n\n\tconst PixelPtr data;\n\tPixelPtr ptr_pos_y;\n\tPixelPtr ptr_pos_x;\n\tGraphSubset range;\n\tint start_x;\n\tint start_y;\n\n\tconst std::pair<int, int> step;\n\n\n\tcontroler_base(PixelPtr base, const GraphSubset& d, const GraphSubset& r, const std::pair<int, int>& s) :\n\t\tdata(pointerByteOffset(base, d.beg_x*s.first + d.beg_y*s.second)),\n\t\tptr_pos_y(0), ptr_pos_x(0),\n\t\trange(r),\n\t\tstart_x(), start_y(),\n\t\tstep(s)\n\t{\n\n\t}\n\n\n\tinline const GraphSubset& get_range()\n\t{\n\t\treturn range;\n\t}\n\n\tinline void mod_range(GraphSubset& r)\n\t{\n\t\tr = GraphSubset::intersection(range, r);\n\t}\n\n\tinline void set_range(const GraphSubset& r)\n\t{\n\t\tstart_x = r.beg_x - range.beg_x;\n\t\tstart_y = r.beg_y - range.beg_y;\n\t\trange = r;\n\t}\n\n\tinline void mod_y(int&, int&)\n\t{\n\t\tptr_pos_y = pointerByteOffset(data, step.first * start_x + step.second * start_y);\n\t}\n\tinline void set_y(const int& begin, const int&)\n\t{\n\t\tptr_pos_y = pointerByteOffset(ptr_pos_y, step.second * begin);\n\t}\n\tinline void inc_y()\n\t{\n\t\tptr_pos_y = pointerByteOffset(ptr_pos_y, step.second);\n\t}\n\n\n\tinline void mod_x(int&, int&)\n\t{\n\t\tptr_pos_x = ptr_pos_y;\n\t}\n\tinline void set_x(const int& begin, const int&)\n\t{\n\t\tptr_pos_x = pointerByteOffset(ptr_pos_x, step.first * begin);\n\t}\n\tinline void inc_x()\n\t{\n\t\tptr_pos_x = pointerByteOffset(ptr_pos_x, step.first);\n\t}\n\n\tinline PixelRef get_ref()\n\t{\n\t\treturn *ptr_pos_x;\n\t}\n};\n\n\n\ntemplate<typename Pixel>\nstruct controler<ShaderBase<Pixel> > : public controler_base<typename ShaderBase<Pixel>::PixelPtr, typename ShaderBase<Pixel>::PixelRef>\n{\n\ttypedef typename ShaderBase<Pixel>::PixelPtr PixelPtr;\n\ttypedef typename ShaderBase<Pixel>::PixelRef PixelRef;\n\n\ttypedef controler_base<PixelPtr, PixelRef> base_type;\n\n\tcontroler(const ShaderBase<Pixel>& f) : base_type(f.ptr(), f.getDomain(), f.getImage(), std::make_pair(sizeof(Pixel), f.pitch()))\n\t{\n\n\t}\n\n};\n\n}//namespace helper\n\n}//namespace OpenXcom\n\n"
  },
  {
    "path": "src/Engine/ShaderMove.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ShaderDraw.h\"\n\nnamespace OpenXcom\n{\n\n\ntemplate<typename Pixel>\nclass ShaderMove : public helper::ShaderBase<Pixel>\n{\n\tint _move_x;\n\tint _move_y;\n\npublic:\n\ttypedef helper::ShaderBase<Pixel> _base;\n\tfriend struct helper::controler<ShaderMove<Pixel> >;\n\n\tinline ShaderMove(SurfaceRaw<Pixel> s):\n\t\t_base(s),\n\t\t_move_x(0), _move_y(0)\n\t{\n\n\t}\n\n\tinline ShaderMove(SurfaceRaw<Pixel> s, int move_x, int move_y):\n\t\t_base(s),\n\t\t_move_x(move_x), _move_y(move_y)\n\t{\n\n\t}\n\n\tinline ShaderMove(const ShaderMove& f):\n\t\t_base(f),\n\t\t_move_x(f._move_x), _move_y(f._move_y)\n\t{\n\n\t}\n\n\tinline GraphSubset getImage() const\n\t{\n\t\treturn _base::_range_domain.offset(_move_x, _move_y);\n\t}\n\n\tinline void setMove(int x, int y)\n\t{\n\t\t_move_x = x;\n\t\t_move_y = y;\n\t}\n\tinline void addMove(int x, int y)\n\t{\n\t\t_move_x += x;\n\t\t_move_y += y;\n\t}\n};\n\n\n\nnamespace helper\n{\n\ntemplate<typename Pixel>\nstruct controler<ShaderMove<Pixel> > : public controler_base<typename ShaderMove<Pixel>::PixelPtr, typename ShaderMove<Pixel>::PixelRef>\n{\n\ttypedef typename ShaderMove<Pixel>::PixelPtr PixelPtr;\n\ttypedef typename ShaderMove<Pixel>::PixelRef PixelRef;\n\n\ttypedef controler_base<PixelPtr, PixelRef> base_type;\n\n\tcontroler(const ShaderMove<Pixel>& f) : base_type(f.ptr(), f.getDomain(), f.getImage(), std::make_pair(sizeof(Pixel), f.pitch()))\n\t{\n\n\t}\n\n};\n\n}//namespace helper\n\n/**\n * Create warper from Surface\n * @param s standard 8bit OpenXcom surface\n * @return\n */\ntemplate<typename T>\ninline ShaderMove<T> ShaderSurface(SurfaceRaw<T> s)\n{\n\treturn ShaderMove<T>(s);\n}\n\n/**\n * Create warper from Surface\n * @param s standard 8bit OpenXcom surface\n * @return\n */\ninline ShaderMove<Uint8> ShaderSurface(SurfaceRaw<Uint8> s)\n{\n\treturn ShaderMove<Uint8>(s);\n}\n\n/**\n * Create warper from Surface and provided offset\n * @param s standard 8bit OpenXcom surface\n * @param x offset on x\n * @param y offset on y\n * @return\n */\ninline ShaderMove<Uint8> ShaderSurface(SurfaceRaw<Uint8> s, int x, int y)\n{\n\treturn ShaderMove<Uint8>(s, x, y);\n}\n\n/**\n * Create warper from cropped Surface and provided offset\n * @param s standard 8bit OpenXcom surface\n * @param x offset on x\n * @param y offset on y\n * @return\n */\ninline ShaderMove<const Uint8> ShaderCrop(SurfaceCrop s, int x, int y)\n{\n\tShaderMove<const Uint8> ret(s.getSurface(), x, y);\n\tSDL_Rect* s_crop = s.getCrop();\n\tif (s_crop->w || s_crop->h)\n\t{\n\t\tGraphSubset crop(std::make_pair(s_crop->x, s_crop->x + s_crop->w), std::make_pair(s_crop->y, s_crop->y + s_crop->h));\n\t\tret.setDomain(crop);\n\t\tret.addMove(-s_crop->x, -s_crop->y);\n\t}\n\treturn ret;\n}\n\n/**\n * Create warper from cropped Surface\n * @param s standard 8bit OpenXcom surface\n * @return\n */\ninline ShaderMove<const Uint8> ShaderCrop(SurfaceCrop s)\n{\n\treturn ShaderCrop(s, s.getX(), s.getY());\n}\n\n}//namespace OpenXcom\n\n"
  },
  {
    "path": "src/Engine/ShaderRepeat.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ShaderDraw.h\"\n\nnamespace OpenXcom\n{\n\n\ntemplate<typename Pixel>\nclass ShaderRepeat : public helper::ShaderBase<const Pixel>\n{\n\tint _off_x;\n\tint _off_y;\n\npublic:\n\ttypedef helper::ShaderBase<const Pixel> _base;\n\tfriend struct helper::controler<ShaderRepeat<Pixel> >;\n\n\tinline ShaderRepeat(SurfaceRaw<Pixel> s):\n\t\t_base(s)\n\t{\n\t\tsetOffset(0, 0);\n\t}\n\n\tinline ShaderRepeat(SurfaceRaw<const Pixel> s):\n\t\t_base(s)\n\t{\n\t\tsetOffset(0, 0);\n\t}\n\n\tinline void setOffset(int x, int y)\n\t{\n\t\t_off_x = x;\n\t\t_off_y = y;\n\t}\n\tinline void addOffset(int x, int y)\n\t{\n\t\t_off_x += x;\n\t\t_off_y += y;\n\t}\n};\n\n\nnamespace helper\n{\n\ntemplate<typename Pixel>\nstruct controler<ShaderRepeat<Pixel> >\n{\n\ttypedef typename ShaderRepeat<Pixel>::PixelPtr PixelPtr;\n\ttypedef typename ShaderRepeat<Pixel>::PixelRef PixelRef;\n\n\tconst PixelPtr _base;\n\n\tconst GraphSubset _range_domain;\n\tGraphSubset _range_image;\n\n\tconst int _off_x;\n\tconst int _off_y;\n\tconst int _size_x;\n\tconst int _size_y;\n\n\n\tint _curr_x;\n\tint _curr_y;\n\n\tconst int _pitch;\n\n\tPixelPtr _ptr_curr_x;\n\tPixelPtr _ptr_curr_y;\n\n\tcontroler(const ShaderRepeat<Pixel>& f) :\n\t\t_base(f.ptr()),\n\t\t_range_domain(f.getDomain()),\n\t\t_range_image(0,0),\n\t\t_off_x(f._off_x),\n\t\t_off_y(f._off_y),\n\t\t_size_x(_range_domain.size_x()),\n\t\t_size_y(_range_domain.size_y()),\n\t\t_curr_x(0),\n\t\t_curr_y(0),\n\t\t_pitch(f.pitch()),\n\t\t_ptr_curr_x(0),\n\t\t_ptr_curr_y(0)\n\t{\n\n\t}\n\n\t//not used\n\t//inline const GraphSubset& get_range()\n\n\tinline void mod_range(GraphSubset&)\n\t{\n\t\t//nothing\n\t}\n\tinline void set_range(const GraphSubset& g)\n\t{\n\t\t_range_image = g;\n\t}\n\n\tinline void mod_y(int&, int&)\n\t{\n\t\t_curr_y = ( _range_image.beg_y - _off_y)%_size_y;\n\t\tif (_curr_y <0)\n\t\t\t_curr_y += _size_y;\n\t\t_ptr_curr_y = _base;\n\t}\n\tinline void set_y(const int& begin, const int&)\n\t{\n\t\t_curr_y = (_curr_y + begin)%_size_y;\n\t\t_ptr_curr_y = pointerByteOffset(_ptr_curr_y, (_range_domain.beg_y + _curr_y) * _pitch);\n\t}\n\tinline void inc_y()\n\t{\n\t\t++_curr_y;\n\t\t_ptr_curr_y = pointerByteOffset(_ptr_curr_y, _pitch);\n\t\tif (_curr_y == _size_y)\n\t\t{\n\t\t\t_curr_y = 0;\n\t\t\t_ptr_curr_y = pointerByteOffset(_ptr_curr_y, -_size_y*_pitch);\n\t\t}\n\t}\n\n\n\tinline void mod_x(int&, int&)\n\t{\n\t\t_curr_x = ( _range_image.beg_x - _off_x)%_size_x;\n\t\tif (_curr_x <0)\n\t\t\t_curr_x += _size_x;\n\t\t_ptr_curr_x = _ptr_curr_y;\n\t}\n\tinline void set_x(const int& begin, const int&)\n\t{\n\t\t_curr_x = (_curr_x + begin)%_size_x;\n\t\t_ptr_curr_x += _range_domain.beg_x +_curr_x;\n\t}\n\tinline void inc_x()\n\t{\n\t\t++_curr_x;\n\t\t_ptr_curr_x += 1;\n\t\tif (_curr_x == _size_x)\n\t\t{\n\t\t\t_curr_x = 0;\n\t\t\t_ptr_curr_x -= _size_x;\n\t\t}\n\t}\n\n\tinline PixelRef get_ref()\n\t{\n\t\treturn *_ptr_curr_x;\n\t}\n};\n\n}//namespace helper\n}//namespace OpenXcom\n\n"
  },
  {
    "path": "src/Engine/Sound.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Sound.h\"\n#include \"Options.h\"\n#include \"Logger.h\"\n#include \"Unicode.h\"\n#include \"FileMap.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Deletes the loaded sound content.\n */\nvoid Sound::UniqueSoundDeleter::operator ()(Mix_Chunk* sound)\n{\n\tMix_FreeChunk(sound);\n}\n\nSound::UniqueSoundPtr Sound::NewSound(Mix_Chunk* sound)\n{\n\treturn Sound::UniqueSoundPtr(sound);\n}\n\n/**\n * Loads a sound file from a specified filename.\n * @param filename Filename of the sound file.\n */\nvoid Sound::load(const std::string &filename) {\n\tauto rw = FileMap::getRWops(filename);\n\tauto s = NewSound(Mix_LoadWAV_RW(rw, SDL_TRUE));\n\tif (!s)\n\t{\n\t\tLog(LOG_ERROR) << \"Sound::load(\" << filename << \"): mix error=\" << Mix_GetError();\n\t}\n\n\t//always overwrite\n\t_sound = std::move(s);\n}\n\n/**\n * Loads a sound file from a specified rwops.\n * @param rw SDL_RWops of the sound data.\n */\nvoid Sound::load(SDL_RWops *rw) {\n\tauto s = NewSound(Mix_LoadWAV_RW(rw, SDL_TRUE));\n\tif (!s)\n\t{\n\t\tLog(LOG_ERROR) << \"Sound::load(data): mix error=\" << Mix_GetError();\n\t}\n\n\t//always overwrite\n\t_sound = std::move(s);\n}\n\n/**\n * Plays the contained sound effect.\n * @param channel Use specified channel, -1 to use any channel\n */\nvoid Sound::play(int channel, int angle, int distance) const\n {\n\tif (!Options::mute && _sound)\n \t{\n\t\tint chan = Mix_PlayChannel(channel, _sound.get(), 0);\n\t\tif (chan == -1)\n\t\t{\n\t\t\tLog(LOG_WARNING) << Mix_GetError();\n\t\t}\n\t\telse if (Options::StereoSound)\n\t\t{\n\t\t\tif (!Mix_SetPosition(chan, angle, distance))\n\t\t\t{\n\t\t\t\tLog(LOG_WARNING) << Mix_GetError();\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Stops all sounds playing.\n */\nvoid Sound::stop()\n{\n\tif (!Options::mute)\n\t{\n\t\tMix_HaltChannel(-1);\n\t}\n}\n\n/**\n * Plays the contained sound effect repeatedly on the reserved ambience channel.\n */\nvoid Sound::loop()\n{\n\tif (!Options::mute && _sound && Mix_Playing(3) == 0)\n\t{\n\t\tint chan = Mix_PlayChannel(3, _sound.get(), -1);\n\t\tif (chan == -1)\n\t\t{\n\t\t\tLog(LOG_WARNING) << Mix_GetError();\n\t\t}\n\t}\n}\n\n/**\n * Stops the contained sound from looping.\n */\nvoid Sound::stopLoop()\n{\n\tif (!Options::mute)\n\t{\n\t\tMix_HaltChannel(3);\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Engine/Sound.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <SDL_rwops.h>\n#include <SDL_mixer.h>\n#include <string>\n#include <memory>\n\nnamespace OpenXcom\n{\n\n/**\n * Container for sound effects.\n * Handles loading and playing various formats through SDL_mixer.\n */\nclass Sound\n{\npublic:\n\tstruct UniqueSoundDeleter\n\t{\n\t\tvoid operator()(Mix_Chunk*);\n\t};\n\n\tusing UniqueSoundPtr = std::unique_ptr<Mix_Chunk, UniqueSoundDeleter>;\n\n\t/// Smart pointer for for Mix_Chunk.\n\tstatic UniqueSoundPtr NewSound(Mix_Chunk* sound);\n\nprivate:\n\tUniqueSoundPtr _sound;\n\npublic:\n\t/// Creates a blank sound effect.\n\tSound() = default;\n\t/// Cleans up the sound effect.\n\t~Sound() = default;\n\t/// Move sound to another place.\n\tSound(Sound&& other) = default;\n\t/// Move assignment\n\tSound& operator=(Sound&& other) = default;\n\n\t/// Loads sound from the specified file.\n\tvoid load(const std::string &filename);\n\t/// Loads sound from SDL_RWops\n\tvoid load(SDL_RWops *rw);\n\t/// Plays the sound.\n\tvoid play(int channel = -1, int angle = 0, int distance = 0) const;\n\t/// Stops all sounds.\n\tstatic void stop();\n\t/// Plays the sound repeatedly.\n\tvoid loop();\n\t/// Stops the looping sound effect.\n\tvoid stopLoop();\n};\n\n}\n"
  },
  {
    "path": "src/Engine/SoundSet.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"SoundSet.h\"\n#include \"CatFile.h\"\n#include \"Sound.h\"\n#include \"Logger.h\"\n#include \"SDL2Helpers.h\"\n#include <climits>\n#include <cassert>\n\nnamespace OpenXcom\n{\n\n/**\n * Sets up a new empty sound set.\n */\nSoundSet::SoundSet() : _sharedSounds(INT_MAX)\n{\n\n}\n\n/**\n * Converts a 8Khz sample to 11Khz.\n * @param oldsound Pointer to original sample buffer.\n * @param oldsize Original buffer size.\n * @param newsound Pointer to converted sample buffer.\n * @return Converted buffer size.\n */\nint SoundSet::convertSampleRate(Uint8 *oldsound, size_t oldsize, Uint8 *newsound) const\n{\n\tconst Uint32 step16 = (8000 << 16) / 11025;\n\tint newsize = 0;\n\tfor (Uint32 offset16 = 0; (offset16 >> 16) < oldsize; offset16 += step16, ++newsound, ++newsize)\n\t{\n\t\t*newsound = oldsound[offset16 >> 16];\n\t}\n\treturn newsize;\n}\n\nstatic const Uint8 header[] = {  'R',  'I',  'F',  'F', 0x00, 0x00, 0x00, 0x00,  'W',  'A',  'V',  'E',\n\t\t\t\t\t\t\t\t 'f',  'm',  't',  ' ', 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,\n\t\t\t\t\t\t\t\t0x11, 0x2b, 0x00, 0x00, 0x11, 0x2b, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00,\n\t\t\t\t\t\t\t\t 'd',  'a',  't',  'a', 0x00, 0x00, 0x00, 0x00                           };\n/**\n * Write out a WAV. Resample if needed.\n * @param dest where to write\n * @param sound sound data\n * @param size  size of sound data\n * @param resample if resampling is needed.\n */\nvoid SoundSet::writeWAV(SDL_RWops *dest, Uint8 *sound, size_t size, bool resample) const {\n\tSDL_RWwrite(dest, header, sizeof(header), 1);\n\tint newsize = size;\n\n\tif (resample) {\n\t\tauto newsound = SDL_malloc(2*size);\n\t\tnewsize = convertSampleRate(sound, size, (Uint8 *)newsound);\n\t\tSDL_RWwrite(dest, newsound, newsize, 1);\n\t\tSDL_free(newsound);\n\t} else {\n\t\tSDL_RWwrite(dest, sound, size, 1);\n\t}\n\n\t// update the header\n\tSDL_RWseek(dest, 4, RW_SEEK_SET);\t// write WAVE chunk size\n\tSDL_WriteLE32(dest, newsize + 36);\n\tSDL_RWseek(dest, 40, RW_SEEK_SET); \t// write data subchunk size\n\tSDL_WriteLE32(dest, newsize);\n}\n\n/**\n * Loads the contents of an X-Com CAT file which usually contains\n * a set of sound files. The CAT starts with an index of the offset\n * and size of every file contained within. Each file consists of a\n * filename followed by its contents.\n * @param rw RWops of the CAT set.\n * @param wav Are the sounds in WAV format?\n * @sa http://www.ufopaedia.org/index.php?title=SOUND\n */\nvoid SoundSet::loadCat(CatFile &catFile)\n{\n\tfor (size_t i = 0; i < catFile.size(); ++i) { loadCatByIndex(catFile, i); }\n}\n\n/**\n * Returns a particular wave from the sound set.\n * @param i Sound number in the set.\n * @return Pointer to the respective sound.\n */\nSound *SoundSet::getSound(int i)\n{\n\tif (_sounds.find(i) != _sounds.end())\n\t{\n\t\treturn &_sounds[i];\n\t}\n\treturn 0;\n}\n\n/**\n * Creates and returns a particular wave in the sound set.\n * @param i Sound number in the set.\n * @return Pointer to the respective sound.\n */\nSound *SoundSet::addSound(int i)\n{\n\tassert(i >= 0 && \"Negative indexes are not supported in SoundSet\");\n\t_sounds[i] = Sound();\n\treturn &_sounds[i];\n}\n\n/**\n * Set number of shared sound indexes that are accessible for all mods.\n */\nvoid SoundSet::setMaxSharedSounds(int i)\n{\n\tif (i >= 0)\n\t{\n\t\t_sharedSounds = i;\n\t}\n\telse\n\t{\n\t\t_sharedSounds = 0;\n\t}\n}\n\n/**\n * Gets number of shared sound indexes that are accessible for all mods.\n */\nint SoundSet::getMaxSharedSounds() const\n{\n\treturn _sharedSounds;\n}\n\n/**\n * Returns the total amount of sounds currently\n * stored in the set.\n * @return Number of sounds.\n */\nsize_t SoundSet::getTotalSounds() const\n{\n\treturn _sounds.size();\n}\n\n/**\n * Loads individual contents of a sound CAT file by index.\n * a set of sound files. The CAT starts with an index of the offset\n * and size of every file contained within. Each file consists of a\n * filename followed by its contents.\n * @param filename Filename of the CAT set.\n * @param index which index in the cat file do we load?\n * @param tftd if to expect signed 8bit 11Khz instead of unsigned 6bit 8KHz in the data.\n *             and also under which ID to put the sound\n * @sa http://www.ufopaedia.org/index.php?title=SOUND\n */\nvoid SoundSet::loadCatByIndex(CatFile &catFile, int index, bool tftd)\n{\n\tint set_index = tftd ? getTotalSounds() : index;\n\t_sounds[set_index] = Sound(); // in case everything else fails, an empty Sound.\n\tauto rwops = catFile.getRWops(index);\n\tif (!rwops) {\n\t\tLog(LOG_VERBOSE) << \"SoundSet::loadCatByIndex(\" << catFile.fileName() << \", \" << index << \"): got NULL.\";\n\t\treturn;\n\t}\n\tint namesize = SDL_ReadU8(rwops);\n\tSDL_RWseek(rwops, namesize, RW_SEEK_CUR); // skip \"name\".\n\t// NB: the original code after ce548c29d5742e26a442a44ef2a5fcce3f80dace\n\t// did not adjust the size for the namesize byte when skipping the name\n\t// and thus submitted one trailing byte of garbage.\n\t// The original code before that commit did not adjust the size at all\n\t// when skipping the name and thus submitted at least one trailing byte of garbage.\n\t// v1.4 sounds do miss namesize+1 bytes as they are in the catfile -\n\t// comparing what's in the WAV header to cat item size without name.\n\n\tsize_t size;\n\tUint8 *sound = (Uint8 *)SDL_LoadFile_RW(rwops, &size, SDL_TRUE);\n\n\t// Skip short data\n\tif (size < 12) {\n\t\tLog(LOG_VERBOSE) << \"SoundSet::loadCatByIndex(\" << catFile.fileName() << \", \" << index << \") size=\" << size <<\" , skipping.\";\n\t\tSDL_free(sound);\n\t\treturn;\n\t}\n\n\t// See if we've got RIFF header here.\n\tbool wav = ((sound[0] == 'R') && (sound[1] == 'I') && (sound[2]  == 'F') && (sound[3]  == 'F')\n\t\t\t && (sound[8] == 'W') && (sound[9] == 'A') && (sound[10] == 'V') && (sound[11] == 'E'));\n\n\tUint8 *samples;\n\tsize_t samplecount;\n\tbool do_resample = true;\n\tif (wav) { // skip WAV header\n\t\tint expected_size = *(Sint32 *)(sound +0x04) + 8;\n\t\tint delta = ((int)size) - expected_size;\n\t\t// fix the header if we miss some data.\n\t\tif (delta < 0) {\n\t\t\t*(Sint32 *)(sound +0x04) += delta; // WAVE chunk size\n\t\t\t*(Sint32 *)(sound +0x28) += delta; // data chunk size\n\t\t}\n\t\tint samplerate = *(Sint32 *)(sound + 0x18);\n\t\tdo_resample  = (samplerate < 11025);\n\t\tsamples = sound + 44;\n\t\tsamplecount = size - 44;\n\t} else { // skip DOS header\n\t\t// UFO2000 style\n\t\tsamples = sound + 6;\n\t\tsamplecount = size - 6;\n\n\t\t// OpenXcom style\n\t\tsamples = sound + 5;\n\t\tsamplecount = size - 6;\n\n\t\t// scale to 8 bits (UFO) or get rid of signedness (TFTD)\n\t\tfor (size_t n = 0; n < samplecount; ++n) {\n\t\t\tint sample = samples[n];\n\t\t\tsamples[n] = (Uint8) (tftd ? sample + 128 : sample * 4);\n\t\t}\n\t}\n\tsize_t dest_size = 44 + 2 * size; // worst-case estimation\n\tauto dest_mem = SDL_malloc(dest_size);\n\tauto dest_rwops = SDL_RWFromMem(dest_mem, dest_size);\n\n\tif (do_resample) {\n\t\twriteWAV(dest_rwops, samples, samplecount, !tftd);\n\t} else { // nothing to do.\n\t\tSDL_RWwrite(dest_rwops, sound, size, 1);\n\t}\n\tSDL_RWseek(dest_rwops, 0, RW_SEEK_SET);\n\t_sounds[set_index].load(dest_rwops);  // this frees the dest_rwops\n\tSDL_free(dest_mem);\n\tSDL_free(sound);\n}\n\n}\n"
  },
  {
    "path": "src/Engine/SoundSet.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <SDL_mixer.h>\n#include <map>\n\nnamespace OpenXcom\n{\n\nclass Sound;\nclass CatFile;\n\n/**\n * Container of a set of sounds.\n * Used to manage file sets that contain a pack\n * of sounds inside.\n */\nclass SoundSet\n{\nprivate:\n\tstd::map<int, Sound> _sounds;\n\tint _sharedSounds;\n\n\tint convertSampleRate(Uint8 *oldsound, size_t oldsize, Uint8 *newsound) const;\n\tvoid writeWAV(SDL_RWops *dest, Uint8 *sound, size_t size, bool resample) const;\n\npublic:\n\t/// Crates a sound set.\n\tSoundSet();\n\t/// Cleans up the sound set.\n\t~SoundSet() = default;\n\t/// Loads an X-Com CAT set of sound files.\n\tvoid loadCat(CatFile& sndFile);\n\t/// Gets a particular sound from the set.\n\tSound *getSound(int i);\n\t/// Creates a new sound and returns a pointer to it.\n\tSound *addSound(int i);\n\n\t/// Set number of shared sound indexes that are accessible for all mods.\n\tvoid setMaxSharedSounds(int i);\n\t/// Gets number of shared sound indexes that are accessible for all mods.\n\tint getMaxSharedSounds() const;\n\n\t/// Gets the total sounds in the set.\n\tsize_t getTotalSounds() const;\n\t/// Loads a specific entry from a CAT file into the soundset.\n\tvoid loadCatByIndex(CatFile &sndFile, int index, bool tftd = false);\n};\n\n}\n"
  },
  {
    "path": "src/Engine/State.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"State.h\"\n#include <algorithm>\n#include <climits>\n#include \"InteractiveSurface.h\"\n#include \"Game.h\"\n#include \"Screen.h\"\n#include \"Surface.h\"\n#include \"Language.h\"\n#include \"LocalizedText.h\"\n#include \"Palette.h\"\n#include \"../Engine/Sound.h\"\n#include \"../Engine/Collections.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/TextEdit.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Interface/BattlescapeButton.h\"\n#include \"../Interface/ComboBox.h\"\n#include \"../Interface/Cursor.h\"\n#include \"../Interface/FpsCounter.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"../Mod/RuleInterface.h\"\n\nnamespace OpenXcom\n{\n\n/// Initializes static member\nGame* State::_game = 0;\n\n/**\n * Initializes a brand new state with no child elements.\n * By default states are full-screen.\n * @param game Pointer to the core game.\n */\nState::State() : _screen(true), _soundPlayed(false), _modal(0), _ruleInterface(0), _ruleInterfaceParent(0), _customSound(nullptr)\n{\n\t// initialize palette to all black\n\tmemset(_palette, 0, sizeof(_palette));\n\t_cursorColor = _game->getCursor()->getColor();\n}\n\n/**\n * Deletes all the child elements contained in the state.\n */\nState::~State()\n{\n\t// Surfaces are deleted in reverse order of adding, same like local variables\n\tfor (auto* surface : Collections::reverse(Collections::range(_surfacesOwned)))\n\t{\n\t\tdelete surface;\n\t}\n}\n\n/**\n * Set interface data from the ruleset, also sets the palette for the state.\n * @param category Name of the interface set.\n * @param alterPal Should we swap out the backpal colors?\n * @param battleGame Should we use battlescape palette? (this only applies to options screens)\n */\nvoid State::setInterface(const std::string& category, bool alterPal, SavedBattleGame *battleGame)\n{\n\tint backPal = -1;\n\tstd::string pal = \"PAL_GEOSCAPE\";\n\n\t_ruleInterface = _game->getMod()->getInterface(category);\n\tif (_ruleInterface)\n\t{\n\t\t_ruleInterfaceParent = _game->getMod()->getInterface(_ruleInterface->getParent());\n\t\tpal = _ruleInterface->getPalette();\n\t\tconst Element *element = _ruleInterface->getElementOptional(\"palette\");\n\t\tif (_ruleInterfaceParent)\n\t\t{\n\t\t\tif (!element)\n\t\t\t{\n\t\t\t\telement = _ruleInterfaceParent->getElementOptional(\"palette\");\n\t\t\t}\n\t\t\tif (pal.empty())\n\t\t\t{\n\t\t\t\tpal = _ruleInterfaceParent->getPalette();\n\t\t\t}\n\t\t}\n\t\tif (element)\n\t\t{\n\t\t\tint color = alterPal ? element->color2 : element->color;\n\t\t\tif (color != INT_MAX)\n\t\t\t{\n\t\t\t\tbackPal = color;\n\t\t\t}\n\t\t}\n\t}\n\tif (battleGame)\n\t{\n\t\tbattleGame->setPaletteByDepth(this);\n\t}\n\telse if (pal.empty())\n\t{\n\t\tpal = \"PAL_GEOSCAPE\";\n\t\tsetStandardPalette(pal, backPal);\n\t}\n\telse\n\t{\n\t\tsetStandardPalette(pal, backPal);\n\t}\n}\n\n/**\n * Set window background from the ruleset.\n * @param window Window handle.\n * @param s ID of the interface ruleset entry.\n */\nvoid State::setWindowBackground(Window *window, const std::string &s)\n{\n\tauto& bgImageName = _game->getMod()->getInterface(s)->getBackgroundImage(_game->getMod(), _game->getSavedGame());\n\tsetWindowBackgroundImage(window, bgImageName);\n}\n\n/**\n * Set window background by image name (instead of by interface name).\n * @param window Window handle.\n * @param s ID of the image.\n */\nvoid State::setWindowBackgroundImage(Window* window, const std::string& bgImageName)\n{\n\tconst auto* bgImage = _game->getMod()->getSurface(bgImageName);\n\twindow->setBackground(bgImage);\n}\n\n/**\n *  Add a optional child element but it will not be displayed.\n */\nvoid State::preAdd(Surface *surface)\n{\n\t//TODO: O(n^2) but number of surfaces is less than 100 (it become lag araund 100k surfaces) and sort of hash will make deleting order nondetermistic\n\tif (std::find(_surfacesOwned.begin(), _surfacesOwned.end(), surface) == _surfacesOwned.end())\n\t{\n\t\t_surfacesOwned.push_back(surface);\n\t}\n}\n\n\n/**\n * Adds a new child surface for the state to take care of,\n * giving it the game's display palette. Once associated,\n * the state handles all of the surface's behaviour\n * and management automatically.\n * @param surface Child surface.\n * @note Since visible elements can overlap one another,\n * they have to be added in ascending Z-Order to be blitted\n * correctly onto the screen.\n */\nvoid State::add(Surface *surface)\n{\n\t// Set palette\n\tsurface->setPalette(_palette);\n\n\t// Set default text resources\n\tif (_game->getLanguage() && _game->getMod())\n\t\tsurface->initText(_game->getMod()->getFont(\"FONT_BIG\"), _game->getMod()->getFont(\"FONT_SMALL\"), _game->getLanguage());\n\n\t_surfaces.push_back(surface);\n\tpreAdd(surface);\n}\n\n/**\n * As above, except this adds a surface based on an\n * interface element defined in the ruleset.\n * @note that this function REQUIRES the ruleset to have been loaded prior to use.\n * @param surface Child surface.\n * @param id the ID of the element defined in the ruleset, if any.\n * @param category the category of elements this interface is associated with.\n * @param parent the surface to base the coordinates of this element off.\n * @note if no parent is defined the element will not be moved.\n */\nvoid State::add(Surface *surface, const std::string &id, const std::string &category, Surface *parent)\n{\n\t// Set palette\n\tsurface->setPalette(_palette);\n\n\t// this only works if we're dealing with a battlescape button\n\tBattlescapeButton *bsbtn = dynamic_cast<BattlescapeButton*>(surface);\n\n\tif (_game->getMod()->getInterface(category, false))\n\t{\n\t\tconst Element *element = _game->getMod()->getInterface(category)->getElementOptional(id);\n\t\tif (element)\n\t\t{\n\t\t\tif (parent && element->w != INT_MAX && element->h != INT_MAX)\n\t\t\t{\n\t\t\t\tsurface->setWidth(element->w);\n\t\t\t\tsurface->setHeight(element->h);\n\t\t\t}\n\n\t\t\tif (parent && element->x != INT_MAX && element->y != INT_MAX)\n\t\t\t{\n\t\t\t\tsurface->setX(parent->getX() + element->x);\n\t\t\t\tsurface->setY(parent->getY() + element->y);\n\t\t\t}\n\n\t\t\tauto inter = dynamic_cast<InteractiveSurface*>(surface);\n\t\t\tif (inter)\n\t\t\t{\n\t\t\t\tinter->setTFTDMode(element->TFTDMode);\n\t\t\t}\n\n\t\t\tif (element->color != INT_MAX)\n\t\t\t{\n\t\t\t\tsurface->setColor(element->color);\n\t\t\t}\n\t\t\tif (element->color2 != INT_MAX)\n\t\t\t{\n\t\t\t\tsurface->setSecondaryColor(element->color2);\n\t\t\t}\n\t\t\tif (element->border != INT_MAX)\n\t\t\t{\n\t\t\t\tsurface->setBorderColor(element->border);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (bsbtn)\n\t{\n\t\t// this will initialize the graphics and settings of the battlescape button.\n\t\tbsbtn->copy(parent);\n\t\tbsbtn->initSurfaces();\n\t}\n\n\t// Set default text resources\n\tif (_game->getLanguage() && _game->getMod())\n\t\tsurface->initText(_game->getMod()->getFont(\"FONT_BIG\"), _game->getMod()->getFont(\"FONT_SMALL\"), _game->getLanguage());\n\n\t_surfaces.push_back(surface);\n\tpreAdd(surface);\n}\n\n/**\n * Returns whether this is a full-screen state.\n * This is used to optimize the state machine since full-screen\n * states automatically cover the whole screen, (whether they\n * actually use it all or not) so states behind them can be\n * safely ignored since they'd be covered up.\n * @return True if it's a screen, False otherwise.\n */\nbool State::isScreen() const\n{\n\treturn _screen;\n}\n\n/**\n * Toggles the full-screen flag. Used by windows to\n * keep the previous screen in display while the window\n * is still \"popping up\".\n */\nvoid State::toggleScreen()\n{\n\t_screen = !_screen;\n}\n\n/**\n * Initializes the state and its child elements. This is\n * used for settings that have to be reset every time the\n * state is returned to focus (eg. palettes), so can't\n * just be put in the constructor (remember there's a stack\n * of states, so they can be created once while being\n * repeatedly switched back into focus).\n */\nvoid State::init()\n{\n\t_game->getScreen()->setPalette(_palette);\n\t_game->getCursor()->setPalette(_palette);\n\t_game->getCursor()->setColor(_cursorColor);\n\t_game->getCursor()->draw();\n\t_game->getFpsCounter()->setPalette(_palette);\n\t_game->getFpsCounter()->setColor(_cursorColor);\n\t_game->getFpsCounter()->draw();\n\n\t// Highest priority: custom sound set explicitly in the code\n\t// Medium priority: sound defined by the interface ruleset\n\t// Lowest priority: default window popup sound\n\tbool muteWindowPopupSound = false;\n\tif (!_soundPlayed)\n\t{\n\t\t_soundPlayed = true;\n\t\tif (!_customSound && _ruleInterface && _ruleInterface->getSound() != Mod::NO_SOUND)\n\t\t{\n\t\t\t_customSound = _game->getMod()->getSound(\"GEO.CAT\", _ruleInterface->getSound());\n\t\t}\n\t\tif (_customSound)\n\t\t{\n\t\t\tmuteWindowPopupSound = true;\n\t\t\t_customSound->play();\n\t\t}\n\t}\n\n\tfor (auto* surface : _surfaces)\n\t{\n\t\tWindow* window = dynamic_cast<Window*>(surface);\n\t\tif (window)\n\t\t{\n\t\t\tif (muteWindowPopupSound)\n\t\t\t{\n\t\t\t\twindow->mute();\n\t\t\t}\n\t\t\twindow->invalidate();\n\t\t}\n\t}\n\tif (_ruleInterface != 0 && !_ruleInterface->getMusic().empty())\n\t{\n\t\t_game->getMod()->playMusic(_ruleInterface->getMusic());\n\t}\n}\n\n/**\n * Runs any code the state needs to keep updating every\n * game cycle, like timers and other real-time elements.\n */\nvoid State::think()\n{\n\tfor (auto* surface : _surfaces)\n\t{\n\t\tsurface->think();\n\t}\n}\n\n/**\n * Takes care of any events from the core game engine,\n * and passes them on to its InteractiveSurface child elements.\n * @param action Pointer to an action.\n */\nvoid State::handle(Action *action)\n{\n\tif (!_modal)\n\t{\n\t\tfor (std::vector<Surface*>::reverse_iterator i = _surfaces.rbegin(); i != _surfaces.rend(); ++i)\n\t\t{\n\t\t\tInteractiveSurface* j = dynamic_cast<InteractiveSurface*>(*i);\n\t\t\tif (j != 0)\n\t\t\t\tj->handle(action, this);\n\t\t}\n\t}\n\telse\n\t{\n\t\t_modal->handle(action, this);\n\t}\n}\n\n/**\n * Blits all the visible Surface child elements onto the\n * display screen, by order of addition.\n */\nvoid State::blit()\n{\n\tfor (auto* surface : _surfaces)\n\t{\n\t\tsurface->blit(_game->getScreen()->getSurface());\n\t}\n}\n\n/**\n * Hides all the Surface child elements on display.\n */\nvoid State::hideAll()\n{\n\tfor (auto* surface : _surfaces)\n\t{\n\t\tsurface->setHidden(true);\n\t}\n}\n\n/**\n * Shows all the hidden Surface child elements.\n */\nvoid State::showAll()\n{\n\tfor (auto* surface : _surfaces)\n\t{\n\t\tsurface->setHidden(false);\n\t}\n}\n\n/**\n * Resets the status of all the Surface child elements,\n * like unpressing buttons.\n */\nvoid State::resetAll()\n{\n\tfor (auto* surface : _surfaces)\n\t{\n\t\tInteractiveSurface *s = dynamic_cast<InteractiveSurface*>(surface);\n\t\tif (s != 0)\n\t\t{\n\t\t\ts->unpress(this);\n\t\t\t//s->setFocus(false);\n\t\t}\n\t}\n}\n\n/**\n * Get the localized text for dictionary key @a id.\n * This function forwards the call to Language::getString(const std::string &).\n * @param id The dictionary key to search for.\n * @return The localized text.\n */\nLocalizedText State::tr(const std::string &id) const\n{\n\treturn _game->getLanguage()->getString(id);\n}\n\n/**\n* Get the localized text from dictionary.\n* This function forwards the call to Language::getString(const std::string &).\n* @param id The (prefix of) dictionary key to search for.\n* @param alt Used to construct the (suffix of) dictionary key to search for.\n* @return The localized text.\n*/\nLocalizedText State::trAlt(const std::string &id, int alt) const\n{\n\tstd::ostringstream ss;\n\tss << id;\n\t// alt = 0 is the original, alt > 0 are the alternatives\n\tif (alt > 0)\n\t{\n\t\tss << \"_\" << alt;\n\t}\n\treturn _game->getLanguage()->getString(ss.str());\n}\n\n/**\n * Get a modifiable copy of the localized text for dictionary key @a id.\n * This function forwards the call to Language::getString(const std::string &, unsigned).\n * @param id The dictionary key to search for.\n * @param n The number to use for the proper version.\n * @return The localized text.\n */\nLocalizedText State::tr(const std::string &id, unsigned n) const\n{\n\treturn _game->getLanguage()->getString(id, n);\n}\n\n/**\n * Get the localized text for dictionary key @a id.\n * This function forwards the call to Language::getString(const std::string &, SoldierGender).\n * @param id The dictionary key to search for.\n * @param gender Current soldier gender.\n * @return The localized text.\n */\nLocalizedText State::tr(const std::string &id, SoldierGender gender) const\n{\n\treturn _game->getLanguage()->getString(id, gender);\n}\n\n/**\n * centers all the surfaces on the screen.\n */\nvoid State::centerAllSurfaces()\n{\n\tfor (auto* surface : _surfaces)\n\t{\n\t\tsurface->setX(surface->getX() + _game->getScreen()->getDX());\n\t\tsurface->setY(surface->getY() + _game->getScreen()->getDY());\n\t}\n}\n\n/**\n * drop all the surfaces by half the screen height\n */\nvoid State::lowerAllSurfaces()\n{\n\tfor (auto* surface : _surfaces)\n\t{\n\t\tsurface->setY(surface->getY() + _game->getScreen()->getDY() / 2);\n\t}\n}\n\n/**\n * switch all the colours to something a little more battlescape appropriate.\n */\nvoid State::applyBattlescapeTheme(const std::string& category)\n{\n\tconst Element * element = _game->getMod()->getInterface(\"mainMenu\")->getElement(\"battlescapeTheme\");\n\tstd::string altBg = _game->getMod()->getInterface(category)->getAltBackgroundImage();\n\tif (altBg.empty())\n\t{\n\t\taltBg = \"TAC00.SCR\";\n\t}\n\tfor (auto* surface : _surfaces)\n\t{\n\t\tsurface->setColor(element->color);\n\t\tsurface->setHighContrast(true);\n\t\tWindow* window = dynamic_cast<Window*>(surface);\n\t\tif (window)\n\t\t{\n\t\t\twindow->setBackground(_game->getMod()->getSurface(altBg));\n\t\t}\n\t\tTextList* list = dynamic_cast<TextList*>(surface);\n\t\tif (list)\n\t\t{\n\t\t\tlist->setArrowColor(element->border);\n\t\t}\n\t\tComboBox *combo = dynamic_cast<ComboBox*>(surface);\n\t\tif (combo)\n\t\t{\n\t\t\tcombo->setArrowColor(element->border);\n\t\t}\n\t}\n}\n\n/**\n * redraw all the text-type surfaces.\n */\nvoid State::redrawText()\n{\n\tfor (auto* surface : _surfaces)\n\t{\n\t\tText* text = dynamic_cast<Text*>(surface);\n\t\tTextButton* button = dynamic_cast<TextButton*>(surface);\n\t\tTextEdit* edit = dynamic_cast<TextEdit*>(surface);\n\t\tTextList* list = dynamic_cast<TextList*>(surface);\n\t\tif (text || button || edit || list)\n\t\t{\n\t\t\tsurface->draw();\n\t\t}\n\t}\n}\n\n/**\n * does the state only have one text list (to scroll)?\n */\nbool State::hasOnlyOneScrollableTextList() const\n{\n\tint count = 0;\n\tfor (auto* surface : _surfaces)\n\t{\n\t\tTextList* list = dynamic_cast<TextList*>(surface);\n\t\tif (list && (list->getRowsDoNotUse() > list->getVisibleRows()))\n\t\t{\n\t\t\tcount++;\n\t\t}\n\t}\n\treturn (count == 1);\n}\n\n/**\n * Changes the current modal surface. If a surface is modal,\n * then only that surface can receive events. This is used\n * when an element needs to take priority over everything else,\n * eg. focus.\n * @param surface Pointer to modal surface, NULL for no modal.\n */\nvoid State::setModal(InteractiveSurface *surface)\n{\n\t_modal = surface;\n}\n\n/**\n * Replaces a certain amount of colors in the state's palette.\n * @param colors Pointer to the set of colors.\n * @param firstcolor Offset of the first color to replace.\n * @param ncolors Amount of colors to replace.\n */\nvoid State::setStatePalette(const SDL_Color *colors, int firstcolor, int ncolors)\n{\n\tif (colors)\n\t{\n\t\tmemcpy(_palette + firstcolor, colors, ncolors * sizeof(SDL_Color));\n\t}\n}\n\n/**\n * Set palette for helper surfaces like cursor or fps counter.\n */\nvoid State::setModPalette()\n{\n\t{\n\t\t_game->getCursor()->setPalette(_palette);\n\t\t_game->getCursor()->draw();\n\t\t_game->getFpsCounter()->setPalette(_palette);\n\t\t_game->getFpsCounter()->draw();\n\t}\n}\n\n/**\n * Loads palettes from the game resources into the state.\n * @param palette String ID of the palette to load.\n * @param backpals BACKPALS.DAT offset to use.\n */\nvoid State::setStandardPalette(const std::string &palette, int backpals)\n{\n\tsetStatePalette(_game->getMod()->getPalette(palette)->getColors(), 0, 256);\n\tif (palette == \"PAL_GEOSCAPE\")\n\t{\n\t\t_cursorColor = Mod::GEOSCAPE_CURSOR;\n\t}\n\telse if (palette == \"PAL_BASESCAPE\")\n\t{\n\t\t_cursorColor = Mod::BASESCAPE_CURSOR;\n\t}\n\telse if (palette == \"PAL_UFOPAEDIA\")\n\t{\n\t\t_cursorColor = Mod::UFOPAEDIA_CURSOR;\n\t}\n\telse if (palette == \"PAL_GRAPHS\")\n\t{\n\t\t_cursorColor = Mod::GRAPHS_CURSOR;\n\t}\n\telse\n\t{\n\t\t_cursorColor = Mod::BATTLESCAPE_CURSOR;\n\t}\n\tif (backpals != -1)\n\t\tsetStatePalette(_game->getMod()->getPalette(\"BACKPALS.DAT\")->getColors(Palette::blockOffset(backpals)), Palette::backPos, 16);\n\tsetModPalette(); // delay actual update to the end\n}\n\n/**\n* Loads palettes from the given resources into the state.\n* @param colors Pointer to the set of colors.\n* @param cursorColor Cursor color to use.\n*/\nvoid State::setCustomPalette(SDL_Color *colors, int cursorColor)\n{\n\tsetStatePalette(colors, 0, 256);\n\t_cursorColor = cursorColor;\n\tsetModPalette(); // delay actual update to the end\n}\n\n/**\n * Returns the state's 8bpp palette.\n * @return Pointer to the palette's colors.\n */\nSDL_Color *State::getPalette()\n{\n\treturn _palette;\n}\n\n/**\n * Each state will probably need its own resize handling,\n * so this space intentionally left blank\n * @param dX delta of X;\n * @param dY delta of Y;\n */\nvoid State::resize(int &dX, int &dY)\n{\n\trecenter(dX, dY);\n}\n\n/**\n * Re-orients all the surfaces in the state.\n * @param dX delta of X;\n * @param dY delta of Y;\n */\nvoid State::recenter(int dX, int dY)\n{\n\tfor (auto* surface : _surfaces)\n\t{\n\t\tsurface->setX(surface->getX() + dX / 2);\n\t\tsurface->setY(surface->getY() + dY / 2);\n\t}\n}\n\nint State::getCursorX() const\n{\n\treturn _game->getCursor()->getX();\n}\n\nint State::getCursorY() const\n{\n\treturn _game->getCursor()->getY();\n}\n\nvoid State::setGamePtr(Game* game)\n{\n\t_game = game;\n}\n\n}\n"
  },
  {
    "path": "src/Engine/State.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <vector>\n#include <string>\n#include <SDL.h>\n#include \"LocalizedText.h\"\n\nnamespace OpenXcom\n{\n\nclass Game;\nclass Surface;\nclass InteractiveSurface;\nclass Window;\nclass Action;\nclass SavedBattleGame;\nclass RuleInterface;\nclass Sound;\n\nenum SoldierGender : char;\n\n/**\n * A game state that receives user input and reacts accordingly.\n * Game states typically represent a whole window or screen that\n * the user interacts with, making the game... well, interactive.\n * They automatically handle child elements used to transmit\n * information from/to the user, and are linked to the core game\n * engine which manages them.\n */\nclass State\n{\n\tfriend class Timer;\n\nprotected:\n\tstatic Game *_game;\n\tstd::vector<Surface*> _surfaces;\n\tstd::vector<Surface*> _surfacesOwned;\n\tbool _screen;\n\tbool _soundPlayed;\n\tInteractiveSurface *_modal;\n\tRuleInterface *_ruleInterface;\n\tRuleInterface *_ruleInterfaceParent;\n\tconst Sound* _customSound;\n\n\tSDL_Color _palette[256];\n\tUint8 _cursorColor;\npublic:\n\t/// Creates a new state linked to a game.\n\tState();\n\t/// Cleans up the state.\n\tvirtual ~State();\n\t/// Set interface rules.\n\tvoid setInterface(const std::string &s, bool alterPal = false, SavedBattleGame *battleGame = 0);\n\t/// Set window background.\n\tvoid setWindowBackground(Window *window, const std::string &s);\n\t/// Set window background by image name (instead of by interface name).\n\tvoid setWindowBackgroundImage(Window* window, const std::string& bgImageName);\n\t/// Add a optional child element but it will not be displayed.\n\ttemplate<typename T>\n\tT* preAdd(T *surface)\n\t{\n\t\tstatic_assert(std::is_base_of_v<Surface, T>, \"Type need to be surface\");\n\t\tpreAdd(static_cast<Surface*>(surface));\n\t\treturn surface;\n\t}\n\t/// Add a optional child element but it will not be displayed.\n\tvoid preAdd(Surface *surface);\n\t/// Adds a child element to the state.\n\tvoid add(Surface *surface);\n\t/// Adds a child element to the state.\n\tvoid add(Surface *surface, const std::string &id, const std::string &category, Surface *parent = 0);\n\t/// Gets whether the state is a full-screen.\n\tbool isScreen() const;\n\t/// Toggles whether the state is a full-screen.\n\tvoid toggleScreen();\n\t/// Initializes the state.\n\tvirtual void init();\n\t/// Handles any events.\n\tvirtual void handle(Action *action);\n\t/// Runs state functionality every cycle.\n\tvirtual void think();\n\t/// Blits the state to the screen.\n\tvirtual void blit();\n\t/// Hides all the state surfaces.\n\tvoid hideAll();\n\t/// Shows all the state surfaces.\n\tvoid showAll();\n\t/// Resets all the state surfaces.\n\tvoid resetAll();\n\t/// Get the localized text.\n\tLocalizedText tr(const std::string &id) const;\n\t/// Get the localized text.\n\tLocalizedText trAlt(const std::string &id, int alt) const;\n\t/// Get the localized text.\n\tLocalizedText tr(const std::string &id, unsigned n) const;\n\t/// Get the localized text.\n\tLocalizedText tr(const std::string &id, SoldierGender gender) const;\n\t/// redraw all the text-type surfaces.\n\tvoid redrawText();\n\t/// does the state only have one text list (to scroll)?\n\tbool hasOnlyOneScrollableTextList() const;\n\t/// center all surfaces relative to the screen.\n\tvoid centerAllSurfaces();\n\t/// lower all surfaces by half the screen height.\n\tvoid lowerAllSurfaces();\n\t/// switch the colours to use the battlescape palette.\n\tvoid applyBattlescapeTheme(const std::string& category);\n\t/// Sets game object pointer\n\tstatic void setGamePtr(Game* game);\n\t/// Sets a modal surface.\n\tvoid setModal(InteractiveSurface *surface);\n\n\t/// Changes a set of colors on the state's 8bpp palette.\n\tvoid setStatePalette(const SDL_Color *colors, int firstcolor = 0, int ncolors = 256);\n\t/// Changes a set of colors on the state's 8bpp palette of helper surfaces.\n\tvoid setModPalette();\n\n\t/// Changes the state's 8bpp palette with certain resources.\n\tvoid setStandardPalette(const std::string &palette, int backpals = -1);\n\t/// Changes the state's 8bpp palette with certain resources.\n\tvoid setCustomPalette(SDL_Color *colors, int cursorColor);\n\n\t/// Gets the state's 8bpp palette.\n\tSDL_Color *getPalette();\n\n\t/// Let the state know the window has been resized.\n\tvirtual void resize(int &dX, int &dY);\n\t/// Re-orients all the surfaces in the state.\n\tvirtual void recenter(int dX, int dY);\n\n\t/// Gets cursor X coordinate.\n\tint getCursorX() const;\n\t/// Gets cursor Y coordinate.\n\tint getCursorY() const;\n};\n\n}\n"
  },
  {
    "path": "src/Engine/Surface.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Surface.h\"\n#include \"ShaderDraw.h\"\n#include \"ShaderMove.h\"\n#include <vector>\n#include <algorithm>\n#include <SDL_gfxPrimitives.h>\n#include <SDL_image.h>\n#include \"../lodepng.h\"\n#include \"Palette.h\"\n#include \"Exception.h\"\n#include \"Logger.h\"\n#include \"SDL2Helpers.h\"\n#include \"FileMap.h\"\n#ifdef _WIN32\n#include <malloc.h>\n#endif\n#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)\n#define _aligned_malloc __mingw_aligned_malloc\n#define _aligned_free   __mingw_aligned_free\n#endif //MINGW\n#ifdef __MORPHOS__\n#include <ppcinline/exec.h>\n#endif\n\nnamespace OpenXcom\n{\n\n\nnamespace\n{\n\n/**\n * Helper function counting pitch in bytes with 16byte padding\n * @param bpp bits per pixel\n * @param width number of pixel in row\n * @return pitch in bytes\n */\ninline int GetPitch(int bpp, int width)\n{\n\treturn ((bpp/8) * width + 15) & ~0xF;\n}\n\n\n/**\n * Raw copy without any change of pixel index value between two SDL surface, palette is ignored\n * @param dest Destination surface\n * @param src Source surface\n */\ninline void RawCopySurf(const Surface::UniqueSurfacePtr& dest, const Surface::UniqueSurfacePtr& src)\n{\n\tShaderDrawFunc(\n\t\t[](Uint8& destStuff, Uint8& srcStuff)\n\t\t{\n\t\t\tdestStuff = srcStuff;\n\t\t},\n\t\tShaderMove<Uint8>(dest.get()),\n\t\tShaderMove<Uint8>(src.get())\n\t);\n}\n\n/**\n * TODO: function for purge, we should accept only \"standard\" surfaces\n * Helper function correcting graphic that should have index 0 as transparent,\n * but some do not have, we swap correct with incorrect\n * for maintain 0 as correct transparent index.\n * @param dest Surface to fix\n * @param currentTransColor current transparent color index\n */\ninline void FixTransparent(const Surface::UniqueSurfacePtr& dest, int currentTransColor)\n{\n\tif (currentTransColor != 0)\n\t{\n\t\tShaderDrawFunc(\n\t\t\t[&](Uint8& destStuff)\n\t\t\t{\n\t\t\t\tif (destStuff == currentTransColor)\n\t\t\t\t{\n\t\t\t\t\tdestStuff = 0;\n\t\t\t\t}\n\t\t\t},\n\t\t\tShaderMove<Uint8>(dest.get())\n\t\t);\n\t}\n}\n\n} //namespace\n\n/**\n * Helper function creating aligned buffer\n * @param bpp bits per pixel\n * @param width number of pixel in row\n * @param height number of rows\n * @return pointer to memory\n */\nSurface::UniqueBufferPtr Surface::NewAlignedBuffer(int bpp, int width, int height)\n{\n\tconst int pitch = GetPitch(bpp, width);\n\tconst int total = pitch * height;\n\tvoid* buffer = 0;\n\n#ifndef _WIN32\n\n\t#ifdef __MORPHOS__\n\n\tbuffer = calloc( total, 1 );\n\tif (!buffer)\n\t{\n\t\tthrow Exception(\"Failed to allocate surface\");\n\t}\n\n\t#else\n\tint rc;\n\tif ((rc = posix_memalign(&buffer, 16, total)))\n\t{\n\t\tthrow Exception(strerror(rc));\n\t}\n\t#endif\n\n#else\n\n\t// of course Windows has to be difficult about this!\n\tbuffer = _aligned_malloc(total, 16);\n\tif (!buffer)\n\t{\n\t\tthrow Exception(\"Failed to allocate surface\");\n\t}\n\n#endif\n\n\tmemset(buffer, 0, total);\n\treturn Surface::UniqueBufferPtr((Uint8*)buffer);\n}\n\n/**\n * Helper function creating new unique pointer\n * @param surface\n * @return Unique pointer\n */\nSurface::UniqueSurfacePtr Surface::NewSdlSurface(SDL_Surface* surface)\n{\n\treturn Surface::UniqueSurfacePtr(surface);\n}\n\n/**\n * Helper function creating new SDL surface in unique pointer\n * @param buffer memory buffer\n * @param bpp bit depth\n * @param width width of surface\n * @param height height of surface\n * @return Unique pointer\n */\nSurface::UniqueSurfacePtr Surface::NewSdlSurface(const Surface::UniqueBufferPtr& buffer, int bpp, int width, int height)\n{\n\tauto surface = SDL_CreateRGBSurfaceFrom(buffer.get(), width, height, bpp, GetPitch(bpp, width), 0, 0, 0, 0);\n\tif (!surface)\n\t{\n\t\tthrow Exception(SDL_GetError());\n\t}\n\n\treturn NewSdlSurface(surface);\n}\n\n/**\n * Zero whole surface.\n */\nvoid Surface::CleanSdlSurface(SDL_Surface* surface)\n{\n\tif (surface->flags & SDL_SWSURFACE)\n\t{\n\t\tmemset(surface->pixels, 0, surface->h * surface->pitch);\n\t}\n\telse\n\t{\n\t\tSDL_Rect c;\n\t\tc.x = 0;\n\t\tc.y = 0;\n\t\tc.w = surface->w;\n\t\tc.h = surface->h;\n\t\tSDL_FillRect(surface, &c, 0);\n\t}\n}\n/**\n * Default deleter for alignment buffer\n * @param buffer\n */\nvoid Surface::UniqueBufferDeleter::operator ()(Uint8* buffer)\n{\n\tif (buffer)\n\t{\n#ifdef _WIN32\n\t\t_aligned_free(buffer);\n#else\n\t\tfree(buffer);\n#endif\n\t}\n}\n\n/**\n * Default deleter for SDL surface\n * @param surf\n */\nvoid Surface::UniqueSurfaceDeleter::operator ()(SDL_Surface* surf)\n{\n\tSDL_FreeSurface(surf);\n}\n\n\n\n/**\n * Default empty surface.\n */\nSurface::Surface() : _x{ }, _y{ }, _width{ }, _height{ }, _pitch{ }, _visible(true), _hidden(false), _redraw(false)\n{\n\n}\n\n/**\n * Sets up a blank 8bpp surface with the specified size and position,\n * with pure black as the transparent color.\n * @note Surfaces don't have to fill the whole size since their\n * background is transparent, specially subclasses with their own\n * drawing logic, so it just covers the maximum drawing area.\n * @param width Width in pixels.\n * @param height Height in pixels.\n * @param x X position in pixels.\n * @param y Y position in pixels.\n * @param bpp Bits-per-pixel depth.\n */\nSurface::Surface(int width, int height, int x, int y) : _x(x), _y(y), _visible(true), _hidden(false), _redraw(false)\n{\n\tstd::tie(_alignedBuffer, _surface) = Surface::NewPair8Bit(width, height);\n\t_width = _surface->w;\n\t_height = _surface->h;\n\t_pitch = _surface->pitch;\n\tSDL_SetColorKey(_surface.get(), SDL_SRCCOLORKEY, 0);\n}\n\n/**\n * Performs a deep copy of an existing surface.\n * @param other Surface to copy from.\n */\nSurface::Surface(const Surface& other) : Surface{ }\n{\n\tif (!other)\n\t{\n\t\treturn;\n\t}\n\tint width = other.getWidth();\n\tint height = other.getHeight();\n\t//move copy\n\t*this = Surface(width, height, other._x, other._y);\n\t//cant call `setPalette` because its virtual function and it doesn't work correctly in constructor\n\tSDL_SetColors(_surface.get(), other.getPalette(), 0, 255);\n\tRawCopySurf(_surface, other._surface);\n\n\t_x = other._x;\n\t_y = other._y;\n\t_visible = other._visible;\n\t_hidden = other._hidden;\n\t_redraw = other._redraw;\n}\n\n/**\n * Deletes the surface from memory.\n */\nSurface::~Surface()\n{\n\n}\n\n/**\n * Performs a fast copy of a pixel array, accounting for pitch.\n * @param src Source array.\n */\ntemplate <typename T>\nvoid Surface::rawCopy(const std::vector<T> &src)\n{\n\t// Copy whole thing\n\tif (_surface->pitch == _surface->w)\n\t{\n\t\tsize_t end = std::min(size_t(_surface->w * _surface->h * _surface->format->BytesPerPixel), src.size());\n\t\tstd::copy(src.begin(), src.begin() + end, (T*)_surface->pixels);\n\t}\n\t// Copy row by row\n\telse\n\t{\n\t\tfor (int y = 0; y < _surface->h; ++y)\n\t\t{\n\t\t\tsize_t begin = y * _surface->w;\n\t\t\tsize_t end = std::min(begin + _surface->w, src.size());\n\t\t\tif (begin >= src.size())\n\t\t\t\tbreak;\n\t\t\tstd::copy(src.begin() + begin, src.begin() + end, (T*)getRaw(0, y));\n\t\t}\n\t}\n}\n\n/**\n * Loads a raw array of pixels into the surface. The pixels must be\n * in the same BPP as the surface.\n * @param bytes Pixel array.\n */\nvoid Surface::loadRaw(const std::vector<unsigned char> &bytes)\n{\n\tlock();\n\trawCopy(bytes);\n\tunlock();\n}\n\n/**\n * Loads a raw array of pixels into the surface. The pixels must be\n * in the same BPP as the surface.\n * @param bytes Pixel array.\n */\nvoid Surface::loadRaw(const std::vector<char> &bytes)\n{\n\tlock();\n\trawCopy(bytes);\n\tunlock();\n}\n\n/**\n * Loads the contents of an X-Com SCR image file into\n * the surface. SCR files are simply uncompressed images\n * containing the palette offset of each pixel.\n * @param filename Filename of the SCR image.\n * @sa http://www.ufopaedia.org/index.php?title=Image_Formats#SCR_.26_DAT\n */\nvoid Surface::loadScr(const std::string& filename)\n{\n\t// Load file and put pixels in surface\n\tauto istream = FileMap::getIStream(filename);\n\tstd::vector<char> buffer((std::istreambuf_iterator<char>(*(istream))), (std::istreambuf_iterator<char>()));\n\tloadRaw(buffer);\n}\n/**\n * Loads the contents of an image file of a\n * known format into the surface.\n * @param filename Filename of the image.\n */\nvoid Surface::loadImage(const std::string &filename)\n{\n\t// Destroy current surface (will be replaced)\n\t_alignedBuffer = nullptr;\n\t_surface = nullptr;\n\n\tLog(LOG_VERBOSE) << \"Loading image: \" << filename;\n\tauto rw = FileMap::getRWops(filename);\n\tif (!rw) { return; } // relevant message gets logged in FileMap.\n\n\t// Try loading with LodePNG first\n\tif (CrossPlatform::compareExt(filename, \"png\"))\n\t{\n\t\tsize_t size;\n\t\tvoid *data = SDL_LoadFile_RW(rw, &size, SDL_FALSE);\n\t\tif ((data != NULL) && (size > 8 + 12 + 12)) // minimal PNG file size: header and two empty chunks\n\t\t{\n\t\t\tstd::vector<unsigned char> png;\n\t\t\tpng.resize(size);\n\t\t\tmemcpy(&png[0], data, size);\n\n\t\t\tstd::vector<unsigned char> image;\n\t\t\tunsigned width, height;\n\t\t\tlodepng::State state;\n\t\t\tstate.decoder.color_convert = 0;\n\t\t\tunsigned error = lodepng::decode(image, width, height, state, png);\n\t\t\tif (!error)\n\t\t\t{\n\t\t\t\tLodePNGColorMode *color = &state.info_png.color;\n\t\t\t\tunsigned bpp = lodepng_get_bpp(color);\n\t\t\t\tif (bpp == 8)\n\t\t\t\t{\n\t\t\t\t\t*this = Surface(width, height, 0, 0);\n\t\t\t\t\tsetPalette((SDL_Color*)color->palette, 0, color->palettesize);\n\n\t\t\t\t\tShaderDrawFunc(\n\t\t\t\t\t\t[](Uint8& dest, unsigned char& src)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tdest = src;\n\t\t\t\t\t\t},\n\t\t\t\t\t\tShaderSurface(this),\n\t\t\t\t\t\tShaderSurface(SurfaceRaw<unsigned char>(image, width, height))\n\t\t\t\t\t);\n\t\t\t\t\tint transparent = 0;\n\t\t\t\t\tfor (int c = 0; c < _surface->format->palette->ncolors; ++c)\n\t\t\t\t\t{\n\t\t\t\t\t\tSDL_Color *palColor = _surface->format->palette->colors + c;\n\t\t\t\t\t\tif (palColor->unused == 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttransparent = c;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tFixTransparent(_surface, transparent);\n\t\t\t\t\tif (transparent != 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tLog(LOG_WARNING) << \"Image \" << filename << \" (from lodepng) has incorrect transparent color index \" << transparent << \" (instead of 0).\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tLog(LOG_ERROR) << \"Image \" << filename << \" lodepng failed:\" << lodepng_error_text(error);\n\t\t\t}\n\t\t}\n\t\tif (data) { SDL_free(data); }\n\t}\n\tif (_surface)\n\t{\n\t\tSDL_RWclose(rw);\n\t}\n\telse // Otherwise default to SDL_Image\n\t{\n\t\tSDL_RWseek(rw, RW_SEEK_SET, 0); // rewind in case .png was no PNG at all\n\t\tauto surface = NewSdlSurface(IMG_Load_RW(rw, SDL_TRUE));\n\t\tif (!surface)\n\t\t{\n\t\t\tstd::string err = filename + \":\" + IMG_GetError();\n\t\t\tthrow Exception(err);\n\t\t}\n\t\tif (surface->format->BitsPerPixel != 8)\n\t\t{\n\t\t\tstd::string err = filename + \": OpenXcom supports only 8bit images.\";\n\t\t\tthrow Exception(err);\n\t\t}\n\n\t\t*this = Surface(surface->w, surface->h, 0, 0);\n\t\tsetPalette(surface->format->palette->colors, 0, surface->format->palette->ncolors);\n\t\tRawCopySurf(_surface, surface);\n\t\tFixTransparent(_surface, surface->format->colorkey);\n\t\tif (surface->format->colorkey != 0)\n\t\t{\n\t\t\tLog(LOG_WARNING) << \"Image \" << filename << \" (from SDL) has incorrect transparent color index \" << surface->format->colorkey << \" (instead of 0).\";\n\t\t}\n\t}\n}\n\n/**\n * Loads the contents of an X-Com SPK image file into\n * the surface. SPK files are compressed with a custom\n * algorithm since they're usually full-screen images.\n * @param filename Filename of the SPK image.\n * @sa http://www.ufopaedia.org/index.php?title=Image_Formats#SPK\n */\nvoid Surface::loadSpk(const std::string& filename)\n{\n\tUint16 flag;\n\tint x = 0, y = 0;\n\tauto rw = FileMap::getRWopsReadAll(filename);\n\tauto rwsize = SDL_RWsize(rw);\n\t// Lock the surface\n\tlock();\n\twhile(SDL_RWtell(rw) < rwsize - 1) {\n\t\tflag = SDL_ReadLE16(rw);\n\t\tif (flag == 65535) {\n\t\t\tflag = SDL_ReadLE16(rw);\n\t\t\tfor (int i = 0; i < flag * 2; ++i) { setPixelIterative(&x, &y, 0); }\n\t\t} else if (flag == 65534) {\n\t\t\tflag = SDL_ReadLE16(rw);\n\t\t\tfor (int i = 0; i < flag * 2; ++i) { setPixelIterative(&x, &y, SDL_ReadU8(rw)); }\n\t\t}\n\t}\n\t// Unlock the surface\n\tunlock();\n\tSDL_RWclose(rw);\n}\n\n/**\n * Loads the contents of a TFTD BDY image file into\n * the surface. BDY files are compressed with a custom\n * algorithm.\n * @param filename Filename of the BDY image.\n * @sa http://www.ufopaedia.org/index.php?title=Image_Formats#BDY\n */\nvoid Surface::loadBdy(const std::string &filename)\n{\n\tUint8 dataByte;\n\tint pixelCnt;\n\tint x = 0, y = 0;\n\tint currentRow = 0;\n\tauto rw = FileMap::getRWopsReadAll(filename);\n\tauto rwsize = SDL_RWsize(rw);\n\t// Lock the surface\n\tlock();\n\twhile (SDL_RWtell(rw) < rwsize) {\n\t\tdataByte = SDL_ReadU8(rw);\n\t\tif (dataByte >= 129)\n\t\t{\n\t\t\tpixelCnt = 257 - (int)dataByte;\n\t\t\tdataByte = SDL_ReadU8(rw);\n\t\t\tcurrentRow = y;\n\t\t\tfor (int i = 0; i < pixelCnt; ++i)\n\t\t\t{\n\t\t\t\tsetPixelIterative(&x, &y, dataByte);\n\t\t\t\tif (currentRow != y) // avoid overscan into next row\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tpixelCnt = 1 + (int)dataByte;\n\t\t\tcurrentRow = y;\n\t\t\tfor (int i = 0; i < pixelCnt; ++i)\n\t\t\t{\n\t\t\t\tdataByte = SDL_ReadU8(rw);\n\t\t\t\tif (currentRow == y) // avoid overscan into next row\n\t\t\t\t\tsetPixelIterative(&x, &y, dataByte);\n\t\t\t}\n\t\t}\n\t}\n\t// Unlock the surface\n\tunlock();\n\tSDL_RWclose(rw);\n}\n\n/**\n * Clears the entire contents of the surface, resulting\n * in a blank image of the specified color. (0 for transparent)\n * @param color the colour for the background of the surface.\n */\nvoid Surface::clear()\n{\n\tCleanSdlSurface(_surface.get());\n}\n\n/**\n * Shifts all the colors in the surface by a set amount.\n * This is a common method in 8bpp games to simulate color\n * effects for cheap.\n * @param off Amount to shift.\n * @param min Minimum color to shift to.\n * @param max Maximum color to shift to.\n * @param mul Shift multiplier.\n */\nvoid Surface::offset(int off, int min, int max, int mul)\n{\n\tif (off == 0)\n\t\treturn;\n\n\t// Lock the surface\n\tlock();\n\n\tfor (int x = 0, y = 0; x < getWidth() && y < getHeight();)\n\t{\n\t\tUint8 pixel = getPixel(x, y);\n\t\tint p;\n\t\tif (off > 0)\n\t\t{\n\t\t\tp = pixel * mul + off;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tp = (pixel + off) / mul;\n\t\t}\n\t\tif (min != -1 && p < min)\n\t\t{\n\t\t\tp = min;\n\t\t}\n\t\telse if (max != -1 && p > max)\n\t\t{\n\t\t\tp = max;\n\t\t}\n\n\t\tif (pixel > 0)\n\t\t{\n\t\t\tsetPixelIterative(&x, &y, p);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tsetPixelIterative(&x, &y, 0);\n\t\t}\n\t}\n\n\t// Unlock the surface\n\tunlock();\n}\n\n/**\n * Shifts all the colors in the surface by a set amount, but\n * keeping them inside a fixed-size color block chunk.\n * @param off Amount to shift.\n * @param blk Color block size.\n * @param mul Shift multiplier.\n */\nvoid Surface::offsetBlock(int off, int blk, int mul)\n{\n\tif (off == 0)\n\t\treturn;\n\n\t// Lock the surface\n\tlock();\n\n\tfor (int x = 0, y = 0; x < getWidth() && y < getHeight();)\n\t{\n\t\tUint8 pixel = getPixel(x, y);\n\t\tint min = pixel / blk * blk;\n\t\tint max = min + blk;\n\t\tint p;\n\t\tif (off > 0)\n\t\t{\n\t\t\tp = pixel * mul + off;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tp = (pixel + off) / mul;\n\t\t}\n\t\tif (min != -1 && p < min)\n\t\t{\n\t\t\tp = min;\n\t\t}\n\t\telse if (max != -1 && p > max)\n\t\t{\n\t\t\tp = max;\n\t\t}\n\n\t\tif (pixel > 0)\n\t\t{\n\t\t\tsetPixelIterative(&x, &y, p);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tsetPixelIterative(&x, &y, 0);\n\t\t}\n\t}\n\n\t// Unlock the surface\n\tunlock();\n}\n\n/**\n * Inverts all the colors in the surface according to a middle point.\n * Used for effects like shifting a button between pressed and unpressed.\n * @param mid Middle point.\n */\nvoid Surface::invert(Uint8 mid)\n{\n\t// Lock the surface\n\tlock();\n\n\tfor (int x = 0, y = 0; x < getWidth() && y < getHeight();)\n\t{\n\t\tUint8 pixel = getPixel(x, y);\n\t\tif (pixel > 0)\n\t\t{\n\t\t\tsetPixelIterative(&x, &y, pixel + 2 * ((int)mid - (int)pixel));\n\t\t}\n\t\telse\n\t\t{\n\t\t\tsetPixelIterative(&x, &y, 0);\n\t\t}\n\t}\n\n\t// Unlock the surface\n\tunlock();\n}\n\n/**\n * Runs any code the surface needs to keep updating every\n * game cycle, like animations and other real-time elements.\n */\nvoid Surface::think()\n{\n\n}\n\n/**\n * Draws the graphic that the surface contains before it\n * gets blitted onto other surfaces. The surface is only\n * redrawn if the flag is set by a property change, to\n * avoid unnecessary drawing.\n */\nvoid Surface::draw()\n{\n\t_redraw = false;\n\tclear();\n}\n\n/**\n * Blits this surface onto another one, with its position\n * relative to the top-left corner of the target surface.\n * The cropping rectangle controls the portion of the surface\n * that is blitted.\n * @param surface Pointer to surface to blit onto.\n */\nvoid Surface::blit(SDL_Surface *surface)\n{\n\tif (_visible && !_hidden)\n\t{\n\t\tif (_redraw)\n\t\t\tdraw();\n\n\t\tSDL_Rect target {};\n\t\ttarget.x = getX();\n\t\ttarget.y = getY();\n\t\tSDL_BlitSurface(_surface.get(), nullptr, surface, &target);\n\t}\n}\n\n/**\n * Copies the exact contents of another surface onto this one.\n * Only the content that would overlap both surfaces is copied, in\n * accordance with their positions. This is handy for applying\n * effects over another surface without modifying the original.\n * @param surface Pointer to surface to copy from.\n */\nvoid Surface::copy(Surface *surface)\n{\n\t/*\n\tSDL_BlitSurface uses colour matching,\n\tand is therefor unreliable as a means\n\tto copy the contents of one surface to another\n\tinstead we have to do this manually\n\n\tSDL_Rect from;\n\tfrom.x = getX() - surface->getX();\n\tfrom.y = getY() - surface->getY();\n\tfrom.w = getWidth();\n\tfrom.h = getHeight();\n\tSDL_BlitSurface(surface->getSurface(), &from, _surface, 0);\n\t*/\n\tconst int from_x = getX() - surface->getX();\n\tconst int from_y = getY() - surface->getY();\n\n\tlock();\n\n\tShaderDrawFunc(\n\t\t[](Uint8& dest, const Uint8& src)\n\t\t{\n\t\t\tdest = src;\n\t\t},\n\t\tShaderMove<Uint8>(_surface.get(), from_x, from_y),\n\t\tShaderMove<Uint8>(surface, 0, 0)\n\t);\n\n\tunlock();\n}\n\n/**\n * Draws a filled rectangle on the surface.\n * @param rect Pointer to Rect.\n * @param color Color of the rectangle.\n */\nvoid Surface::drawRect(SDL_Rect *rect, Uint8 color)\n{\n\tif (rect->w == 0 || rect->h == 0) return;\n\n\tSDL_FillRect(_surface.get(), rect, color);\n}\n\n/**\n * Draws a filled rectangle on the surface.\n * @param x X position in pixels.\n * @param y Y position in pixels.\n * @param w Width in pixels.\n * @param h Height in pixels.\n * @param color Color of the rectangle.\n */\nvoid Surface::drawRect(Sint16 x, Sint16 y, Sint16 w, Sint16 h, Uint8 color)\n{\n\tif (w == 0 || h == 0) return;\n\n\tSDL_Rect rect;\n\trect.w = w;\n\trect.h = h;\n\trect.x = x;\n\trect.y = y;\n\tSDL_FillRect(_surface.get(), &rect, color);\n}\n\n/**\n * Draws a line on the surface.\n * @param x1 Start x coordinate in pixels.\n * @param y1 Start y coordinate in pixels.\n * @param x2 End x coordinate in pixels.\n * @param y2 End y coordinate in pixels.\n * @param color Color of the line.\n */\nvoid Surface::drawLine(Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 color)\n{\n\tlineColor(_surface.get(), x1, y1, x2, y2, Palette::getRGBA(getPalette(), color));\n}\n\n/**\n * Draws a filled circle on the surface.\n * @param x X coordinate in pixels.\n * @param y Y coordinate in pixels.\n * @param r Radius in pixels.\n * @param color Color of the circle.\n */\nvoid Surface::drawCircle(Sint16 x, Sint16 y, Sint16 r, Uint8 color)\n{\n\tfilledCircleColor(_surface.get(), x, y, r, Palette::getRGBA(getPalette(), color));\n}\n\n/**\n * Draws a filled polygon on the surface.\n * @param x Array of x coordinates.\n * @param y Array of y coordinates.\n * @param n Number of points.\n * @param color Color of the polygon.\n */\nvoid Surface::drawPolygon(Sint16 *x, Sint16 *y, int n, Uint8 color)\n{\n\tfilledPolygonColor(_surface.get(), x, y, n, Palette::getRGBA(getPalette(), color));\n}\n\n/**\n * Draws a textured polygon on the surface.\n * @param x Array of x coordinates.\n * @param y Array of y coordinates.\n * @param n Number of points.\n * @param texture Texture for polygon.\n * @param dx X offset of texture relative to the screen.\n * @param dy Y offset of texture relative to the screen.\n */\nvoid Surface::drawTexturedPolygon(Sint16 *x, Sint16 *y, int n, Surface *texture, int dx, int dy)\n{\n\ttexturedPolygon(_surface.get(), x, y, n, texture->getSurface(), dx, dy);\n}\n\n/**\n * Draws a text string on the surface.\n * @param x X coordinate in pixels.\n * @param y Y coordinate in pixels.\n * @param s Character string to draw.\n * @param color Color of string.\n */\nvoid Surface::drawString(Sint16 x, Sint16 y, const char *s, Uint8 color)\n{\n\tstringColor(_surface.get(), x, y, s, Palette::getRGBA(getPalette(), color));\n}\n\n/**\n * Changes the position of the surface in the X axis.\n * @param x X position in pixels.\n */\nvoid Surface::setX(int x)\n{\n\t_x = x;\n}\n\n/**\n * Changes the position of the surface in the Y axis.\n * @param y Y position in pixels.\n */\nvoid Surface::setY(int y)\n{\n\t_y = y;\n}\n\n/**\n * Changes the visibility of the surface. A hidden surface\n * isn't blitted nor receives events.\n * @param visible New visibility.\n */\nvoid Surface::setVisible(bool visible)\n{\n\t_visible = visible;\n}\n\n/**\n * Returns the visible state of the surface.\n * @return Current visibility.\n */\nbool Surface::getVisible() const\n{\n\treturn _visible;\n}\n\n/**\n * Returns the cropping rectangle for this surface.\n * @return Pointer to the cropping rectangle.\n */\nSurfaceCrop Surface::getCrop() const\n{\n\treturn SurfaceCrop{ this };\n}\n\n/**\n * Replaces a certain amount of colors in the surface's palette.\n * @param colors Pointer to the set of colors.\n * @param firstcolor Offset of the first color to replace.\n * @param ncolors Amount of colors to replace.\n */\nvoid Surface::setPalette(const SDL_Color *colors, int firstcolor, int ncolors)\n{\n\tif (_surface->format->BitsPerPixel == 8)\n\t\tSDL_SetColors(_surface.get(), const_cast<SDL_Color *>(colors), firstcolor, ncolors);\n}\n\n/**\n * This is a separate visibility setting intended\n * for temporary effects like window popups,\n * so as to not override the default visibility setting.\n * @note Do not confuse with setVisible!\n * @param hidden Shown or hidden.\n */\nvoid Surface::setHidden(bool hidden)\n{\n\t_hidden = hidden;\n}\n\n/**\n * Locks the surface from outside access\n * for pixel-level access. Must be unlocked\n * afterwards.\n * @sa unlock()\n */\nvoid Surface::lock()\n{\n\tSDL_LockSurface(_surface.get());\n}\n\n/**\n * Unlocks the surface after it's been locked\n * to resume blitting operations.\n * @sa lock()\n */\nvoid Surface::unlock()\n{\n\tSDL_UnlockSurface(_surface.get());\n}\n\n/**\n * Specific blit function to blit battlescape terrain data in different shades in a fast way.\n */\nvoid Surface::blitRaw(SurfaceRaw<Uint8> destSurf, SurfaceRaw<const Uint8> srcSurf, int x, int y, int shade, bool half, int newBaseColor)\n{\n\tShaderMove<const Uint8> src(srcSurf, x, y);\n\tif (half)\n\t{\n\t\tGraphSubset g = src.getDomain();\n\t\tg.beg_x = g.end_x/2;\n\t\tsrc.setDomain(g);\n\t}\n\tif (newBaseColor)\n\t{\n\t\t--newBaseColor;\n\t\tnewBaseColor <<= 4;\n\t\tShaderDraw<helper::ColorReplace>(ShaderSurface(destSurf), src, ShaderScalar(shade), ShaderScalar(newBaseColor));\n\t}\n\telse\n\t{\n\t\tShaderDraw<helper::StandardShade>(ShaderSurface(destSurf), src, ShaderScalar(shade));\n\t}\n}\n\n/**\n * Specific blit function to blit battlescape terrain data in different shades in a fast way.\n * Notice there is no surface locking here - you have to make sure you lock the surface yourself\n * at the start of blitting and unlock it when done.\n * @param surface to blit to\n * @param x\n * @param y\n * @param off\n * @param half some tiles are blitted only the right half\n * @param newBaseColor Attention: the actual color + 1, because 0 is no new base color.\n */\nvoid Surface::blitNShade(SurfaceRaw<Uint8> surface, int x, int y, int shade, bool half, int newBaseColor) const\n{\n\tblitRaw(surface, SurfaceRaw<const Uint8>(this), x, y, shade, half, newBaseColor);\n}\n\n/**\n * Specific blit function to blit battlescape terrain data in different shades in a fast way.\n * @param surface destination blit to\n * @param x\n * @param y\n * @param shade shade offset\n * @param range area that limit draw surface\n */\nvoid Surface::blitNShade(SurfaceRaw<Uint8> surface, int x, int y, int shade, GraphSubset range) const\n{\n\tShaderMove<const Uint8> src(this, x, y);\n\tShaderMove<Uint8> dest(surface);\n\n\tdest.setDomain(range);\n\n\tShaderDraw<helper::StandardShade>(dest, src, ShaderScalar(shade));\n}\n\n/**\n * Set the surface to be redrawn.\n * @param valid true means redraw.\n */\nvoid Surface::invalidate(bool valid)\n{\n\t_redraw = valid;\n}\n\n/**\n * Recreates the surface with a new size.\n * Old contents will not be altered, and may be\n * cropped to fit the new size.\n * @param width Width in pixels.\n * @param height Height in pixels.\n */\nvoid Surface::resize(int width, int height)\n{\n\t// Set up new surface\n\tUint8 bpp = _surface->format->BitsPerPixel;\n\tauto alignedBuffer = NewAlignedBuffer(bpp, width, height);\n\tauto surface = NewSdlSurface(alignedBuffer, bpp, width, height);\n\n\t// Copy old contents\n\tSDL_SetColorKey(surface.get(), SDL_SRCCOLORKEY, 0);\n\tSDL_SetColors(surface.get(), getPalette(), 0, 256);\n\n\tRawCopySurf(surface, _surface);\n\n\t// Delete old surface\n\t_surface = std::move(surface);\n\t_alignedBuffer = std::move(alignedBuffer);\n\t_width = _surface->w;\n\t_height = _surface->h;\n\t_pitch = _surface->pitch;\n}\n\n/**\n * Changes the width of the surface.\n * @warning This is not a trivial setter!\n * It will force the surface to be recreated for the new size.\n * @param width New width in pixels.\n */\nvoid Surface::setWidth(int width)\n{\n\tresize(width, getHeight());\n\t_redraw = true;\n}\n\n/**\n * Changes the height of the surface.\n * @warning This is not a trivial setter!\n * It will force the surface to be recreated for the new size.\n * @param height New height in pixels.\n */\nvoid Surface::setHeight(int height)\n{\n\tresize(getWidth(), height);\n\t_redraw = true;\n}\n\n/**\n * Blit surface with crop\n * @param dest\n */\nvoid SurfaceCrop::blit(Surface* dest)\n{\n\tif (_surface)\n\t{\n\t\tauto srcShader = ShaderCrop(*this, _x, _y);\n\t\tauto destShader = ShaderMove<Uint8>(dest, 0, 0);\n\n\t\tShaderDrawFunc(\n\t\t\t[](Uint8& d, Uint8 s)\n\t\t\t{\n\t\t\t\tif (s) d = s;\n\t\t\t},\n\t\t\tdestShader,\n\t\t\tsrcShader\n\t\t);\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Engine/Surface.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <SDL.h>\n#include <string>\n#include <vector>\n#include <memory>\n#include <vector>\n#include <assert.h>\n#include \"GraphSubset.h\"\n\nnamespace OpenXcom\n{\n\nclass Font;\nclass Language;\nclass ScriptWorkerBase;\nclass SurfaceCrop;\ntemplate<typename Pixel> class SurfaceRaw;\n\n/**\n * Element that is blit (rendered) onto the screen.\n * Mainly an encapsulation for SDL's SDL_Surface struct, so it\n * borrows a lot of its terminology. Takes care of all the common\n * rendering tasks and color effects, while serving as the base\n * class for more specialized screen elements.\n */\nclass Surface\n{\npublic:\n\tstruct UniqueBufferDeleter\n\t{\n\t\tvoid operator()(Uint8*);\n\t};\n\tstruct UniqueSurfaceDeleter\n\t{\n\t\tvoid operator()(SDL_Surface*);\n\t};\n\n\tusing UniqueBufferPtr = std::unique_ptr<Uint8, UniqueBufferDeleter>;\n\tusing UniqueSurfacePtr = std::unique_ptr<SDL_Surface, UniqueSurfaceDeleter>;\n\n\t/// Create aligned buffer for surface.\n\tstatic UniqueBufferPtr NewAlignedBuffer(int bpp, int width, int height);\n\t/// Smart pointer for for SDL_Surface.\n\tstatic UniqueSurfacePtr NewSdlSurface(SDL_Surface* surface);\n\t/// Create surface from aligned buffer.\n\tstatic UniqueSurfacePtr NewSdlSurface(const UniqueBufferPtr& buffer, int bpp, int width, int height);\n\t/// Create buffer and surface.\n\tstatic std::pair<UniqueBufferPtr, UniqueSurfacePtr> NewPair32Bit(int width, int height)\n\t{\n\t\tauto tempBuffer = Surface::NewAlignedBuffer(32, width, height);\n\t\tauto tempSurface = Surface::NewSdlSurface(tempBuffer, 32, width, height);\n\t\treturn std::make_pair(std::move(tempBuffer), std::move(tempSurface));\n\t}\n\n\t/// Create buffer and surface.\n\tstatic std::pair<UniqueBufferPtr, UniqueSurfacePtr> NewPair8Bit(int width, int height)\n\t{\n\t\tauto tempBuffer = Surface::NewAlignedBuffer(8, width, height);\n\t\tauto tempSurface = Surface::NewSdlSurface(tempBuffer, 8, width, height);\n\t\treturn std::make_pair(std::move(tempBuffer), std::move(tempSurface));\n\t}\n\n\t/// Zero whole surface.\n\tstatic void CleanSdlSurface(SDL_Surface* surface);\n\nprotected:\n\tUniqueBufferPtr _alignedBuffer;\n\tUniqueSurfacePtr _surface;\n\tSint16 _x, _y;\n\tUint16 _width, _height, _pitch;\n\tUint8 _visible: 1;\n\tUint8 _hidden: 1;\n\tUint8 _redraw: 1;\n\n\t/// Copies raw pixels.\n\ttemplate <typename T>\n\tvoid rawCopy(const std::vector<T> &bytes);\n\t/// Resizes the surface.\n\tvoid resize(int width, int height);\npublic:\n\t/// Default empty surface.\n\tSurface();\n\t/// Creates a new surface with the specified size and position.\n\tSurface(int width, int height, int x = 0, int y = 0);\n\t/// Creates a new surface from an existing one.\n\tSurface(const Surface& other);\n\t/// Move surface to another place.\n\tSurface(Surface&& other) = default;\n\t/// Move assignment\n\tSurface& operator=(Surface&& other) = default;\n\t/// Copy assignment\n\tSurface& operator=(const Surface& other) { *this = Surface(other); return *this; };\n\t/// Cleans up the surface.\n\tvirtual ~Surface();\n\n\t/// Is surface empty?\n\texplicit operator bool() const\n\t{\n\t\treturn _alignedBuffer.get();\n\t}\n\n\t/// Loads a raw pixel array.\n\tvoid loadRaw(const std::vector<unsigned char> &bytes);\n\t/// Loads a raw pixel array.\n\tvoid loadRaw(const std::vector<char> &bytes);\n\t/// Loads an X-Com SCR graphic.\n\tvoid loadScr(const std::string &filename);\n\t/// Loads an X-Com SPK graphic.\n\tvoid loadSpk(const std::string &filename);\n\t/// Loads a TFTD BDY graphic.\n\tvoid loadBdy(const std::string &filename);\n\t/// Loads a general image file.\n\tvoid loadImage(const std::string &filename);\n\t/// Clears the surface's contents with a specified colour.\n\tvoid clear();\n\t/// Offsets the surface's colors by a set amount.\n\tvoid offset(int off, int min = -1, int max = -1, int mul = 1);\n\t/// Offsets the surface's colors in a color block.\n\tvoid offsetBlock(int off, int blk = 16, int mul = 1);\n\t/// Inverts the surface's colors.\n\tvoid invert(Uint8 mid);\n\t/// Runs surface functionality every cycle\n\tvirtual void think();\n\t/// Draws the surface's graphic.\n\tvirtual void draw();\n\t/// Blits this surface onto another one.\n\tvirtual void blit(SDL_Surface *surface);\n\t/// Initializes the surface's various text resources.\n\tvirtual void initText(Font *, Font *, Language *) {};\n\t/// Copies a portion of another surface into this one.\n\tvoid copy(Surface *surface);\n\t/// Draws a filled rectangle on the surface.\n\tvoid drawRect(SDL_Rect *rect, Uint8 color);\n\t/// Draws a filled rectangle on the surface.\n\tvoid drawRect(Sint16 x, Sint16 y, Sint16 w, Sint16 h, Uint8 color);\n\t/// Draws a line on the surface.\n\tvoid drawLine(Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 color);\n\t/// Draws a filled circle on the surface.\n\tvoid drawCircle(Sint16 x, Sint16 y, Sint16 r, Uint8 color);\n\t/// Draws a filled polygon on the surface.\n\tvoid drawPolygon(Sint16 *x, Sint16 *y, int n, Uint8 color);\n\t/// Draws a textured polygon on the surface.\n\tvoid drawTexturedPolygon(Sint16 *x, Sint16 *y, int n, Surface *texture, int dx, int dy);\n\t/// Draws a string on the surface.\n\tvoid drawString(Sint16 x, Sint16 y, const char *s, Uint8 color);\n\t/// Sets the surface's palette.\n\tvirtual void setPalette(const SDL_Color *colors, int firstcolor = 0, int ncolors = 256);\n\t/**\n\t * Returns the surface's 8bpp palette.\n\t * @return Pointer to the palette's colors.\n\t */\n\tSDL_Color *getPalette() const\n\t{\n\t\treturn _surface->format->palette->colors;\n\t}\n\t/// Sets the X position of the surface.\n\tvirtual void setX(int x);\n\t/**\n\t * Returns the position of the surface in the X axis.\n\t * @return X position in pixels.\n\t */\n\tint getX() const\n\t{\n\t\treturn _x;\n\t}\n\t/// Sets the Y position of the surface.\n\tvirtual void setY(int y);\n\t/**\n\t * Returns the position of the surface in the Y axis.\n\t * @return Y position in pixels.\n\t */\n\tint getY() const\n\t{\n\t\treturn _y;\n\t}\n\t/// Sets the surface's visibility.\n\tvirtual void setVisible(bool visible);\n\t/// Gets the surface's visibility.\n\tbool getVisible() const;\n\t/// Gets the cropping rectangle for the surface.\n\tSurfaceCrop getCrop() const;\n\t/**\n\t * Changes the color of a pixel in the surface, relative to\n\t * the top-left corner of the surface. Invalid positions are ignored.\n\t * @param x X position of the pixel.\n\t * @param y Y position of the pixel.\n\t * @param pixel New color for the pixel.\n\t */\n\tvoid setPixel(int x, int y, Uint8 pixel)\n\t{\n\t\tif (x < 0 || x >= getWidth() || y < 0 || y >= getHeight())\n\t\t{\n\t\t\treturn;\n\t\t}\n\t\t*getRaw(x, y) = pixel;\n\t}\n\t/**\n\t * Changes the color of a pixel in the surface and returns the\n\t * next pixel position. Useful when changing a lot of pixels in\n\t * a row, eg. manipulating images.\n\t * @param x Pointer to the X position of the pixel. Changed to the next X position in the sequence.\n\t * @param y Pointer to the Y position of the pixel. Changed to the next Y position in the sequence.\n\t * @param pixel New color for the pixel.\n\t */\n\tvoid setPixelIterative(int *x, int *y, Uint8 pixel)\n\t{\n\t\tsetPixel(*x, *y, pixel);\n\t\t(*x)++;\n\t\tif (*x == getWidth())\n\t\t{\n\t\t\t(*y)++;\n\t\t\t*x = 0;\n\t\t}\n\t}\n\t/**\n\t * Returns the color of a specified pixel in the surface.\n\t * @param x X position of the pixel.\n\t * @param y Y position of the pixel.\n\t * @return Color of the pixel, zero if the position is invalid.\n\t */\n\tUint8 getPixel(int x, int y) const\n\t{\n\t\tif (x < 0 || x >= getWidth() || y < 0 || y >= getHeight())\n\t\t{\n\t\t\treturn 0;\n\t\t}\n\t\treturn *getRaw(x, y);\n\t}\n\t/**\n\t * Returns the pointer to a specified pixel in the surface.\n\t * @param x X position of the pixel.\n\t * @param y Y position of the pixel.\n\t * @return Pointer to the pixel.\n\t */\n\tconst Uint8 *getRaw(int x, int y) const\n\t{\n\t\treturn (Uint8 *)_surface->pixels + (y * _surface->pitch + x * _surface->format->BytesPerPixel);\n\t}\n\t/**\n\t * Returns the pointer to a specified pixel in the surface.\n\t * @param x X position of the pixel.\n\t * @param y Y position of the pixel.\n\t * @return Pointer to the pixel.\n\t */\n\tUint8 *getRaw(int x, int y)\n\t{\n\t\treturn (Uint8 *)_surface->pixels + (y * _surface->pitch + x * _surface->format->BytesPerPixel);\n\t}\n\t/**\n\t * Returns the internal SDL_Surface for SDL calls.\n\t * @return Pointer to the surface.\n\t */\n\tSDL_Surface *getSurface()\n\t{\n\t\treturn _surface.get();\n\t}\n\t/**\n\t * Returns the width of the surface.\n\t * @return Width in pixels.\n\t */\n\tint getWidth() const\n\t{\n\t\treturn _width;\n\t}\n\t/// Sets the width of the surface.\n\tvirtual void setWidth(int width);\n\t/**\n\t * Returns the height of the surface.\n\t * @return Height in pixels\n\t */\n\tint getHeight() const\n\t{\n\t\treturn _height;\n\t}\n\t/// Sets the height of the surface.\n\tvirtual void setHeight(int height);\n\t/// Get surface pitch in bytes.\n\tint getPitch() const\n\t{\n\t\treturn _pitch;\n\t}\n\t/// Get pointer to buffer\n\tUint8* getBuffer()\n\t{\n\t\treturn _alignedBuffer.get();\n\t}\n\t/// Get pointer to buffer\n\tconst Uint8* getBuffer() const\n\t{\n\t\treturn _alignedBuffer.get();\n\t}\n\t/// Sets the surface's special hidden flag.\n\tvoid setHidden(bool hidden);\n\t/// Locks the surface.\n\tvoid lock();\n\t/// Unlocks the surface.\n\tvoid unlock();\n\t/// Specific blit function to blit battlescape terrain data in different shades in a fast way.\n\tstatic void blitRaw(SurfaceRaw<Uint8> dest, SurfaceRaw<const Uint8> src, int x, int y, int shade, bool half = false, int newBaseColor = 0);\n\t/// Specific blit function to blit battlescape terrain data in different shades in a fast way.\n\tvoid blitNShade(SurfaceRaw<Uint8> surface, int x, int y, int shade = 0, bool half = false, int newBaseColor = 0) const;\n\t/// Specific blit function to blit battlescape terrain data in different shades in a fast way.\n\tvoid blitNShade(SurfaceRaw<Uint8> surface, int x, int y, int shade, GraphSubset range) const;\n\t/// Invalidate the surface: force it to be redrawn\n\tvoid invalidate(bool valid = true);\n\n\t/// Sets the color of the surface.\n\tvirtual void setColor(Uint8 /*color*/) { /* empty by design */ };\n\t/// Sets the secondary color of the surface.\n\tvirtual void setSecondaryColor(Uint8 /*color*/) { /* empty by design */ };\n\t/// Sets the border colour of the surface.\n\tvirtual void setBorderColor(Uint8 /*color*/) { /* empty by design */ };\n\t/// Sets the high contrast color setting of the surface.\n\tvirtual void setHighContrast(bool /*contrast*/) { /* empty by design */ };\n};\n\n/**\n * Raw pointer to surface buffer, can be created from different sources\n */\ntemplate<typename Pixel>\nclass SurfaceRaw\n{\n\tPixel* _buffer;\n\tUint16 _width, _height, _pitch;\n\npublic:\n\t/// Default constructor\n\tSurfaceRaw() :\n\t\t_buffer{ nullptr },\n\t\t_width{ 0 },\n\t\t_height{ 0 },\n\t\t_pitch{ 0 }\n\t{\n\n\t}\n\n\t/// Copy constructor\n\tSurfaceRaw(const SurfaceRaw&) = default;\n\n\t/// Move constructor\n\tSurfaceRaw(SurfaceRaw&&) = default;\n\n\t/// Constructor\n\tSurfaceRaw(Pixel* buffer, int width, int height, int pitch) :\n\t\t_buffer{ buffer },\n\t\t_width{ static_cast<Uint16>(width) },\n\t\t_height{ static_cast<Uint16>(height) },\n\t\t_pitch{ static_cast<Uint16>(pitch) }\n\t{\n\n\t}\n\n\t/// Constructor, SFINAE enable it only for `Uint8`\n\ttemplate<typename = std::enable_if<std::is_same<Uint8, Pixel>::value, void>>\n\tSurfaceRaw(Surface* surf) : SurfaceRaw{ }\n\t{\n\t\tif (surf)\n\t\t{\n\t\t\t*this = SurfaceRaw{ surf->getBuffer(), surf->getWidth(), surf->getHeight(), surf->getPitch() };\n\t\t}\n\t}\n\n\t/// Constructor, SFINAE enable it only for `Uint8`\n\ttemplate<typename = std::enable_if<std::is_same<const Uint8, Pixel>::value, void>>\n\tSurfaceRaw(const Surface* surf) : SurfaceRaw{ }\n\t{\n\t\tif (surf)\n\t\t{\n\t\t\t*this = SurfaceRaw{ surf->getBuffer(), surf->getWidth(), surf->getHeight(), surf->getPitch() };\n\t\t}\n\t}\n\n\t/// Constructor, SFINAE enable it only for `Uint8`\n\ttemplate<typename = std::enable_if<std::is_same<Uint8, Pixel>::value, void>>\n\tSurfaceRaw(SDL_Surface* surf) : SurfaceRaw{ }\n\t{\n\t\tif (surf)\n\t\t{\n\t\t\t*this = SurfaceRaw{ (Pixel*)surf->pixels, surf->w, surf->h, surf->pitch };\n\t\t}\n\t}\n\n\t/// Constructor, SFINAE enable it only for `const Uint8`\n\ttemplate<typename = std::enable_if<std::is_same<const Uint8, Pixel>::value, void>>\n\tSurfaceRaw(const SDL_Surface* surf) : SurfaceRaw{ }\n\t{\n\t\tif (surf)\n\t\t{\n\t\t\t*this = SurfaceRaw{ (Pixel*)surf->pixels, surf->w, surf->h, surf->pitch };\n\t\t}\n\t}\n\n\t/// Constructor, SFINAE enable it only for non const `PixelType`\n\ttemplate<typename = std::enable_if<std::is_const<Pixel>::value == false, void>>\n\tSurfaceRaw(std::vector<Pixel>& vec, int width, int height) : SurfaceRaw{ vec.data(), width, height, static_cast<Uint16>(width*sizeof(Pixel)) }\n\t{\n\t\tassert((size_t)(width*height) <= vec.size() && \"Incorrect dimensions compared to vector size\");\n\t}\n\n\t/// Constructor, SFINAE enable it only for `const PixelType`\n\ttemplate<typename = std::enable_if<std::is_const<Pixel>::value, void>>\n\tSurfaceRaw(const std::vector<typename std::remove_const<Pixel>::type>& vec, int width, int height) : SurfaceRaw{ vec.data(), width, height, static_cast<Uint16>(width*sizeof(Pixel)) }\n\t{\n\t\tassert((size_t)(width*height) <= vec.size() && \"Incorrect dimensions compared to vector size\");\n\t}\n\n\t/// Constructor\n\ttemplate<int I>\n\tSurfaceRaw(Pixel (&buffer)[I], int width, int height) : SurfaceRaw{ buffer, width, height, static_cast<Uint16>(width*sizeof(Pixel)) }\n\t{\n\t\tassert(width*height <= I && \"Incorrect dimensions compared to array size\");\n\t}\n\n\t/// Assignment from nullptr\n\tSurfaceRaw& operator=(std::nullptr_t)\n\t{\n\t\t*this = SurfaceRaw{};\n\t\treturn *this;\n\t}\n\n\t/// Assignment\n\tSurfaceRaw& operator=(const SurfaceRaw&) = default;\n\n\t/// Is empty?\n\texplicit operator bool() const\n\t{\n\t\treturn _buffer;\n\t}\n\n\t/// Returns the width of the surface.\n\tint getWidth() const\n\t{\n\t\treturn _width;\n\t}\n\n\t/// Returns the height of the surface.\n\tint getHeight() const\n\t{\n\t\treturn _height;\n\t}\n\n\t/// Get surface pitch in bytes.\n\tint getPitch() const\n\t{\n\t\treturn _pitch;\n\t}\n\n\t/// Get pointer to buffer\n\tPixel* getBuffer() const\n\t{\n\t\treturn _buffer;\n\t}\n};\n\n/**\n * Helper class used to blit part of surface to another one.\n */\nclass SurfaceCrop\n{\n\tconst Surface* _surface;\n\tSDL_Rect _crop;\n\tint _x, _y;\n\npublic:\n\t/// Default constructor\n\tSurfaceCrop() : _surface{ nullptr }, _crop{ }, _x{ }, _y{ }\n\t{\n\n\t}\n\n\t/// Constructor\n\tSurfaceCrop(const Surface* surf) : _surface{ surf }, _crop{ }, _x{ surf->getX() }, _y{ surf->getY() }\n\t{\n\n\t}\n\n\t/// Get crop rectangle.\n\tSDL_Rect* getCrop()\n\t{\n\t\treturn &_crop;\n\t}\n\n\t/// Get Surface.\n\tconst Surface* getSurface()\n\t{\n\t\treturn _surface;\n\t}\n\n\t/// Sets the X position of the surface.\n\tvoid setX(int x)\n\t{\n\t\t_x = x;\n\t}\n\n\t/// Returns the position of the surface in the X axis.\n\tint getX() const\n\t{\n\t\treturn _x;\n\t}\n\n\t/// Sets the Y position of the surface.\n\tvoid setY(int y)\n\t{\n\t\t_y = y;\n\t}\n\n\t/// Returns the position of the surface in the Y axis.\n\tint getY() const\n\t{\n\t\treturn _y;\n\t}\n\n\t/// Blit Cropped surface to another surface.\n\tvoid blit(Surface* dest);\n};\n\n}\n"
  },
  {
    "path": "src/Engine/SurfaceSet.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"SurfaceSet.h\"\n#include <climits>\n#include \"Surface.h\"\n#include \"FileMap.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Sets up a new empty surface set for frames of the specified size.\n * @param width Frame width in pixels.\n * @param height Frame height in pixels.\n */\nSurfaceSet::SurfaceSet(int width, int height) : _width(width), _height(height), _sharedFrames(INT_MAX)\n{\n\n}\n\n/**\n * Deletes the images from memory.\n */\nSurfaceSet::~SurfaceSet()\n{\n\n}\n\n/**\n * Loads the contents of an X-Com set of PCK/TAB image files\n * into the surface. The PCK file contains an RLE compressed\n * image, while the TAB file contains the offsets to each\n * frame in the image.\n * @param pck Filename of the PCK image.\n * @param tab Filename of the TAB offsets.\n * @sa http://www.ufopaedia.org/index.php?title=Image_Formats#PCK\n */\nvoid SurfaceSet::loadPck(const std::string &pck, const std::string &tab)\n{\n\t_frames.clear();\n\n\tint nframes = 0;\n\n\t// Load TAB and get image offsets\n\tif (!tab.empty())\n\t{\n\t\tauto offsetFile = FileMap::getIStream(tab);\n\t\tstd::streampos begin, end;\n\t\tbegin = offsetFile->tellg();\n\t\tint off;\n\t\toffsetFile->read((char*)&off, sizeof(off));\n\t\toffsetFile->seekg(0, std::ios::end);\n\t\tend = offsetFile->tellg();\n\t\tint size = end - begin;\n\t\t// 16-bit offsets\n\t\tif (off != 0)\n\t\t{\n\t\t\tnframes = size / 2;\n\t\t}\n\t\t// 32-bit offsets\n\t\telse\n\t\t{\n\t\t\tnframes = size / 4;\n\t\t}\n\t\tfor (int frame = 0; frame < nframes; ++frame)\n\t\t{\n\t\t\t_frames.push_back(Surface(_width, _height));\n\t\t}\n\t}\n\telse\n\t{\n\t\tnframes = 1;\n\t\t_frames.push_back(Surface(_width, _height));\n\t}\n\n\tauto imgFile = FileMap::getIStream(pck);\n\tUint8 value;\n\n\tfor (int frame = 0; frame < nframes; ++frame)\n\t{\n\t\tint x = 0, y = 0;\n\n\t\t// Lock the surface\n\t\t_frames[frame].lock();\n\n\t\timgFile->read((char*)&value, 1);\n\t\tfor (int i = 0; i < value; ++i)\n\t\t{\n\t\t\tfor (int j = 0; j < _width; ++j)\n\t\t\t{\n\t\t\t\t_frames[frame].setPixelIterative(&x, &y, 0);\n\t\t\t}\n\t\t}\n\n\t\twhile (imgFile->read((char*)&value, 1) && value != 255)\n\t\t{\n\t\t\tif (value == 254)\n\t\t\t{\n\t\t\t\timgFile->read((char*)&value, 1);\n\t\t\t\tfor (int i = 0; i < value; ++i)\n\t\t\t\t{\n\t\t\t\t\t_frames[frame].setPixelIterative(&x, &y, 0);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_frames[frame].setPixelIterative(&x, &y, value);\n\t\t\t}\n\t\t}\n\n\t\t// Unlock the surface\n\t\t_frames[frame].unlock();\n\t}\n}\n\n/**\n * Loads the contents of an X-Com DAT image file into the\n * surface. Unlike the PCK, a DAT file is an uncompressed\n * image with no offsets so these have to be figured out\n * manually, usually by splitting the image into equal portions.\n * @param filename Filename of the DAT image.\n * @sa http://www.ufopaedia.org/index.php?title=Image_Formats#SCR_.26_DAT\n */\nvoid SurfaceSet::loadDat(const std::string &filename)\n{\n\tint nframes = 0;\n\n\tauto imgFile = FileMap::getIStream(filename);\n\timgFile->seekg(0, std::ios::end);\n\tstd::streamoff size = imgFile->tellg();\n\timgFile->seekg(0, std::ios::beg);\n\n\tnframes = (int)size / (_width * _height);\n\n\t_frames.resize(nframes);\n\tfor (int i = 0; i < nframes; ++i)\n\t{\n\t\t_frames[i] = Surface(_width, _height);\n\t}\n\n\tUint8 value;\n\tint x = 0, y = 0, frame = 0;\n\n\t// Lock the surface\n\t_frames[frame].lock();\n\n\twhile (imgFile->read((char*)&value, 1))\n\t{\n\t\t_frames[frame].setPixelIterative(&x, &y, value);\n\n\t\tif (y >= _height)\n\t\t{\n\t\t\t// Unlock the surface\n\t\t\t_frames[frame].unlock();\n\n\t\t\tframe++;\n\t\t\tx = 0;\n\t\t\ty = 0;\n\n\t\t\tif (frame >= nframes)\n\t\t\t\tbreak;\n\t\t\telse\n\t\t\t\t_frames[frame].lock();\n\t\t}\n\t}\n}\n\n/**\n * Returns a particular frame from the surface set.\n * @param i Frame number in the set.\n * @return Pointer to the respective surface.\n */\nSurface *SurfaceSet::getFrame(int i)\n{\n\tif ((size_t)i < _frames.size())\n\t{\n\t\tif (_frames[i])\n\t\t{\n\t\t\treturn &_frames[i];\n\t\t}\n\t}\n\treturn nullptr;\n}\n\n/**\n * Returns a particular frame from the surface set.\n * @param i Frame number in the set.\n * @return Pointer to the respective surface.\n */\nconst Surface *SurfaceSet::getFrame(int i) const\n{\n\tif ((size_t)i < _frames.size())\n\t{\n\t\tif (_frames[i])\n\t\t{\n\t\t\treturn &_frames[i];\n\t\t}\n\t}\n\treturn nullptr;\n}\n\n/**\n * Creates and returns a particular frame in the surface set.\n * @param i Frame number in the set.\n * @return Pointer to the respective surface.\n */\nSurface *SurfaceSet::addFrame(int i)\n{\n\tassert(i >= 0 && \"Negative indexes are not supported in SurfaceSet\");\n\tif ((size_t)i < _frames.size())\n\t{\n\t\t//nothing\n\t}\n\telse\n\t{\n\t\t_frames.resize(i + 1);\n\t}\n\t_frames[i] = Surface(_width, _height);\n\treturn &_frames[i];\n}\n\n/**\n * Returns the full width of a frame in the set.\n * @return Width in pixels.\n */\nint SurfaceSet::getWidth() const\n{\n\treturn _width;\n}\n\n/**\n * Returns the full height of a frame in the set.\n * @return Height in pixels.\n */\nint SurfaceSet::getHeight() const\n{\n\treturn _height;\n}\n\n/**\n * Set number of shared frame indexes that are accessible for all mods.\n */\nvoid SurfaceSet::setMaxSharedFrames(int i)\n{\n\tif (i >= 0)\n\t{\n\t\t_sharedFrames = i;\n\t}\n\telse\n\t{\n\t\t_sharedFrames = 0;\n\t}\n}\n\n/**\n * Gets number of shared frame indexes that are accessible for all mods.\n */\nint SurfaceSet::getMaxSharedFrames() const\n{\n\treturn _sharedFrames;\n}\n\n/**\n * Returns the total amount of frames currently\n * stored in the set.\n * @return Number of frames.\n */\nsize_t SurfaceSet::getTotalFrames() const\n{\n\treturn _frames.size();\n}\n\n/**\n * Replaces a certain amount of colors in all of the frames.\n * @param colors Pointer to the set of colors.\n * @param firstcolor Offset of the first color to replace.\n * @param ncolors Amount of colors to replace.\n */\nvoid SurfaceSet::setPalette(const SDL_Color *colors, int firstcolor, int ncolors)\n{\n\tfor (size_t i = 0; i < _frames.size(); ++i)\n\t{\n\t\tif (_frames[i])\n\t\t\t_frames[i].setPalette(colors, firstcolor, ncolors);\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Engine/SurfaceSet.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include <vector>\n#include <string>\n#include <SDL.h>\n\nnamespace OpenXcom\n{\n\nclass Surface;\n\n/**\n * Container of a set of surfaces.\n * Used to manage single images that contain series of\n * frames inside, like animated sprites, making them easier\n * to access without constant cropping.\n */\nclass SurfaceSet\n{\nprivate:\n\tstd::vector<Surface> _frames;\n\tint _width, _height;\n\tint _sharedFrames;\n\npublic:\n\t/// Crates a surface set with frames of the specified size.\n\tSurfaceSet(int width, int height);\n\t/// Creates a surface set from an existing one.\n\tSurfaceSet(const SurfaceSet& other) = default;\n\t/// Creates a surface set from an existing one.\n\tSurfaceSet(SurfaceSet&& other) = default;\n\t/// Cleans up the surface set.\n\t~SurfaceSet();\n\t/// Assignment operator.\n\tSurfaceSet& operator=(const SurfaceSet& other) = default;\n\t/// Assignment operator.\n\tSurfaceSet& operator=(SurfaceSet&& other) = default;\n\n\t/// Loads an X-Com set of PCK/TAB image files.\n\tvoid loadPck(const std::string &pck, const std::string &tab = \"\");\n\t/// Loads an X-Com DAT image file.\n\tvoid loadDat(const std::string &filename);\n\t/// Gets a particular frame from the set.\n\tSurface *getFrame(int i);\n\t/// Gets a particular frame from the set.\n\tconst Surface *getFrame(int i) const;\n\t/// Creates a new surface and returns a pointer to it.\n\tSurface *addFrame(int i);\n\t/// Gets the width of all frames.\n\tint getWidth() const;\n\t/// Gets the height of all frames.\n\tint getHeight() const;\n\n\t/// Set number of shared frame indexes that are accessible for all mods.\n\tvoid setMaxSharedFrames(int i);\n\t/// Gets number of shared frame indexes that are accessible for all mods.\n\tint getMaxSharedFrames() const;\n\n\t/// Gets the total frames in the set.\n\tsize_t getTotalFrames() const;\n\t/// Sets the surface set's palette.\n\tvoid setPalette(const SDL_Color *colors, int firstcolor = 0, int ncolors = 256);\n};\n\n}\n"
  },
  {
    "path": "src/Engine/Timer.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Timer.h\"\n#include \"Game.h\"\n#include \"Options.h\"\n\nnamespace OpenXcom\n{\n\nnamespace\n{\n\nconst Uint32 accurate = 4;\nUint32 slowTick()\n{\n\tstatic Uint32 old_time = SDL_GetTicks();\n\tstatic Uint64 false_time = static_cast<Uint64>(old_time) << accurate;\n\tUint64 new_time = ((Uint64)SDL_GetTicks()) << accurate;\n\tfalse_time += (new_time - old_time) / Timer::gameSlowSpeed;\n\told_time = new_time;\n\treturn false_time >> accurate;\n}\n\n}//namespace\n\nUint32 Timer::gameSlowSpeed = 1;\nint Timer::maxFrameSkip = 8; // this is a pretty good default at 60FPS.\n\n\n/**\n * Initializes a new timer with a set interval.\n * @param interval Time interval in milliseconds.\n * @param frameSkipping Use frameskipping.\n */\nTimer::Timer(Uint32 interval, bool frameSkipping) : _start(0), _frameSkipStart(0), _interval(interval), _running(false), _frameSkipping(frameSkipping), _state(0), _surface(0)\n{\n\tTimer::maxFrameSkip = Options::maxFrameSkip;\n}\n\n/**\n *\n */\nTimer::~Timer()\n{\n}\n\n/**\n * Starts the timer running and counting time.\n */\nvoid Timer::start()\n{\n\t_frameSkipStart = _start = slowTick();\n\t_running = true;\n}\n\n/**\n * Stops the timer from running.\n */\nvoid Timer::stop()\n{\n\t_start = 0;\n\t_running = false;\n}\n\n/**\n * Returns the time passed since the last interval.\n * @return Time in milliseconds.\n */\nUint32 Timer::getTime() const\n{\n\tif (_running)\n\t{\n\t\treturn slowTick() - _start;\n\t}\n\treturn 0;\n}\n\n/**\n * Returns if the timer has been started.\n * @return Running state.\n */\nbool Timer::isRunning() const\n{\n\treturn _running;\n}\n\n/**\n * The timer keeps calculating the passed time while it's running,\n * calling the respective action handler whenever the set interval passes.\n * @param state State that the action handler belongs to.\n * @param surface Surface that the action handler belongs to.\n */\nvoid Timer::think(State* state, Surface* surface)\n{\n\tSint64 now = slowTick(); // must be signed to permit negative numbers\n\tGame *game = state ? state->_game : 0; // this is used to make sure we stop calling *_state on *state in the loop once *state has been popped and deallocated\n\t//assert(!game || game->isState(state));\n\n\tif (_running)\n\t{\n\t\tif ((now - _frameSkipStart) >= _interval)\n\t\t{\n\t\t\tfor (int i = 0; i <= maxFrameSkip && isRunning() && (now - _frameSkipStart) >= _interval; ++i)\n\t\t\t{\n\t\t\t\tif (state != 0 && _state != 0)\n\t\t\t\t{\n\t\t\t\t\t(state->*_state)();\n\t\t\t\t}\n\t\t\t\t_frameSkipStart += _interval;\n\t\t\t\t// breaking here after one iteration effectively returns this function to its old functionality:\n\t\t\t\tif (!game || !_frameSkipping || !game->isState(state)) break; // if game isn't set, we can't verify *state\n\t\t\t}\n\n\t\t\tif (_running && surface != 0 && _surface != 0)\n\t\t\t{\n\t\t\t\t(surface->*_surface)();\n\t\t\t}\n\t\t\t_start = slowTick();\n\t\t\tif (_start > _frameSkipStart) _frameSkipStart = _start; // don't play animations in ffwd to catch up :P\n\t\t}\n\t}\n}\n\n/**\n * Changes the timer's interval to a new value.\n * @param interval Interval in milliseconds.\n */\nvoid Timer::setInterval(Uint32 interval)\n{\n\t_interval = interval;\n}\n\n/**\n * Sets a state function for the timer to call every interval.\n * @param handler Event handler.\n */\nvoid Timer::onTimer(StateHandler handler)\n{\n\t_state = handler;\n}\n\n/**\n * Sets a surface function for the timer to call every interval.\n * @param handler Event handler.\n */\nvoid Timer::onTimer(SurfaceHandler handler)\n{\n\t_surface = handler;\n}\n\n}\n"
  },
  {
    "path": "src/Engine/Timer.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <SDL.h>\n#include \"State.h\"\n#include \"Surface.h\"\n\nnamespace OpenXcom\n{\n\ntypedef void (State::* StateHandler)();\ntypedef void (Surface::* SurfaceHandler)();\n\n/**\n * Timer used to run code in fixed intervals.\n * Used for code that should run at the same fixed interval\n * in various machines, based on milliseconds instead of CPU cycles.\n */\nclass Timer\n{\npublic:\n\tstatic int maxFrameSkip;\n\tstatic Uint32 gameSlowSpeed;\n\nprivate:\n\tUint32 _start;\n\tUint32 _frameSkipStart;\n\tint _interval;\n\tbool _running;\n\tbool _frameSkipping;\n\tStateHandler _state;\n\tSurfaceHandler _surface;\npublic:\n\t/// Creates a stopped timer.\n\tTimer(Uint32 interval, bool frameSkipping = false);\n\t/// Cleans up the timer.\n\t~Timer();\n\t/// Starts the timer.\n\tvoid start();\n\t/// Stops the timer.\n\tvoid stop();\n\t/// Gets the current time interval.\n\tUint32 getTime() const;\n\t/// Gets if the timer's running.\n\tbool isRunning() const;\n\t/// Advances the timer.\n\tvoid think(State* state, Surface* surface);\n\t/// Sets the timer's interval.\n\tvoid setInterval(Uint32 interval);\n\t/// Hooks a state action handler to the timer interval.\n\tvoid onTimer(StateHandler handler);\n\t/// Hooks a surface action handler to the timer interval.\n\tvoid onTimer(SurfaceHandler handler);\n};\n\n}\n"
  },
  {
    "path": "src/Engine/TouchState.cpp",
    "content": "/*\n * Copyright 2010-2025 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"TouchState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/ToggleTextButton.h\"\n\nnamespace OpenXcom\n{\n\nvoid TouchState::touchComponentsCreate(Text* txtTitlePtr, bool hideGroup100, int horizontalOffset, int verticalOffset)\n{\n\t// Reset touch flags\n\t_game->resetTouchButtonFlags();\n\n\tif (!Options::oxceBaseTouchButtons)\n\t\treturn;\n\n\t_hideGroup100 = hideGroup100;\n\t_txtTitlePtr = txtTitlePtr;\n\n\t_btnTouch = new TextButton(40, 16, horizontalOffset + 273, 7 + verticalOffset);\n\n\t_btn1     = new       TextButton(25, 16, horizontalOffset + 61 + 0 * 26, 7 + verticalOffset);\n\t_btn10    = new       TextButton(25, 16, horizontalOffset + 61 + 1 * 26, 7 + verticalOffset);\n\t_btn100   = new       TextButton(25, 16, horizontalOffset + 61 + 2 * 26, 7 + verticalOffset);\n\t_owner100 = _btn1;\n\n\t_btnLMB   = new       TextButton(25, 16, horizontalOffset + 65 + 3 * 26, 7 + verticalOffset);\n\t_btnRMB   = new       TextButton(25, 16, horizontalOffset + 65 + 4 * 26, 7 + verticalOffset);\n\t_btnMMB   = new       TextButton(25, 16, horizontalOffset + 65 + 5 * 26, 7 + verticalOffset);\n\t_ownerLRM = _btnLMB;\n\n\t_btnCtrl  = new ToggleTextButton(27, 16, horizontalOffset + 69 + 6 * 26, 7 + verticalOffset);\n\t_btnAlt   = new ToggleTextButton(27, 16, horizontalOffset + 71 + 7 * 26, 7 + verticalOffset);\n\t_btnShift = new ToggleTextButton(32, 16, horizontalOffset + 73 + 8 * 26, 7 + verticalOffset);\n}\n\nvoid TouchState::touchComponentsAdd(const std::string& id, const std::string& category, Surface* parent)\n{\n\tif (!Options::oxceBaseTouchButtons)\n\t\treturn;\n\n\tadd(_btnTouch, \"touchButton\", category, parent);\n\n\tadd(_btn1, id, category);\n\tadd(_btn10, id, category);\n\tadd(_btn100, id, category);\n\n\tadd(_btnLMB, id, category);\n\tadd(_btnRMB, id, category);\n\tadd(_btnMMB, id, category);\n\n\tadd(_btnCtrl, id, category);\n\tadd(_btnAlt, id, category);\n\tadd(_btnShift, id, category);\n}\n\nvoid TouchState::touchComponentsConfigure()\n{\n\tif (!Options::oxceBaseTouchButtons)\n\t\treturn;\n\n\t_btn1->setText(tr(\"STR_BUTTON_1\"));\n\t_btn10->setText(tr(\"STR_BUTTON_10\"));\n\t_btn100->setText(tr(\"STR_BUTTON_100\"));\n\t_btnLMB->setText(tr(\"STR_BUTTON_LMB\"));\n\t_btnRMB->setText(tr(\"STR_BUTTON_RMB\"));\n\t_btnMMB->setText(tr(\"STR_BUTTON_MMB\"));\n\t_btnCtrl->setText(tr(\"STR_BUTTON_CTRL\"));\n\t_btnAlt->setText(tr(\"STR_BUTTON_ALT\"));\n\t_btnShift->setText(tr(\"STR_BUTTON_SHIFT\"));\n\n\t_btn1->setGroup(&_owner100);\n\t_btn10->setGroup(&_owner100);\n\t_btn100->setGroup(&_owner100);\n\t_btnLMB->setGroup(&_ownerLRM);\n\t_btnRMB->setGroup(&_ownerLRM);\n\t_btnMMB->setGroup(&_ownerLRM);\n\n\t_btn1->onMousePress((ActionHandler)&TouchState::btnGroup100Press);\n\t_btn10->onMousePress((ActionHandler)&TouchState::btnGroup100Press);\n\t_btn100->onMousePress((ActionHandler)&TouchState::btnGroup100Press);\n\t_btnLMB->onMousePress((ActionHandler)&TouchState::btnGroupLRMPress);\n\t_btnRMB->onMousePress((ActionHandler)&TouchState::btnGroupLRMPress);\n\t_btnMMB->onMousePress((ActionHandler)&TouchState::btnGroupLRMPress);\n\n\t_btn1->setVisible(false);\n\t_btn10->setVisible(false);\n\t_btn100->setVisible(false);\n\t_btnLMB->setVisible(false);\n\t_btnRMB->setVisible(false);\n\t_btnMMB->setVisible(false);\n\t_btnCtrl->setVisible(false);\n\t_btnAlt->setVisible(false);\n\t_btnShift->setVisible(false);\n\n\t_btnTouch->setText(tr(\"STR_BUTTON_TOUCH\"));\n\t_btnTouch->setVisible(Options::oxceBaseTouchButtons);\n\t_btnTouch->onMouseClick((ActionHandler)&TouchState::btnTouchClick);\n\n\t_btnCtrl->onMouseClick((ActionHandler)&TouchState::btnCtrlClick);\n\t_btnAlt->onMouseClick((ActionHandler)&TouchState::btnAltClick);\n\t_btnShift->onMouseClick((ActionHandler)&TouchState::btnShiftClick);\n}\n\nvoid TouchState::touchComponentsRefresh()\n{\n\tif (!Options::oxceBaseTouchButtons)\n\t\treturn;\n\n\t_owner100 = _game->getScrollStep() == 100 ? _btn100 : (_game->getScrollStep() == 10 ? _btn10 : _btn1);\n\n\t_ownerLRM = _game->getMMBFlag() ? _btnMMB : (_game->getRMBFlag() ? _btnRMB : _btnLMB);\n\n\t_btnCtrl->setPressed(_game->getCtrlPressedFlag());\n\t_btnAlt->setPressed(_game->getAltPressedFlag());\n\t_btnShift->setPressed(_game->getShiftPressedFlag());\n}\n\nvoid TouchState::btnTouchClick(Action* action)\n{\n\tif (_txtTitlePtr)\n\t{\n\t\t_txtTitlePtr->setVisible(false);\n\t}\n\t_btnTouch->setVisible(false);\n\n\tif (!_hideGroup100)\n\t{\n\t\t_btn1->setVisible(true);\n\t\t_btn10->setVisible(true);\n\t\t_btn100->setVisible(true);\n\t}\n\t_btnCtrl->setVisible(true);\n\t_btnAlt->setVisible(true);\n\t_btnShift->setVisible(true);\n\t_btnLMB->setVisible(true);\n\t_btnRMB->setVisible(true);\n\t_btnMMB->setVisible(true);\n}\n\nvoid TouchState::btnGroup100Press(Action*)\n{\n\tint step = (_owner100 == _btn100 ? 100 : (_owner100 == _btn10 ? 10 : 1));\n\t_game->setScrollStep(step);\n}\n\nvoid TouchState::btnGroupLRMPress(Action*)\n{\n\t_game->setRMBFlag(_ownerLRM == _btnRMB);\n\t_game->setMMBFlag(_ownerLRM == _btnMMB);\n}\n\nvoid TouchState::btnCtrlClick(Action*)\n{\n\t_game->setCtrlPressedFlag(_btnCtrl->getPressed());\n}\n\nvoid TouchState::btnAltClick(Action*)\n{\n\t_game->setAltPressedFlag(_btnAlt->getPressed());\n}\n\nvoid TouchState::btnShiftClick(Action*)\n{\n\t_game->setShiftPressedFlag(_btnShift->getPressed());\n}\n\n}\n"
  },
  {
    "path": "src/Engine/TouchState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2025 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"State.h\"\n\nnamespace OpenXcom\n{\n\nclass Text;\nclass TextButton;\nclass ToggleTextButton;\n\n/**\n * A State with touch buttons support.\n */\n\nclass TouchState : public State\n{\nprotected:\n\tbool _hideGroup100;\n\tText *_txtTitlePtr;\n\tTextButton *_btnTouch;\n\tTextButton *_btn1, *_btn10, *_btn100, *_owner100;\n\tTextButton *_btnLMB, *_btnRMB, *_btnMMB, *_ownerLRM;\n\tToggleTextButton *_btnCtrl, *_btnAlt, *_btnShift;\npublic:\n\t/// Creates a new state.\n\tTouchState() = default;\n\tvoid touchComponentsCreate(Text* txtTitlePtr, bool hideGroup100 = false, int horizontalOffset = 0, int verticalOffset = 0);\n\tvoid touchComponentsAdd(const std::string& id, const std::string& category, Surface* parent);\n\tvoid touchComponentsConfigure();\n\t/// Cleans up the state.\n\tvirtual ~TouchState() = default;\n\n\tvoid touchComponentsRefresh();\n\n\t/// Handler for clicking the Touch button.\n\tvoid btnTouchClick(Action* action);\n\t/// Handler for clicking 1-10-100 group buttons.\n\tvoid btnGroup100Press(Action* action);\n\t/// Handler for clicking LMB-RMB-MMB group buttons.\n\tvoid btnGroupLRMPress(Action* action);\n\t/// Handler for clicking the CTRL button.\n\tvoid btnCtrlClick(Action* action);\n\t/// Handler for clicking the ALT button.\n\tvoid btnAltClick(Action* action);\n\t/// Handler for clicking the SHIFT button.\n\tvoid btnShiftClick(Action* action);\n};\n\n}\n"
  },
  {
    "path": "src/Engine/Unicode.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Unicode.h\"\n#include <sstream>\n#include <locale>\n#include <stdexcept>\n#include <cstring>\n#include <assert.h>\n#include \"Logger.h\"\n#include \"Exception.h\"\n\n#ifdef _WIN32\n#ifndef NOMINMAX\n#define NOMINMAX\n#endif\n#define WIN32_LEAN_AND_MEAN\n#include <windows.h>\n#include <shlwapi.h>\n#else\n\n#if defined(__CYGWIN__)\n#include <algorithm>\n#endif\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#endif\n\nnamespace OpenXcom\n{\n\nstd::string OXCE_CURRENCY_SYMBOL = \"$\";\n\nnamespace Unicode\n{\n\nstd::locale utf8;\n\n/**\n * Store a UTF-8 locale to use when dealing with character conversions.\n * Windows doesn't have a UTF-8 locale so we just use its APIs directly.\n */\nvoid getUtf8Locale()\n{\n\tstd::string loc;\n#ifndef _WIN32\n\t// Find any UTF-8 locale\n\tFILE *fp = popen(\"locale -a\", \"r\");\n\tif (fp != NULL)\n\t{\n\t\tchar buf[50];\n\t\twhile (fgets(buf, sizeof(buf), fp) != NULL)\n\t\t{\n\t\t\tif (strstr(buf, \".utf8\") != NULL ||\n\t\t\t\tstrstr(buf, \".UTF-8\") != NULL)\n\t\t\t{\n\t\t\t\t// Trim newline\n\t\t\t\tsize_t end = strlen(buf) - 1;\n\t\t\t\tif (buf[end] == '\\n')\n\t\t\t\t\tbuf[end] = '\\0';\n\n\t\t\t\tloc = buf;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tpclose(fp);\n\t}\n#endif\n\t// Try a UTF-8 locale (or default if none was found)\n\ttry\n\t{\n\t\tLog(LOG_INFO) << \"Attempted locale: \" << loc.c_str();\n\t\tutf8 = std::locale(loc.c_str());\n\t}\n\tcatch (const std::runtime_error &)\n\t{\n\t\t// Well we're stuck with the C locale, hope for the best\n\t}\n\tLog(LOG_INFO) << \"Detected locale: \" << utf8.name();\n}\n\n/**\n * Takes a Unicode 32-bit string and converts it\n * to a 8-bit string encoded in UTF-8.\n * Used for rendering text.\n * @note Adapted from https://stackoverflow.com/a/148766/2683561\n * @param src UTF-8 string.\n * @return Unicode string.\n */\nUString convUtf8ToUtf32(const std::string &src)\n{\n\tif (src.empty())\n\t\treturn UString();\n\tUString out;\n\tout.reserve(src.size());\n\tUCode codepoint = 0;\n\tfor (std::string::const_iterator i = src.begin(); i != src.end();)\n\t{\n\t\tunsigned char ch = static_cast<unsigned char>(*i);\n\t\tif (ch <= 0x7f)\n\t\t\tcodepoint = ch;\n\t\telse if (ch <= 0xbf)\n\t\t\tcodepoint = (codepoint << 6) | (ch & 0x3f);\n\t\telse if (ch <= 0xdf)\n\t\t\tcodepoint = ch & 0x1f;\n\t\telse if (ch <= 0xef)\n\t\t\tcodepoint = ch & 0x0f;\n\t\telse\n\t\t\tcodepoint = ch & 0x07;\n\t\t++i;\n\t\tif (i == src.end() || ((*i & 0xc0) != 0x80 && codepoint <= 0x10ffff))\n\t\t{\n\t\t\tout.append(1, codepoint);\n\t\t}\n\t}\n\treturn out;\n}\n\n/**\n * Takes a Unicode 32-bit string and converts it\n * to a 8-bit string encoded in UTF-8.\n * Used for rendering text.\n * @note Adapted from https://stackoverflow.com/a/148766/2683561\n * @param src Unicode string.\n * @return UTF-8 string.\n */\nstd::string convUtf32ToUtf8(const UString &src)\n{\n\tif (src.empty())\n\t\treturn std::string();\n\tstd::string out;\n\tout.reserve(src.size());\n\tfor (UString::const_iterator i = src.begin(); i != src.end(); ++i)\n\t{\n\t\tUCode codepoint = *i;\n\t\tif (codepoint <= 0x7f)\n\t\t{\n\t\t\tout.append(1, static_cast<char>(codepoint));\n\t\t}\n\t\telse if (codepoint <= 0x7ff)\n\t\t{\n\t\t\tout.append(1, static_cast<char>(0xc0 | ((codepoint >> 6) & 0x1f)));\n\t\t\tout.append(1, static_cast<char>(0x80 | (codepoint & 0x3f)));\n\t\t}\n\t\telse if (codepoint <= 0xffff)\n\t\t{\n\t\t\tout.append(1, static_cast<char>(0xe0 | ((codepoint >> 12) & 0x0f)));\n\t\t\tout.append(1, static_cast<char>(0x80 | ((codepoint >> 6) & 0x3f)));\n\t\t\tout.append(1, static_cast<char>(0x80 | (codepoint & 0x3f)));\n\t\t}\n\t\telse\n\t\t{\n\t\t\tout.append(1, static_cast<char>(0xf0 | ((codepoint >> 18) & 0x07)));\n\t\t\tout.append(1, static_cast<char>(0x80 | ((codepoint >> 12) & 0x3f)));\n\t\t\tout.append(1, static_cast<char>(0x80 | ((codepoint >> 6) & 0x3f)));\n\t\t\tout.append(1, static_cast<char>(0x80 | (codepoint & 0x3f)));\n\t\t}\n\t}\n\treturn out;\n}\n\n/**\n * Takes a wide-character string and converts it to a\n * multibyte 8-bit string in a given encoding.\n * Used for Win32 APIs.\n * @param src Wide-character string.\n * @param cp Codepage of the destination string.\n * @return Multibyte string.\n */\nstd::string convWcToMb(const std::wstring &src, unsigned int cp)\n{\n\tif (src.empty())\n\t\treturn std::string();\n#ifdef _WIN32\n\tint size = WideCharToMultiByte(cp, 0, &src[0], (int)src.size(), NULL, 0, NULL, NULL);\n\tstd::string str(size, 0);\n\tWideCharToMultiByte(cp, 0, &src[0], (int)src.size(), &str[0], size, NULL, NULL);\n\treturn str;\n#elif defined(__CYGWIN__)\n\t(void)cp;\n\tassert(sizeof(wchar_t) == sizeof(Uint16));\n\tUString ustr(src.size(), 0);\n\tstd::transform(src.begin(), src.end(), ustr.begin(),\n\t\t[](wchar_t c) -> UCode\n\t\t{\n\t\t\t//TODO: dropping surrogates, do proper implementation when someone will need that range\n\t\t\tif (c <= 0xD7FF || c >= 0xE000)\n\t\t\t{\n\t\t\t\treturn c;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn '?';\n\t\t\t}\n\t\t}\n\t);\n\treturn convUtf32ToUtf8(ustr);\n#else\n\t(void)cp;\n\tassert(sizeof(wchar_t) == sizeof(UCode));\n\tconst UString *ustr = reinterpret_cast<const UString*>(&src);\n\treturn convUtf32ToUtf8(*ustr);\n#endif\n}\n\n/**\n * Takes a multibyte 8-bit string in a given encoding\n * and converts it to a wide-character string.\n * Used for Win32 APIs.\n * @param src Multibyte string.\n * @param cp Codepage of the source string.\n * @return Wide-character string.\n */\nstd::wstring convMbToWc(const std::string &src, unsigned int cp)\n{\n\tif (src.empty())\n\t\treturn std::wstring();\n#ifdef _WIN32\n\tint size = MultiByteToWideChar(cp, 0, &src[0], (int)src.size(), NULL, 0);\n\tstd::wstring wstr(size, 0);\n\tMultiByteToWideChar(cp, 0, &src[0], (int)src.size(), &wstr[0], size);\n\treturn wstr;\n#elif defined(__CYGWIN__)\n\t(void)cp;\n\tassert(sizeof(wchar_t) == sizeof(Uint16));\n\tconst UString ustr = convUtf8ToUtf32(src);\n\n\tstd::wstring wstr(ustr.size(), 0);\n\tstd::transform(ustr.begin(), ustr.end(), wstr.begin(),\n\t\t[](UCode c) -> wchar_t\n\t\t{\n\t\t\t//TODO: dropping surrogates, do proper implementation when someone will need that range\n\t\t\tif (c <= 0xD7FF || (c >= 0xE000 && c <= 0xFFFF))\n\t\t\t{\n\t\t\t\treturn c;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn '?';\n\t\t\t}\n\t\t}\n\t);\n\treturn wstr;\n#else\n\t(void)cp;\n\tassert(sizeof(wchar_t) == sizeof(UCode));\n\tUString ustr = convUtf8ToUtf32(src);\n\tconst std::wstring *wstr = reinterpret_cast<const std::wstring*>(&ustr);\n\treturn *wstr;\n#endif\n}\n\n\n/**\n * Iterate pointer range without checking for correct range\n * @param begin_ptr In/Out current pointer\n * @param end End pointer\n * @param callback_1 callback for ASCII char\n * @param callback_2 callback for 2byte UTF code point\n * @param callback_3 callback for 3byte UTF code point\n * @param callback_4 callback for 4byte UTF code point\n * @return True if iteration reach end, False if function find UTF8 error or callback request ending\n */\ntemplate<typename F1, typename F2, typename F3, typename F4>\nstatic bool iterateUTF8CodePointsUnsafe(const unsigned char** begin_ptr, const unsigned char* end, F1 callback_1, F2 callback_2, F3 callback_3, F4 callback_4)\n{\n\tauto begin = *begin_ptr;\n\twhile (begin < end) {\n\t\tif (begin[0] < 0x80) {\n\t\t\t/* 0xxxxxxx */\n\t\t\tif (false == callback_1(begin[0]))\n\t\t\t{\n\t\t\t\t*begin_ptr = begin;\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tbegin += 1;\n\t\t} else if ((begin[0] & 0xe0) == 0xc0) {\n\t\t\t/* 110XXXXx 10xxxxxx */\n\t\t\tif ((begin[1] & 0xc0) != 0x80 ||\n\t\t\t\tfalse == callback_2(begin[0], begin[1]))\n\t\t\t{\n\t\t\t\t*begin_ptr = begin;\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tbegin += 2;\n\t\t} else if ((begin[0] & 0xf0) == 0xe0) {\n\t\t\t/* 1110XXXX 10Xxxxxx 10xxxxxx */\n\t\t\tif ((begin[1] & 0xc0) != 0x80 ||\n\t\t\t\t(begin[2] & 0xc0) != 0x80 ||\n\t\t\t\tfalse == callback_3(begin[0], begin[1], begin[2]))\n\t\t\t{\n\t\t\t\t*begin_ptr = begin;\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tbegin +=  3;\n\t\t} else if ((begin[0] & 0xf8) == 0xf0) {\n\t\t\t/* 11110XXX 10XXxxxx 10xxxxxx 10xxxxxx */\n\t\t\tif ((begin[1] & 0xc0) != 0x80 ||\n\t\t\t\t(begin[2] & 0xc0) != 0x80 ||\n\t\t\t\t(begin[3] & 0xc0) != 0x80 ||\n\t\t\t\tfalse == callback_4(begin[0], begin[1], begin[2], begin[3]))\n\t\t\t{\n\t\t\t\t*begin_ptr = begin;\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tbegin += 4;\n\t\t} else {\n\t\t\t*begin_ptr = begin;\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t*begin_ptr = begin;\n\treturn true;\n}\n\n/**\n * Iterate pointer range, function is checking range for correction\n * @param begin_ptr In/Out current pointer\n * @param end End pointer\n * @param callback_1 callback for ASCII char\n * @param callback_2 callback for 2byte UTF code point\n * @param callback_3 callback for 3byte UTF code point\n * @param callback_4 callback for 4byte UTF code point\n * @return True if iteration reach end, False if function find UTF8 error or callback request ending\n */\ntemplate<typename F1, typename F2, typename F3, typename F4>\nstatic bool iterateUTF8CodePoints(const unsigned char* begin, const unsigned char* end, F1 callback_1, F2 callback_2, F3 callback_3, F4 callback_4)\n{\n\tassert(begin <= end && \"Invalid UTF8 text pointers\");\n\n\tif (begin < end)\n\t{\n\t\t// we need buffer to avoid dereferencing memory after end of string\n\t\tconst auto fake_end = end - 3;\n\t\tauto curr = begin;\n\t\tif (false == iterateUTF8CodePointsUnsafe(&curr, fake_end, callback_1, callback_2, callback_3, callback_4))\n\t\t{\n\t\t\treturn false;\n\t\t}\n\n\t\tif (curr != end)\n\t\t{\n\t\t\t// custom buffer for last 4 chars for case of corrupted UTF8\n\t\t\tunsigned char buffer[8] = { };\n\n\t\t\tconst std::size_t tail_size = end - curr;\n\t\t\tstd::memcpy(buffer, curr, tail_size);\n\t\t\tcurr = buffer;\n\t\t\tif (false == iterateUTF8CodePointsUnsafe(&curr, buffer + tail_size, callback_1, callback_2, callback_3, callback_4))\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn true;\n}\n\n/**\n * Checks if UTF-8 string is well-formed.\n * @param ss candidate string\n * @return true if valid\n * @note based on https://www.cl.cam.ac.uk/~mgk25/ucs/utf8_check.c\n */\nbool isValidUTF8(const std::string& ss)\n{\n\tif (false == iterateUTF8CodePoints(\n\t\t\treinterpret_cast<const unsigned char*>(ss.data()),\n\t\t\treinterpret_cast<const unsigned char*>(ss.data() + ss.size()),\n\t\t\t[&](unsigned char s0)\n\t\t\t{\n\t\t\t\t/* 0xxxxxxx */\n\t\t\t\treturn true;\n\t\t\t},\n\t\t\t[&](unsigned char s0, unsigned char s1)\n\t\t\t{\n\t\t\t\t/* 110XXXXx 10xxxxxx */\n\t\t\t\tif ((s0 & 0xfe) == 0xc0)\t/* overlong? */\n\t\t\t\t{\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\t\t\t},\n\t\t\t[&](unsigned char s0, unsigned char s1, unsigned char s2)\n\t\t\t{\n\t\t\t\t/* 1110XXXX 10Xxxxxx 10xxxxxx */\n\t\t\t\tif ((s0 == 0xe0 && (s1 & 0xe0) == 0x80) ||\t\t/* overlong? */\n\t\t\t\t\t(s0 == 0xed && (s1 & 0xe0) == 0xa0) ||\t\t/* surrogate? */\n\t\t\t\t\t(s0 == 0xef && s1 == 0xbf &&\n\t\t\t\t\t(s2 & 0xfe) == 0xbe))\t\t\t\t\t\t/* U+FFFE or U+FFFF? */\n\t\t\t\t{\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\t\t\t},\n\t\t\t[&](unsigned char s0, unsigned char s1, unsigned char s2, unsigned char s3)\n\t\t\t{\n\t\t\t\t/* 11110XXX 10XXxxxx 10xxxxxx 10xxxxxx */\n\t\t\t\tif ((s0 == 0xf0 && (s1 & 0xf0) == 0x80) ||\t\t/* overlong? */\n\t\t\t\t\t(s0 == 0xf4 && s1 > 0x8f) || s0 > 0xf4) \t/* > U+10FFFF? */\n\t\t\t\t{\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\t\t\t}\n\t\t)\n\t)\n\t{\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\n/**\n * Count code points in utf8 string.\n * @param str Base string\n * @return Number of utf8 codepoints in given string.\n */\nstd::size_t codePointLengthUTF8(const std::string &str)\n{\n\tstd::size_t size = 0;\n\n\tif (false == iterateUTF8CodePoints(\n\t\t\treinterpret_cast<const unsigned char*>(str.data()),\n\t\t\treinterpret_cast<const unsigned char*>(str.data() + str.size()),\n\t\t\t[&](unsigned char s0)\n\t\t\t{\n\t\t\t\t/* 0xxxxxxx */\n\t\t\t\tsize += 1;\n\t\t\t\treturn true;\n\t\t\t},\n\t\t\t[&](unsigned char s0, unsigned char s1)\n\t\t\t{\n\t\t\t\t/* 110XXXXx 10xxxxxx */\n\t\t\t\tsize += 1;\n\t\t\t\treturn true;\n\t\t\t},\n\t\t\t[&](unsigned char s0, unsigned char s1, unsigned char s2)\n\t\t\t{\n\t\t\t\t/* 1110XXXX 10Xxxxxx 10xxxxxx */\n\t\t\t\tsize += 1;\n\t\t\t\treturn true;\n\t\t\t},\n\t\t\t[&](unsigned char s0, unsigned char s1, unsigned char s2, unsigned char s3)\n\t\t\t{\n\t\t\t\t/* 11110XXX 10XXxxxx 10xxxxxx 10xxxxxx */\n\t\t\t\tsize += 1;\n\t\t\t\treturn true;\n\t\t\t}\n\t\t)\n\t)\n\t{\n\t\tthrow Exception(\"Invalid utf8 string for length\");\n\t}\n\n\treturn size;\n}\n\n/**\n * Substring based on code points in utf8 string.\n * @param str Base string\n * @param pos Start postion in codepoints, need be less or equal total number of code points in string.\n * @param count Number of codepoints to return.\n * @return utf8 substring from `str`.\n */\nstd::string codePointSubstrUTF8(const std::string &str, std::size_t pos, std::size_t count)\n{\n\tbool found_end = false;\n\tstd::size_t curr = 0;\n\tstd::size_t byte_curr = 0;\n\tstd::size_t byte_begin = std::string::npos;\n\tstd::size_t byte_end = std::string::npos;\n\n\tauto loop = [&]\n\t{\n\t\tif (byte_begin == std::string::npos)\n\t\t{\n\t\t\tif (pos == curr)\n\t\t\t{\n\t\t\t\tbyte_begin = byte_curr;\n\n#if 0\n\t\t\t\t// potential optimalization but it could propagate invalid bytes\n\t\t\t\tif (count == std::string::npos)\n\t\t\t\t{\n\t\t\t\t\tfound_end = true;\n\t\t\t\t\treturn false;\n\t\t\t\t}\n#endif\n\n\t\t\t\tif (count-- == 0)\n\t\t\t\t{\n\t\t\t\t\tfound_end = true;\n\t\t\t\t\tbyte_end = byte_curr;\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (count-- == 0)\n\t\t\t{\n\t\t\t\tfound_end = true;\n\t\t\t\tbyte_end = byte_curr;\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t};\n\n\tif (false == iterateUTF8CodePoints(\n\t\t\treinterpret_cast<const unsigned char*>(str.data()),\n\t\t\treinterpret_cast<const unsigned char*>(str.data() + str.size()),\n\t\t\t[&](unsigned char s0)\n\t\t\t{\n\t\t\t\t/* 0xxxxxxx */\n\t\t\t\tif (false == loop())\n\t\t\t\t{\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tcurr += 1;\n\t\t\t\tbyte_curr += 1;\n\t\t\t\treturn true;\n\t\t\t},\n\t\t\t[&](unsigned char s0, unsigned char s1)\n\t\t\t{\n\t\t\t\t/* 110XXXXx 10xxxxxx */\n\t\t\t\tif (false == loop())\n\t\t\t\t{\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tcurr += 1;\n\t\t\t\tbyte_curr += 2;\n\t\t\t\treturn true;\n\t\t\t},\n\t\t\t[&](unsigned char s0, unsigned char s1, unsigned char s2)\n\t\t\t{\n\t\t\t\t/* 1110XXXX 10Xxxxxx 10xxxxxx */\n\t\t\t\tif (false == loop())\n\t\t\t\t{\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tcurr += 1;\n\t\t\t\tbyte_curr += 3;\n\t\t\t\treturn true;\n\t\t\t},\n\t\t\t[&](unsigned char s0, unsigned char s1, unsigned char s2, unsigned char s3)\n\t\t\t{\n\t\t\t\t/* 11110XXX 10XXxxxx 10xxxxxx 10xxxxxx */\n\t\t\t\tif (false == loop())\n\t\t\t\t{\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tcurr += 1;\n\t\t\t\tbyte_curr += 4;\n\t\t\t\treturn true;\n\t\t\t}\n\t\t)\n\t)\n\t{\n\t\t// early end, check if we have invalid utf8\n\t\tif (false == found_end)\n\t\t{\n\t\t\tthrow Exception(\"Invalid utf8 string for substr\");\n\t\t}\n\t}\n\telse\n\t{\n\t\t// handle `pos == curr` after iterating all code points\n\t\tloop();\n\t}\n\n\t// for big `count` we can do not find correct `byte_end`, it will be `npos` but it still should work\n\t// in some cases for big `pos > curr` we have `byte_begin == std::string::npos` this will throw from `substr` and we want this.\n\treturn str.substr(byte_begin, byte_end - byte_begin);\n}\n\n/**\n * Compares two UTF-8 strings using natural human ordering.\n * @param a String A.\n * @param b String B.\n * @return String A comes before String B.\n */\nbool naturalCompare(const std::string &a, const std::string &b)\n{\n#ifdef _WIN32\n\ttypedef int (WINAPI *WinStrCmp)(PCWSTR, PCWSTR);\n\tWinStrCmp pWinStrCmp = (WinStrCmp)GetProcAddress(GetModuleHandleA(\"shlwapi.dll\"), \"StrCmpLogicalW\");\n\tif (pWinStrCmp)\n\t{\n\t\tstd::wstring wa = convMbToWc(a, CP_UTF8);\n\t\tstd::wstring wb = convMbToWc(b, CP_UTF8);\n\t\treturn (pWinStrCmp(wa.c_str(), wb.c_str()) < 0);\n\t}\n\telse\n#endif\n\t{\n\t\t// fallback to lexical sort\n\t\treturn caseCompare(a, b);\n\t}\n}\n\n/**\n * Compares two UTF-8 strings ignoring case.\n * @param a String A.\n * @param b String B.\n * @return String A comes before String B.\n */\nbool caseCompare(const std::string &a, const std::string &b)\n{\n#ifdef _WIN32\n\tstd::wstring wa = convMbToWc(a, CP_UTF8);\n\tstd::wstring wb = convMbToWc(b, CP_UTF8);\n\treturn (StrCmpIW(wa.c_str(), wb.c_str()) < 0);\n#else\n\treturn (std::use_facet< std::collate<char> >(utf8).compare(&a[0], &a[0] + a.size(), &b[0], &b[0] + b.size()) < 0);\n#endif\n}\n\n/**\n * Searches for a substring in another string ignoring case.\n * @param haystack String to search.\n * @param needle String to find.\n * @return True if the needle is in the haystack.\n */\nbool caseFind(const std::string &haystack, const std::string &needle)\n{\n#ifdef _WIN32\n\tstd::wstring wa = convMbToWc(haystack, CP_UTF8);\n\tstd::wstring wb = convMbToWc(needle, CP_UTF8);\n\treturn (StrStrIW(wa.c_str(), wb.c_str()) != NULL);\n#else\n\tstd::wstring wa = convMbToWc(haystack, 0);\n\tstd::wstring wb = convMbToWc(needle, 0);\n\tstd::use_facet< std::ctype<wchar_t> >(utf8).toupper(&wa[0], &wa[0] + wa.size());\n\tstd::use_facet< std::ctype<wchar_t> >(utf8).toupper(&wb[0], &wb[0] + wb.size());\n\treturn (wa.find(wb) != std::wstring::npos);\n#endif\n}\n\n/**\n * Uppercases a UTF-8 string, modified in place.\n * Used for case-insensitive comparisons.\n * @param s Source string.\n */\nvoid upperCase(std::string &s)\n{\n\tif (s.empty())\n\t\treturn;\n#ifdef _WIN32\n\tstd::wstring ws = convMbToWc(s, CP_UTF8);\n\tCharUpperW(&ws[0]);\n\ts = convWcToMb(ws, CP_UTF8);\n#else\n\tstd::wstring ws = convMbToWc(s, 0);\n\tstd::use_facet< std::ctype<wchar_t> >(utf8).toupper(&ws[0], &ws[0] + ws.size());\n\ts = convWcToMb(ws, 0);\n#endif\n}\n\n/**\n * Lowercases a UTF-8 string, modified in place.\n * Used for case-insensitive comparisons.\n * @param s Source string.\n */\nvoid lowerCase(std::string &s)\n{\n\tif (s.empty())\n\t\treturn;\n#ifdef _WIN32\n\tstd::wstring ws = convMbToWc(s, CP_UTF8);\n\tCharLowerW(&ws[0]);\n\ts = convWcToMb(ws, CP_UTF8);\n#else\n\tstd::wstring ws = convMbToWc(s, 0);\n\tstd::use_facet< std::ctype<wchar_t> >(utf8).tolower(&ws[0], &ws[0] + ws.size());\n\ts = convWcToMb(ws, 0);\n#endif\n}\n\n/**\n * Replaces every instance of a substring.\n * @param str The string to modify.\n * @param find The substring to find.\n * @param replace The substring to replace it with.\n */\nvoid replace(std::string &str, const std::string &find, const std::string &replace)\n{\n\tfor (size_t i = str.find(find); i != std::string::npos; i = str.find(find, i + replace.length()))\n\t{\n\t\tstr.replace(i, find.length(), replace);\n\t}\n}\n\n/**\n * Takes an integer value and formats it as number with separators (spacing the thousands).\n * @param value The value.\n * @param currency Currency symbol.\n * @return The formatted string.\n */\nstd::string formatNumber(int64_t value, const std::string &currency)\n{\n\tconst std::string thousands_sep = \"\\xC2\\xA0\"; // TOK_NBSP\n\n\tbool negative = (value < 0);\n\tstd::ostringstream ss;\n\tss << (negative ? -value : value);\n\tstd::string s = ss.str();\n\tsize_t spacer = s.size() - 3;\n\twhile (spacer > 0 && spacer < s.size())\n\t{\n\t\ts.insert(spacer, thousands_sep);\n\t\tspacer -= 3;\n\t}\n\tif (!currency.empty())\n\t{\n\t\tif (currency.length() > 1) // Note: size in bytes, not characters!\n\t\t\ts.append(currency);\n\t\telse\n\t\t\ts.insert(0, currency);\n\t}\n\tif (negative)\n\t{\n\t\ts.insert(0, \"-\");\n\t}\n\treturn s;\n}\n\n/**\n * Takes an integer value and formats it as currency,\n * spacing the thousands and adding a $ sign to the front.\n * @param funds The funding value.\n * @return The formatted string.\n */\nstd::string formatFunding(int64_t funds)\n{\n\treturn formatNumber(funds, OXCE_CURRENCY_SYMBOL);\n}\n\n/**\n * Takes an integer value and formats it as percentage,\n * adding a % sign.\n * @param value The percentage value.\n * @return The formatted string.\n */\nstd::string formatPercentage(int value)\n{\n\tstd::ostringstream ss;\n\tss << value << \"%\";\n\treturn ss.str();\n}\n\n\n\n#ifndef NDEBUG\n#define assert_throw(A) try { A; assert(false && \"No throw from \" #A ); } catch (...){ /*nothing*/ }\n\nstatic auto dummy = ([]\n{\n\tassert(isValidUTF8(\"012345\") == true);\n\tassert(codePointLengthUTF8(\"012345\") == 6);\n\tassert(isValidUTF8(\"很烫烫的一锅汤\") == true);\n\tassert(codePointLengthUTF8(\"很烫烫的一锅汤\") == 7);\n\n\tassert(isValidUTF8(\"ÐðŁłŠšÝýÞþŽž\") == true);\n\tassert(codePointLengthUTF8(\"ÐðŁłŠšÝýÞþŽž\") == 12);\n\n\tassert(isValidUTF8(\"\\xf0\\x9f\\x92\\xa9\") == true);\n\tassert(codePointLengthUTF8(\"\\xf0\\x9f\\x92\\xa9\") == 1);\n\n\tassert(isValidUTF8(\"\\x7f\") == true);\n\tassert(codePointLengthUTF8(\"\\x7f\") == 1);\n\n\tassert(isValidUTF8(\"\\xff\") == false);\n\tassert_throw(codePointLengthUTF8(\"\\xff\"));\n\n\tassert(isValidUTF8(\"\\x80\") == false);\n\tassert_throw(codePointLengthUTF8(\"\\x80\"));\n\n\tassert(isValidUTF8(\"\\xc5\\x9b\") == true);\n\tassert(isValidUTF8(\"\\xc5\\xc5\") == false);\n\tassert(isValidUTF8(\"\\xc5\") == false);\n\n\tassert(isValidUTF8(\"\\xe5\\xbe\\x88\") == true);\n\tassert(isValidUTF8(\"\\xe5\\xbe\") == false);\n\tassert(isValidUTF8(\"\\xe5\") == false);\n\n\tassert(isValidUTF8(\"\\xc5\\x9b\\xe5\\xbe\\x88\") == true);\n\tassert(isValidUTF8(\"\\xc5\\x9b\\xe5\\xbe\") == false);\n\tassert(isValidUTF8(\"\\xc5\\x9b\\xe5\") == false);\n\n\tassert(isValidUTF8(\"A\\xc5\\x9b\\xe5\\xbe\\x88\") == true);\n\tassert(isValidUTF8(\"A\\xc5\\x9b\\xe5\\xbe\") == false);\n\tassert(isValidUTF8(\"A\\xc5\\x9b\\xe5\") == false);\n\n\tassert(isValidUTF8(\"\\xc4\\x99\\xc5\\x9b\\xe5\\xbe\\x88\") == true);\n\tassert(isValidUTF8(\"\\xc4\\x99\\xc5\\x9b\\xe5\\xbe\") == false);\n\tassert(isValidUTF8(\"\\xc4\\x99\\xc5\\x9b\\xe5\") == false);\n\n\tassert(isValidUTF8(\"\\xe5\\xbe\\x88    \") == true);\n\tassert(isValidUTF8(\"\\xe5\\xbe     \") == false);\n\tassert(isValidUTF8(\"\\xe5    \") == false);\n\n\tassert(isValidUTF8(\"    \\xe5\\xbe\\x88\") == true);\n\tassert(isValidUTF8(\"    \\xe5\\xbe\") == false);\n\tassert(isValidUTF8(\"    \\xe5\") == false);\n\n\tassert(isValidUTF8(\"\\xe5\\xbe\\x88\\xc4\\x99\") == true);\n\tassert(isValidUTF8(\"\\xe5\\xbe\\xc4\\x99\") == false);\n\tassert(isValidUTF8(\"\\xe5\\xc4\\x99\") == false);\n\n\tassert(isValidUTF8(\"\\xf0\\x9f\\x92\\xa9\") == true);\n\tassert(isValidUTF8(\"\\xf0\\x9f\\x92\") == false);\n\tassert(isValidUTF8(\"\\xf0\\x9f\") == false);\n\tassert(isValidUTF8(\"\\xf0\") == false);\n\n\t//handling of embedded zeros\n\tassert(isValidUTF8(std::string{'\\0','\\0','\\xc5','\\x9b'}) == true);\n\tassert(codePointLengthUTF8(std::string{'\\0','\\0','\\xc5','\\x9b'}) == 3);\n\n\tassert(isValidUTF8(std::string{'\\0','\\0','\\xc5'}) == false);\n\tassert_throw(codePointLengthUTF8(std::string{'\\0','\\0','\\xc5'}));\n\n\n\t//test substr\n\tassert(codePointSubstrUTF8(\"很烫烫的一锅汤\", 0) == std::string(\"很烫烫的一锅汤\"));\n\tassert(codePointSubstrUTF8(\"很烫烫的一锅汤\", 1) == std::string(\"烫烫的一锅汤\"));\n\tassert(codePointSubstrUTF8(\"很烫烫的一锅汤\", 2) == std::string(\"烫的一锅汤\"));\n\tassert(codePointSubstrUTF8(\"很烫烫的一锅汤\", 3) == std::string(\"的一锅汤\"));\n\tassert(codePointSubstrUTF8(\"很烫烫的一锅汤\", 4) == std::string(\"一锅汤\"));\n\tassert(codePointSubstrUTF8(\"很烫烫的一锅汤\", 5) == std::string(\"锅汤\"));\n\tassert(codePointSubstrUTF8(\"很烫烫的一锅汤\", 6) == std::string(\"汤\"));\n\tassert(codePointSubstrUTF8(\"很烫烫的一锅汤\", 7) == std::string(\"\"));\n\tassert_throw(codePointSubstrUTF8(\"很烫烫的一锅汤\", 8));\n\n\tassert(codePointSubstrUTF8(\"很烫烫的一锅汤\", 0, 8) == std::string(\"很烫烫的一锅汤\"));\n\tassert(codePointSubstrUTF8(\"很烫烫的一锅汤\", 0, 7) == std::string(\"很烫烫的一锅汤\"));\n\tassert(codePointSubstrUTF8(\"很烫烫的一锅汤\", 0, 6) == std::string(\"很烫烫的一锅\"));\n\tassert(codePointSubstrUTF8(\"很烫烫的一锅汤\", 0, 5) == std::string(\"很烫烫的一\"));\n\tassert(codePointSubstrUTF8(\"很烫烫的一锅汤\", 0, 4) == std::string(\"很烫烫的\"));\n\tassert(codePointSubstrUTF8(\"很烫烫的一锅汤\", 0, 3) == std::string(\"很烫烫\"));\n\tassert(codePointSubstrUTF8(\"很烫烫的一锅汤\", 0, 2) == std::string(\"很烫\"));\n\tassert(codePointSubstrUTF8(\"很烫烫的一锅汤\", 0, 1) == std::string(\"很\"));\n\tassert(codePointSubstrUTF8(\"很烫烫的一锅汤\", 0, 0) == std::string(\"\"));\n\n\tassert(codePointSubstrUTF8(\"ÐðŁłŠšÝýÞþŽž\", 0, 3) == std::string(\"ÐðŁ\"));\n\tassert(codePointSubstrUTF8(\"ÐðŁłŠšÝýÞþŽž\", 3, 3) == std::string(\"łŠš\"));\n\tassert(codePointSubstrUTF8(\"ÐðŁłŠšÝýÞþŽž\", 6, 3) == std::string(\"ÝýÞ\"));\n\tassert(codePointSubstrUTF8(\"ÐðŁłŠšÝýÞþŽž\", 9, 3) == std::string(\"þŽž\"));\n\tassert(codePointSubstrUTF8(\"ÐðŁłŠšÝýÞþŽž\", 12, 3) == std::string(\"\"));\n\n\tassert(codePointSubstrUTF8(\"ÐðŁłŠšÝýÞþŽž\", 11, 5) == std::string(\"ž\"));\n\tassert(codePointSubstrUTF8(\"ÐðŁłŠšÝýÞþŽž\", 10, 5) == std::string(\"Žž\"));\n\tassert(codePointSubstrUTF8(\"ÐðŁłŠšÝýÞþŽž\", 9, 5) == std::string(\"þŽž\"));\n\tassert(codePointSubstrUTF8(\"ÐðŁłŠšÝýÞþŽž\", 8, 5) == std::string(\"ÞþŽž\"));\n\tassert(codePointSubstrUTF8(\"ÐðŁłŠšÝýÞþŽž\", 7, 5) == std::string(\"ýÞþŽž\"));\n\tassert(codePointSubstrUTF8(\"ÐðŁłŠšÝýÞþŽž\", 6, 5) == std::string(\"ÝýÞþŽ\"));\n\tassert(codePointSubstrUTF8(\"ÐðŁłŠšÝýÞþŽž\", 5, 5) == std::string(\"šÝýÞþ\"));\n\n\tassert(codePointSubstrUTF8(\"012\", 0, 1) == std::string(\"0\"));\n\tassert(codePointSubstrUTF8(\"012\", 1, 1) == std::string(\"1\"));\n\tassert(codePointSubstrUTF8(\"012\", 2, 1) == std::string(\"2\"));\n\n\treturn 0;\n})();\n#endif\n\n}\n}\n"
  },
  {
    "path": "src/Engine/Unicode.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *e\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include <stdint.h>\n#include <SDL.h>\n\nnamespace OpenXcom\n{\n\n/**\n * Represents a 32-bit Unicode codepoint.\n */\ntypedef char32_t UCode;\n/**\n * Represents a string where each character\n * is a Unicode codepoint. Used for rendering text.\n */\ntypedef std::basic_string<UCode> UString;\n\n/**\n * Functions for dealing with encoding, strings, text\n * and all related operations.\n */\nnamespace Unicode\n{\n\t/* Special text tokens */\n\tconst char TOK_CUSTOM_FORMAT = 27;\t\t/// special tag for custom text format\n\tconst char TOK_NL_SMALL = 2;\t\t\t/// line break and change to small font\n\tconst char TOK_COLOR_FLIP = 1;\t\t\t/// alternate between primary and secondary color\n\tconst unsigned char TOK_NBSP = 0xA0;\t/// non-breaking space\n\n\t/// Checks if a character is a linebreak.\n\tinline bool isLinebreak(UCode c) { return (c == '\\n' || c == TOK_NL_SMALL); }\n\t/// Checks if a character is a blank space (includes non-breaking spaces).\n\tinline bool isSpace(UCode c) { return (c == ' ' || c == TOK_NBSP); }\n\t/// Checks if a character is a word separator.\n\tinline bool isSeparator(UCode c) { return (c == '-' || c == '/'); }\n\t/// Checks if a character is visible to the user.\n\tinline bool isPrintable(UCode c) { return (c > 32 && c != TOK_NBSP); }\n\n\t/// Find a UTF-8 locale.\n\tvoid getUtf8Locale();\n\t/// Converts a UTF-8 string to UTF-32.\n\tUString convUtf8ToUtf32(const std::string &src);\n\t/// Converts a UTF-32 string to UTF-8.\n\tstd::string convUtf32ToUtf8(const UString &src);\n\t/// Converts a wide-char string to multi-byte.\n\tstd::string convWcToMb(const std::wstring &src, unsigned int cp = 0);\n\t/// Converts a multi-byte string to wide-char.\n\tstd::wstring convMbToWc(const std::string &src, unsigned int cp = 0);\n\n\t/// Checks UTF-8 validity\n\tbool isValidUTF8(const std::string& ss);\n\t/// Count code points in utf8 string.\n\tstd::size_t codePointLengthUTF8(const std::string &str);\n\t/// Substring based on code points in utf8 string.\n\tstd::string codePointSubstrUTF8(const std::string &str, std::size_t pos, std::size_t count = std::string::npos);\n\n\t/// Compares two strings by natural order.\n\tbool naturalCompare(const std::string &a, const std::string &b);\n\t/// Compares two strings case-insensitive.\n\tbool caseCompare(const std::string &a, const std::string &b);\n\t/// Find a string in another case-insensitive.\n\tbool caseFind(const std::string &haystack, const std::string &needle);\n\t/// Uppercases a string in place.\n\tvoid upperCase(std::string &s);\n\t/// Lowercases a string in place.\n\tvoid lowerCase(std::string &s);\n\t/// Replaces a substring.\n\tvoid replace(std::string &str, const std::string &find, const std::string &replace);\n\t/// Formats an integer value as number with separators.\n\tstd::string formatNumber(int64_t value, const std::string &currency = \"\");\n\t/// Formats an integer value as currency.\n\tstd::string formatFunding(int64_t funds);\n\t/// Formats an integer value as percentage.\n\tstd::string formatPercentage(int value);\n}\n\n}\n"
  },
  {
    "path": "src/Engine/Yaml.cpp",
    "content": "/*\n * Copyright 2010-2024 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"Yaml.h\"\n#include \"../Engine/CrossPlatform.h\"\n#include <string>\n#include <c4/format.hpp>\n\nnamespace OpenXcom\n{\n\nnamespace YAML\n{\n\n/// Custom error handler; For now it doesn't do anything\nstruct YamlErrorHandler\n{\n\tryml::Callbacks callbacks();\n\tC4_NORETURN void on_error(const char* msg, size_t len, ryml::Location loc);\n\tC4_NORETURN static void s_error(const char* msg, size_t len, ryml::Location loc, void* this_);\n\tYamlErrorHandler() : defaults(ryml::get_callbacks()) {}\n\tryml::Callbacks defaults;\n};\nC4_NORETURN void YamlErrorHandler::s_error(const char* msg, size_t len, ryml::Location loc, void* this_)\n{\n\t((YamlErrorHandler*)this_)->on_error(msg, len, loc);\n}\nC4_NORETURN void YamlErrorHandler::on_error(const char* msg, size_t len, ryml::Location loc)\n{\n\tthrow Exception(\"Rapidyaml \" + std::string{msg, len}); // This function must not return\n}\nstatic void* s_allocate(size_t len, void* /*hint*/, void* this_)\n{\n\treturn SDL_malloc(len);\n}\nstatic void s_free(void* mem, size_t len, void* this_)\n{\n\tSDL_free(mem);\n}\nryml::Callbacks YamlErrorHandler::callbacks()\n{\n\treturn ryml::Callbacks(this, s_allocate, s_free, YamlErrorHandler::s_error);\n}\n\nvoid setGlobalErrorHandler()\n{\n\tstatic YamlErrorHandler errh;\n\tryml::set_callbacks(errh.callbacks());\n}\n\n\nC4_NORETURN static void RootReader_error(const char* msg, size_t len, ryml::Location loc, void* this_)\n{\n\tconst auto& globalCallback = ryml::get_callbacks();\n\tglobalCallback.m_error(msg, len, loc, globalCallback.m_user_data);\n\tC4_UNREACHABLE();\n}\n\nstatic ryml::Callbacks callbacksForRootReader(const YamlRootNodeReader* root)\n{\n\treturn ryml::Callbacks(const_cast<YamlRootNodeReader*>(root), s_allocate, s_free, RootReader_error);\n}\n\nstatic const YamlRootNodeReader* getRootReaderData(const ryml::Callbacks& callbacks)\n{\n\treturn callbacks.m_error == RootReader_error ? static_cast<const YamlRootNodeReader*>(callbacks.m_user_data) : nullptr;\n}\n\n\nC4_NORETURN static void RootWriter_error(const char* msg, size_t len, ryml::Location loc, void* this_)\n{\n\tconst auto& globalCallback = ryml::get_callbacks();\n\tglobalCallback.m_error(msg, len, loc, globalCallback.m_user_data);\n\tC4_UNREACHABLE();\n}\n\nstatic ryml::Callbacks callbacksForRootWriter(const YamlRootNodeWriter* root)\n{\n\treturn ryml::Callbacks(const_cast<YamlRootNodeWriter*>(root), s_allocate, s_free, RootWriter_error);\n}\n\nstatic const YamlRootNodeWriter* getRootWriterData(const ryml::Callbacks& callbacks)\n{\n\treturn callbacks.m_error == RootWriter_error ?  static_cast<const YamlRootNodeWriter*>(callbacks.m_user_data) : nullptr;\n}\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tYamlNodeReader\n////////////////////////////////////////////////////////////\n\n\nYamlNodeReader::YamlNodeReader()\n\t: _node(ryml::ConstNodeRef(nullptr, ryml::NONE)), _nextChildId(ryml::NONE)\n{\n}\n\nYamlNodeReader::YamlNodeReader(const ryml::ConstNodeRef& node)\n\t: _node(node), _nextChildId(ryml::NONE)\n{\n\n}\n\nYamlNodeReader::YamlNodeReader(const ryml::ConstNodeRef& node, bool useIndex) : YamlNodeReader( node)\n{\n\tif (!useIndex || _node.invalid())\n\t\treturn;\n\t// build and use an index to avoid [] operator's O(n) complexity\n\t_index.emplace();\n\n\tif (!_node.is_map())\n\t{\n\t\tif (_node.is_seq())\n\t\t{\n\t\t\tif (_node.is_stream())\n\t\t\t{\n\t\t\t\t(*this)[1].throwNodeError(\"multi-document yaml file with splits '---'\");\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tthrowNodeError(\"sequence node as map\");\n\t\t\t}\n\t\t}\n\t\telse if (_node.has_val())\n\t\t{\n\t\t\tif (_node.val_is_null())\n\t\t\t{\n\t\t\t\t// it is `~` and we consider this as allowed empty map\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tthrowNodeError(\"value node as map\");\n\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tassert(false && \"unexpected node type for index\");\n\t\t}\n\t}\n\n\t_index->reserve(_node.num_children());\n\tfor (const ryml::ConstNodeRef childNode : _node.cchildren())\n\t\t_index->emplace(childNode.key(), childNode.id());\n}\n\nYamlNodeReader YamlNodeReader::useIndex() const\n{\n\treturn YamlNodeReader(_node, true);\n}\n\nstd::string_view YamlNodeReader::key() const\n{\n\tif (_node.invalid())\n\t\tthrow Exception(\"Tried getting key of an invalid node!\");\n\tconst auto& key = _node.tree()->get(_node.m_id)->m_key.scalar;\n\treturn std::string_view(key.str, key.len);\n}\n\nstd::string_view YamlNodeReader::val() const\n{\n\tif (_node.invalid())\n\t\tthrow Exception(\"Tried getting value of an invalid node!\");\n\tconst auto& val = _node.tree()->get(_node.m_id)->m_val.scalar;\n\treturn std::string_view(val.str, val.len);\n}\n\nstd::vector<char> YamlNodeReader::readValBase64() const\n{\n\t// first run figure out the decoded length\n\tsize_t len = _node.deserialize_val(c4::fmt::base64(ryml::substr()));\n\tstd::vector<char> decodedData(len);\n\tryml::blob buf(decodedData.data(), len);\n\t// deserialize\n\t_node.deserialize_val(c4::fmt::base64(buf));\n\treturn decodedData;\n}\n\nsize_t YamlNodeReader::childrenCount() const\n{\n\tif (_node.invalid())\n\t\treturn 0;\n\treturn _index ? _index->size() : _node.num_children();\n}\n\nryml::ConstNodeRef YamlNodeReader::getChildNode(const ryml::csubstr& key) const\n{\n\tif (_node.invalid())\n\t\treturn ryml::ConstNodeRef(_node.tree(), ryml::NONE);\n\tif (!_index)\n\t{\n\t\tif (!_node.is_map())\n\t\t\treturn ryml::ConstNodeRef(_node.tree(), ryml::NONE);\n\t\treturn findChildNode(key);\n\t}\n\tif (const auto& keyNodeIdPair = _index->find(key); keyNodeIdPair != _index->end())\n\t\treturn _node.tree()->cref(keyNodeIdPair->second);\n\treturn ryml::ConstNodeRef(_node.tree(), ryml::NONE);\n}\n\nryml::ConstNodeRef YamlNodeReader::findChildNode(const ryml::csubstr& key) const\n{\n\tryml::id_type firstChildId = _node.m_tree->get(_node.m_id)->m_first_child;\n\tif (firstChildId == ryml::NONE)\n\t\treturn ryml::ConstNodeRef(_node.m_tree, ryml::NONE);\n\tif (_nextChildId == ryml::NONE)\n\t{ // do a normal search\n\t\tfor (ryml::id_type i = firstChildId; i != ryml::NONE;)\n\t\t{\n\t\t\tconst ryml::NodeData* data = _node.m_tree->_p(i);\n\t\t\tif (data->m_key.scalar == key)\n\t\t\t{\n\t\t\t\t_nextChildId = data->m_next_sibling;\n\t\t\t\treturn ryml::ConstNodeRef(_node.m_tree, i);\n\t\t\t}\n\t\t\ti = data->m_next_sibling;\n\t\t}\n\t\treturn ryml::ConstNodeRef(_node.m_tree, ryml::NONE);\n\t}\n\t// search from saved iterator to the last child\n\tfor (ryml::id_type i = _nextChildId; i != ryml::NONE;)\n\t{\n\t\tconst ryml::NodeData* data = _node.m_tree->_p(i);\n\t\tif (data->m_key.scalar == key)\n\t\t{\n\t\t\t_nextChildId = data->m_next_sibling;\n\t\t\treturn ryml::ConstNodeRef(_node.m_tree, i);\n\t\t}\n\t\ti = data->m_next_sibling;\n\t}\n\t// search from the first child to the saved iterator\n\tfor (ryml::id_type i = firstChildId; i != _nextChildId;)\n\t{\n\t\tconst ryml::NodeData* data = _node.m_tree->_p(i);\n\t\tif (data->m_key.scalar == key)\n\t\t{\n\t\t\t_nextChildId = data->m_next_sibling;\n\t\t\treturn ryml::ConstNodeRef(_node.m_tree, i);\n\t\t}\n\t\ti = data->m_next_sibling;\n\t}\n\treturn ryml::ConstNodeRef(_node.m_tree, ryml::NONE);\n}\n\nstd::vector<YamlNodeReader> YamlNodeReader::children() const\n{\n\tstd::vector<YamlNodeReader> children;\n\tif (_node.invalid())\n\t\treturn children;\n\tchildren.reserve(_node.num_children());\n\tfor (const ryml::ConstNodeRef child : _node.cchildren())\n\t\tchildren.emplace_back(child);\n\treturn children;\n}\n\nbool YamlNodeReader::isValid() const\n{\n\treturn !_node.invalid();\n}\n\nbool YamlNodeReader::isMap() const\n{\n\treturn _node.is_map();\n}\n\nbool YamlNodeReader::isSeq() const\n{\n\treturn _node.is_seq();\n}\n\nbool YamlNodeReader::hasVal() const\n{\n\treturn _node.has_val();\n}\n\nbool YamlNodeReader::hasNullVal() const\n{\n\treturn _node.has_val() && _node.val_is_null();\n}\n\nbool YamlNodeReader::hasValTag() const\n{\n\treturn _node.has_val_tag();\n}\n\nbool YamlNodeReader::hasValTag(ryml::YamlTag_e tag) const\n{\n\tif (_node.invalid() || !_node.has_val_tag())\n\t\treturn false;\n\treturn ryml::to_tag(_node.val_tag()) == tag;\n}\n\nbool YamlNodeReader::hasValTag(const std::string& tagName) const\n{\n\tif (_node.invalid() || !_node.has_val_tag())\n\t\treturn false;\n\treturn _node.val_tag() == tagName;\n}\n\nstd::string YamlNodeReader::getValTag() const\n{\n\tif (_node.invalid() || !_node.has_val_tag())\n\t\treturn std::string();\n\tryml::csubstr valTag = _node.val_tag();\n\treturn std::string(valTag.str, valTag.len);\n}\n\nconst YamlString YamlNodeReader::emit() const\n{\n\treturn YamlString(ryml::emitrs_yaml<std::string>(_node));\n}\n\nconst YamlString YamlNodeReader::emitDescendants() const\n{\n\treturn emitDescendants(YamlNodeReader());\n}\n\nconst YamlString YamlNodeReader::emitDescendants(const YamlNodeReader& defaultValuesReader) const\n{\n\tYAML::YamlRootNodeWriter writer;\n\tif (isMap())\n\t\twriter.setAsMap();\n\telse if (isSeq())\n\t\twriter.setAsSeq();\n\telse\n\t\treturn YamlString(std::string());\n\twriter._tree->duplicate_children(_node.tree(), _node.id(), writer._node.id(), ryml::NONE);\n\tif (defaultValuesReader)\n\t\tfor (const ryml::ConstNodeRef child : defaultValuesReader._node.cchildren())\n\t\t\tif (writer._node.find_child(child.key()).invalid())\n\t\t\t\twriter._tree.get()->duplicate(child.tree(), child.id(), writer._node.id(), writer._node.last_child().id());\n\treturn writer.emit();\n}\n\nryml::Location YamlNodeReader::getLocationInFile() const\n{\n\tauto root = _node.tree() ? getRootReaderData(_node.tree()->callbacks()) : nullptr;\n\treturn root ? root->getLocationInFile(_node) : ryml::Location{};\n}\n\nYamlNodeReader YamlNodeReader::operator[](ryml::csubstr key) const\n{\n\treturn YamlNodeReader(getChildNode(key));\n}\n\nYamlNodeReader YamlNodeReader::operator[](size_t pos) const\n{\n\tif (_node.invalid())\n\t\treturn YamlNodeReader(ryml::ConstNodeRef(_node.tree(), ryml::NONE));\n\treturn YamlNodeReader(_node.child(pos));\n}\n\nYamlNodeReader::operator bool() const\n{\n\treturn !_node.invalid();\n}\n\n\nvoid YamlNodeReader::throwTypeError(const ryml::ConstNodeRef& node, const ryml::cspan<char>& type) const\n{\n\tauto name = ryml::csubstr(type.data(), type.size() - (type.back() == 0));\n\tif (node.readable())\n\t{\n\t\tryml::Location loc = YamlNodeReader{node}.getLocationInFile();\n\t\tthrow Exception(c4::formatrs<std::string>(\"Could not deserialize value to type <{}>! {} at line {}:{}\", name, loc.name, loc.line, loc.col));\n\t}\n\telse\n\t{\n\t\tthrow Exception(c4::formatrs<std::string>(\"Could not deserialize value to type <{}>!\", name));\n\t}\n}\n\nvoid YamlNodeReader::throwNodeError(const std::string& what) const\n{\n\tif (_node.readable())\n\t{\n\t\tryml::Location loc = getLocationInFile();\n\t\tthrow Exception(c4::formatrs<std::string>(\"Tried to deserialize {}. {} at line {}:{}\", what, loc.name, loc.line, loc.col));\n\t}\n\telse\n\t{\n\t\tthrow Exception(c4::formatrs<std::string>(\"Tried to deserialize {}.\", what));\n\t}\n}\n\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tYamlRootNodeReader\n////////////////////////////////////////////////////////////\n\n\nYamlRootNodeReader::YamlRootNodeReader(const std::string& fullFilePath, bool onlyInfoHeader, bool resolveReferences) : YamlNodeReader(), _tree(new ryml::Tree(callbacksForRootReader(this)))\n{\n\tRawData data = onlyInfoHeader ? CrossPlatform::getYamlSaveHeaderRaw(fullFilePath) : CrossPlatform::readFileRaw(fullFilePath);\n\tryml::csubstr str = ryml::csubstr((char*)data.data(), data.size());\n\tif (onlyInfoHeader)\n\t\tstr = ryml::csubstr((char*)data.data(), str.find(\"\\n---\") + 1);\n\tParse(str, fullFilePath, true, resolveReferences);\n}\n\nYamlRootNodeReader::YamlRootNodeReader(const RawData& data, const std::string& fileNameForError, bool resolveReferences) : YamlNodeReader(), _tree(new ryml::Tree(callbacksForRootReader(this)))\n{\n\tParse(ryml::csubstr((char*)data.data(), data.size()), fileNameForError, true, resolveReferences);\n}\n\nYamlRootNodeReader::YamlRootNodeReader(const YamlString& yamlString, std::string description, bool resolveReferences) : YamlNodeReader(), _tree(new ryml::Tree(callbacksForRootReader(this)))\n{\n\tParse(ryml::to_csubstr(yamlString.yaml), std::move(description), false, resolveReferences);\n}\n\nvoid YamlRootNodeReader::Parse(ryml::csubstr yaml, std::string fileNameForError, bool withNodeLocations, bool resoleReferences)\n{\n\tif (yaml.len > 3 && yaml.first(3) == \"\\xEF\\xBB\\xBF\") // skip UTF-8 BOM\n\t\tyaml = yaml.offs(3, 0);\n\n\t{\n\t\t// find only name of file, not whole path\n\t\tsize_t pos = fileNameForError.find_last_of('/');\n\t\tif (pos != std::string::npos)\n\t\t\tfileNameForError.erase(0, pos + 1);\n\t}\n\n\t_eventHandler.reset(new ryml::EventHandlerTree(_tree->callbacks()));\n\t_parser.reset(new ryml::Parser(_eventHandler.get(), ryml::ParserOptions().locations(withNodeLocations)));\n\n\t_fileName = std::move(fileNameForError);\n\t_tree->reserve(yaml.len / 16);\n\tryml::parse_in_arena(_parser.get(), ryml::to_csubstr(_fileName), yaml, _tree.get());\n\tif (resoleReferences)\n\t\t_tree->resolve();\n\t_node = _tree->crootref();\n\n\t// yaml file that start with \"---\\n\" should not be consider a multi-document if there are no others \"---\\n\"\n\tif (_node.is_stream())\n\t{\n\t\tif (_node.first_child() == _node.last_child())\n\t\t{\n\t\t\t_node = _node.first_child();\n\t\t}\n\t}\n\t// if the yaml file is an empty document, it's parsed into a single node with type NOTYPE\n\tif (_tree->size() == 1 && _node.type() == ryml::NOTYPE)\n\t\t_node = ryml::ConstNodeRef(_tree.get(), ryml::NONE); // treat it as an invalid node\n}\n\nYamlNodeReader YamlRootNodeReader::toBase() const\n{\n\treturn YamlNodeReader(_node);\n}\n\nryml::Location YamlRootNodeReader::getLocationInFile(const ryml::ConstNodeRef& node) const\n{\n\tif (_parser)\n\t{\n\t\t// line and column here are 0-based, which isn't correct.\n\t\tryml::Location loc = _parser->location(node);\n\t\tloc.line += 1;\n\t\tloc.col += 1;\n\t\treturn loc;\n\t}\n\telse\n\t\tthrow Exception(\"Parsed yaml without location data logging enabled\");\n}\n\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tYamlNodeWriter\n////////////////////////////////////////////////////////////\n\n\nYamlNodeWriter::YamlNodeWriter(ryml::NodeRef node) : _node(node)\n{\n\n}\n\nYamlNodeReader YamlNodeWriter::toReader()\n{\n\treturn YamlNodeReader(_node);\n}\n\nYamlNodeWriter YamlNodeWriter::write()\n{\n\treturn YamlNodeWriter(_node.append_child());\n}\n\nYamlNodeWriter YamlNodeWriter::operator[](ryml::csubstr key)\n{\n\treturn YamlNodeWriter(_node.append_child({ryml::KEY, key}));\n}\n\nYamlNodeWriter YamlNodeWriter::writeBase64(ryml::csubstr key, char* data, size_t size)\n{\n\treturn YamlNodeWriter(_node.append_child({ryml::KEY, key}) << c4::fmt::base64(ryml::csubstr(data, size)));\n}\n\nvoid YamlNodeWriter::setValueNull()\n{\n\t_node.set_val(\"~\");\n}\n\nvoid YamlNodeWriter::setAsMap()\n{\n\t_node |= ryml::MAP;\n}\n\nvoid YamlNodeWriter::setAsSeq()\n{\n\t_node |= ryml::SEQ;\n}\n\nvoid YamlNodeWriter::setFlowStyle()\n{\n\t_node |= ryml::FLOW_SL;\n}\n\nvoid YamlNodeWriter::setBlockStyle()\n{\n\t_node |= ryml::BLOCK;\n}\n\nbool isPrintable(uint8_t c)\n{\n\t// TAB, LF, CR, and x20-x7E range; Any 2+ byte UTF-8 characters are assumed to be printable\n\treturn c == 0x09 || c == 0x0A || c == 0x0D || (c >= 0x20 && c <= 0x7E) || c >= 0x80;\n}\n\nvoid YamlNodeWriter::setAsQuotedAndEscaped()\n{\n\tryml::csubstr scalar = _node.val();\n\tsize_t pos, last = 0;\n\tfor (pos = 0; pos < scalar.len; pos++)\n\t\tif (!isPrintable(scalar[pos]))\n\t\t\tbreak;\n\tif (pos == scalar.len) // didn't find a non-printable ASCII character;\n\t{\n\t\t_node |= ryml::VAL_DQUO;\n\t\treturn;\n\t}\n\t// manually create a double-quoted scalar; escape the non-printable AND special characters\n\t_node |= ryml::VAL_PLAIN;\n\tconst char hexDigits[] = \"0123456789ABCDEF\";\n\tstd::string newScalar;\n\tnewScalar.reserve(scalar.len + 2 + 3); // 2 for quotes and 3 for one hex escape\n\tnewScalar.push_back('\\\"');\n\tfor (pos = 0; pos < scalar.len; pos++)\n\t{\n\t\tchar toEscape = 0;\n\t\tswitch (scalar[pos])\n\t\t{\n\t\tcase '\"': toEscape = '\\\"'; break;\n\t\tcase '\\\\': toEscape = '\\\\'; break;\n\t\tcase '\\n': toEscape = 'n'; break;\n\t\tcase '\\r': toEscape = 'r'; break;\n\t\tcase '\\b': toEscape = 'b'; break;\n\t\tdefault: if (!isPrintable(scalar[pos])) toEscape = 'x'; break;\n\t\t}\n\t\tif (toEscape != 0)\n\t\t{\n\t\t\tnewScalar.append(&scalar[last], pos - last); // copy from the last escaped to the current position\n\t\t\tnewScalar.push_back('\\\\');\n\t\t\tnewScalar.push_back(toEscape);\n\t\t\tif (toEscape == 'x')\n\t\t\t{\n\t\t\t\tnewScalar.push_back(hexDigits[(scalar[pos] >> 4) & 0xF]);\n\t\t\t\tnewScalar.push_back(hexDigits[scalar[pos] & 0xF]);\n\t\t\t}\n\t\t\tlast = pos + 1;\n\t\t}\n\t}\n\tif (pos != last)\n\t\tnewScalar.append(&scalar[last], pos - last); // copy from the last escaped to the end of string\n\tnewScalar.push_back('\\\"');\n\t_node.set_val(_node.tree()->to_arena(newScalar));\n}\n\nvoid YamlNodeWriter::unsetAsMap()\n{\n\t_node.tree()->_rem_flags(_node.id(), ryml::MAP);\n}\n\nvoid YamlNodeWriter::unsetAsSeq()\n{\n\t_node.tree()->_rem_flags(_node.id(), ryml::SEQ);\n}\n\nryml::csubstr YamlNodeWriter::saveString(const std::string& string)\n{\n\treturn _node.tree()->to_arena(string);\n}\n\nYamlString YamlNodeWriter::emit()\n{\n\treturn YamlString(ryml::emitrs_yaml<std::string>(_node));\n}\n\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tYamlRootNodeWriter\n////////////////////////////////////////////////////////////\n\n\nYamlRootNodeWriter::YamlRootNodeWriter() : YamlNodeWriter(ryml::NodeRef{}), _tree(new ryml::Tree(callbacksForRootWriter(this)))\n{\n\t_node = _tree->rootref();\n}\n\nYamlRootNodeWriter::YamlRootNodeWriter(size_t bufferCapacity) : YamlNodeWriter(ryml::NodeRef{}), _tree(new ryml::Tree(0, bufferCapacity, callbacksForRootWriter(this)))\n{\n\t_node = _tree->rootref();\n}\n\nYamlNodeWriter YamlRootNodeWriter::toBase()\n{\n\treturn YamlNodeWriter(_node);\n}\n\n} // namespace YAML\n\n} // namespace OpenXcom\n\n\n////////////////////////////////////////////////////////////\n//\t\tFunctions for overriding types form other lib\n////////////////////////////////////////////////////////////\n\n\nstd::size_t std::hash<ryml::csubstr>::operator()(const ryml::csubstr& k) const\n{\n#ifdef _MSC_VER\n\treturn _Hash_array_representation(k.str, k.len);\n#else\n\treturn std::hash<std::string_view>{}(std::string_view(k.str, k.len));\n#endif\n};\n\nnamespace std\n{\n\n// Deserializing \"\" should succeed when the output type is std::string\nbool read(ryml::ConstNodeRef const& n, std::string* str)\n{\n\tif (n.val().len > 0)\n\t\tryml::from_chars(n.val(), str);\n\telse if (str->size() != 0)\n\t\tstr->clear();\n\treturn true;\n}\n\n}\n\nnamespace c4::yml\n{\n\n// Serializing bool should output the string version instead of 0 and 1\nvoid write(ryml::NodeRef* n, bool const& v)\n{\n\tn->set_val_serialized(c4::fmt::boolalpha(v));\n}\n\n}\n\n\n#ifndef NDEBUG\n\n#include <cassert>\n\nstatic auto createRootReader(std::string s)\n{\n\treturn OpenXcom::YAML::YamlRootNodeReader(OpenXcom::YAML::YamlString{s}, \"dummy\");\n};\ntemplate<typename T>\nstatic auto throw_exception(T&& func)\n{\n\ttry\n\t{\n\t\tfunc();\n\t\treturn false;\n\t}\n\tcatch (...)\n\t{\n\t\treturn true;\n\t}\n};\ntemplate<typename T>\nstatic auto no_exception(T&& func)\n{\n\ttry\n\t{\n\t\treturn func();\n\t}\n\tcatch (...)\n\t{\n\t\treturn false;\n\t}\n};\n#define assert_exception(A) assert(throw_exception([&]{ (A); }));\n#define assert_noexcept(A) assert(no_exception([&]{ return (A); }));\n\nstatic auto dummyHackInitYaml = ([]\n{\n\tOpenXcom::YAML::setGlobalErrorHandler(); //hack, main should do it but this code is called before main\n\treturn 0;\n})();\n\nstatic auto dummyTestMultiDocYaml = ([]\n{\n\t{\n\t\tauto reader = createRootReader(\"foo: [1, 2]\");\n\n\t\tassert_noexcept(reader[\"foo\"].isValid());\n\t\tassert_noexcept(!reader[\"bar\"].isValid());\n\t\tassert_noexcept(reader.useIndex()[\"foo\"].isValid());\n\t\tassert_noexcept(!reader.useIndex()[\"bar\"].isValid());\n\t}\n\n\t{\n\t\tauto reader = createRootReader(\"---\\nfoo: [1, 2]\");\n\n\t\tassert_noexcept(reader[\"foo\"].isValid());\n\t\tassert_noexcept(!reader[\"bar\"].isValid());\n\t\tassert_noexcept(reader.useIndex()[\"foo\"].isValid());\n\t\tassert_noexcept(!reader.useIndex()[\"bar\"].isValid());\n\t}\n\n\t{\n\t\tauto reader = createRootReader(\"---\\nfoo: [1, 2]\\n---\\nbar: 3\");\n\n\t\tassert_noexcept(!reader[\"foo\"].isValid());\n\t\tassert_noexcept(!reader[\"bar\"].isValid());\n\t\tassert_exception(reader.useIndex()[\"foo\"].isValid());\n\n\t\tassert_noexcept(reader[0][\"foo\"].isValid());\n\t\tassert_noexcept(reader[1][\"bar\"].isValid());\n\t}\n\n\treturn 0;\n})();\n\nstatic auto dummyIndexing = ([]\n{\n\t{\n\t\tauto reader = createRootReader(\"map: ~\");\n\n\t\tassert_noexcept(reader[\"map\"].useIndex().childrenCount() == 0);\n\t}\n\n\t{\n\t\tauto reader = createRootReader(\"map:\");\n\n\t\tassert_noexcept(reader[\"map\"].useIndex().childrenCount() == 0);\n\t}\n\n\t{\n\t\tauto reader = createRootReader(\"map: {}\");\n\n\t\tassert_noexcept(reader[\"map\"].useIndex().childrenCount() == 0);\n\t}\n\n\t{\n\t\tauto reader = createRootReader(\"map: {foo: 1}\");\n\n\t\tassert_noexcept(reader[\"map\"].useIndex().childrenCount() == 1);\n\t}\n\n\t{\n\t\tauto reader = createRootReader(\"map: []\");\n\n\t\tassert_exception(reader[\"map\"].useIndex().isMap());\n\t}\n\n\t{\n\t\tauto reader = createRootReader(\"map: [2]\");\n\n\t\tassert_exception(reader[\"map\"].useIndex().isMap());\n\t}\n\n\t{\n\t\tauto reader = createRootReader(\"map: 2\");\n\n\t\tassert_exception(reader[\"map\"].useIndex().isMap());\n\t}\n\n\t{\n\t\tauto reader = createRootReader(\"map: bar\");\n\n\t\tassert_exception(reader[\"map\"].useIndex().isMap());\n\t}\n\n\treturn 0;\n})();\n\n\nstatic auto dummyTestRead = ([]\n{\n\n\n\t// pair tests\n\t{\n\t\tauto reader = createRootReader(\"foo2: [1, 2]\");\n\t\tstd::pair<int, int> p;\n\n\t\tassert_noexcept(!reader.tryRead(\"foo\", p));\n\t}\n\n\t{\n\t\tauto reader = createRootReader(\"foo: [1, 2]\");\n\t\tstd::pair<int, int> p;\n\n\t\tassert_noexcept(reader.tryRead(\"foo\", p));\n\t\tassert(p.first == 1);\n\t\tassert(p.second == 2);\n\t}\n\n\t{\n\t\tauto reader = createRootReader(\"foo: [1, 2, 3]\");\n\t\tstd::pair<int, int> p;\n\n\t\tassert_exception(reader.tryRead(\"foo\", p));\n\t}\n\n\t{\n\t\tauto reader = createRootReader(\"foo: [1]\");\n\t\tstd::pair<int, int> p;\n\n\t\tassert_exception(reader.tryRead(\"foo\", p));\n\t}\n\n\t{\n\t\tauto reader = createRootReader(\"foo: 2\");\n\t\tstd::pair<int, int> p;\n\n\t\tassert_exception(reader.tryRead(\"foo\", p));\n\t}\n\n\n\t// tuple tests\n\t{\n\t\tauto reader = createRootReader(\"foo2: [1, 2]\");\n\t\tstd::tuple<int, int> p;\n\n\t\tassert_noexcept(!reader.tryRead(\"foo\", p));\n\t}\n\n\t{\n\t\tauto reader = createRootReader(\"foo: [1, 2, 32]\");\n\t\tstd::tuple<int, int, int> p;\n\n\t\tassert(reader.tryRead(\"foo\", p));\n\t\tassert(std::get<0>(p) == 1);\n\t\tassert(std::get<1>(p) == 2);\n\t\tassert(std::get<2>(p) == 32);\n\t}\n\n\t{\n\t\tauto reader = createRootReader(\"foo: [1, 2]\");\n\t\tstd::tuple<int, int> p;\n\n\t\tassert_noexcept(reader.tryRead(\"foo\", p));\n\t\tassert(std::get<0>(p) == 1);\n\t\tassert(std::get<1>(p) == 2);\n\t}\n\n\t{\n\t\tauto reader = createRootReader(\"foo: [13]\");\n\t\tstd::tuple<int> p;\n\n\t\tassert(reader.tryRead(\"foo\", p));\n\t\tassert(std::get<0>(p) == 13);\n\t}\n\n\t{\n\t\tauto reader = createRootReader(\"foo: [1]\");\n\t\tstd::tuple<int, int> p;\n\n\t\tassert_exception(reader.tryRead(\"foo\", p));\n\t}\n\n\t{\n\t\tauto reader = createRootReader(\"foo: [1, 2, 3]\");\n\t\tstd::tuple<int, int> p;\n\n\t\tassert_exception(reader.tryRead(\"foo\", p));\n\t}\n\n\n\t// array\n\t{\n\t\tauto reader = createRootReader(\"foo2: [1, 2]\");\n\t\tstd::array<int, 2> p;\n\n\t\tassert(!reader.tryRead(\"foo\", p));\n\t}\n\n\t{\n\t\tauto reader = createRootReader(\"foo: [1, 2]\");\n\t\tstd::array<int, 2> p;\n\n\t\tassert_noexcept(reader.tryRead(\"foo\", p));\n\t\tassert(std::get<0>(p) == 1);\n\t\tassert(std::get<1>(p) == 2);\n\t}\n\n\t{\n\t\tauto reader = createRootReader(\"foo: [1, 2, 42, 13]\");\n\t\tstd::array<int, 4> p;\n\n\t\tassert_noexcept(reader.tryRead(\"foo\", p));\n\t\tassert(std::get<0>(p) == 1);\n\t\tassert(std::get<1>(p) == 2);\n\t\tassert(std::get<2>(p) == 42);\n\t\tassert(std::get<3>(p) == 13);\n\t}\n\n\t{\n\t\tauto reader = createRootReader(\"foo: [1, 2, 3]\");\n\t\tstd::array<int, 2> p;\n\n\t\tassert_exception(reader.tryRead(\"foo\", p));\n\t}\n\n\t{\n\t\tauto reader = createRootReader(\"foo: [1]\");\n\t\tstd::array<int, 2> p;\n\n\t\tassert_exception(reader.tryRead(\"foo\", p));\n\t}\n\n\n\t{\n\t\tauto reader = createRootReader(\"foo: 1\");\n\t\tOpenXcom::NullableValue<int> p;\n\n\t\tassert_noexcept(reader.tryRead(\"foo\", p));\n\t\tassert(p.isValue());\n\t\tassert(p.getValueOrDefualt() == 1);\n\t}\n\n\t{\n\t\tauto reader = createRootReader(\"foo: -42\");\n\t\tOpenXcom::NullableValue<int> p;\n\n\t\tassert_noexcept(reader.tryRead(\"foo\", p));\n\t\tassert(p.isValue());\n\t\tassert(p.getValueOrDefualt() == -42);\n\t}\n\n\t{\n\t\tauto reader = createRootReader(\"foo: ~\");\n\t\tOpenXcom::NullableValue<int> p;\n\n\t\tassert_noexcept(reader.tryRead(\"foo\", p));\n\t\tassert(p.isNull());\n\t\tassert(p.getValueOrDefualt() == 0);\n\t}\n\n\t{\n\t\tauto reader = createRootReader(\"foo: []\");\n\t\tOpenXcom::NullableValue<int> p;\n\n\t\tassert_exception(reader.tryRead(\"foo\", p));\n\t}\n\n\n\t{\n\t\tauto reader = createRootReader(\"foo: true\");\n\t\tOpenXcom::NullableValue<bool> p;\n\n\t\tassert_noexcept(reader.tryRead(\"foo\", p));\n\t\tassert(p.isValue());\n\t\tassert(p.getValueOrDefualt() == true);\n\t}\n\n\n\t{\n\t\tauto reader = createRootReader(\"foo: false\");\n\t\tOpenXcom::NullableValue<bool> p;\n\n\t\tassert_noexcept(reader.tryRead(\"foo\", p));\n\t\tassert(p.isValue());\n\t\tassert(p.getValueOrDefualt() == false);\n\t}\n\n\t{\n\t\tauto reader = createRootReader(\"foo: ~\");\n\t\tOpenXcom::NullableValue<bool> p;\n\n\t\tassert_noexcept(reader.tryRead(\"foo\", p));\n\t\tassert(p.isNull());\n\t\tassert(p.getValueOrDefualt() == false);\n\t}\n\n\t{\n\t\tauto reader = createRootReader(\"foo: []\");\n\t\tOpenXcom::NullableValue<bool> p;\n\n\t\tassert_exception(reader.tryRead(\"foo\", p));\n\t}\n\n\n\treturn 0;\n})();\n\n#endif\n"
  },
  {
    "path": "src/Engine/Yaml.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2024 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n// the support for vector/map that rapidyaml provides is sadly not backward-compatible with yaml-cpp's due to\n// the fact that yaml-cpp clears collections before deserializing into them. These define's disable the support.\n#define _C4_YML_STD_MAP_HPP_\n#define _C4_YML_STD_VECTOR_HPP_\n\n#ifdef _MSC_VER\n#pragma warning(push)\n#pragma warning(disable : 4668 6011 6255 6293 6386 26439 26495 26498 26819)\n#elif defined(__GNUC__)\n#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Wredundant-decls\"\n#endif\n\n#include \"../../libs/rapidyaml/ryml.hpp\"\n#include \"../../libs/rapidyaml/ryml_std.hpp\"\n\n#ifdef _MSC_VER\n#pragma warning(pop)\n#elif defined(__GNUC__)\n#pragma GCC diagnostic pop\n#endif\n\n#include <map>\n#include <vector>\n#include <memory>\n#include <unordered_map>\n#include <optional>\n#include <c4/format.hpp>\n#include <c4/type_name.hpp>\n#include \"../Engine/CrossPlatform.h\"\n#include \"../Engine/NullableValue.h\"\n\n//hash function for ryml::csubstr for unordered_map -> just calls the same thing std::hash<std::string> does\ntemplate <>\nstruct std::hash<ryml::csubstr> { std::size_t operator()(const ryml::csubstr& k) const; };\n\nnamespace OpenXcom\n{\n\nnamespace YAML\n{\n\nclass YamlRootNodeReader;\nclass YamlRootNodeWriter;\n\n\nvoid setGlobalErrorHandler();\n\n\n/// Basic string wrapper to differentiate from normal strings\nstruct YamlString\n{\n\tstd::string yaml;\n\n\tYamlString() = default;\n\tYamlString(std::string yamlString) : yaml{std::move(yamlString)} { }\n};\n\n\n/// Basic exception class to distinguish YAML exceptions from the rest.\nclass Exception : public std::runtime_error\n{\npublic:\n\tException(const std::string& msg) : runtime_error{msg} { }\n};\n\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tYamlNodeReader\n////////////////////////////////////////////////////////////\n\n\nclass YamlNodeReader\n{\nprotected:\n\tryml::ConstNodeRef _node;\n\tstd::optional<std::unordered_map<ryml::csubstr, ryml::id_type>> _index;\n\tmutable ryml::id_type _nextChildId;\n\n\tryml::ConstNodeRef getChildNode(const ryml::csubstr& key) const;\n\tryml::ConstNodeRef findChildNode(const ryml::csubstr& key) const;\n\t/// Throws an error when failed to parse a node's value into the expected type\n\tvoid throwTypeError(const ryml::ConstNodeRef& node, const ryml::cspan<char>& type) const;\n\t/// Throws an error when failed to find node\n\tvoid throwNodeError(const std::string& what) const;\n\npublic:\n\tYamlNodeReader(); // vector demands a default constructor despite it never being used\n\tYamlNodeReader(const YamlNodeReader& other) = default;\n\tYamlNodeReader(YamlNodeReader&& other) noexcept = default;\n\tYamlNodeReader(const YamlRootNodeReader&) = delete; // no slicing allowed\n\n\tYamlNodeReader(const ryml::ConstNodeRef& node);\n\tYamlNodeReader(const ryml::ConstNodeRef& node, bool useIndex);\n\n\t/// Returns a copy of the current mapping container with O(1) access to the children. O(n) is spent building the index.\n\tYamlNodeReader useIndex() const;\n\n\t/// Returns a string_view wrapping the key. No string construction or deserialization occurs.\n\tstd::string_view key() const;\n\n\t/// Returns a string_view wrapping the value. No string construction or deserialization occurs.\n\tstd::string_view val() const;\n\n\n\t/// Deserializes the value of the found child into the outputValue. Throws if the node is invalid or the key doesn't exist.\n\ttemplate <typename OutputType>\n\tvoid readNode(ryml::csubstr key, OutputType& outputValue) const;\n\n\t/// Deserializes the value of the found child into the outputValue. If the node is invalid or the key doesn't exist, outputValue is set to defaultValue.\n\ttemplate <typename OutputType>\n\tvoid readNode(ryml::csubstr key, OutputType& outputValue, const OutputType& defaultValue) const;\n\n\t/// Returns a deserialized key of the current node. Throws if the node is invalid or itself has no key.\n\ttemplate <typename OutputType>\n\tOutputType readKey() const;\n\n\t/// Returns a deserialized key of the current node, or a default value if the node is invalid or itself has no key\n\ttemplate <typename OutputType>\n\tOutputType readKey(const OutputType& defaultValue) const;\n\n\t/// Returns a deserialized value of the current node. Throws if the node is invalid.\n\ttemplate <typename OutputType>\n\tOutputType readVal() const;\n\n\t/// Returns a deserialized value of the current node, or a default value if the node is invalid\n\ttemplate <typename OutputType>\n\tOutputType readVal(const OutputType& defaultValue) const;\n\n\t/// Returns a deserialized binary value of the current node. Throws if the node is invalid.\n\tstd::vector<char> readValBase64() const;\n\n\n\t/// Returns false if the node is invalid or the key doesn't exist. Otherwise returns true and deserializes the value of the found child into the outputValue.\n\ttemplate <typename OutputType>\n\tbool tryRead(ryml::csubstr key, OutputType& outputValue) const;\n\n\t/// Returns false if the node is invalid or the key doesn't exist. Otherwise returns true and deserializes the value of the found child into the outputValue.\n\ttemplate <typename ReadType, typename OutputType>\n\tbool tryReadAs(ryml::csubstr key, OutputType& outputValue) const\n\t{\n\t\tstatic_assert(std::is_integral<ReadType>::value, \"tryReadAs only supported for int like types\");\n\t\tReadType temp = {};\n\t\tif (tryRead(key, temp))\n\t\t{\n\t\t\toutputValue = static_cast<OutputType>(temp);\n\t\t\treturn true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/// Returns false if the node is invalid or itself has no key. Otherwise returns true and deserializes the key of the current node into the outputValue.\n\ttemplate <typename OutputType>\n\tbool tryReadKey(OutputType& outputValue) const;\n\n\t/// Returns false if the node is invalid. Otherwise returns true and deserializes the value of the current node into the outputValue.\n\ttemplate <typename OutputType>\n\tbool tryReadVal(OutputType& outputValue) const;\n\n\n\t/// Returns the number of children of the current node. O(n) complexity, or O(1) if index is used.\n\tsize_t childrenCount() const;\n\n\t/// Builds a vector of children and retuns it\n\tstd::vector<YamlNodeReader> children() const;\n\n\t/// Returns whether the current node is valid. Just use the bool operator instead.\n\tbool isValid() const;\n\t/// Returns true if the current node is a mapping container\n\tbool isMap() const;\n\t/// Returns true if the current node is a sequence container\n\tbool isSeq() const;\n\t/// Returns true if the current node has a scalar value (empty strings and null constants count)\n\tbool hasVal() const;\n\t/// Returns true if the current node has a scalar value and this value is one of the null constants\n\tbool hasNullVal() const;\n\t/// Returns true if the current node has a scalar value and an explicit tag\n\tbool hasValTag() const;\n\n\t/// Returns true if the node is valid, has a tag, and the tag is a core tag\n\tbool hasValTag(ryml::YamlTag_e tag) const;\n\t/// Returns true if the node is valid, has a tag, and the tag's name equals tagName\n\tbool hasValTag(const std::string& tagName) const;\n\t/// Returns node's value's tag, or an empty string if there is none\n\tstd::string getValTag() const;\n\n\t/// Serializes the node and its descendants to a YamlString\n\tconst YamlString emit() const;\n\t/// Serializes the node's descendants to a YamlString\n\tconst YamlString emitDescendants() const;\n\t/// Serializes the node's descendants, plus default values, to a YamlString\n\tconst YamlString emitDescendants(const YamlNodeReader& defaultValuesReader) const;\n\n\t/// Returns an object that contains data on where the current node is located in the original yaml\n\tryml::Location getLocationInFile() const;\n\n\t/// Returns a child in the current mapping container or an invalid child\n\tYamlNodeReader operator[](ryml::csubstr key) const;\n\t/// Returns a child at a specific position or an invalid child\n\tYamlNodeReader operator[](size_t pos) const;\n\t/// Returns whether the current node is valid\n\texplicit operator bool() const;\n\n\tfriend YamlRootNodeReader;\n\tfriend YamlRootNodeWriter;\n};\n\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tYamlRootNodeReader\n////////////////////////////////////////////////////////////\n\n\nclass YamlRootNodeReader : public YamlNodeReader\n{\nprivate:\n\tstd::unique_ptr<ryml::EventHandlerTree> _eventHandler;\n\tstd::unique_ptr<ryml::Parser> _parser;\n\tstd::unique_ptr<ryml::Tree> _tree;\n\tstd::string _fileName;\n\n\tryml::Location getLocationInFile(const ryml::ConstNodeRef& node) const;\n\n\tvoid Parse(ryml::csubstr yaml, std::string fileName, bool withNodeLocations, bool resolveReferences);\n\npublic:\n\tYamlRootNodeReader(const std::string& fullFilePath, bool onlyInfoHeader = false, bool resolveReferences = true);\n\tYamlRootNodeReader(const RawData& data, const std::string& fileNameForError, bool resolveReferences = true);\n\tYamlRootNodeReader(const YamlString& yamlString, std::string description, bool resolveReferences = true);\n\tYamlRootNodeReader(YamlRootNodeReader&&) = delete;\n\n\t/// Returns base class to avoid slicing\n\tYamlNodeReader toBase() const;\n\n\tfriend YamlNodeReader;\n\tfriend YamlRootNodeWriter;\n};\n\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tYamlNodeWriter\n////////////////////////////////////////////////////////////\n\n\nclass YamlNodeWriter\n{\nprotected:\n\tryml::NodeRef _node;\n\npublic:\n\tYamlNodeWriter(ryml::NodeRef node);\n\tYamlNodeWriter(const YamlNodeWriter& other) = default;\n\tYamlNodeWriter(YamlNodeWriter&& other) noexcept = default;\n\tYamlNodeWriter(YamlRootNodeWriter&&) = delete; // no slicing allowed\n\n\t/// Converts writer to a reader\n\tYamlNodeReader toReader();\n\n\t/// Adds a container child to the current sequence container\n\tYamlNodeWriter write();\n\t/// Adds a container child to the current mapping container\n\tYamlNodeWriter operator[](ryml::csubstr key);\n\t/// Adds a scalar value child to the current sequence container, serializing the provided value\n\ttemplate <typename InputType>\n\tYamlNodeWriter write(const InputType& inputValue);\n\t/// Adds a scalar value child to the current mapping container, serializing the provided value\n\ttemplate <typename InputType>\n\tYamlNodeWriter write(ryml::csubstr key, const InputType& inputValue);\n\n\t/// Adds a scalar value child to the current mapping container, serializing the provided value\n\ttemplate <typename WriteType, typename InputType>\n\tYamlNodeWriter writeAs(ryml::csubstr key, const InputType& inputValue)\n\t{\n\t\tstatic_assert(std::is_integral<WriteType>::value, \"writeAs only supported for int like types\");\n\t\tWriteType temp = static_cast<WriteType>(inputValue);\n\t\treturn write(key, temp);\n\t}\n\n\t/// If the inputVector is not empty, adds a sequence container child to the current mapping container.\n\t/// The callback (YamlNodeWriter w, InputType val) should specify how to write a vector element to the sequence container.\n\ttemplate <typename InputType, typename Func>\n\tvoid write(ryml::csubstr key, const std::vector<InputType>& inputVector, Func callback);\n\t/// Adds a scalar value child to the current mapping container, serializing the provided binary data\n\tYamlNodeWriter writeBase64(ryml::csubstr key, char* data, size_t size);\n\n\t/// Try write value if is different that default\n\ttemplate <typename InputType>\n\tvoid tryWrite(ryml::csubstr key, const InputType& inputValue, const std::remove_reference_t<InputType>& defualtValue)\n\t{\n\t\tif (inputValue != defualtValue)\n\t\t{\n\t\t\twrite(key, inputValue);\n\t\t}\n\t}\n\n\t/// Try write value if is different that default\n\ttemplate <typename WriteType, typename InputType>\n\tvoid tryWriteAs(ryml::csubstr key, const InputType& inputValue, const std::remove_reference_t<InputType>& defualtValue)\n\t{\n\t\tif (inputValue != defualtValue)\n\t\t{\n\t\t\twriteAs<WriteType>(key, inputValue);\n\t\t}\n\t}\n\n\t/// Adds a value to the current node.\n\ttemplate <typename InputType>\n\tvoid setValue(const InputType& inputValue);\n\t/// Set node value to null\n\tvoid setValueNull();\n\n\t/// Marks the current node as a mapping container\n\tvoid setAsMap();\n\t/// Marks the current node as a sequence container\n\tvoid setAsSeq();\n\t/// Marks the current node to serialize as single-line flow-style\n\tvoid setFlowStyle();\n\t/// Marks the current node to serialize as multi-line block-style\n\tvoid setBlockStyle();\n\t/// Marks the current node to serialize the scalar in double quotes. Escapes non-printable ASCII characters.\n\tvoid setAsQuotedAndEscaped();\n\n\tvoid unsetAsMap();\n\tvoid unsetAsSeq();\n\n\t/// Saves a string to the internal buffer. In a rare case when a key isn't a string literal, this ensures its lifetime until the serialization is done.\n\tryml::csubstr saveString(const std::string& string);\n\n\t/// Emits a yaml string based on the current node and its subtree\n\tYamlString emit();\n\n\tfriend YamlRootNodeReader;\n\tfriend YamlRootNodeWriter;\n};\n\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tYamlRootNodeWriter\n////////////////////////////////////////////////////////////\n\n\nclass YamlRootNodeWriter : public YamlNodeWriter\n{\nprivate:\n\tstd::unique_ptr<ryml::EventHandlerTree> _eventHandler;\n\tstd::unique_ptr<ryml::Parser> _parser;\n\tstd::unique_ptr<ryml::Tree> _tree;\n\npublic:\n\tYamlRootNodeWriter();\n\tYamlRootNodeWriter(size_t bufferCapacity);\n\tYamlRootNodeWriter(YamlRootNodeWriter&&) = delete;\n\n\t/// Returns base class to avoid slicing\n\tYamlNodeWriter toBase();\n\n\tfriend YamlNodeReader;\n\tfriend YamlNodeWriter;\n\tfriend YamlRootNodeReader;\n};\n\n\n////////////////////////////////////////////////////////////\n//\t\tYamlNodeReader Template implementations\n////////////////////////////////////////////////////////////\n\n\ntemplate <typename OutputType>\nvoid YamlNodeReader::readNode(ryml::csubstr key, OutputType& outputValue) const\n{\n\tif (!tryRead(key, outputValue))\n\t{\n\t\tthrowNodeError(c4::formatrs<std::string>(\"missing node '{}'\", key));\n\t}\n}\n\ntemplate <typename OutputType>\nvoid YamlNodeReader::readNode(ryml::csubstr key, OutputType& outputValue, const OutputType& defaultValue) const\n{\n\tif (!tryRead(key, outputValue))\n\t\toutputValue = defaultValue;\n}\n\ntemplate <typename OutputType>\nOutputType YamlNodeReader::readKey() const\n{\n\tOutputType output = {};\n\tif (!tryReadKey(output))\n\t{\n\t\tthrowNodeError(\"invalid node's key\");\n\t}\n\treturn output;\n}\n\ntemplate <typename OutputType>\ninline OutputType YamlNodeReader::readKey(const OutputType& defaultValue) const\n{\n\tOutputType output = {};\n\tif (!tryReadKey(output))\n\t\toutput = defaultValue;\n\treturn output;\n}\n\ntemplate <typename OutputType>\nOutputType YamlNodeReader::readVal() const\n{\n\tOutputType output = {};\n\tif (!tryReadVal(output))\n\t{\n\t\tthrowNodeError(\"invalid node's value\");\n\t}\n\treturn output;\n}\n\ntemplate <typename OutputType>\nOutputType YamlNodeReader::readVal(const OutputType& defaultValue) const\n{\n\tOutputType output = {};\n\tif (!tryReadVal(output))\n\t\toutput = defaultValue;\n\treturn output;\n}\n\ntemplate <typename OutputType>\nbool YamlNodeReader::tryRead(ryml::csubstr key, OutputType& outputValue) const\n{\n\tif (_node.invalid())\n\t\treturn false;\n\tconst auto& child = getChildNode(key);\n\tif (child.invalid())\n\t\treturn false;\n\tif (std::is_same_v<std::remove_cv_t<std::remove_reference_t<OutputType> >, std::string> && !child.has_val())\n\t\tthrowTypeError(child, \"string\");\n\tif (std::is_integral_v<std::remove_reference_t<OutputType> > && !child.has_val())\n\t\tthrowTypeError(child, ryml::type_name<OutputType>());\n\tif (!read(child, &outputValue))\n\t\tthrowTypeError(child, ryml::type_name<OutputType>());\n\treturn true;\n}\n\ntemplate <typename OutputType>\nbool YamlNodeReader::tryReadKey(OutputType& outputValue) const\n{\n\tif (_node.invalid() || !_node.has_key())\n\t\treturn false;\n\t_node >> ryml::key(outputValue);\n\treturn true;\n}\n\ntemplate <typename OutputType>\nbool YamlNodeReader::tryReadVal(OutputType& outputValue) const\n{\n\tif (_node.invalid())\n\t\treturn false;\n\tif (std::is_same_v<std::remove_cv_t<std::remove_reference_t<OutputType> >, std::string> && !_node.has_val())\n\t\tthrowTypeError(_node, \"string\");\n\tif (std::is_integral_v<std::remove_reference_t<OutputType> > && !_node.has_val())\n\t\tthrowTypeError(_node, ryml::type_name<OutputType>());\n\tif (!read(_node, &outputValue))\n\t\tthrowTypeError(_node, ryml::type_name<OutputType>());\n\treturn true;\n}\n\n\n////////////////////////////////////////////////////////////\n//\t\tYamlNodeWriter Template implementations\n////////////////////////////////////////////////////////////\n\n\ntemplate <typename InputType>\ninline YamlNodeWriter YamlNodeWriter::write(const InputType& inputValue)\n{\n\treturn YamlNodeWriter(_node.append_child() << inputValue);\n}\n\ntemplate <typename InputType>\nYamlNodeWriter YamlNodeWriter::write(ryml::csubstr key, const InputType& inputValue)\n{\n\treturn YamlNodeWriter(_node.append_child({ ryml::KEY, key }) << inputValue);\n}\n\ntemplate <typename InputType, typename Func>\nvoid YamlNodeWriter::write(ryml::csubstr key, const std::vector<InputType>& inputVector, Func callback)\n{\n\tif (inputVector.empty())\n\t\treturn;\n\tYamlNodeWriter sequenceWriter(_node.append_child({ ryml::KEY, key }));\n\tsequenceWriter.setAsSeq();\n\tfor (const InputType& vectorElement : inputVector)\n\t{\n\t\tcallback(sequenceWriter, vectorElement);\n\t}\n}\n\ntemplate <typename InputType>\ninline void YamlNodeWriter::setValue(const InputType& inputValue)\n{\n\t_node << inputValue;\n}\n\n\n} // namespace YAML\n\n\n// Deserialization template for enums. We have to overload from_chars() instead of read(), because read() already has a template for all types -> template conflict\ntemplate <typename EnumType>\ntypename std::enable_if<std::is_enum<EnumType>::value, bool>::type inline from_chars(ryml::csubstr buf, EnumType* v) noexcept\n{\n\tint value = static_cast<int>(*v);\n\tbool result = ryml::atoi(buf, &value);\n\t*v = static_cast<EnumType>(value);\n\treturn result;\n}\n\ntemplate <typename EnumType>\ntypename std::enable_if<std::is_enum<EnumType>::value, size_t>::type inline to_chars(ryml::substr buf, EnumType v) noexcept\n{\n\treturn ryml::itoa(buf, (int)v);\n}\n\ntemplate<typename T>\nbool read(ryml::ConstNodeRef const& n, NullableValue<T>* val)\n{\n\tif (n.has_val() == false) return false;\n\n\tif (n.val_is_null())\n\t{\n\t\tval->setNull();\n\t\treturn true;\n\t}\n\telse\n\t{\n\t\tT v = {};\n\t\tif (read(n, &v))\n\t\t{\n\t\t\tval->setValue(v);\n\t\t\treturn val->isValue(); // check for case when someone used reserved \"null\" value\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n}\n\n} // namespace OpenXcom\n\n\n////////////////////////////////////////////////////////////\n//\t\tFunctions for types defined in other libraries\n////////////////////////////////////////////////////////////\n\n\n// r/w overloads need to be defined in the same namespace the type is defined in\nnamespace std\n{\n\n// Deserializing \"\" should succeed when output type is std::string\nbool read(ryml::ConstNodeRef const& n, std::string* str);\n\n// for backwards compatibility, pairs should be serialized as sequences with 2 elements.\ntemplate <class T1, class T2>\nbool read(ryml::ConstNodeRef const& n, std::pair<T1, T2>* pair)\n{\n\tif (!n.is_seq() || n.num_children() != 2) return false;\n\n\tn.first_child() >> pair->first;\n\tn.last_child() >> pair->second;\n\n\treturn true;\n}\n\ntemplate <class T1, class T2>\nvoid write(ryml::NodeRef* n, std::pair<T1, T2> const& pair)\n{\n\t*n |= ryml::SEQ;\n\tn->append_child() << pair.first;\n\tn->append_child() << pair.second;\n}\n\n\n// tuple should be serialized as sequences with n elements.\ntemplate <class... T>\nbool read(ryml::ConstNodeRef const& n, std::tuple<T...>* tuple)\n{\n\tif (!n.is_seq() || n.num_children() != sizeof...(T)) return false;\n\n\tauto curr = n.first_child();\n\n\tstd::apply(\n\t\t[&](auto&& first, auto&&... args)\n\t\t{\n\t\t\tcurr >> first;\n\n\t\t\t(\n\t\t\t\t(curr = curr.next_sibling(), curr >> args), ...\n\t\t\t);\n\t\t},\n\t\t*tuple\n\t);\n\n\treturn true;\n}\n\ntemplate <class... T>\nvoid write(ryml::NodeRef* n, std::tuple<T...> const& tuple)\n{\n\t*n |= ryml::SEQ;\n\n\tstd::apply(\n\t\t[&](auto&&... args)\n\t\t{\n\t\t\t(\n\t\t\t\t(n->append_child() << args), ...\n\t\t\t);\n\t\t},\n\t\t*tuple\n\t);\n}\n\n// array.\ntemplate <typename T, std::size_t I>\nbool read(ryml::ConstNodeRef const& n, std::array<T, I>* array)\n{\n\tif (!n.is_seq() || n.num_children() != I) return false;\n\n\tauto curr = n.first_child();\n\n\tstd::apply(\n\t\t[&](auto&& first, auto&&... args)\n\t\t{\n\t\t\tcurr >> first;\n\n\t\t\t(\n\t\t\t\t(curr = curr.next_sibling(), curr >> args), ...\n\t\t\t);\n\t\t},\n\t\t*array\n\t);\n\n\treturn true;\n}\n\ntemplate <typename T, std::size_t I>\nvoid write(ryml::NodeRef* n, std::array<T, I>const& array)\n{\n\t*n |= ryml::SEQ;\n\n\tstd::apply(\n\t\t[&](auto&&... args)\n\t\t{\n\t\t\t(\n\t\t\t\t(n->append_child() << args), ...\n\t\t\t);\n\t\t},\n\t\tarray\n\t);\n}\n\n\n} // namespace std\n\n\nnamespace c4::yml\n{\n\n// Serializing bool should output the string version instead of 0 and 1\nvoid write(ryml::NodeRef* n, bool const& val);\n\n// Copy from c4/yml/std/vector.hpp\ntemplate <class V, class Alloc>\nvoid write(c4::yml::NodeRef* n, std::vector<V, Alloc> const& vec)\n{\n\t*n |= c4::yml::SEQ;\n\tfor (V const& v : vec)\n\t\tn->append_child() << v;\n}\n\n// Backwards-compatibility: deserializing into a vector should clear the collection before adding to it\ntemplate <class V, class Alloc>\nbool read(c4::yml::ConstNodeRef const& n, std::vector<V, Alloc>* vec)\n{\n\tvec->clear();\n\tC4_SUPPRESS_WARNING_GCC_WITH_PUSH(\"-Wuseless-cast\")\n\tvec->resize(static_cast<size_t>(n.num_children()));\n\tC4_SUPPRESS_WARNING_GCC_POP\n\tsize_t pos = 0;\n\tfor (ConstNodeRef const child : n)\n\t\tchild >> (*vec)[pos++];\n\treturn true;\n}\n\n// Backwards-compatibility: deserializing into a vector should clear the collection before adding to it\n/** specialization: std::vector<bool> uses std::vector<bool>::reference as\n * the return value of its operator[]. */\ntemplate <class Alloc>\nbool read(c4::yml::ConstNodeRef const& n, std::vector<bool, Alloc>* vec)\n{\n\tvec->clear();\n\tC4_SUPPRESS_WARNING_GCC_WITH_PUSH(\"-Wuseless-cast\")\n\tvec->resize(static_cast<size_t>(n.num_children()));\n\tC4_SUPPRESS_WARNING_GCC_POP\n\tsize_t pos = 0;\n\tbool tmp = {};\n\tfor (ConstNodeRef const child : n)\n\t{\n\t\tchild >> tmp;\n\t\t(*vec)[pos++] = tmp;\n\t}\n\treturn true;\n}\n\n// Copy from c4/yml/std/map.hpp\ntemplate <class K, class V, class Less, class Alloc>\nvoid write(c4::yml::NodeRef* n, std::map<K, V, Less, Alloc> const& m)\n{\n\t*n |= c4::yml::MAP;\n\tfor (auto const& C4_RESTRICT p : m)\n\t{\n\t\tauto ch = n->append_child();\n\t\tch << c4::yml::key(p.first);\n\t\tch << p.second;\n\t}\n}\n\n// Backwards-compatibility: deserializing into maps should clear the collection before adding to it\n// Also, element constructor inside the loop\ntemplate <class K, class V, class Less, class Alloc>\nbool read(c4::yml::ConstNodeRef const& n, std::map<K, V, Less, Alloc>* m)\n{\n\tm->clear();\n\tfor (ConstNodeRef const ch : n)\n\t{\n\t\tK k{};\n\t\tV v{};\n\t\tch >> c4::yml::key(k);\n\t\tch >> v;\n\t\tm->emplace(std::make_pair(std::move(k), std::move(v)));\n\t}\n\treturn true;\n}\n\n} // namespace c4::yml\n"
  },
  {
    "path": "src/Engine/Zoom.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"Zoom.h\"\n\n#include \"Surface.h\"\n#include \"Logger.h\"\n#include \"Options.h\"\n#include \"Screen.h\"\n\n#include \"OpenGL.h\"\n\n// Scale2X\n#include \"Scalers/scalebit.h\"\n\n// HQX\n\n#include \"Scalers/hqx.h\"\n\n// xBRZ\n\n#include \"Scalers/xbrz.h\"\n\n#if (_MSC_VER >= 1400) || (defined(__MINGW32__) && defined(__SSE2__))\n\n#ifndef __SSE2__\n#define __SSE2__ true\n#endif\n// probably Visual Studio (or Intel C++ which should also work)\n#include <intrin.h>\n#endif\n\n#ifdef __GNUC__\n#if (__i386__ || __x86_64__)\n#include <cpuid.h>\n#endif\n#endif\n\n#ifdef __SSE2__\n#include <emmintrin.h> // for SSE2 intrinsics; see http://msdn.microsoft.com/en-us/library/has3d153%28v=vs.71%29.aspx\n#endif\n\n\n\nnamespace OpenXcom\n{\n\n\n/**\n * Optimized 8-bit zoomer for resizing by a factor of 2. Doesn't flip.\n * Used internally by _zoomSurfaceY() below.\n * source and dest. widths must be multiples of 8 bytes for 64-bit access\n *\n * @param src The surface to zoom (input).\n * @param dst The zoomed surface (output).\n * @return 0 for success or -1 for error.\n */\n/*\nstatic int zoomSurface2X_64bit(SDL_Surface *src, SDL_Surface *dst)\n{\n\tUint64 dataSrc;\n\tUint64 dataDst;\n\tUint8 *pixelSrc = (Uint8*)src->pixels;\n\tUint8 *pixelDstRow = (Uint8*)dst->pixels;\n\tint sx, sy;\n\tstatic bool proclaimed = false;\n\n\tif (!proclaimed)\n\t{\n\t\tproclaimed = true;\n\t\tLog(LOG_INFO) << \"Using somewhat fast 2X zoom routine.\";\n\t}\n\n\tfor (sy = 0; sy < src->h; ++sy, pixelDstRow += dst->pitch*2)\n\t{\n\t\tUint64 *pixelDst = (Uint64*)pixelDstRow;\n\t\tUint64 *pixelDst2 = (Uint64*)(pixelDstRow + dst->pitch);\n\t\tfor (sx = 0; sx < src->w; sx += 8, pixelSrc += 8)\n\t\t{\n\t\t\tdataSrc = *((Uint64*) pixelSrc);\n\t\t\t// boo\n\t\t\t(void)SDL_SwapLE64(dataSrc);\n */\n/* expanded form of data shift:\n\t\t\tdataDst = (dataSrc & 0xFF) | ((dataSrc & 0xFF) << 8) |\n\t\t\t\t((dataSrc & 0xFF00 ) << 8) | ((dataSrc & 0xFF00)) << 16)  |\n\t\t\t\t((dataSrc & 0xFF0000) << 16) | ((dataSrc & 0xFF0000) << 24) |\n\t\t\t\t((dataSrc & 0xFF000000) << 24) | ((dataSrc & 0xFF000000) << 32);\n */\n\t\t\t// compact form, combining terms with equal multipliers (shifts)\n/*\n\t\t\tdataDst = (dataSrc & 0xFF) | ((dataSrc & 0xFFFF) << 8) |\n\t\t\t\t((dataSrc & 0xFFFF00) << 16)  |\n\t\t\t\t((dataSrc & 0xFFFF0000) << 24) |\n\t\t\t\t((dataSrc & 0xFF000000) << 32);\n\n\t\t\t*pixelDst = dataDst;\n\t\t\t*pixelDst2 = dataDst;\n\t\t\tpixelDst++; // forward 8 bytes!\n\t\t\tpixelDst2++;\n\t\t\tdataSrc >>= 32;\n\n\t\t\tdataDst = (dataSrc & 0xFF) | ((dataSrc & 0xFFFF) << 8) |\n\t\t\t\t((dataSrc & 0xFFFF00) << 16)  |\n\t\t\t\t((dataSrc & 0xFFFF0000) << 24) |\n\t\t\t\t((dataSrc & 0xFF000000) << 32);\n\n\t\t\t*pixelDst = dataDst;\n\t\t\t*pixelDst2 = dataDst;\n\t\t\tpixelDst++;\t// 8 bytes again\n\t\t\tpixelDst2++;\n\t\t}\n\t}\n\n\treturn 0;\n}\n */\n\n\n#if defined(__WORDSIZE) && (__WORDSIZE == 64) || defined(SIZE_MAX) && (SIZE_MAX > 0xFFFFFFFF)\n#else\n/**\n * Optimized 8-bit zoomer for resizing by a factor of 2. Doesn't flip.\n * 32-bit version for sad old x86 chips which run out of registers\n * with the 64-bit version.\n * Used internally by _zoomSurfaceY() below.\n * source and dest. widths must be multiples of 4 bytes for 32-bit access\n *\n * @param src The surface to zoom (input).\n * @param dst The zoomed surface (output).\n * @return 0 for success or -1 for error.\n */\n/*\nstatic int zoomSurface2X_32bit(SDL_Surface *src, SDL_Surface *dst)\n{\n\tUint32 dataSrc;\n\tUint32 dataDst;\n\tUint8 *pixelSrc = (Uint8*)src->pixels;\n\tUint8 *pixelDstRow = (Uint8*)dst->pixels;\n\tint sx, sy;\n\tstatic bool proclaimed = false;\n\n\tif (!proclaimed)\n\t{\n\t\tproclaimed = true;\n\t\tLog(LOG_INFO) << \"Using 32-bit 2X zoom routine.\";\n\t}\n\n\n\tfor (sy = 0; sy < src->h; ++sy, pixelDstRow += dst->pitch*2)\n\t{\n\t\tUint32 *pixelDst = (Uint32*)pixelDstRow;\n\t\tUint32 *pixelDst2 = (Uint32*)(pixelDstRow + dst->pitch);\n\t\tfor (sx = 0; sx < src->w; sx += 4, pixelSrc += 4)\n\t\t{\n\t\t\tdataSrc = *((Uint32*) pixelSrc);\n\n\t\t\t// boo\n\t\t\tdataSrc = SDL_SwapLE32(dataSrc);\n\n\t\t\tdataDst = SDL_SwapLE32( (dataSrc & 0xFF) | ((dataSrc & 0xFFFF) << 8) |\n\t\t\t\t((dataSrc & 0xFF00) << 16)  );\n\n\t\t\t*pixelDst = dataDst;\n\t\t\t*pixelDst2 = dataDst;\n\t\t\tpixelDst++; // forward 4 bytes!\n\t\t\tpixelDst2++;\n\n\t\t\tdataSrc >>= 16;\n\n\t\t\tdataDst = SDL_SwapLE32( (dataSrc & 0xFF) | ((dataSrc & 0xFFFF) << 8) |\n\t\t\t\t((dataSrc & 0xFF00) << 16)  );\n\n\t\t\t*pixelDst = dataDst;\n\t\t\t*pixelDst2 = dataDst;\n\t\t\tpixelDst++; // forward 4 bytes!\n\t\t\tpixelDst2++;\n\t\t}\n\n\t}\n\n\treturn 0;\n}\n */\n#endif\n\n/**\n * Optimized 8-bit zoomer for resizing by a factor of 4. Doesn't flip.\n * Used internally by _zoomSurfaceY() below.\n * source and dest. widths must be multiples of 8 bytes for 64-bit access\n *\n * @param src The surface to zoom (input).\n * @param dst The zoomed surface (output).\n * @return 0 for success or -1 for error.\n */\n/*\nstatic int zoomSurface4X_64bit(SDL_Surface *src, SDL_Surface *dst)\n{\n\tUint64 dataSrc;\n\tUint64 dataDst;\n\tUint8 *pixelSrc = (Uint8*)src->pixels;\n\tUint8 *pixelDstRow = (Uint8*)dst->pixels;\n\tint sx, sy;\n\tstatic bool proclaimed = false;\n\n\tif (!proclaimed)\n\t{\n\t\tproclaimed = true;\n\t\tLog(LOG_INFO) << \"Using modestly fast 4X zoom routine.\";\n\t}\n\n\tfor (sy = 0; sy < src->h; ++sy, pixelDstRow += dst->pitch*4)\n\t{\n\t\tUint8 *pixelDst = pixelDstRow;\n\n\t\tfor (sx = 0; sx < src->w; sx += 8, pixelSrc += 8)\n\t\t{\n\t\t\tdataSrc = *((Uint64*) pixelSrc);\n\t\t\t// boo\n\t\t\t(void)SDL_SwapLE64(dataSrc);\n */\n\t\t\t/* expanded form of data shift:\n\t\t\tdataDst = (dataSrc & 0xFF) | ((dataSrc & 0xFF) << 8) |\n\t\t\t\t((dataSrc & 0xFF) << 16 | ((datasrc & 0xFF) << 24) |\n\t\t\t\t((dataSrc & 0xFF00 ) << 24) | ((dataSrc & 0xFF00) << 32)  |\n\t\t\t\t((dataSrc & 0xFF00 ) << 40) | ((dataSrc & 0xFF00) << 48) ;\n\t\t\t\t */\n/*\n\t\t\tfor (int i = 0; i < 4; ++i)\n\t\t\t{\n\t\t\t\t// compact form, combining terms with equal multipliers (shifts)\n\t\t\t\tdataDst = (dataSrc & 0xFF) | ((dataSrc & 0xFF) << 8) |\n\t\t\t\t\t((dataSrc & 0xFF) << 16) |\n\t\t\t\t\t((dataSrc & 0xFFFF ) << 24) | ((dataSrc & 0xFF00) << 32)  |\n\t\t\t\t\t((dataSrc & 0xFF00 ) << 40) | ((dataSrc & 0xFF00) << 48) ;\n\n\t\t\t\t*((Uint64*)pixelDst) = dataDst;\n\t\t\t\t*((Uint64*)(pixelDst + dst->pitch)) = dataDst;\n\t\t\t\t*((Uint64*)(pixelDst + dst->pitch*2)) = dataDst;\n\t\t\t\t*((Uint64*)(pixelDst + dst->pitch*3)) = dataDst;\n\t\t\t\tpixelDst+=8; // forward 8 bytes!\n\t\t\t\tdataSrc >>= 16;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn 0;\n}\n */\n\n\n#if defined(__WORDSIZE) && (__WORDSIZE == 64) || defined(SIZE_MAX) && (SIZE_MAX > 0xFFFFFFFF)\n#else\n/**\n * Optimized 8-bit zoomer for resizing by a factor of 4. Doesn't flip.\n * 32-bit version.\n * Used internally by _zoomSurfaceY() below.\n * source and dest. widths must be multiples of 4 bytes for 32-bit access\n *\n * @param src The surface to zoom (input).\n * @param dst The zoomed surface (output).\n * @return 0 for success or -1 for error.\n */\n/*\nstatic int zoomSurface4X_32bit(SDL_Surface *src, SDL_Surface *dst)\n{\n\tUint32 dataSrc;\n\tUint32 dataDst;\n\tUint8 *pixelSrc = (Uint8*)src->pixels;\n\tUint8 *pixelDstRow = (Uint8*)dst->pixels;\n\tint sx, sy;\n\tstatic bool proclaimed = false;\n\n\tif (!proclaimed)\n\t{\n\t\tproclaimed = true;\n\t\tLog(LOG_INFO) << \"Using 32-bit 4X zoom routine.\";\n\t}\n\n\tfor (sy = 0; sy < src->h; ++sy, pixelDstRow += dst->pitch*4)\n\t{\n\t\tUint32 *pixelDst = (Uint32*)pixelDstRow;\n\t\tUint32 *pixelDst2 = (Uint32*)(pixelDstRow + dst->pitch);\n\t\tUint32 *pixelDst3 = (Uint32*)(pixelDstRow + 2*dst->pitch);\n\t\tUint32 *pixelDst4 = (Uint32*)(pixelDstRow + 3*dst->pitch);\n\t\tfor (sx = 0; sx < src->w; sx += 4, pixelSrc += 4)\n\t\t{\n\t\t\tdataSrc = *((Uint32*) pixelSrc);\n\t\t\t// boo\n\t\t\tdataSrc = SDL_SwapLE32(dataSrc);\n\n\t\t\tfor (int i = 0; i < 4; ++i)\n\t\t\t{\n\t\t\t\tdataDst = SDL_SwapLE32( (dataSrc & 0xFF) | ((dataSrc & 0xFF) << 8) |\n\t\t\t\t\t((dataSrc & 0xFF) << 16) | ((dataSrc & 0xFF ) << 24) );\n\n\t\t\t\t*pixelDst = dataDst;\n\t\t\t\t*pixelDst2 = dataDst;\n\t\t\t\t*pixelDst3 = dataDst;\n\t\t\t\t*pixelDst4 = dataDst;\n\t\t\t\tpixelDst++; // forward 4 bytes!\n\t\t\t\tpixelDst2++;\n\t\t\t\tpixelDst3++;\n\t\t\t\tpixelDst4++;\n\t\t\t\tdataSrc >>= 8;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn 0;\n}\n */\n#endif\n\n/**\n * Optimized 8-bit zoomer for resizing by a factor of 4. Doesn't flip.\n * 32-bit version.\n * Used internally by _zoomSurfaceY() below.\n * source and dest. widths must be multiples of 4 bytes for 32-bit access\n *\n * @param src The surface to zoom (input).\n * @param dst The zoomed surface (output).\n * @return 0 for success or -1 for error.\n */\n/*\nstatic int zoomSurface2X_XAxis_32bit(SDL_Surface *src, SDL_Surface *dst)\n{\n\tUint32 dataSrc;\n\tUint32 dataDst;\n\tUint8 *pixelSrc;\n\tUint8 *pixelDstRow = (Uint8*)dst->pixels;\n\tUint8 *pixelSrcRow = (Uint8*)src->pixels;\n\tint sx;\n\tint dsty;\n\tstatic bool proclaimed = false;\n\n\tstatic Uint32 *say = 0;\n\tUint32 *csay;\n\tint csy;\n\n\tif (!proclaimed)\n\t{\n\t\tproclaimed = true;\n\t\tLog(LOG_INFO) << \"Using mediocre scaling routine due to screen height.\";\n\t}\n\n\tif ((say = (Uint32 *) realloc(say, (dst->h + 1) * sizeof(Uint32))) == NULL) {\n\t\tsay = 0;\n\t\treturn (-1);\n\t}\n\n\tcsy = 0;\n\tcsay = say;\n\tfor (int y = 0; y < dst->h; y++) {\n\t\tcsy += src->h;\n\t\t*csay = 0;\n\t\twhile (csy >= dst->h) {\n\t\t\tcsy -= dst->h;\n\t\t\t(*csay)++;\n\t\t}\n\t\t(*csay) *= src->pitch;\n\t\tcsay++;\n\t}\n\n\tfor (dsty = 0; dsty < dst->h; ++dsty, pixelDstRow += dst->pitch)\n\t{\n\t\tif (!say[dsty]) continue;\n\n\t\tUint32 *pixelDst = (Uint32*)pixelDstRow;\n\t\tpixelSrc = pixelSrcRow;\n\t\tpixelSrcRow += say[dsty];\n\n\t\tfor (sx = 0; sx < src->w; sx += 4, pixelSrc += 4)\n\t\t{\n\t\t\tdataSrc = *((Uint32*) pixelSrc);\n\t\t\t// boo\n\t\t\tdataSrc = SDL_SwapLE32(dataSrc);\n\n\t\t\tfor (int i = 0; i < 2; ++i)\n\t\t\t{\n\t\t\t\tdataDst = SDL_SwapLE32( (dataSrc & 0xFF) | ((dataSrc & 0xFFFF) << 8) |\n\t\t\t\t\t((dataSrc & 0xFF00) << 16) );\n\n\t\t\t\tint j = 0;\n\t\t\t\tdo\n\t\t\t\t{\n\t\t\t\t\tif (dsty + j >= dst->h) break;\n\n\t\t\t\t\t*(pixelDst + (dst->pitch/sizeof(Uint32))*j) = dataDst;\n\t\t\t\t} while (say[dsty + ++j] == 0); // fill in all relevant rows\n\n\t\t\t\tdataSrc >>= 16;\n\t\t\t\tpixelDst++; // forward 4 bytes!\n\t\t\t}\n\t\t}\n\t}\n\n\treturn 0;\n}\n */\n\n\n/**\n * Optimized 8-bit zoomer for resizing by a factor of 2. Doesn't flip.\n * 32-bit version.\n * Used internally by _zoomSurfaceY() below.\n * source and dest. widths must be multiples of 4 bytes for 32-bit access\n *\n * @param src The surface to zoom (input).\n * @param dst The zoomed surface (output).\n * @return 0 for success or -1 for error.\n */\n/*\nstatic int zoomSurface4X_XAxis_32bit(SDL_Surface *src, SDL_Surface *dst)\n{\n\tUint32 dataSrc;\n\tUint32 dataDst;\n\tUint8 *pixelSrc;\n\tUint8 *pixelDstRow = (Uint8*)dst->pixels;\n\tUint8 *pixelSrcRow = (Uint8*)src->pixels;\n\tint sx;\n\tint dsty;\n\tstatic bool proclaimed = false;\n\n\tstatic Uint32 *say = 0;\n\tUint32 *csay;\n\tint csy;\n\n\tif (!proclaimed)\n\t{\n\t\tproclaimed = true;\n\t\tLog(LOG_INFO) << \"Using mediocre scaling routine due to screen height.\";\n\t}\n\n\tif ((say = (Uint32 *) realloc(say, (dst->h + 1) * sizeof(Uint32))) == NULL) {\n\t\tsay = 0;\n\t\treturn (-1);\n\t}\n\n\tcsy = 0;\n\tcsay = say;\n\tfor (int y = 0; y < dst->h; y++) {\n\t\tcsy += src->h;\n\t\t*csay = 0;\n\t\twhile (csy >= dst->h) {\n\t\t\tcsy -= dst->h;\n\t\t\t(*csay)++;\n\t\t}\n\t\t(*csay) *= src->pitch;\n\t\tcsay++;\n\t}\n\n\tfor (dsty = 0; dsty < dst->h; ++dsty, pixelDstRow += dst->pitch)\n\t{\n\t\tif (!say[dsty]) continue;\n\n\t\tUint32 *pixelDst = (Uint32*)pixelDstRow;\n\t\tpixelSrc = pixelSrcRow;\n\t\tpixelSrcRow += say[dsty];\n\n\t\tfor (sx = 0; sx < src->w; sx += 4, pixelSrc += 4)\n\t\t{\n\t\t\tdataSrc = *((Uint32*) pixelSrc);\n\t\t\t// boo\n\t\t\tdataSrc = SDL_SwapLE32(dataSrc);\n\n\t\t\tfor (int i = 0; i < 4; ++i)\n\t\t\t{\n\t\t\t\tdataDst = SDL_SwapLE32( (dataSrc & 0xFF) | ((dataSrc & 0xFF) << 8) |\n\t\t\t\t\t((dataSrc & 0xFF) << 16) | ((dataSrc & 0xFF ) << 24) );\n\n\t\t\t\tint j = 0;\n\t\t\t\tdo\n\t\t\t\t{\n\t\t\t\t\tif (dsty + j >= dst->h) break;\n\n\t\t\t\t\t*(pixelDst + (dst->pitch/sizeof(Uint32))*j) = dataDst;\n\t\t\t\t} while (say[dsty + ++j] == 0); // fill in all relevant rows\n\n\t\t\t\tdataSrc >>= 8;\n\t\t\t\tpixelDst++; // forward 4 bytes!\n\t\t\t}\n\t\t}\n\t}\n\n\treturn 0;\n}\n */\n\n#ifdef __SSE2__\n/**\n * Optimized 8-bit zoomer for resizing by a factor of 4. Doesn't flip.\n * Used internally by _zoomSurfaceY() below.\n * This is an SSE2 version written with Intel intrinsics.\n * source and dest. widths must be multiples of 16 bytes for 128-bit access\n * and it would help if they were aligned properly... :(\n *\n * @param src The surface to zoom (input).\n * @param dst The zoomed surface (output).\n * @return 0 for success or -1 for error.\n */\n/*\nstatic int zoomSurface4X_SSE2(SDL_Surface *src, SDL_Surface *dst)\n{\n\t__m128i dataSrc;\n\t__m128i dataDst;\n\tUint8 *pixelSrc = (Uint8*)src->pixels;\n\tUint8 *pixelDstRow = (Uint8*)dst->pixels;\n\tint sx, sy;\n\tstatic bool proclaimed = false;\n\n\tif (!proclaimed)\n\t{\n\t\tproclaimed = true;\n\t\tLog(LOG_INFO) << \"Using SSE2 4X zoom routine.\";\n\t}\n\n\tfor (sy = 0; sy < src->h; ++sy, pixelDstRow += dst->pitch*4)\n\t{\n\t\t__m128i *pixelDst =  (__m128i*)pixelDstRow;\n\t\t__m128i *pixelDst2 = (__m128i*)((Uint8*)pixelDstRow + dst->pitch);\n\t\t__m128i *pixelDst3 = (__m128i*)((Uint8*)pixelDstRow + dst->pitch*2);\n\t\t__m128i *pixelDst4 = (__m128i*)((Uint8*)pixelDstRow + dst->pitch*3);\n\t\tfor (sx = 0; sx < src->w; sx += 16, pixelSrc += 16)\n\t\t{\n\t\t\tdataSrc = *((__m128i*) pixelSrc);\n\n\t\t\t__m128i halfDone = _mm_unpacklo_epi8(dataSrc, dataSrc);\n\t\t\tdataDst = _mm_unpacklo_epi8(halfDone, halfDone);\n */\n/* #define WRITE_DST if ((char*)pixelDst4 + 128 > (char*)dst->pixels+(dst->w*dst->pitch)) { Log(LOG_ERROR) << \"HELL\"; exit(0); } \\ */\n#define WRITE_DST\t\t\t*(pixelDst++) = dataDst; \\\n\t\t\t*(pixelDst2++) = dataDst; \\\n\t\t\t*(pixelDst3++) = dataDst; \\\n\t\t\t*(pixelDst4++) = dataDst; \\\n\n/*\n\t\t\tWRITE_DST;\n\n\t\t\tdataDst = _mm_unpackhi_epi8(halfDone, halfDone);\n\n\t\t\tWRITE_DST;\n\n\t\t\thalfDone = _mm_unpackhi_epi8(dataSrc, dataSrc);\n\t\t\tdataDst = _mm_unpacklo_epi8(halfDone, halfDone);\n\n\t\t\tWRITE_DST;\n\n\t\t\tdataDst = _mm_unpackhi_epi8(halfDone, halfDone);\n\n\t\t\tWRITE_DST;\n\t\t}\n\t}\n\n\treturn 0;\n}\n */\n\n/**\n * Optimized 8-bit zoomer for resizing by a factor of 2. Doesn't flip.\n * Used internally by _zoomSurfaceY() below.\n * This is an SSE2 version written with Intel intrinsics.\n * source and dest. widths must be multiples of 16 bytes for 128-bit access\n * and it would help if they were aligned properly... :(\n *\n * @param src The surface to zoom (input).\n * @param dst The zoomed surface (output).\n * @return 0 for success or -1 for error.\n */\n/*\nstatic int zoomSurface2X_SSE2(SDL_Surface *src, SDL_Surface *dst)\n{\n\t__m128i dataSrc;\n\t__m128i dataDst;\n\tUint8 *pixelSrc = (Uint8*)src->pixels;\n\tUint8 *pixelDstRow = (Uint8*)dst->pixels;\n\tint sx, sy;\n\tstatic bool proclaimed = false;\n\n\tif (!proclaimed)\n\t{\n\t\tproclaimed = true;\n\t\tLog(LOG_INFO) << \"Using SSE2 2X zoom routine.\";\n\t}\n\n\tfor (sy = 0; sy < src->h; ++sy, pixelDstRow += dst->pitch*2)\n\t{\n\t\t__m128i *pixelDst =  (__m128i*)pixelDstRow;\n\t\t__m128i *pixelDst2 = (__m128i*)((Uint8*)pixelDstRow + dst->pitch);\n\n\t\tfor (sx = 0; sx < src->w; sx += 16, pixelSrc += 16)\n\t\t{\n\t\t\tdataSrc = *((__m128i*) pixelSrc);\n\n\t\t\tdataDst = _mm_unpacklo_epi8(dataSrc, dataSrc);\n\n#undef WRITE_DST\n#define WRITE_DST\t\t\t*(pixelDst++) = dataDst; \\\n\t\t\t*(pixelDst2++) = dataDst; \\\n\n\t\t\tWRITE_DST;\n\n\t\t\tdataDst = _mm_unpackhi_epi8(dataSrc, dataSrc);\n\n\t\t\tWRITE_DST;\n\t\t}\n\t}\n\n\treturn 0;\n}\n */\n\n/**\n * Checks the SSE2 feature bit returned by the CPUID instruction\n * @return Does the CPU support SSE2?\n */\nbool Zoom::haveSSE2()\n{\n#ifdef __GNUC__\n\tunsigned int CPUInfo[4] = {0, 0, 0, 0};\n\t#if (__e2k__) // e2k - MCST Elbrus 2000 architecture\n\t\t#ifdef __SSE2__\n\t\t\tCPUInfo[3] = 0x04000000;\n\t\t#endif\n\t#else // i386/x86_64\n\t\t__get_cpuid(1, CPUInfo, CPUInfo+1, CPUInfo+2, CPUInfo+3);\n\t#endif\n#elif _WIN32\n\tint CPUInfo[4];\n\t__cpuid(CPUInfo, 1);\n#else\n\tunsigned int CPUInfo[4] = {0, 0, 0, 0};\n#endif\n\n\treturn (CPUInfo[3] & 0x04000000) ? true : false;\n}\n\n#endif\n\n/**\n * Wrapper around various software and OpenGL screen buffer pushing functions which zoom.\n * Basically called just from Screen::flip()\n *\n * @param src The surface to zoom (input).\n * @param dst The zoomed surface (output).\n * @param topBlackBand Size of top black band in pixels (letterboxing).\n * @param bottomBlackBand Size of bottom black band in pixels (letterboxing).\n * @param leftBlackBand Size of left black band in pixels (letterboxing).\n * @param rightBlackBand Size of right black band in pixels (letterboxing).\n * @param glOut OpenGL output.\n */\nvoid Zoom::flipWithZoom(SDL_Surface *src, SDL_Surface *dst, int topBlackBand, int bottomBlackBand, int leftBlackBand, int rightBlackBand, OpenGL *glOut)\n{\n\tint dstWidth = dst->w - leftBlackBand - rightBlackBand;\n\tint dstHeight = dst->h - topBlackBand - bottomBlackBand;\n\tif (Screen::useOpenGL())\n\t{\n#ifndef __NO_OPENGL\n\t\tif (glOut->buffer_surface)\n\t\t{\n\t\t\tSDL_BlitSurface(src, 0, glOut->surface.get(), 0); // TODO; this is less than ideal...\n\n\t\t\tglOut->refresh(glOut->linear, glOut->iwidth, glOut->iheight, dst->w, dst->h, topBlackBand, bottomBlackBand, leftBlackBand, rightBlackBand);\n\t\t\tSDL_GL_SwapBuffers();\n\t\t}\n#endif\n\t}\n\telse if (topBlackBand <= 0 && bottomBlackBand <= 0 && leftBlackBand <= 0 && rightBlackBand <= 0)\n\t{\n\t\t_zoomSurfaceY(src, dst, 0, 0);\n\t}\n\telse if (dstWidth == src->w && dstHeight == src->h)\n\t{\n\t\tSDL_Rect dstrect = {(Sint16)leftBlackBand, (Sint16)topBlackBand, (Uint16)src->w, (Uint16)src->h};\n\t\tSDL_BlitSurface(src, NULL, dst, &dstrect);\n\t}\n\telse\n\t{\n\t\tSDL_Surface *tmp = SDL_CreateRGBSurface(dst->flags, dstWidth, dstHeight, dst->format->BitsPerPixel, 0, 0, 0, 0);\n\t\t_zoomSurfaceY(src, tmp, 0, 0);\n\t\tif (src->format->palette != NULL)\n\t\t{\n\t\t\tSDL_SetPalette(tmp, SDL_LOGPAL|SDL_PHYSPAL, src->format->palette->colors, 0, src->format->palette->ncolors);\n\t\t}\n\t\tSDL_Rect dstrect = {(Sint16)leftBlackBand, (Sint16)topBlackBand, (Uint16)tmp->w, (Uint16)tmp->h};\n\t\tSDL_BlitSurface(tmp, NULL, dst, &dstrect);\n\t\tSDL_FreeSurface(tmp);\n\t}\n}\n\n\n/**\n * Internal 8-bit Zoomer without smoothing.\n * Source code originally from SDL_gfx (LGPL) with permission by author.\n *\n * Zooms 8bit palette/Y 'src' surface to 'dst' surface.\n * Assumes src and dst surfaces are of 8-bit depth.\n * Assumes dst surface was allocated with the correct dimensions.\n *\n * @param src The surface to zoom (input).\n * @param dst The zoomed surface (output).\n * @param flipx Flag indicating if the image should be horizontally flipped.\n * @param flipy Flag indicating if the image should be vertically flipped.\n * @return 0 for success or -1 for error.\n */\nint Zoom::_zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst, int flipx, int flipy)\n{\n\tint x, y;\n\tstatic Uint32 *sax, *say;\n\tUint32 *csax, *csay;\n\tint csx, csy;\n\tUint8 *sp, *dp, *csp;\n\tint dgap;\n\tstatic bool proclaimed = false;\n\n\tif (Screen::use32bitScaler())\n\t{\n\t\tif (Options::useXBRZFilter)\n\t\t{\n\t\t\t// check the resolution to see which scale we need\n\t\t\tfor (size_t factor = 2; factor <= 6; factor++)\n\t\t\t{\n\t\t\t\tif (dst->w == src->w * (int)factor && dst->h == src->h * (int)factor)\n\t\t\t\t{\n\t\t\t\t\txbrz::scale(factor, (uint32_t*)src->pixels, (uint32_t*)dst->pixels, src->w, src->h, xbrz::RGB);\n\t\t\t\t\treturn 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (Options::useHQXFilter)\n\t\t{\n\t\t\tstatic bool initDone = false;\n\n\t\t\tif (!initDone)\n\t\t\t{\n\t\t\t\thqxInit();\n\t\t\t\tinitDone = true;\n\t\t\t}\n\n\t\t\t// HQX_API void HQX_CALLCONV hq2x_32_rb( uint32_t * src, uint32_t src_rowBytes, uint32_t * dest, uint32_t dest_rowBytes, int width, int height );\n\n\t\t\tif (dst->w == src->w * 2 && dst->h == src->h * 2)\n\t\t\t{\n\t\t\t\thq2x_32_rb((uint32_t*)src->pixels, src->pitch, (uint32_t*)dst->pixels, dst->pitch, src->w, src->h);\n\t\t\t\treturn 0;\n\t\t\t}\n\n\t\t\tif (dst->w == src->w * 3 && dst->h == src->h * 3)\n\t\t\t{\n\t\t\t\thq3x_32_rb((uint32_t*)src->pixels, src->pitch, (uint32_t*)dst->pixels, dst->pitch, src->w, src->h);\n\t\t\t\treturn 0;\n\t\t\t}\n\n\t\t\tif (dst->w == src->w * 4 && dst->h == src->h * 4)\n\t\t\t{\n\t\t\t\thq4x_32_rb((uint32_t*)src->pixels, src->pitch, (uint32_t*)dst->pixels, dst->pitch, src->w, src->h);\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (Options::useScaleFilter)\n\t{\n\t\t// check the resolution to see which of scale2x, scale3x, etc. we need\n\t\tfor (size_t factor = 2; factor <= 4; factor++)\n\t\t{\n\t\t\tif (dst->w == src->w * (int)factor && dst->h == src->h * (int)factor && !scale_precondition(factor, src->format->BytesPerPixel, src->w, src->h))\n\t\t\t{\n\t\t\t\tscale(factor, dst->pixels, dst->pitch, src->pixels, src->pitch, src->format->BytesPerPixel, src->w, src->h);\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t}\n\t}\n\n\t// if we're scaling by a factor of 2 or 4, try to use a more efficient function\n\t/*\n\tif (src->format->BytesPerPixel == 1 && dst->format->BytesPerPixel == 1)\n\t{\n\n#ifdef __SSE2__\n\t\tstatic bool _haveSSE2 = haveSSE2();\n\n\t\tif (_haveSSE2 &&\n\t\t\t!((ptrdiff_t)src->pixels % 16) &&\n\t\t\t!((ptrdiff_t)dst->pixels % 16)) // alignment check\n\t\t{\n\t\t\tif (dst->w == src->w * 2 && dst->h == src->h * 2) return  zoomSurface2X_SSE2(src, dst);\n\t\t\telse if (dst->w == src->w * 4 && dst->h == src->h * 4) return  zoomSurface4X_SSE2(src, dst);\n\t\t} else\n\t\t{\n\t\t\tstatic bool complained = false;\n\n\t\t\tif (!complained)\n\t\t\t{\n\t\t\t\tcomplained = true;\n\t\t\t\tLog(LOG_ERROR) << \"Misaligned surface buffers.\";\n\t\t\t}\n\t\t}\n#endif\n\n// __WORDSIZE is defined on Linux, SIZE_MAX on Windows\n#if defined(__WORDSIZE) && (__WORDSIZE == 64) || defined(SIZE_MAX) && (SIZE_MAX > 0xFFFFFFFF)\n\t\tif (dst->w == src->w * 2 && dst->h == src->h * 2) return  zoomSurface2X_64bit(src, dst);\n\t\telse if (dst->w == src->w * 4 && dst->h == src->h * 4) return  zoomSurface4X_64bit(src, dst);\n#else\n\t\tif (sizeof(void *) == 8)\n\t\t{\n\t\t\tif (dst->w == src->w * 2 && dst->h == src->h * 2) return  zoomSurface2X_64bit(src, dst);\n\t\t\telse if (dst->w == src->w * 4 && dst->h == src->h * 4) return  zoomSurface4X_64bit(src, dst);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (dst->w == src->w * 2 && dst->h == src->h * 2) return  zoomSurface2X_32bit(src, dst);\n\t\t\telse if (dst->w == src->w * 4 && dst->h == src->h * 4) return  zoomSurface4X_32bit(src, dst);\n\t\t}\n#endif\n\n\t\t// maybe X is scaled by 2 or 4 but not Y?\n\t\tif (dst->w == src->w * 4) return zoomSurface4X_XAxis_32bit(src, dst);\n\t\telse if (dst->w == src->w * 2) return zoomSurface2X_XAxis_32bit(src, dst);\n\t}\n\t*/\n\tif (!proclaimed)\n\t{\n\t\tLog(LOG_INFO) << \"Using software scaling routine. For best results, try an OpenGL filter.\";\n\t\tproclaimed = true;\n\t}\n\n\t/*\n\t* Allocate memory for row increments\n\t*/\n\tif ((sax = (Uint32 *) realloc(sax, (dst->w + 1) * sizeof(Uint32))) == NULL) {\n\t\tsax = 0;\n\t\treturn (-1);\n\t}\n\tif ((say = (Uint32 *) realloc(say, (dst->h + 1) * sizeof(Uint32))) == NULL) {\n\t\tsay = 0;\n\t\t//free(sax);\n\t\treturn (-1);\n\t}\n\n\t/*\n\t* Pointer setup\n\t*/\n\tsp = csp = (Uint8 *) src->pixels;\n\tdp = (Uint8 *) dst->pixels;\n\tdgap = dst->pitch - dst->w;\n\n\tif (flipx) csp += (src->w-1);\n\tif (flipy) csp  = ( (Uint8*)csp + src->pitch*(src->h-1) );\n\n\t/*\n\t* Precalculate row increments\n\t*/\n\tcsx = 0;\n\tcsax = sax;\n\tfor (x = 0; x < dst->w; x++) {\n\t\tcsx += src->w;\n\t\t*csax = 0;\n\t\twhile (csx >= dst->w) {\n\t\t\tcsx -= dst->w;\n\t\t\t(*csax)++;\n\t\t}\n\t\t(*csax) *= (flipx ? -1 : 1);\n\t\tcsax++;\n\t}\n\tcsy = 0;\n\tcsay = say;\n\tfor (y = 0; y < dst->h; y++) {\n\t\tcsy += src->h;\n\t\t*csay = 0;\n\t\twhile (csy >= dst->h) {\n\t\t\tcsy -= dst->h;\n\t\t\t(*csay)++;\n\t\t}\n\t\t(*csay) *= src->pitch * (flipy ? -1 : 1);\n\t\tcsay++;\n\t}\n\t/*\n\t* Draw\n\t*/\n\tcsay = say;\n\tfor (y = 0; y < dst->h; y++) {\n\t\tcsax = sax;\n\t\tsp = csp;\n\t\tfor (x = 0; x < dst->w; x++) {\n\t\t\t/*\n\t\t\t* Draw\n\t\t\t*/\n\t\t\t*dp = *sp;\n\t\t\t/*\n\t\t\t* Advance source pointers\n\t\t\t*/\n\t\t\tsp += (*csax);\n\t\t\tcsax++;\n\t\t\t/*\n\t\t\t* Advance destination pointer\n\t\t\t*/\n\t\t\tdp++;\n\t\t}\n\t\t/*\n\t\t* Advance source pointer (for row)\n\t\t*/\n\t\tcsp += (*csay);\n\t\tcsay++;\n\n\t\t/*\n\t\t* Advance destination pointers\n\t\t*/\n\t\tdp += dgap;\n\t}\n\n\t/*\n\t* Never remove temp arrays\n\t*/\n\t//free(sax);\n\t//free(say);\n\n\treturn 0;\n}\n\n\n}\n\n"
  },
  {
    "path": "src/Engine/Zoom.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <SDL.h>\n#include \"OpenGL.h\"\n\nnamespace OpenXcom\n{\n\n\nclass Zoom\n{\n\n\tpublic:\n\t/// Flip screen given src and dst; might use software or OpenGL.\n\tstatic void flipWithZoom(SDL_Surface *src, SDL_Surface *dst, int topBlackBand, int bottomBlackBand, int leftBlackBand, int rightBlackBand, OpenGL *glOut);\n\t/// Copy src to dst, resizing as needed. Please don't use flipx or flipy as the optimized functions ignore these parameters.\n\tstatic int _zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst, int flipx, int flipy);\n\t/// Check for SSE2 instructions using CPUID.\n\tstatic bool haveSSE2();\n\nprivate:\n\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/AlienBaseState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"AlienBaseState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"GeoscapeState.h\"\n#include \"Globe.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Region.h\"\n#include \"../Savegame/Country.h\"\n#include \"../Mod/RuleRegion.h\"\n#include \"../Mod/RuleCountry.h\"\n#include \"../Savegame/AlienBase.h\"\n#include \"../Engine/Options.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Aliens Base discovered window.\n * @param game Pointer to the core game.\n * @param base Pointer to the alien base to get info from.\n * @param state Pointer to the Geoscape.\n */\nAlienBaseState::AlienBaseState(AlienBase *base, GeoscapeState *state) : _state(state), _base(base)\n{\n\t// Create objects\n\t_window = new Window(this, 320, 200, 0, 0);\n\t_btnOk = new TextButton(50, 12, 135, 180);\n\t_txtTitle = new Text(308, 60, 6, 60);\n\n\tsetInterface(\"alienBase\");\n\n\tadd(_window, \"window\", \"alienBase\");\n\tadd(_btnOk, \"text\", \"alienBase\");\n\tadd(_txtTitle, \"button\", \"alienBase\");\n\n\tcenterAllSurfaces();\n\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"alienBase\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&AlienBaseState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&AlienBaseState::btnOkClick, Options::keyOk);\n\t_btnOk->onKeyboardPress((ActionHandler)&AlienBaseState::btnOkClick, Options::keyCancel);\n\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setBig();\n\t_txtTitle->setWordWrap(true);\n\n\t// Check location of base\n\tstd::string regionName, countryName;\n\tfor (const auto* country : *_game->getSavedGame()->getCountries())\n\t{\n\t\tif (country->getRules()->insideCountry(_base->getLongitude(), _base->getLatitude()))\n\t\t{\n\t\t\tcountryName = tr(country->getRules()->getType());\n\t\t\tbreak;\n\t\t}\n\t}\n\tfor (const auto* region : *_game->getSavedGame()->getRegions())\n\t{\n\t\tif (region->getRules()->insideRegion(_base->getLongitude(), _base->getLatitude()))\n\t\t{\n\t\t\tregionName = tr(region->getRules()->getType());\n\t\t\tbreak;\n\t\t}\n\t}\n\tstd::string location;\n\tif (!countryName.empty())\n\t{\n\t\tlocation = tr(\"STR_COUNTRIES_COMMA\").arg(countryName).arg(regionName);\n\t}\n\telse if (!regionName.empty())\n\t{\n\t\tlocation = regionName;\n\t}\n\telse\n\t{\n\t\tlocation = tr(\"STR_UNKNOWN\");\n\t}\n\tif (!_base->getDeployment()->getAlienBaseDiscoveredMessage().empty())\n\t{\n\t\tstd::string markerName = tr(_base->getDeployment()->getMarkerName());\n\t\t_txtTitle->setText(tr(_base->getDeployment()->getAlienBaseDiscoveredMessage()).arg(location).arg(markerName));\n\t}\n\telse\n\t{\n\t\t_txtTitle->setText(tr(\"STR_XCOM_AGENTS_HAVE_LOCATED_AN_ALIEN_BASE_IN_REGION\").arg(location));\n\t}\n}\n\n/**\n *\n */\nAlienBaseState::~AlienBaseState()\n{\n\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid AlienBaseState::btnOkClick(Action *)\n{\n\t_state->timerReset();\n\t_state->getGlobe()->center(_base->getLongitude(), _base->getLatitude());\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/AlienBaseState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass Region;\nclass TextButton;\nclass Window;\nclass Text;\nclass GeoscapeState;\nclass AlienBase;\n\n/**\n * Displays info on an alien base.\n */\nclass AlienBaseState : public State\n{\nprivate:\n\tGeoscapeState *_state;\n\tAlienBase *_base;\n\tTextButton *_btnOk;\n\tWindow *_window;\n\tText *_txtTitle;\npublic:\n\t/// Creates the Alien Base Detected state.\n\tAlienBaseState(AlienBase *base, GeoscapeState *state);\n\t/// Cleans up the Alien Base Detected state.\n\t~AlienBaseState();\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/AllocatePsiTrainingState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <sstream>\n#include <climits>\n#include \"PsiTrainingState.h\"\n#include \"AllocatePsiTrainingState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/ToggleTextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Savegame/Soldier.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/ComboBox.h\"\n#include \"../Mod/RuleSoldier.h\"\n#include \"../Basescape/SoldierInfoState.h\"\n#include \"../Basescape/SoldierSortUtil.h\"\n#include <algorithm>\n#include \"../Engine/Unicode.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Psi Training screen.\n * @param game Pointer to the core game.\n * @param base Pointer to the base to handle.\n */\nAllocatePsiTrainingState::AllocatePsiTrainingState(Base *base) : _sel(0), _base(base), _origSoldierOrder(*_base->getSoldiers()), _doNotReset(false)\n{\n\t// Create objects\n\t_window = new Window(this, 320, 200, 0, 0);\n\t_txtTitle = new Text(300, 17, 10, 8);\n\t_txtRemaining = new Text(300, 10, 10, 24);\n\t_txtName = new Text(64, 10, 10, 40);\n\t_txtPsiStrength = new Text(80, 20, 124, 32);\n\t_txtPsiSkill = new Text(80, 20, 188, 32);\n\t_txtTraining = new Text(48, 20, 270, 32);\n\t_btnOk = new TextButton(148, 16, 164, 176);\n\t_lstSoldiers = new TextList(290, 112, 8, 52);\n\t_cbxSortBy = new ComboBox(this, 148, 16, 8, 176, true);\n\t_btnPlus = new ToggleTextButton(18, 16, 294, 8);\n\n\t// Set palette\n\tsetInterface(\"allocatePsi\");\n\n\tadd(_window, \"window\", \"allocatePsi\");\n\tadd(_btnOk, \"button\", \"allocatePsi\");\n\tadd(_txtName, \"text\", \"allocatePsi\");\n\tadd(_txtTitle, \"text\", \"allocatePsi\");\n\tadd(_txtRemaining, \"text\", \"allocatePsi\");\n\tadd(_txtPsiStrength, \"text\", \"allocatePsi\");\n\tadd(_txtPsiSkill, \"text\", \"allocatePsi\");\n\tadd(_txtTraining, \"text\", \"allocatePsi\");\n\tadd(_lstSoldiers, \"list\", \"allocatePsi\");\n\tadd(_cbxSortBy, \"button\", \"allocatePsi\");\n\tadd(_btnPlus, \"button\", \"allocatePsi\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"allocatePsi\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&AllocatePsiTrainingState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&AllocatePsiTrainingState::btnOkClick, Options::keyCancel);\n\t_btnOk->onKeyboardPress((ActionHandler)&AllocatePsiTrainingState::btnDeassignAllSoldiersClick, Options::keyRemoveSoldiersFromTraining);\n\t_btnOk->onKeyboardPress((ActionHandler)&AllocatePsiTrainingState::btnAssignAllSoldiersClick, Options::keyAddSoldiersToTraining);\n\n\t_btnPlus->setText(\"+\");\n\t_btnPlus->setPressed(false);\n\tif (_game->getMod()->getSoldierBonusList().empty())\n\t{\n\t\t// no soldier bonuses in the mod = button not needed\n\t\t_btnPlus->setVisible(false);\n\t}\n\telse\n\t{\n\t\t_btnPlus->onMouseClick((ActionHandler)&AllocatePsiTrainingState::btnPlusClick, 0);\n\t}\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_PSIONIC_TRAINING\"));\n\n\t_labSpace = base->getAvailablePsiLabs() - base->getUsedPsiLabs();\n\t_txtRemaining->setText(tr(\"STR_REMAINING_PSI_LAB_CAPACITY\").arg(_labSpace));\n\n\t_txtName->setText(tr(\"STR_NAME\"));\n\n\t_txtPsiStrength->setText(tr(\"STR_PSIONIC__STRENGTH\"));\n\n\t_txtPsiSkill->setText(tr(\"STR_PSIONIC_SKILL_IMPROVEMENT\"));\n\n\t_txtTraining->setText(tr(\"STR_IN_TRAINING\"));\n\n\t// populate sort options\n\tstd::vector<std::string> sortOptions;\n\tsortOptions.push_back(tr(\"STR_ORIGINAL_ORDER\"));\n\t_sortFunctors.push_back(NULL);\n\t_sortFunctorsPlus.push_back(NULL);\n\n#define PUSH_IN(strId, functor) \\\n\tsortOptions.push_back(tr(strId)); \\\n\t_sortFunctors.push_back(new SortFunctor(_game, functor)); \\\n\t_sortFunctorsPlus.push_back(new SortFunctor(_game, functor));\n\n\tPUSH_IN(\"STR_ID\", idStat);\n\tPUSH_IN(\"STR_NAME_UC\", nameStat);\n\tPUSH_IN(\"STR_SOLDIER_TYPE\", typeStat);\n\tPUSH_IN(\"STR_RANK\", rankStat);\n\tPUSH_IN(\"STR_IDLE_DAYS\", idleDaysStat);\n\tPUSH_IN(\"STR_MISSIONS2\", missionsStat);\n\tPUSH_IN(\"STR_KILLS2\", killsStat);\n\tPUSH_IN(\"STR_WOUND_RECOVERY2\", woundRecoveryStat);\n\tif (_game->getMod()->isManaFeatureEnabled() && !_game->getMod()->getReplenishManaAfterMission())\n\t{\n\t\tPUSH_IN(\"STR_MANA_MISSING\", manaMissingStat);\n\t}\n\n#undef PUSH_IN\n\n#define PUSH_IN(strId, functor, functorPlus) \\\n\tsortOptions.push_back(tr(strId)); \\\n\t_sortFunctors.push_back(new SortFunctor(_game, functor)); \\\n\t_sortFunctorsPlus.push_back(new SortFunctor(_game, functorPlus));\n\n\tPUSH_IN(\"STR_TIME_UNITS\", tuStatBase, tuStatPlus);\n\tPUSH_IN(\"STR_STAMINA\", staminaStatBase, staminaStatPlus);\n\tPUSH_IN(\"STR_HEALTH\", healthStatBase, healthStatPlus);\n\tPUSH_IN(\"STR_BRAVERY\", braveryStatBase, braveryStatPlus);\n\tPUSH_IN(\"STR_REACTIONS\", reactionsStatBase, reactionsStatPlus);\n\tPUSH_IN(\"STR_FIRING_ACCURACY\", firingStatBase, firingStatPlus);\n\tPUSH_IN(\"STR_THROWING_ACCURACY\", throwingStatBase, throwingStatPlus);\n\tPUSH_IN(\"STR_MELEE_ACCURACY\", meleeStatBase, meleeStatPlus);\n\tPUSH_IN(\"STR_STRENGTH\", strengthStatBase, strengthStatPlus);\n\tif (_game->getMod()->isManaFeatureEnabled())\n\t{\n\t\t// \"unlock\" is checked later\n\t\tPUSH_IN(\"STR_MANA_POOL\", manaStatBase, manaStatPlus);\n\t}\n\tPUSH_IN(\"STR_PSIONIC_STRENGTH\", psiStrengthStatBase, psiStrengthStatPlus);\n\tPUSH_IN(\"STR_PSIONIC_SKILL\", psiSkillStatBase, psiSkillStatPlus);\n\n#undef PUSH_IN\n\n\t_cbxSortBy->setOptions(sortOptions);\n\t_cbxSortBy->setSelected(0);\n\t_cbxSortBy->onChange((ActionHandler)&AllocatePsiTrainingState::cbxSortByChange);\n\t_cbxSortBy->setText(tr(\"STR_SORT_BY\"));\n\n\t_lstSoldiers->setArrowColumn(238, ARROW_VERTICAL);\n\t_lstSoldiers->setColumns(4, 114, 80, 66, 40);\n\t_lstSoldiers->setSelectable(true);\n\t_lstSoldiers->setBackground(_window);\n\t_lstSoldiers->setMargin(2);\n\t_lstSoldiers->onLeftArrowClick((ActionHandler)&AllocatePsiTrainingState::lstItemsLeftArrowClick);\n\t_lstSoldiers->onRightArrowClick((ActionHandler)&AllocatePsiTrainingState::lstItemsRightArrowClick);\n\t_lstSoldiers->onMouseClick((ActionHandler)&AllocatePsiTrainingState::lstSoldiersClick);\n\t_lstSoldiers->onMouseClick((ActionHandler)&AllocatePsiTrainingState::lstSoldiersClick, SDL_BUTTON_RIGHT);\n\t_lstSoldiers->onMousePress((ActionHandler)&AllocatePsiTrainingState::lstSoldiersMousePress);\n}\n/**\n * cleans up dynamic state\n */\nAllocatePsiTrainingState::~AllocatePsiTrainingState()\n{\n\tfor (auto* sortFunctor : _sortFunctors)\n\t{\n\t\tdelete sortFunctor;\n\t}\n}\n\n/**\n * Sorts the soldiers list by the selected criterion\n * @param action Pointer to an action.\n */\nvoid AllocatePsiTrainingState::cbxSortByChange(Action *action)\n{\n\tsize_t selIdx = _cbxSortBy->getSelected();\n\tif (selIdx == (size_t)-1)\n\t{\n\t\treturn;\n\t}\n\n\tSortFunctor *compFunc = _btnPlus->getPressed() ? _sortFunctorsPlus[selIdx] : _sortFunctors[selIdx];\n\tif (compFunc)\n\t{\n\t\tif (selIdx == 2)\n\t\t{\n\t\t\tstd::stable_sort(_base->getSoldiers()->begin(), _base->getSoldiers()->end(),\n\t\t\t\t[](const Soldier* a, const Soldier* b)\n\t\t\t\t{\n\t\t\t\t\treturn Unicode::naturalCompare(a->getName(), b->getName());\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tstd::stable_sort(_base->getSoldiers()->begin(), _base->getSoldiers()->end(), *compFunc);\n\t\t}\n\t\tif (_game->isShiftPressed())\n\t\t{\n\t\t\tstd::reverse(_base->getSoldiers()->begin(), _base->getSoldiers()->end());\n\t\t}\n\t}\n\telse\n\t{\n\t\t// restore original ordering, ignoring (of course) those\n\t\t// soldiers that have been sacked since this state started\n\t\tfor (const auto* origSoldier : _origSoldierOrder)\n\t\t{\n\t\t\tauto soldierIt = std::find(_base->getSoldiers()->begin(), _base->getSoldiers()->end(), origSoldier);\n\t\t\tif (soldierIt != _base->getSoldiers()->end())\n\t\t\t{\n\t\t\t\tSoldier *s = *soldierIt;\n\t\t\t\t_base->getSoldiers()->erase(soldierIt);\n\t\t\t\t_base->getSoldiers()->insert(_base->getSoldiers()->end(), s);\n\t\t\t}\n\t\t}\n\t}\n\n\tsize_t originalScrollPos = _lstSoldiers->getScroll();\n\tinitList(originalScrollPos);\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid AllocatePsiTrainingState::btnOkClick(Action *)\n{\n\t// Note: statString updates are needed only because of the potential \"psiTraining\" attribute change\n\tbool psiStrengthEval = (Options::psiStrengthEval && _game->getSavedGame()->isResearched(_game->getMod()->getPsiRequirements()));\n\tfor (auto* soldier : *_base->getSoldiers())\n\t{\n\t\tsoldier->calcStatString(_game->getMod()->getStatStrings(), psiStrengthEval);\n\t}\n\t_game->popState();\n}\n\n/**\n * Updates the soldier stats. Sorts the list if applicable.\n * @param action Pointer to an action.\n */\nvoid AllocatePsiTrainingState::btnPlusClick(Action *action)\n{\n\tsize_t selIdx = _cbxSortBy->getSelected();\n\tif (selIdx == (size_t)-1)\n\t{\n\t\tsize_t originalScrollPos = _lstSoldiers->getScroll();\n\t\tinitList(originalScrollPos);\n\t}\n\telse\n\t{\n\t\tcbxSortByChange(action);\n\t}\n}\n\n/**\n * Updates the soldiers list\n * after going to other screens.\n */\nvoid AllocatePsiTrainingState::init()\n{\n\tState::init();\n\n\t// coming back from SoldierInfoState\n\tif (_doNotReset)\n\t{\n\t\t_doNotReset = false;\n\t\treturn;\n\t}\n\n\t_base->prepareSoldierStatsWithBonuses(); // refresh stats for sorting\n\tinitList(0);\n}\n\n/**\n * Shows the soldiers in a list at specified offset/scroll.\n */\nvoid AllocatePsiTrainingState::initList(size_t scrl)\n{\n\tint row = 0;\n\t_lstSoldiers->clearList();\n\tfor (auto* soldier : *_base->getSoldiers())\n\t{\n\t\tconst UnitStats* stats = _btnPlus->getPressed() ? soldier->getStatsWithSoldierBonusesOnly() : soldier->getCurrentStats();\n\n\t\tstd::ostringstream ssStr;\n\t\tstd::ostringstream ssSkl;\n\t\t_soldiers.push_back(soldier);\n\t\tif (soldier->getCurrentStats()->psiSkill > 0 || (Options::psiStrengthEval && _game->getSavedGame()->isResearched(_game->getMod()->getPsiRequirements())))\n\t\t{\n\t\t\tssStr << \"   \" << stats->psiStrength;\n\t\t\tif (Options::allowPsiStrengthImprovement) ssStr << \"/+\" << soldier->getPsiStrImprovement();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tssStr << tr(\"STR_UNKNOWN\");\n\t\t}\n\t\tif (soldier->getCurrentStats()->psiSkill > 0)\n\t\t{\n\t\t\tssSkl << stats->psiSkill << \"/+\" << soldier->getImprovement();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tssSkl << \"0/+0\";\n\t\t}\n\t\tif (soldier->getRules()->getTrainingStatCaps().psiSkill <= 0)\n\t\t{\n\t\t\t_lstSoldiers->addRow(4, soldier->getName(true).c_str(), ssStr.str().c_str(), ssSkl.str().c_str(), tr(\"STR_NO_WOUNDED\").c_str());\n\t\t\t_lstSoldiers->setRowColor(row, _lstSoldiers->getColor());\n\t\t\tif (soldier->isInPsiTraining())\n\t\t\t{\n\t\t\t\t_labSpace++;\n\t\t\t\tsoldier->setPsiTraining(false);\n\t\t\t}\n\t\t}\n\t\telse if (soldier->isFullyPsiTrained())\n\t\t{\n\t\t\t_lstSoldiers->addRow(4, soldier->getName(true).c_str(), ssStr.str().c_str(), ssSkl.str().c_str(), tr(\"STR_NO_DONE\").c_str());\n\t\t\t_lstSoldiers->setRowColor(row, _lstSoldiers->getColor());\n\t\t\tif (soldier->isInPsiTraining())\n\t\t\t{\n\t\t\t\t_labSpace++;\n\t\t\t\tsoldier->setPsiTraining(false);\n\t\t\t}\n\t\t}\n\t\telse if (soldier->isInPsiTraining())\n\t\t{\n\t\t\t_lstSoldiers->addRow(4, soldier->getName(true).c_str(), ssStr.str().c_str(), ssSkl.str().c_str(), tr(\"STR_YES\").c_str());\n\t\t\t_lstSoldiers->setRowColor(row, _lstSoldiers->getSecondaryColor());\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_lstSoldiers->addRow(4, soldier->getName(true).c_str(), ssStr.str().c_str(), ssSkl.str().c_str(), tr(\"STR_NO\").c_str());\n\t\t\t_lstSoldiers->setRowColor(row, _lstSoldiers->getColor());\n\t\t}\n\t\trow++;\n\t}\n\t_txtRemaining->setText(tr(\"STR_REMAINING_PSI_LAB_CAPACITY\").arg(_labSpace));\n\tif (scrl)\n\t\t_lstSoldiers->scrollTo(scrl);\n\t_lstSoldiers->draw();\n}\n\n\n/**\n * Reorders a soldier up.\n * @param action Pointer to an action.\n */\nvoid AllocatePsiTrainingState::lstItemsLeftArrowClick(Action *action)\n{\n\tunsigned int row = _lstSoldiers->getSelectedRow();\n\tif (row > 0)\n\t{\n\t\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT)\n\t\t{\n\t\t\tmoveSoldierUp(action, row);\n\t\t}\n\t\telse if (action->getDetails()->button.button == SDL_BUTTON_RIGHT)\n\t\t{\n\t\t\tmoveSoldierUp(action, row, true);\n\t\t}\n\t}\n\t_cbxSortBy->setText(tr(\"STR_SORT_BY\"));\n\t_cbxSortBy->setSelected(-1);\n}\n\n/**\n * Moves a soldier up on the list.\n * @param action Pointer to an action.\n * @param row Selected soldier row.\n * @param max Move the soldier to the top?\n */\nvoid AllocatePsiTrainingState::moveSoldierUp(Action *action, unsigned int row, bool max)\n{\n\tSoldier *s = _base->getSoldiers()->at(row);\n\tif (max)\n\t{\n\t\t_base->getSoldiers()->erase(_base->getSoldiers()->begin() + row);\n\t\t_base->getSoldiers()->insert(_base->getSoldiers()->begin(), s);\n\t}\n\telse\n\t{\n\t\t_base->getSoldiers()->at(row) = _base->getSoldiers()->at(row - 1);\n\t\t_base->getSoldiers()->at(row - 1) = s;\n\t\tif (row != _lstSoldiers->getScroll())\n\t\t{\n\t\t\tSDL_WarpMouse(action->getLeftBlackBand() + action->getXMouse(), action->getTopBlackBand() + action->getYMouse() - static_cast<Uint16>(8 * action->getYScale()));\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_lstSoldiers->scrollUp(false);\n\t\t}\n\t}\n\tinitList(_lstSoldiers->getScroll());\n}\n\n/**\n * Reorders a soldier down.\n * @param action Pointer to an action.\n */\nvoid AllocatePsiTrainingState::lstItemsRightArrowClick(Action *action)\n{\n\tunsigned int row = _lstSoldiers->getSelectedRow();\n\tsize_t numSoldiers = _base->getSoldiers()->size();\n\tif (0 < numSoldiers && INT_MAX >= numSoldiers && row < numSoldiers - 1)\n\t{\n\t\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT)\n\t\t{\n\t\t\tmoveSoldierDown(action, row);\n\t\t}\n\t\telse if (action->getDetails()->button.button == SDL_BUTTON_RIGHT)\n\t\t{\n\t\t\tmoveSoldierDown(action, row, true);\n\t\t}\n\t}\n\t_cbxSortBy->setText(tr(\"STR_SORT_BY\"));\n\t_cbxSortBy->setSelected(-1);\n}\n\n/**\n * Moves a soldier down on the list.\n * @param action Pointer to an action.\n * @param row Selected soldier row.\n * @param max Move the soldier to the bottom?\n */\nvoid AllocatePsiTrainingState::moveSoldierDown(Action *action, unsigned int row, bool max)\n{\n\tSoldier *s = _base->getSoldiers()->at(row);\n\tif (max)\n\t{\n\t\t_base->getSoldiers()->erase(_base->getSoldiers()->begin() + row);\n\t\t_base->getSoldiers()->insert(_base->getSoldiers()->end(), s);\n\t}\n\telse\n\t{\n\t\t_base->getSoldiers()->at(row) = _base->getSoldiers()->at(row + 1);\n\t\t_base->getSoldiers()->at(row + 1) = s;\n\t\tif (row != _lstSoldiers->getVisibleRows() - 1 + _lstSoldiers->getScroll())\n\t\t{\n\t\t\tSDL_WarpMouse(action->getLeftBlackBand() + action->getXMouse(), action->getTopBlackBand() + action->getYMouse() + static_cast<Uint16>(8 * action->getYScale()));\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_lstSoldiers->scrollDown(false);\n\t\t}\n\t}\n\tinitList(_lstSoldiers->getScroll());\n}\n\n/**\n * Assigns / removes a soldier from Psi Training.\n * @param action Pointer to an action.\n */\nvoid AllocatePsiTrainingState::lstSoldiersClick(Action *action)\n{\n\tdouble mx = action->getAbsoluteXMouse();\n\tif (mx >= _lstSoldiers->getArrowsLeftEdge() && mx < _lstSoldiers->getArrowsRightEdge())\n\t{\n\t\treturn;\n\t}\n\n\t_sel = _lstSoldiers->getSelectedRow();\n\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT)\n\t{\n\t\tauto* s = _base->getSoldiers()->at(_sel);\n\t\tif (s->getRules()->getTrainingStatCaps().psiSkill <= 0)\n\t\t{\n\t\t\t// noop\n\t\t}\n\t\telse if (s->isFullyPsiTrained())\n\t\t{\n\t\t\t// can't put fully psi-trained soldiers back into psi training\n\t\t}\n\t\telse if (!s->isInPsiTraining())\n\t\t{\n\t\t\tif (_base->getUsedPsiLabs() < _base->getAvailablePsiLabs())\n\t\t\t{\n\t\t\t\t_lstSoldiers->setCellText(_sel, 3, tr(\"STR_YES\"));\n\t\t\t\t_lstSoldiers->setRowColor(_sel, _lstSoldiers->getSecondaryColor());\n\t\t\t\t_labSpace--;\n\t\t\t\t_txtRemaining->setText(tr(\"STR_REMAINING_PSI_LAB_CAPACITY\").arg(_labSpace));\n\t\t\t\ts->setPsiTraining(true);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_lstSoldiers->setCellText(_sel, 3, tr(\"STR_NO\"));\n\t\t\t_lstSoldiers->setRowColor(_sel, _lstSoldiers->getColor());\n\t\t\t_labSpace++;\n\t\t\t_txtRemaining->setText(tr(\"STR_REMAINING_PSI_LAB_CAPACITY\").arg(_labSpace));\n\t\t\ts->setPsiTraining(false);\n\t\t}\n\t}\n\telse if (action->getDetails()->button.button == SDL_BUTTON_RIGHT)\n\t{\n\t\t_doNotReset = true;\n\t\t_game->pushState(new SoldierInfoState(_base, _sel, true, true));\n\t}\n}\n\n/**\n * Handles the mouse-wheels on the arrow-buttons.\n * @param action Pointer to an action.\n */\nvoid AllocatePsiTrainingState::lstSoldiersMousePress(Action *action)\n{\n\tif (Options::changeValueByMouseWheel == 0)\n\t\treturn;\n\tunsigned int row = _lstSoldiers->getSelectedRow();\n\tsize_t numSoldiers = _base->getSoldiers()->size();\n\tif (action->getDetails()->button.button == SDL_BUTTON_WHEELUP &&\n\t\trow > 0)\n\t{\n\t\tif (action->getAbsoluteXMouse() >= _lstSoldiers->getArrowsLeftEdge() &&\n\t\t\taction->getAbsoluteXMouse() <= _lstSoldiers->getArrowsRightEdge())\n\t\t{\n\t\t\tmoveSoldierUp(action, row);\n\t\t}\n\t}\n\telse if (action->getDetails()->button.button == SDL_BUTTON_WHEELDOWN &&\n\t\t0 < numSoldiers && INT_MAX >= numSoldiers && row < numSoldiers - 1)\n\t{\n\t\tif (action->getAbsoluteXMouse() >= _lstSoldiers->getArrowsLeftEdge() &&\n\t\t\taction->getAbsoluteXMouse() <= _lstSoldiers->getArrowsRightEdge())\n\t\t{\n\t\t\tmoveSoldierDown(action, row);\n\t\t}\n\t}\n}\n\n/**\n * Removes all soldiers from Psi Training.\n * @param action Pointer to an action.\n */\nvoid AllocatePsiTrainingState::btnDeassignAllSoldiersClick(Action* action)\n{\n\tint row = 0;\n\tfor (auto* s : *_base->getSoldiers())\n\t{\n\t\ts->setPsiTraining(false);\n\t\tif (s->getRules()->getTrainingStatCaps().psiSkill <= 0)\n\t\t{\n\t\t\t_lstSoldiers->setCellText(row, 3, tr(\"STR_NO_WOUNDED\"));\n\t\t}\n\t\telse if (s->isFullyPsiTrained())\n\t\t{\n\t\t\t_lstSoldiers->setCellText(row, 3, tr(\"STR_NO_DONE\"));\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_lstSoldiers->setCellText(row, 3, tr(\"STR_NO\"));\n\t\t}\n\t\t_lstSoldiers->setRowColor(row, _lstSoldiers->getColor());\n\t\trow++;\n\t}\n\t_labSpace = _base->getAvailablePsiLabs() - _base->getUsedPsiLabs();\n\t_txtRemaining->setText(tr(\"STR_REMAINING_PSI_LAB_CAPACITY\").arg(_labSpace));\n}\n\n/**\n * Adds all soldiers to Psi Training.\n * @param action Pointer to an action.\n */\nvoid AllocatePsiTrainingState::btnAssignAllSoldiersClick(Action* action)\n{\n\tint row = 0;\n\tfor (auto* s : *_base->getSoldiers())\n\t{\n\t\tif (s->getRules()->getTrainingStatCaps().psiSkill <= 0)\n\t\t{\n\t\t\t// noop\n\t\t}\n\t\telse if (s->isFullyPsiTrained())\n\t\t{\n\t\t\t// can't put fully psi-trained soldiers back into psi training\n\t\t}\n\t\telse if (_labSpace > 0 && !s->isInPsiTraining())\n\t\t{\n\t\t\t_lstSoldiers->setCellText(row, 3, tr(\"STR_YES\"));\n\t\t\t_lstSoldiers->setRowColor(row, _lstSoldiers->getSecondaryColor());\n\t\t\t_labSpace--;\n\t\t\ts->setPsiTraining(true);\n\t\t}\n\t\trow++;\n\t}\n\t_txtRemaining->setText(tr(\"STR_REMAINING_PSI_LAB_CAPACITY\").arg(_labSpace));\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/AllocatePsiTrainingState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include <vector>\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass ToggleTextButton;\nclass Window;\nclass Text;\nclass Base;\nclass TextList;\nclass ComboBox;\nclass Soldier;\nstruct SortFunctor;\n\n/**\n * Screen shown monthly to allow changing\n * soldiers currently in psi training.\n */\nclass AllocatePsiTrainingState : public State\n{\nprivate:\n\tTextButton *_btnOk;\n\tToggleTextButton *_btnPlus;\n\tWindow *_window;\n\tText *_txtTitle, *_txtTraining, *_txtName, *_txtRemaining;\n\tText *_txtPsiStrength, *_txtPsiSkill;\n\tComboBox *_cbxSortBy;\n\tTextList *_lstSoldiers;\n\tstd::vector<Soldier*> _soldiers;\n\tsize_t _sel;\n\tint _labSpace;\n\tBase *_base;\n\tstd::vector<Soldier *> _origSoldierOrder;\n\tstd::vector<SortFunctor *> _sortFunctors;\n\tstd::vector<SortFunctor *> _sortFunctorsPlus;\n\tbool _doNotReset;\n\n\t///initializes the display list based on the craft soldier's list and the position to display\n\tvoid initList(size_t scrl);\npublic:\n\t/// Creates the Psi Training state.\n\tAllocatePsiTrainingState(Base *base);\n\t/// Cleans up the Psi Training state.\n\t~AllocatePsiTrainingState();\n\t/// Handler for changing the sort by combobox.\n\tvoid cbxSortByChange(Action *action);\n\t/// Updates the soldier info.\n\tvoid init() override;\n\t/// Handler for clicking the Soldiers reordering button.\n\tvoid lstItemsLeftArrowClick(Action *action);\n\t/// Moves a soldier up.\n\tvoid moveSoldierUp(Action *action, unsigned int row, bool max = false);\n\t/// Handler for clicking the Soldiers reordering button.\n\tvoid lstItemsRightArrowClick(Action *action);\n\t/// Moves a soldier down.\n\tvoid moveSoldierDown(Action *action, unsigned int row, bool max = false);\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the PLUS button.\n\tvoid btnPlusClick(Action *action);\n\t/// Handler for clicking the Soldiers list.\n\tvoid lstSoldiersClick(Action *action);\n\t/// Handler for pressing-down a mouse-button in the list.\n\tvoid lstSoldiersMousePress(Action *action);\n\t/// Handler for clicking the De-assign All Soldiers button.\n\tvoid btnDeassignAllSoldiersClick(Action* action);\n\t/// Handler for clicking the Assign All Soldiers button.\n\tvoid btnAssignAllSoldiersClick(Action* action);\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/AllocateTrainingState.cpp",
    "content": "/*\n * Copyright 2010-2015 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <sstream>\n#include <climits>\n#include \"TrainingState.h\"\n#include \"AllocateTrainingState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Language.h\"\n#include \"../Mod/RuleInterface.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/ToggleTextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Savegame/Soldier.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/ComboBox.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Basescape/SoldierInfoState.h\"\n#include \"../Basescape/SoldierSortUtil.h\"\n#include <algorithm>\n#include \"../Engine/Unicode.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Psi Training screen.\n * @param game Pointer to the core game.\n * @param base Pointer to the base to handle.\n */\nAllocateTrainingState::AllocateTrainingState(Base *base) : _sel(0), _base(base), _origSoldierOrder(*_base->getSoldiers()), _doNotReset(false)\n{\n\t// Create objects\n\t_window = new Window(this, 320, 200, 0, 0);\n\t_txtTitle = new Text(300, 17, 10, 8);\n\t_txtRemaining = new Text(300, 10, 10, 24);\n\t_txtName = new Text(64, 10, 10, 40);\n\t_txtTraining = new Text(48, 20, 270, 32);\n\t_btnOk = new TextButton(148, 16, 164, 176);\n\t_lstSoldiers = new TextList(290, 112, 8, 52);\n\t_txtTu = new Text(18, 10, 120, 40);\n\t_txtStamina = new Text(18, 10, 138, 40);\n\t_txtHealth = new Text(18, 10, 156, 40);\n\t_txtFiring = new Text(18, 10, 174, 40);\n\t_txtThrowing = new Text(18, 10, 192, 40);\n\t_txtMelee = new Text(18, 10, 210, 40);\n\t_txtStrength = new Text(18, 10, 228, 40);\n\t_cbxSortBy = new ComboBox(this, 148, 16, 8, 176, true);\n\t_btnPlus = new ToggleTextButton(18, 16, 294, 8);\n\n\t// Set palette\n\tsetInterface(\"allocateMartial\");\n\n\tadd(_window, \"window\", \"allocateMartial\");\n\tadd(_btnOk, \"button\", \"allocateMartial\");\n\tadd(_txtName, \"text\", \"allocateMartial\");\n\tadd(_txtTitle, \"text\", \"allocateMartial\");\n\tadd(_txtRemaining, \"text\", \"allocateMartial\");\n\tadd(_txtTraining, \"text\", \"allocateMartial\");\n\tadd(_lstSoldiers, \"list\", \"allocateMartial\");\n\tadd(_txtTu, \"text\", \"allocateMartial\");\n\tadd(_txtStamina, \"text\", \"allocateMartial\");\n\tadd(_txtHealth, \"text\", \"allocateMartial\");\n\tadd(_txtFiring, \"text\", \"allocateMartial\");\n\tadd(_txtThrowing, \"text\", \"allocateMartial\");\n\tadd(_txtMelee, \"text\", \"allocateMartial\");\n\tadd(_txtStrength, \"text\", \"allocateMartial\");\n\tadd(_cbxSortBy, \"button\", \"allocateMartial\");\n\tadd(_btnPlus, \"button\", \"allocateMartial\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"allocateMartial\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&AllocateTrainingState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&AllocateTrainingState::btnOkClick, Options::keyCancel);\n\t_btnOk->onKeyboardPress((ActionHandler)& AllocateTrainingState::btnDeassignAllSoldiersClick, Options::keyRemoveSoldiersFromTraining);\n\t_btnOk->onKeyboardPress((ActionHandler)&AllocateTrainingState::btnAssignAllSoldiersClick, Options::keyAddSoldiersToTraining);\n\n\t_btnPlus->setText(\"+\");\n\t_btnPlus->setPressed(false);\n\tif (_game->getMod()->getSoldierBonusList().empty())\n\t{\n\t\t// no soldier bonuses in the mod = button not needed\n\t\t_btnPlus->setVisible(false);\n\t}\n\telse\n\t{\n\t\t_btnPlus->onMouseClick((ActionHandler)&AllocateTrainingState::btnPlusClick, 0);\n\t}\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_PHYSICAL_TRAINING\"));\n\n\t_space = base->getAvailableTraining() - base->getUsedTraining();\n\t_txtRemaining->setText(tr(\"STR_REMAINING_TRAINING_FACILITY_CAPACITY\").arg(_space));\n\n\t_txtName->setText(tr(\"STR_NAME\"));\n\t_txtTu->setText(tr(\"STR_TIME_UNITS_ABBREVIATION\"));\n\t_txtStamina->setText(tr(\"STR_STAMINA_ABBREVIATION\"));\n\t_txtHealth->setText(tr(\"STR_HEALTH_ABBREVIATION\"));\n\t_txtFiring->setText(tr(\"STR_FIRING_ACCURACY_ABBREVIATION\"));\n\t_txtThrowing->setText(tr(\"STR_THROWING_ACCURACY_ABBREVIATION\"));\n\t_txtMelee->setText(tr(\"STR_MELEE_ACCURACY_ABBREVIATION\"));\n\t_txtStrength->setText(tr(\"STR_STRENGTH_ABBREVIATION\"));\n\t_txtTraining->setText(tr(\"STR_IN_TRAINING\"));\n\n\t// populate sort options\n\tstd::vector<std::string> sortOptions;\n\tsortOptions.push_back(tr(\"STR_ORIGINAL_ORDER\"));\n\t_sortFunctors.push_back(NULL);\n\t_sortFunctorsPlus.push_back(NULL);\n\n#define PUSH_IN(strId, functor) \\\n\tsortOptions.push_back(tr(strId)); \\\n\t_sortFunctors.push_back(new SortFunctor(_game, functor)); \\\n\t_sortFunctorsPlus.push_back(new SortFunctor(_game, functor));\n\n\tPUSH_IN(\"STR_ID\", idStat);\n\tPUSH_IN(\"STR_NAME_UC\", nameStat);\n\tPUSH_IN(\"STR_SOLDIER_TYPE\", typeStat);\n\tPUSH_IN(\"STR_RANK\", rankStat);\n\tPUSH_IN(\"STR_IDLE_DAYS\", idleDaysStat);\n\tPUSH_IN(\"STR_MISSIONS2\", missionsStat);\n\tPUSH_IN(\"STR_KILLS2\", killsStat);\n\tPUSH_IN(\"STR_WOUND_RECOVERY2\", woundRecoveryStat);\n\tif (_game->getMod()->isManaFeatureEnabled() && !_game->getMod()->getReplenishManaAfterMission())\n\t{\n\t\tPUSH_IN(\"STR_MANA_MISSING\", manaMissingStat);\n\t}\n\n#undef PUSH_IN\n\n#define PUSH_IN(strId, functor, functorPlus) \\\n\tsortOptions.push_back(tr(strId)); \\\n\t_sortFunctors.push_back(new SortFunctor(_game, functor)); \\\n\t_sortFunctorsPlus.push_back(new SortFunctor(_game, functorPlus));\n\n\tPUSH_IN(\"STR_TIME_UNITS\", tuStatBase, tuStatPlus);\n\tPUSH_IN(\"STR_STAMINA\", staminaStatBase, staminaStatPlus);\n\tPUSH_IN(\"STR_HEALTH\", healthStatBase, healthStatPlus);\n\tPUSH_IN(\"STR_BRAVERY\", braveryStatBase, braveryStatPlus);\n\tPUSH_IN(\"STR_REACTIONS\", reactionsStatBase, reactionsStatPlus);\n\tPUSH_IN(\"STR_FIRING_ACCURACY\", firingStatBase, firingStatPlus);\n\tPUSH_IN(\"STR_THROWING_ACCURACY\", throwingStatBase, throwingStatPlus);\n\tPUSH_IN(\"STR_MELEE_ACCURACY\", meleeStatBase, meleeStatPlus);\n\tPUSH_IN(\"STR_STRENGTH\", strengthStatBase, strengthStatPlus);\n\tif (_game->getMod()->isManaFeatureEnabled())\n\t{\n\t\t// \"unlock\" is checked later\n\t\tPUSH_IN(\"STR_MANA_POOL\", manaStatBase, manaStatPlus);\n\t}\n\tPUSH_IN(\"STR_PSIONIC_STRENGTH\", psiStrengthStatBase, psiStrengthStatPlus);\n\tPUSH_IN(\"STR_PSIONIC_SKILL\", psiSkillStatBase, psiSkillStatPlus);\n\n#undef PUSH_IN\n\n\t_cbxSortBy->setOptions(sortOptions);\n\t_cbxSortBy->setSelected(0);\n\t_cbxSortBy->onChange((ActionHandler)&AllocateTrainingState::cbxSortByChange);\n\t_cbxSortBy->setText(tr(\"STR_SORT_BY\"));\n\n\t_lstSoldiers->setArrowColumn(238, ARROW_VERTICAL);\n\t_lstSoldiers->setColumns(9, 110, 18, 18, 18, 18, 18, 18, 42, 40);\n\t_lstSoldiers->setSelectable(true);\n\t_lstSoldiers->setBackground(_window);\n\t_lstSoldiers->setMargin(2);\n\t_lstSoldiers->onLeftArrowClick((ActionHandler)&AllocateTrainingState::lstItemsLeftArrowClick);\n\t_lstSoldiers->onRightArrowClick((ActionHandler)&AllocateTrainingState::lstItemsRightArrowClick);\n\t_lstSoldiers->onMouseClick((ActionHandler)&AllocateTrainingState::lstSoldiersClick);\n\t_lstSoldiers->onMouseClick((ActionHandler)&AllocateTrainingState::lstSoldiersClick, SDL_BUTTON_RIGHT);\n\t_lstSoldiers->onMousePress((ActionHandler)&AllocateTrainingState::lstSoldiersMousePress);\n}\n\n/**\n * cleans up dynamic state\n */\nAllocateTrainingState::~AllocateTrainingState()\n{\n\tfor (auto* sortFunctor : _sortFunctors)\n\t{\n\t\tdelete sortFunctor;\n\t}\n}\n\n/**\n * Sorts the soldiers list by the selected criterion\n * @param action Pointer to an action.\n */\nvoid AllocateTrainingState::cbxSortByChange(Action *action)\n{\n\tsize_t selIdx = _cbxSortBy->getSelected();\n\tif (selIdx == (size_t)-1)\n\t{\n\t\treturn;\n\t}\n\n\tSortFunctor *compFunc = _btnPlus->getPressed() ? _sortFunctorsPlus[selIdx] : _sortFunctors[selIdx];\n\tif (compFunc)\n\t{\n\t\tif (selIdx == 2)\n\t\t{\n\t\t\tstd::stable_sort(_base->getSoldiers()->begin(), _base->getSoldiers()->end(),\n\t\t\t\t[](const Soldier* a, const Soldier* b)\n\t\t\t\t{\n\t\t\t\t\treturn Unicode::naturalCompare(a->getName(), b->getName());\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tstd::stable_sort(_base->getSoldiers()->begin(), _base->getSoldiers()->end(), *compFunc);\n\t\t}\n\t\tif (_game->isShiftPressed())\n\t\t{\n\t\t\tstd::reverse(_base->getSoldiers()->begin(), _base->getSoldiers()->end());\n\t\t}\n\t}\n\telse\n\t{\n\t\t// restore original ordering, ignoring (of course) those\n\t\t// soldiers that have been sacked since this state started\n\t\tfor (const auto* origSoldier : _origSoldierOrder)\n\t\t{\n\t\t\tauto soldierIt = std::find(_base->getSoldiers()->begin(), _base->getSoldiers()->end(), origSoldier);\n\t\t\tif (soldierIt != _base->getSoldiers()->end())\n\t\t\t{\n\t\t\t\tSoldier *s = *soldierIt;\n\t\t\t\t_base->getSoldiers()->erase(soldierIt);\n\t\t\t\t_base->getSoldiers()->insert(_base->getSoldiers()->end(), s);\n\t\t\t}\n\t\t}\n\t}\n\n\tsize_t originalScrollPos = _lstSoldiers->getScroll();\n\tinitList(originalScrollPos);\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid AllocateTrainingState::btnOkClick(Action *)\n{\n\t// Note: statString updates not necessary\n\t_game->popState();\n}\n\n/**\n * Updates the soldier stats. Sorts the list if applicable.\n * @param action Pointer to an action.\n */\nvoid AllocateTrainingState::btnPlusClick(Action *action)\n{\n\tsize_t selIdx = _cbxSortBy->getSelected();\n\tif (selIdx == (size_t)-1)\n\t{\n\t\tsize_t originalScrollPos = _lstSoldiers->getScroll();\n\t\tinitList(originalScrollPos);\n\t}\n\telse\n\t{\n\t\tcbxSortByChange(action);\n\t}\n}\n\n/**\n * The soldier info could maybe change (armor? something else?)\n * after going into other screens.\n */\nvoid AllocateTrainingState::init()\n{\n\tState::init();\n\n\t// coming back from SoldierInfoState\n\tif (_doNotReset)\n\t{\n\t\t_doNotReset = false;\n\t\treturn;\n\t}\n\n\t_base->prepareSoldierStatsWithBonuses(); // refresh stats for sorting\n\tinitList(0);\n}\n\n/**\n * Shows the soldiers in a list at specified offset/scroll.\n */\nvoid AllocateTrainingState::initList(size_t scrl)\n{\n\tint row = 0;\n\t_lstSoldiers->clearList();\n\tfor (auto* soldier : *_base->getSoldiers())\n\t{\n\t\tconst UnitStats* stats = _btnPlus->getPressed() ? soldier->getStatsWithSoldierBonusesOnly() : soldier->getCurrentStats();\n\n\t\tstd::ostringstream tu;\n\t\ttu << stats->tu;\n\t\tstd::ostringstream stamina;\n\t\tstamina << stats->stamina;\n\t\tstd::ostringstream health;\n\t\thealth << stats->health;\n\t\tstd::ostringstream firing;\n\t\tfiring << stats->firing;\n\t\tstd::ostringstream throwing;\n\t\tthrowing << stats->throwing;\n\t\tstd::ostringstream melee;\n\t\tmelee << stats->melee;\n\t\tstd::ostringstream strength;\n\t\tstrength << stats->strength;\n\n\t\tbool isDone = soldier->isFullyTrained();\n\t\tbool isWounded = soldier->isWounded();\n\t\tbool isTraining = soldier->isInTraining();\n\t\tbool isQueued = !isTraining && soldier->getReturnToTrainingWhenHealed();\n\n\t\tstd::string status;\n\t\tif (isDone)\n\t\t\tstatus = tr(\"STR_NO_DONE\");\n\t\telse if (isQueued)\n\t\t\tstatus = tr(\"STR_NO_QUEUED\");\n\t\telse if (isWounded)\n\t\t\tstatus = tr(\"STR_NO_WOUNDED\");\n\t\telse if (isTraining)\n\t\t\tstatus = tr(\"STR_YES\");\n\t\telse\n\t\t\tstatus = tr(\"STR_NO\");\n\n\t\t_lstSoldiers->addRow(9,\n\t\t\tsoldier->getName(true).c_str(),\n\t\t\ttu.str().c_str(),\n\t\t\tstamina.str().c_str(),\n\t\t\thealth.str().c_str(),\n\t\t\tfiring.str().c_str(),\n\t\t\tthrowing.str().c_str(),\n\t\t\tmelee.str().c_str(),\n\t\t\tstrength.str().c_str(),\n\t\t\tstatus.c_str());\n\t\t_lstSoldiers->setRowColor(row, isTraining ? _lstSoldiers->getSecondaryColor() : _lstSoldiers->getColor());\n\t\trow++;\n\t}\n\tif (scrl)\n\t\t_lstSoldiers->scrollTo(scrl);\n\t_lstSoldiers->draw();\n}\n\n/**\n * Reorders a soldier up.\n * @param action Pointer to an action.\n */\nvoid AllocateTrainingState::lstItemsLeftArrowClick(Action *action)\n{\n\tunsigned int row = _lstSoldiers->getSelectedRow();\n\tif (row > 0)\n\t{\n\t\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT)\n\t\t{\n\t\t\tmoveSoldierUp(action, row);\n\t\t}\n\t\telse if (action->getDetails()->button.button == SDL_BUTTON_RIGHT)\n\t\t{\n\t\t\tmoveSoldierUp(action, row, true);\n\t\t}\n\t}\n\t_cbxSortBy->setText(tr(\"STR_SORT_BY\"));\n\t_cbxSortBy->setSelected(-1);\n}\n\n/**\n * Moves a soldier up on the list.\n * @param action Pointer to an action.\n * @param row Selected soldier row.\n * @param max Move the soldier to the top?\n */\nvoid AllocateTrainingState::moveSoldierUp(Action *action, unsigned int row, bool max)\n{\n\tSoldier *s = _base->getSoldiers()->at(row);\n\tif (max)\n\t{\n\t\t_base->getSoldiers()->erase(_base->getSoldiers()->begin() + row);\n\t\t_base->getSoldiers()->insert(_base->getSoldiers()->begin(), s);\n\t}\n\telse\n\t{\n\t\t_base->getSoldiers()->at(row) = _base->getSoldiers()->at(row - 1);\n\t\t_base->getSoldiers()->at(row - 1) = s;\n\t\tif (row != _lstSoldiers->getScroll())\n\t\t{\n\t\t\tSDL_WarpMouse(action->getLeftBlackBand() + action->getXMouse(), action->getTopBlackBand() + action->getYMouse() - static_cast<Uint16>(8 * action->getYScale()));\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_lstSoldiers->scrollUp(false);\n\t\t}\n\t}\n\tinitList(_lstSoldiers->getScroll());\n}\n\n/**\n * Reorders a soldier down.\n * @param action Pointer to an action.\n */\nvoid AllocateTrainingState::lstItemsRightArrowClick(Action *action)\n{\n\tunsigned int row = _lstSoldiers->getSelectedRow();\n\tsize_t numSoldiers = _base->getSoldiers()->size();\n\tif (0 < numSoldiers && INT_MAX >= numSoldiers && row < numSoldiers - 1)\n\t{\n\t\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT)\n\t\t{\n\t\t\tmoveSoldierDown(action, row);\n\t\t}\n\t\telse if (action->getDetails()->button.button == SDL_BUTTON_RIGHT)\n\t\t{\n\t\t\tmoveSoldierDown(action, row, true);\n\t\t}\n\t}\n\t_cbxSortBy->setText(tr(\"STR_SORT_BY\"));\n\t_cbxSortBy->setSelected(-1);\n}\n\n/**\n * Moves a soldier down on the list.\n * @param action Pointer to an action.\n * @param row Selected soldier row.\n * @param max Move the soldier to the bottom?\n */\nvoid AllocateTrainingState::moveSoldierDown(Action *action, unsigned int row, bool max)\n{\n\tSoldier *s = _base->getSoldiers()->at(row);\n\tif (max)\n\t{\n\t\t_base->getSoldiers()->erase(_base->getSoldiers()->begin() + row);\n\t\t_base->getSoldiers()->insert(_base->getSoldiers()->end(), s);\n\t}\n\telse\n\t{\n\t\t_base->getSoldiers()->at(row) = _base->getSoldiers()->at(row + 1);\n\t\t_base->getSoldiers()->at(row + 1) = s;\n\t\tif (row != _lstSoldiers->getVisibleRows() - 1 + _lstSoldiers->getScroll())\n\t\t{\n\t\t\tSDL_WarpMouse(action->getLeftBlackBand() + action->getXMouse(), action->getTopBlackBand() + action->getYMouse() + static_cast<Uint16>(8 * action->getYScale()));\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_lstSoldiers->scrollDown(false);\n\t\t}\n\t}\n\tinitList(_lstSoldiers->getScroll());\n}\n\n/**\n * Assigns / removes a soldier from Psi Training.\n * @param action Pointer to an action.\n */\nvoid AllocateTrainingState::lstSoldiersClick(Action *action)\n{\n\tdouble mx = action->getAbsoluteXMouse();\n\tif (mx >= _lstSoldiers->getArrowsLeftEdge() && mx < _lstSoldiers->getArrowsRightEdge())\n\t{\n\t\treturn;\n\t}\n\n\t_sel = _lstSoldiers->getSelectedRow();\n\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT)\n\t{\n\t\tauto* soldier = _base->getSoldiers()->at(_sel);\n\n\t\t// can't put fully trained soldiers back into training\n\t\tif (soldier->isFullyTrained()) return;\n\n\t\t// wounded soldiers can be queued/dequeued\n\t\tif (soldier->isWounded())\n\t\t{\n\t\t\tif (soldier->getReturnToTrainingWhenHealed())\n\t\t\t{\n\t\t\t\t_lstSoldiers->setCellText(_sel, 8, tr(\"STR_NO_WOUNDED\").c_str());\n\t\t\t\tsoldier->setReturnToTrainingWhenHealed(false);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_lstSoldiers->setCellText(_sel, 8, tr(\"STR_NO_QUEUED\").c_str());\n\t\t\t\tsoldier->setReturnToTrainingWhenHealed(true);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// healthy soldiers can be assigned/deassigned\n\t\tif (!soldier->isInTraining())\n\t\t{\n\t\t\tif (_base->getUsedTraining() < _base->getAvailableTraining())\n\t\t\t{\n\t\t\t\t_lstSoldiers->setCellText(_sel, 8, tr(\"STR_YES\").c_str());\n\t\t\t\t_lstSoldiers->setRowColor(_sel, _lstSoldiers->getSecondaryColor());\n\t\t\t\t_space--;\n\t\t\t\t_txtRemaining->setText(tr(\"STR_REMAINING_TRAINING_FACILITY_CAPACITY\").arg(_space));\n\t\t\t\tsoldier->setTraining(true);\n\t\t\t\tsoldier->setReturnToTrainingWhenHealed(false);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_lstSoldiers->setCellText(_sel, 8, tr(\"STR_NO\").c_str());\n\t\t\t_lstSoldiers->setRowColor(_sel, _lstSoldiers->getColor());\n\t\t\t_space++;\n\t\t\t_txtRemaining->setText(tr(\"STR_REMAINING_TRAINING_FACILITY_CAPACITY\").arg(_space));\n\t\t\tsoldier->setTraining(false);\n\t\t\tsoldier->setReturnToTrainingWhenHealed(false);\n\t\t}\n\t}\n\telse if (action->getDetails()->button.button == SDL_BUTTON_RIGHT)\n\t{\n\t\t_doNotReset = true;\n\t\t_game->pushState(new SoldierInfoState(_base, _sel, true, true));\n\t}\n}\n\n/**\n * Handles the mouse-wheels on the arrow-buttons.\n * @param action Pointer to an action.\n */\nvoid AllocateTrainingState::lstSoldiersMousePress(Action *action)\n{\n\tif (Options::changeValueByMouseWheel == 0)\n\t\treturn;\n\tunsigned int row = _lstSoldiers->getSelectedRow();\n\tsize_t numSoldiers = _base->getSoldiers()->size();\n\tif (action->getDetails()->button.button == SDL_BUTTON_WHEELUP &&\n\t\trow > 0)\n\t{\n\t\tif (action->getAbsoluteXMouse() >= _lstSoldiers->getArrowsLeftEdge() &&\n\t\t\taction->getAbsoluteXMouse() <= _lstSoldiers->getArrowsRightEdge())\n\t\t{\n\t\t\tmoveSoldierUp(action, row);\n\t\t}\n\t}\n\telse if (action->getDetails()->button.button == SDL_BUTTON_WHEELDOWN &&\n\t\t0 < numSoldiers && INT_MAX >= numSoldiers && row < numSoldiers - 1)\n\t{\n\t\tif (action->getAbsoluteXMouse() >= _lstSoldiers->getArrowsLeftEdge() &&\n\t\t\taction->getAbsoluteXMouse() <= _lstSoldiers->getArrowsRightEdge())\n\t\t{\n\t\t\tmoveSoldierDown(action, row);\n\t\t}\n\t}\n}\n\n/**\n * Removes all soldiers from Martial Training.\n * @param action Pointer to an action.\n */\nvoid AllocateTrainingState::btnDeassignAllSoldiersClick(Action* action)\n{\n\tint row = 0;\n\tfor (auto* soldier : *_base->getSoldiers())\n\t{\n\t\tsoldier->setTraining(false);\n\t\tsoldier->setReturnToTrainingWhenHealed(false);\n\n\t\tstd::string status;\n\t\tif (soldier->isFullyTrained())\n\t\t\tstatus = tr(\"STR_NO_DONE\");\n\t\telse if (soldier->isWounded())\n\t\t\tstatus = tr(\"STR_NO_WOUNDED\");\n\t\telse\n\t\t\tstatus = tr(\"STR_NO\");\n\n\t\t_lstSoldiers->setCellText(row, 8, tr(status).c_str());\n\t\t_lstSoldiers->setRowColor(row, _lstSoldiers->getColor());\n\t\trow++;\n\t}\n\t_space = _base->getAvailableTraining() - _base->getUsedTraining();\n\t_txtRemaining->setText(tr(\"STR_REMAINING_TRAINING_FACILITY_CAPACITY\").arg(_space));\n}\n\n/**\n * Adds all soldiers to Martial Training.\n * @param action Pointer to an action.\n */\nvoid AllocateTrainingState::btnAssignAllSoldiersClick(Action* action)\n{\n\tint row = 0;\n\tfor (auto* soldier : *_base->getSoldiers())\n\t{\n\t\tif (soldier->isFullyTrained())\n\t\t{\n\t\t\t// can't put fully trained soldiers back into training\n\t\t}\n\t\telse if (soldier->isWounded())\n\t\t{\n\t\t\t// wounded soldiers can be queued\n\t\t\tif (!soldier->getReturnToTrainingWhenHealed())\n\t\t\t{\n\t\t\t\t_lstSoldiers->setCellText(row, 8, tr(\"STR_NO_QUEUED\").c_str());\n\t\t\t\tsoldier->setReturnToTrainingWhenHealed(true);\n\t\t\t}\n\t\t}\n\t\telse if (_space > 0 && !soldier->isInTraining())\n\t\t{\n\t\t\t// healthy soldiers can be assigned\n\t\t\t_lstSoldiers->setCellText(row, 8, tr(\"STR_YES\").c_str());\n\t\t\t_lstSoldiers->setRowColor(row, _lstSoldiers->getSecondaryColor());\n\t\t\t_space--;\n\t\t\tsoldier->setTraining(true);\n\t\t\tsoldier->setReturnToTrainingWhenHealed(false);\n\t\t}\n\t\trow++;\n\t}\n\t_txtRemaining->setText(tr(\"STR_REMAINING_TRAINING_FACILITY_CAPACITY\").arg(_space));\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/AllocateTrainingState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2015 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include <vector>\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass ToggleTextButton;\nclass Window;\nclass Text;\nclass Base;\nclass TextList;\nclass ComboBox;\nclass Soldier;\nstruct SortFunctor;\n\n/**\n * Screen shown monthly to allow changing\n * soldiers currently in psi training.\n */\nclass AllocateTrainingState : public State\n{\nprivate:\n\tTextButton *_btnOk;\n\tToggleTextButton *_btnPlus;\n\tWindow *_window;\n\tText *_txtTitle, *_txtTraining, *_txtName, *_txtRemaining;\n\tText *_txtTu, *_txtStamina, *_txtHealth, *_txtFiring, *_txtThrowing, *_txtMelee, *_txtStrength;\n\tComboBox *_cbxSortBy;\n\tTextList *_lstSoldiers;\n\tstd::vector<Soldier*> _soldiers;\n\tsize_t _sel;\n\tint _space;\n\tBase *_base;\n\tstd::vector<Soldier *> _origSoldierOrder;\n\tstd::vector<SortFunctor *> _sortFunctors;\n\tstd::vector<SortFunctor *> _sortFunctorsPlus;\n\tbool _doNotReset;\n\n\t///initializes the display list\n\tvoid initList(size_t scrl);\npublic:\n\t/// Creates the Psi Training state.\n\tAllocateTrainingState(Base *base);\n\t/// Cleans up the Psi Training state.\n\t~AllocateTrainingState();\n\t/// Handler for changing the sort by combobox.\n\tvoid cbxSortByChange(Action *action);\n\t/// Updates the soldier info.\n\tvoid init() override;\n\t/// Handler for clicking the Soldiers reordering button.\n\tvoid lstItemsLeftArrowClick(Action *action);\n\t/// Moves a soldier up.\n\tvoid moveSoldierUp(Action *action, unsigned int row, bool max = false);\n\t/// Handler for clicking the Soldiers reordering button.\n\tvoid lstItemsRightArrowClick(Action *action);\n\t/// Moves a soldier down.\n\tvoid moveSoldierDown(Action *action, unsigned int row, bool max = false);\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the PLUS button.\n\tvoid btnPlusClick(Action *action);\n\t/// Handler for clicking the Soldiers list.\n\tvoid lstSoldiersClick(Action *action);\n\t/// Handler for pressing-down a mouse-button in the list.\n\tvoid lstSoldiersMousePress(Action *action);\n\t/// Handler for clicking the De-assign All Soldiers button.\n\tvoid btnDeassignAllSoldiersClick(Action* action);\n\t/// Handler for clicking the Assign All Soldiers button.\n\tvoid btnAssignAllSoldiersClick(Action* action);\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/BaseDefenseState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"BaseDefenseState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/AlienMission.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/ItemContainer.h\"\n#include \"../Savegame/Region.h\"\n#include \"../Mod/RuleRegion.h\"\n#include \"../Savegame/BaseFacility.h\"\n#include \"../Mod/RuleBaseFacility.h\"\n#include \"../Savegame/Ufo.h\"\n#include \"../Interface/TextList.h\"\n#include \"GeoscapeState.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/RNG.h\"\n#include \"../Engine/Sound.h\"\n#include \"../Engine/Timer.h\"\n#include \"../Engine/Options.h\"\n#include \"../Mod/RuleInterface.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Base Defense screen.\n * @param game Pointer to the core game.\n * @param base Pointer to the base being attacked.\n * @param ufo Pointer to the attacking ufo.\n * @param state Pointer to the Geoscape.\n */\nBaseDefenseState::BaseDefenseState(Base *base, Ufo *ufo, GeoscapeState *state, bool instaHyper) : _state(state)\n{\n\tbool showUfo = _game->getMod()->showUfoPreviewInBaseDefense();\n\n\t_base = base;\n\t_action = BDA_NONE;\n\t_row = -1;\n\t_passes = 0;\n\t_attacks = 0;\n\t_thinkcycles = 0;\n\t_ufo = ufo;\n\t// Create objects\n\t_window = new Window(this, 320, 200, 0, 0);\n\t_txtTitle = new Text(300, 17, 16, 6);\n\t_txtInit = new Text(300, 10, 16, 24);\n\t_lstDefenses = new TextList(300, 128, 16, 40);\n\t_btnOk = new TextButton(120, 18, 100, 170);\n\t_btnStart = new TextButton(showUfo ? 148-13 : 148, 16, 8, 176);\n\t_btnAbort = new TextButton(showUfo ? 148+13 : 148, 16, showUfo ? 164-13 : 164, 176);\n\t_preview = new InteractiveSurface(160, 96, 151, 75);\n\n\t// Set palette\n\tstd::string baseDefenseInterface = showUfo ? \"baseDefense_geo\" : \"baseDefense\";\n\tsetInterface(baseDefenseInterface);\n\n\tadd(_window, \"window\", baseDefenseInterface);\n\tadd(_btnOk, \"button\", baseDefenseInterface);\n\tadd(_btnStart, \"button\", baseDefenseInterface);\n\tadd(_btnAbort, \"button\", baseDefenseInterface);\n\tadd(_txtTitle, \"text\", baseDefenseInterface);\n\tadd(_txtInit, \"text\", baseDefenseInterface);\n\tadd(_lstDefenses, \"text\", baseDefenseInterface);\n\tadd(_preview);\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, baseDefenseInterface);\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&BaseDefenseState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&BaseDefenseState::btnOkClick, Options::keyOk);\n\t_btnOk->onKeyboardPress((ActionHandler)&BaseDefenseState::btnOkClick, Options::keyCancel);\n\t_btnOk->setVisible(false);\n\n\t_btnStart->setText(tr(\"STR_START_FIRING\"));\n\t_btnStart->onMouseClick((ActionHandler)&BaseDefenseState::btnStartClick);\n\n\t_btnAbort->setText(tr(\"STR_SKIP_FIRING\"));\n\t_btnAbort->onMouseClick((ActionHandler)&BaseDefenseState::btnOkClick);\n\n\t_txtTitle->setBig();\n\t_txtTitle->setText(tr(\"STR_BASE_UNDER_ATTACK\").arg(_base->getName()));\n\t_txtInit->setVisible(false);\n\n\t_txtInit->setText(tr(\"STR_BASE_DEFENSES_INITIATED\"));\n\n\t_lstDefenses->setColumns(3, 134, 70, 50);\n\t_lstDefenses->setFlooding(true);\n\n\tif (showUfo)\n\t{\n\t\tRuleInterface* dogfightInterface = _game->getMod()->getInterface(\"dogfight\");\n\n\t\tSurfaceCrop crop = _game->getMod()->getSurface(\"INTERWIN.DAT\")->getCrop();\n\t\tcrop.setX(0);\n\t\tcrop.setY(0);\n\t\tcrop.getCrop()->x = 0;\n\t\tcrop.getCrop()->y = 0;\n\t\tcrop.getCrop()->w = _preview->getWidth();\n\t\tcrop.getCrop()->h = _preview->getHeight();\n\t\t//_preview->drawRect(crop.getCrop(), 15);\n\t\t//crop.blit(_preview);\n\n\t\t_preview->drawRect(crop.getCrop(), 15);\n\t\tcrop.getCrop()->y = dogfightInterface->getElement(\"previewTop\")->y;\n\t\tcrop.getCrop()->h = dogfightInterface->getElement(\"previewTop\")->h;\n\t\tcrop.blit(_preview);\n\n\t\tcrop.setY(_preview->getHeight() - dogfightInterface->getElement(\"previewBot\")->h);\n\t\tcrop.getCrop()->y = dogfightInterface->getElement(\"previewBot\")->y;\n\t\tcrop.getCrop()->h = dogfightInterface->getElement(\"previewBot\")->h;\n\t\tcrop.blit(_preview);\n\n\t\tif (ufo->getRules()->getModSprite().empty())\n\t\t{\n\t\t\tcrop.getCrop()->y = dogfightInterface->getElement(\"previewMid\")->y + dogfightInterface->getElement(\"previewMid\")->h * _ufo->getRules()->getSprite();\n\t\t\tcrop.getCrop()->h = dogfightInterface->getElement(\"previewMid\")->h;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tcrop = _game->getMod()->getSurface(ufo->getRules()->getModSprite())->getCrop();\n\t\t}\n\t\tcrop.setX(dogfightInterface->getElement(\"previewTop\")->x);\n\t\tcrop.setY(dogfightInterface->getElement(\"previewTop\")->h);\n\t\tcrop.blit(_preview);\n\n\t\t// extra info\n\t\tbool extraInfo = ufo->getHyperDetected();\n\t\tif (!extraInfo && instaHyper)\n\t\t{\n\t\t\tfor (auto* fac : *_base->getFacilities())\n\t\t\t{\n\t\t\t\tif (fac->getBuildTime() == 0 && fac->getRules()->isHyperwave())\n\t\t\t\t{\n\t\t\t\t\textraInfo = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (extraInfo)\n\t\t{\n\t\t\tstd::ostringstream ss;\n\t\t\tss << Unicode::TOK_COLOR_FLIP << tr(_ufo->getRules()->getType());\n\t\t\t_lstDefenses->addRow(3, tr(\"STR_CRAFT_TYPE\").c_str(), ss.str().c_str(), \"\");\n\n\t\t\tss.str(\"\");\n\t\t\tss << Unicode::TOK_COLOR_FLIP << tr(_ufo->getAlienRace());\n\t\t\t_lstDefenses->addRow(3, tr(\"STR_RACE\").c_str(), ss.str().c_str(), \"\");\n\n\t\t\tss.str(\"\");\n\t\t\tss << Unicode::TOK_COLOR_FLIP << tr(_ufo->getMissionType());\n\t\t\t_lstDefenses->addRow(3, tr(\"STR_MISSION\").c_str(), ss.str().c_str(), \"\");\n\n\t\t}\n\t}\n\telse\n\t{\n\t\t_preview->setVisible(false);\n\t}\n\n\t_gravShields = _base->getGravShields();\n\t_defenses = _base->getDefenses()->size();\n\t_timer = new Timer(250);\n\t_timer->onTimer((StateHandler)&BaseDefenseState::nextStep);\n\n\t_explosionCount = 0;\n\n\tif (_ufo->getRules()->getMissilePower() != 0)\n\t{\n\t\tif (showUfo)\n\t\t{\n\t\t\t_btnAbort->setVisible(false);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tbtnStartClick(0);\n\t\t}\n\t}\n}\n\n/**\n *\n */\nBaseDefenseState::~BaseDefenseState()\n{\n\tdelete _timer;\n}\n\nvoid BaseDefenseState::think()\n{\n\t_timer->think(this, 0);\n}\n\nbool BaseDefenseState::applyDamage(const RuleBaseFacility* rule)\n{\n\tbool shieldDown = false;\n\n\tint power = rule->getDefenseValue();\n\n\tif (rule->unifiedDamageFormula() && rule->getAmmoItem())\n\t{\n\t\t// unified damage formula\n\t\tint damage = rule->getAmmoItem()->getDamageType()->getRandomDamage(power);\n\n\t\tif (_ufo->getShield() != 0)\n\t\t{\n\t\t\tint shieldDamage = damage * rule->getShieldDamageModifier() / 100;\n\t\t\tif (rule->getShieldDamageModifier() == 0)\n\t\t\t{\n\t\t\t\tdamage = 0;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// scale down by bleed-through factor and scale up by shield-effectiveness factor\n\t\t\t\tdamage = std::max(0, shieldDamage - _ufo->getShield()) * _ufo->getCraftStats().shieldBleedThrough / rule->getShieldDamageModifier();\n\t\t\t}\n\t\t\t_ufo->setShield(_ufo->getShield() - shieldDamage);\n\n\t\t\tif (_ufo->getShield() == 0)\n\t\t\t{\n\t\t\t\tshieldDown = true;\n\t\t\t}\n\t\t}\n\n\t\tdamage = std::max(0, damage - _ufo->getCraftStats().armor);\n\t\t_ufo->setDamage(_ufo->getDamage() + damage, _game->getMod());\n\t}\n\telse\n\t{\n\t\t// vanilla dmg formula: 50-150%\n\t\tint dmg = power / 2 + RNG::generate(0, power);\n\n\t\tif (_ufo->getShield() > 0)\n\t\t{\n\t\t\tint shieldDmg = dmg * rule->getShieldDamageModifier() / 100;\n\t\t\tif (rule->getShieldDamageModifier() == 0)\n\t\t\t{\n\t\t\t\tdmg = 0;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// scale down by bleed-through factor NOT performed for backwards-compatibility\n\t\t\t\t// only scale up by shield-effectiveness factor\n\t\t\t\tdmg = std::max(0, shieldDmg - _ufo->getShield()) * 100 / rule->getShieldDamageModifier();\n\t\t\t}\n\t\t\t_ufo->setShield(_ufo->getShield() - shieldDmg);\n\n\t\t\tif (_ufo->getShield() == 0)\n\t\t\t{\n\t\t\t\tshieldDown = true;\n\t\t\t}\n\t\t}\n\t\t_ufo->setDamage(_ufo->getDamage() + dmg, _game->getMod());\n\t}\n\n\treturn shieldDown;\n}\n\nvoid BaseDefenseState::nextStep()\n{\n\tif (_thinkcycles == -1)\n\t\treturn;\n\n\t++_thinkcycles;\n\n\tif (_thinkcycles == 1)\n\t{\n\t\t_txtInit->setVisible(true);\n\t\treturn;\n\t}\n\n\tif (_thinkcycles > 1)\n\t{\n\t\tswitch (_action)\n\t\t{\n\t\tcase BDA_DESTROY:\n\t\t\tif (!_explosionCount)\n\t\t\t{\n\t\t\t\t_lstDefenses->addRow(2, tr(\"STR_UFO_DESTROYED\").c_str(),\" \",\" \");\n\t\t\t\t++_row;\n\t\t\t\tif (_row > 14)\n\t\t\t\t{\n\t\t\t\t\t_lstDefenses->scrollDown(true);\n\t\t\t\t}\n\t\t\t}\n\t\t\t_game->getMod()->getSound(\"GEO.CAT\", Mod::UFO_EXPLODE)->play();\n\t\t\tif (++_explosionCount == 3)\n\t\t\t{\n\t\t\t\t_action = BDA_END;\n\t\t\t}\n\t\t\treturn;\n\t\tcase BDA_END:\n\t\t\t_btnOk->setVisible(true);\n\t\t\t_thinkcycles = -1;\n\t\t\treturn;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t\tif (_attacks == _defenses && _passes == _gravShields)\n\t\t{\n\t\t\t_action = BDA_END;\n\t\t\treturn;\n\t\t}\n\t\telse if (_attacks == _defenses && _passes < _gravShields)\n\t\t{\n\t\t\t_lstDefenses->addRow(3, tr(\"STR_GRAV_SHIELD_REPELS_UFO\").c_str(),\" \",\" \");\n\t\t\tif (_row > 14)\n\t\t\t{\n\t\t\t\t_lstDefenses->scrollDown(true);\n\t\t\t}\n\t\t\t++_row;\n\t\t\t++_passes;\n\t\t\t_attacks = 0;\n\t\t\treturn;\n\t\t}\n\n\n\n\t\tBaseFacility* def = _base->getDefenses()->at(_attacks);\n\t\tconst RuleItem* ammo = (def)->getRules()->getAmmoItem();\n\t\tint ammoNeeded = (def)->getRules()->getAmmoNeeded();\n\t\tbool hasOwnAmmo = def->getRules()->getAmmoMax() > 0;\n\t\tbool spendAmmo = false;\n\n\t\tint chanceToHit = def->getRules()->getHitRatio(); // vanilla xcom\n\t\tchanceToHit -= _ufo->getCraftStats().avoidBonus2;\n\n\t\tswitch (_action)\n\t\t{\n\t\tcase  BDA_NONE:\n\t\t\t_lstDefenses->addRow(3, tr((def)->getRules()->getType()).c_str(),\" \",\" \");\n\t\t\t++_row;\n\t\t\t_action = BDA_FIRE;\n\t\t\tif (_row > 14)\n\t\t\t{\n\t\t\t\t_lstDefenses->scrollDown(true);\n\t\t\t}\n\t\t\treturn;\n\t\tcase BDA_FIRE:\n\t\t\tif (hasOwnAmmo && def->getAmmo() < ammoNeeded)\n\t\t\t{\n\t\t\t\t_lstDefenses->setCellText(_row, 1, tr(\"STR_NO_AMMO\"));\n\t\t\t}\n\t\t\telse if (!hasOwnAmmo && ammo && _base->getStorageItems()->getItem(ammo) < ammoNeeded)\n\t\t\t{\n\t\t\t\t_lstDefenses->setCellText(_row, 1, tr(\"STR_NO_AMMO\"));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_lstDefenses->setCellText(_row, 1, tr(\"STR_FIRING\"));\n\t\t\t\t_game->getMod()->getSound(\"GEO.CAT\", (def)->getRules()->getFireSound())->play();\n\t\t\t}\n\t\t\t_timer->setInterval(333);\n\t\t\t_action = BDA_RESOLVE;\n\t\t\treturn;\n\t\tcase BDA_RESOLVE:\n\t\t\tif (hasOwnAmmo && def->getAmmo() < ammoNeeded)\n\t\t\t{\n\t\t\t\t//_lstDefenses->setCellText(_row, 2, tr(\"STR_NO_AMMO\"));\n\t\t\t}\n\t\t\telse if (!hasOwnAmmo && ammo && _base->getStorageItems()->getItem(ammo) < ammoNeeded)\n\t\t\t{\n\t\t\t\t//_lstDefenses->setCellText(_row, 2, tr(\"STR_NO_AMMO\"));\n\t\t\t}\n\t\t\telse if (!RNG::percent(chanceToHit))\n\t\t\t{\n\t\t\t\tspendAmmo = true;\n\t\t\t\t_lstDefenses->setCellText(_row, 2, tr(\"STR_MISSED\"));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tspendAmmo = true;\n\t\t\t\t_lstDefenses->setCellText(_row, 2, tr(\"STR_HIT\"));\n\t\t\t\t_game->getMod()->getSound(\"GEO.CAT\", (def)->getRules()->getHitSound())->play();\n\n\t\t\t\tbool shieldDown = applyDamage(def->getRules());\n\n\t\t\t\tif (shieldDown)\n\t\t\t\t{\n\t\t\t\t\t_lstDefenses->addRow(3, tr(\"STR_UFO_SHIELD_DOWN\").c_str(), \" \", \" \");\n\t\t\t\t\t++_row;\n\t\t\t\t\tif (_row > 14)\n\t\t\t\t\t{\n\t\t\t\t\t\t_lstDefenses->scrollDown(true);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (spendAmmo && ammoNeeded > 0)\n\t\t\t{\n\t\t\t\tif (hasOwnAmmo)\n\t\t\t\t{\n\t\t\t\t\tdef->setAmmo(def->getAmmo() - ammoNeeded);\n\t\t\t\t\tdef->resetAmmoMissingReported();\n\t\t\t\t}\n\t\t\t\telse if (!hasOwnAmmo && ammo)\n\t\t\t\t{\n\t\t\t\t\t_base->getStorageItems()->removeItem(ammo, ammoNeeded);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (_ufo->getStatus() == Ufo::DESTROYED)\n\t\t\t\t_action = BDA_DESTROY;\n\t\t\telse\n\t\t\t\t_action = BDA_NONE;\n\t\t\t++_attacks;\n\t\t\t_timer->setInterval(250);\n\t\t\treturn;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n/**\n* Starts base defense\n* @param action Pointer to an action.\n*/\nvoid BaseDefenseState::btnStartClick(Action *)\n{\n\t_preview->setVisible(false);\n\t_lstDefenses->clearList();\n\n\t_btnStart->setVisible(false);\n\t_btnAbort->setVisible(false);\n\t_timer->start();\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid BaseDefenseState::btnOkClick(Action *)\n{\n\t_timer->stop();\n\t_game->popState();\n\tif (_ufo->getStatus() != Ufo::DESTROYED)\n\t{\n\t\t_state->handleBaseDefense(_base, _ufo);\n\t}\n\telse\n\t{\n\t\t_base->cleanupDefenses(true);\n\n\t\t// instant retaliation mission only spawns one UFO and then ends\n\t\tif (_ufo->getMission()->getRules().getObjective() == OBJECTIVE_INSTANT_RETALIATION)\n\t\t{\n\t\t\t_ufo->getMission()->setInterrupted(true);\n\t\t}\n\n\t\t// aliens are not stupid and should stop trying eventually\n\t\tif (_ufo->getMission()->getRules().getObjective() == OBJECTIVE_RETALIATION && RNG::percent(_game->getMod()->getChanceToStopRetaliation()))\n\t\t{\n\t\t\t// unmark base...\n\t\t\t_base->setRetaliationTarget(false);\n\n\t\t\tAlienMission* am = _base->getRetaliationMission();\n\t\t\tif (!am)\n\t\t\t{\n\t\t\t\t// backwards-compatibility\n\t\t\t\tRuleRegion* regionRule = _game->getSavedGame()->getRegions()->front()->getRules(); // wrong, but that's how it is in OXC\n\t\t\t\tfor (const auto* region : *_game->getSavedGame()->getRegions())\n\t\t\t\t{\n\t\t\t\t\tif (region->getRules()->insideRegion(_base->getLongitude(), _base->getLatitude()))\n\t\t\t\t\t{\n\t\t\t\t\t\tregionRule = region->getRules();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tam = _game->getSavedGame()->findAlienMission(regionRule->getType(), OBJECTIVE_RETALIATION);\n\t\t\t}\n\n\t\t\tif (am && am->getRules().isMultiUfoRetaliation())\n\t\t\t{\n\t\t\t\t// Remember that more UFOs may be coming\n\t\t\t\tam->setMultiUfoRetaliationInProgress(true);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// Delete the mission and any live UFOs\n\t\t\t\t_game->getSavedGame()->deleteRetaliationMission(am, _base);\n\t\t\t}\n\t\t}\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/BaseDefenseState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass Base;\nclass Ufo;\nclass TextList;\nclass GeoscapeState;\nclass Timer;\nclass RuleBaseFacility;\n\nenum BaseDefenseActionType { BDA_NONE, BDA_FIRE, BDA_RESOLVE, BDA_DESTROY, BDA_END };\n\n/**\n * Base Defense Screen for when ufos try to attack.\n */\nclass BaseDefenseState : public State\n{\nprivate:\n\tTextButton *_btnOk;\n\tTextButton *_btnStart, *_btnAbort;\n\tWindow *_window;\n\tInteractiveSurface *_preview;\n\tText *_txtTitle, *_txtInit;\n\tTextList *_lstDefenses;\n\tBase *_base;\n\tUfo *_ufo;\n\tint _thinkcycles, _row, _passes, _gravShields, _defenses, _attacks, _explosionCount;\n\tBaseDefenseActionType _action;\n\tTimer *_timer;\n\tGeoscapeState *_state;\n\tbool applyDamage(const RuleBaseFacility* rule);\npublic:\n\t/// Creates the Base Defense state.\n\tBaseDefenseState(Base *base, Ufo *ufo, GeoscapeState *state, bool instaHyper);\n\t/// Cleans up the Base Defense state.\n\t~BaseDefenseState();\n\t/// Handle the Timer.\n\tvoid think() override;\n\t/// do the next step.\n\tvoid nextStep();\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the [Start] button.\n\tvoid btnStartClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/BaseDestroyedState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"BaseDestroyedState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/Region.h\"\n#include \"../Savegame/AlienMission.h\"\n#include \"../Savegame/Ufo.h\"\n#include \"../Mod/RuleBaseFacility.h\"\n#include \"../Mod/RuleRegion.h\"\n#include \"../Engine/Options.h\"\n#include \"../Basescape/SellState.h\"\n#include \"../Menu/ErrorMessageState.h\"\n#include \"../Mod/RuleInterface.h\"\n\nnamespace OpenXcom\n{\n\nBaseDestroyedState::BaseDestroyedState(Base *base, const Ufo* ufo, bool missiles, bool partialDestruction) :\n\t_base(base), _missiles(missiles), _partialDestruction(partialDestruction)\n{\n\t_screen = false;\n\n\tint soundId = ufo->getRules()->getHitSound();\n\tif (soundId != Mod::NO_SOUND)\n\t{\n\t\t_customSound = _game->getMod()->getSound(\"GEO.CAT\", soundId);\n\t}\n\n\t// Create objects\n\t_window = new Window(this, 256, 160, 32, 20);\n\t_btnOk = new TextButton(100, 20, 110, 142);\n\t_txtMessage = new Text(224, 48, 48, _partialDestruction ? 42 : 76);\n\t_lstDestroyedFacilities = new TextList(208, 40, 48, 92);\n\n\t// Set palette\n\tsetInterface(\"baseDestroyed\");\n\n\tadd(_window, \"window\", \"baseDestroyed\");\n\tadd(_btnOk, \"button\", \"baseDestroyed\");\n\tadd(_txtMessage, \"text\", \"baseDestroyed\");\n\tadd(_lstDestroyedFacilities, \"text\", \"baseDestroyed\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tif (ufo->getRules()->getHitImage().empty())\n\t{\n\t\tsetWindowBackground(_window, \"baseDestroyed\");\n\t}\n\telse\n\t{\n\t\tsetWindowBackgroundImage(_window, ufo->getRules()->getHitImage());\n\t}\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&BaseDestroyedState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&BaseDestroyedState::btnOkClick, Options::keyOk);\n\t_btnOk->onKeyboardPress((ActionHandler)&BaseDestroyedState::btnOkClick, Options::keyCancel);\n\n\t_txtMessage->setAlign(ALIGN_CENTER);\n\t_txtMessage->setBig();\n\t_txtMessage->setWordWrap(true);\n\n\t_txtMessage->setText(tr(\"STR_THE_ALIENS_HAVE_DESTROYED_THE_UNDEFENDED_BASE\").arg(_base->getName()));\n\tif (_missiles)\n\t{\n\t\tif (_partialDestruction)\n\t\t{\n\t\t\t_txtMessage->setText(tr(\"STR_ALIEN_MISSILES_HAVE_DAMAGED_OUR_BASE\").arg(_base->getName()));\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_txtMessage->setText(tr(\"STR_ALIEN_MISSILES_HAVE_DESTROYED_OUR_BASE\").arg(_base->getName()));\n\t\t}\n\t}\n\n\t_lstDestroyedFacilities->setColumns(2, 162, 14);\n\t_lstDestroyedFacilities->setBackground(_window);\n\t_lstDestroyedFacilities->setSelectable(true);\n\t_lstDestroyedFacilities->setMargin(8);\n\t_lstDestroyedFacilities->setVisible(false);\n\n\tif (_missiles && _partialDestruction)\n\t{\n\t\tfor (const auto& each : *_base->getDestroyedFacilitiesCache())\n\t\t{\n\t\t\tstd::ostringstream ss;\n\t\t\tss << each.second;\n\t\t\t_lstDestroyedFacilities->addRow(2, tr(each.first->getType()).c_str(), ss.str().c_str());\n\t\t}\n\t\t_lstDestroyedFacilities->setVisible(true);\n\t}\n\n\tif (_partialDestruction)\n\t{\n\t\t// don't remove the alien mission yet, there might be more attacks coming\n\t\treturn;\n\t}\n\n\tAlienMission* am = _base->getRetaliationMission();\n\tif (!am)\n\t{\n\t\t// backwards-compatibility\n\t\tRuleRegion* regionRule = _game->getSavedGame()->getRegions()->front()->getRules(); // wrong, but that's how it is in OXC\n\t\tfor (const auto* region : *_game->getSavedGame()->getRegions())\n\t\t{\n\t\t\tif (region->getRules()->insideRegion(_base->getLongitude(), _base->getLatitude()))\n\t\t\t{\n\t\t\t\tregionRule = region->getRules();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tam = _game->getSavedGame()->findAlienMission(regionRule->getType(), OBJECTIVE_RETALIATION);\n\t}\n\t_game->getSavedGame()->deleteRetaliationMission(am, _base);\n}\n\n/**\n *\n */\nBaseDestroyedState::~BaseDestroyedState()\n{\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid BaseDestroyedState::btnOkClick(Action *)\n{\n\t_game->popState();\n\n\tif (_partialDestruction)\n\t{\n\t\tif (_game->getSavedGame()->getMonthsPassed() > -1 && Options::storageLimitsEnforced && _base != 0 && _base->storesOverfull())\n\t\t{\n\t\t\t_game->pushState(new SellState(_base, 0, OPT_BATTLESCAPE));\n\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_STORAGE_EXCEEDED\").arg(_base->getName()), _palette, _game->getMod()->getInterface(\"debriefing\")->getElement(\"errorMessage\")->color, \"BACK01.SCR\", _game->getMod()->getInterface(\"debriefing\")->getElement(\"errorPalette\")->color));\n\t\t}\n\n\t\t// the base was damaged, but survived\n\t\treturn;\n\t}\n\n\tfor (auto xbaseIt = _game->getSavedGame()->getBases()->begin(); xbaseIt != _game->getSavedGame()->getBases()->end(); ++xbaseIt)\n\t{\n\t\tBase* xbase = (*xbaseIt);\n\t\tif (xbase == _base)\n\t\t{\n\t\t\t_game->getSavedGame()->stopHuntingXcomCrafts(xbase); // destroyed together with the base\n\t\t\tdelete xbase;\n\t\t\t_game->getSavedGame()->getBases()->erase(xbaseIt);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/BaseDestroyedState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http:///www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass Base;\nclass Window;\nclass Text;\nclass TextButton;\nclass TextList;\nclass Ufo;\n\n/**\n * Screen that allows the player\n * to pick a target for a craft on the globe.\n */\nclass BaseDestroyedState : public State\n{\nprivate:\n\tWindow *_window;\n\tText *_txtMessage;\n\tTextButton *_btnOk;\n\tTextList *_lstDestroyedFacilities;\n\tBase *_base;\n\tbool _missiles, _partialDestruction;\npublic:\n\t/// Creates the Select Destination state.\n\tBaseDestroyedState(Base *base, const Ufo* ufo, bool missiles, bool partialDestruction);\n\t/// Cleans up the Select Destination state.\n\t~BaseDestroyedState();\n\t/// Handler for clicking the Cydonia mission button.\n\tvoid btnOkClick(Action *action);\n\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/BaseNameState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"BaseNameState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Action.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextEdit.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Basescape/PlaceLiftState.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/RNG.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in a Base Name window.\n * @param game Pointer to the core game.\n * @param base Pointer to the base to name.\n * @param globe Pointer to the Geoscape globe.\n * @param first Is this the first base in the game?\n * @param fixedLocation Is this the first base in the game on a fixed location?\n */\nBaseNameState::BaseNameState(Base *base, Globe *globe, bool first, bool fixedLocation) : _base(base), _globe(globe), _first(first), _fixedLocation(fixedLocation)\n{\n\t_globe->onMouseOver(0);\n\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 192, 80, 32, 60, POPUP_BOTH);\n\t_btnOk = new TextButton(162, 12, 47, 118);\n\t_txtTitle = new Text(182, 17, 37, 70);\n\t_edtName = new TextEdit(this, 127, 16, 59, 94);\n\n\t// Set palette\n\tsetInterface(\"baseNaming\");\n\n\tadd(_window, \"window\", \"baseNaming\");\n\tadd(_btnOk, \"button\", \"baseNaming\");\n\tadd(_txtTitle, \"text\", \"baseNaming\");\n\tadd(_edtName, \"text\", \"baseNaming\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"baseNaming\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&BaseNameState::btnOkClick);\n\t//_btnOk->onKeyboardPress((ActionHandler)&BaseNameState::btnOkClick, Options::keyOk);\n\t_btnOk->onKeyboardPress((ActionHandler)&BaseNameState::btnOkClick, Options::keyCancel);\n\n\t//something must be in the name before it is acceptable\n\t_btnOk->setVisible(false);\n\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setBig();\n\t_txtTitle->setText(tr(\"STR_BASE_NAME\"));\n\n\tif (!_game->getMod()->getBaseNamesFirst().empty())\n\t{\n\t\tstd::ostringstream ss;\n\t\tint pickFirst = RNG::seedless(0, _game->getMod()->getBaseNamesFirst().size() - 1);\n\t\tss << _game->getMod()->getBaseNamesFirst().at(pickFirst);\n\t\tif (!_game->getMod()->getBaseNamesMiddle().empty())\n\t\t{\n\t\t\tint pickMiddle = RNG::seedless(0, _game->getMod()->getBaseNamesMiddle().size() - 1);\n\t\t\tss << \" \" << _game->getMod()->getBaseNamesMiddle().at(pickMiddle);\n\t\t}\n\t\tif (!_game->getMod()->getBaseNamesLast().empty())\n\t\t{\n\t\t\tint pickLast = RNG::seedless(0, _game->getMod()->getBaseNamesLast().size() - 1);\n\t\t\tss << \" \" << _game->getMod()->getBaseNamesLast().at(pickLast);\n\t\t}\n\t\t_edtName->setText(ss.str());\n\t\t_btnOk->setVisible(true);\n\t}\n\n\t_edtName->setBig();\n\t_edtName->setFocus(true, false);\n\t_edtName->onChange((ActionHandler)&BaseNameState::edtNameChange);\n}\n\n/**\n *\n */\nBaseNameState::~BaseNameState()\n{\n\n}\n\n/**\n * Updates the base name and disables the OK button\n * if no name is entered.\n * @param action Pointer to an action.\n */\nvoid BaseNameState::edtNameChange(Action *action)\n{\n\tif (action->getDetails()->key.keysym.sym == SDLK_RETURN ||\n\t\taction->getDetails()->key.keysym.sym == SDLK_KP_ENTER)\n\t{\n\t\tif (!_edtName->getText().empty())\n\t\t{\n\t\t\tbtnOkClick(action);\n\t\t}\n\t}\n\telse\n\t{\n\t\t_btnOk->setVisible(!_edtName->getText().empty());\n\t}\n}\n\n/**\n * Returns to the previous screen\n * @param action Pointer to an action.\n */\nvoid BaseNameState::btnOkClick(Action *)\n{\n\tif (!_edtName->getText().empty())\n\t{\n\t\t_base->setName(_edtName->getText());\n\t\t_game->popState(); // pop BaseNameState\n\n\t\tif (!_fixedLocation)\n\t\t{\n\t\t\t_game->popState(); // pop ConfirmNewBaseState or BuildNewBaseState\n\t\t\tif (!_first)\n\t\t\t{\n\t\t\t\t_game->popState(); // pop BuildNewBaseState\n\t\t\t}\n\t\t}\n\n\t\tif (!_first || Options::customInitialBase)\n\t\t{\n\t\t\t_game->pushState(new PlaceLiftState(_base, _globe, _first));\n\t\t}\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/BaseNameState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include \"Globe.h\"\n\nnamespace OpenXcom\n{\n\nclass Base;\nclass Window;\nclass Text;\nclass TextEdit;\nclass TextButton;\nclass Globe;\n\n/**\n * Window used to input a name for a new base.\n * Player's first Base uses this screen\n * additional bases use ConfirmNewBaseState\n */\nclass BaseNameState : public State\n{\nprivate:\n\tBase *_base;\n\tGlobe *_globe;\n\tWindow *_window;\n\tText *_txtTitle;\n\tTextEdit *_edtName;\n\tTextButton *_btnOk;\n\tbool _first;\n\tbool _fixedLocation;\npublic:\n\t/// Creates the Base Name state.\n\tBaseNameState(Base *base, Globe *globe, bool first, bool fixedLocation);\n\t/// Cleans up the Base Name state.\n\t~BaseNameState();\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for changing text on the Name edit.\n\tvoid edtNameChange(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/BuildNewBaseState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"BuildNewBaseState.h\"\n#include \"../fmath.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Action.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/Surface.h\"\n#include \"../Engine/Timer.h\"\n#include \"../Engine/Screen.h\"\n#include \"../Interface/Window.h\"\n#include \"Globe.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/Craft.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"BaseNameState.h\"\n#include \"ConfirmNewBaseState.h\"\n#include \"../Engine/Options.h\"\n#include \"../Menu/ErrorMessageState.h\"\n#include \"../Mod/RuleInterface.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Build New Base window.\n * @param game Pointer to the core game.\n * @param base Pointer to the base to place.\n * @param globe Pointer to the Geoscape globe.\n * @param first Is this the first base in the game?\n */\nBuildNewBaseState::BuildNewBaseState(Base *base, Globe *globe, bool first) : _base(base), _globe(globe), _first(first), _oldlat(0), _oldlon(0), _mousex(0), _mousey(0)\n{\n\tint dx = _game->getScreen()->getDX();\n\tint dy = _game->getScreen()->getDY();\n\t_screen = false;\n\n\t_oldshowradar = Options::globeRadarLines;\n\tif (!_oldshowradar)\n\t\tOptions::globeRadarLines = true;\n\t// Create objects\n\t_btnRotateLeft = new InteractiveSurface(12, 10, 259 + dx * 2, 176 + dy);\n\t_btnRotateRight = new InteractiveSurface(12, 10, 283 + dx * 2, 176 + dy);\n\t_btnRotateUp = new InteractiveSurface(13, 12, 271 + dx * 2, 162 + dy);\n\t_btnRotateDown = new InteractiveSurface(13, 12, 271 + dx * 2, 187 + dy);\n\t_btnZoomIn = new InteractiveSurface(23, 23, 295 + dx * 2, 156 + dy);\n\t_btnZoomOut = new InteractiveSurface(13, 17, 300 + dx * 2, 182 + dy);\n\n\t_window = new Window(this, 256, 28, 0, 0);\n\t_window->setX(dx);\n\t_window->setDY(0);\n\t_btnCancel = new TextButton(54, 12, 186 + dx, 8);\n\t_txtTitle = new Text(180, 16, 8 + dx, 6);\n\n\t_hoverTimer = new Timer(50);\n\t_hoverTimer->onTimer((StateHandler)&BuildNewBaseState::hoverRedraw);\n\t_hoverTimer->start();\n\n\t// Set palette\n\tsetInterface(\"geoscape\");\n\n\tadd(_btnRotateLeft);\n\tadd(_btnRotateRight);\n\tadd(_btnRotateUp);\n\tadd(_btnRotateDown);\n\tadd(_btnZoomIn);\n\tadd(_btnZoomOut);\n\n\tadd(_window, \"genericWindow\", \"geoscape\");\n\tadd(_btnCancel, \"genericButton2\", \"geoscape\");\n\tadd(_txtTitle, \"genericText\", \"geoscape\");\n\n\t// Set up objects\n\t_globe->onMouseClick((ActionHandler)&BuildNewBaseState::globeClick);\n\n\t_btnRotateLeft->onMousePress((ActionHandler)&BuildNewBaseState::btnRotateLeftPress);\n\t_btnRotateLeft->onMouseRelease((ActionHandler)&BuildNewBaseState::btnRotateLeftRelease);\n\t_btnRotateLeft->onKeyboardPress((ActionHandler)&BuildNewBaseState::btnRotateLeftPress, Options::keyGeoLeft);\n\t_btnRotateLeft->onKeyboardRelease((ActionHandler)&BuildNewBaseState::btnRotateLeftRelease, Options::keyGeoLeft);\n\n\t_btnRotateRight->onMousePress((ActionHandler)&BuildNewBaseState::btnRotateRightPress);\n\t_btnRotateRight->onMouseRelease((ActionHandler)&BuildNewBaseState::btnRotateRightRelease);\n\t_btnRotateRight->onKeyboardPress((ActionHandler)&BuildNewBaseState::btnRotateRightPress, Options::keyGeoRight);\n\t_btnRotateRight->onKeyboardRelease((ActionHandler)&BuildNewBaseState::btnRotateRightRelease, Options::keyGeoRight);\n\n\t_btnRotateUp->onMousePress((ActionHandler)&BuildNewBaseState::btnRotateUpPress);\n\t_btnRotateUp->onMouseRelease((ActionHandler)&BuildNewBaseState::btnRotateUpRelease);\n\t_btnRotateUp->onKeyboardPress((ActionHandler)&BuildNewBaseState::btnRotateUpPress, Options::keyGeoUp);\n\t_btnRotateUp->onKeyboardRelease((ActionHandler)&BuildNewBaseState::btnRotateUpRelease, Options::keyGeoUp);\n\n\t_btnRotateDown->onMousePress((ActionHandler)&BuildNewBaseState::btnRotateDownPress);\n\t_btnRotateDown->onMouseRelease((ActionHandler)&BuildNewBaseState::btnRotateDownRelease);\n\t_btnRotateDown->onKeyboardPress((ActionHandler)&BuildNewBaseState::btnRotateDownPress, Options::keyGeoDown);\n\t_btnRotateDown->onKeyboardRelease((ActionHandler)&BuildNewBaseState::btnRotateDownRelease, Options::keyGeoDown);\n\n\t_btnZoomIn->onMouseClick((ActionHandler)&BuildNewBaseState::btnZoomInLeftClick, SDL_BUTTON_LEFT);\n\t_btnZoomIn->onMouseClick((ActionHandler)&BuildNewBaseState::btnZoomInRightClick, SDL_BUTTON_RIGHT);\n\t_btnZoomIn->onKeyboardPress((ActionHandler)&BuildNewBaseState::btnZoomInLeftClick, Options::keyGeoZoomIn);\n\n\t_btnZoomOut->onMouseClick((ActionHandler)&BuildNewBaseState::btnZoomOutLeftClick, SDL_BUTTON_LEFT);\n\t_btnZoomOut->onMouseClick((ActionHandler)&BuildNewBaseState::btnZoomOutRightClick, SDL_BUTTON_RIGHT);\n\t_btnZoomOut->onKeyboardPress((ActionHandler)&BuildNewBaseState::btnZoomOutLeftClick, Options::keyGeoZoomOut);\n\n\t// dirty hacks to get the rotate buttons to work in \"classic\" style\n\t_btnRotateLeft->setListButton();\n\t_btnRotateRight->setListButton();\n\t_btnRotateUp->setListButton();\n\t_btnRotateDown->setListButton();\n\n\tsetWindowBackground(_window, \"geoscape\");\n\n\t_btnCancel->setText(tr(\"STR_CANCEL_UC\"));\n\t_btnCancel->onMouseClick((ActionHandler)&BuildNewBaseState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&BuildNewBaseState::btnCancelClick, Options::keyCancel);\n\n\t_txtTitle->setText(tr(\"STR_SELECT_SITE_FOR_NEW_BASE\"));\n\t_txtTitle->setVerticalAlign(ALIGN_MIDDLE);\n\t_txtTitle->setWordWrap(true);\n\n\tif (_first)\n\t{\n\t\t_btnCancel->setVisible(false);\n\t}\n}\n\n/**\n *\n */\nBuildNewBaseState::~BuildNewBaseState()\n{\n\tif (Options::globeRadarLines != _oldshowradar)\n\t{\n\t\tOptions::globeRadarLines = false;\n\t}\n\tdelete _hoverTimer;\n}\n\n/**\n * Stops the globe and adds radar hover effect.\n */\nvoid BuildNewBaseState::init()\n{\n\tState::init();\n\t_globe->onMouseOver((ActionHandler)&BuildNewBaseState::globeHover);\n\t_globe->rotateStop();\n\t_globe->setNewBaseHover(true);\n}\n\n/**\n * Runs the globe rotation timer.\n */\nvoid BuildNewBaseState::think()\n{\n\tState::think();\n\t_globe->think();\n\t_hoverTimer->think(this, 0);\n}\n\n/**\n * Handles the globe.\n * @param action Pointer to an action.\n */\nvoid BuildNewBaseState::handle(Action *action)\n{\n\tState::handle(action);\n\t_globe->handle(action, this);\n}\n\n/**\n * Processes mouse-hover event for base placement,\n * @param action Pointer to an action.\n */\nvoid BuildNewBaseState::globeHover(Action *action)\n{\n\t_mousex = (int)floor(action->getAbsoluteXMouse());\n\t_mousey = (int)floor(action->getAbsoluteYMouse());\n\tif (!_hoverTimer->isRunning()) _hoverTimer->start();\n}\n\nvoid BuildNewBaseState::hoverRedraw(void)\n{\n\tdouble lon, lat;\n\t_globe->cartToPolar(_mousex, _mousey, &lon, &lat);\n\tif (lon == lon && lat == lat)\n\t{\n\t\t_globe->setNewBaseHoverPos(lon,lat);\n\t\t_globe->setNewBaseHover(true);\n\t}\n\tif (Options::globeRadarLines && !(AreSame(_oldlat, lat) && AreSame(_oldlon, lon)) )\n\t{\n\t\t_oldlat=lat;\n\t\t_oldlon=lon;\n\t\t_globe->invalidate();\n\t}\n}\n\n/**\n * Processes any left-clicks for base placement,\n * or right-clicks to scroll the globe.\n * @param action Pointer to an action.\n */\nvoid BuildNewBaseState::globeClick(Action *action)\n{\n\tdouble lon, lat;\n\tint mouseX = (int)floor(action->getAbsoluteXMouse()), mouseY = (int)floor(action->getAbsoluteYMouse());\n\t_globe->cartToPolar(mouseX, mouseY, &lon, &lat);\n\n\t// Ignore window clicks\n\tif (mouseY < 28)\n\t{\n\t\treturn;\n\t}\n\n\t// Clicking on a polygon for a base location\n\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT)\n\t{\n\t\tif (_globe->insideLand(lon, lat))\n\t\t{\n\t\t\tbool fakeUnderwaterBasesUnlocked = true;\n\t\t\tif (!_game->getMod()->getFakeUnderwaterBaseUnlockResearch().empty())\n\t\t\t{\n\t\t\t\tfakeUnderwaterBasesUnlocked = _game->getSavedGame()->isResearched(_game->getMod()->getFakeUnderwaterBaseUnlockResearch(), true);\n\t\t\t}\n\t\t\tbool fakeUnderwaterTexture = _globe->insideFakeUnderwaterTexture(lon, lat);\n\t\t\tif ((_first || !fakeUnderwaterBasesUnlocked) && fakeUnderwaterTexture)\n\t\t\t{\n\t\t\t\t// first (starting) base can't be fake underwater base\n\t\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_XCOM_BASE_CANNOT_BE_BUILT\"), _palette, _game->getMod()->getInterface(\"geoscape\")->getElement(\"genericWindow\")->color, \"BACK01.SCR\", _game->getMod()->getInterface(\"geoscape\")->getElement(\"palette\")->color));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_base->setFakeUnderwater(fakeUnderwaterTexture);\n\t\t\t\t_base->setLongitude(lon);\n\t\t\t\t_base->setLatitude(lat);\n\t\t\t\t_base->calculateServices(_game->getSavedGame());\n\t\t\t\tfor (auto* craft : *_base->getCrafts())\n\t\t\t\t{\n\t\t\t\t\tcraft->setLongitude(lon);\n\t\t\t\t\tcraft->setLatitude(lat);\n\t\t\t\t}\n\t\t\t\tif (_first)\n\t\t\t\t{\n\t\t\t\t\t_game->pushState(new BaseNameState(_base, _globe, _first, false));\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t_game->pushState(new ConfirmNewBaseState(_base, _globe));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_XCOM_BASE_CANNOT_BE_BUILT\"), _palette, _game->getMod()->getInterface(\"geoscape\")->getElement(\"genericWindow\")->color, \"BACK01.SCR\", _game->getMod()->getInterface(\"geoscape\")->getElement(\"palette\")->color));\n\t\t}\n\t}\n}\n\n/**\n * Starts rotating the globe to the left.\n * @param action Pointer to an action.\n */\nvoid BuildNewBaseState::btnRotateLeftPress(Action *)\n{\n\t_globe->rotateLeft();\n}\n\n/**\n * Stops rotating the globe to the left.\n * @param action Pointer to an action.\n */\nvoid BuildNewBaseState::btnRotateLeftRelease(Action *)\n{\n\t_globe->rotateStopLon();\n}\n\n/**\n * Starts rotating the globe to the right.\n * @param action Pointer to an action.\n */\nvoid BuildNewBaseState::btnRotateRightPress(Action *)\n{\n\t_globe->rotateRight();\n}\n\n/**\n * Stops rotating the globe to the right.\n * @param action Pointer to an action.\n */\nvoid BuildNewBaseState::btnRotateRightRelease(Action *)\n{\n\t_globe->rotateStopLon();\n}\n\n/**\n * Starts rotating the globe upwards.\n * @param action Pointer to an action.\n */\nvoid BuildNewBaseState::btnRotateUpPress(Action *)\n{\n\t_globe->rotateUp();\n}\n\n/**\n * Stops rotating the globe upwards.\n * @param action Pointer to an action.\n */\nvoid BuildNewBaseState::btnRotateUpRelease(Action *)\n{\n\t_globe->rotateStopLat();\n}\n\n/**\n * Starts rotating the globe downwards.\n * @param action Pointer to an action.\n */\nvoid BuildNewBaseState::btnRotateDownPress(Action *)\n{\n\t_globe->rotateDown();\n}\n\n/**\n * Stops rotating the globe downwards.\n * @param action Pointer to an action.\n */\nvoid BuildNewBaseState::btnRotateDownRelease(Action *)\n{\n\t_globe->rotateStopLat();\n}\n\n/**\n * Zooms into the globe.\n * @param action Pointer to an action.\n */\nvoid BuildNewBaseState::btnZoomInLeftClick(Action *)\n{\n\t_globe->zoomIn();\n}\n\n/**\n * Zooms the globe maximum.\n * @param action Pointer to an action.\n */\nvoid BuildNewBaseState::btnZoomInRightClick(Action *)\n{\n\t_globe->zoomMax();\n}\n\n/**\n * Zooms out of the globe.\n * @param action Pointer to an action.\n */\nvoid BuildNewBaseState::btnZoomOutLeftClick(Action *)\n{\n\t_globe->zoomOut();\n}\n\n/**\n * Zooms the globe minimum.\n * @param action Pointer to an action.\n */\nvoid BuildNewBaseState::btnZoomOutRightClick(Action *)\n{\n\t_globe->zoomMin();\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid BuildNewBaseState::btnCancelClick(Action *)\n{\n\tdelete _base;\n\t_game->popState();\n}\n\n/**\n * Updates the scale.\n * @param dX delta of X;\n * @param dY delta of Y;\n */\nvoid BuildNewBaseState::resize(int &dX, int &dY)\n{\n\tfor (auto* surface : _surfaces)\n\t{\n\t\tsurface->setX(surface->getX() + dX / 2);\n\t\tif (surface != _window && surface != _btnCancel && surface != _txtTitle)\n\t\t{\n\t\t\tsurface->setY(surface->getY() + dY / 2);\n\t\t}\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/BuildNewBaseState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http:///www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass Base;\nclass Globe;\nclass InteractiveSurface;\nclass Timer;\nclass Window;\nclass Text;\nclass TextButton;\n\n/**\n * Screen that allows the player\n * to place a new base on the globe.\n */\nclass BuildNewBaseState : public State\n{\nprivate:\n\tBase *_base;\n\tGlobe *_globe;\n\tInteractiveSurface *_btnRotateLeft, *_btnRotateRight, *_btnRotateUp, *_btnRotateDown, *_btnZoomIn, *_btnZoomOut;\n\tWindow *_window;\n\tText *_txtTitle;\n\tTextButton *_btnCancel;\n\tTimer *_hoverTimer;\n\tbool _first;\n\tbool _oldshowradar;\n\tdouble _oldlat,_oldlon;\n\tint _mousex, _mousey;\npublic:\n\t/// Creates the Build New Base state.\n\tBuildNewBaseState(Base *base, Globe *globe, bool first);\n\t/// Cleans up the Build New Base state.\n\t~BuildNewBaseState();\n\t/// Resets globe.\n\tvoid init() override;\n\t/// Runs the timer.\n\tvoid think() override;\n\t/// Handles actions.\n\tvoid handle(Action *action) override;\n\t/// Handler for clicking the globe.\n\tvoid globeClick(Action *action);\n\t/// Handler for mouse hovering the globe.\n\tvoid globeHover(Action *action);\n\t/// Handler for redrawing hover (delayed)\n\tvoid hoverRedraw(void);\n\t/// Handler for pressing the Rotate Left arrow.\n\tvoid btnRotateLeftPress(Action *action);\n\t/// Handler for releasing the Rotate Left arrow.\n\tvoid btnRotateLeftRelease(Action *action);\n\t/// Handler for pressing the Rotate Right arrow.\n\tvoid btnRotateRightPress(Action *action);\n\t/// Handler for releasing the Rotate Right arrow.\n\tvoid btnRotateRightRelease(Action *action);\n\t/// Handler for pressing the Rotate Up arrow.\n\tvoid btnRotateUpPress(Action *action);\n\t/// Handler for releasing the Rotate Up arrow.\n\tvoid btnRotateUpRelease(Action *action);\n\t/// Handler for pressing the Rotate Down arrow.\n\tvoid btnRotateDownPress(Action *action);\n\t/// Handler for releasing the Rotate Down arrow.\n\tvoid btnRotateDownRelease(Action *action);\n\t/// Handler for left-clicking the Zoom In icon.\n\tvoid btnZoomInLeftClick(Action *action);\n\t/// Handler for right-clicking the Zoom In icon.\n\tvoid btnZoomInRightClick(Action *action);\n\t/// Handler for left-clicking the Zoom Out icon.\n\tvoid btnZoomOutLeftClick(Action *action);\n\t/// Handler for right-clicking the Zoom Out icon.\n\tvoid btnZoomOutRightClick(Action *action);\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action *action);\n\t/// Let the state know the window has been resized.\n\tvoid resize(int &dX, int &dY) override;\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/ConfirmCydoniaState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ConfirmCydoniaState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Battlescape/BattlescapeGenerator.h\"\n#include \"../Battlescape/BriefingState.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Mod/AlienDeployment.h\"\n#include \"../Engine/Options.h\"\n\nnamespace OpenXcom\n{\n\nConfirmCydoniaState::ConfirmCydoniaState(Craft *craft) : _craft(craft)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 256, 160, 32, 20);\n\t_btnYes = new TextButton(80, 20, 70, 142);\n\t_btnNo = new TextButton(80, 20, 170, 142);\n\t_txtMessage = new Text(224, 48, 48, 76);\n\n\t// Set palette\n\tsetInterface(\"confirmCydonia\");\n\n\tadd(_window, \"window\", \"confirmCydonia\");\n\tadd(_btnYes, \"button\", \"confirmCydonia\");\n\tadd(_btnNo, \"button\", \"confirmCydonia\");\n\tadd(_txtMessage, \"text\", \"confirmCydonia\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"confirmCydonia\");\n\n\t_btnYes->setText(tr(\"STR_YES\"));\n\t_btnYes->onMouseClick((ActionHandler)&ConfirmCydoniaState::btnYesClick);\n\t_btnYes->onKeyboardPress((ActionHandler)&ConfirmCydoniaState::btnYesClick, Options::keyOk);\n\n\t_btnNo->setText(tr(\"STR_NO\"));\n\t_btnNo->onMouseClick((ActionHandler)&ConfirmCydoniaState::btnNoClick);\n\t_btnNo->onKeyboardPress((ActionHandler)&ConfirmCydoniaState::btnNoClick, Options::keyCancel);\n\n\t_txtMessage->setAlign(ALIGN_CENTER);\n\t_txtMessage->setBig();\n\t_txtMessage->setWordWrap(true);\n\t_txtMessage->setText(tr(\"STR_ARE_YOU_SURE_CYDONIA\"));\n}\n\n/**\n *\n */\nConfirmCydoniaState::~ConfirmCydoniaState()\n{\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid ConfirmCydoniaState::btnYesClick(Action *)\n{\n\t_game->popState();\n\t_game->popState();\n\n\tSavedBattleGame *bgame = new SavedBattleGame(_game->getMod(), _game->getLanguage());\n\t_game->getSavedGame()->setBattleGame(bgame);\n\tBattlescapeGenerator bgen = BattlescapeGenerator(_game);\n\tfor (auto& ad : _game->getMod()->getDeploymentsList())\n\t{\n\t\tAlienDeployment *deployment = _game->getMod()->getDeployment(ad);\n\t\tif (deployment->isFinalDestination())\n\t\t{\n\t\t\tbgame->setMissionType(ad);\n\t\t\tbgen.setAlienRace(deployment->getRace());\n\t\t\tbreak;\n\t\t}\n\t}\n\tbgen.setCraft(_craft);\n\tbgen.run();\n\n\t_game->pushState(new BriefingState(_craft));\n\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid ConfirmCydoniaState::btnNoClick(Action *)\n{\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/ConfirmCydoniaState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http:///www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass Craft;\nclass Window;\nclass Text;\nclass TextButton;\n\n/**\n * Screen that allows the player\n * to pick a target for a craft on the globe.\n */\nclass ConfirmCydoniaState : public State\n{\nprivate:\n\tWindow *_window;\n\tText *_txtMessage;\n\tTextButton *_btnNo, *_btnYes;\n\tCraft *_craft;\npublic:\n\t/// Creates the Select Destination state.\n\tConfirmCydoniaState(Craft *craft);\n\t/// Cleans up the Select Destination state.\n\t~ConfirmCydoniaState();\n\t/// Handler for clicking the Cancel button.\n\tvoid btnNoClick(Action *action);\n\t/// Handler for clicking the Cydonia mission button.\n\tvoid btnYesClick(Action *action);\n\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/ConfirmDestinationState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"CraftErrorState.h\"\n#include \"CraftNotEnoughPilotsState.h\"\n#include \"ConfirmDestinationState.h\"\n#include \"../fmath.h\"\n#include \"../Engine/Game.h\"\n#include \"../Menu/ErrorMessageState.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/AlienRace.h\"\n#include \"../Mod/RuleInterface.h\"\n#include \"../Mod/RuleStartingCondition.h\"\n#include \"../Mod/RuleSoldier.h\"\n#include \"../Mod/AlienDeployment.h\"\n#include \"../Mod/ArticleDefinition.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/ToggleTextButton.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Craft.h\"\n#include \"../Savegame/Target.h\"\n#include \"../Savegame/Waypoint.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/Ufo.h\"\n#include \"../Savegame/MissionSite.h\"\n#include \"../Savegame/AlienBase.h\"\n#include \"../Savegame/Soldier.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Sound.h\"\n#include \"../Ufopaedia/Ufopaedia.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Confirm Destination window.\n * @param game Pointer to the core game.\n * @param crafts Vector for the crafts part of a wing to retarget.\n * @param target Pointer to the selected target (NULL if it's just a point on the globe).\n */\nConfirmDestinationState::ConfirmDestinationState(std::vector<Craft*> crafts, Target *target) : _crafts(std::move(crafts)), _target(target)\n{\n\tWaypoint *w = dynamic_cast<Waypoint*>(_target);\n\t_screen = false;\n\n\tBase *base = dynamic_cast<Base*>(_target);\n\tbool transferAvailable = false; // no transfer allowed for wings\n\n\tif (_crafts.size() == 1)\n\t{\n\t\ttransferAvailable = (Options::canTransferCraftsWhileAirborne && base != 0 && base != _crafts.front()->getBase() && _crafts.front()->arePilotsOnboard(_game->getMod()));\n\t}\n\n\tint btnOkX = transferAvailable ? 29 : 68;\n\tint btnCancelX = transferAvailable ? 177 : 138;\n\n\t// Create objects\n\t_window = new Window(this, 244, 72, 6, 64);\n\t_btnOk = new TextButton(50, 12, btnOkX, 104);\n\t_btnTransfer = new TextButton(82, 12, 87, 104);\n\t_btnCancel = new TextButton(50, 12, btnCancelX, 104);\n\t_btnFollowWingLeader = new ToggleTextButton(170, 16, 43, 138);\n\t_txtTarget = new Text(232, 32, 12, 72);\n\t_txtETA = new Text(232, 9, 12, 120);\n\n\t// Set palette\n\tsetInterface(\"confirmDestination\", w != 0 && w->getId() == 0);\n\n\tadd(_window, \"window\", \"confirmDestination\");\n\tadd(_btnOk, \"button\", \"confirmDestination\");\n\tadd(_btnCancel, \"button\", \"confirmDestination\");\n\tadd(_btnTransfer, \"button\", \"confirmDestination\");\n\tadd(_btnFollowWingLeader, \"button\", \"confirmDestination\");\n\tadd(_txtTarget, \"text\", \"confirmDestination\");\n\tadd(_txtETA, \"text\", \"confirmDestination\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"confirmDestination\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&ConfirmDestinationState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&ConfirmDestinationState::btnOkClick, Options::keyOk);\n\n\t_btnTransfer->setText(tr(\"STR_TRANSFER_UC\"));\n\t_btnTransfer->onMouseClick((ActionHandler)&ConfirmDestinationState::btnTransferClick);\n\t_btnTransfer->setVisible(transferAvailable);\n\n\t_btnCancel->setText(tr(\"STR_CANCEL_UC\"));\n\t_btnCancel->onMouseClick((ActionHandler)&ConfirmDestinationState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&ConfirmDestinationState::btnCancelClick, Options::keyCancel);\n\n\t_btnFollowWingLeader->setText(tr(\"STR_FOLLOW_WING_LEADER_QUESTION\"));\n\t_btnFollowWingLeader->setVisible(false);\n\n\tif (_crafts.size() > 1)\n\t{\n\t\t_btnFollowWingLeader->setVisible(true);\n\n\t\tUfo* u = dynamic_cast<Ufo*>(_target);\n\t\tif (u && u->getStatus() == Ufo::FLYING)\n\t\t{\n\t\t\t_btnFollowWingLeader->setPressed(false); // everybody go for the UFO as quickly as possible\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_btnFollowWingLeader->setPressed(true); // follow the wing leader please\n\t\t}\n\t}\n\n\t_txtTarget->setBig();\n\t_txtTarget->setAlign(ALIGN_CENTER);\n\t_txtTarget->setVerticalAlign(ALIGN_MIDDLE);\n\t_txtTarget->setWordWrap(true);\n\tif (w != 0 && w->getId() == 0)\n\t{\n\t\t_txtTarget->setText(tr(\"STR_TARGET\").arg(tr(\"STR_WAY_POINT\")));\n\t}\n\telse\n\t{\n\t\t_txtTarget->setText(tr(\"STR_TARGET\").arg(_target->getName(_game->getLanguage())));\n\t}\n\n\t// ETA display\n\tif (Options::oxceShowETAMode > 0 && _target)\n\t{\n\t\tMovingTarget* mt = dynamic_cast<MovingTarget*>(_target);\n\t\tif (Options::oxceShowETAMode == 1 && mt && mt->getSpeed() > 0)\n\t\t{\n\t\t\t// don't show ETA for moving targets (i.e. UFOs and crafts)\n\t\t}\n\t\telse\n\t\t{\n\t\t\tint speed = _crafts.front()->getCraftStats().speedMax;\n\t\t\tint distance = XcomDistance(_crafts.front()->getDistance(_target));\n\t\t\tint etaInHoursHelper = (distance + (speed / 2)) / speed;\n\t\t\tint days = etaInHoursHelper / 24;\n\t\t\tint hours = etaInHoursHelper % 24;\n\t\t\tstd::ostringstream ssStatus;\n\t\t\tif (days > 0) ssStatus << tr(\"STR_DAY_SHORT\").arg(days);\n\t\t\tif (hours > 0 || days == 0)\n\t\t\t{\n\t\t\t\tif (days > 0) ssStatus << \"/\";\n\t\t\t\tssStatus << tr(\"STR_HOUR_SHORT\").arg(hours);\n\t\t\t}\n\t\t\t_txtETA->setAlign(ALIGN_CENTER);\n\t\t\t_txtETA->setText(tr(\"STR_ETA\").arg(ssStatus.str()));\n\t\t}\n\t}\n}\n\n/**\n *\n */\nConfirmDestinationState::~ConfirmDestinationState()\n{\n\n}\n\n/**\n* Checks the starting condition.\n*/\nstd::string ConfirmDestinationState::checkStartingCondition()\n{\n\t// Check all selected craft\n\tfor (auto* xcraft : _crafts)\n\t{\n\t\tif (xcraft->areBannedArmorsOnboard())\n\t\t{\n\t\t\treturn tr(\"STR_ARMOR_NOT_ALLOWED_ONBOARD\");\n\t\t}\n\t}\n\n\tUfo* u = dynamic_cast<Ufo*>(_target);\n\tMissionSite* m = dynamic_cast<MissionSite*>(_target);\n\tAlienBase* b = dynamic_cast<AlienBase*>(_target);\n\n\tAlienDeployment *ruleDeploy = 0;\n\tif (u != 0)\n\t{\n\t\truleDeploy = _game->getMod()->getDeployment(u->getRules()->getType()); // no need to check for fake underwater UFOs here\n\t}\n\telse if (m != 0)\n\t{\n\t\truleDeploy = _game->getMod()->getDeployment(m->getDeployment()->getType());\n\t}\n\telse if (b != 0)\n\t{\n\t\tAlienRace *race = _game->getMod()->getAlienRace(b->getAlienRace());\n\t\truleDeploy = _game->getMod()->getDeployment(race->getBaseCustomMission());\n\t\tif (!ruleDeploy) ruleDeploy = _game->getMod()->getDeployment(b->getDeployment()->getType());\n\t}\n\telse\n\t{\n\t\t// for example just a waypoint\n\t\treturn \"\";\n\t}\n\n\tif (ruleDeploy == 0)\n\t{\n\t\t// e.g. UFOs without alien deployment :(\n\t\treturn \"\";\n\t}\n\n\tRuleStartingCondition *rule = _game->getMod()->getStartingCondition(ruleDeploy->getStartingCondition());\n\tif (rule == 0)\n\t{\n\t\t// rule doesn't exist (mod upgrades?)\n\t\treturn \"\";\n\t}\n\tif (rule->requiresCommanderOnboard() && !_crafts.front()->isCommanderOnboard())\n\t{\n\t\tif (!u || u->getStatus() == Ufo::LANDED || u->getStatus() == Ufo::CRASHED)\n\t\t{\n\t\t\treturn tr(\"STR_STARTING_CONDITION_COMMANDER\");\n\t\t}\n\t}\n\n\t// Only check first selected craft\n\t// The other crafts will follow the first selected craft so they will not land at the mission site\n\t// This check is only performed once per wing\n\t// Checking if _crafts.size() != 1 will disallow the escorting scenario\n\n\t// check required item(s)\n\tauto& requiredItems = rule->getRequiredItems();\n\tif (!_crafts.front()->areRequiredItemsOnboard(requiredItems))\n\t{\n\t\tstd::ostringstream ss2;\n\t\tint i2 = 0;\n\t\tfor (auto& pair : requiredItems)\n\t\t{\n\t\t\tif (i2 > 0)\n\t\t\t\tss2 << \", \";\n\t\t\tss2 << tr(pair.first) << \": \" << pair.second;\n\t\t\ti2++;\n\t\t}\n\t\tstd::string argument2 = ss2.str();\n\t\treturn tr(\"STR_STARTING_CONDITION_ITEM\").arg(argument2);\n\t}\n\n\t// check permitted soldiers\n\tif (!_crafts.front()->areOnlyPermittedSoldierTypesOnboard(rule))\n\t{\n\t\tauto& list = rule->getForbiddenSoldierTypes().empty() ? rule->getAllowedSoldierTypes() : rule->getForbiddenSoldierTypes();\n\t\tconst std::string messageCode = rule->getForbiddenSoldierTypes().empty() ? \"STR_STARTING_CONDITION_SOLDIER_TYPE_ALLOWED\" : \"STR_STARTING_CONDITION_SOLDIER_TYPE_FORBIDDEN\";\n\n\t\tstd::ostringstream ss;\n\t\tint i = 0;\n\t\tfor (auto& soldierType : list)\n\t\t{\n\t\t\tRuleSoldier* soldierTypeRule = _game->getMod()->getSoldier(soldierType, false);\n\t\t\tif (soldierTypeRule && _game->getSavedGame()->isResearched(soldierTypeRule->getRequirements()))\n\t\t\t{\n\t\t\t\tif (i > 0)\n\t\t\t\t\tss << \", \";\n\t\t\t\tss << tr(soldierType);\n\t\t\t\ti++;\n\t\t\t}\n\t\t}\n\t\tstd::string argument = ss.str();\n\t\tif (argument.empty())\n\t\t{\n\t\t\t// no suitable soldier type yet?\n\t\t\targument = tr(\"STR_UNKNOWN\");\n\t\t}\n\t\treturn tr(messageCode).arg(argument);\n\t}\n\n\tif (rule->isCraftPermitted(_crafts.front()->getRules()->getType()))\n\t{\n\t\t// craft is permitted\n\t\treturn \"\";\n\t}\n\n\t// craft is not permitted (= either forbidden or not allowed)\n\tauto& list = rule->getForbiddenCraft().empty() ? rule->getAllowedCraft() : rule->getForbiddenCraft();\n\tconst std::string messageCode = rule->getForbiddenCraft().empty() ? \"STR_STARTING_CONDITION_CRAFT_ALLOWED\" : \"STR_STARTING_CONDITION_CRAFT_FORBIDDEN\";\n\n\tstd::ostringstream ss;\n\tint i = 0;\n\tfor (auto& articleName : list)\n\t{\n\t\tArticleDefinition *article = _game->getMod()->getUfopaediaArticle(articleName, false);\n\t\tif (article && Ufopaedia::isArticleAvailable(_game->getSavedGame(), article))\n\t\t{\n\t\t\tif (i > 0)\n\t\t\t\tss << \", \";\n\t\t\tss << tr(articleName);\n\t\t\ti++;\n\t\t}\n\t}\n\tstd::string argument = ss.str();\n\tif (argument.empty())\n\t{\n\t\t// no suitable craft yet\n\t\targument = tr(\"STR_UNKNOWN\");\n\t}\n\treturn tr(messageCode).arg(argument);\n}\n\n/**\n * Confirms the selected target for the craft.\n * @param action Pointer to an action.\n */\nvoid ConfirmDestinationState::btnOkClick(Action *)\n{\n\tstd::string message = checkStartingCondition();\n\tif (!message.empty())\n\t{\n\t\t_game->popState();\n\t\t_game->popState();\n\t\t_game->pushState(new CraftErrorState(0, message));\n\t\treturn;\n\t}\n\n\tfor (auto* craft : _crafts)\n\t{\n\t\tif (craft->areTooManyItemsOnboard())\n\t\t{\n\t\t\t_game->popState();\n\t\t\t_game->popState();\n\t\t\tstd::string message2 = tr(\"STR_TOO_MANY_ITEMS_ONBOARD\");\n\t\t\t_game->pushState(new CraftErrorState(0, message2));\n\t\t\treturn;\n\t\t}\n\t}\n\n\tfor (auto* craft : _crafts)\n\t{\n\t\tif (!craft->arePilotsOnboard(_game->getMod()))\n\t\t{\n\t\t\t_game->popState();\n\t\t\t_game->popState();\n\t\t\t_game->pushState(new CraftNotEnoughPilotsState(craft));\n\t\t\treturn;\n\t\t}\n\t}\n\n\tWaypoint *w = dynamic_cast<Waypoint*>(_target);\n\tif (w != 0 && w->getId() == 0)\n\t{\n\t\tw->setId(_game->getSavedGame()->getId(\"STR_WAY_POINT\"));\n\t\t_game->getSavedGame()->getWaypoints()->push_back(w);\n\t}\n\n\t// first selected _craft (first shift-clicked craft) is wing leader; the other crafts follow the wing leader\n\tif (_crafts.front() == _target)\n\t{\n\t\t//setting itself as target works fine but it should be saying \"patrolling\" instead\n\t\t_crafts.front()->setDestination(0);\n\t}\n\telse\n\t{\n\t\t_crafts.front()->setDestination(_target);\n\t\tif (_crafts.front()->isTakingOff())\n\t\t{\n\t\t\tif (!_crafts.front()->getRules()->getTakeoffSoundRaw().empty())\n\t\t\t{\n\t\t\t\t_game->getMod()->getSound(\"GEO.CAT\", _crafts.front()->getRules()->getTakeoffSound())->play();\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (auto* craft : _crafts)\n\t{\n\t\tif (craft != _crafts.front())\n\t\t{\n\t\t\tif (_btnFollowWingLeader->getPressed())\n\t\t\t{\n\t\t\t\tcraft->setDestination(_crafts.front()); // follow the wing leader\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tcraft->setDestination(_target); // go for the same target as the wing leader\n\t\t\t}\n\t\t}\n\n\t\tif (craft->getRules()->canAutoPatrol())\n\t\t{\n\t\t\t// cancel auto-patrol\n\t\t\tcraft->setIsAutoPatrolling(false);\n\t\t}\n\n\t\tcraft->setStatus(\"STR_OUT\");\n\t}\n\n\t_game->popState();\n\t_game->popState();\n}\n\n/**\n * Handles clicking the transfer button\n * Performs a transfer of a craft to a targeted base if possible, otherwise pops an error message\n * @param action Pointer to an action.\n */\nvoid ConfirmDestinationState::btnTransferClick(Action *)\n{\n\tstd::string errorMessage;\n\t\n\tBase *targetBase = dynamic_cast<Base*>(_target);\n\tif ((targetBase->getAvailableHangars() - targetBase->getUsedHangars()) <= 0) // don't know how you'd get less than 0 available hangars, but want to handle that just in case\n\t{\n\t\terrorMessage = tr(\"STR_NO_FREE_HANGARS_FOR_TRANSFER\");\n\t}\n\telse if (_crafts.front()->getNumTotalSoldiers() > targetBase->getAvailableQuarters() - targetBase->getUsedQuarters())\n\t{\n\t\terrorMessage = tr(\"STR_NO_FREE_ACCOMODATION_CREW\");\n\t}\n\telse if (Options::storageLimitsEnforced && targetBase->storesOverfull(_crafts.front()->getTotalItemStorageSize()))\n\t{\n\t\terrorMessage = tr(\"STR_NOT_ENOUGH_STORE_SPACE_FOR_CRAFT\");\n\t}\n\telse if (_crafts.front()->getFuel() < _crafts.front()->getFuelLimit(targetBase))\n\t{\n\t\terrorMessage = tr(\"STR_NOT_ENOUGH_FUEL_TO_REACH_TARGET\");\n\t}\n\n\t// clicking transfer will start the craft moving or make us need to pick a new destination\n\t// either way, we need to get rid of this confirming the destination state\n\t_game->popState();\n\tif (errorMessage.empty())\n\t{\n\t\t// Transfer soldiers inside craft\n\t\tBase *currentBase = _crafts.front()->getBase();\n\t\tfor (auto soldierIt = currentBase->getSoldiers()->begin(); soldierIt != currentBase->getSoldiers()->end();)\n\t\t{\n\t\t\tSoldier* soldier = (*soldierIt);\n\t\t\tif (soldier->getCraft() == _crafts.front())\n\t\t\t{\n\t\t\t\tsoldier->setPsiTraining(false);\n\t\t\t\tif (soldier->isInTraining())\n\t\t\t\t{\n\t\t\t\t\tsoldier->setReturnToTrainingWhenHealed(true);\n\t\t\t\t}\n\t\t\t\tsoldier->setTraining(false);\n\t\t\t\ttargetBase->getSoldiers()->push_back(soldier);\n\t\t\t\tsoldierIt = currentBase->getSoldiers()->erase(soldierIt);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t++soldierIt;\n\t\t\t}\n\t\t}\n\n\t\t// Transfer craft\n\t\tcurrentBase->removeCraft(_crafts.front(), false);\n\t\ttargetBase->getCrafts()->push_back(_crafts.front());\n\t\t_crafts.front()->setBase(targetBase, false);\n\t\t_crafts.front()->returnToBase();\n\t\t_crafts.front()->setStatus(\"STR_OUT\");\n\t\tif (_crafts.front()->getFuel() <= _crafts.front()->getFuelLimit(targetBase))\n\t\t{\n\t\t\t_crafts.front()->setLowFuel(true);\n\t\t}\n\n\t\t// pop the selecting the destination state\n\t\t_game->popState();\n\t}\n\telse\n\t{\n\t\tRuleInterface *menuInterface = _game->getMod()->getInterface(\"errorMessages\");\n\t\t_game->pushState(new ErrorMessageState(errorMessage, _palette, menuInterface->getElement(\"geoscapeColor\")->color, \"BACK13.SCR\", menuInterface->getElement(\"geoscapePalette\")->color));\n\t}\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid ConfirmDestinationState::btnCancelClick(Action *)\n{\n\tWaypoint *w = dynamic_cast<Waypoint*>(_target);\n\tif (w != 0 && w->getId() == 0)\n\t{\n\t\tdelete w;\n\t}\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/ConfirmDestinationState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http:///www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass Window;\nclass Text;\nclass TextButton;\nclass ToggleTextButton;\nclass Craft;\nclass Target;\n\n/**\n * Window that allows the player\n * to confirm a craft's new destination.\n */\nclass ConfirmDestinationState : public State\n{\nprivate:\n\tstd::vector<Craft*> _crafts;\n\tTarget *_target;\n\tWindow *_window;\n\tText *_txtTarget;\n\tText *_txtETA;\n\tTextButton *_btnOk, *_btnTransfer, *_btnCancel;\n\tToggleTextButton *_btnFollowWingLeader;\n\t// Checks the starting condition\n\tstd::string checkStartingCondition();\npublic:\n\t/// Creates the Confirm Destination state.\n\tConfirmDestinationState(std::vector<Craft*> crafts, Target *target);\n\t/// Cleans up the Confirm Destination state.\n\t~ConfirmDestinationState();\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the Transfer button.\n\tvoid btnTransferClick(Action *action);\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/ConfirmLandingState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"CraftErrorState.h\"\n#include \"ConfirmLandingState.h\"\n#include <sstream>\n#include \"../Engine/Game.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Engine/SurfaceSet.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Craft.h\"\n#include \"../Savegame/Target.h\"\n#include \"../Savegame/Ufo.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/MissionSite.h\"\n#include \"../Savegame/AlienBase.h\"\n#include \"../Battlescape/BriefingState.h\"\n#include \"../Battlescape/BattlescapeGenerator.h\"\n#include \"../Engine/Exception.h\"\n#include \"../Engine/Options.h\"\n#include \"../Mod/RuleStartingCondition.h\"\n#include \"../Mod/AlienDeployment.h\"\n#include \"../Mod/AlienRace.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/Texture.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Confirm Landing window.\n * @param craft Pointer to the craft to confirm.\n * @param missionTexture Texture specific to the mission (can be either specific/fixed or taken from the globe).\n * @param globeTexture Globe texture of the landing site.\n * @param shade Shade of the landing site.\n */\nConfirmLandingState::ConfirmLandingState(Craft *craft, Texture *missionTexture, Texture *globeTexture, int shade) : _craft(craft), _missionTexture(missionTexture), _globeTexture(globeTexture), _shade(shade)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 216, 160, 20, 20, POPUP_BOTH);\n\t_btnYes = new TextButton(80, 20, 40, 150);\n\t_btnNo = new TextButton(80, 20, 136, 150);\n\t_txtMessage = new Text(206, 80, 25, 40);\n\t_txtBegin = new Text(206, 17, 25, 130);\n\t_sprite = new Surface(24, 24, 202, 30);\n\n\t// Set palette\n\tsetInterface(\"confirmLanding\");\n\n\tadd(_window, \"window\", \"confirmLanding\");\n\tadd(_btnYes, \"button\", \"confirmLanding\");\n\tadd(_btnNo, \"button\", \"confirmLanding\");\n\tadd(_txtMessage, \"text\", \"confirmLanding\");\n\tadd(_txtBegin, \"text\", \"confirmLanding\");\n\tadd(_sprite);\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"confirmLanding\");\n\n\t_btnYes->setText(tr(\"STR_YES\"));\n\t_btnYes->onMouseClick((ActionHandler)&ConfirmLandingState::btnYesClick);\n\t_btnYes->onKeyboardPress((ActionHandler)&ConfirmLandingState::btnYesClick, Options::keyOk);\n\n\tif (_game->isCtrlPressed())\n\t{\n\t\t_btnNo->setText(tr(\"STR_PATROL\"));\n\t}\n\telse\n\t{\n\t\t_btnNo->setText(tr(\"STR_NO\"));\n\t}\n\t_btnNo->onMouseClick((ActionHandler)&ConfirmLandingState::btnNoClick);\n\t_btnNo->onKeyboardPress((ActionHandler)&ConfirmLandingState::btnNoClick, Options::keyCancel);\n\t_btnNo->onKeyboardPress((ActionHandler)&ConfirmLandingState::togglePatrolButton, SDLK_LCTRL);\n\t_btnNo->onKeyboardRelease((ActionHandler)&ConfirmLandingState::togglePatrolButton, SDLK_LCTRL);\n\t_btnNo->onKeyboardPress((ActionHandler)&ConfirmLandingState::togglePatrolButton, SDLK_RCTRL);\n\t_btnNo->onKeyboardRelease((ActionHandler)&ConfirmLandingState::togglePatrolButton, SDLK_RCTRL);\n\n\t_txtMessage->setBig();\n\t_txtMessage->setAlign(ALIGN_CENTER);\n\t_txtMessage->setWordWrap(true);\n\t_txtMessage->setText(tr(\"STR_CRAFT_READY_TO_LAND_NEAR_DESTINATION\")\n\t\t\t\t\t\t .arg(_craft->getName(_game->getLanguage()))\n\t\t\t\t\t\t .arg(_craft->getDestination()->getName(_game->getLanguage())));\n\n\t_txtBegin->setBig();\n\t_txtBegin->setAlign(ALIGN_CENTER);\n\tstd::ostringstream ss;\n\tss << Unicode::TOK_COLOR_FLIP << tr(\"STR_BEGIN_MISSION\");\n\t_txtBegin->setText(ss.str());\n\n\tSurfaceSet *sprites = _game->getMod()->getSurfaceSet(\"DayNightIndicator\", false);\n\tif (sprites != 0)\n\t{\n\t\tif (_shade <= 0)\n\t\t{\n\t\t\t// day (0)\n\t\t\tsprites->getFrame(0)->blitNShade(_sprite, 0, 0);\n\t\t}\n\t\telse if (_shade > _game->getMod()->getMaxDarknessToSeeUnits())\n\t\t{\n\t\t\t// night (10-15); note: this is configurable in the ruleset (in OXCE only)\n\t\t\tsprites->getFrame(1)->blitNShade(_sprite, 0, 0);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// dusk/dawn (1-9)\n\t\t\tsprites->getFrame(2)->blitNShade(_sprite, 0, 0);\n\t\t}\n\t}\n}\n\n/**\n *\n */\nConfirmLandingState::~ConfirmLandingState()\n{\n\n}\n\n/*\n * Make sure we aren't returning to base.\n */\nvoid ConfirmLandingState::init()\n{\n\tState::init();\n\tBase* b = dynamic_cast<Base*>(_craft->getDestination());\n\tif (b == _craft->getBase())\n\t\t_game->popState();\n}\n\n/**\n* Checks the starting condition.\n*/\nstd::string ConfirmLandingState::checkStartingCondition()\n{\n\tif (_craft->areBannedArmorsOnboard())\n\t{\n\t\treturn tr(\"STR_ARMOR_NOT_ALLOWED_ONBOARD\");\n\t}\n\n\tUfo* u = dynamic_cast<Ufo*>(_craft->getDestination());\n\tMissionSite* m = dynamic_cast<MissionSite*>(_craft->getDestination());\n\tAlienBase* b = dynamic_cast<AlienBase*>(_craft->getDestination());\n\n\tAlienDeployment *ruleDeploy = 0;\n\tif (u != 0)\n\t{\n\t\tstd::string ufoMissionName = u->getRules()->getType();\n\t\tif (_missionTexture && _missionTexture->isFakeUnderwater())\n\t\t{\n\t\t\tufoMissionName = u->getRules()->getType() + \"_UNDERWATER\";\n\t\t}\n\t\truleDeploy = _game->getMod()->getDeployment(ufoMissionName);\n\t}\n\telse if (m != 0)\n\t{\n\t\truleDeploy = _game->getMod()->getDeployment(m->getDeployment()->getType());\n\t}\n\telse if (b != 0)\n\t{\n\t\tAlienRace *race = _game->getMod()->getAlienRace(b->getAlienRace());\n\t\truleDeploy = _game->getMod()->getDeployment(race->getBaseCustomMission());\n\t\tif (!ruleDeploy) ruleDeploy = _game->getMod()->getDeployment(b->getDeployment()->getType());\n\t}\n\telse\n\t{\n\t\t// irrelevant for this check\n\t\treturn \"\";\n\t}\n\n\tif (ruleDeploy == 0)\n\t{\n\t\t// just in case\n\t\treturn \"\";\n\t}\n\n\tRuleStartingCondition *rule = _game->getMod()->getStartingCondition(ruleDeploy->getStartingCondition());\n\tif (!rule && _missionTexture)\n\t{\n\t\trule = _game->getMod()->getStartingCondition(_missionTexture->getStartingCondition());\n\t}\n\tif (rule != 0)\n\t{\n\t\tif (rule->requiresCommanderOnboard() && !_craft->isCommanderOnboard())\n\t\t{\n\t\t\tif (!u || u->getStatus() == Ufo::LANDED || u->getStatus() == Ufo::CRASHED)\n\t\t\t{\n\t\t\t\treturn tr(\"STR_STARTING_CONDITION_COMMANDER\");\n\t\t\t}\n\t\t}\n\t\tif (!rule->isCraftPermitted(_craft->getRules()->getType()))\n\t\t{\n\t\t\treturn tr(\"STR_STARTING_CONDITION_CRAFT\"); // simple message without details/argument\n\t\t}\n\t\tif (!_craft->areOnlyPermittedSoldierTypesOnboard(rule))\n\t\t{\n\t\t\treturn tr(\"STR_STARTING_CONDITION_SOLDIER_TYPE\"); // simple message without details/argument\n\t\t}\n\n\t\tif (!_craft->areRequiredItemsOnboard(rule->getRequiredItems()))\n\t\t{\n\t\t\treturn tr(\"STR_STARTING_CONDITION_ITEM\"); // simple message without details/argument\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (rule->getDestroyRequiredItems())\n\t\t\t{\n\t\t\t\t_craft->destroyRequiredItems(rule->getRequiredItems());\n\t\t\t}\n\t\t}\n\t}\n\treturn \"\";\n}\n\n/**\n * Enters the mission.\n * @param action Pointer to an action.\n */\nvoid ConfirmLandingState::btnYesClick(Action *)\n{\n\tstd::string message = checkStartingCondition();\n\tif (!message.empty())\n\t{\n\t\t_craft->returnToBase();\n\t\t_game->popState();\n\t\t_game->pushState(new CraftErrorState(0, message));\n\t\treturn;\n\t}\n\n\t_game->popState();\n\tUfo* u = dynamic_cast<Ufo*>(_craft->getDestination());\n\tMissionSite* m = dynamic_cast<MissionSite*>(_craft->getDestination());\n\tAlienBase* b = dynamic_cast<AlienBase*>(_craft->getDestination());\n\n\tSavedBattleGame *bgame = new SavedBattleGame(_game->getMod(), _game->getLanguage());\n\t_game->getSavedGame()->setBattleGame(bgame);\n\tBattlescapeGenerator bgen(_game);\n\tbgen.setWorldTexture(_missionTexture, _globeTexture);\n\tbgen.setWorldShade(_shade);\n\tbgen.setCraft(_craft);\n\tif (u != 0)\n\t{\n\t\tif (u->getStatus() == Ufo::CRASHED)\n\t\t\tbgame->setMissionType(\"STR_UFO_CRASH_RECOVERY\");\n\t\telse\n\t\t\tbgame->setMissionType(\"STR_UFO_GROUND_ASSAULT\");\n\t\tbgen.setUfo(u);\n\t\tconst AlienDeployment *customWeaponDeploy = _game->getMod()->getDeployment(u->getCraftStats().craftCustomDeploy);\n\t\tif (_missionTexture && _missionTexture->isFakeUnderwater())\n\t\t{\n\t\t\tconst std::string ufoUnderwaterMissionName = u->getRules()->getType() + \"_UNDERWATER\";\n\t\t\tconst AlienDeployment *ufoUnderwaterMission = _game->getMod()->getDeployment(ufoUnderwaterMissionName, true);\n\t\t\tbgen.setAlienCustomDeploy(customWeaponDeploy, ufoUnderwaterMission);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tbgen.setAlienCustomDeploy(customWeaponDeploy);\n\t\t}\n\t\tbgen.setAlienRace(u->getAlienRace());\n\t}\n\telse if (m != 0)\n\t{\n\t\tbgame->setMissionType(m->getDeployment()->getType());\n\t\tbgen.setMissionSite(m);\n\t\tbgen.setAlienCustomDeploy(m->getMissionCustomDeploy());\n\t\tbgen.setAlienRace(m->getAlienRace());\n\t}\n\telse if (b != 0)\n\t{\n\t\tAlienRace *race = _game->getMod()->getAlienRace(b->getAlienRace());\n\t\tbgame->setMissionType(b->getDeployment()->getType());\n\t\tbgen.setAlienBase(b);\n\t\tbgen.setAlienRace(b->getAlienRace());\n\t\tbgen.setAlienCustomDeploy(_game->getMod()->getDeployment(race->getBaseCustomDeploy()), _game->getMod()->getDeployment(race->getBaseCustomMission()));\n\t\tbgen.setWorldTexture(0, _globeTexture);\n\t}\n\telse\n\t{\n\t\tthrow Exception(\"No mission available!\");\n\t}\n\tbgen.run();\n\t_game->pushState(new BriefingState(_craft));\n}\n\n/**\n * Returns the craft to base and closes the window.\n * @param action Pointer to an action.\n */\nvoid ConfirmLandingState::btnNoClick(Action *)\n{\n\tif (_game->isCtrlPressed())\n\t{\n\t\t_craft->setDestination(0);\n\t}\n\telse\n\t{\n\t\t_craft->returnToBase();\n\t}\n\t_game->popState();\n}\n\n/**\n * Toggles No/Patrol button.\n * @param action Pointer to an action.\n */\nvoid ConfirmLandingState::togglePatrolButton(Action *)\n{\n\tif (_game->isCtrlPressed())\n\t{\n\t\t_btnNo->setText(tr(\"STR_PATROL\"));\n\t}\n\telse\n\t{\n\t\t_btnNo->setText(tr(\"STR_NO\"));\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/ConfirmLandingState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http:///www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass Window;\nclass Text;\nclass TextButton;\nclass Craft;\nclass Texture;\nclass Surface;\n\n/**\n * Window that allows the player\n * to confirm a craft landing at its destination.\n */\nclass ConfirmLandingState : public State\n{\nprivate:\n\tCraft *_craft;\n\tWindow *_window;\n\tTexture *_missionTexture, *_globeTexture;\n\tint _shade;\n\tText *_txtMessage, *_txtBegin;\n\tTextButton *_btnYes, *_btnNo;\n\tSurface *_sprite;\n\t// Checks the starting condition\n\tstd::string checkStartingCondition();\npublic:\n\t/// Creates the Confirm Landing state.\n\tConfirmLandingState(Craft *craft, Texture *missionTexture, Texture *globeTexture, int shade);\n\t/// Cleans up the Confirm Landing state.\n\t~ConfirmLandingState();\n\t/// initialize the state, make a sanity check.\n\tvoid init() override;\n\t/// Handler for clicking the Yes button.\n\tvoid btnYesClick(Action *action);\n\t/// Handler for clicking the No button.\n\tvoid btnNoClick(Action *action);\n\t/// Handler for pressing/releasing CTRL.\n\tvoid togglePatrolButton(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/ConfirmNewBaseState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ConfirmNewBaseState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Region.h\"\n#include \"../Mod/RuleRegion.h\"\n#include \"../Savegame/Base.h\"\n#include \"BaseNameState.h\"\n#include \"../Menu/ErrorMessageState.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Mod/RuleInterface.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Confirm New Base window.\n * @param game Pointer to the core game.\n * @param base Pointer to the base to place.\n * @param globe Pointer to the Geoscape globe.\n */\nConfirmNewBaseState::ConfirmNewBaseState(Base *base, Globe *globe) : _base(base), _globe(globe), _cost(0)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 224, 72, 16, 64);\n\t_btnOk = new TextButton(54, 12, 68, 104);\n\t_btnCancel = new TextButton(54, 12, 138, 104);\n\t_txtCost = new Text(120, 9, 68, 80);\n\t_txtArea = new Text(120, 9, 68, 90);\n\n\t// Set palette\n\tsetInterface(\"geoscape\");\n\n\tadd(_window, \"genericWindow\", \"geoscape\");\n\tadd(_btnOk, \"genericButton2\", \"geoscape\");\n\tadd(_btnCancel, \"genericButton2\", \"geoscape\");\n\tadd(_txtCost, \"genericText\", \"geoscape\");\n\tadd(_txtArea, \"genericText\", \"geoscape\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"geoscape\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&ConfirmNewBaseState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&ConfirmNewBaseState::btnOkClick, Options::keyOk);\n\n\t_btnCancel->setText(tr(\"STR_CANCEL_UC\"));\n\t_btnCancel->onMouseClick((ActionHandler)&ConfirmNewBaseState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&ConfirmNewBaseState::btnCancelClick, Options::keyCancel);\n\n\tstd::string area;\n\tfor (const auto* region : *_game->getSavedGame()->getRegions())\n\t{\n\t\tif (region->getRules()->insideRegion(_base->getLongitude(), _base->getLatitude()))\n\t\t{\n\t\t\t_cost = region->getRules()->getBaseCost();\n\t\t\tarea = tr(region->getRules()->getType());\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t_txtCost->setText(tr(\"STR_COST_\").arg(Unicode::formatFunding(_cost)));\n\n\t_txtArea->setText(tr(\"STR_AREA_\").arg(area));\n}\n\n/**\n *\n */\nConfirmNewBaseState::~ConfirmNewBaseState()\n{\n\n}\n\n/**\n * Go to the Place Access Lift screen.\n * @param action Pointer to an action.\n */\nvoid ConfirmNewBaseState::btnOkClick(Action *)\n{\n\tif (_game->getSavedGame()->getFunds() >= _cost)\n\t{\n\t\t_game->getSavedGame()->setFunds(_game->getSavedGame()->getFunds() - _cost);\n\t\t_game->getSavedGame()->getBases()->push_back(_base);\n\t\t_game->pushState(new BaseNameState(_base, _globe, false, false));\n\t}\n\telse\n\t{\n\t\t_game->pushState(new ErrorMessageState(tr(\"STR_NOT_ENOUGH_MONEY\"), _palette, _game->getMod()->getInterface(\"geoscape\")->getElement(\"genericWindow\")->color, \"BACK01.SCR\", _game->getMod()->getInterface(\"geoscape\")->getElement(\"palette\")->color));\n\t}\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid ConfirmNewBaseState::btnCancelClick(Action *)\n{\n\t_globe->onMouseOver(0);\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/ConfirmNewBaseState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http:///www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass Base;\nclass Window;\nclass Text;\nclass TextButton;\nclass Globe;\n\n/**\n * Screen that allows the player\n * to confirm a new base on the globe.\n * Note: This is different from the starting base screen, BaseNameState\n */\nclass ConfirmNewBaseState : public State\n{\nprivate:\n\tBase *_base;\n\tGlobe *_globe;\n\tWindow *_window;\n\tText *_txtCost, *_txtArea;\n\tTextButton *_btnOk, *_btnCancel;\n\tint _cost;\npublic:\n\t/// Creates the Confirm New Base state.\n\tConfirmNewBaseState(Base *base, Globe *globe);\n\t/// Cleans up the Confirm New Base state.\n\t~ConfirmNewBaseState();\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/Cord.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../fmath.h\"\n\nnamespace OpenXcom\n{\n\nstruct Cord;\n\nstruct CordPolar\n{\n\tdouble lon, lat;\n\n\tinline CordPolar(double plon, double plat)\n\t{\n\t\tlon = plon;\n\t\tlat = plat;\n\t}\n\n\tCordPolar(const CordPolar& pol) = default;\n\n\tinline CordPolar()\n\t{\n\t\tlon = 0;\n\t\tlat = 0;\n\t}\n\texplicit inline CordPolar(const Cord&);\n\n\tCordPolar& operator=(const CordPolar& pol) = default;\n};\n\nstruct Cord\n{\n\tdouble x, y, z;\n\n\tinline Cord(double px, double py, double pz)\n\t{\n\t\tx = px;\n\t\ty = py;\n\t\tz = pz;\n\t}\n\tinline Cord()\n\t{\n\t\tx = 0.0;\n\t\ty = 0.0;\n\t\tz = 0.0;\n\t}\n\tinline Cord(const Cord& c) = default;\n\n\texplicit inline Cord(const CordPolar&);\n\n\tCord& operator=(const Cord& pol) = default;\n\n\n\tinline Cord operator +()\n\t{\n\t\treturn *this;\n\t}\n\tinline Cord operator -()\n\t{\n\t\treturn Cord(-x, -y, -z);\n\t}\n\tinline Cord& operator *=(double d)\n\t{\n\t\tx *= d;\n\t\ty *= d;\n\t\tz *= d;\n\t\treturn *this;\n\t}\n\tinline Cord& operator /=(double d)\n\t{\n\t\tdouble re = 1./d;\n\t\tx *= re;\n\t\ty *= re;\n\t\tz *= re;\n\t\treturn *this;\n\t}\n\tinline Cord& operator +=(const Cord& c)\n\t{\n\t\tx += c.x;\n\t\ty += c.y;\n\t\tz += c.z;\n\t\treturn *this;\n\t}\n\tinline Cord& operator -=(const Cord& c)\n\t{\n\t\tx -= c.x;\n\t\ty -= c.y;\n\t\tz -= c.z;\n\t\treturn *this;\n\t}\n\tinline bool operator ==(const Cord& c)\n\t{\n\t\treturn AreSame(x, c.x) && AreSame(y, c.y) && AreSame(z, c.z);\n\t}\n\n\tinline double norm() const\n\t{\n\t\treturn std::sqrt(x*x + y*y + z*z);\n\t}\n};\n\ninline Cord::Cord(const CordPolar& pol)\n{\n\tx = std::sin(pol.lon) * std::cos(pol.lat);\n\ty = std::sin(pol.lat);\n\tz = std::cos(pol.lon) * std::cos(pol.lat);\n}\n\ninline CordPolar::CordPolar(const Cord& c)\n{\n\tdouble inv = 1/c.norm();\n\tlat = asin(c.y * inv);\n\tlon = atan2(c.x, c.z);\n}\n\n}//namespace OpenXcom\n\n"
  },
  {
    "path": "src/Geoscape/CraftErrorState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"CraftErrorState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"GeoscapeState.h\"\n#include \"Globe.h\"\n#include \"../Savegame/Target.h\"\n#include \"../Engine/Options.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in a Craft Error window.\n * @param game Pointer to the core game.\n * @param state Pointer to the Geoscape state.\n * @param msg Error message.\n */\nCraftErrorState::CraftErrorState(GeoscapeState *state, const std::string &msg, bool enableHotkeys, Target* centerOnTarget) :\n\t_state(state), _centerOnTarget(centerOnTarget)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 256, 160, 32, 20, POPUP_BOTH);\n\t_btnOk = new TextButton(100, 18, _state ? 48 : 110, 150);\n\t_btnOk5Secs = new TextButton(100, 18, 172, 150);\n\t_txtMessage = new Text(246, 96, 37, 42);\n\n\t// Set palette\n\tsetInterface(\"craftError\");\n\n\tadd(_window, \"window\", \"craftError\");\n\tadd(_btnOk, \"button\", \"craftError\");\n\tadd(_btnOk5Secs, \"button\", \"craftError\");\n\tadd(_txtMessage, \"text1\", \"craftError\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"craftError\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&CraftErrorState::btnOkClick);\n\tif (enableHotkeys)\n\t{\n\t\t_btnOk->onKeyboardPress((ActionHandler)&CraftErrorState::btnOkClick, Options::keyCancel);\n\t\tif (!_state)\n\t\t{\n\t\t\t_btnOk->onKeyboardPress((ActionHandler)&CraftErrorState::btnOkClick, Options::keyOk);\n\t\t}\n\t}\n\n\t_btnOk5Secs->setText(tr(\"STR_OK_5_SECONDS\"));\n\t_btnOk5Secs->onMouseClick((ActionHandler)&CraftErrorState::btnOk5SecsClick);\n\tif (enableHotkeys && _state)\n\t{\n\t\t_btnOk5Secs->onKeyboardPress((ActionHandler)&CraftErrorState::btnOk5SecsClick, Options::keyOk);\n\t}\n\t_btnOk5Secs->setVisible(_state != 0);\n\n\t_txtMessage->setAlign(ALIGN_CENTER);\n\t_txtMessage->setVerticalAlign(ALIGN_MIDDLE);\n\t_txtMessage->setBig();\n\t_txtMessage->setWordWrap(true);\n\t_txtMessage->setText(msg);\n}\n\n/**\n *\n */\nCraftErrorState::~CraftErrorState()\n{\n\n}\n\n/**\n * Closes the window.\n * @param action Pointer to an action.\n */\nvoid CraftErrorState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Closes the window.\n * @param action Pointer to an action.\n */\nvoid CraftErrorState::btnOk5SecsClick(Action *)\n{\n\t_state->timerReset();\n\tif (_centerOnTarget)\n\t{\n\t\t_state->getGlobe()->center(_centerOnTarget->getLongitude(), _centerOnTarget->getLatitude());\n\t}\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/CraftErrorState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass GeoscapeState;\nclass Target;\n\n/**\n * Window used to notify the player when\n * an error occurs with a craft procedure.\n */\nclass CraftErrorState : public State\n{\nprivate:\n\tGeoscapeState *_state;\n\tTarget* _centerOnTarget;\n\tTextButton *_btnOk, *_btnOk5Secs;\n\tWindow *_window;\n\tText *_txtMessage;\npublic:\n\t/// Creates the Craft Error state.\n\tCraftErrorState(GeoscapeState *state, const std::string &msg, bool enableHotkeys = true, Target* centerOnTarget = nullptr);\n\t/// Cleans up the Craft Error state.\n\t~CraftErrorState();\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the OK 5 Secs button.\n\tvoid btnOk5SecsClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/CraftNotEnoughPilotsState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"CraftNotEnoughPilotsState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Engine/Options.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/Craft.h\"\n#include \"../Basescape/CraftInfoState.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in a Craft Not Enough Pilots window.\n * @param craft Relevant craft.\n */\nCraftNotEnoughPilotsState::CraftNotEnoughPilotsState(Craft *craft) : _craft(craft)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 256, 160, 32, 20, POPUP_BOTH);\n\t_btnOk = new TextButton(108, 18, 48, 150);\n\t_btnAssignPilots = new TextButton(108, 18, 164, 150);\n\t_txtMessage = new Text(246, 96, 37, 42);\n\n\t// Set palette\n\tsetInterface(\"craftPilotError\");\n\n\tadd(_window, \"window\", \"craftPilotError\");\n\tadd(_btnOk, \"button\", \"craftPilotError\");\n\tadd(_btnAssignPilots, \"button\", \"craftPilotError\");\n\tadd(_txtMessage, \"text1\", \"craftPilotError\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"craftPilotError\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&CraftNotEnoughPilotsState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&CraftNotEnoughPilotsState::btnOkClick, Options::keyCancel);\n\n\t_btnAssignPilots->setText(tr(\"STR_ASSIGN_PILOTS\"));\n\t_btnAssignPilots->onMouseClick((ActionHandler)&CraftNotEnoughPilotsState::btnAssignPilotsClick);\n\t_btnAssignPilots->onKeyboardPress((ActionHandler)&CraftNotEnoughPilotsState::btnAssignPilotsClick, Options::keyOk);\n\tif (_craft->getMissionComplete() || _craft->getStatus() == \"STR_OUT\")\n\t{\n\t\t_btnAssignPilots->setVisible(false);\n\t}\n\n\t_txtMessage->setAlign(ALIGN_CENTER);\n\t_txtMessage->setVerticalAlign(ALIGN_MIDDLE);\n\t_txtMessage->setBig();\n\t_txtMessage->setWordWrap(true);\n\t_txtMessage->setText(tr(\"STR_NOT_ENOUGH_PILOTS\").arg(_craft->getRules()->getPilots()));\n}\n\n/**\n *\n */\nCraftNotEnoughPilotsState::~CraftNotEnoughPilotsState()\n{\n\n}\n\n/**\n * Closes the window.\n * @param action Pointer to an action.\n */\nvoid CraftNotEnoughPilotsState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Opens CraftInfo window.\n * @param action Pointer to an action.\n */\nvoid CraftNotEnoughPilotsState::btnAssignPilotsClick(Action *)\n{\n\tBase *b = _craft->getBase();\n\tif (b)\n\t{\n\t\tfor (size_t i = 0; i < b->getCrafts()->size(); ++i)\n\t\t{\n\t\t\tif (b->getCrafts()->at(i) == _craft)\n\t\t\t{\n\t\t\t\t_game->popState();\n\t\t\t\t_game->pushState(new CraftInfoState(_craft->getBase(), i));\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/CraftNotEnoughPilotsState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass Craft;\n\n/**\n * Window used to notify the player when\n * there are not enough pilots to pilot the craft.\n */\nclass CraftNotEnoughPilotsState : public State\n{\nprivate:\n\tTextButton *_btnOk, *_btnAssignPilots;\n\tWindow *_window;\n\tText *_txtMessage;\n\tCraft *_craft;\npublic:\n\t/// Creates the CraftNotEnoughPilotsState state.\n\tCraftNotEnoughPilotsState(Craft *craft);\n\t/// Cleans up the CraftNotEnoughPilotsState state.\n\t~CraftNotEnoughPilotsState();\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the [Assign Pilots] button.\n\tvoid btnAssignPilotsClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/CraftPatrolState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"CraftPatrolState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Savegame/Craft.h\"\n#include \"../Savegame/Target.h\"\n#include \"GeoscapeCraftState.h\"\n#include \"../Engine/Options.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Craft Patrol window.\n * @param game Pointer to the core game.\n * @param craft Pointer to the craft to display.\n * @param globe Pointer to the Geoscape globe.\n */\nCraftPatrolState::CraftPatrolState(Craft *craft, Globe *globe) : _craft(craft), _globe(globe)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 224, 168, 16, 16, POPUP_BOTH);\n\t_btnOk = new TextButton(140, 12, 58, 144);\n\t_btnRedirect = new TextButton(140, 12, 58, 160);\n\t_txtDestination = new Text(224, 64, 16, 48);\n\t_txtPatrolling = new Text(224, 17, 16, 120);\n\n\t// Set palette\n\tsetInterface(\"craftPatrol\");\n\n\tadd(_window, \"window\", \"craftPatrol\");\n\tadd(_btnOk, \"button\", \"craftPatrol\");\n\tadd(_btnRedirect, \"button\", \"craftPatrol\");\n\tadd(_txtDestination, \"text1\", \"craftPatrol\");\n\tadd(_txtPatrolling, \"text1\", \"craftPatrol\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"craftPatrol\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&CraftPatrolState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&CraftPatrolState::btnOkClick, Options::keyCancel);\n\n\t_btnRedirect->setText(tr(\"STR_REDIRECT_CRAFT\"));\n\t_btnRedirect->onMouseClick((ActionHandler)&CraftPatrolState::btnRedirectClick);\n\t_btnRedirect->onKeyboardPress((ActionHandler)&CraftPatrolState::btnRedirectClick, Options::keyOk);\n\n\t_txtDestination->setBig();\n\t_txtDestination->setAlign(ALIGN_CENTER);\n\t_txtDestination->setWordWrap(true);\n\t_txtDestination->setText(tr(\"STR_CRAFT_HAS_REACHED_DESTINATION\")\n\t\t\t\t\t\t\t .arg(_craft->getName(_game->getLanguage()))\n\t\t\t\t\t\t\t .arg(_craft->getDestination()->getName(_game->getLanguage())));\n\n\t_txtPatrolling->setBig();\n\t_txtPatrolling->setAlign(ALIGN_CENTER);\n\t_txtPatrolling->setText(tr(\"STR_NOW_PATROLLING\"));\n}\n\n/**\n *\n */\nCraftPatrolState::~CraftPatrolState()\n{\n\n}\n\n/**\n * Closes the window.\n * @param action Pointer to an action.\n */\nvoid CraftPatrolState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Opens up the Craft window.\n * @param action Pointer to an action.\n */\nvoid CraftPatrolState::btnRedirectClick(Action *)\n{\n\t_game->popState();\n\t_game->pushState(new GeoscapeCraftState(_craft, _globe, 0, false));\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/CraftPatrolState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass Craft;\nclass Globe;\n\n/**\n * Window displayed when a craft\n * starts patrolling a waypoint.\n */\nclass CraftPatrolState : public State\n{\nprivate:\n\tCraft *_craft;\n\tGlobe *_globe;\n\n\tTextButton *_btnOk, *_btnRedirect;\n\tWindow *_window;\n\tText *_txtDestination, *_txtPatrolling;\npublic:\n\t/// Creates the Geoscape Craft state.\n\tCraftPatrolState(Craft *craft, Globe *globe);\n\t/// Cleans up the Geoscape Craft state.\n\t~CraftPatrolState();\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the Redirect Craft button.\n\tvoid btnRedirectClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/DogfightErrorState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"DogfightErrorState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Engine/Options.h\"\n#include \"../Savegame/Craft.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in a Dogfight Error window.\n * @param game Pointer to the core game.\n * @param state Pointer to the Geoscape state.\n * @param msg Error message.\n */\nDogfightErrorState::DogfightErrorState(Craft *craft, const std::string &msg) : _craft(craft)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 208, 120, 24, 48, POPUP_BOTH);\n\t_btnIntercept = new TextButton(180, 12, 38, 128);\n\t_btnBase = new TextButton(180, 12, 38, 144);\n\t_txtCraft = new Text(198, 16, 29, 63);\n\t_txtMessage = new Text(198, 20, 29, 94);\n\n\t// Set palette\n\tsetInterface(\"dogfightInfo\");\n\n\tadd(_window, \"window\", \"dogfightInfo\");\n\tadd(_btnIntercept, \"button\", \"dogfightInfo\");\n\tadd(_btnBase, \"button\", \"dogfightInfo\");\n\tadd(_txtCraft, \"text\", \"dogfightInfo\");\n\tadd(_txtMessage, \"text\", \"dogfightInfo\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"dogfightInfo\");\n\n\t_btnIntercept->setText(tr(\"STR_CONTINUE_INTERCEPTION_PURSUIT\"));\n\t_btnIntercept->onMouseClick((ActionHandler)&DogfightErrorState::btnInterceptClick);\n\t_btnIntercept->onKeyboardPress((ActionHandler)&DogfightErrorState::btnInterceptClick, Options::keyCancel);\n\n\t_btnBase->setText(tr(\"STR_RETURN_TO_BASE\"));\n\t_btnBase->onMouseClick((ActionHandler)&DogfightErrorState::btnBaseClick);\n\t_btnBase->onKeyboardPress((ActionHandler)&DogfightErrorState::btnBaseClick, Options::keyOk);\n\n\t_txtCraft->setAlign(ALIGN_CENTER);\n\t_txtCraft->setBig();\n\t_txtCraft->setText(_craft->getName(_game->getLanguage()));\n\n\t_txtMessage->setAlign(ALIGN_CENTER);\n\t_txtMessage->setWordWrap(true);\n\t_txtMessage->setText(msg);\n}\n\n/**\n *\n */\nDogfightErrorState::~DogfightErrorState()\n{\n\n}\n\n/**\n * Closes the window.\n * @param action Pointer to an action.\n */\nvoid DogfightErrorState::btnInterceptClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Returns the craft to base.\n * @param action Pointer to an action.\n */\nvoid DogfightErrorState::btnBaseClick(Action *)\n{\n\t_craft->returnToBase();\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/DogfightErrorState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass Craft;\n\n/**\n * Window used to notify the player when\n * an error occurs with a dogfight procedure.\n */\nclass DogfightErrorState : public State\n{\nprivate:\n\tCraft *_craft;\n\tTextButton *_btnIntercept, *_btnBase;\n\tWindow *_window;\n\tText *_txtCraft, *_txtMessage;\npublic:\n\t/// Creates the Craft Error state.\n\tDogfightErrorState(Craft *craft, const std::string &msg);\n\t/// Cleans up the Craft Error state.\n\t~DogfightErrorState();\n\t/// Handler for clicking the Continue Interception button.\n\tvoid btnInterceptClick(Action *action);\n\t/// Handler for clicking the Return To Base button.\n\tvoid btnBaseClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/DogfightExperienceState.cpp",
    "content": "/*\n * Copyright 2010-2020 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"DogfightExperienceState.h\"\n#include <sstream>\n#include <algorithm>\n#include \"../Engine/Game.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Interface/Window.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Soldier.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Dogfight Experience screen.\n */\nDogfightExperienceState::DogfightExperienceState()\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 320, 140, 0, 30, POPUP_HORIZONTAL);\n\t_btnOk = new TextButton(300, 16, 10, 146);\n\t_txtTitle = new Text(300, 17, 10, 46);\n\t_txtFiringAcc = new Text(108, 9, 74, 70);\n\t_txtReactions = new Text(58, 9, 182, 70);\n\t_txtBravery = new Text(58, 9, 240, 70);\n\t_txtPilots = new Text(80, 9, 10, 70);\n\t_lstPilots = new TextList(288, 64, 10, 78);\n\n\t// Set palette\n\tsetInterface(\"dogfightExperience\");\n\n\tadd(_window, \"window\", \"dogfightExperience\");\n\tadd(_btnOk, \"button\", \"dogfightExperience\");\n\tadd(_txtTitle, \"text1\", \"dogfightExperience\");\n\tadd(_txtFiringAcc, \"text2\", \"dogfightExperience\");\n\tadd(_txtReactions, \"text2\", \"dogfightExperience\");\n\tadd(_txtBravery, \"text2\", \"dogfightExperience\");\n\tadd(_txtPilots, \"text2\", \"dogfightExperience\");\n\tadd(_lstPilots, \"list\", \"dogfightExperience\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"dogfightExperience\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&DogfightExperienceState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&DogfightExperienceState::btnOkClick, Options::keyOk);\n\t_btnOk->onKeyboardPress((ActionHandler)&DogfightExperienceState::btnOkClick, Options::keyCancel);\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_DAILY_PILOT_EXPERIENCE\"));\n\n\t_txtFiringAcc->setText(tr(\"STR_FIRING_ACCURACY\"));\n\t_txtFiringAcc->setAlign(ALIGN_RIGHT);\n\n\t_txtReactions->setText(tr(\"STR_REACTIONS\"));\n\t_txtReactions->setAlign(ALIGN_RIGHT);\n\n\t_txtBravery->setText(tr(\"STR_BRAVERY\"));\n\t_txtBravery->setAlign(ALIGN_RIGHT);\n\n\t_txtPilots->setText(tr(\"STR_NAME\"));\n\n\t_lstPilots->setColumns(5, 114, 58, 58, 58, 0);\n\t_lstPilots->setAlign(ALIGN_RIGHT);\n\t_lstPilots->setAlign(ALIGN_LEFT, 0);\n\t_lstPilots->setDot(true);\n\n\t_lstPilots->clearList();\n\tfor (auto* xbase : *_game->getSavedGame()->getBases())\n\t{\n\t\tfor (auto* soldier : *xbase->getSoldiers())\n\t\t{\n\t\t\tauto* tmp = soldier->getDailyDogfightExperienceCache();\n\t\t\tif (tmp->firing > 0 || tmp->reactions > 0 || tmp->bravery > 0)\n\t\t\t{\n\t\t\t\tstd::ostringstream ss1;\n\t\t\t\tif (tmp->firing > 0)\n\t\t\t\t\tss1 << Unicode::TOK_COLOR_FLIP << '+' << tmp->firing << Unicode::TOK_COLOR_FLIP;\n\t\t\t\tstd::ostringstream ss2;\n\t\t\t\tif (tmp->reactions > 0)\n\t\t\t\t\tss2 << Unicode::TOK_COLOR_FLIP << '+' << tmp->reactions << Unicode::TOK_COLOR_FLIP;\n\t\t\t\tstd::ostringstream ss3;\n\t\t\t\tif (tmp->bravery > 0)\n\t\t\t\t\tss3 << Unicode::TOK_COLOR_FLIP << '+' << tmp->bravery << Unicode::TOK_COLOR_FLIP;\n\t\t\t\t_lstPilots->addRow(5, soldier->getName(false).c_str(), ss1.str().c_str(), ss2.str().c_str(), ss3.str().c_str(), \"\");\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid DogfightExperienceState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/DogfightExperienceState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2020 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass TextList;\n\n/**\n * Displays experience gained by craft pilot(s) during the current day.\n */\nclass DogfightExperienceState : public State\n{\nprivate:\n\tTextButton *_btnOk;\n\tWindow *_window;\n\tText *_txtTitle, *_txtFiringAcc, *_txtReactions, *_txtBravery, *_txtPilots;\n\tTextList *_lstPilots;\npublic:\n\t/// Creates the DogfightExperienceState.\n\tDogfightExperienceState();\n\t/// Cleans up the DogfightExperienceState.\n\t~DogfightExperienceState() = default;\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/DogfightState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"DogfightState.h\"\n#include <cmath>\n#include <sstream>\n#include \"GeoscapeState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Screen.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/SurfaceSet.h\"\n#include \"../Engine/Surface.h\"\n#include \"../Engine/Action.h\"\n#include \"../Interface/ImageButton.h\"\n#include \"../Interface/Text.h\"\n#include \"../Engine/Timer.h\"\n#include \"../Engine/Collections.h\"\n#include \"Globe.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Soldier.h\"\n#include \"../Savegame/SoldierDiary.h\"\n#include \"../Mod/RuleSoldier.h\"\n#include \"../Savegame/Craft.h\"\n#include \"../Mod/RuleCraft.h\"\n#include \"../Savegame/CraftWeapon.h\"\n#include \"../Mod/RuleCraftWeapon.h\"\n#include \"../Savegame/Ufo.h\"\n#include \"../Mod/RuleUfo.h\"\n#include \"../Mod/AlienRace.h\"\n#include \"../Engine/RNG.h\"\n#include \"../Engine/Sound.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/CraftWeaponProjectile.h\"\n#include \"../Savegame/Country.h\"\n#include \"../Mod/RuleCountry.h\"\n#include \"../Savegame/Region.h\"\n#include \"../Mod/RuleRegion.h\"\n#include \"../Savegame/AlienMission.h\"\n#include \"DogfightErrorState.h\"\n#include \"../Mod/RuleInterface.h\"\n#include \"../Mod/Mod.h\"\n\nnamespace OpenXcom\n{\n\n// UFO blobs graphics ...\nconst int DogfightState::_ufoBlobs[8][13][13] =\n{\n\t\t/*0 STR_VERY_SMALL */\n\t{\n\t\t{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},\n\t\t{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},\n\t\t{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},\n\t\t{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},\n\t\t{0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0},\n\t\t{0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0},\n\t\t{0, 0, 0, 0, 1, 3, 5, 3, 1, 0, 0, 0, 0},\n\t\t{0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0},\n\t\t{0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0},\n\t\t{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},\n\t\t{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},\n\t\t{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},\n\t\t{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}\n\t},\n\t\t/*1 STR_SMALL */\n\t{\n\t\t{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},\n\t\t{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},\n\t\t{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},\n\t\t{0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0},\n\t\t{0, 0, 0, 0, 1, 2, 2, 2, 1, 0, 0, 0, 0},\n\t\t{0, 0, 0, 1, 2, 3, 4, 3, 2, 1, 0, 0, 0},\n\t\t{0, 0, 0, 1, 2, 4, 5, 4, 2, 1, 0, 0, 0},\n\t\t{0, 0, 0, 1, 2, 3, 4, 3, 2, 1, 0, 0, 0},\n\t\t{0, 0, 0, 0, 1, 2, 2, 2, 1, 0, 0, 0, 0},\n\t\t{0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0},\n\t\t{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},\n\t\t{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},\n\t\t{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}\n\t},\n\t\t/*2 STR_MEDIUM_UC */\n\t{\n\t\t{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},\n\t\t{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},\n\t\t{0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0},\n\t\t{0, 0, 0, 1, 1, 2, 2, 2, 1, 1, 0, 0, 0},\n\t\t{0, 0, 0, 1, 2, 3, 3, 3, 2, 1, 0, 0, 0},\n\t\t{0, 0, 1, 2, 3, 4, 5, 4, 3, 2, 1, 0, 0},\n\t\t{0, 0, 1, 2, 3, 5, 5, 5, 3, 2, 1, 0, 0},\n\t\t{0, 0, 1, 2, 3, 4, 5, 4, 3, 2, 1, 0, 0},\n\t\t{0, 0, 0, 1, 2, 3, 3, 3, 2, 1, 0, 0, 0},\n\t\t{0, 0, 0, 1, 1, 2, 2, 2, 1, 1, 0, 0, 0},\n\t\t{0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0},\n\t\t{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},\n\t\t{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}\n\t},\n\t\t/*3 STR_LARGE */\n\t{\n\t\t{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},\n\t\t{0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0},\n\t\t{0, 0, 0, 1, 1, 2, 2, 2, 1, 1, 0, 0, 0},\n\t\t{0, 0, 1, 2, 2, 3, 3, 3, 2, 2, 1, 0, 0},\n\t\t{0, 0, 1, 2, 3, 4, 4, 4, 3, 2, 1, 0, 0},\n\t\t{0, 1, 2, 3, 4, 5, 5, 5, 4, 3, 2, 1, 0},\n\t\t{0, 1, 2, 3, 4, 5, 5, 5, 4, 3, 2, 1, 0},\n\t\t{0, 1, 2, 3, 4, 5, 5, 5, 4, 3, 2, 1, 0},\n\t\t{0, 0, 1, 2, 3, 4, 4, 4, 3, 2, 1, 0, 0},\n\t\t{0, 0, 1, 2, 2, 3, 3, 3, 2, 2, 1, 0, 0},\n\t\t{0, 0, 0, 1, 1, 2, 2, 2, 1, 1, 0, 0, 0},\n\t\t{0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0},\n\t\t{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}\n\t},\n\t\t/*4 STR_VERY_LARGE */\n\t{\n\t\t{0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0},\n\t\t{0, 0, 0, 1, 1, 2, 2, 2, 1, 1, 0, 0, 0},\n\t\t{0, 0, 1, 2, 2, 3, 3, 3, 2, 2, 1, 0, 0},\n\t\t{0, 1, 2, 3, 3, 4, 4, 4, 3, 3, 2, 1, 0},\n\t\t{0, 1, 2, 3, 4, 5, 5, 5, 4, 3, 2, 1, 0},\n\t\t{1, 2, 3, 4, 5, 5, 5, 5, 5, 4, 3, 2, 1},\n\t\t{1, 2, 3, 4, 5, 5, 5, 5, 5, 4, 3, 2, 1},\n\t\t{1, 2, 3, 4, 5, 5, 5, 5, 5, 4, 3, 2, 1},\n\t\t{0, 1, 2, 3, 4, 5, 5, 5, 4, 3, 2, 1, 0},\n\t\t{0, 1, 2, 3, 3, 4, 4, 4, 3, 3, 2, 1, 0},\n\t\t{0, 0, 1, 2, 2, 3, 3, 3, 2, 2, 1, 0, 0},\n\t\t{0, 0, 0, 1, 1, 2, 2, 2, 1, 1, 0, 0, 0},\n\t\t{0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0}\n\t},\n\t\t/*5 STR_HUGE */\n\t{\n\t\t{0, 0, 0, 1, 1, 2, 2, 2, 1, 1, 0, 0, 0},\n\t\t{0, 0, 1, 2, 2, 3, 3, 3, 2, 2, 1, 0, 0},\n\t\t{0, 1, 2, 3, 3, 4, 4, 4, 3, 3, 2, 1, 0},\n\t\t{1, 2, 3, 4, 4, 5, 5, 5, 4, 4, 3, 2, 1},\n\t\t{1, 2, 3, 4, 5, 5, 5, 5, 5, 4, 3, 2, 1},\n\t\t{2, 3, 4, 5, 5, 5, 5, 5, 5, 5, 4, 3, 2},\n\t\t{2, 3, 4, 5, 5, 5, 5, 5, 5, 5, 4, 3, 2},\n\t\t{2, 3, 4, 5, 5, 5, 5, 5, 5, 5, 4, 3, 2},\n\t\t{1, 2, 3, 4, 5, 5, 5, 5, 5, 4, 3, 2, 1},\n\t\t{1, 2, 3, 4, 4, 5, 5, 5, 4, 4, 3, 2, 1},\n\t\t{0, 1, 2, 3, 3, 4, 4, 4, 3, 3, 2, 1, 0},\n\t\t{0, 0, 1, 2, 2, 3, 3, 3, 2, 2, 1, 0, 0},\n\t\t{0, 0, 0, 1, 1, 2, 2, 2, 1, 1, 0, 0, 0}\n\t},\n\t\t/*6 STR_VERY_HUGE :p */\n\t{\n\t\t{0, 0, 0, 2, 2, 3, 3, 3, 2, 2, 0, 0, 0},\n\t\t{0, 0, 2, 3, 3, 4, 4, 4, 3, 3, 2, 0, 0},\n\t\t{0, 2, 3, 4, 4, 5, 5, 5, 4, 4, 3, 2, 0},\n\t\t{2, 3, 4, 5, 5, 5, 5, 5, 5, 5, 4, 3, 2},\n\t\t{2, 3, 4, 5, 5, 5, 5, 5, 5, 5, 4, 3, 2},\n\t\t{3, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 3},\n\t\t{3, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 3},\n\t\t{3, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 3},\n\t\t{2, 3, 4, 5, 5, 5, 5, 5, 5, 5, 4, 3, 2},\n\t\t{2, 3, 4, 5, 5, 5, 5, 5, 5, 5, 4, 3, 2},\n\t\t{0, 2, 3, 4, 4, 5, 5, 5, 4, 4, 3, 2, 0},\n\t\t{0, 0, 2, 3, 3, 4, 4, 4, 3, 3, 2, 0, 0},\n\t\t{0, 0, 0, 2, 2, 3, 3, 3, 2, 2, 0, 0, 0}\n\t},\n\t\t/*7 STR_ENOURMOUS */\n\t{\n\t\t{0, 0, 0, 3, 3, 4, 4, 4, 3, 3, 0, 0, 0},\n\t\t{0, 0, 3, 4, 4, 5, 5, 5, 4, 4, 3, 0, 0},\n\t\t{0, 3, 4, 5, 5, 5, 5, 5, 5, 5, 4, 3, 0},\n\t\t{3, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 3},\n\t\t{3, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 3},\n\t\t{4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4},\n\t\t{4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4},\n\t\t{4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4},\n\t\t{3, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 3},\n\t\t{3, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 3},\n\t\t{0, 3, 4, 5, 5, 5, 5, 5, 5, 5, 4, 3, 0},\n\t\t{0, 0, 3, 4, 4, 5, 5, 5, 4, 4, 3, 0, 0},\n\t\t{0, 0, 0, 3, 3, 4, 4, 4, 3, 3, 0, 0, 0}\n\t}\n};\n\n// Projectile blobs\nconst int DogfightState::_projectileBlobs[4][6][3] =\n{\n\t\t/*0 STR_STINGRAY_MISSILE ?*/\n\t{\n\t\t{0, 1, 0},\n\t\t{1, 9, 1},\n\t\t{1, 4, 1},\n\t\t{0, 3, 0},\n\t\t{0, 2, 0},\n\t\t{0, 1, 0}\n\t},\n\t\t/*1 STR_AVALANCHE_MISSILE ?*/\n\t{\n\t\t{1, 2, 1},\n\t\t{2, 9, 2},\n\t\t{2, 5, 2},\n\t\t{1, 3, 1},\n\t\t{0, 2, 0},\n\t\t{0, 1, 0}\n\t},\n\t\t/*2 STR_CANNON_ROUND ?*/\n\t{\n\t\t{0, 0, 0},\n\t\t{0, 7, 0},\n\t\t{0, 2, 0},\n\t\t{0, 1, 0},\n\t\t{0, 0, 0},\n\t\t{0, 0, 0}\n\t},\n\t\t/*3 STR_FUSION_BALL ?*/\n\t{\n\t\t{2, 4, 2},\n\t\t{4, 9, 4},\n\t\t{2, 4, 2},\n\t\t{0, 0, 0},\n\t\t{0, 0, 0},\n\t\t{0, 0, 0}\n\t}\n};\n/**\n * Initializes all the elements in the Dogfight window.\n * @param game Pointer to the core game.\n * @param state Pointer to the Geoscape.\n * @param craft Pointer to the craft intercepting.\n * @param ufo Pointer to the UFO being intercepted.\n * @param ufoIsAttacking Is UFO the aggressor?\n */\nDogfightState::DogfightState(GeoscapeState *state, Craft *craft, Ufo *ufo, bool ufoIsAttacking) :\n\t_state(state), _craft(craft), _ufo(ufo),\n\t_ufoIsAttacking(ufoIsAttacking), _missileCraft(craft->getRules()->isMissile()), _missileImpact(false),\n\t_disableDisengage(false), _disableStandoff(false), _disableCautious(false), _disableStandard(false), _disableAggressive(false),\n\t_craftIsDefenseless(false), _selfDestructPressed(false),\n\t_timeout(50), _currentDist(640), _targetDist(560),\n\t_end(false), _endUfoHandled(false), _endCraftHandled(false), _ufoBreakingOff(false), _destroyUfo(false), _destroyCraft(false),\n\t_minimized(false), _endDogfight(false), _animatingHit(false), _waitForPoly(false), _waitForAltitude(false), _ufoSize(0), _ufoBlobSize(0),\n\t_craftHeight(0), _currentCraftDamageColor(0),\n\t_interceptionNumber(0), _interceptionsCount(0), _x(0), _y(0), _minimizedIconX(0), _minimizedIconY(0), _firedAtLeastOnce(false), _experienceAwarded(false),\n\t_delayedRecolorDone(false)\n{\n\t_screen = false;\n\t_craft->setInDogfight(true);\n\t_weaponNum = _craft->getRules()->getWeapons();\n\tif (_weaponNum > RuleCraft::WeaponMax)\n\t\t_weaponNum = RuleCraft::WeaponMax;\n\n\tfor (int i = 0; i < _weaponNum; ++i)\n\t{\n\t\t_weaponEnabled[i] = true;\n\t\t_weaponFireCountdown[i] = 0;\n\t\t_tractorLockedOn[i] = false;\n\n\t\tCraftWeapon* w = _craft->getWeapons()->at(i);\n\t\tif (w)\n\t\t{\n\t\t\t_weaponEnabled[i] = !w->isDisabled();\n\t\t}\n\t}\n\n\t// pilot modifiers\n\tconst std::vector<Soldier*> pilots = _craft->getPilotList(false, _game->getMod()); // refresh soldier bonuses\n\n\t_pilotAccuracyBonus = _craft->getPilotAccuracyBonus(pilots, _game->getMod());\n\t_pilotDodgeBonus = _craft->getPilotDodgeBonus(pilots, _game->getMod());\n\t_pilotApproachSpeedModifier = _craft->getPilotApproachSpeedModifier(pilots, _game->getMod());\n\n\t_craftAccelerationBonus = 2; // vanilla\n\tif (!pilots.empty())\n\t{\n\t\t_craftAccelerationBonus = std::min(4, (_craft->getCraftStats().accel / 3) + 1);\n\t}\n\n\t// HK options\n\tif (_ufoIsAttacking)\n\t{\n\t\t_disableStandoff = true;\n\t\t_disableStandard = true;\n\t\t_disableAggressive = false;\n\t\tif (_ufo->getCraftStats().speedMax >= _craft->getCraftStats().speedMax)\n\t\t{\n\t\t\t_disableDisengage = true;\n\t\t}\n\t\tif (_weaponNum == 0)\n\t\t{\n\t\t\t_disableCautious = true;\n\t\t}\n\t\t// make sure the HK attacks its primary target first!\n\t\t{\n\t\t\tCraft* target = dynamic_cast<Craft*>(_ufo->getDestination());\n\t\t\tif (target)\n\t\t\t{\n\t\t\t\tif (_craft != target)\n\t\t\t\t{\n\t\t\t\t\t// push secondary targets a tiny bit away from the HK\n\t\t\t\t\t_currentDist += 16;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// approach primary target at maximum approach speed\n\t\t\t\t\t_pilotApproachSpeedModifier = 4;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t// Missile options\n\tif (_missileCraft)\n\t{\n\t\t_disableStandoff = true;\n\t\t_disableStandard = true;\n\t\t_disableAggressive = false;\n\t\t_disableDisengage = true;\n\t\t_disableCautious = true;\n\n\t\t// approach UFO at maximum approach speed\n\t\t_pilotApproachSpeedModifier = 4;\n\t}\n\n\t// Create objects\n\t_window = new Surface(160, 96, _x, _y);\n\t_battle = new Surface(77, 74, _x + 3, _y + 3);\n\tfor (int i = 0; i < _weaponNum; ++i)\n\t{\n\t\tconst int w_off = i % 2 ? 64 : 4;\n\t\tconst int r_off = i % 2 ? 43 : 19;\n\t\tconst int y_off = 52 - (i / 2) * 28;\n\n\t\t_weapon[i] = new InteractiveSurface(15, 17, _x + w_off, _y + y_off);\n\t\t_range[i] = new Surface(21, 74, _x + r_off, _y + 3);\n\t\t_txtAmmo[i] = new Text(16, 9, _x + w_off, _y + y_off + 18);\n\t}\n\t_craftSprite = new Surface(22, 25, _x + 93, _y + 40);\n\t_damage = new Surface(22, 25, _x + 93, _y + 40);\n\t_craftShield = new Surface(22, 25, _x + 93, _y + 40);\n\n\t_btnMinimize = new InteractiveSurface(12, 12, _x, _y);\n\t_preview = new InteractiveSurface(160, 96, _x, _y);\n\t_btnStandoff = new ImageButton(36, 15, _x + 83, _y + 4);\n\t_btnCautious = new ImageButton(36, 15, _x + 120, _y + 4);\n\t_btnStandard = new ImageButton(36, 15, _x + 83, _y + 20);\n\t_btnAggressive = new ImageButton(36, 15, _x + 120, _y + 20);\n\t_btnDisengage = new ImageButton(36, 15, _x + 120, _y + 36);\n\t_btnUfo = new ImageButton(36, 17, _x + 120, _y + 52);\n\t_txtDistance = new Text(40, 9, _x + 116, _y + 72);\n\t_txtOceanIndicator = new Text(16, 9, _x + 150, _y + 72);\n\t_txtStatus = new Text(154, 9, _x + 4, _y + 85);\n\t_btnMinimizedIcon = new InteractiveSurface(32, 20, _minimizedIconX, _minimizedIconY);\n\t_txtInterceptionNumber = new Text(16, 9, _minimizedIconX + 18, _minimizedIconY + 6);\n\n\t_mode = (_ufoIsAttacking || _missileCraft) ? _btnAggressive : _btnStandoff;\n\t_craftDamageAnimTimer = new Timer(500);\n\n\tmoveWindow();\n\n\t// Set palette\n\tsetInterface(\"dogfight\");\n\n\tadd(_window);\n\tadd(_battle);\n\tfor (int i = 0; i < _weaponNum; ++i)\n\t{\n\t\tadd(_weapon[i]);\n\t\tadd(_range[i]);\n\t}\n\tadd(_craftSprite);\n\tadd(_damage);\n\tadd(_craftShield);\n\tadd(_btnMinimize);\n\tadd(_btnStandoff, \"standoffButton\", \"dogfight\", _window);\n\tadd(_btnCautious, \"cautiousButton\", \"dogfight\", _window);\n\tadd(_btnStandard, \"standardButton\", \"dogfight\", _window);\n\tadd(_btnAggressive, \"aggressiveButton\", \"dogfight\", _window);\n\tadd(_btnDisengage, \"disengageButton\", \"dogfight\", _window);\n\tadd(_btnUfo, \"ufoButton\", \"dogfight\", _window);\n\tfor (int i = 0; i < _weaponNum; ++i)\n\t{\n\t\tadd(_txtAmmo[i], \"numbers\", \"dogfight\", _window);\n\t}\n\tadd(_txtDistance, \"distance\", \"dogfight\", _window);\n\tadd(_txtOceanIndicator, \"oceanIndicator\", \"dogfight\", _window);\n\tadd(_preview);\n\tadd(_txtStatus, \"text\", \"dogfight\", _window);\n\tadd(_btnMinimizedIcon);\n\tadd(_txtInterceptionNumber, \"minimizedNumber\", \"dogfight\");\n\n\t_btnStandoff->invalidate(false);\n\t_btnCautious->invalidate(false);\n\t_btnStandard->invalidate(false);\n\t_btnAggressive->invalidate(false);\n\t_btnDisengage->invalidate(false);\n\t_btnUfo->invalidate(false);\n\n\t// Set up objects\n\tRuleInterface *dogfightInterface = _game->getMod()->getInterface(\"dogfight\");\n\n\tSurfaceCrop crop = _game->getMod()->getSurface(\"INTERWIN.DAT\")->getCrop();\n\tcrop.setX(0);\n\tcrop.setY(0);\n\tcrop.getCrop()->x = 0;\n\tcrop.getCrop()->y = 0;\n\tcrop.getCrop()->w = _window->getWidth();\n\tcrop.getCrop()->h = _window->getHeight();\n\t_window->drawRect(crop.getCrop(), 15);\n\tcrop.blit(_window);\n\n\tif (_ufoIsAttacking || _missileCraft)\n\t{\n\t\tif (_disableStandoff)\n\t\t{\n\t\t\t_window->drawRect(_btnStandoff->getX() + 2, _btnStandoff->getY() + 2, _btnStandoff->getWidth() - 4, _btnStandoff->getHeight() - 4,\n\t\t\t\tdogfightInterface->getElement(\"standoffButton\")->color + 4);\n\t\t}\n\t\tif (_disableCautious)\n\t\t{\n\t\t\t_window->drawRect(_btnCautious->getX() + 2, _btnCautious->getY() + 2, _btnCautious->getWidth() - 4, _btnCautious->getHeight() - 4,\n\t\t\t\tdogfightInterface->getElement(\"cautiousButton\")->color + 4);\n\t\t}\n\t\tif (_disableStandard)\n\t\t{\n\t\t\t_window->drawRect(_btnStandard->getX() + 2, _btnStandard->getY() + 2, _btnStandard->getWidth() - 4, _btnStandard->getHeight() - 4,\n\t\t\t\tdogfightInterface->getElement(\"standardButton\")->color + 4);\n\t\t}\n\t\tif (_disableAggressive)\n\t\t{\n\t\t\t_window->drawRect(_btnAggressive->getX() + 2, _btnAggressive->getY() + 2, _btnAggressive->getWidth() - 4, _btnAggressive->getHeight() - 4,\n\t\t\t\tdogfightInterface->getElement(\"aggressiveButton\")->color + 4);\n\t\t}\n\t\tif (_disableDisengage)\n\t\t{\n\t\t\t_window->drawRect(_btnDisengage->getX() + 2, _btnDisengage->getY() + 2, _btnDisengage->getWidth() - 4, _btnDisengage->getHeight() - 4,\n\t\t\t\tdogfightInterface->getElement(\"disengageButton\")->color + 4);\n\t\t}\n\t}\n\tif (_ufoIsAttacking)\n\t{\n\t\tint offset = dogfightInterface->getElement(\"minimizeButtonDummy\")->TFTDMode ? 1 : 0;\n\t\t_window->drawRect(_btnMinimize->getX() + 1 + offset, _btnMinimize->getY() + 1, _btnMinimize->getWidth() - 2 - offset, _btnMinimize->getHeight() - 2,\n\t\t\tdogfightInterface->getElement(\"minimizeButtonDummy\")->color + 4);\n\t}\n\n\t_preview->drawRect(crop.getCrop(), 15);\n\tcrop.getCrop()->y = dogfightInterface->getElement(\"previewTop\")->y;\n\tcrop.getCrop()->h = dogfightInterface->getElement(\"previewTop\")->h;\n\tcrop.blit(_preview);\n\tcrop.setY(_window->getHeight() - dogfightInterface->getElement(\"previewBot\")->h);\n\tcrop.getCrop()->y = dogfightInterface->getElement(\"previewBot\")->y;\n\tcrop.getCrop()->h = dogfightInterface->getElement(\"previewBot\")->h;\n\tcrop.blit(_preview);\n\n\tif (ufo->getRules()->getModSprite().empty())\n\t{\n\t\tcrop.getCrop()->y = dogfightInterface->getElement(\"previewMid\")->y + dogfightInterface->getElement(\"previewMid\")->h * _ufo->getRules()->getSprite();\n\t\tcrop.getCrop()->h = dogfightInterface->getElement(\"previewMid\")->h;\n\t}\n\telse\n\t{\n\t\tcrop = _game->getMod()->getSurface(ufo->getRules()->getModSprite())->getCrop();\n\t}\n\tcrop.setX(dogfightInterface->getElement(\"previewTop\")->x);\n\tcrop.setY(dogfightInterface->getElement(\"previewTop\")->h);\n\tcrop.blit(_preview);\n\n\t_preview->setVisible(false);\n\t_preview->onMouseClick((ActionHandler)&DogfightState::previewClick);\n\n\t_btnMinimize->onMouseClick((ActionHandler)&DogfightState::btnMinimizeClick);\n\t_btnMinimize->setVisible(!_ufoIsAttacking);\n\n\t_btnStandoff->copy(_window);\n\t_btnStandoff->setGroup(&_mode);\n\t_btnStandoff->onMousePress((ActionHandler)&DogfightState::btnStandoffPress);\n\t_btnStandoff->onMousePress((ActionHandler)&DogfightState::btnStandoffRightPress, SDL_BUTTON_RIGHT);\n\t_btnStandoff->setVisible(!_disableStandoff);\n\n\t_btnCautious->copy(_window);\n\t_btnCautious->setGroup(&_mode);\n\t_btnCautious->onMousePress((ActionHandler)&DogfightState::btnCautiousPress);\n\t_btnCautious->onMousePress((ActionHandler)&DogfightState::btnCautiousRightPress, SDL_BUTTON_RIGHT);\n\t_btnCautious->setVisible(!_disableCautious);\n\n\t_btnStandard->copy(_window);\n\t_btnStandard->setGroup(&_mode);\n\t_btnStandard->onMousePress((ActionHandler)&DogfightState::btnStandardPress);\n\t_btnStandard->onMousePress((ActionHandler)&DogfightState::btnStandardRightPress, SDL_BUTTON_RIGHT);\n\t_btnStandard->setVisible(!_disableStandard);\n\n\t_btnAggressive->copy(_window);\n\t_btnAggressive->setGroup(&_mode);\n\t_btnAggressive->onMousePress((ActionHandler)&DogfightState::btnAggressivePress);\n\t_btnAggressive->onMousePress((ActionHandler)&DogfightState::btnAggressiveRightPress, SDL_BUTTON_RIGHT);\n\t_btnAggressive->setVisible(!_disableAggressive);\n\tif (_ufoIsAttacking || _missileCraft)\n\t{\n\t\tbtnAggressivePress(0);\n\t}\n\n\t_btnDisengage->copy(_window);\n\t_btnDisengage->onMousePress((ActionHandler)&DogfightState::btnDisengagePress);\n\t_btnDisengage->onMousePress((ActionHandler)&DogfightState::btnDisengageRightPress, SDL_BUTTON_RIGHT);\n\t_btnDisengage->setGroup(&_mode);\n\t_btnDisengage->setVisible(!_disableDisengage);\n\n\t_btnUfo->copy(_window);\n\t_btnUfo->onMouseClick((ActionHandler)&DogfightState::btnUfoClick);\n\n\t_txtDistance->setText(\"640\");\n\tupdateOceanIndicator();\n\n\tif (_ufoIsAttacking)\n\t\t_txtStatus->setText(tr(\"STR_AGGRESSIVE_ATTACK\"));\n\telse\n\t\t_txtStatus->setText(tr(\"STR_STANDOFF\"));\n\n\tSurfaceSet *set = _game->getMod()->getSurfaceSet(\"INTICON.PCK\");\n\n\t// Create the minimized dogfight icon.\n\tSurface *frame = set->getFrame(_craft->getSkinSprite());\n\tframe->blitNShade(_btnMinimizedIcon, 0, 0);\n\t_btnMinimizedIcon->onMouseClick((ActionHandler)&DogfightState::btnMinimizedIconClick);\n\t_btnMinimizedIcon->setVisible(false);\n\n\t// Draw correct number on the minimized dogfight icon.\n\tstd::ostringstream ss1;\n\tif (_craft->getInterceptionOrder() == 0)\n\t{\n\t\tint maxInterceptionOrder = 0;\n\t\tfor (auto* xbase : *_game->getSavedGame()->getBases())\n\t\t{\n\t\t\tfor (auto* xcraft : *xbase->getCrafts())\n\t\t\t{\n\t\t\t\tif (xcraft->getInterceptionOrder() > maxInterceptionOrder)\n\t\t\t\t{\n\t\t\t\t\tmaxInterceptionOrder = xcraft->getInterceptionOrder();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t_craft->setInterceptionOrder(++maxInterceptionOrder);\n\t}\n\tss1 << _craft->getInterceptionOrder();\n\t_txtInterceptionNumber->setText(ss1.str());\n\t_txtInterceptionNumber->setVisible(false);\n\n\t// define the colors to be used\n\t_colors[CRAFT_MIN] = dogfightInterface->getElement(\"craftRange\")->color;\n\t_colors[CRAFT_MAX] = dogfightInterface->getElement(\"craftRange\")->color2;\n\t_colors[RADAR_MIN] = dogfightInterface->getElement(\"radarRange\")->color;\n\t_colors[RADAR_MAX] = dogfightInterface->getElement(\"radarRange\")->color2;\n\t_colors[DAMAGE_MIN] = dogfightInterface->getElement(\"damageRange\")->color;\n\t_colors[DAMAGE_MAX] = dogfightInterface->getElement(\"damageRange\")->color2;\n\t_colors[BLOB_MIN] = dogfightInterface->getElement(\"radarDetail\")->color;\n\t_colors[RANGE_METER] = dogfightInterface->getElement(\"radarDetail\")->color2;\n\t_colors[DISABLED_WEAPON] = dogfightInterface->getElement(\"disabledWeapon\")->color;\n\t_colors[DISABLED_RANGE] = dogfightInterface->getElement(\"disabledWeapon\")->color2;\n\t_colors[DISABLED_AMMO] = dogfightInterface->getElement(\"disabledAmmo\")->color;\n\t_colors[SHIELD_MIN] = dogfightInterface->getElement(\"shieldRange\")->color;\n\t_colors[SHIELD_MAX] = dogfightInterface->getElement(\"shieldRange\")->color2;\n\n\tfor (int i = 0; i < _weaponNum; ++i)\n\t{\n\t\tCraftWeapon *w = _craft->getWeapons()->at(i);\n\n\t\t// Slot empty or no sprite, skip!\n\t\tif (w == 0 || w->getRules()->getSprite() < 0)\n\t\t\tcontinue;\n\n\t\tSurface *weapon = _weapon[i], *range = _range[i];\n\t\tText *ammo = _txtAmmo[i];\n\t\tint x1, x2;\n\t\tint x_off = 2 * (i / 2 + 1);\n\t\tif (i % 2 == 0)\n\t\t{\n\t\t\tx1 = x_off;\n\t\t\tx2 = 0;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tx1 = 0;\n\t\t\tx2 = 20 - x_off;\n\t\t}\n\n\t\t// Draw icon\n\t\tframe = set->getFrame(w->getRules()->getSprite() + 5);\n\t\tframe->blitNShade(weapon, 0, 0);\n\n\t\t// Just an equipment, it doesn't have any ammo (weapon) or range (tractor beam), skip!\n\t\tif (w->getRules()->getAmmoMax() == 0 && w->getRules()->getTractorBeamPower() == 0)\n\t\t\tcontinue;\n\n\t\t// Used for weapon toggling.\n\t\t// Only relevant for weapons and tractor beams, not for equipment.\n\t\t_weapon[i]->onMouseClick((ActionHandler)& DogfightState::weaponClick);\n\n\t\t// Draw ammo.\n\t\t// Only relevant for weapons, not for tractor beams.\n\t\tif (w->getRules()->getAmmoMax() > 0)\n\t\t{\n\t\t\tstd::ostringstream ss;\n\t\t\tss << w->getAmmo();\n\t\t\tammo->setText(ss.str());\n\t\t}\n\n\t\t// Draw range (1 km = 1 pixel)\n\t\t// Only relevant for weapons and tractor beams.\n\t\tUint8 color = _colors[RANGE_METER];\n\t\trange->lock();\n\n\t\tint rangeY = range->getHeight() - w->getRules()->getRange();\n\t\tint connectY = weapon->getHeight() / 2 + weapon->getY() - range->getY();\n\t\tfor (int x = x1; x <= x1 + 20 - x_off; x += 2)\n\t\t{\n\t\t\trange->setPixel(x, rangeY, color);\n\t\t}\n\n\t\tint minY = 0, maxY = 0;\n\t\tif (rangeY < connectY)\n\t\t{\n\t\t\tminY = rangeY;\n\t\t\tmaxY = connectY;\n\t\t}\n\t\telse if (rangeY > connectY)\n\t\t{\n\t\t\tminY = connectY;\n\t\t\tmaxY = rangeY;\n\t\t}\n\t\tfor (int y = minY; y <= maxY; ++y)\n\t\t{\n\t\t\trange->setPixel(x1 + x2, y, color);\n\t\t}\n\t\tfor (int x = x2; x <= x2 + x_off; ++x)\n\t\t{\n\t\t\trange->setPixel(x, connectY, color);\n\t\t}\n\t\trange->unlock();\n\t}\n\n\tfor (int i = 0; i < _weaponNum; ++i)\n\t{\n\t\tif (_craft->getWeapons()->at(i) == 0)\n\t\t{\n\t\t\t_weapon[i]->setVisible(false);\n\t\t\t_range[i]->setVisible(false);\n\t\t\t_txtAmmo[i]->setVisible(false);\n\t\t}\n\t}\n\n\t// Draw damage indicator.\n\tframe = set->getFrame(_craft->getSkinSprite() + 11);\n\tframe->blitNShade(_craftSprite, 0, 0);\n\n\t_craftDamageAnimTimer->onTimer((StateHandler)&DogfightState::animateCraftDamage);\n\n\t// don't set these variables if the ufo is already engaged in a dogfight\n\tif (!_ufo->getEscapeCountdown())\n\t{\n\t\t_ufo->setFireCountdown(0);\n\t\tint escapeCountdown = _ufo->getRules()->getBreakOffTime() + RNG::generate(0, _ufo->getRules()->getBreakOffTime()) - 30 * _game->getSavedGame()->getDifficultyCoefficient();\n\t\t{\n\t\t\tint diff = _game->getSavedGame()->getDifficulty();\n\t\t\tauto& custom = _game->getMod()->getUfoEscapeCountdownCoefficients();\n\t\t\tif (custom.size() > (size_t)diff)\n\t\t\t{\n\t\t\t\tescapeCountdown = _ufo->getRules()->getBreakOffTime() + RNG::generate(0, _ufo->getRules()->getBreakOffTime());\n\t\t\t\tescapeCountdown = escapeCountdown * custom[diff] / 100;\n\t\t\t}\n\t\t}\n\t\t_ufo->setEscapeCountdown(std::max(1, escapeCountdown));\n\t}\n\n\tfor (int i = 0; i < _weaponNum; ++i)\n\t{\n\t\tif (_craft->getWeapons()->at(i))\n\t\t{\n\t\t\tif (!_ufoIsAttacking)\n\t\t\t{\n\t\t\t\t_weaponFireInterval[i] = _craft->getWeapons()->at(i)->getRules()->getStandardReload();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_weaponFireInterval[i] = _craft->getWeapons()->at(i)->getRules()->getAggressiveReload();\n\t\t\t}\n\t\t}\n\t}\n\n\t// Set UFO size - going to be moved to Ufo class to implement simultaneous dogfights.\n\t_ufoBlobSize = _ufo->getRules()->getBlobSize();\n\t_ufoSize = std::min(_ufoBlobSize, 4); // yes, maximum supported is 4, not a typo\n\n\t// Get crafts height. Used for damage indication.\n\tfor (int y = 0; y < _craftSprite->getHeight(); ++y)\n\t{\n\t\tfor (int x = 0; x < _craftSprite->getWidth(); ++x)\n\t\t{\n\t\t\tUint8 pixelColor = _craftSprite->getPixel(x, y);\n\t\t\tif (pixelColor >= _colors[CRAFT_MIN] && pixelColor < _colors[CRAFT_MAX])\n\t\t\t{\n\t\t\t\t++_craftHeight;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tdrawCraftDamage();\n\tdrawCraftShield();\n\n\t// Set this as the interception handling UFO shield recharge if no other is doing it\n\tif (_ufo->getShieldRechargeHandle() == 0)\n\t{\n\t\t_ufo->setShieldRechargeHandle(_interceptionNumber);\n\t}\n}\n\n/**\n * Cleans up the dogfight state.\n */\nDogfightState::~DogfightState()\n{\n\tdelete _craftDamageAnimTimer;\n\twhile (!_projectiles.empty())\n\t{\n\t\tdelete _projectiles.back();\n\t\t_projectiles.pop_back();\n\t}\n}\n\n/**\n * Returns true if this is a hunter-killer dogfight. Otherwise returns false.\n * @return Is this a hunter-killer dogfight?\n */\nbool DogfightState::isUfoAttacking() const\n{\n\treturn _ufoIsAttacking;\n}\n\n/**\n * Runs the higher level dogfight functionality.\n */\nvoid DogfightState::think()\n{\n\tif (!_delayedRecolorDone)\n\t{\n\t\t// can't be done in the constructor (recoloring the ammo text doesn't work)\n\t\tfor (int i = 0; i < _weaponNum; ++i)\n\t\t{\n\t\t\tif (_craft->getWeapons()->at(i) && !_weaponEnabled[i])\n\t\t\t{\n\t\t\t\trecolor(i, _weaponEnabled[i]);\n\t\t\t}\n\t\t}\n\t\t_delayedRecolorDone = true;\n\n\t\t// Note: init() is never called for DogfightState, so we'll do it here instead\n\t\t{\n\t\t\tauto& sounds = _game->getMod()->getStartDogfightSounds();\n\t\t\tint soundId = sounds.empty() ? Mod::NO_SOUND : sounds[RNG::generate(0, sounds.size() - 1)];\n\t\t\tif (soundId != Mod::NO_SOUND)\n\t\t\t{\n\t\t\t\tauto* customSound = _game->getMod()->getSound(\"GEO.CAT\", soundId);\n\t\t\t\tcustomSound->play();\n\t\t\t}\n\t\t}\n\t}\n\tif (!_endDogfight)\n\t{\n\t\tupdate();\n\t\t_craftDamageAnimTimer->think(this, 0);\n\t}\n\tif (!_ufoIsAttacking || _ufo->getStatus() == Ufo::LANDED)\n\t{\n\t\tif (!_craft->isInDogfight() || _craft->getDestination() != _ufo || _ufo->getStatus() == Ufo::LANDED)\n\t\t{\n\t\t\tendDogfight();\n\t\t}\n\t}\n}\n\n/**\n * Animates interceptor damage by changing the color and redrawing the image.\n */\nvoid DogfightState::animateCraftDamage()\n{\n\tif (_minimized)\n\t{\n\t\treturn;\n\t}\n\t--_currentCraftDamageColor;\n\tif (_currentCraftDamageColor < _colors[DAMAGE_MIN])\n\t{\n\t\t_currentCraftDamageColor = _colors[DAMAGE_MAX];\n\t}\n\tdrawCraftDamage();\n}\n\n/**\n * Draws interceptor damage according to percentage of HP's left.\n */\nvoid DogfightState::drawCraftDamage()\n{\n\tif (_craft->getDamagePercentage() != 0)\n\t{\n\t\tif (!_craftDamageAnimTimer->isRunning())\n\t\t{\n\t\t\t_craftDamageAnimTimer->start();\n\t\t\tif (_currentCraftDamageColor < _colors[DAMAGE_MIN])\n\t\t\t{\n\t\t\t\t_currentCraftDamageColor = _colors[DAMAGE_MIN];\n\t\t\t}\n\t\t}\n\t\tint damagePercentage = _craft->getDamagePercentage();\n\t\tint rowsToColor = (int)floor((double)_craftHeight * (double)(damagePercentage / 100.));\n\t\tif (rowsToColor == 0)\n\t\t{\n\t\t\treturn;\n\t\t}\n\t\tint rowsColored = 0;\n\t\tbool rowColored = false;\n\t\tfor (int y = 0; y < _damage->getHeight(); ++y)\n\t\t{\n\t\t\trowColored = false;\n\t\t\tfor (int x = 0; x < _damage->getWidth(); ++x)\n\t\t\t{\n\t\t\t\tint craftPixel = _craftSprite->getPixel(x, y);\n\t\t\t\tif (craftPixel != 0)\n\t\t\t\t{\n\t\t\t\t\t_damage->setPixel(x, y, _currentCraftDamageColor);\n\t\t\t\t\trowColored = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (rowColored)\n\t\t\t{\n\t\t\t\t++rowsColored;\n\t\t\t}\n\t\t\tif (rowsColored == rowsToColor)\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n}\n\n/**\n * Draws the craft's shield over it's sprite according to the shield remaining\n */\nvoid DogfightState::drawCraftShield()\n{\n\tif (_craft->getShieldCapacity() == 0)\n\t\treturn;\n\n\tint maxRow = _craftHeight - ((_craftHeight * _craft->getShield()) / _craft->getShieldCapacity());\n\tbool startColoring = false;\n\tfor (int y = _craftShield->getHeight(); y >= 0; --y)\n\t{\n\t\tfor (int x = 0; x < _craftShield->getWidth(); ++x)\n\t\t{\n\t\t\tint craftPixel = _craftSprite->getPixel(x, y);\n\t\t\tif (!startColoring && craftPixel != 0)\n\t\t\t{\n\t\t\t\tmaxRow += (y - _craftHeight + 1);\n\t\t\t\tstartColoring = true;\n\t\t\t}\n\t\t\tif (y < maxRow && craftPixel != 0)\n\t\t\t{\n\t\t\t\t_craftShield->setPixel(x, y, 0);\n\t\t\t}\n\t\t\tif (y >= maxRow && craftPixel != 0)\n\t\t\t{\n\t\t\t\tUint8 shieldColor = std::min(_colors[SHIELD_MAX], _colors[SHIELD_MIN] + (craftPixel - _colors[CRAFT_MIN]));\n\t\t\t\t_craftShield->setPixel(x, y, shieldColor);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Animates the window with a palette effect.\n */\nvoid DogfightState::animate()\n{\n\t// Animate radar waves and other stuff.\n\tfor (int x = 0; x < _window->getWidth(); ++x)\n\t{\n\t\tfor (int y = 0; y < _window->getHeight(); ++y)\n\t\t{\n\t\t\tUint8 radarPixelColor = _window->getPixel(x, y);\n\t\t\tif (radarPixelColor >= _colors[RADAR_MIN] && radarPixelColor < _colors[RADAR_MAX])\n\t\t\t{\n\t\t\t\t++radarPixelColor;\n\t\t\t\tif (radarPixelColor >= _colors[RADAR_MAX])\n\t\t\t\t{\n\t\t\t\t\tradarPixelColor = _colors[RADAR_MIN];\n\t\t\t\t}\n\t\t\t\t_window->setPixel(x, y, radarPixelColor);\n\t\t\t}\n\t\t}\n\t}\n\n\t_battle->clear();\n\n\t// Draw UFO.\n\tif (!_ufo->isDestroyed())\n\t{\n\t\tdrawUfo();\n\t}\n\n\t// Draw projectiles.\n\tfor (auto* cwp : _projectiles)\n\t{\n\t\tdrawProjectile(cwp);\n\t}\n\n\t// Clears text after a while\n\tif (_timeout == 0)\n\t{\n\t\t_txtStatus->setText(\"\");\n\t}\n\telse\n\t{\n\t\t_timeout--;\n\t}\n\n\t// Animate UFO hit.\n\tbool lastHitAnimFrame = false;\n\tif (_animatingHit && _ufo->getHitFrame() > 0)\n\t{\n\t\t_ufo->setHitFrame(_ufo->getHitFrame() - 1);\n\t\tif (_ufo->getHitFrame() == 0)\n\t\t{\n\t\t\t_animatingHit = false;\n\t\t\tlastHitAnimFrame = true;\n\t\t}\n\t}\n\n\t// Animate UFO crash landing.\n\tif (_ufo->isCrashed() && _ufo->getHitFrame() == 0 && !lastHitAnimFrame)\n\t{\n\t\t--_ufoBlobSize;\n\t}\n}\n\n/**\n * Updates all the elements in the dogfight, including ufo movement,\n * weapons fire, projectile movement, ufo escape conditions,\n * craft and ufo destruction conditions, and retaliation mission generation, as applicable.\n */\nvoid DogfightState::update()\n{\n\tbool finalRun = false;\n\t// Check if craft is not low on fuel when window minimized, and\n\t// Check if crafts destination hasn't been changed when window minimized.\n\tif (!_ufoIsAttacking)\n\t{\n\t\tUfo* u = dynamic_cast<Ufo*>(_craft->getDestination());\n\t\tif (u != _ufo || !_craft->isInDogfight() || _craft->getLowFuel() || (_minimized && _ufo->isCrashed()))\n\t\t{\n\t\t\tendDogfight();\n\t\t\treturn;\n\t\t}\n\t}\n\n\tif (!_minimized)\n\t{\n\t\tanimate();\n\t\tif (!_ufo->isCrashed() && !_ufo->isDestroyed() && !_craft->isDestroyed() && !_ufo->getInterceptionProcessed())\n\t\t{\n\t\t\t_ufo->setInterceptionProcessed(true);\n\t\t\tint escapeCounter = _ufo->getEscapeCountdown();\n\t\t\tif (_ufoIsAttacking)\n\t\t\t{\n\t\t\t\tif (_disableDisengage && _ufo->getSoftlockShotCounter() >= _ufo->getRules()->getSoftlockThreshold())\n\t\t\t\t{\n\t\t\t\t\tescapeCounter = 1; // game is in softlock, stop being a hunter-killer and disengage!\n\t\t\t\t}\n\t\t\t\telse if (_ufo->getDamage() > _ufo->getCraftStats().damageMax / 3 && _ufo->getHuntBehavior() != 1)\n\t\t\t\t{\n\t\t\t\t\t// TODO: rethink: unhardcode run away thresholds?\n\t\t\t\t\tif (_craft->getDamage() > _craft->getDamageMax() / 2)\n\t\t\t\t\t{\n\t\t\t\t\t\tescapeCounter = 999; // it's gonna be tight, continue shooting...\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tescapeCounter = 1; // we're badly hurt and xcom isn't, abort immediately!\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tescapeCounter = 999; // we're still ok, continue shooting...\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (escapeCounter > 0)\n\t\t\t{\n\t\t\t\tescapeCounter--;\n\t\t\t\t_ufo->setEscapeCountdown(escapeCounter);\n\t\t\t\t// Check if UFO is breaking off.\n\t\t\t\tif (escapeCounter == 0)\n\t\t\t\t{\n\t\t\t\t\t_ufo->setSpeed(_ufo->getCraftStats().speedMax);\n\t\t\t\t\tif (_ufoIsAttacking && _ufo->isHunterKiller())\n\t\t\t\t\t{\n\t\t\t\t\t\t// stop being a hunter-killer and run away!\n\t\t\t\t\t\t_ufo->resetOriginalDestination(_craft);\n\t\t\t\t\t\t_ufo->setHunterKiller(false);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (_ufo->getFireCountdown() > 0)\n\t\t\t{\n\t\t\t\t_ufo->setFireCountdown(_ufo->getFireCountdown() - 1);\n\t\t\t}\n\t\t}\n\t}\n\t// Crappy craft is chasing UFO.\n\tint speedMinusTractors = std::max(0, _ufo->getSpeed() - _ufo->getTractorBeamSlowdown());\n\tif (speedMinusTractors > _craft->getCraftStats().speedMax)\n\t{\n\t\tif (!_ufoIsAttacking || !_ufo->isHunterKiller())\n\t\t{\n\t\t\t_ufoBreakingOff = true;\n\t\t\tfinalRun = true;\n\t\t\tsetStatus(\"STR_UFO_OUTRUNNING_INTERCEPTOR\");\n\t\t}\n\t}\n\telse\n\t{\n\t\t_ufoBreakingOff = false;\n\t}\n\n\tbool projectileInFlight = false;\n\tif (!_minimized)\n\t{\n\t\tint distanceChange = 0;\n\n\t\t// Update distance\n\t\tif (!_ufoBreakingOff)\n\t\t{\n\t\t\tif (_currentDist < _targetDist && !_ufo->isCrashed() && !_craft->isDestroyed())\n\t\t\t{\n\t\t\t\tdistanceChange = 2 * _craftAccelerationBonus; // disengage speed\n\t\t\t\tif (_currentDist + distanceChange >_targetDist)\n\t\t\t\t{\n\t\t\t\t\tdistanceChange = _targetDist - _currentDist;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (_currentDist > _targetDist && !_ufo->isCrashed() && !_craft->isDestroyed())\n\t\t\t{\n\t\t\t\tdistanceChange = -1 * _pilotApproachSpeedModifier; // engage speed\n\t\t\t}\n\n\t\t\t// don't let the interceptor mystically push or pull its fired projectiles\n\t\t\tfor (auto* cwp : _projectiles)\n\t\t\t{\n\t\t\t\tif (cwp->getGlobalType() != CWPGT_BEAM && cwp->getDirection() == D_UP)\n\t\t\t\t{\n\t\t\t\t\tcwp->setPosition(cwp->getPosition() + distanceChange);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tdistanceChange = 4; // ufo breaking off speed\n\n\t\t\t// UFOs can try to outrun our missiles, don't adjust projectile positions here\n\t\t\t// If UFOs ever fire anything but beams, those positions need to be adjust here though.\n\t\t}\n\n\t\t_currentDist += distanceChange;\n\n\t\tif (_game->getMod()->getShowDogfightDistanceInKm())\n\t\t{\n\t\t\t_txtDistance->setText(tr(\"STR_KILOMETERS\").arg(_currentDist / 8));\n\t\t}\n\t\telse\n\t\t{\n\t\t\tstd::ostringstream ss;\n\t\t\tss << _currentDist;\n\t\t\t_txtDistance->setText(ss.str());\n\t\t}\n\n\t\t// Check and recharge craft shields\n\t\t// Check if the UFO's shields are being handled by an interception window\n\t\tif (_ufo->getShieldRechargeHandle() == 0)\n\t\t{\n\t\t\t_ufo->setShieldRechargeHandle(_interceptionNumber);\n\t\t}\n\n\t\t// UFO shields\n\t\tif ((_ufo->getShield() != 0) && (_interceptionNumber == _ufo->getShieldRechargeHandle()))\n\t\t{\n\t\t\tint total = _ufo->getCraftStats().shieldRecharge / 100;\n\t\t\tif (RNG::percent(_ufo->getCraftStats().shieldRecharge % 100))\n\t\t\t\ttotal++;\n\t\t\t_ufo->setShield(_ufo->getShield() + total);\n\t\t}\n\n\t\t// Player craft shields\n\t\tif (_craft->getShield() != 0)\n\t\t{\n\t\t\tint total = _craft->getCraftStats().shieldRecharge / 100;\n\t\t\tif (RNG::percent(_craft->getCraftStats().shieldRecharge % 100))\n\t\t\t\ttotal++;\n\t\t\tif (total != 0)\n\t\t\t{\n\t\t\t\t_craft->setShield(_craft->getShield() + total);\n\t\t\t\tdrawCraftShield();\n\t\t\t}\n\t\t}\n\n\t\t// Is the craft itself a projectile?\n\t\tif (_missileCraft && !_missileImpact && !_craft->isDestroyed())\n\t\t{\n\t\t\tif (_currentDist <= AGGRESSIVE_DIST) // Note: hard-coded distance, ok\n\t\t\t{\n\t\t\t\t_missileImpact = true;\n\n\t\t\t\t// Missile self-destruct\n\t\t\t\t_craft->setDamage(_craft->getCraftStats().damageMax);\n\t\t\t\tdrawCraftDamage();\n\n\t\t\t\t// Handle UFO shields\n\t\t\t\tint damage = _craft->getRules()->missilePower(); // Note: no randomness :(\n\t\t\t\tint shieldDamage = 0;\n\t\t\t\tif (_ufo->getShield() != 0)\n\t\t\t\t{\n\t\t\t\t\tshieldDamage = damage; // Note: no shield-effectiveness factor\n\t\t\t\t\t// scale down by bleed-through factor\n\t\t\t\t\tdamage = std::max(0, shieldDamage - _ufo->getShield()) * _ufo->getCraftStats().shieldBleedThrough;\n\t\t\t\t\t_ufo->setShield(_ufo->getShield() - shieldDamage);\n\t\t\t\t}\n\t\t\t\tdamage = std::max(0, damage - _ufo->getCraftStats().armor);\n\t\t\t\t_ufo->setDamage(_ufo->getDamage() + damage, _game->getMod());\n\t\t\t\t_state->handleDogfightExperience(); // called after setDamage\n\t\t\t\tif (_ufo->isCrashed())\n\t\t\t\t{\n\t\t\t\t\t_ufo->setShotDownByCraftId(_craft->getUniqueId());\n\t\t\t\t\t_ufo->setSpeed(0);\n\t\t\t\t\t_ufo->setDestination(0);\n\t\t\t\t\t// if the ufo got destroyed here, these no longer apply\n\t\t\t\t\t_ufoBreakingOff = false;\n\t\t\t\t\tfinalRun = false;\n\t\t\t\t\t_end = false;\n\t\t\t\t}\n\t\t\t\tif (_ufo->getHitFrame() == 0)\n\t\t\t\t{\n\t\t\t\t\t_animatingHit = true;\n\t\t\t\t\t_ufo->setHitFrame(3);\n\t\t\t\t}\n\t\t\t\t// How hard was the ufo hit?\n\t\t\t\tif (_ufo->getShield() != 0)\n\t\t\t\t{\n\t\t\t\t\tsetStatus(\"STR_UFO_SHIELD_HIT\");\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif (damage == 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (shieldDamage == 0)\n\t\t\t\t\t\t\tsetStatus(\"STR_UFO_HIT_NO_DAMAGE\");\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tsetStatus(\"STR_UFO_SHIELD_DOWN\");\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tif (damage < _ufo->getCraftStats().damageMax / 2 * _game->getMod()->getUfoGlancingHitThreshold() / 100)\n\t\t\t\t\t\t\tsetStatus(\"STR_UFO_HIT_GLANCING\");\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tsetStatus(\"STR_UFO_HIT\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t_game->getMod()->getSound(\"GEO.CAT\", Mod::UFO_HIT)->play();\n\t\t\t}\n\t\t}\n\n\t\t// Move projectiles and check for hits.\n\t\tfor (auto* p : _projectiles)\n\t\t{\n\t\t\tp->move();\n\t\t\t// Projectiles fired by interceptor.\n\t\t\tif (p->getDirection() == D_UP)\n\t\t\t{\n\t\t\t\t// Projectile reached the UFO - determine if it's been hit.\n\t\t\t\tif (((p->getPosition() >= _currentDist) || (p->getGlobalType() == CWPGT_BEAM && p->toBeRemoved())) && !_ufo->isCrashed() && !p->getMissed())\n\t\t\t\t{\n\t\t\t\t\t// UFO hit.\n\t\t\t\t\tint chanceToHit = (p->getAccuracy() * (100 + 300 / (5 - _ufoSize)) + 100) / 200; // vanilla xcom\n\t\t\t\t\tchanceToHit -= _ufo->getCraftStats().avoidBonus;\n\t\t\t\t\tchanceToHit += _craft->getCraftStats().hitBonus;\n\t\t\t\t\tchanceToHit += _pilotAccuracyBonus;\n\t\t\t\t\tif (RNG::percent(chanceToHit))\n\t\t\t\t\t{\n\t\t\t\t\t\t// Formula delivered by Volutar, altered by Extended version.\n\t\t\t\t\t\tint power = p->getDamage() * (_craft->getCraftStats().powerBonus + 100) / 100;\n\n\t\t\t\t\t\tint damage = 0;\n\t\t\t\t\t\tif (p->getDamageItem())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// unified damage formula\n\t\t\t\t\t\t\tdamage = p->getDamageItem()->getDamageType()->getRandomDamage(power);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// vanilla dmg formula: 50-100%\n\t\t\t\t\t\t\tdamage = RNG::generate(power / 2, power);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Handle UFO shields\n\t\t\t\t\t\tint shieldDamage = 0;\n\t\t\t\t\t\tif (_ufo->getShield() != 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tshieldDamage = damage * p->getShieldDamageModifier() / 100;\n\t\t\t\t\t\t\tif (p->getShieldDamageModifier() == 0)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tdamage = 0;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// scale down by bleed-through factor and scale up by shield-effectiveness factor\n\t\t\t\t\t\t\t\tdamage = std::max(0, shieldDamage - _ufo->getShield()) * _ufo->getCraftStats().shieldBleedThrough / p->getShieldDamageModifier();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t_ufo->setShield(_ufo->getShield() - shieldDamage);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tdamage = std::max(0, damage - _ufo->getCraftStats().armor);\n\t\t\t\t\t\t_ufo->setDamage(_ufo->getDamage() + damage, _game->getMod());\n\t\t\t\t\t\t_state->handleDogfightExperience(); // called after setDamage\n\t\t\t\t\t\tif (_ufo->isCrashed())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_ufo->setShotDownByCraftId(_craft->getUniqueId());\n\t\t\t\t\t\t\t_ufo->setSpeed(0);\n\t\t\t\t\t\t\t_ufo->setDestination(0);\n\t\t\t\t\t\t\t// if the ufo got destroyed here, these no longer apply\n\t\t\t\t\t\t\t_ufoBreakingOff = false;\n\t\t\t\t\t\t\tfinalRun = false;\n\t\t\t\t\t\t\t_end = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (_ufo->getHitFrame() == 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_animatingHit = true;\n\t\t\t\t\t\t\t_ufo->setHitFrame(3);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// How hard was the ufo hit?\n\t\t\t\t\t\tif (_ufo->getShield() != 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsetStatus(\"STR_UFO_SHIELD_HIT\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (damage == 0)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (shieldDamage == 0)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tsetStatus(\"STR_UFO_HIT_NO_DAMAGE\");\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tsetStatus(\"STR_UFO_SHIELD_DOWN\");\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (damage < _ufo->getCraftStats().damageMax / 2 * _game->getMod()->getUfoGlancingHitThreshold() / 100)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tsetStatus(\"STR_UFO_HIT_GLANCING\");\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tsetStatus(\"STR_UFO_HIT\");\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t_game->getMod()->getSound(\"GEO.CAT\", Mod::UFO_HIT)->play();\n\t\t\t\t\t\tp->remove();\n\t\t\t\t\t}\n\t\t\t\t\t// Missed.\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tif (p->getGlobalType() == CWPGT_BEAM)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tp->remove();\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tp->setMissed(true);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Check if projectile passed it's maximum range.\n\t\t\t\tif (p->getGlobalType() == CWPGT_MISSILE && p->getPosition() / 8 >= p->getRange())\n\t\t\t\t{\n\t\t\t\t\tp->remove();\n\t\t\t\t}\n\t\t\t\telse if (!_ufo->isCrashed())\n\t\t\t\t{\n\t\t\t\t\tprojectileInFlight = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Projectiles fired by UFO.\n\t\t\telse if (p->getDirection() == D_DOWN)\n\t\t\t{\n\t\t\t\tif (p->getGlobalType() == CWPGT_MISSILE || (p->getGlobalType() == CWPGT_BEAM && p->toBeRemoved()))\n\t\t\t\t{\n\t\t\t\t\tint chancetoHit = p->getAccuracy(); // vanilla xcom\n\t\t\t\t\tchancetoHit -= _craft->getCraftStats().avoidBonus;\n\t\t\t\t\tchancetoHit += _ufo->getCraftStats().hitBonus;\n\t\t\t\t\tchancetoHit -= _pilotDodgeBonus;\n\t\t\t\t\t// evasive maneuvers\n\t\t\t\t\tif (_ufoIsAttacking && _mode == _btnCautious)\n\t\t\t\t\t{\n\t\t\t\t\t\t// HK's chance to hit is halved, but craft's reload time is doubled too\n\t\t\t\t\t\tchancetoHit = chancetoHit / 2;\n\t\t\t\t\t}\n\t\t\t\t\tif (RNG::percent(chancetoHit) || _selfDestructPressed)\n\t\t\t\t\t{\n\t\t\t\t\t\t// Formula delivered by Volutar, altered by Extended version.\n\t\t\t\t\t\tint power = p->getDamage() * (_ufo->getCraftStats().powerBonus + 100) / 100;\n\t\t\t\t\t\tint damage = RNG::generate(0, power);\n\n\t\t\t\t\t\tif (_craft->getShield() != 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tint shieldBleedThroughDamage = std::max(0, damage - _craft->getShield()) * _craft->getCraftStats().shieldBleedThrough / 100;\n\t\t\t\t\t\t\t_craft->setShield(_craft->getShield() - damage);\n\t\t\t\t\t\t\tdamage = shieldBleedThroughDamage;\n\t\t\t\t\t\t\tdrawCraftShield();\n\t\t\t\t\t\t\tsetStatus(\"STR_INTERCEPTOR_SHIELD_HIT\");\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tdamage = std::max(0, damage - _craft->getCraftStats().armor);\n\n\t\t\t\t\t\t// if a totally crappy HK is attacking a completely defenseless craft, avoid endless fight\n\t\t\t\t\t\tif (_selfDestructPressed)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tdamage = _craft->getCraftStats().damageMax;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (damage)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_craft->setDamage(_craft->getDamage() + damage);\n\t\t\t\t\t\t\tdrawCraftDamage();\n\t\t\t\t\t\t\tif (_missileCraft)\n\t\t\t\t\t\t\t\tsetStatus(\"STR_MISSILE_DAMAGED\");\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tsetStatus(\"STR_INTERCEPTOR_DAMAGED\");\n\t\t\t\t\t\t\t_game->getMod()->getSound(\"GEO.CAT\", Mod::INTERCEPTOR_HIT)->play(); //10\n\t\t\t\t\t\t\tif (_mode == _btnCautious && _craft->getDamagePercentage() >= 50 && !_ufoIsAttacking)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t_targetDist = STANDOFF_DIST;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tp->remove();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Remove projectiles that hit or missed their target.\n\t\tCollections::deleteIf(_projectiles, _projectiles.size(),\n\t\t\t[&](CraftWeaponProjectile* cwp)\n\t\t\t{\n\t\t\t\treturn cwp->toBeRemoved() == true || (cwp->getMissed() == true && cwp->getPosition() <= 0);\n\t\t\t}\n\t\t);\n\n\t\t// Check if the situation is hopeless for the craft\n\t\tif (_disableDisengage && !_craftIsDefenseless && !_missileCraft)\n\t\t{\n\t\t\tif (_projectiles.empty())\n\t\t\t{\n\t\t\t\tbool hasNoAmmo = true;\n\t\t\t\tfor (auto* cw : *_craft->getWeapons())\n\t\t\t\t{\n\t\t\t\t\tif (cw && cw->getAmmo() > 0)\n\t\t\t\t\t{\n\t\t\t\t\t\thasNoAmmo = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// no projectiles in the air and no ammo left\n\t\t\t\tif (hasNoAmmo)\n\t\t\t\t{\n\t\t\t\t\t_craftIsDefenseless = true;\n\n\t\t\t\t\t// self-destruct button\n\t\t\t\t\tint offset = _game->getMod()->getInterface(\"dogfight\")->getElement(\"minimizeButtonDummy\")->TFTDMode ? 1 : 0;\n\t\t\t\t\t_btnMinimize->drawRect(1 + offset, 1, _btnMinimize->getWidth() - 2 - offset, _btnMinimize->getHeight() - 2, _colors[DAMAGE_MAX]);\n\t\t\t\t\t_btnMinimize->setVisible(true);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Handle weapons and craft distance.\n\t\tfor (int i = 0; i < _weaponNum; ++i)\n\t\t{\n\t\t\tCraftWeapon *w = _craft->getWeapons()->at(i);\n\t\t\tif (w == 0 || _missileCraft)\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tint wTimer = _weaponFireCountdown[i];\n\n\t\t\t// Handle weapon firing\n\t\t\tif (wTimer == 0 && _currentDist <= w->getRules()->getRange() * 8 && w->getAmmo() > 0 && _mode != _btnStandoff\n\t\t\t\t&& _mode != _btnDisengage && !_ufo->isCrashed() && !_craft->isDestroyed())\n\t\t\t{\n\t\t\t\tif (_weaponEnabled[i])\n\t\t\t\t{\n\t\t\t\t\tfireWeapon(i);\n\t\t\t\t\tprojectileInFlight = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (wTimer > 0)\n\t\t\t{\n\t\t\t\t--_weaponFireCountdown[i];\n\t\t\t}\n\n\t\t\t// Handle craft tractor beams\n\t\t\tif (w->getRules()->getTractorBeamPower() != 0)\n\t\t\t{\n\t\t\t\tif (_currentDist <= w->getRules()->getRange() * 8 && _mode != _btnStandoff\n\t\t\t\t\t&& _mode != _btnDisengage && !_ufo->isCrashed() && !_craft->isDestroyed()\n\t\t\t\t\t&& _weaponEnabled[i])\n\t\t\t\t{\n\t\t\t\t\tif (!_tractorLockedOn[i])\n\t\t\t\t\t{\n\t\t\t\t\t\t_tractorLockedOn[i] = true;\n\t\t\t\t\t\tint tractorBeamSlowdown = _ufo->getTractorBeamSlowdown();\n\t\t\t\t\t\ttractorBeamSlowdown += w->getRules()->getTractorBeamPower() * _game->getMod()->getUfoTractorBeamSizeModifier(_ufoSize) / 100;\n\t\t\t\t\t\t_ufo->setTractorBeamSlowdown(tractorBeamSlowdown);\n\t\t\t\t\t\tsetStatus(\"STR_TRACTOR_BEAM_ENGAGED\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif (_tractorLockedOn[i])\n\t\t\t\t\t{\n\t\t\t\t\t\t_tractorLockedOn[i] = false;\n\t\t\t\t\t\tint tractorBeamSlowdown = _ufo->getTractorBeamSlowdown();\n\t\t\t\t\t\ttractorBeamSlowdown -= w->getRules()->getTractorBeamPower() * _game->getMod()->getUfoTractorBeamSizeModifier(_ufoSize) / 100;\n\t\t\t\t\t\t_ufo->setTractorBeamSlowdown(tractorBeamSlowdown);\n\t\t\t\t\t\tsetStatus(\"STR_TRACTOR_BEAM_DISENGAGED\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (w->getAmmo() == 0 && !projectileInFlight && !_craft->isDestroyed())\n\t\t\t{\n\t\t\t\t// Handle craft distance according to option set by user and available ammo.\n\t\t\t\tif (_mode == _btnCautious && !_ufoIsAttacking)\n\t\t\t\t{\n\t\t\t\t\tminimumDistance();\n\t\t\t\t}\n\t\t\t\telse if (_mode == _btnStandard)\n\t\t\t\t{\n\t\t\t\t\tmaximumDistance();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Handle UFO firing.\n\t\tif (_currentDist <= _ufo->getRules()->getWeaponRange() * 8 && !_ufo->isCrashed() && !_craft->isDestroyed())\n\t\t{\n\t\t\tif (_ufo->getShootingAt() == 0)\n\t\t\t{\n\t\t\t\t_ufo->setShootingAt(_interceptionNumber);\n\t\t\t}\n\t\t\tif (_ufo->getShootingAt() == _interceptionNumber)\n\t\t\t{\n\t\t\t\tif (_ufo->getFireCountdown() == 0)\n\t\t\t\t{\n\t\t\t\t\tufoFireWeapon();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse if (_ufo->getShootingAt() == _interceptionNumber)\n\t\t{\n\t\t\t_ufo->setShootingAt(0);\n\t\t}\n\t}\n\n\t// Check when battle is over.\n\tif (_end == true && (((_currentDist > 640 || _minimized) && (_mode == _btnDisengage || _ufoBreakingOff == true)) || (_timeout == 0 && (_ufo->isCrashed() || _craft->isDestroyed()))))\n\t{\n\t\tif (_ufoBreakingOff)\n\t\t{\n\t\t\t_ufo->move();\n\t\t\t// TODO: rethink: give hunter-killers opportunity to escape?\n\t\t\tif (!_ufoIsAttacking)\n\t\t\t{\n\t\t\t\t_craft->setDestination(_ufo);\n\t\t\t}\n\t\t}\n\t\tif (!_destroyCraft && (_destroyUfo || _mode == _btnDisengage))\n\t\t{\n\t\t\t// keep original target if attacked by a HK (and didn't disengage manually)\n\t\t\tbool keepOriginalTarget = _ufoIsAttacking && _craft->getDestination() != _ufo;\n\t\t\tif (!keepOriginalTarget || _mode == _btnDisengage)\n\t\t\t{\n\t\t\t\t_craft->returnToBase();\n\t\t\t}\n\n\t\t\t// Need to give the craft at least one step advantage over the hunter-killer (to be able to escape)\n\t\t\tif (_ufoIsAttacking)\n\t\t\t{\n\t\t\t\tbool returnedToBase = _craft->think();\n\t\t\t\tif (returnedToBase)\n\t\t\t\t{\n\t\t\t\t\t_game->getSavedGame()->stopHuntingXcomCraft(_craft); // hiding in the base is good enough, obviously\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (_ufo->isCrashed())\n\t\t{\n\t\t\tfor (auto* follower : _ufo->getCraftFollowers())\n\t\t\t{\n\t\t\t\tif (follower->getNumTotalUnits() == 0 || !follower->getRules()->getAllowLanding())\n\t\t\t\t{\n\t\t\t\t\tfollower->returnToBase();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tendDogfight();\n\t}\n\n\tif (_currentDist > 640 && _ufoBreakingOff)\n\t{\n\t\tfinalRun = true;\n\t}\n\n\tif (!_end)\n\t{\n\t\tif (_endCraftHandled)\n\t\t{\n\t\t\tfinalRun = true;\n\t\t}\n\t\telse if (_craft->isDestroyed())\n\t\t{\n\t\t\t// End dogfight if craft is destroyed.\n\t\t\tif (_missileCraft)\n\t\t\t{\n\t\t\t\tif (_missileImpact)\n\t\t\t\t{\n\t\t\t\t\t// Empty by design\n\t\t\t\t\t// Let's keep showing how much damage was done to the UFO (and/or shields)\n\t\t\t\t\t// No need to say the missile impacted/self-destructed, it's obvious\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tsetStatus(\"STR_MISSILE_DESTROYED\");\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tsetStatus(\"STR_INTERCEPTOR_DESTROYED\");\n\t\t\t}\n\t\t\tif (_ufoIsAttacking)\n\t\t\t{\n\t\t\t\t// Note: this was moved to GeoscapeState.cpp, as it is not 100% reliable here\n\t\t\t\t//_craft->evacuateCrew(_game->getMod());\n\t\t\t}\n\t\t\t_timeout += 30;\n\t\t\t_game->getMod()->getSound(\"GEO.CAT\", Mod::INTERCEPTOR_EXPLODE)->play();\n\t\t\tfinalRun = true;\n\t\t\t_destroyCraft = true;\n\t\t\t_endCraftHandled = true;\n\t\t\t_ufo->setShootingAt(0);\n\t\t}\n\n\t\tif (_endUfoHandled)\n\t\t{\n\t\t\tfinalRun = true;\n\t\t}\n\t\telse if (_ufo->isCrashed())\n\t\t{\n\t\t\t// End dogfight if UFO is crashed or destroyed.\n\t\t\t_endUfoHandled = true;\n\n\t\t\tif (_ufo->getShotDownByCraftId() == _craft->getUniqueId())\n\t\t\t{\n\t\t\t\tAlienRace *race = _game->getMod()->getAlienRace(_ufo->getAlienRace());\n\t\t\t\tAlienMission *mission = _ufo->getMission();\n\t\t\t\tmission->ufoShotDown(*_ufo);\n\t\t\t\t// Check for retaliation trigger.\n\t\t\t\tint retaliationOdds = mission->getRules().getRetaliationOdds();\n\t\t\t\tif (retaliationOdds == -1)\n\t\t\t\t{\n\t\t\t\t\tretaliationOdds = 100 - (4 * (24 - _game->getSavedGame()->getDifficultyCoefficient()) - race->getRetaliationAggression());\n\t\t\t\t\t{\n\t\t\t\t\t\tint diff = _game->getSavedGame()->getDifficulty();\n\t\t\t\t\t\tauto& custom = _game->getMod()->getRetaliationTriggerOdds();\n\t\t\t\t\t\tif (custom.size() > (size_t)diff)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tretaliationOdds = custom[diff] + race->getRetaliationAggression();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Have mercy on beginners\n\t\t\t\tif (_game->getSavedGame()->getMonthsPassed() < Mod::DIFFICULTY_BASED_RETAL_DELAY[_game->getSavedGame()->getDifficulty()])\n\t\t\t\t{\n\t\t\t\t\tretaliationOdds = 0;\n\t\t\t\t}\n\n\t\t\t\tif (RNG::percent(retaliationOdds))\n\t\t\t\t{\n\t\t\t\t\t// Spawn retaliation mission.\n\t\t\t\t\tstd::string targetRegion;\n\t\t\t\t\tint retaliationUfoMissionRegionOdds = 50 - 6 * _game->getSavedGame()->getDifficultyCoefficient();\n\t\t\t\t\t{\n\t\t\t\t\t\tint diff = _game->getSavedGame()->getDifficulty();\n\t\t\t\t\t\tauto& custom = _game->getMod()->getRetaliationBaseRegionOdds();\n\t\t\t\t\t\tif (custom.size() > (size_t)diff)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tretaliationUfoMissionRegionOdds = 100 - custom[diff];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (RNG::percent(retaliationUfoMissionRegionOdds))\n\t\t\t\t\t{\n\t\t\t\t\t\t// Attack on UFO's mission region\n\t\t\t\t\t\ttargetRegion = _ufo->getMission()->getRegion();\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// Try to find and attack the originating base.\n\t\t\t\t\t\ttargetRegion = _game->getSavedGame()->locateRegion(*_craft->getBase())->getRules()->getType();\n\t\t\t\t\t\t// TODO: If the base is removed, the mission is canceled.\n\t\t\t\t\t}\n\t\t\t\t\t// Difference from original: No retaliation until final UFO lands (Original: Is spawned).\n\t\t\t\t\tif (!_game->getSavedGame()->findAlienMission(targetRegion, OBJECTIVE_RETALIATION, race))\n\t\t\t\t\t{\n\t\t\t\t\t\tauto* retalWeights = race->retaliationMissionWeights(_game->getSavedGame()->getMonthsPassed());\n\t\t\t\t\t\tstd::string retalMission = retalWeights ? retalWeights->choose() : \"\";\n\t\t\t\t\t\tconst RuleAlienMission *rule = _game->getMod()->getAlienMission(retalMission, false);\n\t\t\t\t\t\tif (!rule)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\trule = _game->getMod()->getRandomMission(OBJECTIVE_RETALIATION, _game->getSavedGame()->getMonthsPassed());\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (rule)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tAlienMission *newMission = new AlienMission(*rule);\n\t\t\t\t\t\t\tnewMission->setId(_game->getSavedGame()->getId(\"ALIEN_MISSIONS\"));\n\t\t\t\t\t\t\tnewMission->setRegion(targetRegion, *_game->getMod());\n\t\t\t\t\t\t\tnewMission->setRace(_ufo->getAlienRace());\n\t\t\t\t\t\t\tnewMission->start(*_game, *_state->getGlobe(), newMission->getRules().getWave(0).spawnTimer); // fixed delay for first scout\n\t\t\t\t\t\t\t_game->getSavedGame()->getAlienMissions().push_back(newMission);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (_ufo->isDestroyed())\n\t\t\t{\n\t\t\t\tif (_ufo->getShotDownByCraftId() == _craft->getUniqueId())\n\t\t\t\t{\n\t\t\t\t\tfor (auto* country : *_game->getSavedGame()->getCountries())\n\t\t\t\t\t{\n\t\t\t\t\t\tif (country->getRules()->insideCountry(_ufo->getLongitude(), _ufo->getLatitude()))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcountry->addActivityXcom(_ufo->getRules()->getScore()*2);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tfor (auto* region : *_game->getSavedGame()->getRegions())\n\t\t\t\t\t{\n\t\t\t\t\t\tif (region->getRules()->insideRegion(_ufo->getLongitude(), _ufo->getLatitude()))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tregion->addActivityXcom(_ufo->getRules()->getScore()*2);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tsetStatus(\"STR_UFO_DESTROYED\");\n\t\t\t\t\t_game->getMod()->getSound(\"GEO.CAT\", Mod::UFO_EXPLODE)->play(); //11\n\t\t\t\t}\n\t\t\t\t_destroyUfo = true;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (_ufo->getShotDownByCraftId() == _craft->getUniqueId())\n\t\t\t\t{\n\t\t\t\t\tsetStatus(\"STR_UFO_CRASH_LANDS\");\n\t\t\t\t\t_game->getMod()->getSound(\"GEO.CAT\", Mod::UFO_CRASH)->play(); //10\n\t\t\t\t\tfor (auto* country : *_game->getSavedGame()->getCountries())\n\t\t\t\t\t{\n\t\t\t\t\t\tif (country->getRules()->insideCountry(_ufo->getLongitude(), _ufo->getLatitude()))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcountry->addActivityXcom(_ufo->getRules()->getScore());\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tfor (auto* region : *_game->getSavedGame()->getRegions())\n\t\t\t\t\t{\n\t\t\t\t\t\tif (region->getRules()->insideRegion(_ufo->getLongitude(), _ufo->getLatitude()))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tregion->addActivityXcom(_ufo->getRules()->getScore());\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbool survived = true;\n\t\t\t\tbool fakeUnderwaterTexture = _state->getGlobe()->insideFakeUnderwaterTexture(_ufo->getLongitude(), _ufo->getLatitude());\n\t\t\t\tif (!_state->getGlobe()->insideLand(_ufo->getLongitude(), _ufo->getLatitude()))\n\t\t\t\t{\n\t\t\t\t\tsurvived = false; // destroyed on real water\n\t\t\t\t}\n\t\t\t\telse if (fakeUnderwaterTexture)\n\t\t\t\t{\n\t\t\t\t\tif (RNG::percent(_ufo->getRules()->getSplashdownSurvivalChance()))\n\t\t\t\t\t{\n\t\t\t\t\t\tsetStatus(\"STR_UFO_SURVIVED_SPLASHDOWN\");\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tsurvived = false; // destroyed on fake water\n\t\t\t\t\t\tsetStatus(\"STR_UFO_DESTROYED_BY_SPLASHDOWN\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!survived)\n\t\t\t\t{\n\t\t\t\t\t_ufo->setStatus(Ufo::DESTROYED);\n\t\t\t\t\t_destroyUfo = true;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t_ufo->setSecondsRemaining(RNG::generate(24, 96)*3600);\n\t\t\t\t\t_ufo->setAltitude(\"STR_GROUND\");\n\t\t\t\t\tif (_ufo->getCrashId() == 0)\n\t\t\t\t\t{\n\t\t\t\t\t\t_ufo->setCrashId(_game->getSavedGame()->getId(\"STR_CRASH_SITE\"));\n\t\t\t\t\t\tif (_ufo->isHunterKiller())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// stop being a hunter-killer\n\t\t\t\t\t\t\t_ufo->resetOriginalDestination(_craft);\n\t\t\t\t\t\t\t_ufo->setHunterKiller(false);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t_timeout += 30;\n\t\t\tif (_ufo->getShotDownByCraftId() != _craft->getUniqueId())\n\t\t\t{\n\t\t\t\t_timeout += 50;\n\t\t\t\t_ufo->setHitFrame(3);\n\t\t\t}\n\t\t\tfinalRun = true;\n\n\t\t\tif (_ufo->getStatus() == Ufo::LANDED)\n\t\t\t{\n\t\t\t\t_timeout += 30;\n\t\t\t\tfinalRun = true;\n\t\t\t\t_ufo->setShootingAt(0);\n\t\t\t}\n\t\t}\n\t\telse if (_ufo->getCraftStats().speedMax - _ufo->getTractorBeamSlowdown() == 0) // UFO brought down by tractor beam\n\t\t{\n\t\t\t_endUfoHandled = true;\n\n\t\t\tbool survived = true;\n\t\t\tif (!_state->getGlobe()->insideLand(_ufo->getLongitude(), _ufo->getLatitude()))\n\t\t\t{\n\t\t\t\tsurvived = false; // destroyed on real water\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tbool fakeUnderwaterTexture = _state->getGlobe()->insideFakeUnderwaterTexture(_ufo->getLongitude(), _ufo->getLatitude());\n\t\t\t\tif (fakeUnderwaterTexture && !RNG::percent(_ufo->getRules()->getSplashdownSurvivalChance()))\n\t\t\t\t{\n\t\t\t\t\tsurvived = false; // destroyed on fake water\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (_ufo->getRules()->isUnmanned())\n\t\t\t{\n\t\t\t\tsurvived = false; // unmanned UFOs (drones, missiles, etc.) can't be forced to land\n\t\t\t}\n\t\t\tif (!survived) // Brought it down over water (and didn't survive splashdown)\n\t\t\t{\n\t\t\t\tfinalRun = true;\n\t\t\t\t_ufo->setDamage(_ufo->getCraftStats().damageMax, _game->getMod());\n\t\t\t\t_state->handleDogfightExperience(); // called after setDamage\n\t\t\t\t_ufo->setShotDownByCraftId(_craft->getUniqueId());\n\t\t\t\t_ufo->setSpeed(0);\n\t\t\t\t_ufo->setStatus(Ufo::DESTROYED);\n\t\t\t\t_destroyUfo = true;\n\t\t\t\tfor (auto* country : *_game->getSavedGame()->getCountries())\n\t\t\t\t{\n\t\t\t\t\tif (country->getRules()->insideCountry(_ufo->getLongitude(), _ufo->getLatitude()))\n\t\t\t\t\t{\n\t\t\t\t\t\tcountry->addActivityXcom(_ufo->getRules()->getScore());\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfor (auto* region : *_game->getSavedGame()->getRegions())\n\t\t\t\t{\n\t\t\t\t\tif (region->getRules()->insideRegion(_ufo->getLongitude(), _ufo->getLatitude()))\n\t\t\t\t\t{\n\t\t\t\t\t\tregion->addActivityXcom(_ufo->getRules()->getScore());\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse // Brought it down over land (or survived splashdown)\n\t\t\t{\n\t\t\t\tfinalRun = true;\n\t\t\t\t_ufo->setSecondsRemaining(RNG::generate(30, 120)*60);\n\t\t\t\t_ufo->setShootingAt(0);\n\t\t\t\t_ufo->setStatus(Ufo::LANDED);\n\t\t\t\t_ufo->setAltitude(\"STR_GROUND\");\n\t\t\t\t_ufo->setSpeed(0);\n\t\t\t\t_ufo->setTractorBeamSlowdown(0);\n\t\t\t\tif (_ufo->getLandId() == 0)\n\t\t\t\t{\n\t\t\t\t\t_ufo->setLandId(_game->getSavedGame()->getId(\"STR_LANDING_SITE\"));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (!projectileInFlight && finalRun)\n\t{\n\t\t_end = true;\n\t}\n}\n\n/**\n * Fires a shot from the first weapon\n * equipped on the craft.\n */\nvoid DogfightState::fireWeapon(int i)\n{\n\tCraftWeapon *w1 = _craft->getWeapons()->at(i);\n\tif (w1->setAmmo(w1->getAmmo() - 1))\n\t{\n\t\t_weaponFireCountdown[i] = _weaponFireInterval[i];\n\n\t\tstd::ostringstream ss;\n\t\tss << w1->getAmmo();\n\t\t_txtAmmo[i]->setText(ss.str());\n\n\t\tCraftWeaponProjectile *p = w1->fire();\n\t\tp->setDirection(D_UP);\n\t\tp->setHorizontalPosition((i % 2 ? HP_RIGHT : HP_LEFT) * (1 + 2 * (i / 2)));\n\t\t_projectiles.push_back(p);\n\n\t\t_game->getMod()->getSound(\"GEO.CAT\", w1->getRules()->getSound())->play();\n\t\t_firedAtLeastOnce = true;\n\t}\n}\n\n/**\n *\tEach time a UFO will try to fire it's cannons\n *\ta calculation is made. There's only 10% chance\n *\tthat it will actually fire.\n */\nvoid DogfightState::ufoFireWeapon()\n{\n\tint fireCountdown = std::max(1, (_ufo->getRules()->getWeaponReload() - 2 * _game->getSavedGame()->getDifficultyCoefficient()));\n\t{\n\t\tint diff = _game->getSavedGame()->getDifficulty();\n\t\tauto& custom = _game->getMod()->getUfoFiringRateCoefficients();\n\t\tif (custom.size() > (size_t)diff)\n\t\t{\n\t\t\tfireCountdown = std::max(1, _ufo->getRules()->getWeaponReload() * custom[diff] / 100);\n\t\t}\n\t}\n\t_ufo->setFireCountdown(RNG::generate(0, fireCountdown) + fireCountdown);\n\n\tsetStatus(\"STR_UFO_RETURN_FIRE\");\n\tCraftWeaponProjectile *p = new CraftWeaponProjectile(nullptr);\n\tp->setType(CWPT_PLASMA_BEAM);\n\tp->setAccuracy(60);\n\tp->setDamage(_ufo->getRules()->getWeaponPower());\n\tp->setDirection(D_DOWN);\n\tp->setHorizontalPosition(HP_CENTER);\n\tp->setPosition(_currentDist - (_ufo->getRules()->getRadius() / 2));\n\t_projectiles.push_back(p);\n\tif (_ufoIsAttacking && _disableDisengage)\n\t{\n\t\t_ufo->increaseSoftlockShotCounter();\n\t}\n\n\tif (_ufo->getRules()->getFireSound() == -1)\n\t{\n\t\t_game->getMod()->getSound(\"GEO.CAT\", Mod::UFO_FIRE)->play();\n\t}\n\telse\n\t{\n\t\t_game->getMod()->getSound(\"GEO.CAT\", _ufo->getRules()->getFireSound())->play();\n\t}\n}\n\n/**\n * Sets the craft to the minimum distance\n * required to fire a weapon.\n */\nvoid DogfightState::minimumDistance()\n{\n\tint max = 0;\n\tfor (auto* cw : *_craft->getWeapons())\n\t{\n\t\tif (cw == 0)\n\t\t\tcontinue;\n\t\tif (cw->getRules()->getRange() > max && cw->getAmmo() > 0)\n\t\t{\n\t\t\tmax = cw->getRules()->getRange();\n\t\t}\n\t}\n\tif (max == 0)\n\t{\n\t\t_targetDist = STANDOFF_DIST;\n\t}\n\telse\n\t{\n\t\t_targetDist = max * 8;\n\t}\n}\n\n/**\n * Sets the craft to the maximum distance\n * required to fire a weapon.\n */\nvoid DogfightState::maximumDistance()\n{\n\tint min = 1000;\n\tfor (auto* cw : *_craft->getWeapons())\n\t{\n\t\tif (cw == 0)\n\t\t\tcontinue;\n\t\tif (cw->getRules()->getRange() < min && cw->getAmmo() > 0)\n\t\t{\n\t\t\tmin = cw->getRules()->getRange();\n\t\t}\n\t}\n\tif (_ufoIsAttacking)\n\t{\n\t\t// If the UFO is actively hunting us, consider its weapon range too\n\t\tif (_ufo->getRules()->getWeaponRange() > 0 && _ufo->getRules()->getWeaponRange() < min)\n\t\t{\n\t\t\tmin = _ufo->getRules()->getWeaponRange();\n\t\t}\n\t}\n\tif (min == 1000)\n\t{\n\t\t_targetDist = STANDOFF_DIST;\n\t}\n\telse\n\t{\n\t\t_targetDist = min * 8;\n\t}\n}\n\n/**\n * Sets the craft to the distance relevant for aggressive attack.\n */\nvoid DogfightState::aggressiveDistance()\n{\n\tmaximumDistance();\n\tif (_targetDist > AGGRESSIVE_DIST)\n\t{\n\t\t_targetDist = AGGRESSIVE_DIST;\n\t}\n}\n\n/**\n * Updates the status text and restarts\n * the text timeout counter.\n * @param status New status text.\n */\nvoid DogfightState::setStatus(const std::string &status)\n{\n\t_txtStatus->setText(tr(status));\n\t_timeout = 50;\n}\n\n/**\n * Minimizes the dogfight window.\n * @param action Pointer to an action.\n */\nvoid DogfightState::btnMinimizeClick(Action *)\n{\n\tif (_craftIsDefenseless)\n\t{\n\t\t_selfDestructPressed = !_selfDestructPressed;\n\t\tif (_selfDestructPressed)\n\t\t\tsetStatus(\"STR_SELF_DESTRUCT_ACTIVATED\");\n\t\telse\n\t\t\tsetStatus(\"STR_SELF_DESTRUCT_CANCELLED\");\n\t\tint offset = _game->getMod()->getInterface(\"dogfight\")->getElement(\"minimizeButtonDummy\")->TFTDMode ? 1 : 0;\n\t\tint color = _selfDestructPressed ? DAMAGE_MIN : DAMAGE_MAX;\n\t\t_btnMinimize->drawRect(1 + offset, 1, _btnMinimize->getWidth() - 2 - offset, _btnMinimize->getHeight() - 2, _colors[color]);\n\t\treturn;\n\t}\n\n\tif (!_ufo->isCrashed() && !_craft->isDestroyed() && !_ufoBreakingOff)\n\t{\n\t\tif (_currentDist >= STANDOFF_DIST)\n\t\t{\n\t\t\tsetMinimized(true);\n\t\t\t_ufo->setShieldRechargeHandle(0);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tsetStatus(\"STR_MINIMISE_AT_STANDOFF_RANGE_ONLY\");\n\t\t}\n\t}\n}\n\n/**\n * Switches to Standoff mode (maximum range).\n * @param action Pointer to an action.\n */\nvoid DogfightState::btnStandoffPress(Action *)\n{\n\tif (!_ufo->isCrashed() && !_craft->isDestroyed() && !_ufoBreakingOff)\n\t{\n\t\t_end = false;\n\t\tsetStatus(\"STR_STANDOFF\");\n\t\t_targetDist = STANDOFF_DIST;\n\t}\n}\n\nvoid DogfightState::btnStandoffRightPress(Action *)\n{\n\t_state->handleDogfightMultiAction(0);\n}\n\nvoid DogfightState::btnStandoffSimulateLeftPress(Action *action)\n{\n\tif (_btnStandoff->getVisible())\n\t{\n\t\t_btnStandoff->mousePress(action, this);\n\t}\n}\n\n/**\n * Switches to Cautious mode (maximum weapon range).\n * @param action Pointer to an action.\n */\nvoid DogfightState::btnCautiousPress(Action *)\n{\n\tif (!_ufo->isCrashed() && !_craft->isDestroyed() && !_ufoBreakingOff)\n\t{\n\t\t_end = false;\n\t\tif (!_ufoIsAttacking)\n\t\t{\n\t\t\tsetStatus(\"STR_CAUTIOUS_ATTACK\");\n\t\t\tfor (int i = 0; i < _weaponNum; ++i)\n\t\t\t{\n\t\t\t\tCraftWeapon* w = _craft->getWeapons()->at(i);\n\t\t\t\tif (w != 0)\n\t\t\t\t{\n\t\t\t\t\t_weaponFireInterval[i] = w->getRules()->getCautiousReload();\n\t\t\t\t}\n\t\t\t}\n\t\t\tminimumDistance();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tsetStatus(\"STR_EVASIVE_MANEUVERS\");\n\t\t\tfor (int i = 0; i < _weaponNum; ++i)\n\t\t\t{\n\t\t\t\tCraftWeapon* w = _craft->getWeapons()->at(i);\n\t\t\t\tif (w != 0)\n\t\t\t\t{\n\t\t\t\t\t// double the craft's reload time to balance halving the HK's chance to hit\n\t\t\t\t\t_weaponFireInterval[i] = w->getRules()->getAggressiveReload() * 2;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// same distance as aggressive (by design)\n\t\t\taggressiveDistance();\n\t\t}\n\t}\n}\n\nvoid DogfightState::btnCautiousRightPress(Action *)\n{\n\t_state->handleDogfightMultiAction(1);\n}\n\nvoid DogfightState::btnCautiousSimulateLeftPress(Action *action)\n{\n\tif (_btnCautious->getVisible())\n\t{\n\t\t_btnCautious->mousePress(action, this);\n\t}\n}\n\n/**\n * Switches to Standard mode (minimum weapon range).\n * @param action Pointer to an action.\n */\nvoid DogfightState::btnStandardPress(Action *)\n{\n\tif (!_ufo->isCrashed() && !_craft->isDestroyed() && !_ufoBreakingOff)\n\t{\n\t\t_end = false;\n\t\tsetStatus(\"STR_STANDARD_ATTACK\");\n\t\tfor (int i = 0; i < _weaponNum; ++i)\n\t\t{\n\t\t\tCraftWeapon* w = _craft->getWeapons()->at(i);\n\t\t\tif (w != 0)\n\t\t\t{\n\t\t\t\t_weaponFireInterval[i] = w->getRules()->getStandardReload();\n\t\t\t}\n\t\t}\n\t\tmaximumDistance();\n\t}\n}\n\nvoid DogfightState::btnStandardRightPress(Action *)\n{\n\t_state->handleDogfightMultiAction(2);\n}\n\nvoid DogfightState::btnStandardSimulateLeftPress(Action *action)\n{\n\tif (_btnStandard->getVisible())\n\t{\n\t\t_btnStandard->mousePress(action, this);\n\t}\n}\n\n/**\n * Switches to Aggressive mode (minimum range).\n * @param action Pointer to an action.\n */\nvoid DogfightState::btnAggressivePress(Action *)\n{\n\tif (!_ufo->isCrashed() && !_craft->isDestroyed() && !_ufoBreakingOff)\n\t{\n\t\t_end = false;\n\t\tsetStatus(\"STR_AGGRESSIVE_ATTACK\");\n\t\tfor (int i = 0; i < _weaponNum; ++i)\n\t\t{\n\t\t\tCraftWeapon* w = _craft->getWeapons()->at(i);\n\t\t\tif (w != 0)\n\t\t\t{\n\t\t\t\t_weaponFireInterval[i] = w->getRules()->getAggressiveReload();\n\t\t\t}\n\t\t}\n\t\taggressiveDistance();\n\t}\n}\n\nvoid DogfightState::btnAggressiveRightPress(Action *)\n{\n\t_state->handleDogfightMultiAction(3);\n}\n\nvoid DogfightState::btnAggressiveSimulateLeftPress(Action *action)\n{\n\tif (_btnAggressive->getVisible())\n\t{\n\t\t_btnAggressive->mousePress(action, this);\n\t}\n}\n\n/**\n * Disengages from the UFO.\n * @param action Pointer to an action.\n */\nvoid DogfightState::btnDisengagePress(Action *)\n{\n\tif (!_ufo->isCrashed() && !_craft->isDestroyed() && !_ufoBreakingOff)\n\t{\n\t\t_end = true;\n\t\tsetStatus(\"STR_DISENGAGING\");\n\t\t_targetDist = 800;\n\t}\n}\n\nvoid DogfightState::btnDisengageRightPress(Action *)\n{\n\t_state->handleDogfightMultiAction(4);\n}\n\nvoid DogfightState::btnDisengageSimulateLeftPress(Action *action)\n{\n\tif (_btnDisengage->getVisible())\n\t{\n\t\t_btnDisengage->mousePress(action, this);\n\t}\n}\n\n/**\n * Shows a front view of the UFO.\n * @param action Pointer to an action.\n */\nvoid DogfightState::btnUfoClick(Action *)\n{\n\t_preview->setVisible(true);\n\t// Disable all other buttons to prevent misclicks\n\t_btnStandoff->setVisible(false);\n\t_btnCautious->setVisible(false);\n\t_btnStandard->setVisible(false);\n\t_btnAggressive->setVisible(false);\n\t_btnDisengage->setVisible(false);\n\t_btnUfo->setVisible(false);\n\t_btnMinimize->setVisible(false);\n\tfor (int i = 0; i < _weaponNum; ++i)\n\t{\n\t\t_weapon[i]->setVisible(false);\n\t}\n}\n\n/**\n * Hides the front view of the UFO.\n * @param action Pointer to an action.\n */\nvoid DogfightState::previewClick(Action *)\n{\n\t_preview->setVisible(false);\n\t// Reenable all other buttons to prevent misclicks\n\t_btnStandoff->setVisible(!_disableStandoff);\n\t_btnCautious->setVisible(!_disableCautious);\n\t_btnStandard->setVisible(!_disableStandard);\n\t_btnAggressive->setVisible(!_disableAggressive);\n\t_btnDisengage->setVisible(!_disableDisengage);\n\t_btnUfo->setVisible(true);\n\t_btnMinimize->setVisible(!_ufoIsAttacking || _craftIsDefenseless);\n\tfor (int i = 0; i < _weaponNum; ++i)\n\t{\n\t\t_weapon[i]->setVisible(true);\n\t}\n}\n\n/*\n * Draws the UFO blob on the radar screen.\n * Currently works only for original sized blobs\n * 13 x 13 pixels.\n */\nvoid DogfightState::drawUfo()\n{\n\tif (_ufoBlobSize < 0 || _ufo->isDestroyed())\n\t{\n\t\treturn;\n\t}\n\tint currentUfoXposition =  _battle->getWidth() / 2 - 6;\n\tint currentUfoYposition = _battle->getHeight() - (_currentDist / 8) - 6;\n\tfor (int y = 0; y < 13; ++y)\n\t{\n\t\tfor (int x = 0; x < 13; ++x)\n\t\t{\n\t\t\tUint8 pixelOffset = _ufoBlobs[_ufoBlobSize + _ufo->getHitFrame()][y][x];\n\t\t\tif (pixelOffset == 0)\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (_ufo->isCrashed() || _ufo->getHitFrame() > 0)\n\t\t\t\t{\n\t\t\t\t\tpixelOffset *= 2;\n\t\t\t\t}\n\n\t\t\t\tUint8 radarPixelColor = _window->getPixel(currentUfoXposition + x + 3, currentUfoYposition + y + 3); // + 3 cause of the window frame\n\t\t\t\tUint8 color = radarPixelColor - pixelOffset;\n\t\t\t\tif (color < _colors[BLOB_MIN])\n\t\t\t\t{\n\t\t\t\t\tcolor = _colors[BLOB_MIN];\n\t\t\t\t}\n\n\t\t\t\tif (_ufo->getShield() != 0 && _ufo->getCraftStats().shieldCapacity != 0)\n\t\t\t\t{\n\t\t\t\t\tUint8 shieldColor =\n\t\t\t\t\t\t_colors[SHIELD_MAX]\n\t\t\t\t\t\t- ((_colors[SHIELD_MAX] - _colors[SHIELD_MIN]) * _ufo->getShield() / _ufo->getCraftStats().shieldCapacity)\n\t\t\t\t\t\t+ (color - _colors[BLOB_MIN]);\n\t\t\t\t\tif (shieldColor < _colors[SHIELD_MIN])\n\t\t\t\t\t{\n\t\t\t\t\t\tshieldColor = _colors[SHIELD_MIN];\n\t\t\t\t\t}\n\t\t\t\t\tif (shieldColor <=  _colors[SHIELD_MAX])\n\t\t\t\t\t{\n\t\t\t\t\t\tcolor = shieldColor;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t_battle->setPixel(currentUfoXposition + x, currentUfoYposition + y, color);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/*\n * Draws projectiles on the radar screen.\n * Depending on what type of projectile it is, it's\n * shape will be different. Currently works for\n * original sized blobs 3 x 6 pixels.\n */\nvoid DogfightState::drawProjectile(const CraftWeaponProjectile* p)\n{\n\tint xPos = _battle->getWidth() / 2 + p->getHorizontalPosition();\n\t// Draw missiles.\n\tif (p->getGlobalType() == CWPGT_MISSILE)\n\t{\n\t\txPos -= 1;\n\t\tint yPos = _battle->getHeight() - p->getPosition() / 8;\n\t\tfor (int x = 0; x < 3; ++x)\n\t\t{\n\t\t\tfor (int y = 0; y < 6; ++y)\n\t\t\t{\n\t\t\t\tint pixelOffset = _projectileBlobs[p->getType()][y][x];\n\t\t\t\tif (pixelOffset == 0)\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tUint8 radarPixelColor = _window->getPixel(xPos + x + 3, yPos + y + 3); // + 3 cause of the window frame\n\t\t\t\t\tUint8 color = radarPixelColor - pixelOffset;\n\t\t\t\t\tif (color < _colors[BLOB_MIN])\n\t\t\t\t\t{\n\t\t\t\t\t\tcolor = _colors[BLOB_MIN];\n\t\t\t\t\t}\n\t\t\t\t\t_battle->setPixel(xPos + x, yPos + y, color);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t// Draw beams.\n\telse if (p->getGlobalType() == CWPGT_BEAM)\n\t{\n\t\tint yStart = _battle->getHeight() - 2;\n\t\tint yEnd = _battle->getHeight() - (_currentDist / 8);\n\t\tUint8 pixelOffset = p->getState();\n\t\tfor (int y = yStart; y > yEnd; --y)\n\t\t{\n\t\t\tUint8 radarPixelColor = _window->getPixel(xPos + 3, y + 3);\n\n\t\t\tint beamPower = 0;\n\t\t\tif (p->getType() == CWPT_PLASMA_BEAM)\n\t\t\t{\n\t\t\t\tbeamPower = _ufo->getRules()->getWeaponPower() / _game->getMod()->getUfoBeamWidthParameter();\n\t\t\t}\n\n\t\t\tfor (int x = 0; x <= std::min(beamPower, 3); x++)\n\t\t\t{\n\t\t\t\tUint8 color = radarPixelColor - pixelOffset - beamPower + 2 * x;\n\t\t\t\tif (color < _colors[BLOB_MIN])\n\t\t\t\t{\n\t\t\t\t\tcolor = _colors[BLOB_MIN];\n\t\t\t\t}\n\t\t\t\tif (color > radarPixelColor)\n\t\t\t\t{\n\t\t\t\t\tcolor = radarPixelColor;\n\t\t\t\t}\n\t\t\t\t_battle->setPixel(xPos + x, y, color);\n\t\t\t\t_battle->setPixel(xPos - x, y, color);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Toggles usage of weapons.\n * @param action Pointer to an action.\n */\nvoid DogfightState::weaponClick(Action * a)\n{\n\tfor (int i = 0; i < _weaponNum; ++i)\n\t{\n\t\tif (a->getSender() == _weapon[i])\n\t\t{\n\t\t\t_weaponEnabled[i] = !_weaponEnabled[i];\n\t\t\trecolor(i, _weaponEnabled[i]);\n\n\t\t\tif (Options::oxceRememberDisabledCraftWeapons)\n\t\t\t{\n\t\t\t\tCraftWeapon* w = _craft->getWeapons()->at(i);\n\t\t\t\tif (w)\n\t\t\t\t{\n\t\t\t\t\tw->setDisabled(!_weaponEnabled[i]);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t}\n}\n\n/**\n * Changes colors of weapon icons, range indicators and ammo texts base on current weapon state.\n * @param weaponNo - number of weapon for which colors must be changed.\n * @param currentState - state of weapon (enabled = true, disabled = false).\n */\nvoid DogfightState::recolor(const int weaponNo, const bool currentState)\n{\n\tInteractiveSurface *weapon = _weapon[weaponNo];\n\tText *ammo = _txtAmmo[weaponNo];\n\tSurface *range = _range[weaponNo];\n\n\tif (currentState)\n\t{\n\t\tweapon->offset(-_colors[DISABLED_WEAPON]);\n\t\tammo->offset(-_colors[DISABLED_AMMO]);\n\t\trange->offset(-_colors[DISABLED_RANGE]);\n\t}\n\telse\n\t{\n\t\tweapon->offset(_colors[DISABLED_WEAPON]);\n\t\tammo->offset(_colors[DISABLED_AMMO]);\n\t\trange->offset(_colors[DISABLED_RANGE]);\n\t}\n}\n\n/**\n * Returns true if state is minimized. Otherwise returns false.\n * @return Is the dogfight minimized?\n */\nbool DogfightState::isMinimized() const\n{\n\treturn _minimized;\n}\n\nvoid DogfightState::updateOceanIndicator()\n{\n\t// ocean (or cosmetic ocean texture)\n\tbool oceanTexture = !_state->getGlobe()->insideLand(_ufo->getLongitude(), _ufo->getLatitude());\n\t// fake ocean texture\n\tbool fakeUnderwaterTexture = _state->getGlobe()->insideFakeUnderwaterTexture(_ufo->getLongitude(), _ufo->getLatitude());\n\tint survivalChance = _ufo->getRules()->getSplashdownSurvivalChance();\n\n\tif (oceanTexture)\n\t{\n\t\t_txtOceanIndicator->setText(tr(\"STR_OCEAN_INDICATOR\")); // ! ufo lost\n\t}\n\telse if (fakeUnderwaterTexture)\n\t{\n\t\tif (survivalChance >= 100)\n\t\t\t_txtOceanIndicator->setText(\"\");\n\t\telse if (survivalChance > 0)\n\t\t\t_txtOceanIndicator->setText(tr(\"STR_OCEAN_INDICATOR_RNG\")); // ? ufo maybe lost, maybe not\n\t\telse\n\t\t\t_txtOceanIndicator->setText(tr(\"STR_OCEAN_INDICATOR\")); // ! ufo lost\n\t}\n\telse\n\t{\n\t\t_txtOceanIndicator->setText(\"\");\n\t}\n}\n\n/**\n * Sets the state to minimized/maximized status.\n * @param minimized Is the dogfight minimized?\n */\nvoid DogfightState::setMinimized(const bool minimized)\n{\n\tif (!minimized)\n\t{\n\t\tupdateOceanIndicator();\n\t}\n\n\t// set these to the same as the incoming minimized state\n\t_minimized = minimized;\n\t_btnMinimizedIcon->setVisible(minimized);\n\t_txtInterceptionNumber->setVisible(minimized);\n\n\t// set these to the opposite of the incoming minimized state\n\t_window->setVisible(!minimized);\n\t_btnStandoff->setVisible(!minimized);\n\t_btnCautious->setVisible(!minimized);\n\t_btnStandard->setVisible(!minimized);\n\t_btnAggressive->setVisible(!minimized);\n\t_btnDisengage->setVisible(!minimized);\n\t_btnUfo->setVisible(!minimized);\n\t_btnMinimize->setVisible(!minimized);\n\t_battle->setVisible(!minimized);\n\tfor (int i = 0; i < _weaponNum; ++i)\n\t{\n\t\t_weapon[i]->setVisible(!minimized);\n\t\t_range[i]->setVisible(!minimized);\n\t\t_txtAmmo[i]->setVisible(!minimized);\n\t}\n\t_craftSprite->setVisible(!minimized);\n\t_damage->setVisible(!minimized);\n\t_craftShield->setVisible(!minimized);\n\t_txtDistance->setVisible(!minimized);\n\t_txtOceanIndicator->setVisible(!minimized);\n\t_txtStatus->setVisible(!minimized);\n\n\t// set to false regardless\n\t_preview->setVisible(false);\n}\n\n/**\n * Maximizes the interception window.\n * @param action Pointer to an action.\n */\nvoid DogfightState::btnMinimizedIconClick(Action *)\n{\n\tif (_craft->getRules()->isWaterOnly() && _ufo->getAltitudeInt() > _craft->getRules()->getMaxAltitude())\n\t{\n\t\t_state->popup(new DogfightErrorState(_craft, tr(\"STR_UNABLE_TO_ENGAGE_DEPTH\")));\n\t\tsetWaitForAltitude(true);\n\t}\n\telse if (_craft->getRules()->isWaterOnly() && !_state->getGlobe()->insideLand(_craft->getLongitude(), _craft->getLatitude()))\n\t{\n\t\t_state->popup(new DogfightErrorState(_craft, tr(\"STR_UNABLE_TO_ENGAGE_AIRBORNE\")));\n\t\tsetWaitForPoly(true);\n\t}\n\telse\n\t{\n\t\tsetMinimized(false);\n\t}\n}\n\n/**\n * Sets interception number. Used to draw proper number when window minimized.\n * @param number ID number.\n */\nvoid DogfightState::setInterceptionNumber(const int number)\n{\n\t_interceptionNumber = number;\n}\n\n/**\n * Sets interceptions count. Used to properly position the window.\n * @param count Amount of interception windows.\n */\nvoid DogfightState::setInterceptionsCount(const size_t count)\n{\n\t_interceptionsCount = count;\n\tcalculateWindowPosition();\n\tmoveWindow();\n}\n\n/**\n * Calculates dogfight window position according to\n * number of active interceptions.\n */\nvoid DogfightState::calculateWindowPosition()\n{\n\t_minimizedIconX = 5;\n\t_minimizedIconY = (5 * _interceptionNumber) + (16 * (_interceptionNumber - 1));\n\n\tif (_interceptionsCount == 1)\n\t{\n\t\t_x = 80;\n\t\t_y = 52;\n\t}\n\telse if (_interceptionsCount == 2)\n\t{\n\t\tif (_interceptionNumber == 1)\n\t\t{\n\t\t\t_x = 80;\n\t\t\t_y = 0;\n\t\t}\n\t\telse // 2\n\t\t{\n\t\t\t_x = 80;\n\t\t\t//_y = (_game->getScreen()->getHeight() / 2) - 96;\n\t\t\t_y = 200 - _window->getHeight();//96;\n\t\t}\n\t}\n\telse if (_interceptionsCount == 3)\n\t{\n\t\tif (_interceptionNumber == 1)\n\t\t{\n\t\t\t_x = 80;\n\t\t\t_y = 0;\n\t\t}\n\t\telse if (_interceptionNumber == 2)\n\t\t{\n\t\t\t_x = 0;\n\t\t\t//_y = (_game->getScreen()->getHeight() / 2) - 96;\n\t\t\t_y = 200 - _window->getHeight();//96;\n\t\t}\n\t\telse // 3\n\t\t{\n\t\t\t//_x = (_game->getScreen()->getWidth() / 2) - 160;\n\t\t\t//_y = (_game->getScreen()->getHeight() / 2) - 96;\n\t\t\t_x = 320 - _window->getWidth();//160;\n\t\t\t_y = 200 - _window->getHeight();//96;\n\t\t}\n\t}\n\telse\n\t{\n\t\tif (_interceptionNumber == 1)\n\t\t{\n\t\t\t_x = 0;\n\t\t\t_y = 0;\n\t\t}\n\t\telse if (_interceptionNumber == 2)\n\t\t{\n\t\t\t//_x = (_game->getScreen()->getWidth() / 2) - 160;\n\t\t\t_x = 320 - _window->getWidth();//160;\n\t\t\t_y = 0;\n\t\t}\n\t\telse if (_interceptionNumber == 3)\n\t\t{\n\t\t\t_x = 0;\n\t\t\t//_y = (_game->getScreen()->getHeight() / 2) - 96;\n\t\t\t_y = 200 - _window->getHeight();//96;\n\t\t}\n\t\telse // 4\n\t\t{\n\t\t\t//_x = (_game->getScreen()->getWidth() / 2) - 160;\n\t\t\t//_y = (_game->getScreen()->getHeight() / 2) - 96;\n\t\t\t_x = 320 - _window->getWidth();//160;\n\t\t\t_y = 200 - _window->getHeight();//96;\n\t\t}\n\t}\n\t_x += _game->getScreen()->getDX();\n\t_y += _game->getScreen()->getDY();\n}\n\n/**\n * Relocates all dogfight window elements to\n * calculated position. This is used when multiple\n * interceptions are running.\n */\nvoid DogfightState::moveWindow()\n{\n\tint x = _window->getX() - _x;\n\tint y = _window->getY() - _y;\n\tfor (auto* surface : _surfaces)\n\t{\n\t\tsurface->setX(surface->getX() - x);\n\t\tsurface->setY(surface->getY() - y);\n\t}\n\t_btnMinimizedIcon->setX(_minimizedIconX); _btnMinimizedIcon->setY(_minimizedIconY);\n\t_txtInterceptionNumber->setX(_minimizedIconX + 18); _txtInterceptionNumber->setY(_minimizedIconY + 6);\n}\n\n/**\n * Checks whether the dogfight should end.\n * @return Returns true if the dogfight should end, otherwise returns false.\n */\nbool DogfightState::dogfightEnded() const\n{\n\treturn _endDogfight;\n}\n\n/**\n * Returns the UFO associated to this dogfight.\n * @return Returns pointer to UFO object associated to this dogfight.\n */\nUfo *DogfightState::getUfo() const\n{\n\treturn _ufo;\n}\n\n/**\n * Returns the craft associated to this dogfight.\n * @return Returns pointer to craft object associated to this dogfight.\n */\nCraft *DogfightState::getCraft() const\n{\n\treturn _craft;\n}\n\n/**\n * Ends the dogfight.\n */\nvoid DogfightState::endDogfight()\n{\n\tif (_endDogfight)\n\t\treturn;\n\tif (_craft)\n\t{\n\t\t_craft->setInDogfight(false);\n\t\t_craft->setInterceptionOrder(0);\n\t}\n\t// set the ufo as \"free\" for the next engagement (as applicable)\n\tif (_ufo)\n\t{\n\t\t_ufo->setInterceptionProcessed(false);\n\t\t_ufo->setShieldRechargeHandle(0);\n\t}\n\t_endDogfight = true;\n}\n\n/**\n * Returns interception number.\n * @return interception number\n */\nint DogfightState::getInterceptionNumber() const\n{\n\treturn _interceptionNumber;\n}\n\nvoid DogfightState::setWaitForPoly(bool wait)\n{\n\t_waitForPoly = wait;\n}\n\nbool DogfightState::getWaitForPoly() const\n{\n\treturn _waitForPoly;\n}\n\nvoid DogfightState::setWaitForAltitude(bool wait)\n{\n\t_waitForAltitude = wait;\n}\n\nbool DogfightState::getWaitForAltitude() const\n{\n\treturn _waitForAltitude;\n}\n\nvoid DogfightState::awardExperienceToPilots()\n{\n\tif (_firedAtLeastOnce && !_experienceAwarded && _craft && _ufo && (_ufo->isCrashed() || _ufo->isDestroyed()))\n\t{\n\t\tbool psiStrengthEval = (Options::psiStrengthEval && _game->getSavedGame()->isResearched(_game->getMod()->getPsiRequirements()));\n\t\tfor (auto* pilot : _craft->getPilotList(false, nullptr)) // refresh already done in the constructor\n\t\t{\n\t\t\tif (pilot->getCurrentStats()->firing < pilot->getRules()->getStatCaps().firing)\n\t\t\t{\n\t\t\t\tif (RNG::percent(pilot->getRules()->getDogfightExperience().firing))\n\t\t\t\t{\n\t\t\t\t\tpilot->getCurrentStatsEditable()->firing++;\n\t\t\t\t\tpilot->getDailyDogfightExperienceCache()->firing++;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (pilot->getCurrentStats()->reactions < pilot->getRules()->getStatCaps().reactions)\n\t\t\t{\n\t\t\t\tif (RNG::percent(pilot->getRules()->getDogfightExperience().reactions))\n\t\t\t\t{\n\t\t\t\t\tpilot->getCurrentStatsEditable()->reactions++;\n\t\t\t\t\tpilot->getDailyDogfightExperienceCache()->reactions++;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (pilot->getCurrentStats()->bravery < pilot->getRules()->getStatCaps().bravery)\n\t\t\t{\n\t\t\t\tif (RNG::percent(pilot->getRules()->getDogfightExperience().bravery))\n\t\t\t\t{\n\t\t\t\t\tpilot->getCurrentStatsEditable()->bravery += 10; // increase by 10 to keep OCD at bay\n\t\t\t\t\tpilot->getDailyDogfightExperienceCache()->bravery += 10;\n\t\t\t\t}\n\t\t\t}\n\t\t\tpilot->calcStatString(_game->getMod()->getStatStrings(), psiStrengthEval);\n\n\t\t\tpilot->getDiary()->addUfoShotDown(_ufo->getCraftStats().damageMax); // yes, damageMax is intentional\n\t\t}\n\t\t_experienceAwarded = true;\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/DogfightState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include \"../Mod/RuleCraft.h\"\n#include <vector>\n#include <string>\n\nnamespace OpenXcom\n{\n\nconst int STANDOFF_DIST = 560;\nconst int AGGRESSIVE_DIST = 64;\nenum ColorNames { CRAFT_MIN, CRAFT_MAX, RADAR_MIN, RADAR_MAX, DAMAGE_MIN, DAMAGE_MAX, BLOB_MIN, RANGE_METER, DISABLED_WEAPON, DISABLED_AMMO, DISABLED_RANGE, SHIELD_MIN, SHIELD_MAX };\n\nclass ImageButton;\nclass Text;\nclass Surface;\nclass InteractiveSurface;\nclass Timer;\nclass GeoscapeState;\nclass Craft;\nclass Ufo;\nclass CraftWeaponProjectile;\n\n/**\n * Shows a dogfight (interception) between a\n * player craft and an UFO.\n */\nclass DogfightState : public State\n{\nprivate:\n\tGeoscapeState *_state;\n\tTimer *_craftDamageAnimTimer;\n\tSurface *_window, *_battle, *_range[RuleCraft::WeaponMax], *_damage, *_craftSprite, *_craftShield;\n\tInteractiveSurface *_btnMinimize, *_preview, *_weapon[RuleCraft::WeaponMax];\n\tImageButton *_btnStandoff, *_btnCautious, *_btnStandard, *_btnAggressive, *_btnDisengage, *_btnUfo;\n\tImageButton *_mode;\n\tInteractiveSurface *_btnMinimizedIcon;\n\tText *_txtAmmo[RuleCraft::WeaponMax], *_txtDistance, *_txtStatus, *_txtInterceptionNumber;\n\tText *_txtOceanIndicator;\n\tCraft *_craft;\n\tUfo *_ufo;\n\tbool _ufoIsAttacking, _missileCraft, _missileImpact;\n\tbool _disableDisengage, _disableStandoff, _disableCautious, _disableStandard, _disableAggressive;\n\tbool _craftIsDefenseless, _selfDestructPressed;\n\tint _timeout, _currentDist, _targetDist, _weaponFireInterval[RuleCraft::WeaponMax], _weaponFireCountdown[RuleCraft::WeaponMax];\n\tbool _end, _endUfoHandled, _endCraftHandled, _ufoBreakingOff, _destroyUfo, _destroyCraft, _weaponEnabled[RuleCraft::WeaponMax];\n\tbool _minimized, _endDogfight, _animatingHit, _waitForPoly, _waitForAltitude;\n\tstd::vector<CraftWeaponProjectile*> _projectiles;\n\tstatic const int _ufoBlobs[8][13][13];\n\tstatic const int _projectileBlobs[4][6][3];\n\tint _ufoSize, _ufoBlobSize, _craftHeight, _currentCraftDamageColor, _interceptionNumber;\n\tsize_t _interceptionsCount;\n\tint _x, _y, _minimizedIconX, _minimizedIconY;\n\tint _weaponNum;\n\tint _pilotAccuracyBonus, _pilotDodgeBonus, _pilotApproachSpeedModifier, _craftAccelerationBonus;\n\tbool _firedAtLeastOnce, _experienceAwarded;\n\tbool _delayedRecolorDone;\n\t// craft min/max, radar min/max, damage min/max, shield min/max\n\tint _colors[13];\n\t// Ends the dogfight.\n\tvoid endDogfight();\n\tbool _tractorLockedOn[RuleCraft::WeaponMax];\n\tvoid updateOceanIndicator();\n\npublic:\n\t/// Creates the Dogfight state.\n\tDogfightState(GeoscapeState *state, Craft *craft, Ufo *ufo, bool ufoIsAttacking = false);\n\t/// Cleans up the Dogfight state.\n\t~DogfightState();\n\t/// Returns true if this is a hunter-killer dogfight.\n\tbool isUfoAttacking() const;\n\t/// Runs the timers.\n\tvoid think() override;\n\t/// Animates the window.\n\tvoid animate();\n\t/// Moves the craft.\n\tvoid update();\n\t// Fires the weapons.\n\tvoid fireWeapon(int i);\n\t// Fires UFO weapon.\n\tvoid ufoFireWeapon();\n\t// Sets the craft to minimum distance.\n\tvoid minimumDistance();\n\t// Sets the craft to maximum distance.\n\tvoid maximumDistance();\n\t// Sets the craft to maximum distance or 8 km, whichever is smaller.\n\tvoid aggressiveDistance();\n\t/// Changes the status text.\n\tvoid setStatus(const std::string &status);\n\t/// Handler for clicking the Minimize button.\n\tvoid btnMinimizeClick(Action *action);\n\t/// Handler for pressing the Standoff button.\n\tvoid btnStandoffPress(Action *action);\n\tvoid btnStandoffRightPress(Action *action);\n\tvoid btnStandoffSimulateLeftPress(Action *action);\n\t/// Handler for pressing the Cautious Attack button.\n\tvoid btnCautiousPress(Action *action);\n\tvoid btnCautiousRightPress(Action *action);\n\tvoid btnCautiousSimulateLeftPress(Action *action);\n\t/// Handler for pressing the Standard Attack button.\n\tvoid btnStandardPress(Action *action);\n\tvoid btnStandardRightPress(Action *action);\n\tvoid btnStandardSimulateLeftPress(Action *action);\n\t/// Handler for pressing the Aggressive Attack button.\n\tvoid btnAggressivePress(Action *action);\n\tvoid btnAggressiveRightPress(Action *action);\n\tvoid btnAggressiveSimulateLeftPress(Action *action);\n\t/// Handler for pressing the Disengage button.\n\tvoid btnDisengagePress(Action *action);\n\tvoid btnDisengageRightPress(Action *action);\n\tvoid btnDisengageSimulateLeftPress(Action *action);\n\t/// Handler for clicking the Ufo button.\n\tvoid btnUfoClick(Action *action);\n\t/// Handler for clicking the Preview graphic.\n\tvoid previewClick(Action *action);\n\t/// Draws UFO.\n\tvoid drawUfo();\n\t/// Draws projectiles.\n\tvoid drawProjectile(const CraftWeaponProjectile* p);\n\t/// Animates craft damage.\n\tvoid animateCraftDamage();\n\t/// Updates craft damage.\n\tvoid drawCraftDamage();\n\t/// Draws craft shield on sprite\n\tvoid drawCraftShield();\n\t/// Toggles usage of weapons.\n\tvoid weaponClick(Action *action);\n\t/// Changes colors of weapon icons, range indicators and ammo texts base on current weapon state.\n\tvoid recolor(const int weaponNo, const bool currentState);\n\t/// Returns true if state is minimized.\n\tbool isMinimized() const;\n\t/// Sets state minimized or maximized.\n\tvoid setMinimized(const bool minimized);\n\t/// Handler for clicking the minimized interception window icon.\n\tvoid btnMinimizedIconClick(Action *action);\n\t/// Gets interception number.\n\tint getInterceptionNumber() const;\n\t/// Sets interception number.\n\tvoid setInterceptionNumber(const int number);\n\t/// Sets interceptions count.\n\tvoid setInterceptionsCount(const size_t count);\n\t/// Calculates window position according to opened interception windows.\n\tvoid calculateWindowPosition();\n\t/// Moves window to new position.\n\tvoid moveWindow();\n\t/// Checks if the dogfight should be ended.\n\tbool dogfightEnded() const;\n\t/// Gets pointer to the UFO in this dogfight.\n\tUfo *getUfo() const;\n\t/// Gets pointer to the craft in this dogfight.\n\tCraft *getCraft() const;\n\t/// Waits until the UFO reaches a polygon.\n\tvoid setWaitForPoly(bool wait);\n\t/// Waits until the UFO reaches a polygon.\n\tbool getWaitForPoly() const;\n\t/// Waits until the UFO reaches the right altitude.\n\tvoid setWaitForAltitude(bool wait);\n\t/// Waits until the UFO reaches the right altitude.\n\tbool getWaitForAltitude() const;\n\t/// Award experience to the pilots.\n\tvoid awardExperienceToPilots();\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/ExtendedGeoscapeLinksState.cpp",
    "content": "/*\n * Copyright 2010-2021 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"ExtendedGeoscapeLinksState.h\"\n#include \"FundingState.h\"\n#include \"GeoscapeState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Menu/NotesState.h\"\n#include \"../Menu/TestState.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the ExtendedGeoscapeLinksState screen.\n */\nExtendedGeoscapeLinksState::ExtendedGeoscapeLinksState(GeoscapeState* parent) : _parent(parent)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 256, 180, 32, 10, POPUP_BOTH);\n\t_txtTitle = new Text(220, 17, 50, 33);\n\tif (Options::oxceFatFingerLinks)\n\t{\n\t\t_btnFunding = new TextButton(116, 25, 44, 50);\n\t\t_btnTechTree = new TextButton(116, 25, 161, 50);\n\t\t_btnGlobalResearch = new TextButton(116, 25, 44, 76);\n\t\t_btnGlobalProduction = new TextButton(116, 25, 161, 76);\n\t\t_btnUfoTracker = new TextButton(116, 25, 44, 102);\n\t\t_btnPilotExp = new TextButton(116, 25, 161, 102);\n\t\t_btnNotes = new TextButton(116, 25, 44, 128);\n\t\t_btnMusic = new TextButton(116, 25, 161, 128);\n\t\t_btnTest = new TextButton(116, 25, 44, 154);\n\t\t_btnOk = new TextButton(116, 25, 161, 154);\n\t}\n\telse\n\t{\n\t\t_btnFunding = new TextButton(220, 12, 50, 50);\n\t\t_btnTechTree = new TextButton(220, 12, 50, 63);\n\t\t_btnGlobalResearch = new TextButton(220, 12, 50, 76);\n\t\t_btnGlobalProduction = new TextButton(220, 12, 50, 89);\n\t\t_btnUfoTracker = new TextButton(220, 12, 50, 102);\n\t\t_btnPilotExp = new TextButton(220, 12, 50, 115);\n\t\t_btnNotes = new TextButton(220, 12, 50, 128);\n\t\t_btnMusic = new TextButton(220, 12, 50, 141);\n\t\t_btnTest = new TextButton(220, 12, 50, 154);\n\t\t_btnOk = new TextButton(220, 12, 50, 167);\n\t}\n\n\t// Set palette\n\tsetInterface(\"oxceLinks\");\n\n\tadd(_window, \"window\", \"oxceLinks\");\n\tadd(_txtTitle, \"text\", \"oxceLinks\");\n\tadd(_btnOk, \"button\", \"oxceLinks\");\n\n\tadd(_btnFunding, \"button\", \"oxceLinks\");\n\tadd(_btnTechTree, \"button\", \"oxceLinks\");\n\tadd(_btnGlobalResearch, \"button\", \"oxceLinks\");\n\tadd(_btnGlobalProduction, \"button\", \"oxceLinks\");\n\tadd(_btnUfoTracker, \"button\", \"oxceLinks\");\n\tadd(_btnPilotExp, \"button\", \"oxceLinks\");\n\tadd(_btnNotes, \"button\", \"oxceLinks\");\n\tadd(_btnMusic, \"button\", \"oxceLinks\");\n\tadd(_btnTest, \"button\", \"oxceLinks\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"oxceLinks\");\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_EXTENDED_LINKS\"));\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&ExtendedGeoscapeLinksState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&ExtendedGeoscapeLinksState::btnOkClick, Options::keyCancel);\n\n\t_btnFunding->setText(tr(\"STR_FUNDING_UC\"));\n\t_btnFunding->onMouseClick((ActionHandler)&ExtendedGeoscapeLinksState::btnFundingClick);\n\n\tstd::string tmp = tr(\"STR_TECH_TREE_VIEWER\");\n\tUnicode::upperCase(tmp);\n\t_btnTechTree->setText(tmp);\n\t_btnTechTree->onMouseClick((ActionHandler)&ExtendedGeoscapeLinksState::btnTechTreeClick);\n\n\t_btnGlobalResearch->setText(tr(\"STR_RESEARCH_OVERVIEW\"));\n\t_btnGlobalResearch->onMouseClick((ActionHandler)&ExtendedGeoscapeLinksState::btnGlobalResearchClick);\n\n\t_btnGlobalProduction->setText(tr(\"STR_PRODUCTION_OVERVIEW\"));\n\t_btnGlobalProduction->onMouseClick((ActionHandler)&ExtendedGeoscapeLinksState::btnGlobalProductionClick);\n\n\ttmp = tr(\"STR_UFO_TRACKER\");\n\tUnicode::upperCase(tmp);\n\t_btnUfoTracker->setText(tmp);\n\t_btnUfoTracker->onMouseClick((ActionHandler)&ExtendedGeoscapeLinksState::btnUfoTrackerClick);\n\n\ttmp = tr(\"STR_DAILY_PILOT_EXPERIENCE\");\n\tUnicode::upperCase(tmp);\n\t_btnPilotExp->setText(tmp);\n\t_btnPilotExp->onMouseClick((ActionHandler)&ExtendedGeoscapeLinksState::btnPilotExpClick);\n\n\ttmp = tr(\"STR_NOTES\");\n\tUnicode::upperCase(tmp);\n\t_btnNotes->setText(tmp);\n\t_btnNotes->onMouseClick((ActionHandler)&ExtendedGeoscapeLinksState::btnNotesClick);\n\n\ttmp = tr(\"STR_SELECT_MUSIC_TRACK\");\n\tUnicode::upperCase(tmp);\n\t_btnMusic->setText(tmp);\n\t_btnMusic->onMouseClick((ActionHandler)&ExtendedGeoscapeLinksState::btnMusicClick);\n\n\tif (Options::debug)\n\t{\n\t\t_btnTest->setText(tr(\"STR_TOGGLE_DEBUG_MODE\"));\n\t}\n\telse\n\t{\n\t\t_btnTest->setText(tr(\"STR_TEST_SCREEN\"));\n\t}\n\t_btnTest->onMouseClick((ActionHandler)&ExtendedGeoscapeLinksState::btnTestClick);\n}\n\nvoid ExtendedGeoscapeLinksState::btnFundingClick(Action *)\n{\n\t_game->popState();\n\t_game->pushState(new FundingState);\n}\n\nvoid ExtendedGeoscapeLinksState::btnTechTreeClick(Action *)\n{\n\t_game->popState();\n\t_parent->btnTechTreeViewerClick(nullptr);\n}\n\nvoid ExtendedGeoscapeLinksState::btnGlobalResearchClick(Action *)\n{\n\t_game->popState();\n\t_parent->btnGlobalResearchClick(nullptr);\n}\n\nvoid ExtendedGeoscapeLinksState::btnGlobalProductionClick(Action *)\n{\n\t_game->popState();\n\t_parent->btnGlobalProductionClick(nullptr);\n}\n\nvoid ExtendedGeoscapeLinksState::btnUfoTrackerClick(Action *)\n{\n\t_game->popState();\n\t_parent->btnUfoTrackerClick(nullptr);\n}\n\nvoid ExtendedGeoscapeLinksState::btnPilotExpClick(Action *)\n{\n\t_game->popState();\n\t_parent->btnDogfightExperienceClick(nullptr);\n}\n\nvoid ExtendedGeoscapeLinksState::btnNotesClick(Action *)\n{\n\t_game->popState();\n\t_game->pushState(new NotesState(OPT_GEOSCAPE));\n}\n\nvoid ExtendedGeoscapeLinksState::btnMusicClick(Action *)\n{\n\t_game->popState();\n\t_parent->btnSelectMusicTrackClick(nullptr);\n}\n\nvoid ExtendedGeoscapeLinksState::btnTestClick(Action *)\n{\n\t_game->popState();\n\tif (Options::debug)\n\t{\n\t\t_parent->btnDebugClick(nullptr);\n\t}\n\telse\n\t{\n\t\t_game->pushState(new TestState);\n\t}\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid ExtendedGeoscapeLinksState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/ExtendedGeoscapeLinksState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2021 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass GeoscapeState;\n\n/**\n * A screen with links to the OXCE geoscape functionality.\n */\nclass ExtendedGeoscapeLinksState : public State\n{\nprivate:\n\tTextButton *_btnOk;\n\tTextButton *_btnFunding, *_btnTechTree, *_btnGlobalResearch, *_btnGlobalProduction, *_btnUfoTracker, *_btnPilotExp, *_btnNotes, *_btnMusic;\n\tTextButton *_btnTest;\n\tWindow *_window;\n\tText *_txtTitle;\n\tGeoscapeState *_parent;\npublic:\n\t/// Creates the ExtendedGeoscapeLinks state.\n\tExtendedGeoscapeLinksState(GeoscapeState* parent);\n\t/// Cleans up the ExtendedGeoscapeLinks state.\n\t~ExtendedGeoscapeLinksState() = default;\n\t/// Handlers for clicking the buttons.\n\tvoid btnFundingClick(Action* action);\n\tvoid btnTechTreeClick(Action* action);\n\tvoid btnGlobalResearchClick(Action* action);\n\tvoid btnGlobalProductionClick(Action* action);\n\tvoid btnUfoTrackerClick(Action* action);\n\tvoid btnPilotExpClick(Action* action);\n\tvoid btnNotesClick(Action* action);\n\tvoid btnMusicClick(Action* action);\n\tvoid btnTestClick(Action* action);\n\tvoid btnOkClick(Action* action);\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/FundingState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"FundingState.h\"\n#include <sstream>\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Interface/ArrowButton.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Savegame/Country.h\"\n#include \"../Mod/RuleCountry.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Engine/Options.h\"\n\nnamespace OpenXcom\n{\n\nstruct compareFundingCountryName\n{\n\tbool operator()(const FundingCountry &a, const FundingCountry &b) const\n\t{\n\t\treturn Unicode::naturalCompare(a.name, b.name);\n\t}\n};\n\nstruct compareFundingCountryFunding\n{\n\tbool operator()(const FundingCountry &a, const FundingCountry &b) const\n\t{\n\t\treturn a.funding < b.funding;\n\t}\n};\n\nstruct compareFundingCountryChange\n{\n\tbool operator()(const FundingCountry &a, const FundingCountry &b) const\n\t{\n\t\treturn a.change < b.change;\n\t}\n};\n\n/**\n * Initializes all the elements in the Funding screen.\n * @param game Pointer to the core game.\n */\nFundingState::FundingState()\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 320, 200, 0, 0, POPUP_BOTH);\n\t_btnOk = new TextButton(50, 12, 135, 180);\n\t_txtTitle = new Text(320, 17, 0, 8);\n\t_txtCountry = new Text(100, 9, 32, 30);\n\t_txtFunding = new Text(100, 9, 140, 30);\n\t_txtChange = new Text(72, 9, 240, 30);\n\t_lstCountries = new TextList(260, 136, 32, 40);\n\t_sortName = new ArrowButton(ARROW_NONE, 11, 8, 32, 30);\n\t_sortFunding = new ArrowButton(ARROW_NONE, 11, 8, 140, 30);\n\t_sortChange = new ArrowButton(ARROW_NONE, 11, 8, 240, 30);\n\n\t// Set palette\n\tsetInterface(\"fundingWindow\");\n\n\tadd(_window, \"window\", \"fundingWindow\");\n\tadd(_btnOk, \"button\", \"fundingWindow\");\n\tadd(_txtTitle, \"text1\", \"fundingWindow\");\n\tadd(_txtCountry, \"text2\", \"fundingWindow\");\n\tadd(_txtFunding, \"text2\", \"fundingWindow\");\n\tadd(_txtChange, \"text2\", \"fundingWindow\");\n\tadd(_lstCountries, \"list\", \"fundingWindow\");\n\tadd(_sortName, \"text2\", \"fundingWindow\");\n\tadd(_sortFunding, \"text2\", \"fundingWindow\");\n\tadd(_sortChange, \"text2\", \"fundingWindow\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"fundingWindow\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&FundingState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&FundingState::btnOkClick, Options::keyOk);\n\t_btnOk->onKeyboardPress((ActionHandler)&FundingState::btnOkClick, Options::keyCancel);\n\t_btnOk->onKeyboardPress((ActionHandler)&FundingState::btnOkClick, Options::keyGeoFunding);\n\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setBig();\n\t_txtTitle->setText(tr(\"STR_INTERNATIONAL_RELATIONS\"));\n\n\t_txtCountry->setText(tr(\"STR_COUNTRY\"));\n\n\t_txtFunding->setText(tr(\"STR_FUNDING\"));\n\n\t_txtChange->setText(tr(\"STR_CHANGE\"));\n\n\t_lstCountries->setColumns(3, 108, 100, 52);\n\t_lstCountries->setDot(true);\n\n\t_sortName->setX(_sortName->getX() + _txtCountry->getTextWidth() + 4);\n\t_sortName->onMouseClick((ActionHandler)&FundingState::sortNameClick);\n\n\t_sortFunding->setX(_sortFunding->getX() + _txtFunding->getTextWidth() + 4);\n\t_sortFunding->onMouseClick((ActionHandler)&FundingState::sortFundingClick);\n\n\t_sortChange->setX(_sortChange->getX() + _txtChange->getTextWidth() + 4);\n\t_sortChange->onMouseClick((ActionHandler)&FundingState::sortChangeClick);\n\n\t_fundingCountryOrder = FC_NONE;\n\n\tfor (auto* country : *_game->getSavedGame()->getCountries())\n\t{\n\t\t_fundingCountryList.push_back(FundingCountry(\n\t\t\ttr(country->getRules()->getType()),\n\t\t\tcountry->getFunding().back(),\n\t\t\tcountry->getFunding().size() > 1 ? country->getFunding().back() - country->getFunding().at(country->getFunding().size() - 2) : 0)\n\t\t);\n\t}\n}\n\n/**\n *\n */\nFundingState::~FundingState()\n{\n\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid FundingState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Refreshes the funding countries list.\n */\nvoid FundingState::init()\n{\n\tState::init();\n\n\tsortList();\n}\n\n/**\n * Updates the sorting arrows based on the current setting.\n */\nvoid FundingState::updateArrows()\n{\n\t_sortName->setShape(ARROW_NONE);\n\t_sortFunding->setShape(ARROW_NONE);\n\t_sortChange->setShape(ARROW_NONE);\n\tswitch (_fundingCountryOrder)\n\t{\n\tcase FC_NONE:\n\t\tbreak;\n\tcase FC_NAME_ASC:\n\t\t_sortName->setShape(ARROW_SMALL_UP);\n\t\tbreak;\n\tcase FC_NAME_DESC:\n\t\t_sortName->setShape(ARROW_SMALL_DOWN);\n\t\tbreak;\n\tcase FC_FUNDING_ASC:\n\t\t_sortFunding->setShape(ARROW_SMALL_UP);\n\t\tbreak;\n\tcase FC_FUNDING_DESC:\n\t\t_sortFunding->setShape(ARROW_SMALL_DOWN);\n\t\tbreak;\n\tcase FC_CHANGE_ASC:\n\t\t_sortChange->setShape(ARROW_SMALL_UP);\n\t\tbreak;\n\tcase FC_CHANGE_DESC:\n\t\t_sortChange->setShape(ARROW_SMALL_DOWN);\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n}\n\n/**\n * Sorts the funding countries list.\n */\nvoid FundingState::sortList()\n{\n\tupdateArrows();\n\n\tswitch (_fundingCountryOrder)\n\t{\n\tcase FC_NONE:\n\t\tbreak;\n\tcase FC_NAME_ASC:\n\t\tstd::stable_sort(_fundingCountryList.begin(), _fundingCountryList.end(), compareFundingCountryName());\n\t\tbreak;\n\tcase FC_NAME_DESC:\n\t\tstd::stable_sort(_fundingCountryList.rbegin(), _fundingCountryList.rend(), compareFundingCountryName());\n\t\tbreak;\n\tcase FC_FUNDING_ASC:\n\t\tstd::stable_sort(_fundingCountryList.begin(), _fundingCountryList.end(), compareFundingCountryFunding());\n\t\tbreak;\n\tcase FC_FUNDING_DESC:\n\t\tstd::stable_sort(_fundingCountryList.rbegin(), _fundingCountryList.rend(), compareFundingCountryFunding());\n\t\tbreak;\n\tcase FC_CHANGE_ASC:\n\t\tstd::stable_sort(_fundingCountryList.begin(), _fundingCountryList.end(), compareFundingCountryChange());\n\t\tbreak;\n\tcase FC_CHANGE_DESC:\n\t\tstd::stable_sort(_fundingCountryList.rbegin(), _fundingCountryList.rend(), compareFundingCountryChange());\n\t\tbreak;\n\t}\n\n\tupdateList();\n}\n\n/**\n * Updates the funding countries list.\n */\nvoid FundingState::updateList()\n{\n\t_lstCountries->clearList();\n\tfor (const auto& country : _fundingCountryList)\n\t{\n\t\tstd::ostringstream ss;\n\t\tss << Unicode::TOK_COLOR_FLIP << Unicode::formatFunding(country.funding) << Unicode::TOK_COLOR_FLIP;\n\n\t\tstd::ostringstream ss2;\n\t\tif (country.change != 0) ss2 << Unicode::TOK_COLOR_FLIP;\n\t\tif (country.change > 0)  ss2 << '+';\n\t\tss2 << Unicode::formatFunding(country.change);\n\t\tif (country.change != 0) ss2 << Unicode::TOK_COLOR_FLIP;\n\n\t\t_lstCountries->addRow(3, country.name.c_str(), ss.str().c_str(), ss2.str().c_str());\n\t}\n\t_lstCountries->addRow(2, tr(\"STR_TOTAL_UC\").c_str(), Unicode::formatFunding(_game->getSavedGame()->getCountryFunding()).c_str());\n\t_lstCountries->setRowColor(_game->getSavedGame()->getCountries()->size(), _txtCountry->getColor());\n}\n\n/**\n * Sorts the funding countries by name.\n */\nvoid FundingState::sortNameClick(Action*)\n{\n\t_fundingCountryOrder = _fundingCountryOrder == FC_NAME_ASC ? FC_NAME_DESC : FC_NAME_ASC;\n\tsortList();\n}\n\n/**\n * Sorts the funding countries by funding.\n */\nvoid FundingState::sortFundingClick(Action*)\n{\n\t_fundingCountryOrder = _fundingCountryOrder == FC_FUNDING_ASC ? FC_FUNDING_DESC : FC_FUNDING_ASC;\n\tsortList();\n}\n\n/**\n * Sorts the funding countries by funding change.\n */\nvoid FundingState::sortChangeClick(Action*)\n{\n\t_fundingCountryOrder = _fundingCountryOrder == FC_CHANGE_ASC ? FC_CHANGE_DESC : FC_CHANGE_ASC;\n\tsortList();\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/FundingState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass TextList;\nclass ArrowButton;\n\n/// Funding country sorting modes.\nenum FundingCountrySort\n{\n\tFC_NONE,\n\tFC_NAME_ASC,\n\tFC_NAME_DESC,\n\tFC_FUNDING_ASC,\n\tFC_FUNDING_DESC,\n\tFC_CHANGE_ASC,\n\tFC_CHANGE_DESC\n};\n\nstruct FundingCountry\n{\n\tFundingCountry(const std::string& _name, int _funding, int _change)\n\t\t: name(_name), funding(_funding), change(_change)\n\t{\n\t}\n\tstd::string name;\n\tint funding;\n\tint change;\n};\n\n/**\n * Funding screen accessible from the Geoscape\n * that shows all the countries' funding.\n */\nclass FundingState : public State\n{\nprivate:\n\tTextButton *_btnOk;\n\tWindow *_window;\n\tText *_txtTitle, *_txtCountry, *_txtFunding, *_txtChange;\n\tTextList *_lstCountries;\n\tArrowButton *_sortName, *_sortFunding, *_sortChange;\n\n\tstd::vector<FundingCountry> _fundingCountryList;\n\tFundingCountrySort _fundingCountryOrder;\n\tvoid updateArrows();\npublic:\n\t/// Creates the Funding state.\n\tFundingState();\n\t/// Cleans up the Funding state.\n\t~FundingState();\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Sets up the funding countries list.\n\tvoid init() override;\n\t/// Sorts the funding countries list.\n\tvoid sortList();\n\t/// Updates the funding countries list.\n\tvirtual void updateList();\n\t/// Handler for clicking the Name arrow.\n\tvoid sortNameClick(Action* action);\n\t/// Handler for clicking the Funding arrow.\n\tvoid sortFundingClick(Action* action);\n\t/// Handler for clicking the Change arrow.\n\tvoid sortChangeClick(Action* action);\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/GeoscapeCraftState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"GeoscapeCraftState.h\"\n#include <sstream>\n#include \"../fmath.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/Craft.h\"\n#include \"../Mod/RuleCraft.h\"\n#include \"../Savegame/CraftWeapon.h\"\n#include \"../Mod/RuleCraftWeapon.h\"\n#include \"../Savegame/Target.h\"\n#include \"../Savegame/Ufo.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Waypoint.h\"\n#include \"SelectDestinationState.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Unicode.h\"\n#include \"Globe.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Geoscape Craft window.\n * @param game Pointer to the core game.\n * @param craft Pointer to the craft to display.\n * @param globe Pointer to the Geoscape globe.\n * @param waypoint Pointer to the last UFO position (if redirecting the craft).\n */\nGeoscapeCraftState::GeoscapeCraftState(Craft *craft, Globe *globe, Waypoint *waypoint, bool useCustomSound) : _craft(craft), _globe(globe), _waypoint(waypoint)\n{\n\t_screen = false;\n\n\t_weaponNum = _craft->getRules()->getWeapons();\n\tif (_weaponNum > RuleCraft::WeaponMax)\n\t\t_weaponNum = RuleCraft::WeaponMax;\n\n\tconst int offset_upper = -8;\n\tconst int offset_lower = 120;\n\n\tif (useCustomSound)\n\t{\n\t\tint soundId = craft->getRules()->getSelectSound();\n\t\tif (soundId != Mod::NO_SOUND)\n\t\t{\n\t\t\t_customSound = _game->getMod()->getSound(\"GEO.CAT\", soundId);\n\t\t}\n\t}\n\n\t// Create objects\n\t_window = new Window(this, 240, 192, 4, 4, POPUP_BOTH);\n\t_txtTitle = new Text(210, 17, 32, offset_upper + 20);\n\t_txtStatus = new Text(210, 17, 32, offset_upper + 36);\n\t_txtBase = new Text(210, 9, 32, offset_upper + 52);\n\t_txtSpeed = new Text(210, 9, 32, offset_upper + 60);\n\t_txtMaxSpeed = new Text(210, 9, 32, offset_upper + 68);\n\t_txtAltitude = new Text(210, 9, 32, offset_upper + 76);\n\t_txtSoldier = new Text(80, 9, 164, offset_upper + 60);\n\t_txtHWP = new Text(80, 9, 164, offset_upper + 68);\n\t_txtFuel = new Text(130, 9, 32, offset_upper + 84);\n\t_txtDamage = new Text(80, 9, 164, offset_upper + 84);\n\t_txtShield = new Text(80, 9, 164, offset_upper + 76);\n\n\tfor (int i = 0; i < _weaponNum; ++i)\n\t{\n\t\t_txtWeaponName[i] = new Text(130, 9, 32, offset_upper + 92 + 8*i);\n\t\t_txtWeaponAmmo[i] = new Text(80, 9, 164, offset_upper + 92 + 8*i);\n\t}\n\t_txtRedirect = new Text(230, 17, 13, offset_lower + 0);\n\t_txtETA = new Text(230, 9, 13, offset_lower + 4);\n\t_btnBase = new TextButton(192, 12, 32, offset_lower + 14);\n\t_btnTarget = new TextButton(192, 12, 32, offset_lower + 28);\n\t_btnPatrol = new TextButton(192, 12, 32, offset_lower + 42);\n\t_btnCancel = new TextButton(192, 12, 32, offset_lower + 56);\n\n\t// Set palette\n\tsetInterface(\"geoCraft\");\n\n\tadd(_window, \"window\", \"geoCraft\");\n\tadd(_btnBase, \"button\", \"geoCraft\");\n\tadd(_btnTarget, \"button\", \"geoCraft\");\n\tadd(_btnPatrol, \"button\", \"geoCraft\");\n\tadd(_btnCancel, \"button\", \"geoCraft\");\n\tadd(_txtTitle, \"text1\", \"geoCraft\");\n\tadd(_txtStatus, \"text1\", \"geoCraft\");\n\tadd(_txtBase, \"text3\", \"geoCraft\");\n\tadd(_txtSpeed, \"text3\", \"geoCraft\");\n\tadd(_txtMaxSpeed, \"text3\", \"geoCraft\");\n\tadd(_txtAltitude, \"text3\", \"geoCraft\");\n\tadd(_txtFuel, \"text3\", \"geoCraft\");\n\tadd(_txtDamage, \"text3\", \"geoCraft\");\n\tadd(_txtShield, \"text3\", \"geoCraft\");\n\tfor (int i = 0; i < _weaponNum; ++i)\n\t{\n\t\tadd(_txtWeaponName[i], \"text3\", \"geoCraft\");\n\t\tadd(_txtWeaponAmmo[i], \"text3\", \"geoCraft\");\n\t}\n\tadd(_txtRedirect, \"text3\", \"geoCraft\");\n\tadd(_txtETA, \"text3\", \"geoCraft\");\n\tadd(_txtSoldier, \"text3\", \"geoCraft\");\n\tadd(_txtHWP, \"text3\", \"geoCraft\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"geoCraft\");\n\n\t_btnBase->setText(tr(\"STR_RETURN_TO_BASE\"));\n\t_btnBase->onMouseClick((ActionHandler)&GeoscapeCraftState::btnBaseClick);\n\n\t_btnTarget->setText(tr(\"STR_SELECT_NEW_TARGET\"));\n\t_btnTarget->onMouseClick((ActionHandler)&GeoscapeCraftState::btnTargetClick);\n\n\t_btnPatrol->setText(_craft->getRules()->canAutoPatrol() ? tr(\"STR_AUTO_PATROL\") : tr(\"STR_PATROL\"));\n\t_btnPatrol->onMouseClick((ActionHandler)&GeoscapeCraftState::btnPatrolClick);\n\n\t_btnCancel->setText(tr(\"STR_CANCEL_UC\"));\n\t_btnCancel->onMouseClick((ActionHandler)&GeoscapeCraftState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&GeoscapeCraftState::btnCancelClick, Options::keyCancel);\n\n\t_txtTitle->setBig();\n\t_txtTitle->setText(_craft->getName(_game->getLanguage()));\n\n\t_txtStatus->setWordWrap(true);\n\tstd::string status;\n\tif (_waypoint != 0)\n\t{\n\t\tstatus = tr(\"STR_INTERCEPTING_UFO\").arg(_waypoint->getId());\n\t}\n\telse if (_craft->getLowFuel())\n\t{\n\t\tstatus = tr(\"STR_LOW_FUEL_RETURNING_TO_BASE\");\n\t}\n\telse if (_craft->getMissionComplete())\n\t{\n\t\tstatus = tr(\"STR_MISSION_COMPLETE_RETURNING_TO_BASE\");\n\t}\n\telse if (_craft->getDestination() == 0)\n\t{\n\t\tstatus = tr(\"STR_PATROLLING\");\n\t}\n\telse if (_craft->getDestination() == (Target*)_craft->getBase())\n\t{\n\t\tstatus = tr(\"STR_RETURNING_TO_BASE\");\n\t}\n\telse\n\t{\n\t\tUfo *u = dynamic_cast<Ufo*>(_craft->getDestination());\n\t\tif (u != 0)\n\t\t{\n\t\t\tif (_craft->isInDogfight())\n\t\t\t{\n\t\t\t\tstatus = tr(\"STR_TAILING_UFO\");\n\t\t\t}\n\t\t\telse if (u->getStatus() == Ufo::FLYING)\n\t\t\t{\n\t\t\t\tstatus = tr(\"STR_INTERCEPTING_UFO\").arg(u->getId());\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tstatus = tr(\"STR_DESTINATION_UC_\").arg(u->getName(_game->getLanguage()));\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tstatus = tr(\"STR_DESTINATION_UC_\").arg(_craft->getDestination()->getName(_game->getLanguage()));\n\t\t}\n\t}\n\t_txtStatus->setText(tr(\"STR_STATUS_\").arg(status));\n\n\t_txtBase->setText(tr(\"STR_BASE_UC\").arg(_craft->getBase()->getName()));\n\n\t{\n\t\tint speed = _craft->getSpeed();\n\t\tif (_craft->isInDogfight())\n\t\t{\n\t\t\tUfo *ufo = dynamic_cast<Ufo*>(_craft->getDestination());\n\t\t\tif (ufo)\n\t\t\t{\n\t\t\t\tspeed = ufo->getSpeed();\n\t\t\t}\n\t\t}\n\t\t_txtSpeed->setText(tr(\"STR_SPEED_\").arg(Unicode::formatNumber(speed)));\n\t}\n\n\t_txtMaxSpeed->setText(tr(\"STR_MAXIMUM_SPEED_UC\").arg(Unicode::formatNumber(_craft->getCraftStats().speedMax)));\n\n\tstd::string altitude = _craft->getAltitude();\n\tif (_craft->getRules()->isWaterOnly() && !_globe->insideLand(_craft->getLongitude(), _craft->getLatitude()))\n\t{\n\t\taltitude = \"STR_AIRBORNE\";\n\t}\n\t_txtAltitude->setText(tr(\"STR_ALTITUDE_\").arg(tr(altitude)));\n\n\t_txtFuel->setText(tr(\"STR_FUEL\").arg(Unicode::formatPercentage(_craft->getFuelPercentage())));\n\n\t_txtDamage->setText(tr(\"STR_DAMAGE_UC_\").arg(Unicode::formatPercentage(_craft->getDamagePercentage())));\n\n\t_txtShield->setText(tr(\"STR_SHIELD\").arg(Unicode::formatPercentage(_craft->getShieldPercentage())));\n\t_txtShield->setVisible(_craft->getShieldCapacity() != 0);\n\n\tfor (int i = 0; i < _weaponNum; ++i)\n\t{\n\t\tconst std::string &wName = _craft->getRules()->getWeaponSlotString(i);\n\t\tif (wName.empty())\n\t\t{\n\t\t\t_txtWeaponName[i]->setVisible(false);\n\t\t\t_txtWeaponAmmo[i]->setVisible(false);\n\t\t\tcontinue;\n\t\t}\n\n\t\tCraftWeapon *w1 = _craft->getWeapons()->at(i);\n\t\tif (w1 != 0)\n\t\t{\n\t\t\t_txtWeaponName[i]->setText(tr(wName).arg(tr(w1->getRules()->getType())));\n\t\t\tif (w1->getRules()->getAmmoMax())\n\t\t\t\t_txtWeaponAmmo[i]->setText(tr(\"STR_ROUNDS_\").arg(w1->getAmmo()));\n\t\t\telse\n\t\t\t\t_txtWeaponAmmo[i]->setVisible(false);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_txtWeaponName[i]->setText(tr(wName).arg(tr(\"STR_NONE_UC\")));\n\t\t\t_txtWeaponAmmo[i]->setVisible(false);\n\t\t}\n\t}\n\n\t_txtRedirect->setBig();\n\t_txtRedirect->setAlign(ALIGN_CENTER);\n\t_txtRedirect->setText(tr(\"STR_REDIRECT_CRAFT\"));\n\n\tstd::ostringstream ss11;\n\tss11 << tr(\"STR_SOLDIERS_UC\") << \">\" << Unicode::TOK_COLOR_FLIP << _craft->getNumTotalSoldiers();\n\t_txtSoldier->setText(ss11.str());\n\n\tstd::ostringstream ss12;\n\tss12 << tr(\"STR_HWPS\") << \">\" << Unicode::TOK_COLOR_FLIP << _craft->getNumTotalVehicles();\n\t_txtHWP->setText(ss12.str());\n\n\tif (_waypoint == 0)\n\t{\n\t\t_txtRedirect->setVisible(false);\n\n\t\t// ETA display\n\t\tif (Options::oxceShowETAMode > 0 && _craft->getDestination())\n\t\t{\n\t\t\tMovingTarget* mt = dynamic_cast<MovingTarget*>(_craft->getDestination());\n\t\t\tif (Options::oxceShowETAMode == 1 && mt && mt->getSpeed() > 0)\n\t\t\t{\n\t\t\t\t// don't show ETA for moving targets (i.e. UFOs and crafts)\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tint speed = _craft->getCraftStats().speedMax;\n\t\t\t\tint distance = XcomDistance(_craft->getDistance(_craft->getDestination()));\n\t\t\t\tint etaInHoursHelper = (distance + (speed / 2)) / speed;\n\t\t\t\tint days = etaInHoursHelper / 24;\n\t\t\t\tint hours = etaInHoursHelper % 24;\n\t\t\t\tstd::ostringstream ssStatus;\n\t\t\t\tif (days > 0) ssStatus << tr(\"STR_DAY_SHORT\").arg(days);\n\t\t\t\tif (hours > 0 || days == 0)\n\t\t\t\t{\n\t\t\t\t\tif (days > 0) ssStatus << \"/\";\n\t\t\t\t\tssStatus << tr(\"STR_HOUR_SHORT\").arg(hours);\n\t\t\t\t}\n\t\t\t\t_txtETA->setAlign(ALIGN_CENTER);\n\t\t\t\t_txtETA->setText(tr(\"STR_ETA\").arg(ssStatus.str()));\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\t_btnCancel->setText(tr(\"STR_GO_TO_LAST_KNOWN_UFO_POSITION\"));\n\t}\n\n\tif (_craft->getLowFuel() || _craft->getMissionComplete())\n\t{\n\t\t_btnBase->setVisible(false);\n\t\t_btnTarget->setVisible(false);\n\t\t_btnPatrol->setVisible(false);\n\t}\n\n\tif (_craft->getRules()->getMaxUnitsLimit() == 0)\n\t\t_txtSoldier->setVisible(false);\n\tif (_craft->getRules()->getMaxVehiclesAndLargeSoldiersLimit() == 0)\n\t\t_txtHWP->setVisible(false);\n}\n\n/**\n *\n */\nGeoscapeCraftState::~GeoscapeCraftState()\n{\n\n}\n\n/**\n * Returns the craft back to its base.\n * @param action Pointer to an action.\n */\nvoid GeoscapeCraftState::btnBaseClick(Action *)\n{\n\t_game->popState();\n\t_craft->returnToBase();\n\tdelete _waypoint;\n\tif (_craft->getRules()->canAutoPatrol())\n\t{\n\t\t// cancel auto-patrol\n\t\t_craft->setIsAutoPatrolling(false);\n\t}\n}\n\n/**\n * Changes the craft's target.\n * @param action Pointer to an action.\n */\nvoid GeoscapeCraftState::btnTargetClick(Action *)\n{\n\t_game->popState();\n\t_game->pushState(new SelectDestinationState(std::vector{ _craft }, _globe));\n\tdelete _waypoint;\n}\n\n/**\n * Sets the craft to patrol the current location.\n * @param action Pointer to an action.\n */\nvoid GeoscapeCraftState::btnPatrolClick(Action *)\n{\n\t_game->popState();\n\t_craft->setDestination(0);\n\tdelete _waypoint;\n\tif (_craft->getRules()->canAutoPatrol())\n\t{\n\t\t// start auto-patrol\n\t\t_craft->setLatitudeAuto(_craft->getLatitude());\n\t\t_craft->setLongitudeAuto(_craft->getLongitude());\n\t\t_craft->setIsAutoPatrolling(true);\n\t}\n}\n\n/**\n * Closes the window.\n * @param action Pointer to an action.\n */\nvoid GeoscapeCraftState::btnCancelClick(Action *)\n{\n\t// Go to the last known UFO position\n\tif (_waypoint != 0)\n\t{\n\t\t_waypoint->setId(_game->getSavedGame()->getId(\"STR_WAY_POINT\"));\n\t\t_game->getSavedGame()->getWaypoints()->push_back(_waypoint);\n\t\t_craft->setDestination(_waypoint);\n\t}\n\t// Cancel\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/GeoscapeCraftState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include \"../Mod/RuleCraft.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass Craft;\nclass Globe;\nclass Waypoint;\n\n/**\n * Craft window that displays info about\n * a specific craft out on the Geoscape.\n */\nclass GeoscapeCraftState : public State\n{\nprivate:\n\tCraft *_craft;\n\tGlobe *_globe;\n\tWaypoint *_waypoint;\n\n\tTextButton *_btnBase, *_btnTarget, *_btnPatrol, *_btnCancel;\n\tWindow *_window;\n\tText *_txtTitle, *_txtStatus, *_txtBase, *_txtSpeed, *_txtMaxSpeed, *_txtAltitude, *_txtFuel;\n\tText *_txtSoldier, *_txtHWP, *_txtShield, *_txtDamage;\n\tText *_txtWeaponName[RuleCraft::WeaponMax], *_txtWeaponAmmo[RuleCraft::WeaponMax];\n\tText *_txtRedirect;\n\tText *_txtETA;\n\n\tint _weaponNum;\npublic:\n\t/// Creates the Geoscape Craft state.\n\tGeoscapeCraftState(Craft *craft, Globe *globe, Waypoint *waypoint, bool useCustomSound);\n\t/// Cleans up the Geoscape Craft state.\n\t~GeoscapeCraftState();\n\t/// Handler for clicking the Return To Base button.\n\tvoid btnBaseClick(Action *action);\n\t/// Handler for clicking the Select New Target button.\n\tvoid btnTargetClick(Action *action);\n\t/// Handler for clicking the Patrol button.\n\tvoid btnPatrolClick(Action *action);\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/GeoscapeEventState.cpp",
    "content": "/*\n * Copyright 2010-2019 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"GeoscapeEventState.h\"\n#include \"GeoscapeState.h\"\n#include <map>\n#include \"../Basescape/SellState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/RNG.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/ToggleTextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Menu/CutsceneState.h\"\n#include \"../Menu/ErrorMessageState.h\"\n#include \"../Mod/City.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleEvent.h\"\n#include \"../Mod/RuleInterface.h\"\n#include \"../Mod/RuleRegion.h\"\n#include \"../Mod/RuleSoldier.h\"\n#include \"../Mod/RuleVideo.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/ItemContainer.h\"\n#include \"../Savegame/Region.h\"\n#include \"../Savegame/ResearchDiary.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Soldier.h\"\n#include \"../Savegame/Transfer.h\"\n#include \"../Ufopaedia/Ufopaedia.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Geoscape Event window.\n * @param geoEvent Pointer to the event.\n */\nGeoscapeEventState::GeoscapeEventState(const RuleEvent& eventRule) : _eventRule(eventRule)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 256, 176, 32, 12, POPUP_BOTH);\n\t_txtTitle = new Text(236, 32, 42, 23);\n\t_txtMessage = new Text(236, 96, 42, 58);\n\t_btnOk = new TextButton(108, 18, 48, 158);\n\t_btnItemsArriving = new ToggleTextButton(108, 18, 164, 158);\n\t_txtItem = new Text(114, 9, 44, 58);\n\t_txtQuantity = new Text(94, 9, 182, 58);\n\t_lstTransfers = new TextList(216, 80, 42, 69);\n\n\t// Set palette\n\tsetInterface(\"geoscapeEvent\");\n\n\tadd(_window, \"window\", \"geoscapeEvent\");\n\tadd(_txtTitle, \"text1\", \"geoscapeEvent\");\n\tadd(_txtMessage, \"text2\", \"geoscapeEvent\");\n\tadd(_btnOk, \"button\", \"geoscapeEvent\");\n\tadd(_btnItemsArriving, \"button\", \"geoscapeEvent\");\n\tadd(_txtItem, \"text2\", \"geoscapeEvent\");\n\tadd(_txtQuantity, \"text2\", \"geoscapeEvent\");\n\tadd(_lstTransfers, \"list\", \"geoscapeEvent\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\t_window->setBackground(_game->getMod()->getSurface(_eventRule.getBackground()));\n\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setBig();\n\t_txtTitle->setWordWrap(true);\n\t_txtTitle->setText(tr(_eventRule.getName()));\n\n\t_txtMessage->setVerticalAlign(ALIGN_TOP);\n\t_txtMessage->setWordWrap(true);\n\t_txtMessage->setText(tr(_eventRule.getDescription()));\n\tif (_eventRule.alignBottom())\n\t{\n\t\t_txtMessage->setVerticalAlign(ALIGN_BOTTOM);\n\t}\n\t_txtMessage->setScrollable(true);\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)& GeoscapeEventState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&GeoscapeEventState::btnOkClick, Options::keyOk);\n\t_btnOk->onKeyboardPress((ActionHandler)&GeoscapeEventState::btnOkClick, Options::keyCancel);\n\n\t_btnItemsArriving->setText(tr(\"STR_ITEMS_ARRIVING\"));\n\t_btnItemsArriving->onMouseClick((ActionHandler)&GeoscapeEventState::btnItemsArrivingClick);\n\n\t_txtItem->setText(tr(\"STR_ITEM\"));\n\t_txtQuantity->setText(tr(\"STR_QUANTITY_UC\"));\n\n\t_lstTransfers->setColumns(2, 155, 41);\n\t_lstTransfers->setSelectable(true);\n\t_lstTransfers->setBackground(_window);\n\t_lstTransfers->setMargin(2);\n\n\teventLogic();\n\n\t_txtItem->setVisible(false);\n\t_txtQuantity->setVisible(false);\n\t_lstTransfers->setVisible(false);\n\n\tif (_eventRule.getInvert())\n\t{\n\t\t_btnItemsArriving->setText(tr(\"STR_SUMMARY\"));\n\t}\n\telse if (_lstTransfers->getTexts() == 0 || !Options::oxceGeoscapeEventsInstantDelivery)\n\t{\n\t\t_btnOk->setX((_btnOk->getX() + _btnItemsArriving->getX()) / 2);\n\t\t_btnItemsArriving->setVisible(false);\n\t}\n}\n\n/**\n * Helper performing event logic.\n */\nvoid GeoscapeEventState::eventLogic()\n{\n\tif (!_eventRule.getAdhocMissionScriptTags().empty())\n\t{\n\t\tauto* geo = _game->getGeoscapeState();\n\t\tgeo->determineAlienMissions(false, &_eventRule);\n\t}\n\n\tSavedGame *save = _game->getSavedGame();\n\tBase *hq = save->getBases()->front();\n\tconst Mod *mod = _game->getMod();\n\tconst RuleEvent &rule = _eventRule;\n\n\tRuleRegion *regionRule = nullptr;\n\tCity* city = nullptr;\n\tif (!rule.getRegionList().empty())\n\t{\n\t\tsize_t pickRegion = RNG::generate(0, rule.getRegionList().size() - 1);\n\t\tauto& regionName = rule.getRegionList().at(pickRegion);\n\t\tregionRule = _game->getMod()->getRegion(regionName, true);\n\t\tstd::string place = tr(regionName);\n\n\t\tif (rule.isCitySpecific())\n\t\t{\n\t\t\tsize_t cities = regionRule->getCities()->size();\n\t\t\tif (cities > 0)\n\t\t\t{\n\t\t\t\tsize_t pickCity = RNG::generate(0, cities - 1);\n\t\t\t\tcity = regionRule->getCities()->at(pickCity);\n\t\t\t\tplace = city->getName(_game->getLanguage());\n\t\t\t}\n\t\t}\n\n\t\tstd::string titlePlus = tr(rule.getName()).arg(place);\n\t\t_txtTitle->setText(titlePlus);\n\n\t\tstd::string messagePlus = tr(rule.getDescription()).arg(place);\n\t\t_txtMessage->setText(messagePlus);\n\t}\n\n\t// even if the event isn't city-specific, we'll still pick one city randomly to represent the region (and maybe even a country)\n\tif (regionRule)\n\t{\n\t\tif (!rule.isCitySpecific())\n\t\t{\n\t\t\tsize_t cities = regionRule->getCities()->size();\n\t\t\tif (cities > 0)\n\t\t\t{\n\t\t\t\tsize_t pickCity = RNG::generate(0, cities - 1);\n\t\t\t\tcity = regionRule->getCities()->at(pickCity);\n\t\t\t}\n\t\t}\n\t}\n\n\t// 1. give/take score points\n\tif (regionRule)\n\t{\n\t\tfor (auto* region : *_game->getSavedGame()->getRegions())\n\t\t{\n\t\t\tif (region->getRules() == regionRule)\n\t\t\t{\n\t\t\t\tregion->addActivityXcom(rule.getPoints());\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\tsave->addResearchScore(rule.getPoints());\n\t}\n\n\t// 2. give/take funds\n\tsave->setFunds(save->getFunds() + rule.getFunds());\n\n\t// 3. spawn/transfer persons (soldiers, engineers, scientists, ...)\n\tconst std::string& spawnedPersonType = rule.getSpawnedPersonType();\n\tif (rule.getSpawnedPersons() > 0 && !spawnedPersonType.empty())\n\t{\n\t\tif (spawnedPersonType == \"STR_SCIENTIST\")\n\t\t{\n\t\t\tTransfer* t = new Transfer(24);\n\t\t\tt->setScientists(rule.getSpawnedPersons());\n\t\t\thq->getTransfers()->push_back(t);\n\t\t}\n\t\telse if (spawnedPersonType == \"STR_ENGINEER\")\n\t\t{\n\t\t\tTransfer* t = new Transfer(24);\n\t\t\tt->setEngineers(rule.getSpawnedPersons());\n\t\t\thq->getTransfers()->push_back(t);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tRuleSoldier* ruleSoldier = mod->getSoldier(spawnedPersonType);\n\t\t\tif (ruleSoldier)\n\t\t\t{\n\t\t\t\tfor (int i = 0; i < rule.getSpawnedPersons(); ++i)\n\t\t\t\t{\n\t\t\t\t\tTransfer* t = new Transfer(24);\n\t\t\t\t\tint nationality = _game->getSavedGame()->selectSoldierNationalityByLocation(_game->getMod(), ruleSoldier, city);\n\t\t\t\t\tSoldier* s = mod->genSoldier(save, ruleSoldier, nationality);\n\t\t\t\t\tYAML::YamlRootNodeReader reader(rule.getSpawnedSoldierTemplate(), \"(spawned soldier template)\");\n\t\t\t\t\ts->load(reader, mod, save, mod->getScriptGlobal(), true); // load from soldier template\n\t\t\t\t\tif (!rule.getSpawnedPersonName().empty())\n\t\t\t\t\t{\n\t\t\t\t\t\ts->setName(tr(rule.getSpawnedPersonName()));\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\ts->genName();\n\t\t\t\t\t}\n\t\t\t\t\tt->setSoldier(s);\n\t\t\t\t\thq->getTransfers()->push_back(t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// 3. spawn/transfer multiple soldiers into the HQ\n\t{\n\t\tstd::map<const RuleSoldier*, int> soldiersToTransfer;\n\n\t\tfor (auto& pair : rule.getEveryMultiSoldierList())\n\t\t{\n\t\t\tconst RuleSoldier* soldierRule = mod->getSoldier(pair.first, true);\n\t\t\tif (soldierRule)\n\t\t\t{\n\t\t\t\tsoldiersToTransfer[soldierRule] += pair.second;\n\t\t\t}\n\t\t}\n\n\t\tif (!rule.getRandomMultiSoldierList().empty())\n\t\t{\n\t\t\tsize_t pickSoldier = RNG::generate(0, rule.getRandomMultiSoldierList().size() - 1);\n\t\t\tauto& sublist = rule.getRandomMultiSoldierList().at(pickSoldier);\n\t\t\tfor (auto& pair : sublist)\n\t\t\t{\n\t\t\t\tconst RuleSoldier* soldierRule = mod->getSoldier(pair.first, true);\n\t\t\t\tif (soldierRule)\n\t\t\t\t{\n\t\t\t\t\tsoldiersToTransfer[soldierRule] += pair.second;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (auto& ts : soldiersToTransfer)\n\t\t{\n\t\t\tfor (int i = 0; i < ts.second; ++i)\n\t\t\t{\n\t\t\t\tTransfer* t = new Transfer(24);\n\t\t\t\tint nationality = _game->getSavedGame()->selectSoldierNationalityByLocation(_game->getMod(), ts.first, city);\n\t\t\t\tSoldier* s = mod->genSoldier(save, ts.first, nationality);\n\t\t\t\tYAML::YamlRootNodeReader reader(rule.getSpawnedSoldierTemplate(), \"(spawned soldier template)\");\n\t\t\t\ts->load(reader, mod, save, mod->getScriptGlobal(), true); // load from soldier template\n\t\t\t\t{\n\t\t\t\t\t// reset what may have been loaded\n\t\t\t\t\ts->genName();\n\t\t\t\t}\n\t\t\t\tt->setSoldier(s);\n\t\t\t\thq->getTransfers()->push_back(t);\n\t\t\t}\n\t\t}\n\t}\n\n\t// 3. spawn/transfer item into the HQ\n\tstd::map<std::string, int> itemsToTransfer;\n\n\tfor (auto& pair : rule.getEveryMultiItemList())\n\t{\n\t\tconst RuleItem *itemRule = mod->getItem(pair.first, true);\n\t\tif (itemRule)\n\t\t{\n\t\t\titemsToTransfer[itemRule->getType()] += pair.second;\n\t\t}\n\t}\n\n\tfor (auto& itemName : rule.getEveryItemList())\n\t{\n\t\tconst RuleItem *itemRule = mod->getItem(itemName, true);\n\t\tif (itemRule)\n\t\t{\n\t\t\titemsToTransfer[itemRule->getType()] += 1;\n\t\t}\n\t}\n\n\tif (!rule.getRandomItemList().empty())\n\t{\n\t\tsize_t pickItem = RNG::generate(0, rule.getRandomItemList().size() - 1);\n\t\tconst RuleItem *randomItem = mod->getItem(rule.getRandomItemList().at(pickItem), true);\n\t\tif (randomItem)\n\t\t{\n\t\t\titemsToTransfer[randomItem->getType()] += 1;\n\t\t}\n\t}\n\n\tif (!rule.getRandomMultiItemList().empty())\n\t{\n\t\tsize_t pickItem = RNG::generate(0, rule.getRandomMultiItemList().size() - 1);\n\t\tauto& sublist = rule.getRandomMultiItemList().at(pickItem);\n\t\tfor (auto& pair : sublist)\n\t\t{\n\t\t\tconst RuleItem* itemRule = mod->getItem(pair.first, true);\n\t\t\tif (itemRule)\n\t\t\t{\n\t\t\t\titemsToTransfer[itemRule->getType()] += pair.second;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (!rule.getWeightedItemList().empty())\n\t{\n\t\tconst RuleItem *randomItem = mod->getItem(rule.getWeightedItemList().choose(), true);\n\t\tif (randomItem)\n\t\t{\n\t\t\titemsToTransfer[randomItem->getType()] += 1;\n\t\t}\n\t}\n\n\tfor (auto& ti : itemsToTransfer)\n\t{\n\t\tif (rule.getInvert())\n\t\t{\n\t\t\tRuleItem* r = mod->getItem(ti.first, true);\n\t\t\tint removed = 0;\n\t\t\tfor (auto* xbase : *save->getBases())\n\t\t\t{\n\t\t\t\tint bQty = xbase->getStorageItems()->getItem(r);\n\t\t\t\tif (bQty > 0)\n\t\t\t\t{\n\t\t\t\t\tint toRemove = std::min(bQty, ti.second);\n\t\t\t\t\txbase->getStorageItems()->removeItem(r, toRemove);\n\t\t\t\t\tti.second -= toRemove;\n\t\t\t\t\tremoved += toRemove;\n\t\t\t\t}\n\t\t\t\tif (ti.second <= 0) break; // already removed enough\n\t\t\t}\n\t\t\tif (ti.second > 0)\n\t\t\t{\n\t\t\t\tfor (auto* xbase : *save->getBases())\n\t\t\t\t{\n\t\t\t\t\tfor (auto* xcraft : *xbase->getCrafts())\n\t\t\t\t\t{\n\t\t\t\t\t\tint cQty = xcraft->getItems()->getItem(r);\n\t\t\t\t\t\tif (cQty > 0 && xcraft->getStatus() != \"STR_OUT\")\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tint toRemove = std::min(cQty, ti.second);\n\t\t\t\t\t\t\txcraft->getItems()->removeItem(r, toRemove);\n\t\t\t\t\t\t\tti.second -= toRemove;\n\t\t\t\t\t\t\tremoved += toRemove;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (ti.second <= 0) break; // already removed enough\n\t\t\t\t\t}\n\t\t\t\t\tif (ti.second <= 0) break; // already removed enough\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tstd::ostringstream ss;\n\t\t\tss << -removed;\n\t\t\t_lstTransfers->addRow(2, tr(ti.first).c_str(), ss.str().c_str());\n\t\t}\n\t\telse if (Options::oxceGeoscapeEventsInstantDelivery)\n\t\t{\n\t\t\thq->getStorageItems()->addItem(mod->getItem(ti.first, true), ti.second);\n\n\t\t\tstd::ostringstream ss;\n\t\t\tss << ti.second;\n\t\t\t_lstTransfers->addRow(2, tr(ti.first).c_str(), ss.str().c_str());\n\t\t}\n\t\telse\n\t\t{\n\t\t\tTransfer* t = new Transfer(1);\n\t\t\tt->setItems(mod->getItem(ti.first, true), ti.second);\n\t\t\thq->getTransfers()->push_back(t);\n\t\t}\n\t}\n\n\t// 3b. spawn craft into the HQ\n\tconst RuleCraft* craftRule = mod->getCraft(rule.getSpawnedCraftType(), true);\n\tif (craftRule)\n\t{\n\t\tCraft* craft = new Craft(craftRule, hq, save->getId(craftRule->getType()));\n\t\tcraft->initFixedWeapons(mod);\n\t\tif (Options::oxceGeoscapeEventsInstantDelivery)\n\t\t{\n\t\t\t// same as manufacture\n\t\t\tcraft->checkup();\n\t\t\thq->getCrafts()->push_back(craft);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// same as buy\n\t\t\tcraft->setStatus(\"STR_REFUELLING\");\n\t\t\tTransfer* t = new Transfer(1);\n\t\t\tt->setCraft(craft);\n\t\t\thq->getTransfers()->push_back(t);\n\t\t}\n\t}\n\n\t// 4. give bonus research\n\tstd::vector<const RuleResearch*> possibilities;\n\n\tfor (auto* rRule : rule.getResearchList())\n\t{\n\t\tif (!save->isResearched(rRule, false) || save->hasUndiscoveredGetOneFree(rRule, true))\n\t\t{\n\t\t\tpossibilities.push_back(rRule);\n\t\t}\n\t}\n\n\tstd::vector<const RuleResearch*> topicsToCheck;\n\tif (!possibilities.empty())\n\t{\n\t\tsize_t pickResearch = RNG::generate(0, possibilities.size() - 1);\n\t\tconst RuleResearch *eventResearch = possibilities.at(pickResearch);\n\n\t\tbool alreadyResearched = save->isResearched(eventResearch->getLookup() ? eventResearch->getLookup() : eventResearch, false); // we have seen the pedia article already, don't show it again\n\n\t\tauto addResearchDiaryEntryForEvent = [&](const RuleResearch* discoveredResearch, DiscoverySourceType sourceType, const RuleEvent* sourceEvent, const RuleResearch* sourceResearch)\n\t\t{\n\t\t\tif (!save->isResearched(discoveredResearch, false) && !save->isResearchRuleStatusDisabled(discoveredResearch->getName()))\n\t\t\t{\n\t\t\t\tResearchDiaryEntry* entry = new ResearchDiaryEntry(discoveredResearch);\n\t\t\t\tentry->setDate(save->getTime());\n\t\t\t\tentry->source.type = sourceType;\n\t\t\t\tif (sourceType == DiscoverySourceType::EVENT)\n\t\t\t\t{\n\t\t\t\t\tentry->source.event = sourceEvent;\n\t\t\t\t\tentry->source.name = sourceEvent->getName();\n\t\t\t\t}\n\t\t\t\telse // sourceType == DiscoverySourceType::FREE_FROM\n\t\t\t\t{\n\t\t\t\t\tentry->source.research = sourceResearch;\n\t\t\t\t\tentry->source.name = sourceResearch->getName();\n\t\t\t\t}\n\t\t\t\tsave->addResearchDiaryEntry(entry);\n\t\t\t}\n\t\t};\n\n\t\taddResearchDiaryEntryForEvent(eventResearch, DiscoverySourceType::EVENT, &rule, nullptr);\n\t\tsave->addFinishedResearch(eventResearch, mod, hq, true);\n\t\ttopicsToCheck.push_back(eventResearch);\n\t\t_researchName = alreadyResearched ? \"\" : eventResearch->getName();\n\n\t\tif (const RuleResearch *lookupResearch = eventResearch->getLookup())\n\t\t{\n\t\t\taddResearchDiaryEntryForEvent(lookupResearch, DiscoverySourceType::EVENT, &rule, nullptr);\n\t\t\tsave->addFinishedResearch(lookupResearch, mod, hq, true);\n\t\t\t_researchName = alreadyResearched ? \"\" : lookupResearch->getName();\n\t\t}\n\n\t\tif (auto* bonus = save->selectGetOneFree(eventResearch))\n\t\t{\n\t\t\taddResearchDiaryEntryForEvent(bonus, DiscoverySourceType::FREE_FROM, nullptr, eventResearch);\n\t\t\tsave->addFinishedResearch(bonus, mod, hq, true);\n\t\t\ttopicsToCheck.push_back(bonus);\n\t\t\t_bonusResearchName = bonus->getName();\n\n\t\t\tif (const RuleResearch *bonusLookup = bonus->getLookup())\n\t\t\t{\n\t\t\t\taddResearchDiaryEntryForEvent(bonusLookup, DiscoverySourceType::FREE_FROM, nullptr, eventResearch);\n\t\t\t\tsave->addFinishedResearch(bonusLookup, mod, hq, true);\n\t\t\t\t_bonusResearchName = bonusLookup->getName();\n\t\t\t}\n\t\t}\n\t}\n\n\t// Side effects:\n\t// 1. remove obsolete research projects from all bases\n\t// 2. handle items spawned by research\n\t// 3. handle events spawned by research\n\tsave->handlePrimaryResearchSideEffects(topicsToCheck, mod, hq);\n\n\tif (Options::oxceGeoscapeDebugLogMaxEntries > 0)\n\t{\n\t\tstd::ostringstream ss;\n\t\tss << \"gameTime: \" << save->getTime()->getFullString();\n\t\tss << \" eventPopup: \" << rule.getName();\n\t\tsave->getGeoscapeDebugLog().push_back(ss.str());\n\t}\n}\n\n/**\n *\n */\nGeoscapeEventState::~GeoscapeEventState()\n{\n\t// Empty by design\n}\n\n/**\n * Initializes the state.\n */\nvoid GeoscapeEventState::init()\n{\n\tState::init();\n\n\tif (!_eventRule.getMusic().empty())\n\t{\n\t\t_game->getMod()->playMusic(_eventRule.getMusic());\n\t}\n}\n\n/**\n * Closes the window and shows a pedia article if needed.\n * @param action Pointer to an action.\n */\nvoid GeoscapeEventState::btnOkClick(Action *)\n{\n\t_game->popState();\n\n\tif (!_eventRule.getCutscene().empty())\n\t{\n\t\t_game->pushState(new CutsceneState(_eventRule.getCutscene()));\n\t\tif (_game->getSavedGame()->getEnding() == END_NONE)\n\t\t{\n\t\t\tconst RuleVideo* videoRule = _game->getMod()->getVideo(_eventRule.getCutscene(), true);\n\t\t\tif (videoRule->getWinGame()) _game->getSavedGame()->setEnding(END_WIN);\n\t\t\tif (videoRule->getLoseGame()) _game->getSavedGame()->setEnding(END_LOSE);\n\t\t}\n\t}\n\n\tif (_game->getSavedGame()->getEnding() == END_NONE)\n\t{\n\t\tBase* base = _game->getSavedGame()->getBases()->front();\n\t\tif (_game->getSavedGame()->getMonthsPassed() > -1 && Options::storageLimitsEnforced && base != 0 && base->storesOverfull())\n\t\t{\n\t\t\t_game->pushState(new SellState(base, 0));\n\t\t\t_game->pushState(new ErrorMessageState(tr(\"STR_STORAGE_EXCEEDED\").arg(base->getName()), _palette, _game->getMod()->getInterface(\"debriefing\")->getElement(\"errorMessage\")->color, \"BACK01.SCR\", _game->getMod()->getInterface(\"debriefing\")->getElement(\"errorPalette\")->color));\n\t\t}\n\t}\n\n\tif (!_bonusResearchName.empty())\n\t{\n\t\tUfopaedia::openArticle(_game, _bonusResearchName);\n\t}\n\tif (!_researchName.empty())\n\t{\n\t\tUfopaedia::openArticle(_game, _researchName);\n\t}\n}\n\n/**\n * Toggles the view between the description and the ItemsArriving list.\n * @param action Pointer to an action.\n */\nvoid GeoscapeEventState::btnItemsArrivingClick(Action *)\n{\n\tif (_btnItemsArriving->getPressed())\n\t{\n\t\t_txtMessage->setVisible(false);\n\n\t\t_txtItem->setVisible(true);\n\t\t_txtQuantity->setVisible(true);\n\t\t_lstTransfers->setVisible(true);\n\t}\n\telse\n\t{\n\t\t_txtItem->setVisible(false);\n\t\t_txtQuantity->setVisible(false);\n\t\t_lstTransfers->setVisible(false);\n\n\t\t_txtMessage->setVisible(true);\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/GeoscapeEventState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2019 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <map>\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass TextList;\nclass ToggleTextButton;\nclass Window;\nclass Text;\nclass RuleEvent;\n\n/**\n * Displays info about a custom Geoscape event.\n */\nclass GeoscapeEventState : public State\n{\nprivate:\n\tWindow *_window;\n\tText *_txtTitle, *_txtMessage;\n\tText *_txtItem, *_txtQuantity;\n\tTextButton *_btnOk;\n\tToggleTextButton *_btnItemsArriving;\n\tTextList *_lstTransfers;\n\n\tstd::map<std::string, int> _itemsRemoved;\n\tstd::string _researchName;\n\tstd::string _bonusResearchName;\n\tconst RuleEvent &_eventRule;\n\n\t/// Helper performing event logic.\n\tvoid eventLogic();\npublic:\n\t/// Creates the GeoscapeEventState.\n\tGeoscapeEventState(const RuleEvent& eventRule);\n\t/// Cleans up the GeoscapeEventState.\n\t~GeoscapeEventState();\n\t/// Initializes the state.\n\tvoid init() override;\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the ItemsArriving button.\n\tvoid btnItemsArrivingClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/GeoscapeState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"GeoscapeState.h\"\n#include <set>\n#include <sstream>\n#include <iomanip>\n#include <algorithm>\n#include <climits>\n#include <functional>\n#include \"../Engine/RNG.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Action.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Screen.h\"\n#include \"../Engine/Sound.h\"\n#include \"../Engine/Surface.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Collections.h\"\n#include \"../Engine/Unicode.h\"\n#include \"Globe.h\"\n#include \"../Interface/ComboBox.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Engine/Timer.h\"\n#include \"../Savegame/GameTime.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/BaseFacility.h\"\n#include \"../Mod/RuleBaseFacility.h\"\n#include \"../Savegame/Craft.h\"\n#include \"../Mod/RuleCraft.h\"\n#include \"../Savegame/Ufo.h\"\n#include \"../Mod/RuleUfo.h\"\n#include \"../Mod/RuleArcScript.h\"\n#include \"../Mod/RuleEventScript.h\"\n#include \"../Mod/RuleEvent.h\"\n#include \"../Mod/RuleMissionScript.h\"\n#include \"../Savegame/Waypoint.h\"\n#include \"../Savegame/Transfer.h\"\n#include \"../Savegame/Soldier.h\"\n#include \"../Savegame/SoldierDiary.h\"\n#include \"../Menu/PauseState.h\"\n#include \"SelectMusicTrackState.h\"\n#include \"UfoTrackerState.h\"\n#include \"InterceptState.h\"\n#include \"../Basescape/BasescapeState.h\"\n#include \"../Basescape/SellState.h\"\n#include \"../Basescape/ManageAlienContainmentState.h\"\n#include \"../Basescape/TechTreeViewerState.h\"\n#include \"../Basescape/GlobalManufactureState.h\"\n#include \"../Basescape/GlobalResearchState.h\"\n#include \"../Basescape/GlobalAlienContainmentState.h\"\n#include \"../Menu/CutsceneState.h\"\n#include \"../Menu/ErrorMessageState.h\"\n#include \"GraphsState.h\"\n#include \"FundingState.h\"\n#include \"ExtendedGeoscapeLinksState.h\"\n#include \"MonthlyReportState.h\"\n#include \"ProductionCompleteState.h\"\n#include \"UfoDetectedState.h\"\n#include \"GeoscapeCraftState.h\"\n#include \"DogfightState.h\"\n#include \"UfoLostState.h\"\n#include \"CraftPatrolState.h\"\n#include \"LowFuelState.h\"\n#include \"MultipleTargetsState.h\"\n#include \"ConfirmLandingState.h\"\n#include \"ItemsArrivingState.h\"\n#include \"CraftErrorState.h\"\n#include \"DogfightErrorState.h\"\n#include \"DogfightExperienceState.h\"\n#include \"../Ufopaedia/Ufopaedia.h\"\n#include \"../Savegame/ResearchProject.h\"\n#include \"ResearchCompleteState.h\"\n#include \"../Mod/RuleResearch.h\"\n#include \"../Savegame/ResearchDiary.h\"\n#include \"ResearchRequiredState.h\"\n#include \"NewPossibleResearchState.h\"\n#include \"NewPossibleManufactureState.h\"\n#include \"NewPossiblePurchaseState.h\"\n#include \"NewPossibleCraftState.h\"\n#include \"NewPossibleFacilityState.h\"\n#include \"TrainingFinishedState.h\"\n#include \"../Savegame/Production.h\"\n#include \"../Mod/RuleManufacture.h\"\n#include \"../Savegame/ItemContainer.h\"\n#include \"../Savegame/MissionSite.h\"\n#include \"../Savegame/AlienBase.h\"\n#include \"../Mod/RuleRegion.h\"\n#include \"MissionDetectedState.h\"\n#include \"AlienBaseState.h\"\n#include \"../Savegame/Region.h\"\n#include \"../Savegame/Country.h\"\n#include \"../Mod/RuleCountry.h\"\n#include \"../Mod/RuleAlienMission.h\"\n#include \"../Savegame/AlienStrategy.h\"\n#include \"../Savegame/AlienMission.h\"\n#include \"../Savegame/GeoscapeEvent.h\"\n#include \"GeoscapeEventState.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"../Battlescape/BattlescapeGenerator.h\"\n#include \"../Battlescape/BriefingState.h\"\n#include \"../Mod/UfoTrajectory.h\"\n#include \"../Mod/Armor.h\"\n#include \"BaseDefenseState.h\"\n#include \"BaseDestroyedState.h\"\n#include \"../Menu/LoadGameState.h\"\n#include \"../Menu/SaveGameState.h\"\n#include \"../Menu/ListSaveState.h\"\n#include \"../Mod/RuleGlobe.h\"\n#include \"../Engine/Exception.h\"\n#include \"../Mod/AlienDeployment.h\"\n#include \"../Mod/AlienRace.h\"\n#include \"../Mod/RuleInterface.h\"\n#include \"../Mod/RuleSoldier.h\"\n#include \"../Mod/RuleVideo.h\"\n#include \"../Mod/Texture.h\"\n#include \"../fmath.h\"\n#include \"../fallthrough.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Geoscape screen.\n * @param game Pointer to the core game.\n */\nGeoscapeState::GeoscapeState() : _pause(false), _zoomInEffectDone(false), _zoomOutEffectDone(false), _minimizedDogfights(0), _slowdownCounter(0)\n{\n\tint screenWidth = Options::baseXGeoscape;\n\tint screenHeight = Options::baseYGeoscape;\n\n\t// Create objects\n\tSurface *hd = _game->getMod()->getSurface(\"ALTGEOBORD.SCR\");\n\t_bg = new Surface(hd->getWidth(), hd->getHeight(), 0, 0);\n\t_sideLine = new Surface(64, screenHeight, screenWidth - 64, 0);\n\t_sidebar = new Surface(64, 200, screenWidth - 64, screenHeight / 2 - 100);\n\n\t_globe = new Globe(_game, (screenWidth-64)/2, screenHeight/2, screenWidth-64, screenHeight, 0, 0);\n\t_bg->setX((_globe->getWidth() - _bg->getWidth()) / 2);\n\t_bg->setY((_globe->getHeight() - _bg->getHeight()) / 2);\n\n\t_btnIntercept = new TextButton(63, 11, screenWidth-63, screenHeight/2-100);\n\t_btnBases = new TextButton(63, 11, screenWidth-63, screenHeight/2-88);\n\t_btnGraphs = new TextButton(63, 11, screenWidth-63, screenHeight/2-76);\n\t_btnUfopaedia = new TextButton(63, 11, screenWidth-63, screenHeight/2-64);\n\t_btnOptions = new TextButton(63, 11, screenWidth-63, screenHeight/2-52);\n\t_btnFunding = new TextButton(63, 11, screenWidth-63, screenHeight/2-40);\n\n\t_btn5Secs = new TextButton(31, 13, screenWidth-63, screenHeight/2+12);\n\t_btn1Min = new TextButton(31, 13, screenWidth-31, screenHeight/2+12);\n\t_btn5Mins = new TextButton(31, 13, screenWidth-63, screenHeight/2+26);\n\t_btn30Mins = new TextButton(31, 13, screenWidth-31, screenHeight/2+26);\n\t_btn1Hour = new TextButton(31, 13, screenWidth-63, screenHeight/2+40);\n\t_btn1Day = new TextButton(31, 13, screenWidth-31, screenHeight/2+40);\n\n\t_btnRotateLeft = new InteractiveSurface(12, 10, screenWidth-61, screenHeight/2+76);\n\t_btnRotateRight = new InteractiveSurface(12, 10, screenWidth-37, screenHeight/2+76);\n\t_btnRotateUp = new InteractiveSurface(13, 12, screenWidth-49, screenHeight/2+62);\n\t_btnRotateDown = new InteractiveSurface(13, 12, screenWidth-49, screenHeight/2+87);\n\t_btnZoomIn = new InteractiveSurface(23, 23, screenWidth-25, screenHeight/2+56);\n\t_btnZoomOut = new InteractiveSurface(13, 17, screenWidth-20, screenHeight/2+82);\n\n\tint height = (screenHeight - Screen::ORIGINAL_HEIGHT) / 2 + 10;\n\t_sideTop = new TextButton(63, height, screenWidth-63, _sidebar->getY() - height - 1);\n\t_sideBottom = new TextButton(63, height, screenWidth-63, _sidebar->getY() + _sidebar->getHeight() + 1);\n\n\t_txtHour = new Text(20, 16, screenWidth-61, screenHeight/2-26);\n\t_txtHourSep = new Text(4, 16, screenWidth-41, screenHeight/2-26);\n\t_txtMin = new Text(20, 16, screenWidth-37, screenHeight/2-26);\n\t_txtMinSep = new Text(4, 16, screenWidth-17, screenHeight/2-26);\n\t_txtSec = new Text(11, 8, screenWidth-13, screenHeight/2-20);\n\t_txtWeekday = new Text(59, 8, screenWidth-61, screenHeight/2-13);\n\t_txtDay = new Text(29, 8, screenWidth-61, screenHeight/2-6);\n\t_txtMonth = new Text(29, 8, screenWidth-32, screenHeight/2-6);\n\t_txtYear = new Text(59, 8, screenWidth-61, screenHeight/2+1);\n\t_txtFunds = new Text(59, 8, screenWidth-61, screenHeight/2-27);\n\n\tint slackingIndicatorOffset = _game->getMod()->getInterface(\"geoscape\")->getElement(\"slackingIndicator\")->custom;\n\t_txtSlacking = new Text(59, 17, screenWidth - 61, screenHeight / 2 - 100 + slackingIndicatorOffset);\n\tint trainingIndicatorOffset = _game->getMod()->getInterface(\"geoscape\")->getElement(\"trainingIndicator\")->custom;\n\t_txtTraining = new Text(59, 17, screenWidth - 61, screenHeight / 2 + 100 + trainingIndicatorOffset);\n\n\t_timeSpeed = _btn5Secs;\n\t_gameTimer = new Timer(Options::geoClockSpeed);\n\n\t_zoomInEffectTimer = new Timer(Options::dogfightSpeed);\n\t_zoomOutEffectTimer = new Timer(Options::dogfightSpeed);\n\t_dogfightStartTimer = new Timer(Options::dogfightSpeed);\n\t_dogfightTimer = new Timer(Options::dogfightSpeed);\n\n\t_txtDebug = new Text(254, 32, 0, 0);\n\t_cbxRegion = new ComboBox(this, 150, 16, 0, 36);\n\t_cbxZone = new ComboBox(this, 48, 16, 154, 36);\n\t_cbxArea = new ComboBox(this, 48, 16, 206, 36);\n\t_cbxCountry = new ComboBox(this, 150, 16, 0, 36);\n\n\t// Set palette\n\tsetInterface(\"geoscape\");\n\n\tadd(_bg);\n\tadd(_sideLine);\n\tadd(_sidebar);\n\tadd(_globe);\n\n\tadd(_btnIntercept, \"button\", \"geoscape\");\n\tadd(_btnBases, \"button\", \"geoscape\");\n\tadd(_btnGraphs, \"button\", \"geoscape\");\n\tadd(_btnUfopaedia, \"button\", \"geoscape\");\n\tadd(_btnOptions, \"button\", \"geoscape\");\n\tadd(_btnFunding, \"button\", \"geoscape\");\n\n\tadd(_btn5Secs, \"button\", \"geoscape\");\n\tadd(_btn1Min, \"button\", \"geoscape\");\n\tadd(_btn5Mins, \"button\", \"geoscape\");\n\tadd(_btn30Mins, \"button\", \"geoscape\");\n\tadd(_btn1Hour, \"button\", \"geoscape\");\n\tadd(_btn1Day, \"button\", \"geoscape\");\n\n\tadd(_btnRotateLeft);\n\tadd(_btnRotateRight);\n\tadd(_btnRotateUp);\n\tadd(_btnRotateDown);\n\tadd(_btnZoomIn);\n\tadd(_btnZoomOut);\n\n\tadd(_sideTop, \"button\", \"geoscape\");\n\tadd(_sideBottom, \"button\", \"geoscape\");\n\n\tadd(_txtFunds, \"text\", \"geoscape\");\n\tadd(_txtHour, \"text\", \"geoscape\");\n\tadd(_txtHourSep, \"text\", \"geoscape\");\n\tadd(_txtMin, \"text\", \"geoscape\");\n\tadd(_txtMinSep, \"text\", \"geoscape\");\n\tadd(_txtSec, \"text\", \"geoscape\");\n\tadd(_txtWeekday, \"text\", \"geoscape\");\n\tadd(_txtDay, \"text\", \"geoscape\");\n\tadd(_txtMonth, \"text\", \"geoscape\");\n\tadd(_txtYear, \"text\", \"geoscape\");\n\tadd(_txtSlacking, \"slackingIndicator\", \"geoscape\");\n\tadd(_txtTraining, \"trainingIndicator\", \"geoscape\");\n\n\tadd(_txtDebug, \"text\", \"geoscape\");\n\tadd(_cbxRegion, \"button\", \"geoscape\");\n\tadd(_cbxZone, \"button\", \"geoscape\");\n\tadd(_cbxArea, \"button\", \"geoscape\");\n\tadd(_cbxCountry, \"button\", \"geoscape\");\n\n\t// Set up objects\n\tSurface *geobord = _game->getMod()->getSurface(\"GEOBORD.SCR\");\n\tgeobord->setX(_sidebar->getX() - geobord->getWidth() + _sidebar->getWidth());\n\tgeobord->setY(_sidebar->getY());\n\t_sidebar->copy(geobord);\n\t_game->getMod()->getSurface(\"ALTGEOBORD.SCR\")->blitNShade(_bg, 0, 0);\n\n\t_sideLine->drawRect(0, 0, _sideLine->getWidth(), _sideLine->getHeight(), 15);\n\n\t_btnIntercept->initText(_game->getMod()->getFont(\"FONT_GEO_BIG\"), _game->getMod()->getFont(\"FONT_GEO_SMALL\"), _game->getLanguage());\n\t_btnIntercept->setText(tr(\"STR_INTERCEPT\"));\n\t_btnIntercept->onMouseClick((ActionHandler)&GeoscapeState::btnInterceptClick);\n\t_btnIntercept->onKeyboardPress((ActionHandler)&GeoscapeState::btnInterceptClick, Options::keyGeoIntercept);\n\t_btnIntercept->onKeyboardPress((ActionHandler)&GeoscapeState::btnUfoTrackerClick, Options::keyGeoUfoTracker);\n\t_btnIntercept->onKeyboardPress((ActionHandler)&GeoscapeState::btnTechTreeViewerClick, Options::keyGeoTechTreeViewer);\n\t_btnIntercept->onKeyboardPress((ActionHandler)&GeoscapeState::btnSelectMusicTrackClick, Options::keySelectMusicTrack);\n\t_btnIntercept->onKeyboardPress((ActionHandler)&GeoscapeState::btnGlobalProductionClick, Options::keyGeoGlobalProduction);\n\t_btnIntercept->onKeyboardPress((ActionHandler)&GeoscapeState::btnGlobalResearchClick, Options::keyGeoGlobalResearch);\n\t_btnIntercept->onKeyboardPress((ActionHandler)&GeoscapeState::btnGlobalAlienContainmentClick, Options::keyGeoGlobalAlienContainment);\n\t_btnIntercept->onKeyboardPress((ActionHandler)&GeoscapeState::btnDogfightExperienceClick, Options::keyGeoDailyPilotExperience);\n\t_btnIntercept->setGeoscapeButton(true);\n\n\t_btnBases->initText(_game->getMod()->getFont(\"FONT_GEO_BIG\"), _game->getMod()->getFont(\"FONT_GEO_SMALL\"), _game->getLanguage());\n\t_btnBases->setText(tr(\"STR_BASES\"));\n\t_btnBases->onMouseClick((ActionHandler)&GeoscapeState::btnBasesClick);\n\t_btnBases->onKeyboardPress((ActionHandler)&GeoscapeState::btnBasesClick, Options::keyGeoBases);\n\t_btnBases->setGeoscapeButton(true);\n\n\t_btnGraphs->initText(_game->getMod()->getFont(\"FONT_GEO_BIG\"), _game->getMod()->getFont(\"FONT_GEO_SMALL\"), _game->getLanguage());\n\t_btnGraphs->setText(tr(\"STR_GRAPHS\"));\n\t_btnGraphs->onMouseClick((ActionHandler)&GeoscapeState::btnGraphsClick);\n\t_btnGraphs->onKeyboardPress((ActionHandler)&GeoscapeState::btnGraphsClick, Options::keyGeoGraphs);\n\t_btnGraphs->setGeoscapeButton(true);\n\n\t_btnUfopaedia->initText(_game->getMod()->getFont(\"FONT_GEO_BIG\"), _game->getMod()->getFont(\"FONT_GEO_SMALL\"), _game->getLanguage());\n\t_btnUfopaedia->setText(tr(\"STR_UFOPAEDIA_UC\"));\n\t_btnUfopaedia->onMouseClick((ActionHandler)&GeoscapeState::btnUfopaediaClick);\n\t_btnUfopaedia->onKeyboardPress((ActionHandler)&GeoscapeState::btnUfopaediaClick, Options::keyGeoUfopedia);\n\t_btnUfopaedia->setGeoscapeButton(true);\n\n\t_btnOptions->initText(_game->getMod()->getFont(\"FONT_GEO_BIG\"), _game->getMod()->getFont(\"FONT_GEO_SMALL\"), _game->getLanguage());\n\t_btnOptions->setText(tr(\"STR_OPTIONS_UC\"));\n\t_btnOptions->onMouseClick((ActionHandler)&GeoscapeState::btnOptionsClick);\n\t_btnOptions->onKeyboardPress((ActionHandler)&GeoscapeState::btnOptionsClick, Options::keyGeoOptions);\n\t_btnOptions->setGeoscapeButton(true);\n\n\t_btnFunding->initText(_game->getMod()->getFont(\"FONT_GEO_BIG\"), _game->getMod()->getFont(\"FONT_GEO_SMALL\"), _game->getLanguage());\n\t_btnFunding->setText(Options::oxceLinks ? tr(\"STR_EXTENDED_UC\") : tr(\"STR_FUNDING_UC\"));\n\t_btnFunding->onMouseClick((ActionHandler)&GeoscapeState::btnFundingClick);\n\t_btnFunding->onKeyboardPress((ActionHandler)&GeoscapeState::btnFundingClick, Options::keyGeoFunding);\n\t_btnFunding->setGeoscapeButton(true);\n\n\t_btn5Secs->initText(_game->getMod()->getFont(\"FONT_GEO_BIG\"), _game->getMod()->getFont(\"FONT_GEO_SMALL\"), _game->getLanguage());\n\t_btn5Secs->setBig();\n\t_btn5Secs->setText(tr(\"STR_5_SECONDS\"));\n\t_btn5Secs->setGroup(&_timeSpeed);\n\t_btn5Secs->onKeyboardPress((ActionHandler)&GeoscapeState::btnTimerClick, Options::keyGeoSpeed1);\n\t_btn5Secs->setGeoscapeButton(true);\n\n\t_btn1Min->initText(_game->getMod()->getFont(\"FONT_GEO_BIG\"), _game->getMod()->getFont(\"FONT_GEO_SMALL\"), _game->getLanguage());\n\t_btn1Min->setBig();\n\t_btn1Min->setText(tr(\"STR_1_MINUTE\"));\n\t_btn1Min->setGroup(&_timeSpeed);\n\t_btn1Min->onKeyboardPress((ActionHandler)&GeoscapeState::btnTimerClick, Options::keyGeoSpeed2);\n\t_btn1Min->setGeoscapeButton(true);\n\n\t_btn5Mins->initText(_game->getMod()->getFont(\"FONT_GEO_BIG\"), _game->getMod()->getFont(\"FONT_GEO_SMALL\"), _game->getLanguage());\n\t_btn5Mins->setBig();\n\t_btn5Mins->setText(tr(\"STR_5_MINUTES\"));\n\t_btn5Mins->setGroup(&_timeSpeed);\n\t_btn5Mins->onKeyboardPress((ActionHandler)&GeoscapeState::btnTimerClick, Options::keyGeoSpeed3);\n\t_btn5Mins->setGeoscapeButton(true);\n\n\t_btn30Mins->initText(_game->getMod()->getFont(\"FONT_GEO_BIG\"), _game->getMod()->getFont(\"FONT_GEO_SMALL\"), _game->getLanguage());\n\t_btn30Mins->setBig();\n\t_btn30Mins->setText(tr(\"STR_30_MINUTES\"));\n\t_btn30Mins->setGroup(&_timeSpeed);\n\t_btn30Mins->onKeyboardPress((ActionHandler)&GeoscapeState::btnTimerClick, Options::keyGeoSpeed4);\n\t_btn30Mins->setGeoscapeButton(true);\n\n\t_btn1Hour->initText(_game->getMod()->getFont(\"FONT_GEO_BIG\"), _game->getMod()->getFont(\"FONT_GEO_SMALL\"), _game->getLanguage());\n\t_btn1Hour->setBig();\n\t_btn1Hour->setText(tr(\"STR_1_HOUR\"));\n\t_btn1Hour->setGroup(&_timeSpeed);\n\t_btn1Hour->onKeyboardPress((ActionHandler)&GeoscapeState::btnTimerClick, Options::keyGeoSpeed5);\n\t_btn1Hour->setGeoscapeButton(true);\n\n\t_btn1Day->initText(_game->getMod()->getFont(\"FONT_GEO_BIG\"), _game->getMod()->getFont(\"FONT_GEO_SMALL\"), _game->getLanguage());\n\t_btn1Day->setBig();\n\t_btn1Day->setText(tr(\"STR_1_DAY\"));\n\t_btn1Day->setGroup(&_timeSpeed);\n\t_btn1Day->onKeyboardPress((ActionHandler)&GeoscapeState::btnTimerClick, Options::keyGeoSpeed6);\n\t_btn1Day->setGeoscapeButton(true);\n\n\t_sideBottom->setGeoscapeButton(true);\n\t_sideTop->setGeoscapeButton(true);\n\n\t_btnRotateLeft->onMousePress((ActionHandler)&GeoscapeState::btnRotateLeftPress);\n\t_btnRotateLeft->onMouseRelease((ActionHandler)&GeoscapeState::btnRotateLeftRelease);\n\t_btnRotateLeft->onKeyboardPress((ActionHandler)&GeoscapeState::btnRotateLeftPress, Options::keyGeoLeft);\n\t_btnRotateLeft->onKeyboardRelease((ActionHandler)&GeoscapeState::btnRotateLeftRelease, Options::keyGeoLeft);\n\n\t_btnRotateRight->onMousePress((ActionHandler)&GeoscapeState::btnRotateRightPress);\n\t_btnRotateRight->onMouseRelease((ActionHandler)&GeoscapeState::btnRotateRightRelease);\n\t_btnRotateRight->onKeyboardPress((ActionHandler)&GeoscapeState::btnRotateRightPress, Options::keyGeoRight);\n\t_btnRotateRight->onKeyboardRelease((ActionHandler)&GeoscapeState::btnRotateRightRelease, Options::keyGeoRight);\n\n\t_btnRotateUp->onMousePress((ActionHandler)&GeoscapeState::btnRotateUpPress);\n\t_btnRotateUp->onMouseRelease((ActionHandler)&GeoscapeState::btnRotateUpRelease);\n\t_btnRotateUp->onKeyboardPress((ActionHandler)&GeoscapeState::btnRotateUpPress, Options::keyGeoUp);\n\t_btnRotateUp->onKeyboardRelease((ActionHandler)&GeoscapeState::btnRotateUpRelease, Options::keyGeoUp);\n\n\t_btnRotateDown->onMousePress((ActionHandler)&GeoscapeState::btnRotateDownPress);\n\t_btnRotateDown->onMouseRelease((ActionHandler)&GeoscapeState::btnRotateDownRelease);\n\t_btnRotateDown->onKeyboardPress((ActionHandler)&GeoscapeState::btnRotateDownPress, Options::keyGeoDown);\n\t_btnRotateDown->onKeyboardRelease((ActionHandler)&GeoscapeState::btnRotateDownRelease, Options::keyGeoDown);\n\n\t_btnZoomIn->onMouseClick((ActionHandler)&GeoscapeState::btnZoomInLeftClick, SDL_BUTTON_LEFT);\n\t_btnZoomIn->onMouseClick((ActionHandler)&GeoscapeState::btnZoomInRightClick, SDL_BUTTON_RIGHT);\n\t_btnZoomIn->onKeyboardPress((ActionHandler)&GeoscapeState::btnZoomInLeftClick, Options::keyGeoZoomIn);\n\n\t_btnZoomOut->onMouseClick((ActionHandler)&GeoscapeState::btnZoomOutLeftClick, SDL_BUTTON_LEFT);\n\t_btnZoomOut->onMouseClick((ActionHandler)&GeoscapeState::btnZoomOutRightClick, SDL_BUTTON_RIGHT);\n\t_btnZoomOut->onKeyboardPress((ActionHandler)&GeoscapeState::btnZoomOutLeftClick, Options::keyGeoZoomOut);\n\n\t_txtFunds->setAlign(ALIGN_CENTER);\n\t_txtFunds->setVisible(Options::showFundsOnGeoscape);\n\n\t_txtHour->setBig();\n\t_txtHour->setAlign(ALIGN_RIGHT);\n\n\t_txtHourSep->setBig();\n\t_txtHourSep->setText(\":\");\n\n\t_txtMin->setBig();\n\n\t_txtMinSep->setBig();\n\t_txtMinSep->setText(\":\");\n\n\t_txtWeekday->setAlign(ALIGN_CENTER);\n\n\t_txtDay->setAlign(ALIGN_CENTER);\n\n\t_txtMonth->setAlign(ALIGN_CENTER);\n\n\t_txtYear->setAlign(ALIGN_CENTER);\n\n\t_txtSlacking->setAlign(ALIGN_RIGHT);\n\t_txtTraining->setAlign(ALIGN_RIGHT);\n\n\tif (Options::showFundsOnGeoscape)\n\t{\n\t\t_txtHour->setY(_txtHour->getY()+6);\n\t\t_txtHour->setSmall();\n\t\t_txtHourSep->setY(_txtHourSep->getY()+6);\n\t\t_txtHourSep->setSmall();\n\t\t_txtMin->setY(_txtMin->getY()+6);\n\t\t_txtMin->setSmall();\n\t\t_txtMinSep->setX(_txtMinSep->getX()-10);\n\t\t_txtMinSep->setY(_txtMinSep->getY()+6);\n\t\t_txtMinSep->setSmall();\n\t\t_txtSec->setX(_txtSec->getX()-10);\n\t}\n\n\t_gameTimer->onTimer((StateHandler)&GeoscapeState::timeAdvance);\n\t_gameTimer->start();\n\n\t_zoomInEffectTimer->onTimer((StateHandler)&GeoscapeState::zoomInEffect);\n\t_zoomOutEffectTimer->onTimer((StateHandler)&GeoscapeState::zoomOutEffect);\n\t_dogfightStartTimer->onTimer((StateHandler)&GeoscapeState::startDogfight);\n\t_dogfightTimer->onTimer((StateHandler)&GeoscapeState::handleDogfights);\n\n\t// debug helpers\n\t{\n\t\tstd::vector<std::string> regionList;\n\t\tregionList.push_back(\"All regions\");\n\t\tfor (auto* r : *_game->getSavedGame()->getRegions())\n\t\t{\n\t\t\tregionList.push_back(r->getRules()->getType());\n\t\t}\n\t\t_cbxRegion->setOptions(regionList, false);\n\t\t_cbxRegion->setVisible(false);\n\t\t_cbxRegion->onChange((ActionHandler)&GeoscapeState::cbxRegionChange);\n\n\t\tstd::vector<std::string> zoneList;\n\t\tzoneList.push_back(\"All zones\");\n\t\tfor (int z = 0; z < 20; ++z)\n\t\t{\n\t\t\tzoneList.push_back(std::to_string(z));\n\t\t}\n\t\t_cbxZone->setOptions(zoneList, false);\n\t\t_cbxZone->setVisible(false);\n\t\t_cbxZone->onChange((ActionHandler)&GeoscapeState::cbxZoneChange);\n\n\t\tstd::vector<std::string> areaList;\n\t\tareaList.push_back(\"All areas\");\n\t\tfor (int z = 0; z < 100; ++z)\n\t\t{\n\t\t\tareaList.push_back(std::to_string(z));\n\t\t}\n\t\t_cbxArea->setOptions(areaList, false);\n\t\t_cbxArea->setVisible(false);\n\t\t_cbxArea->onChange((ActionHandler)&GeoscapeState::cbxAreaChange);\n\n\t\tstd::vector<std::string> countryList;\n\t\tcountryList.push_back(\"All countries\");\n\t\tfor (auto* c : *_game->getSavedGame()->getCountries())\n\t\t{\n\t\t\tcountryList.push_back(tr(c->getRules()->getType()));\n\t\t}\n\t\t_cbxCountry->setOptions(countryList, false);\n\t\t_cbxCountry->setVisible(false);\n\t\t_cbxCountry->onChange((ActionHandler)&GeoscapeState::cbxCountryChange);\n\t}\n\n\ttimeDisplay();\n}\n\n/**\n * Deletes timers.\n */\nGeoscapeState::~GeoscapeState()\n{\n\tdelete _gameTimer;\n\tdelete _zoomInEffectTimer;\n\tdelete _zoomOutEffectTimer;\n\tdelete _dogfightStartTimer;\n\tdelete _dogfightTimer;\n\n\tfor (auto* dfs : _dogfights)\n\t{\n\t\tdelete dfs;\n\t}\n\t_dogfights.clear();\n\tfor (auto* dfs : _dogfightsToBeStarted)\n\t{\n\t\tdelete dfs;\n\t}\n\t_dogfightsToBeStarted.clear();\n}\n\n/**\n * Handle blitting of Geoscape and Dogfights.\n */\nvoid GeoscapeState::blit()\n{\n\tState::blit();\n\tfor (auto* dfs : _dogfights)\n\t{\n\t\tdfs->blit();\n\t}\n}\n\n/**\n * Handle key shortcuts.\n * @param action Pointer to an action.\n */\nvoid GeoscapeState::handle(Action *action)\n{\n\tif (_dogfights.size() == _minimizedDogfights)\n\t{\n\t\tState::handle(action);\n\t}\n\n\tif (action->getDetails()->type == SDL_KEYDOWN)\n\t{\n\t\tif (!_dogfights.empty() && _dogfights.size() > _minimizedDogfights)\n\t\t{\n\t\t\tif (action->getDetails()->key.keysym.sym == SDLK_1)\n\t\t\t{\n\t\t\t\tOptions::dogfightSpeed = 50;\n\t\t\t\t_dogfightTimer->setInterval(Options::dogfightSpeed);\n\t\t\t}\n\t\t\telse if (action->getDetails()->key.keysym.sym == SDLK_2)\n\t\t\t{\n\t\t\t\tOptions::dogfightSpeed = 35;\n\t\t\t\t_dogfightTimer->setInterval(Options::dogfightSpeed);\n\t\t\t}\n\t\t\telse if (action->getDetails()->key.keysym.sym == SDLK_3)\n\t\t\t{\n\t\t\t\tOptions::dogfightSpeed = 20;\n\t\t\t\t_dogfightTimer->setInterval(Options::dogfightSpeed);\n\t\t\t}\n\t\t}\n\t\t// \"ctrl-d\" - enable debug mode\n\t\tif (Options::debug && action->getDetails()->key.keysym.sym == SDLK_d && _game->isCtrlPressed())\n\t\t{\n\t\t\tbtnDebugClick(nullptr);\n\t\t}\n\t\tif (Options::debug && _game->getSavedGame()->getDebugMode() && _game->isCtrlPressed())\n\t\t{\n\t\t\t// \"ctrl-1\"\n\t\t\tif (action->getDetails()->key.keysym.sym == SDLK_1)\n\t\t\t{\n\t\t\t\t_txtDebug->setText(\"I'M A BILLIONAIRE! ALMOST...\");\n\t\t\t\t_game->getSavedGame()->setFunds(999999999);\n\t\t\t}\n\t\t\t// \"ctrl-2\"\n\t\t\tif (action->getDetails()->key.keysym.sym == SDLK_2)\n\t\t\t{\n\t\t\t\t_txtDebug->setText(\"ALL FACILITY CONSTRUCTION COMPLETED\");\n\t\t\t\tfor (auto* xbase : *_game->getSavedGame()->getBases())\n\t\t\t\t{\n\t\t\t\t\tfor (auto* facility : *xbase->getFacilities())\n\t\t\t\t\t{\n\t\t\t\t\t\tfacility->setBuildTime(0);\n\t\t\t\t\t\tfacility->setIfHadPreviousFacility(false);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// \"ctrl-3\"\n\t\t\tif (action->getDetails()->key.keysym.sym == SDLK_3)\n\t\t\t{\n\t\t\t\t_txtDebug->setText(\"+50 SCIENTISTS/ENGINEERS\");\n\t\t\t\tfor (auto* xbase : *_game->getSavedGame()->getBases())\n\t\t\t\t{\n\t\t\t\t\txbase->setScientists(xbase->getScientists() + 50);\n\t\t\t\t\txbase->setEngineers(xbase->getEngineers() + 50);\n\t\t\t\t}\n\t\t\t}\n\t\t\t// \"ctrl-4\"\n\t\t\tif (action->getDetails()->key.keysym.sym == SDLK_4)\n\t\t\t{\n\t\t\t\t_txtDebug->setText(\"+2 ALL ITEMS\");\n\t\t\t\tfor (auto* xbase : *_game->getSavedGame()->getBases())\n\t\t\t\t{\n\t\t\t\t\tfor (auto& itemType : _game->getMod()->getItemsList())\n\t\t\t\t\t{\n\t\t\t\t\t\tauto* item = _game->getMod()->getItem(itemType);\n\t\t\t\t\t\tif (item && item->isRecoverable() && !item->isAlien() && item->getSellCost() > 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\txbase->getStorageItems()->addItem(item, 2);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// \"ctrl-5\"\n\t\t\tif (action->getDetails()->key.keysym.sym == SDLK_5)\n\t\t\t{\n\t\t\t\t_txtDebug->setText(\"+2 ALL LIVE ALIENS\");\n\t\t\t\tfor (auto* xbase : *_game->getSavedGame()->getBases())\n\t\t\t\t{\n\t\t\t\t\tfor (auto& itemType : _game->getMod()->getItemsList())\n\t\t\t\t\t{\n\t\t\t\t\t\tauto* item = _game->getMod()->getItem(itemType);\n\t\t\t\t\t\tif (item && item->isRecoverable() && item->isAlien() && item->getSellCost() > 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\txbase->getStorageItems()->addItem(item, 2);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// \"ctrl-6\"\n\t\t\tif (action->getDetails()->key.keysym.sym == SDLK_6)\n\t\t\t{\n\t\t\t\t_txtDebug->setText(\"XCOM/ALIEN ACTIVITY FOR THIS MONTH RESET\");\n\t\t\t\tsize_t invertedEntry = _game->getSavedGame()->getFundsList().size() - 1;\n\t\t\t\tfor (auto* region : *_game->getSavedGame()->getRegions())\n\t\t\t\t{\n\t\t\t\t\tregion->getActivityXcom().at(invertedEntry) = 0;\n\t\t\t\t\tregion->getActivityAlien().at(invertedEntry) = 0;\n\t\t\t\t}\n\t\t\t\tfor (auto* country : *_game->getSavedGame()->getCountries())\n\t\t\t\t{\n\t\t\t\t\tcountry->getActivityXcom().at(invertedEntry) = 0;\n\t\t\t\t\tcountry->getActivityAlien().at(invertedEntry) = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// \"ctrl-7\"\n\t\t\tif (action->getDetails()->key.keysym.sym == SDLK_7)\n\t\t\t{\n\t\t\t\t_txtDebug->setText(\"BIG BROTHER SEES ALL\");\n\t\t\t\tfor (auto* ufo : *_game->getSavedGame()->getUfos())\n\t\t\t\t{\n\t\t\t\t\tufo->setDetected(true);\n\t\t\t\t\tufo->setHyperDetected(true);\n\t\t\t\t}\n\t\t\t\tfor (auto* ab : *_game->getSavedGame()->getAlienBases())\n\t\t\t\t{\n\t\t\t\t\tab->setDiscovered(true);\n\t\t\t\t}\n\t\t\t}\n\t\t\t// \"ctrl-a\"\n\t\t\tif (action->getDetails()->key.keysym.sym == SDLK_a)\n\t\t\t{\n\t\t\t\t_txtDebug->setText(\"SOLDIER DIARIES DELETED\");\n\t\t\t\tfor (auto* xbase : *_game->getSavedGame()->getBases())\n\t\t\t\t{\n\t\t\t\t\tfor (auto* soldier : *xbase->getSoldiers())\n\t\t\t\t\t{\n\t\t\t\t\t\tsoldier->resetDiary();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// \"ctrl-c\"\n\t\t\tif (action->getDetails()->key.keysym.sym == SDLK_c)\n\t\t\t{\n\t\t\t\t_txtDebug->setText(\"SOLDIER COMMENDATIONS DELETED\");\n\t\t\t\tfor (auto* xbase : *_game->getSavedGame()->getBases())\n\t\t\t\t{\n\t\t\t\t\tfor (auto* soldier : *xbase->getSoldiers())\n\t\t\t\t\t{\n\t\t\t\t\t\tfor (auto* commendation : *soldier->getDiary()->getSoldierCommendations())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tdelete commendation;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tsoldier->getDiary()->getSoldierCommendations()->clear();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// quick save and quick load\n\t\tif (!_game->getSavedGame()->isIronman())\n\t\t{\n\t\t\tif (action->getDetails()->key.keysym.sym == Options::keyQuickSave)\n\t\t\t{\n\t\t\t\tpopup(new SaveGameState(OPT_GEOSCAPE, SAVE_QUICK, _palette));\n\t\t\t}\n\t\t\telse if (action->getDetails()->key.keysym.sym == Options::keyInstaSave)\n\t\t\t{\n\t\t\t\tpopup(new SaveGameState(OPT_GEOSCAPE, SAVE_INSTA, _palette));\n\t\t\t}\n\t\t\telse if (action->getDetails()->key.keysym.sym == Options::keyQuickLoad)\n\t\t\t{\n\t\t\t\tpopup(new LoadGameState(OPT_GEOSCAPE, SAVE_QUICK, _palette));\n\t\t\t}\n\t\t}\n\t}\n\tif (!_dogfights.empty())\n\t{\n\t\tfor (auto* dfs : _dogfights)\n\t\t{\n\t\t\tdfs->handle(action);\n\t\t}\n\t\t_minimizedDogfights = minimizedDogfightsCount();\n\t}\n}\n\n/**\n * Updates the timer display and resets the palette\n * since it's bound to change on other screens.\n */\nvoid GeoscapeState::init()\n{\n\tState::init();\n\ttimeDisplay();\n\tupdateSlackingIndicator();\n\n\t_globe->onMouseClick((ActionHandler)&GeoscapeState::globeClick);\n\t_globe->onMouseOver(0);\n\t_globe->rotateStop();\n\t_globe->setFocus(true);\n\t_globe->draw();\n\n\t// Pop up save screen if it's a new ironman game\n\tif (_game->getSavedGame()->isIronman() && _game->getSavedGame()->getName().empty())\n\t{\n\t\tpopup(new ListSaveState(OPT_GEOSCAPE));\n\t}\n\n\t// Set music if it's not already playing\n\tif (_dogfights.empty() && !_dogfightStartTimer->isRunning())\n\t{\n\t\tif (_game->getSavedGame()->getMonthsPassed() == -1)\n\t\t{\n\t\t\t_game->getMod()->playMusic(\"GMGEO\", 1);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_game->getMod()->playMusic(\"GMGEO\");\n\t\t}\n\t}\n\telse\n\t{\n\t\t_game->getMod()->playMusic(\"GMINTER\");\n\t}\n\t_globe->setNewBaseHover(false);\n\n\t\t// run once\n\tif (_game->getSavedGame()->getMonthsPassed() == -1 &&\n\t\t// as long as there's a base\n\t\t!_game->getSavedGame()->getBases()->empty() &&\n\t\t// and it has a name (THIS prevents it from running prior to the base being placed.)\n\t\t!_game->getSavedGame()->getBases()->front()->getName().empty())\n\t{\n\t\t_game->getSavedGame()->addMonth();\n\t\t_game->getSavedGame()->increaseDaysPassed();\n\t\tdetermineAlienMissions();\n\t\t_game->getSavedGame()->setFunds(_game->getSavedGame()->getFunds() - (_game->getSavedGame()->getBaseMaintenance() - _game->getSavedGame()->getBases()->front()->getPersonnelMaintenance()));\n\t}\n}\n\n/**\n * Runs the game timer and handles popups.\n */\nvoid GeoscapeState::think()\n{\n\tState::think();\n\n\t_zoomInEffectTimer->think(this, 0);\n\t_zoomOutEffectTimer->think(this, 0);\n\t_dogfightStartTimer->think(this, 0);\n\n\tif (_popups.empty() && _dogfights.empty() && (!_zoomInEffectTimer->isRunning() || _zoomInEffectDone) && (!_zoomOutEffectTimer->isRunning() || _zoomOutEffectDone))\n\t{\n\t\t// Handle timers\n\t\t_gameTimer->think(this, 0);\n\t}\n\telse\n\t{\n\t\tif (!_dogfights.empty() || _minimizedDogfights != 0)\n\t\t{\n\t\t\t// If all dogfights are minimized rotate the globe, etc.\n\t\t\tif (_dogfights.size() == _minimizedDogfights)\n\t\t\t{\n\t\t\t\t_pause = false;\n\t\t\t\t_gameTimer->think(this, 0);\n\t\t\t}\n\t\t\t_dogfightTimer->think(this, 0);\n\t\t}\n\t\tif (!_popups.empty())\n\t\t{\n\t\t\t// Handle popups\n\t\t\t_globe->rotateStop();\n\t\t\t_game->pushState(_popups.front());\n\t\t\t_popups.erase(_popups.begin());\n\t\t}\n\t}\n}\n\n/**\n * Updates the Geoscape clock with the latest\n * game time and date in human-readable format. (+Funds)\n */\nvoid GeoscapeState::timeDisplay()\n{\n\tif (Options::showFundsOnGeoscape)\n\t{\n\t\tif (Options::oxceGeoShowScoreInsteadOfFunds)\n\t\t{\n\t\t\t// it's a cheat (you're not supposed to see this info in real time), for debugging only\n\t\t\t_txtFunds->setText(std::to_string(_game->getSavedGame()->getCurrentScore(_game->getSavedGame()->getMonthsPassed() + 1)));\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_txtFunds->setText(Unicode::formatFunding(_game->getSavedGame()->getFunds()));\n\t\t}\n\t}\n\n\tstd::ostringstream ss;\n\tss << std::setfill('0') << std::setw(2) << _game->getSavedGame()->getTime()->getSecond();\n\t_txtSec->setText(ss.str());\n\n\tstd::ostringstream ss2;\n\tss2 << std::setfill('0') << std::setw(2) << _game->getSavedGame()->getTime()->getMinute();\n\t_txtMin->setText(ss2.str());\n\n\tstd::ostringstream ss3;\n\tss3 << _game->getSavedGame()->getTime()->getHour();\n\t_txtHour->setText(ss3.str());\n\n\tstd::ostringstream ss4;\n\tss4 << _game->getSavedGame()->getTime()->getDayString(_game->getLanguage());\n\t_txtDay->setText(ss4.str());\n\n\t_txtWeekday->setText(tr(_game->getSavedGame()->getTime()->getWeekdayString()));\n\n\t_txtMonth->setText(tr(_game->getSavedGame()->getTime()->getMonthString()));\n\n\tstd::ostringstream ss5;\n\tss5 << _game->getSavedGame()->getTime()->getYear();\n\t_txtYear->setText(ss5.str());\n}\n\n/**\n * Advances the game timer according to\n * the timer speed set, and calls the respective\n * triggers. The timer always advances in \"5 secs\"\n * cycles, regardless of the speed, otherwise it might\n * skip important steps. Instead, it just keeps advancing\n * the timer until the next speed step (eg. the next day\n * on 1 Day speed) or until an event occurs, since updating\n * the screen on each step would become cumbersomely slow.\n */\nvoid GeoscapeState::timeAdvance()\n{\n\tint timeSpan = 0;\n\tif (_timeSpeed == _btn5Secs)\n\t{\n\t\tif (Options::oxceGeoSlowdownFactor > 1)\n\t\t{\n\t\t\t_slowdownCounter--;\n\t\t\tif (_slowdownCounter > 0)\n\t\t\t{\n\t\t\t\t// wait\n\t\t\t\t_globe->draw();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_slowdownCounter = Clamp(Options::oxceGeoSlowdownFactor, 2, 100);\n\t\t\t}\n\t\t}\n\t\ttimeSpan = 1;\n\t}\n\telse if (_timeSpeed == _btn1Min)\n\t{\n\t\ttimeSpan = 12;\n\t}\n\telse if (_timeSpeed == _btn5Mins)\n\t{\n\t\ttimeSpan = 12 * 5;\n\t}\n\telse if (_timeSpeed == _btn30Mins)\n\t{\n\t\ttimeSpan = 12 * 5 * 6;\n\t}\n\telse if (_timeSpeed == _btn1Hour)\n\t{\n\t\ttimeSpan = 12 * 5 * 6 * 2;\n\t}\n\telse if (_timeSpeed == _btn1Day)\n\t{\n\t\ttimeSpan = 12 * 5 * 6 * 2 * 24;\n\t}\n\n\n\tfor (int i = 0; i < timeSpan && !_pause; ++i)\n\t{\n\t\tTimeTrigger trigger;\n\t\ttrigger = _game->getSavedGame()->getTime()->advance();\n\t\tswitch (trigger)\n\t\t{\n\t\tcase TIME_1MONTH:\n\t\t\ttime1Month();\n\t\t\tFALLTHROUGH;\n\t\tcase TIME_1DAY:\n\t\t\ttime1Day();\n\t\t\tFALLTHROUGH;\n\t\tcase TIME_1HOUR:\n\t\t\ttime1Hour();\n\t\t\tFALLTHROUGH;\n\t\tcase TIME_30MIN:\n\t\t\ttime30Minutes();\n\t\t\tFALLTHROUGH;\n\t\tcase TIME_10MIN:\n\t\t\ttime10Minutes();\n\t\t\tFALLTHROUGH;\n\t\tcase TIME_5SEC:\n\t\t\ttime5Seconds();\n\t\t}\n\t}\n\n\t_pause = !_dogfightsToBeStarted.empty() || _zoomInEffectTimer->isRunning() || _zoomOutEffectTimer->isRunning();\n\n\ttimeDisplay();\n\t_globe->draw();\n}\n\n/**\n * Update list of active crafts.\n * @return Const pointer to updated list.\n */\nconst std::vector<Craft*>* GeoscapeState::updateActiveCrafts()\n{\n\t_activeCrafts.clear();\n\tfor (auto* xbase : *_game->getSavedGame()->getBases())\n\t{\n\t\tfor (auto* xcraft : *xbase->getCrafts())\n\t\t{\n\t\t\tif (xcraft->getStatus() == \"STR_OUT\" && !xcraft->isDestroyed())\n\t\t\t{\n\t\t\t\t_activeCrafts.push_back(xcraft);\n\t\t\t}\n\t\t}\n\t}\n\treturn &_activeCrafts;\n}\n\n/**\n * Takes care of any game logic that has to\n * run every game second, like craft movement.\n */\nvoid GeoscapeState::time5Seconds()\n{\n\t// If in \"slow mode\", handle UFO hunting and escorting logic every 5 seconds, not only every 10 minutes\n\tif ((_timeSpeed == _btn5Secs || _timeSpeed == _btn1Min) && _game->getMod()->getHunterKillerFastRetarget())\n\t{\n\t\tufoHuntingAndEscorting();\n\t}\n\n\t// Game over if there are no more bases.\n\tif (_game->getSavedGame()->getBases()->empty())\n\t{\n\t\t_game->getSavedGame()->setEnding(END_LOSE);\n\t}\n\tif (_game->getSavedGame()->getEnding() == END_LOSE)\n\t{\n\t\t_game->pushState(new CutsceneState(_game->getMod()->getLoseDefeatCutscene()));\n\t\tif (_game->getSavedGame()->isIronman())\n\t\t{\n\t\t\t_game->pushState(new SaveGameState(OPT_GEOSCAPE, SAVE_IRONMAN, _palette));\n\t\t}\n\t\treturn;\n\t}\n\n\tauto* activeCrafts = updateActiveCrafts();\n\n\t// Handle UFO logic\n\tbool ufoIsAttacking = false;\n\tfor (auto* ufo : *_game->getSavedGame()->getUfos())\n\t{\n\t\tswitch (ufo->getStatus())\n\t\t{\n\t\tcase Ufo::FLYING:\n\t\t\tufo->think();\n\t\t\tif (ufo->reachedDestination() && !ufo->isEscorting())\n\t\t\t{\n\t\t\t\tCraft* c = dynamic_cast<Craft*>(ufo->getDestination());\n\t\t\t\tif (c != 0 && !c->isDestroyed() && ufo->isHunting())\n\t\t\t\t{\n\t\t\t\t\t// Check if some other HK already attacked before us (at the very same moment)\n\t\t\t\t\tint hkDogfights = 0;\n\t\t\t\t\tfor (auto* f : _dogfights) if (f->isUfoAttacking()) { hkDogfights++; }\n\t\t\t\t\tfor (auto* g : _dogfightsToBeStarted) if (g->isUfoAttacking()) { hkDogfights++; }\n\n\t\t\t\t\t// If yes, wait... not more than 1 HK interception allowed at a time.\n\t\t\t\t\tif (hkDogfights >= 1)\n\t\t\t\t\t{\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\t// If not, interrupt all other (regular) interceptions to prevent a dead-lock (and other possible side effects)\n\t\t\t\t\tfor (auto* f : _dogfights) if (f->getCraft()) { f->getCraft()->setInDogfight(false); f->getCraft()->setInterceptionOrder(0); }\n\t\t\t\t\tfor (auto* g : _dogfightsToBeStarted) if (g->getCraft()) { g->getCraft()->setInDogfight(false); g->getCraft()->setInterceptionOrder(0); }\n\t\t\t\t\tCollections::deleteAll(_dogfights);\n\t\t\t\t\tCollections::deleteAll(_dogfightsToBeStarted);\n\t\t\t\t\t_minimizedDogfights = 0;\n\n\t\t\t\t\t// Start the dogfight\n\t\t\t\t\t{\n\t\t\t\t\t\t// Main target\n\t\t\t\t\t\t_dogfightsToBeStarted.push_back(new DogfightState(this, c, ufo, true));\n\n\t\t\t\t\t\t// Start fighting escorts and other craft as well (if they are in escort range)\n\t\t\t\t\t\tif (_game->getMod()->getEscortsJoinFightAgainstHK())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tint secondaryTargets = 0;\n\t\t\t\t\t\t\tfor (auto* craft : *activeCrafts)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (!craft->isIgnoredByHK() && craft != c)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t// craft is close enough and has at least one loaded weapon\n\t\t\t\t\t\t\t\t\tif (craft->getNumWeapons(true) > 0 && craft->getDistance(c) < Nautical(_game->getMod()->getEscortRange()))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t// only up to 4 dogfights = 1 main + 3 secondary\n\t\t\t\t\t\t\t\t\t\tif (secondaryTargets < 3)\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t// Note: push_front() is used so that main target is attacked first\n\t\t\t\t\t\t\t\t\t\t\t_dogfightsToBeStarted.push_front(new DogfightState(this, craft, ufo, true));\n\t\t\t\t\t\t\t\t\t\t\tsecondaryTargets++;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (!_dogfightStartTimer->isRunning())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_pause = true;\n\t\t\t\t\t\t\ttimerReset();\n\t\t\t\t\t\t\t_globe->center(c->getLongitude(), c->getLatitude());\n\t\t\t\t\t\t\tstartDogfight();\n\t\t\t\t\t\t\t_dogfightStartTimer->start();\n\t\t\t\t\t\t}\n\t\t\t\t\t\t_game->getMod()->playMusic(\"GMINTER\");\n\n\t\t\t\t\t\t// Don't process certain craft logic (moving and reaching destination)\n\t\t\t\t\t\tufoIsAttacking = true;\n\t\t\t\t\t}\n\t\t\t\t\t// Don't handle other logic for this UFO, just continue with the next one\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tsize_t count = _game->getSavedGame()->getMissionSites()->size();\n\t\t\t\tAlienMission *mission = ufo->getMission();\n\t\t\t\tbool detected = ufo->getDetected();\n\t\t\t\tmission->ufoReachedWaypoint(*ufo, *_game, *_globe);\n\t\t\t\tif (Options::oxceUfoLandingAlert && ufo->getStatus() == Ufo::LANDED && ufo->getDetected() && ufo->getLandId() != 0)\n\t\t\t\t{\n\t\t\t\t\tstd::string msg = tr(\"STR_UFO_HAS_LANDED\").arg(ufo->getName(_game->getLanguage()));\n\t\t\t\t\tpopup(new CraftErrorState(this, msg, true, ufo));\n\t\t\t\t}\n\t\t\t\tif (detected != ufo->getDetected() && !ufo->getFollowers()->empty())\n\t\t\t\t{\n\t\t\t\t\tif (!(ufo->getTrajectory().getID() == UfoTrajectory::RETALIATION_ASSAULT_RUN && ufo->getStatus() == Ufo::LANDED))\n\t\t\t\t\t\tpopup(new UfoLostState(ufo->getName(_game->getLanguage())));\n\t\t\t\t}\n\t\t\t\tif (count < _game->getSavedGame()->getMissionSites()->size())\n\t\t\t\t{\n\t\t\t\t\tMissionSite *site = _game->getSavedGame()->getMissionSites()->back();\n\t\t\t\t\tsite->setDetected(true);\n\t\t\t\t\tpopup(new MissionDetectedState(site, this));\n\t\t\t\t}\n\t\t\t\t// If UFO was destroyed, don't spawn missions\n\t\t\t\tif (ufo->getStatus() == Ufo::DESTROYED)\n\t\t\t\t\treturn;\n\t\t\t\tif (Base *base = dynamic_cast<Base*>(ufo->getDestination()))\n\t\t\t\t{\n\t\t\t\t\tmission->setWaveCountdown(30 * (RNG::generate(0, 400) + 48));\n\t\t\t\t\tufo->setDestination(0);\n\t\t\t\t\tbase->setupDefenses(mission);\n\t\t\t\t\ttimerReset();\n\t\t\t\t\tif (!base->getDefenses()->empty() && !ufo->getMission()->getRules().ignoreBaseDefenses())\n\t\t\t\t\t{\n\t\t\t\t\t\tbool instaHyper = ufo->getRules()->isInstaHyper() || mission->getRules().isInstaHyper();\n\t\t\t\t\t\tpopup(new BaseDefenseState(base, ufo, this, instaHyper));\n\t\t\t\t\t\treturn; // don't allow multiple simultaneous attacks in the same game tick\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\thandleBaseDefense(base, ufo);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Init UFO shields\n\t\t\tif (ufo->getShield() == -1)\n\t\t\t{\n\t\t\t\tufo->setShield(ufo->getCraftStats().shieldCapacity);\n\t\t\t}\n\t\t\t// Recharge UFO shields\n\t\t\telse if (ufo->getShield() < ufo->getCraftStats().shieldCapacity)\n\t\t\t{\n\t\t\t\tint shieldRechargeInGeoscape = ufo->getCraftStats().shieldRechargeInGeoscape;\n\t\t\t\tif (shieldRechargeInGeoscape == -1)\n\t\t\t\t{\n\t\t\t\t\tufo->setShield(ufo->getCraftStats().shieldCapacity);\n\t\t\t\t}\n\t\t\t\telse if (shieldRechargeInGeoscape > 0)\n\t\t\t\t{\n\t\t\t\t\tint total = shieldRechargeInGeoscape / 100;\n\t\t\t\t\tif (RNG::percent(shieldRechargeInGeoscape % 100))\n\t\t\t\t\t\ttotal++;\n\t\t\t\t\tufo->setShield(ufo->getShield() + total);\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tcase Ufo::LANDED:\n\t\t\tufo->think();\n\t\t\tif (ufo->getSecondsRemaining() == 0)\n\t\t\t{\n\t\t\t\tAlienMission *mission = ufo->getMission();\n\t\t\t\tbool detected = ufo->getDetected();\n\t\t\t\tmission->ufoLifting(*ufo, *_game->getSavedGame());\n\t\t\t\tif (detected != ufo->getDetected() && !ufo->getFollowers()->empty())\n\t\t\t\t{\n\t\t\t\t\tpopup(new UfoLostState(ufo->getName(_game->getLanguage())));\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tcase Ufo::CRASHED:\n\t\t\tufo->think();\n\t\t\tif (ufo->getSecondsRemaining() == 0)\n\t\t\t{\n\t\t\t\tufo->setDetected(false);\n\t\t\t\tufo->setStatus(Ufo::DESTROYED);\n\t\t\t}\n\t\t\tbreak;\n\t\tcase Ufo::DESTROYED:\n\t\tcase Ufo::IGNORE_ME:\n\t\t\t// Nothing to do\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// Handle craft logic\n\tfor (auto* xbase : *_game->getSavedGame()->getBases())\n\t{\n\t\tfor (auto craftIt = xbase->getCrafts()->begin(); craftIt != xbase->getCrafts()->end();)\n\t\t{\n\t\t\tCraft* xcraft = (*craftIt);\n\t\t\tif (xcraft->isDestroyed())\n\t\t\t{\n\t\t\t\tfor (auto* country : *_game->getSavedGame()->getCountries())\n\t\t\t\t{\n\t\t\t\t\tif (country->getRules()->insideCountry(xcraft->getLongitude(), xcraft->getLatitude()))\n\t\t\t\t\t{\n\t\t\t\t\t\tcountry->addActivityXcom(-xcraft->getRules()->getScore());\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfor (auto* region : *_game->getSavedGame()->getRegions())\n\t\t\t\t{\n\t\t\t\t\tif (region->getRules()->insideRegion(xcraft->getLongitude(), xcraft->getLatitude()))\n\t\t\t\t\t{\n\t\t\t\t\t\tregion->addActivityXcom(-xcraft->getRules()->getScore());\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t//if (_ufoIsAttacking)\n\t\t\t\t{\n\t\t\t\t\t// Note: this was moved from DogfightState.cpp, as it was not 100% reliable there\n\t\t\t\t\txcraft->evacuateCrew(_game->getMod());\n\t\t\t\t}\n\t\t\t\t// if a transport craft has been shot down, kill all the soldiers on board.\n\t\t\t\tif (xcraft->getRules()->getMaxUnitsLimit() > 0)\n\t\t\t\t{\n\t\t\t\t\tfor (auto soldierIt = xbase->getSoldiers()->begin(); soldierIt != xbase->getSoldiers()->end();)\n\t\t\t\t\t{\n\t\t\t\t\t\tSoldier* soldier = (*soldierIt);\n\t\t\t\t\t\tif (soldier->getCraft() == xcraft)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsoldierIt = _game->getSavedGame()->killSoldier(true, soldier);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t++soldierIt;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t_game->getSavedGame()->stopHuntingXcomCraft(xcraft); // craft destroyed in dogfight\n\t\t\t\tCraft *craft = *craftIt;\n\t\t\t\tcraftIt = xbase->removeCraft(craft, false);\n\t\t\t\tdelete craft;\n\t\t\t\t_game->getSavedGame()->increaseCraftLostDogfight();\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (xcraft->getDestination() != 0)\n\t\t\t{\n\t\t\t\tUfo* u = dynamic_cast<Ufo*>(xcraft->getDestination());\n\t\t\t\tif (u != 0)\n\t\t\t\t{\n\t\t\t\t\tif (!u->getDetected())\n\t\t\t\t\t{\n\t\t\t\t\t\tif (u->getTrajectory().getID() == UfoTrajectory::RETALIATION_ASSAULT_RUN && (u->getStatus() == Ufo::LANDED || u->getStatus() == Ufo::DESTROYED))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\txcraft->returnToBase();\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tWaypoint *w = new Waypoint();\n\t\t\t\t\t\t\tw->setLongitude(u->getLongitude());\n\t\t\t\t\t\t\tw->setLatitude(u->getLatitude());\n\t\t\t\t\t\t\tw->setId(u->getId());\n\t\t\t\t\t\t\txcraft->setDestination(0);\n\t\t\t\t\t\t\tpopup(new GeoscapeCraftState(xcraft, _globe, w, false));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (u->getStatus() == Ufo::LANDED && xcraft->isInDogfight())\n\t\t\t\t\t{\n\t\t\t\t\t\txcraft->setInDogfight(false);\n\t\t\t\t\t}\n\t\t\t\t\telse if (u->getStatus() == Ufo::DESTROYED || u->getStatus() == Ufo::IGNORE_ME)\n\t\t\t\t\t{\n\t\t\t\t\t\txcraft->returnToBase();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif (xcraft->isInDogfight())\n\t\t\t\t\t{\n\t\t\t\t\t\txcraft->setInDogfight(false);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!ufoIsAttacking)\n\t\t\t{\n\t\t\t\tbool returnedToBase = xcraft->think();\n\t\t\t\tif (returnedToBase)\n\t\t\t\t{\n\t\t\t\t\t_game->getSavedGame()->stopHuntingXcomCraft(xcraft); // hiding in the base is good enough, obviously\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Handle craft shield recharge\n\t\t\tif (!ufoIsAttacking && xcraft->getShield() < xcraft->getCraftStats().shieldCapacity)\n\t\t\t{\n\t\t\t\tint shieldRechargeInGeoscape = xcraft->getCraftStats().shieldRechargeInGeoscape;\n\t\t\t\tif (shieldRechargeInGeoscape == -1)\n\t\t\t\t{\n\t\t\t\t\txcraft->setShield(xcraft->getCraftStats().shieldCapacity);\n\t\t\t\t}\n\t\t\t\telse if (shieldRechargeInGeoscape > 0)\n\t\t\t\t{\n\t\t\t\t\tint total = xcraft->getCraftStats().shieldRechargeInGeoscape / 100;\n\t\t\t\t\tif (RNG::percent(xcraft->getCraftStats().shieldRechargeInGeoscape % 100))\n\t\t\t\t\t\ttotal++;\n\t\t\t\t\txcraft->setShield(xcraft->getShield() + total);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!ufoIsAttacking && xcraft->reachedDestination())\n\t\t\t{\n\t\t\t\tbool suppressLanding = Options::oxceGeoSuppressLandingWithoutEquipment && xcraft->getItems()->empty();\n\t\t\t\tUfo* u = dynamic_cast<Ufo*>(xcraft->getDestination());\n\t\t\t\tWaypoint *w = dynamic_cast<Waypoint*>(xcraft->getDestination());\n\t\t\t\tMissionSite* m = dynamic_cast<MissionSite*>(xcraft->getDestination());\n\t\t\t\tAlienBase* b = dynamic_cast<AlienBase*>(xcraft->getDestination());\n\t\t\t\tCraft* x = dynamic_cast<Craft*>(xcraft->getDestination());\n\t\t\t\tif (u != 0)\n\t\t\t\t{\n\t\t\t\t\tswitch (u->getStatus())\n\t\t\t\t\t{\n\t\t\t\t\tcase Ufo::FLYING:\n\t\t\t\t\t\t// Not more than 4 interceptions at a time... but hunter-killers are always allowed\n\t\t\t\t\t\tif (!u->isHunterKiller() && _dogfights.size() + _dogfightsToBeStarted.size() >= 4)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t++craftIt;\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Can we actually fight it\n\t\t\t\t\t\tif (!xcraft->isInDogfight() && u->getSpeed() <= xcraft->getCraftStats().speedMax)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (u->isHunterKiller())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// Check if some other HK already attacked before us (at the very same moment)\n\t\t\t\t\t\t\t\tint hkDogfights = 0;\n\t\t\t\t\t\t\t\tfor (auto* f : _dogfights) if (f->isUfoAttacking()) { hkDogfights++; }\n\t\t\t\t\t\t\t\tfor (auto* g : _dogfightsToBeStarted) if (g->isUfoAttacking()) { hkDogfights++; }\n\n\t\t\t\t\t\t\t\t// If yes, wait... not more than 1 HK interception allowed at a time.\n\t\t\t\t\t\t\t\tif (hkDogfights >= 1)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t++craftIt;\n\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// If not, interrupt all other (regular) interceptions to prevent a dead-lock (and other possible side effects)\n\t\t\t\t\t\t\t\tfor (auto* f : _dogfights) if (f->getCraft()) { f->getCraft()->setInDogfight(false); f->getCraft()->setInterceptionOrder(0); }\n\t\t\t\t\t\t\t\tfor (auto* g : _dogfightsToBeStarted) if (g->getCraft()) { g->getCraft()->setInDogfight(false); g->getCraft()->setInterceptionOrder(0); }\n\t\t\t\t\t\t\t\tCollections::deleteAll(_dogfights);\n\t\t\t\t\t\t\t\tCollections::deleteAll(_dogfightsToBeStarted);\n\t\t\t\t\t\t\t\t_minimizedDogfights = 0;\n\n\t\t\t\t\t\t\t\t// Don't process certain craft logic (moving and reaching destination)\n\t\t\t\t\t\t\t\tufoIsAttacking = true;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Main target\n\t\t\t\t\t\t\tDogfightState* dogfight = new DogfightState(this, xcraft, u, u->isHunterKiller());\n\t\t\t\t\t\t\t_dogfightsToBeStarted.push_back(dogfight);\n\n\t\t\t\t\t\t\tif (u->isHunterKiller() && _game->getMod()->getEscortsJoinFightAgainstHK())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// Start fighting escorts and other craft as well (if they are in escort range)\n\t\t\t\t\t\t\t\tint secondaryTargets = 0;\n\t\t\t\t\t\t\t\tfor (auto* craft : *activeCrafts)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tif (!craft->isIgnoredByHK() && craft != xcraft)\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t// craft is close enough and has at least one loaded weapon\n\t\t\t\t\t\t\t\t\t\tif (craft->getNumWeapons(true) > 0 && craft->getDistance(xcraft) < Nautical(_game->getMod()->getEscortRange()))\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t// only up to 4 dogfights = 1 main + 3 secondary\n\t\t\t\t\t\t\t\t\t\t\tif (secondaryTargets < 3)\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t// Note: push_front() is used so that main target is attacked first\n\t\t\t\t\t\t\t\t\t\t\t\t_dogfightsToBeStarted.push_front(new DogfightState(this, craft, u, u->isHunterKiller()));\n\t\t\t\t\t\t\t\t\t\t\t\tsecondaryTargets++;\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Ignore these restrictions when fighting against a HK, otherwise it's very easy to avoid being attacked\n\t\t\t\t\t\t\tif (!u->isHunterKiller())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (xcraft->getRules()->isWaterOnly() && u->getAltitudeInt() > xcraft->getRules()->getMaxAltitude())\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tpopup(new DogfightErrorState(xcraft, tr(\"STR_UNABLE_TO_ENGAGE_DEPTH\")));\n\t\t\t\t\t\t\t\t\tdogfight->setMinimized(true);\n\t\t\t\t\t\t\t\t\tdogfight->setWaitForAltitude(true);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse if (xcraft->getRules()->isWaterOnly() && !_globe->insideLand(xcraft->getLongitude(), xcraft->getLatitude()))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tpopup(new DogfightErrorState(xcraft, tr(\"STR_UNABLE_TO_ENGAGE_AIRBORNE\")));\n\t\t\t\t\t\t\t\t\tdogfight->setMinimized(true);\n\t\t\t\t\t\t\t\t\tdogfight->setWaitForPoly(true);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (!_dogfightStartTimer->isRunning())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t_pause = true;\n\t\t\t\t\t\t\t\ttimerReset();\n\t\t\t\t\t\t\t\t_globe->center(xcraft->getLongitude(), xcraft->getLatitude());\n\t\t\t\t\t\t\t\tstartDogfight();\n\t\t\t\t\t\t\t\t_dogfightStartTimer->start();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t_game->getMod()->playMusic(\"GMINTER\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase Ufo::LANDED:\n\t\t\t\t\tcase Ufo::CRASHED:\n\t\t\t\t\tcase Ufo::DESTROYED: // Just before expiration\n\t\t\t\t\t\tif (xcraft->getNumTotalUnits() > 0 && xcraft->getRules()->getAllowLanding() && !suppressLanding)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (!xcraft->isInDogfight())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// look up polygons texture\n\t\t\t\t\t\t\t\tint texture, shade;\n\t\t\t\t\t\t\t\t_globe->getPolygonTextureAndShade(u->getLongitude(), u->getLatitude(), &texture, &shade);\n\t\t\t\t\t\t\t\ttimerReset();\n\t\t\t\t\t\t\t\tTexture* globeTexture = _game->getMod()->getGlobe()->getTexture(texture);\n\t\t\t\t\t\t\t\tpopup(new ConfirmLandingState(xcraft, globeTexture, globeTexture, shade));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (u->getStatus() != Ufo::LANDED)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\txcraft->returnToBase();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase Ufo::IGNORE_ME:\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (w != 0)\n\t\t\t\t{\n\t\t\t\t\tif (!xcraft->getIsAutoPatrolling())\n\t\t\t\t\t{\n\t\t\t\t\t\tpopup(new CraftPatrolState(xcraft, _globe));\n\t\t\t\t\t}\n\t\t\t\t\txcraft->setDestination(0);\n\t\t\t\t}\n\t\t\t\telse if (m != 0)\n\t\t\t\t{\n\t\t\t\t\tif (xcraft->getNumTotalUnits() > 0 && xcraft->getRules()->getAllowLanding() && !suppressLanding)\n\t\t\t\t\t{\n\t\t\t\t\t\t// look up polygons texture\n\t\t\t\t\t\tint texture, shade;\n\t\t\t\t\t\t_globe->getPolygonTextureAndShade(m->getLongitude(), m->getLatitude(), &texture, &shade);\n\t\t\t\t\t\ttimerReset();\n\t\t\t\t\t\tTexture* globeTexture = _game->getMod()->getGlobe()->getTexture(texture);\n\t\t\t\t\t\tif (globeTexture->isCosmeticOcean())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// Unlike xcom bases, alien bases and ufo crash/land sites, mission sites can actually happen on ocean (=non-polygon part of the globe)\n\t\t\t\t\t\t\t// e.g. TFTD surface attacks\n\t\t\t\t\t\t\t// For backwards-compatibility, let's use texture = -1 instead of any cosmetic ocean texture\n\t\t\t\t\t\t\tglobeTexture = _game->getMod()->getGlobe()->getTexture(-1);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tTexture* missionTexture = _game->getMod()->getGlobe()->getTexture(m->getTexture());\n\t\t\t\t\t\tif (!missionTexture)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tmissionTexture = globeTexture;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tpopup(new ConfirmLandingState(xcraft, missionTexture, globeTexture, shade));\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\txcraft->returnToBase();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (b != 0)\n\t\t\t\t{\n\t\t\t\t\tif (b->isDiscovered())\n\t\t\t\t\t{\n\t\t\t\t\t\tif (xcraft->getNumTotalUnits() > 0 && xcraft->getRules()->getAllowLanding() && !suppressLanding)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tint texture, shade;\n\t\t\t\t\t\t\t_globe->getPolygonTextureAndShade(b->getLongitude(), b->getLatitude(), &texture, &shade);\n\t\t\t\t\t\t\ttimerReset();\n\t\t\t\t\t\t\tTexture* globeTexture = _game->getMod()->getGlobe()->getTexture(texture);\n\t\t\t\t\t\t\tpopup(new ConfirmLandingState(xcraft, globeTexture, globeTexture, shade));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\txcraft->returnToBase();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (x != 0)\n\t\t\t\t{\n\t\t\t\t\tif (x->getStatus() != \"STR_OUT\" || x->isDestroyed())\n\t\t\t\t\t{\n\t\t\t\t\t\txcraft->returnToBase();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t ++craftIt;\n\t\t}\n\t}\n\n\t// Clean up dead UFOs and end dogfights which were minimized.\n\tCollections::deleteIf(*_game->getSavedGame()->getUfos(), _game->getSavedGame()->getUfos()->size(),\n\t\t[&](Ufo* ufo)\n\t\t{\n\t\t\tif (ufo->getStatus() == Ufo::DESTROYED)\n\t\t\t{\n\t\t\t\tCollections::deleteIf(_dogfights, _dogfights.size(),\n\t\t\t\t\t[&](DogfightState* dogfight)\n\t\t\t\t\t{\n\t\t\t\t\t\treturn dogfight->getUfo() == ufo;\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t);\n\n\t// Check any dogfights waiting to open\n\tfor (auto* dfs : _dogfights)\n\t{\n\t\tif (dfs->isMinimized())\n\t\t{\n\t\t\tif ((dfs->getWaitForPoly() && _globe->insideLand(dfs->getUfo()->getLongitude(), dfs->getUfo()->getLatitude())) ||\n\t\t\t\t(dfs->getWaitForAltitude() && dfs->getUfo()->getAltitudeInt() <= dfs->getCraft()->getRules()->getMaxAltitude()))\n\t\t\t{\n\t\t\t\t_pause = true; // the USO reached the sea during this interval period, stop the timer and let handleDogfights() take it from there.\n\t\t\t\ttimerReset();\n\t\t\t}\n\t\t}\n\t}\n\n\t// Clean up unused waypoints\n\tCollections::deleteIf(*_game->getSavedGame()->getWaypoints(), _game->getSavedGame()->getWaypoints()->size(),\n\t\t[&](Waypoint* way)\n\t\t{\n\t\t\treturn way->getFollowers()->empty();\n\t\t}\n\t);\n}\n\n/**\n * Functor that attempt to detect an XCOM base.\n */\nclass DetectXCOMBase\n{\npublic:\n\t/// Create a detector for the given base.\n\tDetectXCOMBase(const Base &base) : _base(base) { /* Empty by design.  */ }\n\t/// Attempt detection\n\tbool operator()(const Ufo *ufo) const;\nprivate:\n\tconst Base &_base;\t//!< The target base.\n};\n\n/**\n * Only UFOs within detection range of the base have a chance to detect it.\n * @param ufo Pointer to the UFO attempting detection.\n * @return If the base is detected by @a ufo.\n */\nbool DetectXCOMBase::operator()(const Ufo *ufo) const\n{\n\tif (ufo->getTrajectoryPoint() <= 1) return false;\n\tif (ufo->getTrajectory().getZone(ufo->getTrajectoryPoint()) == 5) return false;\n\tif ((ufo->getMission()->getRules().getObjective() != OBJECTIVE_RETALIATION && !Options::aggressiveRetaliation) ||\t// only UFOs on retaliation missions actively scan for bases\n\t\tufo->getTrajectory().getID() == UfoTrajectory::RETALIATION_ASSAULT_RUN || \t\t\t\t\t\t\t\t\t\t// UFOs attacking a base don't detect!\n\t\tufo->isCrashed() ||\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Crashed UFOs don't detect!\n\t\tufo->getStatus() == Ufo::IGNORE_ME ||\n\t\t_base.getDistance(ufo) >= Nautical(ufo->getCraftStats().sightRange))\t\t\t\t\t\t\t\t\t\t\t// UFOs have a detection range of 80 XCOM units. - we use a great circle formula and nautical miles.\n\t{\n\t\treturn false;\n\t}\n\treturn RNG::percent(_base.getDetectionChance());\n}\n\n/**\n * Takes care of any game logic that has to\n * run every game ten minutes, like fuel consumption.\n */\nvoid GeoscapeState::time10Minutes()\n{\n\tfor (auto* xbase : *_game->getSavedGame()->getBases())\n\t{\n\t\t// Fuel consumption for XCOM craft.\n\t\tfor (auto* xcraft : *xbase->getCrafts())\n\t\t{\n\t\t\tif (xcraft->getStatus() == \"STR_OUT\")\n\t\t\t{\n\t\t\t\tint escortSpeed = 0;\n\t\t\t\t{\n\t\t\t\t\tCraft *escortee = dynamic_cast<Craft*>(xcraft->getDestination());\n\t\t\t\t\tif (escortee != 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (xcraft->getDistance(escortee) < Nautical(_game->getMod()->getEscortRange()))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tescortSpeed = escortee->getSpeed();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\txcraft->consumeFuel(escortSpeed);\n\t\t\t\tif (!xcraft->getLowFuel() && xcraft->getFuel() <= xcraft->getFuelLimit())\n\t\t\t\t{\n\t\t\t\t\txcraft->setLowFuel(true);\n\t\t\t\t\txcraft->returnToBase();\n\t\t\t\t\tif (!xcraft->getIsAutoPatrolling())\n\t\t\t\t\t{\n\t\t\t\t\t\tpopup(new LowFuelState(xcraft, this));\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (xcraft->getDestination() == 0 && xcraft->getCraftStats().sightRange > 0)\n\t\t\t\t{\n\t\t\t\t\tdouble range = Nautical(xcraft->getCraftStats().sightRange);\n\t\t\t\t\tfor (auto* ab : *_game->getSavedGame()->getAlienBases())\n\t\t\t\t\t{\n\t\t\t\t\t\tif (xcraft->getDistance(ab) <= range)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (RNG::percent(50-(xcraft->getDistance(ab) / range) * 50) && !ab->isDiscovered())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tab->setDiscovered(true);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif (Options::aggressiveRetaliation)\n\t{\n\t\t// Detect as many bases as possible.\n\t\tfor (auto* xbase : *_game->getSavedGame()->getBases())\n\t\t{\n\t\t\t// Find a UFO that detected this base, if any.\n\t\t\tauto uu = std::find_if (_game->getSavedGame()->getUfos()->begin(), _game->getSavedGame()->getUfos()->end(), DetectXCOMBase(*xbase));\n\t\t\tif (uu != _game->getSavedGame()->getUfos()->end())\n\t\t\t{\n\t\t\t\t// Base found\n\t\t\t\txbase->setRetaliationTarget(true);\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\t// Only remember last base in each region.\n\t\tstd::map<const Region *, Base *> discovered;\n\t\tfor (auto* xbase : *_game->getSavedGame()->getBases())\n\t\t{\n\t\t\t// Find a UFO that detected this base, if any.\n\t\t\tauto uu = std::find_if (_game->getSavedGame()->getUfos()->begin(), _game->getSavedGame()->getUfos()->end(), DetectXCOMBase(*xbase));\n\t\t\tif (uu != _game->getSavedGame()->getUfos()->end())\n\t\t\t{\n\t\t\t\tdiscovered[_game->getSavedGame()->locateRegion(*xbase)] = xbase;\n\t\t\t}\n\t\t}\n\t\t// Now mark the bases as discovered.\n\t\tfor (auto& pair : discovered)\n\t\t{\n\t\t\tpair.second->setRetaliationTarget(true);\n\t\t}\n\t}\n\n\t// Handle alien bases detecting xcom craft and generating hunt missions\n\tbaseHunting();\n\n\t// Handle UFO re-targeting (i.e. hunting and escorting) logic\n\tufoHuntingAndEscorting();\n}\n\nvoid GeoscapeState::ufoHuntingAndEscorting()\n{\n\tauto* activeCrafts = updateActiveCrafts();\n\n\tfor (auto* ufo : *_game->getSavedGame()->getUfos())\n\t{\n\t\tif (ufo->isHunterKiller() && ufo->getStatus() == Ufo::FLYING)\n\t\t{\n\t\t\t// current target and attraction\n\t\t\tint newAttraction = INT_MAX;\n\t\t\tCraft *newTarget = 0;\n\t\t\tCraft *originalTarget = 0;\n\t\t\tif (ufo->isHunting())\n\t\t\t{\n\t\t\t\toriginalTarget = ufo->getTargetedXcomCraft();\n\t\t\t}\n\t\t\tif (originalTarget && !originalTarget->isIgnoredByHK())\n\t\t\t{\n\t\t\t\tif (ufo->insideRadarRange(originalTarget))\n\t\t\t\t{\n\t\t\t\t\tnewTarget = originalTarget;\n\t\t\t\t\tnewAttraction = newTarget->getHunterKillerAttraction(ufo->getHuntMode());\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// look for more attractive target\n\t\t\tfor (auto* craft : *activeCrafts)\n\t\t\t{\n\t\t\t\tif (!craft->isIgnoredByHK() && !craft->getRules()->isUndetectable())\n\t\t\t\t{\n\t\t\t\t\tint tmpAttraction = craft->getHunterKillerAttraction(ufo->getHuntMode());\n\t\t\t\t\tif (tmpAttraction < newAttraction && ufo->insideRadarRange(craft))\n\t\t\t\t\t{\n\t\t\t\t\t\tnewTarget = craft;\n\t\t\t\t\t\tnewAttraction = tmpAttraction;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (newTarget)\n\t\t\t{\n\t\t\t\tif (newTarget != originalTarget)\n\t\t\t\t{\n\t\t\t\t\t// set new target\n\t\t\t\t\tufo->setTargetedXcomCraft(newTarget);\n\t\t\t\t\t// TODO: rethink: always reveal the hunting UFO (even outside of radar range?)\n\t\t\t\t\tufo->setDetected(true);\n\t\t\t\t\tif (ufo->getId() == 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tufo->setId(_game->getSavedGame()->getId(\"STR_UFO\"));\n\t\t\t\t\t}\n\t\t\t\t\t// inform the player\n\t\t\t\t\tif (ufo->getRules()->getHuntAlertSound() != Mod::NO_SOUND)\n\t\t\t\t\t{\n\t\t\t\t\t\t_game->getMod()->getSound(\"GEO.CAT\", ufo->getRules()->getHuntAlertSound())->play();\n\t\t\t\t\t}\n\t\t\t\t\tif (Options::oxceGeoSuppressRedundantHKAlert && newTarget->getDestination() == ufo)\n\t\t\t\t\t{\n\t\t\t\t\t\t// Empty by design\n\t\t\t\t\t\t// If the player sent an interceptor after the HK, the alert is redundant\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tstd::string msg = tr(\"STR_UFO_STARTED_HUNTING\")\n\t\t\t\t\t\t\t.arg(ufo->getName(_game->getLanguage()))\n\t\t\t\t\t\t\t.arg(newTarget->getName(_game->getLanguage()));\n\t\t\t\t\t\tpopup(new CraftErrorState(this, msg));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (originalTarget)\n\t\t\t{\n\t\t\t\t// stop hunting\n\t\t\t\tufo->resetOriginalDestination(originalTarget);\n\t\t\t}\n\n\t\t\t// If we are not preoccupied by hunting, let's see if there is still anyone left to escort\n\t\t\tif (ufo->isEscort() && !ufo->isHunting() && !ufo->isEscorting())\n\t\t\t{\n\t\t\t\t// Find a UFO to escort\n\t\t\t\tfor (auto* ufoToBeEscorted : *_game->getSavedGame()->getUfos())\n\t\t\t\t{\n\t\t\t\t\t// From the same mission\n\t\t\t\t\tif (ufoToBeEscorted->getMission()->getId() == ufo->getMission()->getId())\n\t\t\t\t\t{\n\t\t\t\t\t\t// But not another hunter-killer, we escort only normal UFOs\n\t\t\t\t\t\tif (!ufoToBeEscorted->isHunterKiller())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tufo->setEscortedUfo(ufoToBeEscorted);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid GeoscapeState::baseHunting()\n{\n\tauto* activeCrafts = updateActiveCrafts();\n\n\tfor (auto* ab : *_game->getSavedGame()->getAlienBases())\n\t{\n\t\tif (ab->getDeployment()->getBaseDetectionRange() > 0)\n\t\t{\n\t\t\t// Increase counter by 10 minutes\n\t\t\tab->setMinutesSinceLastHuntMissionGeneration(ab->getMinutesSinceLastHuntMissionGeneration() + 10);\n\n\t\t\t// Check counter\n\t\t\tif (ab->getMinutesSinceLastHuntMissionGeneration() >= ab->getDeployment()->getHuntMissionMaxFrequency())\n\t\t\t{\n\t\t\t\t// Look for nearby craft\n\t\t\t\tbool started = false;\n\t\t\t\tfor (auto* craft : *activeCrafts)\n\t\t\t\t{\n\t\t\t\t\t// Craft is flying (i.e. not in base)\n\t\t\t\t\tif (craft->getStatus() == \"STR_OUT\" && !craft->isDestroyed() && !craft->getRules()->isUndetectable() && !craft->isIgnoredByHK())\n\t\t\t\t\t{\n\t\t\t\t\t\t// Craft is close enough and RNG is in our favour\n\t\t\t\t\t\tif (craft->getDistance(ab) < Nautical(ab->getDeployment()->getBaseDetectionRange()) && RNG::percent(ab->getDeployment()->getBaseDetectionChance()))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// Generate a hunt mission\n\t\t\t\t\t\t\tconst std::string huntMission = ab->getDeployment()->generateHuntMission(_game->getSavedGame()->getMonthsPassed());\n\t\t\t\t\t\t\tif (_game->getMod()->getAlienMission(huntMission))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// Spawn hunt mission for this base.\n\t\t\t\t\t\t\t\tconst RuleAlienMission &rule = *_game->getMod()->getAlienMission(huntMission);\n\t\t\t\t\t\t\t\tAlienMission *mission = new AlienMission(rule);\n\t\t\t\t\t\t\t\tmission->setRegion(_game->getSavedGame()->locateRegion(*ab)->getRules()->getType(), *_game->getMod());\n\t\t\t\t\t\t\t\tmission->setId(_game->getSavedGame()->getId(\"ALIEN_MISSIONS\"));\n\t\t\t\t\t\t\t\tif (!ab->getDeployment()->isHuntMissionRaceFromAlienBase() && rule.hasRaceWeights())\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tmission->setRace(rule.generateRace(_game->getSavedGame()->getMonthsPassed()));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tmission->setRace(ab->getAlienRace());\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tmission->setAlienBase(ab);\n\t\t\t\t\t\t\t\tint targetArea = -1;\n\t\t\t\t\t\t\t\tif (mission->getRules().getObjective() == OBJECTIVE_SITE)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tint missionZone = mission->getRules().getSpawnZone();\n\t\t\t\t\t\t\t\t\tRuleRegion *regionRules = _game->getMod()->getRegion(mission->getRegion());\n\t\t\t\t\t\t\t\t\tconst std::vector<MissionArea> areas = regionRules->getMissionZones().at(missionZone).areas;\n\t\t\t\t\t\t\t\t\tif (!areas.empty())\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\ttargetArea = RNG::generate(0, areas.size() - 1);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tmission->setMissionSiteZoneArea(targetArea);\n\t\t\t\t\t\t\t\tmission->start(*_game, *_globe);\n\t\t\t\t\t\t\t\t_game->getSavedGame()->getAlienMissions().push_back(mission);\n\n\t\t\t\t\t\t\t\t// Start immediately\n\t\t\t\t\t\t\t\tmission->think(*_game, *_globe);\n\n\t\t\t\t\t\t\t\t// Reset counter\n\t\t\t\t\t\t\t\tab->setMinutesSinceLastHuntMissionGeneration(0);\n\t\t\t\t\t\t\t\tstarted = true;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if (huntMission != \"\")\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tthrow Exception(\"Alien Base tried to generate undefined hunt mission: \" + huntMission);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (started) break;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/** @brief Process a MissionSite.\n * This function object will count down towards expiring a MissionSite, and handle expired MissionSites.\n * @param ts Pointer to mission site.\n * @return Has mission site expired?\n */\nbool GeoscapeState::processMissionSite(MissionSite *site)\n{\n\tbool removeSite = site->getSecondsRemaining() < 30 * 60;\n\tif (!removeSite)\n\t{\n\t\tsite->setSecondsRemaining(site->getSecondsRemaining() - 30 * 60);\n\t}\n\telse\n\t{\n\t\tbool noFollowers = site->getFollowers()->empty();\n\t\tif (site->getRules()->despawnEvenIfTargeted())\n\t\t{\n\t\t\tfor (auto* follower : site->getCraftFollowers())\n\t\t\t{\n\t\t\t\tfollower->returnToBase();\n\t\t\t}\n\t\t\tif (!noFollowers)\n\t\t\t{\n\t\t\t\tpopup(new UfoLostState(site->getName(_game->getLanguage())));\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tremoveSite = noFollowers; // CHEEKY EXPLOIT\n\t\t}\n\t}\n\tif (removeSite)\n\t{\n\t\t// Unlock research defined in alien deployment, if the mission site despawned\n\t\tconst RuleResearch* research = _game->getMod()->getResearch(site->getDeployment()->getUnlockedResearchOnDespawn());\n\t\t_game->getSavedGame()->handleResearchUnlockedByMissions(research, _game->getMod(), site->getDeployment());\n\n\t\t// Increase counters\n\t\t_game->getSavedGame()->increaseCustomCounter(site->getDeployment()->getCounterDespawn());\n\t\t_game->getSavedGame()->increaseCustomCounter(site->getDeployment()->getCounterFailure()); // despawn is also a type of failure\n\t\t_game->getSavedGame()->increaseCustomCounter(site->getDeployment()->getCounterAll());\n\t\t// Decrease counters\n\t\t_game->getSavedGame()->decreaseCustomCounter(site->getDeployment()->getDecreaseCounterDespawn());\n\t\t_game->getSavedGame()->decreaseCustomCounter(site->getDeployment()->getDecreaseCounterFailure()); // despawn is also a type of failure\n\t\t_game->getSavedGame()->decreaseCustomCounter(site->getDeployment()->getDecreaseCounterAll());\n\n\t\t// Generate a despawn event\n\t\tauto* eventRules = _game->getMod()->getEvent(site->getDeployment()->chooseDespawnEvent());\n\t\tbool canSpawn = _game->getSavedGame()->canSpawnInstantEvent(eventRules);\n\t\tif (canSpawn)\n\t\t{\n\t\t\ttimerReset();\n\t\t\tpopup(new GeoscapeEventState(*eventRules));\n\t\t}\n\t}\n\n\tint score = removeSite ? site->getDeployment()->getDespawnPenalty() : site->getDeployment()->getPoints();\n\n\tRegion *region = _game->getSavedGame()->locateRegion(*site);\n\tif (region)\n\t{\n\t\tregion->addActivityAlien(score);\n\t}\n\tfor (auto* country : *_game->getSavedGame()->getCountries())\n\t{\n\t\tif (country->getRules()->insideCountry(site->getLongitude(), site->getLatitude()))\n\t\t{\n\t\t\tcountry->addActivityAlien(score);\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tUfo* ufo = site->getUfo();\n\tif (removeSite && ufo)\n\t{\n\t\t// \"reactivate\" the corresponding Ufo\n\t\tsite->setUfo(nullptr);\n\t\tufo->getMission()->ufoLifting(*ufo, *_game->getSavedGame());\n\t}\n\n\treturn removeSite;\n}\n\n/**\n * Takes care of any game logic that has to\n * run every game half hour, like UFO detection.\n */\nvoid GeoscapeState::time30Minutes()\n{\n\t// Decrease mission countdowns\n\tfor (auto* am : _game->getSavedGame()->getAlienMissions())\n\t{\n\t\tsize_t abCount = _game->getSavedGame()->getAlienBases()->size();\n\n\t\tam->think(*_game, *_globe);\n\n\t\tif (abCount < _game->getSavedGame()->getAlienBases()->size())\n\t\t{\n\t\t\tAlienBase* newAlienBase = _game->getSavedGame()->getAlienBases()->back();\n\t\t\tif (!newAlienBase->isDiscovered() && am->getRules().showAlienBase())\n\t\t\t{\n\t\t\t\tnewAlienBase->setDiscovered(true);\n\t\t\t\tpopup(new AlienBaseState(newAlienBase, this));\n\t\t\t}\n\t\t}\n\n\t\tif (am->getRules().getObjective() == OBJECTIVE_RETALIATION && am->isOver())\n\t\t{\n\t\t\tfor (auto* xcomBase : *_game->getSavedGame()->getBases())\n\t\t\t{\n\t\t\t\tif (xcomBase->getRetaliationMission() == am)\n\t\t\t\t{\n\t\t\t\t\txcomBase->setRetaliationMission(nullptr);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Remove finished missions\n\tCollections::deleteIf(\n\t\t_game->getSavedGame()->getAlienMissions(),\n\t\t[](AlienMission* am)\n\t\t{\n\t\t\treturn am->isOver();\n\t\t}\n\t);\n\n\t// Handle crashed UFOs expiration\n\tfor (auto* ufo : *_game->getSavedGame()->getUfos())\n\t{\n\t\tif (ufo->getStatus() == Ufo::CRASHED)\n\t\t{\n\t\t\tif (ufo->getSecondsRemaining() >= 30 * 60)\n\t\t\t{\n\t\t\t\tufo->setSecondsRemaining(ufo->getSecondsRemaining() - 30 * 60);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// Marked expired UFOs for removal.\n\t\t\tufo->setStatus(Ufo::DESTROYED);\n\t\t}\n\t}\n\n\t// Handle craft maintenance and alien base detection\n\tfor (auto* xbase : *_game->getSavedGame()->getBases())\n\t{\n\t\tfor (auto* xcraft : *xbase->getCrafts())\n\t\t{\n\t\t\tif (xcraft->getStatus() == \"STR_REFUELLING\")\n\t\t\t{\n\t\t\t\tstd::string item = xcraft->refuel();\n\n\t\t\t\tif (item.empty())\n\t\t\t\t{\n\t\t\t\t\t// notification\n\t\t\t\t\tif (xcraft->getStatus() == \"STR_READY\" && xcraft->getRules()->notifyWhenRefueled())\n\t\t\t\t\t{\n\t\t\t\t\t\tstd::string msg = tr(\"STR_CRAFT_IS_READY\").arg(xcraft->getName(_game->getLanguage())).arg(xbase->getName());\n\t\t\t\t\t\tpopup(new CraftErrorState(this, msg));\n\t\t\t\t\t}\n\t\t\t\t\t// auto-patrol\n\t\t\t\t\tif (xcraft->getStatus() == \"STR_READY\" && xcraft->getRules()->canAutoPatrol())\n\t\t\t\t\t{\n\t\t\t\t\t\tif (xcraft->getIsAutoPatrolling())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tWaypoint *w = new Waypoint();\n\t\t\t\t\t\t\tw->setLongitude(xcraft->getLongitudeAuto());\n\t\t\t\t\t\t\tw->setLatitude(xcraft->getLatitudeAuto());\n\t\t\t\t\t\t\tif (w != 0 && w->getId() == 0)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tw->setId(_game->getSavedGame()->getId(\"STR_WAY_POINT\"));\n\t\t\t\t\t\t\t\t_game->getSavedGame()->getWaypoints()->push_back(w);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\txcraft->setDestination(w);\n\t\t\t\t\t\t\txcraft->setStatus(\"STR_OUT\");\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tstd::string msg = tr(\"STR_NOT_ENOUGH_ITEM_TO_REFUEL_CRAFT_AT_BASE\")\n\t\t\t\t\t\t\t\t\t\t.arg(tr(item))\n\t\t\t\t\t\t\t\t\t\t.arg(xcraft->getName(_game->getLanguage()))\n\t\t\t\t\t\t\t\t\t\t.arg(xbase->getName());\n\t\t\t\t\tpopup(new CraftErrorState(this, msg));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// can be updated by previous loop\n\tauto* activeCrafts = updateActiveCrafts();\n\n\t// Handle UFO detection and give aliens points\n\tfor (auto* ufo : *_game->getSavedGame()->getUfos())\n\t{\n\t\t// instant retaliation missions are ignored (UFOs shouldn't be detected)\n\t\tif (ufo->getMission()->getRules().getObjective() == OBJECTIVE_INSTANT_RETALIATION)\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\n\t\tint points = ufo->getRules()->getMissionScore(); //one point per UFO in-flight per half hour\n\t\tswitch (ufo->getStatus())\n\t\t{\n\t\tcase Ufo::LANDED:\n\t\t\tpoints *= 2;\n\t\t\tFALLTHROUGH;\n\t\tcase Ufo::FLYING:\n\t\t\t// Get area\n\t\t\tfor (auto* region : *_game->getSavedGame()->getRegions())\n\t\t\t{\n\t\t\t\tif (region->getRules()->insideRegion(ufo->getLongitude(), ufo->getLatitude()))\n\t\t\t\t{\n\t\t\t\t\tregion->addActivityAlien(points);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Get country\n\t\t\tfor (auto* country : *_game->getSavedGame()->getCountries())\n\t\t\t{\n\t\t\t\tif (country->getRules()->insideCountry(ufo->getLongitude(), ufo->getLatitude()))\n\t\t\t\t{\n\t\t\t\t\tcountry->addActivityAlien(points);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Detection ufo state\n\t\t\tufoDetection(ufo, activeCrafts);\n\n\t\t\tbreak;\n\t\tcase Ufo::CRASHED:\n\t\tcase Ufo::DESTROYED:\n\t\tcase Ufo::IGNORE_ME:\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// Processes MissionSites\n\tCollections::deleteIf(\n\t\t*_game->getSavedGame()->getMissionSites(),\n\t\t[&](MissionSite* site)\n\t\t{\n\t\t\treturn processMissionSite(site);\n\t\t}\n\t);\n\n\t// Decrease event countdowns and pop up if needed\n\tfor (auto* ge : _game->getSavedGame()->getGeoscapeEvents())\n\t{\n\t\tge->think();\n\n\t\tif (ge->isOver())\n\t\t{\n\t\t\tbool interrupted = false;\n\t\t\tif (!ge->getRules().getInterruptResearch().empty())\n\t\t\t{\n\t\t\t\tif (_game->getSavedGame()->isResearched(ge->getRules().getInterruptResearch(), false))\n\t\t\t\t{\n\t\t\t\t\tinterrupted = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!interrupted)\n\t\t\t{\n\t\t\t\ttimerReset();\n\t\t\t\tpopup(new GeoscapeEventState(ge->getRules()));\n\t\t\t}\n\t\t}\n\t}\n\n\t// Remove finished events\n\tCollections::deleteIf(\n\t\t_game->getSavedGame()->getGeoscapeEvents(),\n\t\t[](GeoscapeEvent *ge)\n\t\t{\n\t\t\treturn ge->isOver();\n\t\t}\n\t);\n}\n\n/**\n * Logic responsible for detecting ufo and its tracking.\n * @param ufo\n */\nvoid GeoscapeState::ufoDetection(Ufo* ufo, const std::vector<Craft*>* activeCrafts)\n{\n\tauto maskTest = [](UfoDetection value, UfoDetection mask)\n\t{\n\t\treturn (value & mask) == mask;\n\t};\n\tauto maskBitOr = [](UfoDetection value, UfoDetection mask)\n\t{\n\t\treturn (UfoDetection)(value | mask);\n\t};\n\n\tauto detected = DETECTION_NONE;\n\tauto alreadyTracked = ufo->getDetected();\n\tauto save = _game->getSavedGame();\n\n\tfor (auto* base : *_game->getSavedGame()->getBases())\n\t{\n\t\tdetected = maskBitOr(detected, base->detect(ufo, save, alreadyTracked));\n\t}\n\n\tfor (auto* craft : *activeCrafts)\n\t{\n\t\tdetected = maskBitOr(detected, craft->detect(ufo, save, alreadyTracked));\n\t}\n\n\tif (!alreadyTracked)\n\t{\n\t\tif (maskTest(detected, DETECTION_RADAR))\n\t\t{\n\t\t\tif (maskTest(detected, DETECTION_HYPERWAVE))\n\t\t\t{\n\t\t\t\tufo->setHyperDetected(true);\n\t\t\t}\n\t\t\tufo->setDetected(true);\n\t\t\t// don't show if player said he doesn't want to see this UFO anymore\n\t\t\tif (!_game->getSavedGame()->isUfoOnIgnoreList(ufo->getId()) && !ufo->getRules()->isNoAlert())\n\t\t\t{\n\t\t\t\tpopup(new UfoDetectedState(ufo, this, true, ufo->getHyperDetected()));\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\tif (maskTest(detected, DETECTION_HYPERWAVE))\n\t\t{\n\t\t\tufo->setHyperDetected(true);\n\t\t}\n\t\t// TODO: rethink: hunting UFOs stay visible even outside of radar range?\n\t\tif (!maskTest(detected, DETECTION_RADAR) && !ufo->isHunting())\n\t\t{\n\t\t\tufo->setDetected(false);\n\t\t\tufo->setHyperDetected(false);\n\t\t\tif (!ufo->getFollowers()->empty())\n\t\t\t{\n\t\t\t\tpopup(new UfoLostState(ufo->getName(_game->getLanguage())));\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Takes care of any game logic that has to\n * run every game hour, like transfers.\n */\nvoid GeoscapeState::time1Hour()\n{\n\t// Handle craft maintenance\n\tfor (auto* xbase : *_game->getSavedGame()->getBases())\n\t{\n\t\tfor (auto* xcraft : *xbase->getCrafts())\n\t\t{\n\t\t\tif (xcraft->getStatus() == \"STR_REPAIRS\")\n\t\t\t{\n\t\t\t\txcraft->repair();\n\t\t\t}\n\t\t\telse if (xcraft->getStatus() == \"STR_REARMING\")\n\t\t\t{\n\t\t\t\tauto* ammo = xcraft->rearm();\n\t\t\t\tif (ammo)\n\t\t\t\t{\n\t\t\t\t\tstd::string msg = tr(\"STR_NOT_ENOUGH_ITEM_TO_REARM_CRAFT_AT_BASE\")\n\t\t\t\t\t\t\t\t\t   .arg(tr(ammo->getType()))\n\t\t\t\t\t\t\t\t\t   .arg(xcraft->getName(_game->getLanguage()))\n\t\t\t\t\t\t\t\t\t   .arg(xbase->getName());\n\t\t\t\t\tpopup(new CraftErrorState(this, msg));\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (xcraft->getShieldCapacity() > 0 && xcraft->getStatus() != \"STR_OUT\")\n\t\t\t{\n\t\t\t\t// Recharge craft shields in parallel (no wait for repair/rearm/refuel)\n\t\t\t\txcraft->setShield(xcraft->getShield() + xcraft->getRules()->getShieldRechargeAtBase());\n\t\t\t}\n\t\t}\n\t}\n\n\t// Handle base defenses maintenance\n\tfor (auto* xbase : *_game->getSavedGame()->getBases())\n\t{\n\t\tfor (auto* facility : *xbase->getFacilities())\n\t\t{\n\t\t\tauto* ammo = facility->rearm();\n\t\t\tif (ammo)\n\t\t\t{\n\t\t\t\tstd::string msg = tr(\"STR_NOT_ENOUGH_ITEM_TO_REARM_FACILITY_AT_BASE\")\n\t\t\t\t\t.arg(tr(ammo->getType()))\n\t\t\t\t\t.arg(tr(facility->getRules()->getType()))\n\t\t\t\t\t.arg(xbase->getName());\n\t\t\t\tpopup(new CraftErrorState(this, msg));\n\t\t\t}\n\t\t}\n\t}\n\n\t// Handle transfers\n\tbool window = false;\n\tfor (auto* xbase : *_game->getSavedGame()->getBases())\n\t{\n\t\tfor (auto* transfer : *xbase->getTransfers())\n\t\t{\n\t\t\ttransfer->advance(xbase);\n\t\t\tif (!window && transfer->getHours() <= 0)\n\t\t\t{\n\t\t\t\twindow = true;\n\t\t\t}\n\t\t}\n\t}\n\tif (window)\n\t{\n\t\tpopup(new ItemsArrivingState(this));\n\t}\n\t// Handle Production\n\tfor (auto* xbase : *_game->getSavedGame()->getBases())\n\t{\n\t\tstd::map<Production*, productionProgress_e> toRemove;\n\t\tfor (auto* prod : xbase->getProductions())\n\t\t{\n\t\t\ttoRemove[prod] = prod->step(xbase, _game->getSavedGame(), _game->getMod(), _game->getLanguage());\n\t\t}\n\t\tfor (const auto& pair : toRemove)\n\t\t{\n\t\t\tif (pair.second > PROGRESS_NOT_COMPLETE)\n\t\t\t{\n\t\t\t\tpopup(new ProductionCompleteState(xbase,  tr(pair.first->getRules()->getName()), this, pair.second, pair.first));\n\t\t\t\txbase->removeProduction(pair.first);\n\t\t\t}\n\t\t}\n\n\t\tif (Options::storageLimitsEnforced)\n\t\t{\n\t\t\tif (xbase->storesOverfull())\n\t\t\t{\n\t\t\t\ttimerReset();\n\t\t\t\tpopup(new ErrorMessageState(tr(\"STR_STORAGE_EXCEEDED\").arg(xbase->getName()), _palette, _game->getMod()->getInterface(\"geoscape\")->getElement(\"errorMessage\")->color, \"BACK13.SCR\", _game->getMod()->getInterface(\"geoscape\")->getElement(\"errorPalette\")->color));\n\t\t\t\tpopup(new SellState(xbase, 0));\n\t\t\t}\n\t\t\tif (!_game->getSavedGame()->getAlienContainmentChecked())\n\t\t\t{\n\t\t\t\tstd::map<int, int> prisonTypes;\n\t\t\t\tfor (const auto& item : *xbase->getStorageItems()->getContents())\n\t\t\t\t{\n\t\t\t\t\tconst RuleItem* rule = item.first;\n\t\t\t\t\tif (rule->isAlien())\n\t\t\t\t\t{\n\t\t\t\t\t\tprisonTypes[rule->getPrisonType()] += 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfor (const auto& pair : prisonTypes)\n\t\t\t\t{\n\t\t\t\t\tint prisonType = pair.first;\n\t\t\t\t\tif (xbase->getUsedContainment(prisonType) > xbase->getAvailableContainment(prisonType))\n\t\t\t\t\t{\n\t\t\t\t\t\ttimerReset();\n\t\t\t\t\t\tpopup(new ErrorMessageState(\n\t\t\t\t\t\t\ttrAlt(\"STR_CONTAINMENT_EXCEEDED\", prisonType).arg(xbase->getName()),\n\t\t\t\t\t\t\t_palette,\n\t\t\t\t\t\t\t_game->getMod()->getInterface(\"geoscape\")->getElement(\"errorMessage\")->color,\n\t\t\t\t\t\t\t\"BACK01.SCR\",\n\t\t\t\t\t\t\t_game->getMod()->getInterface(\"geoscape\")->getElement(\"errorPalette\")->color));\n\t\t\t\t\t\tpopup(new ManageAlienContainmentState(xbase, prisonType, OPT_GEOSCAPE));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t_game->getSavedGame()->setAlienContainmentChecked(true); // check only once after reload\n\n\tbool postpone = false;\n\tfor (auto* msite : *_game->getSavedGame()->getMissionSites())\n\t{\n\t\tif (!msite->getDetected())\n\t\t{\n\t\t\tpostpone = true;\n\t\t\tmsite->setDetected(true);\n\t\t\tif (msite->getSecondsRemaining() < 3600)\n\t\t\t{\n\t\t\t\tmsite->setSecondsRemaining(3600); // minimum 1 hour since detection\n\t\t\t}\n\t\t\tpopup(new MissionDetectedState(msite, this));\n\t\t\tbreak; // only one popup per hour!\n\t\t}\n\t}\n\tif (postpone)\n\t{\n\t\tfor (auto* msite : *_game->getSavedGame()->getMissionSites())\n\t\t{\n\t\t\tif (!msite->getDetected())\n\t\t\t{\n\t\t\t\tmsite->setSecondsRemaining(msite->getSecondsRemaining() + 3600); // +1 hour\n\t\t\t}\n\t\t}\n\t}\n\n\tupdateSlackingIndicator();\n}\n\n/**\n * This class will attempt to generate a supply mission for a base.\n * Each alien base has a 6/101 chance to generate a supply mission.\n */\nclass GenerateSupplyMission\n{\npublic:\n\t/// Store rules and game data references for later use.\n\tGenerateSupplyMission(Game &engine, const Globe &globe) : _engine(engine), _globe(globe) { /* Empty by design */ }\n\t/// Check and spawn mission.\n\tvoid operator()(AlienBase *base) const;\nprivate:\n\tGame &_engine;\n\tconst Globe &_globe;\n};\n\n/**\n * Check and create supply mission for the given base.\n * There is a 6/101 chance of the mission spawning.\n * @param base A pointer to the alien base.\n */\nvoid GenerateSupplyMission::operator()(AlienBase *base) const\n{\n\tconst Mod &_mod = *_engine.getMod();\n\tSavedGame &_save = *_engine.getSavedGame();\n\n\tstd::string missionName = base->getDeployment()->chooseGenMissionType();\n\tif (_mod.getAlienMission(missionName))\n\t{\n\t\tif (base->getGenMissionCount() < base->getDeployment()->getGenMissionLimit() && RNG::percent(base->getDeployment()->getGenMissionFrequency()))\n\t\t{\n\t\t\t//Spawn supply mission for this base.\n\t\t\tconst RuleAlienMission &rule = *_mod.getAlienMission(missionName);\n\t\t\tAlienMission *mission = new AlienMission(rule);\n\t\t\tstd::string targetRegion;\n\t\t\tif (RNG::percent(rule.getTargetBaseOdds()))\n\t\t\t{\n\t\t\t\t// 1. target a random xcom base region\n\t\t\t\tstd::vector<std::string> regionsWithXcomBases;\n\t\t\t\tfor (auto* xbase : *_save.getBases())\n\t\t\t\t{\n\t\t\t\t\tregionsWithXcomBases.push_back(_save.locateRegion(*xbase)->getRules()->getType());\n\t\t\t\t}\n\t\t\t\ttargetRegion = regionsWithXcomBases[RNG::generate(0, regionsWithXcomBases.size() - 1)];\n\t\t\t}\n\t\t\telse if (rule.hasRegionWeights())\n\t\t\t{\n\t\t\t\t// 2. target one of the defined (weighted) regions\n\t\t\t\ttargetRegion = rule.generateRegion(_save.getMonthsPassed());\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// 3. target the region of the alien base (vanilla default)\n\t\t\t\ttargetRegion = _save.locateRegion(*base)->getRules()->getType();\n\t\t\t}\n\t\t\tmission->setRegion(targetRegion, _mod);\n\t\t\tmission->setId(_save.getId(\"ALIEN_MISSIONS\"));\n\t\t\tif (!base->getDeployment()->isGenMissionRaceFromAlienBase() && rule.hasRaceWeights())\n\t\t\t{\n\t\t\t\tmission->setRace(rule.generateRace(_save.getMonthsPassed()));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tmission->setRace(base->getAlienRace());\n\t\t\t}\n\t\t\tmission->setAlienBase(base);\n\t\t\tint targetArea = -1;\n\t\t\tif (mission->getRules().getObjective() == OBJECTIVE_SITE)\n\t\t\t{\n\t\t\t\tint missionZone = mission->getRules().getSpawnZone();\n\t\t\t\tRuleRegion *regionRules = _mod.getRegion(mission->getRegion());\n\t\t\t\tconst std::vector<MissionArea> areas = regionRules->getMissionZones().at(missionZone).areas;\n\t\t\t\tif (!areas.empty())\n\t\t\t\t{\n\t\t\t\t\ttargetArea = RNG::generate(0, areas.size() - 1);\n\t\t\t\t}\n\t\t\t}\n\t\t\tmission->setMissionSiteZoneArea(targetArea);\n\t\t\tmission->start(_engine, _globe);\n\t\t\tbase->setGenMissionCount(base->getGenMissionCount() + 1); // increase counter, used to check mission limit\n\t\t\t_save.getAlienMissions().push_back(mission);\n\t\t}\n\t}\n\telse if (!missionName.empty())\n\t{\n\t\tthrow Exception(\"Alien Base tried to generate undefined mission: \" + missionName);\n\t}\n}\n\n/**\n * Takes care of any game logic that has to\n * run every game day, like constructions.\n */\nvoid GeoscapeState::time1Day()\n{\n\t_game->getSavedGame()->increaseDaysPassed();\n\n\tSavedGame *saveGame = _game->getSavedGame();\n\tMod *mod = _game->getMod();\n\tbool psiStrengthEval = (Options::psiStrengthEval && saveGame->isResearched(mod->getPsiRequirements()));\n\n\tauto addResearchDiaryEntryForBase = [&](const RuleResearch* discoveredResearch, DiscoverySourceType sourceType, const Base* sourceBase, const RuleResearch* sourceResearch)\n\t{\n\t\tif (!saveGame->isResearched(discoveredResearch) && !saveGame->isResearchRuleStatusDisabled(discoveredResearch->getName()))\n\t\t{\n\t\t\tResearchDiaryEntry* entry = new ResearchDiaryEntry(discoveredResearch);\n\t\t\tentry->setDate(saveGame->getTime());\n\t\t\tentry->source.type = sourceType;\n\t\t\tif (sourceType == DiscoverySourceType::BASE)\n\t\t\t{\n\t\t\t\tentry->source.name = sourceBase->getName();\n\t\t\t}\n\t\t\telse // sourceType == DiscoverySourceType::FREE_FROM\n\t\t\t{\n\t\t\t\tentry->source.research = sourceResearch;\n\t\t\t\tentry->source.name = sourceResearch->getName();\n\t\t\t}\n\t\t\tsaveGame->addResearchDiaryEntry(entry);\n\t\t}\n\t};\n\n\tfor (auto* xbase : *_game->getSavedGame()->getBases())\n\t{\n\t\t// Handle facility construction\n\t\tstd::map<const RuleBaseFacility*, int> finishedFacilities;\n\t\tfor (auto* facility : *xbase->getFacilities())\n\t\t{\n\t\t\tif (facility->getBuildTime() > 0)\n\t\t\t{\n\t\t\t\tfacility->build();\n\t\t\t\tif (facility->getBuildTime() == 0)\n\t\t\t\t{\n\t\t\t\t\tfinishedFacilities[facility->getRules()] += 1;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfor (const auto& pair : finishedFacilities)\n\t\t{\n\t\t\tif (pair.second > 1)\n\t\t\t{\n\t\t\t\tstd::ostringstream ssf;\n\t\t\t\tssf << tr(pair.first->getType()) << \" (x\" << pair.second << \")\";\n\t\t\t\tpopup(new ProductionCompleteState(xbase, ssf.str(), this, PROGRESS_CONSTRUCTION));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tpopup(new ProductionCompleteState(xbase, tr(pair.first->getType()), this, PROGRESS_CONSTRUCTION));\n\t\t\t}\n\t\t}\n\n\t\t// Handle science project\n\t\t// 1. gather finished research\n\t\tstd::vector<ResearchProject*> finished;\n\t\tfor (auto* proj : xbase->getResearch())\n\t\t{\n\t\t\tif (proj->step())\n\t\t\t{\n\t\t\t\tfinished.push_back(proj);\n\t\t\t}\n\t\t}\n\t\t// 2. remember available research before adding new finished research\n\t\tstd::vector<RuleResearch*> before;\n\t\tif (!finished.empty())\n\t\t{\n\t\t\tsaveGame->getAvailableResearchProjects(before, mod, xbase);\n\t\t\tfor (auto* fp : finished)\n\t\t\t{\n\t\t\t\tif (fp->getRules()->isRepeatable())\n\t\t\t\t{\n\t\t\t\t\tRuleResearch* nonconst = mod->getResearch(fp->getRules()->getName());\n\t\t\t\t\tbefore.push_back(nonconst);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// 3. add finished research, including lookups and getonefrees (up to 4x)\n\t\tstd::vector<const RuleResearch*> topicsToCheck;\n\t\tfor (auto* project : finished)\n\t\t{\n\t\t\tconst RuleResearch *bonus = 0;\n\t\t\tconst RuleResearch *research = project->getRules();\n\n\t\t\t// 3a. remove finished research from the base where it was researched\n\t\t\txbase->removeResearch(project);\n\t\t\tproject = nullptr;\n\n\t\t\t// 3b. add core research to research diary (before the getonefrees)\n\t\t\taddResearchDiaryEntryForBase(research, DiscoverySourceType::BASE, xbase, nullptr);\n\t\t\tif (const RuleResearch* lookupResearch = research->getLookup())\n\t\t\t\taddResearchDiaryEntryForBase(lookupResearch, DiscoverySourceType::BASE, xbase, nullptr);\n\t\t\t// 3c. handle getonefrees (topic+lookup)\n\t\t\tif ((bonus = saveGame->selectGetOneFree(research)))\n\t\t\t{\n\t\t\t\taddResearchDiaryEntryForBase(bonus, DiscoverySourceType::FREE_FROM, nullptr, research);\n\t\t\t\tsaveGame->addFinishedResearch(bonus, mod, xbase);\n\t\t\t\tif (const RuleResearch* bonusLookup = bonus->getLookup())\n\t\t\t\t{\n\t\t\t\t\taddResearchDiaryEntryForBase(bonusLookup, DiscoverySourceType::FREE_FROM, nullptr, research);\n\t\t\t\t\tsaveGame->addFinishedResearch(bonusLookup, mod, xbase);\n\t\t\t\t}\n\t\t\t}\n\t\t\t// 3d. determine and remember if the ufopedia article should pop up again or not\n\t\t\t// Note: because different topics may lead to the same lookup\n\t\t\tconst RuleResearch *newResearch = research;\n\t\t\tif (saveGame->isResearched(research->getLookup() ? research->getLookup() : research, false))\n\t\t\t{\n\t\t\t\tnewResearch = 0;\n\t\t\t}\n\t\t\t// 3e. handle core research (topic+lookup)\n\t\t\tsaveGame->addFinishedResearch(research, mod, xbase);\n\t\t\tif (research->getLookup())\n\t\t\t{\n\t\t\t\tsaveGame->addFinishedResearch(research->getLookup(), mod, xbase);\n\t\t\t}\n\t\t\t// 3e. handle cutscene\n\t\t\tif (!research->getCutscene().empty())\n\t\t\t{\n\t\t\t\tpopup(new CutsceneState(research->getCutscene()));\n\t\t\t\tif (saveGame->getEnding() == END_NONE)\n\t\t\t\t{\n\t\t\t\t\tconst RuleVideo* videoRule = _game->getMod()->getVideo(research->getCutscene(), true);\n\t\t\t\t\tif (videoRule->getWinGame()) saveGame->setEnding(END_WIN);\n\t\t\t\t\tif (videoRule->getLoseGame()) saveGame->setEnding(END_LOSE);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (bonus && !bonus->getCutscene().empty())\n\t\t\t{\n\t\t\t\tpopup(new CutsceneState(bonus->getCutscene()));\n\t\t\t\tif (saveGame->getEnding() == END_NONE)\n\t\t\t\t{\n\t\t\t\t\tconst RuleVideo* videoRule = _game->getMod()->getVideo(bonus->getCutscene(), true);\n\t\t\t\t\tif (videoRule->getWinGame()) saveGame->setEnding(END_WIN);\n\t\t\t\t\tif (videoRule->getLoseGame()) saveGame->setEnding(END_LOSE);\n\t\t\t\t}\n\t\t\t}\n\t\t\t// 3e. handle research complete popup + ufopedia article popups (topic+bonus)\n\t\t\tpopup(new ResearchCompleteState(newResearch, bonus, research, xbase));\n\t\t\t// 3f. reset timer\n\t\t\ttimerReset();\n\t\t\t// 3g. warning if weapon is researched before its clip\n\t\t\tif (newResearch)\n\t\t\t{\n\t\t\t\tRuleItem *item = mod->getItem(newResearch->getName());\n\t\t\t\tif (item && item->getBattleType() == BT_FIREARM && !item->getPrimaryCompatibleAmmo()->empty())\n\t\t\t\t{\n\t\t\t\t\tRuleManufacture *man = mod->getManufacture(item->getType());\n\t\t\t\t\tif (man && !man->getRequirements().empty())\n\t\t\t\t\t{\n\t\t\t\t\t\tconst auto& req = man->getRequirements();\n\t\t\t\t\t\tconst RuleItem *ammo = item->getPrimaryCompatibleAmmo()->front();\n\t\t\t\t\t\tif (std::find_if(req.begin(), req.end(), [&](const RuleResearch* r){ return r->getName() == ammo->getType(); }) != req.end() && !saveGame->isResearched(req, true))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tpopup(new ResearchRequiredState(item));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// 3h. inform about new possible research\n\t\t\tstd::vector<RuleResearch *> after;\n\t\t\tsaveGame->getAvailableResearchProjects(after, mod, xbase);\n\t\t\tstd::vector<RuleResearch *> newPossibleResearch;\n\t\t\tsaveGame->getNewlyAvailableResearchProjects(before, after, newPossibleResearch);\n\t\t\tpopup(new NewPossibleResearchState(xbase, newPossibleResearch));\n\t\t\t// 3i. inform about new possible manufacture, purchase, craft and facilities\n\t\t\tstd::vector<RuleManufacture *> newPossibleManufacture;\n\t\t\tsaveGame->getDependableManufacture(newPossibleManufacture, research, mod, xbase);\n\t\t\tif (bonus)\n\t\t\t{\n\t\t\t\tsaveGame->getDependableManufacture(newPossibleManufacture, bonus, mod, xbase);\n\t\t\t}\n\t\t\tif (!newPossibleManufacture.empty())\n\t\t\t{\n\t\t\t\tCollections::sortVector(newPossibleManufacture);\n\t\t\t\tCollections::sortVectorMakeUnique(newPossibleManufacture);\n\t\t\t\tpopup(new NewPossibleManufactureState(xbase, newPossibleManufacture));\n\t\t\t}\n\t\t\tstd::vector<RuleItem *> newPossiblePurchase;\n\t\t\t_game->getSavedGame()->getDependablePurchase(newPossiblePurchase, research, _game->getMod());\n\t\t\tif (bonus)\n\t\t\t{\n\t\t\t\t_game->getSavedGame()->getDependablePurchase(newPossiblePurchase, bonus, _game->getMod());\n\t\t\t}\n\t\t\tif (!newPossiblePurchase.empty())\n\t\t\t{\n\t\t\t\tCollections::sortVector(newPossiblePurchase);\n\t\t\t\tCollections::sortVectorMakeUnique(newPossiblePurchase);\n\t\t\t\tpopup(new NewPossiblePurchaseState(xbase, newPossiblePurchase));\n\t\t\t}\n\t\t\tstd::vector<RuleCraft *> newPossibleCraft;\n\t\t\t_game->getSavedGame()->getDependableCraft(newPossibleCraft, research, _game->getMod());\n\t\t\tif (bonus)\n\t\t\t{\n\t\t\t\t_game->getSavedGame()->getDependableCraft(newPossibleCraft, bonus, _game->getMod());\n\t\t\t}\n\t\t\tif (!newPossibleCraft.empty())\n\t\t\t{\n\t\t\t\tCollections::sortVector(newPossibleCraft);\n\t\t\t\tCollections::sortVectorMakeUnique(newPossibleCraft);\n\t\t\t\tpopup(new NewPossibleCraftState(xbase, newPossibleCraft));\n\t\t\t}\n\t\t\tstd::vector<RuleBaseFacility *> newPossibleFacilities;\n\t\t\t_game->getSavedGame()->getDependableFacilities(newPossibleFacilities, research, _game->getMod());\n\t\t\tif (bonus)\n\t\t\t{\n\t\t\t\t_game->getSavedGame()->getDependableFacilities(newPossibleFacilities, bonus, _game->getMod());\n\t\t\t}\n\t\t\tif (!newPossibleFacilities.empty())\n\t\t\t{\n\t\t\t\tCollections::sortVector(newPossibleFacilities);\n\t\t\t\tCollections::sortVectorMakeUnique(newPossibleFacilities);\n\t\t\t\tpopup(new NewPossibleFacilityState(xbase, _globe, newPossibleFacilities));\n\t\t\t}\n\n\t\t\ttopicsToCheck.push_back(research);\n\t\t\tif (bonus)\n\t\t\t{\n\t\t\t\ttopicsToCheck.push_back(bonus);\n\t\t\t}\n\t\t}\n\t\tif (!topicsToCheck.empty())\n\t\t{\n\t\t\tCollections::sortVector(topicsToCheck);\n\t\t\tCollections::sortVectorMakeUnique(topicsToCheck);\n\t\t\t// Side effects:\n\t\t\t// 1. remove obsolete research projects from all bases\n\t\t\t// 2. handle items spawned by research\n\t\t\t// 3. handle events spawned by research\n\t\t\tsaveGame->handlePrimaryResearchSideEffects(topicsToCheck, _game->getMod(), xbase);\n\t\t}\n\n\t\t// Handle soldier wounds and martial training\n\t\tBaseSumDailyRecovery recovery = xbase->getSumRecoveryPerDay();\n\t\tstd::vector<Soldier *> trainingFinishedList;\n\t\tfor (auto* soldier : *xbase->getSoldiers())\n\t\t{\n\t\t\tsoldier->replenishStats(recovery);\n\n\t\t\tif (soldier->isInTraining())\n\t\t\t{\n\t\t\t\tsoldier->trainPhys(_game->getMod()->getCustomTrainingFactor());\n\t\t\t\tsoldier->calcStatString(_game->getMod()->getStatStrings(), psiStrengthEval);\n\t\t\t\tif (soldier->isFullyTrained())\n\t\t\t\t{\n\t\t\t\t\tsoldier->setTraining(false);\n\t\t\t\t\ttrainingFinishedList.push_back(soldier);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (soldier->getReturnToTrainingWhenHealed() && !soldier->isWounded())\n\t\t\t\t{\n\t\t\t\t\tif (!soldier->isFullyTrained() && xbase->getFreeTrainingSpace() > 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tsoldier->setTraining(true);\n\t\t\t\t\t}\n\t\t\t\t\t// only ever try to return once\n\t\t\t\t\tsoldier->setReturnToTrainingWhenHealed(false);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (!trainingFinishedList.empty())\n\t\t{\n\t\t\tpopup(new TrainingFinishedState(xbase, trainingFinishedList, false));\n\t\t}\n\t\t// Handle psionic training\n\t\tif (xbase->getAvailablePsiLabs() > 0 && Options::anytimePsiTraining)\n\t\t{\n\t\t\tstd::vector<Soldier*> psiTrainingFinishedList;\n\t\t\tfor (auto* s : *xbase->getSoldiers())\n\t\t\t{\n\t\t\t\ts->trainPsi1Day();\n\t\t\t\ts->calcStatString(_game->getMod()->getStatStrings(), psiStrengthEval);\n\t\t\t\tif (s->isInPsiTraining() && s->isFullyPsiTrained())\n\t\t\t\t{\n\t\t\t\t\ts->setPsiTraining(false);\n\t\t\t\t\tpsiTrainingFinishedList.push_back(s);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!psiTrainingFinishedList.empty())\n\t\t\t{\n\t\t\t\tpopup(new TrainingFinishedState(xbase, psiTrainingFinishedList, true));\n\t\t\t}\n\t\t}\n\t}\n\n\t// check and remove disabled projects from ongoing research\n\tfor (auto* xbase : *_game->getSavedGame()->getBases())\n\t{\n\t\tstd::vector<ResearchProject*> obsolete;\n\t\tfor (auto* proj : xbase->getResearch())\n\t\t{\n\t\t\tif (_game->getSavedGame()->isResearchRuleStatusDisabled(proj->getRules()->getName()))\n\t\t\t{\n\t\t\t\tobsolete.push_back(proj);\n\t\t\t}\n\t\t}\n\t\tfor (auto* proj : obsolete)\n\t\t{\n\t\t\txbase->removeResearch(proj);\n\t\t}\n\t}\n\n\t// check and interrupt alien missions if necessary (based on discovered research)\n\tfor (auto* am : saveGame->getAlienMissions())\n\t{\n\t\tauto& researchName = am->getRules().getInterruptResearch();\n\t\tif (!researchName.empty())\n\t\t{\n\t\t\tauto* research = mod->getResearch(researchName, true);\n\t\t\tif (saveGame->isResearched(research, false)) // ignore debug mode\n\t\t\t{\n\t\t\t\tam->setInterrupted(true);\n\t\t\t}\n\t\t}\n\t}\n\n\t// check and self-destruct alien bases if necessary (based on discovered research)\n\tauto abIt = saveGame->getAlienBases()->begin();\n\twhile (abIt != saveGame->getAlienBases()->end())\n\t{\n\t\tAlienBase* ab = (*abIt);\n\t\tauto& selfDestructCode = ab->getDeployment()->getBaseSelfDestructCode();\n\t\tif (!selfDestructCode.empty())\n\t\t{\n\t\t\tauto* research = mod->getResearch(selfDestructCode, true);\n\t\t\tif (saveGame->isResearched(research, false)) // ignore debug mode\n\t\t\t{\n\t\t\t\tsaveGame->clearLinksForAlienBase(ab, _game->getMod());\n\t\t\t\tdelete ab;\n\t\t\t\tabIt = saveGame->getAlienBases()->erase(abIt);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t++abIt;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t++abIt;\n\t\t}\n\t}\n\n\t// handle regional and country points for alien bases\n\tfor (auto* ab : *saveGame->getAlienBases())\n\t{\n\t\tfor (auto* region : *saveGame->getRegions())\n\t\t{\n\t\t\tif (region->getRules()->insideRegion(ab->getLongitude(), ab->getLatitude()))\n\t\t\t{\n\t\t\t\tregion->addActivityAlien(ab->getDeployment()->getPoints());\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tfor (auto* country : *saveGame->getCountries())\n\t\t{\n\t\t\tif (country->getRules()->insideCountry(ab->getLongitude(), ab->getLatitude()))\n\t\t\t{\n\t\t\t\tcountry->addActivityAlien(ab->getDeployment()->getPoints());\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Handle resupply of alien bases.\n\tstd::for_each(saveGame->getAlienBases()->begin(), saveGame->getAlienBases()->end(),\n\t\t\t  GenerateSupplyMission(*_game, *_globe));\n\n\t// Handle alien base detection (by xcom base facilities).\n\tfor (auto* alienBase : *_game->getSavedGame()->getAlienBases())\n\t{\n\t\tif (alienBase->isDiscovered()) continue;\n\t\tfor (auto* xcomBase : *_game->getSavedGame()->getBases())\n\t\t{\n\t\t\tint distance = XcomDistance(xcomBase->getDistance(alienBase));\n\t\t\tfor (auto* facility : *xcomBase->getFacilities())\n\t\t\t{\n\t\t\t\tif (facility->getBuildTime() == 0 && facility->getRules()->getSightRange() > distance)\n\t\t\t\t{\n\t\t\t\t\tint chanceToDetect = facility->getRules()->getSightChance(); // static % defined by the modder\n\t\t\t\t\tif (chanceToDetect == 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tchanceToDetect = 50 - (distance * 50 / facility->getRules()->getSightRange()); // dynamic 0-50% based on relative distance\n\t\t\t\t\t}\n\t\t\t\t\tif (RNG::percent(chanceToDetect))\n\t\t\t\t\t{\n\t\t\t\t\t\talienBase->setDiscovered(true);\n\t\t\t\t\t\tpopup(new AlienBaseState(alienBase, this));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// clear the daily dogfight experience cache\n\tfor (auto* xbase : *saveGame->getBases())\n\t{\n\t\tfor (auto* soldier : *xbase->getSoldiers())\n\t\t{\n\t\t\tsoldier->resetDailyDogfightExperienceCache();\n\t\t}\n\t}\n\n\t// Autosave 3 times a month\n\tbool performGeoAutosave = false;\n\tint day = saveGame->getTime()->getDay();\n\tif (Options::oxceGeoAutosaveFrequency == 0 && (day == 10 || day == 20))\n\t{\n\t\t// OXC backwards-compatibility\n\t\tperformGeoAutosave = true;\n\t}\n\telse if (Options::oxceGeoAutosaveFrequency >= 1 && Options::oxceGeoAutosaveFrequency <= 10)\n\t{\n\t\t// every X-th day\n\t\tperformGeoAutosave = (saveGame->getDaysPassed() % Options::oxceGeoAutosaveFrequency == 0);\n\t}\n\tif (performGeoAutosave)\n\t{\n\t\tif (saveGame->isIronman())\n\t\t{\n\t\t\tpopup(new SaveGameState(OPT_GEOSCAPE, SAVE_IRONMAN, _palette));\n\t\t}\n\t\telse if (Options::autosave)\n\t\t{\n\t\t\tpopup(new SaveGameState(OPT_GEOSCAPE, SAVE_AUTO_GEOSCAPE, _palette, saveGame->getDaysPassed()));\n\t\t}\n\t}\n\telse if (saveGame->getEnding() != END_NONE && saveGame->isIronman())\n\t{\n\t\t_game->pushState(new SaveGameState(OPT_GEOSCAPE, SAVE_IRONMAN, _palette));\n\t}\n\n\t// pay attention to your maintenance player!\n\tif (_game->getSavedGame()->getTime()->isLastDayOfMonth())\n\t{\n\t\tint month = _game->getSavedGame()->getMonthsPassed();\n\t\tint currentScore = _game->getSavedGame()->getCurrentScore(month + 1);\n\t\tint performanceBonus = mod->getPerformanceBonus(currentScore);\n\t\tif (performanceBonus < 0)\n\t\t{\n\t\t\tperformanceBonus = 0; // bonus only, no malus\n\t\t}\n\n\t\tint64_t funds = _game->getSavedGame()->getFunds();\n\t\tint64_t income = _game->getSavedGame()->getCountryFunding() + performanceBonus;\n\t\tint64_t maintenance = _game->getSavedGame()->getBaseMaintenance();\n\t\tint64_t projection = funds + income - maintenance;\n\t\tif (projection < 0)\n\t\t{\n\t\t\tprojection = std::abs(projection);\n\t\t\tprojection = ((projection / 100000) + 1) * 100000; // round up to 100k\n\t\t\tstd::string msg = tr(\"STR_ECONOMY_WARNING\")\n\t\t\t\t.arg(Unicode::formatFunding(funds))\n\t\t\t\t.arg(Unicode::formatFunding(income))\n\t\t\t\t.arg(Unicode::formatFunding(maintenance))\n\t\t\t\t.arg(Unicode::formatFunding(projection));\n\t\t\tpopup(new CraftErrorState(this, msg, false));\n\t\t}\n\t}\n}\n\n/**\n * Takes care of any game logic that has to\n * run every game month, like funding.\n */\nvoid GeoscapeState::time1Month()\n{\n\t_game->getSavedGame()->addMonth();\n\n\t// Determine alien mission for this month.\n\tdetermineAlienMissions();\n\n\t// Handle Psi-Training and initiate a new retaliation mission, if applicable\n\tif (!Options::anytimePsiTraining)\n\t{\n\t\tbool psiStrengthEval = (Options::psiStrengthEval && _game->getSavedGame()->isResearched(_game->getMod()->getPsiRequirements()));\n\t\tfor (auto* xbase : *_game->getSavedGame()->getBases())\n\t\t{\n\t\t\tif (xbase->getAvailablePsiLabs() > 0)\n\t\t\t{\n\t\t\t\tfor (auto* soldier : *xbase->getSoldiers())\n\t\t\t\t{\n\t\t\t\t\tif (soldier->isInPsiTraining())\n\t\t\t\t\t{\n\t\t\t\t\t\tsoldier->trainPsi();\n\t\t\t\t\t\tsoldier->calcStatString(_game->getMod()->getStatStrings(), psiStrengthEval);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Handle funding\n\ttimerReset();\n\t_game->getSavedGame()->monthlyFunding();\n\tpopup(new MonthlyReportState(_globe));\n\n\t// Handle Xcom Operatives discovering bases\n\tif (!_game->getSavedGame()->getAlienBases()->empty() && RNG::percent(_game->getMod()->getChanceToDetectAlienBaseEachMonth()))\n\t{\n\t\tfor (auto* ab : *_game->getSavedGame()->getAlienBases())\n\t\t{\n\t\t\tif (!ab->isDiscovered())\n\t\t\t{\n\t\t\t\tab->setDiscovered(true);\n\t\t\t\tpopup(new AlienBaseState(ab, this));\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Slows down the timer back to minimum speed,\n * for when important events occur.\n */\nvoid GeoscapeState::timerReset()\n{\n\tSDL_Event ev;\n\tev.button.button = SDL_BUTTON_LEFT;\n\tAction act(&ev, _game->getScreen()->getXScale(), _game->getScreen()->getYScale(), _game->getScreen()->getCursorTopBlackBand(), _game->getScreen()->getCursorLeftBlackBand());\n\t_btn5Secs->mousePress(&act, this);\n}\n\n/**\n * Adds a new popup window to the queue\n * (this prevents popups from overlapping)\n * and pauses the game timer respectively.\n * @param state Pointer to popup state.\n */\nvoid GeoscapeState::popup(State *state)\n{\n\t_pause = true;\n\t_popups.push_back(state);\n}\n\n/**\n * Returns a pointer to the Geoscape globe for\n * access by other substates.\n * @return Pointer to globe.\n */\nGlobe *GeoscapeState::getGlobe() const\n{\n\treturn _globe;\n}\n\n/**\n * Processes any left-clicks on globe markers,\n * or right-clicks to scroll the globe.\n * @param action Pointer to an action.\n */\n\nvoid GeoscapeState::globeClick(Action *action)\n{\n\tint mouseX = (int)floor(action->getAbsoluteXMouse()), mouseY = (int)floor(action->getAbsoluteYMouse());\n\n\t// Clicking markers on the globe\n\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT)\n\t{\n\t\tstd::vector<Target*> v = _globe->getTargets(mouseX, mouseY, false, 0);\n\t\tif (!v.empty())\n\t\t{\n\t\t\t// Pass empty vector\n\t\t\tstd::vector<Craft*> crafts;\n\t\t\t_game->pushState(new MultipleTargetsState(v, crafts, this, true));\n\t\t}\n\t}\n\n\tif (_game->getSavedGame()->getDebugMode())\n\t{\n\t\tdouble lon, lat;\n\t\tint texture, shade;\n\t\t_globe->cartToPolar(mouseX, mouseY, &lon, &lat);\n\t\tdouble lonDeg = lon / M_PI * 180, latDeg = lat / M_PI * 180;\n\t\t_globe->getPolygonTextureAndShade(lon, lat, &texture, &shade);\n\t\tstd::ostringstream ss;\n\t\tss << \"rad: \" << lon << \", \" << lat << std::endl;\n\t\tss << \"deg: \" << lonDeg << \", \" << latDeg << std::endl;\n\t\tss << \"texture: \" << texture << \", shade: \" << shade << std::endl;\n\n\t\t_txtDebug->setText(ss.str());\n\t}\n}\n\n/**\n * Opens the Intercept window.\n * @param action Pointer to an action.\n */\nvoid GeoscapeState::btnInterceptClick(Action *)\n{\n\tif (buttonsDisabled())\n\t{\n\t\treturn;\n\t}\n\t_game->pushState(new InterceptState(_globe, false));\n}\n\n/**\n* Opens the UFO Tracker window.\n* @param action Pointer to an action.\n*/\nvoid GeoscapeState::btnUfoTrackerClick(Action *)\n{\n\t_game->pushState(new UfoTrackerState(this, _globe));\n}\n\n/**\n* Opens the TechTreeViewer window.\n* @param action Pointer to an action.\n*/\nvoid GeoscapeState::btnTechTreeViewerClick(Action *)\n{\n\t_game->pushState(new TechTreeViewerState());\n}\n\n/**\n * Opens the jukebox.\n * @param action Pointer to an action.\n */\nvoid GeoscapeState::btnSelectMusicTrackClick(Action *)\n{\n\t_game->pushState(new SelectMusicTrackState(SMT_GEOSCAPE));\n}\n\n/**\n * Opens the Current Global Production.\n * @param action Pointer to an action.\n */\nvoid GeoscapeState::btnGlobalProductionClick(Action *)\n{\n\t_game->pushState(new GlobalManufactureState(false));\n}\n\n/**\n * Opens the Current Global Research.\n * @param action Pointer to an action.\n */\nvoid GeoscapeState::btnGlobalResearchClick(Action *)\n{\n\t_game->pushState(new GlobalResearchState(false));\n}\n\n/**\n * Opens the Global Alien Containment overview.\n * @param action Pointer to an action.\n */\nvoid GeoscapeState::btnGlobalAlienContainmentClick(Action *)\n{\n\t_game->pushState(new GlobalAlienContainmentState(false));\n}\n\n/**\n * Opens the Dogfight Experience screen.\n * @param action Pointer to an action.\n */\nvoid GeoscapeState::btnDogfightExperienceClick(Action *)\n{\n\t_game->pushState(new DogfightExperienceState());\n}\n\n/**\n * Toggles debug mode.\n * @param action Pointer to an action.\n */\nvoid GeoscapeState::btnDebugClick(Action *)\n{\n\t_game->getSavedGame()->setDebugMode();\n\tif (_game->getSavedGame()->getDebugMode())\n\t{\n\t\t_txtDebug->setText(\"DEBUG MODE\");\n\t}\n\telse\n\t{\n\t\t_txtDebug->setText(\"\");\n\t}\n\t_cbxRegion->setVisible(_game->getSavedGame()->getDebugMode() && _game->getSavedGame()->debugType >= 1);\n\t_cbxZone->setVisible(_game->getSavedGame()->getDebugMode() && _game->getSavedGame()->debugType == 2);\n\t_cbxArea->setVisible(_game->getSavedGame()->getDebugMode() && _game->getSavedGame()->debugType == 2);\n\t_cbxCountry->setVisible(_game->getSavedGame()->getDebugMode() && _game->getSavedGame()->debugType == 0);\n}\n\n/**\n * Goes to the Basescape screen.\n * @param action Pointer to an action.\n */\nvoid GeoscapeState::btnBasesClick(Action *)\n{\n\tif (buttonsDisabled())\n\t{\n\t\treturn;\n\t}\n\ttimerReset();\n\tif (!_game->getSavedGame()->getBases()->empty())\n\t{\n\t\tif (Options::oxceGeoGoToNearestBase)\n\t\t{\n\t\t\tstd::vector< std::pair<size_t, double> > xbaseSorting;\n\t\t\tsize_t baseIdx = 0;\n\t\t\tfor (auto* xbase : *_game->getSavedGame()->getBases())\n\t\t\t{\n\t\t\t\tdouble xdistance = xbase->getDistance(_game->getSavedGame()->getGlobeLongitude(), _game->getSavedGame()->getGlobeLatitude());\n\t\t\t\txbaseSorting.push_back(std::make_pair(baseIdx, xdistance));\n\t\t\t\tbaseIdx++;\n\t\t\t}\n\t\t\tstd::stable_sort(xbaseSorting.begin(), xbaseSorting.end(),\n\t\t\t\t[](const std::pair<size_t, double> &a, const std::pair<size_t, double> &b)\n\t\t\t\t{\n\t\t\t\t\treturn a.second < b.second;\n\t\t\t\t}\n\t\t\t);\n\t\t\t_game->getSavedGame()->setSelectedBase(xbaseSorting.front().first);\n\t\t}\n\t\t_game->pushState(new BasescapeState(_game->getSavedGame()->getSelectedBase(), _globe));\n\t}\n\telse\n\t{\n\t\t_game->pushState(new BasescapeState(0, _globe));\n\t}\n}\n\n/**\n * Goes to the Graphs screen.\n * @param action Pointer to an action.\n */\nvoid GeoscapeState::btnGraphsClick(Action *)\n{\n\tif (buttonsDisabled())\n\t{\n\t\treturn;\n\t}\n\t_game->pushState(new GraphsState);\n}\n\n/**\n * Goes to the Ufopaedia window.\n * @param action Pointer to an action.\n */\nvoid GeoscapeState::btnUfopaediaClick(Action *)\n{\n\tif (buttonsDisabled())\n\t{\n\t\treturn;\n\t}\n\tUfopaedia::open(_game);\n}\n\n/**\n * Opens the Options window.\n * @param action Pointer to an action.\n */\nvoid GeoscapeState::btnOptionsClick(Action *)\n{\n\tif (buttonsDisabled())\n\t{\n\t\treturn;\n\t}\n\t_game->pushState(new PauseState(OPT_GEOSCAPE));\n}\n\n/**\n * Goes to the Funding screen.\n * @param action Pointer to an action.\n */\nvoid GeoscapeState::btnFundingClick(Action *)\n{\n\tif (buttonsDisabled())\n\t{\n\t\treturn;\n\t}\n\tif (Options::oxceLinks)\n\t{\n\t\t_game->pushState(new ExtendedGeoscapeLinksState(this));\n\t}\n\telse\n\t{\n\t\t_game->pushState(new FundingState);\n\t}\n}\n\n/**\n * Starts rotating the globe to the left.\n * @param action Pointer to an action.\n */\nvoid GeoscapeState::btnRotateLeftPress(Action *)\n{\n\t_globe->rotateLeft();\n}\n\n/**\n * Stops rotating the globe to the left.\n * @param action Pointer to an action.\n */\nvoid GeoscapeState::btnRotateLeftRelease(Action *)\n{\n\t_globe->rotateStopLon();\n}\n\n/**\n * Starts rotating the globe to the right.\n * @param action Pointer to an action.\n */\nvoid GeoscapeState::btnRotateRightPress(Action *)\n{\n\t_globe->rotateRight();\n}\n\n/**\n * Stops rotating the globe to the right.\n * @param action Pointer to an action.\n */\nvoid GeoscapeState::btnRotateRightRelease(Action *)\n{\n\t_globe->rotateStopLon();\n}\n\n/**\n * Starts rotating the globe upwards.\n * @param action Pointer to an action.\n */\nvoid GeoscapeState::btnRotateUpPress(Action *)\n{\n\t_globe->rotateUp();\n}\n\n/**\n * Stops rotating the globe upwards.\n * @param action Pointer to an action.\n */\nvoid GeoscapeState::btnRotateUpRelease(Action *)\n{\n\t_globe->rotateStopLat();\n}\n\n/**\n * Starts rotating the globe downwards.\n * @param action Pointer to an action.\n */\nvoid GeoscapeState::btnRotateDownPress(Action *)\n{\n\t_globe->rotateDown();\n}\n\n/**\n * Stops rotating the globe downwards.\n * @param action Pointer to an action.\n */\nvoid GeoscapeState::btnRotateDownRelease(Action *)\n{\n\t_globe->rotateStopLat();\n}\n\n/**\n * Zooms into the globe.\n * @param action Pointer to an action.\n */\nvoid GeoscapeState::btnZoomInLeftClick(Action *)\n{\n\t_globe->zoomIn();\n}\n\n/**\n * Zooms the globe maximum.\n * @param action Pointer to an action.\n */\nvoid GeoscapeState::btnZoomInRightClick(Action *)\n{\n\t_globe->zoomMax();\n}\n\n/**\n * Zooms out of the globe.\n * @param action Pointer to an action.\n */\nvoid GeoscapeState::btnZoomOutLeftClick(Action *)\n{\n\t_globe->zoomOut();\n}\n\n/**\n * Zooms the globe minimum.\n * @param action Pointer to an action.\n */\nvoid GeoscapeState::btnZoomOutRightClick(Action *)\n{\n\t_globe->zoomMin();\n}\n\n/**\n * Zoom in effect for dogfights.\n */\nvoid GeoscapeState::zoomInEffect()\n{\n\tif (_globe->zoomDogfightIn())\n\t{\n\t\t_zoomInEffectDone = true;\n\t\t_zoomInEffectTimer->stop();\n\t}\n}\n\n/**\n * Zoom out effect for dogfights.\n */\nvoid GeoscapeState::zoomOutEffect()\n{\n\tif (_globe->zoomDogfightOut())\n\t{\n\t\t_zoomOutEffectDone = true;\n\t\t_zoomOutEffectTimer->stop();\n\t\tinit();\n\t}\n}\n\n/**\n * Dogfight logic. Moved here to have the code clean.\n */\nvoid GeoscapeState::handleDogfights()\n{\n\t// Handle dogfights logic.\n\t_minimizedDogfights = 0;\n\n\tfor (auto* dfs : _dogfights)\n\t{\n\t\tdfs->getUfo()->setInterceptionProcessed(false);\n\t}\n\n\tauto dfsIt = _dogfights.begin();\n\twhile (dfsIt != _dogfights.end())\n\t{\n\t\tDogfightState* dfs = (*dfsIt);\n\t\tif (dfs->isMinimized())\n\t\t{\n\t\t\tif (dfs->getWaitForPoly() && _globe->insideLand(dfs->getUfo()->getLongitude(), dfs->getUfo()->getLatitude()))\n\t\t\t{\n\t\t\t\tdfs->setMinimized(false);\n\t\t\t\tdfs->setWaitForPoly(false);\n\t\t\t}\n\t\t\telse if (dfs->getWaitForAltitude() && dfs->getUfo()->getAltitudeInt() <= dfs->getCraft()->getRules()->getMaxAltitude())\n\t\t\t{\n\t\t\t\tdfs->setMinimized(false);\n\t\t\t\tdfs->setWaitForAltitude(false);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_minimizedDogfights++;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_globe->rotateStop();\n\t\t}\n\t\tdfs->think();\n\t\tif (dfs->dogfightEnded())\n\t\t{\n\t\t\tif (dfs->isMinimized())\n\t\t\t{\n\t\t\t\t_minimizedDogfights--;\n\t\t\t}\n\t\t\tdelete dfs;\n\t\t\tdfsIt = _dogfights.erase(dfsIt);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t++dfsIt;\n\t\t}\n\t}\n\tif (_dogfights.empty())\n\t{\n\t\t_dogfightTimer->stop();\n\t\t_zoomOutEffectTimer->start();\n\t}\n}\n\n/**\n * Goes through all active dogfight instances and tries to perform the same action.\n * @param button Action to perform.\n */\nvoid GeoscapeState::handleDogfightMultiAction(int button)\n{\n\tfor (auto* dfs : _dogfights)\n\t{\n\t\tif (dfs->isMinimized())\n\t\t\tcontinue;\n\n\t\tSDL_Event ev;\n\t\tev.type = SDL_MOUSEBUTTONDOWN;\n\t\tev.button.button = SDL_BUTTON_LEFT;\n\t\tAction a = Action(&ev, 0.0, 0.0, 0, 0);\n\n\t\tswitch (button)\n\t\t{\n\t\tcase 0:\n\t\t\tdfs->btnStandoffSimulateLeftPress(&a);\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\tdfs->btnCautiousSimulateLeftPress(&a);\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\tdfs->btnStandardSimulateLeftPress(&a);\n\t\t\tbreak;\n\t\tcase 3:\n\t\t\tdfs->btnAggressiveSimulateLeftPress(&a);\n\t\t\tbreak;\n\t\tcase 4:\n\t\t\tdfs->btnDisengageSimulateLeftPress(&a);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n/**\n * Goes through all dogfight instances and tries to award pilot experience.\n * This is called each time any UFO takes any damage in dogfight... very ugly, but I couldn't find a better place for it.\n *\n * History lesson:\n * - this was in the DogfightState destructor before, but could lead to CTD when people reloaded a saved game while dogfights were still active\n * - both OXCE and vanilla OXC still access already deleted objects (_craft and _ufo) in the destructor... that doesn't seem to trigger CTD that often though\n */\nvoid GeoscapeState::handleDogfightExperience()\n{\n\tfor (auto* dfs : _dogfights)\n\t{\n\t\tdfs->awardExperienceToPilots();\n\t}\n\tfor (auto* dfs : _dogfightsToBeStarted)\n\t{\n\t\tdfs->awardExperienceToPilots();\n\t}\n}\n\n/**\n * Gets the number of minimized dogfights.\n * @return Number of minimized dogfights.\n */\nint GeoscapeState::minimizedDogfightsCount()\n{\n\tint minimizedDogfights = 0;\n\tfor (auto* dfs : _dogfights)\n\t{\n\t\tif (dfs->isMinimized())\n\t\t{\n\t\t\t++minimizedDogfights;\n\t\t}\n\t}\n\treturn minimizedDogfights;\n}\n\n/**\n * Starts a new dogfight.\n */\nvoid GeoscapeState::startDogfight()\n{\n\tif (_globe->getZoom() < 3)\n\t{\n\t\tif (!_zoomInEffectTimer->isRunning())\n\t\t{\n\t\t\t_globe->saveZoomDogfight();\n\t\t\t_globe->rotateStop();\n\t\t\t_zoomInEffectTimer->start();\n\t\t}\n\t}\n\telse\n\t{\n\t\t_dogfightStartTimer->stop();\n\t\t_zoomInEffectTimer->stop();\n\t\t_dogfightTimer->start();\n\t\ttimerReset();\n\t\twhile (!_dogfightsToBeStarted.empty())\n\t\t{\n\t\t\t_dogfights.push_back(_dogfightsToBeStarted.back());\n\t\t\t_dogfightsToBeStarted.pop_back();\n\t\t\t_dogfights.back()->setInterceptionNumber(getFirstFreeDogfightSlot());\n\t\t\t_dogfights.back()->setInterceptionsCount(_dogfights.size() + _dogfightsToBeStarted.size());\n\t\t}\n\t\t// Set correct number of interceptions for every dogfight.\n\t\tfor (auto* dfs : _dogfights)\n\t\t{\n\t\t\tdfs->setInterceptionsCount(_dogfights.size());\n\t\t}\n\t}\n}\n\n/**\n * Returns the first free dogfight slot.\n * @return free slot\n */\nint GeoscapeState::getFirstFreeDogfightSlot()\n{\n\tint slotNo = 1;\n\tfor (auto* dfs : _dogfights)\n\t{\n\t\tif (dfs->getInterceptionNumber() == slotNo)\n\t\t{\n\t\t\t++slotNo;\n\t\t}\n\t}\n\treturn slotNo;\n}\n\n/**\n * Handle base defense\n * @param base Base to defend.\n * @param ufo Ufo attacking base.\n */\nvoid GeoscapeState::handleBaseDefense(Base *base, Ufo *ufo)\n{\n\t// Get the shade and texture for the globe at the location of the base, using the ufo position\n\tint texture, shade;\n\tdouble baseLon = ufo->getLongitude();\n\tdouble baseLat = ufo->getLatitude();\n\t_globe->getPolygonTextureAndShade(baseLon, baseLat, &texture, &shade);\n\n\tint ufoDamagePercentage = 0;\n\tif (_game->getMod()->getLessAliensDuringBaseDefense())\n\t{\n\t\tufoDamagePercentage = ufo->getDamagePercentage();\n\t}\n\n\t// Whatever happens in the base defense, the UFO has finished its duty\n\tufo->setStatus(Ufo::DESTROYED);\n\n\t// instant retaliation mission only spawns one UFO and then ends\n\tif (ufo->getMission()->getRules().getObjective() == OBJECTIVE_INSTANT_RETALIATION)\n\t{\n\t\tufo->getMission()->setInterrupted(true);\n\t}\n\n\tif (ufo->getRules()->getMissilePower() != 0)\n\t{\n\t\tif (ufo->getRules()->getMissilePower() < 0)\n\t\t{\n\t\t\t// It's a nuclear warhead... Skynet knows no mercy\n\t\t\tpopup(new BaseDestroyedState(base, ufo, true, false));\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// This is an overkill, since we may not lose any hangar/craft, but doing it properly requires tons of changes\n\t\t\t_game->getSavedGame()->stopHuntingXcomCrafts(base);\n\n\t\t\t// This can either damage facilities (=replace them with some other facilities); or also destroy facilities\n\t\t\tbase->damageFacilities(ufo);\n\n\t\t\t// don't forget to reset pre-cached stuff\n\t\t\tbase->cleanupDefenses(true);\n\n\t\t\t// let the player know that some facilities were destroyed, but the base survived\n\t\t\tpopup(new BaseDestroyedState(base, ufo, true, true));\n\t\t}\n\n\t\t// continue mayhem?\n\t\tif (ufo->getRules()->getMissileStopChance() > 0 && RNG::percent(ufo->getRules()->getMissileStopChance()))\n\t\t{\n\t\t\tufo->getMission()->setInterrupted(true);\n\t\t}\n\t}\n\telse if (base->getAvailableSoldiers(true, true) > 0 || !base->getVehicles()->empty())\n\t{\n\t\tSavedBattleGame *bgame = new SavedBattleGame(_game->getMod(), _game->getLanguage());\n\t\t_game->getSavedGame()->setBattleGame(bgame);\n\t\tbgame->setMissionType(\"STR_BASE_DEFENSE\");\n\t\tBattlescapeGenerator bgen = BattlescapeGenerator(_game);\n\t\tbgen.setBase(base);\n\t\tbgen.setAlienCustomDeploy(_game->getMod()->getDeployment(ufo->getCraftStats().missionCustomDeploy));\n\t\tbgen.setAlienRace(ufo->getAlienRace());\n\t\tbgen.setWorldShade(shade);\n\t\tTexture* globeTexture = _game->getMod()->getGlobe()->getTexture(texture);\n\t\tbgen.setWorldTexture(globeTexture, globeTexture);\n\t\tbgen.setUfoDamagePercentage(ufoDamagePercentage);\n\t\tbgen.run();\n\t\t_pause = true;\n\t\t_game->pushState(new BriefingState(0, base));\n\t}\n\telse\n\t{\n\t\t// Please garrison your bases in future\n\t\tpopup(new BaseDestroyedState(base, ufo, false, false));\n\t}\n}\n\n/**\n * Determine the alien missions to start this month.\n */\nvoid GeoscapeState::determineAlienMissions(bool isNewMonth, const RuleEvent* eventRules)\n{\n\tSavedGame *save = _game->getSavedGame();\n\tAlienStrategy &strategy = save->getAlienStrategy();\n\tMod *mod = _game->getMod();\n\tint month = _game->getSavedGame()->getMonthsPassed();\n\tint currentScore = save->getCurrentScore(month); // _monthsPassed was already increased by 1\n\tint performanceBonus = mod->getPerformanceBonus(currentScore);\n\tif (performanceBonus < 0)\n\t{\n\t\tperformanceBonus = 0; // bonus only, no malus\n\t}\n\tint64_t currentFunds = save->getFunds();\n\tif (isNewMonth)\n\t{\n\t\tcurrentFunds += save->getCountryFunding() + performanceBonus - save->getBaseMaintenance(); // peek into the next month\n\t}\n\tstd::vector<RuleMissionScript*> availableMissions;\n\tstd::unordered_map<int, bool> conditions;\n\n\tstd::unordered_set<std::string> xcomBaseRegions;\n\tstd::unordered_set<std::string> xcomBaseCountries;\n\tstd::unordered_set<std::string> pactCountries;\n\tfor (auto* xcomBase : *save->getBases())\n\t{\n\t\tauto* region = save->locateRegion(*xcomBase);\n\t\tif (region)\n\t\t{\n\t\t\txcomBaseRegions.insert(region->getRules()->getType());\n\t\t}\n\t\tauto* country = save->locateCountry(*xcomBase);\n\t\tif (country)\n\t\t{\n\t\t\txcomBaseCountries.insert(country->getRules()->getType());\n\t\t}\n\t}\n\tfor (auto* country : *save->getCountries())\n\t{\n\t\tif (country->getPact())\n\t\t{\n\t\t\tpactCountries.insert(country->getRules()->getType());\n\t\t}\n\t}\n\n\t// sorry to interrupt, but before we start determining the actual monthly missions, let's determine and/or adjust our overall game plan\n\tif (isNewMonth)\n\t{\n\t\tstd::vector<RuleArcScript*> relevantArcScripts;\n\n\t\t// first we need to build a list of \"valid\" commands\n\t\tfor (auto& scriptName : *mod->getArcScriptList())\n\t\t{\n\t\t\tRuleArcScript* arcScript = mod->getArcScript(scriptName);\n\n\t\t\t// level one condition check: make sure we're within our time constraints\n\t\t\tif (arcScript->getFirstMonth() <= month &&\n\t\t\t\t(arcScript->getLastMonth() >= month || arcScript->getLastMonth() == -1) &&\n\t\t\t\t// and make sure we satisfy the difficulty restrictions\n\t\t\t\t(month < 1 || arcScript->getMinScore() <= currentScore) &&\n\t\t\t\t(month < 1 || arcScript->getMaxScore() >= currentScore) &&\n\t\t\t\t(month < 1 || arcScript->getMinFunds() <= currentFunds) &&\n\t\t\t\t(month < 1 || arcScript->getMaxFunds() >= currentFunds) &&\n\t\t\t\tarcScript->getMinDifficulty() <= save->getDifficulty() &&\n\t\t\t\tarcScript->getMaxDifficulty() >= save->getDifficulty())\n\t\t\t{\n\t\t\t\t// level two condition check: make sure we meet any research requirements, if any.\n\t\t\t\tbool triggerHappy = true;\n\t\t\t\tfor (auto& trigger : arcScript->getResearchTriggers())\n\t\t\t\t{\n\t\t\t\t\ttriggerHappy = (save->isResearched(trigger.first) == trigger.second);\n\t\t\t\t\tif (!triggerHappy)\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (triggerHappy)\n\t\t\t\t{\n\t\t\t\t\t// check counters\n\t\t\t\t\tif (arcScript->getCounterMin() > 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (!arcScript->getMissionVarName().empty() && arcScript->getCounterMin() > strategy.getMissionsRun(arcScript->getMissionVarName()))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttriggerHappy = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!arcScript->getMissionMarkerName().empty() && arcScript->getCounterMin() > save->getLastId(arcScript->getMissionMarkerName()))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttriggerHappy = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (triggerHappy && arcScript->getCounterMax() != -1)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (!arcScript->getMissionVarName().empty() && arcScript->getCounterMax() < strategy.getMissionsRun(arcScript->getMissionVarName()))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttriggerHappy = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!arcScript->getMissionMarkerName().empty() && arcScript->getCounterMax() < save->getLastId(arcScript->getMissionMarkerName()))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttriggerHappy = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (triggerHappy)\n\t\t\t\t{\n\t\t\t\t\t// item requirements\n\t\t\t\t\tfor (auto& triggerItem : arcScript->getItemTriggers())\n\t\t\t\t\t{\n\t\t\t\t\t\ttriggerHappy = (save->isItemObtained(triggerItem.first, mod) == triggerItem.second);\n\t\t\t\t\t\tif (!triggerHappy)\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (triggerHappy)\n\t\t\t\t{\n\t\t\t\t\t// facility requirements\n\t\t\t\t\tfor (auto& triggerFacility : arcScript->getFacilityTriggers())\n\t\t\t\t\t{\n\t\t\t\t\t\ttriggerHappy = (save->isFacilityBuilt(triggerFacility.first) == triggerFacility.second);\n\t\t\t\t\t\tif (!triggerHappy)\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (triggerHappy)\n\t\t\t\t{\n\t\t\t\t\t// soldier type requirements\n\t\t\t\t\tfor (auto& triggerSoldierType : arcScript->getSoldierTypeTriggers())\n\t\t\t\t\t{\n\t\t\t\t\t\ttriggerHappy = (save->isSoldierTypeHired(triggerSoldierType.first) == triggerSoldierType.second);\n\t\t\t\t\t\tif (!triggerHappy)\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (triggerHappy)\n\t\t\t\t{\n\t\t\t\t\t// xcom base requirements\n\t\t\t\t\tfor (auto& triggerXcomBase : arcScript->getXcomBaseInRegionTriggers())\n\t\t\t\t\t{\n\t\t\t\t\t\tbool found = (xcomBaseRegions.find(triggerXcomBase.first) != xcomBaseRegions.end());\n\t\t\t\t\t\ttriggerHappy = (found == triggerXcomBase.second);\n\t\t\t\t\t\tif (!triggerHappy)\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (triggerHappy)\n\t\t\t\t{\n\t\t\t\t\t// xcom base requirements by country\n\t\t\t\t\tfor (auto& triggerXcomBase2 : arcScript->getXcomBaseInCountryTriggers())\n\t\t\t\t\t{\n\t\t\t\t\t\tbool found = (xcomBaseCountries.find(triggerXcomBase2.first) != xcomBaseCountries.end());\n\t\t\t\t\t\ttriggerHappy = (found == triggerXcomBase2.second);\n\t\t\t\t\t\tif (!triggerHappy)\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (triggerHappy)\n\t\t\t\t{\n\t\t\t\t\t// country with pact\n\t\t\t\t\tfor (auto& triggerPact : arcScript->getPactCountryTriggers())\n\t\t\t\t\t{\n\t\t\t\t\t\tbool found = (pactCountries.find(triggerPact.first) != pactCountries.end());\n\t\t\t\t\t\ttriggerHappy = (found == triggerPact.second);\n\t\t\t\t\t\tif (!triggerHappy)\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// level three condition check: does random chance favour this command's execution?\n\t\t\t\tif (triggerHappy && RNG::percent(arcScript->getExecutionOdds()))\n\t\t\t\t{\n\t\t\t\t\trelevantArcScripts.push_back(arcScript);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// start processing command array\n\t\tfor (auto* arcCommand : relevantArcScripts)\n\t\t{\n\t\t\t// to remember stuff we can still enable\n\t\t\tstd::vector<std::string> disabledSeqArcs;\n\t\t\tWeightedOptions disabledRngArcs;\n\n\t\t\tint arcsEnabled = 0;\n\t\t\t// level four condition check: check maxArcs (duplicates count, arcs enabled by other commands or in any other way count too!)\n\t\t\t{\n\t\t\t\tfor (auto& seqArc : arcCommand->getSequentialArcs())\n\t\t\t\t{\n\t\t\t\t\tif (save->isResearched(seqArc))\n\t\t\t\t\t\t++arcsEnabled;\n\t\t\t\t\telse\n\t\t\t\t\t\tdisabledSeqArcs.push_back(seqArc);\n\t\t\t\t}\n\t\t\t\tWeightedOptions tmp = arcCommand->getRandomArcs(); // copy for the iterator, because of getNames()\n\t\t\t\tdisabledRngArcs = tmp; // copy for us to modify\n\t\t\t\tfor (auto& rngArc : tmp.getNames())\n\t\t\t\t{\n\t\t\t\t\tif (save->isResearched(rngArc))\n\t\t\t\t\t{\n\t\t\t\t\t\t++arcsEnabled;\n\t\t\t\t\t\tdisabledRngArcs.set(rngArc, 0); // delete\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tBase* hq = save->getBases()->front();\n\t\t\tbool canAddOneMore = arcCommand->getMaxArcs() == -1 || arcCommand->getMaxArcs() > arcsEnabled;\n\t\t\tif (canAddOneMore && !disabledSeqArcs.empty())\n\t\t\t{\n\t\t\t\tauto* ruleResearchSeq = mod->getResearch(disabledSeqArcs.front(), true); // take first\n\t\t\t\tsave->addFinishedResearch(ruleResearchSeq, mod, hq, true);\n\t\t\t\t++arcsEnabled;\n\t\t\t\tif (ruleResearchSeq)\n\t\t\t\t{\n\t\t\t\t\tif (ruleResearchSeq->getLookup())\n\t\t\t\t\t{\n\t\t\t\t\t\tsave->addFinishedResearch(ruleResearchSeq->getLookup(), mod, hq, true);\n\t\t\t\t\t\tUfopaedia::openArticle(_game, ruleResearchSeq->getLookup()->getName());\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tUfopaedia::openArticle(_game, ruleResearchSeq->getName());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tcanAddOneMore = arcCommand->getMaxArcs() == -1 || arcCommand->getMaxArcs() > arcsEnabled;\n\t\t\tif (canAddOneMore && !disabledRngArcs.empty())\n\t\t\t{\n\t\t\t\tauto* ruleResearchRng = mod->getResearch(disabledRngArcs.choose(), true); // take random\n\t\t\t\tsave->addFinishedResearch(ruleResearchRng, mod, hq, true);\n\t\t\t\t++arcsEnabled; // for good measure :)\n\t\t\t\tif (ruleResearchRng)\n\t\t\t\t{\n\t\t\t\t\tif (ruleResearchRng->getLookup())\n\t\t\t\t\t{\n\t\t\t\t\t\tsave->addFinishedResearch(ruleResearchRng->getLookup(), mod, hq, true);\n\t\t\t\t\t\tUfopaedia::openArticle(_game, ruleResearchRng->getLookup()->getName());\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tUfopaedia::openArticle(_game, ruleResearchRng->getName());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// well, here it is, ladies and gents, the nuts and bolts behind the geoscape mission scheduling.\n\tconst std::vector<std::string>* scriptList = isNewMonth ? mod->getMissionScriptList() : mod->getAdhocScriptList();\n\n\t// first we need to build a list of \"valid\" commands\n\tfor (auto& missionScriptName : *scriptList)\n\t{\n\t\tRuleMissionScript *command = isNewMonth ? mod->getMissionScript(missionScriptName) : mod->getAdhocScript(missionScriptName);\n\n\t\t// level zero condition check: filter adhoc mission scripts by tags\n\t\tif (!isNewMonth && eventRules)\n\t\t{\n\t\t\tbool matchFound = false;\n\t\t\tfor (auto& atag : eventRules->getAdhocMissionScriptTags())\n\t\t\t{\n\t\t\t\tfor (auto& btag : command->getAdhocMissionScriptTags())\n\t\t\t\t{\n\t\t\t\t\tif (atag == btag) matchFound = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (matchFound) break;\n\t\t\t}\n\t\t\tif (!matchFound) continue;\n\t\t}\n\n\t\t\t// level one condition check: make sure we're within our time constraints\n\t\tif (command->getFirstMonth() <= month &&\n\t\t\t(command->getLastMonth() >= month || command->getLastMonth() == -1) &&\n\t\t\t// make sure we haven't hit our run limit, if we have one\n\t\t\t(command->getMaxRuns() == -1 ||\tcommand->getMaxRuns() > strategy.getMissionsRun(command->getVarName())) &&\n\t\t\t// and make sure we satisfy the difficulty restrictions\n\t\t\t(month < 1 || command->getMinScore() <= currentScore) &&\n\t\t\t(month < 1 || command->getMaxScore() >= currentScore) &&\n\t\t\t(month < 1 || command->getMinFunds() <= currentFunds) &&\n\t\t\t(month < 1 || command->getMaxFunds() >= currentFunds) &&\n\t\t\tcommand->getMinDifficulty() <= save->getDifficulty() &&\n\t\t\tcommand->getMaxDifficulty() >= save->getDifficulty())\n\t\t{\n\t\t\t// level two condition check: make sure we meet any research requirements, if any.\n\t\t\tbool triggerHappy = true;\n\t\t\tfor (auto& triggerResearch : command->getResearchTriggers())\n\t\t\t{\n\t\t\t\ttriggerHappy = (save->isResearched(triggerResearch.first) == triggerResearch.second);\n\t\t\t\tif (!triggerHappy)\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (triggerHappy)\n\t\t\t{\n\t\t\t\t// check counters\n\t\t\t\tif (command->getCounterMin() > 0)\n\t\t\t\t{\n\t\t\t\t\tif (!command->getMissionVarName().empty() && command->getCounterMin() > strategy.getMissionsRun(command->getMissionVarName()))\n\t\t\t\t\t{\n\t\t\t\t\t\ttriggerHappy = false;\n\t\t\t\t\t}\n\t\t\t\t\tif (!command->getMissionMarkerName().empty() && command->getCounterMin() > save->getLastId(command->getMissionMarkerName()))\n\t\t\t\t\t{\n\t\t\t\t\t\ttriggerHappy = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (triggerHappy && command->getCounterMax() != -1)\n\t\t\t\t{\n\t\t\t\t\tif (!command->getMissionVarName().empty() && command->getCounterMax() < strategy.getMissionsRun(command->getMissionVarName()))\n\t\t\t\t\t{\n\t\t\t\t\t\ttriggerHappy = false;\n\t\t\t\t\t}\n\t\t\t\t\tif (!command->getMissionMarkerName().empty() && command->getCounterMax() < save->getLastId(command->getMissionMarkerName()))\n\t\t\t\t\t{\n\t\t\t\t\t\ttriggerHappy = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (triggerHappy)\n\t\t\t{\n\t\t\t\t// item requirements\n\t\t\t\tfor (auto& triggerItem : command->getItemTriggers())\n\t\t\t\t{\n\t\t\t\t\ttriggerHappy = (save->isItemObtained(triggerItem.first, mod) == triggerItem.second);\n\t\t\t\t\tif (!triggerHappy)\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (triggerHappy)\n\t\t\t{\n\t\t\t\t// facility requirements\n\t\t\t\tfor (auto& triggerFacility : command->getFacilityTriggers())\n\t\t\t\t{\n\t\t\t\t\ttriggerHappy = (save->isFacilityBuilt(triggerFacility.first) == triggerFacility.second);\n\t\t\t\t\tif (!triggerHappy)\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (triggerHappy)\n\t\t\t{\n\t\t\t\t// soldier type requirements\n\t\t\t\tfor (auto& triggerSoldierType : command->getSoldierTypeTriggers())\n\t\t\t\t{\n\t\t\t\t\ttriggerHappy = (save->isSoldierTypeHired(triggerSoldierType.first) == triggerSoldierType.second);\n\t\t\t\t\tif (!triggerHappy)\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (triggerHappy)\n\t\t\t{\n\t\t\t\t// xcom base requirements\n\t\t\t\tfor (auto& triggerXcomBase : command->getXcomBaseInRegionTriggers())\n\t\t\t\t{\n\t\t\t\t\tbool found = (xcomBaseRegions.find(triggerXcomBase.first) != xcomBaseRegions.end());\n\t\t\t\t\ttriggerHappy = (found == triggerXcomBase.second);\n\t\t\t\t\tif (!triggerHappy)\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (triggerHappy)\n\t\t\t{\n\t\t\t\t// xcom base requirements by country\n\t\t\t\tfor (auto& triggerXcomBase2 : command->getXcomBaseInCountryTriggers())\n\t\t\t\t{\n\t\t\t\t\tbool found = (xcomBaseCountries.find(triggerXcomBase2.first) != xcomBaseCountries.end());\n\t\t\t\t\ttriggerHappy = (found == triggerXcomBase2.second);\n\t\t\t\t\tif (!triggerHappy)\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (triggerHappy)\n\t\t\t{\n\t\t\t\t// country with pact\n\t\t\t\tfor (auto& triggerPact : command->getPactCountryTriggers())\n\t\t\t\t{\n\t\t\t\t\tbool found = (pactCountries.find(triggerPact.first) != pactCountries.end());\n\t\t\t\t\ttriggerHappy = (found == triggerPact.second);\n\t\t\t\t\tif (!triggerHappy)\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// levels one and two passed: insert this command into the array.\n\t\t\tif (triggerHappy)\n\t\t\t{\n\t\t\t\tavailableMissions.push_back(command);\n\t\t\t}\n\t\t}\n\t}\n\n\t// start processing command array.\n\tfor (auto* command : availableMissions)\n\t{\n\t\tbool process = true;\n\t\tbool success = false;\n\t\t// level three condition check: make sure our conditionals are met, if any. this list is dynamic, and must be checked here.\n\t\tfor (int condition : command->getConditionals())\n\t\t{\n\t\t\tif (!process)\n\t\t\t{\n\t\t\t\tbreak; // loop finished\n\t\t\t}\n\t\t\tauto found = conditions.find(std::abs(condition));\n\t\t\t// just an FYI: if you add a 0 to your conditionals, this flag will never resolve to true, and your command will never run.\n\t\t\tprocess = (found == conditions.end() || (found->second == true && condition > 0) || (found->second == false && condition < 0));\n\t\t}\n\t\tif (command->getLabel() > 0 && conditions.find(command->getLabel()) != conditions.end())\n\t\t{\n\t\t\tstd::ostringstream ss;\n\t\t\tss << \"Mission generator encountered an error: multiple commands: \" << command->getType() << \" and \";\n\t\t\tfor (auto* command2 : availableMissions)\n\t\t\t{\n\t\t\t\tif (command->getLabel() == command2->getLabel() && command2 != command)\n\t\t\t\t{\n\t\t\t\t\tss << command2->getType() << \", \";\n\t\t\t\t}\n\t\t\t}\n\t\t\tss  << \"are sharing the same label: \" << command->getLabel();\n\t\t\tthrow Exception(ss.str());\n\t\t}\n\t\t// level four condition check: does random chance favour this command's execution?\n\t\tif (process)\n\t\t{\n\t\t\tbool rngret = RNG::percent(command->getExecutionOdds());\n\t\t\tif (Options::verboseLogging && Options::oxceGeoscapeDebugLogMaxEntries > 0)\n\t\t\t{\n\t\t\t\tstd::ostringstream ss;\n\t\t\t\tss << \"month: \" << month;\n\t\t\t\tss << \" script: \" << command->getType();\n\t\t\t\tss << \" odds: \" << command->getExecutionOdds();\n\t\t\t\tss << \" rng: \" << rngret;\n\t\t\t\tsave->getGeoscapeDebugLog().push_back(ss.str());\n\t\t\t}\n\t\t\tif (rngret)\n\t\t\t{\n\t\t\t\t// good news, little command pointer! you're FDA approved! off to the main processing facility with you!\n\t\t\t\tsuccess = processCommand(command);\n\t\t\t}\n\n\t\t}\n\t\tif (command->getLabel() > 0)\n\t\t{\n\t\t\t// tsk, tsk. you really should be careful with these unique labels, they're supposed to be unique.\n\t\t\tif (conditions.find(command->getLabel()) != conditions.end())\n\t\t\t{\n\t\t\t\tthrow Exception(\"Error in mission scripts: \" + command->getType() + \". Two or more commands sharing the same label. That's bad, Mmmkay?\");\n\t\t\t}\n\t\t\t// keep track of what happened to this command, so others may reference it.\n\t\t\tconditions[command->getLabel()] = success;\n\t\t}\n\t}\n\n\t// after the mission scripts, it's time for the event scripts\n\tif (isNewMonth)\n\t{\n\t\tstd::vector<RuleEventScript *> relevantEventScripts;\n\n\t\t// first we need to build a list of \"valid\" commands\n\t\tfor (auto& scriptName : *mod->getEventScriptList())\n\t\t{\n\t\t\tRuleEventScript *eventScript = mod->getEventScript(scriptName);\n\n\t\t\t// level one condition check: make sure we're within our time constraints\n\t\t\tif (eventScript->getFirstMonth() <= month &&\n\t\t\t\t(eventScript->getLastMonth() >= month || eventScript->getLastMonth() == -1) &&\n\t\t\t\t// and make sure we satisfy the difficulty restrictions\n\t\t\t\t(month < 1 || eventScript->getMinScore() <= currentScore) &&\n\t\t\t\t(month < 1 || eventScript->getMaxScore() >= currentScore) &&\n\t\t\t\t(month < 1 || eventScript->getMinFunds() <= currentFunds) &&\n\t\t\t\t(month < 1 || eventScript->getMaxFunds() >= currentFunds) &&\n\t\t\t\teventScript->getMinDifficulty() <= save->getDifficulty() &&\n\t\t\t\teventScript->getMaxDifficulty() >= save->getDifficulty())\n\t\t\t{\n\t\t\t\t// level two condition check: make sure we meet any research requirements, if any.\n\t\t\t\tbool triggerHappy = true;\n\t\t\t\tfor (auto& trigger : eventScript->getResearchTriggers())\n\t\t\t\t{\n\t\t\t\t\ttriggerHappy = (save->isResearched(trigger.first) == trigger.second);\n\t\t\t\t\tif (!triggerHappy)\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (triggerHappy)\n\t\t\t\t{\n\t\t\t\t\t// check counters\n\t\t\t\t\tif (eventScript->getCounterMin() > 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (!eventScript->getMissionVarName().empty() && eventScript->getCounterMin() > strategy.getMissionsRun(eventScript->getMissionVarName()))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttriggerHappy = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!eventScript->getMissionMarkerName().empty() && eventScript->getCounterMin() > save->getLastId(eventScript->getMissionMarkerName()))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttriggerHappy = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (triggerHappy && eventScript->getCounterMax() != -1)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (!eventScript->getMissionVarName().empty() && eventScript->getCounterMax() < strategy.getMissionsRun(eventScript->getMissionVarName()))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttriggerHappy = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!eventScript->getMissionMarkerName().empty() && eventScript->getCounterMax() < save->getLastId(eventScript->getMissionMarkerName()))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttriggerHappy = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (triggerHappy)\n\t\t\t\t{\n\t\t\t\t\t// item requirements\n\t\t\t\t\tfor (auto& triggerItem : eventScript->getItemTriggers())\n\t\t\t\t\t{\n\t\t\t\t\t\ttriggerHappy = (save->isItemObtained(triggerItem.first, mod) == triggerItem.second);\n\t\t\t\t\t\tif (!triggerHappy)\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (triggerHappy)\n\t\t\t\t{\n\t\t\t\t\t// facility requirements\n\t\t\t\t\tfor (auto& triggerFacility : eventScript->getFacilityTriggers())\n\t\t\t\t\t{\n\t\t\t\t\t\ttriggerHappy = (save->isFacilityBuilt(triggerFacility.first) == triggerFacility.second);\n\t\t\t\t\t\tif (!triggerHappy)\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (triggerHappy)\n\t\t\t\t{\n\t\t\t\t\t// soldier type requirements\n\t\t\t\t\tfor (auto& triggerSoldierType : eventScript->getSoldierTypeTriggers())\n\t\t\t\t\t{\n\t\t\t\t\t\ttriggerHappy = (save->isSoldierTypeHired(triggerSoldierType.first) == triggerSoldierType.second);\n\t\t\t\t\t\tif (!triggerHappy)\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (triggerHappy)\n\t\t\t\t{\n\t\t\t\t\t// xcom base requirements\n\t\t\t\t\tfor (auto& triggerXcomBase : eventScript->getXcomBaseInRegionTriggers())\n\t\t\t\t\t{\n\t\t\t\t\t\tbool found = (xcomBaseRegions.find(triggerXcomBase.first) != xcomBaseRegions.end());\n\t\t\t\t\t\ttriggerHappy = (found == triggerXcomBase.second);\n\t\t\t\t\t\tif (!triggerHappy)\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (triggerHappy)\n\t\t\t\t{\n\t\t\t\t\t// xcom base requirements by country\n\t\t\t\t\tfor (auto& triggerXcomBase2 : eventScript->getXcomBaseInCountryTriggers())\n\t\t\t\t\t{\n\t\t\t\t\t\tbool found = (xcomBaseCountries.find(triggerXcomBase2.first) != xcomBaseCountries.end());\n\t\t\t\t\t\ttriggerHappy = (found == triggerXcomBase2.second);\n\t\t\t\t\t\tif (!triggerHappy)\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (triggerHappy)\n\t\t\t\t{\n\t\t\t\t\t// country with pact\n\t\t\t\t\tfor (auto& triggerPact : eventScript->getPactCountryTriggers())\n\t\t\t\t\t{\n\t\t\t\t\t\tbool found = (pactCountries.find(triggerPact.first) != pactCountries.end());\n\t\t\t\t\t\ttriggerHappy = (found == triggerPact.second);\n\t\t\t\t\t\tif (!triggerHappy)\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// level three condition check: does random chance favour this command's execution?\n\t\t\t\tif (triggerHappy && RNG::percent(eventScript->getExecutionOdds()))\n\t\t\t\t{\n\t\t\t\t\trelevantEventScripts.push_back(eventScript);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// now, let's process the relevant event scripts\n\t\tfor (auto& eventCommand : relevantEventScripts)\n\t\t{\n\t\t\tstd::vector<const RuleEvent*> toBeGenerated;\n\n\t\t\t// 1. sequentially generated one-time events (cannot repeat)\n\t\t\t{\n\t\t\t\tstd::vector<std::string> possibleSeqEvents;\n\t\t\t\tfor (auto& seqEvent : eventCommand->getOneTimeSequentialEvents())\n\t\t\t\t{\n\t\t\t\t\tif (!save->wasEventGenerated(seqEvent))\n\t\t\t\t\t\tpossibleSeqEvents.push_back(seqEvent); // insert\n\t\t\t\t}\n\t\t\t\tif (!possibleSeqEvents.empty())\n\t\t\t\t{\n\t\t\t\t\tauto* eventRules = mod->getEvent(possibleSeqEvents.front(), true); // take first\n\t\t\t\t\ttoBeGenerated.push_back(eventRules);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// 2. randomly generated one-time events (cannot repeat)\n\t\t\t{\n\t\t\t\tWeightedOptions possibleRngEvents;\n\t\t\t\tWeightedOptions tmp = eventCommand->getOneTimeRandomEvents(); // copy for the iterator, because of getNames()\n\t\t\t\tpossibleRngEvents = tmp; // copy for us to modify\n\t\t\t\tfor (const auto& rngEvent : tmp.getNames())\n\t\t\t\t{\n\t\t\t\t\tif (save->wasEventGenerated(rngEvent))\n\t\t\t\t\t\tpossibleRngEvents.set(rngEvent, 0); // delete\n\t\t\t\t}\n\t\t\t\tif (!possibleRngEvents.empty())\n\t\t\t\t{\n\t\t\t\t\tauto* eventRules = mod->getEvent(possibleRngEvents.choose(), true); // take random\n\t\t\t\t\ttoBeGenerated.push_back(eventRules);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// 3. randomly generated repeatable events\n\t\t\t{\n\t\t\t\tauto* eventRules = mod->getEvent(eventCommand->generate(save->getMonthsPassed()), false);\n\t\t\t\tif (eventRules)\n\t\t\t\t{\n\t\t\t\t\ttoBeGenerated.push_back(eventRules);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// 4. generate\n\t\t\tfor (auto* eventRules : toBeGenerated)\n\t\t\t{\n\t\t\t\tsave->spawnEvent(eventRules);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Alien base upgrades happen only AFTER the first game month\n\tif (isNewMonth && month > 0)\n\t{\n\t\tfor (auto* alienBase : *save->getAlienBases())\n\t\t{\n\t\t\tint baseAgeInMonths = month - alienBase->getStartMonth();\n\t\t\tconst std::string upgradeId = alienBase->getDeployment()->generateAlienBaseUpgrade(baseAgeInMonths);\n\t\t\tAlienDeployment* upgrade = mod->getDeployment(upgradeId, false);\n\t\t\tif (upgrade && upgrade != alienBase->getDeployment())\n\t\t\t{\n\t\t\t\tstd::ostringstream ss;\n\t\t\t\tss << \"month: \" << month;\n\t\t\t\tss << \" baseId: \" << alienBase->getId();\n\t\t\t\tss << \" baseType: \" << alienBase->getType();\n\t\t\t\tif (alienBase->getDeployment()->resetAlienBaseAgeAfterUpgrade() || upgrade->resetAlienBaseAge())\n\t\t\t\t{\n\t\t\t\t\t// reset base age to zero\n\t\t\t\t\talienBase->setStartMonth(month);\n\t\t\t\t\tss << \"; base age was reset;\";\n\t\t\t\t}\n\t\t\t\tss << \" old deployment: \" << alienBase->getDeployment()->getType();\n\t\t\t\talienBase->setDeployment(upgrade);\n\t\t\t\tss << \" new deployment: \" << alienBase->getDeployment()->getType();\n\t\t\t\tauto* upgradeRace = mod->getAlienRace(upgrade->getUpgradeRace(), false);\n\t\t\t\tif (upgradeRace)\n\t\t\t\t{\n\t\t\t\t\tss << \" old race: \" << alienBase->getAlienRace();\n\t\t\t\t\talienBase->setAlienRace(upgradeRace->getId());\n\t\t\t\t\tss << \" new race: \" << alienBase->getAlienRace();\n\t\t\t\t}\n\t\t\t\tif (Options::oxceGeoscapeDebugLogMaxEntries > 0)\n\t\t\t\t{\n\t\t\t\t\tsave->getGeoscapeDebugLog().push_back(ss.str());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Alien race evolution\n\tif (isNewMonth && month > 0)\n\t{\n\t\tfor (auto* alienBase : *save->getAlienBases())\n\t\t{\n\t\t\tif (!alienBase->getDeployment()->getAlienRaceEvolution().empty())\n\t\t\t{\n\t\t\t\tstd::ostringstream ss;\n\t\t\t\tss << \"month: \" << month;\n\t\t\t\tss << \" baseId: \" << alienBase->getId();\n\t\t\t\tss << \" baseType: \" << alienBase->getType();\n\t\t\t\tss << \" deployment: \" << alienBase->getDeployment()->getType();\n\t\t\t\tss << \" old race: \" << alienBase->getAlienRace();\n\t\t\t\tint tries = 0;\n\t\t\t\twhile (attemptAlienRaceEvolution(month, alienBase))\n\t\t\t\t{\n\t\t\t\t\tss << \" new race: \" << alienBase->getAlienRace();\n\t\t\t\t\tif (++tries >= 100)\n\t\t\t\t\t{\n\t\t\t\t\t\tthrow Exception(\"Alien race evolution: endless loop detected. It's not my fault. Crashing now!\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tss << \" end.\";\n\t\t\t\tif (Options::oxceGeoscapeDebugLogMaxEntries > 0)\n\t\t\t\t{\n\t\t\t\t\tsave->getGeoscapeDebugLog().push_back(ss.str());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Try to perform alien race evolution.\n * @return whether the attempt was successful or not.\n */\nbool GeoscapeState::attemptAlienRaceEvolution(int month, AlienBase* ab) const\n{\n\tfor (const auto& tuple : ab->getDeployment()->getAlienRaceEvolution())\n\t{\n\t\tif (std::get<0>(tuple) <= month && std::get<1>(tuple) == ab->getAlienRace())\n\t\t{\n\t\t\tauto* newRace = _game->getMod()->getAlienRace(std::get<2>(tuple), false);\n\t\t\tif (newRace)\n\t\t\t{\n\t\t\t\tab->setAlienRace(newRace->getId());\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Processes a directive to start up a mission, if possible.\n * @param command the directive from which to read information.\n * @return whether the command successfully produced a new mission.\n */\nbool GeoscapeState::processCommand(RuleMissionScript *command)\n{\n\tSavedGame *save = _game->getSavedGame();\n\tAlienStrategy &strategy = save->getAlienStrategy();\n\tMod *mod = _game->getMod();\n\tint month = _game->getSavedGame()->getMonthsPassed();\n\tstd::string targetRegion;\n\tconst RuleAlienMission *missionRules;\n\tstd::string missionType;\n\tstd::string missionRace;\n\tint targetZoneNumber = -1;\n\tint targetAreaNumber = -1;\n\n\t// terror mission type deal? this will require special handling.\n\tif (command->getSiteType())\n\t{\n\t\t// we know for a fact that this command has mission weights defined, otherwise this flag could not be set.\n\t\tmissionType = command->generate(month, GEN_MISSION);\n\t\tstd::vector<std::string> missions = command->getMissionTypes(month);\n\t\tint maxMissions = missions.size();\n\t\tbool targetBase = RNG::percent(command->getTargetBaseOdds());\n\t\tint currPos = 0;\n\t\tfor (; currPos != maxMissions; ++currPos)\n\t\t{\n\t\t\tif (missions[currPos] == missionType)\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// let's build a list of regions with spawn zones to pick from\n\t\tstd::vector<std::pair<std::string, int> > validAreas;\n\n\t\t// this is actually a bit of a cheat, we ARE using the mission weights as defined, but we'll try them all if the one we pick first isn't valid.\n\t\tfor (int h = 0; h != maxMissions; ++h)\n\t\t{\n\t\t\t// we'll use the regions listed in the command, if any, otherwise check all the regions in the ruleset looking for matches\n\t\t\tstd::vector<std::string> regions = (command->hasRegionWeights()) ? command->getRegions(month) : mod->getRegionsList();\n\t\t\tmissionRules = mod->getAlienMission(missionType, true);\n\t\t\ttargetZoneNumber = missionRules->getSpawnZone();\n\n\t\t\tif (targetBase)\n\t\t\t{\n\t\t\t\tstd::vector<std::string> regionsToKeep;\n\t\t\t\t//if we're targetting a base, we ignore regions that don't contain bases, simple.\n\t\t\t\tfor (auto* xbase : *save->getBases())\n\t\t\t\t{\n\t\t\t\t\tregionsToKeep.push_back(save->locateRegion(xbase->getLongitude(), xbase->getLatitude())->getRules()->getType());\n\t\t\t\t}\n\t\t\t\tfor (auto regionNameIt = regions.begin(); regionNameIt != regions.end();)\n\t\t\t\t{\n\t\t\t\t\tif (std::find(regionsToKeep.begin(), regionsToKeep.end(), (*regionNameIt)) == regionsToKeep.end())\n\t\t\t\t\t{\n\t\t\t\t\t\tregionNameIt = regions.erase(regionNameIt);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t++regionNameIt;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// -----------------------------------------------------------\n\t\t\t// Summary of mission site spawning algorithms (objective: 3)\n\t\t\t// -----------------------------------------------------------\n\n\t\t\t// Type 1:\n\t\t\t// - no UFOs involved\n\t\t\t// - only 1 wave\n\t\t\t// - the wave specifies the alien deployment directly (e.g. `ufo: STR_ARTIFACT_SITE_P1 # spawn this site directly`)\n\t\t\t// - example (1): STR_ALIEN_ARTIFACT (TFTD)\n\t\t\t// Support for non-point areas: yes, without any additional ruleset changes required\n\t\t\tconst MissionWave& wave = missionRules->getWave(0);\n\t\t\tbool spawnMissionSiteDirectly = (mod->getDeployment(wave.ufoType) && !mod->getUfo(wave.ufoType) && !mod->getDeployment(wave.ufoType)->getMarkerName().empty());\n\n\t\t\t// Type 2:\n\t\t\t// - no UFOs involved\n\t\t\t// - only 1 wave\n\t\t\t// - the wave does NOT specify the alien deployment directly (e.g. `ufo: dummy #don't spawn a ufo, we only want the site`)\n\t\t\t//   -> option A: alien deployment is chosen randomly = from the area's texture definition\n\t\t\t//   -> option B: alien deployment is specified by the mission's `siteType` (overrides option A if both are defined)\n\t\t\t// - example (2A): STR_ALIEN_SHIP_ATTACK (TFTD)\n\t\t\t// - example (2B): none in vanilla, only mods\n\t\t\t// Support for non-point areas: yes, without any additional ruleset changes required\n\t\t\t// bool spawnMissionSiteByTexture = area.texture < 0\n\t\t\t// bool spawnMissionSiteBySiteType = !missionRules->getSiteType().empty();\n\n\t\t\t// Type 3:\n\t\t\t// - with UFOs waves\n\t\t\t// - only 1 wave with `objective: true`\n\t\t\t// - the wave does NOT specify the alien deployment (because it already specifies the UFO type)\n\t\t\t//   -> option A: alien deployment is chosen randomly = from the area's texture definition\n\t\t\t//   -> option B: alien deployment is specified by the mission's `siteType` (overrides option A if both are defined)\n\t\t\t// - example (3A): STR_ALIEN_SURFACE_ATTACK (TFTD)\n\t\t\t// - example (3B): none in vanilla, only mods\n\t\t\t// Support for non-point areas: yes, but it is recommended to use one more wave attribute: `objectiveOnTheLandingSite: true`\n\t\t\t//   -> false: UFO always lands in the top-left corner of the area; site spawns randomly inside the area\n\t\t\t//   ->  true: UFO lands randomly inside the area; site spawns exactly on the UFO landing site\n\t\t\t// bool spawnMissionSiteByTexture = area.texture < 0\n\t\t\tbool spawnMissionSiteBySiteType = !missionRules->getSiteType().empty();\n\n\t\t\t// -----------------------------------------------\n\t\t\t// End of the summary\n\t\t\t// -----------------------------------------------\n\n\t\t\tfor (auto regionNameIt = regions.begin(); regionNameIt != regions.end();)\n\t\t\t{\n\t\t\t\t// we don't want the same mission running in any given region twice simultaneously, so prune the list as needed.\n\t\t\t\tbool processThisRegion = true;\n\t\t\t\tfor (auto* am : save->getAlienMissions())\n\t\t\t\t{\n\t\t\t\t\tif (am->getRules().getType() == missionRules->getType() && am->getRegion() == (*regionNameIt))\n\t\t\t\t\t{\n\t\t\t\t\t\tprocessThisRegion = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!processThisRegion)\n\t\t\t\t{\n\t\t\t\t\tregionNameIt = regions.erase(regionNameIt);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\t// ok, we found a region that doesn't have our mission in it, let's see if it has an appropriate landing zone.\n\t\t\t\t// if it does, let's add it to our list of valid areas, taking note of which mission area(s) matched.\n\t\t\t\tRuleRegion *region = mod->getRegion((*regionNameIt), true);\n\t\t\t\tif ((int)(region->getMissionZones().size()) > targetZoneNumber)\n\t\t\t\t{\n\t\t\t\t\tif (targetZoneNumber < 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tthrow Exception(\"Cannot spawn mission site, invalid spawn zone! Command: \" + command->getType() + \"; mission: \" + missionRules->getType());\n\t\t\t\t\t}\n\t\t\t\t\tstd::vector<MissionArea> areas = region->getMissionZones()[targetZoneNumber].areas;\n\t\t\t\t\tint counter = 0;\n\t\t\t\t\tfor (const auto& area : areas)\n\t\t\t\t\t{\n\t\t\t\t\t\t// validMissionLocation checks to make sure this city/whatever hasn't been used by the last n missions using this varName\n\t\t\t\t\t\t// this prevents the same location getting hit more than once every n missions.\n\t\t\t\t\t\tif (area.isPoint() && strategy.validMissionLocation(command->getVarName(), region->getType(), counter))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tvalidAreas.push_back(std::make_pair(region->getType(), counter));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (!area.isPoint() && (area.texture < 0 || spawnMissionSiteBySiteType || spawnMissionSiteDirectly))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tvalidAreas.push_back(std::make_pair(region->getType(), counter));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcounter++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t++regionNameIt;\n\t\t\t}\n\n\t\t\t// oh bother, we couldn't find anything valid, this mission won't run this month.\n\t\t\tif (validAreas.empty())\n\t\t\t{\n\t\t\t\tif (maxMissions > 1 && ++currPos == maxMissions)\n\t\t\t\t{\n\t\t\t\t\tcurrPos = 0;\n\t\t\t\t}\n\t\t\t\tmissionType = missions[currPos];\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (validAreas.empty())\n\t\t{\n\t\t\t// now we're in real trouble, we've managed to make it out of the loop and we still don't have any valid choices\n\t\t\t// this command cannot run this month, we have failed, forgive us senpai.\n\t\t\treturn false;\n\t\t}\n\n\t\t// everything went according to plan: we can now pick a city/whatever to attack.\n\t\twhile (targetAreaNumber == -1)\n\t\t{\n\t\t\tif (command->hasRegionWeights())\n\t\t\t{\n\t\t\t\t// if we have a weighted region list, we know we have at least one valid choice for this mission\n\t\t\t\ttargetRegion = command->generate(month, GEN_REGION);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// if we don't have a weighted list, we'll select a region at random from the ruleset,\n\t\t\t\t// validate that it's in our list, and pick one of its cities at random\n\t\t\t\t// this will give us an even distribution between regions regardless of the number of cities.\n\t\t\t\ttargetRegion = mod->getRegionsList().at(RNG::generate(0, mod->getRegionsList().size() - 1));\n\t\t\t}\n\n\t\t\t// we need to know the range of the region within our vector, in order to randomly select a city from it\n\t\t\tint min = -1;\n\t\t\tint max = -1;\n\t\t\tint curr = 0;\n\t\t\tfor (const auto& pair : validAreas)\n\t\t\t{\n\t\t\t\tif (pair.first == targetRegion)\n\t\t\t\t{\n\t\t\t\t\tif (min == -1)\n\t\t\t\t\t{\n\t\t\t\t\t\tmin = curr;\n\t\t\t\t\t}\n\t\t\t\t\tmax = curr;\n\t\t\t\t}\n\t\t\t\telse if (min > -1)\n\t\t\t\t{\n\t\t\t\t\t// if we've stopped detecting matches, we're done looking.\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t++curr;\n\t\t\t}\n\t\t\tif (min != -1)\n\t\t\t{\n\t\t\t\t// we have our random range, we can make a selection, and we're done.\n\t\t\t\ttargetAreaNumber = validAreas[RNG::generate(min, max)].second;\n\t\t\t}\n\t\t}\n\t\t// now add that city to the list of sites we've hit, store the array, etc.\n\t\tstrategy.addMissionLocation(command->getVarName(), targetRegion, targetAreaNumber, command->getRepeatAvoidance());\n\t}\n\telse if (RNG::percent(command->getTargetBaseOdds()))\n\t{\n\t\t// build a list of the mission types we're dealing with, if any\n\t\tstd::vector<std::string> types = command->getMissionTypes(month);\n\t\t// now build a list of regions with bases in.\n\t\tstd::vector<std::string> regionsMaster;\n\t\tfor (auto* xbase : *save->getBases())\n\t\t{\n\t\t\tregionsMaster.push_back(save->locateRegion(*xbase)->getRules()->getType());\n\t\t}\n\t\t// no defined mission types? then we'll prune the region list to ensure we only have a region that can generate a mission.\n\t\tif (types.empty())\n\t\t{\n\t\t\tfor (auto regionNameIt = regionsMaster.begin(); regionNameIt != regionsMaster.end();)\n\t\t\t{\n\t\t\t\tif (!strategy.validMissionRegion((*regionNameIt)))\n\t\t\t\t{\n\t\t\t\t\tregionNameIt = regionsMaster.erase(regionNameIt);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\t++regionNameIt;\n\t\t\t}\n\t\t\t// no valid missions in any base regions? oh dear, i guess we failed.\n\t\t\tif (regionsMaster.empty())\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t// pick a random region from our list\n\t\t\ttargetRegion = regionsMaster[RNG::generate(0, regionsMaster.size()-1)];\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// we don't care about regional mission distributions, we're targetting a base with whatever mission we pick, so let's pick now\n\t\t\t// we'll iterate the mission list, starting at a random point, and wrapping around to the beginning\n\t\t\tint max = types.size();\n\t\t\tint entry = RNG::generate(0,  max - 1);\n\t\t\tstd::vector<std::string> regions;\n\n\t\t\tfor (int i = 0; i != max; ++i)\n\t\t\t{\n\t\t\t\tregions = regionsMaster;\n\t\t\t\tfor (auto* am : save->getAlienMissions())\n\t\t\t\t{\n\t\t\t\t\t// if the mission types match\n\t\t\t\t\tif (types[entry] == am->getRules().getType())\n\t\t\t\t\t{\n\t\t\t\t\t\tfor (auto regionNameIt = regions.begin(); regionNameIt != regions.end();)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// and the regions match\n\t\t\t\t\t\t\tif ((*regionNameIt) == am->getRegion())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// prune the entry from the list\n\t\t\t\t\t\t\t\tregionNameIt = regions.erase(regionNameIt);\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t++regionNameIt;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// we have a valid list of regions containing bases, pick one.\n\t\t\t\tif (!regions.empty())\n\t\t\t\t{\n\t\t\t\t\tmissionType = types[entry];\n\t\t\t\t\ttargetRegion = regions[RNG::generate(0, regions.size()-1)];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t// otherwise, try the next mission in the list.\n\t\t\t\tif (max > 1 && ++entry == max)\n\t\t\t\t{\n\t\t\t\t\tentry = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t// now the easy stuff\n\telse if (!command->hasRegionWeights())\n\t{\n\t\t// no regionWeights means we pick from the table\n\t\ttargetRegion = strategy.chooseRandomRegion(mod);\n\t}\n\telse\n\t{\n\t\t// otherwise, let the command dictate the region.\n\t\ttargetRegion = command->generate(month, GEN_REGION);\n\t}\n\n\tif (targetRegion.empty())\n\t{\n\t\t// something went horribly wrong, we should have had at LEAST a region by now.\n\t\treturn false;\n\t}\n\n\t// we're bound to end up with typos, so let's throw an exception instead of simply returning false\n\t// that way, the modder can fix their mistake\n\tif (mod->getRegion(targetRegion) == 0)\n\t{\n\t\tthrow Exception(\"Error processing mission script named: \" + command->getType() + \", region named: \" + targetRegion + \" is not defined\");\n\t}\n\n\tif (missionType.empty()) // ie: not a terror mission, not targetting a base, or otherwise not already chosen\n\t{\n\t\tif (!command->hasMissionWeights())\n\t\t{\n\t\t\t// no weights means let the strategy pick\n\t\t\tmissionType = strategy.chooseRandomMission(targetRegion);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// otherwise the command gives us the weights.\n\t\t\tmissionType = command->generate(month, GEN_MISSION);\n\t\t}\n\t}\n\n\tif (missionType.empty())\n\t{\n\t\t// something went horribly wrong, we didn't manage to choose a mission type\n\t\treturn false;\n\t}\n\n\tmissionRules = mod->getAlienMission(missionType);\n\n\t// we're bound to end up with typos, so let's throw an exception instead of simply returning false\n\t// that way, the modder can fix their mistake\n\tif (missionRules == 0)\n\t{\n\t\tthrow Exception(\"Error processing mission script named: \" + command->getType() + \", mission type: \" + missionType + \" is not defined\");\n\t}\n\n\t// do i really need to comment this? shouldn't it be obvious what's happening here?\n\tif (!command->hasRaceWeights())\n\t{\n\t\tmissionRace = missionRules->generateRace(month);\n\t}\n\telse\n\t{\n\t\tmissionRace = command->generate(month, GEN_RACE);\n\t}\n\n\tif (missionRace.empty())\n\t{\n\t\tthrow Exception(\"Error processing mission script named: \" + command->getType() + \", mission type: \" + missionType + \" has no available races\");\n\t}\n\n\t// we're bound to end up with typos, so let's throw an exception instead of simply returning false\n\t// that way, the modder can fix their mistake\n\tif (mod->getAlienRace(missionRace) == 0)\n\t{\n\t\tthrow Exception(\"Error processing mission script named: \" + command->getType() + \", race: \" + missionRace + \" is not defined\");\n\t}\n\n\t// ok, we've derived all the variables we need to start up our mission, let's do magic to turn those values into a mission\n\tAlienMission *mission = new AlienMission(*missionRules);\n\tmission->setRace(missionRace);\n\tmission->setId(_game->getSavedGame()->getId(\"ALIEN_MISSIONS\"));\n\tmission->setRegion(targetRegion, *_game->getMod());\n\tmission->setMissionSiteZoneArea(targetAreaNumber);\n\tstrategy.addMissionRun(command->getVarName());\n\tmission->start(*_game, *_globe, command->getDelay());\n\t_game->getSavedGame()->getAlienMissions().push_back(mission);\n\t// if this flag is set, we want to delete it from the table so it won't show up again until the schedule resets.\n\tif (command->getUseTable())\n\t{\n\t\tstrategy.removeMission(targetRegion, missionType);\n\t}\n\n\tif (Options::oxceGeoscapeDebugLogMaxEntries > 0)\n\t{\n\t\tstd::ostringstream ss;\n\t\tss << \"month: \" << month;\n\t\tss << \" script: \" << command->getType();\n\t\tss << \" id: \" << mission->getId();\n\t\tss << \" type: \" << mission->getRules().getType();\n\t\tss << \" race: \" << mission->getRace();\n\t\tss << \" region: \" << targetRegion; /* << \" / \" << mission->getRegion() */\n\t\tss << \" targetZone: \" << targetZoneNumber;\n\t\tss << \" targetArea: \" << targetAreaNumber;\n\t\tsave->getGeoscapeDebugLog().push_back(ss.str());\n\t}\n\n\t// we did it, we can go home now.\n\treturn true;\n\n}\n\n/**\n * Handler for clicking on a timer button.\n * @param action pointer to the mouse action.\n */\nvoid GeoscapeState::btnTimerClick(Action *action)\n{\n\tSDL_Event ev;\n\tev.type = SDL_MOUSEBUTTONDOWN;\n\tev.button.button = SDL_BUTTON_LEFT;\n\tAction a = Action(&ev, 0.0, 0.0, 0, 0);\n\taction->getSender()->mousePress(&a, this);\n}\n\n/**\n * Updates the scale.\n * @param dX delta of X;\n * @param dY delta of Y;\n */\nvoid GeoscapeState::resize(int &dX, int &dY)\n{\n\tif (_game->getSavedGame()->getSavedBattle())\n\t\treturn;\n\tdX = Options::baseXResolution;\n\tdY = Options::baseYResolution;\n\tint divisor = 1;\n\tdouble pixelRatioY = 1.0;\n\n\tif (Options::nonSquarePixelRatio)\n\t{\n\t\tpixelRatioY = 1.2;\n\t}\n\tswitch (Options::geoscapeScale)\n\t{\n\tcase SCALE_SCREEN_DIV_10:\n\t\tdivisor = 10;\n\t\tbreak;\n\tcase SCALE_SCREEN_DIV_8:\n\t\tdivisor = 8;\n\t\tbreak;\n\tcase SCALE_SCREEN_DIV_6:\n\t\tdivisor = 6;\n\t\tbreak;\n\tcase SCALE_SCREEN_DIV_5:\n\t\tdivisor = 5;\n\t\tbreak;\n\tcase SCALE_SCREEN_DIV_4:\n\t\tdivisor = 4;\n\t\tbreak;\n\tcase SCALE_SCREEN_DIV_3:\n\t\tdivisor = 3;\n\t\tbreak;\n\tcase SCALE_SCREEN_DIV_2:\n\t\tdivisor = 2;\n\t\tbreak;\n\tcase SCALE_SCREEN:\n\t\tbreak;\n\tdefault:\n\t\tdX = 0;\n\t\tdY = 0;\n\t\treturn;\n\t}\n\n\tOptions::baseXResolution = std::max(Screen::ORIGINAL_WIDTH, Options::displayWidth / divisor);\n\tOptions::baseYResolution = std::max(Screen::ORIGINAL_HEIGHT, (int)(Options::displayHeight / pixelRatioY / divisor));\n\n\tdX = Options::baseXResolution - dX;\n\tdY = Options::baseYResolution - dY;\n\n\t_globe->resize();\n\n\tfor (auto* surface : _surfaces)\n\t{\n\t\tif (surface != _globe)\n\t\t{\n\t\t\tsurface->setX(surface->getX() + dX);\n\t\t\tsurface->setY(surface->getY() + dY/2);\n\t\t}\n\t}\n\n\t_bg->setX((_globe->getWidth() - _bg->getWidth()) / 2);\n\t_bg->setY((_globe->getHeight() - _bg->getHeight()) / 2);\n\n\tint height = (Options::baseYResolution - Screen::ORIGINAL_HEIGHT) / 2 + 10;\n\t_sideTop->setHeight(height);\n\t_sideTop->setY(_sidebar->getY() - height - 1);\n\t_sideBottom->setHeight(height);\n\t_sideBottom->setY(_sidebar->getY() + _sidebar->getHeight() + 1);\n\n\t_sideLine->setHeight(Options::baseYResolution);\n\t_sideLine->setY(0);\n\t_sideLine->drawRect(0, 0, _sideLine->getWidth(), _sideLine->getHeight(), 15);\n}\nbool GeoscapeState::buttonsDisabled()\n{\n\treturn _zoomInEffectTimer->isRunning() || _zoomOutEffectTimer->isRunning();\n}\n\nvoid GeoscapeState::updateSlackingIndicator()\n{\n\tif (Options::oxceGeoEnableTrainingIndicator)\n\t{\n\t\tint freeGym = 0;\n\t\tint freePsi = 0;\n\t\tfor (auto* xcomBase : *_game->getSavedGame()->getBases())\n\t\t{\n\t\t\tint facilityGym = xcomBase->getFreeTrainingSpace();\n\t\t\tif (facilityGym > 0)\n\t\t\t{\n\t\t\t\tint soldGym = 0;\n\t\t\t\tfor (auto* soldier : *xcomBase->getSoldiers())\n\t\t\t\t{\n\t\t\t\t\tbool isTraining = soldier->isInTraining();\n\t\t\t\t\tbool isQueued = !isTraining && soldier->getReturnToTrainingWhenHealed();\n\t\t\t\t\tbool isDone = soldier->isFullyTrained();\n\n\t\t\t\t\tif (isTraining || isQueued || isDone)\n\t\t\t\t\t{\n\t\t\t\t\t\t// ignore this guy\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// can train, or can be queued for training\n\t\t\t\t\t\tsoldGym++;\n\t\t\t\t\t}\n\t\t\t\t\tif (soldGym >= facilityGym) break;\n\t\t\t\t}\n\t\t\t\tfreeGym += soldGym;\n\t\t\t}\n\n\t\t\tint facilityPsi = xcomBase->getFreePsiLabs();\n\t\t\tif (facilityPsi > 0)\n\t\t\t{\n\t\t\t\tint soldPsi = 0;\n\t\t\t\tfor (auto* soldier : *xcomBase->getSoldiers())\n\t\t\t\t{\n\t\t\t\t\tbool isTraining = soldier->isInPsiTraining();\n\t\t\t\t\tbool isDone = soldier->isFullyPsiTrained();\n\t\t\t\t\tbool isNotEligible = soldier->getRules()->getTrainingStatCaps().psiSkill <= 0;\n\n\t\t\t\t\tif (isTraining || isDone || isNotEligible)\n\t\t\t\t\t{\n\t\t\t\t\t\t// ignore this guy\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// can train\n\t\t\t\t\t\tsoldPsi++;\n\t\t\t\t\t}\n\t\t\t\t\tif (soldPsi >= facilityPsi) break;\n\t\t\t\t}\n\t\t\t\tfreePsi += soldPsi;\n\t\t\t}\n\t\t}\n\t\tif (freeGym > 0 || freePsi > 0)\n\t\t{\n\t\t\t_txtTraining->setText(tr(\"STR_TRAINING_INDICATOR\").arg(freePsi).arg(freeGym));\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_txtTraining->setText(\"\");\n\t\t}\n\t}\n\n\tif (!Options::oxceEnableSlackingIndicator)\n\t\treturn;\n\n\tint scientistsSlacking = 0;\n\tint engineersSlacking = 0;\n\tfor (auto* xcomBase : *_game->getSavedGame()->getBases())\n\t{\n\t\tscientistsSlacking += xcomBase->getAvailableScientists();\n\t\tengineersSlacking += xcomBase->getAvailableEngineers();\n\t}\n\tif (scientistsSlacking > 0 || engineersSlacking > 0)\n\t{\n\t\t_txtSlacking->setText(tr(\"STR_SLACKING_INDICATOR\").arg(scientistsSlacking).arg(engineersSlacking));\n\t}\n\telse\n\t{\n\t\t_txtSlacking->setText(\"\");\n\t}\n}\n\nvoid GeoscapeState::cbxRegionChange(Action *)\n{\n\tint index = _cbxRegion->getSelected();\n\tif (index < 1)\n\t{\n\t\t_game->getSavedGame()->debugRegion = nullptr;\n\t}\n\telse\n\t{\n\t\t_game->getSavedGame()->debugRegion = (*_game->getSavedGame()->getRegions())[index-1];\n\t}\n\tupdateZoneInfo();\n}\n\nvoid GeoscapeState::cbxZoneChange(Action *)\n{\n\t_game->getSavedGame()->debugZone = _cbxZone->getSelected();\n\tupdateZoneInfo();\n}\n\nvoid GeoscapeState::cbxAreaChange(Action *)\n{\n\t_game->getSavedGame()->debugArea = _cbxArea->getSelected();\n\tupdateZoneInfo();\n}\n\nvoid GeoscapeState::updateZoneInfo()\n{\n\tstd::ostringstream ss;\n\tauto* save = _game->getSavedGame();\n\tif (save->debugRegion)\n\t{\n\t\tauto* regionRule = save->debugRegion->getRules();\n\t\tif (save->debugType >= 1)\n\t\t{\n\t\t\tss << \"region: \" << tr(regionRule->getType()) << \" [\" << regionRule->getType() << \"]\" << std::endl;\n\t\t}\n\t\tif (save->debugType == 2)\n\t\t{\n\t\t\tif (save->debugZone > 0 && save->debugZone <= regionRule->getMissionZones().size())\n\t\t\t{\n\t\t\t\tauto& selectedZone = regionRule->getMissionZones().at(save->debugZone - 1);\n\t\t\t\tss << \"zone: \" << save->debugZone - 1 << std::endl;\n\t\t\t\tif (save->debugArea > 0 && save->debugArea <= selectedZone.areas.size())\n\t\t\t\t{\n\t\t\t\t\tauto& selectedArea = selectedZone.areas.at(save->debugArea - 1);\n\t\t\t\t\tss << \"area: \" << save->debugArea - 1;\n\t\t\t\t\tss << \", texture: \" << selectedArea.texture;\n\t\t\t\t\tss << \", name: \" << tr(selectedArea.name) << \" [\" << selectedArea.name << \"]\" << std::endl;\n\t\t\t\t\tif (selectedArea.isPoint())\n\t\t\t\t\t{\n\t\t\t\t\t\tss << \"point = [\" << selectedArea.lonMin / M_PI * 180 << \", \" << selectedArea.latMin / M_PI * 180 << \"]\";\n\t\t\t\t\t\tint texture, shade;\n\t\t\t\t\t\t_globe->getPolygonTextureAndShade(selectedArea.lonMin, selectedArea.latMin, &texture, &shade);\n\t\t\t\t\t\tss << \", globe texture: \" << texture;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tss << \"rect = [\" << selectedArea.lonMin / M_PI * 180 << \", \" << selectedArea.lonMax / M_PI * 180;\n\t\t\t\t\t\tss << \", \" << selectedArea.latMin / M_PI * 180 << \", \" << selectedArea.latMax / M_PI * 180 << \"]\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tss << \"total areas: \" << selectedZone.areas.size() << std::endl;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tss << \"total zones: \" << regionRule->getMissionZones().size() << std::endl;\n\t\t\t}\n\t\t}\n\t}\n\t_txtDebug->setText(ss.str());\n}\n\nvoid GeoscapeState::cbxCountryChange(Action *)\n{\n\tint index = _cbxCountry->getSelected();\n\tif (index < 1)\n\t{\n\t\t_game->getSavedGame()->debugCountry = nullptr;\n\t}\n\telse\n\t{\n\t\t_game->getSavedGame()->debugCountry = (*_game->getSavedGame()->getCountries())[index - 1];\n\t}\n\n\tstd::ostringstream ss;\n\tauto* save = _game->getSavedGame();\n\tif (save->debugCountry)\n\t{\n\t\tauto* countryRule = save->debugCountry->getRules();\n\t\tif (save->debugType == 0)\n\t\t{\n\t\t\tss << \"country: \" << tr(countryRule->getType()) << \" [\" << countryRule->getType() << \"]\" << std::endl;\n\t\t}\n\t}\n\t_txtDebug->setText(ss.str());\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/GeoscapeState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http:///www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include <list>\n\nnamespace OpenXcom\n{\n\nclass Surface;\nclass Globe;\nclass TextButton;\nclass InteractiveSurface;\nclass Text;\nclass ComboBox;\nclass Timer;\nclass DogfightState;\nclass Craft;\nclass Ufo;\nclass MissionSite;\nclass Base;\nclass RuleMissionScript;\nclass RuleEvent;\nclass AlienBase;\n\n/**\n * Geoscape screen which shows an overview of\n * the world and lets the player manage the game.\n */\nclass GeoscapeState : public State\n{\nprivate:\n\tSurface *_bg, *_sideLine, *_sidebar;\n\tGlobe *_globe;\n\tTextButton *_btnIntercept, *_btnBases, *_btnGraphs, *_btnUfopaedia, *_btnOptions, *_btnFunding;\n\tTextButton *_timeSpeed;\n\tTextButton *_btn5Secs, *_btn1Min, *_btn5Mins, *_btn30Mins, *_btn1Hour, *_btn1Day;\n\tTextButton *_sideTop, *_sideBottom;\n\tInteractiveSurface *_btnRotateLeft, *_btnRotateRight, *_btnRotateUp, *_btnRotateDown, *_btnZoomIn, *_btnZoomOut;\n\tText *_txtFunds, *_txtHour, *_txtHourSep, *_txtMin, *_txtMinSep, *_txtSec, *_txtWeekday, *_txtDay, *_txtMonth, *_txtYear;\n\tTimer *_gameTimer, *_zoomInEffectTimer, *_zoomOutEffectTimer, *_dogfightStartTimer, *_dogfightTimer;\n\tbool _pause, _zoomInEffectDone, _zoomOutEffectDone;\n\tText *_txtDebug;\n\tComboBox *_cbxRegion, *_cbxZone, *_cbxArea, *_cbxCountry;\n\tText *_txtSlacking;\n\tText *_txtTraining;\n\tstd::list<State*> _popups;\n\tstd::list<DogfightState*> _dogfights, _dogfightsToBeStarted;\n\tstd::vector<Craft*> _activeCrafts;\n\tsize_t _minimizedDogfights;\n\tint _slowdownCounter;\n\n\t/// Update list of active crafts.\n\tconst std::vector<Craft*>* updateActiveCrafts();\n\n\tvoid cbxRegionChange(Action *action);\n\tvoid cbxZoneChange(Action *action);\n\tvoid cbxAreaChange(Action *action);\n\tvoid updateZoneInfo();\n\tvoid cbxCountryChange(Action *action);\n\npublic:\n\t/// Creates the Geoscape state.\n\tGeoscapeState();\n\t/// Cleans up the Geoscape state.\n\t~GeoscapeState();\n\t/// Handle keypresses.\n\tvoid handle(Action *action) override;\n\t/// Updates the palette and timer.\n\tvoid init() override;\n\t/// Runs the timer.\n\tvoid think() override;\n\t/// Displays the game time/date. (+Funds)\n\tvoid timeDisplay();\n\t/// Advances the game timer.\n\tvoid timeAdvance();\n\t/// Trigger whenever 5 seconds pass.\n\tvoid time5Seconds();\n\t/// Trigger whenever 10 minutes pass.\n\tvoid time10Minutes();\n\tvoid ufoHuntingAndEscorting();\n\tvoid baseHunting();\n\t/// Trigger whenever 30 minutes pass.\n\tvoid time30Minutes();\n\tvoid ufoDetection(Ufo* ufo, const std::vector<Craft*>* activeCrafts);\n\t/// Trigger whenever 1 hour passes.\n\tvoid time1Hour();\n\t/// Trigger whenever 1 day passes.\n\tvoid time1Day();\n\t/// Trigger whenever 1 month passes.\n\tvoid time1Month();\n\t/// Resets the timer to minimum speed.\n\tvoid timerReset();\n\t/// Displays a popup window.\n\tvoid popup(State *state);\n\t/// Gets the Geoscape globe.\n\tGlobe *getGlobe() const;\n\t/// Handler for clicking the globe.\n\tvoid globeClick(Action *action);\n\t/// Handler for clicking the Intercept button.\n\tvoid btnInterceptClick(Action *action);\n\t/// Handler for clicking the UFO Tracker button.\n\tvoid btnUfoTrackerClick(Action *action);\n\t/// Handler for clicking the TechTreeViewer button.\n\tvoid btnTechTreeViewerClick(Action *action);\n\t/// Handler for clicking the [SelectMusicTrack] button.\n\tvoid btnSelectMusicTrackClick(Action *action);\n\t/// Handler for clicking the [GlobalProduction] key.\n\tvoid btnGlobalProductionClick(Action *action);\n\t/// Handler for clicking the [GlobalResearch] key.\n\tvoid btnGlobalResearchClick(Action *action);\n\t/// Handler for clicking the [GlobalAlienContainment] key.\n\tvoid btnGlobalAlienContainmentClick(Action *action);\n\t/// Handler for clicking the [DogfightExperience] key.\n\tvoid btnDogfightExperienceClick(Action *action);\n\t/// Handler for clicking the [Debug] key.\n\tvoid btnDebugClick(Action *action);\n\t/// Handler for clicking the Bases button.\n\tvoid btnBasesClick(Action *action);\n\t/// Handler for clicking the Graph button.\n\tvoid btnGraphsClick(Action *action);\n\t/// Handler for clicking the Ufopaedia button.\n\tvoid btnUfopaediaClick(Action *action);\n\t/// Handler for clicking the Options button.\n\tvoid btnOptionsClick(Action *action);\n\t/// Handler for clicking the Funding button.\n\tvoid btnFundingClick(Action *action);\n\t/// Handler for pressing the Rotate Left arrow.\n\tvoid btnRotateLeftPress(Action *action);\n\t/// Handler for releasing the Rotate Left arrow.\n\tvoid btnRotateLeftRelease(Action *action);\n\t/// Handler for pressing the Rotate Right arrow.\n\tvoid btnRotateRightPress(Action *action);\n\t/// Handler for releasing the Rotate Right arrow.\n\tvoid btnRotateRightRelease(Action *action);\n\t/// Handler for pressing the Rotate Up arrow.\n\tvoid btnRotateUpPress(Action *action);\n\t/// Handler for releasing the Rotate Up arrow.\n\tvoid btnRotateUpRelease(Action *action);\n\t/// Handler for pressing the Rotate Down arrow.\n\tvoid btnRotateDownPress(Action *action);\n\t/// Handler for releasing the Rotate Down arrow.\n\tvoid btnRotateDownRelease(Action *action);\n\t/// Handler for left-clicking the Zoom In icon.\n\tvoid btnZoomInLeftClick(Action *action);\n\t/// Handler for right-clicking the Zoom In icon.\n\tvoid btnZoomInRightClick(Action *action);\n\t/// Handler for left-clicking the Zoom Out icon.\n\tvoid btnZoomOutLeftClick(Action *action);\n\t/// Handler for right-clicking the Zoom Out icon.\n\tvoid btnZoomOutRightClick(Action *action);\n\t/// Blit method - renders the state and dogfights.\n\tvoid blit() override;\n\t/// Globe zoom in effect for dogfights.\n\tvoid zoomInEffect();\n\t/// Globe zoom out effect for dogfights.\n\tvoid zoomOutEffect();\n\t/// Multi-dogfights logic handling.\n\tvoid handleDogfights();\n\tvoid handleDogfightMultiAction(int button);\n\t/// Dogfight experience handling.\n\tvoid handleDogfightExperience();\n\t/// Gets the number of minimized dogfights.\n\tint minimizedDogfightsCount();\n\t/// Starts a new dogfight.\n\tvoid startDogfight();\n\t/// Get first free dogfight slot.\n\tint getFirstFreeDogfightSlot();\n\t/// Handler for clicking the timer button.\n\tvoid btnTimerClick(Action *action);\n\t/// Process a mission site\n\tbool processMissionSite(MissionSite *site);\n\t/// Handles base defense\n\tvoid handleBaseDefense(Base *base, Ufo *ufo);\n\t/// Update the resolution settings, we just resized the window.\n\tvoid resize(int &dX, int &dY) override;\n\t/// Handle alien mission generation.\n\tvoid determineAlienMissions(bool isNewMonth = true, const RuleEvent* eventRules = nullptr);\nprivate:\n\tbool attemptAlienRaceEvolution(int month, AlienBase* ab) const;\n\t/// Process each individual mission script command.\n\tbool processCommand(RuleMissionScript *command);\n\tbool buttonsDisabled();\n\tvoid updateSlackingIndicator();\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/Globe.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Globe.h\"\n#include \"../fmath.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/SurfaceSet.h\"\n#include \"../Engine/Timer.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/Polygon.h\"\n#include \"../Mod/Polyline.h\"\n#include \"../Engine/FastLineClip.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/RNG.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/GameTime.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/Country.h\"\n#include \"../Mod/RuleCountry.h\"\n#include \"../Interface/Text.h\"\n#include \"../Mod/RuleRegion.h\"\n#include \"../Savegame/Region.h\"\n#include \"../Mod/City.h\"\n#include \"../Savegame/Target.h\"\n#include \"../Savegame/Ufo.h\"\n#include \"../Savegame/Craft.h\"\n#include \"../Savegame/Waypoint.h\"\n#include \"../Engine/ShaderMove.h\"\n#include \"../Engine/ShaderRepeat.h\"\n#include \"../Engine/Options.h\"\n#include \"../Savegame/MissionSite.h\"\n#include \"../Savegame/AlienBase.h\"\n#include \"../Engine/Language.h\"\n#include \"../Savegame/BaseFacility.h\"\n#include \"../Mod/RuleBaseFacility.h\"\n#include \"../Mod/RuleCraft.h\"\n#include \"../Mod/RuleGlobe.h\"\n#include \"../Mod/Texture.h\"\n#include \"../Interface/Cursor.h\"\n#include \"../Engine/Screen.h\"\n\nnamespace OpenXcom\n{\n\nconst double Globe::ROTATE_LONGITUDE = 0.10;\nconst double Globe::ROTATE_LATITUDE = 0.06;\n\nUint8 Globe::OCEAN_COLOR;\nbool Globe::OCEAN_SHADING;\nUint8 Globe::COUNTRY_LABEL_COLOR;\nUint8 Globe::LINE_COLOR;\nUint8 Globe::CITY_LABEL_COLOR;\nUint8 Globe::BASE_LABEL_COLOR;\n\nnamespace\n{\n\n///helper class for `Globe` for drawing earth globe with shadows\nstruct GlobeStaticData\n{\n\tstatic const int random_surf_size = 60;\n\tstatic const int random_multiplier_noise_bits = 4;\n\tstatic const int random_distance_noise_bits = 3;\n\tstatic const int random_value_noise_bits = 5;\n\n\tstatic const int shade_gradient_max = 256;\n\tstatic const int shade_step_max = 1 << random_value_noise_bits;\n\t///array of shading gradient\n\tSint16 shade_gradient[shade_gradient_max];\n\tSint16 shade_step[shade_gradient_max];\n\tSint16 shade_seq[shade_gradient_max];\n\tSint16 shade_diff[shade_gradient_max];\n\t///size of x & y of noise surface\n\tSint16 random_noise[random_surf_size*random_surf_size];\n\n\t/**\n\t * Function returning normal vector of sphere surface\n\t * @param ox x cord of sphere center\n\t * @param oy y cord of sphere center\n\t * @param r radius of sphere\n\t * @param x cord of point where we getting this vector\n\t * @param y cord of point where we getting this vector\n\t * @return normal vector of sphere surface\n\t */\n\tstatic inline Cord circle_norm(double ox, double oy, double r, double x, double y)\n\t{\n\t\tconst double limit = r*r;\n\t\tconst double norm = 1./r;\n\t\tCord ret;\n\t\tret.x = (x-ox);\n\t\tret.y = (y-oy);\n\t\tconst double temp = (ret.x)*(ret.x) + (ret.y)*(ret.y);\n\t\tif (limit > temp)\n\t\t{\n\t\t\tret.x *= norm;\n\t\t\tret.y *= norm;\n\t\t\tret.z = sqrt(limit - temp)*norm;\n\t\t\treturn ret;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tret.x = 0.;\n\t\t\tret.y = 0.;\n\t\t\tret.z = 0.;\n\t\t\treturn ret;\n\t\t}\n\t}\n\n\tstatic inline Sint16 shadeCurve(int i)\n\t{\n\t\tconst int shadeOffset = 15;\n\t\tconst int j = i - shade_gradient_max / 2;\n\n\t\tconst int stepSize = 16;\n\t\tconst int steps[stepSize] =\n\t\t{\n\t\t\t1,\n\t\t\t2,\n\t\t\t2,\n\t\t\t3,\n\t\t\t3,\n\t\t\t4,\n\t\t\t4,\n\t\t\t5,\n\t\t\t5,\n\t\t\t6,\n\t\t\t6,\n\t\t\t9,\n\t\t\t12,\n\t\t\t16,\n\t\t\t20,\n\t\t\t30,\n\t\t};\n\n\t\tconst int adjustemt = (j >= 0 ? 1 : 0);\n\t\tconst int d = (adjustemt ? 1 : -1);\n\t\tint offset = (adjustemt ? j + adjustemt : -j);\n\t\tint shadeFinal = shadeOffset + adjustemt;\n\t\tfor (int k = 0; k < stepSize; ++k)\n\t\t{\n\t\t\tint p = steps[k];\n\t\t\tif (offset < p)\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tshadeFinal += d;\n\t\t\toffset -= p;\n\t\t}\n\t\treturn shadeFinal;\n\t}\n\n\tstatic int bitMask(int i)\n\t{\n\t\treturn ((1<< i) - 1);\n\t}\n\n\tint getMultiplierNoise(Sint16 n)\n\t{\n\t\treturn ((n >> (random_value_noise_bits + random_distance_noise_bits)) & bitMask(random_multiplier_noise_bits));\n\t}\n\n\tint getDistanceNoise(Sint16 n)\n\t{\n\t\treturn ((n >> random_value_noise_bits) & bitMask(random_distance_noise_bits)) - random_distance_noise_bits / 2;\n\t}\n\n\tint getValueNoise(Sint16 n)\n\t{\n\t\treturn n &  bitMask(random_value_noise_bits);\n\t}\n\n\t//initialization\n\tGlobeStaticData()\n\t{\n\t\tint iLastVal = shadeCurve(0);\n\t\tint iLast = 0;\n\t\t//filling terminator gradient LUT\n\t\tfor (int i=0; i < shade_gradient_max; ++i)\n\t\t{\n\t\t\tint t = shadeCurve(i);\n\t\t\tif (t != iLastVal)\n\t\t\t{\n\t\t\t\tfor (int p = iLast; p < i; ++p)\n\t\t\t\t{\n\t\t\t\t\tshade_diff[p] = t - iLastVal;\n\t\t\t\t\tshade_step[p] = shade_step_max / (i - iLast);\n\t\t\t\t\tshade_seq[p] = shade_step_max * (p - iLast) / (i - iLast);\n\t\t\t\t}\n\t\t\t\tiLastVal = t;\n\t\t\t\tiLast = i;\n\t\t\t}\n\t\t\tshade_gradient[i] = t;\n\t\t}\n\n\t\tint tLast = shadeCurve(shade_gradient_max);\n\t\tfor (int p = iLast; p < shade_gradient_max; ++p)\n\t\t{\n\t\t\tshade_diff[p] = tLast - iLastVal;\n\t\t\tshade_step[p] = shade_step_max / (shade_gradient_max - iLast);\n\t\t\tshade_seq[p] = shade_step_max * (p - iLast) / (shade_gradient_max - iLast);\n\t\t}\n\n\t\tRNG::RandomState randomState;\n\t\tfor (size_t i = 0; i < (size_t)random_surf_size*random_surf_size; ++i)\n\t\t\trandom_noise[i] = randomState.generate(0, bitMask(random_multiplier_noise_bits + random_distance_noise_bits + random_value_noise_bits));\n\t}\n};\n\nGlobeStaticData static_data;\n\nstruct Ocean\n{\n\tstatic inline void func(Uint8& dest, const int&, const int&, const int&, const int&)\n\t{\n\t\tdest = Globe::OCEAN_COLOR;\n\t}\n};\n\nstruct CreateShadow\n{\n\tstatic inline Uint8 getShadowValue(const Cord& earth, const Cord& sun, const Sint16& noise)\n\t{\n\t\tCord temp = earth;\n\t\t//diff\n\t\ttemp -= sun;\n\t\t//norm\n\t\ttemp.x *= temp.x;\n\t\ttemp.y *= temp.y;\n\t\ttemp.z *= temp.z;\n\t\ttemp.x += temp.z + temp.y;\n\t\t//we have norm of distance between 2 vectors, now stored in `x`\n\n\t\ttemp.x -= 2;\n\t\ttemp.x *= 125.;\n\t\ttemp.x += GlobeStaticData::shade_gradient_max / 2;\n\t\t//random noise that go in any direction\n\t\ttemp.x -= static_data.getDistanceNoise(noise);\n\t\t//random noise than increase with distance from middle of twilight\n\t\ttemp.x += static_data.getMultiplierNoise(noise) * 4 * (temp.x - GlobeStaticData::shade_gradient_max / 2) / GlobeStaticData::shade_gradient_max;\n\n\t\tdouble full = 0;\n\t\tdouble rem = std::modf(temp.x, &full);\n\t\tint offset = Clamp((int)full, 0, GlobeStaticData::shade_gradient_max - 1);\n\t\tint i = static_data.shade_gradient[offset];\n\n\t\tint middle = (static_data.shade_seq[offset] + static_data.shade_step[offset] * rem) - GlobeStaticData::shade_step_max / 2;\n\t\ti += middle / GlobeStaticData::shade_step_max;\n\t\ti += (static_data.getValueNoise(noise) < (middle % GlobeStaticData::shade_step_max));\n\n\t\treturn Clamp(i, 0, 31);\n\t}\n\n\tstatic inline Uint8 getOceanShadow(const Uint8& shadow)\n\t{\n\t\treturn Globe::OCEAN_COLOR + shadow;\n\t}\n\n\tstatic inline Uint8 getLandShadow(const Uint8& dest, const Uint8& shadow)\n\t{\n\t\tif (shadow == 0) return dest;\n\t\tconst int s = shadow / 3;\n\t\tconst int e = dest + s;\n\t\tconst int d = dest & helper::ColorGroup;\n\t\tif (e > d + helper::ColorShade)\n\t\t\treturn d + helper::ColorShade;\n\t\treturn e;\n\t}\n\n\tstatic inline bool isOcean(const Uint8& dest)\n\t{\n\t\treturn Globe::OCEAN_SHADING && dest >= Globe::OCEAN_COLOR && dest < Globe::OCEAN_COLOR + 32;\n\t}\n\n\tstatic inline void func(Uint8& dest, const Cord& earth, const Cord& sun, const Sint16& noise)\n\t{\n\t\tif (dest && earth.z)\n\t\t{\n\t\t\tconst Uint8 shadow = getShadowValue(earth, sun, noise);\n\t\t\t//this pixel is ocean\n\t\t\tif (isOcean(dest))\n\t\t\t{\n\t\t\t\tdest = getOceanShadow(shadow);\n\t\t\t}\n\t\t\t//this pixel is land\n\t\t\telse\n\t\t\t{\n\t\t\t\tdest = getLandShadow(dest, shadow);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tdest = 0;\n\t\t}\n\t}\n};\n\nstruct CreateShadowWithoutCache\n{\n\tstatic inline void func(Uint8& dest, const helper::Offset& offset, const Cord& sun, const Sint16& noise, const int& radius)\n\t{\n\t\tCord earth = static_data.circle_norm(0., 0., radius, offset.x, offset.y);\n\t\tCreateShadow::func(dest, earth, sun, noise);\n\t}\n};\n\n}//namespace\n\n\n/**\n * Sets up a globe with the specified size and position.\n * @param game Pointer to core game.\n * @param cenX X position of the center of the globe.\n * @param cenY Y position of the center of the globe.\n * @param width Width in pixels.\n * @param height Height in pixels.\n * @param x X position in pixels.\n * @param y Y position in pixels.\n */\nGlobe::Globe(Game* game, int cenX, int cenY, int width, int height, int x, int y) : InteractiveSurface(width, height, x, y), _cenX(cenX), _cenY(cenY), _rotLon(0.0), _rotLat(0.0), _hoverLon(0.0), _hoverLat(0.0), _craftLon(0.0), _craftLat(0.0), _craftRange(0.0), _game(game), _hover(false), _craft(false), _blink(-1),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t_isMouseScrolling(false), _isMouseScrolled(false), _xBeforeMouseScrolling(0), _yBeforeMouseScrolling(0), _lonBeforeMouseScrolling(0.0), _latBeforeMouseScrolling(0.0), _mouseScrollingStartTime(0), _totalMouseMoveX(0), _totalMouseMoveY(0), _mouseMovedOverThreshold(false)\n{\n\t_rules = game->getMod()->getGlobe();\n\t_texture = new SurfaceSet(*_game->getMod()->getSurfaceSet(\"TEXTURE.DAT\"));\n\t_markerSet = _game->getMod()->getSurfaceSet(\"GlobeMarkers\");\n\n\t_countries = new Surface(width, height, x, y);\n\t_markers = new Surface(width, height, x, y);\n\t_radars = new Surface(width, height, x, y);\n\t_clipper = new FastLineClip(x, x+width, y, y+height);\n\n\t// Animation timers\n\t_blinkTimer = new Timer(100);\n\t_blinkTimer->onTimer((SurfaceHandler)&Globe::blink);\n\t_blinkTimer->start();\n\t_rotTimer = new Timer(10);\n\t_rotTimer->onTimer((SurfaceHandler)&Globe::rotate);\n\n\t_cenLon = _game->getSavedGame()->getGlobeLongitude();\n\t_cenLat = _game->getSavedGame()->getGlobeLatitude();\n\t_zoom = _game->getSavedGame()->getGlobeZoom();\n\t_zoomOld = _zoom;\n\n\tsetupRadii(width, height);\n\tsetZoom(_zoom);\n\n\tcachePolygons();\n}\n\n/**\n * Deletes the contained surfaces.\n */\nGlobe::~Globe()\n{\n\tdelete _blinkTimer;\n\tdelete _rotTimer;\n\tdelete _countries;\n\tdelete _markers;\n\tdelete _texture;\n\tdelete _radars;\n\tdelete _clipper;\n\n\tfor (auto* polygon : _cacheLand)\n\t{\n\t\tdelete polygon;\n\t}\n}\n\n/**\n * Converts a polar point into a cartesian point for\n * mapping a polygon onto the 3D-looking globe.\n * @param lon Longitude of the polar point.\n * @param lat Latitude of the polar point.\n * @param x Pointer to the output X position.\n * @param y Pointer to the output Y position.\n */\nvoid Globe::polarToCart(double lon, double lat, Sint16 *x, Sint16 *y) const\n{\n\t// Orthographic projection\n\t*x = _cenX + (Sint16)floor(_radius * cos(lat) * sin(lon - _cenLon));\n\t*y = _cenY + (Sint16)floor(_radius * (cos(_cenLat) * sin(lat) - sin(_cenLat) * cos(lat) * cos(lon - _cenLon)));\n}\n\nvoid Globe::polarToCart(double lon, double lat, double *x, double *y) const\n{\n\t// Orthographic projection\n\t*x = _cenX + _radius * cos(lat) * sin(lon - _cenLon);\n\t*y = _cenY + _radius * (cos(_cenLat) * sin(lat) - sin(_cenLat) * cos(lat) * cos(lon - _cenLon));\n}\n\n\n/**\n * Converts a cartesian point into a polar point for\n * mapping a globe click onto the flat world map.\n * @param x X position of the cartesian point.\n * @param y Y position of the cartesian point.\n * @param lon Pointer to the output longitude.\n * @param lat Pointer to the output latitude.\n */\nvoid Globe::cartToPolar(Sint16 x, Sint16 y, double *lon, double *lat) const\n{\n\t// Orthographic projection\n\tx -= _cenX;\n\ty -= _cenY;\n\n\tdouble rho = sqrt((double)(x*x + y*y));\n\tdouble c = asin(rho / _radius);\n\tif ( AreSame(rho, 0.0) )\n\t{\n\t\t*lat = _cenLat;\n\t\t*lon = _cenLon;\n\n\t}\n\telse\n\t{\n\t\t*lat = asin((y * sin(c) * cos(_cenLat)) / rho + cos(c) * sin(_cenLat));\n\t\t*lon = atan2(x * sin(c),(rho * cos(_cenLat) * cos(c) - y * sin(_cenLat) * sin(c))) + _cenLon;\n\t}\n\n\t// Keep between 0 and 2xPI\n\twhile (*lon < 0)\n\t\t*lon += 2 * M_PI;\n\twhile (*lon >= 2 * M_PI)\n\t\t*lon -= 2 * M_PI;\n}\n\n/**\n * Checks if a polar point is on the back-half of the globe,\n * invisible to the player.\n * @param lon Longitude of the point.\n * @param lat Latitude of the point.\n * @return True if it's on the back, False if it's on the front.\n */\nbool Globe::pointBack(double lon, double lat) const\n{\n\tdouble c = cos(_cenLat) * cos(lat) * cos(lon - _cenLon) + sin(_cenLat) * sin(lat);\n\n\treturn c < 0.0;\n}\n\nPolygon* Globe::getPolygonFromLonLat(double lon, double lat) const\n{\n\tconst double zDiscard=0.75f;\n\tdouble coslat = cos(lat);\n\tdouble sinlat = sin(lat);\n\n\tfor (auto* polygon : *_rules->getPolygons())\n\t{\n\t\tdouble x, y, z, x2, y2;\n\t\tdouble clat, clon;\n\t\tz = 0;\n\t\tfor (int j = 0; j < polygon->getPoints(); ++j)\n\t\t{\n\t\t\tz = coslat * cos(polygon->getLatitude(j)) * cos(polygon->getLongitude(j) - lon) + sinlat * sin(polygon->getLatitude(j));\n\t\t\tif (z<zDiscard) break; //discarded\n\t\t}\n\t\tif (z<zDiscard) continue; //discarded\n\n\t\tbool odd = false;\n\n\t\tclat = polygon->getLatitude(0); //initial point\n\t\tclon = polygon->getLongitude(0);\n\t\tx = cos(clat) * sin(clon - lon);\n\t\ty = coslat * sin(clat) - sinlat * cos(clat) * cos(clon - lon);\n\n\t\tfor (int j = 0; j < polygon->getPoints(); ++j)\n\t\t{\n\t\t\tint k = (j + 1) % polygon->getPoints(); //index of next point in poly\n\t\t\tclat = polygon->getLatitude(k);\n\t\t\tclon = polygon->getLongitude(k);\n\n\t\t\tx2 = cos(clat) * sin(clon - lon);\n\t\t\ty2 = coslat * sin(clat) - sinlat * cos(clat) * cos(clon - lon);\n\t\t\tif ( ((y>0)!=(y2>0)) && (0 < (x2-x)*(0-y)/(y2-y)+x) )\n\t\t\t\todd = !odd;\n\t\t\tx = x2;\n\t\t\ty = y2;\n\n\t\t}\n\t\tif (odd) return polygon;\n\t}\n\treturn NULL;\n}\n\n/**\n * Sets a leftwards rotation speed and starts the timer.\n */\nvoid Globe::rotateLeft()\n{\n\t_rotLon = -ROTATE_LONGITUDE;\n\tif (!_rotTimer->isRunning()) _rotTimer->start();\n}\n\n/**\n * Sets a rightwards rotation speed and starts the timer.\n */\nvoid Globe::rotateRight()\n{\n\t_rotLon = ROTATE_LONGITUDE;\n\tif (!_rotTimer->isRunning()) _rotTimer->start();\n}\n\n/**\n * Sets a upwards rotation speed and starts the timer.\n */\nvoid Globe::rotateUp()\n{\n\t_rotLat = -ROTATE_LATITUDE;\n\tif (!_rotTimer->isRunning()) _rotTimer->start();\n}\n\n/**\n * Sets a downwards rotation speed and starts the timer.\n */\nvoid Globe::rotateDown()\n{\n\t_rotLat = ROTATE_LATITUDE;\n\tif (!_rotTimer->isRunning()) _rotTimer->start();\n}\n\n/**\n * Resets the rotation speed and timer.\n */\nvoid Globe::rotateStop()\n{\n\t_rotLon = 0.0;\n\t_rotLat = 0.0;\n\t_rotTimer->stop();\n}\n\n/**\n * Resets longitude rotation speed and timer.\n */\nvoid Globe::rotateStopLon()\n{\n\t_rotLon = 0.0;\n\tif (AreSame(_rotLat, 0.0))\n\t{\n\t\t_rotTimer->stop();\n\t}\n}\n\n/**\n * Resets latitude rotation speed and timer.\n */\nvoid Globe::rotateStopLat()\n{\n\t_rotLat = 0.0;\n\tif (AreSame(_rotLon, 0.0))\n\t{\n\t\t_rotTimer->stop();\n\t}\n}\n\n/**\n * Changes the current globe zoom factor.\n * @param zoom New zoom.\n */\nvoid Globe::setZoom(size_t zoom)\n{\n\t_zoom = Clamp(zoom, (size_t)0u, _zoomRadius.size() - 1);\n\t_zoomTexture = (2 - (int)floor(_zoom / 2.0)) * (_texture->getTotalFrames() / 3);\n\t_radius = _zoomRadius[_zoom];\n\t_game->getSavedGame()->setGlobeZoom(_zoom);\n\tif (_isMouseScrolling)\n\t{\n\t\t_lonBeforeMouseScrolling = _cenLon;\n\t\t_latBeforeMouseScrolling = _cenLat;\n\t\t_totalMouseMoveX = 0; _totalMouseMoveY = 0;\n\t}\n\tinvalidate();\n}\n\n/**\n * Increases the zoom level on the globe.\n */\nvoid Globe::zoomIn()\n{\n\tif (_zoom < _zoomRadius.size() - 1)\n\t{\n\t\tsetZoom(_zoom + 1);\n\t}\n}\n\n/**\n * Decreases the zoom level on the globe.\n */\nvoid Globe::zoomOut()\n{\n\tif (_zoom > 0)\n\t{\n\t\tsetZoom(_zoom - 1);\n\t}\n}\n\n/**\n * Zooms the globe out as far as possible.\n */\nvoid Globe::zoomMin()\n{\n\tif (_zoom > 0)\n\t{\n\t\tsetZoom(0);\n\t}\n}\n\n/**\n * Zooms the globe in as close as possible.\n */\nvoid Globe::zoomMax()\n{\n\tif (_zoom < _zoomRadius.size() - 1)\n\t{\n\t\tsetZoom(_zoomRadius.size() - 1);\n\t}\n}\n\n/**\n * Stores the zoom used before a dogfight.\n */\nvoid Globe::saveZoomDogfight()\n{\n\t_zoomOld = _zoom;\n}\n\n/**\n * Zooms the globe smoothly into dogfight level.\n * @return Is the globe already zoomed in?\n */\nbool Globe::zoomDogfightIn()\n{\n\tif (_zoom < DOGFIGHT_ZOOM)\n\t{\n\t\tdouble radiusNow = _radius;\n\t\tif (radiusNow + _radiusStep >= _zoomRadius[DOGFIGHT_ZOOM])\n\t\t{\n\t\t\tsetZoom(DOGFIGHT_ZOOM);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (radiusNow + _radiusStep >= _zoomRadius[_zoom + 1])\n\t\t\t\t_zoom++;\n\t\t\tsetZoom(_zoom);\n\t\t\t_radius = radiusNow + _radiusStep;\n\t\t}\n\t\treturn false;\n\t}\n\treturn true;\n}\n\n/**\n * Zooms the globe smoothly out of dogfight level.\n * @return Is the globe already zoomed out?\n */\nbool Globe::zoomDogfightOut()\n{\n\tif (_zoom > _zoomOld)\n\t{\n\t\tdouble radiusNow = _radius;\n\t\tif (radiusNow - _radiusStep <= _zoomRadius[_zoomOld])\n\t\t{\n\t\t\tsetZoom(_zoomOld);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (radiusNow - _radiusStep <= _zoomRadius[_zoom - 1])\n\t\t\t\t_zoom--;\n\t\t\tsetZoom(_zoom);\n\t\t\t_radius = radiusNow - _radiusStep;\n\t\t}\n\t\treturn false;\n\t}\n\treturn true;\n}\n\n/**\n * Rotates the globe to center on a certain\n * polar point on the world map.\n * @param lon Longitude of the point.\n * @param lat Latitude of the point.\n */\nvoid Globe::center(double lon, double lat)\n{\n\t_cenLon = lon;\n\t_cenLat = lat;\n\t_game->getSavedGame()->setGlobeLongitude(_cenLon);\n\t_game->getSavedGame()->setGlobeLatitude(_cenLat);\n\tinvalidate();\n}\n\n/**\n * Checks if a polar point is inside the globe's landmass.\n * @param lon Longitude of the point.\n * @param lat Latitude of the point.\n * @return True if it's inside, False if it's outside.\n */\nbool Globe::insideLand(double lon, double lat) const\n{\n\tauto* polygon = getPolygonFromLonLat(lon, lat);\n\tif (!polygon)\n\t{\n\t\treturn false;\n\t}\n\tauto* textureRule = _rules->getTexture(polygon->getTexture());\n\tif (textureRule && textureRule->isCosmeticOcean())\n\t{\n\t\treturn false;\n\t}\n\treturn true;\n}\n\n/**\n * Checks if a polar point is inside the fakeUnderwater texture.\n * @param lon Longitude of the point.\n * @param lat Latitude of the point.\n * @return True if it's inside, False if it's outside.\n */\nbool Globe::insideFakeUnderwaterTexture(double lon, double lat) const\n{\n\tauto* polygon = getPolygonFromLonLat(lon, lat);\n\tif (!polygon)\n\t{\n\t\treturn false;\n\t}\n\tauto* textureRule = _rules->getTexture(polygon->getTexture());\n\tif (textureRule && textureRule->isFakeUnderwater())\n\t{\n\t\treturn true;\n\t}\n\treturn false;\n}\n\n/**\n * Switches the amount of detail shown on the globe.\n * With detail on, country and city details are shown when zoomed in.\n */\nvoid Globe::toggleDetail()\n{\n\tOptions::globeDetail = !Options::globeDetail;\n\tdrawDetail();\n}\n\n/**\n * Checks if a certain target is near a certain cartesian point\n * (within a circled area around it) over the globe.\n * @param target Pointer to target.\n * @param x X coordinate of point.\n * @param y Y coordinate of point.\n * @return True if it's near, false otherwise.\n */\nbool Globe::targetNear(Target* target, int x, int y) const\n{\n\tSint16 tx, ty;\n\tif (pointBack(target->getLongitude(), target->getLatitude()))\n\t\treturn false;\n\tpolarToCart(target->getLongitude(), target->getLatitude(), &tx, &ty);\n\n\tint dx = x - tx;\n\tint dy = y - ty;\n\treturn (dx * dx + dy * dy <= NEAR_RADIUS);\n}\n\n/**\n * Returns a list of all the targets currently near a certain\n * cartesian point over the globe.\n * @param x X coordinate of point.\n * @param y Y coordinate of point.\n * @param craft Only get craft targets.\n * @return List of pointers to targets.\n */\nstd::vector<Target*> Globe::getTargets(int x, int y, bool craft, Craft *currentCraft) const\n{\n\tstd::vector<Target*> v;\n\t{\n\t\tfor (auto* xbase : *_game->getSavedGame()->getBases())\n\t\t{\n\t\t\tif (xbase->getLongitude() == 0.0 && xbase->getLatitude() == 0.0)\n\t\t\t\tcontinue;\n\n\t\t\tif (targetNear(xbase, x, y))\n\t\t\t{\n\t\t\t\tv.push_back(xbase);\n\t\t\t}\n\n\t\t\tfor (auto* xcraft : *xbase->getCrafts())\n\t\t\t{\n\t\t\t\tif (xcraft == currentCraft)\n\t\t\t\t\tcontinue;\n\t\t\t\tif (xcraft->getLongitude() == xbase->getLongitude() && xcraft->getLatitude() == xbase->getLatitude() && xcraft->getDestination() == 0)\n\t\t\t\t\tcontinue;\n\n\t\t\t\tif (targetNear(xcraft, x, y))\n\t\t\t\t{\n\t\t\t\t\tv.push_back(xcraft);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tfor (auto* ufo : *_game->getSavedGame()->getUfos())\n\t{\n\t\tif (!ufo->getDetected() || ufo->getStatus() == Ufo::IGNORE_ME)\n\t\t\tcontinue;\n\n\t\tif (targetNear(ufo, x, y))\n\t\t{\n\t\t\tv.push_back(ufo);\n\t\t}\n\t}\n\tfor (auto* wp : *_game->getSavedGame()->getWaypoints())\n\t{\n\t\tif (targetNear(wp, x, y))\n\t\t{\n\t\t\tv.push_back(wp);\n\t\t}\n\t}\n\tfor (auto* site : *_game->getSavedGame()->getMissionSites())\n\t{\n\t\tif (targetNear(site, x, y))\n\t\t{\n\t\t\tv.push_back(site);\n\t\t}\n\t}\n\tfor (auto* ab : *_game->getSavedGame()->getAlienBases())\n\t{\n\t\tif (!ab->isDiscovered())\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\t\tif (targetNear(ab, x, y))\n\t\t{\n\t\t\tv.push_back(ab);\n\t\t}\n\t}\n\treturn v;\n}\n\n/**\n * Takes care of pre-calculating all the polygons currently visible\n * on the globe and caching them so they only need to be recalculated\n * when the globe is actually moved.\n */\nvoid Globe::cachePolygons()\n{\n\tcache(_rules->getPolygons(), &_cacheLand);\n}\n\n/**\n * Caches a set of polygons.\n * @param polygons Pointer to list of polygons.\n * @param cache Pointer to cache.\n */\nvoid Globe::cache(std::list<Polygon*> *polygons, std::list<Polygon*> *cache)\n{\n\t// Clear existing cache\n\tfor (auto* polygon : *cache)\n\t{\n\t\tdelete polygon;\n\t}\n\tcache->clear();\n\n\t// Pre-calculate values to cache\n\tfor (auto* polygon : *polygons)\n\t{\n\t\t// Is quad on the back face?\n\t\tdouble closest = 0.0;\n\t\tdouble z;\n\t\tdouble furthest = 0.0;\n\t\tfor (int j = 0; j < polygon->getPoints(); ++j)\n\t\t{\n\t\t\tz = cos(_cenLat) * cos(polygon->getLatitude(j)) * cos(polygon->getLongitude(j) - _cenLon) + sin(_cenLat) * sin(polygon->getLatitude(j));\n\t\t\tif (z > closest)\n\t\t\t\tclosest = z;\n\t\t\telse if (z < furthest)\n\t\t\t\tfurthest = z;\n\t\t}\n\t\tif (-furthest > closest)\n\t\t\tcontinue;\n\n\t\tPolygon* p = new Polygon(*polygon);\n\n\t\t// Convert coordinates\n\t\tfor (int j = 0; j < p->getPoints(); ++j)\n\t\t{\n\t\t\tSint16 x, y;\n\t\t\tpolarToCart(p->getLongitude(j), p->getLatitude(j), &x, &y);\n\t\t\tp->setX(j, x);\n\t\t\tp->setY(j, y);\n\t\t}\n\n\t\tcache->push_back(p);\n\t}\n}\n\n/**\n * Replaces a certain amount of colors in the palette of the globe.\n * @param colors Pointer to the set of colors.\n * @param firstcolor Offset of the first color to replace.\n * @param ncolors Amount of colors to replace.\n */\nvoid Globe::setPalette(const SDL_Color *colors, int firstcolor, int ncolors)\n{\n\tSurface::setPalette(colors, firstcolor, ncolors);\n\n\t_texture->setPalette(colors, firstcolor, ncolors);\n\n\t_countries->setPalette(colors, firstcolor, ncolors);\n\t_markers->setPalette(colors, firstcolor, ncolors);\n\t_radars->setPalette(colors, firstcolor, ncolors);\n}\n\n/**\n * Keeps the animation timers running.\n */\nvoid Globe::think()\n{\n\t_blinkTimer->think(0, this);\n\t_rotTimer->think(0, this);\n}\n\n/**\n * Makes the globe markers blink.\n */\nvoid Globe::blink()\n{\n\t_blink = -_blink;\n\n\tdrawMarkers();\n}\n\n/**\n * Rotates the globe by a set amount. Necessary\n * since the globe keeps rotating while a button\n * is pressed down.\n */\nvoid Globe::rotate()\n{\n\t_cenLon += _rotLon * ((110 - Options::geoScrollSpeed) / 100.0) / (_zoom+1);\n\t_cenLat += _rotLat * ((110 - Options::geoScrollSpeed) / 100.0) / (_zoom+1);\n\t_game->getSavedGame()->setGlobeLongitude(_cenLon);\n\t_game->getSavedGame()->setGlobeLatitude(_cenLat);\n\tinvalidate();\n}\n\n/**\n * Draws the whole globe, part by part.\n */\nvoid Globe::draw()\n{\n\tif (_redraw)\n\t{\n\t\tcachePolygons();\n\t}\n\tSurface::draw();\n\tdrawOcean();\n\tdrawLand();\n\tdrawRadars();\n\tdrawFlights();\n\tdrawShadow();\n\tdrawMarkers();\n\tdrawDetail();\n}\n\n\n/**\n * Renders the ocean, shading it according to the time of day.\n */\nvoid Globe::drawOcean()\n{\n\tlock();\n\tdrawCircle(_cenX+1, _cenY, _radius+20, OCEAN_COLOR);\n//\tShaderDraw<Ocean>(ShaderSurface(this));\n\tunlock();\n}\n\n\n\n\n/**\n * Renders the land, taking all the visible world polygons\n * and texturing and shading them accordingly.\n */\nvoid Globe::drawLand()\n{\n\tSint16 x[4], y[4];\n\n\tfor (auto* polygon : _cacheLand)\n\t{\n\t\t// Convert coordinates\n\t\tfor (int j = 0; j < polygon->getPoints(); ++j)\n\t\t{\n\t\t\tx[j] = polygon->getX(j);\n\t\t\ty[j] = polygon->getY(j);\n\t\t}\n\n\t\t// Apply textures according to zoom and shade\n\t\tdrawTexturedPolygon(x, y, polygon->getPoints(), _texture->getFrame(polygon->getTexture() + _zoomTexture), 0, 0);\n\t}\n}\n\n/**\n * Get position of sun from point on globe\n * @param lon longitude of position\n * @param lat latitude of position\n * @return position of sun\n */\nCord Globe::getSunDirection(double lon, double lat) const\n{\n\tconst double curTime = _game->getSavedGame()->getTime()->getDaylight();\n\tconst double rot = curTime * 2*M_PI;\n\tdouble sun;\n\n\tif (Options::globeSeasons)\n\t{\n\t\tconst int MonthDays1[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};\n\t\tconst int MonthDays2[] = {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366};\n\n\t\tint year=_game->getSavedGame()->getTime()->getYear();\n\t\tint month=_game->getSavedGame()->getTime()->getMonth()-1;\n\t\tint day=_game->getSavedGame()->getTime()->getDay()-1;\n\n\t\tdouble tm = (double)(( _game->getSavedGame()->getTime()->getHour() * 60\n\t\t\t+ _game->getSavedGame()->getTime()->getMinute() ) * 60\n\t\t\t+ _game->getSavedGame()->getTime()->getSecond() ) / 86400; //day fraction is also taken into account\n\n\t\tdouble CurDay;\n\t\tif (year%4 == 0 && !(year%100 == 0 && year%400 != 0))\n\t\t\tCurDay = (MonthDays2[month] + day + tm )/366 - 0.219; //spring equinox (start of astronomic year)\n\t\telse\n\t\t\tCurDay = (MonthDays1[month] + day + tm )/365 - 0.219;\n\t\tif (CurDay<0) CurDay += 1.;\n\n\t\tsun = -0.261 * sin(CurDay*2*M_PI);\n\t}\n\telse\n\t\tsun = 0;\n\n\tCord sun_direction(cos(rot+lon), sin(rot+lon)*-sin(lat), sin(rot+lon)*cos(lat));\n\n\tCord pole(0, cos(lat), sin(lat));\n\n\tif (sun>0)\n\t\t sun_direction *= 1. - sun;\n\telse\n\t\t sun_direction *= 1. + sun;\n\n\tpole *= sun;\n\tsun_direction += pole;\n\tdouble norm = sun_direction.norm();\n\t//norm should be always greater than 0\n\tnorm = 1./norm;\n\tsun_direction *= norm;\n\treturn sun_direction;\n}\n\n\nvoid Globe::drawShadow()\n{\n\tif (Options::globeSurfaceCache)\n\t{\n\t\tShaderMove<Cord> earth = ShaderMove<Cord>(SurfaceRaw<Cord>(_earthData[_zoom], getWidth(), getHeight()));\n\t\tShaderRepeat<Sint16> noise = ShaderRepeat<Sint16>(SurfaceRaw<Sint16>(static_data.random_noise, static_data.random_surf_size, static_data.random_surf_size));\n\n\t\tearth.setMove(_cenX-getWidth()/2, _cenY-getHeight()/2);\n\n\t\tlock();\n\t\tShaderDraw<CreateShadow>(ShaderSurface(this), earth, ShaderScalar(getSunDirection(_cenLon, _cenLat)), noise);\n\t\tunlock();\n\t}\n\telse\n\t{\n\t\tShaderRepeat<Sint16> noise = ShaderRepeat<Sint16>(SurfaceRaw<Sint16>(static_data.random_noise, static_data.random_surf_size, static_data.random_surf_size));\n\n\t\tlock();\n\t\tShaderDraw<CreateShadowWithoutCache>(ShaderSurface(this), helper::Offset(_cenX, _cenY), ShaderScalar(getSunDirection(_cenLon, _cenLat)), noise, ShaderScalar(_zoomRadius[_zoom]));\n\t\tunlock();\n\t}\n\n}\n\n\nvoid Globe::XuLine(Surface* surface, Surface* src, double x1, double y1, double x2, double y2, int shade)\n{\n\tif (_clipper->LineClip(&x1,&y1,&x2,&y2) != 1) return; //empty line\n\n\tdouble deltax = x2-x1, deltay = y2-y1;\n\tbool inv;\n\tSint16 tcol;\n\tdouble len,x0,y0,SX,SY;\n\tif (abs((int)y2-(int)y1) > abs((int)x2-(int)x1))\n\t{\n\t\tlen=abs((int)y2-(int)y1);\n\t\tinv=false;\n\t}\n\telse\n\t{\n\t\tlen=abs((int)x2-(int)x1);\n\t\tinv=true;\n\t}\n\n\tif (y2 < y1) {\n\t\tSY = -1;\n\t}\n\telse if (AreSame(deltay, 0.0)) {\n\t\tSY = 0;\n\t}\n\telse {\n\t\tSY = 1;\n\t}\n\n\tif (x2 < x1) {\n\t\tSX = -1;\n\t}\n\telse if (AreSame(deltax, 0.0)) {\n\t\tSX = 0;\n\t}\n\telse {\n\t\tSX = 1;\n\t}\n\n\tx0=x1;  y0=y1;\n\tif (inv)\n\t\tSY=(deltay/len);\n\telse\n\t\tSX=(deltax/len);\n\n\twhile (len>0)\n\t{\n\t\ttcol=src->getPixel((int)x0,(int)y0);\n\t\tif (tcol)\n\t\t{\n\t\t\tif (CreateShadow::isOcean(tcol))\n\t\t\t{\n\t\t\t\ttcol = CreateShadow::getOceanShadow(shade + 8);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\ttcol = CreateShadow::getLandShadow(tcol, shade * 3);\n\t\t\t}\n\t\t\tsurface->setPixel((int)x0,(int)y0,tcol);\n\t\t}\n\t\tx0+=SX;\n\t\ty0+=SY;\n\t\tlen-=1.0;\n\t}\n}\n\n/**\n * Draws the radar ranges of player bases, player craft, alien bases and UFO hunter-killers on the globe.\n */\nvoid Globe::drawRadars()\n{\n\t_radars->clear();\n\n\tif (!Options::globeRadarLines)\n\t\treturn;\n\n\tdouble tr, range;\n\tdouble lat, lon;\n\tstd::vector<double> ranges;\n\n\t_radars->lock();\n\n\t// Draw craft range\n\tif (_craft)\n\t{\n\t\tif (_craftRange < M_PI)\n\t\t{\n\t\t\tdrawGlobeCircle(_craftLat, _craftLon, _craftRange, 64);\n\t\t\tdrawGlobeCircle(_craftLat, _craftLon, _craftRange - 0.025, 64, 2);\n\t\t}\n\t}\n\n\tif (_hover)\n\t{\n\t\tfor (auto& facType : _game->getMod()->getBaseFacilitiesList())\n\t\t{\n\t\t\trange = Nautical(_game->getMod()->getBaseFacility(facType)->getRadarRange());\n\t\t\tdrawGlobeCircle(_hoverLat,_hoverLon,range,48);\n\t\t\tif (Options::globeAllRadarsOnBaseBuild) ranges.push_back(range);\n\t\t}\n\t}\n\n\t// Draw radars around bases\n\tfor (auto* xbase : *_game->getSavedGame()->getBases())\n\t{\n\t\tlat = xbase->getLatitude();\n\t\tlon = xbase->getLongitude();\n\t\t// Cheap hack to hide bases when they haven't been placed yet\n\t\tif (( !(AreSame(lon, 0.0) && AreSame(lat, 0.0)) )/* &&\n\t\t\t!pointBack(xbase->getLongitude(), xbase->getLatitude())*/)\n\t\t{\n\t\t\tif (_hover && Options::globeAllRadarsOnBaseBuild)\n\t\t\t{\n\t\t\t\tfor (size_t j=0; j<ranges.size(); j++) drawGlobeCircle(lat,lon,ranges[j],48);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\trange = 0;\n\t\t\t\tfor (auto* fac : *xbase->getFacilities())\n\t\t\t\t{\n\t\t\t\t\tif (fac->getBuildTime() == 0)\n\t\t\t\t\t{\n\t\t\t\t\t\ttr = fac->getRules()->getRadarRange();\n\t\t\t\t\t\tif (tr < MAX_DRAW_RADAR_CIRCLE_RADIUS && tr > range) range = tr;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\trange = Nautical(range);\n\n\t\t\t\tif (range>0) drawGlobeCircle(lat,lon,range,48);\n\t\t\t}\n\n\t\t}\n\n\t\t// Draw radars around player craft\n\t\tfor (auto* xcraft : *xbase->getCrafts())\n\t\t{\n\t\t\tif (xcraft->getStatus() != \"STR_OUT\")\n\t\t\t\tcontinue;\n\t\t\tlat = xcraft->getLatitude();\n\t\t\tlon = xcraft->getLongitude();\n\t\t\trange = Nautical(xcraft->getCraftStats().radarRange);\n\n\t\t\tif (range>0) drawGlobeCircle(lat,lon,range,24);\n\t\t}\n\t}\n\n\tif (_game->getMod()->getDrawEnemyRadarCircles() > 0)\n\t{\n\t\t// Draw radars around UFO hunter-killers\n\t\tfor (auto* ufo : *_game->getSavedGame()->getUfos())\n\t\t{\n\t\t\tif (ufo->isHunterKiller() && ufo->getDetected() && ufo->getStatus() != Ufo::IGNORE_ME)\n\t\t\t{\n\t\t\t\tif (_game->getMod()->getDrawEnemyRadarCircles() == 1 && !ufo->getHyperDetected())\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tlat = ufo->getLatitude();\n\t\t\t\tlon = ufo->getLongitude();\n\t\t\t\trange = Nautical(ufo->getCraftStats().radarRange);\n\n\t\t\t\tif (range > 0) drawGlobeCircle(lat, lon, range, 24);\n\t\t\t}\n\t\t}\n\n\t\t// Draw radars around alien bases\n\t\tfor (auto* ab : *_game->getSavedGame()->getAlienBases())\n\t\t{\n\t\t\tif (ab->getDeployment()->getBaseDetectionRange() > 0 && ab->isDiscovered())\n\t\t\t{\n\t\t\t\tlat = ab->getLatitude();\n\t\t\t\tlon = ab->getLongitude();\n\t\t\t\trange = Nautical(ab->getDeployment()->getBaseDetectionRange());\n\n\t\t\t\tif (range > 0) drawGlobeCircle(lat, lon, range, 24);\n\t\t\t}\n\t\t}\n\t}\n\n\t_radars->unlock();\n}\n\n/**\n *\tDraw globe range circle\n */\nvoid Globe::drawGlobeCircle(double lat, double lon, double radius, int segments, int frac)\n{\n\tdouble x, y, x2 = 0, y2 = 0;\n\tdouble lat1, lon1;\n\tdouble seg = M_PI / (static_cast<double>(segments) / 2);\n\tint i = 0;\n\tfor (double az = 0; az <= M_PI*2+0.01; az+=seg) //48 circle segments\n\t{\n\t\t//calculating sphere-projected circle\n\t\tlat1 = asin(sin(lat) * cos(radius) + cos(lat) * sin(radius) * cos(az));\n\t\tlon1 = lon + atan2(sin(az) * sin(radius) * cos(lat), cos(radius) - sin(lat) * sin(lat1));\n\t\tpolarToCart(lon1, lat1, &x, &y);\n\t\tif ( AreSame(az, 0.0) ) //first vertex is for initialization only\n\t\t{\n\t\t\tx2=x;\n\t\t\ty2=y;\n\t\t\tcontinue;\n\t\t}\n\t\tif (!pointBack(lon1,lat1) && i % frac == 0)\n\t\t\tXuLine(_radars, this, x, y, x2, y2, 6);\n\t\tx2=x; y2=y;\n\t\ti++;\n\t}\n}\n\nvoid Globe::setNewBaseHover(bool hover)\n{\n\t_hover=hover;\n}\n\nvoid Globe::setNewBaseHoverPos(double lon, double lat)\n{\n\t_hoverLon=lon;\n\t_hoverLat=lat;\n}\n\nvoid Globe::drawVHLine(Surface *surface, double lon1, double lat1, double lon2, double lat2, Uint8 color)\n{\n\tdouble sx = lon2 - lon1;\n\tdouble sy = lat2 - lat1;\n\tdouble ln1, lt1, ln2, lt2;\n\tint seg;\n\tSint16 x1, y1, x2, y2;\n\n\tif (sx<0) sx += 2*M_PI;\n\n\tif (fabs(sx)<0.01)\n\t{\n\t\tseg = std::abs(sy/(2*M_PI)*48);\n\t\tif (seg == 0) ++seg;\n\t}\n\telse\n\t{\n\t\tseg = std::abs(sx/(2*M_PI)*96);\n\t\tif (seg == 0) ++seg;\n\t}\n\n\tsx /= seg;\n\tsy /= seg;\n\n\tfor (int i = 0; i < seg; ++i)\n\t{\n\t\tln1 = lon1 + sx*i;\n\t\tlt1 = lat1 + sy*i;\n\t\tln2 = lon1 + sx*(i+1);\n\t\tlt2 = lat1 + sy*(i+1);\n\n\t\tif (!pointBack(ln2, lt2)&&!pointBack(ln1, lt1))\n\t\t{\n\t\t\tpolarToCart(ln1,lt1,&x1,&y1);\n\t\t\tpolarToCart(ln2,lt2,&x2,&y2);\n\t\t\tsurface->drawLine(x1, y1, x2, y2, color);\n\t\t}\n\t}\n}\n\n\n/**\n * Draws the details of the countries on the globe,\n * based on the current zoom level.\n */\nvoid Globe::drawDetail()\n{\n\t_countries->clear();\n\n\tif (!Options::globeDetail)\n\t\treturn;\n\n\t// Draw the country borders\n\tif (_zoom >= 1)\n\t{\n\t\t// Lock the surface\n\t\t_countries->lock();\n\n\t\tfor (auto* polyline : *_rules->getPolylines())\n\t\t{\n\t\t\tSint16 x[2], y[2];\n\t\t\tfor (int j = 0; j < polyline->getPoints() - 1; ++j)\n\t\t\t{\n\t\t\t\t// Don't draw if polyline is facing back\n\t\t\t\tif (pointBack(polyline->getLongitude(j), polyline->getLatitude(j)) || pointBack(polyline->getLongitude(j + 1), polyline->getLatitude(j + 1)))\n\t\t\t\t\tcontinue;\n\n\t\t\t\t// Convert coordinates\n\t\t\t\tpolarToCart(polyline->getLongitude(j), polyline->getLatitude(j), &x[0], &y[0]);\n\t\t\t\tpolarToCart(polyline->getLongitude(j + 1), polyline->getLatitude(j + 1), &x[1], &y[1]);\n\n\t\t\t\t_countries->drawLine(x[0], y[0], x[1], y[1], LINE_COLOR);\n\t\t\t}\n\t\t}\n\n\t\t// Unlock the surface\n\t\t_countries->unlock();\n\t}\n\n\t// Draw the country names\n\tif (_zoom >= 2)\n\t{\n\t\tText *label = new Text(150, 9, 0, 0);\n\t\tlabel->setPalette(getPalette());\n\t\tlabel->initText(_game->getMod()->getFont(\"FONT_BIG\"), _game->getMod()->getFont(\"FONT_SMALL\"), _game->getLanguage());\n\t\tlabel->setAlign(ALIGN_CENTER);\n\n\t\tSint16 x, y;\n\t\tfor (auto* country : *_game->getSavedGame()->getCountries())\n\t\t{\n\t\t\t// Don't draw if label is facing back\n\t\t\tif (pointBack(country->getRules()->getLabelLongitude(), country->getRules()->getLabelLatitude()))\n\t\t\t\tcontinue;\n\n\t\t\t// Convert coordinates\n\t\t\tpolarToCart(country->getRules()->getLabelLongitude(), country->getRules()->getLabelLatitude(), &x, &y);\n\n\t\t\tlabel->setX(x - 75);\n\t\t\tlabel->setY(y);\n\t\t\tlabel->setText(_game->getLanguage()->getString(country->getRules()->getType()));\n\t\t\tlabel->setColor(COUNTRY_LABEL_COLOR);\n\t\t\tif (country->getRules()->getLabelColor() > 0)\n\t\t\t{\n\t\t\t\tlabel->setColor(country->getRules()->getLabelColor());\n\t\t\t}\n\t\t\tlabel->blit(_countries->getSurface());\n\t\t}\n\n\t\tdelete label;\n\t}\n\n\t// Draw extra globe labels\n\t{\n\t\tText *label = new Text(120, 18, 0, 0);\n\t\tlabel->setPalette(getPalette());\n\t\tlabel->initText(_game->getMod()->getFont(\"FONT_BIG\"), _game->getMod()->getFont(\"FONT_SMALL\"), _game->getLanguage());\n\t\tlabel->setAlign(ALIGN_CENTER);\n\n\t\tSint16 x, y;\n\t\tfor (auto& extraLabelType : _game->getMod()->getExtraGlobeLabelsList())\n\t\t{\n\t\t\tRuleCountry *rule = _game->getMod()->getExtraGlobeLabel(extraLabelType, true);\n\t\t\tif ((int)(_zoom) >= rule->getZoomLevel())\n\t\t\t{\n\t\t\t\t// Don't draw if label is facing back\n\t\t\t\tif (pointBack(rule->getLabelLongitude(), rule->getLabelLatitude()))\n\t\t\t\t\tcontinue;\n\n\t\t\t\t// Convert coordinates\n\t\t\t\tpolarToCart(rule->getLabelLongitude(), rule->getLabelLatitude(), &x, &y);\n\n\t\t\t\tlabel->setX(x - 60);\n\t\t\t\tlabel->setY(y);\n\t\t\t\tlabel->setText(_game->getLanguage()->getString(rule->getType()));\n\t\t\t\tlabel->setColor(COUNTRY_LABEL_COLOR);\n\t\t\t\tif (rule->getLabelColor() > 0)\n\t\t\t\t{\n\t\t\t\t\tlabel->setColor(rule->getLabelColor());\n\t\t\t\t}\n\t\t\t\tlabel->blit(_countries->getSurface());\n\t\t\t}\n\t\t}\n\t\tdelete label;\n\t}\n\n\t// Draw the city and base markers\n\tif (_zoom >= 3)\n\t{\n\t\tText *label = new Text(100, 9, 0, 0);\n\t\tlabel->setPalette(getPalette());\n\t\tlabel->initText(_game->getMod()->getFont(\"FONT_BIG\"), _game->getMod()->getFont(\"FONT_SMALL\"), _game->getLanguage());\n\t\tlabel->setAlign(ALIGN_CENTER);\n\t\tlabel->setColor(CITY_LABEL_COLOR);\n\n\t\tSint16 x, y;\n\t\tfor (auto* region : *_game->getSavedGame()->getRegions())\n\t\t{\n\t\t\tfor (auto* city : *region->getRules()->getCities())\n\t\t\t{\n\t\t\t\tdrawTarget(city, _countries);\n\n\t\t\t\t// Don't draw if city is facing back\n\t\t\t\tif (pointBack(city->getLongitude(), city->getLatitude()))\n\t\t\t\t\tcontinue;\n\n\t\t\t\t// Convert coordinates\n\t\t\t\tpolarToCart(city->getLongitude(), city->getLatitude(), &x, &y);\n\n\t\t\t\tlabel->setX(x - 50);\n\t\t\t\tlabel->setY(y + 2);\n\t\t\t\tlabel->setText(city->getName(_game->getLanguage()));\n\t\t\t\tlabel->blit(_countries->getSurface());\n\t\t\t}\n\t\t}\n\t\t// Draw bases names\n\t\tfor (auto* xbase : *_game->getSavedGame()->getBases())\n\t\t{\n\t\t\tif (xbase->getMarker() == -1 || pointBack(xbase->getLongitude(), xbase->getLatitude()))\n\t\t\t\tcontinue;\n\t\t\tpolarToCart(xbase->getLongitude(), xbase->getLatitude(), &x, &y);\n\t\t\tlabel->setX(x - 50);\n\t\t\tlabel->setY(y + 2);\n\t\t\tlabel->setColor(BASE_LABEL_COLOR);\n\t\t\tlabel->setText(xbase->getName());\n\t\t\tlabel->blit(_countries->getSurface());\n\t\t}\n\n\t\tdelete label;\n\t}\n\n\tint& debugType = _game->getSavedGame()->debugType;\n\tstatic bool canSwitchDebugType = false;\n\tif (_game->getSavedGame()->getDebugMode())\n\t{\n\t\tint color;\n\t\tcanSwitchDebugType = true;\n\t\tif (debugType == 0)\n\t\t{\n\t\t\tcolor = 0;\n\t\t\tfor (auto* country : *_game->getSavedGame()->getCountries())\n\t\t\t{\n\t\t\t\tif (_game->getSavedGame()->debugCountry && _game->getSavedGame()->debugCountry != country)\n\t\t\t\t\tcontinue;\n\n\t\t\t\tcolor += 10;\n\t\t\t\tfor (size_t k = 0; k != country->getRules()->getLatMax().size(); ++k)\n\t\t\t\t{\n\t\t\t\t\tdouble lon2 = country->getRules()->getLonMax().at(k);\n\t\t\t\t\tdouble lon1 = country->getRules()->getLonMin().at(k);\n\t\t\t\t\tdouble lat2 = country->getRules()->getLatMax().at(k);\n\t\t\t\t\tdouble lat1 = country->getRules()->getLatMin().at(k);\n\n\t\t\t\t\tdrawVHLine(_countries, lon1, lat1, lon2, lat1, color);\n\t\t\t\t\tdrawVHLine(_countries, lon1, lat2, lon2, lat2, color);\n\t\t\t\t\tdrawVHLine(_countries, lon1, lat1, lon1, lat2, color);\n\t\t\t\t\tdrawVHLine(_countries, lon2, lat1, lon2, lat2, color);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse if (debugType == 1)\n\t\t{\n\t\t\tcolor = 0;\n\t\t\tfor (auto* region : *_game->getSavedGame()->getRegions())\n\t\t\t{\n\t\t\t\tif (_game->getSavedGame()->debugRegion && _game->getSavedGame()->debugRegion != region)\n\t\t\t\t\tcontinue;\n\n\t\t\t\tcolor += 10;\n\t\t\t\tfor (size_t k = 0; k != region->getRules()->getLatMax().size(); ++k)\n\t\t\t\t{\n\t\t\t\t\tdouble lon2 = region->getRules()->getLonMax().at(k);\n\t\t\t\t\tdouble lon1 = region->getRules()->getLonMin().at(k);\n\t\t\t\t\tdouble lat2 = region->getRules()->getLatMax().at(k);\n\t\t\t\t\tdouble lat1 = region->getRules()->getLatMin().at(k);\n\n\t\t\t\t\tdrawVHLine(_countries, lon1, lat1, lon2, lat1, color);\n\t\t\t\t\tdrawVHLine(_countries, lon1, lat2, lon2, lat2, color);\n\t\t\t\t\tdrawVHLine(_countries, lon1, lat1, lon1, lat2, color);\n\t\t\t\t\tdrawVHLine(_countries, lon2, lat1, lon2, lat2, color);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse if (debugType == 2)\n\t\t{\n\t\t\tfor (auto* region : *_game->getSavedGame()->getRegions())\n\t\t\t{\n\t\t\t\tif (_game->getSavedGame()->debugRegion && _game->getSavedGame()->debugRegion != region)\n\t\t\t\t\tcontinue;\n\n\t\t\t\tcolor = -1;\n\t\t\t\tsize_t zoneNumber = 0;\n\t\t\t\tfor (const auto& missionZone : region->getRules()->getMissionZones())\n\t\t\t\t{\n\t\t\t\t\t++zoneNumber;\n\t\t\t\t\tif (_game->getSavedGame()->debugZone > 0 && _game->getSavedGame()->debugZone != zoneNumber)\n\t\t\t\t\t\tcontinue;\n\n\t\t\t\t\tcolor += 2;\n\t\t\t\t\tsize_t areaNumber = 0;\n\t\t\t\t\tfor (const auto& missionArea : missionZone.areas)\n\t\t\t\t\t{\n\t\t\t\t\t\t++areaNumber;\n\t\t\t\t\t\tif (_game->getSavedGame()->debugArea > 0 && _game->getSavedGame()->debugArea != areaNumber)\n\t\t\t\t\t\t\tcontinue;\n\n\t\t\t\t\t\tdouble lon2 = missionArea.lonMax;\n\t\t\t\t\t\tdouble lon1 = missionArea.lonMin;\n\t\t\t\t\t\tdouble lat2 = missionArea.latMax;\n\t\t\t\t\t\tdouble lat1 = missionArea.latMin;\n\n\t\t\t\t\t\tdrawVHLine(_countries, lon1, lat1, lon2, lat1, color);\n\t\t\t\t\t\tdrawVHLine(_countries, lon1, lat2, lon2, lat2, color);\n\t\t\t\t\t\tdrawVHLine(_countries, lon1, lat1, lon1, lat2, color);\n\t\t\t\t\t\tdrawVHLine(_countries, lon2, lat1, lon2, lat2, color);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\tif (canSwitchDebugType)\n\t\t{\n\t\t\t++debugType;\n\t\t\tif (debugType > 2) debugType = 0;\n\t\t\tcanSwitchDebugType = false;\n\t\t}\n\t}\n}\n\nvoid Globe::drawPath(Surface *surface, double lon1, double lat1, double lon2, double lat2)\n{\n\tdouble length;\n\tSint16 count;\n\tdouble x1, y1, x2, y2;\n\tCordPolar p1, p2;\n\tCord a(CordPolar(lon1, lat1));\n\tCord b(CordPolar(lon2, lat2));\n\n\tif (-b == a)\n\t\treturn;\n\n\tb -= a;\n\n\t//longer path have more parts\n\tlength = b.norm();\n\tlength *= length*15;\n\tcount = length + 1;\n\tb /= count;\n\tp1 = CordPolar(a);\n\tpolarToCart(p1.lon, p1.lat, &x1, &y1);\n\tfor (int i = 0; i < count; ++i)\n\t{\n\t\ta += b;\n\t\tp2 = CordPolar(a);\n\t\tpolarToCart(p2.lon, p2.lat, &x2, &y2);\n\n\t\tif (!pointBack(p1.lon, p1.lat) && !pointBack(p2.lon, p2.lat))\n\t\t{\n\t\t\tXuLine(surface, this, x1, y1, x2, y2, 8);\n\t\t}\n\n\t\tp1 = p2;\n\t\tx1 = x2;\n\t\ty1 = y2;\n\t}\n}\n\n/**\n * Draws the flight paths of player craft (and hunting UFOs) flying on the globe.\n */\nvoid Globe::drawFlights()\n{\n\t//_radars->clear();\n\n\tif (!Options::globeFlightPaths)\n\t\treturn;\n\n\t// Lock the surface\n\t_radars->lock();\n\n\t// Draw the craft flight paths\n\tfor (auto* xbase : *_game->getSavedGame()->getBases())\n\t{\n\t\tfor (auto* xcraft : *xbase->getCrafts())\n\t\t{\n\t\t\t// Hide crafts docked at base\n\t\t\tif (xcraft->getStatus() != \"STR_OUT\" || xcraft->getDestination() == 0 /*|| pointBack(xcraft->getLongitude(), xcraft->getLatitude())*/)\n\t\t\t\tcontinue;\n\n\t\t\tdouble lon1 = xcraft->getLongitude();\n\t\t\tdouble lat1 = xcraft->getLatitude();\n\t\t\tdouble lon2 = xcraft->getDestination()->getLongitude();\n\t\t\tdouble lat2 = xcraft->getDestination()->getLatitude();\n\n\t\t\tif (xcraft->isMeetCalculated())\n\t\t\t{\n\t\t\t\tlon2 = xcraft->getMeetLongitude();\n\t\t\t\tlat2 = xcraft->getMeetLatitude();\n\t\t\t}\n\t\t\tdrawPath(_radars, lon1, lat1, lon2, lat2);\n\n\t\t\tif (xcraft->isMeetCalculated())\n\t\t\t{\n\t\t\t\tlon1 = xcraft->getDestination()->getLongitude();\n\t\t\t\tlat1 = xcraft->getDestination()->getLatitude();\n\n\t\t\t\tdrawPath(_radars, lon1, lat1, lon2, lat2);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Draw the hunting UFO flight paths\n\tfor (auto* ufo : *_game->getSavedGame()->getUfos())\n\t{\n\t\tif (ufo->getDestination() && (ufo->isHunting() || _game->getSavedGame()->getDebugMode()) && ufo->getDetected() && ufo->getStatus() != Ufo::IGNORE_ME)\n\t\t{\n\t\t\tdouble lon1 = ufo->getLongitude();\n\t\t\tdouble lon2 = ufo->getDestination()->getLongitude();\n\t\t\tdouble lat1 = ufo->getLatitude();\n\t\t\tdouble lat2 = ufo->getDestination()->getLatitude();\n\n\t\t\tdrawPath(_radars, lon1, lat1, lon2, lat2);\n\t\t}\n\t}\n\n\t// Unlock the surface\n\t_radars->unlock();\n}\n\n/**\n * Draws the marker for a specified target on the globe.\n * @param target Pointer to globe target.\n */\nvoid Globe::drawTarget(Target *target, Surface *surface)\n{\n\tif (target->getMarker() != -1 && !pointBack(target->getLongitude(), target->getLatitude()))\n\t{\n\t\tSint16 x, y;\n\t\tpolarToCart(target->getLongitude(), target->getLatitude(), &x, &y);\n\t\tauto i = target->getMarker();\n\t\tauto marker = _markerSet->getFrame(i);\n\t\tShaderMove<const Uint8> surf{ marker, x - marker->getWidth() / 2, y - marker->getHeight() / 2 };\n\t\tShaderMove<Uint8> dest{ surface };\n\n\t\tif (i == CITY_MARKER || _blink > 0)\n\t\t{\n\t\t\tShaderDrawFunc(\n\t\t\t\t[](Uint8& destStuff, Uint8 srcStuff)\n\t\t\t\t{\n\t\t\t\t\tif (srcStuff)\n\t\t\t\t\t{\n\t\t\t\t\t\tdestStuff = srcStuff;\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tdest,\n\t\t\t\tsurf\n\t\t\t);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tShaderDrawFunc(\n\t\t\t\t[](Uint8& destStuff, Uint8 srcStuff)\n\t\t\t\t{\n\t\t\t\t\tif (srcStuff)\n\t\t\t\t\t{\n\t\t\t\t\t\tdestStuff = srcStuff + 1;\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tdest,\n\t\t\t\tsurf\n\t\t\t);\n\t\t}\n\t}\n}\n\n/**\n * Draws the markers of all the various things going\n * on around the world on top of the globe.\n */\nvoid Globe::drawMarkers()\n{\n\t_markers->clear();\n\t_markers->lock();\n\t// Draw the base markers\n\tfor (auto* xbase : *_game->getSavedGame()->getBases())\n\t{\n\t\tdrawTarget(xbase, _markers);\n\t}\n\n\t// Draw the waypoint markers\n\tfor (auto* wp : *_game->getSavedGame()->getWaypoints())\n\t{\n\t\tdrawTarget(wp, _markers);\n\t}\n\n\t// Draw the mission site markers\n\tfor (auto* site : *_game->getSavedGame()->getMissionSites())\n\t{\n\t\tdrawTarget(site, _markers);\n\t}\n\n\t// Draw the alien base markers\n\tfor (auto* ab : *_game->getSavedGame()->getAlienBases())\n\t{\n\t\tdrawTarget(ab, _markers);\n\t}\n\n\t// Draw the UFO markers\n\tfor (auto* ufo : *_game->getSavedGame()->getUfos())\n\t{\n\t\tif (ufo->getStatus() == Ufo::IGNORE_ME) continue;\n\t\tdrawTarget(ufo, _markers);\n\t}\n\n\t// Draw the craft markers\n\tfor (auto* xbase : *_game->getSavedGame()->getBases())\n\t{\n\t\tfor (auto* xcraft : *xbase->getCrafts())\n\t\t{\n\t\t\tdrawTarget(xcraft, _markers);\n\t\t}\n\t}\n\t_markers->unlock();\n}\n\n/**\n * Blits the globe onto another surface.\n * @param surface Pointer to another surface.\n */\nvoid Globe::blit(SDL_Surface *surface)\n{\n\tSurface::blit(surface);\n\t_radars->blit(surface);\n\t_countries->blit(surface);\n\t_markers->blit(surface);\n}\n\n/**\n * Ignores any mouse hovers that are outside the globe.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid Globe::mouseOver(Action *action, State *state)\n{\n\tdouble lon, lat;\n\tcartToPolar((Sint16)floor(action->getAbsoluteXMouse()), (Sint16)floor(action->getAbsoluteYMouse()), &lon, &lat);\n\n\tif (_isMouseScrolling && action->getDetails()->type == SDL_MOUSEMOTION)\n\t{\n\t\t// The following is the workaround for a rare problem where sometimes\n\t\t// the mouse-release event is missed for any reason.\n\t\t// (checking: is the dragScroll-mouse-button still pressed?)\n\t\t// However if the SDL is also missed the release event, then it is to no avail :(\n\t\tif (0 == (SDL_GetMouseState(0, 0)&SDL_BUTTON(Options::geoDragScrollButton)))\n\t\t{ // so we missed again the mouse-release :(\n\t\t\t// Check if we have to revoke the scrolling, because it was too short in time, so it was a click\n\t\t\tif ((!_mouseMovedOverThreshold) && ((int)(SDL_GetTicks() - _mouseScrollingStartTime) <= (Options::dragScrollTimeTolerance)))\n\t\t\t{\n\t\t\t\tcenter(_lonBeforeMouseScrolling, _latBeforeMouseScrolling);\n\t\t\t}\n\t\t\t_isMouseScrolled = _isMouseScrolling = false;\n\t\t\tstopScrolling(action);\n\t\t\treturn;\n\t\t}\n\n\t\t_isMouseScrolled = true;\n\n\t\tif (Options::touchEnabled == false)\n\t\t{\n\t\t\t// Set the mouse cursor back\n\t\t\tSDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);\n\t\t\tSDL_WarpMouse((_game->getScreen()->getWidth() - 100) / 2 , _game->getScreen()->getHeight() / 2);\n\t\t\tSDL_EventState(SDL_MOUSEMOTION, SDL_ENABLE);\n\t\t}\n\n\t\t// Check the threshold\n\t\t_totalMouseMoveX += action->getDetails()->motion.xrel;\n\t\t_totalMouseMoveY += action->getDetails()->motion.yrel;\n\n\t\tif (!_mouseMovedOverThreshold)\n\t\t\t_mouseMovedOverThreshold = ((std::abs(_totalMouseMoveX) > Options::dragScrollPixelTolerance) || (std::abs(_totalMouseMoveY) > Options::dragScrollPixelTolerance));\n\n\t\t// Scrolling\n\t\tif (Options::geoDragScrollInvert)\n\t\t{\n\t\t\tdouble newLon = ((double)_totalMouseMoveX / action->getXScale()) * ROTATE_LONGITUDE/(_zoom+1)/2;\n\t\t\tdouble newLat = ((double)_totalMouseMoveY / action->getYScale()) * ROTATE_LATITUDE/(_zoom+1)/2;\n\t\t\tcenter(_lonBeforeMouseScrolling + newLon / (Options::geoScrollSpeed / 10), _latBeforeMouseScrolling + newLat / (Options::geoScrollSpeed / 10));\n\t\t}\n\t\telse\n\t\t{\n\t\t\tdouble newLon = -action->getDetails()->motion.xrel * ROTATE_LONGITUDE/(_zoom+1)/2;\n\t\t\tdouble newLat = -action->getDetails()->motion.yrel * ROTATE_LATITUDE/(_zoom+1)/2;\n\t\t\tcenter(_cenLon + newLon / (Options::geoScrollSpeed / 10), _cenLat + newLat / (Options::geoScrollSpeed / 10));\n\t\t}\n\n\t\tif (Options::touchEnabled == false)\n\t\t{\n\t\t\t// We don't want to see the mouse-cursor jumping :)\n\t\t\taction->setMouseAction(_xBeforeMouseScrolling, _yBeforeMouseScrolling, getX(), getY());\n\t\t\taction->getDetails()->motion.x = _xBeforeMouseScrolling; action->getDetails()->motion.y = _yBeforeMouseScrolling;\n\t\t}\n\n\t\t_game->getCursor()->handle(action);\n\t}\n\n\tif (Options::touchEnabled == false &&\n\t\t_isMouseScrolling &&\n\t\t(action->getDetails()->motion.x != _xBeforeMouseScrolling ||\n\t\taction->getDetails()->motion.y != _yBeforeMouseScrolling))\n\t{\n\t\taction->setMouseAction(_xBeforeMouseScrolling, _yBeforeMouseScrolling, getX(), getY());\n\t\taction->getDetails()->motion.x = _xBeforeMouseScrolling; action->getDetails()->motion.y = _yBeforeMouseScrolling;\n\t}\n\t// Check for errors\n\tif (lat == lat && lon == lon)\n\t{\n\t\tInteractiveSurface::mouseOver(action, state);\n\t}\n}\n\n/**\n * Ignores any mouse clicks that are outside the globe.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid Globe::mousePress(Action *action, State *state)\n{\n\tdouble lon, lat;\n\tcartToPolar((Sint16)floor(action->getAbsoluteXMouse()), (Sint16)floor(action->getAbsoluteYMouse()), &lon, &lat);\n\n\tif (action->getDetails()->button.button == Options::geoDragScrollButton)\n\t{\n\t\t_isMouseScrolling = true;\n\t\t_isMouseScrolled = false;\n\t\tSDL_GetMouseState(&_xBeforeMouseScrolling, &_yBeforeMouseScrolling);\n\t\t_lonBeforeMouseScrolling = _cenLon;\n\t\t_latBeforeMouseScrolling = _cenLat;\n\t\t_totalMouseMoveX = 0; _totalMouseMoveY = 0;\n\t\t_mouseMovedOverThreshold = false;\n\t\t_mouseScrollingStartTime = SDL_GetTicks();\n\t}\n\t// Check for errors\n\tif (lat == lat && lon == lon)\n\t{\n\t\tInteractiveSurface::mousePress(action, state);\n\t}\n}\n\n/**\n * Ignores any mouse clicks that are outside the globe.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid Globe::mouseRelease(Action *action, State *state)\n{\n\tdouble lon, lat;\n\tcartToPolar((Sint16)floor(action->getAbsoluteXMouse()), (Sint16)floor(action->getAbsoluteYMouse()), &lon, &lat);\n\tif (action->getDetails()->button.button == Options::geoDragScrollButton)\n\t{\n\t\tstopScrolling(action);\n\t}\n\t// Check for errors\n\tif (lat == lat && lon == lon)\n\t{\n\t\tInteractiveSurface::mouseRelease(action, state);\n\t}\n}\n\n/**\n * Ignores any mouse clicks that are outside the globe\n * and handles globe rotation and zooming.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid Globe::mouseClick(Action *action, State *state)\n{\n\tif (action->getDetails()->button.button == SDL_BUTTON_WHEELUP)\n\t{\n\t\tzoomIn();\n\t}\n\telse if (action->getDetails()->button.button == SDL_BUTTON_WHEELDOWN)\n\t{\n\t\tzoomOut();\n\t}\n\n\tdouble lon, lat;\n\tcartToPolar((Sint16)floor(action->getAbsoluteXMouse()), (Sint16)floor(action->getAbsoluteYMouse()), &lon, &lat);\n\n\t// The following is the workaround for a rare problem where sometimes\n\t// the mouse-release event is missed for any reason.\n\t// However if the SDL is also missed the release event, then it is to no avail :(\n\t// (this part handles the release if it is missed and now an other button is used)\n\tif (_isMouseScrolling)\n\t{\n\t\tif (action->getDetails()->button.button != Options::geoDragScrollButton\n\t\t\t&& 0 == (SDL_GetMouseState(0, 0)&SDL_BUTTON(Options::geoDragScrollButton)))\n\t\t{ // so we missed again the mouse-release :(\n\t\t\t// Check if we have to revoke the scrolling, because it was too short in time, so it was a click\n\t\t\tif ((!_mouseMovedOverThreshold) && ((int)(SDL_GetTicks() - _mouseScrollingStartTime) <= (Options::dragScrollTimeTolerance)))\n\t\t\t{\n\t\t\t\tcenter(_lonBeforeMouseScrolling, _latBeforeMouseScrolling);\n\t\t\t}\n\t\t\t_isMouseScrolled = _isMouseScrolling = false;\n\t\t\tstopScrolling(action);\n\t\t}\n\t}\n\n\t// DragScroll-Button release: release mouse-scroll-mode\n\tif (_isMouseScrolling)\n\t{\n\t\t// While scrolling, other buttons are ineffective\n\t\tif (action->getDetails()->button.button == Options::geoDragScrollButton)\n\t\t{\n\t\t\t_isMouseScrolling = false;\n\t\t\tstopScrolling(action);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn;\n\t\t}\n\t\t// Check if we have to revoke the scrolling, because it was too short in time, so it was a click\n\t\tif ((!_mouseMovedOverThreshold) && ((int)(SDL_GetTicks() - _mouseScrollingStartTime) <= (Options::dragScrollTimeTolerance)))\n\t\t{\n\t\t\t_isMouseScrolled = false;\n\t\t\tstopScrolling(action);\n\t\t\tcenter(_lonBeforeMouseScrolling, _latBeforeMouseScrolling);\n\t\t}\n\t\tif (_isMouseScrolled) return;\n\t}\n\n\t// Check for errors\n\tif (lat == lat && lon == lon)\n\t{\n\t\tInteractiveSurface::mouseClick(action, state);\n\t\tif (action->getDetails()->button.button == SDL_BUTTON_RIGHT)\n\t\t{\n\t\t\tcenter(lon, lat);\n\t\t}\n\t}\n}\n\n/**\n * Handles globe keyboard shortcuts.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid Globe::keyboardPress(Action *action, State *state)\n{\n\tInteractiveSurface::keyboardPress(action, state);\n\tif (action->getDetails()->key.keysym.sym == Options::keyGeoToggleDetail)\n\t{\n\t\ttoggleDetail();\n\t}\n\tif (action->getDetails()->key.keysym.sym == Options::keyGeoToggleRadar)\n\t{\n\t\ttoggleRadarLines();\n\t}\n}\n\n/**\n * Get the polygons texture at a given point\n * @param lon Longitude of the point.\n * @param lat Latitude of the point.\n * @param texture pointer to texture ID returns -1 when polygon not found\n * @param shade pointer to shade\n */\nvoid Globe::getPolygonTextureAndShade(double lon, double lat, int *texture, int *shade) const\n{\n\t///this is shade conversion from 0..31 levels of geoscape to battlescape levels 0..15\n\tint worldshades[32] = {  0, 0, 0, 0, 1, 1, 2, 2,\n\t\t\t\t\t\t\t 3, 3, 4, 4, 5, 5, 6, 6,\n\t\t\t\t\t\t\t 7, 7, 8, 8, 9, 9,10,11,\n\t\t\t\t\t\t\t11,12,12,13,13,14,15,15};\n\n\t*shade = worldshades[ CreateShadow::getShadowValue(Cord(0.,0.,1.), getSunDirection(lon, lat), 0) ];\n\tPolygon *t = getPolygonFromLonLat(lon,lat);\n\t*texture = (t==NULL)? -1 : t->getTexture();\n}\n\n/**\n * Returns the current globe zoom factor.\n * @return Current zoom (0-5).\n */\nsize_t Globe::getZoom() const\n{\n\treturn _zoom;\n}\n\n/*\n * Turns Radar lines on or off.\n */\nvoid Globe::toggleRadarLines()\n{\n\tOptions::globeRadarLines = !Options::globeRadarLines;\n\tdrawRadars();\n}\n\n/*\n * Resizes the geoscape.\n */\nvoid Globe::resize()\n{\n\tSurface *surfaces[4] = {this, _markers, _countries, _radars};\n\tint width = Options::baseXGeoscape - 64;\n\tint height = Options::baseYGeoscape;\n\n\tfor (int i = 0; i < 4; ++i)\n\t{\n\t\tsurfaces[i]->setWidth(width);\n\t\tsurfaces[i]->setHeight(height);\n\t\tsurfaces[i]->invalidate();\n\t}\n\t_clipper->Wxrig = width;\n\t_clipper->Wybot = height;\n\t_cenX = width / 2;\n\t_cenY = height / 2;\n\tsetupRadii(width, height);\n\tinvalidate();\n}\n\n/*\n * Set up the Radius of earth at the various zoom levels.\n * @param width the new width of the globe.\n * @param height the new height of the globe.\n */\nvoid Globe::setupRadii(int width, int height)\n{\n\t_zoomRadius.clear();\n\n\t_zoomRadius.push_back(0.45*height);\n\t_zoomRadius.push_back(0.60*height);\n\t_zoomRadius.push_back(0.90*height);\n\t_zoomRadius.push_back(1.40*height);\n\t_zoomRadius.push_back(2.25*height);\n\t_zoomRadius.push_back(3.60*height);\n\n\t_radius = _zoomRadius[_zoom];\n\t_radiusStep = (_zoomRadius[DOGFIGHT_ZOOM] - _zoomRadius[0]) / 10.0;\n\n\tif (Options::globeSurfaceCache)\n\t{\n\t\t_earthData.resize(_zoomRadius.size());\n\t\t//filling normal field for each radius\n\n\t\tfor (size_t r = 0; r<_zoomRadius.size(); ++r)\n\t\t{\n\t\t\t_earthData[r].resize(width * height);\n\t\t\tfor (int j=0; j<height; ++j)\n\t\t\t\tfor (int i=0; i<width; ++i)\n\t\t\t\t{\n\t\t\t\t\t_earthData[r][width*j + i] = static_data.circle_norm(width/2, height/2, _zoomRadius[r], i+.5, j+.5);\n\t\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\t_earthData.clear();\n\t}\n}\n\n/**\n * Move the mouse back to where it started after we finish drag scrolling.\n * @param action Pointer to an action.\n */\nvoid Globe::stopScrolling(Action *action)\n{\n\tSDL_WarpMouse(_xBeforeMouseScrolling, _yBeforeMouseScrolling);\n\taction->setMouseAction(_xBeforeMouseScrolling, _yBeforeMouseScrolling, getX(), getY());\n}\n\nvoid Globe::setCraftRange(double lon, double lat, double range)\n{\n\t_craft = (range > 0.0);\n\t_craftLon = lon;\n\t_craftLat = lat;\n\t_craftRange = range;\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/Globe.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <vector>\n#include <list>\n#include \"../Engine/InteractiveSurface.h\"\n#include \"../Engine/FastLineClip.h\"\n#include \"Cord.h\"\n\nnamespace OpenXcom\n{\n\nclass Game;\nclass Polygon;\nclass SurfaceSet;\nclass Timer;\nclass Target;\nclass LocalizedText;\nclass RuleGlobe;\nclass Craft;\n\n/**\n * Interactive globe view of the world.\n * Takes a flat world map made out of land polygons with\n * polar coordinates and renders it as a 3D-looking globe\n * with cartesian coordinates that the player can interact with.\n */\nclass Globe : public InteractiveSurface\n{\nprivate:\n\tstatic const int NUM_LANDSHADES = 48;\n\tstatic const int NUM_SEASHADES = 72;\n\tstatic const int NEAR_RADIUS = 25;\n\tstatic const int MAX_DRAW_RADAR_CIRCLE_RADIUS = 10000;\n\tstatic const size_t DOGFIGHT_ZOOM = 3;\n\tstatic const int CITY_MARKER = 8;\n\tstatic const double ROTATE_LONGITUDE;\n\tstatic const double ROTATE_LATITUDE;\n\n\tRuleGlobe *_rules;\n\tSint16 _cenX, _cenY;\n\tdouble _cenLon, _cenLat, _rotLon, _rotLat, _hoverLon, _hoverLat;\n\tdouble _craftLon, _craftLat, _craftRange;\n\tsize_t _zoom, _zoomOld, _zoomTexture;\n\tSurfaceSet *_texture, *_markerSet;\n\tGame *_game;\n\tSurface *_markers, *_countries, *_radars;\n\tbool _hover, _craft;\n\tint _blink;\n\tTimer *_blinkTimer, *_rotTimer;\n\tstd::list<Polygon*> _cacheLand;\n\tFastLineClip *_clipper;\n\tdouble _radius, _radiusStep;\n\t///normal of each pixel in earth globe per zoom level\n\tstd::vector<std::vector<Cord> > _earthData;\n\t///list of dimension of earth on screen per zoom level\n\tstd::vector<double> _zoomRadius;\n\n\tbool _isMouseScrolling, _isMouseScrolled;\n\tint _xBeforeMouseScrolling, _yBeforeMouseScrolling;\n\tdouble _lonBeforeMouseScrolling, _latBeforeMouseScrolling;\n\tUint32 _mouseScrollingStartTime;\n\tint _totalMouseMoveX, _totalMouseMoveY;\n\tbool _mouseMovedOverThreshold;\n\n\t/// Sets the globe zoom factor.\n\tvoid setZoom(size_t zoom);\n\t/// Checks if a point is behind the globe.\n\tbool pointBack(double lon, double lat) const;\n\t/// Get polygon pointer\n\tPolygon* getPolygonFromLonLat(double lon, double lat) const;\n\t/// Checks if a target is near a point.\n\tbool targetNear(Target* target, int x, int y) const;\n\t/// Caches a set of polygons.\n\tvoid cache(std::list<Polygon*> *polygons, std::list<Polygon*> *cache);\n\t/// Get position of sun relative to given position in polar cords and date.\n\tCord getSunDirection(double lon, double lat) const;\n\t/// Draw globe range circle.\n\tvoid drawGlobeCircle(double lat, double lon, double radius, int segments, int frac = 1);\n\t/// Special \"transparent\" line.\n\tvoid XuLine(Surface* surface, Surface* src, double x1, double y1, double x2, double y2, int shade);\n\t/// Draw line on globe surface.\n\tvoid drawVHLine(Surface *surface, double lon1, double lat1, double lon2, double lat2, Uint8 color);\n\t/// Draw flight path.\n\tvoid drawPath(Surface *surface, double lon1, double lat1, double lon2, double lat2);\n\t/// Draw target marker.\n\tvoid drawTarget(Target *target, Surface *surface);\n\t/// Set up the radius of earth and stuff.\n\tvoid setupRadii(int width, int height);\npublic:\n\tstatic Uint8 OCEAN_COLOR;\n\tstatic bool OCEAN_SHADING;\n\tstatic Uint8 COUNTRY_LABEL_COLOR;\n\tstatic Uint8 LINE_COLOR;\n\tstatic Uint8 CITY_LABEL_COLOR;\n\tstatic Uint8 BASE_LABEL_COLOR;\n\n\t/// Creates a new globe at the specified position and size.\n\tGlobe(Game* game, int cenX, int cenY, int width, int height, int x = 0, int y = 0);\n\t/// Cleans up the globe.\n\t~Globe();\n\t/// Converts polar coordinates to cartesian coordinates.\n\tvoid polarToCart(double lon, double lat, Sint16 *x, Sint16 *y) const;\n\t/// Converts polar coordinates to cartesian coordinates.\n\tvoid polarToCart(double lon, double lat, double *x, double *y) const;\n\t/// Converts cartesian coordinates to polar coordinates.\n\tvoid cartToPolar(Sint16 x, Sint16 y, double *lon, double *lat) const;\n\t/// Starts rotating the globe left.\n\tvoid rotateLeft();\n\t/// Starts rotating the globe right.\n\tvoid rotateRight();\n\t/// Starts rotating the globe up.\n\tvoid rotateUp();\n\t/// Starts rotating the globe down.\n\tvoid rotateDown();\n\t/// Stops rotating the globe.\n\tvoid rotateStop();\n\t/// Stops longitude rotation of the globe.\n\tvoid rotateStopLon();\n\t/// Stops latitude rotation of the globe.\n\tvoid rotateStopLat();\n\t/// Zooms the globe in.\n\tvoid zoomIn();\n\t/// Zooms the globe out.\n\tvoid zoomOut();\n\t/// Zooms the globe minimum.\n\tvoid zoomMin();\n\t/// Zooms the globe maximum.\n\tvoid zoomMax();\n\t/// Saves the zoom level for dogfights.\n\tvoid saveZoomDogfight();\n\t/// Zooms the globe in for dogfights.\n\tbool zoomDogfightIn();\n\t/// Zooms the globe out for dogfights.\n\tbool zoomDogfightOut();\n\t/// Gets the current zoom.\n\tsize_t getZoom() const;\n\t/// Centers the globe on a point.\n\tvoid center(double lon, double lat);\n\t/// Checks if a point is inside land.\n\tbool insideLand(double lon, double lat) const;\n\t/// Checks if a point is inside fakeUnderwater texture.\n\tbool insideFakeUnderwaterTexture(double lon, double lat) const;\n\t/// Turns on/off the globe detail.\n\tvoid toggleDetail();\n\t/// Gets all the targets near a point on the globe.\n\tstd::vector<Target*> getTargets(int x, int y, bool craft, Craft *currentCraft) const;\n\t/// Caches visible globe polygons.\n\tvoid cachePolygons();\n\t/// Sets the palette of the globe.\n\tvoid setPalette(const SDL_Color *colors, int firstcolor = 0, int ncolors = 256) override;\n\t/// Handles the timers.\n\tvoid think() override;\n\t/// Blinks the markers.\n\tvoid blink();\n\t/// Rotates the globe.\n\tvoid rotate();\n\t/// Draws the whole globe.\n\tvoid draw() override;\n\t/// Draws the ocean of the globe.\n\tvoid drawOcean();\n\t/// Draws the land of the globe.\n\tvoid drawLand();\n\t/// Draws the shadow.\n\tvoid drawShadow();\n\t/// Draws the radar ranges of the globe.\n\tvoid drawRadars();\n\t/// Draws the flight paths of the globe.\n\tvoid drawFlights();\n\t/// Draws the country details of the globe.\n\tvoid drawDetail();\n\t/// Draws all the markers over the globe.\n\tvoid drawMarkers();\n\t/// Blits the globe onto another surface.\n\tvoid blit(SDL_Surface *surface) override;\n\t/// Special handling for mouse hover.\n\tvoid mouseOver(Action *action, State *state) override;\n\t/// Special handling for mouse presses.\n\tvoid mousePress(Action *action, State *state) override;\n\t/// Special handling for mouse releases.\n\tvoid mouseRelease(Action *action, State *state) override;\n\t/// Special handling for mouse clicks.\n\tvoid mouseClick(Action *action, State *state) override;\n\t/// Special handling for key presses.\n\tvoid keyboardPress(Action *action, State *state) override;\n\t/// Get the polygons texture and shade at the given point.\n\tvoid getPolygonTextureAndShade(double lon, double lat, int *texture, int *shade) const;\n\t/// Sets hover base position.\n\tvoid setNewBaseHoverPos(double lon, double lat);\n\t/// Turns on new base hover mode.\n\tvoid setNewBaseHover(bool hover);\n\t/// Sets craft range mode.\n\tvoid setCraftRange(double lon, double lat, double range);\n\t/// set the _radarLines variable\n\tvoid toggleRadarLines();\n\t/// Update the resolution settings, we just resized the window.\n\tvoid resize();\n\t/// Move the mouse back to where it started after we finish drag scrolling.\n\tvoid stopScrolling(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/GraphsState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"GraphsState.h\"\n#include <sstream>\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/Palette.h\"\n#include \"../Engine/Surface.h\"\n#include \"../Engine/InteractiveSurface.h\"\n#include \"../Savegame/Country.h\"\n#include \"../Savegame/Region.h\"\n#include \"../Mod/RuleCountry.h\"\n#include \"../Mod/RuleRegion.h\"\n#include \"../Interface/Text.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/ToggleTextButton.h\"\n#include \"../Savegame/GameTime.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Mod/RuleInterface.h\"\n\nnamespace OpenXcom\n{\n\nstruct GraphButInfo\n{\n\tLocalizedText _name;\n\tint _color;\n\tbool _pushed;\n\tGraphButInfo(const LocalizedText& name, Uint8 color): _name(name), _color(color), _pushed(false) {}\n};\n/**\n * Initializes all the elements in the Graphs screen.\n * @param game Pointer to the core game.\n */\nGraphsState::GraphsState() : _butRegionsOffset(0), _butCountriesOffset(0), _zoom(100)\n{\n\t// Create object\n\t_bg = new InteractiveSurface(320, 200, 0, 0);\n\t_bg->onMousePress((ActionHandler)&GraphsState::shiftButtons, SDL_BUTTON_WHEELUP);\n\t_bg->onMousePress((ActionHandler)&GraphsState::shiftButtons, SDL_BUTTON_WHEELDOWN);\n\t_btnUfoRegion = new InteractiveSurface(32, 24, 96, 0);\n\t_btnUfoCountry = new InteractiveSurface(32, 24, 128, 0);\n\t_btnXcomRegion = new InteractiveSurface(32, 24, 160, 0);\n\t_btnXcomCountry = new InteractiveSurface(32, 24, 192, 0);\n\t_btnIncome = new InteractiveSurface(32, 24, 224, 0);\n\t_btnFinance = new InteractiveSurface(32, 24, 256, 0);\n\t_btnGeoscape = new InteractiveSurface(32, 24, 288, 0);\n\t_txtTitle = new Text(230, 16, 90, 28);\n\t_txtFactor = new Text(38, 11, 96, 28);\n\t_txtMonths = new TextList(205, 8, 115, 183);\n\t_txtYears = new TextList(200, 8, 121, 191);\n\n\t// Set palette\n\tsetInterface(\"graphs\");\n\n\t//add all our element\n\tadd(_bg);\n\tadd(_btnUfoRegion);\n\tadd(_btnUfoCountry);\n\tadd(_btnXcomRegion);\n\tadd(_btnXcomCountry);\n\tadd(_btnIncome);\n\tadd(_btnFinance);\n\tadd(_btnGeoscape);\n\tadd(_txtMonths, \"scale\", \"graphs\");\n\tadd(_txtYears, \"scale\", \"graphs\");\n\tadd(_txtTitle, \"text\", \"graphs\");\n\tadd(_txtFactor, \"text\", \"graphs\");\n\tfor (int scaleText = 0; scaleText != 10; ++scaleText)\n\t{\n\t\t_txtScale.push_back(new Text(42, 16, 80, 171 - (scaleText*14)));\n\t\tadd(_txtScale.at(scaleText), \"scale\", \"graphs\");\n\t}\n\tUint8 regionTotalColor = _game->getMod()->getInterface(\"graphs\")->getElement(\"regionTotal\")->color;\n\tUint8 countryTotalColor = _game->getMod()->getInterface(\"graphs\")->getElement(\"countryTotal\")->color;\n\n\t//create buttons (sooooo many buttons)\n\tsize_t offset = 0;\n\tfor (auto* region : *_game->getSavedGame()->getRegions())\n\t{\n\t\t// always save in toggles all the region\n\t\tUint8 color = 13 + 8 * (offset % GRAPH_MAX_BUTTONS);\n\t\t_regionToggles.push_back(new GraphButInfo(tr(region->getRules()->getType()), color));\n\t\t// initially add the GRAPH_MAX_BUTTONS having the first regions information\n\t\tif (offset < GRAPH_MAX_BUTTONS)\n\t\t{\n\t\t\t_btnRegions.push_back(new ToggleTextButton(88, 11, 0, offset*11));\n\t\t\t_btnRegions.at(offset)->setText(tr(region->getRules()->getType()));\n\t\t\t_btnRegions.at(offset)->setInvertColor(color);\n\t\t\t_btnRegions.at(offset)->onMousePress((ActionHandler)&GraphsState::btnRegionListClick);\n\t\t\tadd(_btnRegions.at(offset), \"button\", \"graphs\");\n\t\t}\n\t\t_alienRegionLines.push_back(new Surface(320,200,0,0));\n\t\tadd(_alienRegionLines.at(offset));\n\t\t_xcomRegionLines.push_back(new Surface(320,200,0,0));\n\t\tadd(_xcomRegionLines.at(offset));\n\n\t\t++offset;\n\t}\n\n\tif (_regionToggles.size() < GRAPH_MAX_BUTTONS)\n\t\t_btnRegionTotal = new ToggleTextButton(88, 11, 0, _regionToggles.size()*11);\n\telse\n\t\t_btnRegionTotal = new ToggleTextButton(88, 11, 0, GRAPH_MAX_BUTTONS*11);\n\t_regionToggles.push_back(new GraphButInfo(tr(\"STR_TOTAL_UC\"), regionTotalColor));\n\t_btnRegionTotal->onMousePress((ActionHandler)&GraphsState::btnRegionListClick);\n\t_btnRegionTotal->setInvertColor(regionTotalColor);\n\t_btnRegionTotal->setText(tr(\"STR_TOTAL_UC\"));\n\t_alienRegionLines.push_back(new Surface(320,200,0,0));\n\tadd(_alienRegionLines.at(offset));\n\t_xcomRegionLines.push_back(new Surface(320,200,0,0));\n\tadd(_xcomRegionLines.at(offset));\n\tadd(_btnRegionTotal, \"button\", \"graphs\");\n\n\toffset = 0;\n\tfor (auto* country : *_game->getSavedGame()->getCountries())\n\t{\n\t\t// always save in toggles all the countries\n\t\tUint8 color = 13 + 8 * (offset % GRAPH_MAX_BUTTONS);\n\t\t_countryToggles.push_back(new GraphButInfo(tr(country->getRules()->getType()), color));\n\t\t// initially add the GRAPH_MAX_BUTTONS having the first countries information\n\t\tif (offset < GRAPH_MAX_BUTTONS)\n\t\t{\n\t\t\t_btnCountries.push_back(new ToggleTextButton(88, 11, 0, offset*11));\n\t\t\t_btnCountries.at(offset)->setInvertColor(color);\n\t\t\t_btnCountries.at(offset)->setText(tr(country->getRules()->getType()));\n\t\t\t_btnCountries.at(offset)->onMousePress((ActionHandler)&GraphsState::btnCountryListClick);\n\t\t\tadd(_btnCountries.at(offset), \"button\", \"graphs\");\n\t\t}\n\t\t_alienCountryLines.push_back(new Surface(320,200,0,0));\n\t\tadd(_alienCountryLines.at(offset));\n\t\t_xcomCountryLines.push_back(new Surface(320,200,0,0));\n\t\tadd(_xcomCountryLines.at(offset));\n\t\t_incomeLines.push_back(new Surface(320,200,0,0));\n\t\tadd(_incomeLines.at(offset));\n\n\t\t++offset;\n\t}\n\n\tif (_countryToggles.size() < GRAPH_MAX_BUTTONS)\n\t\t_btnCountryTotal = new ToggleTextButton(88, 11, 0, _countryToggles.size()*11);\n\telse\n\t\t_btnCountryTotal = new ToggleTextButton(88, 11, 0, GRAPH_MAX_BUTTONS*11);\n\t_countryToggles.push_back(new GraphButInfo(tr(\"STR_TOTAL_UC\"), countryTotalColor));\n\t_btnCountryTotal->onMousePress((ActionHandler)&GraphsState::btnCountryListClick);\n\t_btnCountryTotal->setInvertColor(countryTotalColor);\n\t_btnCountryTotal->setText(tr(\"STR_TOTAL_UC\"));\n\t_alienCountryLines.push_back(new Surface(320,200,0,0));\n\tadd(_alienCountryLines.at(offset));\n\t_xcomCountryLines.push_back(new Surface(320,200,0,0));\n\tadd(_xcomCountryLines.at(offset));\n\t_incomeLines.push_back(new Surface(320,200,0,0));\n\tadd(_incomeLines.at(offset));\n\tadd(_btnCountryTotal, \"button\", \"graphs\");\n\n\n\tfor (int iter = 0; iter != 5; ++iter)\n\t{\n\t\toffset = iter;\n\t\t_btnFinances.push_back(new ToggleTextButton(88, 11, 0, offset*11));\n\t\t_financeToggles.push_back(false);\n\t\t_btnFinances.at(offset)->setInvertColor(13 + (8*offset));\n\t\t_btnFinances.at(offset)->onMousePress((ActionHandler)&GraphsState::btnFinanceListClick);\n\t\tadd(_btnFinances.at(offset), \"button\", \"graphs\");\n\t\t_financeLines.push_back(new Surface(320,200,0,0));\n\t\tadd(_financeLines.at(offset));\n\t}\n\n\t_btnFinances.at(0)->setText(tr(\"STR_INCOME\"));\n\t_btnFinances.at(1)->setText(tr(\"STR_EXPENDITURE\"));\n\t_btnFinances.at(2)->setText(tr(\"STR_MAINTENANCE\"));\n\t_btnFinances.at(3)->setText(tr(\"STR_BALANCE\"));\n\t_btnFinances.at(4)->setText(tr(\"STR_SCORE\"));\n\n\t// load back the button state\n\tstd::string graphRegionToggles = _game->getSavedGame()->getGraphRegionToggles();\n\tstd::string graphCountryToggles = _game->getSavedGame()->getGraphCountryToggles();\n\tstd::string graphFinanceToggles = _game->getSavedGame()->getGraphFinanceToggles();\n\twhile (graphRegionToggles.size() < _regionToggles.size()) graphRegionToggles.push_back('0');\n\twhile (graphCountryToggles.size() < _countryToggles.size()) graphCountryToggles.push_back('0');\n\twhile (graphFinanceToggles.size() < _financeToggles.size()) graphFinanceToggles.push_back('0');\n\tfor (size_t i = 0; i < _regionToggles.size(); ++i)\n\t{\n\t\t_regionToggles[i]->_pushed = ('0'==graphRegionToggles[i]) ? false : true;\n\t\tif (_regionToggles.size()-1 == i)\n\t\t\t_btnRegionTotal->setPressed(_regionToggles[i]->_pushed);\n\t\telse if (i < GRAPH_MAX_BUTTONS)\n\t\t\t_btnRegions.at(i)->setPressed(_regionToggles[i]->_pushed);\n\t}\n\tfor (size_t i = 0; i < _countryToggles.size(); ++i)\n\t{\n\t\t_countryToggles[i]->_pushed = ('0'==graphCountryToggles[i]) ? false : true;\n\t\tif (_countryToggles.size()-1 == i)\n\t\t\t_btnCountryTotal->setPressed(_countryToggles[i]->_pushed);\n\t\telse if (i < GRAPH_MAX_BUTTONS)\n\t\t\t_btnCountries.at(i)->setPressed(_countryToggles[i]->_pushed);\n\t}\n\tfor (size_t i = 0; i < _financeToggles.size(); ++i)\n\t{\n\t\t_financeToggles[i] = ('0'==graphFinanceToggles[i]) ? false : true;\n\t\t_btnFinances.at(i)->setPressed(_financeToggles[i]);\n\t}\n\tUint8 gridColor = _game->getMod()->getInterface(\"graphs\")->getElement(\"graph\")->color;\n\t// set up the grid\n\t_bg->drawRect(125, 49, 188, 127, gridColor);\n\n\tfor (int grid = 0; grid !=5; ++grid)\n\t{\n\t\tfor (int y = 50 + grid; y <= 163 + grid; y += 14)\n\t\t{\n\t\t\tfor (int x = 126 + grid; x <= 297 + grid; x += 17)\n\t\t\t{\n\t\t\t\tUint8 color = gridColor + grid + 1;\n\t\t\t\tif (grid == 4)\n\t\t\t\t{\n\t\t\t\t\tcolor = 0;\n\t\t\t\t}\n\t\t\t\t_bg->drawRect(x, y, 16 - (grid*2), 13 - (grid*2), color);\n\t\t\t}\n\t\t}\n\t}\n\n\t//set up the horizontal measurement unit\n\tstd::string months[] = {\"STR_JAN\", \"STR_FEB\", \"STR_MAR\", \"STR_APR\", \"STR_MAY\", \"STR_JUN\", \"STR_JUL\", \"STR_AUG\", \"STR_SEP\", \"STR_OCT\", \"STR_NOV\", \"STR_DEC\"};\n\tint month = _game->getSavedGame()->getTime()->getMonth();\n\t// i know using textlist for this is ugly and brutal, but YOU try getting this damn text to line up.\n\t// also, there's nothing wrong with being ugly or brutal, you should learn tolerance.\n\t_txtMonths->setColumns(12, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17);\n\t_txtMonths->addRow(12, \" \", \" \", \" \", \" \", \" \", \" \", \" \", \" \", \" \", \" \", \" \", \" \");\n\t_txtYears->setColumns(6, 34, 34, 34, 34, 34, 34);\n\t_txtYears->addRow(6, \" \", \" \", \" \", \" \", \" \", \" \");\n\n\tfor (int iter = 0; iter != 12; ++iter)\n\t{\n\t\tif (month > 11)\n\t\t{\n\t\t\tmonth = 0;\n\t\t\tstd::ostringstream ss;\n\t\t\tss << _game->getSavedGame()->getTime()->getYear();\n\t\t\t_txtYears->setCellText(0, iter/2, ss.str());\n\t\t\tif (iter > 2)\n\t\t\t{\n\t\t\t\tstd::ostringstream ss2;\n\t\t\t\tss2 << (_game->getSavedGame()->getTime()->getYear()-1);\n\t\t\t\t_txtYears->setCellText(0, 0, ss2.str());\n\t\t\t}\n\t\t}\n\t\t_txtMonths->setCellText(0, iter, tr(months[month]));\n\t\t++month;\n\t}\n\n\t// set up the vertical measurement unit\n\tfor (auto* scaleText : _txtScale)\n\t{\n\t\tscaleText->setAlign(ALIGN_RIGHT);\n\t}\n\tbtnUfoRegionClick(0);\n\n\t// Set up object\n\tif (_game->getMod()->getSurface(\"GRAPH.BDY\", false))\n\t{\n\t\t_game->getMod()->getSurface(\"GRAPH.BDY\")->blitNShade(_bg, 0, 0);\n\t}\n\telse\n\t{\n\t\t_game->getMod()->getSurface(\"GRAPHS.SPK\")->blitNShade(_bg, 0, 0);\n\t}\n\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\n\t_txtFactor->setText(tr(\"STR_FINANCE_THOUSANDS\"));\n\n\t// Set up buttons\n\t_btnUfoRegion->onMousePress((ActionHandler)&GraphsState::btnUfoRegionClick);\n\t_btnUfoCountry->onMousePress((ActionHandler)&GraphsState::btnUfoCountryClick);\n\t_btnXcomRegion->onMousePress((ActionHandler)&GraphsState::btnXcomRegionClick);\n\t_btnXcomCountry->onMousePress((ActionHandler)&GraphsState::btnXcomCountryClick);\n\t_btnIncome->onMousePress((ActionHandler)&GraphsState::btnIncomeClick);\n\t_btnFinance->onMousePress((ActionHandler)&GraphsState::btnFinanceClick);\n\t_btnGeoscape->onMousePress((ActionHandler)&GraphsState::btnGeoscapeClick);\n\t_btnGeoscape->onKeyboardPress((ActionHandler)&GraphsState::btnGeoscapeClick, Options::keyCancel);\n\t_btnGeoscape->onKeyboardPress((ActionHandler)&GraphsState::btnGeoscapeClick, Options::keyGeoGraphs);\n\t_btnGeoscape->onKeyboardPress((ActionHandler)&GraphsState::btnZoomInClick, Options::keyGraphsZoomIn);\n\t_btnGeoscape->onKeyboardPress((ActionHandler)&GraphsState::btnZoomOutClick, Options::keyGraphsZoomOut);\n\n\tcenterAllSurfaces();\n}\n\n/**\n *\n */\nGraphsState::~GraphsState()\n{\n\tstd::string graphRegionToggles;\n\tstd::string graphCountryToggles;\n\tstd::string graphFinanceToggles;\n\tfor (size_t i = 0; i < _regionToggles.size(); ++i)\n\t{\n\t\tgraphRegionToggles.push_back(_regionToggles[i]->_pushed ? '1' : '0');\n\t\tdelete _regionToggles[i];\n\t}\n\tfor (size_t i = 0; i < _countryToggles.size(); ++i)\n\t{\n\t\tgraphCountryToggles.push_back(_countryToggles[i]->_pushed ? '1' : '0');\n\t\tdelete _countryToggles[i];\n\t}\n\tfor (size_t i = 0; i < _financeToggles.size(); ++i)\n\t{\n\t\tgraphFinanceToggles.push_back(_financeToggles[i] ? '1' : '0');\n\t}\n\t_game->getSavedGame()->setGraphRegionToggles(graphRegionToggles);\n\t_game->getSavedGame()->setGraphCountryToggles(graphCountryToggles);\n\t_game->getSavedGame()->setGraphFinanceToggles(graphFinanceToggles);\n}\n\n/**\n* Zooms in.\n* @param action Pointer to an action.\n*/\nvoid GraphsState::btnZoomInClick(Action *)\n{\n\t_zoom = _zoom * 2 / 3;\n\tif (_zoom < 5) _zoom = 5;\n\n\tdrawLines();\n}\n\n/**\n* Zooms out.\n* @param action Pointer to an action.\n*/\nvoid GraphsState::btnZoomOutClick(Action *)\n{\n\t_zoom = _zoom * 3 / 2;\n\tif (_zoom > 100) _zoom = 100;\n\n\tdrawLines();\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid GraphsState::btnGeoscapeClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Switches to the UFO Region Activity screen.\n * @param action Pointer to an action.\n */\nvoid GraphsState::btnUfoRegionClick(Action *)\n{\n\t_alien = true;\n\t_income = false;\n\t_country = false;\n\t_finance = false;\n\tresetScreen();\n\tdrawLines();\n\tfor (auto* toggleButton : _btnRegions)\n\t{\n\t\ttoggleButton->setVisible(true);\n\t}\n\t_btnRegionTotal->setVisible(true);\n\t_txtTitle->setBig();\n\t_txtTitle->setText(tr(\"STR_UFO_ACTIVITY_IN_AREAS\"));\n}\n\n/**\n * Switches to the UFO Country activity screen.\n * @param action Pointer to an action.\n */\nvoid GraphsState::btnUfoCountryClick(Action *)\n{\n\t_alien = true;\n\t_income = false;\n\t_country = true;\n\t_finance = false;\n\tresetScreen();\n\tdrawLines();\n\tfor (auto* toggleButton : _btnCountries)\n\t{\n\t\ttoggleButton->setVisible(true);\n\t}\n\t_btnCountryTotal->setVisible(true);\n\t_txtTitle->setBig();\n\t_txtTitle->setText(tr(\"STR_UFO_ACTIVITY_IN_COUNTRIES\"));\n}\n\n/**\n * Switches to the XCom Region activity screen.\n * @param action Pointer to an action.\n */\nvoid GraphsState::btnXcomRegionClick(Action *)\n{\n\t_alien = false;\n\t_income = false;\n\t_country = false;\n\t_finance = false;\n\tresetScreen();\n\tdrawLines();\n\tfor (auto* toggleButton : _btnRegions)\n\t{\n\t\ttoggleButton->setVisible(true);\n\t}\n\t_btnRegionTotal->setVisible(true);\n\t_txtTitle->setBig();\n\t_txtTitle->setText(tr(\"STR_XCOM_ACTIVITY_IN_AREAS\"));\n}\n\n/**\n * Switches to the XCom Country activity screen.\n * @param action Pointer to an action.\n */\nvoid GraphsState::btnXcomCountryClick(Action *)\n{\n\t_alien = false;\n\t_income = false;\n\t_country = true;\n\t_finance = false;\n\tresetScreen();\n\tdrawLines();\n\tfor (auto* toggleButton : _btnCountries)\n\t{\n\t\ttoggleButton->setVisible(true);\n\t}\n\t_btnCountryTotal->setVisible(true);\n\t_txtTitle->setBig();\n\t_txtTitle->setText(tr(\"STR_XCOM_ACTIVITY_IN_COUNTRIES\"));\n}\n\n/**\n * Switches to the Income screen.\n * @param action Pointer to an action.\n */\nvoid GraphsState::btnIncomeClick(Action *)\n{\n\t_alien = false;\n\t_income = true;\n\t_country = true;\n\t_finance = false;\n\tresetScreen();\n\tdrawLines();\n\t_txtFactor->setVisible(true);\n\tfor (auto* toggleButton : _btnCountries)\n\t{\n\t\ttoggleButton->setVisible(true);\n\t}\n\t_btnCountryTotal->setVisible(true);\n\t_txtTitle->setBig();\n\t_txtTitle->setText(tr(\"STR_INCOME\"));\n}\n\n/**\n * Switches to the Finances screen.\n * @param action Pointer to an action.\n */\nvoid GraphsState::btnFinanceClick(Action *)\n{\n\t_alien = false;\n\t_income = false;\n\t_country = false;\n\t_finance = true;\n\tresetScreen();\n\tdrawLines();\n\n\tfor (auto* toggleButton : _btnFinances)\n\t{\n\t\ttoggleButton->setVisible(true);\n\t}\n\t_txtTitle->setBig();\n\t_txtTitle->setText(tr(\"STR_FINANCE\"));\n\n}\n\n/**\n * Handles a click on a region button.\n * @param action Pointer to an action.\n */\nvoid GraphsState::btnRegionListClick(Action * action)\n{\n\tsize_t number = 0;\n\tToggleTextButton *button = dynamic_cast<ToggleTextButton*>(action->getSender());\n\n\tif (action->getDetails()->button.button == SDL_BUTTON_RIGHT)\n\t{\n\t\tfor (size_t i = 0; i < _btnRegions.size(); ++i)\n\t\t{\n\t\t\tif (button != _btnRegions[i])\n\t\t\t{\n\t\t\t\t_btnRegions[i]->setPressed(button->getPressed());\n\t\t\t}\n\t\t}\n\t\t_btnRegionTotal->setPressed(button->getPressed());\n\t\tfor (auto* gbi : _regionToggles)\n\t\t{\n\t\t\tgbi->_pushed = button->getPressed();\n\t\t}\n\t}\n\telse\n\t{\n\t\tif (button == _btnRegionTotal)\n\t\t{\n\t\t\tnumber = _regionToggles.size() - 1;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tfor (size_t i = 0; i < _btnRegions.size(); ++i)\n\t\t\t{\n\t\t\t\tif (button == _btnRegions[i])\n\t\t\t\t{\n\t\t\t\t\tnumber = i + _butRegionsOffset;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t_regionToggles.at(number)->_pushed = button->getPressed();\n\t}\n\n\tdrawLines();\n}\n\n/**\n * Handles a click on a country button.\n * @param action Pointer to an action.\n */\nvoid GraphsState::btnCountryListClick(Action * action)\n{\n\tsize_t number = 0;\n\tToggleTextButton *button = dynamic_cast<ToggleTextButton*>(action->getSender());\n\n\tif (action->getDetails()->button.button == SDL_BUTTON_RIGHT)\n\t{\n\t\tfor (size_t i = 0; i < _btnCountries.size(); ++i)\n\t\t{\n\t\t\tif (button != _btnCountries[i])\n\t\t\t{\n\t\t\t\t_btnCountries[i]->setPressed(button->getPressed());\n\t\t\t}\n\t\t}\n\t\t_btnCountryTotal->setPressed(button->getPressed());\n\t\tfor (auto* gbi : _countryToggles)\n\t\t{\n\t\t\tgbi->_pushed = button->getPressed();\n\t\t}\n\t}\n\telse\n\t{\n\t\tif (button == _btnCountryTotal)\n\t\t{\n\t\t\tnumber = _countryToggles.size() - 1;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tfor (size_t i = 0; i < _btnCountries.size(); ++i)\n\t\t\t{\n\t\t\t\tif (button == _btnCountries[i])\n\t\t\t\t{\n\t\t\t\t\tnumber = i + _butCountriesOffset;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t_countryToggles.at(number)->_pushed = button->getPressed();\n\t}\n\n\tdrawLines();\n}\n\n/**\n * handles a click on a finances button.\n * @param action Pointer to an action.\n */\nvoid GraphsState::btnFinanceListClick(Action *action)\n{\n\tsize_t number = 0;\n\tToggleTextButton *button = dynamic_cast<ToggleTextButton*>(action->getSender());\n\n\tfor (size_t i = 0; i < _btnFinances.size(); ++i)\n\t{\n\t\tif (button == _btnFinances[i])\n\t\t{\n\t\t\tnumber = i;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t_financeLines.at(number)->setVisible(!_financeToggles.at(number));\n\t_financeToggles.at(number) = button->getPressed();\n\n\tdrawLines();\n}\n\n/**\n * remove all elements from view\n */\nvoid GraphsState::resetScreen()\n{\n\tfor (auto* surface : _alienRegionLines)\n\t{\n\t\tsurface->setVisible(false);\n\t}\n\tfor (auto* surface : _alienCountryLines)\n\t{\n\t\tsurface->setVisible(false);\n\t}\n\tfor (auto* surface : _xcomRegionLines)\n\t{\n\t\tsurface->setVisible(false);\n\t}\n\tfor (auto* surface : _xcomCountryLines)\n\t{\n\t\tsurface->setVisible(false);\n\t}\n\tfor (auto* surface : _incomeLines)\n\t{\n\t\tsurface->setVisible(false);\n\t}\n\tfor (auto* surface : _financeLines)\n\t{\n\t\tsurface->setVisible(false);\n\t}\n\n\n\tfor (auto* ttb : _btnRegions)\n\t{\n\t\tttb->setVisible(false);\n\t}\n\tfor (auto* ttb : _btnCountries)\n\t{\n\t\tttb->setVisible(false);\n\t}\n\tfor (auto* ttb : _btnFinances)\n\t{\n\t\tttb->setVisible(false);\n\t}\n\n\t_btnRegionTotal->setVisible(false);\n\t_btnCountryTotal->setVisible(false);\n\t_txtFactor->setVisible(false);\n}\n\n/**\n * updates the text on the vertical scale\n * @param lowerLimit minimum value\n * @param upperLimit maximum value\n */\nvoid GraphsState::updateScale(double lowerLimit, double upperLimit)\n{\n\tdouble increment = ((upperLimit - lowerLimit) / 9);\n\tdouble text = lowerLimit;\n\tfor (int i = 0; i < 10; ++i)\n\t{\n\t\t_txtScale.at(i)->setText(Unicode::formatNumber(static_cast<int>(text)));\n\t\ttext += increment;\n\t}\n}\n\n/**\n * instead of having all our line drawing in one giant ridiculous routine, just use the one we need.\n */\nvoid GraphsState::drawLines()\n{\n\tif (!_country && !_finance)\n\t{\n\t\tdrawRegionLines();\n\t}\n\telse if (!_finance)\n\t{\n\t\tdrawCountryLines();\n\t}\n\telse\n\t{\n\t\tdrawFinanceLines();\n\t}\n}\n\n/**\n * Sets up the screens and draws the lines for country button\n * to toggle on and off\n */\nvoid GraphsState::drawCountryLines()\n{\n\t//calculate the totals, and set up our upward maximum\n\tint upperLimit = 0;\n\tint lowerLimit = 0;\n\tint totals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};\n\tfor (size_t entry = 0; entry != _game->getSavedGame()->getFundsList().size(); ++entry)\n\t{\n\t\tint total = 0;\n\t\tif (_alien)\n\t\t{\n\t\t\tfor (size_t iter = 0; iter != _game->getSavedGame()->getCountries()->size(); ++iter)\n\t\t\t{\n\t\t\t\ttotal += _game->getSavedGame()->getCountries()->at(iter)->getActivityAlien().at(entry);\n\t\t\t\tif (_game->getSavedGame()->getCountries()->at(iter)->getActivityAlien().at(entry) > upperLimit && _countryToggles.at(iter)->_pushed)\n\t\t\t\t{\n\t\t\t\t\tupperLimit = _game->getSavedGame()->getCountries()->at(iter)->getActivityAlien().at(entry);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse if (_income)\n\t\t{\n\t\t\tfor (size_t iter = 0; iter != _game->getSavedGame()->getCountries()->size(); ++iter)\n\t\t\t{\n\t\t\t\ttotal += _game->getSavedGame()->getCountries()->at(iter)->getFunding().at(entry) / 1000;\n\t\t\t\tif (_game->getSavedGame()->getCountries()->at(iter)->getFunding().at(entry) / 1000 > upperLimit && _countryToggles.at(iter)->_pushed)\n\t\t\t\t{\n\t\t\t\t\tupperLimit = _game->getSavedGame()->getCountries()->at(iter)->getFunding().at(entry) / 1000;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tfor (size_t iter = 0; iter != _game->getSavedGame()->getCountries()->size(); ++iter)\n\t\t\t{\n\t\t\t\ttotal += _game->getSavedGame()->getCountries()->at(iter)->getActivityXcom().at(entry);\n\t\t\t\tif (_game->getSavedGame()->getCountries()->at(iter)->getActivityXcom().at(entry) > upperLimit && _countryToggles.at(iter)->_pushed)\n\t\t\t\t{\n\t\t\t\t\tupperLimit = _game->getSavedGame()->getCountries()->at(iter)->getActivityXcom().at(entry);\n\t\t\t\t}\n\t\t\t\tif (_game->getSavedGame()->getCountries()->at(iter)->getActivityXcom().at(entry) < lowerLimit && _countryToggles.at(iter)->_pushed)\n\t\t\t\t{\n\t\t\t\t\tlowerLimit = _game->getSavedGame()->getCountries()->at(iter)->getActivityXcom().at(entry);\n\t\t\t\t}\n\n\t\t\t}\n\t\t}\n\t\tif (_countryToggles.back()->_pushed && total > upperLimit)\n\t\t\tupperLimit = total;\n\t\tif (_countryToggles.back()->_pushed && total < lowerLimit)\n\t\t\tlowerLimit = total;\n\t}\n\n\t//adjust the scale to fit the upward maximum\n\tdouble range = upperLimit - lowerLimit;\n\tdouble low = lowerLimit;\n\tint grids = 9; // cells in grid\n\tint check = _income ? 50 : 10;\n\twhile (range > check * grids)\n\t{\n\t\tcheck *= 2;\n\t}\n\n\tlowerLimit = 0;\n\tupperLimit = check * grids;\n\n\tif (low < 0)\n\t{\n\t\twhile (low < lowerLimit)\n\t\t{\n\t\t\tlowerLimit -= check;\n\t\t\tupperLimit -= check;\n\t\t}\n\t}\n\n\t// custom zoom\n\tlowerLimit = (lowerLimit * _zoom) / 100;\n\tupperLimit = (upperLimit * _zoom) / 100;\n\n\trange = upperLimit - lowerLimit;\n\tdouble units = range / 126;\n\n\t// draw country line\n\tfor (size_t entry = 0; entry != _game->getSavedGame()->getCountries()->size(); ++entry)\n\t{\n\t\tCountry *country = _game->getSavedGame()->getCountries()->at(entry);\n\t\t_alienCountryLines.at(entry)->clear();\n\t\t_xcomCountryLines.at(entry)->clear();\n\t\t_incomeLines.at(entry)->clear();\n\t\tstd::vector<Sint16> newLineVector;\n\t\tint reduction = 0;\n\t\tfor (size_t iter = 0; iter != 12; ++iter)\n\t\t{\n\t\t\tint x = 312 - (iter*17);\n\t\t\tint y = 175 - (-lowerLimit / units);\n\t\t\tif (_alien)\n\t\t\t{\n\t\t\t\tif (iter < country->getActivityAlien().size())\n\t\t\t\t{\n\t\t\t\t\treduction = country->getActivityAlien().at(country->getActivityAlien().size()-(1+iter)) / units;\n\t\t\t\t\ty -= reduction;\n\t\t\t\t\ttotals[iter] += country->getActivityAlien().at(country->getActivityAlien().size()-(1+iter));\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (_income)\n\t\t\t{\n\t\t\t\tif (iter < country->getFunding().size())\n\t\t\t\t{\n\t\t\t\t\treduction = (country->getFunding().at(country->getFunding().size()-(1+iter)) / 1000) / units;\n\t\t\t\t\ty -= reduction;\n\t\t\t\t\ttotals[iter] += country->getFunding().at(country->getFunding().size()-(1+iter)) / 1000;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (iter < country->getActivityXcom().size())\n\t\t\t\t{\n\t\t\t\t\treduction = country->getActivityXcom().at(country->getActivityXcom().size()-(1+iter)) / units;\n\t\t\t\t\ty -= reduction;\n\t\t\t\t\ttotals[iter] += country->getActivityXcom().at(country->getActivityXcom().size()-(1+iter));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (y >=180) y = 180;\n\t\t\tif (y <= 45) y = 45;\n\t\t\tnewLineVector.push_back(y);\n\n\t\t\tif (newLineVector.size() > 1 && _alien)\n\t\t\t\t_alienCountryLines.at(entry)->drawLine(x, y, x+17, newLineVector.at(newLineVector.size()-2), _countryToggles.at(entry)->_color+4);\n\t\t\telse if (newLineVector.size() > 1 && _income)\n\t\t\t\t_incomeLines.at(entry)->drawLine(x, y, x+17, newLineVector.at(newLineVector.size()-2), _countryToggles.at(entry)->_color+4);\n\t\t\telse if (newLineVector.size() > 1)\n\t\t\t\t_xcomCountryLines.at(entry)->drawLine(x, y, x+17, newLineVector.at(newLineVector.size()-2), _countryToggles.at(entry)->_color+4);\n\t\t\t}\n\t\tif (_alien)\n\t\t\t_alienCountryLines.at(entry)->setVisible(_countryToggles.at(entry)->_pushed);\n\t\telse if (_income)\n\t\t\t_incomeLines.at(entry)->setVisible(_countryToggles.at(entry)->_pushed);\n\t\telse\n\t\t\t_xcomCountryLines.at(entry)->setVisible(_countryToggles.at(entry)->_pushed);\n\t}\n\tif (_alien)\n\t\t_alienCountryLines.back()->clear();\n\telse if (_income)\n\t\t_incomeLines.back()->clear();\n\telse\n\t\t_xcomCountryLines.back()->clear();\n\n\t// set up the \"total\" line\n\tstd::vector<Sint16> newLineVector;\n\tUint8 color = _game->getMod()->getInterface(\"graphs\")->getElement(\"countryTotal\")->color2;\n\tfor (int iter = 0; iter != 12; ++iter)\n\t{\n\t\tint x = 312 - (iter*17);\n\t\tint y = 175 - (-lowerLimit / units);\n\t\t//if (totals[iter] > 0)\n\t\t{\n\t\t\tint reduction = totals[iter] / units;\n\t\t\ty -= reduction;\n\t\t}\n\n\t\tif (y >=180) y = 180;\n\t\tif (y <= 45) y = 45;\n\t\tnewLineVector.push_back(y);\n\n\t\tif (newLineVector.size() > 1)\n\t\t{\n\t\t\tif (_alien)\n\t\t\t\t_alienCountryLines.back()->drawLine(x, y, x+17, newLineVector.at(newLineVector.size()-2), color);\n\t\t\telse if (_income)\n\t\t\t\t_incomeLines.back()->drawLine(x, y, x+17, newLineVector.at(newLineVector.size()-2), color);\n\t\t\telse\n\t\t\t\t_xcomCountryLines.back()->drawLine(x, y, x+17, newLineVector.at(newLineVector.size()-2), color);\n\t\t}\n\t}\n\tif (_alien)\n\t\t_alienCountryLines.back()->setVisible(_countryToggles.back()->_pushed);\n\telse if (_income)\n\t\t_incomeLines.back()->setVisible(_countryToggles.back()->_pushed);\n\telse\n\t\t_xcomCountryLines.back()->setVisible(_countryToggles.back()->_pushed);\n\tupdateScale(lowerLimit, upperLimit);\n\t_txtFactor->setVisible(_income);\n}\n\n/**\n * Sets up the screens and draws the lines for region button\n * to toggle on and off\n */\nvoid GraphsState::drawRegionLines()\n{\n\t//calculate the totals, and set up our upward maximum\n\tint upperLimit = 0;\n\tint lowerLimit = 0;\n\tint totals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};\n\tfor (size_t entry = 0; entry != _game->getSavedGame()->getFundsList().size(); ++entry)\n\t{\n\t\tint total = 0;\n\t\tif (_alien)\n\t\t{\n\t\t\tfor (size_t iter = 0; iter != _game->getSavedGame()->getRegions()->size(); ++iter)\n\t\t\t{\n\t\t\t\ttotal += _game->getSavedGame()->getRegions()->at(iter)->getActivityAlien().at(entry);\n\t\t\t\tif (_game->getSavedGame()->getRegions()->at(iter)->getActivityAlien().at(entry) > upperLimit && _regionToggles.at(iter)->_pushed)\n\t\t\t\t{\n\t\t\t\t\tupperLimit = _game->getSavedGame()->getRegions()->at(iter)->getActivityAlien().at(entry);\n\t\t\t\t}\n\t\t\t\tif (_game->getSavedGame()->getRegions()->at(iter)->getActivityAlien().at(entry) < lowerLimit && _regionToggles.at(iter)->_pushed)\n\t\t\t\t{\n\t\t\t\t\tlowerLimit = _game->getSavedGame()->getRegions()->at(iter)->getActivityAlien().at(entry);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tfor (size_t iter = 0; iter != _game->getSavedGame()->getRegions()->size(); ++iter)\n\t\t\t{\n\t\t\t\ttotal += _game->getSavedGame()->getRegions()->at(iter)->getActivityXcom().at(entry);\n\t\t\t\tif (_game->getSavedGame()->getRegions()->at(iter)->getActivityXcom().at(entry) > upperLimit && _regionToggles.at(iter)->_pushed)\n\t\t\t\t{\n\t\t\t\t\tupperLimit = _game->getSavedGame()->getRegions()->at(iter)->getActivityXcom().at(entry);\n\t\t\t\t}\n\t\t\t\tif (_game->getSavedGame()->getRegions()->at(iter)->getActivityXcom().at(entry) < lowerLimit && _regionToggles.at(iter)->_pushed)\n\t\t\t\t{\n\t\t\t\t\tlowerLimit = _game->getSavedGame()->getRegions()->at(iter)->getActivityXcom().at(entry);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (_regionToggles.back()->_pushed && total > upperLimit)\n\t\t\t\tupperLimit = total;\n\t\tif (_regionToggles.back()->_pushed && total < lowerLimit)\n\t\t\tlowerLimit = total;\n\t}\n\n\t//adjust the scale to fit the upward maximum\n\tdouble range = upperLimit - lowerLimit;\n\tdouble low = lowerLimit;\n\tint check = 10;\n\tint grids = 9; // cells in grid\n\twhile (range > check * grids)\n\t{\n\t\tcheck *= 2;\n\t}\n\n\tlowerLimit = 0;\n\tupperLimit = check * grids;\n\n\tif (low < 0)\n\t{\n\t\twhile (low < lowerLimit)\n\t\t{\n\t\t\tlowerLimit -= check;\n\t\t\tupperLimit -= check;\n\t\t}\n\t}\n\n\t// custom zoom\n\tlowerLimit = (lowerLimit * _zoom) / 100;\n\tupperLimit = (upperLimit * _zoom) / 100;\n\n\trange = upperLimit - lowerLimit;\n\tdouble units = range / 126;\n\n\t// draw region lines\n\tfor (size_t entry = 0; entry != _game->getSavedGame()->getRegions()->size(); ++entry)\n\t{\n\t\tRegion *region = _game->getSavedGame()->getRegions()->at(entry);\n\t\t_alienRegionLines.at(entry)->clear();\n\t\t_xcomRegionLines.at(entry)->clear();\n\t\tstd::vector<Sint16> newLineVector;\n\t\tint reduction = 0;\n\t\tfor (size_t iter = 0; iter != 12; ++iter)\n\t\t{\n\t\t\tint x = 312 - (iter*17);\n\t\t\tint y = 175 - (-lowerLimit / units);\n\t\t\tif (_alien)\n\t\t\t{\n\t\t\t\tif (iter < region->getActivityAlien().size())\n\t\t\t\t{\n\t\t\t\t\treduction = region->getActivityAlien().at(region->getActivityAlien().size()-(1+iter)) / units;\n\t\t\t\t\ty -= reduction;\n\t\t\t\t\ttotals[iter] += region->getActivityAlien().at(region->getActivityAlien().size()-(1+iter));\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (iter < region->getActivityXcom().size())\n\t\t\t\t{\n\t\t\t\t\treduction = region->getActivityXcom().at(region->getActivityXcom().size()-(1+iter)) / units;\n\t\t\t\t\ty -= reduction;\n\t\t\t\t\ttotals[iter] += region->getActivityXcom().at(region->getActivityXcom().size()-(1+iter));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (y >=180) y = 180;\n\t\t\tif (y <= 45) y = 45;\n\t\t\tnewLineVector.push_back(y);\n\n\t\t\tif (newLineVector.size() > 1 && _alien)\n\t\t\t\t_alienRegionLines.at(entry)->drawLine(x, y, x+17, newLineVector.at(newLineVector.size()-2), _regionToggles.at(entry)->_color+4);\n\t\t\telse if (newLineVector.size() > 1)\n\t\t\t\t_xcomRegionLines.at(entry)->drawLine(x, y, x+17, newLineVector.at(newLineVector.size()-2), _regionToggles.at(entry)->_color+4);\n\t\t}\n\n\t\tif (_alien)\n\t\t\t_alienRegionLines.at(entry)->setVisible(_regionToggles.at(entry)->_pushed);\n\t\telse\n\t\t\t_xcomRegionLines.at(entry)->setVisible(_regionToggles.at(entry)->_pushed);\n\t}\n\n\t// set up the \"total\" line\n\tif (_alien)\n\t\t_alienRegionLines.back()->clear();\n\telse\n\t\t_xcomRegionLines.back()->clear();\n\n\tUint8 color = _game->getMod()->getInterface(\"graphs\")->getElement(\"regionTotal\")->color2;\n\tstd::vector<Sint16> newLineVector;\n\tfor (int iter = 0; iter != 12; ++iter)\n\t{\n\t\tint x = 312 - (iter*17);\n\t\tint y = 175 - (-lowerLimit / units);\n\t\t//if (totals[iter] > 0)\n\t\t{\n\t\t\tint reduction = totals[iter] / units;\n\t\t\ty -= reduction;\n\t\t}\n\n\t\tif (y >=180) y = 180;\n\t\tif (y <= 45) y = 45;\n\t\tnewLineVector.push_back(y);\n\n\t\tif (newLineVector.size() > 1)\n\t\t{\n\t\t\tif (_alien)\n\t\t\t\t_alienRegionLines.back()->drawLine(x, y, x+17, newLineVector.at(newLineVector.size()-2), color);\n\t\t\telse\n\t\t\t\t_xcomRegionLines.back()->drawLine(x, y, x+17, newLineVector.at(newLineVector.size()-2), color);\n\t\t}\n\t}\n\tif (_alien)\n\t\t_alienRegionLines.back()->setVisible(_regionToggles.back()->_pushed);\n\telse\n\t\t_xcomRegionLines.back()->setVisible(_regionToggles.back()->_pushed);\n\tupdateScale(lowerLimit, upperLimit);\n\t_txtFactor->setVisible(false);\n}\n\n/**\n * Sets up the screens and draws the lines for the finance button\n * to toggle on and off\n */\nvoid GraphsState::drawFinanceLines()\n{\n\t//set up array\n\tint upperLimit = 0;\n\tint lowerLimit = 0;\n\tint64_t incomeTotals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};\n\tint64_t balanceTotals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};\n\tint64_t expendTotals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};\n\tint64_t maintTotals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};\n\tint scoreTotals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};\n\tmaintTotals[0] = _game->getSavedGame()->getBaseMaintenance() / 1000;\n\n\t// start filling those arrays with score value\n\t// determine which is the highest one being displayed, so we can adjust the scale\n\tfor (size_t entry = 0; entry != _game->getSavedGame()->getFundsList().size(); ++entry)\n\t{\n\t\tsize_t invertedEntry = _game->getSavedGame()->getFundsList().size() - (1 + entry);\n\t\tmaintTotals[entry] += _game->getSavedGame()->getMaintenances().at(invertedEntry) / 1000;\n\t\tbalanceTotals[entry] = _game->getSavedGame()->getFundsList().at(invertedEntry) / 1000;\n\t\tscoreTotals[entry] = _game->getSavedGame()->getResearchScores().at(invertedEntry);\n\n\t\tfor (auto* region : *_game->getSavedGame()->getRegions())\n\t\t{\n\t\t\tscoreTotals[entry] += region->getActivityXcom().at(invertedEntry) - region->getActivityAlien().at(invertedEntry);\n\t\t}\n\n\t\tif (_financeToggles.at(2))\n\t\t{\n\t\t\tif (maintTotals[entry] > upperLimit)\n\t\t\t{\n\t\t\t\tupperLimit = maintTotals[entry];\n\t\t\t}\n\t\t\tif (maintTotals[entry] < lowerLimit)\n\t\t\t{\n\t\t\t\tlowerLimit = maintTotals[entry];\n\t\t\t}\n\t\t}\n\t\tif (_financeToggles.at(3))\n\t\t{\n\t\t\tif (balanceTotals[entry] > upperLimit)\n\t\t\t{\n\t\t\t\tupperLimit = balanceTotals[entry];\n\t\t\t}\n\t\t\tif (balanceTotals[entry] < lowerLimit)\n\t\t\t{\n\t\t\t\tlowerLimit = balanceTotals[entry];\n\t\t\t}\n\t\t}\n\t\tif (_financeToggles.at(4))\n\t\t{\n\t\t\tif (scoreTotals[entry] > upperLimit)\n\t\t\t{\n\t\t\t\tupperLimit = scoreTotals[entry];\n\t\t\t}\n\t\t\tif (scoreTotals[entry] < lowerLimit)\n\t\t\t{\n\t\t\t\tlowerLimit = scoreTotals[entry];\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (size_t entry = 0; entry !=  _game->getSavedGame()->getExpenditures().size(); ++entry)\n\t{\n\t\texpendTotals[entry] = _game->getSavedGame()->getExpenditures().at(_game->getSavedGame()->getExpenditures().size() - (entry + 1)) / 1000;\n\t\tincomeTotals[entry] = _game->getSavedGame()->getIncomes().at(_game->getSavedGame()->getIncomes().size() - (entry + 1)) / 1000;\n\n\t\tif (_financeToggles.at(0) && incomeTotals[entry] > upperLimit)\n\t\t{\n\t\t\tupperLimit = incomeTotals[entry];\n\t\t}\n\t\tif (_financeToggles.at(1) && expendTotals[entry] > upperLimit)\n\t\t{\n\t\t\tupperLimit = expendTotals[entry];\n\t\t}\n\t}\n\n\tdouble range = upperLimit - lowerLimit;\n\tdouble low = lowerLimit;\n\tint check = 250;\n\tint grids = 9; // cells in grid\n\twhile (range > check * grids)\n\t{\n\t\tcheck *= 2;\n\t}\n\n\tlowerLimit = 0;\n\tupperLimit = check * grids;\n\n\tif (low < 0)\n\t{\n\t\twhile (low < lowerLimit)\n\t\t{\n\t\t\tlowerLimit -= check;\n\t\t\tupperLimit -= check;\n\t\t}\n\t}\n\t//toggle screen\n\tfor (int button = 0; button != 5; ++button)\n\t{\n\t\t_financeLines.at(button)->setVisible(_financeToggles.at(button));\n\t\t_financeLines.at(button)->clear();\n\t}\n\trange = upperLimit - lowerLimit;\n\t//figure out how many units to the pixel, then plot the points for the graph and connect the dots.\n\tdouble units = range / 126;\n\tfor (int button = 0; button != 5; ++button)\n\t{\n\t\tstd::vector<Sint16> newLineVector;\n\t\tfor (int iter = 0; iter != 12; ++iter)\n\t\t{\n\t\t\tint x = 312 - (iter*17);\n\t\t\tint y = 175 - (-lowerLimit / units);\n\t\t\tint reduction = 0;\n\t\t\tswitch(button)\n\t\t\t{\n\t\t\tcase 0:\n\t\t\t\treduction = incomeTotals[iter] / units;\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\t\treduction = expendTotals[iter] / units;\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\treduction = maintTotals[iter] / units;\n\t\t\t\tbreak;\n\t\t\tcase 3:\n\t\t\t\treduction = balanceTotals[iter] / units;\n\t\t\t\tbreak;\n\t\t\tcase 4:\n\t\t\t\treduction = scoreTotals[iter] / units;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\ty -= reduction;\n\t\t\tnewLineVector.push_back(y);\n\t\t\tint offset = button % 2 ? 8 : 0;\n\t\t\tif (newLineVector.size() > 1)\n\t\t\t\t_financeLines.at(button)->drawLine(x, y, x+17, newLineVector.at(newLineVector.size()-2), Palette::blockOffset((button/2)+1)+offset);\n\t\t}\n\t}\n\tupdateScale(lowerLimit, upperLimit);\n\t_txtFactor->setVisible(true);\n}\n\n/**\n * 'Shift' the buttons to display only GRAPH_MAX_BUTTONS - reset their state from toggle\n */\nvoid GraphsState::shiftButtons(Action *action)\n{\n\t// only if active 'screen' is other than finance\n\tif (_finance)\n\t\treturn;\n\t// select the data's we'll processing - regions or countries\n\tif (_country)\n\t{\n\t\t// too few countries? - return\n\t\tif (_countryToggles.size() <= GRAPH_MAX_BUTTONS)\n\t\t\treturn;\n\t\telse if (action->getDetails()->button.button == SDL_BUTTON_WHEELUP)\n\t\t\tscrollButtons(_countryToggles, _btnCountries, _butCountriesOffset, -1);\n\t\telse if (action->getDetails()->button.button == SDL_BUTTON_WHEELDOWN)\n\t\t\tscrollButtons(_countryToggles, _btnCountries, _butCountriesOffset, 1);\n\t}\n\telse\n\t{\n\t\t// too few regions? - return\n\t\tif (_regionToggles.size() <= GRAPH_MAX_BUTTONS)\n\t\t\treturn;\n\t\telse if (action->getDetails()->button.button == SDL_BUTTON_WHEELUP)\n\t\t\tscrollButtons(_regionToggles, _btnRegions, _butRegionsOffset, -1);\n\t\telse if (action->getDetails()->button.button == SDL_BUTTON_WHEELDOWN)\n\t\t\tscrollButtons(_regionToggles, _btnRegions, _butRegionsOffset, 1);\n\t}\n}\n\nvoid GraphsState::scrollButtons(std::vector<GraphButInfo *> &toggles, std::vector<ToggleTextButton *> &buttons, size_t &offset, int step)\n{\n\tif ( int(step + (int)offset) < 0 || offset + step + GRAPH_MAX_BUTTONS >= toggles.size())\n\t\treturn;\n\t// set the next offset - cheaper to do it from starter\n\toffset += step;\n\tsize_t i = 0;\n\tstd::vector<ToggleTextButton *>::iterator iterb = buttons.begin();\n\tfor (std::vector<GraphButInfo *>::iterator itert = toggles.begin() + offset; itert != toggles.end() && i < GRAPH_MAX_BUTTONS; ++itert, ++iterb, ++i)\n\t{\n\t\tupdateButton(*itert, *iterb);\n\t}\n}\n\nvoid GraphsState::updateButton(GraphButInfo *from,ToggleTextButton *to)\n{\n\tto->setText(from->_name);\n\tto->setInvertColor(from->_color);\n\tto->setPressed(from->_pushed);\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/GraphsState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass Surface;\nclass InteractiveSurface;\nclass Text;\nclass TextButton;\nclass ToggleTextButton;\nclass TextList;\nclass Region;\nstruct GraphButInfo;\n\n/**\n * Graphs screen for displaying graphs of various\n * monthly game data like activity and funding.\n */\nclass GraphsState : public State\n{\nprivate:\n\tInteractiveSurface *_bg;\n\tInteractiveSurface *_btnGeoscape;\n\tInteractiveSurface *_btnXcomCountry, *_btnUfoCountry;\n\tInteractiveSurface *_btnXcomRegion, *_btnUfoRegion;\n\tInteractiveSurface *_btnIncome, *_btnFinance;\n\tText *_txtTitle, *_txtFactor;\n\tTextList *_txtMonths, *_txtYears;\n\tstd::vector<Text *> _txtScale;\n\tstd::vector<ToggleTextButton *> _btnRegions, _btnCountries, _btnFinances;\n\tstd::vector<GraphButInfo *>  _regionToggles, _countryToggles;\n\tstd::vector<bool> _financeToggles;\n\tToggleTextButton *_btnRegionTotal, *_btnCountryTotal;\n\tstd::vector<Surface *> _alienRegionLines, _alienCountryLines;\n\tstd::vector<Surface *> _xcomRegionLines, _xcomCountryLines;\n\tstd::vector<Surface *> _financeLines, _incomeLines;\n\tbool _alien, _income, _country, _finance;\n\tstatic const size_t GRAPH_MAX_BUTTONS=16;\n\t//will be only between 0 and size()\n\tsize_t _butRegionsOffset, _butCountriesOffset;\n\tint _zoom;\n\t//scroll and repaint buttons functions\n\tvoid scrollButtons(std::vector<GraphButInfo *> &toggles, std::vector<ToggleTextButton *> &buttons, size_t &offset, int step);\n\tvoid updateButton(GraphButInfo *from,ToggleTextButton *to);\npublic:\n\t/// Creates the Graphs state.\n\tGraphsState();\n\t/// Cleans up the Graphs state.\n\t~GraphsState();\n\t/// Handler for using zoom in/out hotkeys.\n\tvoid btnZoomInClick(Action *action);\n\tvoid btnZoomOutClick(Action *action);\n\t/// Handler for clicking the Geoscape icon.\n\tvoid btnGeoscapeClick(Action *action);\n\t/// Handler for clicking the ufo region icon.\n\tvoid btnUfoRegionClick(Action *action);\n\t/// Handler for clicking the ufo country icon.\n\tvoid btnUfoCountryClick(Action *action);\n\t/// Handler for clicking the xcom region icon.\n\tvoid btnXcomRegionClick(Action *action);\n\t/// Handler for clicking the xcom country icon.\n\tvoid btnXcomCountryClick(Action *action);\n\t/// Handler for clicking the income icon.\n\tvoid btnIncomeClick(Action *action);\n\t/// Handler for clicking the finance icon.\n\tvoid btnFinanceClick(Action *action);\n\t/// Handler for clicking on a region button.\n\tvoid btnRegionListClick(Action *action);\n\t/// Handler for clicking on a country button.\n\tvoid btnCountryListClick(Action *action);\n\t/// Handler for clicking  on a finances button.\n\tvoid btnFinanceListClick(Action *action);\n\t/// Mouse wheel handler for shifting up/down the buttons\n\tvoid shiftButtons(Action *action);\n\t/// Reset all the elements on screen.\n\tvoid resetScreen();\n\t/// Update the scale\n\tvoid updateScale(double lowerLimit, double upperLimit);\n\t/// Decide which lines to draw\n\tvoid drawLines();\n\t/// Draw Region Lines.\n\tvoid drawRegionLines();\n\t/// Draw Country Lines.\n\tvoid drawCountryLines();\n\t/// Draw Finances Lines.\n\tvoid drawFinanceLines();\n\t/// Scroll button lists\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/InterceptState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"InterceptState.h\"\n#include <sstream>\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/Craft.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Ufo.h\"\n#include \"../Savegame/MissionSite.h\"\n#include \"../Savegame/AlienBase.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/RNG.h\"\n#include \"Globe.h\"\n#include \"SelectDestinationState.h\"\n#include \"ConfirmDestinationState.h\"\n#include \"../Basescape/BasescapeState.h\"\n#include \"../Basescape/CraftInfoState.h\"\n#include \"../Ufopaedia/Ufopaedia.h\"\n#include \"../Mod/RuleInterface.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Intercept window.\n * @param game Pointer to the core game.\n * @param globe Pointer to the Geoscape globe.\n * @param base Pointer to base to show contained crafts (NULL to show all crafts).\n * @param target Pointer to target to intercept (NULL to ask user for target).\n */\nInterceptState::InterceptState(Globe *globe, bool useCustomSound, Base *base, Target *target) : _globe(globe), _base(base), _target(target)\n{\n\tconst int WIDTH_CRAFT = 72;\n\tconst int WIDTH_STATUS = 94;\n\tconst int WIDTH_BASE = 74;\n\tconst int WIDTH_WEAPONS = 48;\n\t_screen = false;\n\n\tif (useCustomSound)\n\t{\n\t\tauto& sounds = _game->getMod()->getSelectBaseSounds();\n\t\tint soundId = sounds.empty() ? Mod::NO_SOUND : sounds[RNG::generate(0, sounds.size() - 1)];\n\t\tif (soundId != Mod::NO_SOUND)\n\t\t{\n\t\t\t_customSound = _game->getMod()->getSound(\"GEO.CAT\", soundId);\n\t\t}\n\t}\n\n\tint extraRows = Clamp(Options::oxceInterceptTableSize, 8, 80) - 8;\n\tint extraHeight = 8 * extraRows;\n\tint offset = extraHeight / 2;\n\n\t// Create objects\n\tif (Options::oxceInterceptGuiMaintenanceTime > 0)\n\t{\n\t\t_window = new Window(this, 320, 140 + extraHeight, 0, 30 - offset, POPUP_HORIZONTAL);\n\t\t_btnCancel = new TextButton(_base ? 142 : 288, 16, 16, 146 + offset);\n\t\t_btnGotoBase = new TextButton(142, 16, 162, 146 + offset);\n\t\t_txtTitle = new Text(300, 17, 10, 46 - offset);\n\t\tint x = 14;\n\t\t_txtCraft = new Text(WIDTH_CRAFT, 9, x, 70 - offset);\n\t\tx += WIDTH_CRAFT;\n\t\t_txtStatus = new Text(WIDTH_STATUS, 9, x, 70 - offset);\n\t\tx += WIDTH_STATUS;\n\t\t_txtBase = new Text(WIDTH_BASE, 9, x, 70 - offset);\n\t\tx += WIDTH_BASE;\n\t\t_txtWeapons = new Text(WIDTH_WEAPONS+4, 17, x-4, 62 - offset);\n\t\t_lstCrafts = new TextList(290, 64 + extraHeight, 12, 78 - offset);\n\t}\n\telse\n\t{\n\t\t_window = new Window(this, 320, 140 + extraHeight, 0, 30 - offset, POPUP_HORIZONTAL);\n\t\t_btnCancel = new TextButton(_base ? 142 : 288, 16, 16, 146 + offset);\n\t\t_btnGotoBase = new TextButton(142, 16, 162, 146 + offset);\n\t\t_txtTitle = new Text(300, 17, 10, 46 - offset);\n\t\t_txtCraft = new Text(86, 9, 14, 70 - offset);\n\t\t_txtStatus = new Text(70, 9, 100, 70 - offset);\n\t\t_txtBase = new Text(80, 9, 170, 70 - offset);\n\t\t_txtWeapons = new Text(80, 17, 238, 62 - offset);\n\t\t_lstCrafts = new TextList(288, 64 + extraHeight, 8, 78 - offset);\n\t}\n\n\t// Set palette\n\tsetInterface(\"intercept\");\n\n\tadd(_window, \"window\", \"intercept\");\n\tadd(_btnCancel, \"button\", \"intercept\");\n\tadd(_btnGotoBase, \"button\", \"intercept\");\n\tadd(_txtTitle, \"text1\", \"intercept\");\n\tadd(_txtCraft, \"text2\", \"intercept\");\n\tadd(_txtStatus, \"text2\", \"intercept\");\n\tadd(_txtBase, \"text2\", \"intercept\");\n\tadd(_txtWeapons, \"text2\", \"intercept\");\n\tadd(_lstCrafts, \"list\", \"intercept\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"intercept\");\n\n\t_btnCancel->setText(tr(\"STR_CANCEL\"));\n\t_btnCancel->onMouseClick((ActionHandler)&InterceptState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&InterceptState::btnCancelClick, Options::keyCancel);\n\t_btnCancel->onKeyboardPress((ActionHandler)&InterceptState::btnCancelClick, Options::keyGeoIntercept);\n\n\t_btnGotoBase->setText(tr(\"STR_GO_TO_BASE\"));\n\t_btnGotoBase->onMouseClick((ActionHandler)&InterceptState::btnGotoBaseClick);\n\t_btnGotoBase->setVisible(_base != 0);\n\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setBig();\n\t_txtTitle->setText(tr(\"STR_LAUNCH_INTERCEPTION\"));\n\n\t_txtCraft->setText(tr(\"STR_CRAFT\"));\n\n\t_txtStatus->setText(tr(\"STR_STATUS\"));\n\n\t_txtBase->setText(tr(\"STR_BASE\"));\n\n\tif (Options::oxceInterceptGuiMaintenanceTime > 0)\n\t{\n\t\t_txtWeapons->setAlign(ALIGN_RIGHT);\n\t}\n\t_txtWeapons->setText(tr(\"STR_WEAPONS_CREW_HWPS\"));\n\n\tif (Options::oxceInterceptGuiMaintenanceTime > 0)\n\t{\n\t\t_lstCrafts->setColumns(4, WIDTH_CRAFT, WIDTH_STATUS, WIDTH_BASE, WIDTH_WEAPONS);\n\t\t_lstCrafts->setAlign(ALIGN_RIGHT, 3);\n\t}\n\telse\n\t{\n\t\t_lstCrafts->setColumns(4, 86, 70, 80, 46);\n\t}\n\t_lstCrafts->setSelectable(true);\n\t_lstCrafts->setBackground(_window);\n\tif (Options::oxceInterceptGuiMaintenanceTime > 0)\n\t{\n\t\t_lstCrafts->setMargin(2);\n\t}\n\telse\n\t{\n\t\t_lstCrafts->setMargin(6);\n\t}\n\t_lstCrafts->onMouseClick((ActionHandler)&InterceptState::lstCraftsLeftClick);\n\t_lstCrafts->onMouseClick((ActionHandler)&InterceptState::lstCraftsRightClick, SDL_BUTTON_RIGHT);\n\t_lstCrafts->onMouseClick((ActionHandler)&InterceptState::lstCraftsMiddleClick, SDL_BUTTON_MIDDLE);\n\n\t//clear list of selected crafts before creating a new wing\n\t_selCrafts.clear();\n\n\tstd::vector< std::tuple<Craft*, double, Base*> > craftList;\n\tfor (auto* xbase : *_game->getSavedGame()->getBases())\n\t{\n\t\tif (_base != 0 && xbase != _base)\n\t\t\tcontinue;\n\t\tfor (auto* xcraft : *xbase->getCrafts())\n\t\t{\n\t\t\tdouble xdistance = 0.0;\n\t\t\tif (_target) xdistance = xcraft->getDistance(_target);\n\t\t\tcraftList.push_back(std::make_tuple(xcraft, xdistance, xbase));\n\t\t}\n\t}\n\tif (_target && Options::oxceGeoSortCraftByDistanceToTarget)\n\t{\n\t\tstd::stable_sort(craftList.begin(), craftList.end(),\n\t\t\t[](const std::tuple<Craft*, double, Base*>& a, const std::tuple<Craft*, double, Base*>& b)\n\t\t\t{\n\t\t\t\treturn std::get<1>(a) < std::get<1>(b);\n\t\t\t}\n\t\t);\n\t}\n\n\tint row = 0;\n\tfor (auto& tuple : craftList)\n\t{\n\t\tauto* xbase = std::get<2>(tuple);\n\t\tauto* xcraft = std::get<0>(tuple);\n\t\t{\n\t\t\tstd::ostringstream ssStatus;\n\t\t\tstd::string status = xcraft->getStatus();\n\n\t\t\tbool hasEnoughPilots = xcraft->arePilotsOnboard(_game->getMod());\n\t\t\tif (status == \"STR_OUT\")\n\t\t\t{\n\t\t\t\t// QoL: let's give the player a bit more info\n\t\t\t\tif (xcraft->getDestination() == 0 || xcraft->getIsAutoPatrolling())\n\t\t\t\t{\n\t\t\t\t\tssStatus << tr(\"STR_PATROLLING\");\n\t\t\t\t}\n\t\t\t\telse if (xcraft->getLowFuel() || xcraft->getMissionComplete() || xcraft->getDestination() == (Target*)xcraft->getBase())\n\t\t\t\t{\n\t\t\t\t\tssStatus << tr(\"STR_RETURNING\");\n\t\t\t\t\t//ssStatus << tr(\"STR_RETURNING_TO_BASE\"); // vanilla craft info\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tUfo *u = dynamic_cast<Ufo*>(xcraft->getDestination());\n\t\t\t\t\tMissionSite *m = dynamic_cast<MissionSite*>(xcraft->getDestination());\n\t\t\t\t\tAlienBase *b = dynamic_cast<AlienBase*>(xcraft->getDestination());\n\t\t\t\t\tCraft *craftTarget = dynamic_cast<Craft*>(xcraft->getDestination());\n\t\t\t\t\tif (u != 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (xcraft->isInDogfight())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tssStatus << tr(\"STR_TAILING_UFO\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (u->getStatus() == Ufo::FLYING)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tssStatus << tr(\"STR_INTERCEPTING\");\n\t\t\t\t\t\t\t//ssStatus << tr(\"STR_INTERCEPTING_UFO\").arg(u->getId()); // vanilla craft info\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tssStatus << tr(\"STR_EN_ROUTE\");\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse if (craftTarget != 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tssStatus << tr(\"STR_ESCORTING\");\n\t\t\t\t\t}\n\t\t\t\t\telse if (m != 0 || b != 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tssStatus << tr(\"STR_EN_ROUTE\");\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tssStatus << tr(status); // \"STR_OUT\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (!hasEnoughPilots && status == \"STR_READY\")\n\t\t\t\t{\n\t\t\t\t\tssStatus << tr(\"STR_PILOT_MISSING\");\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tssStatus << tr(status);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (status != \"STR_READY\" && status != \"STR_OUT\")\n\t\t\t{\n\t\t\t\tunsigned int maintenanceHours = 0;\n\n\t\t\t\tif (Options::oxceInterceptGuiMaintenanceTime == 2 || xcraft->getStatus() == \"STR_REPAIRS\")\n\t\t\t\t{\n\t\t\t\t\tmaintenanceHours += xcraft->calcRepairTime();\n\t\t\t\t}\n\t\t\t\tif (Options::oxceInterceptGuiMaintenanceTime == 2 || xcraft->getStatus() == \"STR_REFUELLING\")\n\t\t\t\t{\n\t\t\t\t\tmaintenanceHours += xcraft->calcRefuelTime();\n\t\t\t\t}\n\t\t\t\tif (Options::oxceInterceptGuiMaintenanceTime == 2 || xcraft->getStatus() == \"STR_REARMING\")\n\t\t\t\t{\n\t\t\t\t\t// Note: if the craft is already refueling, don't count any potential rearm time (can be > 0 if ammo is missing)\n\t\t\t\t\tif (xcraft->getStatus() != \"STR_REFUELLING\")\n\t\t\t\t\t{\n\t\t\t\t\t\tmaintenanceHours += xcraft->calcRearmTime();\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tint days = maintenanceHours / 24;\n\t\t\t\tint hours = maintenanceHours % 24;\n\t\t\t\tif (maintenanceHours > 0 && Options::oxceInterceptGuiMaintenanceTime > 0)\n\t\t\t\t{\n\t\t\t\t\tssStatus << \" (\";\n\t\t\t\t\tif (days > 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tssStatus << tr(\"STR_DAY_SHORT\").arg(days);\n\t\t\t\t\t}\n\t\t\t\t\tif (hours > 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (days > 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tssStatus << \"/\";\n\t\t\t\t\t\t}\n\t\t\t\t\t\tssStatus << tr(\"STR_HOUR_SHORT\").arg(hours);\n\t\t\t\t\t}\n\t\t\t\t\tssStatus << \")\";\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// ETA display\n\t\t\t\tif (Options::oxceShowETAMode > 0 && xcraft->getDestination() && Options::oxceInterceptGuiMaintenanceTime > 0)\n\t\t\t\t{\n\t\t\t\t\tMovingTarget* mt = dynamic_cast<MovingTarget*>(xcraft->getDestination());\n\t\t\t\t\tif (Options::oxceShowETAMode == 1 && mt && mt->getSpeed() > 0)\n\t\t\t\t\t{\n\t\t\t\t\t\t// don't show ETA for moving targets (i.e. UFOs and crafts)\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tint speed = xcraft->getCraftStats().speedMax;\n\t\t\t\t\t\tint distance = XcomDistance(xcraft->getDistance(xcraft->getDestination()));\n\t\t\t\t\t\tint etaInHoursHelper = (distance + (speed / 2)) / speed;\n\t\t\t\t\t\tint days = etaInHoursHelper / 24;\n\t\t\t\t\t\tint hours = etaInHoursHelper % 24;\n\t\t\t\t\t\tssStatus << \" (\";\n\t\t\t\t\t\tif (days > 0) ssStatus << tr(\"STR_DAY_SHORT\").arg(days);\n\t\t\t\t\t\tif (hours > 0 || days == 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (days > 0) ssStatus << \"/\";\n\t\t\t\t\t\t\tssStatus << tr(\"STR_HOUR_SHORT\").arg(hours);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tssStatus << \")\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tstd::ostringstream ss;\n\t\t\tif (xcraft->getNumWeapons() > 0)\n\t\t\t{\n\t\t\t\tss << Unicode::TOK_COLOR_FLIP << xcraft->getNumWeapons() << Unicode::TOK_COLOR_FLIP;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tss << 0;\n\t\t\t}\n\t\t\tss << \"/\";\n\t\t\tif (xcraft->getNumTotalSoldiers() > 0)\n\t\t\t{\n\t\t\t\tss << Unicode::TOK_COLOR_FLIP << xcraft->getNumTotalSoldiers() << Unicode::TOK_COLOR_FLIP;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tss << 0;\n\t\t\t}\n\t\t\tss << \"/\";\n\t\t\tif (xcraft->getNumTotalVehicles() > 0)\n\t\t\t{\n\t\t\t\tss << Unicode::TOK_COLOR_FLIP << xcraft->getNumTotalVehicles() << Unicode::TOK_COLOR_FLIP;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tss << 0;\n\t\t\t}\n\t\t\t_crafts.push_back(xcraft);\n\t\t\t_lstCrafts->addRow(4, xcraft->getName(_game->getLanguage()).c_str(), ssStatus.str().c_str(), xbase->getName().c_str(), ss.str().c_str());\n\t\t\tif (hasEnoughPilots && status == \"STR_READY\")\n\t\t\t{\n\t\t\t\t_lstCrafts->setCellColor(row, 1, _lstCrafts->getSecondaryColor());\n\t\t\t}\n\t\t\tif (_target)\n\t\t\t{\n\t\t\t\tbool craftReturning = xcraft->getLowFuel() || xcraft->getMissionComplete();\n\t\t\t\tif (craftReturning)\n\t\t\t\t{\n\t\t\t\t\tauto disabledColor = _game->getMod()->getInterface(\"intercept\")->getElement(\"disabled\")->color;\n\t\t\t\t\t_lstCrafts->setCellColor(row, 0, disabledColor);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tbool craftAvailable = Options::craftLaunchAlways || status == \"STR_READY\" || status == \"STR_OUT\";\n\t\t\t\t\tif (craftAvailable)\n\t\t\t\t\t{\n\t\t\t\t\t\tdouble craftDistanceToTarget = std::get<1>(tuple);\n\t\t\t\t\t\tdouble baseDistanceToTarget = xcraft->getBase()->getDistance(_target);\n\t\t\t\t\t\tif (craftDistanceToTarget + baseDistanceToTarget > xcraft->getBaseRange() * 2.0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tauto disabledColor = _game->getMod()->getInterface(\"intercept\")->getElement(\"disabled\")->color;\n\t\t\t\t\t\t\t_lstCrafts->setCellColor(row, 0, disabledColor);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\trow++;\n\t\t}\n\t}\n}\n\n/**\n *\n */\nInterceptState::~InterceptState()\n{\n\n}\n\n/**\n * Closes the window.\n * @param action Pointer to an action.\n */\nvoid InterceptState::btnCancelClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Goes to the base for the respective craft.\n * @param action Pointer to an action.\n */\nvoid InterceptState::btnGotoBaseClick(Action *)\n{\n\t_game->popState();\n\t_game->pushState(new BasescapeState(_base, _globe));\n}\n\n/**\n * Pick a target for the selected craft.\n * @param action Pointer to an action.\n */\nvoid InterceptState::lstCraftsLeftClick(Action *)\n{\n\t// condition used in shift and non-shift paths\n\tauto allowStart = [&](Craft* c)\n\t{\n\t\treturn c->getStatus() == \"STR_READY\" || (\n\t\t\t (c->getStatus() == \"STR_OUT\" || Options::craftLaunchAlways) &&\n\t\t\t !c->getLowFuel() &&\n\t\t\t !c->getMissionComplete() );\n\t};\n\n\tunsigned int row;\n\trow = _lstCrafts->getSelectedRow();\n\tCraft* c = _crafts[row];\n\n\t// add and remove crafts to the wing to be created\n\tif (_game->isShiftPressed())\n\t{\n\t\t// add craft to the list when it is not included yet\n\t\t// limit to 4 (3+1 due to the dogfight window)\n\t\t// need more sanity checks?\n\t\tif (allowStart(c) && (_selCrafts.size() < 3) && !( std::find(_selCrafts.begin(), _selCrafts.end(), (Craft*) c) != _selCrafts.end()))\n\t\t{\n\t\t\t_selCrafts.push_back(c);\n\t\t\t_lstCrafts->setCellColor(row, 0, _lstCrafts->getSecondaryColor());\n\t\t}\n\t\t// remove craft from the wing to be created when it is already included\n\t\telse if (( std::find(_selCrafts.begin(), _selCrafts.end(), (Craft*) c) != _selCrafts.end()))\n\t\t{\n\t\t\tauto craftIt = std::find (_selCrafts.begin(), _selCrafts.end(), (Craft*) c);\n\t\t\t_selCrafts.erase(craftIt);\n\t\t\t_lstCrafts->setCellColor(row, 0, _lstCrafts->getColor());\n \t\t}\n\t}\n\t// add last craft to the wing (may already be part of the wing) and launch\n\telse\n\t{\n\t\tif (allowStart(c))\n \t\t{\n\t\t\t//remove itself from the vector assuming it is already inside, so it can be put in front of the vector\n\t\t\tauto craftIt = std::find (_selCrafts.begin(), _selCrafts.end(), c);\n\t\t\tif ( craftIt != _selCrafts.end() )\n\t\t\t{\n\t\t\t\t_selCrafts.erase(craftIt);\n\t\t\t}\n\t\t\t_selCrafts.insert(_selCrafts.begin(), c);\n\n\t\t\t_game->popState();\n\t\t\tif (_target == 0)\n\t\t\t{\n\t\t\t\t_game->pushState(new SelectDestinationState(_selCrafts, _globe));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_game->pushState(new ConfirmDestinationState(_selCrafts, _target));\n\t\t\t}\n\t\t }\n\t}\n}\n\n/**\n * Centers on the selected craft.\n * @param action Pointer to an action.\n */\nvoid InterceptState::lstCraftsRightClick(Action *)\n{\n\tCraft* c = _crafts[_lstCrafts->getSelectedRow()];\n\tif (c->getStatus() == \"STR_OUT\")\n\t{\n\t\t_globe->center(c->getLongitude(), c->getLatitude());\n\t\t_game->popState();\n\t}\n\telse\n\t{\n\t\t_game->popState();\n\n\t\tbool found = false;\n\t\tfor (auto* xbase : *_game->getSavedGame()->getBases())\n\t\t{\n\t\t\tif (_base != 0 && xbase != _base)\n\t\t\t\tcontinue;\n\t\t\tfor (size_t ci = 0; ci < xbase->getCrafts()->size(); ++ci)\n\t\t\t{\n\t\t\t\tif (c == xbase->getCrafts()->at(ci))\n\t\t\t\t{\n\t\t\t\t\t_game->pushState(new CraftInfoState(xbase, ci));\n\t\t\t\t\tfound = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (found) break;\n\t\t}\n\t}\n}\n\n/**\n* Opens the corresponding Ufopaedia article.\n* @param action Pointer to an action.\n*/\nvoid InterceptState::lstCraftsMiddleClick(Action *)\n{\n\tCraft* c = _crafts[_lstCrafts->getSelectedRow()];\n\tif (c)\n\t{\n\t\tstd::string articleId = c->getRules()->getType();\n\t\tUfopaedia::openArticle(_game, articleId);\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/InterceptState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <vector>\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass TextList;\nclass Base;\nclass Globe;\nclass Craft;\nclass Target;\n\n/**\n * Intercept window that lets the player launch\n * crafts into missions from the Geoscape.\n */\nclass InterceptState : public State\n{\nprivate:\n\tTextButton *_btnCancel, *_btnGotoBase;\n\tWindow *_window;\n\tText *_txtTitle, *_txtCraft, *_txtStatus, *_txtBase, *_txtWeapons;\n\tTextList *_lstCrafts;\n\tGlobe *_globe;\n\tBase *_base;\n\tTarget *_target;\n\tstd::vector<Craft*> _crafts;\n\tstd::vector<Craft*> _selCrafts;\npublic:\n\t/// Creates the Intercept state.\n\tInterceptState(Globe *globe, bool useCustomSound, Base *base = 0, Target *target = 0);\n\t/// Cleans up the Intercept state.\n\t~InterceptState();\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action *action);\n\t/// Handler for clicking the Go To Base button.\n\tvoid btnGotoBaseClick(Action *action);\n\t/// Handler for clicking the Crafts list.\n\tvoid lstCraftsLeftClick(Action *action);\n\t/// Handler for right clicking the Crafts list.\n\tvoid lstCraftsRightClick(Action *action);\n\t/// Handler for middle clicking the Crafts list.\n\tvoid lstCraftsMiddleClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/ItemsArrivingState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ItemsArrivingState.h\"\n#include <sstream>\n#include <algorithm>\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/Transfer.h\"\n#include \"../Savegame/Craft.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"GeoscapeState.h\"\n#include \"../Engine/Options.h\"\n#include \"../Basescape/BasescapeState.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Items Arriving window.\n * @param game Pointer to the core game.\n * @param state Pointer to the Geoscape state.\n */\nItemsArrivingState::ItemsArrivingState(GeoscapeState *state) : _state(state), _base(0)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 320, 184, 0, 8, POPUP_BOTH);\n\t_btnOk = new TextButton(142, 16, 16, 166);\n\t_btnGotoBase = new TextButton(142, 16, 162, 166);\n\t_txtTitle = new Text(310, 17, 5, 18);\n\t_txtItem = new Text(114, 9, 16, 34);\n\t_txtQuantity = new Text(54, 9, 152, 34);\n\t_txtDestination = new Text(112, 9, 212, 34);\n\t_lstTransfers = new TextList(271, 112, 14, 50);\n\n\t// Set palette\n\tsetInterface(\"itemsArriving\");\n\n\tadd(_window, \"window\", \"itemsArriving\");\n\tadd(_btnOk, \"button\", \"itemsArriving\");\n\tadd(_btnGotoBase, \"button\", \"itemsArriving\");\n\tadd(_txtTitle, \"text1\", \"itemsArriving\");\n\tadd(_txtItem, \"text1\", \"itemsArriving\");\n\tadd(_txtQuantity, \"text1\", \"itemsArriving\");\n\tadd(_txtDestination, \"text1\", \"itemsArriving\");\n\tadd(_lstTransfers, \"text2\", \"itemsArriving\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"itemsArriving\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&ItemsArrivingState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&ItemsArrivingState::btnOkClick, Options::keyCancel);\n\n\t_btnGotoBase->setText(tr(\"STR_GO_TO_BASE\"));\n\t_btnGotoBase->onMouseClick((ActionHandler)&ItemsArrivingState::btnGotoBaseClick);\n\t_btnGotoBase->onKeyboardPress((ActionHandler)&ItemsArrivingState::btnGotoBaseClick, Options::keyOk);\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_ITEMS_ARRIVING\"));\n\n\t_txtItem->setText(tr(\"STR_ITEM\"));\n\n\t_txtQuantity->setText(tr(\"STR_QUANTITY_UC\"));\n\n\t_txtDestination->setText(tr(\"STR_DESTINATION_UC\"));\n\n\t_lstTransfers->setColumns(3, 155, 41, 98);\n\t_lstTransfers->setSelectable(true);\n\t_lstTransfers->setBackground(_window);\n\t_lstTransfers->setMargin(2);\n\n\tfor (auto* xbase : *_game->getSavedGame()->getBases())\n\t{\n\t\tfor (auto transferIt = xbase->getTransfers()->begin(); transferIt != xbase->getTransfers()->end();)\n\t\t{\n\t\t\tTransfer* transfer = (*transferIt);\n\t\t\tif (transfer->getHours() == 0)\n\t\t\t{\n\t\t\t\t_base = xbase;\n\n\t\t\t\t// Check if we have an automated use for an item\n\t\t\t\tif (transfer->getType() == TRANSFER_ITEM)\n\t\t\t\t{\n\t\t\t\t\tconst auto* item = transfer->getItems();\n\t\t\t\t\tif (item->getBattleType() == BT_NONE)\n\t\t\t\t\t{\n\t\t\t\t\t\tfor (auto* xcraft : *xbase->getCrafts())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\txcraft->reuseItem(item);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Remove transfer\n\t\t\t\tstd::ostringstream ss;\n\t\t\t\tss << transfer->getQuantity();\n\t\t\t\t_lstTransfers->addRow(3, transfer->getName(_game->getLanguage()).c_str(), ss.str().c_str(), xbase->getName().c_str());\n\t\t\t\tdelete transfer;\n\t\t\t\ttransferIt = xbase->getTransfers()->erase(transferIt);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t++transferIt;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n *\n */\nItemsArrivingState::~ItemsArrivingState()\n{\n\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid ItemsArrivingState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Goes to the base for the respective transfer.\n * @param action Pointer to an action.\n */\nvoid ItemsArrivingState::btnGotoBaseClick(Action *)\n{\n\t_state->timerReset();\n\t_game->popState();\n\t_game->pushState(new BasescapeState(_base, _state->getGlobe()));\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/ItemsArrivingState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass TextList;\nclass GeoscapeState;\nclass Base;\n\n/**\n * Items Arriving window that displays all\n * the items that have arrived at bases.\n */\nclass ItemsArrivingState : public State\n{\nprivate:\n\tGeoscapeState *_state;\n\tBase *_base;\n\tTextButton *_btnOk, *_btnGotoBase;\n\tWindow *_window;\n\tText *_txtTitle, *_txtItem, *_txtQuantity, *_txtDestination;\n\tTextList *_lstTransfers;\npublic:\n\t/// Creates the ItemsArriving state.\n\tItemsArrivingState(GeoscapeState *state);\n\t/// Cleans up the ItemsArriving state.\n\t~ItemsArrivingState();\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the Go To Base button.\n\tvoid btnGotoBaseClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/LowFuelState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"LowFuelState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Savegame/Craft.h\"\n#include \"GeoscapeState.h\"\n#include \"../Engine/Options.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Low Fuel window.\n * @param game Pointer to the core game.\n * @param craft Pointer to the craft to display.\n * @param state Pointer to the Geoscape.\n */\nLowFuelState::LowFuelState(Craft *craft, GeoscapeState *state) : _craft(craft), _state(state)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 224, 120, 16, 40, POPUP_BOTH);\n\t_btnOk = new TextButton(90, 18, 30, 120);\n\t_btnOk5Secs = new TextButton(90, 18, 136, 120);\n\t_txtTitle = new Text(214, 17, 21, 60);\n\t_txtMessage = new Text(214, 17, 21, 90);\n\n\t// Set palette\n\tsetInterface(\"lowFuel\");\n\n\tadd(_window, \"window\", \"lowFuel\");\n\tadd(_btnOk, \"button\", \"lowFuel\");\n\tadd(_btnOk5Secs, \"button\", \"lowFuel\");\n\tadd(_txtTitle, \"text\", \"lowFuel\");\n\tadd(_txtMessage, \"text\", \"lowFuel\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"lowFuel\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&LowFuelState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&LowFuelState::btnOkClick, Options::keyCancel);\n\n\t_btnOk5Secs->setText(tr(\"STR_OK_5_SECONDS\"));\n\t_btnOk5Secs->onMouseClick((ActionHandler)&LowFuelState::btnOk5SecsClick);\n\t_btnOk5Secs->onKeyboardPress((ActionHandler)&LowFuelState::btnOk5SecsClick, Options::keyOk);\n\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setBig();\n\t_txtTitle->setText(_craft->getName(_game->getLanguage()));\n\n\t_txtMessage->setAlign(ALIGN_CENTER);\n\t_txtMessage->setText(tr(\"STR_IS_LOW_ON_FUEL_RETURNING_TO_BASE\"));\n\n\n}\n\n/**\n *\n */\nLowFuelState::~LowFuelState()\n{\n\n}\n\n/**\n * Closes the window.\n * @param action Pointer to an action.\n */\nvoid LowFuelState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Closes the window and sets the timer to 5 Secs.\n * @param action Pointer to an action.\n */\nvoid LowFuelState::btnOk5SecsClick(Action *)\n{\n\t_state->timerReset();\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/LowFuelState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass Craft;\nclass GeoscapeState;\n\n/**\n * Window displayed when a craft starts running out of fuel\n * (only has exactly enough to make it back to base).\n */\nclass LowFuelState : public State\n{\nprivate:\n\tCraft *_craft;\n\tGeoscapeState *_state;\n\n\tTextButton *_btnOk, *_btnOk5Secs;\n\tWindow *_window;\n\tText *_txtTitle, *_txtMessage;\npublic:\n\t/// Creates the Low Fuel state.\n\tLowFuelState(Craft *craft, GeoscapeState *state);\n\t/// Cleans up the Low Fuel state.\n\t~LowFuelState();\n\t/// Handler for clicking the Ok button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the Ok - 5 Secs button.\n\tvoid btnOk5SecsClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/MissionDetectedState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"MissionDetectedState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"GeoscapeState.h\"\n#include \"Globe.h\"\n#include \"../Savegame/MissionSite.h\"\n#include \"../Engine/Options.h\"\n#include \"InterceptState.h\"\n#include \"../Mod/AlienDeployment.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Mission Detected window.\n * @param game Pointer to the core game.\n * @param mission Pointer to the respective Mission Site.\n * @param state Pointer to the Geoscape.\n */\nMissionDetectedState::MissionDetectedState(MissionSite *mission, GeoscapeState *state) : _mission(mission), _state(state)\n{\n\t_screen = false;\n\n\tint soundId = mission->getDeployment()->getAlertSound();\n\tif (soundId != Mod::NO_SOUND)\n\t{\n\t\t_customSound = _game->getMod()->getSound(\"GEO.CAT\", soundId);\n\t}\n\n\t// Create objects\n\t_window = new Window(this, 256, 200, 0, 0, POPUP_BOTH);\n\t_btnIntercept = new TextButton(200, 16, 28, 130);\n\t_btnCenter = new TextButton(200, 16, 28, 150);\n\t_btnCancel = new TextButton(200, 16, 28, 170);\n\t_txtTitle = new Text(246, 32, 5, 48);\n\t_txtCity = new Text(246, 17, 5, 80);\n\n\t// Set palette\n\tsetInterface(\"terrorSite\");\n\n\tadd(_window, \"window\", \"terrorSite\");\n\tadd(_btnIntercept, \"button\", \"terrorSite\");\n\tadd(_btnCenter, \"button\", \"terrorSite\");\n\tadd(_btnCancel, \"button\", \"terrorSite\");\n\tadd(_txtTitle, \"text\", \"terrorSite\");\n\tadd(_txtCity, \"text\", \"terrorSite\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\t_window->setBackground(_game->getMod()->getSurface(mission->getDeployment()->getAlertBackground()));\n\n\t_btnIntercept->setText(tr(\"STR_INTERCEPT\"));\n\t_btnIntercept->onMouseClick((ActionHandler)&MissionDetectedState::btnInterceptClick);\n\n\t_btnCenter->setText(tr(\"STR_CENTER_ON_SITE_TIME_5_SECONDS\"));\n\t_btnCenter->onMouseClick((ActionHandler)&MissionDetectedState::btnCenterClick);\n\n\t_btnCancel->setText(tr(\"STR_CANCEL_UC\"));\n\t_btnCancel->onMouseClick((ActionHandler)&MissionDetectedState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&MissionDetectedState::btnCancelClick, Options::keyCancel);\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setWordWrap(true);\n\t_txtTitle->setText(tr(mission->getDeployment()->getAlertMessage()));\n\n\t_txtCity->setBig();\n\t_txtCity->setAlign(ALIGN_CENTER);\n\t_txtCity->setText(tr(mission->getCity()));\n}\n\n/**\n *\n */\nMissionDetectedState::~MissionDetectedState()\n{\n\n}\n\n/**\n * Picks a craft to intercept the mission site.\n * @param action Pointer to an action.\n */\nvoid MissionDetectedState::btnInterceptClick(Action *)\n{\n\t_state->timerReset();\n\t_state->getGlobe()->center(_mission->getLongitude(), _mission->getLatitude());\n\t_game->pushState(new InterceptState(_state->getGlobe(), false, 0, _mission));\n}\n\n/**\n * Centers on the mission site and returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid MissionDetectedState::btnCenterClick(Action *)\n{\n\t_state->timerReset();\n\t_state->getGlobe()->center(_mission->getLongitude(), _mission->getLatitude());\n\t_game->popState();\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid MissionDetectedState::btnCancelClick(Action *)\n{\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/MissionDetectedState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass MissionSite;\nclass TextButton;\nclass Window;\nclass Text;\nclass GeoscapeState;\n\n/**\n * Displays info on a detected mission site.\n */\nclass MissionDetectedState : public State\n{\nprivate:\n\tMissionSite *_mission;\n\tGeoscapeState *_state;\n\n\tTextButton *_btnIntercept, *_btnCenter, *_btnCancel;\n\tWindow *_window;\n\tText *_txtTitle, *_txtCity;\npublic:\n\t/// Creates the Mission Detected state.\n\tMissionDetectedState(MissionSite *mission, GeoscapeState *state);\n\t/// Cleans up the Mission Detected state.\n\t~MissionDetectedState();\n\t/// Handler for clicking the Intercept button.\n\tvoid btnInterceptClick(Action *action);\n\t/// Handler for clicking the Center on Site button.\n\tvoid btnCenterClick(Action *action);\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/MonthlyReportState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"MonthlyReportState.h\"\n#include <climits>\n#include <sstream>\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/GameTime.h\"\n#include \"PsiTrainingState.h\"\n#include \"../Savegame/Region.h\"\n#include \"../Savegame/Country.h\"\n#include \"../Mod/RuleCountry.h\"\n#include \"Globe.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Menu/CutsceneState.h\"\n#include \"../Battlescape/CommendationState.h\"\n#include \"../Savegame/SoldierDiary.h\"\n#include \"../Menu/SaveGameState.h\"\n#include \"../Mod/RuleInterface.h\"\n#include \"../Mod/RuleVideo.h\"\n\nnamespace OpenXcom\n{\n/**\n * Initializes all the elements in the Monthly Report screen.\n * @param game Pointer to the core game.\n * @param psi Show psi training afterwards?\n * @param globe Pointer to the globe.\n */\nMonthlyReportState::MonthlyReportState(Globe *globe) : _gameOver(0), _ratingTotal(0), _fundingDiff(0), _lastMonthsRating(0), _happyList(0), _sadList(0), _pactList(0), _cancelPactList(0)\n{\n\t_globe = globe;\n\t// Create objects\n\t_window = new Window(this, 320, 200, 0, 0);\n\t_btnOk = new TextButton(50, 12, 135, 180);\n\t_btnBigOk = new TextButton(120, 18, 100, 174);\n\t_txtTitle = new Text(300, 17, 16, 8);\n\t_txtMonth = new Text(130, 9, 16, 24);\n\t_txtRating = new Text(160, 9, 146, 24);\n\t_txtIncome = new Text(300, 9, 16, 32);\n\t_txtMaintenance = new Text(130, 9, 16, 40);\n\t_txtBalance = new Text(160, 9, 146, 40);\n\t_txtBonus = new Text(300, 9, 16, 48);\n\t_txtDesc = new Text(280, 124, 16, 56);\n\t_txtFailure = new Text(290, 160, 15, 10);\n\n\t// Set palette\n\tsetInterface(\"monthlyReport\");\n\n\tadd(_window, \"window\", \"monthlyReport\");\n\tadd(_btnOk, \"button\", \"monthlyReport\");\n\tadd(_btnBigOk, \"button\", \"monthlyReport\");\n\tadd(_txtTitle, \"text1\", \"monthlyReport\");\n\tadd(_txtMonth, \"text1\", \"monthlyReport\");\n\tadd(_txtRating, \"text1\", \"monthlyReport\");\n\tadd(_txtIncome, \"text1\", \"monthlyReport\");\n\tadd(_txtMaintenance, \"text1\", \"monthlyReport\");\n\tadd(_txtBalance, \"text1\", \"monthlyReport\");\n\tadd(_txtBonus, \"text1\", \"monthlyReport\");\n\tadd(_txtDesc, \"text2\", \"monthlyReport\");\n\tadd(_txtFailure, \"text2\", \"monthlyReport\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"monthlyReport\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&MonthlyReportState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&MonthlyReportState::btnOkClick, Options::keyOk);\n\t_btnOk->onKeyboardPress((ActionHandler)&MonthlyReportState::btnOkClick, Options::keyCancel);\n\n\t_btnBigOk->setText(tr(\"STR_OK\"));\n\t_btnBigOk->onMouseClick((ActionHandler)&MonthlyReportState::btnOkClick);\n\t_btnBigOk->onKeyboardPress((ActionHandler)&MonthlyReportState::btnOkClick, Options::keyOk);\n\t_btnBigOk->onKeyboardPress((ActionHandler)&MonthlyReportState::btnOkClick, Options::keyCancel);\n\t_btnBigOk->setVisible(false);\n\n\t_txtTitle->setBig();\n\t_txtTitle->setText(tr(\"STR_XCOM_PROJECT_MONTHLY_REPORT\"));\n\n\t_txtFailure->setBig();\n\t_txtFailure->setAlign(ALIGN_CENTER);\n\t_txtFailure->setVerticalAlign(ALIGN_MIDDLE);\n\t_txtFailure->setWordWrap(true);\n\t_txtFailure->setText(tr(\"STR_YOU_HAVE_FAILED\"));\n\t_txtFailure->setVisible(false);\n\n\tcalculateChanges();\n\n\tint month = _game->getSavedGame()->getTime()->getMonth() - 1, year = _game->getSavedGame()->getTime()->getYear();\n\tif (month == 0)\n\t{\n\t\tmonth = 12;\n\t\tyear--;\n\t}\n\tstd::string m;\n\tswitch (month)\n\t{\n\tcase 1: m = \"STR_JAN\"; break;\n\tcase 2: m = \"STR_FEB\"; break;\n\tcase 3: m = \"STR_MAR\"; break;\n\tcase 4: m = \"STR_APR\"; break;\n\tcase 5: m = \"STR_MAY\"; break;\n\tcase 6: m = \"STR_JUN\"; break;\n\tcase 7: m = \"STR_JUL\"; break;\n\tcase 8: m = \"STR_AUG\"; break;\n\tcase 9: m = \"STR_SEP\"; break;\n\tcase 10: m = \"STR_OCT\"; break;\n\tcase 11: m = \"STR_NOV\"; break;\n\tcase 12: m = \"STR_DEC\"; break;\n\tdefault: m = \"\";\n\t}\n\t_txtMonth->setText(tr(\"STR_MONTH\").arg(tr(m)).arg(year));\n\n\t// Calculate rating\n\tint difficulty_threshold = _game->getMod()->getDefeatScore() + 100 * _game->getSavedGame()->getDifficultyCoefficient();\n\t{\n\t\tint diff = _game->getSavedGame()->getDifficulty();\n\t\tauto& custom = _game->getMod()->getMonthlyRatingThresholds();\n\t\tif (custom.size() > (size_t)diff)\n\t\t{\n\t\t\t// only negative values are allowed!\n\t\t\tif (custom[diff] < 0)\n\t\t\t{\n\t\t\t\tdifficulty_threshold = custom[diff];\n\t\t\t}\n\t\t}\n\t}\n\tstd::string rating = tr(\"STR_RATING_TERRIBLE\");\n\tif (_ratingTotal > difficulty_threshold - 300)\n\t{\n\t\trating = tr(\"STR_RATING_POOR\");\n\t}\n\tif (_ratingTotal > difficulty_threshold)\n\t{\n\t\trating = tr(\"STR_RATING_OK\");\n\t}\n\tif (_ratingTotal > 0)\n\t{\n\t\trating = tr(\"STR_RATING_GOOD\");\n\t}\n\tif (_ratingTotal > 500)\n\t{\n\t\trating = tr(\"STR_RATING_EXCELLENT\");\n\t}\n\n\tif (!_game->getMod()->getMonthlyRatings()->empty())\n\t{\n\t\trating = \"\";\n\t\tint temp = INT_MIN;\n\t\tfor (auto& pair : *_game->getMod()->getMonthlyRatings())\n\t\t{\n\t\t\tif (pair.first > temp && pair.first <= _ratingTotal)\n\t\t\t{\n\t\t\t\ttemp = pair.first;\n\t\t\t\trating = tr(pair.second);\n\t\t\t}\n\t\t}\n\t}\n\n\t_txtRating->setText(tr(\"STR_MONTHLY_RATING\").arg(_ratingTotal).arg(rating));\n\n\tstd::ostringstream ss;\n\tss << tr(\"STR_INCOME\") << \"> \" << Unicode::TOK_COLOR_FLIP << Unicode::formatFunding(_game->getSavedGame()->getCountryFunding());\n\tss << \" (\";\n\tif (_fundingDiff > 0)\n\t\tss << '+';\n\tss << Unicode::formatFunding(_fundingDiff) << \")\";\n\t_txtIncome->setText(ss.str());\n\n\tstd::ostringstream ss2;\n\tss2 << tr(\"STR_MAINTENANCE\") << \"> \" << Unicode::TOK_COLOR_FLIP << Unicode::formatFunding(_game->getSavedGame()->getBaseMaintenance());\n\t_txtMaintenance->setText(ss2.str());\n\n\tint performanceBonus = _game->getMod()->getPerformanceBonus(_ratingTotal);\n\tif (performanceBonus > 0)\n\t{\n\t\t// increase funds by performance bonus\n\t\t_game->getSavedGame()->setFunds(_game->getSavedGame()->getFunds() + performanceBonus);\n\t\t// display\n\t\tstd::ostringstream ss4;\n\t\tss4 << tr(\"STR_PERFORMANCE_BONUS\") << \"> \" << Unicode::TOK_COLOR_FLIP << Unicode::formatFunding(performanceBonus);\n\t\t_txtBonus->setText(ss4.str());\n\t\t// shuffle the fields a bit for better overview\n\t\tint upper = _txtMaintenance->getY();\n\t\tint lower = _txtBonus->getY();\n\t\t_txtMaintenance->setY(lower);\n\t\t_txtBalance->setY(lower);\n\t\t_txtBonus->setY(upper);\n\t}\n\telse\n\t{\n\t\t// vanilla view\n\t\t_txtBonus->setVisible(false);\n\t\t_txtDesc->setY(_txtBonus->getY());\n\t}\n\n\tstd::ostringstream ss3;\n\tss3 << tr(\"STR_BALANCE\") << \"> \" << Unicode::TOK_COLOR_FLIP << Unicode::formatFunding(_game->getSavedGame()->getFunds());\n\t_txtBalance->setText(ss3.str());\n\n\t_txtDesc->setWordWrap(true);\n\t_txtDesc->setScrollable(true);\n\n\t// calculate satisfaction\n\tstd::ostringstream ss5;\n\tstd::string satisFactionString = tr(\"STR_COUNCIL_IS_DISSATISFIED\");\n\tbool resetWarning = true;\n\tif (_ratingTotal > difficulty_threshold)\n\t{\n\t\tsatisFactionString = tr(\"STR_COUNCIL_IS_GENERALLY_SATISFIED\");\n\t}\n\tif (_ratingTotal > 500)\n\t{\n\t\tsatisFactionString = tr(\"STR_COUNCIL_IS_VERY_PLEASED\");\n\t}\n\tif (_lastMonthsRating <= difficulty_threshold && _ratingTotal <= difficulty_threshold)\n\t{\n\t\tsatisFactionString = tr(\"STR_YOU_HAVE_NOT_SUCCEEDED\");\n\t\t_pactList.erase(_pactList.begin(), _pactList.end());\n\t\t_cancelPactList.erase(_cancelPactList.begin(), _cancelPactList.end());\n\t\t_happyList.erase(_happyList.begin(), _happyList.end());\n\t\t_sadList.erase(_sadList.begin(), _sadList.end());\n\t\t_gameOver = 1;\n\t}\n\n\tss5 << satisFactionString;\n\n\tif (!_gameOver)\n\t{\n\t\tif (_game->getSavedGame()->getFunds() <= _game->getMod()->getDefeatFunds())\n\t\t{\n\t\t\tif (_game->getSavedGame()->getWarned())\n\t\t\t{\n\t\t\t\tss5.str(\"\");\n\t\t\t\tss5 << tr(\"STR_YOU_HAVE_NOT_SUCCEEDED\");\n\t\t\t\t_pactList.erase(_pactList.begin(), _pactList.end());\n\t\t\t\t_cancelPactList.erase(_cancelPactList.begin(), _cancelPactList.end());\n\t\t\t\t_happyList.erase(_happyList.begin(), _happyList.end());\n\t\t\t\t_sadList.erase(_sadList.begin(), _sadList.end());\n\t\t\t\t_gameOver = 2;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tss5 << \"\\n\\n\" << tr(\"STR_COUNCIL_REDUCE_DEBTS\");\n\t\t\t\t_game->getSavedGame()->setWarned(true);\n\t\t\t\tresetWarning = false;\n\t\t\t}\n\t\t}\n\t}\n\tif (resetWarning && _game->getSavedGame()->getWarned())\n\t{\n\t\t_game->getSavedGame()->setWarned(false);\n\t}\n\n\tss5 << countryList(_happyList, \"STR_COUNTRY_IS_PARTICULARLY_PLEASED\", \"STR_COUNTRIES_ARE_PARTICULARLY_HAPPY\");\n\tss5 << countryList(_sadList, \"STR_COUNTRY_IS_UNHAPPY_WITH_YOUR_ABILITY\", \"STR_COUNTRIES_ARE_UNHAPPY_WITH_YOUR_ABILITY\");\n\tss5 << countryList(_pactList, \"STR_COUNTRY_HAS_SIGNED_A_SECRET_PACT\", \"STR_COUNTRIES_HAVE_SIGNED_A_SECRET_PACT\");\n\tss5 << countryList(_cancelPactList, \"STR_COUNTRY_HAS_CANCELLED_A_SECRET_PACT\", \"STR_COUNTRIES_HAVE_CANCELLED_A_SECRET_PACT\");\n\n\t_txtDesc->setText(ss5.str());\n\n\t// Give modders some handles on political situation\n\tfor (const auto& traitorName : _pactList)\n\t{\n\t\tauto traitor = _game->getMod()->getCountry(traitorName, false);\n\t\tif (traitor)\n\t\t{\n\t\t\t_game->getSavedGame()->spawnEvent(traitor->getSignedPactEvent());\n\t\t}\n\t}\n\tfor (const auto& exTraitorName : _cancelPactList)\n\t{\n\t\tauto exTraitor = _game->getMod()->getCountry(exTraitorName, false);\n\t\tif (exTraitor)\n\t\t{\n\t\t\t_game->getSavedGame()->spawnEvent(exTraitor->getRejoinedXcomEvent());\n\t\t}\n\t}\n}\n\n/**\n *\n */\nMonthlyReportState::~MonthlyReportState()\n{\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid MonthlyReportState::btnOkClick(Action *)\n{\n\tif (!_gameOver)\n\t{\n\t\t_game->popState();\n\t\t// Award medals for service time\n\t\t// Iterate through all your bases\n\t\tfor (auto* xbase : *_game->getSavedGame()->getBases())\n\t\t{\n\t\t\t// Iterate through all your soldiers\n\t\t\tfor (auto* soldier : *xbase->getSoldiers())\n\t\t\t{\n\t\t\t\t// Award medals to eligible soldiers\n\t\t\t\tsoldier->getDiary()->addMonthlyService();\n\t\t\t\tif (soldier->getDiary()->manageCommendations(_game->getMod(), _game->getSavedGame(), soldier))\n\t\t\t\t{\n\t\t\t\t\t_soldiersMedalled.push_back(soldier);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (!_soldiersMedalled.empty())\n\t\t{\n\t\t\t_game->pushState(new CommendationState(_soldiersMedalled));\n\t\t}\n\n\t\tbool psi = false;\n\t\tfor (auto* xbase : *_game->getSavedGame()->getBases())\n\t\t{\n\t\t\tpsi = psi || xbase->getAvailablePsiLabs();\n\t\t}\n\t\tif (psi && !Options::anytimePsiTraining)\n\t\t{\n\t\t\t_game->pushState(new PsiTrainingState);\n\t\t}\n\t\t// Autosave\n\t\tif (_game->getSavedGame()->isIronman())\n\t\t{\n\t\t\t_game->pushState(new SaveGameState(OPT_GEOSCAPE, SAVE_IRONMAN, _palette));\n\t\t}\n\t\telse if (Options::autosave)\n\t\t{\n\t\t\t_game->pushState(new SaveGameState(OPT_GEOSCAPE, SAVE_AUTO_GEOSCAPE, _palette));\n\t\t}\n\t}\n\telse\n\t{\n\t\tif (_txtFailure->getVisible())\n\t\t{\n\t\t\t_game->popState(); // in case the cutscene is not marked as \"game over\" (by accident or not) let's return to the geoscape\n\n\t\t\tstd::string cutsceneId;\n\t\t\tif (_gameOver == 1)\n\t\t\t\tcutsceneId = _game->getMod()->getLoseRatingCutscene();\n\t\t\telse\n\t\t\t\tcutsceneId = _game->getMod()->getLoseMoneyCutscene();\n\n\t\t\tconst RuleVideo *videoRule = _game->getMod()->getVideo(cutsceneId, true);\n\t\t\tif (videoRule->getLoseGame())\n\t\t\t{\n\t\t\t\t_game->getSavedGame()->setEnding(END_LOSE);\n\t\t\t}\n\n\t\t\t_game->pushState(new CutsceneState(cutsceneId));\n\t\t\tif (_game->getSavedGame()->isIronman())\n\t\t\t{\n\t\t\t\t_game->pushState(new SaveGameState(OPT_GEOSCAPE, SAVE_IRONMAN, _palette));\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_window->setColor(_game->getMod()->getInterface(\"monthlyReport\")->getElement(\"window\")->color2);\n\t\t\t_txtTitle->setVisible(false);\n\t\t\t_txtMonth->setVisible(false);\n\t\t\t_txtRating->setVisible(false);\n\t\t\t_txtIncome->setVisible(false);\n\t\t\t_txtMaintenance->setVisible(false);\n\t\t\t_txtBalance->setVisible(false);\n\t\t\t_txtBonus->setVisible(false);\n\t\t\t_txtDesc->setVisible(false);\n\t\t\t_btnOk->setVisible(false);\n\t\t\t_btnBigOk->setVisible(true);\n\t\t\t_txtFailure->setVisible(true);\n\t\t\t_game->getMod()->playMusic(\"GMLOSE\");\n\t\t}\n\t}\n}\n\n/**\n * Update all our activity counters, gather all our scores,\n * get our countries to make sign pacts, adjust their fundings,\n * assess their satisfaction, and finally calculate our overall\n * total score, with thanks to Volutar for the formulas.\n */\nvoid MonthlyReportState::calculateChanges()\n{\n\t// initialize all our variables.\n\t_lastMonthsRating = 0;\n\tint xcomSubTotal = 0;\n\tint xcomTotal = 0;\n\tint alienTotal = 0;\n\tint monthOffset = _game->getSavedGame()->getFundsList().size() - 2;\n\tint lastMonthOffset = _game->getSavedGame()->getFundsList().size() - 3;\n\tif (lastMonthOffset < 0)\n\t\tlastMonthOffset += 2;\n\t// update activity meters, calculate a total score based on regional activity\n\t// and gather last month's score\n\tfor (auto* region : *_game->getSavedGame()->getRegions())\n\t{\n\t\tregion->newMonth();\n\t\tif (region->getActivityXcom().size() > 2)\n\t\t\t_lastMonthsRating += region->getActivityXcom().at(lastMonthOffset) - region->getActivityAlien().at(lastMonthOffset);\n\t\txcomSubTotal += region->getActivityXcom().at(monthOffset);\n\t\talienTotal += region->getActivityAlien().at(monthOffset);\n\t}\n\t// apply research bonus AFTER calculating our total, because this bonus applies to the council ONLY,\n\t// and shouldn't influence each country's decision.\n\n\t// the council is more lenient after the first month\n\tif (_game->getSavedGame()->getMonthsPassed() > 1)\n\t\t_game->getSavedGame()->getResearchScores().at(monthOffset) += 400;\n\n\txcomTotal = _game->getSavedGame()->getResearchScores().at(monthOffset) + xcomSubTotal;\n\n\tif (_game->getSavedGame()->getResearchScores().size() > 2)\n\t\t_lastMonthsRating += _game->getSavedGame()->getResearchScores().at(lastMonthOffset);\n\n\t// now that we have our totals we can send the relevant info to the countries\n\t// and have them make their decisions weighted on the council's perspective.\n\tconst RuleAlienMission *infiltration = _game->getMod()->getRandomMission(OBJECTIVE_INFILTRATION, _game->getSavedGame()->getMonthsPassed());\n\tint pactScore = 0;\n\tif (infiltration)\n\t{\n\t\tpactScore = infiltration->getPoints();\n\t}\n\tint averageFunding = _game->getSavedGame()->getCountryFunding() / _game->getSavedGame()->getCountries()->size() / 1000 * 1000;\n\tfor (auto* country : *_game->getSavedGame()->getCountries())\n\t{\n\t\t// check pact status before and after, because scripting can arbitrarily form/break pacts\n\t\tbool wasInPact = country->getPact();\n\n\t\t// determine satisfaction level, sign pacts, adjust funding\n\t\t// and update activity meters,\n\t\tcountry->newMonth(xcomTotal, alienTotal, pactScore, averageFunding, _game->getSavedGame());\n\t\t// and after they've made their decisions, calculate the difference, and add\n\t\t// them to the appropriate lists.\n\t\t_fundingDiff += country->getFunding().back() - country->getFunding().at(country->getFunding().size()-2);\n\n\t\tbool isInPact = country->getPact();\n\t\tif (!wasInPact && isInPact) // signed a new pact this month\n\t\t{\n\t\t\t_pactList.push_back(country->getRules()->getType());\n\t\t}\n\t\telse if (wasInPact && !isInPact) // renounced a pact this month\n\t\t{\n\t\t\t_cancelPactList.push_back(country->getRules()->getType());\n\t\t}\n\n\t\tswitch(country->getSatisfaction())\n\t\t{\n\t\tcase Country::Satisfaction::UNHAPPY:\n\t\t\t_sadList.push_back(country->getRules()->getType());\n\t\t\tbreak;\n\t\tcase Country::Satisfaction::HAPPY:\n\t\t\t_happyList.push_back(country->getRules()->getType());\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t}\n\t//calculate total.\n\t_ratingTotal = xcomTotal - alienTotal;\n}\n\n/**\n * Builds a sentence from a list of countries, adding the appropriate\n * separators and pluralization.\n * @param countries List of country string IDs.\n * @param singular String ID to append at the end if the list is singular.\n * @param plural String ID to append at the end if the list is plural.\n */\nstd::string MonthlyReportState::countryList(const std::vector<std::string> &countries, const std::string &singular, const std::string &plural)\n{\n\tstd::ostringstream ss;\n\tif (!countries.empty())\n\t{\n\t\tss << \"\\n\\n\";\n\t\tif (countries.size() == 1)\n\t\t{\n\t\t\tss << tr(singular).arg(tr(countries.front()));\n\t\t}\n\t\telse\n\t\t{\n\t\t\tLocalizedText list = tr(countries.front());\n\t\t\tstd::vector<std::string>::const_iterator i;\n\t\t\tfor (i = countries.begin() + 1; i < countries.end() - 1; ++i)\n\t\t\t{\n\t\t\t\tlist = tr(\"STR_COUNTRIES_COMMA\").arg(list).arg(tr(*i));\n\t\t\t}\n\t\t\tlist = tr(\"STR_COUNTRIES_AND\").arg(list).arg(tr(*i));\n\t\t\tss << tr(plural).arg(list);\n\t\t}\n\t}\n\treturn ss.str();\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/MonthlyReportState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include <vector>\n#include <string>\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass Globe;\nclass Base;\nclass Soldier;\n\n/**\n * Report screen shown monthly to display\n * changes in the player's performance and funding.\n */\nclass MonthlyReportState : public State\n{\nprivate:\n\tTextButton *_btnOk, *_btnBigOk;\n\tWindow *_window;\n\tText *_txtTitle, *_txtMonth, *_txtRating;\n\tText *_txtIncome, *_txtMaintenance, *_txtBalance, *_txtBonus;\n\tText *_txtDesc, *_txtFailure;\n\tint _gameOver;\n\tint _ratingTotal, _fundingDiff, _lastMonthsRating;\n\tstd::vector<std::string> _happyList, _sadList, _pactList, _cancelPactList;\n\tGlobe *_globe;\n\tstd::vector<Soldier*> _soldiersMedalled;\n\t/// Builds a country list string.\n\tstd::string countryList(const std::vector<std::string> &countries, const std::string &singular, const std::string &plural);\npublic:\n\t/// Creates the Monthly Report state.\n\tMonthlyReportState(Globe *globe);\n\t/// Cleans up the Monthly Report state.\n\t~MonthlyReportState();\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Calculate monthly scores.\n\tvoid calculateChanges();\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/MultipleTargetsState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"MultipleTargetsState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Savegame/Target.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/Craft.h\"\n#include \"../Savegame/Ufo.h\"\n#include \"GeoscapeState.h\"\n#include \"ConfirmDestinationState.h\"\n#include \"InterceptState.h\"\n#include \"UfoDetectedState.h\"\n#include \"GeoscapeCraftState.h\"\n#include \"TargetInfoState.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Action.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Multiple Targets window.\n * @param game Pointer to the core game.\n * @param targets List of targets to display.\n * @param craft Pointer to craft to retarget (NULL if none).\n * @param state Pointer to the Geoscape state.\n */\nMultipleTargetsState::MultipleTargetsState(std::vector<Target*> targets, std::vector<Craft*> crafts, GeoscapeState *state, bool useCustomSound) :\n\t_targets(targets), _crafts(std::move(crafts)), _state(state), _useCustomSound(useCustomSound)\n{\n\t_screen = false;\n\n\tif (_targets.size() > 1)\n\t{\n\t\tint winHeight = BUTTON_HEIGHT * _targets.size() + SPACING * (_targets.size() - 1) + MARGIN * 2;\n\t\tint winY = (200 - winHeight) / 2;\n\t\tint btnY = winY + MARGIN;\n\n\t\t// Create objects\n\t\t_window = new Window(this, 136, winHeight, 60, winY, POPUP_VERTICAL);\n\n\t\t// Set palette\n\t\tsetInterface(\"multipleTargets\");\n\n\t\tadd(_window, \"window\", \"multipleTargets\");\n\n\t\t// Set up objects\n\t\tsetWindowBackground(_window, \"multipleTargets\");\n\n\t\tint y = btnY;\n\t\tfor (size_t i = 0; i < _targets.size(); ++i)\n\t\t{\n\t\t\tTextButton *button = new TextButton(116, BUTTON_HEIGHT, 70, y);\n\t\t\tbutton->setText(_targets[i]->getName(_game->getLanguage()));\n\t\t\tbutton->onMouseClick((ActionHandler)&MultipleTargetsState::btnTargetClick);\n\t\t\tadd(button, \"button\", \"multipleTargets\");\n\n\t\t\t_btnTargets.push_back(button);\n\n\t\t\ty += button->getHeight() + SPACING;\n\t\t}\n\t\t_btnTargets[0]->onKeyboardPress((ActionHandler)&MultipleTargetsState::btnCancelClick, Options::keyCancel);\n\n\t\tcenterAllSurfaces();\n\t}\n}\n\n/**\n *\n */\nMultipleTargetsState::~MultipleTargetsState()\n{\n\n}\n\n/**\n * Resets the palette and ignores the window\n * if there's only one target.\n */\nvoid MultipleTargetsState::init()\n{\n\tif (_targets.size() == 1)\n\t{\n\t\tpopupTarget(*_targets.begin());\n\t}\n\telse\n\t{\n\t\tState::init();\n\t}\n}\n\n/**\n * Displays the right popup for a specific target.\n * @param target Pointer to target.\n */\nvoid MultipleTargetsState::popupTarget(Target *target)\n{\n\t_game->popState();\n\tif (_crafts.size() == 0)\n\t{\n\t\tBase* b = dynamic_cast<Base*>(target);\n\t\tCraft* c = dynamic_cast<Craft*>(target);\n\t\tUfo* u = dynamic_cast<Ufo*>(target);\n\t\tif (b != 0)\n\t\t{\n\t\t\t_game->pushState(new InterceptState(_state->getGlobe(), _useCustomSound, b));\n\t\t}\n\t\telse if (c != 0)\n\t\t{\n\t\t\t_game->pushState(new GeoscapeCraftState(c, _state->getGlobe(), 0, _useCustomSound));\n\t\t}\n\t\telse if (u != 0)\n\t\t{\n\t\t\t_game->pushState(new UfoDetectedState(u, _state, false, u->getHyperDetected()));\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_game->pushState(new TargetInfoState(target, _state->getGlobe()));\n\t\t}\n\t}\n\telse\n\t{\n\t\t_game->pushState(new ConfirmDestinationState(_crafts, target));\n\t}\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid MultipleTargetsState::btnCancelClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Pick a target to display.\n * @param action Pointer to an action.\n */\nvoid MultipleTargetsState::btnTargetClick(Action *action)\n{\n\tfor (size_t i = 0; i < _btnTargets.size(); ++i)\n\t{\n\t\tif (action->getSender() == _btnTargets[i])\n\t\t{\n\t\t\tpopupTarget(_targets[i]);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/MultipleTargetsState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include <vector>\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Craft;\nclass Target;\nclass GeoscapeState;\n\n/**\n * Displays a list of possible targets.\n */\nclass MultipleTargetsState : public State\n{\nprivate:\n\tstatic const int MARGIN = 10;\n\tstatic const int SPACING = 4;\n\tstatic const int BUTTON_HEIGHT = 16;\n\n\tstd::vector<Target*> _targets;\n\tstd::vector<Craft*> _crafts;\n\tGeoscapeState *_state;\n\tbool _useCustomSound;\n\n\tWindow *_window;\n\tstd::vector<TextButton*> _btnTargets;\npublic:\n\t/// Creates the Multiple Targets state.\n\tMultipleTargetsState(std::vector<Target*> targets, std::vector<Craft*> crafts, GeoscapeState *state, bool useCustomSound);\n\t/// Cleans up the Multiple Targets state.\n\t~MultipleTargetsState();\n\t/// Updates the window.\n\tvoid init() override;\n\t/// Popup for a target.\n\tvoid popupTarget(Target *target);\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action *action);\n\t/// Handler for clicking the Targets list.\n\tvoid btnTargetClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/NewPossibleCraftState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"NewPossibleCraftState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Mod/RuleCraft.h\"\n#include \"../Basescape/PurchaseState.h\"\n#include \"../Engine/Options.h\"\n\nnamespace OpenXcom\n{\n/**\n * Initializes all the elements in the NewPossibleCraft screen.\n * @param base Pointer to the base to get info from.\n * @param possibilities List of newly possible craft to buy/rent\n */\nNewPossibleCraftState::NewPossibleCraftState(Base * base, const std::vector<RuleCraft *> & possibilities) : _base(base)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 288, 180, 16, 10);\n\t_btnOk = new TextButton(160, 14, 80, 149);\n\t_btnPurchase = new TextButton(160, 14, 80, 165);\n\t_txtTitle = new Text(288, 40, 16, 20);\n\t_lstPossibilities = new TextList(250, 80, 35, 50);\n\t_txtCaveat = new Text(250, 16, 35, 131);\n\n\t// Set palette\n\tsetInterface(\"geoNewCraft\");\n\n\tadd(_window, \"window\", \"geoNewCraft\");\n\tadd(_btnOk, \"button\", \"geoNewCraft\");\n\tadd(_btnPurchase, \"button\", \"geoNewCraft\");\n\tadd(_txtTitle, \"text1\", \"geoNewCraft\");\n\tadd(_lstPossibilities, \"text2\", \"geoNewCraft\");\n\tadd(_txtCaveat, \"text1\", \"geoNewCraft\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"geoNewCraft\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&NewPossibleCraftState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&NewPossibleCraftState::btnOkClick, Options::keyCancel);\n\t_btnPurchase->setText(tr(\"STR_PURCHASE_HIRE_PERSONNEL\"));\n\t_btnPurchase->onMouseClick((ActionHandler)&NewPossibleCraftState::btnPurchaseClick);\n\t_btnPurchase->onKeyboardPress((ActionHandler)&NewPossibleCraftState::btnPurchaseClick, Options::keyOk);\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_WE_CAN_NOW_RENT\"));\n\n\t// Caveat\n\t{\n\t\tRuleBaseFacilityFunctions requiredServices;\n\t\tfor (const auto* ruleCraft : possibilities)\n\t\t{\n\t\t\trequiredServices |= ruleCraft->getRequiresBuyBaseFunc();\n\t\t}\n\t\tstd::ostringstream ss;\n\t\tint i = 0;\n\t\tfor (const auto& serviceName : _game->getMod()->getBaseFunctionNames(requiredServices))\n\t\t{\n\t\t\tif (i > 0)\n\t\t\t\tss << \", \";\n\t\t\tss << tr(serviceName);\n\t\t\ti++;\n\t\t}\n\t\tstd::string argument = ss.str();\n\n\t\t_txtCaveat->setAlign(ALIGN_CENTER);\n\t\t_txtCaveat->setText(tr(\"STR_REQUIRED_BASE_SERVICES\").arg(argument));\n\t\t_txtCaveat->setVisible(requiredServices.any());\n\t}\n\n\t_lstPossibilities->setColumns(1, 250);\n\t_lstPossibilities->setBig();\n\t_lstPossibilities->setAlign(ALIGN_CENTER);\n\t_lstPossibilities->setScrolling(true, 0);\n\tfor (const auto* ruleCraft : possibilities)\n\t{\n\t\t_lstPossibilities->addRow (1, tr(ruleCraft->getType()).c_str());\n\t}\n}\n\n/**\n * Closes the screen.\n * @param action Pointer to an action.\n */\nvoid NewPossibleCraftState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Opens the PurchaseState.\n * @param action Pointer to an action.\n */\nvoid NewPossibleCraftState::btnPurchaseClick(Action *)\n{\n\t_game->popState();\n\t_game->pushState(new PurchaseState(_base));\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/NewPossibleCraftState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass Game;\nclass Window;\nclass TextButton;\nclass Text;\nclass Base;\nclass TextList;\nclass RuleCraft;\n\n/**\n * Window which informs the player of new possible craft to buy/rent.\n * Also allows to go to the PurchaseState to order some new craft.\n */\nclass NewPossibleCraftState : public State\n{\nprivate:\n\tWindow *_window;\n\tText *_txtTitle;\n\tTextList * _lstPossibilities;\n\tText* _txtCaveat;\n\tTextButton *_btnPurchase, *_btnOk;\n\tBase * _base;\npublic:\n\t/// Creates the NewPossibleCraftState state.\n\tNewPossibleCraftState(Base * base, const std::vector<RuleCraft *> & possibilities);\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the Purchase button.\n\tvoid btnPurchaseClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/NewPossibleFacilityState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"NewPossibleFacilityState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Mod/RuleBaseFacility.h\"\n#include \"../Basescape/BasescapeState.h\"\n#include \"../Engine/Options.h\"\n\nnamespace OpenXcom\n{\n/**\n * Initializes all the elements in the NewPossibleFacility screen.\n * @param base Pointer to the base to get info from.\n * @param globe Pointer to the globe.\n * @param possibilities List of newly possible base facilities to build\n */\nNewPossibleFacilityState::NewPossibleFacilityState(Base *base, Globe *globe, const std::vector<RuleBaseFacility *> & possibilities) : _base(base), _globe(globe)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 288, 180, 16, 10);\n\t_btnOk = new TextButton(160, 14, 80, 149);\n\t_btnOpen = new TextButton(160, 14, 80, 165);\n\t_txtTitle = new Text(288, 40, 16, 20);\n\t_lstPossibilities = new TextList(250, 80, 35, 50);\n\t_txtCaveat = new Text(250, 16, 35, 131);\n\n\t// Set palette\n\tsetInterface(\"geoNewFacility\");\n\n\tadd(_window, \"window\", \"geoNewFacility\");\n\tadd(_btnOk, \"button\", \"geoNewFacility\");\n\tadd(_btnOpen, \"button\", \"geoNewFacility\");\n\tadd(_txtTitle, \"text1\", \"geoNewFacility\");\n\tadd(_lstPossibilities, \"text2\", \"geoNewFacility\");\n\tadd(_txtCaveat, \"text1\", \"geoNewFacility\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"geoNewFacility\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&NewPossibleFacilityState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&NewPossibleFacilityState::btnOkClick, Options::keyCancel);\n\t_btnOpen->setText(tr(\"STR_BASES\"));\n\t_btnOpen->onMouseClick((ActionHandler)&NewPossibleFacilityState::btnOpenClick);\n\t_btnOpen->onKeyboardPress((ActionHandler)&NewPossibleFacilityState::btnOpenClick, Options::keyOk);\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_WE_CAN_NOW_BUILD\"));\n\n\t// Caveat\n\t{\n\t\tRuleBaseFacilityFunctions requiredServices;\n\t\tfor (const auto* facRule : possibilities)\n\t\t{\n\t\t\trequiredServices |= facRule->getRequireBaseFunc();\n\t\t}\n\t\tstd::ostringstream ss;\n\t\tint i = 0;\n\t\tfor (const auto& serviceName : _game->getMod()->getBaseFunctionNames(requiredServices))\n\t\t{\n\t\t\tif (i > 0)\n\t\t\t\tss << \", \";\n\t\t\tss << tr(serviceName);\n\t\t\ti++;\n\t\t}\n\t\tstd::string argument = ss.str();\n\n\t\t_txtCaveat->setAlign(ALIGN_CENTER);\n\t\t_txtCaveat->setText(tr(\"STR_REQUIRED_BASE_SERVICES\").arg(argument));\n\t\t_txtCaveat->setVisible(requiredServices.any());\n\t}\n\n\t_lstPossibilities->setColumns(1, 250);\n\t_lstPossibilities->setBig();\n\t_lstPossibilities->setAlign(ALIGN_CENTER);\n\t_lstPossibilities->setScrolling(true, 0);\n\tfor (const auto* facRule : possibilities)\n\t{\n\t\t_lstPossibilities->addRow (1, tr(facRule->getType()).c_str());\n\t}\n}\n\n/**\n * Closes the screen.\n * @param action Pointer to an action.\n */\nvoid NewPossibleFacilityState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Opens the BaseView.\n * @param action Pointer to an action.\n */\nvoid NewPossibleFacilityState::btnOpenClick(Action *)\n{\n\t_game->popState();\n\t_game->pushState(new BasescapeState(_base, _globe));\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/NewPossibleFacilityState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass Game;\nclass Window;\nclass TextButton;\nclass Text;\nclass Base;\nclass Globe;\nclass TextList;\nclass RuleBaseFacility;\n\n/**\n * Window which informs the player of new possible base facility to build.\n * Also allows to go to the BaseView to build some new facilities.\n */\nclass NewPossibleFacilityState : public State\n{\nprivate:\n\tWindow *_window;\n\tText *_txtTitle;\n\tTextList * _lstPossibilities;\n\tText* _txtCaveat;\n\tTextButton *_btnOpen, *_btnOk;\n\tBase *_base;\n\tGlobe *_globe;\npublic:\n\t/// Creates the NewPossibleFacilityState state.\n\tNewPossibleFacilityState(Base *base, Globe *globe, const std::vector<RuleBaseFacility *> & possibilities);\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the Open button.\n\tvoid btnOpenClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/NewPossibleManufactureState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"NewPossibleManufactureState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Mod/RuleManufacture.h\"\n#include \"../Basescape/ManufactureState.h\"\n#include \"../Engine/Options.h\"\n\nnamespace OpenXcom\n{\n/**\n * Initializes all the elements in the EndManufacture screen.\n * @param game Pointer to the core game.\n * @param base Pointer to the base to get info from.\n * @param possibilities List of newly possible ManufactureProject\n */\nNewPossibleManufactureState::NewPossibleManufactureState(Base * base, const std::vector<RuleManufacture *> & possibilities) : _base(base)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 288, 180, 16, 10);\n\t_btnOk = new TextButton(160, 14, 80, 149);\n\t_btnManufacture = new TextButton(160, 14, 80, 165);\n\t_txtTitle = new Text(288, 40, 16, 20);\n\t_lstPossibilities = new TextList(250, 80, 35, 50);\n\t_txtCaveat = new Text(250, 16, 35, 131);\n\n\t// Set palette\n\tsetInterface(\"geoManufacture\");\n\n\tadd(_window, \"window\", \"geoManufacture\");\n\tadd(_btnOk, \"button\", \"geoManufacture\");\n\tadd(_btnManufacture, \"button\", \"geoManufacture\");\n\tadd(_txtTitle, \"text1\", \"geoManufacture\");\n\tadd(_lstPossibilities, \"text2\", \"geoManufacture\");\n\tadd(_txtCaveat, \"text1\", \"geoManufacture\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"geoManufacture\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&NewPossibleManufactureState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&NewPossibleManufactureState::btnOkClick, Options::keyCancel);\n\t_btnManufacture->setText(tr(\"STR_ALLOCATE_MANUFACTURE\"));\n\t_btnManufacture->onMouseClick((ActionHandler)&NewPossibleManufactureState::btnManufactureClick);\n\t_btnManufacture->onKeyboardPress((ActionHandler)&NewPossibleManufactureState::btnManufactureClick, Options::keyOk);\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_WE_CAN_NOW_PRODUCE\"));\n\n\t// Caveat\n\t{\n\t\tRuleBaseFacilityFunctions requiredServices;\n\t\tfor (const auto* manuf : possibilities)\n\t\t{\n\t\t\trequiredServices |= manuf->getRequireBaseFunc();\n\t\t}\n\t\tstd::ostringstream ss;\n\t\tint i = 0;\n\t\tfor (const auto& serviceName : _game->getMod()->getBaseFunctionNames(requiredServices))\n\t\t{\n\t\t\tif (i > 0)\n\t\t\t\tss << \", \";\n\t\t\tss << tr(serviceName);\n\t\t\ti++;\n\t\t}\n\t\tstd::string argument = ss.str();\n\n\t\t_txtCaveat->setAlign(ALIGN_CENTER);\n\t\t_txtCaveat->setText(tr(\"STR_REQUIRED_BASE_SERVICES\").arg(argument));\n\t\t_txtCaveat->setVisible(requiredServices.any());\n\t}\n\n\t_lstPossibilities->setColumns(1, 250);\n\t_lstPossibilities->setBig();\n\t_lstPossibilities->setAlign(ALIGN_CENTER);\n\t_lstPossibilities->setScrolling(true, 0);\n\tfor (const auto* manuf : possibilities)\n\t{\n\t\t_lstPossibilities->addRow (1, tr(manuf->getName()).c_str());\n\t}\n}\n\n/**\n * return to the previous screen\n * @param action Pointer to an action.\n */\nvoid NewPossibleManufactureState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Open the ManufactureState so the player can dispatch available scientist.\n * @param action Pointer to an action.\n */\nvoid NewPossibleManufactureState::btnManufactureClick(Action *)\n{\n\t_game->popState();\n\t_game->pushState (new ManufactureState(_base));\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/NewPossibleManufactureState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass Game;\nclass Window;\nclass TextButton;\nclass Text;\nclass Base;\nclass TextList;\nclass RuleManufacture;\n\n/**\n * Window which inform the player of new possible manufacture projects.\n * Also allow to go to the ManufactureState to dispatch available engineers.\n */\nclass NewPossibleManufactureState : public State\n{\nprivate:\n\tWindow *_window;\n\tText *_txtTitle;\n\tTextList * _lstPossibilities;\n\tText* _txtCaveat;\n\tTextButton *_btnManufacture, *_btnOk;\n\tBase * _base;\npublic:\n\t/// Creates the NewPossibleManufacture state.\n\tNewPossibleManufactureState(Base * base, const std::vector<RuleManufacture *> & possibilities);\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the Allocate Manufacture button.\n\tvoid btnManufactureClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/NewPossiblePurchaseState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"NewPossiblePurchaseState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"../Basescape/PurchaseState.h\"\n#include \"../Engine/Options.h\"\n\nnamespace OpenXcom\n{\n/**\n * Initializes all the elements in the EndManufacture screen.\n * @param base Pointer to the base to get info from.\n * @param possibilities List of newly possible items to buy\n */\nNewPossiblePurchaseState::NewPossiblePurchaseState(Base * base, const std::vector<RuleItem *> & possibilities) : _base(base)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 288, 180, 16, 10);\n\t_btnOk = new TextButton(160, 14, 80, 149);\n\t_btnPurchase = new TextButton(160, 14, 80, 165);\n\t_txtTitle = new Text(288, 40, 16, 20);\n\t_lstPossibilities = new TextList(250, 80, 35, 50);\n\t_txtCaveat = new Text(250, 16, 35, 131);\n\n\t// Set palette\n\tsetInterface(\"geoNewItem\");\n\n\tadd(_window, \"window\", \"geoNewItem\");\n\tadd(_btnOk, \"button\", \"geoNewItem\");\n\tadd(_btnPurchase, \"button\", \"geoNewItem\");\n\tadd(_txtTitle, \"text1\", \"geoNewItem\");\n\tadd(_lstPossibilities, \"text2\", \"geoNewItem\");\n\tadd(_txtCaveat, \"text1\", \"geoNewItem\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"geoNewItem\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&NewPossiblePurchaseState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&NewPossiblePurchaseState::btnOkClick, Options::keyCancel);\n\t_btnPurchase->setText(tr(\"STR_PURCHASE_HIRE_PERSONNEL\"));\n\t_btnPurchase->onMouseClick((ActionHandler)&NewPossiblePurchaseState::btnPurchaseClick);\n\t_btnPurchase->onKeyboardPress((ActionHandler)&NewPossiblePurchaseState::btnPurchaseClick, Options::keyOk);\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_WE_CAN_NOW_PURCHASE\"));\n\n\t// Caveat\n\t{\n\t\tRuleBaseFacilityFunctions requiredServices;\n\t\tfor (const auto* ruleItem : possibilities)\n\t\t{\n\t\t\trequiredServices |= ruleItem->getRequiresBuyBaseFunc();\n\t\t}\n\t\tstd::ostringstream ss;\n\t\tint i = 0;\n\t\tfor (const auto& serviceName : _game->getMod()->getBaseFunctionNames(requiredServices))\n\t\t{\n\t\t\tif (i > 0)\n\t\t\t\tss << \", \";\n\t\t\tss << tr(serviceName);\n\t\t\ti++;\n\t\t}\n\t\tstd::string argument = ss.str();\n\n\t\t_txtCaveat->setAlign(ALIGN_CENTER);\n\t\t_txtCaveat->setText(tr(\"STR_REQUIRED_BASE_SERVICES\").arg(argument));\n\t\t_txtCaveat->setVisible(requiredServices.any());\n\t}\n\n\t_lstPossibilities->setColumns(1, 250);\n\t_lstPossibilities->setBig();\n\t_lstPossibilities->setAlign(ALIGN_CENTER);\n\t_lstPossibilities->setScrolling(true, 0);\n\tfor (const auto* ruleItem : possibilities)\n\t{\n\t\t_lstPossibilities->addRow (1, tr(ruleItem->getType()).c_str());\n\t}\n}\n\n/**\n * Closes the screen.\n * @param action Pointer to an action.\n */\nvoid NewPossiblePurchaseState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Opens the PurchaseState.\n * @param action Pointer to an action.\n */\nvoid NewPossiblePurchaseState::btnPurchaseClick(Action *)\n{\n\t_game->popState();\n\t_game->pushState(new PurchaseState(_base));\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/NewPossiblePurchaseState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass Game;\nclass Window;\nclass TextButton;\nclass Text;\nclass Base;\nclass TextList;\nclass RuleItem;\n\n/**\n * Window which inform the player of new possible items to buy.\n * Also allows to go to the PurchaseState to order some new items.\n */\nclass NewPossiblePurchaseState : public State\n{\nprivate:\n\tWindow *_window;\n\tText *_txtTitle;\n\tTextList * _lstPossibilities;\n\tText* _txtCaveat;\n\tTextButton *_btnPurchase, *_btnOk;\n\tBase * _base;\npublic:\n\t/// Creates the NewPossiblePurchaseState state.\n\tNewPossiblePurchaseState(Base * base, const std::vector<RuleItem *> & possibilities);\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the Purchase button.\n\tvoid btnPurchaseClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/NewPossibleResearchState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <algorithm>\n#include \"NewPossibleResearchState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Mod/RuleResearch.h\"\n#include \"../Basescape/ResearchState.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Engine/Options.h\"\n\nnamespace OpenXcom\n{\n/**\n * Initializes all the elements in the EndResearch screen.\n * @param game Pointer to the core game.\n * @param base Pointer to the base to get info from.\n * @param possibilities List of newly possible ResearchProject\n */\nNewPossibleResearchState::NewPossibleResearchState(Base * base, const std::vector<RuleResearch *> & possibilities) : _base(base)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 288, 180, 16, 10);\n\t_btnOk = new TextButton(160, 14, 80, 149);\n\t_btnResearch = new TextButton(160, 14, 80, 165);\n\t_txtTitle = new Text(288, 40, 16, 20);\n\t_lstPossibilities = new TextList(250, 96, 35, 50);\n\n\t// Set palette\n\tsetInterface(\"geoResearch\");\n\n\tadd(_window, \"window\", \"geoResearch\");\n\tadd(_btnOk, \"button\", \"geoResearch\");\n\tadd(_btnResearch, \"button\", \"geoResearch\");\n\tadd(_txtTitle, \"text1\", \"geoResearch\");\n\tadd(_lstPossibilities, \"text2\", \"geoResearch\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"geoResearch\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&NewPossibleResearchState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&NewPossibleResearchState::btnOkClick, Options::keyCancel);\n\t_btnResearch->setText(tr(\"STR_ALLOCATE_RESEARCH\"));\n\t_btnResearch->onMouseClick((ActionHandler)&NewPossibleResearchState::btnResearchClick);\n\t_btnResearch->onKeyboardPress((ActionHandler)&NewPossibleResearchState::btnResearchClick, Options::keyOk);\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\n\t_lstPossibilities->setColumns(1, 250);\n\t_lstPossibilities->setBig();\n\t_lstPossibilities->setAlign(ALIGN_CENTER);\n\t_lstPossibilities->setScrolling(true, 0);\n\n\tbool foundNew = false;\n\tfor (const auto* rule : possibilities)\n\t{\n\t\t// Note: ignore all topics with \"requires\" (same reason as in NewResearchListState::fillProjectList())\n\t\tif (rule->getRequirements().empty())\n\t\t{\n\t\t\t// Also ignore:\n\t\t\t// 1. things that already popped before\n\t\t\t// 2. things that never popped, but are researched already (can happen for topics that can be researched multiple times)\n\t\t\tif (!_game->getSavedGame()->wasResearchPopped(rule) && !_game->getSavedGame()->isResearched(rule, false))\n\t\t\t{\n\t\t\t\t_game->getSavedGame()->addPoppedResearch(rule);\n\t\t\t\t_lstPossibilities->addRow(1, tr(rule->getName()).c_str());\n\t\t\t\tfoundNew = true;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (foundNew)\n\t{\n\t\t_txtTitle->setText(tr(\"STR_WE_CAN_NOW_RESEARCH\"));\n\t}\n}\n\n/**\n * return to the previous screen\n * @param action Pointer to an action.\n */\nvoid NewPossibleResearchState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Open the ResearchState so the player can dispatch available scientist.\n * @param action Pointer to an action.\n */\nvoid NewPossibleResearchState::btnResearchClick(Action *)\n{\n\t_game->popState();\n\t_game->pushState (new ResearchState(_base));\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/NewPossibleResearchState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass Game;\nclass Window;\nclass TextButton;\nclass Text;\nclass Base;\nclass TextList;\nclass RuleResearch;\n\n/**\n * Window which inform the player of new possible research projects.\n * Also allow to go to the ResearchState to dispatch available scientist.\n */\nclass NewPossibleResearchState : public State\n{\nprivate:\n\tWindow *_window;\n\tText *_txtTitle;\n\tTextList * _lstPossibilities;\n\tTextButton *_btnResearch, *_btnOk;\n\tBase * _base;\npublic:\n\t/// Creates the NewPossibleResearch state.\n\tNewPossibleResearchState(Base * base, const std::vector<RuleResearch *> & possibilities);\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the Allocate Research button.\n\tvoid btnResearchClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/ProductionCompleteState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <assert.h>\n#include \"ProductionCompleteState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleManufacture.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"GeoscapeState.h\"\n#include \"../Engine/Options.h\"\n#include \"../Basescape/BasescapeState.h\"\n#include \"../Basescape/ManufactureState.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/ItemContainer.h\"\n#include \"../Savegame/SavedGame.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in a Production Complete window.\n * @param game Pointer to the core game.\n * @param base Pointer to base the production belongs to.\n * @param item Item that finished producing.\n * @param state Pointer to the Geoscape state.\n * @param endType What ended the production.\n * @param production Pointer to the production details.\n */\nProductionCompleteState::ProductionCompleteState(Base *base, const std::string &item, GeoscapeState *state, productionProgress_e endType, Production *production) : _base(base), _state(state), _endType(endType)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 256, 160, 32, 20, POPUP_BOTH);\n\t_btnOk = new TextButton(118, 18, 40, 154);\n\t_btnGotoBase = new TextButton(118, 18, 162, 154);\n\t_btnSummary = new TextButton(118, 18, 162, 154);\n\t_txtMessage = new Text(246, 110, 37, 35);\n\t_txtItem = new Text(160, 9, 47, 35);\n\t_txtQuantity = new Text(70, 9, 209, 35);\n\t_lstSummary = new TextList(224, 96, 39, 45);\n\n\t// Set palette\n\tsetInterface(\"geoManufactureComplete\");\n\n\tadd(_window, \"window\", \"geoManufactureComplete\");\n\tadd(_btnOk, \"button\", \"geoManufactureComplete\");\n\tadd(_btnGotoBase, \"button\", \"geoManufactureComplete\");\n\tadd(_btnSummary, \"button\", \"geoManufactureComplete\");\n\tadd(_txtMessage, \"text1\", \"geoManufactureComplete\");\n\tadd(_txtItem, \"text1\", \"geoManufactureComplete\");\n\tadd(_txtQuantity, \"text1\", \"geoManufactureComplete\");\n\tadd(_lstSummary, \"list\", \"geoManufactureComplete\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"geoManufactureComplete\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&ProductionCompleteState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&ProductionCompleteState::btnOkClick, Options::keyCancel);\n\n\tif (_endType != PROGRESS_CONSTRUCTION)\n\t{\n\t\t_btnGotoBase->setText(tr(\"STR_ALLOCATE_MANUFACTURE\"));\n\t}\n\telse\n\t{\n\t\t_btnGotoBase->setText(tr(\"STR_GO_TO_BASE\"));\n\t}\n\t_btnGotoBase->onMouseClick((ActionHandler)&ProductionCompleteState::btnGotoBaseClick);\n\n\t_btnSummary->setText(tr(\"STR_RANDOM_PRODUCTION_SUMMARY\"));\n\t_btnSummary->onMouseClick((ActionHandler)&ProductionCompleteState::btnSummaryClick);\n\n\t_txtItem->setText(tr(\"STR_ITEM\"));\n\t_txtItem->setVisible(false);\n\n\t_txtQuantity->setText(tr(\"STR_QUANTITY_UC\"));\n\t_txtQuantity->setVisible(false);\n\n\t_lstSummary->setColumns(2, 162, 46);\n\t_lstSummary->setBackground(_window);\n\t_lstSummary->setSelectable(true);\n\t_lstSummary->setMargin(8);\n\t_lstSummary->setVisible(false);\n\t_lstSummary->onMouseClick((ActionHandler)&ProductionCompleteState::lstSummaryClick, SDL_BUTTON_RIGHT);\n\n\tif (production && !production->getRules()->getRandomProducedItems().empty())\n\t{\n\t\t_btnGotoBase->setVisible(false);\n\t\t_randomProductionInfo = production->getRandomProductionInfo(); // local copy is necessary\n\t\t_index.reserve(_randomProductionInfo.size());\n\t\tfor (auto& each : production->getRandomProductionInfo())\n\t\t{\n\t\t\tstd::ostringstream ss;\n\t\t\tss << each.second;\n\t\t\t_lstSummary->addRow(2, tr(each.first).c_str(), ss.str().c_str());\n\t\t\t_index.push_back(each.first);\n\t\t}\n\t}\n\telse\n\t{\n\t\t_btnSummary->setVisible(false);\n\t}\n\n\t_txtMessage->setAlign(ALIGN_CENTER);\n\t_txtMessage->setVerticalAlign(ALIGN_MIDDLE);\n\t_txtMessage->setBig();\n\t_txtMessage->setWordWrap(true);\n\tstd::string s;\n\tswitch(_endType)\n\t{\n\tcase PROGRESS_CONSTRUCTION:\n\t\ts = tr(\"STR_CONSTRUCTION_OF_FACILITY_AT_BASE_IS_COMPLETE\").arg(item).arg(base->getName());\n\t\tbreak;\n\tcase PROGRESS_COMPLETE:\n\t\ts = tr(\"STR_PRODUCTION_OF_ITEM_AT_BASE_IS_COMPLETE\").arg(item).arg(base->getName());\n\t\tbreak;\n\tcase PROGRESS_NOT_ENOUGH_MONEY:\n\t\ts = tr(\"STR_NOT_ENOUGH_MONEY_TO_PRODUCE_ITEM_AT_BASE\").arg(item).arg(base->getName());\n\t\tbreak;\n\tcase PROGRESS_NOT_ENOUGH_MATERIALS:\n\t\ts = tr(\"STR_NOT_ENOUGH_SPECIAL_MATERIALS_TO_PRODUCE_ITEM_AT_BASE\").arg(item).arg(base->getName());\n\t\tbreak;\n\tcase PROGRESS_NOT_ENOUGH_LIVING_SPACE:\n\t\ts = tr(\"STR_NOT_ENOUGH_LIVING_SPACE_AT_BASE\").arg(item).arg(base->getName());\n\t\tbreak;\n\tdefault:\n\t\tassert(false);\n\t}\n\t_txtMessage->setText(s);\n}\n\n/**\n *\n */\nProductionCompleteState::~ProductionCompleteState()\n{\n\n}\n\n/**\n * Closes the window.\n * @param action Pointer to an action.\n */\nvoid ProductionCompleteState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Goes to the base for the respective production.\n * @param action Pointer to an action.\n */\nvoid ProductionCompleteState::btnGotoBaseClick(Action *)\n{\n\t_state->timerReset();\n\t_game->popState();\n\tif (_endType != PROGRESS_CONSTRUCTION)\n\t{\n\t\t_game->pushState(new ManufactureState(_base));\n\t}\n\telse\n\t{\n\t\t_game->pushState(new BasescapeState(_base, _state->getGlobe()));\n\t}\n}\n\n/**\n * Displays the random production info.\n * @param action Pointer to an action.\n */\nvoid ProductionCompleteState::btnSummaryClick(Action *)\n{\n\t_btnSummary->setVisible(false);\n\t_txtMessage->setVisible(false);\n\n\t_btnGotoBase->setVisible(true);\n\t_txtItem->setVisible(true);\n\t_txtQuantity->setVisible(true);\n\t_lstSummary->setVisible(true);\n}\n\n/**\n * Sells the selected item(s)... unless they were sold, transferred or otherwise disposed of earlier already.\n * @param action Pointer to an action.\n */\nvoid ProductionCompleteState::lstSummaryClick(Action *)\n{\n\t// 1. remember stuff\n\tauto scrollPos = _lstSummary->getScroll();\n\tunsigned int sel = _lstSummary->getSelectedRow();\n\tstd::string itemName = _index[sel];\n\tint itemCount = _randomProductionInfo[itemName];\n\n\t// 2. deal with it\n\tauto* itemRule = _game->getMod()->getItem(itemName, false);\n\tif (itemRule)\n\t{\n\t\t// check if we sold something in the meantime\n\t\tif (_base->getStorageItems()->getItem(itemRule) < itemCount)\n\t\t{\n\t\t\titemCount = _base->getStorageItems()->getItem(itemRule);\n\t\t\t_randomProductionInfo[itemName] -= itemCount; // just decrease amount by the maximum we can sell\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// remove completely\n\t\t\t_index.erase(_index.begin() + sel);\n\t\t}\n\n\t\tif (itemCount > 0)\n\t\t{\n\t\t\tint64_t adjustedSellValue = itemRule->getSellCostAdjusted(_base, _game->getSavedGame());\n\t\t\tadjustedSellValue *= itemCount;\n\t\t\t_game->getSavedGame()->setFunds(_game->getSavedGame()->getFunds() + adjustedSellValue);\n\t\t\t_base->getStorageItems()->removeItem(itemRule, itemCount);\n\t\t}\n\t}\n\n\t// 3. refresh UI\n\t_lstSummary->clearList();\n\tfor (const auto& name : _index)\n\t{\n\t\tstd::ostringstream ss;\n\t\tss << _randomProductionInfo[name];\n\t\t_lstSummary->addRow(2, tr(name).c_str(), ss.str().c_str());\n\t}\n\t_lstSummary->scrollTo(scrollPos);\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/ProductionCompleteState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include <map>\n#include <vector>\n#include \"../Engine/State.h\"\n#include \"../Savegame/Production.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass TextList;\nclass Base;\nclass GeoscapeState;\n\n/**\n * Window used to notify the player when\n * a production is completed.\n */\nclass ProductionCompleteState : public State\n{\nprivate:\n\tBase *_base;\n\tGeoscapeState *_state;\n\n\tstd::map<std::string, int> _randomProductionInfo;\n\tstd::vector<std::string> _index;\n\n\tTextButton *_btnOk, *_btnGotoBase, *_btnSummary;\n\tWindow *_window;\n\tText *_txtMessage, *_txtItem, *_txtQuantity;\n\tTextList *_lstSummary;\n\tproductionProgress_e _endType;\npublic:\n\t/// Creates the Production Complete state.\n\tProductionCompleteState(Base *base, const std::string &item, GeoscapeState *state, productionProgress_e endType = PROGRESS_COMPLETE, Production *production = nullptr);\n\t/// Cleans up the Production Complete state.\n\t~ProductionCompleteState();\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the Go To Base button.\n\tvoid btnGotoBaseClick(Action *action);\n\t/// Handler for clicking the Summary button.\n\tvoid btnSummaryClick(Action *action);\n\t/// Handler for clicking the Summary list.\n\tvoid lstSummaryClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/PsiTrainingState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <sstream>\n#include \"PsiTrainingState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Action.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Base.h\"\n#include \"AllocatePsiTrainingState.h\"\n#include \"../Engine/Options.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Psi Training screen.\n * @param game Pointer to the core game.\n */\nPsiTrainingState::PsiTrainingState()\n{\n\t// Create objects\n\t_window = new Window(this, 320, 200, 0, 0);\n\t_txtTitle = new Text(300, 17, 10, 16);\n\t_btnOk = new TextButton(160, 14, 80, 174);\n\n\t// Set palette\n\tsetInterface(\"psiTraining\");\n\n\tadd(_window, \"window\", \"psiTraining\");\n\tadd(_btnOk, \"button2\", \"psiTraining\");\n\tadd(_txtTitle, \"text\", \"psiTraining\");\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"psiTraining\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&PsiTrainingState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&PsiTrainingState::btnOkClick, Options::keyCancel);\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_PSIONIC_TRAINING\"));\n\n\tint buttons = 0;\n\tfor (auto* xbase : *_game->getSavedGame()->getBases())\n\t{\n\t\tif (xbase->getAvailablePsiLabs())\n\t\t{\n\t\t\tTextButton *btnBase = new TextButton(160, 14, 80, 40 + 16 * buttons);\n\t\t\tbtnBase->onMouseClick((ActionHandler)&PsiTrainingState::btnBaseXClick);\n\t\t\tbtnBase->setText(xbase->getName());\n\t\t\tadd(btnBase, \"button1\", \"psiTraining\");\n\t\t\t_bases.push_back(xbase);\n\t\t\t_btnBases.push_back(btnBase);\n\t\t\t++buttons;\n\t\t\tif (buttons >= 8)\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tcenterAllSurfaces();\n}\n\n/**\n *\n */\nPsiTrainingState::~PsiTrainingState()\n{\n\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid PsiTrainingState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Goes to the allocation screen for the corresponding base.\n * @param action Pointer to an action.\n */\nvoid PsiTrainingState::btnBaseXClick(Action *action)\n{\n\tfor (size_t i = 0; i < _btnBases.size(); ++i)\n\t{\n\t\tif (action->getSender() == _btnBases[i])\n\t\t{\n\t\t\t_game->pushState(new AllocatePsiTrainingState(_bases.at(i)));\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/PsiTrainingState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass Base;\n\n/**\n * Screen shown monthly when the player has psi labs available.\n */\nclass PsiTrainingState : public State\n{\nprivate:\n\tTextButton *_btnOk;\n\tWindow *_window;\n\tText *_txtTitle;\n\tstd::vector<TextButton*> _btnBases;\n\tstd::vector<Base*> _bases;\npublic:\n\t/// Creates the Psi Training state.\n\tPsiTrainingState();\n\t/// Cleans up the Psi Training state.\n\t~PsiTrainingState();\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking a Base button.\n\tvoid btnBaseXClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/ResearchCompleteState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ResearchCompleteState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Mod/RuleResearch.h\"\n#include \"../Ufopaedia/Ufopaedia.h\"\n#include \"../Engine/Options.h\"\n#include \"../Savegame/Base.h\"\n\nnamespace OpenXcom\n{\n/**\n * Initializes all the elements in the EndResearch screen.\n * @param game Pointer to the core game.\n * @param newResearch Pointer to the completed research (or 0, if the ufopedia article shouldn't popup again).\n * @param bonus Pointer to bonus unlocked research.\n * @param research Pointer to the research project.\n */\nResearchCompleteState::ResearchCompleteState(const RuleResearch *newResearch, const RuleResearch *bonus, const RuleResearch *research, const Base* base) : _research(newResearch), _bonus(bonus)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 230, 140, 45, 30, POPUP_BOTH);\n\t_btnOk = new TextButton(80, 16, 64, 146);\n\t_btnReport = new TextButton(80, 16, 176, 146);\n\t_txtBase = new Text(230, 9, 45, 40);\n\t_txtTitle = new Text(230, 17, 45, 70);\n\t_txtResearch = new Text(230, 32, 45, 96);\n\n\t// Set palette\n\tsetInterface(\"geoResearchComplete\");\n\n\tadd(_window, \"window\", \"geoResearchComplete\");\n\tadd(_btnOk, \"button\", \"geoResearchComplete\");\n\tadd(_btnReport, \"button\", \"geoResearchComplete\");\n\tadd(_txtBase, \"text1\", \"geoResearchComplete\");\n\tadd(_txtTitle, \"text1\", \"geoResearchComplete\");\n\tadd(_txtResearch, \"text2\", \"geoResearchComplete\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"geoResearchComplete\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&ResearchCompleteState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&ResearchCompleteState::btnOkClick, Options::keyCancel);\n\n\t_btnReport->setText(tr(\"STR_VIEW_REPORTS\"));\n\t_btnReport->onMouseClick((ActionHandler)&ResearchCompleteState::btnReportClick);\n\t_btnReport->onKeyboardPress((ActionHandler)&ResearchCompleteState::btnReportClick, Options::keyOk);\n\n\t_txtBase->setAlign(ALIGN_CENTER);\n\t_txtBase->setText(base->getName());\n\t_txtBase->setVisible(Options::oxceShowBaseNameInPopups);\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_RESEARCH_COMPLETED\"));\n\n\t_txtResearch->setAlign(ALIGN_CENTER);\n\t_txtResearch->setBig();\n\t_txtResearch->setWordWrap(true);\n\tif (research)\n\t{\n\t\t_txtResearch->setText(tr(research->getName()));\n\t}\n}\n\n/**\n * return to the previous screen\n * @param action Pointer to an action.\n */\nvoid ResearchCompleteState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * open the Ufopaedia to the entry about the Research.\n * @param action Pointer to an action.\n */\nvoid ResearchCompleteState::btnReportClick(Action *)\n{\n\t_game->popState();\n\tstd::string name;\n\tstd::string bonusName;\n\tif (_bonus)\n\t{\n\t\tif (_bonus->getLookup())\n\t\t\tbonusName = _bonus->getLookup()->getName();\n\t\telse\n\t\t\tbonusName = _bonus->getName();\n\t\tUfopaedia::openArticle(_game, bonusName);\n\t}\n\tif (_research)\n\t{\n\t\tif (_research->getLookup())\n\t\t\tname = _research->getLookup()->getName();\n\t\telse\n\t\t\tname = _research->getName();\n\t\tUfopaedia::openArticle(_game, name);\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/ResearchCompleteState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass Game;\nclass Window;\nclass TextButton;\nclass Text;\nclass Base;\nclass RuleResearch;\n\n/**\n * Window which inform the player that a research project is finished.\n * Allow him to view information about the project (Ufopaedia).\n */\nclass ResearchCompleteState : public State\n{\n\tWindow *_window;\n\tText *_txtTitle, *_txtResearch, *_txtBase;\n\tTextButton *_btnReport, *_btnOk;\n\tconst RuleResearch * _research, * _bonus;\npublic:\n\t/// Creates the EndResearch state.\n\tResearchCompleteState(const RuleResearch *newResearch, const RuleResearch *bonus, const RuleResearch *research, const Base* base);\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the Report button.\n\tvoid btnReportClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/ResearchRequiredState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ResearchRequiredState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"../Engine/Options.h\"\n\nnamespace OpenXcom\n{\n/**\n * Initializes all the elements in the Research Required screen.\n * @param game Pointer to the core game.\n * @param item Pointer to the researched weapon.\n */\nResearchRequiredState::ResearchRequiredState(RuleItem *item)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 288, 180, 16, 10);\n\t_btnOk = new TextButton(160, 18, 80, 150);\n\t_txtTitle = new Text(288, 80, 16, 50);\n\n\t// Set palette\n\tsetInterface(\"geoResearchRequired\");\n\n\tadd(_window, \"window\", \"geoResearchRequired\");\n\tadd(_btnOk, \"button\", \"geoResearchRequired\");\n\tadd(_txtTitle, \"text1\", \"geoResearchRequired\");\n\n\tcenterAllSurfaces();\n\n\tstd::string weapon = item->getType();\n\tstd::string clip = item->getPrimaryCompatibleAmmo()->front()->getType();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"geoResearchRequired\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&ResearchRequiredState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&ResearchRequiredState::btnOkClick, Options::keyCancel);\n\t_btnOk->onKeyboardPress((ActionHandler)&ResearchRequiredState::btnOkClick, Options::keyOk);\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setVerticalAlign(ALIGN_MIDDLE);\n\t_txtTitle->setText(tr(\"STR_YOU_NEED_TO_RESEARCH_ITEM_TO_PRODUCE_ITEM\")\n\t\t\t\t\t   .arg(tr(clip))\n\t\t\t\t\t   .arg(tr(weapon)));\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid ResearchRequiredState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/ResearchRequiredState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass Game;\nclass Window;\nclass TextButton;\nclass Text;\nclass RuleItem;\n\n/**\n * Window shown when the player researches a weapon\n * before the respective clip.\n */\nclass ResearchRequiredState : public State\n{\n\tWindow *_window;\n\tText *_txtTitle;\n\tTextButton *_btnOk;\npublic:\n\t/// Creates the ResearchRequired state.\n\tResearchRequiredState(RuleItem *item);\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/SelectDestinationState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"SelectDestinationState.h\"\n#include <cmath>\n#include \"../Engine/Game.h\"\n#include \"../Engine/Screen.h\"\n#include \"../Engine/Action.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/Surface.h\"\n#include \"../Interface/Window.h\"\n#include \"Globe.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Savegame/Waypoint.h\"\n#include \"MultipleTargetsState.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Craft.h\"\n#include \"../Mod/RuleCraft.h\"\n#include \"../Mod/AlienDeployment.h\"\n#include \"../Mod/RuleStartingCondition.h\"\n#include \"ConfirmCydoniaState.h\"\n#include \"../Engine/Options.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Select Destination window.\n * @param game Pointer to the core game.\n * @param craft Pointer to the craft to target.\n * @param globe Pointer to the Geoscape globe.\n */\nSelectDestinationState::SelectDestinationState(std::vector<Craft*> crafts, Globe *globe) : _crafts(std::move(crafts)), _globe(globe)\n{\n\tint dx = _game->getScreen()->getDX();\n\tint dy = _game->getScreen()->getDY();\n\t_screen = false;\n\n\t// Create objects\n\t_btnRotateLeft = new InteractiveSurface(12, 10, 259 + dx * 2, 176 + dy);\n\t_btnRotateRight = new InteractiveSurface(12, 10, 283 + dx * 2, 176 + dy);\n\t_btnRotateUp = new InteractiveSurface(13, 12, 271 + dx * 2, 162 + dy);\n\t_btnRotateDown = new InteractiveSurface(13, 12, 271 + dx * 2, 187 + dy);\n\t_btnZoomIn = new InteractiveSurface(23, 23, 295 + dx * 2, 156 + dy);\n\t_btnZoomOut = new InteractiveSurface(13, 17, 300 + dx * 2, 182 + dy);\n\n\t_window = new Window(this, 256, 28, 0, 0);\n\t_window->setX(dx);\n\t_window->setDY(0);\n\t_btnCancel = new TextButton(60, 12, 110 + dx, 8);\n\t_btnCydonia = new TextButton(60, 12, 180 + dx, 8);\n\t_txtTitle = new Text(100, 16, 10 + dx, 6);\n\n\t// Set palette\n\tsetInterface(\"geoscape\");\n\n\tadd(_btnRotateLeft);\n\tadd(_btnRotateRight);\n\tadd(_btnRotateUp);\n\tadd(_btnRotateDown);\n\tadd(_btnZoomIn);\n\tadd(_btnZoomOut);\n\n\tadd(_window, \"genericWindow\", \"geoscape\");\n\tadd(_btnCancel, \"genericButton1\", \"geoscape\");\n\tadd(_btnCydonia, \"genericButton1\", \"geoscape\");\n\tadd(_txtTitle, \"genericText\", \"geoscape\");\n\n\t// Set up objects\n\t_globe->onMouseClick((ActionHandler)&SelectDestinationState::globeClick);\n\n\t_btnRotateLeft->onMousePress((ActionHandler)&SelectDestinationState::btnRotateLeftPress);\n\t_btnRotateLeft->onMouseRelease((ActionHandler)&SelectDestinationState::btnRotateLeftRelease);\n\t_btnRotateLeft->onKeyboardPress((ActionHandler)&SelectDestinationState::btnRotateLeftPress, Options::keyGeoLeft);\n\t_btnRotateLeft->onKeyboardRelease((ActionHandler)&SelectDestinationState::btnRotateLeftRelease, Options::keyGeoLeft);\n\n\t_btnRotateRight->onMousePress((ActionHandler)&SelectDestinationState::btnRotateRightPress);\n\t_btnRotateRight->onMouseRelease((ActionHandler)&SelectDestinationState::btnRotateRightRelease);\n\t_btnRotateRight->onKeyboardPress((ActionHandler)&SelectDestinationState::btnRotateRightPress, Options::keyGeoRight);\n\t_btnRotateRight->onKeyboardRelease((ActionHandler)&SelectDestinationState::btnRotateRightRelease, Options::keyGeoRight);\n\n\t_btnRotateUp->onMousePress((ActionHandler)&SelectDestinationState::btnRotateUpPress);\n\t_btnRotateUp->onMouseRelease((ActionHandler)&SelectDestinationState::btnRotateUpRelease);\n\t_btnRotateUp->onKeyboardPress((ActionHandler)&SelectDestinationState::btnRotateUpPress, Options::keyGeoUp);\n\t_btnRotateUp->onKeyboardRelease((ActionHandler)&SelectDestinationState::btnRotateUpRelease, Options::keyGeoUp);\n\n\t_btnRotateDown->onMousePress((ActionHandler)&SelectDestinationState::btnRotateDownPress);\n\t_btnRotateDown->onMouseRelease((ActionHandler)&SelectDestinationState::btnRotateDownRelease);\n\t_btnRotateDown->onKeyboardPress((ActionHandler)&SelectDestinationState::btnRotateDownPress, Options::keyGeoDown);\n\t_btnRotateDown->onKeyboardRelease((ActionHandler)&SelectDestinationState::btnRotateDownRelease, Options::keyGeoDown);\n\n\t_btnZoomIn->onMouseClick((ActionHandler)&SelectDestinationState::btnZoomInLeftClick, SDL_BUTTON_LEFT);\n\t_btnZoomIn->onMouseClick((ActionHandler)&SelectDestinationState::btnZoomInRightClick, SDL_BUTTON_RIGHT);\n\t_btnZoomIn->onKeyboardPress((ActionHandler)&SelectDestinationState::btnZoomInLeftClick, Options::keyGeoZoomIn);\n\n\t_btnZoomOut->onMouseClick((ActionHandler)&SelectDestinationState::btnZoomOutLeftClick, SDL_BUTTON_LEFT);\n\t_btnZoomOut->onMouseClick((ActionHandler)&SelectDestinationState::btnZoomOutRightClick, SDL_BUTTON_RIGHT);\n\t_btnZoomOut->onKeyboardPress((ActionHandler)&SelectDestinationState::btnZoomOutLeftClick, Options::keyGeoZoomOut);\n\n\t// dirty hacks to get the rotate buttons to work in \"classic\" style\n\t_btnRotateLeft->setListButton();\n\t_btnRotateRight->setListButton();\n\t_btnRotateUp->setListButton();\n\t_btnRotateDown->setListButton();\n\n\tsetWindowBackground(_window, \"geoscape\");\n\n\t_btnCancel->setText(tr(\"STR_CANCEL_UC\"));\n\t_btnCancel->onMouseClick((ActionHandler)&SelectDestinationState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&SelectDestinationState::btnCancelClick, Options::keyCancel);\n\n\t_txtTitle->setText(tr(\"STR_SELECT_DESTINATION\"));\n\t_txtTitle->setVerticalAlign(ALIGN_MIDDLE);\n\t_txtTitle->setWordWrap(true);\n\n\tif (_crafts.size() != 1 ||\n\t\t_crafts.front()->getFuelPercentage() < 100 ||\n\t\t!_crafts.front()->getRules()->getSpacecraft() ||\n\t\t(_game->getMod()->getFinalResearch() && // if not Research specified then we look only on `getSpacecraft`\n\t\t\t!_game->getSavedGame()->isResearched(_game->getMod()->getFinalResearch())))\n\t{\n\t\t_btnCydonia->setVisible(false);\n\t}\n\telse\n\t{\n\t\t_btnCydonia->setText(tr(\"STR_CYDONIA\"));\n\t\t_btnCydonia->onMouseClick((ActionHandler)&SelectDestinationState::btnCydoniaClick);\n\n\t\t// one more check...\n\t\tfor (auto& depl : _game->getMod()->getDeploymentsList())\n\t\t{\n\t\t\tAlienDeployment* deploymentRule = _game->getMod()->getDeployment(depl);\n\t\t\tif (deploymentRule->isFinalDestination())\n\t\t\t{\n\t\t\t\tRuleStartingCondition* sc = _game->getMod()->getStartingCondition(deploymentRule->getStartingCondition());\n\t\t\t\tif (sc && sc->requiresCommanderOnboard() && !_crafts.front()->isCommanderOnboard())\n\t\t\t\t{\n\t\t\t\t\t_btnCydonia->setVisible(false);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\t// ok, ok, one more...\n\t\tif (_crafts.front()->areBannedArmorsOnboard())\n\t\t{\n\t\t\t_btnCydonia->setVisible(false);\n\t\t}\n\t\tif (!_crafts.front()->arePilotsOnboard(_game->getMod()))\n\t\t{\n\t\t\t_btnCydonia->setVisible(false);\n\t\t}\n\t}\n\n\tif (_crafts.front()->getStatus() != \"STR_OUT\")\n\t{\n\t\t_globe->setCraftRange(_crafts.front()->getLongitude(), _crafts.front()->getLatitude(), _crafts.front()->getBaseRange());\n\t\t_globe->invalidate();\n\t}\n}\n\n/**\n *\n */\nSelectDestinationState::~SelectDestinationState()\n{\n\t_globe->setCraftRange(0.0, 0.0, 0.0);\n}\n\n/**\n * Stop the globe movement.\n */\nvoid SelectDestinationState::init()\n{\n\tState::init();\n\t_globe->rotateStop();\n}\n\n/**\n * Runs the globe rotation timer.\n */\nvoid SelectDestinationState::think()\n{\n\tState::think();\n\t_globe->think();\n}\n\n/**\n * Handles the globe.\n * @param action Pointer to an action.\n */\nvoid SelectDestinationState::handle(Action *action)\n{\n\tState::handle(action);\n\t_globe->handle(action, this);\n}\n\n/**\n * Processes any left-clicks for picking a target,\n * or right-clicks to scroll the globe.\n * @param action Pointer to an action.\n */\nvoid SelectDestinationState::globeClick(Action *action)\n{\n\tdouble lon, lat;\n\tint mouseX = (int)floor(action->getAbsoluteXMouse()), mouseY = (int)floor(action->getAbsoluteYMouse());\n\t_globe->cartToPolar(mouseX, mouseY, &lon, &lat);\n\n\t// Ignore window clicks\n\tif (mouseY < 28)\n\t{\n\t\treturn;\n\t}\n\n\t// Clicking on a valid target\n\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT)\n\t{\n\t\tstd::vector<Target*> v = _globe->getTargets(mouseX, mouseY, true, _crafts.front());\n\t\tif (v.empty())\n\t\t{\n\t\t\tWaypoint *w = new Waypoint();\n\t\t\tw->setLongitude(lon);\n\t\t\tw->setLatitude(lat);\n\t\t\tv.push_back(w);\n\t\t}\n\t\t_game->pushState(new MultipleTargetsState(v, _crafts, 0, false));\n\t}\n}\n\n/**\n * Starts rotating the globe to the left.\n * @param action Pointer to an action.\n */\nvoid SelectDestinationState::btnRotateLeftPress(Action *)\n{\n\t_globe->rotateLeft();\n}\n\n/**\n * Stops rotating the globe to the left.\n * @param action Pointer to an action.\n */\nvoid SelectDestinationState::btnRotateLeftRelease(Action *)\n{\n\t_globe->rotateStopLon();\n}\n\n/**\n * Starts rotating the globe to the right.\n * @param action Pointer to an action.\n */\nvoid SelectDestinationState::btnRotateRightPress(Action *)\n{\n\t_globe->rotateRight();\n}\n\n/**\n * Stops rotating the globe to the right.\n * @param action Pointer to an action.\n */\nvoid SelectDestinationState::btnRotateRightRelease(Action *)\n{\n\t_globe->rotateStopLon();\n}\n\n/**\n * Starts rotating the globe upwards.\n * @param action Pointer to an action.\n */\nvoid SelectDestinationState::btnRotateUpPress(Action *)\n{\n\t_globe->rotateUp();\n}\n\n/**\n * Stops rotating the globe upwards.\n * @param action Pointer to an action.\n */\nvoid SelectDestinationState::btnRotateUpRelease(Action *)\n{\n\t_globe->rotateStopLat();\n}\n\n/**\n * Starts rotating the globe downwards.\n * @param action Pointer to an action.\n */\nvoid SelectDestinationState::btnRotateDownPress(Action *)\n{\n\t_globe->rotateDown();\n}\n\n/**\n * Stops rotating the globe downwards.\n * @param action Pointer to an action.\n */\nvoid SelectDestinationState::btnRotateDownRelease(Action *)\n{\n\t_globe->rotateStopLat();\n}\n\n/**\n * Zooms into the globe.\n * @param action Pointer to an action.\n */\nvoid SelectDestinationState::btnZoomInLeftClick(Action *)\n{\n\t_globe->zoomIn();\n}\n\n/**\n * Zooms the globe maximum.\n * @param action Pointer to an action.\n */\nvoid SelectDestinationState::btnZoomInRightClick(Action *)\n{\n\t_globe->zoomMax();\n}\n\n/**\n * Zooms out of the globe.\n * @param action Pointer to an action.\n */\nvoid SelectDestinationState::btnZoomOutLeftClick(Action *)\n{\n\t_globe->zoomOut();\n}\n\n/**\n * Zooms the globe minimum.\n * @param action Pointer to an action.\n */\nvoid SelectDestinationState::btnZoomOutRightClick(Action *)\n{\n\t_globe->zoomMin();\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid SelectDestinationState::btnCancelClick(Action *)\n{\n\t_game->popState();\n}\n\nvoid SelectDestinationState::btnCydoniaClick(Action *)\n{\n\tif (_crafts.front()->getNumTotalUnits() > 0)\n\t{\n\t\t_game->pushState(new ConfirmCydoniaState(_crafts.front()));\n\t}\n}\n\n/**\n * Updates the scale.\n * @param dX delta of X;\n * @param dY delta of Y;\n */\nvoid SelectDestinationState::resize(int &dX, int &dY)\n{\n\tfor (auto* surface : _surfaces)\n\t{\n\t\tsurface->setX(surface->getX() + dX / 2);\n\t\tif (surface != _window && surface != _btnCancel && surface != _txtTitle && surface != _btnCydonia)\n\t\t{\n\t\t\tsurface->setY(surface->getY() + dY / 2);\n\t\t}\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/SelectDestinationState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http:///www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass Craft;\nclass Globe;\nclass InteractiveSurface;\nclass Timer;\nclass Window;\nclass Text;\nclass TextButton;\n\n/**\n * Screen that allows the player\n * to pick a target for a craft on the globe.\n */\nclass SelectDestinationState : public State\n{\nprivate:\n\tstd::vector<Craft*> _crafts; \n\tGlobe *_globe;\n\tInteractiveSurface *_btnRotateLeft, *_btnRotateRight, *_btnRotateUp, *_btnRotateDown, *_btnZoomIn, *_btnZoomOut;\n\tWindow *_window;\n\tText *_txtTitle;\n\tTextButton *_btnCancel, *_btnCydonia;\npublic:\n\t/// Creates the Select Destination state.\n\tSelectDestinationState(std::vector<Craft*> crafts, Globe *globe);\n\t/// Cleans up the Select Destination state.\n\t~SelectDestinationState();\n\t/// Resets globe.\n\tvoid init() override;\n\t/// Runs the timer.\n\tvoid think() override;\n\t/// Handles actions.\n\tvoid handle(Action *action) override;\n\t/// Handler for clicking the globe.\n\tvoid globeClick(Action *action);\n\t/// Handler for pressing the Rotate Left arrow.\n\tvoid btnRotateLeftPress(Action *action);\n\t/// Handler for releasing the Rotate Left arrow.\n\tvoid btnRotateLeftRelease(Action *action);\n\t/// Handler for pressing the Rotate Right arrow.\n\tvoid btnRotateRightPress(Action *action);\n\t/// Handler for releasing the Rotate Right arrow.\n\tvoid btnRotateRightRelease(Action *action);\n\t/// Handler for pressing the Rotate Up arrow.\n\tvoid btnRotateUpPress(Action *action);\n\t/// Handler for releasing the Rotate Up arrow.\n\tvoid btnRotateUpRelease(Action *action);\n\t/// Handler for pressing the Rotate Down arrow.\n\tvoid btnRotateDownPress(Action *action);\n\t/// Handler for releasing the Rotate Down arrow.\n\tvoid btnRotateDownRelease(Action *action);\n\t/// Handler for left-clicking the Zoom In icon.\n\tvoid btnZoomInLeftClick(Action *action);\n\t/// Handler for right-clicking the Zoom In icon.\n\tvoid btnZoomInRightClick(Action *action);\n\t/// Handler for left-clicking the Zoom Out icon.\n\tvoid btnZoomOutLeftClick(Action *action);\n\t/// Handler for right-clicking the Zoom Out icon.\n\tvoid btnZoomOutRightClick(Action *action);\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action *action);\n\t/// Handler for clicking the Cydonia mission button.\n\tvoid btnCydoniaClick(Action *action);\n\t/// Let the state know the window has been resized.\n\tvoid resize(int &dX, int &dY) override;\n\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/SelectMusicTrackState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"SelectMusicTrackState.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Music.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Mod/RuleInterface.h\"\n#include \"../Savegame/SavedGame.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Select Music Track window.\n * @param origin Where is the dialog called from?\n */\nSelectMusicTrackState::SelectMusicTrackState(SelectMusicTrackOrigin origin) : _origin(origin)\n{\n\t_screen = false;\n\n\tint x;\n\tif (_origin == SMT_BATTLESCAPE)\n\t{\n\t\tx = 52;\n\t}\n\telse\n\t{\n\t\tx = 20;\n\t}\n\n\t// Create objects\n\t_window = new Window(this, 216, 160, x, 20, POPUP_BOTH);\n\t_txtTitle = new Text(206, 17, x + 5, 32);\n\t_btnCancel = new TextButton(140, 16, x + 38, 156);\n\t_lstTracks = new TextList(180, 96, x + 13, 52);\n\n\t// Set palette\n\tsetInterface(\"selectMusicTrack\", false, _game->getSavedGame() ? _game->getSavedGame()->getSavedBattle() : 0);\n\n\tadd(_window, \"window\", \"selectMusicTrack\");\n\tadd(_txtTitle, \"text\", \"selectMusicTrack\");\n\tadd(_btnCancel, \"button\", \"selectMusicTrack\");\n\tadd(_lstTracks, \"list\", \"selectMusicTrack\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"selectMusicTrack\");\n\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setBig();\n\t_txtTitle->setText(tr(\"STR_SELECT_MUSIC_TRACK\"));\n\n\t_btnCancel->setText(tr(\"STR_CANCEL_UC\"));\n\t_btnCancel->onMouseClick((ActionHandler)&SelectMusicTrackState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&SelectMusicTrackState::btnCancelClick, Options::keyCancel);\n\n\t_lstTracks->setColumns(1, 172);\n\t_lstTracks->setSelectable(true);\n\t_lstTracks->setBackground(_window);\n\t_lstTracks->setMargin(8);\n\t_lstTracks->setAlign(ALIGN_CENTER);\n\t_lstTracks->onMouseClick((ActionHandler)&SelectMusicTrackState::lstTrackClick);\n\n\tconst std::string search = _origin == SMT_BATTLESCAPE ? \"GMTAC\" : \"GMGEO\";\n\tconst std::string& currentName = _game->getMod()->getCurrentMusicTrack();\n\tint currentTrackIndex = -1;\n\tfor (auto& pair : _game->getMod()->getMusicTrackList())\n\t{\n\t\tif (pair.first == currentName || pair.first.find(search) != std::string::npos)\n\t\t{\n\t\t\t_lstTracks->addRow(1, tr(pair.first).c_str());\n\t\t\t_tracks.push_back(pair.second);\n\t\t\t_trackNames.push_back(pair.first);\n\t\t\tif (pair.first == currentName)\n\t\t\t{\n\t\t\t\tcurrentTrackIndex = _lstTracks->getLastRowIndex();\n\t\t\t\t_lstTracks->setRowColor(currentTrackIndex, _lstTracks->getSecondaryColor());\n\t\t\t}\n\t\t}\n\t}\n\n\t// switch to battlescape theme if called from battlestate\n\tif (_origin == SMT_BATTLESCAPE)\n\t{\n\t\tapplyBattlescapeTheme(\"selectMusicTrack\");\n\t\tif (currentTrackIndex > -1)\n\t\t{\n\t\t\tconst Element* element = _game->getMod()->getInterface(\"battlescape\")->getElement(\"optionLists\");\n\t\t\t_lstTracks->setRowColor(currentTrackIndex, element->color2);\n\t\t}\n\t}\n}\n\n/**\n *\n */\nSelectMusicTrackState::~SelectMusicTrackState()\n{\n\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid SelectMusicTrackState::btnCancelClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Starts playing the selected track and returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid SelectMusicTrackState::lstTrackClick(Action *)\n{\n\tMusic *selected = _tracks[_lstTracks->getSelectedRow()];\n\tselected->play();\n\t_game->getMod()->setCurrentMusicTrack(_trackNames[_lstTracks->getSelectedRow()]);\n\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/SelectMusicTrackState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <vector>\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nenum SelectMusicTrackOrigin\n{\n\tSMT_GEOSCAPE,\n\tSMT_BATTLESCAPE\n};\n\nclass Window;\nclass Text;\nclass TextButton;\nclass TextList;\nclass Music;\n\n/**\n * Select Music Track window that allows changing\n * of the currently played music track.\n */\nclass SelectMusicTrackState : public State\n{\nprivate:\n\tSelectMusicTrackOrigin _origin;\n\tWindow *_window;\n\tText *_txtTitle;\n\tTextButton *_btnCancel;\n\tTextList *_lstTracks;\n\tstd::vector<Music*> _tracks;\n\tstd::vector<std::string> _trackNames;\npublic:\n\t/// Creates the Select Music Track state.\n\tSelectMusicTrackState(SelectMusicTrackOrigin origin);\n\t/// Cleans up the Select Music Track state.\n\t~SelectMusicTrackState();\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action *action);\n\t/// Handler for clicking the Weapons list.\n\tvoid lstTrackClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/TargetInfoState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"TargetInfoState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/AlienRace.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextEdit.h\"\n#include \"../Savegame/MovingTarget.h\"\n#include \"../Savegame/AlienBase.h\"\n#include \"../Savegame/MissionSite.h\"\n#include \"../Engine/Options.h\"\n#include \"InterceptState.h\"\n#include \"../Engine/Action.h\"\n#include \"../Battlescape/BriefingLightState.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Target Info window.\n * @param game Pointer to the core game.\n * @param target Pointer to the target to show info from.\n * @param globe Pointer to the Geoscape globe.\n */\nTargetInfoState::TargetInfoState(Target *target, Globe *globe) : _target(target), _globe(globe), _deploymentRule(0)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 192, 120, 32, 40, POPUP_BOTH);\n\t_btnIntercept = new TextButton(160, 12, 48, 124);\n\t_btnInfo = new TextButton(77, 12, 48, 140);\n\t_btnOk = new TextButton(77, 12, 131, 140);\n\t_edtTitle = new TextEdit(this, 182, 32, 37, 46);\n\t_txtTargetted = new Text(182, 9, 37, 78);\n\t_txtFollowers = new Text(182, 40, 37, 88);\n\t_txtPenalty = new Text(160, 9, 48, 114);\n\n\t// Set palette\n\tsetInterface(\"targetInfo\");\n\n\tadd(_window, \"window\", \"targetInfo\");\n\tadd(_btnIntercept, \"button\", \"targetInfo\");\n\tadd(_btnInfo, \"button\", \"targetInfo\");\n\tadd(_btnOk, \"button\", \"targetInfo\");\n\tadd(_edtTitle, \"text2\", \"targetInfo\");\n\tadd(_txtTargetted, \"text1\", \"targetInfo\");\n\tadd(_txtFollowers, \"text1\", \"targetInfo\");\n\tadd(_txtPenalty, \"text2\", \"targetInfo\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"targetInfo\");\n\n\t_btnIntercept->setText(tr(\"STR_INTERCEPT\"));\n\t_btnIntercept->onMouseClick((ActionHandler)&TargetInfoState::btnInterceptClick);\n\n\t_btnInfo->setText(tr(\"STR_INFO\"));\n\t_btnInfo->onMouseClick((ActionHandler)&TargetInfoState::btnInfoClick);\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&TargetInfoState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&TargetInfoState::btnOkClick, Options::keyCancel);\n\n\t_edtTitle->setBig();\n\t_edtTitle->setAlign(ALIGN_CENTER);\n\t_edtTitle->setVerticalAlign(ALIGN_MIDDLE);\n\t_edtTitle->setWordWrap(true);\n\t_edtTitle->setText(_target->getName(_game->getLanguage()));\n\t_edtTitle->onChange((ActionHandler)&TargetInfoState::edtTitleChange);\n\n\t_txtTargetted->setAlign(ALIGN_CENTER);\n\t_txtTargetted->setText(tr(\"STR_TARGETTED_BY\"));\n\t_txtFollowers->setAlign(ALIGN_CENTER);\n\tstd::ostringstream ss;\n\tfor (const auto* follower : *_target->getFollowers())\n\t{\n\t\tss << follower->getName(_game->getLanguage()) << '\\n';\n\t}\n\t_txtFollowers->setText(ss.str());\n\n\t// info\n\tMissionSite* m = dynamic_cast<MissionSite*>(_target);\n\tAlienBase* b = dynamic_cast<AlienBase*>(_target);\n\n\tif (m != 0)\n\t{\n\t\t_deploymentRule = _game->getMod()->getDeployment(m->getDeployment()->getType());\n\t}\n\telse if (b != 0)\n\t{\n\t\tAlienRace *race = _game->getMod()->getAlienRace(b->getAlienRace());\n\t\t_deploymentRule = _game->getMod()->getDeployment(race->getBaseCustomMission());\n\t\tif (!_deploymentRule) _deploymentRule = _game->getMod()->getDeployment(b->getDeployment()->getType());\n\t}\n\n\tif (_deploymentRule && !_deploymentRule->getAlertDescription().empty())\n\t{\n\t\t// all OK\n\t}\n\telse\n\t{\n\t\t_btnInfo->setVisible(false);\n\t\t_btnOk->setWidth(_btnOk->getX() + _btnOk->getWidth() - _btnInfo->getX());\n\t\t_btnOk->setX(_btnInfo->getX());\n\t}\n\n\tif (_deploymentRule && _deploymentRule->getDespawnPenalty() != 0)\n\t{\n\t\t_txtPenalty->setAlign(ALIGN_CENTER);\n\t\t_txtPenalty->setText(tr(\"STR_DESPAWN_PENALTY\").arg(_deploymentRule->getDespawnPenalty()));\n\t}\n}\n\n/**\n *\n */\nTargetInfoState::~TargetInfoState()\n{\n\n}\n\n/**\n * Picks a craft to intercept the UFO.\n * @param action Pointer to an action.\n */\nvoid TargetInfoState::btnInterceptClick(Action *)\n{\n\t_game->pushState(new InterceptState(_globe, false, 0, _target));\n}\n\n/**\n * Closes the window.\n * @param action Pointer to an action.\n */\nvoid TargetInfoState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Shows the BriefingLight screen.\n * @param action Pointer to an action.\n */\nvoid TargetInfoState::btnInfoClick(Action *)\n{\n\t_game->pushState(new BriefingLightState(_deploymentRule));\n}\n\n/**\n * Changes the target name.\n * @param action Pointer to an action.\n */\nvoid TargetInfoState::edtTitleChange(Action *action)\n{\n\tif (_edtTitle->getText() == _target->getDefaultName(_game->getLanguage()))\n\t{\n\t\t_target->setName(\"\");\n\t}\n\telse\n\t{\n\t\t_target->setName(_edtTitle->getText());\n\t}\n\tif (action->getDetails()->key.keysym.sym == SDLK_RETURN ||\n\t\taction->getDetails()->key.keysym.sym == SDLK_KP_ENTER)\n\t{\n\t\t_edtTitle->setText(_target->getName(_game->getLanguage()));\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/TargetInfoState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass TextEdit;\nclass Target;\nclass Globe;\nclass AlienDeployment;\n\n/**\n * Generic window used to display all the\n * crafts targeting a certain point on the map.\n */\nclass TargetInfoState : public State\n{\nprivate:\n\tTarget *_target;\n\tGlobe *_globe;\n\n\tTextButton *_btnIntercept, *_btnOk, *_btnInfo;\n\tWindow *_window;\n\tTextEdit *_edtTitle;\n\tText *_txtTargetted, *_txtFollowers, *_txtPenalty;\n\tAlienDeployment *_deploymentRule;\npublic:\n\t/// Creates the Target Info state.\n\tTargetInfoState(Target *target, Globe *globe);\n\t/// Cleans up the Target Info state.\n\t~TargetInfoState();\n\t/// Handler for clicking the Intercept button.\n\tvoid btnInterceptClick(Action *action);\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the Info button.\n\tvoid btnInfoClick(Action *action);\n\t/// Handler for changing the text on the Name edit.\n\tvoid edtTitleChange(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/TrainingFinishedState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"TrainingFinishedState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/Soldier.h\"\n#include \"AllocateTrainingState.h\"\n#include \"AllocatePsiTrainingState.h\"\n#include \"../Engine/Options.h\"\n\nnamespace OpenXcom\n{\n/**\n * Initializes all the elements in the TrainingFinished screen.\n * @param base Pointer to the base to get info from.\n * @param list List of soldiers who finished their training\n * @param psi Is psi training?\n */\nTrainingFinishedState::TrainingFinishedState(Base *base, const std::vector<Soldier *> & list, bool psi) : _base(base), _psi(psi)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 288, 180, 16, 10);\n\t_btnOk = new TextButton(160, 14, 80, 149);\n\t_btnOpen = new TextButton(160, 14, 80, 165);\n\t_txtTitle = new Text(288, 33, 16, 20);\n\t_lstPossibilities = new TextList(250, 80, 35, 60);\n\n\t// Set palette\n\tsetInterface(\"trainingFinished\");\n\n\tadd(_window, \"window\", \"trainingFinished\");\n\tadd(_btnOk, \"button\", \"trainingFinished\");\n\tadd(_btnOpen, \"button\", \"trainingFinished\");\n\tadd(_txtTitle, \"text1\", \"trainingFinished\");\n\tadd(_lstPossibilities, \"text2\", \"trainingFinished\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"trainingFinished\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&TrainingFinishedState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&TrainingFinishedState::btnOkClick, Options::keyCancel);\n\t_btnOpen->setText(tr(_psi ? \"STR_PSI_TRAINING\" : \"STR_TRAINING\"));\n\t_btnOpen->onMouseClick((ActionHandler)&TrainingFinishedState::btnOpenClick);\n\t_btnOpen->onKeyboardPress((ActionHandler)&TrainingFinishedState::btnOpenClick, Options::keyOk);\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(_psi ? \"STR_PSI_TRAINING_FINISHED\" : \"STR_TRAINING_FINISHED\").arg(base->getName()));\n\n\t_lstPossibilities->setColumns(1, 250);\n\t_lstPossibilities->setBig();\n\t_lstPossibilities->setAlign(ALIGN_CENTER);\n\t_lstPossibilities->setScrolling(true, 0);\n\tfor (const auto* soldier : list)\n\t{\n\t\t_lstPossibilities->addRow (1, soldier->getName().c_str());\n\t}\n}\n\n/**\n * Closes the screen.\n * @param action Pointer to an action.\n */\nvoid TrainingFinishedState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Opens the AllocateTrainingState/AllocatePsiTrainingState.\n * @param action Pointer to an action.\n */\nvoid TrainingFinishedState::btnOpenClick(Action *)\n{\n\t_game->popState();\n\tif (_psi)\n\t{\n\t\t_game->pushState(new AllocatePsiTrainingState(_base));\n\t}\n\telse\n\t{\n\t\t_game->pushState(new AllocateTrainingState(_base));\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/TrainingFinishedState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass Game;\nclass Window;\nclass TextButton;\nclass Text;\nclass Base;\nclass TextList;\nclass Soldier;\n\n/**\n * Window which informs the player of finished soldier training.\n * Also allows to go to the AllocateTrainingState to assign more soldiers into training.\n */\nclass TrainingFinishedState : public State\n{\nprivate:\n\tWindow *_window;\n\tText *_txtTitle;\n\tTextList * _lstPossibilities;\n\tTextButton *_btnOpen, *_btnOk;\n\tBase *_base;\n\tbool _psi;\npublic:\n\t/// Creates the TrainingFinishedState state.\n\tTrainingFinishedState(Base *base, const std::vector<Soldier *> & list, bool psi);\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the Open button.\n\tvoid btnOpenClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/TrainingState.cpp",
    "content": "/*\n * Copyright 2010-2015 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <sstream>\n#include \"TrainingState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Screen.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Language.h\"\n#include \"../Engine/Palette.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Base.h\"\n#include \"GeoscapeState.h\"\n#include \"AllocateTrainingState.h\"\n#include \"../Engine/Options.h\"\n#include \"../Mod/Mod.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Psi Training screen.\n * @param game Pointer to the core game.\n */\nTrainingState::TrainingState()\n{\n\t// Create objects\n\t_window = new Window(this, 320, 200, 0, 0);\n\t_txtTitle = new Text(300, 17, 10, 16);\n\t_btnOk = new TextButton(160, 14, 80, 174);\n\n\t// Set palette\n\tsetInterface(\"martialTraining\");\n\n\tadd(_window, \"window\", \"martialTraining\");\n\tadd(_btnOk, \"button2\", \"martialTraining\");\n\tadd(_txtTitle, \"text\", \"martialTraining\");\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"martialTraining\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&TrainingState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&TrainingState::btnOkClick, Options::keyCancel);\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_PHYSICAL_TRAINING\"));\n\n\tint buttons = 0;\n\tfor (auto* xbase : *_game->getSavedGame()->getBases())\n\t{\n\t\tif (xbase->getAvailableTraining())\n\t\t{\n\t\t\tTextButton *btnBase = new TextButton(160, 14, 80, 40 + 16 * buttons);\n\t\t\tbtnBase->setColor(Palette::blockOffset(15) + 6);\n\t\t\tbtnBase->onMouseClick((ActionHandler)&TrainingState::btnBaseXClick);\n\t\t\tbtnBase->setText(xbase->getName());\n\t\t\tadd(btnBase, \"button1\", \"martialTraining\");\n\t\t\t_bases.push_back(xbase);\n\t\t\t_btnBases.push_back(btnBase);\n\t\t\t++buttons;\n\t\t\tif (buttons >= 8)\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tcenterAllSurfaces();\n}\n/**\n *\n */\nTrainingState::~TrainingState()\n{\n\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid TrainingState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Goes to the allocation screen for the corresponding base.\n * @param action Pointer to an action.\n */\nvoid TrainingState::btnBaseXClick(Action *action)\n{\n\tfor (size_t i = 0; i < _btnBases.size(); ++i)\n\t{\n\t\tif (action->getSender() == _btnBases[i])\n\t\t{\n\t\t\t_game->pushState(new AllocateTrainingState(_bases.at(i)));\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/TrainingState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2015 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass Base;\n\n/**\n * Screen shown monthly when the player has psi labs available.\n */\nclass TrainingState : public State\n{\nprivate:\n\tTextButton *_btnOk;\n\tWindow *_window;\n\tText *_txtTitle;\n\tstd::vector<TextButton*> _btnBases;\n\tstd::vector<Base*> _bases;\npublic:\n\t/// Creates the Psi Training state.\n\tTrainingState();\n\t/// Cleans up the Psi Training state.\n\t~TrainingState();\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking a Base button.\n\tvoid btnBaseXClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/UfoDetectedState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"UfoDetectedState.h\"\n#include <sstream>\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Savegame/Ufo.h\"\n#include \"../Mod/RuleUfo.h\"\n#include \"GeoscapeState.h\"\n#include \"Globe.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Savegame/AlienMission.h\"\n#include \"InterceptState.h\"\n#include \"../Mod/RuleCraft.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Ufo Detected window.\n * @param game Pointer to the core game.\n * @param ufo Pointer to the UFO to get info from.\n * @param state Pointer to the Geoscape.\n * @param detected Was the UFO detected?\n * @param hyperwave Was it a hyperwave radar?\n */\nUfoDetectedState::UfoDetectedState(Ufo *ufo, GeoscapeState *state, bool detected, bool hyperwave) : _ufo(ufo), _state(state)\n{\n\t// Generate UFO ID\n\tif (_ufo->getId() == 0)\n\t{\n\t\t_ufo->setId(_game->getSavedGame()->getId(\"STR_UFO\"));\n\n\t\tint soundId = _ufo->getRules()->getAlertSound();\n\t\tif (soundId != Mod::NO_SOUND)\n\t\t{\n\t\t\t_customSound = _game->getMod()->getSound(\"GEO.CAT\", soundId);\n\t\t}\n\n\t}\n\tif (_ufo->getAltitude() == \"STR_GROUND\" && _ufo->getLandId() == 0)\n\t{\n\t\t_ufo->setLandId(_game->getSavedGame()->getId(\"STR_LANDING_SITE\"));\n\t}\n\n\t_screen = false;\n\n\t// Create objects\n\tif (hyperwave)\n\t{\n\t\t_window = new Window(this, 224, 180, 16, 10, POPUP_BOTH);\n\t}\n\telse\n\t{\n\t\t_window = new Window(this, 224, 128, 16, 44, POPUP_BOTH);\n\t}\n\t_btnIntercept = new TextButton(200, 12, 28, 118);\n\t_btnCentre = new TextButton(200, 12, 28, 134);\n\t_btnCancel = new TextButton(200, 12, 28, 150);\n\t_txtUfo = new Text(207, 17, 28, 53);\n\t_txtDetected = new Text(100, 9, 28, 69);\n\t_txtHyperwave = new Text(214, 17, 21, 44);\n\t_lstInfo = new TextList(217, 32, 28, 80);\n\t_lstInfo2 = new TextList(217, 32, 28, 96);\n\n\tif (hyperwave)\n\t{\n\t\t_btnIntercept->setY(136);\n\t\t_btnCentre->setY(152);\n\t\t_btnCancel->setY(168);\n\t\t_txtUfo->setY(20);\n\t\t_txtDetected->setY(36);\n\t\t_lstInfo->setY(60);\n\t}\n\telse\n\t{\n\t\t_txtHyperwave->setVisible(false);\n\t\t_lstInfo2->setVisible(false);\n\t}\n\n\t// Set palette\n\tsetInterface(\"UFOInfo\", hyperwave);\n\n\tadd(_window, \"window\", \"UFOInfo\");\n\tadd(_btnIntercept, \"button\", \"UFOInfo\");\n\tadd(_btnCentre, \"button\", \"UFOInfo\");\n\tadd(_btnCancel, \"button\", \"UFOInfo\");\n\tadd(_txtUfo, \"text\", \"UFOInfo\");\n\tadd(_txtDetected, \"text\", \"UFOInfo\");\n\tadd(_txtHyperwave, \"text\", \"UFOInfo\");\n\tadd(_lstInfo, \"text\", \"UFOInfo\");\n\tadd(_lstInfo2, \"text\", \"UFOInfo\");\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"UFOInfo\");\n\n\tcenterAllSurfaces();\n\n\t_btnIntercept->setText(tr(\"STR_INTERCEPT\"));\n\t_btnIntercept->onMouseClick((ActionHandler)&UfoDetectedState::btnInterceptClick);\n\n\t_btnCentre->setText(tr(\"STR_CENTER_ON_UFO_TIME_5_SECONDS\"));\n\t_btnCentre->onMouseClick((ActionHandler)&UfoDetectedState::btnCentreClick);\n\n\tif (_game->isCtrlPressed())\n\t{\n\t\t_btnCancel->setText(tr(\"STR_IGNORE_UC\"));\n\t}\n\telse\n\t{\n\t\t_btnCancel->setText(tr(\"STR_CANCEL_UC\"));\n\t}\n\t_btnCancel->onMouseClick((ActionHandler)&UfoDetectedState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&UfoDetectedState::btnCancelClick, Options::keyCancel);\n\t_btnCancel->onKeyboardPress((ActionHandler)&UfoDetectedState::toggleCancel, SDLK_LCTRL);\n\t_btnCancel->onKeyboardRelease((ActionHandler)&UfoDetectedState::toggleCancel, SDLK_LCTRL);\n\t_btnCancel->onKeyboardPress((ActionHandler)&UfoDetectedState::toggleCancel, SDLK_RCTRL);\n\t_btnCancel->onKeyboardRelease((ActionHandler)&UfoDetectedState::toggleCancel, SDLK_RCTRL);\n\n\tif (detected)\n\t{\n\t\t_txtDetected->setText(tr(\"STR_DETECTED\"));\n\t}\n\telse\n\t{\n\t\t_txtDetected->setText(\"\");\n\t}\n\n\t_txtHyperwave->setAlign(ALIGN_CENTER);\n\t_txtHyperwave->setWordWrap(true);\n\t_txtHyperwave->setText(tr(\"STR_HYPER_WAVE_TRANSMISSIONS_ARE_DECODED\"));\n\n\t_txtUfo->setBig();\n\t_txtUfo->setText(_ufo->getName(_game->getLanguage()));\n\n\t_lstInfo->setColumns(2, 77, 140);\n\t_lstInfo->setDot(true);\n\n\tstd::ostringstream ss;\n\tss << Unicode::TOK_COLOR_FLIP << tr(_ufo->getRules()->getSize());\n\t_lstInfo->addRow(2, tr(\"STR_SIZE_UC\").c_str(), ss.str().c_str());\n\tss.str(\"\");\n\n\tstd::string altitude = _ufo->getAltitude() == \"STR_GROUND\" ? \"STR_GROUNDED\" : _ufo->getAltitude();\n\t// Let's assume if there's any underwater craft, the UFO are underwater too\n\tbool underwater = false;\n\tfor (auto& craftType : _game->getMod()->getCraftsList())\n\t{\n\t\tif (underwater)\n\t\t{\n\t\t\tbreak; // loop finished\n\t\t}\n\t\tunderwater = _game->getMod()->getCraft(craftType)->isWaterOnly();\n\t}\n\tif (underwater && !_state->getGlobe()->insideLand(_ufo->getLongitude(), _ufo->getLatitude()))\n\t{\n\t\taltitude = \"STR_AIRBORNE\";\n\t}\n\tss << Unicode::TOK_COLOR_FLIP << tr(altitude);\n\t_lstInfo->addRow(2, tr(\"STR_ALTITUDE\").c_str(), ss.str().c_str());\n\n\tstd::string heading = _ufo->getDirection();\n\tif (_ufo->getStatus() != Ufo::FLYING)\n\t{\n\t\theading = \"STR_NONE_UC\";\n\t}\n\tss.str(\"\");\n\tss << Unicode::TOK_COLOR_FLIP << tr(heading);\n\t_lstInfo->addRow(2, tr(\"STR_HEADING\").c_str(), ss.str().c_str());\n\n\tss.str(\"\");\n\tss << Unicode::TOK_COLOR_FLIP << Unicode::formatNumber(_ufo->getSpeed());\n\t_lstInfo->addRow(2, tr(\"STR_SPEED\").c_str(), ss.str().c_str());\n\n\t_lstInfo2->setColumns(2, 77, 140);\n\t_lstInfo2->setDot(true);\n\n\tss.str(\"\");\n\tss << Unicode::TOK_COLOR_FLIP << tr(_ufo->getRules()->getType());\n\t_lstInfo2->addRow(2, tr(\"STR_CRAFT_TYPE\").c_str(), ss.str().c_str());\n\n\tss.str(\"\");\n\tss << Unicode::TOK_COLOR_FLIP << tr(_ufo->getAlienRace());\n\t_lstInfo2->addRow(2, tr(\"STR_RACE\").c_str(), ss.str().c_str());\n\n\tss.str(\"\");\n\tss << Unicode::TOK_COLOR_FLIP << tr(_ufo->getMissionType());\n\t_lstInfo2->addRow(2, tr(\"STR_MISSION\").c_str(), ss.str().c_str());\n\n\tss.str(\"\");\n\tss << Unicode::TOK_COLOR_FLIP << tr(_ufo->getMission()->getRegion());\n\t_lstInfo2->addRow(2, tr(\"STR_ZONE\").c_str(), ss.str().c_str());\n}\n\n/**\n *\n */\nUfoDetectedState::~UfoDetectedState()\n{\n\n}\n\n/**\n * Picks a craft to intercept the UFO.\n * @param action Pointer to an action.\n */\nvoid UfoDetectedState::btnInterceptClick(Action *)\n{\n\t_state->timerReset();\n\t_state->getGlobe()->center(_ufo->getLongitude(), _ufo->getLatitude());\n\t_game->pushState(new InterceptState(_state->getGlobe(), false, 0, _ufo));\n}\n\n/**\n * Centers on the UFO and returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid UfoDetectedState::btnCentreClick(Action *)\n{\n\t_state->timerReset();\n\t_state->getGlobe()->center(_ufo->getLongitude(), _ufo->getLatitude());\n\t_game->popState();\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid UfoDetectedState::btnCancelClick(Action *)\n{\n\tif (_game->isCtrlPressed())\n\t{\n\t\t// don't show UFO Detected window for this UFO anymore\n\t\t_game->getSavedGame()->addUfoToIgnoreList(_ufo->getId());\n\t}\n\t_game->popState();\n}\n\n/**\n * Toggles Cancel button.\n * @param action Pointer to an action.\n */\nvoid UfoDetectedState::toggleCancel(Action *)\n{\n\tif (_game->isCtrlPressed())\n\t{\n\t\t_btnCancel->setText(tr(\"STR_IGNORE_UC\"));\n\t}\n\telse\n\t{\n\t\t_btnCancel->setText(tr(\"STR_CANCEL_UC\"));\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/UfoDetectedState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass Ufo;\nclass TextButton;\nclass Window;\nclass Text;\nclass TextList;\nclass GeoscapeState;\n\n/**\n * Displays info on a detected UFO.\n */\nclass UfoDetectedState : public State\n{\nprivate:\n\tUfo *_ufo;\n\tGeoscapeState *_state;\n\n\tTextButton *_btnIntercept, *_btnCentre, *_btnCancel;\n\tWindow *_window;\n\tText *_txtUfo, *_txtDetected, *_txtHyperwave;\n\tTextList *_lstInfo, *_lstInfo2;\npublic:\n\t/// Creates the Ufo Detected state.\n\tUfoDetectedState(Ufo *ufo, GeoscapeState *state, bool detected, bool hyperwave);\n\t/// Cleans up the Ufo Detected state.\n\t~UfoDetectedState();\n\t/// Handler for clicking the Intercept button.\n\tvoid btnInterceptClick(Action *action);\n\t/// Handler for clicking the Centre on UFO button.\n\tvoid btnCentreClick(Action *action);\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action *action);\n\t/// Handler for pressing/releasing CTRL.\n\tvoid toggleCancel(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/UfoLostState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"UfoLostState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Engine/Options.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Ufo Lost window.\n * @param game Pointer to the core game.\n * @param id Name of the UFO.\n */\nUfoLostState::UfoLostState(const std::string &id) : _id(id)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 192, 104, 32, 48, POPUP_BOTH);\n\t_btnOk = new TextButton(60, 12, 98, 112);\n\t_txtTitle = new Text(160, 32, 48, 72);\n\n\t// Set palette\n\tsetInterface(\"UFOLost\");\n\n\tadd(_window, \"window\", \"UFOLost\");\n\tadd(_btnOk, \"button\", \"UFOLost\");\n\tadd(_txtTitle, \"text\", \"UFOLost\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"UFOLost\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&UfoLostState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&UfoLostState::btnOkClick, Options::keyOk);\n\t_btnOk->onKeyboardPress((ActionHandler)&UfoLostState::btnOkClick, Options::keyCancel);\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\tstd::string s = _id;\n\ts += '\\n';\n\ts += tr(\"STR_TRACKING_LOST\");\n\t_txtTitle->setText(s);\n}\n\n/**\n *\n */\nUfoLostState::~UfoLostState()\n{\n\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid UfoLostState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/UfoLostState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include <string>\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\n\n/**\n * Notifies the player when a targeted UFO\n * goes outside radar range.\n */\nclass UfoLostState : public State\n{\nprivate:\n\tTextButton *_btnOk;\n\tWindow *_window;\n\tText *_txtTitle;\n\tstd::string _id;\npublic:\n\t/// Creates the Ufo Lost state.\n\tUfoLostState(const std::string &id);\n\t/// Cleans up the Ufo Lost state.\n\t~UfoLostState();\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Geoscape/UfoTrackerState.cpp",
    "content": "/*\n * Copyright 2010-2015 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"UfoTrackerState.h\"\n#include \"InterceptState.h\"\n#include <sstream>\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Savegame/MissionSite.h\"\n#include \"../Savegame/Ufo.h\"\n#include \"../Savegame/AlienBase.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Engine/Options.h\"\n#include \"Globe.h\"\n#include \"GeoscapeState.h\"\n#include \"UfoDetectedState.h\"\n#include \"TargetInfoState.h\"\n#include \"../Ufopaedia/Ufopaedia.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the UfoTracker window.\n * @param state Pointer to the Geoscape.\n * @param globe Pointer to the Geoscape globe.\n */\nUfoTrackerState::UfoTrackerState(GeoscapeState *state, Globe *globe) : _state(state), _globe(globe)\n{\n\tconst int WIDTH_OBJECT = 88;\n\tconst int WIDTH_SIZE = 60;\n\tconst int WIDTH_ALTITUDE = 54;\n\tconst int WIDTH_HEADING = 54;\n\tconst int WIDTH_SPEED = 32;\n\t_screen = false;\n\n\tint extraRows = Clamp(Options::oxceInterceptTableSize, 8, 80) - 8;\n\tint extraHeight = 8 * extraRows;\n\tint offset = extraHeight / 2;\n\n\t// Create objects\n\t_window = new Window(this, 320, 140 + extraHeight, 0, 30 - offset, POPUP_HORIZONTAL);\n\t_btnCancel = new TextButton(288, 16, 16, 146 + offset);\n\t_txtTitle = new Text(300, 17, 10, 46 - offset);\n\tint x = 14;\n\t_txtObject = new Text(WIDTH_OBJECT, 9, x, 70 - offset);\n\tx += WIDTH_OBJECT;\n\t_txtSize = new Text(WIDTH_SIZE, 9, x, 70 - offset);\n\tx += WIDTH_SIZE;\n\t_txtAltitude = new Text(WIDTH_ALTITUDE, 9, x, 70 - offset);\n\tx += WIDTH_ALTITUDE;\n\t_txtHeading = new Text(WIDTH_HEADING, 9, x, 70 - offset);\n\tx += WIDTH_HEADING;\n\t_txtSpeed = new Text(WIDTH_SPEED+16, 17, x-16, 70 - offset); // 16 pixels overlap for translators\n\t_lstObjects = new TextList(290, 64 + extraHeight, 12, 78 - offset);\n\n\t// Set palette\n\tsetInterface(\"ufoTracker\");\n\n\tadd(_window, \"window\", \"ufoTracker\");\n\tadd(_btnCancel, \"button\", \"ufoTracker\");\n\tadd(_txtTitle, \"text1\", \"ufoTracker\");\n\tadd(_txtObject, \"text2\", \"ufoTracker\");\n\tadd(_txtSize, \"text2\", \"ufoTracker\");\n\tadd(_txtAltitude, \"text2\", \"ufoTracker\");\n\tadd(_txtHeading, \"text2\", \"ufoTracker\");\n\tadd(_txtSpeed, \"text2\", \"ufoTracker\");\n\tadd(_lstObjects, \"list\", \"ufoTracker\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"ufoTracker\");\n\n\t_btnCancel->setText(tr(\"STR_CANCEL\"));\n\t_btnCancel->onMouseClick((ActionHandler)&UfoTrackerState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&UfoTrackerState::btnCancelClick, Options::keyCancel);\n\t_btnCancel->onKeyboardPress((ActionHandler)&UfoTrackerState::btnCancelClick, Options::keyGeoUfoTracker);\n\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setBig();\n\t_txtTitle->setText(tr(\"STR_UFO_TRACKER\"));\n\n\t_txtObject->setText(tr(\"STR_NAME_UC\"));\n\n\t_txtSize->setText(tr(\"STR_SIZE_UC\"));\n\n\t_txtAltitude->setText(tr(\"STR_ALTITUDE\"));\n\n\t_txtHeading->setText(tr(\"STR_HEADING\"));\n\n\t_txtSpeed->setAlign(ALIGN_RIGHT);\n\t_txtSpeed->setText(tr(\"STR_SPEED\"));\n\n\t_lstObjects->setColumns(5, WIDTH_OBJECT, WIDTH_SIZE, WIDTH_ALTITUDE, WIDTH_HEADING, WIDTH_SPEED);\n\t_lstObjects->setAlign(ALIGN_RIGHT, 4);\n\t_lstObjects->setSelectable(true);\n\t_lstObjects->setBackground(_window);\n\t_lstObjects->setMargin(2);\n\t_lstObjects->onMouseClick((ActionHandler)&UfoTrackerState::lstObjectsLeftClick);\n\t_lstObjects->onMouseClick((ActionHandler)&UfoTrackerState::lstObjectsRightClick, SDL_BUTTON_RIGHT);\n\t_lstObjects->onMouseClick((ActionHandler)&UfoTrackerState::lstObjectsMiddleClick, SDL_BUTTON_MIDDLE);\n\n\tint row = 0;\n\tfor (auto* site : *_game->getSavedGame()->getMissionSites())\n\t{\n\t\tif (!site->getDetected())\n\t\t\tcontinue;\n\n\t\t_objects.push_back(site);\n\t\t_lstObjects->addRow(1, site->getName(_game->getLanguage()).c_str());\n\t\t_lstObjects->setCellColor(row, 0, _lstObjects->getSecondaryColor());\n\t\trow++;\n\t}\n\n\tfor (auto* ufo : *_game->getSavedGame()->getUfos())\n\t{\n\t\tif (!ufo->getDetected() || ufo->getStatus() == Ufo::IGNORE_ME)\n\t\t\tcontinue;\n\n\t\tstd::ostringstream ss1;\n\t\tss1 << tr(ufo->getRules()->getSize());\n\n\t\tstd::ostringstream ss2;\n\t\tstd::string altitude = ufo->getAltitude() == \"STR_GROUND\" ? \"STR_GROUNDED\" : ufo->getAltitude();\n\t\tss2 << tr(altitude);\n\n\t\tstd::ostringstream ss3;\n\t\tstd::string heading = ufo->getStatus() != Ufo::FLYING ? \"STR_NONE_UC\" : ufo->getDirection();\n\t\tss3 << tr(heading);\n\n\t\tstd::ostringstream ss4;\n\t\tss4 << Unicode::formatNumber(ufo->getSpeed());\n\n\t\t_objects.push_back(ufo);\n\t\t_lstObjects->addRow(5, ufo->getName(_game->getLanguage()).c_str(), ss1.str().c_str(), ss2.str().c_str(), ss3.str().c_str(), ss4.str().c_str());\n\t\tif (altitude == \"STR_GROUNDED\")\n\t\t{\n\t\t\t_lstObjects->setCellColor(row, 2, _lstObjects->getSecondaryColor());\n\t\t}\n\t\trow++;\n\t}\n\n\tfor (auto* ab : *_game->getSavedGame()->getAlienBases())\n\t{\n\t\tif (!ab->isDiscovered())\n\t\t\tcontinue;\n\n\t\t_objects.push_back(ab);\n\t\t_lstObjects->addRow(1, ab->getName(_game->getLanguage()).c_str());\n\t\trow++;\n\t}\n}\n\n/**\n *\n */\nUfoTrackerState::~UfoTrackerState()\n{\n\n}\n\n/**\n * Closes the window.\n * @param action Pointer to an action.\n */\nvoid UfoTrackerState::btnCancelClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n* Displays the right popup for a specific target.\n* @param target Pointer to target.\n*/\nvoid UfoTrackerState::popupTarget(Target *target)\n{\n\t_game->popState();\n\n\tUfo* u = dynamic_cast<Ufo*>(target);\n\n\tif (u != 0)\n\t{\n\t\t_game->pushState(new UfoDetectedState(u, _state, false, u->getHyperDetected()));\n\t}\n\telse\n\t{\n\t\t_game->pushState(new TargetInfoState(target, _globe));\n\t}\n}\n\n/**\n * Displays object detail.\n * @param action Pointer to an action.\n */\nvoid UfoTrackerState::lstObjectsLeftClick(Action *)\n{\n\tTarget* t = _objects[_lstObjects->getSelectedRow()];\n\tif (t)\n\t{\n\t\tpopupTarget(t);\n\t}\n}\n\n/**\n * Centers on the selected object.\n * @param action Pointer to an action.\n */\nvoid UfoTrackerState::lstObjectsRightClick(Action *)\n{\n\tTarget* t = _objects[_lstObjects->getSelectedRow()];\n\tif (t)\n\t{\n\t\t_globe->center(t->getLongitude(), t->getLatitude());\n\t\t_game->popState();\n\t}\n}\n\n/**\n* Opens the corresponding Ufopaedia article.\n* @param action Pointer to an action.\n*/\nvoid UfoTrackerState::lstObjectsMiddleClick(Action *)\n{\n\tTarget* t = _objects[_lstObjects->getSelectedRow()];\n\tif (t)\n\t{\n\t\tUfo* u = dynamic_cast<Ufo*>(t);\n\n\t\tif (u != 0 && u->getHyperDetected())\n\t\t{\n\t\t\tstd::string articleId = u->getRules()->getType();\n\t\t\tUfopaedia::openArticle(_game, articleId);\n\t\t}\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Geoscape/UfoTrackerState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2015 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <vector>\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass TextList;\nclass Globe;\nclass Target;\nclass GeoscapeState;\n\n/**\n * UFO Tracker window that allows the player to track\n * various things (UFOs, Crash sites, Landing sites, Terror sites, Mission sites, Alien bases) on the Geoscape.\n */\nclass UfoTrackerState : public State\n{\nprivate:\n\tTextButton *_btnCancel;\n\tWindow *_window;\n\tText *_txtTitle, *_txtObject, *_txtSize, *_txtAltitude, *_txtHeading, *_txtSpeed;\n\tTextList *_lstObjects;\n\tGeoscapeState *_state;\n\tGlobe *_globe;\n\tstd::vector<Target*> _objects;\npublic:\n\t/// Creates the UfoTracker state.\n\tUfoTrackerState(GeoscapeState *state, Globe *globe);\n\t/// Cleans up the UfoTracker state.\n\t~UfoTrackerState();\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action *action);\n\t/// Popup for a target.\n\tvoid popupTarget(Target *target);\n\t/// Handler for clicking the Objects list.\n\tvoid lstObjectsLeftClick(Action *action);\n\t/// Handler for right clicking the Objects list.\n\tvoid lstObjectsRightClick(Action *action);\n\t/// Handler for middle clicking the Objects list.\n\tvoid lstObjectsMiddleClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Interface/ArrowButton.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ArrowButton.h\"\n#include \"TextList.h\"\n#include \"../Engine/Timer.h\"\n#include \"../Engine/Action.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Sets up an arrow button with the specified size and position.\n * @param shape Shape of the arrow.\n * @param width Width in pixels.\n * @param height Height in pixels.\n * @param x X position in pixels.\n * @param y Y position in pixels.\n */\nArrowButton::ArrowButton(ArrowShape shape, int width, int height, int x, int y) : ImageButton(width, height, x, y), _shape(shape), _list(0)\n{\n\t_timer = new Timer(50);\n\t_timer->onTimer((SurfaceHandler)&ArrowButton::scroll);\n}\n\n/**\n * Deletes timers.\n */\nArrowButton::~ArrowButton()\n{\n\tdelete _timer;\n}\n\nbool ArrowButton::isButtonHandled(Uint8 button)\n{\n\tif (_list != 0)\n\t{\n\t\treturn (button == SDL_BUTTON_LEFT || button == SDL_BUTTON_RIGHT);\n\t}\n\telse\n\t{\n\t\treturn ImageButton::isButtonHandled(button);\n\t}\n}\n\n/**\n * Changes the color for the image button.\n * @param color Color value.\n */\nvoid ArrowButton::setColor(Uint8 color)\n{\n\tImageButton::setColor(color);\n\t_redraw = true;\n}\n\n/**\n * Changes the shape for the arrow button.\n * @param shape Shape of the arrow.\n */\nvoid ArrowButton::setShape(ArrowShape shape)\n{\n\t_shape = shape;\n\t_redraw = true;\n}\n\n/**\n * Changes the list associated with the arrow button.\n * This makes the button scroll that list.\n * @param list Pointer to text list.\n */\nvoid ArrowButton::setTextList(TextList *list)\n{\n\t_list = list;\n}\n\n/**\n * Draws the button with the specified arrow shape.\n */\nvoid ArrowButton::draw()\n{\n\tImageButton::draw();\n\tlock();\n\n\t// Draw button\n\tSDL_Rect square;\n\tint color = _color + 2;\n\n\tsquare.x = 0;\n\tsquare.y = 0;\n\tsquare.w = getWidth() - 1;\n\tsquare.h = getHeight() - 1;\n\n\tdrawRect(&square, color);\n\n\tsquare.x++;\n\tsquare.y++;\n\tcolor = _color + 5;\n\n\tdrawRect(&square, color);\n\n\tsquare.w--;\n\tsquare.h--;\n\tcolor = _color + 4;\n\n\tdrawRect(&square, color);\n\n\tsetPixel(0, 0, _color + 1);\n\tsetPixel(0, getHeight() - 1, _color + 4);\n\tsetPixel(getWidth() - 1, 0, _color + 4);\n\n\tcolor = _color + 1;\n\n\tswitch (_shape)\n\t{\n\tcase OpenXcom::ARROW_BIG_UP:\n\t\t// Draw arrow square\n\t\tsquare.x = 5;\n\t\tsquare.y = 8;\n\t\tsquare.w = 3;\n\t\tsquare.h = 3;\n\n\t\tdrawRect(&square, color);\n\n\t\t// Draw arrow triangle\n\t\tsquare.x = 2;\n\t\tsquare.y = 7;\n\t\tsquare.w = 9;\n\t\tsquare.h = 1;\n\n\t\tfor (; square.w > 1; square.w -= 2)\n\t\t{\n\t\t\tdrawRect(&square, color);\n\t\t\tsquare.x++;\n\t\t\tsquare.y--;\n\t\t}\n\t\tdrawRect(&square, color);\n\t\tbreak;\n\tcase OpenXcom::ARROW_BIG_DOWN:\n\t\t// Draw arrow square\n\t\tsquare.x = 5;\n\t\tsquare.y = 3;\n\t\tsquare.w = 3;\n\t\tsquare.h = 3;\n\n\t\tdrawRect(&square, color);\n\n\t\t// Draw arrow triangle\n\t\tsquare.x = 2;\n\t\tsquare.y = 6;\n\t\tsquare.w = 9;\n\t\tsquare.h = 1;\n\n\t\tfor (; square.w > 1; square.w -= 2)\n\t\t{\n\t\t\tdrawRect(&square, color);\n\t\t\tsquare.x++;\n\t\t\tsquare.y++;\n\t\t}\n\t\tdrawRect(&square, color);\n\t\tbreak;\n\tcase OpenXcom::ARROW_SMALL_UP:\n\t\t// Draw arrow triangle 1\n\t\tsquare.x = 1;\n\t\tsquare.y = 5;\n\t\tsquare.w = 9;\n\t\tsquare.h = 1;\n\n\t\tfor (; square.w > 1; square.w -= 2)\n\t\t{\n\t\t\tdrawRect(&square, color + 2);\n\t\t\tsquare.x++;\n\t\t\tsquare.y--;\n\t\t}\n\t\tdrawRect(&square, color + 2);\n\n\t\t// Draw arrow triangle 2\n\t\tsquare.x = 2;\n\t\tsquare.y = 5;\n\t\tsquare.w = 7;\n\t\tsquare.h = 1;\n\n\t\tfor (; square.w > 1; square.w -= 2)\n\t\t{\n\t\t\tdrawRect(&square, color);\n\t\t\tsquare.x++;\n\t\t\tsquare.y--;\n\t\t}\n\t\tdrawRect(&square, color);\n\t\tbreak;\n\tcase OpenXcom::ARROW_SMALL_DOWN:\n\t\t// Draw arrow triangle 1\n\t\tsquare.x = 1;\n\t\tsquare.y = 2;\n\t\tsquare.w = 9;\n\t\tsquare.h = 1;\n\n\t\tfor (; square.w > 1; square.w -= 2)\n\t\t{\n\t\t\tdrawRect(&square, color + 2);\n\t\t\tsquare.x++;\n\t\t\tsquare.y++;\n\t\t}\n\t\tdrawRect(&square, color + 2);\n\n\t\t// Draw arrow triangle 2\n\t\tsquare.x = 2;\n\t\tsquare.y = 2;\n\t\tsquare.w = 7;\n\t\tsquare.h = 1;\n\n\t\tfor (; square.w > 1; square.w -= 2)\n\t\t{\n\t\t\tdrawRect(&square, color);\n\t\t\tsquare.x++;\n\t\t\tsquare.y++;\n\t\t}\n\t\tdrawRect(&square, color);\n\t\tbreak;\n\tcase OpenXcom::ARROW_SMALL_LEFT:\n\t\t// Draw arrow triangle 1\n\t\tsquare.x = 2;\n\t\tsquare.y = 4;\n\t\tsquare.w = 2;\n\t\tsquare.h = 1;\n\n\t\tfor (; square.h < 5; square.h += 2)\n\t\t{\n\t\t\tdrawRect(&square, color + 2);\n\t\t\tsquare.x += 2;\n\t\t\tsquare.y--;\n\t\t}\n\t\tsquare.w = 1;\n\t\tdrawRect(&square, color + 2);\n\n\t\t// Draw arrow triangle 2\n\t\tsquare.x = 3;\n\t\tsquare.y = 4;\n\t\tsquare.w = 2;\n\t\tsquare.h = 1;\n\n\t\tfor (; square.h < 5; square.h += 2)\n\t\t{\n\t\t\tdrawRect(&square, color);\n\t\t\tsquare.x += 2;\n\t\t\tsquare.y--;\n\t\t}\n\t\tsquare.w = 1;\n\t\tdrawRect(&square, color);\n\t\tbreak;\n\tcase OpenXcom::ARROW_SMALL_RIGHT:\n\t\t// Draw arrow triangle 1\n\t\tsquare.x = 7;\n\t\tsquare.y = 4;\n\t\tsquare.w = 2;\n\t\tsquare.h = 1;\n\n\t\tfor (; square.h < 5; square.h += 2)\n\t\t{\n\t\t\tdrawRect(&square, color + 2);\n\t\t\tsquare.x -= 2;\n\t\t\tsquare.y--;\n\t\t}\n\t\tsquare.x++;\n\t\tsquare.w = 1;\n\t\tdrawRect(&square, color + 2);\n\n\t\t// Draw arrow triangle 2\n\t\tsquare.x = 6;\n\t\tsquare.y = 4;\n\t\tsquare.w = 2;\n\t\tsquare.h = 1;\n\n\t\tfor (; square.h < 5; square.h += 2)\n\t\t{\n\t\t\tdrawRect(&square, color);\n\t\t\tsquare.x -= 2;\n\t\t\tsquare.y--;\n\t\t}\n\t\tsquare.x++;\n\t\tsquare.w = 1;\n\t\tdrawRect(&square, color);\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n\n\tunlock();\n}\n\n/**\n * Keeps the scrolling timers running.\n */\nvoid ArrowButton::think()\n{\n\t_timer->think(0, this);\n}\n\n/**\n * Scrolls the list.\n */\nvoid ArrowButton::scroll()\n{\n\tif (_shape == ARROW_BIG_UP)\n\t{\n\t\t_list->scrollUp(false);\n\t}\n\telse if (_shape == ARROW_BIG_DOWN)\n\t{\n\t\t_list->scrollDown(false);\n\t}\n}\n\n/**\n * Starts scrolling the associated list.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid ArrowButton::mousePress(Action *action, State *state)\n{\n\tImageButton::mousePress(action, state);\n\tif (_list != 0)\n\t{\n\t\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT)\n\t\t{\n\t\t\t_timer->start();\n\t\t}\n\t\telse if (action->getDetails()->button.button == SDL_BUTTON_WHEELUP) _list->scrollUp(false, true);\n\t\telse if (action->getDetails()->button.button == SDL_BUTTON_WHEELDOWN) _list->scrollDown(false, true);\n\t}\n}\n\n/*\n * Stops scrolling the associated list.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid ArrowButton::mouseRelease(Action *action, State *state)\n{\n\tImageButton::mouseRelease(action, state);\n\tif (_list != 0 && action->getDetails()->button.button == SDL_BUTTON_LEFT)\n\t{\n\t\t_timer->stop();\n\t}\n}\n\n/*\n * Scrolls the associated list to top or bottom.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid ArrowButton::mouseClick(Action *action, State *state)\n{\n\tImageButton::mouseClick(action, state);\n\tif (_list != 0 && SDL_BUTTON_RIGHT == action->getDetails()->button.button) {\n\t\tif (_shape == ARROW_BIG_UP) _list->scrollUp(true);\n\t\telse if (_shape == ARROW_BIG_DOWN) _list->scrollDown(true);\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Interface/ArrowButton.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ImageButton.h\"\n\nnamespace OpenXcom\n{\n\nenum ArrowShape { ARROW_NONE, ARROW_BIG_UP, ARROW_BIG_DOWN, ARROW_SMALL_UP, ARROW_SMALL_DOWN, ARROW_SMALL_LEFT, ARROW_SMALL_RIGHT };\n\nclass TextList;\nclass Timer;\n\n/**\n * Button with an arrow on it. Can be used for\n * scrolling lists, spinners, etc. Contains various\n * arrow shapes.\n */\nclass ArrowButton : public ImageButton\n{\nprivate:\n\tArrowShape _shape;\n\tTextList *_list;\n\tTimer *_timer;\nprotected:\n\tbool isButtonHandled(Uint8 button = 0) override;\npublic:\n\t/// Creates a new arrow button with the specified size and position.\n\tArrowButton(ArrowShape shape, int width, int height, int x = 0, int y = 0);\n\t/// Cleans up the arrow button.\n\t~ArrowButton();\n\t/// Sets the arrow button's color.\n\tvoid setColor(Uint8 color) override;\n\t/// Sets the arrow button's shape.\n\tvoid setShape(ArrowShape shape);\n\t/// Sets the arrow button's list.\n\tvoid setTextList(TextList *list);\n\t/// Handles the timers.\n\tvoid think() override;\n\t/// Scrolls the list.\n\tvoid scroll();\n\t/// Draws the arrow button.\n\tvoid draw() override;\n\t/// Special handling for mouse presses.\n\tvoid mousePress(Action *action, State *state) override;\n\t/// Special handling for mouse releases.\n\tvoid mouseRelease(Action *action, State *state) override;\n\t/// Special handling for mouse clicks.\n\tvoid mouseClick(Action *action, State *state) override;\n};\n\n}\n"
  },
  {
    "path": "src/Interface/Bar.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Bar.h\"\n#include <SDL.h>\n\nnamespace OpenXcom\n{\n\n/**\n * Sets up a blank bar with the specified size and position.\n * @param width Width in pixels.\n * @param height Height in pixels.\n * @param x X position in pixels.\n * @param y Y position in pixels.\n */\nBar::Bar(int width, int height, int x, int y) : Surface(width, height, x, y), _color(0), _color2(0), _borderColor(0), _scale(0), _max(0), _value(0), _value2(0), _secondOnTop(true)\n{\n\n}\n\n/**\n *\n */\nBar::~Bar()\n{\n}\n\n/**\n * Changes the color used to draw the border and contents.\n * @param color Color value.\n */\nvoid Bar::setColor(Uint8 color)\n{\n\t_color = color;\n\t_redraw = true;\n}\n\n/**\n * Returns the color used to draw the bar.\n * @return Color value.\n */\nUint8 Bar::getColor() const\n{\n\treturn _color;\n}\n\n/**\n * Changes the color used to draw the second contents.\n * @param color Color value.\n */\nvoid Bar::setSecondaryColor(Uint8 color)\n{\n\t_color2 = color;\n\t_redraw = true;\n}\n\n/**\n * Returns the second color used to draw the bar.\n * @return Color value.\n */\nUint8 Bar::getSecondaryColor() const\n{\n\treturn _color2;\n}\n\n/**\n * Changes the scale factor used to draw the bar values.\n * @param scale Scale in pixels/unit.\n */\nvoid Bar::setScale(double scale)\n{\n\t_scale = scale;\n\t_redraw = true;\n}\n\n/**\n * Returns the scale factor used to draw the bar values.\n * @return Scale in pixels/unit.\n */\ndouble Bar::getScale() const\n{\n\treturn _scale;\n}\n\n/**\n * Changes the maximum value used to draw the outer border.\n * @param max Maximum value.\n */\nvoid Bar::setMax(double max)\n{\n\t_max = max;\n\t_redraw = true;\n}\n\n/**\n * Returns the maximum value used to draw the outer border.\n * @return Maximum value.\n */\ndouble Bar::getMax() const\n{\n\treturn _max;\n}\n\n/**\n * Changes the value used to draw the inner contents.\n * @param value Current value.\n */\nvoid Bar::setValue(double value)\n{\n\t_value = (value < 0.0)? 0.0 : value;\n\t_redraw = true;\n}\n\n/**\n * Returns the value used to draw the inner contents.\n * @return Current value.\n */\ndouble Bar::getValue() const\n{\n\treturn _value;\n}\n\n/**\n * Changes the value used to draw the second inner contents.\n * @param value Current value.\n */\nvoid Bar::setValue2(double value)\n{\n\t_value2 = (value < 0.0)? 0.0 : value;\n\t_redraw = true;\n}\n\n/**\n * Returns the value used to draw the second inner contents.\n * @return Current value.\n */\ndouble Bar::getValue2() const\n{\n\treturn _value2;\n}\n\n/**\n * Defines whether the second value should be drawn on top. Default this is true.\n * @param onTop Second value on top?\n */\nvoid Bar::setSecondValueOnTop(bool onTop)\n{\n\t_secondOnTop = onTop;\n}\n\n/**\n * Draws the bordered bar filled according\n * to its values.\n */\nvoid Bar::draw()\n{\n\tSurface::draw();\n\tSDL_Rect square;\n\n\tsquare.x = 0;\n\tsquare.y = 0;\n\tsquare.w = (Uint16)(_scale * _max) + 1;\n\tsquare.h = getHeight();\n\n\tif (_borderColor)\n\t\tdrawRect(&square, _borderColor);\n\telse\n\t\tdrawRect(&square, _color + 4);\n\n\tsquare.y++;\n\tsquare.w--;\n\tsquare.h -= 2;\n\n\tdrawRect(&square, 0);\n\n\tif (_secondOnTop)\n\t{\n\t\tsquare.w = (Uint16)(_scale * _value);\n\t\tdrawRect(&square, _color);\n\t\tsquare.w = (Uint16)(_scale * _value2);\n\t\tdrawRect(&square, _color2);\n\t}\n\telse\n\t{\n\t\tsquare.w = (Uint16)(_scale * _value2);\n\t\tdrawRect(&square, _color2);\n\t\tsquare.w = (Uint16)(_scale * _value);\n\t\tdrawRect(&square, _color);\n\t}\n}\n\n/**\n * sets the border color for the bar.\n * @param bc the color for the outline of the bar.\n * @note will use base colour + 4 if none is defined here.\n */\nvoid Bar::setBorderColor(Uint8 bc)\n{\n\t_borderColor = bc;\n}\n\n}\n"
  },
  {
    "path": "src/Interface/Bar.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/Surface.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Bar graphic that represents a certain value.\n * Drawn with a coloured border and partially\n * filled content to contrast two values, typically\n * used for showing base and soldier stats.\n */\nclass Bar : public Surface\n{\nprivate:\n\tUint8 _color, _color2, _borderColor;\n\tdouble _scale, _max, _value, _value2;\n\tbool _secondOnTop;\npublic:\n\t/// Creates a new bar with the specified size and position.\n\tBar(int width, int height, int x = 0, int y = 0);\n\t/// Cleans up the bar.\n\t~Bar();\n\t/// Sets the bar's color.\n\tvoid setColor(Uint8 color) override;\n\t/// Gets the bar's color.\n\tUint8 getColor() const;\n\t/// Sets the bar's second color.\n\tvoid setSecondaryColor(Uint8 color) override;\n\t/// Gets the bar's second color.\n\tUint8 getSecondaryColor() const;\n\t/// Sets the bar's scale.\n\tvoid setScale(double scale);\n\t/// Gets the bar's scale.\n\tdouble getScale() const;\n\t/// Sets the bar's maximum value.\n\tvoid setMax(double max);\n\t/// Gets the bar's maximum value.\n\tdouble getMax() const;\n\t/// Sets the bar's current value.\n\tvoid setValue(double value);\n\t/// Gets the bar's current value.\n\tdouble getValue() const;\n\t/// Sets the bar's second current value.\n\tvoid setValue2(double value);\n\t/// Gets the bar's second current value.\n\tdouble getValue2() const;\n\t/// Defines whether the second value should be drawn on top.\n\tvoid setSecondValueOnTop(bool onTop);\n\t/// Draws the bar.\n\tvoid draw() override;\n\t/// set the outline color for the bar.\n\tvoid setBorderColor(Uint8 bc) override;\n};\n\n}\n"
  },
  {
    "path": "src/Interface/BattlescapeButton.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"BattlescapeButton.h\"\n#include \"../Engine/Action.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Sets up a battlescape button with the specified size and position.\n * @param width Width in pixels.\n * @param height Height in pixels.\n * @param x X position in pixels.\n * @param y Y position in pixels.\n */\nBattlescapeButton::BattlescapeButton(int width, int height, int x, int y) : InteractiveSurface(width, height, x, y), _color(0), _group(0), _inverted(false), _toggleMode(INVERT_NONE), _altSurface(0)\n{\n}\n\n/**\n *\n */\nBattlescapeButton::~BattlescapeButton()\n{\n\tdelete _altSurface;\n}\n\n/**\n * Changes the color for the battlescape button.\n * @param color Color value.\n */\nvoid BattlescapeButton::setColor(Uint8 color)\n{\n\t_color = color;\n}\n\n/**\n * Returns the color for the battlescape button.\n * @return Color value.\n */\nUint8 BattlescapeButton::getColor() const\n{\n\treturn _color;\n}\n\n/**\n * Changes the button group this battlescape button belongs to.\n * @param group Pointer to the pressed button pointer in the group.\n * Null makes it a regular button.\n */\nvoid BattlescapeButton::setGroup(BattlescapeButton **group)\n{\n\t_group = group;\n\tif (_group != 0 && *_group == this)\n\t\t_inverted = true;\n}\n\n/**\n * Sets the button as the pressed button if it's part of a group,\n * and inverts the colors when pressed.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid BattlescapeButton::mousePress(Action *action, State *state)\n{\n\tif (_group != 0)\n\t{\n\t\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT)\n\t\t{\n\t\t\t(*_group)->toggle(false);\n\t\t\t*_group = this;\n\t\t\t_inverted = true;\n\t\t}\n\t}\n\telse if ((_tftdMode || _toggleMode == INVERT_CLICK ) && !_inverted && isButtonPressed() && isButtonHandled(action->getDetails()->button.button))\n\t{\n\t\t_inverted = true;\n\t}\n\tInteractiveSurface::mousePress(action, state);\n}\n\n/*\n * Sets the button as the released button if it's part of a group.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid BattlescapeButton::mouseRelease(Action *action, State *state)\n{\n\tif (_inverted && (_tftdMode || _toggleMode == INVERT_CLICK) && isButtonHandled(action->getDetails()->button.button))\n\t{\n\t\t_inverted = false;\n\t}\n\tInteractiveSurface::mouseRelease(action, state);\n}\n\n/**\n * Invert a button explicitly either ON or OFF and keep track of the state using our internal variables.\n * @param press Set this button as pressed.\n */\nvoid BattlescapeButton::toggle(bool press)\n{\n\tif (_tftdMode || _toggleMode == INVERT_TOGGLE || _inverted)\n\t{\n\t\t_inverted = press;\n\t}\n}\n\n/**\n * Toggle inversion mode: click to press, click to unpress.\n */\nvoid BattlescapeButton::allowToggleInversion()\n{\n\t_toggleMode = INVERT_TOGGLE;\n}\n\n/**\n * Click inversion mode: click to press, release to unpress.\n */\nvoid BattlescapeButton::allowClickInversion()\n{\n\t_toggleMode = INVERT_CLICK;\n}\n\n/**\n * Initializes the alternate surface for swapping out as needed.\n * performs a colour swap for TFTD style buttons, and a palette inversion for coloured buttons\n * we use two separate surfaces because it's far easier to keep track of\n * whether or not this surface is inverted.\n */\nvoid BattlescapeButton::initSurfaces(Surface* custom)\n{\n\tdelete _altSurface;\n\t_altSurface = new Surface(_surface->w, _surface->h, _x, _y);\n\t_altSurface->setPalette(getPalette());\n\n\tif (custom)\n\t{\n\t\tcustom->blitNShade(_altSurface, 0, 0);\n\t\treturn;\n\t}\n\n\t// Lock the surface\n\t_altSurface->lock();\n\n\t// tftd mode: use a colour lookup table instead of simple palette inversion for our \"pressed\" state\n\tif (_tftdMode)\n\t{\n\t\t// this is our colour lookup table\n\t\tconst int colorFrom[] = {1, 2, 3, 4,  7,  8, 31, 47, 153, 156, 159};\n\t\tconst int colorTo[]   = {2, 3, 4, 5, 11, 10,  2,  2,  96,   9,  97};\n\n\t\tfor (int x = 0, y = 0; x < getWidth() && y < getHeight();)\n\t\t{\n\t\t\tUint8 pixel = getPixel(x, y);\n\t\t\tfor (size_t i = 0; i != std::size(colorFrom); ++i)\n\t\t\t{\n\t\t\t\tif (pixel == colorFrom[i])\n\t\t\t\t{\n\t\t\t\t\tpixel = colorTo[i];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\t_altSurface->setPixelIterative(&x, &y, pixel);\n\t\t}\n\t}\n\telse\n\t{\n\t\tfor (int x = 0, y = 0; x < getWidth() && y < getHeight();)\n\t\t{\n\t\t\tUint8 pixel = getPixel(x, y);\n\t\t\tif (pixel > 0)\n\t\t\t{\n\t\t\t\t_altSurface->setPixelIterative(&x, &y, pixel + 2 * ((int)_color + 3 - (int)pixel));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_altSurface->setPixelIterative(&x, &y, 0);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Unlock the surface\n\t_altSurface->unlock();\n}\n\n/**\n * Blits this surface or the alternate surface onto another one,\n * depending on whether the button is \"pressed\" or not.\n * @param surface Pointer to surface to blit onto.\n */\nvoid BattlescapeButton::blit(SDL_Surface *surface)\n{\n\tif (_inverted)\n\t{\n\t\t_altSurface->blit(surface);\n\t}\n\telse\n\t{\n\t\tSurface::blit(surface);\n\t}\n}\n\n/**\n * Changes the position of the surface in the X axis.\n * @param x X position in pixels.\n */\nvoid BattlescapeButton::setX(int x)\n{\n\tSurface::setX(x);\n\tif (_altSurface)\n\t{\n\t\t_altSurface->setX(x);\n\t}\n}\n\n/**\n * Changes the position of the surface in the Y axis.\n * @param y Y position in pixels.\n */\nvoid BattlescapeButton::setY(int y)\n{\n\tSurface::setY(y);\n\tif (_altSurface)\n\t{\n\t\t_altSurface->setY(y);\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Interface/BattlescapeButton.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/InteractiveSurface.h\"\n\nnamespace OpenXcom\n{\n\nenum InversionType {INVERT_NONE, INVERT_CLICK, INVERT_TOGGLE};\n\n/**\n * Regular image that works like a button.\n * Unlike the TextButton, this button doesn't draw\n * anything on its own. It takes an existing graphic and\n * treats it as a button, inverting colors when necessary.\n * This is necessary for special buttons like in the Geoscape.\n */\nclass BattlescapeButton : public InteractiveSurface\n{\nprotected:\n\tUint8 _color;\n\tBattlescapeButton **_group;\n\tbool _inverted;\n\tInversionType _toggleMode;\n\tSurface *_altSurface;\npublic:\n\t/// Creates a new image button with the specified size and position.\n\tBattlescapeButton(int width, int height, int x = 0, int y = 0);\n\t/// Cleans up the image button.\n\tvirtual ~BattlescapeButton();\n\t/// Sets the image button's color.\n\tvoid setColor(Uint8 color) override;\n\t/// Gets the image button's color.\n\tUint8 getColor() const;\n\t/// Sets the image button's group.\n\tvoid setGroup(BattlescapeButton **group);\n\t/// Special handling for mouse presses.\n\tvoid mousePress(Action *action, State *state) override;\n\t/// Special handling for mouse releases.\n\tvoid mouseRelease(Action *action, State *state) override;\n\t/// Invert a button explicitly either ON or OFF.\n\tvoid toggle(bool invert);\n\t/// Allows this button to be toggled on/off with a click.\n\tvoid allowToggleInversion();\n\t/// Allows this button to be toggled on when clicked, and off when released.\n\tvoid allowClickInversion();\n\t/// Sets up the \"pressed\" surface.\n\tvoid initSurfaces(Surface* custom = nullptr);\n\t/// Blits this surface onto another one.\n\tvoid blit(SDL_Surface *surface) override;\n\t/// Alters both versions of the button's X pos.\n\tvoid setX(int x) override;\n\t/// Alters both versions of the button's Y pos.\n\tvoid setY(int y) override;\n\n};\n\n}\n"
  },
  {
    "path": "src/Interface/ComboBox.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ComboBox.h\"\n#include <algorithm>\n#include \"TextButton.h\"\n#include \"Window.h\"\n#include \"TextList.h\"\n#include \"../Engine/State.h\"\n#include \"../Engine/Language.h\"\n#include \"../Engine/Font.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Screen.h\"\n\nnamespace OpenXcom\n{\n\nconst int ComboBox::HORIZONTAL_MARGIN = 2;\nconst int ComboBox::VERTICAL_MARGIN = 3;\nconst int ComboBox::MAX_ITEMS = 10;\nconst int ComboBox::BUTTON_WIDTH = 14;\nconst int ComboBox::TEXT_HEIGHT = 8;\n\nstatic int getPopupWindowY(int buttonHeight, int buttonY, int popupHeight, bool popupAboveButton)\n{\n\tint belowButtonY = buttonY + buttonHeight;\n\tif (popupAboveButton)\n\t{\n\t\t// used when popup list won't fit below the button; display it above\n\t\treturn buttonY - popupHeight;\n\t}\n\treturn belowButtonY;\n}\n\n/**\n * Sets up a combobox with the specified size and position.\n * @param state Pointer to state the combobox belongs to.\n * @param width Width in pixels.\n * @param height Height in pixels.\n * @param x X position in pixels.\n * @param y Y position in pixels.\n */\nComboBox::ComboBox(State *state, int width, int height, int x, int y, bool popupAboveButton) : InteractiveSurface(width, height, x, y), _change(0), _sel(0), _state(state), _lang(0), _toggled(false), _popupAboveButton(popupAboveButton)\n{\n\t_button = new TextButton(width, height, x, y);\n\t_button->setComboBox(this);\n\n\t_arrow = new Surface(11, 8, x + width - BUTTON_WIDTH, y + 4);\n\n\tint popupHeight = MAX_ITEMS * TEXT_HEIGHT + VERTICAL_MARGIN * 2;\n\tint popupY = getPopupWindowY(height, y, popupHeight, popupAboveButton);\n\t_window = new Window(state, width, popupHeight, x, popupY);\n\t_window->setThinBorder();\n\n\t_list = new TextList(width - HORIZONTAL_MARGIN * 2 - BUTTON_WIDTH + 1,\n\t\t\t\t\t\tpopupHeight - (VERTICAL_MARGIN * 2 + 2),\n\t\t\t\t\t\tx + HORIZONTAL_MARGIN,\n\t\t\t\t\t\tpopupY + VERTICAL_MARGIN);\n\t_list->setComboBox(this);\n\t_list->setColumns(1, _list->getWidth());\n\t_list->setSelectable(true);\n\t_list->setBackground(_window);\n\t_list->setAlign(ALIGN_CENTER);\n\t_list->setScrolling(true, 0);\n\n\ttoggle(true, false);\n}\n\n/**\n * Deletes all the stuff contained in the list.\n */\nComboBox::~ComboBox()\n{\n\tdelete _button;\n\tdelete _arrow;\n\tdelete _window;\n\tdelete _list;\n}\n\n/**\n * Changes the position of the surface in the X axis.\n * @param x X position in pixels.\n */\nvoid ComboBox::setX(int x)\n{\n\tSurface::setX(x);\n\t_button->setX(x);\n\t_arrow->setX(x + getWidth() - BUTTON_WIDTH);\n\t_window->setX(x);\n\t_list->setX(x + HORIZONTAL_MARGIN);\n}\n\n/**\n * Changes the position of the surface in the Y axis.\n * @param y Y position in pixels.\n */\nvoid ComboBox::setY(int y)\n{\n\tSurface::setY(y);\n\t_button->setY(y);\n\t_arrow->setY(y + 4);\n\n\tint popupHeight = _window->getHeight();\n\tint popupY = getPopupWindowY(getHeight(), y, popupHeight, _popupAboveButton);\n\t_window->setY(popupY);\n\t_list->setY(popupY + VERTICAL_MARGIN);\n}\n\n/**\n * Replaces a certain amount of colors in the palette of all\n * the text contained in the list.\n * @param colors Pointer to the set of colors.\n * @param firstcolor Offset of the first color to replace.\n * @param ncolors Amount of colors to replace.\n */\nvoid ComboBox::setPalette(const SDL_Color *colors, int firstcolor, int ncolors)\n{\n\tSurface::setPalette(colors, firstcolor, ncolors);\n\t_button->setPalette(colors, firstcolor, ncolors);\n\t_arrow->setPalette(colors, firstcolor, ncolors);\n\t_window->setPalette(colors, firstcolor, ncolors);\n\t_list->setPalette(colors, firstcolor, ncolors);\n}\n\n/**\n * Changes the resources for the text in the combo box.\n * @param big Pointer to large-size font.\n * @param small Pointer to small-size font.\n * @param lang Pointer to current language.\n */\nvoid ComboBox::initText(Font *big, Font *small, Language *lang)\n{\n\t_lang = lang;\n\t_button->initText(big, small, lang);\n\t_list->initText(big, small, lang);\n}\n\n/**\n * Changes the surface used to draw the background of the combo box.\n * @param bg New background.\n */\nvoid ComboBox::setBackground(Surface *bg)\n{\n\t_window->setBackground(bg);\n}\n\n/**\n * Changes the color used to draw the combo box.\n * @param color Color value.\n */\nvoid ComboBox::setColor(Uint8 color)\n{\n\t_color = color;\n\tdrawArrow();\n\t_button->setColor(_color);\n\t_window->setColor(_color);\n\t_list->setColor(_color);\n}\n\n/**\n * Returns the color used to draw the combo box.\n * @return Color value.\n */\nUint8 ComboBox::getColor() const\n{\n\treturn _color;\n}\n\n/**\n * Draws the arrow used to indicate the combo box.\n */\nvoid ComboBox::drawArrow()\n{\n\t_arrow->clear();\n\n\tSDL_Rect square;\n\tint color = _color + 1;\n\tif (color == 256)\n\t\tcolor++;\n\n\t// Draw arrow triangle 1\n\tsquare.x = 1;\n\tsquare.y = 2;\n\tsquare.w = 9;\n\tsquare.h = 1;\n\n\tfor (; square.w > 1; square.w -= 2)\n\t{\n\t\t_arrow->drawRect(&square, color + 2);\n\t\tsquare.x++;\n\t\tsquare.y++;\n\t}\n\t_arrow->drawRect(&square, color + 2);\n\n\t// Draw arrow triangle 2\n\tsquare.x = 2;\n\tsquare.y = 2;\n\tsquare.w = 7;\n\tsquare.h = 1;\n\n\tfor (; square.w > 1; square.w -= 2)\n\t{\n\t\t_arrow->drawRect(&square, color);\n\t\tsquare.x++;\n\t\tsquare.y++;\n\t}\n\t_arrow->drawRect(&square, color);\n}\n\n/**\n * Enables/disables high contrast color. Mostly used for\n * Battlescape UI.\n * @param contrast High contrast setting.\n */\nvoid ComboBox::setHighContrast(bool contrast)\n{\n\t_button->setHighContrast(contrast);\n\t_window->setHighContrast(contrast);\n\t_list->setHighContrast(contrast);\n}\n\n/**\n * Changes the color of the arrow buttons in the list.\n * @param color Color value.\n */\nvoid ComboBox::setArrowColor(Uint8 color)\n{\n\t_list->setArrowColor(color);\n}\n\n/**\n * Returns the currently selected option.\n * @return Selected row.\n */\nsize_t ComboBox::getSelected() const\n{\n\treturn _sel;\n}\n\nsize_t ComboBox::getHoveredListIdx() const\n{\n\tsize_t ret = -1;\n\tif (_list->getVisible())\n\t{\n\t\tret = _list->getSelectedRow();\n\t}\n\tif ((size_t)-1 == ret)\n\t{\n\t\tret = _sel;\n\t}\n\treturn ret;\n}\n\n/**\n * sets the button text independent of the currently selected option.\n * @param text the text to display\n */\nvoid ComboBox::setText(const std::string &text)\n{\n\t_button->setText(text);\n}\n\n/**\n * Changes the currently selected option.\n * @param sel Selected row.\n */\nvoid ComboBox::setSelected(size_t sel)\n{\n\t_sel = sel;\n\tif (_sel < _list->getTexts())\n\t{\n\t\t_button->setText(_list->getCellText(_sel, 0));\n\t}\n}\n\n/**\n * Updates the size of the dropdown list based on\n * the number of options available.\n * @param options Number of options.\n */\nvoid ComboBox::setDropdown(int options)\n{\n\tint items = std::min(options, MAX_ITEMS);\n\tint h = _button->getFont()->getHeight() + _button->getFont()->getSpacing();\n\tint dy = (Options::baseYResolution - 200) / 2;\n\twhile (_window->getY() + items * h + VERTICAL_MARGIN * 2 > 200 + dy)\n\t{\n\t\titems--;\n\t}\n\n\tint popupHeight = items * h + VERTICAL_MARGIN * 2;\n\tint popupY = getPopupWindowY(getHeight(), getY(), popupHeight, _popupAboveButton);\n\t_window->setY(popupY);\n\t_window->setHeight(popupHeight);\n\t_list->setY(popupY + VERTICAL_MARGIN);\n\t_list->setHeight(items * h);\n}\n\n/**\n * Changes the list of available options to choose from.\n * @param options List of strings.\n * @param translate True for a list of string IDs, false for a list of raw strings.\n */\nvoid ComboBox::setOptions(const std::vector<std::string> &options, bool translate)\n{\n\tsetDropdown(options.size());\n\t_list->clearList();\n\tfor (const auto& option : options)\n\t{\n\t\tif (translate)\n\t\t\t_list->addRow(1, _lang->getString(option).c_str());\n\t\telse\n\t\t\t_list->addRow(1, option.c_str());\n\t}\n\tsetSelected(_sel);\n}\n\n/**\n * Blits the combo box components.\n * @param surface Pointer to surface to blit onto.\n */\nvoid ComboBox::blit(SDL_Surface *surface)\n{\n\tSurface::blit(surface);\n\t_list->invalidate();\n\tif (_visible && !_hidden)\n\t{\n\t\t_button->blit(surface);\n\t\t_arrow->blit(surface);\n\t\t_window->blit(surface);\n\t\t_list->blit(surface);\n\t}\n}\n\n/**\n * Passes events to internal components.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid ComboBox::handle(Action *action, State *state)\n{\n\tif (!_visible || _hidden)\n\t\treturn;\n\n\t_button->handle(action, state);\n\t_list->handle(action, state);\n\tInteractiveSurface::handle(action, state);\n\tint topY = std::min(getY(), _window->getY());\n\tif (_window->getVisible() && action->getDetails()->type == SDL_MOUSEBUTTONDOWN &&\n\t\t(action->getAbsoluteXMouse() < getX() || action->getAbsoluteXMouse() >= getX() + getWidth() ||\n\t\t action->getAbsoluteYMouse() < topY || action->getAbsoluteYMouse() >= topY + getHeight() + _window->getHeight()))\n\t{\n\t\ttoggle(false, false);\n\t}\n\tif (_toggled)\n\t{\n\t\tif (_change)\n\t\t{\n\t\t\t(state->*_change)(action);\n\t\t}\n\t\t_toggled = false;\n\t}\n}\n\n/**\n * Passes ticks to arrow buttons.\n */\nvoid ComboBox::think()\n{\n\t_button->think();\n\t_arrow->think();\n\t_window->think();\n\t_list->think();\n\tInteractiveSurface::think();\n}\n\n/**\n * Opens/closes the combo box list.\n * @param first Is it the initialization toggle?\n * @param listClick Should the change handler be triggered? (Yes = list click; No = button click or click anywhere else)\n */\nvoid ComboBox::toggle(bool first, bool listClick)\n{\n\t_window->setVisible(!_window->getVisible());\n\t_list->setVisible(!_list->getVisible());\n\t_state->setModal(_window->getVisible() ? this : 0);\n\tif (!first && !_window->getVisible())\n\t{\n\t\t_toggled = listClick;\n\t}\n\tif (_list->getVisible())\n\t{\n\t\tif (_sel < _list->getVisibleRows()/2 || _sel == (size_t)-1)\n\t\t{\n\t\t\t_list->scrollTo(0);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_list->scrollTo(_sel - _list->getVisibleRows()/2);\n\t\t}\n\t}\n}\n\n/**\n * Sets a function to be called every time the slider's value changes.\n * @param handler Action handler.\n */\nvoid ComboBox::onChange(ActionHandler handler)\n{\n\t_change = handler;\n}\n\n/**\n * Sets a function to be called every time the mouse moves in to the listbox surface.\n * @param handler Action handler.\n */\nvoid ComboBox::onListMouseIn(ActionHandler handler)\n{\n\t_list->onMouseIn(handler);\n}\n\n/**\n * Sets a function to be called every time the mouse moves out of the listbox surface.\n * @param handler Action handler.\n */\nvoid ComboBox::onListMouseOut(ActionHandler handler)\n{\n\t_list->onMouseOut(handler);\n}\n\n/**\n * Sets a function to be called every time the mouse moves over the listbox surface.\n * @param handler Action handler.\n */\nvoid ComboBox::onListMouseOver(ActionHandler handler)\n{\n\t_list->onMouseOver(handler);\n}\n\n}\n"
  },
  {
    "path": "src/Interface/ComboBox.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/InteractiveSurface.h\"\n#include <vector>\n#include <string>\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass TextList;\nclass Window;\nclass Language;\n\n/**\n * Text button with a list dropdown when pressed.\n * Allows selection from multiple available options.\n */\nclass ComboBox : public InteractiveSurface\n{\nprivate:\n\tstatic const int HORIZONTAL_MARGIN;\n\tstatic const int VERTICAL_MARGIN;\n\tstatic const int MAX_ITEMS;\n\tstatic const int BUTTON_WIDTH;\n\tstatic const int TEXT_HEIGHT;\n\n\tTextButton *_button;\n\tSurface *_arrow;\n\tWindow *_window;\n\tTextList *_list;\n\n\tActionHandler _change;\n\tsize_t _sel;\n\tState *_state;\n\tLanguage *_lang;\n\tUint8 _color;\n\tbool _toggled;\n\tbool _popupAboveButton;\n\n\tvoid drawArrow();\n\tvoid setDropdown(int options);\npublic:\n\t/// Creates a combo box with the specified size and position.\n\tComboBox(State *state, int width, int height, int x = 0, int y = 0, bool popupAboveButton = false);\n\t/// Cleans up the combo box.\n\t~ComboBox();\n\t/// Sets the X position of the surface.\n\tvoid setX(int x) override;\n\t/// Sets the Y position of the surface.\n\tvoid setY(int y) override;\n\t/// Sets the palette of the text list.\n\tvoid setPalette(const SDL_Color *colors, int firstcolor = 0, int ncolors = 256) override;\n\t/// Initializes the resources for the text list.\n\tvoid initText(Font *big, Font *small, Language *lang) override;\n\t/// Sets the background surface.\n\tvoid setBackground(Surface *bg);\n\t/// Sets the border color.\n\tvoid setColor(Uint8 color) override;\n\t/// Gets the border color.\n\tUint8 getColor() const;\n\t/// Sets the high contrast color setting.\n\tvoid setHighContrast(bool contrast) override;\n\t/// Sets the arrow color of the text list.\n\tvoid setArrowColor(Uint8 color);\n\t/// Gets the selected option in the list.\n\tsize_t getSelected() const;\n\t/// Gets the item that is currently hovered over in the popup list, or the current\n\t/// selected item if no item is hovered over.\n\tsize_t getHoveredListIdx() const;\n\t/// Sets the button text without changing the selected option\n\tvoid setText(const std::string &text);\n\t/// Sets the selected option in the list.\n\tvoid setSelected(size_t sel);\n\t/// Sets the list of options.\n\tvoid setOptions(const std::vector<std::string> &options, bool translate = false);\n\t/// Blits the combo box onto another surface.\n\tvoid blit(SDL_Surface *surface) override;\n\t/// Thinks arrow buttons.\n\tvoid think() override;\n\t/// Handle arrow buttons.\n\tvoid handle(Action *action, State *state) override;\n\t/// Toggles the combo box state.\n\tvoid toggle(bool first, bool listClick);\n\t/// Hooks an action handler to when the slider changes.\n\tvoid onChange(ActionHandler handler);\n\t/// Hooks an action handler to moving the mouse in to the listbox when it is visible.\n\tvoid onListMouseIn(ActionHandler handler);\n\t/// Hooks an action handler to moving the mouse out of the listbox when it is visible.\n\tvoid onListMouseOut(ActionHandler handler);\n\t/// Hooks an action handler to moving the mouse over the listbox when it is visible.\n\tvoid onListMouseOver(ActionHandler handler);\n};\n\n}\n"
  },
  {
    "path": "src/Interface/Cursor.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Cursor.h\"\n#include <cmath>\n#include <SDL.h>\n#include \"../Engine/Action.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Sets up a cursor with the specified size and position\n * and hides the system cursor.\n * @note The size and position don't really matter since\n * it's a 9x13 shape, they're just there for inheritance.\n * @param width Width in pixels.\n * @param height Height in pixels.\n * @param x X position in pixels.\n * @param y Y position in pixels.\n */\nCursor::Cursor(int width, int height, int x, int y) : Surface(width, height, x, y), _color(0)\n{\n}\n\n/**\n *\n */\nCursor::~Cursor()\n{\n}\n\n/**\n * Automatically updates the cursor position\n * when the mouse moves.\n * @param action Pointer to an action.\n */\nvoid Cursor::handle(Action *action)\n{\n\tif (action->getDetails()->type == SDL_MOUSEMOTION)\n\t{\n\t\tsetX((int)floor((action->getDetails()->motion.x - action->getLeftBlackBand()) / action->getXScale()));\n\t\tsetY((int)floor((action->getDetails()->motion.y - action->getTopBlackBand()) / action->getYScale()));\n\t}\n}\n\n/**\n * Changes the cursor's base color.\n * @param color Color value.\n */\nvoid Cursor::setColor(Uint8 color)\n{\n\t_color = color;\n\t_redraw = true;\n}\n\n/**\n * Returns the cursor's base color.\n * @return Color value.\n */\nUint8 Cursor::getColor() const\n{\n\treturn _color;\n}\n\n/**\n * Draws a pointer-shaped cursor graphic.\n */\nvoid Cursor::draw()\n{\n\tSurface::draw();\n\tUint8 color = _color;\n\tint x1 = 0, y1 = 0, x2 = getWidth() - 1, y2 = getHeight() - 1;\n\n\tlock();\n\tfor (int i = 0; i < 4; ++i)\n\t{\n\t\tdrawLine(x1, y1, x1, y2, color);\n\t\tdrawLine(x1, y1, x2, getWidth() - 1, color);\n\t\tx1++;\n\t\ty1 += 2;\n\t\ty2--;\n\t\tx2--;\n\t\tcolor++;\n\t}\n\tthis->setPixel(4, 8, --color);\n\tunlock();\n}\n\n}\n"
  },
  {
    "path": "src/Interface/Cursor.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/Surface.h\"\n\nnamespace OpenXcom\n{\n\nclass Action;\n\n/**\n * Mouse cursor that replaces the system cursor.\n * Drawn as a shaded triangle-like shape, automatically\n * matches the mouse coordinates.\n */\nclass Cursor : public Surface\n{\nprivate:\n\tUint8 _color;\n\npublic:\n\t/// Creates a new cursor with the specified size and position.\n\tCursor(int width, int height, int x = 0, int y = 0);\n\t/// Cleans up the cursor.\n\t~Cursor();\n\t/// Handles mouse events.\n\tvoid handle(Action *action);\n\t/// Sets the cursor's color.\n\tvoid setColor(Uint8 color) override;\n\t/// Gets the cursor's color.\n\tUint8 getColor() const;\n\t/// Draws the cursor.\n\tvoid draw() override;\n};\n\n}\n"
  },
  {
    "path": "src/Interface/FpsCounter.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"FpsCounter.h\"\n#include <cmath>\n#include \"../Engine/Action.h\"\n#include \"../Engine/Timer.h\"\n#include \"../Engine/Options.h\"\n#include \"NumberText.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Creates a FPS counter of the specified size.\n * @param width Width in pixels.\n * @param height Height in pixels.\n * @param x X position in pixels.\n * @param y Y position in pixels.\n */\nFpsCounter::FpsCounter(int width, int height, int x, int y) : Surface(width, height, x, y), _frames(0)\n{\n\t_visible = Options::fpsCounter;\n\n\t_timer = new Timer(1000);\n\t_timer->onTimer((SurfaceHandler)&FpsCounter::update);\n\t_timer->start();\n\n\t_text = new NumberText(width, height, x, y);\n}\n\n/**\n * Deletes FPS counter content.\n */\nFpsCounter::~FpsCounter()\n{\n\tdelete _text;\n\tdelete _timer;\n}\n\n/**\n * Replaces a certain amount of colors in the FPS counter palette.\n * @param colors Pointer to the set of colors.\n * @param firstcolor Offset of the first color to replace.\n * @param ncolors Amount of colors to replace.\n */\nvoid FpsCounter::setPalette(const SDL_Color *colors, int firstcolor, int ncolors)\n{\n\tSurface::setPalette(colors, firstcolor, ncolors);\n\t_text->setPalette(colors, firstcolor, ncolors);\n}\n\n/**\n * Sets the text color of the counter.\n * @param color The color to set.\n */\nvoid FpsCounter::setColor(Uint8 color)\n{\n\t_text->setColor(color);\n}\n\n/**\n * Shows / hides the FPS counter.\n * @param action Pointer to an action.\n */\nvoid FpsCounter::handle(Action *action)\n{\n\tif (action->getDetails()->type == SDL_KEYDOWN && action->getDetails()->key.keysym.sym == Options::keyFps)\n\t{\n\t\t_visible = !_visible;\n\t\tOptions::fpsCounter = _visible;\n\t}\n}\n\n/**\n * Advances frame counter.\n */\nvoid FpsCounter::think()\n{\n\t_timer->think(0, this);\n}\n\n/**\n * Updates the amount of Frames per Second.\n */\nvoid FpsCounter::update()\n{\n\tint fps = (int)floor((double)_frames / _timer->getTime() * 1000);\n\t_text->setValue(fps);\n\t_frames = 0;\n\t_redraw = true;\n}\n\n/**\n * Draws the FPS counter.\n */\nvoid FpsCounter::draw()\n{\n\tSurface::draw();\n\t_text->blit(this->getSurface());\n}\n\nvoid FpsCounter::addFrame()\n{\n\t_frames++;\n}\n\n}\n"
  },
  {
    "path": "src/Interface/FpsCounter.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/Surface.h\"\n\nnamespace OpenXcom\n{\n\nclass NumberText;\nclass Timer;\nclass Action;\n\n/**\n * Counts the amount of frames each second\n * and displays them in a NumberText surface.\n */\nclass FpsCounter : public Surface\n{\nprivate:\n\tNumberText *_text;\n\tTimer *_timer;\n\tint _frames;\npublic:\n\t/// Creates a new FPS counter linked to a game.\n\tFpsCounter(int width, int height, int x, int y);\n\t/// Cleans up all the FPS counter resources.\n\t~FpsCounter();\n\t/// Sets the FPS counter's palette.\n\tvoid setPalette(const SDL_Color *colors, int firstcolor = 0, int ncolors = 256) override;\n\t/// Sets the FpsCounter's color.\n\tvoid setColor(Uint8 color) override;\n\t/// Handles keyboard events.\n\tvoid handle(Action *action);\n\t/// Advances frame counter.\n\tvoid think() override;\n\t// Updates FPS counter.\n\tvoid update();\n\t/// Draws the FPS counter.\n\tvoid draw() override;\n\tvoid addFrame();\n};\n\n}\n"
  },
  {
    "path": "src/Interface/Frame.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Frame.h\"\n#include \"../Engine/Palette.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Sets up a blank frame with the specified size and position.\n * @param width Width in pixels.\n * @param height Height in pixels.\n * @param x X position in pixels.\n * @param y Y position in pixels.\n */\nFrame::Frame(int width, int height, int x, int y) : Surface(width, height, x, y), _color(0), _bg(0), _thickness(5), _contrast(false)\n{\n}\n\n/**\n *\n */\nFrame::~Frame()\n{\n}\n\n/**\n * Changes the color used to draw the shaded border.\n * @param color Color value.\n */\nvoid Frame::setColor(Uint8 color)\n{\n\t_color = color;\n\t_redraw = true;\n}\n\n/**\n * Changes the color used to draw the shaded border.\n * only really to be used in conjunction with the State add()\n * function as a convenience wrapper to avoid ugly hacks on that end\n * better to have them here!\n * @param color Color value.\n */\nvoid Frame::setBorderColor(Uint8 color)\n{\n\tsetColor(color);\n}\n\n/**\n * Returns the color used to draw the shaded border.\n * @return Color value.\n */\nUint8 Frame::getColor() const\n{\n\treturn _color;\n}\n\n/**\n * Changes the color used to draw the background.\n * @param bg Color value.\n */\nvoid Frame::setSecondaryColor(Uint8 bg)\n{\n\t_bg = bg;\n\t_redraw = true;\n}\n\n/**\n * Returns the color used to draw the background.\n * @return Color value.\n */\nUint8 Frame::getSecondaryColor() const\n{\n\treturn _bg;\n}\n\n/**\n * Enables/disables high contrast color. Mostly used for\n * Battlescape UI.\n * @param contrast High contrast setting.\n */\nvoid Frame::setHighContrast(bool contrast)\n{\n\t_contrast = contrast;\n\t_redraw = true;\n}\n\n/**\n * Changes the thickness of the border to draw.\n * @param thickness Thickness in pixels.\n */\nvoid Frame::setThickness(int thickness)\n{\n\t_thickness = thickness;\n\t_redraw = true;\n}\n\n/**\n * Draws the bordered frame with a graphic background.\n * The background never moves with the frame, it's\n * always aligned to the top-left corner of the screen\n * and cropped to fit the inside area.\n */\nvoid Frame::draw()\n{\n\tSurface::draw();\n\tSDL_Rect square;\n\n\tsquare.x = 0;\n\tsquare.w = getWidth();\n\tsquare.y = 0;\n\tsquare.h = getHeight();\n\n\tint mul = 1;\n\tif (_contrast)\n\t{\n\t\tmul = 2;\n\t}\n\n\t// _color denotes our middle line color, so we start (half the thickness times the multiplier) steps darker and build up\n\tUint8 color = _color + ((1 + _thickness) * mul) / 2;\n\t// we want the darkest version of this colour to outline any thick borders\n\tUint8 darkest = Palette::blockOffset(_color / 16) + 15;\n\tfor (int i = 0; i < _thickness; ++i)\n\t{\n\t\tif (_thickness > 5 && (!i || i == _thickness -1))\n\t\t\tdrawRect(&square, darkest);\n\t\telse\n\t\t\tdrawRect(&square, color);\n\t\tif (i < _thickness / 2)\n\t\t\tcolor -= 1 * mul;\n\t\telse\n\t\t\tcolor += 1 * mul;\n\t\tsquare.x++;\n\t\tsquare.y++;\n\t\tif (square.w >= 2)\n\t\t\tsquare.w -= 2;\n\t\telse\n\t\t\tsquare.w = 1;\n\n\t\tif (square.h >= 2)\n\t\t\tsquare.h -= 2;\n\t\telse\n\t\t\tsquare.h = 1;\n\t}\n\tdrawRect(&square, _bg);\n}\n\n}\n"
  },
  {
    "path": "src/Interface/Frame.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/Surface.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Fancy frame border thing used for windows and other elements.\n */\nclass Frame : public Surface\n{\nprivate:\n\tUint8 _color, _bg;\n\tint _thickness;\n\tbool _contrast;\npublic:\n\t/// Creates a new frame with the specified size and position.\n\tFrame(int width, int height, int x = 0, int y = 0);\n\t/// Cleans up the frame.\n\t~Frame();\n\t/// Sets the border color.\n\tvoid setColor(Uint8 color) override;\n\t/// Gets the border color.\n\tUint8 getColor() const;\n\tvoid setBorderColor(Uint8 color) override;\n\t/// Sets the background color.\n\tvoid setSecondaryColor(Uint8 bg) override;\n\t/// Gets the background color.\n\tUint8 getSecondaryColor() const;\n\t/// Sets the high contrast color setting.\n\tvoid setHighContrast(bool contrast) override;\n\t/// Sets the border thickness.\n\tvoid setThickness(int thickness);\n\t/// Draws the frame.\n\tvoid draw() override;\n};\n\n}\n"
  },
  {
    "path": "src/Interface/ImageButton.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ImageButton.h\"\n#include \"../Engine/Action.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Sets up an image button with the specified size and position.\n * @param width Width in pixels.\n * @param height Height in pixels.\n * @param x X position in pixels.\n * @param y Y position in pixels.\n */\nImageButton::ImageButton(int width, int height, int x, int y) : InteractiveSurface(width, height, x, y), _color(0), _group(0), _inverted(false)\n{\n}\n\n/**\n *\n */\nImageButton::~ImageButton()\n{\n\n}\n\n/**\n * Changes the color for the image button.\n * @param color Color value.\n */\nvoid ImageButton::setColor(Uint8 color)\n{\n\t_color = color;\n}\n\n/**\n * Returns the color for the image button.\n * @return Color value.\n */\nUint8 ImageButton::getColor() const\n{\n\treturn _color;\n}\n\n/**\n * Changes the button group this image button belongs to.\n * @param group Pointer to the pressed button pointer in the group.\n * Null makes it a regular button.\n */\nvoid ImageButton::setGroup(ImageButton **group)\n{\n\t_group = group;\n\tif (_group != 0 && *_group == this)\n\t\tinvert(_color + 3);\n}\n\n/**\n * Sets the button as the pressed button if it's part of a group,\n * and inverts the colors when pressed.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid ImageButton::mousePress(Action *action, State *state)\n{\n\tif (_group != 0)\n\t{\n\t\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT)\n\t\t{\n\t\t\t(*_group)->invert((*_group)->getColor() + 3);\n\t\t\t*_group = this;\n\t\t\tinvert(_color + 3);\n\t\t}\n\t}\n\telse if (!_inverted && isButtonPressed() && isButtonHandled(action->getDetails()->button.button))\n\t{\n\t\t_inverted = true;\n\t\tinvert(_color + 3);\n\t}\n\tInteractiveSurface::mousePress(action, state);\n}\n\n/*\n * Sets the button as the released button if it's part of a group.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid ImageButton::mouseRelease(Action *action, State *state)\n{\n\tif (_inverted && isButtonHandled(action->getDetails()->button.button))\n\t{\n\t\t_inverted = false;\n\t\tinvert(_color + 3);\n\t}\n\tInteractiveSurface::mouseRelease(action, state);\n}\n\n/**\n * Invert a button explicitly either ON or OFF and keep track of the state using our internal variables.\n * @param press Set this button as pressed.\n */\nvoid ImageButton::toggle(bool press)\n{\n\tif (_inverted != press)\n\t{\n\t\t_inverted = !_inverted;\n\t\tinvert(_color + 3);\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Interface/ImageButton.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/InteractiveSurface.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Regular image that works like a button.\n * Unlike the TextButton, this button doesn't draw\n * anything on its own. It takes an existing graphic and\n * treats it as a button, inverting colors when necessary.\n * This is necessary for special buttons like in the Geoscape.\n */\nclass ImageButton : public InteractiveSurface\n{\nprotected:\n\tUint8 _color;\n\tImageButton **_group;\n\tbool _inverted;\npublic:\n\t/// Creates a new image button with the specified size and position.\n\tImageButton(int width, int height, int x = 0, int y = 0);\n\t/// Cleans up the image button.\n\tvirtual ~ImageButton();\n\t/// Sets the image button's color.\n\tvoid setColor(Uint8 color) override;\n\t/// Gets the image button's color.\n\tUint8 getColor() const;\n\t/// Sets the image button's group.\n\tvoid setGroup(ImageButton **group);\n\t/// Special handling for mouse presses.\n\tvoid mousePress(Action *action, State *state) override;\n\t/// Special handling for mouse releases.\n\tvoid mouseRelease(Action *action, State *state) override;\n\t/// Invert a button explicitly either ON or OFF.\n\tvoid toggle(bool invert);\n};\n\n}\n"
  },
  {
    "path": "src/Interface/NumberText.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"NumberText.h\"\n#include <sstream>\n#include <string>\n\nnamespace OpenXcom\n{\n\n/**\n * Sets up a blank number text.\n * @param width Width in pixels.\n * @param height Height in pixels.\n * @param x X position in pixels.\n * @param y Y position in pixels.\n */\nNumberText::NumberText(int width, int height, int x, int y) : Surface(width, height, x, y), _value(0), _bordered(false), _color(0)\n{\n\t_chars[0] = new Surface(3, 5);\n\t_chars[0]->lock();\n\t_chars[0]->setPixel(0, 0, 1);\n\t_chars[0]->setPixel(1, 0, 1);\n\t_chars[0]->setPixel(2, 0, 1);\n\t_chars[0]->setPixel(0, 1, 1);\n\t_chars[0]->setPixel(0, 2, 1);\n\t_chars[0]->setPixel(0, 3, 1);\n\t_chars[0]->setPixel(2, 1, 1);\n\t_chars[0]->setPixel(2, 2, 1);\n\t_chars[0]->setPixel(2, 3, 1);\n\t_chars[0]->setPixel(0, 4, 1);\n\t_chars[0]->setPixel(1, 4, 1);\n\t_chars[0]->setPixel(2, 4, 1);\n\t_chars[0]->unlock();\n\n\t_chars[1] = new Surface(3, 5);\n\t_chars[1]->lock();\n\t_chars[1]->setPixel(1, 0, 1);\n\t_chars[1]->setPixel(1, 1, 1);\n\t_chars[1]->setPixel(1, 2, 1);\n\t_chars[1]->setPixel(1, 3, 1);\n\t_chars[1]->setPixel(0, 4, 1);\n\t_chars[1]->setPixel(1, 4, 1);\n\t_chars[1]->setPixel(2, 4, 1);\n\t_chars[1]->setPixel(0, 1, 1);\n\t_chars[1]->unlock();\n\n\t_chars[2] = new Surface(3, 5);\n\t_chars[2]->lock();\n\t_chars[2]->setPixel(0, 0, 1);\n\t_chars[2]->setPixel(1, 0, 1);\n\t_chars[2]->setPixel(2, 0, 1);\n\t_chars[2]->setPixel(2, 1, 1);\n\t_chars[2]->setPixel(0, 2, 1);\n\t_chars[2]->setPixel(1, 2, 1);\n\t_chars[2]->setPixel(2, 2, 1);\n\t_chars[2]->setPixel(0, 3, 1);\n\t_chars[2]->setPixel(0, 4, 1);\n\t_chars[2]->setPixel(1, 4, 1);\n\t_chars[2]->setPixel(2, 4, 1);\n\t_chars[2]->unlock();\n\n\t_chars[3] = new Surface(3, 5);\n\t_chars[3]->lock();\n\t_chars[3]->setPixel(0, 0, 1);\n\t_chars[3]->setPixel(1, 0, 1);\n\t_chars[3]->setPixel(2, 0, 1);\n\t_chars[3]->setPixel(2, 1, 1);\n\t_chars[3]->setPixel(2, 2, 1);\n\t_chars[3]->setPixel(2, 3, 1);\n\t_chars[3]->setPixel(0, 2, 1);\n\t_chars[3]->setPixel(1, 2, 1);\n\t_chars[3]->setPixel(0, 4, 1);\n\t_chars[3]->setPixel(1, 4, 1);\n\t_chars[3]->setPixel(2, 4, 1);\n\t_chars[3]->unlock();\n\n\t_chars[4] = new Surface(3, 5);\n\t_chars[4]->lock();\n\t_chars[4]->setPixel(0, 0, 1);\n\t_chars[4]->setPixel(0, 1, 1);\n\t_chars[4]->setPixel(0, 2, 1);\n\t_chars[4]->setPixel(1, 2, 1);\n\t_chars[4]->setPixel(2, 0, 1);\n\t_chars[4]->setPixel(2, 1, 1);\n\t_chars[4]->setPixel(2, 2, 1);\n\t_chars[4]->setPixel(2, 3, 1);\n\t_chars[4]->setPixel(2, 4, 1);\n\t_chars[4]->unlock();\n\n\t_chars[5] = new Surface(3, 5);\n\t_chars[5]->lock();\n\t_chars[5]->setPixel(0, 0, 1);\n\t_chars[5]->setPixel(1, 0, 1);\n\t_chars[5]->setPixel(2, 0, 1);\n\t_chars[5]->setPixel(0, 1, 1);\n\t_chars[5]->setPixel(0, 2, 1);\n\t_chars[5]->setPixel(1, 2, 1);\n\t_chars[5]->setPixel(2, 2, 1);\n\t_chars[5]->setPixel(2, 3, 1);\n\t_chars[5]->setPixel(0, 4, 1);\n\t_chars[5]->setPixel(1, 4, 1);\n\t_chars[5]->setPixel(2, 4, 1);\n\t_chars[5]->unlock();\n\n\t_chars[6] = new Surface(3, 5);\n\t_chars[6]->lock();\n\t_chars[6]->setPixel(0, 0, 1);\n\t_chars[6]->setPixel(1, 0, 1);\n\t_chars[6]->setPixel(2, 0, 1);\n\t_chars[6]->setPixel(0, 1, 1);\n\t_chars[6]->setPixel(0, 2, 1);\n\t_chars[6]->setPixel(1, 2, 1);\n\t_chars[6]->setPixel(2, 2, 1);\n\t_chars[6]->setPixel(0, 3, 1);\n\t_chars[6]->setPixel(2, 3, 1);\n\t_chars[6]->setPixel(0, 4, 1);\n\t_chars[6]->setPixel(1, 4, 1);\n\t_chars[6]->setPixel(2, 4, 1);\n\t_chars[6]->unlock();\n\n\t_chars[7] = new Surface(3, 5);\n\t_chars[7]->lock();\n\t_chars[7]->setPixel(0, 0, 1);\n\t_chars[7]->setPixel(1, 0, 1);\n\t_chars[7]->setPixel(2, 0, 1);\n\t_chars[7]->setPixel(2, 1, 1);\n\t_chars[7]->setPixel(2, 2, 1);\n\t_chars[7]->setPixel(2, 3, 1);\n\t_chars[7]->setPixel(2, 4, 1);\n\t_chars[7]->unlock();\n\n\t_chars[8] = new Surface(3, 5);\n\t_chars[8]->lock();\n\t_chars[8]->setPixel(0, 0, 1);\n\t_chars[8]->setPixel(1, 0, 1);\n\t_chars[8]->setPixel(2, 0, 1);\n\t_chars[8]->setPixel(0, 1, 1);\n\t_chars[8]->setPixel(0, 2, 1);\n\t_chars[8]->setPixel(0, 3, 1);\n\t_chars[8]->setPixel(2, 1, 1);\n\t_chars[8]->setPixel(2, 2, 1);\n\t_chars[8]->setPixel(2, 3, 1);\n\t_chars[8]->setPixel(1, 2, 1);\n\t_chars[8]->setPixel(0, 4, 1);\n\t_chars[8]->setPixel(1, 4, 1);\n\t_chars[8]->setPixel(2, 4, 1);\n\t_chars[8]->unlock();\n\n\t_chars[9] = new Surface(3, 5);\n\t_chars[9]->lock();\n\t_chars[9]->setPixel(0, 0, 1);\n\t_chars[9]->setPixel(1, 0, 1);\n\t_chars[9]->setPixel(2, 0, 1);\n\t_chars[9]->setPixel(0, 1, 1);\n\t_chars[9]->setPixel(0, 2, 1);\n\t_chars[9]->setPixel(2, 1, 1);\n\t_chars[9]->setPixel(2, 2, 1);\n\t_chars[9]->setPixel(2, 3, 1);\n\t_chars[9]->setPixel(1, 2, 1);\n\t_chars[9]->setPixel(0, 4, 1);\n\t_chars[9]->setPixel(1, 4, 1);\n\t_chars[9]->setPixel(2, 4, 1);\n\t_chars[9]->unlock();\n\n\tfor (int i = 0; i < 10; ++i)\n\t{\n\t\t_borderedChars[i] = new Surface(5, 7);\n\t\t// give it a border\n\t\t// this is the \"darker\" shade that goes in the corners.\n\t\tfor (int j = 0; j <= 2; j += 2)\n\t\t{\n\t\t\tfor (int k = 0; k <= 2; k += 2)\n\t\t\t{\n\t\t\t\t_chars[i]->blitNShade(_borderedChars[i], j, k, 11);\n\t\t\t}\n\t\t}\n\t\t// this is the \"slightly darker\" version that goes in four cardinals.\n\t\tfor (int z = 0; z <= 2; z += 2)\n\t\t{\n\t\t\t_chars[i]->blitNShade(_borderedChars[i], z, 1, 8);\n\t\t\t_chars[i]->blitNShade(_borderedChars[i], 1, z, 8);\n\t\t}\n\t\t// and finally the number itself\n\t\t_chars[i]->blitNShade(_borderedChars[i], 1, 1, 0);\n\t}\n}\n\n/**\n *\n */\nNumberText::~NumberText()\n{\n\tfor (int i = 0; i < 10; ++i)\n\t{\n\t\tdelete _chars[i];\n\t\tdelete _borderedChars[i];\n\t}\n}\n\n/**\n * Changes the value used to render the number.\n * @param value Number value.\n */\nvoid NumberText::setValue(unsigned int value)\n{\n\t_value = value;\n\t_redraw = true;\n}\n\n/**\n * Returns the value used to render the number.\n * @return Number value.\n */\nunsigned int NumberText::getValue() const\n{\n\treturn _value;\n}\n\n/**\n * Changes the color used to render the number.\n * @param color Color value.\n */\nvoid NumberText::setColor(Uint8 color)\n{\n\t_color = color;\n\t_redraw = true;\n}\n\n/**\n * Returns the color used to render the number.\n * @return Color value.\n */\nUint8 NumberText::getColor() const\n{\n\treturn _color;\n}\n\n/**\n * Replaces a certain amount of colors in the number text palette.\n * @param colors Pointer to the set of colors.\n * @param firstcolor Offset of the first color to replace.\n * @param ncolors Amount of colors to replace.\n */\nvoid NumberText::setPalette(const SDL_Color *colors, int firstcolor, int ncolors)\n{\n\tSurface::setPalette(colors, firstcolor, ncolors);\n\tfor (int i = 0; i < 10; ++i)\n\t{\n\t\t_chars[i]->setPalette(colors, firstcolor, ncolors);\n\t\t_borderedChars[i]->setPalette(colors, firstcolor, ncolors);\n\t}\n}\n\n/**\n * Draws all the digits in the number.\n */\nvoid NumberText::draw()\n{\n\tSurface::draw();\n\tstd::ostringstream ss;\n\tss << _value;\n\tstd::string s = ss.str();\n\tint x = 0;\n\tif (!_bordered)\n\t{\n\t\tfor (std::string::iterator i = s.begin(); i != s.end(); ++i)\n\t\t{\n\t\t\t_chars[*i - '0']->blitNShade(this, x, 0);\n\t\t\tx += _chars[*i - '0']->getWidth() + 1;\n\t\t}\n\t}\n\telse\n\t{\n\t\tfor (std::string::iterator i = s.begin(); i != s.end(); ++i)\n\t\t{\n\t\t\t_borderedChars[*i - '0']->blitNShade(this, x, 0);\n\t\t\tx += _chars[*i - '0']->getWidth() + 1; // no this isn't a typo, i want to use the same spacing regardless.\n\t\t}\n\t}\n\n\tthis->offset(_color);\n}\n\nvoid NumberText::setBordered(bool bordered)\n{\n\t_bordered = bordered;\n}\n\n}\n"
  },
  {
    "path": "src/Interface/NumberText.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/Surface.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Number digits displayed on the screen.\n * Takes a number and displays it using a simple hard-coded font.\n */\nclass NumberText : public Surface\n{\nprivate:\n\tunsigned int _value;\n\tSurface *_chars[10];\n\tSurface *_borderedChars[10];\n\tbool _bordered;\n\tUint8 _color;\npublic:\n\t/// Creates a new number text with the specified size and position.\n\tNumberText(int width, int height, int x = 0, int y = 0);\n\t/// Cleans up the number text.\n\t~NumberText();\n\t/// Sets the number text's value.\n\tvoid setValue(unsigned int value);\n\t/// Gets the number text's value.\n\tunsigned int getValue() const;\n\t/// Sets the number text's color.\n\tvoid setColor(Uint8 color) override;\n\t/// Gets the number text's color.\n\tUint8 getColor() const;\n\t/// Sets the number text's palette.\n\tvoid setPalette(const SDL_Color *colors, int firstcolor = 0, int ncolors = 256) override;\n\t/// Draws the number text.\n\tvoid draw() override;\n\t/// sets this numbertext to have a border or not\n\tvoid setBordered(bool bordered);\n\n};\n\n}\n"
  },
  {
    "path": "src/Interface/ProgressBar.cpp",
    "content": "/*\n * Copyright 2010-2024 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ProgressBar.h\"\n#include <SDL.h>\n\nnamespace OpenXcom\n{\n\n/**\n * Sets up a blank ProgressBar with the specified size and position.\n * @param width Width in pixels.\n * @param height Height in pixels.\n * @param x X position in pixels.\n * @param y Y position in pixels.\n */\nProgressBar::ProgressBar(int width, int height, int x, int y) : Surface(width, height, x, y), _color(32), _borderColor(1), _value(0)\n{\n\n}\n\n/**\n *\n */\nProgressBar::~ProgressBar()\n{\n}\n\n/**\n * Changes the color used to draw the border and contents.\n * @param color Color value.\n */\nvoid ProgressBar::setColor(Uint8 color)\n{\n\t_color = color;\n\t_redraw = true;\n}\n\n/**\n * Returns the color used to draw the ProgressBar.\n * @return Color value.\n */\nUint8 ProgressBar::getColor() const\n{\n\treturn _color;\n}\n\n/**\n * Sets the border color for the ProgressBar.\n * @param bc the color for the outline of the ProgressBar.\n * @note will use base colour + 4 if none is defined here.\n */\nvoid ProgressBar::setBorderColor(Uint8 bc)\n{\n\t_borderColor = bc;\n}\n\n/**\n * Changes the value used to draw the inner contents.\n * @param value Current value.\n */\nvoid ProgressBar::setValue(int value)\n{\n\t_value = (value < 0) ? 0 : value;\n\t_redraw = true;\n}\n\n/**\n * Returns the value used to draw the inner contents.\n * @return Current value.\n */\nint ProgressBar::getValue() const\n{\n\treturn _value;\n}\n\n/**\n * Draws the bordered ProgressBar filled according\n * to its value.\n */\nvoid ProgressBar::draw()\n{\n\tSurface::draw();\n\n\tSDL_Rect square;\n\n\t// border\n\tsquare.x = 0;\n\tsquare.y = 0;\n\tsquare.w = getWidth();\n\tsquare.h = getHeight();\n\n\tif (_borderColor)\n\t\tdrawRect(&square, _borderColor);\n\telse\n\t\tdrawRect(&square, _color + 4);\n\n\t// transparent inner content\n\tsquare.x++;\n\tsquare.y++;\n\tsquare.w -= 2;\n\tsquare.h -= 2;\n\n\tdrawRect(&square, 0);\n\n\t// non-transparent inner content\n\tsquare.w = square.w * _value / 100;\n\n\tdrawRect(&square, _color);\n}\n\n}\n"
  },
  {
    "path": "src/Interface/ProgressBar.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2024 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/Surface.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Progress bar graphic that represents a certain percentage value.\n * Drawn with a coloured border and partially filled inner content.\n */\nclass ProgressBar : public Surface\n{\nprivate:\n\tUint8 _color, _borderColor;\n\tint _value;\npublic:\n\t/// Creates a new progress bar with the specified size and position.\n\tProgressBar(int width, int height, int x = 0, int y = 0);\n\t/// Cleans up the progress bar.\n\t~ProgressBar();\n\t/// Sets the progress bar's color.\n\tvoid setColor(Uint8 color) override;\n\t/// Gets the progress bar's color.\n\tUint8 getColor() const;\n\t/// Sets the outline color for the progress bar.\n\tvoid setBorderColor(Uint8 bc) override;\n\t/// Sets the progress bar's current value.\n\tvoid setValue(int value);\n\t/// Gets the progress bar's current value.\n\tint getValue() const;\n\t/// Draws the progress bar.\n\tvoid draw() override;\n};\n\n}\n"
  },
  {
    "path": "src/Interface/ScrollBar.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ScrollBar.h\"\n#include \"../fmath.h\"\n#include \"../Engine/Action.h\"\n#include \"TextList.h\"\n#include \"../Engine/Palette.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Sets up a scrollbar with the specified size and position.\n * @param width Width in pixels.\n * @param height Height in pixels.\n * @param x X position in pixels.\n * @param y Y position in pixels.\n */\nScrollBar::ScrollBar(int width, int height, int x, int y) : InteractiveSurface(width, height, x, y), _list(0), _color(0), _pressed(false), _contrast(false), _offset(0), _bg(0)\n{\n\t_track = new Surface(width-2, height, x+1, y);\n\t_thumb = new Surface(width, height, x, y);\n\t_thumbRect.x = 0;\n\t_thumbRect.y = 0;\n\t_thumbRect.w = 0;\n\t_thumbRect.h = 0;\n}\n\n/**\n * Deletes contents.\n */\nScrollBar::~ScrollBar()\n{\n\tdelete _track;\n\tdelete _thumb;\n}\n\n/**\n * Changes the position of the surface in the X axis.\n * @param x X position in pixels.\n */\nvoid ScrollBar::setX(int x)\n{\n\tSurface::setX(x);\n\t_track->setX(x+1);\n\t_thumb->setX(x);\n}\n\n/**\n * Changes the position of the surface in the Y axis.\n * @param y Y position in pixels.\n */\nvoid ScrollBar::setY(int y)\n{\n\tSurface::setY(y);\n\t_track->setY(y);\n\t_thumb->setY(y);\n}\n\n/**\n * Changes the height of the scrollbar.\n * @param height New height in pixels.\n */\nvoid ScrollBar::setHeight(int height)\n{\n\tSurface::setHeight(height);\n\t_track->setHeight(height);\n\t_thumb->setHeight(height);\n\t_redraw = true;\n}\n\n/**\n * Changes the color used to render the scrollbar.\n * @param color Color value.\n */\nvoid ScrollBar::setColor(Uint8 color)\n{\n\t_color = color;\n}\n\n/**\n * Returns the color used to render the scrollbar.\n * @return Color value.\n */\nUint8 ScrollBar::getColor() const\n{\n\treturn _color;\n}\n\n/**\n * Enables/disables high contrast color. Mostly used for\n * Battlescape text.\n * @param contrast High contrast setting.\n */\nvoid ScrollBar::setHighContrast(bool contrast)\n{\n\t_contrast = contrast;\n}\n\n/**\n * Changes the list associated with the scrollbar.\n * This makes the button scroll that list.\n * @param list Pointer to text list.\n */\nvoid ScrollBar::setTextList(TextList *list)\n{\n\t_list = list;\n}\n\n/**\n * Changes the surface used to draw the background of the track.\n * @param bg New background.\n */\nvoid ScrollBar::setBackground(Surface *bg)\n{\n\t_bg = bg;\n}\n\n/**\n * Replaces a certain amount of colors in the scrollbar's palette.\n * @param colors Pointer to the set of colors.\n * @param firstcolor Offset of the first color to replace.\n * @param ncolors Amount of colors to replace.\n */\nvoid ScrollBar::setPalette(const SDL_Color *colors, int firstcolor, int ncolors)\n{\n\tSurface::setPalette(colors, firstcolor, ncolors);\n\t_track->setPalette(colors, firstcolor, ncolors);\n\t_thumb->setPalette(colors, firstcolor, ncolors);\n}\n\n/**\n * Automatically updates the scrollbar\n * when the mouse moves.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid ScrollBar::handle(Action *action, State *state)\n{\n\tInteractiveSurface::handle(action, state);\n\tif (_pressed && (action->getDetails()->type == SDL_MOUSEMOTION || action->getDetails()->type == SDL_MOUSEBUTTONDOWN))\n\t{\n\t\tint cursorY = action->getAbsoluteYMouse() - getY();\n\t\tint y = Clamp(cursorY + _offset, 0, getHeight() - _thumbRect.h + 1);\n\t\tdouble scale = (double)_list->getRowsDoNotUse() / getHeight();\n\t\tint scroll = (int)Round(y * scale);\n\t\t_list->scrollTo(scroll);\n\t}\n}\n\n/**\n * Blits the scrollbar contents.\n * @param surface Pointer to surface to blit onto.\n */\nvoid ScrollBar::blit(SDL_Surface *surface)\n{\n\tSurface::blit(surface);\n\tif (_visible && !_hidden)\n\t{\n\t\t_track->blit(surface);\n\t\t_thumb->blit(surface);\n\t\tinvalidate();\n\t}\n}\n\n/**\n * The scrollbar only moves while the button is pressed.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid ScrollBar::mousePress(Action *action, State *state)\n{\n\tInteractiveSurface::mousePress(action, state);\n\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT)\n\t{\n\t\tint cursorY = action->getAbsoluteYMouse() - getY();\n\t\tif (cursorY >= _thumbRect.y && cursorY < _thumbRect.y + _thumbRect.h)\n\t\t{\n\t\t\t_offset = _thumbRect.y - cursorY;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_offset = -_thumbRect.h / 2;\n\t\t}\n\t\t_pressed = true;\n\t}\n\telse if (action->getDetails()->button.button == SDL_BUTTON_WHEELUP)\n\t{\n\t\t_list->scrollUp(false, true);\n\t}\n\telse if (action->getDetails()->button.button == SDL_BUTTON_WHEELDOWN)\n\t{\n\t\t_list->scrollDown(false, true);\n\t}\n}\n\n/**\n * The scrollbar stops moving when the button is released.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid ScrollBar::mouseRelease(Action *action, State *state)\n{\n\tInteractiveSurface::mouseRelease(action, state);\n\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT)\n\t{\n\t\t_pressed = false;\n\t\t_offset = 0;\n\t}\n}\n\n/**\n * Updates the thumb according to the current list position.\n */\nvoid ScrollBar::draw()\n{\n\tSurface::draw();\n\tdrawTrack();\n\tdrawThumb();\n}\n\n/**\n * Draws the track (background bar) semi-transparent.\n */\nvoid ScrollBar::drawTrack()\n{\n\tif (_bg)\n\t{\n\t\t_track->copy(_bg);\n\t\tif (_list->getComboBox())\n\t\t{\n\t\t\t_track->offset(+1, Palette::backPos);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_track->offsetBlock(-5);\n\t\t}\n\t}\n}\n\n/**\n * Draws the thumb (button) as a hollow square.\n */\nvoid ScrollBar::drawThumb()\n{\n\tdouble scale = (double)getHeight() / _list->getRowsDoNotUse();\n\t_thumbRect.x = 0;\n\t_thumbRect.y = (int)floor(_list->getScroll() * scale);\n\t_thumbRect.w = _thumb->getWidth();\n\t_thumbRect.h = (int)ceil(_list->getVisibleRows() * scale);\n\n\t// Draw base button\n\t_thumb->clear();\n\t_thumb->lock();\n\n\tSDL_Rect square = _thumbRect;\n\tint color = _color + 2;\n\n\tsquare.w--;\n\tsquare.h--;\n\n\t_thumb->drawRect(&square, color);\n\n\tsquare.x++;\n\tsquare.y++;\n\tcolor = _color + 5;\n\n\t_thumb->drawRect(&square, color);\n\n\tsquare.w--;\n\tsquare.h--;\n\tcolor = _color + 4;\n\n\t_thumb->drawRect(&square, color);\n\n\t_thumb->setPixel(_thumbRect.x, _thumbRect.y, _color + 1);\n\t_thumb->setPixel(_thumbRect.x, _thumbRect.y + _thumbRect.h - 1, _color + 4);\n\t_thumb->setPixel(_thumbRect.x + _thumbRect.w - 1, _thumbRect.y, _color + 4);\n\n\t// Hollow it out\n\tif ((int)square.h - 4 > 0)\n\t{\n\t\tcolor = _color + 5;\n\n\t\tsquare.x++;\n\t\tsquare.y++;\n\t\tsquare.w -= 3;\n\t\tsquare.h -= 3;\n\n\t\t_thumb->drawRect(&square, color);\n\n\t\tsquare.x++;\n\t\tsquare.y++;\n\t\tcolor = _color + 2;\n\n\t\t_thumb->drawRect(&square, color);\n\n\t\tsquare.w--;\n\t\tsquare.h--;\n\t\tcolor = 0;\n\n\t\t_thumb->drawRect(&square, color);\n\n\t\t_thumb->setPixel(_thumbRect.x + 2 + _thumbRect.w - 1 - 4, _thumbRect.y + 2 + _thumbRect.h - 1 - 4, _color + 1);\n\t\t_thumb->setPixel(_thumbRect.x + 2, _thumbRect.y + 2 + _thumbRect.h - 1 - 4, _color + 4);\n\t\t_thumb->setPixel(_thumbRect.x + 2 + _thumbRect.w - 1 - 4, _thumbRect.y + 2, _color + 4);\n\t}\n\t_thumb->unlock();\n}\n\n}\n"
  },
  {
    "path": "src/Interface/ScrollBar.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/InteractiveSurface.h\"\n\nnamespace OpenXcom\n{\n\nclass TextList;\n\n/**\n * Horizontal scrollbar control to select from a range of values.\n */\nclass ScrollBar : public InteractiveSurface\n{\nprivate:\n\tTextList *_list;\n\tUint8 _color;\n\tbool _pressed, _contrast;\n\tSurface *_track, *_thumb;\n\tSDL_Rect _thumbRect;\n\tint _offset;\n\tSurface *_bg;\n\t/// Draws the scrollbar track.\n\tvoid drawTrack();\n\t/// Draws the scrollbar thumb.\n\tvoid drawThumb();\npublic:\n\t/// Creates a new scrollbar with the specified size and position.\n\tScrollBar(int width, int height, int x = 0, int y = 0);\n\t/// Cleans up the scrollbar.\n\t~ScrollBar();\n\t/// Sets the X position of the surface.\n\tvoid setX(int x) override;\n\t/// Sets the Y position of the surface.\n\tvoid setY(int y) override;\n\t/// Sets the height of the surface.\n\tvoid setHeight(int height) override;\n\t/// Sets the scrollbar's color.\n\tvoid setColor(Uint8 color) override;\n\t/// Gets the scrollbar's color.\n\tUint8 getColor() const;\n\t/// Sets the scrollbar's high contrast color setting.\n\tvoid setHighContrast(bool contrast) override;\n\t/// Sets the scrollbar's list.\n\tvoid setTextList(TextList *list);\n\t/// Sets the background for the track.\n\tvoid setBackground(Surface *bg);\n\t/// Sets the scrollbar's palette.\n\tvoid setPalette(const SDL_Color *colors, int firstcolor = 0, int ncolors = 256) override;\n\t/// Blits the scrollbar onto another surface.\n\tvoid blit(SDL_Surface *surface) override;\n\t/// Moves the scrollbar.\n\tvoid handle(Action *action, State *state) override;\n\t/// Special handling for mouse presses.\n\tvoid mousePress(Action *action, State *state) override;\n\t/// Special handling for mouse releases.\n\tvoid mouseRelease(Action *action, State *state) override;\n\t/// Draws the scrollbar contents.\n\tvoid draw() override;\n};\n\n}\n"
  },
  {
    "path": "src/Interface/Slider.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Slider.h\"\n#include \"../fmath.h\"\n#include \"../Engine/Action.h\"\n#include \"TextButton.h\"\n#include \"Text.h\"\n#include \"Frame.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Sets up a slider with the specified size and position.\n * @param width Width in pixels.\n * @param height Height in pixels.\n * @param x X position in pixels.\n * @param y Y position in pixels.\n */\nSlider::Slider(int width, int height, int x, int y) : InteractiveSurface(width, height, x, y), _pos(0.0), _min(0), _max(100), _pressed(false), _change(0), _offsetX(0)\n{\n\t_thickness = 5;\n\t_textness = 8;\n\t_txtMinus = new Text(_textness, height - 2, x - 1, y);\n\t_txtPlus = new Text(_textness, height - 2, x + width - _textness, y);\n\t_frame = new Frame(width - _textness*2, _thickness, x + _textness, y + (height - _thickness) / 2);\n\t_button = new TextButton(10, height, x, y);\n\n\t_frame->setThickness(_thickness);\n\n\t_txtMinus->setAlign(ALIGN_CENTER);\n\t_txtMinus->setVerticalAlign(ALIGN_MIDDLE);\n\t_txtMinus->setText(\"-\");\n\n\t_txtPlus->setAlign(ALIGN_CENTER);\n\t_txtPlus->setVerticalAlign(ALIGN_MIDDLE);\n\t_txtPlus->setText(\"+\");\n\n\t_minX = _frame->getX();\n\t_maxX = _frame->getX() + _frame->getWidth() - _button->getWidth();\n\n\tsetValue(_pos);\n}\n\n/**\n * Deletes contents.\n */\nSlider::~Slider()\n{\n\tdelete _txtMinus;\n\tdelete _txtPlus;\n\tdelete _frame;\n\tdelete _button;\n}\n\n/**\n * Changes the position of the surface in the X axis.\n * @param x X position in pixels.\n */\nvoid Slider::setX(int x)\n{\n\tSurface::setX(x);\n\t_txtMinus->setX(x - 1);\n\t_txtPlus->setX(x + getWidth() - _textness);\n\t_frame->setX(getX() + _textness);\n\n\t_minX = _frame->getX();\n\t_maxX = _frame->getX() + _frame->getWidth() - _button->getWidth();\n\tsetValue(_pos);\n}\n\n/**\n * Changes the position of the surface in the Y axis.\n * @param y Y position in pixels.\n */\nvoid Slider::setY(int y)\n{\n\tSurface::setY(y);\n\t_txtMinus->setY(y);\n\t_txtPlus->setY(y);\n\t_frame->setY(getY() + (getHeight() - _thickness) / 2);\n\t_button->setY(getY());\n}\n\n/**\n * Changes the various resources needed for text rendering.\n * The different fonts need to be passed in advance since the\n * text size can change mid-text, and the language affects\n * how the text is rendered.\n * @param big Pointer to large-size font.\n * @param small Pointer to small-size font.\n * @param lang Pointer to current language.\n */\nvoid Slider::initText(Font *big, Font *small, Language *lang)\n{\n\t_txtMinus->initText(big, small, lang);\n\t_txtPlus->initText(big, small, lang);\n\t_button->initText(big, small, lang);\n}\n\n/**\n * Enables/disables high contrast color. Mostly used for\n * Battlescape.\n * @param contrast High contrast setting.\n */\nvoid Slider::setHighContrast(bool contrast)\n{\n\t_txtMinus->setHighContrast(contrast);\n\t_txtPlus->setHighContrast(contrast);\n\t_frame->setHighContrast(contrast);\n\t_button->setHighContrast(contrast);\n}\n\n/**\n * Changes the color used to render the slider.\n * @param color Color value.\n */\nvoid Slider::setColor(Uint8 color)\n{\n\t_txtMinus->setColor(color);\n\t_txtPlus->setColor(color);\n\t_frame->setColor(color);\n\t_button->setColor(color);\n}\n\n/**\n * Returns the color used to render the slider.\n * @return Color value.\n */\nUint8 Slider::getColor() const\n{\n\treturn _button->getColor();\n}\n\n/**\n * Replaces a certain amount of colors in the slider's palette.\n * @param colors Pointer to the set of colors.\n * @param firstcolor Offset of the first color to replace.\n * @param ncolors Amount of colors to replace.\n */\nvoid Slider::setPalette(const SDL_Color *colors, int firstcolor, int ncolors)\n{\n\tSurface::setPalette(colors, firstcolor, ncolors);\n\t_txtMinus->setPalette(colors, firstcolor, ncolors);\n\t_txtPlus->setPalette(colors, firstcolor, ncolors);\n\t_frame->setPalette(colors, firstcolor, ncolors);\n\t_button->setPalette(colors, firstcolor, ncolors);\n}\n\n/**\n * Automatically updates the slider\n * when the mouse moves.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid Slider::handle(Action *action, State *state)\n{\n\tInteractiveSurface::handle(action, state);\n\t//_button->handle(action, state);\n\tif (_pressed && (action->getDetails()->type == SDL_MOUSEMOTION || action->getDetails()->type == SDL_MOUSEBUTTONDOWN))\n\t{\n\t\tint cursorX = action->getAbsoluteXMouse();\n\t\tdouble buttonX = Clamp(cursorX + _offsetX, _minX, _maxX);\n\t\tdouble pos = (buttonX - _minX) / (_maxX - _minX);\n\t\tint value = _min + (int)Round((_max - _min) * pos);\n\t\tsetValue(value);\n\t\tif (_change)\n\t\t{\n\t\t\t(state->*_change)(action);\n\t\t}\n\t}\n}\n\n/**\n * Moves the slider to the new position.\n * @param value New value.\n */\nvoid Slider::setPosition(double pos)\n{\n\t_pos = pos;\n\t_button->setX((int)floor(_minX + (_maxX - _minX) * _pos));\n}\n\n/**\n * Changes the range of values the slider\n * can contain.\n * @param min Minimum value.\n * @param max Maximum value.\n */\nvoid Slider::setRange(int min, int max)\n{\n\t_min = min;\n\t_max = max;\n\tsetValue(_value);\n}\n\n/**\n * Changes the current value of the slider and\n * positions it appropriately.\n * @param value New value.\n */\nvoid Slider::setValue(int value)\n{\n\tif (_min == _max)\n\t{\n\t\t_value = 0;\n\t\tsetPosition(0.0);\n\t\treturn;\n\t}\n\telse if (_min < _max)\n\t{\n\t\t_value = Clamp(value, _min, _max);\n\t}\n\telse\n\t{\n\t\t_value = Clamp(value, _max, _min);\n\t}\n\tdouble pos = (double)(_value - _min) / (double)(_max - _min);\n\tsetPosition(pos);\n}\n\n/**\n * Returns the current value of the slider.\n * @return Value.\n */\nint Slider::getValue() const\n{\n\treturn _value;\n}\n\n/**\n * Blits the slider contents\n * @param surface Pointer to surface to blit onto.\n */\nvoid Slider::blit(SDL_Surface *surface)\n{\n\tSurface::blit(surface);\n\tif (_visible && !_hidden)\n\t{\n\t\t_txtMinus->blit(surface);\n\t\t_txtPlus->blit(surface);\n\t\t_frame->blit(surface);\n\t\t_button->blit(surface);\n\t}\n}\n\n/**\n * The slider only moves while the button is pressed.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid Slider::mousePress(Action *action, State *state)\n{\n\tInteractiveSurface::mousePress(action, state);\n\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT)\n\t{\n\t\t_pressed = true;\n\t\tint cursorX = action->getAbsoluteXMouse();\n\t\tif (cursorX >= _button->getX() && cursorX < _button->getX() + _button->getWidth())\n\t\t{\n\t\t\t_offsetX = _button->getX() - cursorX;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_offsetX = -_button->getWidth() / 2;\n\t\t}\n\t}\n}\n\n/**\n * The slider stops moving when the button is released.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid Slider::mouseRelease(Action *action, State *state)\n{\n\tInteractiveSurface::mouseRelease(action, state);\n\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT)\n\t{\n\t\t_pressed = false;\n\t\t_offsetX = 0;\n\t}\n}\n\n/**\n * Sets a function to be called every time the slider's value changes.\n * @param handler Action handler.\n */\nvoid Slider::onChange(ActionHandler handler)\n{\n\t_change = handler;\n}\n\n}\n"
  },
  {
    "path": "src/Interface/Slider.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/InteractiveSurface.h\"\n\nnamespace OpenXcom\n{\n\nclass Font;\nclass Language;\nclass Frame;\nclass TextButton;\nclass Text;\n\n/**\n * Horizontal slider control to select from a range of values.\n */\nclass Slider : public InteractiveSurface\n{\nprivate:\n\tFrame *_frame;\n\tText *_txtMinus, *_txtPlus;\n\tTextButton *_button;\n\tdouble _pos;\n\tint _min, _max, _value;\n\tbool _pressed;\n\tActionHandler _change;\n\tint _thickness, _textness, _minX, _maxX, _offsetX;\n\n\t/// Sets the slider's position.\n\tvoid setPosition(double pos);\npublic:\n\t/// Creates a new slider with the specified size and position.\n\tSlider(int width, int height, int x = 0, int y = 0);\n\t/// Cleans up the slider.\n\t~Slider();\n\t/// Sets the X position of the surface.\n\tvoid setX(int x) override;\n\t/// Sets the Y position of the surface.\n\tvoid setY(int y) override;\n\t/// Initializes the slider's resources.\n\tvoid initText(Font *big, Font *small, Language *lang) override;\n\t/// Sets the slider's high contrast color setting.\n\tvoid setHighContrast(bool contrast) override;\n\t/// Sets the slider's color.\n\tvoid setColor(Uint8 color) override;\n\t/// Gets the slider's color.\n\tUint8 getColor() const;\n\t/// Sets the slider's palette.\n\tvoid setPalette(const SDL_Color *colors, int firstcolor = 0, int ncolors = 256) override;\n\t/// Sets the slider's range.\n\tvoid setRange(int min, int max);\n\t/// Sets the slider's value.\n\tvoid setValue(int value);\n\t/// Gets the slider's value.\n\tint getValue() const;\n\t/// Blits the slider onto another surface.\n\tvoid blit(SDL_Surface *surface) override;\n\t/// Moves the slider.\n\tvoid handle(Action *action, State *state) override;\n\t/// Special handling for mouse presses.\n\tvoid mousePress(Action *action, State *state) override;\n\t/// Special handling for mouse releases.\n\tvoid mouseRelease(Action *action, State *state) override;\n\t/// Hooks an action handler to when the slider changes.\n\tvoid onChange(ActionHandler handler);\n};\n\n}\n"
  },
  {
    "path": "src/Interface/Text.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Text.h\"\n#include \"../fmath.h\"\n#include \"../Engine/Font.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Language.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Engine/ShaderDraw.h\"\n#include \"../Engine/ShaderMove.h\"\n#include \"../Engine/Action.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Sets up a blank text with the specified size and position.\n * @param width Width in pixels.\n * @param height Height in pixels.\n * @param x X position in pixels.\n * @param y Y position in pixels.\n */\nText::Text(int width, int height, int x, int y) : InteractiveSurface(width, height, x, y),\n\t_big(0), _small(0), _font(0), _fontOrig(0), _lang(0),\n\t_wrap(false), _invert(false), _contrast(false), _indent(false), _scroll(false), _ignoreSeparators(false),\n\t_align(ALIGN_LEFT), _valign(ALIGN_TOP), _color(0), _color2(0), _scrollY(0)\n{\n}\n\n/**\n *\n */\nText::~Text()\n{\n\n}\n\n/**\n * Changes the text to use the big-size font.\n */\nvoid Text::setBig()\n{\n\t_font = _big;\n\t_fontOrig = _big;\n\tprocessText();\n}\n\n/**\n * Changes the text to use the small-size font.\n */\nvoid Text::setSmall()\n{\n\t_font = _small;\n\t_fontOrig = _small;\n\tprocessText();\n}\n\n/**\n * Returns the font currently used by the text.\n * @return Pointer to font.\n */\nFont *Text::getFont() const\n{\n\treturn _font;\n}\n\n/**\n * Changes the various resources needed for text rendering.\n * The different fonts need to be passed in advance since the\n * text size can change mid-text, and the language affects\n * how the text is rendered.\n * @param big Pointer to large-size font.\n * @param small Pointer to small-size font.\n * @param lang Pointer to current language.\n */\nvoid Text::initText(Font *big, Font *small, Language *lang)\n{\n\t_big = big;\n\t_small = small;\n\t_lang = lang;\n\tsetSmall();\n}\n\n/**\n * Changes the string displayed on screen.\n * @param text Text string.\n */\nvoid Text::setText(const std::string &text)\n{\n\t_text = text;\n\t_font = _fontOrig;\n\tprocessText();\n\t// If big text won't fit the space, try small text\n\tif (!_text.empty())\n\t{\n\t\tif (_font == _big && (getTextWidth() > getWidth() || getTextHeight() > getHeight()) && _text[_text.size() - 1] != '.')\n\t\t{\n\t\t\t_font = _small;\n\t\t\tprocessText();\n\t\t}\n\t}\n}\n\n/**\n * Returns the string displayed on screen.\n * @return Text string.\n */\nstd::string Text::getText() const\n{\n\treturn _text;\n}\n\n/**\n * Enables/disables text wordwrapping. When enabled, lines of\n * text are automatically split to ensure they stay within the\n * drawing area, otherwise they simply go off the edge.\n * @param wrap Wordwrapping setting.\n * @param indent Indent wrapped text.\n * @param ignoreSeparators Handle separators as spaces (false) or as normal text (true)?\n */\nvoid Text::setWordWrap(bool wrap, bool indent, bool ignoreSeparators)\n{\n\tif (wrap != _wrap || indent != _indent || ignoreSeparators != _ignoreSeparators)\n\t{\n\t\t_wrap = wrap;\n\t\t_indent = indent;\n\t\t_ignoreSeparators = ignoreSeparators;\n\t\tprocessText();\n\t}\n}\n\n/**\n * Enables/disables color inverting. Mostly used to make\n * button text look pressed along with the button.\n * @param invert Invert setting.\n */\nvoid Text::setInvert(bool invert)\n{\n\t_invert = invert;\n\t_redraw = true;\n}\n\n/**\n * Enables/disables high contrast color. Mostly used for\n * Battlescape UI.\n * @param contrast High contrast setting.\n */\nvoid Text::setHighContrast(bool contrast)\n{\n\t_contrast = contrast;\n\t_redraw = true;\n}\n\n/**\n * Changes the way the text is aligned horizontally\n * relative to the drawing area.\n * @param align Horizontal alignment.\n */\nvoid Text::setAlign(TextHAlign align)\n{\n\t_align = align;\n\t_redraw = true;\n}\n\n/**\n * Returns the way the text is aligned horizontally\n * relative to the drawing area.\n * @return Horizontal alignment.\n */\nTextHAlign Text::getAlign() const\n{\n\treturn _align;\n}\n\n/**\n * Changes the way the text is aligned vertically\n * relative to the drawing area.\n * @param valign Vertical alignment.\n */\nvoid Text::setVerticalAlign(TextVAlign valign)\n{\n\t_valign = valign;\n\t_redraw = true;\n}\n\n/**\n * Returns the way the text is aligned vertically\n * relative to the drawing area.\n * @return Horizontal alignment.\n */\nTextVAlign Text::getVerticalAlign() const\n{\n\treturn _valign;\n}\n\n/**\n * Changes the color used to render the text. Unlike regular graphics,\n * fonts are greyscale so they need to be assigned a specific position\n * in the palette to be displayed.\n * @param color Color value.\n */\nvoid Text::setColor(Uint8 color)\n{\n\t_color = color;\n\t_color2 = color;\n\t_redraw = true;\n}\n\n/**\n * Returns the color used to render the text.\n * @return Color value.\n */\nUint8 Text::getColor() const\n{\n\treturn _color;\n}\n\n/**\n * Changes the secondary color used to render the text. The text\n * switches between the primary and secondary color whenever there's\n * a 0x01 in the string.\n * @param color Color value.\n */\nvoid Text::setSecondaryColor(Uint8 color)\n{\n\t_color2 = color;\n\t_redraw = true;\n}\n\n/**\n * Returns the secondary color used to render the text.\n * @return Color value.\n */\nUint8 Text::getSecondaryColor() const\n{\n\treturn _color2;\n}\n\nint Text::getNumLines() const\n{\n\treturn _wrap ? _lineHeight.size() : 1;\n}\n\n/**\n * Returns the rendered text's height. Useful to check if wordwrap applies.\n * @param line Line to get the height, or -1 to get whole text height.\n * @return Height in pixels.\n */\nint Text::getTextHeight(int line) const\n{\n\tif (line == -1)\n\t{\n\t\tint height = 0;\n\t\tfor (int lh : _lineHeight)\n\t\t{\n\t\t\theight += lh;\n\t\t}\n\t\treturn height;\n\t}\n\telse\n\t{\n\t\treturn _lineHeight[line];\n\t}\n}\n\n/**\n * Returns the rendered text's width.\n * @param line Line to get the width, or -1 to get whole text width.\n * @return Width in pixels.\n */\nint Text::getTextWidth(int line) const\n{\n\tif (line == -1)\n\t{\n\t\tint width = 0;\n\t\tfor (int lw : _lineWidth)\n\t\t{\n\t\t\tif (lw > width)\n\t\t\t{\n\t\t\t\twidth = lw;\n\t\t\t}\n\t\t}\n\t\treturn width;\n\t}\n\telse\n\t{\n\t\treturn _lineWidth[line];\n\t}\n}\n\n/**\n * Takes care of any text post-processing like converting\n * encoded text to individual codepoints and calculating\n * line metrics for alignment and wordwrapping.\n */\nvoid Text::processText()\n{\n\tif (_font == 0 || _lang == 0)\n\t{\n\t\treturn;\n\t}\n\n\t_processedText = Unicode::convUtf8ToUtf32(_text);\n\t_lineWidth.clear();\n\t_lineHeight.clear();\n\t_scrollY = 0;\n\n\tint width = 0, word = 0;\n\tsize_t space = 0, textIndentation = 0;\n\tbool start = true;\n\tFont *font = _font;\n\tUString &str = _processedText;\n\n\t// Go through the text character by character\n\tfor (size_t c = 0; c <= str.size(); ++c)\n\t{\n\t\t// End of the line\n\t\tif (c == str.size() || Unicode::isLinebreak(str[c]))\n\t\t{\n\t\t\t// Add line measurements for alignment later\n\t\t\t_lineWidth.push_back(width);\n\t\t\t_lineHeight.push_back(font->getCharSize('\\n').h);\n\t\t\tstart = true;\n\t\t\twidth = 0;\n\t\t\tword = 0;\n\n\t\t\tif (c == str.size())\n\t\t\t\tbreak;\n\t\t\telse if (str[c] == Unicode::TOK_NL_SMALL)\n\t\t\t\tfont = _small;\n\t\t}\n\t\t// Keep track of spaces for wordwrapping\n\t\telse if (Unicode::isSpace(str[c]) || (!_ignoreSeparators && Unicode::isSeparator(str[c])))\n\t\t{\n\t\t\t// Store existing indentation\n\t\t\tif (c == textIndentation)\n\t\t\t{\n\t\t\t\ttextIndentation++;\n\t\t\t}\n\t\t\tspace = c;\n\t\t\tstart = start && (word == 0); // consider initial spaces still as start of line until first character is met\n\t\t\twidth += font->getCharSize(str[c]).w;\n\t\t\tword = 0;\n\t\t}\n\t\t// Custom format, skip 3 next chars\n\t\telse if (str[c] == Unicode::TOK_CUSTOM_FORMAT)\n\t\t{\n\t\t\tif (c + 3u > str.size())\n\t\t\t{\n\t\t\t\tstr.resize(c + 3u); // add missing character\n\t\t\t\tstr[c + 1u] = '\\0';\n\t\t\t\tstr[c + 2u] = '\\0';\n\t\t\t}\n\t\t\tc += 2u;\n\t\t}\n\t\t// Keep track of the width of the last line and word\n\t\telse if (str[c] != Unicode::TOK_COLOR_FLIP)\n\t\t{\n\t\t\tint charWidth = font->getCharSize(str[c]).w;\n\n\t\t\twidth += charWidth;\n\t\t\tword += charWidth;\n\n\t\t\t// Wordwrap if the last word doesn't fit the line\n\t\t\tif (_wrap && width >= getWidth() && (!start || _lang->getTextWrapping() == WRAP_LETTERS))\n\t\t\t{\n\t\t\t\tsize_t indentLocation = c;\n\t\t\t\tif (_lang->getTextWrapping() == WRAP_WORDS || Unicode::isSpace(str[c]))\n\t\t\t\t{\n\t\t\t\t\t// Go back to the last space and put a linebreak there\n\t\t\t\t\twidth -= word;\n\t\t\t\t\tindentLocation = space;\n\t\t\t\t\tif (Unicode::isSpace(str[space]))\n\t\t\t\t\t{\n\t\t\t\t\t\twidth -= font->getCharSize(str[space]).w;\n\t\t\t\t\t\tstr[space] = '\\n';\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tstr.insert(space+1, 1, '\\n');\n\t\t\t\t\t\tindentLocation++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (_lang->getTextWrapping() == WRAP_LETTERS)\n\t\t\t\t{\n\t\t\t\t\t// Go back to the last letter and put a linebreak there\n\t\t\t\t\tstr.insert(c, 1, '\\n');\n\t\t\t\t\twidth -= charWidth;\n\t\t\t\t}\n\n\t\t\t\t// Keep initial indentation of text\n\t\t\t\tif (textIndentation > 0)\n\t\t\t\t{\n\t\t\t\t\tstr.insert(indentLocation+1, textIndentation, '\\t');\n\t\t\t\t\tindentLocation += textIndentation;\n\t\t\t\t}\n\t\t\t\t// Indent due to word wrap.\n\t\t\t\tif (_indent)\n\t\t\t\t{\n\t\t\t\t\tstr.insert(indentLocation+1, 1, '\\t');\n\t\t\t\t\twidth += font->getCharSize('\\t').w;\n\t\t\t\t}\n\n\t\t\t\t_lineWidth.push_back(width);\n\t\t\t\t_lineHeight.push_back(font->getCharSize('\\n').h);\n\t\t\t\tif (_lang->getTextWrapping() == WRAP_WORDS)\n\t\t\t\t{\n\t\t\t\t\twidth = word;\n\t\t\t\t}\n\t\t\t\telse if (_lang->getTextWrapping() == WRAP_LETTERS)\n\t\t\t\t{\n\t\t\t\t\twidth = 0;\n\t\t\t\t}\n\t\t\t\tstart = true;\n\t\t\t}\n\t\t}\n\t}\n\n\t_redraw = true;\n}\n\nnamespace\n{\n\nstruct PaletteShift\n{\n\tstatic inline void func(Uint8& dest, const Uint8& src, int off, int mul, int mid)\n\t{\n\t\tif(src)\n\t\t{\n\t\t\tint inverseOffset = mid ? 2 * (mid - src) : 0;\n\t\t\tdest = off + src * mul + inverseOffset;\n\t\t}\n\t}\n};\n\n} //namespace\n\n/**\n * Calculates the starting X position for a line of text.\n * @param line The line number (0 = first, etc).\n * @return The X position in pixels.\n */\nint Text::getLineX(int line) const\n{\n\tint x = 0;\n\tswitch (_lang->getTextDirection())\n\t{\n\tcase DIRECTION_LTR:\n\t\tswitch (_align)\n\t\t{\n\t\tcase ALIGN_LEFT:\n\t\t\tbreak;\n\t\tcase ALIGN_CENTER:\n\t\t\tx = (int)ceil((getWidth() + _font->getSpacing() - _lineWidth[line]) / 2.0);\n\t\t\tbreak;\n\t\tcase ALIGN_RIGHT:\n\t\t\tx = getWidth() - 1 - _lineWidth[line];\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\tcase DIRECTION_RTL:\n\t\tswitch (_align)\n\t\t{\n\t\tcase ALIGN_LEFT:\n\t\t\tx = getWidth() - 1;\n\t\t\tbreak;\n\t\tcase ALIGN_CENTER:\n\t\t\tx = getWidth() - (int)ceil((getWidth() + _font->getSpacing() - _lineWidth[line]) / 2.0);\n\t\t\tbreak;\n\t\tcase ALIGN_RIGHT:\n\t\t\tx = _lineWidth[line];\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\t}\n\treturn x;\n}\n\n/**\n * Draws all the characters in the text with a really\n * nasty complex gritty text rendering algorithm logic stuff.\n */\nvoid Text::draw()\n{\n\tSurface::draw();\n\tif (_text.empty() || _font == 0)\n\t{\n\t\treturn;\n\t}\n\n\t// Show text borders for debugging\n\tif (Options::debugUi)\n\t{\n\t\tSDL_Rect r;\n\t\tr.w = getWidth();\n\t\tr.h = getHeight();\n\t\tr.x = 0;\n\t\tr.y = 0;\n\t\tthis->drawRect(&r, 5);\n\t\tr.w-=2;\n\t\tr.h-=2;\n\t\tr.x++;\n\t\tr.y++;\n\t\tthis->drawRect(&r, 0);\n\t}\n\n\tint x = 0, y = 0, line = 0, height = 0;\n\tFont *font = _font;\n\tint color = _color;\n\tbool isAltColor = false;\n\tconst UString &s = _processedText;\n\n\theight = getTextHeight();\n\n\tif (_scroll && (getHeight() - height < 0))\n\t{\n\t\ty = _scrollY;\n\t}\n\telse\n\t{\n\t\tswitch (_valign)\n\t\t{\n\t\tcase ALIGN_TOP:\n\t\t\ty = 0;\n\t\t\tbreak;\n\t\tcase ALIGN_MIDDLE:\n\t\t\ty = (int)ceil((getHeight() - height) / 2.0);\n\t\t\tbreak;\n\t\tcase ALIGN_BOTTOM:\n\t\t\ty = getHeight() - height;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tx = getLineX(line);\n\n\t// Set up text color\n\tint mul = 1;\n\tif (_contrast)\n\t{\n\t\tmul = 3;\n\t}\n\n\t// Set up text direction\n\tint dir = 1;\n\tif (_lang->getTextDirection() == DIRECTION_RTL)\n\t{\n\t\tdir = -1;\n\t}\n\n\t// Invert text by inverting the font palette on index 3 (font palettes use indices 1-5)\n\tint mid = _invert ? 3 : 0;\n\n\t// Draw each letter one by one\n\tfor (UString::const_iterator c = s.begin(); c != s.end(); ++c)\n\t{\n\t\tif (Unicode::isSpace(*c) || *c == '\\t')\n\t\t{\n\t\t\tx += dir * font->getCharSize(*c).w;\n\t\t}\n\t\telse if (Unicode::isLinebreak(*c))\n\t\t{\n\t\t\tline++;\n\t\t\ty += font->getCharSize(*c).h;\n\t\t\tx = getLineX(line);\n\t\t\tif (*c == Unicode::TOK_NL_SMALL)\n\t\t\t{\n\t\t\t\tfont = _small;\n\t\t\t}\n\t\t}\n\t\telse if (*c == Unicode::TOK_COLOR_FLIP)\n\t\t{\n\t\t\tif (isAltColor == false)\n\t\t\t{\n\t\t\t\tcolor = _color2;\n\t\t\t\tisAltColor = true;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tcolor = _color;\n\t\t\t\tisAltColor = false;\n\t\t\t}\n\t\t}\n\t\telse if (*c == Unicode::TOK_CUSTOM_FORMAT)\n\t\t{\n\t\t\tconst auto op = *(c + 1u);\n\t\t\tconst auto arg = *(c + 2u);\n\t\t\tswitch (op)\n\t\t\t{\n\t\t\t\tcase 'C': // custom color like \"\\eC\\x45\"\n\t\t\t\t\tcolor = arg;\n\t\t\t\t\tisAltColor = false;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'c': // specific color like \"\\ecP\" - primary, \"\\ecS\" - secondary\n\t\t\t\t\tif (arg == 'P')\n\t\t\t\t\t{\n\t\t\t\t\t\tcolor = _color;\n\t\t\t\t\t\tisAltColor = false;\n\t\t\t\t\t}\n\t\t\t\t\telse if (arg == 'S')\n\t\t\t\t\t{\n\t\t\t\t\t\tcolor = _color2;\n\t\t\t\t\t\tisAltColor = true;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\t// nothing\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tc += 2;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (dir < 0)\n\t\t\t\tx += dir * font->getCharSize(*c).w;\n\t\t\tauto chr = font->getChar(*c);\n\t\t\tchr.setX(x);\n\t\t\tchr.setY(y);\n\t\t\tShaderDraw<PaletteShift>(ShaderSurface(this, 0, 0), ShaderCrop(chr), ShaderScalar(color), ShaderScalar(mul), ShaderScalar(mid));\n\t\t\tif (dir > 0)\n\t\t\t\tx += dir * font->getCharSize(*c).w;\n\t\t}\n\t}\n}\n\n/**\n * Allows the text to be scrollable via mouse wheel.\n */\nvoid Text::setScrollable(bool scroll)\n{\n\t_scroll = scroll;\n}\n\n/**\n * Handles scrolling.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid Text::mousePress(Action* action, State* state)\n{\n\tInteractiveSurface::mousePress(action, state);\n\tif (_scroll &&\n\t\t(action->getDetails()->button.button == SDL_BUTTON_WHEELUP ||\n\t\taction->getDetails()->button.button == SDL_BUTTON_WHEELDOWN))\n\t{\n\t\tint scrollArea = getHeight() - getTextHeight();\n\t\tif (scrollArea < 0)\n\t\t{\n\t\t\tint scrollAmount = _font->getHeight() + _font->getSpacing();\n\t\t\tif (action->getDetails()->button.button == SDL_BUTTON_WHEELDOWN)\n\t\t\t\tscrollAmount = -scrollAmount;\n\n\t\t\t_scrollY = Clamp(_scrollY + scrollAmount, scrollArea, 0);\n\t\t\t_redraw = true;\n\t\t}\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Interface/Text.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/InteractiveSurface.h\"\n#include <vector>\n#include <string>\n#include \"../Engine/Unicode.h\"\n\nnamespace OpenXcom\n{\n\nclass Font;\nclass Language;\n\nenum TextHAlign { ALIGN_LEFT, ALIGN_CENTER, ALIGN_RIGHT };\nenum TextVAlign { ALIGN_TOP, ALIGN_MIDDLE, ALIGN_BOTTOM };\n\n/**\n * Text string displayed on screen.\n * Takes the characters from a Font and puts them together on screen\n * to display a string of text, taking care of any required aligning\n * or wrapping.\n */\nclass Text : public InteractiveSurface\n{\nprivate:\n\tFont *_big, *_small, *_font, *_fontOrig;\n\tLanguage *_lang;\n\tstd::string _text;\n\tUString _processedText;\n\tstd::vector<int> _lineWidth, _lineHeight;\n\tbool _wrap, _invert, _contrast, _indent, _scroll, _ignoreSeparators;\n\tTextHAlign _align;\n\tTextVAlign _valign;\n\tUint8 _color, _color2;\n\tint _scrollY;\n\n\t/// Processes the contained text.\n\tvoid processText();\n\t/// Gets the X position of a text line.\n\tint getLineX(int line) const;\npublic:\n\t/// Creates a new text with the specified size and position.\n\tText(int width, int height, int x = 0, int y = 0);\n\t/// Cleans up the text.\n\t~Text();\n\t/// Sets the text size to big.\n\tvoid setBig();\n\t/// Sets the text size to small.\n\tvoid setSmall();\n\t/// Gets the text's current font.\n\tFont *getFont() const;\n\t/// Initializes the resources for the text.\n\tvoid initText(Font *big, Font *small, Language *lang) override;\n\t/// Sets the text's string.\n\tvoid setText(const std::string &text);\n\t/// Gets the text's string.\n\tstd::string getText() const;\n\t/// Sets the text's wordwrap setting.\n\tvoid setWordWrap(bool wrap, bool indent = false, bool ignoreSeparators = false);\n\t/// Sets the text's color invert setting.\n\tvoid setInvert(bool invert);\n\t/// Sets the text's high contrast color setting.\n\tvoid setHighContrast(bool contrast) override;\n\t/// Sets the text's horizontal alignment.\n\tvoid setAlign(TextHAlign align);\n\t/// Gets the text's horizontal alignment.\n\tTextHAlign getAlign() const;\n\t/// Sets the text's vertical alignment.\n\tvoid setVerticalAlign(TextVAlign valign);\n\t/// Gets the text's vertical alignment.\n\tTextVAlign getVerticalAlign() const;\n\t/// Sets the text's color.\n\tvoid setColor(Uint8 color) override;\n\t/// Gets the text's color.\n\tUint8 getColor() const;\n\t/// Sets the text's secondary color.\n\tvoid setSecondaryColor(Uint8 color) override;\n\t/// Gets the text's secondary color.\n\tUint8 getSecondaryColor() const;\n\t/// Gets the number of lines in the (wrapped, if wrapping is enabled) text\n\tint getNumLines() const;\n\t/// Gets the rendered text's width.\n\tint getTextWidth(int line = -1) const;\n\t/// Gets the rendered text's height.\n\tint getTextHeight(int line = -1) const;\n\t/// Draws the text.\n\tvoid draw() override;\n\t/// Sets the text's scrollable setting.\n\tvoid setScrollable(bool scroll);\n\t/// Special handling for mouse presses.\n\tvoid mousePress(Action* action, State* state) override;\n};\n\n}\n"
  },
  {
    "path": "src/Interface/TextButton.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"TextButton.h\"\n#include <SDL.h>\n#include <SDL_mixer.h>\n#include \"Text.h\"\n#include \"../Engine/Sound.h\"\n#include \"../Engine/Action.h\"\n#include \"ComboBox.h\"\n\nnamespace OpenXcom\n{\n\nSound *TextButton::soundPress;\n\n/**\n * Sets up a text button with the specified size and position.\n * The text is centered on the button.\n * @param width Width in pixels.\n * @param height Height in pixels.\n * @param x X position in pixels.\n * @param y Y position in pixels.\n */\nTextButton::TextButton(int width, int height, int x, int y) : InteractiveSurface(width, height, x, y), _color(0), _group(0), _contrast(false), _geoscapeButton(false), _comboBox(0)\n{\n\t_text = new Text(width, height, 0, 0);\n\t_text->setSmall();\n\t_text->setAlign(ALIGN_CENTER);\n\t_text->setVerticalAlign(ALIGN_MIDDLE);\n\t_text->setWordWrap(true);\n}\n\n/**\n * Deletes the contained Text.\n */\nTextButton::~TextButton()\n{\n\tdelete _text;\n}\n\nbool TextButton::isButtonHandled(Uint8 button)\n{\n\tif (_comboBox != 0)\n\t{\n\t\treturn (button == SDL_BUTTON_LEFT);\n\t}\n\telse\n\t{\n\t\treturn InteractiveSurface::isButtonHandled(button);\n\t}\n}\n\n/**\n * Changes the color for the button and text.\n * @param color Color value.\n */\nvoid TextButton::setColor(Uint8 color)\n{\n\t_color = color;\n\t_text->setColor(color);\n\t_redraw = true;\n}\n\n/**\n * Returns the color for the button and text.\n * @return Color value.\n */\nUint8 TextButton::getColor() const\n{\n\treturn _color;\n}\n\n/**\n * Changes the color for the text only.\n * @param color Color value.\n */\nvoid TextButton::setTextColor(Uint8 color)\n{\n\t_text->setColor(color);\n\t_redraw = true;\n}\n\n/**\n * Changes the text to use the big-size font.\n */\nvoid TextButton::setBig()\n{\n\t_text->setBig();\n\t_redraw = true;\n}\n\n/**\n * Changes the text to use the small-size font.\n */\nvoid TextButton::setSmall()\n{\n\t_text->setSmall();\n\t_redraw = true;\n}\n\n/**\n * Returns the font currently used by the text.\n * @return Pointer to font.\n */\nFont *TextButton::getFont() const\n{\n\treturn _text->getFont();\n}\n\n/**\n * Changes the various resources needed for text rendering.\n * The different fonts need to be passed in advance since the\n * text size can change mid-text, and the language affects\n * how the text is rendered.\n * @param big Pointer to large-size font.\n * @param small Pointer to small-size font.\n * @param lang Pointer to current language.\n */\nvoid TextButton::initText(Font *big, Font *small, Language *lang)\n{\n\t_text->initText(big, small, lang);\n\t_redraw = true;\n}\n\n/**\n * Enables/disables high contrast color. Mostly used for\n * Battlescape UI.\n * @param contrast High contrast setting.\n */\nvoid TextButton::setHighContrast(bool contrast)\n{\n\t_contrast = contrast;\n\t_text->setHighContrast(contrast);\n\t_redraw = true;\n}\n\n/**\n * Changes the text of the button label.\n * @param text Text string.\n */\nvoid TextButton::setText(const std::string &text)\n{\n\t_text->setText(text);\n\t_redraw = true;\n}\n\n/**\n * Returns the text of the button label.\n * @return Text string.\n */\nstd::string TextButton::getText() const\n{\n\treturn _text->getText();\n}\n\n/**\n * Changes the button group this button belongs to.\n * @param group Pointer to the pressed button pointer in the group.\n * Null makes it a regular button.\n */\nvoid TextButton::setGroup(TextButton **group)\n{\n\t_group = group;\n\t_redraw = true;\n}\n\n/**\n * Replaces a certain amount of colors in the surface's palette.\n * @param colors Pointer to the set of colors.\n * @param firstcolor Offset of the first color to replace.\n * @param ncolors Amount of colors to replace.\n */\nvoid TextButton::setPalette(const SDL_Color *colors, int firstcolor, int ncolors)\n{\n\tSurface::setPalette(colors, firstcolor, ncolors);\n\t_text->setPalette(colors, firstcolor, ncolors);\n}\n\n/**\n * Draws the labeled button.\n * The colors are inverted if the button is pressed.\n */\nvoid TextButton::draw()\n{\n\tSurface::draw();\n\tSDL_Rect square;\n\n\tint mul = 1;\n\tif (_contrast)\n\t{\n\t\tmul = 2;\n\t}\n\n\tint color = _color + 1 * mul;\n\n\tsquare.x = 0;\n\tsquare.y = 0;\n\tsquare.w = getWidth();\n\tsquare.h = getHeight();\n\n\tfor (int i = 0; i < 5; ++i)\n\t{\n\t\tdrawRect(&square, color);\n\n\t\tif (i % 2 == 0)\n\t\t{\n\t\t\tsquare.x++;\n\t\t\tsquare.y++;\n\t\t}\n\t\tsquare.w--;\n\t\tsquare.h--;\n\n\t\tswitch (i)\n\t\t{\n\t\tcase 0:\n\t\t\tcolor = _color + 5 * mul;\n\t\t\tsetPixel(square.w, 0, color);\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\tcolor = _color + 2 * mul;\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\tcolor = _color + 4 * mul;\n\t\t\tsetPixel(square.w+1, 1, color);\n\t\t\tbreak;\n\t\tcase 3:\n\t\t\tcolor = _color + 3 * mul;\n\t\t\tbreak;\n\t\tcase 4:\n\t\t\tif (_geoscapeButton)\n\t\t\t{\n\t\t\t\tsetPixel(0, 0, _color);\n\t\t\t\tsetPixel(1, 1, _color);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tbool press;\n\tif (_group == 0)\n\t\tpress = isButtonPressed();\n\telse\n\t\tpress = (*_group == this);\n\n\tif (press)\n\t{\n\t\tif (_geoscapeButton)\n\t\t{\n\t\t\tthis->invert(_color + 2 * mul);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tthis->invert(_color + 3 * mul);\n\t\t}\n\t}\n\t_text->setInvert(press);\n\n\t_text->blit(this->getSurface());\n}\n\n/**\n * Sets the button as the pressed button if it's part of a group.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid TextButton::mousePress(Action *action, State *state)\n{\n\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT && _group != 0)\n\t{\n\t\tTextButton *old = *_group;\n\t\t*_group = this;\n\t\tif (old != 0)\n\t\t\told->draw();\n\t\tdraw();\n\t}\n\n\tif (isButtonHandled(action->getDetails()->button.button))\n\t{\n\t\tif (soundPress != 0 && _group == 0 &&\n\t\t\taction->getDetails()->button.button != SDL_BUTTON_WHEELUP && action->getDetails()->button.button != SDL_BUTTON_WHEELDOWN)\n\t\t{\n\t\t\tsoundPress->play(Mix_GroupAvailable(0));\n\t\t}\n\n\t\tif (_comboBox)\n\t\t{\n\t\t\t_comboBox->toggle(false, false);\n\t\t}\n\n\t\tdraw();\n\t\t//_redraw = true;\n\t}\n\tInteractiveSurface::mousePress(action, state);\n}\n\n/**\n * Sets the button as the released button.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid TextButton::mouseRelease(Action *action, State *state)\n{\n\tif (isButtonHandled(action->getDetails()->button.button))\n\t{\n\t\tdraw();\n\t\t//_redraw = true;\n\t}\n\tInteractiveSurface::mouseRelease(action, state);\n}\n\n/**\n * Hooks up the button to work as part of an existing combobox,\n * toggling its state when it's pressed.\n * @param comboBox Pointer to ComboBox.\n */\nvoid TextButton::setComboBox(ComboBox *comboBox)\n{\n\t_comboBox = comboBox;\n\tif (_comboBox)\n\t{\n\t\t_text->setX(-6);\n\t}\n\telse\n\t{\n\t\t_text->setX(0);\n\t}\n}\n\nvoid TextButton::setWidth(int width)\n{\n\tSurface::setWidth(width);\n\t_text->setWidth(width);\n}\n\nvoid TextButton::setHeight(int height)\n{\n\tSurface::setHeight(height);\n\t_text->setHeight(height);\n}\n\nvoid TextButton::setGeoscapeButton(bool geo)\n{\n\t_geoscapeButton = geo;\n}\n\n}\n"
  },
  {
    "path": "src/Interface/TextButton.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/InteractiveSurface.h\"\n\nnamespace OpenXcom\n{\n\nclass Text;\nclass Font;\nclass Language;\nclass Sound;\nclass ComboBox;\n\n/**\n * Coloured button with a text label.\n * Drawn to look like a 3D-shaped box with text on top,\n * responds to mouse clicks. Can be attached to a group of\n * buttons to turn it into a radio button (only one button\n * pushed at a time).\n */\nclass TextButton : public InteractiveSurface\n{\nprivate:\n\tUint8 _color;\n\tText *_text;\n\tTextButton **_group;\n\tbool _contrast, _geoscapeButton;\n\tComboBox *_comboBox;\n\t// for use by RuleInterface\n\tvoid setSecondaryColor(Uint8 color)  override { setTextColor(color); }\nprotected:\n\tbool isButtonHandled(Uint8 button = 0) override;\npublic:\n\tstatic Sound *soundPress;\n\t/// Creates a new text button with the specified size and position.\n\tTextButton(int width, int height, int x = 0, int y = 0);\n\t/// Cleans up the text button.\n\t~TextButton();\n\t/// Sets the text button's color.\n\tvoid setColor(Uint8 color) override;\n\t/// Gets the text button's color.\n\tUint8 getColor() const;\n\t/// Sets the text button's text color.\n\tvoid setTextColor(Uint8 color);\n\t/// Sets the text size to big.\n\tvoid setBig();\n\t/// Sets the text size to small.\n\tvoid setSmall();\n\t/// Gets the text button's current font.\n\tFont *getFont() const;\n\t/// Initializes the text edit's resources.\n\tvoid initText(Font *big, Font *small, Language *lang) override;\n\t/// Sets the text button's high contrast color setting.\n\tvoid setHighContrast(bool contrast) override;\n\t/// Sets the text button's text.\n\tvoid setText(const std::string &text);\n\t/// Gets the text button's text.\n\tstd::string getText() const;\n\t/// Sets the text button's group.\n\tvoid setGroup(TextButton **group);\n\t/// Sets the text button's palette.\n\tvoid setPalette(const SDL_Color *colors, int firstcolor = 0, int ncolors = 256) override;\n\t/// Draws the text button.\n\tvoid draw() override;\n\t/// Special handling for mouse presses.\n\tvoid mousePress(Action *action, State *state) override;\n\t/// Special handling for mouse releases.\n\tvoid mouseRelease(Action *action, State *state) override;\n\t/// Attaches this button to a combobox.\n\tvoid setComboBox(ComboBox *comboBox);\n\tvoid setWidth(int width) override;\n\tvoid setHeight(int height) override;\n\tvoid setGeoscapeButton(bool geo);\n};\n\n}\n"
  },
  {
    "path": "src/Interface/TextEdit.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"TextEdit.h\"\n#include <cmath>\n#include \"../Engine/Action.h\"\n#include \"../Engine/Font.h\"\n#include \"../Engine/Timer.h\"\n#include \"../Engine/Options.h\"\n#include \"../fallthrough.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Sets up a blank text edit with the specified size and position.\n * @param state Pointer to state the text edit belongs to.\n * @param width Width in pixels.\n * @param height Height in pixels.\n * @param x X position in pixels.\n * @param y Y position in pixels.\n */\nTextEdit::TextEdit(State *state, int width, int height, int x, int y) : InteractiveSurface(width, height, x, y),\n\t_blink(true), _modal(true), _drawBackground(true),\n\t_char('A'), _caretPos(0), _textEditConstraint(TEC_NONE),\n\t_change(0), _enter(0), _state(state)\n{\n\t_isFocused = false;\n\t_text = new Text(width, height, 0, 0);\n\t_timer = new Timer(100);\n\t_timer->onTimer((SurfaceHandler)&TextEdit::blink);\n\t_caret = new Text(16, 17, 0, 0);\n\t_caret->setText(\"|\");\n}\n\n/**\n * Deletes contents.\n */\nTextEdit::~TextEdit()\n{\n\tdelete _text;\n\tdelete _caret;\n\tdelete _timer;\n\t// In case it was left focused\n\tSDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL);\n\t_state->setModal(0);\n}\n\n/**\n * Passes events to internal components.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid TextEdit::handle(Action *action, State *state)\n{\n\tInteractiveSurface::handle(action, state);\n\tif (_isFocused && _modal && action->getDetails()->type == SDL_MOUSEBUTTONDOWN &&\n\t\t(action->getAbsoluteXMouse() < getX() || action->getAbsoluteXMouse() >= getX() + getWidth() ||\n\t\t action->getAbsoluteYMouse() < getY() || action->getAbsoluteYMouse() >= getY() + getHeight()))\n\t{\n\t\tsetFocus(false);\n\t}\n}\n\n/**\n * Controls the blinking animation when\n * the text edit is focused.\n * @param focus True if focused, false otherwise.\n * @param modal True to lock input to this control, false otherwise.\n */\nvoid TextEdit::setFocus(bool focus, bool modal)\n{\n\t_modal = modal;\n\tif (focus != _isFocused)\n\t{\n\t\t_redraw = true;\n\t\tInteractiveSurface::setFocus(focus);\n\t\tif (_isFocused)\n\t\t{\n\t\t\tSDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);\n\t\t\t_caretPos = _value.length();\n\t\t\t_blink = true;\n\t\t\t_timer->start();\n\t\t\tif (_modal)\n\t\t\t\t_state->setModal(this);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_blink = false;\n\t\t\t_timer->stop();\n\t\t\tSDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL);\n\t\t\tif (_modal)\n\t\t\t\t_state->setModal(0);\n\t\t}\n\t}\n}\n\n/**\n * Changes the text edit to use the big-size font.\n */\nvoid TextEdit::setBig()\n{\n\t_text->setBig();\n\t_caret->setBig();\n}\n\n/**\n * Changes the text edit to use the small-size font.\n */\nvoid TextEdit::setSmall()\n{\n\t_text->setSmall();\n\t_caret->setSmall();\n}\n\n/**\n * Changes the various fonts for the text edit to use.\n * The different fonts need to be passed in advance since the\n * text size can change mid-text.\n * @param big Pointer to large-size font.\n * @param small Pointer to small-size font.\n * @param lang Pointer to current language.\n */\nvoid TextEdit::initText(Font *big, Font *small, Language *lang)\n{\n\t_text->initText(big, small, lang);\n\t_caret->initText(big, small, lang);\n}\n\n/**\n * Changes the string displayed on screen.\n * @param text Text string.\n */\nvoid TextEdit::setText(const std::string &text)\n{\n\t_value = Unicode::convUtf8ToUtf32(text);\n\t_caretPos = _value.length();\n\t_redraw = true;\n}\n\n/**\n * Returns the string displayed on screen.\n * @return Text string.\n */\nstd::string TextEdit::getText() const\n{\n\treturn Unicode::convUtf32ToUtf8(_value);\n}\n\n/**\n * Enables/disables text wordwrapping. When enabled, lines of\n * text are automatically split to ensure they stay within the\n * drawing area, otherwise they simply go off the edge.\n * @param wrap Wordwrapping setting.\n */\nvoid TextEdit::setWordWrap(bool wrap)\n{\n\t_text->setWordWrap(wrap);\n}\n\n/**\n * Enables/disables color inverting. Mostly used to make\n * button text look pressed along with the button.\n * @param invert Invert setting.\n */\nvoid TextEdit::setInvert(bool invert)\n{\n\t_text->setInvert(invert);\n\t_caret->setInvert(invert);\n}\n\n/**\n * Enables/disables high contrast color. Mostly used for\n * Battlescape text.\n * @param contrast High contrast setting.\n */\nvoid TextEdit::setHighContrast(bool contrast)\n{\n\t_text->setHighContrast(contrast);\n\t_caret->setHighContrast(contrast);\n}\n\n/**\n * Changes the way the text is aligned horizontally\n * relative to the drawing area.\n * @param align Horizontal alignment.\n */\nvoid TextEdit::setAlign(TextHAlign align)\n{\n\t_text->setAlign(align);\n}\n\n/**\n * Changes the way the text is aligned vertically\n * relative to the drawing area.\n * @param valign Vertical alignment.\n */\nvoid TextEdit::setVerticalAlign(TextVAlign valign)\n{\n\t_text->setVerticalAlign(valign);\n}\n\n/**\n * Restricts the text to only numerical input or signed numerical input.\n * @param constraint TextEditConstraint to be applied.\n */\nvoid TextEdit::setConstraint(TextEditConstraint constraint)\n{\n\t_textEditConstraint = constraint;\n}\n\n/**\n * Changes the color used to render the text. Unlike regular graphics,\n * fonts are greyscale so they need to be assigned a specific position\n * in the palette to be displayed.\n * @param color Color value.\n */\nvoid TextEdit::setColor(Uint8 color)\n{\n\t_text->setColor(color);\n\t_caret->setColor(color);\n}\n\n/**\n * Returns the color used to render the text.\n * @return Color value.\n */\nUint8 TextEdit::getColor() const\n{\n\treturn _text->getColor();\n}\n\n/**\n * Changes the secondary color used to render the text. The text\n * switches between the primary and secondary color whenever there's\n * a 0x01 in the string.\n * @param color Color value.\n */\nvoid TextEdit::setSecondaryColor(Uint8 color)\n{\n\t_text->setSecondaryColor(color);\n}\n\n/**\n * Returns the secondary color used to render the text.\n * @return Color value.\n */\nUint8 TextEdit::getSecondaryColor() const\n{\n\treturn _text->getSecondaryColor();\n}\n\n/**\n * Replaces a certain amount of colors in the text edit's palette.\n * @param colors Pointer to the set of colors.\n * @param firstcolor Offset of the first color to replace.\n * @param ncolors Amount of colors to replace.\n */\nvoid TextEdit::setPalette(const SDL_Color *colors, int firstcolor, int ncolors)\n{\n\tSurface::setPalette(colors, firstcolor, ncolors);\n\t_text->setPalette(colors, firstcolor, ncolors);\n\t_caret->setPalette(colors, firstcolor, ncolors);\n}\n\n/**\n * Keeps the animation timers running.\n */\nvoid TextEdit::think()\n{\n\t_timer->think(0, this);\n}\n\n/**\n * Plays the blinking animation when the\n * text edit is focused.\n */\nvoid TextEdit::blink()\n{\n\t_blink = !_blink;\n\t_redraw = true;\n}\n\n/**\n * Adds a flashing | caret to the text\n * to show when it's focused and editable.\n */\nvoid TextEdit::draw()\n{\n\tSurface::draw();\n\tUString newValue = _value;\n\tif (Options::keyboardMode == KEYBOARD_OFF)\n\t{\n\t\tif (_isFocused && _blink)\n\t\t{\n\t\t\tnewValue += _char;\n\t\t}\n\t}\n\t_text->setText(Unicode::convUtf32ToUtf8(newValue));\n\tclear();\n\n\t// TODO: this whole thing is old and ugly, rework later\n\tif (_enter && _drawBackground)\n\t{\n\t\tSDL_Rect square;\n\t\tsquare.x = 0;\n\t\tsquare.y = 0;\n\t\tsquare.w = getWidth();\n\t\tsquare.h = getHeight();\n\t\tdrawRect(&square, getColor());\n\t}\n\n\t_text->blit(this->getSurface());\n\tif (Options::keyboardMode == KEYBOARD_ON)\n\t{\n\t\tif (_isFocused && _blink)\n\t\t{\n\t\t\tint x = 0;\n\t\t\tswitch (_text->getAlign())\n\t\t\t{\n\t\t\tcase ALIGN_LEFT:\n\t\t\t\tx = 0;\n\t\t\t\tbreak;\n\t\t\tcase ALIGN_CENTER:\n\t\t\t\tx = (_text->getWidth() - _text->getTextWidth()) / 2;\n\t\t\t\tbreak;\n\t\t\tcase ALIGN_RIGHT:\n\t\t\t\tx = _text->getWidth() - _text->getTextWidth();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tfor (size_t i = 0; i < _caretPos; ++i)\n\t\t\t{\n\t\t\t\tx += _text->getFont()->getCharSize(_value[i]).w;\n\t\t\t}\n\t\t\t_caret->setX(x);\n\t\t\tint y = 0;\n\t\t\tswitch (_text->getVerticalAlign())\n\t\t\t{\n\t\t\tcase ALIGN_TOP:\n\t\t\t\ty = 0;\n\t\t\t\tbreak;\n\t\t\tcase ALIGN_MIDDLE:\n\t\t\t\ty = (int)ceil((getHeight() - _text->getTextHeight()) / 2.0);\n\t\t\t\tbreak;\n\t\t\tcase ALIGN_BOTTOM:\n\t\t\t\ty = getHeight() - _text->getTextHeight();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t_caret->setY(y);\n\t\t\t_caret->blit(this->getSurface());\n\t\t}\n\t}\n}\n\n/**\n * Checks if adding a certain character to\n * the text edit will exceed the maximum width.\n * Used to make sure user input stays within bounds.\n * @param c Character to add.\n * @return True if it exceeds, False if it doesn't.\n */\nbool TextEdit::exceedsMaxWidth(UCode c) const\n{\n\tint w = 0;\n\tUString s = _value;\n\n\ts += c;\n\tfor (UString::const_iterator i = s.begin(); i < s.end(); ++i)\n\t{\n\t\tw += _text->getFont()->getCharSize(*i).w;\n\t}\n\n\treturn (w > getWidth());\n}\n\n/**\n * Checks if input key character is valid to\n * be inserted at caret position in the text edit\n * without breaking the text edit constraint.\n * @param c Character to validate.\n * @return True if character can be inserted, False if it cannot.\n */\nbool TextEdit::isValidChar(UCode c) const\n{\n\tswitch (_textEditConstraint)\n\t{\n\tcase TEC_NUMERIC_POSITIVE:\n\t\treturn c >= '0' && c <= '9';\n\n\t// If constraint is \"(signed) numeric\", need to check:\n\t// - user does not input a character before '-' or '+'\n\t// - user enter either figure anywhere, or a sign at first position\n\tcase TEC_NUMERIC:\n\t\tif (_caretPos > 0)\n\t\t{\n\t\t\treturn c >= '0' && c <= '9';\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn ((c >= '0' && c <= '9') || c == '+' || c == '-') &&\n\t\t\t\t\t(_value.empty() || (_value[0] != '+' && _value[0] != '-'));\n\t\t}\n\n\tcase TEC_NONE:\n\t\treturn (c >= ' ' && c <= '~') || c >= 160;\n\n\tdefault:\n\t\treturn false;\n\t}\n}\n\n/**\n * Focuses the text edit when it's pressed on.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid TextEdit::mousePress(Action *action, State *state)\n{\n\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT)\n\t{\n\t\tif (!_isFocused)\n\t\t{\n\t\t\tsetFocus(true);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tdouble mouseX = action->getRelativeXMouse();\n\t\t\tdouble scaleX = action->getXScale();\n\t\t\tdouble w = 0;\n\t\t\tint c = 0;\n\t\t\tfor (UString::iterator i = _value.begin(); i < _value.end(); ++i)\n\t\t\t{\n\t\t\t\tif (mouseX <= w)\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tw += (double)_text->getFont()->getCharSize(*i).w / 2 * scaleX;\n\t\t\t\tif (mouseX <= w)\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tc++;\n\t\t\t\tw += (double) _text->getFont()->getCharSize(*i).w / 2 * scaleX;\n\t\t\t}\n\t\t\t_caretPos = c;\n\t\t}\n\t}\n\tInteractiveSurface::mousePress(action, state);\n}\n\n/**\n * Changes the text edit according to keyboard input, and\n * unfocuses the text if Enter is pressed.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid TextEdit::keyboardPress(Action *action, State *state)\n{\n\tbool enterPressed = false;\n\tif (Options::keyboardMode == KEYBOARD_OFF)\n\t{\n\t\tswitch (action->getDetails()->key.keysym.sym)\n\t\t{\n\t\tcase SDLK_UP:\n\t\t\t_char++;\n\t\t\tif (_char > '~')\n\t\t\t{\n\t\t\t\t_char = ' ';\n\t\t\t}\n\t\t\tbreak;\n\t\tcase SDLK_DOWN:\n\t\t\t_char--;\n\t\t\tif (_char < ' ')\n\t\t\t{\n\t\t\t\t_char = '~';\n\t\t\t}\n\t\t\tbreak;\n\t\tcase SDLK_LEFT:\n\t\t\tif (!_value.empty())\n\t\t\t{\n\t\t\t\t_value.resize(_value.length() - 1);\n\t\t\t}\n\t\t\tbreak;\n\t\tcase SDLK_RIGHT:\n\t\t\tif (!exceedsMaxWidth(_char))\n\t\t\t{\n\t\t\t\t_value += _char;\n\t\t\t}\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t}\n\telse if (Options::keyboardMode == KEYBOARD_ON)\n\t{\n\t\tswitch (action->getDetails()->key.keysym.sym)\n\t\t{\n\t\tcase SDLK_LEFT:\n\t\t\tif (_caretPos > 0)\n\t\t\t{\n\t\t\t\t_caretPos--;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase SDLK_RIGHT:\n\t\t\tif (_caretPos < _value.length())\n\t\t\t{\n\t\t\t\t_caretPos++;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase SDLK_HOME:\n\t\t\t_caretPos = 0;\n\t\t\tbreak;\n\t\tcase SDLK_END:\n\t\t\t_caretPos = _value.length();\n\t\t\tbreak;\n\t\tcase SDLK_BACKSPACE:\n\t\t\tif (_caretPos > 0)\n\t\t\t{\n\t\t\t\t_value.erase(_caretPos - 1, 1);\n\t\t\t\t_caretPos--;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase SDLK_DELETE:\n\t\t\tif (_caretPos < _value.length())\n\t\t\t{\n\t\t\t\t_value.erase(_caretPos, 1);\n\t\t\t}\n\t\t\tbreak;\n\t\tcase SDLK_ESCAPE:\n\t\t\t{\n\t\t\t\t_value = Unicode::convUtf8ToUtf32(\"\");\n\t\t\t\t_caretPos = 0;\n\t\t\t}\n\t\t\tFALLTHROUGH;\n\t\t\t// no break; do the ENTER action too\n\t\tcase SDLK_RETURN:\n\t\tcase SDLK_KP_ENTER:\n\t\t\tif (!_value.empty() || _enter != 0)\n\t\t\t{\n\t\t\t\tenterPressed = true;\n\t\t\t\tsetFocus(false);\n\t\t\t}\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tUCode c = action->getDetails()->key.keysym.unicode;\n\t\t\tif (isValidChar(c) && !exceedsMaxWidth(c))\n\t\t\t{\n\t\t\t\t_value.insert(_caretPos, 1, c);\n\t\t\t\t_caretPos++;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n\t_redraw = true;\n\tif (_change)\n\t{\n\t\t(state->*_change)(action);\n\t}\n\tif (_enter && enterPressed)\n\t{\n\t\t(state->*_enter)(action);\n\t}\n\n\tInteractiveSurface::keyboardPress(action, state);\n}\n\n/**\n * Sets a function to be called every time the text changes.\n * @param handler Action handler.\n */\nvoid TextEdit::onChange(ActionHandler handler)\n{\n\t_change = handler;\n}\n\n/**\n* Sets a function to be called every time ENTER is pressed.\n* @param handler Action handler.\n*/\nvoid TextEdit::onEnter(ActionHandler handler)\n{\n\t_enter = handler;\n}\n\n}\n"
  },
  {
    "path": "src/Interface/TextEdit.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/InteractiveSurface.h\"\n#include \"Text.h\"\n#include \"../Engine/Unicode.h\"\n\nnamespace OpenXcom\n{\n\nclass Timer;\nenum TextEditConstraint { TEC_NONE, TEC_NUMERIC_POSITIVE, TEC_NUMERIC };\n\n/**\n * Editable version of Text.\n * Receives keyboard input to allow the player\n * to change the text himself.\n */\nclass TextEdit : public InteractiveSurface\n{\nprivate:\n\tText *_text, *_caret;\n\tUString _value;\n\tbool _blink, _modal;\n\tbool _drawBackground;\n\tTimer *_timer;\n\tUCode _char;\n\tsize_t _caretPos;\n\tTextEditConstraint _textEditConstraint;\n\tActionHandler _change;\n\tActionHandler _enter;\n\tState *_state;\n\t/// Checks if a character will exceed the maximum width.\n\tbool exceedsMaxWidth(UCode c) const;\n\t/// Checks if character is valid to be inserted at caret position.\n\tbool isValidChar(UCode c) const;\npublic:\n\t/// Creates a new text edit with the specified size and position.\n\tTextEdit(State *state, int width, int height, int x = 0, int y = 0);\n\t/// Cleans up the text edit.\n\t~TextEdit();\n\t/// Handle focus.\n\tvoid handle(Action *action, State *state) override;\n\t/// Sets focus on this text edit.\n\tvoid setFocus(bool focus, bool modal = true) override;\n\t/// Sets the text size to big.\n\tvoid setBig();\n\t/// Sets the text size to small.\n\tvoid setSmall();\n\t/// Initializes the text edit's resources.\n\tvoid initText(Font *big, Font *small, Language *lang) override;\n\t/// Sets the text's string.\n\tvoid setText(const std::string &text);\n\t/// Gets the text edit's string.\n\tstd::string getText() const;\n\t/// Sets the text edit's wordwrap setting.\n\tvoid setWordWrap(bool wrap);\n\t/// Sets the text edit's color invert setting.\n\tvoid setInvert(bool invert);\n\t/// Sets the text edit's high contrast color setting.\n\tvoid setHighContrast(bool contrast) override;\n\t/// Sets the text edit's horizontal alignment.\n\tvoid setAlign(TextHAlign align);\n\t/// Sets the text edit's vertical alignment.\n\tvoid setVerticalAlign(TextVAlign valign);\n\t/// Sets the text edit constraint.\n\tvoid setConstraint(TextEditConstraint constraint);\n\t/// Sets the text edit's color.\n\tvoid setColor(Uint8 color) override;\n\t/// Gets the text edit's color.\n\tUint8 getColor() const;\n\t/// Sets the text edit's secondary color.\n\tvoid setSecondaryColor(Uint8 color) override;\n\t/// Gets the text edit's secondary color.\n\tUint8 getSecondaryColor() const;\n\t/// Sets the text edit's palette.\n\tvoid setPalette(const SDL_Color *colors, int firstcolor = 0, int ncolors = 256) override;\n\t/// Handles the timers.\n\tvoid think() override;\n\t/// Plays the blinking animation.\n\tvoid blink();\n\t/// Draws the text edit.\n\tvoid draw() override;\n\t/// Special handling for mouse presses.\n\tvoid mousePress(Action *action, State *state) override;\n\t/// Special handling for keyboard presses.\n\tvoid keyboardPress(Action *action, State *state) override;\n\t/// Hooks an action handler to when the text changes.\n\tvoid onChange(ActionHandler handler);\n\t/// Sets a function to be called every time ENTER is pressed.\n\tvoid onEnter(ActionHandler handler);\n\t/// Sets the text edit's background drawing setting.\n\tvoid setDrawBackground(bool drawBackground) { _drawBackground = drawBackground; }\n};\n\n}\n"
  },
  {
    "path": "src/Interface/TextList.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"TextList.h\"\n#include <cstdarg>\n#include <cmath>\n#include <algorithm>\n#include \"../Engine/Action.h\"\n#include \"../Engine/Font.h\"\n#include \"../Engine/Palette.h\"\n#include \"../Engine/Options.h\"\n#include \"ArrowButton.h\"\n#include \"ComboBox.h\"\n#include \"ScrollBar.h\"\n#include \"../fmath.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Sets up a blank list with the specified size and position.\n * @param width Width in pixels.\n * @param height Height in pixels.\n * @param x X position in pixels.\n * @param y Y position in pixels.\n */\nTextList::TextList(int width, int height, int x, int y) : InteractiveSurface(width, height, x, y),\n\t_big(0), _small(0), _font(0), _lang(nullptr), _scroll(0), _visibleRows(0), _selRow(0), _color(0), _color2(0),\n\t_dot(false), _selectable(false), _condensed(false), _contrast(false), _wrap(false), _flooding(false), _ignoreSeparators(false),\n\t_bg(0), _selector(0), _margin(0), _scrolling(true), _arrowPos(-1), _scrollPos(4), _arrowType(ARROW_VERTICAL),\n\t_leftClick(0), _leftPress(0), _leftRelease(0), _rightClick(0), _rightPress(0), _rightRelease(0),\n\t_arrowsLeftEdge(0), _arrowsRightEdge(0), _noScrollLeftEdge(0), _noScrollRightEdge(0), _comboBox(0)\n{\n\t_up = new ArrowButton(ARROW_BIG_UP, 13, 14, getX() + getWidth() + _scrollPos, getY());\n\t_up->setVisible(false);\n\t_up->setTextList(this);\n\t_down = new ArrowButton(ARROW_BIG_DOWN, 13, 14, getX() + getWidth() + _scrollPos, getY() + getHeight() - 14);\n\t_down->setVisible(false);\n\t_down->setTextList(this);\n\tint h = std::max(_down->getY() - _up->getY() - _up->getHeight(), 1);\n\t_scrollbar = new ScrollBar(_up->getWidth(), h, getX() + getWidth() + _scrollPos, _up->getY() + _up->getHeight());\n\t_scrollbar->setVisible(false);\n\t_scrollbar->setTextList(this);\n}\n\n/**\n * Deletes all the stuff contained in the list.\n */\nTextList::~TextList()\n{\n\tfor (auto& vec : _texts)\n\t{\n\t\tfor (auto* text : vec)\n\t\t{\n\t\t\tdelete text;\n\t\t}\n\t}\n\tfor (auto* ab : _arrowLeft)\n\t{\n\t\tdelete ab;\n\t}\n\tfor (auto* ab : _arrowRight)\n\t{\n\t\tdelete ab;\n\t}\n\tdelete _selector;\n\tdelete _up;\n\tdelete _down;\n\tdelete _scrollbar;\n}\n\n/**\n * Changes the position of the surface in the X axis.\n * @param x X position in pixels.\n */\nvoid TextList::setX(int x)\n{\n\tSurface::setX(x);\n\t_up->setX(getX() + getWidth() + _scrollPos);\n\t_down->setX(getX() + getWidth() + _scrollPos);\n\t_scrollbar->setX(getX() + getWidth() + _scrollPos);\n\tif (_selector != 0)\n\t\t_selector->setX(getX());\n}\n\n/**\n * Changes the position of the surface in the Y axis.\n * @param y Y position in pixels.\n */\nvoid TextList::setY(int y)\n{\n\tSurface::setY(y);\n\t_up->setY(getY());\n\t_down->setY(getY() + getHeight() - 14);\n\t_scrollbar->setY(_up->getY() + _up->getHeight());\n\tif (_selector != 0)\n\t\t_selector->setY(getY());\n}\n\n/**\n * Gets the arrowsLeftEdge.\n * @return arrowsLeftEdge.\n */\nint TextList::getArrowsLeftEdge()\n{\n\treturn _arrowsLeftEdge;\n}\n\n/**\n * Gets the arrowsRightEdge.\n * @return arrowsRightEdge.\n */\nint TextList::getArrowsRightEdge()\n{\n\treturn _arrowsRightEdge;\n}\n\n/**\n * Unpresses all the arrow buttons.\n * @param state Pointer to running state.\n */\nvoid TextList::unpress(State *state)\n{\n\tInteractiveSurface::unpress(state);\n\tfor (auto* ab : _arrowLeft)\n\t{\n\t\tab->unpress(state);\n\t}\n\tfor (auto* ab : _arrowRight)\n\t{\n\t\tab->unpress(state);\n\t}\n}\n\n/**\n * Changes the color of a specific Text object in the list.\n * @param row Row number.\n * @param column Column number.\n * @param color Text color.\n */\nvoid TextList::setCellColor(size_t row, size_t column, Uint8 color)\n{\n\t_texts[row][column]->setColor(color);\n\t_redraw = true;\n}\n\n/**\n * Changes the text color of a whole row in the list.\n * @param row Row number.\n * @param color Text color.\n */\nvoid TextList::setRowColor(size_t row, Uint8 color)\n{\n\tfor (auto* text : _texts[row])\n\t{\n\t\ttext->setColor(color);\n\t}\n\t_redraw = true;\n}\n\n/**\n * Returns the text of a specific Text object in the list.\n * @param row Row number.\n * @param column Column number.\n * @return Text string.\n */\nstd::string TextList::getCellText(size_t row, size_t column) const\n{\n\treturn _texts[row][column]->getText();\n}\n\n/**\n * Changes the text of a specific Text object in the list.\n * @param row Row number.\n * @param column Column number.\n * @param text Text string.\n */\nvoid TextList::setCellText(size_t row, size_t column, const std::string &text)\n{\n\t_texts[row][column]->setText(text);\n\t_redraw = true;\n}\n\n/**\n * Returns the X position of a specific text column in the list.\n * @param column Column number.\n * @return X position in pixels.\n */\nint TextList::getColumnX(size_t column) const\n{\n\treturn getX() + _texts[0][column]->getX();\n}\n\n/**\n * Returns the Y position of a specific text row in the list.\n * @param row Row number.\n * @return Y position in pixels.\n */\nint TextList::getRowY(size_t row) const\n{\n\treturn getY() + _texts[row][0]->getY();\n}\n\n/**\n * Returns the height of a specific text row in the list.\n * @param row Row number.\n * @return height in pixels.\n */\nint TextList::getTextHeight(size_t row) const\n{\n\treturn _texts[row].front()->getTextHeight();\n}\n\n/**\n * Returns the height of a specific text row in the list.\n * @param row Row number.\n * @return height in pixels.\n */\nint TextList::getNumTextLines(size_t row) const\n{\n\treturn _texts[row].front()->getNumLines();\n}\n\n/**\n * Returns the amount of text rows stored in the list.\n * @return Number of rows.\n */\nsize_t TextList::getTexts() const\n{\n\treturn _texts.size();\n}\n\n/**\n * Returns the amount of physical rows stored in the list.\n * @return Number of rows.\n */\nsize_t TextList::getRowsDoNotUse() const\n{\n\treturn _rows.size();\n}\n\n/**\n * Gets the index of the last row in the list.\n * @return Index of the last row or -1 if the list is empty.\n */\nint TextList::getLastRowIndex() const\n{\n\treturn _texts.size() - 1;\n}\n\n/**\n * Returns the amount of visible rows stored in the list.\n * @return Number of rows.\n */\nsize_t TextList::getVisibleRows() const\n{\n\treturn _visibleRows;\n}\n\n/**\n * Adds a new row of text to the list, automatically creating\n * the required Text objects lined up where they need to be.\n * @param cols Number of columns.\n * @param ... Text for each cell in the new row.\n */\nvoid TextList::addRow(int cols, ...)\n{\n\tva_list args;\n\tint ncols;\n\tva_start(args, cols);\n\tif (cols > 0)\n\t{\n\t\tncols = cols;\n\t}\n\telse\n\t{\n\t\tncols = 1;\n\t}\n\n\tstd::vector<Text*> temp;\n\t// Positions are relative to list surface.\n\tint rowX = 0, rowY = 0, rows = 1, rowHeight = 0;\n\tif (!_texts.empty())\n\t{\n\t\trowY = _texts.back().front()->getY() + _texts.back().front()->getHeight() + _font->getSpacing();\n\t}\n\n\tfor (int i = 0; i < ncols; ++i)\n\t{\n\t\tint width;\n\t\t// Place text\n\t\tif (_flooding)\n\t\t{\n\t\t\twidth = 340;\n\t\t}\n\t\telse\n\t\t{\n\t\t\twidth = _columns[i];\n\t\t}\n\t\tText* txt = new Text(width, _font->getHeight(), _margin + rowX, rowY);\n\t\ttxt->setPalette(this->getPalette());\n\t\ttxt->initText(_big, _small, _lang);\n\t\ttxt->setColor(_color);\n\t\ttxt->setSecondaryColor(_color2);\n\t\tif (_align[i])\n\t\t{\n\t\t\ttxt->setAlign(_align[i]);\n\t\t}\n\t\ttxt->setHighContrast(_contrast);\n\t\tif (_font == _big)\n\t\t{\n\t\t\ttxt->setBig();\n\t\t}\n\t\telse\n\t\t{\n\t\t\ttxt->setSmall();\n\t\t}\n\t\tif (cols > 0)\n\t\t\ttxt->setText(va_arg(args, char*));\n\t\t// grab this before we enable word wrapping so we can use it to calculate\n\t\t// the total row height below\n\t\tint vmargin = _font->getHeight() - txt->getTextHeight();\n\t\t// Wordwrap text if necessary\n\t\tif (_wrap && txt->getTextWidth() > txt->getWidth())\n\t\t{\n\t\t\ttxt->setWordWrap(true, true, _ignoreSeparators);\n\t\t\trows = std::max(rows, txt->getNumLines());\n\t\t}\n\t\trowHeight = std::max(rowHeight, txt->getTextHeight() + vmargin);\n\n\t\t// Places dots between text\n\t\tif (_dot && i < cols - 1)\n\t\t{\n\t\t\tstd::string buf = txt->getText();\n\t\t\tunsigned int w = txt->getTextWidth();\n\t\t\twhile (w < _columns[i])\n\t\t\t{\n\t\t\t\tif (_align[i] != ALIGN_RIGHT)\n\t\t\t\t{\n\t\t\t\t\tw += _font->getChar('.').getCrop()->w + _font->getSpacing();\n\t\t\t\t\tbuf += '.';\n\t\t\t\t}\n\t\t\t\tif (_align[i] != ALIGN_LEFT)\n\t\t\t\t{\n\t\t\t\t\tw += _font->getChar('.').getCrop()->w + _font->getSpacing();\n\t\t\t\t\tbuf.insert(0, 1, '.');\n\t\t\t\t}\n\t\t\t}\n\t\t\ttxt->setText(buf);\n\t\t}\n\n\t\ttemp.push_back(txt);\n\t\tif (_condensed)\n\t\t{\n\t\t\trowX += txt->getTextWidth();\n\t\t}\n\t\telse\n\t\t{\n\t\t\trowX += _columns[i];\n\t\t}\n\t}\n\n\t// ensure all elements in this row are the same height\n\tfor (int i = 0; i < cols; ++i)\n\t{\n\t\ttemp[i]->setHeight(rowHeight);\n\t}\n\n\t_texts.push_back(temp);\n\tfor (int i = 0; i < rows; ++i)\n\t{\n\t\t_rows.push_back(_texts.size() - 1);\n\t}\n\n\t// Place arrow buttons\n\t// Position defined w.r.t. main window, NOT TextList.\n\tif (_arrowPos != -1)\n\t{\n\t\tArrowShape shape1, shape2;\n\t\tif (_arrowType == ARROW_VERTICAL)\n\t\t{\n\t\t\tshape1 = ARROW_SMALL_UP;\n\t\t\tshape2 = ARROW_SMALL_DOWN;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tshape1 = ARROW_SMALL_LEFT;\n\t\t\tshape2 = ARROW_SMALL_RIGHT;\n\t\t}\n\t\tArrowButton *a1 = new ArrowButton(shape1, 11, 8, getX() + _arrowPos, getY());\n\t\ta1->setListButton();\n\t\ta1->setPalette(this->getPalette());\n\t\ta1->setColor(_up->getColor());\n\t\ta1->onMouseClick(_leftClick, 0);\n\t\ta1->onMousePress(_leftPress);\n\t\ta1->onMouseRelease(_leftRelease);\n\t\t_arrowLeft.push_back(a1);\n\t\tArrowButton *a2 = new ArrowButton(shape2, 11, 8, getX() + _arrowPos + 12, getY());\n\t\ta2->setListButton();\n\t\ta2->setPalette(this->getPalette());\n\t\ta2->setColor(_up->getColor());\n\t\ta2->onMouseClick(_rightClick, 0);\n\t\ta2->onMousePress(_rightPress);\n\t\ta2->onMouseRelease(_rightRelease);\n\t\t_arrowRight.push_back(a2);\n\t}\n\n\t_redraw = true;\n\tva_end(args);\n\tupdateArrows();\n}\n\n/**\n * Removes the last row from the text list.\n */\nvoid TextList::removeLastRow()\n{\n\tif (!_texts.empty())\n\t{\n\t\t_texts.pop_back();\n\t}\n\tif (!_rows.empty())\n\t{\n\t\tsize_t toRemove = _rows.back();\n\t\twhile (!_rows.empty() && _rows.back() == toRemove)\n\t\t{\n\t\t\t_rows.pop_back();\n\t\t}\n\t}\n\tif (_arrowPos != -1)\n\t{\n\t\tif (!_arrowLeft.empty())\n\t\t{\n\t\t\t_arrowLeft.pop_back();\n\t\t}\n\t\tif (!_arrowRight.empty())\n\t\t{\n\t\t\t_arrowRight.pop_back();\n\t\t}\n\t}\n\t_redraw = true;\n\tupdateArrows();\n}\n\n/**\n * Changes the columns that the list contains.\n * While rows can be unlimited, columns need to be specified\n * since they can have various widths for lining up the text.\n * @param cols Number of columns.\n * @param ... Width of each column.\n */\nvoid TextList::setColumns(int cols, ...)\n{\n\tva_list args;\n\tva_start(args, cols);\n\n\t_columns.clear();\n\tfor (int i = 0; i < cols; ++i)\n\t{\n\t\t_columns.push_back(va_arg(args, int));\n\t}\n\n\tva_end(args);\n}\n\n/**\n * Replaces a certain amount of colors in the palette of all\n * the text contained in the list.\n * @param colors Pointer to the set of colors.\n * @param firstcolor Offset of the first color to replace.\n * @param ncolors Amount of colors to replace.\n */\nvoid TextList::setPalette(const SDL_Color *colors, int firstcolor, int ncolors)\n{\n\tSurface::setPalette(colors, firstcolor, ncolors);\n\tfor (auto& vec : _texts)\n\t{\n\t\tfor (auto* text : vec)\n\t\t{\n\t\t\ttext->setPalette(colors, firstcolor, ncolors);\n\t\t}\n\t}\n\tfor (auto* ab : _arrowLeft)\n\t{\n\t\tab->setPalette(colors, firstcolor, ncolors);\n\t}\n\tfor (auto* ab : _arrowRight)\n\t{\n\t\tab->setPalette(colors, firstcolor, ncolors);\n\t}\n\tif (_selector != 0)\n\t{\n\t\t_selector->setPalette(colors, firstcolor, ncolors);\n\t}\n\t_up->setPalette(colors, firstcolor, ncolors);\n\t_down->setPalette(colors, firstcolor, ncolors);\n\t_scrollbar->setPalette(colors, firstcolor, ncolors);\n}\n\n/**\n * Changes the resources for the text in the list\n * and calculates the selector and visible amount of rows.\n * @param big Pointer to large-size font.\n * @param small Pointer to small-size font.\n * @param lang Pointer to current language.\n */\nvoid TextList::initText(Font *big, Font *small, Language *lang)\n{\n\t_big = big;\n\t_small = small;\n\t_font = small;\n\t_lang = lang;\n\n\tdelete _selector;\n\t_selector = new Surface(getWidth(), _font->getHeight() + _font->getSpacing(), getX(), getY());\n\t_selector->setPalette(getPalette());\n\t_selector->setVisible(false);\n\n\tupdateVisible();\n\n}\n\n/**\n * Changes the height of the text list.\n * @param height New height in pixels.\n */\nvoid TextList::setHeight(int height)\n{\n\tSurface::setHeight(height);\n\tsetY(getY());\n\tint h = std::max(_down->getY() - _up->getY() - _up->getHeight(), 1);\n\t_scrollbar->setHeight(h);\n\tupdateVisible();\n}\n\n/**\n * Changes the color of the text in the list. This doesn't change\n * the color of existing text, just the color of text added from then on.\n * @param color Color value.\n */\nvoid TextList::setColor(Uint8 color)\n{\n\t_color = color;\n\t_up->setColor(color);\n\t_down->setColor(color);\n\t_scrollbar->setColor(color);\n\tfor (auto& vec : _texts)\n\t{\n\t\tfor (auto* text : vec)\n\t\t{\n\t\t\ttext->setColor(color);\n\t\t}\n\t}\n}\n\n/**\n * Returns the color of the text in the list.\n * @return Color value.\n */\nUint8 TextList::getColor() const\n{\n\treturn _color;\n}\n\n/**\n * Changes the secondary color of the text in the list.\n * @param color Color value.\n */\nvoid TextList::setSecondaryColor(Uint8 color)\n{\n\t_color2 = color;\n}\n\n/**\n * Returns the secondary color of the text in the list.\n * @return Color value.\n */\nUint8 TextList::getSecondaryColor() const\n{\n\treturn _color2;\n}\n\n/**\n * Enables/disables text wordwrapping. When enabled, rows can\n * take up multiple lines of the list, otherwise every row\n * is restricted to one line.\n * @param wrap Wordwrapping setting.\n */\nvoid TextList::setWordWrap(bool wrap)\n{\n\t_wrap = wrap;\n}\n\n/**\n * Enables/disables high contrast color. Mostly used for\n * Battlescape text.\n * @param contrast High contrast setting.\n */\nvoid TextList::setHighContrast(bool contrast)\n{\n\t_contrast = contrast;\n\tfor (auto& vec : _texts)\n\t{\n\t\tfor (auto* text : vec)\n\t\t{\n\t\t\ttext->setHighContrast(contrast);\n\t\t}\n\t}\n\t_scrollbar->setHighContrast(contrast);\n}\n\n/**\n * Changes the horizontal alignment of the text in the list. This doesn't change\n * the alignment of existing text, just the alignment of text added from then on.\n * @param align Horizontal alignment.\n * @param col the column to set the alignment for (defaults to -1, meaning \"all\")\n */\nvoid TextList::setAlign(TextHAlign align, int col)\n{\n\tif (col == -1)\n\t{\n\t\tfor (size_t i = 0; i < _columns.size(); ++i)\n\t\t{\n\t\t\t_align[i] = align;\n\t\t}\n\t}\n\telse\n\t{\n\t\t_align[col] = align;\n\t}\n}\n\n/**\n * If enabled, the text in different columns will be separated by dots.\n * Otherwise, it will only be separated by blank space.\n * @param dot True for dots, False for spaces.\n */\nvoid TextList::setDot(bool dot)\n{\n\t_dot = dot;\n}\n\n/**\n * If enabled, the list will respond to player input,\n * highlighting selected rows and receiving clicks.\n * @param selectable Selectable setting.\n */\nvoid TextList::setSelectable(bool selectable)\n{\n\t_selectable = selectable;\n}\n\n/**\n * Changes the text list to use the big-size font.\n */\nvoid TextList::setBig()\n{\n\t_font = _big;\n\n\tdelete _selector;\n\t_selector = new Surface(getWidth(), _font->getHeight() + _font->getSpacing(), getX(), getY());\n\t_selector->setPalette(getPalette());\n\t_selector->setVisible(false);\n\n\tupdateVisible();\n}\n\n/**\n * Changes the text list to use the small-size font.\n */\nvoid TextList::setSmall()\n{\n\t_font = _small;\n\n\tdelete _selector;\n\t_selector = new Surface(getWidth(), _font->getHeight() + _font->getSpacing(), getX(), getY());\n\t_selector->setPalette(getPalette());\n\t_selector->setVisible(false);\n\n\tupdateVisible();\n}\n\n/**\n * If enabled, the columns will match the text width.\n * Otherwise, they will have a fixed width.\n * @param condensed True for condensed layout, False for table layout.\n */\nvoid TextList::setCondensed(bool condensed)\n{\n\t_condensed = condensed;\n}\n\n/**\n * Returns the currently selected row if the text\n * list is selectable.\n * @return Selected row, -1 if none.\n */\nunsigned int TextList::getSelectedRow() const\n{\n\tif (_rows.empty() || _selRow >= _rows.size())\n\t{\n\t\treturn -1;\n\t}\n\telse\n\t{\n\t\treturn _rows[_selRow];\n\t}\n}\n\n/**\n * Changes the surface used to draw the background of the selector.\n * @param bg New background.\n */\nvoid TextList::setBackground(Surface *bg)\n{\n\t_bg = bg;\n\t_scrollbar->setBackground(_bg);\n}\n\n/**\n * Changes the horizontal margin placed around the text.\n * @param margin Margin in pixels.\n */\nvoid TextList::setMargin(int margin)\n{\n\t_margin = margin;\n}\n\n/**\n * Returns the margin of the text in the list.\n * @return Margin in pixels.\n */\nint TextList::getMargin() const\n{\n\treturn _margin;\n}\n\n/**\n * Sets the no scroll area of the text list.\n * @param left Left edge of the no scroll area.\n * @param right Right edge of the no scroll area.\n */\nvoid TextList::setNoScrollArea(int left, int right)\n{\n\t_noScrollLeftEdge = left;\n\t_noScrollRightEdge = right;\n}\n\n/**\n * Checks if a given coordinate is inside of the no scroll area of the text list.\n * @param x Coordinate to check.\n */\nbool TextList::isInsideNoScrollArea(int x)\n{\n\tif (_noScrollRightEdge > 0)\n\t{\n\t\tif (_noScrollLeftEdge <= x && x <= _noScrollRightEdge)\n\t\t\treturn true;\n\t}\n\treturn false;\n}\n\n/**\n * Changes the color of the arrow buttons in the list.\n * @param color Color value.\n */\nvoid TextList::setArrowColor(Uint8 color)\n{\n\t_up->setColor(color);\n\t_down->setColor(color);\n\t_scrollbar->setColor(color);\n}\n\n/**\n * Sets the position of the column of arrow buttons\n * in the text list.\n * @param pos X in pixels (-1 to disable).\n * @param type Arrow orientation type.\n */\nvoid TextList::setArrowColumn(int pos, ArrowOrientation type)\n{\n\t_arrowPos = pos;\n\t_arrowType = type;\n\tif (pos == -1)\n\t{\n\t\t// turned off\n\t\t_arrowsLeftEdge = 0;\n\t\t_arrowsRightEdge = 0;\n\t\treturn;\n\t}\n\t_arrowsLeftEdge = getX() + _arrowPos;\n\t_arrowsRightEdge = _arrowsLeftEdge + 12 + 11;\n}\n\n/**\n * Sets a function to be called every time the left arrows are mouse clicked.\n * @param handler Action handler.\n */\nvoid TextList::onLeftArrowClick(ActionHandler handler)\n{\n\t_leftClick = handler;\n\tfor (auto* ab : _arrowLeft)\n\t{\n\t\tab->onMouseClick(handler, 0);\n\t}\n}\n\n/**\n * Sets a function to be called every time the left arrows are mouse pressed.\n * @param handler Action handler.\n */\nvoid TextList::onLeftArrowPress(ActionHandler handler)\n{\n\t_leftPress = handler;\n\tfor (auto* ab : _arrowLeft)\n\t{\n\t\tab->onMousePress(handler);\n\t}\n}\n\n/**\n * Sets a function to be called every time the left arrows are mouse released.\n * @param handler Action handler.\n */\nvoid TextList::onLeftArrowRelease(ActionHandler handler)\n{\n\t_leftRelease = handler;\n\tfor (auto* ab : _arrowLeft)\n\t{\n\t\tab->onMouseRelease(handler);\n\t}\n}\n\n/**\n * Sets a function to be called every time the right arrows are mouse clicked.\n * @param handler Action handler.\n */\nvoid TextList::onRightArrowClick(ActionHandler handler)\n{\n\t_rightClick = handler;\n\tfor (auto* ab : _arrowRight)\n\t{\n\t\tab->onMouseClick(handler, 0);\n\t}\n}\n\n/**\n * Sets a function to be called every time the right arrows are mouse pressed.\n * @param handler Action handler.\n */\nvoid TextList::onRightArrowPress(ActionHandler handler)\n{\n\t_rightPress = handler;\n\tfor (auto* ab : _arrowRight)\n\t{\n\t\tab->onMousePress(handler);\n\t}\n}\n\n/**\n * Sets a function to be called every time the right arrows are mouse released.\n * @param handler Action handler.\n */\nvoid TextList::onRightArrowRelease(ActionHandler handler)\n{\n\t_rightRelease = handler;\n\tfor (auto* ab : _arrowRight)\n\t{\n\t\tab->onMouseRelease(handler);\n\t}\n}\n\n/**\n * Removes all the rows currently stored in the list.\n */\nvoid TextList::clearList()\n{\n\tfor (auto& vec : _texts)\n\t{\n\t\tfor (auto* text : vec)\n\t\t{\n\t\t\tdelete text;\n\t\t}\n\t\tvec.clear();\n\t}\n\tscrollUp(true, false);\n\t_texts.clear();\n\t_rows.clear();\n\t_redraw = true;\n}\n\n/**\n * Scrolls the text in the list up by one row or to the top.\n * @param toMax If true then scrolls to the top of the list. false => one row up\n * @param scrollByWheel If true then use wheel scroll, otherwise scroll normally.\n */\nvoid TextList::scrollUp(bool toMax, bool scrollByWheel, size_t howMany)\n{\n\tif (!_scrolling)\n\t\treturn;\n\tif (_rows.size() > _visibleRows && _scroll > 0)\n\t{\n\t\tif (toMax)\n\t\t{\n\t\t\tscrollTo(0);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (scrollByWheel)\n\t\t\t{\n\t\t\t\tscrollTo(_scroll - std::min((size_t)(Options::mousewheelSpeed), _scroll));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tscrollTo(_scroll - std::min(howMany, _scroll));\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Scrolls the text in the list down by one row or to the bottom.\n * @param toMax If true then scrolls to the bottom of the list. false => one row down\n * @param scrollByWheel If true then use wheel scroll, otherwise scroll normally.\n */\nvoid TextList::scrollDown(bool toMax, bool scrollByWheel, size_t howMany)\n{\n\tif (!_scrolling)\n\t\treturn;\n\tif (_rows.size() > _visibleRows && _scroll < _rows.size() - _visibleRows)\n\t{\n\t\tif (toMax)\n\t\t{\n\t\t\tscrollTo(_rows.size() - _visibleRows);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (scrollByWheel)\n\t\t\t{\n\t\t\t\tscrollTo(_scroll + Options::mousewheelSpeed);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tscrollTo(_scroll + howMany);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Updates the visibility of the arrow buttons according to\n * the current scroll position.\n */\nvoid TextList::updateArrows()\n{\n\t_up->setVisible(_rows.size() > _visibleRows /*&& _scroll > 0*/);\n\t_down->setVisible(_rows.size() > _visibleRows /*&& _scroll < _rows.size() - _visibleRows*/);\n\t_scrollbar->setVisible(_rows.size() > _visibleRows);\n\t_scrollbar->invalidate();\n\t_scrollbar->blit(this->getSurface());\n}\n\n/**\n * Updates the amount of visible rows according to the\n * current list and font size.\n */\nvoid TextList::updateVisible()\n{\n\t_visibleRows = 0;\n\tfor (int y = 0; y < getHeight(); y += _font->getHeight() + _font->getSpacing())\n\t{\n\t\t_visibleRows++;\n\t}\n\tupdateArrows();\n}\n\n/**\n * Changes whether the list can be scrolled.\n * @param scrolling True to allow scrolling, false otherwise.\n * @param scrollPos Custom X position for the scroll buttons.\n */\nvoid TextList::setScrolling(bool scrolling, int scrollPos)\n{\n\t_scrolling = scrolling;\n\tif (scrollPos != _scrollPos)\n\t{\n\t\t_scrollPos = scrollPos;\n\t\t_up->setX(getX() + getWidth() + _scrollPos);\n\t\t_down->setX(getX() + getWidth() + _scrollPos);\n\t\t_scrollbar->setX(getX() + getWidth() + _scrollPos);\n\t}\n}\n\n/**\n * Draws the text list and all the text contained within.\n */\nvoid TextList::draw()\n{\n\tSurface::draw();\n\tint y = 0;\n\tif (!_rows.empty())\n\t{\n\t\t// for wrapped items, offset the draw height above the visible surface\n\t\t// so that the correct row appears at the top\n\t\tfor (int row = _scroll; row > 0 && _rows[row] == _rows[row - 1]; --row)\n\t\t{\n\t\t\ty -= _font->getHeight() + _font->getSpacing();\n\t\t}\n\t\tfor (size_t i = _rows[_scroll]; i < _texts.size() && i < _rows[_scroll] + _visibleRows; ++i)\n\t\t{\n\t\t\tfor (auto* text : _texts[i])\n\t\t\t{\n\t\t\t\ttext->setY(y);\n\t\t\t\ttext->blit(this->getSurface());\n\t\t\t}\n\t\t\tif (!_texts[i].empty())\n\t\t\t{\n\t\t\t\ty += _texts[i].front()->getHeight() + _font->getSpacing();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\ty += _font->getHeight() + _font->getSpacing();\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Blits the text list and selector.\n * @param surface Pointer to surface to blit onto.\n */\nvoid TextList::blit(SDL_Surface *surface)\n{\n\tif (_visible && !_hidden)\n\t{\n\t\t_selector->blit(surface);\n\t}\n\tSurface::blit(surface);\n\tif (_visible && !_hidden)\n\t{\n\t\tif (_arrowPos != -1 && !_rows.empty())\n\t\t{\n\t\t\tint y = getY();\n\t\t\tfor (int row = _scroll; row > 0 && _rows[row] == _rows[row - 1]; --row)\n\t\t\t{\n\t\t\t\ty -= _font->getHeight() + _font->getSpacing();\n\t\t\t}\n\t\t\tint maxY = getY() + getHeight();\n\t\t\tfor (size_t i = _rows[_scroll]; i < _texts.size() && i < _rows[_scroll] + _visibleRows && y < maxY; ++i)\n\t\t\t{\n\t\t\t\t_arrowLeft[i]->setY(y);\n\t\t\t\t_arrowRight[i]->setY(y);\n\n\t\t\t\tif (y >= getY())\n\t\t\t\t{\n\t\t\t\t\t// only blit arrows that belong to texts that have their first row on-screen\n\t\t\t\t\t_arrowLeft[i]->blit(surface);\n\t\t\t\t\t_arrowRight[i]->blit(surface);\n\t\t\t\t}\n\n\t\t\t\tif (!_texts[i].empty())\n\t\t\t\t{\n\t\t\t\t\ty += _texts[i].front()->getHeight() + _font->getSpacing();\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\ty += _font->getHeight() + _font->getSpacing();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t_up->blit(surface);\n\t\t_down->blit(surface);\n\t\t_scrollbar->blit(surface);\n\t}\n}\n\n/**\n * Passes events to arrow buttons.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid TextList::handle(Action *action, State *state)\n{\n\tInteractiveSurface::handle(action, state);\n\t_up->handle(action, state);\n\t_down->handle(action, state);\n\t_scrollbar->handle(action, state);\n\tif (_arrowPos != -1 && !_rows.empty())\n\t{\n\t\tsize_t startArrowIdx = _rows[_scroll];\n\t\tif (0 < _scroll && _rows[_scroll] == _rows[_scroll - 1])\n\t\t{\n\t\t\t// arrows for first partially-visible line of text are off-screen; don't process them\n\t\t\t++startArrowIdx;\n\t\t}\n\t\tsize_t endArrowIdx = _rows[_scroll] + 1;\n\t\tsize_t endRow = std::min(_rows.size(), _scroll + _visibleRows);\n\t\tfor (size_t i = _scroll + 1; i < endRow; ++i)\n\t\t{\n\t\t\tif (_rows[i] != _rows[i - 1])\n\t\t\t{\n\t\t\t\t++endArrowIdx;\n\t\t\t}\n\t\t}\n\t\tfor (size_t i = startArrowIdx; i < endArrowIdx; ++i)\n\t\t{\n\t\t\t_arrowLeft[i]->handle(action, state);\n\t\t\t_arrowRight[i]->handle(action, state);\n\t\t}\n\t}\n\t// scrolling by keyboard\n\tif (action->getDetails()->type == SDL_KEYDOWN &&\n\t\t_rows.size() > _visibleRows &&\n\t\t(state->hasOnlyOneScrollableTextList() || isMouseCursorOverMe(state)))\n\t{\n\t\tif (action->getDetails()->key.keysym.sym == SDLK_PAGEDOWN)\n\t\t{\n\t\t\tscrollDown(false, false, _visibleRows);\n\t\t}\n\t\telse if (action->getDetails()->key.keysym.sym == SDLK_PAGEUP)\n\t\t{\n\t\t\tscrollUp(false, false, _visibleRows);\n\t\t}\n\t}\n}\n\nbool TextList::isMouseCursorOverMe(State* state) const\n{\n\tif (state->getCursorX() < _x ||\n\t\tstate->getCursorX() > _x + _width ||\n\t\tstate->getCursorY() < _y ||\n\t\tstate->getCursorY() > _y + _height)\n\t{\n\t\treturn false;\n\t}\n\treturn true;\n}\n\n/**\n * Passes ticks to arrow buttons.\n */\nvoid TextList::think()\n{\n\tInteractiveSurface::think();\n\t_up->think();\n\t_down->think();\n\t_scrollbar->think();\n\tfor (auto* ab : _arrowLeft)\n\t{\n\t\tab->think();\n\t}\n\tfor (auto* ab : _arrowRight)\n\t{\n\t\tab->think();\n\t}\n}\n\n/**\n * Ignores any mouse clicks that aren't on a row.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid TextList::mousePress(Action *action, State *state)\n{\n\tbool allowScroll = true;\n\tif (Options::changeValueByMouseWheel != 0)\n\t{\n\t\tallowScroll = (action->getAbsoluteXMouse() < _arrowsLeftEdge || action->getAbsoluteXMouse() > _arrowsRightEdge);\n\t}\n\tif (isInsideNoScrollArea(action->getAbsoluteXMouse()))\n\t{\n\t\tallowScroll = false;\n\t}\n\tif (allowScroll)\n\t{\n\t\tif (action->getDetails()->button.button == SDL_BUTTON_WHEELUP) scrollUp(false, true);\n\t\telse if (action->getDetails()->button.button == SDL_BUTTON_WHEELDOWN) scrollDown(false, true);\n\t}\n\tif (_selectable)\n\t{\n\t\tif (_selRow < _rows.size())\n\t\t{\n\t\t\tInteractiveSurface::mousePress(action, state);\n\t\t}\n\t}\n\telse\n\t{\n\t\tInteractiveSurface::mousePress(action, state);\n\t}\n}\n\n/*\n * Ignores any mouse clicks that aren't on a row.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid TextList::mouseRelease(Action *action, State *state)\n{\n\tif (_selectable)\n\t{\n\t\tif (_selRow < _rows.size())\n\t\t{\n\t\t\tInteractiveSurface::mouseRelease(action, state);\n\t\t}\n\t}\n\telse\n\t{\n\t\tInteractiveSurface::mouseRelease(action, state);\n\t}\n}\n\n/**\n * Ignores any mouse clicks that aren't on a row.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid TextList::mouseClick(Action *action, State *state)\n{\n\tif (_selectable)\n\t{\n\t\tif (_selRow < _rows.size())\n\t\t{\n\t\t\tInteractiveSurface::mouseClick(action, state);\n\t\t\tif (_comboBox && action->getDetails()->button.button == SDL_BUTTON_LEFT)\n\t\t\t{\n\t\t\t\t_comboBox->setSelected(_selRow);\n\t\t\t\t_comboBox->toggle(false, true);\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\tInteractiveSurface::mouseClick(action, state);\n\t}\n}\n\n/**\n * Selects the row the mouse is over.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid TextList::mouseOver(Action *action, State *state)\n{\n\tif (_selectable)\n\t{\n\t\tint rowHeight = _font->getHeight() + _font->getSpacing(); //theoretical line height\n\t\t_selRow = std::max(0, (int)(_scroll + (int)floor(action->getRelativeYMouse() / (rowHeight * action->getYScale()))));\n\t\tif (_selRow < _rows.size())\n\t\t{\n\t\t\tText *selText = _texts[_rows[_selRow]].front();\n\t\t\tint y = getY() + selText->getY();\n\t\t\tint actualHeight = selText->getHeight() + _font->getSpacing(); //current line height\n\t\t\tif (y < getY() || y + actualHeight > getY() + getHeight())\n\t\t\t{\n\t\t\t\tactualHeight /= 2;\n\t\t\t}\n\t\t\tif (y < getY())\n\t\t\t{\n\t\t\t\ty = getY();\n\t\t\t}\n\t\t\tif (_selector->getHeight() != actualHeight)\n\t\t\t{\n\t\t\t\t// resizing doesn't work, but recreating does, so let's do that!\n\t\t\t\tdelete _selector;\n\t\t\t\t_selector = new Surface(getWidth(), actualHeight, getX(), y);\n\t\t\t\t_selector->setPalette(getPalette());\n\t\t\t}\n\t\t\t_selector->setY(y);\n\t\t\t_selector->copy(_bg);\n\t\t\tif (_contrast)\n\t\t\t{\n\t\t\t\t_selector->offsetBlock(-5);\n\t\t\t}\n\t\t\telse if (_comboBox)\n\t\t\t{\n\t\t\t\t_selector->offset(+1, Palette::backPos);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_selector->offsetBlock(-10);\n\t\t\t}\n\t\t\t_selector->setVisible(true);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_selector->setVisible(false);\n\t\t}\n\t}\n\n\tInteractiveSurface::mouseOver(action, state);\n}\n\n/**\n * Deselects the row.\n * @param action Pointer to an action.\n * @param state State that the action handlers belong to.\n */\nvoid TextList::mouseOut(Action *action, State *state)\n{\n\tif (_selectable)\n\t{\n\t\t_selector->setVisible(false);\n\t}\n\n\tInteractiveSurface::mouseOut(action, state);\n}\n\n/*\n * get the scroll depth.\n * @return scroll depth.\n */\nsize_t TextList::getScroll()\n{\n\treturn _scroll;\n}\n\n/*\n * set the scroll depth.\n * @param scroll set the scroll depth to this.\n */\nvoid TextList::scrollTo(size_t scroll)\n{\n\tif (!_scrolling)\n\t\treturn;\n\tif (_rows.size() <= _visibleRows)\n\t\treturn;\n\t_scroll = Clamp(scroll, (size_t)(0), _rows.size() - _visibleRows);\n\tdraw(); // can't just set _redraw here because reasons\n\tupdateArrows();\n}\n\n/**\n * Hooks up the button to work as part of an existing combobox,\n * updating the selection when it's pressed.\n * @param comboBox Pointer to combobox.\n */\nvoid TextList::setComboBox(ComboBox *comboBox)\n{\n\t_comboBox = comboBox;\n}\n\n/**\n * Gets the combobox that this list is attached to, if any.\n * @return the attached combobox.\n */\nComboBox *TextList::getComboBox() const\n{\n\treturn _comboBox;\n}\n\nvoid TextList::setBorderColor(Uint8 color)\n{\n\t_up->setColor(color);\n\t_down->setColor(color);\n\t_scrollbar->setColor(color);\n}\n\nint TextList::getScrollbarColor()\n{\n\treturn _scrollbar->getColor();\n}\n\nbool TextList::isScrollbarVisible() const\n{\n\treturn _scrollbar->getVisible();\n}\n\nvoid TextList::setFlooding(bool flooding)\n{\n\t_flooding = flooding;\n}\n\nvoid TextList::setIgnoreSeparators(bool ignoreSeparators)\n{\n\t_ignoreSeparators = ignoreSeparators;\n}\n\n}\n"
  },
  {
    "path": "src/Interface/TextList.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <vector>\n#include <map>\n#include \"../Engine/InteractiveSurface.h\"\n#include \"Text.h\"\n\nnamespace OpenXcom\n{\n\nenum ArrowOrientation { ARROW_VERTICAL, ARROW_HORIZONTAL };\n\nclass ArrowButton;\nclass ComboBox;\nclass ScrollBar;\n\n/**\n * List of Text's split into columns.\n * Contains a set of Text's that are automatically lined up by\n * rows and columns, like a big table, making it easy to manage\n * them together.\n */\nclass TextList : public InteractiveSurface\n{\nprivate:\n\tstd::vector< std::vector<Text*> > _texts;\n\tstd::vector<size_t> _columns, _rows;\n\tFont *_big, *_small, *_font;\n\tLanguage *_lang;\n\tsize_t _scroll, _visibleRows, _selRow;\n\tUint8 _color, _color2;\n\tstd::map<int, TextHAlign> _align;\n\tbool _dot, _selectable, _condensed, _contrast, _wrap, _flooding, _ignoreSeparators;\n\tSurface *_bg, *_selector;\n\tArrowButton *_up, *_down;\n\tScrollBar *_scrollbar;\n\tint _margin;\n\tbool _scrolling;\n\tstd::vector<ArrowButton*> _arrowLeft, _arrowRight;\n\tint _arrowPos, _scrollPos;\n\tArrowOrientation _arrowType;\n\tActionHandler _leftClick, _leftPress, _leftRelease, _rightClick, _rightPress, _rightRelease;\n\tint _arrowsLeftEdge, _arrowsRightEdge;\n\tint _noScrollLeftEdge, _noScrollRightEdge;\n\tComboBox *_comboBox;\n\n\t/// Updates the arrow buttons.\n\tvoid updateArrows();\n\t/// Updates the visible rows.\n\tvoid updateVisible();\npublic:\n\t/// Creates a text list with the specified size and position.\n\tTextList(int width, int height, int x = 0, int y = 0);\n\t/// Cleans up the text list.\n\t~TextList();\n\t/// Sets the X position of the surface.\n\tvoid setX(int x) override;\n\t/// Sets the Y position of the surface.\n\tvoid setY(int y) override;\n\t/// Gets the arrowsLeftEdge.\n\tint getArrowsLeftEdge();\n\t/// Gets the arrowsRightEdge.\n\tint getArrowsRightEdge();\n\t/// Unpresses the surface.\n\tvoid unpress(State *state) override;\n\t/// Sets the text color of a certain cell.\n\tvoid setCellColor(size_t row, size_t column, Uint8 color);\n\t/// Sets the text color of a certain row.\n\tvoid setRowColor(size_t row, Uint8 color);\n\t/// Gets the text of a certain cell.\n\tstd::string getCellText(size_t row, size_t column) const;\n\t/// Sets the text of a certain cell.\n\tvoid setCellText(size_t row, size_t column, const std::string &text);\n\t/// Gets the X position of a certain column.\n\tint getColumnX(size_t column) const;\n\t/// Gets the Y position of a certain row.\n\tint getRowY(size_t row) const;\n\t/// Gets the height of the row text in pixels\n\tint getTextHeight(size_t row) const;\n\t/// Gets the number of lines in the wrapped text for the specified row\n\tint getNumTextLines(size_t row) const;\n\t/// Gets the amount of text in the list.\n\tsize_t getTexts() const;\n\t/// Gets the amount of rows in the list.\n\tsize_t getRowsDoNotUse() const;\n\t/// Gets the index of the last row in the list.\n\tint getLastRowIndex() const;\n\t/// Gets the amount of visible rows in the list.\n\tsize_t getVisibleRows() const;\n\t/// Adds a new row to the text list.\n\tvoid addRow(int cols, ...);\n\t/// Removes the last row from the text list.\n\tvoid removeLastRow();\n\t/// Sets the columns in the text list.\n\tvoid setColumns(int cols, ...);\n\t/// Sets the palette of the text list.\n\tvoid setPalette(const SDL_Color *colors, int firstcolor = 0, int ncolors = 256) override;\n\t/// Initializes the resources for the text list.\n\tvoid initText(Font *big, Font *small, Language *lang) override;\n\t/// Sets the height of the surface.\n\tvoid setHeight(int height) override;\n\t/// Sets the text color of the text list.\n\tvoid setColor(Uint8 color) override;\n\t/// Gets the text color of the text list.\n\tUint8 getColor() const;\n\t/// Sets the secondary color of the text list.\n\tvoid setSecondaryColor(Uint8 color) override;\n\t/// Gets the secondary color of the text list.\n\tUint8 getSecondaryColor() const;\n\t/// Sets the text list's wordwrap setting.\n\tvoid setWordWrap(bool wrap);\n\t/// Sets the text list's high contrast color setting.\n\tvoid setHighContrast(bool contrast) override;\n\t/// Sets the text horizontal alignment of the text list.\n\tvoid setAlign(TextHAlign align, int col = -1);\n\t/// Sets whether to separate columns with dots.\n\tvoid setDot(bool dot);\n\t/// Sets whether the list is selectable.\n\tvoid setSelectable(bool selectable);\n\t/// Sets the text size to big.\n\tvoid setBig();\n\t/// Sets the text size to small.\n\tvoid setSmall();\n\t/// Sets whether to condense columns instead of a table like layout.\n\tvoid setCondensed(bool condensed);\n\t/// Sets the background for the selector.\n\tvoid setBackground(Surface *bg);\n\t/// Gets the selected row in the list.\n\tunsigned int getSelectedRow() const;\n\t/// Sets the margin of the text list.\n\tvoid setMargin(int margin);\n\t/// Gets the margin of the text list.\n\tint getMargin() const;\n\t/// Sets the no scroll area of the text list.\n\tvoid setNoScrollArea(int left, int right);\n\t/// Checks if a given coordinate is inside of the no scroll area of the text list.\n\tbool isInsideNoScrollArea(int x);\n\t/// Sets the arrow color of the text list.\n\tvoid setArrowColor(Uint8 color);\n\t/// Sets the arrow column of the text list.\n\tvoid setArrowColumn(int pos, ArrowOrientation type);\n\t/// Hooks an action handler to a mouse click on the left arrows.\n\tvoid onLeftArrowClick(ActionHandler handler);\n\t/// Hooks an action handler to a mouse press over the left arrows.\n\tvoid onLeftArrowPress(ActionHandler handler);\n\t/// Hooks an action handler to a mouse release over the left arrows.\n\tvoid onLeftArrowRelease(ActionHandler handler);\n\t/// Hooks an action handler to a mouse click on the right arrows.\n\tvoid onRightArrowClick(ActionHandler handler);\n\t/// Hooks an action handler to a mouse press over the right arrows.\n\tvoid onRightArrowPress(ActionHandler handler);\n\t/// Hooks an action handler to a mouse release over the right arrows.\n\tvoid onRightArrowRelease(ActionHandler handler);\n\t/// Clears the list.\n\tvoid clearList();\n\t/// Scrolls the list up.\n\tvoid scrollUp(bool toMax, bool scrollByWheel = false, size_t howMany = 1);\n\t/// Scrolls the list down.\n\tvoid scrollDown(bool toMax, bool scrollByWheel = false, size_t howMany = 1);\n\t/// Sets the list scrolling.\n\tvoid setScrolling(bool scrolling, int scrollPos = 4);\n\t/// Draws the text onto the text list.\n\tvoid draw() override;\n\t/// Blits the text list onto another surface.\n\tvoid blit(SDL_Surface *surface) override;\n\t/// Thinks arrow buttons.\n\tvoid think() override;\n\t/// Handles arrow buttons.\n\tvoid handle(Action *action, State *state) override;\n\tbool isMouseCursorOverMe(State* state) const;\n\t/// Special handling for mouse presses.\n\tvoid mousePress(Action *action, State *state) override;\n\t/// Special handling for mouse releases.\n\tvoid mouseRelease(Action *action, State *state) override;\n\t/// Special handling for mouse clicks.\n\tvoid mouseClick(Action *action, State *state) override;\n\t/// Special handling for mouse hovering.\n\tvoid mouseOver(Action *action, State *state) override;\n\t/// Special handling for mouse hovering out.\n\tvoid mouseOut(Action *action, State *state) override;\n\t/// get the scroll depth\n\tsize_t getScroll();\n\t/// set the scroll depth\n\tvoid scrollTo(size_t scroll);\n\t/// Attaches this button to a combobox.\n\tvoid setComboBox(ComboBox *comboBox);\n\t/// Check for a combobox.\n\tComboBox *getComboBox() const;\n\tvoid setBorderColor(Uint8 color) override;\n\tint getScrollbarColor();\n\tbool isScrollbarVisible() const;\n\t/// Allows the cell to flood into other columns.\n\tvoid setFlooding(bool flooding);\n\t/// Treat separators as spaces (false) or as normal text (true)?\n\tvoid setIgnoreSeparators(bool ignoreSeparators);\n};\n\n}\n"
  },
  {
    "path": "src/Interface/ToggleTextButton.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"ToggleTextButton.h\"\n#include \"TextButton.h\"\n\n\nnamespace OpenXcom\n{\n\nToggleTextButton::ToggleTextButton(int width, int height, int x, int y) : TextButton(width, height, x, y), _originalColor(-1), _invertedColor(-1), _fakeGroup(0)\n{\n\t_isPressed = false;\n\tTextButton::setGroup(&_fakeGroup);\n}\n\n\nToggleTextButton::~ToggleTextButton(void)\n{\n}\n\n/// handle mouse clicks by toggling the button state; use _fakeGroup to trick TextButton into drawing the right thing\nvoid ToggleTextButton::mousePress(Action *action, State *state)\n{\n\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT || action->getDetails()->button.button == SDL_BUTTON_RIGHT)\n\t{\n\t\t_isPressed = !_isPressed;\n\t\t_fakeGroup = _isPressed ? this : 0; // this is the trick that makes TextButton stick\n\t\tif (_isPressed && _invertedColor > -1) TextButton::setColor(_invertedColor);\n\t\telse TextButton::setColor(_originalColor);\n\t}\n\n\tInteractiveSurface::mousePress(action, state); // skip TextButton's code as it will try to set *_group\n\tdraw();\n}\n\n/// set the _isPressed state of the button and force it to redraw\nvoid ToggleTextButton::setPressed(bool pressed)\n{\n\t_isPressed = pressed;\n\t_fakeGroup = _isPressed ? this : 0;\n\tif (_isPressed && _invertedColor > -1) TextButton::setColor(_invertedColor);\n\telse TextButton::setColor(_originalColor);\n\t_redraw = true;\n}\n\nvoid ToggleTextButton::setColor(Uint8 color)\n{\n\t_originalColor = color;\n\tTextButton::setColor(color);\n}\n\n/// When this is set, Surface::invert() is called with the value from mid when it's time to invert the button\nvoid ToggleTextButton::setInvertColor(Uint8 color)\n{\n\t_invertedColor = color;\n\t_fakeGroup = 0;\n\t_redraw = true;\n}\n\n/// handle draw() in case we need to paint the button a garish color\nvoid ToggleTextButton::draw()\n{\n\tif (_invertedColor > -1) _fakeGroup = 0; // nevermind, TextButton. We'll invert the surface ourselves.\n\tTextButton::draw();\n\n\tif (_invertedColor > -1 && _isPressed)\n\t{\n\t\tthis->invert(_invertedColor + 4);\n\t}\n}\n\n\n\n\n}\n"
  },
  {
    "path": "src/Interface/ToggleTextButton.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"TextButton.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass ToggleTextButton :\n\tpublic TextButton\n{\nprivate:\n\tbool _isPressed;\n\tint _originalColor, _invertedColor;\n\tTextButton *_fakeGroup;\n\npublic:\n\n\tvoid draw() override;\n\tvoid mousePress(Action *action, State *state) override;\n\tvoid setPressed(bool pressed);\n\tbool getPressed() const { return _isPressed; }\n\tvoid setColor(Uint8 color) override;\n\tvoid setInvertColor(Uint8 color);\n\tToggleTextButton(int width, int height, int x, int y);\n\t~ToggleTextButton(void);\n};\n\n}\n"
  },
  {
    "path": "src/Interface/Window.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Window.h\"\n#include <SDL.h>\n#include <SDL_mixer.h>\n#include \"../fmath.h\"\n#include \"../Engine/Timer.h\"\n#include \"../Engine/Sound.h\"\n#include \"../Engine/RNG.h\"\n\nnamespace OpenXcom\n{\n\nconst double Window::POPUP_SPEED = 0.05;\n\nSound *Window::soundPopup[3];\n\n/**\n * Sets up a blank window with the specified size and position.\n * @param state Pointer to state the window belongs to.\n * @param width Width in pixels.\n * @param height Height in pixels.\n * @param x X position in pixels.\n * @param y Y position in pixels.\n * @param popup Popup animation.\n */\nWindow::Window(State *state, int width, int height, int x, int y, WindowPopup popup) : Surface(width, height, x, y),\n\t_dx(-x), _dy(-y), _bg(0), _color(0), _popup(popup), _popupStep(0.0), _state(state), _contrast(false), _screen(false), _thinBorder(false), _innerColor(0), _mute(false)\n{\n\t_timer = new Timer(10);\n\t_timer->onTimer((SurfaceHandler)&Window::popup);\n\n\tif (_popup == POPUP_NONE)\n\t{\n\t\t_popupStep = 1.0;\n\t}\n\telse\n\t{\n\t\tsetHidden(true);\n\t\t_timer->start();\n\t\tif (_state != 0)\n\t\t{\n\t\t\t_screen = state->isScreen();\n\t\t\tif (_screen)\n\t\t\t\t_state->toggleScreen();\n\t\t}\n\t}\n}\n\n/**\n * Deletes timers.\n */\nWindow::~Window()\n{\n\tdelete _timer;\n}\n\n/**\n * Changes the surface used to draw the background of the window.\n * @param bg New background.\n */\nvoid Window::setBackground(const Surface *bg)\n{\n\t_bg = bg;\n\t_redraw = true;\n}\n\n/**\n * Changes the color used to draw the shaded border.\n * @param color Color value.\n */\nvoid Window::setColor(Uint8 color)\n{\n\t_color = color;\n\t_redraw = true;\n}\n\n/**\n * Returns the color used to draw the shaded border.\n * @return Color value.\n */\nUint8 Window::getColor() const\n{\n\treturn _color;\n}\n\n/**\n * Enables/disables high contrast color. Mostly used for\n * Battlescape UI.\n * @param contrast High contrast setting.\n */\nvoid Window::setHighContrast(bool contrast)\n{\n\t_contrast = contrast;\n\t_redraw = true;\n}\n\n/**\n * Keeps the animation timers running.\n */\nvoid Window::think()\n{\n\tif (_hidden && _popupStep < 1.0)\n\t{\n\t\t_state->hideAll();\n\t\tsetHidden(false);\n\t}\n\n\t_timer->think(0, this);\n}\n\n/**\n * Plays the window popup animation.\n */\nvoid Window::popup()\n{\n\tif (!_mute && AreSame(_popupStep, 0.0))\n\t{\n\t\tint sound = RNG::seedless(0,2);\n\t\tif (soundPopup[sound] != 0)\n\t\t{\n\t\t\tsoundPopup[sound]->play(Mix_GroupAvailable(0));\n\t\t}\n\t}\n\tif (_popupStep < 1.0)\n\t{\n\t\t_popupStep += POPUP_SPEED;\n\t}\n\telse\n\t{\n\t\tif (_screen)\n\t\t{\n\t\t\t_state->toggleScreen();\n\t\t}\n\t\t_state->showAll();\n\t\t_popupStep = 1.0;\n\t\t_timer->stop();\n\t}\n\t_redraw = true;\n}\n\n/**\n * Draws the bordered window with a graphic background.\n * The background never moves with the window, it's\n * always aligned to the top-left corner of the screen\n * and cropped to fit the inside area.\n */\nvoid Window::draw()\n{\n\tSurface::draw();\n\tSDL_Rect square;\n\n\tif (_popup == POPUP_HORIZONTAL || _popup == POPUP_BOTH)\n\t{\n\t\tsquare.x = (int)((getWidth() - getWidth() * _popupStep) / 2);\n\t\tsquare.w = (int)(getWidth() * _popupStep);\n\t}\n\telse\n\t{\n\t\tsquare.x = 0;\n\t\tsquare.w = getWidth();\n\t}\n\tif (_popup == POPUP_VERTICAL || _popup == POPUP_BOTH)\n\t{\n\t\tsquare.y = (int)((getHeight() - getHeight() * _popupStep) / 2);\n\t\tsquare.h = (int)(getHeight() * _popupStep);\n\t}\n\telse\n\t{\n\t\tsquare.y = 0;\n\t\tsquare.h = getHeight();\n\t}\n\n\tint mul = 1;\n\tif (_contrast)\n\t{\n\t\tmul = 2;\n\t}\n\tUint8 color = _color + 3 * mul;\n\n\tif (_thinBorder)\n\t{\n\t\tcolor = _color + 1 * mul;\n\t\tfor (int i = 0; i < 5; ++i)\n\t\t{\n\t\t\tdrawRect(&square, color);\n\n\t\t\tif (i % 2 == 0)\n\t\t\t{\n\t\t\t\tsquare.x++;\n\t\t\t\tsquare.y++;\n\t\t\t}\n\t\t\tsquare.w--;\n\t\t\tsquare.h--;\n\n\t\t\tswitch (i)\n\t\t\t{\n\t\t\tcase 0:\n\t\t\t\tcolor = _color + 5 * mul;\n\t\t\t\tsetPixel(square.w, 0, color);\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\t\tcolor = _color + 2 * mul;\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\tcolor = _color + 4 * mul;\n\t\t\t\tsetPixel(square.w+1, 1, color);\n\t\t\t\tbreak;\n\t\t\tcase 3:\n\t\t\t\tcolor = _color + 3 * mul;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\tfor (int i = 0; i < 5; ++i)\n\t\t{\n\t\t\tdrawRect(&square, color);\n\t\t\tif (i < 2)\n\t\t\t\tcolor -= 1 * mul;\n\t\t\telse\n\t\t\t\tcolor += 1 * mul;\n\t\t\tsquare.x++;\n\t\t\tsquare.y++;\n\t\t\tif (square.w >= 2)\n\t\t\t\tsquare.w -= 2;\n\t\t\telse\n\t\t\t\tsquare.w = 1;\n\n\t\t\tif (square.h >= 2)\n\t\t\t\tsquare.h -= 2;\n\t\t\telse\n\t\t\t\tsquare.h = 1;\n\t\t}\n\t\tif (_innerColor != 0)\n\t\t{\n\t\t\tdrawRect(&square, _innerColor);\n\t\t}\n\t}\n\n\tif (_bg != 0)\n\t{\n\t\tSurfaceCrop crop = _bg->getCrop();\n\t\tcrop.getCrop()->x = square.x - _dx;\n\t\tcrop.getCrop()->y = square.y - _dy;\n\t\tcrop.getCrop()->w = square.w ;\n\t\tcrop.getCrop()->h = square.h ;\n\t\tcrop.setX(square.x);\n\t\tcrop.setY(square.y);\n\t\tcrop.blit(this);\n\t}\n}\n\n/**\n * Changes the horizontal offset of the surface in the X axis.\n * @param dx X position in pixels.\n */\nvoid Window::setDX(int dx)\n{\n\t_dx = dx;\n}\n\n/**\n * Changes the vertical offset of the surface in the Y axis.\n * @param dy Y position in pixels.\n */\nvoid Window::setDY(int dy)\n{\n\t_dy = dy;\n}\n\n/**\n * Changes the window to have a thin border.\n */\nvoid Window::setThinBorder()\n{\n\t_thinBorder = true;\n}\n\n/**\n * Changes the window to have a custom inner color.\n */\nvoid Window::setInnerColor(Uint8 innerColor)\n{\n\t_innerColor = innerColor;\n}\n\n}\n"
  },
  {
    "path": "src/Interface/Window.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/Surface.h\"\n\nnamespace OpenXcom\n{\n\nclass Timer;\nclass State;\nclass Sound;\n\n/**\n * Enumeration for the type of animation when a window pops up.\n */\nenum WindowPopup { POPUP_NONE, POPUP_HORIZONTAL, POPUP_VERTICAL, POPUP_BOTH };\n\n/**\n * Box with a coloured border and custom background.\n * Pretty much used as the background in most of the interface. In fact\n * it's also used in screens, so it's not really much of a window, just a... box.\n * But box sounds lame.\n */\nclass Window : public Surface\n{\nprivate:\n\tstatic const double POPUP_SPEED;\n\tint _dx, _dy;\n\tconst Surface *_bg;\n\tUint8 _color;\n\tWindowPopup _popup;\n\tdouble _popupStep;\n\tTimer *_timer;\n\tState *_state;\n\tbool _contrast, _screen, _thinBorder;\n\tUint8 _innerColor;\n\tbool _mute;\npublic:\n\tstatic Sound *soundPopup[3];\n\t/// Creates a new window with the specified size and position.\n\tWindow(State *state, int width, int height, int x = 0, int y = 0, WindowPopup popup = POPUP_NONE);\n\t/// Cleans up the window.\n\t~Window();\n\t/// Sets the background surface.\n\tvoid setBackground(const Surface *bg);\n\t/// Sets the border color.\n\tvoid setColor(Uint8 color) override;\n\t/// Gets the border color.\n\tUint8 getColor() const;\n\t/// Sets the high contrast color setting.\n\tvoid setHighContrast(bool contrast) override;\n\t/// Handles the timers.\n\tvoid think() override;\n\t/// Popups the window.\n\tvoid popup();\n\t/// Draws the window.\n\tvoid draw() override;\n\t/// sets the X delta.\n\tvoid setDX(int dx);\n\t/// sets the Y delta.\n\tvoid setDY(int dy);\n\t/// Give this window a thin border.\n\tvoid setThinBorder();\n\t/// Give this window a custom inner color.\n\tvoid setInnerColor(Uint8 innerColor);\n\t/// Mute the window.\n\tvoid mute() { _mute = true; }\n};\n\n}\n"
  },
  {
    "path": "src/Menu/AbandonGameState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"AbandonGameState.h\"\n#include \"../Engine/Sound.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Options.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"MainMenuState.h\"\n#include \"../Engine/Screen.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"SaveGameState.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Abandon Game screen.\n * @param game Pointer to the core game.\n * @param origin Game section that originated this state.\n */\nAbandonGameState::AbandonGameState(OptionsOrigin origin) : _origin(origin)\n{\n\t_screen = false;\n\n\tint x;\n\tif (_origin == OPT_GEOSCAPE)\n\t{\n\t\tx = 20;\n\t}\n\telse\n\t{\n\t\tx = 52;\n\t}\n\n\t// Create objects\n\t_window = new Window(this, 216, 160, x, 20, POPUP_BOTH);\n\t_btnYes = new TextButton(50, 20, x+18, 140);\n\t_btnNo = new TextButton(50, 20, x+148, 140);\n\t_txtTitle = new Text(206, 17, x+5, 70);\n\n\t// Set palette\n\tsetInterface(\"geoscape\", false, _game->getSavedGame() ? _game->getSavedGame()->getSavedBattle() : 0);\n\n\tadd(_window, \"genericWindow\", \"geoscape\");\n\tadd(_btnYes, \"genericButton2\", \"geoscape\");\n\tadd(_btnNo, \"genericButton2\", \"geoscape\");\n\tadd(_txtTitle, \"genericText\", \"geoscape\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"geoscape\");\n\n\t_btnYes->setText(tr(\"STR_YES\"));\n\t_btnYes->onMouseClick((ActionHandler)&AbandonGameState::btnYesClick);\n\t_btnYes->onKeyboardPress((ActionHandler)&AbandonGameState::btnYesClick, Options::keyOk);\n\n\t_btnNo->setText(tr(\"STR_NO\"));\n\t_btnNo->onMouseClick((ActionHandler)&AbandonGameState::btnNoClick);\n\t_btnNo->onKeyboardPress((ActionHandler)&AbandonGameState::btnNoClick, Options::keyCancel);\n\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setBig();\n\t_txtTitle->setText(tr(\"STR_ABANDON_GAME_QUESTION\"));\n\n\tif (_origin == OPT_BATTLESCAPE)\n\t{\n\t\tapplyBattlescapeTheme(\"geoscape\");\n\t}\n}\n\n/**\n *\n */\nAbandonGameState::~AbandonGameState()\n{\n\n}\n\n/**\n * Goes back to the Main Menu.\n * @param action Pointer to an action.\n */\nvoid AbandonGameState::btnYesClick(Action *)\n{\n\t// Reset touch flags\n\t_game->resetTouchButtonFlags();\n\n\tif (_origin == OPT_BATTLESCAPE && _game->getSavedGame()->getSavedBattle()->getAmbientSound() != Mod::NO_SOUND)\n\t\t_game->getMod()->getSoundByDepth(0, _game->getSavedGame()->getSavedBattle()->getAmbientSound())->stopLoop();\n\tif (!_game->getSavedGame()->isIronman())\n\t{\n\t\tScreen::updateScale(Options::geoscapeScale, Options::baseXGeoscape, Options::baseYGeoscape, true);\n\t\t_game->getScreen()->resetDisplay(false);\n\n\t\t_game->setState(new MainMenuState);\n\t\t_game->setSavedGame(0);\n\t}\n\telse\n\t{\n\t\t_game->pushState(new SaveGameState(OPT_GEOSCAPE, SAVE_IRONMAN_END, _palette));\n\t}\n}\n\n/**\n * Closes the window.\n * @param action Pointer to an action.\n */\nvoid AbandonGameState::btnNoClick(Action *)\n{\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Menu/AbandonGameState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include \"OptionsBaseState.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\n\n/**\n * Abandon Game window shown before\n * quitting the game from the Geoscape.\n */\nclass AbandonGameState : public State\n{\nprivate:\n\tOptionsOrigin _origin;\n\tTextButton *_btnYes, *_btnNo;\n\tWindow *_window;\n\tText *_txtTitle;\npublic:\n\t/// Creates the Abandon Game state.\n\tAbandonGameState(OptionsOrigin origin);\n\t/// Cleans up the Abandon Game state.\n\t~AbandonGameState();\n\t/// Handler for clicking the Yes button.\n\tvoid btnYesClick(Action *action);\n\t/// Handler for clicking the No button.\n\tvoid btnNoClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Menu/ConfirmLoadState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ConfirmLoadState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Engine/Options.h\"\n#include \"LoadGameState.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Confirm Load screen.\n * @param game Pointer to the core game.\n * @param origin Game section that originated this state.\n * @param fileName Name of the save file without extension.\n */\nConfirmLoadState::ConfirmLoadState(OptionsOrigin origin, const std::string &fileName) : _origin(origin), _fileName(fileName)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 216, 100, 52, 50, POPUP_BOTH);\n\t_btnYes = new TextButton(50, 20, 70, 120);\n\t_btnNo = new TextButton(50, 20, 200, 120);\n\t_txtText = new Text(204, 58, 58, 60);\n\n\t// Set palette\n\tsetInterface(\"saveMenus\", false, _game->getSavedGame() ? _game->getSavedGame()->getSavedBattle() : 0);\n\n\tadd(_window, \"confirmLoad\", \"saveMenus\");\n\tadd(_btnYes, \"confirmLoad\", \"saveMenus\");\n\tadd(_btnNo, \"confirmLoad\", \"saveMenus\");\n\tadd(_txtText, \"confirmLoad\", \"saveMenus\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"saveMenus\");\n\n\t_btnYes->setText(tr(\"STR_YES\"));\n\t_btnYes->onMouseClick((ActionHandler)&ConfirmLoadState::btnYesClick);\n\t_btnYes->onKeyboardPress((ActionHandler)&ConfirmLoadState::btnYesClick, Options::keyOk);\n\n\t_btnNo->setText(tr(\"STR_NO\"));\n\t_btnNo->onMouseClick((ActionHandler)&ConfirmLoadState::btnNoClick);\n\t_btnNo->onKeyboardPress((ActionHandler)&ConfirmLoadState::btnNoClick, Options::keyCancel);\n\n\t_txtText->setAlign(ALIGN_CENTER);\n\t_txtText->setBig();\n\t_txtText->setWordWrap(true);\n\t_txtText->setText(tr(\"STR_MISSING_CONTENT_PROMPT\"));\n\n\tif (_origin == OPT_BATTLESCAPE)\n\t{\n\t\tapplyBattlescapeTheme(\"saveMenus\");\n\t}\n}\n\n/// Cleans up the confirmation state.\nConfirmLoadState::~ConfirmLoadState()\n{\n}\n\n/**\n * Proceed to load the save.\n * @param action Pointer to an action.\n */\nvoid ConfirmLoadState::btnYesClick(Action *)\n{\n\t_game->popState();\n\t_game->pushState(new LoadGameState(_origin, _fileName, _palette));\n}\n\n/**\n * Abort loading and return to save list.\n * @param action Pointer to an action.\n */\nvoid ConfirmLoadState::btnNoClick(Action *)\n{\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Menu/ConfirmLoadState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include <string>\n#include \"OptionsBaseState.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\n\n/**\n * Confirms loading a save with missing content.\n */\nclass ConfirmLoadState : public State\n{\nprivate:\n\tOptionsOrigin _origin;\n\tstd::string _fileName;\n\tTextButton *_btnYes, *_btnNo;\n\tWindow *_window;\n\tText *_txtText;\npublic:\n\t/// Creates a new confirmation state.\n\tConfirmLoadState(OptionsOrigin origin, const std::string &fileName);\n\t/// Cleans up the confirmation state.\n\tvirtual ~ConfirmLoadState();\n\t/// Handler for clicking the Yes button.\n\tvoid btnYesClick(Action *action);\n\t/// Handler for clicking the No button.\n\tvoid btnNoClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Menu/CutsceneState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"CutsceneState.h\"\n#include \"MainMenuState.h\"\n#include \"SlideshowState.h\"\n#include \"VideoState.h\"\n#include \"../Engine/CrossPlatform.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Logger.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Screen.h\"\n#include \"../Engine/FileMap.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"StatisticsState.h\"\n\nnamespace OpenXcom\n{\n\nCutsceneState::CutsceneState(const std::string &cutsceneId)\n\t: _cutsceneId(cutsceneId)\n{\n\t// empty\n}\n\nCutsceneState::~CutsceneState()\n{\n\t// empty\n}\n\nvoid CutsceneState::init()\n{\n\tState::init();\n\n\t// pop self off stack and replace with actual player state\n\t_game->popState();\n\n\tconst RuleVideo *videoRule = _game->getMod()->getVideo(_cutsceneId, true);\n\tif (_game->getSavedGame() && _game->getSavedGame()->getEnding() != END_NONE)\n\t{\n\t\tif (_game->getSavedGame()->getMonthsPassed() > -1)\n\t\t{\n\t\t\t_game->setState(new StatisticsState);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_game->setSavedGame(0);\n\t\t\t_game->setState(new GoToMainMenuState);\n\t\t}\n\t}\n\n\tbool fmv = false, slide = false;\n\tif (!videoRule->getVideos()->empty())\n\t{\n\t\tfmv = FileMap::fileExists(videoRule->getVideos()->front());\n\t}\n\tif (!videoRule->getSlides()->empty())\n\t{\n\t\tslide = FileMap::fileExists(videoRule->getSlides()->front().imagePath);\n\t}\n\n\tif (fmv && (!slide || Options::preferredVideo == VIDEO_FMV))\n\t{\n\t\t_game->pushState(new VideoState(videoRule->getVideos(), videoRule->getAudioTracks(), videoRule->useUfoAudioSequence()));\n\t}\n\telse if (slide && (!fmv || Options::preferredVideo == VIDEO_SLIDE))\n\t{\n\t\t_game->pushState(new SlideshowState(videoRule->getSlideshowHeader(), videoRule->getSlides()));\n\t}\n\telse\n\t{\n\t\tLog(LOG_WARNING) << \"cutscene definition empty: \" << _cutsceneId;\n\t}\n}\n\nbool CutsceneState::initDisplay()\n{\n\tbool letterboxed = Options::keepAspectRatio;\n\tOptions::keepAspectRatio = true;\n\tOptions::baseXResolution = Screen::ORIGINAL_WIDTH;\n\tOptions::baseYResolution = Screen::ORIGINAL_HEIGHT;\n\t_game->getScreen()->resetDisplay(false);\n\treturn letterboxed;\n}\n\nvoid CutsceneState::resetDisplay(bool wasLetterboxed)\n{\n\tOptions::keepAspectRatio = wasLetterboxed;\n\tScreen::updateScale(Options::geoscapeScale, Options::baseXGeoscape, Options::baseYGeoscape, true);\n\t_game->getScreen()->resetDisplay(false);\n}\n\n}\n"
  },
  {
    "path": "src/Menu/CutsceneState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Shows cutscenes: inspects the relevant rules and loads the appropriate state\n * for showing slideshows or videos.\n */\nclass CutsceneState : public State\n{\nprivate:\n\tstd::string _cutsceneId;\npublic:\n\t/// Creates the CutsceneState.\n\tCutsceneState(const std::string &cutsceneId);\n\t/// Cleans up the CutsceneState.\n\t~CutsceneState();\n\t/// Replace this state on the stack with the real player state.\n\tvoid init() override;\n\n\t// shared utility methods for SlideshowState and VideoState\n\t/// returns whether the display was letterboxed (for restoration in resetDisplay)\n\tstatic bool initDisplay();\n\t/// restores the screen to its original state\n\tstatic void resetDisplay(bool wasLetterboxed);\n};\n\n}\n"
  },
  {
    "path": "src/Menu/DeleteGameState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"DeleteGameState.h\"\n#include \"../Engine/CrossPlatform.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/Options.h\"\n#include \"ErrorMessageState.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Mod/RuleInterface.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Confirmation screen.\n * @param game Pointer to the core game.\n * @param origin Game section that originated this state.\n * @param save Name of the save file to delete.\n */\nDeleteGameState::DeleteGameState(OptionsOrigin origin, const std::string &save) : _origin(origin)\n{\n\t_filename = Options::getMasterUserFolder() + save;\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 256, 100, 32, 50, POPUP_BOTH);\n\t_btnYes = new TextButton(60, 18, 60, 122);\n\t_btnNo = new TextButton(60, 18, 200, 122);\n\t_txtMessage = new Text(246, 32, 37, 70);\n\n\t// Set palette\n\tsetInterface(\"saveMenus\", false, _game->getSavedGame() ? _game->getSavedGame()->getSavedBattle() : 0);\n\n\tadd(_window, \"confirmDelete\", \"saveMenus\");\n\tadd(_btnYes, \"confirmDelete\", \"saveMenus\");\n\tadd(_btnNo, \"confirmDelete\", \"saveMenus\");\n\tadd(_txtMessage, \"confirmDelete\", \"saveMenus\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"saveMenus\");\n\n\t_btnYes->setText(tr(\"STR_YES\"));\n\t_btnYes->onMouseClick((ActionHandler)&DeleteGameState::btnYesClick);\n\t_btnYes->onKeyboardPress((ActionHandler)&DeleteGameState::btnYesClick, Options::keyOk);\n\n\t_btnNo->setText(tr(\"STR_NO\"));\n\t_btnNo->onMouseClick((ActionHandler)&DeleteGameState::btnNoClick);\n\t_btnNo->onKeyboardPress((ActionHandler)&DeleteGameState::btnNoClick, Options::keyCancel);\n\n\t_txtMessage->setAlign(ALIGN_CENTER);\n\t_txtMessage->setBig();\n\t_txtMessage->setWordWrap(true);\n\t_txtMessage->setText(tr(\"STR_IS_IT_OK_TO_DELETE_THE_SAVED_GAME\"));\n\n\tif (_origin == OPT_BATTLESCAPE)\n\t{\n\t\tapplyBattlescapeTheme(\"saveMenus\");\n\t}\n}\n\n/**\n *\n */\nDeleteGameState::~DeleteGameState()\n{\n\n}\n\nvoid DeleteGameState::btnNoClick(Action *)\n{\n\t_game->popState();\n}\n\nvoid DeleteGameState::btnYesClick(Action *)\n{\n\t_game->popState();\n\tif (!CrossPlatform::deleteFile(_filename))\n\t{\n\t\tstd::string error = tr(\"STR_DELETE_UNSUCCESSFUL\");\n\t\tif (_origin != OPT_BATTLESCAPE)\n\t\t\t_game->pushState(new ErrorMessageState(error, _palette, _game->getMod()->getInterface(\"errorMessages\")->getElement(\"geoscapeColor\")->color, \"BACK01.SCR\", _game->getMod()->getInterface(\"errorMessages\")->getElement(\"geoscapePalette\")->color));\n\t\telse\n\t\t\t_game->pushState(new ErrorMessageState(error, _palette, _game->getMod()->getInterface(\"errorMessages\")->getElement(\"battlescapeColor\")->color, \"TAC00.SCR\", _game->getMod()->getInterface(\"errorMessages\")->getElement(\"battlescapePalette\")->color));\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Menu/DeleteGameState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include \"OptionsBaseState.h\"\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\n\n/**\n * window used to confirm save game deletion.\n */\nclass DeleteGameState : public State\n{\nprivate:\n\tTextButton *_btnNo, *_btnYes;\n\tWindow *_window;\n\tText *_txtMessage;\n\tstd::string _filename;\n\tOptionsOrigin _origin;\npublic:\n\t/// Creates the Confirm state.\n\tDeleteGameState(OptionsOrigin origin, const std::string &save);\n\t/// Cleans up the Confirm state.\n\t~DeleteGameState();\n\t/// Handler for clicking the confirm button.\n\tvoid btnYesClick(Action *action);\n\t/// Handler for clicking the cancel button.\n\tvoid btnNoClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Menu/ErrorMessageState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ErrorMessageState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/Palette.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Engine/Options.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in an error window.\n * @param game Pointer to the core game.\n * @param msg Text string for the message to display.\n * @param palette Parent state palette.\n * @param color Color of the UI controls.\n * @param bg Background image.\n * @param bgColor Background color (-1 for Battlescape).\n */\nErrorMessageState::ErrorMessageState(const std::string &msg, SDL_Color *palette, Uint8 color, const std::string &bg, int bgColor, Uint8 color2)\n{\n\tcreate(msg, palette, color, bg, bgColor, color2);\n}\n\n/**\n *\n */\nErrorMessageState::~ErrorMessageState()\n{\n\n}\n\n/**\n * Creates the elements in an error window.\n * @param str Text string for the message to display.\n * @param palette Parent state palette.\n * @param color Color of the UI controls.\n * @param bg Background image.\n * @param bgColor Background color (-1 for Battlescape).\n */\nvoid ErrorMessageState::create(const std::string &str, SDL_Color *palette, Uint8 color, const std::string &bg, int bgColor, Uint8 color2)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 256, 160, 32, 20, POPUP_BOTH);\n\t_btnOk = new TextButton(120, 18, 100, 154);\n\t_txtMessage = new Text(246, 80, 37, 50);\n\n\t// Set palette\n\tsetStatePalette(palette);\n\tif (bgColor != -1)\n\t\tsetStatePalette(_game->getMod()->getPalette(\"BACKPALS.DAT\")->getColors(Palette::blockOffset(bgColor)), Palette::backPos, 16);\n\n\tadd(_window);\n\tadd(_btnOk);\n\tadd(_txtMessage);\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\t_window->setColor(color);\n\t_window->setBackground(_game->getMod()->getSurface(bg));\n\n\t_btnOk->setColor(color);\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&ErrorMessageState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&ErrorMessageState::btnOkClick, Options::keyOk);\n\t_btnOk->onKeyboardPress((ActionHandler)&ErrorMessageState::btnOkClick, Options::keyCancel);\n\n\t_txtMessage->setColor(color);\n\tif (color2 != 0) // just in case, probably not needed\n\t{\n\t\t_txtMessage->setSecondaryColor(color2);\n\t}\n\t_txtMessage->setAlign(ALIGN_CENTER);\n\t_txtMessage->setVerticalAlign(ALIGN_MIDDLE);\n\t_txtMessage->setBig();\n\t_txtMessage->setWordWrap(true);\n\t_txtMessage->setText(str);\n\n\tif (bgColor == -1)\n\t{\n\t\t_window->setHighContrast(true);\n\t\t_btnOk->setHighContrast(true);\n\t\t_txtMessage->setHighContrast(true);\n\t}\n}\n\n/**\n * Closes the window.\n * @param action Pointer to an action.\n */\nvoid ErrorMessageState::btnOkClick(Action *)\n{\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Menu/ErrorMessageState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\n\n/**\n * Generic window used to display error messages.\n */\nclass ErrorMessageState : public State\n{\nprivate:\n\tTextButton *_btnOk;\n\tWindow *_window;\n\tText *_txtMessage;\n\n\tvoid create(const std::string &str, SDL_Color *palette, Uint8 color, const std::string &bg, int bgColor, Uint8 color2);\npublic:\n\t/// Creates the Error state.\n\tErrorMessageState(const std::string &msg, SDL_Color *palette, Uint8 color, const std::string &bg, int bgColor, Uint8 color2 = 0);\n\t/// Cleans up the Error state.\n\t~ErrorMessageState();\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Menu/ListGamesState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <algorithm>\n#include <functional>\n#include \"ListGamesState.h\"\n#include \"../Engine/Logger.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Exception.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Interface/ToggleTextButton.h\"\n#include \"../Interface/ArrowButton.h\"\n#include \"DeleteGameState.h\"\n\nnamespace OpenXcom\n{\n\nstruct compareSaveName\n{\n\tbool _reverse;\n\n\tcompareSaveName(bool reverse) : _reverse(reverse) {}\n\n\tbool operator()(const SaveInfo &a, const SaveInfo &b) const\n\t{\n\t\tif (a.reserved == b.reserved)\n\t\t{\n\t\t\treturn Unicode::naturalCompare(a.displayName, b.displayName);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn _reverse ? b.reserved : a.reserved;\n\t\t}\n\t}\n};\n\nstruct compareSaveTimestamp\n{\n\tbool _reverse;\n\n\tcompareSaveTimestamp(bool reverse) : _reverse(reverse) {}\n\n\tbool operator()(const SaveInfo &a, const SaveInfo &b) const\n\t{\n\t\tif (a.reserved == b.reserved)\n\t\t{\n\t\t\treturn a.timestamp < b.timestamp;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn _reverse ? b.reserved : a.reserved;\n\t\t}\n\t}\n};\n\n/**\n * Initializes all the elements in the Saved Game screen.\n * @param game Pointer to the core game.\n * @param origin Game section that originated this state.\n * @param firstValidRow First row containing saves.\n * @param autoquick Show auto/quick saved games?\n */\nListGamesState::ListGamesState(OptionsOrigin origin, int firstValidRow, bool autoquick) : _origin(origin), _firstValidRow(firstValidRow), _autoquick(autoquick), _sortable(true)\n{\n\t_screen = false;\n\n\tbool isMobile = false;\n#ifdef __MOBILE__\n\tisMobile = true;\n#endif\n\n\t// Create objects\n\t_window = new Window(this, 320, 200, 0, 0, POPUP_BOTH);\n\t_btnCancel = new TextButton(80, 16, 120, 172);\n\t_txtTitle = new Text(310, 17, 5, 7);\n\t_txtDelete = new Text(310, 9, 5, 23);\n\t_txtName = new Text(150, 9, 16, isMobile ? 40 : 32);\n\t_txtDate = new Text(110, 9, 204, isMobile ? 40 : 32);\n\t_lstSaves = new TextList(288, isMobile ? 104 : 112, 8, isMobile ? 50 : 42);\n\t_txtDetails = new Text(288, 16, 16, 156);\n\t_sortName = new ArrowButton(ARROW_NONE, 11, 8, 16, isMobile ? 40 : 32);\n\t_sortDate = new ArrowButton(ARROW_NONE, 11, 8, 204, isMobile ? 40 : 32);\n\t_btnDelete = new ToggleTextButton(288, 16, 16, 23);\n\n\t// Set palette\n\tsetInterface(\"geoscape\", true, _game->getSavedGame() ? _game->getSavedGame()->getSavedBattle() : 0);\n\n\tadd(_window, \"window\", \"saveMenus\");\n\tadd(_btnCancel, \"button\", \"saveMenus\");\n\tadd(_txtTitle, \"text\", \"saveMenus\");\n\tadd(_txtDelete, \"text\", \"saveMenus\");\n\tadd(_txtName, \"text\", \"saveMenus\");\n\tadd(_txtDate, \"text\", \"saveMenus\");\n\tadd(_lstSaves, \"list\", \"saveMenus\");\n\tadd(_txtDetails, \"text\", \"saveMenus\");\n\tadd(_sortName, \"text\", \"saveMenus\");\n\tadd(_sortDate, \"text\", \"saveMenus\");\n\tadd(_btnDelete, \"button\", \"saveMenus\");\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"saveMenus\");\n\n\t_btnCancel->setText(tr(\"STR_CANCEL\"));\n\t_btnCancel->onMouseClick((ActionHandler)&ListGamesState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&ListGamesState::btnCancelClick, Options::keyCancel);\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\n\tif (isMobile)\n\t{\n\t\t_txtDelete->setVisible(false);\n\t\t_btnDelete->setText(tr(\"STR_RIGHT_CLICK_TO_DELETE\"));\n\t}\n\telse\n\t{\n\t\t_btnDelete->setVisible(false);\n\t\t_txtDelete->setAlign(ALIGN_CENTER);\n\t\t_txtDelete->setText(tr(\"STR_RIGHT_CLICK_TO_DELETE\"));\n\t}\n\n\t_txtName->setText(tr(\"STR_NAME\"));\n\n\t_txtDate->setText(tr(\"STR_DATE\"));\n\n\t_lstSaves->setColumns(3, 188, 60, 40);\n\t_lstSaves->setSelectable(true);\n\t_lstSaves->setBackground(_window);\n\t_lstSaves->setMargin(8);\n\t_lstSaves->onMouseOver((ActionHandler)&ListGamesState::lstSavesMouseOver);\n\t_lstSaves->onMouseOut((ActionHandler)&ListGamesState::lstSavesMouseOut);\n\t_lstSaves->onMousePress((ActionHandler)&ListGamesState::lstSavesPress);\n\n\t_txtDetails->setWordWrap(true);\n\t_txtDetails->setText(tr(\"STR_DETAILS\").arg(\"\"));\n\n\t_sortName->setX(_sortName->getX() + _txtName->getTextWidth() + 5);\n\t_sortName->onMouseClick((ActionHandler)&ListGamesState::sortNameClick);\n\n\t_sortDate->setX(_sortDate->getX() + _txtDate->getTextWidth() + 5);\n\t_sortDate->onMouseClick((ActionHandler)&ListGamesState::sortDateClick);\n\n\tupdateArrows();\n}\n\n/**\n *\n */\nListGamesState::~ListGamesState()\n{\n\n}\n\n/**\n * Refreshes the saves list.\n */\nvoid ListGamesState::init()\n{\n\tState::init();\n\n\tif (_origin == OPT_BATTLESCAPE)\n\t{\n\t\tapplyBattlescapeTheme(\"saveMenus\");\n\t}\n\n\ttry\n\t{\n\t\t_saves = SavedGame::getList(_game->getLanguage(), _autoquick);\n\t\t_lstSaves->clearList();\n\t\tsortList(Options::saveOrder);\n\t}\n\tcatch (Exception &e)\n\t{\n\t\tLog(LOG_ERROR) << e.what();\n\t}\n}\n\n/**\n * Updates the sorting arrows based\n * on the current setting.\n */\nvoid ListGamesState::updateArrows()\n{\n\t_sortName->setShape(ARROW_NONE);\n\t_sortDate->setShape(ARROW_NONE);\n\tswitch (Options::saveOrder)\n\t{\n\tcase SORT_NAME_ASC:\n\t\t_sortName->setShape(ARROW_SMALL_UP);\n\t\tbreak;\n\tcase SORT_NAME_DESC:\n\t\t_sortName->setShape(ARROW_SMALL_DOWN);\n\t\tbreak;\n\tcase SORT_DATE_ASC:\n\t\t_sortDate->setShape(ARROW_SMALL_UP);\n\t\tbreak;\n\tcase SORT_DATE_DESC:\n\t\t_sortDate->setShape(ARROW_SMALL_DOWN);\n\t\tbreak;\n\t}\n}\n\n/**\n * Sorts the save game list.\n * @param sort Order to sort the games in.\n */\nvoid ListGamesState::sortList(SaveSort sort)\n{\n\tswitch (sort)\n\t{\n\tcase SORT_NAME_ASC:\n\t\tstd::sort(_saves.begin(), _saves.end(), compareSaveName(false));\n\t\tbreak;\n\tcase SORT_NAME_DESC:\n\t\tstd::sort(_saves.rbegin(), _saves.rend(), compareSaveName(true));\n\t\tbreak;\n\tcase SORT_DATE_ASC:\n\t\tstd::sort(_saves.begin(), _saves.end(), compareSaveTimestamp(false));\n\t\tbreak;\n\tcase SORT_DATE_DESC:\n\t\tstd::sort(_saves.rbegin(), _saves.rend(), compareSaveTimestamp(true));\n\t\tbreak;\n\t}\n\tupdateList();\n}\n\n/**\n * Updates the save game list with the current list\n * of available savegames.\n */\nvoid ListGamesState::updateList()\n{\n\tint row = 0;\n\tint color = _lstSaves->getSecondaryColor();\n\tfor (const auto& saveInfo : _saves)\n\t{\n\t\t_lstSaves->addRow(3, saveInfo.displayName.c_str(), saveInfo.isoDate.c_str(), saveInfo.isoTime.c_str());\n\t\tif (saveInfo.reserved && _origin != OPT_BATTLESCAPE)\n\t\t{\n\t\t\t_lstSaves->setRowColor(row, color);\n\t\t}\n\t\trow++;\n\t}\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid ListGamesState::btnCancelClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Shows the details of the currently hovered save.\n * @param action Pointer to an action.\n */\nvoid ListGamesState::lstSavesMouseOver(Action *)\n{\n\tint sel = _lstSaves->getSelectedRow() - _firstValidRow;\n\tstd::string wstr;\n\tif (sel >= 0 && sel < (int)_saves.size())\n\t{\n\t\twstr = _saves[sel].details;\n\t}\n\t_txtDetails->setText(tr(\"STR_DETAILS\").arg(wstr));\n}\n\n/**\n * Clears the details.\n * @param action Pointer to an action.\n */\nvoid ListGamesState::lstSavesMouseOut(Action *)\n{\n\t_txtDetails->setText(tr(\"STR_DETAILS\").arg(\"\"));\n}\n\n/**\n * Deletes the selected save.\n * @param action Pointer to an action.\n */\nvoid ListGamesState::lstSavesPress(Action *action)\n{\n\tif ((action->getDetails()->button.button == SDL_BUTTON_RIGHT || _btnDelete->getPressed()) && _lstSaves->getSelectedRow() >= _firstValidRow)\n\t{\n\t\t_game->pushState(new DeleteGameState(_origin, _saves[_lstSaves->getSelectedRow() - _firstValidRow].fileName));\n\t}\n}\n\n/**\n * Sorts the saves by name.\n * @param action Pointer to an action.\n */\nvoid ListGamesState::sortNameClick(Action *)\n{\n\tif (_sortable)\n\t{\n\t\tif (Options::saveOrder == SORT_NAME_ASC)\n\t\t{\n\t\t\tOptions::saveOrder = SORT_NAME_DESC;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tOptions::saveOrder = SORT_NAME_ASC;\n\t\t}\n\t\tupdateArrows();\n\t\t_lstSaves->clearList();\n\t\tsortList(Options::saveOrder);\n\t}\n}\n\n/**\n * Sorts the saves by date.\n * @param action Pointer to an action.\n */\nvoid ListGamesState::sortDateClick(Action *)\n{\n\tif (_sortable)\n\t{\n\t\tif (Options::saveOrder == SORT_DATE_ASC)\n\t\t{\n\t\t\tOptions::saveOrder = SORT_DATE_DESC;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tOptions::saveOrder = SORT_DATE_ASC;\n\t\t}\n\t\tupdateArrows();\n\t\t_lstSaves->clearList();\n\t\tsortList(Options::saveOrder);\n\t}\n}\n\nvoid ListGamesState::disableSort()\n{\n\t_sortable = false;\n}\n\n}\n"
  },
  {
    "path": "src/Menu/ListGamesState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include \"OptionsBaseState.h\"\n#include <vector>\n#include \"../Savegame/SavedGame.h\"\n#include \"../Engine/Options.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass TextList;\nclass ArrowButton;\nclass ToggleTextButton;\n\n/**\n * Base class for saved game screens which\n * provides the common layout and listing.\n */\nclass ListGamesState : public State\n{\nprotected:\n\tTextButton *_btnCancel;\n\tWindow *_window;\n\tToggleTextButton* _btnDelete;\n\tText *_txtTitle, *_txtName, *_txtDate, *_txtDelete, *_txtDetails;\n\tTextList *_lstSaves;\n\tArrowButton *_sortName, *_sortDate;\n\tOptionsOrigin _origin;\n\tstd::vector<SaveInfo> _saves;\n\tunsigned int _firstValidRow;\n\tbool _autoquick, _sortable;\n\n\tvoid updateArrows();\npublic:\n\t/// Creates the Saved Game state.\n\tListGamesState(OptionsOrigin origin, int firstValidRow, bool autoquick);\n\t/// Cleans up the Saved Game state.\n\tvirtual ~ListGamesState();\n\t/// Sets up the saves list.\n\tvoid init() override;\n\t/// Sorts the savegame list.\n\tvoid sortList(SaveSort sort);\n\t/// Updates the savegame list.\n\tvirtual void updateList();\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action *action);\n\t/// Handler for moving the mouse over a list item.\n\tvoid lstSavesMouseOver(Action *action);\n\t/// Handler for moving the mouse outside the list borders.\n\tvoid lstSavesMouseOut(Action *action);\n\t/// Handler for clicking the Saves list.\n\tvirtual void lstSavesPress(Action *action);\n\t/// Handler for clicking the Name arrow.\n\tvoid sortNameClick(Action *action);\n\t/// Handler for clicking the Date arrow.\n\tvoid sortDateClick(Action *action);\n\t/// disables the sort buttons.\n\tvoid disableSort();\n};\n\n}\n"
  },
  {
    "path": "src/Menu/ListLoadOriginalState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ListLoadOriginalState.h\"\n#include <sstream>\n#include \"../Savegame/SaveConverter.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Screen.h\"\n#include \"../Engine/Action.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Geoscape/GeoscapeState.h\"\n#include \"../Battlescape/BattlescapeState.h\"\n#include \"ErrorMessageState.h\"\n#include \"../Mod/RuleInterface.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Saved Game screen.\n * @param game Pointer to the core game.\n * @param origin Game section that originated this state.\n */\nListLoadOriginalState::ListLoadOriginalState(OptionsOrigin origin) : _origin(origin)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 320, 200, 0, 0);\n\t_btnNew = new TextButton(80, 16, 60, 172);\n\t_btnCancel = new TextButton(80, 16, 180, 172);\n\t_txtTitle = new Text(310, 17, 5, 7);\n\t_txtName = new Text(160, 9, 36, 24);\n\t_txtTime = new Text(30, 9, 195, 24);\n\t_txtDate = new Text(90, 9, 225, 24);\n\n\t// Set palette\n\tsetInterface(\"geoscape\", true, _game->getSavedGame() ? _game->getSavedGame()->getSavedBattle() : 0);\n\n\tadd(_window, \"window\", \"saveMenus\");\n\tadd(_btnNew, \"button\", \"saveMenus\");\n\tadd(_btnCancel, \"button\", \"saveMenus\");\n\tadd(_txtTitle, \"text\", \"saveMenus\");\n\tadd(_txtName, \"text\", \"saveMenus\");\n\tadd(_txtTime, \"text\", \"saveMenus\");\n\tadd(_txtDate, \"text\", \"saveMenus\");\n\n\tint y = 34;\n\tfor (int i = 0; i < SaveConverter::NUM_SAVES; ++i)\n\t{\n\t\t_btnSlot[i] = new TextButton(24, 12, 10, y-2);\n\t\t_txtSlotName[i] = new Text(160, 9, 36, y);\n\t\t_txtSlotTime[i] = new Text(30, 9, 195, y);\n\t\t_txtSlotDate[i] = new Text(90, 9, 225, y);\n\n\t\tadd(_btnSlot[i], \"button\", \"saveMenus\");\n\t\tadd(_txtSlotName[i], \"list\", \"saveMenus\");\n\t\tadd(_txtSlotTime[i], \"list\", \"saveMenus\");\n\t\tadd(_txtSlotDate[i], \"list\", \"saveMenus\");\n\n\t\ty += 14;\n\t}\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"saveMenus\");\n\n\t_btnNew->setText(tr(\"STR_OPENXCOM\").arg(Options::getActiveMasterInfo()->getVersionDisplay()));\n\t_btnNew->onMouseClick((ActionHandler)&ListLoadOriginalState::btnNewClick);\n\t_btnNew->onKeyboardPress((ActionHandler)&ListLoadOriginalState::btnNewClick, Options::keyCancel);\n\n\t_btnCancel->setText(tr(\"STR_CANCEL\"));\n\t_btnCancel->onMouseClick((ActionHandler)&ListLoadOriginalState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&ListLoadOriginalState::btnCancelClick, Options::keyCancel);\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_SELECT_GAME_TO_LOAD\"));\n\n\t_txtName->setText(tr(\"STR_NAME\"));\n\n\t_txtTime->setText(tr(\"STR_TIME\"));\n\n\t_txtDate->setText(tr(\"STR_DATE\"));\n\n\tstd::string dots(80, '.');\n\tSaveConverter::getList(_game->getLanguage(), _saves);\n\tfor (int i = 0; i < SaveConverter::NUM_SAVES; ++i)\n\t{\n\t\tstd::ostringstream ss;\n\t\tss << (i + 1);\n\t\t_btnSlot[i]->setText(ss.str());\n\t\t_btnSlot[i]->onMouseClick((ActionHandler)&ListLoadOriginalState::btnSlotClick);\n\n\t\t_txtSlotName[i]->setText(_saves[i].name + dots);\n\t\t_txtSlotTime[i]->setText(_saves[i].time);\n\t\t_txtSlotDate[i]->setText(_saves[i].date);\n\t}\n}\n\n/**\n *\n */\nListLoadOriginalState::~ListLoadOriginalState()\n{\n\n}\n\n/**\n* Refreshes the saves list.\n*/\nvoid ListLoadOriginalState::init()\n{\n\tState::init();\n\n\tif (_origin == OPT_BATTLESCAPE)\n\t{\n\t\tapplyBattlescapeTheme(\"saveMenus\");\n\t}\n}\n\n/**\n * Switches to OpenXcom saves.\n * @param action Pointer to an action.\n */\nvoid ListLoadOriginalState::btnNewClick(Action *)\n{\n\t_game->popState();\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid ListLoadOriginalState::btnCancelClick(Action *action)\n{\n\t_game->popState();\n\t_game->popState();\n\taction->getDetails()->type = SDL_NOEVENT;\n}\n\n/**\n * Loads the specified save.\n * @param action Pointer to an action.\n */\nvoid ListLoadOriginalState::btnSlotClick(Action *action)\n{\n\tint n = 0;\n\tfor (int i = 0; i < SaveConverter::NUM_SAVES; ++i)\n\t{\n\t\tif (action->getSender() == _btnSlot[i])\n\t\t{\n\t\t\tn = i;\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (_saves[n].id > 0)\n\t{\n\t\tif (_saves[n].tactical)\n\t\t{\n\t\t\tstd::ostringstream error;\n\t\t\terror << tr(\"STR_LOAD_UNSUCCESSFUL\") << Unicode::TOK_NL_SMALL << \"Battlescape saves aren't supported.\";\n\t\t\t_game->pushState(new ErrorMessageState(error.str(), _palette, _game->getMod()->getInterface(\"errorMessages\")->getElement(\"geoscapeColor\")->color, \"BACK01.SCR\", _game->getMod()->getInterface(\"errorMessages\")->getElement(\"geoscapePalette\")->color));\n\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// Reset touch flags\n\t\t\t_game->resetTouchButtonFlags();\n\n\t\t\tSaveConverter converter(_saves[n].id, _game->getMod());\n\t\t\t_game->setSavedGame(converter.loadOriginal());\n\t\t\tOptions::baseXResolution = Options::baseXGeoscape;\n\t\t\tOptions::baseYResolution = Options::baseYGeoscape;\n\t\t\t_game->getScreen()->resetDisplay(false);\n\t\t\t_game->setState(new GeoscapeState);\n\t\t\tif (_game->getSavedGame()->getSavedBattle() != 0)\n\t\t\t{\n\t\t\t\t_game->getSavedGame()->getSavedBattle()->loadMapResources(_game->getMod());\n\t\t\t\tOptions::baseXResolution = Options::baseXBattlescape;\n\t\t\t\tOptions::baseYResolution = Options::baseYBattlescape;\n\t\t\t\t_game->getScreen()->resetDisplay(false);\n\t\t\t\tBattlescapeState *bs = new BattlescapeState;\n\t\t\t\t_game->pushState(bs);\n\t\t\t\t_game->getSavedGame()->getSavedBattle()->setBattleState(bs);\n\t\t\t\t// Try to reactivate the touch buttons\n\t\t\t\tbs->toggleTouchButtons(false, true);\n\t\t\t}\n\t\t}\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Menu/ListLoadOriginalState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include \"../Savegame/SaveConverter.h\"\n#include \"OptionsBaseState.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\n\n/**\n * Base class for saved game screens which\n * provides the common layout and listing.\n */\nclass ListLoadOriginalState : public State\n{\nprivate:\n\tTextButton *_btnNew, *_btnCancel;\n\tWindow *_window;\n\tText *_txtTitle, *_txtName, *_txtTime, *_txtDate;\n\tTextButton *_btnSlot[SaveConverter::NUM_SAVES];\n\tText *_txtSlotName[SaveConverter::NUM_SAVES];\n\tText *_txtSlotTime[SaveConverter::NUM_SAVES];\n\tText *_txtSlotDate[SaveConverter::NUM_SAVES];\n\tSaveOriginal _saves[SaveConverter::NUM_SAVES];\n\tOptionsOrigin _origin;\npublic:\n\t/// Creates the Saved Game state.\n\tListLoadOriginalState(OptionsOrigin origin);\n\t/// Cleans up the Saved Game state.\n\t~ListLoadOriginalState();\n\t/// Sets up the saves list.\n\tvoid init() override;\n\t/// Handler for clicking a Save Slot button.\n\tvoid btnSlotClick(Action *action);\n\t/// Handler for clicking the OpenXcom button.\n\tvoid btnNewClick(Action *action);\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Menu/ListLoadState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <algorithm>\n#include \"ListLoadState.h\"\n#include <algorithm>\n#include \"../Engine/Game.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Interface/ToggleTextButton.h\"\n#include \"ConfirmLoadState.h\"\n#include \"LoadGameState.h\"\n#include \"ListLoadOriginalState.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Load Game screen.\n * @param game Pointer to the core game.\n * @param origin Game section that originated this state.\n */\nListLoadState::ListLoadState(OptionsOrigin origin) : ListGamesState(origin, 0, true)\n{\n\t// Create objects\n\t_btnOld = new TextButton(80, 16, 60, 172);\n\t_btnCancel->setX(180);\n\n\tadd(_btnOld, \"button\", \"saveMenus\");\n\n\t// Set up objects\n\t_txtTitle->setText(tr(\"STR_SELECT_GAME_TO_LOAD\"));\n\n\t_btnOld->setText(tr(\"STR_ORIGINAL_XCOM\"));\n\t_btnOld->onMouseClick((ActionHandler)&ListLoadState::btnOldClick);\n\n\tcenterAllSurfaces();\n}\n\n/**\n *\n */\nListLoadState::~ListLoadState()\n{\n\n}\n\n/**\n * Switches to Original X-Com saves.\n * @param action Pointer to an action.\n */\nvoid ListLoadState::btnOldClick(Action *)\n{\n\t_game->pushState(new ListLoadOriginalState(_origin));\n}\n\n/**\n * Loads the selected save.\n * @param action Pointer to an action.\n */\nvoid ListLoadState::lstSavesPress(Action *action)\n{\n\tListGamesState::lstSavesPress(action);\n\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT && !_btnDelete->getPressed())\n\t{\n\t\tloadSave(_lstSaves->getSelectedRow());\n\t}\n}\nvoid ListLoadState::loadSave(size_t list_idx)\n{\n\tbool confirm = false;\n\tconst SaveInfo &saveInfo(_saves[list_idx]);\n\tfor (const auto& modName : saveInfo.mods)\n\t{\n\t\tstd::string name = SavedGame::sanitizeModName(modName);\n\t\tif (std::find(Options::mods.begin(), Options::mods.end(), std::make_pair(name, true)) == Options::mods.end())\n\t\t{\n\t\t\tconfirm = true;\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (confirm)\n\t{\n\t\t_game->pushState(new ConfirmLoadState(_origin, saveInfo.fileName));\n\t}\n\telse\n\t{\n\t\t_game->pushState(new LoadGameState(_origin, saveInfo.fileName, _palette));\n\t}\n}\nvoid ListLoadState::init()\n{\n\tListGamesState::init();\n\tif (_origin == OPT_MENU && Options::getLoadLastSave())\n\t{\n\t\t// make it so that this fires only once\n\t\tOptions::expendLoadLastSave();\n\n\t\t// if the save was explicitly specified, load that one and skip all checks and confirmations\n\t\tif (!Options::getLoadThisSave().empty())\n\t\t{\n\t\t\t// hide the ui\n\t\t\ttoggleScreen();\n\t\t\thideAll();\n\n\t\t\t_game->pushState(new LoadGameState(_origin, Options::getLoadThisSave(), _palette));\n\t\t\treturn;\n\t\t}\n\n\t\t// find the absolutely latest save game including quick and autos\n\t\ttime_t timestamp = 0;\n\t\tint idx = -1, i = 0;\n\t\tfor (auto it = _saves.begin(); it !=_saves.end(); ++it, ++i)\n\t\t{\n\t\t\tif ((*it).timestamp > timestamp)\n\t\t\t{\n\t\t\t\tidx = i;\n\t\t\t\ttimestamp = (*it).timestamp;\n\t\t\t}\n\t\t}\n\t\tif (idx != -1)\n\t\t{\n\t\t\t// hide the ui\n\t\t\ttoggleScreen();\n\t\t\thideAll();\n\t\t\tloadSave(idx);\n\t\t}\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Menu/ListLoadState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ListGamesState.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Load Game screen for listing info on available\n * saved games and loading them.\n */\nclass ListLoadState : public ListGamesState\n{\nprivate:\n\tTextButton *_btnOld;\npublic:\n\t/// Creates the Load Game state.\n\tListLoadState(OptionsOrigin origin);\n\t/// Cleans up the Load Game state.\n\t~ListLoadState();\n\t/// Handler for clicking the Original X-Com button.\n\tvoid btnOldClick(Action *action);\n\t/// Handler for clicking the Saves list.\n\tvoid lstSavesPress(Action *action) override;\n\tvoid init() override;\n\tvoid loadSave(size_t list_idx);\n};\n\n}\n"
  },
  {
    "path": "src/Menu/ListSaveState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ListSaveState.h\"\n#include \"../Engine/CrossPlatform.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Interface/TextEdit.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/ToggleTextButton.h\"\n#include \"SaveGameState.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Save Game screen.\n * @param game Pointer to the core game.\n * @param origin Game section that originated this state.\n */\nListSaveState::ListSaveState(OptionsOrigin origin) : ListGamesState(origin, 1, false), _previousSelectedRow(-1), _selectedRow(-1)\n{\n\t// Create objects\n\t_edtSave = new TextEdit(this, 168, 9, 0, 0);\n\t_btnSaveGame = new TextButton(_game->getSavedGame()->isIronman() ? 200 : 80, 16, 60, 172);\n\n\tadd(_edtSave);\n\tadd(_btnSaveGame, \"button\", \"saveMenus\");\n\n\t// Set up objects\n\t_txtTitle->setText(tr(\"STR_SELECT_SAVE_POSITION\"));\n\n\tif (_game->getSavedGame()->isIronman())\n\t{\n\t\t_btnCancel->setVisible(false);\n\t}\n\telse\n\t{\n\t\t_btnCancel->setX(180);\n\t}\n\n\t_btnSaveGame->setText(tr(\"STR_SAVE_GAME\"));\n\t_btnSaveGame->onMouseClick((ActionHandler)&ListSaveState::btnSaveGameClick);\n\n\t_edtSave->setColor(_lstSaves->getSecondaryColor());\n\t_edtSave->setVisible(false);\n\t_edtSave->onKeyboardPress((ActionHandler)&ListSaveState::edtSaveKeyPress);\n\n\tcenterAllSurfaces();\n}\n\n/**\n *\n */\nListSaveState::~ListSaveState()\n{\n\n}\n\n/**\n * Updates the save game list with the current list\n * of available savegames.\n */\nvoid ListSaveState::updateList()\n{\n\t_lstSaves->addRow(1, tr(\"STR_NEW_SAVED_GAME_SLOT\").c_str());\n\tif (_origin != OPT_BATTLESCAPE)\n\t\t_lstSaves->setRowColor(0, _lstSaves->getSecondaryColor());\n\tListGamesState::updateList();\n}\n\n/**\n * Names the selected save.\n * @param action Pointer to an action.\n */\nvoid ListSaveState::lstSavesPress(Action *action)\n{\n\tif ((action->getDetails()->button.button == SDL_BUTTON_RIGHT || _btnDelete->getPressed()) && _edtSave->isFocused())\n\t{\n\t\t_edtSave->setText(\"\");\n\t\t_edtSave->setVisible(false);\n\t\t_edtSave->setFocus(false, false);\n\t\t_lstSaves->setScrolling(true);\n\t}\n\tListGamesState::lstSavesPress(action);\n\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT && !_btnDelete->getPressed())\n\t{\n\t\t_previousSelectedRow = _selectedRow;\n\t\t_selectedRow = _lstSaves->getSelectedRow();\n\n\t\tswitch (_previousSelectedRow)\n\t\t{\n\t\t\tcase -1:\t// first click on the savegame list\n\t\t\t\tbreak;\n\t\t\tcase 0:\n\t\t\t\t_lstSaves->setCellText(_previousSelectedRow\t, 0, tr(\"STR_NEW_SAVED_GAME_SLOT\"));\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\t_lstSaves->setCellText(_previousSelectedRow\t, 0, _selected);\n\t\t}\n\n\t\t_selected = _lstSaves->getCellText(_lstSaves->getSelectedRow(), 0);\n\t\t_lstSaves->setCellText(_lstSaves->getSelectedRow(), 0, \"\");\n\t\tif (_lstSaves->getSelectedRow() == 0)\n\t\t{\n\t\t\t_edtSave->setText(\"\");\n\t\t\t_selected = \"\";\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_edtSave->setText(_selected);\n\t\t}\n\t\t_edtSave->setX(_lstSaves->getColumnX(0));\n\t\t_edtSave->setY(_lstSaves->getRowY(_selectedRow));\n\t\t_edtSave->setVisible(true);\n\t\t_edtSave->setFocus(true, false);\n\t\t_lstSaves->setScrolling(false);\n\t\tListGamesState::disableSort();\n\t}\n}\n\n/**\n * Saves the selected save.\n * @param action Pointer to an action.\n */\nvoid ListSaveState::edtSaveKeyPress(Action *action)\n{\n\tif (action->getDetails()->key.keysym.sym == SDLK_RETURN ||\n\t\taction->getDetails()->key.keysym.sym == SDLK_KP_ENTER)\n\t{\n\t\tsaveGame();\n\t}\n}\n\n/**\n * Saves the selected save.\n * @param action Pointer to an action.\n */\nvoid ListSaveState::btnSaveGameClick(Action *)\n{\n\tif (_selectedRow != -1)\n\t{\n\t\tsaveGame();\n\t}\n}\n\n/**\n * Saves the selected save.\n */\nvoid ListSaveState::saveGame()\n{\n\t_game->getSavedGame()->setName(_edtSave->getText());\n\tstd::string oldFilename, newFilename;\n\tnewFilename = CrossPlatform::sanitizeFilename(_edtSave->getText());\n\tif (_selectedRow > 0)\n\t{\n\t\toldFilename = _saves[_selectedRow - 1].fileName;\n\t\tif (oldFilename != newFilename + \".sav\")\n\t\t{\n\t\t\twhile (CrossPlatform::fileExists(Options::getMasterUserFolder() + newFilename + \".sav\"))\n\t\t\t{\n\t\t\t\tnewFilename += \"_\";\n\t\t\t}\n\t\t\tstd::string oldPath = Options::getMasterUserFolder() + oldFilename;\n\t\t\tstd::string newPath = Options::getMasterUserFolder() + newFilename + \".sav\";\n\t\t\tCrossPlatform::moveFile(oldPath, newPath);\n\t\t}\n\t}\n\telse\n\t{\n\t\twhile (CrossPlatform::fileExists(Options::getMasterUserFolder() + newFilename + \".sav\"))\n\t\t{\n\t\t\tnewFilename += \"_\";\n\t\t}\n\t}\n\tnewFilename += \".sav\";\n\t_game->pushState(new SaveGameState(_origin, newFilename, _palette));\n}\n\n}\n"
  },
  {
    "path": "src/Menu/ListSaveState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include \"ListGamesState.h\"\n\nnamespace OpenXcom\n{\n\nclass TextEdit;\nclass TextButton;\n\n/**\n * Save Game screen for listing info on available\n * saved games and saving them.\n */\nclass ListSaveState : public ListGamesState\n{\nprivate:\n\tTextEdit *_edtSave;\n\tTextButton *_btnSaveGame;\n\tstd::string _selected;\n\tint _previousSelectedRow, _selectedRow;\npublic:\n\t/// Creates the Save Game state.\n\tListSaveState(OptionsOrigin origin);\n\t/// Cleans up the Save Game state.\n\t~ListSaveState();\n\t/// Updates the savegame list.\n\tvoid updateList() override;\n\t/// Handler for pressing a key on the Save edit.\n\tvoid edtSaveKeyPress(Action *action);\n\t/// Handler for clicking on the Save Game button.\n\tvoid btnSaveGameClick(Action *action);\n\t/// Handler for clicking the Saves list.\n\tvoid lstSavesPress(Action *action) override;\n\t/// Save game.\n\tvoid saveGame();\n};\n\n}\n"
  },
  {
    "path": "src/Menu/LoadGameState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"LoadGameState.h\"\n#include <sstream>\n#include \"../Engine/Logger.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Exception.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/CrossPlatform.h\"\n#include \"../Engine/Screen.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/Text.h\"\n#include \"../Geoscape/GeoscapeState.h\"\n#include \"ErrorMessageState.h\"\n#include \"../Battlescape/BattlescapeState.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/Sound.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Mod/RuleInterface.h\"\n#include \"StatisticsState.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Load Game screen.\n * @param game Pointer to the core game.\n * @param origin Game section that originated this state.\n * @param filename Name of the save file without extension.\n * @param palette Parent state palette.\n */\nLoadGameState::LoadGameState(OptionsOrigin origin, const std::string &filename, SDL_Color *palette) : _firstRun(0), _origin(origin), _filename(filename)\n{\n\tbuildUi(palette);\n}\n\n/**\n * Initializes all the elements in the Load Game screen.\n * @param game Pointer to the core game.\n * @param origin Game section that originated this state.\n * @param type Type of auto-load being used.\n * @param palette Parent state palette.\n */\nLoadGameState::LoadGameState(OptionsOrigin origin, SaveType type, SDL_Color *palette) : _firstRun(0), _origin(origin)\n{\n\tswitch (type)\n\t{\n\tcase SAVE_QUICK:\n\t\t_filename = SavedGame::QUICKSAVE;\n\t\tbreak;\n\tcase SAVE_AUTO_GEOSCAPE:\n\t\t_filename = SavedGame::AUTOSAVE_GEOSCAPE;\n\t\tbreak;\n\tcase SAVE_AUTO_BATTLESCAPE:\n\t\t_filename = SavedGame::AUTOSAVE_BATTLESCAPE;\n\t\tbreak;\n\tdefault:\n\t\t// can't auto-load ironman games\n\t\tbreak;\n\t}\n\n\tbuildUi(palette);\n}\n\n/**\n *\n */\nLoadGameState::~LoadGameState()\n{\n\n}\n\n/**\n * Builds the interface.\n * @param palette Parent state palette.\n */\nvoid LoadGameState::buildUi(SDL_Color *palette)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_txtStatus = new Text(320, 17, 0, 92);\n\n\t// Set palette\n\tsetStatePalette(palette);\n\n\tif (_origin == OPT_BATTLESCAPE)\n\t{\n\t\tadd(_txtStatus, \"textLoad\", \"battlescape\");\n\t\t_txtStatus->setHighContrast(true);\n\t\tif (_game->getSavedGame()->getSavedBattle()->getAmbientSound() != Mod::NO_SOUND)\n\t\t{\n\t\t\t_game->getMod()->getSoundByDepth(0, _game->getSavedGame()->getSavedBattle()->getAmbientSound())->stopLoop();\n\t\t}\n\t}\n\telse\n\t{\n\t\tadd(_txtStatus, \"textLoad\", \"geoscape\");\n\t}\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\t_txtStatus->setBig();\n\t_txtStatus->setAlign(ALIGN_CENTER);\n\t_txtStatus->setText(tr(\"STR_LOADING_GAME\"));\n\n}\n\n/**\n * Ignore quick loads without a save available.\n */\nvoid LoadGameState::init()\n{\n\tState::init();\n\tif (_filename == SavedGame::QUICKSAVE && !CrossPlatform::fileExists(Options::getMasterUserFolder() + _filename))\n\t{\n\t\t_game->popState();\n\t\treturn;\n\t}\n}\n\n/**\n * Loads the specified save.\n */\nvoid LoadGameState::think()\n{\n\tState::think();\n\t// Make sure it gets drawn properly\n\tif (_firstRun < 10)\n\t{\n\t\t_firstRun++;\n\t}\n\telse\n\t{\n\t\t_game->popState();\n\n\t\t// Remember for later (palette reset)\n\t\tBattlescapeState *origBattleState = 0;\n\t\tif (_game->getSavedGame() != 0 && _game->getSavedGame()->getSavedBattle() != 0)\n\t\t{\n\t\t\torigBattleState = _game->getSavedGame()->getSavedBattle()->getBattleState();\n\t\t}\n\n\t\t// Reset touch flags\n\t\t_game->resetTouchButtonFlags();\n\n\t\t// Load the game\n\t\tSavedGame *s = new SavedGame();\n\t\ttry\n\t\t{\n\t\t\ts->load(_filename, _game->getMod(), _game->getLanguage());\n\t\t\t_game->setSavedGame(s);\n\t\t\tif (_game->getSavedGame()->getEnding() != END_NONE)\n\t\t\t{\n\t\t\t\tOptions::baseXResolution = Screen::ORIGINAL_WIDTH;\n\t\t\t\tOptions::baseYResolution = Screen::ORIGINAL_HEIGHT;\n\t\t\t\t_game->getScreen()->resetDisplay(false);\n\t\t\t\t_game->setState(new StatisticsState);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tOptions::baseXResolution = Options::baseXGeoscape;\n\t\t\t\tOptions::baseYResolution = Options::baseYGeoscape;\n\t\t\t\t_game->getScreen()->resetDisplay(false);\n\t\t\t\tif (origBattleState != 0)\n\t\t\t\t{\n\t\t\t\t\t// We need to reset palettes here already, can't wait for the destructor\n\t\t\t\t\torigBattleState->resetPalettes();\n\t\t\t\t}\n\t\t\t\t_game->setState(new GeoscapeState);\n\t\t\t\tif (_game->getSavedGame()->getSavedBattle() != 0)\n\t\t\t\t{\n\t\t\t\t\t_game->getSavedGame()->getSavedBattle()->loadMapResources(_game->getMod());\n\t\t\t\t\tOptions::baseXResolution = Options::baseXBattlescape;\n\t\t\t\t\tOptions::baseYResolution = Options::baseYBattlescape;\n\t\t\t\t\t_game->getScreen()->resetDisplay(false);\n\t\t\t\t\tBattlescapeState *bs = new BattlescapeState;\n\t\t\t\t\t_game->pushState(bs);\n\t\t\t\t\t_game->getSavedGame()->getSavedBattle()->setBattleState(bs);\n\t\t\t\t\t// Try to reactivate the touch buttons\n\t\t\t\t\tbs->toggleTouchButtons(false, true);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Clear the SDL event queue (i.e. ignore input from impatient users)\n\t\t\tSDL_Event e;\n\t\t\twhile (SDL_PollEvent(&e))\n\t\t\t{\n\t\t\t\t// do nothing\n\t\t\t}\n\t\t}\n\t\tcatch (Exception &e)\n\t\t{\n\t\t\terror(e.what(), s);\n\t\t}\n\t\tcatch (YAML::Exception &e)\n\t\t{\n\t\t\terror(e.what(), s);\n\t\t}\n\t\tCrossPlatform::flashWindow();\n\t}\n}\n\n/**\n * Pops up a window with an error message\n * and cleans up afterwards.\n * @param msg Error message.\n * @param save Pending save.\n */\nvoid LoadGameState::error(const std::string &msg, SavedGame *save)\n{\n\n\tLog(LOG_ERROR) << msg;\n\tstd::ostringstream error;\n\terror << tr(\"STR_LOAD_UNSUCCESSFUL\") << Unicode::TOK_NL_SMALL << msg;\n\tif (_origin != OPT_BATTLESCAPE)\n\t\t_game->pushState(new ErrorMessageState(error.str(), _palette, _game->getMod()->getInterface(\"errorMessages\")->getElement(\"geoscapeColor\")->color, \"BACK01.SCR\", _game->getMod()->getInterface(\"errorMessages\")->getElement(\"geoscapePalette\")->color));\n\telse\n\t\t_game->pushState(new ErrorMessageState(error.str(), _palette, _game->getMod()->getInterface(\"errorMessages\")->getElement(\"battlescapeColor\")->color, \"TAC00.SCR\", _game->getMod()->getInterface(\"errorMessages\")->getElement(\"battlescapePalette\")->color));\n\n\tif (_game->getSavedGame() == save)\n\t\t_game->setSavedGame(0);\n\telse\n\t\tdelete save;\n}\n\n}\n"
  },
  {
    "path": "src/Menu/LoadGameState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include <SDL.h>\n#include <string>\n#include \"OptionsBaseState.h\"\n#include \"../Savegame/SavedGame.h\"\n\nnamespace OpenXcom\n{\n\nclass Text;\nclass SavedGame;\n\n/**\n * Loads a saved game, with an optional message.\n */\nclass LoadGameState : public State\n{\nprivate:\n\tint _firstRun;\n\tOptionsOrigin _origin;\n\tText *_txtStatus;\n\tstd::string _filename;\npublic:\n\t/// Creates the Load Game state.\n\tLoadGameState(OptionsOrigin origin, const std::string &filename, SDL_Color *palette);\n\t/// Creates the Load Game state.\n\tLoadGameState(OptionsOrigin origin, SaveType type, SDL_Color *palette);\n\t/// Cleans up the Load Game state.\n\t~LoadGameState();\n\t/// Creates the interface.\n\tvoid buildUi(SDL_Color *palette);\n\t/// Validates game.\n\tvoid init() override;\n\t/// Loads the game.\n\tvoid think() override;\n\t/// Shows an error message.\n\tvoid error(const std::string &msg, SavedGame *save);\n};\n\n}\n"
  },
  {
    "path": "src/Menu/MainMenuState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"MainMenuState.h\"\n#include <sstream>\n#include \"../version.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Screen.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"NewGameState.h\"\n#include \"NewBattleState.h\"\n#include \"ListLoadState.h\"\n#include \"OptionsVideoState.h\"\n#include \"ModListState.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/FileMap.h\"\n#include \"../Engine/SDL2Helpers.h\"\n#include <fstream>\n\nnamespace OpenXcom\n{\n\nGoToMainMenuState::GoToMainMenuState(bool updateCheck) : _updateCheck(updateCheck)\n{\n\t// empty\n}\n\nGoToMainMenuState::~GoToMainMenuState()\n{\n\t// empty\n}\n\nvoid GoToMainMenuState::init()\n{\n\tScreen::updateScale(Options::geoscapeScale, Options::baseXGeoscape, Options::baseYGeoscape, true);\n\t_game->getScreen()->resetDisplay(false);\n\t_game->setState(new MainMenuState(_updateCheck));\n}\n\n/**\n * Initializes all the elements in the Main Menu window.\n * @param updateCheck Perform update check?\n */\nMainMenuState::MainMenuState(bool updateCheck)\n{\n#ifdef _WIN32\n\t_debugInVisualStudio = false;\n#endif\n\n\t// Create objects\n\t_window = new Window(this, 256, 160, 32, 20, POPUP_BOTH);\n\t_btnNewGame = new TextButton(92, 20, 64, 90);\n\t_btnNewBattle = new TextButton(92, 20, 164, 90);\n\t_btnLoad = new TextButton(92, 20, 64, 118);\n\t_btnOptions = new TextButton(92, 20, 164, 118);\n\t_btnMods = new TextButton(92, 20, 64, 146);\n\t_btnQuit = new TextButton(92, 20, 164, 146);\n\t_btnUpdate = new TextButton(72, 16, 209, 27);\n\t_txtUpdateInfo = new Text(320, 17, 0, 11);\n\t_txtTitle = new Text(256, 30, 32, 45);\n\n\t// Set palette\n\tsetInterface(\"mainMenu\");\n\n\tadd(_window, \"window\", \"mainMenu\");\n\tadd(_btnNewGame, \"button\", \"mainMenu\");\n\tadd(_btnNewBattle, \"button\", \"mainMenu\");\n\tadd(_btnLoad, \"button\", \"mainMenu\");\n\tadd(_btnOptions, \"button\", \"mainMenu\");\n\tadd(_btnMods, \"button\", \"mainMenu\");\n\tadd(_btnQuit, \"button\", \"mainMenu\");\n\tadd(_btnUpdate, \"button\", \"mainMenu\");\n\tadd(_txtUpdateInfo, \"text\", \"mainMenu\");\n\tadd(_txtTitle, \"text\", \"mainMenu\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"mainMenu\");\n\n\t_btnNewGame->setText(tr(\"STR_NEW_GAME\"));\n\t_btnNewGame->onMouseClick((ActionHandler)&MainMenuState::btnNewGameClick);\n\n\t_btnNewBattle->setText(tr(\"STR_NEW_BATTLE\"));\n\t_btnNewBattle->onMouseClick((ActionHandler)&MainMenuState::btnNewBattleClick);\n\n\t_btnLoad->setText(tr(\"STR_LOAD_SAVED_GAME\"));\n\t_btnLoad->onMouseClick((ActionHandler)&MainMenuState::btnLoadClick);\n\n\t_btnOptions->setText(tr(\"STR_OPTIONS\"));\n\t_btnOptions->onMouseClick((ActionHandler)&MainMenuState::btnOptionsClick);\n\n\t_btnMods->setText(tr(\"STR_MODS\"));\n\t_btnMods->onMouseClick((ActionHandler)&MainMenuState::btnModsClick);\n\n\t_btnQuit->setText(tr(\"STR_QUIT\"));\n\t_btnQuit->onMouseClick((ActionHandler)&MainMenuState::btnQuitClick);\n\n\t_btnUpdate->setText(tr(\"STR_UPDATE\"));\n\t_btnUpdate->onMouseClick((ActionHandler)& MainMenuState::btnUpdateClick);\n\t_btnUpdate->setVisible(false);\n\n\t_txtUpdateInfo->setAlign(ALIGN_CENTER);\n\t_txtUpdateInfo->setWordWrap(true);\n\t_txtUpdateInfo->setText(tr(\"STR_LATEST_VERSION_INFO\"));\n\t_txtUpdateInfo->setVisible(false);\n\n#ifdef _WIN32\n\t//_debugInVisualStudio = true; // uncomment when debugging in Visual Studio (working dir and exe dir are not the same)\n\n\t// delete (old) update batch file\n\tif (updateCheck && CrossPlatform::fileExists(\"oxce-upd.bat\"))\n\t{\n\t\tCrossPlatform::deleteFile(\"oxce-upd.bat\");\n\t}\n\n\tif (updateCheck && Options::oxceUpdateCheck)\n\t{\n\t\tint checkProgress = 0;\n\t\tconst std::string relativeExeFilename = (_debugInVisualStudio ? \"Debug/\" + CrossPlatform::getExeFilename(false) : CrossPlatform::getExeFilename(false));\n\t\t// (naive) check if working directory and exe directory are the same\n\t\tif (!relativeExeFilename.empty() && CrossPlatform::fileExists(relativeExeFilename))\n\t\t{\n\t\t\tcheckProgress = 1;\n\t\t\tstd::ostringstream antivirusFalsePositive1;\n\t\t\tantivirusFalsePositive1 << \"ht\" << \"tp\" << \"s:\" << \"/\" << \"/\" << \"openxcom.\" << \"org/\";\n\t\t\tconst std::string internetConnectionCheckUrl = antivirusFalsePositive1.str();\n\t\t\tif (CrossPlatform::testInternetConnection(internetConnectionCheckUrl))\n\t\t\t{\n\t\t\t\tcheckProgress = 2;\n\t\t\t\tstd::ostringstream antivirusFalsePositive2;\n\t\t\t\tantivirusFalsePositive2 << \"ht\" << \"tp\" << \"s:\" << \"/\" << \"/\" << \"openxcom.\" << \"org/oxce\" << \"/update.txt\";\n\t\t\t\tconst std::string updateMetadataUrl = antivirusFalsePositive2.str();\n\t\t\t\tconst std::string updateMetadataFilename = Options::getUserFolder() + \"oxce-update.txt\";\n\t\t\t\tif (CrossPlatform::downloadFile(updateMetadataUrl, updateMetadataFilename))\n\t\t\t\t{\n\t\t\t\t\tcheckProgress = 3;\n\t\t\t\t\tif (CrossPlatform::fileExists(updateMetadataFilename))\n\t\t\t\t\t{\n\t\t\t\t\t\tcheckProgress = 4;\n\t\t\t\t\t\ttry\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tYAML::YamlRootNodeReader reader(updateMetadataFilename);\n\t\t\t\t\t\t\tcheckProgress = 5;\n\t\t\t\t\t\t\tif (reader[\"updateInfo\"])\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcheckProgress = 6;\n\t\t\t\t\t\t\t\tstd::string msg = reader[\"updateInfo\"].readVal<std::string>();\n\t\t\t\t\t\t\t\t_txtUpdateInfo->setText(msg);\n\t\t\t\t\t\t\t\t_txtUpdateInfo->setVisible(true);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if (reader[\"newVersion\"])\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcheckProgress = 7;\n\t\t\t\t\t\t\t\t_newVersion = reader[\"newVersion\"].readVal<std::string>();\n\t\t\t\t\t\t\t\tif (CrossPlatform::isHigherThanCurrentVersion(_newVersion))\n\t\t\t\t\t\t\t\t\t_btnUpdate->setVisible(true);\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t_txtUpdateInfo->setVisible(true);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tCrossPlatform::deleteFile(updateMetadataFilename);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcatch (YAML::Exception &e)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tLog(LOG_ERROR) << e.what();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tLog(LOG_INFO) << \"Update check status: \" << checkProgress << \"; newVersion: v\" << _newVersion << \"; \";\n\t}\n#endif\n\n\tif (!_btnUpdate->getVisible())\n\t{\n\t\tint problemCode = 0;\n\t\t// standard\n\t\tconst ModInfo* xcomInfo = Options::getXcomRulesetInfo();\n\t\tif (xcomInfo && CrossPlatform::isLowerThanRequiredVersion(xcomInfo->getVersion()))\n\t\t{\n\t\t\tproblemCode = 1;\n\t\t\tLog(LOG_ERROR) << \"ERROR: The content of the 'standard' folder is too old!\";\n\t\t\t_txtUpdateInfo->setText(\"ERROR: The content of the 'standard' folder is too old!\");\n\t\t}\n\t\t// common\n\t\ttry\n\t\t{\n\t\t\tconst YAML::YamlRootNodeReader& reader = FileMap::getYAML(\"dont-touch.me\");\n\t\t\tif (reader[\"version\"])\n\t\t\t{\n\t\t\t\tif (CrossPlatform::isLowerThanRequiredVersion(reader[\"version\"].readVal<std::string>()))\n\t\t\t\t{\n\t\t\t\t\tproblemCode = 2;\n\t\t\t\t\tLog(LOG_ERROR) << \"ERROR: The content of the 'common' folder is too old!\";\n\t\t\t\t\t_txtUpdateInfo->setText(\"ERROR: The content of the 'common' folder is too old!\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tcatch (Exception& e)\n\t\t{\n\t\t\tproblemCode = 3;\n\t\t\tLog(LOG_ERROR) << \"ERROR: The content of the 'common' folder is too old!!\";\n\t\t\t_txtUpdateInfo->setText(\"ERROR: The content of the 'common' folder is too old!!\");\n\t\t\tLog(LOG_ERROR) << e.what();\n\t\t}\n\t\t// result\n\t\tif (problemCode > 0)\n\t\t{\n\t\t\t_txtUpdateInfo->setColor(81); // hardcoded, readable both in xcom1 and xcom2\n\t\t\t_txtUpdateInfo->setVisible(true);\n\t\t}\n\t}\n\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setBig();\n\tstd::ostringstream title;\n\ttitle << tr(\"STR_OPENXCOM\").arg(Options::getActiveMasterInfo()->getVersionDisplay()) << Unicode::TOK_NL_SMALL;\n\ttitle << \"OpenXcom \" << OPENXCOM_VERSION_SHORT << OPENXCOM_VERSION_GIT;\n\t_txtTitle->setText(title.str());\n}\n\nvoid MainMenuState::init()\n{\n\tState::init();\n\tif (Options::getLoadLastSave() && !Options::getLoadThisSave().empty())\n\t{\n\t\tLog(LOG_INFO) << \"Loading saved game passed as parameter\";\n\t\tbtnLoadClick(NULL);\n\t}\n\telse if (Options::getLoadLastSave() && _game->getSavedGame()->getList(_game->getLanguage(), true).size() > 0)\n\t{\n\t\tLog(LOG_INFO) << \"Loading last saved game\";\n\t\tbtnLoadClick(NULL);\n\t}\n}\n\n/**\n *\n */\nMainMenuState::~MainMenuState()\n{\n\n}\n\n/**\n * Opens the New Game window.\n * @param action Pointer to an action.\n */\nvoid MainMenuState::btnNewGameClick(Action *)\n{\n\t_game->pushState(new NewGameState);\n}\n\n/**\n * Opens the New Battle screen.\n * @param action Pointer to an action.\n */\nvoid MainMenuState::btnNewBattleClick(Action *)\n{\n\t_game->pushState(new NewBattleState);\n}\n\n/**\n * Opens the Load Game screen.\n * @param action Pointer to an action.\n */\nvoid MainMenuState::btnLoadClick(Action *)\n{\n\t_game->pushState(new ListLoadState(OPT_MENU));\n}\n\n/**\n * Opens the Options screen.\n * @param action Pointer to an action.\n */\nvoid MainMenuState::btnOptionsClick(Action *)\n{\n\tOptions::backupDisplay();\n\t_game->pushState(new OptionsVideoState(OPT_MENU));\n}\n\n/**\n* Opens the Mods screen.\n* @param action Pointer to an action.\n*/\nvoid MainMenuState::btnModsClick(Action *)\n{\n\t_game->pushState(new ModListState);\n}\n\n/**\n * Quits the game.\n * @param action Pointer to an action.\n */\nvoid MainMenuState::btnQuitClick(Action *)\n{\n\t_game->quit();\n}\n\n/**\n * Updates OpenXcom to the newest version.\n * @param action Pointer to an action.\n */\nvoid MainMenuState::btnUpdateClick(Action*)\n{\n\tstd::ostringstream antivirusFalsePositive3;\n\tantivirusFalsePositive3 << \"ht\" << \"tp\" << \"s:\" << \"/\" << \"/\" << \"openxcom.\" << \"org/oxce\" << \"/\";\n\tconst std::string oxcePrefix = antivirusFalsePositive3.str();\n\n#ifdef _WIN32\n\tconst std::string subdir = \"v\" + _newVersion + \"/\";\n\n#ifdef _WIN64\n\tconst std::string relativeExeZipFileName = _debugInVisualStudio ? \"Debug/exe64.zip\" : \"exe64.zip\";\n#else\n\tconst std::string relativeExeZipFileName = _debugInVisualStudio ? \"Debug/exe.zip\" : \"exe.zip\";\n#endif\n\tconst std::string relativeExeNewFileName = _debugInVisualStudio ? \"Debug/OpenXcomEx.exe.new\" : \"OpenXcomEx.exe.new\";\n\n\tconst std::string commonDirFilename = Options::getDataFolder() + \"common\";\n\tconst std::string commonZipFilename = Options::getDataFolder() + \"common.zip\";\n\tconst std::string commonZipUrl = oxcePrefix + subdir + \"common.zip\";\n\n\tconst std::string standardDirFilename = Options::getDataFolder() + \"standard\";\n\tconst std::string standardZipFilename = Options::getDataFolder() + \"standard.zip\";\n\tconst std::string standardZipUrl = oxcePrefix + subdir + \"standard.zip\";\n\n\tconst std::string now = CrossPlatform::now();\n\n\tconst std::string exePath = CrossPlatform::getExeFolder();\n\tconst std::string exeFilenameOnly = CrossPlatform::getExeFilename(false);\n\tconst std::string exeFilenameFullPath = CrossPlatform::getExeFilename(true);\n\n#ifdef _WIN64\n\tconst std::string exeZipFilename = exePath + \"exe64.zip\";\n#else\n\tconst std::string exeZipFilename = exePath + \"exe.zip\";\n#endif\n\tconst std::string exeNewFilename = exePath + \"OpenXcomEx.exe.new\";\n#ifdef _WIN64\n\tconst std::string exeZipUrl = oxcePrefix + subdir + \"exe64.zip\";\n#else\n\tconst std::string exeZipUrl = oxcePrefix + subdir + \"exe.zip\";\n#endif\n\n\t// stop using the common/standard zip files, so that we can back them up\n\tFileMap::clear(true, false);\n\n\t// 0. backup the exe\n\tif (CrossPlatform::fileExists(exeFilenameFullPath))\n\t{\n\t\tif (CrossPlatform::copyFile(exeFilenameFullPath, exeFilenameFullPath + \"-\" + now + \".bak\"))\n\t\t\tLog(LOG_INFO) << \"Update step 0 done.\";\n\t\telse return;\n\t}\n\n\t// 1. backup common dir\n\tif (CrossPlatform::fileExists(commonDirFilename))\n\t{\n\t\tif (CrossPlatform::moveFile(commonDirFilename, commonDirFilename + \"-\" + now))\n\t\t\tLog(LOG_INFO) << \"Update step 1 done.\";\n\t\telse return;\n\t}\n\n\t// 2. backup common zip\n\tif (CrossPlatform::fileExists(commonZipFilename))\n\t{\n\t\tif (CrossPlatform::moveFile(commonZipFilename, commonZipFilename + \"-\" + now + \".bak\"))\n\t\t\tLog(LOG_INFO) << \"Update step 2 done.\";\n\t\telse return;\n\t}\n\n\t// 3. backup standard dir\n\tif (CrossPlatform::fileExists(standardDirFilename))\n\t{\n\t\tif (CrossPlatform::moveFile(standardDirFilename, standardDirFilename + \"-\" + now))\n\t\t\tLog(LOG_INFO) << \"Update step 3 done.\";\n\t\telse return;\n\t}\n\n\t// 4. backup standard zip\n\tif (CrossPlatform::fileExists(standardZipFilename))\n\t{\n\t\tif (CrossPlatform::moveFile(standardZipFilename, standardZipFilename + \"-\" + now + \".bak\"))\n\t\t\tLog(LOG_INFO) << \"Update step 4 done.\";\n\t\telse return;\n\t}\n\n\t// 5. delete exe zip\n\tif (CrossPlatform::fileExists(exeZipFilename))\n\t{\n\t\tif (CrossPlatform::deleteFile(exeZipFilename))\n\t\t\tLog(LOG_INFO) << \"Update step 5 done.\";\n\t\telse return;\n\t}\n\n\t// 6. delete unpacked exe zip\n\tif (CrossPlatform::fileExists(exeNewFilename))\n\t{\n\t\tif (CrossPlatform::deleteFile(exeNewFilename))\n\t\t\tLog(LOG_INFO) << \"Update step 6 done.\";\n\t\telse return;\n\t}\n\n\t// 7. download common zip\n\tif (CrossPlatform::downloadFile(commonZipUrl, commonZipFilename))\n\t{\n\t\tLog(LOG_INFO) << \"Update step 7 done.\";\n\t}\n\telse return;\n\n\t// 8. download standard zip\n\tif (CrossPlatform::downloadFile(standardZipUrl, standardZipFilename))\n\t{\n\t\tLog(LOG_INFO) << \"Update step 8 done.\";\n\t}\n\telse return;\n\n\t// 9. download exe zip\n\tif (CrossPlatform::downloadFile(exeZipUrl, exeZipFilename))\n\t{\n\t\tLog(LOG_INFO) << \"Update step 9 done.\";\n\t}\n\telse return;\n\n\t// 10. extract exe zip\n\tif (CrossPlatform::fileExists(exeZipFilename) && CrossPlatform::fileExists(relativeExeZipFileName))\n\t{\n\t\tconst std::string file_to_extract = \"OpenXcomEx.exe.new\";\n\t\tSDL_RWops *rwo_read = FileMap::zipGetFileByName(relativeExeZipFileName, file_to_extract);\n\t\tif (!rwo_read) {\n\t\t\tLog(LOG_ERROR) << \"Step 10a: failed to unzip file.\";\n\t\t\treturn;\n\t\t}\n\t\tsize_t size = 0;\n\t\tauto data = SDL_LoadFile_RW(rwo_read, &size, SDL_TRUE);\n\t\tif (!data) {\n\t\t\tLog(LOG_ERROR) << \"Step 10b: failed to unzip file.\" << SDL_GetError(); // out of memory for a copy ?\n\t\t\treturn;\n\t\t}\n\t\tSDL_RWops *rwo_write = SDL_RWFromFile(relativeExeNewFileName.c_str(), \"wb\");\n\t\tif (!rwo_write) {\n\t\t\tLog(LOG_ERROR) << \"Step 10c: failed to open exe.new file for writing.\" << SDL_GetError();\n\t\t\treturn;\n\t\t}\n\t\tauto wsize = SDL_RWwrite(rwo_write, data, size, 1);\n\t\tif (wsize != 1) {\n\t\t\tLog(LOG_ERROR) << \"Step 10d: failed to write exe.new file.\" << SDL_GetError();\n\t\t\treturn;\n\t\t}\n\t\tif (SDL_RWclose(rwo_write)) {\n\t\t\tLog(LOG_ERROR) << \"Step 10e: failed to write exe.new file.\" << SDL_GetError();\n\t\t\treturn;\n\t\t}\n\t} else {\n\t\tLog(LOG_ERROR) << \"Update step 10 failed.\"; // exe dir and working dir not the same\n\t\treturn;\n\t}\n\n\t// 11. check if extracted exe exists\n\tif (!CrossPlatform::fileExists(exeNewFilename))\n\t{\n\t\tLog(LOG_ERROR) << \"Update step 11 failed.\";\n\t\treturn;\n\t}\n\n\t// 12. delete exe zip (again)\n\tif (CrossPlatform::fileExists(exeZipFilename))\n\t{\n\t\tif (CrossPlatform::deleteFile(exeZipFilename))\n\t\t\tLog(LOG_INFO) << \"Update step 12 done.\";\n\t\telse return;\n\t}\n\n\t// 13. create the update batch file\n\t{\n\t\tstd::ofstream batch;\n\t\tbatch.open(\"oxce-upd.bat\", std::ios::out);\n\n\t\tbatch << \"@echo OFF\\n\";\n\t\tbatch << \"echo OpenXcom is updating, please wait...\\n\";\n\t\tbatch << \"timeout 5\\n\";\n\t\tif (!_debugInVisualStudio)\n\t\t{\n\t\t\tbatch << \"echo Removing the old version...\\n\";\n\t\t\tbatch << \"del \" << exeFilenameOnly << \"\\n\";\n\t\t\tbatch << \"echo Preparing the new version...\\n\";\n\t\t\tbatch << \"ren OpenXcomEx.exe.new \" << exeFilenameOnly << \"\\n\";\n\t\t\tbatch << \"echo Starting the new version...\\n\";\n\t\t\tbatch << \"timeout 2\\n\";\n\t\t\tbatch << \"start \" << exeFilenameOnly << \"\\n\"; // asynchronous\n\t\t\tbatch << \"exit\\n\";\n\t\t}\n\n\t\tbatch.close();\n\t}\n\n\t// 14. Clear the SDL event queue (i.e. ignore input from impatient users)\n\tSDL_Event e;\n\twhile (SDL_PollEvent(&e))\n\t{\n\t\t// do nothing\n\t}\n\n\tLog(LOG_INFO) << \"Update prepared, restarting.\";\n\t_game->setUpdateFlag(true);\n\t_game->quit();\n#endif\n}\n\n/**\n * Updates the scale.\n * @param dX delta of X;\n * @param dY delta of Y;\n */\nvoid MainMenuState::resize(int &dX, int &dY)\n{\n\tdX = Options::baseXResolution;\n\tdY = Options::baseYResolution;\n\tScreen::updateScale(Options::geoscapeScale, Options::baseXGeoscape, Options::baseYGeoscape, true);\n\tdX = Options::baseXResolution - dX;\n\tdY = Options::baseYResolution - dY;\n\tState::resize(dX, dY);\n}\n\n}\n"
  },
  {
    "path": "src/Menu/MainMenuState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\n\n// Utility class for enqueuing a state in the stack that goes to the main menu\nclass GoToMainMenuState : public State\n{\nprivate:\n\tbool _updateCheck;\npublic:\n\tGoToMainMenuState(bool updateCheck = false);\n\t~GoToMainMenuState();\n\tvoid init() override;\n};\n\n/**\n * Main Menu window displayed when first\n * starting the game.\n */\nclass MainMenuState : public State\n{\nprivate:\n\tTextButton *_btnNewGame, *_btnNewBattle, *_btnLoad, *_btnOptions, *_btnMods, *_btnQuit, *_btnUpdate;\n\tWindow *_window;\n\tText *_txtTitle, *_txtUpdateInfo;\n#ifdef _WIN32\n\tbool _debugInVisualStudio;\n\tstd::string _newVersion;\n#endif\npublic:\n\t/// Creates the Main Menu state.\n\tMainMenuState(bool updateCheck = false);\n\t/// Cleans up the Main Menu state.\n\t~MainMenuState();\n\t/// Handler for clicking the New Game button.\n\tvoid btnNewGameClick(Action *action);\n\t/// Handler for clicking the New Battle button.\n\tvoid btnNewBattleClick(Action *action);\n\t/// Handler for clicking the Load Saved Game button.\n\tvoid btnLoadClick(Action *action);\n\t/// Handler for clicking the Options button.\n\tvoid btnOptionsClick(Action *action);\n\t/// Handler for clicking the Mods button.\n\tvoid btnModsClick(Action *action);\n\t/// Handler for clicking the Quit button.\n\tvoid btnQuitClick(Action *action);\n\t/// Handler for clicking the Update button.\n\tvoid btnUpdateClick(Action* action);\n\t/// Update the resolution settings, we just resized the window.\n\tvoid resize(int &dX, int &dY) override;\n\tvoid init() override;\n};\n\n}\n"
  },
  {
    "path": "src/Menu/ModConfirmExtendedState.cpp",
    "content": "/*\n * Copyright 2010-2019 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ModConfirmExtendedState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/ModInfo.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Mod/Mod.h\"\n#include \"../version.h\"\n#include \"ModListState.h\"\n\nnamespace OpenXcom\n{\n\n\t/**\n\t * Initializes all the elements in the Confirm OXCE screen.\n\t * @param state Pointer to the Options|Mod state.\n\t * @param modInfo What exactly mod caused this question?\n\t */\n\tModConfirmExtendedState::ModConfirmExtendedState(ModListState *state, const ModInfo *modInfo, const ModInfo *masterInfo) : _state(state), _isMaster(modInfo->isMaster())\n\t{\n\t\t_screen = false;\n\n\t\t// Create objects\n\t\t_window = new Window(this, 256, 100, 32, 50, POPUP_BOTH);\n\t\t_btnYes = new TextButton(60, 18, 60, 122);\n\t\t_btnNo = new TextButton(60, 18, 200, 122);\n\t\t_txtTitle = new Text(246, 50, 37, 64);\n\n\t\t// Set palette\n\t\tsetInterface(\"optionsMenu\");\n\n\t\tadd(_window, \"confirmDefaults\", \"optionsMenu\");\n\t\tadd(_btnYes, \"confirmDefaults\", \"optionsMenu\");\n\t\tadd(_btnNo, \"confirmDefaults\", \"optionsMenu\");\n\t\tadd(_txtTitle, \"confirmDefaults\", \"optionsMenu\");\n\n\t\tcenterAllSurfaces();\n\n\t\t// Set up objects\n\t\tsetWindowBackground(_window, \"optionsMenu\");\n\n\t\t_btnYes->setText(tr(\"STR_YES\"));\n\t\t_btnYes->onMouseClick((ActionHandler)&ModConfirmExtendedState::btnYesClick);\n\t\tif (!modInfo->isEngineOk())\n\t\t{\n\t\t\t_btnYes->setVisible(false);\n\t\t}\n\n\t\t_btnNo->setText(tr(\"STR_CANCEL\"));\n\t\t_btnNo->onMouseClick((ActionHandler)&ModConfirmExtendedState::btnNoClick);\n\n\t\t_txtTitle->setAlign(ALIGN_CENTER);\n\t\t_txtTitle->setBig();\n\t\t_txtTitle->setWordWrap(true);\n\t\tif (masterInfo && !modInfo->isParentMasterOk(masterInfo))\n\t\t{\n\t\t\t_txtTitle->setText(tr(\"STR_MASTER_MOD_VERSION_REQUIRED_QUESTION\").arg(modInfo->getRequiredMasterVersion()).arg(masterInfo->getVersion()));\n\t\t}\n\t\telse if (modInfo->getRequiredExtendedEngine() != OPENXCOM_VERSION_ENGINE)\n\t\t{\n\t\t\t_txtTitle->setText(tr(\"STR_OXCE_REQUIRED_QUESTION\").arg(modInfo->getRequiredExtendedEngine()));\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_txtTitle->setText(tr(\"STR_VERSION_REQUIRED_QUESTION\").arg(modInfo->getRequiredExtendedVersion()));\n\t\t}\n\t}\n\n\t/**\n\t *\n\t */\n\tModConfirmExtendedState::~ModConfirmExtendedState()\n\t{\n\n\t}\n\n\t/**\n\t * Closes the window. Enables the mod.\n\t * @param action Pointer to an action.\n\t */\n\tvoid ModConfirmExtendedState::btnYesClick(Action *)\n\t{\n\t\t_game->popState();\n\n\t\tif (_isMaster)\n\t\t{\n\t\t\t_state->changeMasterMod();\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_state->toggleMod();\n\t\t}\n\t}\n\n\t/**\n\t * Closes the window. Does not enable the mod.\n\t * @param action Pointer to an action.\n\t */\n\tvoid ModConfirmExtendedState::btnNoClick(Action *)\n\t{\n\t\t_game->popState();\n\n\t\tif (_isMaster)\n\t\t{\n\t\t\t_state->revertMasterMod();\n\t\t}\n\t}\n\n\t/**\n\t * Check if master mod is not valid.\n\t */\n\tbool ModConfirmExtendedState::isMasterNotValid(const ModInfo *masterInfo)\n\t{\n\t\treturn !masterInfo->isEngineOk();\n\t}\n\n\t/**\n\t * Check if mod is not valid.\n\t */\n\tbool ModConfirmExtendedState::isModNotValid(const ModInfo *modInfo, const ModInfo *masterInfo)\n\t{\n\t\treturn !modInfo->isMaster() && // skip checking master mod\n\t\t\t(!modInfo->isEngineOk() || !modInfo->isParentMasterOk(masterInfo));\n\t}\n\n\n\tbool ModConfirmExtendedState::tryShowMasterNotValidConfirmationState(ModListState *state, const ModInfo *masterInfo)\n\t{\n\t\tif (isMasterNotValid(masterInfo))\n\t\t{\n\t\t\t_game->pushState(new ModConfirmExtendedState(state, masterInfo));\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tbool ModConfirmExtendedState::tryShowModNotValidConfirmationState(ModListState *state, const ModInfo *modInfo, const ModInfo *masterInfo)\n\t{\n\t\tif (isModNotValid(modInfo, masterInfo))\n\t\t{\n\t\t\t_game->pushState(new ModConfirmExtendedState(state, modInfo, masterInfo));\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n}\n"
  },
  {
    "path": "src/Menu/ModConfirmExtendedState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2019 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\tclass ModListState;\n\tclass ModInfo;\n\tclass TextButton;\n\tclass Window;\n\tclass Text;\n\tclass ModInfo;\n\n\t/**\n\t * Confirmation window when enabling\n\t * mods that require OXCE.\n\t */\n\tclass ModConfirmExtendedState : public State\n\t{\n\tprivate:\n\t\tModListState *_state;\n\t\tbool _isMaster;\n\t\tTextButton *_btnYes, *_btnNo;\n\t\tWindow *_window;\n\t\tText *_txtTitle;\n\tpublic:\n\t\t/// Creates the Confirm OXCE state.\n\t\tModConfirmExtendedState(ModListState *state, const ModInfo *modInfo, const ModInfo *masterInfo = nullptr);\n\t\t/// Cleans up the Confirm OXCE state.\n\t\t~ModConfirmExtendedState();\n\t\t/// Handler for clicking the Yes button.\n\t\tvoid btnYesClick(Action *action);\n\t\t/// Handler for clicking the No button.\n\t\tvoid btnNoClick(Action *action);\n\n\t\t/// Check if master mod is not valid.\n\t\tstatic bool isMasterNotValid(const ModInfo *masterInfo);\n\t\t/// Check if mod is not valid.\n\t\tstatic bool isModNotValid(const ModInfo *modInfo, const ModInfo *masterInfo);\n\n\t\t/// Show confirmation when mod require.\n\t\tstatic bool tryShowMasterNotValidConfirmationState(ModListState *state, const ModInfo *masterInfo);\n\t\t/// Show confirmation when mod require.\n\t\tstatic bool tryShowModNotValidConfirmationState(ModListState *state, const ModInfo *modInfo, const ModInfo *masterInfo);\n\t};\n\n}\n"
  },
  {
    "path": "src/Menu/ModListState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ModListState.h\"\n#include \"ModConfirmExtendedState.h\"\n#include <climits>\n#include <algorithm>\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/ComboBox.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Action.h\"\n#include \"StartState.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Mod Options window.\n * @param game Pointer to the core game.\n */\nModListState::ModListState() : _curMasterIdx(0)\n{\n\t// Create objects\n\t_window = new Window(this, 320, 200, 0, 0);\n\n\t_txtMaster = new Text(305, 9, 8, 8);\n\t_cbxMasters = new ComboBox(this, 305, 16, 8, 18);\n\t_lstMods = new TextList(288, 104, 8, 40);\n\n\t_btnOk = new TextButton(100, 16, 8, 176);\n\t_btnOpenFolder = new TextButton(100, 16, 110, 176);\n\t_btnCancel = new TextButton(100, 16, 212, 176);\n\n\t_txtTooltip = new Text(305, 25, 8, 148);\n\n\t// Set palette\n\tsetInterface(\"modsMenu\");\n\n\tadd(_window, \"window\", \"modsMenu\");\n\n\tadd(_txtMaster, \"text\", \"modsMenu\");\n\tadd(_lstMods, \"optionLists\", \"modsMenu\");\n\tadd(_btnOk, \"button2\", \"modsMenu\");\n\tadd(_btnOpenFolder, \"button2\", \"modsMenu\");\n\tadd(_btnCancel, \"button2\", \"modsMenu\");\n\tadd(_txtTooltip, \"tooltip\", \"modsMenu\");\n\n\tadd(_cbxMasters, \"button1\", \"modsMenu\");\n\n\tcenterAllSurfaces();\n\n\t// how much room do we need for YES/NO\n\tText text = Text(100, 9, 0, 0);\n\ttext.initText(_game->getMod()->getFont(\"FONT_BIG\"), _game->getMod()->getFont(\"FONT_SMALL\"), _game->getLanguage());\n\ttext.setText(tr(\"STR_YES\"));\n\tint yes = text.getTextWidth();\n\ttext.setText(tr(\"STR_NO\"));\n\tint no = text.getTextWidth();\n\n\tint rightcol = std::max(yes, no) + 2;\n\tint arrowCol = 25;\n\tint leftcol = _lstMods->getWidth() - (rightcol + arrowCol);\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"modsMenu\");\n\n\t_txtMaster->setText(tr(\"STR_BASE_GAME\"));\n\n\t// scan for masters\n\t//Options::refreshMods(); // TODO: uncomment (and properly test!) after mod.io integration is merged\n\tconst std::map<std::string, ModInfo> &modInfos(Options::getModInfos());\n\tstd::vector<std::string> masterNames;\n\tfor (const auto& pair : Options::mods)\n\t{\n\t\tconst auto& modId = pair.first;\n\t\tauto search = modInfos.find(modId);\n\t\tif (search == modInfos.end())\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\t\tconst ModInfo *modInfo = &modInfos.at(modId);\n\t\tif (!modInfo->isMaster())\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (pair.second)\n\t\t{\n\t\t\t_curMasterId = modId;\n\t\t}\n\t\telse if (_curMasterId.empty())\n\t\t{\n\t\t\t++_curMasterIdx;\n\t\t}\n\t\t_masters.push_back(modInfo);\n\t\tmasterNames.push_back(modInfo->getName());\n\t}\n\n\t_cbxMasters->setOptions(masterNames);\n\t_cbxMasters->setSelected(_curMasterIdx);\n\t_cbxMasters->onChange((ActionHandler)&ModListState::cbxMasterChange);\n\t_cbxMasters->onMouseIn((ActionHandler)&ModListState::txtTooltipIn);\n\t_cbxMasters->onMouseOut((ActionHandler)&ModListState::txtTooltipOut);\n\t_cbxMasters->onMouseOver((ActionHandler)&ModListState::cbxMasterHover);\n\t_cbxMasters->onListMouseIn((ActionHandler)&ModListState::txtTooltipIn);\n\t_cbxMasters->onListMouseOut((ActionHandler)&ModListState::txtTooltipOut);\n\t_cbxMasters->onListMouseOver((ActionHandler)&ModListState::cbxMasterHover);\n\n\t_lstMods->setArrowColumn(leftcol + 1, ARROW_VERTICAL);\n\t_lstMods->setColumns(3, leftcol, arrowCol, rightcol);\n\t_lstMods->setAlign(ALIGN_RIGHT, 1);\n\t_lstMods->setSelectable(true);\n\t_lstMods->setBackground(_window);\n\t_lstMods->setWordWrap(true);\n\t_lstMods->onMouseClick((ActionHandler)&ModListState::lstModsClick);\n\t_lstMods->onLeftArrowClick((ActionHandler)&ModListState::lstModsLeftArrowClick);\n\t_lstMods->onRightArrowClick((ActionHandler)&ModListState::lstModsRightArrowClick);\n\t_lstMods->onMousePress((ActionHandler)&ModListState::lstModsMousePress);\n\t_lstMods->onMouseIn((ActionHandler)&ModListState::txtTooltipIn);\n\t_lstMods->onMouseOut((ActionHandler)&ModListState::txtTooltipOut);\n\t_lstMods->onMouseOver((ActionHandler)&ModListState::lstModsHover);\n\tlstModsRefresh(0);\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&ModListState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&ModListState::btnOkClick, Options::keyOk);\n\n\t_btnOpenFolder->setText(tr(\"STR_OPEN_MODS_FOLDER\"));\n\t_btnOpenFolder->onMouseClick((ActionHandler)&ModListState::btnOpenFolderClick);\n#ifdef __MOBILE__\n\t_btnOpenFolder->setVisible(false);\n#endif\n\n\t_btnCancel->setText(tr(\"STR_CANCEL\"));\n\t_btnCancel->onMouseClick((ActionHandler)&ModListState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&ModListState::btnCancelClick, Options::keyCancel);\n\n\t_txtTooltip->setWordWrap(true);\n}\n\nModListState::~ModListState()\n{\n\n}\n\nstd::string ModListState::makeTooltip(const ModInfo &modInfo)\n{\n\treturn tr(\"STR_MODS_TOOLTIP\").arg(modInfo.getVersionDisplay()).arg(modInfo.getAuthor()).arg(modInfo.getDescription());\n}\n\nvoid ModListState::cbxMasterHover(Action *)\n{\n\t_txtTooltip->setText(makeTooltip(*_masters[_cbxMasters->getHoveredListIdx()]));\n}\n\nvoid ModListState::cbxMasterChange(Action *)\n{\n\tconst ModInfo *masterModInfo = _masters[_cbxMasters->getSelected()];\n\n\t// when changing a master mod, check if it requires OXCE\n\tif (ModConfirmExtendedState::tryShowMasterNotValidConfirmationState(this, masterModInfo))\n\t{\n\t\treturn;\n\t}\n\n\tchangeMasterMod();\n}\n\nvoid ModListState::changeMasterMod()\n{\n\tstd::string masterId = _masters[_cbxMasters->getSelected()]->getId();\n\tfor (auto& pair : Options::mods)\n\t{\n\t\tif (masterId == pair.first)\n\t\t{\n\t\t\tpair.second = true;\n\t\t}\n\t\telse if (_curMasterId == pair.first)\n\t\t{\n\t\t\tpair.second = false;\n\t\t}\n\t}\n\tOptions::reload = true;\n\n\t_curMasterIdx = _cbxMasters->getSelected();\n\t_curMasterId = masterId;\n\tlstModsRefresh(0);\n}\n\nvoid ModListState::revertMasterMod()\n{\n\t_cbxMasters->setSelected(_curMasterIdx);\n}\n\nvoid ModListState::lstModsRefresh(size_t scrollLoc)\n{\n\t_lstMods->clearList();\n\t_mods.clear();\n\n\t// only show mods that work with the current master\n\tfor (const auto& pair : Options::mods)\n\t{\n\t\tauto search = Options::getModInfos().find(pair.first);\n\t\tif (search == Options::getModInfos().end())\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\t\tModInfo modInfo = search->second;\n\t\tif (modInfo.isMaster() || !modInfo.canActivate(_curMasterId))\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\n\t\tstd::string modName = modInfo.getName();\n\t\t_lstMods->addRow(3, modName.c_str(), \"\", (pair.second ? tr(\"STR_YES\").c_str() : tr(\"STR_NO\").c_str()));\n\t\t_mods.push_back(pair);\n\t}\n\n\t_lstMods->scrollTo(scrollLoc);\n}\n\nvoid ModListState::lstModsHover(Action *)\n{\n\tsize_t selectedRow = _lstMods->getSelectedRow();\n\tif ((unsigned int)-1 != selectedRow)\n\t{\n\t\t_txtTooltip->setText(makeTooltip(Options::getModInfos().at(_mods[selectedRow].first)));\n\n\t}\n}\n\nvoid ModListState::lstModsClick(Action *action)\n{\n\tif (action->getAbsoluteXMouse() >= _lstMods->getArrowsLeftEdge() &&\n\t\taction->getAbsoluteXMouse() <= _lstMods->getArrowsRightEdge())\n\t{\n\t\t// don't count an arrow click as a mod enable toggle\n\t\treturn;\n\t}\n\n\tstd::pair<std::string, bool> &mod(_mods.at(_lstMods->getSelectedRow()));\n\n\t// when activating a mod, check if it requires OXCE\n\tif (!mod.second)\n\t{\n\t\tconst ModInfo *modInfo = &Options::getModInfos().at(mod.first);\n\t\tconst ModInfo *masterInfo = _masters[_cbxMasters->getSelected()];\n\n\t\tif (ModConfirmExtendedState::tryShowModNotValidConfirmationState(this, modInfo, masterInfo))\n\t\t{\n\t\t\treturn;\n\t\t}\n\t}\n\n\t// if deactivating, or if not OXCE mod\n\ttoggleMod();\n}\n\nvoid ModListState::toggleMod()\n{\n\tstd::pair<std::string, bool> &mod(_mods.at(_lstMods->getSelectedRow()));\n\n\tfor (auto& pair : Options::mods)\n\t{\n\t\tif (mod.first != pair.first)\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\n\t\tmod.second = ! mod.second;\n\t\tpair.second = mod.second;\n\t\t_lstMods->setCellText(_lstMods->getSelectedRow(), 2, (mod.second ? tr(\"STR_YES\") : tr(\"STR_NO\")));\n\n\t\tbreak;\n\t}\n\tOptions::reload = true;\n}\n\nvoid ModListState::lstModsLeftArrowClick(Action *action)\n{\n\tunsigned int row = _lstMods->getSelectedRow();\n\tif (row <= 0)\n\t{\n\t\treturn;\n\t}\n\n\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT)\n\t{\n\t\tmoveModUp(action, row);\n\t}\n\telse if (action->getDetails()->button.button == SDL_BUTTON_RIGHT)\n\t{\n\t\tmoveModUp(action, row, true);\n\t}\n}\n\nstatic void _moveAbove(const std::pair<std::string, bool> &srcMod, const std::pair<std::string, bool> &destMod)\n{\n\t// insert copy of srcMod above destMod\n\tfor (auto i = Options::mods.begin(); i != Options::mods.end(); ++i)\n\t{\n\t\tif (destMod.first == i->first)\n\t\t{\n\t\t\tOptions::mods.insert(i, srcMod);\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// remove old copy of srcMod in separate loop since the insert above invalidated the iterator\n\tfor (std::vector< std::pair<std::string, bool> >::reverse_iterator i = Options::mods.rbegin(); i != Options::mods.rend(); ++i)\n\t{\n\t\tif (srcMod.first == i->first)\n\t\t{\n\t\t\tOptions::mods.erase(i.base() - 1);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nvoid ModListState::moveModUp(Action *action, unsigned int row, bool max)\n{\n\tif (max)\n\t{\n\t\t_moveAbove(_mods.at(row), _mods.at(0));\n\t\t// don't change the scroll position\n\t\tlstModsRefresh(_lstMods->getScroll());\n\t}\n\telse\n\t{\n\t\t// calculate target scroll pos\n\t\tint curScrollPos = _lstMods->getScroll();\n\t\tint targetScrollPos = 0;\n\t\tfor (size_t i = 0; i < row - 1; ++i)\n\t\t{\n\t\t\ttargetScrollPos += _lstMods->getNumTextLines(i);\n\t\t}\n\t\tif (curScrollPos < targetScrollPos)\n\t\t{\n\t\t\tint ydiff = _lstMods->getTextHeight(row - 1);\n\t\t\tSDL_WarpMouse(action->getLeftBlackBand() + action->getXMouse(),\n\t\t\t\t action->getTopBlackBand() + action->getYMouse() - static_cast<Uint16>(ydiff * action->getYScale()));\n\t\t}\n\t\telse\n\t\t{\n\t\t\tint ydiff = _lstMods->getRowY(row) - _lstMods->getY();\n\t\t\tSDL_WarpMouse(action->getLeftBlackBand() + action->getXMouse(),\n\t\t\t\t action->getTopBlackBand() + action->getYMouse() - static_cast<Uint16>(ydiff * action->getYScale()));\n\t\t\t_lstMods->scrollTo(targetScrollPos);\n\t\t}\n\n\t\t_moveAbove(_mods.at(row), _mods.at(row - 1));\n\t\tlstModsRefresh(_lstMods->getScroll());\n\t}\n\tOptions::reload = true;\n}\n\nvoid ModListState::lstModsRightArrowClick(Action *action)\n{\n\tunsigned int row = _lstMods->getSelectedRow();\n\tsize_t numMods = _mods.size();\n\tif (0 >= numMods || INT_MAX < numMods || row >= numMods - 1)\n\t{\n\t\treturn;\n\t}\n\n\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT)\n\t{\n\t\tmoveModDown(action, row);\n\t}\n\telse if (action->getDetails()->button.button == SDL_BUTTON_RIGHT)\n\t{\n\t\tmoveModDown(action, row, true);\n\t}\n}\n\nstatic void _moveBelow(const std::pair<std::string, bool> &srcMod, const std::pair<std::string, bool> &destMod)\n{\n\t// insert copy of srcMod below destMod\n\tfor (std::vector< std::pair<std::string, bool> >::reverse_iterator i = Options::mods.rbegin(); i != Options::mods.rend(); ++i)\n\t{\n\t\tif (destMod.first == i->first)\n\t\t{\n\t\t\tOptions::mods.insert(i.base(), srcMod);\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// remove old copy of srcMod in separate loop since the insert above invalidated the iterator\n\tfor (auto i = Options::mods.begin(); i != Options::mods.end(); ++i)\n\t{\n\t\tif (srcMod.first == i->first)\n\t\t{\n\t\t\tOptions::mods.erase(i);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nvoid ModListState::moveModDown(Action *action, unsigned int row, bool max)\n{\n\tif (max)\n\t{\n\t\t_moveBelow(_mods.at(row), _mods.back());\n\t\t// don't change the scroll position\n\t\tlstModsRefresh(_lstMods->getScroll());\n\t}\n\telse\n\t{\n\t\t// calculate target scroll pos\n\t\tsize_t curScrollPos = _lstMods->getScroll();\n\t\tsize_t targetScrollPos = 0;\n\t\tfor (size_t i = 0; i <= row + 1; ++i)\n\t\t{\n\t\t\tif (i == row)\n\t\t\t{\n\t\t\t\t// don't count the current row -- it will be moved down\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\ttargetScrollPos += _lstMods->getNumTextLines(i);\n\t\t}\n\t\tif (curScrollPos + (int)_lstMods->getVisibleRows() > targetScrollPos)\n\t\t{\n\t\t\tint ydiff = _lstMods->getTextHeight(row + 1);\n\t\t\tSDL_WarpMouse(action->getLeftBlackBand() + action->getXMouse(),\n\t\t\t\t action->getTopBlackBand() + action->getYMouse() + static_cast<Uint16>(ydiff * action->getYScale()));\n\t\t}\n\t\telse\n\t\t{\n\t\t\tint ydiff = _lstMods->getY() + _lstMods->getHeight() - (_lstMods->getRowY(row) + _lstMods->getTextHeight(row));\n\t\t\tSDL_WarpMouse(action->getLeftBlackBand() + action->getXMouse(),\n\t\t\t\t action->getTopBlackBand() + action->getYMouse() + static_cast<Uint16>(ydiff * action->getYScale()));\n\t\t\t_lstMods->scrollTo(targetScrollPos - _lstMods->getVisibleRows() + 1);\n\t\t}\n\n\t\t_moveBelow(_mods.at(row), _mods.at(row + 1));\n\t\tlstModsRefresh(_lstMods->getScroll());\n\t}\n\tOptions::reload = true;\n}\n\nvoid ModListState::lstModsMousePress(Action *action)\n{\n\tif (Options::changeValueByMouseWheel == 0)\n\t\treturn;\n\tunsigned int row = _lstMods->getSelectedRow();\n\tsize_t numMods = _mods.size();\n\tif (action->getDetails()->button.button == SDL_BUTTON_WHEELUP &&\n\t\trow > 0)\n\t{\n\t\tif (action->getAbsoluteXMouse() >= _lstMods->getArrowsLeftEdge() &&\n\t\t\taction->getAbsoluteXMouse() <= _lstMods->getArrowsRightEdge())\n\t\t{\n\t\t\tmoveModUp(action, row);\n\t\t}\n\t}\n\telse if (action->getDetails()->button.button == SDL_BUTTON_WHEELDOWN &&\n\t\t\t 0 < numMods && INT_MAX >= numMods && row < numMods - 1)\n\t{\n\t\tif (action->getAbsoluteXMouse() >= _lstMods->getArrowsLeftEdge() &&\n\t\t\taction->getAbsoluteXMouse() <= _lstMods->getArrowsRightEdge())\n\t\t{\n\t\t\tmoveModDown(action, row);\n\t\t}\n\t}\n}\n\n/**\n * Restarts game with new mods.\n * @param action Pointer to an action.\n */\nvoid ModListState::btnOkClick(Action *)\n{\n\tOptions::save();\n\tif (Options::reload)\n\t{\n\t\t_game->setState(new StartState);\n\t}\n\telse\n\t{\n\t\t_game->popState();\n\t}\n}\n\n/**\n * Opens the mods folder.\n * @param action Pointer to an action.\n */\nvoid ModListState::btnOpenFolderClick(Action *)\n{\n\tstd::string path = Options::getUserFolder() + \"mods\";\n\tCrossPlatform::openExplorer(path);\n}\n\n/**\n * Ignores mod changes and returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid ModListState::btnCancelClick(Action *)\n{\n\tOptions::reload = false;\n\tOptions::load();\n\t_game->popState();\n}\n\n/**\n * Shows a tooltip for the appropriate button.\n * @param action Pointer to an action.\n */\nvoid ModListState::txtTooltipIn(Action *action)\n{\n\t_currentTooltip = action->getSender()->getTooltip();\n\t_txtTooltip->setText(tr(_currentTooltip));\n}\n\n/**\n * Clears the tooltip text.\n * @param action Pointer to an action.\n */\nvoid ModListState::txtTooltipOut(Action *action)\n{\n\tif (_currentTooltip == action->getSender()->getTooltip())\n\t{\n\t\t_txtTooltip->setText(\"\");\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Menu/ModListState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include \"../Engine/ModInfo.h\"\n#include <vector>\n#include <string>\n#include <utility>\n\nnamespace OpenXcom\n{\n\nclass Window;\nclass Text;\nclass TextList;\nclass TextButton;\nclass ComboBox;\n\n/**\n * Mods window to manage the installed mods.\n */\nclass ModListState : public State\n{\nprivate:\n\tWindow *_window;\n\tText *_txtMaster;\n\tComboBox *_cbxMasters;\n\tTextList *_lstMods;\n\tTextButton *_btnOk, *_btnCancel, *_btnOpenFolder;\n\tText *_txtTooltip;\n\tstd::string _currentTooltip;\n\tstd::vector<const ModInfo *> _masters;\n\tstd::string _curMasterId;\n\tstd::vector< std::pair<std::string, bool> > _mods;\n\tsize_t _curMasterIdx;\npublic:\n\t/// Creates the Mods state.\n\tModListState();\n\t/// Cleans up the Mods state.\n\t~ModListState();\n\tstd::string makeTooltip(const ModInfo &modInfo);\n\tvoid cbxMasterHover(Action *action);\n\tvoid cbxMasterChange(Action *action);\n\tvoid changeMasterMod();\n\tvoid revertMasterMod();\n\tvoid lstModsRefresh(size_t scrollLoc);\n\tvoid lstModsHover(Action *action);\n\t/// Handler for clicking an item on the menu.\n\tvoid lstModsClick(Action *action);\n\tvoid toggleMod();\n\t/// Handler for clicking the left reordering button.\n\tvoid lstModsLeftArrowClick(Action *action);\n\t/// Moves a mod up.\n\tvoid moveModUp(Action *action, unsigned int row, bool max = false);\n\t/// Handler for clicking the right reordering button.\n\tvoid lstModsRightArrowClick(Action *action);\n\t/// Moves a mod down.\n\tvoid moveModDown(Action *action, unsigned int row, bool max = false);\n\t/// Handler for pressing-down a mouse-button in the list.\n\tvoid lstModsMousePress(Action *action);\n\t/// Handler for showing tooltip.\n\tvoid txtTooltipIn(Action *action);\n\t/// Handler for hiding tooltip.\n\tvoid txtTooltipOut(Action *action);\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the Open Folder button.\n\tvoid btnOpenFolderClick(Action *action);\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Menu/NewBattleState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"NewBattleState.h\"\n#include <cmath>\n#include <algorithm>\n#include \"../Engine/Yaml.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/TextEdit.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Interface/ToggleTextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/ComboBox.h\"\n#include \"../Interface/Slider.h\"\n#include \"../Interface/Frame.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/Craft.h\"\n#include \"../Savegame/ItemContainer.h\"\n#include \"../Savegame/Soldier.h\"\n#include \"../Battlescape/BattlescapeGenerator.h\"\n#include \"../Battlescape/BriefingState.h\"\n#include \"../Savegame/Ufo.h\"\n#include \"../Savegame/MissionSite.h\"\n#include \"../Savegame/AlienBase.h\"\n#include \"../Mod/RuleCraft.h\"\n#include \"../Mod/RuleTerrain.h\"\n#include \"../Mod/AlienDeployment.h\"\n#include \"../Engine/RNG.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Logger.h\"\n#include \"../Basescape/CraftInfoState.h\"\n#include \"../Engine/CrossPlatform.h\"\n#include \"../Mod/RuleAlienMission.h\"\n#include \"../Mod/AlienRace.h\"\n#include \"../Mod/RuleGlobe.h\"\n#include \"../Mod/Texture.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the New Battle window.\n * @param game Pointer to the core game.\n */\nNewBattleState::NewBattleState() :\n\t_craft(0), _selectType(NewBattleSelectType::MISSION), _isRightClick(false),\n\t_depthVisible(false), _globeTextureVisible(false), _selectedGlobeTexture(0)\n{\n\t// Create objects\n\t_window = new Window(this, 320, 200, 0, 0, POPUP_BOTH);\n\t_btnQuickSearch = new TextEdit(this, 48, 9, 264, 183);\n\t_txtTitle = new Text(304, 17, 8, 9);\n\n\t_txtMapOptions = new Text(148, 9, 8, 68);\n\t_frameLeft = new Frame(148, 96, 8, 78);\n\t_txtAlienOptions = new Text(148, 9, 164, 68);\n\t_frameRight = new Frame(148, 96, 164, 78);\n\n\t_btnUfoLanded = new ToggleTextButton(100, 16, 212, 8);\n\n\t_txtMission = new Text(100, 9, 8, 30);\n\t_cbxMission = new ComboBox(this, 214, 16, 98, 26);\n\t_btnMission = new TextButton(16, 16, 81, 26);\n\n\t_txtCraft = new Text(100, 9, 8, 50);\n\t_cbxCraft = new ComboBox(this, 106, 16, 98, 46);\n\t_btnEquip = new TextButton(106, 16, 206, 46);\n\n\t_txtDarkness = new Text(120, 9, 22, 83);\n\t_slrDarkness = new Slider(120, 16, 22, 93);\n\n\t_txtTerrain = new Text(120, 9, 22, 113);\n\t_cbxTerrain = new ComboBox(this, 120, 16, 22+9, 123);\n\t_btnTerrain = new TextButton(16, 16, 5+9, 123);\n\n\t_txtDepth = new Text(120, 9, 22, 143);\n\t_slrDepth = new Slider(120, 16, 22, 153);\n\n\t_txtGlobeTexture = new Text(120, 9, 22, 143);\n\t_btnGlobeTexture = new TextButton(120, 16, 22, 153);\n\t_btnGlobeTextureToggle = new TextButton(16, 16, 145, 153);\n\n\t_txtDifficulty = new Text(120, 9, 178, 83);\n\t_cbxDifficulty = new ComboBox(this, 120, 16, 178, 93);\n\n\t_txtAlienRace = new Text(120, 9, 178, 113);\n\t_cbxAlienRace = new ComboBox(this, 120, 16, 178+9, 123);\n\t_btnAlienRace = new TextButton(16, 16, 161+9, 123);\n\n\t_txtAlienTech = new Text(120, 9, 178, 143);\n\t_slrAlienTech = new Slider(120, 16, 178, 153);\n\n\t_btnOk = new TextButton(100, 16, 8, 176);\n\t_btnCancel = new TextButton(100, 16, 110, 176);\n\t_btnRandom = new TextButton(100, 16, 212, 176);\n\n\t_lstSelect = new TextList(288, 144, 8, 28);\n\n\t// Set palette\n\tsetInterface(\"newBattleMenu\");\n\n\tadd(_window, \"window\", \"newBattleMenu\");\n\tadd(_btnQuickSearch, \"button1\", \"newBattleMenu\");\n\tadd(_txtTitle, \"heading\", \"newBattleMenu\");\n\tadd(_txtMapOptions, \"heading\", \"newBattleMenu\");\n\tadd(_frameLeft, \"frames\", \"newBattleMenu\");\n\tadd(_txtAlienOptions, \"heading\", \"newBattleMenu\");\n\tadd(_frameRight, \"frames\", \"newBattleMenu\");\n\n\tadd(_btnUfoLanded, \"button1\", \"newBattleMenu\");\n\n\tadd(_txtMission, \"text\", \"newBattleMenu\");\n\tadd(_txtCraft, \"text\", \"newBattleMenu\");\n\tadd(_btnEquip, \"button1\", \"newBattleMenu\");\n\n\tadd(_txtDarkness, \"text\", \"newBattleMenu\");\n\tadd(_slrDarkness, \"button1\", \"newBattleMenu\");\n\tadd(_txtDepth, \"text\", \"newBattleMenu\");\n\tadd(_slrDepth, \"button1\", \"newBattleMenu\");\n\tadd(_txtGlobeTexture, \"text\", \"newBattleMenu\");\n\tadd(_btnGlobeTexture, \"button1\", \"newBattleMenu\");\n\tadd(_btnGlobeTextureToggle, \"button1\", \"newBattleMenu\");\n\tadd(_txtTerrain, \"text\", \"newBattleMenu\");\n\tadd(_txtDifficulty, \"text\", \"newBattleMenu\");\n\tadd(_txtAlienRace, \"text\", \"newBattleMenu\");\n\tadd(_txtAlienTech, \"text\", \"newBattleMenu\");\n\tadd(_slrAlienTech, \"button1\", \"newBattleMenu\");\n\n\tadd(_btnOk, \"button2\", \"newBattleMenu\");\n\tadd(_btnCancel, \"button2\", \"newBattleMenu\");\n\tadd(_btnRandom, \"button2\", \"newBattleMenu\");\n\n\tadd(_btnMission, \"button1\", \"newBattleMenu\");\n\tadd(_btnTerrain, \"button1\", \"newBattleMenu\");\n\tadd(_btnAlienRace, \"button1\", \"newBattleMenu\");\n\n\tadd(_lstSelect, \"list\", \"newBattleMenu\");\n\n\tadd(_cbxTerrain, \"button1\", \"newBattleMenu\");\n\tadd(_cbxAlienRace, \"button1\", \"newBattleMenu\");\n\tadd(_cbxDifficulty, \"button1\", \"newBattleMenu\");\n\tadd(_cbxCraft, \"button1\", \"newBattleMenu\");\n\tadd(_cbxMission, \"button1\", \"newBattleMenu\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"newBattleMenu\");\n\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setBig();\n\t_txtTitle->setText(tr(\"STR_MISSION_GENERATOR\"));\n\n\t_txtMapOptions->setText(tr(\"STR_MAP_OPTIONS\"));\n\n\t_frameLeft->setThickness(3);\n\n\t_txtAlienOptions->setText(tr(\"STR_ALIEN_OPTIONS\"));\n\n\t_frameRight->setThickness(3);\n\n\t_btnUfoLanded->setText(tr(\"STR_LANDED\"));\n\t_btnUfoLanded->setVisible(Options::oxceCrashedOrLanded > 0);\n\t_btnUfoLanded->setPressed(Options::oxceCrashedOrLanded > 1);\n\t_txtTitle->setAlign(_btnUfoLanded->getVisible() ? ALIGN_LEFT : ALIGN_CENTER);\n\n\t_txtMission->setText(tr(\"STR_MISSION\"));\n\n\t_txtCraft->setText(tr(\"STR_CRAFT\"));\n\n\t_txtDarkness->setText(tr(\"STR_MAP_DARKNESS\"));\n\n\t_txtDepth->setText(tr(\"STR_MAP_DEPTH\"));\n\n\t_txtTerrain->setText(tr(\"STR_MAP_TERRAIN\"));\n\n\t_txtGlobeTexture->setText(tr(\"STR_GLOBE_TEXTURE\"));\n\t_txtGlobeTexture->setVisible(false);\n\n\t_txtDifficulty->setText(tr(\"STR_DIFFICULTY\"));\n\n\t_txtAlienRace->setText(tr(\"STR_ALIEN_RACE\"));\n\n\t_txtAlienTech->setText(tr(\"STR_ALIEN_TECH_LEVEL\"));\n\n\tif (Options::debug)\n\t{\n\t\t_missionTypes = _game->getMod()->getDeploymentsList();\n\t}\n\telse\n\t{\n\t\t_missionTypes.reserve(_game->getMod()->getDeploymentsList().size());\n\t\tfor (auto& deploymentName : _game->getMod()->getDeploymentsList())\n\t\t{\n\t\t\tauto* depl = _game->getMod()->getDeployment(deploymentName);\n\t\t\tif (depl && !depl->isHidden())\n\t\t\t{\n\t\t\t\t_missionTypes.push_back(deploymentName);\n\t\t\t}\n\t\t}\n\t}\n\t// ignore, hardcoded\n\t{\n\t\tauto itr = std::find(_missionTypes.begin(), _missionTypes.end(), RuleCraft::DEFAULT_CRAFT_DEPLOYMENT_PREVIEW);\n\t\tif (itr != _missionTypes.end())\n\t\t{\n\t\t\t_missionTypes.erase(itr);\n\t\t}\n\t}\n\t_cbxMission->setOptions(_missionTypes, true);\n\t_cbxMission->onChange((ActionHandler)&NewBattleState::cbxMissionChange);\n\n\tfor (auto& craftType : _game->getMod()->getCraftsList())\n\t{\n\t\tRuleCraft *rule = _game->getMod()->getCraft(craftType);\n\t\tif (rule->isForNewBattle())\n\t\t{\n\t\t\t_crafts.push_back(craftType);\n\t\t}\n\t}\n\t_cbxCraft->setOptions(_crafts, true);\n\t_cbxCraft->onChange((ActionHandler)&NewBattleState::cbxCraftChange);\n\n\t_slrDarkness->setRange(0, 15);\n\n\t_slrDepth->setRange(1, 3);\n\n\t_cbxTerrain->onChange((ActionHandler)&NewBattleState::cbxTerrainChange);\n\n\tfor (auto& pair : _game->getMod()->getGlobe()->getTexturesRaw())\n\t{\n\t\tif (pair.first >= 0 && !pair.second->isCosmeticOcean())\n\t\t{\n\t\t\t_globeTextures.push_back(\"GLOBE_TEXTURE_\" + std::to_string(pair.first));\n\t\t\t_globeTextureIDs.push_back(pair.first);\n\t\t}\n\t}\n\n\t_btnGlobeTexture->setText(tr(_globeTextures[_selectedGlobeTexture]));\n\t_btnGlobeTexture->onMouseClick((ActionHandler)&NewBattleState::btnGlobeTextureChange);\n\t_btnGlobeTexture->onMouseClick((ActionHandler)&NewBattleState::btnGlobeTextureChange, SDL_BUTTON_RIGHT);\n\t_btnGlobeTexture->setVisible(false);\n\n\t_btnGlobeTextureToggle->setText(\"*\");\n\t_btnGlobeTextureToggle->onMouseClick((ActionHandler)&NewBattleState::btnGlobeTextureToggle);\n\t_btnGlobeTextureToggle->setVisible(false);\n\n\tstd::vector<std::string> difficulty;\n\tdifficulty.push_back(tr(\"STR_1_BEGINNER\"));\n\tdifficulty.push_back(tr(\"STR_2_EXPERIENCED\"));\n\tdifficulty.push_back(tr(\"STR_3_VETERAN\"));\n\tdifficulty.push_back(tr(\"STR_4_GENIUS\"));\n\tdifficulty.push_back(tr(\"STR_5_SUPERHUMAN\"));\n\t_cbxDifficulty->setOptions(difficulty);\n\n\t_slrAlienTech->setRange(0, _game->getMod()->getAlienItemLevels().size()-1);\n\tif (_game->getMod()->getAlienItemLevels().size() <= 1)\n\t{\n\t\t_slrAlienTech->setVisible(false);\n\t\t_txtAlienTech->setVisible(false);\n\t}\n\n\t_btnEquip->setText(tr(\"STR_EQUIP_CRAFT\"));\n\t_btnEquip->onMouseClick((ActionHandler)&NewBattleState::btnEquipClick);\n\n\t_btnRandom->setText(tr(\"STR_RANDOMIZE\"));\n\t_btnRandom->onMouseClick((ActionHandler)&NewBattleState::btnRandomClick);\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&NewBattleState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&NewBattleState::btnOkClick, Options::keyOk);\n\n\t_btnCancel->setText(tr(\"STR_CANCEL\"));\n\t_btnCancel->onMouseClick((ActionHandler)&NewBattleState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&NewBattleState::btnCancelClick, Options::keyCancel);\n\n\tload();\n\n\t// -------------------------------\n\n\tbool showExtraButtons = _missionTypes.size() > TFTD_DEPLOYMENTS;\n\tif (!showExtraButtons)\n\t{\n\t\t_cbxTerrain->setX(_txtTerrain->getX());\n\t\t_cbxAlienRace->setX(_txtAlienRace->getX());\n\t}\n\n\t_btnMission->setText(\"...\");\n\t_btnMission->onMouseClick((ActionHandler)&NewBattleState::btnMissionChange);\n\t_btnMission->onMouseClick((ActionHandler)&NewBattleState::btnMissionChange, SDL_BUTTON_RIGHT);\n\t_btnMission->setVisible(showExtraButtons);\n\n\t_btnTerrain->setText(\"...\");\n\t_btnTerrain->onMouseClick((ActionHandler)&NewBattleState::btnTerrainChange);\n\t_btnTerrain->onMouseClick((ActionHandler)&NewBattleState::btnTerrainChange, SDL_BUTTON_RIGHT);\n\t_btnTerrain->setVisible(showExtraButtons);\n\n\t_btnAlienRace->setText(\"...\");\n\t_btnAlienRace->onMouseClick((ActionHandler)&NewBattleState::btnAlienRaceChange);\n\t_btnAlienRace->onMouseClick((ActionHandler)&NewBattleState::btnAlienRaceChange, SDL_BUTTON_RIGHT);\n\t_btnAlienRace->setVisible(showExtraButtons);\n\n\t_lstSelect->setColumns(1, 280);\n\t_lstSelect->setBackground(_window);\n\t_lstSelect->setAlign(ALIGN_CENTER);\n\t_lstSelect->setMargin(8);\n\t_lstSelect->setSelectable(true);\n\t_lstSelect->onMouseClick((ActionHandler)&NewBattleState::lstSelectClick);\n\t_lstSelect->onMouseClick((ActionHandler)&NewBattleState::lstSelectClick, SDL_BUTTON_RIGHT);\n\t_lstSelect->onMouseClick((ActionHandler)&NewBattleState::lstSelectClick, SDL_BUTTON_MIDDLE);\n\t_lstSelect->setVisible(false);\n\n\t_btnQuickSearch->setText(\"\"); // redraw\n\t_btnQuickSearch->onEnter((ActionHandler)&NewBattleState::btnQuickSearchApply);\n\t_btnQuickSearch->setVisible(false);\n\n\t_btnCancel->onKeyboardRelease((ActionHandler)&NewBattleState::btnQuickSearchToggle, Options::keyToggleQuickSearch);\n}\n\n/**\n *\n */\nNewBattleState::~NewBattleState()\n{\n\n}\n\n/**\n * Handle key shortcuts.\n * @param action Pointer to an action.\n */\nvoid NewBattleState::handle(Action* action)\n{\n\tState::handle(action);\n\n\tif (action->getDetails()->type == SDL_KEYDOWN)\n\t{\n\t\t// F11 - show/hide \"UFO crashed\" toggle button\n\t\tif (action->getDetails()->key.keysym.sym == SDLK_F11)\n\t\t{\n\t\t\t_btnUfoLanded->setVisible(!_btnUfoLanded->getVisible());\n\t\t\t_txtTitle->setAlign(_btnUfoLanded->getVisible() ? ALIGN_LEFT : ALIGN_CENTER);\n\t\t}\n\t}\n}\n\n/**\n * Resets the menu music and savegame\n * when coming back from the battlescape.\n */\nvoid NewBattleState::init()\n{\n\tState::init();\n\n\tif (_craft == 0)\n\t{\n\t\tload();\n\t}\n}\n\n/**\n * Loads new battle data from a YAML file.\n * @param filename YAML filename.\n */\nvoid NewBattleState::load(const std::string &filename)\n{\n\tstd::string s = Options::getMasterUserFolder() + filename + \".cfg\";\n\tif (!CrossPlatform::fileExists(s))\n\t{\n\t\tinitSave();\n\t}\n\telse\n\t{\n\t\ttry\n\t\t{\n\t\t\tYAML::YamlRootNodeReader cfgReader(s);\n\t\t\t_cbxMission->setSelected(std::min(cfgReader[\"mission\"].readVal<size_t>(0), _missionTypes.size() - 1));\n\t\t\tcbxMissionChange(0);\n\t\t\t_cbxCraft->setSelected(std::min(cfgReader[\"craft\"].readVal<size_t>(0), _crafts.size() - 1));\n\t\t\t_slrDarkness->setValue(cfgReader[\"darkness\"].readVal<size_t>(0));\n\t\t\t_cbxTerrain->setSelected(std::min(cfgReader[\"terrain\"].readVal<size_t>(0), _terrainTypes.size() - 1));\n\t\t\tcbxTerrainChange(0);\n\t\t\t{\n\t\t\t\t_selectedGlobeTexture = std::min(cfgReader[\"globeTexture\"].readVal<size_t>(0), _globeTextures.size() - 1);\n\t\t\t\t_btnGlobeTexture->setText(tr(_globeTextures[_selectedGlobeTexture]));\n\t\t\t}\n\t\t\t_cbxAlienRace->setSelected(std::min(cfgReader[\"alienRace\"].readVal<size_t>(0), _alienRaces.size() - 1));\n\t\t\t_cbxDifficulty->setSelected(cfgReader[\"difficulty\"].readVal<size_t>(0));\n\t\t\t_slrAlienTech->setValue(cfgReader[\"alienTech\"].readVal<size_t>(0));\n\n\t\t\tif (cfgReader[\"base\"])\n\t\t\t{\n\t\t\t\tconst Mod *mod = _game->getMod();\n\t\t\t\tSavedGame *save = new SavedGame();\n\n\t\t\t\tBase *base = new Base(mod);\n\t\t\t\tbase->load(cfgReader[\"base\"], save, false);\n\t\t\t\tsave->getBases()->push_back(base);\n\n\t\t\t\t// Add research\n\t\t\t\tsave->makeAllResearchDiscovered(mod);\n\n\t\t\t\t// Generate items\n\t\t\t\tbase->getStorageItems()->clear();\n\t\t\t\tfor (auto& itemType : mod->getItemsList())\n\t\t\t\t{\n\t\t\t\t\tRuleItem *rule = _game->getMod()->getItem(itemType);\n\t\t\t\t\tif (rule->getBattleType() != BT_CORPSE && rule->isRecoverable())\n\t\t\t\t\t{\n\t\t\t\t\t\tbase->getStorageItems()->addItem(rule, 1);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Fix invalid contents\n\t\t\t\tif (base->getCrafts()->empty())\n\t\t\t\t{\n\t\t\t\t\tstd::string craftType = _crafts[_cbxCraft->getSelected()];\n\t\t\t\t\t_craft = new Craft(_game->getMod()->getCraft(craftType), base, save->getId(craftType));\n\t\t\t\t\tbase->getCrafts()->push_back(_craft);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t_craft = base->getCrafts()->front();\n\t\t\t\t}\n\n\t\t\t\t_game->setSavedGame(save);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tinitSave();\n\t\t\t}\n\t\t}\n\t\tcatch (YAML::Exception &e)\n\t\t{\n\t\t\tLog(LOG_WARNING) << e.what();\n\t\t\tinitSave();\n\t\t}\n\t}\n\n\tYAML::YamlRootNodeReader starterBaseReader(_game->getMod()->getDefaultStartingBase(), \"(starting base template)\");\n\tif (const auto& globalTemplates = starterBaseReader[\"globalTemplates\"])\n\t{\n\t\t_game->getSavedGame()->loadTemplates(globalTemplates, _game->getMod());\n\t}\n\tif (const auto& ufopediaRuleStatus = starterBaseReader[\"ufopediaRuleStatus\"])\n\t{\n\t\t_game->getSavedGame()->loadUfopediaRuleStatus(ufopediaRuleStatus);\n\t}\n\n}\n\n/**\n * Saves new battle data to a YAML file.\n * @param filename YAML filename.\n */\nvoid NewBattleState::save(const std::string &filename)\n{\n\tYAML::YamlRootNodeWriter writer;\n\twriter.setAsMap();\n\twriter.write(\"mission\", _cbxMission->getSelected());\n\twriter.write(\"craft\", _cbxCraft->getSelected());\n\twriter.write(\"darkness\", _slrDarkness->getValue());\n\twriter.write(\"terrain\", _cbxTerrain->getSelected());\n\twriter.write(\"globeTexture\", _selectedGlobeTexture);\n\twriter.write(\"alienRace\", _cbxAlienRace->getSelected());\n\twriter.write(\"difficulty\", _cbxDifficulty->getSelected());\n\twriter.write(\"alienTech\", _slrAlienTech->getValue());\n\t_game->getSavedGame()->getBases()->front()->save(writer[\"base\"]);\n\n\tstd::string filepath = Options::getMasterUserFolder() + filename + \".cfg\";\n\tif (!CrossPlatform::writeFile(filepath, writer.emit().yaml))\n\t{\n\t\tLog(LOG_WARNING) << \"Failed to save \" << filepath;\n\t\treturn;\n\t}\n}\n\n/**\n * Initializes a new savegame with\n * everything available.\n */\nvoid NewBattleState::initSave()\n{\n\tconst Mod *mod = _game->getMod();\n\tSavedGame *save = new SavedGame();\n\tBase *base = new Base(mod);\n\tYAML::YamlRootNodeReader startingBaseReader(_game->getMod()->getDefaultStartingBase(), \"(starting base template)\");\n\tbase->load(startingBaseReader, save, true, true);\n\tsave->getBases()->push_back(base);\n\n\t// Kill everything we don't want in this base\n\tfor (auto* soldier : *base->getSoldiers())\n\t{\n\t\tdelete soldier;\n\t}\n\tbase->getSoldiers()->clear();\n\tfor (auto* xcraft : *base->getCrafts())\n\t{\n\t\tdelete xcraft;\n\t}\n\tbase->getCrafts()->clear();\n\tbase->getStorageItems()->clear();\n\n\t_craft = new Craft(mod->getCraft(_crafts[_cbxCraft->getSelected()]), base, 1);\n\tbase->getCrafts()->push_back(_craft);\n\n\t// Generate soldiers\n\tbool psiStrengthEval = (Options::psiStrengthEval && save->isResearched(mod->getPsiRequirements()));\n\tfor (int i = 0; i < 30; ++i)\n\t{\n\t\tint randomType = RNG::generate(0, mod->getSoldiersList().size() - 1);\n\t\tRuleSoldier* ruleSoldier = mod->getSoldier(mod->getSoldiersList().at(randomType), true);\n\t\tint nationality = save->selectSoldierNationalityByLocation(mod, ruleSoldier, nullptr); // -1\n\t\tSoldier *soldier = mod->genSoldier(save, ruleSoldier, nationality);\n\n\t\tfor (int n = 0; n < 5; ++n)\n\t\t{\n\t\t\tif (RNG::percent(70))\n\t\t\t\tcontinue;\n\t\t\tsoldier->promoteRank();\n\n\t\t\tUnitStats* stats = soldier->getCurrentStatsEditable();\n\t\t\tstats->tu\t\t\t+= RNG::generate(0, 5);\n\t\t\tstats->stamina\t\t+= RNG::generate(0, 5);\n\t\t\tstats->health\t\t+= RNG::generate(0, 5);\n\t\t\tstats->bravery\t\t+= RNG::generate(0, 5);\n\t\t\tstats->reactions\t+= RNG::generate(0, 5);\n\t\t\tstats->firing\t\t+= RNG::generate(0, 5);\n\t\t\tstats->throwing\t\t+= RNG::generate(0, 5);\n\t\t\tstats->strength\t\t+= RNG::generate(0, 5);\n\t\t\tstats->mana\t\t\t+= RNG::generate(0, 5);\n\t\t\tstats->psiStrength\t+= RNG::generate(0, 5);\n\t\t\tstats->melee\t\t+= RNG::generate(0, 5);\n\t\t\tstats->psiSkill\t\t+= RNG::generate(0, 20);\n\t\t}\n\t\tUnitStats* stats = soldier->getCurrentStatsEditable();\n\t\tstats->bravery = (int)ceil(stats->bravery / 10.0) * 10; // keep it a multiple of 10\n\n\t\t// update again, could have been changed since soldier creation\n\t\tsoldier->calcStatString(mod->getStatStrings(), psiStrengthEval);\n\n\t\tbase->getSoldiers()->push_back(soldier);\n\n\t\tint space = _craft->getSpaceAvailable();\n\t\tif (_craft->validateAddingSoldier(space, soldier) == CPE_None)\n\t\t{\n\t\t\tsoldier->setCraft(_craft);\n\t\t}\n\t}\n\n\t// Generate items\n\tfor (auto& itemType : mod->getItemsList())\n\t{\n\t\tconst RuleItem *rule = _game->getMod()->getItem(itemType);\n\t\tif (rule->getBattleType() != BT_CORPSE && rule->isRecoverable())\n\t\t{\n\t\t\tint howMany = rule->getBattleType() == BT_AMMO ? 2 : 1;\n\t\t\tbase->getStorageItems()->addItem(rule, howMany);\n\t\t\tif (rule->getBattleType() != BT_NONE && rule->isInventoryItem())\n\t\t\t{\n\t\t\t\t_craft->getItems()->addItem(rule, howMany);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Add research\n\tsave->makeAllResearchDiscovered(mod);\n\n\t_game->setSavedGame(save);\n\tcbxMissionChange(0);\n}\n\n/**\n * Starts the battle.\n * @param action Pointer to an action.\n */\nvoid NewBattleState::btnOkClick(Action *)\n{\n\tif (_craft)\n\t{\n\t\t// just in case somebody manually edited battle.cfg\n\t\t_craft->resetCustomDeployment();\n\t}\n\tsave();\n\tif (_missionTypes[_cbxMission->getSelected()] != \"STR_BASE_DEFENSE\" && _craft->getNumTotalUnits() == 0)\n\t{\n\t\treturn;\n\t}\n\n\tSavedBattleGame *bgame = new SavedBattleGame(_game->getMod(), _game->getLanguage());\n\t_game->getSavedGame()->setBattleGame(bgame);\n\tbgame->setMissionType(_missionTypes[_cbxMission->getSelected()]);\n\tBattlescapeGenerator bgen = BattlescapeGenerator(_game);\n\tBase *base = 0;\n\n\tbgen.setTerrain(_game->getMod()->getTerrain(_terrainTypes[_cbxTerrain->getSelected()]));\n\n\tif (_globeTextureVisible)\n\t{\n\t\tint textureId = _globeTextureIDs[_selectedGlobeTexture];\n\t\tauto* globeTexture = _game->getMod()->getGlobe()->getTexture(textureId);\n\t\tbgen.setWorldTexture(nullptr, globeTexture);\n\t}\n\n\t// base defense\n\tif (_missionTypes[_cbxMission->getSelected()] == \"STR_BASE_DEFENSE\")\n\t{\n\t\tbase = _craft->getBase();\n\t\tbgen.setBase(base);\n\t\t_craft = 0;\n\t}\n\t// alien base\n\telse if (_game->getMod()->getDeployment(bgame->getMissionType())->isAlienBase())\n\t{\n\t\tAlienBase *b = new AlienBase(_game->getMod()->getDeployment(bgame->getMissionType()), -1);\n\t\tb->setId(1);\n\t\tb->setAlienRace(_alienRaces[_cbxAlienRace->getSelected()]);\n\t\t_craft->setDestination(b);\n\t\tbgen.setAlienBase(b);\n\t\t_game->getSavedGame()->getAlienBases()->push_back(b);\n\t}\n\t// ufo assault\n\telse if (_craft && _game->getMod()->getUfo(_missionTypes[_cbxMission->getSelected()]))\n\t{\n\t\tUfo *u = new Ufo(_game->getMod()->getUfo(_missionTypes[_cbxMission->getSelected()]), 1);\n\t\tu->setId(1);\n\t\t_craft->setDestination(u);\n\t\tbgen.setUfo(u);\n\t\t// either ground assault or ufo crash\n\t\tbool ufoLanded = _btnUfoLanded->getVisible() ? _btnUfoLanded->getPressed() : RNG::generate(0, 1) == 1;\n\t\tif (ufoLanded)\n\t\t{\n\t\t\tu->setStatus(Ufo::LANDED);\n\t\t\tbgame->setMissionType(\"STR_UFO_GROUND_ASSAULT\");\n\t\t}\n\t\telse\n\t\t{\n\t\t\tu->setStatus(Ufo::CRASHED);\n\t\t\tbgame->setMissionType(\"STR_UFO_CRASH_RECOVERY\");\n\t\t}\n\t\t_game->getSavedGame()->getUfos()->push_back(u);\n\t}\n\t// mission site\n\telse\n\t{\n\t\tconst AlienDeployment *deployment = _game->getMod()->getDeployment(bgame->getMissionType());\n\t\tconst RuleAlienMission *mission = _game->getMod()->getAlienMission(_game->getMod()->getAlienMissionList().front()); // doesn't matter\n\t\tMissionSite *m = new MissionSite(mission, deployment, nullptr);\n\t\tm->setId(1);\n\t\tm->setAlienRace(_alienRaces[_cbxAlienRace->getSelected()]);\n\t\t_craft->setDestination(m);\n\t\tbgen.setMissionSite(m);\n\t\t_game->getSavedGame()->getMissionSites()->push_back(m);\n\t}\n\n\tif (_craft)\n\t{\n\t\t_craft->setSpeed(0);\n\t\tbgen.setCraft(_craft);\n\t}\n\n\t_game->getSavedGame()->setDifficulty((GameDifficulty)_cbxDifficulty->getSelected());\n\n\tbgen.setWorldShade(_slrDarkness->getValue());\n\tbgen.setAlienRace(_alienRaces[_cbxAlienRace->getSelected()]);\n\tbgen.setAlienItemlevel(_slrAlienTech->getValue());\n\tbgame->setDepth(_slrDepth->getValue());\n\n\tbgen.run();\n\n\t_game->popState();\n\t_game->popState();\n\t_game->pushState(new BriefingState(_craft, base));\n\t_craft = 0;\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid NewBattleState::btnCancelClick(Action *)\n{\n\tif (!_surfaceBackup.empty())\n\t{\n\t\tcleanup();\n\t\treturn;\n\t}\n\n\tsave();\n\t_game->setSavedGame(0);\n\t_game->popState();\n}\n\n/**\n * Randomize the state\n * @param action Pointer to an action.\n */\nvoid NewBattleState::btnRandomClick(Action *)\n{\n\tinitSave();\n\n\t_cbxMission->setSelected(RNG::generate(0, _missionTypes.size()-1));\n\tcbxMissionChange(0);\n\t_cbxCraft->setSelected(RNG::generate(0, _crafts.size() - 1));\n\tcbxCraftChange(0);\n\t_slrDarkness->setValue(RNG::generate(0, 15));\n\t_cbxTerrain->setSelected(RNG::generate(0, _terrainTypes.size() - 1));\n\tcbxTerrainChange(0);\n\t_cbxAlienRace->setSelected(RNG::generate(0, _alienRaces.size()-1));\n\t_cbxDifficulty->setSelected(RNG::generate(0, 4));\n\t_slrAlienTech->setValue(RNG::generate(0, _game->getMod()->getAlienItemLevels().size()-1));\n}\n\n/**\n * Shows the Craft Info screen.\n * @param action Pointer to an action.\n */\nvoid NewBattleState::btnEquipClick(Action *)\n{\n\t_game->pushState(new CraftInfoState(_game->getSavedGame()->getBases()->front(), 0));\n}\n\n/**\n * Updates Map Options based on the\n * current Mission type.\n * @param action Pointer to an action.\n */\nvoid NewBattleState::cbxMissionChange(Action *)\n{\n\tAlienDeployment *ruleDeploy = _game->getMod()->getDeployment(_missionTypes[_cbxMission->getSelected()]);\n\tstd::set<std::string> terrains;\n\n\t// Get terrains associated with this mission\n\tstd::vector<std::string> deployTerrains, globeTerrains;\n\tdeployTerrains = ruleDeploy->getTerrains();\n\tif (deployTerrains.empty())\n\t{\n\t\tglobeTerrains = _game->getMod()->getGlobe()->getTerrains(\"\");\n\t}\n\telse\n\t{\n\t\tglobeTerrains = _game->getMod()->getGlobe()->getTerrains(ruleDeploy->getType());\n\t}\n\tfor (const auto& terrain : deployTerrains)\n\t{\n\t\tterrains.insert(terrain);\n\t}\n\tfor (const auto& terrain : globeTerrains)\n\t{\n\t\tterrains.insert(terrain);\n\t}\n\t_terrainTypes.clear();\n\tstd::vector<std::string> terrainStrings;\n\tfor (const auto& terrain : terrains)\n\t{\n\t\t_terrainTypes.push_back(terrain);\n\t\tterrainStrings.push_back(\"MAP_\" + terrain);\n\t}\n\n\t// Hide controls that don't apply to mission\n\t_txtDarkness->setVisible(ruleDeploy->getShade() == -1);\n\t_slrDarkness->setVisible(ruleDeploy->getShade() == -1);\n\t_txtTerrain->setVisible(_terrainTypes.size() > 1);\n\t_cbxTerrain->setVisible(_terrainTypes.size() > 1);\n\t_cbxTerrain->setOptions(terrainStrings, true);\n\t_cbxTerrain->setSelected(0);\n\t_btnTerrain->setVisible(_missionTypes.size() > TFTD_DEPLOYMENTS && _terrainTypes.size() > 1);\n\tcbxTerrainChange(0);\n}\n\n/**\n * Updates craft accordingly.\n * @param action Pointer to an action.\n */\nvoid NewBattleState::cbxCraftChange(Action *)\n{\n\t_craft->changeRules(_game->getMod()->getCraft(_crafts[_cbxCraft->getSelected()]));\n\n\tint count = 0;\n\tCraft* tmpCraft = new Craft(_craft->getRules(), _craft->getBase(), 0);\n\n\t// temporarily re-assign all soldiers to a dummy craft\n\tfor (auto* soldier : *_craft->getBase()->getSoldiers())\n\t{\n\t\tif (soldier->getCraft() == _craft)\n\t\t{\n\t\t\tsoldier->setCraft(tmpCraft);\n\t\t\tcount++;\n\t\t}\n\t}\n\t// try assigning all soldiers back while validating constraints\n\tfor (auto* soldier : *_craft->getBase()->getSoldiers())\n\t{\n\t\tif (count <= 0)\n\t\t{\n\t\t\tbreak;\n\t\t}\n\t\tif (soldier->getCraft() == tmpCraft)\n\t\t{\n\t\t\tcount--;\n\t\t\tint space = _craft->getSpaceAvailable();\n\t\t\tif (_craft->validateAddingSoldier(space, soldier) == CPE_None)\n\t\t\t{\n\t\t\t\tsoldier->setCraft(_craft);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tsoldier->setCraft(0);\n\t\t\t}\n\t\t}\n\t}\n\tdelete tmpCraft;\n\n\t// FIXME? HWPs can still violate the constraints (e.g. when switching from Avenger to Lightning)\n}\n\n/**\n * Updates the depth slider accordingly when terrain selection changes.\n * @param action Pointer to an action.\n */\nvoid NewBattleState::cbxTerrainChange(Action *)\n{\n\tAlienDeployment *ruleDeploy = _game->getMod()->getDeployment(_missionTypes[_cbxMission->getSelected()]);\n\tint minDepth = 0;\n\tint maxDepth = 0;\n\tif (ruleDeploy->getMaxDepth() > 0 || _game->getMod()->getTerrain(_terrainTypes.at(_cbxTerrain->getSelected()))->getMaxDepth() > 0 ||\n\t\t(!ruleDeploy->getTerrains().empty() && _game->getMod()->getTerrain(ruleDeploy->getTerrains().front())->getMaxDepth() > 0))\n\t{\n\t\tminDepth = 1;\n\t\tmaxDepth = 3;\n\t}\n\t_depthVisible = (minDepth != maxDepth);\n\t_txtDepth->setVisible(_depthVisible);\n\t_slrDepth->setVisible(_depthVisible);\n\t_slrDepth->setRange(minDepth, maxDepth);\n\t_slrDepth->setValue(minDepth);\n\n\t{\n\t\tint found = ruleDeploy->hasTextureBasedScript(_game->getMod());\n\t\tif (found == -1)\n\t\t{\n\t\t\t// there is no map script on the alien deployment at all, perform the check on the terrain\n\t\t\tauto* ruleTerrain = _game->getMod()->getTerrain(_terrainTypes[_cbxTerrain->getSelected()]);\n\t\t\tfound = ruleTerrain->hasTextureBasedScript(_game->getMod());\n\t\t}\n\t\t_globeTextureVisible = (found == 1);\n\n\t\t_txtGlobeTexture->setVisible(_globeTextureVisible);\n\t\t_btnGlobeTexture->setVisible(_globeTextureVisible);\n\n\t\t// if both are visible\n\t\tif (_globeTextureVisible && _depthVisible)\n\t\t{\n\t\t\t// hide the depth slider\n\t\t\t_txtDepth->setVisible(false);\n\t\t\t_slrDepth->setVisible(false);\n\t\t\t// and allow toggling between the texture selector and depth slider\n\t\t\t_btnGlobeTextureToggle->setVisible(true);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// not needed\n\t\t\t_btnGlobeTextureToggle->setVisible(false);\n\t\t}\n\t}\n\n\t// Get races \"supported\" by this mission\n\t_alienRaces = _game->getMod()->getAlienRacesList();\n\tint maxAlienRank = ruleDeploy->getMaxAlienRank();\n\tfor (auto iter = _alienRaces.begin(); iter != _alienRaces.end();)\n\t{\n\t\tconst auto& alienRace = (*iter);\n\t\tif (alienRace.find(\"_UNDERWATER\") != std::string::npos)\n\t\t{\n\t\t\titer = _alienRaces.erase(iter);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tstd::string raceName = (minDepth != maxDepth) ? alienRace + \"_UNDERWATER\" : alienRace;\n\t\t\tauto* raceRules = _game->getMod()->getAlienRace(raceName);\n\t\t\tif (!raceRules || maxAlienRank >= raceRules->getMembers())\n\t\t\t{\n\t\t\t\t// not enough members or race doesn't exist\n\t\t\t\titer = _alienRaces.erase(iter);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t++iter;\n\t\t\t}\n\t\t}\n\t}\n\t_cbxAlienRace->setOptions(_alienRaces, true);\n\tif (_cbxAlienRace->getSelected() >= _alienRaces.size())\n\t{\n\t\t_cbxAlienRace->setSelected(0);\n\t}\n}\n\n/**\n * Shows the advanced mission selector.\n */\nvoid NewBattleState::btnMissionChange(Action *action)\n{\n\tfillList(NewBattleSelectType::MISSION, _game->isRightClick(action));\n}\n\n/**\n * Shows the advanced terrain selector.\n */\nvoid NewBattleState::btnTerrainChange(Action *action)\n{\n\tfillList(NewBattleSelectType::TERRAIN, _game->isRightClick(action));\n}\n\n/**\n * Shows the advanced globe texture selector.\n */\nvoid NewBattleState::btnGlobeTextureChange(Action *action)\n{\n\tfillList(NewBattleSelectType::GLOBETEXTURE, _game->isRightClick(action));\n}\n\n/**\n * Toggles between the globe texture selector and depth slider.\n */\nvoid NewBattleState::btnGlobeTextureToggle(Action *action)\n{\n\t_txtDepth->setVisible(!_txtDepth->getVisible());\n\t_slrDepth->setVisible(!_slrDepth->getVisible());\n\n\t_txtGlobeTexture->setVisible(!_txtGlobeTexture->getVisible());\n\t_btnGlobeTexture->setVisible(!_btnGlobeTexture->getVisible());\n}\n\n/**\n * Shows the advanced alien race selector.\n */\nvoid NewBattleState::btnAlienRaceChange(Action *action)\n{\n\tfillList(NewBattleSelectType::ALIENRACE, _game->isRightClick(action));\n}\n\n/**\n * Fills the advanced selector with data.\n */\nvoid NewBattleState::fillList(NewBattleSelectType selectType, bool isRightClick)\n{\n\t_selectType = selectType;\n\t_isRightClick = isRightClick;\n\n\tbool firstRun = false;\n\tif (_surfaceBackup.empty())\n\t{\n\t\tfirstRun = true;\n\t\tfor (auto* surface : _surfaces)\n\t\t{\n\t\t\t_surfaceBackup[surface] = surface->getVisible();\n\t\t\tsurface->setVisible(false);\n\t\t}\n\t\t_window->setVisible(true);\n\t\t_txtTitle->setVisible(true);\n\t\t_btnCancel->setVisible(true);\n\t\t_btnRandom->setVisible(false);\n\t\t_lstSelect->setVisible(true);\n\t\t_btnQuickSearch->setVisible(Options::oxceQuickSearchButton);\n\t}\n\n\tstd::string searchString = _btnQuickSearch->getText();\n\tUnicode::upperCase(searchString);\n\n\tsize_t counter = 0;\n\tauto fill = [&](const std::vector<std::string>& list, bool prefix, size_t scroll)\n\t{\n\t\tfor (auto& m : list)\n\t\t{\n\t\t\tif (!searchString.empty())\n\t\t\t{\n\t\t\t\tstd::string itemName;\n\t\t\t\tif (_isRightClick) { itemName = m; } else { itemName = tr(prefix ? \"MAP_\" + m : m); }\n\t\t\t\tUnicode::upperCase(itemName);\n\t\t\t\tif (itemName.find(searchString) == std::string::npos)\n\t\t\t\t{\n\t\t\t\t\tcounter++;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\t_filtered.push_back(counter);\n\t\t\tcounter++;\n\t\t\t_lstSelect->addRow(1, _isRightClick ? m.c_str() : tr(prefix ? \"MAP_\" + m : m).c_str());\n\t\t}\n\t\tif (firstRun && _lstSelect->isScrollbarVisible()) _lstSelect->scrollTo(scroll);\n\t};\n\n\t_filtered.clear();\n\t_lstSelect->clearList();\n\tif (_selectType == NewBattleSelectType::MISSION)\n\t{\n\t\tfill(_missionTypes, false, _cbxMission->getSelected());\n\t}\n\telse if (_selectType == NewBattleSelectType::TERRAIN)\n\t{\n\t\tfill(_terrainTypes, true, _cbxTerrain->getSelected());\n\t}\n\telse if (_selectType == NewBattleSelectType::GLOBETEXTURE)\n\t{\n\t\tfill(_globeTextures, false, _selectedGlobeTexture);\n\t}\n\telse if (_selectType == NewBattleSelectType::ALIENRACE)\n\t{\n\t\tfill(_alienRaces, false, _cbxAlienRace->getSelected());\n\t}\n}\n\n/**\n * L-click: Selects an item from the advanced selector and closes the selector.\n * R-click: Displays the code of the selected item.\n * M-click: Displays the translation of the selected item.\n */\nvoid NewBattleState::lstSelectClick(Action *action)\n{\n\tauto selected = _lstSelect->getSelectedRow();\n\n\t// quick toggle\n\tif (_game->isRightClick(action) || _game->isMiddleClick(action))\n\t{\n\t\tauto& list =\n\t\t\t(_selectType == NewBattleSelectType::MISSION ? _missionTypes :\n\t\t\t(_selectType == NewBattleSelectType::TERRAIN ? _terrainTypes :\n\t\t\t(_selectType == NewBattleSelectType::GLOBETEXTURE ? _globeTextures : _alienRaces)));\n\t\tstd::string s = list[_filtered[selected]];\n\t\tif (_game->isMiddleClick(action))\n\t\t{\n\t\t\ts = tr((_selectType == NewBattleSelectType::TERRAIN) ? \"MAP_\" + s : s);\n\t\t}\n\t\t_lstSelect->setCellText(selected, 0, s.c_str());\n\t\treturn;\n\t}\n\n\t// restore the GUI\n\tcleanup();\n\n\t// select the new value\n\tif (_selectType == NewBattleSelectType::MISSION)\n\t{\n\t\t_cbxMission->setSelected(_filtered[selected]);\n\t\tcbxMissionChange(0);\n\t}\n\telse if (_selectType == NewBattleSelectType::TERRAIN)\n\t{\n\t\t_cbxTerrain->setSelected(_filtered[selected]);\n\t\tcbxTerrainChange(0);\n\t}\n\telse if (_selectType == NewBattleSelectType::GLOBETEXTURE)\n\t{\n\t\t_selectedGlobeTexture = _filtered[selected];\n\t\t_btnGlobeTexture->setText(tr(_globeTextures[_selectedGlobeTexture]));\n\t}\n\telse if (_selectType == NewBattleSelectType::ALIENRACE)\n\t{\n\t\t_cbxAlienRace->setSelected(_filtered[selected]);\n\t}\n}\n\n/**\n * Restores the GUI after closing the advanced selector.\n */\nvoid NewBattleState::cleanup()\n{\n\t_btnQuickSearch->setText(\"\");\n\t_btnQuickSearch->setVisible(false);\n\n\tfor (auto& surfacePair : _surfaceBackup)\n\t{\n\t\tsurfacePair.first->setVisible(surfacePair.second);\n\t}\n\t_surfaceBackup.clear();\n}\n\n/**\n * Quick search toggle.\n * @param action Pointer to an action.\n */\nvoid NewBattleState::btnQuickSearchToggle(Action *action)\n{\n\tif (_surfaceBackup.empty())\n\t{\n\t\treturn;\n\t}\n\n\tif (_btnQuickSearch->getVisible())\n\t{\n\t\t_btnQuickSearch->setText(\"\");\n\t\t_btnQuickSearch->setVisible(false);\n\t\tbtnQuickSearchApply(action);\n\t}\n\telse\n\t{\n\t\t_btnQuickSearch->setVisible(true);\n\t\t_btnQuickSearch->setFocus(true);\n\t}\n}\n\n/**\n * Quick search.\n * @param action Pointer to an action.\n */\nvoid NewBattleState::btnQuickSearchApply(Action *)\n{\n\tfillList(_selectType, _isRightClick);\n}\n\n}\n"
  },
  {
    "path": "src/Menu/NewBattleState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include <map>\n#include <vector>\n#include <string>\n\nnamespace OpenXcom\n{\n\nenum class NewBattleSelectType { MISSION = 0, TERRAIN, ALIENRACE, GLOBETEXTURE };\n\nclass TextButton;\nclass TextEdit;\nclass TextList;\nclass ToggleTextButton;\nclass Window;\nclass Text;\nclass ComboBox;\nclass Slider;\nclass Frame;\nclass Craft;\n\n/**\n * New Battle that displays a list\n * of options to configure a new\n * standalone mission.\n */\nclass NewBattleState : public State\n{\nprivate:\n\tWindow *_window;\n\tFrame *_frameLeft, *_frameRight;\n\tText *_txtTitle, *_txtMapOptions, *_txtAlienOptions;\n\tText *_txtMission, *_txtCraft, *_txtDarkness, *_txtTerrain, *_txtDifficulty, *_txtAlienRace, *_txtAlienTech, *_txtDepth;\n\tComboBox *_cbxMission, *_cbxCraft, *_cbxTerrain, *_cbxDifficulty, *_cbxAlienRace;\n\tSlider *_slrDarkness, *_slrAlienTech, *_slrDepth;\n\tTextButton *_btnOk, *_btnCancel, *_btnEquip, *_btnRandom;\n\tTextButton *_btnMission, *_btnTerrain, *_btnAlienRace;\n\tText *_txtGlobeTexture;\n\tTextButton *_btnGlobeTexture;\n\tTextButton *_btnGlobeTextureToggle;\n\tToggleTextButton *_btnUfoLanded;\n\tTextList *_lstSelect;\n\tTextEdit *_btnQuickSearch;\n\tstd::map<Surface*, bool> _surfaceBackup;\n\tstd::vector<std::string> _missionTypes, _terrainTypes, _alienRaces, _crafts;\n\tstd::vector<std::string> _globeTextures;\n\tstd::vector<int> _globeTextureIDs;\n\tCraft *_craft;\n\tNewBattleSelectType _selectType;\n\tbool _isRightClick;\n\tbool _depthVisible, _globeTextureVisible;\n\tsize_t _selectedGlobeTexture;\n\tstd::vector<size_t> _filtered;\n\n\tstatic const int TFTD_DEPLOYMENTS = 22;\n\tvoid fillList(NewBattleSelectType selectType, bool isRightClick);\n\tvoid cleanup();\npublic:\n\t/// Creates the New Battle state.\n\tNewBattleState();\n\t/// Cleans up the New Battle state.\n\t~NewBattleState();\n\t/// Handle keypresses.\n\tvoid handle(Action* action) override;\n\t/// Resets state.\n\tvoid init() override;\n\t/// Loads New Battle settings.\n\tvoid load(const std::string &filename = \"battle\");\n\t/// Saves New Battle settings.\n\tvoid save(const std::string &filename = \"battle\");\n\t/// Initializes a blank savegame.\n\tvoid initSave();\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action *action);\n\t/// Handler for clicking the Randomize button.\n\tvoid btnRandomClick(Action *action);\n\t/// Handler for clicking the Equip Craft button.\n\tvoid btnEquipClick(Action *action);\n\t/// Handler for changing the Mission combobox.\n\tvoid cbxMissionChange(Action *action);\n\t/// Handler for changing the Craft combobox.\n\tvoid cbxCraftChange(Action *action);\n\t/// Updates the depth slider accordingly when terrain selection changes.\n\tvoid cbxTerrainChange(Action *action);\n\t/// Handler for clicking the Mission... button.\n\tvoid btnMissionChange(Action *action);\n\t/// Handler for clicking the Terrain... button.\n\tvoid btnTerrainChange(Action *action);\n\t/// Handlers for clicking the Globe Texture buttons.\n\tvoid btnGlobeTextureChange(Action *action);\n\tvoid btnGlobeTextureToggle(Action *action);\n\t/// Handler for clicking the Alien Race... button.\n\tvoid btnAlienRaceChange(Action *action);\n\t/// Handler for clicking the Select list.\n\tvoid lstSelectClick(Action *action);\n\t/// Handlers for Quick Search.\n\tvoid btnQuickSearchToggle(Action *action);\n\tvoid btnQuickSearchApply(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Menu/NewGameState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"NewGameState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/ToggleTextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Geoscape/GeoscapeState.h\"\n#include \"../Geoscape/BuildNewBaseState.h\"\n#include \"../Geoscape/BaseNameState.h\"\n#include \"../Basescape/PlaceLiftState.h\"\n#include \"../Engine/Options.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Base.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Difficulty window.\n * @param game Pointer to the core game.\n */\nNewGameState::NewGameState()\n{\n\t// Create objects\n\t_window = new Window(this, 192, 180, 64, 10, POPUP_VERTICAL);\n\t_btnBeginner = new TextButton(160, 18, 80, 32);\n\t_btnExperienced = new TextButton(160, 18, 80, 52);\n\t_btnVeteran = new TextButton(160, 18, 80, 72);\n\t_btnGenius = new TextButton(160, 18, 80, 92);\n\t_btnSuperhuman = new TextButton(160, 18, 80, 112);\n\t_btnIronman = new ToggleTextButton(78, 18, 80, 138);\n\t_btnOk = new TextButton(78, 16, 80, 164);\n\t_btnCancel = new TextButton(78, 16, 162, 164);\n\t_txtTitle = new Text(192, 9, 64, 20);\n\t_txtIronman = new Text(90, 24, 162, 135);\n\n\tswitch (_game->getMod()->getStartingDifficulty())\n\t{\n\tcase 0:\n\t\t_difficulty = _btnBeginner;\n\t\tbreak;\n\tcase 1:\n\t\t_difficulty = _btnExperienced;\n\t\tbreak;\n\tcase 2:\n\t\t_difficulty = _btnVeteran;\n\t\tbreak;\n\tcase 3:\n\t\t_difficulty = _btnGenius;\n\t\tbreak;\n\tcase 4:\n\t\t_difficulty = _btnSuperhuman;\n\t\tbreak;\n\tdefault:\n\t\t_difficulty = _btnBeginner;\n\t\tbreak;\n\t}\n\n\t// Set palette\n\tsetInterface(\"newGameMenu\");\n\n\tadd(_window, \"window\", \"newGameMenu\");\n\tadd(_btnBeginner, \"button\", \"newGameMenu\");\n\tadd(_btnExperienced, \"button\", \"newGameMenu\");\n\tadd(_btnVeteran, \"button\", \"newGameMenu\");\n\tadd(_btnGenius, \"button\", \"newGameMenu\");\n\tadd(_btnSuperhuman, \"button\", \"newGameMenu\");\n\tadd(_btnIronman, \"ironman\", \"newGameMenu\");\n\tadd(_btnOk, \"button\", \"newGameMenu\");\n\tadd(_btnCancel, \"button\", \"newGameMenu\");\n\tadd(_txtTitle, \"text\", \"newGameMenu\");\n\tadd(_txtIronman, \"ironman\", \"newGameMenu\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"newGameMenu\");\n\n\t_btnBeginner->setText(tr(\"STR_1_BEGINNER\"));\n\t_btnBeginner->setGroup(&_difficulty);\n\n\t_btnExperienced->setText(tr(\"STR_2_EXPERIENCED\"));\n\t_btnExperienced->setGroup(&_difficulty);\n\n\t_btnVeteran->setText(tr(\"STR_3_VETERAN\"));\n\t_btnVeteran->setGroup(&_difficulty);\n\n\t_btnGenius->setText(tr(\"STR_4_GENIUS\"));\n\t_btnGenius->setGroup(&_difficulty);\n\n\t_btnSuperhuman->setText(tr(\"STR_5_SUPERHUMAN\"));\n\t_btnSuperhuman->setGroup(&_difficulty);\n\n\t_btnIronman->setText(tr(\"STR_IRONMAN\"));\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&NewGameState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&NewGameState::btnOkClick, Options::keyOk);\n\n\t_btnCancel->setText(tr(\"STR_CANCEL\"));\n\t_btnCancel->onMouseClick((ActionHandler)&NewGameState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&NewGameState::btnCancelClick, Options::keyCancel);\n\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_SELECT_DIFFICULTY_LEVEL\"));\n\n\t_txtIronman->setWordWrap(true);\n\t_txtIronman->setVerticalAlign(ALIGN_MIDDLE);\n\t_txtIronman->setText(tr(\"STR_IRONMAN_DESC\"));\n}\n\n/**\n *\n */\nNewGameState::~NewGameState()\n{\n\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid NewGameState::btnOkClick(Action *)\n{\n\tGameDifficulty diff = DIFF_BEGINNER;\n\tif (_difficulty == _btnBeginner)\n\t{\n\t\tdiff = DIFF_BEGINNER;\n\t}\n\telse if (_difficulty == _btnExperienced)\n\t{\n\t\tdiff = DIFF_EXPERIENCED;\n\t}\n\telse if (_difficulty == _btnVeteran)\n\t{\n\t\tdiff = DIFF_VETERAN;\n\t}\n\telse if (_difficulty == _btnGenius)\n\t{\n\t\tdiff = DIFF_GENIUS;\n\t}\n\telse if (_difficulty == _btnSuperhuman)\n\t{\n\t\tdiff = DIFF_SUPERHUMAN;\n\t}\n\n\t// Reset touch flags\n\t_game->resetTouchButtonFlags();\n\n\tSavedGame *save = _game->getMod()->newSave(diff);\n\tsave->setDifficulty(diff);\n\tsave->setIronman(_btnIronman->getPressed());\n\t_game->setSavedGame(save);\n\n\tGeoscapeState *gs = new GeoscapeState;\n\t_game->setState(gs);\n\tgs->init();\n\n\tauto* base = _game->getSavedGame()->getBases()->back();\n\tif (base->getMarker() != -1)\n\t{\n\t\t// location known already\n\t\tbase->calculateServices(save);\n\n\t\t// center and rotate 35 degrees down (to see the base location while typoing its name)\n\t\tgs->getGlobe()->center(base->getLongitude(), base->getLatitude() + 0.61);\n\n\t\tif (base->getName().empty())\n\t\t{\n\t\t\t// fixed location, custom name\n\t\t\t_game->pushState(new BaseNameState(base, gs->getGlobe(), true, true));\n\t\t}\n\t\telse if (Options::customInitialBase)\n\t\t{\n\t\t\t// fixed location, fixed name\n\t\t\t_game->pushState(new PlaceLiftState(base, gs->getGlobe(), true));\n\t\t}\n\t}\n\telse\n\t{\n\t\t// custom location, custom name\n\t\t_game->pushState(new BuildNewBaseState(base, gs->getGlobe(), true));\n\t}\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid NewGameState::btnCancelClick(Action *)\n{\n\t_game->setSavedGame(0);\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Menu/NewGameState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass ToggleTextButton;\nclass Window;\nclass Text;\n\n/**\n * New Game window that displays a list\n * of possible difficulties for creating\n * a saved game.\n */\nclass NewGameState : public State\n{\nprivate:\n\tTextButton *_btnBeginner, *_btnExperienced, *_btnVeteran, *_btnGenius, *_btnSuperhuman;\n\tTextButton *_difficulty;\n\tToggleTextButton *_btnIronman;\n\tTextButton *_btnOk, *_btnCancel;\n\tWindow *_window;\n\tText *_txtTitle, *_txtIronman;\npublic:\n\t/// Creates the New Game state.\n\tNewGameState();\n\t/// Cleans up the New Game state.\n\t~NewGameState();\n\t/// Handler for clicking the Ok button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Menu/NotesState.cpp",
    "content": "/*\n * Copyright 2010-2020 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"NotesState.h\"\n#include <algorithm>\n#include \"../Engine/Action.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/TextEdit.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Interface/ToggleTextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Savegame/SavedGame.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Notes screen.\n * @param origin Game section that originated this state.\n */\nNotesState::NotesState(OptionsOrigin origin) : _origin(origin), _previousSelectedRow(-1), _selectedRow(-1)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 320, 200, 0, 0, POPUP_NONE);\n\t_txtTitle = new Text(310, 17, 5, 7);\n\t_txtDelete = new Text(310, 9, 5, 23);\n\t_lstNotes = new TextList(288, 120, 8, 42);\n\t_edtNote = new TextEdit(this, 268, 9, 0, 0);\n\t_btnSave = new TextButton(80, 16, 60, 172);\n\t_btnCancel = new TextButton(80, 16, 180, 172);\n\t_btnDelete = new ToggleTextButton(288, 16, 16, 23);\n\n\t// Set palette\n\tsetInterface(\"geoscape\", true, _game->getSavedGame() ? _game->getSavedGame()->getSavedBattle() : 0);\n\n\tadd(_window, \"window\", \"noteMenu\");\n\tadd(_txtTitle, \"text\", \"noteMenu\");\n\tadd(_txtDelete, \"text\", \"noteMenu\");\n\tadd(_lstNotes, \"list\", \"noteMenu\");\n\tadd(_edtNote);\n\tadd(_btnSave, \"button\", \"noteMenu\");\n\tadd(_btnCancel, \"button\", \"noteMenu\");\n\tadd(_btnDelete, \"button\", \"noteMenu\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"noteMenu\");\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_NOTES\"));\n\n#ifdef __MOBILE__\n\t_txtDelete->setVisible(false);\n\t_btnDelete->setText(tr(\"STR_RIGHT_CLICK_TO_DELETE\"));\n#else\n\t_btnDelete->setVisible(false);\n\t_txtDelete->setAlign(ALIGN_CENTER);\n\t_txtDelete->setText(tr(\"STR_RIGHT_CLICK_TO_DELETE\"));\n#endif\n\n\t_lstNotes->setColumns(1, 288);\n\t_lstNotes->setSelectable(true);\n\t_lstNotes->setBackground(_window);\n\t_lstNotes->setMargin(8);\n\t_lstNotes->setWordWrap(true); // just in case someone modifies the save manually\n\t_lstNotes->onMousePress((ActionHandler)&NotesState::lstNotesPress);\n\n\t_edtNote->setColor(_lstNotes->getSecondaryColor());\n\t_edtNote->setVisible(false);\n\t_edtNote->onKeyboardPress((ActionHandler)&NotesState::edtNoteKeyPress);\n\n\t_btnSave->setText(tr(\"STR_SAVE_UC\"));\n\t_btnSave->onMouseClick((ActionHandler)&NotesState::btnSaveClick);\n\t//_btnSave->onKeyboardPress((ActionHandler)&NotesState::btnSaveClick, Options::keyOk);\n\n\t_btnCancel->setText(tr(\"STR_CANCEL_UC\"));\n\t_btnCancel->onMouseClick((ActionHandler)&NotesState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&NotesState::btnCancelClick, Options::keyCancel);\n}\n\n/**\n *\n */\nNotesState::~NotesState()\n{\n\n}\n\n/**\n * Refreshes the Notes state.\n */\nvoid NotesState::init()\n{\n\tState::init();\n\n\tif (_origin == OPT_BATTLESCAPE)\n\t{\n\t\tapplyBattlescapeTheme(\"noteMenu\");\n\t}\n\n\tupdateList();\n}\n\n/**\n * Updates the Notes list.\n */\nvoid NotesState::updateList()\n{\n\t_lstNotes->clearList();\n\n\tint row = 0;\n\tint color = _lstNotes->getSecondaryColor();\n\n\tfor (const auto& note : _game->getSavedGame()->getUserNotes())\n\t{\n\t\t_lstNotes->addRow(1, note.c_str());\n\t\trow++;\n\t}\n\n\t_lstNotes->addRow(1, tr(\"STR_NEW_NOTE\").c_str());\n\tif (_origin != OPT_BATTLESCAPE)\n\t{\n\t\t_lstNotes->setRowColor(_lstNotes->getLastRowIndex(), color);\n\t}\n\t_lstNotes->scrollDown(true);\n}\n\n/**\n * Returns to the previous screen without saving anything.\n * @param action Pointer to an action.\n */\nvoid NotesState::btnCancelClick(Action*)\n{\n\t_game->popState();\n}\n\n/**\n * Allows to enter, edit and delete notes.\n * @param action Pointer to an action.\n */\nvoid NotesState::lstNotesPress(Action* action)\n{\n\t// ignore scrolling, process only LMB and RMB\n\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT || action->getDetails()->button.button == SDL_BUTTON_RIGHT)\n\t{\n\t\t_previousSelectedRow = _selectedRow;\n\t\t_selectedRow = _lstNotes->getSelectedRow();\n\n\t\t// restore previous\n\t\tif (_previousSelectedRow > -1)\n\t\t{\n\t\t\t_lstNotes->setCellText(_previousSelectedRow, 0, _selectedNote);\n\t\t}\n\n\t\t// back up current\n\t\t_selectedNote = _lstNotes->getCellText(_selectedRow, 0);\n\t}\n\n\tif (action->getDetails()->button.button == SDL_BUTTON_RIGHT || _btnDelete->getPressed())\n\t{\n\t\tif (_edtNote->isFocused())\n\t\t{\n\t\t\t// cancel editing the current note\n\t\t\t_edtNote->setText(\"\");\n\t\t\t_edtNote->setVisible(false);\n\t\t\t_edtNote->setFocus(false, false);\n\t\t\t_lstNotes->setScrolling(true);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// any row except for the last\n\t\t\tif (_selectedRow >= 0 && _selectedRow < _lstNotes->getLastRowIndex())\n\t\t\t{\n\t\t\t\t// delete the selected note\n\t\t\t\t_selectedNote = \"\";\n\t\t\t\t_lstNotes->setCellText(_selectedRow, 0, _selectedNote);\n\t\t\t}\n\t\t}\n\t}\n\telse if (action->getDetails()->button.button == SDL_BUTTON_LEFT)\n\t{\n\t\t// temporarily set to empty during editing\n\t\t_lstNotes->setCellText(_selectedRow, 0, \"\");\n\n\t\t// set the initial text for editing\n\t\tif (_selectedRow == _lstNotes->getLastRowIndex())\n\t\t{\n\t\t\t_edtNote->setText(\"\");\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_edtNote->setText(_selectedNote);\n\t\t}\n\t\t_edtNote->setX(_lstNotes->getColumnX(0));\n\t\t_edtNote->setY(_lstNotes->getRowY(_selectedRow));\n\t\t_edtNote->setVisible(true);\n\t\t_edtNote->setFocus(true, false);\n\t\t_lstNotes->setScrolling(false);\n\t}\n}\n\n/**\n * Updates the currently edited note.\n * @param action Pointer to an action.\n */\nvoid NotesState::edtNoteKeyPress(Action* action)\n{\n\tif (action->getDetails()->key.keysym.sym == SDLK_RETURN ||\n\t\taction->getDetails()->key.keysym.sym == SDLK_KP_ENTER)\n\t{\n\t\t// update the selected note\n\t\t_selectedNote = _edtNote->getText();\n\t\t_lstNotes->setCellText(_selectedRow, 0, _selectedNote);\n\n\t\t// clean up\n\t\t_edtNote->setText(\"\");\n\t\t_edtNote->setVisible(false);\n\t\t_edtNote->setFocus(false, false);\n\t\t_lstNotes->setScrolling(true);\n\n\t\t// if we're adding a new note...\n\t\tif (_selectedRow == _lstNotes->getLastRowIndex())\n\t\t{\n\t\t\t// change color to normal\n\t\t\t_lstNotes->setRowColor(_lstNotes->getLastRowIndex(), _lstNotes->getColor());\n\n\t\t\t// add a new empty note\n\t\t\t_lstNotes->addRow(1, tr(\"STR_NEW_NOTE\").c_str());\n\t\t\tif (_origin != OPT_BATTLESCAPE)\n\t\t\t{\n\t\t\t\t_lstNotes->setRowColor(_lstNotes->getLastRowIndex(), _lstNotes->getSecondaryColor());\n\t\t\t}\n\t\t\t_lstNotes->scrollDown(true);\n\t\t}\n\t}\n}\n\n/**\n * Saves all changes and returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid NotesState::btnSaveClick(Action*)\n{\n\tif (_edtNote->isFocused())\n\t{\n\t\t// edit still in progress\n\t\treturn;\n\t}\n\n\t// overwrite everything, no way back :)\n\tauto& notes = _game->getSavedGame()->getUserNotes();\n\tnotes.clear();\n\tif (_lstNotes->getTexts() > 1)\n\t{\n\t\t// ignore last row\n\t\tfor (int i = 0; i < _lstNotes->getLastRowIndex(); ++i)\n\t\t{\n\t\t\tstd::string note = _lstNotes->getCellText(i, 0);\n\t\t\tif (!note.empty())\n\t\t\t{\n\t\t\t\tnotes.push_back(note);\n\t\t\t}\n\t\t}\n\t}\n\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Menu/NotesState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2020 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include \"OptionsBaseState.h\"\n#include <string>\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass TextEdit;\nclass TextList;\nclass ToggleTextButton;\n\n/**\n * Allows the player to take notes.\n */\nclass NotesState : public State\n{\nprotected:\n\tWindow* _window;\n\tText* _txtTitle;\n\tText* _txtDelete;\n\tTextList* _lstNotes;\n\tTextEdit* _edtNote;\n\tTextButton* _btnSave;\n\tTextButton* _btnCancel;\n\tToggleTextButton* _btnDelete;\n\n\tOptionsOrigin _origin;\n\tstd::string _selectedNote;\n\tint _previousSelectedRow, _selectedRow;\n\n\t/// Updates the Notes list.\n\tvoid updateList();\npublic:\n\t/// Creates the Notes state.\n\tNotesState(OptionsOrigin origin);\n\t/// Cleans up the Notes state.\n\t~NotesState();\n\t/// Refreshes the Notes state.\n\tvoid init() override;\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action* action);\n\t/// Handler for clicking the Notes list.\n\tvoid lstNotesPress(Action* action);\n\t/// Handler for pressing a key on the Note edit.\n\tvoid edtNoteKeyPress(Action* action);\n\t/// Handler for clicking on the Save button.\n\tvoid btnSaveClick(Action* action);\n};\n\n}\n"
  },
  {
    "path": "src/Menu/OptionsAdvancedState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"OptionsAdvancedState.h\"\n#include <sstream>\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleInterface.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Action.h\"\n#include <algorithm>\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Advanced Options window.\n * @param game Pointer to the core game.\n * @param origin Game section that originated this state.\n */\nOptionsAdvancedState::OptionsAdvancedState(OptionsOrigin origin) : OptionsBaseState(origin)\n{\n\tsetCategory(_btnAdvanced);\n\n\t// Create objects\n\t_btnOXC = new TextButton(70, 16, 94, 8);\n\t_btnOXCE = new TextButton(70, 16, 168, 8);\n\t_btnOTHER = new TextButton(70, 16, 242, 8);\n\t_lstOptions = new TextList(200, 120, 94, 26);\n\n\t_owner = _btnOXC;\n\n\t_isTFTD = false;\n\tfor (const auto& pair : Options::mods)\n\t{\n\t\tif (pair.second)\n\t\t{\n\t\t\tif (pair.first == \"xcom2\")\n\t\t\t{\n\t\t\t\t_isTFTD = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tadd(_btnOXC, \"button\", \"advancedMenu\");\n\tadd(_btnOXCE, \"button\", \"advancedMenu\");\n\tadd(_btnOTHER, \"button\", \"advancedMenu\");\n\n\tif (origin != OPT_BATTLESCAPE)\n\t{\n\t\t_greyedOutColor = _game->getMod()->getInterface(\"advancedMenu\")->getElement(\"disabledUserOption\")->color;\n\t\tadd(_lstOptions, \"optionLists\", \"advancedMenu\");\n\t}\n\telse\n\t{\n\t\t_greyedOutColor = _game->getMod()->getInterface(\"battlescape\")->getElement(\"disabledUserOption\")->color;\n\t\tadd(_lstOptions, \"optionLists\", \"battlescape\");\n\t}\n\n\tcenterAllSurfaces();\n\n\t_btnOXC->setText(tr(\"STR_ENGINE_OXC\"));\n\t_btnOXC->setGroup(&_owner);\n\t_btnOXC->onMousePress((ActionHandler)&OptionsAdvancedState::btnGroupPress, SDL_BUTTON_LEFT);\n\n\t_btnOXCE->setText(tr(\"STR_ENGINE_OXCE\"));\n\t_btnOXCE->setGroup(&_owner);\n\t_btnOXCE->onMousePress((ActionHandler)&OptionsAdvancedState::btnGroupPress, SDL_BUTTON_LEFT);\n\n\t_btnOTHER->setText(tr(\"STR_ENGINE_OTHER\")); // rename in your fork\n\t_btnOTHER->setGroup(&_owner);\n\t_btnOTHER->onMousePress((ActionHandler)&OptionsAdvancedState::btnGroupPress, SDL_BUTTON_LEFT);\n\t_btnOTHER->setVisible(false); // enable in your fork\n\n\t// how much room do we need for YES/NO\n\tText text = Text(100, 9, 0, 0);\n\ttext.initText(_game->getMod()->getFont(\"FONT_BIG\"), _game->getMod()->getFont(\"FONT_SMALL\"), _game->getLanguage());\n\ttext.setText(tr(\"STR_YES\"));\n\tint yes = text.getTextWidth();\n\ttext.setText(tr(\"STR_NO\"));\n\tint no = text.getTextWidth();\n\n\tint rightcol = std::max(yes, no) + 2;\n\tint leftcol = _lstOptions->getWidth() - rightcol;\n\n\t// Set up objects\n\t_lstOptions->setAlign(ALIGN_RIGHT, 1);\n\t_lstOptions->setColumns(2, leftcol, rightcol);\n\t_lstOptions->setWordWrap(true);\n\t_lstOptions->setSelectable(true);\n\t_lstOptions->setBackground(_window);\n\t_lstOptions->onMouseClick((ActionHandler)&OptionsAdvancedState::lstOptionsClick, 0);\n\t_lstOptions->onMouseOver((ActionHandler)&OptionsAdvancedState::lstOptionsMouseOver);\n\t_lstOptions->onMouseOut((ActionHandler)&OptionsAdvancedState::lstOptionsMouseOut);\n\n\t_colorGroup = _lstOptions->getSecondaryColor();\n\n\tfor (const auto& optionInfo : Options::getOptionInfo())\n\t{\n\t\tif (optionInfo.type() != OPTION_KEY && !optionInfo.description().empty())\n\t\t{\n\t\t\tif (optionInfo.category() == \"STR_GENERAL\")\n\t\t\t{\n\t\t\t\t_settingsGeneral[optionInfo.owner()].push_back(optionInfo);\n\t\t\t}\n\t\t\telse if (optionInfo.category() == \"STR_GEOSCAPE\")\n\t\t\t{\n\t\t\t\t_settingsGeo[optionInfo.owner()].push_back(optionInfo);\n\t\t\t}\n\t\t\telse if (optionInfo.category() == \"STR_BASESCAPE\")\n\t\t\t{\n\t\t\t\t_settingsBase[optionInfo.owner()].push_back(optionInfo);\n\t\t\t}\n\t\t\telse if (optionInfo.category() == \"STR_BATTLESCAPE\")\n\t\t\t{\n\t\t\t\t_settingsBattle[optionInfo.owner()].push_back(optionInfo);\n\t\t\t}\n\t\t\telse if (optionInfo.category() == \"STR_AI\")\n\t\t\t{\n\t\t\t\t_settingsAI[optionInfo.owner()].push_back(optionInfo);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n *\n */\nOptionsAdvancedState::~OptionsAdvancedState()\n{\n\n}\n\n/**\n * Refreshes the UI.\n */\nvoid OptionsAdvancedState::init()\n{\n\tOptionsBaseState::init();\n\n\tupdateList();\n}\n\n/**\n * Fills the settings list based on category.\n */\nvoid OptionsAdvancedState::updateList()\n{\n\tOptionOwner idx = _owner == _btnOXC ? OPTION_OXC : _owner == _btnOXCE ? OPTION_OXCE : OPTION_OTHER;\n\n\t_offsetGeneralMin = -1;\n\t_offsetGeneralMax = -1;\n\t_offsetGeoMin = -1;\n\t_offsetGeoMax = -1;\n\t_offsetBaseMin = -1;\n\t_offsetBaseMax = -1;\n\t_offsetBattleMin = -1;\n\t_offsetBattleMax = -1;\n\t_offsetAIMin = -1;\n\t_offsetAIMax = -1;\n\n\t_lstOptions->clearList();\n\n\tint row = -1;\n\n\tif (_settingsGeneral[idx].size() > 0)\n\t{\n\t\t_lstOptions->addRow(2, tr(\"STR_GENERAL\").c_str(), \"\");\n\t\trow++;\n\t\t_offsetGeneralMin = row;\n\t\t_lstOptions->setCellColor(_offsetGeneralMin, 0, _colorGroup);\n\t\taddSettings(_settingsGeneral[idx]);\n\t\trow += _settingsGeneral[idx].size();\n\t\t_offsetGeneralMax = row;\n\t}\n\tif (_settingsGeo[idx].size() > 0)\n\t{\n\t\tif (row > -1) { _lstOptions->addRow(2, \"\", \"\"); row++; }\n\t\t_lstOptions->addRow(2, tr(\"STR_GEOSCAPE\").c_str(), \"\");\n\t\trow++;\n\t\t_offsetGeoMin = row;\n\t\t_lstOptions->setCellColor(_offsetGeoMin, 0, _colorGroup);\n\t\taddSettings(_settingsGeo[idx]);\n\t\trow += _settingsGeo[idx].size();\n\t\t_offsetGeoMax = row;\n\t}\n\tif (_settingsBase[idx].size() > 0)\n\t{\n\t\tif (row > -1) { _lstOptions->addRow(2, \"\", \"\"); row++; }\n\t\t_lstOptions->addRow(2, tr(\"STR_BASESCAPE\").c_str(), \"\");\n\t\trow++;\n\t\t_offsetBaseMin = row;\n\t\t_lstOptions->setCellColor(_offsetBaseMin, 0, _colorGroup);\n\t\taddSettings(_settingsBase[idx]);\n\t\trow += _settingsBase[idx].size();\n\t\t_offsetBaseMax = row;\n\t}\n\tif (_settingsBattle[idx].size() > 0)\n\t{\n\t\tif (row > -1) { _lstOptions->addRow(2, \"\", \"\"); row++; }\n\t\t_lstOptions->addRow(2, tr(\"STR_BATTLESCAPE\").c_str(), \"\");\n\t\trow++;\n\t\t_offsetBattleMin = row;\n\t\t_lstOptions->setCellColor(_offsetBattleMin, 0, _colorGroup);\n\t\taddSettings(_settingsBattle[idx]);\n\t\trow += _settingsBattle[idx].size();\n\t\t_offsetBattleMax = row;\n\t}\n\tif (_settingsAI[idx].size() > 0)\n\t{\n\t\tif (row > -1) { _lstOptions->addRow(2, \"\", \"\"); row++; }\n\t\t_lstOptions->addRow(2, tr(\"STR_AI\").c_str(), \"\");\n\t\trow++;\n\t\t_offsetAIMin = row;\n\t\t_lstOptions->setCellColor(_offsetAIMin, 0, _colorGroup);\n\t\taddSettings(_settingsAI[idx]);\n\t\trow += _settingsAI[idx].size();\n\t\t_offsetAIMax = row;\n\t}\n}\n\n/**\n * Adds a bunch of settings to the list.\n * @param settings List of settings.\n */\nvoid OptionsAdvancedState::addSettings(const std::vector<OptionInfo> &settings)\n{\n\tauto& fixeduserOptions = _game->getMod()->getFixedUserOptions();\n\tfor (const auto& optionInfo : settings)\n\t{\n\t\tstd::string name = tr(optionInfo.description());\n\t\tstd::string value;\n\t\tif (optionInfo.type() == OPTION_BOOL)\n\t\t{\n\t\t\tvalue = *optionInfo.asBool() ? tr(\"STR_YES\") : tr(\"STR_NO\");\n\t\t}\n\t\telse if (optionInfo.type() == OPTION_INT)\n\t\t{\n\t\t\tstd::ostringstream ss;\n\t\t\tss << *optionInfo.asInt();\n\t\t\tvalue = ss.str();\n\t\t}\n\t\t_lstOptions->addRow(2, name.c_str(), value.c_str());\n\t\t// grey out fixed options\n\t\tauto search = fixeduserOptions.find(optionInfo.id());\n\t\tif (search != fixeduserOptions.end())\n\t\t{\n\t\t\t_lstOptions->setRowColor(_lstOptions->getLastRowIndex(), _greyedOutColor);\n\t\t}\n\t}\n}\n\n/**\n * Gets the currently selected setting.\n * @param sel Selected row.\n * @return Pointer to option, NULL if none selected.\n */\nOptionInfo *OptionsAdvancedState::getSetting(size_t sel)\n{\n\tint selInt = sel;\n\tOptionOwner idx = _owner == _btnOXC ? OPTION_OXC : _owner == _btnOXCE ? OPTION_OXCE : OPTION_OTHER;\n\n\tif (selInt > _offsetGeneralMin && selInt <= _offsetGeneralMax)\n\t{\n\t\treturn &_settingsGeneral[idx][selInt - 1 - _offsetGeneralMin];\n\t}\n\telse if (selInt > _offsetGeoMin && selInt <= _offsetGeoMax)\n\t{\n\t\treturn &_settingsGeo[idx][selInt - 1 - _offsetGeoMin];\n\t}\n\telse if (selInt > _offsetBaseMin && selInt <= _offsetBaseMax)\n\t{\n\t\treturn &_settingsBase[idx][selInt - 1 - _offsetBaseMin];\n\t}\n\telse if (selInt > _offsetBattleMin && selInt <= _offsetBattleMax)\n\t{\n\t\treturn &_settingsBattle[idx][selInt - 1 - _offsetBattleMin];\n\t}\n\telse if (selInt > _offsetAIMin && selInt <= _offsetAIMax)\n\t{\n\t\treturn &_settingsAI[idx][selInt - 1 - _offsetAIMin];\n\t}\n\telse\n\t{\n\t\treturn 0;\n\t}\n}\n\n/**\n * Changes the clicked setting.\n * @param action Pointer to an action.\n */\nvoid OptionsAdvancedState::lstOptionsClick(Action *action)\n{\n\tUint8 button = action->getDetails()->button.button;\n\tif (button != SDL_BUTTON_LEFT && button != SDL_BUTTON_RIGHT)\n\t{\n\t\treturn;\n\t}\n\tsize_t sel = _lstOptions->getSelectedRow();\n\tOptionInfo *setting = getSetting(sel);\n\tif (!setting) return;\n\n\t// greyed out options are fixed, cannot be changed by the user\n\tauto& fixeduserOptions = _game->getMod()->getFixedUserOptions();\n\tauto it = fixeduserOptions.find(setting->id());\n\tif (it != fixeduserOptions.end())\n\t{\n\t\treturn;\n\t}\n\n\tstd::string settingText;\n\tif (setting->type() == OPTION_BOOL)\n\t{\n\t\tbool *b = setting->asBool();\n\t\t*b = !*b;\n\t\tsettingText = *b ? tr(\"STR_YES\") : tr(\"STR_NO\");\n\t\tif (b == &Options::lazyLoadResources && !*b)\n\t\t{\n\t\t\tOptions::reload = true; // reload when turning lazy loading off\n\t\t}\n\t}\n\telse if (setting->type() == OPTION_INT) // integer variables will need special handling\n\t{\n\t\tint *i = setting->asInt();\n\n\t\tint increment = (button == SDL_BUTTON_LEFT) ? 1 : -1; // left-click increases, right-click decreases\n\t\tif (i == &Options::changeValueByMouseWheel || i == &Options::FPS || i == &Options::FPSInactive || i == &Options::oxceWoundedDefendBaseIf)\n\t\t{\n\t\t\tincrement *= 10;\n\t\t}\n\t\telse if (i == &Options::oxceResearchScrollSpeedWithCtrl || i == &Options::oxceManufactureScrollSpeedWithCtrl || i == &Options::oxceReactionFireThreshold)\n\t\t{\n\t\t\tincrement *= 5;\n\t\t}\n\t\telse if (i == &Options::oxceInterceptTableSize)\n\t\t{\n\t\t\tincrement *= 4;\n\t\t}\n\t\t*i += increment;\n\n\t\tint min = 0, max = 0;\n\t\tif (i == &Options::battleExplosionHeight)\n\t\t{\n\t\t\tmin = 0;\n\t\t\tmax = 3;\n\t\t}\n\t\telse if (i == &Options::changeValueByMouseWheel)\n\t\t{\n\t\t\tmin = 0;\n\t\t\tmax = 100;\n\t\t}\n\t\telse if (i == &Options::FPS)\n\t\t{\n\t\t\tmin = 0;\n\t\t\tmax = 120;\n\t\t}\n\t\telse if (i == &Options::FPSInactive) {\n\t\t\tmin = 10;\n\t\t\tmax = 120;\n\t\t}\n\t\telse if (i == &Options::mousewheelSpeed)\n\t\t{\n\t\t\tmin = 1;\n\t\t\tmax = 7;\n\t\t}\n\t\telse if (i == &Options::autosaveFrequency)\n\t\t{\n\t\t\tmin = 1;\n\t\t\tmax = 5;\n\t\t}\n\t\telse if (i == &Options::oxceGeoAutosaveFrequency)\n\t\t{\n\t\t\tmin = 0;\n\t\t\tmax = 10;\n\t\t}\n\t\telse if (i == &Options::autosaveSlots || i == &Options::oxceGeoAutosaveSlots || i == &Options::oxceResearchScrollSpeed || i == &Options::oxceManufactureScrollSpeed)\n\t\t{\n\t\t\tmin = 1;\n\t\t\tmax = 10;\n\t\t}\n\t\telse if (i == &Options::oxceInterceptGuiMaintenanceTime || i == &Options::oxceShowETAMode || i == &Options::oxceShowAccuracyOnCrosshair || i == &Options::oxceCrashedOrLanded)\n\t\t{\n\t\t\tmin = 0;\n\t\t\tmax = 2;\n\t\t}\n\t\telse if (i == &Options::oxceInterceptTableSize)\n\t\t{\n\t\t\tmin = 8;\n\t\t\tmax = 80;\n\t\t}\n\t\telse if (i == &Options::oxceWoundedDefendBaseIf || i == &Options::oxceReactionFireThreshold) {\n\t\t\tmin = 0;\n\t\t\tmax = 100;\n\t\t}\n\t\telse if (i == &Options::oxceResearchScrollSpeedWithCtrl || i == &Options::oxceManufactureScrollSpeedWithCtrl)\n\t\t{\n\t\t\tmin = 5;\n\t\t\tmax = 50;\n\t\t}\n\t\telse if (i == &Options::oxceAutoNightVisionThreshold) {\n\t\t\tmin = 0;\n\t\t\tmax = 15;\n\t\t}\n\t\telse if (i == &Options::oxceNightVisionColor)\n\t\t{\n\t\t\t// UFO: 1-15, TFTD: 2-16 except 8 and 10\n\t\t\tif (_isTFTD && ((*i) == 8 || (*i) == 10))\n\t\t\t{\n\t\t\t\t*i += increment;\n\t\t\t}\n\t\t\tmin = _isTFTD ? 2 : 1;\n\t\t\tmax = _isTFTD ? 16 : 15;\n\t\t}\n\n\t\tif (*i < min)\n\t\t{\n\t\t\t*i = max;\n\t\t}\n\t\telse if (*i > max)\n\t\t{\n\t\t\t*i = min;\n\t\t}\n\n\t\tstd::ostringstream ss;\n\t\tss << *i;\n\t\tsettingText = ss.str();\n\t}\n\t_lstOptions->setCellText(sel, 1, settingText);\n}\n\nvoid OptionsAdvancedState::lstOptionsMouseOver(Action *)\n{\n\tsize_t sel = _lstOptions->getSelectedRow();\n\tOptionInfo *setting = getSetting(sel);\n\tstd::string desc;\n\tif (setting)\n\t{\n\t\tdesc = tr(setting->description() + \"_DESC\");\n\t}\n\t_txtTooltip->setText(desc);\n}\n\nvoid OptionsAdvancedState::lstOptionsMouseOut(Action *)\n{\n\t_txtTooltip->setText(\"\");\n}\n\nvoid OptionsAdvancedState::btnGroupPress(Action*)\n{\n\tupdateList();\n}\n\n}\n"
  },
  {
    "path": "src/Menu/OptionsAdvancedState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"OptionsBaseState.h\"\n#include \"../Engine/OptionInfo.h\"\n#include <vector>\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass TextList;\n\n/**\n * Options window that displays the\n * advanced game settings.\n */\nclass OptionsAdvancedState : public OptionsBaseState\n{\nprivate:\n\tTextButton *_btnOXC, *_btnOXCE, *_btnOTHER;\n\tTextButton *_owner;\n\tTextList *_lstOptions;\n\tbool _isTFTD;\n\tUint8 _colorGroup, _greyedOutColor;\n\tstd::vector<OptionInfo> _settingsGeneral[OPTION_OWNER_MAX];\n\tstd::vector<OptionInfo> _settingsGeo[OPTION_OWNER_MAX];\n\tstd::vector<OptionInfo> _settingsBase[OPTION_OWNER_MAX];\n\tstd::vector<OptionInfo> _settingsBattle[OPTION_OWNER_MAX];\n\tstd::vector<OptionInfo> _settingsAI[OPTION_OWNER_MAX];\n\tint _offsetGeneralMin = -1;\n\tint _offsetGeneralMax = -1;\n\tint _offsetGeoMin = -1;\n\tint _offsetGeoMax = -1;\n\tint _offsetBaseMin = -1;\n\tint _offsetBaseMax = -1;\n\tint _offsetBattleMin = -1;\n\tint _offsetBattleMax = -1;\n\tint _offsetAIMin = -1;\n\tint _offsetAIMax = -1;\n\n\tvoid addSettings(const std::vector<OptionInfo> &settings);\n\tOptionInfo *getSetting(size_t sel);\npublic:\n\t/// Creates the Advanced state.\n\tOptionsAdvancedState(OptionsOrigin origin);\n\t/// Cleans up the Advanced state.\n\t~OptionsAdvancedState();\n\t/// Refreshes the UI.\n\tvoid init() override;\n\t/// Fills settings list.\n\tvoid updateList();\n\t/// Handler for clicking a setting on the list.\n\tvoid lstOptionsClick(Action *action);\n\t/// Handler for moving the mouse over a setting.\n\tvoid lstOptionsMouseOver(Action *action);\n\t/// Handler for moving the mouse outside the settings.\n\tvoid lstOptionsMouseOut(Action *action);\n\t/// Handler for clicking buttons.\n\tvoid btnGroupPress(Action* action);\n\n};\n\n}\n"
  },
  {
    "path": "src/Menu/OptionsAudioState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"OptionsAudioState.h\"\n#include <SDL_mixer.h>\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/ComboBox.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/ToggleTextButton.h\"\n#include \"../Interface/Slider.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Sound.h\"\n\nnamespace OpenXcom\n{\n/* MUS_NONE, MUS_CMD, MUS_WAV, MUS_MOD, MUS_MID, MUS_OGG, MUS_MP3, MUS_MP3_MAD, MUS_FLAC, MUS_MODPLUG */\nconst std::string OptionsAudioState::musFormats[] = {\"Adlib\", \"?\", \"WAV\", \"MOD\", \"MIDI\", \"OGG\", \"MP3\", \"MP3\", \"FLAC\", \"MOD\"};\nconst std::string OptionsAudioState::sndFormats[] = {\"?\", \"1.4\", \"1.0\"};\n\n/**\n * Initializes all the elements in the Audio Options screen.\n * @param game Pointer to the core game.\n * @param origin Game section that originated this state.\n */\nOptionsAudioState::OptionsAudioState(OptionsOrigin origin) : OptionsBaseState(origin)\n{\n\tsetCategory(_btnAudio);\n\n\t// Create object\n\t_txtMusicVolume = new Text(114, 9, 94, 8);\n\t_slrMusicVolume = new Slider(104, 16, 94, 18);\n\n\t_txtSoundVolume = new Text(114, 9, 94, 40);\n\t_slrSoundVolume = new Slider(104, 16, 94, 50);\n\n\t_txtUiVolume = new Text(114, 9, 94, 72);\n\t_slrUiVolume = new Slider(104, 16, 94, 82);\n\n\t_txtMusicFormat = new Text(114, 9, 206, 40);\n\t_cbxMusicFormat = new ComboBox(this, 104, 16, 206, 50);\n\t_txtCurrentMusic = new Text(114, 9, 206, 68);\n\n\t_txtSoundFormat = new Text(114, 9, 206, 82);\n\t_cbxSoundFormat = new ComboBox(this, 104, 16, 206, 92);\n\t_txtCurrentSound = new Text(114, 9, 206, 110);\n\n\t_txtVideoFormat = new Text(114, 9, 206, 8);\n\t_cbxVideoFormat = new ComboBox(this, 104, 16, 206, 18);\n\n\t_txtOptions = new Text(114, 9, 94, 104);\n\t_btnBackgroundMute = new ToggleTextButton(104, 16, 94, 114);\n\n\tadd(_txtMusicVolume, \"text\", \"audioMenu\");\n\tadd(_slrMusicVolume, \"button\", \"audioMenu\");\n\n\tadd(_txtSoundVolume, \"text\", \"audioMenu\");\n\tadd(_slrSoundVolume, \"button\", \"audioMenu\");\n\n\tadd(_txtUiVolume, \"text\", \"audioMenu\");\n\tadd(_slrUiVolume, \"button\", \"audioMenu\");\n\n\tadd(_txtVideoFormat, \"text\", \"audioMenu\");\n\tadd(_txtMusicFormat, \"text\", \"audioMenu\");\n\tadd(_txtCurrentMusic, \"text\", \"audioMenu\");\n\tadd(_txtSoundFormat, \"text\", \"audioMenu\");\n\tadd(_txtCurrentSound, \"text\", \"audioMenu\");\n\n\tadd(_cbxSoundFormat, \"button\", \"audioMenu\");\n\tadd(_cbxMusicFormat, \"button\", \"audioMenu\");\n\tadd(_cbxVideoFormat, \"button\", \"audioMenu\");\n\n\tadd(_txtOptions, \"text\", \"audioMenu\");\n\tadd(_btnBackgroundMute, \"button\", \"audioMenu\");\n\n\tcenterAllSurfaces();\n\n\t// Set up object\n\t_txtMusicVolume->setText(tr(\"STR_MUSIC_VOLUME\"));\n\n\t_slrMusicVolume->setRange(0, SDL_MIX_MAXVOLUME);\n\t_slrMusicVolume->setValue(Options::musicVolume);\n\t_slrMusicVolume->onChange((ActionHandler)&OptionsAudioState::slrMusicVolumeChange);\n\t_slrMusicVolume->setTooltip(\"STR_MUSIC_VOLUME_DESC\");\n\t_slrMusicVolume->onMouseIn((ActionHandler)&OptionsAudioState::txtTooltipIn);\n\t_slrMusicVolume->onMouseOut((ActionHandler)&OptionsAudioState::txtTooltipOut);\n\n\t_txtSoundVolume->setText(tr(\"STR_SFX_VOLUME\"));\n\n\t_slrSoundVolume->setRange(0, SDL_MIX_MAXVOLUME);\n\t_slrSoundVolume->setValue(Options::soundVolume);\n\t_slrSoundVolume->onChange((ActionHandler)&OptionsAudioState::slrSoundVolumeChange);\n\t_slrSoundVolume->onMouseRelease((ActionHandler)&OptionsAudioState::slrSoundVolumeRelease);\n\t_slrSoundVolume->setTooltip(\"STR_SFX_VOLUME_DESC\");\n\t_slrSoundVolume->onMouseIn((ActionHandler)&OptionsAudioState::txtTooltipIn);\n\t_slrSoundVolume->onMouseOut((ActionHandler)&OptionsAudioState::txtTooltipOut);\n\n\t_txtUiVolume->setText(tr(\"STR_UI_VOLUME\"));\n\n\t_slrUiVolume->setRange(0, SDL_MIX_MAXVOLUME);\n\t_slrUiVolume->setValue(Options::uiVolume);\n\t_slrUiVolume->onChange((ActionHandler)&OptionsAudioState::slrUiVolumeChange);\n\t_slrUiVolume->onMouseRelease((ActionHandler)&OptionsAudioState::slrUiVolumeRelease);\n\t_slrUiVolume->setTooltip(\"STR_UI_VOLUME_DESC\");\n\t_slrUiVolume->onMouseIn((ActionHandler)&OptionsAudioState::txtTooltipIn);\n\t_slrUiVolume->onMouseOut((ActionHandler)&OptionsAudioState::txtTooltipOut);\n\n\tstd::vector<std::string> musicText, soundText, videoText;\n\t/* MUSIC_AUTO, MUSIC_FLAC, MUSIC_OGG, MUSIC_MP3, MUSIC_MOD, MUSIC_WAV, MUSIC_ADLIB, MUSIC_GM, MUSIC_MIDI */\n\tmusicText.push_back(tr(\"STR_PREFERRED_FORMAT_AUTO\"));\n\tmusicText.push_back(\"FLAC\");\n\tmusicText.push_back(\"OGG\");\n\tmusicText.push_back(\"MP3\");\n\tmusicText.push_back(\"MOD\");\n\tmusicText.push_back(\"WAV\");\n\tmusicText.push_back(\"Adlib\");\n\tmusicText.push_back(\"GM\");\n\tmusicText.push_back(\"MIDI\");\n\n\tsoundText.push_back(tr(\"STR_PREFERRED_FORMAT_AUTO\"));\n\tsoundText.push_back(\"1.4\");\n\tsoundText.push_back(\"1.0\");\n\n\tvideoText.push_back(tr(\"STR_PREFERRED_VIDEO_ANIMATION\"));\n\tvideoText.push_back(tr(\"STR_PREFERRED_VIDEO_SLIDESHOW\"));\n\n\t_txtMusicFormat->setText(tr(\"STR_PREFERRED_MUSIC_FORMAT\"));\n\n\t_cbxMusicFormat->setOptions(musicText);\n\t_cbxMusicFormat->setSelected(Options::preferredMusic);\n\t_cbxMusicFormat->setTooltip(\"STR_PREFERRED_MUSIC_FORMAT_DESC\");\n\t_cbxMusicFormat->onChange((ActionHandler)&OptionsAudioState::cbxMusicFormatChange);\n\t_cbxMusicFormat->onMouseIn((ActionHandler)&OptionsAudioState::txtTooltipIn);\n\t_cbxMusicFormat->onMouseOut((ActionHandler)&OptionsAudioState::txtTooltipOut);\n\n\tstd::string curMusic = musFormats[Mix_GetMusicType(0)]; // this is confusing\n\t// since  both GM (GM.CAT) and MIDI (*.mid) are the same from SDL_mixer POV.\n\t_txtCurrentMusic->setText(tr(\"STR_CURRENT_FORMAT\").arg(curMusic));\n\n\t_txtSoundFormat->setText(tr(\"STR_PREFERRED_SFX_FORMAT\"));\n\n\t_cbxSoundFormat->setOptions(soundText);\n\t_cbxSoundFormat->setSelected(Options::preferredSound);\n\t_cbxSoundFormat->setTooltip(\"STR_PREFERRED_SFX_FORMAT_DESC\");\n\t_cbxSoundFormat->onChange((ActionHandler)&OptionsAudioState::cbxSoundFormatChange);\n\t_cbxSoundFormat->onMouseIn((ActionHandler)&OptionsAudioState::txtTooltipIn);\n\t_cbxSoundFormat->onMouseOut((ActionHandler)&OptionsAudioState::txtTooltipOut);\n\n\tstd::string curSound = sndFormats[Options::currentSound];\n\t_txtCurrentSound->setText(tr(\"STR_CURRENT_FORMAT\").arg(curSound));\n\n\t_txtVideoFormat->setText(tr(\"STR_PREFERRED_VIDEO_FORMAT\"));\n\n\t_cbxVideoFormat->setOptions(videoText);\n\t_cbxVideoFormat->setSelected(Options::preferredVideo);\n\t_cbxVideoFormat->setTooltip(\"STR_PREFERRED_VIDEO_FORMAT_DESC\");\n\t_cbxVideoFormat->onChange((ActionHandler)&OptionsAudioState::cbxVideoFormatChange);\n\t_cbxVideoFormat->onMouseIn((ActionHandler)&OptionsAudioState::txtTooltipIn);\n\t_cbxVideoFormat->onMouseOut((ActionHandler)&OptionsAudioState::txtTooltipOut);\n\n\t// These options require a restart, so don't enable them in-game\n\t_txtMusicFormat->setVisible(_origin == OPT_MENU);\n\t_cbxMusicFormat->setVisible(_origin == OPT_MENU);\n\t_txtCurrentMusic->setVisible(_origin == OPT_MENU);\n\n\t// These options only apply to UFO\n\t_txtSoundFormat->setVisible(_origin == OPT_MENU && _game->getMod()->getSoundDefinitions()->empty());\n\t_cbxSoundFormat->setVisible(_origin == OPT_MENU && _game->getMod()->getSoundDefinitions()->empty());\n\t_txtCurrentSound->setVisible(_origin == OPT_MENU && _game->getMod()->getSoundDefinitions()->empty());\n\n\t_txtOptions->setText(tr(\"STR_SOUND_OPTIONS\"));\n\n\t_btnBackgroundMute->setText(tr(\"STR_BACKGROUND_MUTE\"));\n\t_btnBackgroundMute->setPressed(Options::backgroundMute);\n\t_btnBackgroundMute->onMouseClick((ActionHandler)&OptionsAudioState::btnBackgroundMuteClick);\n\t_btnBackgroundMute->setTooltip(\"STR_BACKGROUND_MUTE_DESC\");\n\t_btnBackgroundMute->onMouseIn((ActionHandler)&OptionsAudioState::txtTooltipIn);\n\t_btnBackgroundMute->onMouseOut((ActionHandler)&OptionsAudioState::txtTooltipOut);\n}\n\n/**\n *\n */\nOptionsAudioState::~OptionsAudioState()\n{\n\n}\n\n/**\n * Updates the music volume.\n * @param action Pointer to an action.\n */\nvoid OptionsAudioState::slrMusicVolumeChange(Action *)\n{\n\tOptions::musicVolume = _slrMusicVolume->getValue();\n\t_game->setVolume(Options::soundVolume, Options::musicVolume, Options::uiVolume);\n}\n\n/**\n * Updates the sound volume with the slider.\n * @param action Pointer to an action.\n */\nvoid OptionsAudioState::slrSoundVolumeChange(Action *)\n{\n\tOptions::soundVolume = _slrSoundVolume->getValue();\n\t_game->setVolume(Options::soundVolume, Options::musicVolume, Options::uiVolume);\n}\n\n/**\n * Plays a game sound for volume preview.\n * @param action Pointer to an action.\n */\nvoid OptionsAudioState::slrSoundVolumeRelease(Action *)\n{\n\t_game->getMod()->getSound(\"GEO.CAT\", Mod::UFO_FIRE)->play();\n}\n\n/**\n * Updates the UI volume with the slider.\n * @param action Pointer to an action.\n */\nvoid OptionsAudioState::slrUiVolumeChange(Action *)\n{\n\tOptions::uiVolume = _slrUiVolume->getValue();\n\t_game->setVolume(Options::soundVolume, Options::musicVolume, Options::uiVolume);\n}\n\n/**\n * Plays a UI sound for volume preview.\n * @param action Pointer to an action.\n */\nvoid OptionsAudioState::slrUiVolumeRelease(Action *)\n{\n\tTextButton::soundPress->play(Mix_GroupAvailable(0));\n}\n\n/**\n * Changes the Video Format option.\n * @param action Pointer to an action.\n */\nvoid OptionsAudioState::cbxVideoFormatChange(Action *)\n{\n\tOptions::preferredVideo = (VideoFormat)_cbxVideoFormat->getSelected();\n}\n\n/**\n * Changes the Music Format option.\n * @param action Pointer to an action.\n */\nvoid OptionsAudioState::cbxMusicFormatChange(Action *)\n{\n\tOptions::preferredMusic = (MusicFormat)_cbxMusicFormat->getSelected();\n\tOptions::reload = true;\n}\n\n/**\n * Changes the Sound Format option.\n * @param action Pointer to an action.\n */\nvoid OptionsAudioState::cbxSoundFormatChange(Action *)\n{\n\tOptions::preferredSound = (SoundFormat)_cbxSoundFormat->getSelected();\n\tOptions::reload = true;\n}\n\n/**\n * Updates the Background Mute option.\n * @param action Pointer to an action.\n */\nvoid OptionsAudioState::btnBackgroundMuteClick(Action*)\n{\n\tOptions::backgroundMute = _btnBackgroundMute->getPressed();\n}\n\n}\n"
  },
  {
    "path": "src/Menu/OptionsAudioState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"OptionsBaseState.h\"\n\nnamespace OpenXcom\n{\n\nclass Text;\nclass ComboBox;\nclass Slider;\nclass ToggleTextButton;\n\n/**\n * Screen that lets the user configure various\n * Audio options.\n */\nclass OptionsAudioState : public OptionsBaseState\n{\nprivate:\n\tstatic const std::string musFormats[], sndFormats[];\n\tText *_txtMusicVolume, *_txtSoundVolume, *_txtUiVolume;\n\tSlider *_slrMusicVolume, *_slrSoundVolume, *_slrUiVolume;\n\tText *_txtMusicFormat, *_txtCurrentMusic, *_txtSoundFormat, *_txtCurrentSound, *_txtVideoFormat;\n\tComboBox *_cbxMusicFormat, *_cbxSoundFormat, *_cbxVideoFormat;\n\tText* _txtOptions;\n\tToggleTextButton *_btnBackgroundMute;\npublic:\n\t/// Creates the Audio Options state.\n\tOptionsAudioState(OptionsOrigin origin);\n\t/// Cleans up the Audio Options state.\n\t~OptionsAudioState();\n\t/// Handler for changing the music slider.\n\tvoid slrMusicVolumeChange(Action *action);\n\t/// Handler for changing the sound slider.\n\tvoid slrSoundVolumeChange(Action *action);\n\t/// Handler for sound slider button release.\n\tvoid slrSoundVolumeRelease(Action *action);\n\t/// Handler for changing the sound slider.\n\tvoid slrUiVolumeChange(Action *action);\n\t/// Handler for sound slider button release.\n\tvoid slrUiVolumeRelease(Action *action);\n\t/// Handler for changing the Music Format combobox.\n\tvoid cbxMusicFormatChange(Action *action);\n\t/// Handler for changing the Sound Format combobox.\n\tvoid cbxSoundFormatChange(Action *action);\n\t/// Handler for changing the Video Format combobox.\n\tvoid cbxVideoFormatChange(Action *action);\n\t/// Handler for clicking the Background Mute button.\n\tvoid btnBackgroundMuteClick(Action* action);\n};\n\n}\n"
  },
  {
    "path": "src/Menu/OptionsBaseState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"OptionsBaseState.h\"\n#include <SDL.h>\n#include \"../Engine/Game.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Screen.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Text.h\"\n#include \"../Engine/Action.h\"\n#include \"MainMenuState.h\"\n#include \"../Geoscape/GeoscapeState.h\"\n#include \"../Battlescape/BattlescapeState.h\"\n#include \"OptionsVideoState.h\"\n#include \"OptionsAudioState.h\"\n#include \"OptionsFoldersState.h\"\n#include \"OptionsNoAudioState.h\"\n#include \"OptionsControlsState.h\"\n#include \"OptionsGeoscapeState.h\"\n#include \"OptionsBattlescapeState.h\"\n#include \"OptionsAdvancedState.h\"\n#include \"OptionsDefaultsState.h\"\n#include \"OptionsConfirmState.h\"\n#include \"StartState.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Options window.\n * @param game Pointer to the core game.\n * @param origin Game section that originated this state.\n */\nOptionsBaseState::OptionsBaseState(OptionsOrigin origin) : _origin(origin), _group(0)\n{\n\t// Create objects\n\t_window = new Window(this, 320, 200, 0, 0);\n\n\t_btnVideo = new TextButton(80, 16, 8, 8);\n\t_btnAudio = new TextButton(80, 16, 8, 28);\n\t_btnControls = new TextButton(80, 16, 8, 48);\n\t_btnGeoscape = new TextButton(80, 16, 8, 68);\n\t_btnBattlescape = new TextButton(80, 16, 8, 88);\n\t_btnAdvanced = new TextButton(80, 16, 8, 108);\n\t_btnFolders = new TextButton(80, 16, 8, 128);\n\n\t_btnOk = new TextButton(100, 16, 8, 176);\n\t_btnCancel = new TextButton(100, 16, 110, 176);\n\t_btnDefault = new TextButton(100, 16, 212, 176);\n\n\t_txtTooltip = new Text(305, 25, 8, 148);\n\n\t// Set palette\n\tsetInterface(\"optionsMenu\", false, _game->getSavedGame() ? _game->getSavedGame()->getSavedBattle() : 0);\n\n\tadd(_window, \"window\", \"optionsMenu\");\n\n\tadd(_btnVideo, \"button\", \"optionsMenu\");\n\tadd(_btnAudio, \"button\", \"optionsMenu\");\n\tadd(_btnControls, \"button\", \"optionsMenu\");\n\tadd(_btnGeoscape, \"button\", \"optionsMenu\");\n\tadd(_btnBattlescape, \"button\", \"optionsMenu\");\n\tadd(_btnAdvanced, \"button\", \"optionsMenu\");\n\tadd(_btnFolders, \"button\", \"optionsMenu\");\n\n\tadd(_btnOk, \"button\", \"optionsMenu\");\n\tadd(_btnCancel, \"button\", \"optionsMenu\");\n\tadd(_btnDefault, \"button\", \"optionsMenu\");\n\n\tadd(_txtTooltip, \"tooltip\", \"optionsMenu\");\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"optionsMenu\");\n\n\t_btnVideo->setText(tr(\"STR_VIDEO\"));\n\t_btnVideo->onMousePress((ActionHandler)&OptionsBaseState::btnGroupPress, SDL_BUTTON_LEFT);\n\n\t_btnAudio->setText(tr(\"STR_AUDIO\"));\n\t_btnAudio->onMousePress((ActionHandler)&OptionsBaseState::btnGroupPress, SDL_BUTTON_LEFT);\n\n\t_btnControls->setText(tr(\"STR_CONTROLS\"));\n\t_btnControls->onMousePress((ActionHandler)&OptionsBaseState::btnGroupPress, SDL_BUTTON_LEFT);\n\n\t_btnGeoscape->setText(tr(\"STR_GEOSCAPE_UC\"));\n\t_btnGeoscape->onMousePress((ActionHandler)&OptionsBaseState::btnGroupPress, SDL_BUTTON_LEFT);\n\n\t_btnBattlescape->setText(tr(\"STR_BATTLESCAPE_UC\"));\n\t_btnBattlescape->onMousePress((ActionHandler)&OptionsBaseState::btnGroupPress, SDL_BUTTON_LEFT);\n\n\t_btnAdvanced->setText(tr(\"STR_ADVANCED\"));\n\t_btnAdvanced->onMousePress((ActionHandler)&OptionsBaseState::btnGroupPress, SDL_BUTTON_LEFT);\n\n\t_btnFolders->setText(tr(\"STR_FOLDERS\"));\n\t_btnFolders->onMousePress((ActionHandler)&OptionsBaseState::btnGroupPress, SDL_BUTTON_LEFT);\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&OptionsBaseState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&OptionsBaseState::btnOkClick, Options::keyOk);\n\n\t_btnCancel->setText(tr(\"STR_CANCEL\"));\n\t_btnCancel->onMouseClick((ActionHandler)&OptionsBaseState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&OptionsBaseState::btnCancelClick, Options::keyCancel);\n\n\t_btnDefault->setText(tr(\"STR_RESTORE_DEFAULTS\"));\n\t_btnDefault->onMouseClick((ActionHandler)&OptionsBaseState::btnDefaultClick);\n\n\t_txtTooltip->setWordWrap(true);\n}\n\n/**\n *\n */\nOptionsBaseState::~OptionsBaseState()\n{\n\n}\n\nvoid OptionsBaseState::restart(OptionsOrigin origin)\n{\n\t// Reset touch flags\n\t_game->resetTouchButtonFlags();\n\n\tif (origin == OPT_MENU)\n\t{\n\t\t_game->setState(new MainMenuState);\n\t}\n\telse if (origin == OPT_GEOSCAPE)\n\t{\n\t\t_game->setState(new GeoscapeState);\n\t}\n\telse if (origin == OPT_BATTLESCAPE)\n\t{\n\t\tBattlescapeState *origBattleState = 0;\n\t\tif (_game->getSavedGame() != 0 && _game->getSavedGame()->getSavedBattle() != 0)\n\t\t{\n\t\t\torigBattleState = _game->getSavedGame()->getSavedBattle()->getBattleState();\n\t\t}\n\t\tif (origBattleState != 0)\n\t\t{\n\t\t\t// We need to reset palettes here already, can't wait for the destructor\n\t\t\torigBattleState->resetPalettes();\n\t\t}\n\n\t\t_game->setState(new GeoscapeState);\n\t\tBattlescapeState *bs = new BattlescapeState;\n\t\t_game->pushState(bs);\n\t\t_game->getSavedGame()->getSavedBattle()->setBattleState(bs);\n\t\t// Try to reactivate the touch buttons\n\t\tbs->toggleTouchButtons(false, true);\n\t}\n}\n\n/**\n * Initializes UI colors according to origin.\n */\nvoid OptionsBaseState::init()\n{\n\tState::init();\n\tif (_origin == OPT_BATTLESCAPE)\n\t{\n\t\tapplyBattlescapeTheme(\"optionsMenu\");\n\t}\n}\n\n/**\n * Handles the pressed-button state for the category buttons.\n * @param button Button to press.\n */\nvoid OptionsBaseState::setCategory(TextButton *button)\n{\n\t_group = button;\n\t_btnVideo->setGroup(&_group);\n\t_btnAudio->setGroup(&_group);\n\t_btnControls->setGroup(&_group);\n\t_btnGeoscape->setGroup(&_group);\n\t_btnBattlescape->setGroup(&_group);\n\t_btnAdvanced->setGroup(&_group);\n\t_btnFolders->setGroup(&_group);\n}\n\n/**\n * Saves the new options and returns to the proper origin screen.\n * @param action Pointer to an action.\n */\nvoid OptionsBaseState::btnOkClick(Action *)\n{\n\tOptions::switchDisplay();\n\tint dX = Options::baseXResolution;\n\tint dY = Options::baseYResolution;\n\tScreen::updateScale(Options::battlescapeScale, Options::baseXBattlescape, Options::baseYBattlescape, _origin == OPT_BATTLESCAPE);\n\tScreen::updateScale(Options::geoscapeScale, Options::baseXGeoscape, Options::baseYGeoscape, _origin != OPT_BATTLESCAPE);\n\tdX = Options::baseXResolution - dX;\n\tdY = Options::baseYResolution - dY;\n\trecenter(dX, dY);\n\tOptions::save();\n\t_game->loadLanguages();\n\t_game->getScreen()->resetDisplay();\n\tSDL_WM_GrabInput(Options::captureMouse);\n\t_game->setVolume(Options::soundVolume, Options::musicVolume, Options::uiVolume);\n\tif (Options::reload && _origin == OPT_MENU)\n\t{\n\t\t_game->setState(new StartState);\n\t}\n\telse\n\t{\n\t\t// Confirm any video options changes\n\t\tif (Options::displayWidth != Options::newDisplayWidth ||\n\t\t\tOptions::displayHeight != Options::newDisplayHeight ||\n\t\t\tOptions::useOpenGL != Options::newOpenGL ||\n\t\t\tOptions::useScaleFilter != Options::newScaleFilter ||\n\t\t\tOptions::useHQXFilter != Options::newHQXFilter ||\n\t\t\tOptions::useOpenGLShader != Options::newOpenGLShader)\n\t\t{\n\t\t\t_game->pushState(new OptionsConfirmState(_origin));\n\t\t}\n\t\telse\n\t\t{\n\t\t\trestart(_origin);\n\t\t}\n\t}\n}\n\n/**\n * Loads previous options and returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid OptionsBaseState::btnCancelClick(Action *)\n{\n\tOptions::reload = false;\n\tOptions::load();\n\tSDL_WM_GrabInput(Options::captureMouse);\n\tScreen::updateScale(Options::battlescapeScale, Options::baseXBattlescape, Options::baseYBattlescape, _origin == OPT_BATTLESCAPE);\n\tScreen::updateScale(Options::geoscapeScale, Options::baseXGeoscape, Options::baseYGeoscape, _origin != OPT_BATTLESCAPE);\n\t_game->setVolume(Options::soundVolume, Options::musicVolume, Options::uiVolume);\n\t_game->popState();\n}\n\n/**\n * Restores the Options to default settings.\n * @param action Pointer to an action.\n */\nvoid OptionsBaseState::btnDefaultClick(Action *)\n{\n\t_game->pushState(new OptionsDefaultsState(_origin, this));\n}\n\nvoid OptionsBaseState::btnGroupPress(Action *action)\n{\n\tSurface *sender = action->getSender();\n\t//if (sender != _group)\n\t{\n\t\t_game->popState();\n\t\tif (sender == _btnVideo)\n\t\t{\n\t\t\t_game->pushState(new OptionsVideoState(_origin));\n\t\t}\n\t\telse if (sender == _btnAudio)\n\t\t{\n\t\t\tif (!Options::mute)\n\t\t\t{\n\t\t\t\t_game->pushState(new OptionsAudioState(_origin));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_game->pushState(new OptionsNoAudioState(_origin));\n\t\t\t}\n\t\t}\n\t\telse if (sender == _btnControls)\n\t\t{\n\t\t\t_game->pushState(new OptionsControlsState(_origin));\n\t\t}\n\t\telse if (sender == _btnGeoscape)\n\t\t{\n\t\t\t_game->pushState(new OptionsGeoscapeState(_origin));\n\t\t}\n\t\telse if (sender == _btnBattlescape)\n\t\t{\n\t\t\t_game->pushState(new OptionsBattlescapeState(_origin));\n\t\t}\n\t\telse if (sender == _btnAdvanced)\n\t\t{\n\t\t\t_game->pushState(new OptionsAdvancedState(_origin));\n\t\t}\n\t\telse if (sender == _btnFolders)\n\t\t{\n\t\t\t_game->pushState(new OptionsFoldersState(_origin));\n\t\t}\n\t}\n}\n\n/**\n * Shows a tooltip for the appropriate button.\n * @param action Pointer to an action.\n */\nvoid OptionsBaseState::txtTooltipIn(Action *action)\n{\n\t_currentTooltip = action->getSender()->getTooltip();\n\t_txtTooltip->setText(tr(_currentTooltip));\n}\n\n/**\n * Clears the tooltip text.\n * @param action Pointer to an action.\n */\nvoid OptionsBaseState::txtTooltipOut(Action *action)\n{\n\tif (_currentTooltip == action->getSender()->getTooltip())\n\t{\n\t\t_txtTooltip->setText(\"\");\n\t}\n}\n\n/**\n * Updates the scale.\n * @param dX delta of X;\n * @param dY delta of Y;\n */\nvoid OptionsBaseState::resize(int &dX, int &dY)\n{\n\tOptions::newDisplayWidth = Options::displayWidth;\n\tOptions::newDisplayHeight = Options::displayHeight;\n\tState::resize(dX, dY);\n}\n\n}\n"
  },
  {
    "path": "src/Menu/OptionsBaseState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include <string>\n\nnamespace OpenXcom\n{\n\nenum OptionsOrigin\n{\n\tOPT_MENU,\n\tOPT_GEOSCAPE,\n\tOPT_BATTLESCAPE\n};\n\nclass Window;\nclass TextButton;\nclass Text;\n\n/**\n * Options base state for common stuff\n * across Options windows.\n */\nclass OptionsBaseState : public State\n{\nprotected:\n\tOptionsOrigin _origin;\n\tWindow *_window;\n\tTextButton *_btnVideo, *_btnAudio, *_btnControls, *_btnGeoscape, *_btnBattlescape, *_btnAdvanced, *_btnFolders;\n\tTextButton *_btnOk, *_btnCancel, *_btnDefault;\n\tText *_txtTooltip;\n\tstd::string _currentTooltip;\n\tTextButton *_group;\npublic:\n\t/// Creates the Options state.\n\tOptionsBaseState(OptionsOrigin origin);\n\t/// Cleans up the Options state.\n\t~OptionsBaseState();\n\t/// Restarts the game states.\n\tstatic void restart(OptionsOrigin origin);\n\t/// Initializes palettes.\n\tvoid init() override;\n\t/// Presses a certain category button.\n\tvoid setCategory(TextButton *button);\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action *action);\n\t/// Handler for clicking the Restore Defaults button.\n\tvoid btnDefaultClick(Action *action);\n\t/// Handler for clicking one of the grouping buttons.\n\tvoid btnGroupPress(Action *action);\n\t/// Handler for showing tooltip.\n\tvoid txtTooltipIn(Action *action);\n\t/// Handler for hiding tooltip.\n\tvoid txtTooltipOut(Action *action);\n\t/// Update the resolution settings, we just resized the window.\n\tvoid resize(int &dX, int &dY) override;\n};\n\n}\n"
  },
  {
    "path": "src/Menu/OptionsBattlescapeState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"OptionsBattlescapeState.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/ToggleTextButton.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/Slider.h\"\n#include \"../Interface/ComboBox.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Options.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Battlescape Options screen.\n * @param game Pointer to the core game.\n * @param origin Game section that originated this state.\n */\nOptionsBattlescapeState::OptionsBattlescapeState(OptionsOrigin origin) : OptionsBaseState(origin)\n{\n\tsetCategory(_btnBattlescape);\n\n\t// Create objects\n\t_txtEdgeScroll = new Text(114, 9, 94, 8);\n\t_cbxEdgeScroll = new ComboBox(this, 104, 16, 94, 18);\n\n\t_txtDragScroll = new Text(114, 9, 206, 8);\n\t_cbxDragScroll = new ComboBox(this, 104, 16, 206, 18);\n\n\t_txtScrollSpeed = new Text(114, 9, 94, 40);\n\t_slrScrollSpeed = new Slider(104, 16, 94, 50);\n\n\t_txtFireSpeed = new Text(114, 9, 206, 40);\n\t_slrFireSpeed = new Slider(104, 16, 206, 50);\n\n\t_txtXcomSpeed = new Text(114, 9, 94, 72);\n\t_slrXcomSpeed = new Slider(104, 16, 94, 82);\n\n\t_txtAlienSpeed = new Text(114, 9, 206, 72);\n\t_slrAlienSpeed = new Slider(104, 16, 206, 82);\n\n\t_txtPathPreview = new Text(114, 9, 94, 100);\n\t_btnArrows = new ToggleTextButton(104, 16, 94, 110);\n\t_btnTuCost = new ToggleTextButton(58, 16, 94, 128);\n\t_btnEnergyCost = new ToggleTextButton(44, 16, 154, 128);\n\n\t_txtOptions = new Text(114, 9, 206, 100);\n\t_btnTooltips = new ToggleTextButton(104, 16, 206, 110);\n\t_btnDeaths = new ToggleTextButton(104, 16, 206, 128);\n\n\tadd(_txtEdgeScroll, \"text\", \"battlescapeMenu\");\n\tadd(_txtDragScroll, \"text\", \"battlescapeMenu\");\n\n\tadd(_txtScrollSpeed, \"text\", \"battlescapeMenu\");\n\tadd(_slrScrollSpeed, \"button\", \"battlescapeMenu\");\n\n\tadd(_txtFireSpeed, \"text\", \"battlescapeMenu\");\n\tadd(_slrFireSpeed, \"button\", \"battlescapeMenu\");\n\n\tadd(_txtXcomSpeed, \"text\", \"battlescapeMenu\");\n\tadd(_slrXcomSpeed, \"button\", \"battlescapeMenu\");\n\n\tadd(_txtAlienSpeed, \"text\", \"battlescapeMenu\");\n\tadd(_slrAlienSpeed, \"button\", \"battlescapeMenu\");\n\n\tadd(_txtPathPreview, \"text\", \"battlescapeMenu\");\n\tadd(_btnArrows, \"button\", \"battlescapeMenu\");\n\tadd(_btnTuCost, \"button\", \"battlescapeMenu\");\n\tadd(_btnEnergyCost, \"button\", \"battlescapeMenu\");\n\n\tadd(_txtOptions, \"text\", \"battlescapeMenu\");\n\tadd(_btnTooltips, \"button\", \"battlescapeMenu\");\n\tadd(_btnDeaths, \"button\", \"battlescapeMenu\");\n\n\tadd(_cbxEdgeScroll, \"button\", \"battlescapeMenu\");\n\tadd(_cbxDragScroll, \"button\", \"battlescapeMenu\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\t_txtEdgeScroll->setText(tr(\"STR_EDGE_SCROLL\"));\n\n\tstd::vector<std::string> edgeScrolls;\n\tedgeScrolls.push_back(tr(\"STR_DISABLED\"));\n\tedgeScrolls.push_back(tr(\"STR_TRIGGER_SCROLL\"));\n\tedgeScrolls.push_back(tr(\"STR_AUTO_SCROLL\"));\n\n\t_cbxEdgeScroll->setOptions(edgeScrolls);\n\t_cbxEdgeScroll->setSelected(Options::battleEdgeScroll);\n\t_cbxEdgeScroll->onChange((ActionHandler)&OptionsBattlescapeState::cbxEdgeScrollChange);\n\t_cbxEdgeScroll->setTooltip(\"STR_EDGE_SCROLL_DESC\");\n\t_cbxEdgeScroll->onMouseIn((ActionHandler)&OptionsBattlescapeState::txtTooltipIn);\n\t_cbxEdgeScroll->onMouseOut((ActionHandler)&OptionsBattlescapeState::txtTooltipOut);\n\n\t_txtDragScroll->setText(tr(\"STR_DRAG_SCROLL\"));\n\n\tstd::vector<std::string> dragScrolls;\n\tdragScrolls.push_back(tr(\"STR_DISABLED\"));\n\tdragScrolls.push_back(tr(\"STR_LEFT_MOUSE_BUTTON\"));\n\tdragScrolls.push_back(tr(\"STR_MIDDLE_MOUSE_BUTTON\"));\n\tdragScrolls.push_back(tr(\"STR_RIGHT_MOUSE_BUTTON\"));\n\n\t_cbxDragScroll->setOptions(dragScrolls);\n\t_cbxDragScroll->setSelected(Options::battleDragScrollButton);\n\t_cbxDragScroll->onChange((ActionHandler)&OptionsBattlescapeState::cbxDragScrollChange);\n\t_cbxDragScroll->setTooltip(\"STR_DRAG_SCROLL_DESC\");\n\t_cbxDragScroll->onMouseIn((ActionHandler)&OptionsBattlescapeState::txtTooltipIn);\n\t_cbxDragScroll->onMouseOut((ActionHandler)&OptionsBattlescapeState::txtTooltipOut);\n\n\t_txtScrollSpeed->setText(tr(\"STR_SCROLL_SPEED\"));\n\n\t_slrScrollSpeed->setRange(2, 20);\n\t_slrScrollSpeed->setValue(Options::battleScrollSpeed);\n\t_slrScrollSpeed->onChange((ActionHandler)&OptionsBattlescapeState::slrScrollSpeedChange);\n\t_slrScrollSpeed->setTooltip(\"STR_SCROLL_SPEED_BATTLE_DESC\");\n\t_slrScrollSpeed->onMouseIn((ActionHandler)&OptionsBattlescapeState::txtTooltipIn);\n\t_slrScrollSpeed->onMouseOut((ActionHandler)&OptionsBattlescapeState::txtTooltipOut);\n\n\t_txtFireSpeed->setText(tr(\"STR_FIRE_SPEED\"));\n\n\t_slrFireSpeed->setRange(1, 20);\n\t_slrFireSpeed->setValue(Options::battleFireSpeed);\n\t_slrFireSpeed->onChange((ActionHandler)&OptionsBattlescapeState::slrFireSpeedChange);\n\t_slrFireSpeed->setTooltip(\"STR_FIRE_SPEED_DESC\");\n\t_slrFireSpeed->onMouseIn((ActionHandler)&OptionsBattlescapeState::txtTooltipIn);\n\t_slrFireSpeed->onMouseOut((ActionHandler)&OptionsBattlescapeState::txtTooltipOut);\n\n\t_txtXcomSpeed->setText(tr(\"STR_PLAYER_MOVEMENT_SPEED\"));\n\n\t_slrXcomSpeed->setRange(40, 1);\n\t_slrXcomSpeed->setValue(Options::battleXcomSpeed);\n\t_slrXcomSpeed->onChange((ActionHandler)&OptionsBattlescapeState::slrXcomSpeedChange);\n\t_slrXcomSpeed->setTooltip(\"STR_PLAYER_MOVEMENT_SPEED_DESC\");\n\t_slrXcomSpeed->onMouseIn((ActionHandler)&OptionsBattlescapeState::txtTooltipIn);\n\t_slrXcomSpeed->onMouseOut((ActionHandler)&OptionsBattlescapeState::txtTooltipOut);\n\n\t_txtAlienSpeed->setText(tr(\"STR_COMPUTER_MOVEMENT_SPEED\"));\n\n\t_slrAlienSpeed->setRange(40, 1);\n\t_slrAlienSpeed->setValue(Options::battleAlienSpeed);\n\t_slrAlienSpeed->onChange((ActionHandler)&OptionsBattlescapeState::slrAlienSpeedChange);\n\t_slrAlienSpeed->setTooltip(\"STR_COMPUTER_MOVEMENT_SPEED_DESC\");\n\t_slrAlienSpeed->onMouseIn((ActionHandler)&OptionsBattlescapeState::txtTooltipIn);\n\t_slrAlienSpeed->onMouseOut((ActionHandler)&OptionsBattlescapeState::txtTooltipOut);\n\n\t_txtPathPreview->setText(tr(\"STR_PATH_PREVIEW\"));\n\n\t_btnArrows->setText(tr(\"STR_PATH_ARROWS\"));\n\t_btnArrows->setPressed((Options::battleNewPreviewPath & PATH_ARROWS) != 0);\n\t_btnArrows->onMouseClick((ActionHandler)&OptionsBattlescapeState::btnPathPreviewClick);\n\t_btnArrows->setTooltip(\"STR_PATH_ARROWS_DESC\");\n\t_btnArrows->onMouseIn((ActionHandler)&OptionsBattlescapeState::txtTooltipIn);\n\t_btnArrows->onMouseOut((ActionHandler)&OptionsBattlescapeState::txtTooltipOut);\n\n\t_btnTuCost->setText(tr(\"STR_PATH_TIME_UNIT_COST\"));\n\t_btnTuCost->setPressed((Options::battleNewPreviewPath & PATH_TU_COST) != 0);\n\t_btnTuCost->onMouseClick((ActionHandler)&OptionsBattlescapeState::btnPathPreviewClick);\n\t_btnTuCost->setTooltip(\"STR_PATH_TIME_UNIT_COST_DESC\");\n\t_btnTuCost->onMouseIn((ActionHandler)&OptionsBattlescapeState::txtTooltipIn);\n\t_btnTuCost->onMouseOut((ActionHandler)&OptionsBattlescapeState::txtTooltipOut);\n\n\t_btnEnergyCost->setText(tr(\"STR_PATH_ENERGY_COST\"));\n\t_btnEnergyCost->setPressed((Options::battleNewPreviewPath & PATH_ENERGY_COST) != 0);\n\t_btnEnergyCost->onMouseClick((ActionHandler)&OptionsBattlescapeState::btnPathPreviewClick);\n\t_btnEnergyCost->setTooltip(\"STR_PATH_ENERGY_COST_DESC\");\n\t_btnEnergyCost->onMouseIn((ActionHandler)&OptionsBattlescapeState::txtTooltipIn);\n\t_btnEnergyCost->onMouseOut((ActionHandler)&OptionsBattlescapeState::txtTooltipOut);\n\n\t_txtOptions->setText(tr(\"STR_USER_INTERFACE_OPTIONS\"));\n\n\t_btnTooltips->setText(tr(\"STR_TOOLTIPS\"));\n\t_btnTooltips->setPressed(Options::battleTooltips);\n\t_btnTooltips->onMouseClick((ActionHandler)&OptionsBattlescapeState::btnTooltipsClick);\n\t_btnTooltips->setTooltip(\"STR_TOOLTIPS_DESC\");\n\t_btnTooltips->onMouseIn((ActionHandler)&OptionsBattlescapeState::txtTooltipIn);\n\t_btnTooltips->onMouseOut((ActionHandler)&OptionsBattlescapeState::txtTooltipOut);\n\n\t_btnDeaths->setText(tr(\"STR_DEATH_NOTIFICATIONS\"));\n\t_btnDeaths->setPressed(Options::battleNotifyDeath);\n\t_btnDeaths->onMouseClick((ActionHandler)&OptionsBattlescapeState::btnDeathsClick);\n\t_btnDeaths->setTooltip(\"STR_DEATH_NOTIFICATIONS_DESC\");\n\t_btnDeaths->onMouseIn((ActionHandler)&OptionsBattlescapeState::txtTooltipIn);\n\t_btnDeaths->onMouseOut((ActionHandler)&OptionsBattlescapeState::txtTooltipOut);\n}\n\n/**\n *\n */\nOptionsBattlescapeState::~OptionsBattlescapeState()\n{\n\n}\n\n/**\n * Changes the Edge Scroll option.\n * @param action Pointer to an action.\n */\nvoid OptionsBattlescapeState::cbxEdgeScrollChange(Action *)\n{\n\tOptions::battleEdgeScroll = (ScrollType)_cbxEdgeScroll->getSelected();\n}\n\n/**\n * Changes the Drag Scroll option.\n * @param action Pointer to an action.\n */\nvoid OptionsBattlescapeState::cbxDragScrollChange(Action *)\n{\n\tOptions::battleDragScrollButton = _cbxDragScroll->getSelected();\n}\n\n/**\n * Updates the scroll speed.\n * @param action Pointer to an action.\n */\nvoid OptionsBattlescapeState::slrScrollSpeedChange(Action *)\n{\n\tOptions::battleScrollSpeed = _slrScrollSpeed->getValue();\n}\n\n/**\n * Updates the fire speed.\n * @param action Pointer to an action.\n */\nvoid OptionsBattlescapeState::slrFireSpeedChange(Action *)\n{\n\tOptions::battleFireSpeed = _slrFireSpeed->getValue();\n}\n\n/**\n * Updates the X-COM movement speed.\n * @param action Pointer to an action.\n */\nvoid OptionsBattlescapeState::slrXcomSpeedChange(Action *)\n{\n\tOptions::battleXcomSpeed = _slrXcomSpeed->getValue();\n}\n\n/**\n * Updates the alien movement speed.\n * @param action Pointer to an action.\n */\nvoid OptionsBattlescapeState::slrAlienSpeedChange(Action *)\n{\n\tOptions::battleAlienSpeed = _slrAlienSpeed->getValue();\n}\n\n/**\n * Updates the path preview options.\n * @param action Pointer to an action.\n */\nvoid OptionsBattlescapeState::btnPathPreviewClick(Action *)\n{\n\tint mode = PATH_NONE;\n\tif (_btnArrows->getPressed())\n\t{\n\t\tmode |= PATH_ARROWS;\n\t}\n\tif (_btnTuCost->getPressed())\n\t{\n\t\tmode |= PATH_TU_COST;\n\t}\n\tif (_btnEnergyCost->getPressed())\n\t{\n\t\tmode |= PATH_ENERGY_COST;\n\t}\n\tOptions::battleNewPreviewPath = (PathPreview)mode;\n}\n\n/**\n * Updates the Tooltips option.\n * @param action Pointer to an action.\n */\nvoid OptionsBattlescapeState::btnTooltipsClick(Action *)\n{\n\tOptions::battleTooltips = _btnTooltips->getPressed();\n}\n\n/**\n * Updates the Death Notifications option.\n * @param action Pointer to an action.\n */\nvoid OptionsBattlescapeState::btnDeathsClick(Action *)\n{\n\tOptions::battleNotifyDeath = _btnDeaths->getPressed();\n}\n\n\n}\n"
  },
  {
    "path": "src/Menu/OptionsBattlescapeState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"OptionsBaseState.h\"\n\nnamespace OpenXcom\n{\n\nclass Window;\nclass Text;\nclass TextButton;\nclass ToggleTextButton;\nclass Slider;\nclass ComboBox;\n\n/**\n * Screen that lets the user configure various\n * Battlescape options.\n */\nclass OptionsBattlescapeState : public OptionsBaseState\n{\nprivate:\n\tText *_txtEdgeScroll, *_txtDragScroll;\n\tComboBox *_cbxEdgeScroll, *_cbxDragScroll;\n\tText *_txtScrollSpeed, *_txtFireSpeed, *_txtXcomSpeed, *_txtAlienSpeed;\n\tSlider *_slrScrollSpeed, *_slrFireSpeed, *_slrXcomSpeed, *_slrAlienSpeed;\n\tText *_txtPathPreview;\n\tToggleTextButton *_btnArrows, *_btnTuCost, *_btnEnergyCost;\n\tText *_txtOptions;\n\tToggleTextButton *_btnTooltips, *_btnDeaths;\npublic:\n\t/// Creates the Battlescape Options state.\n\tOptionsBattlescapeState(OptionsOrigin origin);\n\t/// Cleans up the Battlescape Options state.\n\t~OptionsBattlescapeState();\n\t/// Handler for changing the Edge Scroll combobox.\n\tvoid cbxEdgeScrollChange(Action *action);\n\t/// Handler for changing the Drag Scroll combobox.\n\tvoid cbxDragScrollChange(Action *action);\n\t/// Handler for changing the scroll speed slider.\n\tvoid slrScrollSpeedChange(Action *action);\n\t/// Handler for changing the fire speed slider.\n\tvoid slrFireSpeedChange(Action *action);\n\t/// Handler for changing the X-COM movement speed slider.\n\tvoid slrXcomSpeedChange(Action *action);\n\t/// Handler for changing the alien movement speed slider.\n\tvoid slrAlienSpeedChange(Action *action);\n\t/// Handler for clicking a Path Preview button.\n\tvoid btnPathPreviewClick(Action *action);\n\t/// Handler for clicking the Tooltips button.\n\tvoid btnTooltipsClick(Action *action);\n\t/// Handler for clicking the Death Notifications button.\n\tvoid btnDeathsClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Menu/OptionsConfirmState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"OptionsConfirmState.h\"\n#include <sstream>\n#include <iomanip>\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Timer.h\"\n#include \"../Engine/Screen.h\"\n#include \"../Savegame/SavedGame.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Confirm Display Options screen.\n * @param game Pointer to the core game.\n * @param origin Game section that originated this state.\n */\nOptionsConfirmState::OptionsConfirmState(OptionsOrigin origin) : _origin(origin), _countdown(15)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 216, 100, 52, 50, POPUP_BOTH);\n\t_btnYes = new TextButton(50, 20, 70, 120);\n\t_btnNo = new TextButton(50, 20, 200, 120);\n\t_txtTitle = new Text(206, 20, 57, 70);\n\t_txtTimer = new Text(206, 20, 57, 100);\n\t_timer = new Timer(1000);\n\n\t// Set palette\n\tsetInterface(\"optionsMenu\", false, _game->getSavedGame() ? _game->getSavedGame()->getSavedBattle() : 0);\n\n\tadd(_window, \"confirmVideo\", \"optionsMenu\");\n\tadd(_btnYes, \"confirmVideo\", \"optionsMenu\");\n\tadd(_btnNo, \"confirmVideo\", \"optionsMenu\");\n\tadd(_txtTitle, \"confirmVideo\", \"optionsMenu\");\n\tadd(_txtTimer, \"confirmVideo\", \"optionsMenu\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"optionsMenu\");\n\n\t_btnYes->setText(tr(\"STR_YES\"));\n\t_btnYes->onMouseClick((ActionHandler)&OptionsConfirmState::btnYesClick);\n\n\t_btnNo->setText(tr(\"STR_NO\"));\n\t_btnNo->onMouseClick((ActionHandler)&OptionsConfirmState::btnNoClick);\n\t// no keyboard shortcuts to make sure users can see the message\n\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setWordWrap(true);\n\t_txtTitle->setText(tr(\"STR_DISPLAY_OPTIONS_CONFIRM\"));\n\n\t_txtTimer->setAlign(ALIGN_CENTER);\n\t_txtTimer->setWordWrap(true);\n\t_txtTimer->setText(tr(\"STR_DISPLAY_OPTIONS_REVERT\").arg(_countdown));\n\n\tif (_origin == OPT_BATTLESCAPE)\n\t{\n\t\tapplyBattlescapeTheme(\"optionsMenu\");\n\t}\n\n\t_timer->onTimer((StateHandler)&OptionsConfirmState::countdown);\n\t_timer->start();\n}\n\n/**\n *\n */\nOptionsConfirmState::~OptionsConfirmState()\n{\n\tdelete _timer;\n}\n\n/**\n * Runs the countdown timer.\n */\nvoid OptionsConfirmState::think()\n{\n\tState::think();\n\n\t_timer->think(this, 0);\n}\n\n/**\n * Counts down the timer for reverting display options.\n */\nvoid OptionsConfirmState::countdown()\n{\n\t_countdown--;\n\tstd::ostringstream ss;\n\tss << std::setfill('0') << std::setw(2) << _countdown;\n\t_txtTimer->setText(tr(\"STR_DISPLAY_OPTIONS_REVERT\").arg(ss.str()));\n\tif (_countdown == 0)\n\t{\n\t\tbtnNoClick(0);\n\t}\n}\n\n/**\n * Goes back to the Main Menu.\n * @param action Pointer to an action.\n */\nvoid OptionsConfirmState::btnYesClick(Action *)\n{\n\t_game->popState();\n\tOptionsBaseState::restart(_origin);\n}\n\n/**\n * Restores the original display options.\n * @param action Pointer to an action.\n */\nvoid OptionsConfirmState::btnNoClick(Action *)\n{\n\tOptions::switchDisplay();\n\tScreen::updateScale(Options::battlescapeScale, Options::baseXBattlescape, Options::baseYBattlescape, _origin == OPT_BATTLESCAPE);\n\tScreen::updateScale(Options::geoscapeScale, Options::baseXGeoscape, Options::baseYGeoscape, _origin != OPT_BATTLESCAPE);\n\tOptions::save();\n\t_game->getScreen()->resetDisplay();\n\t_game->popState();\n\tOptionsBaseState::restart(_origin);\n}\n\n}\n"
  },
  {
    "path": "src/Menu/OptionsConfirmState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include \"OptionsBaseState.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass Timer;\n\n/**\n * Confirmation window when Display Options\n * are changed.\n */\nclass OptionsConfirmState : public State\n{\nprivate:\n\tOptionsOrigin _origin;\n\tTextButton *_btnYes, *_btnNo;\n\tWindow *_window;\n\tText *_txtTitle, *_txtTimer;\n\tTimer *_timer;\n\tint _countdown;\npublic:\n\t/// Creates the Confirm Display Options state.\n\tOptionsConfirmState(OptionsOrigin origin);\n\t/// Cleans up the Confirm Display Options state.\n\t~OptionsConfirmState();\n\t/// Handle timers.\n\tvoid think() override;\n\t/// Countdown for reverting options.\n\tvoid countdown();\n\t/// Handler for clicking the Yes button.\n\tvoid btnYesClick(Action *action);\n\t/// Handler for clicking the No button.\n\tvoid btnNoClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Menu/OptionsControlsState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"OptionsControlsState.h\"\n#include <SDL.h>\n#include \"../Engine/Options.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Engine/Action.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Controls screen.\n * @param game Pointer to the core game.\n * @param origin Game section that originated this state.\n */\nOptionsControlsState::OptionsControlsState(OptionsOrigin origin) : OptionsBaseState(origin), _selected(-1), _selKey(0)\n{\n\tsetCategory(_btnControls);\n\n\t// Create objects\n\t_btnOXC = new TextButton(70, 16, 94, 8);\n\t_btnOXCE = new TextButton(70, 16, 168, 8);\n\t_btnOTHER = new TextButton(70, 16, 242, 8);\n\t_lstControls = new TextList(200, 120, 94, 26);\n\n\t_owner = _btnOXC;\n\n\tadd(_btnOXC, \"button\", \"controlsMenu\");\n\tadd(_btnOXCE, \"button\", \"controlsMenu\");\n\tadd(_btnOTHER, \"button\", \"controlsMenu\");\n\n\tif (origin != OPT_BATTLESCAPE)\n\t{\n\t\tadd(_lstControls, \"optionLists\", \"controlsMenu\");\n\t}\n\telse\n\t{\n\t\tadd(_lstControls, \"optionLists\", \"battlescape\");\n\t}\n\n\tcenterAllSurfaces();\n\n\t_btnOXC->setText(tr(\"STR_ENGINE_OXC\"));\n\t_btnOXC->setGroup(&_owner);\n\t_btnOXC->onMousePress((ActionHandler)&OptionsControlsState::btnGroupPress, SDL_BUTTON_LEFT);\n\n\t_btnOXCE->setText(tr(\"STR_ENGINE_OXCE\"));\n\t_btnOXCE->setGroup(&_owner);\n\t_btnOXCE->onMousePress((ActionHandler)&OptionsControlsState::btnGroupPress, SDL_BUTTON_LEFT);\n\n\t_btnOTHER->setText(tr(\"STR_ENGINE_OTHER\")); // rename in your fork\n\t_btnOTHER->setGroup(&_owner);\n\t_btnOTHER->onMousePress((ActionHandler)&OptionsControlsState::btnGroupPress, SDL_BUTTON_LEFT);\n\t_btnOTHER->setVisible(false); // enable in your fork\n\n\t// Set up objects\n\t_lstControls->setColumns(2, 152, 48);\n\t_lstControls->setWordWrap(true);\n\t_lstControls->setSelectable(true);\n\t_lstControls->setBackground(_window);\n\t_lstControls->onMouseClick((ActionHandler)&OptionsControlsState::lstControlsClick, 0);\n\t_lstControls->onKeyboardPress((ActionHandler)&OptionsControlsState::lstControlsKeyPress);\n\t_lstControls->setFocus(true);\n\t_lstControls->setTooltip(\"STR_CONTROLS_DESC\");\n\t_lstControls->onMouseIn((ActionHandler)&OptionsControlsState::txtTooltipIn);\n\t_lstControls->onMouseOut((ActionHandler)&OptionsControlsState::txtTooltipOut);\n\n\t_colorGroup = _lstControls->getSecondaryColor();\n\t_colorSel = _lstControls->getScrollbarColor();\n\t_colorNormal = _lstControls->getColor();\n\n\tfor (const auto& optionInfo : Options::getOptionInfo())\n\t{\n\t\tif (optionInfo.type() == OPTION_KEY && !optionInfo.description().empty())\n\t\t{\n\t\t\tif (optionInfo.category() == \"STR_GENERAL\")\n\t\t\t{\n\t\t\t\t_controlsGeneral[optionInfo.owner()].push_back(optionInfo);\n\t\t\t}\n\t\t\telse if (optionInfo.category() == \"STR_GEOSCAPE\")\n\t\t\t{\n\t\t\t\t_controlsGeo[optionInfo.owner()].push_back(optionInfo);\n\t\t\t}\n\t\t\telse if (optionInfo.category() == \"STR_BASESCAPE\")\n\t\t\t{\n\t\t\t\t_controlsBase[optionInfo.owner()].push_back(optionInfo);\n\t\t\t}\n\t\t\telse if (optionInfo.category() == \"STR_BATTLESCAPE\")\n\t\t\t{\n\t\t\t\t_controlsBattle[optionInfo.owner()].push_back(optionInfo);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n *\n */\nOptionsControlsState::~OptionsControlsState()\n{\n}\n\n/**\n * Refreshes the UI.\n */\nvoid OptionsControlsState::init()\n{\n\tOptionsBaseState::init();\n\n\tupdateList();\n}\n\n/**\n * Fills the controls list based on category.\n */\nvoid OptionsControlsState::updateList()\n{\n\tOptionOwner idx = _owner == _btnOXC ? OPTION_OXC : _owner == _btnOXCE ? OPTION_OXCE : OPTION_OTHER;\n\n\t_offsetGeneralMin = -1;\n\t_offsetGeneralMax = -1;\n\t_offsetGeoMin = -1;\n\t_offsetGeoMax = -1;\n\t_offsetBaseMin = -1;\n\t_offsetBaseMax = -1;\n\t_offsetBattleMin = -1;\n\t_offsetBattleMax = -1;\n\n\t_lstControls->clearList();\n\n\tint row = -1;\n\n\tif (_controlsGeneral[idx].size() > 0)\n\t{\n\t\t_lstControls->addRow(2, tr(\"STR_GENERAL\").c_str(), \"\");\n\t\trow++;\n\t\t_offsetGeneralMin = row;\n\t\t_lstControls->setCellColor(_offsetGeneralMin, 0, _colorGroup);\n\t\taddControls(_controlsGeneral[idx]);\n\t\trow += _controlsGeneral[idx].size();\n\t\t_offsetGeneralMax = row;\n\t}\n\tif (_controlsGeo[idx].size() > 0)\n\t{\n\t\tif (row > -1) { _lstControls->addRow(2, \"\", \"\"); row++; }\n\t\t_lstControls->addRow(2, tr(\"STR_GEOSCAPE\").c_str(), \"\");\n\t\trow++;\n\t\t_offsetGeoMin = row;\n\t\t_lstControls->setCellColor(_offsetGeoMin, 0, _colorGroup);\n\t\taddControls(_controlsGeo[idx]);\n\t\trow += _controlsGeo[idx].size();\n\t\t_offsetGeoMax = row;\n\t}\n\tif (_controlsBase[idx].size() > 0)\n\t{\n\t\tif (row > -1) { _lstControls->addRow(2, \"\", \"\"); row++; }\n\t\t_lstControls->addRow(2, tr(\"STR_BASESCAPE\").c_str(), \"\");\n\t\trow++;\n\t\t_offsetBaseMin = row;\n\t\t_lstControls->setCellColor(_offsetBaseMin, 0, _colorGroup);\n\t\taddControls(_controlsBase[idx]);\n\t\trow += _controlsBase[idx].size();\n\t\t_offsetBaseMax = row;\n\t}\n\tif (_controlsBattle[idx].size() > 0)\n\t{\n\t\tif (row > -1) { _lstControls->addRow(2, \"\", \"\"); row++; }\n\t\t_lstControls->addRow(2, tr(\"STR_BATTLESCAPE\").c_str(), \"\");\n\t\trow++;\n\t\t_offsetBattleMin = row;\n\t\t_lstControls->setCellColor(_offsetBattleMin, 0, _colorGroup);\n\t\taddControls(_controlsBattle[idx]);\n\t\trow += _controlsBattle[idx].size();\n\t\t_offsetBattleMax = row;\n\t}\n}\n\n/**\n * Uppercases all the words in a string.\n * @param str Source string.\n * @return Destination string.\n */\nstd::string OptionsControlsState::ucWords(std::string str)\n{\n\tif (!str.empty())\n\t{\n\t\tstr[0] = toupper(str[0]);\n\t}\n\tfor (size_t i = str.find_first_of(' '); i != std::string::npos; i = str.find_first_of(' ', i+1))\n\t{\n\t\tif (str.length() > i+1)\n\t\t\tstr[i+1] = toupper(str[i+1]);\n\t\telse\n\t\t\tbreak;\n\t}\n\treturn str;\n}\n\n/**\n * Adds a bunch of controls to the list.\n * @param keys List of controls.\n */\nvoid OptionsControlsState::addControls(const std::vector<OptionInfo> &keys)\n{\n\tfor (const auto& optionInfo : keys)\n\t{\n\t\tstd::string name = tr(optionInfo.description());\n\t\tSDLKey *key = optionInfo.asKey();\n\t\tstd::string keyName = ucWords(SDL_GetKeyName(*key));\n\t\tif (*key == SDLK_UNKNOWN)\n\t\t\tkeyName = \"\";\n\t\t_lstControls->addRow(2, name.c_str(), keyName.c_str());\n\t}\n}\n\n/**\n * Gets the currently selected control.\n * @param sel Selected row.\n * @return Pointer to option, NULL if none selected.\n */\nOptionInfo *OptionsControlsState::getControl(size_t sel)\n{\n\tint selInt = sel;\n\tOptionOwner idx = _owner == _btnOXC ? OPTION_OXC : _owner == _btnOXCE ? OPTION_OXCE : OPTION_OTHER;\n\n\tif (selInt > _offsetGeneralMin && selInt <= _offsetGeneralMax)\n\t{\n\t\treturn &_controlsGeneral[idx][selInt - 1 - _offsetGeneralMin];\n\t}\n\telse if (selInt > _offsetGeoMin && selInt <= _offsetGeoMax)\n\t{\n\t\treturn &_controlsGeo[idx][selInt - 1 - _offsetGeoMin];\n\t}\n\telse if (selInt > _offsetBaseMin && selInt <= _offsetBaseMax)\n\t{\n\t\treturn &_controlsBase[idx][selInt - 1 - _offsetBaseMin];\n\t}\n\telse if (selInt > _offsetBattleMin && selInt <= _offsetBattleMax)\n\t{\n\t\treturn &_controlsBattle[idx][selInt - 1 - _offsetBattleMin];\n\t}\n\telse\n\t{\n\t\treturn 0;\n\t}\n}\n\n/**\n * Select a control for changing.\n * @param action Pointer to an action.\n */\nvoid OptionsControlsState::lstControlsClick(Action *action)\n{\n\tif (action->getDetails()->button.button != SDL_BUTTON_LEFT && action->getDetails()->button.button != SDL_BUTTON_RIGHT)\n\t{\n\t\treturn;\n\t}\n\tif (_selected != -1)\n\t{\n\t\tunsigned int selected = _selected;\n\t\t_lstControls->setCellColor(_selected, 0, _colorNormal);\n\t\t_lstControls->setCellColor(_selected, 1, _colorNormal);\n\t\t_selected = -1;\n\t\t_selKey = 0;\n\t\tif (selected == _lstControls->getSelectedRow())\n\t\t\treturn;\n\t}\n\t_selected = _lstControls->getSelectedRow();\n\t_selKey = getControl(_selected);\n\tif (!_selKey)\n\t{\n\t\t_selected = -1;\n\t\treturn;\n\t}\n\n\tif (action->getDetails()->button.button == SDL_BUTTON_LEFT)\n\t{\n\t\t_lstControls->setCellColor(_selected, 0, _colorSel);\n\t\t_lstControls->setCellColor(_selected, 1, _colorSel);\n\t}\n\telse if (action->getDetails()->button.button == SDL_BUTTON_RIGHT)\n\t{\n\t\t_lstControls->setCellText(_selected, 1, \"\");\n\t\t*_selKey->asKey() = SDLK_UNKNOWN;\n\t\t_selected = -1;\n\t\t_selKey = 0;\n\t}\n}\n\n/**\n * Change selected control.\n * @param action Pointer to an action.\n */\nvoid OptionsControlsState::lstControlsKeyPress(Action *action)\n{\n\tif (_selected != -1)\n\t{\n\t\tSDLKey key = action->getDetails()->key.keysym.sym;\n\t\tif (key != 0 &&\n\t\t\tkey != SDLK_LSHIFT && key != SDLK_LALT && key != SDLK_LCTRL &&\n\t\t\tkey != SDLK_RSHIFT && key != SDLK_RALT && key != SDLK_RCTRL)\n\t\t{\n\t\t\t*_selKey->asKey() = key;\n\t\t\tstd::string name = ucWords(SDL_GetKeyName(*_selKey->asKey()));\n\t\t\t_lstControls->setCellText(_selected, 1, name);\n\t\t}\n\t\t_lstControls->setCellColor(_selected, 0, _colorNormal);\n\t\t_lstControls->setCellColor(_selected, 1, _colorNormal);\n\t\t_selected = -1;\n\t\t_selKey = 0;\n\t}\n}\n\nvoid OptionsControlsState::btnGroupPress(Action*)\n{\n\tupdateList();\n}\n\n}\n"
  },
  {
    "path": "src/Menu/OptionsControlsState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include <vector>\n#include \"../Engine/OptionInfo.h\"\n#include \"OptionsBaseState.h\"\n\nnamespace OpenXcom\n{\n\nclass TextList;\n\n/**\n * Controls screen which allows the user to\n * customize the various key shortcuts in the game.\n */\nclass OptionsControlsState : public OptionsBaseState\n{\nprivate:\n\tTextButton *_btnOXC, *_btnOXCE, *_btnOTHER;\n\tTextButton *_owner;\n\tTextList *_lstControls;\n\tstd::vector<OptionInfo> _controlsGeneral[OPTION_OWNER_MAX];\n\tstd::vector<OptionInfo> _controlsGeo[OPTION_OWNER_MAX];\n\tstd::vector<OptionInfo> _controlsBase[OPTION_OWNER_MAX];\n\tstd::vector<OptionInfo> _controlsBattle[OPTION_OWNER_MAX];\n\tint _offsetGeneralMin = -1;\n\tint _offsetGeneralMax = -1;\n\tint _offsetGeoMin = -1;\n\tint _offsetGeoMax = -1;\n\tint _offsetBaseMin = -1;\n\tint _offsetBaseMax = -1;\n\tint _offsetBattleMin = -1;\n\tint _offsetBattleMax = -1;\n\n\tint _selected;\n\tOptionInfo *_selKey;\n\tUint8 _colorGroup, _colorSel, _colorNormal;\n\n\tvoid addControls(const std::vector<OptionInfo> &keys);\n\tOptionInfo *getControl(size_t sel);\n\tstd::string ucWords(std::string str);\npublic:\n\t/// Creates the Controls state.\n\tOptionsControlsState(OptionsOrigin origin);\n\t/// Cleans up the Controls state.\n\t~OptionsControlsState();\n\t/// Refreshes the UI.\n\tvoid init() override;\n\t/// Fills controls list.\n\tvoid updateList();\n\t/// Handler for clicking the Controls list.\n\tvoid lstControlsClick(Action *action);\n\t/// Handler for pressing a key in the Controls list.\n\tvoid lstControlsKeyPress(Action *action);\n\t/// Handler for clicking buttons.\n\tvoid btnGroupPress(Action* action);\n};\n\n}\n"
  },
  {
    "path": "src/Menu/OptionsDefaultsState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"OptionsDefaultsState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Engine/Options.h\"\n#include \"../Savegame/SavedGame.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Restore Defaults screen.\n * @param game Pointer to the core game.\n * @param origin Game section that originated this state.\n * @param state Pointer to the base Options state.\n */\nOptionsDefaultsState::OptionsDefaultsState(OptionsOrigin origin, OptionsBaseState *state) : _origin(origin), _state(state)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_window = new Window(this, 256, 100, 32, 50, POPUP_BOTH);\n\t_btnYes = new TextButton(60, 18, 60, 122);\n\t_btnNo = new TextButton(60, 18, 200, 122);\n\t_txtTitle = new Text(246, 32, 37, 70);\n\n\t// Set palette\n\tsetInterface(\"optionsMenu\", false, _game->getSavedGame() ? _game->getSavedGame()->getSavedBattle() : 0);\n\n\tadd(_window, \"confirmDefaults\", \"optionsMenu\");\n\tadd(_btnYes, \"confirmDefaults\", \"optionsMenu\");\n\tadd(_btnNo, \"confirmDefaults\", \"optionsMenu\");\n\tadd(_txtTitle, \"confirmDefaults\", \"optionsMenu\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"optionsMenu\");\n\n\t_btnYes->setText(tr(\"STR_YES\"));\n\t_btnYes->onMouseClick((ActionHandler)&OptionsDefaultsState::btnYesClick);\n\t_btnYes->onKeyboardPress((ActionHandler)&OptionsDefaultsState::btnYesClick, Options::keyOk);\n\n\t_btnNo->setText(tr(\"STR_NO\"));\n\t_btnNo->onMouseClick((ActionHandler)&OptionsDefaultsState::btnNoClick);\n\t_btnNo->onKeyboardPress((ActionHandler)&OptionsDefaultsState::btnNoClick, Options::keyCancel);\n\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setBig();\n\t_txtTitle->setWordWrap(true);\n\t_txtTitle->setText(tr(\"STR_RESTORE_DEFAULTS_QUESTION\"));\n\n\tif (_origin == OPT_BATTLESCAPE)\n\t{\n\t\tapplyBattlescapeTheme(\"optionsMenu\");\n\t}\n}\n\n/**\n *\n */\nOptionsDefaultsState::~OptionsDefaultsState()\n{\n\n}\n\n/**\n * Restores the default options.\n * @param action Pointer to an action.\n */\nvoid OptionsDefaultsState::btnYesClick(Action *action)\n{\n\tOptions::resetDefault(false);\n\tOptions::save(true);\n\tif (_game->isCtrlPressed())\n\t{\n\t\t// my development/debug defaults\n\t\tOptions::debug = true;\n\t\tOptions::language = \"en-US\";\n\t\tOptions::musicVolume = 15;\n\t\tOptions::soundVolume = 15;\n\t\tOptions::uiVolume = 15;\n\t\tOptions::keyFps = SDLK_UNKNOWN;\n\t\tOptions::playIntro = false;\n\t\tOptions::autosave = false;\n\t\tOptions::showFundsOnGeoscape = true;\n\t\tOptions::battleFireSpeed = 16;\n\t\tOptions::battleXcomSpeed = 1;\n\t\tOptions::battleNotifyDeath = true;\n\t\tOptions::battleNewPreviewPath = PATH_ARROW_TU;\n\t\tOptions::battleUFOExtenderAccuracy = true;\n\t\tOptions::showMoreStatsInInventoryView = true;\n\t\tOptions::battleAutoEnd = true;\n\t\tOptions::disableAutoEquip = true;\n\t\tOptions::strafe = true;\n\t\tOptions::skipNextTurnScreen = true;\n\t\tOptions::alienBleeding = true;\n\t}\n\t_game->loadLanguages();\n\t_game->popState();\n\t_state->btnOkClick(action);\n}\n\n/**\n * Closes the window.\n * @param action Pointer to an action.\n */\nvoid OptionsDefaultsState::btnNoClick(Action *)\n{\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Menu/OptionsDefaultsState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include \"OptionsBaseState.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\n\n/**\n * Confirmation window when restoring the\n * default game options.\n */\nclass OptionsDefaultsState : public State\n{\nprivate:\n\tOptionsOrigin _origin;\n\tTextButton *_btnYes, *_btnNo;\n\tWindow *_window;\n\tText *_txtTitle;\n\tOptionsBaseState *_state;\npublic:\n\t/// Creates the Restore Defaults state.\n\tOptionsDefaultsState(OptionsOrigin origin, OptionsBaseState *state);\n\t/// Cleans up the Restore Defaults state.\n\t~OptionsDefaultsState();\n\t/// Handler for clicking the Yes button.\n\tvoid btnYesClick(Action *action);\n\t/// Handler for clicking the No button.\n\tvoid btnNoClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Menu/OptionsFoldersState.cpp",
    "content": "/*\n * Copyright 2010-2019 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"OptionsFoldersState.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/CrossPlatform.h\"\n#include \"../Engine/FileMap.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/Text.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Folders Options screen.\n * @param origin Game section that originated this state.\n */\nOptionsFoldersState::OptionsFoldersState(OptionsOrigin origin) : OptionsBaseState(origin)\n{\n\tsetCategory(_btnFolders);\n\n\t// Create object\n\t_txtDataFolder = new Text(218, 9, 94, 8);\n\t_txtUserFolder = new Text(218, 9, 94, 59);\n\t_txtSaveFolder = new Text(218, 9, 94, 86);\n\t_txtConfigFolder = new Text(218, 9, 94, 121);\n\n\t_txtDataFolderPath1 = new Text(218, 17, 94, 18);\n\t_txtDataFolderPath2 = new Text(218, 17, 94, 38);\n\t_txtUserFolderPath = new Text(218, 17, 94, 69);\n\t_txtSaveFolderPath = new Text(218, 25, 94, 96);\n\t_txtConfigFolderPath = new Text(218, 17, 94, 131);\n\n\tadd(_txtDataFolder, \"text1\", \"foldersMenu\");\n\tadd(_txtUserFolder, \"text1\", \"foldersMenu\");\n\tadd(_txtSaveFolder, \"text1\", \"foldersMenu\");\n\tadd(_txtConfigFolder, \"text1\", \"foldersMenu\");\n\n\tadd(_txtDataFolderPath1, \"text2\", \"foldersMenu\");\n\tadd(_txtDataFolderPath2, \"text2\", \"foldersMenu\");\n\tadd(_txtUserFolderPath, \"text2\", \"foldersMenu\");\n\tadd(_txtSaveFolderPath, \"text2\", \"foldersMenu\");\n\tadd(_txtConfigFolderPath, \"text2\", \"foldersMenu\");\n\n\tcenterAllSurfaces();\n\n\t// Set up object\n\t_txtDataFolder->setText(tr(\"STR_DATA_FOLDER\"));\n\t_txtUserFolder->setText(tr(\"STR_USER_FOLDER\"));\n\t_txtSaveFolder->setText(tr(\"STR_SAVE_FOLDER\"));\n\t_txtConfigFolder->setText(tr(\"STR_CONFIG_FOLDER\"));\n\n\tstd::string file1 = \"GEODATA/BACKPALS.DAT\";\n\tstd::string file2 = \"openxcom.png\";\n\n\tstd::string origDataFolder = \"<error1>\";\n\tif (FileMap::fileExists(file1))\n\t{\n\t\torigDataFolder = FileMap::at(file1)->fullpath;\n\t\torigDataFolder = origDataFolder.substr(0, origDataFolder.find(file1));\n\t}\n\tstd::string oxceDataFolder = \"<error2>\";\n\tif (FileMap::fileExists(file2))\n\t{\n\t\toxceDataFolder = FileMap::at(file2)->fullpath;\n\t\toxceDataFolder = oxceDataFolder.substr(0, oxceDataFolder.find(file2));\n\t}\n\n\t_txtDataFolderPath1->setText(origDataFolder);\n\t_txtDataFolderPath1->setWordWrap(true);\n\t_txtDataFolderPath1->setTooltip(\"STR_DATA_FOLDER_DESC_1\");\n\t_txtDataFolderPath1->onMouseIn((ActionHandler)&OptionsFoldersState::txtTooltipIn);\n\t_txtDataFolderPath1->onMouseOut((ActionHandler)&OptionsFoldersState::txtTooltipOut);\n\t_txtDataFolderPath1->onMouseClick((ActionHandler)&OptionsFoldersState::txtClick);\n\n\t_txtDataFolderPath2->setText(oxceDataFolder);\n\t_txtDataFolderPath2->setWordWrap(true);\n\t_txtDataFolderPath2->setTooltip(\"STR_DATA_FOLDER_DESC_2\");\n\t_txtDataFolderPath2->onMouseIn((ActionHandler)&OptionsFoldersState::txtTooltipIn);\n\t_txtDataFolderPath2->onMouseOut((ActionHandler)&OptionsFoldersState::txtTooltipOut);\n\t_txtDataFolderPath2->onMouseClick((ActionHandler)&OptionsFoldersState::txtClick);\n\n\t_txtUserFolderPath->setText(Options::getUserFolder());\n\t_txtUserFolderPath->setWordWrap(true);\n\t_txtUserFolderPath->setTooltip(\"STR_USER_FOLDER_DESC\");\n\t_txtUserFolderPath->onMouseIn((ActionHandler)&OptionsFoldersState::txtTooltipIn);\n\t_txtUserFolderPath->onMouseOut((ActionHandler)&OptionsFoldersState::txtTooltipOut);\n\t_txtUserFolderPath->onMouseClick((ActionHandler)&OptionsFoldersState::txtClick);\n\n\t_txtSaveFolderPath->setText(Options::getMasterUserFolder());\n\t_txtSaveFolderPath->setWordWrap(true);\n\t_txtSaveFolderPath->setTooltip(\"STR_SAVE_FOLDER_DESC\");\n\t_txtSaveFolderPath->onMouseIn((ActionHandler)&OptionsFoldersState::txtTooltipIn);\n\t_txtSaveFolderPath->onMouseOut((ActionHandler)&OptionsFoldersState::txtTooltipOut);\n\t_txtSaveFolderPath->onMouseClick((ActionHandler)&OptionsFoldersState::txtClick);\n\n\t_txtConfigFolderPath->setText(Options::getConfigFolder());\n\t_txtConfigFolderPath->setWordWrap(true);\n\t_txtConfigFolderPath->setTooltip(\"STR_CONFIG_FOLDER_DESC\");\n\t_txtConfigFolderPath->onMouseIn((ActionHandler)&OptionsFoldersState::txtTooltipIn);\n\t_txtConfigFolderPath->onMouseOut((ActionHandler)&OptionsFoldersState::txtTooltipOut);\n\t_txtConfigFolderPath->onMouseClick((ActionHandler)&OptionsFoldersState::txtClick);\n}\n\n/**\n *\n */\nOptionsFoldersState::~OptionsFoldersState()\n{\n\n}\n\n/**\n * Opens the location of the appropriate folder.\n * @param action Pointer to an action.\n */\nvoid OptionsFoldersState::txtClick(Action* action)\n{\n\tText* sender = (Text*)action->getSender();\n\tstd::string path = sender->getText();\n\tif (Options::getDataFolder().empty() && path.size() < 10)\n\t{\n\t\t// \"UFO/\", \"TFTD/\", \"common/\", \"standard/\"\n\t\tpath = CrossPlatform::getExeFolder() + path;\n\t}\n\tCrossPlatform::openExplorer(path);\n}\n\n}\n"
  },
  {
    "path": "src/Menu/OptionsFoldersState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2019 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"OptionsBaseState.h\"\n\nnamespace OpenXcom\n{\n\nclass Text;\n\n/**\n * Screen that shows the user various folders used by OpenXcom.\n */\nclass OptionsFoldersState : public OptionsBaseState\n{\nprivate:\n\tText *_txtDataFolder, *_txtUserFolder, *_txtSaveFolder, *_txtConfigFolder;\n\tText* _txtDataFolderPath1, *_txtDataFolderPath2, *_txtUserFolderPath, *_txtSaveFolderPath, *_txtConfigFolderPath;\npublic:\n\t/// Creates the Folders Options state.\n\tOptionsFoldersState(OptionsOrigin origin);\n\t/// Cleans up the Folders Options state.\n\t~OptionsFoldersState();\n\t/// Handler for opei.\n\tvoid txtClick(Action* action);\n};\n\n}\n"
  },
  {
    "path": "src/Menu/OptionsGeoscapeState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"OptionsGeoscapeState.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/Slider.h\"\n#include \"../Interface/ToggleTextButton.h\"\n#include \"../Interface/ComboBox.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Options.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Geoscape Options screen.\n * @param game Pointer to the core game.\n * @param origin Game section that originated this state.\n */\nOptionsGeoscapeState::OptionsGeoscapeState(OptionsOrigin origin) : OptionsBaseState(origin)\n{\n\tsetCategory(_btnGeoscape);\n\n\t// Create objects\n\t_txtDragScroll = new Text(114, 9, 206, 8);\n\t_cbxDragScroll = new ComboBox(this, 104, 16, 206, 18);\n\n\t_txtScrollSpeed = new Text(114, 9, 94, 8);\n\t_slrScrollSpeed = new Slider(104, 16, 94, 18);\n\n\t_txtDogfightSpeed = new Text(114, 9, 206, 40);\n\t_slrDogfightSpeed = new Slider(104, 16, 206, 50);\n\n\t_txtClockSpeed = new Text(114, 9, 94, 40);\n\t_slrClockSpeed = new Slider(104, 16, 94, 50);\n\n\t_txtGlobeDetails = new Text(114, 9, 94, 82);\n\t_btnGlobeCountries = new ToggleTextButton(104, 16, 94, 92);\n\t_btnGlobeRadars = new ToggleTextButton(104, 16, 94, 110);\n\t_btnGlobePaths = new ToggleTextButton(104, 16, 94, 128);\n\n\t_txtOptions = new Text(114, 9, 206, 82);\n\t_btnShowFunds = new ToggleTextButton(104, 16, 206, 92);\n\n\tadd(_txtScrollSpeed, \"text\", \"geoscapeMenu\");\n\tadd(_slrScrollSpeed, \"button\", \"geoscapeMenu\");\n\n\tadd(_txtDogfightSpeed, \"text\", \"geoscapeMenu\");\n\tadd(_slrDogfightSpeed, \"button\", \"geoscapeMenu\");\n\n\tadd(_txtClockSpeed, \"text\", \"geoscapeMenu\");\n\tadd(_slrClockSpeed, \"button\", \"geoscapeMenu\");\n\n\tadd(_txtGlobeDetails, \"text\", \"geoscapeMenu\");\n\tadd(_btnGlobeCountries, \"button\", \"geoscapeMenu\");\n\tadd(_btnGlobeRadars, \"button\", \"geoscapeMenu\");\n\tadd(_btnGlobePaths, \"button\", \"geoscapeMenu\");\n\n\tadd(_txtOptions, \"text\", \"geoscapeMenu\");\n\tadd(_btnShowFunds, \"button\", \"geoscapeMenu\");\n\n\tadd(_txtDragScroll, \"text\", \"geoscapeMenu\");\n\tadd(_cbxDragScroll, \"button\", \"geoscapeMenu\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\t_txtDragScroll->setText(tr(\"STR_DRAG_SCROLL\"));\n\n\tstd::vector<std::string> dragScrolls;\n\tdragScrolls.push_back(tr(\"STR_DISABLED\"));\n\tdragScrolls.push_back(tr(\"STR_LEFT_MOUSE_BUTTON\"));\n\tdragScrolls.push_back(tr(\"STR_MIDDLE_MOUSE_BUTTON\"));\n\tdragScrolls.push_back(tr(\"STR_RIGHT_MOUSE_BUTTON\"));\n\n\t_cbxDragScroll->setOptions(dragScrolls);\n\t_cbxDragScroll->setSelected(Options::geoDragScrollButton);\n\t_cbxDragScroll->onChange((ActionHandler)&OptionsGeoscapeState::cbxDragScrollChange);\n\t_cbxDragScroll->setTooltip(\"STR_DRAG_SCROLL_DESC\");\n\t_cbxDragScroll->onMouseIn((ActionHandler)&OptionsGeoscapeState::txtTooltipIn);\n\t_cbxDragScroll->onMouseOut((ActionHandler)&OptionsGeoscapeState::txtTooltipOut);\n\n\t_txtScrollSpeed->setText(tr(\"STR_SCROLL_SPEED\"));\n\n\t_slrScrollSpeed->setRange(100, 10);\n\t_slrScrollSpeed->setValue(Options::geoScrollSpeed);\n\t_slrScrollSpeed->setTooltip(\"STR_SCROLL_SPEED_GEO_DESC\");\n\t_slrScrollSpeed->onChange((ActionHandler)&OptionsGeoscapeState::slrScrollSpeedChange);\n\t_slrScrollSpeed->onMouseIn((ActionHandler)&OptionsGeoscapeState::txtTooltipIn);\n\t_slrScrollSpeed->onMouseOut((ActionHandler)&OptionsGeoscapeState::txtTooltipOut);\n\n\t_txtDogfightSpeed->setText(tr(\"STR_DOGFIGHT_SPEED\"));\n\n\t_slrDogfightSpeed->setRange(50, 20);\n\t_slrDogfightSpeed->setValue(Options::dogfightSpeed);\n\t_slrDogfightSpeed->onChange((ActionHandler)&OptionsGeoscapeState::slrDogfightSpeedChange);\n\t_slrDogfightSpeed->setTooltip(\"STR_DOGFIGHT_SPEED_DESC\");\n\t_slrDogfightSpeed->onMouseIn((ActionHandler)&OptionsGeoscapeState::txtTooltipIn);\n\t_slrDogfightSpeed->onMouseOut((ActionHandler)&OptionsGeoscapeState::txtTooltipOut);\n\n\t_txtClockSpeed->setText(tr(\"STR_CLOCK_SPEED\"));\n\n\t_slrClockSpeed->setRange(250, 10);\n\t_slrClockSpeed->setValue(Options::geoClockSpeed);\n\t_slrClockSpeed->setTooltip(\"STR_CLOCK_SPEED_DESC\");\n\t_slrClockSpeed->onChange((ActionHandler)&OptionsGeoscapeState::slrClockSpeedChange);\n\t_slrClockSpeed->onMouseIn((ActionHandler)&OptionsGeoscapeState::txtTooltipIn);\n\t_slrClockSpeed->onMouseOut((ActionHandler)&OptionsGeoscapeState::txtTooltipOut);\n\n\t_txtGlobeDetails->setText(tr(\"STR_GLOBE_DETAILS\"));\n\n\t_btnGlobeCountries->setText(tr(\"STR_GLOBE_COUNTRIES\"));\n\t_btnGlobeCountries->setPressed(Options::globeDetail);\n\t_btnGlobeCountries->onMouseClick((ActionHandler)&OptionsGeoscapeState::btnGlobeCountriesClick);\n\t_btnGlobeCountries->setTooltip(\"STR_GLOBE_COUNTRIES_DESC\");\n\t_btnGlobeCountries->onMouseIn((ActionHandler)&OptionsGeoscapeState::txtTooltipIn);\n\t_btnGlobeCountries->onMouseOut((ActionHandler)&OptionsGeoscapeState::txtTooltipOut);\n\n\t_btnGlobeRadars->setText(tr(\"STR_GLOBE_RADARS\"));\n\t_btnGlobeRadars->setPressed(Options::globeRadarLines);\n\t_btnGlobeRadars->onMouseClick((ActionHandler)&OptionsGeoscapeState::btnGlobeRadarsClick);\n\t_btnGlobeRadars->setTooltip(\"STR_GLOBE_RADARS_DESC\");\n\t_btnGlobeRadars->onMouseIn((ActionHandler)&OptionsGeoscapeState::txtTooltipIn);\n\t_btnGlobeRadars->onMouseOut((ActionHandler)&OptionsGeoscapeState::txtTooltipOut);\n\n\t_btnGlobePaths->setText(tr(\"STR_GLOBE_FLIGHT_PATHS\"));\n\t_btnGlobePaths->setPressed(Options::globeFlightPaths);\n\t_btnGlobePaths->onMouseClick((ActionHandler)&OptionsGeoscapeState::btnGlobePathsClick);\n\t_btnGlobePaths->setTooltip(\"STR_GLOBE_FLIGHT_PATHS_DESC\");\n\t_btnGlobePaths->onMouseIn((ActionHandler)&OptionsGeoscapeState::txtTooltipIn);\n\t_btnGlobePaths->onMouseOut((ActionHandler)&OptionsGeoscapeState::txtTooltipOut);\n\n\t_txtOptions->setText(tr(\"STR_USER_INTERFACE_OPTIONS\"));\n\n\t_btnShowFunds->setText(tr(\"STR_SHOW_FUNDS\"));\n\t_btnShowFunds->setPressed(Options::showFundsOnGeoscape);\n\t_btnShowFunds->onMouseClick((ActionHandler)&OptionsGeoscapeState::btnShowFundsClick);\n\t_btnShowFunds->setTooltip(\"STR_SHOW_FUNDS_DESC\");\n\t_btnShowFunds->onMouseIn((ActionHandler)&OptionsGeoscapeState::txtTooltipIn);\n\t_btnShowFunds->onMouseOut((ActionHandler)&OptionsGeoscapeState::txtTooltipOut);\n}\n\n/**\n *\n */\nOptionsGeoscapeState::~OptionsGeoscapeState()\n{\n\n}\n\n/**\n * Changes the Drag Scroll option.\n * @param action Pointer to an action.\n */\nvoid OptionsGeoscapeState::cbxDragScrollChange(Action *)\n{\n\tOptions::geoDragScrollButton = _cbxDragScroll->getSelected();\n}\n\n/**\n * Updates the scroll speed.\n * @param action Pointer to an action.\n */\nvoid OptionsGeoscapeState::slrScrollSpeedChange(Action *)\n{\n\tOptions::geoScrollSpeed = _slrScrollSpeed->getValue();\n}\n\n/**\n * Updates the dogfight speed.\n * @param action Pointer to an action.\n */\nvoid OptionsGeoscapeState::slrDogfightSpeedChange(Action *)\n{\n\tOptions::dogfightSpeed = _slrDogfightSpeed->getValue();\n}\n\n/**\n * Updates the clock speed.\n * @param action Pointer to an action.\n */\nvoid OptionsGeoscapeState::slrClockSpeedChange(Action *)\n{\n\tOptions::geoClockSpeed = _slrClockSpeed->getValue();\n}\n\n/**\n * Changes the Globe Country Borders option.\n * @param action Pointer to an action.\n */\nvoid OptionsGeoscapeState::btnGlobeCountriesClick(Action *)\n{\n\tOptions::globeDetail = _btnGlobeCountries->getPressed();\n}\n\n/**\n * Changes the Globe Radar Ranges option.\n * @param action Pointer to an action.\n */\nvoid OptionsGeoscapeState::btnGlobeRadarsClick(Action *)\n{\n\tOptions::globeRadarLines = _btnGlobeRadars->getPressed();\n}\n\n/**\n * Changes the Globe Flight Paths option.\n * @param action Pointer to an action.\n */\nvoid OptionsGeoscapeState::btnGlobePathsClick(Action *)\n{\n\tOptions::globeFlightPaths = _btnGlobePaths->getPressed();\n}\n\n/**\n * Changes the Show Funds option.\n * @param action Pointer to an action.\n */\nvoid OptionsGeoscapeState::btnShowFundsClick(Action *)\n{\n\tOptions::showFundsOnGeoscape = _btnShowFunds->getPressed();\n}\n\n}\n"
  },
  {
    "path": "src/Menu/OptionsGeoscapeState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"OptionsBaseState.h\"\n\nnamespace OpenXcom\n{\n\nclass Text;\nclass TextButton;\nclass ToggleTextButton;\nclass Slider;\nclass ComboBox;\n\n/**\n * Screen that lets the user configure various\n * Geoscape options.\n */\nclass OptionsGeoscapeState : public OptionsBaseState\n{\nprivate:\n\tText *_txtDragScroll;\n\tComboBox *_cbxDragScroll;\n\tText *_txtScrollSpeed, *_txtDogfightSpeed, *_txtClockSpeed;\n\tSlider *_slrScrollSpeed, *_slrDogfightSpeed, *_slrClockSpeed;\n\tText *_txtGlobeDetails;\n\tToggleTextButton *_btnGlobeCountries, *_btnGlobeRadars, *_btnGlobePaths;\n\tText *_txtOptions;\n\tToggleTextButton *_btnShowFunds;\npublic:\n\t/// Creates the Geoscape Options state.\n\tOptionsGeoscapeState(OptionsOrigin origin);\n\t/// Cleans up the Geoscape Options state.\n\t~OptionsGeoscapeState();\n\t/// Handler for changing the Drag Scroll combobox.\n\tvoid cbxDragScrollChange(Action *action);\n\t/// Handler for changing the scroll speed slider.\n\tvoid slrScrollSpeedChange(Action *action);\n\t/// Handler for changing the dogfight speed slider.\n\tvoid slrDogfightSpeedChange(Action *action);\n\t/// Handler for changing the clock speed slider.\n\tvoid slrClockSpeedChange(Action *action);\n\t/// Handler for clicking the Country Borders button.\n\tvoid btnGlobeCountriesClick(Action *action);\n\t/// Handler for clicking the Radar Ranges button.\n\tvoid btnGlobeRadarsClick(Action *action);\n\t/// Handler for clicking the Flight Paths button.\n\tvoid btnGlobePathsClick(Action *action);\n\t/// Handler for clicking the Show Funds button.\n\tvoid btnShowFundsClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Menu/OptionsNoAudioState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"OptionsNoAudioState.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/Text.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Audio Options screen.\n * @param game Pointer to the core game.\n * @param origin Game section that originated this state.\n */\nOptionsNoAudioState::OptionsNoAudioState(OptionsOrigin origin) : OptionsBaseState(origin)\n{\n\tsetCategory(_btnAudio);\n\n\t// Create objects\n\t_txtError = new Text(218, 136, 94, 8);\n\n\tadd(_txtError, \"text\", \"audioMenu\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\t_txtError->setAlign(ALIGN_CENTER);\n\t_txtError->setVerticalAlign(ALIGN_MIDDLE);\n\t_txtError->setBig();\n\t_txtError->setWordWrap(true);\n\t_txtError->setText(tr(\"STR_NO_AUDIO_HARDWARE_DETECTED\"));\n}\n\n/**\n *\n */\nOptionsNoAudioState::~OptionsNoAudioState()\n{\n\n}\n\n}\n"
  },
  {
    "path": "src/Menu/OptionsNoAudioState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"OptionsBaseState.h\"\n\nnamespace OpenXcom\n{\n\nclass Text;\n\n/**\n * Screen that indicates there is no audio available.\n */\nclass OptionsNoAudioState : public OptionsBaseState\n{\nprivate:\n\tText *_txtError;\npublic:\n\t/// Creates the Audio Options state.\n\tOptionsNoAudioState(OptionsOrigin origin);\n\t/// Cleans up the Audio Options state.\n\t~OptionsNoAudioState();\n};\n\n}\n"
  },
  {
    "path": "src/Menu/OptionsVideoState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"OptionsVideoState.h\"\n#include \"../Engine/Language.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Engine/Action.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextEdit.h\"\n#include \"../Interface/ToggleTextButton.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Screen.h\"\n#include \"../Interface/ArrowButton.h\"\n#include \"../Engine/FileMap.h\"\n#include \"../Engine/Logger.h\"\n#include \"../Interface/ComboBox.h\"\n#include \"../Engine/Game.h\"\n#include \"SetWindowedRootState.h\"\n\nnamespace OpenXcom\n{\n\nconst std::string OptionsVideoState::GL_EXT = \"OpenGL.shader\";\nconst std::string OptionsVideoState::GL_FOLDER = \"Shaders/\";\nconst std::string OptionsVideoState::GL_STRING = \"*\";\n\n/**\n * Initializes all the elements in the Video Options screen.\n * @param game Pointer to the core game.\n * @param origin Game section that originated this state.\n */\nOptionsVideoState::OptionsVideoState(OptionsOrigin origin) : OptionsBaseState(origin)\n{\n\tsetCategory(_btnVideo);\n\n\t// Create objects\n\t_displaySurface = new InteractiveSurface(110, 32, 94, 18);\n\t_txtDisplayResolution = new Text(114, 9, 94, 8);\n\t_txtDisplayWidth = new TextEdit(this, 40, 17, 94, 26);\n\t_txtDisplayX = new Text(16, 17, 132, 26);\n\t_txtDisplayHeight = new TextEdit(this, 40, 17, 144, 26);\n\t_btnDisplayResolutionUp = new ArrowButton(ARROW_BIG_UP, 14, 14, 186, 18);\n\t_btnDisplayResolutionDown = new ArrowButton(ARROW_BIG_DOWN, 14, 14, 186, 36);\n\n\t_txtLanguage = new Text(114, 9, 94, 52);\n\t_cbxLanguage = new ComboBox(this, 104, 16, 94, 62);\n\n\t_txtFilter = new Text(114, 9, 206, 52);\n\t_cbxFilter = new ComboBox(this, 104, 16, 206, 62);\n\n\t_txtMode = new Text(114, 9, 206, 22);\n\t_cbxDisplayMode = new ComboBox(this, 104, 16, 206, 32);\n\n\t_txtGeoScale = new Text(114, 9, 94, 82);\n\t_cbxGeoScale = new ComboBox(this, 104, 16, 94, 92);\n\n\t_txtBattleScale = new Text(114, 9, 94, 112);\n\t_cbxBattleScale = new ComboBox(this, 104, 16, 94, 122);\n\n\t_txtOptions = new Text(114, 9, 206, 82);\n\t_btnLetterbox = new ToggleTextButton(104, 16, 206, 92);\n\t_btnLockMouse = new ToggleTextButton(104, 16, 206, 110);\n\t_btnRootWindowedMode = new ToggleTextButton(104, 16, 206, 128);\n\n\t// Get available fullscreen modes\n\t_res = SDL_ListModes(NULL, SDL_FULLSCREEN);\n\tif (_res != (SDL_Rect**)-1 && _res != (SDL_Rect**)0)\n\t{\n\t\tint i;\n\t\t_resCurrent = -1;\n\t\tfor (i = 0; _res[i]; ++i)\n\t\t{\n\t\t\tif (_resCurrent == -1 &&\n\t\t\t\t((_res[i]->w == Options::displayWidth && _res[i]->h <= Options::displayHeight) || _res[i]->w < Options::displayWidth))\n\t\t\t{\n\t\t\t\t_resCurrent = i;\n\t\t\t}\n\t\t}\n\t\t_resAmount = i;\n\t}\n\telse\n\t{\n\t\t_resCurrent = -1;\n\t\t_resAmount = 0;\n\t\t_btnDisplayResolutionDown->setVisible(false);\n\t\t_btnDisplayResolutionUp->setVisible(false);\n\t\tLog(LOG_WARNING) << \"Couldn't get display resolutions\";\n\t}\n\n\tadd(_displaySurface);\n\tadd(_txtDisplayResolution, \"text\", \"videoMenu\");\n\tadd(_txtDisplayWidth, \"resolution\", \"videoMenu\");\n\tadd(_txtDisplayX, \"resolution\", \"videoMenu\");\n\tadd(_txtDisplayHeight, \"resolution\", \"videoMenu\");\n\tadd(_btnDisplayResolutionUp, \"button\", \"videoMenu\");\n\tadd(_btnDisplayResolutionDown, \"button\", \"videoMenu\");\n\n\tadd(_txtLanguage, \"text\", \"videoMenu\");\n\tadd(_txtFilter, \"text\", \"videoMenu\");\n\n\tadd(_txtMode, \"text\", \"videoMenu\");\n\n\tadd(_txtOptions, \"text\", \"videoMenu\");\n\tadd(_btnLetterbox, \"button\", \"videoMenu\");\n\tadd(_btnLockMouse, \"button\", \"videoMenu\");\n\tadd(_btnRootWindowedMode, \"button\", \"videoMenu\");\n\n\tadd(_cbxFilter, \"button\", \"videoMenu\");\n\tadd(_cbxDisplayMode, \"button\", \"videoMenu\");\n\n\tadd(_txtBattleScale, \"text\", \"videoMenu\");\n\tadd(_cbxBattleScale, \"button\", \"videoMenu\");\n\n\tadd(_txtGeoScale, \"text\", \"videoMenu\");\n\tadd(_cbxGeoScale, \"button\", \"videoMenu\");\n\n\tadd(_cbxLanguage, \"button\", \"videoMenu\");\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\t_txtDisplayResolution->setText(tr(\"STR_DISPLAY_RESOLUTION\"));\n\n\t_displaySurface->setTooltip(\"STR_DISPLAY_RESOLUTION_DESC\");\n\t_displaySurface->onMouseIn((ActionHandler)&OptionsVideoState::txtTooltipIn);\n\t_displaySurface->onMouseOut((ActionHandler)&OptionsVideoState::txtTooltipOut);\n\n\t_txtDisplayWidth->setAlign(ALIGN_CENTER);\n\t_txtDisplayWidth->setBig();\n\t_txtDisplayWidth->setConstraint(TEC_NUMERIC_POSITIVE);\n\t_txtDisplayWidth->onChange((ActionHandler)&OptionsVideoState::txtDisplayWidthChange);\n\n\t_txtDisplayX->setAlign(ALIGN_CENTER);\n\t_txtDisplayX->setBig();\n\t_txtDisplayX->setText(\"x\");\n\n\t_txtDisplayHeight->setAlign(ALIGN_CENTER);\n\t_txtDisplayHeight->setBig();\n\t_txtDisplayHeight->setConstraint(TEC_NUMERIC_POSITIVE);\n\t_txtDisplayHeight->onChange((ActionHandler)&OptionsVideoState::txtDisplayHeightChange);\n\n\tstd::ostringstream ssW, ssH;\n\tssW << Options::displayWidth;\n\tssH << Options::displayHeight;\n\t_txtDisplayWidth->setText(ssW.str());\n\t_txtDisplayHeight->setText(ssH.str());\n\n\t_btnDisplayResolutionUp->onMouseClick((ActionHandler)&OptionsVideoState::btnDisplayResolutionUpClick);\n\t_btnDisplayResolutionDown->onMouseClick((ActionHandler)&OptionsVideoState::btnDisplayResolutionDownClick);\n\n\t_txtMode->setText(tr(\"STR_DISPLAY_MODE\"));\n\n\t_txtOptions->setText(tr(\"STR_DISPLAY_OPTIONS\"));\n\n\t_btnLetterbox->setText(tr(\"STR_LETTERBOXED\"));\n\t_btnLetterbox->setPressed(Options::keepAspectRatio);\n\t_btnLetterbox->onMouseClick((ActionHandler)&OptionsVideoState::btnLetterboxClick);\n\t_btnLetterbox->setTooltip(\"STR_LETTERBOXED_DESC\");\n\t_btnLetterbox->onMouseIn((ActionHandler)&OptionsVideoState::txtTooltipIn);\n\t_btnLetterbox->onMouseOut((ActionHandler)&OptionsVideoState::txtTooltipOut);\n\n\t_btnLockMouse->setText(tr(\"STR_LOCK_MOUSE\"));\n\t_btnLockMouse->setPressed(Options::captureMouse == SDL_GRAB_ON);\n\t_btnLockMouse->onMouseClick((ActionHandler)&OptionsVideoState::btnLockMouseClick);\n\t_btnLockMouse->setTooltip(\"STR_LOCK_MOUSE_DESC\");\n\t_btnLockMouse->onMouseIn((ActionHandler)&OptionsVideoState::txtTooltipIn);\n\t_btnLockMouse->onMouseOut((ActionHandler)&OptionsVideoState::txtTooltipOut);\n\n\t_btnRootWindowedMode->setText(tr(\"STR_FIXED_WINDOW_POSITION\"));\n\t_btnRootWindowedMode->setPressed(Options::rootWindowedMode);\n\t_btnRootWindowedMode->onMouseClick((ActionHandler)&OptionsVideoState::btnRootWindowedModeClick);\n\t_btnRootWindowedMode->setTooltip(\"STR_FIXED_WINDOW_POSITION_DESC\");\n\t_btnRootWindowedMode->onMouseIn((ActionHandler)&OptionsVideoState::txtTooltipIn);\n\t_btnRootWindowedMode->onMouseOut((ActionHandler)&OptionsVideoState::txtTooltipOut);\n\n\t_txtLanguage->setText(tr(\"STR_DISPLAY_LANGUAGE\"));\n\n\tstd::vector<std::string> names;\n\tLanguage::getList(_langs, names);\n\t_cbxLanguage->setOptions(names);\n\tfor (size_t i = 0; i < names.size(); ++i)\n\t{\n\t\tif (_langs[i] == Options::language)\n\t\t{\n\t\t\t_cbxLanguage->setSelected(i);\n\t\t\tbreak;\n\t\t}\n\t}\n\t_cbxLanguage->onChange((ActionHandler)&OptionsVideoState::cbxLanguageChange);\n\t_cbxLanguage->setTooltip(\"STR_DISPLAY_LANGUAGE_DESC\");\n\t_cbxLanguage->onMouseIn((ActionHandler)&OptionsVideoState::txtTooltipIn);\n\t_cbxLanguage->onMouseOut((ActionHandler)&OptionsVideoState::txtTooltipOut);\n\n\tstd::vector<std::string> filterNames;\n\tfilterNames.push_back(tr(\"STR_DISABLED\"));\n\tfilterNames.push_back(\"Scale\");\n\tfilterNames.push_back(\"HQx\");\n\tfilterNames.push_back(\"xBRZ\");\n\t_filters.push_back(\"\");\n\t_filters.push_back(\"\");\n\t_filters.push_back(\"\");\n\t_filters.push_back(\"\");\n\n#ifndef __NO_OPENGL\n\tstd::vector<std::string> filters;\n\tfor (const auto& f : FileMap::filterFiles(FileMap::getVFolderContents(GL_FOLDER), GL_EXT)) { filters.push_back(f); }\n\tstd::sort(filters.begin(), filters.end(), Unicode::naturalCompare);\n\tfor (const auto& file : filters)\n\t{\n\t\tstd::string path = GL_FOLDER + file;\n\t\tstd::string name = file.substr(0, file.length() - GL_EXT.length() - 1) + GL_STRING;\n\t\tfilterNames.push_back(ucWords(name));\n\t\t_filters.push_back(path);\n\t}\n#endif\n\n\tsize_t selFilter = 0;\n\tif (Screen::useOpenGL())\n\t{\n#ifndef __NO_OPENGL\n\t\tstd::string path = Options::useOpenGLShader;\n\t\tfor (size_t i = 0; i < _filters.size(); ++i)\n\t\t{\n\t\t\tif (_filters[i] == path)\n\t\t\t{\n\t\t\t\tselFilter = i;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n#endif\n\t}\n\telse if (Options::useScaleFilter)\n\t{\n\t\tselFilter = 1;\n\t}\n\telse if (Options::useHQXFilter)\n\t{\n\t\tselFilter = 2;\n\t}\n\telse if (Options::useXBRZFilter)\n\t{\n\t\tselFilter = 3;\n\t}\n\n\t_txtFilter->setText(tr(\"STR_DISPLAY_FILTER\"));\n\n\t_cbxFilter->setOptions(filterNames);\n\t_cbxFilter->setSelected(selFilter);\n\t_cbxFilter->onChange((ActionHandler)&OptionsVideoState::cbxFilterChange);\n\t_cbxFilter->setTooltip(\"STR_DISPLAY_FILTER_DESC\");\n\t_cbxFilter->onMouseIn((ActionHandler)&OptionsVideoState::txtTooltipIn);\n\t_cbxFilter->onMouseOut((ActionHandler)&OptionsVideoState::txtTooltipOut);\n\n\n\tstd::vector<std::string> displayModes;\n\tdisplayModes.push_back(tr(\"STR_WINDOWED\"));\n\tdisplayModes.push_back(tr(\"STR_FULLSCREEN\"));\n\tdisplayModes.push_back(tr(\"STR_BORDERLESS\"));\n\tdisplayModes.push_back(tr(\"STR_RESIZABLE\"));\n\n\tint displayMode = 0;\n\tif (Options::fullscreen)\n\t{\n\t\tdisplayMode = 1;\n\t}\n\telse if (Options::borderless)\n\t{\n\t\tdisplayMode = 2;\n\t}\n\telse if (Options::allowResize)\n\t{\n\t\tdisplayMode = 3;\n\t}\n\n\t_cbxDisplayMode->setOptions(displayModes);\n\t_cbxDisplayMode->setSelected(displayMode);\n\t_cbxDisplayMode->onChange((ActionHandler)&OptionsVideoState::updateDisplayMode);\n\t_cbxDisplayMode->setTooltip(\"STR_DISPLAY_MODE_DESC\");\n\t_cbxDisplayMode->onMouseIn((ActionHandler)&OptionsVideoState::txtTooltipIn);\n\t_cbxDisplayMode->onMouseOut((ActionHandler)&OptionsVideoState::txtTooltipOut);\n\n\t_txtGeoScale->setText(tr(\"STR_GEOSCAPE_SCALE\"));\n\n\tstd::vector<std::string> scales;\n\tscales.push_back(\"1x\"); // was 5 -> is 0\n\tscales.push_back(\"2x\"); // was 4 -> is 1\n\tscales.push_back(\"3x\"); // was 3 -> is 2\n\tscales.push_back(\"4x\"); // was 6 -> is 3\n\tscales.push_back(\"5x\"); // was 7 -> is 4\n\tscales.push_back(\"6x\"); // was 8 -> is 5\n\tscales.push_back(\"320x200\"); // was 0 -> is 6\n\tscales.push_back(\"480x300\"); // was 1 -> is 7\n\tscales.push_back(\"640x400\"); // was 2 -> is 8\n\tscales.push_back(\"8x\");  // new 9\n\tscales.push_back(\"10x\"); // new 10\n\n\t_scales.push_back(6); // 0\n\t_scales.push_back(7); // 1\n\t_scales.push_back(8); // 2\n\t_scales.push_back(2); // 3\n\t_scales.push_back(1); // 4\n\t_scales.push_back(0); // 5\n\t_scales.push_back(3); // 6\n\t_scales.push_back(4); // 7\n\t_scales.push_back(5); // 8\n\t_scales.push_back(9);\n\t_scales.push_back(10);\n\n\t_reverseScales.push_back(5); // 0\n\t_reverseScales.push_back(4); // 1\n\t_reverseScales.push_back(3); // 2\n\t_reverseScales.push_back(6); // 3\n\t_reverseScales.push_back(7); // 4\n\t_reverseScales.push_back(8); // 5\n\t_reverseScales.push_back(0); // 6\n\t_reverseScales.push_back(1); // 7\n\t_reverseScales.push_back(2); // 8\n\t_reverseScales.push_back(9);\n\t_reverseScales.push_back(10);\n\n\tif (Options::geoscapeScale < 0 || Options::geoscapeScale > 10) Options::geoscapeScale = 0;\n\tif (Options::battlescapeScale < 0 || Options::battlescapeScale > 10) Options::battlescapeScale = 0;\n\n\t_cbxGeoScale->setOptions(scales);\n\t_cbxGeoScale->setSelected(_scales[Options::geoscapeScale]);\n\t_cbxGeoScale->onChange((ActionHandler)&OptionsVideoState::updateGeoscapeScale);\n\t_cbxGeoScale->setTooltip(\"STR_GEOSCAPESCALE_SCALE_DESC\");\n\t_cbxGeoScale->onMouseIn((ActionHandler)&OptionsVideoState::txtTooltipIn);\n\t_cbxGeoScale->onMouseOut((ActionHandler)&OptionsVideoState::txtTooltipOut);\n\n\t_txtBattleScale->setText(tr(\"STR_BATTLESCAPE_SCALE\"));\n\n\t_cbxBattleScale->setOptions(scales);\n\t_cbxBattleScale->setSelected(_scales[Options::battlescapeScale]);\n\t_cbxBattleScale->onChange((ActionHandler)&OptionsVideoState::updateBattlescapeScale);\n\t_cbxBattleScale->setTooltip(\"STR_BATTLESCAPE_SCALE_DESC\");\n\t_cbxBattleScale->onMouseIn((ActionHandler)&OptionsVideoState::txtTooltipIn);\n\t_cbxBattleScale->onMouseOut((ActionHandler)&OptionsVideoState::txtTooltipOut);\n\n}\n\n/**\n *\n */\nOptionsVideoState::~OptionsVideoState()\n{\n\n}\n\n/**\n * Uppercases all the words in a string.\n * @param str Source string.\n * @return Destination string.\n */\nstd::string OptionsVideoState::ucWords(std::string str)\n{\n\tfor (size_t i = 0; i < str.length(); ++i)\n\t{\n\t\tif (i == 0)\n\t\t\tstr[0] = toupper(str[0]);\n\t\telse if (str[i] == ' ' || str[i] == '-' || str[i] == '_')\n\t\t{\n\t\t\tstr[i] = ' ';\n\t\t\tif (str.length() > i + 1)\n\t\t\t\tstr[i + 1] = toupper(str[i + 1]);\n\t\t}\n\t}\n\treturn str;\n}\n\n/**\n * Selects a bigger display resolution.\n * @param action Pointer to an action.\n */\nvoid OptionsVideoState::btnDisplayResolutionUpClick(Action *)\n{\n\tif (_resAmount == 0)\n\t\treturn;\n\tif (_resCurrent <= 0)\n\t{\n\t\t_resCurrent = _resAmount-1;\n\t}\n\telse\n\t{\n\t\t_resCurrent--;\n\t}\n\tupdateDisplayResolution();\n}\n\n/**\n * Selects a smaller display resolution.\n * @param action Pointer to an action.\n */\nvoid OptionsVideoState::btnDisplayResolutionDownClick(Action *)\n{\n\tif (_resAmount == 0)\n\t\treturn;\n\tif (_resCurrent >= _resAmount-1)\n\t{\n\t\t_resCurrent = 0;\n\t}\n\telse\n\t{\n\t\t_resCurrent++;\n\t}\n\tupdateDisplayResolution();\n}\n\n/**\n * Updates the display resolution based on the selection.\n */\nvoid OptionsVideoState::updateDisplayResolution()\n{\n\tstd::ostringstream ssW, ssH;\n\tssW << (int)_res[_resCurrent]->w;\n\tssH << (int)_res[_resCurrent]->h;\n\t_txtDisplayWidth->setText(ssW.str());\n\t_txtDisplayHeight->setText(ssH.str());\n\n\tOptions::newDisplayWidth = _res[_resCurrent]->w;\n\tOptions::newDisplayHeight = _res[_resCurrent]->h;\n}\n\n/**\n * Changes the Display Width option.\n * @param action Pointer to an action.\n */\nvoid OptionsVideoState::txtDisplayWidthChange(Action *)\n{\n\tstd::stringstream ss;\n\tint width = 0;\n\tss << std::dec << _txtDisplayWidth->getText();\n\tss >> std::dec >> width;\n\tOptions::newDisplayWidth = width;\n\t// Update resolution mode\n\tif (_res != (SDL_Rect**)-1 && _res != (SDL_Rect**)0)\n\t{\n\t\tint i;\n\t\t_resCurrent = -1;\n\t\tfor (i = 0; _res[i]; ++i)\n\t\t{\n\t\t\tif (_resCurrent == -1 &&\n\t\t\t\t((_res[i]->w == Options::newDisplayWidth && _res[i]->h <= Options::newDisplayHeight) || _res[i]->w < Options::newDisplayWidth))\n\t\t\t{\n\t\t\t\t_resCurrent = i;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Changes the Display Height option.\n * @param action Pointer to an action.\n */\nvoid OptionsVideoState::txtDisplayHeightChange(Action *)\n{\n\tstd::stringstream ss;\n\tint height = 0;\n\tss << std::dec << _txtDisplayHeight->getText();\n\tss >> std::dec >> height;\n\tOptions::newDisplayHeight = height;\n\t// Update resolution mode\n\tif (_res != (SDL_Rect**)-1 && _res != (SDL_Rect**)0)\n\t{\n\t\tint i;\n\t\t_resCurrent = -1;\n\t\tfor (i = 0; _res[i]; ++i)\n\t\t{\n\t\t\tif (_resCurrent == -1 &&\n\t\t\t\t((_res[i]->w == Options::newDisplayWidth && _res[i]->h <= Options::newDisplayHeight) || _res[i]->w < Options::newDisplayWidth))\n\t\t\t{\n\t\t\t\t_resCurrent = i;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Changes the Language option.\n * @param action Pointer to an action.\n */\nvoid OptionsVideoState::cbxLanguageChange(Action *)\n{\n\tOptions::language = _langs[_cbxLanguage->getSelected()];\n}\n\n/**\n * Changes the Filter options.\n * @param action Pointer to an action.\n */\nvoid OptionsVideoState::cbxFilterChange(Action *)\n{\n\tswitch (_cbxFilter->getSelected())\n\t{\n\tcase 0:\n\t\tOptions::newOpenGL = false;\n\t\tOptions::newScaleFilter = false;\n\t\tOptions::newHQXFilter = false;\n\t\tOptions::newXBRZFilter = false;\n\t\tbreak;\n\tcase 1:\n\t\tOptions::newOpenGL = false;\n\t\tOptions::newScaleFilter = true;\n\t\tOptions::newHQXFilter = false;\n\t\tOptions::newXBRZFilter = false;\n\t\tbreak;\n\tcase 2:\n\t\tOptions::newOpenGL = false;\n\t\tOptions::newScaleFilter = false;\n\t\tOptions::newHQXFilter = true;\n\t\tOptions::newXBRZFilter = false;\n\t\tbreak;\n\tcase 3:\n\t\tOptions::newOpenGL = false;\n\t\tOptions::newScaleFilter = false;\n\t\tOptions::newHQXFilter = false;\n\t\tOptions::newXBRZFilter = true;\n\t\tbreak;\n\tdefault:\n\t\tOptions::newOpenGL = true;\n\t\tOptions::newScaleFilter = false;\n\t\tOptions::newHQXFilter = false;\n\t\tOptions::newXBRZFilter = false;\n\t\tOptions::newOpenGLShader = _filters[_cbxFilter->getSelected()];\n\t\tbreak;\n\t}\n}\n\n/**\n * Changes the Display Mode options.\n * @param action Pointer to an action.\n */\nvoid OptionsVideoState::updateDisplayMode(Action *)\n{\n\tswitch(_cbxDisplayMode->getSelected())\n\t{\n\tcase 0:\n\t\tOptions::newFullscreen = false;\n\t\tOptions::newBorderless = false;\n\t\tOptions::newAllowResize = false;\n\t\tbreak;\n\tcase 1:\n\t\tOptions::newFullscreen = true;\n\t\tOptions::newBorderless = false;\n\t\tOptions::newAllowResize = false;\n\t\tbreak;\n\tcase 2:\n\t\tOptions::newFullscreen = false;\n\t\tOptions::newBorderless = true;\n\t\tOptions::newAllowResize = false;\n\t\tbreak;\n\tcase 3:\n\t\tOptions::newFullscreen = false;\n\t\tOptions::newBorderless = false;\n\t\tOptions::newAllowResize = true;\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n}\n\n/**\n * Changes the Letterboxing option.\n * @param action Pointer to an action.\n */\nvoid OptionsVideoState::btnLetterboxClick(Action *)\n{\n\tOptions::keepAspectRatio = _btnLetterbox->getPressed();\n}\n\n/**\n * Changes the Lock Mouse option.\n * @param action Pointer to an action.\n */\nvoid OptionsVideoState::btnLockMouseClick(Action *)\n{\n\tOptions::captureMouse = (SDL_GrabMode)_btnLockMouse->getPressed();\n\tSDL_WM_GrabInput(Options::captureMouse);\n}\n\n/**\n * Ask user where he wants to root screen.\n * @param action Pointer to an action.\n */\nvoid OptionsVideoState::btnRootWindowedModeClick(Action *)\n{\n\tif (_btnRootWindowedMode->getPressed())\n\t{\n\t\t_game->pushState(new SetWindowedRootState(_origin, this));\n\t}\n\telse\n\t{\n\t\tOptions::newRootWindowedMode = false;\n\t}\n}\n\n/**\n * Changes the geoscape scale.\n * @param action Pointer to an action.\n */\nvoid OptionsVideoState::updateGeoscapeScale(Action *)\n{\n\tOptions::newGeoscapeScale = _reverseScales[_cbxGeoScale->getSelected()];\n}\n\n/**\n * Updates the Battlescape scale.\n * @param action Pointer to an action.\n */\nvoid OptionsVideoState::updateBattlescapeScale(Action *)\n{\n\tOptions::newBattlescapeScale = _reverseScales[_cbxBattleScale->getSelected()];\n}\n\n/**\n * Updates the scale.\n * @param dX delta of X;\n * @param dY delta of Y;\n */\nvoid OptionsVideoState::resize(int &dX, int &dY)\n{\n\tOptionsBaseState::resize(dX, dY);\n\tstd::ostringstream ss;\n\tss << Options::displayWidth;\n\t_txtDisplayWidth->setText(ss.str());\n\tss.str(\"\");\n\tss << Options::displayHeight;\n\t_txtDisplayHeight->setText(ss.str());\n}\n\n/**\n * Takes care of any events from the core game engine.\n * @param action Pointer to an action.\n */\nvoid OptionsVideoState::handle(Action *action)\n{\n\tState::handle(action);\n\tif (action->getDetails()->type == SDL_KEYDOWN && action->getDetails()->key.keysym.sym == SDLK_g && _game->isCtrlPressed())\n\t{\n\t\t_btnLockMouse->setPressed(Options::captureMouse == SDL_GRAB_ON);\n\t}\n}\n\n/**\n * Unpresses Fixed Borderless Pos button\n */\nvoid OptionsVideoState::unpressRootWindowedMode()\n{\n\t_btnRootWindowedMode->setPressed(false);\n}\n\n}\n"
  },
  {
    "path": "src/Menu/OptionsVideoState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include \"OptionsBaseState.h\"\n#include <SDL.h>\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass ToggleTextButton;\nclass Text;\nclass TextEdit;\nclass ArrowButton;\nclass ComboBox;\nclass InteractiveSurface;\n\n/**\n * Screen that lets the user configure various\n * Video options.\n */\nclass OptionsVideoState : public OptionsBaseState\n{\nprivate:\n\tstatic const std::string GL_EXT, GL_FOLDER, GL_STRING;\n\n\tInteractiveSurface *_displaySurface;\n\tText *_txtDisplayResolution, *_txtDisplayX;\n\tTextEdit *_txtDisplayWidth, *_txtDisplayHeight;\n\tArrowButton *_btnDisplayResolutionUp, *_btnDisplayResolutionDown;\n\n\tText *_txtLanguage, *_txtFilter, *_txtGeoScale, *_txtBattleScale;\n\tComboBox *_cbxLanguage, *_cbxFilter, *_cbxDisplayMode, *_cbxGeoScale, *_cbxBattleScale;\n\tText *_txtMode;\n\tText *_txtOptions;\n\tToggleTextButton *_btnLetterbox, *_btnLockMouse, *_btnRootWindowedMode;\n\n\tSDL_Rect** _res;\n\tint _resAmount, _resCurrent;\n\tstd::vector<std::string> _langs, _filters;\n\tstd::vector<int> _scales, _reverseScales;\n\n\tstd::string ucWords(std::string str);\n\tvoid updateDisplayResolution();\npublic:\n\t/// Creates the Options state.\n\tOptionsVideoState(OptionsOrigin origin);\n\t/// Cleans up the Options state.\n\t~OptionsVideoState();\n\t/// Handler for clicking the Next Resolution button.\n\tvoid btnDisplayResolutionUpClick(Action *action);\n\t/// Handler for clicking the Previous Resolution button.\n\tvoid btnDisplayResolutionDownClick(Action *action);\n\t/// Handler for changing the Display Width text.\n\tvoid txtDisplayWidthChange(Action *action);\n\t/// Handler for changing the Display Height text.\n\tvoid txtDisplayHeightChange(Action *action);\n\t/// Handler for changing the Language combobox.\n\tvoid cbxLanguageChange(Action *action);\n\t/// Handler for changing the Filter combobox.\n\tvoid cbxFilterChange(Action *action);\n\t/// Handler for clicking the Display Mode combobox.\n\tvoid updateDisplayMode(Action *action);\n\t/// Handler for clicking the Letterboxed button.\n\tvoid btnLetterboxClick(Action *action);\n\t/// Handler for clicking the Lock Mouse button.\n\tvoid btnLockMouseClick(Action *action);\n\t/// Handler for clicking the Root Window Pos button.\n\tvoid btnRootWindowedModeClick(Action *action);\n\t/// Handler for updating the selected battlescape scale.\n\tvoid updateBattlescapeScale(Action *action);\n\t/// Handler for updating the selected geoscape scale.\n\tvoid updateGeoscapeScale(Action *action);\n\t/// Update the resolution settings, we just resized the window.\n\tvoid resize(int &, int &) override;\n\t/// Handles keypresses.\n\tvoid handle(Action *action) override;\n\t/// Unpresses Root Window Pos button.\n\tvoid unpressRootWindowedMode();\n};\n\n}\n"
  },
  {
    "path": "src/Menu/PauseState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"PauseState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"AbandonGameState.h\"\n#include \"ListLoadState.h\"\n#include \"ListSaveState.h\"\n#include \"../Engine/Options.h\"\n#include \"OptionsVideoState.h\"\n#include \"OptionsGeoscapeState.h\"\n#include \"OptionsBattlescapeState.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"../Battlescape/BattlescapeGame.h\"\n#include \"../version.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Pause window.\n * @param game Pointer to the core game.\n * @param origin Game section that originated this state.\n */\nPauseState::PauseState(OptionsOrigin origin) : _origin(origin)\n{\n\t_screen = false;\n\n\tint x;\n\tif (_origin == OPT_GEOSCAPE)\n\t{\n\t\tx = 20;\n\t}\n\telse\n\t{\n\t\tx = 52;\n\t}\n\n\t// Create objects\n\t_window = new Window(this, 216, 160, x, 20, POPUP_BOTH);\n\t_btnLoad = new TextButton(180, 18, x+18, 52);\n\t_btnSave = new TextButton(180, 18, x+18, 74);\n\t_btnAbandon = new TextButton(180, 18, x+18, 96);\n\t_btnOptions = new TextButton(180, 18, x+18, 122);\n\t_btnCancel = new TextButton(180, 18, x+18, 150);\n\t_txtTitle = new Text(206, 17, x+5, 32);\n\t_txtVersion = new Text(216, 9, x, 11);\n\n\t// Set palette\n\tsetInterface(\"pauseMenu\", false, _game->getSavedGame() ? _game->getSavedGame()->getSavedBattle() : 0);\n\n\tadd(_window, \"window\", \"pauseMenu\");\n\tadd(_btnLoad, \"button\", \"pauseMenu\");\n\tadd(_btnSave, \"button\", \"pauseMenu\");\n\tadd(_btnAbandon, \"button\", \"pauseMenu\");\n\tadd(_btnOptions, \"button\", \"pauseMenu\");\n\tadd(_btnCancel, \"button\", \"pauseMenu\");\n\tadd(_txtTitle, \"text\", \"pauseMenu\");\n\tadd(_txtVersion, \"text\", \"pauseMenu\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"pauseMenu\");\n\n\t_btnLoad->setText(tr(\"STR_LOAD_GAME\"));\n\t_btnLoad->onMouseClick((ActionHandler)&PauseState::btnLoadClick);\n\n\t_btnSave->setText(tr(\"STR_SAVE_GAME\"));\n\t_btnSave->onMouseClick((ActionHandler)&PauseState::btnSaveClick);\n\n\t_btnAbandon->setText(tr(\"STR_ABANDON_GAME\"));\n\t_btnAbandon->onMouseClick((ActionHandler)&PauseState::btnAbandonClick);\n\n\t_btnOptions->setText(tr(\"STR_GAME_OPTIONS\"));\n\t_btnOptions->onMouseClick((ActionHandler)&PauseState::btnOptionsClick);\n\n\t_btnCancel->setText(tr(\"STR_CANCEL_UC\"));\n\t_btnCancel->onMouseClick((ActionHandler)&PauseState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&PauseState::btnCancelClick, Options::keyCancel);\n\tif (origin == OPT_GEOSCAPE)\n\t{\n\t\t_btnCancel->onKeyboardPress((ActionHandler)&PauseState::btnCancelClick, Options::keyGeoOptions);\n\t}\n\telse if (origin == OPT_BATTLESCAPE)\n\t{\n\t\t_btnCancel->onKeyboardPress((ActionHandler)&PauseState::btnCancelClick, Options::keyBattleOptions);\n\t\tif (!_game->getSavedGame()->getSavedBattle()->getBattleGame()->getStates().empty())\n\t\t{\n\t\t\t_btnOptions->setVisible(false);\n\t\t}\n\t}\n\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setBig();\n\t_txtTitle->setText(tr(\"STR_OPTIONS_UC\"));\n\n\tstd::ostringstream title;\n\ttitle << \"OpenXcom \" << OPENXCOM_VERSION_SHORT;\n\t_txtVersion->setText(title.str());\n\t_txtVersion->setAlign(ALIGN_CENTER);\n\n\tif (_origin == OPT_BATTLESCAPE)\n\t{\n\t\tapplyBattlescapeTheme(\"pauseMenu\");\n\t}\n\n\tif (_game->getSavedGame()->isIronman())\n\t{\n\t\t_btnLoad->setVisible(false);\n\t\t_btnSave->setVisible(false);\n\t\t_btnAbandon->setText(tr(\"STR_SAVE_AND_ABANDON_GAME\"));\n\t}\n\n\t// ENOUGH! No save corruption when trying to save/exit mid-action (e.g. during alien turn)\n\tif (origin == OPT_BATTLESCAPE)\n\t{\n\t\tbool playerTurn = _game->getSavedGame()->getSavedBattle()->getSide() == FACTION_PLAYER;\n\t\tbool debugMode = _game->getSavedGame()->getSavedBattle()->getDebugMode();\n\t\tbool busy = !_game->getSavedGame()->getSavedBattle()->getBattleGame()->getStates().empty();\n\n\t\tif ((!playerTurn && !debugMode) || busy)\n\t\t{\n\t\t\t_btnSave->setVisible(false); // non-ironman + ironman\n\n\t\t\tif (_game->getSavedGame()->isIronman())\n\t\t\t{\n\t\t\t\t_btnAbandon->setVisible(false); // ironman only\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n *\n */\nPauseState::~PauseState()\n{\n\n}\n\n/**\n * Opens the Load Game screen.\n * @param action Pointer to an action.\n */\nvoid PauseState::btnLoadClick(Action *)\n{\n\t_game->pushState(new ListLoadState(_origin));\n}\n\n/**\n * Opens the Save Game screen.\n * @param action Pointer to an action.\n */\nvoid PauseState::btnSaveClick(Action *)\n{\n\t_game->pushState(new ListSaveState(_origin));\n}\n\n/**\n * Opens the Game Options screen.\n * @param action Pointer to an action.\n */\nvoid PauseState::btnOptionsClick(Action *)\n{\n\tOptions::backupDisplay();\n\tif (_origin == OPT_GEOSCAPE)\n\t{\n\t\t_game->pushState(new OptionsGeoscapeState(_origin));\n\t}\n\telse if (_origin == OPT_BATTLESCAPE)\n\t{\n\t\t_game->pushState(new OptionsBattlescapeState(_origin));\n\t}\n\telse\n\t{\n\t\t_game->pushState(new OptionsVideoState(_origin));\n\t}\n}\n\n/**\n * Opens the Abandon Game window.\n * @param action Pointer to an action.\n */\nvoid PauseState::btnAbandonClick(Action *)\n{\n\t_game->pushState(new AbandonGameState(_origin));\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid PauseState::btnCancelClick(Action *)\n{\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Menu/PauseState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include \"OptionsBaseState.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\n\n/**\n * Options window shown for loading/saving/quitting the game.\n * Not to be confused with the Game Options window\n * for changing game settings during runtime.\n */\nclass PauseState : public State\n{\nprivate:\n\tOptionsOrigin _origin;\n\tTextButton *_btnLoad, *_btnSave, *_btnAbandon, *_btnOptions, *_btnCancel;\n\tWindow *_window;\n\tText *_txtTitle, *_txtVersion;\npublic:\n\t/// Creates the Pause state.\n\tPauseState(OptionsOrigin origin);\n\t/// Cleans up the Pause state.\n\t~PauseState();\n\t/// Handler for clicking the Load Game button.\n\tvoid btnLoadClick(Action *action);\n\t/// Handler for clicking the Save Game button.\n\tvoid btnSaveClick(Action *action);\n\t/// Handler for clicking the Abandon Game button.\n\tvoid btnAbandonClick(Action *action);\n\t/// Handler for clicking the Game Options button.\n\tvoid btnOptionsClick(Action *action);\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Menu/SaveGameState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"SaveGameState.h\"\n#include <sstream>\n#include \"../Engine/Logger.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Exception.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Screen.h\"\n#include \"../Engine/CrossPlatform.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Interface/Text.h\"\n#include \"ErrorMessageState.h\"\n#include \"MainMenuState.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleInterface.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Save Game screen.\n * @param game Pointer to the core game.\n * @param origin Game section that originated this state.\n * @param filename Name of the save file without extension.\n * @param palette Parent state palette.\n */\nSaveGameState::SaveGameState(OptionsOrigin origin, const std::string &filename, SDL_Color *palette) : _firstRun(0), _origin(origin), _filename(filename), _type(SAVE_DEFAULT)\n{\n\tbuildUi(palette);\n}\n\n/**\n * Initializes all the elements in the Save Game screen.\n * @param game Pointer to the core game.\n * @param origin Game section that originated this state.\n * @param type Type of auto-save being used.\n * @param palette Parent state palette.\n */\nSaveGameState::SaveGameState(OptionsOrigin origin, SaveType type, SDL_Color *palette, int currentTurn) : _firstRun(0), _origin(origin), _type(type)\n{\n\tswitch (type)\n\t{\n\tcase SAVE_QUICK:\n\t\t_filename = SavedGame::QUICKSAVE;\n\t\tbreak;\n\tcase SAVE_INSTA:\n\t\t_filename = \"Instasave_\" + CrossPlatform::sanitizeFilename(CrossPlatform::now()) + \".sav\";\n\t\tbreak;\n\tcase SAVE_AUTO_GEOSCAPE:\n\t\tif (Options::oxceGeoAutosaveFrequency > 0 && Options::oxceGeoAutosaveSlots >= 2 && Options::oxceGeoAutosaveSlots <= 10 && currentTurn > 0)\n\t\t{\n\t\t\t// multi-slot autosave\n\t\t\tint slotIndex = (currentTurn / Options::oxceGeoAutosaveFrequency) % Options::oxceGeoAutosaveSlots;\n\t\t\t_filename = \"_\" + std::to_string(slotIndex) + SavedGame::AUTOSAVE_GEOSCAPE;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// classic autosave\n\t\t\t_filename = SavedGame::AUTOSAVE_GEOSCAPE;\n\t\t}\n\t\tbreak;\n\tcase SAVE_AUTO_BATTLESCAPE:\n\t\tif (currentTurn > 0 && Options::autosaveSlots >= 2 && Options::autosaveSlots <= 10)\n\t\t{\n\t\t\t// multi-slot autosave\n\t\t\tint slotIndex = (currentTurn / Options::autosaveFrequency) % Options::autosaveSlots;\n\t\t\t_filename = \"_\" + std::to_string(slotIndex) + SavedGame::AUTOSAVE_BATTLESCAPE;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// classic autosave\n\t\t\t_filename = SavedGame::AUTOSAVE_BATTLESCAPE;\n\t\t}\n\t\tbreak;\n\tcase SAVE_IRONMAN:\n\tcase SAVE_IRONMAN_END:\n\t\t_filename = CrossPlatform::sanitizeFilename(_game->getSavedGame()->getName()) + \".sav\";\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n\n\tbuildUi(palette);\n}\n\n/**\n *\n */\nSaveGameState::~SaveGameState()\n{\n\n}\n\n/**\n * Builds the interface.\n * @param palette Parent state palette.\n */\nvoid SaveGameState::buildUi(SDL_Color *palette)\n{\n\t_screen = false;\n\n\t// Create objects\n\t_txtStatus = new Text(320, 17, 0, 92);\n\n\t// Set palette\n\tsetStatePalette(palette);\n\n\tif (_origin == OPT_BATTLESCAPE)\n\t{\n\t\tadd(_txtStatus, \"textLoad\", \"battlescape\");\n\t\t_txtStatus->setHighContrast(true);\n\t}\n\telse\n\t{\n\t\tadd(_txtStatus, \"textLoad\", \"geoscape\");\n\t}\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\t_txtStatus->setBig();\n\t_txtStatus->setAlign(ALIGN_CENTER);\n\t_txtStatus->setText(tr(\"STR_SAVING_GAME\"));\n\n}\n\n/**\n * Saves the current save.\n */\nvoid SaveGameState::think()\n{\n\tState::think();\n\t// Make sure it gets drawn properly\n\tif (_firstRun < 10)\n\t{\n\t\t_firstRun++;\n\t}\n\telse\n\t{\n\t\t_game->popState();\n\n\t\tswitch (_type)\n\t\t{\n\t\tcase SAVE_DEFAULT:\n\t\t\t// manual save, close the save screen\n\t\t\t_game->popState();\n\t\t\tif (!_game->getSavedGame()->isIronman())\n\t\t\t{\n\t\t\t\t// and pause screen too\n\t\t\t\t_game->popState();\n\t\t\t}\n\t\t\tbreak;\n\t\tcase SAVE_INSTA:\n\t\t\t// timestamp is visible already, no need to repeat it\n\t\t\t_game->getSavedGame()->setName(tr(\"STR_INSTA_SAVE\"));\n\t\t\tbreak;\n\t\tcase SAVE_QUICK:\n\t\tcase SAVE_AUTO_GEOSCAPE:\n\t\tcase SAVE_AUTO_BATTLESCAPE:\n\t\t\t// automatic save, give it a default name\n\t\t\t_game->getSavedGame()->setName(_filename);\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\n\t\t// Save the game\n\t\ttry\n\t\t{\n\t\t\tstd::string backup = _filename + \".bak\";\n\t\t\t_game->getSavedGame()->save(backup, _game->getMod());\n\t\t\tstd::string fullPath = Options::getMasterUserFolder() + _filename;\n\t\t\tstd::string bakPath = Options::getMasterUserFolder() + backup;\n\t\t\tif (!CrossPlatform::moveFile(bakPath, fullPath))\n\t\t\t{\n\t\t\t\tthrow Exception(\"Save backed up in \" + backup);\n\t\t\t}\n\n\t\t\tif (_type == SAVE_IRONMAN_END)\n\t\t\t{\n\t\t\t\tScreen::updateScale(Options::geoscapeScale, Options::baseXGeoscape, Options::baseYGeoscape, true);\n\t\t\t\t_game->getScreen()->resetDisplay(false);\n\n\t\t\t\t_game->setState(new MainMenuState);\n\t\t\t\t_game->setSavedGame(0);\n\t\t\t}\n\n\t\t\t// Clear the SDL event queue (i.e. ignore input from impatient users)\n\t\t\tSDL_Event e;\n\t\t\twhile (SDL_PollEvent(&e))\n\t\t\t{\n\t\t\t\t// do nothing\n\t\t\t}\n\t\t}\n\t\tcatch (Exception &e)\n\t\t{\n\t\t\terror(e.what());\n\t\t}\n\t\tcatch (YAML::Exception &e)\n\t\t{\n\t\t\terror(e.what());\n\t\t}\n\t}\n}\n\n/**\n * Pops up a window with an error message.\n * @param msg Error message.\n */\nvoid SaveGameState::error(const std::string &msg)\n{\n\tLog(LOG_ERROR) << msg;\n\tstd::ostringstream error;\n\terror << tr(\"STR_SAVE_UNSUCCESSFUL\") << Unicode::TOK_NL_SMALL << msg;\n\tif (_origin != OPT_BATTLESCAPE)\n\t\t_game->pushState(new ErrorMessageState(error.str(), _palette, _game->getMod()->getInterface(\"errorMessages\")->getElement(\"geoscapeColor\")->color, \"BACK01.SCR\", _game->getMod()->getInterface(\"errorMessages\")->getElement(\"geoscapePalette\")->color));\n\telse\n\t\t_game->pushState(new ErrorMessageState(error.str(), _palette, _game->getMod()->getInterface(\"errorMessages\")->getElement(\"battlescapeColor\")->color, \"TAC00.SCR\", _game->getMod()->getInterface(\"errorMessages\")->getElement(\"battlescapePalette\")->color));\n}\n\n}\n"
  },
  {
    "path": "src/Menu/SaveGameState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include <SDL.h>\n#include <string>\n#include \"OptionsBaseState.h\"\n#include \"../Savegame/SavedGame.h\"\n\nnamespace OpenXcom\n{\n\nclass Text;\n\n/**\n * Saves the current game, with an optional message.\n */\nclass SaveGameState : public State\n{\nprivate:\n\tint _firstRun;\n\tOptionsOrigin _origin;\n\tText *_txtStatus;\n\tstd::string _filename;\n\tSaveType _type;\npublic:\n\t/// Creates the Save Game state.\n\tSaveGameState(OptionsOrigin origin, const std::string &filename, SDL_Color *palette);\n\t/// Creates the Load Game state.\n\tSaveGameState(OptionsOrigin origin, SaveType type, SDL_Color *palette, int currentTurn = 0);\n\t/// Cleans up the Save Game state.\n\t~SaveGameState();\n\t/// Creates the interface.\n\tvoid buildUi(SDL_Color *palette);\n\t/// Saves the game.\n\tvoid think() override;\n\t/// Shows an error message.\n\tvoid error(const std::string &msg);\n};\n\n}\n"
  },
  {
    "path": "src/Menu/SetWindowedRootState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"SetWindowedRootState.h\"\n#include <sstream>\n#include \"../Interface/Window.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Engine/Game.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Interface/Text.h\"\n#include \"OptionsVideoState.h\"\n#include \"../Interface/TextEdit.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Asks user new coordinates screen.\n * @param game Pointer to the core game.\n * @param OptionsVideoState Options screen that originated this state.\n */\nSetWindowedRootState::SetWindowedRootState(OptionsOrigin origin, OptionsVideoState *optionsVideoState) : _origin(origin), _optionsVideoState(optionsVideoState)\n{\n\t_screen = false;\n\n\t// Create object\n\t_window = new Window(this, 216, 100, 52, 50, POPUP_BOTH);\n\t_txtTitle = new Text(206, 20, 57, 70);\n\t_txtWindowedModePositionX = new Text(160, 10, 25, 90);\n\t_txtWindowedModePositionY = new Text(160, 10, 25, 100);\n\t_btnOk = new TextButton(50, 20, 70, 120);\n\t_btnCancel = new TextButton(50, 20, 200, 120);\n\t_edtWindowedModePositionX = new TextEdit(this, 40, 10, 190, 90);\n\t_edtWindowedModePositionY = new TextEdit(this, 40, 10, 190, 100);\n\n\t// Set palette\n\tsetInterface(\"optionsMenu\", false, _game->getSavedGame() ? _game->getSavedGame()->getSavedBattle() : 0);\n\n\tadd(_window, \"confirmVideo\", \"optionsMenu\");\n\tadd(_btnOk, \"confirmVideo\", \"optionsMenu\");\n\tadd(_btnCancel, \"confirmVideo\", \"optionsMenu\");\n\tadd(_txtTitle, \"confirmVideo\", \"optionsMenu\");\n\tadd(_txtWindowedModePositionX, \"confirmVideo\", \"optionsMenu\");\n\tadd(_txtWindowedModePositionY, \"confirmVideo\", \"optionsMenu\");\n\tadd(_edtWindowedModePositionX, \"confirmVideo\", \"optionsMenu\");\n\tadd(_edtWindowedModePositionY, \"confirmVideo\", \"optionsMenu\");\n\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setWordWrap(true);\n\t_txtTitle->setText(tr(\"STR_DISPLAY_SET_WINDOW_POSITION\"));\n\n\t_txtWindowedModePositionX->setAlign(ALIGN_RIGHT);\n\t_txtWindowedModePositionX->setWordWrap(true);\n\t_txtWindowedModePositionX->setText(tr(\"STR_DISPLAY_WINDOW_POSITION_NEW_X\"));\n\n\t_txtWindowedModePositionY->setAlign(ALIGN_RIGHT);\n\t_txtWindowedModePositionY->setWordWrap(true);\n\t_txtWindowedModePositionY->setText(tr(\"STR_DISPLAY_WINDOW_POSITION_NEW_Y\"));\n\n\tstd::ostringstream wss, wss2;\n\n\twss << Options::newWindowedModePositionX;\n\twss2 << Options::newWindowedModePositionY;\n\n\t_edtWindowedModePositionX->setText(wss.str());\n\t_edtWindowedModePositionX->setConstraint(TEC_NUMERIC);\n\n\t_edtWindowedModePositionY->setText(wss2.str());\n\t_edtWindowedModePositionY->setConstraint(TEC_NUMERIC);\n\n\tcenterAllSurfaces();\n\n\t// Set up object\n\tsetWindowBackground(_window, \"optionsMenu\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&SetWindowedRootState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&SetWindowedRootState::btnOkClick, Options::keyOk);\n\n\t_btnCancel->setText(tr(\"STR_CANCEL\"));\n\t_btnCancel->onMouseClick((ActionHandler)&SetWindowedRootState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&SetWindowedRootState::btnCancelClick, Options::keyCancel);\n\n\tif (_origin == OPT_BATTLESCAPE)\n\t{\n\t\tapplyBattlescapeTheme(\"optionsMenu\");\n\t}\n}\n\n/**\n *\n */\nSetWindowedRootState::~SetWindowedRootState()\n{\n}\n\n/**\n * Roots borderless window\n * @param action Pointer to an action.\n */\nvoid SetWindowedRootState::btnOkClick(Action *)\n{\n\tstd::stringstream convStreamX, convStreamY;\n\tint newWindowedModePositionX = 0, newWindowedModePositionY = 0;\n\n\tconvStreamX << _edtWindowedModePositionX->getText();\n\tconvStreamY << _edtWindowedModePositionY->getText();\n\n\tconvStreamX >> newWindowedModePositionX;\n\tconvStreamY >> newWindowedModePositionY;\n\n\tOptions::newRootWindowedMode = true;\n\tOptions::newWindowedModePositionX = newWindowedModePositionX;\n\tOptions::newWindowedModePositionY = newWindowedModePositionY;\n\n\t_game->popState();\n}\n\n/**\n * Cancels borderless window rooting\n * @param action Pointer to an action.\n */\nvoid SetWindowedRootState::btnCancelClick(Action *)\n{\n\t_optionsVideoState->unpressRootWindowedMode();\n\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Menu/SetWindowedRootState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include \"OptionsBaseState.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass TextEdit;\nclass OptionsVideoState;\n\n/**\n * Asks user new coordinates when he pushes Fixed Borderless Pos button.\n * are changed.\n */\nclass SetWindowedRootState : public State\n{\nprivate:\n\tOptionsOrigin _origin;\n\tOptionsVideoState *_optionsVideoState;\n\tTextButton *_btnOk, *_btnCancel;\n\tWindow *_window;\n\tText *_txtTitle, *_txtWindowedModePositionX, *_txtWindowedModePositionY;\n\tTextEdit *_edtWindowedModePositionX, *_edtWindowedModePositionY;\npublic:\n\t/// Creates the Confirm Display Options state.\n\tSetWindowedRootState(OptionsOrigin origin, OptionsVideoState *optionsVideoState);\n\t/// Cleans up the Confirm Display Options state.\n\t~SetWindowedRootState();\n\t/// Handler for clicking the Ok button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Menu/SlideshowState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"SlideshowState.h\"\n#include \"CutsceneState.h\"\n#include \"../Engine/FileMap.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/InteractiveSurface.h\"\n#include \"../Engine/Screen.h\"\n#include \"../Engine/Timer.h\"\n#include \"../Interface/Text.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/Cursor.h\"\n\nnamespace OpenXcom\n{\n\nSlideshowState::SlideshowState(const SlideshowHeader &slideshowHeader, const std::vector<SlideshowSlide> *slideshowSlides)\n\t\t: _slideshowHeader(slideshowHeader), _slideshowSlides(slideshowSlides), _curScreen(-1)\n{\n\t_wasLetterboxed = CutsceneState::initDisplay();\n\n\t// pre-render and queue up all the frames\n\tfor (const auto& def : *_slideshowSlides)\n\t{\n\t\tInteractiveSurface *slide =\n\t\t\tnew InteractiveSurface(Screen::ORIGINAL_WIDTH, Screen::ORIGINAL_HEIGHT, 0, 0);\n\t\tslide->loadImage(def.imagePath);\n\t\tslide->onMouseClick((ActionHandler)&SlideshowState::screenClick);\n\t\tslide->onKeyboardPress((ActionHandler)&SlideshowState::screenClick, Options::keyOk);\n\t\tslide->onKeyboardPress((ActionHandler)&SlideshowState::screenSkip, Options::keyCancel);\n\t\tslide->setVisible(false);\n\t\t_slides.push_back(slide);\n\t\tsetStatePalette(slide->getPalette());\n\t\tadd(slide);\n\n\t\t// initialize with default rect; may get overridden by\n\t\t// category/id definition\n\t\tText *caption = new Text(def.w, def.h, def.x, def.y);\n\t\tcaption->setColor(def.color);\n\t\tcaption->setText(tr(def.caption));\n\t\tcaption->setAlign(def.align);\n\t\tcaption->setVerticalAlign(def.valign);\n\t\tcaption->setWordWrap(true);\n\t\tcaption->setVisible(false);\n\t\t_captions.push_back(caption);\n\t\tadd(caption);\n\t}\n\n\tcenterAllSurfaces();\n\n\tint transitionSeconds = _slideshowHeader.transitionSeconds;\n\tif (_slideshowSlides->front().transitionSeconds > 0)\n\t\ttransitionSeconds = _slideshowSlides->front().transitionSeconds;\n\t_transitionTimer = new Timer(transitionSeconds * 1000);\n\t_transitionTimer->onTimer((StateHandler)&SlideshowState::screenTimer);\n\n\t_game->getMod()->playMusic(_slideshowHeader.musicId);\n\t_game->getCursor()->setVisible(false);\n\tscreenClick(0);\n}\n\nSlideshowState::~SlideshowState()\n{\n\tdelete _transitionTimer;\n}\n\n/**\n * Shows the next screen on a timed basis.\n */\nvoid SlideshowState::screenTimer()\n{\n\tscreenClick(0);\n}\n\n/**\n * Handle timers.\n */\nvoid SlideshowState::think()\n{\n\t_transitionTimer->think(this, 0);\n}\n\n/**\n * Shows the next screen in the slideshow; pops the state when there are no more slides\n */\nvoid SlideshowState::screenClick(Action *action)\n{\n\tif (_curScreen >= 0)\n\t{\n\t\t_slides[_curScreen]->setVisible(false);\n\t\t_captions[_curScreen]->setVisible(false);\n\t}\n\n\t++_curScreen;\n\n\t// next screen\n\tif (_curScreen < (int)_slideshowSlides->size())\n\t{\n\t\tint transitionSeconds = _slideshowHeader.transitionSeconds;\n\t\tif (_slideshowSlides->at(_curScreen).transitionSeconds > 0)\n\t\t\ttransitionSeconds = _slideshowSlides->at(_curScreen).transitionSeconds;\n\t\t_transitionTimer->setInterval(transitionSeconds * 1000);\n\t\t_transitionTimer->start();\n\t\tsetStatePalette(_slides[_curScreen]->getPalette());\n\t\t_slides[_curScreen]->setVisible(true);\n\t\t_captions[_curScreen]->setVisible(true);\n\t\tinit();\n\t}\n\telse\n\t{\n\t\tscreenSkip(action);\n\t}\n}\n\n/**\n * Skips the slideshow\n */\nvoid SlideshowState::screenSkip(Action *)\n{\n\t// slideshow is over.  restore the screen scale and pop the state\n\t_game->getCursor()->setVisible(true);\n\tCutsceneState::resetDisplay(_wasLetterboxed);\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Menu/SlideshowState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include \"../Mod/RuleVideo.h\"\n\nnamespace OpenXcom\n{\n\nclass InteractiveSurface;\nclass Text;\nclass Timer;\n\n/**\n * Shows slideshow sequences.\n */\nclass SlideshowState : public State\n{\nprivate:\n\tconst SlideshowHeader &_slideshowHeader;\n\tconst std::vector<SlideshowSlide> *_slideshowSlides;\n\tbool _wasLetterboxed;\n\tstd::vector<InteractiveSurface *> _slides;\n\tstd::vector<Text *>_captions;\n\tint _curScreen;\n\tTimer *_transitionTimer;\npublic:\n\t/// Creates the Slideshow state.\n\tSlideshowState(const SlideshowHeader &slideshowHeader, const std::vector<SlideshowSlide> *slideshowRule);\n\t/// Cleans up the Slideshow state.\n\t~SlideshowState();\n\t/// Handle timers.\n\tvoid think() override;\n\t/// Handler for waiting the screen.\n\tvoid screenTimer();\n\t/// Handler for clicking the screen.\n\tvoid screenClick(Action *action);\n\t/// Handler for skipping the screen.\n\tvoid screenSkip(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Menu/StartState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"StartState.h\"\n#include \"../version.h\"\n#include \"../Engine/Logger.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Screen.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Surface.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Language.h\"\n#include \"../Engine/Sound.h\"\n#include \"../Engine/Music.h\"\n#include \"../Engine/Font.h\"\n#include \"../Engine/Timer.h\"\n#include \"../Engine/CrossPlatform.h\"\n#include \"../Interface/FpsCounter.h\"\n#include \"../Interface/Cursor.h\"\n#include \"../Interface/Text.h\"\n#include \"MainMenuState.h\"\n#include \"CutsceneState.h\"\n#include <SDL_mixer.h>\n#include <SDL_thread.h>\n\nnamespace OpenXcom\n{\n\nLoadingPhase StartState::loading;\nstd::string StartState::error;\n\n/**\n * Initializes all the elements in the Loading screen.\n * @param game Pointer to the core game.\n */\nStartState::StartState() : _anim(0)\n{\n\t//updateScale() uses newDisplayWidth/Height and needs to be set ahead of time\n\tOptions::newDisplayWidth = Options::displayWidth;\n\tOptions::newDisplayHeight = Options::displayHeight;\n\tScreen::updateScale(Options::geoscapeScale, Options::baseXGeoscape, Options::baseYGeoscape, false);\n\tScreen::updateScale(Options::battlescapeScale, Options::baseXBattlescape, Options::baseYBattlescape, false);\n\tOptions::baseXResolution = Options::displayWidth;\n\tOptions::baseYResolution = Options::displayHeight;\n\t_game->getScreen()->resetDisplay(false, true);\n\n\t// Create objects\n\t_thread = 0;\n\tloading = LOADING_STARTED;\n\terror = \"\";\n\t_oldMaster = Options::getActiveMaster();\n\n\t_font = new Font();\n\t_font->loadTerminal();\n\t_lang = new Language();\n\n\t_text = new Text(Options::baseXResolution, Options::baseYResolution, 0, 0);\n\t_cursor = new Text(_font->getWidth(), _font->getHeight(), 0, 0);\n\t_timer = new Timer(150);\n\n\tsetStatePalette(Font::TerminalColors, 0, std::size(Font::TerminalColors));\n\n\tadd(_text);\n\tadd(_cursor);\n\n\t// Set up objects\n\t_text->initText(_font, _font, _lang);\n\t_text->setColor(0);\n\t_text->setWordWrap(true);\n\n\t_cursor->initText(_font, _font, _lang);\n\t_cursor->setColor(0);\n\t_cursor->setText(\"_\");\n\n\t_timer->onTimer((StateHandler)&StartState::animate);\n\t_timer->start();\n\n\t// Hide UI\n\t_game->getCursor()->setVisible(false);\n\t_game->getFpsCounter()->setVisible(false);\n\n\tif (Options::reload)\n\t{\n\t\tif (Options::oxceStartUpTextMode < 2)\n\t\t{\n\t\t\taddLine(\"Restarting...\");\n\t\t\taddLine(\"\");\n\t\t}\n\t}\n\telse\n\t{\n\t\tif (Options::oxceStartUpTextMode < 2)\n\t\t{\n\t\t\taddLine(CrossPlatform::getDosPath() + \">openxcom\");\n\t\t}\n\t}\n}\n\n/**\n * Kill the thread in case the game is quit early.\n */\nStartState::~StartState()\n{\n\tif (_thread != 0)\n\t{\n\t\tSDL_KillThread(_thread);\n\t}\n\tdelete _font;\n\tdelete _timer;\n\tdelete _lang;\n}\n\n/**\n * Reset and reload data.\n */\nvoid StartState::init()\n{\n\tState::init();\n\n\t// Silence!\n\tSound::stop();\n\tMusic::stop();\n\tif (!Options::mute && Options::reload)\n\t{\n\t\tMix_CloseAudio();\n\t\t_game->initAudio();\n\t}\n\n\t// Load the game data in a separate thread\n\t_thread = SDL_CreateThread(load, (void*)_game);\n\tif (_thread == 0)\n\t{\n\t\t// If we can't create the thread, just load it as usual\n\t\tload((void*)_game);\n\t}\n}\n\n/**\n * If the loading fails, it shows an error, otherwise moves on to the game.\n */\nvoid StartState::think()\n{\n\tState::think();\n\t_timer->think(this, 0);\n\n\tswitch (loading)\n\t{\n\tcase LOADING_FAILED:\n\t\tCrossPlatform::flashWindow();\n\t\taddLine(\"\");\n\t\taddLine(\"ERROR: \" + error);\n\t\taddLine(\"\");\n\t\taddLine(\"More details here: \" + CrossPlatform::getLogFileName());\n\t\taddLine(\"Make sure OpenXcom and any mods are installed correctly.\");\n\t\taddLine(\"\");\n\t\taddLine(\"Press any key to continue.\");\n\t\tloading = LOADING_DONE;\n\t\tbreak;\n\tcase LOADING_SUCCESSFUL:\n\t\tCrossPlatform::flashWindow();\n\t\tLog(LOG_INFO) << \"OpenXcom started successfully!\";\n\t\t_game->setState(new GoToMainMenuState(true));\n\t\tif (_oldMaster != Options::getActiveMaster() && Options::playIntro)\n\t\t{\n\t\t\t_game->pushState(new CutsceneState(\"intro\"));\n\t\t}\n\t\tif (Options::reload)\n\t\t{\n\t\t\tOptions::reload = false;\n\t\t}\n\t\t_game->getCursor()->setVisible(true);\n\t\t_game->getFpsCounter()->setVisible(Options::fpsCounter);\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n}\n\n/**\n * The game quits if the player presses any key when an error\n * message is on display.\n * @param action Pointer to an action.\n */\nvoid StartState::handle(Action *action)\n{\n\tState::handle(action);\n\tif (loading == LOADING_DONE)\n\t{\n\t\tif (action->getDetails()->type == SDL_KEYDOWN)\n\t\t{\n\t\t\t_game->quit();\n\t\t}\n\t}\n}\n\n/**\n * Blinks the cursor and spreads out terminal output.\n */\nvoid StartState::animate()\n{\n\t_cursor->setVisible(!_cursor->getVisible());\n\t_anim++;\n\n\tif (loading == LOADING_STARTED)\n\t{\n\t\tstd::ostringstream ss;\n\t\tss << \"Loading OpenXcom \" << OPENXCOM_VERSION_SHORT << OPENXCOM_VERSION_GIT << \"...\";\n\t\tif (Options::reload)\n\t\t{\n\t\t\tif (Options::oxceStartUpTextMode < 2)\n\t\t\t{\n\t\t\t\tif (_anim == 2)\n\t\t\t\t\taddLine(ss.str());\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tswitch (_anim)\n\t\t\t{\n\t\t\tcase 1:\n\t\t\t\tif (Options::oxceStartUpTextMode < 1)\n\t\t\t\t{\n\t\t\t\t\taddLine(\"DOS/4GW Protected Mode Run-time  Version 1.9\");\n\t\t\t\t\taddLine(\"Copyright (c) Rational Systems, Inc. 1990-1993\");\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 6:\n\t\t\t\tif (Options::oxceStartUpTextMode < 2)\n\t\t\t\t{\n\t\t\t\t\taddLine(\"\");\n\t\t\t\t\taddLine(\"OpenXcom initialisation\");\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 7:\n\t\t\t\tif (Options::oxceStartUpTextMode < 1)\n\t\t\t\t{\n\t\t\t\t\taddLine(\"\");\n\t\t\t\t\tif (Options::mute)\n\t\t\t\t\t{\n\t\t\t\t\t\taddLine(\"No Sound Detected\");\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\taddLine(\"SoundBlaster Sound Effects\");\n\t\t\t\t\t\tif (Options::preferredMusic == MUSIC_MIDI)\n\t\t\t\t\t\t\taddLine(\"General MIDI Music\");\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\taddLine(\"SoundBlaster Music\");\n\t\t\t\t\t\taddLine(\"Base Port 220  Irq 7  Dma 1\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (Options::oxceStartUpTextMode < 2)\n\t\t\t\t{\n\t\t\t\t\taddLine(\"\");\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 9:\n\t\t\t\tif (Options::oxceStartUpTextMode < 2)\n\t\t\t\t{\n\t\t\t\t\taddLine(ss.str());\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Adds a line of text to the terminal and moves\n * the cursor appropriately.\n * @param str Text line to add.\n */\nvoid StartState::addLine(const std::string &str)\n{\n\t_output << \"\\n\" << str;\n\t_text->setText(_output.str());\n\tint y = _text->getTextHeight() - _font->getHeight();\n\tint x = _text->getTextWidth(y / _font->getHeight());\n\t_cursor->setX(x);\n\t_cursor->setY(y);\n}\n\n/**\n * Loads game data and updates status accordingly.\n * @param game_ptr Pointer to the game.\n * @return Thread status, 0 = ok\n */\nint StartState::load(void *game_ptr)\n{\n\tGame *game = (Game*)game_ptr;\n\ttry\n\t{\n\t\tLog(LOG_INFO) << \"Loading data...\";\n\t\tOptions::updateMods();\n\t\tgame->loadMods();\n\t\tLog(LOG_INFO) << \"Data loaded successfully.\";\n\t\tLog(LOG_INFO) << \"Loading language...\";\n\t\tgame->loadLanguages();\n\t\tLog(LOG_INFO) << \"Language loaded successfully.\";\n\t\tloading = LOADING_SUCCESSFUL;\n\t}\n\tcatch (std::exception &e)\n\t{\n\t\terror = e.what();\n\t\tLog(LOG_ERROR) << error;\n\t\tloading = LOADING_FAILED;\n\t}\n\n\treturn 0;\n}\n\n}\n"
  },
  {
    "path": "src/Menu/StartState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include <string>\n#include <sstream>\n\nnamespace OpenXcom\n{\n\nclass Text;\nclass Font;\nclass Timer;\nclass Language;\n\nenum LoadingPhase { LOADING_STARTED, LOADING_FAILED, LOADING_SUCCESSFUL, LOADING_DONE };\n\n/**\n * Initializes the game and loads all required content.\n */\nclass StartState : public State\n{\nprivate:\n\tText *_text, *_cursor;\n\tFont *_font;\n\tTimer *_timer;\n\tLanguage *_lang;\n\tint _anim;\n\tstd::string _oldMaster;\n\n\tSDL_Thread *_thread;\n\tstd::ostringstream _output;\npublic:\n\tstatic LoadingPhase loading;\n\tstatic std::string error;\n\n\t/// Creates the Start state.\n\tStartState();\n\t/// Cleans up the Start state.\n\t~StartState();\n\t/// Reset everything.\n\tvoid init() override;\n\t/// Displays messages.\n\tvoid think() override;\n\t/// Handles key clicks.\n\tvoid handle(Action *action) override;\n\t/// Animates the terminal.\n\tvoid animate();\n\t/// Adds a line of text.\n\tvoid addLine(const std::string &str);\n\t/// Loads the game resources.\n\tstatic int load(void *game_ptr);\n};\n\n}\n"
  },
  {
    "path": "src/Menu/StatisticsState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"StatisticsState.h\"\n#include <algorithm>\n#include <string>\n#include <sstream>\n#include <vector>\n#include <map>\n#include \"../Engine/Game.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"MainMenuState.h\"\n#include \"../Savegame/MissionStatistics.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/SoldierDiary.h\"\n#include \"../Savegame/SoldierDeath.h\"\n#include \"../Savegame/BattleUnitStatistics.h\"\n#include \"../Savegame/Country.h\"\n#include \"../Savegame/Region.h\"\n#include \"../Savegame/AlienBase.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Statistics window.\n * @param game Pointer to the core game.\n */\nStatisticsState::StatisticsState()\n{\n\t// Create objects\n\t_window = new Window(this, 320, 200, 0, 0, POPUP_BOTH);\n\t_btnOk = new TextButton(50, 12, 135, 180);\n\t_txtTitle = new Text(310, 25, 5, 8);\n\t_lstStats = new TextList(280, 136, 12, 36);\n\n\t// Set palette\n\tsetInterface(\"endGameStatistics\");\n\n\tadd(_window, \"window\", \"endGameStatistics\");\n\tadd(_btnOk, \"button\", \"endGameStatistics\");\n\tadd(_txtTitle, \"text\", \"endGameStatistics\");\n\tadd(_lstStats, \"list\", \"endGameStatistics\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"endGameStatistics\");\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&StatisticsState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&StatisticsState::btnOkClick, Options::keyOk);\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\n\t_lstStats->setColumns(2, 200, 80);\n\t_lstStats->setDot(true);\n\n\tlistStats();\n}\n\n/**\n *\n */\nStatisticsState::~StatisticsState()\n{\n\n}\n\ntemplate <typename T>\nT StatisticsState::sumVector(const std::vector<T> &vec) const\n{\n\tT total = 0;\n\tfor (typename std::vector<T>::const_iterator i = vec.begin(); i != vec.end(); ++i)\n\t{\n\t\ttotal += *i;\n\t}\n\treturn total;\n}\n\nvoid StatisticsState::listStats()\n{\n\tSavedGame *save = _game->getSavedGame();\n\n\tstd::ostringstream ss;\n\tGameTime *time = save->getTime();\n\tif (save->getEnding() == END_WIN)\n\t{\n\t\tss << tr(\"STR_VICTORY\");\n\t}\n\telse if (save->getEnding() == END_LOSE)\n\t{\n\t\tss << tr(\"STR_DEFEAT\");\n\t}\n\telse\n\t{\n\t\tss << tr(\"STR_STATISTICS\");\n\t}\n\tss << Unicode::TOK_NL_SMALL << time->getDayString(_game->getLanguage()) << \" \" << tr(time->getMonthString()) << \" \" << time->getYear();\n\t_txtTitle->setText(ss.str());\n\n\tint totalScore = sumVector(save->getResearchScores());\n\tfor (auto* region : *save->getRegions())\n\t{\n\t\ttotalScore += sumVector(region->getActivityXcom()) - sumVector(region->getActivityAlien());\n\t}\n\n\tint monthlyScore = totalScore / (int)save->getResearchScores().size();\n\tint64_t totalIncome = sumVector(save->getIncomes());\n\tint64_t totalExpenses = sumVector(save->getExpenditures());\n\n\tint alienBasesDestroyed = 0, xcomBasesLost = 0;\n\tint missionsWin = 0, missionsLoss = 0, nightMissions = 0;\n\tint bestScore = -9999, worstScore = 9999;\n\tfor (const auto* ms : *save->getMissionStatistics())\n\t{\n\t\tif (ms->success)\n\t\t{\n\t\t\tmissionsWin++;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tmissionsLoss++;\n\t\t}\n\t\tbestScore = std::max(bestScore, ms->score);\n\t\tworstScore = std::min(worstScore, ms->score);\n\t\tif (ms->isDarkness(_game->getMod()))\n\t\t{\n\t\t\tnightMissions++;\n\t\t}\n\t\tif (ms->isAlienBase() && ms->success)\n\t\t{\n\t\t\talienBasesDestroyed++;\n\t\t}\n\t\tif (ms->isBaseDefense() && !ms->success)\n\t\t{\n\t\t\txcomBasesLost++;\n\t\t}\n\t}\n\t// Make sure dummy values aren't left in\n\tbestScore = (bestScore == -9999) ? 0 : bestScore;\n\tworstScore = (worstScore == 9999) ? 0 : worstScore;\n\n\tstd::vector<Soldier*> allSoldiers;\n\tfor (auto* xbase : *save->getBases())\n\t{\n\t\tallSoldiers.insert(allSoldiers.end(), xbase->getSoldiers()->begin(), xbase->getSoldiers()->end());\n\t}\n\tallSoldiers.insert(allSoldiers.end(), save->getDeadSoldiers()->begin(), save->getDeadSoldiers()->end());\n\tint soldiersRecruited = allSoldiers.size();\n\tint soldiersLost = save->getDeadSoldiers()->size();\n\tint vehiclesLost = save->getVehiclesLost();\n\tint craftLostDogfight = save->getCraftLostDogfight();\n\tint craftLostMission = save->getCraftLostMission();\n\n\tint aliensKilled = 0, aliensCaptured = 0, friendlyKills = 0;\n\tint daysWounded = 0, longestMonths = 0;\n\tint shotsFired = 0, shotsLanded = 0;\n\tstd::map<std::string, int> weaponKills, alienKills;\n\tfor (const auto* soldier : allSoldiers)\n\t{\n\t\tconst SoldierDiary *diary = soldier->getDiary();\n\t\taliensKilled += diary->getKillTotal();\n\t\taliensCaptured += diary->getStunTotal();\n\t\tdaysWounded += diary->getDaysWoundedTotal();\n\t\tlongestMonths = std::max(longestMonths, diary->getMonthsService());\n\t\tstd::map<std::string, int> weaponTotal = diary->getWeaponTotal();\n\t\tshotsFired += diary->getShotsFiredTotal();\n\t\tshotsLanded += diary->getShotsLandedTotal();\n\t\tfor (const auto& pair : weaponTotal)\n\t\t{\n\t\t\tif (weaponKills.find(pair.first) == weaponKills.end())\n\t\t\t{\n\t\t\t\tweaponKills[pair.first] = pair.second;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tweaponKills[pair.first] += pair.second;\n\t\t\t}\n\t\t}\n\n\t\tif (soldier->getDeath() != 0 && soldier->getDeath()->getCause() != 0)\n\t\t{\n\t\t\tconst BattleUnitKills *kills = soldier->getDeath()->getCause();\n\t\t\tif (kills->faction == FACTION_PLAYER)\n\t\t\t{\n\t\t\t\tfriendlyKills++;\n\t\t\t}\n\t\t\tif (!kills->race.empty())\n\t\t\t{\n\t\t\t\tif (alienKills.find(kills->race) == alienKills.end())\n\t\t\t\t{\n\t\t\t\t\talienKills[kills->race] = 1;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\talienKills[kills->race] += 1;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tint accuracy = 0;\n\tif (shotsFired > 0)\n\t{\n\t\taccuracy = 100 * shotsLanded / shotsFired;\n\t}\n\n\tint maxWeapon = 0;\n\tstd::string highestWeapon = \"STR_NONE\";\n\tfor (const auto& pair : weaponKills)\n\t{\n\t\tif (pair.second > maxWeapon)\n\t\t{\n\t\t\tmaxWeapon = pair.second;\n\t\t\thighestWeapon = pair.first;\n\t\t}\n\t}\n\tint maxAlien = 0;\n\tstd::string highestAlien = \"STR_NONE\";\n\tfor (const auto& pair : alienKills)\n\t{\n\t\tif (pair.second > maxAlien)\n\t\t{\n\t\t\tmaxAlien = pair.second;\n\t\t\thighestAlien = pair.first;\n\t\t}\n\t}\n\n\tstd::map<std::string, int> ids = save->getAllIds();\n\tint alienBases = alienBasesDestroyed;\n\tfor (const auto* ab : *save->getAlienBases())\n\t{\n\t\tif (ab->isDiscovered())\n\t\t{\n\t\t\talienBases++;\n\t\t}\n\t}\n\tint ufosDetected = std::max(0, ids[\"STR_UFO\"] - 1);\n\tint terrorSites = std::max(0, ids[\"STR_TERROR_SITE\"] - 1);\n\tint totalCrafts = 0;\n\tfor (const auto& craftType : _game->getMod()->getCraftsList())\n\t{\n\t\ttotalCrafts += std::max(0, ids[craftType] - 1);\n\t}\n\n\tint xcomBases = save->getBases()->size() + xcomBasesLost;\n\tint currentScientists = 0, currentEngineers = 0;\n\tfor (const auto* xbase : *save->getBases())\n\t{\n\t\tcurrentScientists += xbase->getTotalScientists();\n\t\tcurrentEngineers += xbase->getTotalEngineers();\n\t}\n\n\tint countriesLost = 0;\n\tfor (const auto* country : *save->getCountries())\n\t{\n\t\tif (country->getPact())\n\t\t{\n\t\t\tcountriesLost++;\n\t\t}\n\t}\n\n\tint researchDone = save->getDiscoveredResearch().size();\n\n\tstd::string difficulty[] = { \"STR_1_BEGINNER\", \"STR_2_EXPERIENCED\", \"STR_3_VETERAN\", \"STR_4_GENIUS\", \"STR_5_SUPERHUMAN\" };\n\n\t_lstStats->addRow(2, tr(\"STR_DIFFICULTY\").c_str(), tr(difficulty[save->getDifficulty()]).c_str());\n\t_lstStats->addRow(2, tr(\"STR_AVERAGE_MONTHLY_RATING\").c_str(), Unicode::formatNumber(monthlyScore).c_str());\n\t_lstStats->addRow(2, tr(\"STR_TOTAL_INCOME\").c_str(), Unicode::formatFunding(totalIncome).c_str());\n\t_lstStats->addRow(2, tr(\"STR_TOTAL_EXPENDITURE\").c_str(), Unicode::formatFunding(totalExpenses).c_str());\n\tif (Options::soldierDiaries)\n\t{\n\t\t_lstStats->addRow(2, tr(\"STR_MISSIONS_WON\").c_str(), Unicode::formatNumber(missionsWin).c_str());\n\t\t_lstStats->addRow(2, tr(\"STR_MISSIONS_LOST\").c_str(), Unicode::formatNumber(missionsLoss).c_str());\n\t\t_lstStats->addRow(2, tr(\"STR_NIGHT_MISSIONS\").c_str(), Unicode::formatNumber(nightMissions).c_str());\n\t\t_lstStats->addRow(2, tr(\"STR_BEST_RATING\").c_str(), Unicode::formatNumber(bestScore).c_str());\n\t\t_lstStats->addRow(2, tr(\"STR_WORST_RATING\").c_str(), Unicode::formatNumber(worstScore).c_str());\n\t}\n\t_lstStats->addRow(2, tr(\"STR_SOLDIERS_RECRUITED\").c_str(), Unicode::formatNumber(soldiersRecruited).c_str());\n\t_lstStats->addRow(2, tr(\"STR_SOLDIERS_LOST\").c_str(), Unicode::formatNumber(soldiersLost).c_str());\n\t_lstStats->addRow(2, tr(\"STR_VEHICLES_LOST\").c_str(), Unicode::formatNumber(vehiclesLost).c_str()); // \"STR_TANKS_DESTROYED\" from DebriefingState\n\tif (Options::soldierDiaries)\n\t{\n\t\t_lstStats->addRow(2, tr(\"STR_ALIEN_KILLS\").c_str(), Unicode::formatNumber(aliensKilled).c_str());\n\t\t_lstStats->addRow(2, tr(\"STR_ALIEN_CAPTURES\").c_str(), Unicode::formatNumber(aliensCaptured).c_str());\n\t\t_lstStats->addRow(2, tr(\"STR_FRIENDLY_KILLS\").c_str(), Unicode::formatNumber(friendlyKills).c_str());\n\t\t_lstStats->addRow(2, tr(\"STR_AVERAGE_ACCURACY\").c_str(), Unicode::formatPercentage(accuracy).c_str());\n\t\t_lstStats->addRow(2, tr(\"STR_WEAPON_MOST_KILLS\").c_str(), tr(highestWeapon).c_str());\n\t\t_lstStats->addRow(2, tr(\"STR_ALIEN_MOST_KILLS\").c_str(), tr(highestAlien).c_str());\n\t\t_lstStats->addRow(2, tr(\"STR_LONGEST_SERVICE\").c_str(), Unicode::formatNumber(longestMonths).c_str());\n\t\t_lstStats->addRow(2, tr(\"STR_TOTAL_DAYS_WOUNDED\").c_str(), Unicode::formatNumber(daysWounded).c_str());\n\t}\n\t_lstStats->addRow(2, tr(\"STR_TOTAL_UFOS\").c_str(), Unicode::formatNumber(ufosDetected).c_str());\n\tif (Options::soldierDiaries)\n\t{\n\t\t_lstStats->addRow(2, tr(\"STR_TOTAL_ALIEN_BASES\").c_str(), Unicode::formatNumber(alienBases).c_str());\n\t\t_lstStats->addRow(2, tr(\"STR_ALIEN_BASES_DESTROYED\").c_str(), Unicode::formatNumber(alienBasesDestroyed).c_str());\n\t}\n\t_lstStats->addRow(2, tr(\"STR_COUNTRIES_LOST\").c_str(), Unicode::formatNumber(countriesLost).c_str());\n\t_lstStats->addRow(2, tr(\"STR_TOTAL_TERROR_SITES\").c_str(), Unicode::formatNumber(terrorSites).c_str());\n\tif (Options::soldierDiaries)\n\t{\n\t\t_lstStats->addRow(2, tr(\"STR_TOTAL_BASES\").c_str(), Unicode::formatNumber(xcomBases).c_str());\n\t\t_lstStats->addRow(2, tr(\"STR_XCOM_BASES_LOST\").c_str(), Unicode::formatNumber(xcomBasesLost).c_str());\n\t}\n\t_lstStats->addRow(2, tr(\"STR_TOTAL_CRAFT\").c_str(), Unicode::formatNumber(totalCrafts).c_str());\n\t_lstStats->addRow(2, tr(\"STR_CRAFT_LOST_DOGFIGHT\").c_str(), Unicode::formatNumber(craftLostDogfight).c_str());\n\t_lstStats->addRow(2, tr(\"STR_CRAFT_LOST_MISSION\").c_str(), Unicode::formatNumber(craftLostMission).c_str());\n\t_lstStats->addRow(2, tr(\"STR_TOTAL_SCIENTISTS\").c_str(), Unicode::formatNumber(currentScientists).c_str());\n\t_lstStats->addRow(2, tr(\"STR_TOTAL_ENGINEERS\").c_str(), Unicode::formatNumber(currentEngineers).c_str());\n\t_lstStats->addRow(2, tr(\"STR_TOTAL_RESEARCH\").c_str(), Unicode::formatNumber(researchDone).c_str());\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid StatisticsState::btnOkClick(Action *)\n{\n\tif (_game->getSavedGame()->getEnding() == END_NONE)\n\t{\n\t\t_game->popState();\n\t}\n\telse\n\t{\n\t\t_game->setSavedGame(0);\n\t\t_game->setState(new GoToMainMenuState);\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Menu/StatisticsState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nclass TextButton;\nclass Window;\nclass Text;\nclass TextList;\n\n/**\n * Statistics window that shows up\n * at the end of the game.\n */\nclass StatisticsState : public State\n{\nprivate:\n\tTextButton *_btnOk;\n\tWindow *_window;\n\tText *_txtTitle;\n\tTextList *_lstStats;\n\n\t// Sums a list of numbers.\n\ttemplate <typename T>\n\tT sumVector(const std::vector<T> &vec) const;\npublic:\n\t/// Creates the New Game state.\n\tStatisticsState();\n\t/// Cleans up the New Game state.\n\t~StatisticsState();\n\t/// Gets the save stats.\n\tvoid listStats();\n\t/// Handler for clicking the Ok button.\n\tvoid btnOkClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Menu/TestPaletteState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"TestPaletteState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Palette.h\"\n#include \"../Interface/NumberText.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Mod/Mod.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the test palette screen.\n */\nTestPaletteState::TestPaletteState(const std::string &palette, PaletteActionType action)\n{\n\t// Create objects\n\t_bg = new Surface(320, 200, 0, 0);\n\t_btnCancel = new TextButton(60, 9, 240, 190);\n\n\t// Set palette\n\tsetStandardPalette(palette);\n\tint maxColors = _game->getMod()->getPalette(palette)->getColorCount();\n\n\tif (_game->isCtrlPressed())\n\t{\n\t\t// export the palette\n\t\tconst std::string exportName = palette + \".jasc.pal\";\n\t\t_game->getMod()->getPalette(palette)->savePalJasc(exportName);\n\t}\n\n\tadd(_bg);\n\tadd(_btnCancel);\n\n\tcenterAllSurfaces();\n\n\t_btnCancel->onMouseClick((ActionHandler)&TestPaletteState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&TestPaletteState::btnCancelClick, Options::keyCancel);\n\n\t// basic palette\n\tif (action == PAT_PREVIEW)\n\t{\n\t\tSurface surf = Surface(20, 11, 0, 0);\n\t\tsurf.setPalette(_bg->getPalette());\n\t\tfor (int row = 0; row < 16; ++row)\n\t\t{\n\t\t\tfor (int column = 0; column < 16; ++column)\n\t\t\t{\n\t\t\t\tint index = row * 16 + column;\n\t\t\t\tif (index >= maxColors) return;\n\t\t\t\tsurf.drawRect(0, 0, 20, 11, index);\n\t\t\t\tsurf.blitNShade(_bg, column * 20, row * 11);\n\t\t\t}\n\t\t}\n\t\treturn;\n\t}\n\n\t// small digits without/with border\n\tif (action == PAT_TINY_BORDERLESS || action == PAT_TINY_BORDER)\n\t{\n\t\tNumberText text = NumberText(25, 9, 0, 0);\n\t\ttext.setPalette(_bg->getPalette());\n\t\ttext.initText(_game->getMod()->getFont(\"FONT_BIG\"), _game->getMod()->getFont(\"FONT_SMALL\"), _game->getLanguage());\n\t\ttext.setBordered((action == PAT_TINY_BORDER));\n\t\tfor (int row = 0; row < 22; ++row)\n\t\t{\n\t\t\tfor (int column = 0; column < 12; ++column)\n\t\t\t{\n\t\t\t\tint index = row * 12 + column;\n\t\t\t\tif (index >= maxColors) return;\n\t\t\t\ttext.setColor(index);\n\t\t\t\ttext.setX(column * 26);\n\t\t\t\ttext.setY(row * 9);\n\t\t\t\ttext.setValue(index);\n\t\t\t\ttext.blit(_bg->getSurface());\n\t\t\t}\n\t\t}\n\t\treturn;\n\t}\n\n\t// big text without/with high contrast\n\tif (action == PAT_BIG_LOW || action == PAT_BIG_HIGH)\n\t{\n\t\tText text = Text(13, 17, 0, 0);\n\t\ttext.setPalette(_bg->getPalette());\n\t\ttext.initText(_game->getMod()->getFont(\"FONT_BIG\"), _game->getMod()->getFont(\"FONT_SMALL\"), _game->getLanguage());\n\t\ttext.setHighContrast((action == PAT_BIG_HIGH));\n\t\ttext.setBig();\n\t\tfor (int row = 0; row < 11; ++row)\n\t\t{\n\t\t\tfor (int column = 0; column < 24; ++column)\n\t\t\t{\n\t\t\t\tint index = row * 24 + column;\n\t\t\t\tif (index >= maxColors) return;\n\t\t\t\ttext.setColor(index);\n\t\t\t\ttext.setX(column * 13);\n\t\t\t\ttext.setY(row * 17);\n\t\t\t\tstd::ostringstream ss;\n\t\t\t\tss << index % 10;\n\t\t\t\ttext.setText(ss.str().c_str());\n\t\t\t\ttext.blit(_bg->getSurface());\n\t\t\t}\n\t\t}\n\t\treturn;\n\t}\n\n\t// normal text without/with high contrast\n\tText text = Text(25, 9, 0, 0);\n\ttext.setPalette(_bg->getPalette());\n\ttext.initText(_game->getMod()->getFont(\"FONT_BIG\"), _game->getMod()->getFont(\"FONT_SMALL\"), _game->getLanguage());\n\ttext.setHighContrast((action == PAT_SMALL_HIGH));\n\tfor (int row = 0; row < 22; ++row)\n\t{\n\t\tfor (int column = 0; column < 12; ++column)\n\t\t{\n\t\t\tint index = row * 12 + column;\n\t\t\tif (index >= maxColors) return;\n\t\t\ttext.setColor(index);\n\t\t\ttext.setX(column * 26);\n\t\t\ttext.setY(row * 9);\n\t\t\tstd::ostringstream ss;\n\t\t\tss << index;\n\t\t\ttext.setText(ss.str().c_str());\n\t\t\ttext.blit(_bg->getSurface());\n\t\t}\n\t}\n}\n\nTestPaletteState::~TestPaletteState()\n{\n}\n\n/**\n* Returns to the previous screen.\n* @param action Pointer to an action.\n*/\nvoid TestPaletteState::btnCancelClick(Action *action)\n{\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Menu/TestPaletteState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\nenum PaletteActionType { PAT_PREVIEW, PAT_TINY_BORDERLESS, PAT_TINY_BORDER, PAT_SMALL_LOW, PAT_SMALL_HIGH, PAT_BIG_LOW, PAT_BIG_HIGH };\n\nclass Surface;\nclass TextButton;\n\n/**\n * A state for preview of text color code per palette and contrast.\n */\nclass TestPaletteState : public State\n{\nprivate:\n\tSurface *_bg;\n\tTextButton *_btnCancel;\npublic:\n\t/// Creates the Test state.\n\tTestPaletteState(const std::string &palette, PaletteActionType action);\n\t/// Cleans up the Test state.\n\t~TestPaletteState();\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Menu/TestState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"TestState.h\"\n#include \"TestPaletteState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/ComboBox.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Interface/Window.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/Exception.h\"\n#include \"../Engine/FileMap.h\"\n#include \"../Engine/Logger.h\"\n#include \"../Engine/Palette.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Mod/ExtraSprites.h\"\n#include \"../Mod/RuleTerrain.h\"\n#include \"../Mod/MapBlock.h\"\n#include \"../Mod/MapDataSet.h\"\n#include \"../Mod/MapData.h\"\n#include \"../Mod/RuleUfo.h\"\n#include \"../Mod/RuleGlobe.h\"\n#include \"../Mod/Texture.h\"\n#include \"../Mod/MapScript.h\"\n#include \"../Mod/AlienDeployment.h\"\n\nnamespace OpenXcom\n{\n\n// items are (roughly) ordered by frequency of use... to save a few CPU cycles when looking for a match\nstatic std::map<int, PaletteTestMetadata> _paletteMetadataMap =\n{\n\t{ 1, PaletteTestMetadata(\"UFO_PAL_BATTLEPEDIA\", 1, 255, 0, \"Palettes/UFO-JASC/PAL_BATTLEPEDIA.pal\", false) },\n\t{ 2, PaletteTestMetadata(\"UFO_PAL_BATTLESCAPE\", 1, 255, 0, \"Palettes/UFO-JASC/PAL_BATTLESCAPE.pal\", false) },\n\n\t{ 3, PaletteTestMetadata(\"UFO_PAL_BATTLE_COMMON\", 1, 239, 0, \"Palettes/UFO-JASC/PAL_BATTLE_COMMON.pal\", false) }, // ignore last 16 colors\n\n\t{ 4, PaletteTestMetadata(\"TFTD_PAL_BATTLESCAPE\", 1, 254, 3, \"Palettes/TFTD-JASC/PAL_BATTLESCAPE.pal\", false) }, // ignore last color too\n\n\t{ 5, PaletteTestMetadata(\"UFO_PAL_UFOPAEDIA\", 1, 255, 0, \"Palettes/UFO-JASC/PAL_UFOPAEDIA.pal\", false) },\n\t{ 6, PaletteTestMetadata(\"TFTD_PAL_BASESCAPE\", 1, 255, 0, \"Palettes/TFTD-JASC/PAL_BASESCAPE.pal\", true) }, // TFTD's ufopedia\n\n\t{ 7, PaletteTestMetadata(\"UFO_PAL_BASESCAPE\", 1, 255, 0, \"Palettes/UFO-JASC/PAL_BASESCAPE.pal\", true) },\n\n\t{ 8, PaletteTestMetadata(\"UFO_PAL_GEOSCAPE\", 1, 255, 0, \"Palettes/UFO-JASC/PAL_GEOSCAPE.pal\", true) },\n\t{ 9, PaletteTestMetadata(\"TFTD_PAL_GEOSCAPE\", 1, 255, 0, \"Palettes/TFTD-JASC/PAL_GEOSCAPE.pal\", true) },\n\n\t{ 10, PaletteTestMetadata(\"TFTD_PAL_BATTLESCAPE_1\", 1, 254, 3, \"Palettes/TFTD-JASC/PAL_BATTLESCAPE_1.pal\", false) },\n\t{ 11, PaletteTestMetadata(\"TFTD_PAL_BATTLESCAPE_2\", 1, 254, 3, \"Palettes/TFTD-JASC/PAL_BATTLESCAPE_2.pal\", false) },\n\t{ 12, PaletteTestMetadata(\"TFTD_PAL_BATTLESCAPE_3\", 1, 254, 3, \"Palettes/TFTD-JASC/PAL_BATTLESCAPE_3.pal\", false) },\n\n\t{ 13, PaletteTestMetadata(\"UFO_PAL_BACKGROUND_SAFE\", 0, 255, 0, \"Palettes/UFO-JASC-SAFE/PAL_BACKGROUND_SAFE.pal\", false) },\n\t{ 14, PaletteTestMetadata(\"TFTD_PAL_BACKGROUND_SAFE\", 0, 255, 0, \"Palettes/TFTD-JASC-SAFE/PAL_BACKGROUND_SAFE.pal\", false) },\n\n\t{ 15, PaletteTestMetadata(\"UFO_PAL_GRAPHS\", 1, 255, 0, \"Palettes/UFO-JASC/PAL_GRAPHS.pal\", false) },\n\t{ 16, PaletteTestMetadata(\"TFTD_PAL_GRAPHS\", 1, 255, 0, \"Palettes/TFTD-JASC/PAL_GRAPHS.pal\", false) }\n};\n\n/**\n * Initializes all the elements in the test screen.\n */\nTestState::TestState()\n{\n\t// Create objects\n\t_window = new Window(this, 320, 200, 0, 0);\n\t_txtTitle = new Text(300, 17, 10, 7);\n\t_txtPalette = new Text(66, 9, 10, 30);\n\t_cbxPalette = new ComboBox(this, 114, 16, 78, 26);\n\t_cbxPaletteAction = new ComboBox(this, 114, 16, 198, 26);\n\t_txtTestCase = new Text(66, 9, 10, 50);\n\t_cbxTestCase = new ComboBox(this, 234, 16, 78, 46);\n\t_txtDescription = new Text(300, 25, 10, 66);\n\t_lstOutput = new TextList(284, 80, 10, 94);\n\t_btnRun = new TextButton(146, 16, 10, 176);\n\t_btnCancel = new TextButton(146, 16, 164, 176);\n\n\t// Set palette\n\tsetInterface(\"tests\");\n\n\tadd(_window, \"window\", \"tests\");\n\tadd(_txtTitle, \"heading\", \"tests\");\n\tadd(_txtPalette, \"text\", \"tests\");\n\tadd(_txtTestCase, \"text\", \"tests\");\n\tadd(_txtDescription, \"heading\", \"tests\");\n\tadd(_lstOutput, \"text\", \"tests\");\n\tadd(_btnRun, \"button2\", \"tests\");\n\tadd(_btnCancel, \"button2\", \"tests\");\n\tadd(_cbxTestCase, \"button1\", \"tests\"); // add as last (display over all other components)\n\tadd(_cbxPalette, \"button1\", \"tests\"); // add as last (display over all other components)\n\tadd(_cbxPaletteAction, \"button1\", \"tests\"); // add as last (display over all other components)\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"tests\");\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_TEST_SCREEN\"));\n\n\t_txtPalette->setText(tr(\"STR_PALETTE\"));\n\n\tfor (auto& pal : _game->getMod()->getPalettes())\n\t{\n\t\tif (pal.first.find(\"BACKUP_\") != 0)\n\t\t{\n\t\t\t_paletteList.push_back(pal.first);\n\t\t}\n\t}\n\n\t_cbxPalette->setOptions(_paletteList, true);\n\n\tstd::vector<std::string> _actionList;\n\t_actionList.push_back(\"STR_PREVIEW\");\n\t_actionList.push_back(\"STR_TINY_BORDERLESS\");\n\t_actionList.push_back(\"STR_TINY_BORDER\");\n\t_actionList.push_back(\"STR_SMALL_LOW_CONTRAST\");\n\t_actionList.push_back(\"STR_SMALL_HIGH_CONTRAST\");\n\t_actionList.push_back(\"STR_BIG_LOW_CONTRAST\");\n\t_actionList.push_back(\"STR_BIG_HIGH_CONTRAST\");\n\n\t_cbxPaletteAction->setOptions(_actionList, true);\n\t_cbxPaletteAction->onChange((ActionHandler)&TestState::cbxPaletteAction);\n\n\t_txtTestCase->setText(tr(\"STR_TEST_CASE\"));\n\n\t_testCases.push_back(\"STR_BAD_NODES\");\n\t_testCases.push_back(\"STR_MCD_CHECK\");\n\t_testCases.push_back(\"STR_PALETTE_CHECK\");\n\t_testCases.push_back(\"STR_SCRIPT_TAGS\");\n\t_testCases.push_back(\"STR_MAP_RESOURCES\");\n\n\t_cbxTestCase->setOptions(_testCases, true);\n\t_cbxTestCase->onChange((ActionHandler)&TestState::cbxTestCaseChange);\n\n\t_txtDescription->setWordWrap(true);\n\tcbxTestCaseChange(0); // update description\n\n\t_lstOutput->setColumns(1, 284);\n\t_lstOutput->setBackground(_window);\n\t_lstOutput->setWordWrap(true);\n\n\t_btnRun->setText(tr(\"STR_RUN\"));\n\t_btnRun->onMouseClick((ActionHandler)&TestState::btnRunClick);\n\n\t_btnCancel->setText(tr(\"STR_CANCEL\"));\n\t_btnCancel->onMouseClick((ActionHandler)&TestState::btnCancelClick);\n\t_btnCancel->onKeyboardPress((ActionHandler)&TestState::btnCancelClick, Options::keyCancel);\n}\n\nTestState::~TestState()\n{\n\tfor (auto& item : _vanillaPalettes)\n\t{\n\t\tdelete item.second;\n\t}\n}\n\n/**\n* Updates the test case description.\n* @param action Pointer to an action.\n*/\nvoid TestState::cbxTestCaseChange(Action *)\n{\n\t_lstOutput->clearList();\n\n\tsize_t index = _cbxTestCase->getSelected();\n\t_txtDescription->setText(tr(_testCases[index]+\"_DESC\"));\n}\n\n/**\n* Returns to the previous screen.\n* @param action Pointer to an action.\n*/\nvoid TestState::btnRunClick(Action *action)\n{\n\t_lstOutput->clearList();\n\n\tsize_t index = _cbxTestCase->getSelected();\n\tswitch (index)\n\t{\n\t\tcase 0: testCase0(); break;\n\t\tcase 1: testCase1(); break;\n\t\tcase 2: testCase2(); break;\n\t\tcase 3: testCase3(); break;\n\t\tcase 4: testCase4(); break;\n\t\tdefault: break;\n\t}\n}\n\n/**\n* Returns to the previous screen.\n* @param action Pointer to an action.\n*/\nvoid TestState::btnCancelClick(Action *action)\n{\n\t_game->popState();\n}\n\n/**\n * Shows palette preview.\n * @param action Pointer to an action.\n */\nvoid TestState::cbxPaletteAction(Action *action)\n{\n\tsize_t index = _cbxPalette->getSelected();\n\tconst std::string palette = _paletteList[index];\n\n\tPaletteActionType type = (PaletteActionType)_cbxPaletteAction->getSelected();\n\n\t_game->pushState(new TestPaletteState(palette, type));\n}\n\nvoid TestState::testCase4()\n{\n\t_lstOutput->addRow(1, tr(\"STR_TESTS_STARTING\").c_str());\n\n\tint total = 0;\n\n\t// build a list of all terrains\n\tstd::map<std::string, int> terrainMap;\n\tfor (auto& texturePair : _game->getMod()->getGlobe()->getTexturesRaw())\n\t{\n\t\tfor (auto& terrainCrit : *texturePair.second->getTerrain())\n\t\t\tterrainMap[terrainCrit.name] += 1;\n\t\tfor (auto& baseTerrainCrit : *texturePair.second->getBaseTerrain())\n\t\t\tterrainMap[baseTerrainCrit.name] += 1;\n\t}\n\tfor (auto& terrainName : _game->getMod()->getTerrainList())\n\t{\n\t\tterrainMap[terrainName] += 1;\n\t}\n\tfor (auto& deployName : _game->getMod()->getDeploymentsList())\n\t{\n\t\tAlienDeployment *deployRule = _game->getMod()->getDeployment(deployName);\n\t\tfor (auto& terrainName : deployRule->getTerrains())\n\t\t\tterrainMap[terrainName] += 1;\n\t}\n\tfor (auto& mapScript : _game->getMod()->getMapScriptsRaw())\n\t{\n\t\tfor (auto* mapScriptCommand : mapScript.second)\n\t\t{\n\t\t\tfor (auto& terrainName : mapScriptCommand->getRandomAlternateTerrain())\n\t\t\t{\n\t\t\t\tterrainMap[terrainName] += 1;\n\t\t\t}\n\t\t}\n\t}\n\n\t// erase false positives\n\tterrainMap.erase(\"\");\n\tterrainMap.erase(\"baseTerrain\");\n\tterrainMap.erase(\"globeTerrain\");\n\n\t// 1. check terrain existence in ruleset\n\tLog(LOG_INFO) << \"----------------------------------------------1. check terrain existence in ruleset\";\n\tfor (auto& pair : terrainMap)\n\t{\n\t\tRuleTerrain *tRule = _game->getMod()->getTerrain(pair.first);\n\t\tif (!tRule)\n\t\t{\n\t\t\t++total;\n\t\t\tLog(LOG_INFO) << \"Terrain '\" << pair.first << \"' does not exist!\";\n\t\t}\n\t}\n\n\t// build a list of all mapblocks and mapdatasets\n\tstd::map<std::string, int> blockMap;\n\tstd::map<std::string, int> datasetMap;\n\n\tauto addMapblockAndDataset = [](RuleTerrain *terrainRule, std::map<std::string, int> &blockMapRef, std::map<std::string, int> &datasetMapRef, int maxSkinIndex = 0)\n\t{\n\t\tif (terrainRule)\n\t\t{\n\t\t\tfor (auto* mapblock : *terrainRule->getMapBlocks())\n\t\t\t{\n\t\t\t\tstd::string uc = mapblock->getName();\n\t\t\t\tUnicode::upperCase(uc);\n\t\t\t\tblockMapRef[uc] += 1;\n\t\t\t}\n\t\t\tfor (int skinIndex = 0; skinIndex <= maxSkinIndex; ++skinIndex)\n\t\t\t{\n\t\t\t\tfor (auto* dataset : *terrainRule->getMapDataSets())\n\t\t\t\t{\n\t\t\t\t\tstd::string uc = dataset->getName();\n\t\t\t\t\tUnicode::upperCase(uc);\n\t\t\t\t\tif (skinIndex > 0 && uc != \"BLANKS\")\n\t\t\t\t\t{\n\t\t\t\t\t\tuc = uc + \"_\" + std::to_string(skinIndex);\n\t\t\t\t\t}\n\t\t\t\t\tdatasetMapRef[uc] += 1;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\n\tfor (auto& pair : terrainMap)\n\t{\n\t\tRuleTerrain *terrainRule = _game->getMod()->getTerrain(pair.first);\n\t\taddMapblockAndDataset(terrainRule, blockMap, datasetMap);\n\t}\n\tfor (auto& ufoName : _game->getMod()->getUfosList())\n\t{\n\t\tRuleUfo *ufoRule = _game->getMod()->getUfo(ufoName);\n\t\tRuleTerrain *terrainRule = ufoRule->getBattlescapeTerrainData();\n\t\taddMapblockAndDataset(terrainRule, blockMap, datasetMap);\n\t}\n\tfor (auto& craftName : _game->getMod()->getCraftsList())\n\t{\n\t\tRuleCraft *craftRule = _game->getMod()->getCraft(craftName);\n\t\tRuleTerrain *terrainRule = craftRule->getBattlescapeTerrainData();\n\t\taddMapblockAndDataset(terrainRule, blockMap, datasetMap, craftRule->getMaxSkinIndex());\n\t}\n\n\t// 2. check for existence of mapblock MAP and RMP files\n\tLog(LOG_INFO) << \"----------------------------------------------2. check for existence of mapblock MAP and RMP files\";\n\n\tauto checkExistence = [](std::map<std::string, int> &mapRef, const std::string &dir, const std::string &ext, int &totalRef)\n\t{\n\t\tfor (auto& mapItem : mapRef)\n\t\t{\n\t\t\tstd::ostringstream filename;\n\t\t\tfilename << dir << mapItem.first << ext;\n\t\t\tif (!FileMap::fileExists(filename.str()))\n\t\t\t{\n\t\t\t\t++totalRef;\n\t\t\t\tLog(LOG_INFO) << filename.str() << \" not found\";\n\t\t\t}\n\t\t}\n\t};\n\n\tcheckExistence(blockMap, \"MAPS/\", \".MAP\", total);\n\tcheckExistence(blockMap, \"ROUTES/\", \".RMP\", total);\n\n\t// 3. check for existence of mapdataset MCD, PCK and TAB files\n\tLog(LOG_INFO) << \"----------------------------------------------3. check for existence of mapdataset MCD, PCK and TAB files\";\n\n\tcheckExistence(datasetMap, \"TERRAIN/\", \".MCD\", total);\n\tcheckExistence(datasetMap, \"TERRAIN/\", \".PCK\", total);\n\tcheckExistence(datasetMap, \"TERRAIN/\", \".TAB\", total);\n\n\t// 4. check for unused mapblock MAP and RMP files\n\tLog(LOG_INFO) << \"----------------------------------------------4. check for unused mapblock MAP and RMP files\";\n\n\tauto findUnusedFiles = [](std::map<std::string, int> &mapRef, const std::string &dir, int &totalRef)\n\t{\n\t\tconst auto& contents = FileMap::getVFolderContents(dir);\n\t\tfor (const auto& name : contents)\n\t\t{\n\t\t\tstd::string upper = name; // copy\n\t\t\tUnicode::upperCase(upper);\n\t\t\tstd::string noExt = CrossPlatform::noExt(upper);\n\t\t\tif (mapRef.find(noExt) == mapRef.end())\n\t\t\t{\n\t\t\t\tstd::string fullpath = FileMap::at(dir + upper)->fullpath;\n\n\t\t\t\t// exceptions\n\t\t\t\tif (fullpath.find(\"/standard/xcom1/\") != std::string::npos) continue;\n\t\t\t\tif (fullpath.find(\"/UFO/MAPS/\") != std::string::npos) continue;\n\t\t\t\tif (fullpath.find(\"/UFO/ROUTES/\") != std::string::npos) continue;\n\t\t\t\tif (fullpath.find(\"/TFTD/MAPS/\") != std::string::npos) continue;\n\t\t\t\tif (fullpath.find(\"/TFTD/ROUTES/\") != std::string::npos) continue;\n\t\t\t\tif (fullpath.find(\"/TFTD/TERRAIN/\") != std::string::npos) continue;\n\n\t\t\t\t++totalRef;\n\t\t\t\tLog(LOG_INFO) << fullpath << \" not used anywhere.\";\n\t\t\t}\n\t\t}\n\t};\n\n\tfindUnusedFiles(blockMap, \"MAPS/\", total);\n\tfindUnusedFiles(blockMap, \"ROUTES/\", total);\n\n\t// 5. check for unused mapdataset MCD, PCK and TAB files\n\tLog(LOG_INFO) << \"----------------------------------------------5. check for unused mapdataset MCD, PCK and TAB files\";\n\n\tfindUnusedFiles(datasetMap, \"TERRAIN/\", total);\n\n\n\tif (total > 0)\n\t{\n\t\t_lstOutput->addRow(1, tr(\"STR_TESTS_ERRORS_FOUND\").arg(total).c_str());\n\t\t_lstOutput->addRow(1, tr(\"STR_DETAILED_INFO_IN_LOG_FILE\").c_str());\n\t}\n\telse\n\t{\n\t\t_lstOutput->addRow(1, tr(\"STR_TESTS_NO_ERRORS_FOUND\").c_str());\n\t}\n\t_lstOutput->addRow(1, tr(\"STR_TESTS_FINISHED\").c_str());\n}\n\nvoid TestState::testCase3()\n{\n\t_lstOutput->addRow(1, tr(\"STR_TESTS_STARTING\").c_str());\n\n\tstd::map<const Armor *, std::map<std::string, int> > tagMatrix;\n\tfor (auto& armorName : _game->getMod()->getArmorsList())\n\t{\n\t\tauto* armorRule = _game->getMod()->getArmor(armorName, true);\n\t\tauto& tagValues = armorRule->getScriptValuesRaw().getValuesRaw();\n\t\tArgEnum index = ScriptParserBase::getArgType<ScriptTag<Armor>>();\n\t\tauto& tagNames = _game->getMod()->getScriptGlobal()->getTagNames().at(index);\n\t\tfor (size_t i = 0; i < tagValues.size(); ++i)\n\t\t{\n\t\t\tstd::string nameAsString = tagNames.values[i].name.toString().substr(4);\n\t\t\ttagMatrix[armorRule][nameAsString] = tagValues.at(i);\n\t\t}\n\t}\n\n\tstd::map<std::string, bool> tagNames;\n\tfor (auto& a : tagMatrix)\n\t{\n\t\tfor (auto& t : a.second)\n\t\t{\n\t\t\ttagNames[t.first] = true;\n\t\t}\n\t}\n\n\tLog(LOG_INFO) << \"----------------------------------------------\";\n\tLog(LOG_INFO) << \"Copy/paste into a CSV file\";\n\tLog(LOG_INFO) << \"----------------------------------------------\";\n\t{\n\t\tstd::ostringstream ssNames;\n\t\tssNames << \";Armor\";\n\t\tfor (auto& n : tagNames)\n\t\t{\n\t\t\tssNames << \";\" << n.first;\n\t\t}\n\t\tLog(LOG_INFO) << ssNames.str();\n\t}\n\tfor (auto& armorName : _game->getMod()->getArmorsList())\n\t{\n\t\tauto* armorRule = _game->getMod()->getArmor(armorName, true);\n\t\tauto& armorData = tagMatrix[armorRule];\n\t\tstd::ostringstream ss;\n\t\tss << \";\" << armorName;\n\t\tfor (auto& t : tagNames)\n\t\t{\n\t\t\tss << \";\";\n\t\t\tauto findIt = armorData.find(t.first);\n\t\t\tif (findIt != armorData.end())\n\t\t\t{\n\t\t\t\tss << (*findIt).second;\n\t\t\t}\n\t\t}\n\t\tLog(LOG_INFO) << ss.str();\n\t}\n\tLog(LOG_INFO) << \"----------------------------------------------\";\n\tLog(LOG_INFO) << \"End of export\";\n\tLog(LOG_INFO) << \"----------------------------------------------\";\n\n\t_lstOutput->addRow(1, tr(\"STR_TESTS_FINISHED\").c_str());\n}\n\nvoid TestState::testCase2()\n{\n\t_lstOutput->addRow(1, tr(\"STR_TESTS_STARTING\").c_str());\n\tif (_vanillaPalettes.empty())\n\t{\n\t\tfor (auto& item : _paletteMetadataMap)\n\t\t{\n\t\t\t_vanillaPalettes[item.first] = new Palette();\n\t\t\t_vanillaPalettes[item.first]->initBlack();\n\n\t\t\t// Load from JASC file\n\t\t\tauto palFile = FileMap::getIStream(item.second.palettePath);\n\t\t\tif (palFile)\n\t\t\t{\n\t\t\t\tstd::string line;\n\t\t\t\tstd::getline(*palFile, line); // header\n\t\t\t\tstd::getline(*palFile, line); // file format\n\t\t\t\tstd::getline(*palFile, line); // number of colors\n\t\t\t\tint r = 0, g = 0, b = 0;\n\t\t\t\tfor (int j = 0; j < 256; ++j)\n\t\t\t\t{\n\t\t\t\t\tstd::getline(*palFile, line); // j-th color index\n\t\t\t\t\tstd::stringstream ss(line);\n\t\t\t\t\tss >> r;\n\t\t\t\t\tss >> g;\n\t\t\t\t\tss >> b;\n\t\t\t\t\t_vanillaPalettes[item.first]->copyColor(j, r, g, b); // raw RGB copy, no side effects!\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tthrow Exception(item.second.palettePath + \" not found\");\n\t\t\t}\n\t\t}\n\t}\n\n\tint total = 0;\n\tfor (auto& i : _game->getMod()->getExtraSprites())\n\t{\n\t\tstd::string sheetName = i.first;\n\t\tif (sheetName.find(\"_CPAL\") != std::string::npos)\n\t\t{\n\t\t\t// custom palettes cannot be matched, skip\n\t\t\tcontinue;\n\t\t}\n\n\t\tfor (auto* spritePack : i.second)\n\t\t{\n\t\tif (spritePack->getSingleImage())\n\t\t{\n\t\t\tconst std::string& relPath = (*spritePack->getSprites())[0];\n\t\t\ttotal += checkPalette(relPath, spritePack->getWidth(), spritePack->getHeight());\n\t\t}\n\t\telse\n\t\t{\n\t\t\tfor (auto& j : *spritePack->getSprites())\n\t\t\t{\n\t\t\t\tint startFrame = j.first;\n\t\t\t\tstd::string fileName = j.second;\n\t\t\t\tif (fileName.substr(fileName.length() - 1, 1) == \"/\")\n\t\t\t\t{\n\t\t\t\t\tconst auto& contents = FileMap::getVFolderContents(fileName);\n\t\t\t\t\tfor (const auto& name : contents)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (!ExtraSprites::isImageFile(name))\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\ttry\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tstd::string relPath = fileName + name;\n\t\t\t\t\t\t\ttotal += checkPalette(relPath, spritePack->getWidth(), spritePack->getHeight());\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcatch (Exception &e)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tLog(LOG_WARNING) << e.what();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif (spritePack->getSubX() == 0 && spritePack->getSubY() == 0)\n\t\t\t\t\t{\n\t\t\t\t\t\ttotal += checkPalette(fileName, spritePack->getWidth(), spritePack->getHeight());\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tconst std::string& relPath = (*spritePack->getSprites())[startFrame];\n\t\t\t\t\t\ttotal += checkPalette(relPath, spritePack->getWidth(), spritePack->getHeight());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t}\n\t}\n\n\tif (total > 0)\n\t{\n\t\t_lstOutput->addRow(1, tr(\"STR_TESTS_ERRORS_FOUND\").arg(total).c_str());\n\t\t_lstOutput->addRow(1, tr(\"STR_DETAILED_INFO_IN_LOG_FILE\").c_str());\n\t}\n\telse\n\t{\n\t\t_lstOutput->addRow(1, tr(\"STR_TESTS_NO_ERRORS_FOUND\").c_str());\n\t}\n\t_lstOutput->addRow(1, tr(\"STR_TESTS_FINISHED\").c_str());\n}\n\nint TestState::checkPalette(const std::string& fullPath, int width, int height)\n{\n\tSurface *image = new Surface(width, height);\n\timage->loadImage(fullPath);\n\n\tSDL_Palette *palette = image->getSurface()->format->palette;\n\tif (!palette)\n\t{\n\t\tLog(LOG_ERROR) << \"Image doesn't have a palette at all! Full path: \" << fullPath;\n\t\tdelete image;\n\t\treturn 1;\n\t}\n\n\tint ncolors = image->getSurface()->format->palette->ncolors;\n\tif (ncolors != 256)\n\t{\n\t\tLog(LOG_ERROR) << \"Image palette doesn't have 256 colors! Full path: \" << fullPath;\n\t}\n\n\tint bestMatch = 0;\n\tint matchedPaletteIndex = 0;\n\tfor (auto& item : _vanillaPalettes)\n\t{\n\t\tint match = matchPalette(image, item.first, item.second);\n\t\tif (match > bestMatch)\n\t\t{\n\t\t\tbestMatch = match;\n\t\t\tmatchedPaletteIndex = item.first;\n\t\t}\n\t\tif (match == 100)\n\t\t{\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tdelete image;\n\n\tif (bestMatch < 100)\n\t{\n\t\tLog(LOG_INFO) << \"Best match: \" << bestMatch << \"%; palette: \" << _paletteMetadataMap[matchedPaletteIndex].paletteName << \"; path: \" << fullPath;\n\t\treturn 1;\n\t}\n\n\treturn 0;\n}\n\nint TestState::matchPalette(Surface *image, int index, Palette *test)\n{\n\tSDL_Color *colors = image->getSurface()->format->palette->colors;\n\tint matched = 0;\n\n\tint firstIndexToCheck = _paletteMetadataMap[index].firstIndexToCheck;\n\tint lastIndexToCheck = _paletteMetadataMap[index].lastIndexToCheck;\n\tint maxTolerance = _paletteMetadataMap[index].maxTolerance;\n\tbool usesBackPals = _paletteMetadataMap[index].usesBackPals;\n\n\tfor (int i = firstIndexToCheck; i <= lastIndexToCheck; i++)\n\t{\n\t\tif (usesBackPals)\n\t\t{\n\t\t\tif (i >= 224 && i <= 239)\n\t\t\t{\n\t\t\t\t// don't check and consider matched\n\t\t\t\tmatched++;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\tUint8 rdiff = (colors[i].r > test->getColors(i)->r ? colors[i].r - test->getColors(i)->r : test->getColors(i)->r - colors[i].r);\n\t\tUint8 gdiff = (colors[i].g > test->getColors(i)->g ? colors[i].g - test->getColors(i)->g : test->getColors(i)->g - colors[i].g);\n\t\tUint8 bdiff = (colors[i].b > test->getColors(i)->b ? colors[i].b - test->getColors(i)->b : test->getColors(i)->b - colors[i].b);\n\n\t\tif (rdiff <= maxTolerance && gdiff <= maxTolerance && bdiff <= maxTolerance)\n\t\t{\n\t\t\tmatched++;\n\t\t}\n\t}\n\n\treturn matched * 100 / (lastIndexToCheck - firstIndexToCheck + 1);\n}\n\nvoid TestState::testCase1()\n{\n\t_lstOutput->addRow(1, tr(\"STR_TESTS_STARTING\").c_str());\n\t_lstOutput->addRow(1, tr(\"STR_CHECKING_TERRAIN\").c_str());\n\tint total = 0;\n\tstd::map<std::string, std::set<int>> uniqueResults;\n\tfor (auto& terrainName : _game->getMod()->getTerrainList())\n\t{\n\t\tRuleTerrain *terrainRule = _game->getMod()->getTerrain(terrainName);\n\t\ttotal += checkMCD(terrainRule, uniqueResults);\n\t}\n\t_lstOutput->addRow(1, tr(\"STR_CHECKING_UFOS\").c_str());\n\tfor (auto& ufoName : _game->getMod()->getUfosList())\n\t{\n\t\tRuleUfo *ufoRule = _game->getMod()->getUfo(ufoName);\n\t\tRuleTerrain *terrainRule = ufoRule->getBattlescapeTerrainData();\n\t\tif (!terrainRule)\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\t\ttotal += checkMCD(terrainRule, uniqueResults);\n\t}\n\t_lstOutput->addRow(1, tr(\"STR_CHECKING_CRAFT\").c_str());\n\tfor (auto& craftName : _game->getMod()->getCraftsList())\n\t{\n\t\tRuleCraft *craftRule = _game->getMod()->getCraft(craftName);\n\t\tRuleTerrain *terrainRule = craftRule->getBattlescapeTerrainData();\n\t\tif (!terrainRule)\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\t\tfor (int skinIndex = 0; skinIndex <= craftRule->getMaxSkinIndex(); ++skinIndex)\n\t\t{\n\t\t\tterrainRule->refreshMapDataSets(skinIndex, _game->getMod()); // change skin\n\t\t\ttotal += checkMCD(terrainRule, uniqueResults);\n\t\t}\n\t}\n\tif (total > 0)\n\t{\n\t\t_lstOutput->addRow(1, tr(\"STR_TESTS_ERRORS_FOUND\").arg(total).c_str());\n\t\t_lstOutput->addRow(1, tr(\"STR_DETAILED_INFO_IN_LOG_FILE\").c_str());\n\t}\n\telse\n\t{\n\t\t_lstOutput->addRow(1, tr(\"STR_TESTS_NO_ERRORS_FOUND\").c_str());\n\t}\n\n\t// summary (unique)\n\tif (total > 0)\n\t{\n\t\tLog(LOG_INFO) << \"----------\";\n\t\tLog(LOG_INFO) << \"SUMMARY\";\n\t\tLog(LOG_INFO) << \"----------\";\n\t\tfor (auto& mapItem : uniqueResults)\n\t\t{\n\t\t\tstd::ostringstream ss;\n\t\t\tss << mapItem.first << \": \";\n\t\t\tbool first = true;\n\t\t\tfor (int setItem : mapItem.second)\n\t\t\t{\n\t\t\t\tif (!first)\n\t\t\t\t{\n\t\t\t\t\tss << \", \";\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tfirst = false;\n\t\t\t\t}\n\t\t\t\tss << setItem;\n\t\t\t}\n\t\t\tstd::string line = ss.str();\n\t\t\tLog(LOG_INFO) << line;\n\t\t}\n\t}\n\t_lstOutput->addRow(1, tr(\"STR_TESTS_FINISHED\").c_str());\n}\n\nint TestState::checkMCD(RuleTerrain *terrainRule, std::map<std::string, std::set<int>> &uniqueResults)\n{\n\tint MAX_LOFT_ID = (_game->getMod()->getVoxelData()->size() / 16) - 1;\n\tint errors = 0;\n\tfor (auto* myMapDataSet : *terrainRule->getMapDataSets())\n\t{\n\t\tint index = 0;\n\t\tmyMapDataSet->loadData(_game->getMod()->getMCDPatch(myMapDataSet->getName()), false);\n\t\tint size = (int)(myMapDataSet->getObjectsRaw()->size());\n\t\tfor (auto* myMapData : *myMapDataSet->getObjectsRaw())\n\t\t{\n\t\t\t// Check for 0 armor\n\t\t\tif (myMapData->getArmor() == 0)\n\t\t\t{\n\t\t\t\tstd::ostringstream ss;\n\t\t\t\tss << \"terrain: \" << terrainRule->getName() << \" dataset: \" << myMapDataSet->getName() << \" object \" << index << \" has armor: \" << myMapData->getArmor();\n\t\t\t\tstd::string str = ss.str();\n\t\t\t\tLog(LOG_ERROR) << \"Error in \" << str << \". Found using OXCE test cases.\";\n\t\t\t\terrors++;\n\t\t\t\tuniqueResults[myMapDataSet->getName()].insert(index);\n\t\t\t}\n\n\t\t\t// Check for invalid LOFTemps\n\t\t\tfor (int layer = 0; layer < 12; ++layer)\n\t\t\t{\n\t\t\t\tif (myMapData->getLoftID(layer) < 0 || myMapData->getLoftID(layer) > MAX_LOFT_ID)\n\t\t\t\t{\n\t\t\t\t\tstd::ostringstream ss;\n\t\t\t\t\tss << \"terrain: \" << terrainRule->getName() << \" dataset: \" << myMapDataSet->getName() << \" object \" << index << \" has LoftID: \" << myMapData->getLoftID(layer);\n\t\t\t\t\tstd::string str = ss.str();\n\t\t\t\t\tLog(LOG_ERROR) << \"Error in \" << str << \". MAX_LOFT_ID = \" << MAX_LOFT_ID << \". Found using OXCE test cases.\";\n\t\t\t\t\terrors++;\n\t\t\t\t\tuniqueResults[myMapDataSet->getName()].insert(index);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Validate MCD references\n\t\t\tif (myMapData->getDieMCD() >= size)\n\t\t\t{\n\t\t\t\tstd::ostringstream ss;\n\t\t\t\tss << \"terrain: \" << terrainRule->getName() << \" dataset: \" << myMapDataSet->getName() << \" object \" << index << \" has invalid DieMCD: \" << myMapData->getDieMCD();\n\t\t\t\tstd::string str = ss.str();\n\t\t\t\tLog(LOG_ERROR) << \"Error in \" << str << \". Found using OXCE test cases.\";\n\t\t\t\terrors++;\n\t\t\t\tuniqueResults[myMapDataSet->getName()].insert(index);\n\t\t\t}\n\t\t\tif (myMapData->getAltMCD() >= size)\n\t\t\t{\n\t\t\t\tstd::ostringstream ss;\n\t\t\t\tss << \"terrain: \" << terrainRule->getName() << \" dataset: \" << myMapDataSet->getName() << \" object \" << index << \" has invalid AltMCD: \" << myMapData->getAltMCD();\n\t\t\t\tstd::string str = ss.str();\n\t\t\t\tLog(LOG_ERROR) << \"Error in \" << str << \". Found using OXCE test cases.\";\n\t\t\t\terrors++;\n\t\t\t\tuniqueResults[myMapDataSet->getName()].insert(index);\n\t\t\t}\n\n\t\t\tif (myMapData->getObjectType() == O_FLOOR)\n\t\t\t{\n\t\t\t\tif (myMapData->isNoFloor() && myMapData->getTUCost(MT_WALK) > 0 && myMapData->getTUCost(MT_WALK) < 200 && myMapDataSet->getName() != \"BLANKS\")\n\t\t\t\t{\n\t\t\t\t\t// Note: pathfinding and autoshots don't work on such ground tiles\n\t\t\t\t\t// (such objects were intended to be used only as holes on upper floors/roofs, they should NOT be used on ground floor)\n\t\t\t\t\tstd::ostringstream ss;\n\t\t\t\t\tss << \"terrain: \" << terrainRule->getName() << \" dataset: \" << myMapDataSet->getName() << \" object \" << index << \" is a walkable floor tile with 'No_Floor' flag set to true.\";\n\t\t\t\t\tstd::string str = ss.str();\n\t\t\t\t\tLog(LOG_WARNING) << \"Potential issue in \" << str << \". Found using OXCE test cases.\";\n\t\t\t\t\terrors++;\n\t\t\t\t\tuniqueResults[myMapDataSet->getName()].insert(index);\n\t\t\t\t}\n\t\t\t\tif (myMapData->getTUCost(MT_WALK) < 1)\n\t\t\t\t{\n\t\t\t\t\tstd::ostringstream ss;\n\t\t\t\t\tss << \" walk:\" << myMapData->getTUCost(MT_WALK) << \" terrain:\" << terrainRule->getName() << \" dataset:\" << myMapDataSet->getName() << \" index:\" << index;\n\t\t\t\t\tstd::string str = ss.str();\n\t\t\t\t\tLog(LOG_INFO) << \"Zero movement cost on floor object: \" << str << \". Found using OXCE test cases.\";\n\t\t\t\t\terrors++;\n\t\t\t\t\tuniqueResults[myMapDataSet->getName()].insert(index);\n\t\t\t\t}\n\t\t\t\tif (myMapData->getTUCost(MT_FLY) < 1)\n\t\t\t\t{\n\t\t\t\t\tstd::ostringstream ss;\n\t\t\t\t\tss << \"  fly:\" << myMapData->getTUCost(MT_FLY) << \" terrain:\" << terrainRule->getName() << \" dataset:\" << myMapDataSet->getName() << \" index:\" << index;\n\t\t\t\t\tstd::string str = ss.str();\n\t\t\t\t\tLog(LOG_INFO) << \"Zero movement cost on floor object: \" << str << \". Found using OXCE test cases.\";\n\t\t\t\t\terrors++;\n\t\t\t\t\tuniqueResults[myMapDataSet->getName()].insert(index);\n\t\t\t\t}\n\t\t\t\tif (myMapData->getTUCost(MT_SLIDE) < 1)\n\t\t\t\t{\n\t\t\t\t\tstd::ostringstream ss;\n\t\t\t\t\tss << \"slide:\" << myMapData->getTUCost(MT_SLIDE) << \" terrain:\" << terrainRule->getName() << \" dataset:\" << myMapDataSet->getName() << \" index:\" << index;\n\t\t\t\t\tstd::string str = ss.str();\n\t\t\t\t\tLog(LOG_INFO) << \"Zero movement cost on floor object: \" << str << \". Found using OXCE test cases.\";\n\t\t\t\t\terrors++;\n\t\t\t\t\tuniqueResults[myMapDataSet->getName()].insert(index);\n\t\t\t\t}\n\t\t\t}\n\t\t\tindex++;\n\t\t}\n\t\t//myMapDataSet->unloadData();\n\t}\n\treturn errors;\n}\n\nvoid TestState::testCase0()\n{\n\t_lstOutput->addRow(1, tr(\"STR_TESTS_STARTING\").c_str());\n\t_lstOutput->addRow(1, tr(\"STR_CHECKING_TERRAIN\").c_str());\n\tint total = 0;\n\tfor (auto& terrainName : _game->getMod()->getTerrainList())\n\t{\n\t\tRuleTerrain *terrRule = _game->getMod()->getTerrain(terrainName);\n\t\tfor (auto* mapblock : *terrRule->getMapBlocks())\n\t\t{\n\t\t\ttotal += checkRMP(mapblock);\n\t\t}\n\t}\n\t_lstOutput->addRow(1, tr(\"STR_CHECKING_UFOS\").c_str());\n\tfor (auto& ufoName : _game->getMod()->getUfosList())\n\t{\n\t\tRuleUfo *ufoRule = _game->getMod()->getUfo(ufoName);\n\t\tif (ufoRule->getBattlescapeTerrainData())\n\t\t{\n\t\t\tfor (auto* mapblock : *ufoRule->getBattlescapeTerrainData()->getMapBlocks())\n\t\t\t{\n\t\t\t\ttotal += checkRMP(mapblock);\n\t\t\t}\n\t\t}\n\t}\n\t_lstOutput->addRow(1, tr(\"STR_CHECKING_CRAFT\").c_str());\n\tfor (auto& craftName : _game->getMod()->getCraftsList())\n\t{\n\t\tRuleCraft *craftRule = _game->getMod()->getCraft(craftName);\n\t\tif (craftRule->getBattlescapeTerrainData())\n\t\t{\n\t\t\tfor (auto* mapblock : *craftRule->getBattlescapeTerrainData()->getMapBlocks())\n\t\t\t{\n\t\t\t\ttotal += checkRMP(mapblock);\n\t\t\t}\n\t\t}\n\t}\n\tif (total > 0)\n\t{\n\t\t_lstOutput->addRow(1, tr(\"STR_TESTS_ERRORS_FOUND\").arg(total).c_str());\n\t\t_lstOutput->addRow(1, tr(\"STR_DETAILED_INFO_IN_LOG_FILE\").c_str());\n\t}\n\telse\n\t{\n\t\t_lstOutput->addRow(1, tr(\"STR_TESTS_NO_ERRORS_FOUND\").c_str());\n\t}\n\t_lstOutput->addRow(1, tr(\"STR_TESTS_FINISHED\").c_str());\n}\n\nint TestState::checkRMP(MapBlock *mapblock)\n{\n\t// Z-dimension is not in the ruleset, it's hacked on-the-fly\n\tint mapblockSizeZ = loadMAP(mapblock);\n\n\tunsigned char value[24];\n\tstd::ostringstream filename;\n\tfilename << \"ROUTES/\" << mapblock->getName() << \".RMP\";\n\n\t// Load file\n\tauto mapFile = FileMap::getIStream(filename.str());\n\tif (!mapFile)\n\t{\n\t\tthrow Exception(filename.str() + \" not found\");\n\t}\n\n\tint nodesAdded = 0;\n\tint errors = 0;\n\twhile (mapFile->read((char*)&value, sizeof(value)))\n\t{\n\t\tint pos_x = value[1];\n\t\tint pos_y = value[0];\n\t\tint pos_z = value[2];\n\t\tif (pos_x >= 0 && pos_x < mapblock->getSizeX() &&\n\t\t\tpos_y >= 0 && pos_y < mapblock->getSizeY() &&\n\t\t\tpos_z >= 0 && pos_z < mapblockSizeZ) // using \"mapblockSizeZ\" instead of \"mapblock->getSizeZ()\"!!\n\t\t{\n\t\t\t// all ok\n\t\t}\n\t\telse\n\t\t{\n\t\t\tLog(LOG_INFO) << \"Bad node in RMP file: \" << filename.str() << \" Node #\" << nodesAdded << \" is outside map boundaries at X:\" << pos_x << \" Y:\" << pos_y << \" Z:\" << pos_z << \". Found using OXCE test cases.\";\n\t\t\terrors++;\n\t\t}\n\t\tnodesAdded++;\n\t}\n\n\tif (!mapFile->eof())\n\t{\n\t\tthrow Exception(\"Invalid RMP file: \" + filename.str());\n\t}\n\n\treturn errors;\n}\n\nint TestState::loadMAP(MapBlock *mapblock)\n{\n\tint sizez;\n\tchar size[3];\n\tstd::ostringstream filename;\n\tfilename << \"MAPS/\" << mapblock->getName() << \".MAP\";\n\n\t// Load file\n\tauto mapFile = FileMap::getIStream(filename.str());\n\tif (!mapFile)\n\t{\n\t\tthrow Exception(filename.str() + \" not found\");\n\t}\n\n\tmapFile->read((char*)&size, sizeof(size));\n\t//sizey = (int)size[0];\n\t//sizex = (int)size[1];\n\tsizez = (int)size[2];\n\n\t//mapblock->setSizeZ(sizez); // commented out, for testing purposes we don't need to HACK it like in real code\n\n\treturn sizez;\n}\n\n}\n"
  },
  {
    "path": "src/Menu/TestState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include <map>\n#include <set>\n\nnamespace OpenXcom\n{\n\nclass Window;\nclass TextButton;\nclass Text;\nclass ComboBox;\nclass TextList;\nclass MapBlock;\nclass RuleTerrain;\nclass Palette;\n\nstruct PaletteTestMetadata {\n\tstd::string paletteName;\n\tint firstIndexToCheck;\n\tint lastIndexToCheck;\n\tint maxTolerance;\n\tstd::string palettePath;\n\tbool usesBackPals;\n\n\tPaletteTestMetadata() : firstIndexToCheck(0), lastIndexToCheck(255), maxTolerance(0), usesBackPals(false) { };\n\tPaletteTestMetadata(const std::string &_paletteName, int _firstIndexToCheck, int _lastIndexToCheck, int _maxTolerance, const std::string &_palettePath, bool _usesBackPals) :\n\t\tpaletteName(_paletteName), firstIndexToCheck(_firstIndexToCheck), lastIndexToCheck(_lastIndexToCheck), maxTolerance(_maxTolerance), palettePath(_palettePath), usesBackPals(_usesBackPals)\n\t{\n\t\t// empty\n\t};\n};\n\n/**\n * A state for testing most common modding mistakes.\n */\nclass TestState : public State\n{\nprivate:\n\tWindow *_window;\n\tTextButton *_btnRun, *_btnCancel;\n\tText *_txtPalette;\n\tText *_txtTitle, *_txtTestCase, *_txtDescription;\n\tComboBox *_cbxPalette;\n\tComboBox *_cbxPaletteAction;\n\tComboBox *_cbxTestCase;\n\tTextList *_lstOutput;\n\tstd::vector<std::string> _paletteList;\n\tstd::map<int, Palette*> _vanillaPalettes;\n\tstd::vector<std::string> _testCases;\n\t/// Test cases.\n\tvoid testCase4();\n\tvoid testCase3();\n\tvoid testCase2();\n\tint checkPalette(const std::string& fullPath, int width, int height);\n\tint matchPalette(Surface *image, int index, Palette *test);\n\tvoid testCase1();\n\tint checkMCD(RuleTerrain *terrainRule, std::map<std::string, std::set<int>> &uniqueResults);\n\tvoid testCase0();\n\tint checkRMP(MapBlock *mapblock);\n\tint loadMAP(MapBlock *mapblock);\npublic:\n\t/// Creates the Test state.\n\tTestState();\n\t/// Cleans up the Test state.\n\t~TestState();\n\t/// Handler for changing the Test Case combobox.\n\tvoid cbxTestCaseChange(Action *action);\n\t/// Handler for clicking the Run button.\n\tvoid btnRunClick(Action *action);\n\t/// Handler for clicking the Cancel button.\n\tvoid btnCancelClick(Action *action);\n\t/// Handler for selecting the Palette Action from the combobox.\n\tvoid cbxPaletteAction(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Menu/VideoState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"VideoState.h\"\n#include <algorithm>\n#include <SDL_mixer.h>\n#include \"../Engine/Adlib/adlplayer.h\"\n#include \"../Engine/Logger.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/FlcPlayer.h\"\n#include \"../Engine/CrossPlatform.h\"\n#include \"../Engine/FileMap.h\"\n#include \"../Engine/Screen.h\"\n#include \"../Engine/Music.h\"\n#include \"../Engine/Sound.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleVideo.h\"\n#include \"CutsceneState.h\"\n#include \"../Interface/Cursor.h\"\n#include <algorithm>\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes all the elements in the Intro screen.\n * @param game Pointer to the core game.\n * @param wasLetterBoxed Was the game letterboxed?\n */\nVideoState::VideoState(const std::vector<std::string> *videos, const std::vector<std::string> *tracks, bool useUfoAudioSequence)\n\t\t: _videos(videos), _tracks(tracks), _useUfoAudioSequence(useUfoAudioSequence)\n{\n}\n\n/**\n *\n */\nVideoState::~VideoState()\n{\n}\n\n\ntypedef struct\n{\n\tstd::string catFile;\n\tint sound;\n\tint volume;\n} soundInFile;\n\n\n// the pure MS-DOS experience\nstatic soundInFile introCatOnlySounds[]=\n{\n{\"INTRO.CAT\", 0x0, 32},\n{\"INTRO.CAT\", 0x1, 32},\n{\"INTRO.CAT\", 0x2, 32},\n{\"INTRO.CAT\", 0x3, 32},\n{\"INTRO.CAT\", 0x4, 32},\n{\"INTRO.CAT\", 0x5, 32},\n{\"INTRO.CAT\", 0x6, 32},\n{\"INTRO.CAT\", 0x7, 32},\n{\"INTRO.CAT\", 0x8, 32},\n{\"INTRO.CAT\", 0x9, 32},\n{\"INTRO.CAT\", 0xa, 32},\n{\"INTRO.CAT\", 0xb, 32},\n{\"INTRO.CAT\", 0xc, 32},\n{\"INTRO.CAT\", 0xd, 32},\n{\"INTRO.CAT\", 0xe, 32},\n{\"INTRO.CAT\", 0xf, 32},\n{\"INTRO.CAT\", 0x10, 32},\n{\"INTRO.CAT\", 0x11, 32},\n{\"INTRO.CAT\", 0x12, 32},\n{\"INTRO.CAT\", 0x13, 32},\n{\"INTRO.CAT\", 0x14, 32},\n{\"INTRO.CAT\", 0x15, 32},\n{\"INTRO.CAT\", 0x16, 32},\n{\"INTRO.CAT\", 0x17, 32},\n{\"INTRO.CAT\", 0x18, 32},\n{\"INTRO.CAT\", 0x18, 32}\n};\n\n\nstatic soundInFile sample3CatOnlySounds[]=\n{\n{\"SAMPLE3.CAT\", 24, 32}, // machine gun\n{\"SAMPLE3.CAT\", 5, 32},   // plasma rifle\n{\"SAMPLE3.CAT\", 23, 32}, // rifle\n{\"SAMPLE3.CAT\",  6, 32}, // some kind of death noise, urgh?\n{\"SAMPLE3.CAT\", 9, 64}, // mutdie\n{\"SAMPLE3.CAT\", 7, 64}, // dying alien\n{\"SAMPLE3.CAT\", 27, 64}, // another dying alien\n{\"SAMPLE3.CAT\", 4, 32}, // ??? ship flying? alien screech?\n{\"SAMPLE3.CAT\", 0x8, 32}, // fscream\n{\"SAMPLE3.CAT\", 11, 32}, // alarm\n{\"SAMPLE3.CAT\", 4, 32}, // gun spinning up?\n{\"INTRO.CAT\", 0xb, 32},  // reload; this one's not even in sample3\n{\"SAMPLE3.CAT\",19, 48},  // whoosh\n{\"INTRO.CAT\", 0xd, 32},  // feet, also not in sample3\n{\"SAMPLE3.CAT\", 2, 32},  // low pulsating hum\n{\"SAMPLE3.CAT\", 30, 32}, // energise\n{\"SAMPLE3.CAT\", 21, 32}, // hatch\n{\"SAMPLE3.CAT\", 0, 64}, // phizz -- no equivalent in sample3.cat?\n{\"SAMPLE3.CAT\", 13, 32}, // warning\n{\"SAMPLE3.CAT\", 14, 32}, // detected\n{\"SAMPLE3.CAT\", 19, 64}, // UFO flyby whoosh?\n{\"SAMPLE3.CAT\", 3, 32}, // growl\n{\"SAMPLE3.CAT\", 15, 128}, // voice\n{\"SAMPLE3.CAT\", 12, 32}, // beep 1\n{\"SAMPLE3.CAT\", 18, 32}, // takeoff\n{\"SAMPLE3.CAT\", 20, 32}  // another takeoff/landing sound?? if it exists?\n};\n\n\n\n// an attempt at a mix of (subjectively) the best sounds from the two versions\n// difficult because we can't find a definitive map from old sequence numbers to SAMPLE3.CAT indexes\n// probably only the Steam version of the game comes with both INTRO.CAT and SAMPLE3.CAT\nstatic soundInFile hybridIntroSounds[]=\n{\n{\"SAMPLE3.CAT\", 24, 32}, // machine gun\n{\"SAMPLE3.CAT\", 5, 32},   // plasma rifle\n{\"SAMPLE3.CAT\", 23, 32}, // rifle\n{\"INTRO.CAT\",  3, 32}, // some kind of death noise, urgh?\n{\"INTRO.CAT\", 0x4, 64}, // mutdie\n{\"INTRO.CAT\", 0x5, 64}, // dying alien\n{\"INTRO.CAT\", 0x6, 64}, // another dying alien\n{\"INTRO.CAT\", 0x7, 32}, // ??? ship flying? alien screech?\n{\"SAMPLE3.CAT\", 0x8, 32}, // fscream\n{\"SAMPLE3.CAT\", 11, 32}, // alarm\n{\"SAMPLE3.CAT\", 4, 32}, // gun spinning up?\n{\"INTRO.CAT\", 0xb, 32},  // reload; this one's not even in sample3\n{\"SAMPLE3.CAT\",19, 48},  // whoosh\n{\"INTRO.CAT\", 0xd, 32},  // feet, also not in sample3\n{\"INTRO.CAT\", 0xe, 32},  // low pulsating hum\n{\"SAMPLE3.CAT\", 30, 32}, // energise\n{\"SAMPLE3.CAT\", 21, 32}, // hatch\n{\"INTRO.CAT\", 0x11, 64}, // phizz\n{\"SAMPLE3.CAT\", 13, 32}, // warning\n{\"SAMPLE3.CAT\", 14, 32}, // detected\n{\"SAMPLE3.CAT\", 19, 64}, // UFO flyby whoosh?\n{\"INTRO.CAT\", 0x15, 32}, // growl\n{\"SAMPLE3.CAT\", 15, 128}, // voice\n{\"SAMPLE3.CAT\", 12, 32}, // beep 1\n{\"SAMPLE3.CAT\", 18, 32}, // takeoff\n{\"SAMPLE3.CAT\", 20, 32}  // another takeoff/landing sound?? if it exists?\n};\n\n// sample3: 18 is takeoff, 20 is landing; 19 is flyby whoosh sound, not sure for which craft\n\nstatic soundInFile *introSounds[] =\n{\n\thybridIntroSounds,\n\tintroCatOnlySounds,\n\tsample3CatOnlySounds,\n\t0\n};\n\n\ntypedef struct\n{\n\tint frameNumber;\n\tint sound;\n} introSoundEffect;\n\nstatic introSoundEffect introSoundTrack[] =\n{\n{0, 0x200}, // inserting this to keep the code simple\n{149, 0x11},\n{173, 0x0C},\n{183, 0x0E},\n{205, 0x15},\n{211, 0x201},\n{211, 0x407},\n{223, 0x7},\n{250, 0x1},\n{253, 0x1},\n{255, 0x1},\n{257, 0x1},\n{260, 0x1},\n{261, 0x3},\n{262, 0x1},\n{264, 0x1},\n{268, 0x1},\n{270, 0x1},\n{272, 0x5},\n{272, 0x1},\n{274, 0x1},\n{278, 0x1},\n{280, 0x1},\n{282, 0x8},\n{282, 0x1},\n{284, 0x1},\n{286, 0x1},\n{288, 0x1},\n{290, 0x1},\n{292, 0x6},\n{292, 0x1},\n{296, 0x1},\n{298, 0x1},\n{300, 0x1},\n{302, 0x1},\n{304, 0x1},\n{306, 0x1},\n{308, 0x1},\n{310, 0x1},\n{312, 0x1},\n{378, 0x202},\n{378, 0x9}, // alarm\n{386, 0x9},\n{393, 0x9},\n{399, 0x17}, // bleeps\n{433, 0x17},\n{463, 0x12}, // warning\n{477, 0x12},\n{487, 0x13}, // ufo detected\n{495, 0x16}, // voice\n{501, 0x16},\n{512, 0xd},  // feet -- not in original\n{514, 0xd},  // feet -- not in original\n{522, 0x0B}, // rifle grab\n{523, 0xd},  // feet -- not in original\n{525, 0xd},  // feet -- not in original\n{534, 0x18},\n{535, 0x405},\n{560, 0x407},\n{577, 0x14},\n{582, 0x405},\n// {582, 0x18}, // landing! correcting to landing sound!\n{582, 0x19},\n{613, 0x407},\n{615, 0x10},\n{635, 0x14},\n{638, 0x14},\n{639, 0x14},\n{644, 0x2},\n{646, 0x2},\n{648, 0x2},\n{650, 0x2},\n{652, 0x2},\n{654, 0x2},\n{656, 0x2},\n{658, 0x2},\n{660, 0x2},\n{662, 0x2},\n{664, 0x2},\n{666, 0x2},\n{668, 0x401},\n{681, 0x406},\n{687, 0x402},\n{689, 0x407},\n{694, 0x0A},\n{711, 0x407},\n{711, 0x0},\n{714, 0x0},\n{716, 0x4},\n{717, 0x0},\n{720, 0x0},\n{723, 0x0},\n{726, 0x5},\n{726, 0x0},\n{729, 0x0},\n{732, 0x0},\n{735, 0x0},\n{738, 0x0},\n{741, 0x0},\n{742, 0x6},\n{744, 0x0},\n{747, 0x0},\n{750, 0x0},\n{753, 0x0},\n{756, 0x0},\n{759, 0x0},\n{762, 0x0},\n{765, 0x0},\n{768, 0x0},\n{771, 0x0},\n{774, 0x0},\n{777, 0x0},\n{780, 0x0},\n{783, 0x0},\n{786, 0x0},\n{790, 0x15},\n{790, 0x15},\n{807, 0x2},\n{810, 0x2},\n{812, 0x2},\n{814, 0x2},\n{816, 0x0},\n{819, 0x0},\n{822, 0x0},\n{824, 0x40A},\n{824, 0x5},\n{827, 0x6},\n{835, 0x0F},\n{841, 0x0F},\n{845, 0x0F},\n{855, 0x407},\n{879, 0x0C},\n{65535, 0x0FFFF}\n};\n\n\nstatic struct AudioSequence\n{\n\tMod *mod;\n\tMusic *m;\n\tSound *s;\n\tint trackPosition;\n\tFlcPlayer *_flcPlayer;\n\n\tAudioSequence(Mod *_mod, FlcPlayer *flcPlayer) : mod(_mod), m(0), s(0), trackPosition(0), _flcPlayer(flcPlayer)\n\t{ }\n\n\tvoid operator()()\n\t{\n\t\twhile (_flcPlayer->getFrameCount() >= introSoundTrack[trackPosition].frameNumber)\n\t\t{\n\t\t\tint command = introSoundTrack[trackPosition].sound;\n\n\t\t\tif (command & 0x200)\n\t\t\t{\n#ifndef __NO_MUSIC\n\t\t\t\tswitch(command)\n\t\t\t\t{\n\t\t\t\tcase 0x200:\n\t\t\t\t\tLog(LOG_DEBUG) << \"Playing gmintro1\";\n\t\t\t\t\tm = mod->getMusic(\"GMINTRO1\");\n\t\t\t\t\tm->play(1);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x201:\n\t\t\t\t\tLog(LOG_DEBUG) << \"Playing gmintro2\";\n\t\t\t\t\tm = mod->getMusic(\"GMINTRO2\");\n\t\t\t\t\tm->play(1);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x202:\n\t\t\t\t\tLog(LOG_DEBUG) << \"Playing gmintro3\";\n\t\t\t\t\tm = mod->getMusic(\"GMINTRO3\");\n\t\t\t\t\tm->play(1);\n\t\t\t\t\t//Mix_HookMusicFinished(_FlcPlayer::stop);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n#endif\n\t\t\t}\n\t\t\telse if (command & 0x400)\n\t\t\t{\n\t\t\t\tint newSpeed = (command & 0xff);\n\t\t\t\t_flcPlayer->setHeaderSpeed(newSpeed);\n\t\t\t\tLog(LOG_DEBUG) << \"Frame delay now: \" << newSpeed;\n\t\t\t}\n\t\t\telse if (command <= 0x19)\n\t\t\t{\n\t\t\t\tfor (soundInFile **sounds = introSounds; *sounds; ++sounds) // try hybrid sound set, then intro.cat or sample3.cat alone\n\t\t\t\t{\n\t\t\t\t\tsoundInFile *sf = (*sounds) + command;\n\t\t\t\t\tint channel = trackPosition % 4; // use at most four channels to play sound effects\n\t\t\t\t\tdouble ratio = (double)Options::soundVolume / MIX_MAX_VOLUME;\n\t\t\t\t\tLog(LOG_DEBUG) << \"playing: \" << sf->catFile << \":\" << sf->sound << \" for index \" << command;\n\t\t\t\t\ts = mod->getSound(sf->catFile, sf->sound/*, false*/);\n\t\t\t\t\tif (s)\n\t\t\t\t\t{\n\t\t\t\t\t\ts->play(channel);\n\t\t\t\t\t\tMix_Volume(channel, sf->volume * ratio);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\telse Log(LOG_DEBUG) << \"Couldn't play \" << sf->catFile << \":\" << sf->sound;\n\t\t\t\t}\n\t\t\t}\n\t\t\t++trackPosition;\n\t\t}\n\n\t}\n} *audioSequence = NULL;\n\n\nstatic void audioHandler()\n{\n\t(*audioSequence)();\n}\n\nvoid VideoState::init()\n{\n\tState::init();\n\n\tbool wasLetterboxed = CutsceneState::initDisplay();\n\n\tbool ufoIntroSoundFileDosExists = false;\n\tbool ufoIntroSoundFileWinExists = false;\n\tint prevMusicVol = Options::musicVolume;\n\tint prevSoundVol = Options::soundVolume;\n\tif (_useUfoAudioSequence)\n\t{\n\t\tconst auto& soundDir = FileMap::getVFolderContents(\"SOUND\");\n\t\tufoIntroSoundFileDosExists = soundDir.end() != soundDir.find(\"intro.cat\");\n\t\tufoIntroSoundFileWinExists = soundDir.end() != soundDir.find(\"sample3.cat\");\n\n\t\tif (!ufoIntroSoundFileDosExists && !ufoIntroSoundFileWinExists)\n\t\t{\n\t\t\t_useUfoAudioSequence = false;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// ensure user can hear both music and sound effects for the\n\t\t\t// vanilla intro sequence\n\t\t\tOptions::musicVolume = Options::soundVolume = std::max(prevMusicVol, prevSoundVol);\n\t\t\t_game->setVolume(Options::soundVolume, Options::musicVolume, -1);\n\t\t}\n\t}\n\t_game->getCursor()->setVisible(false);\n\n\tint dx = (Options::baseXResolution - Screen::ORIGINAL_WIDTH) / 2;\n\tint dy = (Options::baseYResolution - Screen::ORIGINAL_HEIGHT) / 2;\n\n\t// We can only do a fade out in 8bpp, otherwise instantly end it\n\tbool fade = (_game->getScreen()->getSurface()->format->BitsPerPixel == 8);\n\tconst int FADE_DELAY = 45;\n\tconst int FADE_STEPS = 20;\n\n\tFlcPlayer *flcPlayer = NULL;\n\tsize_t audioCounter = 0;\n\tfor (const auto& videoFileName : *_videos)\n\t{\n\t\tbool useInternalAudio = true;\n\t\tif (!_tracks->empty() && _tracks->size() > audioCounter && _game->getMod()->getMusic(_tracks->at(audioCounter)))\n\t\t{\n\t\t\t_game->getMod()->getMusic(_tracks->at(audioCounter))->play(0);\n\t\t\tuseInternalAudio = false;\n\t\t}\n\t\taudioCounter++;\n\n\t\tif (!FileMap::fileExists(videoFileName))\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (!flcPlayer)\n\t\t{\n\t\t\tflcPlayer = new FlcPlayer();\n\t\t}\n\n\t\tif (_useUfoAudioSequence)\n\t\t{\n\t\t\taudioSequence = new AudioSequence(_game->getMod(), flcPlayer);\n\t\t}\n\n\t\tflcPlayer->init(videoFileName.c_str(),\n\t\t\t _useUfoAudioSequence ? &audioHandler : NULL,\n\t\t\t _game, useInternalAudio, dx, dy);\n\t\tflcPlayer->play(_useUfoAudioSequence);\n\t\tif (_useUfoAudioSequence)\n\t\t{\n\t\t\tflcPlayer->delay(10000);\n\t\t\tdelete audioSequence;\n\t\t\taudioSequence = NULL;\n\t\t}\n\t\tflcPlayer->deInit();\n\n\t\tif (flcPlayer->wasSkipped())\n\t\t{\n\t\t\tfade = false;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (flcPlayer)\n\t{\n\t\tdelete flcPlayer;\n\t}\n\n#ifndef __NO_MUSIC\n\t// fade out!\n\tif (fade)\n\t{\n\t\tMix_FadeOutChannel(-1, FADE_DELAY * FADE_STEPS);\n\t\t// SDL_Mixer has trouble with native midi and volume on windows,\n\t\t// which is the most likely use case, so f@%# it.\n\t\tif (Mix_GetMusicType(0) != MUS_MID)\n\t\t{\n\t\t\tMix_FadeOutMusic(FADE_DELAY * FADE_STEPS);\n\t\t\tfunc_fade();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tMix_HaltMusic();\n\t\t}\n\t}\n\telse\n\t{\n\t\tMix_HaltChannel(-1);\n\t\tMix_HaltMusic();\n\t}\n#endif\n\n\tif (fade)\n\t{\n\t\tSDL_Color pal[256];\n\t\tSDL_Color pal2[256];\n\t\tmemcpy(pal, _game->getScreen()->getPalette(), sizeof(SDL_Color) * 256);\n\t\tfor (int i = FADE_STEPS; i > 0; --i)\n\t\t{\n\t\t\tSDL_Event event;\n\t\t\tif (SDL_PollEvent(&event) && event.type == SDL_KEYDOWN) break;\n\t\t\tfor (int color = 0; color < 256; ++color)\n\t\t\t{\n\t\t\t\tpal2[color].r = (((int)pal[color].r) * i) / 20;\n\t\t\t\tpal2[color].g = (((int)pal[color].g) * i) / 20;\n\t\t\t\tpal2[color].b = (((int)pal[color].b) * i) / 20;\n\t\t\t\tpal2[color].unused = pal[color].unused;\n\t\t\t}\n\t\t\t_game->getScreen()->setPalette(pal2, 0, 256, true);\n\t\t\t_game->getScreen()->flip();\n\t\t\tSDL_Delay(FADE_DELAY);\n\t\t}\n\t}\n\t_game->getScreen()->clear();\n\t_game->getScreen()->flip();\n\n\tif (_useUfoAudioSequence)\n\t{\n\t\tOptions::musicVolume = prevMusicVol;\n\t\tOptions::soundVolume = prevSoundVol;\n\t\t_game->setVolume(Options::soundVolume, Options::musicVolume, Options::uiVolume);\n\t}\n\n#ifndef __NO_MUSIC\n\tSound::stop();\n\tMusic::stop();\n#endif\n\n\t_game->getCursor()->setVisible(true);\n\tCutsceneState::resetDisplay(wasLetterboxed);\n\t_game->popState();\n}\n\n}\n"
  },
  {
    "path": "src/Menu/VideoState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Shows video cinematics.\n */\nclass VideoState : public State\n{\nprivate:\n\tconst std::vector<std::string> *_videos, *_tracks;\n\tbool _useUfoAudioSequence;\npublic:\n\t/// Creates the Intro state.\n\tVideoState(const std::vector<std::string> *videos, const std::vector<std::string> *tracks, bool useUfoAudioSequence);\n\t/// Cleans up the Intro state.\n\t~VideoState();\n\t/// Plays the video\n\tvoid init() override;\n};\n\n}\n"
  },
  {
    "path": "src/Mod/AlienDeployment.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"AlienDeployment.h\"\n#include \"MapScript.h\"\n#include \"../Engine/RNG.h\"\n#include \"../Mod/Mod.h\"\n#include \"../fmath.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Creates a blank ruleset for a certain\n * type of deployment data.\n * @param type String defining the type.\n */\nAlienDeployment::AlienDeployment(const std::string &type) :\n\t_type(type), _missionBountyItemCount(1), _bughuntMinTurn(0), _forcePercentageOutsideUfo(false),\n\t_width(0), _length(0), _height(0), _civilians(0), _ignoreLivingCivilians(false), _markCiviliansAsVIP(false), _civilianSpawnNodeRank(0),\n\t_shade(-1), _minShade(-1), _maxShade(-1), _finalDestination(false), _isAlienBase(false), _isHidden(false), _fakeUnderwaterSpawnChance(0),\n\t_alert(\"STR_ALIENS_TERRORISE\"), _alertBackground(\"BACK03.SCR\"), _alertDescription(\"\"), _alertSound(-1),\n\t_alienBaseDiscoveredMessage(),\n\t_markerName(\"STR_TERROR_SITE\"), _markerIcon(-1), _durationMin(0), _durationMax(0), _minDepth(0), _maxDepth(0),\n\t_genMissionFrequency(0), _genMissionLimit(1000), _genMissionRaceFromAlienBase(true),\n\t_objectiveType(-1), _objectivesRequired(0), _objectiveCompleteScore(0), _objectiveFailedScore(0), _despawnPenalty(0), _abortPenalty(0), _points(0),\n\t_turnLimit(0), _cheatTurn(20), _chronoTrigger(FORCE_LOSE), _keepCraftAfterFailedMission(false), _allowObjectiveRecovery(false), _escapeType(ESCAPE_NONE), _vipSurvivalPercentage(0),\n\t_baseDetectionRange(0), _baseDetectionChance(100), _huntMissionMaxFrequency(60), _huntMissionRaceFromAlienBase(true),\n\t_resetAlienBaseAgeAfterUpgrade(false), _resetAlienBaseAge(false), _noWeaponPile(false)\n{\n}\n\n/**\n *\n */\nAlienDeployment::~AlienDeployment()\n{\n\tfor (auto& pair : _huntMissionDistribution)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _alienBaseUpgrades)\n\t{\n\t\tdelete pair.second;\n\t}\n}\n\n/**\n * Loads the Deployment from a YAML file.\n * @param node YAML node.\n * @param mod Mod for the deployment.\n */\nvoid AlienDeployment::load(const YAML::YamlNodeReader& node, Mod *mod)\n{\n\tconst auto& reader = node.useIndex();\n\tif (const auto& parent = reader[\"refNode\"])\n\t{\n\t\tload(parent, mod);\n\t}\n\n\treader.tryRead(\"customUfo\", _customUfo);\n\treader.tryRead(\"enviroEffects\", _enviroEffects);\n\treader.tryRead(\"startingCondition\", _startingCondition);\n\treader.tryRead(\"unlockedResearch\", _unlockedResearchOnSuccess);\n\treader.tryRead(\"unlockedResearchOnFailure\", _unlockedResearchOnFailure);\n\treader.tryRead(\"unlockedResearchOnDespawn\", _unlockedResearchOnDespawn);\n\treader.tryRead(\"counterSuccess\", _counterSuccess);\n\treader.tryRead(\"counterFailure\", _counterFailure);\n\treader.tryRead(\"counterDespawn\", _counterDespawn);\n\treader.tryRead(\"counterAll\", _counterAll);\n\treader.tryRead(\"decreaseCounterSuccess\", _decreaseCounterSuccess);\n\treader.tryRead(\"decreaseCounterFailure\", _decreaseCounterFailure);\n\treader.tryRead(\"decreaseCounterDespawn\", _decreaseCounterDespawn);\n\treader.tryRead(\"decreaseCounterAll\", _decreaseCounterAll);\n\treader.tryRead(\"missionBountyItem\", _missionBountyItem);\n\treader.tryRead(\"missionBountyItemCount\", _missionBountyItemCount);\n\treader.tryRead(\"bughuntMinTurn\", _bughuntMinTurn);\n\treader.tryRead(\"forcePercentageOutsideUfo\", _forcePercentageOutsideUfo);\n\treader.tryRead(\"data\", _data);\n\treader.tryRead(\"reinforcements\", _reinforcements);\n\treader.tryRead(\"width\", _width);\n\treader.tryRead(\"length\", _length);\n\treader.tryRead(\"height\", _height);\n\treader.tryRead(\"civilians\", _civilians);\n\treader.tryRead(\"ignoreLivingCivilians\", _ignoreLivingCivilians);\n\treader.tryRead(\"markCiviliansAsVIP\", _markCiviliansAsVIP);\n\treader.tryRead(\"civilianSpawnNodeRank\", _civilianSpawnNodeRank);\n\tmod->loadUnorderedNamesToInt(_type, _civiliansByType, reader[\"civiliansByType\"]);\n\treader.tryRead(\"terrains\", _terrains);\n\treader.tryRead(\"shade\", _shade);\n\treader.tryRead(\"minShade\", _minShade);\n\treader.tryRead(\"maxShade\", _maxShade);\n\treader.tryRead(\"nextStage\", _nextStage);\n\treader.tryRead(\"race\", _race);\n\treader.tryRead(\"randomRace\", _randomRaces);\n\treader.tryRead(\"finalDestination\", _finalDestination);\n\treader.tryRead(\"winCutscene\", _winCutscene);\n\treader.tryRead(\"loseCutscene\", _loseCutscene);\n\treader.tryRead(\"abortCutscene\", _abortCutscene);\n\treader.tryRead(\"script\", _mapScript);\n\treader.tryRead(\"mapScripts\", _mapScripts);\n\treader.tryRead(\"alert\", _alert);\n\treader.tryRead(\"alertBackground\", _alertBackground);\n\treader.tryRead(\"alertDescription\", _alertDescription);\n\tmod->loadSoundOffset(_type, _alertSound, reader[\"alertSound\"], \"GEO.CAT\");\n\treader.tryRead(\"briefing\", _briefingData);\n\treader.tryRead(\"alienBaseDiscoveredMessage\", _alienBaseDiscoveredMessage);\n\treader.tryRead(\"markerName\", _markerName);\n\tif (reader[\"markerIcon\"])\n\t{\n\t\t_markerIcon = mod->getOffset(reader[\"markerIcon\"].readVal<int>(), 8);\n\t}\n\tif (reader[\"depth\"])\n\t{\n\t\t_minDepth = reader[\"depth\"][0].readVal(_minDepth);\n\t\t_maxDepth = reader[\"depth\"][1].readVal(_maxDepth);\n\t}\n\tif (reader[\"duration\"])\n\t{\n\t\t_durationMin = reader[\"duration\"][0].readVal(_durationMin);\n\t\t_durationMax = reader[\"duration\"][1].readVal(_durationMax);\n\t}\n\treader.tryRead(\"music\", _music);\n\treader.tryRead(\"objectiveType\", _objectiveType);\n\treader.tryRead(\"objectivesRequired\", _objectivesRequired);\n\treader.tryRead(\"objectivePopup\", _objectivePopup);\n\n\tif (reader[\"objectiveComplete\"])\n\t{\n\t\t_objectiveCompleteText = reader[\"objectiveComplete\"][0].readVal(_objectiveCompleteText);\n\t\t_objectiveCompleteScore = reader[\"objectiveComplete\"][1].readVal(_objectiveCompleteScore);\n\t}\n\tif (reader[\"objectiveFailed\"])\n\t{\n\t\t_objectiveFailedText = reader[\"objectiveFailed\"][0].readVal(_objectiveFailedText);\n\t\t_objectiveFailedScore = reader[\"objectiveFailed\"][1].readVal(_objectiveFailedScore);\n\t}\n\treader.tryRead(\"missionCompleteText\", _missionCompleteText);\n\treader.tryRead(\"missionFailedText\", _missionFailedText);\n\tif (reader[\"successEvents\"])\n\t{\n\t\t_successEvents.load(reader[\"successEvents\"]);\n\t}\n\tif (reader[\"despawnEvents\"])\n\t{\n\t\t_despawnEvents.load(reader[\"despawnEvents\"]);\n\t}\n\tif (reader[\"failureEvents\"])\n\t{\n\t\t_failureEvents.load(reader[\"failureEvents\"]);\n\t}\n\treader.tryRead(\"despawnPenalty\", _despawnPenalty);\n\treader.tryRead(\"abortPenalty\", _abortPenalty);\n\treader.tryRead(\"points\", _points);\n\treader.tryRead(\"cheatTurn\", _cheatTurn);\n\treader.tryRead(\"turnLimit\", _turnLimit);\n\treader.tryRead(\"chronoTrigger\", _chronoTrigger);\n\treader.tryRead(\"alienBase\", _isAlienBase);\n\treader.tryRead(\"isHidden\", _isHidden);\n\treader.tryRead(\"fakeUnderwaterSpawnChance\", _fakeUnderwaterSpawnChance);\n\treader.tryRead(\"keepCraftAfterFailedMission\", _keepCraftAfterFailedMission);\n\treader.tryRead(\"allowObjectiveRecovery\", _allowObjectiveRecovery);\n\treader.tryRead(\"escapeType\", _escapeType);\n\treader.tryRead(\"vipSurvivalPercentage\", _vipSurvivalPercentage);\n\tif (reader[\"genMission\"])\n\t{\n\t\t_genMission.load(reader[\"genMission\"]);\n\t}\n\treader.tryRead(\"genMissionFreq\", _genMissionFrequency);\n\treader.tryRead(\"genMissionLimit\", _genMissionLimit);\n\treader.tryRead(\"genMissionRaceFromAlienBase\", _genMissionRaceFromAlienBase);\n\n\treader.tryRead(\"baseSelfDestructCode\", _baseSelfDestructCode);\n\treader.tryRead(\"baseDetectionRange\", _baseDetectionRange);\n\treader.tryRead(\"baseDetectionChance\", _baseDetectionChance);\n\treader.tryRead(\"huntMissionMaxFrequency\", _huntMissionMaxFrequency);\n\treader.tryRead(\"huntMissionRaceFromAlienBase\", _huntMissionRaceFromAlienBase);\n\tfor (const auto& weights : reader[\"huntMissionWeights\"].children())\n\t{\n\t\tWeightedOptions *nw = new WeightedOptions();\n\t\tnw->load(weights);\n\t\t_huntMissionDistribution.push_back(std::make_pair(weights.readKey<size_t>(0), nw));\n\t}\n\tfor (const auto& weights : reader[\"alienBaseUpgrades\"].children())\n\t{\n\t\tWeightedOptions *nw = new WeightedOptions();\n\t\tnw->load(weights);\n\t\t_alienBaseUpgrades.push_back(std::make_pair(weights.readKey<size_t>(0), nw));\n\t}\n\treader.tryRead(\"resetAlienBaseAgeAfterUpgrade\", _resetAlienBaseAgeAfterUpgrade);\n\treader.tryRead(\"resetAlienBaseAge\", _resetAlienBaseAge);\n\treader.tryRead(\"upgradeRace\", _upgradeRace);\n\treader.tryRead(\"alienRaceEvolution\", _alienRaceEvolution);\n\tif (!_alienRaceEvolution.empty())\n\t{\n\t\tstd::stable_sort(_alienRaceEvolution.begin(), _alienRaceEvolution.end(),\n\t\t\t[](std::tuple<size_t, std::string, std::string> a, std::tuple<size_t, std::string, std::string> b)\n\t\t\t{\n\t\t\t\treturn std::get<0>(a) > std::get<0>(b);\n\t\t\t}\n\t\t);\n\t}\n\treader.tryRead(\"noWeaponPile\", _noWeaponPile);\n}\n\n/**\n * Returns the language string that names\n * this deployment. Each deployment type has a unique name.\n * @return Deployment name.\n */\nconst std::string& AlienDeployment::getType() const\n{\n\treturn _type;\n}\n\n/**\n * Returns the enviro effects name for this mission.\n * @return String ID for the enviro effects.\n */\nconst std::string& AlienDeployment::getEnviroEffects() const\n{\n\treturn _enviroEffects;\n}\n\n/**\n * Returns the starting condition name for this mission.\n * @return String ID for starting condition.\n */\nconst std::string& AlienDeployment::getStartingCondition() const\n{\n\treturn _startingCondition;\n}\n\n/**\n* Returns the item to be recovered/given after a successful mission.\n* @return String ID for the item.\n*/\nstd::string AlienDeployment::getMissionBountyItem() const\n{\n\treturn _missionBountyItem;\n}\n\n/**\n* Gets the bug hunt mode minimum turn requirement (default = 0 = not used).\n* @return Bug hunt min turn number.\n*/\nint AlienDeployment::getBughuntMinTurn() const\n{\n\treturn _bughuntMinTurn;\n}\n\n/**\n * Gets a pointer to the data.\n * @return Pointer to the data.\n */\nconst std::vector<DeploymentData>* AlienDeployment::getDeploymentData() const\n{\n\treturn &_data;\n}\n\n/**\n * Gets the highest used alien rank.\n * @return Highest used alien rank.\n */\nint AlienDeployment::getMaxAlienRank() const\n{\n\tint max = 0;\n\tfor (auto& dd : _data)\n\t{\n\t\tif (dd.alienRank > max)\n\t\t\tmax = dd.alienRank;\n\t}\n\treturn max;\n}\n\n/**\n * Gets a pointer to the reinforcements data.\n * @return Pointer to the reinforcements data.\n */\nconst std::vector<ReinforcementsData>* AlienDeployment::getReinforcementsData() const\n{\n\treturn &_reinforcements;\n}\n\n/**\n * Gets dimensions.\n * @param width Width.\n * @param length Length.\n * @param height Height.\n */\nvoid AlienDeployment::getDimensions(int *width, int *length, int *height) const\n{\n\t*width = _width;\n\t*length = _length;\n\t*height = _height;\n}\n\n/**\n * Gets the number of civilians.\n * @return The number of civilians.\n */\nint AlienDeployment::getCivilians() const\n{\n\treturn _civilians;\n}\n\n/**\n * Gets the number of civilians per type.\n * @return The number of civilians per type.\n */\nconst std::map<std::string, int> &AlienDeployment::getCiviliansByType() const\n{\n\treturn _civiliansByType;\n}\n\n/**\n * Gets the terrain for battlescape generation.\n * @return The terrain.\n */\nstd::vector<std::string> AlienDeployment::getTerrains() const\n{\n\treturn _terrains;\n}\n\n/**\n * Gets the shade level for battlescape generation.\n * @return The shade level.\n */\nint AlienDeployment::getShade() const\n{\n\treturn _shade;\n}\n\n/**\n* Gets the min shade level for battlescape generation.\n* @return The min shade level.\n*/\nint AlienDeployment::getMinShade() const\n{\n\treturn _minShade;\n}\n\n/**\n* Gets the max shade level for battlescape generation.\n* @return The max shade level.\n*/\nint AlienDeployment::getMaxShade() const\n{\n\treturn _maxShade;\n}\n\n/**\n * Gets the next stage of the mission.\n * @return The next stage of the mission.\n */\nstd::string AlienDeployment::getNextStage() const\n{\n\treturn _nextStage;\n}\n\n/**\n * Gets the race to use on the next stage of the mission.\n * @return The race for the next stage of the mission.\n */\nstd::string AlienDeployment::getRace() const\n{\n\tif (!_randomRaces.empty())\n\t{\n\t\treturn _randomRaces[RNG::generate(0, _randomRaces.size() - 1)];\n\t}\n\treturn _race;\n}\n\n/**\n * Gets the script to use to generate a mission of this type.\n * @return The script to use to generate a mission of this type.\n */\nconst std::string& AlienDeployment::getRandomMapScript() const\n{\n\tif (!_mapScripts.empty())\n\t{\n\t\tsize_t pick = RNG::generate(0, _mapScripts.size() - 1);\n\t\treturn _mapScripts[pick];\n\t}\n\treturn _mapScript;\n}\n\n/**\n * Does any map script use globe terrain?\n * @return 1 = yes, 0 = no, -1 = no map script found.\n */\nint AlienDeployment::hasTextureBasedScript(const Mod* mod) const\n{\n\tint ret = -1;\n\t// iterate _mapScripts\n\tfor (const std::string& script : _mapScripts)\n\t{\n\t\tauto* vec = mod->getMapScript(script);\n\t\tif (vec)\n\t\t{\n\t\t\tret = 0;\n\t\t\t// iterate map script commands\n\t\t\tfor (auto* ms : *vec)\n\t\t\t{\n\t\t\t\t// iterate terrains\n\t\t\t\tfor (const std::string& terrain : ms->getRandomAlternateTerrain())\n\t\t\t\t{\n\t\t\t\t\tif (terrain == \"globeTerrain\" || terrain == \"baseTerrain\")\n\t\t\t\t\t{\n\t\t\t\t\t\treturn 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// iterate vertical levels\n\t\t\t\tfor (auto& vlevel : ms->getVerticalLevels())\n\t\t\t\t{\n\t\t\t\t\tif (vlevel.levelTerrain == \"globeTerrain\" || vlevel.levelTerrain == \"baseTerrain\")\n\t\t\t\t\t{\n\t\t\t\t\t\treturn 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t// check also _mapScript\n\t{\n\t\tauto* vec = mod->getMapScript(_mapScript);\n\t\tif (vec)\n\t\t{\n\t\t\tret = 0;\n\t\t\t// iterate map script commands\n\t\t\tfor (auto* ms : *vec)\n\t\t\t{\n\t\t\t\t// iterate terrains\n\t\t\t\tfor (const std::string& terrain : ms->getRandomAlternateTerrain())\n\t\t\t\t{\n\t\t\t\t\tif (terrain == \"globeTerrain\" || terrain == \"baseTerrain\")\n\t\t\t\t\t{\n\t\t\t\t\t\treturn 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// iterate vertical levels\n\t\t\t\tfor (auto& vlevel : ms->getVerticalLevels())\n\t\t\t\t{\n\t\t\t\t\tif (vlevel.levelTerrain == \"globeTerrain\" || vlevel.levelTerrain == \"baseTerrain\")\n\t\t\t\t\t{\n\t\t\t\t\t\treturn 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t}\n\treturn ret;\n}\n\n/**\n * Gets if winning this mission completes the game.\n * @return if winning this mission completes the game.\n */\nbool AlienDeployment::isFinalDestination() const\n{\n\treturn _finalDestination;\n}\n\n/**\n * Gets the cutscene to play when the mission is won.\n * @return the cutscene to play when the mission is won.\n */\nstd::string AlienDeployment::getWinCutscene() const\n{\n\treturn _winCutscene;\n}\n\n/**\n * Gets the cutscene to play when the mission is lost.\n * @return the cutscene to play when the mission is lost.\n */\nstd::string AlienDeployment::getLoseCutscene() const\n{\n\treturn _loseCutscene;\n}\n\n/**\n* Gets the cutscene to play when the mission is aborted.\n* @return the cutscene to play when the mission is aborted.\n*/\nstd::string AlienDeployment::getAbortCutscene() const\n{\n\treturn _abortCutscene;\n}\n\n/**\n * Gets the alert message displayed when this mission spawns.\n * @return String ID for the message.\n */\nstd::string AlienDeployment::getAlertMessage() const\n{\n\treturn _alert;\n}\n\n/**\n* Gets the alert background displayed when this mission spawns.\n* @return Sprite ID for the background.\n*/\nstd::string AlienDeployment::getAlertBackground() const\n{\n\treturn _alertBackground;\n}\n\n/**\n* Gets the alert description (displayed when clicking on [Info] button in TargetInfo).\n* @return String ID for the description.\n*/\nstd::string AlienDeployment::getAlertDescription() const\n{\n\treturn _alertDescription;\n}\n\n/**\n* Gets the alert sound (played when mission detected screen pops up).\n* @return ID for the sound.\n*/\nint AlienDeployment::getAlertSound() const\n{\n\treturn _alertSound;\n}\n\n/**\n * Gets the briefing data for this mission type.\n * @return data for the briefing window to use.\n */\nBriefingData AlienDeployment::getBriefingData() const\n{\n\treturn _briefingData;\n}\n\n/**\n * Returns the globe marker name for this mission.\n * @return String ID for marker name.\n */\nstd::string AlienDeployment::getMarkerName() const\n{\n\treturn _markerName;\n}\n\n/**\n * Returns the globe marker icon for this mission.\n * @return Marker sprite, -1 if none.\n */\nint AlienDeployment::getMarkerIcon() const\n{\n\treturn _markerIcon;\n}\n\n/**\n * Returns the minimum duration for this mission type.\n * @return Duration in hours.\n */\nint AlienDeployment::getDurationMin() const\n{\n\treturn _durationMin;\n}\n\n/**\n * Returns the maximum duration for this mission type.\n * @return Duration in hours.\n */\nint AlienDeployment::getDurationMax() const\n{\n\treturn _durationMax;\n}\n\n/**\n * Gets The list of musics this deployment has to choose from.\n * @return The list of track names.\n */\nconst std::vector<std::string> &AlienDeployment::getMusic() const\n{\n\treturn _music;\n}\n\n/**\n * Gets The minimum depth for this deployment.\n * @return The minimum depth.\n */\nint AlienDeployment::getMinDepth() const\n{\n\treturn _minDepth;\n}\n\n/**\n * Gets The maximum depth for this deployment.\n * @return The maximum depth.\n */\nint AlienDeployment::getMaxDepth() const\n{\n\treturn _maxDepth;\n}\n\n/**\n * Gets the target type for this mission (ie: alien control consoles and synomium devices).\n * @return the target type for this mission.\n */\nint AlienDeployment::getObjectiveType() const\n{\n\treturn _objectiveType;\n}\n\n/**\n * Gets the number of objectives required by this mission.\n * @return the number of objectives required.\n */\nint AlienDeployment::getObjectivesRequired() const\n{\n\treturn _objectivesRequired;\n}\n\n/**\n * Gets the string name for the popup to splash when the objective conditions are met.\n * @return the string to pop up.\n */\nconst std::string &AlienDeployment::getObjectivePopup() const\n{\n\treturn _objectivePopup;\n}\n\n/**\n * Fills out the variables associated with mission success, and returns if those variables actually contain anything.\n * @param &text a reference to the text we wish to alter.\n * @param &score a reference to the score we wish to alter.\n * @param &missionText a reference to the custom mission text we wish to alter.\n * @return if there is anything worthwhile processing.\n */\nbool AlienDeployment::getObjectiveCompleteInfo(std::string &text, int &score, std::string &missionText) const\n{\n\ttext = _objectiveCompleteText;\n\tscore = _objectiveCompleteScore;\n\tmissionText = _missionCompleteText;\n\treturn !text.empty();\n}\n\n/**\n * Fills out the variables associated with mission failure, and returns if those variables actually contain anything.\n * @param &text a reference to the text we wish to alter.\n * @param &score a reference to the score we wish to alter.\n * @param &missionText a reference to the custom mission text we wish to alter.\n * @return if there is anything worthwhile processing.\n */\nbool AlienDeployment::getObjectiveFailedInfo(std::string &text, int &score, std::string &missionText) const\n{\n\ttext = _objectiveFailedText;\n\tscore = _objectiveFailedScore;\n\tmissionText = _missionFailedText;\n\treturn !text.empty();\n}\n\n/**\n * Gets the score penalty XCom receives for letting this mission despawn.\n * @return the score for letting this site despawn.\n */\nint AlienDeployment::getDespawnPenalty() const\n{\n\treturn _despawnPenalty;\n}\n\n/**\n * Gets the score penalty against XCom for this site existing.\n * This penalty is applied half-hourly for sites and daily for bases.\n * @return the number of points the aliens get per half hour.\n */\nint AlienDeployment::getPoints() const\n{\n\treturn _points;\n}\n\n/**\n * Gets the maximum number of turns we have before this mission ends.\n * @return the turn limit.\n */\nint AlienDeployment::getTurnLimit() const\n{\n\treturn _turnLimit;\n}\n\n/**\n * Gets the action type to perform when the timer expires.\n * @return the action type to perform.\n */\nChronoTrigger AlienDeployment::getChronoTrigger() const\n{\n\treturn _chronoTrigger;\n}\n\n/**\n * Gets the turn at which the players become exposed to the AI.\n * @return the turn to start cheating.\n */\nint AlienDeployment::getCheatTurn() const\n{\n\treturn _cheatTurn;\n}\n\nbool AlienDeployment::isAlienBase() const\n{\n\treturn _isAlienBase;\n}\n\nstd::string AlienDeployment::chooseGenMissionType() const\n{\n\treturn _genMission.choose();\n}\n\nint AlienDeployment::getGenMissionFrequency() const\n{\n\treturn _genMissionFrequency;\n}\n\nint AlienDeployment::getGenMissionLimit() const\n{\n\treturn _genMissionLimit;\n}\n\nbool AlienDeployment::isGenMissionRaceFromAlienBase() const\n{\n\treturn _genMissionRaceFromAlienBase;\n}\n\nbool AlienDeployment::keepCraftAfterFailedMission() const\n{\n\treturn _keepCraftAfterFailedMission;\n}\n\nbool AlienDeployment::allowObjectiveRecovery() const\n{\n\treturn _allowObjectiveRecovery;\n}\n\nEscapeType AlienDeployment::getEscapeType() const\n{\n\treturn _escapeType;\n}\n\n/**\n * Chooses one of the available missions.\n * @param monthsPassed The number of months that have passed in the game world.\n * @return The string id of the hunt mission.\n */\nstd::string AlienDeployment::generateHuntMission(const size_t monthsPassed) const\n{\n\tstd::vector<std::pair<size_t, WeightedOptions*> >::const_reverse_iterator rw;\n\trw = _huntMissionDistribution.rbegin();\n\twhile (monthsPassed < rw->first)\n\t\t++rw;\n\treturn rw->second->choose();\n}\n\n/**\n * Returns the Alien Base self destruct code.\n * @return String ID of the corresponding research topic.\n */\nconst std::string& AlienDeployment::getBaseSelfDestructCode() const\n{\n\treturn _baseSelfDestructCode;\n}\n\n/**\n * Gets the detection range of an alien base.\n * @return Detection range.\n */\ndouble AlienDeployment::getBaseDetectionRange() const\n{\n\treturn _baseDetectionRange;\n}\n\n/**\n * Gets the chance of an alien base to detect a player's craft (once every 10 minutes).\n * @return Chance in percent.\n */\nint AlienDeployment::getBaseDetectionChance() const\n{\n\treturn _baseDetectionChance;\n}\n\n/**\n * Gets the maximum frequency of hunt missions generated by an alien base.\n * @return The frequency (in minutes).\n */\nint AlienDeployment::getHuntMissionMaxFrequency() const\n{\n\treturn _huntMissionMaxFrequency;\n}\n\n/**\n * Should the hunt missions inherit the race from the alien base, or take it from their own 'raceWeights'?\n * @return True, if the race is taken from the alien base (vanilla behavior).\n */\nbool AlienDeployment::isHuntMissionRaceFromAlienBase() const\n{\n\treturn _huntMissionRaceFromAlienBase;\n}\n\n/**\n * Chooses one of the available deployments.\n * @param baseAgeInMonths The number of months that have passed in the game world since the alien base spawned.\n * @return The string id of the deployment.\n */\nstd::string AlienDeployment::generateAlienBaseUpgrade(const size_t baseAgeInMonths) const\n{\n\tif (_alienBaseUpgrades.empty())\n\t\treturn \"\";\n\n\tstd::vector<std::pair<size_t, WeightedOptions*> >::const_reverse_iterator rw;\n\trw = _alienBaseUpgrades.rbegin();\n\twhile (baseAgeInMonths < rw->first)\n\t\t++rw;\n\treturn rw->second->choose();\n}\n\n// helper overloads for deserialization-only\nbool read(ryml::ConstNodeRef const& n, ItemSet* val)\n{\n\tYAML::YamlNodeReader reader(n);\n\treader.tryReadVal(val->items);\n\treturn true;\n}\n\nbool read(ryml::ConstNodeRef const& n, DeploymentData* val)\n{\n\tYAML::YamlNodeReader reader(n);\n\treader.tryRead(\"alienRank\", val->alienRank);\n\treader.tryRead(\"customUnitType\", val->customUnitType);\n\treader.tryRead(\"lowQty\", val->lowQty);\n\treader.tryRead(\"medQty\", val->medQty);\n\treader.tryRead(\"highQty\", val->highQty);\n\treader.tryRead(\"dQty\", val->dQty);\n\treader.readNode(\"extraQty\", val->extraQty, 0);\n\treader.tryRead(\"percentageOutsideUfo\", val->percentageOutsideUfo);\n\treader.tryRead(\"itemSets\", val->itemSets);\n\treader.tryRead(\"extraRandomItems\", val->extraRandomItems);\n\treturn true;\n}\n\nbool read(ryml::ConstNodeRef const& n, BriefingData* val)\n{\n\tYAML::YamlNodeReader reader(n);\n\treader.tryRead(\"palette\", val->palette);\n\treader.tryRead(\"textOffset\", val->textOffset);\n\treader.tryRead(\"title\", val->title);\n\treader.tryRead(\"desc\", val->desc);\n\treader.tryRead(\"music\", val->music);\n\treader.tryRead(\"cutscene\", val->cutscene);\n\treader.tryRead(\"background\", val->background);\n\treader.tryRead(\"showCraft\", val->showCraft);\n\treader.tryRead(\"showTarget\", val->showTarget);\n\treturn true;\n}\n\nbool read(ryml::ConstNodeRef const& n, ReinforcementsData* val)\n{\n\tYAML::YamlNodeReader reader(n);\n\treader.tryRead(\"type\", val->type);\n\treader.tryRead(\"briefing\", val->briefing);\n\treader.tryRead(\"minDifficulty\", val->minDifficulty);\n\treader.tryRead(\"maxDifficulty\", val->maxDifficulty);\n\treader.tryRead(\"objectiveDestroyed\", val->objectiveDestroyed);\n\treader.tryRead(\"turns\", val->turns);\n\treader.tryRead(\"minTurn\", val->minTurn);\n\treader.tryRead(\"maxTurn\", val->maxTurn);\n\treader.tryRead(\"executionOdds\", val->executionOdds);\n\treader.tryRead(\"maxRuns\", val->maxRuns);\n\treader.tryRead(\"useSpawnNodes\", val->useSpawnNodes);\n\treader.tryRead(\"mapBlockFilterType\", val->mapBlockFilterType);\n\treader.tryRead(\"spawnBlocks\", val->spawnBlocks);\n\treader.tryRead(\"spawnBlockGroups\", val->spawnBlockGroups);\n\treader.tryRead(\"spawnNodeRanks\", val->spawnNodeRanks);\n\treader.tryRead(\"spawnZLevels\", val->spawnZLevels);\n\treader.tryRead(\"randomizeZLevels\", val->randomizeZLevels);\n\treader.tryRead(\"minDistanceFromXcomUnits\", val->minDistanceFromXcomUnits);\n\treader.tryRead(\"maxDistanceFromBorders\", val->maxDistanceFromBorders);\n\treader.tryRead(\"forceSpawnNearFriend\", val->forceSpawnNearFriend);\n\treader.tryRead(\"data\", val->data);\n\treturn true;\n}\n\n}\n"
  },
  {
    "path": "src/Mod/AlienDeployment.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <map>\n#include <vector>\n#include <string>\n#include \"../Engine/Yaml.h\"\n#include \"../Savegame/WeightedOptions.h\"\n\nnamespace OpenXcom\n{\n\nclass RuleTerrain;\nclass Mod;\n\nstruct ItemSet\n{\n\tstd::vector<std::string> items;\n};\n\nstruct DeploymentData\n{\n\tint alienRank;\n\tstd::string customUnitType;\n\tint lowQty, medQty, highQty, dQty, extraQty;\n\tint percentageOutsideUfo;\n\tstd::vector<ItemSet> itemSets, extraRandomItems;\n\tDeploymentData() : alienRank(0), lowQty(0), medQty(0), highQty(0), dQty(0), extraQty(0), percentageOutsideUfo(0) { }\n};\nstruct BriefingData\n{\n\tint palette, textOffset;\n\tstd::string title, desc, music, background, cutscene;\n\tbool showCraft, showTarget;\n\tBriefingData() : palette(0), textOffset(0), music(\"GMDEFEND\"), background(\"BACK16.SCR\"), showCraft(true), showTarget(true) { /*Empty by Design*/ };\n};\nenum MapBlockFilterType : int { MFT_NONE, MFT_BY_MAPSCRIPT, MFT_BY_REINFORCEMENTS, MFT_BY_BOTH_UNION, MFT_BY_BOTH_INTERSECTION };\nstruct ReinforcementsData\n{\n\tstd::string type;\n\tBriefingData briefing;\n\tint minDifficulty = 0;\n\tint maxDifficulty = 4;\n\tbool objectiveDestroyed = false;\n\tstd::vector<int> turns;\n\tint minTurn = 0;\n\tint maxTurn = -1;\n\tint executionOdds = 100;\n\tint maxRuns = -1;\n\tbool useSpawnNodes = true;\n\tMapBlockFilterType mapBlockFilterType = MFT_BY_BOTH_UNION;\n\tstd::vector<std::string> spawnBlocks;\n\tstd::vector<int> spawnBlockGroups;\n\tstd::vector<int> spawnNodeRanks;\n\tstd::vector<int> spawnZLevels;\n\tbool randomizeZLevels = true;\n\tint minDistanceFromXcomUnits = 0;\n\tint maxDistanceFromBorders = 0;\n\tbool forceSpawnNearFriend = true;\n\tstd::vector<DeploymentData> data;\n};\nenum ChronoTrigger { FORCE_LOSE, FORCE_ABORT, FORCE_WIN, FORCE_WIN_SURRENDER };\nenum EscapeType : int { ESCAPE_NONE, ESCAPE_EXIT, ESCAPE_ENTRY, ESCAPE_EITHER };\n/**\n * Represents a specific type of Alien Deployment.\n * Contains constant info about a Alien Deployment like\n * the number of aliens for each alien type and what items they carry\n * (itemset depends on alien technology advancement level 0, 1 or 2).\n * - deployment type can be a craft's name, but also alien base or cydonia.\n * - alienRank is used to check which nodeRanks can be used to deploy this unit\n *   + to match to a specific unit (=race/rank combination) that should be deployed.\n * @sa Node\n */\nclass AlienDeployment\n{\nprivate:\n\tstd::string _type;\n\tstd::string _customUfo;\n\tstd::string _enviroEffects, _startingCondition;\n\tstd::string _unlockedResearchOnSuccess, _unlockedResearchOnFailure, _unlockedResearchOnDespawn;\n\tstd::string _counterSuccess, _counterFailure, _counterDespawn, _counterAll;\n\tstd::string _decreaseCounterSuccess, _decreaseCounterFailure, _decreaseCounterDespawn, _decreaseCounterAll;\n\tstd::string _missionBountyItem;\n\tint _missionBountyItemCount;\n\tint _bughuntMinTurn;\n\tbool _forcePercentageOutsideUfo;\n\tstd::vector<DeploymentData> _data;\n\tstd::vector<ReinforcementsData> _reinforcements;\n\tint _width, _length, _height, _civilians;\n\tbool _ignoreLivingCivilians;\n\tbool _markCiviliansAsVIP;\n\tint _civilianSpawnNodeRank;\n\tstd::map<std::string, int> _civiliansByType;\n\tstd::vector<std::string> _terrains, _music;\n\tint _shade, _minShade, _maxShade;\n\tstd::string _nextStage, _race, _mapScript;\n\tstd::vector<std::string> _mapScripts;\n\tstd::vector<std::string> _randomRaces;\n\tbool _finalDestination, _isAlienBase, _isHidden;\n\tint _fakeUnderwaterSpawnChance;\n\tstd::string _winCutscene, _loseCutscene, _abortCutscene;\n\tstd::string _alert, _alertBackground, _alertDescription;\n\tint _alertSound;\n\tBriefingData _briefingData;\n\tstd::string _alienBaseDiscoveredMessage;\n\tstd::string _markerName, _objectivePopup, _objectiveCompleteText, _objectiveFailedText;\n\tstd::string _missionCompleteText, _missionFailedText;\n\tWeightedOptions _genMission, _successEvents, _failureEvents, _despawnEvents;\n\tint _markerIcon, _durationMin, _durationMax, _minDepth, _maxDepth, _genMissionFrequency, _genMissionLimit;\n\tbool _genMissionRaceFromAlienBase;\n\tint _objectiveType, _objectivesRequired, _objectiveCompleteScore, _objectiveFailedScore, _despawnPenalty, _abortPenalty, _points, _turnLimit, _cheatTurn;\n\tChronoTrigger _chronoTrigger;\n\tbool _keepCraftAfterFailedMission, _allowObjectiveRecovery;\n\tEscapeType _escapeType;\n\tint _vipSurvivalPercentage;\n\tstd::string _baseSelfDestructCode;\n\tint _baseDetectionRange, _baseDetectionChance, _huntMissionMaxFrequency;\n\tbool _huntMissionRaceFromAlienBase;\n\tstd::vector<std::pair<size_t, WeightedOptions*> > _huntMissionDistribution;\n\tstd::vector<std::pair<size_t, WeightedOptions*> > _alienBaseUpgrades;\n\tbool _resetAlienBaseAgeAfterUpgrade, _resetAlienBaseAge;\n\tstd::string _upgradeRace;\n\tstd::vector<std::tuple<size_t, std::string, std::string> > _alienRaceEvolution;\n\tbool _noWeaponPile;\npublic:\n\t/// Creates a blank Alien Deployment ruleset.\n\tAlienDeployment(const std::string &type);\n\t/// Cleans up the Alien Deployment ruleset.\n\t~AlienDeployment();\n\t/// Loads Alien Deployment data from YAML.\n\tvoid load(const YAML::YamlNodeReader& node, Mod *mod);\n\t/// Gets the Alien Deployment's type.\n\tconst std::string& getType() const;\n\t/// Gets the custom UFO name to use for the dummy/blank 'addUFO' mapscript command.\n\tconst std::string& getCustomUfoName() const { return _customUfo; }\n\t/// Gets the Alien Deployment's enviro effects.\n\tconst std::string& getEnviroEffects() const;\n\t/// Gets the Alien Deployment's starting condition.\n\tconst std::string& getStartingCondition() const;\n\t/// Gets the research topic to be unlocked after a successful mission.\n\tconst std::string& getUnlockedResearchOnSuccess() const { return _unlockedResearchOnSuccess; }\n\t/// Gets the research topic to be unlocked after a failed mission.\n\tconst std::string& getUnlockedResearchOnFailure() const { return _unlockedResearchOnFailure; }\n\t/// Gets the research topic to be unlocked after a despawned mission site.\n\tconst std::string& getUnlockedResearchOnDespawn() const { return _unlockedResearchOnDespawn; }\n\t/// Gets the name of a custom counter variable to increase on mission success.\n\tconst std::string& getCounterSuccess() const { return _counterSuccess; }\n\t/// Gets the name of a custom counter variable to increase on mission failure (incl. mission despawn).\n\tconst std::string& getCounterFailure() const { return _counterFailure; }\n\t/// Gets the name of a custom counter variable to increase on mission despawn.\n\tconst std::string& getCounterDespawn() const { return _counterDespawn; }\n\t/// Gets the name of a custom counter variable to increase on any mission result (success, failure and despawn).\n\tconst std::string& getCounterAll() const { return _counterAll; }\n\t/// Gets the name of a custom counter variable to decrease on mission success.\n\tconst std::string& getDecreaseCounterSuccess() const { return _decreaseCounterSuccess; }\n\t/// Gets the name of a custom counter variable to decrease on mission failure (incl. mission despawn).\n\tconst std::string& getDecreaseCounterFailure() const { return _decreaseCounterFailure; }\n\t/// Gets the name of a custom counter variable to decrease on mission despawn.\n\tconst std::string& getDecreaseCounterDespawn() const { return _decreaseCounterDespawn; }\n\t/// Gets the name of a custom counter variable to decrease on any mission result (success, failure and despawn).\n\tconst std::string& getDecreaseCounterAll() const { return _decreaseCounterAll; }\n\t/// Gets the item to be recovered/given after a successful mission.\n\tstd::string getMissionBountyItem() const;\n\t/// Gets the number of items to be recovered/given after a successful mission.\n\tint getMissionBountyItemCount() const { return _missionBountyItemCount; }\n\t/// Gets the bug hunt mode minimum turn requirement (default = 0 = not used).\n\tint getBughuntMinTurn() const;\n\t/// Should `percentageOutsideUfo` be forced for all kinds of missions? (instead of just UFO crash/landing sites)\n\tbool getForcePercentageOutsideUfo() const { return _forcePercentageOutsideUfo; }\n\t/// Gets a pointer to the data.\n\tconst std::vector<DeploymentData>* getDeploymentData() const;\n\t/// Gets the highest used alien rank.\n\tint getMaxAlienRank() const;\n\t/// Gets a pointer to the reinforcements data.\n\tconst std::vector<ReinforcementsData>* getReinforcementsData() const;\n\t/// Gets dimensions.\n\tvoid getDimensions(int *width, int *length, int *height) const;\n\t/// Gets civilians.\n\tint getCivilians() const;\n\t/// Should living civilians be ignored for scoring, commendations, etc.?\n\tbool getIgnoreLivingCivilians() const { return _ignoreLivingCivilians; }\n\t/// Gets the civilian spawn node rank.\n\tbool getMarkCiviliansAsVIP() const { return _markCiviliansAsVIP; }\n\t/// Gets the civilian spawn node rank.\n\tint getCivilianSpawnNodeRank() const { return _civilianSpawnNodeRank; }\n\t/// Gets civilians by type.\n\tconst std::map<std::string, int> &getCiviliansByType() const;\n\t/// Gets the terrain for battlescape generation.\n\tstd::vector<std::string> getTerrains() const;\n\t/// Gets the shade level for battlescape generation.\n\tint getShade() const;\n\t/// Gets the min shade level for battlescape generation.\n\tint getMinShade() const;\n\t/// Gets the max shade level for battlescape generation.\n\tint getMaxShade() const;\n\t/// Gets the next stage of the mission.\n\tstd::string getNextStage() const;\n\t/// Gets the race to use in the next stage.\n\tstd::string getRace() const;\n\t/// Gets the script to use for this deployment.\n\tconst std::string& getRandomMapScript() const;\n\tint hasTextureBasedScript(const Mod* mod) const;\n\t/// Checks if this is the destination for the final mission (mars stage 1, t'leth stage 1).\n\tbool isFinalDestination() const;\n\t/// Gets the cutscene to play when this mission is won.\n\tstd::string getWinCutscene() const;\n\t/// Gets the cutscene to play when this mission is lost.\n\tstd::string getLoseCutscene() const;\n\t/// Gets the cutscene to play when this mission is aborted.\n\tstd::string getAbortCutscene() const;\n\t/// Gets geoscape event rule name to spawn after success mission.\n\tstd::string chooseSuccessEvent() const { return _successEvents.choose(); };\n\t/// Gets geoscape event rule name to despawn after success mission.\n\tstd::string chooseDespawnEvent() const { return _despawnEvents.choose(); };\n\t/// Gets geoscape event rule name to spawn after failure mission.\n\tstd::string chooseFailureEvent() const { return _failureEvents.choose(); };\n\t/// Gets the alert message for this mission type.\n\tstd::string getAlertMessage() const;\n\t/// Gets the alert background for this mission type.\n\tstd::string getAlertBackground() const;\n\t/// Gets the alert description for this mission type.\n\tstd::string getAlertDescription() const;\n\t/// Gets the alert sound for this mission type.\n\tint getAlertSound() const;\n\t/// Gets the briefing data for this mission type.\n\tBriefingData getBriefingData() const;\n\t/// Gets the \"alien base discovered\" message for this mission type.\n\tconst std::string& getAlienBaseDiscoveredMessage() const { return _alienBaseDiscoveredMessage; }\n\t/// Gets the marker name for this mission.\n\tstd::string getMarkerName() const;\n\t/// Gets the marker icon for this mission.\n\tint getMarkerIcon() const;\n\t/// Gets the minimum duration for this mission.\n\tint getDurationMin() const;\n\t/// Gets the maximum duration for this mission.\n\tint getDurationMax() const;\n\t/// Gets the list of music to pick from.\n\tconst std::vector<std::string> &getMusic() const;\n\t/// Gets the minimum depth.\n\tint getMinDepth() const;\n\t/// Gets the maximum depth.\n\tint getMaxDepth() const;\n\t/// Gets the target type for this mission.\n\tint getObjectiveType() const;\n\t/// Gets a fixed number of objectives requires (if any).\n\tint getObjectivesRequired() const;\n\t/// Gets the string to pop up when the mission objectives are complete.\n\tconst std::string &getObjectivePopup() const;\n\t/// Fills out the objective complete info.\n\tbool getObjectiveCompleteInfo(std::string &text, int &score, std::string &missionText) const;\n\t/// Fills out the objective failed info.\n\tbool getObjectiveFailedInfo(std::string &text, int &score, std::string &missionText) const;\n\t/// Gets the score penalty XCom receives for ignoring this site.\n\tint getDespawnPenalty() const;\n\t/// Gets the score penalty XCom receives for aborting this mission.\n\tint getAbortPenalty() const { return _abortPenalty; }\n\t/// Gets the (half hourly) score penalty XCom receives for this site existing.\n\tint getPoints() const;\n\t/// Gets the turn limit for this deployment.\n\tint getTurnLimit() const;\n\t/// Gets the action that triggers when the timer runs out.\n\tChronoTrigger getChronoTrigger() const;\n\t/// Gets which turn the aliens start cheating on.\n\tint getCheatTurn() const;\n\t/// Gets whether or not this is an alien base (purely for new battle mode)\n\tbool isAlienBase() const;\n\t/// Gets whether or not this mission should be hidden (purely for new battle mode)\n\tbool isHidden() const { return _isHidden; }\n\t/// Gets the chance for deciding to spawn an alien base on fakeUnderwater globe texture.\n\tint getFakeUnderwaterSpawnChance() const { return _fakeUnderwaterSpawnChance; }\n\n\tstd::string chooseGenMissionType() const;\n\tint getGenMissionFrequency() const;\n\tint getGenMissionLimit() const;\n\tbool isGenMissionRaceFromAlienBase() const;\n\n\tbool keepCraftAfterFailedMission() const;\n\tbool allowObjectiveRecovery() const;\n\tEscapeType getEscapeType() const;\n\t/// Gets the percentage of VIP units that must survive in order to accomplish the mission.\n\tint getVIPSurvivalPercentage() const { return _vipSurvivalPercentage; }\n\n\t/// Generates a hunt mission based on the given month.\n\tstd::string generateHuntMission(const size_t monthsPassed) const;\n\t/// Gets the Alien Base self destruct code.\n\tconst std::string& getBaseSelfDestructCode() const;\n\t/// Gets the detection range of an alien base.\n\tdouble getBaseDetectionRange() const;\n\t/// Gets the chance of an alien base to detect a player's craft (once every 10 minutes).\n\tint getBaseDetectionChance() const;\n\t/// Gets the maximum frequency of hunt missions generated by an alien base.\n\tint getHuntMissionMaxFrequency() const;\n\t/// Should the hunt missions inherit the race from the alien base, or take it from their own 'raceWeights'?\n\tbool isHuntMissionRaceFromAlienBase() const;\n\n\t/// Generates an alien base upgrade.\n\tstd::string generateAlienBaseUpgrade(const size_t baseAgeInMonths) const;\n\t/// Should the age of an alien base be reset after an upgrade (from this type)?\n\tbool resetAlienBaseAgeAfterUpgrade() const { return _resetAlienBaseAgeAfterUpgrade; }\n\t/// Should the age of an alien base be reset after an upgrade (into this type)?\n\tbool resetAlienBaseAge() const { return _resetAlienBaseAge; }\n\t/// Gets the new race for an alien base after an upgrade (into this type).\n\tconst std::string& getUpgradeRace() const { return _upgradeRace; }\n\n\t/// Gets the alien race evolution rules.\n\tconst auto& getAlienRaceEvolution() const { return _alienRaceEvolution; }\n\n\t/// Should items on the \"weapon pile\" be hidden from the player?\n\tbool getNoWeaponPile() const { return _noWeaponPile; }\n};\n\n// helper overloads for deserialization-only\nbool read(ryml::ConstNodeRef const& n, ItemSet* val);\nbool read(ryml::ConstNodeRef const& n, DeploymentData* val);\nbool read(ryml::ConstNodeRef const& n, BriefingData* val);\nbool read(ryml::ConstNodeRef const& n, ReinforcementsData* val);\n\n}\n"
  },
  {
    "path": "src/Mod/AlienRace.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"AlienRace.h\"\n#include \"../Engine/Exception.h\"\n#include \"../Engine/RNG.h\"\n#include \"Mod.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Creates a blank alien race.\n * @param id String defining the id.\n */\nAlienRace::AlienRace(const std::string &id, int listOrder) : _id(id), _retaliationAggression(0), _listOrder(listOrder)\n{\n}\n\nAlienRace::~AlienRace()\n{\n\tfor (auto& pair : _retaliationMissionDistribution)\n\t{\n\t\tdelete pair.second;\n\t}\n}\n\n/**\n * Loads the alien race from a YAML file.\n * @param node YAML node.\n */\nvoid AlienRace::load(const YAML::YamlNodeReader& reader, const Mod* mod)\n{\n\tif (const auto& parent = reader[\"refNode\"])\n\t{\n\t\tload(parent, mod);\n\t}\n\n\treader.tryRead(\"baseCustomDeploy\", _baseCustomDeploy);\n\treader.tryRead(\"baseCustomMission\", _baseCustomMission);\n\treader.tryRead(\"members\", _members);\n\treader.tryRead(\"membersRandom\", _membersRandom);\n\treader.tryRead(\"retaliationAggression\", _retaliationAggression);\n\n\tfor (const auto& weights : reader[\"retaliationMissionWeights\"].children())\n\t{\n\t\tWeightedOptions* nw = new WeightedOptions();\n\t\tnw->load(weights);\n\t\t_retaliationMissionDistribution.push_back(std::make_pair(weights.readKey<size_t>(0), nw));\n\t}\n\treader.tryRead(\"listOrder\", _listOrder);\n}\n\n/**\n * Returns the language string that names\n * this alien race. Each race has a unique name.\n * @return Race name.\n */\nconst std::string &AlienRace::getId() const\n{\n\treturn _id;\n}\n\n/**\n * Returns optional weapon deploy for aliens in they base.\n * @return Alien deployment id.\n */\nconst std::string &AlienRace::getBaseCustomDeploy() const\n{\n\treturn _baseCustomDeploy;\n}\n\n/**\n * Returns custom alien base deploy.\n * @return Alien deployment id.\n */\nconst std::string &AlienRace::getBaseCustomMission() const\n{\n\treturn _baseCustomMission;\n}\n/**\n * Gets a certain member of this alien race family.\n * @param id The member's id.\n * @return The member's name.\n */\nconst std::string &AlienRace::getMember(int id) const\n{\n\tif (!_membersRandom.empty())\n\t{\n\t\tif ((size_t)id >= _membersRandom.size())\n\t\t{\n\t\t\tthrow Exception(\"Race \" + _id + \" does not have a random member at position/rank \" + std::to_string(id));\n\t\t}\n\t\tint rng = RNG::generate(0, _membersRandom[id].size() - 1);\n\t\treturn _membersRandom[id][rng];\n\t}\n\n\tif ((size_t)id >= _members.size())\n\t{\n\t\tthrow Exception(\"Race \" + _id + \" does not have a member at position/rank \" + std::to_string(id));\n\t}\n\treturn _members[id];\n}\n\n/**\n * Gets the total number of members of this alien race family.\n * @return The number of members.\n */\nint AlienRace::getMembers() const\n{\n\tif (!_membersRandom.empty())\n\t{\n\t\treturn _membersRandom.size();\n\t}\n\n\treturn _members.size();\n}\n\n/**\n * Gets how aggressive alien are\n * @return Mission ID or empty string.\n */\nint AlienRace::getRetaliationAggression() const\n{\n\treturn _retaliationAggression;\n}\n\n/**\n * Returns a list of retaliation missions based on the given month.\n * @param monthsPassed The number of months that have passed in the game world.\n * @return The list of missions. Can be NULL.\n */\nWeightedOptions* AlienRace::retaliationMissionWeights(const size_t monthsPassed) const\n{\n\tif (_retaliationMissionDistribution.empty())\n\t\treturn nullptr;\n\n\tstd::vector<std::pair<size_t, WeightedOptions*> >::const_reverse_iterator rw;\n\trw = _retaliationMissionDistribution.rbegin();\n\twhile (monthsPassed < rw->first)\n\t\t++rw;\n\treturn rw->second;\n}\n\n}\n"
  },
  {
    "path": "src/Mod/AlienRace.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include <vector>\n#include \"../Engine/Yaml.h\"\n#include \"../Savegame/WeightedOptions.h\"\n\nenum AlienRank{AR_HUMAN = -1, AR_COMMANDER, AR_LEADER, AR_ENGINEER, AR_MEDIC, AR_NAVIGATOR, AR_SOLDIER, AR_TERRORIST, AR_TERRORIST2};\n\nnamespace OpenXcom\n{\n\nclass Mod;\n\n/**\n * Represents a specific race \"family\", or a \"main race\" if you wish.\n * Here is defined which ranks it contains and also which accompanying terror units.\n */\nclass AlienRace\n{\nprivate:\n\tstd::string _id;\n\tstd::string _baseCustomDeploy;\n\tstd::string _baseCustomMission;\n\tstd::vector<std::pair<size_t, WeightedOptions*> > _retaliationMissionDistribution;\n\tstd::vector<std::string> _members;\n\tstd::vector< std::vector<std::string> > _membersRandom;\n\tint _retaliationAggression;\n\tint _listOrder;\npublic:\n\t/// Creates a blank alien race ruleset.\n\tAlienRace(const std::string &id, int listOrder);\n\t/// Cleans up the alien race ruleset.\n\t~AlienRace();\n\t/// Loads alien race data from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader, const Mod* mod);\n\t/// Gets the alien race's id.\n\tconst std::string &getId() const;\n\t/// Gets the alien base weapon deploy.\n\tconst std::string &getBaseCustomDeploy() const;\n\t/// Gets the alien base mission.\n\tconst std::string &getBaseCustomMission() const;\n\t/// Gets a certain member of this alien race family.\n\tconst std::string &getMember(int id) const;\n\t/// Gets the total number of members of this alien race family.\n\tint getMembers() const;\n\t/// Gets how aggressive alien are to spawn retaliation mission after destroying ufo.\n\tint getRetaliationAggression() const;\n\t/// Returns a list of retaliation missions based on the given month.\n\tWeightedOptions* retaliationMissionWeights(const size_t monthsPassed) const;\n\t/// Get the list weight for this alien race.\n\tint getListOrder() const { return _listOrder; }\n};\n\n}\n"
  },
  {
    "path": "src/Mod/Armor.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Armor.h\"\n#include \"Unit.h\"\n#include \"../Engine/ScriptBind.h\"\n#include \"LoadYaml.h\"\n#include \"Mod.h\"\n#include \"RuleSoldier.h\"\n#include \"../Savegame/SoldierDiary.h\"\n\nnamespace OpenXcom\n{\n\nconst std::string Armor::NONE = \"STR_NONE\";\n\n/**\n * Creates a blank ruleset for a certain\n * type of armor.\n * @param type String defining the type.\n */\nArmor::Armor(const std::string &type, int listOrder) :\n\t_type(type), _infiniteSupply(false), _frontArmor(0), _sideArmor(0), _leftArmorDiff(0), _rearArmor(0), _underArmor(0),\n\t_drawingRoutine(0), _drawBubbles(false), _movementType(MT_WALK), _specab(SPECAB_NONE), _turnBeforeFirstStep(false), _turnCost(1), _moveSound(-1), _size(1), _weight(0),\n\t_visibilityAtDark(0), _visibilityAtDay(0),\n\t_camouflageAtDay(0), _camouflageAtDark(0), _antiCamouflageAtDay(0), _antiCamouflageAtDark(0),\n\t_visibilityThroughSmoke(0), _visibilityThroughFire(100),\n\t_psiVision(0), _psiCamouflage(0),\n\t_deathFrames(3), _constantAnimation(false), _hasInventory(true), _forcedTorso(TORSO_USE_GENDER),\n\t_faceColorGroup(0), _hairColorGroup(0), _utileColorGroup(0), _rankColorGroup(0),\n\t_fearImmune(defBoolNullable), _bleedImmune(defBoolNullable), _painImmune(defBoolNullable), _zombiImmune(defBoolNullable),\n\t_ignoresMeleeThreat(defBoolNullable), _createsMeleeThreat(defBoolNullable),\n\t_overKill(0.5f), _meleeDodgeBackPenalty(0),\n\t_allowsRunning(defBoolNullable), _allowsStrafing(defBoolNullable), _allowsSneaking(defBoolNullable), _allowsKneeling(defBoolNullable), _allowsMoving(1),\n\t_isPilotArmor(false), _allowTwoMainWeapons(false), _instantWoundRecovery(false),\n\t_standHeight(-1), _kneelHeight(-1), _floatHeight(-1), _meleeOriginVoxelVerticalOffset(0), _group(0), _listOrder(listOrder)\n{\n\tfor (int i=0; i < DAMAGE_TYPES; i++)\n\t\t_damageModifier[i] = 1.0f;\n\n\t_psiDefence.setPsiDefense();\n\t_timeRecovery.setTimeRecovery();\n\t_energyRecovery.setEnergyRecovery();\n\t_stunRecovery.setStunRecovery();\n\n\t_customArmorPreviewIndex.push_back(Mod::NO_SURFACE);\n}\n\n/**\n *\n */\nArmor::~Armor()\n{\n\n}\n\n/**\n * Loads the armor from a YAML file.\n * @param node YAML node.\n */\nvoid Armor::load(const YAML::YamlNodeReader& node, Mod *mod, const ModScript &parsers)\n{\n\tconst auto& reader = node.useIndex();\n\tif (const YAML::YamlNodeReader& parent = reader[\"refNode\"])\n\t{\n\t\tload(parent, mod, parsers);\n\t}\n\n\treader.tryRead(\"ufopediaType\", _ufopediaType);\n\treader.tryRead(\"spriteSheet\", _spriteSheet);\n\treader.tryRead(\"spriteInv\", _spriteInv);\n\treader.tryRead(\"allowInv\", _hasInventory);\n\tif (reader[\"corpseItem\"])\n\t{\n\t\t_corpseBattleNames.clear();\n\t\t_corpseBattleNames.push_back(reader[\"corpseItem\"].readVal<std::string>());\n\t\t_corpseGeoName = _corpseBattleNames[0];\n\t}\n\telse if (reader[\"corpseBattle\"])\n\t{\n\t\tmod->loadNames(_type, _corpseBattleNames, reader[\"corpseBattle\"]);\n\t\t_corpseGeoName = _corpseBattleNames.at(0);\n\t}\n\tmod->loadNames(_type, _builtInWeaponsNames, reader[\"builtInWeapons\"]);\n\tmod->loadName(_type, _corpseGeoName, reader[\"corpseGeo\"]);\n\tmod->loadNameNull(_type, _storeItemName, reader[\"storeItem\"]);\n\tmod->loadNameNull(_type, _selfDestructItemName, reader[\"selfDestructItem\"]);\n\tmod->loadNameNull(_type, _specWeaponName, reader[\"specialWeapon\"]);\n\tmod->loadNameNull(_type, _requiresName, reader[\"requires\"]);\n\tmod->loadNameNull(_type, _requiresAwardName, reader[\"requiresAward\"]);\n\tmod->loadNameNull(_type, _requiresBonusName, reader[\"requiresBonus\"]);\n\n\treader.tryRead(\"layersDefaultPrefix\", _layersDefaultPrefix);\n\treader.tryRead(\"layersSpecificPrefix\", _layersSpecificPrefix);\n\treader.tryRead(\"layersDefinition\", _layersDefinition);\n\n\treader.tryRead(\"frontArmor\", _frontArmor);\n\treader.tryRead(\"sideArmor\", _sideArmor);\n\treader.tryRead(\"leftArmorDiff\", _leftArmorDiff);\n\treader.tryRead(\"rearArmor\", _rearArmor);\n\treader.tryRead(\"underArmor\", _underArmor);\n\treader.tryRead(\"drawingRoutine\", _drawingRoutine);\n\treader.tryRead(\"drawBubbles\", _drawBubbles);\n\treader.tryRead(\"movementType\", _movementType);\n\treader.tryRead(\"specab\", _specab);\n\n\tif (const YAML::YamlNodeReader& ai = reader[\"ai\"])\n\t{\n\t\tai.tryRead(\"targetWeightAsHostile\", _aiTargetWeightAsHostile);\n\t\tai.tryRead(\"targetWeightAsHostileCivilians\", _aiTargetWeightAsHostileCivilians);\n\t\tai.tryRead(\"targetWeightAsFriendly\", _aiTargetWeightAsFriendly);\n\t\tai.tryRead(\"targetWeightAsNeutral\", _aiTargetWeightAsNeutral);\n\t}\n\n\treader.tryRead(\"turnBeforeFirstStep\", _turnBeforeFirstStep);\n\treader.tryRead(\"turnCost\", _turnCost);\n\tif (const YAML::YamlNodeReader& move = reader[\"moveCost\"])\n\t{\n\t\t_moveCostBase.load(move[\"basePercent\"]);\n\t\t_moveCostBaseFly.load(move[\"baseFlyPercent\"]);\n\t\t_moveCostBaseClimb.load(move[\"baseClimbPercent\"]);\n\t\t_moveCostBaseNormal.load(move[\"baseNormalPercent\"]);\n\n\t\t_moveCostWalk.load(move[\"walkPercent\"]);\n\t\t_moveCostRun.load(move[\"runPercent\"]);\n\t\t_moveCostStrafe.load(move[\"strafePercent\"]);\n\t\t_moveCostSneak.load(move[\"sneakPercent\"]);\n\n\t\t_moveCostFlyWalk.load(move[\"flyWalkPercent\"]);\n\t\t_moveCostFlyRun.load(move[\"flyRunPercent\"]);\n\t\t_moveCostFlyStrafe.load(move[\"flyStrafePercent\"]);\n\n\t\t_moveCostFlyUp.load(move[\"flyUpPercent\"]);\n\t\t_moveCostFlyDown.load(move[\"flyDownPercent\"]);\n\n\t\t_moveCostClimbUp.load(move[\"climbUpPercent\"]);\n\t\t_moveCostClimbDown.load(move[\"climbDownPercent\"]);\n\n\t\t_moveCostGravLift.load(move[\"gravLiftPercent\"]);\n\t}\n\n\tmod->loadSoundOffset(_type, _moveSound, reader[\"moveSound\"], \"BATTLE.CAT\");\n\tmod->loadSoundOffset(_type, _deathSoundMale, reader[\"deathMale\"], \"BATTLE.CAT\");\n\tmod->loadSoundOffset(_type, _deathSoundFemale, reader[\"deathFemale\"], \"BATTLE.CAT\");\n\n\tmod->loadSoundOffset(_type, _selectUnitSoundMale, reader[\"selectUnitMale\"], \"BATTLE.CAT\");\n\tmod->loadSoundOffset(_type, _selectUnitSoundFemale, reader[\"selectUnitFemale\"], \"BATTLE.CAT\");\n\tmod->loadSoundOffset(_type, _startMovingSoundMale, reader[\"startMovingMale\"], \"BATTLE.CAT\");\n\tmod->loadSoundOffset(_type, _startMovingSoundFemale, reader[\"startMovingFemale\"], \"BATTLE.CAT\");\n\tmod->loadSoundOffset(_type, _selectWeaponSoundMale, reader[\"selectWeaponMale\"], \"BATTLE.CAT\");\n\tmod->loadSoundOffset(_type, _selectWeaponSoundFemale, reader[\"selectWeaponFemale\"], \"BATTLE.CAT\");\n\tmod->loadSoundOffset(_type, _annoyedSoundMale, reader[\"annoyedMale\"], \"BATTLE.CAT\");\n\tmod->loadSoundOffset(_type, _annoyedSoundFemale, reader[\"annoyedFemale\"], \"BATTLE.CAT\");\n\n\treader.tryRead(\"weight\", _weight);\n\treader.tryRead(\"visibilityAtDark\", _visibilityAtDark);\n\treader.tryRead(\"visibilityAtDay\", _visibilityAtDay);\n\treader.tryRead(\"personalLight\", _personalLightFriend);\n\treader.tryRead(\"personalLightHostile\", _personalLightHostile);\n\treader.tryRead(\"personalLightNeutral\", _personalLightNeutral);\n\treader.tryRead(\"camouflageAtDay\", _camouflageAtDay);\n\treader.tryRead(\"camouflageAtDark\", _camouflageAtDark);\n\treader.tryRead(\"antiCamouflageAtDay\", _antiCamouflageAtDay);\n\treader.tryRead(\"antiCamouflageAtDark\", _antiCamouflageAtDark);\n\treader.tryRead(\"heatVision\", _visibilityThroughSmoke);\n\treader.tryRead(\"visibilityThroughFire\", _visibilityThroughFire);\n\treader.tryRead(\"psiVision\", _psiVision);\n\treader.tryRead(\"psiCamouflage\", _psiCamouflage);\n\treader.tryRead(\"alwaysVisible\", _isAlwaysVisible);\n\n\t_stats.merge(reader[\"stats\"].readVal(_stats));\n\tif (const YAML::YamlNodeReader& dmg = reader[\"damageModifier\"])\n\t{\n\t\tsize_t end = std::min(dmg.childrenCount(), (size_t)DAMAGE_TYPES);\n\t\tfor (size_t i = 0; i < end; ++i)\n\t\t{\n\t\t\t_damageModifier[i] = dmg[i].readVal<float>();\n\t\t}\n\t}\n\tmod->loadInts(_type, _loftempsSet, reader[\"loftempsSet\"]);\n\tif (reader[\"loftemps\"])\n\t\t_loftempsSet = { reader[\"loftemps\"].readVal<int>() };\n\treader.tryRead(\"deathFrames\", _deathFrames);\n\treader.tryRead(\"constantAnimation\", _constantAnimation);\n\treader.tryRead(\"forcedTorso\", _forcedTorso);\n\tif (reader.tryRead(\"size\", _size))\n\t{\n\t\tif (_size != 1) //TODO: Add handling for opposite case too\n\t\t{\n\t\t\t_fearImmune = 1;\n\t\t\t_bleedImmune = 1;\n\t\t\t_painImmune = 1;\n\t\t\t_zombiImmune = 1;\n\t\t\t_ignoresMeleeThreat = 1;\n\t\t\t_createsMeleeThreat = 0;\n\t\t}\n\t}\n\tloadBoolNullable(_fearImmune, reader[\"fearImmune\"]);\n\tloadBoolNullable(_bleedImmune, reader[\"bleedImmune\"]);\n\tloadBoolNullable(_painImmune, reader[\"painImmune\"]);\n\tif (_size == 1) //Big units are always immune, because game we don't have 2x2 unit zombie\n\t{\n\t\tloadBoolNullable(_zombiImmune, reader[\"zombiImmune\"]);\n\t}\n\tloadBoolNullable(_ignoresMeleeThreat, reader[\"ignoresMeleeThreat\"]);\n\tloadBoolNullable(_createsMeleeThreat, reader[\"createsMeleeThreat\"]);\n\n\treader.tryRead(\"overKill\", _overKill);\n\treader.tryRead(\"meleeDodgeBackPenalty\", _meleeDodgeBackPenalty);\n\n\t_psiDefence.load(_type, reader, parsers.bonusStatsScripts.get<ModScript::PsiDefenceStatBonus>());\n\t_meleeDodge.load(_type, reader, parsers.bonusStatsScripts.get<ModScript::MeleeDodgeStatBonus>());\n\n\t_timeRecovery.load(_type, reader[\"recovery\"], parsers.bonusStatsScripts.get<ModScript::TimeRecoveryStatBonus>());\n\t_energyRecovery.load(_type, reader[\"recovery\"], parsers.bonusStatsScripts.get<ModScript::EnergyRecoveryStatBonus>());\n\t_moraleRecovery.load(_type, reader[\"recovery\"], parsers.bonusStatsScripts.get<ModScript::MoraleRecoveryStatBonus>());\n\t_healthRecovery.load(_type, reader[\"recovery\"], parsers.bonusStatsScripts.get<ModScript::HealthRecoveryStatBonus>());\n\t_manaRecovery.load(_type, reader[\"recovery\"], parsers.bonusStatsScripts.get<ModScript::ManaRecoveryStatBonus>());\n\t_stunRecovery.load(_type, reader[\"recovery\"], parsers.bonusStatsScripts.get<ModScript::StunRecoveryStatBonus>());\n\n\treader.tryRead(\"spriteFaceGroup\", _faceColorGroup);\n\treader.tryRead(\"spriteHairGroup\", _hairColorGroup);\n\treader.tryRead(\"spriteRankGroup\", _rankColorGroup);\n\treader.tryRead(\"spriteUtileGroup\", _utileColorGroup);\n\tmod->loadInts(_type, _faceColor, reader[\"spriteFaceColor\"]);\n\tmod->loadInts(_type, _hairColor, reader[\"spriteHairColor\"]);\n\tmod->loadInts(_type, _rankColor, reader[\"spriteRankColor\"]);\n\tmod->loadInts(_type, _utileColor, reader[\"spriteUtileColor\"]);\n\n\t_battleUnitScripts.load(_type, reader, parsers.battleUnitScripts);\n\n\tmod->loadUnorderedNames(_type, _unitsNames, reader[\"units\"]);\n\tmod->loadUnorderedInts(_type, _ranks, reader[\"ranks\"]);\n\t_scriptValues.load(reader, parsers.getShared());\n\tmod->loadSpriteOffset(_type, _customArmorPreviewIndex, reader[\"customArmorPreviewIndex\"], \"CustomArmorPreviews\");\n\tloadBoolNullable(_allowsRunning, reader[\"allowsRunning\"]);\n\tloadBoolNullable(_allowsStrafing, reader[\"allowsStrafing\"]);\n\tloadBoolNullable(_allowsSneaking, reader[\"allowsSneaking\"]);\n\tloadBoolNullable(_allowsKneeling, reader[\"allowsKneeling\"]);\n\tloadBoolNullable(_allowsMoving, reader[\"allowsMoving\"]);\n\treader.tryRead(\"isPilotArmor\", _isPilotArmor);\n\treader.tryRead(\"allowTwoMainWeapons\", _allowTwoMainWeapons);\n\treader.tryRead(\"instantWoundRecovery\", _instantWoundRecovery);\n\treader.tryRead(\"standHeight\", _standHeight);\n\treader.tryRead(\"kneelHeight\", _kneelHeight);\n\treader.tryRead(\"floatHeight\", _floatHeight);\n\treader.tryRead(\"meleeOriginVoxelVerticalOffset\", _meleeOriginVoxelVerticalOffset);\n\treader.tryRead(\"group\", _group);\n\treader.tryRead(\"listOrder\", _listOrder);\n}\n\n/**\n * Cross link with other rules.\n */\nvoid Armor::afterLoad(const Mod* mod)\n{\n\tmod->verifySoundOffset(_type, _moveSound, \"BATTLE.CAT\");\n\tmod->verifySoundOffset(_type, _deathSoundMale, \"BATTLE.CAT\");\n\tmod->verifySoundOffset(_type, _deathSoundFemale, \"BATTLE.CAT\");\n\n\tmod->verifySoundOffset(_type, _selectUnitSoundMale, \"BATTLE.CAT\");\n\tmod->verifySoundOffset(_type, _selectUnitSoundFemale, \"BATTLE.CAT\");\n\tmod->verifySoundOffset(_type, _startMovingSoundMale, \"BATTLE.CAT\");\n\tmod->verifySoundOffset(_type, _startMovingSoundFemale, \"BATTLE.CAT\");\n\tmod->verifySoundOffset(_type, _selectWeaponSoundMale, \"BATTLE.CAT\");\n\tmod->verifySoundOffset(_type, _selectWeaponSoundFemale, \"BATTLE.CAT\");\n\tmod->verifySoundOffset(_type, _annoyedSoundMale, \"BATTLE.CAT\");\n\tmod->verifySoundOffset(_type, _annoyedSoundFemale, \"BATTLE.CAT\");\n\n\tmod->verifySpriteOffset(_type, _customArmorPreviewIndex, \"CustomArmorPreviews\");\n\n\n\tmod->linkRule(_corpseBattle, _corpseBattleNames);\n\tmod->linkRule(_corpseGeo, _corpseGeoName);\n\tmod->linkRule(_builtInWeapons, _builtInWeaponsNames);\n\tmod->linkRule(_units, _unitsNames);\n\tmod->linkRule(_requires, _requiresName);\n\tmod->linkRule(_requiresAward, _requiresAwardName);\n\tmod->linkRule(_requiresBonus, _requiresBonusName);\n\tif (_storeItemName == Armor::NONE)\n\t{\n\t\t_infiniteSupply = true;\n\t}\n\tmod->linkRule(_storeItem, _storeItemName); //special logic there: \"STR_NONE\" -> nullptr\n\tmod->linkRule(_selfDestructItem, _selfDestructItemName);\n\tmod->linkRule(_specWeapon, _specWeaponName);\n\n\n\t{\n\t\tsize_t totalSize = getTotalSize();\n\n\t\tmod->checkForSoftError(_corpseBattle.size() != totalSize, _type, \"Number of battle corpse items for 'corpseBattle' does not match the armor size.\", LOG_ERROR);\n\t\tmod->checkForSoftError(_loftempsSet.size() != totalSize, _type, \"Number of defined templates for 'loftempsSet' or 'loftemps' does not match the armor size.\", LOG_ERROR);\n\n\t\tint s = mod->getVoxelData()->size() / 16;\n\t\tfor (auto& lof : _loftempsSet)\n\t\t{\n\t\t\tmod->checkForSoftError(lof >= s, _type, \"Value \" + std::to_string(lof) + \" in 'loftempsSet' or 'loftemps' is larger than number of avaiable templates.\", LOG_ERROR);\n\t\t}\n\t}\n\n\tint numCorpse = 0;\n\tfor (auto* c : _corpseBattle)\n\t{\n\t\tif (!c)\n\t\t{\n\t\t\tthrow Exception(\"Battle corpse item(s) cannot be empty.\");\n\t\t}\n\n\t\tif (!numCorpse++)\n\t\t{\n\t\t\t// only the first item needs to be a corpse item\n\t\t\tmod->checkForSoftError(c->getBattleType() != BT_CORPSE, _type, \"The first battle corpse item must be of item type 'corpse' (battleType: 11)\");\n\t\t}\n\t\telse\n\t\t{\n\t\t\tmod->checkForSoftError(c->isRecoverable(), _type, \"Multiple recoverable battle corpse item(s)\");\n\t\t}\n\t}\n\tif (!_corpseGeo)\n\t{\n\t\tthrow Exception(\"Geo corpse item cannot be empty.\");\n\t}\n\n\t// calcualte final surfaces used by layers\n\tif (!_layersDefaultPrefix.empty())\n\t{\n\t\tfor (auto& version : _layersDefinition)\n\t\t{\n\t\t\tint layerIndex = 0;\n\t\t\tfor (auto& layerItem : version.second)\n\t\t\t{\n\t\t\t\tif (!layerItem.empty())\n\t\t\t\t{\n\t\t\t\t\tstatic std::string buf; //static buffer that grows on demand; that's what she said\n\t\t\t\t\tconst auto& pre = _layersSpecificPrefix.find(layerIndex);\n\t\t\t\t\tconst auto& prefix = pre != _layersSpecificPrefix.end() ? pre->second : _layersDefaultPrefix;\n\t\t\t\t\tsize_t formattedLen = c4::format(c4::to_substr(buf), \"{}__{}__{}\", prefix, layerIndex, layerItem);\n\t\t\t\t\tif (formattedLen > buf.size())\n\t\t\t\t\t{\n\t\t\t\t\t\tbuf.resize(formattedLen);\n\t\t\t\t\t\tc4::format(c4::to_substr(buf), \"{}__{}__{}\", prefix, layerIndex, layerItem);\n\t\t\t\t\t}\n\t\t\t\t\tlayerItem.assign(buf.data(), formattedLen);\n\n\t\t\t\t\t//check if surface is valid\n\t\t\t\t\tif (Options::lazyLoadResources == false)\n\t\t\t\t\t{\n\t\t\t\t\t\t//TODO: remove `const_cast`\n\t\t\t\t\t\tmod->checkForSoftError(const_cast<Mod*>(mod)->getSurface(layerItem, false) == nullptr, _type, \"Missing surface definition for '\" + layerItem + \"'\", LOG_ERROR);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tlayerIndex++;\n\t\t\t}\n\t\t\t//clean unused layers\n\t\t\tCollections::removeIf(version.second, [](const std::string& s) { return s.empty(); });\n\t\t\tversion.second.shrink_to_fit();\n\t\t}\n\t}\n\n\tCollections::sortVector(_units);\n\tCollections::sortVector(_ranks);\n}\n\n\n\n/**\n * Gets the custom name of the Ufopedia article related to this armor.\n * @return The ufopedia article name.\n */\nconst std::string& Armor::getUfopediaType() const\n{\n\tif (!_ufopediaType.empty())\n\t\treturn _ufopediaType;\n\n\treturn _type;\n}\n\n/**\n * Returns the language string that names\n * this armor. Each armor has a unique name. Coveralls, Power Suit,...\n * @return The armor name.\n */\nconst std::string& Armor::getType() const\n{\n\treturn _type;\n}\n\n/**\n * Gets the unit's sprite sheet.\n * @return The sprite sheet name.\n */\nstd::string Armor::getSpriteSheet() const\n{\n\treturn _spriteSheet;\n}\n\n/**\n * Gets the unit's inventory sprite.\n * @return The inventory sprite name.\n */\nstd::string Armor::getSpriteInventory() const\n{\n\treturn _spriteInv;\n}\n\n/**\n * Gets the front armor level.\n * @return The front armor level.\n */\nint Armor::getFrontArmor() const\n{\n\treturn _frontArmor;\n}\n\n/**\n * Gets the left side armor level.\n * @return The left side armor level.\n */\nint Armor::getLeftSideArmor() const\n{\n\treturn _sideArmor + _leftArmorDiff;\n}\n\n/**\n* Gets the right side armor level.\n* @return The right side armor level.\n*/\nint Armor::getRightSideArmor() const\n{\n\treturn _sideArmor;\n}\n\n/**\n * Gets the rear armor level.\n * @return The rear armor level.\n */\nint Armor::getRearArmor() const\n{\n\treturn _rearArmor;\n}\n\n/**\n * Gets the under armor level.\n * @return The under armor level.\n */\nint Armor::getUnderArmor() const\n{\n\treturn _underArmor;\n}\n\n/**\n * Gets the armor level of part.\n * @param side Part of armor.\n * @return The armor level of part.\n */\nint Armor::getArmor(UnitSide side) const\n{\n\tswitch (side)\n\t{\n\tcase SIDE_FRONT:\treturn _frontArmor;\n\tcase SIDE_LEFT:\t\treturn _sideArmor + _leftArmorDiff;\n\tcase SIDE_RIGHT:\treturn _sideArmor;\n\tcase SIDE_REAR:\t\treturn _rearArmor;\n\tcase SIDE_UNDER:\treturn _underArmor;\n\tdefault: return 0;\n\t}\n}\n\n\n/**\n * Gets the corpse item used in the Geoscape.\n * @return The name of the corpse item.\n */\nconst RuleItem* Armor::getCorpseGeoscape() const\n{\n\treturn _corpseGeo;\n}\n\n/**\n * Gets the list of corpse items dropped by the unit\n * in the Battlescape (one per unit tile).\n * @return The list of corpse items.\n */\nconst std::vector<const RuleItem*> &Armor::getCorpseBattlescape() const\n{\n\treturn _corpseBattle;\n}\n\n/**\n * Gets the storage item needed to equip this.\n * Every soldier armor needs an item.\n * @return The name of the store item (STR_NONE for infinite armor).\n */\nconst RuleItem* Armor::getStoreItem() const\n{\n\treturn _storeItem;\n}\n\n/**\n * Gets the type of special weapon.\n * @return The name of the special weapon.\n */\nconst RuleItem* Armor::getSpecialWeapon() const\n{\n\treturn _specWeapon;\n}\n\n/**\n * Gets the research required to be able to equip this armor.\n * @return The name of the research topic.\n */\nconst RuleResearch* Armor::getRequiredResearch() const\n{\n\treturn _requires;\n}\n\n/**\n * Gets the drawing routine ID.\n * @return The drawing routine ID.\n */\nint Armor::getDrawingRoutine() const\n{\n\treturn _drawingRoutine;\n}\n\n/**\n * Gets whether or not to draw bubbles (breathing animation).\n * @return True if breathing animation is enabled, false otherwise.\n */\nbool Armor::drawBubbles() const\n{\n\treturn _drawBubbles;\n}\n\n/**\n * Gets the movement type of this armor.\n * Useful for determining whether the armor can fly.\n * @important: do not use this function outside the BattleUnit constructor,\n * unless you are SURE you know what you are doing.\n * for more information, see the BattleUnit constructor.\n * @return The movement type.\n */\nMovementType Armor::getMovementType() const\n{\n\treturn _movementType;\n}\n\n/**\n * Get MovementType based on depth of battle.\n */\nMovementType Armor::getMovementTypeByDepth(int depth) const\n{\n\tif (_movementType == MT_FLOAT)\n\t{\n\t\tif (depth > 0)\n\t\t{\n\t\t\treturn MT_FLY;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn MT_WALK;\n\t\t}\n\t}\n\telse if (_movementType == MT_SINK)\n\t{\n\t\tif (depth == 0)\n\t\t{\n\t\t\treturn MT_FLY;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn MT_WALK;\n\t\t}\n\t}\n\telse\n\t{\n\t\treturn _movementType;\n\t}\n}\n\n/**\n * Gets the armor's special ability.\n * @return The armor's specab.\n */\nint Armor::getSpecialAbility() const\n{\n\treturn (int)_specab;\n}\n\n/**\n* Gets the armor's move sound.\n* @return The id of the armor's move sound.\n*/\nint Armor::getMoveSound() const\n{\n\treturn _moveSound;\n}\n\n/**\n * Gets the size of the unit. Normally this is 1 (small) or 2 (big).\n * @return The unit's size.\n */\nint Armor::getSize() const\n{\n\treturn _size;\n}\n\n/**\n * Gets the total size of the unit. Normally this is 1 for small or 4 for big.\n * @return The unit's size.\n */\nint Armor::getTotalSize() const\n{\n\treturn _size * _size;\n}\n/**\n * Gets the damage modifier for a certain damage type.\n * @param dt The damageType.\n * @return The damage modifier 0->1.\n */\nfloat Armor::getDamageModifier(ItemDamageType dt) const\n{\n\treturn _damageModifier[(int)dt];\n}\n\nconst std::vector<float> Armor::getDamageModifiersRaw() const\n{\n\tstd::vector<float> result;\n\tfor (int i = 0; i < DAMAGE_TYPES; i++)\n\t{\n\t\tresult.push_back(_damageModifier[i]);\n\t}\n\treturn result;\n}\n\n/** Gets the loftempSet.\n * @return The loftempsSet.\n */\nconst std::vector<int>& Armor::getLoftempsSet() const\n{\n\treturn _loftempsSet;\n}\n\n/**\n  * Gets pointer to the armor's stats.\n  * @return stats Pointer to the armor's stats.\n  */\nconst UnitStats *Armor::getStats() const\n{\n\treturn &_stats;\n}\n\n/**\n * Gets unit psi defense.\n */\nint Armor::getPsiDefence(const BattleUnit* unit) const\n{\n\treturn _psiDefence.getBonus(unit);\n}\n\n/**\n * Gets unit melee dodge chance.\n */\nint Armor::getMeleeDodge(const BattleUnit* unit) const\n{\n\treturn _meleeDodge.getBonus(unit);\n}\n\n/**\n * Gets unit dodge penalty if hit from behind.\n */\nfloat Armor::getMeleeDodgeBackPenalty() const\n{\n\treturn _meleeDodgeBackPenalty;\n}\n\n/**\n *  Gets unit TU recovery.\n */\nint Armor::getTimeRecovery(const BattleUnit* unit, int externalBonuses) const\n{\n\treturn _timeRecovery.getBonus(unit, externalBonuses);\n}\n\n/**\n *  Gets unit Energy recovery.\n */\nint Armor::getEnergyRecovery(const BattleUnit* unit, int externalBonuses) const\n{\n\treturn _energyRecovery.getBonus(unit, externalBonuses);\n}\n\n/**\n *  Gets unit Morale recovery.\n */\nint Armor::getMoraleRecovery(const BattleUnit* unit, int externalBonuses) const\n{\n\treturn _moraleRecovery.getBonus(unit, externalBonuses);\n}\n\n/**\n *  Gets unit Health recovery.\n */\nint Armor::getHealthRecovery(const BattleUnit* unit, int externalBonuses) const\n{\n\treturn _healthRecovery.getBonus(unit, externalBonuses);\n}\n\n/**\n *  Gets unit Mana recovery.\n */\nint Armor::getManaRecovery(const BattleUnit* unit, int externalBonuses) const\n{\n\treturn _manaRecovery.getBonus(unit, externalBonuses);\n}\n\n/**\n *  Gets unit Stun recovery.\n */\nint Armor::getStunRegeneration(const BattleUnit* unit, int externalBonuses) const\n{\n\treturn _stunRecovery.getBonus(unit, externalBonuses);\n}\n\n/**\n * Gets the armor's weight.\n * @return the weight of the armor.\n */\nint Armor::getWeight() const\n{\n\treturn _weight;\n}\n\n/**\n * Gets number of death frames.\n * @return number of death frames.\n */\nint Armor::getDeathFrames() const\n{\n\treturn _deathFrames;\n}\n\n/**\n * Gets if armor uses constant animation.\n * @return if it uses constant animation\n */\nbool Armor::getConstantAnimation() const\n{\n\treturn _constantAnimation;\n}\n\n/**\n * Checks if this armor ignores gender (power suit/flying suit).\n * @return which torso to force on the sprite.\n */\nForcedTorso Armor::getForcedTorso() const\n{\n\treturn _forcedTorso;\n}\n\n/**\n * What weapons does this armor have built in?\n * this is a vector of strings representing any\n * weapons that may be inherent to this armor.\n * note: unlike \"livingWeapon\" this is used in ADDITION to\n * any loadout or living weapon item that may be defined.\n * @return list of weapons that are integral to this armor.\n */\nconst std::vector<const RuleItem*> &Armor::getBuiltInWeapons() const\n{\n\treturn _builtInWeapons;\n}\n\n/**\n * Gets max view distance at dark in BattleScape.\n * @return The distance to see at dark.\n */\nint Armor::getVisibilityAtDark() const\n{\n\treturn _visibilityAtDark;\n}\n\n/**\n* Gets max view distance at day in BattleScape.\n* @return The distance to see at day.\n*/\nint Armor::getVisibilityAtDay() const\n{\n\treturn _visibilityAtDay;\n}\n\n/**\n* Gets info about camouflage at day.\n* @return The vision distance modifier.\n*/\nint Armor::getCamouflageAtDay() const\n{\n\treturn _camouflageAtDay;\n}\n\n/**\n* Gets info about camouflage at dark.\n* @return The vision distance modifier.\n*/\nint Armor::getCamouflageAtDark() const\n{\n\treturn _camouflageAtDark;\n}\n\n/**\n* Gets info about anti camouflage at day.\n* @return The vision distance modifier.\n*/\nint Armor::getAntiCamouflageAtDay() const\n{\n\treturn _antiCamouflageAtDay;\n}\n\n/**\n* Gets info about anti camouflage at dark.\n* @return The vision distance modifier.\n*/\nint Armor::getAntiCamouflageAtDark() const\n{\n\treturn _antiCamouflageAtDark;\n}\n\n/**\n* Gets info about psi vision.\n* @return How many tiles can units be sensed even through solid obstacles (e.g. walls).\n*/\nint Armor::getPsiVision() const\n{\n\treturn _psiVision;\n}\n\n/**\n * Gets info about psi camouflage.\n * @return psi camo data.\n */\nint Armor::getPsiCamouflage() const\n{\n\treturn _psiCamouflage;\n}\n\n/**\n* Gets personal light radius created by solders.\n* @return Return light radius.\n*/\nint Armor::getPersonalLightFriend() const\n{\n\treturn _personalLightFriend;\n}\n\n/**\n* Gets personal light radius created by alien.\n* @return Return light radius.\n*/\nint Armor::getPersonalLightHostile() const\n{\n\treturn _personalLightHostile;\n}\n\n/**\n* Gets personal light radius created by civilian.\n* @return Return light radius.\n*/\nint Armor::getPersonalLightNeutral() const\n{\n\treturn _personalLightNeutral;\n}\n\n/**\n * Gets how armor react to fear.\n * @param def Default value.\n * @return Can ignored fear?\n */\nbool Armor::getFearImmune(bool def) const\n{\n\treturn useBoolNullable(_fearImmune, def);\n}\n\n/**\n * Gets how armor react to bleeding.\n * @param def Default value.\n * @return Can ignore bleed?\n */\nbool Armor::getBleedImmune(bool def) const\n{\n\treturn useBoolNullable(_bleedImmune, def);\n}\n\n/**\n * Gets how armor react to inflicted pain.\n * @param def\n * @return Can ignore pain?\n */\nbool Armor::getPainImmune(bool def) const\n{\n\treturn useBoolNullable(_painImmune, def);\n}\n\n/**\n * Gets how armor react to zombification.\n * @param def Default value.\n * @return Can't be turn to zombie?\n */\nbool Armor::getZombiImmune(bool def) const\n{\n\treturn useBoolNullable(_zombiImmune, def);\n}\n\n/**\n * Gets whether or not this unit ignores close quarters threats.\n * @param def Default value.\n * @return Ignores CQB check?\n */\nbool Armor::getIgnoresMeleeThreat(bool def) const\n{\n\treturn useBoolNullable(_ignoresMeleeThreat, def);\n}\n\n/**\n * Gets whether or not this unit is a close quarters threat.\n * @param def Default value.\n * @return Creates CQB check for others?\n */\nbool Armor::getCreatesMeleeThreat(bool def) const\n{\n\treturn useBoolNullable(_createsMeleeThreat, def);\n}\n\n/**\n * Gets how much damage (over the maximum HP) is needed to vaporize/disintegrate a unit.\n * @return Percent of require hp.\n */\nfloat Armor::getOverKill() const\n{\n\treturn _overKill;\n}\n\n/**\n * Gets hair base color group for replacement, if 0 then don't replace colors.\n * @return Color group or 0.\n */\nint Armor::getFaceColorGroup() const\n{\n\treturn _faceColorGroup;\n}\n\n/**\n * Gets hair base color group for replacement, if 0 then don't replace colors.\n * @return Color group or 0.\n */\nint Armor::getHairColorGroup() const\n{\n\treturn _hairColorGroup;\n}\n\n/**\n * Gets utile base color group for replacement, if 0 then don't replace colors.\n * @return Color group or 0.\n */\nint Armor::getUtileColorGroup() const\n{\n\treturn _utileColorGroup;\n}\n\n/**\n * Gets rank base color group for replacement, if 0 then don't replace colors.\n * @return Color group or 0.\n */\nint Armor::getRankColorGroup() const\n{\n\treturn _rankColorGroup;\n}\n\nnamespace\n{\n\n/**\n * Helper function finding value in vector with fallback if vector is shorter.\n * @param vec Vector with values we try get.\n * @param pos Position in vector that can be greater than size of vector.\n * @return Value in vector.\n */\nint findWithFallback(const std::vector<int> &vec, size_t pos)\n{\n\t//if pos == 31 then we test for 31, 15, 7\n\t//if pos == 36 then we test for 36, 4\n\t//we stop on p < 8 for compatibility reasons.\n\tfor (int i = 0; i <= RuleSoldier::LookVariantBits; ++i)\n\t{\n\t\tsize_t p = (pos & (RuleSoldier::LookTotalMask >> i));\n\t\tif (p < vec.size())\n\t\t{\n\t\t\treturn vec[p];\n\t\t}\n\t}\n\treturn 0;\n}\n\n} //namespace\n\n/**\n * Gets new face colors for replacement, if 0 then don't replace colors.\n * @return Color index or 0.\n */\nint Armor::getFaceColor(int i) const\n{\n\treturn findWithFallback(_faceColor, i);\n}\n\n/**\n * Gets new hair colors for replacement, if 0 then don't replace colors.\n * @return Color index or 0.\n */\nint Armor::getHairColor(int i) const\n{\n\treturn findWithFallback(_hairColor, i);\n}\n\n/**\n * Gets new utile colors for replacement, if 0 then don't replace colors.\n * @return Color index or 0.\n */\nint Armor::getUtileColor(int i) const\n{\n\treturn findWithFallback(_utileColor, i);\n}\n\n/**\n * Gets new rank colors for replacement, if 0 then don't replace colors.\n * @return Color index or 0.\n */\nint Armor::getRankColor(int i) const\n{\n\treturn findWithFallback(_rankColor, i);\n}\n\n/**\n * Can this unit's inventory be accessed for any reason?\n * @return if we can access the inventory.\n */\nbool Armor::hasInventory() const\n{\n\treturn _hasInventory;\n}\n\n/**\n* Gets the list of units this armor applies to.\n* @return The list of unit IDs (empty = applies to all).\n*/\nconst std::vector<const RuleSoldier*> &Armor::getUnitsRaw() const\n{\n\treturn _units;\n}\n\n/**\n * Check if a soldier can use this armor.\n */\nbool Armor::getCanBeUsedBy(const Soldier* soldier) const\n{\n\tif (!_units.empty())\n\t{\n\t\tif (!Collections::sortVectorHave(_units, soldier->getRules()))\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\tif (!_ranks.empty())\n\t{\n\t\tint rankInt = soldier->getRank();\n\t\tif (!Collections::sortVectorHave(_ranks, rankInt))\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\tif (_requiresAward)\n\t{\n\t\tif (!soldier->getDiary()->containsCommendation(_requiresAward))\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\tif (_requiresBonus)\n\t{\n\t\tif (!soldier->hasBonus(_requiresBonus))\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n}\n\n/**\n * Gets the index of the sprite in the CustomArmorPreview sprite set.\n * @return Sprite index.\n */\nconst std::vector<int> &Armor::getCustomArmorPreviewIndex() const\n{\n\treturn _customArmorPreviewIndex;\n}\n\n/**\n * Can you run while wearing this armor?\n * @return True if you are allowed to run.\n */\nbool Armor::allowsRunning(bool def) const\n{\n\treturn useBoolNullable(_allowsRunning, def);\n}\n\n/**\n * Can you strafe while wearing this armor?\n * @return True if you are allowed to strafe.\n */\nbool Armor::allowsStrafing(bool def) const\n{\n\treturn useBoolNullable(_allowsStrafing, def);\n}\n\n/**\n * Can you sneak while wearing this armor?\n * @return True if you are allowed to sneak.\n */\nbool Armor::allowsSneaking(bool def) const\n{\n\treturn useBoolNullable(_allowsSneaking, def);\n}\n\n/**\n * Can you kneel while wearing this armor?\n * @return True if you are allowed to kneel.\n */\nbool Armor::allowsKneeling(bool def) const\n{\n\treturn useBoolNullable(_allowsKneeling, def);\n}\n\n/**\n * Can you move while wearing this armor?\n * @return True if you are allowed to move.\n */\nbool Armor::allowsMoving() const\n{\n\treturn _allowsMoving;\n}\n\n/**\n * Does this armor instantly recover any wounds after the battle?\n * @return True if soldier should not get any recovery time.\n */\nbool Armor::getInstantWoundRecovery() const\n{\n\treturn _instantWoundRecovery;\n}\n\n/**\n * Returns a unit's height at standing in this armor.\n * @return The unit's height.\n */\nint Armor::getStandHeight() const\n{\n\treturn _standHeight;\n}\n\n/**\n * Returns a unit's height at kneeling in this armor.\n * @return The unit's kneeling height.\n */\nint Armor::getKneelHeight() const\n{\n\treturn _kneelHeight;\n}\n\n/**\n * Returns a unit's floating elevation in this armor.\n * @return The unit's floating height.\n */\nint Armor::getFloatHeight() const\n{\n\treturn _floatHeight;\n}\n\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tScript binding\n////////////////////////////////////////////////////////////\n\nnamespace\n{\n\nvoid getTypeScript(const Armor* r, ScriptText& txt)\n{\n\tif (r)\n\t{\n\t\ttxt = { r->getType().c_str() };\n\t\treturn;\n\t}\n\telse\n\t{\n\t\ttxt = ScriptText::empty;\n\t}\n}\n\nvoid getCorpseBattlescapeScript(const Armor *ar, const RuleItem* &ret)\n{\n\tif (ar && 0 < ar->getCorpseBattlescape().size())\n\t{\n\t\tret = ar->getCorpseBattlescape()[0];\n\t\treturn;\n\t}\n\tret = 0;\n}\n\nvoid getCorpseBattlescapeBigUnitScript(const Armor *ar, const RuleItem* &ret, int part)\n{\n\tif (ar && 0 <= part && (size_t)part < ar->getCorpseBattlescape().size())\n\t{\n\t\tret = ar->getCorpseBattlescape()[part];\n\t\treturn;\n\t}\n\tret = 0;\n}\n\nvoid getArmorValueScript(const Armor *ar, int &ret, int side)\n{\n\tif (ar && 0 <= side && side < SIDE_MAX)\n\t{\n\t\tret = ar->getArmor((UnitSide)side);\n\t\treturn;\n\t}\n\tret = 0;\n}\n\nstd::string debugDisplayScript(const Armor* ar)\n{\n\tif (ar)\n\t{\n\t\tstd::string s;\n\t\ts += Armor::ScriptName;\n\t\ts += \"(name: \\\"\";\n\t\ts += ar->getType();\n\t\ts += \"\\\")\";\n\t\treturn s;\n\t}\n\telse\n\t{\n\t\treturn \"null\";\n\t}\n}\n\n} // namespace\n\n/**\n * Register Armor in script parser.\n * @param parser Script parser.\n */\nvoid Armor::ScriptRegister(ScriptParserBase* parser)\n{\n\tBind<Armor> ar = { parser };\n\n\tar.addCustomConst(\"SIDE_FRONT\", SIDE_FRONT);\n\tar.addCustomConst(\"SIDE_LEFT\", SIDE_LEFT);\n\tar.addCustomConst(\"SIDE_RIGHT\", SIDE_RIGHT);\n\tar.addCustomConst(\"SIDE_REAR\", SIDE_REAR);\n\tar.addCustomConst(\"SIDE_UNDER\", SIDE_UNDER);\n\n\tar.add<&getTypeScript>(\"getType\");\n\n\tar.add<&Armor::getCorpseGeoscape>(\"getCorpseGeoscape\");\n\tar.add<&getCorpseBattlescapeScript>(\"getCorpseBattlescape\", \"Get corpse for small unit or main corpse of big unit\");\n\tar.add<&getCorpseBattlescapeBigUnitScript>(\"getCorpseBattlescape\", \"Get corpses for big unit\");\n\n\tar.add<&Armor::getRequiredResearch>(\"getRequiredResearch\");\n\n\tar.add<&Armor::getDrawingRoutine>(\"getDrawingRoutine\");\n\tar.add<&Armor::drawBubbles>(\"getDrawBubbles\");\n\tar.add<&Armor::getDeathFrames>(\"getDeathFrames\");\n\tar.add<&Armor::getConstantAnimation>(\"getConstantAnimation\");\n\n\tar.add<&Armor::getVisibilityAtDark>(\"getVisibilityAtDark\");\n\tar.add<&Armor::getVisibilityAtDay>(\"getVisibilityAtDay\");\n\tar.add<&Armor::getCamouflageAtDark>(\"getCamouflageAtDark\");\n\tar.add<&Armor::getCamouflageAtDay>(\"getCamouflageAtDay\");\n\tar.add<&Armor::getAntiCamouflageAtDark>(\"getAntiCamouflageAtDark\");\n\tar.add<&Armor::getAntiCamouflageAtDay>(\"getAntiCamouflageAtDay\");\n\tar.add<&Armor::getVisibilityThroughSmoke>(\"getHeatVision\", \"getVisibilityThroughSmoke\");\n\tar.add<&Armor::getVisibilityThroughFire>(\"getVisibilityThroughFire\", \"getVisibilityThroughFire\");\n\tar.add<&Armor::getPersonalLightFriend>(\"getPersonalLight\");\n\tar.add<&Armor::getPersonalLightHostile>(\"getPersonalLightHostile\");\n\tar.add<&Armor::getPersonalLightNeutral>(\"getPersonalLightNeutral\");\n\tar.add<&Armor::getSize>(\"getSize\");\n\n\tUnitStats::addGetStatsScript<&Armor::_stats>(ar, \"Stats.\");\n\n\tar.add<&getArmorValueScript>(\"getArmor\");\n\n\n\tar.addField<&Armor::_moveCostBase, &ArmorMoveCost::TimePercent>(\"MoveCost.getBaseTimePercent\");\n\tar.addField<&Armor::_moveCostBase, &ArmorMoveCost::EnergyPercent>(\"MoveCost.getBaseEnergyPercent\");\n\tar.addField<&Armor::_moveCostBaseNormal, &ArmorMoveCost::TimePercent>(\"MoveCost.getBaseNormalTimePercent\");\n\tar.addField<&Armor::_moveCostBaseNormal, &ArmorMoveCost::EnergyPercent>(\"MoveCost.getBaseNormalEnergyPercent\");\n\tar.addField<&Armor::_moveCostBaseFly, &ArmorMoveCost::TimePercent>(\"MoveCost.getBaseFlyTimePercent\");\n\tar.addField<&Armor::_moveCostBaseFly, &ArmorMoveCost::EnergyPercent>(\"MoveCost.getBaseFlyEnergyPercent\");\n\n\n\tar.addScriptValue<BindBase::OnlyGet, &Armor::_scriptValues>();\n\tar.addDebugDisplay<&debugDisplayScript>();\n}\n\n}\n"
  },
  {
    "path": "src/Mod/Armor.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include <vector>\n#include \"../Engine/Yaml.h\"\n#include \"MapData.h\"\n#include \"Unit.h\"\n#include \"RuleStatBonus.h\"\n#include \"RuleDamageType.h\"\n#include \"ModScript.h\"\n\nnamespace OpenXcom\n{\n\nenum ForcedTorso : Uint8;\nenum UnitSide : Uint8;\nenum AIAttackWeight : int;\n\nclass BattleUnit;\nclass RuleItem;\nclass RuleResearch;\nclass RuleSoldier;\nclass RulesoldierBonus;\nclass RuleCommendations;\n\n/**\n * Move cost multipler.\n */\nstruct ArmorMoveCost\n{\n\tint TimePercent;\n\tint EnergyPercent;\n\n\tArmorMoveCost& operator*=(ArmorMoveCost c)\n\t{\n\t\tTimePercent *= c.TimePercent;\n\t\tEnergyPercent *= c.EnergyPercent;\n\t\treturn *this;\n\t}\n\n\tbool operator==(ArmorMoveCost c) const\n\t{\n\t\treturn TimePercent == c.TimePercent && EnergyPercent == c.EnergyPercent;\n\t}\n\n\tbool operator!=(ArmorMoveCost c) const\n\t{\n\t\treturn !(*this == c);\n\t}\n\n\tvoid load(const YAML::YamlNodeReader& reader)\n\t{\n\t\tif (!reader)\n\t\t\treturn;\n\t\tTimePercent = reader[0].readVal<int>();\n\t\tEnergyPercent = reader[1].readVal<int>();\n\t}\n\tvoid save(YAML::YamlNodeWriter writer, const char* name) const\n\t{\n\t\tauto pairWriter = writer[writer.saveString(name)];\n\t\tpairWriter.setAsSeq();\n\t\tpairWriter.write(TimePercent);\n\t\tpairWriter.write(EnergyPercent);\n\t}\n};\n\n\n/**\n * Represents a specific type of armor.\n * Not only soldier armor, but also alien armor - some alien races wear\n * Soldier Armor, Leader Armor or Commander Armor depending on their rank.\n */\nclass Armor\n{\npublic:\n\n\t/// Name of class used in script.\n\tstatic constexpr const char *ScriptName = \"RuleArmor\";\n\t/// Register all useful function used by script.\n\tstatic void ScriptRegister(ScriptParserBase* parser);\n\n\tstatic const std::string NONE;\nprivate:\n\tstd::string _ufopediaType;\n\tstd::string _type, _spriteSheet, _spriteInv, _corpseGeoName, _storeItemName, _selfDestructItemName, _specWeaponName;\n\tstd::string _requiresName;\n\tstd::string _requiresAwardName;\n\tstd::string _requiresBonusName;\n\tstd::string _layersDefaultPrefix;\n\tstd::map<int, std::string> _layersSpecificPrefix;\n\tstd::map<std::string, std::vector<std::string> > _layersDefinition;\n\tstd::vector<std::string> _corpseBattleNames;\n\tstd::vector<std::string> _builtInWeaponsNames;\n\tstd::vector<std::string> _unitsNames;\n\n\tstd::vector<const RuleItem*> _corpseBattle;\n\tstd::vector<const RuleItem*> _builtInWeapons;\n\tstd::vector<const RuleSoldier*> _units;\n\tstd::vector<int> _ranks;\n\tconst RuleResearch* _requires = nullptr;\n\tconst RuleCommendations* _requiresAward = nullptr;\n\tconst RuleSoldierBonus* _requiresBonus = nullptr;\n\tconst RuleItem* _corpseGeo = nullptr;\n\tconst RuleItem* _storeItem = nullptr;\n\tconst RuleItem* _selfDestructItem = nullptr;\n\tconst RuleItem* _specWeapon = nullptr;\n\n\tbool _infiniteSupply;\n\tint _frontArmor, _sideArmor, _leftArmorDiff, _rearArmor, _underArmor, _drawingRoutine;\n\tbool _drawBubbles;\n\tMovementType _movementType;\n\tSpecialAbility _specab;\n\n\tNullableValue<AIAttackWeight> _aiTargetWeightAsHostile = { };\n\tNullableValue<AIAttackWeight> _aiTargetWeightAsHostileCivilians  = { };\n\tNullableValue<AIAttackWeight> _aiTargetWeightAsFriendly  = { };\n\tNullableValue<AIAttackWeight> _aiTargetWeightAsNeutral = { };\n\n\tbool _turnBeforeFirstStep;\n\tint _turnCost;\n\n\tArmorMoveCost _moveCostBase = { 100, 100 };\n\tArmorMoveCost _moveCostBaseFly = { 100, 100 };\n\tArmorMoveCost _moveCostBaseClimb = { 100, 100 };\n\tArmorMoveCost _moveCostBaseNormal = { 100, 100 };\n\n\tArmorMoveCost _moveCostWalk = { 100, 50 };\n\tArmorMoveCost _moveCostRun = { 75, 75 };\n\tArmorMoveCost _moveCostStrafe = { 100, 50 };\n\tArmorMoveCost _moveCostSneak = { 100, 50 };\n\tArmorMoveCost _moveCostFlyWalk = { 100, 50 };\n\tArmorMoveCost _moveCostFlyRun = { 75, 75 };\n\tArmorMoveCost _moveCostFlyStrafe = { 100, 50 };\n\tArmorMoveCost _moveCostFlyUp = { 100, 0 };\n\tArmorMoveCost _moveCostFlyDown = { 100, 0 };\n\tArmorMoveCost _moveCostClimbUp = { 100, 50 };\n\tArmorMoveCost _moveCostClimbDown = { 100, 50 };\n\tArmorMoveCost _moveCostGravLift = { 100, 0 };\n\n\tint _moveSound;\n\tstd::vector<int> _deathSoundMale, _deathSoundFemale;\n\tstd::vector<int> _selectUnitSoundMale, _selectUnitSoundFemale;\n\tstd::vector<int> _startMovingSoundMale, _startMovingSoundFemale;\n\tstd::vector<int> _selectWeaponSoundMale, _selectWeaponSoundFemale;\n\tstd::vector<int> _annoyedSoundMale, _annoyedSoundFemale;\n\n\tint _size, _weight, _visibilityAtDark, _visibilityAtDay;\n\n\tint _personalLightFriend = 15;\n\tint _personalLightHostile = 0;\n\tint _personalLightNeutral = 0;\n\n\tint _camouflageAtDay, _camouflageAtDark, _antiCamouflageAtDay, _antiCamouflageAtDark;\n\tint _visibilityThroughSmoke, _visibilityThroughFire;\n\tint _psiVision, _psiCamouflage;\n\tfloat _damageModifier[DAMAGE_TYPES];\n\tstd::vector<int> _loftempsSet;\n\tUnitStats _stats;\n\tint _deathFrames;\n\tbool _constantAnimation, _hasInventory;\n\tForcedTorso _forcedTorso;\n\tint _faceColorGroup, _hairColorGroup, _utileColorGroup, _rankColorGroup;\n\tstd::vector<int> _faceColor, _hairColor, _utileColor, _rankColor;\n\tSint8  _fearImmune, _bleedImmune, _painImmune, _zombiImmune;\n\tSint8 _ignoresMeleeThreat, _createsMeleeThreat;\n\tfloat _overKill, _meleeDodgeBackPenalty;\n\tRuleStatBonus _psiDefence, _meleeDodge;\n\tRuleStatBonus _timeRecovery, _energyRecovery, _moraleRecovery, _healthRecovery, _stunRecovery, _manaRecovery;\n\tModScript::BattleUnitScripts::Container _battleUnitScripts;\n\n\tScriptValues<Armor> _scriptValues;\n\tstd::vector<int> _customArmorPreviewIndex;\n\tSint8 _allowsRunning, _allowsStrafing, _allowsSneaking, _allowsKneeling, _allowsMoving;\n\tbool _isPilotArmor;\n\tbool _allowTwoMainWeapons;\n\tbool _instantWoundRecovery;\n\tbool _isAlwaysVisible = false;\n\tint _standHeight, _kneelHeight, _floatHeight;\n\tint _meleeOriginVoxelVerticalOffset;\n\tint _group;\n\tint _listOrder;\npublic:\n\t/// Creates a blank armor ruleset.\n\tArmor(const std::string &type, int listOrder);\n\t/// Cleans up the armor ruleset.\n\t~Armor();\n\n\t/// Loads the armor data from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader, Mod *mod, const ModScript& parsers);\n\t/// Cross link with other rules.\n\tvoid afterLoad(const Mod* mod);\n\t/// Gets whether or not there is an infinite supply of this armor.\n\tbool hasInfiniteSupply() const { return _infiniteSupply; }\n\n\t/// Gets the custom name of the Ufopedia article related to this armor.\n\tconst std::string& getUfopediaType() const;\n\n\t/// Gets the armor's type.\n\tconst std::string& getType() const;\n\t/// Gets the unit's sprite sheet.\n\tstd::string getSpriteSheet() const;\n\t/// Gets the unit's inventory sprite.\n\tstd::string getSpriteInventory() const;\n\t/// Gets the front armor level.\n\tint getFrontArmor() const;\n\t/// Gets the left side armor level.\n\tint getLeftSideArmor() const;\n\t/// Gets the right side armor level.\n\tint getRightSideArmor() const;\n\t/// Gets the rear armor level.\n\tint getRearArmor() const;\n\t/// Gets the under armor level.\n\tint getUnderArmor() const;\n\t/// Gets the armor level of armor side.\n\tint getArmor(UnitSide side) const;\n\t/// Gets the Geoscape corpse item.\n\tconst RuleItem* getCorpseGeoscape() const;\n\t/// Gets the Battlescape corpse item.\n\tconst std::vector<const RuleItem*> &getCorpseBattlescape() const;\n\t/// Gets the Geoscape corpse item.\n\tconst RuleItem* getSelfDestructItem() const { return _selfDestructItem ? _selfDestructItem : _corpseGeo && _corpseGeo->getPower() > 0 ? _corpseGeo : nullptr; }\n\t/// Gets the stores item.\n\tconst RuleItem* getStoreItem() const;\n\t/// Gets the special weapon type.\n\tconst RuleItem* getSpecialWeapon() const;\n\t/// Gets the research required to be able to equip this armor.\n\tconst RuleResearch* getRequiredResearch() const;\n\t/// Gets the commendation required to be able to equip this armor.\n\tconst RuleCommendations* getRequiredAward() const { return _requiresAward; }\n\t/// Gets the soldier bonus required to be able to equip this armor.\n\tconst RuleSoldierBonus* getRequiredBonus() const { return _requiresBonus; }\n\n\t/// Armor have layered armor definition. Check by Prefix.\n\tbool hasLayersDefinition() const { return !_layersDefaultPrefix.empty(); }\n\t/// Gets the default prefix for layered armor sprite names.\n\tconst std::string &getLayersDefaultPrefix() const { return _layersDefaultPrefix; }\n\t/// Gets the overrides for layered armor sprite name prefix, per layer.\n\tconst std::map<int, std::string> &getLayersSpecificPrefix() const { return _layersSpecificPrefix; }\n\t/// Gets the layered armor definition.\n\tconst std::map<std::string, std::vector<std::string> > &getLayersDefinition() const { return _layersDefinition; }\n\n\t/// Gets the battlescape drawing routine ID.\n\tint getDrawingRoutine() const;\n\t/// Gets whether or not to draw bubbles (breathing animation).\n\tbool drawBubbles() const;\n\t/// DO NOT USE THIS FUNCTION OUTSIDE THE BATTLEUNIT CONSTRUCTOR OR I WILL HUNT YOU DOWN.\n\tMovementType getMovementType() const;\n\t/// Get MovementType based on depth of battle.\n\tMovementType getMovementTypeByDepth(int depth) const;\n\t/// Gets the armor's special ability.\n\tint getSpecialAbility() const;\n\n\t/// Gets weight value as hostile unit.\n\tNullableValue<AIAttackWeight> getAITargetWeightAsHostile() const { return _aiTargetWeightAsHostile; }\n\t/// Gets weight value as civilian unit when consider by aliens.\n\tNullableValue<AIAttackWeight> getAITargetWeightAsHostileCivilians() const { return _aiTargetWeightAsHostileCivilians; }\n\t/// Gets weight value as same faction unit.\n\tNullableValue<AIAttackWeight> getAITargetWeightAsFriendly() const { return _aiTargetWeightAsFriendly; }\n\t/// Gets weight value as neutral unit (xcom to civ or vice versa).\n\tNullableValue<AIAttackWeight> getAITargetWeightAsNeutral() const { return _aiTargetWeightAsNeutral; }\n\n\t/// Should turning before first step cost TU or not?\n\tbool getTurnBeforeFirstStep() const { return _turnBeforeFirstStep; }\n\t/// Gets the turn cost.\n\tint getTurnCost() const { return _turnCost; }\n\n\t/// Multiplier of all move costs.\n\tArmorMoveCost getMoveCostBase() const { return _moveCostBase; }\n\t/// Multiplier of normal base move cost.\n\tArmorMoveCost getMoveCostBaseNormal() const { return _moveCostBaseNormal; }\n\t/// Multiplier of fly base move cost.\n\tArmorMoveCost getMoveCostBaseFly() const { return _moveCostBaseFly; }\n\t/// Multiplier of climb base move cost.\n\tArmorMoveCost getMoveCostBaseClimb() const { return _moveCostBaseClimb; }\n\n\t/// Multiplier of walk move cost.\n\tArmorMoveCost getMoveCostWalk() const { return _moveCostWalk; }\n\t/// Multiplier of run move cost.\n\tArmorMoveCost getMoveCostRun() const { return _moveCostRun; }\n\t/// Multiplier of strafe move cost.\n\tArmorMoveCost getMoveCostStrafe() const { return _moveCostStrafe; }\n\t/// Multiplier of sneak move cost.\n\tArmorMoveCost getMoveCostSneak() const { return _moveCostSneak; }\n\t/// Multiplier of fly \"walk\" move cost.\n\tArmorMoveCost getMoveCostFlyWalk() const { return _moveCostFlyWalk; }\n\t/// Multiplier of fly \"run\" move cost.\n\tArmorMoveCost getMoveCostFlyRun() const { return _moveCostFlyRun; }\n\t/// Multiplier of fly \"strafe\" cost.\n\tArmorMoveCost getMoveCostFlyStrafe() const { return _moveCostFlyStrafe; }\n\t/// Multiplier of fly up move cost.\n\tArmorMoveCost getMoveCostFlyUp() const { return _moveCostFlyUp; }\n\t/// Multiplier of fly down move cost.\n\tArmorMoveCost getMoveCostFlyDown() const { return _moveCostFlyDown; }\n\t/// Multiplier of climb up move cost.\n\tArmorMoveCost getMoveCostClimbUp() const { return _moveCostClimbUp; }\n\t/// Multiplier of climb down move cost.\n\tArmorMoveCost getMoveCostClimbDown() const { return _moveCostClimbDown; }\n\t/// Multiplier of moving using GravLift cost.\n\tArmorMoveCost getMoveCostGravLift() const { return _moveCostGravLift; }\n\n\t/// Gets the move sound id. Overrides default/unit's move sound. To be used in BattleUnit constructors only too!\n\tint getMoveSound() const;\n\t/// Gets the male death sounds.\n\tconst std::vector<int> &getMaleDeathSounds() const { return _deathSoundMale; }\n\t/// Gets the female death sounds.\n\tconst std::vector<int> &getFemaleDeathSounds() const { return _deathSoundFemale; }\n\t/// Gets the male \"select unit\" sounds.\n\tconst std::vector<int> &getMaleSelectUnitSounds() const { return _selectUnitSoundMale; }\n\t/// Gets the female \"select unit\" sounds.\n\tconst std::vector<int> &getFemaleSelectUnitSounds() const { return _selectUnitSoundFemale; }\n\t/// Gets the male \"start moving\" sounds.\n\tconst std::vector<int> &getMaleStartMovingSounds() const { return _startMovingSoundMale; }\n\t/// Gets the female \"start moving\" sounds.\n\tconst std::vector<int> &getFemaleStartMovingSounds() const { return _startMovingSoundFemale; }\n\t/// Gets the male \"select weapon\" sounds.\n\tconst std::vector<int> &getMaleSelectWeaponSounds() const { return _selectWeaponSoundMale; }\n\t/// Gets the female \"select weapon\" sounds.\n\tconst std::vector<int> &getFemaleSelectWeaponSounds() const { return _selectWeaponSoundFemale; }\n\t/// Gets the male \"annoyed\" sounds.\n\tconst std::vector<int> &getMaleAnnoyedSounds() const { return _annoyedSoundMale; }\n\t/// Gets the female \"annoyed\" sounds.\n\tconst std::vector<int> &getFemaleAnnoyedSounds() const { return _annoyedSoundFemale; }\n\t/// Gets whether this is a normal or big unit.\n\tint getSize() const;\n\t/// Gets how much space the armor occupies in a craft.\n\tint getTotalSize() const;\n\t/// Gets damage modifier.\n\tfloat getDamageModifier(ItemDamageType dt) const;\n\tconst std::vector<float> getDamageModifiersRaw() const;\n\t/// Gets loftempSet\n\tconst std::vector<int> &getLoftempsSet() const;\n\t/// Gets the armor's stats.\n\tconst UnitStats *getStats() const;\n\t/// Gets unit psi defense.\n\tint getPsiDefence(const BattleUnit* unit) const;\n\tconst RuleStatBonus *getPsiDefenceRaw() const { return &_psiDefence; }\n\t/// Gets unit melee dodge chance.\n\tint getMeleeDodge(const BattleUnit* unit) const;\n\tconst RuleStatBonus *getMeleeDodgeRaw() const { return &_meleeDodge; }\n\t/// Gets unit dodge penalty if hit from behind.\n\tfloat getMeleeDodgeBackPenalty() const;\n\n\t/// Gets unit TU recovery.\n\tint getTimeRecovery(const BattleUnit* unit, int externalBonuses) const;\n\tconst RuleStatBonus *getTimeRecoveryRaw() const { return &_timeRecovery; }\n\t/// Gets unit Energy recovery.\n\tint getEnergyRecovery(const BattleUnit* unit, int externalBonuses) const;\n\tconst RuleStatBonus *getEnergyRecoveryRaw() const { return &_energyRecovery; }\n\t/// Gets unit Morale recovery.\n\tint getMoraleRecovery(const BattleUnit* unit, int externalBonuses) const;\n\tconst RuleStatBonus *getMoraleRecoveryRaw() const { return &_moraleRecovery; }\n\t/// Gets unit Health recovery.\n\tint getHealthRecovery(const BattleUnit* unit, int externalBonuses) const;\n\tconst RuleStatBonus *getHealthRecoveryRaw() const { return &_healthRecovery; }\n\t/// Gets unit Mana recovery.\n\tint getManaRecovery(const BattleUnit* unit, int externalBonuses) const;\n\tconst RuleStatBonus* getManaRecoveryRaw() const { return &_manaRecovery; }\n\t/// Gets unit Stun recovery.\n\tint getStunRegeneration(const BattleUnit* unit, int externalBonuses) const;\n\tconst RuleStatBonus *getStunRegenerationRaw() const { return &_stunRecovery; }\n\n\t/// Gets the armor's weight.\n\tint getWeight() const;\n\t/// Gets number of death frames.\n\tint getDeathFrames() const;\n\t/// Gets if armor uses constant animation.\n\tbool getConstantAnimation() const;\n\t/// Checks if this armor ignores gender (power suit/flying suit).\n\tForcedTorso getForcedTorso() const;\n\t/// Gets built-in weapons of armor.\n\tconst std::vector<const RuleItem*> &getBuiltInWeapons() const;\n\n\t/// Gets max view distance at dark in BattleScape.\n\tint getVisibilityAtDark() const;\n\t/// Gets max view distance at day in BattleScape.\n\tint getVisibilityAtDay() const;\n\t/// Gets info about camouflage at day.\n\tint getCamouflageAtDay() const;\n\t/// Gets info about camouflage at dark.\n\tint getCamouflageAtDark() const;\n\t/// Gets info about anti camouflage at day.\n\tint getAntiCamouflageAtDay() const;\n\t/// Gets info about anti camouflage at dark.\n\tint getAntiCamouflageAtDark() const;\n\t/// Gets info about heat vision.\n\tint getVisibilityThroughSmoke() const { return _visibilityThroughSmoke; }\n\t/// Gets info about visibility through fire.\n\tint getVisibilityThroughFire() const { return _visibilityThroughFire; }\n\t/// Gets info about psi vision.\n\tint getPsiVision() const;\n\t/// Gets info about psi camouflage.\n\tint getPsiCamouflage() const;\n\t/// Gets personal soldier light radius;\n\tint getPersonalLightFriend() const;\n\t/// Gets personal alien light radius;\n\tint getPersonalLightHostile() const;\n\t/// Gets personal civilian light radius;\n\tint getPersonalLightNeutral() const;\n\t/// Gets if unit should be always visible.\n\tbool isAlwaysVisible() const { return _isAlwaysVisible; }\n\n\t/// Gets how armor react to fear.\n\tbool getFearImmune(bool def = false) const;\n\t/// Gets how armor react to bleeding.\n\tbool getBleedImmune(bool def = false) const;\n\t/// Gets how armor react to inflicted pain.\n\tbool getPainImmune(bool def = false) const;\n\t/// Gets how armor react to zombification.\n\tbool getZombiImmune(bool def = false) const;\n\t/// Gets whether or not this unit ignores close quarters threats.\n\tbool getIgnoresMeleeThreat(bool def = false) const;\n\t/// Gets whether or not this unit is a close quarters threat.\n\tbool getCreatesMeleeThreat(bool def = true) const;\n\t/// Gets how much damage (over the maximum HP) is needed to vaporize/disintegrate a unit.\n\tfloat getOverKill() const;\n\t/// Get face base color\n\tint getFaceColorGroup() const;\n\t/// Get hair base color\n\tint getHairColorGroup() const;\n\t/// Get utile base color\n\tint getUtileColorGroup() const;\n\t/// Get rank base color\n\tint getRankColorGroup() const;\n\t/// Get face base color\n\tint getFaceColor(int i) const;\n\tconst std::vector<int> &getFaceColorRaw() const { return _faceColor; }\n\t/// Get hair base color\n\tint getHairColor(int i) const;\n\tconst std::vector<int> &getHairColorRaw() const { return _hairColor; }\n\t/// Get utile base color\n\tint getUtileColor(int i) const;\n\tconst std::vector<int> &getUtileColorRaw() const { return _utileColor; }\n\t/// Get rank base color\n\tint getRankColor(int i) const;\n\tconst std::vector<int> &getRankColorRaw() const { return _rankColor; }\n\t/// Can we access this unit's inventory?\n\tbool hasInventory() const;\n\t/// Gets script.\n\ttemplate<typename Script>\n\tconst typename Script::Container &getScript() const { return _battleUnitScripts.get<Script>(); }\n\t/// Get all script values.\n\tconst ScriptValues<Armor> &getScriptValuesRaw() const { return _scriptValues; }\n\n\t/// Gets the armor's units.\n\tconst std::vector<const RuleSoldier*> &getUnitsRaw() const;\n\t/// Gets the armor's supported soldier ranks.\n\tconst std::vector<int>& getRanksRaw() const { return _ranks; }\n\t/// Check if a soldier can use this armor.\n\tbool getCanBeUsedBy(const Soldier* soldier) const;\n\n\n\t/// Gets the index of the sprite in the CustomArmorPreview sprite set\n\tconst std::vector<int> &getCustomArmorPreviewIndex() const;\n\t/// Can you run while wearing this armor?\n\tbool allowsRunning(bool def = true) const;\n\t/// Can you strafe while wearing this armor?\n\tbool allowsStrafing(bool def = true) const;\n\t/// Can you sneak while wearing this armor?\n\tbool allowsSneaking(bool def = true) const;\n\t/// Can you kneel while wearing this armor?\n\tbool allowsKneeling(bool def = true) const;\n\t/// Can you move while wearing this armor?\n\tbool allowsMoving() const;\n\t/// Does this armor count for pilot bonuses?\n\tbool isPilotArmor() const { return _isPilotArmor; }\n\t/// Does this armor allow two main weapons during autoequip?\n\tbool getAllowTwoMainWeapons() const { return _allowTwoMainWeapons; }\n\t/// Does this armor instantly recover any wounds after the battle?\n\tbool getInstantWoundRecovery() const;\n\t/// Gets a unit's height when standing while wearing this armor.\n\tint getStandHeight() const;\n\t/// Gets a unit's height when kneeling while wearing this armor.\n\tint getKneelHeight() const;\n\t/// Gets a unit's float elevation while wearing this armor.\n\tint getFloatHeight() const;\n\t/// Gets a unit's offset for melee attacks.\n\tint getMeleeOriginVoxelVerticalOffset() const { return _meleeOriginVoxelVerticalOffset; }\n\n\t/// Gets the armor type group.\n\tint getGroup() const { return _group; }\n\t/// Get the list weight for this armor.\n\tint getListOrder() const { return _listOrder; }\n};\n\n}\n"
  },
  {
    "path": "src/Mod/ArticleDefinition.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"ArticleDefinition.h\"\n#include \"../Engine/Exception.h\"\n#include \"../Mod/RuleItem.h\"\n\nnamespace OpenXcom\n{\n\n\t/**\n\t * Constructor.\n\t * @param type_id Article type of this instance.\n\t */\n\tArticleDefinition::ArticleDefinition(UfopaediaTypeId type_id) : customPalette(false), hiddenCommendation(false), _type_id(type_id), _listOrder(0)\n\t{\n\t\t_pages.resize(1);\n\t}\n\n\t/**\n\t * Destructor.\n\t */\n\tArticleDefinition::~ArticleDefinition()\n\t{}\n\n\t/**\n\t * Gets the article definition type. (Text, TextImage, Craft, ...)\n\t * @return The type of article definition of this instance.\n\t */\n\tUfopaediaTypeId ArticleDefinition::getType() const\n\t{\n\t\treturn _type_id;\n\t}\n\n\t/**\n\t * Loads the article definition from a YAML file.\n\t * @param node YAML node.\n\t * @param listOrder The list weight for this article.\n\t */\n\tvoid ArticleDefinition::load(const YAML::YamlNodeReader& reader, int listOrder)\n\t{\n\t\treader.tryRead(\"id\", id);\n\t\t_pages[0].title = id;\n\t\treader.tryRead(\"section\", section);\n\t\treader.tryRead(\"requires\", _requires);\n\t\treader.tryRead(\"disabledBy\", disabledBy);\n\t\treader.tryRead(\"hiddenCommendation\", hiddenCommendation);\n\t\t//_type_id = (UfopaediaTypeId)node[\"type_id\"].as<int>(_type_id);\n\t\treader.tryRead(\"listOrder\", _listOrder);\n\t\tif (!_listOrder)\n\t\t{\n\t\t\t_listOrder = listOrder;\n\t\t}\n\n\t\tauto loadPage = [&](size_t offset, const YAML::YamlNodeReader& r)\n\t\t{\n\t\t\tif (r)\n\t\t\t{\n\t\t\t\tr.tryRead(\"title\", _pages[offset].title);\n\t\t\t\tr.tryRead(\"text\", _pages[offset].text);\n\t\t\t\tRuleItem::loadAmmoSlotChecked(_pages[offset].ammoSlot, r[\"ammoSlot\"], id);\n\t\t\t}\n\t\t};\n\n\t\tloadPage(0, reader);\n\t\tif (const auto& pagesNode = reader[\"pages\"])\n\t\t{\n\t\t\tif (pagesNode.isSeq())\n\t\t\t{\n\t\t\t\tsize_t size = pagesNode.childrenCount();\n\t\t\t\tArticlePage firstCopy = _pages[0];\n\t\t\t\t_pages.resize(std::max(size_t{ 1 }, size), firstCopy); //all new pages are copy of old first page\n\t\t\t\tfor (size_t i = 0; i < size; ++i)\n\t\t\t\t{\n\t\t\t\t\tloadPage(i, pagesNode[i]);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tthrow Exception(\"Unsupported type of node 'pages' for Article '\" + id + \"'\");\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Gets the list weight of the article.\n\t * @return The list weight of the article.\n\t */\n\tint ArticleDefinition::getListOrder() const\n\t{\n\t\treturn _listOrder;\n\t}\n\n\t/**\n\t * Constructor.\n\t */\n\tArticleDefinitionRect::ArticleDefinitionRect() : x(0), y(0), width(0), height(0) {}\n\n\t/**\n\t * Sets the rectangle parameters in a function.\n\t * @param set_x X.\n\t * @param set_y Y.\n\t * @param set_width Width.\n\t * @param set_height Height.\n\t */\n\tvoid ArticleDefinitionRect::set(int set_x, int set_y, int set_width, int set_height)\n\t{\n\t\tx = set_x;\n\t\ty = set_y;\n\t\twidth = set_width;\n\t\theight = set_height;\n\t}\n\n\t/**\n\t * Constructor (only setting type of base class).\n\t */\n\tArticleDefinitionUnit::ArticleDefinitionUnit() : ArticleDefinition(UFOPAEDIA_TYPE_UNIT), unit_mode(0)\n\t{\n\t}\n\n\t/**\n\t * Loads the article definition from a YAML file.\n\t * @param node YAML node.\n\t * @param listOrder The list weight for this article.\n\t */\n\tvoid ArticleDefinitionUnit::load(const YAML::YamlNodeReader& reader, int listOrder)\n\t{\n\t\tArticleDefinition::load(reader, listOrder);\n\t\treader.tryRead(\"unit_mode\", unit_mode);\n\t\treader.tryRead(\"image_id\", image_id);\n\t\tif (image_id.find(\"_CPAL\") != std::string::npos)\n\t\t\tcustomPalette = true;\n\t\treader.tryRead(\"rect_stats\", rect_stats);\n\t\treader.tryRead(\"rect_armor\", rect_armor);\n\t\treader.tryRead(\"rect_text\", rect_text);\n\t}\n\n\t/**\n\t * Constructor (only setting type of base class).\n\t */\n\tArticleDefinitionSoldier::ArticleDefinitionSoldier() : ArticleDefinition(UFOPAEDIA_TYPE_SOLDIER), psi_skill_mode(0)\n\t{\n\t}\n\n\t/**\n\t * Loads the article definition from a YAML file.\n\t * @param node YAML node.\n\t * @param listOrder The list weight for this article.\n\t */\n\tvoid ArticleDefinitionSoldier::load(const YAML::YamlNodeReader& reader, int listOrder)\n\t{\n\t\tArticleDefinition::load(reader, listOrder);\n\t\treader.tryRead(\"psi_skill_mode\", psi_skill_mode);\n\t\treader.tryRead(\"image_id\", image_id);\n\t\tif (image_id.find(\"_CPAL\") != std::string::npos)\n\t\t\tcustomPalette = true;\n\t\treader.tryRead(\"rect_stats\", rect_stats);\n\t\treader.tryRead(\"rect_text\", rect_text);\n\t}\n\n\t/**\n\t * Constructor (only setting type of base class).\n\t */\n\tArticleDefinitionCraft::ArticleDefinitionCraft() : ArticleDefinition(UFOPAEDIA_TYPE_CRAFT)\n\t{}\n\n\t/**\n\t * Loads the article definition from a YAML file.\n\t * @param node YAML node.\n\t * @param listOrder The list weight for this article.\n\t */\n\tvoid ArticleDefinitionCraft::load(const YAML::YamlNodeReader& reader, int listOrder)\n\t{\n\t\tArticleDefinition::load(reader, listOrder);\n\t\treader.tryRead(\"image_id\", image_id);\n\t\tif (image_id.find(\"_CPAL\") != std::string::npos)\n\t\t\tcustomPalette = true;\n\t\treader.tryRead(\"rect_stats\", rect_stats);\n\t\treader.tryRead(\"rect_text\", rect_text);\n\t}\n\n\t/**\n\t * Constructor (only setting type of base class).\n\t */\n\tArticleDefinitionCraftWeapon::ArticleDefinitionCraftWeapon() : ArticleDefinition(UFOPAEDIA_TYPE_CRAFT_WEAPON)\n\t{}\n\n\t/**\n\t * Loads the article definition from a YAML file.\n\t * @param node YAML node.\n\t * @param listOrder The list weight for this article.\n\t */\n\tvoid ArticleDefinitionCraftWeapon::load(const YAML::YamlNodeReader& reader, int listOrder)\n\t{\n\t\tArticleDefinition::load(reader, listOrder);\n\t\treader.tryRead(\"image_id\", image_id);\n\t\tif (image_id.find(\"_CPAL\") != std::string::npos)\n\t\t\tcustomPalette = true;\n\t}\n\n\t/**\n\t * Constructor (only setting type of base class).\n\t */\n\tArticleDefinitionText::ArticleDefinitionText() : ArticleDefinition(UFOPAEDIA_TYPE_TEXT)\n\t{}\n\n\t/**\n\t * Loads the article definition from a YAML file.\n\t * @param node YAML node.\n\t * @param listOrder The list weight for this article.\n\t */\n\tvoid ArticleDefinitionText::load(const YAML::YamlNodeReader& reader, int listOrder)\n\t{\n\t\tArticleDefinition::load(reader, listOrder);\n\t}\n\n\t/**\n\t * Constructor (only setting type of base class).\n\t */\n\tArticleDefinitionTextImage::ArticleDefinitionTextImage() : ArticleDefinition(UFOPAEDIA_TYPE_TEXTIMAGE), text_width(0), align_bottom(false)\n\t{}\n\n\t/**\n\t * Loads the article definition from a YAML file.\n\t * @param node YAML node.\n\t * @param listOrder The list weight for this article.\n\t */\n\tvoid ArticleDefinitionTextImage::load(const YAML::YamlNodeReader& reader, int listOrder)\n\t{\n\t\tArticleDefinition::load(reader, listOrder);\n\t\treader.tryRead(\"image_id\", image_id);\n\t\tif (image_id.find(\"_CPAL\") != std::string::npos)\n\t\t\tcustomPalette = true;\n\t\treader.tryRead(\"text_width\", text_width);\n\t\treader.tryRead(\"align_bottom\", align_bottom);\n\t\treader.tryRead(\"rect_text\", rect_text);\n\t}\n\n\t/**\n\t * Constructor (only setting type of base class).\n\t */\n\tArticleDefinitionTFTD::ArticleDefinitionTFTD() : ArticleDefinition(UFOPAEDIA_TYPE_TFTD), text_width(0)\n\t{}\n\n\t/**\n\t * Loads the article definition from a YAML file.\n\t * @param node YAML node.\n\t * @param listOrder The list weight for this article.\n\t */\n\tvoid ArticleDefinitionTFTD::load(const YAML::YamlNodeReader& reader, int listOrder)\n\t{\n\t\tArticleDefinition::load(reader, listOrder);\n\t\treader.tryRead(\"type_id\", _type_id);\n\t\treader.tryRead(\"image_id\", image_id);\n\t\tif (image_id.find(\"_CPAL\") != std::string::npos)\n\t\t\tcustomPalette = true;\n\t\ttext_width = reader[\"text_width\"].readVal(157); // 95% of these won't need to be defined, so let's give it a default\n\t\treader.tryRead(\"weapon\", weapon);\n\t}\n\n\t/**\n\t * Constructor (only setting type of base class).\n\t */\n\tArticleDefinitionBaseFacility::ArticleDefinitionBaseFacility() : ArticleDefinition(UFOPAEDIA_TYPE_BASE_FACILITY)\n\t{}\n\n\t/**\n\t * Loads the article definition from a YAML file.\n\t * @param node YAML node.\n\t * @param listOrder The list weight for this article.\n\t */\n\tvoid ArticleDefinitionBaseFacility::load(const YAML::YamlNodeReader& reader, int listOrder)\n\t{\n\t\tArticleDefinition::load(reader, listOrder);\n\t}\n\n\t/**\n\t * Constructor (only setting type of base class).\n\t */\n\tArticleDefinitionItem::ArticleDefinitionItem() : ArticleDefinition(UFOPAEDIA_TYPE_ITEM)\n\t{}\n\n\t/**\n\t * Loads the article definition from a YAML file.\n\t * @param node YAML node.\n\t * @param listOrder The list weight for this article.\n\t */\n\tvoid ArticleDefinitionItem::load(const YAML::YamlNodeReader& reader, int listOrder)\n\t{\n\t\tArticleDefinition::load(reader, listOrder);\n\t\treader.tryRead(\"weapon\", weapon);\n\t}\n\n\t/**\n\t * Constructor (only setting type of base class).\n\t */\n\tArticleDefinitionUfo::ArticleDefinitionUfo() : ArticleDefinition(UFOPAEDIA_TYPE_UFO)\n\t{}\n\n\t/**\n\t * Loads the article definition from a YAML file.\n\t * @param node YAML node.\n\t * @param listOrder The list weight for this article.\n\t */\n\tvoid ArticleDefinitionUfo::load(const YAML::YamlNodeReader& reader, int listOrder)\n\t{\n\t\tArticleDefinition::load(reader, listOrder);\n\t}\n\n\t/**\n\t * Constructor (only setting type of base class).\n\t */\n\tArticleDefinitionArmor::ArticleDefinitionArmor() : ArticleDefinition(UFOPAEDIA_TYPE_ARMOR)\n\t{}\n\n\t/**\n\t * Loads the article definition from a YAML file.\n\t * @param node YAML node.\n\t * @param listOrder The list weight for this article.\n\t */\n\tvoid ArticleDefinitionArmor::load(const YAML::YamlNodeReader& reader, int listOrder)\n\t{\n\t\tArticleDefinition::load(reader, listOrder);\n\t\treader.tryRead(\"image_id\", image_id);\n\t\tif (image_id.find(\"_CPAL\") != std::string::npos)\n\t\t\tcustomPalette = true;\n\t}\n\n\t/**\n\t * Constructor (only setting type of base class)\n\t */\n\tArticleDefinitionVehicle::ArticleDefinitionVehicle() : ArticleDefinition(UFOPAEDIA_TYPE_VEHICLE)\n\t{}\n\n\t/**\n\t * Loads the article definition from a YAML file.\n\t * @param node YAML node.\n\t * @param listOrder The list weight for this article.\n\t */\n\tvoid ArticleDefinitionVehicle::load(const YAML::YamlNodeReader& reader, int listOrder)\n\t{\n\t\tArticleDefinition::load(reader, listOrder);\n\t\treader.tryRead(\"image_id\", image_id);\n\t\tif (image_id.find(\"_CPAL\") != std::string::npos)\n\t\t\tcustomPalette = true;\n\t\treader.tryRead(\"weapon\", weapon);\n\t}\n\n\t// helper overloads for deserialization-only\n\tbool read(ryml::ConstNodeRef const& n, ArticleDefinitionRect* val)\n\t{\n\t\tYAML::YamlNodeReader reader(n);\n\t\treader.tryRead(\"x\", val->x);\n\t\treader.tryRead(\"y\", val->y);\n\t\treader.tryRead(\"width\", val->width);\n\t\treader.tryRead(\"height\", val->height);\n\t\treturn true;\n\t}\n}\n"
  },
  {
    "path": "src/Mod/ArticleDefinition.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include <vector>\n#include \"../Engine/Yaml.h\"\n#include \"../Engine/Exception.h\"\n\nnamespace OpenXcom\n{\n\t/// define article types\n\tenum UfopaediaTypeId {\n\t\tUFOPAEDIA_TYPE_UNKNOWN            = 0,\n\t\tUFOPAEDIA_TYPE_CRAFT              = 1,\n\t\tUFOPAEDIA_TYPE_CRAFT_WEAPON       = 2,\n\t\tUFOPAEDIA_TYPE_VEHICLE            = 3,\n\t\tUFOPAEDIA_TYPE_ITEM               = 4,\n\t\tUFOPAEDIA_TYPE_ARMOR              = 5,\n\t\tUFOPAEDIA_TYPE_BASE_FACILITY      = 6,\n\t\tUFOPAEDIA_TYPE_TEXTIMAGE          = 7,\n\t\tUFOPAEDIA_TYPE_TEXT               = 8,\n\t\tUFOPAEDIA_TYPE_UFO                = 9,\n\t\tUFOPAEDIA_TYPE_TFTD               = 10,\n\t\tUFOPAEDIA_TYPE_TFTD_CRAFT         = 11,\n\t\tUFOPAEDIA_TYPE_TFTD_CRAFT_WEAPON  = 12,\n\t\tUFOPAEDIA_TYPE_TFTD_VEHICLE       = 13,\n\t\tUFOPAEDIA_TYPE_TFTD_ITEM          = 14,\n\t\tUFOPAEDIA_TYPE_TFTD_ARMOR         = 15,\n\t\tUFOPAEDIA_TYPE_TFTD_BASE_FACILITY = 16,\n\t\tUFOPAEDIA_TYPE_TFTD_USO           = 17,\n\t\tUFOPAEDIA_TYPE_SOLDIER            = 18,\n\t\tUFOPAEDIA_TYPE_UNIT               = 19\n\t};\n\n\t/**\n\t * Definition of one sub page of ufopedia article\n\t */\n\tstruct ArticlePage\n\t{\n\t\tstd::string title;\n\t\tstd::string text;\n\t\tint ammoSlot = 0;\n\t};\n\n\t/**\n\t * ArticleDefinition is the base class for all article types.\n\t * This class is used to store all information about articles\n\t * required to generate an ArticleState from.\n\t */\n\tclass ArticleDefinition\n\t{\n\tprotected:\n\t\t/// Constructor (protected, so this class cannot be instantiated directly).\n\t\tArticleDefinition(UfopaediaTypeId type_id);\n\n\tpublic:\n\t\tstatic const int PEDIA_STATUS_NEW = 0;\n\t\tstatic const int PEDIA_STATUS_NORMAL = 1;\n\t\tstatic const int PEDIA_STATUS_HIDDEN = 2;\n\t\tstatic const int PEDIA_STATUSES = 3;\n\t\t/// Destructor.\n\t\tvirtual ~ArticleDefinition();\n\t\t/// Gets the type of article definition.\n\t\tUfopaediaTypeId getType() const;\n\t\t/// Loads the article from YAML.\n\t\tvirtual void load(const YAML::YamlNodeReader& reader, int listOrder);\n\t\t/// Gets the article's list weight.\n\t\tint getListOrder() const;\n\n\t\tstd::string id;\n\t\tstd::string section;\n\t\tstd::vector<std::string> _requires;\n\t\tstd::vector<std::string> disabledBy;\n\t\tbool customPalette;\n\t\tbool hiddenCommendation;\n\n\t\t/// Get main title of page in ufopedia.\n\t\tconst std::string& getMainTitle()\n\t\t{\n\t\t\treturn _pages[0].title;\n\t\t}\n\n\t\t/// Return number of pages.\n\t\tsize_t getNumberOfPages()\n\t\t{\n\t\t\treturn _pages.size();\n\t\t}\n\n\t\tconst std::string& getTitleForPage(size_t page) const\n\t\t{\n\t\t\tif (page >= _pages.size())\n\t\t\t{\n\t\t\t\tthrow Exception(\"Access to wrong page for article '\" + id + \"'\");\n\t\t\t}\n\t\t\treturn _pages[page].title;\n\t\t}\n\n\t\tconst std::string& getTextForPage(size_t page) const\n\t\t{\n\t\t\tif (page >= _pages.size())\n\t\t\t{\n\t\t\t\tthrow Exception(\"Access to wrong page for article '\" + id + \"'\");\n\t\t\t}\n\t\t\treturn _pages[page].text;\n\t\t}\n\n\t\tint getAmmoSlotForPage(size_t page) const\n\t\t{\n\t\t\tif (page >= _pages.size())\n\t\t\t{\n\t\t\t\tthrow Exception(\"Access to wrong page for article '\" + id + \"'\");\n\t\t\t}\n\t\t\treturn _pages[page].ammoSlot;\n\t\t}\n\n\t\tint getAmmoSlotPrevUsageForPage(size_t page) const\n\t\t{\n\t\t\tint ammoSlot = getAmmoSlotForPage(page);\n\t\t\tint used = 0;\n\t\t\tfor (size_t i = 0; i < page; ++i)\n\t\t\t{\n\t\t\t\tif (_pages[i].ammoSlot == ammoSlot)\n\t\t\t\t{\n\t\t\t\t\t++used;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn used;\n\t\t}\n\n\tprotected:\n\t\tUfopaediaTypeId _type_id;\n\t\tstd::vector<ArticlePage> _pages;\n\tprivate:\n\t\tint _listOrder;\n\t};\n\n\tclass ArticleDefinitionRect\n\t{\n\tpublic:\n\t\tArticleDefinitionRect();\n\n\t\tvoid set(int set_x, int set_y, int set_width, int set_height);\n\n\t\tint x;\n\t\tint y;\n\t\tint width;\n\t\tint height;\n\t};\n\n\t/**\n\t * ArticleDefinitionUnit defines articles for unit types, e.g. STR_SECTOID_LEADER.\n\t * They have a large background image, a stats block, an armor block and a description positioned differently.\n\t */\n\n\tclass ArticleDefinitionUnit : public ArticleDefinition\n\t{\n\tpublic:\n\t\t/// Constructor.\n\t\tArticleDefinitionUnit();\n\t\t/// Loads the article from YAML.\n\t\tvoid load(const YAML::YamlNodeReader& reader, int listOrder) override;\n\n\t\tint unit_mode;\n\t\tstd::string image_id;\n\t\tArticleDefinitionRect rect_stats;\n\t\tArticleDefinitionRect rect_armor;\n\t\tArticleDefinitionRect rect_text;\n\t};\n\n\t/**\n\t * ArticleDefinitionSoldier defines articles for soldier types, e.g. STR_SOLDIER.\n\t * They have a large background image, a stats block and a description positioned differently.\n\t */\n\n\tclass ArticleDefinitionSoldier : public ArticleDefinition\n\t{\n\tpublic:\n\t\t/// Constructor.\n\t\tArticleDefinitionSoldier();\n\t\t/// Loads the article from YAML.\n\t\tvoid load(const YAML::YamlNodeReader& reader, int listOrder) override;\n\n\t\tint psi_skill_mode;\n\t\tstd::string image_id;\n\t\tArticleDefinitionRect rect_stats;\n\t\tArticleDefinitionRect rect_text;\n\t};\n\n\t/**\n\t * ArticleDefinitionCraft defines articles for craft, e.g. SKYRANGER.\n\t * They have a large background image, a stats block and a description positioned differently.\n\t */\n\n\tclass ArticleDefinitionCraft : public ArticleDefinition\n\t{\n\tpublic:\n\t\t/// Constructor.\n\t\tArticleDefinitionCraft();\n\t\t/// Loads the article from YAML.\n\t\tvoid load(const YAML::YamlNodeReader& reader, int listOrder) override;\n\n\t\tstd::string image_id;\n\t\tArticleDefinitionRect rect_stats;\n\t\tArticleDefinitionRect rect_text;\n\t};\n\n\t/**\n\t * ArticleDefinitionCraftWeapon defines articles for craft weapons, e.g. STINGRAY, AVALANCHE.\n\t * They have a large background image and a stats block.\n\t */\n\n\tclass ArticleDefinitionCraftWeapon : public ArticleDefinition\n\t{\n\tpublic:\n\t\t/// Constructor.\n\t\tArticleDefinitionCraftWeapon();\n\t\t/// Loads the article from YAML.\n\t\tvoid load(const YAML::YamlNodeReader& reader, int listOrder) override;\n\n\t\tstd::string image_id;\n\t};\n\n\t/**\n\t * ArticleDefinitionText defines articles with only text, e.g. ALIEN RESEARCH.\n\t */\n\n\tclass ArticleDefinitionText : public ArticleDefinition\n\t{\n\t\tpublic:\n\t\t/// Constructor.\n\t\tArticleDefinitionText();\n\t\t/// Loads the article from YAML.\n\t\tvoid load(const YAML::YamlNodeReader& reader, int listOrder) override;\n\n\t};\n\n\t/**\n\t * ArticleDefinitionTextImage defines articles with text on the left and\n\t * an image on the right side of the screen, e.g. ALIEN LIFEFORMS, UFO COMPONENTS.\n\t */\n\n\tclass ArticleDefinitionTextImage : public ArticleDefinition\n\t{\n\t\tpublic:\n\t\t/// Constructor.\n\t\tArticleDefinitionTextImage();\n\t\t/// Loads the article from YAML.\n\t\tvoid load(const YAML::YamlNodeReader& reader, int listOrder) override;\n\n\t\tstd::string image_id;\n\t\tint text_width;\n\t\tbool align_bottom;\n\t\tArticleDefinitionRect rect_text;\n\t};\n\n\t/**\n\t * ArticleDefinitionTextImage defines articles with text on the left and\n\t * an image on the right side of the screen, e.g. ALIEN LIFEFORMS, UFO COMPONENTS.\n\t */\n\n\tclass ArticleDefinitionTFTD : public ArticleDefinition\n\t{\n\t\tpublic:\n\t\t/// Constructor.\n\t\tArticleDefinitionTFTD();\n\t\t/// Loads the article from YAML.\n\t\tvoid load(const YAML::YamlNodeReader& reader, int listOrder) override;\n\n\t\tstd::string image_id;\n\t\tint text_width;\n\t\tstd::string weapon;\n\t};\n\n\t/**\n\t * ArticleDefinitionBaseFacility defines articles for base facilities, e.g. Access lift.\n\t * They have an image (found in BASEBITS.PCK), a stats block and a description.\n\t */\n\n\tclass ArticleDefinitionBaseFacility : public ArticleDefinition\n\t{\n\tpublic:\n\t\t/// Constructor.\n\t\tArticleDefinitionBaseFacility();\n\t\t/// Loads the article from YAML.\n\t\tvoid load(const YAML::YamlNodeReader& reader, int listOrder) override;\n\n\t};\n\n\t/**\n\t * ArticleDefinitionItem defines articles for all Items, e.g. Weapons, Ammo, Equipment, etc.\n\t * They have an image (found in BIGOBS.PCK), an optional stats block, maybe ammo and a description.\n\t */\n\n\tclass ArticleDefinitionItem : public ArticleDefinition\n\t{\n\tpublic:\n\t\t/// Constructor.\n\t\tArticleDefinitionItem();\n\t\t/// Loads the article from YAML.\n\t\tvoid load(const YAML::YamlNodeReader& reader, int listOrder) override;\n\n\t\tstd::string weapon;\n\t};\n\n\t/**\n\t * ArticleDefinitionUfo defines articles for UFOs, e.g. Small Scout, Terror Ship, etc.\n\t * They have an image (found in INTERWIN.DAT), a stats block and a description.\n\t */\n\n\tclass ArticleDefinitionUfo : public ArticleDefinition\n\t{\n\tpublic:\n\t\t/// Constructor.\n\t\tArticleDefinitionUfo();\n\t\t/// Loads the article from YAML.\n\t\tvoid load(const YAML::YamlNodeReader& reader, int listOrder) override;\n\n\t};\n\n\t/**\n\t * ArticleDefinitionArmor defines articles for Armor, e.g. Personal Armor, Flying Suit, etc.\n\t * They have an image (found in MAN_*.SPK) and a stats block.\n\t */\n\n\tclass ArticleDefinitionArmor : public ArticleDefinition\n\t{\n\tpublic:\n\t\t/// Constructor.\n\t\tArticleDefinitionArmor();\n\t\t/// Loads the article from YAML.\n\t\tvoid load(const YAML::YamlNodeReader& reader, int listOrder) override;\n\n\t\tstd::string image_id;\n\t};\n\n\t/**\n\t * ArticleDefinitionVehicle defines articles for Vehicles, e.g. Tanks, etc.\n\t * They have a text description and a stats block.\n\t */\n\n\tclass ArticleDefinitionVehicle : public ArticleDefinition\n\t{\n\tpublic:\n\t\t/// Constructor.\n\t\tArticleDefinitionVehicle();\n\t\t/// Loads the article from YAML.\n\t\tvoid load(const YAML::YamlNodeReader& reader, int listOrder) override;\n\n\t\tstd::string image_id;\n\t\tstd::string weapon;\n\t};\n\n\t// helper overloads for deserialization-only\n\tbool read(ryml::ConstNodeRef const& n, ArticleDefinitionRect* val);\n}\n"
  },
  {
    "path": "src/Mod/City.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"City.h\"\n#include \"../Engine/Language.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes a city with certain data.\n * @param name Name of the city.\n * @param lon Longitude of the city.\n * @param lat Latitude of the city.\n */\nCity::City(const std::string &name, double lon, double lat) : Target()\n{\n\t_name = name;\n\t_lon = lon;\n\t_lat = lat;\n}\n\n/**\n *\n */\nCity::~City()\n{\n}\n\n/**\n * Returns the city's unique identifying name.\n * @param lang Language to get strings from.\n * @return Full name.\n */\nstd::string City::getName(Language *lang) const\n{\n\treturn lang->getString(_name);\n}\n\n/**\n * Returns the globe marker for the UFO.\n * @return Marker sprite, -1 if none.\n */\nint City::getMarker() const\n{\n\treturn 8;\n}\n\n}\n"
  },
  {
    "path": "src/Mod/City.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include \"../Savegame/Target.h\"\n\nnamespace OpenXcom\n{\n\nclass Language;\n\n/**\n * Represents a city of the world.\n * Aliens target cities for certain missions.\n */\nclass City : public Target\n{\nprivate:\n\t/// Gets the city's type (unused).\n\tstd::string getType() const  override { return \"\"; }\npublic:\n\t/// Creates a new city at a certain position.\n\tCity(const std::string &name, double lon, double lat);\n\t/// Cleans up the city.\n\t~City();\n\t/// Gets the city's name.\n\tstd::string getName(Language *lang) const override;\n\t/// Gets the city's marker.\n\tint getMarker() const override;\n};\n\n}\n"
  },
  {
    "path": "src/Mod/CustomPalettes.cpp",
    "content": "/*\n * Copyright 2010-2015 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"CustomPalettes.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Creates a blank custom palette.\n */\nCustomPalettes::CustomPalettes(const std::string &type) : _type(type)\n{\n}\n\n/**\n * Clean up.\n */\nCustomPalettes::~CustomPalettes()\n{\n}\n\n/**\n * Loads the custom palette from YAML.\n * @param node YAML node.\n */\nvoid CustomPalettes::load(const YAML::YamlNodeReader& reader)\n{\n\treader.tryRead(\"target\", _target);\n\treader.tryRead(\"file\", _file);\n\treader.tryRead(\"palette\", _palette);\n}\n\n/**\n * Returns the custom palette definition.\n * @return The list of RGB values.\n */\nstd::map<int, Position> *CustomPalettes::getPalette()\n{\n\treturn &_palette;\n}\n\n/**\n * Gets the name of the palette.\n * @return The palette type/name.\n */\nconst std::string &CustomPalettes::getType() const\n{\n\treturn _type;\n}\n\n/**\n * Gets the name of the target palette to be modded.\n * @return The target palette type/name.\n */\nconst std::string &CustomPalettes::getTarget() const\n{\n\treturn _target;\n}\n\n/**\n * Gets the source file in JASC palette format (256 colors).\n * @return The relative file path and name.\n */\nconst std::string &CustomPalettes::getFile() const\n{\n\treturn _file;\n}\n\n}\n"
  },
  {
    "path": "src/Mod/CustomPalettes.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2015 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/Yaml.h\"\n#include \"../Battlescape/Position.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * For adding custom palettes to the game.\n */\nclass CustomPalettes\n{\nprivate:\n\tstd::string _type, _target, _file;\n\tstd::map<int, Position> _palette;\npublic:\n\t/// Creates a blank custom palette.\n\tCustomPalettes(const std::string &type);\n\t/// Clean up.\n\tvirtual ~CustomPalettes();\n\t/// Loads the data from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader);\n\t/// Gets the palette.\n\tstd::map<int, Position> *getPalette();\n\t/// Gets the type.\n\tconst std::string &getType() const;\n\t/// Gets the target.\n\tconst std::string &getTarget() const;\n\t/// Gets the source file in JASC palette format (256 colors).\n\tconst std::string &getFile() const;\n\n};\n\n}\n"
  },
  {
    "path": "src/Mod/ExtraSounds.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include <algorithm>\n#include \"ExtraSounds.h\"\n#include \"../Engine/SoundSet.h\"\n#include \"../Engine/Sound.h\"\n#include \"../Engine/FileMap.h\"\n#include \"../Engine/Logger.h\"\n#include \"../Engine/Exception.h\"\n#include \"../Engine/Unicode.h\"\n#include \"Mod.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Creates a blank set of extra sound data.\n */\nExtraSounds::ExtraSounds() : _current(0)\n{\n}\n\n/**\n * Cleans up the extra sound set.\n */\nExtraSounds::~ExtraSounds()\n{\n}\n\n/**\n * Loads the extra sound set from YAML.\n * @param node YAML node.\n * @param modIndex The internal index of the associated mod.\n */\nvoid ExtraSounds::load(const YAML::YamlNodeReader& reader, const ModData* current)\n{\n\treader.tryRead(\"type\", _type);\n\treader.tryRead(\"files\", _sounds);\n\t_current = current;\n}\n\n/**\n * Gets the filename that this sound set represents.\n * @return The sound name.\n */\nconst std::string& ExtraSounds::getType() const\n{\n\treturn _type;\n}\n\n/**\n * Gets the list of sounds defined by this mod.\n * @return The list of sounds defined my this mod.\n */\nstd::map<int, std::string> *ExtraSounds::getSounds()\n{\n\treturn &_sounds;\n}\n\n/**\n * Loads the external sounds into a new or existing soundset.\n * @param set Existing soundset.\n * @return New soundset.\n */\nSoundSet *ExtraSounds::loadSoundSet(SoundSet *set) const\n{\n\tif (set == 0)\n\t{\n\t\tLog(LOG_WARNING) << \"Creating new sound set: \" << _type << \", this will likely have no in-game use.\";\n\t\tset = new SoundSet();\n\t}\n\telse\n\t{\n\t\tLog(LOG_VERBOSE) << \"Adding/Replacing items in sound set: \" << _type;\n\t}\n\tfor (const auto& pair : _sounds)\n\t{\n\t\tint startSound = pair.first;\n\t\tconst auto& fileName = pair.second;\n\t\tif (fileName[fileName.length() - 1] == '/')\n\t\t{\n\t\t\tLog(LOG_VERBOSE) << \"Loading sound set from folder: \" << fileName << \" starting at index: \" << startSound;\n\t\t\tint offset = startSound;\n\t\t\tstd::vector<std::string> contents;\n\t\t\tfor (const auto& f: FileMap::getVFolderContents(fileName)) { contents.push_back(f); }\n\t\t\tstd::sort(contents.begin(), contents.end(), Unicode::naturalCompare);\n\t\t\tfor (const auto& name : contents)\n\t\t\t{\n\t\t\t\ttry\n\t\t\t\t{\n\t\t\t\t\tloadSound(set, offset, fileName + name);\n\t\t\t\t\toffset++;\n\t\t\t\t}\n\t\t\t\tcatch (Exception &e)\n\t\t\t\t{\n\t\t\t\t\tLog(LOG_WARNING) << e.what();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tloadSound(set, startSound, fileName);\n\t\t}\n\t}\n\treturn set;\n}\n\nvoid ExtraSounds::loadSound(SoundSet *set, int index, const std::string &fileName) const\n{\n\tint indexWithOffset = index;\n\tif (indexWithOffset >= set->getMaxSharedSounds())\n\t{\n\t\tif ((size_t)indexWithOffset >= _current->size)\n\t\t{\n\t\t\tstd::ostringstream err;\n\t\t\terr << \"ExtraSounds '\" << _type << \"' sound '\" << indexWithOffset << \"' exceeds mod '\"<< _current->name <<\"' size limit \" << _current->size;\n\t\t\tthrow Exception(err.str());\n\t\t}\n\t\tindexWithOffset += _current->offset;\n\t}\n\n\tSound *sound = set->getSound(indexWithOffset);\n\tif (sound)\n\t{\n\t\tLog(LOG_VERBOSE) << \"Replacing sound: \" << index << \", using index: \" << indexWithOffset;\n\t}\n\telse\n\t{\n\t\tLog(LOG_VERBOSE) << \"Adding sound: \" << index << \", using index: \" << indexWithOffset;\n\t\tsound = set->addSound(indexWithOffset);\n\t}\n\tsound->load(fileName);\n}\n\n}\n"
  },
  {
    "path": "src/Mod/ExtraSounds.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/Yaml.h\"\n#include <string>\n#include <map>\n\nnamespace OpenXcom\n{\n\nclass SoundSet;\nstruct ModData;\n\n/**\n * For adding a set of extra sound data to the game.\n */\nclass ExtraSounds\n{\nprivate:\n\tstd::string _type;\n\tstd::map<int, std::string> _sounds;\n\tconst ModData* _current;\n\n\tvoid loadSound(SoundSet *set, int index, const std::string &fileName) const;\npublic:\n\t/// Creates a blank external sound set.\n\tExtraSounds();\n\t/// Cleans up the external sound set.\n\tvirtual ~ExtraSounds();\n\t/// Loads the data from yaml\n\tvoid load(const YAML::YamlNodeReader& reader, const ModData* current);\n\t/// Gets the sound's type.\n\tconst std::string& getType() const;\n\t/// Gets the list of sounds defined by this mod\n\tstd::map<int, std::string> *getSounds();\n\t/// Load the external sound into a set.\n\tSoundSet *loadSoundSet(SoundSet *set) const;\n\t/// Gets mod data that define this sounds.\n\tconst ModData* getModOwner() { return _current; }\n};\n\n}\n"
  },
  {
    "path": "src/Mod/ExtraSprites.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include <algorithm>\n#include \"ExtraSprites.h\"\n#include \"../Engine/Surface.h\"\n#include \"../Engine/SurfaceSet.h\"\n#include \"../Engine/FileMap.h\"\n#include \"../Engine/Logger.h\"\n#include \"../Engine/Exception.h\"\n#include \"../Engine/Unicode.h\"\n#include \"Mod.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Creates a blank set of extra sprite data.\n */\nExtraSprites::ExtraSprites() : _current(0), _width(320), _height(200), _singleImage(false), _subX(0), _subY(0), _loaded(false)\n{\n}\n\n/**\n * Cleans up the extra sprite set.\n */\nExtraSprites::~ExtraSprites()\n{\n}\n\n/**\n * Loads the extra sprite set from YAML.\n * @param node YAML node.\n * @param modIndex the internal index of the associated mod.\n */\nvoid ExtraSprites::load(const YAML::YamlNodeReader& reader, const ModData* current)\n{\n\treader.tryRead(\"type\", _type);\n\n\tif (_type.empty())\n\t{\n\t\tstd::string typeSingle;\n\t\treader.tryRead(\"typeSingle\", typeSingle);\n\t\tif (!typeSingle.empty())\n\t\t{\n\t\t\t_type = typeSingle;\n\t\t\t_singleImage = true;\n\t\t}\n\t\tstd::string fileSingle;\n\t\treader.tryRead(\"fileSingle\", fileSingle);\n\t\tif (!fileSingle.empty())\n\t\t{\n\t\t\t_sprites[0] = fileSingle;\n\t\t}\n\t}\n\n\treader.tryRead(\"files\", _sprites);\n\treader.tryRead(\"width\", _width);\n\treader.tryRead(\"height\", _height);\n\treader.tryRead(\"singleImage\", _singleImage);\n\treader.tryRead(\"subX\", _subX);\n\treader.tryRead(\"subY\", _subY);\n\t_current = current;\n}\n\n/**\n * Gets the filename that this sprite represents.\n * @return The sprite name.\n */\nconst std::string& ExtraSprites::getType() const\n{\n\treturn _type;\n}\n\n/**\n * Gets the list of sprites defined my this mod.\n * @return The list of sprites.\n */\nstd::map<int, std::string> *ExtraSprites::getSprites()\n{\n\treturn &_sprites;\n}\n\n/**\n * Gets the width of the surfaces (used for single images and new spritesets).\n * @return The width of the surfaces.\n */\nint ExtraSprites::getWidth() const\n{\n\treturn _width;\n}\n\n/**\n * Gets the height of the surfaces (used for single images and new spritesets).\n * @return The height of the surfaces.\n */\nint ExtraSprites::getHeight() const\n{\n\treturn _height;\n}\n\n/**\n * Returns whether this is a single surface as opposed to a set of surfaces.\n * @return True if this is a single surface.\n */\nbool ExtraSprites::getSingleImage() const\n{\n\treturn _singleImage;\n}\n\n/**\n * Gets the x subdivision.\n * @return The x subdivision.\n */\nint ExtraSprites::getSubX() const\n{\n\treturn _subX;\n}\n\n/**\n * Gets the y subdivision.\n * @return The y subdivision.\n */\nint ExtraSprites::getSubY() const\n{\n\treturn _subY;\n}\n\n/**\n * Returns if the sprite is loaded.\n * @return True/false\n */\nbool ExtraSprites::isLoaded() const\n{\n\treturn _loaded;\n}\n\n/**\n * Determines if an image file is an acceptable format for the game.\n * @param filename Image filename.\n * @return True/false\n */\nbool ExtraSprites::isImageFile(const std::string &filename)\n{\n\tstatic const std::string exts[] = { \"PNG\", \"GIF\", \"BMP\", \"LBM\", \"IFF\", \"PCX\", \"TGA\", \"TIF\", \"TIFF\" };\n\n\tfor (size_t i = 0; i < std::size(exts); ++i)\n\t{\n\t\tif (CrossPlatform::compareExt(filename, exts[i]))\n\t\t\treturn true;\n\t}\n\treturn false;\n}\n\n/**\n * Loads the external sprite into a new or existing surface.\n * @param surface Existing surface.\n * @return New surface.\n */\nSurface *ExtraSprites::loadSurface(Surface *surface)\n{\n\tif (!_singleImage)\n\t\treturn surface;\n\t_loaded = true;\n\n\tif (surface == 0)\n\t{\n\t\tLog(LOG_VERBOSE) << \"Creating new single image: \" << _type;\n\t}\n\telse\n\t{\n\t\tLog(LOG_VERBOSE) << \"Adding/Replacing single image: \" << _type;\n\t\tdelete surface;\n\t}\n\tsurface = new Surface(_width, _height);\n\tsurface->loadImage(_sprites.begin()->second);\n\treturn surface;\n}\n\n/**\n * Loads the external sprite into a new or existing surface set.\n * @param set Existing surface set.\n * @return New surface set.\n */\nSurfaceSet *ExtraSprites::loadSurfaceSet(SurfaceSet *set)\n{\n\tif (_singleImage)\n\t\treturn set;\n\t_loaded = true;\n\n\tbool subdivision = (_subX != 0 && _subY != 0);\n\tint surfaceSetX = subdivision ? _subX : _width;\n\tint surfaceSetY = subdivision ? _subY : _height;\n\tif (set == 0)\n\t{\n\t\tLog(LOG_VERBOSE) << \"Creating new surface set: \" << _type;\n\t\tset = new SurfaceSet(surfaceSetX, surfaceSetY);\n\t}\n\telse\n\t{\n\t\tLog(LOG_VERBOSE) << \"Adding/Replacing items in surface set: \" << _type;\n\t\tif (set->getTotalFrames() == 0 && (set->getWidth() != surfaceSetX || set->getHeight() != surfaceSetY))\n\t\t{\n\t\t\tLog(LOG_VERBOSE) << \"Resize empty set to: \" << surfaceSetX << \" x \" << surfaceSetY;\n\t\t\tint shared = set->getMaxSharedFrames();\n\t\t\t*set = SurfaceSet(surfaceSetX, surfaceSetY);\n\t\t\tset->setMaxSharedFrames(shared);\n\t\t}\n\t}\n\n\tfor (const auto& pair : _sprites)\n\t{\n\t\tint startFrame = pair.first;\n\t\tconst auto& fileName = pair.second;\n\t\tif (fileName[fileName.length() - 1] == '/')\n\t\t{\n\t\t\tLog(LOG_VERBOSE) << \"Loading surface set from folder: \" << fileName << \" starting at frame: \" << startFrame;\n\t\t\tint offset = startFrame;\n\t\t\tstd::vector<std::string> contents;\n\t\t\tfor (const auto& f: FileMap::getVFolderContents(fileName)) { contents.push_back(f); }\n\t\t\tstd::sort(contents.begin(), contents.end(), Unicode::naturalCompare);\n\t\t\tfor (const auto& name : contents)\n\t\t\t{\n\t\t\t\tif (!isImageFile(name))\n\t\t\t\t\tcontinue;\n\t\t\t\ttry\n\t\t\t\t{\n\t\t\t\t\tgetFrame(set, offset)->loadImage(fileName + name);\n\t\t\t\t\toffset++;\n\t\t\t\t}\n\t\t\t\tcatch (Exception &e)\n\t\t\t\t{\n\t\t\t\t\tLog(LOG_WARNING) << e.what();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (!subdivision)\n\t\t\t{\n\t\t\t\tgetFrame(set, startFrame)->loadImage(fileName);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tSurface temp = Surface(_width, _height);\n\t\t\t\ttemp.loadImage(fileName);\n\t\t\t\tint xDivision = _width / _subX;\n\t\t\t\tint yDivision = _height / _subY;\n\t\t\t\tint frames = xDivision * yDivision;\n\t\t\t\tLog(LOG_VERBOSE) << \"Subdividing into \" << frames << \" frames.\";\n\t\t\t\tint offset = startFrame;\n\n\t\t\t\tfor (int y = 0; y != yDivision; ++y)\n\t\t\t\t{\n\t\t\t\t\tfor (int x = 0; x != xDivision; ++x)\n\t\t\t\t\t{\n\t\t\t\t\t\tSurface* frame = getFrame(set, offset);\n\t\t\t\t\t\t// for some reason regular blit() doesn't work here how i want it, so i use this function instead.\n\t\t\t\t\t\ttemp.blitNShade(frame, 0 - (x * _subX), 0 - (y * _subY), 0);\n\t\t\t\t\t\t++offset;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn set;\n}\n\nSurface *ExtraSprites::getFrame(SurfaceSet *set, int index) const\n{\n\tint indexWithOffset = index;\n\tif (indexWithOffset >= set->getMaxSharedFrames())\n\t{\n\t\tif ((size_t)indexWithOffset >= _current->size)\n\t\t{\n\t\t\tstd::ostringstream err;\n\t\t\terr << \"ExtraSprites '\" << _type << \"' frame '\" << indexWithOffset << \"' exceeds mod '\"<< _current->name <<\"' size limit \" << _current->size;\n\t\t\tthrow Exception(err.str());\n\t\t}\n\t\tindexWithOffset += _current->offset;\n\t}\n\telse if (indexWithOffset < 0)\n\t{\n\t\tstd::ostringstream err;\n\t\terr << \"ExtraSprites '\" << _type << \"' frame '\" << indexWithOffset << \"' in mod '\" << _current->name << \"' is not allowed.\";\n\t\tthrow Exception(err.str());\n\t}\n\n\tSurface *frame = set->getFrame(indexWithOffset);\n\tif (frame)\n\t{\n\t\tLog(LOG_VERBOSE) << \"Replacing frame: \" << index << \", using index: \" << indexWithOffset;\n\t\tframe->clear();\n\t}\n\telse\n\t{\n\t\tLog(LOG_VERBOSE) << \"Adding frame: \" << index << \", using index: \" << indexWithOffset;\n\t\tframe = set->addFrame(indexWithOffset);\n\t}\n\treturn frame;\n}\n\n}\n"
  },
  {
    "path": "src/Mod/ExtraSprites.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/Yaml.h\"\n#include <string>\n#include <map>\n\nnamespace OpenXcom\n{\n\nclass Surface;\nclass SurfaceSet;\nstruct ModData;\n\n/**\n * For adding a set of extra sprite data to the game.\n */\nclass ExtraSprites\n{\nprivate:\n\tstd::string _type;\n\tstd::map<int, std::string> _sprites;\n\tconst ModData* _current;\n\tint _width, _height;\n\tbool _singleImage;\n\tint _subX, _subY;\n\tbool _loaded;\n\n\tSurface *getFrame(SurfaceSet *set, int index) const;\npublic:\n\t/// Creates a blank external sprite set.\n\tExtraSprites();\n\t/// Cleans up the external sprite set.\n\tvirtual ~ExtraSprites();\n\t/// Loads the data from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader, const ModData* current);\n\t/// Gets the sprite's type.\n\tconst std::string& getType() const;\n\t/// Gets the list of sprites defined by this mod.\n\tstd::map<int, std::string> *getSprites();\n\t/// Gets the width of the surfaces (used for single images and new spritesets).\n\tint getWidth() const;\n\t/// Gets the height of the surfaces (used for single images and new spritesets).\n\tint getHeight() const;\n\t/// Checks if this is a single surface, or a set of surfaces.\n\tbool getSingleImage() const;\n\t/// Gets the x subdivision.\n\tint getSubX() const;\n\t/// Gets the y subdivision.\n\tint getSubY() const;\n\t/// Has this sprite been loaded?\n\tbool isLoaded() const;\n\t/// Checks if a filename is a valid image file.\n\tstatic bool isImageFile(const std::string &filename);\n\t/// Load the external sprite into a surface.\n\tSurface *loadSurface(Surface *surface);\n\t/// Load the external sprite into a surface set.\n\tSurfaceSet *loadSurfaceSet(SurfaceSet *set);\n\t/// Gets mod data that define this surface.\n\tconst ModData* getModOwner() { return _current; }\n};\n\n}\n"
  },
  {
    "path": "src/Mod/ExtraStrings.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"ExtraStrings.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Creates a blank set of extra strings data.\n */\nExtraStrings::ExtraStrings()\n{\n}\n\n/**\n * Cleans up the extra strings set.\n */\nExtraStrings::~ExtraStrings()\n{\n}\n\n/**\n * Loads the extra strings set from YAML.\n * @param node YAML node.\n */\nvoid ExtraStrings::load(const YAML::YamlNodeReader& reader)\n{\n\tfor (const auto& string : reader[\"strings\"].children())\n\t{\n\t\t// Regular strings\n\t\tstd::string key = string.readKey<std::string>();\n\t\tif (string.hasVal())\n\t\t{\n\t\t\t_strings[key] = string.readVal<std::string>();\n\t\t}\n\t\t// Strings with plurality\n\t\telse if (string.isMap())\n\t\t{\n\t\t\tfor (const auto& plurality : string.children())\n\t\t\t{\n\t\t\t\tstd::string s = key + \"_\" + plurality.readKey<std::string>();\n\t\t\t\t_strings[s] = plurality.readVal<std::string>();\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Gets the list of strings defined my this mod.\n * @return The list of strings.\n */\nstd::map<std::string, std::string> *ExtraStrings::getStrings()\n{\n\treturn &_strings;\n}\n\n}\n"
  },
  {
    "path": "src/Mod/ExtraStrings.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/Yaml.h\"\n#include <string>\n#include <map>\n\nnamespace OpenXcom\n{\n\n/**\n * For adding a set of extra strings to the game.\n */\nclass ExtraStrings\n{\nprivate:\n\tstd::map<std::string, std::string> _strings;\npublic:\n\t/// Creates a blank external strings set.\n\tExtraStrings();\n\t/// Cleans up the external strings set.\n\tvirtual ~ExtraStrings();\n\t/// Loads the data from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader);\n\t/// Gets the list of strings defined by this mod.\n\tstd::map<std::string, std::string> *getStrings();\n};\n\n}\n"
  },
  {
    "path": "src/Mod/LoadYaml.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2023 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include \"../Engine/Yaml.h\"\n#include <SDL_stdinc.h>\n\nnamespace OpenXcom\n{\n\n// Default value that is interpreted as null.\nconstexpr int defIntNullable = -1;\n\n// Default value that is interpreted as null.\nconstexpr Sint8 defBoolNullable = -1;\n\n/// Load bool from yaml.\ninline void loadBool(bool& value, const YAML::YamlNodeReader& reader)\n{\n\tif (!reader)\n\t\treturn;\n\tvalue = reader.readVal<bool>();\n}\n\n/// Load bool as int from yaml.\ninline void loadBoolNullable(int& value, const YAML::YamlNodeReader& reader)\n{\n\tif (!reader)\n\t\treturn;\n\tvalue = reader.hasNullVal() ? defBoolNullable : reader.readVal<bool>();\n}\n\n/// Load bool as int from yaml.\ninline void loadBoolNullable(Sint8& value, const YAML::YamlNodeReader& reader)\n{\n\tif (!reader)\n\t\treturn;\n\tvalue = reader.hasNullVal() ? defBoolNullable : reader.readVal<bool>();\n}\n\n/// Load int from yaml.\ninline void loadInt(int& value, const YAML::YamlNodeReader& reader)\n{\n\tif (!reader)\n\t\treturn;\n\tvalue = reader.readVal<int>();\n}\n\n/// Load int from yaml.\ninline void loadIntNullable(int& value, const YAML::YamlNodeReader& reader)\n{\n\tif (!reader)\n\t\treturn;\n\tvalue = reader.hasNullVal() ? defIntNullable : reader.readVal<int>();\n}\n\ninline bool useBoolNullable(int value, bool def)\n{\n\treturn value == defBoolNullable ? def : value;\n}\n\ninline int useIntNullable(int value, int def)\n{\n\treturn value == defIntNullable ? def : value;\n}\n\n\n} //namespace OpenXcom\n"
  },
  {
    "path": "src/Mod/MCDPatch.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"MCDPatch.h\"\n#include \"MapDataSet.h\"\n#include \"MapData.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes an MCD Patch.\n */\nMCDPatch::MCDPatch()\n{\n}\n\n/**\n *\n */\nMCDPatch::~MCDPatch()\n{\n}\n\n/**\n * Loads the MCD Patch from a YAML file.\n * TODO: fill this out with more data.\n * @param node YAML node.\n */\nvoid MCDPatch::load(const YAML::YamlNodeReader& reader)\n{\n\tfor (const auto& d : reader[\"data\"].children())\n\t{\n\t\tconst auto& mcd = d.useIndex();\n\t\tsize_t MCDIndex = mcd[\"MCDIndex\"].readVal<size_t>();\n\t\tif (mcd[\"bigWall\"])\n\t\t{\n\t\t\tint bigWall = mcd[\"bigWall\"].readVal<int>();\n\t\t\t_bigWalls.push_back(std::make_pair(MCDIndex, bigWall));\n\t\t}\n\t\tif (mcd[\"TUWalk\"])\n\t\t{\n\t\t\tint TUWalk = mcd[\"TUWalk\"].readVal<int>();\n\t\t\t_TUWalks.push_back(std::make_pair(MCDIndex, TUWalk));\n\t\t}\n\t\tif (mcd[\"TUFly\"])\n\t\t{\n\t\t\tint TUFly = mcd[\"TUFly\"].readVal<int>();\n\t\t\t_TUFlys.push_back(std::make_pair(MCDIndex, TUFly));\n\t\t}\n\t\tif (mcd[\"TUSlide\"])\n\t\t{\n\t\t\tint TUSlide = mcd[\"TUSlide\"].readVal<int>();\n\t\t\t_TUSlides.push_back(std::make_pair(MCDIndex, TUSlide));\n\t\t}\n\t\tif (mcd[\"deathTile\"])\n\t\t{\n\t\t\tint deathTile = mcd[\"deathTile\"].readVal<int>();\n\t\t\t_deathTiles.push_back(std::make_pair(MCDIndex, deathTile));\n\t\t}\n\t\tif (mcd[\"terrainHeight\"])\n\t\t{\n\t\t\tint terrainHeight = mcd[\"terrainHeight\"].readVal<int>();\n\t\t\t_terrainHeight.push_back(std::make_pair(MCDIndex, terrainHeight));\n\t\t}\n\t\tif (mcd[\"specialType\"])\n\t\t{\n\t\t\tint specialType = mcd[\"specialType\"].readVal<int>();\n\t\t\t_specialTypes.push_back(std::make_pair(MCDIndex, specialType));\n\t\t}\n\t\tif (mcd[\"explosive\"])\n\t\t{\n\t\t\tint explosive = mcd[\"explosive\"].readVal<int>();\n\t\t\t_explosives.push_back(std::make_pair(MCDIndex, explosive));\n\t\t}\n\t\tif (mcd[\"armor\"])\n\t\t{\n\t\t\tint armor = mcd[\"armor\"].readVal<int>();\n\t\t\t_armors.push_back(std::make_pair(MCDIndex, armor));\n\t\t}\n\t\tif (mcd[\"flammability\"])\n\t\t{\n\t\t\tint flammability = mcd[\"flammability\"].readVal<int>();\n\t\t\t_flammabilities.push_back(std::make_pair(MCDIndex, flammability));\n\t\t}\n\t\tif (mcd[\"fuel\"])\n\t\t{\n\t\t\tint fuel = mcd[\"fuel\"].readVal<int>();\n\t\t\t_fuels.push_back(std::make_pair(MCDIndex, fuel));\n\t\t}\n\t\tif (mcd[\"footstepSound\"])\n\t\t{\n\t\t\tint footstepSound = mcd[\"footstepSound\"].readVal<int>();\n\t\t\t_footstepSounds.push_back(std::make_pair(MCDIndex, footstepSound));\n\t\t}\n\t\tif (mcd[\"HEBlock\"])\n\t\t{\n\t\t\tint HEBlock = mcd[\"HEBlock\"].readVal<int>();\n\t\t\t_HEBlocks.push_back(std::make_pair(MCDIndex, HEBlock));\n\t\t}\n\t\tif (mcd[\"noFloor\"])\n\t\t{\n\t\t\tbool noFloor = mcd[\"noFloor\"].readVal<bool>();\n\t\t\t_noFloors.push_back(std::make_pair(MCDIndex, noFloor));\n\t\t}\n\t\tif (mcd[\"LOFTS\"])\n\t\t{\n\t\t\tstd::vector<int> lofts = mcd[\"LOFTS\"].readVal<std::vector<int> >();\n\t\t\t_LOFTS.push_back(std::make_pair(MCDIndex, lofts));\n\t\t}\n\t\tif (mcd[\"stopLOS\"])\n\t\t{\n\t\t\tbool stopLOS = mcd[\"stopLOS\"].readVal<bool>();\n\t\t\t_stopLOSses.push_back(std::make_pair(MCDIndex, stopLOS));\n\t\t}\n\t\tif (mcd[\"objectType\"])\n\t\t{\n\t\t\tint objectType = mcd[\"objectType\"].readVal<int>();\n\t\t\t_objectTypes.push_back(std::make_pair(MCDIndex, objectType));\n\t\t}\n\t}\n}\n\n/**\n * Applies an MCD patch to a mapDataSet.\n * @param dataSet The MapDataSet we want to modify.\n */\nvoid MCDPatch::modifyData(MapDataSet *dataSet) const\n{\n\tfor (const auto& pair : _bigWalls)\n\t{\n\t\tdataSet->getObject(pair.first)->setBigWall(pair.second);\n\t}\n\tfor (const auto& pair : _TUWalks)\n\t{\n\t\tdataSet->getObject(pair.first)->setTUWalk(pair.second);\n\t}\n\tfor (const auto& pair : _TUFlys)\n\t{\n\t\tdataSet->getObject(pair.first)->setTUFly(pair.second);\n\t}\n\tfor (const auto& pair : _TUSlides)\n\t{\n\t\tdataSet->getObject(pair.first)->setTUSlide(pair.second);\n\t}\n\tfor (const auto& pair : _deathTiles)\n\t{\n\t\tdataSet->getObject(pair.first)->setDieMCD(pair.second);\n\t}\n\tfor (const auto& pair : _terrainHeight)\n\t{\n\t\tdataSet->getObject(pair.first)->setTerrainLevel(pair.second);\n\t}\n\tfor (const auto& pair : _specialTypes)\n\t{\n\t\tdataSet->getObject(pair.first)->setSpecialType(pair.second, dataSet->getObject(pair.first)->getObjectType());\n\t}\n\tfor (const auto& pair : _explosives)\n\t{\n\t\tdataSet->getObject(pair.first)->setExplosive(pair.second);\n\t}\n\tfor (const auto& pair : _armors)\n\t{\n\t\tdataSet->getObject(pair.first)->setArmor(pair.second);\n\t}\n\tfor (const auto& pair : _flammabilities)\n\t{\n\t\tdataSet->getObject(pair.first)->setFlammable(pair.second);\n\t}\n\tfor (const auto& pair : _fuels)\n\t{\n\t\tdataSet->getObject(pair.first)->setFuel(pair.second);\n\t}\n\tfor (const auto& pair : _HEBlocks)\n\t{\n\t\tdataSet->getObject(pair.first)->setHEBlock(pair.second);\n\t}\n\tfor (const auto& pair : _footstepSounds)\n\t{\n\t\tdataSet->getObject(pair.first)->setFootstepSound(pair.second);\n\t}\n\tfor (const auto& pair : _objectTypes)\n\t{\n\t\tdataSet->getObject(pair.first)->setObjectType((TilePart)pair.second);\n\t}\n\tfor (const auto& pair : _noFloors)\n\t{\n\t\tdataSet->getObject(pair.first)->setNoFloor(pair.second);\n\t}\n\tfor (const auto& pair : _stopLOSses)\n\t{\n\t\tdataSet->getObject(pair.first)->setStopLOS(pair.second);\n\t}\n\tfor (const auto& pair : _LOFTS)\n\t{\n\t\tint layer = 0;\n\t\tfor (int loft : pair.second)\n\t\t{\n\t\t\tdataSet->getObject(pair.first)->setLoftID(loft, layer);\n\t\t\t++layer;\n\t\t}\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Mod/MCDPatch.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/Yaml.h\"\n\nnamespace OpenXcom\n{\n\nclass MapDataSet;\n/**\n * An MCD data Patch.\n */\nclass MCDPatch\n{\nprivate:\n\tstd::vector<std::pair<size_t, int> > _bigWalls, _TUWalks, _TUFlys, _TUSlides, _deathTiles, _terrainHeight, _specialTypes, _armors, _explosives, _flammabilities, _fuels, _HEBlocks, _footstepSounds, _objectTypes;\n\tstd::vector<std::pair<size_t, bool> > _noFloors, _stopLOSses;\n\tstd::vector<std::pair<size_t, std::vector<int> > > _LOFTS;\npublic:\n\t/// Creates an MCD Patch.\n\tMCDPatch();\n\t/// Cleans up the MCD Patch.\n\t~MCDPatch();\n\t/// Loads the MCD Patch from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader);\n\t/// Applies an MCD patch to a mapDataSet\n\tvoid modifyData(MapDataSet *dataSet) const;\n};\n\n}\n"
  },
  {
    "path": "src/Mod/MapBlock.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <sstream>\n#include <algorithm>\n#include \"MapBlock.h\"\n#include \"../Battlescape/Position.h\"\n#include \"../Engine/Exception.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * MapBlock construction.\n */\nMapBlock::MapBlock(const std::string &name): _name(name), _size_x(10), _size_y(10), _size_z(4)\n{\n\t_groups.push_back(0);\n}\n\n/**\n * MapBlock destruction.\n */\nMapBlock::~MapBlock()\n{\n}\n\n/**\n * Loads the map block from a YAML file.\n * @param node YAML node.\n */\nvoid MapBlock::load(const YAML::YamlNodeReader& reader)\n{\n\treader.tryRead(\"name\", _name);\n\treader.tryRead(\"width\", _size_x);\n\treader.tryRead(\"length\", _size_y);\n\treader.tryRead(\"height\", _size_z);\n\tif ((_size_x % 10) != 0 || (_size_y % 10) != 0)\n\t{\n\t\tstd::ostringstream ss;\n\t\tss << \"Error: MapBlock \" << _name << \": Size must be divisible by ten\";\n\t\tthrow Exception(ss.str());\n\t}\n\tif (const auto& map = reader[\"groups\"])\n\t{\n\t\t_groups.clear();\n\t\tif (map.isSeq())\n\t\t{\n\t\t\tmap.tryReadVal(_groups);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_groups.push_back(map.readVal(0));\n\t\t}\n\t}\n\tif (const auto& map = reader[\"revealedFloors\"])\n\t{\n\t\t_revealedFloors.clear();\n\t\tif (map.isSeq())\n\t\t{\n\t\t\tmap.tryReadVal(_revealedFloors);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_revealedFloors.push_back(map.readVal(0));\n\t\t}\n\t}\n\treader.tryRead(\"items\", _items);\n\treader.tryRead(\"fuseTimers\", _itemsFuseTimer);\n\treader.tryRead(\"randomizedItems\", _randomizedItems);\n\treader.tryRead(\"extendedItems\", _extendedItems);\n\treader.tryRead(\"craftInventoryTile\", _craftInventoryTile);\n}\n\n/**\n * Gets the MapBlock name (string).\n * @return The name.\n */\nconst std::string& MapBlock::getName() const\n{\n\treturn _name;\n}\n\n/**\n * Gets the MapBlock size x.\n * @return The size x in tiles.\n */\nint MapBlock::getSizeX() const\n{\n\treturn _size_x;\n}\n\n/**\n * Gets the MapBlock size y.\n * @return The size y in tiles.\n */\nint MapBlock::getSizeY() const\n{\n\treturn _size_y;\n}\n\n/**\n * Sets the MapBlock size z.\n * @param size_z The size z.\n */\nvoid MapBlock::setSizeZ(int size_z)\n{\n\t_size_z = size_z;\n}\n\n/**\n * Gets the MapBlock size z.\n * @return The size z.\n */\nint MapBlock::getSizeZ() const\n{\n\treturn _size_z;\n}\n\n/**\n * Gets the type of mapblock.\n * @return The mapblock's type.\n */\nbool MapBlock::isInGroup(int group)\n{\n\treturn std::find(_groups.begin(), _groups.end(), group) != _groups.end();\n}\n\n/**\n * Gets if this floor should be revealed or not.\n */\nbool MapBlock::isFloorRevealed(int floor)\n{\n\treturn std::find(_revealedFloors.begin(), _revealedFloors.end(), floor) != _revealedFloors.end();\n}\n\n// helper overloads for deserialization-only\nbool read(ryml::ConstNodeRef const& n, RandomizedItems* val)\n{\n\tYAML::YamlNodeReader reader(n);\n\treader.tryRead(\"position\", val->position);\n\treader.tryRead(\"amount\", val->amount);\n\treader.tryRead(\"fuseTimerMin\", val->fuseTimerMin);\n\treader.tryRead(\"fuseTimerMax\", val->fuseTimerMax);\n\treader.tryRead(\"mixed\", val->mixed);\n\treader.tryRead(\"itemList\", val->itemList);\n\treturn true;\n}\n\nbool read(ryml::ConstNodeRef const& n, ExtendedItems* val)\n{\n\tYAML::YamlNodeReader reader(n);\n\treader.tryRead(\"type\", val->type);\n\treader.tryRead(\"pos\", val->pos);\n\treader.tryRead(\"fuseTimerMin\", val->fuseTimerMin);\n\treader.tryRead(\"fuseTimerMax\", val->fuseTimerMax);\n\treader.tryRead(\"ammoDef\", val->ammoDef);\n\treturn true;\n}\n\n}\n"
  },
  {
    "path": "src/Mod/MapBlock.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include <vector>\n#include \"../Engine/Yaml.h\"\n#include \"../Battlescape/Position.h\"\n\nnamespace OpenXcom\n{\n\nenum MapBlockType {MT_UNDEFINED = -1, MT_DEFAULT, MT_LANDINGZONE, MT_EWROAD, MT_NSROAD, MT_CROSSING};\nclass RuleTerrain;\n\nstruct RandomizedItems\n{\n\tPosition position;\n\tint amount;\n\tint fuseTimerMin;\n\tint fuseTimerMax;\n\tbool mixed;\n\tstd::vector<std::string> itemList;\n\tRandomizedItems() : amount(1), fuseTimerMin(-1), fuseTimerMax(-1), mixed(false) { /*Empty by Design*/ };\n};\n\nstruct ExtendedItems\n{\n\tstd::string type;\n\tstd::vector<Position> pos;\n\tint fuseTimerMin;\n\tint fuseTimerMax;\n\tstd::vector<std::pair<std::string, int> > ammoDef;\n\tExtendedItems() : fuseTimerMin(-1), fuseTimerMax(-1) { /*Empty by Design*/ };\n};\n\n/**\n * Represents a Terrain Map Block.\n * It contains constant info about this mapblock, like its name, dimensions, attributes...\n * Map blocks are stored in RuleTerrain objects.\n * @sa http://www.ufopaedia.org/index.php?title=MAPS_Terrain\n */\nclass MapBlock\n{\nprivate:\n\tstd::string _name;\n\tint _size_x, _size_y, _size_z;\n\tstd::vector<int> _groups, _revealedFloors;\n\tstd::vector<int> _craftInventoryTile;\n\tstd::map<std::string, std::vector<Position> > _items;\n\tstd::map<std::string, std::pair<int, int> > _itemsFuseTimer;\n\tstd::vector<RandomizedItems> _randomizedItems;\n\tstd::vector<ExtendedItems> _extendedItems;\npublic:\n\tMapBlock(const std::string &name);\n\t~MapBlock();\n\t/// Loads the map block from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader);\n\t/// Gets the mapblock's name (used for MAP generation).\n\tconst std::string& getName() const;\n\t/// Gets the mapblock's x size.\n\tint getSizeX() const;\n\t/// Gets the mapblock's y size.\n\tint getSizeY() const;\n\t/// Gets the mapblock's z size.\n\tint getSizeZ() const;\n\t/// Sets the mapblock's z size.\n\tvoid setSizeZ(int size_z);\n\t/// Returns if this mapblock is from the group specified.\n\tbool isInGroup(int group);\n\t/// Gets if this floor should be revealed or not.\n\tbool isFloorRevealed(int floor);\n\t/// Gets the items and their positioning for any items associated with this block.\n\tconst std::map<std::string, std::vector<Position> > *getItems() const { return &_items; }\n\t/// Gets the predefined fuse timers for items on this block.\n\tconst std::map<std::string, std::pair<int, int> > *getItemsFuseTimers() const { return &_itemsFuseTimer; }\n\t/// Gets the to-be-randomized items and their positioning for any items associated with this block.\n\tconst std::vector<RandomizedItems> *getRandomizedItems() const { return &_randomizedItems; }\n\t/// Gets the layout for any items that belong in this map block. Extended syntax.\n\tconst std::vector<ExtendedItems> *getExtendedItems() const { return &_extendedItems; }\n\t/// Gets the craft inventory tile position.\n\tconst std::vector<int>& getCraftInventoryTile() const { return _craftInventoryTile; };\n\n};\n\n// helper overloads for deserialization-only\nbool read(ryml::ConstNodeRef const& n, RandomizedItems* val);\nbool read(ryml::ConstNodeRef const& n, ExtendedItems* val);\n\n}\n"
  },
  {
    "path": "src/Mod/MapData.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"MapData.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Creates a new Map Data Object.\n * @param dataset The dataset this object belongs to.\n */\nMapData::MapData(MapDataSet *dataset) : _dataset(dataset), _specialType(TILE), \n\t\t\t\t_isUfoDoor(false), _stopLOS(false), _isNoFloor(false), _isGravLift(false), _isDoor(false), _blockFire(false), _blockSmoke(false), _baseModule(false),\n\t\t\t\t_yOffset(0), _TUWalk(0), _TUFly(0), _TUSlide(0), _terrainLevel(0), _footstepSound(0), _dieMCD(0), _altMCD(0), _objectType(O_FLOOR), _lightSource(0),\n\t\t\t\t_armor(0), _flammable(0), _fuel(0), _explosive(0), _explosiveType(0), _bigWall(0), _miniMapIndex(0)\n{\n\tstd::fill_n(_sprite, 8, 0);\n\tstd::fill_n(_block, 6, 0);\n\tstd::fill_n(_loftID, 12, 0);\n}\n\n/**\n * Destroys the object.\n */\nMapData::~MapData()\n{\n\n}\n\n/**\n * Gets the dataset this object belongs to.\n * @return Pointer to MapDataSet.\n */\nMapDataSet *MapData::getDataset() const\n{\n\treturn _dataset;\n}\n\n/**\n * Gets the sprite index.\n * @param frameID Animation frame 0-7.\n * @return The original sprite index.\n */\nint MapData::getSprite(int frameID) const\n{\n\treturn _sprite[frameID];\n}\n\n/**\n * Sets the sprite index for a certain frame.\n * @param frameID Animation frame\n * @param value The sprite index in the surfaceset of the mapdataset.\n */\nvoid MapData::setSprite(int frameID, int value)\n{\n\t_sprite[frameID] = value;\n}\n\n/**\n * Gets whether this is an animated ufo door.\n * @return True if this is an animated ufo door.\n */\nbool MapData::isUFODoor() const\n{\n\treturn _isUfoDoor;\n}\n\n/**\n * Gets whether this is a floor.\n * @return True if this is a floor.\n */\nbool MapData::isNoFloor() const\n{\n\treturn _isNoFloor;\n}\n\n/**\n * Gets whether this is a big wall, which blocks all surrounding paths.\n *\n * Return value key:\n * 0: not a bigWall\n * 1: regular bigWall\n * 2: allows movement in ne/sw direction\n * 3: allows movement in nw/se direction\n * 4: acts as a west wall\n * 5: acts as a north wall\n * 6: acts as an east wall\n * 7: acts as a south wall\n * 8: acts as a south and east wall.\n * 9: acts as a north and west wall.\n * @return An integer representing what kind of bigwall this is.\n */\nint MapData::getBigWall() const\n{\n\treturn _bigWall;\n}\n\n/**\n * Gets whether this is a normal door.\n * @return True if this is a normal door.\n */\nbool MapData::isDoor() const\n{\n\treturn _isDoor;\n}\n\n/**\n * Gets whether this is a grav lift.\n * @return True if this is a grav lift.\n */\nbool MapData::isGravLift() const\n{\n\treturn _isGravLift;\n}\n\n/**\n * Gets whether this should be drawn behind a unit or in front of a unit (i.e. if it works as a S or E wall).\n */\nbool MapData::isBackTileObject() const\n{\n\treturn getBigWall() < 6 || getBigWall() == 9;\n}\n\n/**\n * Sets all kinds of flags.\n * @param isUfoDoor True if this is a ufo door.\n * @param stopLOS True if this stops line of sight.\n * @param isNoFloor True if this is a floor.\n * @param bigWall True if this is a bigWall.\n * @param isGravLift True if this is a grav lift.\n * @param isDoor True if this is a normal door.\n * @param blockFire True if this blocks fire.\n * @param blockSmoke True if this blocks smoke.\n * @param baseModule True if this is a base module item.\n */\nvoid MapData::setFlags(bool isUfoDoor, bool stopLOS, bool isNoFloor, int bigWall, bool isGravLift, bool isDoor, bool blockFire, bool blockSmoke, bool baseModule)\n{\n\t_isUfoDoor = isUfoDoor;\n\t_stopLOS = stopLOS;\n\t_isNoFloor = isNoFloor;\n\t_bigWall = bigWall;\n\t_isGravLift = isGravLift;\n\t_isDoor = isDoor;\n\t_blockFire = blockFire;\n\t_blockSmoke = blockSmoke;\n\t_baseModule = baseModule;\n}\n\n/**\n * Gets the amount of blockage of a certain type.\n * @param type Type.\n * @return The blockage (0-255).\n */\nint MapData::getBlock(ItemDamageType type) const\n{\n\tif (type == DT_NONE)\n\t\treturn _block[1];\n\telse if (type == DT_SMOKE)\n\t\treturn _block[3];\n\telse if (type > DT_NONE && type < DAMAGE_TYPES)\n\t\treturn _block[2];\n\n\treturn 0;\n}\n\n/**\n * Sets the amount of blockage for all types.\n * @param lightBlock The light blockage.\n * @param visionBlock The vision blockage.\n * @param HEBlock The high explosive blockage.\n * @param smokeBlock The smoke blockage.\n * @param fireBlock The fire blockage.\n * @param gasBlock The gas blockage.\n */\nvoid MapData::setBlockValue(int lightBlock, int visionBlock, int HEBlock, int smokeBlock, int fireBlock, int gasBlock)\n{\n\t_block[0] = lightBlock; // not used...\n\t_block[1] = visionBlock==1?255:0;\n\t_block[2] = HEBlock;\n\t_block[3] = smokeBlock==1?256:0;\n\t_block[4] = fireBlock;\n\t_block[5] = gasBlock;\n}\n\n/**\n * Sets the amount of HE blockage.\n * @param HEBlock The high explosive blockage.\n */\nvoid MapData::setHEBlock(int HEBlock)\n{\n\t_block[2] = HEBlock;\n}\n\n/**\n * Gets the Y offset for drawing.\n * @return The height in pixels.\n */\nint MapData::getYOffset() const\n{\n\treturn _yOffset;\n}\n\n/**\n * Sets the offset on the Y axis for drawing this object.\n * @param value The offset.\n */\nvoid MapData::setYOffset(int value)\n{\n\t_yOffset = value;\n}\n\n/**\n * Gets info about special tile types.\n * @return The special tile type.\n */\nSpecialTileType MapData::getSpecialType() const\n{\n\treturn _specialType;\n}\n\n/**\n * Sets the type of object.\n * @param type New type of the object.\n */\nvoid MapData::setObjectType(TilePart type)\n{\n\t_objectType = type;\n}\n\n/**\n * Gets the type of object.\n * @return Type of the part of the tile.\n */\nTilePart MapData::getObjectType() const\n{\n\treturn _objectType;\n}\n\n/**\n * Sets a special tile type and object type.\n * @param value Special tile type.\n * @param otype Object type.\n */\nvoid MapData::setSpecialType(int value, TilePart otype)\n{\n\t_specialType = (SpecialTileType)value;\n\t_objectType = otype;\n}\n\n/**\n * Gets the TU cost to walk over the object.\n * @param movementType The movement type.\n * @return The TU cost.\n */\nint MapData::getTUCost(MovementType movementType) const\n{\n\tswitch (movementType)\n\t{\n\tcase MT_WALK:\n\t\treturn _TUWalk;\n\tcase MT_FLY:\n\t\treturn _TUFly;\n\tcase MT_SLIDE:\n\t\treturn _TUSlide;\n\tdefault:\n\t\tbreak;\n\t}\n\treturn 0;\n}\n\n/**\n * Sets the TU cost to move over the object.\n * @param walk The walking TU cost.\n * @param fly The flying TU cost.\n * @param slide The sliding TU cost.\n */\nvoid MapData::setTUCosts(int walk, int fly, int slide)\n{\n\t_TUWalk = walk;\n\t_TUFly = fly;\n\t_TUSlide = slide;\n}\n\n/**\n * Adds this to the graphical Y offset of units or objects on this tile.\n * @return The Y offset.\n */\nint MapData::getTerrainLevel() const\n{\n\treturn _terrainLevel;\n}\n\n/**\n * Sets the Y offset for units/objects on this tile.\n * @param value The Y offset.\n */\nvoid MapData::setTerrainLevel(int value)\n{\n\t_terrainLevel = value;\n}\n\n/**\n * Gets the index to the footstep sound.\n * @return The sound ID.\n */\nint MapData::getFootstepSound() const\n{\n\treturn _footstepSound;\n}\n\n/**\n * Sets the index to the footstep sound.\n * @param value The sound ID.\n */\nvoid MapData::setFootstepSound(int value)\n{\n\t_footstepSound = value;\n}\n\n/**\n * Gets the alternative object ID.\n * @return The alternative object ID.\n */\nint MapData::getAltMCD() const\n{\n\treturn _altMCD;\n}\n\n/**\n * Sets the alternative object ID.\n * @param value The alternative object ID.\n */\nvoid MapData::setAltMCD(int value)\n{\n\t_altMCD = value;\n}\n\n/**\n * Gets the dead object ID.\n * @return The dead object ID.\n */\nint MapData::getDieMCD() const\n{\n\treturn _dieMCD;\n}\n\n/**\n * Sets the dead object ID.\n * @param value The dead object ID.\n */\nvoid MapData::setDieMCD(int value)\n{\n\t_dieMCD = value;\n}\n\n/**\n * Gets the amount of light the object is emitting.\n * @return The amount of light emitted.\n */\nint MapData::getLightSource() const\n{\n\t// lamp posts have 1, but they should emit more light\n\tif (_lightSource == 1)\n\t\treturn 15;\n\telse\n\t\treturn _lightSource - 1;\n}\n\n/**\n * Sets the amount of light the object is emitting.\n * @param value The amount of light emitted.\n */\nvoid MapData::setLightSource(int value)\n{\n\t_lightSource = value;\n}\n\n/**\n * Gets the amount of armor.\n * @return The amount of armor.\n */\nint MapData::getArmor() const\n{\n\treturn _armor;\n}\n\n/**\n * Sets the amount of armor.\n * @param value The amount of armor.\n */\nvoid MapData::setArmor(int value)\n{\n\t_armor = value;\n}\n\n/**\n * Gets the amount of flammable (how flammable this object is).\n * @return The amount of flammable.\n */\nint MapData::getFlammable() const\n{\n\treturn _flammable;\n}\n\n/**\n * Sets the amount of flammable (how flammable this object is).\n * @param value The amount of flammable.\n */\nvoid MapData::setFlammable(int value)\n{\n\t_flammable = value;\n}\n\n/**\n * Gets the amount of fuel.\n * @return The amount of fuel.\n */\nint MapData::getFuel() const\n{\n\treturn _fuel;\n}\n\n/**\n * Sets the amount of fuel.\n * @param value The amount of fuel.\n */\nvoid MapData::setFuel(int value)\n{\n\t_fuel = value;\n}\n\n/**\n * Gets the loft index for a certain layer.\n * @param layer The layer.\n * @return The loft index.\n */\nint MapData::getLoftID(int layer) const\n{\n\treturn _loftID[layer];\n}\n\n/**\n * Sets the loft index for a certain layer.\n * @param loft The loft index.\n * @param layer The layer.\n */\nvoid MapData::setLoftID(int loft, int layer)\n{\n\t_loftID[layer] = loft;\n}\n\n/**\n * Gets the amount of explosive.\n * @return The amount of explosive.\n */\nint MapData::getExplosive() const\n{\n\treturn _explosive;\n}\n\n/**\n * Sets the amount of explosive.\n * @param value The amount of explosive.\n */\nvoid MapData::setExplosive(int value)\n{\n\t_explosive = value;\n}\n\n/**\n * Gets the type of explosive.\n * @return The amount of explosive.\n */\nint MapData::getExplosiveType() const\n{\n\treturn _explosiveType;\n}\n\n/**\n * Sets the type of explosive.\n * @param value The type of explosive.\n */\nvoid MapData::setExplosiveType(int value)\n{\n\t_explosiveType = value;\n}\n\n/**\n * Sets the SCANG.DAT index for minimap.\n * @param i The minimap index.\n */\nvoid MapData::setMiniMapIndex(unsigned short i)\n{\n\t_miniMapIndex = i;\n}\n\n/**\n * Gets the SCANG.DAT index for minimap.\n * @return The minimap index.\n */\nunsigned short MapData::getMiniMapIndex() const\n{\n\treturn _miniMapIndex;\n}\n\n/**\n * Sets the bigWall value.\n * @param bigWall The new bigWall value.\n */\nvoid MapData::setBigWall(const int bigWall)\n{\n\t_bigWall = bigWall;\n}\n\n/**\n * Sets the TUWalk value.\n * @param TUWalk The new TUWalk value.\n */\nvoid MapData::setTUWalk(const int TUWalk)\n{\n\t_TUWalk = TUWalk;\n}\n\n/**\n * Sets the TUFly value.\n * @param TUFly The new TUFly value.\n */\nvoid MapData::setTUFly(const int TUFly)\n{\n\t_TUFly = TUFly;\n}\n\n/**\n * Sets the TUSlide value.\n * @param TUSlide The new TUSlide value.\n */\nvoid MapData::setTUSlide(const int TUSlide)\n{\n\t_TUSlide = TUSlide;\n}\n\n/**\n * check if this is an xcom base object.\n * @return if it is a base object.\n */\nbool MapData::isBaseModule() const\n{\n\treturn _baseModule;\n}\n\n/**\n * set the \"no floor\" flag.\n * @param isNoFloor set the flag to THIS.\n */\nvoid MapData::setNoFloor(bool isNoFloor)\n{\n\t_isNoFloor = isNoFloor;\n}\n\n/**\n * set the \"stops LOS\" flag.\n * @param stopLOS set the flag to THIS.\n */\nvoid MapData::setStopLOS(bool stopLOS)\n{\n\t_stopLOS = stopLOS;\n\t_block[1] = stopLOS ? 255 : 0;\n}\n\n}\n"
  },
  {
    "path": "src/Mod/MapData.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"RuleItem.h\"\n\nnamespace OpenXcom\n{\n\nclass MapDataSet;\n\nenum SpecialTileType : int {TILE=0,\n\t\t\t\t\tSTART_POINT,\n\t\t\t\t\tUFO_POWER_SOURCE,\n\t\t\t\t\tUFO_NAVIGATION,\n\t\t\t\t\tUFO_CONSTRUCTION,\n\t\t\t\t\tALIEN_FOOD,\n\t\t\t\t\tALIEN_REPRODUCTION,\n\t\t\t\t\tALIEN_ENTERTAINMENT,\n\t\t\t\t\tALIEN_SURGERY,\n\t\t\t\t\tEXAM_ROOM,\n\t\t\t\t\tALIEN_ALLOYS,\n\t\t\t\t\tALIEN_HABITAT,\n\t\t\t\t\tDEAD_TILE,\n\t\t\t\t\tEND_POINT,\n\t\t\t\t\tMUST_DESTROY,\n\t\t\t\t\tDEATH_TRAPS=200};\n\nenum MovementType : int { MT_WALK, MT_FLY, MT_SLIDE, MT_FLOAT, MT_SINK};\nenum VoxelType : int { V_EMPTY = -1, V_FLOOR, V_WESTWALL, V_NORTHWALL, V_OBJECT, V_UNIT, V_OUTOFBOUNDS };\nenum TilePart : int { O_FLOOR, O_WESTWALL, O_NORTHWALL, O_OBJECT, O_MAX };\n\n/**\n * MapData is the smallest piece of a Battlescape terrain, holding info about a certain object, wall, floor, ...\n * @sa MapDataSet.\n */\nclass MapData\n{\nprivate:\n\tMapDataSet *_dataset;\n\tSpecialTileType _specialType;\n\tbool _isUfoDoor, _stopLOS, _isNoFloor, _isGravLift, _isDoor, _blockFire, _blockSmoke, _baseModule;\n\tint _yOffset, _TUWalk, _TUFly, _TUSlide, _terrainLevel, _footstepSound, _dieMCD, _altMCD;\n\tTilePart _objectType;\n\tint _lightSource;\n\tint _armor, _flammable, _fuel, _explosive, _explosiveType, _bigWall;\n\tint _sprite[8];\n\tint _block[6];\n\tint _loftID[12];\n\tunsigned short _miniMapIndex;\npublic:\n\tstatic const int O_DUMMY = 999;\n\tMapData(MapDataSet *dataset);\n\t~MapData();\n\t/// Gets the dataset this object belongs to.\n\tMapDataSet *getDataset() const;\n\t/// Gets the sprite index for a certain frame.\n\tint getSprite(int frameID) const;\n\t/// Sets the sprite index for a certain frame.\n\tvoid setSprite(int frameID, int value);\n\t/// Gets whether this is an animated ufo door.\n\tbool isUFODoor() const;\n\t/// Gets whether this is a floor.\n\tbool isNoFloor() const;\n\t/// Gets whether this is a big wall, which blocks all surrounding paths.\n\tint getBigWall() const;\n\t/// Gets whether this is a normal door.\n\tbool isDoor() const;\n\t/// Gets whether this is a grav lift.\n\tbool isGravLift() const;\n\t/// Gets whether this should be drawn behind a unit or in front of a unit (i.e. if it works as a S or E wall).\n\tbool isBackTileObject() const;\n\t/// Sets all kinds of flags.\n\tvoid setFlags(bool isUfoDoor, bool stopLOS, bool isNoFloor, int bigWall, bool isGravLift, bool isDoor, bool blockFire, bool blockSmoke, bool baseModule);\n\t/// Gets the amount of blockage of a certain type.\n\tint getBlock(ItemDamageType type) const;\n\t/// Sets the amount of blockage for all types.\n\tvoid setBlockValue(int lightBlock, int visionBlock, int HEBlock, int smokeBlock, int fireBlock, int gasBlock);\n\t/// Sets the amount of HE blockage.\n\tvoid setHEBlock(int HEBlock);\n\t/// Gets the offset on the Y axis when drawing this object.\n\tint getYOffset() const;\n\t/// Sets the offset on the Y axis for drawing this object.\n\tvoid setYOffset(int value);\n\t/// Set the type of tile.\n\tvoid setObjectType(TilePart type);\n\t/// Get the type of tile.\n\tTilePart getObjectType() const;\n\t/// Gets info about special tile types\n\tSpecialTileType getSpecialType() const;\n\t/// Sets a special tile type and object type.\n\tvoid setSpecialType(int value, TilePart otype);\n\t/// Gets the TU cost to move over the object.\n\tint getTUCost(MovementType movementType) const;\n\t/// Sets the TU cost to move over the object.\n\tvoid setTUCosts(int walk, int fly, int slide);\n\t/// Adds this to the graphical Y offset of units or objects on this tile.\n\tint getTerrainLevel() const;\n\t/// Sets Y offset for units/objects on this tile.\n\tvoid setTerrainLevel(int value);\n\t/// Gets the index to the footstep sound.\n\tint getFootstepSound() const;\n\t/// Sets the index to the footstep sound.\n\tvoid setFootstepSound(int value);\n\t/// Gets the alternative object ID.\n\tint getAltMCD() const;\n\t/// Sets the alternative object ID.\n\tvoid setAltMCD(int value);\n\t/// Gets the dead object ID.\n\tint getDieMCD() const;\n\t/// Sets the dead object ID.\n\tvoid setDieMCD(int value);\n\t/// Gets the amount of light the object is emitting.\n\tint getLightSource() const;\n\t/// Sets the amount of light the object is emitting.\n\tvoid setLightSource(int value);\n\t/// Gets the amount of armor.\n\tint getArmor() const;\n\t/// Sets the amount of armor.\n\tvoid setArmor(int value);\n\t/// Gets the amount of flammable.\n\tint getFlammable() const;\n\t/// Sets the amount of flammable.\n\tvoid setFlammable(int value);\n\t/// Gets the amount of fuel.\n\tint getFuel() const;\n\t/// Sets the amount of fuel.\n\tvoid setFuel(int value);\n\t/// Gets the loft index for a certain layer.\n\tint getLoftID(int layer) const;\n\t/// Sets the loft index for a certain layer.\n\tvoid setLoftID(int loft, int layer);\n\t/// Gets the amount of explosive.\n\tint getExplosive() const;\n\t/// Sets the amount of explosive.\n\tvoid setExplosive(int value);\n\t/// Gets the type of explosive.\n\tint getExplosiveType() const;\n\t/// Sets the type of explosive.\n\tvoid setExplosiveType(int value);\n\t/// Sets the MiniMap index\n\tvoid setMiniMapIndex(unsigned short i);\n\t/// Gets the MiniMap index\n\tunsigned short getMiniMapIndex() const;\n\t/// Sets the bigwall value.\n\tvoid setBigWall(const int bigWall);\n\t/// Sets the TUWalk value.\n\tvoid setTUWalk(const int TUWalk);\n\t/// Sets the TUFly value.\n\tvoid setTUFly(const int TUFly);\n\t/// Sets the TUSlide value.\n\tvoid setTUSlide(const int TUSlide);\n\t/// Check if this is an xcom base object.\n\tbool isBaseModule() const;\n\t/// Sets this tile as not a floor (water, etc.)\n\tvoid setNoFloor(bool isNoFloor);\n\t/// Sets this tile as not stopping LOS.\n\tvoid setStopLOS(bool stopLOS);\n};\n\n}\n"
  },
  {
    "path": "src/Mod/MapDataSet.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"MapDataSet.h\"\n#include \"MapData.h\"\n#include <sstream>\n#include <SDL_endian.h>\n#include \"../Engine/Exception.h\"\n#include \"../Engine/SurfaceSet.h\"\n#include \"../Engine/FileMap.h\"\n#include \"../Engine/Logger.h\"\n\nnamespace OpenXcom\n{\n\nMapData *MapDataSet::_blankTile = 0;\nMapData *MapDataSet::_scorchedTile = 0;\n\n/**\n * MapDataSet construction.\n */\nMapDataSet::MapDataSet(const std::string &name) : _name(name), _surfaceSet(0), _loaded(false)\n{\n}\n\n/**\n * MapDataSet destruction.\n */\nMapDataSet::~MapDataSet()\n{\n\tunloadData();\n}\n\n/**\n * Gets the MapDataSet name (string).\n * @return The MapDataSet name.\n */\nstd::string MapDataSet::getName() const\n{\n\treturn _name;\n}\n\n/**\n * Gets the MapDataSet size.\n * @return The size in number of records.\n */\nsize_t MapDataSet::getSize() const\n{\n\treturn _objects.size();\n}\n\n/**\n * Gets the objects in this dataset.\n * @return Pointer to the objects.\n */\nstd::vector<MapData*> *MapDataSet::getObjectsRaw()\n{\n\treturn &_objects;\n}\n\n/**\n * Gets an object in this dataset.\n * @param i Object index.\n * @return Pointer to the object.\n */\nMapData *MapDataSet::getObject(size_t i)\n{\n\tif (i >= _objects.size())\n\t{\n\t\tstd::ostringstream ss;\n\t\tss << \"MCD \" << _name << \" has no object \" << i;\n\t\tthrow Exception(ss.str());\n\t}\n\treturn _objects[i];\n}\n\n/**\n * Gets the surfaces in this dataset.\n * @return Pointer to the surfaceset.\n */\nSurfaceSet *MapDataSet::getSurfaceset() const\n{\n\treturn _surfaceSet;\n}\n\n/**\n * Loads terrain data in XCom format (MCD & PCK files).\n * @sa http://www.ufopaedia.org/index.php?title=MCD\n */\nvoid MapDataSet::loadData(MCDPatch *patch, bool validate)\n{\n\t// prevents loading twice\n\tif (_loaded) return;\n\t_loaded = true;\n\n\tint objNumber = 0;\n\n\t// the struct below helps to read the xcom file format\n\t#pragma pack(push, 1)\n\tstruct MCD\n\t{\n\tunsigned char Frame[8];\n\tunsigned char LOFT[12];\n\tunsigned short ScanG;\n\tunsigned char u23;\n\tunsigned char u24;\n\tunsigned char u25;\n\tunsigned char u26;\n\tunsigned char u27;\n\tunsigned char u28;\n\tunsigned char u29;\n\tunsigned char u30;\n\tunsigned char UFO_Door;\n\tunsigned char Stop_LOS;\n\tunsigned char No_Floor;\n\tunsigned char Big_Wall;\n\tunsigned char Gravlift;\n\tunsigned char Door;\n\tunsigned char Block_Fire;\n\tunsigned char Block_Smoke;\n\tunsigned char u39;\n\tunsigned char TU_Walk;\n\tunsigned char TU_Slide;\n\tunsigned char TU_Fly;\n\tunsigned char Armor;\n\tunsigned char HE_Block;\n\tunsigned char Die_MCD;\n\tunsigned char Flammable;\n\tunsigned char Alt_MCD;\n\tunsigned char u48;\n\tsigned char T_Level;\n\tunsigned char P_Level;\n\tunsigned char u51;\n\tunsigned char Light_Block;\n\tunsigned char Footstep;\n\tunsigned char Tile_Type;\n\tunsigned char HE_Type;\n\tunsigned char HE_Strength;\n\tunsigned char Smoke_Blockage;\n\tunsigned char Fuel;\n\tunsigned char Light_Source;\n\tunsigned char Target_Type;\n\tunsigned char Xcom_Base;\n\tunsigned char u62;\n\t};\n\t#pragma pack(pop)\n\n\tMCD mcd;\n\n\t// Load Terrain Data from MCD file\n\tstd::string fname = \"TERRAIN/\" + _name + \".MCD\";\n\tauto mapFile = FileMap::getIStream(fname);\n\n\twhile (mapFile->read((char*)&mcd, sizeof(MCD)))\n\t{\n\t\tMapData *to = new MapData(this);\n\t\t_objects.push_back(to);\n\n\t\t// set all the terrain object properties:\n\t\tfor (int frame = 0; frame < 8; frame++)\n\t\t{\n\t\t\tto->setSprite(frame,(int)mcd.Frame[frame]);\n\t\t}\n\t\tto->setYOffset((int)mcd.P_Level);\n\t\tto->setSpecialType((int)mcd.Target_Type, (TilePart)mcd.Tile_Type);\n\t\tto->setTUCosts((int)mcd.TU_Walk, (int)mcd.TU_Fly, (int)mcd.TU_Slide);\n\t\tto->setFlags(mcd.UFO_Door != 0, mcd.Stop_LOS != 0, mcd.No_Floor != 0, (int)mcd.Big_Wall, mcd.Gravlift != 0, mcd.Door != 0, mcd.Block_Fire != 0, mcd.Block_Smoke != 0, mcd.Xcom_Base != 0);\n\t\tto->setTerrainLevel((int)mcd.T_Level);\n\t\tto->setFootstepSound((int)mcd.Footstep);\n\t\tto->setAltMCD((int)(mcd.Alt_MCD));\n\t\tto->setDieMCD((int)(mcd.Die_MCD));\n\t\tto->setBlockValue((int)mcd.Light_Block, (int)mcd.Stop_LOS, (int)mcd.HE_Block, (int)mcd.Block_Smoke, (int)mcd.Flammable, (int)mcd.HE_Block);\n\t\tto->setLightSource((int)mcd.Light_Source);\n\t\tto->setArmor((int)mcd.Armor);\n\t\tto->setFlammable((int)mcd.Flammable);\n\t\tto->setFuel((int)mcd.Fuel);\n\t\tto->setExplosiveType((int)mcd.HE_Type);\n\t\tto->setExplosive((int)mcd.HE_Strength);\n\t\tmcd.ScanG = SDL_SwapLE16(mcd.ScanG);\n\t\tto->setMiniMapIndex(mcd.ScanG);\n\n\t\tfor (int layer = 0; layer < 12; layer++)\n\t\t{\n\t\t\tint loft = (int)mcd.LOFT[layer];\n\t\t\tto->setLoftID(loft, layer);\n\t\t}\n\n\t\t// store the 2 tiles of blanks in a static - so they are accessible everywhere\n\t\tif (_name.compare(\"BLANKS\") == 0)\n\t\t{\n\t\t\tif (objNumber == 0)\n\t\t\t\tMapDataSet::_blankTile = to;\n\t\t\telse if (objNumber == 1)\n\t\t\t\tMapDataSet::_scorchedTile = to;\n\t\t}\n\t\tobjNumber++;\n\t}\n\n\tif (!mapFile->eof())\n\t{\n\t\tthrow Exception(\"Invalid MCD file \" + fname);\n\t}\n\n\t// apply any ruleset patches before validation\n\tif (patch)\n\t{\n\t\tpatch->modifyData(this);\n\t}\n\n\t// Validate MCD references\n\tif (validate)\n\t{\n\t\tfor (size_t i = 0; i < _objects.size(); ++i)\n\t\t{\n\t\t\tif ((size_t)_objects[i]->getDieMCD() >= _objects.size())\n\t\t\t{\n\t\t\t\tLog(LOG_INFO) << \"MCD \" << _name << \" object \" << i << \" has invalid DieMCD: \" << _objects[i]->getDieMCD();\n\t\t\t}\n\t\t\tif ((size_t)_objects[i]->getAltMCD() >= _objects.size())\n\t\t\t{\n\t\t\t\tLog(LOG_INFO) << \"MCD \" << _name << \" object \" << i << \" has invalid AltMCD: \" << _objects[i]->getAltMCD();\n\t\t\t}\n\t\t\tif (_objects[i]->getArmor() == 0)\n\t\t\t{\n\t\t\t\tLog(LOG_INFO) << \"MCD \" << _name << \" object \" << i << \" has 0 armor\";\n\t\t\t}\n\t\t}\n\t}\n\n\t// Load terrain sprites/surfaces/PCK files into a surfaceset\n\t_surfaceSet = new SurfaceSet(32, 40);\n\t_surfaceSet->loadPck(\"TERRAIN/\" + _name + \".PCK\", \"TERRAIN/\" + _name + \".TAB\");\n}\n\n/**\n * Unloads the terrain data.\n */\nvoid MapDataSet::unloadData()\n{\n\tif (_loaded)\n\t{\n\t\tfor (auto* mapdata : _objects)\n\t\t{\n\t\t\tdelete mapdata;\n\t\t}\n\t\t_objects.clear();\n\t\tdelete _surfaceSet;\n\t\t_loaded = false;\n\t}\n}\n\n/**\n * Loads the LOFTEMPS.DAT into the ruleset voxeldata.\n * @param filename Filename of the DAT file.\n * @param voxelData The ruleset.\n */\nvoid MapDataSet::loadLOFTEMPS(const std::string &filename, std::vector<Uint16> *voxelData)\n{\n\tauto mapFile = FileMap::getIStream(filename);\n\tUint16 value;\n\n\twhile (mapFile->read((char*)&value, sizeof(value)))\n\t{\n\t\tvalue = SDL_SwapLE16(value);\n\t\tvoxelData->push_back(value);\n\t}\n\n\tif (!mapFile->eof())\n\t{\n\t\tthrow Exception(\"Invalid LOFTEMPS\");\n\t}\n}\n\n/**\n * Gets a blank floor tile.\n * @return Pointer to a blank tile.\n */\nMapData *MapDataSet::getBlankFloorTile()\n{\n\treturn MapDataSet::_blankTile;\n}\n\n/**\n * Gets a scorched earth tile.\n * @return Pointer to a scorched earth tile.\n */\nMapData *MapDataSet::getScorchedEarthTile()\n{\n\treturn MapDataSet::_scorchedTile;\n}\n\n}\n"
  },
  {
    "path": "src/Mod/MapDataSet.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include <vector>\n#include <SDL.h>\n#include \"../Mod/MCDPatch.h\"\n\nnamespace OpenXcom\n{\n\nclass MapData;\nclass SurfaceSet;\n\n/**\n * Represents a Terrain Map Datafile.\n * Which corresponds to an XCom MCD & PCK file.\n * The list of map datafiles is stored in RuleSet, but referenced in RuleTerrain.\n * @sa http://www.ufopaedia.org/index.php?title=MCD\n */\nclass MapDataSet\n{\nprivate:\n\tstd::string _name;\n\tstd::vector<MapData*> _objects;\n\tSurfaceSet *_surfaceSet;\n\tbool _loaded;\n\tstatic MapData *_blankTile;\n\tstatic MapData *_scorchedTile;\npublic:\n\tMapDataSet(const std::string &name);\n\t~MapDataSet();\n\t/// Loads voxeldata from a DAT file.\n\tstatic void loadLOFTEMPS(const std::string &filename, std::vector<Uint16> *voxelData);\n\t/// Gets the dataset name (used for MAP generation).\n\tstd::string getName() const;\n\t/// Gets the dataset size.\n\tsize_t getSize() const;\n\t/// Gets the objects in this dataset.\n\tstd::vector<MapData*> *getObjectsRaw();\n\t/// Gets an object in this dataset.\n\tMapData *getObject(size_t i);\n\t/// Gets the surfaces in this dataset.\n\tSurfaceSet *getSurfaceset() const;\n\t/// Loads the objects from an MCD file.\n\tvoid loadData(MCDPatch *patch, bool validate = true);\n\t///\tUnloads to free memory.\n\tvoid unloadData();\n\t/// Gets a blank floor tile.\n\tstatic MapData *getBlankFloorTile();\n\t/// Gets a scorched earth tile.\n\tstatic MapData *getScorchedEarthTile();\n};\n\n}\n"
  },
  {
    "path": "src/Mod/MapScript.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"MapScript.h\"\n#include \"../Engine/Yaml.h\"\n#include \"../Engine/RNG.h\"\n#include \"../Engine/Exception.h\"\n#include \"../Engine/Logger.h\"\n#include \"../Mod/RuleTerrain.h\"\n\n\nnamespace OpenXcom\n{\n\nMapScript::MapScript() :\n\t_type(MSC_UNDEFINED), _canBeSkipped(true), _markAsReinforcementsBlock(false),\n\t_verticalGroup(MT_NSROAD), _horizontalGroup(MT_EWROAD), _crossingGroup(MT_CROSSING),\n\t_sizeX(1), _sizeY(1), _sizeZ(0),\n\t_executionChances(100), _executions(1), _cumulativeFrequency(0), _label(0),\n\t_direction(MD_NONE),\n\t_tunnelData(0), _randomTerrain(), _verticalLevels()\n{\n}\n\nMapScript::~MapScript()\n{\n\tfor (auto* rect : _rects)\n\t{\n\t\tdelete rect;\n\t}\n\tdelete _tunnelData;\n}\n\n/**\n * Loads a map script command from YAML.\n * @param node the YAML node from which to read.\n */\nvoid MapScript::load(const YAML::YamlNodeReader& node)\n{\n\tconst auto& reader = node.useIndex();\n\tstd::string command;\n\tif (const auto& map = reader[\"type\"])\n\t{\n\t\tcommand = map.readVal<std::string>(\"\");\n\t\tif (command == \"addBlock\")\n\t\t\t_type = MSC_ADDBLOCK;\n\t\telse if (command == \"addLine\")\n\t\t\t_type = MSC_ADDLINE;\n\t\telse if (command == \"addCraft\")\n\t\t{\n\t\t\t_type = MSC_ADDCRAFT;\n\t\t\t_groups.push_back(1); // this is a default, and can be overridden\n\t\t}\n\t\telse if (command == \"addUFO\")\n\t\t{\n\t\t\t_type = MSC_ADDUFO;\n\t\t\t_groups.push_back(1); // this is a default, and can be overridden\n\t\t}\n\t\telse if (command == \"digTunnel\")\n\t\t\t_type = MSC_DIGTUNNEL;\n\t\telse if (command == \"fillArea\")\n\t\t\t_type = MSC_FILLAREA;\n\t\telse if (command == \"checkBlock\")\n\t\t\t_type = MSC_CHECKBLOCK;\n\t\telse if (command == \"removeBlock\")\n\t\t\t_type = MSC_REMOVE;\n\t\telse if (command == \"resize\")\n\t\t{\n\t\t\t_type = MSC_RESIZE;\n\t\t\t_sizeX = _sizeY = 0; // defaults: don't resize anything unless specified.\n\t\t}\n\t\telse\n\t\t{\n\t\t\tthrow Exception(\"Unknown command: \" + command);\n\t\t}\n\t}\n\telse\n\t{\n\t\tthrow Exception(\"Missing command type.\");\n\t}\n\n\n\tfor (const auto& rectReader : reader[\"rects\"].children())\n\t{\n\t\tSDL_Rect* rect = new SDL_Rect();\n\t\trect->x = rectReader[0].readVal<int>();\n\t\trect->y = rectReader[1].readVal<int>();\n\t\trect->w = rectReader[2].readVal<int>();\n\t\trect->h = rectReader[3].readVal<int>();\n\t\t_rects.push_back(rect);\n\t}\n\tif (const auto& craftGroups = reader[\"craftGroups\"])\n\t{\n\t\tcraftGroups.tryReadVal(_craftGroups);\n\t}\n\tif (const auto& map = reader[\"tunnelData\"])\n\t{\n\t\t_tunnelData = new TunnelData;\n\t\t_tunnelData->level = map[\"level\"].readVal(0);\n\t\tfor (const auto& mcdReplacement : map[\"MCDReplacements\"].children())\n\t\t{\n\t\t\tMCDReplacement replacement;\n\t\t\tstd::string type = mcdReplacement[\"type\"].readVal<std::string>(\"\");\n\t\t\treplacement.entry = mcdReplacement[\"entry\"].readVal(-1);\n\t\t\treplacement.set = mcdReplacement[\"set\"].readVal(-1);\n\t\t\t_tunnelData->replacements[type] = replacement;\n\t\t}\n\t}\n\tif (const auto& map = reader[\"conditionals\"])\n\t{\n\t\tif (map.isSeq())\n\t\t{\n\t\t\tmap.tryReadVal(_conditionals);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_conditionals.push_back(map.readVal(0));\n\t\t}\n\t}\n\tif (const auto& map = reader[\"size\"])\n\t{\n\t\tif (map.isSeq())\n\t\t{\n\t\t\tint *sizes[3] = {&_sizeX, &_sizeY, &_sizeZ};\n\t\t\tint entry = 0;\n\t\t\tfor (const auto& size : map.children())\n\t\t\t{\n\t\t\t\t*sizes[entry] = size.readVal(1);\n\t\t\t\tentry++;\n\t\t\t\tif (entry == 3)\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tmap.tryReadVal(_sizeX);\n\t\t\t_sizeY = _sizeX;\n\t\t}\n\t}\n\n\tif (const auto& map = reader[\"groups\"])\n\t{\n\t\t_groups.clear();\n\t\tif (map.isSeq())\n\t\t{\n\t\t\tfor (const auto& group : map.children())\n\t\t\t{\n\t\t\t\t_groups.push_back(group.readVal(0));\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_groups.push_back(map.readVal(0));\n\t\t}\n\t}\n\tsize_t selectionSize = _groups.size();\n\tif (const auto& map = reader[\"blocks\"])\n\t{\n\t\t_groups.clear();\n\t\tif (map.isSeq())\n\t\t{\n\t\t\tfor (const auto& block : map.children())\n\t\t\t{\n\t\t\t\t_blocks.push_back(block.readVal(0));\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_blocks.push_back(map.readVal(0));\n\t\t}\n\t\tselectionSize = _blocks.size();\n\t}\n\n\t_frequencies.resize(selectionSize, 1);\n\t_maxUses.resize(selectionSize, -1);\n\n\tif (const auto& map = reader[\"freqs\"])\n\t{\n\t\tif (map.isSeq())\n\t\t{\n\t\t\tsize_t entry = 0;\n\t\t\tfor (const auto& freq : map.children())\n\t\t\t{\n\t\t\t\tif (entry == selectionSize)\n\t\t\t\t\tbreak;\n\t\t\t\t_frequencies.at(entry) = freq.readVal(1);\n\t\t\t\tentry++;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_frequencies.at(0) = map.readVal(1);\n\t\t}\n\t}\n\tif (const auto& map = reader[\"maxUses\"])\n\t{\n\t\tif (map.isSeq())\n\t\t{\n\t\t\tsize_t entry = 0;\n\t\t\tfor (const auto& maxUse : map.children())\n\t\t\t{\n\t\t\t\tif (entry == selectionSize)\n\t\t\t\t\tbreak;\n\t\t\t\t_maxUses.at(entry) = maxUse.readVal(-1);\n\t\t\t\tentry++;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_maxUses.at(0) = map.readVal(-1);\n\t\t}\n\t}\n\n\tif (const auto& map = reader[\"direction\"])\n\t{\n\t\tstd::string direction = map.readVal<std::string>(\"\");\n\t\tif (!direction.empty())\n\t\t{\n\t\t\tchar dir = toupper(direction[0]);\n\t\t\tswitch (dir)\n\t\t\t{\n\t\t\tcase 'V':\n\t\t\t\t_direction = MD_VERTICAL;\n\t\t\t\tbreak;\n\t\t\tcase 'H':\n\t\t\t\t_direction = MD_HORIZONTAL;\n\t\t\t\tbreak;\n\t\t\tcase 'B':\n\t\t\t\t_direction = MD_BOTH;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthrow Exception(\"direction must be [V]ertical, [H]orizontal, or [B]oth, what does \" + direction + \" mean?\");\n\t\t\t}\n\t\t}\n\t}\n\n\tif (_direction == MD_NONE)\n\t{\n\t\tif (_type == MSC_DIGTUNNEL || _type == MSC_ADDLINE)\n\t\t{\n\t\t\tthrow Exception(\"no direction defined for \" + command + \" command, must be [V]ertical, [H]orizontal, or [B]oth\");\n\t\t}\n\t}\n\n\n\treader.tryRead(\"verticalGroup\", _verticalGroup);\n\treader.tryRead(\"horizontalGroup\", _horizontalGroup);\n\treader.tryRead(\"crossingGroup\", _crossingGroup);\n\treader.tryRead(\"canBeSkipped\", _canBeSkipped);\n\treader.tryRead(\"markAsReinforcementsBlock\", _markAsReinforcementsBlock);\n\treader.tryRead(\"executionChances\", _executionChances);\n\treader.tryRead(\"executions\", _executions);\n\treader.tryRead(\"UFOName\", _ufoName);\n\treader.tryRead(\"craftName\", _craftName);\n\tif (reader[\"terrain\"])\n\t{\n\t\t_randomTerrain.clear();\n\t\t_randomTerrain.push_back(reader[\"terrain\"].readVal<std::string>());\n\t}\n\treader.tryRead(\"randomTerrain\", _randomTerrain);\n\t// take no chances, don't accept negative values here.\n\t_label = std::abs(reader[\"label\"].readVal(_label));\n\n\t// Load any VerticalLevels into a map if we have them\n\tif (reader[\"verticalLevels\"])\n\t{\n\t\t_verticalLevels.clear();\n\t\tfor (const auto& levelReader : reader[\"verticalLevels\"].children())\n\t\t{\n\t\t\tif (levelReader[\"type\"])\n\t\t\t{\n\t\t\t\tVerticalLevel level;\n\t\t\t\tlevel.load(levelReader);\n\t\t\t\t_verticalLevels.push_back(level);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Initializes all the various scratch values and such for the command.\n */\nvoid MapScript::init()\n{\n\t_cumulativeFrequency = 0;\n\t_blocksTemp.clear();\n\t_groupsTemp.clear();\n\t_frequenciesTemp.clear();\n\t_maxUsesTemp.clear();\n\n\tfor (int freq : _frequencies)\n\t{\n\t\t_cumulativeFrequency += freq;\n\t}\n\t_blocksTemp = _blocks;\n\t_groupsTemp = _groups;\n\t_frequenciesTemp = _frequencies;\n\t_maxUsesTemp = _maxUses;\n}\n\n/**\n * Initializes scratch values for working in a vertical level\n */\nvoid MapScript::initVerticalLevel(VerticalLevel level)\n{\n\t_cumulativeFrequency = 0;\n\t_blocksTemp.clear();\n\t_groupsTemp.clear();\n\t_frequenciesTemp.clear();\n\t_maxUsesTemp.clear();\n\n\t_blocks = level.levelBlocks;\n\t_groups = level.levelGroups;\n\t_cumulativeFrequency = std::max(_blocks.size(), _groups.size());\n\t_frequenciesTemp.resize(_cumulativeFrequency, 1);\n\t_maxUsesTemp.resize(_cumulativeFrequency, -1);\n\t_blocksTemp = _blocks;\n\t_groupsTemp = _groups;\n}\n\n/**\n * Gets a random group number from the array, accounting for frequencies and max uses.\n * If no groups or blocks are defined, this command will return the default\" group,\n * If all the max uses are used up, it will return \"undefined\".\n * @return Group number.\n */\nint MapScript::getGroupNumber()\n{\n\tif (!_groups.size())\n\t{\n\t\treturn MT_DEFAULT;\n\t}\n\tif (_cumulativeFrequency > 0)\n\t{\n\t\tint pick = RNG::generate(0, _cumulativeFrequency-1);\n\t\tfor (size_t i = 0; i != _groupsTemp.size(); ++i)\n\t\t{\n\t\t\tif (pick < _frequenciesTemp.at(i))\n\t\t\t{\n\t\t\t\tint retVal = _groupsTemp.at(i);\n\n\t\t\t\tif (_maxUsesTemp.at(i) > 0)\n\t\t\t\t{\n\t\t\t\t\tif (--_maxUsesTemp.at(i) == 0)\n\t\t\t\t\t{\n\t\t\t\t\t\t_groupsTemp.erase(_groupsTemp.begin() + i);\n\t\t\t\t\t\t_cumulativeFrequency -= _frequenciesTemp.at(i);\n\t\t\t\t\t\t_frequenciesTemp.erase(_frequenciesTemp.begin() + i);\n\t\t\t\t\t\t_maxUsesTemp.erase(_maxUsesTemp.begin() + i);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn retVal;\n\t\t\t}\n\t\t\tpick -= _frequenciesTemp.at(i);\n\t\t}\n\t}\n\treturn MT_UNDEFINED;\n}\n\n/**\n * Gets a random block number from the array, accounting for frequencies and max uses.\n * If no blocks are defined, it will use a group instead.\n * @return Block number.\n */\nint MapScript::getBlockNumber()\n{\n\tif (_cumulativeFrequency > 0)\n\t{\n\t\tint pick = RNG::generate(0, _cumulativeFrequency-1);\n\t\tfor (size_t i = 0; i != _blocksTemp.size(); ++i)\n\t\t{\n\t\t\tif (pick < _frequenciesTemp.at(i))\n\t\t\t{\n\t\t\t\tint retVal = _blocksTemp.at(i);\n\n\t\t\t\tif (_maxUsesTemp.at(i) > 0)\n\t\t\t\t{\n\t\t\t\t\tif (--_maxUsesTemp.at(i) == 0)\n\t\t\t\t\t{\n\t\t\t\t\t\t_blocksTemp.erase(_blocksTemp.begin() + i);\n\t\t\t\t\t\t_cumulativeFrequency -= _frequenciesTemp.at(i);\n\t\t\t\t\t\t_frequenciesTemp.erase(_frequenciesTemp.begin() + i);\n\t\t\t\t\t\t_maxUsesTemp.erase(_maxUsesTemp.begin() + i);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn retVal;\n\t\t\t}\n\t\t\tpick -= _frequenciesTemp.at(i);\n\t\t}\n\t}\n\treturn MT_UNDEFINED;\n}\n\n/**\n * Gets a random map block from a given terrain, using either the groups or the blocks defined.\n * @param terrain the terrain to pick a block from.\n * @return Pointer to a randomly chosen map block, given the options available.\n */\nMapBlock *MapScript::getNextBlock(RuleTerrain *terrain)\n{\n\tif (_blocks.empty())\n\t{\n\t\treturn terrain->getRandomMapBlock(_sizeX * 10, _sizeY * 10, getGroupNumber());\n\t}\n\tint result = getBlockNumber();\n\tif (result < (int)(terrain->getMapBlocks()->size()) && result != MT_UNDEFINED)\n\t{\n\t\treturn terrain->getMapBlocks()->at((size_t)(result));\n\t}\n\treturn 0;\n}\n\n/**\n * Gets the name of the UFO in the case of \"setUFO\"\n * @return the UFO name.\n */\nstd::string MapScript::getUFOName() const\n{\n\treturn _ufoName;\n}\n\n/**\n* Gets the name of the craft in the case of \"addCraft\"\n* @return the craft name.\n*/\nstd::string MapScript::getCraftName()\n{\n\treturn _craftName;\n}\n\n/**\n * Gets the alternate terrain list for this command.\n * @return the vector of terrain names.\n */\nconst std::vector<std::string> &MapScript::getRandomAlternateTerrain() const\n{\n\treturn _randomTerrain;\n}\n\n/**\n * Gets the vertical levels defined in a map script command\n * @return the vector of VerticalLevels\n */\nconst std::vector<VerticalLevel> &MapScript::getVerticalLevels() const\n{\n\treturn _verticalLevels;\n}\n\n/**\n * For use only with base defense maps as a special case,\n * set _verticalLevels directly for a new MapScript\n * @param verticalLevels the vector of VerticalLevels\n * @param sizeX the X-size of the facility whose VerticalLevels are being loaded\n * @param sizeY the Y-size of the facility whose VerticalLevels are being loaded\n */\nvoid MapScript::setVerticalLevels(const std::vector<VerticalLevel> &verticalLevels, int sizeX, int sizeY)\n{\n\t_verticalLevels = verticalLevels;\n\t_sizeX = sizeX;\n\t_sizeY = sizeY;\n}\n\n}\n"
  },
  {
    "path": "src/Mod/MapScript.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <vector>\n#include <string>\n#include \"../Engine/Yaml.h\"\n#include <SDL_video.h>\n#include \"MapBlock.h\"\n#include \"../Engine/Logger.h\"\n\nnamespace OpenXcom\n{\n\nenum MapDirection {MD_NONE, MD_VERTICAL, MD_HORIZONTAL, MD_BOTH};\nstruct MCDReplacement {\tint set, entry;};\nstruct TunnelData\n {\n\tstd::map<std::string, MCDReplacement> replacements;\n\tint level;\n\tTunnelData() : level(0) { }\n\tMCDReplacement *getMCDReplacement(const std::string& type)\n\t{\n\t\tif (replacements.find(type) == replacements.end())\n\t\t{\n\t\t\treturn 0;\n\t\t}\n\n\t\treturn &replacements[type];\n\t}\n };\nenum MapScriptCommand {MSC_UNDEFINED = -1, MSC_ADDBLOCK, MSC_ADDLINE, MSC_ADDCRAFT, MSC_ADDUFO, MSC_DIGTUNNEL, MSC_FILLAREA, MSC_CHECKBLOCK, MSC_REMOVE, MSC_RESIZE};\n\nclass MapBlock;\nclass RuleTerrain;\n\n// Structure for containing multiple levels of map blocks inside a command\nenum VerticalLevelType {VLT_GROUND, VLT_MIDDLE, VLT_CEILING, VLT_EMPTY, VLT_DECORATION, VLT_CRAFT, VLT_LINE};\nstruct VerticalLevel\n{\n\tVerticalLevelType levelType;\n\tstd::vector<int> levelGroups, levelBlocks;\n\tint levelSizeX, levelSizeY, levelSizeZ;\n\tint maxRepeats;\n\tstd::string levelTerrain;\n\n\t// Default constructor\n\tVerticalLevel() :\n\t\tlevelType(VLT_MIDDLE), levelSizeX(1), levelSizeY(1), levelSizeZ(-1), maxRepeats(-1), levelTerrain(\"\")\n\t{\n\n\t}\n\n\t// Load in the data for a VerticalLevel from a YAML file, has to load similar data to a full mapscript command\n\tvoid load(const YAML::YamlNodeReader& reader)\n\t{\n\t\tstd::string type = reader[\"type\"].readVal<std::string>(\"\");\n\t\tif (type == \"ground\")\n\t\t{\n\t\t\tlevelType = VLT_GROUND;\n\t\t}\n\t\telse if (type == \"middle\")\n\t\t{\n\t\t\tlevelType = VLT_MIDDLE;\n\t\t}\n\t\telse if (type == \"ceiling\")\n\t\t{\n\t\t\tlevelType = VLT_CEILING;\n\t\t}\n\t\telse if (type == \"empty\")\n\t\t{\n\t\t\tlevelType = VLT_EMPTY;\n\t\t}\n\t\telse if (type == \"decoration\")\n\t\t{\n\t\t\tlevelType = VLT_DECORATION;\n\t\t\tlevelSizeZ = 0;\n\t\t}\n\t\telse if (type == \"craft\")\n\t\t{\n\t\t\tlevelType = VLT_CRAFT;\n\t\t}\n\t\telse if (type == \"line\")\n\t\t{\n\t\t\tlevelType = VLT_LINE;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tLog(LOG_WARNING) << \"'\" << type << \"'\" << \" does not resolve into a valid verticalLevel type, loading as 'middle'.\";\n\t\t\tlevelType = VLT_MIDDLE;\n\t\t}\n\n\t\tif (const auto& map = reader[\"size\"])\n\t\t{\n\t\t\tif (map.isSeq())\n\t\t\t{\n\t\t\t\tint *sizes[3] = {&levelSizeX, &levelSizeY, &levelSizeZ};\n\t\t\t\tint entry = 0;\n\t\t\t\tfor (const auto& size : map.children())\n\t\t\t\t{\n\t\t\t\t\t*sizes[entry] = size.readVal(1);\n\t\t\t\t\tentry++;\n\t\t\t\t\tif (entry == 3)\n\t\t\t\t\t{\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tmap.tryReadVal(levelSizeX);\n\t\t\t\tlevelSizeY = levelSizeX;\n\t\t\t}\n\t\t}\n\n\t\treader.tryRead(\"maxRepeats\", maxRepeats);\n\n\t\tif (const auto& map = reader[\"groups\"])\n\t\t{\n\t\t\tlevelGroups.clear();\n\t\t\tif (map.isSeq())\n\t\t\t{\n\t\t\t\tfor (const auto& group : map.children())\n\t\t\t\t{\n\t\t\t\t\tlevelGroups.push_back(group.readVal(0));\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tlevelGroups.push_back(map.readVal(0));\n\t\t\t}\n\t\t}\n\n\t\tif (const auto& map = reader[\"blocks\"])\n\t\t{\n\t\t\tlevelGroups.clear();\n\t\t\tif (map.isSeq())\n\t\t\t{\n\t\t\t\tfor (const auto& block : map.children())\n\t\t\t\t{\n\t\t\t\t\tlevelBlocks.push_back(block.readVal(0));\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tlevelBlocks.push_back(map.readVal(0));\n\t\t\t}\n\n\t\t}\n\n\t\treader.tryRead(\"terrain\", levelTerrain);\n\t}\n};\n\nclass MapScript\n{\nprivate:\n\tMapScriptCommand _type;\n\tbool _canBeSkipped, _markAsReinforcementsBlock;\n\tstd::vector<SDL_Rect*> _rects;\n\tstd::vector<int> _craftGroups;\n\tstd::vector<int> _groups, _blocks, _frequencies, _maxUses, _conditionals;\n\tint _verticalGroup, _horizontalGroup, _crossingGroup;\n\tstd::vector<int> _groupsTemp, _blocksTemp, _frequenciesTemp, _maxUsesTemp;\n\tint _sizeX, _sizeY, _sizeZ, _executionChances, _executions, _cumulativeFrequency, _label;\n\tMapDirection _direction;\n\tTunnelData *_tunnelData;\n\tstd::string _ufoName, _craftName;\n\tstd::vector<std::string> _randomTerrain;\n\tstd::vector<VerticalLevel> _verticalLevels;\n\n\t/// Randomly generate a group from within the array.\n\tint getGroupNumber();\n\t/// Randomly generate a block number from within the array.\n\tint getBlockNumber();\npublic:\n\tMapScript();\n\t~MapScript();\n\t/// Loads information from a ruleset file.\n\tvoid load(const YAML::YamlNodeReader& reader);\n\t/// Initializes all the variables and junk for a mapscript command.\n\tvoid init();\n\t/// Initializes the variables for a mapscript command from a VerticalLevel\n\tvoid initVerticalLevel(VerticalLevel level);\n\t/// Gets what type of command this is.\n\tMapScriptCommand getType() const {return _type;};\n\t/// Can this command be skipped if unsuccessful?\n\tbool canBeSkipped() const { return _canBeSkipped; };\n\t/// Should blocks added by this command be used as reinforcements blocks?\n\tbool markAsReinforcementsBlock() const { return _markAsReinforcementsBlock; }\n\t/// Gets the rects, describing the areas this command applies to.\n\tconst std::vector<SDL_Rect*> *getRects() const {return &_rects;};\n\t/// Gets the craft groups vector for iteration.\n\tconst std::vector<int>& getCraftGroups() const { return _craftGroups; };\n\t/// Gets the X size for this command.\n\tint getSizeX() const {return _sizeX;};\n\t/// Gets the Y size for this command.\n\tint getSizeY() const {return _sizeY;};\n\t/// Gets the Z size for this command.\n\tint getSizeZ() const {return _sizeZ;};\n\t/// Get the chances of this command executing.\n\tint getChancesOfExecution() const {return _executionChances;};\n\t/// Gets the label for this command.\n\tint getLabel() const {return _label;};\n\t/// Gets how many times this command repeats (1 repeat means 2 executions)\n\tint getExecutions() const {return _executions;};\n\t/// Gets what conditions apply to this command.\n\tconst std::vector<int> *getConditionals() const {return &_conditionals;};\n\t/// Gets the groups vector for iteration.\n\tconst std::vector<int> *getGroups() const {return &_groups;};\n\t/// Gets the blocks vector for iteration.\n\tconst std::vector<int> *getBlocks() const {return &_blocks;};\n\t/// Gets the verticalGroup for this command.\n\tint getVerticalGroup() const { return _verticalGroup; };\n\t/// Gets the horizontalGroup for this command.\n\tint getHorizontalGroup() const { return _horizontalGroup; };\n\t/// Gets the crossingGroup for this command.\n\tint getCrossingGroup() const { return _crossingGroup; };\n\t/// Gets the direction this command goes (for lines and tunnels).\n\tMapDirection getDirection() const {return _direction;};\n\t/// Gets the mcd replacement data for tunnel replacements.\n\tTunnelData *getTunnelData() {return _tunnelData;};\n\t/// Randomly generate a block from within either the array of groups or blocks.\n\tMapBlock *getNextBlock(RuleTerrain *terrain);\n\t/// Gets the UFO's name (for setUFO)\n\tstd::string getUFOName() const;\n\t/// Gets the craft's name (for addCraft)\n\tstd::string getCraftName();\n\t/// Gets the alternate terrain list for this command.\n\tconst std::vector<std::string> &getRandomAlternateTerrain() const;\n\t/// Gets the vertical levels for a command\n\tconst std::vector<VerticalLevel> &getVerticalLevels() const;\n\t/// Sets the vertical levels for a command from a base facility's vertical levels\n\tvoid setVerticalLevels(const std::vector<VerticalLevel> &verticalLevels, int sizeX, int sizeY);\n};\n\n}\n"
  },
  {
    "path": "src/Mod/Mod.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Mod.h\"\n#include \"ModScript.h\"\n#include <algorithm>\n#include <functional>\n#include <sstream>\n#include <climits>\n#include <cassert>\n#include \"../version.h\"\n#include \"../Engine/CrossPlatform.h\"\n#include \"../Engine/FileMap.h\"\n#include \"../Engine/Palette.h\"\n#include \"../Engine/Font.h\"\n#include \"../Engine/Surface.h\"\n#include \"../Engine/SurfaceSet.h\"\n#include \"../Engine/Music.h\"\n#include \"../Engine/GMCat.h\"\n#include \"../Engine/SoundSet.h\"\n#include \"../Engine/Sound.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"MapDataSet.h\"\n#include \"RuleMusic.h\"\n#include \"../Engine/ShaderDraw.h\"\n#include \"../Engine/ShaderMove.h\"\n#include \"../Engine/Exception.h\"\n#include \"../Engine/Logger.h\"\n#include \"../Engine/ScriptBind.h\"\n#include \"../Engine/Collections.h\"\n#include \"SoundDefinition.h\"\n#include \"ExtraSprites.h\"\n#include \"CustomPalettes.h\"\n#include \"ExtraSounds.h\"\n#include \"../Engine/AdlibMusic.h\"\n#include \"../Engine/CatFile.h\"\n#include \"../fmath.h\"\n#include \"../Engine/RNG.h\"\n#include \"../Engine/Options.h\"\n#include \"../Battlescape/Pathfinding.h\"\n#include \"RuleCountry.h\"\n#include \"RuleRegion.h\"\n#include \"RuleBaseFacility.h\"\n#include \"RuleCraft.h\"\n#include \"RuleCraftWeapon.h\"\n#include \"RuleItemCategory.h\"\n#include \"RuleItem.h\"\n#include \"RuleWeaponSet.h\"\n#include \"RuleUfo.h\"\n#include \"RuleTerrain.h\"\n#include \"MapScript.h\"\n#include \"RuleSoldier.h\"\n#include \"RuleSkill.h\"\n#include \"RuleCommendations.h\"\n#include \"AlienRace.h\"\n#include \"RuleEnviroEffects.h\"\n#include \"RuleStartingCondition.h\"\n#include \"AlienDeployment.h\"\n#include \"Armor.h\"\n#include \"ArticleDefinition.h\"\n#include \"RuleInventory.h\"\n#include \"RuleResearch.h\"\n#include \"RuleManufacture.h\"\n#include \"RuleManufactureShortcut.h\"\n#include \"ExtraStrings.h\"\n#include \"RuleInterface.h\"\n#include \"RuleArcScript.h\"\n#include \"RuleEventScript.h\"\n#include \"RuleEvent.h\"\n#include \"RuleMissionScript.h\"\n#include \"../Geoscape/Globe.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"../Savegame/Region.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/Country.h\"\n#include \"../Savegame/Soldier.h\"\n#include \"../Savegame/BattleUnit.h\"\n#include \"../Savegame/Craft.h\"\n#include \"../Savegame/CraftWeapon.h\"\n#include \"../Savegame/ItemContainer.h\"\n#include \"../Savegame/Transfer.h\"\n#include \"../Ufopaedia/Ufopaedia.h\"\n#include \"../Savegame/AlienStrategy.h\"\n#include \"../Savegame/GameTime.h\"\n#include \"../Savegame/SoldierDiary.h\"\n#include \"UfoTrajectory.h\"\n#include \"RuleAlienMission.h\"\n#include \"MCDPatch.h\"\n#include \"StatString.h\"\n#include \"RuleGlobe.h\"\n#include \"RuleVideo.h\"\n#include \"RuleConverter.h\"\n#include \"RuleSoldierTransformation.h\"\n#include \"RuleSoldierBonus.h\"\n\n#define ARRAYLEN(x) (std::size(x))\n\nnamespace OpenXcom\n{\n\nnamespace\n{\n\nstruct OxceVersionDate\n{\n\tint year = 0;\n\tint month = 0;\n\tint day = 0;\n\n\tOxceVersionDate(const std::string& data)\n\t{\n\t\tauto correct = false;\n\t\t// check if look like format \" (v2023-10-21)\"\n\t\tsize_t offset = data.find(\" (v\");\n\t\tif (offset != std::string::npos && data.size() >= offset + 14 && data[offset + 2] == 'v' && data[offset + 7] == '-' && data[offset + 10] == '-' && data[offset + 13] == ')')\n\t\t{\n\t\t\tcorrect = (std::sscanf(data.data() + offset, \" (v%4d-%2d-%2d)\", &year, &month, &day) == 3);\n\t\t}\n\n\t\tif (!correct)\n\t\t{\n\t\t\tyear = 0;\n\t\t\tmonth = 0;\n\t\t\tday = 0;\n\t\t}\n\t}\n\n\texplicit operator bool() const\n\t{\n\t\treturn year && month && day;\n\t}\n};\n\n\n} //namespace\n\n\nint Mod::DOOR_OPEN;\nint Mod::SLIDING_DOOR_OPEN;\nint Mod::SLIDING_DOOR_CLOSE;\nint Mod::SMALL_EXPLOSION;\nint Mod::LARGE_EXPLOSION;\nint Mod::EXPLOSION_OFFSET;\nint Mod::SMOKE_OFFSET;\nint Mod::UNDERWATER_SMOKE_OFFSET;\nint Mod::ITEM_DROP;\nint Mod::ITEM_THROW;\nint Mod::ITEM_RELOAD;\nint Mod::WALK_OFFSET;\nint Mod::FLYING_SOUND;\nint Mod::BUTTON_PRESS;\nint Mod::WINDOW_POPUP[3];\nint Mod::UFO_FIRE;\nint Mod::UFO_HIT;\nint Mod::UFO_CRASH;\nint Mod::UFO_EXPLODE;\nint Mod::INTERCEPTOR_HIT;\nint Mod::INTERCEPTOR_EXPLODE;\nint Mod::GEOSCAPE_CURSOR;\nint Mod::BASESCAPE_CURSOR;\nint Mod::BATTLESCAPE_CURSOR;\nint Mod::UFOPAEDIA_CURSOR;\nint Mod::GRAPHS_CURSOR;\nint Mod::DAMAGE_RANGE;\nint Mod::EXPLOSIVE_DAMAGE_RANGE;\nint Mod::FIRE_DAMAGE_RANGE[2];\nstd::string Mod::DEBRIEF_MUSIC_GOOD;\nstd::string Mod::DEBRIEF_MUSIC_BAD;\nint Mod::DIFFICULTY_COEFFICIENT[5];\nint Mod::SELL_PRICE_COEFFICIENT[5];\nint Mod::BUY_PRICE_COEFFICIENT[5];\nint Mod::DIFFICULTY_BASED_RETAL_DELAY[5];\nint Mod::UNIT_RESPONSE_SOUNDS_FREQUENCY[4];\nint Mod::PEDIA_FACILITY_RENDER_PARAMETERS[4];\nbool Mod::EXTENDED_ITEM_RELOAD_COST;\nbool Mod::EXTENDED_INVENTORY_SLOT_SORTING;\nbool Mod::EXTENDED_RUNNING_COST;\nint Mod::EXTENDED_MOVEMENT_COST_ROUNDING;\nbool Mod::EXTENDED_HWP_LOAD_ORDER;\nint Mod::EXTENDED_SPOT_ON_HIT_FOR_SNIPING;\nint Mod::EXTENDED_BERSERK_WITH_AIMED;\nint Mod::EXTENDED_MELEE_REACTIONS;\nint Mod::EXTENDED_TERRAIN_MELEE;\nint Mod::EXTENDED_UNDERWATER_THROW_FACTOR;\nbool Mod::EXTENDED_EXPERIENCE_AWARD_SYSTEM;\nbool Mod::EXTENDED_FORCE_SPAWN;\nint Mod::EXTENDED_SMOKE_OFFSET;\n\nextern std::string OXCE_CURRENCY_SYMBOL;\n\nconstexpr size_t MaxDifficultyLevels = 5;\n\n\n/// Special value for default string different to empty one.\nconst std::string Mod::STR_NULL = { '\\0' };\n/// Predefined name for first loaded mod that have all original data\nconst std::string ModNameMaster = \"master\";\n/// Predefined name for current mod that is loading rulesets.\nconst std::string ModNameCurrent = \"current\";\n\n/// Reduction of size allocated for transparency LUTs.\nconst size_t ModTransparencySizeReduction = 100;\n\nvoid Mod::resetGlobalStatics()\n{\n\tDOOR_OPEN = 3;\n\tSLIDING_DOOR_OPEN = 20;\n\tSLIDING_DOOR_CLOSE = 21;\n\tSMALL_EXPLOSION = 2;\n\tLARGE_EXPLOSION = 5;\n\tEXPLOSION_OFFSET = 0;\n\tSMOKE_OFFSET = 8;\n\tUNDERWATER_SMOKE_OFFSET = 0;\n\tITEM_DROP = 38;\n\tITEM_THROW = 39;\n\tITEM_RELOAD = 17;\n\tWALK_OFFSET = 22;\n\tFLYING_SOUND = 15;\n\tBUTTON_PRESS = 0;\n\tWINDOW_POPUP[0] = 1;\n\tWINDOW_POPUP[1] = 2;\n\tWINDOW_POPUP[2] = 3;\n\tUFO_FIRE = 8;\n\tUFO_HIT = 12;\n\tUFO_CRASH = 10;\n\tUFO_EXPLODE = 11;\n\tINTERCEPTOR_HIT = 10;\n\tINTERCEPTOR_EXPLODE = 13;\n\tGEOSCAPE_CURSOR = 252;\n\tBASESCAPE_CURSOR = 252;\n\tBATTLESCAPE_CURSOR = 144;\n\tUFOPAEDIA_CURSOR = 252;\n\tGRAPHS_CURSOR = 252;\n\tDAMAGE_RANGE = 100;\n\tEXPLOSIVE_DAMAGE_RANGE = 50;\n\tFIRE_DAMAGE_RANGE[0] = 5;\n\tFIRE_DAMAGE_RANGE[1] = 10;\n\tDEBRIEF_MUSIC_GOOD = \"GMMARS\";\n\tDEBRIEF_MUSIC_BAD = \"GMMARS\";\n\n\tGlobe::OCEAN_COLOR = Palette::blockOffset(12);\n\tGlobe::OCEAN_SHADING = true;\n\tGlobe::COUNTRY_LABEL_COLOR = 239;\n\tGlobe::LINE_COLOR = 162;\n\tGlobe::CITY_LABEL_COLOR = 138;\n\tGlobe::BASE_LABEL_COLOR = 133;\n\n\tTextButton::soundPress = 0;\n\n\tWindow::soundPopup[0] = 0;\n\tWindow::soundPopup[1] = 0;\n\tWindow::soundPopup[2] = 0;\n\n\tPathfinding::red = 3;\n\tPathfinding::yellow = 10;\n\tPathfinding::green = 4;\n\n\tDIFFICULTY_COEFFICIENT[0] = 0;\n\tDIFFICULTY_COEFFICIENT[1] = 1;\n\tDIFFICULTY_COEFFICIENT[2] = 2;\n\tDIFFICULTY_COEFFICIENT[3] = 3;\n\tDIFFICULTY_COEFFICIENT[4] = 4;\n\n\tSELL_PRICE_COEFFICIENT[0] = 100;\n\tSELL_PRICE_COEFFICIENT[1] = 100;\n\tSELL_PRICE_COEFFICIENT[2] = 100;\n\tSELL_PRICE_COEFFICIENT[3] = 100;\n\tSELL_PRICE_COEFFICIENT[4] = 100;\n\n\tBUY_PRICE_COEFFICIENT[0] = 100;\n\tBUY_PRICE_COEFFICIENT[1] = 100;\n\tBUY_PRICE_COEFFICIENT[2] = 100;\n\tBUY_PRICE_COEFFICIENT[3] = 100;\n\tBUY_PRICE_COEFFICIENT[4] = 100;\n\n\tDIFFICULTY_BASED_RETAL_DELAY[0] = 0;\n\tDIFFICULTY_BASED_RETAL_DELAY[1] = 0;\n\tDIFFICULTY_BASED_RETAL_DELAY[2] = 0;\n\tDIFFICULTY_BASED_RETAL_DELAY[3] = 0;\n\tDIFFICULTY_BASED_RETAL_DELAY[4] = 0;\n\n\tUNIT_RESPONSE_SOUNDS_FREQUENCY[0] = 100; // select unit\n\tUNIT_RESPONSE_SOUNDS_FREQUENCY[1] = 100; // start moving\n\tUNIT_RESPONSE_SOUNDS_FREQUENCY[2] = 100; // select weapon\n\tUNIT_RESPONSE_SOUNDS_FREQUENCY[3] = 20;  // annoyed\n\n\tPEDIA_FACILITY_RENDER_PARAMETERS[0] = 2; // pedia facility max width\n\tPEDIA_FACILITY_RENDER_PARAMETERS[1] = 2; // pedia facility max height\n\tPEDIA_FACILITY_RENDER_PARAMETERS[2] = 0; // pedia facility X offset\n\tPEDIA_FACILITY_RENDER_PARAMETERS[3] = 0; // pedia facility Y offset\n\n\tEXTENDED_ITEM_RELOAD_COST = false;\n\tEXTENDED_INVENTORY_SLOT_SORTING = false;\n\tEXTENDED_RUNNING_COST = false;\n\tEXTENDED_MOVEMENT_COST_ROUNDING = 0;\n\tEXTENDED_HWP_LOAD_ORDER = false;\n\tEXTENDED_SPOT_ON_HIT_FOR_SNIPING = 0;\n\tEXTENDED_BERSERK_WITH_AIMED = 0;\n\tEXTENDED_MELEE_REACTIONS = 0;\n\tEXTENDED_TERRAIN_MELEE = 0;\n\tEXTENDED_UNDERWATER_THROW_FACTOR = 0;\n\tEXTENDED_EXPERIENCE_AWARD_SYSTEM = false;\n\tEXTENDED_FORCE_SPAWN = false;\n\tEXTENDED_SMOKE_OFFSET = 0;\n\n\tOXCE_CURRENCY_SYMBOL = \"$\";\n}\n\n/**\n * Detail\n */\nclass ModScriptGlobal : public ScriptGlobal\n{\n\tsize_t _modCurr = 0;\n\tstd::vector<std::pair<std::string, int>> _modNames;\n\tScriptValues<Mod> _scriptValues;\n\n\tvoid loadRuleList(int &value, const YAML::YamlNodeReader& reader) const\n\t{\n\t\tif (reader)\n\t\t{\n\t\t\tauto name = reader.readVal<std::string>();\n\t\t\tif (name == ModNameMaster)\n\t\t\t{\n\t\t\t\tvalue = 0;\n\t\t\t}\n\t\t\telse if (name == ModNameCurrent)\n\t\t\t{\n\t\t\t\tvalue = _modCurr;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tfor (const auto& p : _modNames)\n\t\t\t\t{\n\t\t\t\t\tif (name == p.first)\n\t\t\t\t\t{\n\t\t\t\t\t\tvalue = p.second;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tvalue = -1;\n\t\t\t}\n\t\t}\n\t}\n\tvoid saveRuleList(const int &value, YAML::YamlNodeWriter& writer) const\n\t{\n\t\tfor (const auto& p : _modNames)\n\t\t{\n\t\t\tif (value == p.second)\n\t\t\t{\n\t\t\t\twriter.setValue(p.first);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\npublic:\n\t/// Initialize shared globals like types.\n\tvoid initParserGlobals(ScriptParserBase* parser) override\n\t{\n\t\tparser->registerPointerType<Mod>();\n\t\tparser->registerPointerType<SavedGame>();\n\t\tparser->registerPointerType<SavedBattleGame>();\n\t}\n\n\t/// Prepare for loading data.\n\tvoid beginLoad() override\n\t{\n\t\tScriptGlobal::beginLoad();\n\n\t\taddTagValueType<ModScriptGlobal, &ModScriptGlobal::loadRuleList, &ModScriptGlobal::saveRuleList>(\"RuleList\");\n\t\taddConst(\"RuleList.\" + ModNameMaster, (int)0);\n\t\taddConst(\"RuleList.\" + ModNameCurrent, (int)0);\n\n\t\tauto v = OxceVersionDate(OPENXCOM_VERSION_GIT);\n\t\taddConst(\"SCRIPT_VERSION_DATE\", (int)(v.year * 10000 + v.month * 100 + v.day));\n\t}\n\t/// Finishing loading data.\n\tvoid endLoad() override\n\t{\n\t\tScriptGlobal::endLoad();\n\t}\n\n\t/// Add mod name and id.\n\tvoid addMod(const std::string& s, int i)\n\t{\n\t\tauto name = \"RuleList.\" + s;\n\t\taddConst(name, (int)i);\n\t\t_modNames.push_back(std::make_pair(s, i));\n\t}\n\t/// Set current mod id.\n\tvoid setMod(int i)\n\t{\n\t\tupdateConst(\"RuleList.\" + ModNameCurrent, (int)i);\n\t\t_modCurr = i;\n\t}\n\n\t/// Get script values\n\tScriptValues<Mod>& getScriptValues() { return _scriptValues; }\n};\n\n/**\n * Creates an empty mod.\n */\nMod::Mod() :\n\t_inventoryOverlapsPaperdoll(false),\n\t_maxViewDistance(20), _maxDarknessToSeeUnits(9), _maxStaticLightDistance(16), _maxDynamicLightDistance(24), _enhancedLighting(0),\n\t_costHireEngineer(0), _costHireScientist(0),\n\t_costEngineer(0), _costScientist(0), _timePersonnel(0), _hireByCountryOdds(0), _hireByRegionOdds(0), _initialFunding(0),\n\t_globalTransferCostMult(1), _globalTransferCostDiv(1),\n\t_aiUseDelayBlaster(3), _aiUseDelayFirearm(0), _aiUseDelayGrenade(3), _aiUseDelayProxy(999), _aiUseDelayMelee(0), _aiUseDelayPsionic(0), _aiUseDelayMedikit(999),\n\t_aiFireChoiceIntelCoeff(5), _aiFireChoiceAggroCoeff(5), _aiExtendedFireModeChoice(false), _aiRespectMaxRange(false), _aiDestroyBaseFacilities(false),\n\t_aiPickUpWeaponsMoreActively(false), _aiPickUpWeaponsMoreActivelyCiv(false),\n\t_aiReactionFireThreshold(0), _aiReactionFireThresholdCiv(0),\n\t_maxLookVariant(0), _tooMuchSmokeThreshold(10), _customTrainingFactor(100),\n\t_chanceToStopRetaliation(0), _chanceToDetectAlienBaseEachMonth(20), _lessAliensDuringBaseDefense(false),\n\t_allowCountriesToCancelAlienPact(false), _buildInfiltrationBaseCloseToTheCountry(false), _infiltrateRandomCountryInTheRegion(false), _allowAlienBasesOnWrongTextures(true),\n\t_kneelBonusGlobal(115), _oneHandedPenaltyGlobal(80),\n\t_enableCloseQuartersCombat(0), _closeQuartersAccuracyGlobal(100), _closeQuartersTuCostGlobal(12), _closeQuartersEnergyCostGlobal(8), _closeQuartersSneakUpGlobal(0),\n\t_noLOSAccuracyPenaltyGlobal(-1),\n\t_explodeInventoryGlobal(0),\n\t_surrenderMode(0),\n\t_bughuntMinTurn(999), _bughuntMaxEnemies(2), _bughuntRank(0), _bughuntLowMorale(40), _bughuntTimeUnitsLeft(60),\n\t_manaEnabled(false), _manaBattleUI(false), _manaTrainingPrimary(false), _manaTrainingSecondary(false), _manaReplenishAfterMission(true),\n\t_loseMoney(\"loseGame\"), _loseRating(\"loseGame\"), _loseDefeat(\"loseGame\"),\n\t_ufoGlancingHitThreshold(0), _ufoBeamWidthParameter(1000),\n\t_escortRange(20), _drawEnemyRadarCircles(1), _escortsJoinFightAgainstHK(true), _hunterKillerFastRetarget(true),\n\t_crewEmergencyEvacuationSurvivalChance(100), _pilotsEmergencyEvacuationSurvivalChance(100),\n\t_showUfoPreviewInBaseDefense(false),\n\t_soldiersPerRank({-1, -1, 5, 11, 23, 30}),\n\t_pilotAccuracyZeroPoint(55), _pilotAccuracyRange(40), _pilotReactionsZeroPoint(55), _pilotReactionsRange(60),\n\t_performanceBonusFactor(0.0), _enableNewResearchSorting(false), _displayCustomCategories(0), _shareAmmoCategories(false), _showDogfightDistanceInKm(false), _showFullNameInAlienInventory(false),\n\t_alienInventoryOffsetX(80), _alienInventoryOffsetBigUnit(32),\n\t_hidePediaInfoButton(false), _extraNerdyPediaInfoType(0),\n\t_giveScoreAlsoForResearchedArtifacts(false), _statisticalBulletConservation(false), _stunningImprovesMorale(false),\n\t_tuRecoveryWakeUpNewTurn(100), _shortRadarRange(0), _buildTimeReductionScaling(100),\n\t_defeatScore(0), _defeatFunds(0), _difficultyDemigod(false), _startingTime(6, 1, 1, 1999, 12, 0, 0), _startingDifficulty(0),\n\t_baseDefenseMapFromLocation(0), _disableUnderwaterSounds(false), _enableUnitResponseSounds(false), _pediaReplaceCraftFuelWithRangeType(-1),\n\t_facilityListOrder(0), _craftListOrder(0), _itemCategoryListOrder(0), _itemListOrder(0), _armorListOrder(0), _alienRaceListOrder(0),\n\t_researchListOrder(0),  _manufactureListOrder(0), _soldierBonusListOrder(0), _transformationListOrder(0), _ufopaediaListOrder(0), _invListOrder(0), _soldierListOrder(0),\n\t_modCurrent(0), _statePalette(0)\n{\n\t_muteMusic = new Music();\n\t_muteSound = new Sound();\n\t_globe = new RuleGlobe();\n\t_scriptGlobal = new ModScriptGlobal();\n\n\t//load base damage types\n\tRuleDamageType *dmg;\n\t_damageTypes.resize(DAMAGE_TYPES);\n\n\tdmg = new RuleDamageType();\n\tdmg->ResistType = DT_NONE;\n\tdmg->RandomType = DRT_NONE;\n\t_damageTypes[dmg->ResistType] = dmg;\n\n\tdmg = new RuleDamageType();\n\tdmg->ResistType = DT_AP;\n\tdmg->IgnoreOverKill = true;\n\t_damageTypes[dmg->ResistType] = dmg;\n\n\tdmg = new RuleDamageType();\n\tdmg->ResistType = DT_ACID;\n\tdmg->IgnoreOverKill = true;\n\t_damageTypes[dmg->ResistType] = dmg;\n\n\tdmg = new RuleDamageType();\n\tdmg->ResistType = DT_LASER;\n\tdmg->IgnoreOverKill = true;\n\t_damageTypes[dmg->ResistType] = dmg;\n\n\tdmg = new RuleDamageType();\n\tdmg->ResistType = DT_PLASMA;\n\tdmg->IgnoreOverKill = true;\n\t_damageTypes[dmg->ResistType] = dmg;\n\n\tdmg = new RuleDamageType();\n\tdmg->ResistType = DT_MELEE;\n\tdmg->IgnoreOverKill = true;\n\tdmg->IgnoreSelfDestruct = true;\n\t_damageTypes[dmg->ResistType] = dmg;\n\n\tdmg = new RuleDamageType();\n\tdmg->ResistType = DT_STUN;\n\tdmg->FixRadius = -1;\n\tdmg->IgnoreOverKill = true;\n\tdmg->IgnoreSelfDestruct = true;\n\tdmg->IgnorePainImmunity = true;\n\tdmg->RadiusEffectiveness = 0.05f;\n\tdmg->ToHealth = 0.0f;\n\tdmg->ToArmor = 0.0f;\n\tdmg->ToWound = 0.0f;\n\tdmg->ToItem = 0.0f;\n\tdmg->ToTile = 0.0f;\n\tdmg->ToStun = 1.0f;\n\tdmg->RandomStun = false;\n\tdmg->TileDamageMethod = 2;\n\t_damageTypes[dmg->ResistType] = dmg;\n\n\tdmg = new RuleDamageType();\n\tdmg->ResistType = DT_HE;\n\tdmg->RandomType = DRT_EXPLOSION;\n\tdmg->FixRadius = -1;\n\tdmg->IgnoreOverKill = true;\n\tdmg->IgnoreSelfDestruct = true;\n\tdmg->RadiusEffectiveness = 0.05f;\n\tdmg->ToItem = 1.0f;\n\tdmg->TileDamageMethod = 2;\n\t_damageTypes[dmg->ResistType] = dmg;\n\n\tdmg = new RuleDamageType();\n\tdmg->ResistType = DT_SMOKE;\n\tdmg->RandomType = DRT_NONE;\n\tdmg->FixRadius = -1;\n\tdmg->IgnoreOverKill = true;\n\tdmg->IgnoreDirection = true;\n\tdmg->ArmorEffectiveness = 0.0f;\n\tdmg->RadiusEffectiveness = 0.05f;\n\tdmg->SmokeThreshold = 0;\n\tdmg->ToHealth = 0.0f;\n\tdmg->ToArmor = 0.0f;\n\tdmg->ToWound = 0.0f;\n\tdmg->ToItem = 0.0f;\n\tdmg->ToTile = 0.0f;\n\tdmg->ToStun = 1.0f;\n\tdmg->TileDamageMethod = 2;\n\t_damageTypes[dmg->ResistType] = dmg;\n\n\tdmg = new RuleDamageType();\n\tdmg->ResistType = DT_IN;\n\tdmg->RandomType = DRT_FIRE;\n\tdmg->FixRadius = -1;\n\tdmg->FireBlastCalc = true;\n\tdmg->IgnoreOverKill = true;\n\tdmg->IgnoreDirection = true;\n\tdmg->IgnoreSelfDestruct = true;\n\tdmg->ArmorEffectiveness = 0.0f;\n\tdmg->RadiusEffectiveness = 0.03f;\n\tdmg->FireThreshold = 0;\n\tdmg->ToHealth = 1.0f;\n\tdmg->ToArmor = 0.0f;\n\tdmg->ToWound = 0.0f;\n\tdmg->ToItem = 0.0f;\n\tdmg->ToTile = 0.0f;\n\tdmg->ToStun = 0.0f;\n\tdmg->TileDamageMethod = 2;\n\t_damageTypes[dmg->ResistType] = dmg;\n\n\tfor (int itd = DT_10; itd < DAMAGE_TYPES; ++itd)\n\t{\n\t\tdmg = new RuleDamageType();\n\t\tdmg->ResistType = static_cast<ItemDamageType>(itd);\n\t\tdmg->IgnoreOverKill = true;\n\t\t_damageTypes[dmg->ResistType] = dmg;\n\t}\n\n\t_converter = new RuleConverter();\n\t_statAdjustment.resize(MaxDifficultyLevels);\n\t_statAdjustment[0].aimMultiplier = 0.5;\n\t_statAdjustment[0].armorMultiplier = 0.5;\n\t_statAdjustment[0].armorMultiplierAbs = 0;\n\t_statAdjustment[0].growthMultiplier = 0;\n\tfor (size_t i = 1; i != MaxDifficultyLevels; ++i)\n\t{\n\t\t_statAdjustment[i].aimMultiplier = 1.0;\n\t\t_statAdjustment[i].armorMultiplier = 1.0;\n\t\t_statAdjustment[i].armorMultiplierAbs = 0;\n\t\t_statAdjustment[i].growthMultiplier = (int)i;\n\t}\n\n\t// Setting default value for array\n\t_ufoTractorBeamSizeModifiers[0] = 400;\n\t_ufoTractorBeamSizeModifiers[1] = 200;\n\t_ufoTractorBeamSizeModifiers[2] = 100;\n\t_ufoTractorBeamSizeModifiers[3] = 50;\n\t_ufoTractorBeamSizeModifiers[4] = 25;\n\n\t_pilotBraveryThresholds[0] = 90;\n\t_pilotBraveryThresholds[1] = 80;\n\t_pilotBraveryThresholds[2] = 30;\n}\n\n/**\n * Deletes all the mod data from memory.\n */\nMod::~Mod()\n{\n\tdelete _muteMusic;\n\tdelete _muteSound;\n\tdelete _globe;\n\tdelete _converter;\n\tdelete _scriptGlobal;\n\tfor (auto& pair : _fonts)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _surfaces)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _sets)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _palettes)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _musics)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _sounds)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto* rdt : _damageTypes)\n\t{\n\t\tdelete rdt;\n\t}\n\tfor (auto& pair : _countries)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _extraGlobeLabels)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _regions)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _facilities)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _crafts)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _craftWeapons)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _itemCategories)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _items)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _weaponSets)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _ufos)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _terrains)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _mapDataSets)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _soldiers)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _skills)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _units)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _alienRaces)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _enviroEffects)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _startingConditions)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _alienDeployments)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _armors)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _ufopaediaArticles)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _invs)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _research)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _manufacture)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _manufactureShortcut)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _soldierBonus)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _soldierTransformation)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _ufoTrajectories)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _alienMissions)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _MCDPatches)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _extraSprites)\n\t{\n\t\tfor (auto* extraSprites : pair.second)\n\t\t{\n\t\t\tdelete extraSprites;\n\t\t}\n\t}\n\tfor (auto& pair : _customPalettes)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _extraSounds)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _extraStrings)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _interfaces)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _mapScripts)\n\t{\n\t\tfor (auto* mapScript : pair.second)\n\t\t{\n\t\t\tdelete mapScript;\n\t\t}\n\t}\n\tfor (auto& pair : _videos)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _musicDefs)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _arcScripts)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _eventScripts)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _events)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _missionScripts)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _adhocScripts)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _soundDefs)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto* statString : _statStrings)\n\t{\n\t\tdelete statString;\n\t}\n\tfor (auto& pair : _commendations)\n\t{\n\t\tdelete pair.second;\n\t}\n}\n\n/**\n * Gets a specific rule element by ID.\n * @param id String ID of the rule element.\n * @param name Human-readable name of the rule type.\n * @param map Map associated to the rule type.\n * @param error Throw an error if not found.\n * @return Pointer to the rule element, or NULL if not found.\n */\ntemplate <typename T>\nT *Mod::getRule(const std::string &id, const std::string &name, const std::map<std::string, T*> &map, bool error) const\n{\n\tif (isEmptyRuleName(id))\n\t{\n\t\treturn 0;\n\t}\n\ttypename std::map<std::string, T*>::const_iterator i = map.find(id);\n\tif (i != map.end() && i->second != 0)\n\t{\n\t\treturn i->second;\n\t}\n\telse\n\t{\n\t\tif (error)\n\t\t{\n\t\t\tthrow Exception(name + \" \" + id + \" not found\");\n\t\t}\n\t\treturn 0;\n\t}\n}\n\n/**\n * Returns a specific font from the mod.\n * @param name Name of the font.\n * @return Pointer to the font.\n */\nFont *Mod::getFont(const std::string &name, bool error) const\n{\n\treturn getRule(name, \"Font\", _fonts, error);\n}\n\n/**\n * Loads any extra sprites associated to a surface when\n * it's first requested.\n * @param name Surface name.\n */\nvoid Mod::lazyLoadSurface(const std::string &name)\n{\n\tif (Options::lazyLoadResources)\n\t{\n\t\tauto i = _extraSprites.find(name);\n\t\tif (i != _extraSprites.end())\n\t\t{\n\t\t\tfor (auto* extraSprites : i->second)\n\t\t\t{\n\t\t\t\tloadExtraSprite(extraSprites);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Returns a specific surface from the mod.\n * @param name Name of the surface.\n * @return Pointer to the surface.\n */\nSurface *Mod::getSurface(const std::string &name, bool error)\n{\n\tlazyLoadSurface(name);\n\treturn getRule(name, \"Sprite\", _surfaces, error);\n}\n\n/**\n * Returns a specific surface set from the mod.\n * @param name Name of the surface set.\n * @return Pointer to the surface set.\n */\nSurfaceSet *Mod::getSurfaceSet(const std::string &name, bool error)\n{\n\tlazyLoadSurface(name);\n\treturn getRule(name, \"Sprite Set\", _sets, error);\n}\n\n/**\n * Returns a specific music from the mod.\n * @param name Name of the music.\n * @return Pointer to the music.\n */\nMusic *Mod::getMusic(const std::string &name, bool error) const\n{\n\tif (Options::mute)\n\t{\n\t\treturn _muteMusic;\n\t}\n\telse\n\t{\n\t\treturn getRule(name, \"Music\", _musics, error);\n\t}\n}\n\n/**\n * Returns the list of all music tracks\n * provided by the mod.\n * @return List of music tracks.\n */\nconst std::map<std::string, Music*> &Mod::getMusicTrackList() const\n{\n\treturn _musics;\n}\n\n/**\n * Returns a random music from the mod.\n * @param name Name of the music to pick from.\n * @return Pointer to the music.\n */\nMusic *Mod::getRandomMusic(const std::string &name) const\n{\n\tif (Options::mute)\n\t{\n\t\treturn _muteMusic;\n\t}\n\telse\n\t{\n\t\tstd::vector<Music*> music;\n\t\tfor (auto& pair : _musics)\n\t\t{\n\t\t\tif (pair.first.find(name) != std::string::npos)\n\t\t\t{\n\t\t\t\tmusic.push_back(pair.second);\n\t\t\t}\n\t\t}\n\t\tif (music.empty())\n\t\t{\n\t\t\treturn _muteMusic;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn music[RNG::seedless(0, music.size() - 1)];\n\t\t}\n\t}\n}\n\n/**\n * Plays the specified track if it's not already playing.\n * @param name Name of the music.\n * @param id Id of the music, 0 for random.\n */\nvoid Mod::playMusic(const std::string &name, int id)\n{\n\tif (!Options::mute && _playingMusic != name)\n\t{\n\t\tint loop = -1;\n\t\t// hacks\n\t\tif (!Options::musicAlwaysLoop && (name == \"GMSTORY\" || name == \"GMWIN\" || name == \"GMLOSE\"))\n\t\t{\n\t\t\tloop = 0;\n\t\t}\n\n\t\tMusic *music = 0;\n\t\tif (id == 0)\n\t\t{\n\t\t\tmusic = getRandomMusic(name);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tstd::ostringstream ss;\n\t\t\tss << name << id;\n\t\t\tmusic = getMusic(ss.str());\n\t\t}\n\t\tmusic->play(loop);\n\t\tif (music != _muteMusic)\n\t\t{\n\t\t\t_playingMusic = name;\n\t\t\tfor (auto& item : _musics)\n\t\t\t{\n\t\t\t\tif (item.second == music)\n\t\t\t\t{\n\t\t\t\t\tsetCurrentMusicTrack(item.first);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tLog(LOG_VERBOSE)<<\"Mod::playMusic('\" << name << \"'): playing \" << _playingMusic;\n\t}\n}\n\n/**\n * Returns a specific sound set from the mod.\n * @param name Name of the sound set.\n * @return Pointer to the sound set.\n */\nSoundSet *Mod::getSoundSet(const std::string &name, bool error) const\n{\n\treturn getRule(name, \"Sound Set\", _sounds, error);\n}\n\n/**\n * Returns a specific sound from the mod.\n * @param set Name of the sound set.\n * @param sound ID of the sound.\n * @return Pointer to the sound.\n */\nSound *Mod::getSound(const std::string &set, int sound) const\n{\n\tif (Options::mute)\n\t{\n\t\treturn _muteSound;\n\t}\n\telse\n\t{\n\t\tSoundSet *ss = getSoundSet(set, false);\n\t\tif (ss != 0)\n\t\t{\n\t\t\tSound *s = ss->getSound(sound);\n\t\t\tif (s == 0)\n\t\t\t{\n\t\t\t\tLog(LOG_ERROR) << \"Sound \" << sound << \" in \" << set << \" not found\";\n\t\t\t\treturn _muteSound;\n\t\t\t}\n\t\t\treturn s;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"SoundSet \" << set << \" not found\";\n\t\t\treturn _muteSound;\n\t\t}\n\t}\n}\n\n/**\n * Returns a specific palette from the mod.\n * @param name Name of the palette.\n * @return Pointer to the palette.\n */\nPalette *Mod::getPalette(const std::string &name, bool error) const\n{\n\treturn getRule(name, \"Palette\", _palettes, error);\n}\n\n/**\n * Returns the list of voxeldata in the mod.\n * @return Pointer to the list of voxeldata.\n */\nconst std::vector<Uint16> *Mod::getVoxelData() const\n{\n\treturn &_voxelData;\n}\n\n/**\n * Returns a specific sound from either the land or underwater sound set.\n * @param depth the depth of the battlescape.\n * @param sound ID of the sound.\n * @return Pointer to the sound.\n */\nSound *Mod::getSoundByDepth(unsigned int depth, unsigned int sound) const\n{\n\tif (depth == 0 || _disableUnderwaterSounds)\n\t\treturn getSound(\"BATTLE.CAT\", sound);\n\telse\n\t\treturn getSound(\"BATTLE2.CAT\", sound);\n}\n\n/**\n * Returns the list of color LUTs in the mod.\n * @return Pointer to the list of LUTs.\n */\nconst std::vector<std::vector<Uint8> > *Mod::getLUTs() const\n{\n\treturn &_transparencyLUTs;\n}\n\n\n/**\n * Check for obsolete error based on year.\n * @param year Year when given function stop be available.\n * @return True if code still should run.\n */\nbool Mod::checkForObsoleteErrorByYear(const std::string &parent, const YAML::YamlNodeReader& reader, const std::string &error, int year) const\n{\n\tSeverityLevel level = LOG_INFO;\n\tbool r = true;\n\n\tconst static OxceVersionDate currYear = { OPENXCOM_VERSION_GIT };\n\tif (currYear)\n\t{\n\t\tif (currYear.year < year)\n\t\t{\n\t\t\tlevel = LOG_INFO;\n\t\t}\n\t\telse // after obsolete year functionality is disabled\n\t\t{\n\t\t\tlevel = LOG_FATAL;\n\t\t\tr = false;\n\t\t}\n\t}\n\tcheckForSoftError(true, parent, reader, \"Obsolete (to removed after year \" + std::to_string(year) + \") operation \" + error, level);\n\n\treturn r;\n}\n\n\n/**\n * Check for error that we can ignore by user request.\n */\nbool Mod::checkForSoftError(bool check, const std::string& parent, const YAML::YamlNodeReader& reader, const std::string& error, SeverityLevel level) const\n{\n\tif (check)\n\t{\n\t\tauto ex = LoadRuleException(parent, reader, error);\n\t\tif (Options::oxceModValidationLevel < level && level != LOG_FATAL)\n\t\t{\n\t\t\tLog(level) << _scriptGlobal->getCurrentFile() << \": Suppressed \" << ex.what();\n\t\t\treturn true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tthrow ex;\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Check for error that we can ignore by user request.\n */\nbool Mod::checkForSoftError(bool check, const std::string &parent, const std::string &error, SeverityLevel level) const\n{\n\tif (check)\n\t{\n\t\tauto ex = LoadRuleException(parent, error);\n\t\tif (Options::oxceModValidationLevel < level && level != LOG_FATAL)\n\t\t{\n\t\t\tLog(level) << _scriptGlobal->getCurrentFile() << \": Suppressed \" << ex.what();\n\t\t\treturn true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tthrow ex;\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Verify if value have defined surface in given set.\n */\nvoid Mod::verifySpriteOffset(const std::string &parent, const int& sprite, const std::string &set) const\n{\n\tif (Options::lazyLoadResources)\n\t{\n\t\t// we can't check if index is correct when set is loaded\n\t\treturn;\n\t}\n\n\tauto* s = getRule(set, \"Sprite Set\", _sets, true);\n\n\tif (s->getTotalFrames() == 0)\n\t{\n\t\t// HACK: some sprites should be shared between different sets (for example 'Projectiles' and 'UnderwaterProjectiles'),\n\t\t// but in some cases one set is not used (for example if the weapon is 'underwaterOnly: true').\n\t\t// If there are no surfaces at all, this means this index is not used.\n\t\t// In some corner cases it will not work correcty, for example if someone does not add any surface to the set at all.\n\t\treturn;\n\t}\n\n\tcheckForSoftError(\n\t\tsprite != Mod::NO_SURFACE && s->getFrame(sprite) == nullptr,\n\t\tparent,\n\t\t\"Wrong index \" + std::to_string(sprite) + \" for surface set \" + set + \" (please note that the index in the ruleset is smaller, by several thousands)\",\n\t\tLOG_ERROR\n\t);\n}\n\n/**\n * Verify if value have defined surface in given set.\n */\nvoid Mod::verifySpriteOffset(const std::string &parent, const std::vector<int>& sprites, const std::string &set) const\n{\n\tif (Options::lazyLoadResources)\n\t{\n\t\t// we can't check if index is correct when set is loaded\n\t\treturn;\n\t}\n\n\tauto* s = getRule(set, \"Sprite Set\", _sets, true);\n\n\tif (s->getTotalFrames() == 0)\n\t{\n\t\t// HACK: some sprites should be shared between different sets (for example 'Projectiles' and 'UnderwaterProjectiles'),\n\t\t// but in some cases one set is not used (for example if the weapon is 'underwaterOnly: true').\n\t\t// If there are no surfaces at all, this means this index is not used.\n\t\t// In some corner cases it will not work correcty, for example if someone does not add any surface to the set at all.\n\t\treturn;\n\t}\n\n\tfor (int sprite : sprites)\n\t{\n\t\tcheckForSoftError(\n\t\t\tsprite != Mod::NO_SURFACE && s->getFrame(sprite) == nullptr,\n\t\t\tparent,\n\t\t\t\"Wrong index \" + std::to_string(sprite) + \" for surface set \" + set + \" (please note that the index in the ruleset is smaller, by several thousands)\",\n\t\t\tLOG_ERROR\n\t\t);\n\t}\n}\n\n/**\n * Verify if value have defined sound in given set.\n */\nvoid Mod::verifySoundOffset(const std::string &parent, const int& sound, const std::string &set) const\n{\n\tif (Options::mute)\n\t{\n\t\t// when mute is set not sound data is loaded and we can't check for correct data\n\t\treturn;\n\t}\n\n\tauto* s = getSoundSet(set);\n\n\tcheckForSoftError(\n\t\tsound != Mod::NO_SOUND && s->getSound(sound) == nullptr,\n\t\tparent,\n\t\t\"Wrong index \" + std::to_string(sound) + \" for sound set \" + set + \" (please note that the index in the ruleset is smaller, by several thousands)\",\n\t\tLOG_ERROR\n\t);\n}\n\n/**\n * Verify if value have defined sound in given set.\n */\nvoid Mod::verifySoundOffset(const std::string &parent, const std::vector<int>& sounds, const std::string &set) const\n{\n\tif (Options::mute)\n\t{\n\t\t// when mute is set not sound data is loaded and we can't check for correct data\n\t\treturn;\n\t}\n\n\tauto* s = getSoundSet(set);\n\n\tfor (int sound : sounds)\n\t{\n\t\tcheckForSoftError(\n\t\t\tsound != Mod::NO_SOUND && s->getSound(sound) == nullptr,\n\t\t\tparent,\n\t\t\t\"Wrong index \" + std::to_string(sound) + \" for sound set \" + set + \" (please note that the index in the ruleset is smaller, by several thousands)\",\n\t\t\tLOG_ERROR\n\t\t);\n\t}\n}\n\n\n/**\n * Returns the current mod-based offset for resources.\n * @return Mod offset.\n */\nint Mod::getModOffset() const\n{\n\treturn _modCurrent->offset;\n}\n\n\n\nnamespace\n{\n\nconst std::string InfoTag = \"!info\";\nconst std::string AddTag = \"!add\";\nconst std::string RemoveTag = \"!remove\";\n\nbool isListHelper(const YAML::YamlNodeReader& reader)\n{\n\treturn reader.isSeq() && (!reader.hasValTag() || reader.hasValTag(ryml::TAG_SEQ) || reader.hasValTag(InfoTag));\n}\n\nbool isListAddTagHelper(const YAML::YamlNodeReader& reader)\n{\n\treturn reader.isSeq() && reader.hasValTag(AddTag);\n}\n\nbool isListRemoveTagHelper(const YAML::YamlNodeReader& reader)\n{\n\treturn reader.isSeq() && reader.hasValTag(RemoveTag);\n}\n\nbool isMapHelper(const YAML::YamlNodeReader& reader)\n{\n\treturn reader.isMap() && (!reader.hasValTag() || reader.hasValTag(ryml::TAG_SEQ) || reader.hasValTag(InfoTag));\n}\n\nbool isMapAddTagHelper(const YAML::YamlNodeReader& reader)\n{\n\treturn reader.isMap() && reader.hasValTag(AddTag);\n}\n\nvoid throwOnBadListHelper(const std::string &parent, const YAML::YamlNodeReader& reader)\n{\n\tstd::ostringstream err;\n\tif (reader.isSeq())\n\t{\n\t\t// it is a sequence, but it could not be loaded... this means the tag is not supported\n\t\terr << \"unsupported node tag '\" << reader.getValTag() << \"'\";\n\t}\n\telse\n\t{\n\t\terr << \"wrong node type, expected a list\";\n\t}\n\tthrow LoadRuleException(parent, reader, err.str());\n}\n\nvoid throwOnBadMapHelper(const std::string &parent, const YAML::YamlNodeReader& reader)\n{\n\tstd::ostringstream err;\n\tif (reader.isMap())\n\t{\n\t\t// it is a map, but it could not be loaded... this means the tag is not supported\n\t\terr << \"unsupported node tag '\" << reader.getValTag() << \"'\";\n\t}\n\telse\n\t{\n\t\terr << \"wrong node type, expected a map\";\n\t}\n\tthrow LoadRuleException(parent, reader, err.str());\n}\n\ntemplate<typename... T>\nvoid showInfo(const std::string &parent, const YAML::YamlNodeReader& reader, T... names)\n{\n\tif (reader.hasValTag(InfoTag))\n\t{\n\t\tLogger info;\n\t\tinfo.get() << \"Options available for \" << parent << \" at line \" << reader.getLocationInFile().line << \" are: \";\n\t\t((info.get() << \" \" << names), ...);\n\t}\n}\n\n\n\n/**\n * Tag dispatch struct representing normal load logic.\n */\nstruct LoadFuncStandard\n{\n\tauto funcTagForNew() -> LoadFuncStandard { return { }; }\n};\n\n/**\n * Tag dispatch struct representing special function that allows adding and removing elements.\n */\nstruct LoadFuncEditable\n{\n\tauto funcTagForNew() -> LoadFuncStandard { return { }; }\n};\n\n/**\n * Tag dispatch struct representing can have null value.\n */\nstruct LoadFuncNullable\n{\n\tauto funcTagForNew() -> LoadFuncNullable { return { }; }\n};\n\n\n\n/**\n * Terminal function loading integer.\n */\nvoid loadHelper(const std::string &parent, int& v, const YAML::YamlNodeReader& reader)\n{\n\tv = reader.readVal<int>();\n}\n\n/**\n * Terminal function loading string.\n * Function can't load empty string.\n */\nvoid loadHelper(const std::string &parent, std::string& v, const YAML::YamlNodeReader& reader)\n{\n\treader.tryReadVal(v);\n\tif (Mod::isEmptyRuleName(v))\n\t{\n\t\tthrow LoadRuleException(parent, reader, \"Invalid value for name\");\n\t}\n}\n\n/**\n * Function loading string.\n * If node do not exists then it do not change value.\n * Function can't load empty string.\n */\nvoid loadHelper(const std::string &parent, std::string& v, const YAML::YamlNodeReader& reader, LoadFuncStandard)\n{\n\tif (reader)\n\t{\n\t\tloadHelper(parent, v, reader);\n\t}\n}\n\n/**\n * Function loading string with option for pseudo null value.\n * If node do not exists then it do not change value.\n */\nvoid loadHelper(const std::string &parent, std::string& v, const YAML::YamlNodeReader& reader, LoadFuncNullable)\n{\n\tif (reader)\n\t{\n\t\tif (reader.hasNullVal())\n\t\t{\n\t\t\tv = Mod::STR_NULL;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tv = reader.readVal<std::string>();\n\t\t\tif (v == Mod::STR_NULL)\n\t\t\t{\n\t\t\t\tthrow LoadRuleException(parent, reader, \"Invalid value for name \");\n\t\t\t}\n\t\t}\n\t}\n}\n\ntemplate<typename T, typename... LoadFuncTag>\nvoid loadHelper(const std::string &parent, std::vector<T>& v, const YAML::YamlNodeReader& reader, LoadFuncStandard, LoadFuncTag... rest)\n{\n\tif (reader)\n\t{\n\t\tshowInfo(parent, reader);\n\n\t\tif (isListHelper(reader))\n\t\t{\n\t\t\tv.clear();\n\t\t\tv.reserve(reader.childrenCount());\n\t\t\tfor (const auto& n : reader.children())\n\t\t\t{\n\t\t\t\tloadHelper(parent, v.emplace_back(), n, rest.funcTagForNew()...);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tthrowOnBadListHelper(parent, reader);\n\t\t}\n\t}\n}\n\ntemplate<typename T, typename... LoadFuncTag>\nvoid loadHelper(const std::string &parent, std::vector<T>& v, const YAML::YamlNodeReader& reader, LoadFuncEditable, LoadFuncTag... rest)\n{\n\tif (reader)\n\t{\n\t\tshowInfo(parent, reader, AddTag, RemoveTag);\n\n\t\tif (isListHelper(reader))\n\t\t{\n\t\t\tv.clear();\n\t\t\tv.reserve(reader.childrenCount());\n\t\t\tfor (const auto& n : reader.children())\n\t\t\t{\n\t\t\t\tloadHelper(parent, v.emplace_back(), n, rest.funcTagForNew()...);\n\t\t\t}\n\t\t}\n\t\telse if (isListAddTagHelper(reader))\n\t\t{\n\t\t\tv.reserve(v.size() + reader.childrenCount());\n\t\t\tfor (const auto& n : reader.children())\n\t\t\t{\n\t\t\t\tloadHelper(parent, v.emplace_back(), n, rest...);\n\t\t\t}\n\t\t}\n\t\telse if (isListRemoveTagHelper(reader))\n\t\t{\n\t\t\tconst auto begin = v.begin();\n\t\t\tauto end = v.end();\n\t\t\tfor (const auto& n : reader.children())\n\t\t\t{\n\t\t\t\tend = std::remove(begin, end, n.readVal<T>());\n\t\t\t}\n\t\t\tv.erase(end, v.end());\n\t\t}\n\t\telse\n\t\t{\n\t\t\tthrowOnBadListHelper(parent, reader);\n\t\t}\n\t}\n}\n\ntemplate<typename K, typename V, typename... LoadFuncTag>\nvoid loadHelper(const std::string &parent, std::map<K, V>& v, const YAML::YamlNodeReader& reader, LoadFuncStandard, LoadFuncTag... rest)\n{\n\tif (reader)\n\t{\n\t\tshowInfo(parent, reader);\n\n\t\tif (isMapHelper(reader))\n\t\t{\n\t\t\tv.clear();\n\t\t\tfor (const auto& n : reader.children())\n\t\t\t{\n\t\t\t\tauto key = n.readKey<K>();\n\n\t\t\t\tloadHelper(parent, v[key], n, rest.funcTagForNew()...);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tthrowOnBadMapHelper(parent, reader);\n\t\t}\n\t}\n}\n\ntemplate<typename K, typename V, typename... LoadFuncTag>\nvoid loadHelper(const std::string &parent, std::map<K, V>& v, const YAML::YamlNodeReader& reader, LoadFuncEditable, LoadFuncTag... rest)\n{\n\tif (reader)\n\t{\n\t\tshowInfo(parent, reader, AddTag, RemoveTag);\n\n\t\tif (isMapHelper(reader))\n\t\t{\n\t\t\tv.clear();\n\t\t\tfor (const auto& n : reader.children())\n\t\t\t{\n\t\t\t\tauto key = n.readKey<K>();\n\n\t\t\t\tloadHelper(parent, v[key], n, rest.funcTagForNew()...);\n\t\t\t}\n\t\t}\n\t\telse if (isMapAddTagHelper(reader))\n\t\t{\n\t\t\tfor (const auto& n : reader.children())\n\t\t\t{\n\t\t\t\tauto key = n.readKey<K>();\n\n\t\t\t\tloadHelper(parent, v[key], n, rest...);\n\t\t\t}\n\t\t}\n\t\telse if (isListRemoveTagHelper(reader)) // we use a list here as we only need the keys\n\t\t{\n\t\t\tfor (const auto& n : reader.children())\n\t\t\t{\n\t\t\t\tv.erase(n.readVal<K>());\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tthrowOnBadMapHelper(parent, reader);\n\t\t}\n\t}\n}\n\n/**\n * Fixed order map, rely on fact that yaml-cpp try preserve map order from loaded file\n */\ntemplate<typename K, typename V, typename... LoadFuncTag>\nvoid loadHelper(const std::string &parent, std::vector<std::pair<K, V>>& v, const YAML::YamlNodeReader& reader, LoadFuncEditable, LoadFuncTag... rest)\n{\n\tif (reader)\n\t{\n\t\tshowInfo(parent, reader, AddTag, RemoveTag);\n\n\t\tauto pushBack = [&](const K& k) -> V&\n\t\t{\n\t\t\treturn v.emplace_back(std::pair<K, V>{ k, V{} }).second;\n\t\t};\n\n\t\tauto findOrPushBack = [&](const K& k) -> V&\n\t\t{\n\t\t\tfor (auto& p : v)\n\t\t\t{\n\t\t\t\tif (p.first == k)\n\t\t\t\t{\n\t\t\t\t\treturn p.second;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn pushBack(k);\n\t\t};\n\n\t\tif (isMapHelper(reader))\n\t\t{\n\t\t\tv.clear();\n\t\t\tfor (const auto& n : reader.children())\n\t\t\t{\n\t\t\t\tauto key = n.readKey<K>();\n\n\t\t\t\tloadHelper(parent, pushBack(key), n, rest.funcTagForNew()...);\n\t\t\t}\n\t\t}\n\t\telse if (isMapAddTagHelper(reader))\n\t\t{\n\t\t\tfor (const auto& n : reader.children())\n\t\t\t{\n\t\t\t\tauto key = n.readKey<K>();\n\n\t\t\t\tloadHelper(parent, findOrPushBack(key), n, rest...);\n\t\t\t}\n\t\t}\n\t\telse if (isListRemoveTagHelper(reader)) // we use a list here as we only need the keys\n\t\t{\n\t\t\tfor (const auto& n : reader.children())\n\t\t\t{\n\t\t\t\tauto key = n.readVal<K>();\n\t\t\t\tCollections::removeIf(v, [&](auto& p){ return p.first == key; });\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tthrowOnBadMapHelper(parent, reader);\n\t\t}\n\t}\n}\n\n\n\nconst std::string YamlRuleNodeDelete = \"delete\";\nconst std::string YamlRuleNodeNew = \"new\";\nconst std::string YamlRuleNodeOverride = \"override\";\nconst std::string YamlRuleNodeUpdate = \"update\";\nconst std::string YamlRuleNodeIgnore = \"ignore\";\n\n\nvoid loadRuleInfoHelper(const YAML::YamlNodeReader& reader, const char* nodeName, const char* type)\n{\n\tif (reader.hasValTag(InfoTag))\n\t{\n\t\tLogger info;\n\t\tinfo.get() << \"Main node names available for '\" << nodeName << \":' at line \" << reader.getLocationInFile().line << \" are: \";\n\t\tinfo.get() << \" '\" << YamlRuleNodeDelete << \":',\";\n\t\tinfo.get() << \" '\" << YamlRuleNodeNew << \":',\";\n\t\tinfo.get() << \" '\" << YamlRuleNodeOverride << \":',\";\n\t\tinfo.get() << \" '\" << YamlRuleNodeUpdate << \":',\";\n\t\tinfo.get() << \" '\" << YamlRuleNodeIgnore << \":',\";\n\t\tinfo.get() << \" '\" << type << \":'\";\n\t}\n}\n\n} // namespace\n\n/**\n * Get offset and index for sound set or sprite set.\n * @param parent Name of parent node, used for better error message\n * @param offset Member to load new value.\n * @param node Node with data\n * @param shared Max offset limit that is shared for every mod\n * @param multiplier Value used by `projectile` surface set to convert projectile offset to index offset in surface.\n * @param sizeScale Value used by transparency colors, reduce total number of available space for offset.\n */\nvoid Mod::loadOffsetNode(const std::string &parent, int& offset, const YAML::YamlNodeReader& reader, int shared, const std::string &set, size_t multiplier, size_t sizeScale) const\n{\n\tassert(_modCurrent);\n\tconst ModData* curr = _modCurrent;\n\tif (reader.hasVal())\n\t{\n\t\toffset = reader.readVal<int>();\n\t}\n\telse if (isMapHelper(reader))\n\t{\n\t\toffset = reader[\"index\"].readVal<int>();\n\t\tstd::string mod = reader[\"mod\"].readVal<std::string>();\n\t\tif (mod == ModNameMaster)\n\t\t{\n\t\t\tcurr = &_modData.at(0);\n\t\t}\n\t\telse if (mod == ModNameCurrent)\n\t\t{\n\t\t\t//nothing\n\t\t}\n\t\telse\n\t\t{\n\t\t\tconst ModData* n = 0;\n\t\t\tfor (size_t i = 0; i < _modData.size(); ++i)\n\t\t\t{\n\t\t\t\tconst ModData& d = _modData[i];\n\t\t\t\tif (d.name == mod)\n\t\t\t\t{\n\t\t\t\t\tn = &d;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (n)\n\t\t\t{\n\t\t\t\tcurr = n;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tstd::ostringstream err;\n\t\t\t\terr << \"unknown mod '\" << mod << \"' used\";\n\t\t\t\tthrow LoadRuleException(parent, reader, err.str());\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\tthrow LoadRuleException(parent, reader, \"unsupported yaml node\");\n\t}\n\n\tstatic_assert(Mod::NO_SOUND == -1, \"NO_SOUND need to equal -1\");\n\tstatic_assert(Mod::NO_SURFACE == -1, \"NO_SURFACE need to equal -1\");\n\n\tif (offset < -1)\n\t{\n\t\tstd::ostringstream err;\n\t\terr << \"offset '\" << offset << \"' has incorrect value in set '\" << set << \"'\";\n\t\tthrow LoadRuleException(parent, reader, err.str());\n\t}\n\telse if (offset == -1)\n\t{\n\t\t//ok\n\t}\n\telse\n\t{\n\t\tint f = offset;\n\t\tf *= multiplier;\n\t\tif ((size_t)f > curr->size / sizeScale)\n\t\t{\n\t\t\tstd::ostringstream err;\n\t\t\terr << \"offset '\" << offset << \"' exceeds mod size limit \" << (curr->size / multiplier / sizeScale) << \" in set '\" << set << \"'\";\n\t\t\tthrow LoadRuleException(parent, reader, err.str());\n\t\t}\n\t\tif (f >= shared)\n\t\t\tf += curr->offset / sizeScale;\n\t\toffset = f;\n\t}\n}\n\n/**\n * Returns the appropriate mod-based offset for a sprite.\n * If the ID is bigger than the surfaceset contents, the mod offset is applied.\n * @param parent Name of parent node, used for better error message\n * @param sprite Member to load new sprite ID index.\n * @param node Node with data\n * @param set Name of the surfaceset to lookup.\n * @param multiplier Value used by `projectile` surface set to convert projectile offset to index offset in surface.\n */\nvoid Mod::loadSpriteOffset(const std::string &parent, int& sprite, const YAML::YamlNodeReader& reader, const std::string &set, size_t multiplier) const\n{\n\tif (reader)\n\t{\n\t\tloadOffsetNode(parent, sprite, reader, getRule(set, \"Sprite Set\", _sets, true)->getMaxSharedFrames(), set, multiplier);\n\t}\n}\n\n/**\n * Gets the mod offset array for a certain sprite.\n * @param parent Name of parent node, used for better error message\n * @param sprites Member to load new array of sprite ID index.\n * @param node Node with data\n * @param set Name of the surfaceset to lookup.\n */\nvoid Mod::loadSpriteOffset(const std::string &parent, std::vector<int>& sprites, const YAML::YamlNodeReader& reader, const std::string &set) const\n{\n\tif (reader)\n\t{\n\t\tint maxShared = getRule(set, \"Sprite Set\", _sets, true)->getMaxSharedFrames();\n\t\tsprites.clear();\n\t\tif (isListHelper(reader))\n\t\t{\n\t\t\tfor (const auto& spriteReader : reader.children())\n\t\t\t{\n\t\t\t\tsprites.push_back(Mod::NO_SURFACE);\n\t\t\t\tloadOffsetNode(parent, sprites.back(), spriteReader, maxShared, set, 1);\n\t\t\t\tif (checkForSoftError(sprites.back() == Mod::NO_SURFACE, parent, spriteReader, \"incorrect value in sprite list\"))\n\t\t\t\t{\n\t\t\t\t\tsprites.pop_back();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tsprites.push_back(Mod::NO_SURFACE);\n\t\t\tloadOffsetNode(parent, sprites.back(), reader, maxShared, set, 1);\n\t\t}\n\t}\n}\n\n/**\n * Returns the appropriate mod-based offset for a sound.\n * If the ID is bigger than the soundset contents, the mod offset is applied.\n * @param parent Name of parent node, used for better error message\n * @param sound Member to load new sound ID index.\n * @param node Node with data\n * @param set Name of the soundset to lookup.\n */\nvoid Mod::loadSoundOffset(const std::string &parent, int& sound, const YAML::YamlNodeReader& reader, const std::string &set) const\n{\n\tif (reader)\n\t{\n\t\tloadOffsetNode(parent, sound, reader, getSoundSet(set)->getMaxSharedSounds(), set, 1);\n\t}\n}\n\n/**\n * Gets the mod offset array for a certain sound.\n * @param parent Name of parent node, used for better error message\n * @param sounds Member to load new list of sound ID indexes.\n * @param node Node with data\n * @param set Name of the soundset to lookup.\n */\nvoid Mod::loadSoundOffset(const std::string &parent, std::vector<int>& sounds, const YAML::YamlNodeReader& reader, const std::string &set) const\n{\n\tif (reader)\n\t{\n\t\tint maxShared = getSoundSet(set)->getMaxSharedSounds();\n\t\tsounds.clear();\n\t\tif (isListHelper(reader))\n\t\t{\n\t\t\tfor (const auto& soundReader : reader.children())\n\t\t\t{\n\t\t\t\tsounds.push_back(Mod::NO_SOUND);\n\t\t\t\tloadOffsetNode(parent, sounds.back(), soundReader, maxShared, set, 1);\n\t\t\t\tif (checkForSoftError(sounds.back() == Mod::NO_SOUND, parent, soundReader, \"incorrect value in sound list\"))\n\t\t\t\t{\n\t\t\t\t\tsounds.pop_back();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tsounds.push_back(Mod::NO_SOUND);\n\t\t\tloadOffsetNode(parent, sounds.back(), reader, maxShared, set, 1);\n\t\t}\n\t}\n}\n\n/**\n * Gets the mod offset array for a certain transparency index.\n * @param parent Name of parent node, used for better error message.\n * @param index Member to load new transparency index.\n * @param node Node with data.\n */\nvoid Mod::loadTransparencyOffset(const std::string &parent, int& index, const YAML::YamlNodeReader& reader) const\n{\n\tif (reader)\n\t{\n\t\tloadOffsetNode(parent, index, reader, 0, \"TransparencyLUTs\", 1, ModTransparencySizeReduction);\n\t}\n}\n\n/**\n * Returns the appropriate mod-based offset for a generic ID.\n * If the ID is bigger than the max, the mod offset is applied.\n * @param id Numeric ID.\n * @param max Maximum vanilla value.\n */\nint Mod::getOffset(int id, int max) const\n{\n\tassert(_modCurrent);\n\tif (id > max)\n\t\treturn id + _modCurrent->offset;\n\telse\n\t\treturn id;\n}\n\n/**\n * Load base functions to bit set.\n */\nvoid Mod::loadBaseFunction(const std::string& parent, RuleBaseFacilityFunctions& f, const YAML::YamlNodeReader& reader)\n{\n\tif (reader)\n\t{\n\t\ttry\n\t\t{\n\t\t\tif (isListHelper(reader))\n\t\t\t{\n\t\t\t\tf.reset();\n\t\t\t\tfor (const auto& n : reader.children())\n\t\t\t\t{\n\t\t\t\t\tf.set(_baseFunctionNames.addName(n.readVal<std::string>(), f.size()));\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (isListAddTagHelper(reader))\n\t\t\t{\n\t\t\t\tfor (const auto& n : reader.children())\n\t\t\t\t{\n\t\t\t\t\tf.set(_baseFunctionNames.addName(n.readVal<std::string>(), f.size()));\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (isListRemoveTagHelper(reader))\n\t\t\t{\n\t\t\t\tfor (const auto& n : reader.children())\n\t\t\t\t{\n\t\t\t\t\tf.set(_baseFunctionNames.addName(n.readVal<std::string>(), f.size()), false);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tthrowOnBadListHelper(parent, reader);\n\t\t\t}\n\t\t}\n\t\tcatch(LoadRuleException& ex)\n\t\t{\n\t\t\t//context is already included in exception, no need add more\n\t\t\tthrow;\n\t\t}\n\t\tcatch(Exception& ex)\n\t\t{\n\t\t\tthrow LoadRuleException(parent, reader, ex.what());\n\t\t}\n\t}\n}\n\n/**\n * Get names of function names in given bitset.\n */\nstd::vector<std::string> Mod::getBaseFunctionNames(RuleBaseFacilityFunctions f) const\n{\n\tstd::vector<std::string> vec;\n\tvec.reserve(f.count());\n\tfor (size_t i = 0; i < f.size(); ++i)\n\t{\n\t\tif (f.test(i))\n\t\t{\n\t\t\tvec.push_back(_baseFunctionNames.getName(i));\n\t\t}\n\t}\n\treturn vec;\n}\n\n/**\n * Loads a list of ints.\n * Another mod can only override the whole list, no partial edits allowed.\n */\nvoid Mod::loadInts(const std::string &parent, std::vector<int>& ints, const YAML::YamlNodeReader& reader) const\n{\n\tloadHelper(parent, ints, reader, LoadFuncStandard{});\n}\n\n/**\n * Loads a list of ints where order of items does not matter.\n * Another mod can remove or add new values without altering the whole list.\n */\nvoid Mod::loadUnorderedInts(const std::string &parent, std::vector<int>& ints, const YAML::YamlNodeReader& reader) const\n{\n\tloadHelper(parent, ints, reader, LoadFuncEditable{});\n}\n\n\n/**\n * Loads a name.\n */\nvoid Mod::loadName(const std::string &parent, std::string& name, const YAML::YamlNodeReader& reader) const\n{\n\tloadHelper(parent, name, reader, LoadFuncStandard{});\n}\n\n/**\n * Loads a name. Have option of loading null `~` as special string value.\n */\nvoid Mod::loadNameNull(const std::string &parent, std::string& name, const YAML::YamlNodeReader& reader) const\n{\n\tloadHelper(parent, name, reader, LoadFuncNullable{});\n}\n\n/**\n * Loads a list of names.\n * Another mod can only override the whole list, no partial edits allowed.\n */\nvoid Mod::loadNames(const std::string &parent, std::vector<std::string>& names, const YAML::YamlNodeReader& reader) const\n{\n\tloadHelper(parent, names, reader, LoadFuncStandard{});\n}\n\n/**\n * Loads a list of names where order of items does not matter.\n * Another mod can remove or add new values without altering the whole list.\n */\nvoid Mod::loadUnorderedNames(const std::string &parent, std::vector<std::string>& names, const YAML::YamlNodeReader& reader) const\n{\n\tloadHelper(parent, names, reader, LoadFuncEditable{});\n}\n\n\n\n/**\n * Loads a map from names to names.\n */\nvoid Mod::loadNamesToNames(const std::string &parent, std::vector<std::pair<std::string, std::vector<std::string>>>& names, const YAML::YamlNodeReader& reader) const\n{\n\tloadHelper(parent, names, reader, LoadFuncEditable{}, LoadFuncEditable{});\n}\n\n/**\n * Loads a map from names to names.\n */\nvoid Mod::loadUnorderedNamesToNames(const std::string &parent, std::map<std::string, std::string>& names, const YAML::YamlNodeReader& reader) const\n{\n\tloadHelper(parent, names, reader, LoadFuncEditable{});\n}\n\n/**\n * Loads a map from names to ints.\n */\nvoid Mod::loadUnorderedNamesToInt(const std::string &parent, std::map<std::string, int>& names, const YAML::YamlNodeReader& reader) const\n{\n\tloadHelper(parent, names, reader, LoadFuncEditable{});\n}\n\n/**\n * Loads a map from names to vector of ints.\n */\nvoid Mod::loadUnorderedNamesToInts(const std::string &parent, std::map<std::string, std::vector<int>>& names, const YAML::YamlNodeReader& reader) const\n{\n\tloadHelper(parent, names, reader, LoadFuncEditable{}, LoadFuncStandard{});\n}\n\n/**\n * Loads a map from names to names to int.\n */\nvoid Mod::loadUnorderedNamesToNamesToInt(const std::string &parent, std::map<std::string, std::map<std::string, int>>& names, const YAML::YamlNodeReader& reader) const\n{\n\tloadHelper(parent, names, reader, LoadFuncEditable{}, LoadFuncEditable{});\n}\n\n/**\n * Loads data for kill criteria from Commendations.\n */\nvoid Mod::loadKillCriteria(const std::string &parent, std::vector<std::vector<std::pair<int, std::vector<std::string> > > >& v, const YAML::YamlNodeReader& reader) const\n{\n\t//TODO: very specific use case, not all levels fully supported\n\tif (reader)\n\t{\n\t\tauto loadInner = [&](std::vector<std::pair<int, std::vector<std::string>>>& vv, const YAML::YamlNodeReader& n)\n\t\t{\n\t\t\tshowInfo(parent, n);\n\n\t\t\tif (isListHelper(n))\n\t\t\t{\n\t\t\t\tvv = n.readVal<std::vector<std::pair<int, std::vector<std::string>>>>();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tthrowOnBadListHelper(parent, n);\n\t\t\t}\n\t\t};\n\n\t\tshowInfo(parent, reader, AddTag);\n\n\t\tif (isListHelper(reader))\n\t\t{\n\t\t\tv.clear();\n\t\t\tv.reserve(reader.childrenCount());\n\t\t\tfor (const auto& n : reader.children())\n\t\t\t{\n\t\t\t\tloadInner(v.emplace_back(), n);\n\t\t\t}\n\t\t}\n\t\telse if (isListAddTagHelper(reader))\n\t\t{\n\t\t\tv.reserve(v.size() + reader.childrenCount());\n\t\t\tfor (const auto& n : reader.children())\n\t\t\t{\n\t\t\t\tloadInner(v.emplace_back(), n);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tthrowOnBadListHelper(parent, reader);\n\t\t}\n\t}\n}\n\n\n\n\ntemplate<typename T>\nstatic void afterLoadHelper(const char* name, Mod* mod, std::map<std::string, T*>& list, void (T::* func)(const Mod*))\n{\n\tstd::ostringstream errorStream;\n\tint errorLimit = 30;\n\tint errorCount = 0;\n\n\terrorStream << \"During linking rulesets of \" << name << \":\\n\";\n\tfor (auto& rule : list)\n\t{\n\t\ttry\n\t\t{\n\t\t\t(rule.second->* func)(mod);\n\t\t}\n\t\tcatch (LoadRuleException &e)\n\t\t{\n\t\t\t++errorCount;\n\t\t\terrorStream << e.what() << \"\\n\";\n\t\t\tif (errorCount == errorLimit)\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tcatch (Exception &e)\n\t\t{\n\t\t\t++errorCount;\n\t\t\terrorStream << \"Error processing '\" << rule.first << \"' in \" << name << \": \" << e.what() << \"\\n\";\n\t\t\tif (errorCount == errorLimit)\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\tif (errorCount)\n\t{\n\t\tthrow Exception(errorStream.str());\n\t}\n}\n\n/**\n * Helper function used to disable invalid mod and throw exception to quit game\n * @param modId Mod id\n * @param error Error message\n */\nstatic void throwModOnErrorHelper(const std::string& modId, const std::string& error)\n{\n\tstd::ostringstream errorStream;\n\n\terrorStream << \"failed to load '\"\n\t\t<< Options::getModInfos().at(modId).getName()\n\t\t<< \"'\";\n\n\tif (!Options::debug)\n\t{\n\t\tLog(LOG_WARNING) << \"disabling mod with invalid ruleset: \" << modId;\n\t\tauto it = std::find(Options::mods.begin(), Options::mods.end(), std::pair<std::string, bool>(modId, true));\n\t\tif (it == Options::mods.end())\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"cannot find broken mod in mods list: \" << modId;\n\t\t\tLog(LOG_ERROR) << \"clearing mods list\";\n\t\t\tOptions::mods.clear();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tit->second = false;\n\t\t}\n\t\tOptions::save();\n\n\t\terrorStream << \"; mod disabled\";\n\t}\n\terrorStream << std::endl << error;\n\n\tthrow Exception(errorStream.str());\n}\n\n/**\n * Loads a list of mods specified in the options.\n * List of <modId, rulesetFiles> pairs is fetched from the FileMap / VFS\n * being set up in options updateMods\n */\nvoid Mod::loadAll()\n{\n\tModScript parser{ _scriptGlobal, this };\n\tconst auto& mods = FileMap::getRulesets();\n\n\tLog(LOG_INFO) << \"Loading begins...\";\n\tif (Options::oxceModValidationLevel < LOG_ERROR)\n\t{\n\t\tLog(LOG_ERROR) << \"Validation of mod data disabled, game can crash when run\";\n\t}\n\telse if (Options::oxceModValidationLevel < LOG_WARNING)\n\t{\n\t\tLog(LOG_WARNING) << \"Validation of mod data reduced, game can behave incorrectly\";\n\t}\n\t_scriptGlobal->beginLoad();\n\t_modData.clear();\n\t_modData.resize(mods.size());\n\n\tstd::set<std::string> usedModNames;\n\tusedModNames.insert(ModNameMaster);\n\tusedModNames.insert(ModNameCurrent);\n\n\n\t// calculated offsets and other things for all mods\n\tsize_t offset = 0;\n\tfor (size_t i = 0; mods.size() > i; ++i)\n\t{\n\t\tconst std::string& modId = mods[i].first;\n\t\tif (usedModNames.insert(modId).second == false)\n\t\t{\n\t\t\tthrowModOnErrorHelper(modId, \"this mod name is already used\");\n\t\t}\n\t\t_scriptGlobal->addMod(mods[i].first, 1000 * (int)offset);\n\t\tconst ModInfo *modInfo = &Options::getModInfos().at(modId);\n\t\tsize_t size = modInfo->getReservedSpace();\n\t\t_modData[i].name = modId;\n\t\t_modData[i].offset = 1000 * offset;\n\t\t_modData[i].info = modInfo;\n\t\t_modData[i].size = 1000 * size;\n\t\toffset += size;\n\t}\n\n\tLog(LOG_INFO) << \"Pre-loading rulesets...\";\n\t// load rulesets that can affect loading vanilla resources\n\tfor (size_t i = 0; _modData.size() > i; ++i)\n\t{\n\t\t_modCurrent = &_modData.at(i);\n\t\t//if (_modCurrent->info->isMaster())\n\t\t{\n\t\t\tauto* file = FileMap::getModRuleFile(_modCurrent->info, _modCurrent->info->getResourceConfigFile());\n\t\t\tif (file)\n\t\t\t{\n\t\t\t\tloadResourceConfigFile(*file);\n\t\t\t}\n\t\t}\n\t}\n\n\tLog(LOG_INFO) << \"Loading vanilla resources...\";\n\t// vanilla resources load\n\t_modCurrent = &_modData.at(0);\n\tloadVanillaResources();\n\t_surfaceOffsetBasebits = _sets[\"BASEBITS.PCK\"]->getMaxSharedFrames();\n\t_surfaceOffsetBigobs = _sets[\"BIGOBS.PCK\"]->getMaxSharedFrames();\n\t_surfaceOffsetFloorob = _sets[\"FLOOROB.PCK\"]->getMaxSharedFrames();\n\t_surfaceOffsetHandob = _sets[\"HANDOB.PCK\"]->getMaxSharedFrames();\n\t_surfaceOffsetHit = _sets[\"HIT.PCK\"]->getMaxSharedFrames();\n\t_surfaceOffsetSmoke = _sets[\"SMOKE.PCK\"]->getMaxSharedFrames();\n\n\t_soundOffsetBattle = _sounds[\"BATTLE.CAT\"]->getMaxSharedSounds();\n\t_soundOffsetGeo = _sounds[\"GEO.CAT\"]->getMaxSharedSounds();\n\n\tLog(LOG_INFO) << \"Loading rulesets...\";\n\t// load rest rulesets\n\tfor (size_t i = 0; mods.size() > i; ++i)\n\t{\n\t\ttry\n\t\t{\n\t\t\t_modCurrent = &_modData.at(i);\n\t\t\t_scriptGlobal->setMod((int)_modCurrent->offset);\n\t\t\tloadMod(mods[i].second, parser);\n\t\t}\n\t\tcatch (Exception &e)\n\t\t{\n\t\t\tconst std::string &modId = mods[i].first;\n\t\t\tthrowModOnErrorHelper(modId, e.what());\n\t\t}\n\t}\n\tLog(LOG_INFO) << \"Loading rulesets done.\";\n\n\t//back master\n\t_modCurrent = &_modData.at(0);\n\t_scriptGlobal->endLoad();\n\n\t// post-processing item categories\n\tstd::map<std::string, std::string> replacementRules;\n\tfor (const auto& pair : _itemCategories)\n\t{\n\t\tif (!pair.second->getReplaceBy().empty())\n\t\t{\n\t\t\treplacementRules[pair.first] = pair.second->getReplaceBy();\n\t\t}\n\t}\n\tfor (auto& pair : _items)\n\t{\n\t\tpair.second->updateCategories(&replacementRules);\n\t}\n\n\t// find out if paperdoll overlaps with inventory slots\n\tint x1 = RuleInventory::PAPERDOLL_X;\n\tint y1 = RuleInventory::PAPERDOLL_Y;\n\tint w1 = RuleInventory::PAPERDOLL_W;\n\tint h1 = RuleInventory::PAPERDOLL_H;\n\tfor (const auto& invCategory : _invs)\n\t{\n\t\tfor (const auto& invSlot : *invCategory.second->getSlots())\n\t\t{\n\t\t\tint x2 = invCategory.second->getX() + (invSlot.x * RuleInventory::SLOT_W);\n\t\t\tint y2 = invCategory.second->getY() + (invSlot.y * RuleInventory::SLOT_H);\n\t\t\tint w2 = RuleInventory::SLOT_W;\n\t\t\tint h2 = RuleInventory::SLOT_H;\n\t\t\tif (x1 + w1 < x2 || x2 + w2 < x1 || y1 + h1 < y2 || y2 + h2 < y1)\n\t\t\t{\n\t\t\t\t// intersection is empty\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_inventoryOverlapsPaperdoll = true;\n\t\t\t}\n\t\t}\n\t}\n\n\tloadExtraResources();\n\n\n\tLog(LOG_INFO) << \"After load.\";\n\t// cross link rule objects\n\n\tafterLoadHelper(\"research\", this, _research, &RuleResearch::afterLoad);\n\tafterLoadHelper(\"items\", this, _items, &RuleItem::afterLoad);\n\tafterLoadHelper(\"weaponSets\", this, _weaponSets, &RuleWeaponSet::afterLoad);\n\tafterLoadHelper(\"manufacture\", this, _manufacture, &RuleManufacture::afterLoad);\n\tafterLoadHelper(\"armors\", this, _armors, &Armor::afterLoad);\n\tafterLoadHelper(\"units\", this, _units, &Unit::afterLoad);\n\tafterLoadHelper(\"soldiers\", this, _soldiers, &RuleSoldier::afterLoad);\n\tafterLoadHelper(\"facilities\", this, _facilities, &RuleBaseFacility::afterLoad);\n\tafterLoadHelper(\"startingConditions\", this, _startingConditions, &RuleStartingCondition::afterLoad);\n\tafterLoadHelper(\"enviroEffects\", this, _enviroEffects, &RuleEnviroEffects::afterLoad);\n\tafterLoadHelper(\"commendations\", this, _commendations, &RuleCommendations::afterLoad);\n\tafterLoadHelper(\"skills\", this, _skills, &RuleSkill::afterLoad);\n\tafterLoadHelper(\"craftWeapons\", this, _craftWeapons, &RuleCraftWeapon::afterLoad);\n\tafterLoadHelper(\"countries\", this, _countries, &RuleCountry::afterLoad);\n\tafterLoadHelper(\"crafts\", this, _crafts, &RuleCraft::afterLoad);\n\tafterLoadHelper(\"events\", this, _events, &RuleEvent::afterLoad);\n\n\tfor (auto& a : _armors)\n\t{\n\t\tif (a.second->hasInfiniteSupply())\n\t\t{\n\t\t\t_armorsForSoldiersCache.push_back(a.second);\n\t\t}\n\t\telse if (a.second->getStoreItem())\n\t\t{\n\t\t\t_armorsForSoldiersCache.push_back(a.second);\n\t\t\t_armorStorageItemsCache.push_back(a.second->getStoreItem());\n\t\t}\n\t}\n\t//_armorsForSoldiersCache sorted in sortList()\n\tCollections::sortVector(_armorStorageItemsCache);\n\tCollections::sortVectorMakeUnique(_armorStorageItemsCache);\n\n\n\tfor (auto& c : _craftWeapons)\n\t{\n\t\tconst RuleItem* item = nullptr;\n\n\t\titem = c.second->getLauncherItem();\n\t\tif (item)\n\t\t{\n\t\t\t_craftWeaponStorageItemsCache.push_back(item);\n\t\t}\n\n\t\titem = c.second->getClipItem();\n\t\tif (item)\n\t\t{\n\t\t\t_craftWeaponStorageItemsCache.push_back(item);\n\t\t}\n\t}\n\tCollections::sortVector(_craftWeaponStorageItemsCache);\n\tCollections::sortVectorMakeUnique(_craftWeaponStorageItemsCache);\n\n\n\tfor (auto& r : _research)\n\t{\n\t\tif (r.second->unlockFinalMission())\n\t\t{\n\t\t\tif (_finalResearch != nullptr)\n\t\t\t{\n\t\t\t\tcheckForSoftError(true, \"mod\", \"Both '\" + _finalResearch->getName() + \"' and '\" + r.second->getName() + \"' research are marked as 'unlockFinalMission: true'\", LOG_INFO);\n\n\t\t\t\t// to make old mods semi-compatible with new code we decide that last updated rule will be consider final research. This could make false-positive as last update could not touch this flag.\n\t\t\t\tif (getModLastUpdatingRule(r.second)->offset < getModLastUpdatingRule(_finalResearch)->offset)\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\t_finalResearch = r.second;\n\t\t}\n\t}\n\n\n\t// check unique listOrder\n\t{\n\t\tstd::vector<int> tmp;\n\t\ttmp.reserve(_soldierBonus.size());\n\t\tfor (auto& i : _soldierBonus)\n\t\t{\n\t\t\ttmp.push_back(i.second->getListOrder());\n\t\t}\n\t\tstd::sort(tmp.begin(), tmp.end());\n\t\tauto it = std::unique(tmp.begin(), tmp.end());\n\t\tbool wasUnique = (it == tmp.end());\n\t\tif (!wasUnique)\n\t\t{\n\t\t\tthrow Exception(\"List order for soldier bonus types must be unique!\");\n\t\t}\n\t}\n\n\t// auto-create alternative manufacture rules\n\tfor (auto& shortcutPair : _manufactureShortcut)\n\t{\n\t\t// 1. check if the new project has a unique name\n\t\tauto& typeNew = shortcutPair.first;\n\t\tauto it = _manufacture.find(typeNew);\n\t\tif (it != _manufacture.end())\n\t\t{\n\t\t\tthrow Exception(\"Manufacture project '\" + typeNew + \"' already exists! Choose a different name for this alternative project.\");\n\t\t}\n\n\t\t// 2. copy an existing manufacture project\n\t\tconst RuleManufacture* ruleStartFrom = getManufacture(shortcutPair.second->getStartFrom(), true);\n\t\tRuleManufacture* ruleNew = new RuleManufacture(*ruleStartFrom);\n\t\t_manufacture[typeNew] = ruleNew;\n\t\t_manufactureIndex.push_back(typeNew);\n\n\t\t// 3. change the name and break down the sub-projects into simpler components\n\t\tif (ruleNew != 0)\n\t\t{\n\t\t\truleNew->breakDown(this, shortcutPair.second);\n\t\t}\n\t}\n\n\t// recommended user options\n\tif (!_recommendedUserOptions.empty() && !Options::oxceRecommendedOptionsWereSet)\n\t{\n\t\t_recommendedUserOptions.erase(\"maximizeInfoScreens\"); // FIXME: make proper categorisations in the next release\n\t\t_recommendedUserOptions.erase(\"oxceModValidationLevel\");\n\n\t\tfor (auto& optionInfo : Options::getOptionInfo())\n\t\t{\n\t\t\tif (optionInfo.type() != OPTION_KEY && !optionInfo.category().empty())\n\t\t\t{\n\t\t\t\toptionInfo.load(_recommendedUserOptions, false);\n\t\t\t}\n\t\t}\n\n\t\tOptions::oxceRecommendedOptionsWereSet = true;\n\t\tOptions::save();\n\t}\n\n\t// fixed user options\n\tif (!_fixedUserOptions.empty())\n\t{\n\t\t_fixedUserOptions.erase(\"oxceLinks\");\n\t\t_fixedUserOptions.erase(\"oxceUpdateCheck\");\n\t\t_fixedUserOptions.erase(\"maximizeInfoScreens\"); // FIXME: make proper categorisations in the next release\n\t\t_fixedUserOptions.erase(\"oxceModValidationLevel\");\n\t\t_fixedUserOptions.erase(\"oxceAutoNightVisionThreshold\");\n\t\t_fixedUserOptions.erase(\"oxceAlternateCraftEquipmentManagement\");\n\n\t\tfor (auto& optionInfo : Options::getOptionInfo())\n\t\t{\n\t\t\tif (optionInfo.type() != OPTION_KEY && !optionInfo.category().empty())\n\t\t\t{\n\t\t\t\toptionInfo.load(_fixedUserOptions, false);\n\t\t\t}\n\t\t}\n\t\tOptions::save();\n\t}\n\n\t// additional validation of options not visible in the GUI\n\t{\n\t\tif (Options::oxceMaxEquipmentLayoutTemplates < 10 ||\n\t\t\tOptions::oxceMaxEquipmentLayoutTemplates > SavedGame::MAX_EQUIPMENT_LAYOUT_TEMPLATES ||\n\t\t\tOptions::oxceMaxEquipmentLayoutTemplates % 10 != 0)\n\t\t{\n\t\t\tOptions::oxceMaxEquipmentLayoutTemplates = 20;\n\t\t}\n\t}\n\n\tLog(LOG_INFO) << \"Loading ended.\";\n\n\tsortLists();\n\tmodResources();\n}\n\n/**\n * Loads a list of rulesets from YAML files for the mod at the specified index. The first\n * mod loaded should be the master at index 0, then 1, and so on.\n * @param rulesetFiles List of rulesets to load.\n * @param parsers Object with all available parsers.\n */\nvoid Mod::loadMod(const std::vector<FileMap::FileRecord> &rulesetFiles, ModScript &parsers)\n{\n\tstd::vector<FileMap::FileRecord> sortedRulesetFiles = rulesetFiles;\n\tstd::sort(sortedRulesetFiles.begin(), sortedRulesetFiles.end(),\n\t\t[](const FileMap::FileRecord& a, const FileMap::FileRecord& b)\n\t\t{ return a.fullpath > b.fullpath; });\n\tfor (const auto& filerec : sortedRulesetFiles)\n\t{\n\t\tLog(LOG_VERBOSE) << \"- \" << filerec.fullpath;\n\t\ttry\n\t\t{\n\t\t\t_scriptGlobal->fileLoad(filerec.fullpath);\n\t\t\tloadFile(filerec, parsers);\n\t\t}\n\t\tcatch (Exception &e)\n\t\t{\n\t\t\tthrow Exception(filerec.fullpath + \": \" + std::string(e.what()));\n\t\t}\n\t\tcatch (YAML::Exception &e)\n\t\t{\n\t\t\tthrow Exception(filerec.fullpath + \": \" + std::string(e.what()));\n\t\t}\n\t}\n\n\t// these need to be validated, otherwise we're gonna get into some serious trouble down the line.\n\t// it may seem like a somewhat arbitrary limitation, but there is a good reason behind it.\n\t// i'd need to know what results are going to be before they are formulated, and there's a hierarchical structure to\n\t// the order in which variables are determined for a mission, and the order is DIFFERENT for regular missions vs\n\t// missions that spawn a mission site. where normally we pick a region, then a mission based on the weights for that region.\n\t// a terror-type mission picks a mission type FIRST, then a region based on the criteria defined by the mission.\n\t// there is no way i can conceive of to reconcile this difference to allow mixing and matching,\n\t// short of knowing the results of calls to the RNG before they're determined.\n\t// the best solution i can come up with is to disallow it, as there are other ways to achieve what this would amount to anyway,\n\t// and they don't require time travel. - Warboy\n\tfor (auto& map : { _missionScripts, _adhocScripts })\n\tfor (auto& pair : map)\n\t{\n\t\tRuleMissionScript *rule = pair.second;\n\t\tstd::set<std::string> missions = rule->getAllMissionTypes();\n\t\tif (!missions.empty())\n\t\t{\n\t\t\tauto j = missions.begin();\n\t\t\tif (!getAlienMission(*j))\n\t\t\t{\n\t\t\t\tthrow Exception(\"Error with MissionScript: \" + pair.first + \": alien mission type: \" + *j + \" not defined, do not incite the judgement of Amaunator.\");\n\t\t\t}\n\t\t\tbool isSiteType = getAlienMission(*j)->getObjective() == OBJECTIVE_SITE;\n\t\t\trule->setSiteType(isSiteType);\n\t\t\tfor (;j != missions.end(); ++j)\n\t\t\t{\n\t\t\t\tif (getAlienMission(*j) && (getAlienMission(*j)->getObjective() == OBJECTIVE_SITE) != isSiteType)\n\t\t\t\t{\n\t\t\t\t\tthrow Exception(\"Error with MissionScript: \" + pair.first + \": cannot mix terror/non-terror missions in a single command, so sayeth the wise Alaundo.\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// instead of passing a pointer to the region load function and moving the alienMission loading before region loading\n\t// and sanitizing there, i'll sanitize here, i'm sure this sanitation will grow, and will need to be refactored into\n\t// its own function at some point, but for now, i'll put it here next to the missionScript sanitation, because it seems\n\t// the logical place for it, given that this sanitation is required as a result of moving all terror mission handling\n\t// into missionScripting behaviour. apologies to all the modders that will be getting errors and need to adjust their\n\t// rulesets, but this will save you weird errors down the line.\n\tfor (auto& pair : _regions)\n\t{\n\t\t// bleh, make copies, const correctness kinda screwed me here.\n\t\tWeightedOptions weights = pair.second->getAvailableMissions();\n\t\tstd::vector<std::string> names = weights.getNames();\n\t\tfor (const auto& name : names)\n\t\t{\n\t\t\tif (!getAlienMission(name))\n\t\t\t{\n\t\t\t\tthrow Exception(\"Error with MissionWeights: Region: \" + pair.first + \": alien mission type: \" + name + \" not defined, do not incite the judgement of Amaunator.\");\n\t\t\t}\n\t\t\tif (getAlienMission(name)->getObjective() == OBJECTIVE_SITE)\n\t\t\t{\n\t\t\t\tthrow Exception(\"Error with MissionWeights: Region: \" + pair.first + \" has \" + name + \" listed. Terror mission can only be invoked via missionScript, so sayeth the Spider Queen.\");\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Loads a ruleset from a YAML file that have basic resources configuration.\n * @param filename YAML filename.\n */\nvoid Mod::loadResourceConfigFile(const FileMap::FileRecord &filerec)\n{\n\tYAML::YamlRootNodeReader reader = filerec.getYAML();\n\n\tfor (const auto& soundDefReader : reader[\"soundDefs\"].children())\n\t{\n\t\tSoundDefinition *rule = loadRule(soundDefReader, &_soundDefs);\n\t\tif (rule != 0)\n\t\t{\n\t\t\trule->load(soundDefReader);\n\t\t}\n\t}\n\n\tif (const auto& luts = reader[\"transparencyLUTs\"])\n\t{\n\t\tconst size_t start = _modCurrent->offset / ModTransparencySizeReduction;\n\t\tconst size_t limit =  _modCurrent->size / ModTransparencySizeReduction;\n\t\tsize_t curr = 0;\n\n\t\t_transparencies.resize(start + limit);\n\t\tfor (const auto& lut : luts.children())\n\t\t{\n\t\t\tconst auto& colors = lut[\"colors\"];\n\t\t\tif (colors.isSeq())\n\t\t\t{\n\t\t\t\tfor (const auto& colorReader : colors.children())\n\t\t\t\t{\n\t\t\t\t\tif (curr == limit)\n\t\t\t\t\t{\n\t\t\t\t\t\tthrow Exception(\"transparencyLUTs mod limit reach\");\n\t\t\t\t\t}\n\n\t\t\t\t\tauto loadByteValue = [&](const YAML::YamlNodeReader& n)\n\t\t\t\t\t{\n\t\t\t\t\t\tint v = n.readVal<int>(-1);\n\t\t\t\t\t\tcheckForSoftError(v < 0 || v > 255, \"transparencyLUTs\", n, \"value outside allowed range\");\n\t\t\t\t\t\treturn Clamp(v, 0, 255);\n\t\t\t\t\t};\n\n\t\t\t\t\tif (colorReader[0].hasVal())\n\t\t\t\t\t{\n\t\t\t\t\t\tSDL_Color color;\n\t\t\t\t\t\tcolor.r = loadByteValue(colorReader[0]);\n\t\t\t\t\t\tcolor.g = loadByteValue(colorReader[1]);\n\t\t\t\t\t\tcolor.b = loadByteValue(colorReader[2]);\n\t\t\t\t\t\tcolor.unused = colorReader[3] ? loadByteValue(colorReader[3]): 2;\n\n\t\t\t\t\t\tfor (int opacity = 0; opacity < TransparenciesOpacityLevels; ++opacity)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// pseudo interpolation of palette color with tint\n\t\t\t\t\t\t\t// for small values `op` its should behave same as original TFTD\n\t\t\t\t\t\t\t// but for bigger values it make result closer to tint color\n\t\t\t\t\t\t\tconst int op = Clamp((opacity+1) * color.unused, 0, 64);\n\t\t\t\t\t\t\tconst float co = 1.0f - Sqr(op / 64.0f); // 1.0 -> 0.0\n\t\t\t\t\t\t\tconst float to = op * 1.0f; // 0.0 -> 64.0\n\n\t\t\t\t\t\t\tSDL_Color taint;\n\t\t\t\t\t\t\ttaint.r = Clamp((int)(color.r * to), 0, 255);\n\t\t\t\t\t\t\ttaint.g = Clamp((int)(color.g * to), 0, 255);\n\t\t\t\t\t\t\ttaint.b = Clamp((int)(color.b * to), 0, 255);\n\t\t\t\t\t\t\ttaint.unused = 255 * co;\n\t\t\t\t\t\t\t_transparencies[start + curr][opacity] = taint;\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tfor (int opacity = 0; opacity < TransparenciesOpacityLevels; ++opacity)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tconst auto& n = colorReader[opacity];\n\n\t\t\t\t\t\t\tSDL_Color taint;\n\t\t\t\t\t\t\ttaint.r = loadByteValue(n[0]);\n\t\t\t\t\t\t\ttaint.g = loadByteValue(n[1]);\n\t\t\t\t\t\t\ttaint.b = loadByteValue(n[2]);\n\t\t\t\t\t\t\ttaint.unused = 255 - loadByteValue(n[3]);\n\t\t\t\t\t\t\t_transparencies[start + curr][opacity] = taint;\n\t\t\t\t\t\t};\n\t\t\t\t\t\tstd::reverse(std::begin(_transparencies[start + curr]), std::end(_transparencies[start + curr]));\n\t\t\t\t\t}\n\t\t\t\t\tcurr++;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tthrow Exception(\"unknown transparencyLUTs node type\");\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Loads \"constants\" node.\n */\nvoid Mod::loadConstants(const YAML::YamlNodeReader &reader)\n{\n\tloadSoundOffset(\"constants\", DOOR_OPEN, reader[\"doorSound\"], \"BATTLE.CAT\");\n\tloadSoundOffset(\"constants\", SLIDING_DOOR_OPEN, reader[\"slidingDoorSound\"], \"BATTLE.CAT\");\n\tloadSoundOffset(\"constants\", SLIDING_DOOR_CLOSE, reader[\"slidingDoorClose\"], \"BATTLE.CAT\");\n\tloadSoundOffset(\"constants\", SMALL_EXPLOSION, reader[\"smallExplosion\"], \"BATTLE.CAT\");\n\tloadSoundOffset(\"constants\", LARGE_EXPLOSION, reader[\"largeExplosion\"], \"BATTLE.CAT\");\n\n\tloadSpriteOffset(\"constants\", EXPLOSION_OFFSET, reader[\"explosionOffset\"], \"X1.PCK\");\n\tloadSpriteOffset(\"constants\", SMOKE_OFFSET, reader[\"smokeOffset\"], \"SMOKE.PCK\");\n\tloadSpriteOffset(\"constants\", UNDERWATER_SMOKE_OFFSET, reader[\"underwaterSmokeOffset\"], \"SMOKE.PCK\");\n\n\tloadSoundOffset(\"constants\", ITEM_DROP, reader[\"itemDrop\"], \"BATTLE.CAT\");\n\tloadSoundOffset(\"constants\", ITEM_THROW, reader[\"itemThrow\"], \"BATTLE.CAT\");\n\tloadSoundOffset(\"constants\", ITEM_RELOAD, reader[\"itemReload\"], \"BATTLE.CAT\");\n\tloadSoundOffset(\"constants\", WALK_OFFSET, reader[\"walkOffset\"], \"BATTLE.CAT\");\n\tloadSoundOffset(\"constants\", FLYING_SOUND, reader[\"flyingSound\"], \"BATTLE.CAT\");\n\n\tloadSoundOffset(\"constants\", BUTTON_PRESS, reader[\"buttonPress\"], \"GEO.CAT\");\n\tif (const auto& arrayReader = reader[\"windowPopup\"])\n\t\tfor (size_t j = 0; j < std::size(WINDOW_POPUP); j++)\n\t\t\tloadSoundOffset(\"constants\", WINDOW_POPUP[j], arrayReader[j], \"GEO.CAT\");\n\n\tloadSoundOffset(\"constants\", UFO_FIRE, reader[\"ufoFire\"], \"GEO.CAT\");\n\tloadSoundOffset(\"constants\", UFO_HIT, reader[\"ufoHit\"], \"GEO.CAT\");\n\tloadSoundOffset(\"constants\", UFO_CRASH, reader[\"ufoCrash\"], \"GEO.CAT\");\n\tloadSoundOffset(\"constants\", UFO_EXPLODE, reader[\"ufoExplode\"], \"GEO.CAT\");\n\tloadSoundOffset(\"constants\", INTERCEPTOR_HIT, reader[\"interceptorHit\"], \"GEO.CAT\");\n\tloadSoundOffset(\"constants\", INTERCEPTOR_EXPLODE, reader[\"interceptorExplode\"], \"GEO.CAT\");\n\treader.tryRead(\"geoscapeCursor\", GEOSCAPE_CURSOR);\n\treader.tryRead(\"basescapeCursor\", BASESCAPE_CURSOR);\n\treader.tryRead(\"battlescapeCursor\", BATTLESCAPE_CURSOR);\n\treader.tryRead(\"ufopaediaCursor\", UFOPAEDIA_CURSOR);\n\treader.tryRead(\"graphsCursor\", GRAPHS_CURSOR);\n\treader.tryRead(\"damageRange\", DAMAGE_RANGE);\n\treader.tryRead(\"explosiveDamageRange\", EXPLOSIVE_DAMAGE_RANGE);\n\tif (const auto& arrayReader = reader[\"fireDamageRange\"])\n\t\tfor (size_t j = 0; j < std::size(FIRE_DAMAGE_RANGE); j++)\n\t\t\tarrayReader[j].tryReadVal(FIRE_DAMAGE_RANGE[j]);\n\treader.tryRead(\"goodDebriefingMusic\", DEBRIEF_MUSIC_GOOD);\n\treader.tryRead(\"badDebriefingMusic\", DEBRIEF_MUSIC_BAD);\n\tif (const auto& arrayReader = reader[\"extendedPediaFacilityParams\"])\n\t\tfor (size_t j = 0; j < std::size(PEDIA_FACILITY_RENDER_PARAMETERS); j++)\n\t\t\tarrayReader[j].tryReadVal(PEDIA_FACILITY_RENDER_PARAMETERS[j]);\n\treader.tryRead(\"extendedItemReloadCost\", EXTENDED_ITEM_RELOAD_COST);\n\treader.tryRead(\"extendedInventorySlotSorting\", EXTENDED_INVENTORY_SLOT_SORTING);\n\treader.tryRead(\"extendedRunningCost\", EXTENDED_RUNNING_COST);\n\treader.tryRead(\"extendedMovementCostRounding\", EXTENDED_MOVEMENT_COST_ROUNDING);\n\treader.tryRead(\"extendedHwpLoadOrder\", EXTENDED_HWP_LOAD_ORDER);\n\treader.tryRead(\"extendedSpotOnHitForSniping\", EXTENDED_SPOT_ON_HIT_FOR_SNIPING);\n\treader.tryRead(\"extendedBerserkWithAimed\", EXTENDED_BERSERK_WITH_AIMED);\n\treader.tryRead(\"extendedMeleeReactions\", EXTENDED_MELEE_REACTIONS);\n\treader.tryRead(\"extendedTerrainMelee\", EXTENDED_TERRAIN_MELEE);\n\treader.tryRead(\"extendedUnderwaterThrowFactor\", EXTENDED_UNDERWATER_THROW_FACTOR);\n\treader.tryRead(\"extendedExperienceAwardSystem\", EXTENDED_EXPERIENCE_AWARD_SYSTEM);\n\treader.tryRead(\"extendedForceSpawn\", EXTENDED_FORCE_SPAWN);\n\treader.tryRead(\"extendedSmokeOffset\", EXTENDED_SMOKE_OFFSET);\n\n\treader.tryRead(\"extendedCurrencySymbol\", OXCE_CURRENCY_SYMBOL);\n}\n\n/**\n * Loads a ruleset's contents from a YAML file.\n * Rules that match pre-existing rules overwrite them.\n * @param filename YAML filename.\n * @param parsers Object with all available parsers.\n */\nvoid Mod::loadFile(const FileMap::FileRecord &filerec, ModScript &parsers)\n{\n\tYAML::YamlRootNodeReader r = filerec.getYAML();\n\tYAML::YamlNodeReader reader = r.useIndex();\n\n\tauto loadDocInfoHelper = [&](const char* nodeName)\n\t{\n\t\tif (reader.hasValTag(InfoTag))\n\t\t{\n\t\t\tLogger info;\n\t\t\tinfo.get() << \"Available rule '\" << nodeName << \":'\";\n\t\t}\n\t\treturn reader[nodeName];\n\t};\n\n\tif (const auto& extended = loadDocInfoHelper(\"extended\"))\n\t{\n\t\tif (const auto& t = extended[\"tagsFile\"])\n\t\t{\n\t\t\tauto filePath = t.readVal<std::string>();\n\t\t\tauto file = FileMap::getModRuleFile(_modCurrent->info, filePath);\n\n\t\t\tif (false == checkForSoftError(file == nullptr, \"extended\", t, \"Unknown file name for 'tagsFile': '\" + filePath + \"'\", LOG_ERROR))\n\t\t\t{\n\t\t\t\t//copy only tags and load them in current file.\n\t\t\t\tconst YAML::YamlRootNodeReader& tempReader = file->getYAML();\n\t\t\t\tstd::map<std::string, std::map<std::string, std::string> > tempTags;\n\t\t\t\ttempReader[\"extended\"].tryRead(\"tags\", tempTags);\n\t\t\t\tYAML::YamlRootNodeWriter tempExtended;\n\t\t\t\ttempExtended.setAsMap();\n\t\t\t\ttempExtended.write(\"tags\", tempTags);\n\t\t\t\t_scriptGlobal->load(tempExtended.toReader());\n\t\t\t}\n\t\t}\n\n\t\t_scriptGlobal->load(extended);\n\t\t_scriptGlobal->getScriptValues().load(extended, parsers.getShared(), \"globals\");\n\t}\n\n\tauto iterateRules = [&](const char* nodeName, const char* type)\n\t{\n\t\tconst auto& node = loadDocInfoHelper(nodeName);\n\n\t\tloadRuleInfoHelper(node, nodeName, type);\n\n\t\treturn node.children();\n\t};\n\n\tauto iterateRulesSpecific = [&](const char* nodeName)\n\t{\n\t\tconst auto& node = loadDocInfoHelper(nodeName);\n\n\t\treturn node.children();\n\t};\n\n\n\n\tfor (const auto& ruleReader : iterateRules(\"countries\", \"type\"))\n\t{\n\t\tRuleCountry* rule = loadRule(ruleReader, &_countries, &_countriesIndex);\n\t\tif (rule != 0)\n\t\t{\n\t\t\trule->load(ruleReader, parsers, this);\n\t\t}\n\t}\n\tfor (const auto& ruleReader : iterateRules(\"extraGlobeLabels\", \"type\"))\n\t{\n\t\tRuleCountry *rule = loadRule(ruleReader, &_extraGlobeLabels, &_extraGlobeLabelsIndex);\n\t\tif (rule != 0)\n\t\t{\n\t\t\trule->load(ruleReader, parsers, this);\n\t\t}\n\t}\n\tfor (const auto& ruleReader : iterateRules(\"regions\", \"type\"))\n\t{\n\t\tRuleRegion *rule = loadRule(ruleReader, &_regions, &_regionsIndex);\n\t\tif (rule != 0)\n\t\t{\n\t\t\trule->load(ruleReader, this);\n\t\t}\n\t}\n\tfor (const auto& ruleReader : iterateRules(\"facilities\", \"type\"))\n\t{\n\t\tRuleBaseFacility *rule = loadRule(ruleReader, &_facilities, &_facilitiesIndex, \"type\", RuleListOrderedFactory<RuleBaseFacility>{ _facilityListOrder, 100 });\n\t\tif (rule != 0)\n\t\t{\n\t\t\trule->load(ruleReader, this);\n\t\t}\n\t}\n\tfor (const auto& ruleReader : iterateRules(\"crafts\", \"type\"))\n\t{\n\t\tRuleCraft *rule = loadRule(ruleReader, &_crafts, &_craftsIndex, \"type\", RuleListOrderedFactory<RuleCraft>{ _craftListOrder, 100 });\n\t\tif (rule != 0)\n\t\t{\n\t\t\trule->load(ruleReader, this, parsers);\n\t\t}\n\t}\n\tfor (const auto& ruleReader : iterateRules(\"craftWeapons\", \"type\"))\n\t{\n\t\tRuleCraftWeapon *rule = loadRule(ruleReader, &_craftWeapons, &_craftWeaponsIndex);\n\t\tif (rule != 0)\n\t\t{\n\t\t\trule->load(ruleReader, this);\n\t\t}\n\t}\n\tfor (const auto& ruleReader : iterateRules(\"itemCategories\", \"type\"))\n\t{\n\t\tRuleItemCategory *rule = loadRule(ruleReader, &_itemCategories, &_itemCategoriesIndex, \"type\", RuleListOrderedFactory<RuleItemCategory>{ _itemCategoryListOrder, 100 });\n\t\tif (rule != 0)\n\t\t{\n\t\t\trule->load(ruleReader, this);\n\t\t}\n\t}\n\tfor (const auto& ruleReader : iterateRules(\"items\", \"type\"))\n\t{\n\t\tRuleItem *rule = loadRule(ruleReader, &_items, &_itemsIndex, \"type\", RuleListOrderedFactory<RuleItem>{ _itemListOrder, 100 });\n\t\tif (rule != 0)\n\t\t{\n\t\t\trule->load(ruleReader, this, parsers);\n\t\t}\n\t}\n\tfor (const auto& ruleReader : iterateRules(\"weaponSets\", \"type\"))\n\t{\n\t\tRuleWeaponSet* rule = loadRule(ruleReader, &_weaponSets);\n\t\tif (rule != 0)\n\t\t{\n\t\t\trule->load(ruleReader, this);\n\t\t}\n\t}\n\tfor (const auto& ruleReader : iterateRules(\"ufos\", \"type\"))\n\t{\n\t\tRuleUfo *rule = loadRule(ruleReader, &_ufos, &_ufosIndex);\n\t\tif (rule != 0)\n\t\t{\n\t\t\trule->load(ruleReader, this, parsers);\n\t\t}\n\t}\n\tfor (const auto& ruleReader : iterateRules(\"invs\", \"id\"))\n\t{\n\t\tRuleInventory *rule = loadRule(ruleReader, &_invs, &_invsIndex, \"id\", RuleListOrderedFactory<RuleInventory>{ _invListOrder, 10 });\n\t\tif (rule != 0)\n\t\t{\n\t\t\trule->load(ruleReader);\n\t\t}\n\t}\n\tfor (const auto& ruleReader : iterateRules(\"terrains\", \"name\"))\n\t{\n\t\tRuleTerrain *rule = loadRule(ruleReader, &_terrains, &_terrainIndex, \"name\");\n\t\tif (rule != 0)\n\t\t{\n\t\t\trule->load(ruleReader, this);\n\t\t}\n\t}\n\n\tfor (const auto& ruleReader : iterateRules(\"armors\", \"type\"))\n\t{\n\t\tArmor *rule = loadRule(ruleReader, &_armors, &_armorsIndex, \"type\", RuleListOrderedFactory<Armor>{ _armorListOrder, 100 });\n\t\tif (rule != 0)\n\t\t{\n\t\t\trule->load(ruleReader, this, parsers);\n\t\t}\n\t}\n\tfor (const auto& ruleReader : iterateRules(\"skills\", \"type\"))\n\t{\n\t\tRuleSkill *rule = loadRule(ruleReader, &_skills, &_skillsIndex);\n\t\tif (rule != 0)\n\t\t{\n\t\t\trule->load(ruleReader, this, parsers);\n\t\t}\n\t}\n\tfor (const auto& ruleReader : iterateRules(\"soldiers\", \"type\"))\n\t{\n\t\tRuleSoldier *rule = loadRule(ruleReader, &_soldiers, &_soldiersIndex, \"type\", RuleListOrderedFactory<RuleSoldier>{ _soldierListOrder, 1 });\n\t\tif (rule != 0)\n\t\t{\n\t\t\trule->load(ruleReader, this, parsers);\n\t\t}\n\t}\n\tfor (const auto& ruleReader : iterateRules(\"units\", \"type\"))\n\t{\n\t\tUnit *rule = loadRule(ruleReader, &_units);\n\t\tif (rule != 0)\n\t\t{\n\t\t\trule->load(ruleReader, this);\n\t\t}\n\t}\n\tfor (const auto& ruleReader : iterateRules(\"alienRaces\", \"id\"))\n\t{\n\t\tAlienRace *rule = loadRule(ruleReader, &_alienRaces, &_aliensIndex, \"id\", RuleListOrderedFactory<AlienRace>{ _alienRaceListOrder, 100 });\n\t\tif (rule != 0)\n\t\t{\n\t\t\trule->load(ruleReader, this);\n\t\t}\n\t}\n\tfor (const auto& ruleReader : iterateRules(\"enviroEffects\", \"type\"))\n\t{\n\t\tRuleEnviroEffects* rule = loadRule(ruleReader, &_enviroEffects, &_enviroEffectsIndex);\n\t\tif (rule != 0)\n\t\t{\n\t\t\trule->load(ruleReader, this);\n\t\t}\n\t}\n\tfor (const auto& ruleReader : iterateRules(\"startingConditions\", \"type\"))\n\t{\n\t\tRuleStartingCondition *rule = loadRule(ruleReader, &_startingConditions, &_startingConditionsIndex);\n\t\tif (rule != 0)\n\t\t{\n\t\t\trule->load(ruleReader, this);\n\t\t}\n\t}\n\tfor (const auto& ruleReader : iterateRules(\"alienDeployments\", \"type\"))\n\t{\n\t\tAlienDeployment *rule = loadRule(ruleReader, &_alienDeployments, &_deploymentsIndex);\n\t\tif (rule != 0)\n\t\t{\n\t\t\trule->load(ruleReader, this);\n\t\t}\n\t}\n\tfor (const auto& ruleReader : iterateRules(\"research\", \"name\"))\n\t{\n\t\tRuleResearch *rule = loadRule(ruleReader, &_research, &_researchIndex, \"name\", RuleListOrderedFactory<RuleResearch>{ _researchListOrder, 100 });\n\t\tif (rule != 0)\n\t\t{\n\t\t\trule->load(ruleReader, this, parsers);\n\t\t}\n\t}\n\tfor (const auto& ruleReader : iterateRules(\"manufacture\", \"name\"))\n\t{\n\t\tRuleManufacture *rule = loadRule(ruleReader, &_manufacture, &_manufactureIndex, \"name\", RuleListOrderedFactory<RuleManufacture>{ _manufactureListOrder, 100 });\n\t\tif (rule != 0)\n\t\t{\n\t\t\trule->load(ruleReader, this);\n\t\t}\n\t}\n\tfor (const auto& ruleReader : iterateRules(\"manufactureShortcut\", \"name\"))\n\t{\n\t\tRuleManufactureShortcut *rule = loadRule(ruleReader, &_manufactureShortcut, 0, \"name\");\n\t\tif (rule != 0)\n\t\t{\n\t\t\trule->load(ruleReader);\n\t\t}\n\t}\n\tfor (const auto& ruleReader : iterateRules(\"soldierBonuses\", \"name\"))\n\t{\n\t\tRuleSoldierBonus *rule = loadRule(ruleReader, &_soldierBonus, &_soldierBonusIndex, \"name\", RuleListOrderedFactory<RuleSoldierBonus>{ _soldierBonusListOrder, 100 });\n\t\tif (rule != 0)\n\t\t{\n\t\t\trule->load(ruleReader, this, parsers);\n\t\t}\n\t}\n\tfor (const auto& ruleReader : iterateRules(\"soldierTransformation\", \"name\"))\n\t{\n\t\tRuleSoldierTransformation *rule = loadRule(ruleReader, &_soldierTransformation, &_soldierTransformationIndex, \"name\", RuleListOrderedFactory<RuleSoldierTransformation>{ _transformationListOrder, 100 });\n\t\tif (rule != 0)\n\t\t{\n\t\t\trule->load(ruleReader, this);\n\t\t}\n\t}\n\tfor (const auto& ruleReader : iterateRules(\"commendations\", \"type\"))\n\t{\n\t\tRuleCommendations *rule = loadRule(ruleReader, &_commendations);\n\t\tif (rule != 0)\n\t\t{\n\t\t\trule->load(ruleReader, this);\n\t\t}\n\t}\n\n\n\n\tfor (const auto& ruleReader : iterateRules(\"ufoTrajectories\", \"id\"))\n\t{\n\t\tUfoTrajectory *rule = loadRule(ruleReader, &_ufoTrajectories, 0, \"id\");\n\t\tif (rule != 0)\n\t\t{\n\t\t\trule->load(ruleReader);\n\t\t}\n\t}\n\tfor (const auto& ruleReader : iterateRules(\"alienMissions\", \"type\"))\n\t{\n\t\tRuleAlienMission *rule = loadRule(ruleReader, &_alienMissions, &_alienMissionsIndex);\n\t\tif (rule != 0)\n\t\t{\n\t\t\trule->load(ruleReader);\n\t\t}\n\t}\n\tfor (const auto& ruleReader : iterateRules(\"arcScripts\", \"type\"))\n\t{\n\t\tRuleArcScript* rule = loadRule(ruleReader, &_arcScripts, &_arcScriptIndex, \"type\");\n\t\tif (rule != 0)\n\t\t{\n\t\t\trule->load(ruleReader);\n\t\t}\n\t}\n\tfor (const auto& ruleReader : iterateRules(\"eventScripts\", \"type\"))\n\t{\n\t\tRuleEventScript* rule = loadRule(ruleReader, &_eventScripts, &_eventScriptIndex, \"type\");\n\t\tif (rule != 0)\n\t\t{\n\t\t\trule->load(ruleReader);\n\t\t}\n\t}\n\tfor (const auto& ruleReader : iterateRules(\"events\", \"name\"))\n\t{\n\t\tRuleEvent* rule = loadRule(ruleReader, &_events, &_eventIndex, \"name\");\n\t\tif (rule != 0)\n\t\t{\n\t\t\trule->load(ruleReader);\n\t\t}\n\t}\n\tfor (const auto& ruleReader : iterateRules(\"missionScripts\", \"type\"))\n\t{\n\t\tRuleMissionScript *rule = loadRule(ruleReader, &_missionScripts, &_missionScriptIndex, \"type\");\n\t\tif (rule != 0)\n\t\t{\n\t\t\trule->load(ruleReader);\n\t\t}\n\t}\n\tfor (const auto& ruleReader : iterateRules(\"adhocScripts\", \"type\"))\n\t{\n\t\tRuleMissionScript* rule = loadRule(ruleReader, &_adhocScripts, &_adhocScriptIndex, \"type\");\n\t\tif (rule != 0)\n\t\t{\n\t\t\trule->load(ruleReader);\n\t\t}\n\t}\n\n\n\n\tfor (const auto& ruleReader : iterateRulesSpecific(\"mapScripts\"))\n\t{\n\t\tstd::string type = ruleReader[\"type\"].readVal<std::string>();\n\t\tif (ruleReader[\"delete\"])\n\t\t{\n\t\t\ttype = ruleReader[\"delete\"].readVal<std::string>(type);\n\t\t}\n\t\tif (_mapScripts.find(type) != _mapScripts.end())\n\t\t{\n\t\t\tCollections::deleteAll(_mapScripts[type]);\n\t\t}\n\t\tfor (const auto& commandsReader : ruleReader[\"commands\"].children())\n\t\t{\n\t\t\tMapScript *mapScript = new MapScript();\n\t\t\tmapScript->load(commandsReader);\n\t\t\t_mapScripts[type].push_back(mapScript);\n\t\t}\n\t}\n\n\n\n\tfor (const auto& ruleReader : iterateRulesSpecific(\"ufopaedia\"))\n\t{\n\t\tif (ruleReader[\"id\"])\n\t\t{\n\t\t\tstd::string id = ruleReader[\"id\"].readVal<std::string>();\n\t\t\tArticleDefinition *rule;\n\t\t\tif (_ufopaediaArticles.find(id) != _ufopaediaArticles.end())\n\t\t\t{\n\t\t\t\trule = _ufopaediaArticles[id];\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (!ruleReader[\"type_id\"]) { // otherwise it throws and I wasted hours\n\t\t\t\t\tLog(LOG_ERROR) << \"ufopaedia item misses type_id attribute.\";\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tUfopaediaTypeId type = ruleReader[\"type_id\"].readVal<UfopaediaTypeId>();\n\t\t\t\tswitch (type)\n\t\t\t\t{\n\t\t\t\tcase UFOPAEDIA_TYPE_UNIT: rule = new ArticleDefinitionUnit(); break;\n\t\t\t\tcase UFOPAEDIA_TYPE_SOLDIER: rule = new ArticleDefinitionSoldier(); break;\n\t\t\t\tcase UFOPAEDIA_TYPE_CRAFT: rule = new ArticleDefinitionCraft(); break;\n\t\t\t\tcase UFOPAEDIA_TYPE_CRAFT_WEAPON: rule = new ArticleDefinitionCraftWeapon(); break;\n\t\t\t\tcase UFOPAEDIA_TYPE_VEHICLE: rule = new ArticleDefinitionVehicle(); break;\n\t\t\t\tcase UFOPAEDIA_TYPE_ITEM: rule = new ArticleDefinitionItem(); break;\n\t\t\t\tcase UFOPAEDIA_TYPE_ARMOR: rule = new ArticleDefinitionArmor(); break;\n\t\t\t\tcase UFOPAEDIA_TYPE_BASE_FACILITY: rule = new ArticleDefinitionBaseFacility(); break;\n\t\t\t\tcase UFOPAEDIA_TYPE_TEXTIMAGE: rule = new ArticleDefinitionTextImage(); break;\n\t\t\t\tcase UFOPAEDIA_TYPE_TEXT: rule = new ArticleDefinitionText(); break;\n\t\t\t\tcase UFOPAEDIA_TYPE_UFO: rule = new ArticleDefinitionUfo(); break;\n\t\t\t\tcase UFOPAEDIA_TYPE_TFTD:\n\t\t\t\tcase UFOPAEDIA_TYPE_TFTD_CRAFT:\n\t\t\t\tcase UFOPAEDIA_TYPE_TFTD_CRAFT_WEAPON:\n\t\t\t\tcase UFOPAEDIA_TYPE_TFTD_VEHICLE:\n\t\t\t\tcase UFOPAEDIA_TYPE_TFTD_ITEM:\n\t\t\t\tcase UFOPAEDIA_TYPE_TFTD_ARMOR:\n\t\t\t\tcase UFOPAEDIA_TYPE_TFTD_BASE_FACILITY:\n\t\t\t\tcase UFOPAEDIA_TYPE_TFTD_USO:\n\t\t\t\t\trule = new ArticleDefinitionTFTD();\n\t\t\t\t\tbreak;\n\t\t\t\tdefault: rule = 0; break;\n\t\t\t\t}\n\t\t\t\t_ufopaediaArticles[id] = rule;\n\t\t\t\t_ufopaediaIndex.push_back(id);\n\t\t\t}\n\t\t\t_ufopaediaListOrder += 100;\n\t\t\trule->load(ruleReader, _ufopaediaListOrder);\n\t\t}\n\t\telse if (ruleReader[\"delete\"])\n\t\t{\n\t\t\tstd::string type = ruleReader[\"delete\"].readVal<std::string>();\n\t\t\tauto j = _ufopaediaArticles.find(type);\n\t\t\tif (j != _ufopaediaArticles.end())\n\t\t\t{\n\t\t\t\t_ufopaediaArticles.erase(j);\n\t\t\t}\n\t\t\tauto idx = std::find(_ufopaediaIndex.begin(), _ufopaediaIndex.end(), type);\n\t\t\tif (idx != _ufopaediaIndex.end())\n\t\t\t{\n\t\t\t\t_ufopaediaIndex.erase(idx);\n\t\t\t}\n\t\t}\n\t}\n\n\n\n\tauto loadStartingBase = [&](const char* startingBaseType, YAML::YamlString& destRef)\n\t{\n\t\t// Bases can't be copied, so for savegame purposes we store the node instead\n\t\tconst auto& base = loadDocInfoHelper(startingBaseType);\n\t\tif (base)\n\t\t{\n\t\t\tif (isMapHelper(base))\n\t\t\t{\n\t\t\t\tdestRef = base.emitDescendants(YAML::YamlRootNodeReader(destRef, \"(starting base template)\"));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tthrow LoadRuleException(startingBaseType, base, \"expected normal map node\");\n\t\t\t}\n\t\t}\n\t};\n\tloadStartingBase(\"startingBase\", _startingBaseDefault);\n\tloadStartingBase(\"startingBaseBeginner\", _startingBaseBeginner);\n\tloadStartingBase(\"startingBaseExperienced\", _startingBaseExperienced);\n\tloadStartingBase(\"startingBaseVeteran\", _startingBaseVeteran);\n\tloadStartingBase(\"startingBaseGenius\", _startingBaseGenius);\n\tloadStartingBase(\"startingBaseSuperhuman\", _startingBaseSuperhuman);\n\n\tif (reader[\"startingTime\"])\n\t{\n\t\t_startingTime.load(reader[\"startingTime\"]);\n\t}\n\treader.tryRead(\"startingDifficulty\", _startingDifficulty);\n\treader.tryRead(\"maxViewDistance\", _maxViewDistance);\n\treader.tryRead(\"maxDarknessToSeeUnits\", _maxDarknessToSeeUnits);\n\treader.tryRead(\"costHireEngineer\", _costHireEngineer);\n\treader.tryRead(\"costHireScientist\", _costHireScientist);\n\treader.tryRead(\"costEngineer\", _costEngineer);\n\treader.tryRead(\"costScientist\", _costScientist);\n\treader.tryRead(\"timePersonnel\", _timePersonnel);\n\treader.tryRead(\"hireByCountryOdds\", _hireByCountryOdds);\n\treader.tryRead(\"hireByRegionOdds\", _hireByRegionOdds);\n\treader.tryRead(\"initialFunding\", _initialFunding);\n\tif (const auto& nodeTransferCosts = loadDocInfoHelper(\"transferCosts\"))\n\t{\n\t\tnodeTransferCosts.tryRead(\"globalCostMult\", _globalTransferCostMult);\n\t\tnodeTransferCosts.tryRead(\"globalCostDiv\", _globalTransferCostDiv);\n\t}\n\treader.tryRead(\"alienFuel\", _alienFuel);\n\treader.tryRead(\"fontName\", _fontName);\n\treader.tryRead(\"psiUnlockResearch\", _psiUnlockResearch);\n\treader.tryRead(\"fakeUnderwaterBaseUnlockResearch\", _fakeUnderwaterBaseUnlockResearch);\n\treader.tryRead(\"newBaseUnlockResearch\", _newBaseUnlockResearch);\n\treader.tryRead(\"hireScientistsUnlockResearch\", _hireScientistsUnlockResearch);\n\treader.tryRead(\"hireEngineersUnlockResearch\", _hireEngineersUnlockResearch);\n\tloadBaseFunction(\"mod\", _hireScientistsRequiresBaseFunc, reader[\"hireScientistsRequiresBaseFunc\"]);\n\tloadBaseFunction(\"mod\", _hireEngineersRequiresBaseFunc, reader[\"hireEngineersRequiresBaseFunc\"]);\n\treader.tryRead(\"destroyedFacility\", _destroyedFacility);\n\n\treader.tryRead(\"turnAIUseGrenade\", _aiUseDelayGrenade);\n\treader.tryRead(\"turnAIUseBlaster\", _aiUseDelayBlaster);\n\tif (const auto& nodeAI = loadDocInfoHelper(\"ai\"))\n\t{\n\t\tnodeAI.tryRead(\"useDelayBlaster\", _aiUseDelayBlaster);\n\t\tnodeAI.tryRead(\"useDelayFirearm\", _aiUseDelayFirearm);\n\t\tnodeAI.tryRead(\"useDelayGrenade\", _aiUseDelayGrenade);\n\t\tnodeAI.tryRead(\"aiUseDelayProxy\", _aiUseDelayProxy);\n\t\tnodeAI.tryRead(\"useDelayMelee\", _aiUseDelayMelee);\n\t\tnodeAI.tryRead(\"useDelayPsionic\", _aiUseDelayPsionic);\n\t\tnodeAI.tryRead(\"useDelayMedikit\", _aiUseDelayMedikit);\n\n\t\tnodeAI.tryRead(\"fireChoiceIntelCoeff\", _aiFireChoiceIntelCoeff);\n\t\tnodeAI.tryRead(\"fireChoiceAggroCoeff\", _aiFireChoiceAggroCoeff);\n\t\tnodeAI.tryRead(\"extendedFireModeChoice\", _aiExtendedFireModeChoice);\n\t\tnodeAI.tryRead(\"respectMaxRange\", _aiRespectMaxRange);\n\t\tnodeAI.tryRead(\"destroyBaseFacilities\", _aiDestroyBaseFacilities);\n\t\tnodeAI.tryRead(\"pickUpWeaponsMoreActively\", _aiPickUpWeaponsMoreActively);\n\t\tnodeAI.tryRead(\"pickUpWeaponsMoreActivelyCiv\", _aiPickUpWeaponsMoreActivelyCiv);\n\t\tnodeAI.tryRead(\"reactionFireThreshold\", _aiReactionFireThreshold);\n\t\tnodeAI.tryRead(\"reactionFireThresholdCiv\", _aiReactionFireThresholdCiv);\n\n\t\tnodeAI.tryRead(\"targetWeightThreatThreshold\", _aiTargetWeightThreatThreshold);\n\t\tnodeAI.tryRead(\"targetWeightAsHostile\", _aiTargetWeightAsHostile);\n\t\tnodeAI.tryRead(\"targetWeightAsHostileCivilians\", _aiTargetWeightAsHostileCivilians);\n\t\tnodeAI.tryRead(\"targetWeightAsFriendly\", _aiTargetWeightAsFriendly);\n\t\tnodeAI.tryRead(\"targetWeightAsNeutral\", _aiTargetWeightAsNeutral);\n\t}\n\treader.tryRead(\"maxLookVariant\", _maxLookVariant);\n\treader.tryRead(\"tooMuchSmokeThreshold\", _tooMuchSmokeThreshold);\n\treader.tryRead(\"customTrainingFactor\", _customTrainingFactor);\n\treader.tryRead(\"chanceToStopRetaliation\", _chanceToStopRetaliation);\n\treader.tryRead(\"chanceToDetectAlienBaseEachMonth\", _chanceToDetectAlienBaseEachMonth);\n\treader.tryRead(\"lessAliensDuringBaseDefense\", _lessAliensDuringBaseDefense);\n\treader.tryRead(\"allowCountriesToCancelAlienPact\", _allowCountriesToCancelAlienPact);\n\treader.tryRead(\"buildInfiltrationBaseCloseToTheCountry\", _buildInfiltrationBaseCloseToTheCountry);\n\treader.tryRead(\"infiltrateRandomCountryInTheRegion\", _infiltrateRandomCountryInTheRegion);\n\treader.tryRead(\"allowAlienBasesOnWrongTextures\", _allowAlienBasesOnWrongTextures);\n\treader.tryRead(\"kneelBonusGlobal\", _kneelBonusGlobal);\n\treader.tryRead(\"oneHandedPenaltyGlobal\", _oneHandedPenaltyGlobal);\n\treader.tryRead(\"enableCloseQuartersCombat\", _enableCloseQuartersCombat);\n\treader.tryRead(\"closeQuartersAccuracyGlobal\", _closeQuartersAccuracyGlobal);\n\treader.tryRead(\"closeQuartersTuCostGlobal\", _closeQuartersTuCostGlobal);\n\treader.tryRead(\"closeQuartersEnergyCostGlobal\", _closeQuartersEnergyCostGlobal);\n\treader.tryRead(\"closeQuartersSneakUpGlobal\", _closeQuartersSneakUpGlobal);\n\treader.tryRead(\"noLOSAccuracyPenaltyGlobal\", _noLOSAccuracyPenaltyGlobal);\n\treader.tryRead(\"explodeInventoryGlobal\", _explodeInventoryGlobal);\n\treader.tryRead(\"surrenderMode\", _surrenderMode);\n\treader.tryRead(\"bughuntMinTurn\", _bughuntMinTurn);\n\treader.tryRead(\"bughuntMaxEnemies\", _bughuntMaxEnemies);\n\treader.tryRead(\"bughuntRank\", _bughuntRank);\n\treader.tryRead(\"bughuntLowMorale\", _bughuntLowMorale);\n\treader.tryRead(\"bughuntTimeUnitsLeft\", _bughuntTimeUnitsLeft);\n\n\n\tif (const auto& nodeMana = loadDocInfoHelper(\"mana\"))\n\t{\n\t\tnodeMana.tryRead(\"enabled\", _manaEnabled);\n\t\tnodeMana.tryRead(\"battleUI\", _manaBattleUI);\n\t\tnodeMana.tryRead(\"unlockResearch\", _manaUnlockResearch);\n\t\tnodeMana.tryRead(\"trainingPrimary\", _manaTrainingPrimary);\n\t\tnodeMana.tryRead(\"trainingSecondary\", _manaTrainingSecondary);\n\n\t\tnodeMana.tryRead(\"woundThreshold\", _manaMissingWoundThreshold);\n\t\tnodeMana.tryRead(\"replenishAfterMission\", _manaReplenishAfterMission);\n\t}\n\tif (const auto& nodeHealth = loadDocInfoHelper(\"health\"))\n\t{\n\t\tnodeHealth.tryRead(\"woundThreshold\", _healthMissingWoundThreshold);\n\t\tnodeHealth.tryRead(\"replenishAfterMission\", _healthReplenishAfterMission);\n\t}\n\n\n\tif (const auto& nodeGameOver = loadDocInfoHelper(\"gameOver\"))\n\t{\n\t\tnodeGameOver.tryRead(\"loseMoney\", _loseMoney);\n\t\tnodeGameOver.tryRead(\"loseRating\", _loseRating);\n\t\tnodeGameOver.tryRead(\"loseDefeat\", _loseDefeat);\n\t}\n\treader.tryRead(\"ufoGlancingHitThreshold\", _ufoGlancingHitThreshold);\n\treader.tryRead(\"ufoBeamWidthParameter\", _ufoBeamWidthParameter);\n\tif (const auto& arrayReader = reader[\"ufoTractorBeamSizeModifiers\"])\n\t{\n\t\tfor (size_t j = 0; j < std::size(_ufoTractorBeamSizeModifiers); j++)\n\t\t\tarrayReader[j].tryReadVal(_ufoTractorBeamSizeModifiers[j]);\n\t}\n\treader.tryRead(\"escortRange\", _escortRange);\n\treader.tryRead(\"drawEnemyRadarCircles\", _drawEnemyRadarCircles);\n\treader.tryRead(\"escortsJoinFightAgainstHK\", _escortsJoinFightAgainstHK);\n\treader.tryRead(\"hunterKillerFastRetarget\", _hunterKillerFastRetarget);\n\treader.tryRead(\"crewEmergencyEvacuationSurvivalChance\", _crewEmergencyEvacuationSurvivalChance);\n\treader.tryRead(\"pilotsEmergencyEvacuationSurvivalChance\", _pilotsEmergencyEvacuationSurvivalChance);\n\treader.tryRead(\"showUfoPreviewInBaseDefense\", _showUfoPreviewInBaseDefense);\n\treader.tryRead(\"soldiersPerSergeant\", _soldiersPerRank[RANK_SERGEANT]);\n\treader.tryRead(\"soldiersPerCaptain\", _soldiersPerRank[RANK_CAPTAIN]);\n\treader.tryRead(\"soldiersPerColonel\", _soldiersPerRank[RANK_COLONEL]);\n\treader.tryRead(\"soldiersPerCommander\", _soldiersPerRank[RANK_COMMANDER]);\n\treader.tryRead(\"pilotAccuracyZeroPoint\", _pilotAccuracyZeroPoint);\n\treader.tryRead(\"pilotAccuracyRange\", _pilotAccuracyRange);\n\treader.tryRead(\"pilotReactionsZeroPoint\", _pilotReactionsZeroPoint);\n\treader.tryRead(\"pilotReactionsRange\", _pilotReactionsRange);\n\tif (const auto& arrayReader = reader[\"pilotBraveryThresholds\"])\n\t{\n\t\tfor (size_t j = 0; j < std::size(_pilotBraveryThresholds); j++)\n\t\t\tarrayReader[j].tryReadVal(_pilotBraveryThresholds[j]);\n\t}\n\treader.tryRead(\"performanceBonusFactor\", _performanceBonusFactor);\n\treader.tryRead(\"enableNewResearchSorting\", _enableNewResearchSorting);\n\treader.tryRead(\"displayCustomCategories\", _displayCustomCategories);\n\treader.tryRead(\"shareAmmoCategories\", _shareAmmoCategories);\n\treader.tryRead(\"showDogfightDistanceInKm\", _showDogfightDistanceInKm);\n\treader.tryRead(\"showFullNameInAlienInventory\", _showFullNameInAlienInventory);\n\treader.tryRead(\"alienInventoryOffsetX\", _alienInventoryOffsetX);\n\treader.tryRead(\"alienInventoryOffsetBigUnit\", _alienInventoryOffsetBigUnit);\n\treader.tryRead(\"hidePediaInfoButton\", _hidePediaInfoButton);\n\treader.tryRead(\"extraNerdyPediaInfoType\", _extraNerdyPediaInfoType);\n\treader.tryRead(\"giveScoreAlsoForResearchedArtifacts\", _giveScoreAlsoForResearchedArtifacts);\n\treader.tryRead(\"statisticalBulletConservation\", _statisticalBulletConservation);\n\treader.tryRead(\"stunningImprovesMorale\", _stunningImprovesMorale);\n\treader.tryRead(\"tuRecoveryWakeUpNewTurn\", _tuRecoveryWakeUpNewTurn);\n\treader.tryRead(\"shortRadarRange\", _shortRadarRange);\n\treader.tryRead(\"buildTimeReductionScaling\", _buildTimeReductionScaling);\n\treader.tryRead(\"baseDefenseMapFromLocation\", _baseDefenseMapFromLocation);\n\treader.tryRead(\"pediaReplaceCraftFuelWithRangeType\", _pediaReplaceCraftFuelWithRangeType);\n\treader.tryRead(\"missionRatings\", _missionRatings);\n\treader.tryRead(\"monthlyRatings\", _monthlyRatings);\n\tloadUnorderedNamesToNames(\"mod\", _fixedUserOptions, reader[\"fixedUserOptions\"]);\n\tloadUnorderedNamesToNames(\"mod\", _recommendedUserOptions, reader[\"recommendedUserOptions\"]);\n\tloadUnorderedNames(\"mod\", _hiddenMovementBackgrounds, reader[\"hiddenMovementBackgrounds\"]);\n\tloadUnorderedNames(\"mod\", _baseNamesFirst, reader[\"baseNamesFirst\"]);\n\tloadUnorderedNames(\"mod\", _baseNamesMiddle, reader[\"baseNamesMiddle\"]);\n\tloadUnorderedNames(\"mod\", _baseNamesLast, reader[\"baseNamesLast\"]);\n\tloadUnorderedNames(\"mod\", _operationNamesFirst, reader[\"operationNamesFirst\"]);\n\tloadUnorderedNames(\"mod\", _operationNamesLast, reader[\"operationNamesLast\"]);\n\treader.tryRead(\"disableUnderwaterSounds\", _disableUnderwaterSounds);\n\treader.tryRead(\"enableUnitResponseSounds\", _enableUnitResponseSounds);\n\tfor (const auto& unitResponseSound : iterateRulesSpecific(\"unitResponseSounds\"))\n\t{\n\t\tstd::string type = unitResponseSound[\"name\"].readVal<std::string>();\n\t\tif (unitResponseSound[\"selectUnitSound\"])\n\t\t\tloadSoundOffset(type, _selectUnitSound[type], unitResponseSound[\"selectUnitSound\"], \"BATTLE.CAT\");\n\t\tif (unitResponseSound[\"startMovingSound\"])\n\t\t\tloadSoundOffset(type, _startMovingSound[type], unitResponseSound[\"startMovingSound\"], \"BATTLE.CAT\");\n\t\tif (unitResponseSound[\"selectWeaponSound\"])\n\t\t\tloadSoundOffset(type, _selectWeaponSound[type], unitResponseSound[\"selectWeaponSound\"], \"BATTLE.CAT\");\n\t\tif (unitResponseSound[\"annoyedSound\"])\n\t\t\tloadSoundOffset(type, _annoyedSound[type], unitResponseSound[\"annoyedSound\"], \"BATTLE.CAT\");\n\t}\n\tloadSoundOffset(\"global\", _selectBaseSound, reader[\"selectBaseSound\"], \"BATTLE.CAT\");\n\tloadSoundOffset(\"global\", _startDogfightSound, reader[\"startDogfightSound\"], \"BATTLE.CAT\");\n\treader.tryRead(\"flagByKills\", _flagByKills);\n\treader.tryRead(\"defeatScore\", _defeatScore);\n\treader.tryRead(\"defeatFunds\", _defeatFunds);\n\treader.tryRead(\"difficultyDemigod\", _difficultyDemigod);\n\n\tif (const auto& difficultyCoefficientOverrides = loadDocInfoHelper(\"difficultyCoefficientOverrides\"))\n\t{\n\t\tdifficultyCoefficientOverrides.tryRead(\"monthlyRatingThresholds\", _monthlyRatingThresholds);\n\t\tdifficultyCoefficientOverrides.tryRead(\"ufoFiringRateCoefficients\", _ufoFiringRateCoefficients);\n\t\tdifficultyCoefficientOverrides.tryRead(\"ufoEscapeCountdownCoefficients\", _ufoEscapeCountdownCoefficients);\n\t\tdifficultyCoefficientOverrides.tryRead(\"retaliationTriggerOdds\", _retaliationTriggerOdds);\n\t\tdifficultyCoefficientOverrides.tryRead(\"retaliationBaseRegionOdds\", _retaliationBaseRegionOdds);\n\t\tdifficultyCoefficientOverrides.tryRead(\"aliensFacingCraftOdds\", _aliensFacingCraftOdds);\n\t}\n\n\tif (const auto& arrayReader = reader[\"difficultyCoefficient\"])\n\t{\n\t\tfor (size_t j = 0; j < std::size(DIFFICULTY_COEFFICIENT); j++)\n\t\t{\n\t\t\tarrayReader[j].tryReadVal(DIFFICULTY_COEFFICIENT[j]);\n\t\t\t_statAdjustment[j].growthMultiplier = DIFFICULTY_COEFFICIENT[j];\n\t\t}\n\t}\n\tif (const auto& arrayReader = reader[\"sellPriceCoefficient\"])\n\t{\n\t\tfor (size_t j = 0; j < std::size(SELL_PRICE_COEFFICIENT); j++)\n\t\t\tarrayReader[j].tryReadVal(SELL_PRICE_COEFFICIENT[j]);\n\t}\n\tif (const auto& arrayReader = reader[\"buyPriceCoefficient\"])\n\t{\n\t\tfor (size_t j = 0; j < std::size(BUY_PRICE_COEFFICIENT); j++)\n\t\t\tarrayReader[j].tryReadVal(BUY_PRICE_COEFFICIENT[j]);\n\t}\n\tif (const auto& arrayReader = reader[\"difficultyBasedRetaliationDelay\"])\n\t{\n\t\tfor (size_t j = 0; j < std::size(DIFFICULTY_BASED_RETAL_DELAY); j++)\n\t\t\tarrayReader[j].tryReadVal(DIFFICULTY_BASED_RETAL_DELAY[j]);\n\t}\n\tif (const auto& arrayReader = reader[\"unitResponseSoundsFrequency\"])\n\t{\n\t\tfor (size_t j = 0; j < std::size(UNIT_RESPONSE_SOUNDS_FREQUENCY); j++)\n\t\t\tarrayReader[j].tryReadVal(UNIT_RESPONSE_SOUNDS_FREQUENCY[j]);\n\t}\n\n\treader.tryRead(\"alienItemLevels\", _alienItemLevels);\n\n\tfor (const auto& patchReader : reader[\"MCDPatches\"].children()) // this should not be used by mods\n\t{\n\t\tstd::string type = patchReader[\"type\"].readVal<std::string>();\n\t\tif (_MCDPatches.find(type) != _MCDPatches.end())\n\t\t{\n\t\t\t_MCDPatches[type]->load(patchReader);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tMCDPatch *patch = new MCDPatch();\n\t\t\tpatch->load(patchReader);\n\t\t\t_MCDPatches[type] = patch;\n\t\t}\n\t}\n\tfor (const auto& ruleReader : iterateRulesSpecific(\"extraSprites\"))\n\t{\n\t\tif (ruleReader[\"type\"] || ruleReader[\"typeSingle\"])\n\t\t{\n\t\t\tstd::string type;\n\t\t\truleReader[\"type\"].tryReadVal<std::string>(type);\n\t\t\tif (type.empty())\n\t\t\t{\n\t\t\t\ttype = ruleReader[\"typeSingle\"].readVal<std::string>();\n\t\t\t}\n\t\t\tExtraSprites *extraSprites = new ExtraSprites();\n\t\t\tconst ModData* data = _modCurrent;\n\t\t\t// doesn't support modIndex\n\t\t\tif (type == \"TEXTURE.DAT\")\n\t\t\t\tdata = &_modData.at(0);\n\t\t\textraSprites->load(ruleReader, data);\n\t\t\t_extraSprites[type].push_back(extraSprites);\n\t\t}\n\t\telse if (ruleReader[\"delete\"])\n\t\t{\n\t\t\tstd::string type = ruleReader[\"delete\"].readVal<std::string>();\n\t\t\tauto j = _extraSprites.find(type);\n\t\t\tif (j != _extraSprites.end())\n\t\t\t{\n\t\t\t\t_extraSprites.erase(j);\n\t\t\t}\n\t\t}\n\t}\n\tfor (const auto& ruleReader : iterateRulesSpecific(\"customPalettes\"))\n\t{\n\t\tCustomPalettes* rule = loadRule(ruleReader, &_customPalettes, &_customPalettesIndex);\n\t\tif (rule != 0)\n\t\t{\n\t\t\trule->load(ruleReader);\n\t\t}\n\t}\n\tfor (const auto& ruleReader : iterateRulesSpecific(\"extraSounds\"))\n\t{\n\t\tstd::string type = ruleReader[\"type\"].readVal<std::string>();\n\t\tExtraSounds *extraSounds = new ExtraSounds();\n\t\textraSounds->load(ruleReader, _modCurrent);\n\t\t_extraSounds.push_back(std::make_pair(type, extraSounds));\n\t}\n\tfor (const auto& ruleReader : iterateRulesSpecific(\"extraStrings\"))\n\t{\n\t\tstd::string type = ruleReader[\"type\"].readVal<std::string>();\n\t\tif (_extraStrings.find(type) != _extraStrings.end())\n\t\t{\n\t\t\t_extraStrings[type]->load(ruleReader);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tExtraStrings *extraStrings = new ExtraStrings();\n\t\t\textraStrings->load(ruleReader);\n\t\t\t_extraStrings[type] = extraStrings;\n\t\t}\n\t}\n\n\tfor (const auto& ruleReader : iterateRulesSpecific(\"statStrings\"))\n\t{\n\t\tStatString *statString = new StatString();\n\t\tstatString->load(ruleReader);\n\t\t_statStrings.push_back(statString);\n\t}\n\n\tfor (const auto& ruleReader : iterateRulesSpecific(\"interfaces\"))\n\t{\n\t\tRuleInterface *rule = loadRule(ruleReader, &_interfaces);\n\t\tif (rule != 0)\n\t\t{\n\t\t\trule->load(ruleReader, this);\n\t\t}\n\t}\n\n\tfor (const auto& ruleReader : iterateRulesSpecific(\"cutscenes\"))\n\t{\n\t\tRuleVideo *rule = loadRule(ruleReader, &_videos);\n\t\tif (rule != 0)\n\t\t{\n\t\t\trule->load(ruleReader);\n\t\t}\n\t}\n\tfor (const auto& ruleReader : iterateRulesSpecific(\"musics\"))\n\t{\n\t\tRuleMusic *rule = loadRule(ruleReader, &_musicDefs);\n\t\tif (rule != 0)\n\t\t{\n\t\t\trule->load(ruleReader);\n\t\t}\n\t}\n\n\tif (reader[\"globe\"])\n\t{\n\t\t_globe->load(reader[\"globe\"], this);\n\t}\n\tif (reader[\"converter\"])\n\t{\n\t\t_converter->load(reader[\"converter\"]);\n\t}\n\tif (const auto& constants = reader[\"constants\"])\n\t{\n\t\t//backward compatibility version\n\t\tif (constants.isSeq())\n\t\t{\n\t\t\tfor (const auto& constant : constants.children())\n\t\t\t{\n\t\t\t\tloadConstants(constant);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tloadConstants(constants.useIndex());\n\t\t}\n\t}\n\n\t// refresh _psiRequirements for psiStrengthEval\n\tfor (const auto& facType : _facilitiesIndex)\n\t{\n\t\tRuleBaseFacility *rule = getBaseFacility(facType);\n\t\tif (rule->getPsiLaboratories() > 0)\n\t\t{\n\t\t\t_psiRequirements = rule->getRequirements();\n\t\t\tbreak;\n\t\t}\n\t}\n\t// override the default (used when you want to separate screening and training)\n\tif (!_psiUnlockResearch.empty())\n\t{\n\t\t_psiRequirements.clear();\n\t\t_psiRequirements.push_back(_psiUnlockResearch);\n\t}\n\n\tif (const auto& arrayReader = reader[\"aimAndArmorMultipliers\"])\n\t{\n\t\tfor (size_t j = 0; j < MaxDifficultyLevels; j++)\n\t\t{\n\t\t\tarrayReader[j].tryReadVal(_statAdjustment[j].aimMultiplier);\n\t\t\tarrayReader[j].tryReadVal(_statAdjustment[j].armorMultiplier);\n\t\t}\n\t}\n\tif (const auto& arrayReader = reader[\"aimMultipliers\"])\n\t{\n\t\tfor (size_t j = 0; j < MaxDifficultyLevels; j++)\n\t\t\tarrayReader[j].tryReadVal(_statAdjustment[j].aimMultiplier);\n\t}\n\tif (const auto& arrayReader = reader[\"armorMultipliers\"])\n\t{\n\t\tfor (size_t j = 0; j < MaxDifficultyLevels; j++)\n\t\t\tarrayReader[j].tryReadVal(_statAdjustment[j].armorMultiplier);\n\t}\n\tif (const auto& arrayReader = reader[\"armorMultipliersAbs\"])\n\t{\n\t\tfor (size_t j = 0; j < MaxDifficultyLevels; j++)\n\t\t\tarrayReader[j].tryReadVal(_statAdjustment[j].armorMultiplierAbs);\n\t}\n\tif (const auto& arrayReader = reader[\"statGrowthMultipliersAbs\"])\n\t{\n\t\tfor (size_t j = 0; j < MaxDifficultyLevels; j++)\n\t\t\tarrayReader[j].tryReadVal(_statAdjustment[j].statGrowthAbs);\n\t}\n\tif (const auto& arrayReader = reader[\"statGrowthMultipliers\"])\n\t{\n\t\tarrayReader.tryReadVal(_statAdjustment[0].statGrowth);\n\t\tfor (size_t j = 1; j < MaxDifficultyLevels; j++)\n\t\t\t_statAdjustment[j].statGrowth = _statAdjustment[0].statGrowth;\n\t}\n\tif (const auto& lighting = loadDocInfoHelper(\"lighting\"))\n\t{\n\t\tlighting.tryRead(\"maxStatic\", _maxStaticLightDistance);\n\t\tlighting.tryRead(\"maxDynamic\", _maxDynamicLightDistance);\n\t\tlighting.tryRead(\"enhanced\", _enhancedLighting);\n\t}\n}\n\n/**\n * Helper function protecting from circular references in node definition.\n * @param node Node to test\n * @param name Name of original node.\n * @param limit Current depth.\n */\nstatic void refNodeTestDeepth(const YAML::YamlNodeReader& reader, const std::string &name, int limit)\n{\n\tif (limit > 64)\n\t{\n\t\tthrow Exception(\"Nest limit of refNode reach in \" + name);\n\t}\n\tif (const auto& nested = reader[\"refNode\"])\n\t{\n\t\tif (!nested.isMap())\n\t\t{\n\t\t\tstd::stringstream ss;\n\t\t\tss << \"Invalid refNode at nest level of \";\n\t\t\tss << limit;\n\t\t\tss << \" in \";\n\t\t\tss << name;\n\t\t\tthrow Exception(ss.str());\n\t\t}\n\t\trefNodeTestDeepth(nested, name, limit + 1);\n\t}\n}\n\n/**\n * Loads a rule element, adding/removing from vectors as necessary.\n * @param node YAML node.\n * @param map Map associated to the rule type.\n * @param index Index vector for the rule type.\n * @param key Rule key name.\n * @return Pointer to new rule if one was created, or NULL if one was removed.\n */\ntemplate <typename T, typename F>\nT *Mod::loadRule(const YAML::YamlNodeReader& reader, std::map<std::string, T*> *map, std::vector<std::string> *index, const std::string &key, F&& factory)\n{\n\tT *rule = 0;\n\n\tauto getNode = [&](const YAML::YamlNodeReader& i, const std::string& nodeName)\n\t{\n\t\tauto n = i[ryml::to_csubstr(nodeName)];\n\t\treturn std::make_tuple(nodeName, std::move(n), !!n);\n\t};\n\tauto haveNode = [&](const std::tuple<std::string, YAML::YamlNodeReader, bool>& nn)\n\t{\n\t\treturn std::get<bool>(nn);\n\t};\n\tauto getDescriptionNode = [&](const std::tuple<std::string, YAML::YamlNodeReader, bool>& nn)\n\t{\n\t\tsize_t line = std::get<YAML::YamlNodeReader>(nn).getLocationInFile().line;\n\t\treturn std::string(\"'\") + std::get<std::string>(nn) + \"' at line \" + std::to_string(line);\n\t};\n\tauto getNameFromNode = [&](const std::tuple<std::string, YAML::YamlNodeReader, bool>& nn)\n\t{\n\t\tauto name = std::get<YAML::YamlNodeReader>(nn).readVal<std::string>();\n\t\tif (isEmptyRuleName(name))\n\t\t{\n\t\t\tsize_t line = std::get<YAML::YamlNodeReader>(nn).getLocationInFile().line;\n\t\t\tthrow Exception(\"Invalid value for main node '\" + std::get<std::string>(nn) + \"' at line \" + std::to_string(line));\n\t\t}\n\t\treturn name;\n\t};\n\tauto addTracking = [&](std::unordered_map<const void*, const ModData*>& track, const auto* t)\n\t{\n\t\ttrack[static_cast<const void*>(t)] = _modCurrent;\n\t};\n\tauto removeTracking = [&]( std::unordered_map<const void*, const ModData*>& track, const auto* t)\n\t{\n\t\ttrack.erase(static_cast<const void*>(t));\n\t};\n\n\tconst auto defaultNode = getNode(reader, key);\n\tconst auto deleteNode = getNode(reader, YamlRuleNodeDelete);\n\tconst auto newNode = getNode(reader, YamlRuleNodeNew);\n\tconst auto overrideNode = getNode(reader, YamlRuleNodeOverride);\n\tconst auto updateNode = getNode(reader, YamlRuleNodeUpdate);\n\tconst auto ignoreNode = getNode(reader, YamlRuleNodeIgnore);\n\n\t{\n\t\t// check for duplicates\n\t\tconst std::tuple<std::string, YAML::YamlNodeReader, bool>* last = nullptr;\n\t\tfor (auto* p : { &defaultNode, &deleteNode, &newNode, &updateNode, &overrideNode, &ignoreNode })\n\t\t{\n\t\t\tif (haveNode(*p))\n\t\t\t{\n\t\t\t\tif (last)\n\t\t\t\t{\n\t\t\t\t\tthrow Exception(\"Conflict of main node \" + getDescriptionNode(*last) + \" and \" + getDescriptionNode(*p));\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tlast = p;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (haveNode(defaultNode))\n\t{\n\t\tstd::string type = getNameFromNode(defaultNode);\n\n\n\t\tauto i = map->find(type);\n\t\tif (i != map->end())\n\t\t{\n\t\t\trule = i->second;\n\t\t}\n\t\telse\n\t\t{\n\t\t\trule = factory(type);\n\t\t\taddTracking(_ruleCreationTracking, rule);\n\t\t\t(*map)[type] = rule;\n\t\t\tif (index != 0)\n\t\t\t{\n\t\t\t\tindex->push_back(type);\n\t\t\t}\n\t\t}\n\n\t\t// protection from self referencing refNode node\n\t\trefNodeTestDeepth(reader, type, 0);\n\t\taddTracking(_ruleLastUpdateTracking, rule);\n\t}\n\telse if (haveNode(deleteNode))\n\t{\n\t\tstd::string type = getNameFromNode(deleteNode);\n\n\t\tauto i = map->find(type);\n\t\tif (i != map->end())\n\t\t{\n\t\t\tremoveTracking(_ruleCreationTracking, i->second);\n\t\t\tremoveTracking(_ruleLastUpdateTracking, i->second);\n\t\t\tdelete i->second;\n\t\t\tmap->erase(i);\n\t\t}\n\t\tif (index != 0)\n\t\t{\n\t\t\tauto idx = std::find(index->begin(), index->end(), type);\n\t\t\tif (idx != index->end())\n\t\t\t{\n\t\t\t\tindex->erase(idx);\n\t\t\t}\n\t\t}\n\t}\n\telse if (haveNode(newNode))\n\t{\n\t\tstd::string type = getNameFromNode(newNode);\n\n\t\tauto i = map->find(type);\n\t\tif (i != map->end())\n\t\t{\n\t\t\tcheckForSoftError(true, type, \"Rule named '\" + type  + \"' already used for \" + getDescriptionNode(newNode), LOG_ERROR);\n\t\t}\n\t\telse\n\t\t{\n\t\t\trule = factory(type);\n\t\t\taddTracking(_ruleCreationTracking, rule);\n\t\t\t(*map)[type] = rule;\n\t\t\tif (index != 0)\n\t\t\t{\n\t\t\t\tindex->push_back(type);\n\t\t\t}\n\n\t\t\t// protection from self referencing refNode node\n\t\t\trefNodeTestDeepth(reader, type, 0);\n\t\t\taddTracking(_ruleLastUpdateTracking, rule);\n\t\t}\n\t}\n\telse if (haveNode(overrideNode))\n\t{\n\t\tstd::string type = getNameFromNode(overrideNode);\n\n\t\tauto i = map->find(type);\n\t\tif (i != map->end())\n\t\t{\n\t\t\trule = i->second;\n\n\t\t\t// protection from self referencing refNode node\n\t\t\trefNodeTestDeepth(reader, type, 0);\n\t\t\taddTracking(_ruleLastUpdateTracking, rule);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tcheckForSoftError(true, type, \"Rule named '\" + type  + \"' do not exist for \" + getDescriptionNode(overrideNode), LOG_ERROR);\n\t\t}\n\t}\n\telse if (haveNode(updateNode))\n\t{\n\t\tstd::string type = getNameFromNode(updateNode);\n\n\t\tauto i = map->find(type);\n\t\tif (i != map->end())\n\t\t{\n\t\t\trule = i->second;\n\n\t\t\t// protection from self referencing refNode node\n\t\t\trefNodeTestDeepth(reader, type, 0);\n\t\t\taddTracking(_ruleLastUpdateTracking, rule);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tLog(LOG_INFO) << \"Rule named '\" << type  << \"' do not exist for \" << getDescriptionNode(updateNode);\n\t\t}\n\t}\n\telse if (haveNode(ignoreNode))\n\t{\n\t\t// nothing to see there...\n\t}\n\telse\n\t{\n\t\tthrow LoadRuleException(\"Mod\", reader, \"Missing main node\");\n\t}\n\n\treturn rule;\n}\n\n/**\n * Generates a brand new saved game with starting data.\n * @return A new saved game.\n */\nSavedGame *Mod::newSave(GameDifficulty diff) const\n{\n\tSavedGame *save = new SavedGame();\n\tsave->setDifficulty(diff);\n\n\t// Add countries\n\tfor (const auto& countryName : _countriesIndex)\n\t{\n\t\tRuleCountry *countryRule = getCountry(countryName);\n\t\tif (!countryRule->getLonMin().empty())\n\t\t\tsave->getCountries()->push_back(new Country(countryRule));\n\t}\n\t// Adjust funding to total $6M\n\tint missing = ((_initialFunding - save->getCountryFunding()/1000) / (int)save->getCountries()->size()) * 1000;\n\tfor (auto* country : *save->getCountries())\n\t{\n\t\tint funding = country->getFunding().back() + missing;\n\t\tif (funding < 0)\n\t\t{\n\t\t\tfunding = country->getFunding().back();\n\t\t}\n\t\tcountry->setFunding(funding);\n\t}\n\tsave->setFunds(save->getCountryFunding());\n\n\t// Add regions\n\tfor (const auto& regionName : _regionsIndex)\n\t{\n\t\tRuleRegion *regionRule = getRegion(regionName);\n\t\tif (!regionRule->getLonMin().empty())\n\t\t\tsave->getRegions()->push_back(new Region(regionRule));\n\t}\n\n\t// Set up starting base\n\tconst YAML::YamlRootNodeReader startingBaseByDiff(getStartingBase(diff), \"(starting base template)\");\n\tBase *base = new Base(this);\n\tbase->load(startingBaseByDiff, save, true);\n\tif (const auto& globalTemplates = startingBaseByDiff[\"globalTemplates\"])\n\t{\n\t\tsave->loadTemplates(globalTemplates, this);\n\t}\n\tif (const auto& ufopediaRuleStatus = startingBaseByDiff[\"ufopediaRuleStatus\"])\n\t{\n\t\tsave->loadUfopediaRuleStatus(ufopediaRuleStatus);\n\t}\n\tsave->getBases()->push_back(base);\n\n\t// Correct IDs\n\tfor (auto* craft : *base->getCrafts())\n\t{\n\t\tsave->getId(craft->getRules()->getType());\n\t}\n\n\t// Correct soldier IDs\n\tfor (auto* soldier : *base->getSoldiers())\n\t{\n\t\tsave->getId(\"STR_SOLDIER\");\n\t}\n\n\t// Remove craft weapons if needed\n\tfor (auto* craft : *base->getCrafts())\n\t{\n\t\tif (craft->getMaxUnitsRaw() < 0 || craft->getMaxVehiclesAndLargeSoldiersRaw() < 0)\n\t\t{\n\t\t\tsize_t weaponIndex = 0;\n\t\t\tfor (auto* current : *craft->getWeapons())\n\t\t\t{\n\t\t\t\tbase->getStorageItems()->addItem(current->getRules()->getLauncherItem());\n\t\t\t\tbase->getStorageItems()->addItem(current->getRules()->getClipItem(), current->getClipsLoaded());\n\t\t\t\tcraft->addCraftStats(-current->getRules()->getBonusStats());\n\t\t\t\tcraft->setShield(craft->getShield());\n\t\t\t\tdelete current;\n\t\t\t\tcraft->getWeapons()->at(weaponIndex) = 0;\n\t\t\t\tweaponIndex++;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Determine starting soldier types\n\tstd::vector<std::string> soldierTypes = _soldiersIndex; // copy!\n\tfor (auto iter = soldierTypes.begin(); iter != soldierTypes.end();)\n\t{\n\t\tif (getSoldier(*iter)->getRequirements().empty())\n\t\t{\n\t\t\t++iter;\n\t\t}\n\t\telse\n\t\t{\n\t\t\titer = soldierTypes.erase(iter);\n\t\t}\n\t}\n\n\tconst auto& randomSoldiersReader = startingBaseByDiff[\"randomSoldiers\"];\n\tstd::vector<std::string> randomTypes;\n\tif (randomSoldiersReader)\n\t{\n\t\t// Starting soldiers specified by type\n\t\tif (randomSoldiersReader.isMap())\n\t\t{\n\t\t\tstd::map<std::string, int> randomSoldiers;\n\t\t\trandomSoldiersReader.tryReadVal(randomSoldiers);\n\t\t\tfor (const auto& pair : randomSoldiers)\n\t\t\t{\n\t\t\t\tfor (int s = 0; s < pair.second; ++s)\n\t\t\t\t{\n\t\t\t\t\trandomTypes.push_back(pair.first);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// Starting soldiers specified by amount\n\t\telse if (randomSoldiersReader.hasVal())\n\t\t{\n\t\t\tint randomSoldiers = randomSoldiersReader.readVal(0);\n\t\t\tif (randomSoldiers > 0 && soldierTypes.empty())\n\t\t\t{\n\t\t\t\tLog(LOG_ERROR) << \"Cannot generate soldiers for the starting base. There are no available soldier types. Maybe all of them are locked by research?\";\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tfor (int s = 0; s < randomSoldiers; ++s)\n\t\t\t\t{\n\t\t\t\t\trandomTypes.push_back(soldierTypes[RNG::generate(0, soldierTypes.size() - 1)]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// Generate soldiers\n\t\tfor (size_t i = 0; i < randomTypes.size(); ++i)\n\t\t{\n\t\t\tRuleSoldier* ruleSoldier = getSoldier(randomTypes[i], true);\n\t\t\tint nationality = save->selectSoldierNationalityByLocation(this, ruleSoldier, nullptr); // -1 (unfortunately the first base is not placed yet)\n\t\t\tSoldier *soldier = genSoldier(save, ruleSoldier, nationality);\n\t\t\tbase->getSoldiers()->push_back(soldier);\n\t\t\t// Award soldier a special 'original eight' commendation\n\t\t\tif (_commendations.find(\"STR_MEDAL_ORIGINAL8_NAME\") != _commendations.end())\n\t\t\t{\n\t\t\t\tSoldierDiary *diary = soldier->getDiary();\n\t\t\t\tdiary->awardOriginalEightCommendation(this);\n\t\t\t\tfor (auto* comm : *diary->getSoldierCommendations())\n\t\t\t\t{\n\t\t\t\t\tcomm->makeOld();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// Assign pilots to craft (interceptors first, transport last) and non-pilots to transports only\n\t\tfor (auto* soldier : *base->getSoldiers())\n\t\t{\n\t\t\tif (soldier->getArmor()->getSize() > 1)\n\t\t\t{\n\t\t\t\t// \"Large soldiers\" just stay in the base\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (soldier->getRules()->getAllowPiloting())\n\t\t\t\t{\n\t\t\t\t\tsoldier->prepareStatsWithBonuses(this); // refresh stats for checking pilot requirements\n\t\t\t\t}\n\n\t\t\t\tCraft *found = 0;\n\t\t\t\tfor (auto* craft : *base->getCrafts())\n\t\t\t\t{\n\t\t\t\t\tCraftPlacementErrors err = craft->validateAddingSoldier(craft->getSpaceAvailable(), soldier);\n\t\t\t\t\tif (!found && craft->getRules()->getAllowLanding() && err == CPE_None)\n\t\t\t\t\t{\n\t\t\t\t\t\t// Remember transporter as fall-back, but search further for interceptors\n\t\t\t\t\t\tfound = craft;\n\t\t\t\t\t}\n\t\t\t\t\tif (!craft->getRules()->getAllowLanding() && err == CPE_None && craft->getSpaceUsed() < craft->getRules()->getPilots())\n\t\t\t\t\t{\n\t\t\t\t\t\t// Fill interceptors with minimum amount of pilots necessary\n\t\t\t\t\t\tif (soldier->hasAllPilotingRequirements(craft))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfound = craft;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tsoldier->setCraft(found);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Setup alien strategy\n\tsave->getAlienStrategy().init(this);\n\tsave->setTime(_startingTime);\n\n\treturn save;\n}\n\n/**\n * Returns the rules for the specified country.\n * @param id Country type.\n * @return Rules for the country.\n */\nRuleCountry *Mod::getCountry(const std::string &id, bool error) const\n{\n\treturn getRule(id, \"Country\", _countries, error);\n}\n\n/**\n * Returns the list of all countries\n * provided by the mod.\n * @return List of countries.\n */\nconst std::vector<std::string> &Mod::getCountriesList() const\n{\n\treturn _countriesIndex;\n}\n\n/**\n * Returns the rules for the specified extra globe label.\n * @param id Extra globe label type.\n * @return Rules for the extra globe label.\n */\nRuleCountry *Mod::getExtraGlobeLabel(const std::string &id, bool error) const\n{\n\treturn getRule(id, \"Extra Globe Label\", _extraGlobeLabels, error);\n}\n\n/**\n * Returns the list of all extra globe labels\n * provided by the mod.\n * @return List of extra globe labels.\n */\nconst std::vector<std::string> &Mod::getExtraGlobeLabelsList() const\n{\n\treturn _extraGlobeLabelsIndex;\n}\n\n/**\n * Returns the rules for the specified region.\n * @param id Region type.\n * @return Rules for the region.\n */\nRuleRegion *Mod::getRegion(const std::string &id, bool error) const\n{\n\treturn getRule(id, \"Region\", _regions, error);\n}\n\n/**\n * Returns the list of all regions\n * provided by the mod.\n * @return List of regions.\n */\nconst std::vector<std::string> &Mod::getRegionsList() const\n{\n\treturn _regionsIndex;\n}\n\n/**\n * Returns the rules for the specified base facility.\n * @param id Facility type.\n * @return Rules for the facility.\n */\nRuleBaseFacility *Mod::getBaseFacility(const std::string &id, bool error) const\n{\n\treturn getRule(id, \"Facility\", _facilities, error);\n}\n\n/**\n * Returns the list of all base facilities\n * provided by the mod.\n * @return List of base facilities.\n */\nconst std::vector<std::string> &Mod::getBaseFacilitiesList() const\n{\n\treturn _facilitiesIndex;\n}\n\n/**\n * Returns the rules for the specified craft.\n * @param id Craft type.\n * @return Rules for the craft.\n */\nRuleCraft *Mod::getCraft(const std::string &id, bool error) const\n{\n\treturn getRule(id, \"Craft\", _crafts, error);\n}\n\n/**\n * Returns the list of all crafts\n * provided by the mod.\n * @return List of crafts.\n */\nconst std::vector<std::string> &Mod::getCraftsList() const\n{\n\treturn _craftsIndex;\n}\n\n/**\n * Returns the rules for the specified craft weapon.\n * @param id Craft weapon type.\n * @return Rules for the craft weapon.\n */\nRuleCraftWeapon *Mod::getCraftWeapon(const std::string &id, bool error) const\n{\n\treturn getRule(id, \"Craft Weapon\", _craftWeapons, error);\n}\n\n/**\n * Returns the list of all craft weapons\n * provided by the mod.\n * @return List of craft weapons.\n */\nconst std::vector<std::string> &Mod::getCraftWeaponsList() const\n{\n\treturn _craftWeaponsIndex;\n}\n/**\n * Is given item a launcher or ammo for craft weapon.\n */\nbool Mod::isCraftWeaponStorageItem(const RuleItem* item) const\n{\n\treturn Collections::sortVectorHave(_craftWeaponStorageItemsCache, item);\n}\n\n/**\n* Returns the rules for the specified item category.\n* @param id Item category type.\n* @return Rules for the item category, or 0 when the item category is not found.\n*/\nRuleItemCategory *Mod::getItemCategory(const std::string &id, bool error) const\n{\n\tauto i = _itemCategories.find(id);\n\tif (_itemCategories.end() != i) return i->second; else return 0;\n}\n\n/**\n* Returns the list of all item categories\n* provided by the mod.\n* @return List of item categories.\n*/\nconst std::vector<std::string> &Mod::getItemCategoriesList() const\n{\n\treturn _itemCategoriesIndex;\n}\n\n/**\n * Returns the rules for the specified item.\n * @param id Item type.\n * @return Rules for the item, or 0 when the item is not found.\n */\nRuleItem *Mod::getItem(const std::string &id, bool error) const\n{\n\tif (id == Armor::NONE)\n\t{\n\t\treturn 0;\n\t}\n\treturn getRule(id, \"Item\", _items, error);\n}\n\n/**\n * Returns the list of all items\n * provided by the mod.\n * @return List of items.\n */\nconst std::vector<std::string> &Mod::getItemsList() const\n{\n\treturn _itemsIndex;\n}\n\n/**\n * Returns the rules for the specified weapon set.\n * @param type Weapon set type.\n * @return Rules for the weapon set.\n */\nRuleWeaponSet* Mod::getWeaponSet(const std::string& type, bool error) const\n{\n\treturn getRule(type, \"WeaponSet\", _weaponSets, error);\n}\n\n/**\n * Returns the rules for the specified UFO.\n * @param id UFO type.\n * @return Rules for the UFO.\n */\nRuleUfo *Mod::getUfo(const std::string &id, bool error) const\n{\n\treturn getRule(id, \"UFO\", _ufos, error);\n}\n\n/**\n * Returns the list of all ufos\n * provided by the mod.\n * @return List of ufos.\n */\nconst std::vector<std::string> &Mod::getUfosList() const\n{\n\treturn _ufosIndex;\n}\n\n/**\n * Returns the rules for the specified terrain.\n * @param name Terrain name.\n * @return Rules for the terrain.\n */\nRuleTerrain *Mod::getTerrain(const std::string &name, bool error) const\n{\n\treturn getRule(name, \"Terrain\", _terrains, error);\n}\n\n/**\n * Returns the list of all terrains\n * provided by the mod.\n * @return List of terrains.\n */\nconst std::vector<std::string> &Mod::getTerrainList() const\n{\n\treturn _terrainIndex;\n}\n\n/**\n * Returns the info about a specific map data file.\n * @param name Datafile name.\n * @return Rules for the datafile.\n */\nMapDataSet *Mod::getMapDataSet(const std::string &name)\n{\n\tauto map = _mapDataSets.find(name);\n\tif (map == _mapDataSets.end())\n\t{\n\t\tMapDataSet *set = new MapDataSet(name);\n\t\t_mapDataSets[name] = set;\n\t\treturn set;\n\t}\n\telse\n\t{\n\t\treturn map->second;\n\t}\n}\n\n/**\n * Returns the rules for the specified skill.\n * @param name Skill type.\n * @return Rules for the skill.\n */\nRuleSkill *Mod::getSkill(const std::string &name, bool error) const\n{\n\treturn getRule(name, \"Skill\", _skills, error);\n}\n\n/**\n * Returns the info about a specific unit.\n * @param name Unit name.\n * @return Rules for the units.\n */\nRuleSoldier *Mod::getSoldier(const std::string &name, bool error) const\n{\n\treturn getRule(name, \"Soldier\", _soldiers, error);\n}\n\n/**\n * Returns the list of all soldiers\n * provided by the mod.\n * @return List of soldiers.\n */\nconst std::vector<std::string> &Mod::getSoldiersList() const\n{\n\treturn _soldiersIndex;\n}\n\n/**\n * Returns the rules for the specified commendation.\n * @param id Commendation type.\n * @return Rules for the commendation.\n */\nRuleCommendations *Mod::getCommendation(const std::string &id, bool error) const\n{\n\treturn getRule(id, \"Commendation\", _commendations, error);\n}\n\n/**\n * Gets the list of commendations provided by the mod.\n * @return The list of commendations.\n */\nconst std::map<std::string, RuleCommendations *> &Mod::getCommendationsList() const\n{\n\treturn _commendations;\n}\n\n/**\n * Returns the info about a specific unit.\n * @param name Unit name.\n * @return Rules for the units.\n */\nUnit *Mod::getUnit(const std::string &name, bool error) const\n{\n\treturn getRule(name, \"Unit\", _units, error);\n}\n\n/**\n * Returns the info about a specific alien race.\n * @param name Race name.\n * @return Rules for the race.\n */\nAlienRace *Mod::getAlienRace(const std::string &name, bool error) const\n{\n\treturn getRule(name, \"Alien Race\", _alienRaces, error);\n}\n\n/**\n * Returns the list of all alien races.\n * provided by the mod.\n * @return List of alien races.\n */\nconst std::vector<std::string> &Mod::getAlienRacesList() const\n{\n\treturn _aliensIndex;\n}\n\n/**\n * Returns specific EnviroEffects.\n * @param name EnviroEffects name.\n * @return Rules for the EnviroEffects.\n */\nRuleEnviroEffects* Mod::getEnviroEffects(const std::string& name) const\n{\n\tauto i = _enviroEffects.find(name);\n\tif (_enviroEffects.end() != i) return i->second; else return 0;\n}\n\n/**\n * Returns the list of all EnviroEffects\n * provided by the mod.\n * @return List of EnviroEffects.\n */\nconst std::vector<std::string>& Mod::getEnviroEffectsList() const\n{\n\treturn _enviroEffectsIndex;\n}\n\n/**\n * Returns the info about a specific starting condition.\n * @param name Starting condition name.\n * @return Rules for the starting condition.\n */\nRuleStartingCondition* Mod::getStartingCondition(const std::string& name) const\n{\n\tauto i = _startingConditions.find(name);\n\tif (_startingConditions.end() != i) return i->second; else return 0;\n}\n\n/**\n * Returns the list of all starting conditions\n * provided by the mod.\n * @return List of starting conditions.\n */\nconst std::vector<std::string>& Mod::getStartingConditionsList() const\n{\n\treturn _startingConditionsIndex;\n}\n\n/**\n * Returns the info about a specific deployment.\n * @param name Deployment name.\n * @return Rules for the deployment.\n */\nAlienDeployment *Mod::getDeployment(const std::string &name, bool error) const\n{\n\treturn getRule(name, \"Alien Deployment\", _alienDeployments, error);\n}\n\n/**\n * Returns the list of all alien deployments\n * provided by the mod.\n * @return List of alien deployments.\n */\nconst std::vector<std::string> &Mod::getDeploymentsList() const\n{\n\treturn _deploymentsIndex;\n}\n\n\n/**\n * Returns the info about a specific armor.\n * @param name Armor name.\n * @return Rules for the armor.\n */\nArmor *Mod::getArmor(const std::string &name, bool error) const\n{\n\treturn getRule(name, \"Armor\", _armors, error);\n}\n\n/**\n * Returns the list of all armors\n * provided by the mod.\n * @return List of armors.\n */\nconst std::vector<std::string> &Mod::getArmorsList() const\n{\n\treturn _armorsIndex;\n}\n\n/**\n * Gets the available armors for soldiers.\n */\nconst std::vector<const Armor*> &Mod::getArmorsForSoldiers() const\n{\n\treturn _armorsForSoldiersCache;\n}\n\n/**\n * Check if item is used for armor storage.\n */\nbool Mod::isArmorStorageItem(const RuleItem* item) const\n{\n\treturn Collections::sortVectorHave(_armorStorageItemsCache, item);\n}\n\n\n/**\n * Returns the hiring cost of an individual engineer.\n * @return Cost.\n */\nint Mod::getHireEngineerCost() const\n{\n\treturn _costHireEngineer != 0 ? _costHireEngineer : _costEngineer * 2;\n}\n\n/**\n* Returns the hiring cost of an individual scientist.\n* @return Cost.\n*/\nint Mod::getHireScientistCost() const\n{\n\treturn _costHireScientist != 0 ? _costHireScientist: _costScientist * 2;\n}\n\n/**\n * Returns the monthly cost of an individual engineer.\n * @return Cost.\n */\nint Mod::getEngineerCost() const\n{\n\treturn _costEngineer;\n}\n\n/**\n * Returns the monthly cost of an individual scientist.\n * @return Cost.\n */\nint Mod::getScientistCost() const\n{\n\treturn _costScientist;\n}\n\n/**\n * Returns the time it takes to transfer personnel\n * between bases.\n * @return Time in hours.\n */\nint Mod::getPersonnelTime() const\n{\n\treturn _timePersonnel;\n}\n\n/**\n * Returns the reaction fire threshold (default = 0).\n * @return The threshold for a given faction.\n */\nint Mod::getReactionFireThreshold(UnitFaction faction) const\n{\n\tswitch (faction)\n\t{\n\tcase FACTION_PLAYER:\n\t\treturn Options::oxceReactionFireThreshold;\n\tcase FACTION_HOSTILE:\n\t\treturn _aiReactionFireThreshold;\n\tcase FACTION_NEUTRAL:\n\t\treturn _aiReactionFireThresholdCiv;\n\tdefault:\n\t\tbreak;\n\t}\n\n\treturn 0;\n}\n\n/**\n * Gets maximum supported lookVariant.\n * @return value in range from 0 to 63\n */\nint Mod::getMaxLookVariant() const\n{\n\treturn abs(_maxLookVariant) % RuleSoldier::LookVariantMax;\n}\n\n/**\n * Gets the escort range.\n * @return Escort range.\n */\ndouble Mod::getEscortRange() const\n{\n\treturn _escortRange;\n}\n\n/**\n * Returns the article definition for a given name.\n * @param name Article name.\n * @return Article definition.\n */\nArticleDefinition *Mod::getUfopaediaArticle(const std::string &name, bool error) const\n{\n\treturn getRule(name, \"UFOpaedia Article\", _ufopaediaArticles, error);\n}\n\n/**\n * Returns the list of all articles\n * provided by the mod.\n * @return List of articles.\n */\nconst std::vector<std::string> &Mod::getUfopaediaList() const\n{\n\treturn _ufopaediaIndex;\n}\n\n/**\n* Returns the list of all article categories\n* provided by the mod.\n* @return List of categories.\n*/\nconst std::vector<std::string> &Mod::getUfopaediaCategoryList() const\n{\n\treturn _ufopaediaCatIndex;\n}\n\n/**\n * Returns the list of inventories.\n * @return Pointer to inventory list.\n */\nstd::map<std::string, RuleInventory*> *Mod::getInventories()\n{\n\treturn &_invs;\n}\n\n/**\n * Returns the rules for a specific inventory.\n * @param id Inventory type.\n * @return Inventory ruleset.\n */\nRuleInventory *Mod::getInventory(const std::string &id, bool error) const\n{\n\treturn getRule(id, \"Inventory\", _invs, error);\n}\n\n/**\n * Returns basic damage type.\n * @param type damage type.\n * @return basic damage ruleset.\n */\nconst RuleDamageType *Mod::getDamageType(ItemDamageType type) const\n{\n\treturn _damageTypes.at(type);\n}\n\n/**\n * Returns the list of inventories.\n * @return The list of inventories.\n */\nconst std::vector<std::string> &Mod::getInvsList() const\n{\n\treturn _invsIndex;\n}\n\n/**\n * Returns the rules for the specified research project.\n * @param id Research project type.\n * @return Rules for the research project.\n */\nRuleResearch *Mod::getResearch(const std::string &id, bool error) const\n{\n\treturn getRule(id, \"Research\", _research, error);\n}\n\n/**\n * Gets the ruleset list for from research list.\n */\nstd::vector<const RuleResearch*> Mod::getResearch(const std::vector<std::string> &id) const\n{\n\tstd::vector<const RuleResearch*> dest;\n\tdest.reserve(id.size());\n\tfor (auto& name : id)\n\t{\n\t\tauto* rule = getResearch(name, false);\n\t\tif (rule)\n\t\t{\n\t\t\tdest.push_back(rule);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tthrow Exception(\"Unknown research '\" + name + \"'\");\n\t\t}\n\t}\n\treturn dest;\n}\n\n/**\n * Gets the ruleset for a specific research project.\n */\nconst std::map<std::string, RuleResearch *> &Mod::getResearchMap() const\n{\n\treturn _research;\n}\n\n/**\n * Returns the list of research projects.\n * @return The list of research projects.\n */\nconst std::vector<std::string> &Mod::getResearchList() const\n{\n\treturn _researchIndex;\n}\n\n/**\n * Returns the rules for the specified manufacture project.\n * @param id Manufacture project type.\n * @return Rules for the manufacture project.\n */\nRuleManufacture *Mod::getManufacture (const std::string &id, bool error) const\n{\n\treturn getRule(id, \"Manufacture\", _manufacture, error);\n}\n\n/**\n * Returns the list of manufacture projects.\n * @return The list of manufacture projects.\n */\nconst std::vector<std::string> &Mod::getManufactureList() const\n{\n\treturn _manufactureIndex;\n}\n\n/**\n * Returns the rules for the specified soldier bonus type.\n * @param id Soldier bonus type.\n * @return Rules for the soldier bonus type.\n */\nRuleSoldierBonus *Mod::getSoldierBonus(const std::string &id, bool error) const\n{\n\treturn getRule(id, \"SoldierBonus\", _soldierBonus, error);\n}\n\n/**\n * Returns the list of soldier bonus types.\n * @return The list of soldier bonus types.\n */\nconst std::vector<std::string> &Mod::getSoldierBonusList() const\n{\n\treturn _soldierBonusIndex;\n}\n\n/**\n * Returns the rules for the specified soldier transformation project.\n * @param id Soldier transformation project type.\n * @return Rules for the soldier transformation project.\n */\nRuleSoldierTransformation *Mod::getSoldierTransformation (const std::string &id, bool error) const\n{\n\treturn getRule(id, \"SoldierTransformation\", _soldierTransformation, error);\n}\n\n/**\n * Returns the list of soldier transformation projects.\n * @return The list of soldier transformation projects.\n */\nconst std::vector<std::string> &Mod::getSoldierTransformationList() const\n{\n\treturn _soldierTransformationIndex;\n}\n\n/**\n * Generates and returns a list of facilities for custom bases.\n * The list contains all the facilities that are listed in the 'startingBase'\n * part of the ruleset.\n * @return The list of facilities for custom bases.\n */\nstd::vector<RuleBaseFacility*> Mod::getCustomBaseFacilities(GameDifficulty diff) const\n{\n\tstd::vector<RuleBaseFacility*> placeList;\n\n\tconst YAML::YamlRootNodeReader startingBaseByDiff(getStartingBase(diff), \"(starting base template)\");\n\tfor (const auto& facilityReader : startingBaseByDiff[\"facilities\"].children())\n\t{\n\t\tstd::string type = facilityReader[\"type\"].readVal<std::string>();\n\t\tRuleBaseFacility *facility = getBaseFacility(type, true);\n\t\tif (!facility->isLift() && !facility->isUpgradeOnly())\n\t\t{\n\t\t\tplaceList.push_back(facility);\n\t\t}\n\t}\n\treturn placeList;\n}\n\n/**\n * Returns the data for the specified ufo trajectory.\n * @param id Ufo trajectory id.\n * @return A pointer to the data for the specified ufo trajectory.\n */\nconst UfoTrajectory *Mod::getUfoTrajectory(const std::string &id, bool error) const\n{\n\treturn getRule(id, \"Trajectory\", _ufoTrajectories, error);\n}\n\n/**\n * Returns the rules for the specified alien mission.\n * @param id Alien mission type.\n * @return Rules for the alien mission.\n */\nconst RuleAlienMission *Mod::getAlienMission(const std::string &id, bool error) const\n{\n\treturn getRule(id, \"Alien Mission\", _alienMissions, error);\n}\n\n/**\n * Returns the rules for a random alien mission based on a specific objective.\n * @param objective Alien mission objective.\n * @return Rules for the alien mission.\n */\nconst RuleAlienMission *Mod::getRandomMission(MissionObjective objective, size_t monthsPassed) const\n{\n\tint totalWeight = 0;\n\tstd::map<int, RuleAlienMission*> possibilities;\n\tfor (auto& pair : _alienMissions)\n\t{\n\t\tif (pair.second->getObjective() == objective && pair.second->getWeight(monthsPassed) > 0)\n\t\t{\n\t\t\ttotalWeight += pair.second->getWeight(monthsPassed);\n\t\t\tpossibilities[totalWeight] = pair.second;\n\t\t}\n\t}\n\tif (totalWeight > 0)\n\t{\n\t\tint pick = RNG::generate(1, totalWeight);\n\t\tfor (auto& pair : possibilities)\n\t\t{\n\t\t\tif (pick <= pair.first)\n\t\t\t{\n\t\t\t\treturn pair.second;\n\t\t\t}\n\t\t}\n\t}\n\treturn 0;\n}\n\n/**\n * Returns the list of alien mission types.\n * @return The list of alien mission types.\n */\nconst std::vector<std::string> &Mod::getAlienMissionList() const\n{\n\treturn _alienMissionsIndex;\n}\n\n/**\n * Gets the alien item level table.\n * @return A deep array containing the alien item levels.\n */\nconst std::vector<std::vector<int> > &Mod::getAlienItemLevels() const\n{\n\treturn _alienItemLevels;\n}\n\n/**\n * Gets the default starting base.\n * @return The starting base definition.\n */\nconst YAML::YamlString& Mod::getDefaultStartingBase() const\n{\n\treturn _startingBaseDefault;\n}\n\n/**\n * Gets the custom starting base (by game difficulty).\n * @return The starting base definition.\n */\nconst YAML::YamlString& Mod::getStartingBase(GameDifficulty diff) const\n{\n\tif (diff == DIFF_BEGINNER && _startingBaseBeginner.yaml != \"\")\n\t{\n\t\treturn _startingBaseBeginner;\n\t}\n\telse if (diff == DIFF_EXPERIENCED && _startingBaseExperienced.yaml != \"\")\n\t{\n\t\treturn _startingBaseExperienced;\n\t}\n\telse if (diff == DIFF_VETERAN && _startingBaseVeteran.yaml != \"\")\n\t{\n\t\treturn _startingBaseVeteran;\n\t}\n\telse if (diff == DIFF_GENIUS && _startingBaseGenius.yaml != \"\")\n\t{\n\t\treturn _startingBaseGenius;\n\t}\n\telse if (diff == DIFF_SUPERHUMAN && _startingBaseSuperhuman.yaml != \"\")\n\t{\n\t\treturn _startingBaseSuperhuman;\n\t}\n\n\treturn _startingBaseDefault;\n}\n\n/**\n * Gets the defined starting time.\n * @return The time the game starts in.\n */\nconst GameTime &Mod::getStartingTime() const\n{\n\treturn _startingTime;\n}\n\n/**\n * Gets an MCDPatch.\n * @param id The ID of the MCDPatch we want.\n * @return The MCDPatch based on ID, or 0 if none defined.\n */\nMCDPatch *Mod::getMCDPatch(const std::string &id) const\n{\n\tauto i = _MCDPatches.find(id);\n\tif (_MCDPatches.end() != i) return i->second; else return 0;\n}\n\n/**\n * Gets the list of external sprites.\n * @return The list of external sprites.\n */\nconst std::map<std::string, std::vector<ExtraSprites *> > &Mod::getExtraSprites() const\n{\n\treturn _extraSprites;\n}\n\n/**\n * Gets the list of custom palettes.\n * @return The list of custom palettes.\n */\nconst std::vector<std::string> &Mod::getCustomPalettes() const\n{\n\treturn _customPalettesIndex;\n}\n\n/**\n * Gets the list of external sounds.\n * @return The list of external sounds.\n */\nconst std::vector<std::pair<std::string, ExtraSounds *> > &Mod::getExtraSounds() const\n{\n\treturn _extraSounds;\n}\n\n/**\n * Gets the list of external strings.\n * @return The list of external strings.\n */\nconst std::map<std::string, ExtraStrings *> &Mod::getExtraStrings() const\n{\n\treturn _extraStrings;\n}\n\n/**\n * Gets the list of StatStrings.\n * @return The list of StatStrings.\n */\nconst std::vector<StatString *> &Mod::getStatStrings() const\n{\n\treturn _statStrings;\n}\n\n/**\n * Compares rules based on their list orders.\n */\ntemplate <typename T>\nstruct compareRule\n{\n\tMod *_mod;\n\n\tcompareRule(Mod *mod) : _mod(mod)\n\t{\n\t}\n\n\tbool operator()(const std::pair<const std::string, T*>* r1, const std::pair<const std::string, T*>* r2) const\n\t{\n\t\treturn (r1->second->getListOrder() < r2->second->getListOrder());\n\t}\n};\n\n/**\n * Craft weapons use the list order of their launcher item.\n */\ntemplate <>\nstruct compareRule<RuleCraftWeapon>\n{\n\tMod *_mod;\n\n\tcompareRule(Mod *mod) : _mod(mod)\n\t{\n\t}\n\n\tbool operator()(const std::pair<const std::string, RuleCraftWeapon*>* r1, const std::pair<const std::string, RuleCraftWeapon*>* r2) const\n\t{\n\t\treturn (r1->second->getLauncherItem()->getListOrder() < r2->second->getLauncherItem()->getListOrder());\n\t}\n};\n\n/**\n * Armor uses the list order of their store item.\n * Itemless armor comes before all else.\n */\ntemplate <>\nstruct compareRule<Armor>\n{\n\tMod *_mod;\n\n\tcompareRule(Mod *mod) : _mod(mod)\n\t{\n\t}\n\n\tbool operator()(const std::pair<const std::string, Armor*>* r1, const std::pair<const std::string, Armor*>* r2) const\n\t{\n\t\treturn operator()(r1->second, r2->second);\n\t}\n\n\tbool operator()(const Armor* armor1, const Armor* armor2) const\n\t{\n\t\tconst RuleItem *rule1 = armor1->getStoreItem();\n\t\tconst RuleItem *rule2 = armor2->getStoreItem();\n\t\tif (!rule1 && !rule2)\n\t\t\treturn (armor1->getListOrder() < armor2->getListOrder()); // tiebreaker\n\t\telse if (!rule1)\n\t\t\treturn true;\n\t\telse if (!rule2)\n\t\t\treturn false;\n\t\telse\n\t\t\treturn (rule1->getListOrder() < rule2->getListOrder() ||\n\t\t\t\t   (rule1->getListOrder() == rule2->getListOrder() && armor1->getListOrder() < armor2->getListOrder()));\n\t}\n};\n\n/**\n * Ufopaedia articles use section and list order.\n */\ntemplate <>\nstruct compareRule<ArticleDefinition>\n{\n\tMod *_mod;\n\tconst std::map<std::string, int> &_sections;\n\n\tcompareRule(Mod *mod) : _mod(mod), _sections(mod->getUfopaediaSections())\n\t{\n\t}\n\n\tbool operator()(const std::pair<const std::string, ArticleDefinition*>* r1, const std::pair<const std::string, ArticleDefinition*>* r2) const\n\t{\n\t\tif (r1->second->section == r2->second->section)\n\t\t\treturn (r1->second->getListOrder() < r2->second->getListOrder());\n\t\telse\n\t\t\treturn (_sections.at(r1->second->section) < _sections.at(r2->second->section));\n\t}\n};\n\n/**\n * Ufopaedia sections use article list order.\n */\nstruct compareSection\n{\n\tMod *_mod;\n\tconst std::map<std::string, int> &_sections;\n\n\tcompareSection(Mod *mod) : _mod(mod), _sections(mod->getUfopaediaSections())\n\t{\n\t}\n\n\tbool operator()(const std::string &r1, const std::string &r2) const\n\t{\n\t\treturn _sections.at(r1) < _sections.at(r2);\n\t}\n};\n\n/**\n* Sort helper to avoid having to do loop-ups inside comparator function\n*/\ntemplate <typename RuleType, typename ComparatorFunc>\nvoid sortIndex(std::vector<std::string>& index, std::map<std::string, RuleType*>& map, ComparatorFunc comparator)\n{\n\tstd::vector<const std::pair<const std::string, RuleType*>*> tempVector;\n\ttempVector.reserve(index.size());\n\tfor (const auto& pair : map)\n\t\ttempVector.push_back(&pair);\n\tstd::sort(tempVector.begin(), tempVector.end(), comparator);\n\tfor (size_t i = 0; i < index.size(); ++i)\n\t\tindex[i].assign(tempVector[i]->first);\n}\n\n/**\n * Sorts all our lists according to their weight.\n */\nvoid Mod::sortLists()\n{\n\tfor (auto& rulePair : _ufopaediaArticles)\n\t{\n\t\tauto* rule = rulePair.second;\n\t\tif (rule->section != UFOPAEDIA_NOT_AVAILABLE)\n\t\t{\n\t\t\tif (_ufopaediaSections.find(rule->section) == _ufopaediaSections.end())\n\t\t\t{\n\t\t\t\t_ufopaediaSections[rule->section] = rule->getListOrder();\n\t\t\t\t_ufopaediaCatIndex.push_back(rule->section);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_ufopaediaSections[rule->section] = std::min(_ufopaediaSections[rule->section], rule->getListOrder());\n\t\t\t}\n\t\t}\n\t}\n\tsortIndex(_itemCategoriesIndex, _itemCategories, compareRule<RuleItemCategory>(this));\n\tsortIndex(_itemsIndex, _items, compareRule<RuleItem>(this));\n\tsortIndex(_craftsIndex, _crafts, compareRule<RuleCraft>(this));\n\tsortIndex(_facilitiesIndex, _facilities, compareRule<RuleBaseFacility>(this));\n\tsortIndex(_researchIndex, _research, compareRule<RuleResearch>(this));\n\tsortIndex(_manufactureIndex, _manufacture, compareRule<RuleManufacture>(this));\n\tsortIndex(_soldierTransformationIndex, _soldierTransformation, compareRule<RuleSoldierTransformation>(this));\n\tsortIndex(_invsIndex, _invs, compareRule<RuleInventory>(this));\n\t// special cases\n\tsortIndex(_craftWeaponsIndex, _craftWeapons, compareRule<RuleCraftWeapon>(this));\n\tsortIndex(_armorsIndex, _armors, compareRule<Armor>(this));\n\tstd::sort(_armorsForSoldiersCache.begin(), _armorsForSoldiersCache.end(), compareRule<Armor>(this));\n\t_ufopaediaSections[UFOPAEDIA_NOT_AVAILABLE] = 0;\n\tsortIndex(_ufopaediaIndex, _ufopaediaArticles, compareRule<ArticleDefinition>(this));\n\tstd::sort(_ufopaediaCatIndex.begin(), _ufopaediaCatIndex.end(), compareSection(this));\n\tsortIndex(_soldiersIndex, _soldiers, compareRule<RuleSoldier>(this));\n\tsortIndex(_aliensIndex, _alienRaces, compareRule<AlienRace>(this));\n}\n\n/**\n * Gets the research-requirements for Psi-Lab (it's a cache for psiStrengthEval)\n */\nconst std::vector<std::string> &Mod::getPsiRequirements() const\n{\n\treturn _psiRequirements;\n}\n\n/**\n * Creates a new randomly-generated soldier.\n * @param save Saved game the soldier belongs to.\n * @param type The soldier type to generate.\n * @return Newly generated soldier.\n */\nSoldier *Mod::genSoldier(SavedGame *save, const RuleSoldier* ruleSoldier, int nationality) const\n{\n\tSoldier *soldier = 0;\n\tint newId = save->getId(\"STR_SOLDIER\");\n\n\t// Check for duplicates\n\t// Original X-COM gives up after 10 tries so might as well do the same here\n\tbool duplicate = true;\n\tfor (int tries = 0; tries < 10 && duplicate; ++tries)\n\t{\n\t\tdelete soldier;\n\t\tsoldier = new Soldier(const_cast<RuleSoldier*>(ruleSoldier), ruleSoldier->getDefaultArmor(), nationality, newId);\n\t\tduplicate = false;\n\t\tfor (auto* xbase : *save->getBases())\n\t\t{\n\t\t\tif (duplicate) break; // loop finished\n\t\t\tfor (auto* xsoldier : *xbase->getSoldiers())\n\t\t\t{\n\t\t\t\tif (duplicate) break; // loop finished\n\t\t\t\tif (xsoldier->getName() == soldier->getName())\n\t\t\t\t{\n\t\t\t\t\tduplicate = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (auto* transfer : *xbase->getTransfers())\n\t\t\t{\n\t\t\t\tif (duplicate) break; // loop finished\n\t\t\t\tif (transfer->getType() == TRANSFER_SOLDIER && transfer->getSoldier()->getName() == soldier->getName())\n\t\t\t\t{\n\t\t\t\t\tduplicate = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// calculate new statString\n\tsoldier->calcStatString(getStatStrings(), (Options::psiStrengthEval && save->isResearched(getPsiRequirements())));\n\n\treturn soldier;\n}\n\n/**\n * Gets the name of the item to be used as alien fuel.\n * @return the name of the fuel.\n */\nstd::string Mod::getAlienFuelName() const\n{\n\treturn _alienFuel.first;\n}\n\n/**\n * Gets the amount of alien fuel to recover.\n * @return the amount to recover.\n */\nint Mod::getAlienFuelQuantity() const\n{\n\treturn _alienFuel.second;\n}\n\n/**\n * Gets name of font collection.\n * @return the name of YAML-file with font data\n */\nstd::string Mod::getFontName() const\n{\n\treturn _fontName;\n}\n\n/**\n * Returns the maximum radar range still considered as short.\n * @return The short radar range threshold.\n */\n int Mod::getShortRadarRange() const\n {\n\tif (_shortRadarRange > 0)\n\t\treturn _shortRadarRange;\n\n\tint minRadarRange = 0;\n\n\t{\n\t\tfor (auto& facType : _facilitiesIndex)\n\t\t{\n\t\t\tRuleBaseFacility *f = getBaseFacility(facType);\n\t\t\tif (f == 0) continue;\n\n\t\t\tint radarRange = f->getRadarRange();\n\t\t\tif (radarRange > 0 && (minRadarRange == 0 || minRadarRange > radarRange))\n\t\t\t{\n\t\t\t\tminRadarRange = radarRange;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn minRadarRange;\n }\n\n/**\n * Returns what should be displayed in craft pedia articles for fuel capacity/range\n * @return 0 = Max theoretical range, 1 = Min and max theoretical max range, 2 = average of the two\n * Otherwise (default), just show the fuel capacity\n */\nint Mod::getPediaReplaceCraftFuelWithRangeType() const\n{\n\treturn _pediaReplaceCraftFuelWithRangeType;\n}\n\n/**\n * Gets information on an interface.\n * @param id the interface we want info on.\n * @return the interface.\n */\nRuleInterface *Mod::getInterface(const std::string &id, bool error) const\n{\n\treturn getRule(id, \"Interface\", _interfaces, error);\n}\n\n/**\n * Gets the rules for the Geoscape globe.\n * @return Pointer to globe rules.\n */\nRuleGlobe *Mod::getGlobe() const\n{\n\treturn _globe;\n}\n\n/**\n* Gets the rules for the Save Converter.\n* @return Pointer to converter rules.\n*/\nRuleConverter *Mod::getConverter() const\n{\n\treturn _converter;\n}\n\nconst std::map<std::string, SoundDefinition *> *Mod::getSoundDefinitions() const\n{\n\treturn &_soundDefs;\n}\n\nconst std::vector<MapScript*> *Mod::getMapScript(const std::string& id) const\n{\n\tauto i = _mapScripts.find(id);\n\tif (_mapScripts.end() != i)\n\t{\n\t\treturn &i->second;\n\t}\n\telse\n\t{\n\t\treturn 0;\n\t}\n}\n\n/**\n * Returns the data for the specified video cutscene.\n * @param id Video id.\n * @return A pointer to the data for the specified video.\n */\nRuleVideo *Mod::getVideo(const std::string &id, bool error) const\n{\n\treturn getRule(id, \"Video\", _videos, error);\n}\n\nconst std::map<std::string, RuleMusic *> *Mod::getMusic() const\n{\n\treturn &_musicDefs;\n}\n\nconst std::vector<std::string>* Mod::getArcScriptList() const\n{\n\treturn &_arcScriptIndex;\n}\n\nRuleArcScript* Mod::getArcScript(const std::string& name, bool error) const\n{\n\treturn getRule(name, \"Arc Script\", _arcScripts, error);\n}\n\nconst std::vector<std::string>* Mod::getEventScriptList() const\n{\n\treturn &_eventScriptIndex;\n}\n\nRuleEventScript* Mod::getEventScript(const std::string& name, bool error) const\n{\n\treturn getRule(name, \"Event Script\", _eventScripts, error);\n}\n\nconst std::vector<std::string>* Mod::getEventList() const\n{\n\treturn &_eventIndex;\n}\n\nRuleEvent* Mod::getEvent(const std::string& name, bool error) const\n{\n\treturn getRule(name, \"Event\", _events, error);\n}\n\nconst std::vector<std::string> *Mod::getMissionScriptList() const\n{\n\treturn &_missionScriptIndex;\n}\n\nconst std::vector<std::string> *Mod::getAdhocScriptList() const\n{\n\treturn &_adhocScriptIndex;\n}\n\nRuleMissionScript *Mod::getMissionScript(const std::string &name, bool error) const\n{\n\treturn getRule(name, \"Mission Script\", _missionScripts, error);\n}\n\nRuleMissionScript *Mod::getAdhocScript(const std::string &name, bool error) const\n{\n\treturn getRule(name, \"Adhoc Script\", _adhocScripts, error);\n}\n\n/// Get global script data.\nScriptGlobal *Mod::getScriptGlobal() const\n{\n\treturn _scriptGlobal;\n}\n\nRuleResearch *Mod::getFinalResearch() const\n{\n\treturn _finalResearch;\n}\n\nRuleBaseFacility *Mod::getDestroyedFacility() const\n{\n\tif (isEmptyRuleName(_destroyedFacility))\n\t\treturn 0;\n\n\tauto* temp = getBaseFacility(_destroyedFacility, true);\n\tif (!temp->isSmall())\n\t{\n\t\tthrow Exception(\"Destroyed base facility definition must have size: 1\");\n\t}\n\treturn temp;\n}\n\nconst std::map<int, std::string> *Mod::getMissionRatings() const\n{\n\treturn &_missionRatings;\n}\nconst std::map<int, std::string> *Mod::getMonthlyRatings() const\n{\n\treturn &_monthlyRatings;\n}\n\nconst std::vector<std::string> &Mod::getHiddenMovementBackgrounds() const\n{\n\treturn _hiddenMovementBackgrounds;\n}\n\nconst std::vector<int> &Mod::getFlagByKills() const\n{\n\treturn _flagByKills;\n}\n\nnamespace\n{\n\tconst Uint8 ShadeMax = 15;\n\t/**\n\t* Recolor class used in UFO\n\t*/\n\tstruct HairXCOM1\n\t{\n\t\tstatic const Uint8 Hair = 9 << 4;\n\t\tstatic const Uint8 Face = 6 << 4;\n\t\tstatic inline void func(Uint8& src, const Uint8& cutoff)\n\t\t{\n\t\t\tif (src > cutoff && src <= Face + ShadeMax)\n\t\t\t{\n\t\t\t\tsrc = Hair + (src & ShadeMax) - 6; //make hair color like male in xcom_0.pck\n\t\t\t}\n\t\t}\n\t};\n\n\t/**\n\t* Recolor class used in TFTD\n\t*/\n\tstruct HairXCOM2\n\t{\n\t\tstatic const Uint8 ManHairColor = 4 << 4;\n\t\tstatic const Uint8 WomanHairColor = 1 << 4;\n\t\tstatic inline void func(Uint8& src)\n\t\t{\n\t\t\tif (src >= WomanHairColor && src <= WomanHairColor + ShadeMax)\n\t\t\t{\n\t\t\t\tsrc = ManHairColor + (src & ShadeMax);\n\t\t\t}\n\t\t}\n\t};\n\n\t/**\n\t* Recolor class used in TFTD\n\t*/\n\tstruct FaceXCOM2\n\t{\n\t\tstatic const Uint8 FaceColor = 10 << 4;\n\t\tstatic const Uint8 PinkColor = 14 << 4;\n\t\tstatic inline void func(Uint8& src)\n\t\t{\n\t\t\tif (src >= FaceColor && src <= FaceColor + ShadeMax)\n\t\t\t{\n\t\t\t\tsrc = PinkColor + (src & ShadeMax);\n\t\t\t}\n\t\t}\n\t};\n\n\t/**\n\t* Recolor class used in TFTD\n\t*/\n\tstruct BodyXCOM2\n\t{\n\t\tstatic const Uint8 IonArmorColor = 8 << 4;\n\t\tstatic inline void func(Uint8& src)\n\t\t{\n\t\t\tif (src == 153)\n\t\t\t{\n\t\t\t\tsrc = IonArmorColor + 12;\n\t\t\t}\n\t\t\telse if (src == 151)\n\t\t\t{\n\t\t\t\tsrc = IonArmorColor + 10;\n\t\t\t}\n\t\t\telse if (src == 148)\n\t\t\t{\n\t\t\t\tsrc = IonArmorColor + 4;\n\t\t\t}\n\t\t\telse if (src == 147)\n\t\t\t{\n\t\t\t\tsrc = IonArmorColor + 2;\n\t\t\t}\n\t\t\telse if (src >= HairXCOM2::WomanHairColor && src <= HairXCOM2::WomanHairColor + ShadeMax)\n\t\t\t{\n\t\t\t\tsrc = IonArmorColor + (src & ShadeMax);\n\t\t\t}\n\t\t}\n\t};\n\t/**\n\t* Recolor class used in TFTD\n\t*/\n\tstruct FallXCOM2\n\t{\n\t\tstatic const Uint8 RoguePixel = 151;\n\t\tstatic inline void func(Uint8& src)\n\t\t{\n\t\t\tif (src == RoguePixel)\n\t\t\t{\n\t\t\t\tsrc = FaceXCOM2::PinkColor + (src & ShadeMax) + 2;\n\t\t\t}\n\t\t\telse if (src >= BodyXCOM2::IonArmorColor && src <= BodyXCOM2::IonArmorColor + ShadeMax)\n\t\t\t{\n\t\t\t\tsrc = FaceXCOM2::PinkColor + (src & ShadeMax);\n\t\t\t}\n\t\t}\n\t};\n}\n\n/**\n * Loads the vanilla resources required by the game.\n */\nvoid Mod::loadVanillaResources()\n{\n\t// Create Geoscape surface\n\t_sets[\"GlobeMarkers\"] = new SurfaceSet(3, 3);\n\t// dummy resources, that need to be defined in order for mod loading to work correctly\n\t_sets[\"CustomArmorPreviews\"] = new SurfaceSet(12, 20);\n\t_sets[\"CustomItemPreviews\"] = new SurfaceSet(12, 20);\n\t_sets[\"TinyRanks\"] = new SurfaceSet(7, 7);\n\t_sets[\"Touch\"] = new SurfaceSet(32, 24);\n\n\t// Load palettes\n\tconst char *pal[] = { \"PAL_GEOSCAPE\", \"PAL_BASESCAPE\", \"PAL_GRAPHS\", \"PAL_UFOPAEDIA\", \"PAL_BATTLEPEDIA\" };\n\tfor (size_t i = 0; i < ARRAYLEN(pal); ++i)\n\t{\n\t\tstd::string s = \"GEODATA/PALETTES.DAT\";\n\t\t_palettes[pal[i]] = new Palette();\n\t\t_palettes[pal[i]]->loadDat(s, 256, Palette::palOffset(i));\n\t}\n\t{\n\t\tstd::string s1 = \"GEODATA/BACKPALS.DAT\";\n\t\tstd::string s2 = \"BACKPALS.DAT\";\n\t\t_palettes[s2] = new Palette();\n\t\t_palettes[s2]->loadDat(s1, 128);\n\t}\n\n\t// Correct Battlescape palette\n\t{\n\t\tstd::string s1 = \"GEODATA/PALETTES.DAT\";\n\t\tstd::string s2 = \"PAL_BATTLESCAPE\";\n\t\t_palettes[s2] = new Palette();\n\t\t_palettes[s2]->loadDat(s1, 256, Palette::palOffset(4));\n\n\t\t// Last 16 colors are a greyish gradient\n\t\tSDL_Color gradient[] = { { 140, 152, 148, 255 },\n\t\t{ 132, 136, 140, 255 },\n\t\t{ 116, 124, 132, 255 },\n\t\t{ 108, 116, 124, 255 },\n\t\t{ 92, 104, 108, 255 },\n\t\t{ 84, 92, 100, 255 },\n\t\t{ 76, 80, 92, 255 },\n\t\t{ 56, 68, 84, 255 },\n\t\t{ 48, 56, 68, 255 },\n\t\t{ 40, 48, 56, 255 },\n\t\t{ 32, 36, 48, 255 },\n\t\t{ 24, 28, 32, 255 },\n\t\t{ 16, 20, 24, 255 },\n\t\t{ 8, 12, 16, 255 },\n\t\t{ 3, 4, 8, 255 },\n\t\t{ 3, 3, 6, 255 } };\n\t\tfor (size_t i = 0; i < ARRAYLEN(gradient); ++i)\n\t\t{\n\t\t\tSDL_Color *color = _palettes[s2]->getColors(Palette::backPos + 16 + i);\n\t\t\t*color = gradient[i];\n\t\t}\n\t\t//_palettes[s2]->savePalMod(\"../../../customPalettes.rul\", \"PAL_BATTLESCAPE_CUSTOM\", \"PAL_BATTLESCAPE\");\n\t}\n\n\t// Load surfaces\n\t{\n\t\tstd::string s1 = \"GEODATA/INTERWIN.DAT\";\n\t\tstd::string s2 = \"INTERWIN.DAT\";\n\t\t_surfaces[s2] = new Surface(160, 600);\n\t\t_surfaces[s2]->loadScr(s1);\n\t}\n\n\tconst auto& geographFiles = FileMap::getVFolderContents(\"GEOGRAPH\");\n\tauto scrs = FileMap::filterFiles(geographFiles, \"SCR\");\n\tfor (const auto& name : scrs)\n\t{\n\t\tstd::string fname = name;\n\t\tstd::transform(name.begin(), name.end(), fname.begin(), toupper);\n\t\t_surfaces[fname] = new Surface(320, 200);\n\t\t_surfaces[fname]->loadScr(\"GEOGRAPH/\" + fname);\n\t}\n\tauto bdys = FileMap::filterFiles(geographFiles, \"BDY\");\n\tfor (const auto& name : bdys)\n\t{\n\t\tstd::string fname = name;\n\t\tstd::transform(name.begin(), name.end(), fname.begin(), toupper);\n\t\t_surfaces[fname] = new Surface(320, 200);\n\t\t_surfaces[fname]->loadBdy(\"GEOGRAPH/\" + fname);\n\t}\n\n\tauto spks = FileMap::filterFiles(geographFiles, \"SPK\");\n\tfor (const auto& name : spks)\n\t{\n\t\tstd::string fname = name;\n\t\tstd::transform(name.begin(), name.end(), fname.begin(), toupper);\n\t\t_surfaces[fname] = new Surface(320, 200);\n\t\t_surfaces[fname]->loadSpk(\"GEOGRAPH/\" + fname);\n\t}\n\n\t// Load surface sets\n\tstd::string sets[] = { \"BASEBITS.PCK\",\n\t\t\"INTICON.PCK\",\n\t\t\"TEXTURE.DAT\" };\n\n\tfor (size_t i = 0; i < ARRAYLEN(sets); ++i)\n\t{\n\t\tstd::ostringstream s;\n\t\ts << \"GEOGRAPH/\" << sets[i];\n\n\t\tstd::string ext = sets[i].substr(sets[i].find_last_of('.') + 1, sets[i].length());\n\t\tif (ext == \"PCK\")\n\t\t{\n\t\t\tstd::string tab = CrossPlatform::noExt(sets[i]) + \".TAB\";\n\t\t\tstd::ostringstream s2;\n\t\t\ts2 << \"GEOGRAPH/\" << tab;\n\t\t\t_sets[sets[i]] = new SurfaceSet(32, 40);\n\t\t\t_sets[sets[i]]->loadPck(s.str(), s2.str());\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_sets[sets[i]] = new SurfaceSet(32, 32);\n\t\t\t_sets[sets[i]]->loadDat(s.str());\n\t\t}\n\t}\n\t{\n\t\tstd::string s1 = \"GEODATA/SCANG.DAT\";\n\t\tstd::string s2 = \"SCANG.DAT\";\n\t\t_sets[s2] = new SurfaceSet(4, 4);\n\t\t_sets[s2]->loadDat(s1);\n\t}\n\n\t// construct sound sets\n\t_sounds[\"GEO.CAT\"] = new SoundSet();\n\t_sounds[\"BATTLE.CAT\"] = new SoundSet();\n\t_sounds[\"BATTLE2.CAT\"] = new SoundSet();\n\t_sounds[\"SAMPLE3.CAT\"] = new SoundSet();\n\t_sounds[\"INTRO.CAT\"] = new SoundSet();\n\n\tif (!Options::mute) // TBD: ain't it wrong? can Options::mute be reset without a reload?\n\t{\n\t\t// Load sounds\n\t\tconst auto& contents = FileMap::getVFolderContents(\"SOUND\");\n\t\tauto soundFiles = FileMap::filterFiles(contents, \"CAT\");\n\t\tif (_soundDefs.empty())\n\t\t{\n\t\t\tstd::string catsId[] = { \"GEO.CAT\", \"BATTLE.CAT\" };\n\t\t\tstd::string catsDos[] = { \"SOUND2.CAT\", \"SOUND1.CAT\" };\n\t\t\tstd::string catsWin[] = { \"SAMPLE.CAT\", \"SAMPLE2.CAT\" };\n\n\t\t\t// Try the preferred format first, otherwise use the default priority\n\t\t\tstd::string *cats[] = { 0, catsWin, catsDos };\n\t\t\tif (Options::preferredSound == SOUND_14)\n\t\t\t\tcats[0] = catsWin;\n\t\t\telse if (Options::preferredSound == SOUND_10)\n\t\t\t\tcats[0] = catsDos;\n\n\t\t\tOptions::currentSound = SOUND_AUTO;\n\t\t\tfor (size_t i = 0; i < ARRAYLEN(catsId); ++i)\n\t\t\t{\n\t\t\t\tSoundSet *sound = _sounds[catsId[i]];\n\t\t\t\tfor (size_t j = 0; j < ARRAYLEN(cats); ++j)\n\t\t\t\t{\n\t\t\t\t\tbool wav = true;\n\t\t\t\t\tif (cats[j] == 0)\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\telse if (cats[j] == catsDos)\n\t\t\t\t\t\twav = false;\n\t\t\t\t\tstd::string fname = \"SOUND/\" + cats[j][i];\n\t\t\t\t\tif (FileMap::fileExists(fname))\n\t\t\t\t\t{\n\t\t\t\t\t\tLog(LOG_VERBOSE) << catsId[i] << \": loading sound \"<<fname;\n\t\t\t\t\t\tCatFile catfile(fname);\n\t\t\t\t\t\tsound->loadCat(catfile);\n\t\t\t\t\t\tOptions::currentSound = (wav) ? SOUND_14 : SOUND_10;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tLog(LOG_VERBOSE) << catsId[i] << \": sound file not found: \"<<fname;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (sound->getTotalSounds() == 0)\n\t\t\t\t{\n\t\t\t\t\tLog(LOG_ERROR) << catsId[i] << \" not found: \" << catsWin[i] + \" or \" + catsDos[i] + \" required\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// we're here if and only if this is the first mod loading\n\t\t\t// and it got soundDefs in the ruleset, which basically means it's xcom2.\n\t\t\tfor (auto& i : _soundDefs)\n\t\t\t{\n\t\t\t\tif (_sounds.find(i.first) == _sounds.end())\n\t\t\t\t{\n\t\t\t\t\t_sounds[i.first] = new SoundSet();\n\t\t\t\t\tLog(LOG_VERBOSE) << \"TFTD: adding soundset\" << i.first;\n\t\t\t\t}\n\t\t\t\tstd::string fname = \"SOUND/\" + i.second->getCATFile();\n\t\t\t\tif (FileMap::fileExists(fname))\n\t\t\t\t{\n\t\t\t\t\tCatFile catfile(fname);\n\t\t\t\t\tfor (int j : i.second->getSoundList())\n\t\t\t\t\t{\n\t\t\t\t\t\t_sounds[i.first]->loadCatByIndex(catfile, j, true);\n\t\t\t\t\t\tLog(LOG_VERBOSE) << \"TFTD: adding sound \" << j << \" to \" << i.first;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tLog(LOG_ERROR) << \"TFTD sound file not found:\" << fname;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tauto file = soundFiles.find(\"intro.cat\");\n\t\tif (file != soundFiles.end())\n\t\t{\n\t\t\tauto catfile = CatFile(\"SOUND/INTRO.CAT\");\n\t\t\t_sounds[\"INTRO.CAT\"]->loadCat(catfile);\n\t\t}\n\n\t\tfile = soundFiles.find(\"sample3.cat\");\n\t\tif (file != soundFiles.end())\n\t\t{\n\t\t\tauto catfile = CatFile(\"SOUND/SAMPLE3.CAT\");\n\t\t\t_sounds[\"SAMPLE3.CAT\"]->loadCat(catfile);\n\t\t}\n\t}\n\n\tloadBattlescapeResources(); // TODO load this at battlescape start, unload at battlescape end?\n\n\n\t//update number of shared indexes in surface sets and sound sets\n\t{\n\t\tstd::string surfaceNames[] =\n\t\t{\n\t\t\t\"BIGOBS.PCK\",\n\t\t\t\"FLOOROB.PCK\",\n\t\t\t\"HANDOB.PCK\",\n\t\t\t\"SMOKE.PCK\",\n\t\t\t\"HIT.PCK\",\n\t\t\t\"BASEBITS.PCK\",\n\t\t\t\"INTICON.PCK\",\n\t\t\t\"CustomArmorPreviews\",\n\t\t\t\"CustomItemPreviews\",\n\t\t};\n\n\t\tfor (size_t i = 0; i < ARRAYLEN(surfaceNames); ++i)\n\t\t{\n\t\t\tSurfaceSet* s = _sets[surfaceNames[i]];\n\t\t\tif (s)\n\t\t\t{\n\t\t\t\ts->setMaxSharedFrames((int)s->getTotalFrames());\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tLog(LOG_ERROR) << \"Surface set \" << surfaceNames[i] << \" not found.\";\n\t\t\t\tthrow Exception(\"Surface set \" + surfaceNames[i] + \" not found.\");\n\t\t\t}\n\t\t}\n\t\t//special case for surface set that is loaded later\n\t\t{\n\t\t\tSurfaceSet* s = _sets[\"Projectiles\"];\n\t\t\ts->setMaxSharedFrames(385);\n\t\t}\n\t\t{\n\t\t\tSurfaceSet* s = _sets[\"UnderwaterProjectiles\"];\n\t\t\ts->setMaxSharedFrames(385);\n\t\t}\n\t\t{\n\t\t\tSurfaceSet* s = _sets[\"GlobeMarkers\"];\n\t\t\ts->setMaxSharedFrames(9);\n\t\t}\n\t\t//HACK: because of value \"hitAnimation\" from item that is used as offset in \"X1.PCK\", this set need have same number of shared frames as \"SMOKE.PCK\".\n\t\t{\n\t\t\tSurfaceSet* s = _sets[\"X1.PCK\"];\n\t\t\ts->setMaxSharedFrames((int)_sets[\"SMOKE.PCK\"]->getMaxSharedFrames());\n\t\t}\n\t\t{\n\t\t\tSurfaceSet* s = _sets[\"TinyRanks\"];\n\t\t\ts->setMaxSharedFrames(6);\n\t\t}\n\t\t{\n\t\t\tSurfaceSet* s = _sets[\"Touch\"];\n\t\t\ts->setMaxSharedFrames(10);\n\t\t}\n\t}\n\t{\n\t\tstd::string soundNames[] =\n\t\t{\n\t\t\t\"BATTLE.CAT\",\n\t\t\t\"GEO.CAT\",\n\t\t};\n\n\t\tfor (size_t i = 0; i < ARRAYLEN(soundNames); ++i)\n\t\t{\n\t\t\tSoundSet* s = _sounds[soundNames[i]];\n\t\t\ts->setMaxSharedSounds((int)s->getTotalSounds());\n\t\t}\n\t\t//HACK: case for underwater surface, it should share same offsets as \"BATTLE.CAT\"\n\t\t{\n\t\t\tSoundSet* s = _sounds[\"BATTLE2.CAT\"];\n\t\t\ts->setMaxSharedSounds((int)_sounds[\"BATTLE.CAT\"]->getTotalSounds());\n\t\t}\n\t}\n}\n\n/**\n * Loads the resources required by the Battlescape.\n */\nvoid Mod::loadBattlescapeResources()\n{\n\t// Load Battlescape ICONS\n\t_sets[\"SPICONS.DAT\"] = new SurfaceSet(32, 24);\n\t_sets[\"SPICONS.DAT\"]->loadDat(\"UFOGRAPH/SPICONS.DAT\");\n\t_sets[\"CURSOR.PCK\"] = new SurfaceSet(32, 40);\n\t_sets[\"CURSOR.PCK\"]->loadPck(\"UFOGRAPH/CURSOR.PCK\", \"UFOGRAPH/CURSOR.TAB\");\n\t_sets[\"SMOKE.PCK\"] = new SurfaceSet(32, 40);\n\t_sets[\"SMOKE.PCK\"]->loadPck(\"UFOGRAPH/SMOKE.PCK\", \"UFOGRAPH/SMOKE.TAB\");\n\t_sets[\"HIT.PCK\"] = new SurfaceSet(32, 40);\n\t_sets[\"HIT.PCK\"]->loadPck(\"UFOGRAPH/HIT.PCK\", \"UFOGRAPH/HIT.TAB\");\n\t_sets[\"X1.PCK\"] = new SurfaceSet(128, 64);\n\t_sets[\"X1.PCK\"]->loadPck(\"UFOGRAPH/X1.PCK\", \"UFOGRAPH/X1.TAB\");\n\t_sets[\"MEDIBITS.DAT\"] = new SurfaceSet(52, 58);\n\t_sets[\"MEDIBITS.DAT\"]->loadDat(\"UFOGRAPH/MEDIBITS.DAT\");\n\t_sets[\"DETBLOB.DAT\"] = new SurfaceSet(16, 16);\n\t_sets[\"DETBLOB.DAT\"]->loadDat(\"UFOGRAPH/DETBLOB.DAT\");\n\t_sets[\"Projectiles\"] = new SurfaceSet(3, 3);\n\t_sets[\"UnderwaterProjectiles\"] = new SurfaceSet(3, 3);\n\n\t// Load Battlescape Terrain (only blanks are loaded, others are loaded just in time)\n\t_sets[\"BLANKS.PCK\"] = new SurfaceSet(32, 40);\n\t_sets[\"BLANKS.PCK\"]->loadPck(\"TERRAIN/BLANKS.PCK\", \"TERRAIN/BLANKS.TAB\");\n\n\t// Load Battlescape units\n\tconst auto& unitsContents = FileMap::getVFolderContents(\"UNITS\");\n\tauto usets = FileMap::filterFiles(unitsContents, \"PCK\");\n\tfor (const auto& name : usets)\n\t{\n\t\tstd::string fname = name;\n\t\tstd::transform(name.begin(), name.end(), fname.begin(), toupper);\n\t\tif (fname != \"BIGOBS.PCK\")\n\t\t\t_sets[fname] = new SurfaceSet(32, 40);\n\t\telse\n\t\t\t_sets[fname] = new SurfaceSet(32, 48);\n\t\t_sets[fname]->loadPck(\"UNITS/\" + name, \"UNITS/\" + CrossPlatform::noExt(name) + \".TAB\");\n\t}\n\t// incomplete chryssalid set: 1.0 data: stop loading.\n\tif (_sets.find(\"CHRYS.PCK\") != _sets.end() && !_sets[\"CHRYS.PCK\"]->getFrame(225))\n\t{\n\t\tLog(LOG_FATAL) << \"Version 1.0 data detected\";\n\t\tthrow Exception(\"Invalid CHRYS.PCK, please patch your X-COM data to the latest version\");\n\t}\n\t// TFTD uses the loftemps dat from the terrain folder, but still has enemy unknown's version in the geodata folder, which is short by 2 entries.\n\tconst auto& terrainContents = FileMap::getVFolderContents(\"TERRAIN\");\n\tif (terrainContents.find(\"loftemps.dat\") != terrainContents.end())\n\t{\n\t\tMapDataSet::loadLOFTEMPS(\"TERRAIN/LOFTEMPS.DAT\", &_voxelData);\n\t}\n\telse\n\t{\n\t\tMapDataSet::loadLOFTEMPS(\"GEODATA/LOFTEMPS.DAT\", &_voxelData);\n\t}\n\n\tstd::string scrs[] = { \"TAC00.SCR\" };\n\n\tfor (size_t i = 0; i < ARRAYLEN(scrs); ++i)\n\t{\n\t\t_surfaces[scrs[i]] = new Surface(320, 200);\n\t\t_surfaces[scrs[i]]->loadScr(\"UFOGRAPH/\" + scrs[i]);\n\t}\n\n\t// lower case so we can find them in the contents map\n\tstd::string lbms[] = { \"d0.lbm\",\n\t\t\"d1.lbm\",\n\t\t\"d2.lbm\",\n\t\t\"d3.lbm\" };\n\tstd::string pals[] = { \"PAL_BATTLESCAPE\",\n\t\t\"PAL_BATTLESCAPE_1\",\n\t\t\"PAL_BATTLESCAPE_2\",\n\t\t\"PAL_BATTLESCAPE_3\" };\n\n\tSDL_Color backPal[] = { { 0, 5, 4, 255 },\n\t{ 0, 10, 34, 255 },\n\t{ 2, 9, 24, 255 },\n\t{ 2, 0, 24, 255 } };\n\n\tconst auto& ufographContents = FileMap::getVFolderContents(\"UFOGRAPH\");\n\tfor (size_t i = 0; i < ARRAYLEN(lbms); ++i)\n\t{\n\t\tif (ufographContents.find(lbms[i]) == ufographContents.end())\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (!i)\n\t\t{\n\t\t\tdelete _palettes[\"PAL_BATTLESCAPE\"];\n\t\t}\n\t\t// TODO: if we need only the palette, say so.\n\t\tSurface *tempSurface = new Surface(1, 1);\n\t\ttempSurface->loadImage(\"UFOGRAPH/\" + lbms[i]);\n\t\t_palettes[pals[i]] = new Palette();\n\t\tSDL_Color *colors = tempSurface->getPalette();\n\t\tcolors[255] = backPal[i];\n\t\t_palettes[pals[i]]->setColors(colors, 256);\n\t\tcreateTransparencyLUT(_palettes[pals[i]]);\n\t\tdelete tempSurface;\n\t}\n\n\tstd::string spks[] = { \"TAC01.SCR\",\n\t\t\"DETBORD.PCK\",\n\t\t\"DETBORD2.PCK\",\n\t\t\"ICONS.PCK\",\n\t\t\"MEDIBORD.PCK\",\n\t\t\"SCANBORD.PCK\",\n\t\t\"UNIBORD.PCK\" };\n\n\tfor (size_t i = 0; i < ARRAYLEN(spks); ++i)\n\t{\n\t\tstd::string fname = spks[i];\n\t\tstd::transform(fname.begin(), fname.end(), fname.begin(), tolower);\n\t\tif (ufographContents.find(fname) == ufographContents.end())\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\n\t\t_surfaces[spks[i]] = new Surface(320, 200);\n\t\t_surfaces[spks[i]]->loadSpk(\"UFOGRAPH/\" + spks[i]);\n\t}\n\n\tauto bdys = FileMap::filterFiles(ufographContents, \"BDY\");\n\tfor (const auto& name : bdys)\n\t{\n\t\tstd::string idxName = name;\n\t\tstd::transform(name.begin(), name.end(), idxName.begin(), toupper);\n\t\tidxName = idxName.substr(0, idxName.length() - 3);\n\t\tif (idxName.substr(0, 3) == \"MAN\")\n\t\t{\n\t\t\tidxName = idxName + \"SPK\";\n\t\t}\n\t\telse if (idxName == \"TAC01.\")\n\t\t{\n\t\t\tidxName = idxName + \"SCR\";\n\t\t}\n\t\telse\n\t\t{\n\t\t\tidxName = idxName + \"PCK\";\n\t\t}\n\t\t_surfaces[idxName] = new Surface(320, 200);\n\t\t_surfaces[idxName]->loadBdy(\"UFOGRAPH/\" + name);\n\t}\n\n\t// Load Battlescape inventory\n\tauto invs = FileMap::filterFiles(ufographContents, \"SPK\");\n\tfor (const auto& name : invs)\n\t{\n\t\tstd::string fname = name;\n\t\tstd::transform(name.begin(), name.end(), fname.begin(), toupper);\n\t\t_surfaces[fname] = new Surface(320, 200);\n\t\t_surfaces[fname]->loadSpk(\"UFOGRAPH/\" + fname);\n\t}\n\n\t//\"fix\" of color index in original solders sprites\n\tif (Options::battleHairBleach)\n\t{\n\t\tstd::string name;\n\n\t\t//personal armor\n\t\tname = \"XCOM_1.PCK\";\n\t\tif (_sets.find(name) != _sets.end())\n\t\t{\n\t\t\tSurfaceSet *xcom_1 = _sets[name];\n\n\t\t\tfor (int i = 0; i < 8; ++i)\n\t\t\t{\n\t\t\t\t//chest frame\n\t\t\t\tSurface *surf = xcom_1->getFrame(4 * 8 + i);\n\t\t\t\tShaderMove<Uint8> head = ShaderMove<Uint8>(surf);\n\t\t\t\tGraphSubset dim = head.getBaseDomain();\n\t\t\t\tsurf->lock();\n\t\t\t\tdim.beg_y = 6;\n\t\t\t\tdim.end_y = 9;\n\t\t\t\thead.setDomain(dim);\n\t\t\t\tShaderDraw<HairXCOM1>(head, ShaderScalar<Uint8>(HairXCOM1::Face + 5));\n\t\t\t\tdim.beg_y = 9;\n\t\t\t\tdim.end_y = 10;\n\t\t\t\thead.setDomain(dim);\n\t\t\t\tShaderDraw<HairXCOM1>(head, ShaderScalar<Uint8>(HairXCOM1::Face + 6));\n\t\t\t\tsurf->unlock();\n\t\t\t}\n\n\t\t\tfor (int i = 0; i < 3; ++i)\n\t\t\t{\n\t\t\t\t//fall frame\n\t\t\t\tSurface *surf = xcom_1->getFrame(264 + i);\n\t\t\t\tShaderMove<Uint8> head = ShaderMove<Uint8>(surf);\n\t\t\t\tGraphSubset dim = head.getBaseDomain();\n\t\t\t\tdim.beg_y = 0;\n\t\t\t\tdim.end_y = 24;\n\t\t\t\tdim.beg_x = 11;\n\t\t\t\tdim.end_x = 20;\n\t\t\t\thead.setDomain(dim);\n\t\t\t\tsurf->lock();\n\t\t\t\tShaderDraw<HairXCOM1>(head, ShaderScalar<Uint8>(HairXCOM1::Face + 6));\n\t\t\t\tsurf->unlock();\n\t\t\t}\n\t\t}\n\n\t\t//all TFTD armors\n\t\tname = \"TDXCOM_?.PCK\";\n\t\tfor (int j = 0; j < 3; ++j)\n\t\t{\n\t\t\tname[7] = '0' + j;\n\t\t\tif (_sets.find(name) != _sets.end())\n\t\t\t{\n\t\t\t\tSurfaceSet *xcom_2 = _sets[name];\n\t\t\t\tfor (int i = 0; i < 16; ++i)\n\t\t\t\t{\n\t\t\t\t\t//chest frame without helm\n\t\t\t\t\tSurface *surf = xcom_2->getFrame(262 + i);\n\t\t\t\t\tsurf->lock();\n\t\t\t\t\tif (i < 8)\n\t\t\t\t\t{\n\t\t\t\t\t\t//female chest frame\n\t\t\t\t\t\tShaderMove<Uint8> head = ShaderMove<Uint8>(surf);\n\t\t\t\t\t\tGraphSubset dim = head.getBaseDomain();\n\t\t\t\t\t\tdim.beg_y = 6;\n\t\t\t\t\t\tdim.end_y = 18;\n\t\t\t\t\t\thead.setDomain(dim);\n\t\t\t\t\t\tShaderDraw<HairXCOM2>(head);\n\n\t\t\t\t\t\tif (j == 2)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t//fix some pixels in ION armor that was overwrite by previous function\n\t\t\t\t\t\t\tif (i == 0)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tsurf->setPixel(18, 14, 16);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if (i == 3)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tsurf->setPixel(19, 12, 20);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if (i == 6)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tsurf->setPixel(13, 14, 16);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t//we change face to pink, to prevent mixup with ION armor backpack that have same color group.\n\t\t\t\t\tShaderDraw<FaceXCOM2>(ShaderMove<Uint8>(surf));\n\t\t\t\t\tsurf->unlock();\n\t\t\t\t}\n\n\t\t\t\tfor (int i = 0; i < 2; ++i)\n\t\t\t\t{\n\t\t\t\t\t//fall frame (first and second)\n\t\t\t\t\tSurface *surf = xcom_2->getFrame(256 + i);\n\t\t\t\t\tsurf->lock();\n\n\t\t\t\t\tShaderMove<Uint8> head = ShaderMove<Uint8>(surf);\n\t\t\t\t\tGraphSubset dim = head.getBaseDomain();\n\t\t\t\t\tdim.beg_y = 0;\n\t\t\t\t\tif (j == 3)\n\t\t\t\t\t{\n\t\t\t\t\t\tdim.end_y = 11 + 5 * i;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tdim.end_y = 17;\n\t\t\t\t\t}\n\t\t\t\t\thead.setDomain(dim);\n\t\t\t\t\tShaderDraw<FallXCOM2>(head);\n\n\t\t\t\t\t//we change face to pink, to prevent mixup with ION armor backpack that have same color group.\n\t\t\t\t\tShaderDraw<FaceXCOM2>(ShaderMove<Uint8>(surf));\n\t\t\t\t\tsurf->unlock();\n\t\t\t\t}\n\n\t\t\t\t//Palette fix for ION armor\n\t\t\t\tif (j == 2)\n\t\t\t\t{\n\t\t\t\t\tint size = xcom_2->getTotalFrames();\n\t\t\t\t\tfor (int i = 0; i < size; ++i)\n\t\t\t\t\t{\n\t\t\t\t\t\tSurface *surf = xcom_2->getFrame(i);\n\t\t\t\t\t\tsurf->lock();\n\t\t\t\t\t\tShaderDraw<BodyXCOM2>(ShaderMove<Uint8>(surf));\n\t\t\t\t\t\tsurf->unlock();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Loads the extra resources defined in rulesets.\n */\nvoid Mod::loadExtraResources()\n{\n\t// Load fonts\n\tYAML::YamlRootNodeReader reader = FileMap::getYAML(\"Language/\" + _fontName);\n\tLog(LOG_INFO) << \"Loading fonts... \" << _fontName;\n\tfor (const auto& fontReader : reader[\"fonts\"].children())\n\t{\n\t\tstd::string id = fontReader[\"id\"].readVal<std::string>();\n\t\tFont *font = new Font();\n\t\tfont->load(fontReader);\n\t\t_fonts[id] = font;\n\t}\n\n#ifndef __NO_MUSIC\n\t// Load musics\n\tif (!Options::mute)\n\t{\n\t\tconst auto& soundFiles = FileMap::getVFolderContents(\"SOUND\");\n\n\t\t// Check which music version is available\n\t\tCatFile *adlibcat = 0, *aintrocat = 0;\n\t\tGMCatFile *gmcat = 0;\n\n\t\tfor (const auto& name : soundFiles)\n\t\t{\n\t\t\tif (0 == name.compare(\"adlib.cat\"))\n\t\t\t{\n\t\t\t\tadlibcat = new CatFile(\"SOUND/\" + name);\n\t\t\t}\n\t\t\telse if (0 == name.compare(\"aintro.cat\"))\n\t\t\t{\n\t\t\t\taintrocat = new CatFile(\"SOUND/\" + name);\n\t\t\t}\n\t\t\telse if (0 == name.compare(\"gm.cat\"))\n\t\t\t{\n\t\t\t\tgmcat = new GMCatFile(\"SOUND/\" + name);\n\t\t\t}\n\t\t}\n\n\t\t// Try the preferred format first, otherwise use the default priority\n\t\tMusicFormat priority[] = { Options::preferredMusic, MUSIC_FLAC, MUSIC_OGG, MUSIC_MP3, MUSIC_MOD, MUSIC_WAV, MUSIC_ADLIB, MUSIC_GM, MUSIC_MIDI };\n\t\tfor (auto& pair : _musicDefs)\n\t\t{\n\t\t\tMusic *music = 0;\n\t\t\tfor (size_t j = 0; j < ARRAYLEN(priority) && music == 0; ++j)\n\t\t\t{\n\t\t\t\tmusic = loadMusic(priority[j], pair.second, adlibcat, aintrocat, gmcat);\n\t\t\t}\n\t\t\tif (music)\n\t\t\t{\n\t\t\t\t_musics[pair.first] = music;\n\t\t\t}\n\n\t\t}\n\n\t\tdelete gmcat;\n\t\tdelete adlibcat;\n\t\tdelete aintrocat;\n\t}\n#endif\n\n\tLog(LOG_INFO) << \"Lazy loading: \" << Options::lazyLoadResources;\n\tif (!Options::lazyLoadResources)\n\t{\n\t\tLog(LOG_INFO) << \"Loading extra resources from ruleset...\";\n\t\tfor (auto& pair : _extraSprites)\n\t\t{\n\t\t\tfor (auto* extraSprites : pair.second)\n\t\t\t{\n\t\t\t\tloadExtraSprite(extraSprites);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (!Options::mute)\n\t{\n\t\tfor (const auto& pair : _extraSounds)\n\t\t{\n\t\t\tconst auto& setName = pair.first;\n\t\t\tExtraSounds *soundPack = pair.second;\n\t\t\tSoundSet *set = 0;\n\n\t\t\tauto search = _sounds.find(setName);\n\t\t\tif (search != _sounds.end())\n\t\t\t{\n\t\t\t\tset = search->second;\n\t\t\t}\n\t\t\t_sounds[setName] = soundPack->loadSoundSet(set);\n\t\t}\n\t}\n\n\tLog(LOG_INFO) << \"Loading custom palettes from ruleset...\";\n\tfor (const auto& pair : _customPalettes)\n\t{\n\t\tCustomPalettes *palDef = pair.second;\n\t\tconst auto& palTargetName = palDef->getTarget();\n\t\tif (_palettes.find(palTargetName) == _palettes.end())\n\t\t{\n\t\t\tLog(LOG_INFO) << \"Creating a new palette: \" << palTargetName;\n\t\t\t_palettes[palTargetName] = new Palette();\n\t\t\t_palettes[palTargetName]->initBlack();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tLog(LOG_VERBOSE) << \"Replacing items in target palette: \" << palTargetName;\n\t\t}\n\n\t\tPalette *target = _palettes[palTargetName];\n\t\tconst auto& fileName = palDef->getFile();\n\t\tif (fileName.empty())\n\t\t{\n\t\t\tfor (const auto& def : *palDef->getPalette())\n\t\t\t{\n\t\t\t\ttarget->setColor(def.first, def.second.x, def.second.y, def.second.z);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// Load from JASC file\n\t\t\tauto palFile = FileMap::getIStream(fileName);\n\t\t\tstd::string line;\n\t\t\tstd::getline(*palFile, line); // header\n\t\t\tstd::getline(*palFile, line); // file format\n\t\t\tstd::getline(*palFile, line); // number of colors\n\t\t\tint r = 0, g = 0, b = 0;\n\t\t\tfor (int j = 0; j < 256; ++j)\n\t\t\t{\n\t\t\t\tstd::getline(*palFile, line); // j-th color index\n\t\t\t\tstd::stringstream ss(line);\n\t\t\t\tss >> r;\n\t\t\t\tss >> g;\n\t\t\t\tss >> b;\n\t\t\t\ttarget->setColor(j, r, g, b);\n\t\t\t}\n\t\t}\n\t}\n\n\tbool backup_logged = false;\n\tfor (auto& pal : _palettes)\n\t{\n\t\tif (pal.first.find(\"PAL_\") == 0)\n\t\t{\n\t\t\tif (!backup_logged) { Log(LOG_INFO) << \"Making palette backups...\"; backup_logged = true; }\n\t\t\tLog(LOG_VERBOSE) << \"Creating a backup for palette: \" << pal.first;\n\t\t\tstd::string newName = \"BACKUP_\" + pal.first;\n\t\t\t_palettes[newName] = new Palette();\n\t\t\t_palettes[newName]->initBlack();\n\t\t\t_palettes[newName]->copyFrom(pal.second);\n\t\t}\n\t}\n\n\t// Support for UFO-based mods and hybrid mods\n\tif (_transparencyLUTs.empty() && !_transparencies.empty())\n\t{\n\t\tif (_palettes[\"PAL_BATTLESCAPE\"])\n\t\t{\n\t\t\tLog(LOG_INFO) << \"Creating transparency LUTs for PAL_BATTLESCAPE...\";\n\t\t\tcreateTransparencyLUT(_palettes[\"PAL_BATTLESCAPE\"]);\n\t\t}\n\t\tif (_palettes[\"PAL_BATTLESCAPE_1\"] &&\n\t\t\t_palettes[\"PAL_BATTLESCAPE_2\"] &&\n\t\t\t_palettes[\"PAL_BATTLESCAPE_3\"])\n\t\t{\n\t\t\tLog(LOG_INFO) << \"Creating transparency LUTs for hybrid custom palettes...\";\n\t\t\tcreateTransparencyLUT(_palettes[\"PAL_BATTLESCAPE_1\"]);\n\t\t\tcreateTransparencyLUT(_palettes[\"PAL_BATTLESCAPE_2\"]);\n\t\t\tcreateTransparencyLUT(_palettes[\"PAL_BATTLESCAPE_3\"]);\n\t\t}\n\t}\n\n\tTextButton::soundPress = getSound(\"GEO.CAT\", Mod::BUTTON_PRESS);\n\tWindow::soundPopup[0] = getSound(\"GEO.CAT\", Mod::WINDOW_POPUP[0]);\n\tWindow::soundPopup[1] = getSound(\"GEO.CAT\", Mod::WINDOW_POPUP[1]);\n\tWindow::soundPopup[2] = getSound(\"GEO.CAT\", Mod::WINDOW_POPUP[2]);\n}\n\nvoid Mod::loadExtraSprite(ExtraSprites *spritePack)\n{\n\tif (spritePack->isLoaded())\n\t\treturn;\n\n\tif (spritePack->getSingleImage())\n\t{\n\t\tSurface *surface = 0;\n\t\tauto i = _surfaces.find(spritePack->getType());\n\t\tif (i != _surfaces.end())\n\t\t{\n\t\t\tsurface = i->second;\n\t\t}\n\n\t\t_surfaces[spritePack->getType()] = spritePack->loadSurface(surface);\n\t\tif (_statePalette)\n\t\t{\n\t\t\tif (spritePack->getType().find(\"_CPAL\") == std::string::npos)\n\t\t\t{\n\t\t\t\t_surfaces[spritePack->getType()]->setPalette(_statePalette);\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\tSurfaceSet *set = 0;\n\t\tauto i = _sets.find(spritePack->getType());\n\t\tif (i != _sets.end())\n\t\t{\n\t\t\tset = i->second;\n\t\t}\n\n\t\t_sets[spritePack->getType()] = spritePack->loadSurfaceSet(set);\n\t\tif (_statePalette)\n\t\t{\n\t\t\tif (spritePack->getType().find(\"_CPAL\") == std::string::npos)\n\t\t\t{\n\t\t\t\t_sets[spritePack->getType()]->setPalette(_statePalette);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Applies necessary modifications to vanilla resources.\n */\nvoid Mod::modResources()\n{\n\t// we're gonna need these\n\tgetSurface(\"GEOBORD.SCR\");\n\tgetSurface(\"ALTGEOBORD.SCR\", false);\n\tgetSurface(\"BACK07.SCR\");\n\tgetSurface(\"ALTBACK07.SCR\", false);\n\tgetSurface(\"BACK06.SCR\");\n\tgetSurface(\"UNIBORD.PCK\");\n\tgetSurfaceSet(\"HANDOB.PCK\");\n\tgetSurfaceSet(\"FLOOROB.PCK\");\n\tgetSurfaceSet(\"BIGOBS.PCK\");\n\n\t// embiggen the geoscape background by mirroring the contents\n\t// modders can provide their own backgrounds via ALTGEOBORD.SCR\n\tif (_surfaces.find(\"ALTGEOBORD.SCR\") == _surfaces.end())\n\t{\n\t\tint newWidth = 320 - 64, newHeight = 200;\n\t\tSurface *newGeo = new Surface(newWidth * 3, newHeight * 3);\n\t\tSurface *oldGeo = _surfaces[\"GEOBORD.SCR\"];\n\t\tfor (int x = 0; x < newWidth; ++x)\n\t\t{\n\t\t\tfor (int y = 0; y < newHeight; ++y)\n\t\t\t{\n\t\t\t\tnewGeo->setPixel(newWidth + x, newHeight + y, oldGeo->getPixel(x, y));\n\t\t\t\tnewGeo->setPixel(newWidth - x - 1, newHeight + y, oldGeo->getPixel(x, y));\n\t\t\t\tnewGeo->setPixel(newWidth * 3 - x - 1, newHeight + y, oldGeo->getPixel(x, y));\n\n\t\t\t\tnewGeo->setPixel(newWidth + x, newHeight - y - 1, oldGeo->getPixel(x, y));\n\t\t\t\tnewGeo->setPixel(newWidth - x - 1, newHeight - y - 1, oldGeo->getPixel(x, y));\n\t\t\t\tnewGeo->setPixel(newWidth * 3 - x - 1, newHeight - y - 1, oldGeo->getPixel(x, y));\n\n\t\t\t\tnewGeo->setPixel(newWidth + x, newHeight * 3 - y - 1, oldGeo->getPixel(x, y));\n\t\t\t\tnewGeo->setPixel(newWidth - x - 1, newHeight * 3 - y - 1, oldGeo->getPixel(x, y));\n\t\t\t\tnewGeo->setPixel(newWidth * 3 - x - 1, newHeight * 3 - y - 1, oldGeo->getPixel(x, y));\n\t\t\t}\n\t\t}\n\t\t_surfaces[\"ALTGEOBORD.SCR\"] = newGeo;\n\t}\n\n\t// here we create an \"alternate\" background surface for the base info screen.\n\tif (_surfaces.find(\"ALTBACK07.SCR\") == _surfaces.end())\n\t{\n\t\t_surfaces[\"ALTBACK07.SCR\"] = new Surface(320, 200);\n\t\t_surfaces[\"ALTBACK07.SCR\"]->loadScr(\"GEOGRAPH/BACK07.SCR\");\n\t\tfor (int y = 172; y >= 152; --y)\n\t\t\tfor (int x = 5; x <= 314; ++x)\n\t\t\t\t_surfaces[\"ALTBACK07.SCR\"]->setPixel(x, y + 4, _surfaces[\"ALTBACK07.SCR\"]->getPixel(x, y));\n\t\tfor (int y = 147; y >= 134; --y)\n\t\t\tfor (int x = 5; x <= 314; ++x)\n\t\t\t\t_surfaces[\"ALTBACK07.SCR\"]->setPixel(x, y + 9, _surfaces[\"ALTBACK07.SCR\"]->getPixel(x, y));\n\t\tfor (int y = 132; y >= 109; --y)\n\t\t\tfor (int x = 5; x <= 314; ++x)\n\t\t\t\t_surfaces[\"ALTBACK07.SCR\"]->setPixel(x, y + 10, _surfaces[\"ALTBACK07.SCR\"]->getPixel(x, y));\n\t}\n\n\t// we create extra rows on the soldier stat screens by shrinking them all down one pixel/two pixels.\n\tint rowHeight = _manaEnabled ? 10 : 11;\n\tbool moveOnePixelUp = _manaEnabled ? false : true;\n\n\t// first, let's do the base info screen\n\t// erase the old lines, copying from a +2 offset to account for the dithering\n\tfor (int y = 91; y < 199; y += 12)\n\t\tfor (int x = 0; x < 149; ++x)\n\t\t\t_surfaces[\"BACK06.SCR\"]->setPixel(x, y, _surfaces[\"BACK06.SCR\"]->getPixel(x, y + 2));\n\t// drawn new lines, use the bottom row of pixels as a basis\n\tfor (int y = 89; y < 199; y += rowHeight)\n\t\tfor (int x = 0; x < 149; ++x)\n\t\t\t_surfaces[\"BACK06.SCR\"]->setPixel(x, y, _surfaces[\"BACK06.SCR\"]->getPixel(x, 199));\n\t// finally, move the top of the graph up by one pixel, offset for the last iteration again due to dithering.\n\tif (moveOnePixelUp)\n\t{\n\t\tfor (int y = 72; y < 80; ++y)\n\t\t\tfor (int x = 0; x < 320; ++x)\n\t\t\t{\n\t\t\t\t_surfaces[\"BACK06.SCR\"]->setPixel(x, y, _surfaces[\"BACK06.SCR\"]->getPixel(x, y + (y == 79 ? 2 : 1)));\n\t\t\t}\n\t}\n\n\t// now, let's adjust the battlescape info screen.\n\tint startHere = _manaEnabled ? 191 : 190;\n\tint stopHere = _manaEnabled ? 28 : 37;\n\tbool moveDown = _manaEnabled ? false : true;\n\n\t// erase the old lines, no need to worry about dithering on this one.\n\tfor (int y = 39; y < 199; y += 10)\n\t\tfor (int x = 0; x < 169; ++x)\n\t\t\t_surfaces[\"UNIBORD.PCK\"]->setPixel(x, y, _surfaces[\"UNIBORD.PCK\"]->getPixel(x, 30));\n\t// drawn new lines, use the bottom row of pixels as a basis\n\tfor (int y = startHere; y > stopHere; y -= 9)\n\t\tfor (int x = 0; x < 169; ++x)\n\t\t\t_surfaces[\"UNIBORD.PCK\"]->setPixel(x, y, _surfaces[\"UNIBORD.PCK\"]->getPixel(x, 199));\n\t// move the top of the graph down by eight pixels to erase the row we don't need (we actually created ~1.8 extra rows earlier)\n\tif (moveDown)\n\t{\n\t\tfor (int y = 37; y > 29; --y)\n\t\t\tfor (int x = 0; x < 320; ++x)\n\t\t\t{\n\t\t\t\t_surfaces[\"UNIBORD.PCK\"]->setPixel(x, y, _surfaces[\"UNIBORD.PCK\"]->getPixel(x, y - 8));\n\t\t\t\t_surfaces[\"UNIBORD.PCK\"]->setPixel(x, y - 8, 0);\n\t\t\t}\n\t}\n\telse\n\t{\n\t\t// remove bottom line of the (entire) last row\n\t\tfor (int x = 0; x < 320; ++x)\n\t\t\t_surfaces[\"UNIBORD.PCK\"]->setPixel(x, 199, _surfaces[\"UNIBORD.PCK\"]->getPixel(x, 30));\n\t}\n}\n\n/**\n * Loads the specified music file format.\n * @param fmt Format of the music.\n * @param rule Parameters of the music.\n * @param adlibcat Pointer to ADLIB.CAT if available.\n * @param aintrocat Pointer to AINTRO.CAT if available.\n * @param gmcat Pointer to GM.CAT if available.\n * @return Pointer to the music file, or NULL if it couldn't be loaded.\n */\nMusic* Mod::loadMusic(MusicFormat fmt, RuleMusic* rule, CatFile* adlibcat, CatFile* aintrocat, GMCatFile* gmcat) const\n{\n\t/* MUSIC_AUTO, MUSIC_FLAC, MUSIC_OGG, MUSIC_MP3, MUSIC_MOD, MUSIC_WAV, MUSIC_ADLIB, MUSIC_GM, MUSIC_MIDI */\n\tstatic const std::string exts[] = { \"\", \".flac\", \".ogg\", \".mp3\", \".mod\", \".wav\", \"\", \"\", \".mid\" };\n\tMusic *music = 0;\n\tconst auto& soundContents = FileMap::getVFolderContents(\"SOUND\");\n\tsize_t track = rule->getCatPos();\n\ttry\n\t{\n\t\t// Try Adlib music\n\t\tif (fmt == MUSIC_ADLIB)\n\t\t{\n\t\t\tif (adlibcat && Options::audioBitDepth == 16)\n\t\t\t{\n\t\t\t\tif (track < adlibcat->size())\n\t\t\t\t{\n\t\t\t\t\tmusic = new AdlibMusic(rule->getNormalization());\n\t\t\t\t\tmusic->load(adlibcat->getRWops(track));\n\t\t\t\t}\n\t\t\t\t// separate intro music\n\t\t\t\telse if (aintrocat)\n\t\t\t\t{\n\t\t\t\t\ttrack -= adlibcat->size();\n\t\t\t\t\tif (track < aintrocat->size())\n\t\t\t\t\t{\n\t\t\t\t\t\tmusic = new AdlibMusic(rule->getNormalization());\n\t\t\t\t\t\tmusic->load(aintrocat->getRWops(track));\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tdelete music;\n\t\t\t\t\t\tmusic = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// Try MIDI music (from GM.CAT)\n\t\telse if (fmt == MUSIC_GM)\n\t\t{\n\t\t\t// DOS MIDI\n\t\t\tif (gmcat && track < gmcat->size())\n\t\t\t{\n\t\t\t\tmusic = gmcat->loadMIDI(track);\n\t\t\t}\n\t\t}\n\t\t// Try digital tracks\n\t\telse\n\t\t{\n\t\t\tstd::string fname = rule->getName() + exts[fmt];\n\t\t\tstd::transform(fname.begin(), fname.end(), fname.begin(), ::tolower);\n\n\t\t\tif (soundContents.find(fname) != soundContents.end())\n\t\t\t{\n\t\t\t\tmusic = new Music();\n\t\t\t\tmusic->load(\"SOUND/\" + fname);\n\t\t\t}\n\t\t}\n\t}\n\tcatch (Exception &e)\n\t{\n\t\tLog(LOG_INFO) << e.what();\n\t\tif (music) delete music;\n\t\tmusic = 0;\n\t}\n\treturn music;\n}\n\n/**\n * Preamble:\n * this is the most horrible function i've ever written, and it makes me sad.\n * this is, however, a necessary evil, in order to save massive amounts of time in the draw function.\n * when used with the default TFTD mod, this function loops 4,194,304 times\n * (4 palettes, 4 tints, 4 levels of opacity, 256 colors, 256 comparisons per)\n * each additional tint in the rulesets will result in over a million iterations more.\n * @param pal the palette to base the lookup table on.\n */\nvoid Mod::createTransparencyLUT(Palette *pal)\n{\n\tconst SDL_Color* palColors = pal->getColors(0);\n\tstd::vector<Uint8> lookUpTable;\n\t// start with the color sets\n\tlookUpTable.reserve(_transparencies.size() * TransparenciesPaletteColors * TransparenciesOpacityLevels);\n\tfor (const auto& tintLevels : _transparencies)\n\t{\n\t\t// then the opacity levels, using the alpha channel as the step\n\t\tfor (const SDL_Color& tint : tintLevels)\n\t\t{\n\t\t\t// then the palette itself\n\t\t\tfor (int currentColor = 0; currentColor < TransparenciesPaletteColors; ++currentColor)\n\t\t\t{\n\t\t\t\tSDL_Color desiredColor;\n\n\t\t\t\tdesiredColor.r = std::min(255, (palColors[currentColor].r * tint.unused / 255) + tint.r);\n\t\t\t\tdesiredColor.g = std::min(255, (palColors[currentColor].g * tint.unused / 255) + tint.g);\n\t\t\t\tdesiredColor.b = std::min(255, (palColors[currentColor].b * tint.unused / 255) + tint.b);\n\n\t\t\t\tUint8 closest = currentColor;\n\t\t\t\tint lowestDifference = INT_MAX;\n\t\t\t\t// if opacity is zero then we stay with current color, transparent color will stay same too\n\t\t\t\tif (tint.unused != 0 && currentColor != 0)\n\t\t\t\t{\n\t\t\t\t\t// now compare each color in the palette to find the closest match to our desired one\n\t\t\t\t\tfor (int comparator = 1; comparator < TransparenciesPaletteColors; ++comparator)\n\t\t\t\t\t{\n\t\t\t\t\t\tint currentDifference = Sqr(desiredColor.r - palColors[comparator].r) +\n\t\t\t\t\t\t\tSqr(desiredColor.g - palColors[comparator].g) +\n\t\t\t\t\t\t\tSqr(desiredColor.b - palColors[comparator].b);\n\n\t\t\t\t\t\tif (currentDifference < lowestDifference)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tclosest = comparator;\n\t\t\t\t\t\t\tlowestDifference = currentDifference;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tlookUpTable.push_back(closest);\n\t\t\t}\n\t\t}\n\t}\n\t_transparencyLUTs.push_back(std::move(lookUpTable));\n}\n\nStatAdjustment *Mod::getStatAdjustment(int difficulty)\n{\n\tif ((size_t)difficulty >= MaxDifficultyLevels)\n\t{\n\t\treturn &_statAdjustment[MaxDifficultyLevels - 1];\n\t}\n\treturn &_statAdjustment[difficulty];\n}\n\n/**\n * Returns the minimum amount of score the player can have,\n * otherwise they are defeated. Changes based on difficulty.\n * @return Score.\n */\nint Mod::getDefeatScore() const\n{\n\treturn _defeatScore;\n}\n\n/**\n * Returns the minimum amount of funds the player can have,\n * otherwise they are defeated.\n * @return Funds.\n */\nint Mod::getDefeatFunds() const\n{\n\treturn _defeatFunds;\n}\n\n/**\n * Enables non-vanilla difficulty features.\n * Dehumanize yourself and face the Warboy.\n * @return Is the player screwed?\n*/\nbool Mod::isDemigod() const\n{\n\treturn _difficultyDemigod;\n}\n\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tScript binding\n////////////////////////////////////////////////////////////\n\nnamespace\n{\n\ntemplate<size_t Mod::*f>\nvoid offset(const Mod *m, int &base, int modId)\n{\n\tint baseMax = (m->*f);\n\tif (base >= baseMax)\n\t{\n\t\tbase += modId;\n\t}\n}\n\nvoid getSmokeReduction(const Mod *m, int &smoke)\n{\n\t// initial smoke \"density\" of a smoke grenade is around 15 per tile\n\t// we do density/3 to get the decay of visibility\n\t// so in fresh smoke we should only have 4 tiles of visibility\n\t// this is traced in voxel space, with smoke affecting visibility every step of the way\n\n\t// 3  - coefficient of calculation (see above).\n\t// 20 - maximum view distance in vanilla Xcom.\n\t// Even if MaxViewDistance will be increased via ruleset, smoke will keep effect.\n\tsmoke = smoke * m->getMaxViewDistance() / (3 * 20);\n}\n\nvoid getUnitScript(const Mod* mod, const Unit* &unit, const std::string &name)\n{\n\tif (mod)\n\t{\n\t\tunit = mod->getUnit(name);\n\t}\n\telse\n\t{\n\t\tunit = nullptr;\n\t}\n}\nvoid getArmorScript(const Mod* mod, const Armor* &armor, const std::string &name)\n{\n\tif (mod)\n\t{\n\t\tarmor = mod->getArmor(name);\n\t}\n\telse\n\t{\n\t\tarmor = nullptr;\n\t}\n}\nvoid getItemScript(const Mod* mod, const RuleItem* &item, const std::string &name)\n{\n\tif (mod)\n\t{\n\t\titem = mod->getItem(name);\n\t}\n\telse\n\t{\n\t\titem = nullptr;\n\t}\n}\nvoid getSkillScript(const Mod* mod, const RuleSkill* &skill, const std::string &name)\n{\n\tif (mod)\n\t{\n\t\tskill = mod->getSkill(name);\n\t}\n\telse\n\t{\n\t\tskill = nullptr;\n\t}\n}\nvoid getRuleResearch(const Mod* mod, const RuleResearch*& rule, const std::string& name)\n{\n\tif (mod)\n\t{\n\t\trule = mod->getResearch(name);\n\t}\n\telse\n\t{\n\t\trule = nullptr;\n\t}\n}\nvoid getSoldierScript(const Mod* mod, const RuleSoldier* &soldier, const std::string &name)\n{\n\tif (mod)\n\t{\n\t\tsoldier = mod->getSoldier(name);\n\t}\n\telse\n\t{\n\t\tsoldier = nullptr;\n\t}\n}\nvoid getInventoryScript(const Mod* mod, const RuleInventory* &inv, const std::string &name)\n{\n\tif (mod)\n\t{\n\t\tinv = mod->getInventory(name);\n\t}\n\telse\n\t{\n\t\tinv = nullptr;\n\t}\n}\n\n} // namespace\n\n/**\n * Register all useful function used by script.\n */\nvoid Mod::ScriptRegister(ScriptParserBase *parser)\n{\n\tparser->registerPointerType<Unit>();\n\tparser->registerPointerType<RuleItem>();\n\tparser->registerPointerType<Armor>();\n\tparser->registerPointerType<RuleSkill>();\n\tparser->registerPointerType<RuleResearch>();\n\tparser->registerPointerType<RuleSoldier>();\n\tparser->registerPointerType<RuleInventory>();\n\n\tBind<Mod> mod = { parser };\n\n\tmod.add<&offset<&Mod::_soundOffsetBattle>>(\"getSoundOffsetBattle\", \"convert mod sound index in first argument to runtime index in given set, second argument is mod id\");\n\tmod.add<&offset<&Mod::_soundOffsetGeo>>(\"getSoundOffsetGeo\", \"convert mod sound index in first argument to runtime index in given set, second argument is mod id\");\n\tmod.add<&offset<&Mod::_surfaceOffsetBasebits>>(\"getSpriteOffsetBasebits\", \"convert mod surface index in first argument to runtime index in given set, second argument is mod id\");\n\tmod.add<&offset<&Mod::_surfaceOffsetBigobs>>(\"getSpriteOffsetBigobs\", \"convert mod surface index in first argument to runtime index in given set, second argument is mod id\");\n\tmod.add<&offset<&Mod::_surfaceOffsetFloorob>>(\"getSpriteOffsetFloorob\", \"convert mod surface index in first argument to runtime index in given set, second argument is mod id\");\n\tmod.add<&offset<&Mod::_surfaceOffsetHandob>>(\"getSpriteOffsetHandob\", \"convert mod surface index in first argument to runtime index in given set, second argument is mod id\");\n\tmod.add<&offset<&Mod::_surfaceOffsetHit>>(\"getSpriteOffsetHit\", \"convert mod surface index in first argument to runtime index in given set, second argument is mod id\");\n\tmod.add<&offset<&Mod::_surfaceOffsetSmoke>>(\"getSpriteOffsetSmoke\", \"convert mod surface index in first argument to runtime index in given set, second argument is mod id\");\n\tmod.add<&Mod::getMaxDarknessToSeeUnits>(\"getMaxDarknessToSeeUnits\");\n\tmod.add<&Mod::getMaxViewDistance>(\"getMaxViewDistance\");\n\tmod.add<&getSmokeReduction>(\"getSmokeReduction\");\n\n\tmod.add<&getUnitScript>(\"getRuleUnit\");\n\tmod.add<&getItemScript>(\"getRuleItem\");\n\tmod.add<&getArmorScript>(\"getRuleArmor\");\n\tmod.add<&getSkillScript>(\"getRuleSkill\");\n\tmod.add<&getRuleResearch>(\"getRuleResearch\");\n\tmod.add<&getSoldierScript>(\"getRuleSoldier\");\n\tmod.add<&getInventoryScript>(\"getRuleInventory\");\n\tmod.add<&Mod::getInventoryRightHand>(\"getRuleInventoryRightHand\");\n\tmod.add<&Mod::getInventoryLeftHand>(\"getRuleInventoryLeftHand\");\n\tmod.add<&Mod::getInventoryBackpack>(\"getRuleInventoryBackpack\");\n\tmod.add<&Mod::getInventoryBelt>(\"getRuleInventoryBelt\");\n\tmod.add<&Mod::getInventoryGround>(\"getRuleInventoryGround\");\n\n\tmod.addScriptValue<&Mod::_scriptGlobal, &ModScriptGlobal::getScriptValues>();\n}\n\n\n#ifndef NDEBUG\n\nstatic auto dummyParseDate = ([]\n{\n\tassert(OxceVersionDate(OPENXCOM_VERSION_GIT));\n\tassert(OxceVersionDate(\" (v1976-04-23)\"));\n\tassert(OxceVersionDate(\" (v9999-99-99)\")); //accept impossible dates\n\tassert(OxceVersionDate(\" (v   6-04-23)\"));\n\tassert(OxceVersionDate(\" (v   1- 1- 1)\"));\n\n\tassert(!OxceVersionDate(\" (v21976-04-23)\"));\n\tassert(!OxceVersionDate(\" (v1976-034-22)\"));\n\tassert(!OxceVersionDate(\" (v1976-04-232)\"));\n\tassert(!OxceVersionDate(\" (v1976-b4-23)\"));\n\n\tassert(!OxceVersionDate(\"\"));\n\tassert(!OxceVersionDate(\" (v\"));\n\tassert(!OxceVersionDate(\" (v)\"));\n\tassert(!OxceVersionDate(\" (v 1976-04-23)\"));\n\tassert(!OxceVersionDate(\" (v1976- 04-23)\"));\n\tassert(!OxceVersionDate(\" (v1976-04- 23)\"));\n\tassert(!OxceVersionDate(\" (v1976-04-23 )\"));\n\tassert(!OxceVersionDate(\" (v    -  -  )\"));\n\tassert(!OxceVersionDate(\" (v   0- 0- 0)\"));\n\tassert(!OxceVersionDate(\" (v 1 1- 1- 1)\"));\n\n\t{\n\t\tOxceVersionDate d(\"   (v1976-04-23)\");\n\t\tassert(d && d.year == 1976 && d.month == 04 && d.day == 23);\n\t}\n\n\t{\n\t\tOxceVersionDate d(\"   (v1976-04-22)    \");\n\t\tassert(d && d.year == 1976 && d.month == 04 && d.day == 22);\n\t}\n\n\t{\n\t\tOxceVersionDate d(\" aaads  (v1976-04-22)  sdafdfsfsd  \");\n\t\tassert(d && d.year == 1976 && d.month == 04 && d.day == 22);\n\t}\n\n\treturn 0;\n})();\n#endif\n\n}\n"
  },
  {
    "path": "src/Mod/Mod.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <map>\n#include <unordered_map>\n#include <vector>\n#include <string>\n#include <bitset>\n#include <array>\n#include <SDL.h>\n#include \"../Engine/Yaml.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/FileMap.h\"\n#include \"../Engine/Collections.h\"\n#include \"../Savegame/GameTime.h\"\n#include \"../Savegame/Soldier.h\"\n#include \"RuleDamageType.h\"\n#include \"RuleAlienMission.h\"\n#include \"RuleBaseFacilityFunctions.h\"\n#include \"RuleItem.h\"\n\nnamespace OpenXcom\n{\n\nclass Surface;\nclass SurfaceSet;\nclass Font;\nclass Palette;\nclass Music;\nclass SoundSet;\nclass Sound;\nclass CatFile;\nclass GMCatFile;\nclass Music;\nclass Palette;\nclass SavedGame;\nclass Soldier;\nclass RuleCountry;\nclass RuleRegion;\nclass RuleBaseFacility;\nclass RuleCraft;\nclass RuleCraftWeapon;\nclass RuleItemCategory;\nclass RuleItem;\nclass RuleWeaponSet;\nstruct RuleDamageType;\nclass RuleUfo;\nclass RuleTerrain;\nclass MapDataSet;\nclass RuleSkill;\nclass RuleSoldier;\nclass Unit;\nclass Armor;\nclass ArticleDefinition;\nclass RuleInventory;\nclass RuleResearch;\nclass RuleManufacture;\nclass RuleManufactureShortcut;\nclass RuleSoldierBonus;\nclass RuleSoldierTransformation;\nclass AlienRace;\nclass RuleEnviroEffects;\nclass RuleStartingCondition;\nclass AlienDeployment;\nclass UfoTrajectory;\nclass RuleAlienMission;\nclass Base;\nclass MCDPatch;\nclass ExtraSprites;\nclass ExtraSounds;\nclass CustomPalettes;\nclass ExtraStrings;\nclass RuleCommendations;\nclass StatString;\nclass RuleInterface;\nclass RuleGlobe;\nclass RuleConverter;\nclass SoundDefinition;\nclass MapScript;\nclass ModInfo;\nclass RuleVideo;\nclass RuleMusic;\nclass RuleArcScript;\nclass RuleEventScript;\nclass RuleEvent;\nclass RuleMissionScript;\nclass ModScript;\nclass ModScriptGlobal;\nclass ScriptParserBase;\nclass ScriptGlobal;\nstruct StatAdjustment;\n\nenum GameDifficulty : int;\nenum AIAttackWeight : int;\n\n/**\n * Mod data used when loading resources\n */\nstruct ModData\n{\n\t/// Mod name\n\tstd::string name;\n\t/// Optional info about mod\n\tconst ModInfo* info;\n\t/// Offset that mod use is common sets\n\tsize_t offset;\n\t/// Maximum size allowed by mod in common sets\n\tsize_t size;\n};\n\n/**\n * Helper exception representing the final message with all the required context for the end user to fix the errors in rulesets\n */\nstruct LoadRuleException : Exception\n{\n\tLoadRuleException(const std::string& parent, const YAML::YamlNodeReader& reader, const std::string& message)\n\t\t: Exception{\"Error for '\" + parent + \"': \" + message + \" at line \" + std::to_string(reader.getLocationInFile().line)}\n\t{\n\n\t}\n\n\tLoadRuleException(const std::string& parent, const std::string& message) : Exception{ \"Error for '\" + parent + \"': \" + message}\n\t{\n\n\t}\n};\n\n/**\n * Contains all the game-specific static data that never changes\n * throughout the game, like rulesets and resources.\n */\nclass Mod\n{\npublic:\n\t/// Number of color per opacity level.\n\tconstexpr static int TransparenciesPaletteColors = 256;\n\t/// Number of opacity levels.\n\tconstexpr static int TransparenciesOpacityLevels = 4;\n\nprivate:\n\tMusic *_muteMusic;\n\tSound *_muteSound;\n\tstd::string _playingMusic, _currentMusicTrack;\n\n\tstd::map<std::string, Palette*> _palettes;\n\tstd::map<std::string, Font*> _fonts;\n\tstd::map<std::string, Surface*> _surfaces;\n\tstd::map<std::string, SurfaceSet*> _sets;\n\tstd::map<std::string, SoundSet*> _sounds;\n\tstd::map<std::string, Music*> _musics;\n\tstd::vector<Uint16> _voxelData;\n\tstd::vector<std::vector<Uint8> > _transparencyLUTs;\n\n\tstd::map<std::string, RuleCountry*> _countries, _extraGlobeLabels;\n\tstd::map<std::string, RuleRegion*> _regions;\n\tstd::map<std::string, RuleBaseFacility*> _facilities;\n\tstd::map<std::string, RuleCraft*> _crafts;\n\tstd::map<std::string, RuleCraftWeapon*> _craftWeapons;\n\tstd::map<std::string, RuleItemCategory*> _itemCategories;\n\tstd::map<std::string, RuleItem*> _items;\n\tstd::map<std::string, RuleWeaponSet*> _weaponSets;\n\tstd::map<std::string, RuleUfo*> _ufos;\n\tstd::map<std::string, RuleTerrain*> _terrains;\n\tstd::map<std::string, MapDataSet*> _mapDataSets;\n\tstd::map<std::string, RuleSkill*> _skills;\n\tstd::map<std::string, RuleSoldier*> _soldiers;\n\tstd::map<std::string, Unit*> _units;\n\tstd::map<std::string, AlienRace*> _alienRaces;\n\tstd::map<std::string, RuleEnviroEffects*> _enviroEffects;\n\tstd::map<std::string, RuleStartingCondition*> _startingConditions;\n\tstd::map<std::string, AlienDeployment*> _alienDeployments;\n\tstd::map<std::string, Armor*> _armors;\n\tstd::map<std::string, ArticleDefinition*> _ufopaediaArticles;\n\tstd::map<std::string, RuleInventory*> _invs;\n\tbool _inventoryOverlapsPaperdoll;\n\tstd::map<std::string, RuleResearch *> _research;\n\tstd::map<std::string, RuleManufacture *> _manufacture;\n\tstd::map<std::string, RuleManufactureShortcut *> _manufactureShortcut;\n\tstd::map<std::string, RuleSoldierBonus *> _soldierBonus;\n\tstd::map<std::string, RuleSoldierTransformation *> _soldierTransformation;\n\tstd::map<std::string, UfoTrajectory *> _ufoTrajectories;\n\tstd::map<std::string, RuleAlienMission *> _alienMissions;\n\tstd::map<std::string, RuleInterface *> _interfaces;\n\tstd::map<std::string, SoundDefinition *> _soundDefs;\n\tstd::map<std::string, RuleVideo *>_videos;\n\tstd::map<std::string, MCDPatch *> _MCDPatches;\n\tstd::map<std::string, std::vector<MapScript *> > _mapScripts;\n\tstd::map<std::string, RuleCommendations *> _commendations;\n\tstd::map<std::string, RuleArcScript*> _arcScripts;\n\tstd::map<std::string, RuleEventScript*> _eventScripts;\n\tstd::map<std::string, RuleEvent*> _events;\n\tstd::map<std::string, RuleMissionScript*> _missionScripts;\n\tstd::map<std::string, RuleMissionScript*> _adhocScripts;\n\tstd::map<std::string, std::vector<ExtraSprites *> > _extraSprites;\n\tstd::map<std::string, CustomPalettes *> _customPalettes;\n\tstd::vector<std::pair<std::string, ExtraSounds *> > _extraSounds;\n\tstd::map<std::string, ExtraStrings *> _extraStrings;\n\tstd::vector<StatString*> _statStrings;\n\tstd::vector<RuleDamageType*> _damageTypes;\n\tstd::map<std::string, RuleMusic *> _musicDefs;\n\n\tRuleGlobe *_globe;\n\tRuleConverter *_converter;\n\tModScriptGlobal *_scriptGlobal;\n\n\tint _maxViewDistance, _maxDarknessToSeeUnits;\n\tint _maxStaticLightDistance, _maxDynamicLightDistance, _enhancedLighting;\n\tint _costHireEngineer, _costHireScientist;\n\tint _costEngineer, _costScientist, _timePersonnel, _hireByCountryOdds, _hireByRegionOdds, _initialFunding;\n\tint _globalTransferCostMult, _globalTransferCostDiv;\n\n\tint _aiUseDelayBlaster, _aiUseDelayFirearm, _aiUseDelayGrenade, _aiUseDelayProxy, _aiUseDelayMelee, _aiUseDelayPsionic, _aiUseDelayMedikit;\n\tint _aiFireChoiceIntelCoeff, _aiFireChoiceAggroCoeff;\n\tbool _aiExtendedFireModeChoice, _aiRespectMaxRange, _aiDestroyBaseFacilities;\n\tbool _aiPickUpWeaponsMoreActively, _aiPickUpWeaponsMoreActivelyCiv;\n\tint _aiReactionFireThreshold, _aiReactionFireThresholdCiv;\n\tAIAttackWeight _aiTargetWeightThreatThreshold = AIAttackWeight{ 50 };\n\tAIAttackWeight _aiTargetWeightAsHostile = AIAttackWeight{ 100 };\n\tAIAttackWeight _aiTargetWeightAsHostileCivilians = AIAttackWeight{ 50 };\n\tAIAttackWeight _aiTargetWeightAsFriendly = AIAttackWeight{ -200 };\n\tAIAttackWeight _aiTargetWeightAsNeutral = AIAttackWeight{ -100 };\n\n\tint _maxLookVariant, _tooMuchSmokeThreshold, _customTrainingFactor;\n\tint _chanceToStopRetaliation;\n\tint _chanceToDetectAlienBaseEachMonth;\n\tbool _lessAliensDuringBaseDefense;\n\tbool _allowCountriesToCancelAlienPact, _buildInfiltrationBaseCloseToTheCountry, _infiltrateRandomCountryInTheRegion;\n\tbool _allowAlienBasesOnWrongTextures;\n\tint _kneelBonusGlobal, _oneHandedPenaltyGlobal;\n\tint _enableCloseQuartersCombat, _closeQuartersAccuracyGlobal, _closeQuartersTuCostGlobal, _closeQuartersEnergyCostGlobal, _closeQuartersSneakUpGlobal;\n\tint _noLOSAccuracyPenaltyGlobal;\n\tint _explodeInventoryGlobal;\n\tint _surrenderMode;\n\tint _bughuntMinTurn, _bughuntMaxEnemies, _bughuntRank, _bughuntLowMorale, _bughuntTimeUnitsLeft;\n\n\tint _manaMissingWoundThreshold = 200;\n\tint _healthMissingWoundThreshold = 100;\n\tbool _manaEnabled, _manaBattleUI, _manaTrainingPrimary, _manaTrainingSecondary, _manaReplenishAfterMission;\n\tbool _healthReplenishAfterMission = true;\n\tstd::string _manaUnlockResearch;\n\n\tstd::string _loseMoney, _loseRating, _loseDefeat;\n\tint _ufoGlancingHitThreshold, _ufoBeamWidthParameter;\n\tint _ufoTractorBeamSizeModifiers[5];\n\tint _escortRange, _drawEnemyRadarCircles;\n\tbool _escortsJoinFightAgainstHK, _hunterKillerFastRetarget;\n\tint _crewEmergencyEvacuationSurvivalChance, _pilotsEmergencyEvacuationSurvivalChance;\n\tbool _showUfoPreviewInBaseDefense;\n\tstd::array<int, (size_t)(RANK_COMMANDER + 1)> _soldiersPerRank;\n\tint _pilotAccuracyZeroPoint, _pilotAccuracyRange, _pilotReactionsZeroPoint, _pilotReactionsRange;\n\tint _pilotBraveryThresholds[3];\n\tdouble _performanceBonusFactor;\n\tbool _enableNewResearchSorting;\n\tint _displayCustomCategories;\n\tbool _shareAmmoCategories, _showDogfightDistanceInKm, _showFullNameInAlienInventory;\n\tint _alienInventoryOffsetX, _alienInventoryOffsetBigUnit;\n\tbool _hidePediaInfoButton;\n\tint _extraNerdyPediaInfoType;\n\tbool _giveScoreAlsoForResearchedArtifacts, _statisticalBulletConservation, _stunningImprovesMorale;\n\tint _tuRecoveryWakeUpNewTurn;\n\tint _shortRadarRange;\n\tint _buildTimeReductionScaling;\n\tint _defeatScore, _defeatFunds;\n\tbool _difficultyDemigod;\n\tstd::pair<std::string, int> _alienFuel;\n\tRuleResearch* _finalResearch = nullptr;\n\tstd::string _fontName, _psiUnlockResearch, _fakeUnderwaterBaseUnlockResearch, _newBaseUnlockResearch;\n\tstd::string _hireScientistsUnlockResearch, _hireEngineersUnlockResearch;\n\tRuleBaseFacilityFunctions _hireScientistsRequiresBaseFunc, _hireEngineersRequiresBaseFunc;\n\n\tstd::string _destroyedFacility;\n\tYAML::YamlString _startingBaseDefault, _startingBaseBeginner, _startingBaseExperienced, _startingBaseVeteran, _startingBaseGenius, _startingBaseSuperhuman;\n\tCollections::NamesToIndex _baseFunctionNames;\n\n\tGameTime _startingTime;\n\tint _startingDifficulty;\n\tint _baseDefenseMapFromLocation;\n\tstd::map<int, std::string> _missionRatings, _monthlyRatings;\n\tstd::map<std::string, std::string> _fixedUserOptions, _recommendedUserOptions;\n\tstd::vector<std::string> _hiddenMovementBackgrounds;\n\tstd::vector<std::string> _baseNamesFirst, _baseNamesMiddle, _baseNamesLast;\n\tstd::vector<std::string> _operationNamesFirst, _operationNamesLast;\n\tbool _disableUnderwaterSounds;\n\tbool _enableUnitResponseSounds;\n\tstd::map<std::string, std::vector<int> > _selectUnitSound, _startMovingSound, _selectWeaponSound, _annoyedSound;\n\tstd::vector<int> _selectBaseSound, _startDogfightSound;\n\tstd::vector<int> _flagByKills;\n\tint _pediaReplaceCraftFuelWithRangeType;\n\tstd::vector<StatAdjustment> _statAdjustment;\n\n\t// overrides for DIFFICULTY_COEFFICIENT[]\n\tstd::vector<int> _monthlyRatingThresholds;\n\tstd::vector<int> _ufoFiringRateCoefficients;\n\tstd::vector<int> _ufoEscapeCountdownCoefficients;\n\tstd::vector<int> _retaliationTriggerOdds;\n\tstd::vector<int> _retaliationBaseRegionOdds;\n\tstd::vector<int> _aliensFacingCraftOdds;\n\n\tstd::map<std::string, int> _ufopaediaSections;\n\tstd::vector<std::string> _countriesIndex, _extraGlobeLabelsIndex, _regionsIndex, _facilitiesIndex, _craftsIndex, _craftWeaponsIndex, _itemCategoriesIndex, _itemsIndex, _invsIndex, _ufosIndex;\n\tstd::vector<std::string> _aliensIndex, _enviroEffectsIndex, _startingConditionsIndex, _deploymentsIndex, _armorsIndex, _ufopaediaIndex, _ufopaediaCatIndex, _researchIndex, _manufactureIndex;\n\tstd::vector<std::string> _skillsIndex, _soldiersIndex, _soldierTransformationIndex, _soldierBonusIndex;\n\tstd::vector<std::string> _alienMissionsIndex, _terrainIndex, _customPalettesIndex, _arcScriptIndex, _eventScriptIndex, _eventIndex, _missionScriptIndex, _adhocScriptIndex;\n\tstd::vector<std::vector<int> > _alienItemLevels;\n\tstd::vector<std::array<SDL_Color, TransparenciesOpacityLevels>> _transparencies;\n\tint _facilityListOrder, _craftListOrder, _itemCategoryListOrder, _itemListOrder, _armorListOrder, _alienRaceListOrder, _researchListOrder,  _manufactureListOrder;\n\tint _soldierBonusListOrder, _transformationListOrder, _ufopaediaListOrder, _invListOrder, _soldierListOrder;\n\tstd::vector<ModData> _modData;\n\tModData* _modCurrent;\n\tconst SDL_Color *_statePalette;\n\n\tstd::vector<std::string> _psiRequirements; // it's a cache for psiStrengthEval\n\tstd::vector<const Armor*> _armorsForSoldiersCache;\n\tstd::vector<const RuleItem*> _armorStorageItemsCache;\n\tstd::vector<const RuleItem*> _craftWeaponStorageItemsCache;\n\t/// Track of what mod create rule object.\n\tstd::unordered_map<const void*, const ModData*> _ruleCreationTracking;\n\t/// Track of what mod last update rule object.\n\tstd::unordered_map<const void*, const ModData*> _ruleLastUpdateTracking;\n\n\tsize_t _surfaceOffsetBigobs = 0;\n\tsize_t _surfaceOffsetFloorob = 0;\n\tsize_t _surfaceOffsetHandob = 0;\n\tsize_t _surfaceOffsetSmoke = 0;\n\tsize_t _surfaceOffsetHit = 0;\n\tsize_t _surfaceOffsetBasebits = 0;\n\tsize_t _soundOffsetBattle = 0;\n\tsize_t _soundOffsetGeo = 0;\n\n\t/// Loads a ruleset from a YAML file that have basic resources configuration.\n\tvoid loadResourceConfigFile(const FileMap::FileRecord &filerec);\n\tvoid loadConstants(const YAML::YamlNodeReader& reader);\n\t/// Loads a ruleset from a YAML file.\n\tvoid loadFile(const FileMap::FileRecord &filerec, ModScript &parsers);\n\n\ttemplate<typename T>\n\tstruct RuleFactory\n\t{\n\t\tT* operator()(const std::string& type) { return new T(type); }\n\t};\n\ttemplate<typename T>\n\tstruct RuleListOrderedFactory\n\t{\n\t\tint& _currentListOrder;\n\t\tint offset;\n\n\t\tT* operator()(const std::string& type) { _currentListOrder += offset; return new T(type, _currentListOrder); }\n\t};\n\n\t/// Loads a ruleset element.\n\ttemplate <typename T, typename F = RuleFactory<T>>\n\tT* loadRule(const YAML::YamlNodeReader& reader, std::map<std::string, T*>* map, std::vector<std::string>* index = 0, const std::string& key = \"type\", F&& factory = {});\n\t/// Gets a ruleset element.\n\ttemplate <typename T>\n\tT *getRule(const std::string &id, const std::string &name, const std::map<std::string, T*> &map, bool error) const;\n\t/// Gets a random music. This is private to prevent access, use playMusic(name, true) instead.\n\tMusic *getRandomMusic(const std::string &name) const;\n\t/// Gets a particular sound set. This is private to prevent access, use getSound(name, id) instead.\n\tSoundSet *getSoundSet(const std::string &name, bool error = true) const;\n\t/// Loads battlescape specific resources.\n\tvoid loadBattlescapeResources();\n\t/// Loads a specified music file.\n\tMusic* loadMusic(MusicFormat fmt, RuleMusic* rule, CatFile* adlibcat, CatFile* aintrocat, GMCatFile* gmcat) const;\n\t/// Creates a transparency lookup table for a given palette.\n\tvoid createTransparencyLUT(Palette *pal);\n\t/// Loads a specified mod content.\n\tvoid loadMod(const std::vector<FileMap::FileRecord> &rulesetFiles, ModScript &parsers);\n\t/// Loads resources from vanilla.\n\tvoid loadVanillaResources();\n\t/// Loads resources from extra rulesets.\n\tvoid loadExtraResources();\n\t/// Loads surfaces on demand.\n\tvoid lazyLoadSurface(const std::string &name);\n\t/// Loads an external sprite.\n\tvoid loadExtraSprite(ExtraSprites *spritePack);\n\t/// Applies mods to vanilla resources.\n\tvoid modResources();\n\t/// Sorts all our lists according to their weight.\n\tvoid sortLists();\npublic:\n\tstatic int DOOR_OPEN;\n\tstatic int SLIDING_DOOR_OPEN;\n\tstatic int SLIDING_DOOR_CLOSE;\n\tstatic int SMALL_EXPLOSION;\n\tstatic int LARGE_EXPLOSION;\n\tstatic int EXPLOSION_OFFSET;\n\tstatic int SMOKE_OFFSET;\n\tstatic int UNDERWATER_SMOKE_OFFSET;\n\n\t/// Empty surface.\n\tconstexpr static int NO_SURFACE = -1;\n\t/// Empty sound.\n\tconstexpr static int NO_SOUND = -1;\n\t/// Special value for default string different to empty one.\n\tstatic const std::string STR_NULL;\n\n\tstatic int ITEM_DROP;\n\tstatic int ITEM_THROW;\n\tstatic int ITEM_RELOAD;\n\tstatic int WALK_OFFSET;\n\tstatic int FLYING_SOUND;\n\tstatic int BUTTON_PRESS;\n\tstatic int WINDOW_POPUP[3];\n\tstatic int UFO_FIRE;\n\tstatic int UFO_HIT;\n\tstatic int UFO_CRASH;\n\tstatic int UFO_EXPLODE;\n\tstatic int INTERCEPTOR_HIT;\n\tstatic int INTERCEPTOR_EXPLODE;\n\n\tstatic int GEOSCAPE_CURSOR;\n\tstatic int BASESCAPE_CURSOR;\n\tstatic int BATTLESCAPE_CURSOR;\n\tstatic int UFOPAEDIA_CURSOR;\n\tstatic int GRAPHS_CURSOR;\n\tstatic int DAMAGE_RANGE;\n\tstatic int EXPLOSIVE_DAMAGE_RANGE;\n\tstatic int FIRE_DAMAGE_RANGE[2];\n\tstatic std::string DEBRIEF_MUSIC_GOOD;\n\tstatic std::string DEBRIEF_MUSIC_BAD;\n\tstatic int DIFFICULTY_COEFFICIENT[5];\n\tstatic int SELL_PRICE_COEFFICIENT[5];\n\tstatic int BUY_PRICE_COEFFICIENT[5];\n\tstatic int DIFFICULTY_BASED_RETAL_DELAY[5];\n\tstatic int UNIT_RESPONSE_SOUNDS_FREQUENCY[4];\n\tstatic int PEDIA_FACILITY_RENDER_PARAMETERS[4];\n\tstatic bool EXTENDED_ITEM_RELOAD_COST;\n\tstatic bool EXTENDED_INVENTORY_SLOT_SORTING;\n\tstatic bool EXTENDED_RUNNING_COST;\n\tstatic int EXTENDED_MOVEMENT_COST_ROUNDING;\n\tstatic bool EXTENDED_HWP_LOAD_ORDER;\n\tstatic int EXTENDED_SPOT_ON_HIT_FOR_SNIPING;\n\tstatic int EXTENDED_BERSERK_WITH_AIMED;\n\tstatic int EXTENDED_MELEE_REACTIONS;\n\tstatic int EXTENDED_TERRAIN_MELEE;\n\tstatic int EXTENDED_UNDERWATER_THROW_FACTOR;\n\tstatic bool EXTENDED_EXPERIENCE_AWARD_SYSTEM;\n\tstatic bool EXTENDED_FORCE_SPAWN;\n\tstatic int EXTENDED_SMOKE_OFFSET;\n\n\n\t/// Return `true` when given string is empty or pseudo null value.\n\tstatic bool isEmptyRuleName(const std::string& s)\n\t{\n\t\treturn s.empty() || s == Mod::STR_NULL;\n\t}\n\t// reset all the statics in all classes to default values\n\tstatic void resetGlobalStatics();\n\n\t/// Name of class used in script.\n\tstatic constexpr const char *ScriptName = \"RuleMod\";\n\t/// Register all useful function used by script.\n\tstatic void ScriptRegister(ScriptParserBase* parser);\n\n\t/// Creates a blank mod.\n\tMod();\n\t/// Cleans up the mod.\n\t~Mod();\n\n\t/// For internal use only\n\tconst std::map<std::string, int> &getUfopaediaSections() const { return _ufopaediaSections; }\n\n\t/// Gets a particular font.\n\tFont *getFont(const std::string &name, bool error = true) const;\n\t/// Gets a particular surface.\n\tSurface *getSurface(const std::string &name, bool error = true);\n\t/// Gets a particular surface set.\n\tSurfaceSet *getSurfaceSet(const std::string &name, bool error = true);\n\t/// Gets a particular music.\n\tMusic *getMusic(const std::string &name, bool error = true) const;\n\t/// Gets the available music tracks.\n\tconst std::map<std::string, Music*> &getMusicTrackList() const;\n\tconst std::string& getCurrentMusicTrack() const { return _currentMusicTrack; }\n\tvoid setCurrentMusicTrack(const std::string& currentMusicTrack) { _currentMusicTrack = currentMusicTrack; }\n\t/// Plays a particular music.\n\tvoid playMusic(const std::string &name, int id = 0);\n\t/// Gets a particular sound.\n\tSound *getSound(const std::string &set, int sound) const;\n\t/// Gets all palettes.\n\tconst std::map<std::string, Palette*> &getPalettes() const { return _palettes; }\n\t/// Gets a particular palette.\n\tPalette *getPalette(const std::string &name, bool error = true) const;\n\t/// Gets list of voxel data.\n\tconst std::vector<Uint16> *getVoxelData() const;\n\t/// Returns a specific sound from either the land or underwater sound set.\n\tSound *getSoundByDepth(unsigned int depth, unsigned int sound) const;\n\t/// Gets list of LUT data.\n\tconst std::vector<std::vector<Uint8> > *getLUTs() const;\n\n\n\t/// Check for obsolete error based on year.\n\tbool checkForObsoleteErrorByYear(const std::string& parent, const YAML::YamlNodeReader& reader, const std::string& error, int year) const;\n\t/// Check for error that we can ignore by user request.\n\tbool checkForSoftError(bool check, const std::string& parent, const YAML::YamlNodeReader& reader, const std::string& error, SeverityLevel level = LOG_WARNING) const;\n\t/// Check for error that we can ignore by user request.\n\tbool checkForSoftError(bool check, const std::string &parent, const std::string &error, SeverityLevel level = LOG_WARNING) const;\n\n\n\t/// Verify if value have defined surface in given set.\n\tvoid verifySpriteOffset(const std::string &parent, const int& sprite, const std::string &set) const;\n\t/// Verify if value have defined surface in given set.\n\tvoid verifySpriteOffset(const std::string &parent, const std::vector<int>& sprites, const std::string &set) const;\n\t/// Verify if value have defined sound in given set.\n\tvoid verifySoundOffset(const std::string &parent, const int& sound, const std::string &set) const;\n\t/// Verify if value have defined sound in given set.\n\tvoid verifySoundOffset(const std::string &parent, const std::vector<int>& sounds, const std::string &set) const;\n\n\n\t/// Gets the mod offset.\n\tint getModOffset() const;\n\t/// Get offset and index for sound set or sprite set.\n\tvoid loadOffsetNode(const std::string &parent, int& offset, const YAML::YamlNodeReader& reader, int shared, const std::string &set, size_t multiplier, size_t sizeScale = 1) const;\n\t/// Gets the mod offset for a certain sprite.\n\tvoid loadSpriteOffset(const std::string& parent, int& sprite, const YAML::YamlNodeReader& reader, const std::string& set, size_t multiplier = 1) const;\n\t/// Gets the mod offset array for a certain sprite.\n\tvoid loadSpriteOffset(const std::string& parent, std::vector<int>& sprites, const YAML::YamlNodeReader& reader, const std::string& set) const;\n\t/// Gets the mod offset for a certain sound.\n\tvoid loadSoundOffset(const std::string &parent, int& sound, const YAML::YamlNodeReader& reader, const std::string &set) const;\n\t/// Gets the mod offset array for a certain sound.\n\tvoid loadSoundOffset(const std::string& parent, std::vector<int>& sounds, const YAML::YamlNodeReader& reader, const std::string& set) const;\n\t/// Gets the mod offset array for a certain transparency index.\n\tvoid loadTransparencyOffset(const std::string& parent, int& index, const YAML::YamlNodeReader& reader) const;\n\t/// Gets the mod offset for a generic value.\n\tint getOffset(int id, int max) const;\n\n\t/// Gets base functions from string array in yaml.\n\tvoid loadBaseFunction(const std::string& parent, RuleBaseFacilityFunctions& f, const YAML::YamlNodeReader& reader);\n\t/// Get names of function names in given bitset.\n\tstd::vector<std::string> getBaseFunctionNames(RuleBaseFacilityFunctions f) const;\n\n\t/// Loads a list of ints.\n\tvoid loadInts(const std::string& parent, std::vector<int>& ints, const YAML::YamlNodeReader& reader) const;\n\t/// Loads a list of ints where order of items does not matter.\n\tvoid loadUnorderedInts(const std::string& parent, std::vector<int>& ints, const YAML::YamlNodeReader& reader) const;\n\n\t/// Loads a name.\n\tvoid loadName(const std::string& parent, std::string& names, const YAML::YamlNodeReader& reader) const;\n\t/// Loads a name.\n\tvoid loadNameNull(const std::string& parent, std::string& names, const YAML::YamlNodeReader& reader) const;\n\t/// Loads a list of names.\n\tvoid loadNames(const std::string& parent, std::vector<std::string>& names, const YAML::YamlNodeReader& reader) const;\n\t/// Loads a list of names where order of items does not matter.\n\tvoid loadUnorderedNames(const std::string& parent, std::vector<std::string>& names, const YAML::YamlNodeReader& reader) const;\n\n\t/// Loads a map from names to names.\n\tvoid loadNamesToNames(const std::string& parent, std::vector<std::pair<std::string, std::vector<std::string> > >& names, const YAML::YamlNodeReader& reader) const;\n\t/// Loads a map from names to names.\n\tvoid loadUnorderedNamesToNames(const std::string& parent, std::map<std::string, std::string>& names, const YAML::YamlNodeReader& reader) const;\n\t/// Loads a map from names to ints.\n\tvoid loadUnorderedNamesToInt(const std::string &parent, std::map<std::string, int>& names, const YAML::YamlNodeReader &reader) const;\n\t/// Loads a map from names to vector of ints.\n\tvoid loadUnorderedNamesToInts(const std::string& parent, std::map<std::string, std::vector<int> >& names, const YAML::YamlNodeReader& reader) const;\n\t/// Loads a map from names to names to int.\n\tvoid loadUnorderedNamesToNamesToInt(const std::string& parent, std::map<std::string, std::map<std::string, int> >& names, const YAML::YamlNodeReader& reader) const;\n\n\t/// Loads data for kill criteria from Commendations.\n\tvoid loadKillCriteria(const std::string& parent, std::vector<std::vector<std::pair<int, std::vector<std::string> > > >& names, const YAML::YamlNodeReader& reader) const;\n\n\n\t/// Convert names to correct rule objects\n\ttemplate<typename T>\n\tvoid linkRule(const T*& rule, std::string& name) const\n\t{\n\t\tif constexpr (std::is_same_v<T, RuleItem>)\n\t\t{\n\t\t\trule = getItem(name, true);\n\t\t}\n\t\telse if constexpr (std::is_same_v<T, RuleSoldier>)\n\t\t{\n\t\t\trule = getSoldier(name, true);\n\t\t}\n\t\telse if constexpr (std::is_same_v<T, RuleSoldierBonus>)\n\t\t{\n\t\t\trule = getSoldierBonus(name, true);\n\t\t}\n\t\telse if constexpr (std::is_same_v<T, Armor>)\n\t\t{\n\t\t\trule = getArmor(name, true);\n\t\t}\n\t\telse if constexpr (std::is_same_v<T, RuleResearch>)\n\t\t{\n\t\t\trule = getResearch(name, true);\n\t\t}\n\t\telse if constexpr (std::is_same_v<T, Unit>)\n\t\t{\n\t\t\trule = getUnit(name, true);\n\t\t}\n\t\telse if constexpr (std::is_same_v<T, RuleSkill>)\n\t\t{\n\t\t\trule = getSkill(name, true);\n\t\t}\n\t\telse if constexpr (std::is_same_v<T, RuleCraft>)\n\t\t{\n\t\t\trule = getCraft(name, true);\n\t\t}\n\t\telse if constexpr (std::is_same_v<T, RuleUfo>)\n\t\t{\n\t\t\trule = getUfo(name, true);\n\t\t}\n\t\telse if constexpr (std::is_same_v<T, RuleBaseFacility>)\n\t\t{\n\t\t\trule = getBaseFacility(name, true);\n\t\t}\n\t\telse if constexpr (std::is_same_v<T, RuleInventory>)\n\t\t{\n\t\t\trule = getInventory(name, true);\n\t\t}\n\t\telse if constexpr (std::is_same_v<T, RuleEvent>)\n\t\t{\n\t\t\trule = getEvent(name, true);\n\t\t}\n\t\telse if constexpr (std::is_same_v<T, RuleCommendations>)\n\t\t{\n\t\t\trule = getCommendation(name, true);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tstatic_assert(sizeof(T) == 0, \"Unsupported type to link\");\n\t\t}\n\t\tname = {};\n\t}\n\t/// Convert names to correct rule objects\n\ttemplate<typename T>\n\tvoid linkRule(std::vector<T>& rule, std::vector<std::string>& names) const\n\t{\n\t\trule.reserve(names.size());\n\t\tfor (auto& n : names)\n\t\t{\n\t\t\tlinkRule(rule.emplace_back(), n);\n\t\t}\n\t\tnames = {};\n\t}\n\t/// Convert names to correct rule objects\n\ttemplate<typename T>\n\tvoid linkRule(std::vector<T>& rule, std::vector<std::vector<std::string>>& names) const\n\t{\n\t\trule.reserve(names.size());\n\t\tfor (auto& n : names)\n\t\t{\n\t\t\tlinkRule(rule.emplace_back(), n);\n\t\t}\n\t\tnames = {};\n\t}\n\n\n\t/// Loads a list of mods.\n\tvoid loadAll();\n\t/// Generates the starting saved game.\n\tSavedGame *newSave(GameDifficulty diff) const;\n\t/// Gets the ruleset for a country type.\n\tRuleCountry *getCountry(const std::string &id, bool error = false) const;\n\t/// Gets the available countries.\n\tconst std::vector<std::string> &getCountriesList() const;\n\t/// Gets the ruleset for an extra globe label type.\n\tRuleCountry *getExtraGlobeLabel(const std::string &id, bool error = false) const;\n\t/// Gets the available extra globe labels.\n\tconst std::vector<std::string> &getExtraGlobeLabelsList() const;\n\t/// Gets the ruleset for a region type.\n\tRuleRegion *getRegion(const std::string &id, bool error = false) const;\n\t/// Gets the available regions.\n\tconst std::vector<std::string> &getRegionsList() const;\n\t/// Gets the ruleset for a facility type.\n\tRuleBaseFacility *getBaseFacility(const std::string &id, bool error = false) const;\n\t/// Gets the available facilities.\n\tconst std::vector<std::string> &getBaseFacilitiesList() const;\n\t/// Gets the ruleset for a craft type.\n\tRuleCraft *getCraft(const std::string &id, bool error = false) const;\n\t/// Gets the available crafts.\n\tconst std::vector<std::string> &getCraftsList() const;\n\n\t/// Gets the ruleset for a craft weapon type.\n\tRuleCraftWeapon *getCraftWeapon(const std::string &id, bool error = false) const;\n\t/// Gets the available craft weapons.\n\tconst std::vector<std::string> &getCraftWeaponsList() const;\n\t/// Is given item a launcher or ammo for craft weapon.\n\tbool isCraftWeaponStorageItem(const RuleItem* item) const;\n\n\t/// Gets the ruleset for an item category type.\n\tRuleItemCategory *getItemCategory(const std::string &id, bool error = false) const;\n\t/// Gets the available item categories.\n\tconst std::vector<std::string> &getItemCategoriesList() const;\n\t/// Gets the ruleset for an item type.\n\tRuleItem *getItem(const std::string &id, bool error = false) const;\n\t/// Gets the available items.\n\tconst std::vector<std::string> &getItemsList() const;\n\t/// Gets the ruleset for a weapon set type.\n\tRuleWeaponSet* getWeaponSet(const std::string& type, bool error = false) const;\n\t/// Gets the ruleset for a UFO type.\n\tRuleUfo *getUfo(const std::string &id, bool error = false) const;\n\t/// Gets the available UFOs.\n\tconst std::vector<std::string> &getUfosList() const;\n\t/// Gets terrains for battlescape games.\n\tRuleTerrain *getTerrain(const std::string &name, bool error = false) const;\n\t/// Gets the available terrains.\n\tconst std::vector<std::string> &getTerrainList() const;\n\t/// Gets mapdatafile for battlescape games.\n\tMapDataSet *getMapDataSet(const std::string &name);\n\t/// Gets skill rules.\n\tRuleSkill *getSkill(const std::string &name, bool error = false) const;\n\t/// Gets soldier unit rules.\n\tRuleSoldier *getSoldier(const std::string &name, bool error = false) const;\n\t/// Gets the available soldiers.\n\tconst std::vector<std::string> &getSoldiersList() const;\n\t/// Gets commendation rules.\n\tRuleCommendations *getCommendation(const std::string &id, bool error = false) const;\n\t/// Gets the available commendations.\n\tconst std::map<std::string, RuleCommendations *> &getCommendationsList() const;\n\t/// Gets generated unit rules.\n\tUnit *getUnit(const std::string &name, bool error = false) const;\n\t/// Gets alien race rules.\n\tAlienRace *getAlienRace(const std::string &name, bool error = false) const;\n\t/// Gets the available alien races.\n\tconst std::vector<std::string> &getAlienRacesList() const;\n\t/// Gets an enviro effects definition.\n\tRuleEnviroEffects* getEnviroEffects(const std::string& name) const;\n\t/// Gets the available enviro effects.\n\tconst std::vector<std::string>& getEnviroEffectsList() const;\n\t/// Gets a starting condition.\n\tRuleStartingCondition* getStartingCondition(const std::string& name) const;\n\t/// Gets the available starting conditions.\n\tconst std::vector<std::string>& getStartingConditionsList() const;\n\t/// Gets deployment rules.\n\tAlienDeployment *getDeployment(const std::string &name, bool error = false) const;\n\t/// Gets the available alien deployments.\n\tconst std::vector<std::string> &getDeploymentsList() const;\n\n\t/// Gets armor rules.\n\tArmor *getArmor(const std::string &name, bool error = false) const;\n\t/// Gets the all armors.\n\tconst std::vector<std::string> &getArmorsList() const;\n\t/// Gets the available armors for soldiers.\n\tconst std::vector<const Armor*> &getArmorsForSoldiers() const;\n\t/// Check if item is used for armor storage.\n\tbool isArmorStorageItem(const RuleItem* item) const;\n\n\t/// Gets Ufopaedia article definition.\n\tArticleDefinition *getUfopaediaArticle(const std::string &name, bool error = false) const;\n\t/// Gets the available articles.\n\tconst std::vector<std::string> &getUfopaediaList() const;\n\t/// Gets the available article categories.\n\tconst std::vector<std::string> &getUfopaediaCategoryList() const;\n\n\t/// Gets the inventory list.\n\tstd::map<std::string, RuleInventory*> *getInventories();\n\t/// Gets the ruleset for a specific inventory.\n\tRuleInventory *getInventory(const std::string &id, bool error = false) const;\n\t/// Gets the ruleset for right hand inventory slot.\n\tRuleInventory *getInventoryRightHand() const { return getInventory(\"STR_RIGHT_HAND\", true); }\n\t/// Gets the ruleset for left hand inventory slot.\n\tRuleInventory *getInventoryLeftHand() const { return getInventory(\"STR_LEFT_HAND\", true); }\n\t/// Gets the ruleset for backpack inventory slot.\n\tRuleInventory *getInventoryBackpack() const { return getInventory(\"STR_BACK_PACK\", true); }\n\t/// Gets the ruleset for belt inventory slot.\n\tRuleInventory *getInventoryBelt() const { return getInventory(\"STR_BELT\", true); }\n\t/// Gets the ruleset for ground inventory slot.\n\tRuleInventory *getInventoryGround() const { return getInventory(\"STR_GROUND\", true); }\n\n\t/// Gets whether or not the inventory slots overlap with the paperdoll button\n\tbool getInventoryOverlapsPaperdoll() const { return _inventoryOverlapsPaperdoll; }\n\t/// Gets max view distance in BattleScape.\n\tint getMaxViewDistance() const { return _maxViewDistance; }\n\t/// Gets threshold of darkness for LoS calculation.\n\tint getMaxDarknessToSeeUnits() const { return _maxDarknessToSeeUnits; }\n\t/// Gets max static (tiles & fire) light distance in BattleScape.\n\tint getMaxStaticLightDistance() const { return _maxStaticLightDistance; }\n\t/// Gets max dynamic (items & units) light distance in BattleScape.\n\tint getMaxDynamicLightDistance() const { return _maxDynamicLightDistance; }\n\t/// Get flags for enhanced lighting, 0x1 - tiles and fire, 0x2 - items, 0x4 - units.\n\tint getEnhancedLighting() const { return _enhancedLighting; }\n\t/// Get basic damage type\n\tconst RuleDamageType *getDamageType(ItemDamageType type) const;\n\n\t/// Gets the cost of hiring an engineer.\n\tint getHireEngineerCost() const;\n\t/// Gets the research topic required for hiring new engineers.\n\tconst std::string &getHireEngineersUnlockResearch() const { return _hireEngineersUnlockResearch; }\n\t/// Gets the base functions required for hiring new engineers.\n\tRuleBaseFacilityFunctions getHireEngineersRequiresBaseFunc() const { return _hireEngineersRequiresBaseFunc; }\n\t/// Gets the cost of hiring a scientist.\n\tint getHireScientistCost() const;\n\t/// Gets the research topic required for hiring new scientists.\n\tconst std::string &getHireScientistsUnlockResearch() const { return _hireScientistsUnlockResearch; }\n\t/// Gets the base functions topic required for hiring new scientists.\n\tRuleBaseFacilityFunctions getHireScientistsRequiresBaseFunc() const { return _hireScientistsRequiresBaseFunc; }\n\t/// Gets the monthly cost of an engineer.\n\tint getEngineerCost() const;\n\t/// Gets the monthly cost of a scientist.\n\tint getScientistCost() const;\n\t/// Gets the transfer time of personnel.\n\tint getPersonnelTime() const;\n\t/// Gets the odds of hiring soldiers by country.\n\tint getHireByCountryOdds() const { return _hireByCountryOdds; }\n\t/// Gets the odds of hiring soldiers by region.\n\tint getHireByRegionOdds() const { return _hireByRegionOdds; }\n\n\t/// Gets the global transfer cost multiplier.\n\tint getGlobalTransferCostMultiplier() const { return _globalTransferCostMult; }\n\t/// Gets the global transfer cost divider.\n\tint getGlobalTransferCostDivider() const { return _globalTransferCostDiv; }\n\n\t/// Gets first turn when AI can use Blaster launcher.\n\tint getAIUseDelayBlaster() const  {return _aiUseDelayBlaster;}\n\t/// Gets first turn when AI can use firearms.\n\tint getAIUseDelayFirearm() const  {return _aiUseDelayFirearm;}\n\t/// Gets first turn when AI can use grenades.\n\tint getAIUseDelayGrenade() const  {return _aiUseDelayGrenade;}\n\t/// Gets first turn when AI can use proxy grenades.\n\tint getAIUseDelayProxy() const  {return _aiUseDelayProxy;}\n\t/// Gets first turn when AI can use martial arts.\n\tint getAIUseDelayMelee() const {return _aiUseDelayMelee;}\n\t/// Gets first turn when AI can use psionic abilities.\n\tint getAIUseDelayPsionic() const  {return _aiUseDelayPsionic;}\n\t/// Gets first turn when AI can use self-target medikits.\n\tint getAIUseDelayMedikit() const { return _aiUseDelayMedikit; }\n\t/// Gets how much AI intelligence should be used to determine firing mode for sniping.\n\tint getAIFireChoiceIntelCoeff() const {return _aiFireChoiceIntelCoeff;}\n\t/// Gets how much AI aggression should be used to determine firing mode for sniping.\n\tint getAIFireChoiceAggroCoeff() const {return _aiFireChoiceAggroCoeff;}\n\t/// Gets whether or not to use extended firing mode scoring for determining which attack the AI should use\n\tbool getAIExtendedFireModeChoice() const {return _aiExtendedFireModeChoice;}\n\t/// Gets whether or not the AI should try to shoot beyond a weapon's max range, true = don't shoot if you can't\n\tbool getAIRespectMaxRange() const {return _aiRespectMaxRange;}\n\t/// Gets whether or not the AI should be allowed to continue destroying base facilities after first encountering XCom\n\tbool getAIDestroyBaseFacilities() const { return _aiDestroyBaseFacilities; }\n\t/// Gets whether or not the alien AI should pick up weapons more actively.\n\tbool getAIPickUpWeaponsMoreActively() const { return _aiPickUpWeaponsMoreActively; }\n\t/// Gets whether or not the civilian AI should pick up weapons more actively.\n\tbool getAIPickUpWeaponsMoreActivelyCiv() const { return _aiPickUpWeaponsMoreActivelyCiv; }\n\t/// Gets the reaction fire threshold (default = 0).\n\tint getReactionFireThreshold(UnitFaction faction) const;\n\t/// Gets weight value that AI use to determine if target is dangerous.\n\tAIAttackWeight getAITargetWeightThreatThreshold() const { return _aiTargetWeightThreatThreshold; }\n\t/// Gets default weight value of hostile unit.\n\tAIAttackWeight getAITargetWeightAsHostile() const { return _aiTargetWeightAsHostile; }\n\t/// Gets default weight value of civilian unit when consider by aliens.\n\tAIAttackWeight getAITargetWeightAsHostileCivilians() const { return _aiTargetWeightAsHostileCivilians; }\n\t/// Gets default weight value of same faction unit.\n\tAIAttackWeight getAITargetWeightAsFriendly() const { return _aiTargetWeightAsFriendly; }\n\t/// Gets default weight value of neutral unit (xcom to civ or vice versa).\n\tAIAttackWeight getAITargetWeightAsNeutral() const { return _aiTargetWeightAsNeutral; }\n\n\t/// Gets maximum supported lookVariant.\n\tint getMaxLookVariant() const;\n\t/// Gets the threshold for too much smoke (vanilla default = 10).\n\tint getTooMuchSmokeThreshold() const  {return _tooMuchSmokeThreshold;}\n\t/// Gets the custom physical training factor in percent (default = 100).\n\tint getCustomTrainingFactor() const { return _customTrainingFactor; }\n\t/// Gets the chance to stop retaliation after unsuccessful xcom base attack (default = 0).\n\tint getChanceToStopRetaliation() const { return _chanceToStopRetaliation; }\n\t/// Gets the chance to detect an alien base by xcom operatives each month (default = 20).\n\tint getChanceToDetectAlienBaseEachMonth() const { return _chanceToDetectAlienBaseEachMonth; }\n\t/// Should a damaged UFO deploy less aliens during the base defense?\n\tbool getLessAliensDuringBaseDefense() const { return _lessAliensDuringBaseDefense; }\n\t/// Will countries join the good side again after the infiltrator base is destroyed?\n\tbool getAllowCountriesToCancelAlienPact() const { return _allowCountriesToCancelAlienPact; }\n\t/// Should alien infiltration bases be built close to the infiltrated country?\n\tbool getBuildInfiltrationBaseCloseToTheCountry() const { return _buildInfiltrationBaseCloseToTheCountry; }\n\t/// Should alien infiltration pick countries in a region randomly (or in a pre-defined ruleset order)?\n\tbool getInfiltrateRandomCountryInTheRegion() const { return _infiltrateRandomCountryInTheRegion; }\n\t/// Should alien bases be allowed (in worst case) on invalid globe textures or not?\n\tbool getAllowAlienBasesOnWrongTextures() const { return _allowAlienBasesOnWrongTextures; }\n\t/// Gets the global kneel bonus (default = 115).\n\tint getKneelBonusGlobal() const { return _kneelBonusGlobal; }\n\t/// Gets the global one-handed penalty (default = 80).\n\tint getOneHandedPenaltyGlobal() const { return _oneHandedPenaltyGlobal; }\n\t/// Gets whether close quarters combat is enabled (default = 0 is off).\n\tint getEnableCloseQuartersCombat() const { return _enableCloseQuartersCombat; }\n\t/// Gets the default close quarters combat accuracy (default = 100).\n\tint getCloseQuartersAccuracyGlobal() const { return _closeQuartersAccuracyGlobal; }\n\t/// Gets the default close quarters combat TU cost (default = 12).\n\tint getCloseQuartersTuCostGlobal() const { return _closeQuartersTuCostGlobal; }\n\t/// Gets the default close quarters combat energy cost (default = 8).\n\tint getCloseQuartersEnergyCostGlobal() const { return _closeQuartersEnergyCostGlobal; }\n\t/// Gets the percentage for successfully avoiding CQC when sneaking up on the enemy (default = 0% = turned off).\n\tint getCloseQuartersSneakUpGlobal() const { return _closeQuartersSneakUpGlobal; }\n\t/// Gets the default accuracy penalty for having no LOS to the target (default = 0 is no penalty)\n\tint getNoLOSAccuracyPenaltyGlobal() const { return _noLOSAccuracyPenaltyGlobal; }\n\t/// Gets the default setting for primed grenades exploding in the inventory (default = 0 is no explosion)\n\tint getExplodeInventoryGlobal() const { return _explodeInventoryGlobal; }\n\t/// Gets the surrender mode (default = 0).\n\tint getSurrenderMode() const { return _surrenderMode; }\n\t/// Gets the bug hunt mode minimum turn requirement (default = 20).\n\tint getBughuntMinTurn() const { return _bughuntMinTurn; }\n\t/// Gets the bug hunt mode maximum remaining enemies requirement (default = 2).\n\tint getBughuntMaxEnemies() const { return _bughuntMaxEnemies; }\n\t/// Gets the bug hunt mode \"VIP rank\" parameter (default = 0).\n\tint getBughuntRank() const { return _bughuntRank; }\n\t/// Gets the bug hunt mode low morale threshold parameter (default = 40).\n\tint getBughuntLowMorale() const { return _bughuntLowMorale; }\n\t/// Gets the bug hunt mode time units % parameter (default = 60).\n\tint getBughuntTimeUnitsLeft() const { return _bughuntTimeUnitsLeft; }\n\n\t/// Is the mana feature enabled (default false)?\n\tbool isManaFeatureEnabled() const { return _manaEnabled; }\n\t/// Is the mana bar enabled for the Battlescape UI (default false)?\n\tbool isManaBarEnabled() const { return _manaBattleUI; }\n\t/// Is the mana trained as a primary skill (e.g. like firing accuracy)?\n\tbool isManaTrainingPrimary() const { return _manaTrainingPrimary; }\n\t/// Is the mana trained as a secondary skill (e.g. like strength)?\n\tbool isManaTrainingSecondary() const { return _manaTrainingSecondary; }\n\t/// Gets the mana unlock research topic (default empty)?\n\tconst std::string &getManaUnlockResearch() const { return _manaUnlockResearch; }\n\n\t/// How much missing mana will act as \"fatal wounds\" and prevent the soldier from going into battle.\n\tint getManaWoundThreshold() const { return _manaMissingWoundThreshold; }\n\t/// Should a soldier's mana be fully replenished after a mission?\n\tbool getReplenishManaAfterMission() const { return _manaReplenishAfterMission; }\n\n\t/// How much missing health will act as \"fatal wounds\" and prevent the soldier from going into battle.\n\tint getHealthWoundThreshold() const { return _healthMissingWoundThreshold; }\n\t/// Should a soldier's health be fully replenished after a mission?\n\tbool getReplenishHealthAfterMission() const { return _healthReplenishAfterMission; }\n\n\t/// Gets the cutscene ID that should be played when the player loses due to poor economy management.\n\tconst std::string &getLoseMoneyCutscene() const { return _loseMoney; }\n\t/// Gets the cutscene ID that should be played when the player loses due to poor rating.\n\tconst std::string &getLoseRatingCutscene() const { return _loseRating; }\n\t/// Gets the cutscene ID that should be played when the player loses the last base.\n\tconst std::string &getLoseDefeatCutscene() const { return _loseDefeat; }\n\n\t/// Gets the research topic required for building XCOM bases on fakeUnderwater globe textures.\n\tconst std::string &getFakeUnderwaterBaseUnlockResearch() const { return _fakeUnderwaterBaseUnlockResearch; }\n\t/// Gets the research topic required for building XCOM bases.\n\tconst std::string &getNewBaseUnlockResearch() const { return _newBaseUnlockResearch; }\n\n\t/// Gets the threshold for defining a glancing hit on a ufo during interception\n\tint getUfoGlancingHitThreshold() const { return _ufoGlancingHitThreshold; }\n\t/// Gets the parameter for drawing the width of a ufo's beam weapon based on power\n\tint getUfoBeamWidthParameter() const { return _ufoBeamWidthParameter; }\n\t/// Gets the modifier to a tractor beam's power based on a ufo's size\n\tint getUfoTractorBeamSizeModifier(int ufoSize) const { return _ufoTractorBeamSizeModifiers[ufoSize]; }\n\t/// Gets the escort range\n\tdouble getEscortRange() const;\n\t/// Gets the setting for drawing alien base/UFO radar circles.\n\tint getDrawEnemyRadarCircles() const { return _drawEnemyRadarCircles; }\n\t/// Should escorts join the fight against HK (automatically)? Or is only fighting one-on-one allowed?\n\tbool getEscortsJoinFightAgainstHK() const { return _escortsJoinFightAgainstHK; }\n\t/// Should hunter-killers be able to retarget every 5 seconds on slow game timers (5Sec / 1Min)?\n\tbool getHunterKillerFastRetarget() const { return _hunterKillerFastRetarget; }\n\t/// Gets the crew emergency evacuation survival chance\n\tint getCrewEmergencyEvacuationSurvivalChance() const { return _crewEmergencyEvacuationSurvivalChance; }\n\t/// Gets the pilots emergency evacuation survival chance\n\tint getPilotsEmergencyEvacuationSurvivalChance() const { return _pilotsEmergencyEvacuationSurvivalChance; }\n\t/// Should UFO preview be shown in base defense UI?\n\tbool showUfoPreviewInBaseDefense() const { return _showUfoPreviewInBaseDefense; }\n\t/// Gets how many soldiers are needed for one promotion of a given rank\n\tint getSoldiersPerRank(const SoldierRank rank) const { return _soldiersPerRank[(size_t)rank]; }\n\t/// Gets the firing accuracy needed for no bonus/penalty\n\tint getPilotAccuracyZeroPoint() const { return _pilotAccuracyZeroPoint; }\n\t/// Gets the firing accuracy impact (as percentage of distance to zero point) on pilot's aim in dogfight\n\tint getPilotAccuracyRange() const { return _pilotAccuracyRange; }\n\t/// Gets the reactions needed for no bonus/penalty\n\tint getPilotReactionsZeroPoint() const { return _pilotReactionsZeroPoint; }\n\t/// Gets the reactions impact (as percentage of distance to zero point) on pilot's dodge ability in dogfight\n\tint getPilotReactionsRange() const { return _pilotReactionsRange; }\n\t/// Gets the pilot's bravery needed for very bold approach speed\n\tint getPilotBraveryThresholdVeryBold() const { return _pilotBraveryThresholds[0]; }\n\t/// Gets the pilot's bravery needed for bold approach speed\n\tint getPilotBraveryThresholdBold() const { return _pilotBraveryThresholds[1]; }\n\t/// Gets the pilot's bravery needed for normal approach speed\n\tint getPilotBraveryThresholdNormal() const { return _pilotBraveryThresholds[2]; }\n\t/// Gets a performance bonus for a given score\n\tint getPerformanceBonus(int score) const { return (int)(score * _performanceBonusFactor); }\n\t/// Should the player have the option to sort the 'New Research' list?\n\tbool getEnableNewResearchSorting() const { return _enableNewResearchSorting; }\n\t/// Should custom categories be used in Buy/Sell/Transfer GUIs? 0=no, 1=yes, custom only, 2=both vanilla and custom.\n\tint getDisplayCustomCategories() const { return _displayCustomCategories; }\n\t/// Should weapons \"inherit\" categories of their ammo?\n\tbool getShareAmmoCategories() const { return _shareAmmoCategories; }\n\t/// Should distance in dogfight GUI be shown in kilometers?\n\tbool getShowDogfightDistanceInKm() const { return _showDogfightDistanceInKm; }\n\t/// Should alien inventory show full name (e.g. Sectoid Leader) or just the race (e.g. Sectoid)?\n\tbool getShowFullNameInAlienInventory() const { return _showFullNameInAlienInventory; }\n\t/// Gets the offset for alien inventory paperdoll and hand slots\n\tint getAlienInventoryOffsetX() const { return _alienInventoryOffsetX; }\n\t/// Gets the extra offset for alien inventory hand slots for 2x2 units\n\tint getAlienInventoryOffsetBigUnit() const { return _alienInventoryOffsetBigUnit; }\n\t/// Show the INFO button (where applicable) or not?\n\tbool getShowPediaInfoButton() const { return !_hidePediaInfoButton; }\n\t/// Display extra item info (accuracy modifier and power bonus) in the main pedia article?\n\tint getExtraNerdyPediaInfoType() const { return _extraNerdyPediaInfoType; }\n\t/// In debriefing, give score also for already researched alien artifacts?\n\tbool getGiveScoreAlsoForResearchedArtifacts() const { return _giveScoreAlsoForResearchedArtifacts; }\n\t/// When recovering ammo, should partially spent clip have a chance to recover as full?\n\tbool getStatisticalBulletConservation() const { return _statisticalBulletConservation; }\n\t/// Does stunning an enemy improve unit and squad morale?\n\tbool getStunningImprovesMorale() const { return _stunningImprovesMorale; }\n\t/// Gets how much TU (in percent) should be given to a unit waking up from stun at the beginning of a new turn.\n\tint getTURecoveryWakeUpNewTurn() const { return _tuRecoveryWakeUpNewTurn; }\n\t/// Gets whether or not to load base defense terrain from globe texture\n\tint getBaseDefenseMapFromLocation() const { return _baseDefenseMapFromLocation; }\n\n\t/// Return mod what created given rule object.\n\ttemplate<typename T>\n\tconst ModData* getModCreatingRule(const T* t) const { return _ruleCreationTracking.at(static_cast<const void*>(t)); }\n\t/// Return mod what last updated given rule object.\n\ttemplate<typename T>\n\tconst ModData* getModLastUpdatingRule(const T* t) const { return _ruleLastUpdateTracking.at(static_cast<const void*>(t)); }\n\n\t/// Gets the ruleset for a specific research project.\n\tRuleResearch *getResearch(const std::string &id, bool error = false) const;\n\t/// Gets the ruleset for a specific research project.\n\tstd::vector<const RuleResearch*> getResearch(const std::vector<std::string> &id) const;\n\t/// Gets the ruleset for a specific research project.\n\tconst std::map<std::string, RuleResearch *> &getResearchMap() const;\n\t/// Gets the list of all research projects.\n\tconst std::vector<std::string> &getResearchList() const;\n\t/// Gets the ruleset for a specific manufacture project.\n\tRuleManufacture *getManufacture (const std::string &id, bool error = false) const;\n\t/// Gets the list of all manufacture projects.\n\tconst std::vector<std::string> &getManufactureList() const;\n\t/// Gets the ruleset for a specific soldier bonus type.\n\tRuleSoldierBonus *getSoldierBonus(const std::string &id, bool error = false) const;\n\t/// Gets the list of all soldier bonus types.\n\tconst std::vector<std::string> &getSoldierBonusList() const;\n\t/// Gets the ruleset for a specific soldier transformation project.\n\tRuleSoldierTransformation *getSoldierTransformation(const std::string &id, bool error = false) const;\n\t/// Gets the list of all soldier transformation projects.\n\tconst std::vector<std::string> &getSoldierTransformationList() const;\n\t/// Gets facilities for custom bases.\n\tstd::vector<RuleBaseFacility*> getCustomBaseFacilities(GameDifficulty diff) const;\n\t/// Gets a specific UfoTrajectory.\n\tconst UfoTrajectory *getUfoTrajectory(const std::string &id, bool error = false) const;\n\t/// Gets the ruleset for a specific alien mission.\n\tconst RuleAlienMission *getAlienMission(const std::string &id, bool error = false) const;\n\t/// Gets the ruleset for a random alien mission.\n\tconst RuleAlienMission *getRandomMission(MissionObjective objective, size_t monthsPassed) const;\n\t/// Gets the list of all alien missions.\n\tconst std::vector<std::string> &getAlienMissionList() const;\n\t/// Gets the alien item level table.\n\tconst std::vector<std::vector<int> > &getAlienItemLevels() const;\n\t/// Gets the player starting base.\n\tconst YAML::YamlString& getDefaultStartingBase() const;\n\tconst YAML::YamlString& getStartingBase(GameDifficulty diff) const;\n\t/// Gets the game starting time.\n\tconst GameTime &getStartingTime() const;\n\t/// Gets the game starting difficulty.\n\tint getStartingDifficulty() const { return _startingDifficulty; }\n\t/// Gets an MCDPatch.\n\tMCDPatch *getMCDPatch(const std::string &id) const;\n\t/// Gets the list of external Sprites.\n\tconst std::map<std::string, std::vector<ExtraSprites *> > &getExtraSprites() const;\n\t/// Gets the list of custom palettes.\n\tconst std::vector<std::string> &getCustomPalettes() const;\n\t/// Gets the list of external Sounds.\n\tconst std::vector<std::pair<std::string, ExtraSounds *> > &getExtraSounds() const;\n\t/// Gets the list of external Strings.\n\tconst std::map<std::string, ExtraStrings *> &getExtraStrings() const;\n\t/// Gets the list of StatStrings.\n\tconst std::vector<StatString *> &getStatStrings() const;\n\t/// Gets the research-requirements for Psi-Lab (it's a cache for psiStrengthEval)\n\tconst std::vector<std::string> &getPsiRequirements() const;\n\t/// Returns the sorted list of inventories.\n\tconst std::vector<std::string> &getInvsList() const;\n\t/// Generates a new soldier.\n\tSoldier *genSoldier(SavedGame *save, const RuleSoldier* ruleSoldier, int nationality) const;\n\t/// Gets the item to be used as fuel for ships.\n\tstd::string getAlienFuelName() const;\n\t/// Gets the amount of alien fuel to recover\n\tint getAlienFuelQuantity() const;\n\t/// Gets the font name.\n\tstd::string getFontName() const;\n\t/// Gets the maximum radar range still considered as short.\n\tint getShortRadarRange() const;\n\t/// Gets the custom scaling (defined by the modder) applied on the facility upgrade/build time reduction calculated by the game.\n\tint getBuildTimeReductionScaling() const { return _buildTimeReductionScaling; }\n\t/// Gets what type of information should be shown in craft articles for the fuel capacity/range\n\tint getPediaReplaceCraftFuelWithRangeType() const;\n\t/// Gets information on an interface element.\n\tRuleInterface *getInterface(const std::string &id, bool error = true) const;\n\t/// Gets the ruleset for the globe.\n\tRuleGlobe *getGlobe() const;\n\t/// Gets the ruleset for the converter.\n\tRuleConverter *getConverter() const;\n\t/// Gets the list of selective files for insertion into our cat files.\n\tconst std::map<std::string, SoundDefinition *> *getSoundDefinitions() const;\n\tconst std::vector<MapScript*> *getMapScript(const std::string& id) const;\n\tconst std::map<std::string, std::vector<MapScript*> > &getMapScriptsRaw() const { return _mapScripts; }\n\t/// Gets a video for intro/outro etc.\n\tRuleVideo *getVideo(const std::string &id, bool error = false) const;\n\tconst std::map<std::string, RuleMusic *> *getMusic() const;\n\tconst std::vector<std::string>* getArcScriptList() const;\n\tRuleArcScript* getArcScript(const std::string& name, bool error = false) const;\n\tconst std::vector<std::string>* getEventScriptList() const;\n\tRuleEventScript* getEventScript(const std::string& name, bool error = false) const;\n\tconst std::vector<std::string>* getEventList() const;\n\tRuleEvent* getEvent(const std::string& name, bool error = false) const;\n\tconst std::vector<std::string> *getMissionScriptList() const;\n\tconst std::vector<std::string> *getAdhocScriptList() const;\n\tRuleMissionScript *getMissionScript(const std::string &name, bool error = false) const;\n\tRuleMissionScript *getAdhocScript(const std::string &name, bool error = false) const;\n\t/// Get global script data.\n\tScriptGlobal *getScriptGlobal() const;\n\tRuleResearch *getFinalResearch() const;\n\tRuleBaseFacility *getDestroyedFacility() const;\n\tconst std::map<int, std::string> *getMissionRatings() const;\n\tconst std::map<int, std::string> *getMonthlyRatings() const;\n\tconst std::map<std::string, std::string> &getFixedUserOptions() const { return _fixedUserOptions; }\n\tconst std::map<std::string, std::string> &getRecommendedUserOptions() const { return _recommendedUserOptions; }\n\tconst std::vector<std::string> &getHiddenMovementBackgrounds() const;\n\tconst std::vector<std::string> &getBaseNamesFirst() const { return _baseNamesFirst; }\n\tconst std::vector<std::string> &getBaseNamesMiddle() const { return _baseNamesMiddle; }\n\tconst std::vector<std::string> &getBaseNamesLast() const { return _baseNamesLast; }\n\tconst std::vector<std::string> &getOperationNamesFirst() const { return _operationNamesFirst; }\n\tconst std::vector<std::string> &getOperationNamesLast() const { return _operationNamesLast; }\n\tbool getEnableUnitResponseSounds() const { return _enableUnitResponseSounds; }\n\tconst std::map<std::string, std::vector<int> > &getSelectUnitSounds() const { return _selectUnitSound; }\n\tconst std::map<std::string, std::vector<int> > &getStartMovingSounds() const { return _startMovingSound; }\n\tconst std::map<std::string, std::vector<int> > &getSelectWeaponSounds() const { return _selectWeaponSound; }\n\tconst std::map<std::string, std::vector<int> > &getAnnoyedSounds() const { return _annoyedSound; }\n\tconst std::vector<int> &getSelectBaseSounds() const { return _selectBaseSound; }\n\tconst std::vector<int> &getStartDogfightSounds() const { return _startDogfightSound; }\n\tconst std::vector<int> &getFlagByKills() const;\n\tStatAdjustment *getStatAdjustment(int difficulty);\n\tint getDefeatScore() const;\n\tint getDefeatFunds() const;\n\tbool isDemigod() const;\n\tconst std::vector<int>& getMonthlyRatingThresholds() { return _monthlyRatingThresholds; }\n\tconst std::vector<int>& getUfoFiringRateCoefficients() { return _ufoFiringRateCoefficients; }\n\tconst std::vector<int>& getUfoEscapeCountdownCoefficients() { return _ufoEscapeCountdownCoefficients; }\n\tconst std::vector<int>& getRetaliationTriggerOdds() { return _retaliationTriggerOdds; }\n\tconst std::vector<int>& getRetaliationBaseRegionOdds() { return _retaliationBaseRegionOdds; }\n\tconst std::vector<int>& getAliensFacingCraftOdds() { return _aliensFacingCraftOdds; }\n\n};\n\n}\n"
  },
  {
    "path": "src/Mod/ModScript.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2015 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/Script.h\"\n\n\nnamespace OpenXcom\n{\n\nnamespace RNG { class RandomState; }\nclass Surface;\nclass SurfaceSet;\nclass Soldier;\nclass RuleCountry;\nclass Country;\nclass RuleRegion;\nclass RuleBaseFacility;\nclass RuleCraft;\nclass RuleCraftWeapon;\nclass RuleItem;\nstruct RuleDamageType;\nclass RuleTerrain;\nclass MapDataSet;\nclass RuleSoldier;\nclass RuleSoldierBonus;\nclass Unit;\nclass Armor;\nclass RuleInventory;\nclass RuleResearch;\nclass RuleManufacture;\nclass RuleSkill;\nclass AlienRace;\nclass RuleAlienMission;\nclass Base;\nclass MapScript;\nclass RuleVideo;\n\nclass Mod;\nclass Position;\nclass Tile;\nclass BattleUnit;\nclass BattleUnitVisibility;\nclass BattleItem;\nstruct StatAdjustment;\n\nclass Ufo;\nclass RuleUfo;\nclass Craft;\nclass RuleCraft;\n\nclass SavedBattleGame;\nclass SavedGame;\n\nclass StatsForNerdsState;\n\n\n/**\n * Main class handling all script types used by the game.\n */\nclass ModScript\n{\n\tfriend class Mod;\n\n\tScriptGlobal* _shared;\n\tMod* _mod;\n\n\tModScript(ScriptGlobal* shared, Mod* mod) : _shared{ shared }, _mod{ mod }\n\t{\n\n\t}\n\n\tusing Output = ScriptOutputArgs<int&, int>;\n\n\t////////////////////////////////////////////////////////////\n\t//\t\t\t\t\tunit script\n\t////////////////////////////////////////////////////////////\n\n\tstruct RecolorUnitParser : ScriptParserEvents<Output, const BattleUnit*, const SavedBattleGame*, int, int, int, int>\n\t{\n\t\tRecolorUnitParser(ScriptGlobal* shared, const std::string& name, Mod* mod);\n\t};\n\tstruct SelectUnitParser : ScriptParserEvents<Output, const BattleUnit*, const SavedBattleGame*, int, int, int>\n\t{\n\t\tSelectUnitParser(ScriptGlobal* shared, const std::string& name, Mod* mod);\n\t};\n\tstruct SelectMoveSoundUnitParser : ScriptParserEvents<ScriptOutputArgs<int&>, const BattleUnit*, int, int, int, int, int, int, int>\n\t{\n\t\tSelectMoveSoundUnitParser(ScriptGlobal* shared, const std::string& name, Mod* mod);\n\t};\n\n\tstruct ReactionUnitParser : ScriptParserEvents<Output, const BattleUnit*, const BattleUnit*, const BattleItem*, int, int, const BattleItem*, const RuleSkill*, int, const BattleUnit*, int, int, const SavedBattleGame*>\n\t{\n\t\tReactionUnitParser(ScriptGlobal* shared, const std::string& name, Mod* mod);\n\t};\n\n\tstruct VisibilityUnitParser : ScriptParserEvents<ScriptOutputArgs<int&, int, ScriptTag<BattleUnitVisibility>&>, const BattleUnit*, const BattleUnit*, const Tile*, int, int, int, int, int, int, int>\n\t{\n\t\tVisibilityUnitParser(ScriptGlobal* shared, const std::string& name, Mod* mod);\n\t};\n\n\tstruct AiCalculateTargetWeightParser : ScriptParserEvents<Output, const BattleUnit*, const BattleUnit*, const SavedBattleGame*>\n\t{\n\t\tAiCalculateTargetWeightParser(ScriptGlobal* shared, const std::string& name, Mod* mod);\n\t};\n\n\tstruct HitUnitParser : ScriptParserEvents<ScriptOutputArgs<int&, int&, int&>, BattleUnit*, BattleItem*, BattleItem*, BattleUnit*, SavedBattleGame*, const RuleSkill*, int, int, int>\n\t{\n\t\tHitUnitParser(ScriptGlobal* shared, const std::string& name, Mod* mod);\n\t};\n\tstruct SkillUseUnitParser : ScriptParserEvents<ScriptOutputArgs<int&, int&>, BattleUnit*, BattleItem*, SavedBattleGame*, const RuleSkill*, int, int>\n\t{\n\t\tSkillUseUnitParser(ScriptGlobal* shared, const std::string& name, Mod* mod);\n\t};\n\tstruct TryPsiAttackUnitParser : ScriptParserEvents<ScriptOutputArgs<int&>, const BattleItem*, const BattleUnit*, const BattleUnit*, const RuleSkill*, int, int, int, const SavedBattleGame*>\n\t{\n\t\tTryPsiAttackUnitParser(ScriptGlobal* shared, const std::string& name, Mod* mod);\n\t};\n\tstruct TryMeleeAttackUnitParser : ScriptParserEvents<ScriptOutputArgs<int&>, const BattleItem*, const BattleUnit*, const BattleUnit*, const RuleSkill*, int, int, int, const SavedBattleGame*>\n\t{\n\t\tTryMeleeAttackUnitParser(ScriptGlobal* shared, const std::string& name, Mod* mod);\n\t};\n\tstruct DamageUnitParser : ScriptParserEvents<ScriptOutputArgs<int&, int&, int&, int&, int&, int&, int&, int&, int&>, BattleUnit*, BattleItem*, BattleItem*, BattleUnit*, SavedBattleGame*, const RuleSkill*, int, int, int, int, int, int>\n\t{\n\t\tDamageUnitParser(ScriptGlobal* shared, const std::string& name, Mod* mod);\n\t};\n\tstruct DamageSpecialUnitParser : ScriptParserEvents<ScriptOutputArgs<int, int&, int, int&, int&, int&, int&, int&>, BattleUnit*, BattleItem*, BattleItem*, BattleUnit*, SavedBattleGame*, const RuleSkill*, int, int, int, int, int, int>\n\t{\n\t\tDamageSpecialUnitParser(ScriptGlobal* shared, const std::string& name, Mod* mod);\n\t};\n\tstruct HealUnitParser : ScriptParserEvents<ScriptOutputArgs<int&, int&, int&, int&, int&, int&, int&, int&, int&>, BattleUnit*, BattleItem*, SavedBattleGame*, BattleUnit*, int>\n\t{\n\t\tHealUnitParser(ScriptGlobal* shared, const std::string& name, Mod* mod);\n\t};\n\tstruct CreateUnitParser : ScriptParserEvents<ScriptOutputArgs<>, BattleUnit*, SavedBattleGame*, int>\n\t{\n\t\tCreateUnitParser(ScriptGlobal* shared, const std::string& name, Mod* mod);\n\t};\n\tstruct NewTurnUnitParser : ScriptParserEvents<ScriptOutputArgs<>, BattleUnit*, SavedBattleGame*, int, int>\n\t{\n\t\tNewTurnUnitParser(ScriptGlobal* shared, const std::string& name, Mod* mod);\n\t};\n\tstruct ReturnFromMissionUnitParser : ScriptParserEvents<ScriptOutputArgs<int&, int, int, int&, int&>, BattleUnit*, SavedBattleGame*, Soldier*, const StatAdjustment*, const StatAdjustment*>\n\t{\n\t\tReturnFromMissionUnitParser(ScriptGlobal* shared, const std::string& name, Mod* mod);\n\t};\n\n\tstruct AwardExperienceParser : ScriptParserEvents<Output, const BattleUnit*, const BattleUnit*, const BattleItem*, int>\n\t{\n\t\tAwardExperienceParser(ScriptGlobal* shared, const std::string& name, Mod* mod);\n\t};\n\n\tstruct StatsForNerdsArmorParser : ScriptParserEvents<ScriptOutputArgs<>, const Armor*, StatsForNerdsState*, const SavedGame*>\n\t{\n\t\tStatsForNerdsArmorParser(ScriptGlobal* shared, const std::string& name, Mod* mod);\n\t};\n\n\t////////////////////////////////////////////////////////////\n\t//\t\t\t\t\titem script\n\t////////////////////////////////////////////////////////////\n\n\tstruct CreateItemParser : ScriptParserEvents<ScriptOutputArgs<>, BattleItem*, BattleUnit*,  SavedBattleGame*, int>\n\t{\n\t\tCreateItemParser(ScriptGlobal* shared, const std::string& name, Mod* mod);\n\t};\n\tstruct NewTurnItemParser : ScriptParserEvents<ScriptOutputArgs<>, BattleItem*, SavedBattleGame*, int, int>\n\t{\n\t\tNewTurnItemParser(ScriptGlobal* shared, const std::string& name, Mod* mod);\n\t};\n\tstruct RecolorItemParser : ScriptParserEvents<Output, const BattleItem*, const SavedBattleGame*, int, int, int>\n\t{\n\t\tRecolorItemParser(ScriptGlobal* shared, const std::string& name, Mod* mod);\n\t};\n\tstruct SelectItemParser : ScriptParserEvents<Output, const BattleItem*, const SavedBattleGame*, int, int, int>\n\t{\n\t\tSelectItemParser(ScriptGlobal* shared, const std::string& name, Mod* mod);\n\t};\n\n\n\tstruct VaporParticleBaseParser : ScriptParser<ScriptOutputArgs<int&, Position&, Position&, Position&, int&, int&, int&, int>, const BattleItem*, const BattleItem*, int, int, int, Position, Position, Position, RNG::RandomState*>\n\t{\n\t\tVaporParticleBaseParser(ScriptGlobal* shared, const std::string& name, Mod* mod);\n\t};\n\tstruct VaporParticleAmmoParser : VaporParticleBaseParser\n\t{\n\t\tVaporParticleAmmoParser(ScriptGlobal* shared, const std::string& name, Mod* mod);\n\t};\n\tstruct VaporParticleWeaponParser : VaporParticleBaseParser\n\t{\n\t\tVaporParticleWeaponParser(ScriptGlobal* shared, const std::string& name, Mod* mod);\n\t};\n\n\n\tstruct TryPsiAttackItemParser : ScriptParserEvents<ScriptOutputArgs<int&>, const BattleItem*, const BattleUnit*, const BattleUnit*, const RuleSkill*, int, int, int, RNG::RandomState*, int, int, const SavedBattleGame*>\n\t{\n\t\tTryPsiAttackItemParser(ScriptGlobal* shared, const std::string& name, Mod* mod);\n\t};\n\n\tstruct TryMeleeAttackItemParser : ScriptParserEvents<ScriptOutputArgs<int&>, const BattleItem*, const BattleUnit*, const BattleUnit*, const RuleSkill*, int, int, int, RNG::RandomState*, int, int, const SavedBattleGame*>\n\t{\n\t\tTryMeleeAttackItemParser(ScriptGlobal* shared, const std::string& name, Mod* mod);\n\t};\n\n\tstruct SellCostItemParser : ScriptParserEvents<Output, const RuleItem*, const SavedGame*, int>\n\t{\n\t\tSellCostItemParser(ScriptGlobal* shared, const std::string& name, Mod* mod);\n\t};\n\tstruct BuyCostItemParser : ScriptParserEvents<Output, const RuleItem*, const SavedGame*, int>\n\t{\n\t\tBuyCostItemParser(ScriptGlobal* shared, const std::string& name, Mod* mod);\n\t};\n\n\tstruct StatsForNerdsItemParser : ScriptParserEvents<ScriptOutputArgs<>, const RuleItem*, StatsForNerdsState*, const SavedGame*>\n\t{\n\t\tStatsForNerdsItemParser(ScriptGlobal* shared, const std::string& name, Mod* mod);\n\t};\n\n\t////////////////////////////////////////////////////////////\n\t//\t\t\t\t\tbonus stat script\n\t////////////////////////////////////////////////////////////\n\n\tstruct BonusStatsBaseParser : ScriptParserEvents<ScriptOutputArgs<int&>, const BattleUnit*, int, const BattleItem*, const BattleItem*, int, const RuleSkill*>\n\t{\n\t\tBonusStatsBaseParser(ScriptGlobal* shared, const std::string& name, Mod* mod);\n\n\t\t/// Get name of YAML node where config is stored.\n\t\tconst std::string& getPropertyNodeName() const { return _propertyNodeName; }\n\n\tprotected:\n\n\t\t/// Name of YAML node where config is stored.\n\t\tstd::string _propertyNodeName;\n\t};\n\n\tstruct BonusStatsParser : BonusStatsBaseParser\n\t{\n\t\tBonusStatsParser(ScriptGlobal* shared, const std::string& name, Mod* mod) : BonusStatsBaseParser{ shared, name + \"BonusStats\", mod }\n\t\t{\n\t\t\t_propertyNodeName = name;\n\t\t}\n\t};\n\n\tstruct BonusStatsRecoveryParser : BonusStatsBaseParser\n\t{\n\t\tBonusStatsRecoveryParser(ScriptGlobal* shared, const std::string& name, Mod* mod) : BonusStatsBaseParser{ shared, name + \"RecoveryBonusStats\", mod }\n\t\t{\n\t\t\t_propertyNodeName = name;\n\t\t}\n\t};\n\n\tstruct BonusSoldierStatsRecoveryParser : BonusStatsBaseParser\n\t{\n\t\tBonusSoldierStatsRecoveryParser(ScriptGlobal* shared, const std::string& name, Mod* mod) : BonusStatsBaseParser{ shared, name + \"SoldierRecoveryBonusStats\", mod }\n\t\t{\n\t\t\t_propertyNodeName = name;\n\t\t}\n\t};\n\n\t////////////////////////////////////////////////////////////\n\t//\t\t\t\t\tcountry script\n\t////////////////////////////////////////////////////////////\n\n\tstruct NewMonthCountryParser : ScriptParserEvents<ScriptOutputArgs<int&, int&, int&, int&>, const Country*, const SavedGame*, int, int>\n\t{\n\t\tNewMonthCountryParser(ScriptGlobal* shared, const std::string& name, Mod* mod);\n\t};\n\n\t////////////////////////////////////////////////////////////\n\t//\t\t\t\t\tufo script\n\t////////////////////////////////////////////////////////////\n\n\tstruct DetectUfoFromBaseParser : ScriptParserEvents<ScriptOutputArgs<int&, int&>, const Ufo*, const SavedGame*, int, int, int, int, int, int>\n\t{\n\t\tDetectUfoFromBaseParser(ScriptGlobal* shared, const std::string& name, Mod* mod);\n\t};\n\n\tstruct DetectUfoFromCraftParser : ScriptParserEvents<ScriptOutputArgs<int&, int&>, const Ufo*, const SavedGame*, const Craft*, int, int, int, int>\n\t{\n\t\tDetectUfoFromCraftParser(ScriptGlobal* shared, const std::string& name, Mod* mod);\n\t};\n\n\tstruct StatsForNerdsUfoParser : ScriptParserEvents<ScriptOutputArgs<>, const RuleUfo*, StatsForNerdsState*, const SavedGame*>\n\t{\n\t\tStatsForNerdsUfoParser(ScriptGlobal* shared, const std::string& name, Mod* mod);\n\t};\n\n\t////////////////////////////////////////////////////////////\n\t//\t\t\t\t\tcraft script\n\t////////////////////////////////////////////////////////////\n\n\tstruct StatsForNerdsCraftParser : ScriptParserEvents<ScriptOutputArgs<>, const RuleCraft*, StatsForNerdsState*, const SavedGame*>\n\t{\n\t\tStatsForNerdsCraftParser(ScriptGlobal* shared, const std::string& name, Mod* mod);\n\t};\n\n\t////////////////////////////////////////////////////////////\n\t//\t\t\t\tsoldier bonus stat script\n\t////////////////////////////////////////////////////////////\n\n\tstruct ApplySoldierBonusesParser : ScriptParserEvents<ScriptOutputArgs<>, BattleUnit*, SavedBattleGame*, const RuleSoldierBonus*>\n\t{\n\t\tApplySoldierBonusesParser(ScriptGlobal* shared, const std::string& name, Mod* mod);\n\t};\n\npublic:\n\t/// Get shared state.\n\tconst ScriptGlobal* getShared() const\n\t{\n\t\treturn _shared;\n\t}\n\n\tusing ReactionCommon = ReactionUnitParser;\n\tusing BonusStatsCommon = BonusStatsBaseParser;\n\n\t////////////////////////////////////////////////////////////\n\t//\t\t\t\t\tunit script\n\t////////////////////////////////////////////////////////////\n\n\tusing RecolorUnitSprite = MACRO_NAMED_SCRIPT(\"recolorUnitSprite\", RecolorUnitParser);\n\tusing SelectUnitSprite = MACRO_NAMED_SCRIPT(\"selectUnitSprite\", SelectUnitParser);\n\tusing SelectMoveSoundUnit = MACRO_NAMED_SCRIPT(\"selectMoveSoundUnit\", SelectMoveSoundUnitParser);\n\n\tusing ReactionUnitAction = MACRO_NAMED_SCRIPT(\"reactionUnitAction\", ReactionUnitParser);\n\tusing ReactionUnitReaction = MACRO_NAMED_SCRIPT(\"reactionUnitReaction\", ReactionUnitParser);\n\n\tusing TryPsiAttackUnit = MACRO_NAMED_SCRIPT(\"tryPsiAttackUnit\", TryPsiAttackUnitParser);\n\tusing TryMeleeAttackUnit = MACRO_NAMED_SCRIPT(\"tryMeleeAttackUnit\", TryMeleeAttackUnitParser);\n\tusing HitUnit = MACRO_NAMED_SCRIPT(\"hitUnit\", HitUnitParser);\n\tusing DamageUnit = MACRO_NAMED_SCRIPT(\"damageUnit\", DamageUnitParser);\n\tusing DamageSpecialUnit = MACRO_NAMED_SCRIPT(\"damageSpecialUnit\", DamageSpecialUnitParser);\n\tusing HealUnit = MACRO_NAMED_SCRIPT(\"healUnit\", HealUnitParser);\n\n\tusing CreateUnit = MACRO_NAMED_SCRIPT(\"createUnit\", CreateUnitParser);\n\tusing NewTurnUnit = MACRO_NAMED_SCRIPT(\"newTurnUnit\", NewTurnUnitParser);\n\tusing ReturnFromMissionUnit = MACRO_NAMED_SCRIPT(\"returnFromMissionUnit\", ReturnFromMissionUnitParser);\n\n\tusing AwardExperience = MACRO_NAMED_SCRIPT(\"awardExperience\", AwardExperienceParser);\n\n\tusing VisibilityUnit = MACRO_NAMED_SCRIPT(\"visibilityUnit\", VisibilityUnitParser);\n\n\tusing AiCalculateTargetWeight = MACRO_NAMED_SCRIPT(\"aiCalculateTargetWeight\", AiCalculateTargetWeightParser);\n\n\tusing StatsForNerdsArmor = MACRO_NAMED_SCRIPT(\"statsForNerdsArmor\", StatsForNerdsArmorParser);\n\n\t////////////////////////////////////////////////////////////\n\t//\t\t\t\t\titem script\n\t////////////////////////////////////////////////////////////\n\n\tusing RecolorItemSprite = MACRO_NAMED_SCRIPT(\"recolorItemSprite\", RecolorItemParser);\n\tusing SelectItemSprite = MACRO_NAMED_SCRIPT(\"selectItemSprite\", SelectItemParser);\n\tusing VaporParticleAmmo = MACRO_NAMED_SCRIPT(\"vaporParticleAmmo\", VaporParticleAmmoParser);\n\tusing VaporParticleWeapon = MACRO_NAMED_SCRIPT(\"vaporParticleWeapon\", VaporParticleWeaponParser);\n\n\tusing ReactionWeaponAction = MACRO_NAMED_SCRIPT(\"reactionWeaponAction\", ReactionUnitParser);\n\n\tusing TryPsiAttackItem = MACRO_NAMED_SCRIPT(\"tryPsiAttackItem\", TryPsiAttackItemParser);\n\tusing TryMeleeAttackItem = MACRO_NAMED_SCRIPT(\"tryMeleeAttackItem\", TryMeleeAttackItemParser);\n\tusing HitUnitAmmo = MACRO_NAMED_SCRIPT(\"hitUnitAmmo\", HitUnitParser);\n\tusing DamageUnitAmmo = MACRO_NAMED_SCRIPT(\"damageUnitAmmo\", DamageUnitParser);\n\tusing DamageSpecialUnitAmmo = MACRO_NAMED_SCRIPT(\"damageSpecialUnitAmmo\", DamageSpecialUnitParser);\n\n\tusing CreateItem = MACRO_NAMED_SCRIPT(\"createItem\", CreateItemParser);\n\tusing NewTurnItem = MACRO_NAMED_SCRIPT(\"newTurnItem\", NewTurnItemParser);\n\n\tusing SellCostItem = MACRO_NAMED_SCRIPT(\"sellCostItem\", SellCostItemParser);\n\tusing BuyCostItem = MACRO_NAMED_SCRIPT(\"buyCostItem\", BuyCostItemParser);\n\n\tusing StatsForNerdsItem = MACRO_NAMED_SCRIPT(\"statsForNerdsItem\", StatsForNerdsItemParser);\n\n\t////////////////////////////////////////////////////////////\n\t//\t\t\t\t\tbonus stat script\n\t////////////////////////////////////////////////////////////\n\n\tusing PsiDefenceStatBonus = MACRO_NAMED_SCRIPT(\"psiDefence\", BonusStatsParser);\n\tusing MeleeDodgeStatBonus = MACRO_NAMED_SCRIPT(\"meleeDodge\", BonusStatsParser);\n\n\tusing TimeRecoveryStatBonus = MACRO_NAMED_SCRIPT(\"time\", BonusStatsRecoveryParser);\n\tusing EnergyRecoveryStatBonus = MACRO_NAMED_SCRIPT(\"energy\", BonusStatsRecoveryParser);\n\tusing MoraleRecoveryStatBonus = MACRO_NAMED_SCRIPT(\"morale\", BonusStatsRecoveryParser);\n\tusing HealthRecoveryStatBonus = MACRO_NAMED_SCRIPT(\"health\", BonusStatsRecoveryParser);\n\tusing ManaRecoveryStatBonus = MACRO_NAMED_SCRIPT(\"mana\", BonusStatsRecoveryParser);\n\tusing StunRecoveryStatBonus = MACRO_NAMED_SCRIPT(\"stun\", BonusStatsRecoveryParser);\n\n\tusing TimeSoldierRecoveryStatBonus = MACRO_NAMED_SCRIPT(\"time\", BonusSoldierStatsRecoveryParser);\n\tusing EnergySoldierRecoveryStatBonus = MACRO_NAMED_SCRIPT(\"energy\", BonusSoldierStatsRecoveryParser);\n\tusing MoraleSoldierRecoveryStatBonus = MACRO_NAMED_SCRIPT(\"morale\", BonusSoldierStatsRecoveryParser);\n\tusing HealthSoldierRecoveryStatBonus = MACRO_NAMED_SCRIPT(\"health\", BonusSoldierStatsRecoveryParser);\n\tusing ManaSoldierRecoveryStatBonus = MACRO_NAMED_SCRIPT(\"mana\", BonusSoldierStatsRecoveryParser);\n\tusing StunSoldierRecoveryStatBonus = MACRO_NAMED_SCRIPT(\"stun\", BonusSoldierStatsRecoveryParser);\n\n\tusing DamageBonusStatBonus = MACRO_NAMED_SCRIPT(\"damageBonus\", BonusStatsParser);\n\tusing MeleeBonusStatBonus = MACRO_NAMED_SCRIPT(\"meleeBonus\", BonusStatsParser);\n\tusing AccuracyMultiplierStatBonus = MACRO_NAMED_SCRIPT(\"accuracyMultiplier\", BonusStatsParser);\n\tusing MeleeMultiplierStatBonus = MACRO_NAMED_SCRIPT(\"meleeMultiplier\", BonusStatsParser);\n\tusing ThrowMultiplierStatBonus = MACRO_NAMED_SCRIPT(\"throwMultiplier\", BonusStatsParser);\n\tusing CloseQuarterMultiplierStatBonus = MACRO_NAMED_SCRIPT(\"closeQuartersMultiplier\", BonusStatsParser);\n\n\t////////////////////////////////////////////////////////////\n\t//\t\t\t\t\tskill script\n\t////////////////////////////////////////////////////////////\n\n\tusing SkillUseUnit = MACRO_NAMED_SCRIPT(\"skillUseUnit\", SkillUseUnitParser);\n\n\t////////////////////////////////////////////////////////////\n\t//\t\t\t\t\tcountry script\n\t////////////////////////////////////////////////////////////\n\n\tusing NewMonthCountry = MACRO_NAMED_SCRIPT(\"newMonthCountry\", NewMonthCountryParser);\n\n\t////////////////////////////////////////////////////////////\n\t//\t\t\t\t\tufo script\n\t////////////////////////////////////////////////////////////\n\n\tusing DetectUfoFromBase = MACRO_NAMED_SCRIPT(\"detectUfoFromBase\", DetectUfoFromBaseParser);\n\tusing DetectUfoFromCraft = MACRO_NAMED_SCRIPT(\"detectUfoFromCraft\", DetectUfoFromCraftParser);\n\n\tusing StatsForNerdsUfo = MACRO_NAMED_SCRIPT(\"statsForNerdsUfo\", StatsForNerdsUfoParser);\n\n\t////////////////////////////////////////////////////////////\n\t//\t\t\t\t\tcraft script\n\t////////////////////////////////////////////////////////////\n\n\tusing StatsForNerdsCraft = MACRO_NAMED_SCRIPT(\"statsForNerdsCraft\", StatsForNerdsCraftParser);\n\n\t////////////////////////////////////////////////////////////\n\t//\t\t\t\t\tsoldier bonus stat script\n\t////////////////////////////////////////////////////////////\n\n\tusing ApplySoldierBonuses = MACRO_NAMED_SCRIPT(\"applySoldierBonuses\", ApplySoldierBonusesParser);\n\n\t////////////////////////////////////////////////////////////\n\t//\t\t\t\t\tgroups\n\t////////////////////////////////////////////////////////////\n\n\tusing BattleUnitScripts = ScriptGroup<Mod,\n\t\tRecolorUnitSprite,\n\t\tSelectUnitSprite,\n\t\tSelectMoveSoundUnit,\n\n\t\tReactionUnitAction,\n\t\tReactionUnitReaction,\n\n\t\tTryPsiAttackUnit,\n\t\tTryMeleeAttackUnit,\n\t\tHitUnit,\n\t\tDamageUnit,\n\t\tDamageSpecialUnit,\n\t\tHealUnit,\n\n\t\tCreateUnit,\n\t\tNewTurnUnit,\n\t\tReturnFromMissionUnit,\n\n\t\tAwardExperience,\n\n\t\tVisibilityUnit,\n\n\t\tAiCalculateTargetWeight,\n\n\t\tStatsForNerdsArmor\n\t>;\n\n\tusing BattleItemScripts = ScriptGroup<Mod,\n\t\tRecolorItemSprite,\n\t\tSelectItemSprite,\n\t\tVaporParticleAmmo,\n\t\tVaporParticleWeapon,\n\n\t\tReactionWeaponAction,\n\n\t\tTryPsiAttackItem,\n\t\tTryMeleeAttackItem,\n\t\tHitUnitAmmo,\n\t\tDamageUnitAmmo,\n\t\tDamageSpecialUnitAmmo,\n\n\t\tCreateItem,\n\t\tNewTurnItem,\n\n\t\tSellCostItem,\n\t\tBuyCostItem,\n\n\t\tStatsForNerdsItem\n\t>;\n\n\tusing BonusStatsScripts = ScriptGroup<Mod,\n\t\tPsiDefenceStatBonus,\n\t\tMeleeDodgeStatBonus,\n\n\t\tTimeRecoveryStatBonus,\n\t\tEnergyRecoveryStatBonus,\n\t\tMoraleRecoveryStatBonus,\n\t\tHealthRecoveryStatBonus,\n\t\tManaRecoveryStatBonus,\n\t\tStunRecoveryStatBonus,\n\n\t\tTimeSoldierRecoveryStatBonus,\n\t\tEnergySoldierRecoveryStatBonus,\n\t\tMoraleSoldierRecoveryStatBonus,\n\t\tHealthSoldierRecoveryStatBonus,\n\t\tManaSoldierRecoveryStatBonus,\n\t\tStunSoldierRecoveryStatBonus,\n\n\t\tDamageBonusStatBonus,\n\t\tMeleeBonusStatBonus,\n\t\tAccuracyMultiplierStatBonus,\n\t\tMeleeMultiplierStatBonus,\n\t\tThrowMultiplierStatBonus,\n\t\tCloseQuarterMultiplierStatBonus\n\t>;\n\n\tusing SkillScripts = ScriptGroup<Mod,\n\t\tSkillUseUnit\n\t>;\n\n\tusing CountryScripts = ScriptGroup<Mod,\n\t\tNewMonthCountry\n\t>;\n\n\tusing UfoScripts = ScriptGroup<Mod,\n\t\tDetectUfoFromBase,\n\t\tDetectUfoFromCraft,\n\n\t\tStatsForNerdsUfo\n\t>;\n\n\tusing CraftScripts = ScriptGroup<Mod,\n\t\tStatsForNerdsCraft\n\t>;\n\n\tusing SoldierBonusScripts = ScriptGroup<Mod,\n\t\tApplySoldierBonuses\n\t>;\n\n\t////////////////////////////////////////////////////////////\n\t//\t\t\t\t\tmembers\n\t////////////////////////////////////////////////////////////\n\tBattleUnitScripts battleUnitScripts = { _shared, _mod, \"unit\" };\n\tBattleItemScripts battleItemScripts = { _shared, _mod, \"item\" };\n\tBonusStatsScripts bonusStatsScripts = { _shared, _mod, \"bonuses\" };\n\tSkillScripts skillScripts = { _shared, _mod, \"skill\" };\n\tCountryScripts countryScripts = { _shared, _mod, \"country\" };\n\tUfoScripts ufoScripts = { _shared, _mod, \"ufo\" };\n\tCraftScripts craftScripts = { _shared, _mod, \"craft\" };\n\tSoldierBonusScripts soldierBonusScripts = { _shared, _mod, \"soldier\" };\n\n\n\t////////////////////////////////////////////////////////////\n\t//\t\t\t\t\thelper functions\n\t////////////////////////////////////////////////////////////\n\n\t/**\n\t * Script helper that call script that do not return any values.\n\t * @param t Obect that hold script data.\n\t * @param args List of additionl parameters.\n\t * @return void\n\t */\n\ttemplate<typename ScriptType, typename T, typename... Args>\n\tstatic auto scriptCallback(T* t, Args... args) -> std::enable_if_t<std::is_same<typename ScriptType::Output, ScriptOutputArgs<>>::value, void>\n\t{\n\t\ttypename ScriptType::Output arg{};\n\t\ttypename ScriptType::Worker work{ std::forward<Args>(args)... };\n\n\t\twork.execute(t->template getScript<ScriptType>(), arg);\n\t}\n\n\t/**\n\t * Script helper that call script that return one value and take one parmeters using `ScriptType::Output`\n\t * @param t Obect that hold script data.\n\t * @param first First parameter of `ScriptType::Output`.\n\t * @param args List of additionl parameters.\n\t * @return final value of first parameter.\n\t */\n\ttemplate<typename ScriptType, typename T, typename... Args>\n\tstatic auto scriptFunc1(T* t, int first, Args... args) -> std::enable_if_t<std::is_same<typename ScriptType::Output, ScriptOutputArgs<int&>>::value, int>\n\t{\n\t\ttypename ScriptType::Output arg{ first };\n\t\ttypename ScriptType::Worker work{ std::forward<Args>(args)... };\n\n\t\twork.execute(t->template getScript<ScriptType>(), arg);\n\n\t\treturn arg.getFirst();\n\t}\n\n\t/**\n\t * Script helper that call script that return one value and take two parmeters using `ScriptType::Output`\n\t * @param t Obect that hold script data.\n\t * @param first First parameter of `ScriptType::Output`.\n\t * @param second Second parameter of `ScriptType::Output`.\n\t * @param args List of additionl parameters.\n\t * @return final value of first parameter.\n\t */\n\ttemplate<typename ScriptType, typename T, typename... Args>\n\tstatic auto scriptFunc2(T* t, int first, int second, Args... args) -> std::enable_if_t<std::is_same<typename ScriptType::Output, Output>::value, int>\n\t{\n\t\ttypename ScriptType::Output arg{ first, second };\n\t\ttypename ScriptType::Worker work{ std::forward<Args>(args)... };\n\n\t\twork.execute(t->template getScript<ScriptType>(), arg);\n\n\t\treturn arg.getFirst();\n\t}\n};\n\n}\n"
  },
  {
    "path": "src/Mod/Polygon.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Polygon.h\"\n#include \"../fmath.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes the polygon with arrays to store each point's coordinates.\n * @param points Number of points.\n */\nPolygon::Polygon(int points) : _points(points), _texture(0)\n{\n\t_lat = new double[_points];\n\t_lon = new double[_points];\n\t_x = new Sint16[_points];\n\t_y = new Sint16[_points];\n\tfor (int i = 0; i < _points; ++i)\n\t{\n\t\t_lat[i] = 0.0;\n\t\t_lon[i] = 0.0;\n\t\t_x[i] = 0;\n\t\t_y[i] = 0;\n\t}\n}\n\n/**\n * Performs a deep copy of an existing polygon.\n * @param other Polygon to copy from.\n */\nPolygon::Polygon(const Polygon& other)\n{\n\t_points = other._points;\n\t_lat = new double[_points];\n\t_lon = new double[_points];\n\t_x = new Sint16[_points];\n\t_y = new Sint16[_points];\n\tfor (int i = 0; i < _points; ++i)\n\t{\n\t\t_lat[i] = other._lat[i];\n\t\t_lon[i] = other._lon[i];\n\t\t_x[i] = other._x[i];\n\t\t_y[i] = other._y[i];\n\t}\n\t_texture = other._texture;\n}\n\n/**\n * Deletes the arrays from memory.\n */\nPolygon::~Polygon()\n{\n\tdelete[] _lat;\n\tdelete[] _lon;\n\tdelete[] _x;\n\tdelete[] _y;\n}\n\n/**\n * Loads the polygon from a YAML file.\n * @param node YAML node.\n */\nvoid Polygon::load(const YAML::YamlNodeReader& reader)\n{\n\tdelete[] _lat;\n\tdelete[] _lon;\n\tdelete[] _x;\n\tdelete[] _y;\n\n\tstd::vector<double> coords = reader.readVal<std::vector<double> >();\n\t_points = (coords.size() - 1) / 2;\n\t_lat = new double[_points];\n\t_lon = new double[_points];\n\t_x = new Sint16[_points];\n\t_y = new Sint16[_points];\n\n\t_texture = coords[0];\n\tfor (size_t i = 1; i < coords.size(); i += 2)\n\t{\n\t\tsize_t j = (i - 1) / 2;\n\t\t_lon[j] = Deg2Rad(coords[i]);\n\t\t_lat[j] = Deg2Rad(coords[i+1]);\n\t\t_x[j] = 0;\n\t\t_y[j] = 0;\n\t}\n}\n\n/**\n * Returns the latitude of a given point.\n * @param i Point number (0-max).\n * @return Point's latitude.\n */\ndouble Polygon::getLatitude(int i) const\n{\n\treturn _lat[i];\n}\n\n/**\n * Changes the latitude of a given point.\n * @param i Point number (0-max).\n * @param lat Point's latitude.\n */\nvoid Polygon::setLatitude(int i, double lat)\n{\n\t_lat[i] = lat;\n}\n\n/**\n * Returns the longitude of a given point.\n * @param i Point number (0-max).\n * @return Point's longitude.\n */\ndouble Polygon::getLongitude(int i) const\n{\n\treturn _lon[i];\n}\n\n/**\n * Changes the latitude of a given point.\n * @param i Point number (0-max).\n * @param lon Point's longitude.\n */\nvoid Polygon::setLongitude(int i, double lon)\n{\n\t_lon[i] = lon;\n}\n\n/**\n * Returns the X coordinate of a given point.\n * @param i Point number (0-max).\n * @return Point's X coordinate.\n */\nSint16 Polygon::getX(int i) const\n{\n\treturn _x[i];\n}\n\n/**\n * Changes the X coordinate of a given point.\n * @param i Point number (0-max).\n * @param x Point's X coordinate.\n */\nvoid Polygon::setX(int i, Sint16 x)\n{\n\t_x[i] = x;\n}\n\n/**\n * Returns the Y coordinate of a given point.\n * @param i Point number (0-max).\n * @return Point's Y coordinate.\n */\nSint16 Polygon::getY(int i) const\n{\n\treturn _y[i];\n}\n\n/**\n * Changes the Y coordinate of a given point.\n * @param i Point number (0-max).\n * @param y Point's Y coordinate.\n */\nvoid Polygon::setY(int i, Sint16 y)\n{\n\t_y[i] = y;\n}\n\n/**\n * Returns the texture used to draw the polygon\n * (textures are stored in a set).\n * @return Texture sprite number.\n */\nint Polygon::getTexture() const\n{\n\treturn _texture;\n}\n\n/**\n * Changes the texture used to draw the polygon.\n * @param tex Texture sprite number.\n */\nvoid Polygon::setTexture(int tex)\n{\n\t_texture = tex;\n}\n\n/**\n * Returns the number of points (vertexes) that make up the polygon.\n * @return Number of points.\n */\nint Polygon::getPoints() const\n{\n\treturn _points;\n}\n\n}\n"
  },
  {
    "path": "src/Mod/Polygon.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <SDL_types.h>\n#include \"../Engine/Yaml.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Represents a polygon in the world map.\n * Polygons constitute the textured land portions\n * of the X-Com globe and typically have 3-4 points.\n */\nclass Polygon\n{\nprivate:\n\tdouble *_lat, *_lon;\n\tSint16 *_x, *_y;\n\tint _points, _texture;\npublic:\n\t/// Creates a polygon with a number of points.\n\tPolygon(int points);\n\t/// Creates a new polygon from an existing one.\n\tPolygon(const Polygon& other);\n\t/// Cleans up the polygon.\n\t~Polygon();\n\t/// Loads the polygon from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader);\n\t/// Gets the latitude of a point.\n\tdouble getLatitude(int i) const;\n\t/// Sets the latitude of a point.\n\tvoid setLatitude(int i, double lat);\n\t/// Gets the longitude of a point.\n\tdouble getLongitude(int i) const;\n\t/// Sets the longitude of a point.\n\tvoid setLongitude(int i, double lon);\n\t/// Gets the X coordinate of a point.\n\tSint16 getX(int i) const;\n\t/// Sets the X coordinate of a point.\n\tvoid setX(int i, Sint16 x);\n\t/// Gets the Y coordinate of a point.\n\tSint16 getY(int i) const;\n\t/// Sets the Y coordinate of a point.\n\tvoid setY(int i, Sint16 y);\n\t/// Gets the texture of the polygon.\n\tint getTexture() const;\n\t/// Sets the texture of the polygon.\n\tvoid setTexture(int tex);\n\t/// Gets the number of points of the polygon.\n\tint getPoints() const;\n};\n\n}\n"
  },
  {
    "path": "src/Mod/Polyline.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Polyline.h\"\n#include \"../fmath.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes the polyline with arrays to store each point's coordinates.\n * @param points Number of points.\n */\nPolyline::Polyline(int points) : _points(points)\n{\n\t_lat = new double[points];\n\t_lon = new double[points];\n}\n\n/**\n * Deletes the arrays from memory.\n */\nPolyline::~Polyline()\n{\n\tdelete[] _lat;\n\tdelete[] _lon;\n}\n\n/**\n * Loads the polyline from a YAML file.\n * @param node YAML node.\n */\nvoid Polyline::load(const YAML::YamlNodeReader& reader)\n{\n\tdelete[] _lat;\n\tdelete[] _lon;\n\n\tstd::vector<double> coords = reader.readVal<std::vector<double> >();\n\t_points = coords.size() / 2;\n\t_lat = new double[_points];\n\t_lon = new double[_points];\n\n\tfor (size_t i = 0; i < coords.size(); i += 2)\n\t{\n\t\tsize_t j = i / 2;\n\t\t_lon[j] = Deg2Rad(coords[i]);\n\t\t_lat[j] = Deg2Rad(coords[i+1]);\n\t}\n}\n\n/**\n * Returns the latitude (X) of a given point.\n * @param i Point number (0-max).\n * @return Point's latitude.\n */\ndouble Polyline::getLatitude(int i) const\n{\n\treturn _lat[i];\n}\n\n/**\n * Changes the latitude of a given point.\n * @param i Point number (0-max).\n * @param lat Point's latitude.\n */\nvoid Polyline::setLatitude(int i, double lat)\n{\n\t_lat[i] = lat;\n}\n\n/**\n * Returns the longitude (Y) of a given point.\n * @param i Point number (0-max).\n * @return Point's longitude.\n */\ndouble Polyline::getLongitude(int i) const\n{\n\treturn _lon[i];\n}\n\n/**\n * Changes the latitude of a given point.\n * @param i Point number (0-max).\n * @param lon Point's longitude.\n */\nvoid Polyline::setLongitude(int i, double lon)\n{\n\t_lon[i] = lon;\n}\n\n/**\n * Returns the number of points (vertexes) that make up the polyline.\n * @return Number of points.\n */\nint Polyline::getPoints() const\n{\n\treturn _points;\n}\n\n}\n"
  },
  {
    "path": "src/Mod/Polyline.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/Yaml.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Represents a polyline in the world map.\n * Polylines constitute the detail portions of the\n * X-Com globe and typically represent borders and rivers.\n */\nclass Polyline\n{\nprivate:\n\tdouble *_lat, *_lon;\n\tint _points;\npublic:\n\t/// Creates a polyline with a number of points.\n\tPolyline(int points);\n\t/// Cleans up the polyline.\n\t~Polyline();\n\t/// Loads the polyline from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader);\n\t/// Gets the latitude of a point.\n\tdouble getLatitude(int i) const;\n\t/// Sets the latitude of a point.\n\tvoid setLatitude(int i, double lat);\n\t/// Gets the longitude of a point.\n\tdouble getLongitude(int i) const;\n\t/// Sets the longitude of a point.\n\tvoid setLongitude(int i, double lon);\n\t/// Gets the number of points of the polyline.\n\tint getPoints() const;\n};\n\n}\n"
  },
  {
    "path": "src/Mod/RuleAlienMission.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"RuleAlienMission.h\"\n#include \"../Savegame/WeightedOptions.h\"\n\nnamespace OpenXcom\n{\n\nRuleAlienMission::RuleAlienMission(const std::string &type) :\n\t_type(type), _skipScoutingPhase(false), _points(0), _objective(OBJECTIVE_SCORE), _spawnZone(-1),\n\t_retaliationOdds(-1), _endlessInfiltration(true), _multiUfoRetaliation(false), _multiUfoRetaliationExtra(false),\n\t_ignoreBaseDefenses(false), _instaHyper(false),\n\t_despawnEvenIfTargeted(false), _respawnUfoAfterSiteDespawn(false), _showAlienBase(false),\n\t_operationType(AMOT_SPACE), _operationSpawnZone(-1),\n\t_targetBaseOdds(0)\n{\n}\n\n/**\n * Ensures the allocated memory is released.\n */\nRuleAlienMission::~RuleAlienMission()\n{\n\tfor (auto& pair : _raceDistribution)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _regionWeights)\n\t{\n\t\tdelete pair.second;\n\t}\n}\n\n/**\n * Loads the mission data from a YAML node.\n * @param node YAML node.\n */\nvoid RuleAlienMission::load(const YAML::YamlNodeReader& node)\n{\n\tconst auto& reader = node.useIndex();\n\tif (const auto& parent = reader[\"refNode\"])\n\t{\n\t\tload(parent);\n\t}\n\n\treader.tryRead(\"points\", _points);\n\treader.tryRead(\"waves\", _waves);\n\treader.tryRead(\"objective\", _objective);\n\treader.tryRead(\"spawnUfo\", _spawnUfo);\n\treader.tryRead(\"skipScoutingPhase\", _skipScoutingPhase);\n\treader.tryRead(\"spawnZone\", _spawnZone);\n\treader.tryRead(\"missionWeights\", _weights);\n\treader.tryRead(\"retaliationOdds\", _retaliationOdds);\n\treader.tryRead(\"endlessInfiltration\", _endlessInfiltration);\n\treader.tryRead(\"multiUfoRetaliation\", _multiUfoRetaliation);\n\treader.tryRead(\"multiUfoRetaliationExtra\", _multiUfoRetaliationExtra);\n\tif (_multiUfoRetaliationExtra)\n\t{\n\t\t// yes, I should have changed _multiUfoRetaliation to int instead, but I'm lazy\n\t\t// I also don't want to break existing mods or handle it in a complicated way\n\t\t_multiUfoRetaliation = true;\n\t}\n\treader.tryRead(\"ignoreBaseDefenses\", _ignoreBaseDefenses);\n\treader.tryRead(\"instaHyper\", _instaHyper);\n\treader.tryRead(\"despawnEvenIfTargeted\", _despawnEvenIfTargeted);\n\treader.tryRead(\"respawnUfoAfterSiteDespawn\", _respawnUfoAfterSiteDespawn);\n\treader.tryRead(\"showAlienBase\", _showAlienBase);\n\treader.tryRead(\"interruptResearch\", _interruptResearch);\n\treader.tryRead(\"siteType\", _siteType);\n\treader.tryRead(\"operationType\", _operationType);\n\treader.tryRead(\"operationSpawnZone\", _operationSpawnZone);\n\treader.tryRead(\"operationBaseType\", _operationBaseType);\n\treader.tryRead(\"targetBaseOdds\", _targetBaseOdds);\n\n\tfor (const auto& weights : reader[\"regionWeights\"].children())\n\t{\n\t\tWeightedOptions* nw = new WeightedOptions();\n\t\tnw->load(weights);\n\t\t_regionWeights.push_back(std::make_pair(weights.readKey<size_t>(0), nw));\n\t}\n\n\t//Only allow full replacement of mission racial distribution.\n\tif (const auto& weights = reader[\"raceWeights\"])\n\t{\n\t\ttypedef std::map<size_t, WeightedOptions*> Associative;\n\t\ttypedef std::vector< std::pair<size_t, WeightedOptions*> > Linear;\n\n\t\tAssociative assoc;\n\t\t//Place in the associative container so we can index by month and keep entries sorted.\n\t\tfor (Linear::iterator ii = _raceDistribution.begin(); ii != _raceDistribution.end(); ++ii)\n\t\t{\n\t\t\tassoc.insert(*ii);\n\t\t}\n\n\t\t// Now go through the node contents and merge with existing data.\n\t\tfor (const auto& nn : weights.children())\n\t\t{\n\t\t\tsize_t month = nn.readKey<size_t>();\n\t\t\tAssociative::iterator existing = assoc.find(month);\n\t\t\tif (assoc.end() == existing)\n\t\t\t{\n\t\t\t\t// New entry, load and add it.\n\t\t\t\tWeightedOptions *nw = new WeightedOptions();\n\t\t\t\tnw->load(nn);\n\t\t\t\tassoc.insert(std::make_pair(month, nw));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// Existing entry, update it.\n\t\t\t\texisting->second->load(nn);\n\t\t\t}\n\t\t}\n\n\t\t// Now replace values in our actual member variable!\n\t\t_raceDistribution.clear();\n\t\t_raceDistribution.reserve(assoc.size());\n\t\tfor (Associative::iterator ii = assoc.begin(); ii != assoc.end(); ++ii)\n\t\t{\n\t\t\tif (ii->second->empty())\n\t\t\t{\n\t\t\t\t// Don't keep empty lists.\n\t\t\t\tdelete ii->second;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// Place it\n\t\t\t\t_raceDistribution.push_back(*ii);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * @return if this mission uses a weighted distribution to pick a race.\n */\nbool RuleAlienMission::hasRaceWeights() const\n{\n\treturn !_raceDistribution.empty();\n}\n\n/**\n * Chooses one of the available races for this mission.\n * The racial distribution may vary based on the current game date.\n * @param monthsPassed The number of months that have passed in the game world.\n * @return The string id of the race.\n */\nstd::string RuleAlienMission::generateRace(const size_t monthsPassed) const\n{\n\tstd::vector<std::pair<size_t, WeightedOptions*> >::const_reverse_iterator rc;\n\tfor (rc = _raceDistribution.rbegin(); rc != _raceDistribution.rend() && monthsPassed < rc->first; ++rc);\n\tif (rc == _raceDistribution.rend())\n\t\treturn \"\";\n\treturn rc->second->choose();\n}\n\n/**\n * Returns the Alien score for this mission.\n * @return Amount of points.\n */\nint RuleAlienMission::getPoints() const\n{\n\treturn _points;\n}\n\n/**\n * Returns the chances of this mission being generated based on the current game date.\n * @param monthsPassed The number of months that have passed in the game world.\n * @return The weight.\n */\nint RuleAlienMission::getWeight(const size_t monthsPassed) const\n{\n\tif (_weights.empty())\n\t{\n\t\treturn 1;\n\t}\n\tint weight = 0;\n\tfor (auto& pair : _weights)\n\t{\n\t\tif (pair.first > monthsPassed)\n\t\t{\n\t\t\tbreak;\n\t\t}\n\t\tweight = pair.second;\n\t}\n\treturn weight;\n}\n\n/**\n * Returns the Alien score for this mission.\n * @return Amount of points.\n */\nint RuleAlienMission::getRetaliationOdds() const\n{\n\treturn _retaliationOdds;\n}\n\n/**\n * Should the infiltration end after first cycle or continue indefinitely?\n * @return True, if infiltration should continue indefinitely.\n */\nbool RuleAlienMission::isEndlessInfiltration() const\n{\n\treturn _endlessInfiltration;\n}\n\n/**\n * Does this mission have region weights?\n * @return if this mission uses a weighted distribution to pick a region.\n */\nbool RuleAlienMission::hasRegionWeights() const\n{\n\treturn !_regionWeights.empty();\n}\n\n/**\n * Chooses one of the available regions for this mission.\n * The region distribution may vary based on the current game date.\n * @param monthsPassed The number of months that have passed in the game world.\n * @return The string id of the region.\n */\nstd::string RuleAlienMission::generateRegion(const size_t monthsPassed) const\n{\n\tstd::vector<std::pair<size_t, WeightedOptions*> >::const_reverse_iterator rc = _regionWeights.rbegin();\n\twhile (monthsPassed < rc->first)\n\t\t++rc;\n\treturn rc->second->choose();\n}\n\n// helper overloads for deserialization-only\nbool read(ryml::ConstNodeRef const& n, MissionWave* val)\n{\n\tYAML::YamlNodeReader reader(n);\n\treader.tryRead(\"ufo\", val->ufoType);\n\treader.tryRead(\"count\", val->ufoCount);\n\treader.tryRead(\"trajectory\", val->trajectory);\n\treader.tryRead(\"timer\", val->spawnTimer);\n\treader.readNode(\"objective\", val->objective, false);\n\treader.readNode(\"objectiveOnTheLandingSite\", val->objectiveOnTheLandingSite, false);\n\treader.readNode(\"objectiveOnXcomBase\", val->objectiveOnXcomBase, false);\n\treader.readNode(\"hunterKillerPercentage\", val->hunterKillerPercentage, -1);\n\treader.readNode(\"huntMode\", val->huntMode, -1);\n\treader.readNode(\"huntBehavior\", val->huntBehavior, -1);\n\treader.readNode(\"escort\", val->escort, false);\n\treader.readNode(\"interruptPercentage\", val->interruptPercentage, 0);\n\n\treturn true;\n}\n\n}\n"
  },
  {
    "path": "src/Mod/RuleAlienMission.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <vector>\n#include <map>\n#include <string>\n#include \"../Engine/Yaml.h\"\n\nnamespace OpenXcom\n{\n\nenum AlienMissionOperationType {\n\tAMOT_SPACE,\n\tAMOT_REGION_EXISTING_BASE,\n\tAMOT_REGION_NEW_BASE,\n\tAMOT_REGION_NEW_BASE_IF_NECESSARY,\n\tAMOT_EARTH_EXISTING_BASE,\n\tAMOT_EARTH_NEW_BASE_IF_NECESSARY,\n\tAMOT_EXISTING_BASE_HUNT_MISSION\n};\n\nclass WeightedOptions;\n\n/**\n * @brief Information about a mission wave.\n * Mission waves control the UFOs that will be generated during an alien mission.\n */\nstruct MissionWave\n{\n\t/// The type of the spawned UFOs.\n\tstd::string ufoType;\n\t/// The number of UFOs that will be generated.\n\t/**\n\t * The UFOs are generated sequentially, one every @a spawnTimer minutes.\n\t */\n\tsize_t ufoCount;\n\t/// The trajectory ID for this wave's UFOs.\n\t/**\n\t * Trajectories control the way UFOs fly around the Geoscape.\n\t */\n\tstd::string trajectory;\n\t/// Number of minutes between UFOs in the wave.\n\t/**\n\t * The actual value used is spawnTimer/4 or 3*spawnTimer/4.\n\t */\n\tsize_t spawnTimer;\n\t/// This wave performs the mission objective.\n\t/**\n\t * The UFO executes a special action based on the mission objective.\n\t */\n\tbool objective;\n\t/// This wave performs the mission objective in a rectangular (non-point) area.\n\t/**\n\t * Make the UFO land on a random landing site (instead of always top left). Make the mission site spawn exactly on the landing site.\n\t */\n\tbool objectiveOnTheLandingSite;\n\t/**\n\t * Make the mission site spawn on an xcom base (or not at all).\n\t */\n\tbool objectiveOnXcomBase;\n\t/// The chance to become a hunter-killer UFO upon spawning.\n\t/**\n\t * -1 (default): take the info from RuleUfo\n\t *  0: not a hunter-killer\n\t *  1..99: percentage chance to be flagged as hunter-killer upon spawn\n\t *  100: always a hunter-killer\n\t */\n\tint hunterKillerPercentage;\n\t/// Algorithm to use when prioritizing xcom targets\n\t/**\n\t * -1 (default): take the info from RuleUfo\n\t * 0: prefer hunting xcom interceptors\n\t * 1: prefer hunting xcom transports\n\t * 2: random preference (0 or 1) determined at spawn\n\t */\n\tint huntMode;\n\t/// Algorithm to use when considering retreating from the dogfight\n\t/**\n\t* -1 (default): take the info from RuleUfo\n\t* 0: flee if you're losing\n\t* 1: never flee, never crash (is destroyed instead of crashing)\n\t* 2: random preference (0 or 1) determined at spawn\n\t*/\n\tint huntBehavior;\n\t/// Does this wave escort/protect the previous wave(s)?\n\t/**\n\t* The UFO escorts other UFO(s) from the same mission.\n\t*/\n\tbool escort;\n\t/// The chance to interrupt the alien mission when successfully shooting down a UFO from this wave.\n\t/**\n\t*  0 (default): cannot interrupt\n\t*  1..99: percentage chance to be interrupted\n\t*  100: always interrupted\n\t*/\n\tint interruptPercentage;\n};\n\nenum MissionObjective { OBJECTIVE_SCORE, OBJECTIVE_INFILTRATION, OBJECTIVE_BASE, OBJECTIVE_SITE, OBJECTIVE_RETALIATION, OBJECTIVE_SUPPLY, OBJECTIVE_INSTANT_RETALIATION };\n\n/**\n * Stores fixed information about a mission type.\n * It stores the mission waves and the distribution of the races that can\n * undertake the mission based on game date.\n */\nclass RuleAlienMission\n{\npublic:\n\tRuleAlienMission(const std::string &type);\n\t/// Releases all resources held by the mission.\n\t~RuleAlienMission();\n\t/// Gets the mission's type.\n\tconst std::string &getType() const { return _type; }\n\t/// Does this mission have raceWeights?\n\tbool hasRaceWeights() const;\n\t/// Gets a race based on the game time and the racial distribution.\n\tstd::string generateRace(const size_t monthsPassed) const;\n\t/// Loads alien mission data from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader);\n\t/// Gets the number of waves.\n\tsize_t getWaveCount() const { return _waves.size(); }\n\t/// Gets the full wave information.\n\tconst MissionWave &getWave(size_t index) const { return _waves[index]; }\n\t/// Gets the score for this mission.\n\tint getPoints() const;\n\t/// Gets the objective for this mission.\n\tMissionObjective getObjective() const { return _objective; }\n\t/// Gets the UFO type for special spawns.\n\tconst std::string &getSpawnUfo() const { return _spawnUfo; }\n\t/// Should the scouting phase of the retaliation mission be skipped?\n\tbool skipScoutingPhase() const { return _skipScoutingPhase; }\n\t/// Gets the zone for spawning an alien site or base.\n\tint getSpawnZone() const { return _spawnZone; }\n\t/// Gets the chances of this mission based on the game time.\n\tint getWeight(const size_t monthsPassed) const;\n\t/// Gets the inherent odds of this mission spawning a retaliation mission.\n\tint getRetaliationOdds() const;\n\t/// Should the infiltration end after first cycle or continue indefinitely?\n\tbool isEndlessInfiltration() const;\n\t/// Should the retaliation mission end after the first base defense or continue until all already spawned UFOs disappear?\n\tbool isMultiUfoRetaliation() const { return _multiUfoRetaliation; }\n\t/// Should the retaliation mission continue generating UFOs even after the first base defense?\n\tbool isMultiUfoRetaliationExtra() const { return _multiUfoRetaliationExtra; }\n\t/// Should the retaliation UFO ignore xcom base defenses?\n\tbool ignoreBaseDefenses() const { return _ignoreBaseDefenses; }\n\t/// Show extra info during base defense even if the UFO was not yet hyper-detected classically?\n\tbool isInstaHyper() const { return _instaHyper; }\n\t/// Should the mission site despawn even if targeted?\n\tbool despawnEvenIfTargeted() const { return _despawnEvenIfTargeted; }\n\t/// Should the original UFO be respawned when the mission site despawns?\n\tbool respawnUfoAfterSiteDespawn() const { return _respawnUfoAfterSiteDespawn; }\n\t/// Should the spawned alien base be revealed immediately?\n\tbool showAlienBase() const { return _showAlienBase; }\n\t/// Gets the ID of the research topic that interrupts this mission (if any).\n\tconst std::string &getInterruptResearch() const { return _interruptResearch; }\n\t/// the type of missionSite to spawn (if any)\n\tstd::string getSiteType() const { return _siteType; }\n\t/// From where does this mission operate?\n\tAlienMissionOperationType getOperationType() const { return _operationType; }\n\t/// Gets the mission zone for spawning the operation base (if necessary).\n\tint getOperationSpawnZone() const { return _operationSpawnZone; }\n\t/// Gets the type of operation base to spawn (if any).\n\tconst std::string &getOperationBaseType() const { return _operationBaseType; }\n\t/// Gets the odds of this mission targetting an xcom base. Works only for \"gen missions\" spawned by an alien base.\n\tint getTargetBaseOdds() const { return _targetBaseOdds; }\n\t/// Does this mission have region weights? Works only for \"gen missions\" spawned by an alien base.\n\tbool hasRegionWeights() const;\n\t/// Gets a region based on the game time and the region distribution. Works only for \"gen missions\" spawned by an alien base.\n\tstd::string generateRegion(const size_t monthsPassed) const;\nprivate:\n\t/// The mission's type ID.\n\tstd::string _type;\n\t/// The UFO to use for spawning.\n\tstd::string _spawnUfo;\n\t/// Should the scouting phase of the retaliation mission be skipped?\n\tbool _skipScoutingPhase;\n\t/// The race distribution over game time.\n\tstd::vector<std::pair<size_t, WeightedOptions*> > _raceDistribution;\n\t/// The mission's weights.\n\tstd::map<size_t, int> _weights;\n\t/// The mission's waves.\n\tstd::vector<MissionWave> _waves;\n\t/// The mission's points.\n\tint _points;\n\t/// The mission's objective.\n\tMissionObjective _objective;\n\t/// The mission zone to use for spawning.\n\tint _spawnZone;\n\t/// The odds that this mission will result in retaliation\n\tint _retaliationOdds;\n\t/// Should the infiltration end after first cycle or continue indefinitely?\n\tbool _endlessInfiltration;\n\t/// Should the retaliation mission end after the first base defense or continue until all already spawned UFOs disappear?\n\tbool _multiUfoRetaliation;\n\t/// Should the retaliation mission continue generating UFOs even after the first base defense?\n\tbool _multiUfoRetaliationExtra;\n\t/// Should the retaliation UFO ignore xcom base defenses?\n\tbool _ignoreBaseDefenses;\n\t/// Should the retaliation UFO display extra info before xcom base defenses?\n\tbool _instaHyper;\n\t/// Should the mission site despawn even if targeted?\n\tbool _despawnEvenIfTargeted;\n\t/// Should the original UFO be respawned when the mission site despawns?\n\tbool _respawnUfoAfterSiteDespawn;\n\t/// Should the spawned alien base be revealed immediately?\n\tbool _showAlienBase;\n\t/// the research topic that interrupts this mission type (when discovered)\n\tstd::string _interruptResearch;\n\t/// the type of missionSite to spawn (if any)\n\tstd::string _siteType;\n\t/// From where does this mission operate?\n\tAlienMissionOperationType _operationType;\n\t/// The mission zone for spawning the operation base (if necessary).\n\tint _operationSpawnZone;\n\t/// The type of operation base to spawn (if any).\n\tstd::string _operationBaseType;\n\t/// The odds of this mission targetting an xcom base. Works only for \"gen missions\" spawned by an alien base.\n\tint _targetBaseOdds;\n\t/// The region distribution over game time. Works only for \"gen missions\" spawned by an alien base.\n\tstd::vector<std::pair<size_t, WeightedOptions*> > _regionWeights;\n};\n\n// helper overloads for deserialization-only\nbool read(ryml::ConstNodeRef const& n, MissionWave* val);\n\n}\n"
  },
  {
    "path": "src/Mod/RuleArcScript.cpp",
    "content": "/*\n * Copyright 2010-2019 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"RuleArcScript.h\"\n#include <climits>\n\nnamespace OpenXcom\n{\n\n/**\n * RuleArcScript: the (optional) rules for the high-level game progression.\n * Each script element is independent, and the saved game will probe the list of these each month to determine what's going to happen.\n * Arc scripts are executed just before the mission scripts and unlock research topics that can then be used by mission scripts.\n */\nRuleArcScript::RuleArcScript(const std::string& type) :\n\t_type(type), _firstMonth(0), _lastMonth(-1), _executionOdds(100), _maxArcs(-1), _minDifficulty(0), _maxDifficulty(4),\n\t_minScore(INT_MIN), _maxScore(INT_MAX), _minFunds(INT64_MIN), _maxFunds(INT64_MAX)\n{\n}\n\n/**\n *\n */\nRuleArcScript::~RuleArcScript()\n{\n}\n\n/**\n * Loads an arcScript from a YML file.\n * @param node the node within the file we're reading.\n */\nvoid RuleArcScript::load(const YAML::YamlNodeReader& node)\n{\n\tconst auto& reader = node.useIndex();\n\tif (const auto& parent = reader[\"refNode\"])\n\t{\n\t\tload(parent);\n\t}\n\n\treader.tryRead(\"sequentialArcs\", _sequentialArcs);\n\tif (reader[\"randomArcs\"])\n\t{\n\t\t_randomArcs.load(reader[\"randomArcs\"]);\n\t}\n\treader.tryRead(\"firstMonth\", _firstMonth);\n\treader.tryRead(\"lastMonth\", _lastMonth);\n\treader.tryRead(\"executionOdds\", _executionOdds);\n\treader.tryRead(\"maxArcs\", _maxArcs);\n\treader.tryRead(\"minDifficulty\", _minDifficulty);\n\treader.tryRead(\"maxDifficulty\", _maxDifficulty);\n\treader.tryRead(\"minScore\", _minScore);\n\treader.tryRead(\"maxScore\", _maxScore);\n\treader.tryRead(\"minFunds\", _minFunds);\n\treader.tryRead(\"maxFunds\", _maxFunds);\n\treader.tryRead(\"missionVarName\", _missionVarName);\n\treader.tryRead(\"missionMarkerName\", _missionMarkerName);\n\treader.tryRead(\"counterMin\", _counterMin);\n\treader.tryRead(\"counterMax\", _counterMax);\n\n\treader.tryRead(\"researchTriggers\", _researchTriggers);\n\treader.tryRead(\"itemTriggers\", _itemTriggers);\n\treader.tryRead(\"facilityTriggers\", _facilityTriggers);\n\treader.tryRead(\"soldierTypeTriggers\", _soldierTypeTriggers);\n\treader.tryRead(\"xcomBaseInRegionTriggers\", _xcomBaseInRegionTriggers);\n\treader.tryRead(\"xcomBaseInCountryTriggers\", _xcomBaseInCountryTriggers);\n\treader.tryRead(\"pactCountryTriggers\", _pactCountryTriggers);\n}\n\n}\n"
  },
  {
    "path": "src/Mod/RuleArcScript.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2019 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include <vector>\n#include <map>\n#include \"../Engine/Yaml.h\"\n#include \"../Savegame/WeightedOptions.h\"\n\nnamespace OpenXcom\n{\n\nclass RuleArcScript\n{\nprivate:\n\tstd::string _type;\n\tstd::vector<std::string> _sequentialArcs;\n\tWeightedOptions _randomArcs;\n\tint _firstMonth, _lastMonth, _executionOdds, _maxArcs, _minDifficulty, _maxDifficulty;\n\tint _minScore, _maxScore;\n\tint64_t _minFunds, _maxFunds;\n\tstd::string _missionVarName, _missionMarkerName;\n\tint _counterMin, _counterMax;\n\n\tstd::map<std::string, bool> _researchTriggers;\n\tstd::map<std::string, bool> _itemTriggers;\n\tstd::map<std::string, bool> _facilityTriggers;\n\tstd::map<std::string, bool> _soldierTypeTriggers;\n\tstd::map<std::string, bool> _xcomBaseInRegionTriggers;\n\tstd::map<std::string, bool> _xcomBaseInCountryTriggers;\n\tstd::map<std::string, bool> _pactCountryTriggers;\n\npublic:\n\t/// Creates a new arc script.\n\tRuleArcScript(const std::string& type);\n\t/// Deletes an arc script.\n\t~RuleArcScript();\n\t/// Loads an arc script from yaml.\n\tvoid load(const YAML::YamlNodeReader& reader);\n\t/// Gets the name of the script command.\n\tconst std::string &getType() const { return _type; }\n\t/// Gets the sequential arcs list.\n\tconst std::vector<std::string> &getSequentialArcs() const { return _sequentialArcs; }\n\t/// Gets the random arcs weighted list.\n\tconst WeightedOptions &getRandomArcs() const { return _randomArcs; }\n\t/// Gets the first month this command will run.\n\tint getFirstMonth() const { return _firstMonth; }\n\t/// Gets the last month this command will run.\n\tint getLastMonth() const { return _lastMonth; }\n\t/// Gets the odds of this command executing.\n\tint getExecutionOdds() const { return _executionOdds; }\n\t/// Gets the maximum number of arcs this command can generate (during the whole game).\n\tint getMaxArcs() const { return _maxArcs; }\n\t/// Gets the minimum difficulty for this command to run.\n\tint getMinDifficulty() const { return _minDifficulty; }\n\t/// Gets the maximum difficulty for this command to run.\n\tint getMaxDifficulty() const { return _maxDifficulty; }\n\t/// Gets the minimum score (from last month) for this command to run.\n\tint getMinScore() const { return _minScore; }\n\t/// Gets the maximum score (from last month) for this command to run.\n\tint getMaxScore() const { return _maxScore; }\n\t/// Gets the minimum funds (from current month) for this command to run.\n\tint64_t getMinFunds() const { return _minFunds; }\n\t/// Gets the maximum funds (from current month) for this command to run.\n\tint64_t getMaxFunds() const { return _maxFunds; }\n\t/// Gets the name of the mission script tracking variable.\n\tconst std::string& getMissionVarName() const { return _missionVarName; }\n\t/// Gets the name of the mission marker tracking variable.\n\tconst std::string& getMissionMarkerName() const { return _missionMarkerName; }\n\t/// Gets the minimum number of missions generated for this command to run.\n\tint getCounterMin() const { return _counterMin; }\n\t/// Gets the maximum number of missions generated for this command to run.\n\tint getCounterMax() const { return _counterMax; }\n\n\t/// Gets the research triggers that may apply to this command.\n\tconst std::map<std::string, bool> &getResearchTriggers() const { return _researchTriggers; }\n\t/// Gets the item triggers that may apply to this command.\n\tconst std::map<std::string, bool> &getItemTriggers() const { return _itemTriggers; }\n\t/// Gets the facility triggers that may apply to this command.\n\tconst std::map<std::string, bool> &getFacilityTriggers() const { return _facilityTriggers; }\n\t/// Gets the soldier type triggers that may apply to this command.\n\tconst std::map<std::string, bool> &getSoldierTypeTriggers() const { return _soldierTypeTriggers; }\n\t/// Gets the xcom base triggers that may apply to this command.\n\tconst std::map<std::string, bool> &getXcomBaseInRegionTriggers() const { return _xcomBaseInRegionTriggers; }\n\t/// Gets the xcom base triggers that may apply to this command.\n\tconst std::map<std::string, bool> &getXcomBaseInCountryTriggers() const { return _xcomBaseInCountryTriggers; }\n\t/// Gets the country pact triggers that may apply to this command.\n\tconst std::map<std::string, bool> &getPactCountryTriggers() const { return _pactCountryTriggers; }\n\n};\n\n}\n"
  },
  {
    "path": "src/Mod/RuleBaseFacility.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <algorithm>\n#include \"RuleBaseFacility.h\"\n#include \"Mod.h\"\n#include \"MapScript.h\"\n#include \"../Battlescape/Position.h\"\n#include \"../Battlescape/TileEngine.h\"\n#include \"../Engine/Exception.h\"\n#include \"../Engine/Collections.h\"\n#include \"../Savegame/Base.h\"\n\n\nnamespace OpenXcom\n{\n\n/**\n * Creates a blank ruleset for a certain\n * type of base facility.\n * @param type String defining the type.\n */\nRuleBaseFacility::RuleBaseFacility(const std::string &type, int listOrder) :\n\t_type(type), _spriteShape(-1), _spriteFacility(-1), _connectorsDisabled(false),\n\t_missileAttraction(100), _fakeUnderwater(-1),\n\t_lift(false), _hyper(false), _mind(false), _grav(false), _mindPower(1),\n\t_sizeX(1), _sizeY(1), _buildCost(0), _refundValue(0), _buildTime(0), _monthlyCost(0),\n\t_storage(0), _personnel(0), _aliens(0), _crafts(0), _labs(0), _workshops(0), _psiLabs(0),\n\t_spriteEnabled(false),\n\t_sightRange(0), _sightChance(0), _radarRange(0), _radarChance(0),\n\t_defense(0), _hitRatio(0), _fireSound(0), _hitSound(0), _placeSound(-1),\n\t_ammoMax(0), _rearmRate(1), _ammoNeeded(1), _unifiedDamageFormula(false), _shieldDamageModifier(100), _listOrder(listOrder),\n\t_trainingRooms(0), _maxAllowedPerBase(0), _sickBayAbsoluteBonus(0.0f), _sickBayRelativeBonus(0.0f),\n\t_prisonType(0), _rightClickActionType(0), _verticalLevels(),\n\t_removalTime(0), _canBeBuiltOver(false), _upgradeOnly(false), _destroyedFacility(0)\n{\n}\n\n/**\n *\n */\nRuleBaseFacility::~RuleBaseFacility()\n{\n}\n\n/**\n * Loads the base facility type from a YAML file.\n * @param node YAML node.\n * @param mod Mod for the facility.\n * @param listOrder The list weight for this facility.\n */\nvoid RuleBaseFacility::load(const YAML::YamlNodeReader& node, Mod *mod)\n{\n\tconst auto& reader = node.useIndex();\n\tif (const auto& parent = reader[\"refNode\"])\n\t{\n\t\tload(parent, mod);\n\t}\n\n\treader.tryRead(\"ufopediaType\", _ufopediaType);\n\n\tmod->loadUnorderedNames(_type, _requires, reader[\"requires\"]);\n\n\tmod->loadBaseFunction(_type, _requiresBaseFunc, reader[\"requiresBaseFunc\"]);\n\tmod->loadBaseFunction(_type, _provideBaseFunc, reader[\"provideBaseFunc\"]);\n\tmod->loadBaseFunction(_type, _forbiddenBaseFunc, reader[\"forbiddenBaseFunc\"]);\n\n\tmod->loadSpriteOffset(_type, _spriteShape, reader[\"spriteShape\"], \"BASEBITS.PCK\");\n\tmod->loadSpriteOffset(_type, _spriteFacility, reader[\"spriteFacility\"], \"BASEBITS.PCK\");\n\n\treader.tryRead(\"connectorsDisabled\", _connectorsDisabled);\n\treader.tryRead(\"fakeUnderwater\", _fakeUnderwater);\n\treader.tryRead(\"missileAttraction\", _missileAttraction);\n\treader.tryRead(\"lift\", _lift);\n\treader.tryRead(\"hyper\", _hyper);\n\treader.tryRead(\"mind\", _mind);\n\treader.tryRead(\"grav\", _grav);\n\treader.tryRead(\"mindPower\", _mindPower);\n\tif (reader[\"size\"])\n\t{\n\t\t// backwards-compatibility\n\t\treader.tryRead(\"size\", _sizeX);\n\t\treader.tryRead(\"size\", _sizeY);\n\t}\n\treader.tryRead(\"sizeX\", _sizeX);\n\treader.tryRead(\"sizeY\", _sizeY);\n\treader.tryRead(\"buildCost\", _buildCost);\n\treader.tryRead(\"refundValue\", _refundValue);\n\treader.tryRead(\"buildTime\", _buildTime);\n\treader.tryRead(\"monthlyCost\", _monthlyCost);\n\treader.tryRead(\"storage\", _storage);\n\treader.tryRead(\"personnel\", _personnel);\n\treader.tryRead(\"aliens\", _aliens);\n\treader.tryRead(\"crafts\", _crafts);\n\treader.tryRead(\"labs\", _labs);\n\treader.tryRead(\"workshops\", _workshops);\n\treader.tryRead(\"psiLabs\", _psiLabs);\n\n\treader.tryRead(\"spriteEnabled\", _spriteEnabled);\n\n\treader.tryRead(\"sightRange\", _sightRange);\n\treader.tryRead(\"sightChance\", _sightChance);\n\treader.tryRead(\"radarRange\", _radarRange);\n\treader.tryRead(\"radarChance\", _radarChance);\n\treader.tryRead(\"defense\", _defense);\n\treader.tryRead(\"hitRatio\", _hitRatio);\n\n\tmod->loadSoundOffset(_type, _fireSound, reader[\"fireSound\"], \"GEO.CAT\");\n\tmod->loadSoundOffset(_type, _hitSound, reader[\"hitSound\"], \"GEO.CAT\");\n\tmod->loadSoundOffset(_type, _placeSound, reader[\"placeSound\"], \"GEO.CAT\");\n\n\treader.tryRead(\"ammoMax\", _ammoMax);\n\treader.tryRead(\"rearmRate\", _rearmRate);\n\treader.tryRead(\"ammoNeeded\", _ammoNeeded);\n\treader.tryRead(\"unifiedDamageFormula\", _unifiedDamageFormula);\n\treader.tryRead(\"shieldDamageModifier\", _shieldDamageModifier);\n\treader.tryRead(\"ammoItem\", _ammoItemName);\n\treader.tryRead(\"mapName\", _mapName);\n\treader.tryRead(\"listOrder\", _listOrder);\n\treader.tryRead(\"trainingRooms\", _trainingRooms);\n\treader.tryRead(\"maxAllowedPerBase\", _maxAllowedPerBase);\n\treader.tryRead(\"manaRecoveryPerDay\", _manaRecoveryPerDay);\n\treader.tryRead(\"healthRecoveryPerDay\", _healthRecoveryPerDay);\n\treader.tryRead(\"sickBayAbsoluteBonus\", _sickBayAbsoluteBonus);\n\treader.tryRead(\"sickBayRelativeBonus\", _sickBayRelativeBonus);\n\treader.tryRead(\"prisonType\", _prisonType);\n\treader.tryRead(\"rightClickActionType\", _rightClickActionType);\n\n\tif (const auto& items = reader[\"buildCostItems\"])\n\t{\n\t\tfor (const auto& buildCostReader : items.children())\n\t\t{\n\t\t\tstd::string id = buildCostReader.readKey<std::string>();\n\t\t\tstd::pair<int, int> &cost = _buildCostItems[id];\n\n\t\t\tbuildCostReader.tryRead(\"build\", cost.first);\n\t\t\tbuildCostReader.tryRead(\"refund\", cost.second);\n\n\t\t\tif (cost.first <= 0 && cost.second <= 0)\n\t\t\t{\n\t\t\t\t_buildCostItems.erase(id);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Load any VerticalLevels into a map if we have them\n\tif (reader[\"verticalLevels\"])\n\t{\n\t\t_verticalLevels.clear();\n\t\tfor (const auto& levelReader : reader[\"verticalLevels\"].children())\n\t\t{\n\t\t\tif (levelReader[\"type\"])\n\t\t\t{\n\t\t\t\tVerticalLevel level;\n\t\t\t\tlevel.load(levelReader);\n\t\t\t\t_verticalLevels.push_back(level);\n\t\t\t}\n\t\t}\n\t}\n\n\tmod->loadNames(_type, _leavesBehindOnSellNames, reader[\"leavesBehindOnSell\"]);\n\treader.tryRead(\"removalTime\", _removalTime);\n\treader.tryRead(\"canBeBuiltOver\", _canBeBuiltOver);\n\treader.tryRead(\"upgradeOnly\", _upgradeOnly);\n\tmod->loadUnorderedNames(_type, _buildOverFacilitiesNames, reader[\"buildOverFacilities\"]);\n\tstd::sort(_buildOverFacilities.begin(), _buildOverFacilities.end());\n\n\treader.tryRead(\"storageTiles\", _storageTiles);\n\treader.tryRead(\"destroyedFacility\", _destroyedFacilityName);\n}\n\n/**\n * Cross link with other Rules.\n */\nvoid RuleBaseFacility::afterLoad(const Mod* mod)\n{\n\tmod->verifySpriteOffset(_type, _spriteShape, \"BASEBITS.PCK\");\n\tmod->verifySpriteOffset(_type, _spriteFacility, \"BASEBITS.PCK\");\n\tmod->verifySoundOffset(_type, _fireSound, \"GEO.CAT\");\n\tmod->verifySoundOffset(_type, _hitSound, \"GEO.CAT\");\n\tmod->verifySoundOffset(_type, _placeSound, \"GEO.CAT\");\n\n\tmod->linkRule(_ammoItem, _ammoItemName);\n\n\tif (_unifiedDamageFormula && !_ammoItem)\n\t{\n\t\tthrow Exception(\"Unified damage formula requires `ammoItem` to be defined.\");\n\t}\n\n\tif (!_destroyedFacilityName.empty())\n\t{\n\t\tmod->linkRule(_destroyedFacility, _destroyedFacilityName);\n\t\tif (_destroyedFacility->getSizeX() != _sizeX || _destroyedFacility->getSizeY() != _sizeY)\n\t\t{\n\t\t\tthrow Exception(\"Destroyed version of a facility must have the same size as the original facility.\");\n\t\t}\n\t}\n\tif (_leavesBehindOnSellNames.size())\n\t{\n\t\t_leavesBehindOnSell.reserve(_leavesBehindOnSellNames.size());\n\t\tauto* first = mod->getBaseFacility(_leavesBehindOnSellNames.at(0), true);\n\t\tif (first->getSizeX() == _sizeX && first->getSizeY() == _sizeY)\n\t\t{\n\t\t\tif (_leavesBehindOnSellNames.size() != 1)\n\t\t\t{\n\t\t\t\tthrow Exception(\"Only one replacement facility allowed (when using the same size as the original facility).\");\n\t\t\t}\n\t\t\t_leavesBehindOnSell.push_back(first);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tfor (const auto& n : _leavesBehindOnSellNames)\n\t\t\t{\n\t\t\t\tauto* r = mod->getBaseFacility(n, true);\n\t\t\t\tif (!r->isSmall())\n\t\t\t\t{\n\t\t\t\t\tthrow Exception(\"All replacement facilities must have size=1 (when using different size as the original facility).\");\n\t\t\t\t}\n\t\t\t\t_leavesBehindOnSell.push_back(r);\n\t\t\t}\n\t\t}\n\t}\n\tif (_buildOverFacilitiesNames.size())\n\t{\n\t\tmod->linkRule(_buildOverFacilities, _buildOverFacilitiesNames);\n\t\tCollections::sortVector(_buildOverFacilities);\n\t}\n\tif (_mapName.empty())\n\t{\n\t\tthrow Exception(\"Battlescape map name is missing.\");\n\t}\n\tif (_storageTiles.size() > 0)\n\t{\n\t\tif (_storageTiles.size() != 1 || _storageTiles[0] != TileEngine::invalid)\n\t\t{\n\t\t\tconst int sizeX = 10 * _sizeX;\n\t\t\tconst int sizeY = 10 * _sizeY;\n\t\t\tfor (const auto& p : _storageTiles)\n\t\t\t{\n\t\t\t\tif (p.x < 0 || p.x > sizeX ||\n\t\t\t\t\tp.y < 0 || p.y > sizeY ||\n\t\t\t\t\tp.z < 0 || p.z > 8) // accurate max z will be check during map creation when we know map heigth, now we only check for very bad values.\n\t\t\t\t{\n\t\t\t\t\tif (p == TileEngine::invalid)\n\t\t\t\t\t{\n\t\t\t\t\t\tthrow Exception(\"Invalid tile position (-1, -1, -1) can be only one in storage position list.\");\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tthrow Exception(\"Tile position (\" + std::to_string(p.x) + \", \" + std::to_string(p.y)+ \", \" + std::to_string(p.z) + \") is outside the facility area.\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tCollections::removeAll(_leavesBehindOnSellNames);\n}\n\n/**\n * Gets the custom name of the Ufopedia article related to this facility.\n * @return The ufopedia article name.\n */\nconst std::string& RuleBaseFacility::getUfopediaType() const\n{\n\tif (!_ufopediaType.empty())\n\t\treturn _ufopediaType;\n\n\treturn _type;\n}\n\n/**\n * Gets the language string that names\n * this base facility. Each base facility type\n * has a unique name.\n * @return The facility's name.\n */\nconst std::string& RuleBaseFacility::getType() const\n{\n\treturn _type;\n}\n\n/**\n * Gets the list of research required to\n * build this base facility.\n * @return A list of research IDs.\n */\nconst std::vector<std::string> &RuleBaseFacility::getRequirements() const\n{\n\treturn _requires;\n}\n\n/**\n * Gets the ID of the sprite used to draw the\n * base structure of the facility that defines its shape.\n * @return The sprite ID.\n */\nint RuleBaseFacility::getSpriteShape() const\n{\n\treturn _spriteShape;\n}\n\n/**\n * Gets the ID of the sprite used to draw the\n * facility's contents inside the base shape.\n * @return The sprite ID.\n */\nint RuleBaseFacility::getSpriteFacility() const\n{\n\treturn _spriteFacility;\n}\n\n/**\n * Gets if the facility's size is 1x1.\n * @return True if facility size is 1x1.\n */\nbool RuleBaseFacility::isSmall() const\n{\n\treturn _sizeX == 1 && _sizeY == 1;\n}\n\n/**\n * Is sprite over shape behavior retained for bigger facility?\n * @return True if retained.\n */\nbool RuleBaseFacility::getSpriteEnabled() const\n{\n\treturn isSmall() || _spriteEnabled;\n}\n\n/**\n * Is this facility allowed for a given type of base?\n * @return True if allowed.\n */\nbool RuleBaseFacility::isAllowedForBaseType(bool fakeUnderwaterBase) const\n{\n\tif (_fakeUnderwater == -1)\n\t\treturn true;\n\telse if (_fakeUnderwater == 0 && !fakeUnderwaterBase)\n\t\treturn true;\n\telse if (_fakeUnderwater == 1 && fakeUnderwaterBase)\n\t\treturn true;\n\n\treturn false;\n}\n\n/**\n * Checks if this facility is the core access lift\n * of a base. Every base has an access lift and all\n * facilities have to be connected to it.\n * @return True if it's a lift.\n */\nbool RuleBaseFacility::isLift() const\n{\n\treturn _lift;\n}\n\n/**\n * Checks if this facility has hyperwave detection\n * capabilities. This allows it to get extra details about UFOs.\n * @return True if it has hyperwave detection.\n */\nbool RuleBaseFacility::isHyperwave() const\n{\n\treturn _hyper;\n}\n\n/**\n * Checks if this facility has a mind shield,\n * which covers your base from alien detection.\n * @return True if it has a mind shield.\n */\nbool RuleBaseFacility::isMindShield() const\n{\n\treturn _mind;\n}\n\n/**\n * Gets the mind shield power.\n * @return Mind shield power.\n */\nint RuleBaseFacility::getMindShieldPower() const\n{\n\treturn _mindPower;\n}\n\n/**\n * Checks if this facility has a grav shield,\n * which doubles base defense's fire ratio.\n * @return True if it has a grav shield.\n */\nbool RuleBaseFacility::isGravShield() const\n{\n\treturn _grav;\n}\n\n/**\n * Gets the amount of funds that this facility costs\n * to build on a base.\n * @return The building cost.\n */\nint RuleBaseFacility::getBuildCost() const\n{\n\treturn _buildCost;\n}\n\n/**\n * Gets the amount that is refunded when the facility\n * is dismantled.\n * @return The refund value.\n */\nint RuleBaseFacility::getRefundValue() const\n{\n\treturn _refundValue;\n}\n\n/**\n * Gets the amount of items that this facility require to build on a base or amount of items returned after dismantling.\n * @return The building cost in items.\n */\nconst std::map<std::string, std::pair<int, int> >& RuleBaseFacility::getBuildCostItems() const\n{\n\treturn _buildCostItems;\n}\n\n/**\n * Gets the amount of time that this facility takes\n * to be constructed since placement.\n * @return The time in days.\n */\nint RuleBaseFacility::getBuildTime() const\n{\n\treturn _buildTime;\n}\n\n/**\n * Gets the amount of funds this facility costs monthly\n * to maintain once it's fully built.\n * @return The monthly cost.\n */\nint RuleBaseFacility::getMonthlyCost() const\n{\n\treturn _monthlyCost;\n}\n\n/**\n * Gets the amount of storage space this facility provides\n * for base equipment.\n * @return The storage space.\n */\nint RuleBaseFacility::getStorage() const\n{\n\treturn _storage;\n}\n\n/**\n * Gets the number of base personnel (soldiers, scientists,\n * engineers) this facility can contain.\n * @return The number of personnel.\n */\nint RuleBaseFacility::getPersonnel() const\n{\n\treturn _personnel;\n}\n\n/**\n * Gets the number of captured live aliens this facility\n * can contain.\n * @return The number of aliens.\n */\nint RuleBaseFacility::getAliens() const\n{\n\treturn _aliens;\n}\n\n/**\n * Gets the number of base craft this facility can contain.\n * @return The number of craft.\n */\nint RuleBaseFacility::getCrafts() const\n{\n\treturn _crafts;\n}\n\n/**\n * Gets the amount of laboratory space this facility provides\n * for research projects.\n * @return The laboratory space.\n */\nint RuleBaseFacility::getLaboratories() const\n{\n\treturn _labs;\n}\n\n/**\n * Gets the amount of workshop space this facility provides\n * for manufacturing projects.\n * @return The workshop space.\n */\nint RuleBaseFacility::getWorkshops() const\n{\n\treturn _workshops;\n}\n\n/**\n * Gets the number of soldiers this facility can contain\n * for monthly psi-training.\n * @return The number of soldiers.\n */\nint RuleBaseFacility::getPsiLaboratories() const\n{\n\treturn _psiLabs;\n}\n\n/**\n * Gets the radar range this facility provides for the\n * detection of UFOs.\n * @return The range in nautical miles.\n */\nint RuleBaseFacility::getRadarRange() const\n{\n\treturn _radarRange;\n}\n\n/**\n * Gets the chance of UFOs that come within the facility's\n * radar range being detected.\n * @return The chance as a percentage.\n */\nint RuleBaseFacility::getRadarChance() const\n{\n\treturn _radarChance;\n}\n\n/**\n * Gets the defense value of this facility's weaponry\n * against UFO invasions on the base.\n * @return The defense value.\n */\nint RuleBaseFacility::getDefenseValue() const\n{\n\treturn _defense;\n}\n\n/**\n * Gets the hit ratio of this facility's weaponry\n * against UFO invasions on the base.\n * @return The hit ratio as a percentage.\n */\nint RuleBaseFacility::getHitRatio() const\n{\n\treturn _hitRatio;\n}\n\n/**\n * Gets the battlescape map block name for this facility\n * to construct the base defense mission map.\n * @return The map name.\n */\nstd::string RuleBaseFacility::getMapName() const\n{\n\treturn _mapName;\n}\n\n/**\n * Gets the hit sound of this facility's weaponry.\n * @return The sound index number.\n */\nint RuleBaseFacility::getHitSound() const\n{\n\treturn _hitSound;\n}\n\n/**\n * Gets the fire sound of this facility's weaponry.\n * @return The sound index number.\n */\nint RuleBaseFacility::getFireSound() const\n{\n\treturn _fireSound;\n}\n\n/**\n * Gets the facility's list weight.\n * @return The list weight for this research item.\n */\nint RuleBaseFacility::getListOrder() const\n{\n\treturn _listOrder;\n}\n\n/**\n * Returns the amount of soldiers this facility can contain\n * for monthly training.\n * @return Amount of room.\n */\nint RuleBaseFacility::getTrainingFacilities() const\n{\n\treturn _trainingRooms;\n}\n\n/**\n* Gets the maximum allowed number of facilities per base.\n* @return The number of facilities.\n*/\nint RuleBaseFacility::getMaxAllowedPerBase() const\n{\n\treturn _maxAllowedPerBase;\n}\n\n/**\n* Gets the prison type.\n* @return 0=alien containment, 1=prison, 2=animal cages, etc.\n*/\nint RuleBaseFacility::getPrisonType() const\n{\n\treturn _prisonType;\n}\n\n/**\n* Gets the action type to perform on right click.\n* @return 0=default, 1 = prison, 2 = manufacture, 3 = research, 4 = training, 5 = psi training, 6 = soldiers, 7 = sell\n*/\nint RuleBaseFacility::getRightClickActionType() const\n{\n\treturn _rightClickActionType;\n}\n\n/*\n * Gets the vertical levels for a base facility map\n * @return the vector of VerticalLevels\n */\nconst std::vector<VerticalLevel> &RuleBaseFacility::getVerticalLevels() const\n{\n\treturn _verticalLevels;\n}\n\n/**\n * Gets how long facilities left behind when this one is sold should take to build\n * @return the number of days, -1 = from other facilities' rulesets, 0 = instant, > 0 is that many days\n */\nint RuleBaseFacility::getRemovalTime() const\n{\n\treturn _removalTime;\n}\n\n/**\n * Gets whether or not this facility can be built over\n * @return can we build over this?\n */\nbool RuleBaseFacility::getCanBeBuiltOver() const\n{\n\treturn _canBeBuiltOver;\n}\n\n/**\n * Check if a given facility `fac` can be replaced by this facility.\n */\nBasePlacementErrors RuleBaseFacility::getCanBuildOverOtherFacility(const RuleBaseFacility* fac) const\n{\n\tif (fac->getCanBeBuiltOver() == true)\n\t{\n\t\t// the old facility allows unrestricted build-over.\n\t\treturn BPE_None;\n\t}\n\telse if (_buildOverFacilities.empty())\n\t{\n\t\t// the old facility does not allow unrestricted build-over and we do not have any exception list\n\t\treturn BPE_UpgradeDisallowed;\n\t}\n\telse if (Collections::sortVectorHave(_buildOverFacilities, fac))\n\t{\n\t\t// the old facility is on the exception list\n\t\treturn BPE_None;\n\t}\n\telse\n\t{\n\t\t// we have an exception list, but this facility is not on it.\n\t\treturn BPE_UpgradeRequireSpecific;\n\t}\n}\n\n/**\n * Gets the list of tile positions where to place items in this facility's storage\n * If empty, vanilla checkerboard pattern will be used\n * @return the list of positions\n */\nconst std::vector<Position> &RuleBaseFacility::getStorageTiles() const\n{\n\treturn _storageTiles;\n}\n\n/*\n * Gets the ruleset for the destroyed version of this facility.\n * @return Facility ruleset or null.\n */\nconst RuleBaseFacility* RuleBaseFacility::getDestroyedFacility() const\n{\n\treturn _destroyedFacility;\n}\n\n}\n"
  },
  {
    "path": "src/Mod/RuleBaseFacility.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include <vector>\n#include <map>\n#include <bitset>\n#include \"../Engine/Yaml.h\"\n#include \"RuleBaseFacilityFunctions.h\"\n\nnamespace OpenXcom\n{\n\nclass Mod;\nclass Base;\nclass Position;\nclass RuleItem;\nstruct VerticalLevel;\nenum BasePlacementErrors : int;\n\n/**\n * Represents a specific type of base facility.\n * Contains constant info about a facility like\n * costs, capacities, size, etc.\n * @sa BaseFacility\n */\nclass RuleBaseFacility\n{\nprivate:\n\tstd::string _ufopediaType;\n\tstd::string _type;\n\tstd::vector<std::string> _requires;\n\tRuleBaseFacilityFunctions _requiresBaseFunc = 0;\n\tRuleBaseFacilityFunctions _provideBaseFunc = 0;\n\tRuleBaseFacilityFunctions _forbiddenBaseFunc = 0;\n\tint _spriteShape, _spriteFacility;\n\tbool _connectorsDisabled;\n\tint _missileAttraction;\n\tint _fakeUnderwater;\n\tbool _lift, _hyper, _mind, _grav;\n\tint _mindPower;\n\tint _sizeX, _sizeY;\n\tint _buildCost, _refundValue, _buildTime, _monthlyCost;\n\tstd::map<std::string, std::pair<int, int> > _buildCostItems;\n\tint _storage, _personnel, _aliens, _crafts, _labs, _workshops, _psiLabs;\n\tbool _spriteEnabled;\n\tint _sightRange, _sightChance;\n\tint _radarRange, _radarChance, _defense, _hitRatio, _fireSound, _hitSound, _placeSound;\n\tint _ammoMax, _rearmRate;\n\tint _ammoNeeded;\n\tbool _unifiedDamageFormula;\n\tint _shieldDamageModifier;\n\tconst RuleItem* _ammoItem = nullptr;\n\tstd::string _ammoItemName;\n\tstd::string _mapName;\n\tint _listOrder, _trainingRooms;\n\tint _maxAllowedPerBase;\n\tint _manaRecoveryPerDay = 0;\n\tint _healthRecoveryPerDay = 0;\n\tfloat _sickBayAbsoluteBonus, _sickBayRelativeBonus;\n\tint _prisonType;\n\tint _rightClickActionType;\n\tstd::vector<VerticalLevel> _verticalLevels;\n\tstd::vector<const RuleBaseFacility*> _leavesBehindOnSell;\n\tint _removalTime;\n\tbool _canBeBuiltOver;\n\tbool _upgradeOnly;\n\tstd::vector<const RuleBaseFacility*> _buildOverFacilities;\n\tstd::vector<Position> _storageTiles;\n\tstd::string _destroyedFacilityName;\n\tconst RuleBaseFacility* _destroyedFacility;\n\n\n\tstd::vector<std::string> _leavesBehindOnSellNames;\n\tstd::vector<std::string> _buildOverFacilitiesNames;\n\npublic:\n\t/// Creates a blank facility ruleset.\n\tRuleBaseFacility(const std::string &type, int listOrder);\n\t/// Cleans up the facility ruleset.\n\t~RuleBaseFacility();\n\t/// Loads the facility from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader, Mod *mod);\n\t/// Cross link with other rules.\n\tvoid afterLoad(const Mod* mod);\n\n\t/// Gets the custom name of the Ufopedia article related to this facility.\n\tconst std::string& getUfopediaType() const;\n\n\t/// Gets the facility's type.\n\tconst std::string& getType() const;\n\t/// Gets the facility's requirements.\n\tconst std::vector<std::string> &getRequirements() const;\n\t/// Gets the facility's required function in base to build.\n\tRuleBaseFacilityFunctions getRequireBaseFunc() const { return _requiresBaseFunc; }\n\t/// Gets the functions that facility provide in base.\n\tRuleBaseFacilityFunctions getProvidedBaseFunc() const { return _provideBaseFunc; }\n\t/// Gets the functions that facility prevent in base.\n\tRuleBaseFacilityFunctions getForbiddenBaseFunc() const { return _forbiddenBaseFunc; }\n\t/// Gets the facility's shape sprite.\n\tint getSpriteShape() const;\n\t/// Gets the facility's content sprite.\n\tint getSpriteFacility() const;\n\t/// Retain sprite over shape behavior for bigger facility?\n\tbool getSpriteEnabled() const;\n\tbool getSpriteEnabledRaw() const { return _spriteEnabled; }\n\t/// Should there be connectors leading to this facility?\n\tbool connectorsDisabled() const { return _connectorsDisabled; }\n\t/// Gets if the facility's size is 1x1.\n\tbool isSmall() const;\n\t/// Gets the facility's size.\n\tint getSizeX() const { return _sizeX; }\n\t/// Gets the facility's size.\n\tint getSizeY() const { return _sizeY; }\n\t/// Gets the facility's missile attraction.\n\tint getMissileAttraction() const { return _missileAttraction; }\n\t/// Is this facility allowed for a given type of base?\n\tbool isAllowedForBaseType(bool fakeUnderwaterBase) const;\n\tint getFakeUnderwaterRaw() const { return _fakeUnderwater; }\n\t/// Gets if the facility is an access lift.\n\tbool isLift() const;\n\t/// Gets if the facility has hyperwave detection.\n\tbool isHyperwave() const;\n\t/// Gets if the facility is a mind shield.\n\tbool isMindShield() const;\n\t/// Gets the mind shield power.\n\tint getMindShieldPower() const;\n\t/// Gets if the facility is a grav shield.\n\tbool isGravShield() const;\n\t/// Gets the facility's construction cost.\n\tint getBuildCost() const;\n\t/// Gets the facility's refund value.\n\tint getRefundValue() const;\n\t/// Gets the facility's construction cost in items, `first` is build cost, `second` is refund.\n\tconst std::map<std::string, std::pair<int, int> >& getBuildCostItems() const;\n\t/// Gets the facility's construction time.\n\tint getBuildTime() const;\n\t/// Gets the facility's monthly cost.\n\tint getMonthlyCost() const;\n\t/// Gets the facility's storage capacity.\n\tint getStorage() const;\n\t/// Gets the facility's personnel capacity.\n\tint getPersonnel() const;\n\t/// Gets the facility's alien capacity.\n\tint getAliens() const;\n\t/// Gets the facility's craft capacity.\n\tint getCrafts() const;\n\t/// Gets the facility's laboratory space.\n\tint getLaboratories() const;\n\t/// Gets the facility's workshop space.\n\tint getWorkshops() const;\n\t/// Gets the facility's psi-training capacity.\n\tint getPsiLaboratories() const;\n\t/// Gets the facility's sight range.\n\tint getSightRange() const { return _sightRange; }\n\t/// Gets the facility's alien base detection chance.\n\tint getSightChance() const { return _sightChance; }\n\t/// Gets the facility's radar range.\n\tint getRadarRange() const;\n\t/// Gets the facility's detection chance.\n\tint getRadarChance() const;\n\t/// Gets the facility's defense value.\n\tint getDefenseValue() const;\n\t/// Gets the facility's weapon hit ratio.\n\tint getHitRatio() const;\n\t/// Gets the facility's weapon ammo capacity.\n\tint getAmmoMax() const { return _ammoMax; }\n\t/// Gets the facility's weapon rearm rate.\n\tint getRearmRate() const { return _rearmRate; }\n\t/// Gets the facility's weapon ammo spent per shot.\n\tint getAmmoNeeded() const { return _ammoNeeded; }\n\t/// Should unified or vanilla formula be used?\n\tbool unifiedDamageFormula() const { return _unifiedDamageFormula; }\n\t/// Gets the facility's weapon effectiveness against shields.\n\tint getShieldDamageModifier() const { return _shieldDamageModifier; }\n\t/// Gets the facility's weapon ammo item.\n\tconst RuleItem* getAmmoItem() const { return _ammoItem; }\n\t/// Gets the facility's battlescape map name.\n\tstd::string getMapName() const;\n\t/// Gets the facility's fire sound.\n\tint getFireSound() const;\n\t/// Gets the facility's hit sound.\n\tint getHitSound() const;\n\t/// Gets the facility's place sound.\n\tint getPlaceSound() const { return _placeSound; }\n\t/// Gets the facility's list weight.\n\tint getListOrder() const;\n\t/// Gets the facility's training capacity.\n\tint getTrainingFacilities() const;\n\t/// Gets the maximum allowed number of facilities per base.\n\tint getMaxAllowedPerBase() const;\n\t/// Gets the facility's mana recovery rate.\n\tint getManaRecoveryPerDay() const { return _manaRecoveryPerDay; }\n\t/// Gets the facility's health recovery rate.\n\tint getHealthRecoveryPerDay() const { return _healthRecoveryPerDay; }\n\t/// Gets the facility's bonus to wound healing.\n\tfloat getSickBayAbsoluteBonus() const { return _sickBayAbsoluteBonus; }\n\t/// Gets the facility's bonus to wound healing (as percentage of max hp of the soldier).\n\tfloat getSickBayRelativeBonus() const { return _sickBayRelativeBonus; }\n\t/// Gets the prison type.\n\tint getPrisonType() const;\n\t/// Gets the action type to perform on right click.\n\tint getRightClickActionType() const;\n\t/// Gets the vertical levels for this facility map generation.\n\tconst std::vector<VerticalLevel> &getVerticalLevels() const;\n\t/// Gets the facility left behind when this one is sold\n\tconst std::vector<const RuleBaseFacility*> &getLeavesBehindOnSell() const { return _leavesBehindOnSell; }\n\t/// Gets how long facilities left behind when this one is sold should take to build\n\tint getRemovalTime() const;\n\t/// Gets whether or not this facility can be built over by other ones\n\tbool getCanBeBuiltOver() const;\n\t/// Gets whether or not this facility can ONLY be built over another facility (i.e. not standalone)\n\tbool isUpgradeOnly() const { return _upgradeOnly; }\n\t/// Check if a given facility `fac` can be replaced by this facility.\n\tBasePlacementErrors getCanBuildOverOtherFacility(const RuleBaseFacility* fac) const;\n\t/// Gets which facilities are allowed to be replaced by this building\n\tconst std::vector<const RuleBaseFacility*> &getBuildOverFacilities() const { return _buildOverFacilities; }\n\t/// Gets a list of which tiles are used to place items stored in this facility\n\tconst std::vector<Position> &getStorageTiles() const;\n\t/// Gets the ruleset for the destroyed version of this facility.\n\tconst RuleBaseFacility* getDestroyedFacility() const;\n};\n\n}\n"
  },
  {
    "path": "src/Mod/RuleBaseFacilityFunctions.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2020 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include <bitset>\n#include <SDL_stdinc.h>\n\nnamespace OpenXcom\n{\n\nclass Base;\ntemplate<typename Tag, typename DataType> struct AreaSubset;\n\n\n/**\n * Fixed collection of base functionalites\n */\nusing RuleBaseFacilityFunctions = std::bitset<128>;\n\n/**\n * Subset area of base.\n */\nusing BaseAreaSubset = AreaSubset<Base, Sint8>;\n\n}"
  },
  {
    "path": "src/Mod/RuleCommendations.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"RuleCommendations.h\"\n#include \"Mod.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Creates a blank set of commendation data.\n */\nRuleCommendations::RuleCommendations(const std::string& type) : _type(type), _criteria(), _killCriteria(), _description(\"\"), _sprite(), _soldierBonusTypes()\n{\n}\n\n/**\n * Cleans up the commendation.\n */\nRuleCommendations::~RuleCommendations()\n{\n}\n\n/**\n * Loads the commendations from YAML.\n * @param node YAML node.\n */\nvoid RuleCommendations::load(const YAML::YamlNodeReader& reader, const Mod* mod)\n{\n\tif (const auto& parent = reader[\"refNode\"])\n\t{\n\t\tload(parent, mod);\n\t}\n\n\treader.tryRead(\"description\", _description);\n\tmod->loadUnorderedNamesToInts(_type, _criteria, reader[\"criteria\"]);\n\treader.tryRead(\"sprite\", _sprite);\n\tmod->loadKillCriteria(_type, _killCriteria, reader[\"killCriteria\"]);\n\tmod->loadNames(_type, _soldierBonusTypesNames, reader[\"soldierBonusTypes\"]);\n\tmod->loadNames(_type, _missionMarkerNames, reader[\"missionMarkerFilter\"]);\n\tmod->loadNames(_type, _missionTypeNames, reader[\"missionTypeFilter\"]);\n\n\tmod->loadUnorderedNames(_type, _requiresNames, reader[\"requires\"]);\n\tmod->loadUnorderedNames(_type, _unitsNames, reader[\"units\"]);\n}\n\n/**\n * Cross link with other rules.\n */\nvoid RuleCommendations::afterLoad(const Mod* mod)\n{\n\tmod->linkRule(_soldierBonusTypes, _soldierBonusTypesNames);\n\n\tmod->linkRule(_requires, _requiresNames);\n\tmod->linkRule(_units, _unitsNames);\n\n\tCollections::sortVector(_units);\n}\n\n/**\n * Get the commendation's description.\n * @return string Commendation description.\n */\nconst std::string& RuleCommendations::getDescription() const\n{\n\treturn _description;\n}\n\n/**\n * Get the commendation's award criteria.\n * @return map<string, int> Commendation criteria.\n */\nconst std::map<std::string, std::vector<int> > *RuleCommendations::getCriteria() const\n{\n\treturn &_criteria;\n}\n\n/**\n * Get the commendation's award kill criteria.\n * @return vector<string> Commendation kill criteria.\n */\nconst std::vector<std::vector<std::pair<int, std::vector<std::string> > > > *RuleCommendations::getKillCriteria() const\n{\n\treturn &_killCriteria;\n}\n\n/**\n * Get the commendation's sprite.\n * @return int Sprite number.\n */\nint RuleCommendations::getSprite() const\n{\n\treturn _sprite;\n}\n\n/**\n * Gets the soldier bonus type corresponding to the commendation's decoration level.\n * @return Soldier bonus type.\n */\nconst RuleSoldierBonus *RuleCommendations::getSoldierBonus(int decorationLevel) const\n{\n\tif (!_soldierBonusTypes.empty())\n\t{\n\t\tint lastIndex = (int)(_soldierBonusTypes.size()) - 1;\n\t\tint index = decorationLevel > lastIndex ? lastIndex : decorationLevel;\n\t\treturn _soldierBonusTypes.at(index);\n\t}\n\treturn nullptr;\n}\n\n/**\n * Gets the commendation's mission marker filter.\n * @return vector<string> Mission marker types.\n */\nconst std::vector<std::string>& RuleCommendations::getMissionMarkerNames() const\n{\n\treturn _missionMarkerNames;\n}\n\n/**\n * Gets the commendation's mission type filter.\n * @return vector<string> Mission types.\n */\nconst std::vector<std::string>& RuleCommendations::getMissionTypeNames() const\n{\n\treturn _missionTypeNames;\n}\n\n/**\n * Check if a given soldier type can be awarded this commendation.\n */\nbool RuleCommendations::isSupportedBy(const RuleSoldier* soldier) const\n{\n\treturn _units.empty() || Collections::sortVectorHave(_units, soldier);\n}\n\n}\n"
  },
  {
    "path": "src/Mod/RuleCommendations.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/Yaml.h\"\n\nnamespace OpenXcom\n{\n\nclass Mod;\nclass RuleSoldierBonus;\nclass RuleResearch;\nclass RuleSoldier;\n\n/**\n * Represents a specific type of commendation.\n * Contains constant info about a commendation like\n * award criteria, sprite, description, etc.\n * @sa Commendation\n */\nclass RuleCommendations\n{\nprivate:\n\tstd::string _type;\n\tstd::map<std::string, std::vector<int> > _criteria;\n\tstd::vector<std::vector<std::pair<int, std::vector<std::string> > > > _killCriteria;\n\tstd::string _description;\n\tint _sprite;\n\tstd::vector<std::string> _soldierBonusTypesNames;\n\tstd::vector<const RuleSoldierBonus*> _soldierBonusTypes;\n\tstd::vector<std::string> _missionMarkerNames; // these are not alien deployment type names!\n\tstd::vector<std::string> _missionTypeNames;   // these are not alien deployment type names!\n\n\tstd::vector<std::string> _requiresNames;\n\tstd::vector<const RuleResearch*> _requires;\n\tstd::vector<std::string> _unitsNames;\n\tstd::vector<const RuleSoldier*> _units;\n\npublic:\n\t/// Creates a blank commendation ruleset.\n\tRuleCommendations(const std::string& type);\n\t/// Cleans up the commendation ruleset.\n\t~RuleCommendations();\n\t/// Loads commendation data from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader, const Mod* mod);\n\t/// Cross link with other rules.\n\tvoid afterLoad(const Mod* mod);\n\n\t/// Gets the commendation's type.\n\tconst std::string& getType() const { return _type; }\n\t/// Get the commendation's description.\n\tconst std::string& getDescription() const;\n\t/// Get the commendation's award criteria.\n\tconst std::map<std::string, std::vector<int> > *getCriteria() const;\n\t/// Get the commendation's award kill related criteria.\n\tconst std::vector<std::vector<std::pair<int, std::vector<std::string> > > > *getKillCriteria() const;\n\t/// Get the commendation's sprite.\n\tint getSprite() const;\n\t/// Gets the soldier bonus type corresponding to the commendation's decoration level.\n\tconst RuleSoldierBonus *getSoldierBonus(int decorationLevel) const;\n\t/// Gets the commendation's mission marker filter.\n\tconst std::vector<std::string>& getMissionMarkerNames() const;\n\t/// Gets the commendation's mission type filter.\n\tconst std::vector<std::string>& getMissionTypeNames() const;\n\n\t/// Gets the commendation's research requirements.\n\tconst std::vector<const RuleResearch*>& getRequires() const { return _requires; }\n\t/// Check if a given soldier type can be awarded this commendation.\n\tbool isSupportedBy(const RuleSoldier* soldier) const;\n\n};\n\n}\n"
  },
  {
    "path": "src/Mod/RuleConverter.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"RuleConverter.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Creates a blank ruleset for converter data.\n */\nRuleConverter::RuleConverter()\n{\n}\n\n/**\n *\n */\nRuleConverter::~RuleConverter()\n{\n}\n\n/**\n * Loads the converter data from a YAML file.\n * @param node YAML node.\n */\nvoid RuleConverter::load(const YAML::YamlNodeReader& node)\n{\n\tconst auto reader = node.useIndex();\n\treader.tryRead(\"offsets\", _offsets);\n\treader.tryRead(\"markers\", _markers);\n\treader.tryRead(\"countries\", _countries);\n\treader.tryRead(\"regions\", _regions);\n\treader.tryRead(\"facilities\", _facilities);\n\treader.tryRead(\"items\", _items);\n\treader.tryRead(\"crews\", _crews);\n\treader.tryRead(\"crafts\", _crafts);\n\treader.tryRead(\"ufos\", _ufos);\n\treader.tryRead(\"craftWeapons\", _craftWeapons);\n\treader.tryRead(\"missions\", _missions);\n\treader.tryRead(\"armor\", _armor);\n\treader.tryRead(\"alienRaces\", _alienRaces);\n\treader.tryRead(\"alienRanks\", _alienRanks);\n\treader.tryRead(\"research\", _research);\n\treader.tryRead(\"manufacture\", _manufacture);\n\treader.tryRead(\"ufopaedia\", _ufopaedia);\n}\n\n}\n"
  },
  {
    "path": "src/Mod/RuleConverter.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <map>\n#include <vector>\n#include <string>\n#include \"../Engine/Yaml.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Represents game-specific contents needed\n * for save conversion and ID matching.\n * @sa SaveConverter\n */\nclass RuleConverter\n{\nprivate:\n\tstd::map<std::string, int> _offsets;\n\tstd::vector<std::string> _markers, _countries, _regions, _facilities, _items, _crews, _crafts, _ufos, _craftWeapons, _missions, _armor, _alienRaces, _alienRanks, _research, _manufacture, _ufopaedia;\npublic:\n\t/// Creates a blank converter ruleset.\n\tRuleConverter();\n\t/// Cleans up the converter ruleset.\n\t~RuleConverter();\n\t/// Loads the converter from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader);\n\t/// Gets the offset for a specific attribute.\n\tint getOffset(const std::string &id) { return _offsets[id]; }\n\t/// Gets the marker ID list.\n\tconst std::vector<std::string> &getMarkers() const { return _markers; }\n\t/// Gets the country ID list.\n\tconst std::vector<std::string> &getCountries() const { return _countries; }\n\t/// Gets the region ID list.\n\tconst std::vector<std::string> &getRegions() const { return _regions; }\n\t/// Gets the facility ID list.\n\tconst std::vector<std::string> &getFacilities() const { return _facilities; }\n\t/// Gets the item ID list.\n\tconst std::vector<std::string> &getItems() const { return _items; }\n\t/// Gets the UFO crew ID list.\n\tconst std::vector<std::string> &getCrews() const { return _crews; }\n\t/// Gets the craft ID list.\n\tconst std::vector<std::string> &getCrafts() const { return _crafts; }\n\t/// Gets the UFO ID list.\n\tconst std::vector<std::string> &getUfos() const { return _ufos; }\n\t/// Gets the craft weapon ID list.\n\tconst std::vector<std::string> &getCraftWeapons() const { return _craftWeapons; }\n\t/// Gets the alien mission ID list.\n\tconst std::vector<std::string> &getMissions() const { return _missions; }\n\t/// Gets the armor ID list.\n\tconst std::vector<std::string> &getArmor() const { return _armor; }\n\t/// Gets the alien race ID list.\n\tconst std::vector<std::string> &getAlienRaces() const { return _alienRaces; }\n\t/// Gets the alien rank ID list.\n\tconst std::vector<std::string> &getAlienRanks() const { return _alienRanks; }\n\t/// Gets the research ID list.\n\tconst std::vector<std::string> &getResearch() const { return _research; }\n\t/// Gets the manufacture ID list.\n\tconst std::vector<std::string> &getManufacture() const { return _manufacture; }\n\t/// Gets the ufopaedia ID list.\n\tconst std::vector<std::string> &getUfopaedia() const { return _ufopaedia; }\n};\n\n}\n"
  },
  {
    "path": "src/Mod/RuleCountry.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"RuleCountry.h\"\n#include \"Mod.h\"\n#include \"../Engine/RNG.h\"\n#include \"../Engine/ScriptBind.h\"\n#include \"../fmath.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Creates a blank ruleset for a certain\n * type of country.\n * @param type String defining the type.\n */\nRuleCountry::RuleCountry(const std::string &type) : _type(type), _fundingBase(0), _fundingCap(0), _labelLon(0.0), _labelLat(0.0), _labelColor(0), _zoomLevel(0)\n{\n}\n\n/**\n *\n */\nRuleCountry::~RuleCountry()\n{\n}\n\n/**\n * Loads the country type from a YAML file.\n * @param node YAML node.\n */\nvoid RuleCountry::load(const YAML::YamlNodeReader& reader, const ModScript& parsers, Mod* mod)\n{\n\tif (const auto& parent = reader[\"refNode\"])\n\t{\n\t\tload(parent, parsers, mod);\n\t}\n\n\treader.tryRead(\"signedPactEvent\", _signedPactEventName);\n\treader.tryRead(\"rejoinedXcomEvent\", _rejoinedXcomEventName);\n\treader.tryRead(\"fundingBase\", _fundingBase);\n\treader.tryRead(\"fundingCap\", _fundingCap);\n\tif (reader[\"labelLon\"])\n\t\t_labelLon = Deg2Rad(reader[\"labelLon\"].readVal<double>());\n\tif (reader[\"labelLat\"])\n\t\t_labelLat = Deg2Rad(reader[\"labelLat\"].readVal<double>());\n\treader.tryRead(\"labelColor\", _labelColor);\n\treader.tryRead(\"zoomLevel\", _zoomLevel);\n\tstd::vector< std::vector<double> > areas;\n\treader.tryRead(\"areas\", areas);\n\tfor (size_t i = 0; i != areas.size(); ++i)\n\t{\n\t\t_lonMin.push_back(Deg2Rad(areas[i][0]));\n\t\t_lonMax.push_back(Deg2Rad(areas[i][1]));\n\t\t_latMin.push_back(Deg2Rad(areas[i][2]));\n\t\t_latMax.push_back(Deg2Rad(areas[i][3]));\n\n\t\tif (_latMin.back() > _latMax.back())\n\t\t\tstd::swap(_latMin.back(), _latMax.back());\n\t}\n\n\tmod->loadBaseFunction(_type, _provideBaseFunc, reader[\"provideBaseFunc\"]);\n\tmod->loadBaseFunction(_type, _forbiddenBaseFunc, reader[\"forbiddenBaseFunc\"]);\n\n\t_countryScripts.load(_type, reader, parsers.countryScripts);\n\t_scriptValues.load(reader, parsers.getShared());\n}\n\n/**\n * Cross link with other rules.\n */\nvoid RuleCountry::afterLoad(const Mod* mod)\n{\n\tmod->linkRule(_signedPactEvent, _signedPactEventName);\n\tmod->linkRule(_rejoinedXcomEvent, _rejoinedXcomEventName);\n}\n\n/**\n * Gets the language string that names\n * this country. Each country type\n * has a unique name.\n * @return The country's name.\n */\nconst std::string& RuleCountry::getType() const\n{\n\treturn _type;\n}\n\n/**\n * Generates the random starting funding for the country.\n * @return The monthly funding.\n */\nint RuleCountry::generateFunding() const\n{\n\treturn RNG::generate(_fundingBase, _fundingBase*2) * 1000;\n}\n\n/**\n * Gets the country's funding cap.\n * Country funding can never exceed this.\n * @return The funding cap, in thousands.\n */\nint RuleCountry::getFundingCap() const\n{\n\treturn _fundingCap;\n}\n\n/**\n * Gets the longitude of the country's label on the globe.\n * @return The longitude in radians.\n */\ndouble RuleCountry::getLabelLongitude() const\n{\n\treturn _labelLon;\n}\n\n/**\n * Gets the latitude of the country's label on the globe.\n * @return The latitude in radians.\n */\ndouble RuleCountry::getLabelLatitude() const\n{\n\treturn _labelLat;\n}\n\n/**\n * Checks if a point is inside this country.\n * @param lon Longitude in radians.\n * @param lat Latitude in radians.\n * @return True if it's inside, false if it's outside.\n */\nbool RuleCountry::insideCountry(double lon, double lat) const\n{\n\tfor (size_t i = 0; i < _lonMin.size(); ++i)\n\t{\n\t\tbool inLon, inLat;\n\n\t\tif (_lonMin[i] <= _lonMax[i])\n\t\t\tinLon = (lon >= _lonMin[i] && lon < _lonMax[i]);\n\t\telse\n\t\t\tinLon = ((lon >= _lonMin[i] && lon < M_PI*2.0) || (lon >= 0 && lon < _lonMax[i]));\n\n\t\tif (lat > 0) // make that both poles could be in some regions, this means `M_PI == _latMax[i]` or `-M_PI == _latMin[i]`\n\t\t\tinLat = (lat > _latMin[i] && lat <= _latMax[i]);\n\t\telse\n\t\t\tinLat = (lat >= _latMin[i] && lat < _latMax[i]);\n\n\t\tif (inLon && inLat)\n\t\t\treturn true;\n\t}\n\treturn false;\n}\n\n/**\n * Gets the country's label color.\n * @return The color code.\n */\nint RuleCountry::getLabelColor() const\n{\n\treturn _labelColor;\n}\n\n/**\n * Gets the minimum zoom level required to display the label.\n * Note: this works for extraGlobeLabels only, not for vanilla countries.\n * @return The zoom level.\n */\nint RuleCountry::getZoomLevel() const\n{\n\treturn _zoomLevel;\n}\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tScript binding\n////////////////////////////////////////////////////////////\n\nnamespace\n{\n\nstd::string debugDisplayScript(const RuleCountry* rc)\n{\n\tif (rc)\n\t{\n\t\tstd::string s;\n\t\ts += RuleCountry::ScriptName;\n\t\ts += \"(name: \\\"\";\n\t\ts += rc->getType();\n\t\ts += \"\\\")\";\n\t\treturn s;\n\t}\n\telse\n\t{\n\t\treturn \"null\";\n\t}\n}\n\n} // namespace\n\n/**\n * Register RuleCountry in script parser.\n * @param parser Script parser.\n */\nvoid RuleCountry::ScriptRegister(ScriptParserBase* parser)\n{\n\tBind<RuleCountry> rcb = { parser };\n\n\trcb.add<&RuleCountry::getFundingCap>(\"getFundingCap\", \"Gets the predefined max funding cap for this country.\");\n\n\trcb.addScriptValue<BindBase::OnlyGet, &RuleCountry::_scriptValues>();\n\trcb.addDebugDisplay<&debugDisplayScript>();\n}\n\n}\n"
  },
  {
    "path": "src/Mod/RuleCountry.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include \"../Engine/Yaml.h\"\n#include \"RuleEvent.h\"\n#include \"ModScript.h\"\n#include \"RuleBaseFacilityFunctions.h\"\n\nnamespace OpenXcom\n{\n\nclass Mod;\n\n/**\n * Represents a specific funding country.\n * Contains constant info like its location in the\n * world and starting funding range.\n */\nclass RuleCountry\n{\nprivate:\n\tstd::string _type;\n\tstd::string _signedPactEventName, _rejoinedXcomEventName;\n\tint _fundingBase, _fundingCap;\n\tdouble _labelLon, _labelLat;\n\tstd::vector<double> _lonMin, _lonMax, _latMin, _latMax;\n\tint _labelColor, _zoomLevel;\n\tconst RuleEvent* _signedPactEvent = nullptr;\n\tconst RuleEvent* _rejoinedXcomEvent = nullptr;\n\tRuleBaseFacilityFunctions _provideBaseFunc = 0;\n\tRuleBaseFacilityFunctions _forbiddenBaseFunc = 0;\n\n\tModScript::CountryScripts::Container _countryScripts;\n\tScriptValues<RuleCountry> _scriptValues;\npublic:\n\t/// Name of class used in script.\n\tstatic constexpr const char* ScriptName = \"RuleCountry\";\n\t/// Register all useful function used by script.\n\tstatic void ScriptRegister(ScriptParserBase* parser);\n\n\t/// Creates a blank country ruleset.\n\tRuleCountry(const std::string &type);\n\t/// Cleans up the country ruleset.\n\t~RuleCountry();\n\t/// Loads the country from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader, const ModScript& parsers, Mod* mod);\n\t/// Cross link with other rules.\n\tvoid afterLoad(const Mod* mod);\n\t/// Gets the country's type.\n\tconst std::string& getType() const;\n\t/// Gets the event triggered after the country leaves Xcom.\n\tconst RuleEvent* getSignedPactEvent() const { return _signedPactEvent; }\n\t/// Gets the event triggered after the country rejoins Xcom.\n\tconst RuleEvent* getRejoinedXcomEvent() const { return _rejoinedXcomEvent; }\n\t/// Generates the country's starting funding.\n\tint generateFunding() const;\n\t/// Gets the country's funding cap.\n\tint getFundingCap() const;\n\t/// Gets the country's label X position.\n\tdouble getLabelLongitude() const;\n\t/// Gets the country's label Y position.\n\tdouble getLabelLatitude() const;\n\t/// Checks if a point is inside the country.\n\tbool insideCountry(double lon, double lat) const;\n\tconst std::vector<double> &getLonMax() const { return _lonMax; }\n\tconst std::vector<double> &getLonMin() const { return _lonMin; }\n\tconst std::vector<double> &getLatMax() const { return _latMax; }\n\tconst std::vector<double> &getLatMin() const { return _latMin; }\n\t/// Gets the country's label color.\n\tint getLabelColor() const;\n\t/// Gets the minimum zoom level required to display the label (Note: works for extraGlobeLabels only, not for vanilla countries).\n\tint getZoomLevel() const;\n\t/// Gets the functions provided by the country.\n\tRuleBaseFacilityFunctions getProvidedBaseFunc() const { return _provideBaseFunc; }\n\t/// Gets the functions forbidden by the coutry.\n\tRuleBaseFacilityFunctions getForbiddenBaseFunc() const { return _forbiddenBaseFunc; }\n\n\t/// Gets script.\n\ttemplate<typename Script>\n\tconst typename Script::Container& getScript() const { return _countryScripts.get<Script>(); }\n};\n\n}\n"
  },
  {
    "path": "src/Mod/RuleCraft.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"RuleCraft.h\"\n#include \"RuleTerrain.h\"\n#include \"../Engine/Exception.h\"\n#include \"../Engine/RNG.h\"\n#include \"../Engine/ScriptBind.h\"\n#include \"Mod.h\"\n\nnamespace OpenXcom\n{\n\nconst std::string RuleCraft::DEFAULT_CRAFT_DEPLOYMENT_PREVIEW = \"STR_CRAFT_DEPLOYMENT_PREVIEW\";\n\n/**\n * Creates a blank ruleset for a certain\n * type of craft.\n * @param type String defining the type.\n */\nRuleCraft::RuleCraft(const std::string &type, int listOrder) :\n\t_type(type), _sprite(-1), _marker(-1), _weapons(0), _maxUnitsLimit(-1), _pilots(0), _maxVehiclesAndLargeSoldiersLimit(-1),\n\t_maxSmallSoldiers(-1), _maxLargeSoldiers(-1), _maxSmallVehicles(-1), _maxLargeVehicles(-1),\n\t_maxSmallUnits(-1), _maxLargeUnits(-1), _maxSoldiers(-1), _maxVehicles(-1),\n\t_monthlyBuyLimit(0), _costBuy(0), _costRent(0), _costSell(0), _repairRate(1), _refuelRate(1),\n\t_transferTime(24), _score(0), _battlescapeTerrainData(0), _maxSkinIndex(0),\n\t_keepCraftAfterFailedMission(false), _allowLanding(true), _spacecraft(false), _notifyWhenRefueled(false), _autoPatrol(false), _undetectable(false),\n\t_patrolWithoutFuel(false),\n\t_missilePower(0),\n\t_listOrder(listOrder), _maxAltitude(-1), _defaultAltitude(\"STR_VERY_LOW\"), _onlyOneSoldierGroupAllowed(false), _stats(),\n\t_shieldRechargeAtBase(1000),\n\t_mapVisible(true), _forceShowInMonthlyCosts(false), _useAllStartTiles(false)\n{\n\tfor (int i = 0; i < WeaponMax; ++ i)\n\t{\n\t\tfor (int j = 0; j < WeaponTypeMax; ++j)\n\t\t\t_weaponTypes[i][j] = 0;\n\t}\n\t_stats.radarRange = 672;\n\t_stats.radarChance = 100;\n\t_stats.sightRange = 1696;\n\t_stats.maxItems = 999999;\n\t_stats.maxStorageSpace = 99999.0;\n\t_weaponStrings[0] = \"STR_WEAPON_ONE\";\n\t_weaponStrings[1] = \"STR_WEAPON_TWO\";\n}\n\n/**\n *\n */\nRuleCraft::~RuleCraft()\n{\n\tdelete _battlescapeTerrainData;\n}\n\n/**\n * Loads the craft from a YAML file.\n * @param node YAML node.\n * @param mod Mod for the craft.\n * @param modIndex A value that offsets the sounds and sprite values to avoid conflicts.\n * @param listOrder The list weight for this craft.\n */\nvoid RuleCraft::load(const YAML::YamlNodeReader& node, Mod *mod, const ModScript &parsers)\n{\n\tconst auto& reader = node.useIndex();\n\tif (const auto& parent = reader[\"refNode\"])\n\t{\n\t\tload(parent, mod, parsers);\n\t}\n\n\t//requires\n\tmod->loadUnorderedNames(_type, _requires, reader[\"requires\"]);\n\tmod->loadBaseFunction(_type, _requiresBuyBaseFunc, reader[\"requiresBuyBaseFunc\"]);\n\treader.tryRead(\"requiresBuyCountry\", _requiresBuyCountry);\n\n\tif (reader[\"sprite\"])\n\t{\n\t\t// used in\n\t\t// Surface set (baseOffset):\n\t\t//   BASEBITS.PCK (33)\n\t\t//   INTICON.PCK (11)\n\t\t//   INTICON.PCK (0)\n\t\t//\n\t\t// Final index in surfaceset is `baseOffset + sprite + (sprite > 4 ? modOffset : 0)`\n\t\t_sprite = mod->getOffset(reader[\"sprite\"].readVal(_sprite), 4);\n\t}\n\tif (const auto& skinSprites = reader[\"skinSprites\"])\n\t{\n\t\t_skinSprites.clear();\n\t\tfor (const auto& skinSprite : skinSprites.children())\n\t\t{\n\t\t\tint tmp = mod->getOffset(skinSprite.readVal<int>(), 4);\n\t\t\t_skinSprites.push_back(tmp);\n\t\t}\n\t}\n\t_stats.load(reader);\n\tif (reader[\"marker\"])\n\t{\n\t\t_marker = mod->getOffset(reader[\"marker\"].readVal(_marker), 8);\n\t}\n\treader.tryRead(\"weapons\", _weapons);\n\treader.tryRead(\"maxUnitsLimit\", _maxUnitsLimit);\n\treader.tryRead(\"pilots\", _pilots);\n\treader.tryRead(\"maxHWPUnitsLimit\", _maxVehiclesAndLargeSoldiersLimit);\n\treader.tryRead(\"maxSmallSoldiers\", _maxSmallSoldiers);\n\treader.tryRead(\"maxLargeSoldiers\", _maxLargeSoldiers);\n\treader.tryRead(\"maxSmallVehicles\", _maxSmallVehicles);\n\treader.tryRead(\"maxLargeVehicles\", _maxLargeVehicles);\n\treader.tryRead(\"maxSmallUnits\", _maxSmallUnits);\n\treader.tryRead(\"maxLargeUnits\", _maxLargeUnits);\n\treader.tryRead(\"maxSoldiers\", _maxSoldiers);\n\treader.tryRead(\"maxVehicles\", _maxVehicles);\n\treader.tryRead(\"monthlyBuyLimit\", _monthlyBuyLimit);\n\treader.tryRead(\"monthlyBuyLimitMessage\", _monthlyBuyLimitMessage);\n\treader.tryRead(\"costBuy\", _costBuy);\n\treader.tryRead(\"costRent\", _costRent);\n\treader.tryRead(\"costSell\", _costSell);\n\tmod->loadName(_type, _refuelItemName, reader[\"refuelItem\"]);\n\treader.tryRead(\"repairRate\", _repairRate);\n\treader.tryRead(\"refuelRate\", _refuelRate);\n\treader.tryRead(\"transferTime\", _transferTime);\n\treader.tryRead(\"score\", _score);\n\tif (const auto& terrain = reader[\"battlescapeTerrainData\"])\n\t{\n\t\tRuleTerrain *rule = new RuleTerrain(terrain[\"name\"].readVal<std::string>());\n\t\trule->load(terrain, mod);\n\t\t_battlescapeTerrainData = rule;\n\t}\n\treader.tryRead(\"craftInventoryTile\", _craftInventoryTile);\n\tmod->loadUnorderedInts(_type, _groups, reader[\"groups\"]);\n\tmod->loadUnorderedInts(_type, _allowedSoldierGroups, reader[\"allowedSoldierGroups\"]);\n\tmod->loadUnorderedInts(_type, _allowedArmorGroups, reader[\"allowedArmorGroups\"]);\n\treader.tryRead(\"limitArmorGroups\", _limitArmorGroups);\n\treader.tryRead(\"onlyOneSoldierGroupAllowed\", _onlyOneSoldierGroupAllowed);\n\treader.tryRead(\"maxSkinIndex\", _maxSkinIndex);\n\treader.tryRead(\"deployment\", _deployment);\n\treader.tryRead(\"keepCraftAfterFailedMission\", _keepCraftAfterFailedMission);\n\treader.tryRead(\"allowLanding\", _allowLanding);\n\treader.tryRead(\"spacecraft\", _spacecraft);\n\treader.tryRead(\"notifyWhenRefueled\", _notifyWhenRefueled);\n\treader.tryRead(\"autoPatrol\", _autoPatrol);\n\treader.tryRead(\"undetectable\", _undetectable);\n\treader.tryRead(\"patrolWithoutFuel\", _patrolWithoutFuel);\n\treader.tryRead(\"missilePower\", _missilePower);\n\treader.tryRead(\"listOrder\", _listOrder);\n\treader.tryRead(\"maxAltitude\", _maxAltitude);\n\treader.tryRead(\"defaultAltitude\", _defaultAltitude);\n\n\tif (const auto& types = reader[\"weaponTypes\"])\n\t{\n\t\tsize_t max = std::min(types.childrenCount(), (size_t)WeaponMax);\n\t\tfor (size_t i = 0; i < max; ++i)\n\t\t{\n\t\t\tconst auto& type = types[i];\n\t\t\tif (type.hasVal())\n\t\t\t{\n\t\t\t\tfor (int j = 0; j < WeaponTypeMax; ++j)\n\t\t\t\t\t_weaponTypes[i][j] = type.readVal<int>();\n\t\t\t}\n\t\t\telse if (type.isSeq())\n\t\t\t{\n\t\t\t\tfor (int j = 0; (size_t)j < type.childrenCount() && j < WeaponTypeMax; ++j)\n\t\t\t\t\t_weaponTypes[i][j] = type[j].readVal<int>();\n\t\t\t\tfor (int j = type.childrenCount(); j < WeaponTypeMax; ++j)\n\t\t\t\t\t_weaponTypes[i][j] = _weaponTypes[i][0];\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tthrow Exception(\"Invalid weapon type in craft \" + _type + \".\");\n\t\t\t}\n\t\t}\n\t}\n\tif (const auto& str = reader[\"weaponStrings\"])\n\t{\n\t\tfor (int i = 0; (size_t)i < str.childrenCount() &&  i < WeaponMax; ++i)\n\t\t\t_weaponStrings[i] = str[i].readVal<std::string>();\n\t}\n\tif (const auto& str = reader[\"fixedWeapons\"])\n\t{\n\t\tfor (int i = 0; (size_t)i < str.childrenCount() && i < WeaponMax; ++i)\n\t\t\t_fixedWeaponNames[i] = str[i].readVal<std::string>();\n\t}\n\treader.tryRead(\"shieldRechargedAtBase\", _shieldRechargeAtBase);\n\treader.tryRead(\"mapVisible\", _mapVisible);\n\treader.tryRead(\"forceShowInMonthlyCosts\", _forceShowInMonthlyCosts);\n\treader.tryRead(\"useAllStartTiles\", _useAllStartTiles);\n\treader.tryRead(\"customPreview\", _customPreview);\n\n\tmod->loadSoundOffset(_type, _selectSound, reader[\"selectSound\"], \"GEO.CAT\");\n\tmod->loadSoundOffset(_type, _takeoffSound, reader[\"takeoffSound\"], \"GEO.CAT\");\n\n\treader.tryRead(\"pilotMinStatsRequired\", _pilotMinStatsRequired);\n\tmod->loadNames(_type, _pilotSoldierBonusesRequiredNames, reader[\"pilotSoldierBonusesRequired\"]);\n\n\t_craftScripts.load(_type, reader, parsers.craftScripts);\n\t_scriptValues.load(reader, parsers.getShared());\n}\n\n/**\n * Cross link with other rules.\n */\nvoid RuleCraft::afterLoad(const Mod* mod)\n{\n\tmod->linkRule(_refuelItem, _refuelItemName);\n\tmod->linkRule(_pilotSoldierBonusesRequired, _pilotSoldierBonusesRequiredNames);\n\n\t// No turning soldiers into antimatter\n\tmod->checkForSoftError(_stats.soldiers < 0, _type, \"Default unit capacity cannot be negative.\", LOG_ERROR);\n\tmod->checkForSoftError(_stats.vehicles < 0, _type, \"Default HWP capacity cannot be negative.\", LOG_ERROR);\n\n\t// Backwards-compatibility\n\tif (_maxUnitsLimit < 0)\n\t{\n\t\t_maxUnitsLimit = _stats.soldiers;\n\t}\n\tif (_maxVehiclesAndLargeSoldiersLimit < 0)\n\t{\n\t\t_maxVehiclesAndLargeSoldiersLimit = _stats.vehicles;\n\t}\n\n\t// Sanity checks\n\tmod->checkForSoftError(_maxUnitsLimit < _stats.soldiers, _type, \"Maximum unit capacity is smaller than the default unit capacity.\", LOG_ERROR);\n\tmod->checkForSoftError(_maxVehiclesAndLargeSoldiersLimit < _stats.vehicles, _type, \"Maximum HWP capacity is smaller than the default HWP capacity.\", LOG_ERROR);\n}\n\n/**\n * Gets the language string that names\n * this craft. Each craft type has a unique name.\n * @return The craft's name.\n */\nconst std::string &RuleCraft::getType() const\n{\n\treturn _type;\n}\n\n/**\n * Gets the list of research required to\n * acquire this craft.\n * @return The list of research IDs.\n */\nconst std::vector<std::string> &RuleCraft::getRequirements() const\n{\n\treturn _requires;\n}\n\n/**\n * Gets the ID of the sprite used to draw the craft\n * in the Basescape and Equip Craft screens.\n * @return The Sprite ID.\n */\nint RuleCraft::getSprite(int skinIndex) const\n{\n\tif (skinIndex > 0)\n\t{\n\t\tsize_t vectorIndex = skinIndex - 1;\n\t\tif (vectorIndex < _skinSprites.size())\n\t\t{\n\t\t\treturn _skinSprites[vectorIndex];\n\t\t}\n\t}\n\treturn _sprite;\n}\n\n/**\n * Returns the globe marker for the craft type.\n * @return Marker sprite, -1 if none.\n */\nint RuleCraft::getMarker() const\n{\n\treturn _marker;\n}\n\n/**\n * Gets the maximum fuel the craft can contain.\n * @return The fuel amount.\n */\nint RuleCraft::getMaxFuel() const\n{\n\treturn _stats.fuelMax;\n}\n\n/**\n * Gets the maximum damage (damage the craft can take)\n * of the craft.\n * @return The maximum damage.\n */\nint RuleCraft::getMaxDamage() const\n{\n\treturn _stats.damageMax;\n}\n\n/**\n * Gets the maximum speed of the craft flying\n * around the Geoscape.\n * @return The speed in knots.\n */\nint RuleCraft::getMaxSpeed() const\n{\n\treturn _stats.speedMax;\n}\n\n/**\n * Gets the acceleration of the craft for\n * taking off / stopping.\n * @return The acceleration.\n */\nint RuleCraft::getAcceleration() const\n{\n\treturn _stats.accel;\n}\n\n/**\n * Gets the maximum number of weapons that\n * can be equipped onto the craft.\n * @return The weapon capacity.\n */\nint RuleCraft::getWeapons() const\n{\n\treturn _weapons;\n}\n\n/**\n * Checks if this craft is supported in the New Battle mode (and Preview mode).\n */\nbool RuleCraft::isForNewBattle() const\n{\n\treturn getBattlescapeTerrainData() && getMaxUnitsLimit() > 0 && getAllowLanding();\n}\n\n/**\n * Gets the maximum number of units (soldiers and vehicles, small and large) that\n * the craft can carry.\n * @return The maximum unit capacity.\n */\nint RuleCraft::getMaxUnits() const\n{\n\treturn _stats.soldiers;\n}\n\n/**\n* Gets the number of pilots that the craft requires in order to take off.\n* @return The number of pilots.\n*/\nint RuleCraft::getPilots() const\n{\n\treturn _pilots;\n}\n\n/**\n * Gets the maximum number of vehicles (and 2x2 soldiers) that\n * the craft can carry.\n * @return The maximum vehicle capacity (incl. 2x2 soldiers).\n */\nint RuleCraft::getMaxVehiclesAndLargeSoldiers() const\n{\n\treturn _stats.vehicles;\n}\n\n/**\n * Gets the cost of this craft for\n * purchase/rent (0 if not purchasable).\n * @return The cost.\n */\nint RuleCraft::getBuyCost() const\n{\n\treturn _costBuy;\n}\n\n/**\n * Gets the cost of rent for a month.\n * @return The cost.\n */\nint RuleCraft::getRentCost() const\n{\n\treturn _costRent;\n}\n\n/**\n * Gets the sell value of this craft\n * Rented craft should use 0.\n * @return The sell value.\n */\nint RuleCraft::getSellCost() const\n{\n\treturn _costSell;\n}\n\n/**\n * Gets what item is required while\n * the craft is refuelling.\n * @return The item ID or \"\" if none.\n */\nconst RuleItem* RuleCraft::getRefuelItem() const\n{\n\treturn _refuelItem;\n}\n\n/**\n * Gets how much damage is removed from the\n * craft while repairing.\n * @return The amount of damage.\n */\nint RuleCraft::getRepairRate() const\n{\n\treturn _repairRate;\n}\n\n/**\n * Gets how much fuel is added to the\n * craft while refuelling.\n * @return The amount of fuel.\n */\nint RuleCraft::getRefuelRate() const\n{\n\treturn _refuelRate;\n}\n\n/**\n * Gets the craft's radar range\n * for detecting UFOs.\n * @return The range in nautical miles.\n */\nint RuleCraft::getRadarRange() const\n{\n\treturn _stats.radarRange;\n}\n\n/**\n * Gets the craft's radar chance\n * for detecting UFOs.\n * @return The chance in percentage.\n */\nint RuleCraft::getRadarChance() const\n{\n\treturn _stats.radarChance;\n}\n\n/**\n * Gets the craft's sight range\n * for detecting bases.\n * @return The range in nautical miles.\n */\nint RuleCraft::getSightRange() const\n{\n\treturn _stats.sightRange;\n}\n\n/**\n * Gets the amount of time this item\n * takes to arrive at a base.\n * @return The time in hours.\n */\nint RuleCraft::getTransferTime() const\n{\n\treturn _transferTime;\n}\n\n/**\n * Gets the number of points you lose\n * when this craft is destroyed.\n * @return The score in points.\n */\nint RuleCraft::getScore() const\n{\n\treturn _score;\n}\n\n/**\n * Gets the terrain data needed to draw the Craft in the battlescape.\n * @return The terrain data.\n */\nRuleTerrain *RuleCraft::getBattlescapeTerrainData() const\n{\n\treturn _battlescapeTerrainData;\n}\n\n/**\n * Checks if this craft is lost after a failed mission or not.\n * @return True if this craft is NOT lost (e.g. paratroopers).\n */\nbool RuleCraft::keepCraftAfterFailedMission() const\n{\n\treturn _keepCraftAfterFailedMission;\n}\n\n/**\n * Checks if this craft is capable of landing (on missions).\n * @return True if this ship is capable of landing (on missions).\n */\nbool RuleCraft::getAllowLanding() const\n{\n\treturn _allowLanding;\n}\n\n/**\n * Checks if this ship is capable of going to mars.\n * @return True if this ship is capable of going to mars.\n */\nbool RuleCraft::getSpacecraft() const\n{\n\treturn _spacecraft;\n}\n\n/**\n * Checks if a notification should be displayed when the craft is refueled.\n * @return True if notification should appear.\n */\nbool RuleCraft::notifyWhenRefueled() const\n{\n\treturn _notifyWhenRefueled;\n}\n\n/**\n* Checks if the craft supports auto-patrol feature.\n* @return True if auto-patrol is supported.\n*/\nbool RuleCraft::canAutoPatrol() const\n{\n\treturn _autoPatrol;\n}\n\n/**\n * Gets the list weight for this research item.\n * @return The list weight.\n */\nint RuleCraft::getListOrder() const\n{\n\treturn _listOrder;\n}\n\n/**\n * Gets the deployment layout for this craft.\n * @return The deployment layout.\n */\nconst RuleCraftDeployment &RuleCraft::getDeployment() const\n{\n\treturn _deployment;\n}\n\n/**\n* Gets the craft inventory tile position.\n* @return The tile position.\n*/\nconst std::vector<int> &RuleCraft::getCraftInventoryTile() const\n{\n\treturn _craftInventoryTile;\n}\n\n/**\n * Gets the maximum amount of items this craft can store.\n * @return number of items.\n */\nint RuleCraft::getMaxItems() const\n{\n\treturn _stats.maxItems;\n}\n\n/**\n * Gets the maximum storage space for items in this craft.\n * @return storage space limit.\n */\ndouble RuleCraft::getMaxStorageSpace() const\n{\n\treturn _stats.maxStorageSpace;\n}\n\n/**\n * Test for possibility of usage of weapon type in weapon slot.\n * @param slot value less than WeaponMax.\n * @param weaponType weapon type of weapon that we try insert.\n * @return True if can use.\n */\nbool RuleCraft::isValidWeaponSlot(int slot, int weaponType) const\n{\n\tfor (int j = 0; j < WeaponTypeMax; ++j)\n\t{\n\t\tif (_weaponTypes[slot][j] == weaponType)\n\t\t\treturn true;\n\t}\n\treturn false;\n}\n\nint RuleCraft::getWeaponTypesRaw(int slot, int subslot) const\n{\n\treturn _weaponTypes[slot][subslot];\n}\n\n/**\n * Return string ID of weapon slot name for geoscape craft state.\n * @param slot value less than WeaponMax.\n * @return String ID for translation.\n */\nconst std::string &RuleCraft::getWeaponSlotString(int slot) const\n{\n\treturn _weaponStrings[slot];\n}\n\n/**\n * Gets the string ID of a fixed weapon in a given slot.\n * @param slot value less than WeaponMax.\n * @return String ID.\n */\nconst std::string &RuleCraft::getFixedWeaponInSlot(int slot) const\n{\n\treturn _fixedWeaponNames[slot];\n}\n\n/**\n * Gets basic statistic of craft.\n * @return Basic stats of craft.\n */\nconst RuleCraftStats& RuleCraft::getStats() const\n{\n\treturn _stats;\n}\n\n/**\n * Gets the maximum altitude this craft can dogfight to.\n * @return max altitude (0-4).\n */\nint RuleCraft::getMaxAltitude() const\n{\n\treturn _maxAltitude;\n}\n\n/**\n * Gets the craft's default display altitude.\n * @return String ID of an altitude for display purposes.\n */\nconst std::string& RuleCraft::getDefaultDisplayAltitude() const\n{\n\treturn _defaultAltitude;\n}\n\n/**\n * If the craft is underwater, it can only dogfight over polygons.\n * TODO: Replace this with its own flag.\n * @return underwater or not\n */\nbool RuleCraft::isWaterOnly() const\n{\n\treturn _maxAltitude > -1;\n}\n\n/**\n * Gets how many shield points are recharged when landed at base per hour\n * @return shield recharged per hour\n */\nint RuleCraft::getShieldRechargeAtBase() const\n{\n\treturn _shieldRechargeAtBase;\n}\n\n/**\n * Gets whether or not the craft map should be visible at the beginning of the battlescape\n * @return visible or not?\n */\nbool RuleCraft::isMapVisible() const\n{\n\treturn _mapVisible;\n}\n\n/**\n * Gets whether or not the craft type should be displayed in Monthly Costs even if not present in the base.\n * @return visible or not?\n */\nbool RuleCraft::forceShowInMonthlyCosts() const\n{\n\treturn _forceShowInMonthlyCosts;\n}\n\n/**\n * Can the player utilize all start tiles on a craft or only the ones specified in the '_deployment' list?\n * @return can use all or not?\n */\nbool RuleCraft::useAllStartTiles() const\n{\n\treturn _useAllStartTiles;\n}\n\n/**\n * Gets the craft's custom preview type.\n * @return String ID of an alienDeployment.\n */\nconst std::string& RuleCraft::getCustomPreviewType() const\n{\n\treturn _customPreview.empty() ? DEFAULT_CRAFT_DEPLOYMENT_PREVIEW : _customPreview;\n}\n\n/**\n * Gets the craft's custom preview type.\n * @return String ID of an alienDeployment or an empty string.\n */\nconst std::string& RuleCraft::getCustomPreviewTypeRaw() const\n{\n\treturn _customPreview;\n}\n\n/**\n * Calculates the theoretical range of the craft\n * This depends on when you launch the craft as fuel is consumed only on exact 10 minute increments\n * @param type Which calculation should we do? 0 = maximum, 1 = minimum, 2 = average of the two\n * @return The calculated range\n */\nint RuleCraft::calculateRange(int type)\n{\n\t// If the craft uses an item to refuel, the tick rate is one fuel unit per 10 minutes\n\tint totalFuelTicks = _stats.fuelMax;\n\n\t// If no item is used to refuel, the tick rate depends on speed\n\tif (_refuelItem == nullptr)\n\t{\n\t\t// Craft with less than 100 speed don't consume fuel and therefore have infinite range\n\t\tif (_stats.speedMax < 100)\n\t\t{\n\t\t\treturn -1;\n\t\t}\n\n\t\ttotalFuelTicks = _stats.fuelMax / (_stats.speedMax / 100);\n\t}\n\n\t// Six ticks per hour, factor return trip and speed for total range\n\tint range;\n\tswitch (type)\n\t{\n\t\t// Min range happens when the craft is sent at xx:x9:59, as a unit of fuel is immediately consumed, so we subtract an extra 'tick' of fuel in this case\n\t\tcase 1:\n\t\t\trange = (totalFuelTicks - 1) * _stats.speedMax / 12;\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\trange = (2 * totalFuelTicks - 1) * _stats.speedMax / 12 / 2;\n\t\t\tbreak;\n\t\tdefault :\n\t\t\trange = totalFuelTicks * _stats.speedMax / 12;\n\t\t\tbreak;\n\t}\n\n\treturn range;\n}\n\n/**\n * Gets a random sound id from a given sound vector.\n * @param vector The source vector.\n * @param defaultValue Default value (in case nothing is specified = vector is empty).\n * @return The sound id.\n */\nint RuleCraft::getRandomSound(const std::vector<int>& vector, int defaultValue) const\n{\n\tif (!vector.empty())\n\t{\n\t\treturn vector[RNG::generate(0, vector.size() - 1)];\n\t}\n\treturn defaultValue;\n}\n\n/**\n * Gets the sound played when the player directly selects a craft on the globe.\n * @return The select sound id.\n */\nint RuleCraft::getSelectSound() const\n{\n\treturn getRandomSound(_selectSound);\n}\n\n/**\n * Gets the sound played when a craft takes off from a base.\n * @return The takeoff sound id.\n */\nint RuleCraft::getTakeoffSound() const\n{\n\treturn getRandomSound(_takeoffSound);\n}\n\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tScript binding\n////////////////////////////////////////////////////////////\n\nnamespace\n{\n\nvoid getTypeScript(const RuleCraft* r, ScriptText& txt)\n{\n\tif (r)\n\t{\n\t\ttxt = { r->getType().c_str() };\n\t\treturn;\n\t}\n\telse\n\t{\n\t\ttxt = ScriptText::empty;\n\t}\n}\n\nstd::string debugDisplayScript(const RuleCraft* rc)\n{\n\tif (rc)\n\t{\n\t\tstd::string s;\n\t\ts += RuleCraft::ScriptName;\n\t\ts += \"(type: \\\"\";\n\t\ts += rc->getType();\n\t\ts += \"\\\"\";\n\t\ts += \")\";\n\t\treturn s;\n\t}\n\telse\n\t{\n\t\treturn \"null\";\n\t}\n}\n\n} // namespace\n\n/**\n * Register Type in script parser.\n * @param parser Script parser.\n */\nvoid RuleCraft::ScriptRegister(ScriptParserBase* parser)\n{\n\tBind<RuleCraft> b = { parser };\n\n\tb.add<&getTypeScript>(\"getType\");\n\n\tb.add<&RuleCraft::getWeapons>(\"getWeaponsMax\");\n\tb.add<&RuleCraft::getMaxUnits>(\"getSoldiersMax\");\n\tb.add<&RuleCraft::getMaxVehiclesAndLargeSoldiers>(\"getVehiclesMax\");\n\tb.add<&RuleCraft::getPilots>(\"getPilotsMax\");\n\n\tRuleCraftStats::addGetStatsScript<&RuleCraft::_stats>(b, \"Stats.\");\n\n\tb.addScriptValue<&RuleCraft::_scriptValues>();\n\tb.addDebugDisplay<&debugDisplayScript>();\n}\n\n}\n\n"
  },
  {
    "path": "src/Mod/RuleCraft.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <vector>\n#include <map>\n#include <string>\n#include \"../Engine/Yaml.h\"\n#include \"Unit.h\"\n#include \"RuleBaseFacilityFunctions.h\"\n#include \"ModScript.h\"\n\nnamespace OpenXcom\n{\n\ntypedef std::vector<std::vector<int> > RuleCraftDeployment;\n\nclass RuleTerrain;\nclass RuleItem;\nclass Mod;\nclass ModScript;\nclass ScriptParserBase;\n\n/**\n * Battle statistic of craft type and bonus from craft weapons.\n */\nstruct RuleCraftStats\n{\n\tint fuelMax, damageMax, speedMax, accel;\n\tint radarRange, radarChance, sightRange;\n\tint hitBonus, avoidBonus, avoidBonus2, powerBonus, armor;\n\tint shieldCapacity, shieldRecharge, shieldRechargeInGeoscape, shieldBleedThrough;\n\tint soldiers, vehicles;\n\tint maxItems;\n\tdouble maxStorageSpace;\n\n\t/// Default constructor.\n\tRuleCraftStats() :\n\t\tfuelMax(0), damageMax(0), speedMax(0), accel(0),\n\t\tradarRange(0), radarChance(0), sightRange(0),\n\t\thitBonus(0), avoidBonus(0), avoidBonus2(0), powerBonus(0), armor(0),\n\t\tshieldCapacity(0), shieldRecharge(0), shieldRechargeInGeoscape(0), shieldBleedThrough(0),\n\t\tsoldiers(0), vehicles(0),\n\t\tmaxItems(0), maxStorageSpace(0.0)\n\t{\n\n\t}\n\t/// Add different stats.\n\tRuleCraftStats& operator+=(const RuleCraftStats& r)\n\t{\n\t\tfuelMax += r.fuelMax;\n\t\tdamageMax += r.damageMax;\n\t\tspeedMax += r.speedMax;\n\t\taccel += r.accel;\n\t\tradarRange += r.radarRange;\n\t\tradarChance += r.radarChance;\n\t\tsightRange += r.sightRange;\n\t\thitBonus += r.hitBonus;\n\t\tavoidBonus += r.avoidBonus;\n\t\tavoidBonus2 += r.avoidBonus2;\n\t\tpowerBonus += r.powerBonus;\n\t\tarmor += r.armor;\n\t\tshieldCapacity += r.shieldCapacity;\n\t\tshieldRecharge += r.shieldRecharge;\n\t\tshieldRechargeInGeoscape += r.shieldRechargeInGeoscape;\n\t\tshieldBleedThrough += r.shieldBleedThrough;\n\t\tsoldiers += r.soldiers;\n\t\tvehicles += r.vehicles;\n\t\tmaxItems += r.maxItems;\n\t\tmaxStorageSpace += r.maxStorageSpace;\n\t\treturn *this;\n\t}\n\t/// Subtract different stats.\n\tRuleCraftStats& operator-=(const RuleCraftStats& r)\n\t{\n\t\tfuelMax -= r.fuelMax;\n\t\tdamageMax -= r.damageMax;\n\t\tspeedMax -= r.speedMax;\n\t\taccel -= r.accel;\n\t\tradarRange -= r.radarRange;\n\t\tradarChance -= r.radarChance;\n\t\tsightRange -= r.sightRange;\n\t\thitBonus -= r.hitBonus;\n\t\tavoidBonus -= r.avoidBonus;\n\t\tavoidBonus2 -= r.avoidBonus2;\n\t\tpowerBonus -= r.powerBonus;\n\t\tarmor -= r.armor;\n\t\tshieldCapacity -= r.shieldCapacity;\n\t\tshieldRecharge -= r.shieldRecharge;\n\t\tshieldRechargeInGeoscape -= r.shieldRechargeInGeoscape;\n\t\tshieldBleedThrough -= r.shieldBleedThrough;\n\t\tsoldiers -= r.soldiers;\n\t\tvehicles -= r.vehicles;\n\t\tmaxItems -= r.maxItems;\n\t\tmaxStorageSpace -= r.maxStorageSpace;\n\t\treturn *this;\n\t}\n\t/// Gets negative values of stats.\n\tRuleCraftStats operator-() const\n\t{\n\t\tRuleCraftStats s;\n\t\ts -= *this;\n\t\treturn s;\n\t}\n\t/// Loads stats from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader)\n\t{\n\t\t//const auto& reader = r.useIndex();\n\t\treader.tryRead(\"fuelMax\", fuelMax);\n\t\treader.tryRead(\"damageMax\", damageMax);\n\t\treader.tryRead(\"speedMax\", speedMax);\n\t\treader.tryRead(\"accel\", accel);\n\t\treader.tryRead(\"radarRange\", radarRange);\n\t\treader.tryRead(\"radarChance\", radarChance);\n\t\treader.tryRead(\"sightRange\", sightRange);\n\t\treader.tryRead(\"hitBonus\", hitBonus);\n\t\treader.tryRead(\"avoidBonus\", avoidBonus);\n\t\treader.tryRead(\"avoidBonus2\", avoidBonus2);\n\t\treader.tryRead(\"powerBonus\", powerBonus);\n\t\treader.tryRead(\"armor\", armor);\n\t\treader.tryRead(\"shieldCapacity\", shieldCapacity);\n\t\treader.tryRead(\"shieldRecharge\", shieldRecharge);\n\t\treader.tryRead(\"shieldRechargeInGeoscape\", shieldRechargeInGeoscape);\n\t\treader.tryRead(\"shieldBleedThrough\", shieldBleedThrough);\n\t\treader.tryRead(\"soldiers\", soldiers);\n\t\treader.tryRead(\"vehicles\", vehicles);\n\t\treader.tryRead(\"maxItems\", maxItems);\n\t\treader.tryRead(\"maxStorageSpace\", maxStorageSpace);\n\t}\n\n\ttemplate<auto Stat, typename TBind>\n\tstatic void addGetStatsScript(TBind& b, std::string prefix)\n\t{\n\t\tb.template addField<Stat, &RuleCraftStats::fuelMax>(prefix + \"getFuelMax\");\n\t\tb.template addField<Stat, &RuleCraftStats::damageMax>(prefix + \"getDamageMax\");\n\t\tb.template addField<Stat, &RuleCraftStats::speedMax>(prefix + \"getSpeedMax\");\n\t\tb.template addField<Stat, &RuleCraftStats::accel>(prefix + \"getAccel\");\n\t\tb.template addField<Stat, &RuleCraftStats::radarRange>(prefix + \"getRadarRange\");\n\t\tb.template addField<Stat, &RuleCraftStats::radarChance>(prefix + \"getRadarChance\");\n\t\tb.template addField<Stat, &RuleCraftStats::sightRange>(prefix + \"getSightRange\");\n\t\tb.template addField<Stat, &RuleCraftStats::hitBonus>(prefix + \"getHitBonus\");\n\t\tb.template addField<Stat, &RuleCraftStats::avoidBonus>(prefix + \"getAvoidBonus\");\n\t\tb.template addField<Stat, &RuleCraftStats::avoidBonus2>(prefix + \"getAvoidBonus2\");\n\t\tb.template addField<Stat, &RuleCraftStats::powerBonus>(prefix + \"getPowerBonus\");\n\t\tb.template addField<Stat, &RuleCraftStats::armor>(prefix + \"getArmor\");\n\t\tb.template addField<Stat, &RuleCraftStats::shieldCapacity>(prefix + \"getShieldCapacity\");\n\t\tb.template addField<Stat, &RuleCraftStats::shieldRecharge>(prefix + \"getShieldRecharge\");\n\t\tb.template addField<Stat, &RuleCraftStats::shieldRechargeInGeoscape>(prefix + \"getShieldRechargeInGeoscape\");\n\t\tb.template addField<Stat, &RuleCraftStats::shieldBleedThrough>(prefix + \"getShieldBleedThrough\");\n\t\tb.template addField<Stat, &RuleCraftStats::soldiers>(prefix + \"getMaxUnits\");\n\t\tb.template addField<Stat, &RuleCraftStats::vehicles>(prefix + \"getMaxVehiclesAndLargeSoldiers\");\n\t\tb.template addField<Stat, &RuleCraftStats::maxItems>(prefix + \"getMaxItems\");\n\t\t//b.template addField<Stat, &RuleCraftStats::maxStorageSpace>(prefix + \"getMaxStorageSpace\");\n\t}\n};\n\n/**\n * Represents a specific type of craft.\n * Contains constant info about a craft like\n * costs, speed, capacities, consumptions, etc.\n * @sa Craft\n */\nclass RuleCraft\n{\npublic:\n\t/// Maximum number of weapon slots on craft.\n\tstatic const int WeaponMax = 4;\n\t/// Maximum of different types in one weapon slot.\n\tstatic const int WeaponTypeMax = 8;\n\n\t/// Default craft preview ID.\n\tstatic const std::string DEFAULT_CRAFT_DEPLOYMENT_PREVIEW;\n\t/// Dummy craft ID.\n\tstatic const int DUMMY_CRAFT_ID = -42; // a negative integer\n\n\t/// Name of class used in script.\n\tstatic constexpr const char *ScriptName = \"RuleCraft\";\n\t/// Register all useful function used by script.\n\tstatic void ScriptRegister(ScriptParserBase* parser);\n\nprivate:\n\tstd::string _type;\n\tstd::vector<std::string> _requires;\n\tRuleBaseFacilityFunctions _requiresBuyBaseFunc;\n\tstd::string _requiresBuyCountry;\n\tint _sprite, _marker;\n\tstd::vector<int> _skinSprites;\n\tint _weapons, _maxUnitsLimit, _pilots, _maxVehiclesAndLargeSoldiersLimit;\n\tint _maxSmallSoldiers, _maxLargeSoldiers, _maxSmallVehicles, _maxLargeVehicles;\n\tint _maxSmallUnits, _maxLargeUnits, _maxSoldiers, _maxVehicles;\n\tint _monthlyBuyLimit;\n\tstd::string _monthlyBuyLimitMessage;\n\tint _costBuy, _costRent, _costSell;\n\tchar _weaponTypes[WeaponMax][WeaponTypeMax];\n\tconst RuleItem* _refuelItem;\n\tstd::string _refuelItemName;\n\tstd::string _weaponStrings[WeaponMax];\n\tstd::string _fixedWeaponNames[WeaponMax];\n\tint _repairRate, _refuelRate, _transferTime, _score;\n\tRuleTerrain *_battlescapeTerrainData;\n\tint _maxSkinIndex;\n\tbool _keepCraftAfterFailedMission, _allowLanding, _spacecraft, _notifyWhenRefueled, _autoPatrol, _undetectable, _patrolWithoutFuel;\n\tint _missilePower;\n\tint _listOrder, _maxAltitude;\n\tstd::string _defaultAltitude;\n\tRuleCraftDeployment _deployment;\n\tstd::vector<int> _craftInventoryTile;\n\tstd::vector<int> _groups;\n\tstd::vector<int> _allowedSoldierGroups;\n\tstd::vector<int> _allowedArmorGroups;\n\tstd::map<int, int> _limitArmorGroups;\n\tbool _onlyOneSoldierGroupAllowed;\n\tRuleCraftStats _stats;\n\tint _shieldRechargeAtBase;\n\tbool _mapVisible, _forceShowInMonthlyCosts;\n\tbool _useAllStartTiles;\n\tstd::string _customPreview;\n\tstd::vector<int> _selectSound, _takeoffSound;\n\tUnitStats _pilotMinStatsRequired;\n\tstd::vector<std::string> _pilotSoldierBonusesRequiredNames;\n\tstd::vector<const RuleSoldierBonus*> _pilotSoldierBonusesRequired;\n\n\tModScript::CraftScripts::Container _craftScripts;\n\tScriptValues<RuleCraft> _scriptValues;\n\n\t/// Gets a random sound from a given vector.\n\tint getRandomSound(const std::vector<int>& vector, int defaultValue = -1) const;\n\npublic:\n\t/// Creates a blank craft ruleset.\n\tRuleCraft(const std::string &type, int listOrder);\n\t/// Cleans up the craft ruleset.\n\t~RuleCraft();\n\t/// Loads craft data from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader, Mod *mod, const ModScript &parsers);\n\t/// Cross link with other rules.\n\tvoid afterLoad(const Mod* mod);\n\t/// Gets the craft's type.\n\tconst std::string &getType() const;\n\t/// Gets the craft's requirements.\n\tconst std::vector<std::string> &getRequirements() const;\n\t/// Gets the base functions required to buy craft.\n\tRuleBaseFacilityFunctions getRequiresBuyBaseFunc() const { return _requiresBuyBaseFunc; }\n\t/// Gets the allied country name required to buy this craft.\n\tconst std::string& getRequiresBuyCountry() const { return _requiresBuyCountry; }\n\t/// Gets the craft's sprite.\n\tint getSprite(int skinIndex) const;\n\tconst std::vector<int> &getSkinSpritesRaw() const { return _skinSprites; }\n\t/// Gets the craft's globe marker.\n\tint getMarker() const;\n\t/// Gets the craft's maximum fuel.\n\tint getMaxFuel() const;\n\t/// Gets the craft's maximum damage.\n\tint getMaxDamage() const;\n\t/// Gets the craft's maximum speed.\n\tint getMaxSpeed() const;\n\t/// Gets the craft's acceleration.\n\tint getAcceleration() const;\n\t/// Gets the craft's weapon capacity.\n\tint getWeapons() const;\n\n\t/// Checks if this craft is supported in the New Battle mode (and Preview mode).\n\tbool isForNewBattle() const;\n\n\t/// Gets the craft's maximum unit capacity (soldiers and vehicles, small and large).\n\tint getMaxUnits() const;\n\t/// Gets the craft's maximum unit capacity (soldiers and vehicles, small and large) *including* any additional weapons module bonuses.\n\tint getMaxUnitsLimit() const { return _maxUnitsLimit; }\n\t/// Gets the craft's pilot capacity/requirement.\n\tint getPilots() const;\n\t/// Gets the craft's maximum vehicle capacity (incl. 2x2 soldiers).\n\tint getMaxVehiclesAndLargeSoldiers() const;\n\t/// Gets the craft's maximum vehicle capacity (incl. 2x2 soldiers) *including* any additional weapons module bonuses.\n\tint getMaxVehiclesAndLargeSoldiersLimit() const { return _maxVehiclesAndLargeSoldiersLimit; }\n\t/// Gets the craft's maximum supported number of small (size=1) soldiers.\n\tint getMaxSmallSoldiers() const { return _maxSmallSoldiers; }\n\t/// Gets the craft's maximum supported number of large (size=2) soldiers.\n\tint getMaxLargeSoldiers() const { return _maxLargeSoldiers; }\n\t/// Gets the craft's maximum supported number of small (size=1) vehicles (HWPs/SWSs).\n\tint getMaxSmallVehicles() const { return _maxSmallVehicles; }\n\t/// Gets the craft's maximum supported number of large (size=2) vehicles (HWPs/SWSs).\n\tint getMaxLargeVehicles() const { return _maxLargeVehicles; }\n\t/// Gets the craft's maximum supported number of small (size=1) units (soldiers + vehicles).\n\tint getMaxSmallUnits() const { return _maxSmallUnits; }\n\t/// Gets the craft's maximum supported number of large (size=2) units (soldiers + vehicles).\n\tint getMaxLargeUnits() const { return _maxLargeUnits; }\n\t/// Gets the craft's maximum supported number of soldiers (small + large).\n\tint getMaxSoldiers() const { return _maxSoldiers; }\n\t/// Gets the craft's maximum supported number of vehicles (small + large).\n\tint getMaxVehicles() const { return _maxVehicles; }\n\t/// Gets the craft's monthly buy limit.\n\tint getMonthlyBuyLimit() const { return _monthlyBuyLimit; }\n\t/// Gets the craft's monthly buy limit message.\n\tconst std::string& getMonthlyBuyLimitMessage() const { return _monthlyBuyLimitMessage; }\n\t/// Gets the craft's cost.\n\tint getBuyCost() const;\n\t/// Gets the craft's rent for a month.\n\tint getRentCost() const;\n\t/// Gets the craft's value.\n\tint getSellCost() const;\n\t/// Gets the craft's refuel item.\n\tconst RuleItem* getRefuelItem() const;\n\t/// Gets the craft's repair rate.\n\tint getRepairRate() const;\n\t/// Gets the craft's refuel rate.\n\tint getRefuelRate() const;\n\t/// Gets the craft's radar range.\n\tint getRadarRange() const;\n\t/// Gets the craft's radar chance.\n\tint getRadarChance() const;\n\t/// Gets the craft's sight range.\n\tint getSightRange() const;\n\t/// Gets the craft's transfer time.\n\tint getTransferTime() const;\n\t/// Gets the craft's score.\n\tint getScore() const;\n\t/// Gets the craft's terrain data.\n\tRuleTerrain *getBattlescapeTerrainData() const;\n\t/// Gets the craft's maximum skin index.\n\tint getMaxSkinIndex() const { return _maxSkinIndex; }\n\t/// Checks if this craft is lost after a failed mission or not.\n\tbool keepCraftAfterFailedMission() const;\n\t/// Checks if this craft is capable of landing (on missions).\n\tbool getAllowLanding() const;\n\t/// Checks if this craft is capable of travelling to mars.\n\tbool getSpacecraft() const;\n\t/// Should notification be displayed when the craft is refueled?\n\tbool notifyWhenRefueled() const;\n\t/// Does this craft support auto-patrol?\n\tbool canAutoPatrol() const;\n\t/// Is this craft immune to detection by HKs and alien bases?\n\tbool isUndetectable() const { return _undetectable; }\n\t/// Can this craft patrol without fuel comsumption?\n\tbool patrolWithoutFuel() const { return _patrolWithoutFuel; }\n\t/// Is this craft a self-destruct missile?\n\tbool isMissile() const { return (_missilePower > 0); }\n\t/// Gets the missile power.\n\tint missilePower() const { return _missilePower; }\n\t/// Gets the list weight for this craft.\n\tint getListOrder() const;\n\t/// Gets the deployment priority for the craft.\n\tconst RuleCraftDeployment &getDeployment() const;\n\t/// Gets the craft inventory tile position.\n\tconst std::vector<int> &getCraftInventoryTile() const;\n\t/// Gets the craft groups (used in map scripts).\n\tconst std::vector<int>& getGroups() const { return _groups; }\n\t/// Gets the list of allowed soldier groups.\n\tconst std::vector<int>& getAllowedSoldierGroups() const { return _allowedSoldierGroups; }\n\t/// Gets the list of allowed armor groups.\n\tconst std::vector<int>& getAllowedArmorGroups() const { return _allowedArmorGroups; }\n\t/// Gets the list of allowed armor groups.\n\tconst std::map<int, int>& getLimitArmorGroups() const { return _limitArmorGroups; }\n\t/// Does this craft allow soldiers of the same group only?\n\tbool isOnlyOneSoldierGroupAllowed() const { return _onlyOneSoldierGroupAllowed; }\n\t/// Gets the item limit for this craft.\n\tint getMaxItems() const;\n\t/// Gets the item storage space limit for this craft.\n\tdouble getMaxStorageSpace() const;\n\t/// Test for possibility of usage of weapon type in weapon slot.\n\tbool isValidWeaponSlot(int slot, int weaponType) const;\n\tint getWeaponTypesRaw(int slot, int subslot) const;\n\t/// Get description string of weapon slot.\n\tconst std::string &getWeaponSlotString(int slot) const;\n\t/// Gets the string ID of a fixed weapon in a given slot.\n\tconst std::string &getFixedWeaponInSlot(int slot) const;\n\t/// Get basic statistic of craft.\n\tconst RuleCraftStats& getStats() const;\n\t/// Gets how high this craft can go.\n\tint getMaxAltitude() const;\n\t/// Gets the craft's default display altitude.\n\tconst std::string& getDefaultDisplayAltitude() const;\n\t/// Gets if this craft only fights on water.\n\tbool isWaterOnly() const;\n\t/// Get how many shield points are recharged per hour at base\n\tint getShieldRechargeAtBase() const;\n\t/// Get whether the craft's map should be visible at the start of a battle\n\tbool isMapVisible() const;\n\t/// Gets whether or not the craft type should be displayed in Monthly Costs even if not present in the base.\n\tbool forceShowInMonthlyCosts() const;\n\t/// Can the player utilize all start tiles on a craft or only the ones specified in the '_deployment' list?\n\tbool useAllStartTiles() const;\n\t/// Gets the craft's custom preview type.\n\tconst std::string& getCustomPreviewType() const;\n\tconst std::string& getCustomPreviewTypeRaw() const;\n\n\t/// Calculate the theoretical range of the craft in nautical miles\n\tint calculateRange(int type);\n\n\t/// Gets the sound played when the player directly selects a craft on the globe.\n\tint getSelectSound() const;\n\tconst std::vector<int>& getSelectSoundRaw() const { return _selectSound; }\n\t/// Gets the sound played when a craft takes off from a base.\n\tint getTakeoffSound() const;\n\tconst std::vector<int>& getTakeoffSoundRaw() const { return _takeoffSound; }\n\n\t/// Gets the minimum stats a soldier needs to be eligible for piloting this craft\n\tconst UnitStats& getPilotMinStatsRequired() const { return _pilotMinStatsRequired; }\n\t/// Gets the list of soldier bonuses a soldier needs to be eligible for piloting this craft\n\tconst std::vector<const RuleSoldierBonus*>& getPilotSoldierBonusesRequired() const { return _pilotSoldierBonusesRequired; }\n\n\t/// Gets script.\n\ttemplate<typename Script>\n\tconst typename Script::Container &getScript() const { return _craftScripts.get<Script>(); }\n\t/// Get all script values.\n\tconst ScriptValues<RuleCraft>& getScriptValuesRaw() const { return _scriptValues; }\n};\n\n}\n"
  },
  {
    "path": "src/Mod/RuleCraftWeapon.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"RuleCraftWeapon.h\"\n#include \"Mod.h\"\n#include \"../Engine/Logger.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Creates a blank ruleset for a certain type of craft weapon.\n * @param type String defining the type.\n */\nRuleCraftWeapon::RuleCraftWeapon(const std::string &type) :\n\t_type(type), _sprite(-1), _sound(-1), _damage(0), _shieldDamageModifier(100), _range(0), _accuracy(0),\n\t_reloadCautious(0), _reloadStandard(0), _reloadAggressive(0), _ammoMax(0),\n\t_rearmRate(1), _projectileSpeed(0), _weaponType(0), _projectileType(CWPT_CANNON_ROUND),\n\t_stats(), _underwaterOnly(false),\n\t_tractorBeamPower(0), _hidePediaInfo(false), _statisticalBulletSaving(false), _unifiedDamageFormula(false)\n{\n}\n\n/**\n *\n */\nRuleCraftWeapon::~RuleCraftWeapon()\n{\n}\n\n/**\n * Loads the craft weapon from a YAML file.\n * @param node YAML node.\n * @param mod Mod for the craft weapon.\n */\nvoid RuleCraftWeapon::load(const YAML::YamlNodeReader& node, Mod *mod)\n{\n\tconst auto& reader = node.useIndex();\n\tif (const auto& parent = reader[\"refNode\"])\n\t{\n\t\tload(parent, mod);\n\t}\n\n\treader.tryRead(\"ufopediaType\", _ufopediaType);\n\treader.tryRead(\"tooltip\", _tooltip);\n\tif (reader[\"stats\"])\n\t{\n\t\t_stats.load(reader[\"stats\"]);\n\t}\n\tif (reader[\"sprite\"])\n\t{\n\t\t// used in\n\t\t// Surface set (baseOffset):\n\t\t//   BASEBITS.PCK (48)\n\t\t//   INTICON.PCK (5)\n\t\t//\n\t\t// Final index in surfaceset is `baseOffset + sprite + (sprite > 5 ? modOffset : 0)`\n\t\t_sprite = mod->getOffset(reader[\"sprite\"].readVal(_sprite), 5);\n\t}\n\tmod->loadSoundOffset(_type, _sound, reader[\"sound\"], \"GEO.CAT\");\n\treader.tryRead(\"damage\", _damage);\n\treader.tryRead(\"unifiedDamageFormula\", _unifiedDamageFormula);\n\treader.tryRead(\"shieldDamageModifier\", _shieldDamageModifier);\n\treader.tryRead(\"range\", _range);\n\treader.tryRead(\"accuracy\", _accuracy);\n\treader.tryRead(\"reloadCautious\", _reloadCautious);\n\treader.tryRead(\"reloadStandard\", _reloadStandard);\n\treader.tryRead(\"reloadAggressive\", _reloadAggressive);\n\treader.tryRead(\"ammoMax\", _ammoMax);\n\treader.tryRead(\"rearmRate\", _rearmRate);\n\treader.tryRead(\"projectileType\", _projectileType);\n\treader.tryRead(\"projectileSpeed\", _projectileSpeed);\n\treader.tryRead(\"launcher\", _launcherName);\n\treader.tryRead(\"clip\", _clipName);\n\treader.tryRead(\"weaponType\", _weaponType);\n\treader.tryRead(\"underwaterOnly\", _underwaterOnly);\n\treader.tryRead(\"tractorBeamPower\", _tractorBeamPower);\n\treader.tryRead(\"hidePediaInfo\", _hidePediaInfo);\n\treader.tryRead(\"bulletSaving\", _statisticalBulletSaving);\n}\n\n\n/**\n * Cross link with other rules.\n */\nvoid RuleCraftWeapon::afterLoad(const Mod* mod)\n{\n\tmod->linkRule(_launcher, _launcherName);\n\tmod->linkRule(_clip, _clipName);\n\n\tif (_unifiedDamageFormula && !_launcher && !_clip)\n\t{\n\t\tthrow Exception(\"Unified damage formula requires `clip` or `launcher` to be defined.\");\n\t}\n\n\tif (_projectileType < CWPT_LASER_BEAM && _damage > 0)\n\t{\n\t\tif (_projectileSpeed <= 0)\n\t\t{\n\t\t\tthrow Exception(\"Missile-like craft weapons (with 'damage' > 0) must have a positive 'projectileSpeed'.\");\n\t\t}\n\t\telse if (_projectileSpeed <= 4 && _range > 10)\n\t\t{\n\t\t\tLog(LOG_WARNING) << \"Missile speed for \" << _type << \" is very low! Depending on craft approach speed, the missile may seem not moving, or even moving backwards. Speed: \" << _projectileSpeed << \"; range: \" << _range;\n\t\t}\n\t\telse if (_projectileSpeed <= 5 && _range > 20)\n\t\t{\n\t\t\tLog(LOG_INFO) << \"Missile speed for \" << _type << \" is quite low. Depending on craft approach speed, the missile may seem moving very slowly. Speed: \" << _projectileSpeed << \"; range: \" << _range;\n\t\t}\n\t}\n\tif (_launcher == nullptr)\n\t{\n\t\tthrow Exception(\"Launcher item is required for a craft weapon\");\n\t}\n\tif (_ammoMax)\n\t{\n\t\tif (_rearmRate <= 0)\n\t\t{\n\t\t\tthrow Exception(\"Attribute 'rearmRate' must be positive when 'ammoMax' is set\");\n\t\t}\n\t\tif (_clip && _clip->getClipSize() > _rearmRate)\n\t\t{\n\t\t\tthrow Exception(\"Attribute 'clipSize' of the clip item is too big for the given 'rearmRate'\");\n\t\t}\n\t}\n}\n\n\n/**\n * Gets the custom name of the Ufopedia article related to this craft weapon.\n * @return The ufopedia article name.\n */\nconst std::string& RuleCraftWeapon::getUfopediaType() const\n{\n\tif (!_ufopediaType.empty())\n\t\treturn _ufopediaType;\n\n\treturn _type;\n}\n\n/**\n * Gets the language string that names this craft weapon.\n * Each craft weapon type has a unique name.\n * @return The craft weapon's name.\n */\nconst std::string& RuleCraftWeapon::getType() const\n{\n\treturn _type;\n}\n\n/**\n * Gets the ID of the sprite used to draw the craft weapon\n * in the Equip Craft and Interception screens.\n * @return The sprite ID.\n */\nint RuleCraftWeapon::getSprite() const\n{\n\treturn _sprite;\n}\n\n/**\n * Gets the ID of the sound used when firing the weapon\n * in the Dogfight screen.\n * @return The sound ID.\n */\nint RuleCraftWeapon::getSound() const\n{\n\treturn _sound;\n}\n\n/**\n * Gets the amount of damage this craft weapon\n * inflicts on enemy crafts.\n * @return The damage amount.\n */\nint RuleCraftWeapon::getDamage() const\n{\n\treturn _damage;\n}\n\n/**\n * Gets the percent effectiveness of this craft weapon against shields\n * @return modifier to damage against shields\n */\nint RuleCraftWeapon::getShieldDamageModifier() const\n{\n\treturn _shieldDamageModifier;\n}\n\n/**\n * Gets the maximum range of this craft weapon.\n * @return The range in km.\n */\nint RuleCraftWeapon::getRange() const\n{\n\treturn _range;\n}\n\n/**\n * Gets the percentage chance of each shot of\n * this craft weapon hitting an enemy craft.\n * @return The accuracy as a percentage.\n */\nint RuleCraftWeapon::getAccuracy() const\n{\n\treturn _accuracy;\n}\n\n/**\n * Gets the amount of time the craft weapon takes to\n * reload in cautious mode.\n * @return The time in game seconds.\n */\nint RuleCraftWeapon::getCautiousReload() const\n{\n\treturn _reloadCautious;\n}\n\n/**\n * Gets the amount of time the craft weapon takes to\n * reload in standard mode.\n * @return The time in game seconds.\n */\nint RuleCraftWeapon::getStandardReload() const\n{\n\treturn _reloadStandard;\n}\n\n/**\n * Gets the amount of time the craft weapon takes to\n * reload in aggressive mode.\n * @return The time in game seconds.\n */\nint RuleCraftWeapon::getAggressiveReload() const\n{\n\treturn _reloadAggressive;\n}\n\n/**\n * Gets the maximum amount of ammo the craft weapon\n * can carry.\n * @return The amount of ammo.\n */\nint RuleCraftWeapon::getAmmoMax() const\n{\n\treturn _ammoMax;\n}\n\n/**\n * Gets how much ammo is added to the craft weapon\n * while rearming (the amount of ammo in each clip item).\n * @return The amount of ammo.\n */\nint RuleCraftWeapon::getRearmRate() const\n{\n\treturn _rearmRate;\n}\n\n/**\n * Gets the rule of the item used to\n * equip this craft weapon.\n * @return The item rule.\n */\nconst RuleItem* RuleCraftWeapon::getLauncherItem() const\n{\n\treturn _launcher;\n}\n\n/**\n * Gets the rule of the item used to\n * load this craft weapon with ammo.\n * @return The item rule.\n */\nconst RuleItem* RuleCraftWeapon::getClipItem() const\n{\n\treturn _clip;\n}\n\n/**\n * Gets the Projectile Type this weapon will fire\n * @return The projectile type.\n */\nCraftWeaponProjectileType RuleCraftWeapon::getProjectileType() const\n{\n\treturn _projectileType;\n}\n\n/**\n * Gets the speed of the projectile fired by this weapon\n * @return The projectile speed.\n */\nint RuleCraftWeapon::getProjectileSpeed() const\n{\n\treturn _projectileSpeed;\n}\n\n/**\n * Gets weapon type used by craft slots.\n * @return What type of slot is valid to equip this weapon.\n */\nint RuleCraftWeapon::getWeaponType() const\n{\n\treturn _weaponType;\n}\n\n/**\n * Gets bonus stats given by this weapon.\n */\nconst RuleCraftStats& RuleCraftWeapon::getBonusStats() const\n{\n\treturn _stats;\n}\n\n/**\n * Can this item be used on land or is it underwater only?\n * @return if this is an underwater weapon or not.\n */\nbool RuleCraftWeapon::isWaterOnly() const\n{\n\treturn _underwaterOnly;\n}\n\n/**\n * Get the craft weapon's tractor beam power\n * @return The tractor beam power.\n */\nint RuleCraftWeapon::getTractorBeamPower() const\n{\n\treturn _tractorBeamPower;\n}\n\n}\n"
  },
  {
    "path": "src/Mod/RuleCraftWeapon.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include \"../Engine/Yaml.h\"\n#include \"RuleCraft.h\"\n#include \"../Savegame/CraftWeaponProjectile.h\"\n\nnamespace OpenXcom\n{\n\nclass Mod;\nclass RuleItem;\n\nenum CraftWeaponCategory { CWC_WEAPON, CWC_TRACTOR_BEAM, CWC_EQUIPMENT };\n\n/**\n * Represents a specific type of craft weapon.\n * Contains constant info about a craft weapon like\n * damage, range, accuracy, items used, etc.\n * @sa CraftWeapon\n */\nclass RuleCraftWeapon\n{\nprivate:\n\tstd::string _ufopediaType;\n\tstd::string _type;\n\tstd::string _tooltip;\n\tint _sprite, _sound, _damage, _shieldDamageModifier, _range, _accuracy, _reloadCautious, _reloadStandard, _reloadAggressive, _ammoMax, _rearmRate, _projectileSpeed, _weaponType;\n\tCraftWeaponProjectileType _projectileType;\n\tstd::string _launcherName, _clipName;\n\tconst RuleItem* _launcher;\n\tconst RuleItem* _clip;\n\tRuleCraftStats _stats;\n\tbool _underwaterOnly;\n\tint _tractorBeamPower;\n\tbool _hidePediaInfo;\n\tbool _statisticalBulletSaving;\n\tbool _unifiedDamageFormula;\npublic:\n\t/// Creates a blank craft weapon ruleset.\n\tRuleCraftWeapon(const std::string &type);\n\t/// Cleans up the craft weapon ruleset.\n\t~RuleCraftWeapon();\n\t/// Loads craft weapon data from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader, Mod *mod);\n\t/// Cross link with other rules.\n\tvoid afterLoad(const Mod* mod);\n\n\t/// Gets the custom name of the Ufopedia article related to this craft weapon.\n\tconst std::string& getUfopediaType() const;\n\n\t/// Gets the craft weapon's type.\n\tconst std::string& getType() const;\n\t/// Gets the craft weapon's tooltip.\n\tconst std::string& getTooltip() const { return _tooltip; }\n\t/// Gets the craft weapon's sprite.\n\tint getSprite() const;\n\t/// Gets the craft weapon's sound.\n\tint getSound() const;\n\t/// Gets the craft weapon's damage.\n\tint getDamage() const;\n\t/// Should the weapon's stats be displayed in Ufopedia or not?\n\tbool getHidePediaInfo() const { return _hidePediaInfo; }\n\t/// Should the statistical bullet saving be used or not?\n\tbool useStatisticalBulletSaving() const { return _statisticalBulletSaving; }\n\t/// Should unified or vanilla formula be used?\n\tbool unifiedDamageFormula() const { return _unifiedDamageFormula; }\n\t/// Gets the craft weapon's effectiveness against shields.\n\tint getShieldDamageModifier() const;\n\t/// Gets the craft weapon's range.\n\tint getRange() const;\n\t/// Gets the craft weapon's accuracy.\n\tint getAccuracy() const;\n\t/// Gets the craft weapon's cautious reload time.\n\tint getCautiousReload() const;\n\t/// Gets the craft weapon's standard reload time.\n\tint getStandardReload() const;\n\t/// Gets the craft weapon's aggressive reload time.\n\tint getAggressiveReload() const;\n\t/// Gets the craft weapon's maximum ammo.\n\tint getAmmoMax() const;\n\t/// Gets the craft weapon's rearm rate.\n\tint getRearmRate() const;\n\t/// Gets the craft weapon's launcher item.\n\tconst RuleItem* getLauncherItem() const;\n\t/// Gets the craft weapon's clip item.\n\tconst RuleItem* getClipItem() const;\n\t/// Gets the craft weapon's projectile's type.\n\tCraftWeaponProjectileType getProjectileType() const;\n\t/// Gets the craft weapon's projectile speed.\n\tint getProjectileSpeed() const;\n\t/// Gets weapon type used by craft slots.\n\tint getWeaponType() const;\n\t/// Gets bonus stats given by this weapon.\n\tconst RuleCraftStats& getBonusStats() const;\n\t/// Is this item restricted to use underwater?\n\tbool isWaterOnly() const;\n\t/// Get the craft weapon's tractor beam power\n\tint getTractorBeamPower() const;\n};\n\n}\n"
  },
  {
    "path": "src/Mod/RuleDamageType.cpp",
    "content": "/*\n * Copyright 2010-2015 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <cmath>\n#include \"RuleDamageType.h\"\n#include \"../Engine/RNG.h\"\n#include \"Mod.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Default constructor\n */\nRuleDamageType::RuleDamageType() :\n\tFixRadius(0), RandomType(DRT_STANDARD), ResistType(DT_NONE), FireBlastCalc(false),\n\tIgnoreDirection(false), IgnoreSelfDestruct(false), IgnorePainImmunity(false), IgnoreNormalMoraleLose(false), IgnoreOverKill(false),\n\tArmorEffectiveness(1.0f), RadiusEffectiveness(0.0f), RadiusReduction(10.0f),\n\tFireThreshold(1000), SmokeThreshold(1000),\n\tToHealth(1.0f), ToMana(0.0f), ToArmor(0.1f), ToArmorPre(0.0f), ToWound(1.0f), ToItem(0.0f), ToTile(0.5f), ToStun(0.25f), ToEnergy(0.0f), ToTime(0.0f), ToMorale(0.0f),\n\tRandomHealth(false), RandomMana(false), RandomArmor(false), RandomArmorPre(false), RandomWound(true), RandomItem(false), RandomTile(false), RandomStun(true), RandomEnergy(false), RandomTime(false), RandomMorale(false),\n\tTileDamageMethod(1), TileDamageLimit(-1)\n{\n\n}\n\n\n/**\n * Function converting power to damage.\n * @param power Input power.\n * @return Random damage based on power.\n */\nint RuleDamageType::getRandomDamage(int power) const\n{\n\treturn getRandomDamage(power, +[](int min, int max){ return RNG::generate(min, max); });\n}\n\n/**\n * Function converting power to damage.\n * @param power Input power.\n * @param mode Calc mode (0 = dmg, 1 = min dmg, 2 = max dmg)\n * @return Random damage based on power.\n */\nint RuleDamageType::getRandomDamage(int power, int mode) const\n{\n\tif (mode == 0)\n\t{\n\t\treturn getRandomDamage(power);\n\t}\n\telse if (mode == 1)\n\t{\n\t\treturn getRandomDamage(power, +[](int min, int max){ return min; });\n\t}\n\telse\n\t{\n\t\treturn getRandomDamage(power, +[](int min, int max){ return max; });\n\t}\n}\n\n/**\n * Function converting power to damage.\n * @param power Input power.\n * @param randFunc Function to get random value\n * @return Random damage based on power.\n */\nint RuleDamageType::getRandomDamage(int power, FuncRef<int(int, int)> randFunc) const\n{\n\tItemDamageRandomType randType = RandomType;\n\tif (randType == DRT_UFO_WITH_TWO_DICE)\n\t{\n\t\tint firstThrow = randFunc(0, power);\n\t\tint secondThrow = randFunc(0, power);\n\n\t\treturn firstThrow + secondThrow;\n\t}\n\telse if (randType == DRT_EASY)\n\t{\n\t\tint min = power / 2; // 50%\n\t\tint max = power * 2; // 200%\n\n\t\treturn randFunc(min, max);\n\t}\n\n\tconst bool def = randType == DRT_DEFAULT;\n\tif (def)\n\t{\n\t\tswitch (ResistType)\n\t\t{\n\t\tcase DT_NONE: randType = DRT_NONE; break;\n\t\tcase DT_IN: randType = DRT_FIRE; break;\n\t\tcase DT_HE: randType = DRT_EXPLOSION; break;\n\t\tcase DT_SMOKE: randType = DRT_NONE; break;\n\t\tdefault: randType = DRT_STANDARD; break;\n\t\t}\n\t}\n\n\tint dmgRng = 0;\n\tswitch (randType)\n\t{\n\tcase DRT_UFO: dmgRng = 100; break;\n\tcase DRT_TFTD: dmgRng = 50; break;\n\tcase DRT_STANDARD: dmgRng = Mod::DAMAGE_RANGE; break;\n\tcase DRT_EXPLOSION: dmgRng = Mod::EXPLOSIVE_DAMAGE_RANGE; break;\n\tcase DRT_FLAT: dmgRng = 0; break;\n\tcase DRT_FIRE:\n\t\treturn randFunc(Mod::FIRE_DAMAGE_RANGE[0], Mod::FIRE_DAMAGE_RANGE[1]);\n\n\tcase DRT_NONE: return 0;\n\tdefault: return 0;\n\t}\n\n\tint min = power * (100 - dmgRng) / 100;\n\tint max = power * (100 + dmgRng) / 100;\n\n\treturn randFunc(min, max);\n}\n\n/**\n * Calculate random value of damage for tile attack.\n * @param power Raw power of attack\n * @param damage Random damage done to units\n * @return Random damage for tile.\n */\nint RuleDamageType::getRandomDamageForTile(int power, int damage) const\n{\n\treturn TileDamageMethod == 1 ? RNG::generate(power / 2, 3 * power / 2) : damage;\n}\n\n/**\n * Is this damage single target.\n * @return True if it can only hit one target.\n */\nbool RuleDamageType::isDirect() const\n{\n\treturn FixRadius == 0;\n}\n\n/**\n * Load rule from YAML.\n * @param node Node with data.\n */\nvoid RuleDamageType::load(const YAML::YamlNodeReader& node)\n{\n\tconst auto& reader = node.useIndex();\n\treader.tryRead(\"FixRadius\", FixRadius);\n\treader.tryRead(\"RandomType\", RandomType);\n\treader.tryRead(\"ResistType\", ResistType);\n\treader.tryRead(\"FireBlastCalc\", FireBlastCalc);\n\treader.tryRead(\"IgnoreDirection\", IgnoreDirection);\n\treader.tryRead(\"IgnoreSelfDestruct\", IgnoreSelfDestruct);\n\treader.tryRead(\"IgnorePainImmunity\", IgnorePainImmunity);\n\treader.tryRead(\"IgnoreNormalMoraleLose\", IgnoreNormalMoraleLose);\n\treader.tryRead(\"IgnoreOverKill\", IgnoreOverKill);\n\treader.tryRead(\"ArmorEffectiveness\", ArmorEffectiveness);\n\treader.tryRead(\"RadiusEffectiveness\", RadiusEffectiveness);\n\treader.tryRead(\"RadiusReduction\", RadiusReduction);\n\n\treader.tryRead(\"FireThreshold\", FireThreshold);\n\treader.tryRead(\"SmokeThreshold\", SmokeThreshold);\n\n\treader.tryRead(\"ToHealth\", ToHealth);\n\treader.tryRead(\"ToMana\", ToMana);\n\treader.tryRead(\"ToArmor\", ToArmor);\n\treader.tryRead(\"ToArmorPre\", ToArmorPre);\n\treader.tryRead(\"ToWound\", ToWound);\n\treader.tryRead(\"ToItem\", ToItem);\n\treader.tryRead(\"ToTile\", ToTile);\n\treader.tryRead(\"ToStun\", ToStun);\n\treader.tryRead(\"ToEnergy\", ToEnergy);\n\treader.tryRead(\"ToTime\", ToTime);\n\treader.tryRead(\"ToMorale\", ToMorale);\n\n\treader.tryRead(\"RandomHealth\", RandomHealth);\n\treader.tryRead(\"RandomMana\", RandomMana);\n\treader.tryRead(\"RandomArmor\", RandomArmor);\n\treader.tryRead(\"RandomArmorPre\", RandomArmorPre);\n\treader.tryRead(\"RandomWound\", RandomWound);\n\treader.tryRead(\"RandomItem\", RandomItem);\n\treader.tryRead(\"RandomTile\", RandomTile);\n\treader.tryRead(\"RandomStun\", RandomStun);\n\treader.tryRead(\"RandomEnergy\", RandomEnergy);\n\treader.tryRead(\"RandomTime\", RandomTime);\n\treader.tryRead(\"RandomMorale\", RandomMorale);\n\n\treader.tryRead(\"TileDamageMethod\", TileDamageMethod);\n\treader.tryRead(\"TileDamageLimit\", TileDamageLimit);\n}\n\nnamespace\n{\n/**\n * Helper function for calculating damage from damage.\n * @param random\n * @param multiplier\n * @param damage\n * @return Damage to something.\n */\nint getDamageHelper(bool random, float multipler, int damage)\n{\n\tif (damage > 0)\n\t{\n\t\tif (random)\n\t\t{\n\t\t\treturn (int)std::round(RNG::generate(0, damage) * multipler);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn (int)std::round(damage * multipler);\n\t\t}\n\t}\n\treturn 0;\n}\n\n}\n\n/**\n * Get final damage value to health based on damage.\n */\nint RuleDamageType::getHealthFinalDamage(int damage) const\n{\n\treturn getDamageHelper(RandomHealth, ToHealth, damage);\n}\n\n/**\n * Get final damage value to mana based on damage.\n */\nint RuleDamageType::getManaFinalDamage(int damage) const\n{\n\treturn getDamageHelper(RandomMana, ToMana, damage);\n}\n\n/**\n * Get final damage value to armor based on damage.\n */\nint RuleDamageType::getArmorFinalDamage(int damage) const\n{\n\treturn getDamageHelper(RandomArmor, ToArmor, damage);\n}\n\n/**\n * Get final damage value to armor based on damage before armor reduction.\n */\nint RuleDamageType::getArmorPreFinalDamage(int damage) const\n{\n\treturn getDamageHelper(RandomArmorPre, ToArmorPre, damage);\n}\n\n/**\n * Get numbers of wound based on damage.\n */\nint RuleDamageType::getWoundFinalDamage(int damage) const\n{\n\tif (damage > 0)\n\t{\n\t\tif (RandomWound)\n\t\t{\n\t\t\tif (RNG::generate(0, 10) < int(damage * ToWound))\n\t\t\t{\n\t\t\t\treturn RNG::generate(1,3);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn (int)std::round(damage * ToWound);\n\t\t}\n\t}\n\treturn 0;\n}\n\n/**\n * Get final damage value to item based on damage.\n */\nint RuleDamageType::getItemFinalDamage(int damage) const\n{\n\treturn getDamageHelper(RandomItem, ToItem, damage);\n}\n\n/**\n * Get final damage value to tile based on damage.\n */\nint RuleDamageType::getTileFinalDamage(int damage) const\n{\n\tint tmp = getDamageHelper(RandomTile, ToTile, damage);\n\tif (TileDamageLimit >= 0 && tmp > TileDamageLimit)\n\t{\n\t\treturn TileDamageLimit;\n\t}\n\treturn tmp;\n}\n\n/**\n * Get stun level change based on damage.\n */\nint RuleDamageType::getStunFinalDamage(int damage) const\n{\n\treturn getDamageHelper(RandomStun, ToStun, damage);\n}\n\n/**\n * Get energy change based on damage.\n */\nint RuleDamageType::getEnergyFinalDamage(int damage) const\n{\n\treturn getDamageHelper(RandomEnergy, ToEnergy, damage);\n}\n\n/**\n * Get time units change based on damage.\n */\nint RuleDamageType::getTimeFinalDamage(int damage) const\n{\n\treturn getDamageHelper(RandomTime, ToTime, damage);\n}\n\n/**\n * Get morale change based on damage.\n */\nint RuleDamageType::getMoraleFinalDamage(int damage) const\n{\n\treturn getDamageHelper(RandomMorale, ToMorale, damage);\n}\n\n} //namespace OpenXcom\n"
  },
  {
    "path": "src/Mod/RuleDamageType.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2015 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/Yaml.h\"\n#include \"../Engine/Functions.h\"\n\nnamespace OpenXcom\n{\n\nenum ItemDamageType { DT_NONE, DT_AP, DT_IN, DT_HE, DT_LASER, DT_PLASMA, DT_STUN, DT_MELEE, DT_ACID, DT_SMOKE, DT_10, DT_11, DT_12, DT_13, DT_14, DT_15, DT_16, DT_17, DT_18, DT_19, DAMAGE_TYPES };\nenum ItemDamageRandomType\n{\n\tDRT_DEFAULT = 0,\n\tDRT_UFO = 1,\n\tDRT_TFTD = 2,\n\tDRT_FLAT = 3,\n\tDRT_FIRE = 4,\n\tDRT_NONE = 5,\n\tDRT_UFO_WITH_TWO_DICE = 6,\n\tDRT_EASY = 7,\n\tDRT_STANDARD = 8,\n\tDRT_EXPLOSION = 9,\n};\n\n/**\n * Represents a specific damage type.\n * @sa Item\n * @sa RuleItem\n */\nstruct RuleDamageType\n{\n\t/// Set fixed arena of effect radius.\n\tint FixRadius;\n\t/// Set what random range use when calculating damage.\n\tItemDamageRandomType RandomType;\n\t/// Set what resistance on armor is used.\n\tItemDamageType ResistType;\n\t/// Use fire calculation of radius and power.\n\tbool FireBlastCalc;\n\t/// Damage type ignore direction of attack.\n\tbool IgnoreDirection;\n\t/// Damage type do not cause self destruct explosion.\n\tbool IgnoreSelfDestruct;\n\t/// Damage type can do stun damage to big units.\n\tbool IgnorePainImmunity;\n\t/// Damage type doesn't cause morale loss from health damage.\n\tbool IgnoreNormalMoraleLose;\n\t/// Damage type do not move health to negative values.\n\tbool IgnoreOverKill;\n\t/// How much of armor is ignored.\n\tfloat ArmorEffectiveness;\n\t/// Conversion from power to max explosion radius.\n\tfloat RadiusEffectiveness;\n\t/// Reduction of explosion power per tile.\n\tfloat RadiusReduction;\n\t/// Threshold of fire creation\n\tint FireThreshold;\n\t/// Threshold of smoke creation\n\tint SmokeThreshold;\n\n\t/// Conversion from power to unit damage.\n\tfloat ToHealth;\n\t/// Conversion from power to mana loss.\n\tfloat ToMana;\n\t/// Conversion from power to unit armor damage.\n\tfloat ToArmor;\n\t/// Conversion from power to unit armor damage before applying armor protection.\n\tfloat ToArmorPre;\n\t/// Conversion from power to wound chance.\n\tfloat ToWound;\n\t/// Conversion from power to item damage.\n\tfloat ToItem;\n\t/// Conversion from power to tile damage.\n\tfloat ToTile;\n\t/// Conversion from power to stun level.\n\tfloat ToStun;\n\t/// Conversion from power to energy lose.\n\tfloat ToEnergy;\n\t/// Conversion from power to time units lose.\n\tfloat ToTime;\n\t/// Conversion from power to morale lose.\n\tfloat ToMorale;\n\n\t/// Damage type use random conversion to health damage.\n\tbool RandomHealth;\n\t/// Damage type use random conversion mana loss.\n\tbool RandomMana;\n\t///Damage type use random conversion armor damage.\n\tbool RandomArmor;\n\t/// Damage type use random conversion armor pre damage.\n\tbool RandomArmorPre;\n\t/// Damage type use random chance for wound number or linear.\n\tbool RandomWound;\n\t/// Damage type use random conversion item damage.\n\tbool RandomItem;\n\t/// Damage type use random conversion tile damage.\n\tbool RandomTile;\n\t/// Damage type use random conversion stun level.\n\tbool RandomStun;\n\t/// Damage type use random conversion energy lose.\n\tbool RandomEnergy;\n\t/// Damage type use random conversion time units lose.\n\tbool RandomTime;\n\t/// Damage type use random conversion morale lose.\n\tbool RandomMorale;\n\n\t/// Which tile damage method should be used?\n\t/// A. For AOE (area-of-effect) weapons:\n\t///   TileDamageMethod==1: (50%-150% * power * ToTile)\n\t///   TileDamageMethod==2: ((power x RandomTile) * ToTile), which defaults to vanilla 50% damage for HE and 0% for stun, smoke and incendiary\n\t/// B. For non-AOE (projectile) weapons:\n\t///   TileDamageMethod==1: (50%-150% * power * ToTile), which defaults to vanilla 25%-75% damage for AP/laser/plasma/etc.\n\t///   TileDamageMethod==2: ((damage x RandomTile) * ToTile)\n\tint TileDamageMethod;\n\n\t/// Maximum final tile damage possible, regardless of Power, ToTile, RandomTile, TileDamageMethod, etc.\n\tint TileDamageLimit;\n\n\t/// Default constructor.\n\tRuleDamageType();\n\t/// Calculate random value of damage.\n\tint getRandomDamage(int power) const;\n\t/// Calculate random value of damage.\n\tint getRandomDamage(int power, int mode) const;\n\t/// Calculate random value of damage using given random func.\n\tint getRandomDamage(int power, FuncRef<int(int, int)> randFunc) const;\n\t/// Calculate random value of damage for tile attack.\n\tint getRandomDamageForTile(int power, int damage) const;\n\t/// Do this damage type affect only one target\n\tbool isDirect() const;\n\t/// Loads item data from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader);\n\n\t/// Get final damage value to health based on damage.\n\tint getHealthFinalDamage(int damage) const;\n\t/// Get final damage value to mana based on damage.\n\tint getManaFinalDamage(int damage) const;\n\t/// Get final damage value to armor based on damage.\n\tint getArmorFinalDamage(int damage) const;\n\t/// Get final damage value to armor based on damage before armor reduction.\n\tint getArmorPreFinalDamage(int damage) const;\n\t/// Get numbers of wound based on damage.\n\tint getWoundFinalDamage(int damage) const;\n\t/// Get final damage value to item based on damage.\n\tint getItemFinalDamage(int damage) const;\n\t/// Get final damage value to tile based on damage.\n\tint getTileFinalDamage(int damage) const;\n\t/// Get stun level change based on damage.\n\tint getStunFinalDamage(int damage) const;\n\t/// Get energy change based on damage.\n\tint getEnergyFinalDamage(int damage) const;\n\t/// Get time units change based on damage.\n\tint getTimeFinalDamage(int damage) const;\n\t/// Get morale change based on damage.\n\tint getMoraleFinalDamage(int damage) const;\n};\n\n} //namespace OpenXcom\n"
  },
  {
    "path": "src/Mod/RuleEnviroEffects.cpp",
    "content": "/*\n * Copyright 2010-2019 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"RuleEnviroEffects.h\"\n#include \"../Engine/Collections.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Mod/Mod.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Creates a blank ruleset for a certain type of EnviroEffects.\n * @param type String defining the type.\n */\nRuleEnviroEffects::RuleEnviroEffects(const std::string& type) : _type(type), _mapBackgroundColor(15), _ignoreAutoNightVisionUserSetting(false)\n{\n}\n\n/**\n *\n */\nRuleEnviroEffects::~RuleEnviroEffects()\n{\n}\n\n/**\n * Loads the EnviroEffects from a YAML file.\n * @param node YAML node.\n */\nvoid RuleEnviroEffects::load(const YAML::YamlNodeReader& reader, const Mod* mod)\n{\n\tif (const auto& parent = reader[\"refNode\"])\n\t{\n\t\tload(parent, mod);\n\t}\n\n\treader.tryRead(\"environmentalConditions\", _environmentalConditions);\n\tmod->loadUnorderedNamesToNames(_type, _paletteTransformations, reader[\"paletteTransformations\"]);\n\tmod->loadUnorderedNamesToNames(_type, _armorTransformationsName, reader[\"armorTransformations\"]);\n\treader.tryRead(\"mapBackgroundColor\", _mapBackgroundColor);\n\treader.tryRead(\"ignoreAutoNightVisionUserSetting\", _ignoreAutoNightVisionUserSetting);\n\treader.tryRead(\"inventoryShockIndicator\", _inventoryShockIndicator);\n\treader.tryRead(\"mapShockIndicator\", _mapShockIndicator);\n}\n\n/**\n * Cross link with other rules.\n */\nvoid RuleEnviroEffects::afterLoad(const Mod* mod)\n{\n\tfor (auto& pair : _armorTransformationsName)\n\t{\n\t\tauto* src = mod->getArmor(pair.first, true);\n\t\tauto* dest = mod->getArmor(pair.second, true);\n\t\t_armorTransformations[src] = dest;\n\t}\n\n\t//remove not needed data\n\tCollections::removeAll(_armorTransformationsName);\n}\n\n/**\n * Gets the environmental condition for a given faction.\n * @param faction Faction code (STR_FRIENDLY, STR_HOSTILE or STR_NEUTRAL).\n * @return Environmental condition definition.\n */\nEnvironmentalCondition RuleEnviroEffects::getEnvironmetalCondition(const std::string& faction) const\n{\n\tif (!_environmentalConditions.empty())\n\t{\n\t\tauto i = _environmentalConditions.find(faction);\n\t\tif (i != _environmentalConditions.end())\n\t\t{\n\t\t\treturn i->second;\n\t\t}\n\t}\n\n\treturn EnvironmentalCondition();\n}\n\n/**\n * Gets the transformed armor.\n * @param sourceArmor Existing/old armor type.\n * @return Transformed armor type (or null if there is no transformation).\n */\nArmor* RuleEnviroEffects::getArmorTransformation(const Armor* sourceArmor) const\n{\n\tif (!_armorTransformations.empty())\n\t{\n\t\tauto i = _armorTransformations.find(sourceArmor);\n\t\tif (i != _armorTransformations.end())\n\t\t{\n\t\t\t// cannot switch into a bigger armor size!\n\t\t\tif (sourceArmor->getSize() >= i->second->getSize())\n\t\t\t{\n\t\t\t\treturn i->second;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nullptr;\n}\n\n// helper overloads for deserialization-only\nbool read(ryml::ConstNodeRef const& n, EnvironmentalCondition* val)\n{\n\tYAML::YamlNodeReader reader(n);\n\treader.tryRead(\"globalChance\", val->globalChance);\n\treader.tryRead(\"chancePerTurn\", val->chancePerTurn);\n\treader.tryRead(\"firstTurn\", val->firstTurn);\n\treader.tryRead(\"lastTurn\", val->lastTurn);\n\treader.tryRead(\"message\", val->message);\n\treader.tryRead(\"color\", val->color);\n\treader.tryRead(\"weaponOrAmmo\", val->weaponOrAmmo);\n\treader.tryRead(\"side\", val->side);\n\treader.tryRead(\"bodyPart\", val->bodyPart);\n\treturn true;\n}\n\n}\n"
  },
  {
    "path": "src/Mod/RuleEnviroEffects.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2019 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <map>\n#include <string>\n#include \"../Engine/Yaml.h\"\n\nnamespace OpenXcom\n{\nclass Mod;\nclass Armor;\n\nstruct EnvironmentalCondition\n{\n\tint globalChance;\n\tint chancePerTurn;\n\tint firstTurn, lastTurn;\n\tstd::string message;\n\tint color;\n\tstd::string weaponOrAmmo;\n\tint side;\n\tint bodyPart;\n\tEnvironmentalCondition() : globalChance(100), chancePerTurn(0), firstTurn(1), lastTurn(1000), color(29), side(-1), bodyPart(-1) { /*Empty by Design*/ };\n};\n\n/**\n * Represents a specific Starting Condition.\n */\nclass RuleEnviroEffects\n{\nprivate:\n\tstd::string _type;\n\tstd::map<std::string, EnvironmentalCondition> _environmentalConditions;\n\tstd::map<std::string, std::string> _paletteTransformations;\n\tstd::map<std::string, std::string> _armorTransformationsName;\n\tstd::map<const Armor*, Armor*> _armorTransformations;\n\tint _mapBackgroundColor;\n\tbool _ignoreAutoNightVisionUserSetting;\n\tstd::string _inventoryShockIndicator;\n\tstd::string _mapShockIndicator;\npublic:\n\t/// Creates a blank EnviroEffects ruleset.\n\tRuleEnviroEffects(const std::string& type);\n\t/// Cleans up the EnviroEffects ruleset.\n\t~RuleEnviroEffects();\n\t/// Loads EnviroEffects data from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader, const Mod* mod);\n\t/// Cross link with other rules.\n\tvoid afterLoad(const Mod* mod);\n\t/// Gets the EnviroEffects's type.\n\tconst std::string& getType() const { return _type; }\n\t/// Gets the palette transformations.\n\tconst std::map<std::string, std::string>& getPaletteTransformations() const { return _paletteTransformations; }\n\t/// Gets the environmental condition for a given faction.\n\tEnvironmentalCondition getEnvironmetalCondition(const std::string& faction) const;\n\t/// Gets the transformed armor.\n\tArmor* getArmorTransformation(const Armor* sourceArmor) const;\n\t/// Gets the battlescape map background color.\n\tint getMapBackgroundColor() const { return _mapBackgroundColor; }\n\t/// Gets the corresponding flag.\n\tbool ignoreAutoNightVisionUserSetting() const { return _ignoreAutoNightVisionUserSetting; }\n\t/// Gets the inventory shock indicator sprite name.\n\tconst std::string& getInventoryShockIndicator() const { return _inventoryShockIndicator; }\n\t/// Gets the map shock indicator sprite name.\n\tconst std::string& getMapShockIndicator() const { return _mapShockIndicator; }\n};\n\n// helper overloads for deserialization-only\nbool read(ryml::ConstNodeRef const& n, EnvironmentalCondition* val);\n\n}\n"
  },
  {
    "path": "src/Mod/RuleEvent.cpp",
    "content": "/*\n * Copyright 2010-2019 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"RuleEvent.h\"\n#include \"Mod.h\"\n\nnamespace OpenXcom\n{\n\nRuleEvent::RuleEvent(const std::string &name) :\n\t_name(name), _background(\"BACK13.SCR\"), _alignBottom(false),\n\t_city(false), _points(0), _funds(0), _spawnedPersons(0), _timer(30), _timerRandom(0), _invert(false)\n{\n}\n\n/**\n * Loads the event definition from YAML.\n * @param node YAML node.\n */\nvoid RuleEvent::load(const YAML::YamlNodeReader& node)\n{\n\tconst auto& reader = node.useIndex();\n\tif (const auto& parent = reader[\"refNode\"])\n\t{\n\t\tload(parent);\n\t}\n\n\treader.tryRead(\"description\", _description);\n\treader.tryRead(\"alignBottom\", _alignBottom);\n\treader.tryRead(\"background\", _background);\n\treader.tryRead(\"music\", _music);\n\treader.tryRead(\"cutscene\", _cutscene);\n\treader.tryRead(\"regionList\", _regionList);\n\treader.tryRead(\"city\", _city);\n\treader.tryRead(\"points\", _points);\n\treader.tryRead(\"funds\", _funds);\n\treader.tryRead(\"spawnedCraftType\", _spawnedCraftType);\n\treader.tryRead(\"spawnedPersons\", _spawnedPersons);\n\treader.tryRead(\"spawnedPersonType\", _spawnedPersonType);\n\treader.tryRead(\"spawnedPersonName\", _spawnedPersonName);\n\tif (reader[\"spawnedSoldier\"])\n\t{\n\t\t_spawnedSoldier = reader[\"spawnedSoldier\"].emitDescendants(YAML::YamlRootNodeReader(_spawnedSoldier, \"(spawned soldier template)\"));\n\t}\n\treader.tryRead(\"everyMultiItemList\", _everyMultiItemList);\n\treader.tryRead(\"everyItemList\", _everyItemList);\n\treader.tryRead(\"randomItemList\", _randomItemList);\n\treader.tryRead(\"randomMultiItemList\", _randomMultiItemList);\n\tif (reader[\"weightedItemList\"])\n\t{\n\t\t_weightedItemList.load(reader[\"weightedItemList\"]);\n\t}\n\treader.tryRead(\"researchList\", _researchNames);\n\treader.tryRead(\"adhocMissionScriptTags\", _adhocMissionScriptTags);\n\treader.tryRead(\"interruptResearch\", _interruptResearch);\n\treader.tryRead(\"timer\", _timer);\n\treader.tryRead(\"timerRandom\", _timerRandom);\n\treader.tryRead(\"invert\", _invert);\n\n\treader.tryRead(\"everyMultiSoldierList\", _everyMultiSoldierList);\n\treader.tryRead(\"randomMultiSoldierList\", _randomMultiSoldierList);\n}\n\n/**\n * Cross link with other Rules.\n */\nvoid RuleEvent::afterLoad(const Mod* mod)\n{\n\tmod->linkRule(_research, _researchNames);\n}\n\n}\n"
  },
  {
    "path": "src/Mod/RuleEvent.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2019 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include <map>\n#include <vector>\n#include \"../Engine/Yaml.h\"\n#include \"../Savegame/WeightedOptions.h\"\n\nnamespace OpenXcom\n{\n\nclass Mod;\nclass RuleResearch;\n\n/**\n * Represents a custom Geoscape event.\n * Events are spawned using Event Script ruleset.\n */\nclass RuleEvent\n{\nprivate:\n\tstd::string _name, _description, _background, _music, _cutscene;\n\tstd::vector<std::string> _regionList;\n\tbool _alignBottom;\n\tbool _city;\n\tint _points, _funds;\n\tstd::string _spawnedCraftType;\n\tint _spawnedPersons;\n\tstd::string _spawnedPersonType, _spawnedPersonName;\n\tYAML::YamlString _spawnedSoldier;\n\tstd::map<std::string, int> _everyMultiItemList;\n\tstd::vector<std::string> _everyItemList, _randomItemList;\n\tstd::vector<std::map<std::string, int> > _randomMultiItemList;\n\tWeightedOptions _weightedItemList;\n\tstd::vector<std::string> _researchNames;\n\tstd::vector<const RuleResearch*> _research;\n\tstd::vector<std::string> _adhocMissionScriptTags;\n\tstd::string _interruptResearch;\n\tint _timer, _timerRandom;\n\tbool _invert;\n\tstd::map<std::string, int> _everyMultiSoldierList;\n\tstd::vector<std::map<std::string, int> > _randomMultiSoldierList;\npublic:\n\t/// Creates a blank RuleEvent.\n\tRuleEvent(const std::string &name);\n\t/// Cleans up the event ruleset.\n\t~RuleEvent() = default;\n\t/// Loads the event definition from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader);\n\t/// Cross link with other rules.\n\tvoid afterLoad(const Mod* mod);\n\n\t/// Gets the event's name.\n\tconst std::string &getName() const { return _name; }\n\t/// Gets the event's description.\n\tconst std::string &getDescription() const { return _description; }\n\t/// Should the description be bottom aligned?\n\tbool alignBottom() const { return _alignBottom; }\n\t/// Gets the event's background sprite name.\n\tconst std::string &getBackground() const { return _background; }\n\t/// Gets the event's music.\n\tconst std::string &getMusic() const { return _music; }\n\t/// Gets the cutscene to play when the event dialog is closed.\n\tconst std::string &getCutscene() const { return _cutscene; }\n\t/// Gets a list of regions where this event can occur.\n\tconst std::vector<std::string> &getRegionList() const { return _regionList; }\n\t/// Is this event city specific?\n\tbool isCitySpecific() const { return _city; }\n\t/// Gets the amount of score points awarded when this event pops up.\n\tint getPoints() const { return _points; }\n\t/// Gets the amount of funds awarded when this event pops up.\n\tint getFunds() const { return _funds; }\n\n\t/// Gets the spawned craft type.\n\tconst std::string& getSpawnedCraftType() const { return _spawnedCraftType; }\n\n\t/// Gets the number of spawned persons.\n\tint getSpawnedPersons() const { return _spawnedPersons; }\n\t/// Gets the spawned person type.\n\tconst std::string& getSpawnedPersonType() const { return _spawnedPersonType; }\n\t/// Gets the custom name of the spawned person.\n\tconst std::string& getSpawnedPersonName() const { return _spawnedPersonName; }\n\t/// Gets the spawned soldier template.\n\tconst YAML::YamlString& getSpawnedSoldierTemplate() const { return _spawnedSoldier; }\n\n\t/// Gets a list of items; they are all transferred to HQ stores when this event pops up.\n\tconst std::map<std::string, int> &getEveryMultiItemList() const { return _everyMultiItemList; }\n\t/// Gets a list of items; they are all transferred to HQ stores when this event pops up.\n\tconst std::vector<std::string> &getEveryItemList() const { return _everyItemList; }\n\t/// Gets a list of items; one of them is randomly selected and transferred to HQ stores when this event pops up.\n\tconst std::vector<std::string> &getRandomItemList() const { return _randomItemList; }\n\t/// Gets a list of lists of items; one of them is randomly selected and transferred to HQ stores when this event pops up.\n\tconst std::vector<std::map<std::string, int> > &getRandomMultiItemList() const { return _randomMultiItemList; }\n\t/// Gets a list of items; one of them is randomly selected (considering weights) and transferred to HQ stores when this event pops up.\n\tconst WeightedOptions &getWeightedItemList() const { return _weightedItemList; }\n\t/// Gets a list of research projects; one of them will be randomly discovered when this event pops up.\n\tconst std::vector<const RuleResearch*> &getResearchList() const { return _research; }\n\t/// Gets a list of adhoc script tags; used for adhoc alien mission generation.\n\tconst std::vector<std::string> &getAdhocMissionScriptTags() const { return _adhocMissionScriptTags; }\n\t/// Gets the research project that will interrupt/terminate an already generated (but not yet popped up) event.\n\tconst std::string &getInterruptResearch() const { return _interruptResearch; }\n\t/// Gets the timer of delay for this event, for it occurring after being spawned with eventScripts ruleset.\n\tint getTimer() const { return _timer; }\n\t/// Gets value for calculation of random part of delay for this event.\n\tint getTimerRandom() const { return _timerRandom; }\n\t/// Should the event remove items instead of adding them?\n\tbool getInvert() const { return _invert; }\n\n\t/// Gets a list of soldiers; they are all transferred to HQ when this event pops up.\n\tconst std::map<std::string, int> &getEveryMultiSoldierList() const { return _everyMultiSoldierList; }\n\t/// Gets a list of lists of soldiers; one of them is randomly selected and transferred to HQ when this event pops up.\n\tconst std::vector<std::map<std::string, int> > &getRandomMultiSoldierList() const { return _randomMultiSoldierList; }\n};\n\n}\n"
  },
  {
    "path": "src/Mod/RuleEventScript.cpp",
    "content": "/*\n * Copyright 2010-2019 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"RuleEventScript.h\"\n#include <climits>\n\nnamespace OpenXcom\n{\n\n/**\n * RuleEventScript: the (optional) rules for generating custom Geoscape events.\n * Each script element is independent, and the saved game will probe the list of these each month to determine what's going to happen.\n * Event scripts are executed just after the mission scripts.\n */\nRuleEventScript::RuleEventScript(const std::string &type) :\n\t_type(type), _firstMonth(0), _lastMonth(-1), _executionOdds(100), _minDifficulty(0), _maxDifficulty(4),\n\t_minScore(INT_MIN), _maxScore(INT_MAX), _minFunds(INT64_MIN), _maxFunds(INT64_MAX),\n\t_counterMin(0), _counterMax(-1),\n\t_affectsGameProgression(false)\n{\n}\n\n/**\n * Cleans up the event script ruleset.\n */\nRuleEventScript::~RuleEventScript()\n{\n\tfor (auto& pair : _eventWeights)\n\t{\n\t\tdelete pair.second;\n\t}\n}\n\n/**\n * Loads an event script from YAML.\n * @param node YAML node.\n */\nvoid RuleEventScript::load(const YAML::YamlNodeReader& node)\n{\n\tconst auto& reader = node.useIndex();\n\tif (const auto& parent = reader[\"refNode\"])\n\t{\n\t\tload(parent);\n\t}\n\n\treader.tryRead(\"oneTimeSequentialEvents\", _oneTimeSequentialEvents);\n\tif (reader[\"oneTimeRandomEvents\"])\n\t{\n\t\t_oneTimeRandomEvents.load(reader[\"oneTimeRandomEvents\"]);\n\t}\n\tfor (const auto& monthWeights : reader[\"eventWeights\"].children())\n\t{\n\t\tWeightedOptions *nw = new WeightedOptions();\n\t\tnw->load(monthWeights);\n\t\t_eventWeights.push_back(std::make_pair(monthWeights.readKey<size_t>(0), nw));\n\t}\n\treader.tryRead(\"firstMonth\", _firstMonth);\n\treader.tryRead(\"lastMonth\", _lastMonth);\n\treader.tryRead(\"executionOdds\", _executionOdds);\n\treader.tryRead(\"minDifficulty\", _minDifficulty);\n\treader.tryRead(\"maxDifficulty\", _maxDifficulty);\n\treader.tryRead(\"minScore\", _minScore);\n\treader.tryRead(\"maxScore\", _maxScore);\n\treader.tryRead(\"minFunds\", _minFunds);\n\treader.tryRead(\"maxFunds\", _maxFunds);\n\treader.tryRead(\"missionVarName\", _missionVarName);\n\treader.tryRead(\"missionMarkerName\", _missionMarkerName);\n\t{\n\t\t// deprecated, remove after July 2022\n\t\treader.tryRead(\"missionMinRuns\", _counterMin);\n\t\treader.tryRead(\"missionMaxRuns\", _counterMax);\n\t}\n\treader.tryRead(\"counterMin\", _counterMin);\n\treader.tryRead(\"counterMax\", _counterMax);\n\n\treader.tryRead(\"researchTriggers\", _researchTriggers);\n\treader.tryRead(\"itemTriggers\", _itemTriggers);\n\treader.tryRead(\"facilityTriggers\", _facilityTriggers);\n\treader.tryRead(\"soldierTypeTriggers\", _soldierTypeTriggers);\n\treader.tryRead(\"xcomBaseInRegionTriggers\", _xcomBaseInRegionTriggers);\n\treader.tryRead(\"xcomBaseInCountryTriggers\", _xcomBaseInCountryTriggers);\n\treader.tryRead(\"pactCountryTriggers\", _pactCountryTriggers);\n\n\treader.tryRead(\"affectsGameProgression\", _affectsGameProgression);\n}\n\n/**\n * Chooses one of the available events for this command.\n * @param monthsPassed The number of months that have passed in the game world.\n * @return The string id of the event.\n */\nstd::string RuleEventScript::generate(const size_t monthsPassed) const\n{\n\tif (_eventWeights.empty())\n\t\treturn std::string();\n\n\tstd::vector<std::pair<size_t, WeightedOptions*> >::const_reverse_iterator rw;\n\trw = _eventWeights.rbegin();\n\twhile (monthsPassed < rw->first)\n\t\t++rw;\n\treturn rw->second->choose();\n}\n\n}\n"
  },
  {
    "path": "src/Mod/RuleEventScript.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2019 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include <vector>\n#include <map>\n#include \"../Engine/Yaml.h\"\n#include \"../Savegame/WeightedOptions.h\"\n\nnamespace OpenXcom\n{\n\nclass RuleEventScript\n{\nprivate:\n\tstd::string _type;\n\tstd::vector<std::string> _oneTimeSequentialEvents;\n\tWeightedOptions _oneTimeRandomEvents;\n\tstd::vector<std::pair<size_t, WeightedOptions*> > _eventWeights;\n\tint _firstMonth, _lastMonth, _executionOdds, _minDifficulty, _maxDifficulty;\n\tint _minScore, _maxScore;\n\tint64_t _minFunds, _maxFunds;\n\tstd::string _missionVarName, _missionMarkerName;\n\tint _counterMin, _counterMax;\n\n\tstd::map<std::string, bool> _researchTriggers;\n\tstd::map<std::string, bool> _itemTriggers;\n\tstd::map<std::string, bool> _facilityTriggers;\n\tstd::map<std::string, bool> _soldierTypeTriggers;\n\tstd::map<std::string, bool> _xcomBaseInRegionTriggers;\n\tstd::map<std::string, bool> _xcomBaseInCountryTriggers;\n\tstd::map<std::string, bool> _pactCountryTriggers;\n\n\tbool _affectsGameProgression;\n\npublic:\n\t/// Creates a blank RuleEventScript.\n\tRuleEventScript(const std::string &type);\n\t/// Cleans up the event script ruleset.\n\t~RuleEventScript();\n\t/// Loads an event script from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader);\n\t/// Gets the name of the script command.\n\tconst std::string &getType() const { return _type; }\n\t/// Gets the list of one time sequential events.\n\tconst std::vector<std::string> &getOneTimeSequentialEvents() const { return _oneTimeSequentialEvents; }\n\t/// Gets the list of one time random events (with weights).\n\tconst WeightedOptions &getOneTimeRandomEvents() const { return _oneTimeRandomEvents; }\n\t/// Gets the first month this command will run.\n\tint getFirstMonth() const { return _firstMonth; }\n\t/// Gets the last month this command will run.\n\tint getLastMonth() const { return _lastMonth; }\n\t/// Gets the odds of this command executing.\n\tint getExecutionOdds() const { return _executionOdds; }\n\t/// Gets the minimum difficulty for this command to run.\n\tint getMinDifficulty() const { return _minDifficulty; }\n\t/// Gets the maximum difficulty for this command to run.\n\tint getMaxDifficulty() const { return _maxDifficulty; }\n\t/// Gets the minimum score (from last month) for this command to run.\n\tint getMinScore() const { return _minScore; }\n\t/// Gets the maximum score (from last month) for this command to run.\n\tint getMaxScore() const { return _maxScore; }\n\t/// Gets the minimum funds (from current month) for this command to run.\n\tint64_t getMinFunds() const { return _minFunds; }\n\t/// Gets the maximum funds (from current month) for this command to run.\n\tint64_t getMaxFunds() const { return _maxFunds; }\n\t/// Gets the name of the mission script tracking variable.\n\tconst std::string& getMissionVarName() const { return _missionVarName; }\n\t/// Gets the name of the mission marker tracking variable.\n\tconst std::string& getMissionMarkerName() const { return _missionMarkerName; }\n\t/// Gets the minimum number of missions generated for this command to run.\n\tint getCounterMin() const { return _counterMin; }\n\t/// Gets the maximum number of missions generated for this command to run.\n\tint getCounterMax() const { return _counterMax; }\n\n\t/// Gets the research triggers that may apply to this command.\n\tconst std::map<std::string, bool> &getResearchTriggers() const { return _researchTriggers; }\n\t/// Gets the item triggers that may apply to this command.\n\tconst std::map<std::string, bool> &getItemTriggers() const { return _itemTriggers; }\n\t/// Gets the facility triggers that may apply to this command.\n\tconst std::map<std::string, bool> &getFacilityTriggers() const { return _facilityTriggers; }\n\t/// Gets the soldier type triggers that may apply to this command.\n\tconst std::map<std::string, bool> &getSoldierTypeTriggers() const { return _soldierTypeTriggers; }\n\t/// Gets the xcom base triggers that may apply to this command.\n\tconst std::map<std::string, bool> &getXcomBaseInRegionTriggers() const { return _xcomBaseInRegionTriggers; }\n\t/// Gets the xcom base triggers that may apply to this command.\n\tconst std::map<std::string, bool> &getXcomBaseInCountryTriggers() const { return _xcomBaseInCountryTriggers; }\n\t/// Gets the country pact triggers that may apply to this command.\n\tconst std::map<std::string, bool> &getPactCountryTriggers() const { return _pactCountryTriggers; }\n\n\t/// Gets a flag used for TechTreeViewer.\n\tbool getAffectsGameProgression() const { return _affectsGameProgression; }\n\t/// Generates an event based on the month.\n\tstd::string generate(const size_t monthsPassed) const;\n};\n\n}\n"
  },
  {
    "path": "src/Mod/RuleGlobe.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"RuleGlobe.h\"\n#include <SDL_endian.h>\n#include \"../Engine/Exception.h\"\n#include \"Polygon.h\"\n#include \"Polyline.h\"\n#include \"Texture.h\"\n#include \"../Engine/Palette.h\"\n#include \"../Geoscape/Globe.h\"\n#include \"../Engine/FileMap.h\"\n#include \"../fmath.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Creates a blank ruleset for globe contents.\n */\nRuleGlobe::RuleGlobe()\n{\n}\n\n/**\n *\n */\nRuleGlobe::~RuleGlobe()\n{\n\tfor (auto* polygon : _polygons)\n\t{\n\t\tdelete polygon;\n\t}\n\tfor (auto* polyline : _polylines)\n\t{\n\t\tdelete polyline;\n\t}\n\tfor (auto& pair : _textures)\n\t{\n\t\tdelete pair.second;\n\t}\n}\n\n/**\n * Loads the globe from a YAML file.\n * @param node YAML node.\n */\nvoid RuleGlobe::load(const YAML::YamlNodeReader& reader, Mod* mod)\n{\n\tif (const auto& data = reader[\"data\"])\n\t{\n\t\tfor (auto* polygon : _polygons)\n\t\t{\n\t\t\tdelete polygon;\n\t\t}\n\t\t_polygons.clear();\n\t\tloadDat(data.readVal<std::string>());\n\t}\n\tif (const auto& polygonsReader = reader[\"polygons\"])\n\t{\n\t\tfor (auto* polygon : _polygons)\n\t\t{\n\t\t\tdelete polygon;\n\t\t}\n\t\t_polygons.clear();\n\t\tfor (const auto& polygonReader : polygonsReader.children())\n\t\t{\n\t\t\tPolygon *polygon = new Polygon(3);\n\t\t\tpolygon->load(polygonReader);\n\t\t\t_polygons.push_back(polygon);\n\t\t}\n\t}\n\tif (const auto& polylinesReader = reader[\"polylines\"])\n\t{\n\t\tfor (auto* polyline : _polylines)\n\t\t{\n\t\t\tdelete polyline;\n\t\t}\n\t\t_polylines.clear();\n\t\tfor (const auto& polylineReader : polylinesReader.children())\n\t\t{\n\t\t\tPolyline *polyline = new Polyline(3);\n\t\t\tpolyline->load(polylineReader);\n\t\t\t_polylines.push_back(polyline);\n\t\t}\n\t}\n\tfor (const auto& textureReader : reader[\"textures\"].children())\n\t{\n\t\tif (textureReader[\"id\"])\n\t\t{\n\t\t\tint id = textureReader[\"id\"].readVal<int>();\n\t\t\tauto j = _textures.find(id);\n\t\t\tTexture *texture;\n\t\t\tif (j != _textures.end())\n\t\t\t{\n\t\t\t\ttexture = j->second;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\ttexture = new Texture(id);\n\t\t\t\t_textures[id] = texture;\n\t\t\t}\n\t\t\ttexture->load(textureReader, mod);\n\t\t}\n\t\telse if (textureReader[\"delete\"])\n\t\t{\n\t\t\tint id = textureReader[\"delete\"].readVal<int>();\n\t\t\tauto j = _textures.find(id);\n\t\t\tif (j != _textures.end())\n\t\t\t{\n\t\t\t\t_textures.erase(j);\n\t\t\t}\n\t\t}\n\t}\n\n\treader.tryRead(\"countryColor\", Globe::COUNTRY_LABEL_COLOR);\n\treader.tryRead(\"cityColor\", Globe::CITY_LABEL_COLOR);\n\treader.tryRead(\"baseColor\", Globe::BASE_LABEL_COLOR);\n\treader.tryRead(\"lineColor\", Globe::LINE_COLOR);\n\tif (reader[\"oceanPalette\"])\n\t{\n\t\tGlobe::OCEAN_COLOR = Palette::blockOffset(reader[\"oceanPalette\"].readVal(Globe::OCEAN_COLOR));\n\t}\n\treader.tryRead(\"oceanShading\", Globe::OCEAN_SHADING);\n}\n\n/**\n * Returns the list of polygons in the globe.\n * @return Pointer to the list of polygons.\n */\nstd::list<Polygon*> *RuleGlobe::getPolygons()\n{\n\treturn &_polygons;\n}\n\n/**\n * Returns the list of polylines in the globe.\n * @return Pointer to the list of polylines.\n */\nstd::list<Polyline*> *RuleGlobe::getPolylines()\n{\n\treturn &_polylines;\n}\n\n/**\n * Loads a series of map polar coordinates in X-Com format,\n * converts them and stores them in a set of polygons.\n * @param filename Filename of the DAT file.\n * @sa http://www.ufopaedia.org/index.php?title=WORLD.DAT\n */\nvoid RuleGlobe::loadDat(const std::string &filename)\n{\n\tauto mapFile = FileMap::getIStream(filename);\n\tshort value[10];\n\n\twhile (mapFile->read((char*)&value, sizeof(value)))\n\t{\n\t\tPolygon* poly;\n\t\tint points;\n\n\t\tfor (int i = 0; i < 10; ++i)\n\t\t{\n\t\t\tvalue[i] = SDL_SwapLE16(value[i]);\n\t\t}\n\n\t\tif (value[6] != -1)\n\t\t{\n\t\t\tpoints = 4;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tpoints = 3;\n\t\t}\n\t\tpoly = new Polygon(points);\n\n\t\tfor (int i = 0, j = 0; i < points; ++i)\n\t\t{\n\t\t\t// Correct X-Com degrees and convert to radians\n\t\t\tdouble lonRad = Xcom2Rad(value[j++]);\n\t\t\tdouble latRad = Xcom2Rad(value[j++]);\n\n\t\t\tpoly->setLongitude(i, lonRad);\n\t\t\tpoly->setLatitude(i, latRad);\n\t\t}\n\t\tpoly->setTexture(value[8]);\n\n\t\t_polygons.push_back(poly);\n\t}\n\n\tif (!mapFile->eof())\n\t{\n\t\tthrow Exception(\"Invalid globe map\");\n\t}\n}\n\n/**\n * Returns the rules for the specified texture.\n * @param id Texture ID.\n * @return Rules for the texture.\n */\nTexture *RuleGlobe::getTexture(int id) const\n{\n\tauto i = _textures.find(id);\n\tif (_textures.end() != i) return i->second; else return 0;\n}\n\n/**\n * Returns a list of all globe terrains associated with this deployment.\n * @param deployment Deployment name.\n * @return List of terrains.\n */\nstd::vector<std::string> RuleGlobe::getTerrains(const std::string &deployment) const\n{\n\tstd::vector<std::string> terrains;\n\tfor (auto& pair : _textures)\n\t{\n\t\tif ((deployment.empty() && pair.second->getDeployments().empty()) || pair.second->getDeployments().find(deployment) != pair.second->getDeployments().end())\n\t\t{\n\t\t\tfor (const auto& tc : *pair.second->getTerrain())\n\t\t\t{\n\t\t\t\tterrains.push_back(tc.name);\n\t\t\t}\n\t\t}\n\t}\n\treturn terrains;\n}\n\n}\n"
  },
  {
    "path": "src/Mod/RuleGlobe.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <list>\n#include <string>\n#include \"../Engine/Yaml.h\"\n\nnamespace OpenXcom\n{\n\nclass Polygon;\nclass Polyline;\nclass Texture;\nclass Mod;\n\n/**\n * Represents the contents of the Geoscape globe,\n * such as world polygons, polylines, etc.\n * @sa Globe\n */\nclass RuleGlobe\n{\nprivate:\n\tstd::list<Polygon*> _polygons;\n\tstd::list<Polyline*> _polylines;\n\tstd::map<int, Texture*> _textures;\npublic:\n\t/// Creates a blank globe ruleset.\n\tRuleGlobe();\n\t/// Cleans up the globe ruleset.\n\t~RuleGlobe();\n\t/// Loads the globe from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader, Mod* mod);\n\t/// Gets the list of world polygons.\n\tstd::list<Polygon*> *getPolygons();\n\t/// Gets the list of world polylines.\n\tstd::list<Polyline*> *getPolylines();\n\t/// Loads a set of polygons from a DAT file.\n\tvoid loadDat(const std::string &filename);\n\t/// Gets a specific world texture.\n\tTexture *getTexture(int id) const;\n\t/// Gets all the terrains for a specific deployment.\n\tstd::vector<std::string> getTerrains(const std::string &deployment) const;\n\n\t/// Raw data.\n\tconst std::map<int, Texture*> &getTexturesRaw() const { return _textures; }\n};\n\n}\n"
  },
  {
    "path": "src/Mod/RuleInterface.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"RuleInterface.h\"\n#include \"Mod.h\"\n#include <climits>\n#include \"../Savegame/SavedGame.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Creates a blank ruleset for a certain\n * type of interface, containing an index of elements that make it up.\n * @param type String defining the type.\n */\nRuleInterface::RuleInterface(const std::string & type) : _type(type), _sound(-1)\n{\n}\n\nRuleInterface::~RuleInterface()\n{\n}\n\n/**\n * Loads the elements from a YAML file.\n * @param node YAML node.\n */\nvoid RuleInterface::load(const YAML::YamlNodeReader& reader, Mod *mod)\n{\n\tif (const auto& parent = reader[\"refNode\"])\n\t{\n\t\tload(parent, mod);\n\t}\n\n\treader.tryRead(\"palette\", _palette);\n\treader.tryRead(\"parent\", _parent);\n\treader.tryRead(\"backgroundImage\", _backgroundImage);\n\treader.tryRead(\"altBackgroundImage\", _altBackgroundImage);\n\treader.tryRead(\"upgBackgroundImage\", _upgBackgroundImage);\n\treader.tryRead(\"music\", _music);\n\tmod->loadSoundOffset(_type, _sound, reader[\"sound\"], \"GEO.CAT\");\n\tfor (const auto& elementReader : reader[\"elements\"].children())\n\t{\n\t\tElement& element = _elements[elementReader[\"id\"].readVal<std::string>()];\n\t\tif (elementReader[\"size\"])\n\t\t{\n\t\t\tstd::pair<int, int> pos = elementReader[\"size\"].readVal<std::pair<int, int> >();\n\t\t\telement.w = pos.first;\n\t\t\telement.h = pos.second;\n\t\t}\n\t\tif (elementReader[\"pos\"])\n\t\t{\n\t\t\tstd::pair<int, int> pos = elementReader[\"pos\"].readVal<std::pair<int, int> >();\n\t\t\telement.x = pos.first;\n\t\t\telement.y = pos.second;\n\t\t}\n\t\telementReader.tryRead(\"color\", element.color);\n\t\telementReader.tryRead(\"color2\", element.color2);\n\t\telementReader.tryRead(\"border\", element.border);\n\t\telementReader.tryRead(\"custom\", element.custom);\n\t\telementReader.tryRead(\"TFTDMode\", element.TFTDMode);\n\t}\n}\n\n/**\n * Retrieves info on an element\n * @param id String defining the element.\n */\nconst Element *RuleInterface::getElementOptional(const std::string &id) const\n{\n\tauto i = _elements.find(id);\n\tif (_elements.end() != i) return &i->second; else return 0;\n}\n\n/**\n * Retrieves info on an element\n * @param id String defining the element.\n */\nconst Element *RuleInterface::getElement(const std::string &id) const\n{\n\tauto i = getElementOptional(id);\n\tif (i == nullptr)\n\t{\n\t\tthrow Exception(\"Missing interface Element '\" + id + \"' in '\" + _type + \"'\");\n\t}\n\treturn i;\n}\n\nconst std::string &RuleInterface::getPalette() const\n{\n\treturn _palette;\n}\n\nconst std::string &RuleInterface::getParent() const\n{\n\treturn _parent;\n}\n\nconst std::string &RuleInterface::getBackgroundImage(const Mod* mod, const SavedGame* save) const\n{\n\tif (save)\n\t{\n\t\tfor (auto& pair : _upgBackgroundImage)\n\t\t{\n\t\t\tauto r = mod->getResearch(pair.first, false);\n\t\t\tif (r && save->isResearched(r))\n\t\t\t{\n\t\t\t\treturn pair.second;\n\t\t\t}\n\t\t}\n\t}\n\treturn _backgroundImage;\n}\n\nconst std::string &RuleInterface::getAltBackgroundImage() const\n{\n\treturn _altBackgroundImage;\n}\n\nconst std::string &RuleInterface::getMusic() const\n{\n\treturn _music;\n}\n\nint RuleInterface::getSound() const\n{\n\treturn _sound;\n}\n\n}\n"
  },
  {
    "path": "src/Mod/RuleInterface.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include <map>\n#include \"../Engine/Yaml.h\"\n\nnamespace OpenXcom\n{\n\nclass Mod;\nclass SavedGame;\n\nstruct Element\n{\n\t/// basic rect info.\n\tint x = INT_MAX;\n\tint y = INT_MAX;\n\tint w = INT_MAX;\n\tint h = INT_MAX;\n\n\t/// 3 colors\n\tint color = INT_MAX;\n\tint color2 = INT_MAX;\n\tint border = INT_MAX;\n\n\t/// Custom value\n\tint custom = 0;\n\n\t/// defines inversion behaviour\n\tbool TFTDMode = false;\n};\n\nclass RuleInterface\n{\nprivate:\n\tstd::string _type;\n\tstd::string _palette;\n\tstd::string _parent;\n\tstd::string _backgroundImage;\n\tstd::string _altBackgroundImage;\n\tstd::string _music;\n\tint _sound;\n\tstd::vector< std::pair<std::string, std::string> > _upgBackgroundImage;\n\n\tstd::map <std::string, Element> _elements;\npublic:\n\t/// Constructor.\n\tRuleInterface(const std::string & type);\n\t/// Destructor.\n\t~RuleInterface();\n\t/// Load from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader, Mod *mod);\n\t/// Get an element. Can be `nullptr`.\n\tconst Element *getElementOptional(const std::string &id) const;\n\t/// Get an element.\n\tconst Element *getElement(const std::string &id) const;\n\t/// Get palette.\n\tconst std::string &getPalette() const;\n\t/// Get parent interface rule.\n\tconst std::string &getParent() const;\n\t/// Get background image.\n\tconst std::string &getBackgroundImage(const Mod* mod, const SavedGame* save) const;\n\t/// Get alternative background image (for battlescape theme).\n\tconst std::string &getAltBackgroundImage() const;\n\t/// Get music.\n\tconst std::string &getMusic() const;\n\t/// Get sound.\n\tint getSound() const;\n};\n\n}\n"
  },
  {
    "path": "src/Mod/RuleInventory.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"RuleInventory.h\"\n#include <cmath>\n#include \"RuleItem.h\"\n#include \"../Engine/Screen.h\"\n#include \"../Engine/ScriptBind.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Creates a blank ruleset for a certain\n * type of inventory section.\n * @param id String defining the id.\n */\nRuleInventory::RuleInventory(const std::string &id, int listOrder): _id(id), _x(0), _y(0), _type(INV_SLOT), _listOrder(listOrder), _hand(0)\n{\n}\n\nRuleInventory::~RuleInventory()\n{\n}\n\n/**\n * Loads the inventory from a YAML file.\n * @param node YAML node.\n * @param listOrder The list weight for this inventory.\n */\nvoid RuleInventory::load(const YAML::YamlNodeReader& reader)\n{\n\tif (const auto& parent = reader[\"refNode\"])\n\t{\n\t\tload(parent);\n\t}\n\n\treader.tryRead(\"x\", _x);\n\treader.tryRead(\"y\", _y);\n\treader.tryRead(\"type\", _type);\n\treader.tryRead(\"slots\", _slots);\n\treader.tryRead(\"costs\", _costs);\n\treader.tryRead(\"listOrder\", _listOrder);\n\tif (_id == \"STR_RIGHT_HAND\")\n\t{\n\t\t_hand = 2;\n\t}\n\telse if (_id == \"STR_LEFT_HAND\")\n\t{\n\t\t_hand = 1;\n\t}\n\telse\n\t{\n\t\t_hand = 0;\n\t}\n}\n\n/**\n * Gets the language string that names\n * this inventory section. Each section has a unique name.\n * @return The section name.\n */\nconst std::string& RuleInventory::getId() const\n{\n\treturn _id;\n}\n\n/**\n * Gets the X position of the inventory section on the screen.\n * @return The X position in pixels.\n */\nint RuleInventory::getX() const\n{\n\treturn _x;\n}\n\n/**\n * Gets the Y position of the inventory section on the screen.\n * @return The Y position in pixels.\n */\nint RuleInventory::getY() const\n{\n\treturn _y;\n}\n\n/**\n * Gets the type of the inventory section.\n * Slot-based contain a limited number of slots.\n * Hands only contain one slot but can hold any item.\n * Ground can hold infinite items but don't attach to soldiers.\n * @return The inventory type.\n */\nInventoryType RuleInventory::getType() const\n{\n\treturn _type;\n}\n\n/**\n * Gets if this slot is right hand.\n * @return This is right hand.\n */\nbool RuleInventory::isRightHand() const\n{\n\treturn _hand == 2;\n}\n\n/**\n * Gets if this slot is left hand.\n * @return This is wrong hand.\n */\nbool RuleInventory::isLeftHand() const\n{\n\treturn _hand == 1;\n}\n\n/**\n * Gets all the slots in the inventory section.\n * @return The list of slots.\n */\nconst std::vector<struct RuleSlot> *RuleInventory::getSlots() const\n{\n\treturn &_slots;\n}\n\n/**\n * Gets the slot located in the specified mouse position.\n * @param x Mouse X position. Returns the slot's X position.\n * @param y Mouse Y position. Returns the slot's Y position.\n * @return True if there's a slot there.\n */\nbool RuleInventory::checkSlotInPosition(int *x, int *y) const\n{\n\tint mouseX = *x, mouseY = *y;\n\tif (_type == INV_HAND)\n\t{\n\t\tfor (int xx = 0; xx < HAND_W; ++xx)\n\t\t{\n\t\t\tfor (int yy = 0; yy < HAND_H; ++yy)\n\t\t\t{\n\t\t\t\tif (mouseX >= _x + xx * SLOT_W && mouseX < _x + (xx + 1) * SLOT_W &&\n\t\t\t\t\tmouseY >= _y + yy * SLOT_H && mouseY < _y + (yy + 1) * SLOT_H)\n\t\t\t\t{\n\t\t\t\t\t*x = 0;\n\t\t\t\t\t*y = 0;\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\telse if (_type == INV_GROUND)\n\t{\n\t\tif (mouseX >= _x && mouseX < Screen::ORIGINAL_WIDTH && mouseY >= _y && mouseY < Screen::ORIGINAL_HEIGHT)\n\t\t{\n\t\t\t*x = (int)floor(double(mouseX - _x) / SLOT_W);\n\t\t\t*y = (int)floor(double(mouseY - _y) / SLOT_H);\n\t\t\treturn true;\n\t\t}\n\t}\n\telse\n\t{\n\t\tfor (const auto& coord : _slots)\n\t\t{\n\t\t\tif (mouseX >= _x + coord.x * SLOT_W && mouseX < _x + (coord.x + 1) * SLOT_W &&\n\t\t\t\tmouseY >= _y + coord.y * SLOT_H && mouseY < _y + (coord.y + 1) * SLOT_H)\n\t\t\t{\n\t\t\t\t*x = coord.x;\n\t\t\t\t*y = coord.y;\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Checks if an item completely fits when\n * placed in a certain slot.\n * @param item Pointer to item ruleset.\n * @param x Slot X position.\n * @param y Slot Y position.\n * @return True if there's a slot there.\n */\nbool RuleInventory::fitItemInSlot(const RuleItem *item, int x, int y) const\n{\n\tif (_type == INV_HAND)\n\t{\n\t\treturn true;\n\t}\n\telse if (_type == INV_GROUND)\n\t{\n\t\tint width = (320 - _x) / SLOT_W;\n\t\tint height = (200 - _y) / SLOT_H;\n\t\tint xOffset = 0;\n\t\twhile (x >= xOffset + width)\n\t\t\txOffset += width;\n\t\tfor (int xx = x; xx < x + item->getInventoryWidth(); ++xx)\n\t\t{\n\t\t\tfor (int yy = y; yy < y + item->getInventoryHeight(); ++yy)\n\t\t\t{\n\t\t\t\tif (!(xx >= xOffset && xx < xOffset + width && yy >= 0 && yy < height))\n\t\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\telse\n\t{\n\t\tint totalSlots = item->getInventoryWidth() * item->getInventoryHeight();\n\t\tint foundSlots = 0;\n\t\tfor (const auto& coord : _slots)\n\t\t{\n\t\t\tif (foundSlots >= totalSlots)\n\t\t\t{\n\t\t\t\tbreak; // loop finished\n\t\t\t}\n\t\t\tif (coord.x >= x && coord.x < x + item->getInventoryWidth() &&\n\t\t\t\tcoord.y >= y && coord.y < y + item->getInventoryHeight())\n\t\t\t{\n\t\t\t\tfoundSlots++;\n\t\t\t}\n\t\t}\n\t\treturn (foundSlots == totalSlots);\n\t}\n}\n\n/**\n * Gets the time unit cost to place an item in another section.\n * @param slot The new section id.\n * @return The time unit cost.\n */\nint RuleInventory::getCost(const RuleInventory* slot) const\n{\n\tif (slot == this)\n\t\treturn 0;\n\treturn _costs.find(slot->getId())->second;\n}\n\nint RuleInventory::getListOrder() const\n{\n\treturn _listOrder;\n}\n\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tScript binding\n////////////////////////////////////////////////////////////\n\nnamespace\n{\n\nvoid getIdScript(const RuleInventory* bu, ScriptText& txt)\n{\n\tif (bu)\n\t{\n\t\ttxt = { bu->getId().c_str() };\n\t\treturn;\n\t}\n\telse\n\t{\n\t\ttxt = ScriptText::empty;\n\t}\n}\n\nvoid getTypeScript(const RuleInventory* bu, int& type)\n{\n\tif (bu)\n\t{\n\t\ttype = (int)bu->getType();\n\t}\n\telse\n\t{\n\t\ttype = 0;\n\t}\n}\n\nstd::string debugDisplayScript(const RuleInventory* bu)\n{\n\tif (bu)\n\t{\n\t\tstd::string s;\n\t\ts += RuleInventory::ScriptName;\n\t\ts += \"(id: \\\"\";\n\t\ts += bu->getId();\n\t\ts += \"\\\")\";\n\t\treturn s;\n\t}\n\telse\n\t{\n\t\treturn \"null\";\n\t}\n}\n\n} // namespace\n\n\n\n/**\n * Register RuleInventory in script parser.\n * @param parser Script parser.\n */\nvoid RuleInventory::ScriptRegister(ScriptParserBase* parser)\n{\n\tBind<RuleInventory> bu = { parser };\n\n\tbu.add<&getIdScript>(\"getId\");\n\tbu.add<&getTypeScript>(\"getType\");\n\tbu.add<&RuleInventory::isRightHand>(\"isRightHand\");\n\tbu.add<&RuleInventory::isLeftHand>(\"isLeftHand\");\n\tbu.add<&RuleInventory::getCost>(\"getMoveToCost\", \"Cost of moving item from slot in first arg to slot from last arg\");\n\n\tbu.addDebugDisplay<&debugDisplayScript>();\n\n\tbu.addCustomConst(\"INV_GROUND\", INV_GROUND);\n\tbu.addCustomConst(\"INV_SLOT\", INV_SLOT);\n\tbu.addCustomConst(\"INV_HAND\", INV_HAND);\n}\n\n// helper overloads for deserialization-only\nbool read(ryml::ConstNodeRef const& n, RuleSlot* val)\n{\n\tYAML::YamlNodeReader reader(n);\n\tval->x = reader[0].readVal<int>();\n\tval->y = reader[1].readVal<int>();\n\treturn true;\n}\n\n}\n"
  },
  {
    "path": "src/Mod/RuleInventory.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include <vector>\n#include <map>\n#include \"../Engine/Yaml.h\"\n\nnamespace OpenXcom\n{\n\nstruct RuleSlot\n{\n\tint x, y;\n};\n\nenum InventoryType { INV_SLOT, INV_HAND, INV_GROUND };\n\nclass RuleItem;\nclass ScriptParserBase;\n\n/**\n * Represents a specific section of the inventory,\n * containing information like available slots and\n * screen position.\n */\nclass RuleInventory\n{\nprivate:\n\tstd::string _id;\n\tint _x, _y;\n\tInventoryType _type;\n\tstd::vector<RuleSlot> _slots;\n\tstd::map<std::string, int> _costs;\n\tint _listOrder;\n\tint _hand;\npublic:\n\tstatic const int SLOT_W = 16;\n\tstatic const int SLOT_H = 16;\n\tstatic const int HAND_W = 2;\n\tstatic const int HAND_H = 3;\n\tstatic const int PAPERDOLL_W = 40;\n\tstatic const int PAPERDOLL_H = 70;\n\tstatic const int PAPERDOLL_X = 60;\n\tstatic const int PAPERDOLL_Y = 65;\n\n\t/// Name of class used in script.\n\tstatic constexpr const char *ScriptName = \"RuleInventory\";\n\t/// Register all useful function used by script.\n\tstatic void ScriptRegister(ScriptParserBase* parser);\n\n\t/// Creates a blank inventory ruleset.\n\tRuleInventory(const std::string &id, int listOrder);\n\t/// Cleans up the inventory ruleset.\n\t~RuleInventory();\n\t/// Loads inventory data from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader);\n\t/// Gets the inventory's id.\n\tconst std::string& getId() const;\n\t/// Gets the X position of the inventory.\n\tint getX() const;\n\t/// Gets the Y position of the inventory.\n\tint getY() const;\n\t/// Gets the inventory type.\n\tInventoryType getType() const;\n\t/// Gets if this slot is right hand;\n\tbool isRightHand() const;\n\t/// Gets if this slot is left hand;\n\tbool isLeftHand() const;\n\t/// Gets all the slots in the inventory.\n\tconst std::vector<struct RuleSlot> *getSlots() const;\n\t/// Checks for a slot in a certain position.\n\tbool checkSlotInPosition(int *x, int *y) const;\n\t/// Checks if an item fits in a slot.\n\tbool fitItemInSlot(const RuleItem *item, int x, int y) const;\n\t/// Gets a certain cost in the inventory.\n\tint getCost(const RuleInventory *slot) const;\n\tint getListOrder() const;\n};\n\n// helper overloads for deserialization-only\nbool read(ryml::ConstNodeRef const& n, RuleSlot* val);\n\n}\n"
  },
  {
    "path": "src/Mod/RuleItem.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <algorithm>\n#include \"LoadYaml.h\"\n#include \"Mod.h\"\n#include \"Armor.h\"\n#include \"Unit.h\"\n#include \"RuleItem.h\"\n#include \"RuleItemCategory.h\"\n#include \"RuleInventory.h\"\n#include \"RuleDamageType.h\"\n#include \"RuleSoldier.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/BattleUnit.h\"\n#include \"../Engine/Exception.h\"\n#include \"../Engine/Collections.h\"\n#include \"../Engine/SurfaceSet.h\"\n#include \"../Engine/Surface.h\"\n#include \"../Engine/ScriptBind.h\"\n#include \"../Engine/RNG.h\"\n#include \"../Battlescape/BattlescapeGame.h\"\n\nnamespace OpenXcom\n{\n\nnamespace\n{\n\n/**\n * Update `attacker` from `weapon_item`.\n */\nvoid UpdateAttacker(BattleActionAttack& attack)\n{\n\tif (attack.weapon_item && !attack.attacker)\n\t{\n\t\tconst BattleType battleType = attack.weapon_item->getRules()->getBattleType();\n\t\tif (battleType == BT_PROXIMITYGRENADE || battleType == BT_GRENADE)\n\t\t{\n\t\t\tBattleUnit* owner = attack.weapon_item->getPreviousOwner();\n\t\t\tif (owner)\n\t\t\t{\n\t\t\t\tattack.attacker = owner;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Update `damage_item` from `weapon_item`.\n */\nvoid UpdateAmmo(BattleActionAttack& attack)\n{\n\tif (attack.weapon_item && !attack.damage_item)\n\t{\n\t\tconst BattleType battleType = attack.weapon_item->getRules()->getBattleType();\n\t\tif (battleType == BT_PROXIMITYGRENADE || battleType == BT_GRENADE || battleType == BT_PSIAMP)\n\t\t{\n\t\t\tattack.damage_item = attack.weapon_item;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tattack.damage_item = attack.weapon_item->getAmmoForAction(attack.type);\n\t\t}\n\t}\n}\n\n/**\n * Update grenade `damage_item` from `weapon_item`.\n */\nvoid UpdateGrenade(BattleActionAttack& attack)\n{\n\tif (attack.weapon_item && !attack.damage_item)\n\t{\n\t\tconst BattleType battleType = attack.weapon_item->getRules()->getBattleType();\n\t\tif (battleType == BT_PROXIMITYGRENADE || battleType == BT_GRENADE)\n\t\t{\n\t\t\tattack.damage_item = attack.weapon_item;\n\t\t}\n\t}\n}\n\n}\n\n/**\n * Generate ActionAttack before shooting, this means we can get the ammo from the weapon.\n * @param action BattleCost of attack.\n * @return All attack action data.\n */\nBattleActionAttack BattleActionAttack::GetBeforeShoot(const BattleActionCost &action)\n{\n\treturn GetBeforeShoot(action.type, action.actor, action.weapon, action.skillRules);\n}\n\nBattleActionAttack BattleActionAttack::GetBeforeShoot(BattleActionType type, BattleUnit *unit, BattleItem *wepon, const RuleSkill *skill)\n{\n\tauto attack = BattleActionAttack{ type, unit, wepon };\n\tUpdateAttacker(attack);\n\tUpdateAmmo(attack);\n\tattack.skill_rules = skill;\n\treturn attack;\n}\n\n/**\n * Generate ActionAttack after shooting, the ammo can be already spent and unloaded from the weapon.\n * @param action BattleCost of attack.\n * @param ammo Ammo used to shoot/attack.\n * @return All attack action data.\n */\nBattleActionAttack BattleActionAttack::GetAferShoot(const BattleActionCost &action, BattleItem *ammo)\n{\n\treturn GetAferShoot(action.type, action.actor, action.weapon, ammo, action.skillRules);\n}\n\nBattleActionAttack BattleActionAttack::GetAferShoot(BattleActionType type, BattleUnit *unit, BattleItem *wepon, BattleItem *ammo, const RuleSkill *skill)\n{\n\tauto attack = BattleActionAttack{ type, unit, wepon };\n\tUpdateAttacker(attack);\n\tattack.damage_item = ammo;\n\tattack.skill_rules = skill;\n\tUpdateGrenade(attack);\n\treturn attack;\n}\n\n\n\nconst float VexelsToTiles = 0.0625f;\nconst float TilesToVexels = 16.0f;\n\n/**\n * Creates a blank ruleset for a certain type of item.\n * @param type String defining the type.\n */\nRuleItem::RuleItem(const std::string &type, int listOrder) :\n\t_type(type), _name(type), _vehicleUnit(nullptr), _vehicleFixedAmmoSlot(0), _size(0.0),\n\t_monthlyBuyLimit(0), _costBuy(0), _costSell(0), _transferTime(24), _weight(3), _throwRange(200), _underwaterThrowRange(200),\n\t_throwDropoffRange(99), _underwaterThrowDropoffRange(99), _throwDropoff(5),\n\t_bigSprite(-1), _floorSprite(-1), _handSprite(120), _bulletSprite(-1), _specialIconSprite(-1),\n\t_hitAnimation(0), _hitAnimFrames(-1), _hitMissAnimation(-1), _hitMissAnimFrames(-1),\n\t_meleeAnimation(0), _meleeAnimFrames(-1), _meleeMissAnimation(-1), _meleeMissAnimFrames(-1),\n\t_psiAnimation(-1), _psiAnimFrames(-1), _psiMissAnimation(-1), _psiMissAnimFrames(-1),\n\t_power(0), _powerForAnimation(0), _hidePower(false), _ignoreAmmoPower(false), _powerRangeReduction(0), _powerRangeThreshold(0),\n\t_damageTypeSet(false), _meleeTypeSet(false),\n\t_accuracyUse(0), _accuracyMind(0), _accuracyPanic(20), _accuracyThrow(100), _accuracyCloseQuarters(-1),\n\t_noLOSAccuracyPenalty(-1),\n\t_explodeInventory(-1),\n\t_costUse(25), _costMind({}, {}), _costPanic({}, {}), _costThrow(25), _costPrime(50), _costUnprime(25),\n\t_clipSize(0), _specialChance(100), _tuLoad{ }, _tuUnload{ },\n\t_battleType(BT_NONE), _fuseType(BFT_NONE), _fuseTriggerEvents{ }, _hiddenOnMinimap(false),\n\t_painKillerActionName(\"STR_PAIN_KILLER\"), _stimulantActionName(\"STR_STIMULANT\"), _healActionName(\"STR_HEAL\"),\n\t_medikitActionName(\"STR_USE_MEDI_KIT\"),\n\t_psiAttackName(), _primeActionName(\"STR_PRIME_GRENADE\"), _unprimeActionName(),\n\t_primeActionMessage(\"STR_GRENADE_IS_ACTIVATED\"), _unprimeActionMessage(\"STR_GRENADE_IS_DEACTIVATED\"),\n\t_twoHanded(false), _blockBothHands(false), _fixedWeapon(false), _fixedWeaponShow(false), _isConsumable(false), _isFireExtinguisher(false), _isAmmoRechargeable(false),\n\t_specialUseEmptyHand(false), _specialUseEmptyHandShow(false),\n\t_defaultInvSlotX(0), _defaultInvSlotY(0), _waypoints(0), _invWidth(1), _invHeight(1),\n\t_painKiller(0), _heal(0), _stimulant(0), _medikitType(BMT_NORMAL), _medikitTargetSelf(false), _medikitTargetImmune(false), _medikitTargetMatrix(63),\n\t_woundRecovery(0), _healthRecovery(0), _stunRecovery(0), _energyRecovery(0), _manaRecovery(0), _moraleRecovery(0), _painKillerRecovery(1.0f),\n\t_recoveryPoints(0), _armor(20), _turretType(-1),\n\t_aiUseDelay(-1), _aiMeleeHitCount(25),\n\t_recover(true), _recoverCorpse(true), _ignoreInBaseDefense(false), _ignoreInCraftEquip(true), _liveAlien(false),\n\t_liveAlienPrisonType(0), _attraction(0), _flatUse(0, 1), _flatThrow(0, 1), _flatPrime(0, 1), _flatUnprime(0, 1), _arcingShot(false),\n\t_experienceTrainingMode(ETM_DEFAULT), _manaExperience(0), _loadOrder(0), _listOrder(listOrder),\n\t_maxRange(200), _minRange(0), _dropoff(2), _bulletSpeed(0), _explosionSpeed(0), _shotgunPellets(0), _shotgunBehaviorType(0), _shotgunSpread(100), _shotgunChoke(100),\n\t_spawnUnitFaction(FACTION_NONE), _zombieUnitFaction(FACTION_HOSTILE),\n\t_targetMatrix(7), _convertToCivilian(false),\n\t_LOSRequired(false), _underwaterOnly(false), _landOnly(false), _psiReqiured(false), _manaRequired(false),\n\t_meleePower(0), _specialType(-1), _vaporColor(-1), _vaporDensity(0), _vaporProbability(15),\n\t_vaporColorSurface(-1), _vaporDensitySurface(0), _vaporProbabilitySurface(15),\n\t_kneelBonus(-1), _oneHandedPenalty(-1),\n\t_monthlySalary(0), _monthlyMaintenance(0),\n\t_sprayWaypoints(0)\n{\n\t_accuracyMulti.setFiring();\n\t_meleeMulti.setMelee();\n\t_throwMulti.setThrowing();\n\t_closeQuartersMulti.setCloseQuarters();\n\n\tfor (auto& load : _tuLoad)\n\t{\n\t\tload = 15;\n\t}\n\tfor (auto& unload : _tuUnload)\n\t{\n\t\tunload = 8;\n\t}\n\n\t_confAimed.range = 200;\n\t_confSnap.range = 15;\n\t_confAuto.range = 7;\n\n\t_confAimed.cost = { 0 };\n\t_confSnap.cost = { 0, {} };\n\t_confAuto.cost = { 0, {} };\n\t_confMelee.cost = { 0 };\n\n\t_confAimed.flat = { {}, {} };\n\t_confSnap.flat = { {}, {} };\n\t_confAuto.flat = { {}, {} };\n\t_confMelee.flat = { {}, {} };\n\n\t_confAimed.name = \"STR_AIMED_SHOT\";\n\t_confSnap.name = \"STR_SNAP_SHOT\";\n\t_confAuto.name = \"STR_AUTO_SHOT\";\n\n\t_confAuto.shots = 3;\n\n\t_customItemPreviewIndex.push_back(Mod::NO_SURFACE);\n}\n\n/**\n *\n */\nRuleItem::~RuleItem()\n{\n}\n\n/**\n * Load ammo slot with checking correct range.\n * @param result\n * @param node\n * @param parentName\n */\nvoid RuleItem::loadAmmoSlotChecked(int& result, const YAML::YamlNodeReader& reader, const std::string& parentName)\n{\n\tif (reader)\n\t{\n\t\tint s = reader.readVal(result);\n\t\tif (s < AmmoSlotSelfUse || s >= AmmoSlotMax)\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"ammoSlot outside of allowed range in '\" << parentName << \"'\";\n\t\t}\n\t\telse\n\t\t{\n\t\t\tresult = s;\n\t\t}\n\t}\n}\n\n/**\n * Load RuleItemAction from yaml.\n * @param a Item use config.\n * @param node YAML node.\n * @param name Name of action type.\n */\nvoid RuleItem::loadConfAction(RuleItemAction& a, const YAML::YamlNodeReader& reader, const std::string& name) const\n{\n\tif (const auto& conf = reader[ryml::to_csubstr(\"conf\" + name)])\n\t{\n\n\t\tconf.tryRead(\"shots\", a.shots);\n\t\tconf.tryRead(\"spendPerShot\", a.spendPerShot);\n\t\tconf.tryRead(\"followProjectiles\", a.followProjectiles);\n\t\tconf.tryRead(\"name\", a.name);\n\t\tconf.tryRead(\"shortName\", a.shortName);\n\t\tloadAmmoSlotChecked(a.ammoSlot, conf[\"ammoSlot\"], _name);\n\t\tloadIntNullable(a.ammoZombieUnitChanceOverride, conf[\"ammoZombieUnitChanceOverride\"]);\n\t\tloadIntNullable(a.ammoSpawnUnitChanceOverride, conf[\"ammoSpawnUnitChanceOverride\"]);\n\t\tloadIntNullable(a.ammoSpawnItemChanceOverride, conf[\"ammoSpawnItemChanceOverride\"]);\n\t\tconf.tryRead(\"arcing\", a.arcing);\n\t}\n}\n\n/**\n * Load RuleItemFuseTrigger from yaml.\n */\nvoid RuleItem::loadConfFuse(RuleItemFuseTrigger& a, const YAML::YamlNodeReader& reader, const std::string& name) const\n{\n\tif (const auto& conf = reader[ryml::to_csubstr(name)])\n\t{\n\t\tloadBool(a.defaultBehavior, conf[\"defaultBehavior\"]);\n\t\tloadBool(a.throwTrigger, conf[\"throwTrigger\"]);\n\t\tloadBool(a.throwExplode, conf[\"throwExplode\"]);\n\t\tloadBool(a.proximityTrigger, conf[\"proximityTrigger\"]);\n\t\tloadBool(a.proximityExplode, conf[\"proximityExplode\"]);\n\t}\n}\n\n/**\n* Updates item categories based on replacement rules.\n* @param replacementRules The list replacement rules.\n*/\nvoid RuleItem::updateCategories(std::map<std::string, std::string> *replacementRules)\n{\n\tfor (const auto& pair : *replacementRules)\n\t{\n\t\tstd::replace(_categories.begin(), _categories.end(), pair.first, pair.second);\n\t}\n}\n\n/**\n * Loads the item from a YAML file.\n * @param node YAML node.\n * @param mod Mod for the item.\n * @param listOrder The list weight for this item.\n */\nvoid RuleItem::load(const YAML::YamlNodeReader& node, Mod *mod, const ModScript& parsers)\n{\n\tconst auto& reader = node.useIndex();\n\tif (const auto& parent = reader[\"refNode\"])\n\t{\n\t\tload(parent, mod, parsers);\n\t}\n\n\treader.tryRead(\"ufopediaType\", _ufopediaType);\n\treader.tryRead(\"name\", _name);\n\treader.tryRead(\"nameAsAmmo\", _nameAsAmmo);\n\n\t//requires\n\treader.tryRead(\"requiresBuyCountry\", _requiresBuyCountry);\n\tmod->loadUnorderedNames(_type, _requiresName, reader[\"requires\"]);\n\tmod->loadUnorderedNames(_type, _requiresBuyName, reader[\"requiresBuy\"]);\n\tmod->loadBaseFunction(_type, _requiresBuyBaseFunc, reader[\"requiresBuyBaseFunc\"]);\n\n\n\tmod->loadUnorderedNamesToInt(_type, _recoveryDividers, reader[\"recoveryDividers\"]);\n\treader.tryRead(\"recoveryTransformations\", _recoveryTransformationsName);\n\tmod->loadUnorderedNames(_type, _categories, reader[\"categories\"]);\n\n\treader.tryRead(\"vehicleFixedAmmoSlot\", _vehicleFixedAmmoSlot);\n\treader.tryRead(\"size\", _size);\n\treader.tryRead(\"monthlyBuyLimit\", _monthlyBuyLimit);\n\treader.tryRead(\"monthlyBuyLimitMessage\", _monthlyBuyLimitMessage);\n\treader.tryRead(\"costBuy\", _costBuy);\n\treader.tryRead(\"costSell\", _costSell);\n\treader.tryRead(\"transferTime\", _transferTime);\n\treader.tryRead(\"weight\", _weight);\n\treader.tryRead(\"throwRange\", _throwRange);\n\treader.tryRead(\"underwaterThrowRange\", _underwaterThrowRange);\n\treader.tryRead(\"throwDropoffRange\", _throwDropoffRange);\n\treader.tryRead(\"underwaterThrowDropoffRange\", _underwaterThrowDropoffRange);\n\treader.tryRead(\"throwDropoff\", _throwDropoff);\n\n\tmod->loadSpriteOffset(_type, _bigSprite, reader[\"bigSprite\"], \"BIGOBS.PCK\");\n\tmod->loadSpriteOffset(_type, _floorSprite, reader[\"floorSprite\"], \"FLOOROB.PCK\");\n\tmod->loadSpriteOffset(_type, _handSprite, reader[\"handSprite\"], \"HANDOB.PCK\");\n\t// Projectiles: 0-384 entries ((105*33) / (3*3)) (35 sprites per projectile(0-34), 11 projectiles (0-10))\n\tmod->loadSpriteOffset(_type, _bulletSprite, reader[\"bulletSprite\"], \"Projectiles\", 35);\n\tmod->loadSpriteOffset(_type, _specialIconSprite, reader[\"specialIconSprite\"], \"SPICONS.DAT\");\n\n\tmod->loadSoundOffset(_type, _reloadSound, reader[\"reloadSound\"], \"BATTLE.CAT\");\n\tmod->loadSoundOffset(_type, _primeSound, reader[\"primeSound\"], \"BATTLE.CAT\");\n\tmod->loadSoundOffset(_type, _unprimeSound, reader[\"unprimeSound\"], \"BATTLE.CAT\");\n\tmod->loadSoundOffset(_type, _fireSound, reader[\"fireSound\"], \"BATTLE.CAT\");\n\tmod->loadSoundOffset(_type, _hitSound, reader[\"hitSound\"], \"BATTLE.CAT\");\n\tmod->loadSoundOffset(_type, _hitMissSound, reader[\"hitMissSound\"], \"BATTLE.CAT\");\n\tmod->loadSoundOffset(_type, _meleeSound, reader[\"meleeSound\"], \"BATTLE.CAT\");\n\tmod->loadSoundOffset(_type, _meleeHitSound, reader[\"meleeHitSound\"], \"BATTLE.CAT\");\n\tmod->loadSoundOffset(_type, _meleeMissSound, reader[\"meleeMissSound\"], \"BATTLE.CAT\");\n\tmod->loadSoundOffset(_type, _psiSound, reader[\"psiSound\"], \"BATTLE.CAT\");\n\tmod->loadSoundOffset(_type, _psiMissSound, reader[\"psiMissSound\"], \"BATTLE.CAT\");\n\tmod->loadSoundOffset(_type, _explosionHitSound, reader[\"explosionHitSound\"], \"BATTLE.CAT\");\n\n\tmod->loadSpriteOffset(_type, _hitAnimation, reader[\"hitAnimation\"], \"SMOKE.PCK\");\n\tmod->loadSpriteOffset(_type, _hitMissAnimation, reader[\"hitMissAnimation\"], \"SMOKE.PCK\");\n\tmod->loadSpriteOffset(_type, _meleeAnimation, reader[\"meleeAnimation\"], \"HIT.PCK\");\n\tmod->loadSpriteOffset(_type, _meleeMissAnimation, reader[\"meleeMissAnimation\"], \"HIT.PCK\");\n\tmod->loadSpriteOffset(_type, _psiAnimation, reader[\"psiAnimation\"], \"HIT.PCK\");\n\tmod->loadSpriteOffset(_type, _psiMissAnimation, reader[\"psiMissAnimation\"], \"HIT.PCK\");\n\n\treader.tryRead(\"hitAnimFrames\", _hitAnimFrames);\n\treader.tryRead(\"hitMissAnimFrames\", _hitMissAnimFrames);\n\treader.tryRead(\"meleeAnimFrames\", _meleeAnimFrames);\n\treader.tryRead(\"meleeMissAnimFrames\", _meleeMissAnimFrames);\n\treader.tryRead(\"psiAnimFrames\", _psiAnimFrames);\n\treader.tryRead(\"psiMissAnimFrames\", _psiMissAnimFrames);\n\n\tif (reader[\"battleType\"])\n\t{\n\t\treader.tryRead(\"battleType\", _battleType);\n\t\t_ignoreInCraftEquip = !isUsefulBattlescapeItem();\n\n\t\tif (_battleType == BT_PSIAMP)\n\t\t{\n\t\t\t_psiReqiured = true;\n\t\t\t_dropoff = 1;\n\t\t\t_confAimed.range = 0;\n\t\t\t_accuracyMulti.setPsiAttack();\n\t\t\t_targetMatrix = 6; // only hostile and neutral by default\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_psiReqiured = false;\n\t\t}\n\n\t\tif (_battleType == BT_PROXIMITYGRENADE)\n\t\t{\n\t\t\t_fuseType = BFT_INSTANT;\n\t\t}\n\t\telse if (_battleType == BT_GRENADE)\n\t\t{\n\t\t\t_fuseType = BFT_SET;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_fuseType = BFT_NONE;\n\t\t}\n\n\t\tif (_battleType == BT_MELEE)\n\t\t{\n\t\t\t_confMelee.ammoSlot = 0;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_confMelee.ammoSlot = RuleItem::AmmoSlotSelfUse;\n\t\t}\n\n\t\tif (_battleType == BT_CORPSE)\n\t\t{\n\t\t\t//compatibility hack for corpse explosion, that didn't have defined damage type\n\t\t\t_damageType = *mod->getDamageType(DT_HE);\n\t\t\t_damageTypeSet = true;\n\t\t}\n\t\t_meleeType = *mod->getDamageType(DT_MELEE);\n\t\t_meleeTypeSet = true;\n\t}\n\n\tif (const auto& type = reader[\"damageType\"])\n\t{\n\t\t//load predefined damage type\n\t\t_damageType = *mod->getDamageType((ItemDamageType)type.readVal<int>());\n\t\t_damageTypeSet = true;\n\t}\n\treader.tryRead(\"blastRadius\", _damageType.FixRadius);\n\tif (const auto& alter = reader[\"damageAlter\"])\n\t{\n\t\t_damageType.load(alter);\n\t}\n\n\tif (const auto& type = reader[\"meleeType\"])\n\t{\n\t\t//load predefined damage type\n\t\t_meleeType = *mod->getDamageType((ItemDamageType)type.readVal<int>());\n\t\t_meleeTypeSet = true;\n\t}\n\tif (const auto& alter = reader[\"meleeAlter\"])\n\t{\n\t\t_meleeType.load(alter);\n\t}\n\n\tif (const auto& skill = reader[\"skillApplied\"])\n\t{\n\t\tif (skill.readVal(false))\n\t\t{\n\t\t\t_meleeMulti.setMelee();\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_meleeMulti.setFlatHundred();\n\t\t\t_meleeMulti.setModded(true); // vanilla default = true\n\t\t}\n\t}\n\tif (reader[\"strengthApplied\"].readVal(false))\n\t{\n\t\t_damageBonus.setStrength();\n\t\t_damageBonus.setModded(true); // vanilla default = false\n\t}\n\n\treader.tryRead(\"power\", _power);\n\treader.tryRead(\"powerForAnimation\", _powerForAnimation);\n\treader.tryRead(\"hidePower\", _hidePower);\n\treader.tryRead(\"ignoreAmmoPower\", _ignoreAmmoPower);\n\treader.tryRead(\"painKillerActionName\", _painKillerActionName);\n\treader.tryRead(\"stimulantActionName\", _stimulantActionName);\n\treader.tryRead(\"healActionName\", _healActionName);\n\treader.tryRead(\"medikitActionName\", _medikitActionName);\n\treader.tryRead(\"psiAttackName\", _psiAttackName);\n\treader.tryRead(\"primeActionName\", _primeActionName);\n\treader.tryRead(\"primeActionMessage\", _primeActionMessage);\n\treader.tryRead(\"unprimeActionName\", _unprimeActionName);\n\treader.tryRead(\"unprimeActionMessage\", _unprimeActionMessage);\n\treader.tryRead(\"sellActionMessage\", _sellActionMessage);\n\treader.tryRead(\"fuseType\", _fuseType);\n\treader.tryRead(\"hiddenOnMinimap\", _hiddenOnMinimap);\n\treader.tryRead(\"clipSize\", _clipSize);\n\n\tloadConfFuse(_fuseTriggerEvents, reader, \"fuseTriggerEvents\");\n\n\treader.tryRead(\"accuracyAimed\", _confAimed.accuracy);\n\treader.tryRead(\"accuracyAuto\", _confAuto.accuracy);\n\treader.tryRead(\"accuracySnap\", _confSnap.accuracy);\n\treader.tryRead(\"accuracyMelee\", _confMelee.accuracy);\n\treader.tryRead(\"accuracyUse\", _accuracyUse);\n\treader.tryRead(\"accuracyMindControl\", _accuracyMind);\n\treader.tryRead(\"accuracyPanic\", _accuracyPanic);\n\treader.tryRead(\"accuracyThrow\", _accuracyThrow);\n\treader.tryRead(\"accuracyCloseQuarters\", _accuracyCloseQuarters);\n\treader.tryRead(\"noLOSAccuracyPenalty\", _noLOSAccuracyPenalty);\n\tif (reader[\"isExplodingInHands\"])\n\t{\n\t\t// FIXME: backwards-compatibility only, remove in 2026\n\t\tbool tmpBool = false;\n\t\treader.tryRead(\"isExplodingInHands\", tmpBool);\n\t\t_explodeInventory = tmpBool ? 2 : 0;\n\t}\n\treader.tryRead(\"explodeInventory\", _explodeInventory);\n\n\t_confAimed.cost.loadCost(reader, \"Aimed\");\n\t_confAuto.cost.loadCost(reader, \"Auto\");\n\t_confSnap.cost.loadCost(reader, \"Snap\");\n\t_confMelee.cost.loadCost(reader, \"Melee\");\n\t_costUse.loadCost(reader, \"Use\");\n\t_costMind.loadCost(reader, \"MindControl\");\n\t_costPanic.loadCost(reader, \"Panic\");\n\t_costThrow.loadCost(reader, \"Throw\");\n\t_costPrime.loadCost(reader, \"Prime\");\n\t_costUnprime.loadCost(reader, \"Unprime\");\n\n\treader.tryRead(\"flatRate\", _flatUse.Time);\n\n\t_confAimed.flat.loadFlat(reader, \"Aimed\");\n\t_confAuto.flat.loadFlat(reader, \"Auto\");\n\t_confSnap.flat.loadFlat(reader, \"Snap\");\n\t_confMelee.flat.loadFlat(reader, \"Melee\");\n\t_flatUse.loadFlat(reader, \"Use\");\n\t_flatThrow.loadFlat(reader, \"Throw\");\n\t_flatPrime.loadFlat(reader, \"Prime\");\n\t_flatUnprime.loadFlat(reader, \"Unprime\");\n\n\tloadConfAction(_confAimed, reader, \"Aimed\");\n\tloadConfAction(_confAuto, reader, \"Auto\");\n\tloadConfAction(_confSnap, reader, \"Snap\");\n\tloadConfAction(_confMelee, reader, \"Melee\");\n\n\tauto loadAmmoConf = [&](int offset, const YAML::YamlNodeReader& n)\n\t{\n\t\tif (n)\n\t\t{\n\t\t\tmod->loadUnorderedNames(_type, _compatibleAmmoNames[offset], n[\"compatibleAmmo\"]);\n\t\t\tn.tryRead(\"tuLoad\", _tuLoad[offset]);\n\t\t\tn.tryRead(\"tuUnload\", _tuUnload[offset]);\n\t\t}\n\t};\n\n\tloadAmmoConf(0, reader);\n\tif (const auto& nodeAmmo = reader[\"ammo\"])\n\t{\n\t\tfor (int slot = 0; slot < AmmoSlotMax; ++slot)\n\t\t{\n\t\t\tloadAmmoConf(slot, nodeAmmo[ryml::to_csubstr(std::to_string(slot))]);\n\t\t}\n\t}\n\n\treader.tryRead(\"specialChance\", _specialChance);\n\treader.tryRead(\"twoHanded\", _twoHanded);\n\treader.tryRead(\"blockBothHands\", _blockBothHands);\n\treader.tryRead(\"waypoints\", _waypoints);\n\treader.tryRead(\"fixedWeapon\", _fixedWeapon);\n\treader.tryRead(\"fixedWeaponShow\", _fixedWeaponShow);\n\treader[\"inventoryMoveCost\"][\"basePercent\"].tryReadVal(_inventoryMoveCostPercent);\n\tmod->loadNameNull(_type, _defaultInventorySlotName, reader[\"defaultInventorySlot\"]);\n\treader.tryRead(\"defaultInvSlotX\", _defaultInvSlotX);\n\treader.tryRead(\"defaultInvSlotY\", _defaultInvSlotY);\n\tmod->loadUnorderedNames(_type, _supportedInventorySectionsNames, reader[\"supportedInventorySections\"]);\n\treader.tryRead(\"isConsumable\", _isConsumable);\n\treader.tryRead(\"isFireExtinguisher\", _isFireExtinguisher);\n\treader.tryRead(\"isAmmoRechargeable\", _isAmmoRechargeable);\n\treader.tryRead(\"specialUseEmptyHand\", _specialUseEmptyHand);\n\treader.tryRead(\"specialUseEmptyHandShow\", _specialUseEmptyHandShow);\n\treader.tryRead(\"invWidth\", _invWidth);\n\treader.tryRead(\"invHeight\", _invHeight);\n\n\treader.tryRead(\"painKiller\", _painKiller);\n\treader.tryRead(\"heal\", _heal);\n\treader.tryRead(\"stimulant\", _stimulant);\n\treader.tryRead(\"woundRecovery\", _woundRecovery);\n\treader.tryRead(\"healthRecovery\", _healthRecovery);\n\treader.tryRead(\"stunRecovery\", _stunRecovery);\n\treader.tryRead(\"energyRecovery\", _energyRecovery);\n\treader.tryRead(\"manaRecovery\", _manaRecovery);\n\treader.tryRead(\"moraleRecovery\", _moraleRecovery);\n\treader.tryRead(\"painKillerRecovery\", _painKillerRecovery);\n\treader.tryRead(\"medikitType\", _medikitType);\n\treader.tryRead(\"medikitTargetSelf\", _medikitTargetSelf);\n\treader.tryRead(\"medikitTargetImmune\", _medikitTargetImmune);\n\treader.tryRead(\"medikitTargetMatrix\", _medikitTargetMatrix);\n\treader.tryRead(\"medikitBackground\", _medikitBackground);\n\n\treader.tryRead(\"recoveryPoints\", _recoveryPoints);\n\treader.tryRead(\"armor\", _armor);\n\treader.tryRead(\"turretType\", _turretType);\n\tif (const auto& nodeAI = reader[\"ai\"])\n\t{\n\t\tnodeAI.tryRead(\"useDelay\", _aiUseDelay);\n\t\tnodeAI.tryRead(\"meleeHitCount\", _aiMeleeHitCount);\n\t}\n\treader.tryRead(\"recover\", _recover);\n\treader.tryRead(\"recoverCorpse\", _recoverCorpse);\n\treader.tryRead(\"ignoreInBaseDefense\", _ignoreInBaseDefense);\n\treader.tryRead(\"ignoreInCraftEquip\", _ignoreInCraftEquip);\n\treader.tryRead(\"liveAlien\", _liveAlien);\n\treader.tryRead(\"prisonType\", _liveAlienPrisonType);\n\treader.tryRead(\"attraction\", _attraction);\n\treader.tryRead(\"arcingShot\", _arcingShot);\n\treader.tryRead(\"experienceTrainingMode\", _experienceTrainingMode);\n\treader.tryRead(\"manaExperience\", _manaExperience);\n\treader.tryRead(\"loadOrder\", _loadOrder);\n\treader.tryRead(\"listOrder\", _listOrder);\n\treader.tryRead(\"maxRange\", _maxRange);\n\treader.tryRead(\"aimRange\", _confAimed.range);\n\treader.tryRead(\"autoRange\", _confAuto.range);\n\treader.tryRead(\"snapRange\", _confSnap.range);\n\treader.tryRead(\"minRange\", _minRange);\n\treader.tryRead(\"dropoff\", _dropoff);\n\treader.tryRead(\"bulletSpeed\", _bulletSpeed);\n\treader.tryRead(\"explosionSpeed\", _explosionSpeed);\n\treader.tryRead(\"autoShots\", _confAuto.shots);\n\treader.tryRead(\"shotgunPellets\", _shotgunPellets);\n\treader.tryRead(\"shotgunBehavior\", _shotgunBehaviorType);\n\treader.tryRead(\"shotgunSpread\", _shotgunSpread);\n\treader.tryRead(\"shotgunChoke\", _shotgunChoke);\n\n\tmod->loadUnorderedNamesToNames(_type, _zombieUnitByArmorMale, reader[\"zombieUnitByArmorMale\"]);\n\tmod->loadUnorderedNamesToNames(_type, _zombieUnitByArmorFemale, reader[\"zombieUnitByArmorFemale\"]);\n\tmod->loadUnorderedNamesToNames(_type, _zombieUnitByType, reader[\"zombieUnitByType\"]);\n\tmod->loadNameNull(_type, _zombieUnit, reader[\"zombieUnit\"]);\n\tmod->loadNameNull(_type, _spawnUnitName, reader[\"spawnUnit\"]);\n\tmod->loadNameNull(_type, _spawnItemName, reader[\"spawnItem\"]);\n\treader.tryRead(\"spawnUnitFaction\", _spawnUnitFaction);\n\treader.tryRead(\"zombieUnitFaction\", _zombieUnitFaction);\n\tloadIntNullable(_spawnUnitChance, reader[\"spawnUnitChance\"]);\n\tloadIntNullable(_zombieUnitChance, reader[\"zombieUnitChance\"]);\n\tloadIntNullable(_spawnItemChance, reader[\"spawnItemChance\"]);\n\n\t// TODO: just backwards-compatibility, remove in 2022, update ruleset validator too\n\treader.tryRead(\"psiTargetMatrix\", _targetMatrix);\n\n\treader.tryRead(\"targetMatrix\", _targetMatrix);\n\treader.tryRead(\"convertToCivilian\", _convertToCivilian);\n\treader.tryRead(\"LOSRequired\", _LOSRequired);\n\treader.tryRead(\"meleePower\", _meleePower);\n\treader.tryRead(\"underwaterOnly\", _underwaterOnly);\n\treader.tryRead(\"landOnly\", _landOnly);\n\treader.tryRead(\"specialType\", _specialType);\n\n\tmod->loadTransparencyOffset(_type, _vaporColor, reader[\"vaporColor\"]);\n\treader.tryRead(\"vaporDensity\", _vaporDensity);\n\treader.tryRead(\"vaporProbability\", _vaporProbability);\n\n\tmod->loadTransparencyOffset(_type, _vaporColorSurface, reader[\"vaporColorSurface\"]);\n\treader.tryRead(\"vaporDensitySurface\", _vaporDensitySurface);\n\treader.tryRead(\"vaporProbabilitySurface\", _vaporProbabilitySurface);\n\n\tmod->loadSpriteOffset(_type, _customItemPreviewIndex, reader[\"customItemPreviewIndex\"], \"CustomItemPreviews\");\n\treader.tryRead(\"kneelBonus\", _kneelBonus);\n\treader.tryRead(\"oneHandedPenalty\", _oneHandedPenalty);\n\treader.tryRead(\"monthlySalary\", _monthlySalary);\n\treader.tryRead(\"monthlyMaintenance\", _monthlyMaintenance);\n\treader.tryRead(\"sprayWaypoints\", _sprayWaypoints);\n\n\t_damageBonus.load(_type, reader, parsers.bonusStatsScripts.get<ModScript::DamageBonusStatBonus>());\n\t_meleeBonus.load(_type, reader, parsers.bonusStatsScripts.get<ModScript::MeleeBonusStatBonus>());\n\t_accuracyMulti.load(_type, reader, parsers.bonusStatsScripts.get<ModScript::AccuracyMultiplierStatBonus>());\n\t_meleeMulti.load(_type, reader, parsers.bonusStatsScripts.get<ModScript::MeleeMultiplierStatBonus>());\n\t_throwMulti.load(_type, reader, parsers.bonusStatsScripts.get<ModScript::ThrowMultiplierStatBonus>());\n\t_closeQuartersMulti.load(_type, reader, parsers.bonusStatsScripts.get<ModScript::CloseQuarterMultiplierStatBonus>());\n\n\treader.tryRead(\"powerRangeReduction\", _powerRangeReduction);\n\treader.tryRead(\"powerRangeThreshold\", _powerRangeThreshold);\n\n\treader.tryRead(\"psiRequired\", _psiReqiured);\n\treader.tryRead(\"manaRequired\", _manaRequired);\n\t_scriptValues.load(reader, parsers.getShared());\n\n\t_battleItemScripts.load(_type, reader, parsers.battleItemScripts);\n}\n\n/**\n * Cross link with other Rules.\n */\nvoid RuleItem::afterLoad(const Mod* mod)\n{\n\tif ((_battleType == BT_MELEE || _battleType == BT_FIREARM) && _clipSize == 0)\n\t{\n\t\tfor (RuleItemAction* conf : { &_confAimed, &_confAuto, &_confSnap, &_confMelee, })\n\t\t{\n\t\t\tif (conf->ammoSlot != RuleItem::AmmoSlotSelfUse && _compatibleAmmoNames[conf->ammoSlot].empty())\n\t\t\t{\n\t\t\t\tthrow Exception(\"Weapon \" + _type + \" has clip size 0 and no ammo defined. Please use 'clipSize: -1' for unlimited ammo, or allocate a compatibleAmmo item.\");\n\t\t\t}\n\t\t}\n\t}\n\n\t// these are good defaults for vanilla\n\tif (_loadOrder <= 0)\n\t{\n\t\t_loadOrder = _listOrder;\n\t}\n\n\tmod->verifySpriteOffset(_type, _bigSprite, \"BIGOBS.PCK\");\n\tmod->verifySpriteOffset(_type, _floorSprite, \"FLOOROB.PCK\");\n\tmod->verifySpriteOffset(_type, _handSprite, \"HANDOB.PCK\");\n\t// Projectiles: this will check only if first one is correct\n\tif (!isWaterOnly()) mod->verifySpriteOffset(_type, _bulletSprite, \"Projectiles\");\n\tif (isWaterOnly()) mod->verifySpriteOffset(_type, _bulletSprite, \"UnderwaterProjectiles\");\n\tmod->verifySpriteOffset(_type, _specialIconSprite, \"SPICONS.DAT\");\n\n\tmod->verifySoundOffset(_type, _reloadSound, \"BATTLE.CAT\");\n\tmod->verifySoundOffset(_type, _fireSound, \"BATTLE.CAT\");\n\tmod->verifySoundOffset(_type, _hitSound, \"BATTLE.CAT\");\n\tmod->verifySoundOffset(_type, _hitMissSound, \"BATTLE.CAT\");\n\tmod->verifySoundOffset(_type, _meleeSound, \"BATTLE.CAT\");\n\tmod->verifySoundOffset(_type, _meleeHitSound, \"BATTLE.CAT\");\n\tmod->verifySoundOffset(_type, _meleeMissSound, \"BATTLE.CAT\");\n\tmod->verifySoundOffset(_type, _psiSound, \"BATTLE.CAT\");\n\tmod->verifySoundOffset(_type, _psiMissSound, \"BATTLE.CAT\");\n\tmod->verifySoundOffset(_type, _explosionHitSound, \"BATTLE.CAT\");\n\n\tmod->verifySpriteOffset(_type, _hitAnimation, _damageType.FixRadius ? \"X1.PCK\" : \"SMOKE.PCK\");\n\tmod->verifySpriteOffset(_type, _hitMissAnimation, _damageType.FixRadius ? \"X1.PCK\" : \"SMOKE.PCK\");\n\tmod->verifySpriteOffset(_type, _meleeAnimation, \"HIT.PCK\");\n\tmod->verifySpriteOffset(_type, _meleeMissAnimation, \"HIT.PCK\");\n\tmod->verifySpriteOffset(_type, _psiAnimation, \"HIT.PCK\");\n\tmod->verifySpriteOffset(_type, _psiMissAnimation, \"HIT.PCK\");\n\n\tmod->verifySpriteOffset(_type, _customItemPreviewIndex, \"CustomItemPreviews\");\n\n\n\t_requires = mod->getResearch(_requiresName);\n\t_requiresBuy = mod->getResearch(_requiresBuyName);\n\t// fixedWeapons can mean vehicle\n\tif (_fixedWeapon)\n\t{\n\t\t_vehicleUnit = mod->getUnit(_type);\n\t}\n\tmod->linkRule(_spawnUnit, _spawnUnitName);\n\tmod->linkRule(_spawnItem, _spawnItemName);\n\n\tfor (auto& pair : _recoveryTransformationsName)\n\t{\n\t\tauto* item = mod->getItem(pair.first, true);\n\t\tif (!item->isAlien())\n\t\t{\n\t\t\tif (!pair.second.empty())\n\t\t\t{\n\t\t\t\t_recoveryTransformations[item] = pair.second;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tthrow Exception(\"Right-hand value of recovery transformations definition cannot be empty!\");\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tthrow Exception(\"Sorry modders, cannot recover live aliens from random inorganic junk '\" + pair.first + \"'!\");\n\t\t}\n\t}\n\n\tmod->linkRule(_defaultInventorySlot, _defaultInventorySlotName);\n\tif (_supportedInventorySectionsNames.size())\n\t{\n\t\tmod->linkRule(_supportedInventorySections, _supportedInventorySectionsNames);\n\t\tCollections::sortVector(_supportedInventorySections);\n\t}\n\tfor (int i = 0; i < AmmoSlotMax; ++i)\n\t{\n\t\tmod->linkRule(_compatibleAmmo[i], _compatibleAmmoNames[i]);\n\t\tfor (auto* a : _compatibleAmmo[i])\n\t\t{\n\t\t\tif (_compatibleAmmoSlots.count(a) == 0)\n\t\t\t{\n\t\t\t\t_compatibleAmmoSlots.insert(std::make_pair(a, i));\n\t\t\t}\n\t\t}\n\t}\n\tif (_vehicleUnit)\n\t{\n\t\tif (_vehicleFixedAmmoSlot != 0 && _vehicleFixedAmmoSlot != -1)\n\t\t{\n\t\t\tthrow Exception(\"Vehicle primary weapon fixed ammo slot can be only 0 or -1.\");\n\t\t}\n\t\tif (_vehicleFixedAmmoSlot > -1)\n\t\t{\n\t\t\tif (_compatibleAmmo[_vehicleFixedAmmoSlot].size() > 1)\n\t\t\t{\n\t\t\t\tthrow Exception(\"Vehicle weapons support only one ammo type\");\n\t\t\t}\n\t\t\tif (_compatibleAmmo[_vehicleFixedAmmoSlot].size() == 1)\n\t\t\t{\n\t\t\t\tauto* ammo = _compatibleAmmo[_vehicleFixedAmmoSlot].front();\n\t\t\t\tif (ammo->getClipSize() > 0 && getClipSize() > 0)\n\t\t\t\t{\n\t\t\t\t\tif (getClipSize() % ammo->getClipSize())\n\t\t\t\t\t{\n\t\t\t\t\t\tthrow Exception(\"Vehicle weapon clip size is not a multiple of '\" + ammo->getType() + \"' clip size\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t//remove not needed data\n\tCollections::removeAll(_requiresName);\n\tCollections::removeAll(_requiresBuyName);\n\tCollections::removeAll(_recoveryTransformationsName);\n\tCollections::removeAll(_compatibleAmmoNames);\n}\n\n/**\n * Gets the custom name of the Ufopedia article related to this item.\n * @return The ufopedia article name.\n */\nconst std::string& RuleItem::getUfopediaType() const\n{\n\tif (!_ufopediaType.empty())\n\t\treturn _ufopediaType;\n\n\treturn _type;\n}\n\n/**\n * Gets the item type. Each item has a unique type.\n * @return The item's type.\n */\nconst std::string &RuleItem::getType() const\n{\n\treturn _type;\n}\n\n/**\n * Gets the language string that names\n * this item. This is not necessarily unique.\n * @return  The item's name.\n */\nconst std::string &RuleItem::getName() const\n{\n\treturn _name;\n}\n\n/**\n * Gets name id to use when displaying in loaded weapon.\n * @return Translation StringId.\n */\nconst std::string &RuleItem::getNameAsAmmo() const\n{\n\treturn _nameAsAmmo;\n}\n\n/**\n * Gets the list of research required to\n * use this item.\n * @return The list of research IDs.\n */\nconst std::vector<const RuleResearch *> &RuleItem::getRequirements() const\n{\n\treturn _requires;\n}\n\n/**\n * Gets the list of research required to\n * buy this item from market.\n * @return The list of research IDs.\n */\nconst std::vector<const RuleResearch *> &RuleItem::getBuyRequirements() const\n{\n\treturn _requiresBuy;\n}\n\n/**\n * Gets the dividers used for recovery of special items (specialType > 1).\n * @return The list of recovery divider rules\n */\nconst std::map<std::string, int> &RuleItem::getRecoveryDividers() const\n{\n\treturn _recoveryDividers;\n}\n\n/**\n * Gets the item(s) to be recovered instead of this item.\n * @return The list of recovery transformation rules\n */\nconst std::map<const RuleItem*, std::vector<int> > &RuleItem::getRecoveryTransformations() const\n{\n\treturn _recoveryTransformations;\n}\n\n/**\n* Gets the list of categories\n* this item belongs to.\n* @return The list of category IDs.\n*/\nconst std::vector<std::string> &RuleItem::getCategories() const\n{\n\treturn _categories;\n}\n\n/**\n* Checks if the item belongs to a category.\n* @param category Category name.\n* @return True if item belongs to the category, False otherwise.\n*/\nbool RuleItem::belongsToCategory(const std::string &category) const\n{\n\treturn std::find(_categories.begin(), _categories.end(), category) != _categories.end();\n}\n\n/**\n * Returns the first item category that has a non-empty invOrder, if it exists.\n */\nconst RuleItemCategory* RuleItem::getFirstCategoryWithInvOrder(const Mod* mod) const\n{\n\tfor (auto& catName : _categories)\n\t{\n\t\tauto* cat = mod->getItemCategory(catName, false);\n\t\tif (cat && !cat->getInvOrder().empty())\n\t\t{\n\t\t\treturn cat;\n\t\t}\n\t}\n\treturn nullptr;\n}\n\n/**\n * Gets unit rule if the item is vehicle weapon.\n */\nUnit* RuleItem::getVehicleUnit() const\n{\n\treturn _vehicleUnit;\n}\n\n/**\n * Gets the amount of space this item\n * takes up in a storage facility.\n * @return The storage size.\n */\ndouble RuleItem::getSize() const\n{\n\treturn _size;\n}\n\n/**\n * Gets the amount of money this item\n * costs to purchase (0 if not purchasable).\n * @return The buy cost.\n */\nint RuleItem::getBuyCost() const\n{\n\treturn _costBuy;\n}\n\n/**\n * Gets the item's purchase cost.\n * @param base Current base from where item is bought\n * @param save Game\n * @return Current cost\n */\nint RuleItem::getBuyCostAdjusted(const Base* base, const SavedGame* save) const\n{\n\t(void)base; //TODO: not exposed to scripts yet\n\n\tint buyPriceCoefficient = save->getBuyPriceCoefficient();\n\tint cost = getBuyCost();\n\tint adjusted = ((int64_t)cost) * buyPriceCoefficient / 100;\n\n\tadjusted = ModScript::scriptFunc2<ModScript::BuyCostItem>(this, adjusted, cost, this, save, buyPriceCoefficient);\n\n\treturn adjusted;\n}\n\n/**\n * Gets the amount of money this item\n * is worth to sell.\n * @return The sell cost.\n */\nint RuleItem::getSellCost() const\n{\n\treturn _costSell;\n}\n\n/**\n * Gets the item's sale cost.\n * @param base Current base from where item is sold\n * @param save Game\n * @return Current cost\n */\nint RuleItem::getSellCostAdjusted(const Base* base, const SavedGame* save) const\n{\n\t(void)base; //TODO: not exposed to scripts yet\n\n\tint sellPriceCoefficient = save->getSellPriceCoefficient();\n\tint cost = getSellCost();\n\tint adjusted = ((int64_t)cost) * sellPriceCoefficient / 100;\n\n\tadjusted = ModScript::scriptFunc2<ModScript::SellCostItem>(this, adjusted, cost, this, save, sellPriceCoefficient);\n\n\treturn adjusted;\n}\n\n/**\n * Gets the amount of time this item\n * takes to arrive at a base.\n * @return The time in hours.\n */\nint RuleItem::getTransferTime() const\n{\n\treturn _transferTime;\n}\n\n/**\n * Gets the weight of the item.\n * @return The weight in strength units.\n */\nint RuleItem::getWeight() const\n{\n\treturn _weight;\n}\n\n/**\n * Gets the reference in BIGOBS.PCK for use in inventory.\n * @return The sprite reference.\n */\nint RuleItem::getBigSprite() const\n{\n\treturn _bigSprite;\n}\n\n/**\n * Gets the reference in FLOOROB.PCK for use in battlescape.\n * @return The sprite reference.\n */\nint RuleItem::getFloorSprite() const\n{\n\treturn _floorSprite;\n}\n\n/**\n * Gets the reference in HANDOB.PCK for use in inventory.\n * @return The sprite reference.\n */\nint RuleItem::getHandSprite() const\n{\n\treturn _handSprite;\n}\n\n/**\n * Gets the reference in SPICONS.DAT for use in battlescape.\n * @return The sprite reference.\n */\nint RuleItem::getSpecialIconSprite() const\n{\n\treturn _specialIconSprite;\n}\n\n/**\n * Returns whether this item is held with two hands.\n * @return True if it is two-handed.\n */\nbool RuleItem::isTwoHanded() const\n{\n\treturn _twoHanded;\n}\n\n/**\n * Returns whether this item must be used with both hands.\n * @return True if requires both hands.\n */\nbool RuleItem::isBlockingBothHands() const\n{\n\treturn _blockBothHands;\n}\n\n/**\n * Returns whether this item uses waypoints.\n * @return True if it uses waypoints.\n */\nint RuleItem::getWaypoints() const\n{\n\treturn _waypoints;\n}\n\n/**\n * Returns whether this item is a fixed weapon.\n * You can't move/throw/drop fixed weapons - e.g. HWP turrets.\n * @return True if it is a fixed weapon.\n */\nbool RuleItem::isFixed() const\n{\n\treturn _fixedWeapon;\n}\n\n/**\n * Do show fixed item on unit.\n * @return true if show even is fixed.\n */\nbool RuleItem::getFixedShow() const\n{\n\treturn _fixedWeaponShow;\n}\n\n/**\n * Checks if the item can be placed into a given inventory section.\n * @param inventorySection Inventory section rule.\n * @return True if the item can be placed into a given inventory section.\n */\nbool RuleItem::canBePlacedIntoInventorySection(const RuleInventory* inventorySection) const\n{\n\t// backwards-compatibility\n\tif (_supportedInventorySections.empty())\n\t\treturn true;\n\n\t// always possible to put an item on the ground\n\tif (inventorySection->getType() == INV_GROUND)\n\t\treturn true;\n\n\t// otherwise check allowed inventory sections\n\treturn Collections::sortVectorHave(_supportedInventorySections, inventorySection);\n}\n\n/**\n * Gets the item's bullet sprite reference.\n * @return The sprite reference.\n */\nint RuleItem::getBulletSprite() const\n{\n\treturn _bulletSprite;\n}\n\n/**\n * Gets a random sound id from a given sound vector.\n * @param vector The source vector.\n * @param defaultValue Default value (in case nothing is specified = vector is empty).\n * @return The sound id.\n */\nint RuleItem::getRandomSound(const std::vector<int> &vector, int defaultValue) const\n{\n\tif (!vector.empty())\n\t{\n\t\treturn vector[RNG::generate(0, vector.size() - 1)];\n\t}\n\treturn defaultValue;\n}\n\n/**\n * Gets the item's reload sound.\n * @return The reload sound id.\n */\nint RuleItem::getReloadSound() const\n{\n\treturn getRandomSound(_reloadSound);\n}\n\n/**\n * Gets the item's prime sound.\n * @return The prime sound id.\n */\nint RuleItem::getPrimeSound() const\n{\n\treturn getRandomSound(_primeSound);\n}\n\n/**\n * Gets the item's unprime sound.\n * @return The unprime sound id.\n */\nint RuleItem::getUnprimeSound() const\n{\n\treturn getRandomSound(_unprimeSound);\n}\n\n/**\n * Gets the item's fire sound.\n * @return The fire sound id.\n */\nint RuleItem::getFireSound() const\n{\n\treturn getRandomSound(_fireSound);\n}\n\n/**\n * Gets the item's hit sound.\n * @return The hit sound id.\n */\nint RuleItem::getHitSound() const\n{\n\treturn getRandomSound(_hitSound);\n}\n\n/**\n * Gets the item's hit animation.\n * @return The hit animation id.\n */\nint RuleItem::getHitAnimation() const\n{\n\treturn _hitAnimation;\n}\n\n/**\n * Gets the item's miss sound.\n * @return The miss sound id.\n */\nint RuleItem::getHitMissSound() const\n{\n\treturn getRandomSound(_hitMissSound);\n}\n\n/**\n * Gets the item's miss animation.\n * @return The miss animation id.\n */\nint RuleItem::getHitMissAnimation() const\n{\n\treturn _hitMissAnimation;\n}\n\n\n/**\n * What sound does this weapon make when you swing this at someone?\n * @return The weapon's melee attack sound.\n */\nint RuleItem::getMeleeSound() const\n{\n\treturn getRandomSound(_meleeSound, 39);\n}\n\n/**\n * What is the starting frame offset in hit.pck to use for the animation?\n * @return the starting frame offset in hit.pck to use for the animation.\n */\nint RuleItem::getMeleeAnimation() const\n{\n\treturn _meleeAnimation;\n}\n\n/**\n * What sound does this weapon make when you miss a swing?\n * @return The weapon's melee attack miss sound.\n */\nint RuleItem::getMeleeMissSound() const\n{\n\treturn getRandomSound(_meleeMissSound);\n}\n\n/**\n * What is the starting frame offset in hit.pck to use for the animation?\n * @return the starting frame offset in hit.pck to use for the animation.\n */\nint RuleItem::getMeleeMissAnimation() const\n{\n\treturn _meleeMissAnimation;\n}\n\n/**\n * What sound does this weapon make when you punch someone in the face with it?\n * @return The weapon's melee hit sound.\n */\nint RuleItem::getMeleeHitSound() const\n{\n\treturn getRandomSound(_meleeHitSound);\n}\n\n/**\n * What sound does explosion sound?\n * @return The weapon's explosion sound.\n */\nint RuleItem::getExplosionHitSound() const\n{\n\treturn getRandomSound(_explosionHitSound);\n}\n\n/**\n * Gets the item's psi hit sound.\n * @return The hit sound id.\n */\nint RuleItem::getPsiSound() const\n{\n\treturn getRandomSound(_psiSound);\n}\n\n/**\n * What is the starting frame offset in hit.pck to use for the animation?\n * @return the starting frame offset in hit.pck to use for the animation.\n */\nint RuleItem::getPsiAnimation() const\n{\n\treturn _psiAnimation;\n}\n\n/**\n * Gets the item's psi miss sound.\n * @return The miss sound id.\n */\nint RuleItem::getPsiMissSound() const\n{\n\treturn getRandomSound(_psiMissSound);\n}\n\n/**\n * What is the starting frame offset in hit.pck to use for the animation?\n * @return the starting frame offset in hit.pck to use for the animation.\n */\nint RuleItem::getPsiMissAnimation() const\n{\n\treturn _psiMissAnimation;\n}\n\n/**\n * Gets the item's power.\n * @return The power.\n */\nint RuleItem::getPower() const\n{\n\treturn _power;\n}\n\n/**\n * Gets amount of power dropped for range in voxels.\n * @return Power reduction.\n */\nfloat RuleItem::getPowerRangeReduction(float range) const\n{\n\trange -= _powerRangeThreshold * TilesToVexels;\n\treturn (_powerRangeReduction * VexelsToTiles) * (range > 0 ? range : 0);\n}\n\n/**\n * Get amount of psi accuracy dropped for range in voxels.\n * @param range\n * @return Psi accuracy reduction.\n */\nfloat RuleItem::getPsiAccuracyRangeReduction(float range) const\n{\n\trange -= _confAimed.range * TilesToVexels;\n\treturn (_dropoff * VexelsToTiles) * (range > 0 ? range : 0);\n}\n\n/**\n * Get configuration of aimed shot action.\n */\nconst RuleItemAction *RuleItem::getConfigAimed() const\n{\n\treturn &_confAimed;\n}\n\n/**\n * Get configuration of autoshot action.\n */\nconst RuleItemAction *RuleItem::getConfigAuto() const\n{\n\treturn &_confAuto;\n}\n\n/**\n * Get configuration of snapshot action.\n */\nconst RuleItemAction *RuleItem::getConfigSnap() const\n{\n\treturn &_confSnap;\n}\n\n/**\n * Get configuration of melee action.\n */\nconst RuleItemAction *RuleItem::getConfigMelee() const\n{\n\treturn &_confMelee;\n}\n\n\n/**\n * Gets the item's accuracy for snapshots.\n * @return The snapshot accuracy.\n */\nint RuleItem::getAccuracySnap() const\n{\n\treturn _confSnap.accuracy;\n}\n\n/**\n * Gets the item's accuracy for autoshots.\n * @return The autoshot accuracy.\n */\nint RuleItem::getAccuracyAuto() const\n{\n\treturn _confAuto.accuracy;\n}\n\n/**\n * Gets the item's accuracy for aimed shots.\n * @return The aimed accuracy.\n */\nint RuleItem::getAccuracyAimed() const\n{\n\treturn _confAimed.accuracy;\n}\n\n/**\n * Gets the item's accuracy for melee attacks.\n * @return The melee accuracy.\n */\nint RuleItem::getAccuracyMelee() const\n{\n\treturn _confMelee.accuracy;\n}\n\n/**\n * Gets the item's accuracy for use psi-amp.\n * @return The psi-amp accuracy.\n */\nint RuleItem::getAccuracyUse() const\n{\n\treturn _accuracyUse;\n}\n\n/**\n * Gets the item's accuracy for mind control use.\n * @return The mind control accuracy.\n */\nint RuleItem::getAccuracyMind() const\n{\n\treturn _accuracyMind;\n}\n\n/**\n * Gets the item's accuracy for panic use.\n * @return The panic accuracy.\n */\nint RuleItem::getAccuracyPanic() const\n{\n\treturn _accuracyPanic;\n}\n\n/**\n * Gets the item's accuracy for throw.\n * @return The throw accuracy.\n */\nint RuleItem::getAccuracyThrow() const\n{\n\treturn _accuracyThrow;\n}\n\n/**\n * Gets the item's accuracy for close quarters combat.\n * @return The close quarters accuracy.\n */\nint RuleItem::getAccuracyCloseQuarters(const Mod *mod) const\n{\n\treturn _accuracyCloseQuarters != -1 ? _accuracyCloseQuarters : mod->getCloseQuartersAccuracyGlobal();\n}\n\n/**\n * Gets the item's accuracy penalty for out-of-LOS targets\n * @return The no-LOS accuracy penalty.\n */\nint RuleItem::getNoLOSAccuracyPenalty(Mod *mod) const\n{\n\treturn _noLOSAccuracyPenalty != -1 ? _noLOSAccuracyPenalty : mod->getNoLOSAccuracyPenaltyGlobal();\n}\n\n/**\n * Gets the setting for primed explosives exploding in the inventory.\n * @return The setting (0 = no, 1 = yes, except when in hands, 2 = always).\n */\nint RuleItem::getExplodeInventory(const Mod* mod) const\n{\n\treturn _explodeInventory != -1 ? _explodeInventory : (_battleType == BT_GRENADE ? mod->getExplodeInventoryGlobal() : 0);\n}\n\n/**\n * Gets the item's time unit percentage for aimed shots.\n * @return The aimed shot TU percentage.\n */\nRuleItemUseCost RuleItem::getCostAimed() const\n{\n\treturn getDefault(_confAimed.cost);\n}\n\n/**\n * Gets the item's time unit percentage for autoshots.\n * @return The autoshot TU percentage.\n */\nRuleItemUseCost RuleItem::getCostAuto() const\n{\n\treturn getDefault(_confAuto.cost, _confAimed.cost);\n}\n\n/**\n * Gets the item's time unit percentage for snapshots.\n * @return The snapshot TU percentage.\n */\nRuleItemUseCost RuleItem::getCostSnap() const\n{\n\treturn getDefault(_confSnap.cost, _confAimed.cost);\n}\n\n/**\n * Gets the item's time unit percentage for melee attacks.\n * @return The melee TU percentage.\n */\nRuleItemUseCost RuleItem::getCostMelee() const\n{\n\treturn getDefault(_confMelee.cost);\n}\n\n/**\n * Gets the number of Time Units needed to use this item.\n * @return The number of Time Units needed to use this item.\n */\nRuleItemUseCost RuleItem::getCostUse() const\n{\n\tif (_battleType != BT_PSIAMP || !_psiAttackName.empty())\n\t{\n\t\treturn getDefault(_costUse);\n\t}\n\telse\n\t{\n\t\treturn {};\n\t}\n}\n\n/**\n * Gets the number of Time Units needed to use mind control action.\n * @return The number of Time Units needed to mind control.\n */\nRuleItemUseCost RuleItem::getCostMind() const\n{\n\treturn getDefault(_costMind, _costUse);\n}\n\n/**\n * Gets the number of Time Units needed to use panic action.\n * @return The number of Time Units needed to panic.\n */\nRuleItemUseCost RuleItem::getCostPanic() const\n{\n\treturn getDefault(_costPanic, _costUse);\n}\n\n/**\n * Gets the item's time unit percentage for throwing.\n * @return The throw TU percentage.\n */\nRuleItemUseCost RuleItem::getCostThrow() const\n{\n\treturn getDefault(_costThrow);\n}\n\n/**\n * Gets the item's time unit percentage for prime grenade.\n * @return The prime TU percentage.\n */\nRuleItemUseCost RuleItem::getCostPrime() const\n{\n\tif (!_primeActionName.empty())\n\t{\n\t\treturn getDefault(_costPrime);\n\t}\n\telse\n\t{\n\t\treturn { };\n\t}\n}\n\n/**\n * Gets the item's time unit percentage for unprime grenade.\n * @return The prime TU percentage.\n */\nRuleItemUseCost RuleItem::getCostUnprime() const\n{\n\treturn getDefault(_costUnprime);\n}\n\n/**\n * Gets the item's time unit for loading weapon ammo.\n * @param slot Slot position.\n * @return The throw TU.\n */\nint RuleItem::getTULoad(int slot) const\n{\n\treturn _tuLoad[slot];\n}\n\n/**\n * Gets the item's time unit for unloading weapon ammo.\n * @param slot Slot position.\n * @return The throw TU.\n */\nint RuleItem::getTUUnload(int slot) const\n{\n\treturn _tuUnload[slot];\n}\n\n/**\n * Gets the ammo type for a vehicle.\n */\nconst RuleItem* RuleItem::getVehicleClipAmmo() const\n{\n\tif (_vehicleFixedAmmoSlot > -1)\n\t{\n\t\treturn _compatibleAmmo[_vehicleFixedAmmoSlot].empty() ? nullptr : _compatibleAmmo[_vehicleFixedAmmoSlot].front();\n\t}\n\treturn nullptr;\n}\n\n/**\n * Gets the maximum number of rounds for a vehicle. E.g. a vehicle that can load 6 clips with 10 rounds each, returns 60.\n */\nint RuleItem::getVehicleClipSize() const\n{\n\tauto* ammo = getVehicleClipAmmo();\n\tif (ammo)\n\t{\n\t\tif (ammo->getClipSize() > 0 && getClipSize() > 0)\n\t\t{\n\t\t\treturn getClipSize();\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn ammo->getClipSize();\n\t\t}\n\t}\n\telse\n\t{\n\t\treturn getClipSize();\n\t}\n}\n\n/**\n * Gets the number of clips needed to fully load a vehicle. E.g. a vehicle that holds max 60 rounds and clip size is 10, returns 6.\n */\nint RuleItem::getVehicleClipsLoaded() const\n{\n\tauto* ammo = getVehicleClipAmmo();\n\tif (ammo)\n\t{\n\t\tif (ammo->getClipSize() > 0 && getClipSize() > 0)\n\t\t{\n\t\t\treturn getClipSize() / ammo->getClipSize();\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn ammo->getClipSize();\n\t\t}\n\t}\n\telse\n\t{\n\t\treturn 0;\n\t}\n}\n/**\n * Gets a list of compatible ammo.\n * @return Pointer to a list of compatible ammo.\n */\nconst std::vector<const RuleItem*> *RuleItem::getPrimaryCompatibleAmmo() const\n{\n\treturn &_compatibleAmmo[0];\n}\n\n/**\n * Gets slot position for ammo type.\n * @param type Type of ammo item.\n * @return Slot position.\n */\nint RuleItem::getSlotForAmmo(const RuleItem* type) const\n{\n\tauto f = _compatibleAmmoSlots.find(type);\n\tif (f != _compatibleAmmoSlots.end())\n\t{\n\t\treturn f->second;\n\t}\n\treturn -1;\n}\n\n/**\n *  Get slot position for ammo type.\n */\nconst std::vector<const RuleItem*> *RuleItem::getCompatibleAmmoForSlot(int slot) const\n{\n\treturn &_compatibleAmmo[slot];\n}\n\n/**\n * Gets the item's damage type.\n * @return The damage type.\n */\nconst RuleDamageType *RuleItem::getDamageType() const\n{\n\treturn &_damageType;\n}\n\n/**\n * Gets the item's melee damage type for range weapons.\n * @return The damage type.\n */\nconst RuleDamageType *RuleItem::getMeleeType() const\n{\n\treturn &_meleeType;\n}\n\n/**\n * Gets the item's battle type.\n * @return The battle type.\n */\nBattleType RuleItem::getBattleType() const\n{\n\treturn _battleType;\n}\n\n/**\n * Is the item's type BT_GRENADE or BT_PROXIMITYGRENADE?\n */\nbool RuleItem::isGrenadeOrProxy() const\n{\n\treturn _battleType == BT_GRENADE || _battleType == BT_PROXIMITYGRENADE;\n}\n\n/**\n * Gets the item's fuse timer type.\n * @return Fuse Timer Type.\n */\nBattleFuseType RuleItem::getFuseTimerType() const\n{\n\treturn _fuseType;\n}\n\n/**\n * Gets the item's default fuse timer.\n * @return Time in turns.\n */\nint RuleItem::getFuseTimerDefault() const\n{\n\tif (_fuseType >= BFT_FIX_MIN && _fuseType < BFT_FIX_MAX)\n\t{\n\t\treturn (int)_fuseType;\n\t}\n\telse if (_fuseType == BFT_SET || _fuseType == BFT_INSTANT)\n\t{\n\t\treturn 0;\n\t}\n\telse\n\t{\n\t\treturn -1; //can't prime\n\t}\n}\n\n/**\n * Is this item (e.g. a mine) hidden on the minimap?\n * @return True if the item should be hidden.\n */\nbool RuleItem::isHiddenOnMinimap() const\n{\n\treturn _hiddenOnMinimap;\n}\n\n/**\n * Get fuse trigger event.\n */\nconst RuleItemFuseTrigger *RuleItem::getFuseTriggerEvent() const\n{\n\treturn &_fuseTriggerEvents;\n}\n\n/**\n * Gets the item's width in a soldier's inventory.\n * @return The width.\n */\nint RuleItem::getInventoryWidth() const\n{\n\treturn _invWidth;\n}\n\n/**\n * Gets the item's height in a soldier's inventory.\n * @return The height.\n */\nint RuleItem::getInventoryHeight() const\n{\n\treturn _invHeight;\n}\n\n/**\n * Gets the item's ammo clip size.\n * @return The ammo clip size.\n */\nint RuleItem::getClipSize() const\n{\n\treturn _clipSize;\n}\n\n/**\n * Gets the chance of special effect like zombify or corpse explosion or mine triggering.\n * @return Percent value.\n */\nint RuleItem::getSpecialChance() const\n{\n\treturn _specialChance;\n}\n/**\n * Draws and centers the hand sprite on a surface\n * according to its dimensions.\n * @param texture Pointer to the surface set to get the sprite from.\n * @param surface Pointer to the surface to draw to.\n */\nvoid RuleItem::drawHandSprite(const SurfaceSet *texture, Surface *surface, const BattleItem *item, const SavedBattleGame *save, int animFrame) const\n{\n\t//TODO: split this function to one using only `this` and another using only `item`\n\tconst Surface *frame = nullptr;\n\tif (item)\n\t{\n\t\tframe = item->getBigSprite(texture, save, animFrame);\n\t\tif (frame)\n\t\t{\n\t\t\tScriptWorkerBlit scr;\n\t\t\tBattleItem::ScriptFill(&scr, item, save, BODYPART_ITEM_INVENTORY, animFrame, 0);\n\t\t\tscr.executeBlit(frame, surface, this->getHandSpriteOffX(), this->getHandSpriteOffY(), 0);\n\t\t}\n\t}\n\telse\n\t{\n\t\tframe = texture->getFrame(this->getBigSprite());\n\t\tframe->blitNShade(surface, this->getHandSpriteOffX(), this->getHandSpriteOffY());\n\t}\n}\n\n/**\n * item's hand spite x offset\n * @return x offset\n */\nint RuleItem::getHandSpriteOffX() const\n{\n\treturn (RuleInventory::HAND_W - getInventoryWidth()) * RuleInventory::SLOT_W/2;\n}\n\n/**\n * item's hand spite y offset\n * @return y offset\n */\nint RuleItem::getHandSpriteOffY() const\n{\n\treturn (RuleInventory::HAND_H - getInventoryHeight()) * RuleInventory::SLOT_H/2;\n}\n\n/**\n * Gets the heal quantity of the item.\n * @return The new heal quantity.\n */\nint RuleItem::getHealQuantity() const\n{\n\treturn _heal;\n}\n\n/**\n * Gets the pain killer quantity of the item.\n * @return The new pain killer quantity.\n */\nint RuleItem::getPainKillerQuantity() const\n{\n\treturn _painKiller;\n}\n\n/**\n * Gets the stimulant quantity of the item.\n * @return The new stimulant quantity.\n */\nint RuleItem::getStimulantQuantity() const\n{\n\treturn _stimulant;\n}\n\n/**\n * Gets the amount of fatal wound healed per usage.\n * @return The amount of fatal wound healed.\n */\nint RuleItem::getWoundRecovery() const\n{\n\treturn _woundRecovery;\n}\n\n/**\n * Gets the amount of health added to a wounded soldier's health.\n * @return The amount of health to add.\n */\nint RuleItem::getHealthRecovery() const\n{\n\treturn _healthRecovery;\n}\n\n/**\n * Gets the amount of energy added to a soldier's energy.\n * @return The amount of energy to add.\n */\nint RuleItem::getEnergyRecovery() const\n{\n\treturn _energyRecovery;\n}\n\n/**\n * Gets the amount of stun removed from a soldier's stun level.\n * @return The amount of stun removed.\n */\nint RuleItem::getStunRecovery() const\n{\n\treturn _stunRecovery;\n}\n\n/**\n * Gets the amount of morale added to a solders's morale.\n * @return The amount of morale to add.\n */\nint RuleItem::getMoraleRecovery() const\n{\n\treturn _moraleRecovery;\n}\n\n/**\n * Gets the medikit morale recovered based on missing health.\n * @return The ratio of how much restore.\n */\nfloat RuleItem::getPainKillerRecovery() const\n{\n\treturn _painKillerRecovery;\n}\n\n/**\n * Is this (medikit-type & items with prime) item consumable?\n * @return True if the item is consumable.\n */\nbool RuleItem::isConsumable() const\n{\n\treturn _isConsumable;\n}\n\n/**\n * Does this item extinguish fire?\n * @return True if the item extinguishes fire.\n */\nbool RuleItem::isFireExtinguisher() const\n{\n\treturn _isFireExtinguisher;\n}\n\n/**\n * If this item is used as a specialWeapon, can it be accessed by an empty hand?\n * @return True if accessed by empty hand.\n */\nbool RuleItem::isSpecialUsingEmptyHand() const\n{\n\treturn _specialUseEmptyHand;\n}\n\n/**\n * Gets the medikit type of how it operate.\n * @return Type of medikit.\n */\nBattleMediKitType RuleItem::getMediKitType() const\n{\n\treturn _medikitType;\n}\n\n/**\n * Gets the medikit custom background.\n * @return Sprite ID.\n */\nconst std::string &RuleItem::getMediKitCustomBackground() const\n{\n\treturn _medikitBackground;\n}\n\n/**\n * Returns the item's max explosion radius. Small explosions don't have a restriction.\n * Larger explosions are restricted using a formula, with a maximum of radius 10 no matter how large the explosion is.\n * @param stats unit stats\n * @return The radius.\n */\nint RuleItem::getExplosionRadius(BattleActionAttack::ReadOnly attack) const\n{\n\tint radius = 0;\n\n\tif (_damageType.FixRadius == -1)\n\t{\n\t\tradius = getPowerBonus(attack) * _damageType.RadiusEffectiveness;\n\t\tif (_damageType.FireBlastCalc)\n\t\t{\n\t\t\tradius += 1;\n\t\t}\n\t\t// cap the formula to 11\n\t\tif (radius > 11)\n\t\t{\n\t\t\tradius = 11;\n\t\t}\n\t\tif (radius <= 0)\n\t\t{\n\t\t\tradius = 1;\n\t\t}\n\t}\n\telse\n\t{\n\t\t// unless a blast radius is actually defined.\n\t\tradius = _damageType.FixRadius;\n\t}\n\n\treturn radius;\n}\n\n/**\n * Returns the item's recovery points.\n * This is used during the battlescape debriefing score calculation.\n * @return The recovery points.\n */\nint RuleItem::getRecoveryPoints() const\n{\n\treturn _recoveryPoints;\n}\n\n/**\n * Returns the item's armor.\n * The item is destroyed when an explosion power bigger than its armor hits it.\n * @return The armor.\n */\nint RuleItem::getArmor() const\n{\n\treturn _armor;\n}\n\n/**\n * Check if item is normal inventory item.\n */\nbool RuleItem::isInventoryItem() const\n{\n\treturn getBigSprite() > -1 && isFixed() == false;\n}\n\n/**\n * Checks if item have some use in battlescape.\n */\nbool RuleItem::isUsefulBattlescapeItem() const\n{\n\treturn (_battleType != BT_CORPSE && _battleType != BT_NONE);\n}\n\n/**\n * Returns if the item should be recoverable\n * from the battlescape.\n * @return True if it is recoverable.\n */\nbool RuleItem::isRecoverable() const\n{\n\treturn _recover;\n}\n\n\n/**\n * Returns if the corpse item should be recoverable from the battlescape.\n * @return True if it is recoverable.\n */\nbool RuleItem::isCorpseRecoverable() const\n{\n\t// Explanation:\n\t// Since the \"recover\" flag applies to both live body (prisoner capture) and dead body (corpse recovery) in OXC,\n\t// OXCE adds this new flag to allow recovery of a live body, but disable recovery of the corpse\n\t// (used in mods mostly to ignore dead bodies of killed humans)\n\treturn _recoverCorpse;\n}\n\n\n/**\n* Checks if the item can be equipped in base defense mission.\n* @return True if it can be equipped.\n*/\nbool RuleItem::canBeEquippedBeforeBaseDefense() const\n{\n\treturn !_ignoreInBaseDefense;\n}\n\n/**\n * Check if the item can be equipped to craft inventory.\n * @return True if it can be equipped.\n */\nbool RuleItem::canBeEquippedToCraftInventory() const\n{\n\treturn !_ignoreInCraftEquip;\n}\n\n/**\n * Returns the item's Turret Type.\n * @return The turret index (-1 for no turret).\n */\nint RuleItem::getTurretType() const\n{\n\treturn _turretType;\n}\n\n/**\n * Returns first turn when AI can use item.\n * @param Pointer to the mod. 0 by default.\n * @return First turn when AI can use item.\n *\tif mod == 0 returns only local defined aiUseDelay\n *\telse takes into account global define of aiUseDelay for this item\n */\nint RuleItem::getAIUseDelay(const Mod *mod) const\n{\n\tif (mod == 0 || _aiUseDelay >= 0)\n\t\treturn _aiUseDelay;\n\n\tswitch (getBattleType())\n\t{\n\tcase BT_FIREARM:\n\t\tif (getWaypoints())\n\t\t{\n\t\t\treturn mod->getAIUseDelayBlaster();\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn mod->getAIUseDelayFirearm();\n\t\t}\n\n\tcase BT_MELEE:\n\t\treturn mod->getAIUseDelayMelee();\n\n\tcase BT_GRENADE:\n\t\treturn mod->getAIUseDelayGrenade();\n\n\tcase BT_PROXIMITYGRENADE:\n\t\treturn mod->getAIUseDelayProxy();\n\n\tcase BT_PSIAMP:\n\t\treturn mod->getAIUseDelayPsionic();\n\n\tcase BT_MEDIKIT:\n\t\treturn mod->getAIUseDelayMedikit();\n\n\tdefault:\n\t\treturn _aiUseDelay;\n\t}\n}\n\n/**\n * Returns number of melee hits AI should do when attacking enemy.\n * @return Number of hits.\n */\nint RuleItem::getAIMeleeHitCount() const\n{\n\treturn _aiMeleeHitCount;\n}\n\n/**\n * Returns if this is a live alien.\n * @return True if this is a live alien.\n */\nbool RuleItem::isAlien() const\n{\n\treturn _liveAlien;\n}\n\n/**\n* Returns to which type of prison does the live alien belong.\n* @return Prison type.\n*/\nint RuleItem::getPrisonType() const\n{\n\treturn _liveAlienPrisonType;\n}\n\n/**\n * Returns whether this item charges a flat rate for costAimed.\n * @return True if this item charges a flat rate for costAimed.\n */\nRuleItemUseFlat RuleItem::getFlatAimed() const\n{\n\treturn getDefault(_confAimed.flat, _flatUse);\n}\n\n/**\n * Returns whether this item charges a flat rate for costAuto.\n * @return True if this item charges a flat rate for costAuto.\n */\nRuleItemUseFlat RuleItem::getFlatAuto() const\n{\n\treturn getDefault(_confAuto.flat, _confAimed.flat, _flatUse);\n}\n\n/**\n * Returns whether this item charges a flat rate for costSnap.\n * @return True if this item charges a flat rate for costSnap.\n */\nRuleItemUseFlat RuleItem::getFlatSnap() const\n{\n\treturn getDefault(_confSnap.flat, _confAimed.flat, _flatUse);\n}\n\n/**\n * Returns whether this item charges a flat rate for costMelee.\n * @return True if this item charges a flat rate for costMelee.\n */\nRuleItemUseFlat RuleItem::getFlatMelee() const\n{\n\treturn getDefault(_confMelee.flat, _flatUse);\n}\n\n/**\n * Returns whether this item charges a flat rate of use and attack cost.\n * @return True if this item charges a flat rate of use and attack cost.\n */\nRuleItemUseFlat RuleItem::getFlatUse() const\n{\n\treturn getDefault(_flatUse);\n}\n\n/**\n * Returns whether this item charges a flat rate for costThrow.\n * @return True if this item charges a flat rate for costThrow.\n */\nRuleItemUseFlat RuleItem::getFlatThrow() const\n{\n\treturn getDefault(_flatThrow);\n}\n\n/**\n * Returns whether this item charges a flat rate for costPrime.\n * @return True if this item charges a flat rate for costPrime.\n */\nRuleItemUseFlat RuleItem::getFlatPrime() const\n{\n\treturn getDefault(_flatPrime);\n}\n\n/**\n * Returns whether this item charges a flat rate for costUnprime.\n * @return True if this item charges a flat rate for costUnprime.\n */\nRuleItemUseFlat RuleItem::getFlatUnprime() const\n{\n\treturn getDefault(_flatUnprime);\n}\n\n/**\n * Returns if this weapon should arc its shots.\n * @return True if this weapon should arc its shots.\n */\nbool RuleItem::getArcingShot() const\n{\n\treturn _arcingShot;\n}\n\n/**\n * Returns the experience training mode configured for this weapon.\n * @return The mode ID.\n */\nExperienceTrainingMode RuleItem::getExperienceTrainingMode() const\n{\n\treturn _experienceTrainingMode;\n}\n\n/**\n * Gets the attraction value for this item (for AI).\n * @return The attraction value.\n */\nint RuleItem::getAttraction() const\n{\n\treturn _attraction;\n}\n\n/**\n * Gets the list weight for this research item\n * @return The list weight.\n */\nint RuleItem::getListOrder() const\n{\n\treturn _listOrder;\n}\n\n/**\n * Gets the maximum range of this weapon\n * @return The maximum range.\n */\nint RuleItem::getMaxRange() const\n{\n\treturn _maxRange;\n}\n\n/**\n * Checks whether a given distance is out of range for this item.\n * @param distanceSq Given distance squared.\n * @return True, if out of range.\n */\nbool RuleItem::isOutOfRange(int distanceSq) const\n{\n\tbool outOfRange = distanceSq > (_maxRange * _maxRange);\n\t// special handling for short ranges and diagonals\n\tif (outOfRange)\n\t{\n\t\t// special handling for maxRange 1: allow it to target diagonally adjacent tiles (one diagonal move)\n\t\tif (_maxRange == 1 && distanceSq <= 3)\n\t\t{\n\t\t\toutOfRange = false;\n\t\t}\n\t\t// special handling for maxRange 2: allow it to target diagonally adjacent tiles (one diagonal move + one straight move)\n\t\telse if (_maxRange == 2 && distanceSq <= 6)\n\t\t{\n\t\t\toutOfRange = false;\n\t\t}\n\t}\n\treturn outOfRange;\n}\n\n/**\n * Checks whether a given distance is out of throw range for this item.\n * @return True, if out of throw range.\n */\nbool RuleItem::isOutOfThrowRange(int distanceSq, int depth) const\n{\n\tbool outOfRange = false;\n\n\tif (depth > 0)\n\t{\n\t\tif (distanceSq > _underwaterThrowRange * _underwaterThrowRange)\n\t\t{\n\t\t\toutOfRange = true;\n\t\t}\n\t}\n\telse\n\t{\n\t\tif (distanceSq > _throwRange * _throwRange)\n\t\t{\n\t\t\toutOfRange = true;\n\t\t}\n\t}\n\n\t// no special handling for short ranges and diagonals\n\treturn outOfRange;\n}\n\n/**\n * Gets the maximum effective range of this weapon when using Aimed Shot.\n * @return The maximum range.\n */\nint RuleItem::getAimRange() const\n{\n\treturn _confAimed.range;\n}\n\n/**\n * Gets the maximum effective range of this weapon for Snap Shot.\n * @return The maximum range.\n */\nint RuleItem::getSnapRange() const\n{\n\treturn _confSnap.range;\n}\n\n/**\n * Gets the maximum effective range of this weapon for Auto Shot.\n * @return The maximum range.\n */\nint RuleItem::getAutoRange() const\n{\n\treturn _confAuto.range;\n}\n\n/**\n * Gets the minimum effective range of this weapon.\n * @return The minimum effective range.\n */\nint RuleItem::getMinRange() const\n{\n\treturn _minRange;\n}\n\n/**\n * Gets the accuracy dropoff value of this weapon.\n * @return The per-tile dropoff.\n */\nint RuleItem::getDropoff() const\n{\n\treturn _dropoff;\n}\n\n/**\n * Helper function to calculate limits and dropoff.\n * @return The per-tile dropoff.\n */\nint RuleItem::calculateLimits(int& upperLimit, int& lowerLimit, int depth, BattleActionType type) const\n{\n\tupperLimit = type == BA_THROW ? 200 : getAimRange();\n\tlowerLimit = type == BA_THROW ?   0 : getMinRange();\n\n\tif (Options::battleUFOExtenderAccuracy)\n\t{\n\t\tswitch (type)\n\t\t{\n\t\tcase BA_SNAPSHOT:\n\t\t\tupperLimit = getSnapRange();\n\t\t\tbreak;\n\t\tcase BA_AUTOSHOT:\n\t\t\tupperLimit = getAutoRange();\n\t\t\tbreak;\n\t\tcase BA_THROW:\n\t\t\tupperLimit = depth > 0 ? getUnderwaterThrowDropoffRange() : getThrowDropoffRange();\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn type == BA_THROW ? getThrowDropoff() : getDropoff();\n}\n\n/**\n * Gets the speed at which this bullet travels.\n * @return The speed.\n */\nint RuleItem::getBulletSpeed() const\n{\n\treturn _bulletSpeed;\n}\n\n/**\n * Gets the speed at which this bullet explodes.\n * @return The speed.\n */\nint RuleItem::getExplosionSpeed() const\n{\n\treturn _explosionSpeed;\n}\n\n/**\n * is this item a rifle?\n * @return whether or not it is a rifle.\n */\nbool RuleItem::isRifle() const\n{\n\treturn (_battleType == BT_FIREARM || _battleType == BT_MELEE) && _twoHanded;\n}\n\n/**\n * is this item a pistol?\n * @return whether or not it is a pistol.\n */\nbool RuleItem::isPistol() const\n{\n\treturn (_battleType == BT_FIREARM || _battleType == BT_MELEE) && !_twoHanded;\n}\n\n/**\n * Gets the number of projectiles this ammo shoots at once.\n * @return The number of projectiles.\n */\nint RuleItem::getShotgunPellets() const\n{\n\treturn _shotgunPellets;\n}\n\n/**\n* Gets the shotgun behavior type. This is an attribute of shotgun ammo.\n* @return 0 = cone-like spread (vanilla), 1 = grouping.\n*/\nint RuleItem::getShotgunBehaviorType() const\n{\n\treturn _shotgunBehaviorType;\n}\n\n/**\n* Gets the spread of shotgun projectiles. This is an attribute of shotgun ammo.\n* Can be used in both shotgun behavior types.\n* @return The shotgun spread.\n*/\nint RuleItem::getShotgunSpread() const\n{\n\treturn _shotgunSpread;\n}\n\n/**\n* Gets the shotgun choke value for modifying pellet spread. This is an attribute of the weapon (not ammo).\n* @return The shotgun choke value.\n*/\nint RuleItem::getShotgunChoke() const\n{\n\treturn _shotgunChoke;\n}\n\n/**\n * Gets the unit that the victim is morphed into when attacked.\n * @return The weapon's zombie unit.\n */\nconst std::string &RuleItem::getZombieUnit(const BattleUnit* victim) const\n{\n\tif (victim)\n\t{\n\t\t// by armor and gender\n\t\tif (victim->getGender() == GENDER_MALE)\n\t\t{\n\t\t\tauto i = _zombieUnitByArmorMale.find(victim->getArmor()->getType());\n\t\t\tif (i != _zombieUnitByArmorMale.end())\n\t\t\t{\n\t\t\t\treturn i->second;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tauto j = _zombieUnitByArmorFemale.find(victim->getArmor()->getType());\n\t\t\tif (j != _zombieUnitByArmorFemale.end())\n\t\t\t{\n\t\t\t\treturn j->second;\n\t\t\t}\n\t\t}\n\t\t// by type\n\t\tconst std::string victimType = victim->getUnitRules() ? victim->getUnitRules()->getType() : victim->getGeoscapeSoldier()->getRules()->getType();\n\t\tauto k = _zombieUnitByType.find(victimType);\n\t\tif (k != _zombieUnitByType.end())\n\t\t{\n\t\t\treturn k->second;\n\t\t}\n\t}\n\t// fall back\n\treturn _zombieUnit;\n}\n\n/**\n * How much damage does this weapon do when you punch someone in the face with it?\n * @return The weapon's melee power.\n */\nint RuleItem::getMeleePower() const\n{\n\treturn _meleePower;\n}\n\n/**\n * Checks if this item can be used to target a given faction.\n * Usage #1: checks the psiamp's allowed targets.\n * - Not used in AI.\n * - Mind control of the same faction is hardcoded disabled.\n * Usage #2: checks if a death trap item applies to a given faction (it use `attacker == FACTION_PLAYER`).\n * @return True if allowed, false otherwise.\n */\nbool RuleItem::isTargetAllowed(UnitFaction targetFaction, UnitFaction attacker) const\n{\n\tif (targetFaction == attacker) // same faction \"attack\"\n\t{\n\t\treturn _targetMatrix & 1;\n\t}\n\telse if ((targetFaction == FACTION_HOSTILE) || (attacker == FACTION_HOSTILE)) // can't be both true as first `if` cover this case\n\t{\n\t\treturn _targetMatrix & 2;\n\t}\n\telse if ((targetFaction == FACTION_NEUTRAL) || (attacker == FACTION_NEUTRAL)) // only `Player -> Neutral` or `Neutral -> Player` left\n\t{\n\t\treturn _targetMatrix & 4;\n\t}\n\treturn false;\n}\n\n/**\n * Is line of sight required for this psionic weapon to function?\n * @return If line of sight is required.\n */\nbool RuleItem::isLOSRequired() const\n{\n\treturn _LOSRequired;\n}\n\n/**\n * Can this item only be used underwater?\n * @return if this is an underwater weapon or not.\n */\nbool RuleItem::isWaterOnly() const\n{\n\treturn _underwaterOnly;\n}\n\n/**\n* Can this item only be used on land?\n* @return if this is a land weapon or not.\n*/\nbool RuleItem::isLandOnly() const\n{\n\treturn _landOnly;\n}\n\n/**\n * Is psi skill is required to use this weapon.\n * @return If psi skill is required.\n */\nbool RuleItem::isPsiRequired() const\n{\n\treturn _psiReqiured;\n}\n\n/**\n * Is mana required to use this weapon?\n * @return If mana is required.\n */\nbool RuleItem::isManaRequired() const\n{\n\treturn _manaRequired;\n}\n\n/**\n * Compute power bonus based on unit stats.\n * @param stats unit stats\n * @return bonus power.\n */\nint RuleItem::getPowerBonus(BattleActionAttack::ReadOnly attack) const\n{\n\treturn _damageBonus.getBonus(attack, _power);\n}\n\n/**\n * Compute power bonus based on unit stats.\n * @param stats unit stats\n * @return bonus power.\n */\nint RuleItem::getMeleeBonus(BattleActionAttack::ReadOnly attack) const\n{\n\treturn _meleeBonus.getBonus(attack, _meleePower);\n}\n\n/**\n * Compute multiplier of melee hit chance based on unit stats.\n * @param stats unit stats\n * @return multiplier.\n */\nint RuleItem::getMeleeMultiplier(BattleActionAttack::ReadOnly attack) const\n{\n\treturn _meleeMulti.getBonus(attack);\n}\n\n/**\n * Compute multiplier of accuracy based on unit stats.\n * @param stats unit stats\n * @return multiplier.\n */\nint RuleItem::getAccuracyMultiplier(BattleActionAttack::ReadOnly attack) const\n{\n\treturn _accuracyMulti.getBonus(attack);\n}\n\n/**\n * Compute multiplier of throw accuracy based on unit stats.\n * @param stats unit stats\n * @return multiplier.\n */\nint RuleItem::getThrowMultiplier(BattleActionAttack::ReadOnly attack) const\n{\n\treturn _throwMulti.getBonus(attack);\n}\n\n/**\n * Compute multiplier of close quarters accuracy based on unit stats.\n * @param stats unit stats\n * @return multiplier.\n */\nint RuleItem::getCloseQuartersMultiplier(BattleActionAttack::ReadOnly attack) const\n{\n\treturn _closeQuartersMulti.getBonus(attack);\n}\n\n/**\n * Gets the associated special type of this item.\n * note that type 14 is the alien brain, and types\n * 0 and 1 are \"regular tile\" and \"starting point\"\n * so try not to use those ones.\n * @return special type.\n */\nint RuleItem::getSpecialType() const\n{\n\treturn _specialType;\n}\n\n/**\n * Gets the color offset to use for the vapor trail.\n * @param depth battlescape depth (0=surface, 1-3=underwater)\n * @return the color offset.\n */\nint RuleItem::getVaporColor(int depth) const\n{\n\tif (depth == 0)\n\t\treturn _vaporColorSurface;\n\n\treturn _vaporColor;\n}\n\n/**\n * Gets the vapor cloud density for the vapor trail.\n * @param depth battlescape depth (0=surface, 1-3=underwater)\n * @return the vapor density.\n */\nint RuleItem::getVaporDensity(int depth) const\n{\n\tif (depth == 0)\n\t\treturn _vaporDensitySurface;\n\n\treturn _vaporDensity;\n}\n\n/**\n * Gets the vapor cloud probability for the vapor trail.\n * @param depth battlescape depth (0=surface, 1-3=underwater)\n * @return the vapor probability.\n */\nint RuleItem::getVaporProbability(int depth) const\n{\n\tif (depth == 0)\n\t\treturn _vaporProbabilitySurface;\n\n\treturn _vaporProbability;\n}\n\n/**\n * Gets the index of the sprite in the CustomItemPreview sprite set.\n * @return Sprite index.\n */\nconst std::vector<int> &RuleItem::getCustomItemPreviewIndex() const\n{\n\treturn _customItemPreviewIndex;\n}\n\n/**\n* Gets the kneel bonus (15% bonus is encoded as 100+15 = 115).\n* @return Kneel bonus.\n*/\nint RuleItem::getKneelBonus(const Mod *mod) const\n{\n\treturn _kneelBonus != -1 ? _kneelBonus : mod->getKneelBonusGlobal();\n}\n\n/**\n* Gets the one-handed penalty (20% penalty is encoded as 100-20 = 80).\n* @return One-handed penalty.\n*/\nint RuleItem::getOneHandedPenalty(const Mod *mod) const\n{\n\treturn _oneHandedPenalty != -1 ? _oneHandedPenalty : mod->getOneHandedPenaltyGlobal();\n}\n\n/**\n* Gets the monthly salary.\n* @return Monthly salary.\n*/\nint RuleItem::getMonthlySalary() const\n{\n\treturn _monthlySalary;\n}\n\n/**\n* Gets the monthly maintenance.\n* @return Monthly maintenance.\n*/\nint RuleItem::getMonthlyMaintenance() const\n{\n\treturn _monthlyMaintenance;\n}\n\n/**\n * Gets how many waypoints are used for a \"spray\" attack\n * @return Number of waypoints.\n */\nint RuleItem::getSprayWaypoints() const\n{\n\treturn _sprayWaypoints;\n}\n\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tScript binding\n////////////////////////////////////////////////////////////\n\nnamespace\n{\n\nvoid getTypeScript(const RuleItem* r, ScriptText& txt)\n{\n\tif (r)\n\t{\n\t\ttxt = { r->getType().c_str() };\n\t\treturn;\n\t}\n\telse\n\t{\n\t\ttxt = ScriptText::empty;\n\t}\n}\n\nvoid getBattleTypeScript(const RuleItem *ri, int &ret)\n{\n\tif (ri)\n\t{\n\t\tret = (int)ri->getBattleType();\n\t\treturn;\n\t}\n\tret = (int)BT_NONE;\n}\n\nvoid isSingleTargetScript(const RuleItem* r, int &ret)\n{\n\tif (r)\n\t{\n\t\tret = (r->getDamageType()->FixRadius == 0);\n\t\treturn;\n\t}\n\telse\n\t{\n\t\tret = 0;\n\t}\n}\n\nvoid hasCategoryScript(const RuleItem* ri, int& val, const std::string& cat)\n{\n\tif (ri)\n\t{\n\t\tauto it = std::find(ri->getCategories().begin(), ri->getCategories().end(), cat);\n\t\tif (it != ri->getCategories().end())\n\t\t{\n\t\t\tval = 1;\n\t\t\treturn;\n\t\t}\n\t}\n\tval = 0;\n}\n\nvoid getResistTypeScript(const RuleDamageType* rdt, int &ret)\n{\n\tret = rdt ? rdt->ResistType : 0;\n}\n\nvoid getAoeScript(const RuleDamageType* rdt, int &ret)\n{\n\tret = rdt ? !rdt->isDirect() : 0;\n}\n\nvoid getRandomTypeScript(const RuleDamageType* rdt, int &ret)\n{\n\tret = rdt ? rdt->RandomType : 0;\n}\n\nvoid getArmorEffectivenessScript(const RuleDamageType* rdt, int& ret)\n{\n\tret = rdt ? round(rdt->ArmorEffectiveness * 100) : 0;\n}\n\ntemplate<float RuleDamageType::* Ptr>\nvoid getDamageToScript(const RuleDamageType* rdt, int &ret, int value)\n{\n\tret = rdt ? (rdt->* Ptr) * value : 0;\n}\n\nvoid getRandomDamageScript(const RuleDamageType* rdt, int &ret, int value, RNG::RandomState* rng)\n{\n\tret = 0;\n\tif (rdt && rng)\n\t{\n\t\tauto func = [&](int min, int max)\n\t\t{\n\t\t\treturn rng->generate(min, max);\n\t\t};\n\t\tret = rdt->getRandomDamage(value, &func);\n\t}\n}\n\nstd::string debugDisplayScript(const RuleDamageType* rdt)\n{\n\tif (rdt)\n\t{\n\t\tstd::string s;\n\t\ts += \"RuleDamageType\";\n\t\ts += \"(resist: \";\n\t\ts += std::to_string((int)rdt->ResistType);\n\t\ts += \" random: \";\n\t\ts += std::to_string((int)rdt->RandomType);\n\t\ts += \")\";\n\t\treturn s;\n\t}\n\telse\n\t{\n\t\treturn \"null\";\n\t}\n}\n\nstd::string debugDisplayScript(const RuleItem* ri)\n{\n\tif (ri)\n\t{\n\t\tstd::string s;\n\t\ts += RuleItem::ScriptName;\n\t\ts += \"(type: \\\"\";\n\t\ts += ri->getType();\n\t\ts += \"\\\")\";\n\t\treturn s;\n\t}\n\telse\n\t{\n\t\treturn \"null\";\n\t}\n}\n\n}\n\n\n/**\n * Register RuleItem in script parser.\n * @param parser Script parser.\n */\nvoid RuleItem::ScriptRegister(ScriptParserBase* parser)\n{\n\t{\n\t\tconst auto name = std::string{ \"RuleDamageType\" };\n\t\tparser->registerRawPointerType<RuleDamageType>(name);\n\t\tBind<RuleDamageType> rs = { parser, name };\n\n\t\trs.add<&RuleDamageType::isDirect>(\"isDirect\", \"if this damage type affects only one target\");\n\t\trs.add<&getAoeScript>(\"isAreaOfEffect\", \"if this damage type can affect multiple targets\");\n\n\t\trs.add<&getResistTypeScript>(\"getResistType\", \"which damage resistance type is used for damage reduction\");\n\t\trs.add<&getRandomTypeScript>(\"getRandomType\", \"how to calculate randomized weapon damage from the weapon's power\");\n\n\t\trs.add<&getArmorEffectivenessScript>(\"getArmorEffectiveness\", \"how effective is a unit's armor against this damage, % (value multiplied by 100 compared to ruleset value)\");\n\n\t\trs.add<&getDamageToScript<&RuleDamageType::ToArmorPre>>(\"getDamageToArmorPre\", \"calculated damage value multiplied by the corresponding modifier\");\n\t\trs.add<&getDamageToScript<&RuleDamageType::ToArmor>>(\"getDamageToArmor\", \"calculated damage value multiplied by the corresponding modifier\");\n\t\trs.add<&getDamageToScript<&RuleDamageType::ToEnergy>>(\"getDamageToEnergy\", \"calculated damage value multiplied by the corresponding modifier\");\n\t\trs.add<&getDamageToScript<&RuleDamageType::ToHealth>>(\"getDamageToHealth\", \"calculated damage value multiplied by the corresponding modifier\");\n\t\trs.add<&getDamageToScript<&RuleDamageType::ToItem>>(\"getDamageToItem\", \"calculated damage value multiplied by the corresponding modifier\");\n\t\trs.add<&getDamageToScript<&RuleDamageType::ToMana>>(\"getDamageToMana\", \"calculated damage value multiplied by the corresponding modifier\");\n\t\trs.add<&getDamageToScript<&RuleDamageType::ToMorale>>(\"getDamageToMorale\", \"calculated damage value multiplied by the corresponding modifier\");\n\t\trs.add<&getDamageToScript<&RuleDamageType::ToStun>>(\"getDamageToStun\", \"calculated damage value multiplied by the corresponding modifier\");\n\t\trs.add<&getDamageToScript<&RuleDamageType::ToTile>>(\"getDamageToTile\", \"calculated damage value multiplied by the corresponding modifier\");\n\t\trs.add<&getDamageToScript<&RuleDamageType::ToTime>>(\"getDamageToTime\", \"calculated damage value multiplied by the corresponding modifier\");\n\t\trs.add<&getDamageToScript<&RuleDamageType::ToWound>>(\"getDamageToWound\", \"calculated damage value multiplied by the corresponding modifier\");\n\n\t\trs.add<&getRandomDamageScript>(\"getRandomDamage\", \"calculated damage value (based on weapon's power)\");\n\n\t\trs.addDebugDisplay<&debugDisplayScript>();\n\t}\n\n\tparser->registerPointerType<Mod>();\n\n\tBind<RuleItem> ri = { parser };\n\n\tri.addCustomConst(\"BT_NONE\", BT_NONE);\n\tri.addCustomConst(\"BT_FIREARM\", BT_FIREARM);\n\tri.addCustomConst(\"BT_AMMO\", BT_AMMO);\n\tri.addCustomConst(\"BT_MELEE\", BT_MELEE);\n\tri.addCustomConst(\"BT_GRENADE\", BT_GRENADE);\n\tri.addCustomConst(\"BT_PROXIMITYGRENADE\", BT_PROXIMITYGRENADE);\n\tri.addCustomConst(\"BT_MEDIKIT\", BT_MEDIKIT);\n\tri.addCustomConst(\"BT_SCANNER\", BT_SCANNER);\n\tri.addCustomConst(\"BT_MINDPROBE\", BT_MINDPROBE);\n\tri.addCustomConst(\"BT_PSIAMP\", BT_PSIAMP);\n\tri.addCustomConst(\"BT_FLARE\", BT_FLARE);\n\tri.addCustomConst(\"BT_CORPSE\", BT_CORPSE);\n\n\tri.add<&getTypeScript>(\"getType\");\n\n\tri.add<&RuleItem::getAccuracyAimed>(\"getAccuracyAimed\");\n\tri.add<&RuleItem::getAccuracyAuto>(\"getAccuracyAuto\");\n\tri.add<&RuleItem::getAccuracyMelee>(\"getAccuracyMelee\");\n\tri.add<&RuleItem::getAccuracyMind>(\"getAccuracyMind\");\n\tri.add<&RuleItem::getAccuracyPanic>(\"getAccuracyPanic\");\n\tri.add<&RuleItem::getAccuracySnap>(\"getAccuracySnap\");\n\tri.add<&RuleItem::getAccuracyThrow>(\"getAccuracyThrow\");\n\tri.add<&RuleItem::getAccuracyUse>(\"getAccuracyUse\");\n\n\tri.add<&RuleItem::getPower>(\"getPower\", \"primary power, before applying unit bonuses, random rolls or other modifiers\");\n\tri.add<&RuleItem::getDamageType>(\"getDamageType\", \"primary damage type\");\n\tri.add<&RuleItem::getMeleePower>(\"getMeleePower\", \"secondary power (gunbutt), before applying unit bonuses, random rolls or other modifiers\");\n\tri.add<&RuleItem::getMeleeType>(\"getMeleeDamageType\", \"secondary damage type (gunbutt)\");\n\n\tri.add<&RuleItem::getArmor>(\"getArmorValue\");\n\tri.add<&RuleItem::getWeight>(\"getWeight\");\n\tri.add<&getBattleTypeScript>(\"getBattleType\");\n\tri.add<&RuleItem::getWaypoints>(\"getWaypoints\");\n\tri.add<&RuleItem::isWaterOnly>(\"isWaterOnly\");\n\tri.add<&RuleItem::isTwoHanded>(\"isTwoHanded\");\n\tri.add<&RuleItem::isBlockingBothHands>(\"isBlockingBothHands\");\n\tri.add<&isSingleTargetScript>(\"isSingleTarget\");\n\tri.add<&hasCategoryScript>(\"hasCategory\");\n\n\tri.addScriptValue<BindBase::OnlyGet, &RuleItem::_scriptValues>();\n\tri.addDebugDisplay<&debugDisplayScript>();\n}\n\n}\n"
  },
  {
    "path": "src/Mod/RuleItem.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include <vector>\n#include <unordered_map>\n#include \"../Engine/Yaml.h\"\n#include \"LoadYaml.h\"\n#include \"RuleStatBonus.h\"\n#include \"RuleDamageType.h\"\n#include \"ModScript.h\"\n#include \"RuleResearch.h\"\n#include \"RuleBaseFacilityFunctions.h\"\n\nnamespace OpenXcom\n{\n\nenum BattleType { BT_NONE, BT_FIREARM, BT_AMMO, BT_MELEE, BT_GRENADE, BT_PROXIMITYGRENADE, BT_MEDIKIT, BT_SCANNER, BT_MINDPROBE, BT_PSIAMP, BT_FLARE, BT_CORPSE };\nenum BattleFuseType { BFT_NONE = -3, BFT_INSTANT = -2, BFT_SET = -1, BFT_FIX_MIN = 0, BFT_FIX_MAX = 64 };\nenum BattleMediKitType { BMT_NORMAL = 0, BMT_HEAL = 1, BMT_STIMULANT = 2, BMT_PAINKILLER = 3 };\nenum BattleMediKitAction { BMA_HEAL = 1, BMA_STIMULANT = 2, BMA_PAINKILLER = 4 };\nenum ExperienceTrainingMode {\n\tETM_DEFAULT,\n\tETM_MELEE_100, ETM_MELEE_50, ETM_MELEE_33,\n\tETM_FIRING_100, ETM_FIRING_50, ETM_FIRING_33,\n\tETM_THROWING_100, ETM_THROWING_50, ETM_THROWING_33,\n\tETM_FIRING_AND_THROWING,\n\tETM_FIRING_OR_THROWING,\n\tETM_REACTIONS,\n\tETM_REACTIONS_AND_MELEE, ETM_REACTIONS_AND_FIRING, ETM_REACTIONS_AND_THROWING,\n\tETM_REACTIONS_OR_MELEE, ETM_REACTIONS_OR_FIRING, ETM_REACTIONS_OR_THROWING,\n\tETM_BRAVERY, ETM_BRAVERY_2X,\n\tETM_BRAVERY_AND_REACTIONS,\n\tETM_BRAVERY_OR_REACTIONS, ETM_BRAVERY_OR_REACTIONS_2X,\n\tETM_PSI_STRENGTH, ETM_PSI_STRENGTH_2X,\n\tETM_PSI_SKILL, ETM_PSI_SKILL_2X,\n\tETM_PSI_STRENGTH_AND_SKILL, ETM_PSI_STRENGTH_AND_SKILL_2X,\n\tETM_PSI_STRENGTH_OR_SKILL, ETM_PSI_STRENGTH_OR_SKILL_2X,\n\tETM_NOTHING\n};\nenum BattleActionType : Uint8\n{\n\tBA_NONE = 0,\n\n\tBA_TURN = 1,\n\tBA_WALK = 2,\n\tBA_KNEEL = 3,\n\n\tBA_PRIME = 4,\n\tBA_UNPRIME = 5,\n\tBA_THROW = 6,\n\tBA_AUTOSHOT = 7,\n\tBA_SNAPSHOT = 8,\n\tBA_AIMEDSHOT = 9,\n\tBA_HIT = 10,\n\n\tBA_USE = 11,\n\tBA_LAUNCH = 12,\n\tBA_MINDCONTROL = 13,\n\tBA_PANIC = 14,\n\n\tBA_RETHINK = 15,\n\n\tBA_CQB = 16,\n\n\tBA_TRIGGER_TIMED_GRENADE = 17,\n\tBA_TRIGGER_PROXY_GRENADE = 18,\n\n\tBA_SELF_DESTRUCT = 19,\n};\n\nenum class BattleActionOrigin { CENTRE = 0, LEFT, RIGHT }; // Used for off-centre shooting.\n\nstruct BattleActionCost;\nclass BattleItem;\nclass SavedGame;\nclass Base;\nclass RuleSkill;\nclass Unit;\nclass SurfaceSet;\nclass Surface;\nclass Mod;\nclass RuleInventory;\nclass RuleItemCategory;\n\nenum UnitFaction : int;\n\ntemplate<typename T>\nstruct RuleItemUseRuleBase\n{\n\tT Time;\n\tT Energy;\n\tT Morale;\n\tT Health;\n\tT Stun;\n\tT Mana;\n\n\t/// Default constructor.\n\tRuleItemUseRuleBase() : Time(), Energy(), Morale(), Health(), Stun(), Mana()\n\t{\n\n\t}\n\t/// Create new cost with one value for time units and another for rest.\n\tRuleItemUseRuleBase(T tu, T rest) : Time(tu), Energy(rest), Morale(rest), Health(rest), Stun(rest), Mana(rest)\n\t{\n\n\t}\n\n\tvoid load(const YAML::YamlNodeReader& reader)\n\t{\n\t\treader.tryRead(\"time\", Time);\n\t\treader.tryRead(\"energy\", Energy);\n\t\treader.tryRead(\"morale\", Morale);\n\t\treader.tryRead(\"health\", Health);\n\t\treader.tryRead(\"stun\", Stun);\n\t\treader.tryRead(\"mana\", Mana);\n\t}\n};\n\nstruct RuleItemUseCost : RuleItemUseRuleBase<Sint16>\n{\n\t/// Default constructor.\n\tRuleItemUseCost() : RuleItemUseRuleBase{ 0, 0 }\n\t{\n\n\t}\n\t/// Create new cost with one value for time units and another for rest.\n\tRuleItemUseCost(Sint16 tu, Sint16 rest = 0) : RuleItemUseRuleBase{tu, rest}\n\t{\n\n\t}\n\t/// Copy constructor.\n\tRuleItemUseCost(const RuleItemUseRuleBase<Sint16>& b) : RuleItemUseRuleBase{ b }\n\t{\n\n\t}\n\n\t/// Add cost.\n\tRuleItemUseCost& operator+=(const RuleItemUseCost& cost)\n\t{\n\t\tTime += cost.Time;\n\t\tEnergy += cost.Energy;\n\t\tMorale += cost.Morale;\n\t\tHealth += cost.Health;\n\t\tStun += cost.Stun;\n\t\tMana += cost.Mana;\n\t\treturn *this;\n\t}\n};\n\nstruct RuleItemUseFlat : RuleItemUseRuleBase<bool>\n{\n\t/// Default constructor.\n\tRuleItemUseFlat() : RuleItemUseRuleBase{ false, false }\n\t{\n\n\t}\n\t/// Create new cost with one value for time units and another for rest.\n\tRuleItemUseFlat(bool tu, bool rest = false) : RuleItemUseRuleBase{tu, rest}\n\t{\n\n\t}\n\t/// Copy constructor.\n\tRuleItemUseFlat(const RuleItemUseRuleBase<bool>& b) : RuleItemUseRuleBase{ b }\n\t{\n\n\t}\n};\n\nstruct RuleItemUseCostRule : RuleItemUseRuleBase<NullableValue<Sint16>>\n{\n\t/// Default constructor.\n\tRuleItemUseCostRule() : RuleItemUseRuleBase{ 0, 0 }\n\t{\n\n\t}\n\t/// Create new cost with one value for time units and another for rest.\n\tRuleItemUseCostRule(NullableValue<Sint16> tu, NullableValue<Sint16> rest = 0) : RuleItemUseRuleBase{tu, rest}\n\t{\n\n\t}\n\n\t/**\n\t * Load use cost.\n\t * @param a Item use cost.\n\t * @param node YAML node.\n\t * @param name Name of action type.\n\t */\n\tvoid loadCost(const YAML::YamlNodeReader& reader, const std::string& name)\n\t{\n\t\treader.tryRead(ryml::to_csubstr(\"tu\" + name), Time);\n\t\tif (const auto& cost = reader[ryml::to_csubstr(\"cost\" + name)])\n\t\t{\n\t\t\tload(cost);\n\t\t}\n\t}\n};\n\nstruct RuleItemUseFlatRule : RuleItemUseRuleBase<NullableValue<bool>>\n{\n\t/// Default constructor.\n\tRuleItemUseFlatRule() : RuleItemUseRuleBase{ false, false }\n\t{\n\n\t}\n\t/// Create new cost with one value for time units and another for rest.\n\tRuleItemUseFlatRule(NullableValue<bool> tu, NullableValue<bool> rest = false) : RuleItemUseRuleBase{tu, rest}\n\t{\n\n\t}\n\n\t/**\n\t * Load use cost type (flat or percent).\n\t * @param a Item use type.\n\t * @param node YAML node.\n\t * @param name Name of action type.\n\t */\n\tvoid loadFlat(const YAML::YamlNodeReader& reader, const std::string& name)\n\t{\n\t\tif (const auto& cost = reader[ryml::to_csubstr(\"flat\" + name)])\n\t\t{\n\t\t\tif (cost.hasVal())\n\t\t\t{\n\t\t\t\tcost.tryReadVal(Time);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tload(cost);\n\t\t\t}\n\t\t}\n\t}\n};\n\n/// Get final value of cost.\ntemplate<typename T, typename... Rest>\ninline RuleItemUseRuleBase<T> getDefault(const RuleItemUseRuleBase<NullableValue<T>>& a, const Rest&... b)\n{\n\tRuleItemUseRuleBase<T> n;\n\tn.Time = coalesceNullValues(a.Time, b.Time...);\n\tn.Energy = coalesceNullValues(a.Energy, b.Energy...);\n\tn.Morale = coalesceNullValues(a.Morale, b.Morale...);\n\tn.Health = coalesceNullValues(a.Health, b.Health...);\n\tn.Stun = coalesceNullValues(a.Stun, b.Stun...);\n\tn.Mana = coalesceNullValues(a.Mana, b.Mana...);\n\treturn n;\n}\n\n/**\n * Common configuration of item action.\n */\nstruct RuleItemAction\n{\n\tint accuracy = 0;\n\tint range = 0;\n\tint shots = 1;\n\tint spendPerShot = 1;\n\tbool followProjectiles = true;\n\tint ammoSlot = 0;\n\tint ammoZombieUnitChanceOverride = -1;\n\tint ammoSpawnUnitChanceOverride = -1;\n\tint ammoSpawnItemChanceOverride = -1;\n\tRuleItemUseCostRule cost;\n\tRuleItemUseFlatRule flat;\n\tbool arcing = false; // Only overrides arcing: false on a weapon for a specific action\n\tstd::string name;\n\tstd::string shortName;\n};\n\n/**\n * Config for fuse triggers.\n */\nstruct RuleItemFuseTrigger\n{\n\tbool defaultBehavior = true;\n\tbool throwTrigger = false;\n\tbool throwExplode = false;\n\tbool proximityTrigger = false;\n\tbool proximityExplode = false;\n};\n\nnamespace helper\n{\n\n/**\n * Defined outside struct BattleActionAttack to allow forward declaration of it for RuleStatBonus\n */\nstruct BattleActionAttackReadOnlyImpl\n{\n\tBattleActionType type;\n\tconst BattleUnit *attacker = nullptr;\n\tconst BattleItem *weapon_item = nullptr;\n\tconst BattleItem *damage_item = nullptr;\n\tconst RuleSkill *skill_rules = nullptr;\n};\n\n}\n\n\n/**\n * Helper struct that has all the data needed for weapon attack.\n */\nstruct BattleActionAttack\n{\n\tBattleActionType type;\n\tBattleUnit *attacker = nullptr;\n\tBattleItem *weapon_item = nullptr;\n\tBattleItem *damage_item = nullptr;\n\tconst RuleSkill *skill_rules = nullptr;\n\n\t/**\n\t * Helper class that have only readonly access to data.\n\t */\n\tusing ReadOnly = helper::BattleActionAttackReadOnlyImpl;\n\n\t/**\n\t * Cast operator to readonly version.\n\t */\n\toperator ReadOnly() const\n\t{\n\t\treturn { type, attacker, weapon_item, damage_item, skill_rules, };\n\t}\n\n\t/// Get Action Attack from Action cost.\n\tstatic BattleActionAttack GetBeforeShoot(const BattleActionCost &action);\n\t/// Get Action Attack with updated unit and ammo.\n\tstatic BattleActionAttack GetBeforeShoot(BattleActionType type, BattleUnit *unit, BattleItem *wepon, const RuleSkill *skill = nullptr);\n\t/// Get Action Attack from Action cost with defined ammo.\n\tstatic BattleActionAttack GetAferShoot(const BattleActionCost &action, BattleItem *ammo);\n\t/// Get Action Attack with updated unit with defined ammo.\n\tstatic BattleActionAttack GetAferShoot(BattleActionType type, BattleUnit *unit, BattleItem *wepon, BattleItem *ammo, const RuleSkill *skill = nullptr);\n};\n\n/**\n * Represents a specific type of item.\n * Contains constant info about an item like\n * storage size, sell price, etc.\n * @sa Item\n */\nclass RuleItem\n{\npublic:\n\t/// Maximum number of ammo slots on weapon.\n\tstatic const int AmmoSlotMax = 4;\n\t/// Special ammo slot that represent usage of weapon itself as ammo.\n\tstatic const int AmmoSlotSelfUse = -1;\n\tstatic const int MedikitSlots = 3;\n\n\t/// Load ammo slot with checking correct range.\n\tstatic void loadAmmoSlotChecked(int& result, const YAML::YamlNodeReader& reader, const std::string& parentName);\n\nprivate:\n\tstd::string _ufopediaType;\n\tstd::string _type, _name, _nameAsAmmo; // two types of objects can have the same name\n\tstd::string _requiresBuyCountry;\n\tstd::vector<std::string> _requiresName;\n\tstd::vector<std::string> _requiresBuyName;\n\tstd::vector<const RuleResearch *> _requires, _requiresBuy;\n\tRuleBaseFacilityFunctions _requiresBuyBaseFunc;\n\tstd::map<std::string, int> _recoveryDividers;\n\tstd::map<std::string, std::vector<int> > _recoveryTransformationsName;\n\tstd::map<const RuleItem*, std::vector<int> > _recoveryTransformations;\n\tstd::vector<std::string> _categories;\n\n\tUnit* _vehicleUnit;\n\tint _vehicleFixedAmmoSlot;\n\tdouble _size;\n\tint _monthlyBuyLimit;\n\tstd::string _monthlyBuyLimitMessage;\n\tint _costBuy, _costSell, _transferTime, _weight;\n\tint _throwRange, _underwaterThrowRange;\n\tint _throwDropoffRange, _underwaterThrowDropoffRange, _throwDropoff;\n\tint _bigSprite;\n\tint _floorSprite;\n\tint _handSprite, _bulletSprite;\n\tint _specialIconSprite;\n\tstd::vector<int> _reloadSound, _primeSound, _unprimeSound;\n\tstd::vector<int> _fireSound, _hitSound;\n\tint _hitAnimation, _hitAnimFrames;\n\tstd::vector<int> _hitMissSound;\n\tint _hitMissAnimation, _hitMissAnimFrames;\n\tstd::vector<int> _meleeSound;\n\tint _meleeAnimation, _meleeAnimFrames;\n\tstd::vector<int> _meleeMissSound;\n\tint _meleeMissAnimation, _meleeMissAnimFrames;\n\tstd::vector<int> _meleeHitSound, _explosionHitSound, _psiSound;\n\tint _psiAnimation, _psiAnimFrames;\n\tstd::vector<int> _psiMissSound;\n\tint _psiMissAnimation, _psiMissAnimFrames;\n\tint _power, _powerForAnimation;\n\tbool _hidePower;\n\tbool _ignoreAmmoPower;\n\tfloat _powerRangeReduction;\n\tfloat _powerRangeThreshold;\n\tstd::vector<std::vector<std::string>> _compatibleAmmoNames = std::vector<std::vector<std::string>>(AmmoSlotMax);\n\tstd::vector<const RuleItem*> _compatibleAmmo[AmmoSlotMax];\n\tstd::unordered_map<const RuleItem*, int> _compatibleAmmoSlots;\n\tRuleDamageType _damageType, _meleeType;\n\tbool _damageTypeSet, _meleeTypeSet;\n\tRuleItemAction _confAimed, _confAuto, _confSnap, _confMelee;\n\tint _accuracyUse, _accuracyMind, _accuracyPanic, _accuracyThrow, _accuracyCloseQuarters;\n\tint _noLOSAccuracyPenalty;\n\tint _explodeInventory;\n\tRuleItemUseCostRule _costUse, _costMind, _costPanic, _costThrow, _costPrime, _costUnprime;\n\tint _clipSize, _specialChance, _tuLoad[AmmoSlotMax], _tuUnload[AmmoSlotMax];\n\tBattleType _battleType;\n\tBattleFuseType _fuseType;\n\tRuleItemFuseTrigger _fuseTriggerEvents;\n\tbool _hiddenOnMinimap;\n\tstd::string _painKillerActionName, _stimulantActionName, _healActionName;\n\tstd::string _medikitActionName, _psiAttackName, _primeActionName, _unprimeActionName, _primeActionMessage, _unprimeActionMessage;\n\tstd::string _sellActionMessage;\n\n\tbool _twoHanded, _blockBothHands, _fixedWeapon, _fixedWeaponShow, _isConsumable, _isFireExtinguisher;\n\tbool _isAmmoRechargeable;\n\tbool _specialUseEmptyHand, _specialUseEmptyHandShow;\n\tint _inventoryMoveCostPercent = 100;\n\tstd::string _defaultInventorySlotName;\n\tconst RuleInventory* _defaultInventorySlot = nullptr;\n\tint _defaultInvSlotX, _defaultInvSlotY;\n\tstd::vector<std::string> _supportedInventorySectionsNames;\n\tstd::vector<const RuleInventory*> _supportedInventorySections;\n\tint _waypoints, _invWidth, _invHeight;\n\n\tint _painKiller, _heal, _stimulant;\n\tBattleMediKitType _medikitType;\n\tbool _medikitTargetSelf, _medikitTargetImmune;\n\tint _medikitTargetMatrix;\n\tstd::string _medikitBackground;\n\tint _woundRecovery, _healthRecovery, _stunRecovery, _energyRecovery, _manaRecovery, _moraleRecovery;\n\tfloat _painKillerRecovery;\n\n\tint _recoveryPoints;\n\tint _armor;\n\tint _turretType;\n\tint _aiUseDelay, _aiMeleeHitCount;\n\tbool _recover, _recoverCorpse, _ignoreInBaseDefense, _ignoreInCraftEquip, _liveAlien;\n\tint _liveAlienPrisonType;\n\tint _attraction;\n\tRuleItemUseFlatRule _flatUse, _flatThrow, _flatPrime, _flatUnprime;\n\tbool _arcingShot;\n\tExperienceTrainingMode _experienceTrainingMode;\n\tint _manaExperience;\n\tint _loadOrder;\n\tint _listOrder, _maxRange, _minRange, _dropoff, _bulletSpeed, _explosionSpeed, _shotgunPellets;\n\tint _shotgunBehaviorType, _shotgunSpread, _shotgunChoke;\n\n\tstd::map<std::string, std::string> _zombieUnitByArmorMale, _zombieUnitByArmorFemale, _zombieUnitByType;\n\tstd::string _zombieUnit, _spawnUnitName, _spawnItemName;\n\tconst Unit* _spawnUnit = nullptr;\n\tconst RuleItem* _spawnItem = nullptr;\n\tUnitFaction _spawnUnitFaction;\n\tUnitFaction _zombieUnitFaction;\n\tint _spawnUnitChance = -1;\n\tint _zombieUnitChance = -1;\n\tint _spawnItemChance = -1;\n\n\tint _targetMatrix;\n\tbool _convertToCivilian;\n\tbool _LOSRequired, _underwaterOnly, _landOnly, _psiReqiured, _manaRequired;\n\tint _meleePower, _specialType, _vaporColor, _vaporDensity, _vaporProbability;\n\tint _vaporColorSurface, _vaporDensitySurface, _vaporProbabilitySurface;\n\tstd::vector<int> _customItemPreviewIndex;\n\tint _kneelBonus, _oneHandedPenalty;\n\tint _monthlySalary, _monthlyMaintenance;\n\tint _sprayWaypoints;\n\tRuleStatBonus _damageBonus, _meleeBonus, _accuracyMulti, _meleeMulti, _throwMulti, _closeQuartersMulti;\n\tModScript::BattleItemScripts::Container _battleItemScripts;\n\tScriptValues<RuleItem> _scriptValues;\n\n\t/// Load RuleItemUseCost from yaml.\n\tvoid loadCost(RuleItemUseCost& a, const YAML::YamlNodeReader& reader, const std::string& name) const;\n\t/// Load RuleItemUseCost as bool from yaml.\n\tvoid loadPercent(RuleItemUseCost& a, const YAML::YamlNodeReader& reader, const std::string& name) const;\n\t/// Load RuleItemAction from yaml.\n\tvoid loadConfAction(RuleItemAction& a, const YAML::YamlNodeReader& reader, const std::string& name) const;\n\t/// Gets a random sound from a given vector.\n\tint getRandomSound(const std::vector<int> &vector, int defaultValue = -1) const;\n\t/// Load RuleItemFuseTrigger from yaml.\n\tvoid loadConfFuse(RuleItemFuseTrigger& a, const YAML::YamlNodeReader& reader, const std::string& name) const;\n\npublic:\n\t/// Name of class used in script.\n\tstatic constexpr const char *ScriptName = \"RuleItem\";\n\t/// Register all useful function used by script.\n\tstatic void ScriptRegister(ScriptParserBase* parser);\n\n\t/// Creates a blank item ruleset.\n\tRuleItem(const std::string &type, int listOrder);\n\t/// Cleans up the item ruleset.\n\t~RuleItem();\n\t/// Updates item categories based on replacement rules.\n\tvoid updateCategories(std::map<std::string, std::string> *replacementRules);\n\t/// Loads item data from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader, Mod *mod, const ModScript& parsers);\n\t/// Cross link with other rules.\n\tvoid afterLoad(const Mod* mod);\n\n\t/// Gets the custom name of the Ufopedia article related to this item.\n\tconst std::string& getUfopediaType() const;\n\n\t/// Gets the item's type.\n\tconst std::string &getType() const;\n\t/// Gets the item's name.\n\tconst std::string &getName() const;\n\t/// Gets the item's name when loaded in weapon.\n\tconst std::string &getNameAsAmmo() const;\n\t/// Gets the item's requirements.\n\tconst std::vector<const RuleResearch*> &getRequirements() const;\n\t/// Gets the item's buy requirements.\n\tconst std::vector<const RuleResearch*> &getBuyRequirements() const;\n\t/// Gets the allied country name required to buy this item.\n\tconst std::string& getRequiresBuyCountry() const { return _requiresBuyCountry; }\n\t/// Gets the base functions required to buy craft.\n\tRuleBaseFacilityFunctions getRequiresBuyBaseFunc() const { return _requiresBuyBaseFunc; }\n\t/// Gets the dividers used for recovery of special items.\n\tconst std::map<std::string, int> &getRecoveryDividers() const;\n\t/// Gets the item(s) to be recovered instead of this item.\n\tconst std::map<const RuleItem*, std::vector<int> > &getRecoveryTransformations() const;\n\t/// Gets the item's categories.\n\tconst std::vector<std::string> &getCategories() const;\n\t/// Checks if the item belongs to a category.\n\tbool belongsToCategory(const std::string &category) const;\n\t/// Returns the first item category that has a non-empty invOrder, if it exists.\n\tconst RuleItemCategory* getFirstCategoryWithInvOrder(const Mod* mod) const;\n\t/// Gets unit rule if the item is vehicle weapon.\n\tUnit* getVehicleUnit() const;\n\t/// Gets the fixed ammo slot of the primary vehicle weapon.\n\tint getVehicleFixedAmmoSlot() const { return _vehicleFixedAmmoSlot; }\n\t/// Gets the item's size.\n\tdouble getSize() const;\n\n\t/// Gets the item's monthly buy limit.\n\tint getMonthlyBuyLimit() const { return _monthlyBuyLimit; }\n\t/// Gets the item's monthly buy limit message.\n\tconst std::string& getMonthlyBuyLimitMessage() const { return _monthlyBuyLimitMessage; }\n\t/// Gets the item's basic purchase cost.\n\tint getBuyCost() const;\n\t/// Gets the item's purchase cost.\n\tint getBuyCostAdjusted(const Base* base, const SavedGame* save) const;\n\t/// Gets the item's basic sale cost.\n\tint getSellCost() const;\n\t/// Gets the item's sale cost.\n\tint getSellCostAdjusted(const Base* base, const SavedGame* save) const;\n\t/// Gets the item's transfer time.\n\tint getTransferTime() const;\n\n\t/// Gets the item's weight.\n\tint getWeight() const;\n\t/// Gets the item's maximum throw range.\n\tint getThrowRange() const { return _throwRange; }\n\t/// Gets the item's maximum underwater throw range.\n\tint getUnderwaterThrowRange() const { return _underwaterThrowRange; }\n\t/// Gets the item's reference in BIGOBS.PCK for use in inventory.\n\tint getBigSprite() const;\n\t/// Gets the item's reference in FLOOROB.PCK for use in battlescape.\n\tint getFloorSprite() const;\n\t/// Gets the item's reference in HANDOB.PCK for use in inventory.\n\tint getHandSprite() const;\n\t/// Gets the item's reference in SPICONS.DAT for special weapon button.\n\tint getSpecialIconSprite() const;\n\n\t/// Gets cost of moving item around inventory.\n\tint getInventoryMoveCostPercent() const { return _inventoryMoveCostPercent; }\n\t/// Gets if the item is two-handed.\n\tbool isTwoHanded() const;\n\t/// Gets if the item can only be used by both hands.\n\tbool isBlockingBothHands() const;\n\t/// Gets if the item is fixed.\n\tbool isFixed() const;\n\t/// Do show fixed weapon on unit.\n\tbool getFixedShow() const;\n\t/// Get name of the default inventory slot.\n\tconst RuleInventory* getDefaultInventorySlot() const { return _defaultInventorySlot; }\n\t/// Get inventory slot default X position.\n\tint getDefaultInventorySlotX() const { return _defaultInvSlotX; }\n\t/// Get inventory slot default Y position.\n\tint getDefaultInventorySlotY() const { return _defaultInvSlotY; }\n\t/// Gets the item's supported inventory sections.\n\tconst std::vector<const RuleInventory*> &getSupportedInventorySections() const { return _supportedInventorySections; }\n\t/// Checks if the item can be placed into a given inventory section.\n\tbool canBePlacedIntoInventorySection(const RuleInventory* inventorySection) const;\n\n\t/// Gets if the item is a launcher.\n\tint getWaypoints() const;\n\t/// Gets the item's bullet sprite reference.\n\tint getBulletSprite() const;\n\t/// Gets the item's reload sound.\n\tint getReloadSound() const;\n\tconst std::vector<int> &getReloadSoundRaw() const { return _reloadSound; }\n\t/// Gets the item's prime sound.\n\tint getPrimeSound() const;\n\tconst std::vector<int>& getPrimeSoundRaw() const { return _primeSound; }\n\t/// Gets the item's unprime sound.\n\tint getUnprimeSound() const;\n\tconst std::vector<int>& getUnprimeSoundRaw() const { return _unprimeSound; }\n\t/// Gets the item's fire sound.\n\tint getFireSound() const;\n\tconst std::vector<int> &getFireSoundRaw() const { return _fireSound; }\n\n\t/// Gets the item's hit sound.\n\tint getHitSound() const;\n\tconst std::vector<int> &getHitSoundRaw() const { return _hitSound; }\n\t/// Gets the item's hit animation.\n\tint getHitAnimation() const;\n\t/// Gets the item's hit animation frame count.\n\tint getHitAnimationFrames() const { return _hitAnimFrames; }\n\t/// Gets the item's hit sound.\n\tint getHitMissSound() const;\n\tconst std::vector<int> &getHitMissSoundRaw() const { return _hitMissSound; }\n\t/// Gets the item's psiUse miss animation.\n\tint getHitMissAnimation() const;\n\t/// Gets the item's psiUse miss animation frame count.\n\tint getHitMissAnimationFrames() const { return _hitMissAnimFrames; }\n\n\t/// What sound does this weapon make when you swing this at someone?\n\tint getMeleeSound() const;\n\tconst std::vector<int> &getMeleeSoundRaw() const { return _meleeSound; }\n\t/// Get the melee animation starting frame (comes from hit.pck).\n\tint getMeleeAnimation() const;\n\t/// Gets the melee animation frame count.\n\tint getMeleeAnimationFrames() const { return _meleeAnimFrames; }\n\t/// What sound does this weapon make when you miss a swing?\n\tint getMeleeMissSound() const;\n\tconst std::vector<int> &getMeleeMissSoundRaw() const { return _meleeMissSound; }\n\t/// Get the melee miss animation starting frame (comes from hit.pck).\n\tint getMeleeMissAnimation() const;\n\t/// Gets the melee miss animation frame count.\n\tint getMeleeMissAnimationFrames() const { return _meleeMissAnimFrames; }\n\t/// What sound does this weapon make when you punch someone in the face with it?\n\tint getMeleeHitSound() const;\n\tconst std::vector<int> &getMeleeHitSoundRaw() const { return _meleeHitSound; }\n\t/// What sound does explosion sound?\n\tint getExplosionHitSound() const;\n\tconst std::vector<int> &getExplosionHitSoundRaw() const { return _explosionHitSound; }\n\n\t/// Gets the item's psi hit sound.\n\tint getPsiSound() const;\n\tconst std::vector<int> &getPsiSoundRaw() const { return _psiSound; }\n\t/// Get the psi animation starting frame (comes from hit.pck).\n\tint getPsiAnimation() const;\n\t/// Gets the psi animation frame count.\n\tint getPsiAnimationFrames() const { return _psiAnimFrames; }\n\t/// Gets the item's psi miss sound.\n\tint getPsiMissSound() const;\n\tconst std::vector<int> &getPsiMissSoundRaw() const { return _psiMissSound; }\n\t/// Get the psi miss animation starting frame (comes from hit.pck).\n\tint getPsiMissAnimation() const;\n\t/// Gets the psi miss animation frame count.\n\tint getPsiMissAnimationFrames() const { return _psiMissAnimFrames; }\n\n\n\t/// Gets the item's power.\n\tint getPower() const;\n\t/// Gets the item's power used for AoE explosion animation.\n\tint getPowerForAnimation() const { return _powerForAnimation; }\n\t/// Should the item's power be displayed in Ufopedia or not?\n\tbool getHidePower() const { return _hidePower; }\n\t/// Ok, so this isn't a melee type weapon but we're using it for melee... how much damage should it do?\n\tint getMeleePower() const;\n\n\t/// Should the (selected) power attributes come from the weapon/firearm only (and not from the ammo, even if defined)?\n\tbool getIgnoreAmmoPower() const { return _ignoreAmmoPower && _battleType == BT_FIREARM; }\n\n\t/// Gets amount of power dropped for range in voxels.\n\tfloat getPowerRangeReduction(float range) const;\n\tfloat getPowerRangeReductionRaw() const { return _powerRangeReduction; }\n\tfloat getPowerRangeThresholdRaw() const { return _powerRangeThreshold; }\n\t/// Gets amount of psi accuracy dropped for range in voxels.\n\tfloat getPsiAccuracyRangeReduction(float range) const;\n\n\t/// Get additional power from unit statistics\n\tint getPowerBonus(BattleActionAttack::ReadOnly attack) const;\n\tconst RuleStatBonus *getDamageBonusRaw() const { return &_damageBonus; }\n\n\t/// Get additional power for melee attack in range weapon from unit statistics.\n\tint getMeleeBonus(BattleActionAttack::ReadOnly attack) const;\n\tconst RuleStatBonus *getMeleeBonusRaw() const { return &_meleeBonus; }\n\n\t/// Get multiplier of accuracy from unit statistics\n\tint getAccuracyMultiplier(BattleActionAttack::ReadOnly attack) const;\n\tconst RuleStatBonus *getAccuracyMultiplierRaw() const { return &_accuracyMulti; }\n\n\t/// Get multiplier of melee hit chance from unit statistics\n\tint getMeleeMultiplier(BattleActionAttack::ReadOnly  attack) const;\n\tconst RuleStatBonus *getMeleeMultiplierRaw() const { return &_meleeMulti; }\n\n\t/// Get multiplier of throwing from unit statistics\n\tint getThrowMultiplier(BattleActionAttack::ReadOnly attack) const;\n\tconst RuleStatBonus *getThrowMultiplierRaw() const { return &_throwMulti; }\n\n\t/// Get multiplier of close quarters combat from unit statistics\n\tint getCloseQuartersMultiplier(BattleActionAttack::ReadOnly attack) const;\n\tconst RuleStatBonus *getCloseQuartersMultiplierRaw() const { return &_closeQuartersMulti; }\n\n\n\t/// Get configuration of aimed shot action.\n\tconst RuleItemAction *getConfigAimed() const;\n\t/// Get configuration of autoshot action.\n\tconst RuleItemAction *getConfigAuto() const;\n\t/// Get configuration of snapshot action.\n\tconst RuleItemAction *getConfigSnap() const;\n\t/// Get configuration of melee action.\n\tconst RuleItemAction *getConfigMelee() const;\n\n\n\t/// Gets the item's aimed shot accuracy.\n\tint getAccuracyAimed() const;\n\t/// Gets the item's autoshot accuracy.\n\tint getAccuracyAuto() const;\n\t/// Gets the item's snapshot accuracy.\n\tint getAccuracySnap() const;\n\t/// Gets the item's melee accuracy.\n\tint getAccuracyMelee() const;\n\t/// Gets the item's use accuracy.\n\tint getAccuracyUse() const;\n\t/// Gets the item's mind control accuracy.\n\tint getAccuracyMind() const;\n\t/// Gets the item's panic accuracy.\n\tint getAccuracyPanic() const;\n\t/// Gets the item's throw accuracy.\n\tint getAccuracyThrow() const;\n\t/// Gets the item's close quarters combat accuracy.\n\tint getAccuracyCloseQuarters(const Mod *mod) const;\n\t/// Get penalty for firing this weapon on out-of-LOS targets\n\tint getNoLOSAccuracyPenalty(Mod *mod) const;\n\t/// Get setting for primed explosives exploding in the inventory.\n\tint getExplodeInventory(const Mod* mod) const;\n\n\t/// Gets the item's aimed shot cost.\n\tRuleItemUseCost getCostAimed() const;\n\t/// Gets the item's autoshot cost.\n\tRuleItemUseCost getCostAuto() const;\n\t/// Gets the item's snapshot cost.\n\tRuleItemUseCost getCostSnap() const;\n\t/// Gets the item's melee cost.\n\tRuleItemUseCost getCostMelee() const;\n\t/// Gets the item's use cost.\n\tRuleItemUseCost getCostUse() const;\n\t/// Gets the item's mind control cost.\n\tRuleItemUseCost getCostMind() const;\n\t/// Gets the item's panic cost.\n\tRuleItemUseCost getCostPanic() const;\n\t/// Gets the item's throw cost.\n\tRuleItemUseCost getCostThrow() const;\n\t/// Gets the item's prime cost.\n\tRuleItemUseCost getCostPrime() const;\n\t/// Gets the item's unprime cost.\n\tRuleItemUseCost getCostUnprime() const;\n\n\t/// Should we charge a flat rate of costAimed?\n\tRuleItemUseFlat getFlatAimed() const;\n\t/// Should we charge a flat rate of costAuto?\n\tRuleItemUseFlat getFlatAuto() const;\n\t/// Should we charge a flat rate of costSnap?\n\tRuleItemUseFlat getFlatSnap() const;\n\t/// Should we charge a flat rate of costMelee?\n\tRuleItemUseFlat getFlatMelee() const;\n\t/// Should we charge a flat rate?\n\tRuleItemUseFlat getFlatUse() const;\n\t/// Should we charge a flat rate of costThrow?\n\tRuleItemUseFlat getFlatThrow() const;\n\t/// Should we charge a flat rate of costPrime?\n\tRuleItemUseFlat getFlatPrime() const;\n\t/// Should we charge a flat rate of costUnrime?\n\tRuleItemUseFlat getFlatUnprime() const;\n\n\t/// Gets the item's load TU cost.\n\tint getTULoad(int slot) const;\n\t/// Gets the item's unload TU cost.\n\tint getTUUnload(int slot) const;\n\t/// Gets the ammo type for a vehicle.\n\tconst RuleItem* getVehicleClipAmmo() const;\n\t/// Gets the maximum number of rounds for a vehicle. E.g. a vehicle that can load 6 clips with 10 rounds each, returns 60.\n\tint getVehicleClipSize() const;\n\t/// Gets the number of clips needed to fully load a vehicle. E.g. a vehicle that holds max 60 rounds and clip size is 10, returns 6.\n\tint getVehicleClipsLoaded() const;\n\t/// Gets list of compatible ammo.\n\tconst std::vector<const RuleItem*> *getPrimaryCompatibleAmmo() const;\n\t/// Get slot position for ammo type.\n\tint getSlotForAmmo(const RuleItem* type) const;\n\t/// Get slot position for ammo type.\n\tconst std::vector<const RuleItem*> *getCompatibleAmmoForSlot(int slot) const;\n\n\t/// Gets the item's damage type.\n\tconst RuleDamageType *getDamageType() const;\n\tbool isDamageTypeSet() const { return _damageTypeSet; }\n\t/// Gets the item's melee damage type for range weapons.\n\tconst RuleDamageType *getMeleeType() const;\n\tbool isMeleeTypeSet() const { return _meleeTypeSet; }\n\t/// Gets the item's type.\n\tBattleType getBattleType() const;\n\t/// Is the item's type BT_GRENADE or BT_PROXIMITYGRENADE?\n\tbool isGrenadeOrProxy() const;\n\t/// Gets the item's fuse type.\n\tBattleFuseType getFuseTimerType() const;\n\t/// Gets the item's default fuse value.\n\tint getFuseTimerDefault() const;\n\t/// Is this item (e.g. a mine) hidden on the minimap?\n\tbool isHiddenOnMinimap() const;\n\t/// Get fuse trigger event.\n\tconst RuleItemFuseTrigger *getFuseTriggerEvent() const;\n\n\t/// Gets the item's inventory width.\n\tint getInventoryWidth() const;\n\t/// Gets the item's inventory height.\n\tint getInventoryHeight() const;\n\t/// Gets the ammo amount.\n\tint getClipSize() const;\n\t/// Gets the chance of special effect like zombify or corpse explosion or mine triggering.\n\tint getSpecialChance() const;\n\t/// Draws the item's hand sprite onto a surface.\n\tvoid drawHandSprite(const SurfaceSet *texture, Surface *surface, const BattleItem *item = 0, const SavedBattleGame* save = 0, int animFrame = 0) const;\n\t/// item's hand spite x offset\n\tint getHandSpriteOffX() const;\n\t/// item's hand spite y offset\n\tint getHandSpriteOffY() const;\n\t/// Gets the medikit heal quantity.\n\tint getHealQuantity() const;\n\t/// Gets the medikit pain killer quantity.\n\tint getPainKillerQuantity() const;\n\t/// Gets the medikit stimulant quantity.\n\tint getStimulantQuantity() const;\n\t/// Gets the medikit wound healed per shot.\n\tint getWoundRecovery() const;\n\t/// Gets the medikit health recovered per shot.\n\tint getHealthRecovery() const;\n\t/// Gets the medikit energy recovered per shot.\n\tint getEnergyRecovery() const;\n\t/// Gets the medikit stun recovered per shot.\n\tint getStunRecovery() const;\n\t/// Gets the medikit mana recovered per shot.\n\tint getManaRecovery() const { return _manaRecovery; }\n\t/// Gets the medikit morale recovered per shot.\n\tint getMoraleRecovery() const;\n\t/// Gets the medikit morale recovered based on missing health.\n\tfloat getPainKillerRecovery() const;\n\t/// Gets the medikit's allowed targets.\n\tbool getAllowTargetSelf() const { return _medikitTargetSelf; }\n\tbool getAllowTargetImmune() const { return _medikitTargetImmune; }\n\tbool getAllowTargetGround() const { return _medikitTargetMatrix & 21; } // 1 + 4 + 16\n\tbool getAllowTargetStanding() const { return _medikitTargetMatrix & 42; } // 2 + 8 + 32\n\tbool getAllowTargetFriendGround() const { return _medikitTargetMatrix & 1; }\n\tbool getAllowTargetFriendStanding() const { return _medikitTargetMatrix & 2; }\n\tbool getAllowTargetNeutralGround() const { return _medikitTargetMatrix & 4; }\n\tbool getAllowTargetNeutralStanding() const { return _medikitTargetMatrix & 8; }\n\tbool getAllowTargetHostileGround() const { return _medikitTargetMatrix & 16; }\n\tbool getAllowTargetHostileStanding() const { return _medikitTargetMatrix & 32; }\n\tint getMedikitTargetMatrixRaw() const { return _medikitTargetMatrix; }\n\t/// Is this (medikit-type & items with prime) item consumable?\n\tbool isConsumable() const;\n\t/// Does this item extinguish fire?\n\tbool isFireExtinguisher() const;\n\t/// Is ammo replenished after battle? (Intended side effect: ammo item with 0 ammo left does not disappear.)\n\tbool isAmmoRechargeable() const { return _isAmmoRechargeable; }\n\t/// If this is used as a speacialWeapon, is it accessed by empty hand?\n\tbool isSpecialUsingEmptyHand() const;\n\t/// Display icon in an empty hand?\n\tbool showSpecialInEmptyHand() const { return _specialUseEmptyHandShow; }\n\t/// Gets the medikit use type.\n\tBattleMediKitType getMediKitType() const;\n\t/// Gets the medikit custom background.\n\tconst std::string &getMediKitCustomBackground() const;\n\t/// Gets the max explosion radius.\n\tint getExplosionRadius(BattleActionAttack::ReadOnly attack) const;\n\t/// Gets the recovery points score\n\tint getRecoveryPoints() const;\n\t/// Gets the item's armor.\n\tint getArmor() const;\n\t/// Check if item is normal inventory item.\n\tbool isInventoryItem() const;\n\t/// Checks if item have some use in battlescape.\n\tbool isUsefulBattlescapeItem() const;\n\t/// Gets the item's recoverability.\n\tbool isRecoverable() const;\n\t/// Gets the corpse item's recoverability.\n\tbool isCorpseRecoverable() const;\n\t/// Checks if the item can be equipped in base defense mission.\n\tbool canBeEquippedBeforeBaseDefense() const;\n\t/// Checks if the item can be equipped to craft inventory.\n\tbool canBeEquippedToCraftInventory() const;\n\t/// Gets the item's turret type.\n\tint getTurretType() const;\n\t/// Gets first turn when AI can use item.\n\tint getAIUseDelay(const Mod *mod = 0) const;\n\t/// Gets how many melee hits AI should do.\n\tint getAIMeleeHitCount() const;\n\t/// Checks if this a live alien.\n\tbool isAlien() const;\n\t/// Returns to which type of prison does the live alien belong.\n\tint getPrisonType() const;\n\n\t/// Should this weapon arc?\n\tbool getArcingShot() const;\n\t/// Which experience training mode to use for this weapon?\n\tExperienceTrainingMode getExperienceTrainingMode() const;\n\t/// How much mana experience does this weapon provide?\n\tint getManaExperience() const { return _manaExperience; }\n\t/// How much do aliens want this thing?\n\tint getAttraction() const;\n\t/// Get the load order for this item.\n\tint getLoadOrder() const { return _loadOrder; }\n\t/// Get the list weight for this item.\n\tint getListOrder() const;\n\t/// How fast does a projectile fired from this weapon travel?\n\tint getBulletSpeed() const;\n\t/// How fast does the explosion animation play?\n\tint getExplosionSpeed() const;\n\t/// Get name of medikit pain killer action for medikit view.\n\tconst std::string& getPainKillerActionName() const { return _painKillerActionName; }\n\t/// Get name of medikit stimulant action for medikit view.\n\tconst std::string& getStimulantActionName() const { return _stimulantActionName; }\n\t/// Get name of medikit heal action for medikit view.\n\tconst std::string& getHealActionName() const { return _healActionName; }\n\t/// Get name of medikit action for action menu.\n\tconst std::string &getMedikitActionName() const { return _medikitActionName; }\n\t/// Get name of psi attack for action menu.\n\tconst std::string &getPsiAttackName() const { return _psiAttackName; }\n\t/// Get name of prime action for action menu.\n\tconst std::string &getPrimeActionName() const { return _primeActionName; }\n\t/// Get message for prime action.\n\tconst std::string &getPrimeActionMessage() const { return _primeActionMessage; }\n\t/// Get name of unprime action for action menu.\n\tconst std::string &getUnprimeActionName() const { return _unprimeActionName; }\n\t/// Get message for unprime action.\n\tconst std::string &getUnprimeActionMessage() const { return _unprimeActionMessage; }\n\t/// Get message when trying to sell the item.\n\tconst std::string& getSellActionMessage() const { return _sellActionMessage; }\n\t/// is this item a 2 handed weapon?\n\tbool isRifle() const;\n\t/// is this item a single handed weapon?\n\tbool isPistol() const;\n\t/// Get the max range of this weapon.\n\tint getMaxRange() const;\n\t/// Checks whether a given distance is out of range for this item.\n\tbool isOutOfRange(int distanceSq) const;\n\t/// Checks whether a given distance is out of throw range for this item.\n\tbool isOutOfThrowRange(int distanceSq, int depth) const;\n\t/// Get the max range of aimed shots with this weapon.\n\tint getAimRange() const;\n\t/// Get the max range of snap shots with this weapon.\n\tint getSnapRange() const;\n\t/// Get the max range of auto shots with this weapon.\n\tint getAutoRange() const;\n\t/// Get the minimum effective range of this weapon.\n\tint getMinRange() const;\n\t/// Gets the item's throw dropoff range.\n\tint getThrowDropoffRange() const { return _throwDropoffRange; }\n\t/// Gets the item's underwater throw dropoff range.\n\tint getUnderwaterThrowDropoffRange() const { return _underwaterThrowDropoffRange; }\n\t/// Get the throwing accuracy dropoff of this weapon.\n\tint getThrowDropoff() const { return _throwDropoff; }\n\t/// Get the accuracy dropoff of this weapon.\n\tint getDropoff() const;\n\t/// Helper function to calculate limits and dropoff.\n\tint calculateLimits(int& upperLimit, int& lowerLimit, int depth, BattleActionType type) const;\n\t/// Get the number of projectiles to trace.\n\tint getShotgunPellets() const;\n\t/// Get the shotgun behavior type.\n\tint getShotgunBehaviorType() const;\n\t/// Get the spread of shotgun projectiles.\n\tint getShotgunSpread() const;\n\t/// Get the shotgun choke value.\n\tint getShotgunChoke() const;\n\n\t/// Gets the weapon's zombie unit.\n\tconst std::string &getZombieUnit(const BattleUnit* victim) const;\n\tconst std::map<std::string, std::string> &getZombieUnitByArmorMaleRaw() const { return _zombieUnitByArmorMale; }\n\tconst std::map<std::string, std::string> &getZombieUnitByArmorFemaleRaw() const { return _zombieUnitByArmorFemale; }\n\tconst std::map<std::string, std::string> &getZombieUnitByTypeRaw() const { return _zombieUnitByType; }\n\t/// Gets which faction the spawned unit should have.\n\tUnitFaction getZombieUnitFaction() const { return _zombieUnitFaction; }\n\t/// Gets chance for zombie transformation on attack.\n\tint getZombieUnitChance() const { return useIntNullable(_zombieUnitChance, _specialChance); }\n\n\t/// Gets the weapon's spawn unit.\n\tconst Unit* getSpawnUnit() const { return _spawnUnit; }\n\t/// Gets which faction the spawned unit should have.\n\tUnitFaction getSpawnUnitFaction() const { return _spawnUnitFaction; }\n\t/// Gets chance for unit spawn on attack.\n\tint getSpawnUnitChance() const { return useIntNullable(_spawnUnitChance, _specialChance); }\n\n\t/// Gets the weapon's spawn item.\n\tconst RuleItem* getSpawnItem() const { return _spawnItem; }\n\t/// Gets chance for item spawn on attack.\n\tint getSpawnItemChance() const { return useIntNullable(_spawnItemChance, _specialChance); }\n\n\t/// Checks if this item can be used to target a given faction.\n\tbool isTargetAllowed(UnitFaction targetFaction, UnitFaction attacker) const;\n\tint getTargetMatrixRaw() const { return _targetMatrix; }\n\t/// Should mind control convert the unit to the neutral faction?\n\tbool convertToCivilian() const { return _convertToCivilian; }\n\t/// Check if LOS is required to use this item (only applies to psionic type items)\n\tbool isLOSRequired() const;\n\t/// Is this item restricted to underwater use?\n\tbool isWaterOnly() const;\n\t/// Is this item restricted to land use?\n\tbool isLandOnly() const;\n\t/// Is this item require unit with psi skill to use it?\n\tbool isPsiRequired() const;\n\t/// Does this item need mana to operate?\n\tbool isManaRequired() const;\n\t/// Get the associated special type of this item.\n\tint getSpecialType() const;\n\t/// Get the color offset to use for the vapor trail.\n\tint getVaporColor(int depth) const;\n\t/// Gets the vapor cloud density.\n\tint getVaporDensity(int depth) const;\n\t/// Gets the vapor cloud probability.\n\tint getVaporProbability(int depth) const;\n\t/// Gets the index of the sprite in the CustomItemPreview sprite set\n\tconst std::vector<int> &getCustomItemPreviewIndex() const;\n\t/// Gets the kneel bonus.\n\tint getKneelBonus(const Mod *mod) const;\n\t/// Gets the one-handed penalty.\n\tint getOneHandedPenalty(const Mod *mod) const;\n\t/// Gets the monthly salary.\n\tint getMonthlySalary() const;\n\t/// Gets the monthly maintenance.\n\tint getMonthlyMaintenance() const;\n\t/// Gets how many waypoints are used for a \"spray\" attack\n\tint getSprayWaypoints() const;\n\t/// Gets script.\n\ttemplate<typename Script>\n\tconst typename Script::Container &getScript() const { return _battleItemScripts.get<Script>(); }\n\t/// Get all script values.\n\tconst ScriptValues<RuleItem> &getScriptValuesRaw() const { return _scriptValues; }\n};\n\n}\n"
  },
  {
    "path": "src/Mod/RuleItemCategory.cpp",
    "content": "/*\n * Copyright 2010-2015 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"RuleItemCategory.h\"\n#include \"Mod.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Creates a blank ruleset for a certain item category.\n * @param type String defining the item category.\n */\nRuleItemCategory::RuleItemCategory(const std::string &type, int listOrder) : _type(type), _hidden(false), _listOrder(listOrder)\n{\n}\n\n/**\n *\n */\nRuleItemCategory::~RuleItemCategory()\n{\n}\n\n/**\n * Loads the item category from a YAML file.\n * @param node YAML node.\n * @param mod Mod for the item.\n * @param listOrder The list weight for this item.\n */\nvoid RuleItemCategory::load(const YAML::YamlNodeReader& reader, Mod *mod)\n{\n\tif (const auto& parent = reader[\"refNode\"])\n\t{\n\t\tload(parent, mod);\n\t}\n\n\treader.tryRead(\"replaceBy\", _replaceBy);\n\treader.tryRead(\"hidden\", _hidden);\n\n\treader.tryRead(\"listOrder\", _listOrder);\n\tmod->loadUnorderedNames(_type, _invOrder, reader[\"invOrder\"]);\n}\n\n/**\n * Gets the item category type. Each category has a unique type.\n * @return The category's type.\n */\nconst std::string &RuleItemCategory::getType() const\n{\n\treturn _type;\n}\n\n/**\n* Gets the item category type, which should be used instead of this one.\n* @return The replacement category's type.\n*/\nconst std::string &RuleItemCategory::getReplaceBy() const\n{\n\treturn _replaceBy;\n}\n\n/**\n* Indicates whether the category is hidden or visible.\n* @return True if hidden, false if visible.\n*/\nbool RuleItemCategory::isHidden() const\n{\n\treturn _hidden;\n}\n\n/**\n * Gets the list weight for this item category.\n * @return The list weight.\n */\nint RuleItemCategory::getListOrder() const\n{\n\treturn _listOrder;\n}\n\n}\n"
  },
  {
    "path": "src/Mod/RuleItemCategory.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2015 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include <vector>\n#include \"../Engine/Yaml.h\"\n\nnamespace OpenXcom\n{\n\nclass Mod;\n\n/**\n * Represents an item category.\n * Contains info about list order.\n */\nclass RuleItemCategory\n{\nprivate:\n\tstd::string _type, _replaceBy;\n\tbool _hidden;\n\tint _listOrder;\n\tstd::vector<std::string> _invOrder;\npublic:\n\t/// Creates a blank item category ruleset.\n\tRuleItemCategory(const std::string &type, int listOrder);\n\t/// Cleans up the item category ruleset.\n\t~RuleItemCategory();\n\t/// Loads item data from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader, Mod *mod);\n\t/// Gets the item category type.\n\tconst std::string &getType() const;\n\t/// Gets the item category type, which should be used instead of this one.\n\tconst std::string &getReplaceBy() const;\n\t/// Indicates whether the category is hidden or visible.\n\tbool isHidden() const;\n\t/// Get the list weight for this item category.\n\tint getListOrder() const;\n\t/// Gets the inventory slot order to be used for auto-equip and ctrl-click-equip.\n\tconst std::vector<std::string>& getInvOrder() const { return _invOrder; }\n\n};\n\n}\n"
  },
  {
    "path": "src/Mod/RuleManufacture.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <algorithm>\n#include \"RuleManufacture.h\"\n#include \"RuleManufactureShortcut.h\"\n#include \"RuleResearch.h\"\n#include \"RuleCraft.h\"\n#include \"RuleItem.h\"\n#include \"Mod.h\"\n#include \"../Engine/Collections.h\"\n\nnamespace OpenXcom\n{\n/**\n * Creates a new Manufacture.\n * @param name The unique manufacture name.\n */\nRuleManufacture::RuleManufacture(const std::string& name, int listOrder)\n\t: _name(name), _space(0), _time(0), _cost(0), _points(0), _refund(false), _producedCraft(0), _listOrder(listOrder)\n{\n\t_producedItemsNames[name] = 1;\n}\n\n/**\n * Loads the manufacture project from a YAML file.\n * @param node YAML node.\n * @param listOrder The list weight for this manufacture.\n */\nvoid RuleManufacture::load(const YAML::YamlNodeReader& node, Mod* mod)\n{\n\tconst auto& reader = node.useIndex();\n\tif (const auto& parent = reader[\"refNode\"])\n\t{\n\t\tload(parent, mod);\n\t}\n\n\treader.tryRead(\"category\", _category);\n\tmod->loadUnorderedNames(_name, _requiresName, reader[\"requires\"]);\n\tmod->loadBaseFunction(_name, _requiresBaseFunc, reader[\"requiresBaseFunc\"]);\n\treader.tryRead(\"space\", _space);\n\treader.tryRead(\"time\", _time);\n\treader.tryRead(\"cost\", _cost);\n\treader.tryRead(\"points\", _points);\n\treader.tryRead(\"refund\", _refund);\n\tmod->loadUnorderedNamesToInt(_name, _requiredItemsNames, reader[\"requiredItems\"]);\n\tmod->loadUnorderedNamesToInt(_name, _producedItemsNames, reader[\"producedItems\"]);\n\treader.tryRead(\"randomProducedItems\", _randomProducedItemsNames);\n\treader.tryRead(\"spawnedPersonType\", _spawnedPersonType);\n\treader.tryRead(\"spawnedPersonName\", _spawnedPersonName);\n\tif (reader[\"spawnedSoldier\"])\n\t{\n\t\t_spawnedSoldier = reader[\"spawnedSoldier\"].emitDescendants(YAML::YamlRootNodeReader(_spawnedSoldier, \"(spawned soldier template)\"));\n\t}\n\treader.tryRead(\"transferTimes\", _transferTimes);\n\tif (reader[\"events\"])\n\t{\n\t\t_events.load(reader[\"events\"]);\n\t}\n\treader.tryRead(\"listOrder\", _listOrder);\n}\n\n/**\n * Cross link with other Rules.\n */\nvoid RuleManufacture::afterLoad(const Mod* mod)\n{\n\tif (_time <= 0)\n\t{\n\t\tthrow Exception(\"Manufacturing time must be greater than zero.\");\n\t}\n\n\t_requires = mod->getResearch(_requiresName);\n\tif (_category == \"STR_CRAFT\")\n\t{\n\t\tauto item = _producedItemsNames.begin();\n\t\tif (item == _producedItemsNames.end())\n\t\t{\n\t\t\tthrow Exception(\"No craft defined for production\");\n\t\t}\n\t\telse if (item->second != 1)\n\t\t{\n\t\t\tthrow Exception(\"Only one craft can be build in production\");\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_producedCraft = mod->getCraft(item->first, true);\n\t\t}\n\t}\n\telse\n\t{\n\t\tfor (auto& i : _producedItemsNames)\n\t\t{\n\t\t\t_producedItems[mod->getItem(i.first, true)] = i.second;\n\t\t}\n\t}\n\tfor (auto& i : _requiredItemsNames)\n\t{\n\t\tauto* itemRule = mod->getItem(i.first, false);\n\t\tauto* craftRule = mod->getCraft(i.first, false);\n\t\tif (itemRule)\n\t\t{\n\t\t\t_requiredItems[itemRule] = i.second;\n\t\t}\n\t\telse if (craftRule)\n\t\t{\n\t\t\t_requiredCrafts[craftRule] = i.second;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tthrow Exception(\"Unknown required item '\" + i.first + \"'\");\n\t\t}\n\t}\n\n\tfor (auto& itemSet : _randomProducedItemsNames)\n\t{\n\t\tstd::map<const RuleItem*, int> tmp;\n\t\tfor (auto& i : itemSet.second)\n\t\t{\n\t\t\ttmp[mod->getItem(i.first, true)] = i.second;\n\t\t}\n\t\t_randomProducedItems.push_back(std::make_pair(itemSet.first, tmp));\n\t}\n\n\t//remove not needed data\n\tCollections::removeAll(_requiresName);\n\tCollections::removeAll(_producedItemsNames);\n\tCollections::removeAll(_requiredItemsNames);\n\tCollections::removeAll(_randomProducedItemsNames);\n}\n\n/**\n * Change the name and break down the sub-projects into simpler components.\n */\nvoid RuleManufacture::breakDown(const Mod* mod, const RuleManufactureShortcut* recipe)\n{\n\t// 0. rename\n\t_name = recipe->getName();\n\n\t// 1. init temp variables\n\tstd::map<const RuleItem*, int> tempRequiredItems = _requiredItems;\n\tstd::map<const RuleResearch*, bool> tempRequires;\n\tfor (auto* r : _requires)\n\t\ttempRequires[r] = true;\n\tRuleBaseFacilityFunctions tempRequiresBaseFunc = _requiresBaseFunc;\n\n\t// 2. break down iteratively\n\tbool doneSomething = false;\n\tdo\n\t{\n\t\tdoneSomething = false;\n\t\tfor (auto& projectName : recipe->getBreakDownItems())\n\t\t{\n\t\t\tRuleItem* itemRule = mod->getItem(projectName, true);\n\t\t\tRuleManufacture* projectRule = mod->getManufacture(projectName, true);\n\t\t\tint count = tempRequiredItems[itemRule];\n\t\t\tif (count > 0)\n\t\t\t{\n\t\t\t\ttempRequiredItems[itemRule] = 0;\n\t\t\t\tdoneSomething = true;\n\n\t\t\t\t_space = std::max(_space, projectRule->getRequiredSpace());\n\t\t\t\t_time += count * projectRule->getManufactureTime();\n\t\t\t\t_cost += count * projectRule->getManufactureCost();\n\n\t\t\t\tfor (auto& ri : projectRule->getRequiredItems())\n\t\t\t\t\ttempRequiredItems[ri.first] += count * ri.second;\n\t\t\t\tfor (auto* r : projectRule->getRequirements())\n\t\t\t\t\ttempRequires[r] = true;\n\n\t\t\t\ttempRequiresBaseFunc |= projectRule->getRequireBaseFunc();\n\t\t\t}\n\t\t}\n\t}\n\twhile (doneSomething);\n\n\t// 3. update\n\t{\n\t\t_requiredItems.clear();\n\t\tfor (auto& item : tempRequiredItems)\n\t\t\tif (item.second > 0)\n\t\t\t\t_requiredItems[item.first] = item.second;\n\t}\n\tif (recipe->getBreakDownRequires())\n\t{\n\t\t_requires.clear();\n\t\tfor (auto& item : tempRequires)\n\t\t\tif (item.second)\n\t\t\t\t_requires.push_back(item.first);\n\t}\n\tif (recipe->getBreakDownRequiresBaseFunc())\n\t{\n\t\t_requiresBaseFunc = tempRequiresBaseFunc;\n\t}\n}\n\n/**\n * Gets the unique name of the manufacture.\n * @return The name.\n */\nconst std::string &RuleManufacture::getName() const\n{\n\treturn _name;\n}\n\n/**\n * Gets the category shown in the manufacture list.\n * @return The category.\n */\nconst std::string &RuleManufacture::getCategory() const\n{\n\treturn _category;\n}\n\n/**\n * Gets the list of research required to\n * manufacture this object.\n * @return A list of research IDs.\n */\nconst std::vector<const RuleResearch*> &RuleManufacture::getRequirements() const\n{\n\treturn _requires;\n}\n\n/**\n * Gets the required workspace to start production.\n * @return The required workspace.\n */\nint RuleManufacture::getRequiredSpace() const\n{\n\treturn _space;\n}\n\n/**\n * Gets the time needed to manufacture one object.\n * @return The time needed to manufacture one object (in man/hour).\n */\nint RuleManufacture::getManufactureTime() const\n{\n\treturn _time;\n}\n\n\n/**\n * Gets the cost of manufacturing one object.\n * @return The cost of manufacturing one object.\n */\nint RuleManufacture::getManufactureCost() const\n{\n\treturn _cost;\n}\n\n/**\n * Checks if there's enough funds to manufacture one object.\n * @param funds Current funds.\n * @return True if manufacture is possible.\n */\nbool RuleManufacture::haveEnoughMoneyForOneMoreUnit(int64_t funds) const\n{\n\t// either we have enough money, or the production doesn't cost anything\n\treturn funds >= _cost || _cost <= 0;\n}\n\n/**\n * Should all resources of a cancelled project be refunded?\n * @return True, if all resources should be refunded. False otherwise.\n */\nbool RuleManufacture::getRefund() const\n{\n\treturn _refund;\n}\n\n/**\n * Gets the list of items required to manufacture one object.\n * @return The list of items required to manufacture one object.\n */\nconst std::map<const RuleItem*, int> &RuleManufacture::getRequiredItems() const\n{\n\treturn _requiredItems;\n}\n\n/**\n * Gets the list of crafts required to manufacture one object.\n */\nconst std::map<const RuleCraft*, int> &RuleManufacture::getRequiredCrafts() const\n{\n\treturn _requiredCrafts;\n}\n\n/**\n * Gets the list of items produced by completing \"one object\" of this project.\n * @return The list of items produced by completing \"one object\" of this project.\n */\nconst std::map<const RuleItem*, int> &RuleManufacture::getProducedItems() const\n{\n\treturn _producedItems;\n}\n\n/*\n * Gets craft build by this project. null if is not craft production.\n * @return Craft rule set.\n */\nconst RuleCraft* RuleManufacture::getProducedCraft() const\n{\n\treturn _producedCraft;\n}\n\n/**\n * Gets the random manufacture rules.\n * @return The random manufacture rules.\n */\nconst std::vector<std::pair<int, std::map<const RuleItem*, int> > > &RuleManufacture::getRandomProducedItems() const\n{\n\treturn _randomProducedItems;\n}\n\n/**\n* Gets the \"manufactured person\", i.e. person spawned when manufacturing project ends.\n* @return The person type ID.\n*/\nconst std::string &RuleManufacture::getSpawnedPersonType() const\n{\n\treturn _spawnedPersonType;\n}\n\n/**\n* Gets the custom name of the \"manufactured person\".\n* @return The person name translation code.\n*/\nconst std::string &RuleManufacture::getSpawnedPersonName() const\n{\n\treturn _spawnedPersonName;\n}\n\n/**\n * Is it possible to use auto-sell feature for this manufacturing project?\n * @return True for normal projects, false for special projects.\n */\nbool RuleManufacture::canAutoSell() const\n{\n\tif (!_spawnedPersonType.empty())\n\t{\n\t\t// can't sell people\n\t\treturn false;\n\t}\n\tif (!_randomProducedItems.empty())\n\t{\n\t\t// sell profit label can't show reasonable info\n\t\treturn false;\n\t}\n\treturn true;\n}\n\n/**\n * Gets the list weight for this manufacture item.\n * @return The list weight for this manufacture item.\n */\nint RuleManufacture::getListOrder() const\n{\n\treturn _listOrder;\n}\n\n}\n"
  },
  {
    "path": "src/Mod/RuleManufacture.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include <map>\n#include \"../Engine/Yaml.h\"\n#include <stdint.h>\n#include \"RuleBaseFacilityFunctions.h\"\n#include \"../Savegame/WeightedOptions.h\"\n\nnamespace OpenXcom\n{\n\nenum ManufacturingFilterType\n{\n\tMANU_FILTER_DEFAULT,\n\tMANU_FILTER_DEFAULT_SUPPLIES_OK,\n\tMANU_FILTER_DEFAULT_NO_SUPPLIES,\n\tMANU_FILTER_FACILITY_REQUIRED,\n\tMANU_FILTER_HIDDEN\n};\n\nclass RuleManufactureShortcut;\nclass RuleResearch;\nclass RuleItem;\nclass RuleCraft;\nclass Mod;\n\n/**\n * Represents the information needed to manufacture an object.\n */\nclass RuleManufacture\n{\nprivate:\n\tstd::string _name, _category;\n\tstd::string _spawnedPersonType, _spawnedPersonName;\n\tYAML::YamlString _spawnedSoldier;\n\tstd::vector<std::string> _requiresName;\n\tRuleBaseFacilityFunctions _requiresBaseFunc;\n\tstd::vector<const RuleResearch*> _requires;\n\tint _space, _time, _cost;\n\tint _points;\n\tbool _refund;\n\tstd::map<std::string, int> _requiredItemsNames, _producedItemsNames;\n\tstd::map<const RuleItem*, int> _requiredItems, _producedItems;\n\tstd::map<const RuleCraft*, int> _requiredCrafts;\n\tconst RuleCraft* _producedCraft;\n\tstd::vector<std::pair<int, std::map<std::string, int> > > _randomProducedItemsNames;\n\tstd::vector<std::pair<int, std::map<const RuleItem*, int> > > _randomProducedItems;\n\tstd::vector<int> _transferTimes;\n\tWeightedOptions _events;\n\tint _listOrder;\npublic:\n\tstatic const int MANU_STATUS_NEW = 0;\n\tstatic const int MANU_STATUS_NORMAL = 1;\n\tstatic const int MANU_STATUS_HIDDEN = 2;\n\tstatic const int MANU_STATUSES = 3;\n\t/// Creates a new manufacture.\n\tRuleManufacture(const std::string &name, int listOrder);\n\n\t/// Loads the manufacture from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader, Mod* mod);\n\t/// Cross link with other rules.\n\tvoid afterLoad(const Mod* mod);\n\t/// Change the name and break down the sub-projects into simpler components.\n\tvoid breakDown(const Mod* mod, const RuleManufactureShortcut* recipe);\n\n\t/// Gets the manufacture name.\n\tconst std::string &getName() const;\n\t/// Gets the manufacture category.\n\tconst std::string &getCategory() const;\n\t/// Gets the manufacture's requirements.\n\tconst std::vector<const RuleResearch*> &getRequirements() const;\n\t/// Gets the base requirements.\n\tRuleBaseFacilityFunctions getRequireBaseFunc() const { return _requiresBaseFunc; }\n\t/// Gets the required workshop space.\n\tint getRequiredSpace() const;\n\t/// Gets the time required to manufacture one object.\n\tint getManufactureTime() const;\n\t/// Gets the cost of manufacturing one object.\n\tint getManufactureCost() const;\n\t/// Checks if there's enough funds to manufacture one object.\n\tbool haveEnoughMoneyForOneMoreUnit(int64_t funds) const;\n\t/// Gets the points earned for manufacturing one production object.\n\tint getPoints() const { return _points; }\n\t/// Should all resources of a cancelled project be refunded?\n\tbool getRefund() const;\n\t/// Gets the list of items required to manufacture one object.\n\tconst std::map<const RuleItem*, int> &getRequiredItems() const;\n\t/// Gets the list of crafts required to manufacture one object.\n\tconst std::map<const RuleCraft*, int> &getRequiredCrafts() const;\n\t/// Gets the list of items produced by completing \"one object\" of this project.\n\t/// by default: it contains only the \"name\" item with a value of 1.\n\tconst std::map<const RuleItem*, int> &getProducedItems() const;\n\t/// If this produce craft return its type, otherwise null.\n\tconst RuleCraft* getProducedCraft() const;\n\t/// Gets the random manufacture rules.\n\tconst std::vector<std::pair<int, std::map<const RuleItem*, int> > > &getRandomProducedItems() const;\n\t/// Gets the \"manufactured person\", i.e. person spawned when manufacturing project ends.\n\tconst std::string &getSpawnedPersonType() const;\n\t/// Gets the custom name of the \"manufactured person\".\n\tconst std::string &getSpawnedPersonName() const;\n\t/// Gets the spawned soldier template.\n\tconst YAML::YamlString& getSpawnedSoldierTemplate() const { return _spawnedSoldier; }\n\t/// Is it possible to use auto-sell feature for this manufacturing project?\n\tbool canAutoSell() const;\n\t/// Gets the transfer time info.\n\tconst std::vector<int>& getTransferTimes() const { return _transferTimes; }\n\t/// Gets geoscape event rule name to spawn after (each) item production\n\tstd::string chooseEvent() const { return _events.choose(); }\n\tconst WeightedOptions& getEventsRaw() const { return _events; }\n\t/// Gets the list weight for this manufacture item.\n\tint getListOrder() const;\n};\n\n}\n"
  },
  {
    "path": "src/Mod/RuleManufactureShortcut.cpp",
    "content": "/*\n * Copyright 2010-2020 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"RuleManufactureShortcut.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Creates a new RuleManufactureShortcut.\n * @param name The unique manufacture name.\n */\nRuleManufactureShortcut::RuleManufactureShortcut(const std::string &name) : _name(name), _breakDownRequires(false), _breakDownRequiresBaseFunc(true)\n{\n\t// empty\n}\n\n/**\n * Loads the RuleManufactureShortcut from a YAML file.\n * @param node YAML node.\n */\nvoid RuleManufactureShortcut::load(const YAML::YamlNodeReader& reader)\n{\n\tif (const auto& parent = reader[\"refNode\"])\n\t{\n\t\tload(parent);\n\t}\n\n\treader.tryRead(\"startFrom\", _startFrom);\n\treader.tryRead(\"breakDownItems\", _breakDownItems);\n\treader.tryRead(\"breakDownRequires\", _breakDownRequires);\n\treader.tryRead(\"breakDownRequiresBaseFunc\", _breakDownRequiresBaseFunc);\n}\n\n}\n"
  },
  {
    "path": "src/Mod/RuleManufactureShortcut.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2020 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include <vector>\n#include \"../Engine/Yaml.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Represents the information needed to create a new manufacture rule based on some existing manufacture rule.\n */\nclass RuleManufactureShortcut\n{\nprivate:\n\tstd::string _name, _startFrom;\n\tstd::vector<std::string> _breakDownItems;\n\tbool _breakDownRequires, _breakDownRequiresBaseFunc;\npublic:\n\t/// Creates a new RuleManufactureShortcut.\n\tRuleManufactureShortcut(const std::string &name);\n\t/// Deletes a RuleManufactureShortcut.\n\t~RuleManufactureShortcut() = default;\n\t/// Loads the RuleManufactureShortcut from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader);\n\t/// Gets the name of a new manufacture rule to be created.\n\tconst std::string& getName() const { return _name; }\n\t/// Gets the name of a manufacture rule to be used as a starting point.\n\tconst std::string& getStartFrom() const { return _startFrom; }\n\t/// Gets the names of items that should be broken down into simpler components.\n\tconst std::vector<std::string>& getBreakDownItems() const { return _breakDownItems; }\n\t/// Gets whether or not the required research should also be broken down.\n\tbool getBreakDownRequires() const { return _breakDownRequires; }\n\t/// Gets whether or not the required base services should also be broken down.\n\tbool getBreakDownRequiresBaseFunc() const { return _breakDownRequiresBaseFunc; }\n};\n\n}\n"
  },
  {
    "path": "src/Mod/RuleMissionScript.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"RuleMissionScript.h\"\n#include \"../Engine/Exception.h\"\n#include \"../Engine/RNG.h\"\n#include <climits>\n#include <set>\n\nnamespace OpenXcom\n{\n\n/**\n * RuleMissionScript: the rules for the alien mission progression.\n * Each script element is independent, and the saved game will probe the list of these each month to determine what's going to happen.\n */\nRuleMissionScript::RuleMissionScript(const std::string &type) :\n\t_type(type), _firstMonth(0), _lastMonth(-1), _label(0), _executionOdds(100),\n\t_targetBaseOdds(0), _minDifficulty(0), _maxDifficulty(4), _maxRuns(-1), _avoidRepeats(0), _delay(0), _randomDelay(0),\n\t_minScore(INT_MIN), _maxScore(INT_MAX), _minFunds(INT64_MIN), _maxFunds(INT64_MAX),\n\t_useTable(true), _siteType(false)\n{\n}\n\n/**\n * Destructor, cleans up the mess we left in ram.\n */\nRuleMissionScript::~RuleMissionScript()\n{\n\tfor (auto& pair : _missionWeights)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _raceWeights)\n\t{\n\t\tdelete pair.second;\n\t}\n\tfor (auto& pair : _regionWeights)\n\t{\n\t\tdelete pair.second;\n\t}\n}\n\n/**\n * Loads a missionScript from a YML file.\n * @param node the node within the file we're reading.\n */\nvoid RuleMissionScript::load(const YAML::YamlNodeReader& node)\n{\n\tconst auto& reader = node.useIndex();\n\tif (const auto& parent = reader[\"refNode\"])\n\t{\n\t\tload(parent);\n\t}\n\n\treader.tryRead(\"varName\", _varName);\n\treader.tryRead(\"firstMonth\", _firstMonth);\n\treader.tryRead(\"lastMonth\", _lastMonth);\n\treader.tryRead(\"label\", _label);\n\treader.tryRead(\"executionOdds\", _executionOdds);\n\treader.tryRead(\"targetBaseOdds\", _targetBaseOdds);\n\treader.tryRead(\"minDifficulty\", _minDifficulty);\n\treader.tryRead(\"maxDifficulty\", _maxDifficulty);\n\treader.tryRead(\"maxRuns\", _maxRuns);\n\treader.tryRead(\"avoidRepeats\", _avoidRepeats);\n\treader.tryRead(\"startDelay\", _delay);\n\treader.tryRead(\"randomDelay\", _randomDelay);\n\treader.tryRead(\"minScore\", _minScore);\n\treader.tryRead(\"maxScore\", _maxScore);\n\treader.tryRead(\"minFunds\", _minFunds);\n\treader.tryRead(\"maxFunds\", _maxFunds);\n\treader.tryRead(\"missionVarName\", _missionVarName);\n\treader.tryRead(\"missionMarkerName\", _missionMarkerName);\n\treader.tryRead(\"counterMin\", _counterMin);\n\treader.tryRead(\"counterMax\", _counterMax);\n\treader.tryRead(\"conditionals\", _conditionals);\n\treader.tryRead(\"adhocMissionScriptTags\", _adhocMissionScriptTags);\n\tfor (const auto& monthWeights : reader[\"missionWeights\"].children())\n\t{\n\t\tWeightedOptions* nw = new WeightedOptions();\n\t\tnw->load(monthWeights);\n\t\t_missionWeights.push_back(std::make_pair(monthWeights.readKey<size_t>(0), nw));\n\t}\n\tfor (const auto& monthWeights : reader[\"raceWeights\"].children())\n\t{\n\t\tWeightedOptions* nw = new WeightedOptions();\n\t\tnw->load(monthWeights);\n\t\t_raceWeights.push_back(std::make_pair(monthWeights.readKey<size_t>(0), nw));\n\t}\n\tfor (const auto& monthWeights : reader[\"regionWeights\"].children())\n\t{\n\t\tWeightedOptions* nw = new WeightedOptions();\n\t\tnw->load(monthWeights);\n\t\t_regionWeights.push_back(std::make_pair(monthWeights.readKey<size_t>(0), nw));\n\t}\n\n\treader.tryRead(\"researchTriggers\", _researchTriggers);\n\treader.tryRead(\"itemTriggers\", _itemTriggers);\n\treader.tryRead(\"facilityTriggers\", _facilityTriggers);\n\treader.tryRead(\"soldierTypeTriggers\", _soldierTypeTriggers);\n\treader.tryRead(\"xcomBaseInRegionTriggers\", _xcomBaseInRegionTriggers);\n\treader.tryRead(\"xcomBaseInCountryTriggers\", _xcomBaseInCountryTriggers);\n\treader.tryRead(\"pactCountryTriggers\", _pactCountryTriggers);\n\n\treader.tryRead(\"useTable\", _useTable);\n\tif (_varName.empty() && (_maxRuns > 0 || _avoidRepeats > 0))\n\t{\n\t\tthrow Exception(\"Error in mission script: \" + _type +\": no varName provided for a script with maxRuns or repeatAvoidance.\");\n\t}\n\n}\n\n/**\n * Gets the name of this command.\n * @return the name of the command.\n */\nconst std::string& RuleMissionScript::getType() const\n{\n\treturn _type;\n}\n\n/**\n * @return the first month this script should run.\n */\nint RuleMissionScript::getFirstMonth() const\n{\n\treturn _firstMonth;\n}\n\n/**\n * @return the last month this script should run.\n */\nint RuleMissionScript::getLastMonth() const\n{\n\treturn _lastMonth;\n}\n\n/**\n * @return the label this command uses for conditional tracking.\n */\nint RuleMissionScript::getLabel() const\n{\n\treturn _label;\n}\n\n/**\n * @return the odds of this command's execution.\n */\nint RuleMissionScript::getExecutionOdds() const\n{\n\treturn _executionOdds;\n}\n\n/**\n * @return the odds of this command targetting a base.\n */\nint RuleMissionScript::getTargetBaseOdds() const\n{\n\treturn _targetBaseOdds;\n}\n\n/**\n * @return the minimum difficulty for this script to run.\n */\nint RuleMissionScript::getMinDifficulty() const\n{\n\treturn _minDifficulty;\n}\n\n/**\n * @return the maximum runs for scripts tracking our varName.\n */\nint RuleMissionScript::getMaxRuns() const\n{\n\treturn _maxRuns;\n}\n\n/**\n * @return the number of sites to avoid repeating missions against.\n */\nint RuleMissionScript::getRepeatAvoidance() const\n{\n\treturn _avoidRepeats;\n}\n\n/**\n * @return the fixed (or randomized) delay on spawning the first wave (if any) to override whatever's written in the mission definition.\n */\nint RuleMissionScript::getDelay() const\n{\n\tif (_randomDelay == 0)\n\t\treturn _delay;\n\telse\n\t\treturn _delay + RNG::generate(0, _randomDelay);\n}\n\n/**\n * @return the list of conditions that govern execution of this command.\n */\nconst std::vector<int> &RuleMissionScript::getConditionals() const\n{\n\treturn _conditionals;\n}\n\n/**\n * @return if this command uses a weighted distribution to pick a race.\n */\nbool RuleMissionScript::hasRaceWeights() const\n{\n\treturn !_raceWeights.empty();\n}\n\n/**\n * @return if this command uses a weighted distribution to pick a mission.\n */\nbool RuleMissionScript::hasMissionWeights() const\n{\n\treturn !_missionWeights.empty();\n}\n\n/**\n * @return if this command uses a weighted distribution to pick a region.\n */\nbool RuleMissionScript::hasRegionWeights() const\n{\n\treturn !_regionWeights.empty();\n}\n\n/**\n * @return a list of research topics that govern execution of this script.\n */\nconst std::map<std::string, bool> &RuleMissionScript::getResearchTriggers() const\n{\n\treturn _researchTriggers;\n}\n\n/**\n * @return a list of item triggers that govern execution of this script.\n */\nconst std::map<std::string, bool> &RuleMissionScript::getItemTriggers() const\n{\n\treturn _itemTriggers;\n}\n\n/**\n * @return a list of facility triggers that govern execution of this script.\n */\nconst std::map<std::string, bool> &RuleMissionScript::getFacilityTriggers() const\n{\n\treturn _facilityTriggers;\n}\n\n/**\n * @return a list of xcom base triggers that govern execution of this script.\n */\nconst std::map<std::string, bool> &RuleMissionScript::getXcomBaseInRegionTriggers() const\n{\n\treturn _xcomBaseInRegionTriggers;\n}\n\n/**\n * @return a list of xcom base triggers that govern execution of this script.\n */\nconst std::map<std::string, bool> &RuleMissionScript::getXcomBaseInCountryTriggers() const\n{\n\treturn _xcomBaseInCountryTriggers;\n}\n\n/**\n * @return if this command should remove the mission it generates from the strategy table.\n */\nbool RuleMissionScript::getUseTable() const\n{\n\treturn _useTable;\n}\n\n/**\n * @return the name of the variable we want to use to track in the saved game.\n */\nstd::string RuleMissionScript::getVarName() const\n{\n\treturn _varName;\n}\n\n/**\n * @return a complete, unique list of all the mission types this command could possibly generate.\n */\nstd::set<std::string> RuleMissionScript::getAllMissionTypes() const\n{\n\tstd::set<std::string> types;\n\tfor (auto& pair : _missionWeights)\n\t{\n\t\tstd::vector<std::string> names = pair.second->getNames();\n\t\tfor (const auto& name : names)\n\t\t{\n\t\t\ttypes.insert(name);\n\t\t}\n\t}\n\treturn types;\n}\n\n/**\n * @param month the month for which we want info.\n * @return a list of the possible missions for the given month.\n */\nstd::vector<std::string> RuleMissionScript::getMissionTypes(const int month) const\n{\n\tstd::vector<std::string> missions;\n\tstd::vector<std::pair<size_t, WeightedOptions*> >::const_reverse_iterator rw = _missionWeights.rbegin();\n\twhile (month < (int)(rw->first))\n\t{\n\t\t++rw;\n\t\tif (rw == _missionWeights.rend())\n\t\t{\n\t\t\t--rw;\n\t\t\tbreak;\n\t\t}\n\t}\n\tstd::vector<std::string> names = rw->second->getNames();\n\tfor (const auto& name : names)\n\t{\n\t\tmissions.push_back(name);\n\t}\n\treturn missions;\n}\n\n/**\n * @param month the month for which we want info.\n * @return the list of regions we have to pick from this month.\n */\nstd::vector<std::string> RuleMissionScript::getRegions(const int month) const\n{\n\tstd::vector<std::string> regions;\n\tstd::vector<std::pair<size_t, WeightedOptions*> >::const_reverse_iterator rw = _regionWeights.rbegin();\n\twhile (month < (int)(rw->first))\n\t{\n\t\t++rw;\n\t\tif (rw == _regionWeights.rend())\n\t\t{\n\t\t\t--rw;\n\t\t\tbreak;\n\t\t}\n\t}\n\tstd::vector<std::string> names = rw->second->getNames();\n\tfor (const auto& name : names)\n\t{\n\t\tregions.push_back(name);\n\t}\n\treturn regions;\n}\n\n/**\n * Chooses one of the available races, regions, or missions for this command.\n * @param monthsPassed The number of months that have passed in the game world.\n * @param type the type of thing we want to generate, region, mission or race.\n * @return The string id of the thing.\n */\nstd::string RuleMissionScript::generate(const size_t monthsPassed, const GenerationType type) const\n{\n\tstd::vector<std::pair<size_t, WeightedOptions*> >::const_reverse_iterator rw;\n\tif (type == GEN_RACE)\n\t\trw = _raceWeights.rbegin();\n\telse if (type == GEN_REGION)\n\t\trw = _regionWeights.rbegin();\n\telse\n\t\trw = _missionWeights.rbegin();\n\twhile (monthsPassed < rw->first)\n\t\t++rw;\n\treturn rw->second->choose();\n}\n\n/**\n * @param siteType set this command to be a missionSite type or not.\n */\nvoid RuleMissionScript::setSiteType(const bool siteType)\n{\n\t_siteType = siteType;\n}\n\n/**\n * @return if this is a mission site type command or not.\n */\nbool RuleMissionScript::getSiteType() const\n{\n\treturn _siteType;\n}\n\n}\n"
  },
  {
    "path": "src/Mod/RuleMissionScript.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include <vector>\n#include <map>\n#include \"../Engine/Yaml.h\"\n#include \"../Savegame/WeightedOptions.h\"\n#include <set>\n\nnamespace OpenXcom\n{\nenum GenerationType { GEN_REGION, GEN_MISSION, GEN_RACE };\nclass WeightedOptions;\n\nclass RuleMissionScript\n{\nprivate:\n\tstd::string _type, _varName;\n\tint _firstMonth, _lastMonth, _label, _executionOdds, _targetBaseOdds, _minDifficulty, _maxDifficulty, _maxRuns, _avoidRepeats, _delay, _randomDelay;\n\tint _minScore, _maxScore;\n\tint64_t _minFunds, _maxFunds;\n\tstd::string _missionVarName, _missionMarkerName;\n\tint _counterMin, _counterMax;\n\tstd::vector<int> _conditionals;\n\tstd::vector<std::string> _adhocMissionScriptTags;\n\tstd::vector<std::pair<size_t, WeightedOptions*> > _regionWeights, _missionWeights, _raceWeights;\n\n\tstd::map<std::string, bool> _researchTriggers;\n\tstd::map<std::string, bool> _itemTriggers;\n\tstd::map<std::string, bool> _facilityTriggers;\n\tstd::map<std::string, bool> _soldierTypeTriggers;\n\tstd::map<std::string, bool> _xcomBaseInRegionTriggers;\n\tstd::map<std::string, bool> _xcomBaseInCountryTriggers;\n\tstd::map<std::string, bool> _pactCountryTriggers;\n\n\tbool _useTable, _siteType;\n\npublic:\n\t/// Creates a new mission script.\n\tRuleMissionScript(const std::string &type);\n\t/// Deletes a mission script.\n\t~RuleMissionScript();\n\t/// Loads a mission script from yaml.\n\tvoid load(const YAML::YamlNodeReader& reader);\n\t/// Gets the name of the script command.\n\tconst std::string& getType() const;\n\t/// Gets the name of the variable to use for keeping track of... things.\n\tstd::string getVarName() const;\n\t/// Gets a complete and unique list of all the mission types contained within this command.\n\tstd::set<std::string> getAllMissionTypes() const;\n\t/// Gets a list of the regions in this command's region weights for a given month.\n\tstd::vector<std::string> getRegions(const int month) const;\n\t/// Gets a list of the mission types in this command's mission weights for a given month.\n\tstd::vector<std::string> getMissionTypes(const int month) const;\n\t/// Gets the first month this command will run.\n\tint getFirstMonth() const;\n\t/// Gets the last month this command will run.\n\tint getLastMonth() const;\n\t/// Gets the label of this command, used for conditionals.\n\tint getLabel() const;\n\t/// Gets the odds of this command executing.\n\tint getExecutionOdds() const;\n\t/// Gets the odds of this mission targetting an xcom base.\n\tint getTargetBaseOdds() const;\n\t/// Gets the minimum difficulty for this command to run\n\tint getMinDifficulty() const;\n\t/// Gets the maximum difficulty for this command to run.\n\tint getMaxDifficulty() const { return _maxDifficulty; }\n\t/// Gets the maximum number of times to run a command with this varName\n\tint getMaxRuns() const;\n\t/// Gets how many previous mission sites to keep track of (to avoid using them again)\n\tint getRepeatAvoidance() const;\n\t/// Gets the number of minutes to delay spawning of the first wave of this mission, overrides the spawn delay defined in the mission waves.\n\tint getDelay() const;\n\t/// Gets the minimum score (from last month) for this command to run.\n\tint getMinScore() const { return _minScore; }\n\t/// Gets the maximum score (from last month) for this command to run.\n\tint getMaxScore() const { return _maxScore; }\n\t/// Gets the minimum funds (from current month) for this command to run.\n\tint64_t getMinFunds() const { return _minFunds; }\n\t/// Gets the maximum funds (from current month) for this command to run.\n\tint64_t getMaxFunds() const { return _maxFunds; }\n\t/// Gets the name of the mission script tracking variable.\n\tconst std::string& getMissionVarName() const { return _missionVarName; }\n\t/// Gets the name of the mission marker tracking variable.\n\tconst std::string& getMissionMarkerName() const { return _missionMarkerName; }\n\t/// Gets the minimum number of missions generated for this command to run.\n\tint getCounterMin() const { return _counterMin; }\n\t/// Gets the maximum number of missions generated for this command to run.\n\tint getCounterMax() const { return _counterMax; }\n\t/// Gets the list of conditions this command requires in order to run.\n\tconst std::vector<int> &getConditionals() const;\n\t/// Gets the list of tags for this command.\n\tconst std::vector<std::string> &getAdhocMissionScriptTags() const { return _adhocMissionScriptTags; }\n\t/// Does this command have raceWeights?\n\tbool hasRaceWeights() const;\n\t/// Does this command have mission weights?\n\tbool hasMissionWeights() const;\n\t/// Does this command have region weights?\n\tbool hasRegionWeights() const;\n\n\t/// Gets the research triggers that may apply to this command.\n\tconst std::map<std::string, bool> &getResearchTriggers() const;\n\t/// Gets the item triggers that may apply to this command.\n\tconst std::map<std::string, bool> &getItemTriggers() const;\n\t/// Gets the facility triggers that may apply to this command.\n\tconst std::map<std::string, bool> &getFacilityTriggers() const;\n\t/// Gets the soldier type triggers that may apply to this command.\n\tconst std::map<std::string, bool> &getSoldierTypeTriggers() const { return _soldierTypeTriggers; }\n\t/// Gets the xcom base triggers that may apply to this command.\n\tconst std::map<std::string, bool> &getXcomBaseInRegionTriggers() const;\n\t/// Gets the xcom base triggers that may apply to this command.\n\tconst std::map<std::string, bool> &getXcomBaseInCountryTriggers() const;\n\t/// Gets the country pact triggers that may apply to this command.\n\tconst std::map<std::string, bool> &getPactCountryTriggers() const { return _pactCountryTriggers; }\n\n\t/// Delete this mission from the table? stops it coming up again in random selection, but NOT if a missionScript calls it by name.\n\tbool getUseTable() const;\n\t/// Sets this script to a terror mission type command or not.\n\tvoid setSiteType(const bool siteType);\n\t/// Checks if this is a terror-type mission or not.\n\tbool getSiteType() const;\n\t/// Generates either a region, a mission, or a race based on the month.\n\tstd::string generate(const size_t monthsPassed, const GenerationType type) const;\n\n};\n\n}\n"
  },
  {
    "path": "src/Mod/RuleMusic.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"RuleMusic.h\"\n#include <climits>\n\nnamespace OpenXcom\n{\n/**\n * initialize catpos as int_max to prevent trying to load files from cats that don't exist,\n * but allow for optional music to be listed regardless for loading .ogg or .mp3 versions\n * of said files, should they be present.\n * default normalization value is 0.76, this only applies to the adlib mixer as far as i know.\n * also, 0.76 is roughly optimal for all the TFTD tracks.\n * @param type String defining the type.\n */\nRuleMusic::RuleMusic(const std::string &type) : _type(type), _catPos(INT_MAX), _normalization(0.76f)\n{\n}\n\nRuleMusic::~RuleMusic()\n{\n}\n\n/**\n * Loads info about the music track.\n * @param node yaml node to read from.\n */\nvoid RuleMusic::load(const YAML::YamlNodeReader& reader)\n{\n\treader.tryRead(\"name\", _name);\n\treader.tryRead(\"catPos\", _catPos);\n\treader.tryRead(\"normalization\", _normalization);\n}\n\n/**\n * Gets the track's filename in the SOUND folder.\n * @return the track's filename (no extension).\n */\nconst std::string& RuleMusic::getName() const\n{\n\tif (_name.empty())\n\t\treturn _type;\n\treturn _name;\n}\n\n/**\n * Gets the track's index in the catalog file.\n * @return the track's index in the file.\n */\nint RuleMusic::getCatPos() const\n{\n\treturn _catPos;\n}\n\n/**\n * Gets the track's normalization level (Adlib only).\n * @return the track's normalization value.\n */\nfloat RuleMusic::getNormalization() const\n{\n\treturn _normalization;\n}\n\n}\n"
  },
  {
    "path": "src/Mod/RuleMusic.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include \"../Engine/Yaml.h\"\n\nnamespace OpenXcom\n{\n\nclass RuleMusic\n{\nprivate:\n\tstd::string _type, _name;\n\tint _catPos;\n\tfloat _normalization;\npublic:\n\tRuleMusic(const std::string &type);\n\t~RuleMusic();\n\tvoid load(const YAML::YamlNodeReader& reader);\n\tconst std::string& getName() const;\n\tint getCatPos() const;\n\tfloat getNormalization() const;\n};\n\n}\n"
  },
  {
    "path": "src/Mod/RuleRegion.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <assert.h>\n#include \"RuleRegion.h\"\n#include \"Mod.h\"\n#include \"City.h\"\n#include \"../Engine/Logger.h\"\n#include \"../Engine/RNG.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Creates a blank ruleset for a certain type of region.\n * @param type String defining the type.\n */\nRuleRegion::RuleRegion(const std::string &type): _type(type), _cost(0), _regionWeight(0)\n{\n}\n\n/**\n * Deletes the cities from memory.\n */\nRuleRegion::~RuleRegion()\n{\n\tfor (auto* city : _cities)\n\t{\n\t\tdelete city;\n\t}\n}\n\n/**\n * Loads the region type from a YAML file.\n * @param node YAML node.\n */\nvoid RuleRegion::load(const YAML::YamlNodeReader& reader, Mod* mod)\n{\n\tif (const auto& parent = reader[\"refNode\"])\n\t{\n\t\tload(parent, mod);\n\t}\n\n\treader.tryRead(\"cost\", _cost);\n\n\tif (reader[\"deleteOldAreas\"].readVal(false))\n\t{\n\t\t_lonMin.clear();\n\t\t_lonMax.clear();\n\t\t_latMin.clear();\n\t\t_latMax.clear();\n\t}\n\tfor (const auto& area : reader[\"areas\"].children())\n\t{\n\t\t_lonMin.push_back(Deg2Rad(area[0].readVal<double>()));\n\t\t_lonMax.push_back(Deg2Rad(area[1].readVal<double>()));\n\t\t_latMin.push_back(Deg2Rad(area[2].readVal<double>()));\n\t\t_latMax.push_back(Deg2Rad(area[3].readVal<double>()));\n\n\t\tif (_latMin.back() > _latMax.back())\n\t\t\tstd::swap(_latMin.back(), _latMax.back());\n\t}\n\n\treader.tryRead(\"missionZones\", _missionZones);\n\t{\n\t\tint zn = 0;\n\t\tfor (auto& z : _missionZones)\n\t\t{\n\t\t\tif (z.areas.size() < 1)\n\t\t\t{\n\t\t\t\tLog(LOG_WARNING) << \"Empty zone, region: \" << _type << \", zone: \" << zn;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tint an = 0;\n\t\t\tbool firstAreaType = z.areas.at(0).isPoint();\n\t\t\tfor (auto& a : z.areas)\n\t\t\t{\n\t\t\t\tif (a.isPoint() != firstAreaType)\n\t\t\t\t{\n\t\t\t\t\tLog(LOG_WARNING) << \"Mixed area types (point vs non-point), region: \" << _type << \", zone: \" << zn << \", area: \" << an;\n\t\t\t\t}\n\t\t\t\tif (a.lonMin > a.lonMax)\n\t\t\t\t{\n\t\t\t\t\tLog(LOG_ERROR) << \"Crossing the prime meridian in mission zones requires a different syntax, region: \" << _type << \", zone: \" << zn << \", area: \" << an << \", lonMin: \" << Rad2Deg(a.lonMin) << \", lonMax: \" << Rad2Deg(a.lonMax);\n\t\t\t\t\tLog(LOG_INFO) << \"  Wrong example: [350,   8, 20, 30]\";\n\t\t\t\t\tLog(LOG_INFO) << \"Correct example: [350, 368, 20, 30]\";\n\t\t\t\t}\n\t\t\t\t++an;\n\t\t\t}\n\t\t\t++zn;\n\t\t}\n\t}\n\tif (const auto& weights = reader[\"missionWeights\"])\n\t{\n\t\t_missionWeights.load(weights);\n\t}\n\treader.tryRead(\"regionWeight\", _regionWeight);\n\treader.tryRead(\"missionRegion\", _missionRegion);\n\n\tmod->loadBaseFunction(_type, _provideBaseFunc, reader[\"provideBaseFunc\"]);\n\tmod->loadBaseFunction(_type, _forbiddenBaseFunc, reader[\"forbiddenBaseFunc\"]);\n}\n\n/**\n * Gets the language string that names\n * this region. Each region type\n * has a unique name.\n * @return The region type.\n */\nconst std::string& RuleRegion::getType() const\n{\n\treturn _type;\n}\n\n/**\n * Gets the cost of building a base inside this region.\n * @return The construction cost.\n */\nint RuleRegion::getBaseCost() const\n{\n\treturn _cost;\n}\n\n/**\n * Checks if a point is inside this region.\n * @param lon Longitude in radians.\n * @param lat Latitude in radians.\n * @param ignoreTechnicalRegion If true, empty technical regions (i.e. regions with no areas, just having mission zones) will return true.\n * @return True if it's inside, false if it's outside.\n */\nbool RuleRegion::insideRegion(double lon, double lat, bool ignoreTechnicalRegion) const\n{\n\tif (ignoreTechnicalRegion && _lonMin.empty())\n\t\treturn true;\n\n\tfor (size_t i = 0; i < _lonMin.size(); ++i)\n\t{\n\t\tbool inLon, inLat;\n\n\t\tif (_lonMin[i] <= _lonMax[i])\n\t\t\tinLon = (lon >= _lonMin[i] && lon < _lonMax[i]);\n\t\telse\n\t\t\tinLon = ((lon >= _lonMin[i] && lon < M_PI*2.0) || (lon >= 0 && lon < _lonMax[i]));\n\n\t\tif (lat > 0) // make that both poles could be in some regions, this means `M_PI == _latMax[i]` or `-M_PI == _latMin[i]`\n\t\t\tinLat = (lat > _latMin[i] && lat <= _latMax[i]);\n\t\telse\n\t\t\tinLat = (lat >= _latMin[i] && lat < _latMax[i]);\n\n\t\tif (inLon && inLat)\n\t\t\treturn true;\n\t}\n\treturn false;\n}\n\n/**\n * Gets the list of cities contained in this region.\n * @return Pointer to a list.\n */\nstd::vector<City*> *RuleRegion::getCities()\n{\n\t// Build a cached list of all mission zones that are cities\n\t// Saves us from constantly searching for them\n\tif (_cities.empty())\n\t{\n\t\tfor (const auto& mz : _missionZones)\n\t\t{\n\t\t\tfor (const auto& ma : mz.areas)\n\t\t\t{\n\t\t\t\tif (ma.isPoint() && !ma.name.empty())\n\t\t\t\t{\n\t\t\t\t\t_cities.push_back(new City(ma.name, ma.lonMin, ma.latMin));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn &_cities;\n}\n\n/**\n * Gets the weight of this region for mission selection.\n * This is only used when creating a new game, since these weights change in the course of the game.\n * @return The initial weight of this region.\n */\nsize_t RuleRegion::getWeight() const\n{\n\treturn _regionWeight;\n}\n\n/**\n * Gets a list of all the missionZones in the region.\n * @return A list of missionZones.\n */\nconst std::vector<MissionZone> &RuleRegion::getMissionZones() const\n{\n\treturn _missionZones;\n}\n\n/**\n * Gets a random point that is guaranteed to be inside the given zone.\n * @param zone The target zone.\n * @return A pair of longitude and latitude.\n */\nstd::pair<double, double> RuleRegion::getRandomPoint(size_t zone, int area) const\n{\n\tif (zone < _missionZones.size())\n\t{\n\t\tsize_t a = area != -1 ? area : RNG::generate(0, _missionZones[zone].areas.size() - 1);\n\t\tdouble lonMin = _missionZones[zone].areas[a].lonMin;\n\t\tdouble lonMax = _missionZones[zone].areas[a].lonMax;\n\t\tdouble latMin = _missionZones[zone].areas[a].latMin;\n\t\tdouble latMax = _missionZones[zone].areas[a].latMax;\n\t\tif (lonMin > lonMax)\n\t\t{\n\t\t\tlonMin = _missionZones[zone].areas[a].lonMax;\n\t\t\tlonMax = _missionZones[zone].areas[a].lonMin;\n\t\t}\n\t\tif (latMin > latMax)\n\t\t{\n\t\t\tlatMin = _missionZones[zone].areas[a].latMax;\n\t\t\tlatMax = _missionZones[zone].areas[a].latMin;\n\t\t}\n\t\tdouble lon = RNG::generate(lonMin, lonMax);\n\t\tdouble lat = RNG::generate(latMin, latMax);\n\t\treturn std::make_pair(lon, lat);\n\t}\n\tassert(0 && \"Invalid zone number\");\n\treturn std::make_pair(0.0, 0.0);\n}\n\n// helper overloads for deserialization-only\nbool read(ryml::ConstNodeRef const& n, MissionArea* val)\n{\n\tYAML::YamlNodeReader reader(n);\n\tval->lonMin = Deg2Rad(reader[0].readVal<double>());\n\tval->lonMax = Deg2Rad(reader[1].readVal<double>());\n\tval->latMin = Deg2Rad(reader[2].readVal<double>());\n\tval->latMax = Deg2Rad(reader[3].readVal<double>());\n\tif (val->latMin > val->latMax)\n\t\tstd::swap(val->latMin, val->latMax);\n\tsize_t count = reader.childrenCount();\n\tif (count >= 5)\n\t\tval->texture = reader[4].readVal<int>();\n\tif (count >= 6)\n\t\tval->name = reader[5].readVal<std::string>();\n\treturn true;\n}\n\nbool read(ryml::ConstNodeRef const& n, MissionZone* val)\n{\n\tYAML::YamlNodeReader reader(n);\n\treader.tryReadVal(val->areas);\n\treturn true;\n}\n\n}\n"
  },
  {
    "path": "src/Mod/RuleRegion.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include <vector>\n#include \"../Engine/Yaml.h\"\n#include \"../fmath.h\"\n#include \"../Savegame/WeightedOptions.h\"\n#include \"RuleBaseFacilityFunctions.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Defines a rectangle in polar coordinates.\n * It is used to define areas for a mission zone.\n */\nstruct MissionArea\n{\n\tdouble lonMin, lonMax, latMin, latMax;\n\tint texture;\n\tstd::string name;\n\n\tMissionArea() : lonMin(0.0), lonMax(360.0), latMin(-90.0), latMax(90.0), texture(0) { }\n\n\tbool operator== (const MissionArea& ma) const\n\t{\n\t\treturn AreSame(lonMax, ma.lonMax) && AreSame(lonMin, ma.lonMin) && AreSame(latMax, ma.latMax) && AreSame(latMin, ma.latMin);\n\t}\n\n\tbool isPoint() const\n\t{\n\t\treturn AreSame(lonMin, lonMax) && AreSame(latMin, latMax);\n\t}\n};\n\n/**\n * A zone (set of areas) on the globe.\n */\nstruct MissionZone\n{\n\tstd::vector<MissionArea> areas;\n\n\tvoid swap(MissionZone &other)\n\t{\n\t\tareas.swap(other.areas);\n\t}\n};\n\nclass City;\nclass Mod;\n\n\n/**\n * Represents a specific region of the world.\n * Contains constant info about a region like area\n * covered and base construction costs.\n */\nclass RuleRegion\n{\nprivate:\n\tstd::string _type;\n\tint _cost;\n\tstd::vector<double> _lonMin, _lonMax, _latMin, _latMax;\n\tstd::vector<City*> _cities;\n\t/// Weighted list of the different mission types for this region.\n\tWeightedOptions _missionWeights;\n\t/// Weight of this region when selecting regions for alien missions.\n\tsize_t _regionWeight;\n\t/// All the mission zones in this region.\n\tstd::vector<MissionZone> _missionZones;\n\t/// Do missions in the region defined by this string instead.\n\tstd::string _missionRegion;\n\tRuleBaseFacilityFunctions _provideBaseFunc = 0;\n\tRuleBaseFacilityFunctions _forbiddenBaseFunc = 0;\npublic:\n\t/// Creates a blank region ruleset.\n\tRuleRegion(const std::string &type);\n\t/// Cleans up the region ruleset.\n\t~RuleRegion();\n\t/// Loads the region from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader, Mod* mod);\n\t/// Gets the region's type.\n\tconst std::string& getType() const;\n\t/// Gets the region's base cost.\n\tint getBaseCost() const;\n\t/// Checks if a point is inside the region.\n\tbool insideRegion(double lon, double lat, bool ignoreTechnicalRegion = false) const;\n\t/// Gets the cities in this region.\n\tstd::vector<City*> *getCities();\n\t/// Gets the weight of this region for mission selection.\n\tsize_t getWeight() const;\n\t/// Gets the weighted list of missions for this region.\n\tconst WeightedOptions &getAvailableMissions() const { return _missionWeights; }\n\t/// Gets the substitute mission region.\n\tconst std::string &getMissionRegion() const { return _missionRegion; }\n\t/// Gets a random point inside a mission zone.\n\tstd::pair<double, double> getRandomPoint(size_t zone, int area = -1) const;\n\t/// Gets the maximum longitude.\n\tconst std::vector<double> &getLonMax() const { return _lonMax; }\n\t/// Gets the minimum longitude.\n\tconst std::vector<double> &getLonMin() const { return _lonMin; }\n\t/// Gets the maximum latitude.\n\tconst std::vector<double> &getLatMax() const { return _latMax; }\n\t/// Gets the minimum latitude.\n\tconst std::vector<double> &getLatMin() const { return _latMin; }\n\t/// Gets a list of MissionZones.\n\tconst std::vector<MissionZone> &getMissionZones() const;\n\t/// Gets the functions provided by the region.\n\tRuleBaseFacilityFunctions getProvidedBaseFunc() const { return _provideBaseFunc; }\n\t/// Gets the functions forbidden by the region.\n\tRuleBaseFacilityFunctions getForbiddenBaseFunc() const { return _forbiddenBaseFunc; }\n};\n\n// helper overloads for deserialization-only\nbool read(ryml::ConstNodeRef const& n, MissionArea* val);\nbool read(ryml::ConstNodeRef const& n, MissionZone* val);\n\n}\n"
  },
  {
    "path": "src/Mod/RuleResearch.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"RuleResearch.h\"\n#include \"../Engine/Exception.h\"\n#include \"../Engine/Collections.h\"\n#include \"../Engine/ScriptBind.h\"\n#include \"Mod.h\"\n\nnamespace OpenXcom\n{\n\nRuleResearch::RuleResearch(const std::string &name, int listOrder) :\n\t_name(name), _spawnedItemCount(1), _cost(0), _points(0),\n\t_sequentialGetOneFree(false), _needItem(false), _destroyItem(false), _unlockFinalMission(false), _repeatable(false),\n\t_listOrder(listOrder)\n{\n}\n\n/**\n * Loads the research project from a YAML file.\n * @param node YAML node.\n * @param listOrder The list weight for this research.\n */\nvoid RuleResearch::load(const YAML::YamlNodeReader& node, Mod* mod, const ModScript& parsers)\n{\n\tconst auto& reader = node.useIndex();\n\tif (const auto& parent = reader[\"refNode\"])\n\t{\n\t\tload(parent, mod, parsers);\n\t}\n\n\treader.tryRead(\"lookup\", _lookupName);\n\treader.tryRead(\"cutscene\", _cutscene);\n\treader.tryRead(\"spawnedItem\", _spawnedItem);\n\treader.tryRead(\"spawnedItemCount\", _spawnedItemCount);\n\tmod->loadUnorderedNames(_name, _spawnedItemList, reader[\"spawnedItemList\"]);\n\tmod->loadUnorderedNames(_name, _decreaseCounter, reader[\"decreaseCounter\"]);\n\tmod->loadUnorderedNames(_name, _increaseCounter, reader[\"increaseCounter\"]);\n\treader.tryRead(\"spawnedEvent\", _spawnedEvent);\n\tif (reader[\"events\"])\n\t{\n\t\t_events.load(reader[\"events\"]);\n\t}\n\treader.tryRead(\"cost\", _cost);\n\treader.tryRead(\"points\", _points);\n\tmod->loadUnorderedNames(_name, _dependenciesName, reader[\"dependencies\"]);\n\tmod->loadUnorderedNames(_name, _unlocksName, reader[\"unlocks\"]);\n\tmod->loadUnorderedNames(_name, _disablesName, reader[\"disables\"]);\n\tmod->loadUnorderedNames(_name, _reenablesName, reader[\"reenables\"]);\n\tmod->loadUnorderedNames(_name, _getOneFreeName, reader[\"getOneFree\"]);\n\tmod->loadUnorderedNames(_name, _requiresName, reader[\"requires\"]);\n\tmod->loadBaseFunction(_name, _requiresBaseFunc, reader[\"requiresBaseFunc\"]);\n\treader.tryRead(\"sequentialGetOneFree\", _sequentialGetOneFree);\n\tmod->loadNamesToNames(_name, _getOneFreeProtectedName, reader[\"getOneFreeProtected\"]);\n\tmod->loadNameNull(_name, _neededItemName, reader[\"neededItem\"]);\n\treader.tryRead(\"needItem\", _needItem);\n\treader.tryRead(\"destroyItem\", _destroyItem);\n\treader.tryRead(\"returnsItem\", _returnsItem);\n\treader.tryRead(\"unlockFinalMission\", _unlockFinalMission);\n\treader.tryRead(\"repeatable\", _repeatable);\n\treader.tryRead(\"listOrder\", _listOrder);\n\n\t_scriptValues.load(reader, parsers.getShared());\n}\n\n/**\n * Cross link with other Rules.\n */\nvoid RuleResearch::afterLoad(const Mod* mod)\n{\n\t// This is necessary, research code assumes it!\n\tif (!_requiresName.empty() && _cost != 0)\n\t{\n\t\tthrow Exception(\"Research topic \" + _name + \" has requirements, but the cost is not zero. Sorry, this is not allowed!\");\n\t}\n\n\tif (_lookupName == _name)\n\t{\n\t\t_lookupName = \"\";\n\t}\n\tmod->linkRule(_lookup, _lookupName);\n\n\n\tif (_needItem)\n\t{\n\t\t// FIXME: this would break all mods unfortunately, maybe one day...\n\t\t//mod->linkRule(_neededItem, _neededItemName.empty() ? _name : _neededItemName);\n\n\t\tconst auto* linkedByName = mod->getItem(_name, false); // false, because even vanilla ruleset is a mess\n\t\tif (_neededItemName.empty())\n\t\t{\n\t\t\t_neededItem = linkedByName;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_neededItem = mod->getItem(_neededItemName, true);\n\t\t}\n\t\tif (_neededItem && linkedByName && linkedByName != _neededItem)\n\t\t{\n\t\t\tthrow LoadRuleException(_name, \"Conflict between researched item '\" + _name + \"' and needed item '\" + _neededItemName + \"'\");\n\t\t}\n\t}\n\n\t_dependencies = mod->getResearch(_dependenciesName);\n\t_unlocks = mod->getResearch(_unlocksName);\n\t_disables = mod->getResearch(_disablesName);\n\t_reenables = mod->getResearch(_reenablesName);\n\t_getOneFree = mod->getResearch(_getOneFreeName);\n\t_requires = mod->getResearch(_requiresName);\n\n\t_getOneFreeProtected.reserve(_getOneFreeProtectedName.size());\n\tfor (auto& n : _getOneFreeProtectedName)\n\t{\n\t\tauto* left = mod->getResearch(n.first, false);\n\t\tif (left)\n\t\t{\n\t\t\tauto right = mod->getResearch(n.second);\n\t\t\t_getOneFreeProtected.push_back(std::make_pair(left, right));\n\t\t}\n\t\telse\n\t\t{\n\t\t\tthrow Exception(\"Unknown research '\" + n.first + \"'\");\n\t\t}\n\t}\n\n\t//remove not needed data\n\tCollections::removeAll(_dependenciesName);\n\tCollections::removeAll(_unlocksName);\n\tCollections::removeAll(_disablesName);\n\tCollections::removeAll(_reenablesName);\n\tCollections::removeAll(_getOneFreeName);\n\tCollections::removeAll(_requiresName);\n\tCollections::removeAll(_getOneFreeProtectedName);\n}\n\n/**\n * Gets the cost of this ResearchProject.\n * @return The cost of this ResearchProject (in man/day).\n */\nint RuleResearch::getCost() const\n{\n\treturn _cost;\n}\n\n/**\n * Gets the name of this ResearchProject.\n * @return The name of this ResearchProject.\n */\nconst std::string &RuleResearch::getName() const\n{\n\treturn _name;\n}\n\n/**\n * Gets the list of dependencies, i.e. ResearchProjects, that must be discovered before this one.\n * @return The list of ResearchProjects.\n */\nconst std::vector<const RuleResearch*> &RuleResearch::getDependencies() const\n{\n\treturn _dependencies;\n}\n\n/**\n * Checks if this ResearchProject gives free topics in sequential order (or random order).\n * @return True if the ResearchProject gives free topics in sequential order.\n */\nbool RuleResearch::sequentialGetOneFree() const\n{\n\treturn _sequentialGetOneFree;\n}\n\n/**\n * Checks if this ResearchProject needs a corresponding Item to be researched.\n *  @return True if the ResearchProject needs a corresponding item.\n */\nbool RuleResearch::needItem() const\n{\n\treturn _needItem;\n}\n\n/**\n * Checks if this ResearchProject needs a corresponding Item to be researched.\n *  @return True if the ResearchProject needs a corresponding item.\n */\nbool RuleResearch::destroyItem() const\n{\n\treturn _destroyItem;\n}\n/**\n * Gets the list of ResearchProjects unlocked by this research.\n * @return The list of ResearchProjects.\n */\nconst std::vector<const RuleResearch*> &RuleResearch::getUnlocked() const\n{\n\treturn _unlocks;\n}\n\n/**\n * Gets the list of ResearchProjects disabled by this research.\n * @return The list of ResearchProjects.\n */\nconst std::vector<const RuleResearch*> &RuleResearch::getDisabled() const\n{\n\treturn _disables;\n}\n\n/**\n * Gets the list of ResearchProjects reenabled by this research.\n * @return The list of ResearchProjects.\n */\nconst std::vector<const RuleResearch*> &RuleResearch::getReenabled() const\n{\n\treturn _reenables;\n}\n\n/**\n * Get the points earned for this ResearchProject.\n * @return The points earned for this ResearchProject.\n */\nint RuleResearch::getPoints() const\n{\n\treturn _points;\n}\n\n/**\n * Gets the list of ResearchProjects granted at random for free by this research.\n * @return The list of ResearchProjects.\n */\nconst std::vector<const RuleResearch*> &RuleResearch::getGetOneFree() const\n{\n\treturn _getOneFree;\n}\n\n/**\n * Gets the list(s) of ResearchProjects granted at random for free by this research (if a defined prerequisite is met).\n * @return The list(s) of ResearchProjects.\n */\nconst std::vector<std::pair<const RuleResearch*, std::vector<const RuleResearch*> > > &RuleResearch::getGetOneFreeProtected() const\n{\n\treturn _getOneFreeProtected;\n}\n\n/**\n * Gets the requirements for this ResearchProject.\n * @return The requirement for this research.\n */\nconst std::vector<const RuleResearch*> &RuleResearch::getRequirements() const\n{\n\treturn _requires;\n}\n\n/**\n * Gets the list weight for this research item.\n * @return The list weight for this research item.\n */\nint RuleResearch::getListOrder() const\n{\n\treturn _listOrder;\n}\n\n/**\n * Gets the cutscene to play when this research item is completed.\n * @return The cutscene id.\n */\nconst std::string & RuleResearch::getCutscene() const\n{\n\treturn _cutscene;\n}\n\n/**\n * Gets the item to spawn in the base stores when this topic is researched.\n * @return The item id.\n */\nconst std::string & RuleResearch::getSpawnedItem() const\n{\n\treturn _spawnedItem;\n}\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tScript binding\n////////////////////////////////////////////////////////////\n\nnamespace\n{\n\n\tstd::string debugDisplayScript(const RuleResearch* ru)\n\t{\n\t\tif (ru)\n\t\t{\n\t\t\tstd::string s;\n\t\t\ts += RuleResearch::ScriptName;\n\t\t\ts += \"(name: \\\"\";\n\t\t\ts += ru->getName();\n\t\t\ts += \"\\\")\";\n\t\t\treturn s;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn \"null\";\n\t\t}\n\t}\n\n}\n\n/**\n * Register RuleResearch in script parser.\n * @param parser Script parser.\n */\nvoid RuleResearch::ScriptRegister(ScriptParserBase* parser)\n{\n\tBind<RuleResearch> ar = { parser };\n\n\tar.add<&RuleResearch::getCost>(\"getCost\");\n\tar.add<&RuleResearch::getPoints>(\"getPoints\");\n\tar.add<&RuleResearch::getLookup>(\"getLookup\");\n\tar.add<&RuleResearch::getNeededItem>(\"getNeededItem\");\n\n\tar.addScriptValue<BindBase::OnlyGet, &RuleResearch::_scriptValues>();\n\tar.addDebugDisplay<&debugDisplayScript>();\n}\n\n}\n"
  },
  {
    "path": "src/Mod/RuleResearch.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include <vector>\n#include \"../Engine/Yaml.h\"\n#include \"RuleBaseFacilityFunctions.h\"\n#include \"ModScript.h\"\n#include \"../Savegame/WeightedOptions.h\"\n\nnamespace OpenXcom\n{\n\nclass Mod;\n\n/**\n * Represents one research project.\n * Dependency is the list of RuleResearchs which must be discovered before a RuleResearch became available.\n * Unlocks are used to immediately unlock a RuleResearch (even if not all the dependencies have been researched).\n *\n * Fake ResearchProjects: A RuleResearch is fake one, if its cost is 0. They are used to to create check points in the dependency tree.\n *\n * For example, if we have a Research E which needs either A & B or C & D, we create two fake research projects:\n *  - F which need A & B\n *  - G which need C & D\n * both F and G can unlock E.\n */\nclass RuleResearch\n{\n private:\n\tstd::string _name, _lookupName, _cutscene, _spawnedItem, _spawnedEvent;\n\tWeightedOptions _events;\n\tint _spawnedItemCount;\n\tstd::vector<std::string> _spawnedItemList;\n\tstd::vector<std::string> _decreaseCounter, _increaseCounter;\n\tint _cost, _points;\n\tstd::vector<std::string> _dependenciesName, _unlocksName, _disablesName, _reenablesName, _getOneFreeName, _requiresName;\n\tRuleBaseFacilityFunctions _requiresBaseFunc;\n\tstd::vector<const RuleResearch*> _dependencies, _unlocks, _disables, _reenables, _getOneFree, _requires;\n\tbool _sequentialGetOneFree;\n\tstd::vector<std::pair<std::string, std::vector<std::string> > > _getOneFreeProtectedName;\n\tstd::vector<std::pair<const RuleResearch*, std::vector<const RuleResearch*> > > _getOneFreeProtected;\n\tconst RuleResearch* _lookup = nullptr;\n\tstd::string _neededItemName;\n\tconst RuleItem* _neededItem = nullptr;\n\tbool _needItem, _destroyItem, _returnsItem = false, _unlockFinalMission;\n\tbool _repeatable;\n\tint _listOrder;\n\n\tScriptValues<RuleResearch> _scriptValues;\npublic:\n\t/// Name of class used in script.\n\tstatic constexpr const char* ScriptName = \"RuleResearch\";\n\t/// Register all useful function used by script.\n\tstatic void ScriptRegister(ScriptParserBase* parser);\n\n\tstatic const int RESEARCH_STATUS_NEW = 0;\n\tstatic const int RESEARCH_STATUS_NORMAL = 1;\n\tstatic const int RESEARCH_STATUS_DISABLED = 2;\n\tstatic const int RESEARCH_STATUS_HIDDEN = 3;\n\tRuleResearch(const std::string &name, int listOrder);\n\n\t/// Loads the research from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader, Mod* mod, const ModScript& parsers);\n\t/// Cross link with other rules.\n\tvoid afterLoad(const Mod* mod);\n\n\t/// Gets time needed to discover this ResearchProject.\n\tint getCost() const;\n\t/// Gets the research name.\n\tconst std::string &getName() const;\n\t/// Gets the research dependencies.\n\tconst std::vector<const RuleResearch*> &getDependencies() const;\n\t/// Checks if this ResearchProject gives free topics in sequential order (or random order).\n\tbool sequentialGetOneFree() const;\n\n\t/// Gets the Item needed for this research.\n\tconst RuleItem* getNeededItem() const { return _neededItem; }\n\t/// Checks if this ResearchProject needs a corresponding Item to be researched.\n\tbool needItem() const;\n\t/// Checks if this ResearchProject consumes the corresponding Item when research completes.\n\tbool destroyItem() const;\n\t/// Checks if this ResearchProject returns the corresponding Item when research completes.\n\tbool returnItem() const { return _returnsItem; }\n\t/// Checks if this ResearchProject hold reserched item during research.\n\tbool isHoldingNeededItem() const { return _needItem && (_destroyItem || _returnsItem); }\n\n\t/// Check if this ResearchProject is unlocking final mission, it can be only one!\n\tbool unlockFinalMission() const { return _unlockFinalMission; }\n\t/// Check if this ResearchProject is repeatable, i.e. is never marked as discovered.\n\tbool isRepeatable() const { return _repeatable; }\n\t/// Gets the list of ResearchProjects unlocked by this research.\n\tconst std::vector<const RuleResearch*> &getUnlocked() const;\n\t/// Gets the list of ResearchProjects disabled by this research.\n\tconst std::vector<const RuleResearch*> &getDisabled() const;\n\t/// Gets the list of ResearchProjects reenabled by this research.\n\tconst std::vector<const RuleResearch*> &getReenabled() const;\n\t/// Gets the points earned for discovering this ResearchProject.\n\tint getPoints() const;\n\t/// Gets the list of ResearchProjects granted at random for free by this research.\n\tconst std::vector<const RuleResearch*> &getGetOneFree() const;\n\t/// Gets the list(s) of ResearchProjects granted at random for free by this research (if a defined prerequisite is met).\n\tconst std::vector<std::pair<const RuleResearch*, std::vector<const RuleResearch*> > > &getGetOneFreeProtected() const;\n\t/// Gets what to look up in the ufopedia.\n\tconst RuleResearch* getLookup() const { return _lookup; }\n\t/// Gets the requirements for this ResearchProject.\n\tconst std::vector<const RuleResearch*> &getRequirements() const;\n\t/// Gets the base requirements for this ResearchProject.\n\tRuleBaseFacilityFunctions getRequireBaseFunc() const { return _requiresBaseFunc; }\n\t/// Gets the list weight for this research item.\n\tint getListOrder() const;\n\t/// Gets the cutscene to play when this item is researched\n\tconst std::string & getCutscene() const;\n\t/// Gets the item to spawn in the base stores when this topic is researched.\n\tconst std::string & getSpawnedItem() const;\n\t/// Gets the number of items to spawn in the base stores when this topic is researched.\n\tint getSpawnedItemCount() const { return _spawnedItemCount; }\n\t/// Gets the list of items to spawn in the base stores when this topic is researched.\n\tconst std::vector<std::string>& getSpawnedItemList() const { return _spawnedItemList; }\n\t/// Gets the geoscape event to spawn when this topic is researched.\n\tconst std::string& getSpawnedEvent() const { return _spawnedEvent; }\n\t/// Gets the name of custom counter variables to decrease when this topic is researched.\n\tconst std::vector<std::string>& getDecreaseCounter() const { return _decreaseCounter; }\n\t/// Gets the name of custom counter variables to increase when this topic is researched.\n\tconst std::vector<std::string>& getIncreaseCounter() const { return _increaseCounter; }\n\t/// Gets geoscape event rule name to spawn after (each) research completion\n\tstd::string chooseEvent() const { return _events.choose(); }\n\tconst WeightedOptions& getEventsRaw() const { return _events; }\n};\n\n}\n"
  },
  {
    "path": "src/Mod/RuleSkill.cpp",
    "content": "/*\n * Copyright 2010-2020 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"RuleSkill.h\"\n#include \"Mod.h\"\n#include \"../Engine/Collections.h\"\n#include \"../Engine/ScriptBind.h\"\n\nnamespace OpenXcom\n{\n\nRuleSkill::RuleSkill(const std::string& type) : _type(type),\n\t_targetMode(BA_NONE), _compatibleBattleType(BT_NONE), _isPsiRequired(false), _checkHandsOnly(true), _checkHandsOnly2(false)\n{\n}\n\n/**\n * Loads the skill from a YAML file.\n * @param node YAML node.\n * @param mod Mod for the skill.\n */\nvoid RuleSkill::load(const YAML::YamlNodeReader& reader, Mod *mod, const ModScript& parsers)\n{\n\tif (const auto& parent = reader[\"refNode\"])\n\t{\n\t\tload(parent, mod, parsers);\n\t}\n\n\tint targetMode = (int)reader[\"targetMode\"].readVal(_targetMode);\n\ttargetMode = targetMode < 0 ? 0 : targetMode;\n\ttargetMode = targetMode > BA_CQB ? 0 : targetMode;\n\t_targetMode = static_cast<BattleActionType>(targetMode);\n\n\tint compBattleType = (int)reader[\"battleType\"].readVal(_compatibleBattleType);\n\tcompBattleType = compBattleType < 0 ? 0 : compBattleType;\n\tcompBattleType = compBattleType > BT_CORPSE ? 0 : compBattleType;\n\t_compatibleBattleType = static_cast<BattleType>(compBattleType);\n\n\treader.tryRead(\"isPsiRequired\", _isPsiRequired);\n\treader.tryRead(\"checkHandsOnly\", _checkHandsOnly);\n\treader.tryRead(\"checkHandsOnly2\", _checkHandsOnly2);\n\n\t_cost.loadCost(reader, \"Use\");\n\t_flat.loadFlat(reader, \"Use\");\n\n\tmod->loadUnorderedNames(_type, _compatibleWeaponNames, reader[\"compatibleWeapons\"]);\n\tmod->loadUnorderedNames(_type,_requiredBonusNames, reader[\"requiredBonuses\"]);\n\n\t_scriptValues.load(reader, parsers.getShared());\n\n\t_skillScripts.load(_type, reader, parsers.skillScripts);\n}\n\n/**\n * Cross link with other Rules.\n */\nvoid RuleSkill::afterLoad(const Mod* mod)\n{\n\tmod->linkRule(_compatibleWeapons, _compatibleWeaponNames);\n\tmod->linkRule(_requiredBonuses, _requiredBonusNames);\n\n\t//remove not needed data\n\tCollections::removeAll(_compatibleWeaponNames);\n\tCollections::removeAll(_requiredBonusNames);\n}\n\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tScript binding\n////////////////////////////////////////////////////////////\n\nnamespace\n{\n\nvoid getTypeScript(const RuleSkill* r, ScriptText& txt)\n{\n\tif (r)\n\t{\n\t\ttxt = { r->getType().c_str() };\n\t\treturn;\n\t}\n\telse\n\t{\n\t\ttxt = ScriptText::empty;\n\t}\n}\n\nstd::string debugDisplayScript(const RuleSkill* rs)\n{\n\tif (rs)\n\t{\n\t\tstd::string s;\n\t\ts += RuleSkill::ScriptName;\n\t\ts += \"(name: \\\"\";\n\t\ts += rs->getType();\n\t\ts += \"\\\")\";\n\t\treturn s;\n\t}\n\telse\n\t{\n\t\treturn \"null\";\n\t}\n}\n\n}\n\n\n/**\n * Register RuleSkill in script parser.\n * @param parser Script parser.\n */\nvoid RuleSkill::ScriptRegister(ScriptParserBase* parser)\n{\n\tBind<RuleSkill> rs = { parser };\n\n\trs.add<&getTypeScript>(\"getType\");\n\n\trs.addScriptValue<&RuleSkill::_scriptValues>();\n\trs.addDebugDisplay<&debugDisplayScript>();\n}\n\n}\n"
  },
  {
    "path": "src/Mod/RuleSkill.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2020 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include <vector>\n#include \"RuleItem.h\"\n#include \"RuleSoldierBonus.h\"\n#include \"ModScript.h\"\n\nnamespace OpenXcom\n{\n\nenum BattleActionType : Uint8;\n\nclass RuleSkill\n{\nprivate:\n\tstd::string _type;\n\tBattleActionType _targetMode;\n\tBattleType _compatibleBattleType;\n\tbool _isPsiRequired;\n\tbool _checkHandsOnly;\n\tbool _checkHandsOnly2;\n\tRuleItemUseCostRule _cost;\n\tRuleItemUseFlatRule _flat;\n\tstd::vector<std::string> _compatibleWeaponNames;\n\tstd::vector<std::string> _requiredBonusNames;\n\tstd::vector<const RuleItem*> _compatibleWeapons;\n\tstd::vector<const RuleSoldierBonus*> _requiredBonuses;\n\n\tScriptValues<RuleSkill> _scriptValues;\n\tModScript::SkillScripts::Container _skillScripts;\n\npublic:\n\t/// Creates a blank soldier skill ruleset.\n\tRuleSkill(const std::string& type);\n\t/// Cleans up the soldier skill ruleset.\n\t~RuleSkill() = default;\n\t/// Loads the soldier skill data from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader, Mod *mod, const ModScript& parsers);\n\t/// Cross link with other rules.\n\tvoid afterLoad(const Mod* mod);\n\n\t/// Gets the skill's type.\n\tconst std::string& getType() const { return _type; }\n\t/// Gets the targeting mode this skill will be using.\n\tBattleActionType getTargetMode() const { return _targetMode; }\n\t/// Gets the BattleType for potentially compatible items.\n\tBattleType getCompatibleBattleType() const { return _compatibleBattleType; }\n\t/// Is Psi Skill required for this skill to work?\n\tbool isPsiRequired() const { return _isPsiRequired; }\n\t/// Should the check for compatible items only consider the hands (or also the inventory and specialweapon)?\n\tbool checkHandsOnly() const { return _checkHandsOnly; }\n\t/// Should the check for compatible items (by battle type) only consider the hands (or also the inventory and specialweapon)?\n\tbool checkHandsOnly2() const { return _checkHandsOnly2; }\n\t/// Gets the use cost for this skill.\n\tRuleItemUseCost getCost() const { return getDefault(_cost); }\n\t/// Gets the flat vs. percentage cost flags for the use cost of this skill.\n\tRuleItemUseFlat getFlat() const { return getDefault(_flat); }\n\t/// Gets the list of weapons which are compatible with this skill.\n\tconst std::vector<const RuleItem*>& getCompatibleWeapons() const { return _compatibleWeapons; }\n\t/// Gets the list of required soldier bonuses for this skill.\n\tconst std::vector<const RuleSoldierBonus*>& getRequiredBonuses() const { return _requiredBonuses; }\n\n\t/// Name of class used in script.\n\tstatic constexpr const char* ScriptName = \"RuleSkill\";\n\t/// Register all useful function used by script.\n\tstatic void ScriptRegister(ScriptParserBase* parser);\n\n\t/// Gets script.\n\ttemplate<typename Script>\n\tconst typename Script::Container& getScript() const { return _skillScripts.get<Script>(); }\n\t/// Get all script values.\n\tconst ScriptValues<RuleSkill>& getScriptValuesRaw() const { return _scriptValues; }\n};\n\n}\n"
  },
  {
    "path": "src/Mod/RuleSoldier.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include <algorithm>\n#include \"RuleSoldier.h\"\n#include \"RuleSkill.h\"\n#include \"Mod.h\"\n#include \"ModScript.h\"\n#include \"RuleItem.h\"\n#include \"Armor.h\"\n#include \"SoldierNamePool.h\"\n#include \"StatString.h\"\n#include \"../Engine/FileMap.h\"\n#include \"../Engine/ScriptBind.h\"\n#include \"../Engine/Unicode.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Creates a blank RuleSoldier for a certain\n * type of soldier.\n * @param type String defining the type.\n */\nRuleSoldier::RuleSoldier(const std::string &type, int listOrder) : _type(type), _group(0), _listOrder(listOrder), _armor(nullptr), _specWeapon(nullptr),\n\t_monthlyBuyLimit(0), _costBuy(0), _costSalary(0),\n\t_costSalarySquaddie(0), _costSalarySergeant(0), _costSalaryCaptain(0), _costSalaryColonel(0), _costSalaryCommander(0),\n\t_standHeight(0), _kneelHeight(0), _floatHeight(0), _femaleFrequency(50), _value(20), _transferTime(0), _moraleLossWhenKilled(100),\n\t_totalSoldierNamePoolWeight(0),\n\t_avatarOffsetX(67), _avatarOffsetY(48), _flagOffset(0),\n\t_allowPromotion(true), _allowPiloting(true), _showTypeInInventory(false),\n\t_rankSprite(42), _rankSpriteBattlescape(20), _rankSpriteTiny(0), _skillIconSprite(1)\n{\n}\n\n/**\n *\n */\nRuleSoldier::~RuleSoldier()\n{\n\tfor (auto* namepool : _names)\n\t{\n\t\tdelete namepool;\n\t}\n\tfor (auto* statString : _statStrings)\n\t{\n\t\tdelete statString;\n\t}\n}\n\n/**\n * Loads the soldier from a YAML file.\n * @param node YAML node.\n * @param mod Mod for the unit.\n */\nvoid RuleSoldier::load(const YAML::YamlNodeReader& node, Mod *mod, const ModScript &parsers)\n{\n\tconst auto& reader = node.useIndex();\n\tif (const auto& parent = reader[\"refNode\"])\n\t{\n\t\tload(parent, mod, parsers);\n\t}\n\n\t//requires\n\tmod->loadUnorderedNames(_type, _requires, reader[\"requires\"]);\n\tmod->loadBaseFunction(_type, _requiresBuyBaseFunc, reader[\"requiresBuyBaseFunc\"]);\n\treader.tryRead(\"requiresBuyCountry\", _requiresBuyCountry);\n\n\n\t_minStats.merge(reader[\"minStats\"].readVal(_minStats));\n\t_maxStats.merge(reader[\"maxStats\"].readVal(_maxStats));\n\t_statCaps.merge(reader[\"statCaps\"].readVal(_statCaps));\n\tif (reader[\"trainingStatCaps\"])\n\t{\n\t\t_trainingStatCaps.merge(reader[\"trainingStatCaps\"].readVal(_trainingStatCaps));\n\t}\n\telse\n\t{\n\t\t_trainingStatCaps.merge(reader[\"statCaps\"].readVal(_trainingStatCaps));\n\t}\n\t_dogfightExperience.merge(reader[\"dogfightExperience\"].readVal(_dogfightExperience));\n\tmod->loadName(_type, _armorName, reader[\"armor\"]);\n\treader.tryRead(\"specialWeapon\", _specWeaponName);\n\treader.tryRead(\"armorForAvatar\", _armorForAvatar);\n\treader.tryRead(\"avatarOffsetX\", _avatarOffsetX);\n\treader.tryRead(\"avatarOffsetY\", _avatarOffsetY);\n\treader.tryRead(\"flagOffset\", _flagOffset);\n\treader.tryRead(\"allowPromotion\", _allowPromotion);\n\treader.tryRead(\"allowPiloting\", _allowPiloting);\n\treader.tryRead(\"monthlyBuyLimit\", _monthlyBuyLimit);\n\treader.tryRead(\"monthlyBuyLimitMessage\", _monthlyBuyLimitMessage);\n\treader.tryRead(\"costBuy\", _costBuy);\n\treader.tryRead(\"costSalary\", _costSalary);\n\treader.tryRead(\"costSalarySquaddie\", _costSalarySquaddie);\n\treader.tryRead(\"costSalarySergeant\", _costSalarySergeant);\n\treader.tryRead(\"costSalaryCaptain\", _costSalaryCaptain);\n\treader.tryRead(\"costSalaryColonel\", _costSalaryColonel);\n\treader.tryRead(\"costSalaryCommander\", _costSalaryCommander);\n\treader.tryRead(\"standHeight\", _standHeight);\n\treader.tryRead(\"kneelHeight\", _kneelHeight);\n\treader.tryRead(\"floatHeight\", _floatHeight);\n\treader.tryRead(\"femaleFrequency\", _femaleFrequency);\n\treader.tryRead(\"value\", _value);\n\treader.tryRead(\"transferTime\", _transferTime);\n\treader.tryRead(\"moraleLossWhenKilled\", _moraleLossWhenKilled);\n\treader.tryRead(\"showTypeInInventory\", _showTypeInInventory);\n\n\tmod->loadSoundOffset(_type, _deathSoundMale, reader[\"deathMale\"], \"BATTLE.CAT\");\n\tmod->loadSoundOffset(_type, _deathSoundFemale, reader[\"deathFemale\"], \"BATTLE.CAT\");\n\tmod->loadSoundOffset(_type, _panicSoundMale, reader[\"panicMale\"], \"BATTLE.CAT\");\n\tmod->loadSoundOffset(_type, _panicSoundFemale, reader[\"panicFemale\"], \"BATTLE.CAT\");\n\tmod->loadSoundOffset(_type, _berserkSoundMale, reader[\"berserkMale\"], \"BATTLE.CAT\");\n\tmod->loadSoundOffset(_type, _berserkSoundFemale, reader[\"berserkFemale\"], \"BATTLE.CAT\");\n\n\tmod->loadSoundOffset(_type, _selectUnitSoundMale, reader[\"selectUnitMale\"], \"BATTLE.CAT\");\n\tmod->loadSoundOffset(_type, _selectUnitSoundFemale, reader[\"selectUnitFemale\"], \"BATTLE.CAT\");\n\tmod->loadSoundOffset(_type, _startMovingSoundMale, reader[\"startMovingMale\"], \"BATTLE.CAT\");\n\tmod->loadSoundOffset(_type, _startMovingSoundFemale, reader[\"startMovingFemale\"], \"BATTLE.CAT\");\n\tmod->loadSoundOffset(_type, _selectWeaponSoundMale, reader[\"selectWeaponMale\"], \"BATTLE.CAT\");\n\tmod->loadSoundOffset(_type, _selectWeaponSoundFemale, reader[\"selectWeaponFemale\"], \"BATTLE.CAT\");\n\tmod->loadSoundOffset(_type, _annoyedSoundMale, reader[\"annoyedMale\"], \"BATTLE.CAT\");\n\tmod->loadSoundOffset(_type, _annoyedSoundFemale, reader[\"annoyedFemale\"], \"BATTLE.CAT\");\n\n\tfor (const auto& fileNameOrCommand : reader[\"soldierNames\"].children())\n\t{\n\t\tstd::string fileName = fileNameOrCommand.readVal<std::string>();\n\t\tif (fileName == \"delete\")\n\t\t{\n\t\t\tfor (auto* namepool : _names)\n\t\t\t{\n\t\t\t\tdelete namepool;\n\t\t\t}\n\t\t\t_names.clear();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (fileName[fileName.length() - 1] == '/')\n\t\t\t{\n\t\t\t\t// load all *.nam files in given directory\n\t\t\t\tstd::vector<std::string> names;\n\t\t\t\tfor (const auto& f: FileMap::filterFiles(FileMap::getVFolderContents(fileName), \"nam\")) { names.push_back(f); }\n\t\t\t\tstd::sort(names.begin(), names.end(), Unicode::naturalCompare);\n\t\t\t\tfor (const auto& name : names)\n\t\t\t\t{\n\t\t\t\t\taddSoldierNamePool(fileName + name);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// load given file\n\t\t\t\taddSoldierNamePool(fileName);\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (const auto& statStringReader : reader[\"statStrings\"].children())\n\t{\n\t\tStatString *statString = new StatString();\n\t\tstatString->load(statStringReader);\n\t\t_statStrings.push_back(statString);\n\t}\n\n\tmod->loadNames(_type, _rankStrings, reader[\"rankStrings\"]);\n\tmod->loadSpriteOffset(_type, _rankSprite, reader[\"rankSprite\"], \"BASEBITS.PCK\");\n\tmod->loadSpriteOffset(_type, _rankSpriteBattlescape, reader[\"rankBattleSprite\"], \"SMOKE.PCK\");\n\tmod->loadSpriteOffset(_type, _rankSpriteTiny, reader[\"rankTinySprite\"], \"TinyRanks\");\n\tmod->loadSpriteOffset(_type, _skillIconSprite, reader[\"skillIconSprite\"], \"SPICONS.DAT\");\n\n\tmod->loadNames(_type, _skillNames, reader[\"skills\"]);\n\n\tif (reader[\"spawnedSoldier\"])\n\t{\n\t\t_spawnedSoldier = reader[\"spawnedSoldier\"].emitDescendants(YAML::YamlRootNodeReader(_spawnedSoldier, \"(spawned soldier template)\"));\n\t}\n\treader.tryRead(\"group\", _group);\n\treader.tryRead(\"listOrder\", _listOrder);\n\n\t_scriptValues.load(reader, parsers.getShared());\n}\n\n/**\n * Cross link with other Rules.\n */\nvoid RuleSoldier::afterLoad(const Mod* mod)\n{\n\t_totalSoldierNamePoolWeight = 0;\n\tfor (auto* namepool : _names)\n\t{\n\t\t_totalSoldierNamePoolWeight += namepool->getGlobalWeight();\n\t}\n\tif (_totalSoldierNamePoolWeight < 1)\n\t{\n\t\tLog(LOG_ERROR) << _type << \": total soldier name pool weight is invalid. Forgotten 'soldierNames:' ?\";\n\t}\n\n\tmod->linkRule(_armor, _armorName);\n\tmod->checkForSoftError(_armor == nullptr, _type, \"Soldier type is missing the default armor\", LOG_ERROR);\n\n\tmod->verifySoundOffset(_type, _deathSoundMale, \"BATTLE.CAT\");\n\tmod->verifySoundOffset(_type, _deathSoundFemale, \"BATTLE.CAT\");\n\tmod->verifySoundOffset(_type, _panicSoundMale, \"BATTLE.CAT\");\n\tmod->verifySoundOffset(_type, _panicSoundFemale, \"BATTLE.CAT\");\n\tmod->verifySoundOffset(_type, _berserkSoundMale, \"BATTLE.CAT\");\n\tmod->verifySoundOffset(_type, _berserkSoundFemale, \"BATTLE.CAT\");\n\n\tmod->verifySoundOffset(_type, _selectUnitSoundMale, \"BATTLE.CAT\");\n\tmod->verifySoundOffset(_type, _selectUnitSoundFemale, \"BATTLE.CAT\");\n\tmod->verifySoundOffset(_type, _startMovingSoundMale, \"BATTLE.CAT\");\n\tmod->verifySoundOffset(_type, _startMovingSoundFemale, \"BATTLE.CAT\");\n\tmod->verifySoundOffset(_type, _selectWeaponSoundMale, \"BATTLE.CAT\");\n\tmod->verifySoundOffset(_type, _selectWeaponSoundFemale, \"BATTLE.CAT\");\n\tmod->verifySoundOffset(_type, _annoyedSoundMale, \"BATTLE.CAT\");\n\tmod->verifySoundOffset(_type, _annoyedSoundFemale, \"BATTLE.CAT\");\n\n\tmod->verifySpriteOffset(_type, _rankSprite, \"BASEBITS.PCK\");\n\tmod->verifySpriteOffset(_type, _rankSpriteBattlescape, \"SMOKE.PCK\");\n\tmod->verifySpriteOffset(_type, _rankSpriteTiny, \"TinyRanks\");\n\tmod->verifySpriteOffset(_type, _skillIconSprite, \"SPICONS.DAT\");\n\n\tif (!_specWeaponName.empty())\n\t{\n\t\tmod->linkRule(_specWeapon, _specWeaponName);\n\n\t\tif ((_specWeapon->getBattleType() == BT_FIREARM || _specWeapon->getBattleType() == BT_MELEE) && !_specWeapon->getClipSize())\n\t\t{\n\t\t\tthrow Exception(\"Weapon \" + _specWeaponName + \" is used as a special weapon, but doesn't have its own ammo - give it a clipSize!\");\n\t\t}\n\t}\n\tmod->linkRule(_skills, _skillNames);\n\n\t_manaMissingWoundThreshold = mod->getManaWoundThreshold();\n\t_healthMissingWoundThreshold = mod->getHealthWoundThreshold();\n}\n\nvoid RuleSoldier::addSoldierNamePool(const std::string &namFile)\n{\n\tSoldierNamePool *pool = new SoldierNamePool();\n\tpool->load(namFile);\n\t_names.push_back(pool);\n}\n\n/**\n * Returns the language string that names\n * this soldier. Each soldier type has a unique name.\n * @return Soldier name.\n */\nconst std::string& RuleSoldier::getType() const\n{\n\treturn _type;\n}\n\n/**\n * Gets the list/sort order of the soldier's type.\n * @return The list/sort order.\n */\nint RuleSoldier::getListOrder() const\n{\n\treturn _listOrder;\n}\n\n/**\n * Gets the list of research required to\n * acquire this soldier.\n * @return The list of research IDs.\n*/\nconst std::vector<std::string> &RuleSoldier::getRequirements() const\n{\n\treturn _requires;\n}\n\n/**\n * Gets the minimum stats for the random stats generator.\n * @return The minimum stats.\n */\nUnitStats RuleSoldier::getMinStats() const\n{\n\treturn _minStats;\n}\n\n/**\n * Gets the maximum stats for the random stats generator.\n * @return The maximum stats.\n */\nUnitStats RuleSoldier::getMaxStats() const\n{\n\treturn _maxStats;\n}\n\n/**\n * Gets the stat caps.\n * @return The stat caps.\n */\nUnitStats RuleSoldier::getStatCaps() const\n{\n\treturn _statCaps;\n}\n\n/**\n* Gets the training stat caps.\n* @return The training stat caps.\n*/\nUnitStats RuleSoldier::getTrainingStatCaps() const\n{\n\treturn _trainingStatCaps;\n}\n\n/**\n* Gets the improvement chances for pilots (after dogfight).\n* @return The improvement changes.\n*/\nUnitStats RuleSoldier::getDogfightExperience() const\n{\n\treturn _dogfightExperience;\n}\n\n/**\n * Gets the cost of hiring this soldier.\n * @return The cost.\n */\nint RuleSoldier::getBuyCost() const\n{\n\treturn _costBuy;\n}\n\n/**\n* Does salary depend on rank?\n* @return True if salary depends on rank, false otherwise.\n*/\nbool RuleSoldier::isSalaryDynamic() const\n{\n\treturn _costSalarySquaddie || _costSalarySergeant || _costSalaryCaptain || _costSalaryColonel || _costSalaryCommander;\n}\n\n/**\n * Gets the list of defined skills.\n * @return The list of defined skills.\n */\nconst std::vector<const RuleSkill*> &RuleSoldier::getSkills() const\n{\n\treturn _skills;\n}\n\n/**\n * Gets the sprite index into SPICONS for the skill icon sprite.\n * @return The sprite index.\n */\nint RuleSoldier::getSkillIconSprite() const\n{\n\treturn _skillIconSprite;\n}\n\n/**\n * Gets the cost of salary for a month (for a given rank).\n * @param rank Soldier rank.\n * @return The cost.\n */\nint RuleSoldier::getSalaryCost(int rank) const\n{\n\tint total = _costSalary;\n\tswitch (rank)\n\t{\n\t\tcase 1: total += _costSalarySquaddie; break;\n\t\tcase 2: total += _costSalarySergeant; break;\n\t\tcase 3: total += _costSalaryCaptain; break;\n\t\tcase 4: total += _costSalaryColonel; break;\n\t\tcase 5: total += _costSalaryCommander; break;\n\t\tdefault: break;\n\t}\n\treturn total;\n}\n\n/**\n * Gets the height of the soldier when it's standing.\n * @return The standing height.\n */\nint RuleSoldier::getStandHeight() const\n{\n\treturn _standHeight;\n}\n\n/**\n * Gets the height of the soldier when it's kneeling.\n * @return The kneeling height.\n */\nint RuleSoldier::getKneelHeight() const\n{\n\treturn _kneelHeight;\n}\n\n/**\n * Gets the elevation of the soldier when it's flying.\n * @return The floating height.\n */\nint RuleSoldier::getFloatHeight() const\n{\n\treturn _floatHeight;\n}\n\n/**\n * Gets the default armor name.\n * @return The armor name.\n */\nArmor* RuleSoldier::getDefaultArmor() const\n{\n\treturn const_cast<Armor*>(_armor); //TODO: fix this function usage to remove const cast\n}\n\n/**\n* Gets the armor for avatar.\n* @return The armor name.\n*/\nconst std::string& RuleSoldier::getArmorForAvatar() const\n{\n\treturn _armorForAvatar;\n}\n\n/**\n* Gets the avatar's X offset.\n* @return The X offset.\n*/\nint RuleSoldier::getAvatarOffsetX() const\n{\n\treturn _avatarOffsetX;\n}\n\n/**\n* Gets the avatar's Y offset.\n* @return The Y offset.\n*/\nint RuleSoldier::getAvatarOffsetY() const\n{\n\treturn _avatarOffsetY;\n}\n\n/**\n* Gets the flag offset.\n* @return The flag offset.\n*/\nint RuleSoldier::getFlagOffset() const\n{\n\treturn _flagOffset;\n}\n\n/**\n* Gets the allow promotion flag.\n* @return True if promotion is allowed.\n*/\nbool RuleSoldier::getAllowPromotion() const\n{\n\treturn _allowPromotion;\n}\n\n/**\n* Gets the allow piloting flag.\n* @return True if piloting is allowed.\n*/\nbool RuleSoldier::getAllowPiloting() const\n{\n\treturn _allowPiloting;\n}\n\n/**\n * Gets the female appearance ratio.\n * @return The percentage ratio.\n */\nint RuleSoldier::getFemaleFrequency() const\n{\n\treturn _femaleFrequency;\n}\n\n/**\n * Gets the death sounds for male soldiers.\n * @return List of sound IDs.\n */\nconst std::vector<int> &RuleSoldier::getMaleDeathSounds() const\n{\n\treturn _deathSoundMale;\n}\n\n/**\n * Gets the death sounds for female soldiers.\n * @return List of sound IDs.\n */\nconst std::vector<int> &RuleSoldier::getFemaleDeathSounds() const\n{\n\treturn _deathSoundFemale;\n}\n\n/**\n * Gets the panic sounds for male soldiers.\n * @return List of sound IDs.\n */\nconst std::vector<int> &RuleSoldier::getMalePanicSounds() const\n{\n\treturn _panicSoundMale;\n}\n\n/**\n * Gets the panic sounds for female soldiers.\n * @return List of sound IDs.\n */\nconst std::vector<int> &RuleSoldier::getFemalePanicSounds() const\n{\n\treturn _panicSoundFemale;\n}\n\n/**\n * Gets the berserk sounds for male soldiers.\n * @return List of sound IDs.\n */\nconst std::vector<int> &RuleSoldier::getMaleBerserkSounds() const\n{\n\treturn _berserkSoundMale;\n}\n\n/**\n * Gets the berserk sounds for female soldiers.\n * @return List of sound IDs.\n */\nconst std::vector<int> &RuleSoldier::getFemaleBerserkSounds() const\n{\n\treturn _berserkSoundFemale;\n}\n\n/**\n * Returns the list of soldier name pools.\n * @return Pointer to soldier name pool list.\n */\nconst std::vector<SoldierNamePool*> &RuleSoldier::getNames() const\n{\n\treturn _names;\n}\n\n/*\n * Gets the soldier's base value, without experience modifiers.\n * @return The soldier's value.\n */\nint RuleSoldier::getValue() const\n{\n\treturn _value;\n}\n\n/*\n * Gets the amount of time this item\n * takes to arrive at a base.\n * @return The time in hours.\n */\nint RuleSoldier::getTransferTime() const\n{\n\treturn _transferTime;\n}\n\n/**\n* Gets the list of StatStrings.\n* @return The list of StatStrings.\n*/\nconst std::vector<StatString *> &RuleSoldier::getStatStrings() const\n{\n\treturn _statStrings;\n}\n\n/**\n * Gets the list of strings for this soldier's ranks\n * @return The list rank strings.\n */\nconst std::vector<std::string> &RuleSoldier::getRankStrings() const\n{\n\treturn _rankStrings;\n}\n\n/**\n * Gets the index of the sprites to use to represent this soldier's rank in BASEBITS.PCK\n * @return The sprite index.\n */\nint RuleSoldier::getRankSprite() const\n{\n\treturn _rankSprite;\n}\n\n/**\n * Gets the index of the sprites to use to represent this soldier's rank in SMOKE.PCK\n * @return The sprite index.\n */\nint RuleSoldier::getRankSpriteBattlescape() const\n{\n\treturn _rankSpriteBattlescape;\n}\n\n/**\n * Gets the index of the sprites to use to represent this soldier's rank in TinyRanks\n * @return The sprite index.\n */\nint RuleSoldier::getRankSpriteTiny() const\n{\n\treturn _rankSpriteTiny;\n}\n\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tScript binding\n////////////////////////////////////////////////////////////\n\n\nnamespace\n{\n\nvoid getTypeScript(const RuleSkill* r, ScriptText& txt)\n{\n\tif (r)\n\t{\n\t\ttxt = { r->getType().c_str() };\n\t\treturn;\n\t}\n\telse\n\t{\n\t\ttxt = ScriptText::empty;\n\t}\n}\n\nstd::string debugDisplayScript(const RuleSoldier* rs)\n{\n\tif (rs)\n\t{\n\t\tstd::string s;\n\t\ts += RuleSoldier::ScriptName;\n\t\ts += \"(name: \\\"\";\n\t\ts += rs->getType();\n\t\ts += \"\\\")\";\n\t\treturn s;\n\t}\n\telse\n\t{\n\t\treturn \"null\";\n\t}\n}\n\n}\n\n/**\n * Register Armor in script parser.\n * @param parser Script parser.\n */\nvoid RuleSoldier::ScriptRegister(ScriptParserBase* parser)\n{\n\tBind<RuleSoldier> ra = { parser };\n\n\tUnitStats::addGetStatsScript<&RuleSoldier::_statCaps>(ra, \"StatsCap.\");\n\tUnitStats::addGetStatsScript<&RuleSoldier::_minStats>(ra, \"StatsMin.\");\n\tUnitStats::addGetStatsScript<&RuleSoldier::_maxStats>(ra, \"StatsMax.\");\n\n\tra.add<&getTypeScript>(\"getType\");\n\n\tra.addScriptValue<BindBase::OnlyGet, &RuleSoldier::_scriptValues>();\n\tra.addDebugDisplay<&debugDisplayScript>();\n}\n\n}\n"
  },
  {
    "path": "src/Mod/RuleSoldier.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include \"../Engine/Yaml.h\"\n#include \"Unit.h\"\n#include \"RuleBaseFacilityFunctions.h\"\n#include \"../Engine/Script.h\"\n\nnamespace OpenXcom\n{\n\nclass Mod;\nclass ModScript;\nclass SoldierNamePool;\nclass StatString;\nclass RuleItem;\nclass RuleSkill;\nclass Armor;\n\n/**\n * Represents the creation data for an X-COM unit.\n * This info is copied to either Soldier for Geoscape or BattleUnit for Battlescape.\n * @sa Soldier BattleUnit\n */\nclass RuleSoldier\n{\npublic:\n\n\t/// Number of bits for soldier gender.\n\tstatic constexpr int LookGenderBits = 1;\n\t/// Number of bits for soldier look.\n\tstatic constexpr int LookBaseBits = 2;\n\t/// Number of bits for soldier lookVariants.\n\tstatic constexpr int LookVariantBits = 6;\n\t/// Max number of soldier lookVariant.s\n\tstatic constexpr int LookVariantMax = (1 << LookVariantBits);\n\t/// Mask for soldier lookVariants.\n\tstatic constexpr int LookVariantMask = LookVariantMax - 1;\n\t/// Mask for all possible looks types for soldier.\n\tstatic constexpr int LookTotalMask = (1 << (LookVariantBits + LookBaseBits + LookGenderBits)) - 1;\n\n\t/// Name of class used in script.\n\tstatic constexpr const char *ScriptName = \"RuleSoldier\";\n\t/// Register all useful function used by script.\n\tstatic void ScriptRegister(ScriptParserBase* parser);\n\nprivate:\n\tstd::string _type;\n\tYAML::YamlString _spawnedSoldier;\n\tint _group;\n\tint _listOrder;\n\tstd::vector<std::string> _requires;\n\tRuleBaseFacilityFunctions _requiresBuyBaseFunc;\n\tstd::string _requiresBuyCountry;\n\tUnitStats _minStats, _maxStats, _statCaps, _trainingStatCaps, _dogfightExperience;\n\tstd::string _armorName;\n\tconst Armor* _armor;\n\tstd::string _specWeaponName;\n\tconst RuleItem* _specWeapon;\n\tint _monthlyBuyLimit;\n\tstd::string _monthlyBuyLimitMessage;\n\tint _costBuy, _costSalary, _costSalarySquaddie, _costSalarySergeant, _costSalaryCaptain, _costSalaryColonel, _costSalaryCommander;\n\tint _standHeight, _kneelHeight, _floatHeight;\n\tint _femaleFrequency, _value, _transferTime, _moraleLossWhenKilled;\n\tint _manaMissingWoundThreshold = -1;\n\tint _healthMissingWoundThreshold = -1;\n\tstd::vector<int> _deathSoundMale, _deathSoundFemale;\n\tstd::vector<int> _panicSoundMale, _panicSoundFemale, _berserkSoundMale, _berserkSoundFemale;\n\tstd::vector<int> _selectUnitSoundMale, _selectUnitSoundFemale;\n\tstd::vector<int> _startMovingSoundMale, _startMovingSoundFemale;\n\tstd::vector<int> _selectWeaponSoundMale, _selectWeaponSoundFemale;\n\tstd::vector<int> _annoyedSoundMale, _annoyedSoundFemale;\n\tstd::vector<SoldierNamePool*> _names;\n\tint _totalSoldierNamePoolWeight;\n\tstd::string _armorForAvatar;\n\tint _avatarOffsetX, _avatarOffsetY, _flagOffset;\n\tbool _allowPromotion, _allowPiloting, _showTypeInInventory;\n\tstd::vector<StatString*> _statStrings;\n\tstd::vector<std::string> _rankStrings;\n\tint _rankSprite, _rankSpriteBattlescape, _rankSpriteTiny;\n\tint _skillIconSprite;\n\tstd::vector<std::string> _skillNames;\n\tstd::vector<const RuleSkill*> _skills;\n\tScriptValues<RuleSoldier> _scriptValues;\n\n\tvoid addSoldierNamePool(const std::string &namFile);\npublic:\n\t/// Creates a blank soldier ruleset.\n\tRuleSoldier(const std::string &type, int listOrder);\n\t/// Cleans up the soldier ruleset.\n\t~RuleSoldier();\n\t/// Loads the soldier data from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader, Mod *mod, const ModScript &parsers);\n\t/// Cross link with other rules.\n\tvoid afterLoad(const Mod* mod);\n\t/// Gets the soldier's type.\n\tconst std::string& getType() const;\n\t/// Gets the spawned soldier template.\n\tconst YAML::YamlString& getSpawnedSoldierTemplate() const { return _spawnedSoldier; }\n\t/// Gets the soldier type group.\n\tint getGroup() const { return _group; }\n\t/// Gets whether or not the soldier type should be displayed in the inventory.\n\tbool getShowTypeInInventory() const { return _showTypeInInventory; }\n\t/// Gets the list/sort order of the soldier's type.\n\tint getListOrder() const;\n\t/// Gets the soldier's requirements.\n\tconst std::vector<std::string> &getRequirements() const;\n\t/// Gets the base functions required to hire this soldier type.\n\tRuleBaseFacilityFunctions getRequiresBuyBaseFunc() const { return _requiresBuyBaseFunc; }\n\t/// Gets the allied country name required to hire this soldier type.\n\tconst std::string& getRequiresBuyCountry() const { return _requiresBuyCountry; }\n\t/// Gets the minimum stats for the random stats generator.\n\tUnitStats getMinStats() const;\n\t/// Gets the maximum stats for the random stats generator.\n\tUnitStats getMaxStats() const;\n\t/// Gets the stat caps.\n\tUnitStats getStatCaps() const;\n\t/// Gets the training stat caps.\n\tUnitStats getTrainingStatCaps() const;\n\t/// Gets the improvement chances for pilots (after dogfight).\n\tUnitStats getDogfightExperience() const;\n\t/// Gets the monthly hiring limit.\n\tint getMonthlyBuyLimit() const { return _monthlyBuyLimit; }\n\t/// Gets the monthly hiring limit message.\n\tconst std::string& getMonthlyBuyLimitMessage() const { return _monthlyBuyLimitMessage; }\n\t/// Gets the cost of the soldier.\n\tint getBuyCost() const;\n\t/// Does salary depend on rank?\n\tbool isSalaryDynamic() const;\n\t/// Gets the list of defined skills.\n\tconst std::vector<const RuleSkill*> &getSkills() const;\n\t/// Returns the sprite index for the skill icon sprite.\n\tint getSkillIconSprite() const;\n\t/// Gets the monthly salary of the soldier (for a given rank).\n\tint getSalaryCost(int rank) const;\n\t/// Gets the height of the soldier when it's standing.\n\tint getStandHeight() const;\n\t/// Gets the height of the soldier when it's kneeling.\n\tint getKneelHeight() const;\n\t/// Gets the elevation of the soldier when it's flying.\n\tint getFloatHeight() const;\n\t/// Gets the default-equipped armor.\n\tArmor* getDefaultArmor() const;\n\t/// Gets the armor for avatar display.\n\tconst std::string& getArmorForAvatar() const;\n\t/// Gets the X offset used for avatar.\n\tint getAvatarOffsetX() const;\n\t/// Gets the Y offset used for avatar.\n\tint getAvatarOffsetY() const;\n\t/// Gets the flag offset.\n\tint getFlagOffset() const;\n\t/// Gets the special weapon.\n\tconst RuleItem* getSpecialWeapon() const { return _specWeapon; }\n\t/// Gets the allow promotion flag.\n\tbool getAllowPromotion() const;\n\t/// Gets the allow piloting flag.\n\tbool getAllowPiloting() const;\n\t/// Gets the female appearance ratio.\n\tint getFemaleFrequency() const;\n\t/// Gets the soldier's male death sounds.\n\tconst std::vector<int> &getMaleDeathSounds() const;\n\t/// Gets the soldier's female death sounds.\n\tconst std::vector<int> &getFemaleDeathSounds() const;\n\t/// Gets the soldier's male panic sounds.\n\tconst std::vector<int> &getMalePanicSounds() const;\n\t/// Gets the soldier's female panic sounds.\n\tconst std::vector<int> &getFemalePanicSounds() const;\n\t/// Gets the soldier's male berserk sounds.\n\tconst std::vector<int> &getMaleBerserkSounds() const;\n\t/// Gets the soldier's female berserk sounds.\n\tconst std::vector<int> &getFemaleBerserkSounds() const;\n\t/// Gets the soldier's male \"select unit\" sounds.\n\tconst std::vector<int> &getMaleSelectUnitSounds() const { return _selectUnitSoundMale; }\n\t/// Gets the soldier's female \"select unit\" sounds.\n\tconst std::vector<int> &getFemaleSelectUnitSounds() const { return _selectUnitSoundFemale; }\n\t/// Gets the soldier's male \"start moving\" sounds.\n\tconst std::vector<int> &getMaleStartMovingSounds() const { return _startMovingSoundMale; }\n\t/// Gets the soldier's female \"start moving\" sounds.\n\tconst std::vector<int> &getFemaleStartMovingSounds() const { return _startMovingSoundFemale; }\n\t/// Gets the soldier's male \"select weapon\" sounds.\n\tconst std::vector<int> &getMaleSelectWeaponSounds() const { return _selectWeaponSoundMale; }\n\t/// Gets the soldier's female \"select weapon\" sounds.\n\tconst std::vector<int> &getFemaleSelectWeaponSounds() const { return _selectWeaponSoundFemale; }\n\t/// Gets the soldier's male \"annoyed\" sounds.\n\tconst std::vector<int> &getMaleAnnoyedSounds() const { return _annoyedSoundMale; }\n\t/// Gets the soldier's female \"annoyed\" sounds.\n\tconst std::vector<int> &getFemaleAnnoyedSounds() const { return _annoyedSoundFemale; }\n\t/// Gets the pool list for soldier names.\n\tconst std::vector<SoldierNamePool*> &getNames() const;\n\t/// Gets the total weight of all the soldier name pools.\n\tint getTotalSoldierNamePoolWeight() const { return _totalSoldierNamePoolWeight; }\n\t/// Gets the value - for score calculation.\n\tint getValue() const;\n\t/// Gets the soldier's transfer time.\n\tint getTransferTime() const;\n\t/// Percentage modifier for morale loss when this unit is killed.\n\tint getMoraleLossWhenKilled() const { return _moraleLossWhenKilled; };\n\t/// Gets the list of StatStrings.\n\tconst std::vector<StatString *> &getStatStrings() const;\n\t/// Gets the list of strings for ranks.\n\tconst std::vector<std::string> &getRankStrings() const;\n\t/// Gets the offset of the rank sprite in BASEBITS.PCK.\n\tint getRankSprite() const;\n\t/// Gets the offset of the rank sprite in SMOKE.PCK.\n\tint getRankSpriteBattlescape() const;\n\t/// Gets the offset of the rank sprite in TinyRanks.\n\tint getRankSpriteTiny() const;\n\n\t/// Get all script values.\n\tconst ScriptValues<RuleSoldier> &getScriptValuesRaw() const { return _scriptValues; }\n\n\t/// How much missing mana will act as \"fatal wounds\" and prevent the soldier from going into battle.\n\tint getManaWoundThreshold() const { return _manaMissingWoundThreshold; }\n\t/// How much missing health will act as \"fatal wounds\" and prevent the soldier from going into battle.\n\tint getHealthWoundThreshold() const { return _healthMissingWoundThreshold; }\n};\n\n}\n"
  },
  {
    "path": "src/Mod/RuleSoldierBonus.cpp",
    "content": "/*\n * Copyright 2010-2019 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"RuleSoldierBonus.h\"\n#include \"Mod.h\"\n#include \"../Engine/ScriptBind.h\"\n#include \"../Savegame/BattleUnit.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n\n\nnamespace OpenXcom\n{\n\nRuleSoldierBonus::RuleSoldierBonus(const std::string &name, int listOrder) : _name(name), _frontArmor(0), _sideArmor(0), _leftArmorDiff(0), _rearArmor(0), _underArmor(0), _listOrder(listOrder)\n{\n}\n\n/**\n * Loads the soldier bonus definition from YAML.\n * @param node YAML node.\n */\nvoid RuleSoldierBonus::load(const YAML::YamlNodeReader& node, Mod* mod, const ModScript &parsers)\n{\n\tconst auto& reader = node.useIndex();\n\tif (const auto& parent = reader[\"refNode\"])\n\t{\n\t\tload(parent, mod, parsers);\n\t}\n\n\treader.tryRead(\"visibilityAtDark\", _visibilityAtDark);\n\treader.tryRead(\"visibilityAtDay\", _visibilityAtDay);\n\treader.tryRead(\"psiVision\", _psiVision);\n\treader.tryRead(\"heatVision\", _visibilityThroughSmoke);\n\treader.tryRead(\"visibilityThroughFire\", _visibilityThroughFire);\n\n\treader.tryRead(\"frontArmor\", _frontArmor);\n\treader.tryRead(\"sideArmor\", _sideArmor);\n\treader.tryRead(\"leftArmorDiff\", _leftArmorDiff);\n\treader.tryRead(\"rearArmor\", _rearArmor);\n\treader.tryRead(\"underArmor\", _underArmor);\n\t_stats.merge(reader[\"stats\"].readVal(_stats));\n\tconst auto& rec = reader[\"recovery\"];\n\t{\n\t\t_timeRecovery.load(_name, rec, parsers.bonusStatsScripts.get<ModScript::TimeSoldierRecoveryStatBonus>());\n\t\t_energyRecovery.load(_name, rec, parsers.bonusStatsScripts.get<ModScript::EnergySoldierRecoveryStatBonus>());\n\t\t_moraleRecovery.load(_name, rec, parsers.bonusStatsScripts.get<ModScript::MoraleSoldierRecoveryStatBonus>());\n\t\t_healthRecovery.load(_name, rec, parsers.bonusStatsScripts.get<ModScript::HealthSoldierRecoveryStatBonus>());\n\t\t_manaRecovery.load(_name, rec, parsers.bonusStatsScripts.get<ModScript::ManaSoldierRecoveryStatBonus>());\n\t\t_stunRecovery.load(_name, rec, parsers.bonusStatsScripts.get<ModScript::StunSoldierRecoveryStatBonus>());\n\t}\n\n\t_soldierBonusScripts.load(_name, reader, parsers.soldierBonusScripts);\n\t_scriptValues.load(reader, parsers.getShared());\n\n\treader.tryRead(\"listOrder\", _listOrder);\n}\n\n/**\n *  Gets the bonus TU recovery.\n */\nint RuleSoldierBonus::getTimeRecovery(const BattleUnit *unit) const\n{\n\treturn _timeRecovery.getBonus(unit);\n}\n\n/**\n *  Gets the bonus Energy recovery.\n */\nint RuleSoldierBonus::getEnergyRecovery(const BattleUnit *unit) const\n{\n\treturn _energyRecovery.getBonus(unit);\n}\n\n/**\n *  Gets the bonus Morale recovery.\n */\nint RuleSoldierBonus::getMoraleRecovery(const BattleUnit *unit) const\n{\n\treturn _moraleRecovery.getBonus(unit);\n}\n\n/**\n *  Gets the bonus Health recovery.\n */\nint RuleSoldierBonus::getHealthRecovery(const BattleUnit *unit) const\n{\n\treturn _healthRecovery.getBonus(unit);\n}\n\n/**\n *  Gets the bonus Mana recovery.\n */\nint RuleSoldierBonus::getManaRecovery(const BattleUnit *unit) const\n{\n\treturn _manaRecovery.getBonus(unit);\n}\n\n/**\n *  Gets the bonus Stun recovery.\n */\nint RuleSoldierBonus::getStunRegeneration(const BattleUnit *unit) const\n{\n\treturn _stunRecovery.getBonus(unit);\n}\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tScript binding\n////////////////////////////////////////////////////////////\n\nnamespace\n{\n\nstd::string debugDisplayScript(const RuleSoldierBonus* ri)\n{\n\tif (ri)\n\t{\n\t\tstd::string s;\n\t\ts += RuleSoldierBonus::ScriptName;\n\t\ts += \"(name: \\\"\";\n\t\ts += ri->getName();\n\t\ts += \"\\\")\";\n\t\treturn s;\n\t}\n\telse\n\t{\n\t\treturn \"null\";\n\t}\n}\n\n}\n\n/**\n * Register RuleSoldierBonus in script parser.\n * @param parser Script parser.\n */\nvoid RuleSoldierBonus::ScriptRegister(ScriptParserBase* parser)\n{\n\tparser->registerPointerType<Mod>();\n\n\tBind<RuleSoldierBonus> rsb = { parser };\n\n\tUnitStats::addGetStatsScript<&RuleSoldierBonus::_stats>(rsb, \"Stats.\");\n\trsb.addScriptValue<BindBase::OnlyGet, &RuleSoldierBonus::_scriptValues>();\n\trsb.addDebugDisplay<&debugDisplayScript>();\n}\n\n\nModScript::ApplySoldierBonusesParser::ApplySoldierBonusesParser(ScriptGlobal* shared, const std::string& name, Mod* mod) : ScriptParserEvents{ shared, name, \"unit\", \"save_game\", \"soldier_bonus\", }\n{\n\tBindBase b { this };\n\n\tb.addCustomPtr<const Mod>(\"rules\", mod);\n}\n\n}\n"
  },
  {
    "path": "src/Mod/RuleSoldierBonus.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2019 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include \"../Engine/Yaml.h\"\n#include \"Unit.h\"\n#include \"RuleStatBonus.h\"\n#include \"ModScript.h\"\n\nnamespace OpenXcom\n{\n\nclass BattleUnit;\n\n/**\n * Represents an assignable extra bonus to soldier's stats, regen and night vision.\n * Bonus is awarded either via SoldierCommendations or via SoldierTransformations.\n */\nclass RuleSoldierBonus\n{\npublic:\n\n\t/// Name of class used in script.\n\tstatic constexpr const char *ScriptName = \"RuleSoldierBonus\";\n\t/// Register all useful function used by script.\n\tstatic void ScriptRegister(ScriptParserBase* parser);\n\nprivate:\n\tstd::string _name;\n\n\tint _visibilityAtDark = 0;\n\tint _visibilityAtDay = 0;\n\tint _psiVision = 0;\n\tint _visibilityThroughSmoke = 0;\n\tint _visibilityThroughFire = 0;\n\n\tint _frontArmor, _sideArmor, _leftArmorDiff, _rearArmor, _underArmor;\n\tUnitStats _stats;\n\tint _listOrder;\n\tRuleStatBonus _timeRecovery, _energyRecovery, _moraleRecovery, _healthRecovery, _stunRecovery, _manaRecovery;\n\tScriptValues<RuleSoldierBonus> _scriptValues;\n\tModScript::SoldierBonusScripts::Container _soldierBonusScripts;\n\npublic:\n\t/// Creates a blank RuleSoldierBonus.\n\tRuleSoldierBonus(const std::string &name, int listOrder);\n\t/// Cleans up the soldier bonus ruleset.\n\t~RuleSoldierBonus() = default;\n\t/// Loads the soldier bonus definition from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader, Mod* mod, const ModScript &parsers);\n\t/// Gets the soldier bonus unique name/type.\n\tconst std::string &getName() const { return _name; }\n\n\t/// Gets the bonus to night vision (in tiles).\n\tint getVisibilityAtDark() const { return _visibilityAtDark; }\n\t/// Gets the bonus to day vision (in tiles).\n\tint getVisibilityAtDay() const { return _visibilityAtDay; }\n\t/// Gets the bonus to psi vision (in tiles).\n\tint getPsiVision() const { return _psiVision; }\n\t/// Gets the bonus to heat vision.\n\tint getVisibilityThroughSmoke() const { return _visibilityThroughSmoke; }\n\t/// Gets the bonus to visibility through fire.\n\tint getVisibilityThroughFire() const { return _visibilityThroughFire; }\n\n\t/// Gets the bonus to front armor.\n\tint getFrontArmor() const { return _frontArmor; }\n\t/// Gets the bonus to left side armor.\n\tint getLeftSideArmor() const { return _sideArmor + _leftArmorDiff; }\n\t/// Gets the bonus to right side armor.\n\tint getRightSideArmor() const { return _sideArmor; }\n\t/// Gets the bonus to rear armor.\n\tint getRearArmor() const { return _rearArmor; }\n\t/// Gets the bonus to under armor.\n\tint getUnderArmor() const { return _underArmor; }\n\t/// Gets the bonus stats.\n\tconst UnitStats *getStats() const { return &_stats; }\n\t/// Gets the list order for display purposes.\n\tint getListOrder() const { return _listOrder; }\n\n\t/// Gets the bonus TU recovery.\n\tint getTimeRecovery(const BattleUnit *unit) const;\n\tconst RuleStatBonus *getTimeRecoveryRaw() const { return &_timeRecovery; }\n\t/// Gets the bonus Energy recovery.\n\tint getEnergyRecovery(const BattleUnit *unit) const;\n\tconst RuleStatBonus *getEnergyRecoveryRaw() const { return &_energyRecovery; }\n\t/// Gets the bonus Morale recovery.\n\tint getMoraleRecovery(const BattleUnit *unit) const;\n\tconst RuleStatBonus *getMoraleRecoveryRaw() const { return &_moraleRecovery; }\n\t/// Gets the bonus Health recovery.\n\tint getHealthRecovery(const BattleUnit *unit) const;\n\tconst RuleStatBonus *getHealthRecoveryRaw() const { return &_healthRecovery; }\n\t/// Gets the bonus Mana recovery.\n\tint getManaRecovery(const BattleUnit *unit) const;\n\tconst RuleStatBonus *getManaRecoveryRaw() const { return &_manaRecovery; }\n\t/// Gets the bonus Stun recovery.\n\tint getStunRegeneration(const BattleUnit *unit) const;\n\tconst RuleStatBonus *getStunRegenerationRaw() const { return &_stunRecovery; }\n\t/// Gets script.\n\ttemplate<typename Script>\n\tconst typename Script::Container &getScript() const { return _soldierBonusScripts.get<Script>(); }\n\t/// Get all script values.\n\tconst ScriptValues<RuleSoldierBonus> &getScriptValuesRaw() const { return _scriptValues; }\n};\n\n}\n"
  },
  {
    "path": "src/Mod/RuleSoldierTransformation.cpp",
    "content": "/*\n * Copyright 2010-2018 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"RuleSoldierTransformation.h\"\n#include \"Mod.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Constructor for a soldier transformation project (necromancy, cloning, ascending!)\n * @param name The unique project name id\n */\nRuleSoldierTransformation::RuleSoldierTransformation(const std::string &name, int listOrder) :\n\t_name(name),\n\t_keepSoldierArmor(false), _createsClone(false), _needsCorpseRecovered(true),\n\t_allowsDeadSoldiers(false), _allowsLiveSoldiers(false), _allowsWoundedSoldiers(false),\n\t_listOrder(listOrder), _cost(0), _transferTime(0), _recoveryTime(0), _minRank(0), _includeBonusesForMinStats(false), _includeBonusesForMaxStats(false),\n\t_showMinMax(false), _lowerBoundAtMinStats(true), _upperBoundAtMaxStats(false), _upperBoundAtStatCaps(false), _upperBoundType(0),\n\t_reset(false), _resetRank(false)\n{\n\t_requiredMaxStats = UnitStats::scalar(9999); // set all default max stats to 9999\n}\n\n/**\n * Loads the transformation project from a YAML file.\n * @param node YAML node.\n * @param listOrder The list weight for this transformation project.\n */\nvoid RuleSoldierTransformation::load(const YAML::YamlNodeReader& node, Mod* mod)\n{\n\tconst auto& reader = node.useIndex();\n\tif (const auto& parent = reader[\"refNode\"])\n\t{\n\t\tload(parent, mod);\n\t}\n\n\treader.tryRead(\"listOrder\", _listOrder);\n\n\tmod->loadUnorderedNames(_name, _requires, reader[\"requires\"]);\n\tmod->loadBaseFunction(_name, _requiresBaseFunc, reader[\"requiresBaseFunc\"]);\n\treader.tryRead(\"producedItem\", _producedItem);\n\treader.tryRead(\"producedSoldierType\", _producedSoldierType);\n\treader.tryRead(\"producedSoldierArmor\", _producedSoldierArmor);\n\treader.tryRead(\"keepSoldierArmor\", _keepSoldierArmor);\n\treader.tryRead(\"createsClone\", _createsClone);\n\treader.tryRead(\"needsCorpseRecovered\", _needsCorpseRecovered);\n\treader.tryRead(\"allowsDeadSoldiers\", _allowsDeadSoldiers);\n\treader.tryRead(\"allowsLiveSoldiers\", _allowsLiveSoldiers);\n\treader.tryRead(\"allowsWoundedSoldiers\", _allowsWoundedSoldiers);\n\tmod->loadUnorderedNames(_name, _allowedSoldierTypes, reader[\"allowedSoldierTypes\"]);\n\tmod->loadUnorderedNames(_name, _requiredPreviousTransformations, reader[\"requiredPreviousTransformations\"]);\n\tmod->loadUnorderedNames(_name, _forbiddenPreviousTransformations, reader[\"forbiddenPreviousTransformations\"]);\n\treader.tryRead(\"includeBonusesForMinStats\", _includeBonusesForMinStats);\n\treader.tryRead(\"includeBonusesForMaxStats\", _includeBonusesForMaxStats);\n\treader.tryRead(\"requiredMinStats\", _requiredMinStats);\n\tif (reader[\"requiredMaxStats\"])\n\t{\n\t\tUnitStats tmp = reader[\"requiredMaxStats\"].readVal(_requiredMaxStats);\n\t\t_requiredMaxStats.merge(tmp);\n\t}\n\tmod->loadUnorderedNamesToInt(_name, _requiredItems, reader[\"requiredItems\"]);\n\tmod->loadUnorderedNamesToInt(_name, _requiredCommendations, reader[\"requiredCommendations\"]);\n\treader.tryRead(\"cost\", _cost);\n\treader.tryRead(\"transferTime\", _transferTime);\n\treader.tryRead(\"recoveryTime\", _recoveryTime);\n\treader.tryRead(\"minRank\", _minRank);\n\treader.tryRead(\"flatOverallStatChange\", _flatOverallStatChange);\n\treader.tryRead(\"percentOverallStatChange\", _percentOverallStatChange);\n\treader.tryRead(\"percentGainedStatChange\", _percentGainedStatChange);\n\treader.tryRead(\"flatMin\", _flatMin);\n\treader.tryRead(\"flatMax\", _flatMax);\n\treader.tryRead(\"percentMin\", _percentMin);\n\treader.tryRead(\"percentMax\", _percentMax);\n\treader.tryRead(\"percentGainedMin\", _percentGainedMin);\n\treader.tryRead(\"percentGainedMax\", _percentGainedMax);\n\treader.tryRead(\"showMinMax\", _showMinMax);\n\treader.tryRead(\"rerollStats\", _rerollStats);\n\treader.tryRead(\"lowerBoundAtMinStats\", _lowerBoundAtMinStats);\n\treader.tryRead(\"upperBoundAtMaxStats\", _upperBoundAtMaxStats);\n\treader.tryRead(\"upperBoundAtStatCaps\", _upperBoundAtStatCaps);\n\treader.tryRead(\"upperBoundType\", _upperBoundType);\n\n\tmod->loadUnorderedNames(_name, _removeTransformations, reader[\"removeTransformations\"]);\n\treader.tryRead(\"reset\", _reset);\n\treader.tryRead(\"resetRank\", _resetRank);\n\treader.tryRead(\"soldierBonusType\", _soldierBonusType);\n\n\tif (reader[\"events\"])\n\t{\n\t\t_events.load(reader[\"events\"]);\n\t}\n}\n\n/**\n * Gets the unique name id of the project\n * @return The name of the project\n */\nconst std::string &RuleSoldierTransformation::getName() const\n{\n\treturn _name;\n}\n\n/**\n * Gets the list weight of the project\n * @return The list order\n */\nint RuleSoldierTransformation::getListOrder() const\n{\n\treturn _listOrder;\n}\n\n/**\n * Gets the list of research this project requires\n * @return The list of required research\n */\nconst std::vector<std::string > &RuleSoldierTransformation::getRequiredResearch() const\n{\n\treturn _requires;\n}\n\n/**\n * Gets the type of soldier produced by this project\n * @return The soldier type\n */\nconst std::string &RuleSoldierTransformation::getProducedSoldierType() const\n{\n\treturn _producedSoldierType;\n}\n\n/**\n * Gets the armor that the produced soldier should be wearing\n * @return The armor type\n */\nconst std::string &RuleSoldierTransformation::getProducedSoldierArmor() const\n{\n\treturn _producedSoldierArmor;\n}\n\n/**\n * Gets whether or not the project should have the soldier keep their current armor\n * @return Keep the current armor?\n */\nbool RuleSoldierTransformation::isKeepingSoldierArmor() const\n{\n\treturn _keepSoldierArmor;\n}\n\n/**\n * Gets whether or not the project should produce a clone (new id) of the input soldier\n * @return Create a clone?\n */\nbool RuleSoldierTransformation::isCreatingClone() const\n{\n\treturn _createsClone;\n}\n\n/**\n * Gets whether or not the project needs the body of the soldier to have been recovered\n * @return Needs the body?\n */\nbool RuleSoldierTransformation::needsCorpseRecovered() const\n{\n\treturn _needsCorpseRecovered;\n}\n\n/**\n * Gets whether or not the project allows input of dead soldiers\n * @return Allow dead soldiers?\n */\nbool RuleSoldierTransformation::isAllowingDeadSoldiers() const\n{\n\treturn _allowsDeadSoldiers;\n}\n\n/**\n * Gets whether or not the project allows input of alive soldiers\n * @return Allow live soldiers?\n */\nbool RuleSoldierTransformation::isAllowingAliveSoldiers() const\n{\n\treturn _allowsLiveSoldiers;\n}\n\n/**\n * Gets whether or not the project allows input of wounded soldiers\n * @return Allow wounded soldiers?\n */\nbool RuleSoldierTransformation::isAllowingWoundedSoldiers() const\n{\n\treturn _allowsWoundedSoldiers;\n}\n\n/**\n * Gets the list of soldier types eligible for this project\n * @return The list of allowed soldier types\n */\nconst std::vector<std::string > &RuleSoldierTransformation::getAllowedSoldierTypes() const\n{\n\treturn _allowedSoldierTypes;\n}\n\n/**\n * Gets the list of previous soldier transformations a soldier needs for this project\n * @return The list of required previous transformations.\n */\nconst std::vector<std::string > &RuleSoldierTransformation::getRequiredPreviousTransformations() const\n{\n\treturn _requiredPreviousTransformations;\n}\n\n/**\n * Gets the list of previous soldier transformations that make a soldier ineligible for this project\n * @return The list of forbidden previous\n */\nconst std::vector<std::string > &RuleSoldierTransformation::getForbiddenPreviousTransformations() const\n{\n\treturn _forbiddenPreviousTransformations;\n}\n\n/**\n * Gets the minimum stats a soldier needs to be eligible for this project\n * @return The stat requirements\n */\nconst UnitStats &RuleSoldierTransformation::getRequiredMinStats() const\n{\n\treturn _requiredMinStats;\n}\n\n/**\n * Gets the maximum stats a soldier can have to be eligible for this project\n * @return The stat requirements\n */\nconst UnitStats &RuleSoldierTransformation::getRequiredMaxStats() const\n{\n\treturn _requiredMaxStats;\n}\n\n/**\n * Gets the list of items necessary to complete this project\n * @return The list of required items\n */\nconst std::map<std::string, int> &RuleSoldierTransformation::getRequiredItems() const\n{\n\treturn _requiredItems;\n}\n\n/**\n * Gets the list of commendations necessary to complete this project\n * @return The list of required commendations\n */\nconst std::map<std::string, int> &RuleSoldierTransformation::getRequiredCommendations() const\n{\n\treturn _requiredCommendations;\n}\n\n/**\n * Gets the cash cost of the project\n * @return The cost\n */\nint RuleSoldierTransformation::getCost() const\n{\n\treturn _cost;\n}\n\n/**\n * Gets how long the transformed soldier should be in transit to the base after completion\n * @return The transfer time in hours\n */\nint RuleSoldierTransformation::getTransferTime() const\n{\n\treturn _transferTime;\n}\n\n/**\n * Gets how long the transformed soldier should take to recover after completion\n * @return The recovery time in days\n */\nint RuleSoldierTransformation::getRecoveryTime() const\n{\n\treturn _recoveryTime;\n}\n\n/**\n * Gets the minimum rank a soldier needs to be eligible for this project\n * @return The rank requirement\n */\nint RuleSoldierTransformation::getMinRank() const\n{\n\treturn _minRank;\n}\n\n/**\n * Gets the flat change to a soldier's overall stats when undergoing this project\n * @return The flat overall stat changes\n */\nconst UnitStats &RuleSoldierTransformation::getFlatOverallStatChange() const\n{\n\treturn _flatOverallStatChange;\n}\n\n/**\n * Gets the percent change to a soldier's overall stats when undergoing this project\n * @return The percent overall stat changes\n */\nconst UnitStats &RuleSoldierTransformation::getPercentOverallStatChange() const\n{\n\treturn _percentOverallStatChange;\n}\n\n/**\n * Gets the percent change to a soldier's gained stats when undergoing this project\n * @return The percent gained stat changes\n */\nconst UnitStats &RuleSoldierTransformation::getPercentGainedStatChange() const\n{\n\treturn _percentGainedStatChange;\n}\n\n/**\n * Gets whether or not this project should bound stat penalties at the produced RuleSoldier's minStats\n * @return Lower bound at minStats?\n */\nbool RuleSoldierTransformation::hasLowerBoundAtMinStats() const\n{\n\treturn _lowerBoundAtMinStats;\n}\n\n/**\n * Gets whether or not this project should cap stats at the produced RuleSoldier's maxStats\n * @return Upper bound at maxStats?\n */\nbool RuleSoldierTransformation::hasUpperBoundAtMaxStats() const\n{\n\treturn _upperBoundAtMaxStats;\n}\n\n/**\n * Gets whether or not this project should cap stats at the produced RuleSoldier's statCaps\n * @return Upper bound at statCaps?\n */\nbool RuleSoldierTransformation::hasUpperBoundAtStatCaps() const\n{\n\treturn _upperBoundAtStatCaps;\n}\n\n/**\n * Gets whether to use soft upper bound limit or not.\n * @return Soft upper bound or hard upper bound?\n */\nbool RuleSoldierTransformation::isSoftLimit(bool isSameSoldierType) const\n{\n\tif (_upperBoundType == 0)\n\t{\n\t\treturn isSameSoldierType; // 0 = dynamic\n\t}\n\telse if (_upperBoundType == 1)\n\t{\n\t\treturn true; // 1 = soft limit\n\t}\n\treturn false; // 2+ = hard limit\n}\n\n/**\n * Gets whether or not this project should reset info about all previous transformations and all previously assigned soldier bonuses\n * @return Reset previous transformation info and soldier bonuses?\n */\nbool RuleSoldierTransformation::getReset() const\n{\n\treturn _reset;\n}\n\n/**\n * Gets whether or not this project should reset the rank of the destination soldier to rookie\n * @return Reset the rank to rookie?\n */\nbool RuleSoldierTransformation::getResetRank() const\n{\n\treturn _resetRank;\n}\n\n/**\n * Gets the type of soldier bonus assigned by this project\n * @return The soldier bonus type\n */\nconst std::string &RuleSoldierTransformation::getSoldierBonusType() const\n{\n\treturn _soldierBonusType;\n}\n\n}\n"
  },
  {
    "path": "src/Mod/RuleSoldierTransformation.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2018 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include <map>\n#include \"../Engine/Yaml.h\"\n#include \"Unit.h\"\n#include \"RuleBaseFacilityFunctions.h\"\n#include \"../Savegame/WeightedOptions.h\"\n\nnamespace OpenXcom\n{\n\nclass Mod;\n\n/**\n * Ruleset data structure for the information to transform a soldier.\n */\nclass RuleSoldierTransformation\n{\nprivate:\n\tstd::string _name;\n\tstd::vector<std::string > _requires, _requiredPreviousTransformations, _forbiddenPreviousTransformations;\n\tRuleBaseFacilityFunctions _requiresBaseFunc;\n\tstd::string _producedItem;\n\tstd::string _producedSoldierType, _producedSoldierArmor;\n\tbool _keepSoldierArmor, _createsClone, _needsCorpseRecovered, _allowsDeadSoldiers, _allowsLiveSoldiers, _allowsWoundedSoldiers;\n\tstd::vector<std::string > _allowedSoldierTypes;\n\tstd::map<std::string, int> _requiredItems;\n\tstd::map<std::string, int> _requiredCommendations;\n\tint _listOrder, _cost, _transferTime, _recoveryTime;\n\tint _minRank;\n\tbool _includeBonusesForMinStats, _includeBonusesForMaxStats;\n\tUnitStats _requiredMinStats, _requiredMaxStats, _flatOverallStatChange, _percentOverallStatChange, _percentGainedStatChange;\n\tUnitStats _flatMin, _flatMax, _percentMin, _percentMax, _percentGainedMin, _percentGainedMax;\n\tbool _showMinMax;\n\tUnitStats _rerollStats;\n\tbool _lowerBoundAtMinStats, _upperBoundAtMaxStats, _upperBoundAtStatCaps;\n\tint _upperBoundType;\n\tstd::vector<std::string> _removeTransformations;\n\tbool _reset;\n\tbool _resetRank;\n\tstd::string _soldierBonusType;\n\tWeightedOptions _events;\n\npublic:\n\t/// Default constructor\n\tRuleSoldierTransformation(const std::string &name, int listOrder);\n\t/// Loads the project data from YAML\n\tvoid load(const YAML::YamlNodeReader& reader, Mod* mod);\n\t/// Gets the unique name id of the project\n\tconst std::string &getName() const;\n\t/// Gets the list weight of the project\n\tint getListOrder() const;\n\t/// Gets the list of research this project requires\n\tconst std::vector<std::string > &getRequiredResearch() const;\n\t/// Gets the list of required base functions for this project\n\tRuleBaseFacilityFunctions getRequiredBaseFuncs() const { return _requiresBaseFunc; }\n\t/// Gets the type of item produced by this project (the soldier stops existing completely and is fully replaced by the item)\n\tconst std::string &getProducedItem() const { return _producedItem; }\n\t/// Gets the type of soldier produced by this project\n\tconst std::string &getProducedSoldierType() const;\n\t/// Gets the armor that the produced soldier should be wearing\n\tconst std::string &getProducedSoldierArmor() const;\n\t/// Gets whether or not the soldier should keep their armor after the project\n\tbool isKeepingSoldierArmor() const;\n\t/// Gets whether or not the project should produce a clone (new id) of the input soldier\n\tbool isCreatingClone() const;\n\t/// Gets whether or not the project needs the body of the soldier to have been recovered\n\tbool needsCorpseRecovered() const;\n\t/// Gets whether or not the project allows input of dead soldiers\n\tbool isAllowingDeadSoldiers() const;\n\t/// Gets whether or not the project allows input of alive soldiers\n\tbool isAllowingAliveSoldiers() const;\n\t/// Gets whether or not the project allows input of wounded soldiers\n\tbool isAllowingWoundedSoldiers() const;\n\t/// Gets the list of soldier types eligible for this project\n\tconst std::vector<std::string > &getAllowedSoldierTypes() const;\n\t/// Gets the list of previous soldier transformations a soldier needs for this project\n\tconst std::vector<std::string > &getRequiredPreviousTransformations() const;\n\t/// Gets the list of previous soldier transformations that make a soldier ineligible for this project\n\tconst std::vector<std::string > &getForbiddenPreviousTransformations() const;\n\t/// Gets whether or not to include soldier bonuses when checking required min stats.\n\tbool getIncludeBonusesForMinStats() const { return _includeBonusesForMinStats; }\n\t/// Gets whether or not to include soldier bonuses when checking required max stats.\n\tbool getIncludeBonusesForMaxStats() const { return _includeBonusesForMaxStats; }\n\t/// Gets the minimum stats a soldier needs to be eligible for this project\n\tconst UnitStats &getRequiredMinStats() const;\n\t/// Gets the maximum stats a soldier can have to be eligible for this project\n\tconst UnitStats &getRequiredMaxStats() const;\n\t/// Gets the list of items necessary to complete this project\n\tconst std::map<std::string, int> &getRequiredItems() const;\n\t/// Gets the list of commendations necessary to complete this project\n\tconst std::map<std::string, int> &getRequiredCommendations() const;\n\t/// Gets the cash cost of the project\n\tint getCost() const;\n\t/// Gets how long the transformed soldier should be in transit to the base after completion\n\tint getTransferTime() const;\n\t/// Gets how long the transformed soldier should take to recover after completion\n\tint getRecoveryTime() const;\n\t/// Gets the minimum rank a soldier needs to be eligible for this project\n\tint getMinRank() const;\n\t/// Gets the flat change to a soldier's overall stats when undergoing this project\n\tconst UnitStats &getFlatOverallStatChange() const;\n\t/// Gets the percent change to a soldier's overall stats when undergoing this project\n\tconst UnitStats &getPercentOverallStatChange() const;\n\t/// Gets the percent change to a soldier's gained stats when undergoing this project\n\tconst UnitStats &getPercentGainedStatChange() const;\n\n\t/// Gets the min flat change to a soldier's overall stats when undergoing this project\n\tconst UnitStats &getFlatMin() const { return _flatMin; }\n\t/// Gets the max flat change to a soldier's overall stats when undergoing this project\n\tconst UnitStats &getFlatMax() const { return _flatMax; }\n\t/// Gets the min percent change to a soldier's overall stats when undergoing this project\n\tconst UnitStats &getPercentMin() const { return _percentMin; }\n\t/// Gets the max percent change to a soldier's overall stats when undergoing this project\n\tconst UnitStats &getPercentMax() const { return _percentMax; }\n\t/// Gets the min percent change to a soldier's gained stats when undergoing this project\n\tconst UnitStats &getPercentGainedMin() const { return _percentGainedMin; }\n\t/// Gets the max percent change to a soldier's gained stats when undergoing this project\n\tconst UnitStats &getPercentGainedMax() const { return _percentGainedMax; }\n\t/// Gets whether to display min/max changes in two lines; or just one line with randomized changes replaced with a question mark\n\tbool getShowMinMax() const { return _showMinMax; }\n\n\t/// Gets information about which soldier stats should be re-rolled when undergoing this project\n\tconst UnitStats &getRerollStats() const { return _rerollStats; }\n\n\t/// Gets whether or not this project should bound stat penalties at the produced RuleSoldier's minStats\n\tbool hasLowerBoundAtMinStats() const;\n\t/// Gets whether or not this project should cap stats at the produced RuleSoldier's maxStats\n\tbool hasUpperBoundAtMaxStats() const;\n\t/// Gets whether or not this project should cap stats at the produced RuleSoldier's statCaps\n\tbool hasUpperBoundAtStatCaps() const;\n\t/// Gets whether to use soft upper bound limit or not.\n\tbool isSoftLimit(bool isSameSoldierType) const;\n\n\t/// Gets the list of (potential) previous soldier transformations to remove when undergoing this project\n\tconst std::vector<std::string>& getRemoveTransformations() const { return _removeTransformations; }\n\t/// Gets whether or not this project should reset info about all previous transformations and all previously assigned soldier bonuses\n\tbool getReset() const;\n\t/// Gets whether or not this project should reset the rank of the destination soldier to rookie\n\tbool getResetRank() const;\n\t/// Gets the type of soldier bonus assigned by this project\n\tconst std::string &getSoldierBonusType() const;\n\n\t/// Gets geoscape event rule name to spawn after soldier transformation\n\tstd::string chooseEvent() const { return _events.choose(); }\n};\n\n}\n"
  },
  {
    "path": "src/Mod/RuleStartingCondition.cpp",
    "content": "/*\n * Copyright 2010-2019 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"RuleStartingCondition.h\"\n#include \"RuleItem.h\"\n#include \"../Engine/Logger.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Savegame/Craft.h\"\n#include \"../Savegame/ItemContainer.h\"\n#include \"../Savegame/WeightedOptions.h\"\n#include <algorithm>\n\nnamespace OpenXcom\n{\n\n/**\n * Creates a blank ruleset for a certain type of Starting Condition.\n * @param type String defining the type.\n */\nRuleStartingCondition::RuleStartingCondition(const std::string& type) : _type(type), _destroyRequiredItems(false), _requireCommanderOnboard(false)\n{\n}\n\n/**\n *\n */\nRuleStartingCondition::~RuleStartingCondition()\n{\n}\n\n/**\n * Loads the Starting Conditions from a YAML file.\n * @param node YAML node.\n */\nvoid RuleStartingCondition::load(const YAML::YamlNodeReader& node, Mod *mod)\n{\n\tconst auto& reader = node.useIndex();\n\tif (const auto& parent = reader[\"refNode\"])\n\t{\n\t\tload(parent, mod);\n\t}\n\n\tmod->loadUnorderedNamesToNamesToInt(_type, _defaultArmor, reader[\"defaultArmor\"]);\n\tmod->loadUnorderedNames(_type, _allowedArmors, reader[\"allowedArmors\"]);\n\tmod->loadUnorderedNames(_type, _forbiddenArmors, reader[\"forbiddenArmors\"]);\n\tmod->loadUnorderedNames(_type, _forbiddenArmorsInNextStageName, reader[\"forbiddenArmorsInNextStage\"]);\n\tmod->loadUnorderedNames(_type, _allowedVehicles, reader[\"allowedVehicles\"]);\n\tmod->loadUnorderedNames(_type, _forbiddenVehicles, reader[\"forbiddenVehicles\"]);\n\tmod->loadUnorderedNames(_type, _allowedItems, reader[\"allowedItems\"]);\n\tmod->loadUnorderedNames(_type, _forbiddenItems, reader[\"forbiddenItems\"]);\n\tmod->loadUnorderedNames(_type, _allowedItemCategories, reader[\"allowedItemCategories\"]);\n\tmod->loadUnorderedNames(_type, _forbiddenItemCategories, reader[\"forbiddenItemCategories\"]);\n\tmod->loadUnorderedNames(_type, _allowedCraft, reader[\"allowedCraft\"]);\n\tmod->loadUnorderedNames(_type, _forbiddenCraft, reader[\"forbiddenCraft\"]);\n\tmod->loadUnorderedNames(_type, _allowedSoldierTypes, reader[\"allowedSoldierTypes\"]);\n\tmod->loadUnorderedNames(_type, _forbiddenSoldierTypes, reader[\"forbiddenSoldierTypes\"]);\n\tmod->loadUnorderedNamesToInt(_type, _requiredItems, reader[\"requiredItems\"]);\n\tmod->loadUnorderedNamesToNames(_type, _craftTransformationsName, reader[\"craftTransformations\"]);\n\treader.tryRead(\"destroyRequiredItems\", _destroyRequiredItems);\n\treader.tryRead(\"requireCommanderOnboard\", _requireCommanderOnboard);\n\n\tif (reader[\"environmentalConditions\"] || reader[\"paletteTransformations\"] || reader[\"armorTransformations\"]\n\t\t|| reader[\"mapBackgroundColor\"] || reader[\"inventoryShockIndicator\"] || reader[\"mapShockIndicator\"])\n\t{\n\t\tLog(LOG_ERROR) << \"There are invalid/obsolete attributes in starting condition \" << _type << \". Please review the ruleset.\";\n\t}\n}\n\n/**\n * Cross link with other rules.\n */\nvoid RuleStartingCondition::afterLoad(const Mod* mod)\n{\n\tmod->linkRule(_forbiddenArmorsInNextStage, _forbiddenArmorsInNextStageName);\n\n\tfor (auto& pair : _craftTransformationsName)\n\t{\n\t\tauto* src = mod->getCraft(pair.first, true);\n\t\tauto* dest = mod->getCraft(pair.second, true);\n\t\t_craftTransformations[src] = dest;\n\t}\n\n\t//remove not needed data\n\tCollections::removeAll(_craftTransformationsName);\n}\n\n/**\n * Checks if the craft type is permitted.\n * @param craftType Craft type name.\n * @return True if permitted, false otherwise.\n */\nbool RuleStartingCondition::isCraftPermitted(const std::string& craftType) const\n{\n\tif (!_forbiddenCraft.empty())\n\t{\n\t\treturn (std::find(_forbiddenCraft.begin(), _forbiddenCraft.end(), craftType) == _forbiddenCraft.end());\n\t}\n\telse if (!_allowedCraft.empty())\n\t{\n\t\treturn (std::find(_allowedCraft.begin(), _allowedCraft.end(), craftType) != _allowedCraft.end());\n\t}\n\treturn true;\n}\n\n/**\n * Checks if the soldier type is permitted.\n * @param soldierType Soldier type name.\n * @return True if permitted, false otherwise.\n */\nbool RuleStartingCondition::isSoldierTypePermitted(const std::string& soldierType) const\n{\n\tif (!_forbiddenSoldierTypes.empty())\n\t{\n\t\treturn (std::find(_forbiddenSoldierTypes.begin(), _forbiddenSoldierTypes.end(), soldierType) == _forbiddenSoldierTypes.end());\n\t}\n\telse if (!_allowedSoldierTypes.empty())\n\t{\n\t\treturn (std::find(_allowedSoldierTypes.begin(), _allowedSoldierTypes.end(), soldierType) != _allowedSoldierTypes.end());\n\t}\n\treturn true;\n}\n\n/**\n * Gets the replacement armor.\n * @param soldierType Soldier type name.\n * @param armorType Existing/old armor type name.\n * @return Replacement armor type name (or empty string if no replacement is needed).\n */\nstd::string RuleStartingCondition::getArmorReplacement(const std::string& soldierType, const std::string& armorType) const\n{\n\tbool allowed = true;\n\tif (!_forbiddenArmors.empty())\n\t{\n\t\tallowed = (std::find(_forbiddenArmors.begin(), _forbiddenArmors.end(), armorType) == _forbiddenArmors.end());\n\t}\n\telse if (!_allowedArmors.empty())\n\t{\n\t\tallowed = (std::find(_allowedArmors.begin(), _allowedArmors.end(), armorType) != _allowedArmors.end());\n\t}\n\n\tif (!allowed)\n\t{\n\t\tauto j = _defaultArmor.find(soldierType);\n\t\tif (j != _defaultArmor.end())\n\t\t{\n\t\t\tWeightedOptions w = WeightedOptions();\n\t\t\tfor (auto& k : (j->second))\n\t\t\t{\n\t\t\t\tw.set(k.first, k.second);\n\t\t\t}\n\t\t\tstd::string pick = w.choose();\n\t\t\treturn pick == \"noChange\" ? \"\" : pick;\n\t\t}\n\t}\n\n\treturn \"\";\n}\n\n/**\n * Gets the replacement craft.\n * @param sourceCraft Existing/old craft type.\n * @param mapScriptCraft Fallback craft type defined by map script (can be null).\n * @return Replacement craft type (or nullptr if no replacement is needed).\n */\nconst RuleCraft* RuleStartingCondition::getCraftReplacement(const RuleCraft* sourceCraft, const RuleCraft* mapScriptCraft) const\n{\n\tif (!_craftTransformations.empty())\n\t{\n\t\tauto i = _craftTransformations.find(sourceCraft);\n\t\tif (i != _craftTransformations.end())\n\t\t{\n\t\t\treturn i->second;\n\t\t}\n\t}\n\n\treturn mapScriptCraft;\n}\n\n/**\n * Checks if the vehicle type is permitted.\n * @param vehicleType Vehicle type name.\n * @return True if permitted, false otherwise.\n */\nbool RuleStartingCondition::isVehiclePermitted(const std::string& vehicleType) const\n{\n\tif (!_forbiddenVehicles.empty())\n\t{\n\t\treturn (std::find(_forbiddenVehicles.begin(), _forbiddenVehicles.end(), vehicleType) == _forbiddenVehicles.end());\n\t}\n\telse if (!_allowedVehicles.empty())\n\t{\n\t\treturn (std::find(_allowedVehicles.begin(), _allowedVehicles.end(), vehicleType) != _allowedVehicles.end());\n\t}\n\treturn true;\n}\n\n/**\n * Checks if the item type is permitted.\n * @param itemType Item type name.\n * @return True if permitted, false otherwise.\n */\nbool RuleStartingCondition::isItemPermitted(const std::string& itemType, Mod* mod, Craft* craft) const\n{\n\tbool itemCheckSubResult = true; // if both item lists are empty, item is OK\n\n\tif (!_forbiddenItems.empty())\n\t{\n\t\tif (std::find(_forbiddenItems.begin(), _forbiddenItems.end(), itemType) != _forbiddenItems.end())\n\t\t{\n\t\t\treturn false; // item explicitly forbidden\n\t\t}\n\t\telse\n\t\t{\n\t\t\titemCheckSubResult = true; // item is OK, unless category rules below say otherwise\n\t\t}\n\t}\n\telse if (!_allowedItems.empty())\n\t{\n\t\tif (std::find(_allowedItems.begin(), _allowedItems.end(), itemType) != _allowedItems.end())\n\t\t{\n\t\t\treturn true; // item explicitly allowed\n\t\t}\n\t\telse\n\t\t{\n\t\t\titemCheckSubResult = false; // item is NOT OK, unless category rules below say otherwise\n\t\t}\n\t}\n\n\tbool checkForbiddenCategories = !_forbiddenItemCategories.empty();\n\tbool checkAllowedCategories = !checkForbiddenCategories && !_allowedItemCategories.empty();\n\n\tbool categoryCheckSubResult = true;\n\n\tif (checkForbiddenCategories)\n\t\tcategoryCheckSubResult = true;\n\telse if (checkAllowedCategories)\n\t\tcategoryCheckSubResult = false;\n\n\tif (checkForbiddenCategories || checkAllowedCategories)\n\t{\n\t\tRuleItem* item = mod->getItem(itemType);\n\t\tif (item)\n\t\t{\n\t\t\t// primary categories\n\t\t\tstd::vector<std::string> itemCategories = item->getCategories();\n\n\t\t\t// secondary categories (\"inherited\" from equipped ammo)\n\t\t\tif (mod->getShareAmmoCategories() && item->getBattleType() == BT_FIREARM)\n\t\t\t{\n\t\t\t\tfor (auto* ammoRule : *item->getPrimaryCompatibleAmmo())\n\t\t\t\t{\n\t\t\t\t\tif (craft->getItems()->getItem(ammoRule) > 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tfor (auto& cat : ammoRule->getCategories())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\titemCategories.push_back(cat);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!itemCategories.empty())\n\t\t\t{\n\t\t\t\t// check all categories of the item\n\t\t\t\tfor (const auto& catName : itemCategories)\n\t\t\t\t{\n\t\t\t\t\tif (checkForbiddenCategories)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (std::find(_forbiddenItemCategories.begin(), _forbiddenItemCategories.end(), catName) != _forbiddenItemCategories.end())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn false; // found a category that is forbidden\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse if (checkAllowedCategories)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (std::find(_allowedItemCategories.begin(), _allowedItemCategories.end(), catName) != _allowedItemCategories.end())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn true; // found a category that is allowed\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn itemCheckSubResult && categoryCheckSubResult;\n}\n\n}\n"
  },
  {
    "path": "src/Mod/RuleStartingCondition.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2019 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <map>\n#include <vector>\n#include <string>\n#include \"../Engine/Yaml.h\"\n\nnamespace OpenXcom\n{\nclass Mod;\nclass Armor;\nclass Craft;\nclass RuleCraft;\n\n/**\n * Represents a specific Starting Condition.\n */\nclass RuleStartingCondition\n{\nprivate:\n\tstd::string _type;\n\tstd::map<std::string, std::map<std::string, int> > _defaultArmor;\n\tstd::vector<std::string> _allowedArmors, _forbiddenArmors;\n\tstd::vector<std::string> _forbiddenArmorsInNextStageName;\n\tstd::vector<const Armor*> _forbiddenArmorsInNextStage;\n\tstd::vector<std::string> _allowedVehicles, _forbiddenVehicles;\n\tstd::vector<std::string> _allowedItems, _forbiddenItems;\n\tstd::vector<std::string> _allowedItemCategories, _forbiddenItemCategories;\n\tstd::vector<std::string> _allowedCraft, _forbiddenCraft;\n\tstd::vector<std::string> _allowedSoldierTypes, _forbiddenSoldierTypes;\n\tstd::map<std::string, int> _requiredItems;\n\tstd::map<std::string, std::string> _craftTransformationsName;\n\tstd::map<const RuleCraft*, const RuleCraft*> _craftTransformations;\n\tbool _destroyRequiredItems;\n\tbool _requireCommanderOnboard;\npublic:\n\t/// Creates a blank Starting Conditions ruleset.\n\tRuleStartingCondition(const std::string& type);\n\t/// Cleans up the Starting Conditions ruleset.\n\t~RuleStartingCondition();\n\t/// Loads Starting Conditions data from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader, Mod *mod);\n\t/// Cross link with other rules.\n\tvoid afterLoad(const Mod* mod);\n\t/// Gets the Starting Conditions's type.\n\tconst std::string& getType() const { return _type; }\n\t/// Gets the allowed armor types.\n\tconst std::vector<std::string>& getAllowedArmors() const { return _allowedArmors; }\n\t/// Gets the forbidden armor types.\n\tconst std::vector<std::string>& getForbiddenArmors() const { return _forbiddenArmors; }\n\t/// Gets the forbidden armors (in later stages).\n\tconst std::vector<const Armor*>& getForbiddenArmorsInNextStage() const { return _forbiddenArmorsInNextStage; }\n\t/// Gets the allowed craft types.\n\tconst std::vector<std::string>& getAllowedCraft() const { return _allowedCraft; }\n\t/// Gets the forbidden craft types.\n\tconst std::vector<std::string>& getForbiddenCraft() const { return _forbiddenCraft; }\n\t/// Gets the allowed soldier types.\n\tconst std::vector<std::string>& getAllowedSoldierTypes() const { return _allowedSoldierTypes; }\n\t/// Gets the forbidden soldier types.\n\tconst std::vector<std::string>& getForbiddenSoldierTypes() const { return _forbiddenSoldierTypes; }\n\t/// Gets the required items.\n\tconst std::map<std::string, int>& getRequiredItems() const { return _requiredItems; }\n\t/// Should the required items be destroyed when the mission starts?\n\tbool getDestroyRequiredItems() const { return _destroyRequiredItems; }\n\t/// Does the mission require a commander present onboard?\n\tbool requiresCommanderOnboard() const { return _requireCommanderOnboard; }\n\t/// Checks if the craft type is permitted.\n\tbool isCraftPermitted(const std::string& craftType) const;\n\t/// Checks if the soldier type is permitted.\n\tbool isSoldierTypePermitted(const std::string& soldierType) const;\n\t/// Gets the replacement armor.\n\tstd::string getArmorReplacement(const std::string& soldierType, const std::string& armorType) const;\n\t/// Gets the replacement craft.\n\tconst RuleCraft* getCraftReplacement(const RuleCraft* sourceCraft, const RuleCraft* mapScriptCraft) const;\n\t/// Checks if the vehicle type is permitted.\n\tbool isVehiclePermitted(const std::string& vehicleType) const;\n\t/// Checks if the item type is permitted.\n\tbool isItemPermitted(const std::string& itemType, Mod* mod, Craft* craft) const;\n};\n\n}\n"
  },
  {
    "path": "src/Mod/RuleStatBonus.cpp",
    "content": "/*\n * Copyright 2010-2015 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <assert.h>\n#include \"Unit.h\"\n#include \"RuleStatBonus.h\"\n#include \"RuleSkill.h\"\n#include \"../Engine/ScriptBind.h\"\n#include \"../Savegame/BattleUnit.h\"\n#include \"../Savegame/BattleItem.h\"\n#include \"../fmath.h\"\n\nnamespace OpenXcom\n{\n\nnamespace\n{\n\ntypedef float (*BonusStatFunc)(const BattleUnit*);\n\n/**\n * Function returning static value.\n */\ntemplate<int I>\nfloat stat0(const BattleUnit *unit)\n{\n\treturn I;\n}\n/**\n * Getter for one basic stat of unit.\n */\ntemplate<UnitStats::Ptr field, int divisor>\nfloat stat1(const BattleUnit *unit)\n{\n\tconst UnitStats *stat = unit->getBaseStats();\n\treturn (stat->*field) * (1.0f / divisor);\n}\n\n/**\n * Getter for multiply of two basic stat of unit.\n */\ntemplate<UnitStats::Ptr fieldA, UnitStats::Ptr fieldB, int divisor>\nfloat stat2(const BattleUnit *unit)\n{\n\tconst UnitStats *stat = unit->getBaseStats();\n\treturn (stat->*fieldA) * (stat->*fieldB) * (1.0f / divisor);\n}\n\nfloat currentFatalWounds(const BattleUnit *unit)\n{\n\treturn unit->getFatalWounds();\n}\n\nfloat currentRank(const BattleUnit *unit)\n{\n\treturn unit->getRankInt();\n}\n\nfloat currentRankUnified(const BattleUnit *unit)\n{\n\treturn unit->getRankIntUnified();\n}\n\nfloat currentTimeUnits(const BattleUnit *unit)\n{\n\treturn unit->getTimeUnits();\n}\n\nfloat currentHealth(const BattleUnit *unit)\n{\n\treturn unit->getHealth();\n}\n\nfloat currentMana(const BattleUnit* unit)\n{\n\treturn unit->getMana();\n}\n\nfloat currentEnergy(const BattleUnit *unit)\n{\n\treturn unit->getEnergy();\n}\n\nfloat currentMorale(const BattleUnit *unit)\n{\n\treturn unit->getMorale();\n}\n\nfloat currentStun(const BattleUnit *unit)\n{\n\treturn unit->getStunlevel();\n}\n\nfloat normalizedHelper(int val, int max)\n{\n\treturn max > 0 ? 1.0f * val / max : 0.0f;\n}\n\nfloat normalizedTimeUnits(const BattleUnit *unit)\n{\n\treturn normalizedHelper(unit->getTimeUnits(), unit->getBaseStats()->tu);\n}\n\nfloat normalizedHealth(const BattleUnit *unit)\n{\n\treturn normalizedHelper(unit->getHealth(), unit->getBaseStats()->health);\n}\n\nfloat normalizedMana(const BattleUnit* unit)\n{\n\treturn normalizedHelper(unit->getMana(), unit->getBaseStats()->mana);\n}\n\nfloat normalizedEnergy(const BattleUnit *unit)\n{\n\treturn normalizedHelper(unit->getEnergy(), unit->getBaseStats()->stamina);\n}\n\nfloat normalizedMorale(const BattleUnit *unit)\n{\n\treturn normalizedHelper(unit->getMorale(), 100);\n}\n\nfloat normalizedStun(const BattleUnit *unit)\n{\n\treturn normalizedHelper(unit->getStunlevel(), unit->getHealth());\n}\n\nfloat basicEnergyRegeneration(const BattleUnit *unit)\n{\n\tSoldier *solder = unit->getGeoscapeSoldier();\n\tif (solder != 0)\n\t{\n\t\treturn solder->getInitStats()->tu / 3;\n\t}\n\telse\n\t{\n\t\treturn unit->getUnitRules()->getEnergyRecovery();\n\t}\n}\n\nconstexpr size_t statDataFuncSize = 4;\nconstexpr size_t statMultiper = 1000;\nconstexpr const char* statNamePostfix = \"BonusStats\";\n\ntemplate<BonusStatFunc Func>\nstruct getBonusStatsScript\n{\n\tstatic RetEnum func(const BattleUnit *bu, int &ret, int pow1, int pow2, int pow3, int pow4)\n\t{\n\t\tif (bu)\n\t\t{\n\t\t\tconst float stat = Func(bu);\n\t\t\tfloat bonus = 0;\n\t\t\tbonus += pow4; bonus *= stat;\n\t\t\tbonus += pow3; bonus *= stat;\n\t\t\tbonus += pow2; bonus *= stat;\n\t\t\tbonus += pow1; bonus *= stat;\n\t\t\tret += bonus / statMultiper;\n\t\t}\n\t\treturn RetContinue;\n\t}\n};\n\n/**\n * Data describing same functions but with different exponent.\n */\nusing BonusStatDataFunc = void (*)(Bind<BattleUnit>& b, const std::string& name);\n/**\n * Data describing basic stat getter.\n */\nstruct BonusStatData\n{\n\tstd::string name;\n\tBonusStatDataFunc func;\n};\n\n/**\n * Helper function creating BonusStatData with proper functions.\n */\ntemplate<BonusStatFunc Func>\nBonusStatDataFunc create()\n{\n\treturn [](Bind<BattleUnit>& b, const std::string& name)\n\t{\n\t\tb.addFunc<getBonusStatsScript<Func>>(name + statNamePostfix, \"add stat '\" + name + \"' transformed by polynomial (const arguments are coefficients), final result of polynomial is divided by \" + std::to_string(statMultiper));\n\t};\n}\n\n/**\n * Helper function creating BonusStatData with proper functions.\n */\ntemplate<int Val>\nBonusStatDataFunc create0()\n{\n\treturn create<&stat0<Val> >();\n}\n\n/**\n * Helper function creating BonusStatData with proper functions.\n */\ntemplate<UnitStats::Ptr fieldA, int divisor = 1>\nBonusStatDataFunc create1()\n{\n\treturn create<&stat1<fieldA, divisor> >();\n}\n\n/**\n * Helper function creating BonusStatData with proper functions.\n */\ntemplate<UnitStats::Ptr fieldA, UnitStats::Ptr fieldB, int divisor = 1>\nBonusStatDataFunc create2()\n{\n\treturn create<&stat2<fieldA, fieldB, divisor> >();\n}\n\n/**\n * List of all possible getters of basic stats.\n */\nBonusStatData statDataMap[] =\n{\n\t{ \"flatOne\", create0<1>() },\n\t{ \"flatHundred\", create0<100>() },\n\n\t{ \"strength\", create1<&UnitStats::strength>() },\n\t{ \"psi\", create2<&UnitStats::psiSkill, &UnitStats::psiStrength>() },\n\t{ \"psiSkill\", create1<&UnitStats::psiSkill>() },\n\t{ \"psiStrength\", create1<&UnitStats::psiStrength>() },\n\t{ \"throwing\", create1<&UnitStats::throwing>() },\n\t{ \"bravery\", create1<&UnitStats::bravery>() },\n\t{ \"firing\", create1<&UnitStats::firing>() },\n\t{ \"health\", create1<&UnitStats::health>() },\n\t{ \"mana\", create1<&UnitStats::mana>() },\n\t{ \"tu\", create1<&UnitStats::tu>() },\n\t{ \"reactions\", create1<&UnitStats::reactions>() },\n\t{ \"stamina\", create1<&UnitStats::stamina>() },\n\t{ \"melee\", create1<&UnitStats::melee>() },\n\t{ \"strengthMelee\", create2<&UnitStats::strength, &UnitStats::melee>() },\n\t{ \"strengthThrowing\", create2<&UnitStats::strength, &UnitStats::throwing>() },\n\t{ \"firingReactions\", create2<&UnitStats::firing, &UnitStats::reactions>() },\n\n\t{ \"strengthScaled\", create1<&UnitStats::strength, 100>() },\n\t{ \"psiScaled\", create2<&UnitStats::psiSkill, &UnitStats::psiStrength, 10000>() },\n\t{ \"psiSkillScaled\", create1<&UnitStats::psiSkill, 100>() },\n\t{ \"psiStrengthScaled\", create1<&UnitStats::psiStrength, 100>() },\n\t{ \"throwingScaled\", create1<&UnitStats::throwing, 100>() },\n\t{ \"braveryScaled\", create1<&UnitStats::bravery, 100>() },\n\t{ \"firingScaled\", create1<&UnitStats::firing, 100>() },\n\t{ \"healthScaled\", create1<&UnitStats::health, 100>() },\n\t{ \"manaScaled\", create1<&UnitStats::mana, 100>() },\n\t{ \"tuScaled\", create1<&UnitStats::tu, 100>() },\n\t{ \"reactionsScaled\", create1<&UnitStats::reactions, 100>() },\n\t{ \"staminaScaled\", create1<&UnitStats::stamina, 100>() },\n\t{ \"meleeScaled\", create1<&UnitStats::melee, 100>() },\n\t{ \"strengthMeleeScaled\", create2<&UnitStats::strength, &UnitStats::melee, 10000>() },\n\t{ \"strengthThrowingScaled\", create2<&UnitStats::strength, &UnitStats::throwing, 10000>() },\n\t{ \"firingReactionsScaled\", create2<&UnitStats::firing, &UnitStats::reactions, 10000>() },\n\n\t{ \"rank\", create<&currentRank>() },\n\t{ \"rankUnified\", create<&currentRankUnified>() },\n\t{ \"fatalWounds\", create<&currentFatalWounds>() },\n\n\t{ \"healthCurrent\", create<&currentHealth>() },\n\t{ \"manaCurrent\", create<&currentMana>() },\n\t{ \"tuCurrent\", create<&currentTimeUnits>() },\n\t{ \"energyCurrent\", create<&currentEnergy>() },\n\t{ \"moraleCurrent\", create<&currentMorale>() },\n\t{ \"stunCurrent\", create<&currentStun>() },\n\n\t{ \"healthNormalized\", create<&normalizedHealth>() },\n\t{ \"manaNormalized\", create<&normalizedMana>() },\n\t{ \"tuNormalized\", create<&normalizedTimeUnits>() },\n\t{ \"energyNormalized\", create<&normalizedEnergy>() },\n\t{ \"moraleNormalized\", create<&normalizedMorale>() },\n\t{ \"stunNormalized\", create<&normalizedStun>() },\n\n\t{ \"energyRegen\", create<&basicEnergyRegeneration>() },\n};\n\n} //namespace\n\n/**\n * Default constructor.\n */\nRuleStatBonus::RuleStatBonus()\n{\n\n}\n/**\n * Loads the item from a YAML file.\n * @param node YAML node.\n */\nvoid RuleStatBonus::load(const std::string& parentName, const YAML::YamlNodeReader& reader, const ModScript::BonusStatsCommon& parser)\n{\n\tif (reader)\n\t{\n\t\tif (const auto& stats = reader[ryml::to_csubstr(parser.getPropertyNodeName())])\n\t\t{\n\t\t\t_bonusOrig.clear();\n\t\t\tif (stats.isMap())\n\t\t\t{\n\t\t\t\tconst auto& statsChildren = stats.children();\n\t\t\t\t_bonusOrig.reserve(statsChildren.size());\n\t\t\t\tfor (const auto& child : statsChildren)\n\t\t\t\t\t_bonusOrig.emplace_back().first.assign(child.key());\n\t\t\t\tsize_t bonusIndex = 0;\n\t\t\t\tfor (size_t statIndex = 0; statIndex < std::size(statDataMap) && bonusIndex < _bonusOrig.size(); ++statIndex)\n\t\t\t\t{\n\t\t\t\t\tfor (size_t bonusSearchIndex = bonusIndex; bonusSearchIndex < _bonusOrig.size(); ++bonusSearchIndex)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (statDataMap[statIndex].name != _bonusOrig[bonusSearchIndex].first)\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\tif (bonusSearchIndex != bonusIndex)\n\t\t\t\t\t\t\tstd::swap(_bonusOrig[bonusSearchIndex], _bonusOrig[bonusIndex]);\n\t\t\t\t\t\tconst auto& statReader = stats[ryml::to_csubstr(_bonusOrig[bonusIndex].first)];\n\t\t\t\t\t\tstd::vector<float>& vec = _bonusOrig[bonusIndex].second;\n\t\t\t\t\t\tif (statReader.hasVal())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfloat val = statReader.readVal<float>();\n\t\t\t\t\t\t\tvec.push_back(val);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfor (size_t j = 0; j < statDataFuncSize; ++j)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (j < statReader.childrenCount())\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tfloat val = statReader[j].readVal<float>();\n\t\t\t\t\t\t\t\t\tvec.push_back(val);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbonusIndex++;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (bonusIndex != _bonusOrig.size()) // one more stats were not processed\n\t\t\t\t{\n\t\t\t\t\tfor (size_t errorIndex = bonusIndex; errorIndex < _bonusOrig.size(); ++errorIndex)\n\t\t\t\t\t{\n\t\t\t\t\t\tconst auto& loc = stats[ryml::to_csubstr(_bonusOrig[errorIndex].first)].getLocationInFile();\n\t\t\t\t\t\tLog(LOG_ERROR) << ryml::formatrs<std::string>(\"Unknown stat multiplier term '{}' at {}:{}\", _bonusOrig[errorIndex].first, loc.name, loc.line);\n\t\t\t\t\t}\n\t\t\t\t\t_bonusOrig.erase(_bonusOrig.begin() + bonusIndex, _bonusOrig.end());\n\t\t\t\t}\n\t\t\t\t_refresh = true;\n\t\t\t}\n\t\t\telse if (stats.hasVal())\n\t\t\t{\n\t\t\t\t_container.loadContainer(parentName, stats.readVal<std::string>(), parser);\n\t\t\t\t_refresh = false;\n\t\t\t}\n\t\t\t// let's remember that this was modified by a modder (i.e. is not a default value)\n\t\t\t_modded = true;\n\t\t}\n\t}\n\n\t//convert bonus vector to script\n\tif (_refresh)\n\t{\n\t\tauto script = std::string{ };\n\t\tscript.reserve(1024);\n\n\t\tif (!_bonusOrig.empty())\n\t\t{\n\t\t\t//scale up for rounding\n\t\t\tscript += \"mul bonus 1000;\\n\";\n\n\t\t\tfor (const auto& p : _bonusOrig)\n\t\t\t{\n\t\t\t\tscript += \"unit.\";\n\t\t\t\tscript += p.first;\n\t\t\t\tscript += statNamePostfix;\n\t\t\t\tscript += \" bonus\";\n\t\t\t\tfor (size_t j = 0; j < statDataFuncSize; ++j)\n\t\t\t\t{\n\t\t\t\t\tif (j < p.second.size())\n\t\t\t\t\t{\n\t\t\t\t\t\tscript += \" \";\n\t\t\t\t\t\tscript += std::to_string((int)(p.second[j] * statMultiper * 1000));\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tscript += \" 0\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tscript += \";\\n\";\n\t\t\t}\n\n\t\t\t//rounding to the nearest\n\t\t\tscript += \"if ge bonus 0; add bonus 500; else; sub bonus 500; end;\\n\";\n\t\t\tscript += \"div bonus 1000;\\n\";\n\t\t}\n\t\tscript += \"return bonus;\";\n\t\t_container.loadContainer(parentName, script, parser);\n\t\t_refresh = false;\n\t}\n}\n\n/**\n * Set new values of bonus vector\n * @param bonuses\n */\nvoid RuleStatBonus::setValues(std::vector<RuleStatBonusDataOrig>&& bonuses)\n{\n\t_bonusOrig = std::move(bonuses);\n\t_refresh = true;\n}\n/**\n * Set default bonus for firing accuracy.\n */\nvoid RuleStatBonus::setFiring()\n{\n\tsetValues(\n\t\t{\n\t\t\t{ \"firing\", { 1.0f } },\n\t\t}\n\t);\n}\n\n/**\n * Set default bonus for melee accuracy.\n */\nvoid RuleStatBonus::setMelee()\n{\n\tsetValues(\n\t\t{\n\t\t\t{ \"melee\", { 1.0f } },\n\t\t}\n\t);\n}\n\n/**\n * Set default bonus for throwing accuracy.\n */\nvoid RuleStatBonus::setThrowing()\n{\n\tsetValues(\n\t\t{\n\t\t\t{ \"throwing\", { 1.0f } },\n\t\t}\n\t);\n}\n\n/**\n * Set default bonus for close quarters combat\n */\nvoid RuleStatBonus::setCloseQuarters()\n{\n\tsetValues(\n\t\t{\n\t\t\t{ \"melee\", { 0.5f } },\n\t\t\t{ \"reactions\", { 0.5f } },\n\t\t}\n\t);\n}\n\n/**\n * Set default bonus for psi attack accuracy.\n */\nvoid RuleStatBonus::setPsiAttack()\n{\n\tsetValues(\n\t\t{\n\t\t\t{ \"psi\", { 0.02f } },\n\t\t}\n\t);\n}\n\n/**\n * Set default bonus for psi defense.\n */\nvoid RuleStatBonus::setPsiDefense()\n{\n\tsetValues(\n\t\t{\n\t\t\t{ \"psiStrength\", { 1.0f } },\n\t\t\t{ \"psiSkill\", { 0.2f } },\n\t\t}\n\t);\n}\n\n/**\n * Set flat bonus equal 100% hit chance.\n */\nvoid RuleStatBonus::setFlatHundred()\n{\n\tsetValues(\n\t\t{\n\t\t\t{ \"flatHundred\", { 1.0f } },\n\t\t}\n\t);\n}\n\n/**\n * Set default bonus for melee power.\n */\nvoid RuleStatBonus::setStrength()\n{\n\tsetValues(\n\t\t{\n\t\t\t{ \"strength\", { 1.0f } },\n\t\t}\n\t);\n}\n\n/**\n *  Set default for TU recovery.\n */\nvoid RuleStatBonus::setTimeRecovery()\n{\n\tsetValues(\n\t\t{\n\t\t\t{ \"tu\", { 1.0f } },\n\t\t}\n\t);\n}\n\n/**\n * Set default for Energy recovery.\n */\nvoid RuleStatBonus::setEnergyRecovery()\n{\n\tsetValues(\n\t\t{\n\t\t\t{ \"energyRegen\", { 1.0f } },\n\t\t}\n\t);\n}\n\n/**\n *  Set default for Stun recovery.\n */\nvoid RuleStatBonus::setStunRecovery()\n{\n\tsetValues(\n\t\t{\n\t\t\t{ \"flatOne\", { 1.0f } },\n\t\t}\n\t);\n}\n\n/**\n * Calculate bonus based on attack unit and weapons.\n */\nint RuleStatBonus::getBonus(BattleActionAttack::ReadOnly attack, int externalBonuses) const\n{\n\tassert(!_refresh && \"RuleStatBonus not loaded correctly\");\n\n\tModScript::BonusStatsCommon::Output arg{ externalBonuses };\n\tModScript::BonusStatsCommon::Worker work{ attack.attacker, externalBonuses, attack.weapon_item, attack.damage_item, attack.type, attack.skill_rules };\n\twork.execute(_container, arg);\n\n\treturn arg.getFirst();\n}\n\n/**\n * Calculate bonus based on unit stats.\n */\nint RuleStatBonus::getBonus(const BattleUnit* unit, int externalBonuses) const\n{\n\tassert(!_refresh && \"RuleStatBonus not loaded correctly\");\n\n\tModScript::BonusStatsCommon::Output arg{ externalBonuses };\n\tModScript::BonusStatsCommon::Worker work{ unit, externalBonuses, nullptr, nullptr, BA_NONE, nullptr };\n\twork.execute(_container, arg);\n\n\treturn arg.getFirst();\n}\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tScript binding\n////////////////////////////////////////////////////////////\n\nModScript::BonusStatsBaseParser::BonusStatsBaseParser(ScriptGlobal* shared, const std::string& name, Mod* mod) : ScriptParserEvents{ shared, name,\n\t\"bonus\",\n\t\"unit\", \"external_bonuses\", \"weapon\", \"ammo\", \"battle_action\", \"skill\" }\n{\n\tBind<BattleUnit> bu = { this };\n\n\tfor (const auto& stat : statDataMap)\n\t{\n\t\tstat.func(bu, stat.name);\n\t}\n}\n\n} //namespace OpenXcom\n"
  },
  {
    "path": "src/Mod/RuleStatBonus.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2015 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <vector>\n#include <string>\n#include \"../Engine/Yaml.h\"\n#include \"ModScript.h\"\n\nnamespace OpenXcom\n{\n\nnamespace helper { struct BattleActionAttackReadOnlyImpl; }\n\nclass BattleUnit;\nclass BattleItem;\ntypedef std::pair<float (*)(const BattleUnit*), float> RuleStatBonusData;\ntypedef std::pair<std::string, std::vector<float> > RuleStatBonusDataOrig;\n/**\n * Helper class used for storing unit stat bonuses.\n */\nclass RuleStatBonus\n{\n\tModScript::BonusStatsCommon::Container _container;\n\tstd::vector<RuleStatBonusDataOrig> _bonusOrig;\n\tbool _modded = false;\n\tbool _refresh = true;\n\n\tvoid setValues(std::vector<RuleStatBonusDataOrig>&& bonuses);\n\npublic:\n\t/// Default constructor.\n\tRuleStatBonus();\n\t/// Loads item data from YAML.\n\tvoid load(const std::string& parentName, const YAML::YamlNodeReader& reader, const ModScript::BonusStatsCommon& parser);\n\t/// Set default firing bonus.\n\tvoid setFiring();\n\t/// Set default melee bonus.\n\tvoid setMelee();\n\t/// Set default throwing bonus.\n\tvoid setThrowing();\n\t/// Set default close quarters combat bonus.\n\tvoid setCloseQuarters();\n\t/// Set default psi attack bonus.\n\tvoid setPsiAttack();\n\t/// Set default psi defense bonus.\n\tvoid setPsiDefense();\n\t/// Set default strength bonus.\n\tvoid setStrength();\n\t/// Set flat 100 bonus.\n\tvoid setFlatHundred();\n\t/// Set default for TU recovery.\n\tvoid setTimeRecovery();\n\t/// Set default for Energy recovery.\n\tvoid setEnergyRecovery();\n\t/// Set default for Stun recovery.\n\tvoid setStunRecovery();\n\t/// Get bonus based on attack unit and weapons.\n\tint getBonus(helper::BattleActionAttackReadOnlyImpl unit, int externalBonuses = 0) const;\n\t/// Get bonus based on unit stats.\n\tint getBonus(const BattleUnit* unit, int externalBonuses = 0) const;\n\t/// Used for \"Stats for Nerds\".\n\tconst std::vector<RuleStatBonusDataOrig> *getBonusRaw() const { return &_bonusOrig; }\n\tbool isModded() const { return _modded; }\n\tvoid setModded(bool modded) { _modded = modded; }\n};\n\n}\n"
  },
  {
    "path": "src/Mod/RuleTerrain.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"RuleTerrain.h\"\n#include \"MapBlock.h\"\n#include \"MapDataSet.h\"\n#include \"MapScript.h\"\n#include \"../Engine/RNG.h\"\n#include \"Mod.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * RuleTerrain construction.\n */\nRuleTerrain::RuleTerrain(const std::string &name) : _name(name), _mapScript(\"DEFAULT\"), _minDepth(0), _maxDepth(0),\n\t_ambience(-1), _ambientVolume(0.5), _minAmbienceRandomDelay(20), _maxAmbienceRandomDelay(60),\n\t_lastCraftSkinIndex(0)\n{\n\t_civilianTypes.push_back(\"MALE_CIVILIAN\");\n\t_civilianTypes.push_back(\"FEMALE_CIVILIAN\");\n}\n\n/**\n * RuleTerrain only holds mapblocks. Map datafiles are referenced.\n */\nRuleTerrain::~RuleTerrain()\n{\n\tfor (auto* mapblock : _mapBlocks)\n\t{\n\t\tdelete mapblock;\n\t}\n}\n\n/**\n * Loads the terrain from a YAML file.\n * @param node YAML node.\n * @param mod Mod for the terrain.\n */\nvoid RuleTerrain::load(const YAML::YamlNodeReader& node, Mod *mod)\n{\n\tconst auto& reader = node.useIndex();\n\tif (const auto& parent = reader[\"refNode\"])\n\t{\n\t\tload(parent, mod);\n\t}\n\n\tbool adding = reader[\"addOnly\"].readVal(false);\n\tif (const auto& map = reader[\"mapDataSets\"])\n\t{\n\t\t_mapDataSets.clear();\n\t\tfor (const auto& mapDataSet : map.children())\n\t\t{\n\t\t\t_mapDataSets.push_back(mod->getMapDataSet(mapDataSet.readVal<std::string>()));\n\t\t}\n\t}\n\tif (const auto& map = reader[\"mapBlocks\"])\n\t{\n\t\tif (!adding)\n\t\t{\n\t\t\tCollections::deleteAll(_mapBlocks);\n\t\t}\n\t\tfor (const auto& mapBlockReader : map.children())\n\t\t{\n\t\t\tMapBlock *mapBlock = new MapBlock(mapBlockReader[\"name\"].readVal<std::string>());\n\t\t\tmapBlock->load(mapBlockReader);\n\t\t\t_mapBlocks.push_back(mapBlock);\n\t\t}\n\t}\n\n\treader.tryRead(\"enviroEffects\", _enviroEffects);\n\tmod->loadUnorderedNames(_name, _civilianTypes, reader[\"civilianTypes\"]);\n\tmod->loadUnorderedNames(_name, _music, reader[\"music\"]);\n\tif (reader[\"depth\"])\n\t{\n\t\treader[\"depth\"][0].tryReadVal(_minDepth);\n\t\treader[\"depth\"][1].tryReadVal(_maxDepth);\n\t}\n\tmod->loadSoundOffset(_name, _ambience, reader[\"ambience\"], \"BATTLE.CAT\");\n\treader.tryRead(\"ambientVolume\", _ambientVolume);\n\tmod->loadSoundOffset(_name, _ambienceRandom, reader[\"ambienceRandom\"], \"BATTLE.CAT\");\n\tif (reader[\"ambienceRandomDelay\"])\n\t{\n\t\treader[\"ambienceRandomDelay\"][0].tryReadVal(_minAmbienceRandomDelay);\n\t\treader[\"ambienceRandomDelay\"][1].tryReadVal(_maxAmbienceRandomDelay);\n\t}\n\treader.tryRead(\"script\", _mapScript);\n\treader.tryRead(\"mapScripts\", _mapScripts);\n}\n\n/**\n * Gets the array of mapblocks.\n * @return Pointer to the array of mapblocks.\n */\nstd::vector<MapBlock*> *RuleTerrain::getMapBlocks()\n{\n\treturn &_mapBlocks;\n}\n\n/**\n * Gets the array of mapdatafiles.\n * @return Pointer to the array of mapdatafiles.\n */\nstd::vector<MapDataSet*> *RuleTerrain::getMapDataSets()\n{\n\treturn &_mapDataSets;\n}\n\n/**\n * Refreshes the terrain's mapdatafiles. Use for craft skins ONLY!\n */\nvoid RuleTerrain::refreshMapDataSets(int craftSkinIndex, Mod *mod)\n{\n\tif (_lastCraftSkinIndex == craftSkinIndex)\n\t{\n\t\treturn;\n\t}\n\n\tstd::vector<std::string> newNames;\n\tfor (auto* item : _mapDataSets)\n\t{\n\t\tif (item->getName() == \"BLANKS\")\n\t\t{\n\t\t\tnewNames.push_back(item->getName());\n\t\t}\n\t\telse if (_lastCraftSkinIndex == 0)\n\t\t{\n\t\t\tnewNames.push_back(item->getName() + \"_\" + std::to_string(craftSkinIndex));\n\t\t}\n\t\telse\n\t\t{\n\t\t\tsize_t lastPos = item->getName().find_last_of(\"_\");\n\t\t\tstd::string stripped = item->getName().substr(0, lastPos);\n\t\t\tif (craftSkinIndex > 0)\n\t\t\t{\n\t\t\t\tnewNames.push_back(stripped + \"_\" + std::to_string(craftSkinIndex));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tnewNames.push_back(stripped);\n\t\t\t}\n\t\t}\n\t}\n\t_mapDataSets.clear();\n\tfor (const auto& newName : newNames)\n\t{\n\t\t_mapDataSets.push_back(mod->getMapDataSet(newName));\n\t}\n\tnewNames.clear();\n\t_lastCraftSkinIndex = craftSkinIndex;\n}\n\n/**\n * Gets the terrain name.\n * @return The terrain name.\n */\nstd::string RuleTerrain::getName() const\n{\n\treturn _name;\n}\n\n/**\n * Returns the enviro effects name for this terrain.\n * @return String ID for the enviro effects.\n */\nconst std::string& RuleTerrain::getEnviroEffects() const\n{\n\treturn _enviroEffects;\n}\n\n/**\n * Gets a random mapblock within the given constraints.\n * @param maxsize The maximum size of the mapblock (10 or 20 or 999 - don't care).\n * @param type Whether this must be a block of a certain type.\n * @param force Whether to enforce the max size.\n * @return Pointer to the mapblock.\n */\nMapBlock* RuleTerrain::getRandomMapBlock(int maxSizeX, int maxSizeY, int group, bool force)\n{\n\tstd::vector<MapBlock*> compliantMapBlocks;\n\n\tfor (auto* mapblock : _mapBlocks)\n\t{\n\t\tif ((mapblock->getSizeX() == maxSizeX ||\n\t\t\t(!force && mapblock->getSizeX() < maxSizeX)) &&\n\t\t\t(mapblock->getSizeY() == maxSizeY ||\n\t\t\t(!force && mapblock->getSizeY() < maxSizeY)) &&\n\t\t\tmapblock->isInGroup(group))\n\t\t{\n\t\t\tcompliantMapBlocks.push_back(mapblock);\n\t\t}\n\t}\n\n\tif (compliantMapBlocks.empty()) return 0;\n\n\tsize_t n = RNG::generate(0, compliantMapBlocks.size() - 1);\n\n\treturn compliantMapBlocks[n];\n}\n\n/**\n * Gets a mapblock with a given name.\n * @param name The name of the mapblock.\n * @return Pointer to mapblock.\n */\nMapBlock* RuleTerrain::getMapBlock(const std::string &name)\n{\n\tfor (auto* mapblock : _mapBlocks)\n\t{\n\t\tif (mapblock->getName() == name)\n\t\t\treturn mapblock;\n\t}\n\treturn 0;\n}\n\n/**\n * Gets a mapdata object.\n * @param id The id in the terrain.\n * @param mapDataSetID The id of the map data set.\n * @return Pointer to MapData object.\n */\nMapData *RuleTerrain::getMapData(unsigned int *id, int *mapDataSetID) const\n{\n\tMapDataSet* mdf = 0;\n\tauto iter = _mapDataSets.begin();\n\tfor (; iter != _mapDataSets.end(); ++iter)\n\t{\n\t\tmdf = *iter;\n\t\tif (*id < mdf->getSize())\n\t\t{\n\t\t\tbreak;\n\t\t}\n\t\t*id -= mdf->getSize();\n\t\t(*mapDataSetID)++;\n\t}\n\tif (iter == _mapDataSets.end())\n\t{\n\t\t// oops! someone at microprose made an error in the map!\n\t\t// set this broken tile reference to BLANKS 0.\n\t\tmdf = _mapDataSets.front();\n\t\t*id = 0;\n\t\t*mapDataSetID = 0;\n\t}\n\treturn mdf->getObject(*id);\n}\n\n/**\n * Gets the list of civilian types to use on this terrain (default MALE_CIVILIAN and FEMALE_CIVILIAN)\n * @return list of civilian types to use.\n */\nstd::vector<std::string> RuleTerrain::getCivilianTypes() const\n{\n\treturn _civilianTypes;\n}\n\n/**\n * Gets the min depth.\n * @return The min depth.\n */\nint RuleTerrain::getMinDepth() const\n{\n\treturn _minDepth;\n}\n\n/**\n * Gets the max depth.\n * @return max depth.\n */\nint RuleTerrain::getMaxDepth() const\n{\n\treturn _maxDepth;\n}\n\n/**\n * Gets The ambient sound effect.\n * @return The ambient sound effect.\n */\nint RuleTerrain::getAmbience() const\n{\n\treturn _ambience;\n}\n\n/**\n * Gets The generation script name.\n * @return The name of the script to use.\n */\nconst std::string& RuleTerrain::getRandomMapScript() const\n{\n\tif (!_mapScripts.empty())\n\t{\n\t\tsize_t pick = RNG::generate(0, _mapScripts.size() - 1);\n\t\treturn _mapScripts[pick];\n\t}\n\treturn _mapScript;\n}\n\n/**\n * Does any map script use globe terrain?\n * @return 1 = yes, 0 = no, -1 = no map script found.\n */\nint RuleTerrain::hasTextureBasedScript(const Mod* mod) const\n{\n\tint ret = -1;\n\t// iterate _mapScripts\n\tfor (const std::string& script : _mapScripts)\n\t{\n\t\tauto* vec = mod->getMapScript(script);\n\t\tif (vec)\n\t\t{\n\t\t\tret = 0;\n\t\t\t// iterate map script commands\n\t\t\tfor (auto* ms : *vec)\n\t\t\t{\n\t\t\t\t// iterate terrains\n\t\t\t\tfor (const std::string& terrain : ms->getRandomAlternateTerrain())\n\t\t\t\t{\n\t\t\t\t\tif (terrain == \"globeTerrain\" || terrain == \"baseTerrain\")\n\t\t\t\t\t{\n\t\t\t\t\t\treturn 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// iterate vertical levels\n\t\t\t\tfor (auto& vlevel : ms->getVerticalLevels())\n\t\t\t\t{\n\t\t\t\t\tif (vlevel.levelTerrain == \"globeTerrain\" || vlevel.levelTerrain == \"baseTerrain\")\n\t\t\t\t\t{\n\t\t\t\t\t\treturn 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t// check also _mapScript\n\t{\n\t\tauto* vec = mod->getMapScript(_mapScript);\n\t\tif (vec)\n\t\t{\n\t\t\tret = 0;\n\t\t\t// iterate map script commands\n\t\t\tfor (auto* ms : *vec)\n\t\t\t{\n\t\t\t\t// iterate terrains\n\t\t\t\tfor (const std::string& terrain : ms->getRandomAlternateTerrain())\n\t\t\t\t{\n\t\t\t\t\tif (terrain == \"globeTerrain\" || terrain == \"baseTerrain\")\n\t\t\t\t\t{\n\t\t\t\t\t\treturn 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// iterate vertical levels\n\t\t\t\tfor (auto& vlevel : ms->getVerticalLevels())\n\t\t\t\t{\n\t\t\t\t\tif (vlevel.levelTerrain == \"globeTerrain\" || vlevel.levelTerrain == \"baseTerrain\")\n\t\t\t\t\t{\n\t\t\t\t\t\treturn 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t}\n\treturn ret;\n}\n\n/**\n * Gets The list of musics this terrain has to choose from.\n * @return The list of track names.\n */\nconst std::vector<std::string> &RuleTerrain::getMusic() const\n{\n\treturn _music;\n}\n\n\ndouble RuleTerrain::getAmbientVolume() const\n{\n\treturn _ambientVolume;\n}\n\n}\n"
  },
  {
    "path": "src/Mod/RuleTerrain.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <vector>\n#include <string>\n#include \"../Engine/Yaml.h\"\n#include \"MapBlock.h\"\n\nnamespace OpenXcom\n{\n\nclass MapBlock;\nclass MapDataSet;\nclass MapData;\nclass Mod;\n\n/**\n * Represents a specific type of Battlescape Terrain.\n * - the names of the objectsets needed in this specific terrain.\n * - the mapblocks that can be used to build this terrain.\n * @sa http://www.ufopaedia.org/index.php?title=TERRAIN\n */\nclass RuleTerrain\n{\nprivate:\n\tstd::vector<MapDataSet*> _mapDataSets;\n\tstd::vector<MapBlock*> _mapBlocks;\n\tstd::string _name, _mapScript;\n\tstd::vector<std::string> _mapScripts;\n\tstd::string _enviroEffects;\n\tstd::vector<std::string> _civilianTypes, _music;\n\tint _minDepth, _maxDepth, _ambience;\n\tdouble _ambientVolume;\n\tstd::vector<int> _ambienceRandom;\n\tint _minAmbienceRandomDelay, _maxAmbienceRandomDelay;\n\tint _lastCraftSkinIndex;\npublic:\n\tRuleTerrain(const std::string &name);\n\t~RuleTerrain();\n\t/// Loads the terrain from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader, Mod *mod);\n\t/// Gets the terrain's name (used for MAP generation).\n\tstd::string getName() const;\n\t/// Gets the terrain's enviro effects.\n\tconst std::string& getEnviroEffects() const;\n\t/// Gets the terrain's mapblocks.\n\tstd::vector<MapBlock*> *getMapBlocks();\n\t/// Gets the terrain's mapdatafiles.\n\tstd::vector<MapDataSet*> *getMapDataSets();\n\t/// Refreshes the terrain's mapdatafiles. Use for craft skins ONLY!\n\tvoid refreshMapDataSets(int craftSkinIndex, Mod *mod);\n\t/// Gets a random mapblock.\n\tMapBlock *getRandomMapBlock(int maxSizeX, int maxSizeY, int group, bool force = true);\n\t/// Gets a mapblock given its name.\n\tMapBlock *getMapBlock(const std::string &name);\n\t/// Gets the mapdata object.\n\tMapData *getMapData(unsigned int *id, int *mapDataSetID) const;\n\t/// Gets the civilian types to use.\n\tstd::vector<std::string> getCivilianTypes() const;\n\t/// Gets the minimum depth.\n\tint getMinDepth() const;\n\t/// Gets the maximum depth.\n\t int getMaxDepth() const;\n\t/// Gets the ambient sound effect.\n\tint getAmbience() const;\n\t/// Gets the random ambient sound effects.\n\tconst std::vector<int> &getAmbienceRandom() const { return _ambienceRandom; }\n\t/// Gets the minimum delay for the random ambient sound effect.\n\tint getMinAmbienceRandomDelay() const { return _minAmbienceRandomDelay; }\n\t/// Gets the maximum delay for the random ambient sound effect.\n\tint getMaxAmbienceRandomDelay() const { return _maxAmbienceRandomDelay; }\n\t/// Gets the generation script name.\n\tconst std::string& getRandomMapScript() const;\n\tint hasTextureBasedScript(const Mod* mod) const;\n\t/// Gets the list of music to pick from.\n\tconst std::vector<std::string> &getMusic() const;\n\tdouble getAmbientVolume() const;\n};\n\n}\n"
  },
  {
    "path": "src/Mod/RuleUfo.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"RuleUfo.h\"\n#include \"RuleTerrain.h\"\n#include \"Mod.h\"\n#include \"../Engine/ScriptBind.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Creates a blank ruleset for a certain\n * type of UFO.\n * @param type String defining the type.\n */\nRuleUfo::RuleUfo(const std::string &type) :\n\t_type(type), _size(\"STR_VERY_SMALL\"),\n\t_radius(-1), _visibility(0), _blobSize(-1),\n\t_sprite(-1), _marker(-1), _markerLand(-1), _markerCrash(-1),\n\t_power(0), _range(0), _score(0), _reload(0), _breakOffTime(0), _missionScore(1),\n\t_hunterKillerPercentage(0), _huntMode(0), _huntSpeed(100), _huntBehavior(2), _softlockThreshold(100),\n\t_missilePower(0), _missileStopChance(0),\n\t_unmanned(false), _instaHyper(false), _noAlert(false),\n\t_splashdownSurvivalChance(100), _fakeWaterLandingChance(0),\n\t_fireSound(-1), _alertSound(-1), _huntAlertSound(-1), _hitSound(-1),\n\t_battlescapeTerrainData(0), _stats(), _statsRaceBonus()\n{\n\t_stats.sightRange = 268;\n\t_stats.radarRange = 672; // same default as in RuleCraft (used by hunter-killers)\n\t_statsRaceBonus[\"\"] = RuleUfoStats();\n}\n\n/**\n *\n */\nRuleUfo::~RuleUfo()\n{\n\tdelete _battlescapeTerrainData;\n}\n\n/**\n * Loads the UFO from a YAML file.\n * @param node YAML node.\n * @param mod Mod for the UFO.\n */\nvoid RuleUfo::load(const YAML::YamlNodeReader& node, Mod *mod, const ModScript &parsers)\n{\n\tconst auto& reader = node.useIndex();\n\tif (const auto& parent = reader[\"refNode\"])\n\t{\n\t\tload(parent, mod, parsers);\n\t}\n\n\treader.tryRead(\"size\", _size);\n\t// sigh\n\tif (_size == \"STR_MEDIUM\")\n\t{\n\t\t_size = \"STR_MEDIUM_UC\";\n\t}\n\treader.tryRead(\"radius\", _radius);\n\treader.tryRead(\"visibility\", _visibility);\n\treader.tryRead(\"blobSize\", _blobSize);\n\tif (_blobSize > 7)\n\t{\n\t\t_blobSize = 7; // maximum possible\n\t}\n\treader.tryRead(\"sprite\", _sprite);\n\tif (reader[\"marker\"])\n\t{\n\t\t_marker = mod->getOffset(reader[\"marker\"].readVal(_marker), 8);\n\t}\n\tif (reader[\"markerLand\"])\n\t{\n\t\t_markerLand = mod->getOffset(reader[\"markerLand\"].readVal(_markerLand), 8);\n\t}\n\tif (reader[\"markerCrash\"])\n\t{\n\t\t_markerCrash = mod->getOffset(reader[\"markerCrash\"].readVal(_markerCrash), 8);\n\t}\n\treader.tryRead(\"power\", _power);\n\treader.tryRead(\"range\", _range);\n\treader.tryRead(\"score\", _score);\n\treader.tryRead(\"reload\", _reload);\n\treader.tryRead(\"breakOffTime\", _breakOffTime);\n\treader.tryRead(\"missionScore\", _missionScore);\n\treader.tryRead(\"hunterKillerPercentage\", _hunterKillerPercentage);\n\treader.tryRead(\"huntMode\", _huntMode);\n\treader.tryRead(\"huntSpeed\", _huntSpeed);\n\treader.tryRead(\"huntBehavior\", _huntBehavior);\n\treader.tryRead(\"softlockThreshold\", _softlockThreshold);\n\treader.tryRead(\"missilePower\", _missilePower);\n\treader.tryRead(\"missileStopChance\", _missileStopChance);\n\treader.tryRead(\"unmanned\", _unmanned);\n\treader.tryRead(\"instaHyper\", _instaHyper);\n\treader.tryRead(\"noAlert\", _noAlert);\n\treader.tryRead(\"splashdownSurvivalChance\", _splashdownSurvivalChance);\n\treader.tryRead(\"fakeWaterLandingChance\", _fakeWaterLandingChance);\n\n\t_stats.load(reader);\n\n\tif (const auto& terrain = reader[\"battlescapeTerrainData\"])\n\t{\n\t\tif (_battlescapeTerrainData)\n\t\t\tdelete _battlescapeTerrainData;\n\t\tRuleTerrain *rule = new RuleTerrain(terrain[\"name\"].readVal<std::string>());\n\t\trule->load(terrain, mod);\n\t\t_battlescapeTerrainData = rule;\n\t}\n\treader.tryRead(\"modSprite\", _modSprite);\n\treader.tryRead(\"hitImage\", _hitImage);\n\tfor (const auto& raceBonus : reader[\"raceBonus\"].children())\n\t{\n\t\t_statsRaceBonus[raceBonus.readKey<std::string>()].load(raceBonus);\n\t}\n\n\tmod->loadSoundOffset(_type, _fireSound, reader[\"fireSound\"], \"GEO.CAT\");\n\tmod->loadSoundOffset(_type, _alertSound, reader[\"alertSound\"], \"GEO.CAT\");\n\tmod->loadSoundOffset(_type, _huntAlertSound, reader[\"huntAlertSound\"], \"GEO.CAT\");\n\tmod->loadSoundOffset(_type, _hitSound, reader[\"hitSound\"], \"GEO.CAT\");\n\n\t_ufoScripts.load(_type, reader, parsers.ufoScripts);\n\t_scriptValues.load(reader, parsers.getShared());\n}\n\n/**\n * Gets the language string that names\n * this UFO. Each UFO type has a unique name.\n * @return The Ufo's name.\n */\nconst std::string &RuleUfo::getType() const\n{\n\treturn _type;\n}\n\n/**\n * Gets the size of this type of UFO.\n * @return The Ufo's size.\n */\nconst std::string &RuleUfo::getSize() const\n{\n\treturn _size;\n}\n\n/**\n * Gets the radius of this type of UFO\n * on the dogfighting window.\n * @return The radius in pixels.\n */\nint RuleUfo::getRadius() const\n{\n\tif (_radius > -1)\n\t{\n\t\treturn _radius;\n\t}\n\n\tif (_size == \"STR_VERY_SMALL\")\n\t{\n\t\treturn 2;\n\t}\n\telse if (_size == \"STR_SMALL\")\n\t{\n\t\treturn 3;\n\t}\n\telse if (_size == \"STR_MEDIUM_UC\")\n\t{\n\t\treturn 4;\n\t}\n\telse if (_size == \"STR_LARGE\")\n\t{\n\t\treturn 5;\n\t}\n\telse if (_size == \"STR_VERY_LARGE\")\n\t{\n\t\treturn 6;\n\t}\n\treturn 0;\n}\n\n/**\n * Gets the default visibility of this type of UFO,\n * i.e. not considering the altitude.\n * @return The default visibility.\n */\nint RuleUfo::getDefaultVisibility() const\n{\n\tif (_visibility != 0)\n\t{\n\t\treturn _visibility;\n\t}\n\n\t// vanilla = 15*(3-ufosize);\n\tif (_size == \"STR_VERY_SMALL\")\n\t\treturn -30;\n\telse if (_size == \"STR_SMALL\")\n\t\treturn -15;\n\telse if (_size == \"STR_MEDIUM_UC\")\n\t\treturn 0;\n\telse if (_size == \"STR_LARGE\")\n\t\treturn 15;\n\telse if (_size == \"STR_VERY_LARGE\")\n\t\treturn 30;\n\n\treturn 0;\n}\n\n/**\n * Gets the blob size of this type of UFO\n * on the dogfighting window.\n * @return The blob size.\n */\nint RuleUfo::getBlobSize() const\n{\n\tif (_blobSize > -1 && _blobSize < 8)\n\t{\n\t\treturn _blobSize;\n\t}\n\n\tif (_size == \"STR_VERY_SMALL\")\n\t{\n\t\treturn 0;\n\t}\n\telse if (_size == \"STR_SMALL\")\n\t{\n\t\treturn 1;\n\t}\n\telse if (_size == \"STR_MEDIUM_UC\")\n\t{\n\t\treturn 2;\n\t}\n\telse if (_size == \"STR_LARGE\")\n\t{\n\t\treturn 3;\n\t}\n\telse if (_size == \"STR_VERY_LARGE\")\n\t{\n\t\treturn 4;\n\t}\n\n\treturn 4;\n}\n\n/**\n * Gets the ID of the sprite used to draw the UFO\n * in the Dogfight window.\n * @return The sprite ID.\n */\nint RuleUfo::getSprite() const\n{\n\treturn _sprite;\n}\n\n/**\n * Returns the globe marker for the UFO while in flight.\n * @return Marker sprite, -1 if none.\n */\nint RuleUfo::getMarker() const\n{\n\treturn _marker;\n}\n\n/**\n * Returns the globe marker for the UFO while landed.\n * @return Marker sprite, -1 if none.\n */\nint RuleUfo::getLandMarker() const\n{\n\treturn _markerLand;\n}\n\n/**\n * Returns the globe marker for the UFO when crashed.\n * @return Marker sprite, -1 if none.\n */\nint RuleUfo::getCrashMarker() const\n{\n\treturn _markerCrash;\n}\n\n/**\n * Gets the maximum damage done by the\n * UFO's weapons per shot.\n * @return The weapon power.\n */\nint RuleUfo::getWeaponPower() const\n{\n\treturn _power;\n}\n\n/**\n * Gets the maximum range for the\n * UFO's weapons.\n * @return The weapon range.\n */\nint RuleUfo::getWeaponRange() const\n{\n\treturn _range;\n}\n\n/**\n * Gets the amount of points the player\n * gets for shooting down the UFO.\n * @return The score.\n */\nint RuleUfo::getScore() const\n{\n\treturn _score;\n}\n\n/**\n * Gets the terrain data needed to draw the UFO in the battlescape.\n * @return The RuleTerrain.\n */\nRuleTerrain *RuleUfo::getBattlescapeTerrainData() const\n{\n\treturn _battlescapeTerrainData;\n}\n\n/**\n * Gets the weapon reload for UFO ships.\n * @return The UFO weapon reload time.\n */\nint RuleUfo::getWeaponReload() const\n{\n\treturn _reload;\n}\n\n/**\n * Gets the UFO's break off time.\n * @return The UFO's break off time in game seconds.\n */\nint RuleUfo::getBreakOffTime() const\n{\n\treturn _breakOffTime;\n}\n\n/**\n * Gets the UFO's fire sound.\n * @return The fire sound ID.\n */\nint RuleUfo::getFireSound() const\n{\n\treturn _fireSound;\n}\n\n/**\n * Gets the UFO's alert sound (UFO detected alert).\n * @return The alert sound ID.\n */\nint RuleUfo::getAlertSound() const\n{\n\treturn _alertSound;\n}\n\n/**\n * Gets the UFO's alert sound (UFO on intercept course alert).\n * @return The alert sound ID.\n */\nint RuleUfo::getHuntAlertSound() const\n{\n\treturn _huntAlertSound;\n}\n\n/**\n * For user-defined UFOs, use a surface for the \"preview\" image.\n * @return The name of the surface that represents this UFO.\n */\nconst std::string &RuleUfo::getModSprite() const\n{\n\treturn _modSprite;\n}\n\n/**\n * Gets basic statistic of UFO.\n * @return Basic stats of UFO.\n */\nconst RuleUfoStats& RuleUfo::getStats() const\n{\n\treturn _stats;\n}\n\n\n/**\n * Gets bonus statistic of UFO based on race.\n * @param s Race name.\n * @return Bonus stats.\n */\nconst RuleUfoStats& RuleUfo::getRaceBonus(const std::string& s) const\n{\n\tauto i = _statsRaceBonus.find(s);\n\tif (i != _statsRaceBonus.end())\n\t\treturn i->second;\n\telse\n\t\treturn _statsRaceBonus.find(\"\")->second;\n}\n\nconst std::map<std::string, RuleUfoStats> &RuleUfo::getRaceBonusRaw() const\n{\n\treturn _statsRaceBonus;\n}\n\n/**\n * Gets the amount of points awarded every 30 minutes\n * while the UFO is on a mission (doubled when landed).\n * @return Score.\n */\nint RuleUfo::getMissionScore() const\n{\n\treturn _missionScore;\n}\n\n/**\n * Gets the UFO's chance to become a hunter-killer.\n * @return Percentage to become a hunter-killer.\n */\nint RuleUfo::getHunterKillerPercentage() const\n{\n\treturn _hunterKillerPercentage;\n}\n\n/**\n * Gets the UFO's hunting preferences.\n * @return Hunt mode ID.\n */\nint RuleUfo::getHuntMode() const\n{\n\treturn _huntMode;\n}\n\n/**\n * Gets the UFO's hunting speed (in percent of maximum speed).\n * @return Percentage of maximum speed.\n */\nint RuleUfo::getHuntSpeed() const\n{\n\treturn _huntSpeed;\n}\n\n/**\n * Gets the UFO's hunting behavior (normal, kamikaze or random).\n * @return Hunt behavior ID.\n */\nint RuleUfo::getHuntBehavior() const\n{\n\treturn _huntBehavior;\n}\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tScript binding\n////////////////////////////////////////////////////////////\n\nnamespace\n{\n\nstd::string debugDisplayScript(const RuleUfo* ru)\n{\n\tif (ru)\n\t{\n\t\tstd::string s;\n\t\ts += RuleUfo::ScriptName;\n\t\ts += \"(name: \\\"\";\n\t\ts += ru->getType();\n\t\ts += \"\\\")\";\n\t\treturn s;\n\t}\n\telse\n\t{\n\t\treturn \"null\";\n\t}\n}\n\n} // namespace\n\n/**\n * Register RuleUfo in script parser.\n * @param parser Script parser.\n */\nvoid RuleUfo::ScriptRegister(ScriptParserBase* parser)\n{\n\tBind<RuleUfo> ar = { parser };\n\n\tar.add<&RuleUfo::getRadius>(\"getRadius\");\n\tar.add<&RuleUfo::getWeaponRange>(\"getWeaponRange\");\n\tar.add<&RuleUfo::getWeaponPower>(\"getWeaponPower\");\n\tar.add<&RuleUfo::getWeaponReload>(\"getWeaponReload\");\n\n\tRuleUfoStats::addGetStatsScript<&RuleUfo::_stats>(ar, \"\");\n\n\tar.addScriptValue<BindBase::OnlyGet, &RuleUfo::_scriptValues>();\n\tar.addDebugDisplay<&debugDisplayScript>();\n}\n\n}\n"
  },
  {
    "path": "src/Mod/RuleUfo.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include <map>\n#include \"../Engine/Yaml.h\"\n#include \"RuleCraft.h\"\n#include \"ModScript.h\"\n\nnamespace OpenXcom\n{\n\nclass RuleTerrain;\nclass Mod;\n\nstruct RuleUfoStats : RuleCraftStats\n{\n\tstd::string craftCustomDeploy, missionCustomDeploy;\n\n\t/// Add different stats.\n\tRuleUfoStats& operator+=(const RuleUfoStats& r)\n\t{\n\t\t*(RuleCraftStats*)this += r;\n\t\tif (!r.craftCustomDeploy.empty()) craftCustomDeploy = r.craftCustomDeploy;\n\t\tif (!r.missionCustomDeploy.empty()) missionCustomDeploy = r.missionCustomDeploy;\n\t\treturn *this;\n\t}\n\t/// Loads stats from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader)\n\t{\n\t\t(*(RuleCraftStats*)this).load(reader);\n\t\treader.tryRead(\"craftCustomDeploy\", craftCustomDeploy);\n\t\treader.tryRead(\"missionCustomDeploy\", missionCustomDeploy);\n\t}\n\n\ttemplate<auto Stat, typename TBind>\n\tstatic void addGetStatsScript(TBind& b, std::string prefix)\n\t{\n\t\tRuleCraftStats::addGetStatsScript<Stat>(b, prefix);\n//\t\tb.template addField<Stat, &RuleUfoStats::?>(prefix + \"?\");\n\t}\n\n\t/// Helper function needed by scripts\n\tconst RuleCraftStats& getBase() const { return *this; }\n};\n\n/**\n * Represents a specific type of UFO.\n * Contains constant info about a UFO like\n * speed, weapons, scores, etc.\n * @sa Ufo\n */\nclass RuleUfo\n{\nprivate:\n\tstd::string _type, _size;\n\tint _radius, _visibility, _blobSize;\n\tint _sprite, _marker, _markerLand, _markerCrash;\n\tint _power, _range, _score, _reload, _breakOffTime, _missionScore;\n\tint _hunterKillerPercentage, _huntMode, _huntSpeed, _huntBehavior, _softlockThreshold;\n\tint _missilePower;\n\tint _missileStopChance;\n\tbool _unmanned;\n\tbool _instaHyper;\n\tbool _noAlert;\n\tint _splashdownSurvivalChance;\n\tint _fakeWaterLandingChance;\n\tint _fireSound;\n\tint _alertSound;\n\tint _huntAlertSound;\n\tint _hitSound;\n\tRuleTerrain *_battlescapeTerrainData;\n\tRuleUfoStats _stats;\n\tstd::map<std::string, RuleUfoStats> _statsRaceBonus;\n\tstd::string _modSprite;\n\tstd::string _hitImage;\n\n\tModScript::UfoScripts::Container _ufoScripts;\n\tScriptValues<RuleUfo> _scriptValues;\npublic:\n\n\t/// Name of class used in script.\n\tstatic constexpr const char *ScriptName = \"RuleUfo\";\n\t/// Register all useful function used by script.\n\tstatic void ScriptRegister(ScriptParserBase* parser);\n\n\t/// Creates a blank UFO ruleset.\n\tRuleUfo(const std::string &type);\n\t/// Cleans up the UFO ruleset.\n\t~RuleUfo();\n\t/// Loads UFO data from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader, Mod *mod, const ModScript &parsers);\n\t/// Gets the UFO's type.\n\tconst std::string &getType() const;\n\t/// Gets the UFO's size.\n\tconst std::string &getSize() const;\n\t/// Gets the UFO's radius.\n\tint getRadius() const;\n\t/// Gets the UFO's default visibility.\n\tint getDefaultVisibility() const;\n\t/// Gets the UFO's blob size.\n\tint getBlobSize() const;\n\t/// Gets the UFO's sprite.\n\tint getSprite() const;\n\t/// Gets the UFO's globe marker when flying.\n\tint getMarker() const;\n\t/// Gets the UFO's globe marker when landed.\n\tint getLandMarker() const;\n\t/// Gets the UFO's globe marker when crashed.\n\tint getCrashMarker() const;\n\t/// Gets the UFO's weapon power.\n\tint getWeaponPower() const;\n\t/// Gets the UFO's weapon range.\n\tint getWeaponRange() const;\n\t/// Gets the UFO's score.\n\tint getScore() const;\n\t/// Sets the battlescape terrain data ruleset for this UFO\n\tRuleTerrain *getBattlescapeTerrainData() const;\n\t/// Gets the reload time of the UFO's weapon.\n\tint getWeaponReload() const;\n\t/// Gets the UFO's escape time.\n\tint getBreakOffTime() const;\n\t/// Gets the UFO's fire sound.\n\tint getFireSound() const;\n\t/// Gets the alert sound for this UFO (UFO detected alert).\n\tint getAlertSound() const;\n\t/// Gets the alert sound for this UFO (UFO on intercept course alert).\n\tint getHuntAlertSound() const;\n\t/// Gets the hit sound for this UFO (to be used in the BaseDestroyedState UI).\n\tint getHitSound() const { return _hitSound; }\n\t/// Gets the name of the surface that represents this UFO.\n\tconst std::string &getModSprite() const;\n\t/// Gets the name of the surface to be displayed in the BaseDestroyedState UI.\n\tconst std::string& getHitImage() const { return _hitImage; }\n\t/// Get basic statistic of UFO.\n\tconst RuleUfoStats& getStats() const;\n\t/// Get race bonus of statistic of UFO.\n\tconst RuleUfoStats& getRaceBonus(const std::string& s) const;\n\tconst std::map<std::string, RuleUfoStats> &getRaceBonusRaw() const;\n\t/// Gets the UFO's mission score.\n\tint getMissionScore() const;\n\t/// Gets the UFO's chance to become a hunter-killer.\n\tint getHunterKillerPercentage() const;\n\t/// Gets the UFO's hunting preferences.\n\tint getHuntMode() const;\n\t/// Gets the UFO's hunting speed (in percent of maximum speed).\n\tint getHuntSpeed() const;\n\t/// Gets the UFO's hunting behavior (normal, kamikaze or random).\n\tint getHuntBehavior() const;\n\t/// Gets the amount of shots fired before a softlock is detected.\n\tint getSoftlockThreshold() const { return _softlockThreshold; }\n\t/// Gets the missile power (of a UFO that represents one or more missiles).\n\tint getMissilePower() const { return _missilePower; }\n\t/// Gets the chance to stop retaliation mission after a successful missile strike (default = 0).\n\tint getMissileStopChance() const { return _missileStopChance; }\n\t/// Is this an unmanned UFO (drone, missile, etc.)?\n\tbool isUnmanned() const { return _unmanned; }\n\t/// Show extra info during base defense even if the UFO was not yet hyper-detected classically?\n\tbool isInstaHyper() const { return _instaHyper; }\n\t/// Suppress UFO detection alerts?\n\tbool isNoAlert() const { return _noAlert; }\n\t/// Gets the chance of surviving a splashdown on fake water.\n\tint getSplashdownSurvivalChance() const { return _splashdownSurvivalChance; }\n\t/// Gets the chance for deciding to land on fake water texture.\n\tint getFakeWaterLandingChance() const { return _fakeWaterLandingChance; }\n\t/// Gets script.\n\ttemplate<typename Script>\n\tconst typename Script::Container &getScript() const { return _ufoScripts.get<Script>(); }\n\t/// Get all script values.\n\tconst ScriptValues<RuleUfo> &getScriptValuesRaw() const { return _scriptValues; }\n};\n\n}\n"
  },
  {
    "path": "src/Mod/RuleVideo.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"RuleVideo.h\"\n#include <climits>\n#include \"../Engine/Screen.h\"\n\nnamespace OpenXcom\n{\n\nRuleVideo::RuleVideo(const std::string &id) : _id(id), _useUfoAudioSequence(false), _winGame(false), _loseGame(false)\n{\n\t// backwards-compatibility failsafe\n\tif (_id == \"winGame\")\n\t\t_winGame = true;\n\tif (_id == \"loseGame\")\n\t\t_loseGame = true;\n}\n\nRuleVideo::~RuleVideo()\n{\n}\n\nstatic void _loadSlide(SlideshowSlide &slide, const YAML::YamlNodeReader& reader)\n{\n\tslide.imagePath = reader[\"imagePath\"].readVal<std::string>(\"\");\n\tslide.caption = reader[\"caption\"].readVal<std::string>(\"\");\n\n\tstd::pair<int, int> size = reader[\"captionSize\"].readVal<std::pair<int, int> >(\n\t\tstd::pair<int, int>(Screen::ORIGINAL_WIDTH, Screen::ORIGINAL_HEIGHT));\n\tslide.w = size.first;\n\tslide.h = size.second;\n\n\tstd::pair<int, int> pos = reader[\"captionPos\"].readVal<std::pair<int, int> >(std::pair<int, int>(0, 0));\n\tslide.x = pos.first;\n\tslide.y = pos.second;\n\n\tslide.color = reader[\"captionColor\"].readVal<int>(INT_MAX);\n\tslide.transitionSeconds = reader[\"transitionSeconds\"].readVal<int>(0);\n\tslide.align = reader[\"captionAlign\"].readVal(ALIGN_LEFT);\n\tslide.valign = reader[\"captionVerticalAlign\"].readVal(ALIGN_TOP);\n}\n\nvoid RuleVideo::load(const YAML::YamlNodeReader& reader)\n{\n\t_useUfoAudioSequence = reader[\"useUfoAudioSequence\"].readVal(false);\n\treader.tryRead(\"winGame\", _winGame);\n\treader.tryRead(\"loseGame\", _loseGame);\n\n\tfor (const auto& video : reader[\"videos\"].children())\n\t\t_videos.push_back(video.readVal<std::string>());\n\n\tfor (const auto& track : reader[\"audioTracks\"].children())\n\t\t_audioTracks.push_back(track.readVal<std::string>());\n\n\tif (const auto& slideshow = reader[\"slideshow\"])\n\t{\n\t\t_slideshowHeader.musicId = slideshow[\"musicId\"].readVal<std::string>(\"\");\n\t\t_slideshowHeader.transitionSeconds = slideshow[\"transitionSeconds\"].readVal<int>(30);\n\n\t\tfor (const auto& slideReader : slideshow[\"slides\"].children())\n\t\t{\n\t\t\tSlideshowSlide slide;\n\t\t\t_loadSlide(slide, slideReader);\n\t\t\t_slides.push_back(slide);\n\t\t}\n\t}\n}\n\nbool RuleVideo::useUfoAudioSequence() const\n{\n\treturn _useUfoAudioSequence;\n}\n\nconst std::vector<std::string> * RuleVideo::getVideos() const\n{\n\treturn &_videos;\n}\n\nconst SlideshowHeader & RuleVideo::getSlideshowHeader() const\n{\n\treturn _slideshowHeader;\n}\n\nconst std::vector<SlideshowSlide> * RuleVideo::getSlides() const\n{\n\treturn &_slides;\n}\n\nconst std::vector<std::string> * RuleVideo::getAudioTracks() const\n{\n\treturn &_audioTracks;\n}\n\n}\n"
  },
  {
    "path": "src/Mod/RuleVideo.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/Yaml.h\"\n#include <vector>\n#include <string>\n#include \"../Interface/Text.h\"\n\nnamespace OpenXcom\n{\n\nstruct SlideshowHeader\n{\n\tstd::string musicId; // just the extension-less filename, like \"GMWIN\"\n\tint transitionSeconds; // number of seconds to show each slide\n\tSlideshowHeader() : transitionSeconds(0) { }\n};\n\nstruct SlideshowSlide\n{\n\tstd::string imagePath; // relative path to slide image\n\tstd::string caption; // STR id of caption text\n\tint w, h, x, y, color; // caption rect and color info\n\tTextHAlign align; // caption alignment\n\tTextVAlign valign; // caption vertical alignment\n\tint transitionSeconds; // number of seconds to show this slide\n\tSlideshowSlide() : w(0), h(0), x(0), y(0), color(0), align(ALIGN_LEFT), valign(ALIGN_TOP), transitionSeconds(0) { }\n};\n\nclass RuleVideo\n{\nprivate:\n\tstd::string _id;\n\tbool _useUfoAudioSequence;\n\tbool _winGame, _loseGame;\n\tstd::vector<std::string> _videos, _audioTracks;\n\tSlideshowHeader _slideshowHeader;\n\tstd::vector<SlideshowSlide> _slides;\npublic:\n\tRuleVideo(const std::string &type);\n\t~RuleVideo();\n\tvoid load(const YAML::YamlNodeReader& reader);\n\t/// returns whether to use the UFO audio sequence.  in general, this\n\t/// should only ever be true for the vanilla UFO intro cutscene\n\tbool useUfoAudioSequence() const;\n\tconst std::vector<std::string> * getVideos() const;\n\tconst SlideshowHeader & getSlideshowHeader() const;\n\tconst std::vector<SlideshowSlide> * getSlides() const;\n\tconst std::vector<std::string> * getAudioTracks() const;\n\tbool getWinGame() const { return _winGame; }\n\tbool getLoseGame() const { return _loseGame; }\n};\n\n}\n"
  },
  {
    "path": "src/Mod/RuleWeaponSet.cpp",
    "content": "/*\n * Copyright 2010-2015 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"RuleWeaponSet.h\"\n#include \"Mod.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Creates a blank ruleset for a weapon set.\n * @param type String defining the weapon set.\n */\nRuleWeaponSet::RuleWeaponSet(const std::string& type) : _type(type)\n{\n}\n\n/**\n *\n */\nRuleWeaponSet::~RuleWeaponSet()\n{\n}\n\n/**\n * Loads the weapon set from a YAML file.\n * @param node YAML node.\n * @param mod Mod handle.\n */\nvoid RuleWeaponSet::load(const YAML::YamlNodeReader& reader, Mod* mod)\n{\n\tif (const auto& parent = reader[\"refNode\"])\n\t{\n\t\tload(parent, mod);\n\t}\n\n\tmod->loadUnorderedNames(_type, _weaponNames, reader[\"weapons\"]);\n}\n\n/**\n * Cross link with other Rules.\n */\nvoid RuleWeaponSet::afterLoad(const Mod* mod)\n{\n\tmod->linkRule(_weapons, _weaponNames);\n}\n\n}\n"
  },
  {
    "path": "src/Mod/RuleWeaponSet.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2015 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include <vector>\n#include \"../Engine/Yaml.h\"\n\nnamespace OpenXcom\n{\n\nclass Mod;\nclass RuleItem;\n\n/**\n * Represents a weapon set.\n */\nclass RuleWeaponSet\n{\nprivate:\n\tstd::string _type;\n\tstd::vector<std::string> _weaponNames;\n\tstd::vector<const RuleItem*> _weapons;\npublic:\n\t/// Creates a blank weapon set ruleset.\n\tRuleWeaponSet(const std::string& type);\n\t/// Cleans up the weapon set ruleset.\n\t~RuleWeaponSet();\n\t/// Loads ruleset from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader, Mod* mod);\n\t/// Cross link with other rules.\n\tvoid afterLoad(const Mod* mod);\n\t/// Gets the weapon set type.\n\tconst std::string& getType() const { return _type; }\n\t/// Gets the weapon set content.\n\tconst std::vector<const RuleItem*>& getWeapons() const { return _weapons; }\n\n};\n\n}\n"
  },
  {
    "path": "src/Mod/SoldierNamePool.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"SoldierNamePool.h\"\n#include <sstream>\n#include \"../Savegame/Soldier.h\"\n#include \"../Engine/RNG.h\"\n#include \"../Engine/Language.h\"\n#include \"../Engine/FileMap.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes a new pool with blank lists of names.\n */\nSoldierNamePool::SoldierNamePool() : _totalWeight(0), _femaleFrequency(-1), _globalWeight(100)\n{\n}\n\n/**\n *\n */\nSoldierNamePool::~SoldierNamePool()\n{\n}\n\n/**\n * Loads the pool from a YAML file.\n * @param filename YAML file.\n */\nvoid SoldierNamePool::load(const std::string &filename)\n{\n\tYAML::YamlRootNodeReader reader = FileMap::getYAML(filename);\n\n\treader.tryRead(\"maleFirst\", _maleFirst);\n\treader.tryRead(\"femaleFirst\", _femaleFirst);\n\treader.tryRead(\"maleLast\", _maleLast);\n\treader.tryRead(\"femaleLast\", _femaleLast);\n\treader.tryRead(\"maleCallsign\", _maleCallsign);\n\treader.tryRead(\"femaleCallsign\", _femaleCallsign);\n\tif (_femaleCallsign.empty())\n\t{\n\t\t_femaleCallsign = _maleCallsign;\n\t}\n\tif (_femaleFirst.empty())\n\t{\n\t\t_femaleFirst = _maleFirst;\n\t}\n\tif (_femaleLast.empty())\n\t{\n\t\t_femaleLast = _maleLast;\n\t}\n\treader.tryRead(\"lookWeights\", _lookWeights);\n\t_totalWeight = 0;\n\tfor (int lw : _lookWeights)\n\t{\n\t\t_totalWeight += lw;\n\t}\n\treader.tryRead(\"femaleFrequency\", _femaleFrequency);\n\treader.tryRead(\"globalWeight\", _globalWeight);\n\tif (_globalWeight <= 0)\n\t{\n\t\t// can't let the modders break this completely\n\t\t_globalWeight = 100;\n\t}\n\n\treader.tryRead(\"country\", _country);\n\treader.tryRead(\"region\", _region);\n\n\t// Note: each name pool *instance* is only ever loaded once,\n\t// there are no overrides, so we can do checks here instead of needing afterLoad()\n\tif (_maleFirst.empty())\n\t{\n\t\tthrow Exception(\"A name pool cannot have an empty 'maleFirst:' list. File name: \" + filename);\n\t}\n\tif (_femaleFirst.empty())\n\t{\n\t\tthrow Exception(\"A name pool cannot have an empty 'femaleFirst:' list. File name: \" + filename);\n\t}\n}\n\n/**\n * Returns a new random name (first + last) from the\n * lists of names contained within.\n * @param gender Returned gender of the name.\n * @return The soldier's name.\n */\nstd::string SoldierNamePool::genName(SoldierGender *gender, int femaleFrequency) const\n{\n\tstd::ostringstream name;\n\tbool female;\n\tif (_femaleFrequency > -1)\n\t{\n\t\tfemale = RNG::percent(_femaleFrequency);\n\t}\n\telse\n\t{\n\t\tfemale = RNG::percent(femaleFrequency);\n\t}\n\n\tif (!female)\n\t{\n\t\t*gender = GENDER_MALE;\n\t\tsize_t first = RNG::generate(0, _maleFirst.size() - 1);\n\t\tname << _maleFirst[first];\n\t\tif (!_maleLast.empty())\n\t\t{\n\t\t\tsize_t last = RNG::generate(0, _maleLast.size() - 1);\n\t\t\tname << \" \" << _maleLast[last];\n\t\t}\n\t}\n\telse\n\t{\n\t\t*gender = GENDER_FEMALE;\n\t\tsize_t first = RNG::generate(0, _femaleFirst.size() - 1);\n\t\tname << _femaleFirst[first];\n\t\tif (!_femaleLast.empty())\n\t\t{\n\t\t\tsize_t last = RNG::generate(0, _femaleLast.size() - 1);\n\t\t\tname << \" \" << _femaleLast[last];\n\t\t}\n\t}\n\treturn name.str();\n}\n\n/**\n * Returns a new random callsign from the\n * lists of names contained within.\n * @param gender Gender of the callsign.\n * @return The soldier's callsign.\n */\nstd::string SoldierNamePool::genCallsign(const SoldierGender gender) const\n{\n\tstd::string callsign;\n\tif (!_femaleCallsign.empty())\n\t{\n\t\tif (gender == GENDER_MALE)\n\t\t{\n\t\t\tsize_t first = RNG::generate(0, _maleCallsign.size() - 1);\n\t\t\tcallsign = _maleCallsign[first];\n\t\t}\n\t\telse\n\t\t{\n\t\t\tsize_t first = RNG::generate(0, _femaleCallsign.size() - 1);\n\t\t\tcallsign = _femaleCallsign[first];\n\t\t}\n\t}\n\treturn callsign;\n}\n\n/**\n * Generates an int representing the index of the soldier's look, when passed the maximum index value.\n * @param numLooks The maximum index.\n * @return The index of the soldier's look.\n */\nsize_t SoldierNamePool::genLook(size_t numLooks)\n{\n\tint look = 0;\n\tconst int minimumChance = 2;\t// minimum chance of a look being selected if it isn't enumerated. This ensures that looks MUST be zeroed to not appear.\n\n\twhile (_lookWeights.size() < numLooks)\n\t{\n\t\t_lookWeights.push_back(minimumChance);\n\t\t_totalWeight += minimumChance;\n\t}\n\twhile (_lookWeights.size() > numLooks)\n\t{\n\t\t_totalWeight -= _lookWeights.back();\n\t\t_lookWeights.pop_back();\n\t}\n\n\tif (_totalWeight < 1)\n\t{\n\t\treturn RNG::generate(0, numLooks - 1);\n\t}\n\n\tint random = RNG::generate(1, _totalWeight);\n\tfor (int lw : _lookWeights)\n\t{\n\t\tif (random <= lw)\n\t\t{\n\t\t\treturn look;\n\t\t}\n\t\trandom -= lw;\n\t\t++look;\n\t}\n\n\treturn RNG::generate(0, numLooks - 1);\n}\n\n}\n"
  },
  {
    "path": "src/Mod/SoldierNamePool.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include <vector>\n#include \"../Savegame/Soldier.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Pool of soldier names to generate random names.\n * Each pool contains a set of first names (male or female) and last names.\n * The first names define the soldier's gender, and are randomly associated\n * with a last name.\n */\nclass SoldierNamePool\n{\nprivate:\n\tstd::vector<std::string> _maleFirst, _femaleFirst, _maleLast, _femaleLast, _maleCallsign, _femaleCallsign;\n\tstd::vector<int> _lookWeights;\n\tint _totalWeight, _femaleFrequency;\n\tint _globalWeight;\n\tstd::string _country, _region;\npublic:\n\t/// Creates a blank pool.\n\tSoldierNamePool();\n\t/// Cleans up the pool.\n\t~SoldierNamePool();\n\t/// Loads the pool from YAML.\n\tvoid load(const std::string &filename);\n\t/// Generates a new name from the pool.\n\tstd::string genName(SoldierGender *gender, int femaleFrequency) const;\n\t/// Generates a new callsign from the pool.\n\tstd::string genCallsign(const SoldierGender gender) const;\n\t/// Generates an int representing the index of the soldier's look, when passed the maximum index value.\n\tsize_t genLook(size_t numLooks);\n\t/// Gets a global weight of this name pool.\n\tint getGlobalWeight() const { return _globalWeight; }\n\t/// Gets the country assigned to this name pool.\n\tconst std::string& getCountry() const { return _country; }\n\t/// Gets the region assigned to this name pool.\n\tconst std::string& getRegion() const { return _region; }\n};\n\n}\n"
  },
  {
    "path": "src/Mod/SoundDefinition.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"SoundDefinition.h\"\n\nnamespace OpenXcom\n{\n\nSoundDefinition::SoundDefinition(const std::string &type) : _type(type)\n{\n}\n\nSoundDefinition::~SoundDefinition()\n{\n}\n\nvoid SoundDefinition::load(const YAML::YamlNodeReader& reader)\n{\n\tfor (const auto& soundRange : reader[\"soundRanges\"].children())\n\t{\n\t\tstd::pair<int, int> range = soundRange.readVal(std::make_pair<int, int>(0, 0));\n\t\tfor (int j = range.first; j <= range.second; ++j)\n\t\t{\n\t\t\t_soundList.push_back(j);\n\t\t}\n\t}\n\tfor (const auto& sound : reader[\"sounds\"].children())\n\t{\n\t\t_soundList.push_back(sound.readVal(-1));\n\t}\n\treader.tryRead(\"file\", _catFile);\n}\n\nconst std::vector<int> &SoundDefinition::getSoundList() const\n{\n\treturn _soundList;\n}\n\nstd::string SoundDefinition::getCATFile() const\n{\n\treturn _catFile;\n}\n\n}\n"
  },
  {
    "path": "src/Mod/SoundDefinition.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/Yaml.h\"\n#include <vector>\n#include <string>\n\nnamespace OpenXcom\n{\n\nclass SoundDefinition\n{\nprivate:\n\tstd::string _type;\n\tstd::string _catFile;\n\tstd::vector<int> _soundList;\npublic:\n\tSoundDefinition(const std::string &type);\n\t~SoundDefinition();\n\tvoid load(const YAML::YamlNodeReader& reader);\n\tconst std::vector<int> &getSoundList() const;\n\tstd::string getCATFile() const;\n\n};\n\n}\n"
  },
  {
    "path": "src/Mod/StatString.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"StatString.h\"\n#include \"Unit.h\"\n#include <vector>\n#include \"../Engine/Language.h\"\n#include \"../Engine/Unicode.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Creates a blank StatString.\n */\nStatString::StatString()\n{\n}\n\n/**\n * Cleans up the extra StatString.\n */\nStatString::~StatString()\n{\n}\n\n/**\n * Loads the StatString from a YAML file.\n * @param node YAML node.\n */\nvoid StatString::load(const YAML::YamlNodeReader& reader)\n{\n\tstd::string conditionNames[] = {\"psiStrength\", \"psiSkill\", \"bravery\", \"strength\", \"firing\", \"reactions\", \"stamina\", \"tu\", \"health\", \"throwing\", \"melee\", \"psiTraining\", \"manaPool\"};\n\treader.tryRead(\"string\", _stringToBeAddedIfAllConditionsAreMet);\n\tfor (size_t i = 0; i < std::size(conditionNames); i++)\n\t{\n\t\tif (const auto& conditionReader = reader[ryml::to_csubstr(conditionNames[i])])\n\t\t{\n\t\t\t_conditions.push_back(getCondition(conditionNames[i], conditionReader));\n\t\t}\n\t}\n}\n\n/**\n * Generates a condition from YAML.\n * @param conditionName Stat name of the condition.\n * @param node YAML node.\n * @return New StatStringCondition.\n */\nStatStringCondition *StatString::getCondition(const std::string &conditionName, const YAML::YamlNodeReader& conditionReader)\n{\n\t// These are the defaults from xcomutil\n\tint minValue = 0, maxValue = 255;\n\tif (conditionReader[0] && !conditionReader[0].hasNullVal())\n\t\tconditionReader[0].tryReadVal(minValue);\n\tif (conditionReader[1] && !conditionReader[1].hasNullVal())\n\t\tconditionReader[1].tryReadVal(maxValue);\n\tStatStringCondition *thisCondition = new StatStringCondition(conditionName, minValue, maxValue);\n\treturn thisCondition;\n}\n\n/**\n * Returns the conditions associated with this StatString.\n * @return List of StatStringConditions.\n */\nconst std::vector<StatStringCondition*> &StatString::getConditions() const\n{\n\treturn _conditions;\n}\n\n/**\n * Returns the string to add to a name for this StatString.\n * @return StatString... string.\n */\nstd::string StatString::getString() const\n{\n\treturn _stringToBeAddedIfAllConditionsAreMet;\n}\n\n/**\n * Calculates the list of StatStrings that apply to certain unit stats.\n * @param currentStats Unit stats.\n * @param statStrings List of statString rules.\n * @param psiStrengthEval Are psi stats available?\n * @return Resulting string of all valid StatStrings.\n */\nstd::string StatString::calcStatString(UnitStats &currentStats, const std::vector<StatString *> &statStrings, bool psiStrengthEval, bool inTraining)\n{\n\tstd::string result;\n\tstd::map<std::string, int> currentStatsMap = getCurrentStats(currentStats);\n\tif (inTraining)\n\t{\n\t\tcurrentStatsMap[\"psiTraining\"] = 1;\n\t}\n\tfor (auto* statStringDef : statStrings)\n\t{\n\t\tbool conditionsMet = true;\n\t\tfor (auto* statStringCondition : statStringDef->getConditions())\n\t\t{\n\t\t\tif (!conditionsMet) break; // loop finished\n\t\t\tauto name = currentStatsMap.find(statStringCondition->getConditionName());\n\t\t\tif (name != currentStatsMap.end())\n\t\t\t{\n\t\t\t\tconditionsMet = conditionsMet && statStringCondition->isMet(name->second, currentStats.psiSkill > 0 || psiStrengthEval);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// if name == currentStatsMap.end() we've searched for a stat that doesn't exist.\n\t\t\t\t// this means psi training. if there's no \"psiTraining\" stat in the statsMap,\n\t\t\t\t// this soldier isn't in training, so we won't append his name with the psiTraining tag.\n\t\t\t\t// presumably conditionsMet was originally initialized as false, but for whatever reason that was changed, hence this.\n\t\t\t\tconditionsMet = false;\n\t\t\t}\n\t\t}\n\t\tif (conditionsMet)\n\t\t{\n\t\t\tstd::string wstring = statStringDef->getString();\n\t\t\tresult += wstring;\n\t\t\tif (Unicode::codePointLengthUTF8(wstring) > 1)\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\treturn result;\n}\n\n/**\n * Get a map associating stat names to unit stats.\n * @param currentStats Unit stats to use.\n * @return Map of unit stats.\n */\nstd::map<std::string, int> StatString::getCurrentStats(UnitStats &currentStats)\n{\n\tstd::map<std::string, int> currentStatsMap;\n\tcurrentStatsMap[\"psiStrength\"] = currentStats.psiStrength;\n\tcurrentStatsMap[\"psiSkill\"] = currentStats.psiSkill;\n\tcurrentStatsMap[\"bravery\"] = currentStats.bravery;\n\tcurrentStatsMap[\"strength\"] = currentStats.strength;\n\tcurrentStatsMap[\"firing\"] = currentStats.firing;\n\tcurrentStatsMap[\"reactions\"] = currentStats.reactions;\n\tcurrentStatsMap[\"stamina\"] = currentStats.stamina;\n\tcurrentStatsMap[\"tu\"] = currentStats.tu;\n\tcurrentStatsMap[\"health\"] = currentStats.health;\n\tcurrentStatsMap[\"throwing\"] = currentStats.throwing;\n\tcurrentStatsMap[\"melee\"] = currentStats.melee;\n\tcurrentStatsMap[\"manaPool\"] = currentStats.mana;\n\treturn currentStatsMap;\n}\n\n\n}\n"
  },
  {
    "path": "src/Mod/StatString.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/Yaml.h\"\n#include \"StatStringCondition.h\"\n\nnamespace OpenXcom\n{\n\nstruct UnitStats;\n\n/**\n * For adding statStrings to the game.\n * See http://ufopaedia.org/index.php?title=Statstrings\n */\n\n/*\nNameStats in XCOMUTIL.CFG:\n\nStatStrings, which were added in version 7.2, are used for automatically\nrenaming soldiers.  They are case sensitive and they are processed in the\norder in which they are specified.  The format of these StatStrings is:\n\n  string statid:[lower]-[upper] [statid:[lower]-[upper] [...] ]\n\n  where string = string to add to name.  If length == 1, then the strings\n\t\t\t\t accumulate.  Otherwise, success ends the search.  All\n\t\t\t\t single character strings SHOULD come last, but that is\n\t\t\t\t not required. / and ; are not a valid strings.  The maximum\n\t\t\t\t string length is 19.\n\t\tstatid = a = armor (front)\n\t\t\t\t b = bravery\n\t\t\t\t d = time units (dexterity)\n\t\t\t\t e = stamina (endurance)\n\t\t\t\t f = firing accuracy\n\t\t\t\t h = health\n\t\t\t\t k = psi/mc skill\n\t\t\t\t p = psi/mc strength (if skill > 0)\n\t\t\t\t q = psi/mc strength (regardless of skill)\n\t\t\t\t r = reactions\n\t\t\t\t s = strength\n\t\t\t\t t = throwing accuracy\n\t\t lower = lower limit of stat (inclusive), defaults to 0\n\t\t upper = upper limit of stat (inclusive), defaults to 255\n\nStat ranges are ANDed together when testing for success.  To achieve a logical\nOR, list the same string more than once.  For example, Wimp b:0-10 and\nWimp s:0-20 would designate a Wimp as either someone who is not brave or\nsomeone who is very weak.  By arranging the string properly, you can put all\nof your strengths before your weaknesses or list the stats in order, which is\nthe default.\n\nYou may specify as many ranges for one StatString as you like, up to the limit\nof the memory I have allocated.  There is enough space for a total of more\nthan 600 ranges to be defined.  Let me know if you need more.\n\nThe # character is a special string that will be replaced by numbers\ncorresponding to the values of the statistics listed, divided by 10.  For\nexample, # fr will generate the string 74 if the firing accuracy value is 72\nand the reactions value is 48.  This is a cumulative string, so that you could\nprefix your strings with letters by using statid:0-255 before it.  For\nexample P p:0-255 followed by # p would generate P6 for a Psi Strength of 64,\nassuming that Psi Skill is non-zero.  Psi/MC Strength is always reported as\nzero unless Psi/MC Skill is greater than 0.  To test Psi/MC Strength without\nchecking the Psi/MC Skill, use the q statid.\n\nSince strings longer than one character will terminate the checking, these\nstrings are normally listed first.  More stats accumulating after Snpr would\nruin the usefulness of Snpr as an equipment type.  However, if you wanted to\nplace an indicator in front of Snpr as a warning of some critical weakness,\nyou could place a single character string at the start of the list.  For\nexample, if you wanted to know that your Snpr had a very low Psi/MC Strength\nand had little resistance to alien control, you could put x p:0-30 or x q:0-30\nat the start of the list to produce Snpr or xSnpr as your final code. This is\nwhat I did in the default case.  See the XCOMUTIL.CFG file for examples.\n\nIf the resulting string exceeds the maximum length for a name, the first\nname will be replaced by an initial.  If the string is still too long, the\nfirst name will be removed entirely.  If this string is still too long, no\nchange will be made.\n\nIf / is used as a statid, it indicates that this is the last required name\nstat.  That is, if the name stats make the name too long, the total string\nwill be reduced to the size at the moment that the / statid was\nencountered.  XcomUtil will again check the length of the name, reducing\nor eliminating the first name as needed.  If this string is still too\nlong, nothing will be changed.\n */\n\nclass StatString\n{\nprivate:\n\tstd::string _stringToBeAddedIfAllConditionsAreMet;\n\tstd::vector<StatStringCondition*> _conditions;\n\tstatic StatStringCondition *getCondition(const std::string &conditionName, const YAML::YamlNodeReader& reader);\npublic:\n\t/// Creates a blank StatString ruleset.\n\tStatString();\n\t/// Cleans up the StatString ruleset.\n\tvirtual ~StatString();\n\t/// Loads the StatString from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader);\n\t/// Get the conditions for this StatString.\n\tconst std::vector<StatStringCondition*> &getConditions() const;\n\t/// Get the StatString string.\n\tstd::string getString() const;\n\t/// Calculate a StatString.\n\tstatic std::string calcStatString(UnitStats &currentStats, const std::vector<StatString*> &statStrings, bool psiStrengthEval, bool inTraining);\n\t/// Get the CurrentStats.\n\tstatic std::map<std::string, int> getCurrentStats(UnitStats &currentStats);\n};\n\n}\n"
  },
  {
    "path": "src/Mod/StatStringCondition.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"StatStringCondition.h\"\n\n\nnamespace OpenXcom\n{\n/**\n * Creates a blank StatStringCondition.\n * @param conditionName Name of the condition.\n * @param minVal Minimum value.\n * @param maxVal Maximum value.\n */\nStatStringCondition::StatStringCondition(const std::string &conditionName, int minVal, int maxVal) : _conditionName(conditionName), _minVal(minVal), _maxVal(maxVal)\n{\n}\n\n/**\n * Cleans up the extra StatStringCondition.\n */\nStatStringCondition::~StatStringCondition()\n{\n}\n\n/**\n * Gets the condition string.\n * @return Name of the associated stat.\n */\nstd::string StatStringCondition::getConditionName() const\n{\n\treturn _conditionName;\n}\n\n/**\n * Gets the minimum value for the condition (default is 0).\n * @return The minimum value.\n */\nint StatStringCondition::getMinVal() const\n{\n\treturn _minVal;\n}\n\n/**\n * Gets the maximum value for the condition (default is 255).\n * @return The maximum value.\n */\nint StatStringCondition::getMaxVal() const\n{\n\treturn _maxVal;\n}\n\n/**\n * Checks if this condition is valid for the current stat.\n * @param stat The current soldier stat.\n * @param psi Can we show psi stats?\n * @return If the condition is met.\n */\nbool StatStringCondition::isMet(int stat, bool psi) const\n{\n\tif (_conditionName == \"psiTraining\")\n\t{\n\t\treturn true;\n\t}\n\tbool conditionMet = (stat >= _minVal && stat <= _maxVal);\n\tif (_conditionName == \"psiStrength\" || _conditionName == \"psiSkill\")\n\t{\n\t\tconditionMet = conditionMet && psi;\n\t}\n\treturn conditionMet;\n}\n\n}\n"
  },
  {
    "path": "src/Mod/StatStringCondition.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n\nnamespace OpenXcom\n{\n\nclass StatStringCondition\n{\nprivate:\n\tstd::string _conditionName;\n\tint _minVal;\n\tint _maxVal;\npublic:\n\t/// Creates a blank StatStringCondition.\n\tStatStringCondition(const std::string &conditionName, int minVal, int maxVal);\n\t/// Cleans up the StatStringCondition.\n\tvirtual ~StatStringCondition();\n\t/// Gets the condition name.\n\tstd::string getConditionName() const;\n\t/// Gets the minimum value.\n\tint getMinVal() const;\n\t/// Gets the maximum value.\n\tint getMaxVal() const;\n\t/// Checks if the condition has been met.\n\tbool isMet(int stat, bool psi) const;\n};\n\n}\n"
  },
  {
    "path": "src/Mod/Texture.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Texture.h\"\n#include \"Mod.h\"\n#include \"../Savegame/Target.h\"\n#include \"../Engine/RNG.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes a globe texture.\n * @param id Texture identifier.\n */\nTexture::Texture(int id) : _id(id), _baseGridSprite(0), _isOcean(false), _fakeUnderwater(false)\n{\n}\n\n/**\n *\n */\nTexture::~Texture()\n{\n}\n\n/**\n * Loads the texture type from a YAML file.\n * @param node YAML node.\n */\nvoid Texture::load(const YAML::YamlNodeReader& reader, Mod* mod)\n{\n\treader.tryRead(\"id\", _id);\n\t{\n\t\tstd::string parent = \"id_\" + std::to_string(_id);\n\t\tmod->loadSpriteOffset(parent, _baseGridSprite, reader[\"baseGridSprite\"], \"BASEBITS.PCK\");\n\t}\n\treader.tryRead(\"isOcean\", _isOcean);\n\treader.tryRead(\"fakeUnderwater\", _fakeUnderwater);\n\treader.tryRead(\"startingCondition\", _startingCondition);\n\treader.tryRead(\"deployments\", _deployments);\n\treader.tryRead(\"terrain\", _terrain);\n\treader.tryRead(\"baseTerrain\", _baseTerrain);\n}\n\n/**\n * Returns the list of terrain criteria associated\n * with this texture.\n * @return List of terrain.\n */\nstd::vector<TerrainCriteria> *Texture::getTerrain()\n{\n\treturn &_terrain;\n}\n\n/**\n * Calculates a random terrain for a mission target based\n * on the texture's available terrain criteria.\n * @param target Pointer to the mission target.\n * @return the name of the picked terrain.\n */\nstd::string Texture::getRandomTerrain(Target *target) const\n{\n\tint totalWeight = 0;\n\tstd::map<int, std::string> possibilities;\n\tfor (const auto& terrainCrit : _terrain)\n\t{\n\t\tif (terrainCrit.weight > 0 &&\n\t\t\ttarget->getLongitude() >= terrainCrit.lonMin && target->getLongitude() < terrainCrit.lonMax &&\n\t\t\ttarget->getLatitude() >= terrainCrit.latMin && target->getLatitude() < terrainCrit.latMax)\n\t\t{\n\t\t\ttotalWeight += terrainCrit.weight;\n\t\t\tpossibilities[totalWeight] = terrainCrit.name;\n\t\t}\n\t}\n\tif (totalWeight > 0)\n\t{\n\t\tint pick = RNG::generate(1, totalWeight);\n\t\tfor (const auto& pair : possibilities)\n\t\t{\n\t\t\tif (pick <= pair.first)\n\t\t\t{\n\t\t\t\treturn pair.second;\n\t\t\t}\n\t\t}\n\t}\n\treturn \"\";\n}\n\n/**\n * Returns the list of terrain criteria associated\n * with this texture for base defense missions.\n * @return List of terrain.\n */\nstd::vector<TerrainCriteria> *Texture::getBaseTerrain()\n{\n\treturn &_baseTerrain;\n}\n\n/**\n * Calculates a random terrain for a base defense mission target based\n * on the texture's available terrain criteria.\n * @param target Pointer to the mission target.\n * @return the name of the picked terrain.\n */\nstd::string Texture::getRandomBaseTerrain(Target *target) const\n{\n\tint totalWeight = 0;\n\tstd::map<int, std::string> possibilities;\n\tfor (const auto& terrainCrit : _baseTerrain)\n\t{\n\t\tif (terrainCrit.weight > 0 &&\n\t\t\ttarget->getLongitude() >= terrainCrit.lonMin && target->getLongitude() < terrainCrit.lonMax &&\n\t\t\ttarget->getLatitude() >= terrainCrit.latMin && target->getLatitude() < terrainCrit.latMax)\n\t\t{\n\t\t\ttotalWeight += terrainCrit.weight;\n\t\t\tpossibilities[totalWeight] = terrainCrit.name;\n\t\t}\n\t}\n\tint pick = RNG::generate(1, totalWeight);\n\tfor (const auto& pair : possibilities)\n\t{\n\t\tif (pick <= pair.first)\n\t\t{\n\t\t\treturn pair.second;\n\t\t}\n\t}\n\treturn \"\";\n}\n\n/**\n * Returns the list of deployments associated\n * with this texture.\n * @return List of deployments.\n */\nconst std::map<std::string, int> &Texture::getDeployments() const\n{\n\treturn _deployments;\n}\n\n/**\n * Calculates a random deployment for a mission target based\n * on the texture's available deployments.\n * @return the name of the picked deployment.\n */\nstd::string Texture::getRandomDeployment() const\n{\n\tif (_deployments.empty())\n\t{\n\t\treturn \"\";\n\t}\n\tif (_deployments.size() == 1)\n\t{\n\t\treturn _deployments.begin()->first;\n\t}\n\n\tint totalWeight = 0;\n\tfor (const auto& pair : _deployments)\n\t{\n\t\ttotalWeight += pair.second;\n\t}\n\n\tif (totalWeight >= 1)\n\t{\n\t\tint pick = RNG::generate(1, totalWeight);\n\t\tfor (const auto& pair : _deployments)\n\t\t{\n\t\t\tif (pick <= pair.second)\n\t\t\t{\n\t\t\t\treturn pair.first;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tpick -= pair.second;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn \"\";\n}\n\n// helper overloads for deserialization-only\nbool read(ryml::ConstNodeRef const& n, TerrainCriteria* val)\n{\n\tYAML::YamlNodeReader reader(n);\n\treader.tryRead(\"name\", val->name);\n\treader.tryRead(\"weight\", val->weight);\n\tif (const auto& areaReader = reader[\"area\"])\n\t{\n\t\tstd::vector<double> area = areaReader.readVal<std::vector<double> >();\n\t\tval->lonMin = Deg2Rad(area[0]);\n\t\tval->lonMax = Deg2Rad(area[1]);\n\t\tval->latMin = Deg2Rad(area[2]);\n\t\tval->latMax = Deg2Rad(area[3]);\n\t}\n\treturn true;\n}\n\n}\n"
  },
  {
    "path": "src/Mod/Texture.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../fmath.h\"\n#include <string>\n#include <vector>\n#include \"../Engine/Yaml.h\"\n\nnamespace OpenXcom\n{\n\nstruct TerrainCriteria\n{\n\tstd::string name;\n\tint weight;\n\tdouble lonMin, lonMax, latMin, latMax;\n\tTerrainCriteria() : weight(1), lonMin(0.0), lonMax(360.0), latMin(-90.0), latMax(90.0) {};\n};\n\nclass Target;\nclass Mod;\n\n/**\n * Represents the relations between a Geoscape texture\n * and the corresponding Battlescape mission attributes.\n */\nclass Texture\n{\nprivate:\n\tint _id;\n\tint _baseGridSprite;\n\tbool _isOcean;\n\tbool _fakeUnderwater;\n\tstd::string _startingCondition;\n\tstd::map<std::string, int> _deployments;\n\tstd::vector<TerrainCriteria> _terrain;\n\tstd::vector<TerrainCriteria> _baseTerrain;\npublic:\n\t/// Creates a new texture with mission data.\n\tTexture(int id);\n\t/// Cleans up the texture.\n\t~Texture();\n\t/// Loads the texture from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader, Mod* mod);\n\t/// Gets the list of terrain criteria.\n\tstd::vector<TerrainCriteria> *getTerrain();\n\t/// Gets a random texture terrain for a given target.\n\tstd::string getRandomTerrain(Target *target) const;\n\t/// Gets the list of terrain criteria for base defenses.\n\tstd::vector<TerrainCriteria> *getBaseTerrain();\n\t/// Gets a random texture terrain for base defenses for a given target.\n\tstd::string getRandomBaseTerrain(Target *target) const;\n\t/// Gets the alien deployment for this texture.\n\tconst std::map<std::string, int> &getDeployments() const;\n\t/// Gets a random deployment.\n\tstd::string getRandomDeployment() const;\n\t/// Gets the index into BASEBITS.PCK sprite set. Used to draw the base grid.\n\tint getBaseGridSprite() const { return _baseGridSprite; }\n\t/// Is the texture a cosmetic-only ocean texture?\n\tbool isCosmeticOcean() const { return _isOcean; }\n\t/// Is the texture a fake underwater texture?\n\tbool isFakeUnderwater() const { return _fakeUnderwater; }\n\t/// Gets the Texture's starting condition.\n\tconst std::string &getStartingCondition() const { return _startingCondition; }\n};\n\n// helper overloads for deserialization-only\nbool read(ryml::ConstNodeRef const& n, TerrainCriteria* val);\n\n}\n"
  },
  {
    "path": "src/Mod/UfoTrajectory.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"UfoTrajectory.h\"\n#include \"../Savegame/Ufo.h\"\n\nnamespace OpenXcom\n{\n\nconst std::string UfoTrajectory::RETALIATION_ASSAULT_RUN = \"__RETALIATION_ASSAULT_RUN\";\n\nUfoTrajectory::UfoTrajectory(const std::string &id) : _id(id), _groundTimer(5)\n{\n}\n\n/**\n * Overwrites trajectory data with the data stored in @a node.\n * Only the fields contained in the node will be overwritten.\n * @param node The node containing the new values.\n */\nvoid UfoTrajectory::load(const YAML::YamlNodeReader& reader)\n{\n\tif (const auto& parent = reader[\"refNode\"])\n\t{\n\t\tload(parent);\n\t}\n\n\treader.tryRead(\"groundTimer\", _groundTimer);\n\treader.tryRead(\"waypoints\", _waypoints);\n}\n\n/**\n * Gets the altitude at a waypoint.\n * @param wp The waypoint.\n * @return The altitude.\n */\nstd::string UfoTrajectory::getAltitude(size_t wp) const\n{\n\treturn Ufo::ALTITUDE_STRING[_waypoints[wp].altitude];\n}\n\n// helper overloads for (de)serialization\nbool read(ryml::ConstNodeRef const& n, TrajectoryWaypoint* val)\n{\n\tYAML::YamlNodeReader reader(n);\n\tval->zone = reader[0].readVal<int>();\n\tval->altitude = reader[1].readVal<int>();\n\tval->speed = reader[2].readVal<int>();\n\treturn true;\n}\n\n}\n"
  },
  {
    "path": "src/Mod/UfoTrajectory.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <vector>\n#include <string>\n#include \"../Engine/Yaml.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Information for points on a UFO trajectory.\n */\nstruct TrajectoryWaypoint\n{\n\t/// The mission zone.\n\tsize_t zone;\n\t/// The altitude to reach.\n\tsize_t altitude;\n\t/// The speed percentage ([0..100])\n\tsize_t speed;\n};\n\n/**\n * Holds information about a specific trajectory.\n * Ufo trajectories are a sequence of mission zones, altitudes and speed percentages.\n */\nclass UfoTrajectory\n{\npublic:\n\tstatic const std::string RETALIATION_ASSAULT_RUN;\n\n\tUfoTrajectory(const std::string &id);\n\t/**\n\t * Gets the trajectory's ID.\n\t * @return The trajectory's ID.\n\t */\n\tconst std::string &getID() const { return _id; }\n\n\t/// Loads trajectory data from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader);\n\n\t/**\n\t * Gets the number of waypoints in this trajectory.\n\t * @return The number of waypoints.\n\t */\n\tsize_t getWaypointCount() const { return _waypoints.size(); }\n\n\t/**\n\t * Gets the zone index at a waypoint.\n\t * @param wp The waypoint.\n\t * @return The zone index.\n\t */\n\tsize_t getZone(size_t wp) const { return _waypoints[wp].zone; }\n\n\t/// Gets the altitude at a waypoint.\n\tstd::string getAltitude(size_t wp) const;\n\n\t/**\n\t * Applies the speed percentage at a waypoint to the base speed.\n\t * @param wp The waypoint.\n\t * @param baseSpeed The base speed.\n\t * @return The new speed after applying the percentage.\n\t */\n\tint applySpeedPercentage(size_t wp, int baseSpeed) const { return baseSpeed * _waypoints[wp].speed / 100; }\n\n\t/**\n\t * Gets the number of seconds UFOs should spend on the ground.\n\t * @return The number of seconds.\n\t */\n\tsize_t groundTimer() const { return _groundTimer; }\nprivate:\n\tstd::string _id;\n\tsize_t _groundTimer;\n\tstd::vector<TrajectoryWaypoint> _waypoints;\n};\n\n// helper overloads for (de)serialization\nbool read(ryml::ConstNodeRef const& n, TrajectoryWaypoint* val);\n\n}\n"
  },
  {
    "path": "src/Mod/Unit.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Unit.h\"\n#include \"../Engine/Exception.h\"\n#include \"../Engine/ScriptBind.h\"\n#include \"LoadYaml.h\"\n#include \"Mod.h\"\n#include \"Armor.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Creates a certain type of unit.\n * @param type String defining the type.\n */\nUnit::Unit(const std::string &type) :\n\t_type(type), _liveAlienName(Mod::STR_NULL), _showFullNameInAlienInventory(-1), _armor(nullptr), _standHeight(0), _kneelHeight(0), _floatHeight(0), _value(0),\n\t_moraleLossWhenKilled(100), _moveSound(-1), _intelligence(0), _aggression(0),\n\t_spotter(0), _sniper(0), _energyRecovery(30), _specab(SPECAB_NONE), _livingWeapon(false),\n\t_psiWeapon(\"ALIEN_PSI_WEAPON\"), _capturable(true), _canSurrender(false), _autoSurrender(false),\n\t_isLeeroyJenkins(false), _waitIfOutsideWeaponRange(false), _pickUpWeaponsMoreActively(-1), _avoidsFire(defBoolNullable),\n\t_vip(false), _cosmetic(false), _ignoredByAI(false),\n\t_canPanic(true), _canBeMindControlled(true), _berserkChance(-1)\n{\n}\n\n/**\n *\n */\nUnit::~Unit()\n{\n\tfor (auto* opts : _weightedBuiltInWeapons)\n\t{\n\t\tdelete opts;\n\t}\n}\n\n/**\n * Loads the unit from a YAML file.\n * @param node YAML node.\n * @param mod Mod for the unit.\n */\nvoid Unit::load(const YAML::YamlNodeReader& node, Mod *mod)\n{\n\tconst auto& reader = node.useIndex();\n\tif (const auto& parent = reader[\"refNode\"])\n\t{\n\t\tload(parent, mod);\n\t}\n\n\tmod->loadNameNull(_type, _civilianRecoveryTypeName, reader[\"civilianRecoveryType\"]);\n\tmod->loadNameNull(_type, _spawnedPersonName, reader[\"spawnedPersonName\"]);\n\tmod->loadNameNull(_type, _liveAlienName, reader[\"liveAlien\"]);\n\tif (reader[\"spawnedSoldier\"])\n\t{\n\t\t_spawnedSoldier = reader[\"spawnedSoldier\"].emitDescendants(YAML::YamlRootNodeReader(_spawnedSoldier, \"(spawned soldier template)\"));\n\t}\n\treader.tryRead(\"race\", _race);\n\treader.tryRead(\"showFullNameInAlienInventory\", _showFullNameInAlienInventory);\n\n\treader.tryRead(\"rank\", _rank);\n\t_stats.merge(reader[\"stats\"].readVal(_stats));\n\tmod->loadName(_type, _armorName, reader[\"armor\"]);\n\treader.tryRead(\"standHeight\", _standHeight);\n\treader.tryRead(\"kneelHeight\", _kneelHeight);\n\treader.tryRead(\"floatHeight\", _floatHeight);\n\tif (_floatHeight + _standHeight > 25)\n\t{\n\t\tthrow Exception(\"Error with unit \"+ _type +\": Unit height may not exceed 25\");\n\t}\n\treader.tryRead(\"value\", _value);\n\treader.tryRead(\"moraleLossWhenKilled\", _moraleLossWhenKilled);\n\treader.tryRead(\"intelligence\", _intelligence);\n\treader.tryRead(\"aggression\", _aggression);\n\treader.tryRead(\"spotter\", _spotter);\n\treader.tryRead(\"sniper\", _sniper);\n\treader.tryRead(\"energyRecovery\", _energyRecovery);\n\treader.tryRead(\"specab\", _specab);\n\treader.tryRead(\"spawnUnit\", _spawnUnitName);\n\treader.tryRead(\"livingWeapon\", _livingWeapon);\n\treader.tryRead(\"canSurrender\", _canSurrender);\n\treader.tryRead(\"autoSurrender\", _autoSurrender);\n\treader.tryRead(\"isLeeroyJenkins\", _isLeeroyJenkins);\n\treader.tryRead(\"waitIfOutsideWeaponRange\", _waitIfOutsideWeaponRange);\n\treader.tryRead(\"pickUpWeaponsMoreActively\", _pickUpWeaponsMoreActively);\n\tloadBoolNullable(_avoidsFire, reader[\"avoidsFire\"]);\n\treader.tryRead(\"meleeWeapon\", _meleeWeapon);\n\treader.tryRead(\"psiWeapon\", _psiWeapon);\n\treader.tryRead(\"capturable\", _capturable);\n\treader.tryRead(\"vip\", _vip);\n\treader.tryRead(\"cosmetic\", _cosmetic);\n\treader.tryRead(\"ignoredByAI\", _ignoredByAI);\n\treader.tryRead(\"canPanic\", _canPanic);\n\treader.tryRead(\"canBeMindControlled\", _canBeMindControlled);\n\treader.tryRead(\"berserkChance\", _berserkChance);\n\treader.tryRead(\"builtInWeaponSets\", _builtInWeaponsNames);\n\tif (reader[\"builtInWeapons\"])\n\t{\n\t\t_builtInWeaponsNames.push_back(reader[\"builtInWeapons\"].readVal<std::vector<std::string> >());\n\t}\n\tfor (const auto& weights : reader[\"weightedBuiltInWeaponSets\"].children())\n\t{\n\t\tWeightedOptions* nw = new WeightedOptions();\n\t\tnw->load(weights);\n\t\t_weightedBuiltInWeapons.push_back(nw);\n\t}\n\n\tmod->loadSoundOffset(_type, _deathSound, reader[\"deathSound\"], \"BATTLE.CAT\");\n\tmod->loadSoundOffset(_type, _panicSound, reader[\"panicSound\"], \"BATTLE.CAT\");\n\tmod->loadSoundOffset(_type, _berserkSound, reader[\"berserkSound\"], \"BATTLE.CAT\");\n\tmod->loadSoundOffset(_type, _aggroSound, reader[\"aggroSound\"], \"BATTLE.CAT\");\n\n\tmod->loadSoundOffset(_type, _selectUnitSound, reader[\"selectUnitSound\"], \"BATTLE.CAT\");\n\tmod->loadSoundOffset(_type, _startMovingSound, reader[\"startMovingSound\"], \"BATTLE.CAT\");\n\tmod->loadSoundOffset(_type, _selectWeaponSound, reader[\"selectWeaponSound\"], \"BATTLE.CAT\");\n\tmod->loadSoundOffset(_type, _annoyedSound, reader[\"annoyedSound\"], \"BATTLE.CAT\");\n\n\tmod->loadSoundOffset(_type, _moveSound, reader[\"moveSound\"], \"BATTLE.CAT\");\n}\n\n/**\n * Cross link with other rules\n */\nvoid Unit::afterLoad(const Mod* mod)\n{\n\tmod->linkRule(_armor, _armorName);\n\tmod->linkRule(_spawnUnit, _spawnUnitName);\n\tmod->linkRule(_builtInWeapons, _builtInWeaponsNames);\n\tif (_liveAlienName == Mod::STR_NULL)\n\t{\n\t\t_liveAlien = mod->getItem(_type, false); // this is optional default behavior\n\t}\n\telse\n\t{\n\t\tmod->linkRule(_liveAlien, _liveAlienName);\n\t}\n\n\tif (Mod::isEmptyRuleName(_civilianRecoveryTypeName) == false)\n\t{\n\t\tif (!isRecoverableAsEngineer() && !isRecoverableAsScientist())\n\t\t{\n\t\t\t_civilianRecoverySoldierType = mod->getSoldier(_civilianRecoveryTypeName, false);\n\t\t\tif (_civilianRecoverySoldierType)\n\t\t\t{\n\t\t\t\t_civilianRecoveryTypeName = \"\";\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tmod->linkRule(_civilianRecoveryItemType, _civilianRecoveryTypeName);\n\t\t\t}\n\t\t}\n\t\tassert(isRecoverableAsCivilian() && \"Check missing some cases\");\n\t}\n\n\tmod->checkForSoftError(_armor == nullptr, _type, \"Unit is missing armor\", LOG_ERROR);\n\tif (_armor)\n\t{\n\t\tif (_capturable && _armor->getCorpseBattlescape().front()->isRecoverable() && _spawnUnit == nullptr)\n\t\t{\n\t\t\tmod->checkForSoftError(\n\t\t\t\t_liveAlien == nullptr && !isRecoverableAsCivilian(),\n\t\t\t\t_type,\n\t\t\t\t\"This unit can be recovered (in theory), but there is no corresponding 'liveAlien:' or 'civilianRecoveryType:' to recover.\",\n\t\t\t\tLOG_INFO\n\t\t\t);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tstd::string s =\n\t\t\t\t!_capturable ? \"the unit is marked with 'capturable: false'\" :\n\t\t\t\t!_armor->getCorpseBattlescape().front()->isRecoverable() ? \"the first 'corpseBattle' item of the unit's armor is marked with 'recover: false'\" :\n\t\t\t\t_spawnUnit != nullptr ? \"the unit will be converted into another unit type on stun/kill/capture\" :\n\t\t\t\t\"???\";\n\n\t\t\tmod->checkForSoftError(\n\t\t\t\t_liveAlien\n\t\t\t\t&& _liveAlien->getVehicleUnit() == nullptr\n\t\t\t\t&& _spawnUnit == nullptr, // if unit is `_capturable` we can still get live species even if it can spawn unit\n\t\t\t\t_type,\n\t\t\t\t\"This unit has a corresponding item to recover, but still isn't recoverable. Reason: (\" + s + \"). Consider marking the unit with 'liveAlien: \\\"\\\"'.\",\n\t\t\t\tLOG_INFO\n\t\t\t);\n\t\t}\n\t}\n}\n\n/**\n * Returns the language string that names\n * this unit. Each unit type has a unique name.\n * @return The unit's name.\n */\nconst std::string& Unit::getType() const\n{\n\treturn _type;\n}\n\n/**\n * Returns the unit's stats data object.\n * @return The unit's stats.\n */\nconst UnitStats *Unit::getStats() const\n{\n\treturn &_stats;\n}\n\n/**\n * Returns the unit's height at standing.\n * @return The unit's height.\n */\nint Unit::getStandHeight() const\n{\n\treturn _standHeight;\n}\n\n/**\n * Returns the unit's height at kneeling.\n * @return The unit's kneeling height.\n */\nint Unit::getKneelHeight() const\n{\n\treturn _kneelHeight;\n}\n\n/**\n * Returns the unit's floating elevation.\n * @return The unit's floating height.\n */\nint Unit::getFloatHeight() const\n{\n\treturn _floatHeight;\n}\n\n/**\n * Gets the unit's armor type.\n * @return The unit's armor type.\n */\nconst Armor* Unit::getArmor() const\n{\n\treturn _armor;\n}\n\n/**\n * Gets the alien's race.\n * @return The alien's race.\n */\nstd::string Unit::getRace() const\n{\n\treturn _race;\n}\n\n/**\n * Gets the unit's rank.\n * @return The unit's rank.\n */\nstd::string Unit::getRank() const\n{\n\treturn _rank;\n}\n\n/**\n * Gets the unit's value - for scoring.\n * @return The unit's value.\n */\nint Unit::getValue() const\n{\n\treturn _value;\n}\n\n/**\n* Get the unit's death sounds.\n* @return List of sound IDs.\n*/\nconst std::vector<int> &Unit::getDeathSounds() const\n{\n\treturn _deathSound;\n}\n\n/**\n * Gets the unit's panic sounds.\n * @return List of sound IDs.\n */\nconst std::vector<int> &Unit::getPanicSounds() const\n{\n\treturn _panicSound;\n}\n\n/**\n * Gets the unit's berserk sounds.\n * @return List of sound IDs.\n */\nconst std::vector<int> &Unit::getBerserkSounds() const\n{\n\treturn _berserkSound;\n}\n\n/**\n * Gets the unit's move sound.\n * @return The id of the unit's move sound.\n */\nint Unit::getMoveSound() const\n{\n\treturn _moveSound;\n}\n\n/**\n * Gets the intelligence. This is the number of turns the AI remembers your troop positions.\n * @return The unit's intelligence.\n */\nint Unit::getIntelligence() const\n{\n\treturn _intelligence;\n}\n\n/**\n * Gets the aggression. Determines the chance of revenge and taking cover.\n * @return The unit's aggression.\n */\nint Unit::getAggression() const\n{\n\treturn _aggression;\n}\n\n/**\n * Gets the spotter score. Determines how many turns sniper AI units can act on this unit seeing your troops.\n * @return The unit's spotter value.\n */\nint Unit::getSpotterDuration() const\n{\n\t// Lazy balance - use -1 to make this the same as intelligence value\n\treturn (_spotter == -1) ? _intelligence : _spotter;\n}\n\n/**\n * Gets the sniper score. Determines the chances of firing from out of LOS on spotted units.\n * @return The unit's sniper value.\n */\nint Unit::getSniperPercentage() const\n{\n\treturn _sniper;\n}\n\n/**\n * Gets the unit's special ability.\n * @return The unit's specab.\n */\nint Unit::getSpecialAbility() const\n{\n\treturn (int)_specab;\n}\n\n/**\n * Gets the unit that is spawned when this one dies.\n * @return The unit's spawn unit.\n */\nconst Unit *Unit::getSpawnUnit() const\n{\n\treturn _spawnUnit;\n}\n\n/**\n * Gets the unit's aggro sounds (warcries).\n * @return List of sound IDs.\n */\nconst std::vector<int> &Unit::getAggroSounds() const\n{\n\treturn _aggroSound;\n}\n\n/**\n * How much energy does this unit recover per turn?\n * @return energy recovery amount.\n */\nint Unit::getEnergyRecovery() const\n{\n\treturn _energyRecovery;\n}\n\n/**\n * Checks if this unit is a living weapon.\n * a living weapon ignores any loadout that may be available to\n * its rank and uses the one associated with its race.\n * @return True if this unit is a living weapon.\n */\nbool Unit::isLivingWeapon() const\n{\n\treturn _livingWeapon;\n}\n\n/**\n * What is this unit's built in melee weapon (if any).\n * @return the name of the weapon.\n */\nconst std::string &Unit::getMeleeWeapon() const\n{\n\treturn _meleeWeapon;\n}\n\n/**\n* What is this unit's built in psi weapon (if any).\n* @return the name of the weapon.\n*/\nconst std::string &Unit::getPsiWeapon() const\n{\n\treturn _psiWeapon;\n}\n\n/**\n * What weapons does this unit have built in?\n * this is a vector of strings representing any\n * weapons that may be inherent to this creature.\n * note: unlike \"livingWeapon\" this is used in ADDITION to\n * any loadout or living weapon item that may be defined.\n * @return list of weapons that are integral to this unit.\n */\nconst std::vector<std::vector<const RuleItem*> > &Unit::getBuiltInWeapons() const\n{\n\treturn _builtInWeapons;\n}\n\n/**\n* Gets whether the alien can be captured alive.\n* @return a value determining whether the alien can be captured alive.\n*/\nbool Unit::getCapturable() const\n{\n\treturn _capturable;\n}\n\n/**\n* Checks if this unit can surrender.\n* @return True if this unit can surrender.\n*/\nbool Unit::canSurrender() const\n{\n\treturn _canSurrender || _autoSurrender;\n}\n\n/**\n* Checks if this unit surrenders automatically, if all other units surrendered too.\n* @return True if this unit auto-surrenders.\n*/\nbool Unit::autoSurrender() const\n{\n\treturn _autoSurrender;\n}\n\n/**\n * Is the unit afraid to pathfind through fire?\n * @return True if this unit has a penalty when pathfinding through fire.\n */\nbool Unit::avoidsFire() const\n{\n\treturn useBoolNullable(_avoidsFire, _specab < SPECAB_BURNFLOOR);\n}\n\n/**\n * Should alien inventory show full name (e.g. Sectoid Leader) or just the race (e.g. Sectoid)?\n * @return True if full name can be shown.\n */\nbool Unit::getShowFullNameInAlienInventory(Mod *mod) const\n{\n\tif (_showFullNameInAlienInventory != -1)\n\t{\n\t\treturn _showFullNameInAlienInventory == 0 ? false : true;\n\t}\n\treturn mod->getShowFullNameInAlienInventory();\n}\n\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tScript binding\n////////////////////////////////////////////////////////////\n\nnamespace\n{\n\nvoid getTypeScript(const Unit* r, ScriptText& txt)\n{\n\tif (r)\n\t{\n\t\ttxt = { r->getType().c_str() };\n\t\treturn;\n\t}\n\telse\n\t{\n\t\ttxt = ScriptText::empty;\n\t}\n}\n\nstd::string debugDisplayScript(const Unit* unit)\n{\n\tif (unit)\n\t{\n\t\tstd::string s;\n\t\ts += Unit::ScriptName;\n\t\ts += \"(name: \\\"\";\n\t\ts += unit->getType();\n\t\ts += \"\\\")\";\n\t\treturn s;\n\t}\n\telse\n\t{\n\t\treturn \"null\";\n\t}\n}\n\n} // namespace\n\nvoid Unit::ScriptRegister(ScriptParserBase* parser)\n{\n\tBind<Unit> un = { parser };\n\n\tun.add<&getTypeScript>(\"getType\");\n\tun.add<&Unit::getSpawnUnit>(\"getSpawnUnit\");\n\tun.add<&Unit::getCivilianRecoveryItemType>(\"getCivilianRecoveryItemType\");\n\t// un.add<&Unit::getCivilianRecoverySoldierType>(\"getCivilianRecoverySoldierType\"); //TODO: add `RuleSoldier` to scripts\n\tun.add<&Unit::getLiveAlienGeoscape>(\"getLiveAlienGeoscape\");\n\n\tun.addDebugDisplay<&debugDisplayScript>();\n}\n/**\n * Register StatAdjustment in script parser.\n * @param parser Script parser.\n */\nvoid StatAdjustment::ScriptRegister(ScriptParserBase* parser)\n{\n\tBind<StatAdjustment> sa = { parser };\n\n\tUnitStats::addGetStatsScript<&StatAdjustment::statGrowth>(sa, \"\");\n}\n\n// helper overloads for (de)serialization\nbool read(ryml::ConstNodeRef const& n, UnitStats* val)\n{\n\tYAML::YamlNodeReader reader(n);\n\treader.tryRead(\"tu\", val->tu);\n\treader.tryRead(\"stamina\", val->stamina);\n\treader.tryRead(\"health\", val->health);\n\treader.tryRead(\"bravery\", val->bravery);\n\treader.tryRead(\"reactions\", val->reactions);\n\treader.tryRead(\"firing\", val->firing);\n\treader.tryRead(\"throwing\", val->throwing);\n\treader.tryRead(\"strength\", val->strength);\n\treader.tryRead(\"psiStrength\", val->psiStrength);\n\treader.tryRead(\"psiSkill\", val->psiSkill);\n\treader.tryRead(\"melee\", val->melee);\n\treader.tryRead(\"mana\", val->mana);\n\treturn true;\n}\n\nvoid write(ryml::NodeRef* n, UnitStats const& val)\n{\n\tYAML::YamlNodeWriter writer(*n);\n\twriter.setAsMap();\n\twriter.write(\"tu\", val.tu);\n\twriter.write(\"stamina\", val.stamina);\n\twriter.write(\"health\", val.health);\n\twriter.write(\"bravery\", val.bravery);\n\twriter.write(\"reactions\", val.reactions);\n\twriter.write(\"firing\", val.firing);\n\twriter.write(\"throwing\", val.throwing);\n\twriter.write(\"strength\", val.strength);\n\twriter.write(\"psiStrength\", val.psiStrength);\n\twriter.write(\"psiSkill\", val.psiSkill);\n\twriter.write(\"melee\", val.melee);\n\twriter.write(\"mana\", val.mana);\n}\n\n} // namespace OpenXcom\n"
  },
  {
    "path": "src/Mod/Unit.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include <vector>\n#include \"../Engine/Yaml.h\"\n#include <SDL_types.h>\n#include \"../Engine/RNG.h\"\n#include \"../Savegame/WeightedOptions.h\"\n\nnamespace OpenXcom\n{\n\nclass Mod;\nclass Armor;\nclass RuleItem;\nclass RuleSoldier;\nclass ModScript;\nclass ScriptParserBase;\n\nenum SpecialAbility { SPECAB_NONE, SPECAB_EXPLODEONDEATH, SPECAB_BURNFLOOR, SPECAB_BURN_AND_EXPLODE };\nenum SpecialTileType : int;\nenum MovementType : int;\n\n\nenum ForcedTorso : Uint8 { TORSO_USE_GENDER, TORSO_ALWAYS_MALE, TORSO_ALWAYS_FEMALE };\nenum UnitSide : Uint8 { SIDE_FRONT, SIDE_LEFT, SIDE_RIGHT, SIDE_REAR, SIDE_UNDER, SIDE_MAX };\nenum UnitStatus {STATUS_STANDING, STATUS_WALKING, STATUS_FLYING, STATUS_TURNING, STATUS_AIMING, STATUS_COLLAPSING, STATUS_DEAD, STATUS_UNCONSCIOUS, STATUS_PANICKING, STATUS_BERSERK, STATUS_IGNORE_ME};\n\n/**\n * Faction naming \"absolute\":\n *\n * Xcom for FACTION_PLAYER.\n * Aliens for FACTION_HOSTILE.\n * Civilians for FACTION_NEUTRAL.\n *\n *\n * Faction naming \"relative\":\n *\n * Hostile: between Aliens and Xcom, between Aliens and Civilians.\n * Friendly: Xcom to Xcom, Aliens to Aliens, Civilians to Civilians.\n * Neutral: between Xcom and Civilians.\n * HostileCivilians: Special case for relation of Aliens to Civilians as it should be handled sometimes different than to Xcom.\n */\nenum UnitFaction : int {FACTION_NONE = -1, FACTION_PLAYER = 0, FACTION_HOSTILE = 1, FACTION_NEUTRAL = 2, FACTION_MAX };\nenum UnitBodyPart : int {BODYPART_HEAD, BODYPART_TORSO, BODYPART_RIGHTARM, BODYPART_LEFTARM, BODYPART_RIGHTLEG, BODYPART_LEFTLEG, BODYPART_MAX};\nenum UnitBodyPartEx {BODYPART_LEGS = BODYPART_MAX, BODYPART_COLLAPSING, BODYPART_ITEM_RIGHTHAND, BODYPART_ITEM_LEFTHAND, BODYPART_ITEM_FLOOR, BODYPART_ITEM_INVENTORY, BODYPART_LARGE_TORSO, BODYPART_LARGE_PROPULSION = BODYPART_LARGE_TORSO + 4, BODYPART_LARGE_TURRET = BODYPART_LARGE_PROPULSION + 4};\n\n\n/**\n * This struct holds some plain unit attribute data together.\n */\nstruct UnitStats\n{\n\tusing Type = Sint16;\n\tusing Ptr = Type UnitStats::*;\n\n\t/// Max value that is allowed to set to stat, less that max value allowed by type.\n\tconstexpr static int BaseStatLimit = 8000;\n\n\t/// How much more stun can be than health.\n\tconstexpr static int StunMultipler = 4;\n\t/// Max value allowed for stun value.\n\tconstexpr static int StunStatLimit = BaseStatLimit * StunMultipler;\n\n\t/// How much more over kill can go to negative than health.\n\tconstexpr static int OverkillMultipler = 4;\n\n\tType tu, stamina, health, bravery, reactions, firing, throwing, strength, psiStrength, psiSkill, melee, mana;\n\n\tUnitStats() : tu(0), stamina(0), health(0), bravery(0), reactions(0), firing(0), throwing(0), strength(0), psiStrength(0), psiSkill(0), melee(0), mana(0) {};\n\tUnitStats(int tu_, int stamina_, int health_, int bravery_, int reactions_, int firing_, int throwing_, int strength_, int psiStrength_, int psiSkill_, int melee_, int mana_) : tu(tu_), stamina(stamina_), health(health_), bravery(bravery_), reactions(reactions_), firing(firing_), throwing(throwing_), strength(strength_), psiStrength(psiStrength_), psiSkill(psiSkill_), melee(melee_), mana(mana_) {};\n\tUnitStats& operator+=(const UnitStats& stats) { tu += stats.tu; stamina += stats.stamina; health += stats.health; bravery += stats.bravery; reactions += stats.reactions; firing += stats.firing; throwing += stats.throwing; strength += stats.strength; psiStrength += stats.psiStrength; psiSkill += stats.psiSkill; melee += stats.melee; mana += stats.mana; return *this; }\n\tUnitStats operator+(const UnitStats& stats) const { return UnitStats(tu + stats.tu, stamina + stats.stamina, health + stats.health, bravery + stats.bravery, reactions + stats.reactions, firing + stats.firing, throwing + stats.throwing, strength + stats.strength, psiStrength + stats.psiStrength, psiSkill + stats.psiSkill, melee + stats.melee, mana + stats.mana); }\n\tUnitStats& operator-=(const UnitStats& stats) { tu -= stats.tu; stamina -= stats.stamina; health -= stats.health; bravery -= stats.bravery; reactions -= stats.reactions; firing -= stats.firing; throwing -= stats.throwing; strength -= stats.strength; psiStrength -= stats.psiStrength; psiSkill -= stats.psiSkill; melee -= stats.melee; mana -= stats.mana; return *this; }\n\tUnitStats operator-(const UnitStats& stats) const { return UnitStats(tu - stats.tu, stamina - stats.stamina, health - stats.health, bravery - stats.bravery, reactions - stats.reactions, firing - stats.firing, throwing - stats.throwing, strength - stats.strength, psiStrength - stats.psiStrength, psiSkill - stats.psiSkill, melee - stats.melee, mana - stats.mana); }\n\tUnitStats operator-() const { return UnitStats(-tu, -stamina, -health, -bravery, -reactions, -firing, -throwing, -strength, -psiStrength, -psiSkill, -melee, -mana); }\n\tvoid merge(const UnitStats& stats) { tu = (stats.tu ? stats.tu : tu); stamina = (stats.stamina ? stats.stamina : stamina); health = (stats.health ? stats.health : health); bravery = (stats.bravery ? stats.bravery : bravery); reactions = (stats.reactions ? stats.reactions : reactions); firing = (stats.firing ? stats.firing : firing); throwing = (stats.throwing ? stats.throwing : throwing); strength = (stats.strength ? stats.strength : strength); psiStrength = (stats.psiStrength ? stats.psiStrength : psiStrength); psiSkill = (stats.psiSkill ? stats.psiSkill : psiSkill); melee = (stats.melee ? stats.melee : melee); mana = (stats.mana ? stats.mana : mana); };\n\n\ttemplate<typename Func>\n\tstatic void fieldLoop(Func f)\n\t{\n\t\tconstexpr static Ptr allFields[] =\n\t\t{\n\t\t\t&UnitStats::tu, &UnitStats::stamina,\n\t\t\t&UnitStats::health, &UnitStats::bravery,\n\t\t\t&UnitStats::reactions, &UnitStats::firing,\n\t\t\t&UnitStats::throwing, &UnitStats::strength,\n\t\t\t&UnitStats::psiStrength, &UnitStats::psiSkill,\n\t\t\t&UnitStats::melee, &UnitStats::mana,\n\t\t};\n\n\t\tfor (Ptr p : allFields)\n\t\t{\n\t\t\tf(p);\n\t\t}\n\t}\n\n\tstatic UnitStats templateMerge(const UnitStats& origStats, const UnitStats& fixedStats)\n\t{\n\t\tUnitStats r;\n\t\tfieldLoop(\n\t\t\t[&](Ptr p)\n\t\t\t{\n\t\t\t\tif ((fixedStats.*p) == -1)\n\t\t\t\t{\n\t\t\t\t\t(r.*p) = 0;\n\t\t\t\t}\n\t\t\t\telse if ((fixedStats.*p) != 0)\n\t\t\t\t{\n\t\t\t\t\t(r.*p) = (fixedStats.*p);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t(r.*p) = (origStats.*p);\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\t\treturn r;\n\t}\n\n\t/*\n\t * Soft limit definition:\n\t * 1. if the statChange is zero or negative, keep statChange as it is (i.e. don't apply any limits)\n\t * 2. if the statChange is positive and currentStats <= upperBound, consider upperBound   (i.e. set result to min(statChange, upperBound-currentStats))\n\t * 3. if the statChange is positive and currentStats >  upperBound, keep the currentStats (i.e. set result to 0)\n\t */\n\tstatic UnitStats softLimit(const UnitStats& statChange, const UnitStats& currentStats, const UnitStats& upperBound)\n\t{\n\t\tUnitStats r;\n\t\tfieldLoop(\n\t\t\t[&](Ptr p)\n\t\t\t{\n\t\t\t\tif ((statChange.*p) <= 0)\n\t\t\t\t{\n\t\t\t\t\t// 1. keep statChange\n\t\t\t\t\t(r.*p) = (statChange.*p);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif ((currentStats.*p) <= (upperBound.*p))\n\t\t\t\t\t{\n\t\t\t\t\t\t// 2. consider upperBound\n\t\t\t\t\t\tSint16 tmp = (upperBound.*p) - (currentStats.*p);\n\t\t\t\t\t\t(r.*p) = std::min((statChange.*p), tmp);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// 3. keep currentStats\n\t\t\t\t\t\t(r.*p) = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\t\treturn r;\n\t}\n\n\tstatic UnitStats combine(const UnitStats &mask, const UnitStats &keep, const UnitStats &reroll)\n\t{\n\t\tUnitStats r;\n\t\tfieldLoop(\n\t\t\t[&](Ptr p)\n\t\t\t{\n\t\t\t\tif ((mask.*p))\n\t\t\t\t{\n\t\t\t\t\t(r.*p) = (reroll.*p);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t(r.*p) = (keep.*p);\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\t\treturn r;\n\t}\n\n\tstatic UnitStats random(const UnitStats &a, const UnitStats &b)\n\t{\n\t\tUnitStats r;\n\t\tfieldLoop(\n\t\t\t[&](Ptr p)\n\t\t\t{\n\t\t\t\tSint16 min = std::min((a.*p), (b.*p));\n\t\t\t\tSint16 max = std::max((a.*p), (b.*p));\n\t\t\t\tif (min == max)\n\t\t\t\t{\n\t\t\t\t\t(r.*p) = max;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tSint16 rnd = RNG::generate(min, max);\n\t\t\t\t\t(r.*p) = rnd;\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\t\treturn r;\n\t}\n\n\tstatic UnitStats isRandom(const UnitStats &a, const UnitStats &b)\n\t{\n\t\tUnitStats r;\n\t\tfieldLoop(\n\t\t\t[&](Ptr p)\n\t\t\t{\n\t\t\t\tif ( ((a.*p) != 0 || (b.*p) != 0) && (a.*p) != (b.*p))\n\t\t\t\t{\n\t\t\t\t\t(r.*p) = 1;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t(r.*p) = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\t\treturn r;\n\t}\n\n\tstatic UnitStats percent(const UnitStats& base, const UnitStats& percent, int multipler = 1)\n\t{\n\t\tUnitStats r;\n\t\tfieldLoop(\n\t\t\t[&](Ptr p)\n\t\t\t{\n\t\t\t\t(r.*p) = (base.*p) * (percent.*p) * multipler / 100;\n\t\t\t}\n\t\t);\n\t\treturn r;\n\t}\n\n\tstatic UnitStats scalar(int i)\n\t{\n\t\tUnitStats r;\n\t\tfieldLoop(\n\t\t\t[&](Ptr p)\n\t\t\t{\n\t\t\t\t(r.*p) = i;\n\t\t\t}\n\t\t);\n\t\treturn r;\n\t}\n\n\tstatic UnitStats obeyFixedMinimum(const UnitStats &a)\n\t{\n\t\t// minimum 1 for health, minimum 0 for other stats (note to self: it might be worth considering minimum 10 for bravery in the future)\n\t\tstatic const UnitStats fixedMinimum = UnitStats(0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0);\n\t\treturn max(a, fixedMinimum);\n\t}\n\n\tstatic UnitStats max(const UnitStats& a, const UnitStats& b)\n\t{\n\t\tUnitStats r;\n\t\tfieldLoop(\n\t\t\t[&](Ptr p)\n\t\t\t{\n\t\t\t\t(r.*p) = std::max((a.*p), (b.*p));\n\t\t\t}\n\t\t);\n\t\treturn r;\n\t}\n\n\tstatic UnitStats min(const UnitStats& a, const UnitStats& b)\n\t{\n\t\tUnitStats r;\n\t\tfieldLoop(\n\t\t\t[&](Ptr p)\n\t\t\t{\n\t\t\t\t(r.*p) = std::min((a.*p), (b.*p));\n\t\t\t}\n\t\t);\n\t\treturn r;\n\t}\n\n\ttemplate<typename T, UnitStats T::*Stat, Ptr StatMax>\n\tstatic void getMaxStatScript(const T *t, int& val)\n\t{\n\t\tif (t)\n\t\t{\n\t\t\tval = ((t->*Stat).*StatMax);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tval = 0;\n\t\t}\n\t}\n\n\ttemplate<typename T, UnitStats T::*Stat, Ptr StatMax>\n\tstatic void setMaxStatScript(T *t, int val)\n\t{\n\t\tif (t)\n\t\t{\n\t\t\tval = std::min(std::max(val, 1), BaseStatLimit);\n\t\t\t((t->*Stat).*StatMax) = val;\n\t\t}\n\t}\n\n\ttemplate<typename T, UnitStats T::*Stat, Ptr StatMax>\n\tstatic void addMaxStatScript(T *t, int val)\n\t{\n\t\tif (t)\n\t\t{\n\t\t\t//limit range to prevent overflow\n\t\t\tval = std::min(std::max(val, -BaseStatLimit), BaseStatLimit);\n\t\t\tsetMaxStatScript<T, Stat, StatMax>(t, val + ((t->*Stat).*StatMax));\n\t\t}\n\t}\n\n\ttemplate<typename T, UnitStats T::*Stat, int T::*Curr, Ptr StatMax>\n\tstatic void setMaxAndCurrStatScript(T *t, int val)\n\t{\n\t\tif (t)\n\t\t{\n\t\t\tval = std::min(std::max(val, 1), BaseStatLimit);\n\t\t\t((t->*Stat).*StatMax) = val;\n\n\t\t\t//update current value\n\t\t\tif ((t->*Curr) > val)\n\t\t\t{\n\t\t\t\t(t->*Curr) = val;\n\t\t\t}\n\t\t}\n\t}\n\n\ttemplate<typename T, UnitStats T::*Stat, int T::*Curr, Ptr StatMax>\n\tstatic void addMaxAndCurrStatScript(T *t, int val)\n\t{\n\t\tif (t)\n\t\t{\n\t\t\t//limit range to prevent overflow\n\t\t\tval = std::min(std::max(val, -BaseStatLimit), BaseStatLimit);\n\t\t\tsetMaxAndCurrStatScript<T, Stat, Curr, StatMax>(t, val + ((t->*Stat).*StatMax));\n\t\t}\n\t}\n\n\ttemplate<auto Stat, typename TBind>\n\tstatic void addGetStatsScript(TBind& b, std::string prefix, bool skipResorcesStats = false)\n\t{\n\t\tif (!skipResorcesStats)\n\t\t{\n\t\t\tb.template add<&getMaxStatScript<typename TBind::Type, Stat, &UnitStats::tu>>(prefix + \"getTimeUnits\");\n\t\t\tb.template add<&getMaxStatScript<typename TBind::Type, Stat, &UnitStats::stamina>>(prefix + \"getStamina\");\n\t\t\tb.template add<&getMaxStatScript<typename TBind::Type, Stat, &UnitStats::health>>(prefix + \"getHealth\");\n\t\t\tb.template add<&getMaxStatScript<typename TBind::Type, Stat, &UnitStats::mana>>(prefix + \"getManaPool\");\n\t\t}\n\n\t\tb.template add<&getMaxStatScript<typename TBind::Type, Stat, &UnitStats::bravery>>(prefix + \"getBravery\");\n\t\tb.template add<&getMaxStatScript<typename TBind::Type, Stat, &UnitStats::reactions>>(prefix + \"getReactions\");\n\t\tb.template add<&getMaxStatScript<typename TBind::Type, Stat, &UnitStats::firing>>(prefix + \"getFiring\");\n\t\tb.template add<&getMaxStatScript<typename TBind::Type, Stat, &UnitStats::throwing>>(prefix + \"getThrowing\");\n\t\tb.template add<&getMaxStatScript<typename TBind::Type, Stat, &UnitStats::strength>>(prefix + \"getStrength\");\n\t\tb.template add<&getMaxStatScript<typename TBind::Type, Stat, &UnitStats::psiStrength>>(prefix + \"getPsiStrength\");\n\t\tb.template add<&getMaxStatScript<typename TBind::Type, Stat, &UnitStats::psiSkill>>(prefix + \"getPsiSkill\");\n\t\tb.template add<&getMaxStatScript<typename TBind::Type, Stat, &UnitStats::melee>>(prefix + \"getMelee\");\n\t}\n\n\ttemplate<auto Stat, typename TBind>\n\tstatic void addSetStatsScript(TBind& b, std::string prefix, bool skipResorcesStats = false)\n\t{\n\t\tif (!skipResorcesStats)\n\t\t{\n\t\t\tb.template add<&setMaxStatScript<typename TBind::Type, Stat, &UnitStats::tu>>(prefix + \"setTimeUnits\");\n\t\t\tb.template add<&setMaxStatScript<typename TBind::Type, Stat, &UnitStats::stamina>>(prefix + \"setStamina\");\n\t\t\tb.template add<&setMaxStatScript<typename TBind::Type, Stat, &UnitStats::health>>(prefix + \"setHealth\");\n\t\t\tb.template add<&setMaxStatScript<typename TBind::Type, Stat, &UnitStats::mana>>(prefix + \"setManaPool\");\n\n\t\t\tb.template add<&addMaxStatScript<typename TBind::Type, Stat, &UnitStats::tu>>(prefix + \"addTimeUnits\");\n\t\t\tb.template add<&addMaxStatScript<typename TBind::Type, Stat, &UnitStats::stamina>>(prefix + \"addStamina\");\n\t\t\tb.template add<&addMaxStatScript<typename TBind::Type, Stat, &UnitStats::health>>(prefix + \"addHealth\");\n\t\t\tb.template add<&addMaxStatScript<typename TBind::Type, Stat, &UnitStats::mana>>(prefix + \"addManaPool\");\n\t\t}\n\n\t\tb.template add<&setMaxStatScript<typename TBind::Type, Stat, &UnitStats::bravery>>(prefix + \"setBravery\");\n\t\tb.template add<&setMaxStatScript<typename TBind::Type, Stat, &UnitStats::reactions>>(prefix + \"setReactions\");\n\t\tb.template add<&setMaxStatScript<typename TBind::Type, Stat, &UnitStats::firing>>(prefix + \"setFiring\");\n\t\tb.template add<&setMaxStatScript<typename TBind::Type, Stat, &UnitStats::throwing>>(prefix + \"setThrowing\");\n\t\tb.template add<&setMaxStatScript<typename TBind::Type, Stat, &UnitStats::strength>>(prefix + \"setStrength\");\n\t\tb.template add<&setMaxStatScript<typename TBind::Type, Stat, &UnitStats::psiStrength>>(prefix + \"setPsiStrength\");\n\t\tb.template add<&setMaxStatScript<typename TBind::Type, Stat, &UnitStats::psiSkill>>(prefix + \"setPsiSkill\");\n\t\tb.template add<&setMaxStatScript<typename TBind::Type, Stat, &UnitStats::melee>>(prefix + \"setMelee\");\n\n\t\tb.template add<&addMaxStatScript<typename TBind::Type, Stat, &UnitStats::bravery>>(prefix + \"addBravery\");\n\t\tb.template add<&addMaxStatScript<typename TBind::Type, Stat, &UnitStats::reactions>>(prefix + \"addReactions\");\n\t\tb.template add<&addMaxStatScript<typename TBind::Type, Stat, &UnitStats::firing>>(prefix + \"addFiring\");\n\t\tb.template add<&addMaxStatScript<typename TBind::Type, Stat, &UnitStats::throwing>>(prefix + \"addThrowing\");\n\t\tb.template add<&addMaxStatScript<typename TBind::Type, Stat, &UnitStats::strength>>(prefix + \"addStrength\");\n\t\tb.template add<&addMaxStatScript<typename TBind::Type, Stat, &UnitStats::psiStrength>>(prefix + \"addPsiStrength\");\n\t\tb.template add<&addMaxStatScript<typename TBind::Type, Stat, &UnitStats::psiSkill>>(prefix + \"addPsiSkill\");\n\t\tb.template add<&addMaxStatScript<typename TBind::Type, Stat, &UnitStats::melee>>(prefix + \"addMelee\");\n\t}\n\n\ttemplate<auto Stat, auto CurrTu, auto CurrEnergy, auto CurrHealth, auto CurrMana, typename TBind>\n\tstatic void addSetStatsWithCurrScript(TBind& b, std::string prefix)\n\t{\n\t\t// when we change stats of BattleUnit its resources should be adjust.\n\t\tb.template add<&setMaxAndCurrStatScript<typename TBind::Type, Stat, CurrTu, &UnitStats::tu>>(prefix + \"setTimeUnits\");\n\t\tb.template add<&setMaxAndCurrStatScript<typename TBind::Type, Stat, CurrEnergy, &UnitStats::stamina>>(prefix + \"setStamina\");\n\t\tb.template add<&setMaxAndCurrStatScript<typename TBind::Type, Stat, CurrHealth, &UnitStats::health>>(prefix + \"setHealth\");\n\t\tb.template add<&setMaxAndCurrStatScript<typename TBind::Type, Stat, CurrMana, &UnitStats::mana>>(prefix + \"setManaPool\");\n\n\t\tb.template add<&addMaxAndCurrStatScript<typename TBind::Type, Stat, CurrTu, &UnitStats::tu>>(prefix + \"addTimeUnits\");\n\t\tb.template add<&addMaxAndCurrStatScript<typename TBind::Type, Stat, CurrEnergy, &UnitStats::stamina>>(prefix + \"addStamina\");\n\t\tb.template add<&addMaxAndCurrStatScript<typename TBind::Type, Stat, CurrHealth, &UnitStats::health>>(prefix + \"addHealth\");\n\t\tb.template add<&addMaxAndCurrStatScript<typename TBind::Type, Stat, CurrMana, &UnitStats::mana>>(prefix + \"addManaPool\");\n\n\t\taddSetStatsScript<Stat>(b, prefix, true);\n\t}\n};\n\nstruct StatAdjustment\n{\n\t/// Name of class used in script.\n\tstatic constexpr const char *ScriptName = \"StatAdjustment\";\n\t/// Register all useful function used by script.\n\tstatic void ScriptRegister(ScriptParserBase* parser);\n\n\tUnitStats statGrowth;\n\tUnitStats statGrowthAbs;\n\tint growthMultiplier;\n\tdouble aimMultiplier;\n\tdouble armorMultiplier;\n\tint armorMultiplierAbs;\n};\n\n/**\n * Represents the static data for a unit that is generated on the battlescape, this includes: HWPs, aliens and civilians.\n * @sa Soldier BattleUnit\n */\nclass Unit\n{\nprivate:\n\tstd::string _type;\n\tstd::string _civilianRecoveryTypeName, _spawnedPersonName, _liveAlienName;\n\tconst RuleSoldier* _civilianRecoverySoldierType = nullptr;\n\tconst RuleItem* _civilianRecoveryItemType = nullptr;\n\tYAML::YamlString _spawnedSoldier;\n\tstd::string _race;\n\tint _showFullNameInAlienInventory;\n\tstd::string _rank;\n\tUnitStats _stats;\n\tstd::string _armorName;\n\tconst Armor* _armor;\n\tint _standHeight, _kneelHeight, _floatHeight;\n\tstd::vector<int> _deathSound, _panicSound, _berserkSound, _aggroSound;\n\tstd::vector<int> _selectUnitSound, _startMovingSound, _selectWeaponSound, _annoyedSound;\n\tint _value, _moraleLossWhenKilled, _moveSound;\n\tint _intelligence, _aggression, _spotter, _sniper, _energyRecovery;\n\tSpecialAbility _specab;\n\tconst RuleItem* _liveAlien = nullptr;\n\tconst Unit *_spawnUnit = nullptr;\n\tstd::string _spawnUnitName;\n\tbool _livingWeapon;\n\tstd::string _meleeWeapon, _psiWeapon;\n\tstd::vector<std::vector<std::string> > _builtInWeaponsNames;\n\tstd::vector<std::vector<const RuleItem*> > _builtInWeapons;\n\tstd::vector<WeightedOptions*> _weightedBuiltInWeapons;\n\tbool _capturable;\n\tbool _canSurrender, _autoSurrender;\n\tbool _isLeeroyJenkins;\n\tbool _waitIfOutsideWeaponRange;\n\tint _pickUpWeaponsMoreActively;\n\tSint8 _avoidsFire;\n\tbool _vip;\n\tbool _cosmetic, _ignoredByAI;\n\tbool _canPanic;\n\tbool _canBeMindControlled;\n\tint _berserkChance;\n\npublic:\n\t/// Creates a blank unit ruleset.\n\tUnit(const std::string &type);\n\t/// Cleans up the unit ruleset.\n\t~Unit();\n\t/// Loads the unit data from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader, Mod *mod);\n\t/// Cross link with other rules.\n\tvoid afterLoad(const Mod* mod);\n\n\t/// Gets the unit's type.\n\tconst std::string& getType() const;\n\n\t/// Gets if unit can be recovered as civilian.\n\tbool isRecoverableAsCivilian() const { return _civilianRecoveryTypeName.empty() == false || _civilianRecoverySoldierType || _civilianRecoveryItemType; }\n\t/// Gets if engineer is recovered when a civilian is saved.\n\tbool isRecoverableAsEngineer() const { return _civilianRecoveryTypeName == \"STR_ENGINEER\"; }\n\t/// Gets if scientist is recovered when a civilian is saved.\n\tbool isRecoverableAsScientist() const { return _civilianRecoveryTypeName == \"STR_SCIENTIST\"; }\n\t/// Gets soldier type that is recovered when a civilian is saved.\n\tconst RuleSoldier* getCivilianRecoverySoldierType() const { return _civilianRecoverySoldierType; }\n\t/// Gets item type that is recovered when a civilian is saved.\n\tconst RuleItem* getCivilianRecoveryItemType() const { return _civilianRecoveryItemType; }\n\t/// Gets the custom name of the \"spawned person\".\n\tconst std::string &getSpawnedPersonName() const { return _spawnedPersonName; }\n\t/// Gets the spawned soldier template.\n\tconst YAML::YamlString &getSpawnedSoldierTemplate() const { return _spawnedSoldier; }\n\n\t/// Gets the unit's stats.\n\tconst UnitStats *getStats() const;\n\t/// Gets the unit's height when standing.\n\tint getStandHeight() const;\n\t/// Gets the unit's height when kneeling.\n\tint getKneelHeight() const;\n\t/// Gets the unit's float elevation.\n\tint getFloatHeight() const;\n\t/// Gets the armor type.\n\tconst Armor* getArmor() const;\n\t/// Gets the alien race type.\n\tstd::string getRace() const;\n\t/// Gets the alien rank.\n\tstd::string getRank() const;\n\t/// Gets the value - for score calculation.\n\tint getValue() const;\n\t/// Percentage modifier for morale loss when this unit is killed.\n\tint getMoraleLossWhenKilled() const { return _moraleLossWhenKilled; };\n\t/// Gets the death sound id.\n\tconst std::vector<int> &getDeathSounds() const;\n\t/// Gets the unit's panic sounds.\n\tconst std::vector<int> &getPanicSounds() const;\n\t/// Gets the unit's berserk sounds.\n\tconst std::vector<int> &getBerserkSounds() const;\n\t/// Gets the unit's \"select unit\" sounds.\n\tconst std::vector<int> &getSelectUnitSounds() const { return _selectUnitSound; }\n\t/// Gets the unit's \"start moving\" sounds.\n\tconst std::vector<int> &getStartMovingSounds() const { return _startMovingSound; }\n\t/// Gets the unit's \"select weapon\" sounds.\n\tconst std::vector<int> &getSelectWeaponSounds() const { return _selectWeaponSound; }\n\t/// Gets the unit's \"annoyed\" sounds.\n\tconst std::vector<int> &getAnnoyedSounds() const { return _annoyedSound; }\n\t/// Gets the move sound id.\n\tint getMoveSound() const;\n\t/// Gets the intelligence. This is the number of turns AI remembers your troop positions.\n\tint getIntelligence() const;\n\t/// Gets the aggression. Determines the chance of revenge and taking cover.\n\tint getAggression() const;\n\t/// Gets the spotter score. This is the number of turns sniper AI units can use spotting info from this unit.\n\tint getSpotterDuration() const;\n\t/// Gets the sniper score. Determines chance of acting on information gained by spotter units.\n\tint getSniperPercentage() const;\n\t/// Gets the alien's special ability.\n\tint getSpecialAbility() const;\n\t/// Gets the Geoscape live alien item.\n\tconst RuleItem* getLiveAlienGeoscape() const { return _liveAlien; }\n\t/// Gets the unit's spawn unit.\n\tconst Unit *getSpawnUnit() const;\n\t/// Gets the unit's warcries.\n\tconst std::vector<int> &getAggroSounds() const;\n\t/// Gets how much energy this unit recovers per turn.\n\tint getEnergyRecovery() const;\n\t/// Checks if this unit has a built in weapon.\n\tbool isLivingWeapon() const;\n\t/// Gets the name of any melee weapon that may be built in to this unit.\n\tconst std::string &getMeleeWeapon() const;\n\t/// Gets the name of any psi weapon that may be built in to this unit.\n\tconst std::string &getPsiWeapon() const;\n\t/// Gets a vector of integrated items this unit has available.\n\tconst std::vector<std::vector<const RuleItem*> > &getBuiltInWeapons() const;\n\t/// Gets a vector of integrated item options this unit has available.\n\tconst std::vector<WeightedOptions*>& getWeightedBuiltInWeapons() const { return _weightedBuiltInWeapons; }\n\t/// Gets whether the alien can be captured alive.\n\tbool getCapturable() const;\n\t/// Checks if this unit can surrender.\n\tbool canSurrender() const;\n\t/// Checks if this unit surrenders automatically, if all other units surrendered too.\n\tbool autoSurrender() const;\n\tbool isLeeroyJenkins() const { return _isLeeroyJenkins; };\n\t/// Should the unit get \"stuck\" trying to fire from outside of weapon range? Vanilla bug, that may serve as \"feature\" in rare cases.\n\tbool waitIfOutsideWeaponRange() const { return _waitIfOutsideWeaponRange; };\n\t/// Should the unit try to pick up weapons more actively?\n\tint getPickUpWeaponsMoreActively() const { return _pickUpWeaponsMoreActively; }\n\t/// Is the unit afraid to pathfind through fire?\n\tbool avoidsFire() const;\n\t/// Should alien inventory show full name (e.g. Sectoid Leader) or just the race (e.g. Sectoid)?\n\tbool getShowFullNameInAlienInventory(Mod *mod) const;\n\t/// Is this a VIP unit?\n\tbool isVIP() const { return _vip; }\n\t/// Is this only a cosmetic unit?\n\tbool isCosmetic() const { return _cosmetic; }\n\t/// Should this unit be ignored by the AI?\n\tbool isIgnoredByAI() const { return _ignoredByAI; }\n\t/// Checks if this unit can panic.\n\tbool canPanic() const { return _canPanic; }\n\t/// Checks if this unit can be mind controlled.\n\tbool canBeMindControlled() const { return _canBeMindControlled; }\n\t/// Gets the probability of unit berserking when panicked.\n\tint getBerserkChance() const { return _berserkChance; }\n\n\t/// Name of class used in script.\n\tstatic constexpr const char *ScriptName = \"RuleUnit\";\n\t/// Register all useful function used by script.\n\tstatic void ScriptRegister(ScriptParserBase* parser);\n};\n\n// helper overloads for (de)serialization\nbool read(ryml::ConstNodeRef const& n, UnitStats* val);\nvoid write(ryml::NodeRef* n, UnitStats const& val);\n\n}\n"
  },
  {
    "path": "src/OpenXcom.2010.sln",
    "content": "﻿\r\nMicrosoft Visual Studio Solution File, Format Version 11.00\r\n# Visual C++ Express 2010\r\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"OpenXcom\", \"OpenXcom.2010.vcxproj\", \"{D8F55ED4-1A4E-4111-8E83-153CF91FE25A}\"\r\nEndProject\r\nGlobal\r\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\r\n\t\tDebug|Win32 = Debug|Win32\r\n\t\tDebug|x64 = Debug|x64\r\n\t\tRelease_XP|Win32 = Release_XP|Win32\r\n\t\tRelease_XP|x64 = Release_XP|x64\r\n\t\tRelease|Win32 = Release|Win32\r\n\t\tRelease|x64 = Release|x64\r\n\tEndGlobalSection\r\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\r\n\t\t{D8F55ED4-1A4E-4111-8E83-153CF91FE25A}.Debug|Win32.ActiveCfg = Debug|Win32\r\n\t\t{D8F55ED4-1A4E-4111-8E83-153CF91FE25A}.Debug|Win32.Build.0 = Debug|Win32\r\n\t\t{D8F55ED4-1A4E-4111-8E83-153CF91FE25A}.Debug|x64.ActiveCfg = Debug|x64\r\n\t\t{D8F55ED4-1A4E-4111-8E83-153CF91FE25A}.Debug|x64.Build.0 = Debug|x64\r\n\t\t{D8F55ED4-1A4E-4111-8E83-153CF91FE25A}.Release_XP|Win32.ActiveCfg = Release_XP|Win32\r\n\t\t{D8F55ED4-1A4E-4111-8E83-153CF91FE25A}.Release_XP|Win32.Build.0 = Release_XP|Win32\r\n\t\t{D8F55ED4-1A4E-4111-8E83-153CF91FE25A}.Release_XP|x64.ActiveCfg = Release_XP|x64\r\n\t\t{D8F55ED4-1A4E-4111-8E83-153CF91FE25A}.Release_XP|x64.Build.0 = Release_XP|x64\r\n\t\t{D8F55ED4-1A4E-4111-8E83-153CF91FE25A}.Release|Win32.ActiveCfg = Release|Win32\r\n\t\t{D8F55ED4-1A4E-4111-8E83-153CF91FE25A}.Release|Win32.Build.0 = Release|Win32\r\n\t\t{D8F55ED4-1A4E-4111-8E83-153CF91FE25A}.Release|x64.ActiveCfg = Release|x64\r\n\t\t{D8F55ED4-1A4E-4111-8E83-153CF91FE25A}.Release|x64.Build.0 = Release|x64\r\n\tEndGlobalSection\r\n\tGlobalSection(SolutionProperties) = preSolution\r\n\t\tHideSolutionNode = FALSE\r\n\tEndGlobalSection\r\nEndGlobal\r\n"
  },
  {
    "path": "src/OpenXcom.2010.vcxproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project DefaultTargets=\"Build\" ToolsVersion=\"14.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\r\n  <ItemGroup Label=\"ProjectConfigurations\">\r\n    <ProjectConfiguration Include=\"Debug|Win32\">\r\n      <Configuration>Debug</Configuration>\r\n      <Platform>Win32</Platform>\r\n    </ProjectConfiguration>\r\n    <ProjectConfiguration Include=\"Debug|x64\">\r\n      <Configuration>Debug</Configuration>\r\n      <Platform>x64</Platform>\r\n    </ProjectConfiguration>\r\n    <ProjectConfiguration Include=\"Release_XP|Win32\">\r\n      <Configuration>Release_XP</Configuration>\r\n      <Platform>Win32</Platform>\r\n    </ProjectConfiguration>\r\n    <ProjectConfiguration Include=\"Release_XP|x64\">\r\n      <Configuration>Release_XP</Configuration>\r\n      <Platform>x64</Platform>\r\n    </ProjectConfiguration>\r\n    <ProjectConfiguration Include=\"Release|Win32\">\r\n      <Configuration>Release</Configuration>\r\n      <Platform>Win32</Platform>\r\n    </ProjectConfiguration>\r\n    <ProjectConfiguration Include=\"Release|x64\">\r\n      <Configuration>Release</Configuration>\r\n      <Platform>x64</Platform>\r\n    </ProjectConfiguration>\r\n  </ItemGroup>\r\n  <PropertyGroup Label=\"Globals\">\r\n    <ProjectName>OpenXcom</ProjectName>\r\n    <ProjectGuid>{D8F55ED4-1A4E-4111-8E83-153CF91FE25A}</ProjectGuid>\r\n    <RootNamespace>OpenXcom</RootNamespace>\r\n    <Keyword>Win32Proj</Keyword>\r\n  </PropertyGroup>\r\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\r\n    <ConfigurationType>Application</ConfigurationType>\r\n    <CharacterSet>Unicode</CharacterSet>\r\n    <WholeProgramOptimization>true</WholeProgramOptimization>\r\n    <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>\r\n    <PreferredToolArchitecture>x64</PreferredToolArchitecture>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release_XP|Win32'\" Label=\"Configuration\">\r\n    <ConfigurationType>Application</ConfigurationType>\r\n    <CharacterSet>Unicode</CharacterSet>\r\n    <WholeProgramOptimization>true</WholeProgramOptimization>\r\n    <PlatformToolset>v141_xp</PlatformToolset>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\" Label=\"Configuration\">\r\n    <ConfigurationType>Application</ConfigurationType>\r\n    <CharacterSet>Unicode</CharacterSet>\r\n    <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>\r\n    <PreferredToolArchitecture>x64</PreferredToolArchitecture>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release_XP|x64'\" Label=\"Configuration\">\r\n    <ConfigurationType>Application</ConfigurationType>\r\n    <CharacterSet>Unicode</CharacterSet>\r\n    <PlatformToolset>v141_xp</PlatformToolset>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\r\n    <ConfigurationType>Application</ConfigurationType>\r\n    <CharacterSet>Unicode</CharacterSet>\r\n    <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>\r\n    <PreferredToolArchitecture>x64</PreferredToolArchitecture>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\" Label=\"Configuration\">\r\n    <ConfigurationType>Application</ConfigurationType>\r\n    <CharacterSet>Unicode</CharacterSet>\r\n    <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>\r\n    <PreferredToolArchitecture>x64</PreferredToolArchitecture>\r\n  </PropertyGroup>\r\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\r\n  <ImportGroup Label=\"ExtensionSettings\">\r\n  </ImportGroup>\r\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"PropertySheets\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Release_XP|Win32'\" Label=\"PropertySheets\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\" Label=\"PropertySheets\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Release_XP|x64'\" Label=\"PropertySheets\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"PropertySheets\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\" Label=\"PropertySheets\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <PropertyGroup Label=\"UserMacros\" />\r\n  <PropertyGroup>\r\n    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>\r\n    <OutDir Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">$(ProjectDir)..\\bin\\$(Platform)\\$(Configuration)\\</OutDir>\r\n    <OutDir Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">$(ProjectDir)..\\bin\\$(Platform)\\$(Configuration)\\</OutDir>\r\n    <IntDir Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">$(ProjectDir)..\\obj\\$(Platform)\\$(Configuration)\\</IntDir>\r\n    <IntDir Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">$(ProjectDir)..\\obj\\$(Platform)\\$(Configuration)\\</IntDir>\r\n    <LinkIncremental Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">true</LinkIncremental>\r\n    <LinkIncremental Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">true</LinkIncremental>\r\n    <GenerateManifest Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">false</GenerateManifest>\r\n    <GenerateManifest Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">false</GenerateManifest>\r\n    <EmbedManifest Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">false</EmbedManifest>\r\n    <EmbedManifest Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">false</EmbedManifest>\r\n    <OutDir Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">$(ProjectDir)..\\bin\\$(Platform)\\$(Configuration)\\</OutDir>\r\n    <OutDir Condition=\"'$(Configuration)|$(Platform)'=='Release_XP|Win32'\">$(ProjectDir)..\\bin\\$(Platform)\\$(Configuration)\\</OutDir>\r\n    <OutDir Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">$(ProjectDir)..\\bin\\$(Platform)\\$(Configuration)\\</OutDir>\r\n    <OutDir Condition=\"'$(Configuration)|$(Platform)'=='Release_XP|x64'\">$(ProjectDir)..\\bin\\$(Platform)\\$(Configuration)\\</OutDir>\r\n    <IntDir Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">$(ProjectDir)..\\obj\\$(Platform)\\$(Configuration)\\</IntDir>\r\n    <IntDir Condition=\"'$(Configuration)|$(Platform)'=='Release_XP|Win32'\">$(ProjectDir)..\\obj\\$(Platform)\\$(Configuration)\\</IntDir>\r\n    <IntDir Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">$(ProjectDir)..\\obj\\$(Platform)\\$(Configuration)\\</IntDir>\r\n    <IntDir Condition=\"'$(Configuration)|$(Platform)'=='Release_XP|x64'\">$(ProjectDir)..\\obj\\$(Platform)\\$(Configuration)\\</IntDir>\r\n    <LinkIncremental Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">false</LinkIncremental>\r\n    <LinkIncremental Condition=\"'$(Configuration)|$(Platform)'=='Release_XP|Win32'\">false</LinkIncremental>\r\n    <LinkIncremental Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">false</LinkIncremental>\r\n    <LinkIncremental Condition=\"'$(Configuration)|$(Platform)'=='Release_XP|x64'\">false</LinkIncremental>\r\n    <GenerateManifest Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">false</GenerateManifest>\r\n    <GenerateManifest Condition=\"'$(Configuration)|$(Platform)'=='Release_XP|Win32'\">false</GenerateManifest>\r\n    <GenerateManifest Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">false</GenerateManifest>\r\n    <GenerateManifest Condition=\"'$(Configuration)|$(Platform)'=='Release_XP|x64'\">false</GenerateManifest>\r\n    <EmbedManifest Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">false</EmbedManifest>\r\n    <EmbedManifest Condition=\"'$(Configuration)|$(Platform)'=='Release_XP|Win32'\">false</EmbedManifest>\r\n    <EmbedManifest Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">false</EmbedManifest>\r\n    <EmbedManifest Condition=\"'$(Configuration)|$(Platform)'=='Release_XP|x64'\">false</EmbedManifest>\r\n  </PropertyGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\r\n    <ClCompile>\r\n      <Optimization>Disabled</Optimization>\r\n      <AdditionalIncludeDirectories>$(ProjectDir)..\\deps\\include;$(ProjectDir)..\\deps\\include\\SDL;$(ProjectDir)..\\libs\\rapidyaml\\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r\n      <PreprocessorDefinitions>WIN32;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r\n      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r\n      <WarningLevel>Level1</WarningLevel>\r\n      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r\n      <MinimalRebuild>false</MinimalRebuild>\r\n      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r\n      <LanguageStandard>stdcpp17</LanguageStandard>\r\n      <AdditionalOptions>/utf-8 /bigobj %(AdditionalOptions)</AdditionalOptions>\r\n      <ConformanceMode>true</ConformanceMode>\r\n    </ClCompile>\r\n    <Link>\r\n      <AdditionalDependencies>SDL_image.lib;SDL_mixer.lib;SDL_gfx.lib;SDLmain.lib;SDL.lib;opengl32.lib;%(AdditionalDependencies)</AdditionalDependencies>\r\n      <AdditionalLibraryDirectories>$(ProjectDir)..\\deps\\lib\\$(Platform);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r\n      <GenerateDebugInformation>true</GenerateDebugInformation>\r\n      <SubSystem>Console</SubSystem>\r\n      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r\n      <DataExecutionPrevention>\r\n      </DataExecutionPrevention>\r\n      <TargetMachine>MachineX86</TargetMachine>\r\n      <GenerateMapFile>false</GenerateMapFile>\r\n      <MapExports>false</MapExports>\r\n      <IgnoreSpecificDefaultLibraries>MSVCRT</IgnoreSpecificDefaultLibraries>\r\n    </Link>\r\n    <PostBuildEvent>\r\n      <Command>copy /y \"$(ProjectDir)..\\deps\\lib\\$(Platform)\\*.dll\" \"$(ProjectDir)..\\bin\\$(Platform)\\\"</Command>\r\n    </PostBuildEvent>\r\n    <Manifest>\r\n      <EnableDpiAwareness>PerMonitorHighDPIAware</EnableDpiAwareness>\r\n    </Manifest>\r\n  </ItemDefinitionGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\r\n    <ClCompile>\r\n      <Optimization>Disabled</Optimization>\r\n      <AdditionalIncludeDirectories>$(ProjectDir)..\\deps\\include;$(ProjectDir)..\\deps\\include\\SDL;$(ProjectDir)..\\libs\\rapidyaml\\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r\n      <PreprocessorDefinitions>WIN32;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r\n      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r\n      <WarningLevel>Level3</WarningLevel>\r\n      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r\n      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r\n      <LanguageStandard>stdcpp17</LanguageStandard>\r\n      <AdditionalOptions>/utf-8 /bigobj %(AdditionalOptions)</AdditionalOptions>\r\n      <ConformanceMode>true</ConformanceMode>\r\n    </ClCompile>\r\n    <Link>\r\n      <AdditionalDependencies>SDL_image.lib;SDL_mixer.lib;SDL_gfx.lib;SDLmain.lib;SDL.lib;opengl32.lib;%(AdditionalDependencies)</AdditionalDependencies>\r\n      <AdditionalLibraryDirectories>$(ProjectDir)..\\deps\\lib\\$(Platform);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r\n      <GenerateDebugInformation>true</GenerateDebugInformation>\r\n      <SubSystem>Console</SubSystem>\r\n      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r\n      <DataExecutionPrevention>\r\n      </DataExecutionPrevention>\r\n      <GenerateMapFile>false</GenerateMapFile>\r\n      <MapExports>false</MapExports>\r\n    </Link>\r\n    <PostBuildEvent>\r\n      <Command>copy /y \"$(ProjectDir)..\\deps\\lib\\$(Platform)\\*.dll\" \"$(ProjectDir)..\\bin\\$(Platform)\\\"</Command>\r\n    </PostBuildEvent>\r\n    <Manifest>\r\n      <EnableDpiAwareness>PerMonitorHighDPIAware</EnableDpiAwareness>\r\n    </Manifest>\r\n  </ItemDefinitionGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\r\n    <ClCompile>\r\n      <AdditionalIncludeDirectories>$(ProjectDir)..\\deps\\include;$(ProjectDir)..\\deps\\include\\SDL;$(ProjectDir)..\\libs\\rapidyaml\\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r\n      <PreprocessorDefinitions>WIN32;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r\n      <WarningLevel>Level1</WarningLevel>\r\n      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r\n      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r\n      <IntrinsicFunctions>true</IntrinsicFunctions>\r\n      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r\n      <OmitFramePointers>true</OmitFramePointers>\r\n      <LanguageStandard>stdcpp17</LanguageStandard>\r\n      <AdditionalOptions>/utf-8 /bigobj %(AdditionalOptions)</AdditionalOptions>\r\n      <ConformanceMode>true</ConformanceMode>\r\n    </ClCompile>\r\n    <Link>\r\n      <AdditionalDependencies>SDL_image.lib;SDL_mixer.lib;SDL_gfx.lib;SDLmain.lib;SDL.lib;SDL_gfx.lib;opengl32.lib;%(AdditionalDependencies)</AdditionalDependencies>\r\n      <AdditionalLibraryDirectories>$(ProjectDir)..\\deps\\lib\\$(Platform);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r\n      <GenerateDebugInformation>true</GenerateDebugInformation>\r\n      <SubSystem>Windows</SubSystem>\r\n      <OptimizeReferences>true</OptimizeReferences>\r\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\r\n      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r\n      <DataExecutionPrevention>\r\n      </DataExecutionPrevention>\r\n      <TargetMachine>MachineX86</TargetMachine>\r\n      <Profile>false</Profile>\r\n    </Link>\r\n    <PostBuildEvent>\r\n      <Command>copy /y \"$(ProjectDir)..\\deps\\lib\\$(Platform)\\*.dll\" \"$(ProjectDir)..\\bin\\$(Platform)\\\"</Command>\r\n    </PostBuildEvent>\r\n    <Manifest>\r\n      <EnableDpiAwareness>PerMonitorHighDPIAware</EnableDpiAwareness>\r\n    </Manifest>\r\n  </ItemDefinitionGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release_XP|Win32'\">\r\n    <ClCompile>\r\n      <AdditionalIncludeDirectories>$(ProjectDir)..\\deps\\include;$(ProjectDir)..\\deps\\include\\SDL;$(ProjectDir)..\\libs\\rapidyaml\\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r\n      <PreprocessorDefinitions>WIN32;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;_WIN32_WINNT=0x0501;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r\n      <WarningLevel>Level1</WarningLevel>\r\n      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r\n      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r\n      <IntrinsicFunctions>true</IntrinsicFunctions>\r\n      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r\n      <OmitFramePointers>true</OmitFramePointers>\r\n      <LanguageStandard>stdcpp17</LanguageStandard>\r\n      <AdditionalOptions>/utf-8 /bigobj %(AdditionalOptions)</AdditionalOptions>\r\n      <ConformanceMode>false</ConformanceMode>\r\n    </ClCompile>\r\n    <Link>\r\n      <AdditionalDependencies>SDL_image.lib;SDL_mixer.lib;SDL_gfx.lib;SDLmain.lib;SDL.lib;SDL_gfx.lib;opengl32.lib;%(AdditionalDependencies)</AdditionalDependencies>\r\n      <AdditionalLibraryDirectories>$(ProjectDir)..\\deps\\lib\\$(Platform);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r\n      <GenerateDebugInformation>true</GenerateDebugInformation>\r\n      <SubSystem>Windows</SubSystem>\r\n      <OptimizeReferences>true</OptimizeReferences>\r\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\r\n      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r\n      <DataExecutionPrevention>\r\n      </DataExecutionPrevention>\r\n      <TargetMachine>MachineX86</TargetMachine>\r\n      <Profile>false</Profile>\r\n    </Link>\r\n    <PostBuildEvent>\r\n      <Command>copy /y \"$(ProjectDir)..\\deps\\lib\\$(Platform)\\*.dll\" \"$(ProjectDir)..\\bin\\$(Platform)\\\"</Command>\r\n    </PostBuildEvent>\r\n    <Manifest>\r\n      <EnableDpiAwareness>PerMonitorHighDPIAware</EnableDpiAwareness>\r\n    </Manifest>\r\n  </ItemDefinitionGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\r\n    <ClCompile>\r\n      <AdditionalIncludeDirectories>$(ProjectDir)..\\deps\\include;$(ProjectDir)..\\deps\\include\\SDL;$(ProjectDir)..\\libs\\rapidyaml\\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r\n      <PreprocessorDefinitions>WIN32;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r\n      <WarningLevel>Level3</WarningLevel>\r\n      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r\n      <IntrinsicFunctions>true</IntrinsicFunctions>\r\n      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r\n      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r\n      <WholeProgramOptimization>false</WholeProgramOptimization>\r\n      <LanguageStandard>stdcpp17</LanguageStandard>\r\n      <AdditionalOptions>/utf-8 /bigobj %(AdditionalOptions)</AdditionalOptions>\r\n      <ConformanceMode>true</ConformanceMode>\r\n    </ClCompile>\r\n    <Link>\r\n      <AdditionalDependencies>SDL_image.lib;SDL_mixer.lib;SDL_gfx.lib;SDLmain.lib;SDL.lib;SDL_gfx.lib;opengl32.lib;%(AdditionalDependencies)</AdditionalDependencies>\r\n      <AdditionalLibraryDirectories>$(ProjectDir)..\\deps\\lib\\$(Platform);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r\n      <GenerateDebugInformation>true</GenerateDebugInformation>\r\n      <SubSystem>Windows</SubSystem>\r\n      <OptimizeReferences>true</OptimizeReferences>\r\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\r\n      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r\n      <DataExecutionPrevention>\r\n      </DataExecutionPrevention>\r\n      <Profile>false</Profile>\r\n    </Link>\r\n    <PostBuildEvent>\r\n      <Command>copy /y \"$(ProjectDir)..\\deps\\lib\\$(Platform)\\*.dll\" \"$(ProjectDir)..\\bin\\$(Platform)\\\"</Command>\r\n    </PostBuildEvent>\r\n    <Manifest>\r\n      <EnableDpiAwareness>PerMonitorHighDPIAware</EnableDpiAwareness>\r\n    </Manifest>\r\n  </ItemDefinitionGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release_XP|x64'\">\r\n    <ClCompile>\r\n      <AdditionalIncludeDirectories>$(ProjectDir)..\\deps\\include;$(ProjectDir)..\\deps\\include\\SDL;$(ProjectDir)..\\libs\\rapidyaml\\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r\n      <PreprocessorDefinitions>WIN32;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r\n      <WarningLevel>Level3</WarningLevel>\r\n      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r\n      <IntrinsicFunctions>true</IntrinsicFunctions>\r\n      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r\n      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r\n      <WholeProgramOptimization>false</WholeProgramOptimization>\r\n      <LanguageStandard>stdcpp17</LanguageStandard>\r\n      <AdditionalOptions>/utf-8 /bigobj %(AdditionalOptions)</AdditionalOptions>\r\n      <ConformanceMode>false</ConformanceMode>\r\n    </ClCompile>\r\n    <Link>\r\n      <AdditionalDependencies>SDL_image.lib;SDL_mixer.lib;SDL_gfx.lib;SDLmain.lib;SDL.lib;SDL_gfx.lib;opengl32.lib;%(AdditionalDependencies)</AdditionalDependencies>\r\n      <AdditionalLibraryDirectories>$(ProjectDir)..\\deps\\lib\\$(Platform);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r\n      <GenerateDebugInformation>true</GenerateDebugInformation>\r\n      <SubSystem>Windows</SubSystem>\r\n      <OptimizeReferences>true</OptimizeReferences>\r\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\r\n      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r\n      <DataExecutionPrevention>\r\n      </DataExecutionPrevention>\r\n      <Profile>false</Profile>\r\n    </Link>\r\n    <PostBuildEvent>\r\n      <Command>copy /y \"$(ProjectDir)..\\deps\\lib\\$(Platform)\\*.dll\" \"$(ProjectDir)..\\bin\\$(Platform)\\\"</Command>\r\n    </PostBuildEvent>\r\n    <Manifest>\r\n      <EnableDpiAwareness>PerMonitorHighDPIAware</EnableDpiAwareness>\r\n    </Manifest>\r\n  </ItemDefinitionGroup>\r\n  <ItemGroup>\r\n    <ClCompile Include=\"..\\libs\\miniz\\miniz.c\" />\r\n    <ClCompile Include=\"..\\libs\\rapidyaml\\c4\\base64.cpp\" />\r\n    <ClCompile Include=\"..\\libs\\rapidyaml\\c4\\char_traits.cpp\" />\r\n    <ClCompile Include=\"..\\libs\\rapidyaml\\c4\\error.cpp\" />\r\n    <ClCompile Include=\"..\\libs\\rapidyaml\\c4\\format.cpp\" />\r\n    <ClCompile Include=\"..\\libs\\rapidyaml\\c4\\language.cpp\" />\r\n    <ClCompile Include=\"..\\libs\\rapidyaml\\c4\\memory_resource.cpp\" />\r\n    <ClCompile Include=\"..\\libs\\rapidyaml\\c4\\memory_util.cpp\" />\r\n    <ClCompile Include=\"..\\libs\\rapidyaml\\c4\\utf.cpp\" />\r\n    <ClCompile Include=\"..\\libs\\rapidyaml\\c4\\yml\\common.cpp\" />\r\n    <ClCompile Include=\"..\\libs\\rapidyaml\\c4\\yml\\node.cpp\" />\r\n    <ClCompile Include=\"..\\libs\\rapidyaml\\c4\\yml\\node_type.cpp\" />\r\n    <ClCompile Include=\"..\\libs\\rapidyaml\\c4\\yml\\parse.cpp\" />\r\n    <ClCompile Include=\"..\\libs\\rapidyaml\\c4\\yml\\preprocess.cpp\" />\r\n    <ClCompile Include=\"..\\libs\\rapidyaml\\c4\\yml\\reference_resolver.cpp\" />\r\n    <ClCompile Include=\"..\\libs\\rapidyaml\\c4\\yml\\tag.cpp\" />\r\n    <ClCompile Include=\"..\\libs\\rapidyaml\\c4\\yml\\tree.cpp\" />\r\n    <ClCompile Include=\"..\\libs\\rapidyaml\\c4\\yml\\version.cpp\" />\r\n    <ClCompile Include=\"Basescape\\BaseInfoState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\BasescapeState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\BaseView.cpp\" />\r\n    <ClCompile Include=\"Basescape\\BuildFacilitiesState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\CraftArmorState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\CraftEquipmentLoadState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\CraftEquipmentSaveState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\CraftEquipmentState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\CraftInfoState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\CraftPilotSelectState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\CraftPilotsState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\CraftSoldiersState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\CraftsState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\CraftWeaponsState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\DismantleFacilityState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\GlobalAlienContainmentState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\GlobalManufactureState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\GlobalResearchDiaryState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\GlobalResearchState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\ItemLocationsState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\ManageAlienContainmentState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\ManufactureDependenciesTreeState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\ManufactureState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\NewManufactureListState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\ManufactureInfoState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\MiniBaseView.cpp\" />\r\n    <ClCompile Include=\"Basescape\\MonthlyCostsState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\NewResearchListState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\PlaceFacilityState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\PlaceLiftState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\ManufactureStartState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\PlaceStartFacilityState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\PurchaseState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\ResearchInfoState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\ResearchState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\SelectStartFacilityState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\SackSoldierState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\SellState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\SoldierArmorState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\SoldierBonusState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\SoldierDiaryLightState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\SoldierDiaryMissionState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\SoldierDiaryOverviewState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\SoldierDiaryPerformanceState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\SoldierAvatarState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\SoldierInfoState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\SoldierMemorialState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\SoldierRankState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\SoldierSortUtil.cpp\" />\r\n    <ClCompile Include=\"Basescape\\SoldiersState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\SoldierTransformationListState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\SoldierTransformationState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\SoldierTransformState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\StoresState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\TechTreeSelectState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\TechTreeViewerState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\TransferBaseState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\TransferConfirmState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\TransferItemsState.cpp\" />\r\n    <ClCompile Include=\"Basescape\\TransfersState.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\AbortMissionState.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\ActionMenuItem.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\ActionMenuState.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\AlienInventory.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\AlienInventoryState.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\AliensCrashState.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\AIModule.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\BattlescapeGame.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\BattlescapeGenerator.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\BattlescapeMessage.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\BattlescapeState.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\BattleState.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\BriefingLightState.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\BriefingState.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\Camera.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\CannotReequipState.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\CommendationLateState.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\CommendationState.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\ConfirmEndMissionState.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\DebriefingState.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\ExperienceOverviewState.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\Explosion.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\ExplosionBState.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\ExtendedBattlescapeLinksState.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\ExtendedInventoryLinksState.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\InfoboxOKState.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\InfoboxState.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\Inventory.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\InventoryLoadState.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\InventoryPersonalState.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\InventorySaveState.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\InventoryState.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\ItemSprite.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\Map.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\MedikitState.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\MedikitView.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\MeleeAttackBState.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\MiniMapState.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\MiniMapView.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\NextTurnState.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\NoExperienceState.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\Pathfinding.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\PathfindingNode.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\PathfindingOpenSet.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\Position.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\PrimeGrenadeState.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\Projectile.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\ProjectileFlyBState.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\PromotionsState.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\PsiAttackBState.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\ScannerState.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\ScannerView.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\SkillMenuState.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\TurnDiaryState.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\UnitFallBState.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\UnitInfoState.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\TileEngine.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\UnitDieBState.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\UnitPanicBState.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\UnitSprite.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\UnitTurnBState.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\UnitWalkBState.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\Particle.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\WarningMessage.cpp\" />\r\n    <ClCompile Include=\"Engine\\Action.cpp\" />\r\n    <ClCompile Include=\"Engine\\AdlibMusic.cpp\" />\r\n    <ClCompile Include=\"Engine\\Adlib\\adlplayer.cpp\" />\r\n    <ClCompile Include=\"Engine\\Adlib\\fmopl.cpp\" />\r\n    <ClCompile Include=\"Engine\\CatFile.cpp\" />\r\n    <ClCompile Include=\"Engine\\CrossPlatform.cpp\" />\r\n    <ClCompile Include=\"Engine\\FastLineClip.cpp\" />\r\n    <ClCompile Include=\"Engine\\FileMap.cpp\" />\r\n    <ClCompile Include=\"Engine\\FlcPlayer.cpp\" />\r\n    <ClCompile Include=\"Engine\\Font.cpp\" />\r\n    <ClCompile Include=\"Engine\\Game.cpp\" />\r\n    <ClCompile Include=\"Engine\\GMCat.cpp\" />\r\n    <ClCompile Include=\"Engine\\InteractiveSurface.cpp\" />\r\n    <ClCompile Include=\"Engine\\Language.cpp\">\r\n      <ObjectFileName>$(IntDir)%(RelativeDir)</ObjectFileName>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\LanguagePlurality.cpp\" />\r\n    <ClCompile Include=\"Engine\\LocalizedText.cpp\" />\r\n    <ClCompile Include=\"Engine\\ModInfo.cpp\" />\r\n    <ClCompile Include=\"Engine\\Music.cpp\" />\r\n    <ClCompile Include=\"Engine\\OpenGL.cpp\" />\r\n    <ClCompile Include=\"Engine\\OptionInfo.cpp\" />\r\n    <ClCompile Include=\"Engine\\Options.cpp\" />\r\n    <ClCompile Include=\"Engine\\Palette.cpp\" />\r\n    <ClCompile Include=\"Engine\\RNG.cpp\" />\r\n    <ClCompile Include=\"Engine\\Scalers\\hq2x.cpp\" />\r\n    <ClCompile Include=\"Engine\\Scalers\\hq3x.cpp\" />\r\n    <ClCompile Include=\"Engine\\Scalers\\hq4x.cpp\" />\r\n    <ClCompile Include=\"Engine\\Scalers\\init.cpp\" />\r\n    <ClCompile Include=\"Engine\\Scalers\\scale2x.cpp\" />\r\n    <ClCompile Include=\"Engine\\Scalers\\scale3x.cpp\" />\r\n    <ClCompile Include=\"Engine\\Scalers\\scalebit.cpp\" />\r\n    <ClCompile Include=\"Engine\\Scalers\\xbrz.cpp\" />\r\n    <ClCompile Include=\"Engine\\Screen.cpp\" />\r\n    <ClCompile Include=\"Engine\\Script.cpp\" />\r\n    <ClCompile Include=\"Engine\\Sound.cpp\" />\r\n    <ClCompile Include=\"Engine\\SoundSet.cpp\" />\r\n    <ClCompile Include=\"Engine\\State.cpp\" />\r\n    <ClCompile Include=\"Engine\\Surface.cpp\" />\r\n    <ClCompile Include=\"Engine\\SurfaceSet.cpp\" />\r\n    <ClCompile Include=\"Engine\\Timer.cpp\" />\r\n    <ClCompile Include=\"Engine\\TouchState.cpp\" />\r\n    <ClCompile Include=\"Engine\\Unicode.cpp\" />\r\n    <ClCompile Include=\"Engine\\Yaml.cpp\" />\r\n    <ClCompile Include=\"Engine\\Zoom.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\AlienBaseState.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\AllocateTrainingState.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\CraftNotEnoughPilotsState.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\DogfightErrorState.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\DogfightExperienceState.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\ExtendedGeoscapeLinksState.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\GeoscapeEventState.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\MissionDetectedState.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\AllocatePsiTrainingState.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\BaseDefenseState.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\BaseDestroyedState.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\BaseNameState.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\BuildNewBaseState.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\ConfirmCydoniaState.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\CraftErrorState.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\ConfirmDestinationState.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\ConfirmLandingState.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\ConfirmNewBaseState.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\CraftPatrolState.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\DogfightState.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\NewPossibleCraftState.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\NewPossibleFacilityState.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\NewPossiblePurchaseState.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\ResearchRequiredState.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\NewPossibleManufactureState.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\PsiTrainingState.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\ResearchCompleteState.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\FundingState.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\GeoscapeCraftState.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\NewPossibleResearchState.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\ProductionCompleteState.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\GeoscapeState.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\Globe.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\GraphsState.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\InterceptState.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\ItemsArrivingState.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\LowFuelState.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\MonthlyReportState.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\MultipleTargetsState.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\SelectDestinationState.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\SelectMusicTrackState.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\TargetInfoState.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\TrainingFinishedState.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\TrainingState.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\UfoDetectedState.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\UfoLostState.cpp\" />\r\n    <ClCompile Include=\"Geoscape\\UfoTrackerState.cpp\" />\r\n    <ClCompile Include=\"Interface\\ArrowButton.cpp\" />\r\n    <ClCompile Include=\"Interface\\Bar.cpp\" />\r\n    <ClCompile Include=\"Interface\\BattlescapeButton.cpp\" />\r\n    <ClCompile Include=\"Interface\\ComboBox.cpp\" />\r\n    <ClCompile Include=\"Interface\\Cursor.cpp\" />\r\n    <ClCompile Include=\"Interface\\FpsCounter.cpp\" />\r\n    <ClCompile Include=\"Interface\\Frame.cpp\" />\r\n    <ClCompile Include=\"Interface\\ImageButton.cpp\" />\r\n    <ClCompile Include=\"Interface\\NumberText.cpp\" />\r\n    <ClCompile Include=\"Interface\\ProgressBar.cpp\" />\r\n    <ClCompile Include=\"Interface\\ScrollBar.cpp\" />\r\n    <ClCompile Include=\"Interface\\Slider.cpp\" />\r\n    <ClCompile Include=\"Interface\\Text.cpp\" />\r\n    <ClCompile Include=\"Interface\\TextButton.cpp\" />\r\n    <ClCompile Include=\"Interface\\TextEdit.cpp\" />\r\n    <ClCompile Include=\"Interface\\TextList.cpp\" />\r\n    <ClCompile Include=\"Interface\\ToggleTextButton.cpp\" />\r\n    <ClCompile Include=\"Interface\\Window.cpp\" />\r\n    <ClCompile Include=\"lodepng.cpp\" />\r\n    <ClCompile Include=\"main.cpp\" />\r\n    <ClCompile Include=\"md5.cpp\" />\r\n    <ClCompile Include=\"Menu\\AbandonGameState.cpp\" />\r\n    <ClCompile Include=\"Menu\\ConfirmLoadState.cpp\" />\r\n    <ClCompile Include=\"Menu\\CutsceneState.cpp\" />\r\n    <ClCompile Include=\"Menu\\ListGamesState.cpp\" />\r\n    <ClCompile Include=\"Menu\\ListLoadOriginalState.cpp\" />\r\n    <ClCompile Include=\"Menu\\ListLoadState.cpp\" />\r\n    <ClCompile Include=\"Menu\\ListSaveState.cpp\" />\r\n    <ClCompile Include=\"Menu\\LoadGameState.cpp\" />\r\n    <ClCompile Include=\"Menu\\ModConfirmExtendedState.cpp\" />\r\n    <ClCompile Include=\"Menu\\NotesState.cpp\" />\r\n    <ClCompile Include=\"Menu\\OptionsAdvancedState.cpp\" />\r\n    <ClCompile Include=\"Menu\\DeleteGameState.cpp\" />\r\n    <ClCompile Include=\"Menu\\ErrorMessageState.cpp\" />\r\n    <ClCompile Include=\"Menu\\OptionsAudioState.cpp\" />\r\n    <ClCompile Include=\"Menu\\OptionsConfirmState.cpp\" />\r\n    <ClCompile Include=\"Menu\\OptionsDefaultsState.cpp\" />\r\n    <ClCompile Include=\"Menu\\OptionsFoldersState.cpp\" />\r\n    <ClCompile Include=\"Menu\\OptionsGeoscapeState.cpp\" />\r\n    <ClCompile Include=\"Menu\\MainMenuState.cpp\" />\r\n    <ClCompile Include=\"Menu\\NewBattleState.cpp\" />\r\n    <ClCompile Include=\"Menu\\NewGameState.cpp\" />\r\n    <ClCompile Include=\"Menu\\OptionsBaseState.cpp\" />\r\n    <ClCompile Include=\"Menu\\OptionsBattlescapeState.cpp\" />\r\n    <ClCompile Include=\"Menu\\OptionsControlsState.cpp\" />\r\n    <ClCompile Include=\"Menu\\ModListState.cpp\" />\r\n    <ClCompile Include=\"Menu\\OptionsNoAudioState.cpp\" />\r\n    <ClCompile Include=\"Menu\\OptionsVideoState.cpp\" />\r\n    <ClCompile Include=\"Menu\\PauseState.cpp\" />\r\n    <ClCompile Include=\"Menu\\SaveGameState.cpp\" />\r\n    <ClCompile Include=\"Menu\\SetWindowedRootState.cpp\" />\r\n    <ClCompile Include=\"Menu\\SlideshowState.cpp\" />\r\n    <ClCompile Include=\"Menu\\StartState.cpp\" />\r\n    <ClCompile Include=\"Menu\\StatisticsState.cpp\" />\r\n    <ClCompile Include=\"Menu\\TestPaletteState.cpp\" />\r\n    <ClCompile Include=\"Menu\\TestState.cpp\" />\r\n    <ClCompile Include=\"Menu\\VideoState.cpp\" />\r\n    <ClCompile Include=\"Mod\\CustomPalettes.cpp\" />\r\n    <ClCompile Include=\"Mod\\RuleArcScript.cpp\" />\r\n    <ClCompile Include=\"Mod\\RuleDamageType.cpp\" />\r\n    <ClCompile Include=\"Mod\\RuleEnviroEffects.cpp\" />\r\n    <ClCompile Include=\"Mod\\RuleEvent.cpp\" />\r\n    <ClCompile Include=\"Mod\\RuleEventScript.cpp\" />\r\n    <ClCompile Include=\"Mod\\RuleItemCategory.cpp\" />\r\n    <ClCompile Include=\"Mod\\RuleManufactureShortcut.cpp\" />\r\n    <ClCompile Include=\"Mod\\RuleSkill.cpp\" />\r\n    <ClCompile Include=\"Mod\\RuleSoldierBonus.cpp\" />\r\n    <ClCompile Include=\"Mod\\RuleSoldierTransformation.cpp\" />\r\n    <ClCompile Include=\"Mod\\RuleStartingCondition.cpp\" />\r\n    <ClCompile Include=\"Mod\\RuleStatBonus.cpp\" />\r\n    <ClCompile Include=\"Mod\\RuleCommendations.cpp\" />\r\n    <ClCompile Include=\"Mod\\RuleConverter.cpp\" />\r\n    <ClCompile Include=\"Mod\\ExtraSounds.cpp\" />\r\n    <ClCompile Include=\"Mod\\ExtraSprites.cpp\" />\r\n    <ClCompile Include=\"Mod\\ExtraStrings.cpp\" />\r\n    <ClCompile Include=\"Mod\\RuleMissionScript.cpp\" />\r\n    <ClCompile Include=\"Mod\\RuleWeaponSet.cpp\" />\r\n    <ClCompile Include=\"Mod\\Texture.cpp\" />\r\n    <ClCompile Include=\"Mod\\MapScript.cpp\" />\r\n    <ClCompile Include=\"Mod\\MCDPatch.cpp\" />\r\n    <ClCompile Include=\"Mod\\Polygon.cpp\" />\r\n    <ClCompile Include=\"Mod\\Polyline.cpp\" />\r\n    <ClCompile Include=\"Mod\\RuleAlienMission.cpp\" />\r\n    <ClCompile Include=\"Mod\\ArticleDefinition.cpp\" />\r\n    <ClCompile Include=\"Mod\\City.cpp\" />\r\n    <ClCompile Include=\"Mod\\MapBlock.cpp\" />\r\n    <ClCompile Include=\"Mod\\MapDataSet.cpp\" />\r\n    <ClCompile Include=\"Mod\\MapData.cpp\" />\r\n    <ClCompile Include=\"Mod\\AlienDeployment.cpp\" />\r\n    <ClCompile Include=\"Mod\\AlienRace.cpp\" />\r\n    <ClCompile Include=\"Mod\\RuleGlobe.cpp\" />\r\n    <ClCompile Include=\"Mod\\RuleMusic.cpp\" />\r\n    <ClCompile Include=\"Mod\\RuleVideo.cpp\" />\r\n    <ClCompile Include=\"Mod\\SoundDefinition.cpp\" />\r\n    <ClCompile Include=\"Mod\\StatString.cpp\" />\r\n    <ClCompile Include=\"Mod\\StatStringCondition.cpp\" />\r\n    <ClCompile Include=\"Mod\\RuleInterface.cpp\" />\r\n    <ClCompile Include=\"Mod\\Unit.cpp\" />\r\n    <ClCompile Include=\"Mod\\Armor.cpp\" />\r\n    <ClCompile Include=\"Mod\\RuleBaseFacility.cpp\" />\r\n    <ClCompile Include=\"Mod\\RuleCountry.cpp\" />\r\n    <ClCompile Include=\"Mod\\RuleCraft.cpp\" />\r\n    <ClCompile Include=\"Mod\\RuleCraftWeapon.cpp\" />\r\n    <ClCompile Include=\"Mod\\RuleInventory.cpp\" />\r\n    <ClCompile Include=\"Mod\\RuleItem.cpp\" />\r\n    <ClCompile Include=\"Mod\\RuleManufacture.cpp\" />\r\n    <ClCompile Include=\"Mod\\RuleRegion.cpp\" />\r\n    <ClCompile Include=\"Mod\\RuleResearch.cpp\" />\r\n    <ClCompile Include=\"Mod\\Mod.cpp\" />\r\n    <ClCompile Include=\"Mod\\RuleSoldier.cpp\" />\r\n    <ClCompile Include=\"Mod\\RuleUfo.cpp\" />\r\n    <ClCompile Include=\"Mod\\RuleTerrain.cpp\" />\r\n    <ClCompile Include=\"Mod\\SoldierNamePool.cpp\" />\r\n    <ClCompile Include=\"Mod\\UfoTrajectory.cpp\" />\r\n    <ClCompile Include=\"Savegame\\AlienBase.cpp\" />\r\n    <ClCompile Include=\"Savegame\\AlienStrategy.cpp\" />\r\n    <ClCompile Include=\"Savegame\\AlienMission.cpp\" />\r\n    <ClCompile Include=\"Savegame\\Base.cpp\" />\r\n    <ClCompile Include=\"Savegame\\BaseFacility.cpp\" />\r\n    <ClCompile Include=\"Savegame\\BattleItem.cpp\" />\r\n    <ClCompile Include=\"Savegame\\BattleUnit.cpp\" />\r\n    <ClCompile Include=\"Savegame\\Country.cpp\" />\r\n    <ClCompile Include=\"Savegame\\Craft.cpp\" />\r\n    <ClCompile Include=\"Savegame\\CraftWeapon.cpp\" />\r\n    <ClCompile Include=\"Savegame\\CraftWeaponProjectile.cpp\" />\r\n    <ClCompile Include=\"Savegame\\EquipmentLayoutItem.cpp\" />\r\n    <ClCompile Include=\"Savegame\\GameTime.cpp\" />\r\n    <ClCompile Include=\"Savegame\\GeoscapeEvent.cpp\" />\r\n    <ClCompile Include=\"Savegame\\HitLog.cpp\" />\r\n    <ClCompile Include=\"Savegame\\ItemContainer.cpp\" />\r\n    <ClCompile Include=\"Savegame\\MovingTarget.cpp\" />\r\n    <ClCompile Include=\"Savegame\\Production.cpp\" />\r\n    <ClCompile Include=\"Savegame\\RankCount.cpp\" />\r\n    <ClCompile Include=\"Savegame\\Region.cpp\" />\r\n    <ClCompile Include=\"Savegame\\ResearchProject.cpp\" />\r\n    <ClCompile Include=\"Savegame\\SaveConverter.cpp\" />\r\n    <ClCompile Include=\"Savegame\\SavedBattleGame.cpp\" />\r\n    <ClCompile Include=\"Savegame\\SavedGame.cpp\" />\r\n    <ClCompile Include=\"Savegame\\SerializationHelper.cpp\" />\r\n    <ClCompile Include=\"Savegame\\Soldier.cpp\" />\r\n    <ClCompile Include=\"Savegame\\Node.cpp\">\r\n      <ObjectFileName>$(IntDir)%(RelativeDir)</ObjectFileName>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Savegame\\SoldierAvatar.cpp\" />\r\n    <ClCompile Include=\"Savegame\\SoldierDeath.cpp\" />\r\n    <ClCompile Include=\"Savegame\\SoldierDiary.cpp\" />\r\n    <ClCompile Include=\"Savegame\\Target.cpp\" />\r\n    <ClCompile Include=\"Savegame\\MissionSite.cpp\" />\r\n    <ClCompile Include=\"Savegame\\Tile.cpp\" />\r\n    <ClCompile Include=\"Savegame\\Transfer.cpp\" />\r\n    <ClCompile Include=\"Savegame\\Ufo.cpp\" />\r\n    <ClCompile Include=\"Savegame\\Vehicle.cpp\" />\r\n    <ClCompile Include=\"Savegame\\Waypoint.cpp\" />\r\n    <ClCompile Include=\"Savegame\\WeightedOptions.cpp\" />\r\n    <ClCompile Include=\"Ufopaedia\\ArticleState.cpp\" />\r\n    <ClCompile Include=\"Ufopaedia\\ArticleStateArmor.cpp\" />\r\n    <ClCompile Include=\"Ufopaedia\\ArticleStateBaseFacility.cpp\" />\r\n    <ClCompile Include=\"Ufopaedia\\ArticleStateCraft.cpp\" />\r\n    <ClCompile Include=\"Ufopaedia\\ArticleStateCraftWeapon.cpp\" />\r\n    <ClCompile Include=\"Ufopaedia\\ArticleStateItem.cpp\" />\r\n    <ClCompile Include=\"Ufopaedia\\ArticleStateSoldier.cpp\" />\r\n    <ClCompile Include=\"Ufopaedia\\ArticleStateText.cpp\" />\r\n    <ClCompile Include=\"Ufopaedia\\ArticleStateTextImage.cpp\" />\r\n    <ClCompile Include=\"Ufopaedia\\ArticleStateTFTD.cpp\" />\r\n    <ClCompile Include=\"Ufopaedia\\ArticleStateTFTDArmor.cpp\" />\r\n    <ClCompile Include=\"Ufopaedia\\ArticleStateTFTDCraft.cpp\" />\r\n    <ClCompile Include=\"Ufopaedia\\ArticleStateTFTDCraftWeapon.cpp\" />\r\n    <ClCompile Include=\"Ufopaedia\\ArticleStateTFTDFacility.cpp\" />\r\n    <ClCompile Include=\"Ufopaedia\\ArticleStateTFTDItem.cpp\" />\r\n    <ClCompile Include=\"Ufopaedia\\ArticleStateTFTDUso.cpp\" />\r\n    <ClCompile Include=\"Ufopaedia\\ArticleStateTFTDVehicle.cpp\" />\r\n    <ClCompile Include=\"Ufopaedia\\ArticleStateUfo.cpp\" />\r\n    <ClCompile Include=\"Ufopaedia\\ArticleStateUnit.cpp\" />\r\n    <ClCompile Include=\"Ufopaedia\\ArticleStateVehicle.cpp\" />\r\n    <ClCompile Include=\"Ufopaedia\\StatsForNerdsState.cpp\" />\r\n    <ClCompile Include=\"Ufopaedia\\Ufopaedia.cpp\" />\r\n    <ClCompile Include=\"Ufopaedia\\UfopaediaSelectState.cpp\" />\r\n    <ClCompile Include=\"Ufopaedia\\UfopaediaStartState.cpp\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ClInclude Include=\"..\\libs\\miniz\\miniz.h\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\allocator.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\base64.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\bitmask.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\blob.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\c4_pop.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\c4_push.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\charconv.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\char_traits.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\common.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\compiler.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\config.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\cpu.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\ctor_dtor.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\dump.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\enum.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\error.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\export.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\ext\\fast_float.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\ext\\fast_float_all.h\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\ext\\rng\\rng.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\ext\\sg14\\inplace_function.h\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\format.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\gcc-4.8.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\hash.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\language.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\memory_resource.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\memory_util.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\platform.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\preprocessor.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\restrict.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\span.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\std\\std.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\std\\std_fwd.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\std\\string.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\std\\string_fwd.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\std\\string_view.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\std\\tuple.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\std\\vector.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\std\\vector_fwd.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\substr.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\substr_fwd.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\szconv.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\types.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\type_name.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\unrestrict.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\utf.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\windows.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\windows_pop.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\windows_push.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\common.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\detail\\checks.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\detail\\parser_dbg.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\detail\\print.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\detail\\stack.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\emit.def.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\emit.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\event_handler_stack.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\event_handler_tree.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\export.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\filter_processor.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\fwd.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\node.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\node_type.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\parse.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\parser_state.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\parse_engine.def.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\parse_engine.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\preprocess.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\reference_resolver.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\std\\map.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\std\\std.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\std\\string.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\std\\vector.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\tag.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\tree.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\version.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\writer.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\yml.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\ryml.hpp\" />\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\ryml_std.hpp\" />\r\n    <ClInclude Include=\"Basescape\\BaseInfoState.h\" />\r\n    <ClInclude Include=\"Basescape\\BasescapeState.h\" />\r\n    <ClInclude Include=\"Basescape\\BaseView.h\" />\r\n    <ClInclude Include=\"Basescape\\BuildFacilitiesState.h\" />\r\n    <ClInclude Include=\"Basescape\\CraftArmorState.h\" />\r\n    <ClInclude Include=\"Basescape\\CraftEquipmentLoadState.h\" />\r\n    <ClInclude Include=\"Basescape\\CraftEquipmentSaveState.h\" />\r\n    <ClInclude Include=\"Basescape\\CraftEquipmentState.h\" />\r\n    <ClInclude Include=\"Basescape\\CraftInfoState.h\" />\r\n    <ClInclude Include=\"Basescape\\CraftPilotSelectState.h\" />\r\n    <ClInclude Include=\"Basescape\\CraftPilotsState.h\" />\r\n    <ClInclude Include=\"Basescape\\CraftSoldiersState.h\" />\r\n    <ClInclude Include=\"Basescape\\CraftsState.h\" />\r\n    <ClInclude Include=\"Basescape\\CraftWeaponsState.h\" />\r\n    <ClInclude Include=\"Basescape\\DismantleFacilityState.h\" />\r\n    <ClInclude Include=\"Basescape\\GlobalAlienContainmentState.h\" />\r\n    <ClInclude Include=\"Basescape\\GlobalManufactureState.h\" />\r\n    <ClInclude Include=\"Basescape\\GlobalResearchDiaryState.h\" />\r\n    <ClInclude Include=\"Basescape\\GlobalResearchState.h\" />\r\n    <ClInclude Include=\"Basescape\\ItemLocationsState.h\" />\r\n    <ClInclude Include=\"Basescape\\ManufactureDependenciesTreeState.h\" />\r\n    <ClInclude Include=\"Basescape\\NewManufactureListState.h\" />\r\n    <ClInclude Include=\"Basescape\\ManageAlienContainmentState.h\" />\r\n    <ClInclude Include=\"Basescape\\ManufactureInfoState.h\" />\r\n    <ClInclude Include=\"Basescape\\ManufactureState.h\" />\r\n    <ClInclude Include=\"Basescape\\MiniBaseView.h\" />\r\n    <ClInclude Include=\"Basescape\\MonthlyCostsState.h\" />\r\n    <ClInclude Include=\"Basescape\\NewResearchListState.h\" />\r\n    <ClInclude Include=\"Basescape\\PlaceFacilityState.h\" />\r\n    <ClInclude Include=\"Basescape\\PlaceLiftState.h\" />\r\n    <ClInclude Include=\"Basescape\\ManufactureStartState.h\" />\r\n    <ClInclude Include=\"Basescape\\PlaceStartFacilityState.h\" />\r\n    <ClInclude Include=\"Basescape\\PurchaseState.h\" />\r\n    <ClInclude Include=\"Basescape\\ResearchInfoState.h\" />\r\n    <ClInclude Include=\"Basescape\\ResearchState.h\" />\r\n    <ClInclude Include=\"Basescape\\SelectStartFacilityState.h\" />\r\n    <ClInclude Include=\"Basescape\\SackSoldierState.h\" />\r\n    <ClInclude Include=\"Basescape\\SellState.h\" />\r\n    <ClInclude Include=\"Basescape\\SoldierArmorState.h\" />\r\n    <ClInclude Include=\"Basescape\\SoldierBonusState.h\" />\r\n    <ClInclude Include=\"Basescape\\SoldierDiaryLightState.h\" />\r\n    <ClInclude Include=\"Basescape\\SoldierDiaryMissionState.h\" />\r\n    <ClInclude Include=\"Basescape\\SoldierDiaryOverviewState.h\" />\r\n    <ClInclude Include=\"Basescape\\SoldierDiaryPerformanceState.h\" />\r\n    <ClInclude Include=\"Basescape\\SoldierAvatarState.h\" />\r\n    <ClInclude Include=\"Basescape\\SoldierInfoState.h\" />\r\n    <ClInclude Include=\"Basescape\\SoldierMemorialState.h\" />\r\n    <ClInclude Include=\"Basescape\\SoldierRankState.h\" />\r\n    <ClInclude Include=\"Basescape\\SoldierSortUtil.h\" />\r\n    <ClInclude Include=\"Basescape\\SoldiersState.h\" />\r\n    <ClInclude Include=\"Basescape\\SoldierTransformationListState.h\" />\r\n    <ClInclude Include=\"Basescape\\SoldierTransformationState.h\" />\r\n    <ClInclude Include=\"Basescape\\SoldierTransformState.h\" />\r\n    <ClInclude Include=\"Basescape\\StoresState.h\" />\r\n    <ClInclude Include=\"Basescape\\TechTreeSelectState.h\" />\r\n    <ClInclude Include=\"Basescape\\TechTreeViewerState.h\" />\r\n    <ClInclude Include=\"Basescape\\TransferBaseState.h\" />\r\n    <ClInclude Include=\"Basescape\\TransferConfirmState.h\" />\r\n    <ClInclude Include=\"Basescape\\TransferItemsState.h\" />\r\n    <ClInclude Include=\"Basescape\\TransfersState.h\" />\r\n    <ClInclude Include=\"Battlescape\\AbortMissionState.h\" />\r\n    <ClInclude Include=\"Battlescape\\ActionMenuItem.h\" />\r\n    <ClInclude Include=\"Battlescape\\ActionMenuState.h\" />\r\n    <ClInclude Include=\"Battlescape\\AlienInventory.h\" />\r\n    <ClInclude Include=\"Battlescape\\AlienInventoryState.h\" />\r\n    <ClInclude Include=\"Battlescape\\AliensCrashState.h\" />\r\n    <ClInclude Include=\"Battlescape\\AIModule.h\" />\r\n    <ClInclude Include=\"Battlescape\\BattlescapeGame.h\" />\r\n    <ClInclude Include=\"Battlescape\\BattlescapeGenerator.h\" />\r\n    <ClInclude Include=\"Battlescape\\BattlescapeMessage.h\" />\r\n    <ClInclude Include=\"Battlescape\\BattlescapeState.h\" />\r\n    <ClInclude Include=\"Battlescape\\BattleState.h\" />\r\n    <ClInclude Include=\"Battlescape\\BriefingLightState.h\" />\r\n    <ClInclude Include=\"Battlescape\\BriefingState.h\" />\r\n    <ClInclude Include=\"Battlescape\\Camera.h\" />\r\n    <ClInclude Include=\"Battlescape\\CannotReequipState.h\" />\r\n    <ClInclude Include=\"Battlescape\\CommendationLateState.h\" />\r\n    <ClInclude Include=\"Battlescape\\CommendationState.h\" />\r\n    <ClInclude Include=\"Battlescape\\ConfirmEndMissionState.h\" />\r\n    <ClInclude Include=\"Battlescape\\DebriefingState.h\" />\r\n    <ClInclude Include=\"Battlescape\\ExperienceOverviewState.h\" />\r\n    <ClInclude Include=\"Battlescape\\Explosion.h\" />\r\n    <ClInclude Include=\"Battlescape\\ExplosionBState.h\" />\r\n    <ClInclude Include=\"Battlescape\\ExtendedBattlescapeLinksState.h\" />\r\n    <ClInclude Include=\"Battlescape\\ExtendedInventoryLinksState.h\" />\r\n    <ClInclude Include=\"Battlescape\\InfoboxOKState.h\" />\r\n    <ClInclude Include=\"Battlescape\\InfoboxState.h\" />\r\n    <ClInclude Include=\"Battlescape\\Inventory.h\" />\r\n    <ClInclude Include=\"Battlescape\\InventoryLoadState.h\" />\r\n    <ClInclude Include=\"Battlescape\\InventoryPersonalState.h\" />\r\n    <ClInclude Include=\"Battlescape\\InventorySaveState.h\" />\r\n    <ClInclude Include=\"Battlescape\\InventoryState.h\" />\r\n    <ClInclude Include=\"Battlescape\\ItemSprite.h\" />\r\n    <ClInclude Include=\"Battlescape\\Map.h\" />\r\n    <ClInclude Include=\"Battlescape\\MedikitState.h\" />\r\n    <ClInclude Include=\"Battlescape\\MedikitView.h\" />\r\n    <ClInclude Include=\"Battlescape\\MeleeAttackBState.h\" />\r\n    <ClInclude Include=\"Battlescape\\MiniMapState.h\" />\r\n    <ClInclude Include=\"Battlescape\\MiniMapView.h\" />\r\n    <ClInclude Include=\"Battlescape\\NextTurnState.h\" />\r\n    <ClInclude Include=\"Battlescape\\NoExperienceState.h\" />\r\n    <ClInclude Include=\"Battlescape\\Pathfinding.h\" />\r\n    <ClInclude Include=\"Battlescape\\PathfindingNode.h\" />\r\n    <ClInclude Include=\"Battlescape\\PathfindingOpenSet.h\" />\r\n    <ClInclude Include=\"Battlescape\\Position.h\" />\r\n    <ClInclude Include=\"Battlescape\\PrimeGrenadeState.h\" />\r\n    <ClInclude Include=\"Battlescape\\Projectile.h\" />\r\n    <ClInclude Include=\"Battlescape\\ProjectileFlyBState.h\" />\r\n    <ClInclude Include=\"Battlescape\\PromotionsState.h\" />\r\n    <ClInclude Include=\"Battlescape\\PsiAttackBState.h\" />\r\n    <ClInclude Include=\"Battlescape\\ScannerState.h\" />\r\n    <ClInclude Include=\"Battlescape\\ScannerView.h\" />\r\n    <ClInclude Include=\"Battlescape\\SkillMenuState.h\" />\r\n    <ClInclude Include=\"Battlescape\\TurnDiaryState.h\" />\r\n    <ClInclude Include=\"Battlescape\\UnitFallBState.h\" />\r\n    <ClInclude Include=\"Battlescape\\UnitInfoState.h\" />\r\n    <ClInclude Include=\"Battlescape\\TileEngine.h\" />\r\n    <ClInclude Include=\"Battlescape\\UnitDieBState.h\" />\r\n    <ClInclude Include=\"Battlescape\\UnitPanicBState.h\" />\r\n    <ClInclude Include=\"Battlescape\\UnitSprite.h\" />\r\n    <ClInclude Include=\"Battlescape\\UnitTurnBState.h\" />\r\n    <ClInclude Include=\"Battlescape\\UnitWalkBState.h\" />\r\n    <ClInclude Include=\"Battlescape\\Particle.h\" />\r\n    <ClInclude Include=\"Battlescape\\WarningMessage.h\" />\r\n    <ClInclude Include=\"Engine\\Action.h\" />\r\n    <ClInclude Include=\"Engine\\AdlibMusic.h\" />\r\n    <ClInclude Include=\"Engine\\Adlib\\adlplayer.h\" />\r\n    <ClInclude Include=\"Engine\\Adlib\\fmopl.h\" />\r\n    <ClInclude Include=\"Engine\\CatFile.h\" />\r\n    <ClInclude Include=\"Engine\\Collections.h\" />\r\n    <ClInclude Include=\"Engine\\CrossPlatform.h\" />\r\n    <ClInclude Include=\"Engine\\DosFont.h\" />\r\n    <ClInclude Include=\"Engine\\Exception.h\" />\r\n    <ClInclude Include=\"Engine\\FastLineClip.h\" />\r\n    <ClInclude Include=\"Engine\\FileMap.h\" />\r\n    <ClInclude Include=\"Engine\\FlcPlayer.h\" />\r\n    <ClInclude Include=\"Engine\\Font.h\" />\r\n    <ClInclude Include=\"Engine\\Functions.h\" />\r\n    <ClInclude Include=\"Engine\\Game.h\" />\r\n    <ClInclude Include=\"Engine\\GMCat.h\" />\r\n    <ClInclude Include=\"Engine\\GraphSubset.h\" />\r\n    <ClInclude Include=\"Engine\\HelperMeta.h\" />\r\n    <ClInclude Include=\"Engine\\InteractiveSurface.h\" />\r\n    <ClInclude Include=\"Engine\\Language.h\" />\r\n    <ClInclude Include=\"Engine\\LanguagePlurality.h\" />\r\n    <ClInclude Include=\"Engine\\LocalizedText.h\" />\r\n    <ClInclude Include=\"Engine\\Logger.h\" />\r\n    <ClInclude Include=\"Engine\\ModInfo.h\" />\r\n    <ClInclude Include=\"Engine\\Music.h\" />\r\n    <ClInclude Include=\"Engine\\NullableValue.h\" />\r\n    <ClInclude Include=\"Engine\\OpenGL.h\" />\r\n    <ClInclude Include=\"Engine\\OptionInfo.h\" />\r\n    <ClInclude Include=\"Engine\\Options.h\" />\r\n    <ClInclude Include=\"Engine\\Options.inc.h\" />\r\n    <ClInclude Include=\"Engine\\Palette.h\" />\r\n    <ClInclude Include=\"Engine\\RNG.h\" />\r\n    <ClInclude Include=\"Engine\\Scalers\\common.h\" />\r\n    <ClInclude Include=\"Engine\\Scalers\\config.h\" />\r\n    <ClInclude Include=\"Engine\\Scalers\\hqx.h\" />\r\n    <ClInclude Include=\"Engine\\Scalers\\scale2x.h\" />\r\n    <ClInclude Include=\"Engine\\Scalers\\scale3x.h\" />\r\n    <ClInclude Include=\"Engine\\Scalers\\scalebit.h\" />\r\n    <ClInclude Include=\"Engine\\Scalers\\xbrz.h\" />\r\n    <ClInclude Include=\"Engine\\Screen.h\" />\r\n    <ClInclude Include=\"Engine\\Script.h\" />\r\n    <ClInclude Include=\"Engine\\ScriptBind.h\" />\r\n    <ClInclude Include=\"Engine\\SDL2Helpers.h\" />\r\n    <ClInclude Include=\"Engine\\ShaderDraw.h\" />\r\n    <ClInclude Include=\"Engine\\ShaderDrawHelper.h\" />\r\n    <ClInclude Include=\"Engine\\ShaderMove.h\" />\r\n    <ClInclude Include=\"Engine\\ShaderRepeat.h\" />\r\n    <ClInclude Include=\"Engine\\Sound.h\" />\r\n    <ClInclude Include=\"Engine\\SoundSet.h\" />\r\n    <ClInclude Include=\"Engine\\State.h\" />\r\n    <ClInclude Include=\"Engine\\Surface.h\" />\r\n    <ClInclude Include=\"Engine\\SurfaceSet.h\" />\r\n    <ClInclude Include=\"Engine\\Timer.h\" />\r\n    <ClInclude Include=\"Engine\\TouchState.h\" />\r\n    <ClInclude Include=\"Engine\\Unicode.h\" />\r\n    <ClInclude Include=\"Engine\\Yaml.h\" />\r\n    <ClInclude Include=\"Engine\\Zoom.h\" />\r\n    <ClInclude Include=\"fallthrough.h\" />\r\n    <ClInclude Include=\"fmath.h\" />\r\n    <ClInclude Include=\"Geoscape\\AlienBaseState.h\" />\r\n    <ClInclude Include=\"Geoscape\\AllocateTrainingState.h\" />\r\n    <ClInclude Include=\"Geoscape\\Cord.h\" />\r\n    <ClInclude Include=\"Geoscape\\CraftNotEnoughPilotsState.h\" />\r\n    <ClInclude Include=\"Geoscape\\DogfightErrorState.h\" />\r\n    <ClInclude Include=\"Geoscape\\DogfightExperienceState.h\" />\r\n    <ClInclude Include=\"Geoscape\\ExtendedGeoscapeLinksState.h\" />\r\n    <ClInclude Include=\"Geoscape\\GeoscapeEventState.h\" />\r\n    <ClInclude Include=\"Geoscape\\MissionDetectedState.h\" />\r\n    <ClInclude Include=\"Geoscape\\AllocatePsiTrainingState.h\" />\r\n    <ClInclude Include=\"Geoscape\\BaseDefenseState.h\" />\r\n    <ClInclude Include=\"Geoscape\\BaseDestroyedState.h\" />\r\n    <ClInclude Include=\"Geoscape\\BaseNameState.h\" />\r\n    <ClInclude Include=\"Geoscape\\BuildNewBaseState.h\" />\r\n    <ClInclude Include=\"Geoscape\\ConfirmCydoniaState.h\" />\r\n    <ClInclude Include=\"Geoscape\\CraftErrorState.h\" />\r\n    <ClInclude Include=\"Geoscape\\ConfirmDestinationState.h\" />\r\n    <ClInclude Include=\"Geoscape\\ConfirmLandingState.h\" />\r\n    <ClInclude Include=\"Geoscape\\ConfirmNewBaseState.h\" />\r\n    <ClInclude Include=\"Geoscape\\CraftPatrolState.h\" />\r\n    <ClInclude Include=\"Geoscape\\DogfightState.h\" />\r\n    <ClInclude Include=\"Geoscape\\FundingState.h\" />\r\n    <ClInclude Include=\"Geoscape\\NewPossibleCraftState.h\" />\r\n    <ClInclude Include=\"Geoscape\\NewPossibleFacilityState.h\" />\r\n    <ClInclude Include=\"Geoscape\\NewPossiblePurchaseState.h\" />\r\n    <ClInclude Include=\"Geoscape\\ResearchRequiredState.h\" />\r\n    <ClInclude Include=\"Geoscape\\GeoscapeCraftState.h\" />\r\n    <ClInclude Include=\"Geoscape\\NewPossibleManufactureState.h\" />\r\n    <ClInclude Include=\"Geoscape\\NewPossibleResearchState.h\" />\r\n    <ClInclude Include=\"Geoscape\\ProductionCompleteState.h\" />\r\n    <ClInclude Include=\"Geoscape\\GeoscapeState.h\" />\r\n    <ClInclude Include=\"Geoscape\\Globe.h\" />\r\n    <ClInclude Include=\"Geoscape\\GraphsState.h\" />\r\n    <ClInclude Include=\"Geoscape\\InterceptState.h\" />\r\n    <ClInclude Include=\"Geoscape\\ItemsArrivingState.h\" />\r\n    <ClInclude Include=\"Geoscape\\LowFuelState.h\" />\r\n    <ClInclude Include=\"Geoscape\\MonthlyReportState.h\" />\r\n    <ClInclude Include=\"Geoscape\\MultipleTargetsState.h\" />\r\n    <ClInclude Include=\"Geoscape\\PsiTrainingState.h\" />\r\n    <ClInclude Include=\"Geoscape\\ResearchCompleteState.h\" />\r\n    <ClInclude Include=\"Geoscape\\SelectDestinationState.h\" />\r\n    <ClInclude Include=\"Geoscape\\SelectMusicTrackState.h\" />\r\n    <ClInclude Include=\"Geoscape\\TargetInfoState.h\" />\r\n    <ClInclude Include=\"Geoscape\\TrainingFinishedState.h\" />\r\n    <ClInclude Include=\"Geoscape\\TrainingState.h\" />\r\n    <ClInclude Include=\"Geoscape\\UfoDetectedState.h\" />\r\n    <ClInclude Include=\"Geoscape\\UfoLostState.h\" />\r\n    <ClInclude Include=\"Geoscape\\UfoTrackerState.h\" />\r\n    <ClInclude Include=\"Interface\\ArrowButton.h\" />\r\n    <ClInclude Include=\"Interface\\Bar.h\" />\r\n    <ClInclude Include=\"Interface\\BattlescapeButton.h\" />\r\n    <ClInclude Include=\"Interface\\ComboBox.h\" />\r\n    <ClInclude Include=\"Interface\\Cursor.h\" />\r\n    <ClInclude Include=\"Interface\\FpsCounter.h\" />\r\n    <ClInclude Include=\"Interface\\Frame.h\" />\r\n    <ClInclude Include=\"Interface\\ImageButton.h\" />\r\n    <ClInclude Include=\"Interface\\NumberText.h\" />\r\n    <ClInclude Include=\"Interface\\ProgressBar.h\" />\r\n    <ClInclude Include=\"Interface\\ScrollBar.h\" />\r\n    <ClInclude Include=\"Interface\\Slider.h\" />\r\n    <ClInclude Include=\"Interface\\Text.h\" />\r\n    <ClInclude Include=\"Interface\\TextButton.h\" />\r\n    <ClInclude Include=\"Interface\\TextEdit.h\" />\r\n    <ClInclude Include=\"Interface\\TextList.h\" />\r\n    <ClInclude Include=\"Interface\\ToggleTextButton.h\" />\r\n    <ClInclude Include=\"Interface\\Window.h\" />\r\n    <ClInclude Include=\"lodepng.h\" />\r\n    <ClInclude Include=\"md5.h\" />\r\n    <ClInclude Include=\"Menu\\AbandonGameState.h\" />\r\n    <ClInclude Include=\"Menu\\ConfirmLoadState.h\" />\r\n    <ClInclude Include=\"Menu\\CutsceneState.h\" />\r\n    <ClInclude Include=\"Menu\\ListGamesState.h\" />\r\n    <ClInclude Include=\"Menu\\ListLoadOriginalState.h\" />\r\n    <ClInclude Include=\"Menu\\ListLoadState.h\" />\r\n    <ClInclude Include=\"Menu\\ListSaveState.h\" />\r\n    <ClInclude Include=\"Menu\\LoadGameState.h\" />\r\n    <ClInclude Include=\"Menu\\ModConfirmExtendedState.h\" />\r\n    <ClInclude Include=\"Menu\\NotesState.h\" />\r\n    <ClInclude Include=\"Menu\\OptionsAdvancedState.h\" />\r\n    <ClInclude Include=\"Menu\\DeleteGameState.h\" />\r\n    <ClInclude Include=\"Menu\\ErrorMessageState.h\" />\r\n    <ClInclude Include=\"Menu\\OptionsAudioState.h\" />\r\n    <ClInclude Include=\"Menu\\OptionsConfirmState.h\" />\r\n    <ClInclude Include=\"Menu\\OptionsDefaultsState.h\" />\r\n    <ClInclude Include=\"Menu\\OptionsFoldersState.h\" />\r\n    <ClInclude Include=\"Menu\\OptionsGeoscapeState.h\" />\r\n    <ClInclude Include=\"Menu\\MainMenuState.h\" />\r\n    <ClInclude Include=\"Menu\\NewBattleState.h\" />\r\n    <ClInclude Include=\"Menu\\NewGameState.h\" />\r\n    <ClInclude Include=\"Menu\\OptionsBaseState.h\" />\r\n    <ClInclude Include=\"Menu\\OptionsBattlescapeState.h\" />\r\n    <ClInclude Include=\"Menu\\OptionsControlsState.h\" />\r\n    <ClInclude Include=\"Menu\\ModListState.h\" />\r\n    <ClInclude Include=\"Menu\\OptionsNoAudioState.h\" />\r\n    <ClInclude Include=\"Menu\\OptionsVideoState.h\" />\r\n    <ClInclude Include=\"Menu\\PauseState.h\" />\r\n    <ClInclude Include=\"Menu\\SaveGameState.h\" />\r\n    <ClInclude Include=\"Menu\\SetWindowedRootState.h\" />\r\n    <ClInclude Include=\"Menu\\SlideshowState.h\" />\r\n    <ClInclude Include=\"Menu\\StartState.h\" />\r\n    <ClInclude Include=\"Menu\\StatisticsState.h\" />\r\n    <ClInclude Include=\"Menu\\TestPaletteState.h\" />\r\n    <ClInclude Include=\"Menu\\TestState.h\" />\r\n    <ClInclude Include=\"Menu\\VideoState.h\" />\r\n    <ClInclude Include=\"Mod\\CustomPalettes.h\" />\r\n    <ClInclude Include=\"Mod\\ModScript.h\" />\r\n    <ClInclude Include=\"Mod\\RuleArcScript.h\" />\r\n    <ClInclude Include=\"Mod\\RuleBaseFacilityFunctions.h\" />\r\n    <ClInclude Include=\"Mod\\RuleDamageType.h\" />\r\n    <ClInclude Include=\"Mod\\RuleEnviroEffects.h\" />\r\n    <ClInclude Include=\"Mod\\RuleEvent.h\" />\r\n    <ClInclude Include=\"Mod\\RuleEventScript.h\" />\r\n    <ClInclude Include=\"Mod\\RuleItemCategory.h\" />\r\n    <ClInclude Include=\"Mod\\RuleManufactureShortcut.h\" />\r\n    <ClInclude Include=\"Mod\\RuleSkill.h\" />\r\n    <ClInclude Include=\"Mod\\RuleSoldierBonus.h\" />\r\n    <ClInclude Include=\"Mod\\RuleSoldierTransformation.h\" />\r\n    <ClInclude Include=\"Mod\\RuleStartingCondition.h\" />\r\n    <ClInclude Include=\"Mod\\RuleStatBonus.h\" />\r\n    <ClInclude Include=\"Mod\\RuleCommendations.h\" />\r\n    <ClInclude Include=\"Mod\\RuleConverter.h\" />\r\n    <ClInclude Include=\"Mod\\RuleWeaponSet.h\" />\r\n    <ClInclude Include=\"resource.h\" />\r\n    <ClInclude Include=\"Mod\\ArticleDefinition.h\" />\r\n    <ClInclude Include=\"Mod\\City.h\" />\r\n    <ClInclude Include=\"Mod\\ExtraSounds.h\" />\r\n    <ClInclude Include=\"Mod\\ExtraSprites.h\" />\r\n    <ClInclude Include=\"Mod\\ExtraStrings.h\" />\r\n    <ClInclude Include=\"Mod\\RuleMissionScript.h\" />\r\n    <ClInclude Include=\"Mod\\Texture.h\" />\r\n    <ClInclude Include=\"Mod\\LoadYaml.h\" />\r\n    <ClInclude Include=\"Mod\\MapBlock.h\" />\r\n    <ClInclude Include=\"Mod\\MapDataSet.h\" />\r\n    <ClInclude Include=\"Mod\\MapData.h\" />\r\n    <ClInclude Include=\"Mod\\AlienDeployment.h\" />\r\n    <ClInclude Include=\"Mod\\AlienRace.h\" />\r\n    <ClInclude Include=\"Mod\\MapScript.h\" />\r\n    <ClInclude Include=\"Mod\\MCDPatch.h\" />\r\n    <ClInclude Include=\"Mod\\Polygon.h\" />\r\n    <ClInclude Include=\"Mod\\Polyline.h\" />\r\n    <ClInclude Include=\"Mod\\RuleGlobe.h\" />\r\n    <ClInclude Include=\"Mod\\RuleMusic.h\" />\r\n    <ClInclude Include=\"Mod\\RuleVideo.h\" />\r\n    <ClInclude Include=\"Mod\\SoundDefinition.h\" />\r\n    <ClInclude Include=\"Mod\\StatString.h\" />\r\n    <ClInclude Include=\"Mod\\StatStringCondition.h\" />\r\n    <ClInclude Include=\"Mod\\RuleInterface.h\" />\r\n    <ClInclude Include=\"Mod\\Unit.h\" />\r\n    <ClInclude Include=\"Mod\\Armor.h\" />\r\n    <ClInclude Include=\"Mod\\RuleAlienMission.h\" />\r\n    <ClInclude Include=\"Mod\\RuleBaseFacility.h\" />\r\n    <ClInclude Include=\"Mod\\RuleCountry.h\" />\r\n    <ClInclude Include=\"Mod\\RuleCraft.h\" />\r\n    <ClInclude Include=\"Mod\\RuleCraftWeapon.h\" />\r\n    <ClInclude Include=\"Mod\\RuleInventory.h\" />\r\n    <ClInclude Include=\"Mod\\RuleItem.h\" />\r\n    <ClInclude Include=\"Mod\\RuleManufacture.h\" />\r\n    <ClInclude Include=\"Mod\\RuleRegion.h\" />\r\n    <ClInclude Include=\"Mod\\RuleResearch.h\" />\r\n    <ClInclude Include=\"Mod\\Mod.h\" />\r\n    <ClInclude Include=\"Mod\\RuleSoldier.h\" />\r\n    <ClInclude Include=\"Mod\\RuleUfo.h\" />\r\n    <ClInclude Include=\"Mod\\RuleTerrain.h\" />\r\n    <ClInclude Include=\"Mod\\SoldierNamePool.h\" />\r\n    <ClInclude Include=\"Mod\\UfoTrajectory.h\" />\r\n    <ClInclude Include=\"Savegame\\AlienBase.h\" />\r\n    <ClInclude Include=\"Savegame\\AlienStrategy.h\" />\r\n    <ClInclude Include=\"Savegame\\AlienMission.h\" />\r\n    <ClInclude Include=\"Savegame\\Base.h\" />\r\n    <ClInclude Include=\"Savegame\\BaseFacility.h\" />\r\n    <ClInclude Include=\"Savegame\\BattleItem.h\" />\r\n    <ClInclude Include=\"Savegame\\BattleUnit.h\" />\r\n    <ClInclude Include=\"Savegame\\BattleUnitStatistics.h\" />\r\n    <ClInclude Include=\"Savegame\\Country.h\" />\r\n    <ClInclude Include=\"Savegame\\Craft.h\" />\r\n    <ClInclude Include=\"Savegame\\CraftWeapon.h\" />\r\n    <ClInclude Include=\"Savegame\\CraftWeaponProjectile.h\" />\r\n    <ClInclude Include=\"Savegame\\EquipmentLayoutItem.h\" />\r\n    <ClInclude Include=\"Savegame\\GameTime.h\" />\r\n    <ClInclude Include=\"Savegame\\GeoscapeEvent.h\" />\r\n    <ClInclude Include=\"Savegame\\HitLog.h\" />\r\n    <ClInclude Include=\"Savegame\\ItemContainer.h\" />\r\n    <ClInclude Include=\"Savegame\\MissionStatistics.h\" />\r\n    <ClInclude Include=\"Savegame\\MovingTarget.h\" />\r\n    <ClInclude Include=\"Savegame\\Production.h\" />\r\n    <ClInclude Include=\"Savegame\\RankCount.h\" />\r\n    <ClInclude Include=\"Savegame\\Region.h\" />\r\n    <ClInclude Include=\"Savegame\\ResearchDiary.h\" />\r\n    <ClInclude Include=\"Savegame\\ResearchProject.h\" />\r\n    <ClInclude Include=\"Savegame\\SaveConverter.h\" />\r\n    <ClInclude Include=\"Savegame\\SavedBattleGame.h\" />\r\n    <ClInclude Include=\"Savegame\\SavedGame.h\" />\r\n    <ClInclude Include=\"Savegame\\SerializationHelper.h\" />\r\n    <ClInclude Include=\"Savegame\\Soldier.h\" />\r\n    <ClInclude Include=\"Savegame\\Node.h\" />\r\n    <ClInclude Include=\"Savegame\\SoldierAvatar.h\" />\r\n    <ClInclude Include=\"Savegame\\SoldierDeath.h\" />\r\n    <ClInclude Include=\"Savegame\\SoldierDiary.h\" />\r\n    <ClInclude Include=\"Savegame\\Target.h\" />\r\n    <ClInclude Include=\"Savegame\\MissionSite.h\" />\r\n    <ClInclude Include=\"Savegame\\Tile.h\" />\r\n    <ClInclude Include=\"Savegame\\Transfer.h\" />\r\n    <ClInclude Include=\"Savegame\\Ufo.h\" />\r\n    <ClInclude Include=\"Savegame\\Vehicle.h\" />\r\n    <ClInclude Include=\"Savegame\\Waypoint.h\" />\r\n    <ClInclude Include=\"Savegame\\WeightedOptions.h\" />\r\n    <ClInclude Include=\"Ufopaedia\\ArticleState.h\" />\r\n    <ClInclude Include=\"Ufopaedia\\ArticleStateArmor.h\" />\r\n    <ClInclude Include=\"Ufopaedia\\ArticleStateBaseFacility.h\" />\r\n    <ClInclude Include=\"Ufopaedia\\ArticleStateCraft.h\" />\r\n    <ClInclude Include=\"Ufopaedia\\ArticleStateCraftWeapon.h\" />\r\n    <ClInclude Include=\"Ufopaedia\\ArticleStateItem.h\" />\r\n    <ClInclude Include=\"Ufopaedia\\ArticleStateSoldier.h\" />\r\n    <ClInclude Include=\"Ufopaedia\\ArticleStateText.h\" />\r\n    <ClInclude Include=\"Ufopaedia\\ArticleStateTextImage.h\" />\r\n    <ClInclude Include=\"Ufopaedia\\ArticleStateTFTD.h\" />\r\n    <ClInclude Include=\"Ufopaedia\\ArticleStateTFTDArmor.h\" />\r\n    <ClInclude Include=\"Ufopaedia\\ArticleStateTFTDCraft.h\" />\r\n    <ClInclude Include=\"Ufopaedia\\ArticleStateTFTDCraftWeapon.h\" />\r\n    <ClInclude Include=\"Ufopaedia\\ArticleStateTFTDFacility.h\" />\r\n    <ClInclude Include=\"Ufopaedia\\ArticleStateTFTDItem.h\" />\r\n    <ClInclude Include=\"Ufopaedia\\ArticleStateTFTDUso.h\" />\r\n    <ClInclude Include=\"Ufopaedia\\ArticleStateTFTDVehicle.h\" />\r\n    <ClInclude Include=\"Ufopaedia\\ArticleStateUfo.h\" />\r\n    <ClInclude Include=\"Ufopaedia\\ArticleStateUnit.h\" />\r\n    <ClInclude Include=\"Ufopaedia\\ArticleStateVehicle.h\" />\r\n    <ClInclude Include=\"Ufopaedia\\StatsForNerdsState.h\" />\r\n    <ClInclude Include=\"Ufopaedia\\Ufopaedia.h\" />\r\n    <ClInclude Include=\"Ufopaedia\\UfopaediaSelectState.h\" />\r\n    <ClInclude Include=\"Ufopaedia\\UfopaediaStartState.h\" />\r\n    <ClInclude Include=\"version.h\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <None Include=\"..\\res\\windows\\openxcom.ico\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ResourceCompile Include=\"OpenXcom.rc\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <Natvis Include=\"..\\libs\\rapidyaml\\c4\\c4core.natvis\" />\r\n    <Natvis Include=\"..\\libs\\rapidyaml\\ryml.natvis\" />\r\n  </ItemGroup>\r\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\r\n  <ImportGroup Label=\"ExtensionTargets\">\r\n  </ImportGroup>\r\n</Project>"
  },
  {
    "path": "src/OpenXcom.2010.vcxproj.filters",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\r\n  <ItemGroup>\r\n    <ClCompile Include=\"main.cpp\" />\r\n    <ClCompile Include=\"Basescape\\MiniBaseView.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\MonthlyCostsState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\PlaceFacilityState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\PurchaseState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\ResearchState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\SackSoldierState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\SellState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\SoldierInfoState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\SoldiersState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\StoresState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\BaseInfoState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\BasescapeState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\BaseView.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\BuildFacilitiesState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\CraftInfoState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\CraftSoldiersState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\CraftsState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\CraftWeaponsState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\DismantleFacilityState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\Screen.cpp\">\r\n      <Filter>Engine</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\Script.cpp\">\r\n      <Filter>Engine</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\Sound.cpp\">\r\n      <Filter>Engine</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\SoundSet.cpp\">\r\n      <Filter>Engine</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\State.cpp\">\r\n      <Filter>Engine</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\Surface.cpp\">\r\n      <Filter>Engine</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\SurfaceSet.cpp\">\r\n      <Filter>Engine</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\Timer.cpp\">\r\n      <Filter>Engine</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\Font.cpp\">\r\n      <Filter>Engine</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\Game.cpp\">\r\n      <Filter>Engine</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\InteractiveSurface.cpp\">\r\n      <Filter>Engine</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\Language.cpp\">\r\n      <Filter>Engine</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\LocalizedText.cpp\">\r\n      <Filter>Engine</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\Music.cpp\">\r\n      <Filter>Engine</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\Palette.cpp\">\r\n      <Filter>Engine</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\RNG.cpp\">\r\n      <Filter>Engine</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Interface\\TextButton.cpp\">\r\n      <Filter>Interface</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Interface\\TextEdit.cpp\">\r\n      <Filter>Interface</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Interface\\TextList.cpp\">\r\n      <Filter>Interface</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Interface\\Window.cpp\">\r\n      <Filter>Interface</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Interface\\ArrowButton.cpp\">\r\n      <Filter>Interface</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Interface\\Bar.cpp\">\r\n      <Filter>Interface</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Interface\\Cursor.cpp\">\r\n      <Filter>Interface</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Interface\\ImageButton.cpp\">\r\n      <Filter>Interface</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Interface\\Text.cpp\">\r\n      <Filter>Interface</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Menu\\StartState.cpp\">\r\n      <Filter>Menu</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Menu\\TestState.cpp\">\r\n      <Filter>Menu</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Menu\\MainMenuState.cpp\">\r\n      <Filter>Menu</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Menu\\NewGameState.cpp\">\r\n      <Filter>Menu</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Savegame\\SavedGame.cpp\">\r\n      <Filter>Savegame</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Savegame\\Soldier.cpp\">\r\n      <Filter>Savegame</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Savegame\\Target.cpp\">\r\n      <Filter>Savegame</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Savegame\\Ufo.cpp\">\r\n      <Filter>Savegame</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Savegame\\Waypoint.cpp\">\r\n      <Filter>Savegame</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Savegame\\Base.cpp\">\r\n      <Filter>Savegame</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Savegame\\BaseFacility.cpp\">\r\n      <Filter>Savegame</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Savegame\\Country.cpp\">\r\n      <Filter>Savegame</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Savegame\\Craft.cpp\">\r\n      <Filter>Savegame</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Savegame\\CraftWeapon.cpp\">\r\n      <Filter>Savegame</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Savegame\\GameTime.cpp\">\r\n      <Filter>Savegame</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Savegame\\MovingTarget.cpp\">\r\n      <Filter>Savegame</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Savegame\\Region.cpp\">\r\n      <Filter>Savegame</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\ConfirmDestinationState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\ConfirmNewBaseState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\CraftPatrolState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\DogfightState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\FundingState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\GeoscapeCraftState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\GeoscapeState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\Globe.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\GraphsState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\InterceptState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\LowFuelState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\MonthlyReportState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\MultipleTargetsState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\SelectDestinationState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\TargetInfoState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\UfoDetectedState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\UfoLostState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\BaseNameState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\BuildNewBaseState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\PlaceLiftState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\Action.cpp\">\r\n      <Filter>Engine</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\GMCat.cpp\">\r\n      <Filter>Engine</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\CatFile.cpp\">\r\n      <Filter>Engine</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\BattlescapeState.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\Map.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Savegame\\SavedBattleGame.cpp\">\r\n      <Filter>Savegame</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Savegame\\Tile.cpp\">\r\n      <Filter>Savegame</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Savegame\\Node.cpp\">\r\n      <Filter>Savegame</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Savegame\\BattleUnit.cpp\">\r\n      <Filter>Savegame</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Interface\\FpsCounter.cpp\">\r\n      <Filter>Interface</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\UnitSprite.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Interface\\NumberText.cpp\">\r\n      <Filter>Interface</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\Pathfinding.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\PathfindingNode.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\PathfindingOpenSet.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Savegame\\BattleItem.cpp\">\r\n      <Filter>Savegame</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\ConfirmLandingState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\BattlescapeGenerator.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Savegame\\ItemContainer.cpp\">\r\n      <Filter>Savegame</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\Projectile.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Savegame\\Transfer.cpp\">\r\n      <Filter>Savegame</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\BattleState.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\TransfersState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\ExplosionBState.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\ProjectileFlyBState.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\UnitTurnBState.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\UnitWalkBState.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\Explosion.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\ItemsArrivingState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Ufopaedia\\ArticleState.cpp\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Ufopaedia\\ArticleStateText.cpp\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Ufopaedia\\ArticleStateTextImage.cpp\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Ufopaedia\\Ufopaedia.cpp\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Ufopaedia\\UfopaediaSelectState.cpp\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Ufopaedia\\UfopaediaStartState.cpp\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\ProductionCompleteState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Ufopaedia\\ArticleStateCraft.cpp\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Ufopaedia\\ArticleStateCraftWeapon.cpp\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\CraftEquipmentState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\CraftArmorState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\SoldierArmorState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\TransferItemsState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\TransferBaseState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\ActionMenuItem.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\TransferConfirmState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\CrossPlatform.cpp\">\r\n      <Filter>Engine</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\ModInfo.cpp\">\r\n      <Filter>Engine</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\FileMap.cpp\">\r\n      <Filter>Engine</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\ActionMenuState.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\UnitInfoState.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\PrimeGrenadeState.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\Options.cpp\">\r\n      <Filter>Engine</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Ufopaedia\\ArticleStateBaseFacility.cpp\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Ufopaedia\\ArticleStateItem.cpp\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Ufopaedia\\ArticleStateUfo.cpp\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\NextTurnState.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\InventoryState.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\Inventory.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\WarningMessage.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\BattlescapeMessage.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\AbortMissionState.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\DebriefingState.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\NewResearchListState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\NewPossibleResearchState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Savegame\\ResearchProject.cpp\">\r\n      <Filter>Savegame</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\InfoboxState.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\TileEngine.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\UnitDieBState.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Ufopaedia\\ArticleStateArmor.cpp\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\MiniMapState.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\MiniMapView.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Savegame\\Production.cpp\">\r\n      <Filter>Savegame</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\Camera.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\MedikitState.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\MedikitView.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\ScannerState.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\ScannerView.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\PromotionsState.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\BattlescapeGame.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\InfoboxOKState.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Savegame\\CraftWeaponProjectile.cpp\">\r\n      <Filter>Savegame</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Menu\\NewBattleState.cpp\">\r\n      <Filter>Menu</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\ManufactureStartState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\ManageAlienContainmentState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\ManufactureInfoState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\NewManufactureListState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\ResearchInfoState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\ManufactureState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\ResearchCompleteState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\BriefingState.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Menu\\ErrorMessageState.cpp\">\r\n      <Filter>Menu</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\CraftErrorState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Savegame\\Vehicle.cpp\">\r\n      <Filter>Savegame</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"lodepng.cpp\" />\r\n    <ClCompile Include=\"Battlescape\\CannotReequipState.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Ufopaedia\\ArticleStateVehicle.cpp\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\NewPossibleManufactureState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\SelectStartFacilityState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Savegame\\EquipmentLayoutItem.cpp\">\r\n      <Filter>Savegame</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\PlaceStartFacilityState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Savegame\\AlienBase.cpp\">\r\n      <Filter>Savegame</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Savegame\\AlienMission.cpp\">\r\n      <Filter>Savegame</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\AlienBaseState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\AllocatePsiTrainingState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\PsiTrainingState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Savegame\\WeightedOptions.cpp\">\r\n      <Filter>Savegame</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Savegame\\AlienStrategy.cpp\">\r\n      <Filter>Savegame</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\BaseDefenseState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Menu\\DeleteGameState.cpp\">\r\n      <Filter>Menu</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\BaseDestroyedState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\ConfirmCydoniaState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\UnitFallBState.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\UnitPanicBState.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\FastLineClip.cpp\">\r\n      <Filter>Engine</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Menu\\OptionsControlsState.cpp\">\r\n      <Filter>Menu</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\Zoom.cpp\">\r\n      <Filter>Engine</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\Zoom.cpp\">\r\n      <Filter>Engine</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\Scalers\\hq2x.cpp\">\r\n      <Filter>Engine\\Scalers</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\Scalers\\hq3x.cpp\">\r\n      <Filter>Engine\\Scalers</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\Scalers\\hq4x.cpp\">\r\n      <Filter>Engine\\Scalers</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\Scalers\\init.cpp\">\r\n      <Filter>Engine\\Scalers</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\Zoom.cpp\">\r\n      <Filter>Engine</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\Scalers\\scale2x.cpp\">\r\n      <Filter>Engine\\Scalers</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\Scalers\\scale3x.cpp\">\r\n      <Filter>Engine\\Scalers</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\Scalers\\scalebit.cpp\">\r\n      <Filter>Engine\\Scalers</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\OpenGL.cpp\">\r\n      <Filter>Engine</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Interface\\ToggleTextButton.cpp\">\r\n      <Filter>Interface</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Savegame\\SerializationHelper.cpp\">\r\n      <Filter>Savegame</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Interface\\Slider.cpp\">\r\n      <Filter>Interface</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Interface\\Frame.cpp\">\r\n      <Filter>Interface</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\LanguagePlurality.cpp\">\r\n      <Filter>Engine</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Menu\\PauseState.cpp\">\r\n      <Filter>Menu</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Menu\\AbandonGameState.cpp\">\r\n      <Filter>Menu</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Menu\\OptionsAdvancedState.cpp\">\r\n      <Filter>Menu</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Menu\\OptionsBattlescapeState.cpp\">\r\n      <Filter>Menu</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Menu\\OptionsBaseState.cpp\">\r\n      <Filter>Menu</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\AliensCrashState.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\ResearchRequiredState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Savegame\\SoldierDeath.cpp\">\r\n      <Filter>Savegame</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\SoldierMemorialState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Menu\\OptionsVideoState.cpp\">\r\n      <Filter>Menu</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Menu\\OptionsAudioState.cpp\">\r\n      <Filter>Menu</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Menu\\OptionsGeoscapeState.cpp\">\r\n      <Filter>Menu</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\OptionInfo.cpp\">\r\n      <Filter>Engine</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Interface\\ComboBox.cpp\">\r\n      <Filter>Interface</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Menu\\OptionsDefaultsState.cpp\">\r\n      <Filter>Menu</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Menu\\OptionsConfirmState.cpp\">\r\n      <Filter>Menu</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Menu\\VideoState.cpp\">\r\n      <Filter>Menu</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Menu\\CutsceneState.cpp\">\r\n      <Filter>Menu</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Menu\\SlideshowState.cpp\">\r\n      <Filter>Menu</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Menu\\ConfirmLoadState.cpp\">\r\n      <Filter>Menu</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Menu\\ListGamesState.cpp\">\r\n      <Filter>Menu</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Menu\\ListLoadState.cpp\">\r\n      <Filter>Menu</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Menu\\ListSaveState.cpp\">\r\n      <Filter>Menu</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Menu\\SaveGameState.cpp\">\r\n      <Filter>Menu</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Menu\\LoadGameState.cpp\">\r\n      <Filter>Menu</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\Adlib\\adlplayer.cpp\">\r\n      <Filter>Engine\\Adlib</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\AdlibMusic.cpp\">\r\n      <Filter>Engine</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\Adlib\\fmopl.cpp\">\r\n      <Filter>Engine\\Adlib</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Interface\\ScrollBar.cpp\">\r\n      <Filter>Interface</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Menu\\OptionsNoAudioState.cpp\">\r\n      <Filter>Menu</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Ufopaedia\\ArticleStateTFTD.cpp\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Interface\\BattlescapeButton.cpp\">\r\n      <Filter>Interface</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\Scalers\\xbrz.cpp\">\r\n      <Filter>Engine\\Scalers</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\Particle.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Ufopaedia\\ArticleStateTFTDFacility.cpp\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Ufopaedia\\ArticleStateTFTDCraft.cpp\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Ufopaedia\\ArticleStateTFTDUso.cpp\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Ufopaedia\\ArticleStateTFTDArmor.cpp\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Ufopaedia\\ArticleStateTFTDItem.cpp\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Ufopaedia\\ArticleStateTFTDCraftWeapon.cpp\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Ufopaedia\\ArticleStateTFTDVehicle.cpp\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Savegame\\SaveConverter.cpp\">\r\n      <Filter>Savegame</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Menu\\ListLoadOriginalState.cpp\">\r\n      <Filter>Menu</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\FlcPlayer.cpp\">\r\n      <Filter>Engine</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Savegame\\MissionSite.cpp\">\r\n      <Filter>Savegame</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\MissionDetectedState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\MeleeAttackBState.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\PsiAttackBState.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\DogfightErrorState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\AlienDeployment.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\AlienRace.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\Armor.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\ArticleDefinition.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\City.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\ExtraSounds.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\ExtraSprites.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\ExtraStrings.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\MapBlock.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\MapData.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\MapDataSet.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\MapScript.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\MCDPatch.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\Polygon.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\Polyline.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\RuleAlienMission.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\RuleBaseFacility.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\RuleCountry.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\RuleCraft.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\RuleCraftWeapon.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\RuleGlobe.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\RuleInterface.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\RuleInventory.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\RuleItem.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\RuleManufacture.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\RuleMissionScript.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\RuleMusic.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\RuleRegion.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\RuleResearch.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\RuleSoldier.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\RuleTerrain.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\RuleUfo.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\RuleVideo.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\SoldierNamePool.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\SoundDefinition.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\StatString.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\StatStringCondition.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\Texture.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\UfoTrajectory.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\Unit.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\Mod.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\AllocateTrainingState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\RuleDamageType.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\RuleStatBonus.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\TrainingState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\ItemSprite.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\RuleStartingCondition.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\RuleItemCategory.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\CommendationLateState.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\CommendationState.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\RuleCommendations.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Savegame\\SoldierDiary.cpp\">\r\n      <Filter>Savegame</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\SoldierDiaryMissionState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\SoldierDiaryOverviewState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\SoldierDiaryPerformanceState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\RuleConverter.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\SoldierSortUtil.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\SoldierAvatarState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Savegame\\SoldierAvatar.cpp\">\r\n      <Filter>Savegame</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\ConfirmEndMissionState.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\UfoTrackerState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\TechTreeViewerState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\TechTreeSelectState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\ManufactureDependenciesTreeState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\InventoryLoadState.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\InventorySaveState.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\CraftPilotsState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\CraftPilotSelectState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\CustomPalettes.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Menu\\StatisticsState.cpp\">\r\n      <Filter>Menu</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\AIModule.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Menu\\SetWindowedRootState.cpp\">\r\n      <Filter>Menu</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\AlienInventory.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\AlienInventoryState.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\BriefingLightState.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\CraftNotEnoughPilotsState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\NewPossiblePurchaseState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\NewPossibleCraftState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\NewPossibleFacilityState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\TrainingFinishedState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\CraftEquipmentLoadState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\CraftEquipmentSaveState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Menu\\TestPaletteState.cpp\">\r\n      <Filter>Menu</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\SelectMusicTrackState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Ufopaedia\\StatsForNerdsState.cpp\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\GlobalResearchState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\RuleSoldierTransformation.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\SoldierTransformationState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\Unicode.cpp\">\r\n      <Filter>Engine</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Menu\\ModListState.cpp\">\r\n      <Filter>Menu</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Menu\\ModConfirmExtendedState.cpp\">\r\n      <Filter>Menu</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\libs\\miniz\\miniz.c\" />\r\n    <ClCompile Include=\"Basescape\\GlobalManufactureState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\RuleArcScript.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"md5.cpp\" />\r\n    <ClCompile Include=\"Mod\\RuleEnviroEffects.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\GeoscapeEventState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\RuleEvent.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\RuleEventScript.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Savegame\\GeoscapeEvent.cpp\">\r\n      <Filter>Savegame</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\RuleSoldierBonus.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\SoldierBonusState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Menu\\OptionsFoldersState.cpp\">\r\n      <Filter>Menu</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Savegame\\HitLog.cpp\">\r\n      <Filter>Savegame</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\TurnDiaryState.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\SkillMenuState.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\RuleSkill.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\RuleManufactureShortcut.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\InventoryPersonalState.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\DogfightExperienceState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\SoldierTransformationListState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Menu\\NotesState.cpp\">\r\n      <Filter>Menu</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Geoscape\\ExtendedGeoscapeLinksState.cpp\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\ExtendedBattlescapeLinksState.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\ExtendedInventoryLinksState.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\GlobalAlienContainmentState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\SoldierRankState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Savegame\\RankCount.cpp\">\r\n      <Filter>Savegame</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\SoldierTransformState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Interface\\ProgressBar.cpp\">\r\n      <Filter>Interface</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\SoldierDiaryLightState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\NoExperienceState.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Mod\\RuleWeaponSet.cpp\">\r\n      <Filter>Mod</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\ExperienceOverviewState.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\Yaml.cpp\">\r\n      <Filter>Engine</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Battlescape\\Position.cpp\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\libs\\rapidyaml\\c4\\base64.cpp\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\libs\\rapidyaml\\c4\\char_traits.cpp\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\libs\\rapidyaml\\c4\\error.cpp\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\libs\\rapidyaml\\c4\\format.cpp\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\libs\\rapidyaml\\c4\\language.cpp\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\libs\\rapidyaml\\c4\\memory_resource.cpp\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\libs\\rapidyaml\\c4\\memory_util.cpp\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\libs\\rapidyaml\\c4\\utf.cpp\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\libs\\rapidyaml\\c4\\yml\\common.cpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\yml</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\libs\\rapidyaml\\c4\\yml\\node.cpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\yml</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\libs\\rapidyaml\\c4\\yml\\node_type.cpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\yml</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\libs\\rapidyaml\\c4\\yml\\parse.cpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\yml</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\libs\\rapidyaml\\c4\\yml\\preprocess.cpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\yml</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\libs\\rapidyaml\\c4\\yml\\reference_resolver.cpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\yml</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\libs\\rapidyaml\\c4\\yml\\tag.cpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\yml</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\libs\\rapidyaml\\c4\\yml\\tree.cpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\yml</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\libs\\rapidyaml\\c4\\yml\\version.cpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\yml</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\GlobalResearchDiaryState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Engine\\TouchState.cpp\">\r\n      <Filter>Engine</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Basescape\\ItemLocationsState.cpp\">\r\n      <Filter>Basescape</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Ufopaedia\\ArticleStateSoldier.cpp\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Ufopaedia\\ArticleStateUnit.cpp\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClCompile>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ClInclude Include=\"resource.h\" />\r\n    <ClInclude Include=\"Basescape\\ManufactureState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\ManageAlienContainmentState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\MiniBaseView.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\MonthlyCostsState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\PlaceFacilityState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\PurchaseState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\ResearchState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\SackSoldierState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\SellState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\SoldierInfoState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\SoldiersState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\StoresState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\BaseInfoState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\BasescapeState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\BaseView.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\BuildFacilitiesState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\CraftInfoState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\CraftSoldiersState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\CraftsState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\CraftWeaponsState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\DismantleFacilityState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\RNG.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\Screen.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\Script.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\ScriptBind.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\Sound.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\SoundSet.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\State.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\Surface.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\SurfaceSet.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\Timer.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\Font.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\Game.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\InteractiveSurface.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\Language.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\LocalizedText.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\Music.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\Palette.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Interface\\TextButton.h\">\r\n      <Filter>Interface</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Interface\\TextEdit.h\">\r\n      <Filter>Interface</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Interface\\TextList.h\">\r\n      <Filter>Interface</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Interface\\Window.h\">\r\n      <Filter>Interface</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Interface\\ArrowButton.h\">\r\n      <Filter>Interface</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Interface\\Bar.h\">\r\n      <Filter>Interface</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Interface\\Cursor.h\">\r\n      <Filter>Interface</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Interface\\ImageButton.h\">\r\n      <Filter>Interface</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Interface\\Text.h\">\r\n      <Filter>Interface</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Menu\\NewGameState.h\">\r\n      <Filter>Menu</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Menu\\StartState.h\">\r\n      <Filter>Menu</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Menu\\TestState.h\">\r\n      <Filter>Menu</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Menu\\MainMenuState.h\">\r\n      <Filter>Menu</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Savegame\\SavedGame.h\">\r\n      <Filter>Savegame</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Savegame\\Soldier.h\">\r\n      <Filter>Savegame</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Savegame\\Target.h\">\r\n      <Filter>Savegame</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Savegame\\Ufo.h\">\r\n      <Filter>Savegame</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Savegame\\Waypoint.h\">\r\n      <Filter>Savegame</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Savegame\\Base.h\">\r\n      <Filter>Savegame</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Savegame\\BaseFacility.h\">\r\n      <Filter>Savegame</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Savegame\\Country.h\">\r\n      <Filter>Savegame</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Savegame\\Craft.h\">\r\n      <Filter>Savegame</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Savegame\\CraftWeapon.h\">\r\n      <Filter>Savegame</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Savegame\\GameTime.h\">\r\n      <Filter>Savegame</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Savegame\\MovingTarget.h\">\r\n      <Filter>Savegame</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Savegame\\Region.h\">\r\n      <Filter>Savegame</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\ConfirmDestinationState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\ConfirmNewBaseState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\CraftPatrolState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\DogfightState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\FundingState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\GeoscapeCraftState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\GeoscapeState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\Globe.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\GraphsState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\InterceptState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\LowFuelState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\MonthlyReportState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\MultipleTargetsState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\SelectDestinationState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\TargetInfoState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\UfoDetectedState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\UfoLostState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\BaseNameState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\BuildNewBaseState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\PlaceLiftState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\Action.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\GMCat.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\CatFile.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\BattlescapeState.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\Map.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Savegame\\SavedBattleGame.h\">\r\n      <Filter>Savegame</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Savegame\\Tile.h\">\r\n      <Filter>Savegame</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Savegame\\Node.h\">\r\n      <Filter>Savegame</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Savegame\\BattleUnit.h\">\r\n      <Filter>Savegame</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Interface\\FpsCounter.h\">\r\n      <Filter>Interface</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\UnitSprite.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\Position.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Interface\\NumberText.h\">\r\n      <Filter>Interface</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\Pathfinding.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\PathfindingNode.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\PathfindingOpenSet.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Savegame\\BattleItem.h\">\r\n      <Filter>Savegame</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\ConfirmLandingState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\BattlescapeGenerator.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\Exception.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Savegame\\ItemContainer.h\">\r\n      <Filter>Savegame</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\Projectile.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Savegame\\Transfer.h\">\r\n      <Filter>Savegame</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\BattleState.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\ExplosionBState.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\ProjectileFlyBState.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\UnitTurnBState.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\UnitWalkBState.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\Explosion.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\TransfersState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\ItemsArrivingState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Ufopaedia\\ArticleState.h\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Ufopaedia\\ArticleStateText.h\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Ufopaedia\\ArticleStateTextImage.h\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Ufopaedia\\Ufopaedia.h\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Ufopaedia\\UfopaediaSelectState.h\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Ufopaedia\\UfopaediaStartState.h\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\ProductionCompleteState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Ufopaedia\\ArticleStateCraft.h\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Ufopaedia\\ArticleStateCraftWeapon.h\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\CraftEquipmentState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\CraftArmorState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\SoldierArmorState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\TransferItemsState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\TransferBaseState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\ActionMenuItem.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\TransferConfirmState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\CrossPlatform.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\ModInfo.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\FileMap.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\ActionMenuState.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\UnitInfoState.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\PrimeGrenadeState.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\Options.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Ufopaedia\\ArticleStateBaseFacility.h\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Ufopaedia\\ArticleStateItem.h\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Ufopaedia\\ArticleStateUfo.h\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\NextTurnState.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\InventoryState.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\Inventory.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\WarningMessage.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\BattlescapeMessage.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\AbortMissionState.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\DebriefingState.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\NewResearchListState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\NewPossibleResearchState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Savegame\\ResearchProject.h\">\r\n      <Filter>Savegame</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\InfoboxState.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\TileEngine.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\UnitDieBState.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Ufopaedia\\ArticleStateArmor.h\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\MiniMapState.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\MiniMapView.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Savegame\\Production.h\">\r\n      <Filter>Savegame</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\Camera.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\MedikitState.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\MedikitView.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\ScannerState.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\ScannerView.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\PromotionsState.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\BattlescapeGame.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\InfoboxOKState.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Savegame\\CraftWeaponProjectile.h\">\r\n      <Filter>Savegame</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Menu\\NewBattleState.h\">\r\n      <Filter>Menu</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\ManufactureStartState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\ManufactureInfoState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\ResearchInfoState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\NewManufactureListState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\ResearchCompleteState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\BriefingState.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Menu\\ErrorMessageState.h\">\r\n      <Filter>Menu</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\CraftErrorState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Savegame\\Vehicle.h\">\r\n      <Filter>Savegame</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"lodepng.h\" />\r\n    <ClInclude Include=\"Battlescape\\CannotReequipState.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Ufopaedia\\ArticleStateVehicle.h\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\NewPossibleManufactureState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\Logger.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\SelectStartFacilityState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\PlaceStartFacilityState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Savegame\\AlienBase.h\">\r\n      <Filter>Savegame</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Savegame\\AlienMission.h\">\r\n      <Filter>Savegame</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\AlienBaseState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Savegame\\EquipmentLayoutItem.h\">\r\n      <Filter>Savegame</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\AllocatePsiTrainingState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\PsiTrainingState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Savegame\\WeightedOptions.h\">\r\n      <Filter>Savegame</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Savegame\\AlienStrategy.h\">\r\n      <Filter>Savegame</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\BaseDefenseState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Menu\\DeleteGameState.h\">\r\n      <Filter>Menu</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\ConfirmCydoniaState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\BaseDestroyedState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\UnitFallBState.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\UnitPanicBState.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\FastLineClip.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Menu\\OptionsControlsState.h\">\r\n      <Filter>Menu</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\Zoom.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\Zoom.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\Scalers\\scalebit.h\">\r\n      <Filter>Engine\\Scalers</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\Scalers\\scale2x.h\">\r\n      <Filter>Engine\\Scalers</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\Scalers\\scale3x.h\">\r\n      <Filter>Engine\\Scalers</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\Scalers\\common.h\">\r\n      <Filter>Engine\\Scalers</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\Scalers\\hqx.h\">\r\n      <Filter>Engine\\Scalers</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\Zoom.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Savegame\\SerializationHelper.h\">\r\n      <Filter>Savegame</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\OpenGL.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Interface\\ToggleTextButton.h\">\r\n      <Filter>Interface</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\ShaderDraw.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\ShaderDrawHelper.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\ShaderMove.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\ShaderRepeat.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\GraphSubset.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"version.h\" />\r\n    <ClInclude Include=\"Interface\\Slider.h\">\r\n      <Filter>Interface</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Interface\\Frame.h\">\r\n      <Filter>Interface</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\LanguagePlurality.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Menu\\PauseState.h\">\r\n      <Filter>Menu</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Menu\\AbandonGameState.h\">\r\n      <Filter>Menu</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Menu\\OptionsBaseState.h\">\r\n      <Filter>Menu</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Menu\\OptionsAdvancedState.h\">\r\n      <Filter>Menu</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Menu\\OptionsBattlescapeState.h\">\r\n      <Filter>Menu</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\AliensCrashState.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\ResearchRequiredState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Savegame\\SoldierDeath.h\">\r\n      <Filter>Savegame</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\SoldierMemorialState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Menu\\OptionsVideoState.h\">\r\n      <Filter>Menu</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Menu\\OptionsAudioState.h\">\r\n      <Filter>Menu</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Menu\\OptionsGeoscapeState.h\">\r\n      <Filter>Menu</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\OptionInfo.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Interface\\ComboBox.h\">\r\n      <Filter>Interface</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Menu\\OptionsDefaultsState.h\">\r\n      <Filter>Menu</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Menu\\OptionsConfirmState.h\">\r\n      <Filter>Menu</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Menu\\VideoState.h\">\r\n      <Filter>Menu</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Menu\\CutsceneState.h\">\r\n      <Filter>Menu</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Menu\\SlideshowState.h\">\r\n      <Filter>Menu</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\Options.inc.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Menu\\ConfirmLoadState.h\">\r\n      <Filter>Menu</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Menu\\ListGamesState.h\">\r\n      <Filter>Menu</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Menu\\ListLoadState.h\">\r\n      <Filter>Menu</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Menu\\ListSaveState.h\">\r\n      <Filter>Menu</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Menu\\SaveGameState.h\">\r\n      <Filter>Menu</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Menu\\LoadGameState.h\">\r\n      <Filter>Menu</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\Adlib\\adlplayer.h\">\r\n      <Filter>Engine\\Adlib</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\Adlib\\fmopl.h\">\r\n      <Filter>Engine\\Adlib</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\AdlibMusic.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Interface\\ScrollBar.h\">\r\n      <Filter>Interface</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Menu\\OptionsNoAudioState.h\">\r\n      <Filter>Menu</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"fmath.h\" />\r\n    <ClInclude Include=\"Engine\\DosFont.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Ufopaedia\\ArticleStateTFTD.h\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Interface\\BattlescapeButton.h\">\r\n      <Filter>Interface</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\Scalers\\xbrz.h\">\r\n      <Filter>Engine\\Scalers</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\Scalers\\config.h\">\r\n      <Filter>Engine\\Scalers</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\Particle.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Ufopaedia\\ArticleStateTFTDFacility.h\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Ufopaedia\\ArticleStateTFTDCraft.h\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Ufopaedia\\ArticleStateTFTDUso.h\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Ufopaedia\\ArticleStateTFTDArmor.h\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Ufopaedia\\ArticleStateTFTDItem.h\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Ufopaedia\\ArticleStateTFTDCraftWeapon.h\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Ufopaedia\\ArticleStateTFTDVehicle.h\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Savegame\\SaveConverter.h\">\r\n      <Filter>Savegame</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Menu\\ListLoadOriginalState.h\">\r\n      <Filter>Menu</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\FlcPlayer.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Savegame\\MissionSite.h\">\r\n      <Filter>Savegame</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\MissionDetectedState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\MeleeAttackBState.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\PsiAttackBState.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\DogfightErrorState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\AlienDeployment.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\AlienRace.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\Armor.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\ArticleDefinition.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\City.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\ExtraSounds.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\ExtraSprites.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\ExtraStrings.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\MapBlock.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\MapData.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\MapDataSet.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\MapScript.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\MCDPatch.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\Polygon.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\Polyline.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\RuleAlienMission.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\RuleBaseFacility.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\RuleCountry.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\RuleCraft.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\RuleCraftWeapon.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\RuleGlobe.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\RuleInterface.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\RuleInventory.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\RuleItem.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\RuleManufacture.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\RuleMissionScript.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\RuleMusic.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\RuleRegion.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\RuleResearch.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\RuleSoldier.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\RuleTerrain.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\RuleUfo.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\RuleVideo.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\SoldierNamePool.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\SoundDefinition.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\StatString.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\StatStringCondition.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\Texture.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\UfoTrajectory.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\Unit.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\Mod.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\AllocateTrainingState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\RuleDamageType.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\RuleStatBonus.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\TrainingState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\ItemSprite.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\RuleStartingCondition.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\RuleItemCategory.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Savegame\\BattleUnitStatistics.h\">\r\n      <Filter>Savegame</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\CommendationLateState.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\CommendationState.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\Cord.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Savegame\\MissionStatistics.h\">\r\n      <Filter>Savegame</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\RuleCommendations.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Savegame\\SoldierDiary.h\">\r\n      <Filter>Savegame</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\SoldierDiaryMissionState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\SoldierDiaryOverviewState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\SoldierDiaryPerformanceState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\RuleConverter.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\SoldierSortUtil.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\SoldierAvatarState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Savegame\\SoldierAvatar.h\">\r\n      <Filter>Savegame</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\ConfirmEndMissionState.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\UfoTrackerState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\TechTreeViewerState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\TechTreeSelectState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\ManufactureDependenciesTreeState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\InventoryLoadState.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\InventorySaveState.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\CraftPilotsState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\CraftPilotSelectState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\CustomPalettes.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Menu\\StatisticsState.h\">\r\n      <Filter>Menu</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\AIModule.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Menu\\SetWindowedRootState.h\">\r\n      <Filter>Menu</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\AlienInventory.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\AlienInventoryState.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\BriefingLightState.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\CraftNotEnoughPilotsState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\NewPossiblePurchaseState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\NewPossibleCraftState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\NewPossibleFacilityState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\TrainingFinishedState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\CraftEquipmentLoadState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\CraftEquipmentSaveState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Menu\\TestPaletteState.h\">\r\n      <Filter>Menu</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\SelectMusicTrackState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Ufopaedia\\StatsForNerdsState.h\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\GlobalResearchState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\RuleSoldierTransformation.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\SoldierTransformationState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\Unicode.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Menu\\ModListState.h\">\r\n      <Filter>Menu</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Menu\\ModConfirmExtendedState.h\">\r\n      <Filter>Menu</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\miniz\\miniz.h\" />\r\n    <ClInclude Include=\"Basescape\\GlobalManufactureState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\RuleArcScript.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"md5.h\" />\r\n    <ClInclude Include=\"Mod\\RuleEnviroEffects.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\Collections.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\HelperMeta.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\SDL2Helpers.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\ModScript.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"fallthrough.h\" />\r\n    <ClInclude Include=\"Geoscape\\GeoscapeEventState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\RuleEvent.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\RuleEventScript.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Savegame\\GeoscapeEvent.h\">\r\n      <Filter>Savegame</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\RuleSoldierBonus.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\SoldierBonusState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Menu\\OptionsFoldersState.h\">\r\n      <Filter>Menu</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Savegame\\HitLog.h\">\r\n      <Filter>Savegame</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\TurnDiaryState.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\SkillMenuState.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\RuleSkill.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\RuleManufactureShortcut.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\RuleBaseFacilityFunctions.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\InventoryPersonalState.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\DogfightExperienceState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\Functions.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\SoldierTransformationListState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Menu\\NotesState.h\">\r\n      <Filter>Menu</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Geoscape\\ExtendedGeoscapeLinksState.h\">\r\n      <Filter>Geoscape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\ExtendedBattlescapeLinksState.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\ExtendedInventoryLinksState.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\GlobalAlienContainmentState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\SoldierRankState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Savegame\\RankCount.h\">\r\n      <Filter>Savegame</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\LoadYaml.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\SoldierTransformState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Interface\\ProgressBar.h\">\r\n      <Filter>Interface</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\SoldierDiaryLightState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\NoExperienceState.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Mod\\RuleWeaponSet.h\">\r\n      <Filter>Mod</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Battlescape\\ExperienceOverviewState.h\">\r\n      <Filter>Battlescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\Yaml.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\ryml.hpp\">\r\n      <Filter>Engine\\rapidyaml</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\ryml_std.hpp\">\r\n      <Filter>Engine\\rapidyaml</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\allocator.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\base64.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\bitmask.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\blob.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\c4_pop.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\c4_push.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\char_traits.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\charconv.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\common.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\compiler.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\config.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\cpu.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\ctor_dtor.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\dump.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\enum.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\error.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\export.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\format.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\gcc-4.8.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\hash.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\language.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\memory_resource.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\memory_util.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\platform.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\preprocessor.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\restrict.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\span.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\substr.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\substr_fwd.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\szconv.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\type_name.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\types.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\unrestrict.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\utf.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\windows.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\windows_pop.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\windows_push.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\ext\\fast_float.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\ext</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\ext\\fast_float_all.h\">\r\n      <Filter>Engine\\rapidyaml\\c4\\ext</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\ext\\rng\\rng.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\ext\\rng</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\ext\\sg14\\inplace_function.h\">\r\n      <Filter>Engine\\rapidyaml\\c4\\ext\\sg14</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\std\\std.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\std</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\std\\std_fwd.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\std</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\std\\string.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\std</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\std\\string_fwd.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\std</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\std\\string_view.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\std</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\std\\tuple.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\std</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\std\\vector.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\std</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\std\\vector_fwd.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\std</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\common.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\yml</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\emit.def.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\yml</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\emit.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\yml</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\event_handler_stack.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\yml</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\event_handler_tree.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\yml</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\export.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\yml</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\filter_processor.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\yml</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\fwd.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\yml</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\node.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\yml</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\node_type.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\yml</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\parse.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\yml</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\parse_engine.def.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\yml</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\parse_engine.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\yml</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\parser_state.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\yml</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\preprocess.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\yml</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\reference_resolver.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\yml</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\tag.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\yml</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\tree.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\yml</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\version.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\yml</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\writer.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\yml</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\yml.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\yml</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\detail\\checks.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\yml\\detail</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\detail\\parser_dbg.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\yml\\detail</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\detail\\print.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\yml\\detail</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\detail\\stack.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\yml\\detail</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\std\\map.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\yml\\std</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\std\\std.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\yml\\std</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\std\\string.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\yml\\std</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libs\\rapidyaml\\c4\\yml\\std\\vector.hpp\">\r\n      <Filter>Engine\\rapidyaml\\c4\\yml\\std</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Savegame\\ResearchDiary.h\">\r\n      <Filter>Savegame</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\GlobalResearchDiaryState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\TouchState.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Basescape\\ItemLocationsState.h\">\r\n      <Filter>Basescape</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Engine\\NullableValue.h\">\r\n      <Filter>Engine</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Ufopaedia\\ArticleStateSoldier.h\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Ufopaedia\\ArticleStateUnit.h\">\r\n      <Filter>Ufopaedia</Filter>\r\n    </ClInclude>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <Filter Include=\"Geoscape\">\r\n      <UniqueIdentifier>{f0521223-4515-4155-bf25-5f00373167d5}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Engine\">\r\n      <UniqueIdentifier>{8fafa8d9-0283-4082-9361-01ebd937e3bb}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Interface\">\r\n      <UniqueIdentifier>{e996bc13-2f6a-4a8b-bdd9-7a8621048cea}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Basescape\">\r\n      <UniqueIdentifier>{cc069fa8-f772-4dae-be38-87bcd1013fdd}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Battlescape\">\r\n      <UniqueIdentifier>{f7e493ce-c074-420c-8b38-40d81b2d0509}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Savegame\">\r\n      <UniqueIdentifier>{3b64dd6e-f151-4246-a211-0c6fec5766c5}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Menu\">\r\n      <UniqueIdentifier>{4218da2f-b393-45b2-a55f-da7fa4d91fe4}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Ufopaedia\">\r\n      <UniqueIdentifier>{41135935-090f-4179-a64d-0efbd66b5f5c}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Engine\\Scalers\">\r\n      <UniqueIdentifier>{fef61e76-5d44-4389-a40c-12da6e590e2c}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Engine\\Adlib\">\r\n      <UniqueIdentifier>{09464f19-4bce-449f-a27c-5cd7b9850dbe}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Mod\">\r\n      <UniqueIdentifier>{ea5b1e9f-9ff1-457d-9a15-5af8773ccb50}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Engine\\rapidyaml\">\r\n      <UniqueIdentifier>{0be071a8-546d-40f0-a2e9-f36fa549568c}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Engine\\rapidyaml\\c4\">\r\n      <UniqueIdentifier>{a1203b04-dfc9-47e6-9243-c036c33aa1d7}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Engine\\rapidyaml\\c4\\ext\">\r\n      <UniqueIdentifier>{1ac6e24e-c346-4d98-acde-fb61e5f468f5}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Engine\\rapidyaml\\c4\\ext\\rng\">\r\n      <UniqueIdentifier>{44c74bf0-ac0b-4551-a210-faa15a9327c3}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Engine\\rapidyaml\\c4\\ext\\sg14\">\r\n      <UniqueIdentifier>{b44914e3-3635-4d44-89f1-63592c1d5e17}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Engine\\rapidyaml\\c4\\ext\\debugbreak\">\r\n      <UniqueIdentifier>{c0c64f4a-8d12-4354-8c17-0be6ba14160b}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Engine\\rapidyaml\\c4\\std\">\r\n      <UniqueIdentifier>{98137b59-2141-4ea5-94a2-930128026098}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Engine\\rapidyaml\\c4\\yml\">\r\n      <UniqueIdentifier>{75853d8b-7f68-41d5-83f8-c0adff56fd08}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Engine\\rapidyaml\\c4\\yml\\detail\">\r\n      <UniqueIdentifier>{a24b27c8-e79d-4e81-9c5f-e43ba1a49320}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Engine\\rapidyaml\\c4\\yml\\std\">\r\n      <UniqueIdentifier>{032166e7-3396-4da8-8b9a-79ec1b036488}</UniqueIdentifier>\r\n    </Filter>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ResourceCompile Include=\"OpenXcom.rc\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <None Include=\"..\\res\\windows\\openxcom.ico\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <Natvis Include=\"..\\libs\\rapidyaml\\ryml.natvis\">\r\n      <Filter>Engine\\rapidyaml</Filter>\r\n    </Natvis>\r\n    <Natvis Include=\"..\\libs\\rapidyaml\\c4\\c4core.natvis\">\r\n      <Filter>Engine\\rapidyaml\\c4</Filter>\r\n    </Natvis>\r\n  </ItemGroup>\r\n</Project>"
  },
  {
    "path": "src/OpenXcom.rc",
    "content": "#include \"resource.h\"\n#include \"version.h\"\n#include \"winresrc.h\"\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// Manifest\n//\n\nCREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST \"../res/windows/openxcom.manifest\"\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// Version\n//\n\n VS_VERSION_INFO VERSIONINFO\n FILEVERSION OPENXCOM_VERSION_NUMBER\n PRODUCTVERSION OPENXCOM_VERSION_NUMBER\n FILEFLAGSMASK 0x3fL\n#ifdef _DEBUG\n FILEFLAGS 0x1L\n#else\n FILEFLAGS 0x0L\n#endif\n FILEOS 0x40004L\n FILETYPE 0x1L\n FILESUBTYPE 0x0L\nBEGIN\n    BLOCK \"StringFileInfo\"\n    BEGIN\n        BLOCK \"000004b0\"\n        BEGIN\n            VALUE \"CompanyName\", \"OpenXcom Developers\"\n            VALUE \"FileDescription\", \"OpenXcom Extended\"\n            VALUE \"FileVersion\", OPENXCOM_VERSION_LONG\n            VALUE \"InternalName\", \"OpenXcomEx.exe\"\n            VALUE \"LegalCopyright\", \"Copyright 2010-2019 OpenXcom Developers\"\n            VALUE \"OriginalFilename\", \"OpenXcomEx.exe\"\n            VALUE \"ProductName\", \"OpenXcom Extended\"\n            VALUE \"ProductVersion\", OPENXCOM_VERSION_LONG\n        END\n    END\n    BLOCK \"VarFileInfo\"\n    BEGIN\n        VALUE \"Translation\", 0x0, 1200\n    END\nEND\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// Icon\n//\n// Icon with lowest ID value placed first to ensure application icon\n// remains consistent on all systems.\nIDI_ICON1               ICON                    \"../res/windows/openxcom.ico\"\n\n#ifdef EMBED_ASSETS\n\nIDZ_COMMON_ZIP           RCDATA                  \"../common.zip\"\nIDZ_STANDARD_ZIP         RCDATA                  \"../standard.zip\"\n\n#endif\n"
  },
  {
    "path": "src/OpenXcom.s",
    "content": "\t.section .rodata\n\t.global common_zip\n\t.type common_zip, @object\n\t.align 8\ncommon_zip:\n\t.incbin \"common.zip\"\ncommon_zip_end:\n\n\t.global common_zip_size\n\t.type common_zip_size, @object\n\t.align 8\ncommon_zip_size:\n\t.int common_zip_end - common_zip\n\n\t.global standard_zip\n\t.type standard_zip, @object\n\t.align 8\nstandard_zip:\n\t.incbin \"standard.zip\"\nstandard_zip_end:\n\n\t.global standard_zip_size\n\t.type standard_zip_size, @object\n\t.align 8\nstandard_zip_size:\n\t.int standard_zip_end - standard_zip\n"
  },
  {
    "path": "src/Savegame/AlienBase.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"AlienBase.h\"\n#include \"../Engine/Language.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes an alien base\n */\nAlienBase::AlienBase(AlienDeployment *deployment, int startMonth) : Target(), _inBattlescape(false), _discovered(false), _deployment(deployment), _startMonth(startMonth), _genMissionCount(0)\n{\n\t// allow spawning hunt missions immediately after the base is created, i.e. no initial delay\n\t_minutesSinceLastHuntMissionGeneration = _deployment->getHuntMissionMaxFrequency();\n}\n\n/**\n *\n */\nAlienBase::~AlienBase()\n{\n}\n\n/**\n * Loads the alien base from a YAML file.\n * @param node YAML node.\n */\nvoid AlienBase::load(const YAML::YamlNodeReader& reader)\n{\n\tTarget::load(reader);\n\treader.tryRead(\"pactCountry\", _pactCountry);\n\treader.tryRead(\"race\", _race);\n\treader.tryRead(\"inBattlescape\", _inBattlescape);\n\treader.tryRead(\"discovered\", _discovered);\n\treader.tryRead(\"startMonth\", _startMonth);\n\treader.tryRead(\"minutesSinceLastHuntMissionGeneration\", _minutesSinceLastHuntMissionGeneration);\n\treader.tryRead(\"genMissionCount\", _genMissionCount);\n}\n\n/**\n * Saves the alien base to a YAML file.\n * @return YAML node.\n */\nvoid AlienBase::save(YAML::YamlNodeWriter writer) const\n{\n\twriter.setAsMap();\n\tTarget::save(writer);\n\n\twriter.write(\"pactCountry\", _pactCountry);\n\twriter.write(\"race\", _race);\n\tif (_inBattlescape)\n\t\twriter.write(\"inBattlescape\", _inBattlescape);\n\tif (_discovered)\n\t\twriter.write(\"discovered\", _discovered);\n\twriter.write(\"deployment\", _deployment->getType());\n\twriter.write(\"startMonth\", _startMonth);\n\twriter.write(\"minutesSinceLastHuntMissionGeneration\", _minutesSinceLastHuntMissionGeneration);\n\twriter.write(\"genMissionCount\", _genMissionCount);\n}\n\n/**\n * Returns the alien base's unique type used for\n * savegame purposes.\n * @return ID.\n */\nstd::string AlienBase::getType() const\n{\n\treturn _deployment->getMarkerName();\n}\n\n/**\n * Returns the globe marker for the alien base.\n * @return Marker sprite, -1 if none.\n */\nint AlienBase::getMarker() const\n{\n\tif (!_discovered)\n\t\treturn -1;\n\treturn _deployment->getMarkerIcon();\n}\n\n/**\n * Returns the country this base has a pact with.\n * @return Country ID.\n */\nconst std::string &AlienBase::getPactCountry() const\n{\n\treturn _pactCountry;\n}\n\n/**\n * Changes the country that has a pact with this alien base.\n * @param pactCountry Country ID.\n */\nvoid AlienBase::setPactCountry(const std::string &pactCountry)\n{\n\t_pactCountry = pactCountry;\n}\n\n/**\n * Returns the alien race currently residing in the alien base.\n * @return Alien race.\n */\nstd::string AlienBase::getAlienRace() const\n{\n\treturn _race;\n}\n\n/**\n * Changes the alien race currently residing in the alien base.\n * @param race Alien race.\n */\nvoid AlienBase::setAlienRace(const std::string &race)\n{\n\t_race = race;\n}\n\n/**\n * Gets the alien base's battlescape status.\n * @return Is the base on the battlescape?\n */\nbool AlienBase::isInBattlescape() const\n{\n\treturn _inBattlescape;\n}\n\n/**\n * Sets the alien base's battlescape status.\n * @param inbattle True if it's in battle, False otherwise.\n */\nvoid AlienBase::setInBattlescape(bool inbattle)\n{\n\t_inBattlescape = inbattle;\n}\n\n/**\n * Gets the alien base's geoscape status.\n * @return Has the base been discovered?\n */\nbool AlienBase::isDiscovered() const\n{\n\treturn _discovered;\n}\n\n/**\n * Sets the alien base's geoscape status.\n * @param discovered Has the base been discovered?\n */\nvoid AlienBase::setDiscovered(bool discovered)\n{\n\t_discovered = discovered;\n}\n\nAlienDeployment *AlienBase::getDeployment() const\n{\n\treturn _deployment;\n}\n\nvoid AlienBase::setDeployment(AlienDeployment *deployment)\n{\n\t_deployment = deployment;\n\n\t// allow spawning hunt missions immediately after the base is upgraded, i.e. no initial delay\n\t_minutesSinceLastHuntMissionGeneration = _deployment->getHuntMissionMaxFrequency();\n}\n\n/**\n * Gets the number of minutes passed since the last hunt mission was generated.\n * @return Number of minutes.\n */\nint AlienBase::getMinutesSinceLastHuntMissionGeneration() const\n{\n\treturn _minutesSinceLastHuntMissionGeneration;\n}\n\n/**\n * Sets the number of minutes passed since the last hunt mission was generated.\n * @param newValue Number of minutes.\n */\nvoid AlienBase::setMinutesSinceLastHuntMissionGeneration(int newValue)\n{\n\t_minutesSinceLastHuntMissionGeneration = newValue;\n}\n\n/**\n * Gets the number of genMissions generated so far by this base.\n * @return Number of missions.\n */\nint AlienBase::getGenMissionCount() const\n{\n\treturn _genMissionCount;\n}\n\n/**\n * Sets the number of genMissions generated so far by this base.\n * @param newValue Number of missions.\n */\nvoid AlienBase::setGenMissionCount(int newValue)\n{\n\t_genMissionCount = newValue;\n}\n\n}\n"
  },
  {
    "path": "src/Savegame/AlienBase.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Target.h\"\n#include <string>\n#include \"../Mod/AlienDeployment.h\"\n#include \"../Engine/Yaml.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Represents an alien base on the world.\n */\nclass AlienBase : public Target\n{\nprivate:\n\tstd::string _pactCountry;\n\tstd::string _race;\n\tbool _inBattlescape, _discovered;\n\tAlienDeployment *_deployment;\n\tint _startMonth;\n\tint _minutesSinceLastHuntMissionGeneration;\n\tint _genMissionCount;\npublic:\n\t/// Creates an alien base.\n\tAlienBase(AlienDeployment *deployment, int startMonth);\n\t/// Cleans up the alien base.\n\t~AlienBase();\n\t/// Loads the alien base from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader) override;\n\t/// Saves the alien base to YAML.\n\tvoid save(YAML::YamlNodeWriter writer) const override;\n\t/// Gets the alien base's type.\n\tstd::string getType() const override;\n\t/// Gets the alien base's marker sprite.\n\tint getMarker() const override;\n\t/// Gets the alien base's pact country.\n\tconst std::string &getPactCountry() const;\n\t/// Sets the alien base's pact country.\n\tvoid setPactCountry(const std::string &pactCountry);\n\t/// Gets the alien base's amount of active hours.\n\tstd::string getAlienRace() const;\n\t/// Sets the alien base's alien race.\n\tvoid setAlienRace(const std::string &race);\n\t/// Sets the alien base's battlescape status.\n\tvoid setInBattlescape(bool inbattle);\n\t/// Gets the alien base's battlescape status.\n\tbool isInBattlescape() const;\n\t/// Gets the alien base's discovered status.\n\tbool isDiscovered() const;\n\t/// Sets the alien base's discovered status.\n\tvoid setDiscovered(bool discovered);\n\n\tAlienDeployment *getDeployment() const;\n\tvoid setDeployment(AlienDeployment *deployment);\n\n\t/// Gets the month on which the base spawned.\n\tint getStartMonth() const { return _startMonth; }\n\t/// Sets the month on which the base spawned.\n\tvoid setStartMonth(int startMonth) { _startMonth = startMonth; }\n\t/// Gets the number of minutes passed since the last hunt mission was generated.\n\tint getMinutesSinceLastHuntMissionGeneration() const;\n\t/// Sets the number of minutes passed since the last hunt mission was generated.\n\tvoid setMinutesSinceLastHuntMissionGeneration(int newValue);\n\t/// Gets the number of genMissions generated so far by this base.\n\tint getGenMissionCount() const;\n\t/// Sets the number of genMissions generated so far by this base.\n\tvoid setGenMissionCount(int newValue);\n\n};\n\n}\n"
  },
  {
    "path": "src/Savegame/AlienMission.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"AlienMission.h\"\n#include \"AlienBase.h\"\n#include \"Base.h\"\n#include \"../fmath.h\"\n#include \"../Engine/Exception.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Logger.h\"\n#include \"../Engine/RNG.h\"\n#include \"../Geoscape/Globe.h\"\n#include \"../Mod/RuleAlienMission.h\"\n#include \"../Mod/RuleRegion.h\"\n#include \"../Mod/RuleCountry.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleUfo.h\"\n#include \"../Mod/UfoTrajectory.h\"\n#include \"../Mod/RuleGlobe.h\"\n#include \"../Mod/Texture.h\"\n#include \"SavedGame.h\"\n#include \"MissionSite.h\"\n#include \"Ufo.h\"\n#include \"Craft.h\"\n#include \"Region.h\"\n#include \"Country.h\"\n#include \"Waypoint.h\"\n#include <assert.h>\n#include <algorithm>\n#include <functional>\n#include \"../Mod/AlienDeployment.h\"\n\nnamespace OpenXcom\n{\n\nAlienMission::AlienMission(const RuleAlienMission &rule) : _rule(rule), _nextWave(0), _nextUfoCounter(0), _spawnCountdown(0), _liveUfos(0),\n\t_interrupted(false), _multiUfoRetaliationInProgress(false), _uniqueID(0), _missionSiteZoneArea(-1), _base(0)\n{\n\t// Empty by design.\n}\n\nAlienMission::~AlienMission()\n{\n\t// Empty by design.\n}\n\n/**\n * Loads the alien mission from a YAML file.\n * @param node The YAML node containing the data.\n * @param game The game data, required to locate the alien base.\n */\nvoid AlienMission::load(const YAML::YamlNodeReader& reader, SavedGame &game, const Mod* mod)\n{\n\treader.tryRead(\"region\", _region);\n\treader.tryRead(\"race\", _race);\n\treader.tryRead(\"nextWave\", _nextWave);\n\treader.tryRead(\"nextUfoCounter\", _nextUfoCounter);\n\treader.tryRead(\"spawnCountdown\", _spawnCountdown);\n\treader.tryRead(\"liveUfos\", _liveUfos);\n\treader.tryRead(\"interrupted\", _interrupted);\n\treader.tryRead(\"multiUfoRetaliationInProgress\", _multiUfoRetaliationInProgress);\n\treader.tryRead(\"uniqueID\", _uniqueID);\n\tif (const auto& base = reader[\"alienBase\"])\n\t{\n\t\tint id = base.isMap() ? base[\"id\"].readVal<int>() : base.readVal<int>();\n\t\tstd::string type = base.isMap() ? base[\"type\"].readVal<std::string>() : \"STR_ALIEN_BASE\";\n\t\tauto found = std::find_if(game.getAlienBases()->begin(), game.getAlienBases()->end(),\n\t\t\t\t\t\t\t\t   [&](AlienBase* ab)\n\t\t\t\t\t\t\t\t   { return ab->getId() == id && ab->getDeployment()->getMarkerName() == type; });\n\t\tif (found == game.getAlienBases()->end())\n\t\t\tthrow Exception(\"Corrupted save: Invalid base for mission.\");\n\t\t_base = *found;\n\t}\n\treader.tryRead(\"missionSiteZone\", _missionSiteZoneArea);\n\n\t// fix invalid saves\n\tRuleRegion* region = mod->getRegion(_region, false);\n\tif (!region)\n\t{\n\t\tLog(LOG_ERROR) << \"Corrupted save: Mission with uniqueID: \" << _uniqueID << \" has an invalid region: \" << _region;\n\t\t_interrupted = true;\n\t\tif (_missionSiteZoneArea > -1)\n\t\t{\n\t\t\t_missionSiteZoneArea = 0;\n\t\t}\n\t\t_region = mod->getRegionsList().front();\n\t\tif (_liveUfos > 0)\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"Mission still has some live UFOs, please leave them be until they disappear.\";\n\t\t}\n\t\tLog(LOG_ERROR) << \"Mission was interrupted! Temporarily assigned to a new region: \" << _region;\n\t}\n\tAlienRace* race = mod->getAlienRace(_race, false);\n\tif (!race)\n\t{\n\t\tLog(LOG_ERROR) << \"Corrupted save: Mission with uniqueID: \" << _uniqueID << \" has an invalid alien race: \" << _race;\n\t\t_interrupted = true;\n\t\t_race = mod->getAlienRacesList().front();\n\t\tif (_liveUfos > 0)\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"Mission still has some live UFOs, please leave them be until they disappear.\";\n\t\t}\n\t\tLog(LOG_ERROR) << \"Mission was interrupted! Temporarily assigned a new alien race: \" << _race;\n\t}\n}\n\n/**\n * Saves the alien mission to a YAML file.\n * @return YAML node.\n */\nvoid AlienMission::save(YAML::YamlNodeWriter writer) const\n{\n\twriter.setAsMap();\n\twriter.write(\"type\", _rule.getType());\n\twriter.write(\"region\", _region);\n\twriter.write(\"race\", _race);\n\twriter.write(\"nextWave\", _nextWave);\n\twriter.write(\"nextUfoCounter\", _nextUfoCounter);\n\twriter.write(\"spawnCountdown\", _spawnCountdown);\n\twriter.write(\"liveUfos\", _liveUfos);\n\tif (_interrupted)\n\t\twriter.write(\"interrupted\", _interrupted);\n\tif (_multiUfoRetaliationInProgress)\n\t\twriter.write(\"multiUfoRetaliationInProgress\", _multiUfoRetaliationInProgress);\n\twriter.write(\"uniqueID\", _uniqueID);\n\tif (_base)\n\t\t_base->saveId(writer[\"alienBase\"]);\n\twriter.write(\"missionSiteZone\", _missionSiteZoneArea);\n}\n\n/**\n * Check if a mission is over and can be safely removed from the game.\n * A mission is over if it will spawn no more UFOs and it has no UFOs still in\n * the game.\n * @return If the mission can be safely removed from game.\n */\nbool AlienMission::isOver() const\n{\n\tif (_interrupted && !_liveUfos)\n\t{\n\t\treturn true;\n\t}\n\tif (_rule.getObjective() == OBJECTIVE_INFILTRATION && _rule.isEndlessInfiltration())\n\t{\n\t\t//Infiltrations continue for ever.\n\t\treturn false;\n\t}\n\tif (_nextWave == _rule.getWaveCount() && !_liveUfos)\n\t{\n\t\treturn true;\n\t}\n\treturn false;\n}\n\nvoid AlienMission::think(Game &engine, const Globe &globe)\n{\n\t// if interrupted, don't generate any more UFOs or anything else\n\tif (_interrupted || (_multiUfoRetaliationInProgress && !_rule.isMultiUfoRetaliationExtra()))\n\t{\n\t\treturn;\n\t}\n\n\tconst Mod &mod = *engine.getMod();\n\tSavedGame &game = *engine.getSavedGame();\n\tif (_nextWave >= _rule.getWaveCount())\n\t\treturn;\n\tif (_spawnCountdown > 30)\n\t{\n\t\t_spawnCountdown -= 30;\n\t\treturn;\n\t}\n\tconst MissionWave &wave = _rule.getWave(_nextWave);\n\tconst UfoTrajectory &trajectory = *mod.getUfoTrajectory(wave.trajectory, true);\n\tUfo *ufo = spawnUfo(game, mod, globe, wave, trajectory);\n\tif (ufo)\n\t{\n\t\t//Some missions may not spawn a UFO!\n\t\tufo->setMissionWaveNumber(_nextWave);\n\t\tgame.getUfos()->push_back(ufo);\n\t}\n\telse if ((mod.getDeployment(wave.ufoType) && !mod.getUfo(wave.ufoType) && !mod.getDeployment(wave.ufoType)->getMarkerName().empty()) // a mission site that we want to spawn directly\n\t\t\t|| (_rule.getObjective() == OBJECTIVE_SITE && wave.objective)) // or we want to spawn one at random according to our terrain\n\t{\n\t\tRuleRegion* regionRules = mod.getRegion(_region, true);\n\t\tstd::vector<MissionArea> areas = regionRules->getMissionZones().at((_rule.getSpawnZone() == -1) ? trajectory.getZone(0) : _rule.getSpawnZone()).areas;\n\t\tMissionArea area = areas.at((_missionSiteZoneArea == -1) ? RNG::generate(0, areas.size() - 1) : _missionSiteZoneArea);\n\n\t\tif (wave.objectiveOnXcomBase)\n\t\t{\n\t\t\tBase* xcombase = selectXcomBase(game, *regionRules);\n\t\t\t// no xcom base = don't spawn a mission site\n\t\t\tif (xcombase)\n\t\t\t{\n\t\t\t\tarea.lonMin = xcombase->getLongitude();\n\t\t\t\tarea.lonMax = xcombase->getLongitude();\n\t\t\t\tarea.latMin = xcombase->getLatitude();\n\t\t\t\tarea.latMax = xcombase->getLatitude();\n\t\t\t\t// area.texture is taken from the ruleset\n\t\t\t\tarea.name = \"\"; // remove the city name, if there was any\n\t\t\t\tspawnMissionSite(game, mod, area, 0, mod.getDeployment(wave.ufoType, false));\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tspawnMissionSite(game, mod, area, 0, mod.getDeployment(wave.ufoType, false));\n\t\t}\n\t}\n\n\t++_nextUfoCounter;\n\tif (_nextUfoCounter >= wave.ufoCount)\n\t{\n\t\t_nextUfoCounter = 0;\n\t\t++_nextWave;\n\t}\n\tif (_rule.getObjective() == OBJECTIVE_INFILTRATION && _nextWave == _rule.getWaveCount())\n\t{\n\t\tstd::vector<Country*> countriesCopy = *game.getCountries();\n\t\tif (mod.getInfiltrateRandomCountryInTheRegion())\n\t\t{\n\t\t\tRNG::shuffle(countriesCopy);\n\t\t}\n\t\tfor (auto* c : countriesCopy)\n\t\t{\n\t\t\tRuleRegion *region = mod.getRegion(_region, true);\n\t\t\tif (c->canBeInfiltrated() && region->insideRegion(c->getRules()->getLabelLongitude(), c->getRules()->getLabelLatitude()))\n\t\t\t{\n\t\t\t\tstd::pair<double, double> pos;\n\t\t\t\tint tries = 0;\n\t\t\t\tbool dynamicBaseType = _rule.getSiteType().empty();\n\t\t\t\tAlienDeployment *alienBaseType = nullptr;\n\t\t\t\tbool wantsToSpawnFakeUnderwater = false;\n\t\t\t\tbool found = false;\n\t\t\t\tif (!mod.getBuildInfiltrationBaseCloseToTheCountry())\n\t\t\t\t{\n\t\t\t\t\tstd::vector<MissionArea> areas = region->getMissionZones().at(_rule.getSpawnZone()).areas;\n\t\t\t\t\twhile (!found)\n\t\t\t\t\t{\n\t\t\t\t\t\tMissionArea &area = areas.at(RNG::generate(0, areas.size() - 1));\n\t\t\t\t\t\tpos.first = RNG::generate(std::min(area.lonMin, area.lonMax), std::max(area.lonMin, area.lonMax));\n\t\t\t\t\t\tpos.second = RNG::generate(std::min(area.latMin, area.latMax), std::max(area.latMin, area.latMax));\n\n\t\t\t\t\t\tif (tries == 0 || dynamicBaseType)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\talienBaseType = chooseAlienBaseType(mod, area);\n\t\t\t\t\t\t\twantsToSpawnFakeUnderwater = RNG::percent(alienBaseType->getFakeUnderwaterSpawnChance());\n\t\t\t\t\t\t}\n\t\t\t\t\t\t++tries;\n\n\t\t\t\t\t\tif (tries == 100)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfound = true; // forced spawn on invalid location\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (globe.insideLand(pos.first, pos.second) && region->insideRegion(pos.first, pos.second))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tbool isFakeUnderwater = globe.insideFakeUnderwaterTexture(pos.first, pos.second);\n\t\t\t\t\t\t\tif (wantsToSpawnFakeUnderwater)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (isFakeUnderwater) found = true; // found spawn point on fakeUnderwater texture\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (!isFakeUnderwater) found = true; // found spawn point on land\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tdynamicBaseType = false; // just to make absolutely clear this feature is not supported in this case\n\t\t\t\t\tMissionArea dummyArea;\n\t\t\t\t\talienBaseType = chooseAlienBaseType(mod, dummyArea);\n\t\t\t\t\twantsToSpawnFakeUnderwater = RNG::percent(alienBaseType->getFakeUnderwaterSpawnChance());\n\n\t\t\t\t\tconst RuleCountry* cRule = c->getRules();\n\t\t\t\t\tint pick = 0;\n\t\t\t\t\tdouble lonMini, lonMaxi, latMini, latMaxi;\n\t\t\t\t\twhile (!found)\n\t\t\t\t\t{\n\t\t\t\t\t\tpick = RNG::generate(0, cRule->getLonMin().size() - 1);\n\t\t\t\t\t\tlonMini = cRule->getLonMin()[pick];\n\t\t\t\t\t\tlonMaxi = cRule->getLonMax()[pick];\n\t\t\t\t\t\tif (lonMini > lonMaxi)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// UK, France, Spain, or anything crossed by the prime meridian\n\t\t\t\t\t\t\tif (RNG::percent(50)) { lonMini = Deg2Rad(0.0); } else { lonMaxi = Deg2Rad(359.99); }\n\t\t\t\t\t\t}\n\t\t\t\t\t\tlatMini = cRule->getLatMin()[pick];\n\t\t\t\t\t\tlatMaxi = cRule->getLatMax()[pick];\n\t\t\t\t\t\tpos.first = RNG::generate(std::min(lonMini, lonMaxi), std::max(lonMini, lonMaxi));\n\t\t\t\t\t\tpos.second = RNG::generate(std::min(latMini, latMaxi), std::max(latMini, latMaxi));\n\t\t\t\t\t\t++tries;\n\n\t\t\t\t\t\tif (tries == 100)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfound = true; // forced spawn on invalid location\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (globe.insideLand(pos.first, pos.second) && cRule->insideCountry(pos.first, pos.second))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tbool isFakeUnderwater = globe.insideFakeUnderwaterTexture(pos.first, pos.second);\n\t\t\t\t\t\t\tif (wantsToSpawnFakeUnderwater)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (isFakeUnderwater) found = true; // found spawn point on fakeUnderwater texture\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (!isFakeUnderwater) found = true; // found spawn point on land\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (tries < 100 || mod.getAllowAlienBasesOnWrongTextures())\n\t\t\t\t{\n\t\t\t\t\t// only create a pact if the base is going to be spawned too\n\t\t\t\t\tc->setNewPact();\n\n\t\t\t\t\tspawnAlienBase(c, engine, pos, alienBaseType);\n\n\t\t\t\t\t// if the base can't be spawned for this country, try the next country\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (_rule.isEndlessInfiltration())\n\t\t{\n\t\t\t// Infiltrations loop for ever.\n\t\t\t_nextWave = 0;\n\t\t}\n\t}\n\tif (_rule.getObjective() == OBJECTIVE_BASE && _nextWave == _rule.getWaveCount() && !wave.objectiveOnTheLandingSite)\n\t{\n\t\tRuleRegion *region = mod.getRegion(_region, true);\n\t\tif (_rule.getSpawnZone() < 0 || _rule.getSpawnZone() >= (int)region->getMissionZones().size())\n\t\t{\n\t\t\tthrow Exception(\"Cannot spawn alien base, invalid spawnZone! Mission: \" + _rule.getType());\n\t\t}\n\t\tstd::vector<MissionArea> areas = region->getMissionZones().at(_rule.getSpawnZone()).areas;\n\t\tstd::pair<double, double> pos;\n\t\tint tries = 0;\n\t\tbool dynamicBaseType = _rule.getSiteType().empty();\n\t\tAlienDeployment* alienBaseType = nullptr;\n\t\tbool wantsToSpawnFakeUnderwater = false;\n\t\tbool found = false;\n\t\twhile (!found)\n\t\t{\n\t\t\tMissionArea &area = areas.at(RNG::generate(0, areas.size()-1));\n\t\t\tpos.first = RNG::generate(std::min(area.lonMin, area.lonMax), std::max(area.lonMin, area.lonMax));\n\t\t\tpos.second = RNG::generate(std::min(area.latMin, area.latMax), std::max(area.latMin, area.latMax));\n\n\t\t\tif (tries == 0 || dynamicBaseType)\n\t\t\t{\n\t\t\t\talienBaseType = chooseAlienBaseType(mod, area);\n\t\t\t\twantsToSpawnFakeUnderwater = RNG::percent(alienBaseType->getFakeUnderwaterSpawnChance());\n\t\t\t}\n\t\t\t++tries;\n\n\t\t\tif (tries == 100)\n\t\t\t{\n\t\t\t\tfound = true; // forced spawn on invalid location\n\t\t\t}\n\t\t\telse if (globe.insideLand(pos.first, pos.second) && region->insideRegion(pos.first, pos.second, true))\n\t\t\t{\n\t\t\t\tbool isFakeUnderwater = globe.insideFakeUnderwaterTexture(pos.first, pos.second);\n\t\t\t\tif (wantsToSpawnFakeUnderwater)\n\t\t\t\t{\n\t\t\t\t\tif (isFakeUnderwater) found = true; // found spawn point on fakeUnderwater texture\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif (!isFakeUnderwater) found = true; // found spawn point on land\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (tries < 100 || mod.getAllowAlienBasesOnWrongTextures())\n\t\t{\n\t\t\tspawnAlienBase(0, engine, pos, alienBaseType);\n\t\t}\n\t}\n\n\tif (_nextWave != _rule.getWaveCount())\n\t{\n\t\tsize_t origSpawnTimerValue = _rule.getWave(_nextWave).spawnTimer;\n\t\tsize_t spawnTimer = origSpawnTimerValue / 30;\n\t\t_spawnCountdown = (spawnTimer/2 + RNG::generate(0, spawnTimer)) * 30;\n\n\t\tif (origSpawnTimerValue == 0)\n\t\t{\n\t\t\t// spawn more UFOs immediately\n\t\t\tthink(engine, globe);\n\t\t}\n\t}\n}\n\n/**\n * Selects an xcom base in a given region.\n * @param game The saved game information.\n * @param regionRules The rule for the given region.\n * @return Pointer to the selected xcom base or nullptr.\n */\nBase* AlienMission::selectXcomBase(SavedGame& game, const RuleRegion& regionRules)\n{\n\tstd::vector<Base*> validxcombases;\n\tfor (auto* xb : *game.getBases())\n\t{\n\t\tif (regionRules.insideRegion(xb->getLongitude(), xb->getLatitude()))\n\t\t{\n\t\t\tif (_rule.getObjective() == OBJECTIVE_RETALIATION)\n\t\t\t{\n\t\t\t\t// only discovered xcom bases!\n\t\t\t\tif (xb->getRetaliationTarget())\n\t\t\t\t{\n\t\t\t\t\tvalidxcombases.push_back(xb);\n\t\t\t\t\tif (_rule.isMultiUfoRetaliation())\n\t\t\t\t\t{\n\t\t\t\t\t\tcontinue; // non-vanilla: let's consider all, for fun\n\t\t\t\t\t}\n\t\t\t\t\tbreak; // vanilla: the first is enough\n\t\t\t\t}\n\t\t\t}\n\t\t\telse // instant retaliation; or a mission wave with `objectiveOnXcomBase: true`\n\t\t\t{\n\t\t\t\tvalidxcombases.push_back(xb);\n\t\t\t}\n\t\t}\n\t}\n\tBase* xcombase = nullptr;\n\tif (!validxcombases.empty())\n\t{\n\t\tif (validxcombases.size() == 1)\n\t\t{\n\t\t\t// take the first (don't mess with the RNG seed)\n\t\t\txcombase = validxcombases.front();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tint rngpick = RNG::generate(0, validxcombases.size() - 1);\n\t\t\txcombase = validxcombases[rngpick];\n\t\t}\n\t}\n\treturn xcombase;\n}\n\n/**\n * This function will spawn a UFO according the mission rules.\n * Some code is duplicated between cases, that's ok for now. It's on different\n * code paths and the function is MUCH easier to read written this way.\n * @param game The saved game information.\n * @param mod The mod.\n * @param globe The globe, for land checks.\n * @param wave The wave for the desired UFO.\n * @param trajectory The rule for the desired trajectory.\n * @return Pointer to the spawned UFO. If the mission does not desire to spawn a UFO, 0 is returned.\n */\nUfo *AlienMission::spawnUfo(SavedGame &game, const Mod &mod, const Globe &globe, const MissionWave &wave, const UfoTrajectory &trajectory)\n{\n\tauto logUfo = [](Ufo* u, SavedGame& g, AlienMission* a)\n\t{\n\t\tif (Options::oxceGeoscapeDebugLogMaxEntries > 0)\n\t\t{\n\t\t\tstd::ostringstream ss;\n\t\t\tss << \"gameTime: \" << g.getTime()->getFullString();\n\t\t\tss << \" ufoId: \" << u->getUniqueId();\n\t\t\tss << \" ufoType: \" << u->getRules()->getType();\n\t\t\tss << \" race: \" << u->getAlienRace();\n\t\t\tss << \" region: \" << a->getRegion();\n\t\t\tss << \" trajectory: \" << u->getTrajectory().getID();\n\t\t\tif (u->isHunterKiller())\n\t\t\t{\n\t\t\t\tss << \" hk: true\";\n\t\t\t}\n\t\t\tss << \" missionId: \" << a->getId();\n\t\t\tss << \" missionType: \" << a->getRules().getType();\n\t\t\tg.getGeoscapeDebugLog().push_back(ss.str());\n\t\t}\n\t};\n\n\tRuleUfo *ufoRule = mod.getUfo(wave.ufoType);\n\tint hunterKillerPercentage = wave.hunterKillerPercentage;\n\tif (hunterKillerPercentage == -1 && ufoRule)\n\t{\n\t\thunterKillerPercentage = ufoRule->getHunterKillerPercentage();\n\t}\n\tint huntMode = wave.huntMode;\n\tif (huntMode == -1 && ufoRule)\n\t{\n\t\thuntMode = ufoRule->getHuntMode();\n\t}\n\tint huntBehavior = wave.huntBehavior;\n\tif (huntBehavior == -1 && ufoRule)\n\t{\n\t\thuntBehavior = ufoRule->getHuntBehavior();\n\t}\n\tif (_rule.getObjective() == OBJECTIVE_RETALIATION || _rule.getObjective() == OBJECTIVE_INSTANT_RETALIATION)\n\t{\n\t\tconst RuleRegion &regionRules = *mod.getRegion(_region, true);\n\t\tBase* xcombase = nullptr;\n\n\t\t// skip the scouting phase of a retaliation mission\n\t\tif (_rule.skipScoutingPhase() && _rule.getObjective() == OBJECTIVE_RETALIATION)\n\t\t{\n\t\t\tfor (auto* xbase : *game.getBases())\n\t\t\t{\n\t\t\t\tif (regionRules.insideRegion(xbase->getLongitude(), xbase->getLatitude()))\n\t\t\t\t{\n\t\t\t\t\txcombase = xbase;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\txcombase = selectXcomBase(game, regionRules);\n\t\t}\n\n\t\tif (xcombase)\n\t\t{\n\t\t\t// Spawn a battleship straight for the XCOM base.\n\t\t\tconst RuleUfo &battleshipRule = _rule.getSpawnUfo().empty() ? *ufoRule : *mod.getUfo(_rule.getSpawnUfo(), true);\n\t\t\tconst UfoTrajectory &assaultTrajectory = *mod.getUfoTrajectory(UfoTrajectory::RETALIATION_ASSAULT_RUN, true);\n\t\t\tUfo *ufo = new Ufo(&battleshipRule, game.getId(\"STR_UFO_UNIQUE\"));\n\t\t\tufo->setMissionInfo(this, &assaultTrajectory);\n\t\t\tstd::pair<double, double> pos;\n\t\t\tif (_rule.getObjective() == OBJECTIVE_INSTANT_RETALIATION)\n\t\t\t{\n\t\t\t\tpos.first = xcombase->getLongitude();\n\t\t\t\tpos.second = xcombase->getLatitude();\n\t\t\t}\n\t\t\telse if (_rule.getOperationType() != AMOT_SPACE && _base)\n\t\t\t{\n\t\t\t\tpos.first = _base->getLongitude();\n\t\t\t\tpos.second = _base->getLatitude();\n\t\t\t}\n\t\t\telse if (trajectory.getAltitude(0) == \"STR_GROUND\")\n\t\t\t{\n\t\t\t\tpos = getLandPoint(globe, regionRules, trajectory.getZone(0), *ufo);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tpos = regionRules.getRandomPoint(trajectory.getZone(0));\n\t\t\t}\n\t\t\tufo->setAltitude(assaultTrajectory.getAltitude(0));\n\t\t\tufo->setSpeed(assaultTrajectory.applySpeedPercentage(0, ufo->getCraftStats().speedMax));\n\t\t\tufo->setLongitude(pos.first);\n\t\t\tufo->setLatitude(pos.second);\n\t\t\tWaypoint *wp = new Waypoint();\n\t\t\twp->setLongitude(xcombase->getLongitude());\n\t\t\twp->setLatitude(xcombase->getLatitude());\n\t\t\tufo->setDestination(wp);\n\t\t\tlogUfo(ufo, game, this);\n\t\t\treturn ufo;\n\t\t}\n\t\telse if (_rule.getObjective() == OBJECTIVE_INSTANT_RETALIATION)\n\t\t{\n\t\t\t// no xcom base found, nothing to do, terminate\n\t\t\t_interrupted = true;\n\t\t\treturn 0;\n\t\t}\n\t}\n\telse if (_rule.getObjective() == OBJECTIVE_SUPPLY)\n\t{\n\t\tif (ufoRule == 0 || (wave.objective && !_base))\n\t\t{\n\t\t\t// No base to supply!\n\t\t\treturn 0;\n\t\t}\n\t\t// Our destination is always an alien base.\n\t\tUfo *ufo = 0;\n\t\tif (wave.objective)\n\t\t{\n\t\t\tufo = new Ufo(ufoRule, game.getId(\"STR_UFO_UNIQUE\"));\n\t\t}\n\t\telse\n\t\t{\n\t\t\tufo = new Ufo(ufoRule, game.getId(\"STR_UFO_UNIQUE\"), hunterKillerPercentage, huntMode, huntBehavior);\n\t\t}\n\t\tufo->setMissionInfo(this, &trajectory);\n\t\tconst RuleRegion &regionRules = *mod.getRegion(_region, true);\n\t\tstd::pair<double, double> pos;\n\t\tif (_rule.getOperationType() != AMOT_SPACE && _base)\n\t\t{\n\t\t\tpos.first = _base->getLongitude();\n\t\t\tpos.second = _base->getLatitude();\n\t\t}\n\t\telse if (trajectory.getAltitude(0) == \"STR_GROUND\")\n\t\t{\n\t\t\tpos = getLandPoint(globe, regionRules, trajectory.getZone(0), *ufo);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tpos = regionRules.getRandomPoint(trajectory.getZone(0));\n\t\t}\n\t\tufo->setAltitude(trajectory.getAltitude(0));\n\t\tufo->setSpeed(trajectory.applySpeedPercentage(0, ufo->getCraftStats().speedMax));\n\t\tufo->setLongitude(pos.first);\n\t\tufo->setLatitude(pos.second);\n\t\tWaypoint *wp = new Waypoint();\n\t\tif (trajectory.getAltitude(1) == \"STR_GROUND\")\n\t\t{\n\t\t\tif (wave.objective)\n\t\t\t{\n\t\t\t\t// Supply ships on supply missions land on bases, ignore trajectory zone.\n\t\t\t\tpos.first = _base->getLongitude();\n\t\t\t\tpos.second = _base->getLatitude();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// Other ships can land where they want.\n\t\t\t\tpos = getLandPoint(globe, regionRules, trajectory.getZone(1), *ufo);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tpos = regionRules.getRandomPoint(trajectory.getZone(1));\n\t\t}\n\t\twp->setLongitude(pos.first);\n\t\twp->setLatitude(pos.second);\n\t\tufo->setDestination(wp);\n\n\t\t// Only hunter-killers can escort\n\t\tif (ufo->isHunterKiller() && wave.escort && !wave.objective)\n\t\t{\n\t\t\tufo->setEscort(true);\n\t\t\t// Find a UFO to escort\n\t\t\tfor (auto* ufoToBeEscorted : *game.getUfos())\n\t\t\t{\n\t\t\t\t// From the same mission\n\t\t\t\tif (ufoToBeEscorted->getMission()->getId() == ufo->getMission()->getId())\n\t\t\t\t{\n\t\t\t\t\t// But not another hunter-killer, we escort only normal UFOs\n\t\t\t\t\tif (!ufoToBeEscorted->isHunterKiller())\n\t\t\t\t\t{\n\t\t\t\t\t\tufo->setLongitude(ufoToBeEscorted->getLongitude());\n\t\t\t\t\t\tufo->setLatitude(ufoToBeEscorted->getLatitude());\n\t\t\t\t\t\tufo->setEscortedUfo(ufoToBeEscorted);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tlogUfo(ufo, game, this);\n\t\treturn ufo;\n\t}\n\tif (ufoRule == 0)\n\t\treturn 0;\n\t// Spawn according to sequence.\n\tUfo *ufo = new Ufo(ufoRule, game.getId(\"STR_UFO_UNIQUE\"), hunterKillerPercentage, huntMode, huntBehavior);\n\tufo->setMissionInfo(this, &trajectory);\n\tconst RuleRegion &regionRules = *mod.getRegion(_region, true);\n\tstd::pair<double, double> pos = getWaypoint(wave, trajectory, 0, globe, regionRules, *ufo);\n\tufo->setAltitude(trajectory.getAltitude(0));\n\tif (trajectory.getAltitude(0) == \"STR_GROUND\")\n\t{\n\t\tufo->setSecondsRemaining(trajectory.groundTimer()*5);\n\t}\n\tufo->setSpeed(trajectory.applySpeedPercentage(0, ufo->getCraftStats().speedMax));\n\tufo->setLongitude(pos.first);\n\tufo->setLatitude(pos.second);\n\tif (_rule.getOperationType() != AMOT_SPACE && _base)\n\t{\n\t\t// override starting location for Earth-based alien operations\n\t\tufo->setLongitude(_base->getLongitude());\n\t\tufo->setLatitude(_base->getLatitude());\n\t}\n\tWaypoint *wp = new Waypoint();\n\tif (trajectory.getWaypointCount() > 1)\n\t{\n\t\tpos = getWaypoint(wave, trajectory, 1, globe, regionRules, *ufo);\n\t}\n\telse\n\t{\n\t\tstd::stringstream ss;\n\t\tss << \"Missing second waypoint! Error occurred while trying to determine UFO waypoint for mission type: \" << _rule.getType();\n\t\tss << \" in region: \" << regionRules.getType() << \"; ufo type: \" << ufo->getRules()->getType() << \", trajectory ID: \" << trajectory.getID() << \".\";\n\t\tthrow Exception(ss.str());\n\t}\n\twp->setLongitude(pos.first);\n\twp->setLatitude(pos.second);\n\tufo->setDestination(wp);\n\n\t// Only hunter-killers can escort\n\tif (ufo->isHunterKiller() && wave.escort)\n\t{\n\t\tufo->setEscort(true);\n\t\t// Find a UFO to escort\n\t\tfor (auto* ufoToBeEscorted : *game.getUfos())\n\t\t{\n\t\t\t// From the same mission\n\t\t\tif (ufoToBeEscorted->getMission()->getId() == ufo->getMission()->getId())\n\t\t\t{\n\t\t\t\t// But not another hunter-killer, we escort only normal UFOs\n\t\t\t\tif (!ufoToBeEscorted->isHunterKiller())\n\t\t\t\t{\n\t\t\t\t\tufo->setLongitude(ufoToBeEscorted->getLongitude());\n\t\t\t\t\tufo->setLatitude(ufoToBeEscorted->getLatitude());\n\t\t\t\t\tufo->setEscortedUfo(ufoToBeEscorted);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tlogUfo(ufo, game, this);\n\treturn ufo;\n}\n\nvoid AlienMission::start(Game &engine, const Globe &globe, size_t initialCount)\n{\n\t_nextWave = 0;\n\t_nextUfoCounter = 0;\n\t_liveUfos = 0;\n\tif (initialCount == 0)\n\t{\n\t\tsize_t spawnTimer = _rule.getWave(0).spawnTimer / 30;\n\t\t_spawnCountdown = (spawnTimer / 2 + RNG::generate(0, spawnTimer)) * 30;\n\t}\n\telse\n\t{\n\t\t_spawnCountdown = initialCount;\n\t}\n\n\t// Earth-based alien operations\n\tif (_rule.getOperationType() != AMOT_SPACE && !_base)\n\t{\n\t\tconst Mod &mod = *engine.getMod();\n\t\tSavedGame &game = *engine.getSavedGame();\n\n\t\tstd::vector<AlienBase*> possibilities;\n\t\tif (_rule.getOperationType() == AMOT_REGION_NEW_BASE)\n\t\t{\n\t\t\t// new base, leave possibilities empty\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (_rule.getOperationType() == AMOT_REGION_EXISTING_BASE || _rule.getOperationType() == AMOT_REGION_NEW_BASE_IF_NECESSARY)\n\t\t\t{\n\t\t\t\t// region only\n\t\t\t\tauto* missionRegion = mod.getRegion(_region, true);\n\t\t\t\tfor (auto* ab : *game.getAlienBases())\n\t\t\t\t{\n\t\t\t\t\tif (missionRegion->insideRegion(ab->getLongitude(), ab->getLatitude()))\n\t\t\t\t\t{\n\t\t\t\t\t\tpossibilities.push_back(ab);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// whole Earth\n\t\t\t\tpossibilities = *game.getAlienBases();\n\t\t\t}\n\t\t}\n\t\tif (!possibilities.empty())\n\t\t{\n\t\t\t// 1. existing base selected\n\t\t\tint selected = RNG::generate(0, possibilities.size() - 1);\n\t\t\t_base = possibilities[selected];\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (_rule.getOperationType() == AMOT_REGION_EXISTING_BASE || _rule.getOperationType() == AMOT_EARTH_EXISTING_BASE)\n\t\t\t{\n\t\t\t\t// 2. no base available, mission aborted!\n\t\t\t\t_interrupted = true;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// 3. spawn a new base\n\t\t\t\tRuleRegion *region = mod.getRegion(_region, true);\n\t\t\t\tif (_rule.getOperationSpawnZone() < 0 || _rule.getOperationSpawnZone() >= (int)region->getMissionZones().size())\n\t\t\t\t{\n\t\t\t\t\tthrow Exception(\"Cannot spawn alien base, invalid operationSpawnZone! Mission: \" + _rule.getType());\n\t\t\t\t}\n\t\t\t\tstd::vector<MissionArea> areas = region->getMissionZones().at(_rule.getOperationSpawnZone()).areas;\n\t\t\t\tstd::pair<double, double> pos;\n\t\t\t\tint tries = 0;\n\t\t\t\tAlienDeployment* operationBaseType = mod.getDeployment(_rule.getOperationBaseType(), true);\n\t\t\t\tbool wantsToSpawnFakeUnderwater = RNG::percent(operationBaseType->getFakeUnderwaterSpawnChance());\n\t\t\t\tbool found = false;\n\t\t\t\twhile (!found)\n\t\t\t\t{\n\t\t\t\t\tMissionArea &area = areas.at(RNG::generate(0, areas.size() - 1));\n\t\t\t\t\tpos.first = RNG::generate(std::min(area.lonMin, area.lonMax), std::max(area.lonMin, area.lonMax));\n\t\t\t\t\tpos.second = RNG::generate(std::min(area.latMin, area.latMax), std::max(area.latMin, area.latMax));\n\t\t\t\t\t++tries;\n\n\t\t\t\t\tif (tries == 100)\n\t\t\t\t\t{\n\t\t\t\t\t\tfound = true; // forced spawn on invalid location\n\t\t\t\t\t}\n\t\t\t\t\telse if (globe.insideLand(pos.first, pos.second) && region->insideRegion(pos.first, pos.second, true))\n\t\t\t\t\t{\n\t\t\t\t\t\tbool isFakeUnderwater = globe.insideFakeUnderwaterTexture(pos.first, pos.second);\n\t\t\t\t\t\tif (wantsToSpawnFakeUnderwater)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (isFakeUnderwater) found = true; // found spawn point on fakeUnderwater texture\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (!isFakeUnderwater) found = true; // found spawn point on land\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tAlienBase* newAlienOperationBase = nullptr;\n\t\t\t\tif (tries < 100 || mod.getAllowAlienBasesOnWrongTextures())\n\t\t\t\t{\n\t\t\t\t\tnewAlienOperationBase = spawnAlienBase(0, engine, pos, operationBaseType);\n\t\t\t\t}\n\t\t\t\tif (newAlienOperationBase)\n\t\t\t\t{\n\t\t\t\t\t_base = newAlienOperationBase;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t_interrupted = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * This function is called when one of the mission's UFOs arrives at it's current destination.\n * It takes care of sending the UFO to the next waypoint, landing UFOs and\n * marking them for removal as required. It must set the game data in a way that the rest of the code\n * understands what to do.\n * @param ufo The UFO that reached it's waypoint.\n * @param engine The game engine, required to get access to game data and game rules.\n * @param globe The earth globe, required to get access to land checks.\n */\nvoid AlienMission::ufoReachedWaypoint(Ufo &ufo, Game &engine, const Globe &globe)\n{\n\tif (_interrupted)\n\t{\n\t\tufo.setDetected(false);\n\t\tufo.setStatus(Ufo::DESTROYED);\n\t\treturn;\n\t}\n\n\tconst Mod &mod = *engine.getMod();\n\tSavedGame &game = *engine.getSavedGame();\n\tconst size_t curWaypoint = ufo.getTrajectoryPoint();\n\tconst size_t nextWaypoint = curWaypoint + 1;\n\tconst UfoTrajectory &trajectory = ufo.getTrajectory();\n\tint waveNumber = ufo.getMissionWaveNumber() > -1 ? ufo.getMissionWaveNumber() : _nextWave - 1;\n\tif (waveNumber < 0)\n\t{\n\t\twaveNumber = _rule.getWaveCount() - 1;\n\t}\n\n\tconst MissionWave &wave = _rule.getWave(waveNumber);\n\tif (nextWaypoint >= trajectory.getWaypointCount())\n\t{\n\t\tufo.setDetected(false);\n\t\tufo.setStatus(Ufo::DESTROYED);\n\t\treturn;\n\t}\n\tufo.setAltitude(trajectory.getAltitude(nextWaypoint));\n\tufo.setTrajectoryPoint(nextWaypoint);\n\tconst RuleRegion &regionRules = *mod.getRegion(_region, true);\n\n\t{\n\t\tstd::pair<double, double> pos = getWaypoint(wave, trajectory, nextWaypoint, globe, regionRules, ufo);\n\n\t\tWaypoint *wp = new Waypoint();\n\t\twp->setLongitude(pos.first);\n\t\twp->setLatitude(pos.second);\n\t\tufo.setDestination(wp);\n\t}\n\n\tif (ufo.getAltitude() != \"STR_GROUND\")\n\t{\n\t\tif (ufo.getLandId() != 0)\n\t\t{\n\t\t\tufo.setLandId(0);\n\t\t}\n\t\t// Set next waypoint.\n\t\tufo.setSpeed(trajectory.applySpeedPercentage(nextWaypoint, ufo.getCraftStats().speedMax));\n\t}\n\telse\n\t{\n\t\t// UFO landed.\n\t\tif (_missionSiteZoneArea != -1 && wave.objective && trajectory.getZone(curWaypoint) == (size_t)(_rule.getSpawnZone()))\n\t\t{\n\t\t\t// Remove UFO, replace with MissionSite.\n\t\t\taddScore(ufo.getLongitude(), ufo.getLatitude(), game);\n\n\t\t\tMissionArea area = regionRules.getMissionZones().at(trajectory.getZone(curWaypoint)).areas.at(_missionSiteZoneArea);\n\t\t\tif (wave.objectiveOnTheLandingSite)\n\t\t\t{\n\t\t\t\t// Note: 'area' is a local variable; we're not changing the ruleset\n\t\t\t\tarea.lonMin = ufo.getLongitude();\n\t\t\t\tarea.lonMax = ufo.getLongitude();\n\t\t\t\tarea.latMin = ufo.getLatitude();\n\t\t\t\tarea.latMax = ufo.getLatitude();\n\t\t\t}\n\t\t\tMissionSite *missionSite = spawnMissionSite(game, mod, area, &ufo);\n\t\t\tif (missionSite && _rule.respawnUfoAfterSiteDespawn())\n\t\t\t{\n\t\t\t\tufo.setStatus(Ufo::IGNORE_ME);\n\t\t\t\tmissionSite->setUfo(&ufo);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tufo.setStatus(Ufo::DESTROYED);\n\t\t\t}\n\t\t\tif (missionSite)\n\t\t\t{\n\t\t\t\tfor (auto* follower : ufo.getCraftFollowers())\n\t\t\t\t{\n\t\t\t\t\tif (follower->getNumTotalUnits() > 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tfollower->setDestination(missionSite);\n\t\t\t\t\t}\n\t\t\t\t\telse if (ufo.getStatus() == Ufo::IGNORE_ME)\n\t\t\t\t\t{\n\t\t\t\t\t\tfollower->returnToBase(); // no craft is allowed to follow an ignored UFO\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse if (trajectory.getID() == UfoTrajectory::RETALIATION_ASSAULT_RUN)\n\t\t{\n\t\t\t// Ignore what the trajectory might say, this is a base assault.\n\t\t\t// Remove UFO, replace with Base defense.\n\t\t\tufo.setDetected(false);\n\t\t\tBase* found = nullptr;\n\t\t\tfor (auto* xbase : *game.getBases())\n\t\t\t{\n\t\t\t\tif (AreSame(xbase->getLongitude(), ufo.getLongitude()) && AreSame(xbase->getLatitude(), ufo.getLatitude()))\n\t\t\t\t{\n\t\t\t\t\tfound = xbase;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!found)\n\t\t\t{\n\t\t\t\tufo.setStatus(Ufo::DESTROYED);\n\t\t\t\t// Only spawn mission if the base is still there.\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tufo.setDestination(found);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tbool landingAllowed = true;\n\t\t\tif (!globe.insideLand(ufo.getLongitude(), ufo.getLatitude()))\n\t\t\t{\n\t\t\t\tlandingAllowed = false; // real water\n\t\t\t}\n\t\t\telse if (globe.insideFakeUnderwaterTexture(ufo.getLongitude(), ufo.getLatitude()))\n\t\t\t{\n\t\t\t\t// decision to land on fake water was done earlier already\n\t\t\t\t// most of the time it's a proper decision, but sometimes it's a forced decision (i.e. no other option left)\n\t\t\t\t// because of forced decisions, let's check if the UFO can (at least theoretically) land on fake water...\n\t\t\t\t// ...and if not, don't land!\n\t\t\t\tif (ufo.getRules()->getFakeWaterLandingChance() <= 0)\n\t\t\t\t{\n\t\t\t\t\tlandingAllowed = false; // UFO was forced to go here, but it's not going to land!\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (landingAllowed)\n\t\t\t{\n\t\t\t\t// Set timer for UFO on the ground.\n\t\t\t\tufo.setSecondsRemaining(trajectory.groundTimer() * 5);\n\t\t\t\tif (ufo.getDetected() && ufo.getLandId() == 0)\n\t\t\t\t{\n\t\t\t\t\tufo.setLandId(engine.getSavedGame()->getId(\"STR_LANDING_SITE\"));\n\t\t\t\t}\n\n\t\t\t\t// Many players wanted this over the years... you're welcome\n\t\t\t\tif (_rule.getObjective() == OBJECTIVE_BASE && wave.objectiveOnTheLandingSite && trajectory.getZone(curWaypoint) == (size_t)(_rule.getSpawnZone()))\n\t\t\t\t{\n\t\t\t\t\tstd::pair<double, double> pos;\n\t\t\t\t\tpos.first = ufo.getLongitude();\n\t\t\t\t\tpos.second = ufo.getLatitude();\n\n\t\t\t\t\tMissionArea dummyArea;\n\t\t\t\t\tAlienDeployment* alienBaseType = chooseAlienBaseType(mod, dummyArea);\n\n\t\t\t\t\tspawnAlienBase(0, engine, pos, alienBaseType);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// There's nothing to land on\n\t\t\t\tufo.setSecondsRemaining(5);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * This function is called when one of the mission's UFOs is shot down (crashed or destroyed).\n * Currently the only thing that happens is delaying the next UFO in the mission sequence.\n * @param ufo The UFO that was shot down.\n */\nvoid AlienMission::ufoShotDown(Ufo &ufo)\n{\n\tswitch (ufo.getStatus())\n\t{\n\tcase Ufo::FLYING:\n\tcase Ufo::LANDED:\n\t\tassert(0 && \"Ufo seems ok!\");\n\t\tbreak;\n\tcase Ufo::CRASHED:\n\tcase Ufo::DESTROYED:\n\t\tif (_nextWave != _rule.getWaveCount())\n\t\t{\n\t\t\t// Delay next wave\n\t\t\t_spawnCountdown += 30 * (RNG::generate(0, 400) + 48);\n\t\t}\n\t\tbreak;\n\tcase Ufo::IGNORE_ME:\n\t\tbreak;\n\t}\n}\n\n/**\n * This function is called when one of the mission's UFOs has finished it's time on the ground.\n * It takes care of sending the UFO to the next waypoint and marking them for removal as required.\n * It must set the game data in a way that the rest of the code understands what to do.\n * @param ufo The UFO that reached it's waypoint.\n * @param game The saved game information.\n */\nvoid AlienMission::ufoLifting(Ufo &ufo, SavedGame &game)\n{\n\tswitch (ufo.getStatus())\n\t{\n\tcase Ufo::FLYING:\n\t\tassert(0 && \"Ufo is already on the air!\");\n\t\tbreak;\n\tcase Ufo::LANDED:\n\tcase Ufo::IGNORE_ME:\n\t\t{\n\t\t\t// base missions only get points when they are completed.\n\t\t\tif (_rule.getPoints() > 0 && _rule.getObjective() != OBJECTIVE_BASE)\n\t\t\t{\n\t\t\t\taddScore(ufo.getLongitude(), ufo.getLatitude(), game);\n\t\t\t}\n\t\t\tufo.setAltitude(\"STR_VERY_LOW\");\n\t\t\tufo.setSpeed(ufo.getTrajectory().applySpeedPercentage(ufo.getTrajectoryPoint(), ufo.getCraftStats().speedMax));\n\t\t}\n\t\tbreak;\n\tcase Ufo::CRASHED:\n\t\t// Mission expired\n\t\tufo.setDetected(false);\n\t\tufo.setStatus(Ufo::DESTROYED);\n\t\tbreak;\n\tcase Ufo::DESTROYED:\n\t\tassert(0 && \"UFO can't fly!\");\n\t\tbreak;\n\t}\n}\n\n/**\n * The new time must be a multiple of 30 minutes, and more than 0.\n * Calling this on a finished mission has no effect.\n * @param minutes The minutes until the next UFO wave will spawn.\n */\nvoid AlienMission::setWaveCountdown(size_t minutes)\n{\n\tassert(minutes != 0 && minutes % 30 == 0);\n\tif (isOver())\n\t{\n\t\treturn;\n\t}\n\t_spawnCountdown = minutes;\n}\n\n/**\n * Assigns a unique ID to this mission.\n * It is an error to assign two IDs to the same mission.\n * @param id The UD to assign.\n */\nvoid AlienMission::setId(int id)\n{\n\tassert(_uniqueID == 0 && \"Reassigning ID!\");\n\t_uniqueID = id;\n}\n\n/**\n * @return The unique ID assigned to this mission.\n */\nint AlienMission::getId() const\n{\n\tassert(_uniqueID != 0 && \"Uninitialized mission!\");\n\treturn _uniqueID;\n}\n\n/**\n * Sets the alien base associated with this mission.\n * Only the alien supply missions care about this.\n * @param base A pointer to an alien base.\n */\nvoid AlienMission::setAlienBase(const AlienBase *base)\n{\n\t_base = base;\n}\n\n/**\n * Only alien supply missions ever have a valid pointer.\n * @return A pointer (possibly 0) of the AlienBase for this mission.\n */\nconst AlienBase *AlienMission::getAlienBase() const\n{\n\treturn _base;\n}\n\n/**\n * Add alien points to the country and region at the coordinates given.\n * @param lon Longitudinal coordinates to check.\n * @param lat Latitudinal coordinates to check.\n * @param game The saved game information.\n */\nvoid AlienMission::addScore(double lon, double lat, SavedGame &game) const\n{\n\tif (_rule.getObjective() == OBJECTIVE_INFILTRATION)\n\t\treturn; // pact score is a special case\n\tfor (auto* region : *game.getRegions())\n\t{\n\t\tif (region->getRules()->insideRegion(lon, lat))\n\t\t{\n\t\t\tregion->addActivityAlien(_rule.getPoints());\n\t\t\tbreak;\n\t\t}\n\t}\n\tfor (auto* country : *game.getCountries())\n\t{\n\t\tif (country->getRules()->insideCountry(lon, lat))\n\t\t{\n\t\t\tcountry->addActivityAlien(_rule.getPoints());\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n/**\n * Spawn an alien base.\n * @param pactCountry A country that has signed a pact with the aliens and allowed them to build this base.\n * @param engine The game engine, required to get access to game data and game rules.\n * @param pos The base coordinates.\n * @param deployment The base type.\n * @return Pointer to the spawned alien base.\n */\nAlienBase *AlienMission::spawnAlienBase(Country *pactCountry, Game &engine, std::pair<double, double> pos, AlienDeployment *deployment)\n{\n\tSavedGame &game = *engine.getSavedGame();\n\tAlienBase *ab = new AlienBase(deployment, game.getMonthsPassed());\n\tif (pactCountry)\n\t{\n\t\tab->setPactCountry(pactCountry->getRules()->getType());\n\t}\n\tab->setAlienRace(_race);\n\tab->setId(game.getId(deployment->getMarkerName()));\n\tab->setLongitude(pos.first);\n\tab->setLatitude(pos.second);\n\tgame.getAlienBases()->push_back(ab);\n\taddScore(ab->getLongitude(), ab->getLatitude(), game);\n\n\tif (Options::oxceGeoscapeDebugLogMaxEntries > 0)\n\t{\n\t\tstd::ostringstream ss;\n\t\tss << \"gameTime: \" << game.getTime()->getFullString();\n\t\tss << \" baseId: \" << ab->getId();\n\t\tss << \" baseType: \" << ab->getType();\n\t\tss << \" race: \" << _race;\n\t\tss << \" region: \" << _region;\n\t\tss << \" deployment: \" << deployment->getType();\n\t\tss << \" missionId: \" << _uniqueID;\n\t\tss << \" missionType: \" << _rule.getType();\n\t\tgame.getGeoscapeDebugLog().push_back(ss.str());\n\t}\n\n\treturn ab;\n}\n\n/**\n * Chooses a mission type for a new alien base.\n */\nAlienDeployment *AlienMission::chooseAlienBaseType(const Mod &mod, const MissionArea &area)\n{\n\tAlienDeployment *deployment = nullptr;\n\tif (!_rule.getSiteType().empty())\n\t{\n\t\tdeployment = mod.getDeployment(_rule.getSiteType(), true);\n\t}\n\tif (!deployment)\n\t{\n\t\tTexture *texture = mod.getGlobe()->getTexture(area.texture);\n\t\tif (texture && !texture->getDeployments().empty())\n\t\t{\n\t\t\t// Note: only used in Area51 mod (as of April 2020)\n\t\t\tdeployment = mod.getDeployment(texture->getRandomDeployment(), true);\n\t\t}\n\t}\n\tif (!deployment)\n\t{\n\t\t// Note: emergency fall-back\n\t\tdeployment = mod.getDeployment(\"STR_ALIEN_BASE_ASSAULT\", true);\n\t}\n\treturn deployment;\n}\n\n/*\n * Sets the mission's region. if the region is incompatible with\n * actually carrying out an attack, use the \"fallback\" region as\n * defined in the ruleset.\n * (this is a slight difference from the original, which just\n * defaulted them to zone[0], North America)\n * @param region the region we want to try to set the mission to.\n * @param mod the mod, in case we need to swap out the region.\n */\nvoid AlienMission::setRegion(const std::string &region, const Mod &mod)\n{\n\tRuleRegion *r = mod.getRegion(region, true);\n\tif (!r->getMissionRegion().empty())\n\t{\n\t\t_region = r->getMissionRegion();\n\t}\n\telse\n\t{\n\t\t_region = region;\n\t}\n}\n\n/**\n * Select a destination based on the criteria of our trajectory and desired waypoint.\n * @param trajectory the trajectory in question.\n * @param nextWaypoint the next logical waypoint in sequence (0 for newly spawned UFOs)\n * @param globe The earth globe, required to get access to land checks.\n * @param region the ruleset for the region of our mission.\n * @param ufo Required when making landing decisions on fake water.\n * @return a set of lon and lat coordinates based on the criteria of the trajectory.\n */\nstd::pair<double, double> AlienMission::getWaypoint(const MissionWave &wave, const UfoTrajectory &trajectory, const size_t nextWaypoint, const Globe &globe, const RuleRegion &region, const Ufo &ufo)\n{\n\tif (trajectory.getZone(nextWaypoint) >= region.getMissionZones().size())\n\t{\n\t\tlogMissionError(trajectory.getZone(nextWaypoint), region);\n\t}\n\n\tif (_missionSiteZoneArea != -1 && wave.objective && trajectory.getZone(nextWaypoint) == (size_t)(_rule.getSpawnZone()))\n\t{\n\t\tif (wave.objectiveOnTheLandingSite)\n\t\t{\n\t\t\treturn getLandPointForMissionSite(globe, region, _rule.getSpawnZone(), _missionSiteZoneArea, ufo);\n\t\t}\n\t\tconst MissionArea *area = &region.getMissionZones().at(_rule.getSpawnZone()).areas.at(_missionSiteZoneArea);\n\t\treturn std::make_pair(area->lonMin, area->latMin);\n\t}\n\n\t// if we are an Earth-based operation\n\tif (_rule.getOperationType() != AMOT_SPACE && _base)\n\t{\n\t\t// and this is our last waypoint\n\t\tif (nextWaypoint >= trajectory.getWaypointCount() - 1)\n\t\t{\n\t\t\t// finish our business at the operation base\n\t\t\treturn std::make_pair(_base->getLongitude(), _base->getLatitude());\n\t\t}\n\t}\n\t// Note: if the operation base is destroyed in the meantime, remaining live UFOs will follow the original trajectory...\n\t// ...therefore it is important to have a valid last trajectory waypoint even for such missions\n\n\tif (trajectory.getWaypointCount() > nextWaypoint + 1 && trajectory.getAltitude(nextWaypoint + 1) == \"STR_GROUND\")\n\t{\n\t\treturn getLandPoint(globe, region, trajectory.getZone(nextWaypoint), ufo);\n\t}\n\treturn region.getRandomPoint(trajectory.getZone(nextWaypoint));\n}\n\n/**\n * Get a random point inside the given region zone.\n * The point will be used to land a UFO, so it HAS to be on land (UNLESS it's landing on a city).\n * @param globe reference to the globe data.\n * @param region reference to the region we want a land point in.\n * @param zone the missionZone set within the region to find a landing zone in.\n * @param ufo Required when making landing decisions on fake water.\n * @return a set of longitudinal and latitudinal coordinates.\n */\nstd::pair<double, double> AlienMission::getLandPoint(const Globe &globe, const RuleRegion &region, size_t zone, const Ufo &ufo)\n{\n\tif (zone >= region.getMissionZones().size() || region.getMissionZones().at(zone).areas.size() == 0)\n\t{\n\t\tlogMissionError(zone, region);\n\t}\n\n\tstd::pair<double, double> pos;\n\n\tif (region.getMissionZones().at(zone).areas.at(0).isPoint()) // if a UFO wants to land on a city, let it.\n\t{\n\t\tpos = region.getRandomPoint(zone);\n\t}\n\telse\n\t{\n\t\tint tries = 0;\n\t\tbool wantsToLandOnFakeWater = RNG::percent(ufo.getRules()->getFakeWaterLandingChance());\n\t\tbool found = false;\n\t\twhile (!found)\n\t\t{\n\t\t\tpos = region.getRandomPoint(zone);\n\t\t\t++tries;\n\n\t\t\tif (tries == 100)\n\t\t\t{\n\t\t\t\tfound = true; // forced decision\n\t\t\t}\n\t\t\telse if (globe.insideLand(pos.first, pos.second) && region.insideRegion(pos.first, pos.second))\n\t\t\t{\n\t\t\t\tbool isFakeWater = globe.insideFakeUnderwaterTexture(pos.first, pos.second);\n\t\t\t\tif (wantsToLandOnFakeWater)\n\t\t\t\t{\n\t\t\t\t\tif (isFakeWater)\n\t\t\t\t\t{\n\t\t\t\t\t\tfound = true; // found landing point on fake water\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif (!isFakeWater)\n\t\t\t\t\t{\n\t\t\t\t\t\tfound = true; // found landing point on land\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (tries == 100)\n\t\t{\n\t\t\tLog(LOG_WARNING) << \"Region: \" << region.getType() << \" Longitude: \" << pos.first << \" Latitude: \" << pos.second << \" invalid zone: \" << zone << \" ufo forced to land on water (or invalid texture)!\";\n\t\t\tif (wantsToLandOnFakeWater)\n\t\t\t{\n\t\t\t\tLog(LOG_WARNING) << \"UFO: \" << ufo.getRules()->getType() << \" wanted to land on fake water.\";\n\t\t\t}\n\t\t}\n\t}\n\treturn pos;\n}\n\n/**\n * Get a random point for the given region, zone and area.\n * The point doesn't necessarily need to be inside the region boundaries.\n * The point will be used to land a UFO, which immediately converts into a mission site, so it HAS to be on land (or fake water).\n */\nstd::pair<double, double> AlienMission::getLandPointForMissionSite(const Globe& globe, const RuleRegion& region, size_t zone, int area, const Ufo& ufo)\n{\n\t// Full error report in case of corrupted saves and/or modding-related issues\n\t// Note: checking only areas; zones were already checked earlier in getWaypoint()\n\tif (region.getMissionZones().at(zone).areas.empty())\n\t{\n\t\tstd::stringstream ss;\n\t\tss << \"Error occurred while trying to determine land+site point for mission type: \" << _rule.getType() << \" in region: \" << region.getType() << \", in zone: \" << zone;\n\t\tss << \", zone has no valid areas.\";\n\t\tthrow Exception(ss.str());\n\t}\n\telse if ((size_t)area >= region.getMissionZones().at(zone).areas.size())\n\t{\n\t\tstd::stringstream ss;\n\t\tss << \"Error occurred while trying to determine land+site point for mission type: \" << _rule.getType() << \" in region: \" << region.getType() << \", in zone: \" << zone;\n\t\tss << \", mission tried to find a land+site point in area \" << area;\n\t\tss << \", but this zone only has areas valid up to \" << region.getMissionZones().at(zone).areas.size() - 1 << \".\";\n\t\tthrow Exception(ss.str());\n\t}\n\n\tstd::pair<double, double> pos;\n\t{\n\t\tint tries = 0;\n\t\tbool wantsToLandOnFakeWater = RNG::percent(ufo.getRules()->getFakeWaterLandingChance());\n\t\tbool found = false;\n\t\twhile (!found)\n\t\t{\n\t\t\tpos = region.getRandomPoint(zone, area); // pass the area as a parameter too!\n\t\t\t++tries;\n\n\t\t\tif (tries == 100)\n\t\t\t{\n\t\t\t\tfound = true; // forced decision\n\t\t\t}\n\t\t\telse if (globe.insideLand(pos.first, pos.second) /* && region.insideRegion(pos.first, pos.second) */) // doesn't need to be inside the region!\n\t\t\t{\n\t\t\t\tbool isFakeWater = globe.insideFakeUnderwaterTexture(pos.first, pos.second);\n\t\t\t\tif (wantsToLandOnFakeWater)\n\t\t\t\t{\n\t\t\t\t\tif (isFakeWater)\n\t\t\t\t\t{\n\t\t\t\t\t\tfound = true; // found landing point on fake water\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif (!isFakeWater)\n\t\t\t\t\t{\n\t\t\t\t\t\tfound = true; // found landing point on land\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (tries == 100)\n\t\t{\n\t\t\tLog(LOG_WARNING) << \"Region: \" << region.getType() << \" Longitude: \" << pos.first << \" Latitude: \" << pos.second << \" zone: \" << zone << \" area: \" << area << \" ufo forced to land on water (or invalid texture)!\";\n\t\t\tif (wantsToLandOnFakeWater)\n\t\t\t{\n\t\t\t\tLog(LOG_WARNING) << \"UFO: \" << ufo.getRules()->getType() << \" wanted to land on fake water.\";\n\t\t\t}\n\t\t}\n\t}\n\treturn pos;\n}\n\n/**\n * Attempt to spawn a Mission Site at a given location.\n * @param game reference to the saved game.\n * @param rules reference to the game rules.\n * @param area the point on the globe at which to spawn this site.\n * @param ufo ufo that spawn that mission.\n * @return a pointer to the mission site.\n */\nMissionSite *AlienMission::spawnMissionSite(SavedGame &game, const Mod &mod, const MissionArea &area, const Ufo *ufo, AlienDeployment *missionOveride)\n{\n\tTexture *texture = mod.getGlobe()->getTexture(area.texture);\n\tAlienDeployment *deployment = nullptr;\n\tAlienDeployment *alienCustomDeploy = ufo ? mod.getDeployment(ufo->getCraftStats().missionCustomDeploy) : 0;\n\n\tif (missionOveride)\n\t{\n\t\tdeployment = missionOveride;\n\t}\n\telse if (mod.getDeployment(_rule.getSiteType()))\n\t{\n\t\tdeployment = mod.getDeployment(_rule.getSiteType());\n\t}\n\telse\n\t{\n\t\tif (!texture)\n\t\t{\n\t\t\tthrow Exception(\"Error occurred while spawning mission site: \" + _rule.getType());\n\t\t}\n\t\tdeployment = mod.getDeployment(texture->getRandomDeployment(), true);\n\t}\n\n\tif (deployment)\n\t{\n\t\tMissionSite *missionSite = new MissionSite(&_rule, deployment, alienCustomDeploy);\n\t\tmissionSite->setLongitude(RNG::generate(area.lonMin, area.lonMax));\n\t\tmissionSite->setLatitude(RNG::generate(area.latMin, area.latMax));\n\t\tmissionSite->setId(game.getId(deployment->getMarkerName()));\n\t\tmissionSite->setSecondsRemaining(RNG::generate(deployment->getDurationMin(), deployment->getDurationMax()) * 3600);\n\t\tmissionSite->setAlienRace(_race);\n\t\tmissionSite->setTexture(area.texture);\n\t\tmissionSite->setCity(area.name);\n\t\tgame.getMissionSites()->push_back(missionSite);\n\n\t\tif (Options::oxceGeoscapeDebugLogMaxEntries > 0)\n\t\t{\n\t\t\tstd::ostringstream ss;\n\t\t\tss << \"gameTime: \" << game.getTime()->getFullString();\n\t\t\tss << \" siteId: \" << missionSite->getId();\n\t\t\tss << \" siteType: \" << missionSite->getType();\n\t\t\tss << \" race: \" << _race;\n\t\t\tss << \" region: \" << _region;\n\t\t\tif (!missionSite->getCity().empty())\n\t\t\t{\n\t\t\t\tss << \" city: \" << missionSite->getCity();\n\t\t\t}\n\t\t\tss << \" deployment: \" << deployment->getType();\n\t\t\tif (alienCustomDeploy)\n\t\t\t{\n\t\t\t\tss << \" / \" << alienCustomDeploy->getType();\n\t\t\t}\n\t\t\tss << \" missionId: \" << _uniqueID;\n\t\t\tss << \" missionType: \" << _rule.getType();\n\t\t\tgame.getGeoscapeDebugLog().push_back(ss.str());\n\t\t}\n\n\t\treturn missionSite;\n\t}\n\treturn 0;\n}\n\n/**\n * Tell the mission which entry in the 'areas' array we're targetting for our missionSite payload.\n * @param area the number of the area to target, synonymous with a city.\n */\nvoid AlienMission::setMissionSiteZoneArea(int area)\n{\n\t_missionSiteZoneArea = area;\n}\n\nvoid AlienMission::logMissionError(int zone, const RuleRegion &region)\n{\n\tif (!region.getMissionZones().empty())\n\t{\n\t\tstd::stringstream ss, ss2;\n\t\tss << zone;\n\t\tss2 << region.getMissionZones().size() - 1;\n\t\tthrow Exception(\"Error occurred while trying to determine waypoint for mission type: \" + _rule.getType() + \" in region: \" + region.getType() + \", mission tried to find a waypoint in zone \" + ss.str() + \" but this region only has zones valid up to \" + ss2.str() + \".\");\n\t}\n\telse\n\t{\n\t\tthrow Exception(\"Error occurred while trying to determine waypoint for mission type: \" + _rule.getType() + \" in region: \" + region.getType() + \", region has no valid zones.\");\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Savegame/AlienMission.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include \"../Engine/Yaml.h\"\n\nnamespace OpenXcom\n{\n\nclass RuleAlienMission;\nclass Ufo;\nclass Globe;\nclass Game;\nclass SavedGame;\nclass Mod;\nclass RuleRegion;\nstruct MissionWave;\nclass UfoTrajectory;\nclass AlienBase;\nclass MissionSite;\nstruct MissionArea;\nclass AlienDeployment;\nclass Country;\nclass Base;\n\n/**\n * Represents an ongoing alien mission.\n * Contains variable info about the mission, like spawn counter, target region\n * and current wave.\n * @sa RuleAlienMission\n */\nclass AlienMission\n{\nprivate:\n\tconst RuleAlienMission &_rule;\n\tstd::string _region, _race;\n\tsize_t _nextWave;\n\tsize_t _nextUfoCounter;\n\tsize_t _spawnCountdown;\n\tsize_t _liveUfos;\n\tbool _interrupted, _multiUfoRetaliationInProgress;\n\tint _uniqueID, _missionSiteZoneArea;\n\tconst AlienBase *_base;\npublic:\n\t// Data\n\n\t/// Creates a mission of the specified type.\n\tAlienMission(const RuleAlienMission &rule);\n\t/// Cleans up the mission info.\n\t~AlienMission();\n\t/// Loads the mission from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader, SavedGame &game, const Mod* mod);\n\t/// Saves the mission to YAML.\n\tvoid save(YAML::YamlNodeWriter writer) const;\n\t/// Gets the mission's ruleset.\n\tconst RuleAlienMission &getRules() const { return _rule; }\n\t/// Gets the mission's region.\n\tconst std::string &getRegion() const { return _region; }\n\t/// Sets the mission's region.\n\tvoid setRegion(const std::string &region, const Mod &rules);\n\t/// Gets the mission's race.\n\tconst std::string &getRace() const { return _race; }\n\t/// Sets the mission's race.\n\tvoid setRace(const std::string &race) { _race = race; }\n\t/// Gets the minutes until next wave spawns.\n\tsize_t getWaveCountdown() const { return _spawnCountdown; }\n\t/// Sets the minutes until next wave spawns.\n\tvoid setWaveCountdown(size_t minutes);\n\t/// Sets the unique ID for this mission.\n\tvoid setId(int id);\n\t/// Gets the unique ID for this mission.\n\tint getId() const;\n\t/// Gets the alien base for this mission.\n\tconst AlienBase *getAlienBase() const;\n\t/// Sets the alien base for this mission.\n\tvoid setAlienBase(const AlienBase *base);\n\n\t// Behaviour\n\n\t/// Is this mission over?\n\tbool isOver() const;\n\t/// Handle UFO spawning for the mission.\n\tvoid think(Game &engine, const Globe &globe);\n\t/// Initialize with values from rules.\n\tvoid start(Game &engine, const Globe &globe, size_t initialCount = 0);\n\t/// Increase number of live UFOs.\n\tvoid increaseLiveUfos() { ++_liveUfos; }\n\t/// Decrease number of live UFOs.\n\tvoid decreaseLiveUfos() { --_liveUfos; }\n\t/// Sets the interrupted flag.\n\tvoid setInterrupted(bool interrupted) { _interrupted = interrupted; }\n\t/// Sets the multiUfoRetaliationInProgress flag.\n\tvoid setMultiUfoRetaliationInProgress(bool multiUfoRetaliationInProgress) { _multiUfoRetaliationInProgress = multiUfoRetaliationInProgress; }\n\t/// Handle UFO reaching a waypoint.\n\tvoid ufoReachedWaypoint(Ufo &ufo, Game &engine, const Globe &globe);\n\t/// Handle UFO lifting from the ground.\n\tvoid ufoLifting(Ufo &ufo, SavedGame &game);\n\t/// Handle UFO shot down.\n\tvoid ufoShotDown(Ufo &ufo);\n\t/// Handle Points for mission successes.\n\tvoid addScore(double lon, double lat, SavedGame &game) const;\n\t/// Keep track of the city/whatever that we're going to target.\n\tvoid setMissionSiteZoneArea(int area);\nprivate:\n\t/// Selects an xcom base in a given region.\n\tBase* selectXcomBase(SavedGame& game, const RuleRegion& regionRules);\n\t/// Spawns a UFO, based on mission rules.\n\tUfo *spawnUfo(SavedGame &game, const Mod &mod, const Globe &globe, const MissionWave &wave, const UfoTrajectory &trajectory);\n\t/// Spawn an alien base\n\tAlienBase *spawnAlienBase(Country *pactCountry, Game &engine, std::pair<double, double> pos, AlienDeployment *deployment);\n\t/// Chooses a mission type for a new alien base.\n\tAlienDeployment *chooseAlienBaseType(const Mod &mod, const MissionArea &area);\n\t/// Select a destination (lon/lat) based on the criteria of our trajectory and desired waypoint.\n\tstd::pair<double, double> getWaypoint(const MissionWave &wave, const UfoTrajectory &trajectory, const size_t nextWaypoint, const Globe &globe, const RuleRegion &region, const Ufo &ufo);\n\t/// Get a random landing point inside the given region zone.\n\tstd::pair<double, double> getLandPoint(const Globe &globe, const RuleRegion &region, size_t zone, const Ufo &ufo);\n\t/// Get a random landing point inside the given region zone and area.\n\tstd::pair<double, double> getLandPointForMissionSite(const Globe& globe, const RuleRegion& region, size_t zone, int area, const Ufo& ufo);\n\t/// Spawns a MissionSite at a specific location.\n\tMissionSite *spawnMissionSite(SavedGame &game, const Mod &mod, const MissionArea &area, const Ufo *ufo = 0, AlienDeployment *missionOveride = 0);\n\t/// Provides some error information for bad mission definitions\n\tvoid logMissionError(int zone, const RuleRegion &region);\n\n};\n\n}\n"
  },
  {
    "path": "src/Savegame/AlienStrategy.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <assert.h>\n#include \"AlienStrategy.h\"\n#include \"WeightedOptions.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleRegion.h\"\n#include \"../Engine/Logger.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Create an AlienStrategy with no values.\n * Running a game like this will most likely crash.\n */\nAlienStrategy::AlienStrategy()\n{\n\t// Empty by design!\n}\n\n/**\n * Free all resources used by this AlienStrategy.\n */\nAlienStrategy::~AlienStrategy()\n{\n\t// Free allocated memory.\n\tfor (auto& pair : _regionMissions)\n\t{\n\t\tdelete pair.second;\n\t}\n}\n\n/**\n * Get starting values from the rules.\n * @param mod Pointer to the game mod.\n */\nvoid AlienStrategy::init(const Mod *mod)\n{\n\tfor (const auto& regionName : mod->getRegionsList())\n\t{\n\t\tRuleRegion *region = mod->getRegion(regionName, true);\n\t\t_regionChances.set(regionName, region->getWeight());\n\t\tWeightedOptions *missions = new WeightedOptions(region->getAvailableMissions());\n\t\t_regionMissions.insert(std::make_pair(regionName, missions));\n\t}\n}\n\n/**\n * Loads the data from a YAML file.\n * @param node YAML node.\n */\nvoid AlienStrategy::load(const YAML::YamlNodeReader& reader, const Mod* mod)\n{\n\t// Free allocated memory.\n\tfor (auto& pair : _regionMissions)\n\t{\n\t\tdelete pair.second;\n\t}\n\t_regionMissions.clear();\n\t_regionChances.clear();\n\t_regionChances.load(reader[\"regions\"]);\n\n\tfor (const auto& possibleMissionReader : reader[\"possibleMissions\"].children())\n\t{\n\t\tstd::string region = possibleMissionReader[\"region\"].readVal<std::string>();\n\t\tif (mod->getRegion(region, false))\n\t\t{\n\t\t\tconst auto& missionOptionsReader = possibleMissionReader[\"missions\"];\n\t\t\tWeightedOptions* options = new WeightedOptions();\n\t\t\toptions->load(missionOptionsReader);\n\t\t\t_regionMissions.insert(std::make_pair(region, options));\n\t\t}\n\t\telse\n\t\t{\n\t\t\tLog(LOG_WARNING) << \"Corrupted save: Alien strategy contains an invalid region: \" << region << \", skipping...\";\n\t\t}\n\t}\n\treader.tryRead(\"missionLocations\", _missionLocations);\n\treader.tryRead(\"missionsRun\", _missionRuns);\n}\n\n/**\n * Saves the alien data to a YAML file.\n * @return YAML node.\n */\nvoid AlienStrategy::save(YAML::YamlNodeWriter writer) const\n{\n\twriter.setAsMap();\n\t_regionChances.save(writer[\"regions\"]);\n\tif (!_regionMissions.empty())\n\t{\n\t\tauto possibleMissionsWriter = writer[\"possibleMissions\"];\n\t\tpossibleMissionsWriter.setAsSeq();\n\t\tfor (auto& pair : _regionMissions)\n\t\t{\n\t\t\tauto regionWriter = possibleMissionsWriter.write();\n\t\t\tregionWriter.setAsMap();\n\t\t\tregionWriter.write(\"region\", pair.first);\n\t\t\tpair.second->save(regionWriter[\"missions\"]);\n\t\t}\n\t}\n\twriter.write(\"missionLocations\", _missionLocations);\n\twriter.write(\"missionsRun\", _missionRuns);\n}\n\n/**\n * Choose one of the regions for a mission.\n * @param mod Pointer to the mod.\n * @return The region id.\n */\nstd::string AlienStrategy::chooseRandomRegion(const Mod *mod)\n{\n\tstd::string chosen = _regionChances.choose();\n\tif (chosen.empty())\n\t{\n\t\t// no more missions to choose from: refresh.\n\t\t// First, free allocated memory.\n\t\tfor (auto& pair : _regionMissions)\n\t\t{\n\t\t\tdelete pair.second;\n\t\t}\n\t\t_regionMissions.clear();\n\t\t// re-initialize the list\n\t\tinit(mod);\n\t\t// now let's try that again.\n\t\tchosen = _regionChances.choose();\n\t}\n\tassert (\"\" != chosen);\n\treturn chosen;\n}\n\n/**\n * Choose one missions available for @a region.\n * @param region The region id.\n * @return The mission id.\n */\nstd::string AlienStrategy::chooseRandomMission(const std::string &region) const\n{\n\tauto found = _regionMissions.find(region);\n\tassert(found != _regionMissions.end());\n\treturn found->second->choose();\n}\n\n/**\n * Remove @a mission from the list of possible missions for @a region.\n * @param region The region id.\n * @param mission The mission id.\n * @return If there are no more regions with missions available.\n */\nbool AlienStrategy::removeMission(const std::string &region, const std::string &mission)\n{\n\tauto found = _regionMissions.find(region);\n\tif (found != _regionMissions.end())\n\t{\n\t\tfound->second->set(mission, 0);\n\t\tif (found->second->empty())\n\t\t{\n\t\t\t_regionMissions.erase(found);\n\t\t\t_regionChances.set(region, 0);\n\t\t}\n\t}\n\treturn _regionMissions.empty();\n}\n\n\n/**\n * Checks the number of missions run labelled as \"varName\".\n * @return the number of missions run under the variable name.\n */\nint AlienStrategy::getMissionsRun(const std::string &varName)\n{\n\tif (_missionRuns.find(varName) != _missionRuns.end())\n\t\treturn _missionRuns[varName];\n\treturn 0;\n}\n\n/**\n * Increments the number of missions run labelled as \"varName\".\n * @param varName the variable name that we want to use to keep track of this.\n * @param increment the value to increment by.\n */\nvoid AlienStrategy::addMissionRun(const std::string &varName, int increment)\n{\n\tif (varName.empty())\n\t\treturn;\n\t_missionRuns[varName] += increment;\n}\n\n/**\n * Adds a mission location to our storage array.\n * @param varName the name on the variable under which to store this info.\n * @param regionName the name of the region we're using.\n * @param zoneNumber the number of the zone within that region we're using.\n * @param maximum the maximum size of the list we want to maintain.\n */\nvoid AlienStrategy::addMissionLocation(const std::string &varName, const std::string &regionName, int zoneNumber, int maximum)\n{\n\tif (maximum <= 0) return;\n\t_missionLocations[varName].push_back(std::make_pair(regionName, zoneNumber));\n\tif (_missionLocations[varName].size() > (size_t)(maximum))\n\t{\n\t\t_missionLocations.erase(_missionLocations.begin());\n\t}\n}\n\n/**\n * Checks that a given mission location (city or whatever) isn't stored in our list of previously attacked locations.\n * @param varName the name of the variable that is storing our data.\n * @param regionName the name of the region we're looking for.\n * @param zoneNumber the number in the region that we want to check.\n * @return if the region is valid (meaning it is not in our table).\n */\nbool AlienStrategy::validMissionLocation(const std::string &varName, const std::string &regionName, int zoneNumber)\n{\n\tif (_missionLocations.find(varName) != _missionLocations.end())\n\t{\n\t\tfor (const auto& pair : _missionLocations[varName])\n\t\t{\n\t\t\tif (pair.first == regionName && pair.second == zoneNumber)\n\t\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n}\n\n/**\n * Checks that a given region appears in our strategy table.\n * @param region the region we want to check for validity.\n * @return if the region appears in the table or not.\n */\nbool AlienStrategy::validMissionRegion(const std::string &region)\n{\n\tauto search = _regionMissions.find(region);\n\treturn (search != _regionMissions.end());\n}\n\n}\n"
  },
  {
    "path": "src/Savegame/AlienStrategy.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/Yaml.h\"\n#include \"WeightedOptions.h\"\n\nnamespace OpenXcom\n{\n\nclass Mod;\n\n/**\n * Stores the information about alien strategy.\n */\nclass AlienStrategy\n{\npublic:\n\t/// Create an AlienStrategy with no data.\n\tAlienStrategy();\n\t/// Free resources used by the AlienStrategy.\n\t~AlienStrategy();\n\t/// Initialize values according to the rules.\n\tvoid init(const Mod *mod);\n\t/// Loads the data from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader, const Mod* mod);\n\t/// Saves the data to YAML.\n\tvoid save(YAML::YamlNodeWriter writer) const;\n\t/// Choose a random region for a regular mission.\n\tstd::string chooseRandomRegion(const Mod *mod);\n\t/// Choose a random mission for a region.\n\tstd::string chooseRandomMission(const std::string &region) const;\n\t/// Remove a region and mission from the list of possibilities.\n\tbool removeMission(const std::string &region, const std::string &mission);\n\t/// Checks the number of missions run labelled as \"varName\".\n\tint getMissionsRun(const std::string &varName);\n\t/// Increments the number of missions run labelled as \"varName\".\n\tvoid addMissionRun(const std::string &varName, int increment = 1);\n\t/// Adds a mission location to our storage array.\n\tvoid addMissionLocation(const std::string &varName, const std::string &regionName, int zoneNumber, int maximum);\n\t/// Checks that a given mission location (city or whatever) isn't stored in our list of previously attacked locations.\n\tbool validMissionLocation(const std::string &varName, const std::string &regionName, int zoneNumber);\n\t/// Checks that a given region appears in our strategy table.\n\tbool validMissionRegion(const std::string &regionName);\nprivate:\n\t/// The chances of each region to be targeted for a mission.\n\tWeightedOptions _regionChances;\n\t/// The chances of each mission type for each region.\n\tstd::map<std::string, WeightedOptions*> _regionMissions;\n\n\t// Disable copy and assignments.\n\tAlienStrategy(const AlienStrategy &);\n\tAlienStrategy &operator=(const AlienStrategy &);\n\tstd::map<std::string, int> _missionRuns;\n\tstd::map<std::string, std::vector<std::pair<std::string, int> > > _missionLocations;\n\n};\n\n}\n"
  },
  {
    "path": "src/Savegame/Base.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Base.h\"\n#include \"../fmath.h\"\n#include <stack>\n#include <algorithm>\n#include <functional>\n#include \"BaseFacility.h\"\n#include \"../Mod/RuleBaseFacility.h\"\n#include \"Craft.h\"\n#include \"SavedGame.h\"\n#include \"../Mod/RuleCraft.h\"\n#include \"../Mod/Mod.h\"\n#include \"ItemContainer.h\"\n#include \"Soldier.h\"\n#include \"../Engine/Language.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Mod/RuleManufacture.h\"\n#include \"../Mod/RuleResearch.h\"\n#include \"Transfer.h\"\n#include \"ResearchProject.h\"\n#include \"Production.h\"\n#include \"Vehicle.h\"\n#include \"Target.h\"\n#include \"Ufo.h\"\n#include \"../Engine/RNG.h\"\n#include \"../Engine/Options.h\"\n#include \"../Mod/RuleSoldier.h\"\n#include \"../Engine/Logger.h\"\n#include \"../Engine/Collections.h\"\n#include \"WeightedOptions.h\"\n#include \"AlienMission.h\"\n#include \"Country.h\"\n#include \"../Mod/RuleCountry.h\"\n#include \"Region.h\"\n#include \"../Mod/RuleRegion.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes an empty base.\n * @param mod Pointer to mod.\n */\nBase::Base(const Mod *mod) : Target(), _mod(mod), _scientists(0), _engineers(0), _inBattlescape(false),\n\t_retaliationTarget(false), _retaliationMission(nullptr), _fakeUnderwater(false)\n{\n\t_items = new ItemContainer();\n}\n\n/**\n * Deletes the contents of the base from memory.\n */\nBase::~Base()\n{\n\tfor (auto* fac : _facilities)\n\t{\n\t\tdelete fac;\n\t}\n\tfor (auto* soldier : _soldiers)\n\t{\n\t\tdelete soldier;\n\t}\n\tfor (auto* xcraft : _crafts)\n\t{\n\t\tdelete xcraft;\n\t}\n\tfor (auto* transfer : _transfers)\n\t{\n\t\tdelete transfer;\n\t}\n\tfor (auto* prod : _productions)\n\t{\n\t\tdelete prod;\n\t}\n\tdelete _items;\n\tfor (auto* proj : _research)\n\t{\n\t\tdelete proj;\n\t}\n\tCollections::deleteAll(_vehiclesFromBase);\n}\n\n/**\n * Loads the base from a YAML file.\n * @param node YAML node.\n * @param save Pointer to saved game.\n * @param newGame Is this the first base of a new game?\n * @param newBattleGame Is this the base of a skirmish game?\n */\nvoid Base::load(const YAML::YamlNodeReader& reader, SavedGame *save, bool newGame, bool newBattleGame)\n{\n\tTarget::load(reader);\n\tif (!newGame || !Options::customInitialBase || newBattleGame)\n\t{\n\t\tfor (const auto& facilityReader : reader[\"facilities\"].children())\n\t\t{\n\t\t\tstd::string type = facilityReader[\"type\"].readVal<std::string>();\n\t\t\tif (_mod->getBaseFacility(type))\n\t\t\t{\n\t\t\t\tBaseFacility* f = new BaseFacility(_mod->getBaseFacility(type), this);\n\t\t\t\tf->load(facilityReader);\n\t\t\t\t_facilities.push_back(f);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tLog(LOG_ERROR) << \"Failed to load facility \" << type;\n\t\t\t}\n\t\t}\n\t}\n\tfor (const auto& craftReader : reader[\"crafts\"].children())\n\t{\n\t\tstd::string type = craftReader[\"type\"].readVal<std::string>();\n\t\tif (_mod->getCraft(type))\n\t\t{\n\t\t\tCraft* c = new Craft(_mod->getCraft(type), this);\n\t\t\tc->load(craftReader, _mod->getScriptGlobal(), _mod, save);\n\t\t\t_crafts.push_back(c);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"Failed to load craft \" << type;\n\t\t}\n\t}\n\tfor (const auto& soldierReader : reader[\"soldiers\"].children())\n\t{\n\t\tstd::string type = soldierReader[\"type\"].readVal(_mod->getSoldiersList().front());\n\t\tif (_mod->getSoldier(type))\n\t\t{\n\t\t\tSoldier* s = new Soldier(_mod->getSoldier(type), nullptr, 0 /*nationality*/);\n\t\t\ts->load(soldierReader, _mod, save, _mod->getScriptGlobal());\n\t\t\ts->setCraft(0);\n\t\t\tif (const auto& craftIdReader = soldierReader[\"craft\"])\n\t\t\t{\n\t\t\t\tCraftId craftId = Craft::loadId(craftIdReader);\n\t\t\t\tfor (auto* xcraft : _crafts)\n\t\t\t\t{\n\t\t\t\t\tif (xcraft->getUniqueId() == craftId)\n\t\t\t\t\t{\n\t\t\t\t\t\ts->setCraft(xcraft);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t_soldiers.push_back(s);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"Failed to load soldier \" << type;\n\t\t}\n\t}\n\n\t_items->load(reader[\"items\"], _mod);\n\n\treader.tryRead(\"scientists\", _scientists);\n\treader.tryRead(\"engineers\", _engineers);\n\treader.tryRead(\"inBattlescape\", _inBattlescape);\n\n\tfor (const auto& transfersReader : reader[\"transfers\"].children())\n\t{\n\t\tint hours = transfersReader[\"hours\"].readVal<int>();\n\t\tTransfer *t = new Transfer(hours);\n\t\tif (t->load(transfersReader, this, _mod, save))\n\t\t{\n\t\t\t_transfers.push_back(t);\n\t\t}\n\t}\n\tfor (const auto& researchReader : reader[\"research\"].children())\n\t{\n\t\tstd::string research = researchReader[\"project\"].readVal<std::string>();\n\t\tif (_mod->getResearch(research))\n\t\t{\n\t\t\tResearchProject *r = new ResearchProject(_mod->getResearch(research));\n\t\t\tr->load(researchReader);\n\t\t\t_research.push_back(r);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_scientists += researchReader[\"assigned\"].readVal(0);\n\t\t\tLog(LOG_ERROR) << \"Failed to load research \" << research;\n\t\t}\n\t}\n\tfor (const auto& productionReader : reader[\"productions\"].children())\n\t{\n\t\tstd::string item = productionReader[\"item\"].readVal<std::string>();\n\t\tif (_mod->getManufacture(item))\n\t\t{\n\t\t\tProduction *p = new Production(_mod->getManufacture(item), 0);\n\t\t\tp->load(productionReader);\n\t\t\t_productions.push_back(p);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_engineers += productionReader[\"assigned\"].readVal(0);\n\t\t\tLog(LOG_ERROR) << \"Failed to load manufacture \" << item;\n\t\t}\n\t}\n\n\treader.tryRead(\"retaliationTarget\", _retaliationTarget);\n\tif (const auto& missionIdReader = reader[\"retaliationMissionUniqueId\"])\n\t{\n\t\tint missionId = missionIdReader.readVal<int>();\n\t\tfor (auto* am : save->getAlienMissions())\n\t\t{\n\t\t\tif (am->getId() == missionId)\n\t\t\t{\n\t\t\t\t_retaliationMission = am;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\treader.tryRead(\"fakeUnderwater\", _fakeUnderwater);\n\n\tisOverlappingOrOverflowing(); // don't crash, just report in the log file...\n}\n\n/**\n * Finishes loading the base (more specifically all craft in the base) from YAML.\n * @param node YAML node.\n * @param save Pointer to saved game.\n */\nvoid Base::finishLoading(const YAML::YamlNodeReader& reader, SavedGame *save)\n{\n\tfor (const auto& craftsReader : reader[\"crafts\"].children())\n\t{\n\t\tint id = craftsReader[\"id\"].readVal<int>();\n\t\tstd::string type = craftsReader[\"type\"].readVal<std::string>();\n\t\tif (_mod->getCraft(type))\n\t\t{\n\t\t\tCraft *craft = 0;\n\t\t\tfor (auto* xcraft : _crafts)\n\t\t\t{\n\t\t\t\tif (xcraft->getId() == id && xcraft->getRules()->getType() == type)\n\t\t\t\t{\n\t\t\t\t\tcraft = xcraft;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (craft)\n\t\t\t{\n\t\t\t\tcraft->finishLoading(craftsReader, save);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"Failed to load craft \" << type;\n\t\t}\n\t}\n\tcalculateServices(save);\n}\n\n/**\n * Pre-calculates base services provided by region and country.\n */\nvoid Base::calculateServices(SavedGame* save)\n{\n\tfor (const auto* country : *save->getCountries())\n\t{\n\t\tif (country->getRules()->insideCountry(_lon, _lat))\n\t\t{\n\t\t\t_provideBaseFunc |= country->getRules()->getProvidedBaseFunc();\n\t\t\t_forbiddenBaseFunc |= country->getRules()->getForbiddenBaseFunc();\n\t\t\tbreak;\n\t\t}\n\t}\n\tfor (const auto* region : *save->getRegions())\n\t{\n\t\tif (region->getRules()->insideRegion(_lon, _lat))\n\t\t{\n\t\t\t_provideBaseFunc |= region->getRules()->getProvidedBaseFunc();\n\t\t\t_forbiddenBaseFunc |= region->getRules()->getForbiddenBaseFunc();\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n/**\n * Tests whether the base facilities are within the base boundaries and not overlapping.\n * @return True if the base has a problem.\n */\nbool Base::isOverlappingOrOverflowing()\n{\n\tbool result = false;\n\tBaseFacility* grid[BASE_SIZE][BASE_SIZE];\n\n\t// i don't think i NEED to do this for a pointer array, but who knows what might happen on weird archaic linux distros if i don't?\n\tfor (int x = 0; x < BASE_SIZE; ++x)\n\t{\n\t\tfor (int y = 0; y < BASE_SIZE; ++y)\n\t\t{\n\t\t\tgrid[x][y] = 0;\n\t\t}\n\t}\n\n\tfor (auto* fac : _facilities)\n\t{\n\t\tconst RuleBaseFacility *rules = fac->getRules();\n\t\tint facilityX = fac->getX();\n\t\tint facilityY = fac->getY();\n\t\tint facilitySizeX = rules->getSizeX();\n\t\tint facilitySizeY = rules->getSizeY();\n\n\t\tif (facilityX < 0 || facilityY < 0 || facilityX + (facilitySizeX - 1) >= BASE_SIZE || facilityY + (facilitySizeY - 1) >= BASE_SIZE)\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"Facility \" << rules->getType()\n\t\t\t\t<< \" at [\" << facilityX << \", \" << facilityY\n\t\t\t\t<< \"] (size [\" << facilitySizeX << \", \" << facilitySizeY\n\t\t\t\t<< \"]) is outside of base boundaries.\";\n\t\t\tresult = true;\n\t\t\tcontinue;\n\t\t}\n\n\t\tfor (int x = facilityX; x < facilityX + facilitySizeX; ++x)\n\t\t{\n\t\t\tfor (int y = facilityY; y < facilityY + facilitySizeY; ++y)\n\t\t\t{\n\t\t\t\tif (grid[x][y] != 0)\n\t\t\t\t{\n\t\t\t\t\tLog(LOG_ERROR) << \"Facility \" << rules->getType()\n\t\t\t\t\t\t<< \" at [\" << facilityX << \", \" << facilityY\n\t\t\t\t\t\t<< \"] (size [\" << facilitySizeX << \", \" << facilitySizeY\n\t\t\t\t\t\t<< \"]) overlaps with \" << grid[x][y]->getRules()->getType()\n\t\t\t\t\t\t<< \" at [\" << x << \", \" << y\n\t\t\t\t\t\t<< \"] (size [\" << grid[x][y]->getRules()->getSizeX() << \", \" << grid[x][y]->getRules()->getSizeY()\n\t\t\t\t\t\t<< \")\";\n\t\t\t\t\tresult = true;\n\t\t\t\t}\n\t\t\t\tgrid[x][y] = fac;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result;\n}\n\n/**\n * Saves the base to a YAML file.\n * @return YAML node.\n */\nvoid Base::save(YAML::YamlNodeWriter writer) const\n{\n\twriter.setAsMap();\n\tTarget::save(writer);\n\twriter.write(\"facilities\", _facilities,\n\t\t[](YAML::YamlNodeWriter& vectorWriter, BaseFacility* f)\n\t\t{ f->save(vectorWriter.write()); });\n\twriter.write(\"soldiers\", _soldiers,\n\t\t[&](YAML::YamlNodeWriter& vectorWriter, Soldier* s)\n\t\t{ s->save(vectorWriter.write(), _mod->getScriptGlobal()); });\n\twriter.write(\"crafts\", _crafts,\n\t\t[&](YAML::YamlNodeWriter& vectorWriter, Craft* c)\n\t\t{ c->save(vectorWriter.write(), _mod->getScriptGlobal()); });\n\t_items->save(writer[\"items\"]);\n\twriter.write(\"scientists\", _scientists);\n\twriter.write(\"engineers\", _engineers);\n\tif (_inBattlescape)\n\t\twriter.write(\"inBattlescape\", _inBattlescape);\n\twriter.write(\"transfers\", _transfers,\n\t\t[&](YAML::YamlNodeWriter& vectorWriter, Transfer* t)\n\t\t{ t->save(vectorWriter.write(), this, _mod); });\n\twriter.write(\"research\", _research,\n\t\t[](YAML::YamlNodeWriter& vectorWriter, ResearchProject* r)\n\t\t{ r->save(vectorWriter.write()); });\n\twriter.write(\"productions\", _productions,\n\t\t[](YAML::YamlNodeWriter& vectorWriter, Production* p)\n\t\t{ p->save(vectorWriter.write()); });\n\tif (_retaliationTarget)\n\t\twriter.write(\"retaliationTarget\", _retaliationTarget);\n\tif (_retaliationMission)\n\t\twriter.write(\"retaliationMissionUniqueId\", _retaliationMission->getId());\n\tif (_fakeUnderwater)\n\t\twriter.write(\"fakeUnderwater\", _fakeUnderwater);\n}\n\n/**\n * Returns the base's unique type used for\n * savegame purposes.\n * @return ID.\n */\nstd::string Base::getType() const\n{\n\treturn \"STR_BASE\";\n}\n\n/**\n * Returns the custom name for the base.\n * @param lang Language to get strings from (unused).\n * @return Name.\n */\nstd::string Base::getName(Language *) const\n{\n\treturn _name;\n}\n\n/**\n * Returns the globe marker for the base.\n * @return Marker sprite, -1 if none.\n */\nint Base::getMarker() const\n{\n\t// Cheap hack to hide bases when they haven't been placed yet\n\tif (AreSame(_lon, 0.0) && AreSame(_lat, 0.0))\n\t\treturn -1;\n\treturn 0;\n}\n\n/**\n * Returns the list of facilities in the base.\n * @return Pointer to the facility list.\n */\nstd::vector<BaseFacility*> *Base::getFacilities()\n{\n\treturn &_facilities;\n}\n\n/**\n * Returns the list of soldiers in the base.\n * @return Pointer to the soldier list.\n */\nstd::vector<Soldier*> *Base::getSoldiers()\n{\n\treturn &_soldiers;\n}\n\n/**\n * Pre-calculates soldier stats with various bonuses.\n */\nvoid Base::prepareSoldierStatsWithBonuses()\n{\n\tfor (auto* soldier : _soldiers)\n\t{\n\t\tsoldier->prepareStatsWithBonuses(_mod);\n\t}\n}\n\n/**\n * Returns the amount of scientists currently in the base.\n * @return Number of scientists.\n */\nint Base::getScientists() const\n{\n\treturn _scientists;\n}\n\n/**\n * Changes the amount of scientists currently in the base.\n * @param scientists Number of scientists.\n */\nvoid Base::setScientists(int scientists)\n{\n\t _scientists = scientists;\n}\n\n/**\n * Returns the amount of engineers currently in the base.\n * @return Number of engineers.\n */\nint Base::getEngineers() const\n{\n\treturn _engineers;\n}\n\n/**\n * Changes the amount of engineers currently in the base.\n * @param engineers Number of engineers.\n */\nvoid Base::setEngineers(int engineers)\n{\n\t _engineers = engineers;\n}\n\n/**\n * Returns if a certain target is covered by the base's\n * radar range, taking in account the range and chance.\n * @param target Pointer to target to compare.\n * @param alreadyDedected Was ufo already detected, `true` mean we track it without probability.\n * @return 0 - not detected, 1 - detected by conventional radar, 2 - detected by hyper-wave decoder.\n */\nUfoDetection Base::detect(const Ufo *target, const SavedGame *save, bool alreadyTracked) const\n{\n\tint distance = XcomDistance(getDistance(target));\n\tbool hyperwave = false;\n\tint hyperwave_max_range = 0;\n\tint hyperwave_chance = 0;\n\tint radar_max_range = 0;\n\tint radar_chance = 0;\n\n\tfor (const auto* fac : _facilities)\n\t{\n\t\tif (fac->getBuildTime() != 0)\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\t\tif (fac->getRules()->getRadarRange() >= distance)\n\t\t{\n\t\t\tint radarChance = fac->getRules()->getRadarChance();\n\t\t\tif (fac->getRules()->isHyperwave())\n\t\t\t{\n\t\t\t\tif (radarChance == 100 || RNG::percent(radarChance))\n\t\t\t\t{\n\t\t\t\t\thyperwave = true;\n\t\t\t\t}\n\t\t\t\thyperwave_chance += radarChance;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tradar_chance += radarChance;\n\t\t\t}\n\t\t}\n\t\tif (fac->getRules()->isHyperwave())\n\t\t{\n\t\t\thyperwave_max_range = std::max(hyperwave_max_range, fac->getRules()->getRadarRange());\n\t\t}\n\t\telse\n\t\t{\n\t\t\tradar_max_range = std::max(radar_max_range, fac->getRules()->getRadarRange());\n\t\t}\n\t}\n\n\tint detectionChance = 0;\n\tUfoDetection detectionType = DETECTION_NONE;\n\n\tif (alreadyTracked)\n\t{\n\t\tif (hyperwave || hyperwave_chance > 0)\n\t\t{\n\t\t\tdetectionType = hyperwave ? DETECTION_HYPERWAVE : DETECTION_RADAR;\n\t\t\tdetectionChance = 100;\n\t\t}\n\t\telse if (radar_chance > 0)\n\t\t{\n\t\t\tdetectionType = DETECTION_RADAR;\n\t\t\tdetectionChance = 100;\n\t\t}\n\t}\n\telse\n\t{\n\t\tif (hyperwave)\n\t\t{\n\t\t\tdetectionType = DETECTION_HYPERWAVE;\n\t\t\tdetectionChance = 100;\n\t\t}\n\t\telse if (radar_chance > 0)\n\t\t{\n\t\t\tdetectionType = DETECTION_RADAR;\n\t\t\tdetectionChance = radar_chance * (100 + target->getVisibility()) / 100;\n\t\t}\n\t}\n\n\tModScript::DetectUfoFromBase::Output args { detectionType, detectionChance, };\n\tModScript::DetectUfoFromBase::Worker work { target, save, distance, alreadyTracked, radar_chance, radar_max_range, hyperwave_chance, hyperwave_max_range, };\n\n\twork.execute(target->getRules()->getScript<ModScript::DetectUfoFromBase>(), args);\n\n\treturn RNG::percent(args.getSecond()) ? (UfoDetection)args.getFirst() : DETECTION_NONE;\n}\n\n/**\n * Returns the amount of soldiers contained\n * in the base without any assignments.\n * @param checkCombatReadiness does what it says on the tin.\n * @param includeWounded even wounded soldiers can fight in the base defense, if they have enough HP (user option).\n * @return Number of soldiers.\n */\nint Base::getAvailableSoldiers(bool checkCombatReadiness, bool includeWounded) const\n{\n\tint total = 0;\n\tfor (const auto* soldier : _soldiers)\n\t{\n\t\tif (!checkCombatReadiness && soldier->getCraft() == 0)\n\t\t{\n\t\t\ttotal++;\n\t\t}\n\t\telse if (checkCombatReadiness && ((soldier->getCraft() != 0 && soldier->getCraft()->getStatus() != \"STR_OUT\") ||\n\t\t\t(soldier->getCraft() == 0 && (soldier->hasFullHealth() || (includeWounded && soldier->canDefendBase())))))\n\t\t{\n\t\t\ttotal++;\n\t\t}\n\t}\n\treturn total;\n}\n\n/**\n * Returns the total amount of soldiers contained\n * in the base.\n * @return Number of soldiers.\n */\nint Base::getTotalSoldiers() const\n{\n\tsize_t total = _soldiers.size();\n\tfor (const auto* transfer : _transfers)\n\t{\n\t\tif (transfer->getType() == TRANSFER_SOLDIER)\n\t\t{\n\t\t\ttotal += transfer->getQuantity();\n\t\t}\n\t}\n\treturn total;\n}\n\n/**\n * Returns the amount of scientists contained\n * in the base without any assignments.\n * @return Number of scientists.\n */\nint Base::getAvailableScientists() const\n{\n\treturn getScientists();\n}\n\n/**\n * Returns the total amount of scientists contained\n * in the base.\n * @return Number of scientists.\n */\nint Base::getTotalScientists() const\n{\n\tint total = _scientists;\n\tfor (const auto* transfer : _transfers)\n\t{\n\t\tif (transfer->getType() == TRANSFER_SCIENTIST)\n\t\t{\n\t\t\ttotal += transfer->getQuantity();\n\t\t}\n\t}\n\tfor (const auto* proj : _research)\n\t{\n\t\ttotal += proj->getAssigned();\n\t}\n\treturn total;\n}\n\n/**\n * Returns the amount of engineers contained\n * in the base without any assignments.\n * @return Number of engineers.\n */\nint Base::getAvailableEngineers() const\n{\n\treturn getEngineers();\n}\n\n/**\n * Returns the total amount of engineers contained\n * in the base.\n * @return Number of engineers.\n */\nint Base::getTotalEngineers() const\n{\n\tint total = _engineers;\n\tfor (const auto* transfer : _transfers)\n\t{\n\t\tif (transfer->getType() == TRANSFER_ENGINEER)\n\t\t{\n\t\t\ttotal += transfer->getQuantity();\n\t\t}\n\t}\n\tfor (const auto* prod : _productions)\n\t{\n\t\ttotal += prod->getAssignedEngineers();\n\t}\n\treturn total;\n}\n\n/**\n * Returns the total cost of other staff & inventory contained in the base.\n * @return Total cost.\n */\nint Base::getTotalOtherStaffAndInventoryCost(int& staffCount, int& inventoryCount) const\n{\n\tstaffCount = 0;\n\tinventoryCount = 0;\n\tint totalCost = 0;\n\n\tfor (auto* transfer : _transfers)\n\t{\n\t\tif (transfer->getType() == TRANSFER_ITEM)\n\t\t{\n\t\t\tconst auto* ruleItem = transfer->getItems();\n\t\t\tif (ruleItem->getMonthlySalary() != 0)\n\t\t\t{\n\t\t\t\tstaffCount += transfer->getQuantity();\n\t\t\t\ttotalCost += ruleItem->getMonthlySalary() * transfer->getQuantity();\n\t\t\t}\n\t\t\tif (ruleItem->getMonthlyMaintenance() != 0)\n\t\t\t{\n\t\t\t\tinventoryCount += transfer->getQuantity();\n\t\t\t\ttotalCost += ruleItem->getMonthlyMaintenance() * transfer->getQuantity();\n\t\t\t}\n\t\t}\n\t\telse if (transfer->getType() == TRANSFER_SOLDIER)\n\t\t{\n\t\t\tauto* ruleItem = transfer->getSoldier()->getArmor()->getStoreItem();\n\t\t\tif (ruleItem && ruleItem->getMonthlySalary() != 0)\n\t\t\t{\n\t\t\t\tstaffCount += 1;\n\t\t\t\ttotalCost += ruleItem->getMonthlySalary();\n\t\t\t}\n\t\t\tif (ruleItem && ruleItem->getMonthlyMaintenance() != 0)\n\t\t\t{\n\t\t\t\tinventoryCount += 1;\n\t\t\t\ttotalCost += ruleItem->getMonthlyMaintenance();\n\t\t\t}\n\t\t}\n\t}\n\tfor (const auto& storeItem : *_items->getContents())\n\t{\n\t\tauto* ruleItem = storeItem.first;\n\t\tif (ruleItem->getMonthlySalary() != 0)\n\t\t{\n\t\t\tstaffCount += storeItem.second;\n\t\t\ttotalCost += ruleItem->getMonthlySalary() * storeItem.second;\n\t\t}\n\t\tif (ruleItem->getMonthlyMaintenance() != 0)\n\t\t{\n\t\t\tinventoryCount += storeItem.second;\n\t\t\ttotalCost += ruleItem->getMonthlyMaintenance() * storeItem.second;\n\t\t}\n\t}\n\tfor (auto* xcraft : _crafts)\n\t{\n\t\tfor (const auto& craftItem : *xcraft->getItems()->getContents())\n\t\t{\n\t\t\tauto* ruleItem = craftItem.first;\n\t\t\tif (ruleItem->getMonthlySalary() != 0)\n\t\t\t{\n\t\t\t\tstaffCount += craftItem.second;\n\t\t\t\ttotalCost += ruleItem->getMonthlySalary() * craftItem.second;\n\t\t\t}\n\t\t\tif (ruleItem->getMonthlyMaintenance() != 0)\n\t\t\t{\n\t\t\t\tinventoryCount += craftItem.second;\n\t\t\t\ttotalCost += ruleItem->getMonthlyMaintenance() * craftItem.second;\n\t\t\t}\n\t\t}\n\t\tfor (auto* vehicle : *xcraft->getVehicles())\n\t\t{\n\t\t\tauto* ruleItem = vehicle->getRules();\n\t\t\tif (ruleItem->getMonthlySalary() != 0)\n\t\t\t{\n\t\t\t\tstaffCount += 1;\n\t\t\t\ttotalCost += ruleItem->getMonthlySalary();\n\t\t\t}\n\t\t\tif (ruleItem->getMonthlyMaintenance() != 0)\n\t\t\t{\n\t\t\t\tinventoryCount += 1;\n\t\t\t\ttotalCost += ruleItem->getMonthlyMaintenance();\n\t\t\t}\n\t\t}\n\t}\n\tfor (auto* soldier : _soldiers)\n\t{\n\t\tauto* ruleItem = soldier->getArmor()->getStoreItem();\n\t\tif (ruleItem && ruleItem->getMonthlySalary() != 0)\n\t\t{\n\t\t\tstaffCount += 1;\n\t\t\ttotalCost += ruleItem->getMonthlySalary();\n\t\t}\n\t\tif (ruleItem && ruleItem->getMonthlyMaintenance() != 0)\n\t\t{\n\t\t\tinventoryCount += 1;\n\t\t\ttotalCost += ruleItem->getMonthlyMaintenance();\n\t\t}\n\t}\n\n\treturn totalCost;\n}\n\n/**\n * Returns the amount of living quarters used up\n * by personnel in the base.\n * @return Living space.\n */\nint Base::getUsedQuarters() const\n{\n\tint total = getTotalSoldiers() + getTotalScientists() + getTotalEngineers();\n\tfor (const auto* prod : _productions)\n\t{\n\t\tif (prod->getRules()->getSpawnedPersonType() != \"\")\n\t\t{\n\t\t\t// reserve one living space for each production project (even if it's on hold)\n\t\t\ttotal += 1;\n\t\t}\n\t}\n\treturn total;\n}\n\n/**\n * Returns the total amount of living quarters\n * available in the base.\n * @return Living space.\n */\nint Base::getAvailableQuarters() const\n{\n\tint total = 0;\n\tfor (const auto* fac : _facilities)\n\t{\n\t\tif (fac->getBuildTime() == 0)\n\t\t{\n\t\t\ttotal += fac->getRules()->getPersonnel();\n\t\t}\n\t}\n\treturn total;\n}\n\n/**\n * Returns the amount of stores used up by equipment in the base,\n * and equipment about to arrive.\n * @return Storage space.\n */\ndouble Base::getUsedStores(bool excludeNormalItems) const\n{\n\tdouble total = excludeNormalItems ? 0.0 : _items->getTotalSize();\n\tfor (const auto* xcraft : _crafts)\n\t{\n\t\ttotal += xcraft->getTotalItemStorageSize();\n\t}\n\tfor (auto* transfer : _transfers)\n\t{\n\t\tif (transfer->getType() == TRANSFER_ITEM)\n\t\t{\n\t\t\ttotal += transfer->getQuantity() * transfer->getItems()->getSize();\n\t\t}\n\t\telse if (transfer->getType() == TRANSFER_CRAFT)\n\t\t{\n\t\t\ttotal += transfer->getCraft()->getTotalItemStorageSize();\n\t\t}\n\t}\n\treturn total;\n}\n\n/**\n * Checks if the base's stores are overfull.\n *\n * Supplying an offset will add/subtract to the used capacity before performing the check.\n * A positive offset simulates adding items to the stores, whereas a negative offset\n * can be used to check whether sufficient items have been removed to stop the stores overflowing.\n * @param offset Adjusts the used capacity.\n * @return True if the base's stores are over their limit.\n */\nbool Base::storesOverfull(double offset) const\n{\n\tint capacity = getAvailableStores() * 100;\n\tdouble used = (getUsedStores() + offset) * 100;\n\treturn (int)used > capacity;\n}\n\n/**\n * Checks if the base's stores are so full that even craft equipment and incoming transfers can't fit.\n */\nbool Base::storesOverfullCritical() const\n{\n\tint capacity = getAvailableStores() * 100;\n\tdouble total = getUsedStores(true);\n\tint used = total * 100;\n\treturn used > capacity;\n}\n\n/**\n * Returns the total amount of stores\n * available in the base.\n * @return Storage space.\n */\nint Base::getAvailableStores() const\n{\n\tint total = 0;\n\tfor (const auto* fac : _facilities)\n\t{\n\t\tif (fac->getBuildTime() == 0)\n\t\t{\n\t\t\ttotal += fac->getRules()->getStorage();\n\t\t}\n\t}\n\treturn total;\n}\n\n/**\n * Returns the amount of laboratories used up\n * by research projects in the base.\n * @return Laboratory space.\n */\nint Base::getUsedLaboratories() const\n{\n\tint usedLabSpace = 0;\n\tfor (const auto* proj : _research)\n\t{\n\t\tusedLabSpace += proj->getAssigned();\n\t}\n\treturn usedLabSpace;\n}\n\n/**\n * Returns the total amount of laboratories\n * available in the base.\n * @return Laboratory space.\n */\nint Base::getAvailableLaboratories() const\n{\n\tint total = 0;\n\tfor (const auto* fac : _facilities)\n\t{\n\t\tif (fac->getBuildTime() == 0)\n\t\t{\n\t\t\ttotal += fac->getRules()->getLaboratories();\n\t\t}\n\t}\n\treturn total;\n}\n\n/**\n * Returns the amount of workshops used up\n * by manufacturing projects in the base.\n * @return Storage space.\n */\nint Base::getUsedWorkshops() const\n{\n\tint usedWorkShop = 0;\n\tfor (const auto* prod : _productions)\n\t{\n\t\tusedWorkShop += prod->getAssignedEngineers();\n\n\t\t// don't count the workshop space yet if the production is only queued (for future)\n\t\tif (!prod->isQueuedOnly())\n\t\t{\n\t\t\tusedWorkShop += prod->getRules()->getRequiredSpace();\n\t\t}\n\t}\n\treturn usedWorkShop;\n}\n\n/**\n * Returns the total amount of workshops\n * available in the base.\n * @return Workshop space.\n */\nint Base::getAvailableWorkshops() const\n{\n\tint total = 0;\n\tfor (const auto* fac : _facilities)\n\t{\n\t\tif (fac->getBuildTime() == 0)\n\t\t{\n\t\t\ttotal += fac->getRules()->getWorkshops();\n\t\t}\n\t}\n\treturn total;\n}\n\n/**\n * Returns the amount of hangars used up\n * by crafts in the base.\n * @return Number of hangars.\n */\nint Base::getUsedHangars() const\n{\n\tsize_t total = _crafts.size();\n\tfor (const auto* transfer : _transfers)\n\t{\n\t\tif (transfer->getType() == TRANSFER_CRAFT)\n\t\t{\n\t\t\ttotal += transfer->getQuantity();\n\t\t}\n\t}\n\tfor (const auto* prod : _productions)\n\t{\n\t\tif (prod->getRules()->getProducedCraft())\n\t\t{\n\t\t\t// This should be fixed on the case when prod->getInfiniteAmount() == TRUE\n\t\t\ttotal += (prod->getAmountTotal() - prod->getAmountProduced());\n\t\t}\n\t}\n\treturn total;\n}\n\n/**\n * Returns the total amount of hangars\n * available in the base.\n * @return Number of hangars.\n */\nint Base::getAvailableHangars() const\n{\n\tint total = 0;\n\tfor (const auto* fac : _facilities)\n\t{\n\t\tif (fac->getBuildTime() == 0)\n\t\t{\n\t\t\ttotal += fac->getRules()->getCrafts();\n\t\t}\n\t}\n\treturn total;\n}\n\n/**\n * Return laboratories space not used by a ResearchProject\n * @return laboratories space not used by a ResearchProject\n */\nint Base::getFreeLaboratories() const\n{\n\treturn getAvailableLaboratories() - getUsedLaboratories();\n}\n\n/**\n * Return workshop space not used by a Production\n * @return workshop space not used by a Production\n */\nint Base::getFreeWorkshops() const\n{\n\treturn getAvailableWorkshops() - getUsedWorkshops();\n}\n\n/**\n * Return psi lab space not in use\n * @return psi lab space not in use\n */\nint Base::getFreePsiLabs() const\n{\n\treturn getAvailablePsiLabs() - getUsedPsiLabs();\n}\n\n/**\n * Return containment space not in use\n * @return containment space not in use\n */\nint Base::getFreeContainment(int prisonType) const\n{\n\treturn getAvailableContainment(prisonType) - getUsedContainment(prisonType);\n}\n\n/**\n * Returns the amount of scientists currently in use.\n * @return Amount of scientists.\n */\nint Base::getAllocatedScientists() const\n{\n\tint total = 0;\n\tfor (const auto* proj : _research)\n\t{\n\t\ttotal += proj->getAssigned();\n\t}\n\treturn total;\n}\n\n/**\n * Returns the amount of engineers currently in use.\n * @return Amount of engineers.\n */\nint Base::getAllocatedEngineers() const\n{\n\tint total = 0;\n\tfor (const auto* prod : _productions)\n\t{\n\t\ttotal += prod->getAssignedEngineers();\n\t}\n\treturn total;\n}\n\n/**\n * Returns the total defense value of all\n * the facilities in the base.\n * @return Defense value.\n */\nint Base::getDefenseValue() const\n{\n\tint total = 0;\n\tfor (const auto* fac : _facilities)\n\t{\n\t\tif (fac->getBuildTime() == 0)\n\t\t{\n\t\t\ttotal += fac->getRules()->getDefenseValue();\n\t\t}\n\t}\n\treturn total;\n}\n\n/**\n * Returns the total amount of short range\n * detection facilities in the base.\n * @return Defense value.\n */\nint Base::getShortRangeDetection() const\n{\n\tint total = 0;\n\tint minRadarRange = _mod->getShortRadarRange();\n\n\tif (minRadarRange == 0) return 0;\n\tfor (const auto* fac : _facilities)\n\t{\n\t\tif (fac->getRules()->getRadarRange() > 0 && fac->getRules()->getRadarRange() <= minRadarRange && fac->getBuildTime() == 0)\n\t\t{\n\t\t\ttotal++;\n\t\t}\n\t}\n\treturn total;\n}\n\n/**\n * Returns the total amount of long range\n * detection facilities in the base.\n * @return Defense value.\n */\nint Base::getLongRangeDetection() const\n{\n\tint total = 0;\n\tint minRadarRange = _mod->getShortRadarRange();\n\n\tfor (const auto* fac : _facilities)\n\t{\n\t\tif (fac->getRules()->getRadarRange() > minRadarRange && fac->getBuildTime() == 0)\n\t\t{\n\t\t\ttotal++;\n\t\t}\n\t}\n\treturn total;\n}\n\n/**\n * Returns the total amount of craft of\n * a certain type stored in the base.\n * @param craft Craft type.\n * @return Number of craft.\n */\nint Base::getCraftCount(const RuleCraft *craft) const\n{\n\tint total = 0;\n\tfor (auto* transfer : _transfers)\n\t{\n\t\tif (transfer->getType() == TRANSFER_CRAFT && transfer->getCraft()->getRules() == craft)\n\t\t{\n\t\t\ttotal++;\n\t\t}\n\t}\n\tfor (const auto* xcraft : _crafts)\n\t{\n\t\tif (xcraft->getRules() == craft)\n\t\t{\n\t\t\ttotal++;\n\t\t}\n\t}\n\treturn total;\n}\n\n/**\n * Gets the base's crafts of a certain type.\n */\nint Base::getCraftCountForProduction(const RuleCraft *craft) const\n{\n\tint total = 0;\n\tfor (const auto* xcraft : _crafts)\n\t{\n\t\tif (xcraft->getRules() == craft && xcraft->getStatus() != \"STR_OUT\")\n\t\t{\n\t\t\ttotal++;\n\t\t}\n\t}\n\treturn total;\n}\n\n/**\n * Returns the total amount of monthly costs\n * for maintaining the craft in the base.\n * @return Maintenance costs.\n */\nint Base::getCraftMaintenance() const\n{\n\tint total = 0;\n\tfor (auto* transfer : _transfers)\n\t{\n\t\tif (transfer->getType() == TRANSFER_CRAFT)\n\t\t{\n\t\t\ttotal += transfer->getCraft()->getRules()->getRentCost();\n\t\t}\n\t}\n\tfor (const auto* xcraft : _crafts)\n\t{\n\t\ttotal += xcraft->getRules()->getRentCost();\n\t}\n\treturn total;\n}\n\n/**\n * Returns the total count and total salary of soldiers of\n * a certain type stored in the base.\n * @param soldier Soldier type.\n * @return Number of soldiers and their salary.\n */\nstd::pair<int, int> Base::getSoldierCountAndSalary(const std::string &soldier) const\n{\n\tint total = 0;\n\tint totalSalary = 0;\n\tfor (auto* transfer : _transfers)\n\t{\n\t\tif (transfer->getType() == TRANSFER_SOLDIER && transfer->getSoldier()->getRules()->getType() == soldier)\n\t\t{\n\t\t\ttotal++;\n\t\t\ttotalSalary += transfer->getSoldier()->getRules()->getSalaryCost(transfer->getSoldier()->getRank());\n\t\t}\n\t}\n\tfor (const auto* xsoldier : _soldiers)\n\t{\n\t\tif (xsoldier->getRules()->getType() == soldier)\n\t\t{\n\t\t\ttotal++;\n\t\t\ttotalSalary += xsoldier->getRules()->getSalaryCost(xsoldier->getRank());\n\t\t}\n\t}\n\treturn std::make_pair(total, totalSalary);\n}\n\n/**\n * Returns the total amount of monthly costs\n * for maintaining the personnel in the base.\n * @return Maintenance costs.\n */\nint Base::getPersonnelMaintenance() const\n{\n\tint total = 0;\n\tfor (auto* transfer : _transfers)\n\t{\n\t\tif (transfer->getType() == TRANSFER_SOLDIER)\n\t\t{\n\t\t\ttotal += transfer->getSoldier()->getRules()->getSalaryCost(transfer->getSoldier()->getRank());\n\t\t}\n\t}\n\tfor (const auto* soldier : _soldiers)\n\t{\n\t\ttotal += soldier->getRules()->getSalaryCost(soldier->getRank());\n\t}\n\ttotal += getTotalEngineers() * _mod->getEngineerCost();\n\ttotal += getTotalScientists() * _mod->getScientistCost();\n\tint dummy1, dummy2;\n\ttotal += getTotalOtherStaffAndInventoryCost(dummy1, dummy2); // other staff & inventory\n\treturn total;\n}\n\n/**\n * Returns the total amount of monthly costs\n * for maintaining the facilities in the base.\n * @return Maintenance costs.\n */\nint Base::getFacilityMaintenance() const\n{\n\tint total = 0;\n\tfor (const auto* fac : _facilities)\n\t{\n\t\tif (fac->getBuildTime() == 0)\n\t\t{\n\t\t\ttotal += fac->getRules()->getMonthlyCost();\n\t\t}\n\t}\n\treturn total;\n}\n\n/**\n * Returns the total amount of all the maintenance\n * monthly costs in the base.\n * @return Maintenance costs.\n */\nint Base::getMonthlyMaintenace() const\n{\n\treturn getCraftMaintenance() + getPersonnelMaintenance() + getFacilityMaintenance();\n}\n\n/**\n * Returns the list of all base's ResearchProject\n * @return list of base's ResearchProject\n */\nconst std::vector<ResearchProject *> & Base::getResearch() const\n{\n\treturn _research;\n}\n\n/**\n * Add a new Production to the Base\n * @param p A pointer to a Production\n */\nvoid Base::addProduction (Production * p)\n{\n\t_productions.push_back(p);\n}\n\n/**\n * Add A new ResearchProject to Base\n * @param project The project to add\n */\nvoid Base::addResearch(ResearchProject * project)\n{\n\t_research.push_back(project);\n}\n\n/**\n * Remove a ResearchProject from base\n * @param project the project to remove\n */\nvoid Base::removeResearch(ResearchProject * project)\n{\n\t_scientists += project->getAssigned();\n\tconst RuleResearch *ruleResearch = project->getRules();\n\tif (ruleResearch->isHoldingNeededItem())\n\t{\n\t\tif (!project->isFinished())\n\t\t{\n\t\t\t\tgetStorageItems()->addItem(ruleResearch->getNeededItem(), 1);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// handle interrogation\n\t\t\tif (ruleResearch->returnItem())\n\t\t\t{\n\t\t\t\tgetStorageItems()->addItem(ruleResearch->getNeededItem(), 1);\n\t\t\t}\n\t\t\telse if (Options::retainCorpses && ruleResearch->destroyItem())\n\t\t\t{\n\t\t\t\tauto* ruleUnit = _mod->getUnit(ruleResearch->getName(), false); // research & item & unit should have same name to work correctly\n\t\t\t\tif (ruleUnit)\n\t\t\t\t{\n\t\t\t\t\tauto* ruleCorpse = ruleUnit->getArmor()->getCorpseGeoscape();\n\t\t\t\t\tif (ruleCorpse && ruleCorpse->isRecoverable() && ruleCorpse->isCorpseRecoverable())\n\t\t\t\t\t{\n\t\t\t\t\t\tgetStorageItems()->addItem(ruleCorpse);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tCollections::deleteIf(_research, 1,\n\t\t[&](ResearchProject* r)\n\t\t{\n\t\t\treturn r == project;\n\t\t}\n\t);\n}\n\n/**\n * Remove a Production from the Base\n * @param p A pointer to a Production\n */\nvoid Base::removeProduction(Production* production)\n{\n\t_engineers += production->getAssignedEngineers();\n\n\tCollections::deleteIf(_productions, 1,\n\t\t[&](Production* r)\n\t\t{\n\t\t\treturn r == production;\n\t\t}\n\t);\n}\n\n/**\n * Get the list of Base Production's\n * @return the list of Base Production's\n */\nconst std::vector<Production *> & Base::getProductions() const\n{\n\treturn _productions;\n}\n\n/**\n * Returns the total amount of Psi Lab Space\n * available in the base.\n * @return Psi Lab space.\n */\nint Base::getAvailablePsiLabs() const\n{\n\tint total = 0;\n\tfor (const auto* fac : _facilities)\n\t{\n\t\tif (fac->getBuildTime() == 0)\n\t\t{\n\t\t\ttotal += fac->getRules()->getPsiLaboratories();\n\t\t}\n\t}\n\treturn total;\n}\n\n/**\n * Returns the total amount of used\n * Psi Lab Space in the base.\n * @return used Psi Lab space.\n */\nint Base::getUsedPsiLabs() const\n{\n\tint total = 0;\n\tfor (const auto* soldier : _soldiers)\n\t{\n\t\tif (soldier->isInPsiTraining())\n\t\t{\n\t\t\ttotal++;\n\t\t}\n\t}\n\t// Only soldiers returning home after being shot down by a HK can ever be in psi training while in transfer\n\tfor (auto* transfer : _transfers)\n\t{\n\t\tif (transfer->getType() == TRANSFER_SOLDIER)\n\t\t{\n\t\t\tif (transfer->getSoldier()->isInPsiTraining())\n\t\t\t{\n\t\t\t\ttotal++;\n\t\t\t}\n\t\t}\n\t}\n\treturn total;\n}\n\n/**\n * Returns the total amount of training space\n * available in the base.\n * @return Training space.\n */\nint Base::getAvailableTraining() const\n{\n\tint total = 0;\n\tfor (const auto* fac : _facilities)\n\t{\n\t\tif (fac->getBuildTime() == 0)\n\t\t{\n\t\t\ttotal += fac->getRules()->getTrainingFacilities();\n\t\t}\n\t}\n\treturn total;\n}\n\n/**\n * Returns the total amount of used training space\n * available in the base.\n * @return used training space.\n */\nint Base::getUsedTraining() const\n{\n\tint total = 0;\n\tfor (const auto* soldier : _soldiers)\n\t{\n\t\tif (soldier->isInTraining())\n\t\t{\n\t\t\ttotal++;\n\t\t}\n\t}\n\treturn total;\n}\n\n/**\n * Returns training space not in use\n * @return training space not in use\n */\nint Base::getFreeTrainingSpace() const\n{\n\treturn getAvailableTraining() - getUsedTraining();\n}\n\n/**\n * Returns the total amount of used\n * Containment Space in the base.\n * @return Containment Lab space.\n */\nint Base::getUsedContainment(int prisonType, bool onlyExternal) const\n{\n\tint total = 0;\n\tconst RuleItem *rule = 0;\n\tfor (const auto* transfer : _transfers)\n\t{\n\t\tif (transfer->getType() == TRANSFER_ITEM)\n\t\t{\n\t\t\trule = transfer->getItems();\n\t\t\tif (rule->isAlien() && rule->getPrisonType() == prisonType)\n\t\t\t{\n\t\t\t\ttotal += transfer->getQuantity();\n\t\t\t}\n\t\t}\n\t}\n\tfor (const auto* proj : _research)\n\t{\n\t\tconst RuleResearch *projRules = proj->getRules();\n\t\tif (projRules->isHoldingNeededItem())\n\t\t{\n\t\t\trule = projRules->getNeededItem();\n\t\t\tif (rule && rule->isAlien() && rule->getPrisonType() == prisonType)\n\t\t\t{\n\t\t\t\t++total;\n\t\t\t}\n\t\t}\n\t}\n\tif (onlyExternal)\n\t{\n\t\treturn total;\n\t}\n\n\tfor (const auto& pair : *_items->getContents())\n\t{\n\t\trule = pair.first;\n\t\tif (rule->isAlien() && rule->getPrisonType() == prisonType)\n\t\t{\n\t\t\ttotal += pair.second;\n\t\t}\n\t}\n\treturn total;\n}\n\n/**\n * Returns the total amount of Containment Space\n * available in the base.\n * @return Containment Lab space.\n */\nint Base::getAvailableContainment(int prisonType) const\n{\n\tint total = 0;\n\tfor (const auto* fac : _facilities)\n\t{\n\t\tif (fac->getBuildTime() == 0 && fac->getRules()->getPrisonType() == prisonType)\n\t\t{\n\t\t\ttotal += fac->getRules()->getAliens();\n\t\t}\n\t}\n\treturn total;\n}\n\n/**\n * Returns the base's battlescape status.\n * @return Is the craft on the battlescape?\n */\nbool Base::isInBattlescape() const\n{\n\treturn _inBattlescape;\n}\n\n/**\n * Changes the base's battlescape status.\n * @param inbattle True if it's in battle, False otherwise.\n */\nvoid Base::setInBattlescape(bool inbattle)\n{\n\t_inBattlescape = inbattle;\n}\n\n/**\n * Mark the base as a valid alien retaliation target.\n * @param mark Mark (if @c true) or unmark (if @c false) the base.\n */\nvoid Base::setRetaliationTarget(bool mark)\n{\n\t_retaliationTarget = mark;\n}\n\n/**\n * Get the base's retaliation status.\n * @return If the base is a valid target for alien retaliation.\n */\nbool Base::getRetaliationTarget() const\n{\n\treturn _retaliationTarget;\n}\n\n/**\n * Calculate the detection chance of this base.\n * Big bases without mind shields are easier to detect.\n * @param difficulty The savegame difficulty.\n * @return The detection chance.\n */\nsize_t Base::getDetectionChance() const\n{\n\tsize_t mindShields = 0;\n\tsize_t completedFacilities = 0;\n\tfor (const auto* fac : _facilities)\n\t{\n\t\tif (fac->getBuildTime() == 0)\n\t\t{\n\t\t\tcompletedFacilities += fac->getRules()->getSizeX() * fac->getRules()->getSizeY();\n\t\t\tif (fac->getRules()->isMindShield() && !fac->getDisabled())\n\t\t\t{\n\t\t\t\tmindShields += fac->getRules()->getMindShieldPower();\n\t\t\t}\n\t\t}\n\t}\n\treturn ((completedFacilities / 6 + 15) / (mindShields + 1));\n}\n\nint Base::getGravShields() const\n{\n\tint total = 0;\n\tfor (const auto* fac : _facilities)\n\t{\n\t\tif (fac->getBuildTime() == 0 && fac->getRules()->isGravShield())\n\t\t{\n\t\t\t++total;\n\t\t}\n\t}\n\treturn total;\n}\n\nvoid Base::setupDefenses(AlienMission* am)\n{\n\t// Note: OBJECTIVE_INSTANT_RETALIATION is intentionally ignored here\n\tif (am->getRules().getObjective() == OBJECTIVE_RETALIATION)\n\t{\n\t\tsetRetaliationMission(am);\n\t}\n\n\t_defenses.clear();\n\tfor (auto* fac : _facilities)\n\t{\n\t\tif (fac->getBuildTime() == 0 && fac->getRules()->getDefenseValue())\n\t\t{\n\t\t\t_defenses.push_back(fac);\n\t\t}\n\t}\n\n\t_vehicles.clear();\n\tCollections::deleteAll(_vehiclesFromBase);\n\n\t// add vehicles that are in the crafts of the base, if it's not out\n\tfor (auto* xcraft : _crafts)\n\t{\n\t\tif (xcraft->getStatus() != \"STR_OUT\")\n\t\t{\n\t\t\tfor (auto* vehicle : *xcraft->getVehicles())\n\t\t\t{\n\t\t\t\t_vehicles.push_back(vehicle);\n\t\t\t}\n\t\t}\n\t}\n\n\t// add vehicles left on the base\n\tfor (auto iter = _items->getContents()->begin(); iter != _items->getContents()->end(); )\n\t{\n\t\tint itemQty = iter->second;\n\t\tconst RuleItem *rule = iter->first;\n\t\tif (rule->getVehicleUnit())\n\t\t{\n\t\t\tint size = rule->getVehicleUnit()->getArmor()->getTotalSize();\n\t\t\tif (rule->getVehicleClipAmmo() == nullptr) // so this vehicle does not need ammo\n\t\t\t{\n\t\t\t\tfor (int j = 0; j < itemQty; ++j)\n\t\t\t\t{\n\t\t\t\t\tauto* vehicle = new Vehicle(rule, rule->getVehicleClipSize(), size);\n\t\t\t\t\t_vehicles.push_back(vehicle);\n\t\t\t\t\t_vehiclesFromBase.push_back(vehicle);\n\t\t\t\t}\n\t\t\t\t_items->removeItem(rule, itemQty);\n\t\t\t}\n\t\t\telse // so this vehicle needs ammo\n\t\t\t{\n\t\t\t\tconst RuleItem *ammo = rule->getVehicleClipAmmo();\n\t\t\t\tint ammoPerVehicle = rule->getVehicleClipsLoaded();\n\n\t\t\t\tint baseQty = _items->getItem(ammo) / ammoPerVehicle;\n\t\t\t\tif (!baseQty)\n\t\t\t\t{\n\t\t\t\t\t++iter;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tint canBeAdded = std::min(itemQty, baseQty);\n\t\t\t\tfor (int j=0; j<canBeAdded; ++j)\n\t\t\t\t{\n\t\t\t\t\tauto* vehicle = new Vehicle(rule, rule->getVehicleClipSize(), size);\n\t\t\t\t\t_vehicles.push_back(vehicle);\n\t\t\t\t\t_vehiclesFromBase.push_back(vehicle);\n\t\t\t\t\t_items->removeItem(ammo, ammoPerVehicle);\n\t\t\t\t}\n\t\t\t\t_items->removeItem(rule, canBeAdded);\n\t\t\t}\n\n\t\t\titer = _items->getContents()->begin(); // we have to start over because iterator is broken because of the removeItem\n\t\t}\n\t\telse ++iter;\n\t}\n}\n\nstd::vector<BaseFacility*> *Base::getDefenses()\n{\n\treturn &_defenses;\n}\n\n/**\n * Returns the list of vehicles currently equipped\n * in the base.\n * @return Pointer to vehicle list.\n */\nstd::vector<Vehicle*> *Base::getVehicles()\n{\n\treturn &_vehicles;\n}\n\n/**\n * Damage and/or destroy facilities after a missile impact.\n * @param ufo The missile that hit the base.\n */\nvoid Base::damageFacilities(Ufo *ufo)\n{\n\t_destroyedFacilitiesCache.clear();\n\n\tfor (int i = 0; i < ufo->getRules()->getMissilePower();)\n\t{\n\t\tWeightedOptions options;\n\t\tint index = 0;\n\t\tfor (auto* facility : _facilities)\n\t\t{\n\t\t\tif (facility->getRules()->getMissileAttraction() > 0 && !facility->getRules()->isLift())\n\t\t\t{\n\t\t\t\toptions.set(std::to_string(index), facility->getRules()->getMissileAttraction());\n\t\t\t}\n\t\t\t++index;\n\t\t}\n\t\tif (options.empty())\n\t\t{\n\t\t\t// only indestructible stuff remains, stop trying\n\t\t\tbreak;\n\t\t}\n\n\t\tstd::string sel = options.choose();\n\t\tint selected = std::stoi(sel);\n\t\tBaseFacility* toBeDamaged = _facilities[selected];\n\n\t\ti += damageFacility(toBeDamaged);\n\t}\n\n\t// this may cause the base to become disjointed, destroy the disconnected parts\n\tif (!_mod->getDestroyedFacility())\n\t{\n\t\tdestroyDisconnectedFacilities();\n\t}\n}\n\n/**\n * Damage a given facility.\n * @param toBeDamaged The facility to be damaged.\n * @return Missile power spent on this facility.\n */\nint Base::damageFacility(BaseFacility *toBeDamaged)\n{\n\tint result = 0;\n\n\t// 1. Create the new \"damaged facility\" first, so that when we destroy the original facility we don't lose \"too much\"\n\tif (toBeDamaged->getRules()->getDestroyedFacility())\n\t{\n\t\tBaseFacility *fac = new BaseFacility(toBeDamaged->getRules()->getDestroyedFacility(), this);\n\t\tfac->setX(toBeDamaged->getX());\n\t\tfac->setY(toBeDamaged->getY());\n\t\tfac->setBuildTime(0);\n\t\t_facilities.push_back(fac);\n\n\t\t// move the craft from the original hangar to the damaged hangar\n\t\tif (fac->getRules()->getCrafts() > 0)\n\t\t{\n\t\t\tfac->setCraftForDrawing(toBeDamaged->getCraftForDrawing());\n\t\t\ttoBeDamaged->setCraftForDrawing(0);\n\t\t}\n\t}\n\telse if (_mod->getDestroyedFacility())\n\t{\n\t\tfor (int x = 0; x < toBeDamaged->getRules()->getSizeX(); ++x)\n\t\t{\n\t\t\tfor (int y = 0; y < toBeDamaged->getRules()->getSizeY(); ++y)\n\t\t\t{\n\t\t\t\tBaseFacility *fac = new BaseFacility(_mod->getDestroyedFacility(), this);\n\t\t\t\tfac->setX(toBeDamaged->getX() + x);\n\t\t\t\tfac->setY(toBeDamaged->getY() + y);\n\t\t\t\tfac->setBuildTime(0);\n\t\t\t\t_facilities.push_back(fac);\n\t\t\t}\n\t\t}\n\t}\n\n\t// 2. Now destroy the original\n\tfor (auto iter = _facilities.begin(); iter != _facilities.end(); ++iter)\n\t{\n\t\tif ((*iter) == toBeDamaged)\n\t\t{\n\t\t\t// bigger facilities spend more missile power\n\t\t\tresult = toBeDamaged->getRules()->getSizeX() * toBeDamaged->getRules()->getSizeY();\n\t\t\tdestroyFacility(iter);\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn result;\n}\n\n/**\n * Destroys all disconnected facilities in the base.\n */\nvoid Base::destroyDisconnectedFacilities()\n{\n\tauto disFacs = getDisconnectedFacilities(0);\n\tfor (std::list<BASEFACILITIESITERATOR>::reverse_iterator outerIterator = disFacs.rbegin(); outerIterator != disFacs.rend(); ++outerIterator)\n\t{\n\t\tdestroyFacility(*outerIterator);\n\t}\n}\n\n/**\n * Gets a sorted list of the facilities(=iterators) NOT connected to the Access Lift.\n * @param remove Facility to ignore (in case of facility dismantling).\n * @return a sorted list of iterators pointing to elements in _facilities.\n */\nstd::list<BASEFACILITIESITERATOR> Base::getDisconnectedFacilities(BaseFacility *remove)\n{\n\tstd::list<BASEFACILITIESITERATOR> result;\n\n\tif (remove != 0 && remove->getRules()->isLift())\n\t{ // Theoretically this is impossible, but sanity check is good :)\n\t\tfor (BASEFACILITIESITERATOR iter = _facilities.begin(); iter != _facilities.end(); ++iter)\n\t\t{\n\t\t\tif ((*iter) != remove) result.push_back(iter);\n\t\t}\n\t\treturn result;\n\t}\n\n\tstd::vector< std::pair<BASEFACILITIESITERATOR, bool>* > facilitiesConnStates;\n\tstd::pair<BASEFACILITIESITERATOR, bool> *grid[BASE_SIZE][BASE_SIZE];\n\tBaseFacility *lift = 0;\n\n\tfor (int x = 0; x < BASE_SIZE; ++x)\n\t{\n\t\tfor (int y = 0; y < BASE_SIZE; ++y)\n\t\t{\n\t\t\tgrid[x][y] = 0;\n\t\t}\n\t}\n\n\t// Ok, fill up the grid(+facilitiesConnStates), and search the lift\n\tfor (BASEFACILITIESITERATOR iter = _facilities.begin(); iter != _facilities.end(); ++iter)\n\t{\n\t\tBaseFacility* fac = (*iter);\n\t\tif (fac != remove)\n\t\t{\n\t\t\tif (fac->getRules()->isLift()) lift = fac;\n\t\t\tfor (int x = 0; x != fac->getRules()->getSizeX(); ++x)\n\t\t\t{\n\t\t\t\tfor (int y = 0; y != fac->getRules()->getSizeY(); ++y)\n\t\t\t\t{\n\t\t\t\t\tstd::pair<BASEFACILITIESITERATOR, bool> *p = new std::pair<BASEFACILITIESITERATOR, bool>(iter,false);\n\t\t\t\t\tfacilitiesConnStates.push_back(p);\n\t\t\t\t\tgrid[fac->getX() + x][fac->getY() + y] = p;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// we're in real trouble if this happens...\n\tif (lift == 0)\n\t{\n\t\t//TODO: something clever.\n\t\treturn result;\n\t}\n\n\t// Now make the recursion manually using a stack\n\tstd::stack<std::pair<int, int> > stack;\n\tstack.push(std::make_pair(lift->getX(),lift->getY()));\n\twhile (!stack.empty())\n\t{\n\t\tint x = stack.top().first, y = stack.top().second;\n\t\tstack.pop();\n\t\tif (x >= 0 && x < BASE_SIZE && y >= 0 && y < BASE_SIZE && grid[x][y] != 0 && !grid[x][y]->second)\n\t\t{\n\t\t\tgrid[x][y]->second = true;\n\t\t\tBaseFacility *fac = *(grid[x][y]->first);\n\t\t\tBaseFacility *neighborLeft = (x-1 >= 0 && grid[x-1][y] != 0) ? *(grid[x-1][y]->first) : 0;\n\t\t\tBaseFacility *neighborRight = (x+1 < BASE_SIZE && grid[x+1][y] != 0) ? *(grid[x+1][y]->first) : 0;\n\t\t\tBaseFacility *neighborTop = (y-1 >= 0 && grid[x][y-1] != 0) ? *(grid[x][y-1]->first) : 0;\n\t\t\tBaseFacility *neighborBottom= (y+1 < BASE_SIZE && grid[x][y+1] != 0) ? *(grid[x][y+1]->first) : 0;\n\t\t\tif (fac->isBuiltOrHadPreviousFacility() || (neighborLeft != 0 && (neighborLeft == fac || neighborLeft->getBuildTime() > neighborLeft->getRules()->getBuildTime()))) stack.push(std::make_pair(x-1,y));\n\t\t\tif (fac->isBuiltOrHadPreviousFacility() || (neighborRight != 0 && (neighborRight == fac || neighborRight->getBuildTime() > neighborRight->getRules()->getBuildTime()))) stack.push(std::make_pair(x+1,y));\n\t\t\tif (fac->isBuiltOrHadPreviousFacility() || (neighborTop != 0 && (neighborTop == fac || neighborTop->getBuildTime() > neighborTop->getRules()->getBuildTime()))) stack.push(std::make_pair(x,y-1));\n\t\t\tif (fac->isBuiltOrHadPreviousFacility() || (neighborBottom != 0 && (neighborBottom == fac || neighborBottom->getBuildTime() > neighborBottom->getRules()->getBuildTime()))) stack.push(std::make_pair(x,y+1));\n\t\t}\n\t}\n\n\tBaseFacility *lastFacility = 0;\n\tfor (auto*& pair : facilitiesConnStates)\n\t{\n\t\t// Not a connected facility? -> push its iterator into the list!\n\t\t// Oh, and we don't want duplicates (facilities with bigger sizes like hangar)\n\t\tif (*(pair->first) != lastFacility && !pair->second) result.push_back(pair->first);\n\t\tlastFacility = *(pair->first);\n\t\tdelete pair; // We don't need the pair anymore.\n\t}\n\n\treturn result;\n}\n\n/**\n * Removes a base module, and deals with the ramifications thereof.\n * @param facility An iterator reference to the facility to destroy and remove.\n */\nvoid Base::destroyFacility(BASEFACILITIESITERATOR facility)\n{\n\tif ((*facility)->getRules()->getCrafts() > 0)\n\t{\n\t\t// hangar destruction - destroy crafts and any production of crafts\n\t\t// if this will mean there is no hangar to contain it\n\t\tif ((*facility)->getCraftForDrawing())\n\t\t{\n\t\t\t// remove all soldiers\n\t\t\tfor (Soldier *s : _soldiers)\n\t\t\t{\n\t\t\t\tif (s->getCraft() == (*facility)->getCraftForDrawing())\n\t\t\t\t{\n\t\t\t\t\ts->setCraft(0);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// remove all items\n\t\t\twhile (!(*facility)->getCraftForDrawing()->getItems()->getContents()->empty())\n\t\t\t{\n\t\t\t\tauto i = (*facility)->getCraftForDrawing()->getItems()->getContents()->begin();\n\t\t\t\t_items->addItem(i->first, i->second);\n\t\t\t\t(*facility)->getCraftForDrawing()->getItems()->removeItem(i->first, i->second);\n\t\t\t}\n\t\t\tCollections::deleteIf(_crafts, 1,\n\t\t\t\t[&](Craft* c)\n\t\t\t\t{\n\t\t\t\t\treturn c == (*facility)->getCraftForDrawing();\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tint remove = -(getAvailableHangars() - getUsedHangars() - (*facility)->getRules()->getCrafts());\n\t\t\tremove = Collections::deleteIf(_productions, remove,\n\t\t\t\t[&](Production* i)\n\t\t\t\t{\n\t\t\t\t\tif (i->getRules()->getProducedCraft())\n\t\t\t\t\t{\n\t\t\t\t\t\t_engineers += i->getAssignedEngineers();\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t);\n\t\t\tremove = Collections::deleteIf(_transfers, remove,\n\t\t\t\t[&](Transfer* i)\n\t\t\t\t{\n\t\t\t\t\treturn i->getType() == TRANSFER_CRAFT;\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t}\n\tif ((*facility)->getRules()->getPsiLaboratories() > 0)\n\t{\n\t\t// psi lab destruction: remove any soldiers over the maximum allowable from psi training.\n\t\tint toRemove = (*facility)->getRules()->getPsiLaboratories() - getFreePsiLabs();\n\t\tfor (auto* soldier : _soldiers)\n\t\t{\n\t\t\tif (toRemove <= 0) break; // loop finished\n\t\t\tif (soldier->isInPsiTraining())\n\t\t\t{\n\t\t\t\tsoldier->setPsiTraining(false);\n\t\t\t\t--toRemove;\n\t\t\t}\n\t\t}\n\t}\n\tif ((*facility)->getRules()->getTrainingFacilities() > 0)\n\t{\n\t\t// gym destruction: remove any soldiers over the maximum allowable from martial training.\n\t\tint toRemove = (*facility)->getRules()->getTrainingFacilities() - getFreeTrainingSpace();\n\t\tfor (auto* soldier : _soldiers)\n\t\t{\n\t\t\tif (toRemove <= 0) break; // loop finished\n\t\t\tif (soldier->isInTraining())\n\t\t\t{\n\t\t\t\tsoldier->setTraining(false);\n\t\t\t\t--toRemove;\n\t\t\t}\n\t\t}\n\t}\n\tif ((*facility)->getRules()->getLaboratories())\n\t{\n\t\t// lab destruction: enforce lab space limits. take scientists off projects until\n\t\t// it all evens out. research is not cancelled.\n\t\tint toRemove = (*facility)->getRules()->getLaboratories() - getFreeLaboratories();\n\t\tfor (auto iter = _research.begin(); iter != _research.end() && toRemove > 0;)\n\t\t{\n\t\t\tResearchProject* proj = (*iter);\n\t\t\tif (proj->getAssigned() >= toRemove)\n\t\t\t{\n\t\t\t\tproj->setAssigned(proj->getAssigned() - toRemove);\n\t\t\t\t_scientists += toRemove;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\ttoRemove -= proj->getAssigned();\n\t\t\t\t_scientists += proj->getAssigned();\n\t\t\t\tproj->setAssigned(0);\n\t\t\t\t++iter;\n\t\t\t}\n\t\t}\n\t}\n\tif ((*facility)->getRules()->getWorkshops())\n\t{\n\t\t// workshop destruction: similar to lab destruction, but we'll lay off engineers instead\n\t\t// in this case, however, production IS cancelled, as it takes up space in the workshop.\n\t\tint toRemove = (*facility)->getRules()->getWorkshops() - getFreeWorkshops();\n\t\tCollections::deleteIf(_productions, _productions.size(),\n\t\t\t[&](Production* p)\n\t\t\t{\n\t\t\t\tif (toRemove <= 0)\n\t\t\t\t{\n\t\t\t\t\t// skip rest\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\telse if (p->getAssignedEngineers() > toRemove)\n\t\t\t\t{\n\t\t\t\t\tp->setAssignedEngineers(p->getAssignedEngineers() - toRemove);\n\t\t\t\t\t_engineers += toRemove;\n\t\t\t\t\ttoRemove = 0;\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t_engineers += p->getAssignedEngineers();\n\t\t\t\t\ttoRemove -= p->getAssignedEngineers();\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\t}\n\tif ((*facility)->getRules()->getStorage())\n\t{\n\t\t// we won't destroy the items physically AT the base,\n\t\t// but any items in transit will end up at the dead letter office.\n\t\tif (storesOverfull((*facility)->getRules()->getStorage()))\n\t\t{\n\t\t\tCollections::deleteIf(_transfers, _transfers.size(),\n\t\t\t\t[&](Transfer* i)\n\t\t\t\t{\n\t\t\t\t\tif (i->getType() == TRANSFER_ITEM)\n\t\t\t\t\t{\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t}\n\tif ((*facility)->getRules()->getPersonnel())\n\t{\n\t\t// as above, we won't actually fire people, but we'll block any new ones coming in.\n\t\tif ((getAvailableQuarters() - getUsedQuarters()) - (*facility)->getRules()->getPersonnel() < 0)\n\t\t{\n\t\t\tCollections::deleteIf(_transfers, _transfers.size(),\n\t\t\t\t[&](Transfer* i)\n\t\t\t\t{\n\t\t\t\t\tif (i->getType() == TRANSFER_ENGINEER || i->getType() == TRANSFER_SCIENTIST)\n\t\t\t\t\t{\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t}\n\n\t_destroyedFacilitiesCache[(*facility)->getRules()] += 1;\n\tdelete *facility;\n\t_facilities.erase(facility);\n}\n\n/**\n * Cancels all prisoner interrogations. Cancels all incoming prisoner transfers.\n */\nvoid Base::cleanupPrisons(int prisonType)\n{\n\t// cancel all interrogations\n\tCollections::deleteIf(_research, _research.size(),\n\t\t[&](ResearchProject* project)\n\t\t{\n\t\t\tconst RuleResearch* projRules = project->getRules();\n\t\t\tif (projRules->isHoldingNeededItem())\n\t\t\t{\n\t\t\t\tconst RuleItem* rule = projRules->getNeededItem();\n\t\t\t\tif (rule && rule->isAlien() && rule->getPrisonType() == prisonType)\n\t\t\t\t{\n\t\t\t\t\t_scientists += project->getAssigned();\n\t\t\t\t\tproject->setAssigned(0);\n\t\t\t\t\tgetStorageItems()->addItem(rule, 1);\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\t);\n\n\t// act as if all incoming prisoners arrived already, let player decide what to do with them\n\tCollections::deleteIf(_transfers, _transfers.size(),\n\t\t[&](Transfer* transfer)\n\t\t{\n\t\t\tif (transfer->getType() == TRANSFER_ITEM)\n\t\t\t{\n\t\t\t\tconst auto* rule = transfer->getItems();\n\t\t\t\tif (rule->isAlien() && rule->getPrisonType() == prisonType)\n\t\t\t\t{\n\t\t\t\t\tgetStorageItems()->addItem(rule, transfer->getQuantity());\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\t);\n}\n\n/**\n * Cleans up the defenses vector and optionally reclaims the tanks and their ammo.\n * @param reclaimItems determines whether the HWPs should be returned to storage.\n */\nvoid Base::cleanupDefenses(bool reclaimItems)\n{\n\tCollections::removeAll(_defenses);\n\n\tif (reclaimItems)\n\t{\n\t\tfor (auto* vehicle : _vehiclesFromBase)\n\t\t{\n\t\t\tconst RuleItem *rule = vehicle->getRules();\n\t\t\t_items->addItem(rule);\n\t\t\tif (rule->getVehicleClipAmmo())\n\t\t\t{\n\t\t\t\t_items->addItem(rule->getVehicleClipAmmo(), rule->getVehicleClipsLoaded());\n\t\t\t}\n\t\t}\n\t}\n\n\tCollections::removeAll(_vehicles);\n\tCollections::deleteAll(_vehiclesFromBase);\n}\n\n/**\n * Check if any facilities in a given area are used.\n */\nBasePlacementErrors Base::isAreaInUse(BaseAreaSubset area, const RuleBaseFacility* replacement) const\n{\n\tstruct Av\n\t{\n\t\tint quarters = 0;\n\t\tint stores = 0;\n\t\tint laboratories = 0;\n\t\tint workshops = 0;\n\t\tint hangars = 0;\n\t\tint psiLaboratories = 0;\n\t\tint training = 0;\n\n\t\tvoid add(const RuleBaseFacility* rule)\n\t\t{\n\t\t\tstores += rule->getStorage();\n\t\t\taddWithoutStores(rule);\n\t\t}\n\t\tvoid addWithoutStores(const RuleBaseFacility* rule)\n\t\t{\n\t\t\tquarters += rule->getPersonnel();\n\t\t\tlaboratories += rule->getLaboratories();\n\t\t\tworkshops += rule->getWorkshops();\n\t\t\thangars += rule->getCrafts();\n\t\t\tpsiLaboratories += rule->getPsiLaboratories();\n\t\t\ttraining += rule->getTrainingFacilities();\n\t\t}\n\t};\n\n\tAv available;\n\tAv removed;\n\tRuleBaseFacilityFunctions provide = _provideBaseFunc;\n\tRuleBaseFacilityFunctions require;\n\tRuleBaseFacilityFunctions forbidden = _forbiddenBaseFunc;\n\tRuleBaseFacilityFunctions future = _provideBaseFunc;\n\tRuleBaseFacilityFunctions missed;\n\n\tint removedBuildings = 0;\n\tint removedPrisonType[9] = { };\n\tconst auto prisonBegin = std::begin(removedPrisonType);\n\tconst auto prisonEnd = std::end(removedPrisonType);\n\tauto prisonCurr = prisonBegin;\n\n\tfor (const auto* bf : _facilities)\n\t{\n\t\tauto* rule = bf->getRules();\n\t\tif (BaseAreaSubset::intersection(bf->getPlacement(), area))\n\t\t{\n\t\t\t++removedBuildings;\n\n\t\t\t// removed one, check what we lose\n\t\t\tremoved.add(rule);\n\t\t\tmissed |= rule->getProvidedBaseFunc();\n\n\t\t\tif (rule->getAliens() > 0)\n\t\t\t{\n\t\t\t\tint type = rule->getPrisonType();\n\t\t\t\tif (std::find(prisonBegin, prisonCurr, type) == prisonCurr)\n\t\t\t\t{\n\t\t\t\t\t//too many prison types, give up\n\t\t\t\t\tif (prisonCurr == prisonEnd)\n\t\t\t\t\t{\n\t\t\t\t\t\treturn BPE_Used_AlienContainment;\n\t\t\t\t\t}\n\t\t\t\t\t*prisonCurr = type;\n\t\t\t\t\t++prisonCurr;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// if we build over a lift better if the new one is a lift too, right now it is a bit buggy and the game can crash if two lifts are defined but in the future it can be useful.\n\t\t\tif (replacement && rule->isLift() && !replacement->isLift())\n\t\t\t{\n\t\t\t\treturn BPE_Used;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// sum all old one, not removed\n\t\t\trequire |= rule->getRequireBaseFunc();\n\t\t\tforbidden |= rule->getForbiddenBaseFunc();\n\t\t\tfuture |= rule->getProvidedBaseFunc();\n\t\t\tif (bf->getBuildTime() == 0)\n\t\t\t{\n\t\t\t\tavailable.add(rule);\n\t\t\t\tprovide |= rule->getProvidedBaseFunc();\n\t\t\t}\n\t\t\telse if (bf->getIfHadPreviousFacility())\n\t\t\t{\n\t\t\t\tif (Options::storageLimitsEnforced)\n\t\t\t\t{\n\t\t\t\t\t// with enforced limits we can't allow upgrades that make (temporarily) insufficient storage in a base\n\t\t\t\t\tavailable.addWithoutStores(rule);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tavailable.add(rule);\n\t\t\t\t}\n\n\t\t\t\t// do not give any `provide`, you need to wait until it finishes upgrading\n\t\t\t}\n\t\t}\n\n\t}\n\n\t// sum new one too.\n\tif (replacement)\n\t{\n\t\tif (Options::storageLimitsEnforced)\n\t\t{\n\t\t\t// with enforced limits we can't allow upgrades that make (temporarily) insufficient storage in a base\n\t\t\tavailable.addWithoutStores(replacement);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tavailable.add(replacement);\n\t\t}\n\n\t\t// temporarily allow `provide` from a new building\n\t\tprovide |= replacement->getProvidedBaseFunc();\n\t\trequire |= replacement->getRequireBaseFunc();\n\n\t\t// there is still some other bulding that prevents placing the new one\n\t\tif ((forbidden & replacement->getProvidedBaseFunc()).any())\n\t\t{\n\t\t\treturn BPE_ForbiddenByOther;\n\t\t}\n\n\t\t// check if there are any other buildings that are forbidden by this one\n\t\tif ((future & replacement->getForbiddenBaseFunc()).any())\n\t\t{\n\t\t\treturn BPE_ForbiddenByThis;\n\t\t}\n\t}\n\n\t// if there is any required function that we do not have then it means we are trying to remove something still needed.\n\t// in case when building was destroyed by aliens attack we can lack some functions,\n\t// if we do not remove anything now then we can add new building even if we lack some functions.\n\tif ((~provide & require & missed).any())\n\t{\n\t\treturn BPE_Used;\n\t}\n\n\t// nothing removed, skip.\n\tif (removedBuildings == 0)\n\t{\n\t\treturn BPE_None;\n\t}\n\n\tif (prisonBegin != prisonCurr)\n\t{\n\t\tint availablePrisonTypes[std::size(removedPrisonType)] = { };\n\n\t\tauto sumAvailablePrisons = [&](const RuleBaseFacility* rule)\n\t\t{\n\t\t\tint prisonSize = rule->getAliens();\n\t\t\tif (prisonSize > 0)\n\t\t\t{\n\t\t\t\tint type = rule->getPrisonType();\n\t\t\t\tauto find = std::find(prisonBegin, prisonCurr, type);\n\t\t\t\tif (find != prisonCurr)\n\t\t\t\t{\n\t\t\t\t\tavailablePrisonTypes[find - prisonBegin] += prisonSize;\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\t// sum all available space\n\t\tfor (const auto* bf : _facilities)\n\t\t{\n\t\t\tauto* rule = bf->getRules();\n\t\t\tif (!BaseAreaSubset::intersection(bf->getPlacement(), area))\n\t\t\t{\n\t\t\t\tsumAvailablePrisons(rule);\n\t\t\t}\n\t\t}\n\n\t\t// sum new space too\n\t\tif (replacement)\n\t\t{\n\t\t\t// same as like with storage, only when limits are not enforced you can upgrade full prison\n\t\t\tif (!Options::storageLimitsEnforced)\n\t\t\t{\n\t\t\t\tsumAvailablePrisons(replacement);\n\t\t\t}\n\t\t}\n\n\t\t// check if usage fits space\n\t\tfor (std::pair<int, int> typeSize : Collections::zip(Collections::range(prisonBegin, prisonCurr), Collections::range(availablePrisonTypes)))\n\t\t{\n\t\t\tif (typeSize.second < getUsedContainment(typeSize.first))\n\t\t\t{\n\t\t\t\treturn BPE_Used_AlienContainment;\n\t\t\t}\n\t\t}\n\t}\n\n\t// only check space for things that are removed\n\tif (removed.stores > 0 && available.stores < getUsedStores())\n\t{\n\t\treturn BPE_Used_Stores;\n\t}\n\telse if (removed.quarters > 0 && available.quarters < getUsedQuarters())\n\t{\n\t\treturn BPE_Used_Quarters;\n\t}\n\telse if (removed.laboratories > 0 && available.laboratories < getUsedLaboratories())\n\t{\n\t\treturn BPE_Used_Laboratories;\n\t}\n\telse if (removed.workshops > 0 && available.workshops < getUsedWorkshops())\n\t{\n\t\treturn BPE_Used_Workshops;\n\t}\n\telse if (removed.hangars > 0 && available.hangars < getUsedHangars())\n\t{\n\t\treturn BPE_Used_Hangars;\n\t}\n\telse if (removed.psiLaboratories > 0 && available.psiLaboratories < getUsedPsiLabs())\n\t{\n\t\treturn BPE_Used_PsiLabs;\n\t}\n\telse if (removed.training > 0 && available.training < getUsedTraining())\n\t{\n\t\treturn BPE_Used_Gyms;\n\t}\n\n\treturn BPE_None;\n}\n\n/**\n * Return list of all provided functionality in base.\n * @param skip Skip functions provide by this facility.\n * @return List of custom IDs.\n */\nRuleBaseFacilityFunctions Base::getProvidedBaseFunc(BaseAreaSubset skip) const\n{\n\tRuleBaseFacilityFunctions ret = 0;\n\n\tfor (const auto* bf : _facilities)\n\t{\n\t\tif (BaseAreaSubset::intersection(bf->getPlacement(), skip))\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\t\tif (bf->getBuildTime() > 0)\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\t\tret |= bf->getRules()->getProvidedBaseFunc();\n\t}\n\n\tret |= _provideBaseFunc;\n\n\treturn ret;\n}\n\n/**\n * Return list of all required functionality in base.\n * @param skip Skip functions require by this facility.\n * @return List of custom IDs.\n */\nRuleBaseFacilityFunctions Base::getRequireBaseFunc(BaseAreaSubset skip) const\n{\n\tRuleBaseFacilityFunctions ret = 0;\n\n\tfor (const auto* bf : _facilities)\n\t{\n\t\tif (BaseAreaSubset::intersection(bf->getPlacement(), skip))\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\t\tret |= bf->getRules()->getRequireBaseFunc();\n\t}\n\n\tfor (const auto* proj : _research)\n\t{\n\t\tret |= proj->getRules()->getRequireBaseFunc();\n\t}\n\n\tfor (const auto* prod : _productions)\n\t{\n\t\tret |= prod->getRules()->getRequireBaseFunc();\n\t}\n\n\treturn ret;\n}\n\n/**\n * Return list of all forbidden functionality in base.\n * @return List of custom IDs.\n */\nRuleBaseFacilityFunctions Base::getForbiddenBaseFunc(BaseAreaSubset skip) const\n{\n\tRuleBaseFacilityFunctions ret = 0;\n\n\tfor (const auto* bf : _facilities)\n\t{\n\t\tif (BaseAreaSubset::intersection(bf->getPlacement(), skip))\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\t\tret |= bf->getRules()->getForbiddenBaseFunc();\n\t}\n\n\tret |= _forbiddenBaseFunc;\n\n\treturn ret;\n}\n\n/**\n * Return list of all future provided functionality in base.\n * @return List of custom IDs.\n */\nRuleBaseFacilityFunctions Base::getFutureBaseFunc(BaseAreaSubset skip) const\n{\n\tRuleBaseFacilityFunctions ret = 0;\n\n\tfor (const auto* bf : _facilities)\n\t{\n\t\tif (BaseAreaSubset::intersection(bf->getPlacement(), skip))\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\t\tret |= bf->getRules()->getProvidedBaseFunc();\n\t}\n\n\tret |= _provideBaseFunc;\n\n\treturn ret;\n}\n\n/**\n* Checks if it is possible to build another facility of a given type.\n* @return True if limit is reached (i.e. can't build anymore).\n*/\nbool Base::isMaxAllowedLimitReached(RuleBaseFacility *rule) const\n{\n\tif (rule->getMaxAllowedPerBase() == 0)\n\t\treturn false;\n\n\tint total = 0;\n\n\tfor (const auto* bf : _facilities)\n\t{\n\t\tif (bf->getRules()->getType() == rule->getType())\n\t\t{\n\t\t\ttotal++;\n\t\t}\n\t}\n\n\treturn total >= rule->getMaxAllowedPerBase();\n}\n\n/**\n * Gets the summary of all recovery rates provided by the base.\n */\nBaseSumDailyRecovery Base::getSumRecoveryPerDay() const\n{\n\tauto result = BaseSumDailyRecovery{ };\n\n\tint manaMinimum = 0;\n\tint manaMaximum = 0;\n\n\tint healthMaxinum = 0;\n\n\tfor (const auto* bf : _facilities)\n\t{\n\t\tif (bf->getBuildTime() == 0)\n\t\t{\n\t\t\tauto* rule = bf->getRules();\n\n\t\t\tmanaMinimum = std::min(manaMinimum, rule->getManaRecoveryPerDay());\n\t\t\tmanaMaximum = std::max(manaMaximum, rule->getManaRecoveryPerDay());\n\n\t\t\thealthMaxinum = std::max(healthMaxinum, rule->getHealthRecoveryPerDay());\n\n\t\t\tresult.SickBayAbsoluteBonus += rule->getSickBayAbsoluteBonus();\n\t\t\tresult.SickBayRelativeBonus += rule->getSickBayRelativeBonus();\n\t\t}\n\t}\n\n\tif (manaMaximum > 0)\n\t\tresult.ManaRecovery = manaMaximum;\n\telse if (manaMinimum < 0)\n\t\tresult.ManaRecovery =  manaMinimum;\n\n\tresult.HealthRecovery = healthMaxinum;\n\n\treturn result;\n}\n\n/**\n * Removes the craft and all associations from the base (does not destroy it!).\n * @param craft Pointer to craft.\n * @param unload Unload craft contents before removing.\n */\nstd::vector<Craft*>::iterator Base::removeCraft(Craft *craft, bool unload)\n{\n\t// Unload craft\n\tif (unload)\n\t{\n\t\tcraft->unload();\n\t}\n\n\t// Clear hangar\n\tfor (auto* fac : _facilities)\n\t{\n\t\tif (fac->getCraftForDrawing() == craft)\n\t\t{\n\t\t\tfac->setCraftForDrawing(0);\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// Remove craft\n\tstd::vector<Craft*>::iterator c;\n\tfor (c = _crafts.begin(); c != _crafts.end(); ++c)\n\t{\n\t\tif (*c == craft)\n\t\t{\n\t\t\treturn _crafts.erase(c);\n\t\t}\n\t}\n\treturn c;\n}\n\n}\n"
  },
  {
    "path": "src/Savegame/Base.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Target.h\"\n#include <string>\n#include <vector>\n#include <map>\n#include <list>\n#include \"../Engine/Yaml.h\"\n#include \"../Mod/RuleBaseFacilityFunctions.h\"\n\n#ifndef BASEFACILITIESITERATOR\n#define BASEFACILITIESITERATOR std::vector<BaseFacility*>::iterator\n#endif\n\nnamespace OpenXcom\n{\n\nclass RuleCraft;\nclass Soldier;\nclass Craft;\nclass ItemContainer;\nclass Transfer;\nclass Language;\nclass Mod;\nclass SavedGame;\nclass RuleBaseFacility;\nclass BaseFacility;\nclass ResearchProject;\nclass Production;\nclass Vehicle;\nclass Ufo;\nclass AlienMission;\nclass Texture;\n\nenum UfoDetection : int;\nenum BasePlacementErrors : int\n{\n\t/// 0: ok\n\tBPE_None = 0,\n\t/// 1: not connected to lift or on top of another facility (standard OXC behavior)\n\tBPE_NotConnected = 1,\n\t/// 2: trying to upgrade over existing facility, but it's in use\n\tBPE_Used = 2,\n\t/// 3: trying to upgrade over existing facility, but it's already being upgraded\n\tBPE_Upgrading = 3,\n\t/// 4: trying to upgrade over existing facility, but size/placement mismatch\n\tBPE_UpgradeSizeMismatch = 4,\n\t/// 5: trying to upgrade over existing facility, but ruleset of new facility requires a specific existing facility\n\tBPE_UpgradeRequireSpecific = 5,\n\t/// 6: trying to upgrade over existing facility, but ruleset disallows it\n\tBPE_UpgradeDisallowed = 6,\n\t/// 7: trying to upgrade over existing facility, but all buildings next to it are under construction and build queue is off\n\tBPE_Queue = 7,\n\t/// 8: trying to build a facility, which is forbidden by other existing facilities in the base\n\tBPE_ForbiddenByOther = 8,\n\t/// 9: trying to build a facility, which would forbid (i.e. would be in conflict with) other existing facilities in the base\n\tBPE_ForbiddenByThis = 9,\n\t/// 10: not enough storage space\n\tBPE_Used_Stores = 10,\n\t/// 11: not enough living quarters\n\tBPE_Used_Quarters = 11,\n\t/// 12: not enough laboratories\n\tBPE_Used_Laboratories = 12,\n\t/// 13: not enough workshops\n\tBPE_Used_Workshops = 13,\n\t/// 14: not enough hangars\n\tBPE_Used_Hangars = 14,\n\t/// 15: not enough psi labs\n\tBPE_Used_PsiLabs = 15,\n\t/// 16: not enough gyms\n\tBPE_Used_Gyms = 16,\n\t/// 17: not enough alien containment\n\tBPE_Used_AlienContainment = 17,\n\t/// 18: trying to build a facility (from scratch) that can only be built as an upgrade of another facility\n\tBPE_UpgradeOnly = 18,\n};\n\nstruct BaseSumDailyRecovery\n{\n\t/// Amount of mana recovery or loss provided by the base.\n\tint ManaRecovery = 0;\n\t/// Amount of health recovery provided by the base.\n\tint HealthRecovery = 0;\n\t/// Sum of the amount of additional wounds healed in this base due to sick bay facilities (as percentage of max HP per soldier).\n\tfloat SickBayRelativeBonus = 0.0f;\n\t/// Sum of the amount of additional wounds healed in this base due to sick bay facilities (in absolute number).\n\tfloat SickBayAbsoluteBonus = 0.0f;\n};\n\n/**\n * Represents a player base on the globe.\n * Bases can contain facilities, personnel, crafts and equipment.\n */\nclass Base : public Target\n{\nprivate:\n\tstatic const int BASE_SIZE = 6;\n\tconst Mod *_mod;\n\tstd::vector<BaseFacility*> _facilities;\n\tstd::vector<Soldier*> _soldiers;\n\tstd::vector<Craft*> _crafts;\n\tstd::vector<Transfer*> _transfers;\n\tItemContainer *_items;\n\tint _scientists, _engineers;\n\tstd::vector<ResearchProject *> _research;\n\tstd::vector<Production *> _productions;\n\tbool _inBattlescape;\n\tbool _retaliationTarget;\n\tAlienMission* _retaliationMission;\n\tbool _fakeUnderwater;\n\tstd::vector<Vehicle*> _vehicles;\n\tstd::vector<Vehicle*> _vehiclesFromBase;\n\tstd::vector<BaseFacility*> _defenses;\n\tstd::map<const RuleBaseFacility*, int> _destroyedFacilitiesCache;\n\tRuleBaseFacilityFunctions _provideBaseFunc = 0;\n\tRuleBaseFacilityFunctions _forbiddenBaseFunc = 0;\n\tconst Texture* _globeTexture = nullptr;\n\n\tusing Target::load;\npublic:\n\t/// Creates a new base.\n\tBase(const Mod *mod);\n\t/// Cleans up the base.\n\t~Base();\n\t/// Loads the base from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader, SavedGame *save, bool newGame, bool newBattleGame = false);\n\t/// Finishes loading the base (more specifically all craft in the base) from YAML.\n\tvoid finishLoading(const YAML::YamlNodeReader& reader, SavedGame *save);\n\tvoid calculateServices(SavedGame* save);\n\t/// Tests whether the base facilities are within the base boundaries and not overlapping.\n\tbool isOverlappingOrOverflowing();\n\t/// Saves the base to YAML.\n\tvoid save(YAML::YamlNodeWriter writer) const override;\n\t/// Gets the base's type.\n\tstd::string getType() const override;\n\t/// Gets the base's name.\n\tstd::string getName(Language *lang = 0) const override;\n\t/// Gets the base's marker sprite.\n\tint getMarker() const override;\n\t/// Gets the base's facilities.\n\tstd::vector<BaseFacility*> *getFacilities();\n\t/// Gets the base's soldiers.\n\tstd::vector<Soldier*> *getSoldiers();\n\t/// Pre-calculates soldier stats with various bonuses.\n\tvoid prepareSoldierStatsWithBonuses();\n\t/// Gets the base's crafts.\n\tstd::vector<Craft*> *getCrafts() {\treturn &_crafts; }\n\t/// Gets the base's crafts.\n\tconst std::vector<Craft*> *getCrafts() const { return &_crafts; }\n\t/// Gets the base's transfers.\n\tstd::vector<Transfer*> *getTransfers() { return &_transfers; }\n\t/// Gets the base's transfers.\n\tconst std::vector<Transfer*> *getTransfers() const { return &_transfers; }\n\t/// Gets the base's items.\n\tItemContainer *getStorageItems() { return _items; }\n\t/// Gets the base's items.\n\tconst ItemContainer *getStorageItems() const { return _items; }\n\t/// Gets the base's scientists.\n\tint getScientists() const;\n\t/// Sets the base's scientists.\n\tvoid setScientists(int scientists);\n\t/// Gets the base's engineers.\n\tint getEngineers() const;\n\t/// Sets the base's engineers.\n\tvoid setEngineers(int engineers);\n\t/// Checks if a target is detected by the base's radar.\n\tUfoDetection detect(const Ufo *target, const SavedGame *save, bool alreadyTracked) const;\n\t/// Gets the base's available soldiers.\n\tint getAvailableSoldiers(bool checkCombatReadiness = false, bool includeWounded = false) const;\n\t/// Gets the base's total soldiers.\n\tint getTotalSoldiers() const;\n\t/// Gets the base's available scientists.\n\tint getAvailableScientists() const;\n\t/// Gets the base's total scientists.\n\tint getTotalScientists() const;\n\t/// Gets the base's available engineers.\n\tint getAvailableEngineers() const;\n\t/// Gets the base's total engineers.\n\tint getTotalEngineers() const;\n\t/// Gets the base's total number and cost of other staff & inventory.\n\tint getTotalOtherStaffAndInventoryCost(int& staffCount, int& inventoryCount) const;\n\t/// Gets the base's used living quarters.\n\tint getUsedQuarters() const;\n\t/// Gets the base's available living quarters.\n\tint getAvailableQuarters() const;\n\t/// Gets the base's used storage space.\n\tdouble getUsedStores(bool excludeNormalItems = false) const;\n\t/// Checks if the base's stores are overfull.\n\tbool storesOverfull(double offset = 0.0) const;\n\t/// Checks if the base's stores are so full that even craft equipment and incoming transfers can't fit.\n\tbool storesOverfullCritical() const;\n\t/// Gets the base's available storage space.\n\tint getAvailableStores() const;\n\t/// Gets the base's used laboratory space.\n\tint getUsedLaboratories() const;\n\t/// Gets the base's available laboratory space.\n\tint getAvailableLaboratories() const;\n\t/// Gets the base's used workshop space.\n\tint getUsedWorkshops() const;\n\t/// Gets the base's available workshop space.\n\tint getAvailableWorkshops() const;\n\t/// Gets the base's used hangars.\n\tint getUsedHangars() const;\n\t/// Gets the base's available hangars.\n\tint getAvailableHangars() const;\n\t/// Get the number of available space lab (not used by a ResearchProject)\n\tint getFreeLaboratories() const;\n\t/// Get the number of available space lab (not used by a Production)\n\tint getFreeWorkshops() const;\n\n\tint getAllocatedScientists() const;\n\n\tint getAllocatedEngineers() const;\n\t/// Gets the base's defense value.\n\tint getDefenseValue() const;\n\t/// Gets the base's short range detection.\n\tint getShortRangeDetection() const;\n\t/// Gets the base's long range detection.\n\tint getLongRangeDetection() const;\n\t/// Gets the base's crafts of a certain type.\n\tint getCraftCount(const RuleCraft *craft) const;\n\t/// Gets the base's crafts of a certain type.\n\tint getCraftCountForProduction(const RuleCraft *craft) const;\n\t/// Gets the base's craft maintenance.\n\tint getCraftMaintenance() const;\n\t/// Gets the total count and total salary of soldiers of a certain type stored in the base.\n\tstd::pair<int, int> getSoldierCountAndSalary(const std::string &soldier) const;\n\t/// Gets the base's personnel maintenance.\n\tint getPersonnelMaintenance() const;\n\t/// Gets the base's facility maintenance.\n\tint getFacilityMaintenance() const;\n\t/// Gets the base's total monthly maintenance.\n\tint getMonthlyMaintenace() const;\n\t/// Get the list of base's ResearchProject\n\tconst std::vector<ResearchProject *> & getResearch() const;\n\t/// Get the list of base's ResearchProject\n\tstd::vector<ResearchProject *> & getResearch() { return _research; }\n\t/// Add a new ResearchProject to the Base\n\tvoid addResearch(ResearchProject *);\n\t/// Remove a ResearchProject from the Base\n\tvoid removeResearch(ResearchProject *);\n\t/// Add a new Production to Base\n\tvoid addProduction (Production * p);\n\t/// Remove a Base Production's\n\tvoid removeProduction (Production * p);\n\t/// Get the list of Base Production's\n\tconst std::vector<Production *> & getProductions() const;\n\t/// Gets the base's used psi lab space.\n\tint getUsedPsiLabs() const;\n\t/// Gets the base's total available psi lab space.\n\tint getAvailablePsiLabs() const;\n\t/// Gets the base's total free psi lab space.\n\tint getFreePsiLabs() const;\n\t/// Gets the base's used training space.\n\tint getUsedTraining() const;\n\t/// Gets the base's total available training space.\n\tint getAvailableTraining() const;\n\t/// Gets the base's total free training space.\n\tint getFreeTrainingSpace() const;\n\t/// Gets the amount of free Containment space.\n\tint getFreeContainment(int prisonType) const;\n\t/// Gets the total amount of Containment space.\n\tint getAvailableContainment(int prisonType) const;\n\t/// Gets the total amount of used Containment space.\n\tint getUsedContainment(int prisonType, bool onlyExternal = false) const;\n\t/// Sets the craft's battlescape status.\n\tvoid setInBattlescape(bool inbattle);\n\t/// Gets if the craft is in battlescape.\n\tbool isInBattlescape() const;\n\t/// Mark this base for alien retaliation.\n\tvoid setRetaliationTarget(bool mark = true);\n\t/// Gets the retaliation status of this base.\n\tbool getRetaliationTarget() const;\n\t/// Sets the corresponding alien retaliation mission.\n\tvoid setRetaliationMission(AlienMission* retaliationMission) { _retaliationMission = retaliationMission; }\n\t/// Gets the corresponding alien retaliation mission.\n\tAlienMission* getRetaliationMission() const { return _retaliationMission; }\n\t/// Mark/unmark this base as a fake underwater base.\n\tvoid setFakeUnderwater(bool fakeUnderwater) { _fakeUnderwater = fakeUnderwater; }\n\t/// Is this a fake underwater base?\n\tbool isFakeUnderwater() const { return _fakeUnderwater; }\n\t/// Get the detection chance for this base.\n\tsize_t getDetectionChance() const;\n\t/// Gets how many Grav Shields the base has\n\tint getGravShields() const;\n\t/// Setup base defenses.\n\tvoid setupDefenses(AlienMission* am);\n\t/// Get a list of Defensive Facilities\n\tstd::vector<BaseFacility*> *getDefenses();\n\t/// Gets the base's vehicles.\n\tstd::vector<Vehicle*> *getVehicles();\n\t/// Gets the list of recently destroyed base facilities.\n\tstd::map<const RuleBaseFacility*, int> *getDestroyedFacilitiesCache() { return &_destroyedFacilitiesCache; }\n\t/// Damage and/or destroy facilities after a missile impact.\n\tvoid damageFacilities(Ufo *ufo);\n\t/// Damage a given facility.\n\tint damageFacility(BaseFacility *toBeDamaged);\n\t/// Destroys all disconnected facilities in the base.\n\tvoid destroyDisconnectedFacilities();\n\t/// Gets a sorted list of the facilities(=iterators) NOT connected to the Access Lift.\n\tstd::list<BASEFACILITIESITERATOR> getDisconnectedFacilities(BaseFacility *remove);\n\t/// destroy a facility and deal with the side effects.\n\tvoid destroyFacility(BASEFACILITIESITERATOR facility);\n\tvoid cleanupPrisons(int prisonType);\n\t/// Cleans up the defenses vector and optionally reclaims the tanks and their ammo.\n\tvoid cleanupDefenses(bool reclaimItems);\n\n\t/// Check if any facilities in a given area are used.\n\tBasePlacementErrors isAreaInUse(BaseAreaSubset area, const RuleBaseFacility* replacement = nullptr) const;\n\t/// Gets available base functionality.\n\tRuleBaseFacilityFunctions getProvidedBaseFunc(BaseAreaSubset skip) const;\n\tRuleBaseFacilityFunctions getInherentProvidedBaseFunc() const { return _provideBaseFunc; }\n\t/// Gets used base functionality.\n\tRuleBaseFacilityFunctions getRequireBaseFunc(BaseAreaSubset skip) const;\n\t/// Gets forbidden base functionality.\n\tRuleBaseFacilityFunctions getForbiddenBaseFunc(BaseAreaSubset skip) const;\n\tRuleBaseFacilityFunctions getInherentForbiddenBaseFunc() const { return _forbiddenBaseFunc; }\n\t/// Gets future base functionality.\n\tRuleBaseFacilityFunctions getFutureBaseFunc(BaseAreaSubset skip) const;\n\tRuleBaseFacilityFunctions getInherentFutureBaseFunc() const { return _provideBaseFunc; }\n\t/// Checks if it is possible to build another facility of a given type.\n\tbool isMaxAllowedLimitReached(RuleBaseFacility *rule) const;\n\n\t/// Gets the summary of all recovery rates provided by the base.\n\tBaseSumDailyRecovery getSumRecoveryPerDay() const;\n\t/// Removes a craft from the base.\n\tstd::vector<Craft*>::iterator removeCraft(Craft *craft, bool unload);\n\n\t/// Gets the base's globe texture.\n\tconst Texture* getGlobeTexture() const { return _globeTexture; }\n\t/// Sets the base's globe texture.\n\tvoid setGlobeTexture(const Texture* globeTexture) { _globeTexture = globeTexture; }\n};\n\n}\n"
  },
  {
    "path": "src/Savegame/BaseFacility.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"BaseFacility.h\"\n#include \"../Mod/RuleBaseFacility.h\"\n#include \"../Engine/GraphSubset.h\"\n#include \"Base.h\"\n#include \"ItemContainer.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes a base facility of the specified type.\n * @param rules Pointer to ruleset.\n * @param base Pointer to base of origin.\n */\nBaseFacility::BaseFacility(const RuleBaseFacility *rules, Base *base) :\n\t_rules(rules), _base(base),\n\t_x(-1), _y(-1), _buildTime(0),\n\t_ammo(0),\n\t_ammoMissingReported(false),\n\t_disabled(false),\n\t_craftForDrawing(0),\n\t_hadPreviousFacility(false)\n{\n}\n\n/**\n *\n */\nBaseFacility::~BaseFacility()\n{\n}\n\n/**\n * Loads the base facility from a YAML file.\n * @param node YAML node.\n */\nvoid BaseFacility::load(const YAML::YamlNodeReader& reader)\n{\n\treader.tryRead(\"x\", _x);\n\treader.tryRead(\"y\", _y);\n\treader.tryRead(\"buildTime\", _buildTime);\n\treader.tryRead(\"ammo\", _ammo);\n\treader.tryRead(\"ammoMissingReported\", _ammoMissingReported);\n\treader.tryRead(\"disabled\", _disabled);\n\treader.tryRead(\"hadPreviousFacility\", _hadPreviousFacility);\n}\n\n/**\n * Saves the base facility to a YAML file.\n * @return YAML node.\n */\nvoid BaseFacility::save(YAML::YamlNodeWriter writer) const\n{\n\twriter.setAsMap();\n\twriter.write(\"type\", _rules->getType());\n\twriter.write(\"x\", _x);\n\twriter.write(\"y\", _y);\n\tif (_buildTime != 0)\n\t\twriter.write(\"buildTime\", _buildTime);\n\tif (_ammo != 0)\n\t\twriter.write(\"ammo\", _ammo);\n\tif (_ammoMissingReported)\n\t\twriter.write(\"ammoMissingReported\", _ammoMissingReported);\n\tif (_disabled)\n\t\twriter.write(\"disabled\", _disabled);\n\tif (_hadPreviousFacility)\n\t\twriter.write(\"hadPreviousFacility\", _hadPreviousFacility);\n}\n\n/**\n * Returns the ruleset for the base facility's type.\n * @return Pointer to ruleset.\n */\nconst RuleBaseFacility *BaseFacility::getRules() const\n{\n\treturn _rules;\n}\n\n/**\n * Returns the base facility's X position on the\n * base grid that it's placed on.\n * @return X position in grid squares.\n */\nint BaseFacility::getX() const\n{\n\treturn _x;\n}\n\n/**\n * Changes the base facility's X position on the\n * base grid that it's placed on.\n * @param x X position in grid squares.\n */\nvoid BaseFacility::setX(int x)\n{\n\t_x = x;\n}\n\n/**\n * Returns the base facility's Y position on the\n * base grid that it's placed on.\n * @return Y position in grid squares.\n */\nint BaseFacility::getY() const\n{\n\treturn _y;\n}\n\n/**\n * Changes the base facility's Y position on the\n * base grid that it's placed on.\n * @param y Y position in grid squares.\n */\nvoid BaseFacility::setY(int y)\n{\n\t_y = y;\n}\n\n/**\n * Get placement of facility in base.\n */\nBaseAreaSubset BaseFacility::getPlacement() const\n{\n\tint sizeX = _rules->getSizeX();\n\tint sizeY = _rules->getSizeY();\n\treturn BaseAreaSubset(sizeX, sizeY).offset(_x, _y);\n}\n\n/**\n * Returns the base facility's remaining time\n * until it's finished building (0 = complete).\n * @return Time left in days.\n */\nint BaseFacility::getBuildTime() const\n{\n\treturn _buildTime;\n}\n\n/**\n * Returns the base facility's remaining time\n * until it's finished building (0 = complete).\n * Facility upgrades and downgrades are ignored in this calculation.\n * @return Time left in days.\n */\nint BaseFacility::getAdjustedBuildTime() const\n{\n\tif (_hadPreviousFacility)\n\t\treturn 0;\n\n\treturn _buildTime;\n}\n\n/**\n * Changes the base facility's remaining time\n * until it's finished building.\n * @param time Time left in days.\n */\nvoid BaseFacility::setBuildTime(int time)\n{\n\t_buildTime = time;\n}\n\n/**\n * Handles the facility building every day.\n */\nvoid BaseFacility::build()\n{\n\t_buildTime--;\n\tif (_buildTime == 0)\n\t\t_hadPreviousFacility = false;\n}\n\n/**\n * Returns if this facility is currently being\n * used by its base.\n * @return True if it's under use, False otherwise.\n */\nBasePlacementErrors BaseFacility::inUse() const\n{\n\tif (_buildTime > 0)\n\t{\n\t\treturn BPE_None;\n\t}\n\n\treturn _base->isAreaInUse(getPlacement());\n}\n\n/**\n * Rearms the facility.\n * @return The ammo item missing for rearming, or nullptr if none or reported already.\n */\nconst RuleItem* BaseFacility::rearm()\n{\n\t// facility doesn't need to be rearmed at all (vanilla)\n\tif (_rules->getAmmoMax() <= 0)\n\t\treturn nullptr;\n\n\t// facility is not operational\n\tif (_buildTime > 0)\n\t\treturn nullptr;\n\n\t// facility is already fully armed\n\tif (_ammo >= _rules->getAmmoMax())\n\t{\n\t\tresetAmmoMissingReported();\n\t\treturn nullptr;\n\t}\n\n\tint ammoMissing = _rules->getAmmoMax() - _ammo;\n\tint ammoUsed = std::min(ammoMissing, _rules->getRearmRate());\n\n\tconst RuleItem* ammoItem = nullptr;\n\tif (_rules->getAmmoItem())\n\t{\n\t\tint ammoAvailable = _base->getStorageItems()->getItem(_rules->getAmmoItem());\n\t\tif (ammoAvailable < ammoUsed)\n\t\t{\n\t\t\tif (!_ammoMissingReported)\n\t\t\t{\n\t\t\t\tammoItem = _rules->getAmmoItem();\n\t\t\t\t_ammoMissingReported = true;\n\t\t\t}\n\t\t\tammoUsed = ammoAvailable;\n\t\t}\n\t\t_base->getStorageItems()->removeItem(_rules->getAmmoItem(), ammoUsed);\n\t}\n\n\t_ammo += ammoUsed;\n\n\treturn ammoItem;\n}\n\n/**\n * Checks if the facility is disabled.\n * @return True if facility is disabled, False otherwise.\n */\nbool BaseFacility::getDisabled() const\n{\n\treturn _disabled;\n}\n\n/**\n * Sets the facility's disabled flag.\n * @param disabled flag to set.\n */\nvoid BaseFacility::setDisabled(bool disabled)\n{\n\t_disabled = disabled;\n}\n\n/**\n * Gets craft, used for drawing facility.\n * @return craft\n */\nCraft *BaseFacility::getCraftForDrawing() const\n{\n\treturn _craftForDrawing;\n}\n\n/**\n * Sets craft, used for drawing facility.\n * @param craft for drawing hangar.\n */\nvoid BaseFacility::setCraftForDrawing(Craft *craft)\n{\n\t_craftForDrawing = craft;\n}\n\n/**\n * Gets whether this facility was placed over another or was placed by removing another\n * @return true if placed over or by removing another facility\n */\nbool BaseFacility::getIfHadPreviousFacility() const\n{\n\treturn _hadPreviousFacility;\n}\n\n/**\n * Sets whether this facility was placed over another or was placed by removing another\n * @param was there another facility just here?\n */\nvoid BaseFacility::setIfHadPreviousFacility(bool hadPreviousFacility)\n{\n\t_hadPreviousFacility = hadPreviousFacility;\n}\n\n/**\n * Is the facility fully built or being upgraded/downgraded?\n * Used for determining if this facility should count for base connectivity\n * @return True, if fully built or being upgraded/downgraded.\n */\nbool BaseFacility::isBuiltOrHadPreviousFacility() const\n{\n\treturn _buildTime == 0 || _hadPreviousFacility;\n}\n\n}\n"
  },
  {
    "path": "src/Savegame/BaseFacility.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/Yaml.h\"\n#include \"../Mod/RuleBaseFacility.h\"\n\nnamespace OpenXcom\n{\n\nclass RuleBaseFacility;\nclass RuleItem;\nclass Base;\nclass Mod;\nclass Craft;\n\n/**\n * Represents a base facility placed in a base.\n * Contains variable info about a facility like\n * position and build time.\n * @sa RuleBaseFacility\n */\nclass BaseFacility\n{\nprivate:\n\tconst RuleBaseFacility *_rules;\n\tBase *_base;\n\tint _x, _y, _buildTime;\n\tint _ammo;\n\tbool _ammoMissingReported;\n\tbool _disabled;\n\tCraft *_craftForDrawing;\t// craft, used for drawing facility\n\tbool _hadPreviousFacility;\npublic:\n\t/// Creates a base facility of the specified type.\n\tBaseFacility(const RuleBaseFacility *rules, Base *base);\n\t/// Cleans up the base facility.\n\t~BaseFacility();\n\t/// Loads the base facility from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader);\n\t/// Saves the base facility to YAML.\n\tvoid save(YAML::YamlNodeWriter writer) const;\n\t/// Gets the facility's ruleset.\n\tconst RuleBaseFacility *getRules() const;\n\t/// Gets the facility's X position.\n\tint getX() const;\n\t/// Sets the facility's X position.\n\tvoid setX(int x);\n\t/// Gets the facility's Y position.\n\tint getY() const;\n\t/// Sets the facility's Y position.\n\tvoid setY(int y);\n\t/// Get placement of facility in base.\n\tBaseAreaSubset getPlacement() const;\n\t/// Gets the facility's construction time.\n\tint getBuildTime() const;\n\t/// Gets the facility's adjusted construction time (i.e. NOT considering upgrades/downgrades).\n\tint getAdjustedBuildTime() const;\n\t/// Sets the facility's construction time.\n\tvoid setBuildTime(int time);\n\t/// Builds up the facility.\n\tvoid build();\n\t/// Checks if the facility is currently in use.\n\tBasePlacementErrors inUse() const;\n\t/// Gets the facility's ammo count.\n\tint getAmmo() const { return _ammo; }\n\t/// Sets the facility's ammo count.\n\tvoid setAmmo(int ammo) { _ammo = ammo; }\n\t/// Resets the helper flag.\n\tvoid resetAmmoMissingReported() { _ammoMissingReported = false; }\n\t/// Rearms the facility.\n\tconst RuleItem* rearm();\n\t/// Checks if the facility is disabled.\n\tbool getDisabled() const;\n\t/// Sets the facility's disabled flag.\n\tvoid setDisabled(bool disabled);\n\t/// Gets craft, used for drawing facility.\n\tCraft *getCraftForDrawing() const;\n\t/// Sets craft, used for drawing facility.\n\tvoid setCraftForDrawing(Craft *craft);\n\t/// Gets whether this facility was placed over another or was placed by removing another\n\tbool getIfHadPreviousFacility() const;\n\t/// Sets whether this facility was placed over another or was placed by removing another\n\tvoid setIfHadPreviousFacility(bool hadPreviousFacility);\n\t/// Is the facility fully built or being upgraded/downgraded?\n\tbool isBuiltOrHadPreviousFacility() const;\n};\n\n}\n"
  },
  {
    "path": "src/Savegame/BattleItem.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"BattleItem.h\"\n#include \"BattleUnit.h\"\n#include \"Tile.h\"\n#include \"SavedGame.h\"\n#include \"SavedBattleGame.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"../Mod/RuleSkill.h\"\n#include \"../Mod/RuleInventory.h\"\n#include \"../Engine/Collections.h\"\n#include \"../Engine/Surface.h\"\n#include \"../Engine/SurfaceSet.h\"\n#include \"../Engine/Script.h\"\n#include \"../Engine/ScriptBind.h\"\n#include \"../Engine/RNG.h\"\n#include \"../Battlescape/Particle.h\"\n#include \"../fmath.h\"\n#include <optional>\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes a item of the specified type.\n * @param rules Pointer to ruleset.\n * @param id The id of the item.\n */\nBattleItem::BattleItem(const RuleItem *rules, int *id) : _id(*id), _rules(rules), _owner(0), _previousOwner(0), _unit(0), _tile(0), _inventorySlot(0), _inventoryX(0), _inventoryY(0), _ammoItem{ }, _fuseTimer(-1), _ammoQuantity(0), _painKiller(0), _heal(0), _stimulant(0), _XCOMProperty(false), _droppedOnAlienTurn(false), _isAmmo(false), _isWeaponWithAmmo(false), _fuseEnabled(false)\n{\n\t(*id)++;\n\tif (_rules)\n\t{\n\t\t_inventoryMoveCostPercent = _rules->getInventoryMoveCostPercent();\n\t\t_confMelee = _rules->getConfigMelee();\n\t\tsetAmmoQuantity(_rules->getClipSize());\n\t\tif (_rules->getBattleType() == BT_MEDIKIT)\n\t\t{\n\t\t\tsetHealQuantity (_rules->getHealQuantity());\n\t\t\tsetPainKillerQuantity (_rules->getPainKillerQuantity());\n\t\t\tsetStimulantQuantity (_rules->getStimulantQuantity());\n\t\t}\n\t\t// weapon does not need ammo, ammo item points to weapon\n\t\telse if (_rules->getBattleType() == BT_FIREARM || _rules->getBattleType() == BT_MELEE)\n\t\t{\n\t\t\t_confAimedOrLaunch = _rules->getConfigAimed();\n\t\t\t_confAuto = _rules->getConfigAuto();\n\t\t\t_confSnap = _rules->getConfigSnap();\n\t\t\tbool showSelfAmmo = _rules->getClipSize() > 0;\n\t\t\tfor (int slot = 0; slot < RuleItem::AmmoSlotMax; ++slot)\n\t\t\t{\n\t\t\t\tbool used = false;\n\t\t\t\tused |= (_confAimedOrLaunch && _confAimedOrLaunch->ammoSlot == slot);\n\t\t\t\tused |= (_confAuto && _confAuto->ammoSlot == slot);\n\t\t\t\tused |= (_confSnap && _confSnap->ammoSlot == slot);\n\t\t\t\tused |= (_confMelee && _confMelee->ammoSlot == slot);\n\t\t\t\tif (_rules->getCompatibleAmmoForSlot(slot)->empty())\n\t\t\t\t{\n\t\t\t\t\tif (used && showSelfAmmo)\n\t\t\t\t\t{\n\t\t\t\t\t\t_ammoVisibility[slot] = true;\n\t\t\t\t\t\tshowSelfAmmo = false;\n\t\t\t\t\t}\n\t\t\t\t\t_ammoItem[slot] = this;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t_ammoVisibility[slot] = used;\n\t\t\t\t\t_isWeaponWithAmmo = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n *\n */\nBattleItem::~BattleItem()\n{\n}\n\n/**\n * Loads the item from a YAML file.\n * @param node YAML node.\n * @param mod Mod for the item.\n */\nvoid BattleItem::load(const YAML::YamlNodeReader& reader, Mod *mod, const ScriptGlobal *shared)\n{\n\tif (const auto& cost = reader[\"inventoryMoveCost\"])\n\t\t_inventoryMoveCostPercent = cost[\"basePercent\"].readVal(_inventoryMoveCostPercent);\n\tstd::string slot = reader[\"inventoryslot\"].readVal<std::string>(\"NULL\");\n\tif (slot != \"NULL\")\n\t{\n\t\t_inventorySlot = mod->getInventory(slot);\n\t\tif (!_inventorySlot)\n\t\t\t_inventorySlot = mod->getInventoryGround();\n\t}\n\treader.tryRead(\"inventoryX\", _inventoryX);\n\treader.tryRead(\"inventoryY\", _inventoryY);\n\treader.tryRead(\"ammoqty\", _ammoQuantity);\n\treader.tryRead(\"painKiller\", _painKiller);\n\treader.tryRead(\"heal\", _heal);\n\treader.tryRead(\"stimulant\", _stimulant);\n\t//reader.tryRead(\"fuseTimer\", _fuseTimer);\n\tif (const auto& fuseTimer = reader[\"fuseTimer\"]) // needed for compatibility with OXC\n\t\tsetFuseTimer(fuseTimer.readVal<int>());\n\treader.tryRead(\"fuseEnabed\", _fuseEnabled);\n\treader.tryRead(\"droppedOnAlienTurn\", _droppedOnAlienTurn);\n\treader.tryRead(\"XCOMProperty\", _XCOMProperty);\n\t_scriptValues.load(reader, shared);\n}\n\n/**\n * Saves the item to a YAML file.\n * @return YAML node.\n */\nvoid BattleItem::save(YAML::YamlNodeWriter writer, const ScriptGlobal *shared) const\n{\n\twriter.setAsMap();\n\twriter.write(\"id\", _id);\n\twriter.write(\"type\", _rules->getType());\n\tif (_owner)\n\t\twriter.write(\"owner\", _owner->getId());\n\tif (_previousOwner)\n\t\twriter.write(\"previousOwner\", _previousOwner->getId());\n\tif (_unit)\n\t\twriter.write(\"unit\", _unit->getId());\n\tif (_inventoryMoveCostPercent != _rules->getInventoryMoveCostPercent())\n\t{\n\t\tauto mcWriter = writer[\"inventoryMoveCost\"];\n\t\tmcWriter.setAsMap();\n\t\tmcWriter.write(\"basePercent\", _inventoryMoveCostPercent);\n\t}\n\tif (_inventorySlot)\n\t{\n\t\twriter.write(\"inventoryslot\", _inventorySlot->getId());\n\t\tif (_inventorySlot->getType() == INV_SLOT) // only for slot items this matter, for hands and ground it can be `0` for both\n\t\t{\n\t\t\twriter.write(\"inventoryX\", _inventoryX);\n\t\t\twriter.write(\"inventoryY\", _inventoryY);\n\t\t}\n\t}\n\tif (_tile)\n\t\twriter.write(\"position\", _tile->getPosition());\n\tif (_ammoQuantity || _rules->isAmmoRechargeable()) // To consider: maybe it would be better to just always write also zero?\n\t\twriter.write(\"ammoqty\", _ammoQuantity);\n\tif (_ammoItem[0])\n\t\twriter.write(\"ammoItem\", _ammoItem[0]->getId());\n\tstd::optional<YAML::YamlNodeWriter> ammoSlotWriter;\n\tCollections::untilLastIf(\n\t\t_ammoItem,\n\t\t[](BattleItem* i)\n\t\t{\n\t\t\treturn i != nullptr;\n\t\t},\n\t\t[&](BattleItem* i)\n\t\t{\n\t\t\tif (!ammoSlotWriter.has_value())\n\t\t\t{\n\t\t\t\tammoSlotWriter.emplace(writer[\"ammoItemSlots\"]);\n\t\t\t\tammoSlotWriter->setAsSeq();\n\t\t\t\tammoSlotWriter->setFlowStyle();\n\t\t\t}\n\t\t\tammoSlotWriter->write(i ? i->getId() : -1);\n\t\t});\n\tif (_rules && _rules->getBattleType() == BT_MEDIKIT)\n\t{\n\t\twriter.write(\"painKiller\", _painKiller);\n\t\twriter.write(\"heal\", _heal);\n\t\twriter.write(\"stimulant\", _stimulant);\n\t}\n\tif (_fuseTimer != -1)\n\t\twriter.write(\"fuseTimer\", _fuseTimer);\n\tif (_fuseEnabled)\n\t\twriter.write(\"fuseEnabed\", _fuseEnabled);\n\tif (_droppedOnAlienTurn)\n\t\twriter.write(\"droppedOnAlienTurn\", _droppedOnAlienTurn);\n\tif (_XCOMProperty)\n\t\twriter.write(\"XCOMProperty\", _XCOMProperty);\n\n\t_scriptValues.save(writer, shared);\n}\n\n/**\n * Gets the ruleset for the item's type.\n * @return Pointer to ruleset.\n */\nconst RuleItem *BattleItem::getRules() const\n{\n\treturn _rules;\n}\n\n/**\n * Gets the turns until detonation. -1 = unprimed grenade. -2 = mapblock grenade to explode before battle.\n * @return turns until detonation.\n */\nint BattleItem::getFuseTimer() const\n{\n\treturn _fuseTimer;\n}\n\n/**\n * Sets the turn to explode on.\n * @param turns Turns until detonation (player/alien turns, not game turns).\n */\nvoid BattleItem::setFuseTimer(int turns)\n{\n\tauto* event = _rules->getFuseTriggerEvent();\n\t_fuseTimer = turns;\n\tif (_fuseTimer >= 0)\n\t{\n\t\tif (event->throwTrigger || event->proximityTrigger)\n\t\t{\n\t\t\t_fuseEnabled = false;\n\t\t}\n\t\telse if (event->defaultBehavior)\n\t\t{\n\t\t\t_fuseEnabled = true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_fuseEnabled = false;\n\t\t}\n\t}\n\telse\n\t{\n\t\t_fuseEnabled = false;\n\t}\n}\n\n/**\n * Gets if fuse was triggered.\n */\nbool BattleItem::isFuseEnabled() const\n{\n\treturn _fuseEnabled;\n}\n\n/**\n * Set fuse trigger.\n */\nvoid BattleItem::setFuseEnabled(bool enable)\n{\n\tif (getFuseTimer() > -1)\n\t{\n\t\t_fuseEnabled = enable;\n\t}\n}\n\n/**\n * Called at end of turn.\n */\nvoid BattleItem::fuseEndTurnUpdate()\n{\n\tauto* event = _rules->getFuseTriggerEvent();\n\tif (_fuseEnabled && getFuseTimer() > 0)\n\t{\n\t\tif (event->defaultBehavior)\n\t\t{\n\t\t\tif (_rules->getFuseTimerType() != BFT_INSTANT)\n\t\t\t{\n\t\t\t\t--_fuseTimer;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Get if item can trigger end of turn effect.\n * @return True if grenade should explode or other item removed\n */\nbool BattleItem::fuseTimeEvent()\n{\n\tauto* event = _rules->getFuseTriggerEvent();\n\tauto check = [&]\n\t{\n\t\tif (_fuseEnabled && getFuseTimer() == 0)\n\t\t{\n\t\t\tif (event->defaultBehavior)\n\t\t\t{\n\t\t\t\treturn _rules->getFuseTimerType() != BFT_INSTANT;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t};\n\n\tif (check())\n\t{\n\t\tif (RNG::percent(_rules->getSpecialChance()))\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t//grenade fail to explode or item to get removed.\n\t\t\tif (_rules->getFuseTimerType() == BFT_SET)\n\t\t\t{\n\t\t\t\tsetFuseTimer(1);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tsetFuseTimer(-1);\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Called when item is throw.\n */\nbool BattleItem::fuseThrowEvent()\n{\n\tauto* event = _rules->getFuseTriggerEvent();\n\tauto check = [&]\n\t{\n\t\tif (_fuseEnabled && getFuseTimer() == 0)\n\t\t{\n\t\t\tif (event->throwExplode)\n\t\t\t{\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\telse if (event->defaultBehavior)\n\t\t\t{\n\t\t\t\treturn _rules->getBattleType() == BT_GRENADE && (Options::battleInstantGrenade || _rules->getFuseTimerType() == BFT_INSTANT);\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t};\n\n\tif (event->throwTrigger)\n\t{\n\t\tif (_rules->getFuseTimerType() == BFT_NONE)\n\t\t{\n\t\t\t_fuseEnabled = true;\n\t\t\t_fuseTimer = 0;\n\t\t}\n\t\telse if (_fuseTimer >= 0)\n\t\t{\n\t\t\t_fuseEnabled = true;\n\t\t}\n\t}\n\n\tif (check())\n\t{\n\t\treturn RNG::percent(_rules->getSpecialChance());\n\t}\n\treturn false;\n}\n\n/**\n * Called when item is throw.\n */\nbool BattleItem::fuseProximityEvent()\n{\n\tauto* event = _rules->getFuseTriggerEvent();\n\tauto check = [&]\n\t{\n\t\tif (_fuseEnabled && getFuseTimer() >= 0)\n\t\t{\n\t\t\tif (event->proximityExplode)\n\t\t\t{\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\telse if (event->defaultBehavior)\n\t\t\t{\n\t\t\t\treturn _rules->getBattleType() == BT_PROXIMITYGRENADE;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t};\n\n\tif (event->proximityTrigger)\n\t{\n\t\tif (_rules->getFuseTimerType() == BFT_NONE)\n\t\t{\n\t\t\t_fuseEnabled = true;\n\t\t\t_fuseTimer = 0;\n\t\t}\n\t\telse if (_fuseTimer >= 0)\n\t\t{\n\t\t\t_fuseEnabled = true;\n\t\t}\n\t}\n\n\tif (check())\n\t{\n\t\treturn RNG::percent(_rules->getSpecialChance());\n\t}\n\treturn false;\n}\n\n\n/**\n * Gets the quantity of ammo in this item.\n * @return Ammo quantity.\n */\nint BattleItem::getAmmoQuantity() const\n{\n\tif (_rules->getClipSize() == -1)\n\t{\n\t\treturn 255;\n\t}\n\treturn _ammoQuantity;\n}\n\n/**\n * Changes the quantity of ammo in this item.\n * @param qty Ammo quantity.\n */\nvoid BattleItem::setAmmoQuantity(int qty)\n{\n\t_ammoQuantity = qty;\n}\n\n/**\n * Spends a bullet from the ammo in this item.\n * (Or spends a certain amount of energy from this battery item.)\n * @return True if there are bullets left.\n */\nbool BattleItem::spendBullet(int spendPerShot)\n{\n\tif (_ammoQuantity >= spendPerShot)\n\t\t_ammoQuantity -= spendPerShot;\n\n\tif (_ammoQuantity == 0)\n\t\treturn false;\n\telse\n\t\treturn true;\n}\n\nvoid BattleItem::spendHealingItemUse(BattleMediKitAction mediKitAction)\n{\n\tif (mediKitAction == BMA_PAINKILLER)\n\t{\n\t\tsetPainKillerQuantity(getPainKillerQuantity() - 1);\n\t}\n\telse if (mediKitAction == BMA_STIMULANT)\n\t{\n\t\tsetStimulantQuantity(getStimulantQuantity() - 1);\n\t}\n\telse if (mediKitAction == BMA_HEAL)\n\t{\n\t\tsetHealQuantity(getHealQuantity() - 1);\n\t}\n}\n\n\n/**\n * Check if owner is removed from game.\n */\nbool BattleItem::isOwnerIgnored() const\n{\n\treturn _owner && _owner->isIgnored();\n}\n\n/**\n * Gets the item's owner.\n * @return Pointer to Battleunit.\n */\nBattleUnit *BattleItem::getOwner()\n{\n\treturn _owner;\n}\n\n/**\n * Gets the item's owner.\n * @return Pointer to Battleunit.\n */\nconst BattleUnit *BattleItem::getOwner() const\n{\n\treturn _owner;\n}\n\n/**\n * Gets the item's previous owner.\n * @return Pointer to Battleunit.\n */\nBattleUnit *BattleItem::getPreviousOwner()\n{\n\treturn _previousOwner;\n}\n\n/**\n * Gets the item's previous owner.\n * @return Pointer to Battleunit.\n */\nconst BattleUnit *BattleItem::getPreviousOwner() const\n{\n\treturn _previousOwner;\n}\n\n/**\n * Sets the item's owner.\n * @param owner Pointer to Battleunit.\n */\nvoid BattleItem::setOwner(BattleUnit *owner)\n{\n\t_previousOwner = _owner;\n\t_owner = owner;\n}\n\n/**\n * Sets the item's previous owner.\n * @param owner Pointer to Battleunit.\n */\nvoid BattleItem::setPreviousOwner(BattleUnit *owner)\n{\n\t_previousOwner = owner;\n}\n\n/**\n * Removes the item from the previous owner and moves it to the new owner.\n * @param owner Pointer to Battleunit.\n */\nvoid BattleItem::moveToOwner(BattleUnit *owner)\n{\n\tif (_tile)\n\t{\n\t\t_tile->removeItem(this);\n\t\t_tile = nullptr;\n\t}\n\tif (owner != _owner)\n\t{\n\t\tsetOwner(owner);\n\n\t\tif (_previousOwner)\n\t\t{\n\t\t\tfor (auto iter = _previousOwner->getInventory()->begin(); iter != _previousOwner->getInventory()->end(); ++iter)\n\t\t\t{\n\t\t\t\tif ((*iter) == this)\n\t\t\t\t{\n\t\t\t\t\t_previousOwner->getInventory()->erase(iter);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (_owner)\n\t\t{\n\t\t\t_owner->getInventory()->push_back(this);\n\t\t}\n\t}\n}\n\n/**\n * Gets the item's inventory slot.\n * @return The slot id.\n */\nconst RuleInventory *BattleItem::getSlot() const\n{\n\treturn _inventorySlot;\n}\n\n/**\n * Gets the cost of moving item to given slot.\n */\nint BattleItem::getMoveToCost(const RuleInventory *slot) const\n{\n\tint cost = _inventorySlot->getCost(slot);\n\tif (cost == 0)\n\t{\n\t\t// if move was free it stay free, required to prevent paying cost of move only for clicking on item in inventory\n\t\treturn 0;\n\t}\n\telse if (_inventorySlot->getType() == INV_HAND && slot->getType() == INV_GROUND)\n\t{\n\t\t// this special case has two roles:\n\t\t// * right now dropping ammo when reloading only uses default move cost, manually dropping should have same cost.\n\t\t// * conceptually you should be able to relese grip and item should fall down, \"hard to grab, easy to drop\"\n\t\treturn cost;\n\t}\n\telse\n\t{\n\t\treturn std::max(1, cost * _inventoryMoveCostPercent / 100);\n\t}\n}\n\n/**\n * Sets the item's inventory slot.\n * @param slot The slot id.\n */\nvoid BattleItem::setSlot(const RuleInventory *slot)\n{\n\t_inventorySlot = slot;\n}\n\n/**\n * Gets the item's inventory X position.\n * @return X position.\n */\nint BattleItem::getSlotX() const\n{\n\treturn _inventoryX;\n}\n\n/**\n * Sets the item's inventory X position.\n * @param x X position.\n */\nvoid BattleItem::setSlotX(int x)\n{\n\t_inventoryX = x;\n}\n\n/**\n * Gets the item's inventory Y position.\n * @return Y position.\n */\nint BattleItem::getSlotY() const\n{\n\treturn _inventoryY;\n}\n\n/**\n * Sets the item's inventory Y position.\n * @param y Y position.\n */\nvoid BattleItem::setSlotY(int y)\n{\n\t_inventoryY = y;\n}\n\n/**\n * Checks if the item is covering certain inventory slot(s).\n * @param x Slot X position.\n * @param y Slot Y position.\n * @param item Item to check for overlap, or NULL if none.\n * @return True if it is covering.\n */\nbool BattleItem::occupiesSlot(int x, int y, BattleItem *item) const\n{\n\tif (item == this || !_inventorySlot)\n\t\treturn false;\n\tif (_inventorySlot->getType() == INV_HAND)\n\t\treturn true;\n\tif (item == 0)\n\t{\n\t\treturn (x >= _inventoryX && x < _inventoryX + _rules->getInventoryWidth() &&\n\t\t\t\ty >= _inventoryY && y < _inventoryY + _rules->getInventoryHeight());\n\t}\n\telse\n\t{\n\t\treturn !(x >= _inventoryX + _rules->getInventoryWidth() ||\n\t\t\t\tx + item->getRules()->getInventoryWidth() <= _inventoryX ||\n\t\t\t\ty >= _inventoryY + _rules->getInventoryHeight() ||\n\t\t\t\ty + item->getRules()->getInventoryHeight() <= _inventoryY);\n\t}\n}\n\n/**\n * Gets the item's floor sprite.\n * @return Return current floor sprite.\n */\nconst Surface *BattleItem::getFloorSprite(const SurfaceSet *set, const SavedBattleGame *save, int animFrame, int shade) const\n{\n\tint i = _rules->getFloorSprite();\n\tif (i != -1)\n\t{\n\t\tconst Surface *surf = set->getFrame(i);\n\t\t//enforce compatibility with basic version\n\t\tif (surf == nullptr)\n\t\t{\n\t\t\tthrow Exception(\"Image missing in 'FLOOROB.PCK' for item '\" + _rules->getType() + \"'\");\n\t\t}\n\n\t\ti = ModScript::scriptFunc2<ModScript::SelectItemSprite>(\n\t\t\t_rules,\n\t\t\ti, 0,\n\t\t\tthis, save, BODYPART_ITEM_FLOOR, animFrame, shade\n\t\t);\n\t\tauto* newSurf = set->getFrame(i);\n\t\tif (newSurf == nullptr)\n\t\t{\n\t\t\tnewSurf = surf;\n\t\t}\n\t\treturn newSurf;\n\t}\n\telse\n\t{\n\t\treturn nullptr;\n\t}\n}\n\n/**\n * Gets the item's inventory sprite.\n * @return Return current inventory sprite.\n */\nconst Surface *BattleItem::getBigSprite(const SurfaceSet *set, const SavedBattleGame *save, int animFrame) const\n{\n\tint i = _rules->getBigSprite();\n\tif (i != -1)\n\t{\n\t\tconst Surface *surf = set->getFrame(i);\n\t\t//enforce compatibility with basic version\n\t\tif (surf == nullptr)\n\t\t{\n\t\t\tthrow Exception(\"Image missing in 'BIGOBS.PCK' for item '\" + _rules->getType() + \"'\");\n\t\t}\n\n\t\ti = ModScript::scriptFunc2<ModScript::SelectItemSprite>(\n\t\t\t_rules,\n\t\t\ti, 0,\n\t\t\tthis, save, BODYPART_ITEM_INVENTORY, animFrame, 0\n\t\t);\n\n\t\tauto* newSurf = set->getFrame(i);\n\t\tif (newSurf == nullptr)\n\t\t{\n\t\t\tnewSurf = surf;\n\t\t}\n\t\treturn newSurf;\n\t}\n\telse\n\t{\n\t\treturn nullptr;\n\t}\n}\n\n/**\n * Check if item use any ammo.\n * @return True if item accept ammo.\n */\nbool BattleItem::isWeaponWithAmmo() const\n{\n\treturn _isWeaponWithAmmo;\n}\n\n/**\n * Check if the weapon is loaded with any ammo item(s). IMPORTANT: ammo quantity can also be zero!\n * @return True if the weapon is loaded. IMPORTANT: empty clip also counts as a loaded weapon! empty \"built-in\" clip also counts as a loaded weapon!\n */\nbool BattleItem::haveAnyAmmo() const\n{\n\tif (!_isWeaponWithAmmo)\n\t{\n\t\treturn true;\n\t}\n\tif (_rules->getBattleType() == BT_MELEE)\n\t{\n\t\treturn getAmmoForAction(BA_HIT);\n\t}\n\telse\n\t{\n\t\treturn getAmmoForAction(BA_AIMEDSHOT) ||\n\t\t\tgetAmmoForAction(BA_AUTOSHOT) ||\n\t\t\tgetAmmoForAction(BA_SNAPSHOT);\n\t}\n}\n\n/**\n * Check if weapon have all ammo slot filled.\n * @return True if all ammo slots are fill.\n */\nbool BattleItem::haveAllAmmo() const\n{\n\tfor (const auto* a : _ammoItem)\n\t{\n\t\tif (a == nullptr)\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n}\n\n/**\n * Sets the item's ammo item.\n * @param item The ammo item.\n * @return True if item fit to weapon.\n */\nbool BattleItem::setAmmoPreMission(BattleItem *item)\n{\n\tint slot = _rules->getSlotForAmmo(item->getRules());\n\tif (slot >= 0)\n\t{\n\t\tif (_ammoItem[slot])\n\t\t\treturn false;\n\n\t\tsetAmmoForSlot(slot, item);\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\n/**\n * Get configuration of action on that item.\n * @param action Action type.\n * @return Return config of item action or nullptr for wrong action type or item.\n */\nconst RuleItemAction *BattleItem::getActionConf(BattleActionType action) const\n{\n\tswitch (action)\n\t{\n\tcase BA_LAUNCH:\n\tcase BA_AIMEDSHOT: return _confAimedOrLaunch;\n\tcase BA_AUTOSHOT: return _confAuto;\n\tcase BA_SNAPSHOT: return _confSnap;\n\tcase BA_HIT: return _confMelee;\n\tdefault: return nullptr;\n\t}\n}\n\n/**\n * Check if attack shoot in arc.\n */\nbool BattleItem::getArcingShot(BattleActionType action) const\n{\n\tif (_rules->getArcingShot())\n\t{\n\t\treturn true;\n\t}\n\n\tauto* conf = getActionConf(action);\n\tif (conf && conf->arcing)\n\t{\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\n/**\n * Determines if this item uses ammo.\n */\nbool BattleItem::needsAmmoForAction(BattleActionType action) const\n{\n\tauto* conf = getActionConf(action);\n\tif (!conf || conf->ammoSlot == RuleItem::AmmoSlotSelfUse)\n\t{\n\t\treturn false;\n\t}\n\n\treturn needsAmmoForSlot(conf->ammoSlot);\n}\n\n/**\n * Get ammo used by action.\n * @param action Battle Action done using this item.\n * @return\n */\nconst BattleItem *BattleItem::getAmmoForAction(BattleActionType action) const\n{\n\tauto* conf = getActionConf(action);\n\tif (!conf)\n\t{\n\t\treturn nullptr;\n\t}\n\tif (conf->ammoSlot == RuleItem::AmmoSlotSelfUse)\n\t{\n\t\treturn this;\n\t}\n\n\tauto* ammo = getAmmoForSlot(conf->ammoSlot);\n\tif (ammo && ammo->getAmmoQuantity() == 0 && !ammo->getRules()->isAmmoRechargeable())\n\t{\n\t\treturn nullptr;\n\t}\n\treturn ammo;\n}\n\n/**\n * Get ammo used by action.\n * @param action Battle Action done using this item.\n * @param message Error message if weapon don't have ammo.\n * @param spendPerShot How much ammo should be spent for one shot.\n * @return\n */\nBattleItem *BattleItem::getAmmoForAction(BattleActionType action, std::string* message, int* spendPerShot)\n{\n\tauto* conf = getActionConf(action);\n\tif (!conf)\n\t{\n\t\treturn nullptr;\n\t}\n\tif (spendPerShot) *spendPerShot = conf->spendPerShot;\n\tif (conf->ammoSlot == RuleItem::AmmoSlotSelfUse)\n\t{\n\t\treturn this;\n\t}\n\n\tauto* ammo = getAmmoForSlot(conf->ammoSlot);\n\tif (ammo == nullptr)\n\t{\n\t\tif (message) *message = \"STR_NO_AMMUNITION_LOADED\";\n\t\treturn nullptr;\n\t}\n\tif (ammo->getAmmoQuantity() < conf->spendPerShot)\n\t{\n\t\tif (message)\n\t\t{\n\t\t\t*message = \"STR_NO_ROUNDS_LEFT\"; // no rounds left (or not enough energy left in the battery)\n\t\t}\n\t\treturn nullptr;\n\t}\n\treturn ammo;\n}\n\n/**\n * Spend weapon ammo, if depleted remove clip.\n * @param action Battle Action done using this item.\n * @param save Save game.\n */\nvoid BattleItem::spendAmmoForAction(BattleActionType action, SavedBattleGame* save)\n{\n\tif (save->getDebugMode() || getActionConf(action)->ammoSlot == RuleItem::AmmoSlotSelfUse)\n\t{\n\t\treturn;\n\t}\n\n\tint spendPerShot = 1;\n\tauto* ammo = getAmmoForAction(action, nullptr, &spendPerShot);\n\tif (ammo)\n\t{\n\t\tif (ammo->getRules()->getClipSize() > 0 && ammo->spendBullet(spendPerShot) == false && !ammo->getRules()->isAmmoRechargeable())\n\t\t{\n\t\t\tsave->removeItem(ammo);\n\t\t\tammo->setIsAmmo(false);\n\t\t\tif (ammo != this)\n\t\t\t{\n\t\t\t\tfor (auto*& a : _ammoItem)\n\t\t\t\t{\n\t\t\t\t\tif (a == ammo)\n\t\t\t\t\t{\n\t\t\t\t\t\ta = nullptr;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Check how many shoots attack can perform.\n * @param action Attack type.\n * @param shotCount Current shot count.\n * @return True if still can shoot.\n */\nbool BattleItem::haveNextShotsForAction(BattleActionType action, int shotCount) const\n{\n\tauto* conf = getActionConf(action);\n\tif (conf)\n\t{\n\t\treturn shotCount < conf->shots;\n\t}\n\treturn false;\n}\n\n/**\n * Determines if the item uses ammo.\n * @return True if ammo is used.\n */\nbool BattleItem::needsAmmoForSlot(int slot) const\n{\n\treturn (_isWeaponWithAmmo && _ammoItem[slot] != this); // no ammo for this weapon is needed\n}\n\n/**\n * Set ammo slot with new ammo\n * @param slot Ammo slot position.\n * @param item Ammo item.\n * @return Old item if was set.\n */\nBattleItem *BattleItem::setAmmoForSlot(int slot, BattleItem* item)\n{\n\tif (!needsAmmoForSlot(slot))\n\t{\n\t\treturn nullptr;\n\t}\n\n\tBattleItem *oldItem = _ammoItem[slot];\n\tif (oldItem)\n\t{\n\t\toldItem->setIsAmmo(false);\n\t}\n\t_ammoItem[slot] = item;\n\tif (item)\n\t{\n\t\titem->moveToOwner(nullptr);\n\t\titem->setSlot(nullptr);\n\t\titem->setIsAmmo(true);\n\t}\n\treturn oldItem;\n}\n\n/**\n * Gets the item's ammo item.\n * @return The ammo item.\n */\nBattleItem *BattleItem::getAmmoForSlot(int slot)\n{\n\treturn _ammoItem[slot];\n}\n\n/**\n * Gets the item's ammo item.\n * @return The ammo item.\n */\nconst BattleItem *BattleItem::getAmmoForSlot(int slot) const\n{\n\treturn _ammoItem[slot];\n}\n\n/**\n * Get ammo count visibility for slot.\n */\nbool BattleItem::isAmmoVisibleForSlot(int slot) const\n{\n\treturn _ammoVisibility[slot];\n}\n\n/**\n * Get item weight with ammo weight.\n * @return Weight.\n */\nint BattleItem::getTotalWeight() const\n{\n\tint weight = _rules->getWeight();\n\tfor (const auto* a : _ammoItem)\n\t{\n\t\tif (a && a != this)\n\t\t{\n\t\t\tweight += a->_rules->getWeight();\n\t\t}\n\t}\n\treturn weight;\n}\n\n/**\n * Get waypoints count of weapon or from ammo.\n * @return Maximum waypoints count or -1 if unlimited.\n */\nint BattleItem::getCurrentWaypoints() const\n{\n\tint waypoints = _rules->getWaypoints();\n\tauto* ammo = getAmmoForAction(BA_LAUNCH);\n\tif (waypoints == 0 && ammo && ammo != this)\n\t{\n\t\twaypoints = ammo->_rules->getWaypoints();\n\t}\n\treturn waypoints;\n}\n\n/**\n * Gets the item's tile.\n * @return The tile.\n */\nTile *BattleItem::getTile() const\n{\n\treturn _tile;\n}\n\n/**\n * Sets the item's tile.\n * @param tile The tile.\n */\nvoid BattleItem::setTile(Tile *tile)\n{\n\t_tile = tile;\n}\n\n/**\n * Gets the item's id.\n * @return The item's id.\n */\nint BattleItem::getId() const\n{\n\treturn _id;\n}\n\n/**\n * Gets the corpse's unit.\n * @return Pointer to BattleUnit.\n */\nBattleUnit *BattleItem::getUnit()\n{\n\treturn _unit;\n}\n\n/**\n * Gets the corpse's unit.\n * @return Pointer to BattleUnit.\n */\nconst BattleUnit *BattleItem::getUnit() const\n{\n\treturn _unit;\n}\n\n/**\n * Sets the corpse's unit.\n * @param unit Pointer to BattleUnit.\n */\nvoid BattleItem::setUnit(BattleUnit *unit)\n{\n\t_unit = unit;\n}\n\n/**\n * Sets the heal quantity of the item.\n * @param heal The new heal quantity.\n */\nvoid BattleItem::setHealQuantity (int heal)\n{\n\t_heal = heal;\n}\n\n/**\n * Gets the heal quantity of the item.\n * @return The new heal quantity.\n */\nint BattleItem::getHealQuantity() const\n{\n\treturn _heal;\n}\n\n/**\n * Sets the pain killer quantity of the item.\n * @param pk The new pain killer quantity.\n */\nvoid BattleItem::setPainKillerQuantity (int pk)\n{\n\t_painKiller = pk;\n}\n\n/**\n * Gets the pain killer quantity of the item.\n * @return The new pain killer quantity.\n */\nint BattleItem::getPainKillerQuantity() const\n{\n\treturn _painKiller;\n}\n\n/**\n * Sets the stimulant quantity of the item.\n * @param stimulant The new stimulant quantity.\n */\nvoid BattleItem::setStimulantQuantity (int stimulant)\n{\n\t_stimulant = stimulant;\n}\n\n/**\n * Gets the stimulant quantity of the item.\n * @return The new stimulant quantity.\n */\nint BattleItem::getStimulantQuantity() const\n{\n\treturn _stimulant;\n}\n\n/**\n * Sets the XCom property flag. This is to determine at debriefing what goes into the base/craft.\n * @param flag True if it's XCom property.\n */\nvoid BattleItem::setXCOMProperty (bool flag)\n{\n\t_XCOMProperty = flag;\n}\n\n/**\n * Gets the XCom property flag. This is to determine at debriefing what goes into the base/craft.\n * @return True if it's XCom property.\n */\nbool BattleItem::getXCOMProperty() const\n{\n\treturn _XCOMProperty;\n}\n\n/**\n * Gets the \"dropped on non-player turn\" flag. This is to determine whether or not\n * aliens should attempt to pick this item up, as items dropped by the player may be \"honey traps\".\n * @return True if the aliens dropped the item.\n */\nbool BattleItem::getTurnFlag() const\n{\n\treturn _droppedOnAlienTurn;\n}\n\n/**\n * Sets the \"dropped on non-player turn\" flag. This is set when the item is dropped in the battlescape\n * or picked up in the inventory screen.\n * @param flag True if the aliens dropped the item.\n */\nvoid BattleItem::setTurnFlag(bool flag)\n{\n\t_droppedOnAlienTurn = flag;\n}\n\n/**\n * Converts an unconscious body into a dead one.\n * @param rules the rules of the corpse item to convert this item into.\n */\nvoid BattleItem::convertToCorpse(const RuleItem *rules)\n{\n\tif (_unit && _rules->getBattleType() == BT_CORPSE && rules->getBattleType() == BT_CORPSE)\n\t{\n\t\t_rules = rules;\n\t}\n}\n\n/**\n * Check if item can glow in darkness.\n * @return True if it glow.\n */\nbool BattleItem::getGlow() const\n{\n\tif (_rules->getBattleType() == BT_FLARE)\n\t{\n\t\treturn (_rules->getFuseTriggerEvent()->defaultBehavior && _rules->getFuseTimerType() == BFT_NONE) || (_fuseEnabled && getFuseTimer() >= 0);\n\t}\n\telse\n\t{\n\t\treturn false;\n\t}\n}\n\n/**\n * Gets range of glow in tiles.\n * @return Range.\n */\nint BattleItem::getGlowRange() const\n{\n\tauto* owner = _unit ? _unit : _previousOwner;\n\treturn _rules->getPowerBonus({ BA_NONE, owner, this, this });\n}\n\n/**\n * Gets update range needed by this item. For simplicity we always update to max range if it can glow.\n * @return Range.\n */\nint BattleItem::getVisibilityUpdateRange() const\n{\n\treturn _rules->getBattleType() == BT_FLARE ? getGlowRange() : 1;\n}\n\n/**\n * Sets the flag on this item indicating whether or not it is a clip used in a weapon.\n * @param ammo set the ammo flag to this.\n */\nvoid BattleItem::setIsAmmo(bool ammo)\n{\n\t_isAmmo = ammo;\n}\n\n/**\n * Checks if this item is loaded into a weapon.\n * @return if this is loaded into a weapon or not.\n */\nbool BattleItem::isAmmo() const\n{\n\treturn _isAmmo;\n}\n\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tScript binding\n////////////////////////////////////////////////////////////\n\nnamespace\n{\n\nstruct getAmmoForSlotScript\n{\n\tstatic RetEnum func(BattleItem *weapon, BattleItem *&ammo, int slot)\n\t{\n\t\tif (weapon && slot >= 0 && slot < RuleItem::AmmoSlotMax)\n\t\t{\n\t\t\tammo = weapon->getAmmoForSlot(slot);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tammo = nullptr;\n\t\t}\n\t\treturn RetContinue;\n\t}\n};\n\nstruct getAmmoForSlotConstScript\n{\n\tstatic RetEnum func(const BattleItem *weapon, const BattleItem *&ammo, int slot)\n\t{\n\t\tif (weapon && slot >= 0 && slot < RuleItem::AmmoSlotMax)\n\t\t{\n\t\t\tammo = weapon->getAmmoForSlot(slot);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tammo = nullptr;\n\t\t}\n\t\treturn RetContinue;\n\t}\n};\n\nstruct getAmmoItemScript\n{\n\tstatic RetEnum func(BattleItem *weapon, BattleItem *&ammo)\n\t{\n\t\treturn getAmmoForSlotScript::func(weapon, ammo, 0);\n\t}\n};\n\nstruct getAmmoItemConstScript\n{\n\tstatic RetEnum func(const BattleItem *weapon, const BattleItem *&ammo)\n\t{\n\t\treturn getAmmoForSlotConstScript::func(weapon, ammo, 0);\n\t}\n};\n\nstruct getAmmoForActionScript\n{\n\tstatic RetEnum func(BattleItem *weapon, BattleItem *&ammo, int action)\n\t{\n\t\tBattleActionType bat = (BattleActionType)action;\n\t\tif (weapon)\n\t\t{\n\t\t\tammo = weapon->getAmmoForAction(bat);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tammo = nullptr;\n\t\t}\n\t\treturn RetContinue;\n\t}\n};\n\nstruct getAmmoForActionConstScript\n{\n\tstatic RetEnum func(const BattleItem *weapon, const BattleItem *&ammo, int action)\n\t{\n\t\tBattleActionType bat = (BattleActionType)action;\n\t\tif (weapon)\n\t\t{\n\t\t\tammo = weapon->getAmmoForAction(bat);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tammo = nullptr;\n\t\t}\n\t\treturn RetContinue;\n\t}\n};\n\nstruct getRuleInventorySlotScript\n{\n\tstatic RetEnum func(const BattleItem *weapon, const RuleInventory *&inv)\n\t{\n\t\tif (weapon)\n\t\t{\n\t\t\tinv = weapon->getSlot();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tinv = nullptr;\n\t\t}\n\t\treturn RetContinue;\n\t}\n};\n\nstruct getRuleInventoryMoveToCostScript\n{\n\tstatic RetEnum func(const BattleItem *weapon, int& cost, const RuleInventory *inv)\n\t{\n\t\tif (weapon && weapon->getSlot() && inv)\n\t\t{\n\t\t\tcost = weapon->getMoveToCost(inv);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tcost = 0;\n\t\t}\n\t\treturn RetContinue;\n\t}\n};\n\nstd::string debugDisplayScript(const BattleItem* bt)\n{\n\tif (bt)\n\t{\n\t\tauto* rule = bt->getRules();\n\t\tstd::string s;\n\t\ts += BattleItem::ScriptName;\n\t\ts += \"(type: \\\"\";\n\t\ts += rule->getType();\n\t\ts += \"\\\" id: \";\n\t\ts += std::to_string(bt->getId());\n\n\t\tint clipSize = rule->getClipSize();\n\t\tif (clipSize > 0)\n\t\t{\n\t\t\ts += \" ammo: \";\n\t\t\ts += std::to_string(bt->getAmmoQuantity());\n\t\t\ts += \"/\";\n\t\t\ts += std::to_string(clipSize);\n\t\t}\n\t\ts += \")\";\n\t\treturn s;\n\t}\n\telse\n\t{\n\t\treturn \"null\";\n\t}\n}\n\nvoid getActionTUsScript(const BattleItem* bt, int& i, const BattleUnit* bu, const int battle_action)\n{\n\tBattleActionType bat = (BattleActionType)battle_action;\n\tif (bt && bu)\n\t{\n\t\ti = bu->getActionTUs(bat, bt).Time;\n\t}\n\telse\n\t{\n\t\ti = -1;\n\t}\n}\n\nvoid getFuseTimerDefaultScript(const BattleItem* bt, int& i)\n{\n\tif (bt)\n\t{\n\t\ti = bt->getRules()->getFuseTimerDefault();\n\t}\n\telse\n\t{\n\t\ti = -1;\n\t}\n}\n\nvoid setFuseTimerScript(BattleItem* bt, int i)\n{\n\tif (bt)\n\t{\n\t\tbt->setFuseTimer(Clamp(i, -1, 100));\n\t}\n}\n\nvoid setAmmoQuantityScript(BattleItem* bt, int i)\n{\n\tif (bt)\n\t{\n\t\tbt->setAmmoQuantity(Clamp(i, 1, bt->getRules()->getClipSize()));\n\t}\n}\n\nvoid setHealQuantityScript(BattleItem* bt, int i)\n{\n\tif (bt)\n\t{\n\t\tbt->setHealQuantity(Clamp(i, 0, bt->getRules()->getHealQuantity()));\n\t}\n}\n\nvoid setPainKillerQuantityScript(BattleItem* bt, int i)\n{\n\tif (bt)\n\t{\n\t\tbt->setPainKillerQuantity(Clamp(i, 0, bt->getRules()->getPainKillerQuantity()));\n\t}\n}\n\nvoid setStimulantQuantityScript(BattleItem* bt, int i)\n{\n\tif (bt)\n\t{\n\t\tbt->setStimulantQuantity(Clamp(i, 0, bt->getRules()->getStimulantQuantity()));\n\t}\n}\n\n\nvoid commonBattleItemAnimations(ScriptParserBase* parser)\n{\n\tSavedBattleGame::ScriptRegisterUnitAnimations(parser);\n}\n\n\n} // namespace\n\n/**\n * Register BattleItem in script parser.\n * @param parser Script parser.\n */\nvoid BattleItem::ScriptRegister(ScriptParserBase* parser)\n{\n\tparser->registerPointerType<Mod>();\n\tparser->registerPointerType<Tile>();\n\tparser->registerPointerType<RuleItem>();\n\tparser->registerPointerType<BattleUnit>();\n\n\tBind<BattleItem> bi = { parser };\n\n\tbi.addRules<RuleItem, &BattleItem::getRules>(\"getRuleItem\");\n\tbi.addPair<BattleUnit, &BattleItem::getUnit, &BattleItem::getUnit>(\"getBattleUnit\");\n\tbi.addFunc<getAmmoItemScript>(\"getAmmoItem\");\n\tbi.addFunc<getAmmoItemConstScript>(\"getAmmoItem\");\n\tbi.addFunc<getAmmoForSlotScript>(\"getAmmoForSlot\");\n\tbi.addFunc<getAmmoForSlotConstScript>(\"getAmmoForSlot\");\n\tbi.addFunc<getAmmoForActionScript>(\"getAmmoForAction\");\n\tbi.addFunc<getAmmoForActionConstScript>(\"getAmmoForAction\");\n\n\tbi.addFunc<getRuleInventorySlotScript>(\"getSlot\");\n\tbi.addFunc<getRuleInventoryMoveToCostScript>(\"getMoveToCost\", \"cost of moving item from slot in first arg to slot from last arg\");\n\tbi.addField<&BattleItem::_inventoryMoveCostPercent>(\"InventoryMoveCost.getBaseTimePercent\", \"InventoryMoveCost.setBaseTimePercent\");\n\n\tbi.addPair<BattleUnit, &BattleItem::getPreviousOwner, &BattleItem::getPreviousOwner>(\"getPreviousOwner\");\n\tbi.addPair<BattleUnit, &BattleItem::getOwner, &BattleItem::getOwner>(\"getOwner\");\n\tbi.add<&BattleItem::getId>(\"getId\");\n\tbi.add<&BattleItem::getGlow>(\"getGlow\");\n\tbi.add<&BattleItem::getTotalWeight>(\"getTotalWeight\");\n\tbi.add<&BattleItem::isAmmo>(\"isAmmo\");\n\tbi.add<&BattleItem::isSpecialWeapon>(\"isSpecialWeapon\");\n\n\tbi.add<&BattleItem::getRules, &RuleItem::getClipSize>(\"getAmmoQuantityMax\");\n\tbi.add<&BattleItem::getAmmoQuantity>(\"getAmmoQuantity\");\n\tbi.add<&setAmmoQuantityScript>(\"setAmmoQuantity\");\n\n\tbi.add<&BattleItem::getFuseTimer>(\"getFuseTimer\");\n\tbi.add<&getFuseTimerDefaultScript>(\"getFuseTimerDefault\", \"get default fuse timer\");\n\tbi.add<&setFuseTimerScript>(\"setFuseTimer\", \"set item fuse timer, -1 mean disable it\");\n\n\tbi.add<&BattleItem::isFuseEnabled>(\"isFuseEnabled\", \"check if fuse is triggered (like throw or proxy unit)\");\n\tbi.add<&BattleItem::setFuseEnabled>(\"setFuseEnabled\", \"force set or unset fuse trigger state\");\n\n\tbi.add<&BattleItem::getHealQuantity>(\"getHealQuantity\");\n\tbi.add<&setHealQuantityScript>(\"setHealQuantity\");\n\n\tbi.add<&BattleItem::getPainKillerQuantity>(\"getPainKillerQuantity\");\n\tbi.add<&setPainKillerQuantityScript>(\"setPainKillerQuantity\");\n\n\tbi.add<&BattleItem::getStimulantQuantity>(\"getStimulantQuantity\");\n\tbi.add<&setStimulantQuantityScript>(\"setStimulantQuantity\");\n\n\tbi.add<&getActionTUsScript>(\"getActionCost.getTimeUnits\");\n\n\tbi.addScriptValue<BindBase::OnlyGet, &BattleItem::_rules, &RuleItem::getScriptValuesRaw>();\n\tbi.addScriptValue<&BattleItem::_scriptValues>();\n\tbi.addDebugDisplay<&debugDisplayScript>();\n\n\tbi.addCustomConst(\"BA_AUTOSHOT\", BA_AUTOSHOT);\n\tbi.addCustomConst(\"BA_SNAPSHOT\", BA_SNAPSHOT);\n\tbi.addCustomConst(\"BA_AIMEDSHOT\", BA_AIMEDSHOT);\n\tbi.addCustomConst(\"BA_LAUNCH\", BA_LAUNCH);\n\tbi.addCustomConst(\"BA_HIT\", BA_HIT);\n\tbi.addCustomConst(\"BA_USE\", BA_USE);\n\tbi.addCustomConst(\"BA_THROW\", BA_THROW);\n\tbi.addCustomConst(\"BA_MINDCONTROL\", BA_MINDCONTROL);\n\tbi.addCustomConst(\"BA_PANIC\", BA_PANIC);\n\tbi.addCustomConst(\"BA_PRIME\", BA_PRIME);\n\tbi.addCustomConst(\"BA_UNPRIME\", BA_UNPRIME);\n\tbi.addCustomConst(\"BA_NONE\", BA_NONE);\n\tbi.addCustomConst(\"BA_TRIGGER_TIMED_GRENADE\", BA_TRIGGER_TIMED_GRENADE);\n\tbi.addCustomConst(\"BA_TRIGGER_PROXY_GRENADE\", BA_TRIGGER_PROXY_GRENADE);\n}\n\nnamespace\n{\n\nvoid commonImpl(BindBase& b, Mod* mod)\n{\n\tb.addCustomPtr<const Mod>(\"rules\", mod);\n\n\tb.addCustomConst(\"blit_item_righthand\", BODYPART_ITEM_RIGHTHAND);\n\tb.addCustomConst(\"blit_item_lefthand\", BODYPART_ITEM_LEFTHAND);\n\tb.addCustomConst(\"blit_item_floor\", BODYPART_ITEM_FLOOR);\n\tb.addCustomConst(\"blit_item_big\", BODYPART_ITEM_INVENTORY);\n}\n\n}\n\n/**\n * Constructor of recolor script parser.\n */\nModScript::RecolorItemParser::RecolorItemParser(ScriptGlobal* shared, const std::string& name, Mod* mod) : ScriptParserEvents{ shared, name,\n\t\"new_pixel\",\n\t\"old_pixel\",\n\n\t\"item\", \"battle_game\", \"blit_part\", \"anim_frame\", \"shade\" }\n{\n\tBindBase b { this };\n\n\tcommonImpl(b, mod);\n\tcommonBattleItemAnimations(this);\n\n\tsetDefault(\"add_shade new_pixel shade; return new_pixel;\");\n}\n\n/**\n * Constructor of select sprite script parser.\n */\nModScript::SelectItemParser::SelectItemParser(ScriptGlobal* shared, const std::string& name, Mod* mod) : ScriptParserEvents{ shared, name,\n\t\"sprite_index\",\n\t\"sprite_offset\",\n\n\t\"item\", \"battle_game\", \"blit_part\", \"anim_frame\", \"shade\" }\n{\n\tBindBase b { this };\n\n\tcommonImpl(b, mod);\n\tcommonBattleItemAnimations(this);\n\n\tsetDefault(\"add sprite_index sprite_offset; return sprite_index;\");\n}\n\nModScript::VaporParticleBaseParser::VaporParticleBaseParser(ScriptGlobal* shared, const std::string& name, Mod* mod) : ScriptParser{ shared, name,\n\t\"vapor_color\",\n\t\"subvoxel_offset\",\n\t\"subvoxel_velocity\",\n\t\"subvoxel_acceleration\",\n\t\"subvoxel_drift\",\n\t\"particle_density\",\n\t\"particle_lifetime\",\n\t\"particle_number\",\n\n\t\"weapon\", \"ammo\", \"particle_number_max\", \"subvoxel_trajectory_distance\", \"subvoxel_trajectory_distance_max\", \"subvoxel_trajectory_forward\", \"subvoxel_trajectory_right\", \"subvoxel_trajectory_up\", \"random\" }\n{\n\tBindBase b { this };\n\n\tb.addCustomPtr<const Mod>(\"rules\", mod);\n\tb.addCustomConst(\"subvoxel_scale\", Particle::SubVoxelAccuracy);\n\n\tsetEmptyReturn();\n\tsetDescription(\"alter default behavior of vapor particle\");\n}\n\nModScript::VaporParticleAmmoParser::VaporParticleAmmoParser(ScriptGlobal* shared, const std::string& name, Mod* mod) : VaporParticleBaseParser(shared, name, mod)\n{\n\tsetDescription(\"alter default behavior of vapor particle from ammo\");\n\tsetDefault(\n\t\t\"var int temp;\\n\"\n\t\t\"var int randMax;\\n\"\n\n\t\t\"set randMax subvoxel_scale;\\n\"\n\t\t\"muldiv randMax 3 2;\\n\"\n\n\n\t\t\"random.randomRangeSymmetric temp randMax;\\n\"\n\t\t\"subvoxel_offset.setX temp;\\n\"\n\t\t\"random.randomRangeSymmetric temp randMax;\\n\"\n\t\t\"subvoxel_offset.setY temp;\\n\"\n\t\t\"random.randomRangeSymmetric temp randMax;\\n\"\n\t\t\"subvoxel_offset.setZ temp;\\n\"\n\n\t\t\"set temp 320;\\n\"\n\t\t\"sub temp particle_density;\\n\"\n\t\t\"subvoxel_velocity.setZ temp;\\n\"\n\n\t\t\"return;\"\n\t);\n}\n\nModScript::VaporParticleWeaponParser::VaporParticleWeaponParser(ScriptGlobal* shared, const std::string& name, Mod* mod) : VaporParticleBaseParser(shared, name, mod)\n{\n\tsetDescription(\"alter default behavior of vapor particle from firing weapon\");\n}\n\n\nModScript::CreateItemParser::CreateItemParser(ScriptGlobal* shared, const std::string& name, Mod* mod) : ScriptParserEvents{ shared, name, \"item\", \"unit\", \"battle_game\", \"turn\", }\n{\n\tBindBase b { this };\n\n\tb.addCustomPtr<const Mod>(\"rules\", mod);\n}\n\nModScript::NewTurnItemParser::NewTurnItemParser(ScriptGlobal* shared, const std::string& name, Mod* mod) : ScriptParserEvents{ shared, name, \"item\", \"battle_game\", \"turn\", \"side\", }\n{\n\tBindBase b { this };\n\n\tb.addCustomPtr<const Mod>(\"rules\", mod);\n}\n\nModScript::TryPsiAttackItemParser::TryPsiAttackItemParser(ScriptGlobal* shared, const std::string& name, Mod* mod) : ScriptParserEvents{ shared, name,\n\t\"psi_attack_success\",\n\n\t\"item\",\n\t\"attacker\",\n\t\"victim\",\n\t\"skill\",\n\t\"attack_strength\",\n\t\"defense_strength\",\n\t\"battle_action\",\n\t\"random\",\n\t\"distance\",\n\t\"distance_strength_reduction\",\n\t\"battle_game\",\n}\n{\n\tBindBase b { this };\n\n\tb.addCustomPtr<const Mod>(\"rules\", mod);\n\n\tsetDefault(\"var int r; random.randomRange r 0 55; add psi_attack_success attack_strength; add psi_attack_success r; sub psi_attack_success defense_strength; sub psi_attack_success distance_strength_reduction; return psi_attack_success;\");\n}\n\nModScript::TryMeleeAttackItemParser::TryMeleeAttackItemParser(ScriptGlobal* shared, const std::string& name, Mod* mod) : ScriptParserEvents{ shared, name,\n\t\"melee_attack_success\",\n\n\t\"item\",\n\t\"attacker\",\n\t\"victim\",\n\t\"skill\",\n\t\"attack_strength\",\n\t\"defense_strength\",\n\t\"battle_action\",\n\t\"random\",\n\t\"arc_to_attacker\",\n\t\"defense_strength_penalty\",\n\t\"battle_game\",\n}\n{\n\tBindBase b { this };\n\n\tb.addCustomPtr<const Mod>(\"rules\", mod);\n\n\tsetDefault(\n\t\t\"var int r;\\n\"\n\t\t\"random.randomRange r 0 99;\\n\"\n\t\t\"sub melee_attack_success r;\\n\"\n\t\t\"add melee_attack_success attack_strength;\\n\"\n\t\t\"sub melee_attack_success defense_strength;\\n\"\n\t\t\"add melee_attack_success defense_strength_penalty;\\n\"\n\t\t\"return melee_attack_success;\\n\"\n\t);\n}\n\nModScript::SellCostItemParser::SellCostItemParser(ScriptGlobal* shared, const std::string& name, Mod* mod) : ScriptParserEvents{ shared, name,\n\t\"cost_current\",\n\t\"cost_base\",\n\n\t\"item_rule\",\n\t\"geoscape_game\",\n\t\"difficulty_coefficient\"\n}\n{\n\tBindBase b { this };\n\n\tb.addCustomPtr<const Mod>(\"rules\", mod);\n}\nModScript::BuyCostItemParser::BuyCostItemParser(ScriptGlobal* shared, const std::string& name, Mod* mod) : ScriptParserEvents{ shared, name,\n\t\"cost_current\",\n\t\"cost_base\",\n\n\t\"item_rule\",\n\t\"geoscape_game\",\n\t\"difficulty_coefficient\"\n}\n{\n\tBindBase b { this };\n\n\tb.addCustomPtr<const Mod>(\"rules\", mod);\n}\n\n/**\n * Init all required data in script using object data.\n */\nvoid BattleItem::ScriptFill(ScriptWorkerBlit* w, const BattleItem* item, const SavedBattleGame* save, int part, int anim_frame, int shade)\n{\n\tw->clear();\n\tif(item)\n\t{\n\t\tconst auto& scr = item->getRules()->getScript<ModScript::RecolorItemSprite>();\n\t\tif (scr)\n\t\t{\n\t\t\tw->update(scr, item, save, part, anim_frame, shade);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tBattleUnit::ScriptFill(w, item->getUnit(), save, part, anim_frame, shade, 0);\n\t\t}\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Savegame/BattleItem.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/Yaml.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"../Engine/Script.h\"\n\nnamespace OpenXcom\n{\n\nclass RuleItem;\nclass RuleInventory;\nclass BattleUnit;\nclass Tile;\nclass Mod;\nclass SurfaceSet;\nclass Surface;\nclass ScriptWorkerBlit;\nclass ScriptParserBase;\nclass SavedBattleGame;\nstruct RuleItemAction;\n\nenum BattleActionType : Uint8;\n\n/**\n * Represents a single item in the battlescape.\n * Contains battle-related info about an item like the position, ammo quantity, ...\n * @sa RuleItem\n * @sa Item\n */\nclass BattleItem\n{\nprivate:\n\tint _id;\n\tconst RuleItem *_rules;\n\tBattleUnit *_owner, *_previousOwner;\n\tBattleUnit *_unit;\n\tTile *_tile;\n\tint _inventoryMoveCostPercent = 0;\n\tconst RuleInventory *_inventorySlot;\n\tint _inventoryX, _inventoryY;\n\tBattleItem *_ammoItem[RuleItem::AmmoSlotMax] = { };\n\tbool _ammoVisibility[RuleItem::AmmoSlotMax] = { };\n\tint _fuseTimer, _ammoQuantity;\n\tint _painKiller, _heal, _stimulant;\n\tbool _XCOMProperty, _droppedOnAlienTurn, _isAmmo, _isWeaponWithAmmo, _fuseEnabled;\n\tconst RuleItemAction *_confAimedOrLaunch = nullptr;\n\tconst RuleItemAction *_confSnap = nullptr;\n\tconst RuleItemAction *_confAuto = nullptr;\n\tconst RuleItemAction *_confMelee = nullptr;\n\tScriptValues<BattleItem> _scriptValues;\n\npublic:\n\n\t/// Name of class used in script.\n\tstatic constexpr const char *ScriptName = \"BattleItem\";\n\t/// Register all useful function used by script.\n\tstatic void ScriptRegister(ScriptParserBase* parser);\n\t/// Init all required data in script using object data.\n\tstatic void ScriptFill(ScriptWorkerBlit* w, const BattleItem* item, const SavedBattleGame* save, int part, int anim_frame, int shade);\n\n\t/// Creates a item of the specified type.\n\tBattleItem(const RuleItem *rules, int *id);\n\t/// Cleans up the item.\n\t~BattleItem();\n\t/// Loads the item from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader, Mod *mod, const ScriptGlobal *shared);\n\t/// Saves the item to YAML.\n\tvoid save(YAML::YamlNodeWriter writer, const ScriptGlobal *shared) const;\n\t/// Gets the item's ruleset.\n\tconst RuleItem *getRules() const;\n\t/// Gets the item's ammo quantity\n\tint getAmmoQuantity() const;\n\t/// Sets the item's ammo quantity.\n\tvoid setAmmoQuantity(int qty);\n\n\t/// Gets the turn until explosion\n\tint getFuseTimer() const;\n\t/// Sets the turns until explosion.\n\tvoid setFuseTimer(int turns);\n\t/// Gets if fuse was triggered.\n\tbool isFuseEnabled() const;\n\t/// Set fuse trigger.\n\tvoid setFuseEnabled(bool enable);\n\t/// Called on end of turn is triggered.\n\tvoid fuseEndTurnUpdate();\n\t/// Get if item can trigger end of turn effect.\n\tbool fuseTimeEvent();\n\t/// Called when item fuse is triggered on throw.\n\tbool fuseThrowEvent();\n\t/// Called when item fuse is triggered on throw.\n\tbool fuseProximityEvent();\n\n\t/// Spend one bullet. (Or spend a given amount of energy from a battery.)\n\tbool spendBullet(int spendPerShot);\n\n\t/// Check if owner is removed from game.\n\tbool isOwnerIgnored() const;\n\t/// Gets the item's owner.\n\tBattleUnit *getOwner();\n\t/// Gets the item's owner.\n\tconst BattleUnit *getOwner() const;\n\t/// Gets the item's previous owner.\n\tBattleUnit *getPreviousOwner();\n\t/// Gets the item's previous owner.\n\tconst BattleUnit *getPreviousOwner() const;\n\t/// Sets the owner.\n\tvoid setOwner(BattleUnit *owner);\n\t/// Sets the item's previous owner.\n\tvoid setPreviousOwner(BattleUnit *owner);\n\t/// Removes the item from previous owner and moves to new owner.\n\tvoid moveToOwner(BattleUnit *owner);\n\n\t/// Checks if the item is a special built-in weapon (outside of the inventory).\n\tbool isSpecialWeapon() const { return getOwner() && !getSlot(); }\n\t/// Gets the item's inventory slot.\n\tconst RuleInventory *getSlot() const;\n\t/// Gets the cost of moving item to given slot.\n\tint getMoveToCost(const RuleInventory *slot) const;\n\t/// Sets the item's inventory slot.\n\tvoid setSlot(const RuleInventory *slot);\n\t/// Gets the item's inventory X position.\n\tint getSlotX() const;\n\t/// Sets the item's inventory X position.\n\tvoid setSlotX(int x);\n\t/// Gets the item's inventory Y position.\n\tint getSlotY() const;\n\t/// Sets the item's inventory Y position.\n\tvoid setSlotY(int y);\n\t/// Checks if the item is occupying a slot.\n\tbool occupiesSlot(int x, int y, BattleItem *item = 0) const;\n\t/// Gets the item's floor sprite.\n\tconst Surface *getFloorSprite(const SurfaceSet *set, const SavedBattleGame *save, int animFrame, int shade) const;\n\t/// Gets the item's inventory sprite.\n\tconst Surface *getBigSprite(const SurfaceSet *set, const SavedBattleGame *save, int animFrame) const;\n\n\t/// Check if item can use any ammo.\n\tbool isWeaponWithAmmo() const;\n\t/// Check if the weapon is loaded with any ammo item(s). IMPORTANT: ammo quantity can also be zero!\n\tbool haveAnyAmmo() const;\n\t/// Check if weapon have all ammo slot filled.\n\tbool haveAllAmmo() const;\n\t/// Sets the item's ammo item based on it type.\n\tbool setAmmoPreMission(BattleItem *item);\n\t/// Get ammo slot for action.\n\tconst RuleItemAction *getActionConf(BattleActionType action) const;\n\t/// Check if attack shoot in arc.\n\tbool getArcingShot(BattleActionType action) const;\n\t/// Determines if this item uses ammo.\n\tbool needsAmmoForAction(BattleActionType action) const;\n\t/// Get ammo for action.\n\tconst BattleItem *getAmmoForAction(BattleActionType action) const;\n\t/// Get ammo for action.\n\tBattleItem *getAmmoForAction(BattleActionType action, std::string* message = nullptr, int* spendPerShot = nullptr);\n\t/// Spend weapon ammo.\n\tvoid spendAmmoForAction(BattleActionType action, SavedBattleGame *save);\n\t/// Spend one quantity of a healing item use\n\tvoid spendHealingItemUse(BattleMediKitAction mediKitAction);\n\t/// How many auto shots does this weapon fire.\n\tbool haveNextShotsForAction(BattleActionType action, int shotCount) const;\n\t/// Determines if this item uses ammo.\n\tbool needsAmmoForSlot(int slot) const;\n\t/// Set the item's ammo slot.\n\tBattleItem *setAmmoForSlot(int slot, BattleItem *item);\n\t/// Gets the item's ammo item.\n\tBattleItem *getAmmoForSlot(int slot);\n\t/// Gets the item's ammo item.\n\tconst BattleItem *getAmmoForSlot(int slot) const;\n\t/// Get ammo count visibility for slot.\n\tbool isAmmoVisibleForSlot(int slot) const;\n\t/// Get total weight (with ammo).\n\tint getTotalWeight() const;\n\t/// Get waypoints count.\n\tint getCurrentWaypoints() const;\n\n\t/// Gets the item's tile.\n\tTile *getTile() const;\n\t/// Sets the tile.\n\tvoid setTile(Tile *tile);\n\t/// Gets it's unique id.\n\tint getId() const;\n\t/// Gets the corpse's unit.\n\tBattleUnit *getUnit();\n\t/// Gets the corpse's unit.\n\tconst BattleUnit *getUnit() const;\n\t/// Sets the corpse's unit.\n\tvoid setUnit(BattleUnit *unit);\n\t/// Set medikit Heal quantity\n\tvoid setHealQuantity (int heal);\n\t/// Get medikit heal quantity\n\tint getHealQuantity() const;\n\t/// Set medikit pain killers quantity\n\tvoid setPainKillerQuantity (int pk);\n\t/// Get medikit pain killers quantity\n\tint getPainKillerQuantity() const;\n\t/// Set medikit stimulant quantity\n\tvoid setStimulantQuantity (int stimulant);\n\t/// Get medikit stimulant quantity\n\tint getStimulantQuantity() const;\n\t/// Set xcom property flag\n\tvoid setXCOMProperty (bool flag);\n\t/// Get xcom property flag\n\tbool getXCOMProperty() const;\n\t/// get the flag representing \"not dropped on player turn\"\n\tbool getTurnFlag() const;\n\t/// set the flag representing \"not dropped on player turn\"\n\tvoid setTurnFlag(bool flag);\n\t/// Sets the item's ruleset.\n\tvoid convertToCorpse(const RuleItem *rules);\n\t/// Get if item can glow.\n\tbool getGlow() const;\n\t/// Gets range of glow in tiles.\n\tint getGlowRange() const;\n\t/// Calculate range need to be updated by changing this weapon.\n\tint getVisibilityUpdateRange() const;\n\t/// Sets a flag on the item indicating if this is a clip in a weapon or not.\n\tvoid setIsAmmo(bool ammo);\n\t/// Checks a flag on the item to see if it's a clip in a weapon or not.\n\tbool isAmmo() const;\n};\n\n}\n"
  },
  {
    "path": "src/Savegame/BattleUnit.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"BattleUnit.h\"\n#include \"BattleItem.h\"\n#include <sstream>\n#include <algorithm>\n#include \"../Engine/Collections.h\"\n#include \"../Engine/Surface.h\"\n#include \"../Engine/Script.h\"\n#include \"../Engine/ScriptBind.h\"\n#include \"../Engine/Language.h\"\n#include \"../Engine/Exception.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/RNG.h\"\n#include \"../Battlescape/Pathfinding.h\"\n#include \"../Battlescape/BattlescapeGame.h\"\n#include \"../Battlescape/AIModule.h\"\n#include \"../Battlescape/Inventory.h\"\n#include \"../Battlescape/TileEngine.h\"\n#include \"../Battlescape/ExplosionBState.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Mod/Unit.h\"\n#include \"../Mod/RuleEnviroEffects.h\"\n#include \"../Mod/RuleInventory.h\"\n#include \"../Mod/RuleItemCategory.h\"\n#include \"../Mod/RuleSkill.h\"\n#include \"../Mod/RuleSoldier.h\"\n#include \"../Mod/RuleSoldierBonus.h\"\n#include \"../Mod/RuleStartingCondition.h\"\n#include \"Soldier.h\"\n#include \"Tile.h\"\n#include \"SavedGame.h\"\n#include \"SavedBattleGame.h\"\n#include \"../Engine/ShaderDraw.h\"\n#include \"BattleUnitStatistics.h\"\n#include \"../fmath.h\"\n#include \"../fallthrough.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes a BattleUnit from a Soldier\n * @param soldier Pointer to the Soldier.\n * @param depth the depth of the battlefield (used to determine movement type in case of MT_FLOAT).\n */\nBattleUnit::BattleUnit(const Mod *mod, Soldier *soldier, int depth, const RuleStartingCondition* sc) :\n\t_faction(FACTION_PLAYER), _originalFaction(FACTION_PLAYER), _killedBy(FACTION_PLAYER), _id(0), _tile(0),\n\t_lastPos(Position()), _direction(0), _toDirection(0), _directionTurret(0), _toDirectionTurret(0),\n\t_verticalDirection(0), _status(STATUS_STANDING), _wantsToSurrender(false), _isSurrendering(false), _walkPhase(0), _fallPhase(0), _kneeled(false), _floating(false),\n\t_dontReselect(false), _aiMedikitUsed(false), _fire(0), _currentAIState(0), _visible(false),\n\t_exp{ }, _expTmp{ },\n\t_motionPoints(0), _scannedTurn(-1), _customMarker(0), _kills(0), _hitByFire(false), _hitByAnything(false), _alreadyExploded(false), _fireMaxHit(0), _smokeMaxHit(0),\n\t_moraleRestored(0), _notificationShown(0), _charging(0),\n\t_statistics(), _murdererId(0), _mindControllerID(0), _fatalShotSide(SIDE_FRONT), _fatalShotBodyPart(BODYPART_HEAD), _armor(0),\n\t_geoscapeSoldier(soldier), _unitRules(0), _rankInt(0), _turretType(-1), _hidingForTurn(false), _floorAbove(false), _respawn(false), _alreadyRespawned(false),\n\t_isLeeroyJenkins(false), _summonedPlayerUnit(false), _resummonedFakeCivilian(false), _pickUpWeaponsMoreActively(false), _disableIndicators(false),\n\t_capturable(true), _vip(false), _bannedInNextStage(false), _skillMenuCheck(false)\n{\n\t_name = soldier->getName(true);\n\t_id = soldier->getId();\n\n\t_type = \"SOLDIER\";\n\t_rank = soldier->getRankString();\n\t_gender = soldier->getGender();\n\t_intelligence = 2;\n\t_aggression = 1;\n\t_faceDirection = -1;\n\t_floorAbove = false;\n\t_breathing = false;\n\n\tint rankbonus = 0;\n\n\tswitch (soldier->getRank())\n\t{\n\tcase RANK_SERGEANT:  rankbonus =  1; break;\n\tcase RANK_CAPTAIN:   rankbonus =  3; break;\n\tcase RANK_COLONEL:   rankbonus =  6; break;\n\tcase RANK_COMMANDER: rankbonus = 10; break;\n\tdefault:             rankbonus =  0; break;\n\t}\n\n\t_value = soldier->getRules()->getValue() + soldier->getMissions() + rankbonus;\n\n\n\tfor (int i = 0; i < BODYPART_MAX; ++i)\n\t\t_fatalWounds[i] = 0;\n\tfor (int i = 0; i < SPEC_WEAPON_MAX; ++i)\n\t\t_specWeapon[i] = 0;\n\n\t_activeHand = \"STR_RIGHT_HAND\";\n\t_preferredHandForReactions = \"\";\n\n\tlastCover = TileEngine::invalid;\n\n\t_statistics = new BattleUnitStatistics();\n\n\tderiveSoldierRank();\n\n\tupdateArmorFromSoldier(mod, soldier, soldier->getArmor(), depth, false, sc);\n\n\t// soldier bonus cache was built above in updateArmorFromSoldier(), so we can also calculate this now\n\tif (_geoscapeSoldier)\n\t{\n\t\tfor (auto* skill : _geoscapeSoldier->getRules()->getSkills())\n\t\t{\n\t\t\tif (_geoscapeSoldier->hasAllRequiredBonusesForSkill(skill)\n\t\t\t\t&& (skill->getCost().Time > 0 || skill->getCost().Mana > 0)\n\t\t\t\t&& (!skill->isPsiRequired() || getBaseStats()->psiSkill > 0))\n\t\t\t{\n\t\t\t\t_skillMenuCheck = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Updates BattleUnit's armor and related attributes (after a change/transformation of armor).\n * @param soldier Pointer to the Geoscape Soldier.\n * @param ruleArmor Pointer to the new Armor ruleset.\n * @param depth The depth of the battlefield.\n */\nvoid BattleUnit::updateArmorFromSoldier(const Mod *mod, Soldier *soldier, const Armor *ruleArmor, int depth, bool nextStage, const RuleStartingCondition* sc)\n{\n\t_armor = ruleArmor;\n\n\t_standHeight = _armor->getStandHeight() == -1 ? soldier->getRules()->getStandHeight() : _armor->getStandHeight();\n\t_kneelHeight = _armor->getKneelHeight() == -1 ? soldier->getRules()->getKneelHeight() : _armor->getKneelHeight();\n\t_floatHeight = _armor->getFloatHeight() == -1 ? soldier->getRules()->getFloatHeight() : _armor->getFloatHeight();\n\t_loftempsSet = _armor->getLoftempsSet();\n\n\t_specab = (SpecialAbility)_armor->getSpecialAbility();\n\n\t_originalMovementType = _movementType = _armor->getMovementTypeByDepth(depth);\n\t_moveCostBase = _armor->getMoveCostBase();\n\t_moveCostBaseFly = _armor->getMoveCostBaseFly();\n\t_moveCostBaseClimb = _armor->getMoveCostBaseClimb();\n\t_moveCostBaseNormal = _armor->getMoveCostBaseNormal();\n\n\n\t_stats = *soldier->getCurrentStats();\n\t// armor and soldier bonuses may modify effective stats\n\t{\n\t\tsoldier->prepareStatsWithBonuses(mod); // refresh needed, because of armor stats\n\t\t_stats = *soldier->getStatsWithAllBonuses();\n\t}\n\n\tint visibilityDarkBonus = 0;\n\tint visibilityDayBonus = 0;\n\tint psiVision = 0;\n\tint bonusVisibilityThroughSmoke =  0;\n\tint bonusVisibilityThroughFire = 0;\n\tfor (const auto* bonusRule : *soldier->getBonuses(nullptr))\n\t{\n\t\tvisibilityDarkBonus += bonusRule->getVisibilityAtDark();\n\t\tvisibilityDayBonus += bonusRule->getVisibilityAtDay();\n\t\tpsiVision += bonusRule->getPsiVision();\n\t\tbonusVisibilityThroughSmoke += bonusRule->getVisibilityThroughSmoke();\n\t\tbonusVisibilityThroughFire += bonusRule->getVisibilityThroughFire();\n\t}\n\t_maxViewDistanceAtDark = _armor->getVisibilityAtDark() ? _armor->getVisibilityAtDark() : 9;\n\t_maxViewDistanceAtDark = Clamp(_maxViewDistanceAtDark + visibilityDarkBonus, 1, mod->getMaxViewDistance());\n\t_maxViewDistanceAtDarkSquared = _maxViewDistanceAtDark * _maxViewDistanceAtDark;\n\t_maxViewDistanceAtDay = _armor->getVisibilityAtDay() ? _armor->getVisibilityAtDay() : mod->getMaxViewDistance();\n\t_maxViewDistanceAtDay = Clamp(_maxViewDistanceAtDay + visibilityDayBonus, 1, mod->getMaxViewDistance());\n\t_psiVision = _armor->getPsiVision() + psiVision;\n\t_visibilityThroughSmoke = _armor->getVisibilityThroughSmoke() + bonusVisibilityThroughSmoke;\n\t_visibilityThroughFire = _armor->getVisibilityThroughFire() + bonusVisibilityThroughFire;\n\n\n\t_maxArmor[SIDE_FRONT] = _armor->getFrontArmor();\n\t_maxArmor[SIDE_LEFT] = _armor->getLeftSideArmor();\n\t_maxArmor[SIDE_RIGHT] = _armor->getRightSideArmor();\n\t_maxArmor[SIDE_REAR] = _armor->getRearArmor();\n\t_maxArmor[SIDE_UNDER] = _armor->getUnderArmor();\n\t{\n\t\tfor (const auto* bonusRule : *soldier->getBonuses(nullptr))\n\t\t{\n\t\t\t_maxArmor[SIDE_FRONT] += bonusRule->getFrontArmor();\n\t\t\t_maxArmor[SIDE_LEFT]  += bonusRule->getLeftSideArmor();\n\t\t\t_maxArmor[SIDE_RIGHT] += bonusRule->getRightSideArmor();\n\t\t\t_maxArmor[SIDE_REAR]  += bonusRule->getRearArmor();\n\t\t\t_maxArmor[SIDE_UNDER] += bonusRule->getUnderArmor();\n\t\t}\n\t\t_maxArmor[SIDE_FRONT] = std::max(0, _maxArmor[SIDE_FRONT]);\n\t\t_maxArmor[SIDE_LEFT]  = std::max(0, _maxArmor[SIDE_LEFT]);\n\t\t_maxArmor[SIDE_RIGHT] = std::max(0, _maxArmor[SIDE_RIGHT]);\n\t\t_maxArmor[SIDE_REAR]  = std::max(0, _maxArmor[SIDE_REAR]);\n\t\t_maxArmor[SIDE_UNDER] = std::max(0, _maxArmor[SIDE_UNDER]);\n\t}\n\t_currentArmor[SIDE_FRONT] = _maxArmor[SIDE_FRONT];\n\t_currentArmor[SIDE_LEFT] = _maxArmor[SIDE_LEFT];\n\t_currentArmor[SIDE_RIGHT] = _maxArmor[SIDE_RIGHT];\n\t_currentArmor[SIDE_REAR] = _maxArmor[SIDE_REAR];\n\t_currentArmor[SIDE_UNDER] = _maxArmor[SIDE_UNDER];\n\n\n\tif (_armor->drawBubbles())\n\t{\n\t\t_breathFrame = 0;\n\t}\n\telse\n\t{\n\t\t_breathFrame = -1;\n\t}\n\n\t_tu = _stats.tu;\n\t_energy = _stats.stamina;\n\tif (nextStage)\n\t{\n\t\t_health = std::min(_health, (int)_stats.health);\n\t\t_mana = std::min(_mana, (int)_stats.mana);\n\t}\n\telse\n\t{\n\t\t_health = std::max(1, _stats.health - soldier->getHealthMissing());\n\t\t_mana = std::max(0, _stats.mana - soldier->getManaMissing());\n\t\t_morale = 100;\n\t\t_stunlevel = 0;\n\n\t\t// wounded soldiers (defending the base) start with lowered morale\n\t\t{\n\t\t\tif (soldier->isWounded())\n\t\t\t{\n\t\t\t\t_morale = 75;\n\t\t\t\t_health = std::max(1, _health - soldier->getWoundRecoveryInt());\n\t\t\t}\n\t\t}\n\t}\n\n\tint look = soldier->getGender() + 2 * soldier->getLook() + 8 * soldier->getLookVariant();\n\tsetRecolor(look, look, _rankIntUnified);\n\n\tprepareUnitSounds();\n\tprepareUnitResponseSounds(mod);\n\tprepareBannedFlag(sc);\n}\n\n/**\n * Helper function preparing unit sounds.\n */\nvoid BattleUnit::prepareUnitSounds()\n{\n\t_lastReloadSound = Mod::ITEM_RELOAD;\n\n\tif (_geoscapeSoldier)\n\t{\n\t\tCollections::removeAll(_aggroSound);\n\t\t_moveSound = _armor->getMoveSound() != Mod::NO_SOUND ? _armor->getMoveSound() : Mod::NO_SOUND; // there's no soldier move sound, thus hardcoded -1\n\t}\n\telse if (_unitRules)\n\t{\n\t\t_aggroSound = _unitRules->getAggroSounds();\n\t\t_moveSound = _armor->getMoveSound() != Mod::NO_SOUND ? _armor->getMoveSound() : _unitRules->getMoveSound();\n\t}\n\n\t// lower priority: soldier type / unit type\n\tif (_geoscapeSoldier)\n\t{\n\t\tauto soldierRules = _geoscapeSoldier->getRules();\n\t\tif (_gender == GENDER_MALE)\n\t\t\t_deathSound = soldierRules->getMaleDeathSounds();\n\t\telse\n\t\t\t_deathSound = soldierRules->getFemaleDeathSounds();\n\t}\n\telse if (_unitRules)\n\t{\n\t\t_deathSound = _unitRules->getDeathSounds();\n\t}\n\n\t// higher priority: armor\n\tif (_gender == GENDER_MALE)\n\t{\n\t\tif (!_armor->getMaleDeathSounds().empty())\n\t\t\t_deathSound = _armor->getMaleDeathSounds();\n\t}\n\telse\n\t{\n\t\tif (!_armor->getFemaleDeathSounds().empty())\n\t\t\t_deathSound = _armor->getFemaleDeathSounds();\n\t}\n}\n\n/**\n * Helper function preparing unit response sounds.\n */\nvoid BattleUnit::prepareUnitResponseSounds(const Mod *mod)\n{\n\tif (!mod->getEnableUnitResponseSounds())\n\t\treturn;\n\n\t// custom sounds by soldier name\n\tbool custom = false;\n\tif (mod->getSelectUnitSounds().find(_name) != mod->getSelectUnitSounds().end())\n\t{\n\t\tcustom = true;\n\t\t_selectUnitSound = mod->getSelectUnitSounds().find(_name)->second;\n\t}\n\tif (mod->getStartMovingSounds().find(_name) != mod->getStartMovingSounds().end())\n\t{\n\t\tcustom = true;\n\t\t_startMovingSound = mod->getStartMovingSounds().find(_name)->second;\n\t}\n\tif (mod->getSelectWeaponSounds().find(_name) != mod->getSelectWeaponSounds().end())\n\t{\n\t\tcustom = true;\n\t\t_selectWeaponSound = mod->getSelectWeaponSounds().find(_name)->second;\n\t}\n\tif (mod->getAnnoyedSounds().find(_name) != mod->getAnnoyedSounds().end())\n\t{\n\t\tcustom = true;\n\t\t_annoyedSound = mod->getAnnoyedSounds().find(_name)->second;\n\t}\n\n\tif (custom)\n\t\treturn;\n\n\t// lower priority: soldier type / unit type\n\tif (_geoscapeSoldier)\n\t{\n\t\tauto soldierRules = _geoscapeSoldier->getRules();\n\t\tif (_gender == GENDER_MALE)\n\t\t{\n\t\t\t_selectUnitSound = soldierRules->getMaleSelectUnitSounds();\n\t\t\t_startMovingSound = soldierRules->getMaleStartMovingSounds();\n\t\t\t_selectWeaponSound = soldierRules->getMaleSelectWeaponSounds();\n\t\t\t_annoyedSound = soldierRules->getMaleAnnoyedSounds();\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_selectUnitSound = soldierRules->getFemaleSelectUnitSounds();\n\t\t\t_startMovingSound = soldierRules->getFemaleStartMovingSounds();\n\t\t\t_selectWeaponSound = soldierRules->getFemaleSelectWeaponSounds();\n\t\t\t_annoyedSound = soldierRules->getFemaleAnnoyedSounds();\n\t\t}\n\t}\n\telse if (_unitRules)\n\t{\n\t\t_selectUnitSound = _unitRules->getSelectUnitSounds();\n\t\t_startMovingSound = _unitRules->getStartMovingSounds();\n\t\t_selectWeaponSound = _unitRules->getSelectWeaponSounds();\n\t\t_annoyedSound = _unitRules->getAnnoyedSounds();\n\t}\n\n\t// higher priority: armor\n\tif (_gender == GENDER_MALE)\n\t{\n\t\tif (!_armor->getMaleSelectUnitSounds().empty())\n\t\t\t_selectUnitSound = _armor->getMaleSelectUnitSounds();\n\t\tif (!_armor->getMaleStartMovingSounds().empty())\n\t\t\t_startMovingSound = _armor->getMaleStartMovingSounds();\n\t\tif (!_armor->getMaleSelectWeaponSounds().empty())\n\t\t\t_selectWeaponSound = _armor->getMaleSelectWeaponSounds();\n\t\tif (!_armor->getMaleAnnoyedSounds().empty())\n\t\t\t_annoyedSound = _armor->getMaleAnnoyedSounds();\n\t}\n\telse\n\t{\n\t\tif (!_armor->getFemaleSelectUnitSounds().empty())\n\t\t\t_selectUnitSound = _armor->getFemaleSelectUnitSounds();\n\t\tif (!_armor->getFemaleStartMovingSounds().empty())\n\t\t\t_startMovingSound = _armor->getFemaleStartMovingSounds();\n\t\tif (!_armor->getFemaleSelectWeaponSounds().empty())\n\t\t\t_selectWeaponSound = _armor->getFemaleSelectWeaponSounds();\n\t\tif (!_armor->getFemaleAnnoyedSounds().empty())\n\t\t\t_annoyedSound = _armor->getFemaleAnnoyedSounds();\n\t}\n}\n\n/**\n * Helper function preparing the banned flag.\n */\nvoid BattleUnit::prepareBannedFlag(const RuleStartingCondition* sc)\n{\n\t_bannedInNextStage = false;\n\tif (sc && !sc->getForbiddenArmorsInNextStage().empty())\n\t{\n\t\tconst auto& bannedList = sc->getForbiddenArmorsInNextStage();\n\t\tif (std::find(bannedList.begin(), bannedList.end(), _armor) != bannedList.end())\n\t\t{\n\t\t\t_bannedInNextStage = true;\n\t\t}\n\t}\n}\n\n/**\n * Initializes a BattleUnit from a Unit (non-player) object.\n * @param unit Pointer to Unit object.\n * @param faction Which faction the units belongs to.\n * @param id Unique unit ID.\n * @param enviro Pointer to battle enviro effects.\n * @param armor Pointer to unit Armor.\n * @param diff difficulty level (for stat adjustment).\n * @param depth the depth of the battlefield (used to determine movement type in case of MT_FLOAT).\n */\nBattleUnit::BattleUnit(const Mod *mod, const Unit *unit, UnitFaction faction, int id, const RuleEnviroEffects* enviro, const Armor *armor, StatAdjustment *adjustment, int depth, const RuleStartingCondition* sc) :\n\t_faction(faction), _originalFaction(faction), _killedBy(faction), _id(id),\n\t_tile(0), _lastPos(Position()), _direction(0), _toDirection(0), _directionTurret(0),\n\t_toDirectionTurret(0), _verticalDirection(0), _status(STATUS_STANDING), _wantsToSurrender(false), _isSurrendering(false), _walkPhase(0),\n\t_fallPhase(0), _kneeled(false), _floating(false), _dontReselect(false), _aiMedikitUsed(false), _fire(0), _currentAIState(0),\n\t_visible(false), _exp{ }, _expTmp{ },\n\t_motionPoints(0), _scannedTurn(-1), _customMarker(0), _kills(0), _hitByFire(false), _hitByAnything(false), _alreadyExploded(false), _fireMaxHit(0), _smokeMaxHit(0),\n\t_moraleRestored(0), _notificationShown(0), _charging(0),\n\t_statistics(), _murdererId(0), _mindControllerID(0), _fatalShotSide(SIDE_FRONT),\n\t_fatalShotBodyPart(BODYPART_HEAD), _armor(armor), _geoscapeSoldier(0),  _unitRules(unit),\n\t_rankInt(0), _turretType(-1), _hidingForTurn(false), _respawn(false), _alreadyRespawned(false),\n\t_isLeeroyJenkins(false), _summonedPlayerUnit(false), _resummonedFakeCivilian(false), _pickUpWeaponsMoreActively(false), _disableIndicators(false),\n\t_vip(false), _bannedInNextStage(false), _skillMenuCheck(false)\n{\n\tif (enviro)\n\t{\n\t\tauto newArmor = enviro->getArmorTransformation(_armor);\n\t\tif (newArmor)\n\t\t{\n\t\t\t_armor = newArmor;\n\t\t}\n\t}\n\t_type = unit->getType();\n\t_rank = unit->getRank();\n\t_race = unit->getRace();\n\t_gender = GENDER_MALE;\n\t_intelligence = unit->getIntelligence();\n\t_aggression = unit->getAggression();\n\t_faceDirection = -1;\n\t_floorAbove = false;\n\t_breathing = false;\n\n\t_spawnUnit = unit->getSpawnUnit();\n\t_capturable = unit->getCapturable();\n\t_isLeeroyJenkins = unit->isLeeroyJenkins();\n\tif (unit->getPickUpWeaponsMoreActively() != -1)\n\t{\n\t\t_pickUpWeaponsMoreActively = (unit->getPickUpWeaponsMoreActively() != 0);\n\t}\n\telse\n\t{\n\t\tif (faction == FACTION_HOSTILE)\n\t\t\t_pickUpWeaponsMoreActively = mod->getAIPickUpWeaponsMoreActively();\n\t\telse\n\t\t\t_pickUpWeaponsMoreActively = mod->getAIPickUpWeaponsMoreActivelyCiv();\n\t}\n\tif (_unitRules && _unitRules->isVIP())\n\t{\n\t\t_vip = true;\n\t}\n\n\t_value = unit->getValue();\n\n\n\tfor (int i = 0; i < BODYPART_MAX; ++i)\n\t\t_fatalWounds[i] = 0;\n\tfor (int i = 0; i < SPEC_WEAPON_MAX; ++i)\n\t\t_specWeapon[i] = 0;\n\n\t_activeHand = \"STR_RIGHT_HAND\";\n\t_preferredHandForReactions = \"\";\n\n\tlastCover = TileEngine::invalid;\n\n\t_statistics = new BattleUnitStatistics();\n\n\tif (_originalFaction == FACTION_HOSTILE)\n\t{\n\t\tderiveHostileRank();\n\t}\n\telse if (_originalFaction == FACTION_NEUTRAL)\n\t{\n\t\tderiveNeutralRank();\n\t}\n\n\tupdateArmorFromNonSoldier(mod, _armor, depth, false, sc);\n\n\tif (_specab == SPECAB_NONE)\n\t{\n\t\t_specab = (SpecialAbility) unit->getSpecialAbility();\n\t}\n\n\tif (_originalFaction == FACTION_HOSTILE)\n\t{\n\t\tadjustStats(*adjustment);\n\t}\n}\n\n/**\n * Updates BattleUnit's armor and related attributes (after a change/transformation of armor).\n */\nvoid BattleUnit::updateArmorFromNonSoldier(const Mod* mod, const Armor* newArmor, int depth, bool nextStage, const RuleStartingCondition* sc)\n{\n\t_armor = newArmor;\n\n\t_standHeight = _armor->getStandHeight() == -1 ? _unitRules->getStandHeight() : _armor->getStandHeight();\n\t_kneelHeight = _armor->getKneelHeight() == -1 ? _unitRules->getKneelHeight() : _armor->getKneelHeight();\n\t_floatHeight = _armor->getFloatHeight() == -1 ? _unitRules->getFloatHeight() : _armor->getFloatHeight();\n\t_loftempsSet = _armor->getLoftempsSet();\n\n\t_specab = (SpecialAbility)_armor->getSpecialAbility();\n\n\t_originalMovementType = _movementType = _armor->getMovementTypeByDepth(depth);\n\t_moveCostBase = _armor->getMoveCostBase();\n\t_moveCostBaseFly = _armor->getMoveCostBaseFly();\n\t_moveCostBaseClimb = _armor->getMoveCostBaseClimb();\n\t_moveCostBaseNormal = _armor->getMoveCostBaseNormal();\n\n\n\t_stats = *_unitRules->getStats();\n\t_stats += *_armor->getStats();\t// armors may modify effective stats\n\t_stats = UnitStats::obeyFixedMinimum(_stats); // don't allow to go into minus!\n\n\n\t_maxViewDistanceAtDark = _armor->getVisibilityAtDark() ? _armor->getVisibilityAtDark() : _originalFaction == FACTION_HOSTILE ? mod->getMaxViewDistance() : 9;\n\t_maxViewDistanceAtDarkSquared = _maxViewDistanceAtDark * _maxViewDistanceAtDark;\n\t_maxViewDistanceAtDay = _armor->getVisibilityAtDay() ? _armor->getVisibilityAtDay() : mod->getMaxViewDistance();\n\t_psiVision = _armor->getPsiVision();\n\t_visibilityThroughSmoke =  _armor->getVisibilityThroughSmoke();\n\t_visibilityThroughFire = _armor->getVisibilityThroughFire();\n\n\n\t_maxArmor[SIDE_FRONT] = _armor->getFrontArmor();\n\t_maxArmor[SIDE_LEFT] = _armor->getLeftSideArmor();\n\t_maxArmor[SIDE_RIGHT] = _armor->getRightSideArmor();\n\t_maxArmor[SIDE_REAR] = _armor->getRearArmor();\n\t_maxArmor[SIDE_UNDER] = _armor->getUnderArmor();\n\n\t_currentArmor[SIDE_FRONT] = _maxArmor[SIDE_FRONT];\n\t_currentArmor[SIDE_LEFT] = _maxArmor[SIDE_LEFT];\n\t_currentArmor[SIDE_RIGHT] = _maxArmor[SIDE_RIGHT];\n\t_currentArmor[SIDE_REAR] = _maxArmor[SIDE_REAR];\n\t_currentArmor[SIDE_UNDER] = _maxArmor[SIDE_UNDER];\n\n\n\tif (_armor->drawBubbles())\n\t{\n\t\t_breathFrame = 0;\n\t}\n\telse\n\t{\n\t\t_breathFrame = -1; // most aliens don't breathe per-se, that's exclusive to humanoids\n\t}\n\n\t_tu = _stats.tu;\n\t_energy = _stats.stamina;\n\tif (nextStage)\n\t{\n\t\t_health = std::min(_health, (int)_stats.health);\n\t\t_mana = std::min(_mana, (int)_stats.mana);\n\t}\n\telse\n\t{\n\t\t_health = _stats.health;\n\t\t_mana = _stats.mana;\n\t\t_morale = 100;\n\t\t_stunlevel = 0;\n\t}\n\n\tsetRecolor(RNG::seedless(0, 127), RNG::seedless(0, 127), _rankIntUnified);\n\n\tprepareUnitSounds();\n\tprepareUnitResponseSounds(mod);\n\tprepareBannedFlag(sc);\n}\n\n\n/**\n *\n */\nBattleUnit::~BattleUnit()\n{\n\tfor (auto* buk : _statistics->kills)\n\t{\n\t\tdelete buk;\n\t}\n\tdelete _statistics;\n\tdelete _currentAIState;\n}\n\n/**\n * Loads the unit from a YAML file.\n * @param node YAML node.\n */\nvoid BattleUnit::load(const YAML::YamlNodeReader& node, const Mod *mod, const ScriptGlobal *shared)\n{\n\tconst auto& reader = node.useIndex();\n\treader.tryRead(\"id\", _id);\n\treader.tryRead(\"faction\", _faction);\n\treader.tryRead(\"status\", _status);\n\treader.tryRead(\"wantsToSurrender\", _wantsToSurrender);\n\treader.tryRead(\"isSurrendering\", _isSurrendering);\n\treader.tryRead(\"position\", _pos);\n\treader.tryRead(\"direction\", _direction);\n\t_toDirection = _direction;\n\treader.tryRead(\"directionTurret\", _directionTurret);\n\t_toDirectionTurret = _directionTurret;\n\treader.tryRead(\"tu\", _tu);\n\treader.tryRead(\"health\", _health);\n\treader.tryRead(\"mana\", _mana);\n\treader.tryRead(\"stunlevel\", _stunlevel);\n\treader.tryRead(\"energy\", _energy);\n\treader.tryRead(\"morale\", _morale);\n\treader.tryRead(\"kneeled\", _kneeled);\n\treader.tryRead(\"floating\", _floating);\n\tfor (int i = 0; i < SIDE_MAX; i++)\n\t\treader[\"armor\"][i].tryReadVal(_currentArmor[i]);\n\tfor (int i = 0; i < BODYPART_MAX; i++)\n\t\treader[\"fatalWounds\"][i].tryReadVal(_fatalWounds[i]);\n\treader.tryRead(\"fire\", _fire);\n\treader.tryRead(\"expBravery\", _exp.bravery);\n\treader.tryRead(\"expReactions\", _exp.reactions);\n\treader.tryRead(\"expFiring\", _exp.firing);\n\treader.tryRead(\"expThrowing\", _exp.throwing);\n\treader.tryRead(\"expPsiSkill\", _exp.psiSkill);\n\treader.tryRead(\"expPsiStrength\", _exp.psiStrength);\n\treader.tryRead(\"expMana\", _exp.mana);\n\treader.tryRead(\"expMelee\", _exp.melee);\n\treader.tryRead(\"currStats\", _stats);\n\treader.tryRead(\"turretType\", _turretType);\n\treader.tryRead(\"visible\", _visible);\n\n\treader.tryReadAs<int>(\"turnsSinceSpotted\", _turnsSinceSpotted[FACTION_HOSTILE]);\n\treader.tryReadAs<int>(\"turnsLeftSpottedForSnipers\", _turnsLeftSpottedForSnipers[FACTION_HOSTILE]);\n\treader.tryReadAs<int>(\"turnsSinceSpottedByXcom\", _turnsSinceSpotted[FACTION_PLAYER]);\n\treader.tryReadAs<int>(\"turnsLeftSpottedForSnipersByXcom\", _turnsLeftSpottedForSnipers[FACTION_PLAYER]);\n\treader.tryReadAs<int>(\"turnsSinceSpottedByCivilian\", _turnsSinceSpotted[FACTION_NEUTRAL]);\n\treader.tryReadAs<int>(\"turnsLeftSpottedForSnipersByCivilian\", _turnsLeftSpottedForSnipers[FACTION_NEUTRAL]);\n\treader.tryReadAs<int>(\"turnsSinceStunned\", _turnsSinceStunned);\n\n\treader.tryRead(\"rankInt\", _rankInt);\n\treader.tryRead(\"rankIntUnified\", _rankIntUnified);\n\treader.tryRead(\"moraleRestored\", _moraleRestored);\n\treader.tryRead(\"notificationShown\", _notificationShown);\n\treader.tryRead(\"killedBy\", _killedBy);\n\treader.tryRead(\"kills\", _kills);\n\treader.tryRead(\"dontReselect\", _dontReselect);\n\treader.tryRead(\"aiMedikitUsed\", _aiMedikitUsed);\n\t_charging = 0;\n\tif ((_spawnUnit = mod->getUnit(reader[\"spawnUnit\"].readVal<std::string>(\"\"), false))) // ignore bugged types\n\t{\n\t\treader.tryRead(\"respawn\", _respawn);\n\t\treader.tryRead(\"spawnUnitFaction\", _spawnUnitFaction);\n\t}\n\treader.tryRead(\"motionPoints\", _motionPoints);\n\treader.tryRead(\"customMarker\", _customMarker);\n\treader.tryRead(\"alreadyRespawned\", _alreadyRespawned);\n\treader.tryRead(\"activeHand\", _activeHand);\n\treader.tryRead(\"preferredHandForReactions\", _preferredHandForReactions);\n\treader.tryRead(\"reactionsDisabledForLeftHand\", _reactionsDisabledForLeftHand);\n\treader.tryRead(\"reactionsDisabledForRightHand\", _reactionsDisabledForRightHand);\n\tif (reader[\"tempUnitStatistics\"])\n\t\t_statistics->load(reader[\"tempUnitStatistics\"]);\n\treader.tryRead(\"murdererId\", _murdererId);\n\treader.tryRead(\"fatalShotSide\", _fatalShotSide);\n\treader.tryRead(\"fatalShotBodyPart\", _fatalShotBodyPart);\n\treader.tryRead(\"murdererWeapon\", _murdererWeapon);\n\treader.tryRead(\"murdererWeaponAmmo\", _murdererWeaponAmmo);\n\n\tif (const auto& recolor = reader[\"recolor\"])\n\t{\n\t\t_recolor.clear();\n\t\tfor (size_t i = 0; i < recolor.childrenCount(); ++i)\n\t\t\t_recolor.push_back(std::make_pair(recolor[i][0].readVal<Uint8>(), recolor[i][1].readVal<Uint8>()));\n\t}\n\treader.tryRead(\"mindControllerID\", _mindControllerID);\n\treader.tryRead(\"summonedPlayerUnit\", _summonedPlayerUnit);\n\treader.tryRead(\"resummonedFakeCivilian\", _resummonedFakeCivilian);\n\treader.tryRead(\"pickUpWeaponsMoreActively\", _pickUpWeaponsMoreActively);\n\treader.tryRead(\"disableIndicators\", _disableIndicators);\n\treader.tryRead(\"movementType\", _movementType);\n\tif (const auto& moveCost = reader[\"moveCost\"])\n\t{\n\t\t_moveCostBase.load(moveCost[\"basePercent\"]);\n\t\t_moveCostBaseFly.load(moveCost[\"baseFlyPercent\"]);\n\t\t_moveCostBaseClimb.load(moveCost[\"baseClimbPercent\"]);\n\t\t_moveCostBaseNormal.load(moveCost[\"baseNormalPercent\"]);\n\t}\n\treader.tryRead(\"vip\", _vip);\n\treader.tryRead(\"bannedInNextStage\", _bannedInNextStage);\n\treader.tryRead(\"meleeAttackedBy\", _meleeAttackedBy);\n\t_scriptValues.load(reader, shared);\n}\n\n/**\n * Saves the soldier to a YAML file.\n * @return YAML node.\n */\nvoid BattleUnit::save(YAML::YamlNodeWriter writer, const ScriptGlobal *shared) const\n{\n\twriter.setAsMap();\n\twriter.write(\"id\", _id);\n\twriter.write(\"genUnitType\", _type);\n\twriter.write(\"genUnitArmor\", _armor->getType());\n\twriter.write(\"faction\", _faction);\n\twriter.write(\"status\", _status);\n\tif (_wantsToSurrender)\n\t\twriter.write(\"wantsToSurrender\", _wantsToSurrender);\n\tif (_isSurrendering)\n\t\twriter.write(\"isSurrendering\", _isSurrendering);\n\twriter.write(\"position\", _pos);\n\twriter.write(\"direction\", _direction);\n\twriter.write(\"directionTurret\", _directionTurret);\n\twriter.write(\"tu\", _tu);\n\twriter.write(\"health\", _health);\n\twriter.write(\"mana\", _mana);\n\twriter.write(\"stunlevel\", _stunlevel);\n\twriter.write(\"energy\", _energy);\n\twriter.write(\"morale\", _morale);\n\tif (_kneeled)\n\t\twriter.write(\"kneeled\", _kneeled);\n\tif (_floating)\n\t\twriter.write(\"floating\", _floating);\n\tauto armorWriter = writer[\"armor\"];\n\tarmorWriter.setAsSeq();\n\tarmorWriter.setFlowStyle();\n\tfor (int i = 0; i < SIDE_MAX; i++)\n\t\tarmorWriter.write(_currentArmor[i]);\n\tauto fwWriter = writer[\"fatalWounds\"];\n\tfwWriter.setAsSeq();\n\tfwWriter.setFlowStyle();\n\tfor (int i=0; i < BODYPART_MAX; i++)\n\t\tfwWriter.write(_fatalWounds[i]);\n\twriter.write(\"fire\", _fire);\n\twriter.write(\"expBravery\", _exp.bravery);\n\twriter.write(\"expReactions\", _exp.reactions);\n\twriter.write(\"expFiring\", _exp.firing);\n\twriter.write(\"expThrowing\", _exp.throwing);\n\twriter.write(\"expPsiSkill\", _exp.psiSkill);\n\twriter.write(\"expPsiStrength\", _exp.psiStrength);\n\twriter.write(\"expMana\", _exp.mana);\n\twriter.write(\"expMelee\", _exp.melee);\n\twriter.write(\"currStats\", _stats);\n\tif (_turretType > -1)\n\t\twriter.write(\"turretType\", _turretType);\n\tif (_visible)\n\t\twriter.write(\"visible\", _visible);\n\n\twriter.writeAs<int>(\"turnsSinceSpotted\", _turnsSinceSpotted[FACTION_HOSTILE]);\n\twriter.writeAs<int>(\"turnsLeftSpottedForSnipers\", _turnsLeftSpottedForSnipers[FACTION_HOSTILE]);\n\twriter.tryWriteAs<int>(\"turnsSinceSpottedByXcom\", _turnsSinceSpotted[FACTION_PLAYER], 255);\n\twriter.tryWriteAs<int>(\"turnsLeftSpottedForSnipersByXcom\", _turnsLeftSpottedForSnipers[FACTION_PLAYER], 0);\n\twriter.tryWriteAs<int>(\"turnsSinceSpottedByCivilian\", _turnsSinceSpotted[FACTION_NEUTRAL], 255);\n\twriter.tryWriteAs<int>(\"turnsLeftSpottedForSnipersByCivilian\", _turnsLeftSpottedForSnipers[FACTION_NEUTRAL], 0);\n\twriter.writeAs<int>(\"turnsSinceStunned\", _turnsSinceStunned);\n\n\twriter.write(\"rankInt\", _rankInt);\n\twriter.write(\"rankIntUnified\", _rankIntUnified);\n\twriter.write(\"moraleRestored\", _moraleRestored);\n\tif (_notificationShown > 0)\n\t\twriter.write(\"notificationShown\", _notificationShown);\n\tif (getAIModule())\n\t\tgetAIModule()->save(writer[\"AI\"]);\n\twriter.write(\"killedBy\", _killedBy); // does not have a default value, must always be saved\n\tif (_originalFaction != _faction)\n\t\twriter.write(\"originalFaction\", _originalFaction);\n\tif (_kills)\n\t\twriter.write(\"kills\", _kills);\n\tif (_faction == FACTION_PLAYER && _dontReselect)\n\t\twriter.write(\"dontReselect\", _dontReselect);\n\tif (_aiMedikitUsed)\n\t\twriter.write(\"aiMedikitUsed\", _aiMedikitUsed);\n\tif (_previousOwner)\n\t\twriter.write(\"previousOwner\", _previousOwner->getId());\n\tif (_spawnUnit)\n\t{\n\t\twriter.write(\"spawnUnit\", _spawnUnit->getType());\n\t\twriter.write(\"respawn\", _respawn);\n\t\twriter.write(\"spawnUnitFaction\", _spawnUnitFaction);\n\t}\n\twriter.write(\"motionPoints\", _motionPoints);\n\tif (_customMarker > 0)\n\t\twriter.write(\"customMarker\", _customMarker);\n\tif (_alreadyRespawned)\n\t\twriter.write(\"alreadyRespawned\", _alreadyRespawned);\n\twriter.write(\"activeHand\", _activeHand);\n\tif (!_preferredHandForReactions.empty())\n\t\twriter.write(\"preferredHandForReactions\", _preferredHandForReactions);\n\tif (_reactionsDisabledForLeftHand)\n\t\twriter.write(\"reactionsDisabledForLeftHand\", _reactionsDisabledForLeftHand);\n\tif (_reactionsDisabledForRightHand)\n\t\twriter.write(\"reactionsDisabledForRightHand\", _reactionsDisabledForRightHand);\n\t_statistics->save(writer[\"tempUnitStatistics\"]);\n\tif (_murdererId)\n\t\twriter.write(\"murdererId\", _murdererId);\n\tif (_fatalShotSide)\n\t\twriter.write(\"fatalShotSide\", _fatalShotSide);\n\tif (_fatalShotBodyPart)\n\t\twriter.write(\"fatalShotBodyPart\", _fatalShotBodyPart);\n\tif (!_murdererWeapon.empty())\n\t\twriter.write(\"murdererWeapon\", _murdererWeapon);\n\tif (!_murdererWeaponAmmo.empty())\n\t\twriter.write(\"murdererWeaponAmmo\", _murdererWeaponAmmo);\n\twriter.write(\"recolor\", _recolor,\n\t\t[](YAML::YamlNodeWriter& vectorWriter, std::pair<Uint8, Uint8> pair)\n\t\t{\n\t\t\tauto pairWriter = vectorWriter.write();\n\t\t\tpairWriter.setAsSeq();\n\t\t\tpairWriter.setFlowStyle();\n\t\t\tpairWriter.write(pair.first);\n\t\t\tpairWriter.write(pair.second);\n\t\t});\n\tif (_mindControllerID)\n\t\twriter.write(\"mindControllerID\", _mindControllerID);\n\tif (_summonedPlayerUnit)\n\t\twriter.write(\"summonedPlayerUnit\", _summonedPlayerUnit);\n\tif (_resummonedFakeCivilian)\n\t\twriter.write(\"resummonedFakeCivilian\", _resummonedFakeCivilian);\n\tif (_pickUpWeaponsMoreActively)\n\t\twriter.write(\"pickUpWeaponsMoreActively\", _pickUpWeaponsMoreActively);\n\tif (_disableIndicators)\n\t\twriter.write(\"disableIndicators\", _disableIndicators);\n\n\tif (_originalMovementType != _movementType)\n\t\twriter.write(\"movementType\", (int)_movementType);\n\tif (_moveCostBase != _armor->getMoveCostBase() ||\n\t\t_moveCostBaseFly != _armor->getMoveCostBaseFly() ||\n\t\t_moveCostBaseClimb != _armor->getMoveCostBaseClimb() ||\n\t\t_moveCostBaseNormal != _armor->getMoveCostBaseNormal())\n\t{\n\t\tauto moveCostWriter = writer[\"moveCost\"];\n\t\tmoveCostWriter.setAsMap();\n\t\tmoveCostWriter.setFlowStyle();\n\t\tif (_moveCostBase != _armor->getMoveCostBase())\n\t\t\t_moveCostBase.save(moveCostWriter, \"basePercent\");\n\t\tif (_moveCostBaseFly != _armor->getMoveCostBaseFly())\n\t\t\t_moveCostBaseFly.save(moveCostWriter, \"baseFlyPercent\");\n\t\tif (_moveCostBaseClimb != _armor->getMoveCostBaseClimb())\n\t\t\t_moveCostBaseClimb.save(moveCostWriter, \"baseClimbPercent\");\n\t\tif (_moveCostBaseNormal != _armor->getMoveCostBaseNormal())\n\t\t\t_moveCostBaseNormal.save(moveCostWriter, \"baseNormalPercent\");\n\t}\n\tif (_vip)\n\t\twriter.write(\"vip\", _vip);\n\tif (_bannedInNextStage)\n\t\twriter.write(\"bannedInNextStage\", _bannedInNextStage);\n\tif (!_meleeAttackedBy.empty())\n\t\twriter.write(\"meleeAttackedBy\", _meleeAttackedBy);\n\n\t_scriptValues.save(writer, shared);\n}\n\n/**\n * Prepare vector values for recolor.\n * @param basicLook select index for hair and face color.\n * @param utileLook select index for utile color.\n * @param rankLook select index for rank color.\n */\nvoid BattleUnit::setRecolor(int basicLook, int utileLook, int rankLook)\n{\n\t_recolor.clear(); // reset in case of OXCE on-the-fly armor changes/transformations\n\tconst int colorsMax = 4;\n\tstd::pair<int, int> colors[colorsMax] =\n\t{\n\t\tstd::make_pair(_armor->getFaceColorGroup(), _armor->getFaceColor(basicLook)),\n\t\tstd::make_pair(_armor->getHairColorGroup(), _armor->getHairColor(basicLook)),\n\t\tstd::make_pair(_armor->getUtileColorGroup(), _armor->getUtileColor(utileLook)),\n\t\tstd::make_pair(_armor->getRankColorGroup(), _armor->getRankColor(rankLook)),\n\t};\n\n\tfor (int i = 0; i < colorsMax; ++i)\n\t{\n\t\tif (colors[i].first > 0 && colors[i].second > 0)\n\t\t{\n\t\t\t_recolor.push_back(std::make_pair(colors[i].first << 4, colors[i].second));\n\t\t}\n\t}\n}\n\n/**\n * Returns the BattleUnit's unique ID.\n * @return Unique ID.\n */\nint BattleUnit::getId() const\n{\n\treturn _id;\n}\n\n/**\n * Calculates the distance squared between the unit and a given position.\n * @param pos The position.\n * @return Distance squared.\n */\nint BattleUnit::distance3dToPositionSq(const Position& pos) const\n{\n\tint x = _pos.x - pos.x;\n\tint y = _pos.y - pos.y;\n\tint z = _pos.z - pos.z;\n\tif (isBigUnit())\n\t{\n\t\tif (_pos.x < pos.x)\n\t\t\tx++;\n\t\tif (_pos.y < pos.y)\n\t\t\ty++;\n\t}\n\treturn x*x + y*y + z*z;\n}\n\n/**\n * Calculates the distance squared between the unit and a given other unit.\n * @param otherUnit The other unit.\n * @param considerZ Whether to consider the z coordinate.\n * @return Distance squared.\n */\nint BattleUnit::distance3dToUnitSq(BattleUnit* otherUnit) const\n{\n\t// TODO?: distance calculation isn't precise for 2x2 units here\n\t// and even though improving just the distance calculation would be easy\n\t// it would also require changes on other places:\n\t// - we would need to improve AI targeting involving 2x2 units\n\t// - we would need to improve reaction fire targeting involving 2x2 units\n\t// and that is NOT trivial and currently not worth the effort\n\t// PS: targeting involving a player-controlled 2x2 unit/actor was fixed recently, OXC PR #1307 commit dd7f938\n\n\treturn Position::distanceSq(_pos, otherUnit->getPosition());\n}\n\n/**\n * Changes the BattleUnit's position.\n * @param pos position\n * @param updateLastPos refresh last stored position\n */\nvoid BattleUnit::setPosition(Position pos, bool updateLastPos)\n{\n\tif (updateLastPos) { _lastPos = _pos; }\n\t_pos = pos;\n}\n\n/**\n * Gets the BattleUnit's position.\n * @return position\n */\nPosition BattleUnit::getPosition() const\n{\n\treturn _pos;\n}\n\n/**\n * Gets the BattleUnit's position.\n * @return position\n */\nPosition BattleUnit::getLastPosition() const\n{\n\treturn _lastPos;\n}\n\n/**\n * Gets position of unit center in voxels.\n * @return position in voxels\n */\nPosition BattleUnit::getPositionVexels() const\n{\n\tPosition center = _pos.toVoxel();\n\tcenter += Position(8, 8, 0) * _armor->getSize();\n\treturn center;\n}\n\n/**\n * Gets the BattleUnit's destination.\n * @return destination\n */\nPosition BattleUnit::getDestination() const\n{\n\treturn _destination;\n}\n\n/**\n * Changes the BattleUnit's (horizontal) direction.\n * Only used for initial unit placement.\n * @param direction new horizontal direction\n */\nvoid BattleUnit::setDirection(int direction)\n{\n\t_direction = direction;\n\t_toDirection = direction;\n\t_directionTurret = direction;\n\t_toDirectionTurret = direction;\n}\n\n/**\n * Changes the BattleUnit's (horizontal) face direction.\n * Only used for strafing moves.\n * @param direction new face direction\n */\nvoid BattleUnit::setFaceDirection(int direction)\n{\n\t_faceDirection = direction;\n}\n\n/**\n * Gets the BattleUnit's (horizontal) direction.\n * @return horizontal direction\n */\nint BattleUnit::getDirection() const\n{\n\treturn _direction;\n}\n\n/**\n * Gets the BattleUnit's (horizontal) face direction.\n * Used only during strafing moves.\n * @return face direction\n */\nint BattleUnit::getFaceDirection() const\n{\n\treturn _faceDirection;\n}\n\n/**\n * Gets the BattleUnit's turret direction.\n * @return direction\n */\nint BattleUnit::getTurretDirection() const\n{\n\treturn _directionTurret;\n}\n\n/**\n * Gets the BattleUnit's turret To direction.\n * @return toDirectionTurret\n */\nint BattleUnit::getTurretToDirection() const\n{\n\treturn _toDirectionTurret;\n}\n\n/**\n * Gets the BattleUnit's vertical direction. This is when going up or down.\n * @return direction\n */\nint BattleUnit::getVerticalDirection() const\n{\n\treturn _verticalDirection;\n}\n\n/**\n * Gets the unit's status.\n * @return the unit's status\n */\nUnitStatus BattleUnit::getStatus() const\n{\n\treturn _status;\n}\n\n/**\n* Does the unit want to surrender?\n* @return True if the unit wants to surrender\n*/\nbool BattleUnit::wantsToSurrender() const\n{\n\treturn _wantsToSurrender;\n}\n\n/**\n * Is the unit surrendering this turn?\n * @return True if the unit is surrendering (on this turn)\n */\nbool BattleUnit::isSurrendering() const\n{\n\treturn _isSurrendering;\n}\n\n/**\n * Mark the unit as surrendering this turn.\n * @param isSurrendering\n */\nvoid BattleUnit::setSurrendering(bool isSurrendering)\n{\n\t_isSurrendering = isSurrendering;\n}\n\n/**\n * Initialises variables to start walking.\n * @param direction Which way to walk.\n * @param destination The position we should end up on.\n * @param savedBattleGame Which is used to get tile is currently below the unit.\n */\nvoid BattleUnit::startWalking(int direction, Position destination, SavedBattleGame *savedBattleGame)\n{\n\tif (direction >= Pathfinding::DIR_UP)\n\t{\n\t\t_verticalDirection = direction;\n\t\t_status = STATUS_FLYING;\n\t}\n\telse\n\t{\n\t\t_direction = direction;\n\t\t_status = STATUS_WALKING;\n\t}\n\tif (_haveNoFloorBelow || direction >= Pathfinding::DIR_UP)\n\t{\n\t\t_status = STATUS_FLYING;\n\t\t_floating = true;\n\t}\n\telse\n\t{\n\t\t_floating = false;\n\t}\n\n\t_walkPhase = 0;\n\t_destination = destination;\n\t_lastPos = _pos;\n\t_kneeled = false;\n\tif (_breathFrame >= 0)\n\t{\n\t\t_breathing = false;\n\t\t_breathFrame = 0;\n\t}\n}\n\n/**\n * This will increment the walking phase.\n * @param savedBattleGame Pointer to save to get tile currently below the unit.\n * @param fullWalkCycle Do full walk cycle or short one when unit is off screen.\n */\nvoid BattleUnit::keepWalking(SavedBattleGame *savedBattleGame, bool fullWalkCycle)\n{\n\tint middle, end;\n\tif (_verticalDirection)\n\t{\n\t\tmiddle = 4;\n\t\tend = 8;\n\t}\n\telse\n\t{\n\t\t// diagonal walking takes double the steps\n\t\tmiddle = 4 + 4 * (_direction % 2);\n\t\tend = 8 + 8 * (_direction % 2);\n\t\tif (isBigUnit())\n\t\t{\n\t\t\tif (_direction < 1 || _direction > 5)\n\t\t\t\tmiddle = end;\n\t\t\telse if (_direction == 5)\n\t\t\t\tmiddle = 12;\n\t\t\telse if (_direction == 1)\n\t\t\t\tmiddle = 5;\n\t\t\telse\n\t\t\t\tmiddle = 1;\n\t\t}\n\t}\n\n\tif (!fullWalkCycle)\n\t{\n\t\t_pos = _destination;\n\t\tend = 2;\n\t}\n\n\t_walkPhase++;\n\n\tif (_walkPhase == middle)\n\t{\n\t\t// we assume we reached our destination tile\n\t\t// this is actually a drawing hack, so soldiers are not overlapped by floor tiles\n\t\t_pos = _destination;\n\t}\n\n\tif (!fullWalkCycle || (_walkPhase == middle))\n\t{\n\t\tsetTile(savedBattleGame->getTile(_destination), savedBattleGame);\n\t}\n\n\tif (_walkPhase >= end)\n\t{\n\t\tif (_floating && !_haveNoFloorBelow)\n\t\t{\n\t\t\t_floating = false;\n\t\t}\n\t\t// we officially reached our destination tile\n\t\t_status = STATUS_STANDING;\n\t\t_walkPhase = 0;\n\t\t_verticalDirection = 0;\n\t\tif (_faceDirection >= 0) {\n\t\t\t// Finish strafing move facing the correct way.\n\t\t\t_direction = _faceDirection;\n\t\t\t_faceDirection = -1;\n\t\t}\n\n\t\t// motion points calculation for the motion scanner blips\n\t\tif (isBigUnit())\n\t\t{\n\t\t\t_motionPoints += 30;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// sectoids actually have less motion points\n\t\t\t// but instead of create yet another variable,\n\t\t\t// I used the height of the unit instead (logical)\n\t\t\tif (getStandHeight() > 16)\n\t\t\t\t_motionPoints += 4;\n\t\t\telse\n\t\t\t\t_motionPoints += 3;\n\t\t}\n\t}\n}\n\n/**\n * Gets the walking phase for animation and sound.\n * @return phase will always go from 0-7\n */\nint BattleUnit::getWalkingPhase() const\n{\n\treturn _walkPhase % 8;\n}\n\n/**\n * Gets the walking phase for diagonal walking.\n * @return phase this will be 0 or 8\n */\nint BattleUnit::getDiagonalWalkingPhase() const\n{\n\treturn (_walkPhase / 8) * 8;\n}\n\n/**\n * Look at a point.\n * @param point Position to look at.\n * @param turret True to turn the turret, false to turn the unit.\n */\nvoid BattleUnit::lookAt(Position point, bool turret)\n{\n\tint dir = directionTo (point);\n\n\tif (turret)\n\t{\n\t\t_toDirectionTurret = dir;\n\t\tif (_toDirectionTurret != _directionTurret)\n\t\t{\n\t\t\t_status = STATUS_TURNING;\n\t\t}\n\t}\n\telse\n\t{\n\t\t_toDirection = dir;\n\t\tif (_toDirection != _direction\n\t\t\t&& _toDirection < 8\n\t\t\t&& _toDirection > -1)\n\t\t{\n\t\t\t_status = STATUS_TURNING;\n\t\t}\n\t}\n}\n\n/**\n * Look at a direction.\n * @param direction Direction to look at.\n * @param force True to reset the direction, false to animate to it.\n */\nvoid BattleUnit::lookAt(int direction, bool force)\n{\n\tif (!force)\n\t{\n\t\tif (direction < 0 || direction >= 8) return;\n\t\t_toDirection = direction;\n\t\tif (_toDirection != _direction)\n\t\t{\n\t\t\t_status = STATUS_TURNING;\n\t\t}\n\t}\n\telse\n\t{\n\t\t_toDirection = direction;\n\t\t_direction = direction;\n\t}\n}\n\n/**\n * Advances the turning towards the target direction.\n * @param turret True to turn the turret, false to turn the unit.\n */\nvoid BattleUnit::turn(bool turret)\n{\n\tint a = 0;\n\n\tif (turret)\n\t{\n\t\tif (_directionTurret == _toDirectionTurret)\n\t\t{\n\t\t\tabortTurn();\n\t\t\treturn;\n\t\t}\n\t\ta = _toDirectionTurret - _directionTurret;\n\t}\n\telse\n\t{\n\t\tif (_direction == _toDirection)\n\t\t{\n\t\t\tabortTurn();\n\t\t\treturn;\n\t\t}\n\t\ta = _toDirection - _direction;\n\t}\n\n\tif (a != 0) {\n\t\tif (a > 0) {\n\t\t\tif (a <= 4) {\n\t\t\t\tif (!turret) {\n\t\t\t\t\tif (_turretType > -1)\n\t\t\t\t\t\t_directionTurret++;\n\t\t\t\t\t_direction++;\n\t\t\t\t} else _directionTurret++;\n\t\t\t} else {\n\t\t\t\tif (!turret) {\n\t\t\t\t\tif (_turretType > -1)\n\t\t\t\t\t\t_directionTurret--;\n\t\t\t\t\t_direction--;\n\t\t\t\t} else _directionTurret--;\n\t\t\t}\n\t\t} else {\n\t\t\tif (a > -4) {\n\t\t\t\tif (!turret) {\n\t\t\t\t\tif (_turretType > -1)\n\t\t\t\t\t\t_directionTurret--;\n\t\t\t\t\t_direction--;\n\t\t\t\t} else _directionTurret--;\n\t\t\t} else {\n\t\t\t\tif (!turret) {\n\t\t\t\t\tif (_turretType > -1)\n\t\t\t\t\t\t_directionTurret++;\n\t\t\t\t\t_direction++;\n\t\t\t\t} else _directionTurret++;\n\t\t\t}\n\t\t}\n\t\tif (_direction < 0) _direction = 7;\n\t\tif (_direction > 7) _direction = 0;\n\t\tif (_directionTurret < 0) _directionTurret = 7;\n\t\tif (_directionTurret > 7) _directionTurret = 0;\n\t}\n\n\tif (turret)\n\t{\n\t\t if (_toDirectionTurret == _directionTurret)\n\t\t {\n\t\t\t// we officially reached our destination\n\t\t\t_status = STATUS_STANDING;\n\t\t }\n\t}\n\telse if (_toDirection == _direction || _status == STATUS_UNCONSCIOUS)\n\t{\n\t\t// we officially reached our destination\n\t\t_status = STATUS_STANDING;\n\t}\n}\n\n/**\n * Stops the turning towards the target direction.\n */\nvoid BattleUnit::abortTurn()\n{\n\t_status = STATUS_STANDING;\n}\n\n\n/**\n * Gets the soldier's gender.\n */\nSoldierGender BattleUnit::getGender() const\n{\n\treturn _gender;\n}\n\n/**\n * Returns the unit's faction.\n * @return Faction. (player, hostile or neutral)\n */\nUnitFaction BattleUnit::getFaction() const\n{\n\treturn _faction;\n}\n\n/**\n * Gets values used for recoloring sprites.\n * @param i what value choose.\n * @return Pairs of value, where first is color group to replace and second is new color group with shade.\n */\nconst std::vector<std::pair<Uint8, Uint8> > &BattleUnit::getRecolor() const\n{\n\treturn _recolor;\n}\n\n/**\n * Kneel down.\n * @param kneeled to kneel or to stand up\n */\nvoid BattleUnit::kneel(bool kneeled)\n{\n\t_kneeled = kneeled;\n}\n\n/**\n * Is kneeled down?\n * @return true/false\n */\nbool BattleUnit::isKneeled() const\n{\n\treturn _kneeled;\n}\n\n/**\n * Is floating? A unit is floating when there is no ground under him/her.\n * @return true/false\n */\nbool BattleUnit::isFloating() const\n{\n\treturn _floating;\n}\n\n/**\n * Aim. (shows the right hand sprite and weapon holding)\n * @param aiming true/false\n */\nvoid BattleUnit::aim(bool aiming)\n{\n\tif (aiming)\n\t\t_status = STATUS_AIMING;\n\telse\n\t\t_status = STATUS_STANDING;\n}\n\n/**\n * Returns the direction from this unit to a given point.\n * 0 <-> y = -1, x = 0\n * 1 <-> y = -1, x = 1\n * 3 <-> y = 1, x = 1\n * 5 <-> y = 1, x = -1\n * 7 <-> y = -1, x = -1\n * @param point given position.\n * @return direction.\n */\nint BattleUnit::directionTo(Position point) const\n{\n\tdouble ox = point.x - _pos.x;\n\tdouble oy = point.y - _pos.y;\n\tdouble angle = atan2(ox, -oy);\n\t// divide the pie in 4 angles each at 1/8th before each quarter\n\tdouble pie[4] = {(M_PI_4 * 4.0) - M_PI_4 / 2.0, (M_PI_4 * 3.0) - M_PI_4 / 2.0, (M_PI_4 * 2.0) - M_PI_4 / 2.0, (M_PI_4 * 1.0) - M_PI_4 / 2.0};\n\tint dir = 0;\n\n\tif (angle > pie[0] || angle < -pie[0])\n\t{\n\t\tdir = 4;\n\t}\n\telse if (angle > pie[1])\n\t{\n\t\tdir = 3;\n\t}\n\telse if (angle > pie[2])\n\t{\n\t\tdir = 2;\n\t}\n\telse if (angle > pie[3])\n\t{\n\t\tdir = 1;\n\t}\n\telse if (angle < -pie[1])\n\t{\n\t\tdir = 5;\n\t}\n\telse if (angle < -pie[2])\n\t{\n\t\tdir = 6;\n\t}\n\telse if (angle < -pie[3])\n\t{\n\t\tdir = 7;\n\t}\n\telse if (angle < pie[0])\n\t{\n\t\tdir = 0;\n\t}\n\treturn dir;\n}\n\n/**\n * Returns the soldier's amount of time units.\n * @return Time units.\n */\nint BattleUnit::getTimeUnits() const\n{\n\treturn _tu;\n}\n\n/**\n * Returns the soldier's amount of energy.\n * @return Energy.\n */\nint BattleUnit::getEnergy() const\n{\n\treturn _energy;\n}\n\n/**\n * Returns the soldier's amount of health.\n * @return Health.\n */\nint BattleUnit::getHealth() const\n{\n\treturn _health;\n}\n\n/**\n * Returns the soldier's amount of mana.\n * @return Mana.\n */\nint BattleUnit::getMana() const\n{\n\treturn _mana;\n}\n\n/**\n * Returns the soldier's amount of morale.\n * @return Morale.\n */\nint BattleUnit::getMorale() const\n{\n\treturn _morale;\n}\n\n/**\n * Get overkill damage to unit.\n * @return Damage over normal health.\n */\nint BattleUnit::getOverKillDamage() const\n{\n\treturn std::max(-_health - (int)(_stats.health * _armor->getOverKill()), 0);\n}\n\n/**\n * Helper function for setting value with max bound.\n */\nstatic inline void setValueMax(int& value, int diff, int min, int max)\n{\n\tvalue = Clamp(value + diff, min, max);\n}\n\n/**\n * Do an amount of damage.\n * @param relative The relative position of which part of armor and/or bodypart is hit.\n * @param damage The amount of damage to inflict.\n * @param type The type of damage being inflicted.\n * @return damage done after adjustment\n */\nint BattleUnit::damage(Position relative, int damage, const RuleDamageType *type, SavedBattleGame *save, BattleActionAttack attack, UnitSide sideOverride, UnitBodyPart bodypartOverride)\n{\n\tif (save->isPreview())\n\t{\n\t\treturn 0;\n\t}\n\tUnitSide side = SIDE_FRONT;\n\tUnitBodyPart bodypart = BODYPART_TORSO;\n\n\t_hitByAnything = true;\n\tif (_health <= 0)\n\t{\n\t\treturn 0;\n\t}\n\n\tRNG::RandomState rand = RNG::globalRandomState().subSequence();\n\tdamage = reduceByResistance(damage, type->ResistType);\n\n\tif (!type->IgnoreDirection)\n\t{\n\t\tif (relative.x == 0 && relative.y == 0 && relative.z <= 0)\n\t\t{\n\t\t\tside = SIDE_UNDER;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tint relativeDirection;\n\t\t\tconst int abs_x = abs(relative.x);\n\t\t\tconst int abs_y = abs(relative.y);\n\t\t\tif (abs_y > abs_x * 2)\n\t\t\t\trelativeDirection = 8 + 4 * (relative.y > 0);\n\t\t\telse if (abs_x > abs_y * 2)\n\t\t\t\trelativeDirection = 10 + 4 * (relative.x < 0);\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (relative.x < 0)\n\t\t\t\t{\n\t\t\t\t\tif (relative.y > 0)\n\t\t\t\t\t\trelativeDirection = 13;\n\t\t\t\t\telse\n\t\t\t\t\t\trelativeDirection = 15;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif (relative.y > 0)\n\t\t\t\t\t\trelativeDirection = 11;\n\t\t\t\t\telse\n\t\t\t\t\t\trelativeDirection = 9;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tswitch((relativeDirection - _direction) % 8)\n\t\t\t{\n\t\t\tcase 0:\tside = SIDE_FRONT; \t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\tcase 1:\tside = RNG::generate(0,2) < 2 ? SIDE_FRONT:SIDE_RIGHT; \tbreak;\n\t\t\tcase 2:\tside = SIDE_RIGHT; \t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\tcase 3:\tside = RNG::generate(0,2) < 2 ? SIDE_REAR:SIDE_RIGHT; \tbreak;\n\t\t\tcase 4:\tside = SIDE_REAR; \t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\tcase 5:\tside = RNG::generate(0,2) < 2 ? SIDE_REAR:SIDE_LEFT; \tbreak;\n\t\t\tcase 6:\tside = SIDE_LEFT; \t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\tcase 7:\tside = RNG::generate(0,2) < 2 ? SIDE_FRONT:SIDE_LEFT; \tbreak;\n\t\t\t}\n\t\t\tif (relative.z >= getHeight())\n\t\t\t{\n\t\t\t\tbodypart = BODYPART_HEAD;\n\t\t\t}\n\t\t\telse if (relative.z > 4)\n\t\t\t{\n\t\t\t\tswitch(side)\n\t\t\t\t{\n\t\t\t\tcase SIDE_LEFT:\t\tbodypart = BODYPART_LEFTARM; break;\n\t\t\t\tcase SIDE_RIGHT:\tbodypart = BODYPART_RIGHTARM; break;\n\t\t\t\tdefault:\t\t\tbodypart = BODYPART_TORSO;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tswitch(side)\n\t\t\t\t{\n\t\t\t\tcase SIDE_LEFT: \tbodypart = BODYPART_LEFTLEG; \tbreak;\n\t\t\t\tcase SIDE_RIGHT:\tbodypart = BODYPART_RIGHTLEG; \tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbodypart = (UnitBodyPart) rand.generate(BODYPART_RIGHTLEG,BODYPART_LEFTLEG);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tconst int orgDamage = damage;\n\tconst int overKillMinimum = type->IgnoreOverKill ? 0 : -UnitStats::OverkillMultipler * _stats.health;\n\n\n\t{\n\t\tModScript::HitUnit::Output args { damage, bodypart, side, };\n\t\tModScript::HitUnit::Worker work { this, attack.damage_item, attack.weapon_item, attack.attacker, save, attack.skill_rules, orgDamage, type->ResistType, attack.type };\n\n\t\tif (attack.damage_item)\n\t\t{\n\t\t\twork.execute(attack.damage_item->getRules()->getScript<ModScript::HitUnitAmmo>(), args);\n\t\t}\n\n\t\twork.execute(this->getArmor()->getScript<ModScript::HitUnit>(), args);\n\n\t\tdamage = args.getFirst();\n\t\tbodypart = (UnitBodyPart)args.getSecond();\n\t\tside = (UnitSide)args.getThird();\n\t\tif (bodypart >= BODYPART_MAX)\n\t\t{\n\t\t\tbodypart = {};\n\t\t}\n\t\tif (side >= SIDE_MAX)\n\t\t{\n\t\t\tside = {};\n\t\t}\n\t}\n\n\t// side and bodypart overrides (used by environmental conditions only)\n\tif (sideOverride != SIDE_MAX)\n\t{\n\t\tside = sideOverride;\n\t}\n\tif (bodypartOverride != BODYPART_MAX)\n\t{\n\t\tbodypart = bodypartOverride;\n\t}\n\n\n\tconst RuleItem *specialDamageTransform = attack.damage_item ? attack.damage_item->getRules() : nullptr;\n\tint specialDamageTransformChance = 0;\n\n\tif (specialDamageTransform\n\t\t&& !specialDamageTransform->getZombieUnit(this).empty()\n\t\t&& getArmor()->getZombiImmune() == false)\n\t{\n\t\tspecialDamageTransformChance = specialDamageTransform->getZombieUnitChance();\n\n\t\tif (auto conf = attack.weapon_item ? attack.weapon_item->getActionConf(attack.type) : nullptr)\n\t\t{\n\t\t\tspecialDamageTransformChance = useIntNullable(conf->ammoZombieUnitChanceOverride, specialDamageTransformChance);\n\t\t}\n\n\t\tif (getOriginalFaction() == FACTION_HOSTILE)\n\t\t{\n\t\t\tif (attack.attacker == nullptr || attack.attacker->getOriginalFaction() == FACTION_HOSTILE)\n\t\t\t{\n\t\t\t\t// (mind-controlled) chryssalid on snakeman action still not allowed\n\t\t\t\tspecialDamageTransformChance = 0;\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\tspecialDamageTransform = nullptr;\n\t}\n\n\n\t// update state of unit stats\n\tif (damage > 0)\n\t{\n\t\tconstexpr int toHealth = 0;\n\t\tconstexpr int toArmor = 1;\n\t\tconstexpr int toStun = 2;\n\t\tconstexpr int toTime = 3;\n\t\tconstexpr int toEnergy = 4;\n\t\tconstexpr int toMorale = 5;\n\t\tconstexpr int toWound = 6;\n\t\tconstexpr int toTransform = 7;\n\t\tconstexpr int toMana = 8;\n\n\t\tModScript::DamageUnit::Output args { };\n\n\t\tstd::get<toTransform>(args.data) += specialDamageTransformChance;\n\t\tstd::get<toArmor>(args.data) += type->getArmorPreFinalDamage(damage);\n\n\t\tif (type->ArmorEffectiveness > 0.0f)\n\t\t{\n\t\t\tdamage -= getArmor(side) * type->ArmorEffectiveness;\n\t\t}\n\n\t\tif (damage > 0)\n\t\t{\n\t\t\t// stun level change\n\t\t\tstd::get<toStun>(args.data) += type->getStunFinalDamage(damage);\n\n\t\t\t// morale change\n\t\t\tstd::get<toMorale>(args.data) += type->getMoraleFinalDamage(damage);\n\n\t\t\t// time units change\n\t\t\tstd::get<toTime>(args.data) += type->getTimeFinalDamage(damage);\n\n\t\t\t// health change\n\t\t\tstd::get<toHealth>(args.data) += type->getHealthFinalDamage(damage);\n\n\t\t\t// mana change\n\t\t\tstd::get<toMana>(args.data) += type->getManaFinalDamage(damage);\n\n\t\t\t// energy change\n\t\t\tstd::get<toEnergy>(args.data) += type->getEnergyFinalDamage(damage);\n\n\t\t\t// fatal wounds change\n\t\t\tstd::get<toWound>(args.data) += type->getWoundFinalDamage(damage);\n\n\t\t\t// armor value change\n\t\t\tstd::get<toArmor>(args.data) += type->getArmorFinalDamage(damage);\n\t\t}\n\n\t\tModScript::DamageUnit::Worker work { this, attack.damage_item, attack.weapon_item, attack.attacker, save, attack.skill_rules, damage, orgDamage, bodypart, side, type->ResistType, attack.type, };\n\n\t\tif (attack.damage_item)\n\t\t{\n\t\t\twork.execute(attack.damage_item->getRules()->getScript<ModScript::DamageUnitAmmo>(), args);\n\t\t}\n\n\t\twork.execute(this->getArmor()->getScript<ModScript::DamageUnit>(), args);\n\n\t\tif (!_armor->getPainImmune() || type->IgnorePainImmunity)\n\t\t{\n\t\t\tsetValueMax(_stunlevel, std::get<toStun>(args.data), 0, UnitStats::StunMultipler * _stats.health);\n\t\t}\n\n\t\tmoraleChange(- reduceByBravery(std::get<toMorale>(args.data)));\n\n\t\tsetValueMax(_tu, - std::get<toTime>(args.data), 0, _stats.tu);\n\n\t\tsetValueMax(_health, - std::get<toHealth>(args.data), std::min(overKillMinimum, _health), _stats.health); // `std::min` required because of script that could set `_health = -100`, if we do not have \"overkill\" `-100` become min value allowed by this line, if \"overkill\" then this line can go lower than this.\n\n\t\tsetValueMax(_mana, - std::get<toMana>(args.data), 0, _stats.mana);\n\n\t\tsetValueMax(_energy, - std::get<toEnergy>(args.data), 0, _stats.stamina);\n\n\t\tif (isWoundable())\n\t\t{\n\t\t\tsetValueMax(_fatalWounds[bodypart], std::get<toWound>(args.data), 0, UnitStats::BaseStatLimit);\n\t\t\tmoraleChange(-std::get<toWound>(args.data));\n\t\t}\n\n\t\tsetValueMax(_currentArmor[side], - std::get<toArmor>(args.data), 0, _maxArmor[side]);\n\n\n\t\tsetFatalShotInfo(side, bodypart);\n\n\n\t\tdamage = std::get<toHealth>(args.data);\n\t\tspecialDamageTransformChance = std::get<toTransform>(args.data);\n\t}\n\n\t// special effects\n\tif (save->getBattleState())\n\t{\n\t\tconstexpr int arg_specialDamageTransform = 0;\n\t\tconstexpr int arg_specialDamageTransformChance = 1;\n\t\tconstexpr int arg_selfDestruct = 2;\n\t\tconstexpr int arg_selfDestructChance = 3;\n\t\tconstexpr int arg_moraleLoss = 4;\n\t\tconstexpr int arg_fire = 5;\n\t\tconstexpr int arg_attackerTurnsSinceSpotted = 6;\n\t\tconstexpr int arg_attackerTurnsLeftSpottedForSnipers = 7;\n\n\t\tModScript::DamageSpecialUnit::Output args { };\n\n\t\t// chance to tranform\n\t\tstd::get<arg_specialDamageTransform>(args.data) = specialDamageTransform != nullptr;\n\t\tstd::get<arg_specialDamageTransformChance>(args.data) = specialDamageTransformChance;\n\n\t\t// morale loss based on final damage to health\n\t\tif (type->IgnoreNormalMoraleLose == false)\n\t\t{\n\t\t\tconst int bravery = reduceByBravery(10);\n\t\t\tconst int modifier = getFaction() == FACTION_PLAYER ? save->getFactionMoraleModifier(true) : 100;\n\n\t\t\tstd::get<arg_moraleLoss>(args.data) = 100 * (damage * bravery / 10) / modifier;\n\t\t}\n\n\t\t// self destruction\n\t\tstd::get<arg_selfDestruct>(args.data) = (getSpecialAbility() == SPECAB_EXPLODEONDEATH || getSpecialAbility() == SPECAB_BURN_AND_EXPLODE);\n\t\tif (std::get<arg_selfDestruct>(args.data) && !isOut() && isOutThresholdExceed())\n\t\t{\n\t\t\tif (type->IgnoreSelfDestruct == false)\n\t\t\t{\n\t\t\t\tstd::get<arg_selfDestructChance>(args.data) = 100;\n\t\t\t}\n\t\t}\n\n\t\t// normal fire\n\t\tstd::get<arg_fire>(args.data) = getFire();\n\t\tif (damage >= type->FireThreshold)\n\t\t{\n\t\t\tfloat resistance = getArmor()->getDamageModifier(type->ResistType);\n\t\t\tif (resistance > 0.0)\n\t\t\t{\n\t\t\t\tint burnTime = rand.generate(0, int(5.0f * resistance));\n\t\t\t\tif (std::get<arg_fire>(args.data) < burnTime)\n\t\t\t\t{\n\t\t\t\t\tstd::get<arg_fire>(args.data) = burnTime; // catch fire and burn\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// fire extinguisher\n\t\tif (std::get<arg_fire>(args.data) > 0)\n\t\t{\n\t\t\tif (attack.weapon_item && attack.weapon_item->getRules()->isFireExtinguisher())\n\t\t\t{\n\t\t\t\t// firearm, melee weapon, or even a grenade...\n\t\t\t\tstd::get<arg_fire>(args.data) = 0;\n\t\t\t}\n\t\t\telse if (attack.damage_item && attack.damage_item->getRules()->isFireExtinguisher())\n\t\t\t{\n\t\t\t\t// bullet/ammo\n\t\t\t\tstd::get<arg_fire>(args.data) = 0;\n\t\t\t}\n\t\t}\n\n\t\t// AI direct hit tracking\n\t\tstd::get<arg_attackerTurnsSinceSpotted>(args.data) = 255;\n\t\tstd::get<arg_attackerTurnsLeftSpottedForSnipers>(args.data) = 0;\n\t\tif (attack.attacker)\n\t\t{\n\t\t\tstd::get<arg_attackerTurnsSinceSpotted>(args.data) = attack.attacker->getTurnsSinceSpottedByFaction(getFaction());\n\t\t\tstd::get<arg_attackerTurnsLeftSpottedForSnipers>(args.data) = attack.attacker->getTurnsLeftSpottedForSnipersByFaction(getFaction());\n\n\t\t\tif (getFaction() != attack.attacker->getFaction() &&\n\t\t\t\t(attack.type == BA_AIMEDSHOT || attack.type == BA_SNAPSHOT || attack.type == BA_AUTOSHOT) &&\n\t\t\t\tattack.damage_item != nullptr &&\n\t\t\t\t(relative == Position(0,0,0) || (attack.damage_item->getRules()->getExplosionRadius(attack) == 0)))\n\t\t\t{\n\t\t\t\tAIModule *ai = getAIModule();\n\t\t\t\tif (ai != 0)\n\t\t\t\t{\n\t\t\t\t\tai->setWasHitBy(attack.attacker);\n\t\t\t\t}\n\n\t\t\t\tstd::get<arg_attackerTurnsSinceSpotted>(args.data) = 0;\n\t\t\t\tif (Mod::EXTENDED_SPOT_ON_HIT_FOR_SNIPING > 0)\n\t\t\t\t{\n\t\t\t\t\t// 0 = don't spot\n\t\t\t\t\t// 1 = spot only if the victim doesn't die or pass out\n\t\t\t\t\t// 2 = always spot\n\t\t\t\t\tif (Mod::EXTENDED_SPOT_ON_HIT_FOR_SNIPING > 1 || !this->isOutThresholdExceed())\n\t\t\t\t\t{\n\t\t\t\t\t\tstd::get<arg_attackerTurnsLeftSpottedForSnipers>(args.data) = std::max(std::get<arg_attackerTurnsLeftSpottedForSnipers>(args.data), getSpotterDuration());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\n\t\t// script call\n\n\t\tModScript::DamageSpecialUnit::Worker work { this, attack.damage_item, attack.weapon_item, attack.attacker, save, attack.skill_rules, damage, orgDamage, bodypart, side, type->ResistType, attack.type, };\n\n\t\tif (attack.damage_item)\n\t\t{\n\t\t\twork.execute(attack.damage_item->getRules()->getScript<ModScript::DamageSpecialUnitAmmo>(), args);\n\t\t}\n\n\t\twork.execute(this->getArmor()->getScript<ModScript::DamageSpecialUnit>(), args);\n\n\n\t\t// update state\n\t\tmoraleChange(-std::get<arg_moraleLoss>(args.data));\n\t\tsetFire(std::get<arg_fire>(args.data));\n\n\t\t// check if this unit turns others into zombies\n\t\tif (rand.percent(std::get<arg_specialDamageTransformChance>(args.data)) && specialDamageTransform\n\t\t\t&& !getSpawnUnit())\n\t\t{\n\t\t\tauto& spawnName = specialDamageTransform->getZombieUnit(this);\n\t\t\tauto* spawnType = save->getMod()->getUnit(spawnName);\n\t\t\tif (spawnType->getArmor()->getSize() <= getArmor()->getSize())\n\t\t\t{\n\t\t\t\tUnitFaction faction = specialDamageTransform->getZombieUnitFaction();\n\t\t\t\tif (faction == FACTION_NONE)\n\t\t\t\t{\n\t\t\t\t\tif (attack.attacker)\n\t\t\t\t\t{\n\t\t\t\t\t\tfaction = attack.attacker->getFaction();\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tfaction = FACTION_HOSTILE;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// converts the victim to a zombie on death\n\t\t\t\tsetRespawn(true);\n\t\t\t\tsetSpawnUnitFaction(faction);\n\t\t\t\tsetSpawnUnit(spawnType);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tLog(LOG_ERROR) << \"Transforming armor type '\" << this->getArmor()->getType() << \"' to unit type '\" << spawnName << \"' is not allowed because of bigger armor size\";\n\t\t\t}\n\t\t}\n\n\t\tauto* selfDestructItem = getSpecialWeapon(getArmor()->getSelfDestructItem());\n\t\tif (rand.percent(std::get<arg_selfDestructChance>(args.data))\n\t\t\t&& !hasAlreadyExploded() && selfDestructItem)\n\t\t{\n\t\t\tsetAlreadyExploded(true);\n\t\t\tPosition p = getPosition().toVoxel();\n\t\t\tsave->getBattleGame()->statePushNext(new ExplosionBState(save->getBattleGame(), p, BattleActionAttack{ BA_SELF_DESTRUCT, this, selfDestructItem, selfDestructItem }, 0));\n\t\t}\n\n\t\tif (attack.attacker)\n\t\t{\n\t\t\tattack.attacker->setTurnsSinceSpottedByFaction(getFaction(), std::get<arg_attackerTurnsSinceSpotted>(args.data));\n\t\t\tattack.attacker->setTurnsLeftSpottedForSnipersByFaction(getFaction(), std::get<arg_attackerTurnsLeftSpottedForSnipers>(args.data));\n\t\t}\n\t}\n\n\treturn damage;\n}\n\n/**\n * Do an amount of stun recovery.\n * @param power\n */\nvoid BattleUnit::healStun(int power)\n{\n\t_stunlevel -= power;\n\tif (_stunlevel < 0) _stunlevel = 0;\n}\n\nint BattleUnit::getStunlevel() const\n{\n\treturn _stunlevel;\n}\n\nbool BattleUnit::hasNegativeHealthRegen() const\n{\n\tif (_health > 0)\n\t{\n\t\tint HPRecovery = 0;\n\n\t\t// apply soldier bonuses\n\t\tif (_geoscapeSoldier)\n\t\t{\n\t\t\tfor (const auto* bonusRule : *_geoscapeSoldier->getBonuses(nullptr))\n\t\t\t{\n\t\t\t\tHPRecovery += bonusRule->getHealthRecovery(this);\n\t\t\t}\n\t\t}\n\n\t\treturn _armor->getHealthRecovery(this, HPRecovery) < 0;\n\t}\n\treturn false;\n}\n\n/**\n * Raises a unit's stun level sufficiently so that the unit is ready to become unconscious.\n * Used when another unit falls on top of this unit.\n * Zombified units first convert to their spawn unit.\n * @param battle Pointer to the battlescape game.\n */\nvoid BattleUnit::knockOut(BattlescapeGame *battle)\n{\n\tif (_spawnUnit)\n\t{\n\t\tsetRespawn(false);\n\t\tBattleUnit *newUnit = battle->convertUnit(this);\n\n\t\tif (newUnit)\n\t\t{\n\t\t\tif (newUnit->getSpawnUnit())\n\t\t\t{\n\t\t\t\t//scripts or rulesets could make new chryssalid from chryssalid, this means we could have infinite loop there\n\t\t\t\t//setting null will break it\n\t\t\t\tnewUnit->clearSpawnUnit();\n\t\t\t}\n\n\t\t\tnewUnit->knockOut(battle);\n\t\t}\n\t}\n\telse\n\t{\n\t\t_stunlevel = std::max(_health, 1);\n\t}\n}\n\n/**\n * Initialises the falling sequence. Occurs after death or stunned.\n */\nvoid BattleUnit::startFalling()\n{\n\t_status = STATUS_COLLAPSING;\n\t_fallPhase = 0;\n\t_turnsSinceStunned = 0;\n}\n\n/**\n * Advances the phase of falling sequence.\n */\nvoid BattleUnit::keepFalling()\n{\n\t_fallPhase++;\n\tif (_fallPhase == _armor->getDeathFrames())\n\t{\n\t\t_fallPhase--;\n\t\tif (_health <= 0)\n\t\t{\n\t\t\t_status = STATUS_DEAD;\n\t\t}\n\t\telse\n\t\t\t_status = STATUS_UNCONSCIOUS;\n\t}\n}\n\n/**\n * Set final falling state. Skipping animation.\n */\nvoid BattleUnit::instaFalling()\n{\n\tstartFalling();\n\t_fallPhase =  _armor->getDeathFrames() - 1;\n\tif (_health <= 0)\n\t{\n\t\t_status = STATUS_DEAD;\n\t}\n\telse\n\t{\n\t\t_status = STATUS_UNCONSCIOUS;\n\t}\n}\n\n\n/**\n * Returns the phase of the falling sequence.\n * @return phase\n */\nint BattleUnit::getFallingPhase() const\n{\n\treturn _fallPhase;\n}\n\n/**\n * Returns whether the soldier is out of combat, dead or unconscious.\n * A soldier that is out, cannot perform any actions, cannot be selected, but it's still a unit.\n * @return flag if out or not.\n */\nbool BattleUnit::isOut() const\n{\n\treturn _status == STATUS_DEAD || _status == STATUS_UNCONSCIOUS || isIgnored();\n}\n\n/**\n * Return true when unit stun level is greater that current health or unit have no health.\n * @return true if unit should be knockout.\n */\nbool BattleUnit::isOutThresholdExceed() const\n{\n\treturn getHealth() <= 0 || getHealth() <= getStunlevel();\n}\n\n/**\n * Unit is removed from game.\n */\nbool BattleUnit::isIgnored() const\n{\n\treturn _status == STATUS_IGNORE_ME;\n}\n\n/**\n * Get the number of time units a certain action takes.\n * @param actionType\n * @param item\n * @return TUs\n */\nRuleItemUseCost BattleUnit::getActionTUs(BattleActionType actionType, const BattleItem *item) const\n{\n\tif (item == 0)\n\t{\n\t\treturn 0;\n\t}\n\treturn getActionTUs(actionType, item->getRules());\n}\n\n/**\n * Get the number of time units a certain skill action takes.\n * @param actionType\n * @param skillRules\n * @return TUs\n */\nRuleItemUseCost BattleUnit::getActionTUs(BattleActionType actionType, const RuleSkill *skillRules) const\n{\n\tif (skillRules == 0)\n\t{\n\t\treturn 0;\n\t}\n\tRuleItemUseCost cost(skillRules->getCost());\n\tapplyPercentages(cost, skillRules->getFlat());\n\n\treturn cost;\n}\n\n/**\n * Get the number of time units a certain action takes.\n * @param actionType\n * @param item\n * @return TUs\n */\nRuleItemUseCost BattleUnit::getActionTUs(BattleActionType actionType, const RuleItem *item) const\n{\n\tRuleItemUseCost cost;\n\tif (item != 0)\n\t{\n\t\tRuleItemUseFlat flat = item->getFlatUse();\n\t\tswitch (actionType)\n\t\t{\n\t\t\tcase BA_PRIME:\n\t\t\t\tflat = item->getFlatPrime();\n\t\t\t\tcost = item->getCostPrime();\n\t\t\t\tbreak;\n\t\t\tcase BA_UNPRIME:\n\t\t\t\tflat = item->getFlatUnprime();\n\t\t\t\tcost = item->getCostUnprime();\n\t\t\t\tbreak;\n\t\t\tcase BA_THROW:\n\t\t\t\tflat = item->getFlatThrow();\n\t\t\t\tcost = item->getCostThrow();\n\t\t\t\tbreak;\n\t\t\tcase BA_AUTOSHOT:\n\t\t\t\tflat = item->getFlatAuto();\n\t\t\t\tcost = item->getCostAuto();\n\t\t\t\tbreak;\n\t\t\tcase BA_SNAPSHOT:\n\t\t\t\tflat = item->getFlatSnap();\n\t\t\t\tcost = item->getCostSnap();\n\t\t\t\tbreak;\n\t\t\tcase BA_HIT:\n\t\t\t\tflat = item->getFlatMelee();\n\t\t\t\tcost = item->getCostMelee();\n\t\t\t\tbreak;\n\t\t\tcase BA_LAUNCH:\n\t\t\tcase BA_AIMEDSHOT:\n\t\t\t\tflat = item->getFlatAimed();\n\t\t\t\tcost = item->getCostAimed();\n\t\t\t\tbreak;\n\t\t\tcase BA_USE:\n\t\t\t\tcost = item->getCostUse();\n\t\t\t\tbreak;\n\t\t\tcase BA_MINDCONTROL:\n\t\t\t\tcost = item->getCostMind();\n\t\t\t\tbreak;\n\t\t\tcase BA_PANIC:\n\t\t\t\tcost = item->getCostPanic();\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\tapplyPercentages(cost, flat);\n\t}\n\treturn cost;\n}\n\nvoid BattleUnit::applyPercentages(RuleItemUseCost &cost, const RuleItemUseFlat &flat) const\n{\n\t{\n\t\t// if it's a percentage, apply it to unit TUs\n\t\tif (!flat.Time && cost.Time)\n\t\t{\n\t\t\tcost.Time = std::max(1, (int)floor(getBaseStats()->tu * cost.Time / 100.0f));\n\t\t}\n\t\t// if it's a percentage, apply it to unit Energy\n\t\tif (!flat.Energy && cost.Energy)\n\t\t{\n\t\t\tcost.Energy = std::max(1, (int)floor(getBaseStats()->stamina * cost.Energy / 100.0f));\n\t\t}\n\t\t// if it's a percentage, apply it to unit Morale\n\t\tif (!flat.Morale && cost.Morale)\n\t\t{\n\t\t\tcost.Morale = std::max(1, (int)floor((110 - getBaseStats()->bravery) * cost.Morale / 100.0f));\n\t\t}\n\t\t// if it's a percentage, apply it to unit Health\n\t\tif (!flat.Health && cost.Health)\n\t\t{\n\t\t\tcost.Health = std::max(1, (int)floor(getBaseStats()->health * cost.Health / 100.0f));\n\t\t}\n\t\t// if it's a percentage, apply it to unit Health\n\t\tif (!flat.Stun && cost.Stun)\n\t\t{\n\t\t\tcost.Stun = std::max(1, (int)floor(getBaseStats()->health * cost.Stun / 100.0f));\n\t\t}\n\t\t// if it's a percentage, apply it to unit Mana\n\t\tif (!flat.Mana && cost.Mana)\n\t\t{\n\t\t\tcost.Mana = std::max(1, (int)floor(getBaseStats()->mana * cost.Mana / 100.0f));\n\t\t}\n\t}\n}\n\n/**\n * Spend time units if it can. Return false if it can't.\n * @param tu\n * @return flag if it could spend the time units or not.\n */\nbool BattleUnit::spendTimeUnits(int tu)\n{\n\tif (tu <= _tu)\n\t{\n\t\t_tu -= tu;\n\t\treturn true;\n\t}\n\telse\n\t{\n\t\treturn false;\n\t}\n}\n\n/**\n * Spend energy  if it can. Return false if it can't.\n * @param energy\n * @return flag if it could spend the time units or not.\n */\nbool BattleUnit::spendEnergy(int energy)\n{\n\tif (energy <= _energy)\n\t{\n\t\t_energy -= energy;\n\t\treturn true;\n\t}\n\telse\n\t{\n\t\treturn false;\n\t}\n}\n\n/**\n * Spend resources cost without checking.\n * @param cost\n */\nvoid BattleUnit::spendCost(const RuleItemUseCost& cost)\n{\n\t_tu -= cost.Time;\n\t_energy -= cost.Energy;\n\t_morale -= cost.Morale;\n\t_health -= cost.Health;\n\t_stunlevel += cost.Stun;\n\t_mana -= cost.Mana;\n}\n\n/**\n * Clear number of time units.\n */\nvoid BattleUnit::clearTimeUnits()\n{\n\t_tu = 0;\n}\n\n/**\n * Reset time units and energy.\n */\nvoid BattleUnit::resetTimeUnitsAndEnergy()\n{\n\t_tu = _stats.tu;\n\t_energy = _stats.stamina;\n}\n\n/**\n * Add this unit to the list of visible units. Returns true if this is a new one.\n * @param unit\n * @return\n */\nbool BattleUnit::addToVisibleUnits(BattleUnit *unit)\n{\n\tbool add = true;\n\tfor (auto* bu : _unitsSpottedThisTurn)\n\t{\n\t\tif (bu == unit)\n\t\t{\n\t\t\tadd = false;\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (add)\n\t{\n\t\t_unitsSpottedThisTurn.push_back(unit);\n\t}\n\tfor (auto* bu : _visibleUnits)\n\t{\n\t\tif (bu == unit)\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\t_visibleUnits.push_back(unit);\n\treturn true;\n}\n\n/**\n* Removes the given unit from the list of visible units.\n* @param unit The unit to add to our visibility cache.\n* @return true if unit found and removed\n*/\nbool BattleUnit::removeFromVisibleUnits(BattleUnit *unit)\n{\n\tif (!_visibleUnits.size()) {\n\t\treturn false;\n\t}\n\tauto i = std::find(_visibleUnits.begin(), _visibleUnits.end(), unit);\n\tif (i == _visibleUnits.end())\n\t{\n\t\treturn false;\n\t}\n\t//Slow to remove stuff from vector as it shuffles all the following items. Swap in rearmost element before removal.\n\t(*i) = *(_visibleUnits.end() - 1);\n\t_visibleUnits.pop_back();\n\treturn true;\n}\n\n/**\n* Checks if the given unit is on the list of visible units.\n* @param unit The unit to check whether we have in our visibility cache.\n* @return true if on the visible list or of the same faction\n*/\nbool BattleUnit::hasVisibleUnit(const BattleUnit *unit) const\n{\n\tif (getFaction() == unit->getFaction())\n\t{\n\t\t//Units of same faction are always visible, but not stored in the visible unit list\n\t\treturn true;\n\t}\n\treturn std::find(_visibleUnits.begin(), _visibleUnits.end(), unit) != _visibleUnits.end();\n}\n\n/**\n * Get the pointer to the vector of visible units.\n * @return pointer to vector.\n */\nstd::vector<BattleUnit*> *BattleUnit::getVisibleUnits()\n{\n\treturn &_visibleUnits;\n}\n\n/**\n * Clear visible units.\n */\nvoid BattleUnit::clearVisibleUnits()\n{\n\t_visibleUnits.clear();\n}\n\n/**\n * Add this unit to the list of visible tiles.\n * @param tile that we're now able to see.\n * @return true if a new tile.\n */\nbool BattleUnit::addToVisibleTiles(Tile *tile)\n{\n\t//Only add once, otherwise we're going to mess up the visibility value and make trouble for the AI (if sneaky).\n\tif (_visibleTilesLookup.insert(tile).second)\n\t{\n\t\ttile->setVisible(1);\n\t\t_visibleTiles.push_back(tile);\n\t\treturn true;\n\t}\n\treturn false;\n}\n\n/**\n * Get the pointer to the vector of visible tiles.\n * @return pointer to vector.\n */\nconst std::vector<Tile*> *BattleUnit::getVisibleTiles()\n{\n\treturn &_visibleTiles;\n}\n\n/**\n * Clears visible tiles. Also reduces the associated visibility counter used by the AI.\n */\nvoid BattleUnit::clearVisibleTiles()\n{\n\tfor (auto* tile : _visibleTiles)\n\t{\n\t\ttile->setVisible(-1);\n\t}\n\t_visibleTilesLookup.clear();\n\t_visibleTiles.clear();\n}\n\n/**\n * Get accuracy of different types of psi attack.\n * @param actionType Psi attack type.\n * @param item Psi-Amp.\n * @return Attack bonus.\n */\nint BattleUnit::getPsiAccuracy(BattleActionAttack::ReadOnly attack)\n{\n\tauto actionType = attack.type;\n\tauto item = attack.weapon_item;\n\n\tint psiAcc = 0;\n\tif (actionType == BA_MINDCONTROL)\n\t{\n\t\tpsiAcc = item->getRules()->getAccuracyMind();\n\t}\n\telse if (actionType == BA_PANIC)\n\t{\n\t\tpsiAcc = item->getRules()->getAccuracyPanic();\n\t}\n\telse if (actionType == BA_USE)\n\t{\n\t\tpsiAcc = item->getRules()->getAccuracyUse();\n\t}\n\n\tpsiAcc += item->getRules()->getAccuracyMultiplier(attack);\n\n\treturn psiAcc;\n}\n\n/**\n * Calculate firing accuracy.\n * Formula = accuracyStat * weaponAccuracy * kneeling bonus(1.15) * one-handPenalty(0.8) * woundsPenalty(% health) * critWoundsPenalty (-10%/wound)\n * @param actionType\n * @param item\n * @return firing Accuracy\n */\nint BattleUnit::getFiringAccuracy(BattleActionAttack::ReadOnly attack, const Mod *mod)\n{\n\tauto actionType = attack.type;\n\tauto item = attack.weapon_item;\n\tconst int modifier = attack.attacker->getAccuracyModifier(item);\n\tint result = 0;\n\tbool kneeled = attack.attacker->_kneeled;\n\n\tif (actionType == BA_SNAPSHOT)\n\t{\n\t\tresult = item->getRules()->getAccuracyMultiplier(attack) * item->getRules()->getAccuracySnap() / 100;\n\t}\n\telse if (actionType == BA_AIMEDSHOT || actionType == BA_LAUNCH)\n\t{\n\t\tresult = item->getRules()->getAccuracyMultiplier(attack) * item->getRules()->getAccuracyAimed() / 100;\n\t}\n\telse if (actionType == BA_AUTOSHOT)\n\t{\n\t\tresult = item->getRules()->getAccuracyMultiplier(attack) * item->getRules()->getAccuracyAuto() / 100;\n\t}\n\telse if (actionType == BA_HIT)\n\t{\n\t\tkneeled = false;\n\t\tresult = item->getRules()->getMeleeMultiplier(attack) * item->getRules()->getAccuracyMelee() / 100;\n\t}\n\telse if (actionType == BA_THROW)\n\t{\n\t\tkneeled = false;\n\t\tresult = item->getRules()->getThrowMultiplier(attack) * item->getRules()->getAccuracyThrow() / 100;\n\t}\n\telse if (actionType == BA_CQB)\n\t{\n\t\tkneeled = false;\n\t\tresult = item->getRules()->getCloseQuartersMultiplier(attack) * item->getRules()->getAccuracyCloseQuarters(mod) / 100;\n\t}\n\n\tif (kneeled)\n\t{\n\t\tresult = result * item->getRules()->getKneelBonus(mod) / 100;\n\t}\n\n\tif (item->getRules()->isTwoHanded() && actionType != BA_THROW)\n\t{\n\t\t// two handed weapon, means one hand should be empty\n\t\tif (attack.attacker->getRightHandWeapon() != 0 && attack.attacker->getLeftHandWeapon() != 0)\n\t\t{\n\t\t\tresult = result * item->getRules()->getOneHandedPenalty(mod) / 100;\n\t\t}\n\t\telse if (item->getRules()->isSpecialUsingEmptyHand())\n\t\t{\n\t\t\t// for special weapons that use an empty hand... already one hand with an item is enough for the penalty to apply\n\t\t\tif (attack.attacker->getRightHandWeapon() != 0 || attack.attacker->getLeftHandWeapon() != 0)\n\t\t\t{\n\t\t\t\tresult = result * item->getRules()->getOneHandedPenalty(mod) / 100;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result * modifier / 100;\n}\n\n/**\n * To calculate firing accuracy. Takes health and fatal wounds into account.\n * Formula = accuracyStat * woundsPenalty(% health) * critWoundsPenalty (-10%/wound)\n * @param item the item we are shooting right now.\n * @return modifier\n */\nint BattleUnit::getAccuracyModifier(const BattleItem *item) const\n{\n\tint wounds = _fatalWounds[BODYPART_HEAD];\n\n\tif (item)\n\t{\n\t\tif (item->getRules()->isTwoHanded())\n\t\t{\n\t\t\twounds += _fatalWounds[BODYPART_RIGHTARM] + _fatalWounds[BODYPART_LEFTARM];\n\t\t}\n\t\telse\n\t\t{\n\t\t\tauto slot = item->getSlot();\n\t\t\tif (slot)\n\t\t\t{\n\t\t\t\t// why broken hands should affect your aim if you shoot not using them?\n\t\t\t\tif (slot->isRightHand())\n\t\t\t\t{\n\t\t\t\t\twounds += _fatalWounds[BODYPART_RIGHTARM];\n\t\t\t\t}\n\t\t\t\tif (slot->isLeftHand())\n\t\t\t\t{\n\t\t\t\t\twounds += _fatalWounds[BODYPART_LEFTARM];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn std::max(10, 25 * _health / getBaseStats()->health + 75 + -10 * wounds);\n}\n\n/**\n * Set the armor value of a certain armor side.\n * @param armor Amount of armor.\n * @param side The side of the armor.\n */\nvoid BattleUnit::setArmor(int armor, UnitSide side)\n{\n\t_currentArmor[side] = Clamp(armor, 0, _maxArmor[side]);\n}\n\n/**\n * Get the armor value of a certain armor side.\n * @param side The side of the armor.\n * @return Amount of armor.\n */\nint BattleUnit::getArmor(UnitSide side) const\n{\n\treturn _currentArmor[side];\n}\n\n/**\n * Set the max armor value of a certain armor side.\n * @param armor Amount of armor.\n * @param side The side of the armor.\n */\nvoid BattleUnit::setMaxArmor(int armor, UnitSide side)\n{\n\t_maxArmor[side] = Clamp(armor, 0, UnitStats::BaseStatLimit);\n\t_currentArmor[side] = Clamp(_currentArmor[side], 0, _maxArmor[side]);\n}\n\n\n/**\n * Get the max armor value of a certain armor side.\n * @param side The side of the armor.\n * @return Amount of armor.\n */\nint BattleUnit::getMaxArmor(UnitSide side) const\n{\n\treturn _maxArmor[side];\n}\n\n/**\n * Get total amount of fatal wounds this unit has.\n * @return Number of fatal wounds.\n */\nint BattleUnit::getFatalWounds() const\n{\n\tint sum = 0;\n\tfor (int i = 0; i < BODYPART_MAX; ++i)\n\t\tsum += _fatalWounds[i];\n\treturn sum;\n}\n\n\n/**\n * Little formula to calculate reaction score.\n * @return Reaction score.\n */\ndouble BattleUnit::getReactionScore() const\n{\n\t//(Reactions Stat) x (Current Time Units / Max TUs)\n\tdouble score = ((double)getBaseStats()->reactions * (double)getTimeUnits()) / (double)getBaseStats()->tu;\n\treturn score;\n}\n\n/**\n * Helper function preparing Time Units recovery at beginning of turn.\n * @param tu New time units for this turn.\n */\nvoid BattleUnit::prepareTimeUnits(int tu)\n{\n\tif (!isOut())\n\t{\n\t\t// Add to previous turn TU, if regen is less than normal unit need couple of turns to regen full bar\n\t\tsetValueMax(_tu, tu, 0, getBaseStats()->tu);\n\n\t\t// Apply reductions, if new TU == 0 then it could make not spend TU decay\n\t\tfloat encumbrance = (float)getBaseStats()->strength / (float)getCarriedWeight();\n\t\tif (encumbrance < 1)\n\t\t{\n\t\t  _tu = int(encumbrance * _tu);\n\t\t}\n\t\t// Each fatal wound to the left or right leg reduces the soldier's TUs by 10%.\n\t\t_tu -= (_tu * ((_fatalWounds[BODYPART_LEFTLEG]+_fatalWounds[BODYPART_RIGHTLEG]) * 10))/100;\n\n\t\tsetValueMax(_tu, 0, 0, getBaseStats()->tu);\n\t}\n}\n\n/**\n * Helper function preparing Energy recovery at beginning of turn.\n * @param energy Energy grain this turn.\n */\nvoid BattleUnit::prepareEnergy(int energy)\n{\n\tif (!isOut())\n\t{\n\t\t// Each fatal wound to the body reduces the soldier's energy recovery by 10%.\n\t\tenergy -= (_energy * (_fatalWounds[BODYPART_TORSO] * 10))/100;\n\n\t\tsetValueMax(_energy, energy, 0, getBaseStats()->stamina);\n\t}\n}\n\n/**\n * Helper function preparing Health recovery at beginning of turn.\n * @param health Health grain this turn.\n */\nvoid BattleUnit::prepareHealth(int health)\n{\n\t// suffer from fatal wounds\n\thealth -= getFatalWounds();\n\n\t// suffer from fire\n\tif (!_hitByFire && _fire > 0)\n\t{\n\t\thealth -= reduceByResistance(RNG::generate(Mod::FIRE_DAMAGE_RANGE[0], Mod::FIRE_DAMAGE_RANGE[1]), DT_IN);\n\t\t_fire--;\n\t}\n\n\tsetValueMax(_health, health, -UnitStats::OverkillMultipler * _stats.health, _stats.health);\n\n\t// if unit is dead, AI state should be gone\n\tif (_health <= 0 && _currentAIState)\n\t{\n\t\tdelete _currentAIState;\n\t\t_currentAIState = 0;\n\t}\n}\n\n/**\n * Helper function preparing Mana recovery at beginning of turn.\n * @param mana Mana gain this turn.\n */\nvoid BattleUnit::prepareMana(int mana)\n{\n\tif (!isOut())\n\t{\n\t\tsetValueMax(_mana, mana, 0, getBaseStats()->mana);\n\t}\n}\n\n/**\n * Helper function preparing Stun recovery at beginning of turn.\n * @param stun Stun damage reduction this turn.\n */\nvoid BattleUnit::prepareStun(int stun)\n{\n\tif (isSmallUnit() || !isOut())\n\t{\n\t\thealStun(stun);\n\t}\n}\n\n/**\n * Helper function preparing Morale recovery at beginning of turn.\n * @param morale Morale grain this turn.\n */\nvoid BattleUnit::prepareMorale(int morale)\n{\n\tif (!isOut())\n\t{\n\t\tmoraleChange(morale);\n\t\tint chance = 100 - (2 * getMorale());\n\t\tif (RNG::percent(chance))\n\t\t{\n\t\t\tint berserkChance = _unitRules ? _unitRules->getBerserkChance() : -1; // -1 represents true 1/3 (33.33333...%)\n\t\t\tbool berserk = false;\n\t\t\tif (berserkChance == -1)\n\t\t\t{\n\t\t\t\tberserk = (RNG::generate(0, 2) == 0); // vanilla OG\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tberserk = RNG::percent(berserkChance);\n\t\t\t}\n\t\t\t_status = (berserk ? STATUS_BERSERK : STATUS_PANICKING); // 33% chance of berserk, panic can mean freeze or flee, but that is determined later\n\t\t\t_wantsToSurrender = true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// successfully avoided panic\n\t\t\t// increase bravery experience counter\n\t\t\tif (chance > 1)\n\t\t\t\taddBraveryExp();\n\t\t}\n\t}\n\telse\n\t{\n\t\t// knocked out units are willing to surrender if they wake up\n\t\tif (_status == STATUS_UNCONSCIOUS)\n\t\t\t_wantsToSurrender = true;\n\t}\n}\n/**\n * Prepare for a new turn.\n */\nvoid BattleUnit::prepareNewTurn(bool fullProcess)\n{\n\tif (isIgnored())\n\t{\n\t\treturn;\n\t}\n\n\t_isSurrendering = false;\n\t_unitsSpottedThisTurn.clear();\n\t_meleeAttackedBy.clear();\n\n\t_hitByFire = false;\n\t_dontReselect = false;\n\t_aiMedikitUsed = false;\n\t_motionPoints = 0;\n\n\tif (!isOut())\n\t{\n\t\tincTurnsSinceStunned();\n\t}\n\n\t// don't give it back its TUs or anything this round\n\t// because it's no longer a unit of the team getting TUs back\n\tif (_faction != _originalFaction)\n\t{\n\t\t_faction = _originalFaction;\n\t\tif (_faction == FACTION_PLAYER && _currentAIState)\n\t\t{\n\t\t\tdelete _currentAIState;\n\t\t\t_currentAIState = 0;\n\t\t}\n\t\treturn;\n\t}\n\telse\n\t{\n\t\tupdateUnitStats(true, false);\n\t}\n\n\t// transition between stages, don't do damage or panic\n\tif (!fullProcess)\n\t{\n\t\tif (_kneeled)\n\t\t{\n\t\t\t// stand up if kneeling\n\t\t\t_kneeled = false;\n\t\t}\n\t\treturn;\n\t}\n\n\tupdateUnitStats(false, true);\n}\n\n/**\n * Update stats of unit.\n * @param tuAndEnergy\n * @param rest\n */\nvoid BattleUnit::updateUnitStats(bool tuAndEnergy, bool rest)\n{\n\t// snapshot of current stats\n\tint TURecovery = 0;\n\tint ENRecovery = 0;\n\n\tif (tuAndEnergy)\n\t{\n\t\t// apply soldier bonuses\n\t\tif (_geoscapeSoldier)\n\t\t{\n\t\t\tfor (const auto* bonusRule : *_geoscapeSoldier->getBonuses(nullptr))\n\t\t\t{\n\t\t\t\tTURecovery += bonusRule->getTimeRecovery(this);\n\t\t\t\tENRecovery += bonusRule->getEnergyRecovery(this);\n\t\t\t}\n\t\t}\n\n\t\t//unit update will be done after other stats are calculated and updated\n\t}\n\n\tif (rest)\n\t{\n\t\t// snapshot of current stats\n\t\tint HPRecovery = 0;\n\t\tint MNRecovery = 0;\n\t\tint MRRecovery = 0;\n\t\tint STRecovery = 0;\n\n\t\t// apply soldier bonuses\n\t\tif (_geoscapeSoldier)\n\t\t{\n\t\t\tfor (const auto* bonusRule : *_geoscapeSoldier->getBonuses(nullptr))\n\t\t\t{\n\t\t\t\tHPRecovery += bonusRule->getHealthRecovery(this);\n\t\t\t\tMNRecovery += bonusRule->getManaRecovery(this);\n\t\t\t\tMRRecovery += bonusRule->getMoraleRecovery(this);\n\t\t\t\tSTRecovery += bonusRule->getStunRegeneration(this);\n\t\t\t}\n\t\t}\n\n\t\t// update stats\n\t\tprepareHealth(_armor->getHealthRecovery(this, HPRecovery));\n\t\tprepareMana(_armor->getManaRecovery(this, MNRecovery));\n\t\tprepareMorale(_armor->getMoraleRecovery(this, MRRecovery));\n\t\tprepareStun(_armor->getStunRegeneration(this, STRecovery));\n\t}\n\n\tif (tuAndEnergy)\n\t{\n\t\t// update stats\n\t\tprepareTimeUnits(_armor->getTimeRecovery(this, TURecovery));\n\t\tprepareEnergy(_armor->getEnergyRecovery(this, ENRecovery));\n\t}\n}\n\n/**\n * Morale change with bounds check.\n * @param change can be positive or negative\n */\nvoid BattleUnit::moraleChange(int change)\n{\n\tif (!isFearable()) return;\n\n\t_morale += change;\n\tif (_morale > 100)\n\t\t_morale = 100;\n\tif (_morale < 0)\n\t\t_morale = 0;\n}\n\n/**\n * Get reduced morale change value by bravery.\n */\nint BattleUnit::reduceByBravery(int moraleChange) const\n{\n\treturn (110 - _stats.bravery) * moraleChange / 100;\n}\n\n/**\n * Calculate power reduction by resistances.\n */\nint BattleUnit::reduceByResistance(int power, ItemDamageType resistType) const\n{\n\treturn (int)floor(power * _armor->getDamageModifier(resistType));\n}\n\n/**\n * Mark this unit as not reselectable.\n */\nvoid BattleUnit::dontReselect()\n{\n\t_dontReselect = true;\n}\n\n/**\n * Mark this unit as reselectable.\n */\nvoid BattleUnit::allowReselect()\n{\n\t_dontReselect = false;\n}\n\n\n/**\n * Check whether reselecting this unit is allowed.\n * @return bool\n */\nbool BattleUnit::reselectAllowed() const\n{\n\treturn !_dontReselect;\n}\n\n/**\n * Set the amount of turns this unit is on fire. 0 = no fire.\n * @param fire : amount of turns this tile is on fire.\n */\nvoid BattleUnit::setFire(int fire)\n{\n\tif (_specab != SPECAB_BURNFLOOR && _specab != SPECAB_BURN_AND_EXPLODE)\n\t\t_fire = fire;\n}\n\n/**\n * Get the amount of turns this unit is on fire. 0 = no fire.\n * @return fire : amount of turns this tile is on fire.\n */\nint BattleUnit::getFire() const\n{\n\treturn _fire;\n}\n\n/**\n * Get the pointer to the vector of inventory items.\n * @return pointer to vector.\n */\nstd::vector<BattleItem*> *BattleUnit::getInventory()\n{\n\treturn &_inventory;\n}\n\n/**\n * Get the pointer to the vector of inventory items.\n * @return pointer to vector.\n */\nconst std::vector<BattleItem*> *BattleUnit::getInventory() const\n{\n\treturn &_inventory;\n}\n\n/**\n * Fit item into inventory slot.\n * @param slot Slot to fit.\n * @param item Item to fit.\n * @return True if succeeded, false otherwise.\n */\nbool BattleUnit::fitItemToInventory(const RuleInventory *slot, BattleItem *item)\n{\n\tauto rule = item->getRules();\n\tif (rule->canBePlacedIntoInventorySection(slot) == false)\n\t{\n\t\treturn false;\n\t}\n\tif (slot->getType() == INV_HAND)\n\t{\n\t\tif (!Inventory::overlapItems(this, item, slot))\n\t\t{\n\t\t\titem->moveToOwner(this);\n\t\t\titem->setSlot(slot);\n\t\t\treturn true;\n\t\t}\n\t}\n\telse if (slot->getType() == INV_SLOT)\n\t{\n\t\tfor (const RuleSlot &rs : *slot->getSlots())\n\t\t{\n\t\t\tif (!Inventory::overlapItems(this, item, slot, rs.x, rs.y) && slot->fitItemInSlot(rule, rs.x, rs.y))\n\t\t\t{\n\t\t\t\titem->moveToOwner(this);\n\t\t\t\titem->setSlot(slot);\n\t\t\t\titem->setSlotX(rs.x);\n\t\t\t\titem->setSlotY(rs.y);\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Adds an item to an XCom soldier (auto-equip).\n * @param item Pointer to the Item.\n * @param mod Pointer to the Mod.\n * @param save Pointer to the saved battle game for storing items.\n * @param allowSecondClip allow the unit to take a second clip or not. (only applies to xcom soldiers, aliens are allowed regardless of this flag)\n * @param allowAutoLoadout allow auto equip of weapons for solders.\n * @param allowUnloadedWeapons allow equip of weapons without ammo.\n * @return if the item was placed or not.\n */\nbool BattleUnit::addItem(BattleItem *item, const Mod *mod, bool allowSecondClip, bool allowAutoLoadout, bool allowUnloadedWeapons)\n{\n\tRuleInventory *rightHand = mod->getInventoryRightHand();\n\tRuleInventory *leftHand = mod->getInventoryLeftHand();\n\tbool placed = false;\n\tbool loaded = false;\n\tconst RuleItem *rule = item->getRules();\n\tint weight = 0;\n\n\tbool isStandardPlayerUnit = getFaction() == FACTION_PLAYER && hasInventory() && !isSummonedPlayerUnit();\n\n\t// tanks and aliens don't care about weight or multiple items,\n\t// their loadouts are defined in the rulesets and more or less set in stone.\n\tif (isStandardPlayerUnit)\n\t{\n\t\tweight = getCarriedWeight() + item->getTotalWeight();\n\t\t// allow all weapons to be loaded by avoiding this check,\n\t\t// they'll return false later anyway if the unit has something in his hand.\n\t\tif (rule->getBattleType() != BT_FIREARM && rule->getBattleType() != BT_MELEE)\n\t\t{\n\t\t\tint tally = 0;\n\t\t\tfor (auto* bi : *getInventory())\n\t\t\t{\n\t\t\t\tif (rule->getType() == bi->getRules()->getType())\n\t\t\t\t{\n\t\t\t\t\tif (allowSecondClip && rule->getBattleType() == BT_AMMO)\n\t\t\t\t\t{\n\t\t\t\t\t\ttally++;\n\t\t\t\t\t\tif (tally == 2)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// we already have one, thanks.\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// place fixed weapon\n\tif (rule->isFixed())\n\t{\n\t\t// either in the default slot provided in the ruleset\n\t\tif (rule->getDefaultInventorySlot())\n\t\t{\n\t\t\tRuleInventory *defaultSlot = const_cast<RuleInventory *>(rule->getDefaultInventorySlot());\n\t\t\tBattleItem *defaultSlotWeapon = getItem(defaultSlot);\n\t\t\tif (!defaultSlotWeapon)\n\t\t\t{\n\t\t\t\titem->moveToOwner(this);\n\t\t\t\titem->setSlot(defaultSlot);\n\t\t\t\titem->setSlotX(rule->getDefaultInventorySlotX());\n\t\t\t\titem->setSlotY(rule->getDefaultInventorySlotY());\n\t\t\t\tplaced = true;\n\t\t\t\titem->setXCOMProperty(getFaction() == FACTION_PLAYER && !isSummonedPlayerUnit());\n\t\t\t\tif (item->getRules()->getTurretType() > -1)\n\t\t\t\t{\n\t\t\t\t\tsetTurretType(item->getRules()->getTurretType());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// or in the left/right hand\n\t\tif (!placed && (fitItemToInventory(rightHand, item) || fitItemToInventory(leftHand, item)))\n\t\t{\n\t\t\tplaced = true;\n\t\t\titem->setXCOMProperty(getFaction() == FACTION_PLAYER && !isSummonedPlayerUnit());\n\t\t\tif (item->getRules()->getTurretType() > -1)\n\t\t\t{\n\t\t\t\tsetTurretType(item->getRules()->getTurretType());\n\t\t\t}\n\t\t}\n\t\treturn placed;\n\t}\n\n\t// we equip item only if we have skill to use it.\n\tif (getBaseStats()->psiSkill <= 0 && rule->isPsiRequired())\n\t{\n\t\treturn false;\n\t}\n\n\tif (rule->isManaRequired() && getOriginalFaction() == FACTION_PLAYER)\n\t{\n\t\t// don't auto-equip items that require mana for now, maybe reconsider in the future\n\t\treturn false;\n\t}\n\n\tbool keep = true;\n\tswitch (rule->getBattleType())\n\t{\n\tcase BT_FIREARM:\n\tcase BT_MELEE:\n\t\tif (item->haveAnyAmmo() || getFaction() != FACTION_PLAYER || !hasInventory() || allowUnloadedWeapons)\n\t\t{\n\t\t\tloaded = true;\n\t\t}\n\n\t\tif (loaded && (getGeoscapeSoldier() == 0 || allowAutoLoadout))\n\t\t{\n\t\t\tif (getBaseStats()->strength * 0.66 >= weight) // weight is always considered 0 for aliens\n\t\t\t{\n\t\t\t\t// C1 - vanilla right-hand main weapon (and OXCE left-hand second main weapon)\n\t\t\t\tif (fitItemToInventory(rightHand, item))\n\t\t\t\t{\n\t\t\t\t\tplaced = true;\n\t\t\t\t}\n\t\t\t\tbool allowTwoMainWeapons = (getFaction() != FACTION_PLAYER) || _armor->getAllowTwoMainWeapons();\n\t\t\t\tif (!placed && allowTwoMainWeapons && fitItemToInventory(leftHand, item))\n\t\t\t\t{\n\t\t\t\t\tplaced = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tbreak;\n\tcase BT_AMMO:\n\t\t{\n\t\t\tBattleItem *rightWeapon = getRightHandWeapon();\n\t\t\tBattleItem *leftWeapon = getLeftHandWeapon();\n\t\t\t// xcom weapons will already be loaded, aliens and tanks, however, get their ammo added afterwards.\n\t\t\t// so let's try to load them here.\n\t\t\tif (rightWeapon && (rightWeapon->getRules()->isFixed() || getFaction() != FACTION_PLAYER || allowUnloadedWeapons) &&\n\t\t\t\trightWeapon->isWeaponWithAmmo() && rightWeapon->setAmmoPreMission(item))\n\t\t\t{\n\t\t\t\tplaced = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (leftWeapon && (leftWeapon->getRules()->isFixed() || getFaction() != FACTION_PLAYER || allowUnloadedWeapons) &&\n\t\t\t\tleftWeapon->isWeaponWithAmmo() && leftWeapon->setAmmoPreMission(item))\n\t\t\t{\n\t\t\t\tplaced = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t// don't take ammo for weapons we don't have.\n\t\t\tkeep = (getFaction() != FACTION_PLAYER);\n\t\t\tif (rightWeapon)\n\t\t\t{\n\t\t\t\tif (rightWeapon->getRules()->getSlotForAmmo(rule) != -1)\n\t\t\t\t{\n\t\t\t\t\tkeep = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (leftWeapon)\n\t\t\t{\n\t\t\t\tif (leftWeapon->getRules()->getSlotForAmmo(rule) != -1)\n\t\t\t\t{\n\t\t\t\t\tkeep = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!keep)\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tFALLTHROUGH;\n\t\t}\n\tdefault:\n\t\tif (rule->getBattleType() == BT_PSIAMP && getFaction() == FACTION_HOSTILE)\n\t\t{\n\t\t\t// C2 - vanilla left-hand psi-amp for hostiles\n\t\t\tif (fitItemToInventory(rightHand, item) || fitItemToInventory(leftHand, item))\n\t\t\t{\n\t\t\t\tplaced = true;\n\t\t\t}\n\t\t}\n\t\telse if ((getGeoscapeSoldier() == 0 || allowAutoLoadout))\n\t\t{\n\t\t\tif (getBaseStats()->strength >= weight) // weight is always considered 0 for aliens\n\t\t\t{\n\t\t\t\t// D1 - default slot by item\n\t\t\t\tif (!placed && isStandardPlayerUnit)\n\t\t\t\t{\n\t\t\t\t\tif (item->getRules()->getDefaultInventorySlot())\n\t\t\t\t\t{\n\t\t\t\t\t\tconst RuleInventory* slot = item->getRules()->getDefaultInventorySlot();\n\t\t\t\t\t\tif (slot->getType() != INV_GROUND)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tplaced = fitItemToInventory(slot, item);\n\t\t\t\t\t\t\tif (placed)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// D2 - slot order by item category\n\t\t\t\tif (!placed && isStandardPlayerUnit)\n\t\t\t\t{\n\t\t\t\t\tauto* cat = item->getRules()->getFirstCategoryWithInvOrder(mod);\n\t\t\t\t\tif (cat)\n\t\t\t\t\t{\n\t\t\t\t\t\tfor (const auto& s : cat->getInvOrder())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tRuleInventory* slot = mod->getInventory(s);\n\t\t\t\t\t\t\tif (slot->getType() != INV_GROUND)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tplaced = fitItemToInventory(slot, item);\n\t\t\t\t\t\t\t\tif (placed)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// C3 - fallback: vanilla slot order by listOrder\n\t\t\t\tif (!placed)\n\t\t\t\t{\n\t\t\t\t\t// this is `n*(log(n) + log(n))` code, it could be `n` but we would lose predefined order, as `RuleItem` have them in effective in random order (depending on global memory allocations)\n\t\t\t\t\tfor (const auto& s : mod->getInvsList())\n\t\t\t\t\t{\n\t\t\t\t\t\tRuleInventory* slot = mod->getInventory(s);\n\t\t\t\t\t\tif (slot->getType() == INV_SLOT)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tplaced = fitItemToInventory(slot, item);\n\t\t\t\t\t\t\tif (placed)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tbreak;\n\t}\n\n\titem->setXCOMProperty(getFaction() == FACTION_PLAYER && !isSummonedPlayerUnit());\n\n\treturn placed;\n}\n\n/**\n * Let AI do their thing.\n * @param action AI action.\n */\nvoid BattleUnit::think(BattleAction *action)\n{\n\treloadAmmo();\n\tif (!_aiMedikitUsed)\n\t{\n\t\t// only perform once per turn\n\t\t_aiMedikitUsed = true;\n\t\twhile (_currentAIState->medikit_think(BMT_HEAL)) {}\n\t\twhile (_currentAIState->medikit_think(BMT_STIMULANT)) {}\n\t}\n\t_currentAIState->think(action);\n}\n\n/**\n * Changes the current AI state.\n * @param aiState Pointer to AI state.\n */\nvoid BattleUnit::setAIModule(AIModule *ai)\n{\n\tif (_currentAIState)\n\t{\n\t\tdelete _currentAIState;\n\t}\n\t_currentAIState = ai;\n}\n\n/**\n * Returns the current AI state.\n * @return Pointer to AI state.\n */\nAIModule *BattleUnit::getAIModule() const\n{\n\treturn _currentAIState;\n}\n\n/**\n * Gets weight value as hostile unit.\n */\nAIAttackWeight BattleUnit::getAITargetWeightAsHostile(const Mod *mod) const\n{\n\treturn _armor->getAITargetWeightAsHostile().getValueOr(mod->getAITargetWeightAsHostile());\n}\n\n/**\n * Gets weight value as civilian unit when consider by aliens.\n */\nAIAttackWeight BattleUnit::getAITargetWeightAsHostileCivilians(const Mod *mod) const\n{\n\treturn _armor->getAITargetWeightAsHostileCivilians().getValueOr(mod->getAITargetWeightAsHostileCivilians());\n}\n\n/**\n * Gets weight value as same faction unit.\n */\nAIAttackWeight BattleUnit::getAITargetWeightAsFriendly(const Mod *mod) const\n{\n\treturn _armor->getAITargetWeightAsFriendly().getValueOr(mod->getAITargetWeightAsFriendly());\n}\n\n/**\n * Gets weight value as neutral unit (xcom to civ or vice versa).\n */\nAIAttackWeight BattleUnit::getAITargetWeightAsNeutral(const Mod *mod) const\n{\n\treturn _armor->getAITargetWeightAsNeutral().getValueOr(mod->getAITargetWeightAsNeutral());\n}\n\n\n/**\n * Set whether this unit is visible.\n * @param flag\n */\nvoid BattleUnit::setVisible(bool flag)\n{\n\t_visible = flag;\n}\n\n\n/**\n * Get whether this unit is visible.\n * @return flag\n */\nbool BattleUnit::getVisible() const\n{\n\tif (getFaction() == FACTION_PLAYER || _armor->isAlwaysVisible())\n\t{\n\t\treturn true;\n\t}\n\telse\n\t{\n\t\treturn _visible;\n\t}\n}\n\n/**\n * Check if unit can fall down.\n * @param saveBattleGame\n */\nvoid BattleUnit::updateTileFloorState(SavedBattleGame *saveBattleGame)\n{\n\tif (_tile)\n\t{\n\t\t_haveNoFloorBelow = true;\n\n\t\tif (isBigUnit())\n\t\t{\n\t\t\tauto armorSize = _armor->getSize() - 1;\n\t\t\tauto newPos = _tile->getPosition();\n\t\t\tfor (int x = armorSize; x >= 0; --x)\n\t\t\t{\n\t\t\t\tfor (int y = armorSize; y >= 0; --y)\n\t\t\t\t{\n\t\t\t\t\tauto t = saveBattleGame->getTile(newPos + Position(x, y, 0));\n\t\t\t\t\tif (t)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (!t->hasNoFloor(saveBattleGame))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_haveNoFloorBelow = false;\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_haveNoFloorBelow &= _tile->hasNoFloor(saveBattleGame) && !_tile->hasLadder();\n\t\t}\n\t}\n\telse\n\t{\n\t\t_haveNoFloorBelow = false;\n\t}\n}\n/**\n * Sets the unit's tile it's standing on\n * @param tile Pointer to tile.\n * @param saveBattleGame Pointer to save to get tile below.\n */\nvoid BattleUnit::setTile(Tile *tile, SavedBattleGame *saveBattleGame)\n{\n\tif (_tile == tile)\n\t{\n\t\treturn;\n\t}\n\n\tauto armorSize = _armor->getSize() - 1;\n\t// Reset tiles moved from.\n\tif (_tile)\n\t{\n\t\tauto prevPos = _tile->getPosition();\n\t\tfor (int x = armorSize; x >= 0; --x)\n\t\t{\n\t\t\tfor (int y = armorSize; y >= 0; --y)\n\t\t\t{\n\t\t\t\tauto t = saveBattleGame->getTile(prevPos + Position(x,y, 0));\n\t\t\t\tif (t && t->getUnit() == this)\n\t\t\t\t{\n\t\t\t\t\tt->setUnit(nullptr);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t_tile = tile;\n\n\tupdateTileFloorState(saveBattleGame);\n\n\tif (!_tile)\n\t{\n\t\t_floating = false;\n\t\treturn;\n\t}\n\n\t// Update tiles moved to.\n\tauto newPos = _tile->getPosition();\n\tfor (int x = armorSize; x >= 0; --x)\n\t{\n\t\tfor (int y = armorSize; y >= 0; --y)\n\t\t{\n\t\t\tauto t = saveBattleGame->getTile(newPos + Position(x, y, 0));\n\t\t\tif (t)\n\t\t\t{\n\t\t\t\tt->setUnit(this);\n\t\t\t}\n\t\t}\n\t}\n\n\t// unit could have changed from flying to walking or vice versa\n\tif (_status == STATUS_WALKING && _haveNoFloorBelow && _movementType == MT_FLY)\n\t{\n\t\t_status = STATUS_FLYING;\n\t\t_floating = true;\n\t}\n\telse if (_status == STATUS_FLYING && !_haveNoFloorBelow && _verticalDirection == 0)\n\t{\n\t\t_status = STATUS_WALKING;\n\t\t_floating = false;\n\t}\n\telse if (_status == STATUS_UNCONSCIOUS)\n\t{\n\t\t_floating = _movementType == MT_FLY && _haveNoFloorBelow;\n\t}\n}\n\n/**\n * Set only unit tile without any additional logic.\n * Used only in before battle, other wise will break game.\n * Need call setTile after to fix links\n * @param tile\n */\nvoid BattleUnit::setInventoryTile(Tile *tile)\n{\n\t_tile = tile;\n}\n\n/**\n * Gets the unit's tile.\n * @return Tile\n */\nTile *BattleUnit::getTile() const\n{\n\treturn _tile;\n}\n\n\n/**\n * Gets the unit's creator.\n */\nBattleUnit *BattleUnit::getPreviousOwner()\n{\n\treturn _previousOwner;\n}\n\n/**\n * Gets the unit's creator.\n */\nconst BattleUnit *BattleUnit::getPreviousOwner() const\n{\n\treturn _previousOwner;\n}\n\n/**\n * Sets the unit's creator.\n */\nvoid BattleUnit::setPreviousOwner(BattleUnit *owner)\n{\n\t_previousOwner = owner;\n}\n\n/**\n * Checks if there's an inventory item in\n * the specified inventory position.\n * @param slot Inventory slot.\n * @param x X position in slot.\n * @param y Y position in slot.\n * @return Item in the slot, or NULL if none.\n */\nBattleItem *BattleUnit::getItem(const RuleInventory *slot, int x, int y) const\n{\n\t// Soldier items\n\tif (slot->getType() != INV_GROUND)\n\t{\n\t\tfor (auto* bi : _inventory)\n\t\t{\n\t\t\tif (bi->getSlot() == slot && bi->occupiesSlot(x, y))\n\t\t\t{\n\t\t\t\treturn bi;\n\t\t\t}\n\t\t}\n\t}\n\t// Ground items\n\telse if (_tile != 0)\n\t{\n\t\tfor (auto* bi : *_tile->getInventory())\n\t\t{\n\t\t\tif (bi->occupiesSlot(x, y))\n\t\t\t{\n\t\t\t\treturn bi;\n\t\t\t}\n\t\t}\n\t}\n\treturn 0;\n}\n\n/**\n * Get the \"main hand weapon\" from the unit.\n * @param quickest Whether to get the quickest weapon, default true\n * @return Pointer to item.\n */\nBattleItem *BattleUnit::getMainHandWeapon(bool quickest, bool reactions) const\n{\n\tBattleItem *weaponRightHand = getRightHandWeapon();\n\tBattleItem *weaponLeftHand = getLeftHandWeapon();\n\n\t// ignore weapons without ammo (rules out grenades)\n\tif (!weaponRightHand || !weaponRightHand->haveAnyAmmo())\n\t\tweaponRightHand = 0;\n\tif (!weaponLeftHand || !weaponLeftHand->haveAnyAmmo())\n\t\tweaponLeftHand = 0;\n\n\t// ignore disabled hands/weapons (player units only... to prevent abuse)\n\t// Note: there is another check later, but this one is still needed, so that also non-main weapons get a chance to be used in case the main weapon is disabled\n\tif (reactions && _faction == FACTION_PLAYER)\n\t{\n\t\tif (_reactionsDisabledForRightHand)\n\t\t\tweaponRightHand = nullptr;\n\t\tif (_reactionsDisabledForLeftHand)\n\t\t\tweaponLeftHand = nullptr;\n\t}\n\n\t// if there is only one weapon, it's easy:\n\tif (weaponRightHand && !weaponLeftHand)\n\t\treturn weaponRightHand;\n\telse if (!weaponRightHand && weaponLeftHand)\n\t\treturn weaponLeftHand;\n\telse if (!weaponRightHand && !weaponLeftHand)\n\t{\n\t\t// Allow *AI* to use also a special weapon, but only when both hands are empty\n\t\t// Only need to check for firearms since melee/psi is handled elsewhere\n\t\tBattleItem* specialWeapon = getSpecialWeapon(BT_FIREARM);\n\t\tif (specialWeapon)\n\t\t{\n\t\t\treturn specialWeapon;\n\t\t}\n\n\t\treturn 0;\n\t}\n\n\t// otherwise pick the one with the least snapshot TUs\n\tint tuRightHand = getActionTUs(BA_SNAPSHOT, weaponRightHand).Time;\n\tint tuLeftHand = getActionTUs(BA_SNAPSHOT, weaponLeftHand).Time;\n\tBattleItem *weaponCurrentHand = const_cast<BattleItem*>(getActiveHand(weaponLeftHand, weaponRightHand));\n\t//prioritize blaster\n\tif (!quickest && _faction != FACTION_PLAYER)\n\t{\n\t\tif (weaponRightHand->getCurrentWaypoints() != 0)\n\t\t{\n\t\t\treturn weaponRightHand;\n\t\t}\n\t\tif (weaponLeftHand->getCurrentWaypoints() != 0)\n\t\t{\n\t\t\treturn weaponLeftHand;\n\t\t}\n\t}\n\t// if only one weapon has snapshot, pick that one\n\tif (tuLeftHand <= 0 && tuRightHand > 0)\n\t\treturn weaponRightHand;\n\telse if (tuRightHand <= 0 && tuLeftHand > 0)\n\t\treturn weaponLeftHand;\n\t// else pick the better one\n\telse\n\t{\n\t\tif (tuLeftHand >= tuRightHand)\n\t\t{\n\t\t\tif (quickest)\n\t\t\t{\n\t\t\t\treturn weaponRightHand;\n\t\t\t}\n\t\t\telse if (_faction == FACTION_PLAYER)\n\t\t\t{\n\t\t\t\treturn weaponCurrentHand;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn weaponLeftHand;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (quickest)\n\t\t\t{\n\t\t\t\treturn weaponLeftHand;\n\t\t\t}\n\t\t\telse if (_faction == FACTION_PLAYER)\n\t\t\t{\n\t\t\t\treturn weaponCurrentHand;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn weaponRightHand;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Get a grenade from the belt (used for AI)\n * @return Pointer to item.\n */\nBattleItem *BattleUnit::getGrenadeFromBelt(const SavedBattleGame* battle) const\n{\n\tfor (auto* bi : _inventory)\n\t{\n\t\tif (bi->getRules()->isGrenadeOrProxy())\n\t\t{\n\t\t\tif (battle->getTurn() >= bi->getRules()->getAIUseDelay(battle->getMod()))\n\t\t\t{\n\t\t\t\treturn bi;\n\t\t\t}\n\t\t}\n\t}\n\treturn 0;\n}\n\n/**\n * Gets the item from right hand.\n * @return Item in right hand.\n */\nBattleItem *BattleUnit::getRightHandWeapon() const\n{\n\tfor (auto* bi : _inventory)\n\t{\n\t\tauto* slot = bi->getSlot();\n\t\tif (slot && slot->isRightHand())\n\t\t{\n\t\t\treturn bi;\n\t\t}\n\t}\n\treturn nullptr;\n}\n\n/**\n *  Gets the item from left hand.\n * @return Item in left hand.\n */\nBattleItem *BattleUnit::getLeftHandWeapon() const\n{\n\tfor (auto* bi : _inventory)\n\t{\n\t\tauto* slot = bi->getSlot();\n\t\tif (slot && slot->isLeftHand())\n\t\t{\n\t\t\treturn bi;\n\t\t}\n\t}\n\treturn nullptr;\n}\n\n/**\n * Set the right hand as main active hand.\n */\nvoid BattleUnit::setActiveRightHand()\n{\n\t_activeHand = \"STR_RIGHT_HAND\";\n}\n\n/**\n * Set the left hand as main active hand.\n */\nvoid BattleUnit::setActiveLeftHand()\n{\n\t_activeHand = \"STR_LEFT_HAND\";\n}\n\n/**\n * Choose what weapon was last use by unit.\n */\nconst BattleItem *BattleUnit::getActiveHand(const BattleItem *left, const BattleItem *right) const\n{\n\tif (_activeHand == \"STR_RIGHT_HAND\" && right) return right;\n\tif (_activeHand == \"STR_LEFT_HAND\" && left) return left;\n\treturn left ? left : right;\n}\n\n/**\n * Check if we have ammo and reload if needed (used for AI).\n * @return Do we have ammo?\n */\nbool BattleUnit::reloadAmmo()\n{\n\tBattleItem *list[2] =\n\t{\n\t\tgetRightHandWeapon(),\n\t\tgetLeftHandWeapon(),\n\t};\n\n\tfor (int i = 0; i < 2; ++i)\n\t{\n\t\tBattleItem *weapon = list[i];\n\t\tif (!weapon || !weapon->isWeaponWithAmmo() || weapon->haveAllAmmo())\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\n\t\t// we have a non-melee weapon with no ammo and 15 or more TUs - we might need to look for ammo then\n\t\tBattleItem *ammo = 0;\n\t\tauto ruleWeapon = weapon->getRules();\n\t\tauto tuCost = getTimeUnits() + 1;\n\t\tauto slotAmmo = 0;\n\n\t\tfor (auto* bi : *getInventory())\n\t\t{\n\t\t\tint slot = ruleWeapon->getSlotForAmmo(bi->getRules());\n\t\t\tif (slot != -1 && !weapon->getAmmoForSlot(slot))\n\t\t\t{\n\t\t\t\tint tuTemp = (Mod::EXTENDED_ITEM_RELOAD_COST && bi->getSlot()->getType() != INV_HAND) ? bi->getMoveToCost(weapon->getSlot()) : 0;\n\t\t\t\ttuTemp += ruleWeapon->getTULoad(slot);\n\t\t\t\tif (tuTemp < tuCost)\n\t\t\t\t{\n\t\t\t\t\ttuCost = tuTemp;\n\t\t\t\t\tammo = bi;\n\t\t\t\t\tslotAmmo = slot;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (ammo && spendTimeUnits(tuCost))\n\t\t{\n\t\t\tweapon->setAmmoForSlot(slotAmmo, ammo);\n\n\t\t\tauto sound = ammo->getRules()->getReloadSound();\n\t\t\tif (sound == Mod::NO_SOUND)\n\t\t\t{\n\t\t\t\tsound = ruleWeapon->getReloadSound();\n\t\t\t}\n\t\t\tif (sound == Mod::NO_SOUND)\n\t\t\t{\n\t\t\t\tsound = Mod::ITEM_RELOAD;\n\t\t\t}\n\n\t\t\t_lastReloadSound = sound;\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Toggle the right hand as main hand for reactions.\n */\nvoid BattleUnit::toggleRightHandForReactions(bool isCtrl)\n{\n\tif (isCtrl)\n\t{\n\t\tif (isRightHandPreferredForReactions())\n\t\t{\n\t\t\t_preferredHandForReactions = \"\";\n\t\t}\n\t\t_reactionsDisabledForRightHand = !_reactionsDisabledForRightHand;\n\t}\n\telse\n\t{\n\t\tif (isRightHandPreferredForReactions())\n\t\t{\n\t\t\t_preferredHandForReactions = \"\";\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_preferredHandForReactions = \"STR_RIGHT_HAND\";\n\t\t}\n\t\t_reactionsDisabledForRightHand = false;\n\t}\n}\n\n/**\n * Toggle the left hand as main hand for reactions.\n */\nvoid BattleUnit::toggleLeftHandForReactions(bool isCtrl)\n{\n\tif (isCtrl)\n\t{\n\t\tif (isLeftHandPreferredForReactions())\n\t\t{\n\t\t\t_preferredHandForReactions = \"\";\n\t\t}\n\t\t_reactionsDisabledForLeftHand = !_reactionsDisabledForLeftHand;\n\t}\n\telse\n\t{\n\t\tif (isLeftHandPreferredForReactions())\n\t\t{\n\t\t\t_preferredHandForReactions = \"\";\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_preferredHandForReactions = \"STR_LEFT_HAND\";\n\t\t}\n\t\t_reactionsDisabledForLeftHand = false;\n\t}\n}\n\n/**\n * Is right hand preferred for reactions?\n */\nbool BattleUnit::isRightHandPreferredForReactions() const\n{\n\treturn _preferredHandForReactions == \"STR_RIGHT_HAND\";\n}\n\n/**\n * Is left hand preferred for reactions?\n */\nbool BattleUnit::isLeftHandPreferredForReactions() const\n{\n\treturn _preferredHandForReactions == \"STR_LEFT_HAND\";\n}\n\n/**\n * Get preferred weapon for reactions, if applicable.\n */\nBattleItem *BattleUnit::getWeaponForReactions() const\n{\n\tif (_preferredHandForReactions.empty())\n\t\treturn nullptr;\n\n\tBattleItem* weapon = nullptr;\n\tif (isRightHandPreferredForReactions())\n\t\tweapon = getRightHandWeapon();\n\telse\n\t\tweapon = getLeftHandWeapon();\n\n\tif (!weapon)\n\t{\n\t\t// find the empty hands weapon using the standard algorithm (i.e. standard order)\n\t\tauto typesToCheck = { BT_MELEE, BT_PSIAMP, BT_FIREARM/*, BT_MEDIKIT, BT_SCANNER, BT_MINDPROBE*/};\n\t\tfor (auto& type : typesToCheck)\n\t\t{\n\t\t\tweapon = getSpecialWeapon(type);\n\t\t\tif (weapon && weapon->getRules()->isSpecialUsingEmptyHand())\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tweapon = nullptr;\n\t\t}\n\t\t// but only use BT_MELEE and BT_FIREARM (BT_PSIAMP doesn't have BA_HIT nor BA_SNAPSHOT)\n\t\tif (weapon && weapon->getRules()->getBattleType() == BT_PSIAMP)\n\t\t{\n\t\t\tweapon = nullptr;\n\t\t}\n\t}\n\n\tif (!weapon)\n\t\treturn nullptr;\n\n\tif (weapon->getRules()->getBattleType() == BT_MELEE)\n\t{\n\t\treturn weapon;\n\t}\n\telse\n\t{\n\t\t// ignore weapons without ammo (rules out grenades)\n\t\tif (!weapon->haveAnyAmmo())\n\t\t\treturn nullptr;\n\n\t\tint tu = getActionTUs(BA_SNAPSHOT, weapon).Time;\n\t\tif (tu > 0)\n\t\t\treturn weapon;\n\n\t}\n\n\treturn nullptr;\n}\n\n/**\n * Check if this unit is in the exit area.\n * @param stt Type of exit tile to check for.\n * @return Is in the exit area?\n */\nbool BattleUnit::isInExitArea(SpecialTileType stt) const\n{\n\treturn liesInExitArea(_tile, stt);\n}\n\n/**\n * Check if this unit lies (e.g. unconscious) in the exit area.\n * @param tile Unit's location.\n * @param stt Type of exit tile to check for.\n * @return Is in the exit area?\n */\nbool BattleUnit::liesInExitArea(Tile *tile, SpecialTileType stt) const\n{\n\treturn tile && tile->getFloorSpecialTileType() == stt;\n}\n\n/**\n * Gets the unit height taking into account kneeling/standing.\n * @return Unit's height.\n */\nint BattleUnit::getHeight() const\n{\n\treturn isKneeled()?getKneelHeight():getStandHeight();\n}\n\n/**\n * Adds one to the bravery exp counter.\n */\nvoid BattleUnit::addBraveryExp()\n{\n\t_exp.bravery++;\n}\n\n/**\n * Adds one to the reaction exp counter.\n */\nvoid BattleUnit::addReactionExp()\n{\n\t_exp.reactions++;\n}\n\n/**\n * Adds one to the firing exp counter.\n */\nvoid BattleUnit::addFiringExp()\n{\n\t_exp.firing++;\n}\n\n/**\n * Adds one to the throwing exp counter.\n */\nvoid BattleUnit::addThrowingExp()\n{\n\t_exp.throwing++;\n}\n\n/**\n * Adds one to the psi skill exp counter.\n */\nvoid BattleUnit::addPsiSkillExp()\n{\n\t_exp.psiSkill++;\n}\n\n/**\n * Adds one to the psi strength exp counter.\n */\nvoid BattleUnit::addPsiStrengthExp()\n{\n\t_exp.psiStrength++;\n}\n\n/**\n * Adds to the mana exp counter.\n */\nvoid BattleUnit::addManaExp(int weaponStat)\n{\n\tif (weaponStat > 0)\n\t{\n\t\t_exp.mana += weaponStat / 100;\n\t\tif (RNG::percent(weaponStat % 100))\n\t\t{\n\t\t\t_exp.mana++;\n\t\t}\n\t}\n}\n\n/**\n * Adds one to the melee exp counter.\n */\nvoid BattleUnit::addMeleeExp()\n{\n\t_exp.melee++;\n}\n\n/**\n * Did the unit gain any experience yet?\n */\nbool BattleUnit::hasGainedAnyExperience()\n{\n\tif (!Mod::EXTENDED_EXPERIENCE_AWARD_SYSTEM)\n\t{\n\t\t// vanilla compatibility (throwing doesn't count)\n\t\treturn _exp.bravery || _exp.reactions || _exp.firing || _exp.psiSkill || _exp.psiStrength || _exp.melee || _exp.mana;\n\t}\n\treturn _exp.bravery || _exp.reactions || _exp.firing || _exp.psiSkill || _exp.psiStrength || _exp.melee || _exp.throwing || _exp.mana;\n}\n\nvoid BattleUnit::updateGeoscapeStats(Soldier *soldier) const\n{\n\tsoldier->addMissionCount();\n\tsoldier->addKillCount(_kills);\n}\n\n/**\n * Check if unit eligible for squaddie promotion. If yes, promote the unit.\n * Increase the mission counter. Calculate the experience increases.\n * @param geoscape Pointer to geoscape save.\n * @param statsDiff (out) The passed UnitStats struct will be filled with the stats differences.\n * @return True if the soldier was eligible for squaddie promotion.\n */\nbool BattleUnit::postMissionProcedures(const Mod *mod, SavedGame *geoscape, SavedBattleGame *battle, StatAdjustment &statsDiff)\n{\n\tSoldier *s = geoscape->getSoldier(_id);\n\tif (s == 0)\n\t{\n\t\treturn false;\n\t}\n\n\tupdateGeoscapeStats(s);\n\n\tUnitStats *stats = s->getCurrentStatsEditable();\n\tStatAdjustment statsOld = { };\n\tstatsOld.statGrowth = (*stats);\n\tstatsDiff.statGrowth = -(*stats);        // subtract old stat\n\tconst UnitStats caps = s->getRules()->getStatCaps();\n\tint manaLossOriginal = _stats.mana - _mana;\n\tint healthLossOriginal = _stats.health - _health;\n\tint manaLoss = mod->getReplenishManaAfterMission() ? 0 : manaLossOriginal;\n\tint healthLoss = mod->getReplenishHealthAfterMission() ? 0 : healthLossOriginal;\n\n\tauto recovery = (int)RNG::generate((healthLossOriginal*0.5),(healthLossOriginal*1.5));\n\n\tif (_exp.bravery && stats->bravery < caps.bravery)\n\t{\n\t\tif (_exp.bravery > RNG::generate(0,10)) stats->bravery += 10;\n\t}\n\tif (_exp.reactions && stats->reactions < caps.reactions)\n\t{\n\t\tstats->reactions += improveStat(_exp.reactions);\n\t}\n\tif (_exp.firing && stats->firing < caps.firing)\n\t{\n\t\tstats->firing += improveStat(_exp.firing);\n\t}\n\tif (_exp.melee && stats->melee < caps.melee)\n\t{\n\t\tstats->melee += improveStat(_exp.melee);\n\t}\n\tif (_exp.throwing && stats->throwing < caps.throwing)\n\t{\n\t\tstats->throwing += improveStat(_exp.throwing);\n\t}\n\tif (_exp.psiSkill && stats->psiSkill < caps.psiSkill)\n\t{\n\t\tstats->psiSkill += improveStat(_exp.psiSkill);\n\t}\n\tif (_exp.psiStrength && stats->psiStrength < caps.psiStrength)\n\t{\n\t\tstats->psiStrength += improveStat(_exp.psiStrength);\n\t}\n\tif (mod->isManaTrainingPrimary())\n\t{\n\t\tif (_exp.mana && stats->mana < caps.mana)\n\t\t{\n\t\t\tstats->mana += improveStat(_exp.mana);\n\t\t}\n\t}\n\n\tbool hasImproved = false;\n\tif (hasGainedAnyExperience())\n\t{\n\t\thasImproved = true;\n\t\tif (s->getRank() == RANK_ROOKIE)\n\t\t\ts->promoteRank();\n\t\tint v;\n\t\tv = caps.tu - stats->tu;\n\t\tif (v > 0) stats->tu += RNG::generate(0, v/10 + 2);\n\t\tv = caps.health - stats->health;\n\t\tif (v > 0) stats->health += RNG::generate(0, v/10 + 2);\n\t\tif (mod->isManaTrainingSecondary())\n\t\t{\n\t\t\tv = caps.mana - stats->mana;\n\t\t\tif (v > 0) stats->mana += RNG::generate(0, v/10 + 2);\n\t\t}\n\t\tv = caps.strength - stats->strength;\n\t\tif (v > 0) stats->strength += RNG::generate(0, v/10 + 2);\n\t\tv = caps.stamina - stats->stamina;\n\t\tif (v > 0) stats->stamina += RNG::generate(0, v/15 + 2);\n\t}\n\n\tstatsDiff.statGrowth += *stats; // add new stat\n\n\tif (_armor->getInstantWoundRecovery())\n\t{\n\t\trecovery = 0;\n\t}\n\n\t{\n\t\tModScript::ReturnFromMissionUnit::Output arg { };\n\t\tModScript::ReturnFromMissionUnit::Worker work{ this, battle, s, &statsDiff, &statsOld };\n\n\t\tauto ref = std::tie(recovery, manaLossOriginal, healthLossOriginal, manaLoss, healthLoss);\n\n\t\targ.data = ref;\n\n\t\twork.execute(getArmor()->getScript<ModScript::ReturnFromMissionUnit>(), arg);\n\n\t\tref = arg.data;\n\t}\n\n\t//after mod execution this value could change\n\tstatsDiff.statGrowth = *stats - statsOld.statGrowth;\n\n\ts->setWoundRecovery(recovery);\n\ts->setManaMissing(manaLoss);\n\ts->setHealthMissing(healthLoss);\n\n\tif (s->isWounded())\n\t{\n\t\t// remove from craft\n\t\t//s->setCraft(nullptr); // Note to self: we need to do this much later (as late as possible), so that we can correctly remove the items too (without side effects)\n\n\t\t// remove from training, but remember to return to training when healed\n\t\t{\n\t\t\tif (s->isInTraining())\n\t\t\t{\n\t\t\t\ts->setReturnToTrainingWhenHealed(true);\n\t\t\t}\n\t\t\ts->setTraining(false);\n\t\t}\n\t}\n\n\treturn hasImproved;\n}\n\n/**\n * Converts the number of experience to the stat increase.\n * @param Experience counter.\n * @return Stat increase.\n */\nint BattleUnit::improveStat(int exp) const\n{\n\tif      (exp > 10) return RNG::generate(2, 6);\n\telse if (exp > 5)  return RNG::generate(1, 4);\n\telse if (exp > 2)  return RNG::generate(1, 3);\n\telse if (exp > 0)  return RNG::generate(0, 1);\n\telse               return 0;\n}\n\n/**\n * Get the unit's minimap sprite index. Used to display the unit on the minimap\n * @return the unit minimap index\n */\nint BattleUnit::getMiniMapSpriteIndex() const\n{\n\t//minimap sprite index:\n\t// * 0-2   : Xcom soldier\n\t// * 3-5   : Alien\n\t// * 6-8   : Civilian\n\t// * 9-11  : Item\n\t// * 12-23 : Xcom HWP\n\t// * 24-35 : Alien big terror unit(cyberdisk, ...)\n\tif (isOut())\n\t{\n\t\treturn 9;\n\t}\n\tswitch (getFaction())\n\t{\n\tcase FACTION_HOSTILE:\n\t\tif (isSmallUnit())\n\t\t\treturn 3;\n\t\telse\n\t\t\treturn 24;\n\tcase FACTION_NEUTRAL:\n\t\tif (isSmallUnit())\n\t\t\treturn 6;\n\t\telse\n\t\t\treturn 12;\n\tdefault:\n\t\tif (isSmallUnit())\n\t\t\treturn 0;\n\t\telse\n\t\t\treturn 12;\n\t}\n}\n\n/**\n  * Set the turret type. -1 is no turret.\n  * @param turretType\n  */\nvoid BattleUnit::setTurretType(int turretType)\n{\n\t_turretType = turretType;\n}\n\n/**\n  * Get the turret type. -1 is no turret.\n  * @return type\n  */\nint BattleUnit::getTurretType() const\n{\n\treturn _turretType;\n}\n\n/**\n * Get the amount of fatal wound for a body part\n * @param part The body part (in the range 0-5)\n * @return The amount of fatal wound of a body part\n */\nint BattleUnit::getFatalWound(UnitBodyPart part) const\n{\n\tif (part < 0 || part >= BODYPART_MAX)\n\t\treturn 0;\n\treturn _fatalWounds[part];\n}\n/**\n * Set fatal wound amount of a body part\n * @param wound The amount of fatal wound of a body part shoud have\n * @param part The body part (in the range 0-5)\n */\nvoid BattleUnit::setFatalWound(int wound, UnitBodyPart part)\n{\n\tif (part < 0 || part >= BODYPART_MAX)\n\t\treturn;\n\t_fatalWounds[part] = Clamp(wound, 0, UnitStats::BaseStatLimit);\n}\n\n/**\n * Heal a fatal wound of the soldier\n * @param part the body part to heal\n * @param woundAmount the amount of fatal wound healed\n * @param healthAmount The amount of health to add to soldier health\n */\nvoid BattleUnit::heal(UnitBodyPart part, int woundAmount, int healthAmount)\n{\n\tif (part < 0 || part >= BODYPART_MAX || !_fatalWounds[part])\n\t{\n\t\treturn;\n\t}\n\n\tsetValueMax(_fatalWounds[part], -woundAmount, 0, UnitStats::BaseStatLimit);\n\tsetValueMax(_health, healthAmount, std::min(_health, 1), getBaseStats()->health); //Hippocratic Oath: First do no harm\n\n}\n\n/**\n * Restore soldier morale\n * @param moraleAmount additional morale boost.\n * @param painKillersStrength how much of damage convert to morale.\n */\nvoid BattleUnit::painKillers(int moraleAmount, float painKillersStrength)\n{\n\tint lostHealth = (getBaseStats()->health - _health) * painKillersStrength;\n\tif (lostHealth > _moraleRestored)\n\t{\n\t\t_morale = std::min(100, (lostHealth - _moraleRestored + _morale));\n\t\t_moraleRestored = lostHealth;\n\t}\n\tmoraleChange(moraleAmount);\n}\n\n/**\n * Restore soldier energy and reduce stun level, can restore mana too\n * @param energy The amount of energy to add\n * @param stun The amount of stun level to reduce\n * @param mana The amount of mana to add\n */\nvoid BattleUnit::stimulant(int energy, int stun, int mana)\n{\n\t_energy += energy;\n\tif (_energy > getBaseStats()->stamina)\n\t\t_energy = getBaseStats()->stamina;\n\thealStun(stun);\n\tsetValueMax(_mana, mana, 0, getBaseStats()->mana);\n}\n\n\n/**\n * Get motion points for the motion scanner. More points\n * is a larger blip on the scanner.\n * @return points.\n */\nint BattleUnit::getMotionPoints() const\n{\n\treturn _motionPoints;\n}\n\n/**\n * Gets the unit's armor.\n * @return Pointer to armor.\n */\nconst Armor *BattleUnit::getArmor() const\n{\n\treturn _armor;\n}\n\n/**\n * Set the unit's name.\n * @param name Name\n */\nvoid BattleUnit::setName(const std::string &name)\n{\n\t_name = name;\n}\n\n/**\n * Get unit's name.\n * An aliens name is the translation of it's race and rank.\n * hence the language pointer needed.\n * @param lang Pointer to language.\n * @param debugAppendId Append unit ID to name for debug purposes.\n * @return name String of the unit's name.\n */\nstd::string BattleUnit::getName(Language *lang, bool debugAppendId) const\n{\n\tif (_type != \"SOLDIER\" && lang != 0)\n\t{\n\t\tstd::string ret;\n\n\t\tif (_type.find(\"STR_\") != std::string::npos)\n\t\t\tret = lang->getString(_type);\n\t\telse\n\t\t\tret = lang->getString(_race);\n\n\t\tif (debugAppendId)\n\t\t{\n\t\t\tstd::ostringstream ss;\n\t\t\tss << ret << \" \" << _id;\n\t\t\tret = ss.str();\n\t\t}\n\t\treturn ret;\n\t}\n\n\treturn _name;\n}\n\n/**\n  * Gets pointer to the unit's stats.\n  * @return stats Pointer to the unit's stats.\n  */\nUnitStats *BattleUnit::getBaseStats()\n{\n\treturn &_stats;\n}\n\n/**\n  * Gets pointer to the unit's stats.\n  * @return stats Pointer to the unit's stats.\n  */\nconst UnitStats *BattleUnit::getBaseStats() const\n{\n\treturn &_stats;\n}\n\n/**\n  * Get the unit's stand height.\n  * @return The unit's height in voxels, when standing up.\n  */\nint BattleUnit::getStandHeight() const\n{\n\treturn _standHeight;\n}\n\n/**\n  * Get the unit's kneel height.\n  * @return The unit's height in voxels, when kneeling.\n  */\nint BattleUnit::getKneelHeight() const\n{\n\treturn _kneelHeight;\n}\n\n/**\n  * Get the unit's floating elevation.\n  * @return The unit's elevation over the ground in voxels, when flying.\n  */\nint BattleUnit::getFloatHeight() const\n{\n\treturn _floatHeight;\n}\n\n/**\n  * Get the unit's loft ID, one per unit tile.\n  * Each tile only has one loft, as it is repeated over the entire height of the unit.\n  * @param entry Unit tile\n  * @return The unit's line of fire template ID.\n  */\nint BattleUnit::getLoftemps(int entry) const\n{\n\treturn _loftempsSet.at(entry);\n}\n\n/**\n  * Get the unit's value. Used for score at debriefing.\n  * @return value score\n  */\nint BattleUnit::getValue() const\n{\n\treturn _value;\n}\n\n/**\n * Get the unit's death sounds.\n * @return List of sound IDs.\n */\nconst std::vector<int> &BattleUnit::getDeathSounds() const\n{\n\treturn _deathSound;\n}\n\n/**\n * Get the unit's move sound.\n * @return id.\n */\nint BattleUnit::getMoveSound() const\n{\n\treturn _moveSound;\n}\n\n\n/**\n * Get whether the unit is affected by fatal wounds.\n * Normally only soldiers are affected by fatal wounds.\n * @return Is the unit affected by wounds?\n */\nbool BattleUnit::isWoundable() const\n{\n\treturn !_armor->getBleedImmune(!(_type==\"SOLDIER\" || (Options::alienBleeding && _originalFaction != FACTION_PLAYER)));\n}\n\n/**\n * Get whether the unit is affected by morale loss.\n * Normally only small units are affected by morale loss.\n * @return Is the unit affected by morale?\n */\nbool BattleUnit::isFearable() const\n{\n\treturn !_armor->getFearImmune();\n}\n\n/**\n * Is this unit capable of shooting beyond max. visual range?\n * @return True, if unit is capable of shooting beyond max. visual range.\n */\nbool BattleUnit::isSniper() const\n{\n\tif (_unitRules && _unitRules->getSniperPercentage() > 0)\n\t{\n\t\treturn true;\n\t}\n\treturn false;\n}\n\n/**\n * Gets true when unit is 1x1 sized unit.\n */\nbool BattleUnit::isSmallUnit() const\n{\n\treturn _armor->getSize() == 1;\n}\n\n/**\n * Gets true when unit is 2x2 sized unit.\n */\nbool BattleUnit::isBigUnit() const\n{\n\treturn _armor->getSize() > 1;\n}\n\n/**\n * Get the number of turns an AI unit remembers a soldier's position.\n * @return intelligence.\n */\nint BattleUnit::getIntelligence() const\n{\n\treturn _intelligence;\n}\n\n/**\n * Get the unit's aggression.\n * @return aggression.\n */\nint BattleUnit::getAggression() const\n{\n\treturn _aggression;\n}\n\nint BattleUnit::getMaxViewDistance(int baseVisibility, int nerf, int buff) const\n{\n\tint result = baseVisibility;\n\tif (nerf > 0)\n\t{\n\t\tresult = nerf; // fixed distance nerf\n\t}\n\telse\n\t{\n\t\tresult += nerf; // relative distance nerf\n\t}\n\tif (result < 1)\n\t{\n\t\tresult = 1;  // can't go under melee distance\n\t}\n\tresult += buff; // relative distance buff\n\tif (result > baseVisibility)\n\t{\n\t\tresult = baseVisibility; // don't overbuff (buff is only supposed to counter the nerf)\n\t}\n\treturn result;\n}\n\nint BattleUnit::getMaxViewDistanceAtDark(const BattleUnit* otherUnit) const\n{\n\tif (otherUnit)\n\t{\n\t\treturn getMaxViewDistance(_maxViewDistanceAtDark, otherUnit->getArmor()->getCamouflageAtDark(), _armor->getAntiCamouflageAtDark());\n\t}\n\telse\n\t{\n\t\treturn _maxViewDistanceAtDark;\n\t}\n}\n\nint BattleUnit::getMaxViewDistanceAtDarkSquared() const\n{\n\treturn _maxViewDistanceAtDarkSquared;\n}\n\nint BattleUnit::getMaxViewDistanceAtDay(const BattleUnit* otherUnit) const\n{\n\tif (otherUnit)\n\t{\n\t\treturn getMaxViewDistance(_maxViewDistanceAtDay, otherUnit->getArmor()->getCamouflageAtDay(), _armor->getAntiCamouflageAtDay());\n\t}\n\telse\n\t{\n\t\treturn _maxViewDistanceAtDay;\n\t}\n}\n\n/**\n * Returns the unit's special ability.\n * @return special ability.\n */\nint BattleUnit::getSpecialAbility() const\n{\n\treturn _specab;\n}\n\n/**\n * Sets this unit to respawn (or not).\n * @param respawn whether it should respawn.\n */\nvoid BattleUnit::setRespawn(bool respawn)\n{\n\t_respawn = respawn;\n}\n\n/**\n * Gets this unit's respawn flag.\n */\nbool BattleUnit::getRespawn() const\n{\n\treturn _respawn;\n}\n\n/**\n * Marks this unit as already respawned (or not).\n * @param alreadyRespawned whether it already respawned.\n */\nvoid BattleUnit::setAlreadyRespawned(bool alreadyRespawned)\n{\n\t_alreadyRespawned = alreadyRespawned;\n}\n\n/**\n * Gets this unit's alreadyRespawned flag.\n */\nbool BattleUnit::getAlreadyRespawned() const\n{\n\treturn _alreadyRespawned;\n}\n\n/**\n * Get the unit that is spawned when this one dies.\n * @return unit.\n */\nconst Unit *BattleUnit::getSpawnUnit() const\n{\n\treturn _spawnUnit;\n}\n\n/**\n * Set the unit that is spawned when this one dies.\n * @param spawnUnit unit.\n */\nvoid BattleUnit::setSpawnUnit(const Unit *spawnUnit)\n{\n\t_spawnUnit = spawnUnit;\n}\n\n/**\n * Clear all information for spawn unit.\n */\nvoid BattleUnit::clearSpawnUnit()\n{\n\tsetSpawnUnit(nullptr);\n\tsetSpawnUnitFaction(FACTION_HOSTILE);\n\tsetRespawn(false);\n}\n\n\n\n/**\n * Get the units's rank string.\n * @return rank.\n */\nconst std::string& BattleUnit::getRankString() const\n{\n\treturn _rank;\n}\n\n/**\n * Get the geoscape-soldier object.\n * @return soldier.\n */\nSoldier *BattleUnit::getGeoscapeSoldier() const\n{\n\treturn _geoscapeSoldier;\n}\n\n/**\n * Add a kill to the counter.\n */\nvoid BattleUnit::addKillCount()\n{\n\t_kills++;\n}\n\n/**\n * Get unit type.\n * @return unit type.\n */\nconst std::string& BattleUnit::getType() const\n{\n\treturn _type;\n}\n\n/**\n * Converts unit to another faction (original faction is still stored).\n * @param f faction.\n */\nvoid BattleUnit::convertToFaction(UnitFaction f)\n{\n\t_faction = f;\n}\n\n/**\n* Set health to 0 - used when getting killed unconscious.\n*/\nvoid BattleUnit::kill()\n{\n\t_health = 0;\n}\n\n/**\n * Set health to 0 and set status dead - used when getting zombified.\n */\nvoid BattleUnit::instaKill()\n{\n\t_health = 0;\n\t_status = STATUS_DEAD;\n\t_turnsSinceStunned = 0;\n}\n\n/**\n * Gets whether the unit has any aggro sounds.\n * @return True, if the unit has any aggro sounds.\n */\nbool BattleUnit::hasAggroSound() const\n{\n\treturn !_aggroSound.empty();\n}\n\n/**\n * Gets a unit's random aggro sound.\n * @return The sound id.\n */\nint BattleUnit::getRandomAggroSound() const\n{\n\tif (hasAggroSound())\n\t{\n\t\treturn _aggroSound[RNG::generate(0, _aggroSound.size() - 1)];\n\t}\n\treturn -1;\n}\n\n/**\n * Set a specific amount of time units.\n * @param tu time units.\n */\nvoid BattleUnit::setTimeUnits(int tu)\n{\n\t_tu = Clamp(tu, 0, (int)_stats.tu);\n}\n\n/**\n * Get the faction the unit was killed by.\n * @return faction\n */\nUnitFaction BattleUnit::killedBy() const\n{\n\treturn _killedBy;\n}\n\n/**\n * Set the faction the unit was killed by.\n * @param f faction\n */\nvoid BattleUnit::killedBy(UnitFaction f)\n{\n\t_killedBy = f;\n}\n\n/**\n * Set the units we are charging towards.\n * @param chargeTarget Charge Target\n */\nvoid BattleUnit::setCharging(BattleUnit *chargeTarget)\n{\n\t_charging = chargeTarget;\n}\n\n/**\n * Get the units we are charging towards.\n * @return Charge Target\n */\nBattleUnit *BattleUnit::getCharging()\n{\n\treturn _charging;\n}\n\n/**\n * Get the units carried weight in strength units.\n * @param draggingItem item to ignore\n * @return weight\n */\nint BattleUnit::getCarriedWeight(BattleItem *draggingItem) const\n{\n\tint weight = _armor->getWeight();\n\tfor (const auto* bi : _inventory)\n\t{\n\t\tif (bi == draggingItem) continue;\n\t\tweight += bi->getTotalWeight();\n\t}\n\treturn std::max(0,weight);\n}\n\n\n\n/**\n * Set default state on unit.\n */\nvoid BattleUnit::resetTurnsSince()\n{\n\tfor (auto& since : _turnsSinceSpotted)\n\t{\n\t\tsince = 255;\n\t}\n\tfor (auto& left : _turnsLeftSpottedForSnipers)\n\t{\n\t\tleft = 0;\n\t}\n\t//_turnsSinceStunned is reset elsewhere\n}\n\n\n/**\n * Update counters on unit.\n */\nvoid BattleUnit::updateTurnsSince()\n{\n\tfor (auto& since : _turnsSinceSpotted)\n\t{\n\t\tsince = Clamp(since + 1, 0, 255);\n\t}\n\tfor (auto& left : _turnsLeftSpottedForSnipers)\n\t{\n\t\tleft = Clamp(left - 1, 0, 255);\n\t}\n\t//_turnsSinceStunned is updated elsewhere\n}\n\n\n\nnamespace\n{\n\n/// safe setter of value in array\ntemplate<int I>\nvoid setUint8Array(Uint8 (&arr)[I], int offset, int value)\n{\n\tif (0 <= offset && offset < I)\n\t{\n\t\tarr[offset] = Clamp(value, 0, 255);\n\t}\n}\n\n/// safe getter of value in array\ntemplate<int I>\nint getUint8Array(const Uint8 (&arr)[I], int offset)\n{\n\tif (0 <= offset && offset < I)\n\t{\n\t\treturn arr[offset];\n\t}\n\n\treturn 0;\n}\n\n} // namespace\n\n\n/**\n * Set how long since this unit was last exposed.\n * @param turns number of turns\n */\nvoid BattleUnit::setTurnsSinceSpotted (int turns)\n{\n\t_turnsSinceSpotted[FACTION_HOSTILE] = turns;\n}\n\n/**\n * Set how many turns this unit will be exposed for. For specific faction.\n */\nvoid BattleUnit::setTurnsSinceSpottedByFaction(UnitFaction faction, int turns)\n{\n\tsetUint8Array(_turnsSinceSpotted, faction, turns);\n}\n\n/**\n * Get how long since this unit was exposed.\n * @return number of turns\n */\nint BattleUnit::getTurnsSinceSpotted() const\n{\n\treturn _turnsSinceSpotted[FACTION_HOSTILE];\n}\n\n/**\n * Set how many turns this unit will be exposed for. For specific faction.\n */\nint BattleUnit::getTurnsSinceSpottedByFaction(UnitFaction faction) const\n{\n\treturn getUint8Array(_turnsSinceSpotted, faction);\n}\n\n/**\n * Set how many turns left snipers will know about this unit.\n * @param turns number of turns\n */\nvoid BattleUnit::setTurnsLeftSpottedForSnipers (int turns)\n{\n\t_turnsLeftSpottedForSnipers[FACTION_HOSTILE] = turns;\n}\n\n/**\n * Set how many turns left snipers know about this target. For specific faction.\n */\nvoid BattleUnit::setTurnsLeftSpottedForSnipersByFaction (UnitFaction faction, int turns)\n{\n\tsetUint8Array(_turnsLeftSpottedForSnipers, faction, turns);\n}\n\n/**\n * Get how many turns left snipers can fire on this unit.\n * @return number of turns\n */\nint BattleUnit::getTurnsLeftSpottedForSnipers() const\n{\n\treturn _turnsLeftSpottedForSnipers[FACTION_HOSTILE];\n}\n\n/**\n * Get how many turns left snipers know about this target. For specific faction.\n */\nint BattleUnit::getTurnsLeftSpottedForSnipersByFaction(UnitFaction faction) const\n{\n\treturn getUint8Array(_turnsLeftSpottedForSnipers, faction);\n}\n\n/**\n * Get this unit's original Faction.\n * @return original faction\n */\nUnitFaction BattleUnit::getOriginalFaction() const\n{\n\treturn _originalFaction;\n}\n\n/**\n * Get the list of units spotted this turn.\n * @return List of units.\n */\nstd::vector<BattleUnit *> &BattleUnit::getUnitsSpottedThisTurn()\n{\n\treturn _unitsSpottedThisTurn;\n}\n\n/**\n * Get the list of units spotted this turn.\n * @return List of units.\n */\nconst std::vector<BattleUnit *> &BattleUnit::getUnitsSpottedThisTurn() const\n{\n\treturn _unitsSpottedThisTurn;\n}\n\n/**\n * Change the numeric version of the unit's rank.\n * @param rank unit rank, 0 = lowest\n */\nvoid BattleUnit::setRankInt(int rank)\n{\n\t_rankInt = rank;\n}\n\n/**\n * Return the numeric version of the unit's rank.\n * @return unit rank, 0 = lowest\n */\nint BattleUnit::getRankInt() const\n{\n\treturn _rankInt;\n}\n\n/**\n * Derive the numeric unit rank from the string rank\n * (for soldier units).\n */\nvoid BattleUnit::deriveSoldierRank()\n{\n\tif (_geoscapeSoldier)\n\t{\n\t\tswitch (_geoscapeSoldier->getRank())\n\t\t{\n\t\tcase RANK_ROOKIE:    _rankInt = 0; break;\n\t\tcase RANK_SQUADDIE:  _rankInt = 1; break;\n\t\tcase RANK_SERGEANT:  _rankInt = 2; break;\n\t\tcase RANK_CAPTAIN:   _rankInt = 3; break;\n\t\tcase RANK_COLONEL:   _rankInt = 4; break;\n\t\tcase RANK_COMMANDER: _rankInt = 5; break;\n\t\tdefault:             _rankInt = 0; break;\n\t\t}\n\t}\n\t_rankIntUnified = _rankInt;\n}\n\n/**\n * derive a rank integer based on rank string (for Alien)\n */\nvoid BattleUnit::deriveHostileRank()\n{\n\tconst int max = 7;\n\tconst char* rankList[max] =\n\t{\n\t\t\"STR_LIVE_SOLDIER\",\n\t\t\"STR_LIVE_ENGINEER\",\n\t\t\"STR_LIVE_MEDIC\",\n\t\t\"STR_LIVE_NAVIGATOR\",\n\t\t\"STR_LIVE_LEADER\",\n\t\t\"STR_LIVE_COMMANDER\",\n\t\t\"STR_LIVE_TERRORIST\",\n\t};\n\tfor (int i = 0; i < max; ++i)\n\t{\n\t\tif (_rank.compare(rankList[i]) == 0)\n\t\t{\n\t\t\t_rankIntUnified = i;\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n/**\n * derive a rank integer based on rank string (for Civilians)\n */\nvoid BattleUnit::deriveNeutralRank()\n{\n\t_rankIntUnified = RNG::seedless(0, 7);\n}\n\n/**\n* this function checks if a tile is visible from either of the unit's tiles, using maths.\n* @param pos the position to check against\n* @param useTurretDirection use turret facing (true) or body facing (false) for sector calculation\n* @return what the maths decide\n*/\nbool BattleUnit::checkViewSector (Position pos, bool useTurretDirection /* = false */) const\n{\n\tint unitSize = getArmor()->getSize();\n\t//Check view cone from each of the unit's tiles\n\tfor (int x = 0; x < unitSize; ++x)\n\t{\n\t\tfor (int y = 0; y < unitSize; ++y)\n\t\t{\n\t\t\tint deltaX = pos.x - (_pos.x + x);\n\t\t\tint deltaY = (_pos.y + y) - pos.y;\n\t\t\tswitch (useTurretDirection ? _directionTurret : _direction)\n\t\t\t{\n\t\t\tcase 0:\n\t\t\t\tif ((deltaX + deltaY >= 0) && (deltaY - deltaX >= 0))\n\t\t\t\t\treturn true;\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\t\tif ((deltaX >= 0) && (deltaY >= 0))\n\t\t\t\t\treturn true;\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\tif ((deltaX + deltaY >= 0) && (deltaY - deltaX <= 0))\n\t\t\t\t\treturn true;\n\t\t\t\tbreak;\n\t\t\tcase 3:\n\t\t\t\tif ((deltaY <= 0) && (deltaX >= 0))\n\t\t\t\t\treturn true;\n\t\t\t\tbreak;\n\t\t\tcase 4:\n\t\t\t\tif ((deltaX + deltaY <= 0) && (deltaY - deltaX <= 0))\n\t\t\t\t\treturn true;\n\t\t\t\tbreak;\n\t\t\tcase 5:\n\t\t\t\tif ((deltaX <= 0) && (deltaY <= 0))\n\t\t\t\t\treturn true;\n\t\t\t\tbreak;\n\t\t\tcase 6:\n\t\t\t\tif ((deltaX + deltaY <= 0) && (deltaY - deltaX >= 0))\n\t\t\t\t\treturn true;\n\t\t\t\tbreak;\n\t\t\tcase 7:\n\t\t\t\tif ((deltaY >= 0) && (deltaX <= 0))\n\t\t\t\t\treturn true;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * common function to adjust a unit's stats according to difficulty setting.\n * @param statAdjustment the stat adjustment variables coefficient value.\n */\nvoid BattleUnit::adjustStats(const StatAdjustment &adjustment)\n{\n\t_stats += UnitStats::percent(_stats, adjustment.statGrowth, adjustment.growthMultiplier);\n\n\t_stats.firing *= adjustment.aimMultiplier;\n\t_stats += adjustment.statGrowthAbs;\n\n\tfor (int i = 0; i < SIDE_MAX; ++i)\n\t{\n\t\t_maxArmor[i] *= adjustment.armorMultiplier;\n\t\t_maxArmor[i] += adjustment.armorMultiplierAbs;\n\t\t_currentArmor[i] = _maxArmor[i];\n\t}\n\n\t// update base stats again as they could be altered by `adjustment`.\n\t_tu = _stats.tu;\n\t_energy = _stats.stamina;\n\t_health = _stats.health;\n\t_mana = _stats.mana;\n}\n\n/**\n * did this unit already take fire damage this turn?\n * (used to avoid damaging large units multiple times.)\n * @return ow it burns\n */\nbool BattleUnit::tookFireDamage() const\n{\n\treturn _hitByFire;\n}\n\n/**\n * toggle the state of the fire damage tracking boolean.\n */\nvoid BattleUnit::toggleFireDamage()\n{\n\t_hitByFire = !_hitByFire;\n}\n\n/**\n * Checks if this unit can be selected. Only alive units\n * belonging to the faction can be selected.\n * @param faction The faction to compare with.\n * @param checkReselect Check if the unit is reselectable.\n * @param checkInventory Check if the unit has an inventory.\n * @return True if the unit can be selected, false otherwise.\n */\nbool BattleUnit::isSelectable(UnitFaction faction, bool checkReselect, bool checkInventory) const\n{\n\treturn (_faction == faction && !isOut() && (!checkReselect || reselectAllowed()) && (!checkInventory || hasInventory()));\n}\n\n/**\n * Checks if this unit has an inventory. Large units and/or\n * terror units generally don't have inventories.\n * @return True if an inventory is available, false otherwise.\n */\nbool BattleUnit::hasInventory() const\n{\n\treturn (_armor->hasInventory());\n}\n\n/**\n * If this unit is breathing, what frame should be displayed?\n * @return frame number.\n */\nint BattleUnit::getBreathExhaleFrame() const\n{\n\tif (_breathing)\n\t{\n\t\tauto frame = _breathFrame - BUBBLES_FIRST_FRAME;\n\t\tif (frame >= 0)\n\t\t{\n\t\t\treturn frame;\n\t\t}\n\t}\n\n\treturn -1;\n}\n\n/**\n * Count frames to next start of breath animation.\n */\nint BattleUnit::getBreathInhaleFrame() const\n{\n\tif (_breathing)\n\t{\n\t\tauto frame = BUBBLES_FIRST_FRAME - _breathFrame;\n\t\tif (frame >= 0)\n\t\t{\n\t\t\treturn frame;\n\t\t}\n\t}\n\n\treturn -1;\n}\n\n/**\n * Decides if we should start producing bubbles, and/or updates which bubble frame we are on.\n */\nvoid BattleUnit::breathe()\n{\n\t// _breathFrame of -1 means this unit doesn't produce bubbles\n\tif (_breathFrame < 0)\n\t{\n\t\t_breathing = false;\n\t\treturn;\n\t}\n\n\t// moving or knock out do not breathe, even when still alive :)\n\tif (isOut() || _status == STATUS_WALKING)\n\t{\n\t\t_breathing = false;\n\t\t_breathFrame = 0;\n\t\treturn;\n\t}\n\n\tif (!_breathing)\n\t{\n\t\t// deviation from original: TFTD used a static 10% chance for every animation frame,\n\t\t// instead let's use 5%, but allow morale to affect it.\n\t\t_breathing = RNG::seedless(0, 99) < (105 - _morale);\n\t\t_breathFrame = 0;\n\t}\n\n\tif (_breathing)\n\t{\n\t\t// advance the bubble frame\n\t\t_breathFrame++;\n\n\t\t// we've reached the end of the cycle, get rid of the bubbles\n\t\tif (_breathFrame > BUBBLES_LAST_FRAME)\n\t\t{\n\t\t\t_breathFrame = 0;\n\t\t\t_breathing = false;\n\t\t}\n\t}\n}\n\n/**\n * Sets the flag for \"this unit is under cover\" meaning don't draw bubbles.\n * @param floor is there a floor.\n */\nvoid BattleUnit::setFloorAbove(bool floor)\n{\n\t_floorAbove = floor;\n}\n\n/**\n * Checks if the floor above flag has been set.\n * @return if we're under cover.\n */\nbool BattleUnit::getFloorAbove() const\n{\n\treturn _floorAbove;\n}\n\n/**\n * Get the name of any utility weapon we may be carrying, or a built in one.\n * @return the name .\n */\nBattleItem *BattleUnit::getUtilityWeapon(BattleType type)\n{\n\tBattleItem *melee = getRightHandWeapon();\n\tif (melee && melee->getRules()->getBattleType() == type)\n\t{\n\t\treturn melee;\n\t}\n\tmelee = getLeftHandWeapon();\n\tif (melee && melee->getRules()->getBattleType() == type)\n\t{\n\t\treturn melee;\n\t}\n\tmelee = getSpecialWeapon(type);\n\tif (melee)\n\t{\n\t\treturn melee;\n\t}\n\treturn 0;\n}\n\n/**\n * Set fire damage from environment.\n * @param damage\n */\nvoid BattleUnit::setEnviFire(int damage)\n{\n\tif (_fireMaxHit < damage) _fireMaxHit = damage;\n}\n\n/**\n * Set smoke damage from environment.\n * @param damage\n */\nvoid BattleUnit::setEnviSmoke(int damage)\n{\n\tif (_smokeMaxHit < damage) _smokeMaxHit = damage;\n}\n\n/**\n * Calculate smoke and fire damage from environment.\n */\nvoid BattleUnit::calculateEnviDamage(Mod *mod, SavedBattleGame *save)\n{\n\tif (_fireMaxHit)\n\t{\n\t\t_hitByFire = true;\n\t\tdamage(Position(0, 0, 0), _fireMaxHit, mod->getDamageType(DT_IN), save, { });\n\t\t// try to set the unit on fire.\n\t\tif (RNG::percent(40 * getArmor()->getDamageModifier(DT_IN)))\n\t\t{\n\t\t\tint burnTime = RNG::generate(0, int(5.0f * getArmor()->getDamageModifier(DT_IN)));\n\t\t\tif (getFire() < burnTime)\n\t\t\t{\n\t\t\t\tsetFire(burnTime);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (_smokeMaxHit)\n\t{\n\t\tdamage(Position(0,0,0), _smokeMaxHit, mod->getDamageType(DT_SMOKE), save, { });\n\t}\n\n\t_fireMaxHit = 0;\n\t_smokeMaxHit = 0;\n}\n\n/**\n * Gets the turn cost.\n */\nint BattleUnit::getTurnCost() const\n{\n\treturn _armor->getTurnCost();\n}\n\n/**\n * Elevates the unit to grand galactic inquisitor status,\n * meaning they will NOT take part in the current battle.\n */\nvoid BattleUnit::goToTimeOut()\n{\n\t_status = STATUS_IGNORE_ME;\n\n\t// 1. Problem:\n\t// Take 2 rookies to an alien colony, leave 1 behind, and teleport the other to the exit and abort.\n\t// Then let the aliens kill the rookie in the second stage.\n\t// The mission will be a success, alien colony destroyed and everything recovered! (which is unquestionably wrong)\n\t// ------------\n\t// 2. Solution:\n\t// Proper solution would be to fix this in the Debriefing, but (as far as I can say)\n\t// that would require a lot of changes, Debriefing simply is not prepared for this scenario.\n\t// ------------\n\t// 3. Workaround:\n\t// Knock out all the player units left behind in the earlier stages\n\t// so that they don't count as survivors when all player units in the later stage are killed.\n\tif (_originalFaction == FACTION_PLAYER)\n\t{\n\t\t_stunlevel = std::max(_health, 1);\n\t}\n}\n\n/**\n * Set special weapon that is handled outside inventory.\n * @param save\n */\nvoid BattleUnit::setSpecialWeapon(SavedBattleGame *save, bool updateFromSave)\n{\n\tconst Mod *mod = save->getMod();\n\tint i = 0;\n\n\tauto addItem = [&](const RuleItem *item)\n\t{\n\t\tif (item && i < SPEC_WEAPON_MAX)\n\t\t{\n\t\t\tif (getBaseStats()->psiSkill <= 0 && item->isPsiRequired())\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t//TODO: move this check to load of ruleset\n\t\t\tif ((item->getBattleType() == BT_FIREARM || item->getBattleType() == BT_MELEE) && !item->getClipSize())\n\t\t\t{\n\t\t\t\tthrow Exception(\"Weapon \" + item->getType() + \" is used as a special built-in weapon on unit \" + getUnitRules()->getType() + \" but doesn't have it's own ammo - give it a clipSize!\");\n\t\t\t}\n\n\t\t\t// we already have an item of this type, skip it\n\t\t\tfor (auto* w : _specWeapon)\n\t\t\t{\n\t\t\t\tif (w && w->getRules() == item)\n\t\t\t\t{\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t_specWeapon[i++] = save->createItemForUnitSpecialBuiltin(item, this);\n\t\t}\n\t};\n\n\tif (_specWeapon[0] && updateFromSave)\n\t{\n\t\t// for backward compatibility, we try add corpse explosion\n\t\taddItem(getArmor()->getSelfDestructItem());\n\n\t\t// new saves already contain special built-in weapons, we can stop here\n\t\treturn;\n\t\t// old saves still need the below functionality to work properly\n\t}\n\n\tif (getUnitRules())\n\t{\n\t\taddItem(mod->getItem(getUnitRules()->getMeleeWeapon()));\n\t}\n\n\taddItem(getArmor()->getSpecialWeapon());\n\n\tif (getUnitRules() && getOriginalFaction() == FACTION_HOSTILE)\n\t{\n\t\taddItem(mod->getItem(getUnitRules()->getPsiWeapon()));\n\t}\n\tif (getGeoscapeSoldier())\n\t{\n\t\taddItem(getGeoscapeSoldier()->getRules()->getSpecialWeapon());\n\t}\n\n\taddItem(getArmor()->getSelfDestructItem());\n}\n\n/**\n * Add/assign a special weapon loaded from a save.\n */\nvoid BattleUnit::addLoadedSpecialWeapon(BattleItem* item)\n{\n\tfor (auto*& s : _specWeapon)\n\t{\n\t\tif (s == nullptr)\n\t\t{\n\t\t\ts = item;\n\t\t\treturn;\n\t\t}\n\t}\n\tLog(LOG_ERROR) << \"Failed to add special built-in item '\" << item->getRules()->getType() << \"' (id \" << item->getId() << \") to unit '\" << getType() << \"' (id \" << getId() << \")\";\n}\n\n/**\n * Remove all special weapons.\n */\nvoid BattleUnit::removeSpecialWeapons(SavedBattleGame *save)\n{\n\tfor (auto*& s : _specWeapon)\n\t{\n\t\tif (s)\n\t\t{\n\t\t\ts->setOwner(nullptr); // stops being a special weapon, so that `removeItem` can remove it\n\t\t\tsave->removeItem(s);\n\t\t\ts = nullptr;\n\t\t}\n\t}\n}\n\n/**\n * Get special weapon by battletype.\n */\nBattleItem *BattleUnit::getSpecialWeapon(BattleType type) const\n{\n\tfor (int i = 0; i < SPEC_WEAPON_MAX; ++i)\n\t{\n\t\tif (!_specWeapon[i])\n\t\t{\n\t\t\tbreak;\n\t\t}\n\t\tif (_specWeapon[i]->getRules()->getBattleType() == type)\n\t\t{\n\t\t\treturn _specWeapon[i];\n\t\t}\n\t}\n\treturn 0;\n}\n\n\n/**\n * Get special weapon by name.\n */\nBattleItem *BattleUnit::getSpecialWeapon(const RuleItem *weaponRule) const\n{\n\tfor (int i = 0; i < SPEC_WEAPON_MAX; ++i)\n\t{\n\t\tif (!_specWeapon[i])\n\t\t{\n\t\t\tbreak;\n\t\t}\n\t\tif (_specWeapon[i]->getRules() == weaponRule)\n\t\t{\n\t\t\treturn _specWeapon[i];\n\t\t}\n\t}\n\treturn 0;\n}\n\n/**\n * Gets the special weapon that uses an icon\n * @param type Parameter passed to get back the type of the weapon\n * @return Pointer the the weapon, null if not found\n */\nBattleItem *BattleUnit::getSpecialIconWeapon(BattleType &type) const\n{\n\tfor (int i = 0; i < SPEC_WEAPON_MAX; ++i)\n\t{\n\t\tif (!_specWeapon[i])\n\t\t{\n\t\t\tbreak;\n\t\t}\n\n\t\tif (_specWeapon[i]->getRules()->getSpecialIconSprite() != -1)\n\t\t{\n\t\t\ttype = _specWeapon[i]->getRules()->getBattleType();\n\t\t\treturn _specWeapon[i];\n\t\t}\n\t}\n\treturn 0;\n}\n\n/**\n * Recovers a unit's TUs and energy, taking a number of factors into consideration.\n */\nvoid BattleUnit::recoverTimeUnits()\n{\n\tupdateUnitStats(true, false);\n}\n\n/**\n * Get the unit's statistics.\n * @return BattleUnitStatistics statistics.\n */\nBattleUnitStatistics* BattleUnit::getStatistics()\n{\n\treturn _statistics;\n}\n\n/**\n * Sets the unit murderer's id.\n * @param int murderer id.\n */\nvoid BattleUnit::setMurdererId(int id)\n{\n\t_murdererId = id;\n}\n\n/**\n * Gets the unit murderer's id.\n * @return int murderer id.\n */\nint BattleUnit::getMurdererId() const\n{\n\treturn _murdererId;\n}\n\n/**\n * Set information on the unit's fatal blow.\n * @param UnitSide unit's side that was shot.\n * @param UnitBodyPart unit's body part that was shot.\n */\nvoid BattleUnit::setFatalShotInfo(UnitSide side, UnitBodyPart bodypart)\n{\n\t_fatalShotSide = side;\n\t_fatalShotBodyPart = bodypart;\n}\n\n/**\n * Get information on the unit's fatal shot's side.\n * @return UnitSide fatal shot's side.\n */\nUnitSide BattleUnit::getFatalShotSide() const\n{\n\treturn _fatalShotSide;\n}\n\n/**\n * Get information on the unit's fatal shot's body part.\n * @return UnitBodyPart fatal shot's body part.\n */\nUnitBodyPart BattleUnit::getFatalShotBodyPart() const\n{\n\treturn _fatalShotBodyPart;\n}\n\n/**\n * Gets the unit murderer's weapon.\n * @return int murderer weapon.\n */\nstd::string BattleUnit::getMurdererWeapon() const\n{\n\treturn _murdererWeapon;\n}\n\n/**\n * Set the murderer's weapon.\n * @param string murderer's weapon.\n */\nvoid BattleUnit::setMurdererWeapon(const std::string& weapon)\n{\n\t_murdererWeapon = weapon;\n}\n\n/**\n * Gets the unit murderer's weapon's ammo.\n * @return int murderer weapon ammo.\n */\nstd::string BattleUnit::getMurdererWeaponAmmo() const\n{\n\treturn _murdererWeaponAmmo;\n}\n\n/**\n * Set the murderer's weapon's ammo.\n * @param string murderer weapon ammo.\n */\nvoid BattleUnit::setMurdererWeaponAmmo(const std::string& weaponAmmo)\n{\n\t_murdererWeaponAmmo = weaponAmmo;\n}\n\n/**\n * Sets the unit mind controller's id.\n * @param int mind controller id.\n */\nvoid BattleUnit::setMindControllerId(int id)\n{\n\t_mindControllerID = id;\n}\n\n/**\n * Gets the unit mind controller's id.\n * @return int mind controller id.\n */\nint BattleUnit::getMindControllerId() const\n{\n\treturn _mindControllerID;\n}\n\n/**\n * Gets the spotter score. Determines how many turns sniper AI units can act on this unit seeing your troops.\n * @return The unit's spotter value.\n */\nint BattleUnit::getSpotterDuration() const\n{\n\tif (_unitRules)\n\t{\n\t\treturn _unitRules->getSpotterDuration();\n\t}\n\treturn 0;\n}\n\n/**\n * Remembers the unit's XP (used for shotguns).\n */\nvoid BattleUnit::rememberXP()\n{\n\t_expTmp = _exp;\n}\n\n/**\n * Artificially alter a unit's XP (used for shotguns).\n */\nvoid BattleUnit::nerfXP()\n{\n\t_exp = UnitStats::min(_exp, _expTmp + UnitStats::scalar(1));\n}\n\n/**\n * Was this unit just hit?\n */\nbool BattleUnit::getHitState()\n{\n\treturn _hitByAnything;\n}\n\n/**\n * reset the unit hit state.\n */\nvoid BattleUnit::resetHitState()\n{\n\t_hitByAnything = false;\n}\n\n/**\n * Was this unit melee attacked by a given attacker this turn (both hit and miss count)?\n */\nbool BattleUnit::wasMeleeAttackedBy(int attackerId) const\n{\n\treturn std::find(_meleeAttackedBy.begin(), _meleeAttackedBy.end(), attackerId) != _meleeAttackedBy.end();\n}\n\n/**\n * Set the \"melee attacked by\" flag.\n */\nvoid BattleUnit::setMeleeAttackedBy(int attackerId)\n{\n\tif (!wasMeleeAttackedBy(attackerId))\n\t{\n\t\t_meleeAttackedBy.push_back(attackerId);\n\t}\n}\n\n/**\n * Gets whether this unit can be captured alive (applies to aliens).\n */\nbool BattleUnit::getCapturable() const\n{\n\treturn _capturable;\n}\n\nvoid BattleUnit::freePatrolTarget()\n{\n\tif (_currentAIState)\n\t{\n\t\t_currentAIState->freePatrolTarget();\n\t}\n}\n\n/**\n * Marks this unit as summoned by an item or not.\n * @param summonedPlayerUnit summoned?\n */\nvoid BattleUnit::setSummonedPlayerUnit(bool summonedPlayerUnit)\n{\n\t_summonedPlayerUnit = summonedPlayerUnit;\n}\n\n/**\n * Was this unit summoned by an item?\n * @return True, if this unit was summoned by an item and therefore won't count for recovery or total player units left.\n */\nbool BattleUnit::isSummonedPlayerUnit() const\n{\n\treturn _summonedPlayerUnit;\n}\n\n/**\n * Should this unit (player, alien or civilian) be ignored for various things related to soldier diaries and commendations?\n */\nbool BattleUnit::isCosmetic() const\n{\n\treturn _unitRules && _unitRules->isCosmetic();\n}\n\n/**\n * Should this AI unit (alien or civilian) be ignored by other AI units?\n */\nbool BattleUnit::isIgnoredByAI() const\n{\n\treturn _unitRules && _unitRules->isIgnoredByAI();\n}\n\n/**\n * Is the unit afraid to pathfind through fire?\n * @return True if this unit has a penalty when pathfinding through fire.\n */\nbool BattleUnit::avoidsFire() const\n{\n\tif (_unitRules)\n\t{\n\t\treturn _unitRules->avoidsFire();\n\t}\n\treturn _specab < SPECAB_BURNFLOOR;\n}\n\n/**\n * Disable showing indicators for this unit.\n */\nvoid BattleUnit::disableIndicators()\n{\n\t_disableIndicators = true;\n}\n\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tScript binding\n////////////////////////////////////////////////////////////\n\nnamespace\n{\n\nvoid setArmorValueScript(BattleUnit *bu, int side, int value)\n{\n\tif (bu && 0 <= side && side < SIDE_MAX)\n\t{\n\t\tbu->setArmor(value, (UnitSide)side);\n\t}\n}\nvoid addArmorValueScript(BattleUnit *bu, int side, int value)\n{\n\tif (bu && 0 <= side && side < SIDE_MAX)\n\t{\n\t\t//limit range to prevent overflow\n\t\tvalue = Clamp(value, -UnitStats::BaseStatLimit, UnitStats::BaseStatLimit);\n\t\tbu->setArmor(value + bu->getArmor((UnitSide)side), (UnitSide)side);\n\t}\n}\nvoid getArmorValueScript(const BattleUnit *bu, int &ret, int side)\n{\n\tif (bu && 0 <= side && side < SIDE_MAX)\n\t{\n\t\tret = bu->getArmor((UnitSide)side);\n\t\treturn;\n\t}\n\tret = 0;\n}\nvoid setArmorValueMaxScript(BattleUnit *bu, int side, int value)\n{\n\tif (bu && 0 <= side && side < SIDE_MAX)\n\t{\n\t\tbu->setMaxArmor(value, (UnitSide)side);\n\t}\n}\nvoid getArmorValueMaxScript(const BattleUnit *bu, int &ret, int side)\n{\n\tif (bu && 0 <= side && side < SIDE_MAX)\n\t{\n\t\tret = bu->getMaxArmor((UnitSide)side);\n\t\treturn;\n\t}\n\tret = 0;\n}\n\nvoid setFatalWoundScript(BattleUnit *bu, int part, int val)\n{\n\tif (bu && 0 <= part && part < BODYPART_MAX)\n\t{\n\t\tbu->setFatalWound(val, (UnitBodyPart)part);\n\t}\n}\nvoid addFatalWoundScript(BattleUnit *bu, int part, int val)\n{\n\tif (bu && 0 <= part && part < BODYPART_MAX)\n\t{\n\t\t//limit range to prevent overflow\n\t\tval = Clamp(val, -UnitStats::BaseStatLimit, UnitStats::BaseStatLimit);\n\t\tbu->setFatalWound(val + bu->getFatalWound((UnitBodyPart)part), (UnitBodyPart)part);\n\t}\n}\nvoid getFatalWoundScript(const BattleUnit *bu, int &ret, int part)\n{\n\tif (bu && 0 <= part && part < BODYPART_MAX)\n\t{\n\t\tret = bu->getFatalWound((UnitBodyPart)part);\n\t\treturn;\n\t}\n\tret = 0;\n}\nvoid getFatalWoundMaxScript(const BattleUnit *bu, int &ret, int part)\n{\n\tif (bu && 0 <= part && part < BODYPART_MAX)\n\t{\n\t\tret = 100;\n\t\treturn;\n\t}\n\tret = 0;\n}\n\n\n\nvoid getMovmentTypeScript(const BattleUnit *bu, int &ret)\n{\n\tif (bu)\n\t{\n\t\tret = (int)bu->getMovementType();\n\t\treturn;\n\t}\n\tret = 0;\n}\nvoid getOriginalMovmentTypeScript(const BattleUnit *bu, int &ret)\n{\n\tif (bu)\n\t{\n\t\tret = (int)bu->getOriginalMovementType();\n\t\treturn;\n\t}\n\tret = 0;\n}\n\nvoid setMovmentTypeScript(BattleUnit *bu, int type)\n{\n\tif (bu && 0 <= type && type <= MT_SLIDE)\n\t{\n\t\tbu->setMovementType((MovementType)type);\n\t\treturn;\n\t}\n}\n\n\n\nvoid getGenderScript(const BattleUnit *bu, int &ret)\n{\n\tif (bu)\n\t{\n\t\tret = bu->getGender();\n\t\treturn;\n\t}\n\tret = 0;\n}\nvoid getLookScript(const BattleUnit *bu, int &ret)\n{\n\tif (bu)\n\t{\n\t\tauto g = bu->getGeoscapeSoldier();\n\t\tif (g)\n\t\t{\n\t\t\tret = g->getLook();\n\t\t\treturn;\n\t\t}\n\t}\n\tret = 0;\n}\nvoid getLookVariantScript(const BattleUnit *bu, int &ret)\n{\n\tif (bu)\n\t{\n\t\tauto g = bu->getGeoscapeSoldier();\n\t\tif (g)\n\t\t{\n\t\t\tret = g->getLookVariant();\n\t\t\treturn;\n\t\t}\n\t}\n\tret = 0;\n}\n\nstruct getRuleUnitScript\n{\n\tstatic RetEnum func(const BattleUnit* bu, const Unit*& ret)\n\t{\n\t\tif (bu)\n\t\t{\n\t\t\tret = bu->getUnitRules(); // Note: can be nullptr\n\t\t}\n\t\telse\n\t\t{\n\t\t\tret = nullptr;\n\t\t}\n\t\treturn RetContinue;\n\t}\n};\nstruct getRuleSoldierScript\n{\n\tstatic RetEnum func(const BattleUnit *bu, const RuleSoldier* &ret)\n\t{\n\t\tif (bu)\n\t\t{\n\t\t\tauto g = bu->getGeoscapeSoldier();\n\t\t\tif (g)\n\t\t\t{\n\t\t\t\tret = g->getRules();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tret = nullptr;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tret = nullptr;\n\t\t}\n\t\treturn RetContinue;\n\t}\n};\nstruct getGeoscapeSoldierScript\n{\n\tstatic RetEnum func(BattleUnit *bu, Soldier* &ret)\n\t{\n\t\tif (bu)\n\t\t{\n\t\t\tret = bu->getGeoscapeSoldier();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tret = nullptr;\n\t\t}\n\t\treturn RetContinue;\n\t}\n};\nstruct getGeoscapeSoldierConstScript\n{\n\tstatic RetEnum func(const BattleUnit *bu, const Soldier* &ret)\n\t{\n\t\tif (bu)\n\t\t{\n\t\t\tret = bu->getGeoscapeSoldier();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tret = nullptr;\n\t\t}\n\t\treturn RetContinue;\n\t}\n};\n\nvoid getReactionScoreScript(const BattleUnit *bu, int &ret)\n{\n\tif (bu)\n\t{\n\t\tret = (int)bu->getReactionScore();\n\t\treturn;\n\t}\n\tret = 0;\n}\nvoid getRecolorScript(const BattleUnit *bu, int &pixel)\n{\n\tif (bu)\n\t{\n\t\tconst auto& vec = bu->getRecolor();\n\t\tconst int g = pixel & helper::ColorGroup;\n\t\tconst int s = pixel & helper::ColorShade;\n\t\tfor (auto& p : vec)\n\t\t{\n\t\t\tif (g == p.first)\n\t\t\t{\n\t\t\t\tpixel = s + p.second;\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n}\nvoid getTileShade(const BattleUnit *bu, int &shade)\n{\n\tif (bu)\n\t{\n\t\tauto tile = bu->getTile();\n\t\tif (tile)\n\t\t{\n\t\t\tshade = tile->getShade();\n\t\t\treturn;\n\t\t}\n\t}\n\tshade = 0;\n}\n\nvoid getStunMaxScript(const BattleUnit *bu, int &maxStun)\n{\n\tif (bu)\n\t{\n\t\tmaxStun = bu->getBaseStats()->health * UnitStats::StunMultipler;\n\t\treturn;\n\t}\n\tmaxStun = 0;\n}\n\nstruct getRightHandWeaponScript\n{\n\tstatic RetEnum func(BattleUnit *bu, BattleItem *&bi)\n\t{\n\t\tif (bu)\n\t\t{\n\t\t\tbi = bu->getRightHandWeapon();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tbi = nullptr;\n\t\t}\n\t\treturn RetContinue;\n\t}\n};\nstruct getRightHandWeaponConstScript\n{\n\tstatic RetEnum func(const BattleUnit *bu, const BattleItem *&bi)\n\t{\n\t\tif (bu)\n\t\t{\n\t\t\tbi = bu->getRightHandWeapon();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tbi = nullptr;\n\t\t}\n\t\treturn RetContinue;\n\t}\n};\nstruct getLeftHandWeaponScript\n{\n\tstatic RetEnum func(BattleUnit *bu, BattleItem *&bi)\n\t{\n\t\tif (bu)\n\t\t{\n\t\t\tbi = bu->getLeftHandWeapon();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tbi = nullptr;\n\t\t}\n\t\treturn RetContinue;\n\t}\n};\nstruct getLeftHandWeaponConstScript\n{\n\tstatic RetEnum func(const BattleUnit *bu, const BattleItem *&bi)\n\t{\n\t\tif (bu)\n\t\t{\n\t\t\tbi = bu->getLeftHandWeapon();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tbi = nullptr;\n\t\t}\n\t\treturn RetContinue;\n\t}\n};\n\nstruct reduceByBraveryScript\n{\n\tstatic RetEnum func(const BattleUnit *bu, int &ret)\n\t{\n\t\tif (bu)\n\t\t{\n\t\t\tret = bu->reduceByBravery(ret);\n\t\t}\n\t\treturn RetContinue;\n\t}\n};\n\nstruct reduceByResistanceScript\n{\n\tstatic RetEnum func(const BattleUnit *bu, int &ret, int resistType)\n\t{\n\t\tif (bu)\n\t\t{\n\t\t\tif (resistType >= 0 && resistType < DAMAGE_TYPES)\n\t\t\t{\n\t\t\t\tret = bu->reduceByResistance(ret, (ItemDamageType)resistType);\n\t\t\t}\n\t\t}\n\t\treturn RetContinue;\n\t}\n};\n\nvoid isWalkingScript(const BattleUnit *bu, int &ret)\n{\n\tif (bu)\n\t{\n\t\tret = bu->getStatus() == STATUS_WALKING;\n\t\treturn;\n\t}\n\tret = 0;\n}\nvoid isFlyingScript(const BattleUnit *bu, int &ret)\n{\n\tif (bu)\n\t{\n\t\tret = bu->getStatus() == STATUS_FLYING;\n\t\treturn;\n\t}\n\tret = 0;\n}\nvoid isStunnedScript(const BattleUnit *bu, int &ret)\n{\n\tif (bu)\n\t{\n\t\tret = bu->getStatus() == STATUS_UNCONSCIOUS;\n\t\treturn;\n\t}\n\tret = 0;\n}\nvoid isKilledScript(const BattleUnit *bu, int &ret)\n{\n\tif (bu)\n\t{\n\t\tret = bu->getStatus() == STATUS_DEAD;\n\t\treturn;\n\t}\n\tret = 0;\n}\nvoid isCollapsingScript(const BattleUnit *bu, int &ret)\n{\n\tif (bu)\n\t{\n\t\tret = bu->getStatus() == STATUS_COLLAPSING;\n\t\treturn;\n\t}\n\tret = 0;\n}\nvoid isStandingScript(const BattleUnit *bu, int &ret)\n{\n\tif (bu)\n\t{\n\t\tret = bu->getStatus() == STATUS_STANDING;\n\t\treturn;\n\t}\n\tret = 0;\n}\nvoid isAimingScript(const BattleUnit *bu, int &ret)\n{\n\tif (bu)\n\t{\n\t\tret = bu->getStatus() == STATUS_AIMING;\n\t\treturn;\n\t}\n\tret = 0;\n}\n\nvoid makeVisibleScript(BattleUnit *bu)\n{\n\tif (bu)\n\t{\n\t\tbu->setVisible(true);\n\t\treturn;\n\t}\n}\n\nstruct burnShadeScript\n{\n\tstatic RetEnum func(int &curr, int burn, int shade)\n\t{\n\t\tUint8 d = curr;\n\t\tUint8 s = curr;\n\t\thelper::BurnShade::func(d, s, burn, shade);\n\t\tcurr = d;\n\t\treturn RetContinue;\n\t}\n};\n\ntemplate<int BattleUnit::*StatCurr, UnitStats::Ptr StatMax, int NegativeLimitMult = 0>\nvoid setBaseStatScript(BattleUnit *bu, int val)\n{\n\tif (bu)\n\t{\n\t\t(bu->*StatCurr) = Clamp(val, - NegativeLimitMult * (bu->getBaseStats()->*StatMax), +(bu->getBaseStats()->*StatMax));\n\t}\n}\ntemplate<int BattleUnit::*StatCurr, UnitStats::Ptr StatMax, int NegativeLimitMult = 0>\nvoid addBaseStatScript(BattleUnit *bu, int val)\n{\n\tif (bu)\n\t{\n\t\t//limit range to prevent overflow\n\t\tval = Clamp(val, -UnitStats::BaseStatLimit, UnitStats::BaseStatLimit);\n\t\tsetBaseStatScript<StatCurr, StatMax, NegativeLimitMult>(bu, val + (bu->*StatCurr));\n\t}\n}\n\ntemplate<int BattleUnit::*StatCurr>\nvoid setStunScript(BattleUnit *bu, int val)\n{\n\tif (bu)\n\t{\n\t\t(bu->*StatCurr) = Clamp(val, 0, (bu->getBaseStats()->health) * UnitStats::StunMultipler);\n\t}\n}\n\ntemplate<int BattleUnit::*StatCurr>\nvoid addStunScript(BattleUnit *bu, int val)\n{\n\tif (bu)\n\t{\n\t\t//limit range to prevent overflow, 4 time bigger than normal as stun can be 4 time bigger than health\n\t\tval = Clamp(val, -UnitStats::StunStatLimit, UnitStats::StunStatLimit);\n\t\tsetStunScript<StatCurr>(bu, val + (bu->*StatCurr));\n\t}\n}\n\ntemplate<auto StatCurr, int Min, int Max>\nvoid setBaseStatRangeScript(BattleUnit *bu, int val)\n{\n\tif (bu)\n\t{\n\t\t(bu->*StatCurr) = Clamp(val, Min, Max);\n\t}\n}\n\ntemplate<auto StatCurr, int Offset, int Min, int Max>\nvoid setBaseStatRangeArrayScript(BattleUnit *bu, int val)\n{\n\tif (bu)\n\t{\n\t\t(bu->*StatCurr)[Offset] = Clamp(val, Min, Max);\n\t}\n}\n\n\ntemplate<int BattleUnit::*StatCurr, int Min, int Max>\nvoid addBaseStatRangeScript(BattleUnit *bu, int val)\n{\n\tif (bu)\n\t{\n\t\t//limit range to prevent overflow\n\t\tval = Clamp(val, -UnitStats::BaseStatLimit, UnitStats::BaseStatLimit);\n\t\tsetBaseStatRangeScript<StatCurr, Min, Max>(bu, val + (bu->*StatCurr));\n\t}\n}\n\nvoid setFireScript(BattleUnit *bu, int val)\n{\n\tif (bu)\n\t{\n\t\tval = Clamp(val, 0, UnitStats::BaseStatLimit);\n\t\tbu->setFire(val);\n\t}\n}\n\n\nvoid getVisibleUnitsCountScript(BattleUnit *bu, int &ret)\n{\n\tif (bu)\n\t{\n\n\t\tauto visibleUnits = bu->getVisibleUnits();\n\t\tret = visibleUnits->size();\n\t}\n}\n\n/**\n * Get the X part of the tile coordinate of this unit.\n * @return X Position.\n */\nvoid getPositionXScript(const BattleUnit *bu, int &ret)\n{\n\tif (bu)\n\t{\n\t\tret = bu->getPosition().x;\n\t\treturn;\n\t}\n\tret = 0;\n}\n\n/**\n * Get the Y part of the tile coordinate of this unit.\n * @return Y Position.\n */\nvoid getPositionYScript(const BattleUnit *bu, int &ret)\n{\n\tif (bu)\n\t{\n\t\tret = bu->getPosition().y;\n\t\treturn;\n\t}\n\tret = 0;\n}\n/**\n * Get the Z part of the tile coordinate of this unit.\n * @return Z Position.\n */\nvoid getPositionZScript(const BattleUnit *bu, int &ret)\n{\n\tif (bu)\n\t{\n\t\tret = bu->getPosition().z;\n\t\treturn;\n\t}\n\tret = 0;\n}\n\nvoid getFactionScript(const BattleUnit *bu, int &faction)\n{\n\tif (bu)\n\t{\n\t\tfaction = (int)bu->getFaction();\n\t\treturn;\n\t}\n\tfaction = 0;\n}\n\nvoid getOriginalFactionScript(const BattleUnit *bu, int &faction)\n{\n\tif (bu)\n\t{\n\t\tfaction = (int)bu->getOriginalFaction();\n\t\treturn;\n\t}\n\tfaction = 0;\n}\n\n\nvoid setSpawnUnitScript(BattleUnit *bu, const Unit* unitType)\n{\n\tif (bu && unitType && bu->getArmor()->getSize() >= unitType->getArmor()->getSize())\n\t{\n\t\tbu->setSpawnUnit(unitType);\n\t\tbu->setRespawn(true);\n\t\tbu->setSpawnUnitFaction(FACTION_HOSTILE);\n\t}\n\telse if (bu)\n\t{\n\t\tbu->clearSpawnUnit();\n\t}\n}\n\nvoid getSpawnUnitScript(BattleUnit *bu, const Unit*& unitType)\n{\n\tunitType = bu ? bu->getSpawnUnit() : nullptr;\n}\n\nvoid setSpawnUnitInstantRespawnScript(BattleUnit *bu, int respawn)\n{\n\tif (bu && bu->getSpawnUnit())\n\t{\n\t\tbu->setRespawn(respawn);\n\t}\n}\n\nvoid getSpawnUnitInstantRespawnScript(BattleUnit *bu, int& respawn)\n{\n\trespawn = bu ? bu->getRespawn() : 0;\n}\n\nvoid setSpawnUnitFactionScript(BattleUnit *bu, int faction)\n{\n\tif (bu && bu->getSpawnUnit())\n\t{\n\t\tif (faction >= FACTION_PLAYER && faction <= FACTION_NEUTRAL)\n\t\t{\n\t\t\tbu->setSpawnUnitFaction((UnitFaction)faction);\n\t\t}\n\t}\n}\n\nvoid getSpawnUnitFactionScript(BattleUnit *bu, int& faction)\n{\n\tfaction = bu ? bu->getSpawnUnitFaction() : 0;\n}\n\n\nvoid getInventoryItemScript(BattleUnit* bu, BattleItem *&foundItem, const RuleItem *itemRules)\n{\n\tfoundItem = nullptr;\n\tif (bu)\n\t{\n\t\tfor (auto* i : *bu->getInventory())\n\t\t{\n\t\t\tif (i->getRules() == itemRules)\n\t\t\t{\n\t\t\t\tfoundItem = i;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid getInventoryItemConstScript(const BattleUnit* bu, const BattleItem *&foundItem, const RuleItem *itemRules)\n{\n\tfoundItem = nullptr;\n\tif (bu)\n\t{\n\t\tfor (auto* i : *bu->getInventory())\n\t\t{\n\t\t\tif (i->getRules() == itemRules)\n\t\t\t{\n\t\t\t\tfoundItem = i;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid getInventoryItemScript1(BattleUnit* bu, BattleItem *&foundItem, const RuleInventory *inv, const RuleItem *itemRules)\n{\n\tfoundItem = nullptr;\n\tif (bu)\n\t{\n\t\tfor (auto* i : *bu->getInventory())\n\t\t{\n\t\t\tif (i->getSlot() == inv && i->getRules() == itemRules)\n\t\t\t{\n\t\t\t\tfoundItem = i;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid getInventoryItemConstScript1(const BattleUnit* bu, const BattleItem *&foundItem, const RuleInventory *inv, const RuleItem *itemRules)\n{\n\tfoundItem = nullptr;\n\tif (bu)\n\t{\n\t\tfor (auto* i : *bu->getInventory())\n\t\t{\n\t\t\tif (i->getSlot() == inv && i->getRules() == itemRules)\n\t\t\t{\n\t\t\t\tfoundItem = i;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid getInventoryItemScript2(BattleUnit* bu, BattleItem *&foundItem, const RuleInventory *inv)\n{\n\tfoundItem = nullptr;\n\tif (bu)\n\t{\n\t\tfor (auto* i : *bu->getInventory())\n\t\t{\n\t\t\tif (i->getSlot() == inv)\n\t\t\t{\n\t\t\t\tfoundItem = i;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid getInventoryItemConstScript2(const BattleUnit* bu, const BattleItem *&foundItem, const RuleInventory *inv)\n{\n\tfoundItem = nullptr;\n\tif (bu)\n\t{\n\t\tfor (auto* i : *bu->getInventory())\n\t\t{\n\t\t\tif (i->getSlot() == inv)\n\t\t\t{\n\t\t\t\tfoundItem = i;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\n//TODO: move it to script bindings\ntemplate<auto Member>\nvoid getListScript(BattleUnit* bu, BattleItem *&foundItem, int i)\n{\n\tfoundItem = nullptr;\n\tif (bu)\n\t{\n\t\tauto& ptr = (bu->*Member);\n\t\tif ((size_t)i < std::size(ptr))\n\t\t{\n\t\t\tfoundItem = ptr[i];\n\t\t}\n\t}\n}\n\n//TODO: move it to script bindings\ntemplate<auto Member>\nvoid getListConstScript(const BattleUnit* bu, const BattleItem *&foundItem, int i)\n{\n\tfoundItem = nullptr;\n\tif (bu)\n\t{\n\t\tauto& ptr = (bu->*Member);\n\t\tif ((size_t)i < std::size(ptr))\n\t\t{\n\t\t\tfoundItem = ptr[i];\n\t\t}\n\t}\n}\n\n//TODO: move it to script bindings\ntemplate<auto Member>\nvoid getListSizeScript(const BattleUnit* bu, int& i)\n{\n\ti = 0;\n\tif (bu)\n\t{\n\t\tauto& ptr = (bu->*Member);\n\t\ti = (int)std::size(ptr);\n\t}\n}\n\ntemplate<auto Member>\nvoid getListSizeHackScript(const BattleUnit* bu, int& i)\n{\n\ti = 0;\n\tif (bu)\n\t{\n\t\tauto& ptr = (bu->*Member);\n\t\t//count number of elements until null, and interpret this as size of array\n\t\ti = std::distance(\n\t\t\tstd::begin(ptr),\n\t\t\tstd::find(std::begin(ptr), std::end(ptr), nullptr)\n\t\t);\n\t}\n}\n\nbool filterItemScript(BattleUnit* unit, BattleItem* item)\n{\n\treturn item;\n}\n\nbool filterItemConstScript(const BattleUnit* unit, const BattleItem* item)\n{\n\treturn item;\n}\n\nstd::string debugDisplayScript(const BattleUnit* bu)\n{\n\tif (bu)\n\t{\n\t\tstd::string s;\n\t\ts += BattleUnit::ScriptName;\n\t\ts += \"(type: \\\"\";\n\t\ts += bu->getType();\n\t\tauto unit = bu->getUnitRules();\n\t\tif (unit)\n\t\t{\n\t\t\ts += \"\\\" race: \\\"\";\n\t\t\ts += unit->getRace();\n\t\t}\n\t\tauto soldier = bu->getGeoscapeSoldier();\n\t\tif (soldier)\n\t\t{\n\t\t\ts += \"\\\" name: \\\"\";\n\t\t\ts += soldier->getName();\n\t\t}\n\t\ts += \"\\\" id: \";\n\t\ts += std::to_string(bu->getId());\n\t\ts += \" faction: \";\n\t\tswitch (bu->getFaction())\n\t\t{\n\t\tcase FACTION_HOSTILE: s += \"Hostile\"; break;\n\t\tcase FACTION_NEUTRAL: s += \"Neutral\"; break;\n\t\tcase FACTION_PLAYER: s += \"Player\"; break;\n\t\tdefault: s += \"???\"; break;\n\t\t}\n\t\ts += \" hp: \";\n\t\ts += std::to_string(bu->getHealth());\n\t\ts += \"/\";\n\t\ts += std::to_string(bu->getBaseStats()->health);\n\t\ts += \")\";\n\t\treturn s;\n\t}\n\telse\n\t{\n\t\treturn \"null\";\n\t}\n}\n\n} // namespace\n\n/**\n * Register BattleUnit in script parser.\n * @param parser Script parser.\n */\nvoid BattleUnit::ScriptRegister(ScriptParserBase* parser)\n{\n\tparser->registerPointerType<Mod>();\n\tparser->registerPointerType<Armor>();\n\tparser->registerPointerType<RuleSoldier>();\n\tparser->registerPointerType<BattleItem>();\n\tparser->registerPointerType<Soldier>();\n\tparser->registerPointerType<RuleSkill>();\n\tparser->registerPointerType<Unit>();\n\tparser->registerPointerType<RuleInventory>();\n\n\tBind<BattleUnit> bu = { parser };\n\n\tbu.addField<&BattleUnit::_id>(\"getId\");\n\tbu.addField<&BattleUnit::_rankInt>(\"getRank\");\n\tbu.addField<&BattleUnit::_rankIntUnified>(\"getRankUnified\");\n\tbu.add<&getGenderScript>(\"getGender\");\n\tbu.add<&getLookScript>(\"getLook\");\n\tbu.add<&getLookVariantScript>(\"getLookVariant\");\n\tbu.add<&getRecolorScript>(\"getRecolor\");\n\tbu.add<&BattleUnit::isFloating>(\"isFloating\");\n\tbu.add<&BattleUnit::isKneeled>(\"isKneeled\");\n\tbu.add<&isStunnedScript>(\"isStunned\");\n\tbu.add<&isKilledScript>(\"isKilled\");\n\tbu.add<&isStandingScript>(\"isStanding\");\n\tbu.add<&isWalkingScript>(\"isWalking\");\n\tbu.add<&isFlyingScript>(\"isFlying\");\n\tbu.add<&isCollapsingScript>(\"isCollapsing\");\n\tbu.add<&isAimingScript>(\"isAiming\");\n\tbu.add<&BattleUnit::isFearable>(\"isFearable\");\n\tbu.add<&BattleUnit::isWoundable>(\"isWoundable\");\n\tbu.add<&getReactionScoreScript>(\"getReactionScore\");\n\tbu.add<&BattleUnit::getDirection>(\"getDirection\");\n\tbu.add<&BattleUnit::getIntelligence>(\"getIntelligence\");\n\tbu.add<&BattleUnit::getAggression>(\"getAggression\");\n\tbu.add<&BattleUnit::getTurretDirection>(\"getTurretDirection\");\n\tbu.add<&BattleUnit::getWalkingPhase>(\"getWalkingPhase\");\n\tbu.add<&BattleUnit::disableIndicators>(\"disableIndicators\");\n\n\tbu.add<&BattleUnit::getVisible>(\"isVisible\");\n\tbu.add<&makeVisibleScript>(\"makeVisible\");\n\n\tbu.add<&BattleUnit::getMaxViewDistanceAtDark>(\"getMaxViewDistanceAtDark\", \"get maximum visibility distance in tiles to another unit at dark\");\n\tbu.add<&BattleUnit::getMaxViewDistanceAtDay>(\"getMaxViewDistanceAtDay\", \"get maximum visibility distance in tiles to another unit at day\");\n\tbu.add<&BattleUnit::getMaxViewDistance>(\"getMaxViewDistance\", \"calculate maximum visibility distance consider camouflage, first arg is base visibility, second arg is cammo reduction, third arg is anti-cammo boost\");\n\tbu.add<&BattleUnit::getPsiVision>(\"getPsiVision\");\n\tbu.add<&BattleUnit::getVisibilityThroughSmoke>(\"getHeatVision\", \"getVisibilityThroughSmoke\");\n\tbu.add<&BattleUnit::getVisibilityThroughFire>(\"getVisibilityThroughFire\", \"getVisibilityThroughFire\");\n\n\tbu.add<&setSpawnUnitScript>(\"setSpawnUnit\", \"set type of zombie will be spawn from current unit, it will reset everything to default (hostile & instant)\");\n\tbu.add<&getSpawnUnitScript>(\"getSpawnUnit\", \"get type of zombie will be spawn from current unit\");\n\tbu.add<&setSpawnUnitInstantRespawnScript>(\"setSpawnUnitInstantRespawn\", \"set 1 to make unit instantly change to spawn zombie unit, other wise it will transform on death\");\n\tbu.add<&getSpawnUnitInstantRespawnScript>(\"getSpawnUnitInstantRespawn\", \"get state of instant respawn\");\n\tbu.add<&setSpawnUnitFactionScript>(\"setSpawnUnitFaction\", \"set faction of unit that will spawn\");\n\tbu.add<&getSpawnUnitFactionScript>(\"getSpawnUnitFaction\", \"get faction of unit that will spawn\");\n\n\n\tbu.addPair<BattleUnit, &BattleUnit::getPreviousOwner, &BattleUnit::getPreviousOwner>(\"getPreviousOwner\");\n\n\n\tbu.addField<&BattleUnit::_tu>(\"getTimeUnits\");\n\tbu.add<&UnitStats::getMaxStatScript<BattleUnit, &BattleUnit::_stats, &UnitStats::tu>>(\"getTimeUnitsMax\");\n\tbu.add<&setBaseStatScript<&BattleUnit::_tu, &UnitStats::tu>>(\"setTimeUnits\");\n\tbu.add<&addBaseStatScript<&BattleUnit::_tu, &UnitStats::tu>>(\"addTimeUnits\");\n\n\tbu.addField<&BattleUnit::_health>(\"getHealth\");\n\tbu.add<UnitStats::getMaxStatScript<BattleUnit, &BattleUnit::_stats, &UnitStats::health>>(\"getHealthMax\");\n\tbu.add<&setBaseStatScript<&BattleUnit::_health, &UnitStats::health>>(\"setHealth\");\n\tbu.add<&addBaseStatScript<&BattleUnit::_health, &UnitStats::health>>(\"addHealth\");\n\tbu.add<&setBaseStatScript<&BattleUnit::_health, &UnitStats::health, UnitStats::OverkillMultipler>>(\"setHealthWithOverkill\", \"same as setHealth but allow negative health values like with Overkill\");\n\tbu.add<&addBaseStatScript<&BattleUnit::_health, &UnitStats::health, UnitStats::OverkillMultipler>>(\"addHealthWithOverkill\", \"same as addHealth but allow negative health values like with Overkill\");\n\n\tbu.addField<&BattleUnit::_mana>(\"getMana\");\n\tbu.add<&UnitStats::getMaxStatScript<BattleUnit, &BattleUnit::_stats, &UnitStats::mana>>(\"getManaMax\");\n\tbu.add<&setBaseStatScript<&BattleUnit::_mana, &UnitStats::mana>>(\"setMana\");\n\tbu.add<&addBaseStatScript<&BattleUnit::_mana, &UnitStats::mana>>(\"addMana\");\n\n\tbu.addField<&BattleUnit::_energy>(\"getEnergy\");\n\tbu.add<&UnitStats::getMaxStatScript<BattleUnit, &BattleUnit::_stats, &UnitStats::stamina>>(\"getEnergyMax\");\n\tbu.add<&setBaseStatScript<&BattleUnit::_energy, &UnitStats::stamina>>(\"setEnergy\");\n\tbu.add<&addBaseStatScript<&BattleUnit::_energy, &UnitStats::stamina>>(\"addEnergy\");\n\n\tbu.addField<&BattleUnit::_stunlevel>(\"getStun\");\n\tbu.add<&getStunMaxScript>(\"getStunMax\");\n\tbu.add<&setStunScript<&BattleUnit::_stunlevel>>(\"setStun\");\n\tbu.add<&addStunScript<&BattleUnit::_stunlevel>>(\"addStun\");\n\n\tbu.addField<&BattleUnit::_morale>(\"getMorale\");\n\tbu.addFake<100>(\"getMoraleMax\");\n\tbu.add<&setBaseStatRangeScript<&BattleUnit::_morale, 0, 100>>(\"setMorale\");\n\tbu.add<&addBaseStatRangeScript<&BattleUnit::_morale, 0, 100>>(\"addMorale\");\n\n\n\tbu.add<&BattleUnit::getFire>(\"getFire\");\n\tbu.add<&setFireScript>(\"setFire\");\n\n\n\tbu.add<&setArmorValueScript>(\"setArmor\", \"first arg is side, second one is new value of armor\");\n\tbu.add<&addArmorValueScript>(\"addArmor\", \"first arg is side, second one is value to add to armor\");\n\tbu.add<&getArmorValueScript>(\"getArmor\", \"first arg return armor value, second arg is side\");\n\tbu.add<&setArmorValueMaxScript>(\"setArmorMax\", \"first arg is side, second one is new value of max armor\");\n\tbu.add<&getArmorValueMaxScript>(\"getArmorMax\", \"first arg return max armor value, second arg is side\");\n\n\tbu.add<&BattleUnit::getFatalWounds>(\"getFatalwoundsTotal\", \"sum for every body part\");\n\tbu.add<&setFatalWoundScript>(\"setFatalwounds\", \"first arg is body part, second one is new value of wounds\");\n\tbu.add<&addFatalWoundScript>(\"addFatalwounds\", \"first arg is body part, second one is value to add to wounds\");\n\tbu.add<&getFatalWoundScript>(\"getFatalwounds\", \"first arg return wounds number, second arg is body part\");\n\tbu.add<&getFatalWoundMaxScript>(\"getFatalwoundsMax\", \"first arg return max wounds number, second arg is body part\");\n\n\tUnitStats::addGetStatsScript<&BattleUnit::_stats>(bu, \"Stats.\");\n\tUnitStats::addSetStatsWithCurrScript<&BattleUnit::_stats, &BattleUnit::_tu, &BattleUnit::_energy, &BattleUnit::_health, &BattleUnit::_mana>(bu, \"Stats.\");\n\n\tUnitStats::addGetStatsScript<&BattleUnit::_exp>(bu, \"Exp.\", true);\n\n\n\tbu.add<&getMovmentTypeScript>(\"getMovmentType\", BindBase::functionInvisible); //old bugged name\n\tbu.add<&getMovmentTypeScript>(\"getMovementType\", \"get move type of unit\");\n\tbu.add<&getOriginalMovmentTypeScript>(\"getOriginalMovementType\", \"get original move type of unit\");\n\tbu.add<&setMovmentTypeScript>(\"setMovementType\", \"set move type of unit\");\n\n\tbu.addField<&BattleUnit::_moveCostBase, &ArmorMoveCost::TimePercent>(\"MoveCost.getBaseTimePercent\", \"MoveCost.setBaseTimePercent\");\n\tbu.addField<&BattleUnit::_moveCostBase, &ArmorMoveCost::EnergyPercent>(\"MoveCost.getBaseEnergyPercent\", \"MoveCost.setBaseEnergyPercent\");\n\tbu.addField<&BattleUnit::_moveCostBaseFly, &ArmorMoveCost::TimePercent>(\"MoveCost.getBaseFlyTimePercent\", \"MoveCost.setBaseFlyTimePercent\");\n\tbu.addField<&BattleUnit::_moveCostBaseFly, &ArmorMoveCost::EnergyPercent>(\"MoveCost.getBaseFlyEnergyPercent\", \"MoveCost.setBaseFlyEnergyPercent\");\n\tbu.addField<&BattleUnit::_moveCostBaseClimb, &ArmorMoveCost::TimePercent>(\"MoveCost.getBaseClimbTimePercent\", \"MoveCost.setBaseClimbTimePercent\");\n\tbu.addField<&BattleUnit::_moveCostBaseClimb, &ArmorMoveCost::EnergyPercent>(\"MoveCost.getBaseClimbEnergyPercent\", \"MoveCost.setBaseClimbEnergyPercent\");\n\tbu.addField<&BattleUnit::_moveCostBaseNormal, &ArmorMoveCost::TimePercent>(\"MoveCost.getBaseNormalTimePercent\", \"MoveCost.setBaseNormalTimePercent\");\n\tbu.addField<&BattleUnit::_moveCostBaseNormal, &ArmorMoveCost::EnergyPercent>(\"MoveCost.getBaseNormalEnergyPercent\", \"MoveCost.setBaseNormalEnergyPercent\");\n\n\tbu.add<&getVisibleUnitsCountScript>(\"getVisibleUnitsCount\");\n\tbu.add<&getFactionScript>(\"getFaction\", \"get current faction of unit\");\n\tbu.add<&getOriginalFactionScript>(\"getOriginalFaction\", \"get original faction of unit\");\n\n\tbu.add<&BattleUnit::getOverKillDamage>(\"getOverKillDamage\");\n\tbu.addRules<Armor, &BattleUnit::getArmor>(\"getRuleArmor\");\n\tbu.addFunc<getRuleUnitScript>(\"getRuleUnit\");\n\tbu.addFunc<getRuleSoldierScript>(\"getRuleSoldier\");\n\tbu.addFunc<getGeoscapeSoldierScript>(\"getGeoscapeSoldier\");\n\tbu.addFunc<getGeoscapeSoldierConstScript>(\"getGeoscapeSoldier\");\n\tbu.addFunc<reduceByBraveryScript>(\"reduceByBravery\", \"change first arg1 to `(110 - bravery) * arg1 / 100`\");\n\tbu.addFunc<reduceByResistanceScript>(\"reduceByResistance\", \"change first arg1 to `arg1 * resist[arg2]`\");\n\n\tbu.addFunc<getRightHandWeaponScript>(\"getRightHandWeapon\");\n\tbu.addFunc<getRightHandWeaponConstScript>(\"getRightHandWeapon\");\n\tbu.addFunc<getLeftHandWeaponScript>(\"getLeftHandWeapon\");\n\tbu.addFunc<getLeftHandWeaponConstScript>(\"getLeftHandWeapon\");\n\tbu.add<&getInventoryItemScript>(\"getInventoryItem\");\n\tbu.add<&getInventoryItemScript1>(\"getInventoryItem\");\n\tbu.add<&getInventoryItemScript2>(\"getInventoryItem\");\n\tbu.add<&getInventoryItemConstScript>(\"getInventoryItem\");\n\tbu.add<&getInventoryItemConstScript1>(\"getInventoryItem\");\n\tbu.add<&getInventoryItemConstScript2>(\"getInventoryItem\");\n\tbu.add<&getListSizeScript<&BattleUnit::_inventory>>(\"getInventoryItem.size\");\n\tbu.add<&getListScript<&BattleUnit::_inventory>>(\"getInventoryItem\");\n\tbu.add<&getListConstScript<&BattleUnit::_inventory>>(\"getInventoryItem\");\n\tbu.addList<&filterItemScript, &BattleUnit::_inventory>(\"getInventoryItem\");\n\tbu.addList<&filterItemConstScript, &BattleUnit::_inventory>(\"getInventoryItem\");\n\tbu.add<&getListSizeHackScript<&BattleUnit::_specWeapon>>(\"getSpecialItem.size\");\n\tbu.add<&getListScript<&BattleUnit::_specWeapon>>(\"getSpecialItem\");\n\tbu.add<&getListConstScript<&BattleUnit::_specWeapon>>(\"getSpecialItem\");\n\tbu.addList<&filterItemScript, &BattleUnit::_specWeapon>(\"getSpecialItem\");\n\tbu.addList<&filterItemConstScript, &BattleUnit::_specWeapon>(\"getSpecialItem\");\n\n\tbu.add<&getPositionXScript>(\"getPosition.getX\");\n\tbu.add<&getPositionYScript>(\"getPosition.getY\");\n\tbu.add<&getPositionZScript>(\"getPosition.getZ\");\n\tbu.add<&BattleUnit::getPosition>(\"getPosition\");\n\n\n\tbu.add<&BattleUnit::getTurnsSinceSpotted>(\"getTurnsSinceSpotted\");\n\tbu.add<&setBaseStatRangeArrayScript<&BattleUnit::_turnsSinceSpotted, FACTION_HOSTILE, 0, 255>>(\"setTurnsSinceSpotted\");\n\n\tbu.add<&BattleUnit::getTurnsSinceSpottedByFaction>(\"getTurnsSinceSpottedByFaction\");\n\tbu.add<&BattleUnit::setTurnsSinceSpottedByFaction>(\"setTurnsSinceSpottedByFaction\");\n\n\tbu.add<&BattleUnit::getTurnsLeftSpottedForSnipers>(\"getTurnsLeftSpottedForSnipers\");\n\tbu.add<&setBaseStatRangeArrayScript<&BattleUnit::_turnsLeftSpottedForSnipers, FACTION_HOSTILE, 0, 255>>(\"setTurnsLeftSpottedForSnipers\");\n\n\tbu.add<&BattleUnit::getTurnsLeftSpottedForSnipersByFaction>(\"getTurnsLeftSpottedForSnipersByFaction\");\n\tbu.add<&BattleUnit::setTurnsLeftSpottedForSnipersByFaction>(\"setTTurnsLeftSpottedForSnipersByFaction\");\n\n\tbu.addField<&BattleUnit::_turnsSinceStunned>(\"getTurnsSinceStunned\");\n\tbu.add<&setBaseStatRangeScript<&BattleUnit::_turnsSinceStunned, 0, 255>>(\"setTurnsSinceStunned\");\n\n\n\tbu.addScriptValue<BindBase::OnlyGet, &BattleUnit::_armor, &Armor::getScriptValuesRaw>();\n\tbu.addScriptValue<&BattleUnit::_scriptValues>();\n\tbu.addDebugDisplay<&debugDisplayScript>();\n\n\n\tbu.add<&getTileShade>(\"getTileShade\");\n\n\n\tbu.addCustomConst(\"BODYPART_HEAD\", BODYPART_HEAD);\n\tbu.addCustomConst(\"BODYPART_TORSO\", BODYPART_TORSO);\n\tbu.addCustomConst(\"BODYPART_LEFTARM\", BODYPART_LEFTARM);\n\tbu.addCustomConst(\"BODYPART_RIGHTARM\", BODYPART_RIGHTARM);\n\tbu.addCustomConst(\"BODYPART_LEFTLEG\", BODYPART_LEFTLEG);\n\tbu.addCustomConst(\"BODYPART_RIGHTLEG\", BODYPART_RIGHTLEG);\n\n\tbu.addCustomConst(\"UNIT_RANK_ROOKIE\", 0);\n\tbu.addCustomConst(\"UNIT_RANK_SQUADDIE\", 1);\n\tbu.addCustomConst(\"UNIT_RANK_SERGEANT\", 2);\n\tbu.addCustomConst(\"UNIT_RANK_CAPTAIN\", 3);\n\tbu.addCustomConst(\"UNIT_RANK_COLONEL\", 4);\n\tbu.addCustomConst(\"UNIT_RANK_COMMANDER\", 5);\n\n\tbu.addCustomConst(\"COLOR_X1_HAIR\", 6);\n\tbu.addCustomConst(\"COLOR_X1_FACE\", 9);\n\n\tbu.addCustomConst(\"COLOR_X1_NULL\", 0);\n\tbu.addCustomConst(\"COLOR_X1_YELLOW\", 1);\n\tbu.addCustomConst(\"COLOR_X1_RED\", 2);\n\tbu.addCustomConst(\"COLOR_X1_GREEN0\", 3);\n\tbu.addCustomConst(\"COLOR_X1_GREEN1\", 4);\n\tbu.addCustomConst(\"COLOR_X1_GRAY\", 5);\n\tbu.addCustomConst(\"COLOR_X1_BROWN0\", 6);\n\tbu.addCustomConst(\"COLOR_X1_BLUE0\", 7);\n\tbu.addCustomConst(\"COLOR_X1_BLUE1\", 8);\n\tbu.addCustomConst(\"COLOR_X1_BROWN1\", 9);\n\tbu.addCustomConst(\"COLOR_X1_BROWN2\", 10);\n\tbu.addCustomConst(\"COLOR_X1_PURPLE0\", 11);\n\tbu.addCustomConst(\"COLOR_X1_PURPLE1\", 12);\n\tbu.addCustomConst(\"COLOR_X1_BLUE2\", 13);\n\tbu.addCustomConst(\"COLOR_X1_SILVER\", 14);\n\tbu.addCustomConst(\"COLOR_X1_SPECIAL\", 15);\n\n\n\tbu.addCustomConst(\"LOOK_BLONDE\", LOOK_BLONDE);\n\tbu.addCustomConst(\"LOOK_BROWNHAIR\", LOOK_BROWNHAIR);\n\tbu.addCustomConst(\"LOOK_ORIENTAL\", LOOK_ORIENTAL);\n\tbu.addCustomConst(\"LOOK_AFRICAN\", LOOK_AFRICAN);\n\n\tbu.addCustomConst(\"GENDER_MALE\", GENDER_MALE);\n\tbu.addCustomConst(\"GENDER_FEMALE\", GENDER_FEMALE);\n\n\tbu.addCustomConst(\"movement_type_walk\", MT_WALK);\n\tbu.addCustomConst(\"movement_type_fly\", MT_FLY);\n\tbu.addCustomConst(\"movement_type_slide\", MT_SLIDE);\n}\n\n/**\n * Register BattleUnitVisibility in script parser.\n * @param parser Script parser.\n */\nvoid BattleUnitVisibility::ScriptRegister(ScriptParserBase* parser)\n{\n\tBind<BattleUnitVisibility> uv = { parser };\n\n\tuv.addScriptTag();\n}\n\n\nnamespace\n{\n\nvoid commonImpl(BindBase& b, Mod* mod)\n{\n\tb.addCustomPtr<const Mod>(\"rules\", mod);\n\n\tb.addCustomConst(\"blit_torso\", BODYPART_TORSO);\n\tb.addCustomConst(\"blit_leftarm\", BODYPART_LEFTARM);\n\tb.addCustomConst(\"blit_rightarm\", BODYPART_RIGHTARM);\n\tb.addCustomConst(\"blit_legs\", BODYPART_LEGS);\n\tb.addCustomConst(\"blit_collapse\", BODYPART_COLLAPSING);\n\n\tb.addCustomConst(\"blit_large_torso_0\", BODYPART_LARGE_TORSO + 0);\n\tb.addCustomConst(\"blit_large_torso_1\", BODYPART_LARGE_TORSO + 1);\n\tb.addCustomConst(\"blit_large_torso_2\", BODYPART_LARGE_TORSO + 2);\n\tb.addCustomConst(\"blit_large_torso_3\", BODYPART_LARGE_TORSO + 3);\n\tb.addCustomConst(\"blit_large_propulsion_0\", BODYPART_LARGE_PROPULSION + 0);\n\tb.addCustomConst(\"blit_large_propulsion_1\", BODYPART_LARGE_PROPULSION + 1);\n\tb.addCustomConst(\"blit_large_propulsion_2\", BODYPART_LARGE_PROPULSION + 2);\n\tb.addCustomConst(\"blit_large_propulsion_3\", BODYPART_LARGE_PROPULSION + 3);\n\tb.addCustomConst(\"blit_large_turret\", BODYPART_LARGE_TURRET);\n}\n\nvoid battleActionImpl(BindBase& b)\n{\n\tb.addCustomConst(\"battle_action_aimshoot\", BA_AIMEDSHOT); //TODO: fix name, it require some new logic in script to allow old typo for backward compatiblity\n\tb.addCustomConst(\"battle_action_autoshoot\", BA_AUTOSHOT);\n\tb.addCustomConst(\"battle_action_snapshot\", BA_SNAPSHOT);\n\tb.addCustomConst(\"battle_action_walk\", BA_WALK);\n\tb.addCustomConst(\"battle_action_hit\", BA_HIT);\n\tb.addCustomConst(\"battle_action_throw\", BA_THROW);\n\tb.addCustomConst(\"battle_action_use\", BA_USE);\n\tb.addCustomConst(\"battle_action_mindcontrol\", BA_MINDCONTROL);\n\tb.addCustomConst(\"battle_action_panic\", BA_PANIC);\n\tb.addCustomConst(\"battle_action_cqb\", BA_CQB);\n}\n\nvoid moveTypesImpl(BindBase& b)\n{\n\tb.addCustomConst(\"move_normal\", BAM_NORMAL);\n\tb.addCustomConst(\"move_run\", BAM_RUN);\n\tb.addCustomConst(\"move_strafe\", BAM_STRAFE);\n\tb.addCustomConst(\"move_sneak\", BAM_SNEAK);\n}\n\nvoid medikitBattleActionImpl(BindBase& b)\n{\n\tb.addCustomConst(\"medikit_action_heal\", BMA_HEAL);\n\tb.addCustomConst(\"medikit_action_stimulant\", BMA_STIMULANT);\n\tb.addCustomConst(\"medikit_action_painkiller\", BMA_PAINKILLER);\n}\n\nvoid commonBattleUnitAnimations(ScriptParserBase* parser)\n{\n\tBind<BattleUnit> bu = { parser, BindBase::ExtensionBinding{} };\n\n\tbu.add<&BattleUnit::getFloorAbove>(\"isFloorAbove\", \"check if floor is shown above unit\");\n\tbu.add<&BattleUnit::getBreathExhaleFrame>(\"getBreathExhaleFrame\", \"return animation frame of breath bubbles, -1 means no animation\");\n\tbu.add<&BattleUnit::getBreathInhaleFrame>(\"getBreathInhaleFrame\", \"return number of frames to next breath animation start, 0 means animation started, -1 no animation\");\n\n\tSavedBattleGame::ScriptRegisterUnitAnimations(parser);\n}\n\n\n} // namespace\n\n/**\n * Constructor of recolor script parser.\n */\nModScript::RecolorUnitParser::RecolorUnitParser(ScriptGlobal* shared, const std::string& name, Mod* mod) : ScriptParserEvents{ shared, name,\n\t\"new_pixel\",\n\t\"old_pixel\",\n\n\t\"unit\", \"battle_game\", \"blit_part\", \"anim_frame\", \"shade\", \"burn\" }\n{\n\tBindBase b { this };\n\n\tb.addCustomFunc<burnShadeScript>(\"add_burn_shade\");\n\n\tcommonImpl(b, mod);\n\tcommonBattleUnitAnimations(this);\n\n\tb.addCustomConst(\"blit_item_righthand\", BODYPART_ITEM_RIGHTHAND);\n\tb.addCustomConst(\"blit_item_lefthand\", BODYPART_ITEM_LEFTHAND);\n\tb.addCustomConst(\"blit_item_floor\", BODYPART_ITEM_FLOOR);\n\tb.addCustomConst(\"blit_item_big\", BODYPART_ITEM_INVENTORY);\n\n\tsetDefault(\"unit.getRecolor new_pixel; add_burn_shade new_pixel burn shade; return new_pixel;\");\n}\n\n/**\n * Constructor of select sprite script parser.\n */\nModScript::SelectUnitParser::SelectUnitParser(ScriptGlobal* shared, const std::string& name, Mod* mod) : ScriptParserEvents{ shared, name,\n\t\"sprite_index\",\n\t\"sprite_offset\",\n\n\t\"unit\", \"battle_game\", \"blit_part\", \"anim_frame\", \"shade\" }\n{\n\tBindBase b { this };\n\n\tcommonImpl(b, mod);\n\tcommonBattleUnitAnimations(this);\n\n\tsetDefault(\"add sprite_index sprite_offset; return sprite_index;\");\n}\n\n/**\n * Constructor of select sound script parser.\n */\nModScript::SelectMoveSoundUnitParser::SelectMoveSoundUnitParser(ScriptGlobal* shared, const std::string& name, Mod* mod) : ScriptParserEvents{ shared, name,\n\t\"sound_index\",\n\t\"unit\", \"walking_phase\", \"unit_sound_index\", \"tile_sound_index\",\n\t\"base_tile_sound_index\", \"base_tile_sound_offset\", \"base_fly_sound_index\",\n\t\"move\", }\n{\n\tBindBase b { this };\n\n\tcommonImpl(b, mod);\n\tcommonBattleUnitAnimations(this);\n\n\tmoveTypesImpl(b);\n}\n\n/**\n * Constructor of reaction chance script parser.\n */\nModScript::ReactionUnitParser::ReactionUnitParser(ScriptGlobal* shared, const std::string& name, Mod* mod) : ScriptParserEvents{ shared, name,\n\t\"reaction_chance\",\n\t\"distance\",\n\n\t\"action_unit\",\n\t\"reaction_unit\", \"reaction_weapon\", \"reaction_battle_action\", \"reaction_count\",\n\t\"weapon\", \"skill\", \"battle_action\", \"action_target\",\n\t\"move\", \"arc_to_action_unit\", \"battle_game\" }\n{\n\tBindBase b { this };\n\n\tb.addCustomPtr<const Mod>(\"rules\", mod);\n\n\tbattleActionImpl(b);\n\n\tmoveTypesImpl(b);\n}\n\n/**\n * Constructor of visibility script parser.\n */\nModScript::VisibilityUnitParser::VisibilityUnitParser(ScriptGlobal* shared, const std::string& name, Mod* mod) : ScriptParserEvents{ shared, name,\n\t\"current_visibility\",\n\t\"default_visibility\",\n\t\"visibility_mode\",\n\n\t\"observer_unit\", \"target_unit\", \"target_tile\",\n\t\"distance\", \"distance_max\", \"distance_target_max\",\n\t\"smoke_density\", \"fire_density\",\n\t\"smoke_density_near_observer\", \"fire_density_near_observer\" }\n{\n\tBindBase b { this };\n\n\tb.addCustomPtr<const Mod>(\"rules\", mod);\n}\n\n/**\n * Constructor of visibility script parser.\n */\nModScript::AiCalculateTargetWeightParser::AiCalculateTargetWeightParser(ScriptGlobal* shared, const std::string& name, Mod* mod) : ScriptParserEvents{ shared, name,\n\t\"current_target_weight\",\n\t\"default_target_weight\",\n\n\t\"ai_unit\", \"target_unit\", \"battle_game\" }\n{\n\tBindBase b { this };\n\n\tb.addCustomPtr<const Mod>(\"rules\", mod);\n}\n\n/**\n * Init all required data in script using object data.\n */\nvoid BattleUnit::ScriptFill(ScriptWorkerBlit* w, const BattleUnit* unit, const SavedBattleGame* save, int body_part, int anim_frame, int shade, int burn)\n{\n\tw->clear();\n\tif(unit)\n\t{\n\t\tw->update(unit->getArmor()->getScript<ModScript::RecolorUnitSprite>(), unit, save, body_part, anim_frame, shade, burn);\n\t}\n}\n\nModScript::DamageUnitParser::DamageUnitParser(ScriptGlobal* shared, const std::string& name, Mod* mod) : ScriptParserEvents{ shared, name,\n\t\"to_health\",\n\t\"to_armor\",\n\t\"to_stun\",\n\t\"to_time\",\n\t\"to_energy\",\n\t\"to_morale\",\n\t\"to_wound\",\n\t\"to_transform\",\n\t\"to_mana\",\n\n\t\"unit\", \"damaging_item\", \"weapon_item\", \"attacker\",\n\t\"battle_game\", \"skill\", \"currPower\", \"orig_power\", \"part\", \"side\", \"damaging_type\", \"battle_action\", }\n{\n\tBindBase b { this };\n\n\tb.addCustomPtr<const Mod>(\"rules\", mod);\n\n\tbattleActionImpl(b);\n\n\tsetEmptyReturn();\n}\n\nModScript::DamageSpecialUnitParser::DamageSpecialUnitParser(ScriptGlobal* shared, const std::string& name, Mod* mod) : ScriptParserEvents{ shared, name,\n\t\"transform\",\n\t\"transform_chance\",\n\t\"self_destruct\",\n\t\"self_destruct_chance\",\n\t\"morale_loss\",\n\t\"fire\",\n\t\"attacker_turns_since_spotted\",\n\t\"attacker_turns_left_spotted_for_snipers\",\n\n\t\"unit\", \"damaging_item\", \"weapon_item\", \"attacker\",\n\t\"battle_game\", \"skill\", \"health_damage\", \"orig_power\", \"part\", \"side\", \"damaging_type\", \"battle_action\", }\n{\n\tBindBase b { this };\n\n\tb.addCustomPtr<const Mod>(\"rules\", mod);\n\n\tbattleActionImpl(b);\n\n\tsetEmptyReturn();\n}\n\nModScript::TryPsiAttackUnitParser::TryPsiAttackUnitParser(ScriptGlobal* shared, const std::string& name, Mod* mod) : ScriptParserEvents{ shared, name,\n\t\"psi_attack_success\",\n\n\t\"item\",\n\t\"attacker\",\n\t\"victim\",\n\t\"skill\",\n\t\"attack_strength\",\n\t\"defense_strength\",\n\t\"battle_action\",\n\t\"battle_game\",\n}\n{\n\tBindBase b { this };\n\n\tb.addCustomPtr<const Mod>(\"rules\", mod);\n\n\tbattleActionImpl(b);\n}\n\nModScript::TryMeleeAttackUnitParser::TryMeleeAttackUnitParser(ScriptGlobal* shared, const std::string& name, Mod* mod) : ScriptParserEvents{ shared, name,\n\t\"melee_attack_success\",\n\n\t\"item\",\n\t\"attacker\",\n\t\"victim\",\n\t\"skill\",\n\t\"attack_strength\",\n\t\"defense_strength\",\n\t\"battle_action\",\n\t\"battle_game\",\n}\n{\n\tBindBase b { this };\n\n\tb.addCustomPtr<const Mod>(\"rules\", mod);\n\n\tbattleActionImpl(b);\n}\n\nModScript::HitUnitParser::HitUnitParser(ScriptGlobal* shared, const std::string& name, Mod* mod) : ScriptParserEvents{ shared, name,\n\t\"power\",\n\t\"part\",\n\t\"side\",\n\t\"unit\", \"damaging_item\", \"weapon_item\", \"attacker\",\n\t\"battle_game\", \"skill\", \"orig_power\", \"damaging_type\", \"battle_action\" }\n{\n\tBindBase b { this };\n\n\tb.addCustomPtr<const Mod>(\"rules\", mod);\n\n\tbattleActionImpl(b);\n}\n\nModScript::SkillUseUnitParser::SkillUseUnitParser(ScriptGlobal* shared, const std::string& name, Mod* mod) : ScriptParserEvents { shared, name,\n\t\"continue_action\",\n\t\"spend_tu\",\n\t\"actor\",\n\t\"item\",\n\t\"battle_game\",\n\t\"skill\",\n\t\"battle_action\",\n\t\"have_tu\"\n}\n{\n\tBindBase b { this };\n\n\tb.addCustomPtr<const Mod>(\"rules\", mod);\n\n\tbattleActionImpl(b);\n\n\tsetEmptyReturn();\n}\n\nModScript::HealUnitParser::HealUnitParser(ScriptGlobal* shared, const std::string& name, Mod* mod) : ScriptParserEvents{ shared, name,\n\t\"medikit_action_type\",\n\t\"body_part\",\n\t\"wound_recovery\",\n\t\"health_recovery\",\n\t\"energy_recovery\",\n\t\"stun_recovery\",\n\t\"mana_recovery\",\n\t\"morale_recovery\",\n\t\"painkiller_recovery\",\n\t\"actor\",\n\t\"item\",\n\t\"battle_game\",\n\t\"target\", \"battle_action\"}\n{\n\tBindBase b { this };\n\n\tb.addCustomPtr<const Mod>(\"rules\", mod);\n\n\tbattleActionImpl(b);\n\n\tmedikitBattleActionImpl(b);\n\n\tsetEmptyReturn();\n}\n\nModScript::CreateUnitParser::CreateUnitParser(ScriptGlobal* shared, const std::string& name, Mod* mod) : ScriptParserEvents{ shared, name, \"unit\", \"battle_game\", \"turn\", }\n{\n\tBindBase b { this };\n\n\tb.addCustomPtr<const Mod>(\"rules\", mod);\n\n\tbattleActionImpl(b);\n}\n\nModScript::NewTurnUnitParser::NewTurnUnitParser(ScriptGlobal* shared, const std::string& name, Mod* mod) : ScriptParserEvents{ shared, name, \"unit\", \"battle_game\", \"turn\", \"side\", }\n{\n\tBindBase b { this };\n\n\tb.addCustomPtr<const Mod>(\"rules\", mod);\n}\n\nModScript::ReturnFromMissionUnitParser::ReturnFromMissionUnitParser(ScriptGlobal* shared, const std::string& name, Mod* mod) : ScriptParserEvents{ shared, name,\n\t\"recovery_time\",\n\t\"mana_loss\",\n\t\"health_loss\",\n\t\"final_mana_loss\",\n\t\"final_health_loss\",\n\t\"unit\", \"battle_game\", \"soldier\", \"statChange\", \"statPrevious\" }\n{\n\tBindBase b { this };\n\n\tb.addCustomPtr<const Mod>(\"rules\", mod);\n\n\tsetEmptyReturn();\n}\n\nModScript::AwardExperienceParser::AwardExperienceParser(ScriptGlobal* shared, const std::string& name, Mod* mod) : ScriptParserEvents{ shared, name,\n\t\"experience_multipler\",\n\t\"experience_type\",\n\t\"attacker\", \"unit\", \"weapon\", \"battle_action\", }\n{\n\tBindBase b { this };\n\n\tb.addCustomPtr<const Mod>(\"rules\", mod);\n\n\tbattleActionImpl(b);\n}\n\n\n} //namespace OpenXcom\n"
  },
  {
    "path": "src/Savegame/BattleUnit.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <vector>\n#include <string>\n#include <unordered_set>\n#include \"../Battlescape/Position.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"Soldier.h\"\n#include \"BattleItem.h\"\n\nnamespace OpenXcom\n{\n/**\n * User interface string identifier of body parts.\n */\nconst std::string PARTS_STRING[6] =\n{\n\t\"STR_HEAD\",\n\t\"STR_TORSO\",\n\t\"STR_RIGHT_ARM\",\n\t\"STR_LEFT_ARM\",\n\t\"STR_RIGHT_LEG\",\n\t\"STR_LEFT_LEG\"\n};\n\n\nclass Tile;\nclass BattleItem;\nclass Armor;\nclass Unit;\nclass BattlescapeGame;\nstruct BattleAction;\nstruct BattleActionCost;\nstruct RuleItemUseCost;\nclass SavedBattleGame;\nclass Node;\nclass Surface;\nclass RuleInventory;\nclass RuleEnviroEffects;\nclass RuleStartingCondition;\nclass Soldier;\nclass SavedGame;\nclass Language;\nclass AIModule;\ntemplate<typename, typename...> class ScriptContainer;\ntemplate<typename, typename...> class ScriptParser;\nclass ScriptWorkerBlit;\nstruct BattleUnitStatistics;\nstruct StatAdjustment;\n\n/**\n * Placeholder class for future functionality.\n */\nclass BattleUnitVisibility\n{\npublic:\n\n\t/// Name of class used in script.\n\tstatic constexpr const char *ScriptName = \"BattleUnitVisibility\";\n\t/// Register all useful function used by script.\n\tstatic void ScriptRegister(ScriptParserBase* parser);\n};\n\n/**\n * Represents a moving unit in the battlescape, player controlled or AI controlled\n * it holds info about it's position, items carrying, stats, etc\n */\nclass BattleUnit\n{\nprivate:\n\tstatic const int SPEC_WEAPON_MAX = 4;\n\n\tUnitFaction _faction, _originalFaction;\n\tUnitFaction _killedBy;\n\tUnitFaction _spawnUnitFaction = FACTION_HOSTILE;\n\tint _id;\n\tPosition _pos;\n\tTile *_tile;\n\tPosition _lastPos;\n\tint _direction, _toDirection;\n\tint _directionTurret, _toDirectionTurret;\n\tint _verticalDirection;\n\tPosition _destination;\n\tUnitStatus _status;\n\tbool _wantsToSurrender, _isSurrendering;\n\tint _walkPhase, _fallPhase;\n\tstd::vector<BattleUnit *> _visibleUnits, _unitsSpottedThisTurn;\n\tstd::vector<Tile *> _visibleTiles;\n\tstd::unordered_set<Tile *> _visibleTilesLookup;\n\tint _tu, _energy, _health, _morale, _stunlevel, _mana;\n\tbool _kneeled, _floating, _dontReselect, _aiMedikitUsed;\n\tbool _haveNoFloorBelow = false;\n\tint _currentArmor[SIDE_MAX], _maxArmor[SIDE_MAX];\n\tint _fatalWounds[BODYPART_MAX];\n\tint _fire;\n\tstd::vector<BattleItem*> _inventory;\n\tBattleItem* _specWeapon[SPEC_WEAPON_MAX];\n\tAIModule *_currentAIState;\n\tbool _visible;\n\tUnitStats _exp, _expTmp;\n\tint _motionPoints;\n\tint _scannedTurn;\n\tint _customMarker;\n\tint _kills;\n\tint _faceDirection; // used only during strafing moves\n\tstd::vector<int> _meleeAttackedBy;\n\tbool _hitByFire, _hitByAnything, _alreadyExploded;\n\tint _fireMaxHit;\n\tint _smokeMaxHit;\n\tint _moraleRestored;\n\tint _notificationShown;\n\tBattleUnit *_charging;\n\n\tUint8 _turnsSinceSpotted[FACTION_MAX] = { 255, 255, 255 };\n\tUint8 _turnsLeftSpottedForSnipers[FACTION_MAX] = { 0, 0, 0 };\n\tUint8 _turnsSinceStunned = 255;\n\n\tBattleUnit* _previousOwner = nullptr;\n\tconst Unit *_spawnUnit = nullptr;\n\tstd::string _activeHand;\n\tstd::string _preferredHandForReactions;\n\tbool _reactionsDisabledForLeftHand = false;\n\tbool _reactionsDisabledForRightHand = false;\n\tBattleUnitStatistics* _statistics;\n\tint _murdererId;\t// used to credit the murderer with the kills that this unit got by blowing up on death\n\tint _mindControllerID;\t// used to credit the mind controller with the kills of the mind controllee\n\tUnitSide _fatalShotSide;\n\tUnitBodyPart _fatalShotBodyPart;\n\tstd::string _murdererWeapon, _murdererWeaponAmmo;\n\n\t// static data\n\tstd::string _type;\n\tstd::string _rank;\n\tstd::string _race;\n\tstd::string _name;\n\tUnitStats _stats;\n\tint _standHeight, _kneelHeight, _floatHeight;\n\tint _lastReloadSound;\n\tstd::vector<int> _deathSound, _aggroSound;\n\tstd::vector<int> _selectUnitSound, _startMovingSound, _selectWeaponSound, _annoyedSound;\n\tint _value, _moveSound;\n\tint _intelligence, _aggression;\n\tint _maxViewDistanceAtDark, _maxViewDistanceAtDay;\n\tint _maxViewDistanceAtDarkSquared;\n\tint _psiVision = 0;\n\tint _visibilityThroughSmoke = 0;\n\tint _visibilityThroughFire = 100;\n\tSpecialAbility _specab;\n\tconst Armor *_armor;\n\tSoldierGender _gender;\n\tSoldier *_geoscapeSoldier;\n\tstd::vector<int> _loftempsSet;\n\tconst Unit *_unitRules;\n\tint _rankInt;\n\tint _rankIntUnified = 0;\n\tint _turretType;\n\tint _breathFrame;\n\tbool _breathing;\n\tbool _hidingForTurn, _floorAbove, _respawn, _alreadyRespawned;\n\tbool _isLeeroyJenkins;\t// always charges enemy, never retreats.\n\tbool _summonedPlayerUnit, _resummonedFakeCivilian;\n\tbool _pickUpWeaponsMoreActively;\n\tbool _disableIndicators;\n\tMovementType _movementType;\n\tMovementType _originalMovementType;\n\tArmorMoveCost _moveCostBase = { 0, 0 };\n\tArmorMoveCost _moveCostBaseFly = { 0, 0 };\n\tArmorMoveCost _moveCostBaseClimb = { 0, 0 };\n\tArmorMoveCost _moveCostBaseNormal = { 0, 0 };\n\tstd::vector<std::pair<Uint8, Uint8> > _recolor;\n\tbool _capturable;\n\tbool _vip;\n\tbool _bannedInNextStage;\n\tbool _skillMenuCheck;\n\tScriptValues<BattleUnit> _scriptValues;\n\n\t/// Calculate stat improvement.\n\tint improveStat(int exp) const;\n\t/// Helper function initializing recolor vector.\n\tvoid setRecolor(int basicLook, int utileLook, int rankLook);\n\t/// Helper function preparing Time Units recovery at beginning of turn.\n\tvoid prepareTimeUnits(int tu);\n\t/// Helper function preparing Energy recovery at beginning of turn.\n\tvoid prepareEnergy(int energy);\n\t/// Helper function preparing Health recovery at beginning of turn.\n\tvoid prepareHealth(int helath);\n\t/// Helper function preparing Mana recovery at beginning of turn.\n\tvoid prepareMana(int mana);\n\t/// Helper function preparing Stun recovery at beginning of turn.\n\tvoid prepareStun(int strun);\n\t/// Helper function preparing Morale recovery at beginning of turn.\n\tvoid prepareMorale(int morale);\n\t/// Helper function preparing unit sounds.\n\tvoid prepareUnitSounds();\n\t/// Helper function preparing unit response sounds.\n\tvoid prepareUnitResponseSounds(const Mod *mod);\n\t/// Helper function preparing the banned flag.\n\tvoid prepareBannedFlag(const RuleStartingCondition* sc);\n\t/// Applies percentual and/or flat adjustments to the use costs.\n\tvoid applyPercentages(RuleItemUseCost &cost, const RuleItemUseFlat &flat) const;\npublic:\n\tstatic const int MAX_SOLDIER_ID = 1000000;\n\tstatic const int BUBBLES_FIRST_FRAME = 3;\n\tstatic const int BUBBLES_LAST_FRAME = BUBBLES_FIRST_FRAME + 15;\n\n\t/// Name of class used in script.\n\tstatic constexpr const char *ScriptName = \"BattleUnit\";\n\t/// Register all useful function used by script.\n\tstatic void ScriptRegister(ScriptParserBase* parser);\n\t/// Init all required data in script using object data.\n\tstatic void ScriptFill(ScriptWorkerBlit* w, const BattleUnit* item, const SavedBattleGame* save, int body_part, int anim_frame, int shade, int burn);\n\n\t/// Creates a BattleUnit from solder.\n\tBattleUnit(const Mod *mod, Soldier *soldier, int depth, const RuleStartingCondition* sc);\n\t/// Creates a BattleUnit from unit.\n\tBattleUnit(const Mod *mod, const Unit *unit, UnitFaction faction, int id, const RuleEnviroEffects* enviro, const Armor *armor, StatAdjustment *adjustment, int depth, const RuleStartingCondition* sc);\n\t/// Updates BattleUnit's armor and related attributes (after a change/transformation of armor).\n\tvoid updateArmorFromSoldier(const Mod *mod, Soldier *soldier, const Armor *ruleArmor, int depth, bool nextStage, const RuleStartingCondition* sc);\n\t/// Updates BattleUnit's armor and related attributes (after a change/transformation of armor).\n\tvoid updateArmorFromNonSoldier(const Mod* mod, const Armor* newArmor, int depth, bool nextStage, const RuleStartingCondition* sc);\n\t/// Cleans up the BattleUnit.\n\t~BattleUnit();\n\t/// Loads the unit from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader, const Mod *mod, const ScriptGlobal *shared);\n\t/// Saves the unit to YAML.\n\tvoid save(YAML::YamlNodeWriter writer, const ScriptGlobal *shared) const;\n\t/// Gets the BattleUnit's ID.\n\tint getId() const;\n\t/// Calculates the distance squared between the unit and a given position.\n\tint distance3dToPositionSq(const Position& pos) const;\n\t/// Calculates the distance squared between the unit and a given other unit.\n\tint distance3dToUnitSq(BattleUnit* otherUnit) const;\n\t/// Sets the unit's position\n\tvoid setPosition(Position pos, bool updateLastPos = true);\n\t/// Gets the unit's position.\n\tPosition getPosition() const;\n\t/// Gets the unit's position.\n\tPosition getLastPosition() const;\n\t/// Gets the unit's position of center in voxels.\n\tPosition getPositionVexels() const;\n\t/// Sets the unit's direction 0-7.\n\tvoid setDirection(int direction);\n\t/// Sets the unit's face direction (only used by strafing moves)\n\tvoid setFaceDirection(int direction);\n\t/// Gets the unit's direction.\n\tint getDirection() const;\n\t/// Gets the unit's face direction (only used by strafing moves)\n\tint getFaceDirection() const;\n\t/// Gets the unit's turret direction.\n\tint getTurretDirection() const;\n\t/// Gets the unit's turret To direction.\n\tint getTurretToDirection() const;\n\t/// Gets the unit's vertical direction.\n\tint getVerticalDirection() const;\n\t/// Gets the unit's status.\n\tUnitStatus getStatus() const;\n\t/// Does the unit want to surrender?\n\tbool wantsToSurrender() const;\n\t/// Is the unit surrendering this turn?\n\tbool isSurrendering() const;\n\t/// Mark the unit as surrendering this turn.\n\tvoid setSurrendering(bool isSurrendering);\n\t/// Start the walkingPhase\n\tvoid startWalking(int direction, Position destination, SavedBattleGame *savedBattleGame);\n\t/// Increase the walkingPhase\n\tvoid keepWalking(SavedBattleGame *savedBattleGame, bool fullWalkCycle);\n\t/// Gets the walking phase for animation and sound\n\tint getWalkingPhase() const;\n\t/// Gets the walking phase for diagonal walking\n\tint getDiagonalWalkingPhase() const;\n\t/// Gets the unit's destination when walking\n\tPosition getDestination() const;\n\t/// Look at a certain point.\n\tvoid lookAt(Position point, bool turret = false);\n\t/// Look at a certain direction.\n\tvoid lookAt(int direction, bool force = false);\n\t/// Turn to the destination direction.\n\tvoid turn(bool turret = false);\n\t/// Abort turning.\n\tvoid abortTurn();\n\t/// Gets the soldier's gender.\n\tSoldierGender getGender() const;\n\t/// Gets the unit's faction.\n\tUnitFaction getFaction() const;\n\t/// Gets unit sprite recolors values.\n\tconst std::vector<std::pair<Uint8, Uint8> > &getRecolor() const;\n\t/// Kneel down.\n\tvoid kneel(bool kneeled);\n\t/// Is kneeled?\n\tbool isKneeled() const;\n\t/// Is floating?\n\tbool isFloating() const;\n\t/// Have unit floor below?\n\tbool haveNoFloorBelow() const { return _haveNoFloorBelow; }\n\n\t/// Aim.\n\tvoid aim(bool aiming);\n\t/// Get direction to a certain point\n\tint directionTo(Position point) const;\n\t/// Gets the unit's time units.\n\tint getTimeUnits() const;\n\t/// Gets the unit's stamina.\n\tint getEnergy() const;\n\t/// Gets the unit's health.\n\tint getHealth() const;\n\t/// Gets the unit's mana.\n\tint getMana() const;\n\t/// Gets the unit's bravery.\n\tint getMorale() const;\n\t/// Get overkill damage to unit.\n\tint getOverKillDamage() const;\n\t/// Do damage to the unit.\n\tint damage(Position relative, int power, const RuleDamageType *type, SavedBattleGame *save, BattleActionAttack attack, UnitSide sideOverride = SIDE_MAX, UnitBodyPart bodypartOverride = BODYPART_MAX);\n\t/// Heal stun level of the unit.\n\tvoid healStun(int power);\n\t/// Gets the unit's stun level.\n\tint getStunlevel() const;\n\t/// Is the unit losing HP (due to negative health regeneration)?\n\tbool hasNegativeHealthRegen() const;\n\t/// Knocks the unit out instantly.\n\tvoid knockOut(BattlescapeGame *battle);\n\n\t/// Start falling sequence.\n\tvoid startFalling();\n\t/// Increment the falling sequence.\n\tvoid keepFalling();\n\t/// Set final falling state.\n\tvoid instaFalling();\n\t/// Get falling sequence.\n\tint getFallingPhase() const;\n\n\t/// The unit is out - either dead or unconscious.\n\tbool isOut() const;\n\t/// Check if unit stats will cause knock out.\n\tbool isOutThresholdExceed() const;\n\t/// Unit is removed from game.\n\tbool isIgnored() const;\n\n\t/// Get the number of time units a certain action takes.\n\tRuleItemUseCost getActionTUs(BattleActionType actionType, const BattleItem *item) const;\n\t/// Get the number of time units a certain action takes.\n\tRuleItemUseCost getActionTUs(BattleActionType actionType, const RuleItem *item) const;\n\t/// Get the number of time units a certain skill action takes.\n\tRuleItemUseCost getActionTUs(BattleActionType actionType, const RuleSkill *skillRules) const;\n\t/// Spend time units if it can.\n\tbool spendTimeUnits(int tu);\n\t/// Spend energy if it can.\n\tbool spendEnergy(int energy);\n\t/// Force to spend resources cost without checking.\n\tvoid spendCost(const RuleItemUseCost& cost);\n\t/// Clear time units.\n\tvoid clearTimeUnits();\n\t/// Reset time units and energy.\n\tvoid resetTimeUnitsAndEnergy();\n\t/// Add unit to visible units.\n\tbool addToVisibleUnits(BattleUnit *unit);\n\t/// Remove a unit from the list of visible units.\n\tbool removeFromVisibleUnits(BattleUnit *unit);\n\t/// Is the given unit among this unit's visible units?\n\tbool hasVisibleUnit(const BattleUnit *unit) const;\n\t/// Get the list of visible units.\n\tstd::vector<BattleUnit*> *getVisibleUnits();\n\t/// Clear visible units.\n\tvoid clearVisibleUnits();\n\t/// Add unit to visible tiles.\n\tbool addToVisibleTiles(Tile *tile);\n\t/// Has this unit marked this tile as within its view?\n\tbool hasVisibleTile(Tile *tile) const\n\t{\n\t\treturn _visibleTilesLookup.find(tile) != _visibleTilesLookup.end(); //find?\n\t}\n\t/// Get the list of visible tiles.\n\tconst std::vector<Tile*> *getVisibleTiles();\n\t/// Clear visible tiles.\n\tvoid clearVisibleTiles();\n\t/// Calculate psi attack accuracy.\n\tstatic int getPsiAccuracy(BattleActionAttack::ReadOnly attack);\n\t/// Calculate firing accuracy.\n\tstatic int getFiringAccuracy(BattleActionAttack::ReadOnly attack, const Mod *mod);\n\t/// Calculate accuracy modifier.\n\tint getAccuracyModifier(const BattleItem *item = 0) const;\n\t/// Get the current reaction score.\n\tdouble getReactionScore() const;\n\t/// Prepare for a new turn.\n\tvoid prepareNewTurn(bool fullProcess = true);\n\t/// Calculate change in unit stats.\n\tvoid updateUnitStats(bool tuAndEnergy, bool rest);\n\t/// Morale change\n\tvoid moraleChange(int change);\n\t/// Calculate value of morale change based on bravery.\n\tint reduceByBravery(int moraleChange) const;\n\t/// Calculate power reduction by resistances.\n\tint reduceByResistance(int power, ItemDamageType resistType) const;\n\t/// Don't reselect this unit\n\tvoid dontReselect();\n\t/// Reselect this unit\n\tvoid allowReselect();\n\t/// Check whether reselecting this unit is allowed.\n\tbool reselectAllowed() const;\n\t/// Set fire.\n\tvoid setFire(int fire);\n\t/// Get fire.\n\tint getFire() const;\n\n\t/// Get the list of items in the inventory.\n\tstd::vector<BattleItem*> *getInventory();\n\t/// Get the list of items in the inventory.\n\tconst std::vector<BattleItem*> *getInventory() const;\n\t/// Fit item into inventory slot.\n\tbool fitItemToInventory(const RuleInventory *slot, BattleItem *item);\n\t/// Add item to unit.\n\tbool addItem(BattleItem *item, const Mod *mod, bool allowSecondClip = false, bool allowAutoLoadout = false, bool allowUnloadedWeapons = false);\n\n\t/// Let AI do their thing.\n\tvoid think(BattleAction *action);\n\t/// Get AI Module.\n\tAIModule *getAIModule() const;\n\t/// Set AI Module.\n\tvoid setAIModule(AIModule *ai);\n\t/// Gets weight value as hostile unit.\n\tAIAttackWeight getAITargetWeightAsHostile(const Mod *mod) const;\n\t/// Gets weight value as civilian unit when consider by aliens.\n\tAIAttackWeight getAITargetWeightAsHostileCivilians(const Mod *mod) const;\n\t/// Gets weight value as same faction unit.\n\tAIAttackWeight getAITargetWeightAsFriendly(const Mod *mod) const;\n\t/// Gets weight value as neutral unit (xcom to civ or vice versa).\n\tAIAttackWeight getAITargetWeightAsNeutral(const Mod *mod) const;\n\t/// Set whether this unit is visible\n\tvoid setVisible(bool flag);\n\t/// Get whether this unit is visible\n\tbool getVisible() const;\n\n\n\t/// Check if unit can fall down.\n\tvoid updateTileFloorState(SavedBattleGame *saveBattleGame);\n\t/// Sets the unit's tile it's standing on\n\tvoid setTile(Tile *tile, SavedBattleGame *saveBattleGame = 0);\n\t/// Set only unit tile without any additional logic.\n\tvoid setInventoryTile(Tile *tile);\n\t/// Gets the unit's tile.\n\tTile *getTile() const;\n\n\t/// Gets the unit's creator.\n\tBattleUnit *getPreviousOwner();\n\t/// Gets the unit's creator.\n\tconst BattleUnit *getPreviousOwner() const;\n\t/// Sets the unit's creator.\n\tvoid setPreviousOwner(BattleUnit *owner);\n\n\t/// Gets the item in the specified slot.\n\tBattleItem *getItem(const RuleInventory *slot, int x = 0, int y = 0) const;\n\t/// Gets the item in the main hand.\n\tBattleItem *getMainHandWeapon(bool quickest = true, bool reactions = false) const;\n\t/// Gets a grenade from the belt, if any.\n\tBattleItem *getGrenadeFromBelt(const SavedBattleGame* battle) const;\n\t/// Gets the item from right hand.\n\tBattleItem *getRightHandWeapon() const;\n\t/// Gets the item from left hand.\n\tBattleItem *getLeftHandWeapon() const;\n\t/// Set the right hand as main active hand.\n\tvoid setActiveRightHand();\n\t/// Set the left hand as main active hand.\n\tvoid setActiveLeftHand();\n\t/// Choose what weapon was last use by unit.\n\tconst BattleItem *getActiveHand(const BattleItem *left, const BattleItem *right) const;\n\t/// Reloads a weapon if needed.\n\tbool reloadAmmo();\n\n\t/// Toggle the right hand as main hand for reactions.\n\tvoid toggleRightHandForReactions(bool isCtrl);\n\t/// Toggle the left hand as main hand for reactions.\n\tvoid toggleLeftHandForReactions(bool isCtrl);\n\t/// Is right hand preferred for reactions?\n\tbool isRightHandPreferredForReactions() const;\n\t/// Is left hand preferred for reactions?\n\tbool isLeftHandPreferredForReactions() const;\n\t/// Get preferred weapon for reactions, if applicable.\n\tBattleItem *getWeaponForReactions() const;\n\n\t/// Is right hand disabled for reactions?\n\tbool isRightHandDisabledForReactions() const { return _reactionsDisabledForRightHand; }\n\t/// Is left hand disabled for reactions?\n\tbool isLeftHandDisabledForReactions() const { return _reactionsDisabledForLeftHand; }\n\n\t/// Check if this unit is in the exit area\n\tbool isInExitArea(SpecialTileType stt) const;\n\tbool liesInExitArea(Tile *tile, SpecialTileType stt) const;\n\t/// Gets the unit height taking into account kneeling/standing.\n\tint getHeight() const;\n\t/// Gets the unit floating elevation.\n\tint getFloatHeight() const;\n\t/// Adds one to the bravery exp counter.\n\tvoid addBraveryExp();\n\t/// Adds one to the reaction exp counter.\n\tvoid addReactionExp();\n\t/// Adds one to the firing exp counter.\n\tvoid addFiringExp();\n\t/// Adds one to the throwing exp counter.\n\tvoid addThrowingExp();\n\t/// Adds one to the psi skill exp counter.\n\tvoid addPsiSkillExp();\n\t/// Adds one to the psi strength exp counter.\n\tvoid addPsiStrengthExp();\n\t/// Adds to the mana exp counter.\n\tvoid addManaExp(int weaponStat);\n\t/// Adds one to the melee exp counter.\n\tvoid addMeleeExp();\n\t/// Did the unit gain any experience yet?\n\tbool hasGainedAnyExperience();\n\t/// Updates the stats of a Geoscape soldier.\n\tvoid updateGeoscapeStats(Soldier *soldier) const;\n\t/// Check if unit eligible for squaddie promotion.\n\tbool postMissionProcedures(const Mod *mod, SavedGame *geoscape, SavedBattleGame *battle, StatAdjustment &statsDiff);\n\t/// Get the sprite index for the minimap\n\tint getMiniMapSpriteIndex() const;\n\t/// Set the turret type. -1 is no turret.\n\tvoid setTurretType(int turretType);\n\t/// Get the turret type. -1 is no turret.\n\tint getTurretType() const;\n\n\t/// Set armor value.\n\tvoid setArmor(int armor, UnitSide side);\n\t/// Get armor value.\n\tint getArmor(UnitSide side) const;\n\t/// Set max armor value.\n\tvoid setMaxArmor(int armor, UnitSide side);\n\t/// Get max armor value.\n\tint getMaxArmor(UnitSide side) const;\n\t/// Set fatal wound amount of a body part\n\tvoid setFatalWound(int wound, UnitBodyPart part);\n\t/// Get total number of fatal wounds.\n\tint getFatalWounds() const;\n\t/// Get fatal wound amount of a body part\n\tint getFatalWound(UnitBodyPart part) const;\n\n\t/// Heal one fatal wound\n\tvoid heal(UnitBodyPart part, int woundAmount, int healthAmount);\n\t/// Give pain killers to this unit\n\tvoid painKillers(int moraleAmount, float painKillersStrength);\n\t/// Give stimulant to this unit\n\tvoid stimulant (int energy, int stun, int mana);\n\t/// Get motion points for the motion scanner.\n\tint getMotionPoints() const;\n\t/// Get turn when unit was scanned by the motion scanner.\n\tint getScannedTurn() const { return _scannedTurn; }\n\t/// Set turn when unit was scanned by the motion scanner.\n\tvoid setScannedTurn(int turn) { _scannedTurn = turn; }\n\t/// Get unit custom marker.\n\tint getCustomMarker() const { return _customMarker; }\n\t/// Set unit custom marker.\n\tvoid setCustomMarker(int customMarker) { _customMarker = customMarker; }\n\t/// Gets the unit's armor.\n\tconst Armor *getArmor() const;\n\t/// Sets the unit's name.\n\tvoid setName(const std::string &name);\n\t/// Gets the unit's name.\n\tstd::string getName(Language *lang, bool debugAppendId = false) const;\n\t/// Gets the unit's gained experience points.\n\tconst UnitStats* getExpStats() const { return &_exp; }\n\t/// Gets the unit's stats.\n\tUnitStats *getBaseStats();\n\t/// Gets the unit's stats.\n\tconst UnitStats *getBaseStats() const;\n\t/// Get the unit's stand height.\n\tint getStandHeight() const;\n\t/// Get the unit's kneel height.\n\tint getKneelHeight() const;\n\t/// Get the unit's loft ID.\n\tint getLoftemps(int entry = 0) const;\n\t/// Get the unit's value.\n\tint getValue() const;\n\t/// Get the reload sound (of the last reloaded weapon).\n\tint getReloadSound() const { return _lastReloadSound; }\n\t/// Get the unit's death sounds.\n\tconst std::vector<int> &getDeathSounds() const;\n\t/// Gets the unit's \"select unit\" sounds.\n\tconst std::vector<int> &getSelectUnitSounds() const { return _selectUnitSound; }\n\t/// Gets the unit's \"start moving\" sounds.\n\tconst std::vector<int> &getStartMovingSounds() const { return _startMovingSound; }\n\t/// Gets the unit's \"select weapon\" sounds.\n\tconst std::vector<int> &getSelectWeaponSounds() const { return _selectWeaponSound; }\n\t/// Gets the unit's \"annoyed\" sounds.\n\tconst std::vector<int> &getAnnoyedSounds() const { return _annoyedSound; }\n\t/// Get the unit's move sound.\n\tint getMoveSound() const;\n\n\n\t/// Get whether the unit is affected by fatal wounds.\n\tbool isWoundable() const;\n\t/// Get whether the unit is affected by fear.\n\tbool isFearable() const;\n\t/// Is this unit capable of shooting beyond max. visual range?\n\tbool isSniper() const;\n\t/// Is small unit.\n\tbool isSmallUnit() const;\n\t/// Is big unit.\n\tbool isBigUnit() const;\n\t/// Get the unit's intelligence.\n\tint getIntelligence() const;\n\t/// Get the unit's aggression.\n\tint getAggression() const;\n\t/// Get the units's special ability.\n\tint getSpecialAbility() const;\n\n\t/// Helper method.\n\tint getMaxViewDistance(int baseVisibility, int nerf, int buff) const;\n\t/// Get maximum view distance at dark.\n\tint getMaxViewDistanceAtDark(const BattleUnit* otherUnit) const;\n\t/// Max view distance at dark squared.\n\tint getMaxViewDistanceAtDarkSquared() const;\n\t/// Get maximum view distance at day.\n\tint getMaxViewDistanceAtDay(const BattleUnit* otherUnit) const;\n\t/// Get unit psi vision with bonuses.\n\tint getPsiVision() const { return _psiVision; }\n\t/// Get unit heat vision with bonuses.\n\tint getVisibilityThroughSmoke() const { return _visibilityThroughSmoke; }\n\t/// Get unit visibility through fire with bonuses.\n\tint getVisibilityThroughFire() const { return _visibilityThroughFire; }\n\n\t/// Gets the unit's spawn unit.\n\tconst Unit *getSpawnUnit() const;\n\t/// Sets the unit's spawn unit.\n\tvoid setSpawnUnit(const Unit *spawnUnit);\n\t/// Gets the faction of spawned unit.\n\tUnitFaction getSpawnUnitFaction() const { return _spawnUnitFaction; }\n\t/// Set the faction of spawned unit.\n\tvoid setSpawnUnitFaction(UnitFaction f) { _spawnUnitFaction = f; }\n\t/// Set the units's respawn flag.\n\tvoid setRespawn(bool respawn);\n\t/// Get the units's respawn flag.\n\tbool getRespawn() const;\n\t/// Set the units's alreadyRespawned flag.\n\tvoid setAlreadyRespawned(bool alreadyRespawned);\n\t/// Get the units's alreadyRespawned flag.\n\tbool getAlreadyRespawned() const;\n\t/// Remove all spawn unit info.\n\tvoid clearSpawnUnit();\n\n\t/// Get the units's rank string.\n\tconst std::string& getRankString() const;\n\t/// Get the geoscape-soldier object.\n\tSoldier *getGeoscapeSoldier() const;\n\t/// Add a kill to the counter.\n\tvoid addKillCount();\n\t/// Get unit type.\n\tconst std::string& getType() const;\n\t/// Convert's unit to a faction\n\tvoid convertToFaction(UnitFaction f);\n\t/// Set health to 0\n\tvoid kill();\n\t/// Set health to 0 and set status dead\n\tvoid instaKill();\n\n\t/// Gets whether the unit has any aggro sounds.\n\tbool hasAggroSound() const;\n\t/// Gets a unit's random aggro sound.\n\tint getRandomAggroSound() const;\n\t/// Sets the unit's time units.\n\tvoid setTimeUnits(int tu);\n\t/// Get the faction that killed this unit.\n\tUnitFaction killedBy() const;\n\t/// Set the faction that killed this unit.\n\tvoid killedBy(UnitFaction f);\n\t/// Set the units we are charging towards.\n\tvoid setCharging(BattleUnit *chargeTarget);\n\t/// Get the units we are charging towards.\n\tBattleUnit *getCharging();\n\t/// Get the carried weight in strength units.\n\tint getCarriedWeight(BattleItem *draggingItem = 0) const;\n\n\t/// Set default state on unit.\n\tvoid resetTurnsSince();\n\t/// Update counters on unit.\n\tvoid updateTurnsSince();\n\t/// Set how many turns this unit will be exposed for.\n\tvoid setTurnsSinceSpotted(int turns);\n\t/// Set how many turns this unit will be exposed for. For specific faction.\n\tvoid setTurnsSinceSpottedByFaction(UnitFaction faction, int turns);\n\t/// Set how many turns this unit will be exposed for.\n\tint getTurnsSinceSpotted() const;\n\t/// Set how many turns this unit will be exposed for. For specific faction.\n\tint getTurnsSinceSpottedByFaction(UnitFaction faction) const;\n\t/// Set how many turns left snipers know about this target.\n\tvoid setTurnsLeftSpottedForSnipers (int turns);\n\t/// Set how many turns left snipers know about this target. For specific faction.\n\tvoid setTurnsLeftSpottedForSnipersByFaction (UnitFaction faction, int turns);\n\t/// Get how many turns left snipers know about this target.\n\tint  getTurnsLeftSpottedForSnipers() const;\n\t/// Get how many turns left snipers know about this target. For specific faction.\n\tint  getTurnsLeftSpottedForSnipersByFaction(UnitFaction faction) const;\n\t/// Reset how many turns passed since stunned last time.\n\tvoid resetTurnsSinceStunned() { _turnsSinceStunned = 255; }\n\t/// Increase how many turns passed since stunned last time.\n\tvoid incTurnsSinceStunned() { _turnsSinceStunned = std::min(255, _turnsSinceStunned + 1); }\n\t/// Return how many turns passed since stunned last time.\n\tint getTurnsSinceStunned() const { return _turnsSinceStunned; }\n\n\t/// Get this unit's original faction\n\tUnitFaction getOriginalFaction() const;\n\t/// Get alien/HWP unit.\n\tconst Unit *getUnitRules() const { return _unitRules; }\n\tPosition lastCover;\n\t/// get the vector of units we've seen this turn.\n\tstd::vector<BattleUnit *> &getUnitsSpottedThisTurn();\n\t/// get the vector of units we've seen this turn.\n\tconst std::vector<BattleUnit *> &getUnitsSpottedThisTurn() const;\n\t/// set the rank integer\n\tvoid setRankInt(int rank);\n\t/// get the rank integer\n\tint getRankInt() const;\n\t/// get the rank unified integer\n\tint getRankIntUnified() const { return _rankIntUnified; };\n\t/// derive a rank integer based on rank string (for xcom soldiers ONLY)\n\tvoid deriveSoldierRank();\n\t/// derive a rank integer based on rank string (for Alien)\n\tvoid deriveHostileRank();\n\t/// derive a rank integer based on rank string (for Civilians)\n\tvoid deriveNeutralRank();\n\t/// this function checks if a tile is visible, using maths.\n\tbool checkViewSector(Position pos, bool useTurretDirection = false) const;\n\t/// adjust this unit's stats according to difficulty.\n\tvoid adjustStats(const StatAdjustment &adjustment);\n\t/// did this unit already take fire damage this turn? (used to avoid damaging large units multiple times.)\n\tbool tookFireDamage() const;\n\t/// switch the state of the fire damage tracker.\n\tvoid toggleFireDamage();\n\t/// Is this unit selectable?\n\tbool isSelectable(UnitFaction faction, bool checkReselect, bool checkInventory) const;\n\t/// Does this unit have an inventory?\n\tbool hasInventory() const;\n\n\t/// Is this unit breathing and if so what frame?\n\tint getBreathExhaleFrame() const;\n\t/// Count frames to next start of breath animation.\n\tint getBreathInhaleFrame() const;\n\t/// Start breathing and/or update the breathing frame.\n\tvoid breathe();\n\n\t/// Set the flag for \"floor above me\" meaning stop rendering bubbles.\n\tvoid setFloorAbove(bool floor);\n\t/// Get the flag for \"floor above me\".\n\tbool getFloorAbove() const;\n\t/// Get any utility weapon we may be carrying, or a built in one.\n\tBattleItem *getUtilityWeapon(BattleType type);\n\t/// Set fire damage from environment.\n\tvoid setEnviFire(int damage);\n\t/// Set smoke damage from environment.\n\tvoid setEnviSmoke(int damage);\n\t/// Calculate smoke and fire damage from environment.\n\tvoid calculateEnviDamage(Mod *mod, SavedBattleGame *save);\n\t/// Gets original unit's movement type.\n\tMovementType getOriginalMovementType() const { return _originalMovementType; }\n\t/// Use this function to check the unit's movement type.\n\tMovementType getMovementType() const { return _movementType; }\n\t/// Set unit movement type.\n\tvoid setMovementType(MovementType type) { _movementType = type; }\n\t/// Gets the turn cost.\n\tint getTurnCost() const;\n\t/// Gets cost of standing up from kneeling.\n\tint getKneelUpCost() const { return 8; }\n\t/// Gets cost of kneel down.\n\tint getKneelDownCost() const { return 4; }\n\t/// Gets cost of current transiton form kneeling to standing or reverse.\n\tint getKneelChangeCost() const { return isKneeled() ? getKneelUpCost() : getKneelDownCost(); }\n\n\t/// Create special weapon for unit.\n\tvoid setSpecialWeapon(SavedBattleGame *save, bool updateFromSave);\n\t/// Add/assign a special weapon loaded from a save.\n\tvoid addLoadedSpecialWeapon(BattleItem* item);\n\t/// Remove all special weapons.\n\tvoid removeSpecialWeapons(SavedBattleGame *save);\n\t/// Get special weapon by battle type.\n\tBattleItem *getSpecialWeapon(BattleType type) const;\n\t/// Get special weapon by name.\n\tBattleItem *getSpecialWeapon(const RuleItem *weaponRule) const;\n\t/// Gets special weapon that uses an icon, if any.\n\tBattleItem *getSpecialIconWeapon(BattleType &type) const;\n\n\t/// Checks if this unit is in hiding for a turn.\n\tbool isHiding() const {return _hidingForTurn; };\n\t/// Sets this unit is in hiding for a turn (or not).\n\tvoid setHiding(bool hiding) { _hidingForTurn = hiding; };\n\t/// Puts the unit in the corner to think about what he's done.\n\tvoid goToTimeOut();\n\t/// Recovers the unit's time units and energy.\n\tvoid recoverTimeUnits();\n\t/// Get the unit's mission statistics.\n\tBattleUnitStatistics* getStatistics();\n\t/// Set the unit murderer's id.\n\tvoid setMurdererId(int id);\n\t/// Get the unit murderer's id.\n\tint getMurdererId() const;\n\t/// Set information on the unit's fatal shot.\n\tvoid setFatalShotInfo(UnitSide side, UnitBodyPart bodypart);\n\t/// Get information on the unit's fatal shot's side.\n\tUnitSide getFatalShotSide() const;\n\t/// Get information on the unit's fatal shot's body part.\n\tUnitBodyPart getFatalShotBodyPart() const;\n\t/// Get the unit murderer's weapon.\n\tstd::string getMurdererWeapon() const;\n\t/// Set the unit murderer's weapon.\n\tvoid setMurdererWeapon(const std::string& weapon);\n\t/// Get the unit murderer's weapon's ammo.\n\tstd::string getMurdererWeaponAmmo() const;\n\t/// Set the unit murderer's weapon's ammo.\n\tvoid setMurdererWeaponAmmo(const std::string& weaponAmmo);\n\t/// Set the unit mind controller's id.\n\tvoid setMindControllerId(int id);\n\t/// Get the unit mind controller's id.\n\tint getMindControllerId() const;\n\t/// Get the unit leeroyJenkins flag\n\tbool isLeeroyJenkins() const { return _isLeeroyJenkins; };\n\t/// Gets the spotter score. This is the number of turns sniper AI units can use spotting info from this unit.\n\tint getSpotterDuration() const;\n\t/// Remembers the unit's XP (used for shotguns).\n\tvoid rememberXP();\n\t/// Artificially alter a unit's XP (used for shotguns).\n\tvoid nerfXP();\n\t/// Was this unit just hit?\n\tbool getHitState();\n\t/// reset the unit hit state.\n\tvoid resetHitState();\n\t/// Was this unit melee attacked by a given attacker this turn (both hit and miss count)?\n\tbool wasMeleeAttackedBy(int attackerId) const;\n\t/// Set the \"melee attacked by\" flag.\n\tvoid setMeleeAttackedBy(int attackerId);\n\t/// Did this unit explode already?\n\tbool hasAlreadyExploded() const { return _alreadyExploded; }\n\t/// Set the already exploded flag.\n\tvoid setAlreadyExploded(bool alreadyExploded) { _alreadyExploded = alreadyExploded; }\n\t/// Get the unconscious/dead notification shown flag.\n\tint getNotificationShown() const { return _notificationShown; }\n\t/// Set the unconscious/dead notification shown flag.\n\tvoid setNotificationShown(int notificationShown) { _notificationShown = notificationShown; }\n\t/// Gets whether this unit can be captured alive (applies to aliens).\n\tbool getCapturable() const;\n\t/// free up the patrol node target, to allow others to use it.\n\tvoid freePatrolTarget();\n\t/// Marks this unit as summoned by an item and therefore won't count for recovery or total player units left.\n\tvoid setSummonedPlayerUnit(bool summonedPlayerUnit);\n\t/// Was this unit summoned by an item?\n\tbool isSummonedPlayerUnit() const;\n\t/// Should this unit (player, alien or civilian) be ignored for various things related to soldier diaries and commendations?\n\tbool isCosmetic() const;\n\t/// Should this AI unit (alien or civilian) be ignored by other AI units?\n\tbool isIgnoredByAI() const;\n\t/// Marks this unit as resummoned fake civilian and therefore won't count for civilian scoring in the Debriefing.\n\tvoid markAsResummonedFakeCivilian() { _resummonedFakeCivilian = true; _status = STATUS_IGNORE_ME; }\n\t/// Is this unit a resummoned fake civilian?\n\tbool isResummonedFakeCivilian() const { return _resummonedFakeCivilian; }\n\t/// Marks this unit as VIP.\n\tvoid markAsVIP() { _vip = true; }\n\t/// Is this a VIP unit?\n\tbool isVIP() const { return _vip; }\n\t/// Is this unit banned in the next stage?\n\tbool isBannedInNextStage() const { return _bannedInNextStage; }\n\t/// Is at least one soldier skill usable? (i.e. shown in the skill menu)\n\tbool skillMenuCheck() const { return _skillMenuCheck; }\n\t/// Is the unit eagerly picking up weapons?\n\tbool getPickUpWeaponsMoreActively() const { return _pickUpWeaponsMoreActively; }\n\t/// Is the unit afraid to pathfind through fire?\n\tbool avoidsFire() const;\n\t/// Show indicators for this unit or not?\n\tbool indicatorsAreEnabled() const { return !_disableIndicators; }\n\t/// Disable showing indicators for this unit.\n\tvoid disableIndicators();\n\n\t/// Multiplier of move cost.\n\tArmorMoveCost getMoveCostBase() const { return _moveCostBase; }\n\t/// Multiplier of fly move cost.\n\tArmorMoveCost getMoveCostBaseFly() const { return _moveCostBaseFly; }\n\t/// Multiplier of climb move cost.\n\tArmorMoveCost getMoveCostBaseClimb() const { return _moveCostBaseClimb; }\n\t/// Multiplier of normal move cost.\n\tArmorMoveCost getMoveCostBaseNormal() const { return _moveCostBaseNormal; }\n};\n\n} //namespace OpenXcom\n\n"
  },
  {
    "path": "src/Savegame/BattleUnitStatistics.h",
    "content": "#pragma once\n/*\n* Copyright 2010-2016 OpenXcom Developers.\n*\n* This file is part of OpenXcom.\n*\n* OpenXcom is free software: you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation, either version 3 of the License, or\n* (at your option) any later version.\n*\n* OpenXcom is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*\n* You should have received a copy of the GNU General Public License\n* along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n*/\n#include <string>\n#include <sstream>\n#include \"../Engine/Yaml.h\"\n#include \"BattleUnit.h\"\n#include \"../Engine/Language.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Container for battle unit kills statistics.\n */\nstruct BattleUnitKills\n{\n\t// Variables\n\tstd::string name;\n\tstd::string type, rank, race, weapon, weaponAmmo;\n\tUnitFaction faction;\n\tUnitStatus status;\n\tint mission, turn, id;\n\tUnitSide side;\n\tUnitBodyPart bodypart;\n\n\t// Functions\n\t/// Make turn unique across all kills\n\tint makeTurnUnique()\n\t{\n\t\treturn turn += mission * 300; // Maintains divisibility by 3 as well\n\t}\n\n\t/// Check to see if turn was on HOSTILE side\n\tbool hostileTurn() const\n\t{\n\t\tif ((turn - 1) % 3 == 0) return true;\n\t\treturn false;\n\t}\n\n\t/// Make turn unique across mission\n\tvoid setTurn(int unitTurn, UnitFaction unitFaction)\n\t{\n\t\tturn = unitTurn * 3 + (int)unitFaction;\n\t}\n\n\t/// Load\n\tvoid load(const YAML::YamlNodeReader& reader)\n\t{\n\t\treader.tryRead(\"type\", type); // The ones killed are usually hostiles, so read this first\n\t\tif (type.empty())\n\t\t\treader.tryRead(\"name\", name); // Can't have both type and name at the same time\n\t\treader.tryRead(\"rank\", rank);\n\t\treader.tryRead(\"race\", race);\n\t\treader.tryRead(\"weapon\", weapon);\n\t\treader.tryRead(\"weaponAmmo\", weaponAmmo);\n\t\treader.tryRead(\"status\", status);\n\t\treader.tryRead(\"faction\", faction);\n\t\treader.tryRead(\"mission\", mission);\n\t\treader.tryRead(\"turn\", turn);\n\t\treader.tryRead(\"side\", side);\n\t\treader.tryRead(\"bodypart\", bodypart);\n\t\treader.tryRead(\"id\", id);\n\t}\n\n\t/// Save\n\tvoid save(YAML::YamlNodeWriter writer) const\n\t{\n\t\twriter.setAsMap();\n\t\twriter.setFlowStyle();\n\t\tif (!name.empty())\n\t\t\twriter.write(\"name\", name);\n\t\tif (!type.empty())\n\t\t\twriter.write(\"type\", type);\n\t\twriter.write(\"rank\", rank);\n\t\twriter.write(\"race\", race);\n\t\twriter.write(\"weapon\", weapon);\n\t\twriter.write(\"weaponAmmo\", weaponAmmo);\n\t\twriter.write(\"status\", status);\n\t\twriter.write(\"faction\", faction);\n\t\twriter.write(\"mission\", mission);\n\t\twriter.write(\"turn\", turn);\n\t\twriter.write(\"side\", side);\n\t\twriter.write(\"bodypart\", bodypart);\n\t\twriter.write(\"id\", id);\n\t}\n\n\t/// Convert kill Status to string.\n\tstd::string getKillStatusString() const\n\t{\n\t\tswitch (status)\n\t\t{\n\t\tcase STATUS_DEAD:           return \"STR_KILLED\";\n\t\tcase STATUS_UNCONSCIOUS:    return \"STR_STUNNED\";\n\t\tcase STATUS_PANICKING:\t\treturn \"STR_PANICKED\";\n\t\tcase STATUS_TURNING:\t\treturn \"STR_MINDCONTROLLED\";\n\t\tdefault:                    return \"status error\";\n\t\t}\n\t}\n\n\t/// Convert victim Status to string.\n\tstd::string getUnitStatusString() const\n\t{\n\t\tswitch (status)\n\t\t{\n\t\tcase STATUS_DEAD:           return \"STATUS_DEAD\";\n\t\tcase STATUS_UNCONSCIOUS:    return \"STATUS_UNCONSCIOUS\";\n\t\tcase STATUS_PANICKING:\t\treturn \"STATUS_PANICKING\";\n\t\tcase STATUS_TURNING:\t\treturn \"STATUS_TURNING\";\n\t\tdefault:                    return \"status error\";\n\t\t}\n\t}\n\n\t/// Convert victim Faction to string.\n\tstd::string getUnitFactionString() const\n\t{\n\t\tswitch (faction)\n\t\t{\n\t\tcase FACTION_PLAYER:    return \"FACTION_PLAYER\";\n\t\tcase FACTION_HOSTILE:   return \"FACTION_HOSTILE\";\n\t\tcase FACTION_NEUTRAL:   return \"FACTION_NEUTRAL\";\n\t\tdefault:                return \"faction error\";\n\t\t}\n\t}\n\n\t/// Convert victim Side to string.\n\tstd::string getUnitSideString() const\n\t{\n\t\tswitch (side)\n\t\t{\n\t\tcase SIDE_FRONT:    return \"SIDE_FRONT\";\n\t\tcase SIDE_LEFT:     return \"SIDE_LEFT\";\n\t\tcase SIDE_RIGHT:    return \"SIDE_RIGHT\";\n\t\tcase SIDE_REAR:     return \"SIDE_REAR\";\n\t\tcase SIDE_UNDER:    return \"SIDE_UNDER\";\n\t\tdefault:            return \"side error\";\n\t\t}\n\t}\n\n\t/// Convert victim Body part to string.\n\tstd::string getUnitBodyPartString() const\n\t{\n\t\tswitch (bodypart)\n\t\t{\n\t\tcase BODYPART_HEAD:     return \"BODYPART_HEAD\";\n\t\tcase BODYPART_TORSO:    return \"BODYPART_TORSO\";\n\t\tcase BODYPART_RIGHTARM: return \"BODYPART_RIGHTARM\";\n\t\tcase BODYPART_LEFTARM:  return \"BODYPART_LEFTARM\";\n\t\tcase BODYPART_RIGHTLEG: return \"BODYPART_RIGHTLEG\";\n\t\tcase BODYPART_LEFTLEG:  return \"BODYPART_LEFTLEG\";\n\t\tdefault:                return \"body part error\";\n\t\t}\n\t}\n\n\t/// Get human-readable victim name.\n\tstd::string getUnitName(Language *lang) const\n\t{\n\t\tif (!name.empty())\n\t\t{\n\t\t\treturn name;\n\t\t}\n\t\telse if (!type.empty())\n\t\t{\n\t\t\treturn lang->getString(type);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tstd::ostringstream ss;\n\t\t\tss << lang->getString(race) << \" \" << lang->getString(rank);\n\t\t\treturn ss.str();\n\t\t}\n\t}\n\n\t/// Decide victim name, race and rank.\n\tvoid setUnitStats(BattleUnit *unit)\n\t{\n\t\tname = \"\";\n\t\ttype = \"\";\n\t\tif (unit->getGeoscapeSoldier())\n\t\t{\n\t\t\tname = unit->getGeoscapeSoldier()->getName();\n\t\t}\n\t\telse\n\t\t{\n\t\t\ttype = unit->getType();\n\t\t}\n\n\t\tif (unit->getOriginalFaction() == FACTION_PLAYER)\n\t\t{\n\t\t\t// Soldiers\n\t\t\tif (unit->getGeoscapeSoldier())\n\t\t\t{\n\t\t\t\tif (!unit->getGeoscapeSoldier()->getRankString().empty())\n\t\t\t\t{\n\t\t\t\t\trank = unit->getGeoscapeSoldier()->getRankString();\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\trank = \"STR_SOLDIER\";\n\t\t\t\t}\n\t\t\t\tif (unit->getUnitRules() != 0 && !unit->getUnitRules()->getRace().empty())\n\t\t\t\t{\n\t\t\t\t\trace = unit->getUnitRules()->getRace();\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\trace = \"STR_FRIENDLY\";\n\t\t\t\t}\n\t\t\t}\n\t\t\t// HWPs\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (unit->getUnitRules() != 0 && !unit->getUnitRules()->getRank().empty())\n\t\t\t\t{\n\t\t\t\t\trank = unit->getUnitRules()->getRank();\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\trank = \"STR_HWPS\";\n\t\t\t\t}\n\t\t\t\tif (unit->getUnitRules() != 0 && !unit->getUnitRules()->getRace().empty())\n\t\t\t\t{\n\t\t\t\t\trace = unit->getUnitRules()->getRace();\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\trace = \"STR_FRIENDLY\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// Aliens\n\t\telse if (unit->getOriginalFaction() == FACTION_HOSTILE)\n\t\t{\n\t\t\tif (unit->getUnitRules() != 0 && !unit->getUnitRules()->getRank().empty())\n\t\t\t{\n\t\t\t\trank = unit->getUnitRules()->getRank();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\trank = \"STR_LIVE_SOLDIER\";\n\t\t\t}\n\t\t\tif (unit->getUnitRules() != 0 && !unit->getUnitRules()->getRace().empty())\n\t\t\t{\n\t\t\t\trace = unit->getUnitRules()->getRace();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\trace = \"STR_HOSTILE\";\n\t\t\t}\n\t\t}\n\t\t// Civilians\n\t\telse if (unit->getOriginalFaction() == FACTION_NEUTRAL)\n\t\t{\n\t\t\tif (unit->getUnitRules() != 0 && !unit->getUnitRules()->getRank().empty())\n\t\t\t{\n\t\t\t\trank = unit->getUnitRules()->getRank();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\trank = \"STR_CIVILIAN\";\n\t\t\t}\n\t\t\tif (unit->getUnitRules() != 0 && !unit->getUnitRules()->getRace().empty())\n\t\t\t{\n\t\t\t\trace = unit->getUnitRules()->getRace();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\trace = \"STR_NEUTRAL\";\n\t\t\t}\n\t\t}\n\t\t// Error\n\t\telse\n\t\t{\n\t\t\trank = \"STR_UNKNOWN\";\n\t\t\trace = \"STR_UNKNOWN\";\n\t\t}\n\t}\n\n\tBattleUnitKills(const YAML::YamlNodeReader& reader) { load(reader); }\n\tBattleUnitKills(): faction(FACTION_HOSTILE), status(STATUS_IGNORE_ME), mission(0), turn(0), id(0), side(SIDE_FRONT), bodypart(BODYPART_HEAD) { }\n\t~BattleUnitKills() { }\n};\n\n/**\n * Container for battle unit statistics.\n */\nstruct BattleUnitStatistics\n{\n\t// Variables\n\tbool wasUnconcious;                  ///< Tracks if the soldier fell unconscious\n\tint shotAtCounter;                   ///< Tracks how many times the unit was shot at\n\tint hitCounter;                      ///< Tracks how many times the unit was hit\n\tint shotByFriendlyCounter;           ///< Tracks how many times the unit was hit by a friendly\n\tint shotFriendlyCounter;             ///< Tracks how many times the unit was hit a friendly\n\tbool loneSurvivor;                   ///< Tracks if the soldier was the only survivor\n\tbool ironMan;                        ///< Tracks if the soldier was the only soldier on the mission\n\tint longDistanceHitCounter;          ///< Tracks how many long distance shots were landed\n\tint lowAccuracyHitCounter;           ///< Tracks how many times the unit landed a low probability shot\n\tint shotsFiredCounter;               ///< Tracks how many times a unit has shot\n\tint shotsLandedCounter;              ///< Tracks how many times a unit has hit his target\n\tstd::vector<BattleUnitKills*> kills; ///< Tracks kills\n\tint daysWounded;                     ///< Tracks how many days the unit was wounded for\n\tbool KIA;                            ///< Tracks if the soldier was killed in battle\n\tbool nikeCross;                      ///< Tracks if a soldier killed every alien or killed and stunned every alien\n\tbool mercyCross;                     ///< Tracks if a soldier stunned every alien\n\tint woundsHealed;                    ///< Tracks how many times a fatal wound was healed by this unit\n\tUnitStats delta;                     ///< Tracks the increase in unit stats (is not saved, only used during debriefing)\n\tint appliedStimulant;                ///< Tracks how many times this soldier applied stimulant\n\tint appliedPainKill;                 ///< Tracks how many times this soldier applied pain killers\n\tint revivedSoldier;                  ///< Tracks how many times this soldier revived another soldier\n\tint revivedHostile;                  ///< Tracks how many times this soldier revived another hostile\n\tint revivedNeutral;                  ///< Tracks how many times this soldier revived another civilian\n\tbool MIA;                            ///< Tracks if the soldier was left behind :(\n\tint martyr;                          ///< Tracks how many kills the soldier landed on the turn of his death\n\tint slaveKills;                      ///< Tracks how many kills the soldier landed thanks to a mind controlled unit.\n\n\t// Functions\n\t/// Duplicate entry check\n\tbool duplicateEntry(UnitStatus status, int id) const\n\t{\n\t\tfor (const auto* buk : kills)\n\t\t{\n\t\t\tif (buk->id == id && buk->status == status)\n\t\t\t{\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t/// Friendly fire check\n\tbool hasFriendlyFired() const\n\t{\n\t\tfor (const auto* buk : kills)\n\t\t{\n\t\t\tif (buk->faction == FACTION_PLAYER)\n\t\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\t/// Load function\n\tvoid load(const YAML::YamlNodeReader& node)\n\t{\n\t\tconst auto& reader = node.useIndex();\n\t\treader.tryRead(\"wasUnconcious\", wasUnconcious);\n\t\tfor (const auto& kill : reader[\"kills\"].children())\n\t\t\tkills.push_back(new BattleUnitKills(kill));\n\t\treader.tryRead(\"shotAtCounter\", shotAtCounter);\n\t\treader.tryRead(\"hitCounter\", hitCounter);\n\t\treader.tryRead(\"shotByFriendlyCounter\", shotByFriendlyCounter);\n\t\treader.tryRead(\"shotFriendlyCounter\", shotFriendlyCounter);\n\t\treader.tryRead(\"loneSurvivor\", loneSurvivor);\n\t\treader.tryRead(\"ironMan\", ironMan);\n\t\treader.tryRead(\"longDistanceHitCounter\", longDistanceHitCounter);\n\t\treader.tryRead(\"lowAccuracyHitCounter\", lowAccuracyHitCounter);\n\t\treader.tryRead(\"shotsFiredCounter\", shotsFiredCounter);\n\t\treader.tryRead(\"shotsLandedCounter\", shotsLandedCounter);\n\t\treader.tryRead(\"nikeCross\", nikeCross);\n\t\treader.tryRead(\"mercyCross\", mercyCross);\n\t\treader.tryRead(\"woundsHealed\", woundsHealed);\n\t\treader.tryRead(\"appliedStimulant\", appliedStimulant);\n\t\treader.tryRead(\"appliedPainKill\", appliedPainKill);\n\t\treader.tryRead(\"revivedSoldier\", revivedSoldier);\n\t\treader.tryRead(\"revivedHostile\", revivedHostile);\n\t\treader.tryRead(\"revivedNeutral\", revivedNeutral);\n\t\treader.tryRead(\"martyr\", martyr);\n\t\treader.tryRead(\"slaveKills\", slaveKills);\n\t}\n\n\t/// Save function\n\tvoid save(YAML::YamlNodeWriter writer) const\n\t{\n\t\twriter.setAsMap();\n\t\tif (wasUnconcious) writer.write(\"wasUnconcious\", wasUnconcious);\n\t\twriter.write(\"kills\", kills,\n\t\t\t[](YAML::YamlNodeWriter& w, BattleUnitKills* k)\n\t\t\t{ k->save(w.write()); });\n\t\tif (shotAtCounter) writer.write(\"shotAtCounter\", shotAtCounter);\n\t\tif (hitCounter) writer.write(\"hitCounter\", hitCounter);\n\t\tif (shotByFriendlyCounter) writer.write(\"shotByFriendlyCounter\", shotByFriendlyCounter);\n\t\tif (shotFriendlyCounter) writer.write(\"shotFriendlyCounter\", shotFriendlyCounter);\n\t\tif (loneSurvivor) writer.write(\"loneSurvivor\", loneSurvivor);\n\t\tif (ironMan) writer.write(\"ironMan\", ironMan);\n\t\tif (longDistanceHitCounter) writer.write(\"longDistanceHitCounter\", longDistanceHitCounter);\n\t\tif (lowAccuracyHitCounter) writer.write(\"lowAccuracyHitCounter\", lowAccuracyHitCounter);\n\t\tif (shotsFiredCounter) writer.write(\"shotsFiredCounter\", shotsFiredCounter);\n\t\tif (shotsLandedCounter) writer.write(\"shotsLandedCounter\", shotsLandedCounter);\n\t\tif (nikeCross) writer.write(\"nikeCross\", nikeCross);\n\t\tif (mercyCross) writer.write(\"mercyCross\", mercyCross);\n\t\tif (woundsHealed) writer.write(\"woundsHealed\", woundsHealed);\n\t\tif (appliedStimulant) writer.write(\"appliedStimulant\", appliedStimulant);\n\t\tif (appliedPainKill) writer.write(\"appliedPainKill\", appliedPainKill);\n\t\tif (revivedSoldier) writer.write(\"revivedSoldier\", revivedSoldier);\n\t\tif (revivedHostile) writer.write(\"revivedHostile\", revivedHostile);\n\t\tif (revivedNeutral) writer.write(\"revivedNeutral\", revivedNeutral);\n\t\tif (martyr) writer.write(\"martyr\", martyr);\n\t\tif (slaveKills) writer.write(\"slaveKills\", slaveKills);\n\t\t// for backwards compatibility, we output empty map as null\n\t\tif (!writer.toReader()[0])\n\t\t{\n\t\t\twriter.unsetAsMap();\n\t\t\twriter.setValueNull();\n\t\t}\n\t}\n\n\tBattleUnitStatistics(const YAML::YamlNodeReader& reader) { load(reader); }\n\tBattleUnitStatistics() : wasUnconcious(false), shotAtCounter(0), hitCounter(0), shotByFriendlyCounter(0), shotFriendlyCounter(0), loneSurvivor(false), ironMan(false), longDistanceHitCounter(0), lowAccuracyHitCounter(0), shotsFiredCounter(0), shotsLandedCounter(0), kills(), daysWounded(0), KIA(false), nikeCross(false), mercyCross(false), woundsHealed(0), appliedStimulant(0), appliedPainKill(0), revivedSoldier(0), revivedHostile(0), revivedNeutral(0), MIA(false), martyr(0), slaveKills(0) { }\n\t~BattleUnitStatistics() { }\n};\n\n}\n"
  },
  {
    "path": "src/Savegame/Country.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Country.h\"\n#include \"../Mod/RuleCountry.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/RNG.h\"\n#include \"../Engine/ScriptBind.h\"\n#include \"../Savegame/SavedGame.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes a country of the specified type.\n * @param rules Pointer to ruleset.\n * @param gen Generate new funding.\n */\nCountry::Country(RuleCountry *rules, bool gen) : _rules(rules), _pact(false), _newPact(false), _cancelPact(false), _funding(0), _satisfaction(Satisfaction::SATISFIED)\n{\n\tif (gen)\n\t{\n\t\t_funding.push_back(_rules->generateFunding());\n\t}\n\t_activityAlien.push_back(0);\n\t_activityXcom.push_back(0);\n}\n\n/**\n *\n */\nCountry::~Country()\n{\n}\n\n/**\n * Loads the country from a YAML file.\n * @param node YAML node.\n */\nvoid Country::load(const YAML::YamlNodeReader& reader, const ScriptGlobal* shared)\n{\n\treader.tryRead(\"funding\", _funding);\n\treader.tryRead(\"activityXcom\", _activityXcom);\n\treader.tryRead(\"activityAlien\", _activityAlien);\n\treader.tryRead(\"pact\", _pact);\n\treader.tryRead(\"newPact\", _newPact);\n\treader.tryRead(\"cancelPact\", _cancelPact);\n\n\t_scriptValues.load(reader, shared);\n}\n\n/**\n * Saves the country to a YAML file.\n * @return YAML node.\n */\nvoid Country::save(YAML::YamlNodeWriter writer, const ScriptGlobal* shared) const\n{\n\twriter.setAsMap();\n\twriter.write(\"type\", _rules->getType());\n\twriter.write(\"funding\", _funding);\n\twriter.write(\"activityXcom\", _activityXcom);\n\twriter.write(\"activityAlien\", _activityAlien);\n\tif (_pact)\n\t{\n\t\twriter.write(\"pact\", _pact);\n\t\tif (_cancelPact)\n\t\t\twriter.write(\"cancelPact\", _cancelPact);\n\t}\n\t// Note: can have a _newPact flag, even if already has a _pact from earlier (when xcom liberates and aliens retake a country during the same month)\n\tif (_newPact)\n\t\twriter.write(\"newPact\", _newPact);\n\n\t_scriptValues.save(writer, shared);\n}\n\n/**\n * Returns the ruleset for the country's type.\n * @return Pointer to ruleset.\n */\nconst RuleCountry *Country::getRules() const\n{\n\treturn _rules;\n}\n\n/**\n * Returns the country's current monthly funding.\n * @return Monthly funding.\n */\nstd::vector<int> &Country::getFunding()\n{\n\treturn _funding;\n}\n\n/**\n * Changes the country's current monthly funding.\n * @param funding Monthly funding.\n */\nvoid Country::setFunding(int funding)\n{\n\t_funding.back() = funding;\n}\n\n/*\n * Keith Richards would be so proud\n * @return satisfaction level, 0 = alien pact, 1 = unhappy, 2 = satisfied, 3 = happy.\n */\nCountry::Satisfaction Country::getSatisfaction() const\n{\n\tif (_pact)\n\t\treturn Satisfaction::ALIEN_PACT;\n\treturn _satisfaction;\n}\n\n/**\n * Adds to the country's xcom activity level.\n * @param activity how many points to add.\n */\nvoid Country::addActivityXcom(int activity)\n{\n\t_activityXcom.back() += activity;\n}\n\n/**\n * Adds to the country's alien activity level.\n * @param activity how many points to add.\n */\nvoid Country::addActivityAlien(int activity)\n{\n\t_activityAlien.back() += activity;\n}\n\n/**\n * Gets the country's xcom activity level.\n * @return activity level.\n */\nstd::vector<int> &Country::getActivityXcom()\n{\n\treturn _activityXcom;\n}\n\n/**\n * Gets the country's alien activity level.\n * @return activity level.\n */\nstd::vector<int> &Country::getActivityAlien()\n{\n\treturn _activityAlien;\n}\n\n/**\n * reset all the counters,\n * calculate this month's funding,\n * set the change value for the month.\n * @param xcomTotal the council's xcom score\n * @param alienTotal the council's alien score\n * @param pactScore the penalty for signing a pact\n * @param averageFunding current average funding across all countries (including withdrawn countries)\n */\n\nvoid Country::newMonth(int xcomTotal, int alienTotal, int pactScore, int averageFunding, const SavedGame* save)\n{\n\t// Note: this is a TEMPORARY variable! it's not saved in the save file, i.e. we don't know the value from the previous month!\n\t_satisfaction = Satisfaction::SATISFIED;\n\tconst int funding = getFunding().back();\n\tconst int good = (xcomTotal / 10) + _activityXcom.back();\n\tconst int bad = (alienTotal / 20) + _activityAlien.back();\n\tconst int oldFunding = _funding.back() / 1000;\n\tint newFunding = (oldFunding * RNG::generate(5, 20) / 100) * 1000;\n\tif (newFunding == 0)\n\t{\n\t\tnewFunding = 1000; // increase at least by 1000\n\t}\n\n\tif (bad <= good + 30)\n\t{\n\t\tif (good > bad + 30)\n\t\t{\n\t\t\tif (RNG::generate(0, good) > bad)\n\t\t\t{\n\t\t\t\t// don't go over the cap\n\t\t\t\tint cap = getRules()->getFundingCap()*1000;\n\t\t\t\tif (funding + newFunding > cap)\n\t\t\t\t\tnewFunding = cap - funding;\n\t\t\t\tif (newFunding)\n\t\t\t\t\t_satisfaction = Satisfaction::HAPPY;\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\tif (RNG::generate(0, bad) > good)\n\t\t{\n\t\t\tif (newFunding)\n\t\t\t{\n\t\t\t\tnewFunding = -newFunding;\n\t\t\t\t// don't go below zero\n\t\t\t\tif (funding + newFunding < 0)\n\t\t\t\t\tnewFunding = 0 - funding;\n\t\t\t\tif (newFunding)\n\t\t\t\t\t_satisfaction = Satisfaction::UNHAPPY;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (_satisfaction == Satisfaction::SATISFIED)\n\t{\n\t\tnewFunding = 0;\n\t}\n\tif (_cancelPact)\n\t{\n\t\tif (oldFunding <= 0)\n\t\t{\n\t\t\t_satisfaction = Satisfaction::SATISFIED; // satisfied, not happy or unhappy\n\t\t\tnewFunding = averageFunding;\n\t\t}\n\t}\n\n\t// call script which can adjust values.\n\tModScript::NewMonthCountry::Output args{ newFunding, static_cast<int>(_satisfaction), _newPact, _cancelPact };\n\tModScript::NewMonthCountry::Worker work{ this, save, xcomTotal, alienTotal };\n\twork.execute(_rules->getScript<ModScript::NewMonthCountry>(), args);\n\n\tnewFunding = std::get<0>(args.data);\n\t_satisfaction = static_cast<Satisfaction>(std::get<1>(args.data));\n\t_newPact = static_cast<bool>(std::get<2>(args.data));\n\t_cancelPact = static_cast<bool>(std::get<3>(args.data));\n\n\t// form/cancel pacts\n\tif (_newPact)\n\t{\n\t\t_pact = true;\n\t\taddActivityAlien(pactScore);\n\t}\n\telse if (_cancelPact)\n\t{\n\t\t_pact = false;\n\t}\n\n\t// reset pact change states\n\t_newPact = false;\n\t_cancelPact = false;\n\n\t// set the new funding and reset the activity meters\n\tif (_pact)\n\t\t_funding.push_back(0); // yes, hardcoded!\n\telse\n\t\t_funding.push_back(funding + newFunding);\n\n\t_activityAlien.push_back(0);\n\t_activityXcom.push_back(0);\n\tif (_activityAlien.size() > 12)\n\t\t_activityAlien.erase(_activityAlien.begin());\n\tif (_activityXcom.size() > 12)\n\t\t_activityXcom.erase(_activityXcom.begin());\n\tif (_funding.size() > 12)\n\t\t_funding.erase(_funding.begin());\n}\n\n/**\n * @return if we will sign a new pact.\n */\nbool Country::getNewPact() const\n{\n\treturn _newPact;\n}\n\n/**\n * sign a new pact at month's end.\n */\nvoid Country::setNewPact()\n{\n\t _newPact = true;\n\t _cancelPact = false;\n}\n\n/**\n * @return if we will cancel a pact at month's end.\n */\nbool Country::getCancelPact() const\n{\n\treturn _cancelPact;\n}\n\n/**\n * cancel or prevent a pact.\n */\nvoid Country::setCancelPact()\n{\n\tif (_pact)\n\t{\n\t\t// cancel an existing signed pact\n\t\t_cancelPact = true;\n\t\t_newPact = false;\n\t}\n\telse\n\t{\n\t\t// prevent a not-yet-signed pact\n\t\t_cancelPact = false;\n\t\t_newPact = false;\n\t}\n}\n\n/**\n * no setter for this one, as it gets set automatically\n * at month's end if _newPact is set.\n * @return if we have signed a pact.\n */\nbool Country::getPact() const\n{\n\treturn _pact;\n}\n\n/**\n * sign a new pact.\n */\nvoid Country::setPact()\n{\n\t _pact = true;\n}\n\n/**\n * can be (re)infiltrated?\n */\nbool Country::canBeInfiltrated()\n{\n\tif (!_pact && !_newPact)\n\t{\n\t\t// completely new infiltration; or retaking a previously liberated country\n\t\treturn true;\n\t}\n\tif (_pact && _cancelPact)\n\t{\n\t\t// xcom tried to liberate them this month, but the aliens were not amused... who shall they listen to at the end?\n\t\treturn true;\n\t}\n\treturn false;\n}\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tScript binding\n////////////////////////////////////////////////////////////\n\nnamespace\n{\n\nstd::string debugDisplayScript(const Country* c)\n{\n\tif (c)\n\t{\n\t\tstd::string s;\n\t\ts += Country::ScriptName;\n\t\ts += \"(name: \\\"\";\n\t\ts += c->getRules()->getType();\n\t\ts += \"\\\")\";\n\t\treturn s;\n\t}\n\telse\n\t{\n\t\treturn \"null\";\n\t}\n}\n\n} // namespace\n\nvoid Country::ScriptRegister(ScriptParserBase* parser)\n{\n\tparser->registerPointerType<RuleCountry>();\n\n\tBind<Country> c = { parser };\n\n\tc.addRules<RuleCountry, &Country::getRules>(\"getRuleCountry\");\n\n\tc.add<&Country::getPact>(\"getPact\", \"Get if the country has signed an alien pact or not.\");\n\n\tc.add<&Country::getCurrentFunding>(\"getCurrentFunding\", \"Get the country's current funding.\");\n\tc.add<&Country::getCurrentActivityAlien>(\"getCurrentActivityAlien\", \"Get the country's current alien activity.\");\n\tc.add<&Country::getCurrentActivityXcom>(\"getCurrentActivityXcom\", \"Get the country's current xcom activity.\");\n\n\tc.addScriptValue<&Country::_scriptValues>();\n\tc.addDebugDisplay<&debugDisplayScript>();\n\n\tc.addCustomConst(\"SATISFACTION_ALIENPACT\", 0);\n\tc.addCustomConst(\"SATISFACTION_UNHAPPY\", 1);\n\tc.addCustomConst(\"SATISFACTION_SATISIFIED\", 2);\n\tc.addCustomConst(\"SATISFACTION_HAPPY\", 3);\n}\n\n/**\n * Constructor of new month country script parser.\n * Called every new month for every country.\n */\nModScript::NewMonthCountryParser::NewMonthCountryParser(ScriptGlobal* shared, const std::string& name, Mod* mod) : ScriptParserEvents{ shared, name,\n\t\"fundingChange\", \"satisfaction\", \"formPact\", \"cancelPact\",\n\t\"country\", \"geoscape_game\", \"totalXcomScore\", \"totalAlienScore\" }\n{\n\tBindBase b { this };\n\n\tb.addCustomPtr<const Mod>(\"rules\", mod);\n}\n\n}\n"
  },
  {
    "path": "src/Savegame/Country.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <vector>\n#include \"../Engine/Yaml.h\"\n#include \"../Engine/Script.h\"\n\nnamespace OpenXcom\n{\n\nclass RuleCountry;\nclass SavedGame;\n\n/**\n * Represents a country that funds the player.\n * Contains variable info about a country like\n * monthly funding and various activities.\n */\nclass Country\n{\npublic:\n\tenum class Satisfaction : int { ALIEN_PACT, UNHAPPY, SATISFIED, HAPPY };\n\n\t/// Name of class used in script.\n\tstatic constexpr const char* ScriptName = \"Country\";\n\t/// Register all useful function used by script.\n\tstatic void ScriptRegister(ScriptParserBase* parser);\n\nprivate:\n\tRuleCountry *_rules;\n\tbool _pact, _newPact, _cancelPact;\n\tstd::vector<int> _funding, _activityXcom, _activityAlien;\n\tSatisfaction _satisfaction;\n\tScriptValues<Country> _scriptValues;\n\npublic:\n\t/// Creates a new country of the specified type.\n\tCountry(RuleCountry *rules, bool gen = true);\n\t/// Cleans up the country.\n\t~Country();\n\t/// Loads the country from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader, const ScriptGlobal* shared);\n\t/// Saves the country to YAML.\n\tvoid save(YAML::YamlNodeWriter writer, const ScriptGlobal* shared) const;\n\t/// Gets the country's ruleset.\n\tconst RuleCountry *getRules() const;\n\t/// Gets the country's funding.\n\tstd::vector<int> &getFunding();\n\t/// Sets the country's funding.\n\tvoid setFunding(int funding);\n\t/// get the country's satisfaction level\n\tSatisfaction getSatisfaction() const;\n\t/// add xcom activity in this country\n\tvoid addActivityXcom(int activity);\n\t/// add alien activity in this country\n\tvoid addActivityAlien(int activity);\n\t/// get xcom activity to this country\n\tstd::vector<int> &getActivityXcom();\n\t/// get xcom activity to this country\n\tstd::vector<int> &getActivityAlien();\n\t/// store last month's counters, start new counters, set this month's change.\n\tvoid newMonth(int xcomTotal, int alienTotal, int pactScore, int averageFunding, const SavedGame* save);\n\t/// are we signing a new pact?\n\tbool getNewPact() const;\n\t/// sign a pact at the end of this month.\n\tvoid setNewPact();\n\t/// are we cancelling an existing pact?\n\tbool getCancelPact() const;\n\t/// cancel or prevent a pact.\n\tvoid setCancelPact();\n\t/// have we signed a pact?\n\tbool getPact() const;\n\t/// sign a pact immediately\n\tvoid setPact();\n\t/// can be (re)infiltrated?\n\tbool canBeInfiltrated();\n\nprivate:\n\tint getCurrentFunding() const { return _funding.back(); }\n\tint getCurrentActivityAlien()  const { return _activityAlien.back(); }\n\tint getCurrentActivityXcom() const { return _activityXcom.back(); }\n};\n\n}\n"
  },
  {
    "path": "src/Savegame/Craft.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Craft.h\"\n#include <algorithm>\n#include \"../fmath.h\"\n#include \"../Engine/Language.h\"\n#include \"../Engine/RNG.h\"\n#include \"../Engine/ScriptBind.h\"\n#include \"../Mod/RuleCraft.h\"\n#include \"CraftWeapon.h\"\n#include \"../Mod/RuleCraftWeapon.h\"\n#include \"../Mod/Mod.h\"\n#include \"SavedGame.h\"\n#include \"ItemContainer.h\"\n#include \"Soldier.h\"\n#include \"EquipmentLayoutItem.h\"\n#include \"Transfer.h\"\n#include \"../Mod/RuleSoldier.h\"\n#include \"../Mod/RuleSoldierBonus.h\"\n#include \"Base.h\"\n#include \"Ufo.h\"\n#include \"Waypoint.h\"\n#include \"MissionSite.h\"\n#include \"AlienBase.h\"\n#include \"Vehicle.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"../Mod/RuleStartingCondition.h\"\n#include \"../Mod/AlienDeployment.h\"\n#include \"SerializationHelper.h\"\n#include \"../Engine/Logger.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes a craft of the specified type and\n * assigns it the latest craft ID available.\n * @param rules Pointer to ruleset.\n * @param base Pointer to base of origin.\n * @param id ID to assign to the craft (0 to not assign).\n */\nCraft::Craft(const RuleCraft *rules, Base *base, int id) : MovingTarget(),\n\t_rules(rules), _base(base), _fuel(0), _excessFuel(0), _damage(0), _shield(0),\n\t_interceptionOrder(0), _takeoff(0), _weapons(),\n\t_status(\"STR_READY\"), _lowFuel(false), _mission(false),\n\t_inBattlescape(false), _inDogfight(false), _stats(),\n\t_isAutoPatrolling(false), _lonAuto(0.0), _latAuto(0.0),\n\t_skinIndex(0)\n{\n\t_stats = rules->getStats();\n\t_items = new ItemContainer();\n\t_tempSoldierItems = new ItemContainer();\n\t_tempExtraItems = new ItemContainer();\n\tif (id != 0)\n\t{\n\t\t_id = id;\n\t}\n\tfor (int i = 0; i < _rules->getWeapons(); ++i)\n\t{\n\t\t_weapons.push_back(0);\n\t}\n\tif (base != 0)\n\t{\n\t\tsetBase(base);\n\t}\n\trecalcSpeedMaxRadian();\n}\n\n/**\n * Helper method.\n */\nvoid Craft::recalcSpeedMaxRadian()\n{\n\t_speedMaxRadian = calculateRadianSpeed(_stats.speedMax) * 120;\n}\n\n/**\n * Delete the contents of the craft from memory.\n */\nCraft::~Craft()\n{\n\tfor (auto* cw : _weapons)\n\t{\n\t\tdelete cw;\n\t}\n\tdelete _items;\n\tdelete _tempSoldierItems;\n\tdelete _tempExtraItems;\n\tfor (auto* vehicle : _vehicles)\n\t{\n\t\tdelete vehicle;\n\t}\n}\n\n/**\n * Loads the craft from a YAML file.\n * @param node YAML node.\n * @param mod Mod for the saved game.\n * @param save Pointer to the saved game.\n */\nvoid Craft::load(const YAML::YamlNodeReader& node, const ScriptGlobal *shared, const Mod *mod, SavedGame *save)\n{\n\tconst auto& reader = node.useIndex();\n\tMovingTarget::load(reader);\n\n\treader.tryRead(\"fuel\", _fuel);\n\treader.tryRead(\"excessFuel\", _excessFuel);\n\treader.tryRead(\"damage\", _damage);\n\treader.tryRead(\"shield\", _shield);\n\n\tint j = 0;\n\tfor (const auto& weaponsReader : reader[\"weapons\"].children())\n\t{\n\t\tif (_rules->getWeapons() > j)\n\t\t{\n\t\t\tstd::string type = weaponsReader[\"type\"].readVal<std::string>();\n\t\t\tRuleCraftWeapon* weapon = mod->getCraftWeapon(type);\n\t\t\tif (type != \"0\" && weapon)\n\t\t\t{\n\t\t\t\tCraftWeapon *w = new CraftWeapon(weapon, 0);\n\t\t\t\tw->load(weaponsReader);\n\t\t\t\t_weapons[j] = w;\n\t\t\t\t_stats += weapon->getBonusStats();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_weapons[j] = 0;\n\t\t\t\tif (type != \"0\")\n\t\t\t\t{\n\t\t\t\t\tLog(LOG_ERROR) << \"Failed to load craft weapon \" << type;\n\t\t\t\t}\n\t\t\t}\n\t\t\tj++;\n\t\t}\n\t}\n\n\t_items->load(reader[\"items\"], mod);\n\t// Some old saves have bad items, better get rid of them to avoid further bugs\n\tfor (auto iter = _items->getContents()->begin(); iter != _items->getContents()->end();)\n\t{\n\t\tauto* ruleItem = iter->first;\n\t\tif (!ruleItem->canBeEquippedToCraftInventory())\n\t\t{\n\t\t\tLog(LOG_WARNING) << \"Item '\" << iter->first->getType() << \"' cannot be equipped in the craft inventory (\" << _rules->getType() << \", \" << _id << \"). Skipping \" << iter->second << \" items.\";\n\t\t\tauto old = iter++; // avoid erase in `removeItem`\n\t\t\t_items->removeItem(old->first, old->second);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t++iter;\n\t\t}\n\t}\n\tfor (const auto& vehiclesReader : reader[\"vehicles\"].children())\n\t{\n\t\tstd::string type = vehiclesReader[\"type\"].readVal<std::string>();\n\t\tauto* ruleItem = mod->getItem(type);\n\t\tif (ruleItem)\n\t\t{\n\t\t\tauto* ruleUnit = ruleItem->getVehicleUnit();\n\t\t\tif (ruleUnit)\n\t\t\t{\n\t\t\t\tint size = ruleUnit->getArmor()->getTotalSize();\n\t\t\t\tVehicle *v = new Vehicle(ruleItem, 0, size);\n\t\t\t\tv->load(vehiclesReader);\n\t\t\t\t_vehicles.push_back(v);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tLog(LOG_ERROR) << \"Failed to load vehicle \" << type;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"Failed to load vehicles item \" << type;\n\t\t}\n\t}\n\treader.tryRead(\"status\", _status);\n\treader.tryRead(\"lowFuel\", _lowFuel);\n\treader.tryRead(\"mission\", _mission);\n\treader.tryRead(\"interceptionOrder\", _interceptionOrder);\n\tif (const auto& dest = reader[\"dest\"])\n\t{\n\t\tstd::string type = dest[\"type\"].readVal<std::string>();\n\t\tint id = dest[\"id\"].readVal<int>();\n\t\tif (type == \"STR_BASE\")\n\t\t{\n\t\t\treturnToBase();\n\t\t}\n\t\telse if (type == \"STR_UFO\")\n\t\t{\n\t\t\tfor (auto* ufo : *save->getUfos())\n\t\t\t{\n\t\t\t\tif (ufo->getId() == id)\n\t\t\t\t{\n\t\t\t\t\tsetDestination(ufo);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse if (type == \"STR_WAY_POINT\")\n\t\t{\n\t\t\tfor (auto* wp : *save->getWaypoints())\n\t\t\t{\n\t\t\t\tif (wp->getId() == id)\n\t\t\t\t{\n\t\t\t\t\tsetDestination(wp);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// Backwards compatibility\n\t\t\tif (type == \"STR_ALIEN_TERROR\")\n\t\t\t\ttype = \"STR_TERROR_SITE\";\n\t\t\tbool found = false;\n\t\t\tfor (auto* ms : *save->getMissionSites())\n\t\t\t{\n\t\t\t\tif (found) break; // loop finished\n\t\t\t\tif (ms->getId() == id && ms->getDeployment()->getMarkerName() == type)\n\t\t\t\t{\n\t\t\t\t\tsetDestination(ms);\n\t\t\t\t\tfound = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (auto* ab : *save->getAlienBases())\n\t\t\t{\n\t\t\t\tif (found) break; // loop finished\n\t\t\t\tif (ab->getId() == id && ab->getDeployment()->getMarkerName() == type)\n\t\t\t\t{\n\t\t\t\t\tsetDestination(ab);\n\t\t\t\t\tfound = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treader.tryRead(\"takeoff\", _takeoff);\n\treader.tryRead(\"inBattlescape\", _inBattlescape);\n\treader.tryRead(\"isAutoPatrolling\", _isAutoPatrolling);\n\treader.tryRead(\"lonAuto\", _lonAuto);\n\treader.tryRead(\"latAuto\", _latAuto);\n\treader.tryRead(\"pilots\", _pilots);\n\treader.tryRead(\"customSoldierDeployment\", _customSoldierDeployment);\n\treader.tryRead(\"customVehicleDeployment\", _customVehicleDeployment);\n\treader.tryRead(\"skinIndex\", _skinIndex);\n\tif (_skinIndex > _rules->getMaxSkinIndex())\n\t{\n\t\t_skinIndex = 0;\n\t}\n\tif (_inBattlescape)\n\t\tsetSpeed(0);\n\n\trecalcSpeedMaxRadian();\n\n\t_scriptValues.load(reader, shared);\n}\n\n/**\n * Finishes loading the craft from YAML (called after all other XCOM craft are loaded too).\n * @param node YAML node.\n * @param save The game data. Used to find the UFO's target (= xcom craft).\n */\nvoid Craft::finishLoading(const YAML::YamlNodeReader& reader, SavedGame *save)\n{\n\tif (const auto& dest = reader[\"dest\"])\n\t{\n\t\tstd::string type = dest[\"type\"].readVal<std::string>();\n\t\tint id = dest[\"id\"].readVal<int>();\n\n\t\tbool found = false;\n\t\tfor (auto* xbase : *save->getBases())\n\t\t{\n\t\t\tif (found) break; // loop finished\n\t\t\tfor (auto* xcraft : *xbase->getCrafts())\n\t\t\t{\n\t\t\t\tif (found) break; // loop finished\n\t\t\t\tif (xcraft->getId() == id && xcraft->getRules()->getType() == type)\n\t\t\t\t{\n\t\t\t\t\tsetDestination(xcraft);\n\t\t\t\t\tfound = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Initializes fixed weapons.\n */\nvoid Craft::initFixedWeapons(const Mod* mod)\n{\n\tfor (int i = 0; i < _rules->getWeapons(); ++i)\n\t{\n\t\tif (!_rules->getFixedWeaponInSlot(i).empty())\n\t\t{\n\t\t\tRuleCraftWeapon* rule = mod->getCraftWeapon(_rules->getFixedWeaponInSlot(i), true);\n\t\t\tCraftWeapon* w = new CraftWeapon(rule, 0);\n\t\t\taddCraftStats(w->getRules()->getBonusStats());\n\t\t\t_weapons.at(i) = w;\n\t\t}\n\t}\n\n\t// Remove craft weapons if needed\n\tif (getMaxUnitsRaw() < 0 || getMaxVehiclesAndLargeSoldiersRaw() < 0)\n\t{\n\t\tsize_t weaponIndex = 0;\n\t\tfor (auto* current : _weapons)\n\t\t{\n\t\t\taddCraftStats(-current->getRules()->getBonusStats());\n\t\t\tsetShield(getShield());\n\t\t\tdelete current;\n\t\t\t_weapons.at(weaponIndex) = 0;\n\t\t\tweaponIndex++;\n\t\t}\n\t}\n}\n\n/**\n * Saves the craft to a YAML file.\n * @return YAML node.\n */\nvoid Craft::save(YAML::YamlNodeWriter writer, const ScriptGlobal *shared) const\n{\n\twriter.setAsMap();\n\tMovingTarget::save(writer);\n\twriter.write(\"type\", _rules->getType());\n\twriter.write(\"fuel\", _fuel);\n\tif (_excessFuel != 0)\n\t\twriter.write(\"excessFuel\", _excessFuel);\n\twriter.write(\"damage\", _damage);\n\twriter.write(\"shield\", _shield);\n\twriter.write(\"weapons\", _weapons,\n\t\t[](YAML::YamlNodeWriter& vectorWriter, CraftWeapon* w)\n\t\t{\n\t\t\tauto cwWriter = vectorWriter.write();\n\t\t\tcwWriter.setAsMap();\n\t\t\tif (w)\n\t\t\t\tw->save(cwWriter);\n\t\t\telse\n\t\t\t\tcwWriter.write(\"type\", \"0\");\n\t\t});\n\t_items->save(writer[\"items\"]);\n\twriter.write(\"vehicles\", _vehicles,\n\t\t[](YAML::YamlNodeWriter& vectorWriter, Vehicle* v)\n\t\t{ v->save(vectorWriter.write()); });\n\twriter.write(\"status\", _status);\n\tif (_lowFuel)\n\t\twriter.write(\"lowFuel\", _lowFuel);\n\tif (_mission)\n\t\twriter.write(\"mission\", _mission);\n\tif (_inBattlescape)\n\t\twriter.write(\"inBattlescape\", _inBattlescape);\n\tif (_interceptionOrder != 0)\n\t\twriter.write(\"interceptionOrder\", _interceptionOrder);\n\tif (_takeoff != 0)\n\t\twriter.write(\"takeoff\", _takeoff);\n\tif (_isAutoPatrolling)\n\t\twriter.write(\"isAutoPatrolling\", _isAutoPatrolling);\n\twriter.write(\"lonAuto\", serializeDouble(_lonAuto));\n\twriter.write(\"latAuto\", serializeDouble(_latAuto));\n\tif (_pilots.size())\n\t\twriter.write(\"pilots\", _pilots);\n\tif (!_customSoldierDeployment.empty())\n\t\twriter.write(\"customSoldierDeployment\", _customSoldierDeployment);\n\tif (!_customVehicleDeployment.empty())\n\t\twriter.write(\"customVehicleDeployment\", _customVehicleDeployment);\n\tif (_skinIndex != 0)\n\t\twriter.write(\"skinIndex\", _skinIndex);\n\n\t_scriptValues.save(writer, shared);\n}\n\n/**\n * Loads a craft unique identifier from a YAML file.\n * @param node YAML node.\n * @return Unique craft id.\n */\nCraftId Craft::loadId(const YAML::YamlNodeReader& reader)\n{\n\treturn std::make_pair(reader[\"type\"].readVal<std::string>(), reader[\"id\"].readVal<int>());\n}\n\n/**\n * Returns the craft's unique type used for\n * savegame purposes.\n * @return ID.\n */\nstd::string Craft::getType() const\n{\n\treturn _rules->getType();\n}\n\n/**\n * Returns the ruleset for the craft's type.\n * @return Pointer to ruleset.\n */\nconst RuleCraft *Craft::getRules() const\n{\n\treturn _rules;\n}\n\n/**\n * Changes the ruleset for the craft's type.\n * @param rules Pointer to ruleset.\n * @warning ONLY FOR NEW BATTLE USE!\n */\nvoid Craft::changeRules(RuleCraft *rules)\n{\n\t_rules = rules;\n\t_stats = rules->getStats();\n\t_weapons.clear();\n\tfor (int i = 0; i < _rules->getWeapons(); ++i)\n\t{\n\t\t_weapons.push_back(0);\n\t}\n}\n\n/**\n * Returns the craft's unique default name.\n * @param lang Language to get strings from.\n * @return Full name.\n */\nstd::string Craft::getDefaultName(Language *lang) const\n{\n\treturn lang->getString(\"STR_CRAFTNAME\").arg(lang->getString(getType())).arg(_id);\n}\n\n/**\n * Returns the globe marker for the craft.\n * @return Marker sprite, -1 if none.\n */\nint Craft::getMarker() const\n{\n\tif (_status != \"STR_OUT\")\n\t\treturn -1;\n\telse if (_rules->getMarker() == -1)\n\t\treturn 1;\n\treturn _rules->getMarker();\n}\n\n/**\n * Returns the base the craft belongs to.\n * @return Pointer to base.\n */\nBase *Craft::getBase() const\n{\n\treturn _base;\n}\n\n/**\n * Changes the base the craft belongs to.\n * @param base Pointer to base.\n * @param move Move the craft to the base coordinates.\n */\nvoid Craft::setBase(Base *base, bool move)\n{\n\t_base = base;\n\tif (move)\n\t{\n\t\t_lon = base->getLongitude();\n\t\t_lat = base->getLatitude();\n\t}\n}\n\n/**\n * Returns the current status of the craft.\n * @return Status string.\n */\nstd::string Craft::getStatus() const\n{\n\treturn _status;\n}\n\n/**\n * Changes the current status of the craft.\n * @param status Status string.\n */\nvoid Craft::setStatus(const std::string &status)\n{\n\t_status = status;\n}\n\n/**\n * Returns the current altitude of the craft.\n * @return Altitude.\n */\nstd::string Craft::getAltitude() const\n{\n\tUfo *u = dynamic_cast<Ufo*>(_dest);\n\tif (u && u->getAltitude() != \"STR_GROUND\")\n\t{\n\t\treturn u->getAltitude();\n\t}\n\telse\n\t{\n\t\treturn _rules->getDefaultDisplayAltitude();\n\t}\n}\n\n\n/**\n * Changes the destination the craft is heading to.\n * @param dest Pointer to new destination.\n */\nvoid Craft::setDestination(Target *dest)\n{\n\tif (_status != \"STR_OUT\")\n\t{\n\t\t_takeoff = 60;\n\t}\n\tif (dest == 0)\n\t\tsetSpeed(_stats.speedMax/2);\n\telse\n\t\tsetSpeed(_stats.speedMax);\n\tMovingTarget::setDestination(dest);\n}\n\nbool Craft::getIsAutoPatrolling() const\n{\n\treturn _isAutoPatrolling;\n}\n\nvoid Craft::setIsAutoPatrolling(bool isAuto)\n{\n\t_isAutoPatrolling = isAuto;\n}\n\ndouble Craft::getLongitudeAuto() const\n{\n\treturn _lonAuto;\n}\n\nvoid Craft::setLongitudeAuto(double lon)\n{\n\t_lonAuto = lon;\n}\n\ndouble Craft::getLatitudeAuto() const\n{\n\treturn _latAuto;\n}\n\nvoid Craft::setLatitudeAuto(double lat)\n{\n\t_latAuto = lat;\n}\n\n/**\n * Returns the amount of weapons currently\n * equipped on this craft.\n * @return Number of weapons.\n */\nint Craft::getNumWeapons(bool onlyLoaded) const\n{\n\tif (_rules->getWeapons() == 0)\n\t{\n\t\treturn 0;\n\t}\n\n\tint total = 0;\n\n\tfor (const auto* cw : _weapons)\n\t{\n\t\tif (cw != 0)\n\t\t{\n\t\t\tif (onlyLoaded && !cw->getAmmo())\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\ttotal++;\n\t\t}\n\t}\n\n\treturn total;\n}\n\n/**\n * Returns the amount of equipment currently\n * equipped on this craft.\n * @return Number of items.\n */\nint Craft::getNumEquipment() const\n{\n\treturn _items->getTotalQuantity();\n}\n\n/**\n * Returns the list of weapons currently equipped\n * in the craft.\n * @return Pointer to weapon list.\n */\nstd::vector<CraftWeapon*> *Craft::getWeapons()\n{\n\treturn &_weapons;\n}\n\n/**\n * Returns the list of items in the craft.\n * @return Pointer to the item list.\n */\nItemContainer *Craft::getItems()\n{\n\treturn _items;\n}\n\n/**\n * Returns the list of items in the craft equipped by the soldiers.\n * @return Pointer to the item list.\n */\nItemContainer* Craft::getSoldierItems()\n{\n\treturn _tempSoldierItems;\n}\n\n/**\n * Returns the list of items in the craft not equipped by the soldiers.\n * @return Pointer to the item list.\n */\nItemContainer* Craft::getExtraItems()\n{\n\treturn _tempExtraItems;\n}\n\n/**\n * Returns the list of vehicles currently equipped\n * in the craft.\n * @return Pointer to vehicle list.\n */\nstd::vector<Vehicle*> *Craft::getVehicles()\n{\n\treturn &_vehicles;\n}\n\n/**\n * Calculates (and stores) the sum of all equipment of all soldiers on the craft.\n */\nvoid Craft::calculateTotalSoldierEquipment()\n{\n\t_tempSoldierItems->clear();\n\n\tfor (auto* soldier : *_base->getSoldiers())\n\t{\n\t\tif (soldier->getCraft() == this)\n\t\t{\n\t\t\tfor (auto* invItem : *soldier->getEquipmentLayout())\n\t\t\t{\n\t\t\t\t// ignore fixed weapons...\n\t\t\t\tif (!invItem->isFixed())\n\t\t\t\t{\n\t\t\t\t\t_tempSoldierItems->addItem(invItem->getItemType());\n\t\t\t\t}\n\t\t\t\t// ...but not their ammo\n\t\t\t\tfor (int slot = 0; slot < RuleItem::AmmoSlotMax; ++slot)\n\t\t\t\t{\n\t\t\t\t\tconst auto* invItemAmmo = invItem->getAmmoItemForSlot(slot);\n\t\t\t\t\tif (invItemAmmo != nullptr)\n\t\t\t\t\t{\n\t\t\t\t\t\t_tempSoldierItems->addItem(invItemAmmo);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Gets the total storage size of all items in the craft. Including vehicles+ammo and craft weapons+ammo.\n */\ndouble Craft::getTotalItemStorageSize() const\n{\n\tdouble total = _items->getTotalSize();\n\n\tfor (const auto* v : _vehicles)\n\t{\n\t\ttotal += v->getRules()->getSize();\n\n\t\tauto* clip = v->getRules()->getVehicleClipAmmo();\n\t\tif (clip)\n\t\t{\n\t\t\ttotal += clip->getSize() *  v->getRules()->getVehicleClipsLoaded();\n\t\t}\n\t}\n\n\tfor (const auto* w : _weapons)\n\t{\n\t\tif (w)\n\t\t{\n\t\t\ttotal += w->getRules()->getLauncherItem()->getSize();\n\n\t\t\tauto* clip = w->getRules()->getClipItem();\n\t\t\tif (clip)\n\t\t\t{\n\t\t\t\ttotal += clip->getSize() * w->getClipsLoaded();\n\t\t\t}\n\t\t}\n\t}\n\n\treturn total;\n}\n\n/**\n * Gets the total number of items of a given type in the craft. Including vehicles+ammo and craft weapons+ammo.\n */\nint Craft::getTotalItemCount(const RuleItem* item) const\n{\n\tint qty = _items->getItem(item);\n\n\tfor (const auto* v : _vehicles)\n\t{\n\t\tif (v->getRules() == item)\n\t\t{\n\t\t\tqty += 1;\n\t\t}\n\t\telse if (v->getRules()->getVehicleClipAmmo() == item)\n\t\t{\n\t\t\tqty += v->getRules()->getVehicleClipsLoaded();\n\t\t}\n\t}\n\n\tfor (const auto* w : _weapons)\n\t{\n\t\tif (w)\n\t\t{\n\t\t\tif (w->getRules()->getLauncherItem() == item)\n\t\t\t{\n\t\t\t\tqty += 1;\n\t\t\t}\n\t\t\telse if (w->getRules()->getClipItem() == item)\n\t\t\t{\n\t\t\t\tqty += w->getClipsLoaded();\n\t\t\t}\n\t\t}\n\t}\n\n\treturn qty;\n}\n\n/**\n * Update stats of craft.\n * @param s\n */\nvoid Craft::addCraftStats(const RuleCraftStats& s)\n{\n\tsetDamage(_damage + s.damageMax); //you need \"fix\" new damage capability first before use.\n\t_stats += s;\n\n\tsetFuel(_fuel);\n\n\trecalcSpeedMaxRadian();\n}\n\n/**\n * Gets all basic stats of craft.\n * @return Stats of craft\n */\nconst RuleCraftStats& Craft::getCraftStats() const\n{\n\treturn _stats;\n}\n\n/**\n * Returns current max amount of fuel that craft can carry.\n * @return Max amount of fuel.\n */\nint Craft::getFuelMax() const\n{\n\treturn _stats.fuelMax;\n}\n\n/**\n * Returns the amount of fuel currently contained\n * in this craft.\n * @return Amount of fuel.\n */\nint Craft::getFuel() const\n{\n\treturn _fuel;\n}\n\n/**\n * Changes the amount of fuel currently contained\n * in this craft.\n * @param fuel Amount of fuel.\n */\nvoid Craft::setFuel(int fuel)\n{\n\t_fuel = fuel;\n\tif (_fuel > _stats.fuelMax)\n\t{\n\t\tint overflowFuel = _fuel - _stats.fuelMax + _excessFuel;\n\t\tif (overflowFuel > 0 && _rules->getRefuelItem())\n\t\t{\n\t\t\tint returnQty = overflowFuel / _rules->getRefuelRate();\n\t\t\tif (returnQty > 0)\n\t\t\t{\n\t\t\t\t_base->getStorageItems()->addItem(_rules->getRefuelItem(), returnQty);\n\t\t\t}\n\t\t\t_excessFuel = overflowFuel % _rules->getRefuelRate();\n\t\t}\n\t\t_fuel = _stats.fuelMax;\n\t}\n\telse if (_fuel < 0)\n\t{\n\t\t_fuel = 0;\n\t}\n}\n\n/**\n * Returns the ratio between the amount of fuel currently\n * contained in this craft and the total it can carry.\n * @return Percentage of fuel.\n */\nint Craft::getFuelPercentage() const\n{\n\treturn (int)floor((double)_fuel / _stats.fuelMax * 100.0);\n}\n\n/**\n * Return current max amount of damage this craft can take.\n * @return Max amount of damage.\n */\nint Craft::getDamageMax() const\n{\n\treturn _stats.damageMax;\n}\n\n/**\n * Returns the amount of damage this craft has taken.\n * @return Amount of damage.\n */\nint Craft::getDamage() const\n{\n\treturn _damage;\n}\n\n/**\n * Changes the amount of damage this craft has taken.\n * @param damage Amount of damage.\n */\nvoid Craft::setDamage(int damage)\n{\n\t_damage = damage;\n\tif (_damage < 0)\n\t{\n\t\t_damage = 0;\n\t}\n}\n\n/**\n * Returns the ratio between the amount of damage this\n * craft can take and the total it can take before it's\n * destroyed.\n * @return Percentage of damage.\n */\nint Craft::getDamagePercentage() const\n{\n\treturn (int)floor((double)_damage / _stats.damageMax * 100);\n}\n\n/**\n * Gets the max shield capacity of this craft\n * @return max shield capacity.\n */\nint Craft::getShieldCapacity() const\n{\n\treturn _stats.shieldCapacity;\n}\n\n/**\n * Gets the amount of shield this craft has remaining\n * @return shield points remaining.\n */\nint Craft::getShield() const\n{\n\treturn _shield;\n}\n\n/**\n * Sets the amount of shield for this craft, capped at the capacity plus bonuses\n * @param shield value to set the shield.\n */\nvoid Craft::setShield(int shield)\n{\n\t_shield = std::max(0, std::min(_stats.shieldCapacity, shield));\n}\n\n/**\n * Returns the percentage of shields remaining out of the max capacity\n * @return Percentage of shield\n */\nint Craft::getShieldPercentage() const\n{\n\treturn _stats.shieldCapacity != 0 ? _shield * 100 / _stats.shieldCapacity : 0;\n}\n\n/**\n * Returns whether the craft is ignored by hunter-killers.\n * (is returning from a mission or is low on fuel).\n * @return True if it's ignored, false otherwise.\n */\nbool Craft::isIgnoredByHK() const\n{\n\treturn getMissionComplete() || getLowFuel();\n}\n\n/**\n * Returns whether the craft is currently low on fuel\n * (only has enough to head back to base).\n * @return True if it's low, false otherwise.\n */\nbool Craft::getLowFuel() const\n{\n\treturn _lowFuel;\n}\n\n/**\n * Changes whether the craft is currently low on fuel\n * (only has enough to head back to base).\n * @param low True if it's low, false otherwise.\n */\nvoid Craft::setLowFuel(bool low)\n{\n\t_lowFuel = low;\n}\n\n/**\n * Returns whether the craft has just done a ground mission,\n * and is forced to return to base.\n * @return True if it's returning, false otherwise.\n */\nbool Craft::getMissionComplete() const\n{\n\treturn _mission;\n}\n\n/**\n * Changes whether the craft has just done a ground mission,\n * and is forced to return to base.\n * @param mission True if it's returning, false otherwise.\n */\nvoid Craft::setMissionComplete(bool mission)\n{\n\t_mission = mission;\n}\n\n/**\n * Returns the current distance between the craft\n * and the base it belongs to.\n * @return Distance in radian.\n */\ndouble Craft::getDistanceFromBase() const\n{\n\treturn getDistance(_base);\n}\n\n/**\n * Returns the amount of fuel the craft uses up\n * while it's on the air.\n * @param speed Craft speed for estimation.\n * @return Fuel amount.\n */\nint Craft::getFuelConsumption(int speed, int escortSpeed) const\n{\n\tif (_rules->getRefuelItem())\n\t\treturn 1;\n\tif (escortSpeed > 0)\n\t{\n\t\t// based on the speed of the escorted craft, but capped between 50% and 100% of escorting craft's speed\n\t\treturn std::max(_stats.speedMax / 200, std::min(escortSpeed / 100, _stats.speedMax / 100));\n\t}\n\treturn (int)floor(speed / 100.0);\n}\n\n/**\n * Returns the minimum required fuel for the\n * craft to make it back to base.\n * @return Fuel amount.\n */\nint Craft::getFuelLimit() const\n{\n\treturn getFuelLimit(_base);\n}\n\n/**\n * Returns the minimum required fuel for the\n * craft to go to a base.\n * @param base Pointer to target base.\n * @return Fuel amount.\n */\nint Craft::getFuelLimit(Base *base) const\n{\n\treturn (int)floor(getFuelConsumption(_stats.speedMax, 0) * getDistance(base) / _speedMaxRadian);\n}\n\n/**\n * Gets the maximum number of units (soldiers and vehicles, small and large) that\n * the craft can carry.\n * @return The maximum unit capacity.\n */\nint Craft::getMaxUnitsClamped() const\n{\n\treturn Clamp(_stats.soldiers, 0, _rules->getMaxUnitsLimit());\n}\n\n/**\n * Gets the maximum number of vehicles (and 2x2 soldiers) that\n * the craft can carry.\n * @return The maximum vehicle capacity (incl. 2x2 soldiers).\n */\nint Craft::getMaxVehiclesAndLargeSoldiersClamped() const\n{\n\treturn Clamp(_stats.vehicles, 0, _rules->getMaxVehiclesAndLargeSoldiersLimit());\n}\n\n/**\n * Returns the maximum range the craft can travel\n * from its origin base on its current fuel.\n * @return Range in radians.\n */\ndouble Craft::getBaseRange() const\n{\n\treturn _fuel / 2.0 / getFuelConsumption(_stats.speedMax, 0) * _speedMaxRadian;\n}\n\n/**\n * Sends the craft back to its origin base.\n */\nvoid Craft::returnToBase()\n{\n\tsetDestination(_base);\n}\n\n/**\n * Returns the crew to their base (using transfers).\n */\nvoid Craft::evacuateCrew(const Mod *mod)\n{\n\tfor (auto iter = _base->getSoldiers()->begin(); iter != _base->getSoldiers()->end(); )\n\t{\n\t\tSoldier* soldier = (*iter);\n\t\tif (soldier->getCraft() == this)\n\t\t{\n\t\t\tint survivalChance = isPilot(soldier->getId()) ? mod->getPilotsEmergencyEvacuationSurvivalChance() : mod->getCrewEmergencyEvacuationSurvivalChance();\n\t\t\tif (RNG::percent(survivalChance))\n\t\t\t{\n\t\t\t\t// remove from craft\n\t\t\t\tsoldier->setCraft(0);\n\t\t\t\t// remove from training, but remember to return to training when back in the base\n\t\t\t\t{\n\t\t\t\t\tif (soldier->isInTraining())\n\t\t\t\t\t{\n\t\t\t\t\t\tsoldier->setReturnToTrainingWhenHealed(true);\n\t\t\t\t\t}\n\t\t\t\t\tsoldier->setTraining(false);\n\t\t\t\t}\n\t\t\t\t// transfer to base\n\t\t\t\tTransfer *t = new Transfer(mod->getPersonnelTime());\n\t\t\t\tt->setSoldier(soldier);\n\t\t\t\t_base->getTransfers()->push_back(t);\n\t\t\t\t// next\n\t\t\t\titer = _base->getSoldiers()->erase(iter);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t++iter; // will be killed later\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t++iter; // next\n\t\t}\n\t}\n\tremoveAllPilots(); // just in case\n}\n\n/**\n * Moves the craft to its destination.\n */\nbool Craft::think()\n{\n\tif (_takeoff == 0)\n\t{\n\t\tmove();\n\t}\n\telse\n\t{\n\t\t_takeoff--;\n\t\tresetMeetPoint();\n\t}\n\tif (reachedDestination() && _dest == (Target*)_base)\n\t{\n\t\tsetInterceptionOrder(0); // just to be sure\n\t\tcheckup();\n\t\tsetDestination(0);\n\t\tsetSpeed(0);\n\t\t_lowFuel = false;\n\t\t_mission = false;\n\t\t_takeoff = 0;\n\t\treturn true;\n\t}\n\treturn false;\n}\n\n/**\n * Is the craft about to take off?\n */\nbool Craft::isTakingOff() const\n{\n\treturn _takeoff == 60;\n}\n\n/**\n * Checks the condition of all the craft's systems\n * to define its new status (eg. when arriving at base).\n */\nvoid Craft::checkup()\n{\n\tint available = 0, full = 0;\n\tfor (auto* cw : _weapons)\n\t{\n\t\tif (cw == 0)\n\t\t\tcontinue;\n\t\tavailable++;\n\t\tif (cw->getAmmo() >= cw->getRules()->getAmmoMax() || cw->isDisabled())\n\t\t{\n\t\t\tfull++;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tcw->setRearming(true);\n\t\t}\n\t}\n\n\tif (_damage > 0)\n\t{\n\t\t_status = \"STR_REPAIRS\";\n\t}\n\telse if (available != full)\n\t{\n\t\t_status = \"STR_REARMING\";\n\t}\n\telse if (_fuel < _stats.fuelMax)\n\t{\n\t\t_status = \"STR_REFUELLING\";\n\t}\n\telse\n\t{\n\t\t_status = \"STR_READY\";\n\t}\n}\n\n/**\n * Returns if a certain target is detected by the craft's\n * radar, taking in account the range and chance.\n * @param target Pointer to target to compare.\n * @return True if it's detected, False otherwise.\n */\nUfoDetection Craft::detect(const Ufo *target, const SavedGame *save, bool alreadyTracked) const\n{\n\tint distance = XcomDistance(getDistance(target));\n\n\tint detectionChance = 0;\n\tUfoDetection detectionType = DETECTION_NONE;\n\n\tif (distance < _stats.radarRange)\n\t{\n\t\t// backward compatibility with vanilla\n\t\tif (_stats.radarChance == 100)\n\t\t{\n\t\t\tdetectionType = DETECTION_RADAR;\n\t\t\tdetectionChance = 100;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tdetectionType = DETECTION_RADAR;\n\t\t\tif (alreadyTracked)\n\t\t\t{\n\t\t\t\tdetectionChance = 100;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tdetectionChance = _stats.radarChance * (100 + target->getVisibility()) / 100;\n\t\t\t}\n\t\t}\n\t}\n\n\tModScript::DetectUfoFromCraft::Output args { detectionType, detectionChance, };\n\tModScript::DetectUfoFromCraft::Worker work { target, save, this, distance, alreadyTracked, _stats.radarChance, _stats.radarRange, };\n\n\twork.execute(target->getRules()->getScript<ModScript::DetectUfoFromCraft>(), args);\n\n\treturn RNG::percent(args.getSecond()) ? (UfoDetection)args.getFirst() : DETECTION_NONE;\n}\n\n/**\n * Consumes the craft's fuel every 10 minutes\n * while it's on the air.\n */\nvoid Craft::consumeFuel(int escortSpeed)\n{\n\tif (!_dest && _rules->patrolWithoutFuel())\n\t{\n\t\t// patrol without fuel consumption\n\t\treturn;\n\t}\n\tsetFuel(_fuel - getFuelConsumption(_speed, escortSpeed));\n}\n\n/**\n * Returns how long in hours until the\n * craft is repaired.\n */\nunsigned int Craft::calcRepairTime()\n{\n\tunsigned int repairTime = 0;\n\n\tif (_damage > 0)\n\t{\n\t\trepairTime = (int)ceil((double)_damage / _rules->getRepairRate());\n\t}\n\treturn repairTime;\n}\n\n/**\n * Returns how long in hours until the\n * craft is refuelled (assumes fuel is available).\n */\nunsigned int Craft::calcRefuelTime()\n{\n\tunsigned int refuelTime = 0;\n\n\tint needed = _stats.fuelMax - _fuel;\n\tif (needed > 0)\n\t{\n\t\trefuelTime = (int)ceil((double)(needed) / _rules->getRefuelRate() / 2.0);\n\t}\n\treturn refuelTime;\n}\n\n/**\n * Returns how long in hours until the\n * craft is re-armed (assumes ammo is available).\n */\nunsigned int Craft::calcRearmTime()\n{\n\tunsigned int rearmTime = 0;\n\n\tfor (int idx = 0; idx < _rules->getWeapons(); idx++)\n\t{\n\t\tCraftWeapon *w1 = _weapons.at(idx);\n\t\tif (w1 != 0 && !w1->isDisabled())\n\t\t{\n\t\t\tint needed = w1->getRules()->getAmmoMax() - w1->getAmmo();\n\t\t\tif (needed > 0)\n\t\t\t{\n\t\t\t\trearmTime += (int)ceil((double)(needed) / w1->getRules()->getRearmRate());\n\t\t\t}\n\t\t}\n\t}\n\n\treturn rearmTime;\n}\n\n/**\n * Repairs the craft's damage every hour\n * while it's docked in the base.\n */\nvoid Craft::repair()\n{\n\tsetDamage(_damage - _rules->getRepairRate());\n\tif (_damage <= 0)\n\t{\n\t\t_status = \"STR_REARMING\";\n\t}\n}\n\n/**\n * Refuels the craft every 30 minutes\n * while it's docked in the base.\n * @return The item ID missing for refuelling, or \"\" if none.\n */\nstd::string Craft::refuel()\n{\n\tstd::string fuel;\n\tif (_fuel < _stats.fuelMax)\n\t{\n\t\tconst auto* item = _rules->getRefuelItem();\n\t\tif (item == nullptr)\n\t\t{\n\t\t\tsetFuel(_fuel + _rules->getRefuelRate());\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (_base->getStorageItems()->getItem(item) > 0)\n\t\t\t{\n\t\t\t\t_base->getStorageItems()->removeItem(item);\n\t\t\t\tsetFuel(_fuel + _rules->getRefuelRate());\n\t\t\t\t_lowFuel = false;\n\t\t\t}\n\t\t\telse if (!_lowFuel)\n\t\t\t{\n\t\t\t\tfuel = item->getType();\n\t\t\t\tif (_fuel > 0)\n\t\t\t\t{\n\t\t\t\t\t_status = \"STR_READY\";\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t_lowFuel = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif (_fuel >= _stats.fuelMax)\n\t{\n\t\t_status = \"STR_READY\";\n\t\tfor (const auto* cw : _weapons)\n\t\t{\n\t\t\tif (cw && cw->isRearming())\n\t\t\t{\n\t\t\t\t_status = \"STR_REARMING\";\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\treturn fuel;\n}\n\n/**\n * Rearms the craft's weapons by adding ammo every hour\n * while it's docked in the base.\n * @param mod Pointer to mod.\n * @return The ammo ID missing for rearming, or \"\" if none.\n */\nconst RuleItem* Craft::rearm()\n{\n\tconst RuleItem* ammo = nullptr;\n\tfor (auto iter = _weapons.begin(); ; ++iter)\n\t{\n\t\tif (iter == _weapons.end())\n\t\t{\n\t\t\t_status = \"STR_REFUELLING\";\n\t\t\tbreak;\n\t\t}\n\t\tCraftWeapon* cw = (*iter);\n\t\tif (cw != 0 && cw->isRearming())\n\t\t{\n\t\t\tauto* clip = cw->getRules()->getClipItem();\n\t\t\tint available = _base->getStorageItems()->getItem(clip);\n\t\t\tif (clip == nullptr)\n\t\t\t{\n\t\t\t\tcw->rearm(0, 0);\n\t\t\t}\n\t\t\telse if (available > 0)\n\t\t\t{\n\t\t\t\tint used = cw->rearm(available, clip->getClipSize());\n\n\t\t\t\tif (used == available && cw->isRearming())\n\t\t\t\t{\n\t\t\t\t\tammo = clip;\n\t\t\t\t\tcw->setRearming(false);\n\t\t\t\t}\n\n\t\t\t\t_base->getStorageItems()->removeItem(clip, used);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tammo = clip;\n\t\t\t\tcw->setRearming(false);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn ammo;\n}\n\n/**\n * Returns the craft's battlescape status.\n * @return Is the craft currently in battle?\n */\nbool Craft::isInBattlescape() const\n{\n\treturn _inBattlescape;\n}\n\n/**\n * Changes the craft's battlescape status.\n * @param inbattle True if it's in battle, False otherwise.\n */\nvoid Craft::setInBattlescape(bool inbattle)\n{\n\tif (inbattle)\n\t\tsetSpeed(0);\n\t_inBattlescape = inbattle;\n}\n\n/**\n * Returns the craft destroyed status.\n * If the amount of damage the craft take\n * is more than it's health it will be\n * destroyed.\n * @return Is the craft destroyed?\n */\nbool Craft::isDestroyed() const\n{\n\treturn (_damage >= _stats.damageMax);\n}\n\n/**\n * Returns the amount of space available for\n * soldiers and vehicles.\n * @return Space available.\n */\nint Craft::getSpaceAvailable() const\n{\n\treturn getMaxUnitsClamped() - getSpaceUsed();\n}\n\n/**\n * Returns the amount of space in use by\n * soldiers and vehicles.\n * @return Space used.\n */\nint Craft::getSpaceUsed() const\n{\n\tint vehicleSpaceUsed = 0;\n\tfor (auto* vehicle : _vehicles)\n\t{\n\t\tvehicleSpaceUsed += vehicle->getTotalSize();\n\t}\n\tfor (auto* soldier : *_base->getSoldiers())\n\t{\n\t\tif (soldier->getCraft() == this)\n\t\t{\n\t\t\tvehicleSpaceUsed += soldier->getArmor()->getTotalSize();\n\t\t}\n\t}\n\treturn vehicleSpaceUsed;\n}\n\n/**\n * Checks if the commander is onboard.\n * @return True if the commander is onboard.\n */\nbool Craft::isCommanderOnboard() const\n{\n\tfor (const auto* soldier : *_base->getSoldiers())\n\t{\n\t\tif (soldier->getCraft() == this && soldier->getRank() == RANK_COMMANDER)\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Checks if there are only permitted soldier types onboard.\n * @return True if all soldiers onboard are permitted.\n */\nbool Craft::areOnlyPermittedSoldierTypesOnboard(const RuleStartingCondition* sc) const\n{\n\tfor (const auto* soldier : *_base->getSoldiers())\n\t{\n\t\tif (soldier->getCraft() == this && !sc->isSoldierTypePermitted(soldier->getRules()->getType()))\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n}\n\n/**\n * Checks if there are enough required items onboard.\n * @return True if the craft has enough required items.\n */\nbool Craft::areRequiredItemsOnboard(const std::map<std::string, int>& requiredItems) const\n{\n\tfor (const auto& mapItem : requiredItems)\n\t{\n\t\tif (_items->getItem(mapItem.first) < mapItem.second)\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n}\n\n/**\n * Destroys given required items.\n */\nvoid Craft::destroyRequiredItems(const std::map<std::string, int>& requiredItems)\n{\n\tfor (const auto& mapItem : requiredItems)\n\t{\n\t\t_items->removeItem(mapItem.first, mapItem.second);\n\t}\n}\n\n/**\n * Checks item limits.\n * @return True if there are too many items onboard.\n */\nbool Craft::areTooManyItemsOnboard()\n{\n\tif (_items->getTotalQuantity() > getMaxItemsClamped())\n\t{\n\t\treturn true;\n\t}\n\tif (_items->getTotalSize() > getMaxStorageSpaceClamped() + 0.05)\n\t{\n\t\treturn true;\n\t}\n\treturn false;\n}\n\n/**\n * Checks armor constraints.\n * @return True if there are soldiers wearing banned armor onboard.\n */\nbool Craft::areBannedArmorsOnboard()\n{\n\tif (!_rules->getAllowedArmorGroups().empty())\n\t{\n\t\tauto& allowedArmorGroups = _rules->getAllowedArmorGroups();\n\t\tfor (auto* xsoldier : *_base->getSoldiers())\n\t\t{\n\t\t\tif (xsoldier->getCraft() == this)\n\t\t\t{\n\t\t\t\tif (std::find(allowedArmorGroups.begin(), allowedArmorGroups.end(), xsoldier->getArmor()->getGroup()) == allowedArmorGroups.end())\n\t\t\t\t{\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif (!_rules->getLimitArmorGroups().empty())\n\t{\n\t\tauto& limitArmorGroups = _rules->getLimitArmorGroups();\n\t\tfor (auto& limit : limitArmorGroups)\n\t\t{\n\t\t\tint subTotal = 0;\n\t\t\tfor (const auto* tmpSoldier : *_base->getSoldiers())\n\t\t\t{\n\t\t\t\tif (tmpSoldier->getCraft() == this && tmpSoldier->getArmor()->getGroup() == limit.first)\n\t\t\t\t{\n\t\t\t\t\t++subTotal;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (subTotal > limit.second)\n\t\t\t{\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n* Checks if there are enough pilots onboard.\n* @return True if the craft has enough pilots.\n*/\nbool Craft::arePilotsOnboard(const Mod* mod)\n{\n\tif (_rules->getPilots() == 0)\n\t\treturn true;\n\n\t// refresh the list of pilots (must be performed here, list may be out-of-date!)\n\tconst std::vector<Soldier*> pilots = getPilotList(true, mod);\n\n\treturn (int)(pilots.size()) >= _rules->getPilots();\n}\n\n/**\n* Checks if a pilot is already on the list.\n*/\nbool Craft::isPilot(int pilotId)\n{\n\tif (std::find(_pilots.begin(), _pilots.end(), pilotId) != _pilots.end())\n\t{\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\n/**\n* Adds a pilot to the list.\n*/\nvoid Craft::addPilot(int pilotId)\n{\n\tif (std::find(_pilots.begin(), _pilots.end(), pilotId) == _pilots.end())\n\t{\n\t\t_pilots.push_back(pilotId);\n\t}\n}\n\n/**\n* Removes all pilots from the list.\n*/\nvoid Craft::removeAllPilots()\n{\n\t_pilots.clear();\n}\n\n/**\n* Gets the list of craft pilots.\n* @return List of pilots.\n*/\nconst std::vector<Soldier*> Craft::getPilotList(bool autoAdd, const Mod* mod)\n{\n\tstd::vector<Soldier*> result;\n\n\t// 1. no pilots needed\n\tif (_rules->getPilots() == 0)\n\t\treturn result;\n\n\t{\n\t\t// 2. just enough pilots or pilot candidates onboard (assign them all automatically)\n\t\tint total = 0;\n\t\tfor (auto* soldier : *_base->getSoldiers())\n\t\t{\n\t\t\tif (soldier->getCraft() == this && mod)\n\t\t\t{\n\t\t\t\tsoldier->prepareStatsWithBonuses(mod); // refresh stats for checking pilot requirements\n\t\t\t}\n\t\t\tif (soldier->getCraft() == this && soldier->hasAllPilotingRequirements())\n\t\t\t{\n\t\t\t\tresult.push_back(soldier);\n\t\t\t\ttotal++;\n\t\t\t}\n\t\t}\n\t\tif (total == _rules->getPilots())\n\t\t{\n\t\t\t// nothing more to do\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// 3. mix of manually selected pilots and pilot candidates onboard\n\t\t\tint total2 = 0;\n\t\t\tresult.clear();\n\t\t\t// 3a. first take all available (manually selected) pilots\n\t\t\tfor (int soldierId : _pilots)\n\t\t\t{\n\t\t\t\tfor (auto* soldier : *_base->getSoldiers())\n\t\t\t\t{\n\t\t\t\t\tif (soldier->getCraft() == this && soldier->getId() == soldierId && soldier->hasAllPilotingRequirements())\n\t\t\t\t\t{\n\t\t\t\t\t\tresult.push_back(soldier);\n\t\t\t\t\t\ttotal2++;\n\t\t\t\t\t\tbreak; // pilot found, don't search anymore\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (total2 >= _rules->getPilots())\n\t\t\t\t{\n\t\t\t\t\tbreak; // enough pilots found\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (autoAdd)\n\t\t\t{\n\t\t\t\t// 3b. if not enough manually selected pilots, take some pilot candidates automatically (take from the rear first)\n\t\t\t\tfor (std::vector<Soldier*>::reverse_iterator iter = _base->getSoldiers()->rbegin(); iter != _base->getSoldiers()->rend(); ++iter)\n\t\t\t\t{\n\t\t\t\t\tSoldier* soldier = (*iter);\n\t\t\t\t\tif (soldier->getCraft() == this && !isPilot(soldier->getId()) && soldier->hasAllPilotingRequirements())\n\t\t\t\t\t{\n\t\t\t\t\t\tresult.push_back(soldier);\n\t\t\t\t\t\ttotal2++;\n\t\t\t\t\t}\n\t\t\t\t\tif (total2 >= _rules->getPilots())\n\t\t\t\t\t{\n\t\t\t\t\t\tbreak; // enough pilots found\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// remember the pilots and return\n\tremoveAllPilots();\n\tfor (auto* soldier : result)\n\t{\n\t\taddPilot(soldier->getId());\n\t}\n\treturn result;\n}\n\n/**\n* Calculates the accuracy bonus based on pilot skills.\n* @return Accuracy bonus.\n*/\nint Craft::getPilotAccuracyBonus(const std::vector<Soldier*> &pilots, const Mod *mod) const\n{\n\tif (pilots.empty())\n\t\treturn 0;\n\n\tint firingAccuracy = 0;\n\tfor (const auto* soldier : pilots)\n\t{\n\t\tfiringAccuracy += soldier->getStatsWithSoldierBonusesOnly()->firing;\n\t}\n\tfiringAccuracy = firingAccuracy / pilots.size(); // average firing accuracy of all pilots\n\n\treturn ((firingAccuracy - mod->getPilotAccuracyZeroPoint()) * mod->getPilotAccuracyRange()) / 100;\n}\n\n/**\n* Calculates the dodge bonus based on pilot skills.\n* @return Dodge bonus.\n*/\nint Craft::getPilotDodgeBonus(const std::vector<Soldier*> &pilots, const Mod *mod) const\n{\n\tif (pilots.empty())\n\t\treturn 0;\n\n\tint reactions = 0;\n\tfor (const auto* soldier : pilots)\n\t{\n\t\treactions += soldier->getStatsWithSoldierBonusesOnly()->reactions;\n\t}\n\treactions = reactions / pilots.size(); // average reactions of all pilots\n\n\treturn ((reactions - mod->getPilotReactionsZeroPoint()) * mod->getPilotReactionsRange()) / 100;\n}\n\n/**\n* Calculates the approach speed modifier based on pilot skills.\n* @return Approach speed modifier.\n*/\nint Craft::getPilotApproachSpeedModifier(const std::vector<Soldier*> &pilots, const Mod *mod) const\n{\n\tif (pilots.empty())\n\t\treturn 2; // vanilla\n\n\tint bravery = 0;\n\tfor (const auto* soldier : pilots)\n\t{\n\t\tbravery += soldier->getStatsWithSoldierBonusesOnly()->bravery;\n\t}\n\tbravery = bravery / pilots.size(); // average bravery of all pilots\n\n\tif (bravery >= mod->getPilotBraveryThresholdVeryBold())\n\t{\n\t\treturn 4; // double the speed\n\t}\n\telse if (bravery >= mod->getPilotBraveryThresholdBold())\n\t{\n\t\treturn 3; // 50% speed increase\n\t}\n\telse if (bravery >= mod->getPilotBraveryThresholdNormal())\n\t{\n\t\treturn 2; // normal speed\n\t}\n\telse\n\t{\n\t\treturn 1; // half the speed\n\t}\n}\n\n/**\n * Returns the total amount of vehicles of\n * a certain type stored in the craft.\n * @param vehicle Vehicle type.\n * @return Number of vehicles.\n */\nint Craft::getVehicleCount(const std::string &vehicle) const\n{\n\tint total = 0;\n\tfor (const auto* v : _vehicles)\n\t{\n\t\tif (v->getRules()->getType() == vehicle)\n\t\t{\n\t\t\ttotal++;\n\t\t}\n\t}\n\treturn total;\n}\n\n/**\n * Returns the craft's dogfight status.\n * @return Is the craft ion a dogfight?\n */\nbool Craft::isInDogfight() const\n{\n\treturn _inDogfight;\n}\n\n/**\n * Changes the craft's dogfight status.\n * @param inDogfight True if it's in dogfight, False otherwise.\n */\nvoid Craft::setInDogfight(bool inDogfight)\n{\n\t_inDogfight = inDogfight;\n}\n\n/**\n * Sets interception order (first craft to leave the base gets 1, second 2, etc.).\n * @param order Interception order.\n */\nvoid Craft::setInterceptionOrder(const int order)\n{\n\t_interceptionOrder = order;\n}\n\n/**\n * Gets interception order.\n * @return Interception order.\n */\nint Craft::getInterceptionOrder() const\n{\n\treturn _interceptionOrder;\n}\n\n/**\n * Gets the craft's unique id.\n * @return A tuple of the craft's type and per-type id.\n */\nCraftId Craft::getUniqueId() const\n{\n\treturn std::make_pair(_rules->getType(), _id);\n}\n\n/**\n * Unloads all the craft contents to the base.\n * @param mod Pointer to mod.\n */\nvoid Craft::unload()\n{\n\t// Remove weapons\n\tfor (auto*& cw : _weapons)\n\t{\n\t\tif (cw != 0)\n\t\t{\n\t\t\t_base->getStorageItems()->addItem(cw->getRules()->getLauncherItem());\n\t\t\t_base->getStorageItems()->addItem(cw->getRules()->getClipItem(), cw->getClipsLoaded());\n\t\t\tdelete cw;\n\t\t\tcw = nullptr;\n\t\t}\n\t}\n\n\t// Remove items\n\tfor (const auto& pair : *_items->getContents())\n\t{\n\t\t_base->getStorageItems()->addItem(pair.first, pair.second);\n\t}\n\n\t// Remove vehicles\n\tfor (auto*& vehicle : _vehicles)\n\t{\n\t\t_base->getStorageItems()->addItem(vehicle->getRules());\n\t\tif (vehicle->getRules()->getVehicleClipAmmo())\n\t\t{\n\t\t\t_base->getStorageItems()->addItem(vehicle->getRules()->getVehicleClipAmmo(), vehicle->getRules()->getVehicleClipsLoaded());\n\t\t}\n\t\tdelete vehicle;\n\t\tvehicle = nullptr;\n\t}\n\t_vehicles.clear();\n\n\t// Remove soldiers\n\tfor (auto* soldier : *_base->getSoldiers())\n\t{\n\t\tif (soldier->getCraft() == this)\n\t\t{\n\t\t\tsoldier->setCraft(0);\n\t\t}\n\t}\n}\n\n/**\n * Checks if an item can be reused by the craft and\n * updates its status appropriately.\n * @param item Item ID.\n */\nvoid Craft::reuseItem(const RuleItem* item)\n{\n\t// Note: Craft in-base status hierarchy is repair, rearm, refuel, ready.\n\t// We only want to interrupt processes that are lower in the hierarchy.\n\t// (And we don't want to interrupt any out-of-base status.)\n\n\t// The only states we are willing to interrupt are \"ready\" and \"refuelling\"\n\tif (_status != \"STR_READY\" && _status != \"STR_REFUELLING\")\n\t{\n\t\treturn;\n\t}\n\n\t// Check if it's ammo to reload the craft\n\tfor (auto* cw : _weapons)\n\t{\n\t\tif (cw != 0 && item == cw->getRules()->getClipItem() && cw->getAmmo() < cw->getRules()->getAmmoMax() && !cw->isDisabled())\n\t\t{\n\t\t\tcw->setRearming(true);\n\t\t\t_status = \"STR_REARMING\";\n\t\t}\n\t}\n\n\t// Only consider refuelling if everything else is complete\n\tif (_status != \"STR_READY\")\n\t\treturn;\n\n\t// Check if it's fuel to refuel the craft\n\tif (item == _rules->getRefuelItem() && _fuel < _stats.fuelMax)\n\t\t_status = \"STR_REFUELLING\";\n}\n\n/**\n * Gets the attraction value of the craft for alien hunter-killers.\n * @param huntMode Hunt mode ID.\n * @return Attraction value.\n */\nint Craft::getHunterKillerAttraction(int huntMode) const\n{\n\tint attraction = 0;\n\tif (huntMode == 0)\n\t{\n\t\t// prefer interceptors...\n\t\tif (_rules->getAllowLanding())\n\t\t{\n\t\t\t// craft that can land (i.e. transports) are not attractive\n\t\t\tattraction += 1000000;\n\t\t}\n\t\tif (getMaxUnitsClamped() > 0)\n\t\t{\n\t\t\t// craft with more crew capacity (i.e. transports) are less attractive\n\t\t\tattraction += 500000 + (getMaxUnitsClamped() * 1000);\n\t\t}\n\t\t// faster craft (i.e. interceptors) are more attractive\n\t\tattraction += 100000 - _stats.speedMax;\n\t\t// craft with more damage taken are less attractive\n\t\t// this is just to simplify re-targeting when interceptor is fast enough to disengage\n\t\t// and another identical but healthier interceptor is waiting for its chance\n\t\tattraction += _damage * 100 / _stats.damageMax;\n\t}\n\telse\n\t{\n\t\t// prefer transports...\n\t\tif (!_rules->getAllowLanding())\n\t\t{\n\t\t\t// craft that cannot land (i.e. interceptors) are not attractive\n\t\t\tattraction += 1000000;\n\t\t}\n\t\t// craft with more crew capacity (i.e. transports) are more attractive\n\t\tattraction += 500000 - (getMaxUnitsClamped() * 1000);\n\t\t// faster craft (i.e. interceptors) are less attractive\n\t\tattraction += 100000 + _stats.speedMax;\n\t}\n\n\t// the higher the number the less attractive the target is for UFO hunter-killers\n\treturn attraction;\n}\n\n/**\n * Gets the craft's skin sprite ID.\n * @return Sprite ID.\n */\nint Craft::getSkinSprite() const\n{\n\treturn getRules()->getSprite(_skinIndex);\n}\n\n/**\n * Does this craft have a custom deployment set?\n */\nbool Craft::hasCustomDeployment() const\n{\n\treturn !_customSoldierDeployment.empty() || !_customVehicleDeployment.empty();\n}\n\n/**\n * Resets the craft's custom deployment.\n */\nvoid Craft::resetCustomDeployment()\n{\n\tif (!_customSoldierDeployment.empty())\n\t{\n\t\t_customSoldierDeployment.clear();\n\t}\n\tif (!_customVehicleDeployment.empty())\n\t{\n\t\t_customVehicleDeployment.clear();\n\t}\n}\n\n/**\n * Resets the craft's custom deployment of vehicles temp variables.\n */\nvoid Craft::resetTemporaryCustomVehicleDeploymentFlags()\n{\n\tfor (auto& depl : _customVehicleDeployment)\n\t{\n\t\tdepl.used = false;\n\t}\n}\n\n/**\n * Returns the amount of vehicles and 2x2 soldiers currently contained in this craft.\n * @return Number of vehicles and 2x2 soldiers.\n */\nint Craft::getNumVehiclesAndLargeSoldiers() const\n{\n\treturn getNumTotalVehicles() + getNumLargeSoldiers();\n}\n\n/**\n * Returns the amount of 1x1 soldiers from a list that are currently attached to this craft.\n * @return Number of 1x1 soldiers.\n */\nint Craft::getNumSmallSoldiers() const\n{\n\tif (_rules->getMaxUnitsLimit() == 0)\n\t\treturn 0;\n\n\tint total = 0;\n\n\tfor (const auto* s : *_base->getSoldiers())\n\t{\n\t\tif (s->getCraft() == this && s->getArmor()->getSize() == 1)\n\t\t\t++total;\n\t}\n\n\treturn total;\n}\n\n/**\n * Returns the amount of 2x2 soldiers from a list that are currently attached to this craft.\n * @return Number of 2x2 soldiers.\n */\nint Craft::getNumLargeSoldiers() const\n{\n\tif (_rules->getMaxUnitsLimit() == 0)\n\t\treturn 0;\n\n\tint total = 0;\n\n\tfor (const auto* s : *_base->getSoldiers())\n\t{\n\t\tif (s->getCraft() == this && s->getArmor()->getSize() == 2)\n\t\t\t++total;\n\t}\n\n\treturn total;\n}\n\n/**\n * Returns the amount of 1x1 vehicles from a list that are currently attached to this craft.\n * @return Number of 1x1 vehicles.\n */\nint Craft::getNumSmallVehicles() const\n{\n\tif (_rules->getMaxUnitsLimit() == 0)\n\t\treturn 0;\n\n\tint total = 0;\n\n\tfor (const auto* v : _vehicles)\n\t{\n\t\tif (v->getTotalSize() == 1)\n\t\t\t++total;\n\t}\n\n\treturn total;\n}\n\n/**\n * Returns the amount of 2x2 vehicles from a list that are currently attached to this craft.\n * @return Number of 2x2 vehicles.\n */\nint Craft::getNumLargeVehicles() const\n{\n\tif (_rules->getMaxUnitsLimit() == 0)\n\t\treturn 0;\n\n\tint total = 0;\n\n\tfor (const auto* v : _vehicles)\n\t{\n\t\tif (v->getTotalSize() > 1)\n\t\t\t++total;\n\t}\n\n\treturn total;\n}\n\n/**\n * Returns the amount of 1x1 units from a list that are currently attached to this craft.\n * @return Number of 1x1 units.\n */\nint Craft::getNumSmallUnits() const\n{\n\treturn getNumSmallSoldiers() + getNumSmallVehicles();\n}\n\n/**\n * Returns the amount of 2x2 units from a list that are currently attached to this craft.\n * @return Number of 2x2 units.\n */\nint Craft::getNumLargeUnits() const\n{\n\treturn getNumLargeSoldiers() + getNumLargeVehicles();\n}\n\n/**\n * Returns the total amount of soldiers from a list that are currently attached to this craft.\n * @return Number of soldiers.\n */\nint Craft::getNumTotalSoldiers() const\n{\n\tif (_rules->getMaxUnitsLimit() == 0)\n\t\treturn 0;\n\n\tint total = 0;\n\n\tfor (const auto* s : *_base->getSoldiers())\n\t{\n\t\tif (s->getCraft() == this)\n\t\t\t++total;\n\t}\n\n\treturn total;\n}\n\n/**\n * Returns the total amount of vehicles from a list that are currently attached to this craft.\n * @return Number of vehicles.\n */\nint Craft::getNumTotalVehicles() const\n{\n\treturn _vehicles.size();\n}\n\n/**\n * Returns the total amount of units from a list that are currently attached to this craft.\n * @return Number of units.\n */\nint Craft::getNumTotalUnits() const\n{\n\treturn getNumTotalSoldiers() + getNumTotalVehicles();\n}\n\n/**\n * Validates craft space and craft constraints on soldier armor change.\n * @return True, if armor change is allowed.\n */\nbool Craft::validateArmorChange(int sizeFrom, int sizeTo) const\n{\n\tif (sizeFrom == sizeTo)\n\t{\n\t\treturn true;\n\t}\n\telse\n\t{\n\t\tif (sizeFrom < sizeTo)\n\t\t{\n\t\t\tif (getSpaceAvailable() < 3)\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (getNumVehiclesAndLargeSoldiers() >= getMaxVehiclesAndLargeSoldiersClamped())\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (_rules->getMaxLargeSoldiers() > -1 && getNumLargeSoldiers() >= _rules->getMaxLargeSoldiers())\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (_rules->getMaxLargeUnits() > -1 && getNumLargeUnits() >= _rules->getMaxLargeUnits())\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\telse if (sizeFrom > sizeTo)\n\t\t{\n\t\t\tif (_rules->getMaxSmallSoldiers() > -1 && getNumSmallSoldiers() >= _rules->getMaxSmallSoldiers())\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (_rules->getMaxSmallUnits() > -1 && getNumSmallUnits() >= _rules->getMaxSmallUnits())\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t}\n\treturn true;\n}\n\n/**\n * Validates craft space and craft constraints on adding soldier to a craft.\n */\nCraftPlacementErrors Craft::validateAddingSoldier(int space, const Soldier* s) const\n{\n\tif (space < s->getArmor()->getTotalSize())\n\t{\n\t\treturn CPE_NotEnoughSpace;\n\t}\n\tif (_rules->getMaxSoldiers() > -1 && getNumTotalSoldiers() >= _rules->getMaxSoldiers())\n\t{\n\t\treturn CPE_TooManySoldiers;\n\t}\n\tif (s->getArmor()->getSize() == 1)\n\t{\n\t\tif (_rules->getMaxSmallSoldiers() > -1 && getNumSmallSoldiers() >= _rules->getMaxSmallSoldiers())\n\t\t{\n\t\t\treturn CPE_TooManySmallSoldiers;\n\t\t}\n\t\tif (_rules->getMaxSmallUnits() > -1 && getNumSmallUnits() >= _rules->getMaxSmallUnits())\n\t\t{\n\t\t\treturn CPE_TooManySmallUnits;\n\t\t}\n\t}\n\telse // armorSize > 1\n\t{\n\t\tif (getNumVehiclesAndLargeSoldiers() >= getMaxVehiclesAndLargeSoldiersClamped())\n\t\t{\n\t\t\treturn CPE_TooManyVehiclesAndLargeSoldiers;\n\t\t}\n\t\tif (_rules->getMaxLargeSoldiers() > -1 && getNumLargeSoldiers() >= _rules->getMaxLargeSoldiers())\n\t\t{\n\t\t\treturn CPE_TooManyLargeSoldiers;\n\t\t}\n\t\tif (_rules->getMaxLargeUnits() > -1 && getNumLargeUnits() >= _rules->getMaxLargeUnits())\n\t\t{\n\t\t\treturn CPE_TooManyLargeUnits;\n\t\t}\n\t}\n\tauto& allowedSoldierGroups = _rules->getAllowedSoldierGroups();\n\tif (!allowedSoldierGroups.empty())\n\t{\n\t\tif (std::find(allowedSoldierGroups.begin(), allowedSoldierGroups.end(), s->getRules()->getGroup()) == allowedSoldierGroups.end())\n\t\t{\n\t\t\treturn CPE_SoldierGroupNotAllowed;\n\t\t}\n\t}\n\tif (_rules->isOnlyOneSoldierGroupAllowed() && getNumTotalSoldiers() > 0)\n\t{\n\t\tint currentGroup = -1;\n\t\tfor (const auto* tmpSoldier : *_base->getSoldiers())\n\t\t{\n\t\t\tif (tmpSoldier->getCraft() == this)\n\t\t\t{\n\t\t\t\tcurrentGroup = tmpSoldier->getRules()->getGroup();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (s->getRules()->getGroup() != currentGroup)\n\t\t{\n\t\t\treturn CPE_SoldierGroupNotSame;\n\t\t}\n\t}\n\tauto& allowedArmorGroups = _rules->getAllowedArmorGroups();\n\tif (!allowedArmorGroups.empty())\n\t{\n\t\tif (std::find(allowedArmorGroups.begin(), allowedArmorGroups.end(), s->getArmor()->getGroup()) == allowedArmorGroups.end())\n\t\t{\n\t\t\treturn CPE_ArmorGroupNotAllowed;\n\t\t}\n\t}\n\tauto& limitArmorGroups = _rules->getLimitArmorGroups();\n\tif (!limitArmorGroups.empty())\n\t{\n\t\tfor (auto& limit : limitArmorGroups)\n\t\t{\n\t\t\tint subTotal = 0;\n\t\t\tfor (const auto* tmpSoldier : *_base->getSoldiers())\n\t\t\t{\n\t\t\t\tif (tmpSoldier->getCraft() == this && tmpSoldier->getArmor()->getGroup() == limit.first)\n\t\t\t\t{\n\t\t\t\t\t++subTotal;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (subTotal >= limit.second)\n\t\t\t{\n\t\t\t\treturn CPE_ArmorGroupNotAllowed;\n\t\t\t}\n\t\t}\n\t}\n\treturn CPE_None;\n}\n\n/**\n * Validates craft space and craft constraints on adding vehicles to a craft.\n * @return Maximum allowed number of vehicles to add.\n */\nint Craft::validateAddingVehicles(int totalSize) const\n{\n\tint maximumAllowed = getSpaceAvailable() / totalSize;\n\n\t{\n\t\tmaximumAllowed = std::min(maximumAllowed, getMaxVehiclesAndLargeSoldiersClamped() - getNumVehiclesAndLargeSoldiers());\n\t}\n\tif (_rules->getMaxVehicles() > -1)\n\t{\n\t\tmaximumAllowed = std::min(maximumAllowed, _rules->getMaxVehicles() - getNumTotalVehicles());\n\t}\n\tif (totalSize == 1)\n\t{\n\t\tif (_rules->getMaxSmallVehicles() > -1)\n\t\t{\n\t\t\tmaximumAllowed = std::min(maximumAllowed, _rules->getMaxSmallVehicles() - getNumSmallVehicles());\n\t\t}\n\t\tif (_rules->getMaxSmallUnits() > -1)\n\t\t{\n\t\t\tmaximumAllowed = std::min(maximumAllowed, _rules->getMaxSmallUnits() - getNumSmallUnits());\n\t\t}\n\t}\n\telse // armorSize > 1\n\t{\n\t\tif (_rules->getMaxLargeVehicles() > -1)\n\t\t{\n\t\t\tmaximumAllowed = std::min(maximumAllowed, _rules->getMaxLargeVehicles() - getNumLargeVehicles());\n\t\t}\n\t\tif (_rules->getMaxLargeUnits() > -1)\n\t\t{\n\t\t\tmaximumAllowed = std::min(maximumAllowed, _rules->getMaxLargeUnits() - getNumLargeUnits());\n\t\t}\n\t}\n\treturn maximumAllowed;\n}\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tScript binding\n////////////////////////////////////////////////////////////\n\nnamespace\n{\n\nstd::string debugDisplayScript(const Craft* c)\n{\n\tif (c)\n\t{\n\t\tstd::string s;\n\t\ts += Craft::ScriptName;\n\t\ts += \"(type: \\\"\";\n\t\ts += c->getType();\n\t\ts += \"\\\" id: \";\n\t\ts += std::to_string(c->getId());\n\t\ts += \" damage: \";\n\t\ts += std::to_string(c->getDamagePercentage());\n\t\ts += \"%)\";\n\t\treturn s;\n\t}\n\telse\n\t{\n\t\treturn \"null\";\n\t}\n}\n\n} // namespace\n\n\n/**\n * Register Type in script parser.\n * @param parser Script parser.\n */\nvoid Craft::ScriptRegister(ScriptParserBase* parser)\n{\n\tparser->registerPointerType<RuleCraft>();\n\n\tBind<Craft> b = { parser };\n\n\tb.add<&Craft::getId>(\"getId\");\n\n\tb.add<&Craft::getDamage>(\"getDamage\");\n\tb.addField<&Craft::_stats, &RuleCraftStats::damageMax>(\"getDamageMax\");\n\tb.add<&Craft::getDamagePercentage>(\"getDamagePercentage\");\n\n\tb.add<&Craft::getShield>(\"getShield\");\n\tb.addField<&Craft::_stats, &RuleCraftStats::shieldCapacity>(\"getShieldMax\");\n\tb.add<&Craft::getShieldPercentage>(\"getShieldPercentage\");\n\n\tb.addRules<RuleCraft, &Craft::getRules>(\"getRuleCraft\");\n\n\tRuleCraftStats::addGetStatsScript<&Craft::_stats>(b, \"Stats.\");\n\n\tb.addScriptValue<BindBase::OnlyGet, &Craft::_rules, &RuleCraft::getScriptValuesRaw>();\n\tb.addScriptValue<&Craft::_scriptValues>();\n\tb.addDebugDisplay<&debugDisplayScript>();\n}\n\n// helper overloads for (de)serialization\nbool read(ryml::ConstNodeRef const& n, VehicleDeploymentData* val)\n{\n\tYAML::YamlNodeReader reader(n);\n\tif (!reader.isMap())\n\t\treturn false;\n\treader.tryRead(\"type\", val->type);\n\treader.tryRead(\"pos\", val->pos);\n\treader.tryRead(\"dir\", val->dir);\n\t// reader.tryRead(\"used\", val->used); // not needed\n\treturn true;\n}\n\nvoid write(ryml::NodeRef* n, VehicleDeploymentData const& val)\n{\n\tYAML::YamlNodeWriter writer(*n);\n\twriter.setAsMap();\n\twriter.setFlowStyle();\n\twriter.write(\"type\", val.type);\n\twriter.write(\"pos\", val.pos);\n\twriter.write(\"dir\", val.dir);\n\t// writer.write(\"used\", val.used); // not needed\n}\n\n}\n"
  },
  {
    "path": "src/Savegame/Craft.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"MovingTarget.h\"\n#include <utility>\n#include <map>\n#include <vector>\n#include <string>\n#include \"../Mod/RuleCraft.h\"\n#include \"../Engine/Script.h\"\n#include \"../Battlescape/Position.h\"\n\nnamespace OpenXcom\n{\n\ntypedef std::pair<std::string, int> CraftId;\n\nclass RuleCraft;\nclass RuleItem;\nclass Base;\nclass Soldier;\nclass CraftWeapon;\nclass ItemContainer;\nclass Mod;\nclass SavedGame;\nclass Vehicle;\nclass RuleStartingCondition;\nclass ScriptParserBase;\nclass ScriptGlobal;\n\nenum UfoDetection : int;\nenum CraftPlacementErrors : int\n{\n\tCPE_None = 0,\n\tCPE_NotEnoughSpace = 1,\n\tCPE_TooManySoldiers = 2,\n\tCPE_TooManySmallSoldiers = 3,\n\tCPE_TooManySmallUnits = 4,\n\tCPE_TooManyVehiclesAndLargeSoldiers = 5,\n\tCPE_TooManyLargeSoldiers = 6,\n\tCPE_TooManyLargeUnits = 7,\n\tCPE_SoldierGroupNotAllowed = 8,\n\tCPE_SoldierGroupNotSame = 9,\n\tCPE_ArmorGroupNotAllowed = 10,\n};\n\ntypedef std::pair<Position, int> SoldierDeploymentData;\n\nstruct VehicleDeploymentData\n{\n\tstd::string type;\n\tPosition pos;\n\tint dir;\n\tbool used;\n\tVehicleDeploymentData() : pos(-1, -1, -1), dir(0), used(false) { }\n};\n\n/**\n * Represents a craft stored in a base.\n * Contains variable info about a craft like\n * position, fuel, damage, etc.\n * @sa RuleCraft\n */\nclass Craft : public MovingTarget\n{\npublic:\n\t/// Name of class used in script.\n\tstatic constexpr const char *ScriptName = \"Craft\";\n\t/// Register all useful function used by script.\n\tstatic void ScriptRegister(ScriptParserBase* parser);\n\n\nprivate:\n\tconst RuleCraft *_rules;\n\tBase *_base;\n\tint _fuel, _excessFuel, _damage, _shield, _interceptionOrder, _takeoff;\n\tstd::vector<CraftWeapon*> _weapons;\n\tItemContainer *_items;\n\tItemContainer *_tempSoldierItems;\n\tItemContainer *_tempExtraItems;\n\tstd::vector<Vehicle*> _vehicles;\n\tstd::string _status;\n\tbool _lowFuel, _mission, _inBattlescape, _inDogfight;\n\tdouble _speedMaxRadian;\n\tRuleCraftStats _stats;\n\tbool _isAutoPatrolling;\n\tdouble _lonAuto, _latAuto;\n\tstd::vector<int> _pilots;\n\tstd::map<int, SoldierDeploymentData> _customSoldierDeployment;\n\tstd::vector<VehicleDeploymentData> _customVehicleDeployment;\n\tint _skinIndex;\n\tScriptValues<Craft> _scriptValues;\n\n\tvoid recalcSpeedMaxRadian();\n\n\tusing MovingTarget::load;\n\tusing MovingTarget::save;\n\npublic:\n\t/// Creates a craft of the specified type.\n\tCraft(const RuleCraft *rules, Base *base, int id = 0);\n\t/// Cleans up the craft.\n\t~Craft();\n\t/// Loads the craft from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader, const ScriptGlobal *shared, const Mod *mod, SavedGame *save);\n\t/// Finishes loading the craft from YAML (called after all other XCOM craft are loaded too).\n\tvoid finishLoading(const YAML::YamlNodeReader& reader, SavedGame *save);\n\t/// Initializes fixed weapons.\n\tvoid initFixedWeapons(const Mod* mod);\n\t/// Saves the craft to YAML.\n\tvoid save(YAML::YamlNodeWriter writer, const ScriptGlobal *shared) const;\n\t/// Loads a craft ID from YAML.\n\tstatic CraftId loadId(const YAML::YamlNodeReader& reader);\n\t/// Gets the craft's type.\n\tstd::string getType() const override;\n\t/// Gets the craft's ruleset.\n\tconst RuleCraft *getRules() const;\n\t/// Sets the craft's ruleset.\n\tvoid changeRules(RuleCraft *rules);\n\t/// Gets the craft's default name.\n\tstd::string getDefaultName(Language *lang) const override;\n\t/// Gets the craft's marker sprite.\n\tint getMarker() const override;\n\t/// Gets the craft's base.\n\tBase *getBase() const;\n\t/// Sets the craft's base.\n\tvoid setBase(Base *base, bool move = true);\n\t/// Gets the craft's status.\n\tstd::string getStatus() const;\n\t/// Sets the craft's status.\n\tvoid setStatus(const std::string &status);\n\t/// Gets the craft's altitude.\n\tstd::string getAltitude() const;\n\t/// Sets the craft's destination.\n\tvoid setDestination(Target *dest) override;\n\t/// Gets whether the craft is on auto-patrol.\n\tbool getIsAutoPatrolling() const;\n\t/// Sets whether the craft is on auto-patrol.\n\tvoid setIsAutoPatrolling(bool isAuto);\n\t/// Gets the auto-patrol longitude.\n\tdouble getLongitudeAuto() const;\n\t/// Sets the auto-patrol longitude.\n\tvoid setLongitudeAuto(double lon);\n\t/// Gets the auto-patrol latitude.\n\tdouble getLatitudeAuto() const;\n\t/// Sets the auto-patrol latitude.\n\tvoid setLatitudeAuto(double lat);\n\t/// Gets the craft's amount of weapons.\n\tint getNumWeapons(bool onlyLoaded = false) const;\n\t/// Gets the craft's amount of equipment.\n\tint getNumEquipment() const;\n\t/// Gets the craft's weapons.\n\tstd::vector<CraftWeapon*> *getWeapons();\n\t/// Gets the craft's items.\n\tItemContainer *getItems();\n\t/// Gets the craft's items equipped by the soldiers.\n\tItemContainer* getSoldierItems();\n\t/// Gets the craft's items not equipped by the soldiers.\n\tItemContainer* getExtraItems();\n\t/// Gets the craft's vehicles.\n\tstd::vector<Vehicle*> *getVehicles();\n\t/// Calculates (and stores) the sum of all equipment of all soldiers on the craft.\n\tvoid calculateTotalSoldierEquipment();\n\n\t/// Gets the total storage size of all items in the craft. Including vehicles+ammo and craft weapons+ammo.\n\tdouble getTotalItemStorageSize() const;\n\t/// Gets the total number of items of a given type in the craft. Including vehicles+ammo and craft weapons+ammo.\n\tint getTotalItemCount(const RuleItem* item) const;\n\n\t/// Update the craft's stats.\n\tvoid addCraftStats(const RuleCraftStats& s);\n\t/// Gets the craft's stats.\n\tconst RuleCraftStats& getCraftStats() const;\n\t/// Gets the craft's max amount of fuel.\n\tint getFuelMax() const;\n\t/// Gets the craft's amount of fuel.\n\tint getFuel() const;\n\t/// Sets the craft's amount of fuel.\n\tvoid setFuel(int fuel);\n\t/// Gets the craft's percentage of fuel.\n\tint getFuelPercentage() const;\n\t/// Gets the craft's max amount of damage.\n\tint getDamageMax() const;\n\t/// Gets the craft's amount of damage.\n\tint getDamage() const;\n\t/// Sets the craft's amount of damage.\n\tvoid setDamage(int damage);\n\t/// Gets the craft's percentage of damage.\n\tint getDamagePercentage() const;\n\t/// Gets the craft's max shield capacity\n\tint getShieldCapacity () const;\n\t/// Gets the craft's shield remaining\n\tint getShield() const;\n\t/// Sets the craft's shield remaining\n\tvoid setShield(int shield);\n\t/// Gets the percent shield remaining\n\tint getShieldPercentage() const;\n\t/// Gets whether the craft is ignored by hunter-killers.\n\tbool isIgnoredByHK() const;\n\t/// Gets whether the craft is running out of fuel.\n\tbool getLowFuel() const;\n\t/// Sets whether the craft is running out of fuel.\n\tvoid setLowFuel(bool low);\n\t/// Gets whether the craft has just finished a mission.\n\tbool getMissionComplete() const;\n\t/// Sets whether the craft has just finished a mission.\n\tvoid setMissionComplete(bool mission);\n\t/// Gets the craft's distance from its base.\n\tdouble getDistanceFromBase() const;\n\t/// Gets the craft's fuel consumption at a certain speed.\n\tint getFuelConsumption(int speed, int escortSpeed) const;\n\t/// Gets the craft's minimum fuel limit.\n\tint getFuelLimit() const;\n\t/// Gets the craft's minimum fuel limit to go to a base.\n\tint getFuelLimit(Base *base) const;\n\n\t/// Gets the craft's maximum unit capacity (soldiers and vehicles, small and large).\n\tint getMaxUnitsClamped() const;\n\tint getMaxUnitsRaw() const { return _stats.soldiers; }\n\t/// Gets the craft's maximum vehicle capacity (incl. 2x2 soldiers).\n\tint getMaxVehiclesAndLargeSoldiersClamped() const;\n\tint getMaxVehiclesAndLargeSoldiersRaw() const { return _stats.vehicles; }\n\n\t/// Gets the item limit for this craft.\n\tint getMaxItemsClamped() const { return std::max(0, _stats.maxItems); }\n\tint getMaxItemsRaw() const { return _stats.maxItems; }\n\tvoid setMaxItemsRaw(int p) { _stats.maxItems = p; }\n\t/// Gets the item storage space limit for this craft.\n\tdouble getMaxStorageSpaceClamped() const { return std::max(0.0, _stats.maxStorageSpace); }\n\tdouble getMaxStorageSpaceRaw() const { return _stats.maxStorageSpace; }\n\tvoid setMaxStorageSpaceRaw(double p) { _stats.maxStorageSpace = p; }\n\n\tdouble getBaseRange() const;\n\t/// Returns the craft to its base.\n\tvoid returnToBase();\n\t/// Returns the crew to their base (using transfers).\n\tvoid evacuateCrew(const Mod *mod);\n\t/// Checks if a target is detected by the craft's radar.\n\tUfoDetection detect(const Ufo *target, const SavedGame *save, bool alreadyTracked) const;\n\t/// Handles craft logic.\n\tbool think();\n\t/// Is the craft about to take off?\n\tbool isTakingOff() const;\n\t/// Does a craft full checkup.\n\tvoid checkup();\n\t/// Consumes the craft's fuel.\n\tvoid consumeFuel(int escortSpeed);\n\t/// Calculates the time to repair\n\tunsigned int calcRepairTime();\n\t/// Calculates the time to refuel\n\tunsigned int calcRefuelTime();\n\t/// Calculates the time to rearm\n\tunsigned int calcRearmTime();\n\t/// Repairs the craft.\n\tvoid repair();\n\t/// Refuels the craft.\n\tstd::string refuel();\n\t/// Rearms the craft.\n\tconst RuleItem* rearm();\n\t/// Sets the craft's battlescape status.\n\tvoid setInBattlescape(bool inbattle);\n\t/// Gets if the craft is in battlescape.\n\tbool isInBattlescape() const;\n\t/// Gets if craft is destroyed during dogfights.\n\tbool isDestroyed() const;\n\t/// Gets the amount of space available inside a craft.\n\tint getSpaceAvailable() const;\n\t/// Gets the amount of space used inside a craft.\n\tint getSpaceUsed() const;\n\t/// Checks if the commander is onboard.\n\tbool isCommanderOnboard() const;\n\t/// Checks if there are only permitted soldier types onboard.\n\tbool areOnlyPermittedSoldierTypesOnboard(const RuleStartingCondition* sc) const;\n\t/// Checks if there are enough required items onboard.\n\tbool areRequiredItemsOnboard(const std::map<std::string, int>& requiredItems) const;\n\t/// Destroys given required items.\n\tvoid destroyRequiredItems(const std::map<std::string, int>& requiredItems);\n\t/// Checks item limits.\n\tbool areTooManyItemsOnboard();\n\t/// Checks armor constraints.\n\tbool areBannedArmorsOnboard();\n\t/// Checks if there are enough pilots onboard.\n\tbool arePilotsOnboard(const Mod* mod);\n\t/// Checks if a pilot is already on the list.\n\tbool isPilot(int pilotId);\n\t/// Adds a pilot to the list.\n\tvoid addPilot(int pilotId);\n\t/// Removes all pilots from the list.\n\tvoid removeAllPilots();\n\t/// Gets the list of craft pilots.\n\tconst std::vector<Soldier*> getPilotList(bool autoAdd, const Mod* mod);\n\t/// Calculates the accuracy bonus based on pilot skills.\n\tint getPilotAccuracyBonus(const std::vector<Soldier*> &pilots, const Mod *mod) const;\n\t/// Calculates the dodge bonus based on pilot skills.\n\tint getPilotDodgeBonus(const std::vector<Soldier*> &pilots, const Mod *mod) const;\n\t/// Calculates the approach speed modifier based on pilot skills.\n\tint getPilotApproachSpeedModifier(const std::vector<Soldier*> &pilots, const Mod *mod) const;\n\t/// Gets the craft's vehicles of a certain type.\n\tint getVehicleCount(const std::string &vehicle) const;\n\t/// Sets the craft's dogfight status.\n\tvoid setInDogfight(const bool inDogfight);\n\t/// Gets if the craft is in dogfight.\n\tbool isInDogfight() const;\n\t/// Sets interception order (first craft to leave the base gets 1, second 2, etc.).\n\tvoid setInterceptionOrder(const int order);\n\t/// Gets interception number.\n\tint getInterceptionOrder() const;\n\t/// Gets the craft's unique id.\n\tCraftId getUniqueId() const;\n\t/// Unloads the craft.\n\tvoid unload();\n\t/// Reuses a base item.\n\tvoid reuseItem(const RuleItem* item);\n\t/// Gets the attraction value of the craft for alien hunter-killers.\n\tint getHunterKillerAttraction(int huntMode) const;\n\t/// Gets the craft's skin index.\n\tint getSkinIndex() const { return _skinIndex; }\n\t/// Sets the craft's skin index.\n\tvoid setSkinIndex(int skinIndex) { _skinIndex = skinIndex; }\n\t/// Gets the craft's skin sprite ID.\n\tint getSkinSprite() const;\n\n\t/// Gets the craft's custom deployment of soldiers.\n\tstd::map<int, SoldierDeploymentData>& getCustomSoldierDeployment() { return _customSoldierDeployment; };\n\t/// Gets the craft's custom deployment of vehicles.\n\tstd::vector<VehicleDeploymentData>& getCustomVehicleDeployment() { return _customVehicleDeployment; };\n\t/// Does this craft have a custom deployment set?\n\tbool hasCustomDeployment() const;\n\t/// Resets the craft's custom deployment.\n\tvoid resetCustomDeployment();\n\t/// Resets the craft's custom deployment of vehicles temp variables.\n\tvoid resetTemporaryCustomVehicleDeploymentFlags();\n\n\t/// Gets the craft's amount of vehicles and 2x2 soldiers.\n\tint getNumVehiclesAndLargeSoldiers() const;\n\n\t/// Gets the craft's amount of 1x1 soldiers.\n\tint getNumSmallSoldiers() const;\n\t/// Gets the craft's amount of 2x2 soldiers.\n\tint getNumLargeSoldiers() const;\n\t/// Gets the craft's amount of 1x1 vehicles.\n\tint getNumSmallVehicles() const;\n\t/// Gets the craft's amount of 2x2 vehicles.\n\tint getNumLargeVehicles() const;\n\t/// Gets the craft's amount of 1x1 units.\n\tint getNumSmallUnits() const;\n\t/// Gets the craft's amount of 2x2 units.\n\tint getNumLargeUnits() const;\n\t/// Gets the craft's total amount of soldiers.\n\tint getNumTotalSoldiers() const;\n\t/// Gets the craft's total amount of vehicles.\n\tint getNumTotalVehicles() const;\n\t/// Gets the craft's total amount of units.\n\tint getNumTotalUnits() const;\n\n\t/// Validates craft space and craft constraints on soldier armor change.\n\tbool validateArmorChange(int sizeFrom, int sizeTo) const;\n\t/// Validates craft space and craft constraints on adding soldier to a craft.\n\tCraftPlacementErrors validateAddingSoldier(int space, const Soldier* s) const;\n\t/// Validates craft space and craft constraints on adding vehicles to a craft.\n\tint validateAddingVehicles(int totalSize) const;\n};\n\n// helper overloads for (de)serialization\nbool read(ryml::ConstNodeRef const& n, VehicleDeploymentData* val);\nvoid write(ryml::NodeRef* n, VehicleDeploymentData const& val);\n\n}\n"
  },
  {
    "path": "src/Savegame/CraftWeapon.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <cmath>\n#include <algorithm>\n#include <cmath>\n#include \"CraftWeapon.h\"\n#include \"../Mod/RuleCraftWeapon.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"CraftWeaponProjectile.h\"\n#include \"../Engine/RNG.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes a craft weapon of the specified type.\n * @param rules Pointer to ruleset.\n * @param ammo Initial ammo.\n */\nCraftWeapon::CraftWeapon(RuleCraftWeapon *rules, int ammo) : _rules(rules), _ammo(ammo), _rearming(false), _disabled(false)\n{\n}\n\n/**\n *\n */\nCraftWeapon::~CraftWeapon()\n{\n}\n\n/**\n * Loads the craft weapon from a YAML file.\n * @param node YAML node.\n */\nvoid CraftWeapon::load(const YAML::YamlNodeReader& reader)\n{\n\treader.tryRead(\"ammo\", _ammo);\n\treader.tryRead(\"rearming\", _rearming);\n\treader.tryRead(\"disabled\", _disabled);\n}\n\n/**\n * Saves the base to a YAML file.\n * @return YAML node.\n */\nvoid CraftWeapon::save(YAML::YamlNodeWriter writer) const\n{\n\twriter.setAsMap();\n\n\twriter.write(\"type\", _rules->getType());\n\twriter.write(\"ammo\", _ammo);\n\tif (_rearming)\n\t\twriter.write(\"rearming\", _rearming);\n\tif (_disabled)\n\t\twriter.write(\"disabled\", _disabled);\n}\n\n/**\n * Returns the ruleset for the craft weapon's type.\n * @return Pointer to ruleset.\n */\nRuleCraftWeapon *CraftWeapon::getRules() const\n{\n\treturn _rules;\n}\n\n/**\n * Returns the ammo contained in this craft weapon.\n * @return Weapon ammo.\n */\nint CraftWeapon::getAmmo() const\n{\n\treturn _ammo;\n}\n\n/**\n * Changes the ammo contained in this craft weapon.\n * @param ammo Weapon ammo.\n * @return If the weapon ran out of ammo.\n */\nbool CraftWeapon::setAmmo(int ammo)\n{\n\t_ammo = ammo;\n\tif (_ammo < 0)\n\t{\n\t\t_ammo = 0;\n\t\treturn false;\n\t}\n\tif (_ammo > _rules->getAmmoMax())\n\t{\n\t\t_ammo = _rules->getAmmoMax();\n\t}\n\treturn true;\n}\n\n/**\n * Returns whether this craft weapon needs rearming.\n * @return Rearming status.\n */\nbool CraftWeapon::isRearming() const\n{\n\tif (_disabled)\n\t\treturn false;\n\n\treturn _rearming;\n}\n\n/**\n * Changes whether this craft weapon needs rearming\n * (for example, in case there's no more ammo).\n * @param rearming Rearming status.\n */\nvoid CraftWeapon::setRearming(bool rearming)\n{\n\t_rearming = rearming;\n}\n\n/**\n * Returns whether this craft weapon is disabled.\n * @return Disabled status.\n */\nbool CraftWeapon::isDisabled() const\n{\n\treturn _disabled;\n}\n\n/**\n * Sets whether this craft weapon is disabled or not.\n * @param disabled Disabled status.\n */\nvoid CraftWeapon::setDisabled(bool disabled)\n{\n\t_disabled = disabled;\n}\n\n/**\n * Rearms this craft weapon's ammo.\n * @param available number of clips available.\n * @param clipSize number of rounds in said clips.\n * @return number of clips used.\n */\nint CraftWeapon::rearm(const int available, const int clipSize)\n{\n\tint ammoUsed = _rules->getRearmRate();\n\tint clipsSaved = 0;\n\n\tif (clipSize > 0)\n\t{\t// +(clipSize - 1) correction for rounding up\n\t\tint needed = std::min(_rules->getRearmRate(), _rules->getAmmoMax() - _ammo + clipSize - 1) / clipSize;\n\t\tammoUsed = ((needed > available)? available : needed) * clipSize;\n\n\t\t// statistical bullet saving\n\t\tif (clipSize > 1 && _rules->useStatisticalBulletSaving())\n\t\t{\n\t\t\tint overusedAmmo = _ammo + ammoUsed - _rules->getAmmoMax();\n\t\t\tif (overusedAmmo > 0)\n\t\t\t{\n\t\t\t\tif (RNG::generate(0, clipSize - 1) < overusedAmmo)\n\t\t\t\t{\n\t\t\t\t\tclipsSaved = 1;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tsetAmmo(_ammo + ammoUsed);\n\n\t_rearming = _ammo < _rules->getAmmoMax();\n\n\treturn (clipSize <= 0)? 0 : (ammoUsed / clipSize) - clipsSaved;\n}\n\n/*\n * Fires a projectile from crafts weapon.\n * @return Pointer to the new projectile.\n */\nCraftWeaponProjectile* CraftWeapon::fire() const\n{\n\tconst RuleItem* damageItem = nullptr;\n\tif (this->getRules()->unifiedDamageFormula())\n\t{\n\t\tdamageItem = this->getRules()->getClipItem() ? this->getRules()->getClipItem() : this->getRules()->getLauncherItem();\n\t}\n\tCraftWeaponProjectile *p = new CraftWeaponProjectile(damageItem);\n\tp->setType(this->getRules()->getProjectileType());\n\tp->setSpeed(this->getRules()->getProjectileSpeed());\n\tp->setAccuracy(this->getRules()->getAccuracy());\n\tp->setDamage(this->getRules()->getDamage());\n\tp->setRange(this->getRules()->getRange());\n\tp->setShieldDamageModifier(this->getRules()->getShieldDamageModifier());\n\treturn p;\n}\n\n/*\n * get how many clips are loaded into this weapon.\n * @return number of clips loaded.\n */\nint CraftWeapon::getClipsLoaded() const\n{\n\tint retVal = (int)floor((double)_ammo / _rules->getRearmRate());\n\tauto* clip = _rules->getClipItem();\n\n\tif (clip && clip->getClipSize() > 0)\n\t{\n\t\tretVal = (int)floor((double)_ammo / clip->getClipSize());\n\t}\n\n\treturn retVal;\n}\n\n}\n"
  },
  {
    "path": "src/Savegame/CraftWeapon.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/Yaml.h\"\n\nnamespace OpenXcom\n{\n\nclass RuleCraftWeapon;\nclass CraftWeaponProjectile;\nclass Mod;\n\n/**\n * Represents a craft weapon equipped by a craft.\n * Contains variable info about a craft weapon like ammo.\n * @sa RuleCraftWeapon\n */\nclass CraftWeapon\n{\nprivate:\n\tRuleCraftWeapon *_rules;\n\tint _ammo;\n\tbool _rearming;\n\tbool _disabled;\npublic:\n\t/// Creates a craft weapon of the specified type.\n\tCraftWeapon(RuleCraftWeapon *rules, int ammo);\n\t/// Cleans up the craft weapon.\n\t~CraftWeapon();\n\t/// Loads the craft weapon from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader);\n\t/// Saves the craft weapon to YAML.\n\tvoid save(YAML::YamlNodeWriter writer) const;\n\t/// Gets the craft weapon's ruleset.\n\tRuleCraftWeapon *getRules() const;\n\t/// Gets the craft weapon's ammo.\n\tint getAmmo() const;\n\t/// Sets the craft weapon's ammo.\n\tbool setAmmo(int ammo);\n\t/// Gets the craft weapon's rearming status.\n\tbool isRearming() const;\n\t/// Sets the craft weapon's rearming status\n\tvoid setRearming(bool rearming);\n\t/// Is the weapon disabled?\n\tbool isDisabled() const;\n\t/// Sets whether the weapon is disabled or not.\n\tvoid setDisabled(bool disabled);\n\t/// Rearms the craft weapon.\n\tint rearm(const int available, const int clipSize);\n\t/// Fires the craft weapon. Used during dogfights.\n\tCraftWeaponProjectile* fire() const;\n\t/// get how many clips are loaded into this weapon.\n\tint getClipsLoaded() const;\n\n};\n\n}\n"
  },
  {
    "path": "src/Savegame/CraftWeaponProjectile.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"CraftWeaponProjectile.h\"\n\nnamespace OpenXcom {\n\nCraftWeaponProjectile::CraftWeaponProjectile(const RuleItem* damageItem) : _damageItem(damageItem),\n\t_type(CWPT_CANNON_ROUND), _globalType(CWPGT_MISSILE),\n\t_speed(0), _direction(D_NONE), _currentPosition(0), _horizontalPosition(0), _state(0), _accuracy(0), _damage(0), _range(0),\n\t_toBeRemoved(false), _missed(false), _distanceCovered(0),\n\t_shieldDamageModifier(100)\n{\n}\n\n\nCraftWeaponProjectile::~CraftWeaponProjectile(void)\n{\n}\n\n/*\n * Sets the type of projectile according to the type of\n * weapon it was shot from. This is used for drawing the\n * projectiles.\n */\nvoid CraftWeaponProjectile::setType(CraftWeaponProjectileType type)\n{\n\t_type = type;\n\tif (type >= CWPT_LASER_BEAM)\n\t{\n\t\t_globalType = CWPGT_BEAM;\n\t\t_state = 8;\n\t}\n}\n\n/*\n * Returns the type of projectile.\n * @return Projectile type as an integer value.\n */\nCraftWeaponProjectileType CraftWeaponProjectile::getType() const\n{\n\treturn _type;\n}\n\n/*\n * Returns the global type of projectile.\n * @return 0 - if it's a missile, 1 if beam.\n */\nCraftWeaponProjectileGlobalType CraftWeaponProjectile::getGlobalType() const\n{\n\treturn _globalType;\n}\n\n/*\n * Sets the direction of the projectile.\n */\nvoid CraftWeaponProjectile::setDirection(const int &directon)\n{\n\t_direction = directon;\n\tif (_direction == D_UP)\n\t{\n\t\t_currentPosition = 0;\n\t}\n}\n\n/*\n * Gets the direction of the projectile.\n */\nint CraftWeaponProjectile::getDirection() const\n{\n\treturn _direction;\n}\n\n/*\n * Moves the projectile according to it's speed\n * or changes the phase of beam animation.\n */\nvoid CraftWeaponProjectile::move()\n{\n\tif (_globalType == CWPGT_MISSILE)\n\t{\n\t\tint positionChange = _speed;\n\n\t\t// Check if projectile would reach its maximum range this tick.\n\t\tif ((_distanceCovered / 8) < getRange() && ((_distanceCovered + _speed)/ 8) >= getRange())\n\t\t\tpositionChange = getRange() * 8 - _distanceCovered;\n\n\t\t// Check if projectile passed its maximum range on previous tick.\n\t\tif ((_distanceCovered / 8) >= getRange())\n\t\t\tsetMissed(true);\n\n\t\tif (_direction == D_UP)\n\t\t{\n\t\t\t_currentPosition += positionChange;\n\t\t}\n\t\telse if (_direction == D_DOWN)\n\t\t{\n\t\t\t_currentPosition -= positionChange;\n\t\t}\n\n\t\t_distanceCovered += positionChange;\n\t}\n\telse if (_globalType == CWPGT_BEAM)\n\t{\n\t\t_state /= 2;\n\t\tif (_state == 1)\n\t\t{\n\t\t\t_toBeRemoved = true;\n\t\t}\n\t}\n}\n\n/*\n * Sets the y position of the projectile on the radar.\n */\nvoid CraftWeaponProjectile::setPosition(const int &position)\n{\n\t_currentPosition = position;\n}\n\n/*\n * Gets the y position of the projectile on the radar.\n */\nint CraftWeaponProjectile::getPosition() const\n{\n\treturn _currentPosition;\n}\n\n/*\n * Sets the x position of the projectile on the radar.\n * It's used only once for each projectile during firing.\n */\nvoid CraftWeaponProjectile::setHorizontalPosition(int position)\n{\n\t_horizontalPosition = position;\n}\n\n/*\n * Gets the x position of the projectile.\n */\nint CraftWeaponProjectile::getHorizontalPosition() const\n{\n\treturn _horizontalPosition;\n}\n\n/*\n * Marks the projectile to be removed.\n */\nvoid CraftWeaponProjectile::remove()\n{\n\t_toBeRemoved = true;\n}\n\n/*\n * Returns if a projectile should be removed.\n */\nbool CraftWeaponProjectile::toBeRemoved() const\n{\n\treturn _toBeRemoved;\n}\n\n/*\n * Returns animation state of a beam.\n */\nint CraftWeaponProjectile::getState() const\n{\n\treturn _state;\n}\n\n/*\n * Sets the amount of damage the projectile can do\n * when hitting it's target.\n */\nvoid CraftWeaponProjectile::setDamage(const int &damage)\n{\n\t_damage = damage;\n}\n\n/*\n * Gets the amount of damage the projectile can do\n * when hitting it's target.\n */\nint CraftWeaponProjectile::getDamage() const\n{\n\treturn _damage;\n}\n\n/*\n * Sets the accuracy of the projectile.\n */\nvoid CraftWeaponProjectile::setAccuracy(const int &accuracy)\n{\n\t_accuracy = accuracy;\n}\n\n/*\n * Gets the accuracy of the projectile.\n */\nint CraftWeaponProjectile::getAccuracy() const\n{\n\treturn _accuracy;\n}\n\n/*\n * Marks the projectile as a one which missed it's target.\n */\nvoid CraftWeaponProjectile::setMissed(const bool &missed)\n{\n\t_missed = missed;\n}\n\n/*\n * Returns true if the projectile missed it's target.\n * Otherwise returns false.\n */\nbool CraftWeaponProjectile::getMissed() const\n{\n\treturn _missed;\n}\n\n/*\n * Sets maximum range of projectile.\n */\nvoid CraftWeaponProjectile::setRange(const int &range)\n{\n\t_range = range;\n}\n\n/*\n * Returns maximum range of projectile.\n */\nint CraftWeaponProjectile::getRange() const\n{\n\treturn _range;\n}\n\n/*\n * Sets the speed of the projectile.\n */\nvoid CraftWeaponProjectile::setSpeed(int speed)\n{\n\t_speed = speed;\n}\n\n/*\n * Sets how effective this projectile is against shields\n */\nvoid CraftWeaponProjectile::setShieldDamageModifier(const int &shieldDamageModifier)\n{\n\t_shieldDamageModifier = shieldDamageModifier;\n}\n\n/*\n * Gets how effective this projectile is against shields\n */\nint CraftWeaponProjectile::getShieldDamageModifier() const\n{\n\treturn _shieldDamageModifier;\n}\n\n}\n"
  },
  {
    "path": "src/Savegame/CraftWeaponProjectile.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\nnamespace OpenXcom {\n\nclass Surface;\nclass RuleItem;\n\n// Do not change the order of these enums because they are related to blob order.\nenum CraftWeaponProjectileType { CWPT_STINGRAY_MISSILE, CWPT_AVALANCHE_MISSILE, CWPT_CANNON_ROUND, CWPT_FUSION_BALL, CWPT_LASER_BEAM, CWPT_PLASMA_BEAM };\nenum CraftWeaponProjectileGlobalType { CWPGT_MISSILE, CWPGT_BEAM };\nenum Directions { D_NONE, D_UP, D_DOWN };\nconst int HP_LEFT = -1;\nconst int HP_CENTER = 0;\nconst int HP_RIGHT = 1;\n\nclass CraftWeaponProjectile\n{\nprivate:\n\tconst RuleItem* _damageItem;\n\tCraftWeaponProjectileType _type;\n\tCraftWeaponProjectileGlobalType _globalType;\n\tint _speed;\n\tint _direction;\n\tint _currentPosition; // relative to interceptor, apparently, which is a problem when the interceptor disengages while projectile is in flight\n\tint _horizontalPosition;\n\tint _state;\n\tint _accuracy;\n\tint _damage;\n\tint _range;\n\tbool _toBeRemoved;\n\tbool _missed;\n\n\tint _distanceCovered;\n\tint _shieldDamageModifier;\n\t\npublic:\n\tCraftWeaponProjectile(const RuleItem* damageItem);\n\t~CraftWeaponProjectile(void);\n\n\t/// Sets projectile type. This determines it's speed.\n\tvoid setType(CraftWeaponProjectileType type);\n\t/// Returns projectile type.\n\tCraftWeaponProjectileType getType() const;\n\t/// Returns projectile global type.\n\tCraftWeaponProjectileGlobalType getGlobalType() const;\n\t/// Sets projectile direction. This determines it's initial position.\n\tvoid setDirection(const int &directon);\n\t/// Gets projectile direction.\n\tint getDirection() const;\n\t/// Moves projectile in _direction with _speed.\n\tvoid move();\n\t/// Gets projectile position.\n\tint getPosition() const;\n\t/// Sets projectile position.\n\tvoid setPosition(const int &position);\n\t/// Sets horizontal position. This determines from which weapon projectile has been fired.\n\tvoid setHorizontalPosition(int position);\n\t/// Gets horizontal position.\n\tint getHorizontalPosition() const;\n\t/// Marks projectile to be removed.\n\tvoid remove();\n\t/// Returns true if the projectile should be removed.\n\tbool toBeRemoved() const;\n\t/// Returns state of the beam.\n\tint getState() const;\n\t/// Sets power of the projectile.\n\tvoid setDamage(const int &damage);\n\t/// Gets power of the projectile.\n\tint getDamage() const;\n\t/// Sets accuracy of the projectile.\n\tvoid setAccuracy(const int &accuracy);\n\t/// Gets accuracy of the projectile.\n\tint getAccuracy() const;\n\t/// Sets the projectile to missed status.\n\tvoid setMissed(const bool &missed);\n\t/// Gets the projectile missed status.\n\tbool getMissed() const;\n\t/// Sets maximum range of projectile.\n\tvoid setRange(const int &range);\n\t/// Gets maximum range of projectile.\n\tint getRange() const;\n\t/// Sets the speed of a missile type projectile.\n\tvoid setSpeed(const int speed);\n\t/// Sets how effective this projectile is against shields\n\tvoid setShieldDamageModifier(const int &shieldDamageModifier);\n\t/// Gets how effective this projectile is against shields\n\tint getShieldDamageModifier() const;\n\t/// Gets the damage item.\n\tconst RuleItem* getDamageItem() const { return _damageItem; }\n};\n\n}\n"
  },
  {
    "path": "src/Savegame/EquipmentLayoutItem.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"EquipmentLayoutItem.h\"\n#include \"../Mod/RuleInventory.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/Collections.h\"\n#include \"BattleItem.h\"\n#include <optional>\n\nnamespace OpenXcom\n{\n\n/**\n * Value used for save backward and forward compatibility. Represent empty slot.\n */\nconst std::string EmptyPlaceHolder = \"NONE\";\n\n/**\n * Initializes a new soldier-equipment layout item from YAML.\n * @param node YAML node.\n */\nEquipmentLayoutItem::EquipmentLayoutItem(const YAML::YamlNodeReader& reader, const Mod* mod)\n{\n\tfor (int slot = 0; slot < RuleItem::AmmoSlotMax; ++slot)\n\t{\n\t\t_ammoItem[slot] = nullptr;\n\t}\n\tload(reader, mod);\n}\n\n/**\n * Initializes a new soldier-equipment layout item.\n * @param itemType Item's type.\n * @param slot Occupied slot's id.\n * @param slotX Position-X in the occupied slot.\n * @param slotY Position-Y in the occupied slot.\n * @param ammoItem The ammo has to be loaded into the item. (it's type)\n * @param fuseTimer The turn until explosion of the item. (if it's an activated grenade-type)\n */\nEquipmentLayoutItem::EquipmentLayoutItem(const BattleItem* item) :\n\t_itemType(item->getRules()),\n\t_slot(item->getSlot()),\n\t_slotX(item->getSlotX()), _slotY(item->getSlotY()),\n\t_ammoItem{}, _fuseTimer(item->getFuseTimer()),\n\t_fixed(item->getRules()->isFixed())\n{\n\tfor (int slot = 0; slot < RuleItem::AmmoSlotMax; ++slot)\n\t{\n\t\tif (item->needsAmmoForSlot(slot) && item->getAmmoForSlot(slot))\n\t\t{\n\t\t\t_ammoItem[slot] = item->getAmmoForSlot(slot)->getRules();\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_ammoItem[slot] = nullptr;\n\t\t}\n\t}\n}\n\n/**\n *\n */\nEquipmentLayoutItem::~EquipmentLayoutItem()\n{\n}\n\n/**\n * Returns the item's type which has to be in a slot.\n * @return item type.\n */\nconst RuleItem* EquipmentLayoutItem::getItemType() const\n{\n\treturn _itemType;\n}\n\n/**\n * Returns the slot to be occupied.\n * @return slot name.\n */\nconst RuleInventory* EquipmentLayoutItem::getSlot() const\n{\n\treturn _slot;\n}\n\n/**\n * Returns the position-X in the slot to be occupied.\n * @return slot-X.\n */\nint EquipmentLayoutItem::getSlotX() const\n{\n\treturn _slotX;\n}\n\n/**\n * Returns the position-Y in the slot to be occupied.\n * @return slot-Y.\n */\nint EquipmentLayoutItem::getSlotY() const\n{\n\treturn _slotY;\n}\n\n/**\n * Returns the ammo has to be loaded into the item.\n * @return ammo type.\n */\nconst RuleItem* EquipmentLayoutItem::getAmmoItemForSlot(int slot) const\n{\n\treturn _ammoItem[slot];\n}\n\n/**\n * Returns the turn until explosion of the item. (if it's an activated grenade-type)\n * @return turn count.\n */\nint EquipmentLayoutItem::getFuseTimer() const\n{\n\treturn _fuseTimer;\n}\n\n/**\n * Is this a fixed weapon entry?\n * @return True, if this is a fixed weapon entry.\n */\nbool EquipmentLayoutItem::isFixed() const\n{\n\treturn _fixed;\n}\n\n/**\n * Loads the soldier-equipment layout item from a YAML file.\n * @param node YAML node.\n */\nvoid EquipmentLayoutItem::load(const YAML::YamlNodeReader& reader, const Mod* mod)\n{\n\t_itemType = mod->getItem(reader[\"itemType\"].readVal<std::string>(), true);\n\t_slot = mod->getInventory(reader[\"slot\"].readVal<std::string>(), true);\n\t_slotX = reader[\"slotX\"].readVal(0);\n\t_slotY = reader[\"slotY\"].readVal(0);\n\tif (const auto& ammoSlots = reader[\"ammoItemSlots\"])\n\t{\n\t\tfor (int slot = 0; slot < RuleItem::AmmoSlotMax && ammoSlots[slot]; ++slot)\n\t\t{\n\t\t\tauto s = ammoSlots[slot].readVal<std::string>();\n\t\t\t_ammoItem[slot] = s != EmptyPlaceHolder ? mod->getItem(s, true) : nullptr;\n\t\t}\n\t}\n\telse if (const auto& ammo = reader[\"ammoItem\"])\n\t{\n\t\t_ammoItem[0] = mod->getItem(ammo.readVal<std::string>(), true);\n\t}\n\t_fuseTimer = reader[\"fuseTimer\"].readVal(-1);\n\t_fixed = reader[\"fixed\"].readVal(false);\n}\n\n/**\n * Saves the soldier-equipment layout item to a YAML file.\n * @return YAML node.\n */\nvoid EquipmentLayoutItem::save(YAML::YamlNodeWriter writer) const\n{\n\twriter.setAsMap();\n\twriter.setFlowStyle();\n\twriter.write(\"itemType\", _itemType->getType());\n\twriter.write(\"slot\", _slot->getId());\n\t// only save this info if it's needed, reduce clutter in saves\n\tif (_slotX != 0)\n\t\twriter.write(\"slotX\", _slotX);\n\tif (_slotY != 0)\n\t\twriter.write(\"slotY\", _slotY);\n\tif (_ammoItem[0] != nullptr)\n\t\twriter.write(\"ammoItem\", _ammoItem[0]->getType());\n\tstd::optional<YAML::YamlNodeWriter> ammoSlotWriter;\n\tCollections::untilLastIf(\n\t\t_ammoItem,\n\t\t[](const RuleItem* s)\n\t\t{\n\t\t\treturn s != nullptr;\n\t\t},\n\t\t[&](const RuleItem* s)\n\t\t{\n\t\t\tif (!ammoSlotWriter.has_value())\n\t\t\t{\n\t\t\t\tammoSlotWriter.emplace(writer[\"ammoItemSlots\"]);\n\t\t\t\tammoSlotWriter->setAsSeq();\n\t\t\t}\n\t\t\tammoSlotWriter->write(s ? s->getType() : EmptyPlaceHolder);\n\t\t});\n\tif (_fuseTimer >= 0)\n\t\twriter.write(\"fuseTimer\", _fuseTimer);\n\tif (_fixed)\n\t\twriter.write(\"fixed\", _fixed);\n}\n\n}\n"
  },
  {
    "path": "src/Savegame/EquipmentLayoutItem.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include \"../Engine/Yaml.h\"\n#include \"../Mod/RuleItem.h\"\n\nnamespace OpenXcom\n{\n\nclass BattleItem;\nclass RuleItem;\nclass RuleInventory;\nclass Mod;\n\n/**\n * Represents a soldier-equipment layout item which is used\n * on the beginning of the Battlescape.\n */\nclass EquipmentLayoutItem\n{\nprivate:\n\tconst RuleItem* _itemType;\n\tconst RuleInventory* _slot;\n\tint _slotX, _slotY;\n\tconst RuleItem* _ammoItem[RuleItem::AmmoSlotMax];\n\tint _fuseTimer;\n\tbool _fixed;\npublic:\n\t/// Creates a new soldier-equipment layout item and loads its contents from YAML.\n\tEquipmentLayoutItem(const YAML::YamlNodeReader& reader, const Mod* mod);\n\t/// Creates a new soldier-equipment layout item.\n\tEquipmentLayoutItem(const BattleItem* item);\n\t/// Cleans up the soldier-equipment layout item.\n\t~EquipmentLayoutItem();\n\t/// Gets the item's type which has to be in a slot\n\tconst RuleItem* getItemType() const;\n\t/// Gets the slot to be occupied\n\tconst RuleInventory* getSlot() const;\n\t/// Gets the slotX to be occupied\n\tint getSlotX() const;\n\t/// Gets the slotY to be occupied\n\tint getSlotY() const;\n\t/// Gets the ammo item\n\tconst RuleItem* getAmmoItemForSlot(int i) const;\n\t/// Gets the turn until explosion\n\tint getFuseTimer() const;\n\t/// Is this a fixed weapon entry?\n\tbool isFixed() const;\n\t/// Loads the soldier-equipment layout item from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader, const Mod* mod);\n\t/// Saves the soldier-equipment layout item to YAML.\n\tvoid save(YAML::YamlNodeWriter writer) const;\n};\n\n}\n"
  },
  {
    "path": "src/Savegame/GameTime.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"GameTime.h\"\n#include \"../Engine/Language.h\"\n#include <iomanip>\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes a new ingame time with a certain starting point.\n * @param weekday Starting weekday.\n * @param day Starting day.\n * @param month Starting month.\n * @param year Starting year.\n * @param hour Starting hour.\n * @param minute Starting minute.\n * @param second Starting second.\n */\nGameTime::GameTime(int weekday, int day, int month, int year, int hour, int minute, int second) : _second(second), _minute(minute), _hour(hour), _weekday(weekday), _day(day), _month(month), _year(year)\n{\n}\n\n/**\n *\n */\nGameTime::~GameTime()\n{\n}\n\n/**\n * Loads the time from a YAML file.\n * @param node YAML node.\n */\nvoid GameTime::load(const YAML::YamlNodeReader& reader)\n{\n\treader.tryRead(\"second\", _second);\n\treader.tryRead(\"minute\", _minute);\n\treader.tryRead(\"hour\", _hour);\n\treader.tryRead(\"weekday\", _weekday);\n\treader.tryRead(\"day\", _day);\n\treader.tryRead(\"month\", _month);\n\treader.tryRead(\"year\", _year);\n}\n\n/**\n * Saves the time to a YAML file.\n * @return YAML node.\n */\nvoid GameTime::save(YAML::YamlNodeWriter writer) const\n{\n\twriter.setAsMap();\n\twriter.setFlowStyle();\n\twriter.write(\"second\", _second);\n\twriter.write(\"minute\", _minute);\n\twriter.write(\"hour\", _hour);\n\twriter.write(\"weekday\", _weekday);\n\twriter.write(\"day\", _day);\n\twriter.write(\"month\", _month);\n\twriter.write(\"year\", _year);\n}\n\nbool GameTime::isLastDayOfMonth()\n{\n\tint monthDays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };\n\t// Leap year\n\tif ((_year % 4 == 0) && !(_year % 100 == 0 && _year % 400 != 0))\n\t\tmonthDays[1]++;\n\treturn _day == monthDays[_month - 1];\n}\n\n/**\n * Advances the ingame time by 5 seconds, automatically correcting\n * the other components when necessary and sending out a trigger when\n * a certain time span has elapsed for time-dependent events.\n * @return Time span trigger.\n */\nTimeTrigger GameTime::advance()\n{\n\tTimeTrigger trigger = TIME_5SEC;\n\tint monthDays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };\n\t// Leap year\n\tif ((_year % 4 == 0) && !(_year % 100 == 0 && _year % 400 != 0))\n\t\tmonthDays[1]++;\n\n\t_second += 5;\n\n\tif (_second >= 60)\n\t{\n\t\t_minute++;\n\t\t_second = 0;\n\t\tif (_minute % 10 == 0)\n\t\t{\n\t\t\ttrigger = TIME_10MIN;\n\t\t}\n\t\tif (_minute % 30 == 0)\n\t\t{\n\t\t\ttrigger = TIME_30MIN;\n\t\t}\n\t}\n\tif (_minute >= 60)\n\t{\n\t\t_hour++;\n\t\t_minute = 0;\n\t\ttrigger = TIME_1HOUR;\n\t}\n\tif (_hour >= 24)\n\t{\n\t\t_day++;\n\t\t_weekday++;\n\t\t_hour = 0;\n\t\ttrigger = TIME_1DAY;\n\t}\n\tif (_weekday > 7)\n\t{\n\t\t_weekday = 1;\n\t}\n\tif (_day > monthDays[_month - 1])\n\t{\n\t\t_day = 1;\n\t\t_month++;\n\t\ttrigger = TIME_1MONTH;\n\t}\n\tif (_month > 12)\n\t{\n\t\t_month = 1;\n\t\t_year++;\n\t}\n\n\treturn trigger;\n}\n\n/**\n * Returns the current ingame second.\n * @return Second (0-59).\n */\nint GameTime::getSecond() const\n{\n\treturn _second;\n}\n\n/**\n * Returns the current ingame minute.\n * @return Minute (0-59).\n */\nint GameTime::getMinute() const\n{\n\treturn _minute;\n}\n\n/**\n * Returns the current ingame hour.\n * @return Hour (0-23).\n */\nint GameTime::getHour() const\n{\n\treturn _hour;\n}\n\n/**\n * Returns the current ingame weekday.\n * @return Weekday (1-7), starts on Sunday.\n */\nint GameTime::getWeekday() const\n{\n\treturn _weekday;\n}\n\n/**\n * Returns a localizable-string representation of\n * the current ingame weekday.\n * @return Weekday string ID.\n */\nstd::string GameTime::getWeekdayString() const\n{\n\tstd::string weekdays[] = {\"STR_SUNDAY\", \"STR_MONDAY\", \"STR_TUESDAY\", \"STR_WEDNESDAY\", \"STR_THURSDAY\", \"STR_FRIDAY\", \"STR_SATURDAY\"};\n\treturn weekdays[_weekday - 1];\n}\n\n/**\n * Returns the current ingame day.\n * @return Day (1-31).\n */\nint GameTime::getDay() const\n{\n\treturn _day;\n}\n\n/**\n * Returns the localized representation of the current\n * ingame day with the cardinal operator.\n * @param lang Pointer to current language.\n * @return Localized day string.\n */\nstd::string GameTime::getDayString(Language *lang) const\n{\n\tstd::string s;\n\tswitch (_day)\n\t{\n\tcase 1:\n\tcase 21:\n\tcase 31:\n\t\ts = \"STR_DATE_FIRST\";\n\t\tbreak;\n\tcase 2:\n\tcase 22:\n\t\ts = \"STR_DATE_SECOND\";\n\t\tbreak;\n\tcase 3:\n\tcase 23:\n\t\ts = \"STR_DATE_THIRD\";\n\t\tbreak;\n\tdefault:\n\t\ts = \"STR_DATE_FOURTH\";\n\t}\n\treturn lang->getString(s).arg(_day);\n}\n\n/**\n * Returns the current ingame month.\n * @return Month (1-12).\n */\nint GameTime::getMonth() const\n{\n\treturn _month;\n}\n\n/**\n * Returns a localizable-string representation of\n * the current ingame month.\n * @return Month string ID.\n */\nstd::string GameTime::getMonthString() const\n{\n\tstd::string months[] = {\"STR_JAN\", \"STR_FEB\", \"STR_MAR\", \"STR_APR\", \"STR_MAY\", \"STR_JUN\", \"STR_JUL\", \"STR_AUG\", \"STR_SEP\", \"STR_OCT\", \"STR_NOV\", \"STR_DEC\"};\n\treturn months[_month - 1];\n}\n\n/**\n * Returns the current ingame year.\n * @return Year.\n */\nint GameTime::getYear() const\n{\n\treturn _year;\n}\n\n/**\n * Returns a string version of the ingame date and time.\n * @return Game date and time string.\n */\nstd::string GameTime::getFullString() const\n{\n\tstd::ostringstream ss;\n\tss << _year << \"-\" << std::setfill('0') << std::setw(2) << _month << \"-\" << std::setw(2) << _day;\n\tss << \" \" << std::setw(2) << _hour << \":\" << std::setw(2) << _minute << \":\" << std::setw(2) << _second;\n\treturn ss.str();\n}\n\n/**\n * Returns the current position of the daylight emitted on the globe\n * according to the current ingame time, so the value is 0 when the light\n * starts at 0 longitude (6h) and 1 when the light ends at 0 longitude (18h).\n * @return Daylight position (0-1).\n */\ndouble GameTime::getDaylight() const\n{\n\treturn (double)((((((_hour + 18) % 24) * 60) + _minute) * 60) + _second) / (60 * 60 * 24);\n}\n\n}\n"
  },
  {
    "path": "src/Savegame/GameTime.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include \"../Engine/Yaml.h\"\n\nnamespace OpenXcom\n{\n\nclass Language;\n\n/**\n * Enumerator for time periods.\n */\nenum TimeTrigger { TIME_5SEC, TIME_10MIN, TIME_30MIN, TIME_1HOUR, TIME_1DAY, TIME_1MONTH };\n\n/**\n * Stores the current ingame time/date according to GMT.\n * Takes care of managing and representing each component,\n * as well as common time operations.\n */\nclass GameTime\n{\nprivate:\n\tint _second, _minute, _hour, _weekday, _day, _month, _year;\npublic:\n\t/// Creates a new ingame time at a certain point.\n\tGameTime(int weekday, int day, int month, int year, int hour, int minute, int second);\n\t/// Cleans up the ingame time.\n\t~GameTime();\n\t/// Loads the time from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader);\n\t/// Saves the time to YAML.\n\tvoid save(YAML::YamlNodeWriter writer) const;\n\t/// Checks if it is the last day of the month.\n\tbool isLastDayOfMonth();\n\t/// Advances the time by 5 seconds.\n\tTimeTrigger advance();\n\t/// Gets the ingame second.\n\tint getSecond() const;\n\t/// Gets the ingame minute.\n\tint getMinute() const;\n\t/// Gets the ingame hour.\n\tint getHour() const;\n\t/// Gets the ingame weekday.\n\tint getWeekday() const;\n\t// Gets a string version of the ingame weekday.\n\tstd::string getWeekdayString() const;\n\t/// Gets the ingame day.\n\tint getDay() const;\n\t// Gets a string version of the ingame day.\n\tstd::string getDayString(Language *lang) const;\n\t/// Gets the ingame month.\n\tint getMonth() const;\n\t// Gets a string version of the ingame month.\n\tstd::string getMonthString() const;\n\t/// Gets the ingame year.\n\tint getYear() const;\n\t// Gets a string version of the ingame date and time.\n\tstd::string getFullString() const;\n\t/// Gets the position of the daylight according to the ingame time.\n\tdouble getDaylight() const;\n};\n\n}\n"
  },
  {
    "path": "src/Savegame/GeoscapeEvent.cpp",
    "content": "/*\n * Copyright 2010-2019 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"GeoscapeEvent.h\"\n#include <assert.h>\n#include \"../Mod/RuleEvent.h\"\n\nnamespace OpenXcom\n{\n\nGeoscapeEvent::GeoscapeEvent(const RuleEvent &rule) : _rule(rule), _spawnCountdown(0), _over(false)\n{\n\t// Empty by design.\n}\n\nGeoscapeEvent::~GeoscapeEvent()\n{\n\t// Empty by design.\n}\n\n/**\n * Loads the event from YAML.\n * @param node The YAML node containing the data.\n */\nvoid GeoscapeEvent::load(const YAML::YamlNodeReader& reader)\n{\n\treader.tryRead(\"spawnCountdown\", _spawnCountdown);\n\treader.tryRead(\"over\", _over);\n}\n\n/**\n * Saves the event to YAML.\n * @return YAML node.\n */\nvoid GeoscapeEvent::save(YAML::YamlNodeWriter writer) const\n{\n\twriter.setAsMap();\n\twriter.write(\"name\", _rule.getName());\n\twriter.write(\"spawnCountdown\", _spawnCountdown);\n\tif (_over)\n\t\twriter.write(\"over\", _over);\n}\n\n/**\n * The new time must be a multiple of 30 minutes, and more than 0.\n * Calling this on a finished event has no effect.\n * @param minutes The minutes until the event will pop up.\n */\nvoid GeoscapeEvent::setSpawnCountdown(size_t minutes)\n{\n\tassert(minutes != 0 && minutes % 30 == 0);\n\tif (_over)\n\t{\n\t\treturn;\n\t}\n\t_spawnCountdown = minutes;\n}\n\nvoid GeoscapeEvent::think()\n{\n\t// if finished, don't do anything\n\tif (_over)\n\t{\n\t\treturn;\n\t}\n\n\t// are we there yet?\n\tif (_spawnCountdown > 30)\n\t{\n\t\t_spawnCountdown -= 30;\n\t\treturn;\n\t}\n\n\t// ok, the time has come...\n\t_over = true;\n}\n\n}\n"
  },
  {
    "path": "src/Savegame/GeoscapeEvent.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2019 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/Yaml.h\"\n\nnamespace OpenXcom\n{\n\nclass RuleEvent;\n\n/**\n * Represents a custom Geoscape event, generated in the background and waiting to pop up.\n */\nclass GeoscapeEvent\n{\nprivate:\n\tconst RuleEvent &_rule;\n\tsize_t _spawnCountdown;\n\tbool _over;\npublic:\n\t/// Creates a blank GeoscapeEvent.\n\tGeoscapeEvent(const RuleEvent &rule);\n\t/// Cleans up the event info.\n\t~GeoscapeEvent();\n\t/// Loads the event from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader);\n\t/// Saves the event to YAML.\n\tvoid save(YAML::YamlNodeWriter writer) const;\n\t/// Gets the event's ruleset.\n\tconst RuleEvent &getRules() const { return _rule; };\n\t/// Gets the minutes until the event pops up.\n\tsize_t getSpawnCountdown() const { return _spawnCountdown; }\n\t/// Sets the minutes until the event pops up.\n\tvoid setSpawnCountdown(size_t minutes);\n\n\t/// Is this event over?\n\tbool isOver() const { return _over; }\n\t/// Handle event spawning schedule.\n\tvoid think();\n};\n\n}\n"
  },
  {
    "path": "src/Savegame/HitLog.cpp",
    "content": "/*\n * Copyright 2010-2019 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"HitLog.h\"\n#include \"../Engine/Language.h\"\n#include <regex>\n\nnamespace OpenXcom\n{\n\nHitLog::HitLog(Language *lang) : _lastEventType(HITLOG_EMPTY), _lastFaction(FACTION_PLAYER)\n{\n\t// cache\n\t_newTurn = lang->getString(\"STR_HIT_LOG_NEW_TURN\");\n\t_reactionFire = lang->getString(\"STR_HIT_LOG_REACTION_FIRE\");\n\t_newShot = lang->getString(\"STR_HIT_LOG_NEW_BULLET\");\n\t_noDamage = lang->getString(\"STR_HIT_LOG_NO_DAMAGE\");\n\t_smallDamage = lang->getString(\"STR_HIT_LOG_SMALL_DAMAGE\");\n\t_bigDamage = lang->getString(\"STR_HIT_LOG_BIG_DAMAGE\");\n}\n\n/**\n * Clears the hit log. And updates the turn diary.\n */\nvoid HitLog::clearHitLog(bool resetTurnDiary, bool ignoreLastEntry)\n{\n\tif (resetTurnDiary)\n\t{\n\t\t_turnDiary.clear();\n\t}\n\telse if (!ignoreLastEntry)\n\t{\n\t\t_turnDiary.push_back(getHitLogText(true));\n\t}\n\n\t_ss.str(std::string());\n\t_ss.clear();\n}\n\n/**\n * Appends a given entry to the hit log.\n * @param type Type of hit log entry.\n * @param faction Faction of the actor.\n */\nvoid HitLog::appendToHitLog(HitLogEntryType type, UnitFaction faction)\n{\n\tswitch (type)\n\t{\n\tcase HITLOG_NEW_TURN:\n\t\tclearHitLog(true);\n\t\t_ss << _newTurn;\n\t\tbreak;\n\tcase HITLOG_REACTION_FIRE:\n\t\tif (_lastEventType != HITLOG_REACTION_FIRE) // don't produce duplicates\n\t\t{\n\t\t\tclearHitLog(false);\n\t\t\t_ss << _reactionFire;\n\t\t\t_ss << \"\\n\\n\";\n\t\t}\n\t\tbreak;\n\tcase HITLOG_NEW_SHOT:\n\t\tif (_lastFaction != faction && faction == FACTION_PLAYER)\n\t\t{\n\t\t\t// player continues shooting (without selecting a weapon) after enemy reaction fire\n\t\t\tclearHitLog(false);\n\t\t\t_ss << _lastPlayerWeapon; // this is why we needed to remember it :)\n\t\t\t_ss << \"\\n\\n\";\n\t\t}\n\t\t_ss << _newShot;\n\t\tbreak;\n\tcase HITLOG_NO_DAMAGE:\n\t\t_ss << _noDamage;\n\t\tbreak;\n\tcase HITLOG_SMALL_DAMAGE:\n\t\t_ss << _smallDamage;\n\t\tbreak;\n\tcase HITLOG_BIG_DAMAGE:\n\t\t_ss << _bigDamage;\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n\n\t_lastEventType = type;\n\t_lastFaction = faction;\n}\n\n/**\n * Appends a given entry to the hit log.\n * @param type Type of hit log entry.\n * @param faction Faction of the actor.\n * @param text Text to append.\n */\nvoid HitLog::appendToHitLog(HitLogEntryType type, UnitFaction faction, const std::string &text)\n{\n\tswitch (type)\n\t{\n\tcase HITLOG_NEW_TURN_WITH_MESSAGE:\n\t\tclearHitLog(true);\n\t\t_ss << text;\n\t\tbreak;\n\tcase HITLOG_PLAYER_FIRING:\n\t\tclearHitLog(false, _lastEventType == HITLOG_PLAYER_FIRING); // don't produce duplicates and irrelevant diary entries\n\t\t_lastPlayerWeapon = text; // remember this, we may need it again if we are interrupted by reaction fire\n\t\t_ss << _lastPlayerWeapon;\n\t\t_ss << \"\\n\\n\";\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n\n\t_lastEventType = type;\n\t_lastFaction = faction;\n}\n\n/**\n * Gets the hit log text.\n * @param convert Convert line breaks to spaces?\n * @return hit log text.\n */\nstd::string HitLog::getHitLogText(bool convert) const\n{\n\tif (convert)\n\t{\n\t\treturn std::regex_replace(_ss.str(), std::regex(\"\\n\"), \" \");\n\t}\n\treturn _ss.str();\n}\n\n}\n"
  },
  {
    "path": "src/Savegame/HitLog.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2019 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include <sstream>\n#include <vector>\n#include \"BattleUnit.h\"\n\nnamespace OpenXcom\n{\n\nenum HitLogEntryType : int\n{\n\tHITLOG_EMPTY,\n\tHITLOG_NEW_TURN,\n\tHITLOG_NEW_TURN_WITH_MESSAGE,\n\tHITLOG_PLAYER_FIRING,\n\tHITLOG_REACTION_FIRE,\n\tHITLOG_NEW_SHOT,\n\tHITLOG_NO_DAMAGE,\n\tHITLOG_SMALL_DAMAGE,\n\tHITLOG_BIG_DAMAGE\n};\n\nclass Language;\n\nclass HitLog\n{\nprivate:\n\tstd::ostringstream _ss;\n\tstd::vector<std::string> _turnDiary;\n\n\tstd::string _newTurn, _reactionFire, _newShot, _noDamage, _smallDamage, _bigDamage;\n\n\tHitLogEntryType _lastEventType;\n\tUnitFaction _lastFaction;\n\tstd::string _lastPlayerWeapon;\n\n\t/// Clears the hit log. And updates the turn diary.\n\tvoid clearHitLog(bool resetTurnDiary, bool ignoreLastEntry = false);\n\npublic:\n\t/// Creates a new hit log.\n\tHitLog(Language *lang);\n\t/// Appends the given text to the hit log.\n\tvoid appendToHitLog(HitLogEntryType type, UnitFaction faction);\n\tvoid appendToHitLog(HitLogEntryType type, UnitFaction faction, const std::string &text);\n\t/// Gets the hit log text.\n\tstd::string getHitLogText(bool convert = false) const;\n\t/// Gets the turn diary.\n\tconst std::vector<std::string> &getTurnDiary() const { return _turnDiary; }\n};\n\n}\n"
  },
  {
    "path": "src/Savegame/ItemContainer.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ItemContainer.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleItem.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes an item container with no contents.\n */\nItemContainer::ItemContainer()\n{\n}\n\n/**\n *\n */\nItemContainer::~ItemContainer()\n{\n}\n\n/**\n * Loads the item container from a YAML file.\n * @param node YAML node.\n */\nvoid ItemContainer::load(const YAML::YamlNodeReader& reader, const Mod* mod)\n{\n\tif (!reader || !reader.isMap())\n\t\treturn;\n\t_qty.clear();\n\tfor (const auto& item : reader.children())\n\t{\n\t\tstd::string name = item.readKey<std::string>();\n\t\tconst auto* type = mod->getItem(name);\n\t\tif (type)\n\t\t{\n\t\t\t_qty[type] = item.readVal<int>();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"Failed to load item \" << name;\n\t\t}\n\t}\n}\n\n/**\n * Saves the item container to a YAML file.\n * @return YAML node.\n */\nvoid ItemContainer::save(YAML::YamlNodeWriter writer) const\n{\n\twriter.setAsMap();\n\t// item containers are sorted alphabetically in the yaml mapping\n\tstd::vector<std::pair<std::string, int>> sortedItems;\n\tsortedItems.reserve(_qty.size());\n\tfor (auto& pair : _qty)\n\t\tsortedItems.push_back(std::make_pair(pair.first->getType(), pair.second));\n\tstd::sort(sortedItems.begin(), sortedItems.end(), [](auto& a, auto& b){ return a < b; });\n\tfor (auto& pair : sortedItems)\n\t\twriter.write(writer.saveString(pair.first), pair.second);\n}\n\n/**\n * Adds an item amount to the container.\n * @param id Item ID.\n * @param qty Item quantity.\n */\nvoid ItemContainer::addItem(const RuleItem* item, int qty)\n{\n\tif (item)\n\t{\n\t\t_qty[item] += qty;\n\t}\n}\n\n/**\n * Removes an item amount from the container.\n * @param id Item ID.\n * @param qty Item quantity.\n */\nvoid ItemContainer::removeItem(const std::string &id, int qty)\n{\n\tif (Mod::isEmptyRuleName(id))\n\t{\n\t\treturn;\n\t}\n\tauto it = std::find_if(_qty.begin(), _qty.end(), [&](auto& pair) { return pair.first->getType() == id; });\n\tif (it == _qty.end())\n\t{\n\t\treturn;\n\t}\n\n\tif (qty < it->second)\n\t{\n\t\tit->second -= qty;\n\t}\n\telse\n\t{\n\t\t_qty.erase(it);\n\t}\n}\n\n/**\n * Removes an item amount from the container.\n * @param id Item ID.\n * @param qty Item quantity.\n */\nvoid ItemContainer::removeItem(const RuleItem* item, int qty)\n{\n\tif (item)\n\t{\n\t\tauto it = _qty.find(item);\n\t\tif (it == _qty.end())\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tif (qty < it->second)\n\t\t{\n\t\t\tit->second -= qty;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_qty.erase(it);\n\t\t}\n\t}\n}\n\n/**\n * Returns the quantity of an item in the container.\n * @param id Item ID.\n * @return Item quantity.\n */\nint ItemContainer::getItem(const std::string &id) const\n{\n\tif (Mod::isEmptyRuleName(id))\n\t{\n\t\treturn 0;\n\t}\n\n\tauto it = std::find_if(_qty.begin(), _qty.end(), [&](auto& pair) { return pair.first->getType() == id; });\n\tif (it == _qty.end())\n\t{\n\t\treturn 0;\n\t}\n\telse\n\t{\n\t\treturn it->second;\n\t}\n}\n\n/**\n * Returns the quantity of an item in the container.\n * @param id Item ID.\n * @return Item quantity.\n */\nint ItemContainer::getItem(const RuleItem* item) const\n{\n\tif (item)\n\t{\n\t\tauto it = _qty.find(item);\n\t\tif (it == _qty.end())\n\t\t{\n\t\t\treturn 0;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn it->second;\n\t\t}\n\t}\n\telse\n\t{\n\t\treturn 0;\n\t}\n}\n\n/**\n * Returns the total quantity of the items in the container.\n * @return Total item quantity.\n */\nint ItemContainer::getTotalQuantity() const\n{\n\tint total = 0;\n\tfor (const auto& pair : _qty)\n\t{\n\t\ttotal += pair.second;\n\t}\n\treturn total;\n}\n\n/**\n * Returns the total size of the items in the container.\n * @return Total item size.\n */\ndouble ItemContainer::getTotalSize() const\n{\n\tdouble total = 0;\n\tfor (const auto& pair : _qty)\n\t{\n\t\ttotal += pair.first->getSize() * pair.second;\n\t}\n\treturn total;\n}\n\n/**\n * Returns all the items currently contained within.\n * @return List of contents.\n */\nconst std::map<const RuleItem*, int> *ItemContainer::getContents() const\n{\n\treturn &_qty;\n}\n\n}\n"
  },
  {
    "path": "src/Savegame/ItemContainer.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include <map>\n#include \"../Engine/Yaml.h\"\n\nnamespace OpenXcom\n{\n\nclass Mod;\nclass RuleItem;\n\n/**\n * Represents the items contained by a certain entity,\n * like base stores, craft equipment, etc.\n * Handles all necessary item management tasks.\n */\nclass ItemContainer\n{\nprivate:\n\tstd::map<const RuleItem*, int> _qty;\npublic:\n\t/// Creates an empty item container.\n\tItemContainer();\n\t/// Cleans up the item container.\n\t~ItemContainer();\n\t/// Loads the item container from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader, const Mod* mod);\n\t/// Saves the item container to YAML.\n\tvoid save(YAML::YamlNodeWriter writer) const;\n\t/// Adds an item to the container.\n\tvoid addItem(const std::string &id, int qty = 1) = delete;\n\t/// Adds an item to the container.\n\tvoid addItem(const RuleItem* item, int qty = 1);\n\t/// Removes an item from the container.\n\tvoid removeItem(const std::string &id, int qty = 1);\n\t/// Removes an item from the container.\n\tvoid removeItem(const RuleItem* item, int qty = 1);\n\t/// Gets an item in the container.\n\tint getItem(const std::string &id) const;\n\t/// Gets an item in the container.\n\tint getItem(const RuleItem* item) const;\n\t/// Gets the total quantity of items in the container.\n\tint getTotalQuantity() const;\n\t/// Gets the total size of items in the container.\n\tdouble getTotalSize() const;\n\t/// Check if have any item\n\tbool empty() const { return _qty.empty(); }\n\t/// Clear all content.\n\tvoid clear() { _qty.clear(); }\n\t/// Gets all the items in the container.\n\tconst std::map<const RuleItem*, int> *getContents() const;\n};\n\n}\n"
  },
  {
    "path": "src/Savegame/MissionSite.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"MissionSite.h\"\n#include \"Ufo.h\"\n#include \"../Engine/Language.h\"\n#include \"../Mod/RuleAlienMission.h\"\n#include \"../Mod/AlienDeployment.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes a mission site.\n */\nMissionSite::MissionSite(const RuleAlienMission *rules, const AlienDeployment *deployment, const AlienDeployment *alienCustomDeploy) : Target(),\n\t_rules(rules), _deployment(deployment), _missionCustomDeploy(alienCustomDeploy),\n\t_texture(-1), _secondsRemaining(0), _inBattlescape(false), _detected(false), _ufo(nullptr), _ufoUniqueId(-1)\n{\n}\n\n/**\n *\n */\nMissionSite::~MissionSite()\n{\n}\n\n/**\n * Loads the mission site from a YAML file.\n * @param node YAML node.\n */\nvoid MissionSite::load(const YAML::YamlNodeReader& reader)\n{\n\tTarget::load(reader);\n\treader.tryRead(\"texture\", _texture);\n\treader.tryRead(\"secondsRemaining\", _secondsRemaining);\n\treader.tryRead(\"race\", _race);\n\treader.tryRead(\"inBattlescape\", _inBattlescape);\n\treader.tryRead(\"detected\", _detected);\n\t//_missionCustomDeploy loaded outside\n\treader.tryRead(\"ufoUniqueId\", _ufoUniqueId);\n\t// _ufo loaded outside\n}\n\n/**\n * Saves the mission site to a YAML file.\n * @return YAML node.\n */\nvoid MissionSite::save(YAML::YamlNodeWriter writer) const\n{\n\twriter.setAsMap();\n\tTarget::save(writer);\n\n\twriter.write(\"type\", _rules->getType());\n\twriter.write(\"deployment\", _deployment->getType());\n\tif (_missionCustomDeploy)\n\t\twriter.write(\"missionCustomDeploy\", _missionCustomDeploy->getType());\n\twriter.write(\"texture\", _texture);\n\tif (_secondsRemaining)\n\t\twriter.write(\"secondsRemaining\", _secondsRemaining);\n\twriter.write(\"race\", _race);\n\tif (_inBattlescape)\n\t\twriter.write(\"inBattlescape\", _inBattlescape);\n\twriter.write(\"detected\", _detected);\n\tif (_ufo)\n\t\twriter.write(\"ufoUniqueId\", _ufo->getUniqueId());\n}\n\n/**\n * Returns the mission's unique type used for\n * savegame purposes.\n * @return ID.\n */\nstd::string MissionSite::getType() const\n{\n\treturn _deployment->getMarkerName();\n}\n\n/**\n * Returns the ruleset for the mission's type.\n * @return Pointer to ruleset.\n */\nconst RuleAlienMission *MissionSite::getRules() const\n{\n\treturn _rules;\n}\n\n/**\n * Returns the ruleset for the mission's deployment.\n * @return Pointer to deployment rules.\n */\nconst AlienDeployment *MissionSite::getDeployment() const\n{\n\treturn _deployment;\n}\n\n/**\n * Get mission's custom deployment of weapons.\n * @return Aline deployment.\n */\nconst AlienDeployment *MissionSite::getMissionCustomDeploy() const\n{\n\treturn _missionCustomDeploy;\n}\n\n/**\n * Returns the name on the globe for the mission.\n * @return String ID.\n */\nstd::string MissionSite::getMarkerName() const\n{\n\treturn getType();\n}\n\n/**\n * Returns the globe marker for the mission site.\n * @return Marker sprite, -1 if none.\n */\nint MissionSite::getMarker() const\n{\n\tif (!_detected)\n\t\treturn -1;\n\tif (_deployment->getMarkerIcon() == -1)\n\t\treturn 5;\n\treturn _deployment->getMarkerIcon();\n}\n\n/**\n * Returns the number of seconds remaining before the mission site expires.\n * @return Amount of seconds.\n */\nsize_t MissionSite::getSecondsRemaining() const\n{\n\treturn _secondsRemaining;\n}\n\n/**\n * Changes the number of seconds before the mission site expires.\n * @param seconds Amount of seconds.\n */\nvoid MissionSite::setSecondsRemaining(size_t seconds)\n{\n\t_secondsRemaining = seconds;\n}\n\n/**\n * Returns the alien race currently residing in the mission site.\n * @return Alien race.\n */\nstd::string MissionSite::getAlienRace() const\n{\n\treturn _race;\n}\n\n/**\n * Changes the alien race currently residing in the mission site.\n * @param race Alien race.\n */\nvoid MissionSite::setAlienRace(const std::string &race)\n{\n\t_race = race;\n}\n\n/**\n * Gets the mission site's battlescape status.\n * @return Is the mission currently in battle?\n */\nbool MissionSite::isInBattlescape() const\n{\n\treturn _inBattlescape;\n}\n\n/**\n * Sets the mission site's battlescape status.\n * @param inbattle True if it's in battle, False otherwise.\n */\nvoid MissionSite::setInBattlescape(bool inbattle)\n{\n\t_inBattlescape = inbattle;\n}\n\n/**\n * Gets the mission site's associated texture.\n * @return Texture ID.\n */\nint MissionSite::getTexture() const\n{\n\treturn _texture;\n}\n\n/**\n * Sets the mission site's associated texture.\n * @param texture Texture ID.\n */\nvoid MissionSite::setTexture(int texture)\n{\n\t_texture = texture;\n}\n\n/**\n * Gets the mission site's associated city, if any.\n * @return String ID for the city, \"\" if none.\n */\nconst std::string& MissionSite::getCity() const\n{\n\treturn _city;\n}\n\n/**\n * Sets the mission site's associated city, if any.\n * @param city String ID for the city, \"\" if none.\n */\nvoid MissionSite::setCity(const std::string &city)\n{\n\t_city = city;\n}\n\n/**\n * Gets the detection state for this mission site.\n * used for popups of sites spawned directly rather than by UFOs.\n * @return whether or not this site has been detected.\n */\nbool MissionSite::getDetected() const\n{\n\treturn _detected;\n}\n\n/**\n * Sets the mission site's detection state.\n * @param detected whether we want this site to show on the geoscape or not.\n */\nvoid MissionSite::setDetected(bool detected)\n{\n\t_detected = detected;\n}\n\n}\n"
  },
  {
    "path": "src/Savegame/MissionSite.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Target.h\"\n#include <string>\n#include \"../Engine/Yaml.h\"\n\nnamespace OpenXcom\n{\n\nclass RuleAlienMission;\nclass AlienDeployment;\nclass Ufo;\n\n/**\n * Represents an alien mission site on the world.\n */\nclass MissionSite : public Target\n{\nprivate:\n\tconst RuleAlienMission *_rules;\n\tconst AlienDeployment *_deployment;\n\tconst AlienDeployment *_missionCustomDeploy;\n\tint _texture;\n\tsize_t _secondsRemaining;\n\tstd::string _race, _city;\n\tbool _inBattlescape, _detected;\n\tUfo* _ufo;\n\tint _ufoUniqueId;\npublic:\n\t/// Creates a mission site.\n\tMissionSite(const RuleAlienMission *rules, const AlienDeployment *deployment, const AlienDeployment *alienWeaponDeploy);\n\t/// Cleans up the mission site.\n\t~MissionSite();\n\t/// Loads the mission site from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader) override;\n\t/// Saves the mission site to YAML.\n\tvoid save(YAML::YamlNodeWriter writer) const override;\n\t/// Gets the waypoint's type.\n\tstd::string getType() const override;\n\t/// Gets the mission site's ruleset.\n\tconst RuleAlienMission *getRules() const;\n\t/// Gets the mission site's deployment.\n\tconst AlienDeployment *getDeployment() const;\n\t/// Gets the optional alien weapon deployment for site.\n\tconst AlienDeployment *getMissionCustomDeploy() const;\n\t/// Gets the mission site's marker name.\n\tstd::string getMarkerName() const override;\n\t/// Gets the mission site's marker sprite.\n\tint getMarker() const override;\n\t/// Gets the seconds until this mission site expires.\n\tsize_t getSecondsRemaining() const;\n\t/// Sets the seconds until this mission site expires.\n\tvoid setSecondsRemaining(size_t seconds);\n\t/// Gets the mission site's alien race.\n\tstd::string getAlienRace() const;\n\t/// Sets the mission site's alien race.\n\tvoid setAlienRace(const std::string &race);\n\t/// Sets the mission site's battlescape status.\n\tvoid setInBattlescape(bool inbattle);\n\t/// Gets if the mission site is in battlescape.\n\tbool isInBattlescape() const;\n\t/// Gets the mission site's texture.\n\tint getTexture() const;\n\t/// Sets the mission site's texture.\n\tvoid setTexture(int texture);\n\t/// Gets the mission site's city.\n\tconst std::string& getCity() const;\n\t/// Sets the mission site's city.\n\tvoid setCity(const std::string &city);\n\t/// Gets the mission site's detection state.\n\tbool getDetected() const;\n\t/// Sets the mission site's detection state.\n\tvoid setDetected(bool detected);\n\t/// Gets the mission site's corresponding Ufo.\n\tUfo* getUfo() const { return _ufo; }\n\t/// Sets the mission site's corresponding Ufo.\n\tvoid setUfo(Ufo* ufo) { _ufo = ufo; }\n\t/// DO NOT USE! Used only for loading saved games.\n\tint getUfoUniqueId() const { return _ufoUniqueId; }\n};\n\n}\n"
  },
  {
    "path": "src/Savegame/MissionStatistics.h",
    "content": "#pragma once\n/*\n* Copyright 2010-2016 OpenXcom Developers.\n*\n* This file is part of OpenXcom.\n*\n* OpenXcom is free software: you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation, either version 3 of the License, or\n* (at your option) any later version.\n*\n* OpenXcom is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*\n* You should have received a copy of the GNU General Public License\n* along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n*/\n#include \"../Engine/Yaml.h\"\n#include <map>\n#include <string>\n#include <sstream>\n#include \"GameTime.h\"\n#include \"../Engine/Language.h\"\n#include \"../Mod/Mod.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Container for mission statistics.\n */\nstruct MissionStatistics\n{\n\t// Variables\n\tint id;\n\tstd::string markerName;\n\tint markerId;\n\tGameTime time;\n\tstd::string region, country, type, ufo;\n\tbool success;\n\tstd::string rating;\n\tint score;\n\tstd::string alienRace;\n\tint daylight;\n\tstd::map<int, int> injuryList;\n\tbool valiantCrux;\n\tint lootValue;\n\n\t/// Load\n\tvoid load(const YAML::YamlNodeReader& reader)\n\t{\n\t\treader.tryRead(\"id\", id);\n\t\treader.tryRead(\"markerName\", markerName);\n\t\treader.tryRead(\"markerId\", markerId);\n\t\ttime.load(reader[\"time\"]);\n\t\treader.tryRead(\"region\", region);\n\t\treader.tryRead(\"country\", country);\n\t\treader.tryRead(\"type\", type);\n\t\treader.tryRead(\"ufo\", ufo);\n\t\treader.tryRead(\"success\", success);\n\t\treader.tryRead(\"score\", score);\n\t\treader.tryRead(\"rating\", rating);\n\t\treader.tryRead(\"alienRace\", alienRace);\n\t\treader.tryRead(\"daylight\", daylight);\n\t\treader.tryRead(\"injuryList\", injuryList);\n\t\treader.tryRead(\"valiantCrux\", valiantCrux);\n\t\treader.tryRead(\"lootValue\", lootValue);\n\t}\n\n\t/// Save\n\tvoid save(YAML::YamlNodeWriter writer) const\n\t{\n\t\twriter.setAsMap();\n\t\twriter.write(\"id\", id);\n\t\tif (!markerName.empty())\n\t\t{\n\t\t\twriter.write(\"markerName\", markerName);\n\t\t\twriter.write(\"markerId\", markerId);\n\t\t}\n\t\ttime.save(writer[\"time\"]);\n\t\twriter.write(\"region\", region);\n\t\twriter.write(\"country\", country);\n\t\twriter.write(\"type\", type);\n\t\twriter.write(\"ufo\", ufo);\n\t\twriter.write(\"success\", success);\n\t\twriter.write(\"score\", score);\n\t\twriter.write(\"rating\", rating);\n\t\twriter.write(\"alienRace\", alienRace);\n\t\twriter.write(\"daylight\", daylight);\n\t\tif (!injuryList.empty())\n\t\t\twriter.write(\"injuryList\", injuryList);\n\t\tif (valiantCrux) writer.write(\"valiantCrux\", valiantCrux);\n\t\tif (lootValue) writer.write(\"lootValue\", lootValue);\n\t}\n\n\tstd::string getMissionName(Language *lang) const\n\t{\n\t\tif (!markerName.empty())\n\t\t{\n\t\t\treturn lang->getString(markerName).arg(markerId);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn lang->getString(type);\n\t\t}\n\t}\n\n\tstd::string getRatingString(Language *lang) const\n\t{\n\t\tstd::ostringstream ss;\n\t\tif (success)\n\t\t{\n\t\t\tss << lang->getString(\"STR_VICTORY\");\n\t\t}\n\t\telse\n\t\t{\n\t\t\tss << lang->getString(\"STR_DEFEAT\");\n\t\t}\n\t\tss << \" - \" << lang->getString(rating);\n\t\treturn ss.str();\n\t}\n\n\tstd::string getLocationString() const\n\t{\n\t\tif (country == \"STR_UNKNOWN\")\n\t\t{\n\t\t\treturn region;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn country;\n\t\t}\n\t}\n\n\tbool isDarkness(const Mod* mod) const\n\t{\n\t\treturn daylight > mod->getMaxDarknessToSeeUnits();\n\t}\n\n\tstd::string getDaylightString(const Mod* mod) const\n\t{\n\t\tif (isDarkness(mod))\n\t\t{\n\t\t\treturn \"STR_NIGHT\";\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn \"STR_DAY\";\n\t\t}\n\t}\n\n\tbool isAlienBase() const\n\t{\n\t\tif (type.find(\"STR_ALIEN_BASE\") != std::string::npos || type.find(\"STR_ALIEN_COLONY\") != std::string::npos)\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tbool isBaseDefense() const\n\t{\n\t\tif (type == \"STR_BASE_DEFENSE\")\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tbool isUfoMission() const\n\t{\n\t\tif(ufo != \"NO_UFO\")\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tMissionStatistics(const YAML::YamlNodeReader& reader) : time(0, 0, 0, 0, 0, 0, 0) { load(reader); }\n\tMissionStatistics() : id(0), markerId(0), time(0, 0, 0, 0, 0, 0, 0), region(\"STR_REGION_UNKNOWN\"), country(\"STR_UNKNOWN\"), ufo(\"NO_UFO\"), success(false), score(0), alienRace(\"STR_UNKNOWN\"), daylight(0), valiantCrux(false), lootValue(0) { }\n\t~MissionStatistics() { }\n};\n\n}\n"
  },
  {
    "path": "src/Savegame/MovingTarget.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"MovingTarget.h\"\n#include \"../fmath.h\"\n#include \"SerializationHelper.h\"\n#include \"../Engine/Options.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes a moving target with blank coordinates.\n */\nMovingTarget::MovingTarget() : Target(), _dest(0), _speedLon(0.0), _speedLat(0.0), _speedRadian(0.0), _meetPointLon(0.0), _meetPointLat(0.0), _speed(0), _meetCalculated(false)\n{\n}\n\n/**\n * Make sure to cleanup the target's destination followers.\n */\nMovingTarget::~MovingTarget()\n{\n\tsetDestination(0);\n}\n\n/**\n * Loads the moving target from a YAML file.\n * @param node YAML node.\n */\nvoid MovingTarget::load(const YAML::YamlNodeReader& reader)\n{\n\tTarget::load(reader);\n\treader.tryRead(\"speedLon\", _speedLon);\n\treader.tryRead(\"speedLat\", _speedLat);\n\treader.tryRead(\"speedRadian\", _speedRadian);\n\treader.tryRead(\"speed\", _speed);\n}\n\n/**\n * Saves the moving target to a YAML file.\n * @return YAML node.\n */\nvoid MovingTarget::save(YAML::YamlNodeWriter writer) const\n{\n\twriter.setAsMap();\n\tTarget::save(writer);\n\tif (_dest)\n\t\t_dest->saveId(writer[\"dest\"]);\n\twriter.write(\"speedLon\", serializeDouble(_speedLon));\n\twriter.write(\"speedLat\", serializeDouble(_speedLat));\n\twriter.write(\"speedRadian\", serializeDouble(_speedRadian));\n\twriter.write(\"speed\", _speed);\n}\n\n/**\n * Returns the destination the moving target is heading to.\n * @return Pointer to destination.\n */\nTarget *MovingTarget::getDestination() const\n{\n\treturn _dest;\n}\n\n/**\n * Changes the destination the moving target is heading to.\n * @param dest Pointer to destination.\n */\nvoid MovingTarget::setDestination(Target *dest)\n{\n\t_meetCalculated = false;\n\t// Remove moving target from old destination's followers\n\tif (_dest != 0)\n\t{\n\t\tfor (auto iter = _dest->getFollowers()->begin(); iter != _dest->getFollowers()->end(); ++iter)\n\t\t{\n\t\t\tif ((*iter) == this)\n\t\t\t{\n\t\t\t\t_dest->getFollowers()->erase(iter);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\t_dest = dest;\n\t// Add moving target to new destination's followers\n\tif (_dest != 0)\n\t{\n\t\t_dest->getFollowers()->push_back(this);\n\t}\n\t// Recalculate meeting point for any followers\n\tfor (auto* mt : *getFollowers())\n\t{\n\t\tmt->resetMeetPoint();\n\t}\n\tcalculateSpeed();\n}\n\n/**\n * Returns the speed of the moving target.\n * @return Speed in knots.\n */\nint MovingTarget::getSpeed() const\n{\n\treturn _speed;\n}\n\n/**\n * Returns the radial speed of the moving target.\n * @return Speed in 1 / 5 sec.\n */\ndouble MovingTarget::getSpeedRadian() const\n{\n\treturn _speedRadian;\n}\n\n/**\n * Converts a speed in degrees to a speed in radians.\n * Each nautical mile is 1/60th of a degree.\n * Each hour contains 720 5-seconds.\n * @param speed Speed in degrees.\n * @return Speed in radians.\n */\ndouble MovingTarget::calculateRadianSpeed(int speed)\n{\n\treturn Nautical(speed) / 720.0;\n}\n\n/**\n * Changes the speed of the moving target\n * and converts it from standard knots (nautical miles per hour)\n * into radians per 5 in-game seconds.\n * @param speed Speed in knots.\n */\nvoid MovingTarget::setSpeed(int speed)\n{\n\t_speed = speed;\n\t_speedRadian = calculateRadianSpeed(_speed);\n\t// Recalculate meeting point for any followers\n\tfor (auto* mt : *getFollowers())\n\t{\n\t\tmt->resetMeetPoint();\n\t}\n\tcalculateSpeed();\n}\n\n/**\n * Calculates the speed vector based on the\n * great circle distance to destination and\n * current raw speed.\n */\nvoid MovingTarget::calculateSpeed()\n{\n\tcalculateMeetPoint();\n\tif (_dest != 0)\n\t{\n\t\tdouble dLon, dLat, length;\n\t\tdLon = sin(_meetPointLon - _lon) * cos(_meetPointLat);\n\t\tdLat = cos(_lat) * sin(_meetPointLat) - sin(_lat) * cos(_meetPointLat) * cos(_meetPointLon - _lon);\n\t\tlength = sqrt(dLon * dLon + dLat * dLat);\n\t\t_speedLat = dLat / length * _speedRadian;\n\t\t_speedLon = dLon / length * _speedRadian / cos(_lat + _speedLat);\n\n\t\t// Check for invalid speeds when a division by zero occurs due to near-zero values\n\t\tif (!(_speedLon == _speedLon) || !(_speedLat == _speedLat))\n\t\t{\n\t\t\t_speedLon = 0;\n\t\t\t_speedLat = 0;\n\t\t}\n\t}\n\telse\n\t{\n\t\t_speedLon = 0;\n\t\t_speedLat = 0;\n\t}\n}\n\n/**\n * Checks if the moving target has reached its destination.\n * @return True if it has, False otherwise.\n */\nbool MovingTarget::reachedDestination() const\n{\n\tif (_dest == 0)\n\t{\n\t\treturn false;\n\t}\n\treturn ( AreSame(_dest->getLongitude(), _lon) && AreSame(_dest->getLatitude(), _lat) );\n}\n\n/**\n * Executes a movement cycle for the moving target.\n */\nvoid MovingTarget::move()\n{\n\tcalculateSpeed();\n\tif (_dest != 0)\n\t{\n\t\tif (getDistance(_meetPointLon, _meetPointLat) > _speedRadian)\n\t\t{\n\t\t\tsetLongitude(_lon + _speedLon);\n\t\t\tsetLatitude(_lat + _speedLat);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (getDistance(_dest) > _speedRadian)\n\t\t\t{\n\t\t\t\tsetLongitude(_meetPointLon);\n\t\t\t\tsetLatitude(_meetPointLat);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tsetLongitude(_dest->getLongitude());\n\t\t\t\tsetLatitude(_dest->getLatitude());\n\t\t\t}\n\t\t\tresetMeetPoint();\n\t\t}\n\t}\n}\n\n/**\n * Calculate meeting point with the target.\n */\nvoid MovingTarget::calculateMeetPoint()\n{\n#if 0\n\tif (!Options::meetingPoint) _meetCalculated = false;\n\tif (_meetCalculated) return;\n#endif\n\t_meetCalculated = false;\n\n\t// Initialize\n\tif (_dest != 0)\n\t{\n\t\t_meetPointLat = _dest->getLatitude();\n\t\t_meetPointLon = _dest->getLongitude();\n\t}\n\telse\n\t{\n\t\t_meetPointLat = _lat;\n\t\t_meetPointLon = _lon;\n\t}\n\n\t// ***IMPORTANT*** this functionality has been disabled until further notice, most probably forever\n#if 0\n\n\tif (!_dest || !Options::meetingPoint || reachedDestination()) return;\n\n\tMovingTarget *t = dynamic_cast<MovingTarget*>(_dest);\n\tif (!t || !t->getDestination()) return;\n\n\t// Speed ratio\n\tif (AreSame(t->getSpeedRadian(), 0.0)) return;\n\tconst double speedRatio = _speedRadian/ t->getSpeedRadian();\n\n\t// The direction pseudovector\n\tdouble\tnx = cos(t->getLatitude())*sin(t->getLongitude())*sin(t->getDestination()->getLatitude()) -\n\t\t\t\t\tsin(t->getLatitude())*cos(t->getDestination()->getLatitude())*sin(t->getDestination()->getLongitude()),\n\t\t\tny = sin(t->getLatitude())*cos(t->getDestination()->getLatitude())*cos(t->getDestination()->getLongitude()) -\n\t\t\t\t\tcos(t->getLatitude())*cos(t->getLongitude())*sin(t->getDestination()->getLatitude()),\n\t\t\tnz = cos(t->getLatitude())*cos(t->getDestination()->getLatitude())*sin(t->getDestination()->getLongitude() - t->getLongitude());\n\t// Normalize and multiplex with radian speed\n\tdouble\tnk = _speedRadian/sqrt(nx*nx+ny*ny+nz*nz);\n\tnx *= nk;\n\tny *= nk;\n\tnz *= nk;\n\n\t// Finding the meeting point. Don't search further than halfway across the\n\t// globe (distance from interceptor's current point >= 1), as that may\n\t// cause the interceptor to go the wrong way later.\n\tfor (double path = 0, distance = 1;\n\t\tpath < M_PI && distance - path*speedRatio > 0 && path*speedRatio < 1;\n\t\tpath += _speedRadian)\n\t{\n\t\t_meetPointLat += nx*sin(_meetPointLon) - ny*cos(_meetPointLon);\n\t\tif (std::abs(_meetPointLat) < M_PI_2) _meetPointLon += nz - (nx*cos(_meetPointLon) + ny*sin(_meetPointLon))*tan(_meetPointLat); else _meetPointLon += M_PI;\n\n\t\tdistance = acos(cos(_lat) * cos(_meetPointLat) * cos(_meetPointLon - _lon) + sin(_lat) * sin(_meetPointLat));\n\t}\n\n\t// Correction overflowing angles\n\tdouble lonSign = Sign(_meetPointLon);\n\tdouble latSign = Sign(_meetPointLat);\n\twhile (std::abs(_meetPointLon) > M_PI) _meetPointLon -= lonSign * 2 * M_PI;\n\twhile (std::abs(_meetPointLat) > M_PI) _meetPointLat -= latSign * 2 * M_PI;\n\tif (std::abs(_meetPointLat) > M_PI_2) { _meetPointLat = latSign * std::abs(2 * M_PI - std::abs(_meetPointLat)); _meetPointLon -= lonSign * M_PI; }\n\n\t_meetCalculated = true;\n#endif\n}\n\n/**\n * Returns the latitude of the meeting point.\n * @return Angle in rad.\n */\ndouble MovingTarget::getMeetLatitude() const\n{\n\treturn _meetPointLat;\n}\n\n/**\n * Returns the longitude of the meeting point.\n * @return Angle in rad.\n */\ndouble MovingTarget::getMeetLongitude() const\n{\n\treturn _meetPointLon;\n}\n\n/**\n * Forces the meeting point to be recalculated in the event\n * that the target has changed direction.\n */\nvoid MovingTarget::resetMeetPoint()\n{\n\t_meetCalculated = false;\n}\n\nbool MovingTarget::isMeetCalculated() const\n{\n\treturn _meetCalculated;\n}\n\n}\n"
  },
  {
    "path": "src/Savegame/MovingTarget.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Target.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Base class for moving targets on the globe\n * with a certain speed and destination.\n */\nclass MovingTarget : public Target\n{\nprotected:\n\tstatic const double GLOBE_RADIUS;\n\n\tTarget *_dest;\n\tdouble _speedLon, _speedLat, _speedRadian;\n\tdouble _meetPointLon, _meetPointLat;\n\tint _speed;\n\tbool _meetCalculated;\n\n\t/// Calculates a new speed vector to the destination.\n\tvirtual void calculateSpeed();\n\t/// Converts a speed to radians.\n\tstatic double calculateRadianSpeed(int speed);\n\t/// Creates a moving target.\n\tMovingTarget();\npublic:\n\t/// Cleans up the moving target.\n\tvirtual ~MovingTarget();\n\t/// Loads the moving target from YAML.\n\tvirtual void load(const YAML::YamlNodeReader& reader) override;\n\t/// Saves the moving target to YAML.\n\tvirtual void save(YAML::YamlNodeWriter writer) const override;\n\t/// Gets the moving target's destination.\n\tTarget *getDestination() const;\n\t/// Sets the moving target's destination.\n\tvirtual void setDestination(Target *dest);\n\t/// Gets the moving target's speed.\n\tint getSpeed() const;\n\t/// Gets the moving target's radial speed.\n\tdouble getSpeedRadian() const;\n\t/// Sets the moving target's speed.\n\tvoid setSpeed(int speed);\n\t/// Has the moving target reached its destination?\n\tbool reachedDestination() const;\n\t/// Move towards the destination.\n\tvoid move();\n\t/// Calculate meeting point with the target.\n\tvoid calculateMeetPoint();\n\t/// Returns the latitude of the meeting point.\n\tdouble getMeetLatitude() const;\n\t/// Returns the longitude of the meeting point.\n\tdouble getMeetLongitude() const;\n\t/// Reset meeting point calculation.\n\tvoid resetMeetPoint();\n\t/// Returns if the meeting point was calculated.\n\tbool isMeetCalculated() const;\n};\n\n}\n"
  },
  {
    "path": "src/Savegame/Node.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Node.h\"\n\nnamespace OpenXcom\n{\n\n\nNode::Node() : _id(0), _segment(0), _type(0), _rank(0), _flags(0), _reserved(0), _priority(0), _allocated(false), _dummy(false)\n{\n\n}\n\n/**\n * Initializes a Node.\n * @param id\n * @param pos\n * @param segment\n * @param type\n * @param rank\n * @param flags\n * @param reserved\n * @param priority\n */\nNode::Node(int id, Position pos, int segment, int type, int rank, int flags, int reserved, int priority) : _id(id), _pos(pos), _segment(segment), _type(type), _rank(rank), _flags(flags), _reserved(reserved), _priority(priority), _allocated(false), _dummy(false)\n{\n}\n\n/**\n * clean up node.\n */\nNode::~Node()\n{\n}\n\n\n\n\n/* following data is the order in which certain alien ranks spawn on certain node ranks */\n/* note that they all can fall back to rank 0 nodes - which is scout (outside ufo) */\nconst int Node::nodeRank[8][7] = {\n\t{ 4, 3, 5, 8, 7, 2, 0 }, //commander\n\t{ 4, 3, 5, 8, 7, 2, 0 }, //leader\n\t{ 5, 4, 3, 2, 7, 8, 0 }, //engineer\n\t{ 7, 6, 2, 8, 3, 4, 0 }, //medic\n\t{ 3, 4, 5, 2, 7, 8, 0 }, //navigator\n\t{ 2, 5, 3, 4, 6, 8, 0 }, //soldier\n\t{ 2, 5, 3, 4, 6, 8, 0 }, //terrorist\n\t{ 2, 5, 3, 4, 6, 8, 0 }  }; //also terrorist\n\n\n\n/**\n * Loads the UFO from a YAML file.\n * @param node YAML node.\n */\nvoid Node::load(const YAML::YamlNodeReader& reader)\n{\n\treader.tryRead(\"id\", _id);\n\treader.tryRead(\"position\", _pos);\n\t//reader.tryRead(\"segment\", _segment);\n\treader.tryRead(\"type\", _type);\n\treader.tryRead(\"rank\", _rank);\n\treader.tryRead(\"flags\", _flags);\n\treader.tryRead(\"reserved\", _reserved);\n\treader.tryRead(\"priority\", _priority);\n\treader.tryRead(\"allocated\", _allocated);\n\treader.tryRead(\"links\", _nodeLinks);\n\treader.tryRead(\"dummy\", _dummy);\n}\n\n/**\n * Saves the UFO to a YAML file.\n * @return YAML node.\n */\nvoid Node::save(YAML::YamlNodeWriter writer) const\n{\n\twriter.setAsMap();\n\twriter.setFlowStyle();\n\twriter.write(\"id\", _id);\n\twriter.write(\"position\", _pos);\n\t//writer.write(\"segment\", _segment);\n\twriter.write(\"type\", _type);\n\twriter.write(\"rank\", _rank);\n\twriter.write(\"flags\", _flags);\n\twriter.write(\"reserved\", _reserved);\n\twriter.write(\"priority\", _priority);\n\tif (_allocated)\n\t\twriter.write(\"allocated\", _allocated);\n\twriter.write(\"links\", _nodeLinks);\n\tif (_dummy)\n\t\twriter.write(\"dummy\", _dummy);\n}\n\n/**\n * Get the node's id\n * @return unique id\n */\nint Node::getID() const\n{\n\treturn _id;\n}\n\n/**\n * Get the rank of units that can spawn on this node.\n * @return node rank\n */\nNodeRank Node::getRank() const\n{\n\treturn (NodeRank)_rank;\n}\n\n/**\n * Get the priority of this spawnpoint.\n * @return priority\n */\nint Node::getPriority() const\n{\n\treturn _priority;\n}\n\n/**\n * Gets the Node's position.\n * @return position\n */\nPosition Node::getPosition() const\n{\n\treturn _pos;\n}\n\n/**\n * Gets the Node's segment.\n * @return segment\n */\nint Node::getSegment() const\n{\n\treturn _segment;\n}\n\n/// get the node's paths\nstd::vector<int> *Node::getNodeLinks()\n{\n\treturn &_nodeLinks;\n}\n\n/**\n * Gets the Node's type.\n * @return type\n */\nint Node::getType() const\n{\n\treturn _type;\n}\n\nbool Node::isAllocated() const\n{\n\treturn _allocated;\n}\n\nvoid Node::allocateNode()\n{\n\t_allocated = true;\n}\n\nvoid Node::freeNode()\n{\n\t_allocated = false;\n}\n\nbool Node::isTarget() const\n{\n\treturn _reserved == 5;\n}\n\nvoid Node::setType(int type)\n{\n\t_type = type;\n}\n\nvoid Node::setDummy(bool dummy)\n{\n\t_dummy = dummy;\n}\n\nbool Node::isDummy() const\n{\n\treturn _dummy;\n}\n\n}\n"
  },
  {
    "path": "src/Savegame/Node.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Battlescape/Position.h\"\n#include \"../Engine/Yaml.h\"\n\nnamespace OpenXcom\n{\n\nenum NodeRank{NR_SCOUT=0, NR_XCOM, NR_SOLDIER, NR_NAVIGATOR, NR_LEADER, NR_ENGINEER, NR_MISC1, NR_MEDIC, NR_MISC2};\n\n/**\n * Represents a node/spawnpoint in the battlescape, loaded from RMP files.\n * @sa http://www.ufopaedia.org/index.php?title=ROUTES\n */\nclass Node\n{\nprivate:\n\tint _id;\n\tPosition _pos;\n\tint _segment;\n\tstd::vector<int> _nodeLinks;\n\tint _type;      // 19 = Unit type in Mapview 2\n\tint _rank;      // 20 = Node rank in Mapview 2\n\tint _flags;     // 21 = Patrol priority in Mapview 2\n\tint _reserved;  // 22 = Base Attack in Mapview 2\n\tint _priority;  // 23 = Spawn weight in Mapview 2\n\tbool _allocated;\n\tbool _dummy;\npublic:\n\tstatic const int CRAFTSEGMENT = 1000;\n\tstatic const int UFOSEGMENT = 2000;\n\tstatic const int TYPE_FLYING = 0x01; // non-flying unit can not spawn here when this bit is set\n\tstatic const int TYPE_SMALL = 0x02; // large unit can not spawn here when this bit is set\n\tstatic const int TYPE_DANGEROUS = 0x04; // an alien was shot here, stop patrolling to it like an idiot with a death wish\n\tstatic const int nodeRank[8][7]; // maps alien ranks to node (.RMP) ranks\n\t/// Creates a Node.\n\tNode();\n\tNode(int id, Position pos, int segment, int type, int rank, int flags, int reserved, int priority);\n\t/// Cleans up the Node.\n\t~Node();\n\t/// Loads the node from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader);\n\t/// Saves the node to YAML.\n\tvoid save(YAML::YamlNodeWriter writer) const;\n\t/// get the node's id\n\tint getID() const;\n\t/// get the node's paths\n\tstd::vector<int> *getNodeLinks();\n\t/// Gets node's rank.\n\tNodeRank getRank() const;\n\t/// Gets node's priority.\n\tint getPriority() const;\n\t/// Gets the node's position.\n\tPosition getPosition() const;\n\t/// Gets the node's segment.\n\tint getSegment() const;\n\t/// Gets the node's type.\n\tint getType() const;\n\t/// Sets the node's type, surprisingly\n\tvoid setType(int type);\n\t/// gets \"flags\" variable, which is really the patrolling desirability value\n\tint getFlags() const { return _flags; }\n\t/// compares the _flags variables of the nodes (for the purpose of patrol decisions!)\n\tbool operator<(Node &b) const { return _flags < b.getFlags(); };\n\tbool isAllocated() const;\n\tvoid allocateNode();\n\tvoid freeNode();\n\tbool isTarget() const;\n\tvoid setDummy(bool dummy);\n\tbool isDummy() const;\n\n};\n\n}\n"
  },
  {
    "path": "src/Savegame/Production.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Production.h\"\n#include <algorithm>\n#include \"../Engine/Collections.h\"\n#include \"../Mod/RuleManufacture.h\"\n#include \"../Mod/RuleSoldier.h\"\n#include \"Base.h\"\n#include \"SavedGame.h\"\n#include \"Transfer.h\"\n#include \"ItemContainer.h\"\n#include \"Soldier.h\"\n#include \"Craft.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"../Mod/RuleCraft.h\"\n#include \"../Engine/Language.h\"\n#include \"../Engine/RNG.h\"\n#include <climits>\n#include \"BaseFacility.h\"\n\nnamespace OpenXcom\n{\nProduction::Production(const RuleManufacture * rules, int amount) :\n\t_rules(rules), _amount(amount), _infinite(false), _timeSpent(0), _engineers(0), _sell(false), _isFallback(false)\n{\n}\n\nint Production::getAmountTotal() const\n{\n\treturn _amount;\n}\n\nvoid Production::setAmountTotal (int amount)\n{\n\t_amount = amount;\n}\n\nbool Production::getInfiniteAmount() const\n{\n\treturn _infinite;\n}\n\nvoid Production::setInfiniteAmount (bool inf)\n{\n\t_infinite = inf;\n}\n\nint Production::getTimeSpent() const\n{\n\treturn _timeSpent;\n}\n\nvoid Production::setTimeSpent (int done)\n{\n\t_timeSpent = done;\n}\n\nbool Production::isQueuedOnly() const\n{\n\t// no progress made yet and nobody assigned\n\treturn (getTimeSpent() == 0 && getAssignedEngineers() == 0);\n}\n\nint Production::getAssignedEngineers() const\n{\n\treturn _engineers;\n}\n\nvoid Production::setAssignedEngineers (int engineers)\n{\n\t_engineers = engineers;\n}\n\nbool Production::getSellItems() const\n{\n\treturn _sell;\n}\n\nvoid Production::setSellItems (bool sell)\n{\n\t_sell = sell;\n}\n\nbool Production::haveEnoughMoneyForOneMoreUnit(SavedGame * g) const\n{\n\treturn _rules->haveEnoughMoneyForOneMoreUnit(g->getFunds());\n}\n\nbool Production::haveEnoughLivingSpaceForOneMoreUnit(Base * b)\n{\n\tif (_rules->getSpawnedPersonType() != \"\")\n\t{\n\t\t// Note: if the production is running then the space we need is already counted by getUsedQuarters\n\t\tif (b->getAvailableQuarters() < b->getUsedQuarters())\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n}\n\nbool Production::haveEnoughMaterialsForOneMoreUnit(Base * b, const Mod *m) const\n{\n\tfor (const auto& i : _rules->getRequiredItems())\n\t{\n\t\tif (b->getStorageItems()->getItem(i.first) < i.second)\n\t\t\treturn false;\n\t}\n\tfor (const auto& i : _rules->getRequiredCrafts())\n\t{\n\t\tif (b->getCraftCountForProduction(i.first) < i.second)\n\t\t\treturn false;\n\t}\n\treturn true;\n}\n\nproductionProgress_e Production::step(Base * b, SavedGame * g, const Mod *m, Language *lang)\n{\n\tif (_isFallback)\n\t{\n\t\tint availableEngineer = b->getAvailableEngineers();\n\t\tint availableWorkSpace = b->getFreeWorkshops();\n\n\t\tif (isQueuedOnly())\n\t\t{\n\t\t\t// start counting the workshop space now\n\t\t\tavailableWorkSpace -= _rules->getRequiredSpace();\n\t\t}\n\t\tif (availableEngineer > 0 && availableWorkSpace > 0)\n\t\t{\n\t\t\tint change = std::min(availableEngineer, availableWorkSpace);\n\t\t\tsetAssignedEngineers(getAssignedEngineers() + change);\n\t\t\tb->setEngineers(b->getEngineers() - change);\n\t\t}\n\t}\n\n\tint done = getAmountProduced();\n\t_timeSpent += _engineers;\n\n\tif (done < getAmountProduced())\n\t{\n\t\tint produced;\n\t\tif (!getInfiniteAmount())\n\t\t{\n\t\t\tproduced = std::min(getAmountProduced(), _amount) - done; // std::min is required because we don't want to overproduce\n\t\t}\n\t\telse\n\t\t{\n\t\t\tproduced = getAmountProduced() - done;\n\t\t}\n\t\tint count = 0;\n\t\tdo\n\t\t{\n\t\t\tauto* ruleCraft = _rules->getProducedCraft();\n\t\t\tif (ruleCraft)\n\t\t\t{\n\t\t\t\tCraft *craft = new Craft(ruleCraft, b, g->getId(ruleCraft->getType()));\n\t\t\t\tcraft->initFixedWeapons(m);\n\t\t\t\tcraft->checkup();\n\t\t\t\tint transferTimeCraft = std::max(0, _rules->getTransferTimes().size() < 3 ? 0 : _rules->getTransferTimes().at(2));\n\t\t\t\tif (transferTimeCraft > 0)\n\t\t\t\t{\n\t\t\t\t\tTransfer* t = new Transfer(transferTimeCraft);\n\t\t\t\t\tt->setCraft(craft);\n\t\t\t\t\tb->getTransfers()->push_back(t);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tb->getCrafts()->push_back(craft);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tint transferTimeItems = std::max(0, _rules->getTransferTimes().empty() ? 0 : _rules->getTransferTimes().front());\n\t\t\t\tfor (const auto& i : _rules->getProducedItems())\n\t\t\t\t{\n\t\t\t\t\tif (getSellItems())\n\t\t\t\t\t{\n\t\t\t\t\t\tint64_t adjustedSellValue = i.first->getSellCostAdjusted(b, g);\n\t\t\t\t\t\tadjustedSellValue *= i.second;\n\t\t\t\t\t\tg->setFunds(g->getFunds() + adjustedSellValue);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tif (transferTimeItems > 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tTransfer* t = new Transfer(transferTimeItems);\n\t\t\t\t\t\t\tt->setItems(i.first, i.second);\n\t\t\t\t\t\t\tb->getTransfers()->push_back(t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tb->getStorageItems()->addItem(i.first, i.second);\n\t\t\t\t\t\t\tif (i.first->getBattleType() == BT_NONE)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tfor (auto* c : *b->getCrafts())\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tc->reuseItem(i.first);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!_rules->getRandomProducedItems().empty())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_randomProductionInfo[i.first->getType()] += i.second;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Random manufacture\n\t\t\tif (!_rules->getRandomProducedItems().empty())\n\t\t\t{\n\t\t\t\tint transferTimeItems = std::max(0, _rules->getTransferTimes().empty() ? 0 : _rules->getTransferTimes().front());\n\t\t\t\tint totalWeight = 0;\n\t\t\t\tfor (const auto& itemSet : _rules->getRandomProducedItems())\n\t\t\t\t{\n\t\t\t\t\ttotalWeight += itemSet.first;\n\t\t\t\t}\n\t\t\t\t// RNG\n\t\t\t\tint roll = RNG::generate(1, totalWeight);\n\t\t\t\tint runningTotal = 0;\n\t\t\t\tfor (const auto& itemSet : _rules->getRandomProducedItems())\n\t\t\t\t{\n\t\t\t\t\trunningTotal += itemSet.first;\n\t\t\t\t\tif (runningTotal >= roll)\n\t\t\t\t\t{\n\t\t\t\t\t\tfor (const auto& i : itemSet.second)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (transferTimeItems > 0)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tTransfer* t = new Transfer(transferTimeItems);\n\t\t\t\t\t\t\t\tt->setItems(i.first, i.second);\n\t\t\t\t\t\t\t\tb->getTransfers()->push_back(t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tb->getStorageItems()->addItem(i.first, i.second);\n\t\t\t\t\t\t\t\tif (i.first->getBattleType() == BT_NONE)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tfor (auto* c : *b->getCrafts())\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tc->reuseItem(i.first);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t_randomProductionInfo[i.first->getType()] += i.second;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// break outer loop\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Spawn persons (soldiers, engineers, scientists, ...)\n\t\t\tconst std::string &spawnedPersonType = _rules->getSpawnedPersonType();\n\t\t\tif (spawnedPersonType != \"\")\n\t\t\t{\n\t\t\t\tint transferTimePersonnel = std::max(1, _rules->getTransferTimes().size() < 2 ? 24 : _rules->getTransferTimes().at(1));\n\t\t\t\tif (spawnedPersonType == \"STR_SCIENTIST\")\n\t\t\t\t{\n\t\t\t\t\tTransfer *t = new Transfer(transferTimePersonnel);\n\t\t\t\t\tt->setScientists(1);\n\t\t\t\t\tb->getTransfers()->push_back(t);\n\t\t\t\t}\n\t\t\t\telse if (spawnedPersonType == \"STR_ENGINEER\")\n\t\t\t\t{\n\t\t\t\t\tTransfer *t = new Transfer(transferTimePersonnel);\n\t\t\t\t\tt->setEngineers(1);\n\t\t\t\t\tb->getTransfers()->push_back(t);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tRuleSoldier *rule = m->getSoldier(spawnedPersonType);\n\t\t\t\t\tif (rule != 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tTransfer *t = new Transfer(transferTimePersonnel);\n\t\t\t\t\t\tint nationality = g->selectSoldierNationalityByLocation(m, rule, b);\n\t\t\t\t\t\tSoldier *s = m->genSoldier(g, rule, nationality);\n\t\t\t\t\t\tYAML::YamlRootNodeReader reader(_rules->getSpawnedSoldierTemplate(), \"(spawned soldier template)\");\n\t\t\t\t\t\ts->load(reader, m, g, m->getScriptGlobal(), true); // load from soldier template\n\t\t\t\t\t\tif (_rules->getSpawnedPersonName() != \"\")\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ts->setName(lang->getString(_rules->getSpawnedPersonName()));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ts->genName();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tt->setSoldier(s);\n\t\t\t\t\t\tb->getTransfers()->push_back(t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Generate an event (side effect)\n\t\t\tconst std::string choice = _rules->chooseEvent();\n\t\t\tif (!choice.empty())\n\t\t\t{\n\t\t\t\tRuleEvent* eventToSpawn = m->getEvent(choice, false);\n\t\t\t\tif (eventToSpawn)\n\t\t\t\t{\n\t\t\t\t\tg->spawnEvent(eventToSpawn);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (_rules->getPoints() != 0)\n\t\t\t{\n\t\t\t\t// yes, negative points are allowed too\n\t\t\t\tg->addResearchScore(_rules->getPoints());\n\t\t\t}\n\t\t\tcount++;\n\t\t\tif (count < produced)\n\t\t\t{\n\t\t\t\t// We need to ensure that player has enough cash/item to produce a new unit\n\t\t\t\tif (!haveEnoughMoneyForOneMoreUnit(g)) return PROGRESS_NOT_ENOUGH_MONEY;\n\t\t\t\tif (!haveEnoughMaterialsForOneMoreUnit(b, m)) return PROGRESS_NOT_ENOUGH_MATERIALS;\n\t\t\t\tstartItem(b, g, m);\n\t\t\t}\n\t\t}\n\t\twhile (count < produced);\n\t}\n\tif (getAmountProduced() >= _amount && !getInfiniteAmount()) return PROGRESS_COMPLETE;\n\tif (done < getAmountProduced())\n\t{\n\t\t// We need to ensure that player has enough cash/item to produce a new unit\n\t\tif (!haveEnoughMoneyForOneMoreUnit(g)) return PROGRESS_NOT_ENOUGH_MONEY;\n\t\tif (!haveEnoughLivingSpaceForOneMoreUnit(b)) return PROGRESS_NOT_ENOUGH_LIVING_SPACE;\n\t\tif (!haveEnoughMaterialsForOneMoreUnit(b, m)) return PROGRESS_NOT_ENOUGH_MATERIALS;\n\t\tstartItem(b, g, m);\n\t}\n\treturn PROGRESS_NOT_COMPLETE;\n}\n\nint Production::getAmountProduced() const\n{\n\tif (_rules->getManufactureTime() > 0)\n\t\treturn _timeSpent / _rules->getManufactureTime();\n\telse\n\t\treturn _amount;\n}\n\nconst RuleManufacture * Production::getRules() const\n{\n\treturn _rules;\n}\n\nvoid Production::startItem(Base * b, SavedGame * g, const Mod *m) const\n{\n\tg->setFunds(g->getFunds() - _rules->getManufactureCost());\n\tfor (const auto& i : _rules->getRequiredItems())\n\t{\n\t\tb->getStorageItems()->removeItem(i.first, i.second);\n\t}\n\tfor (const auto& i : _rules->getRequiredCrafts())\n\t{\n\t\t// Find suitable craft\n\t\tfor (auto* c : *b->getCrafts())\n\t\t{\n\t\t\tif (c->getRules() == i.first)\n\t\t\t{\n\t\t\t\tCraft *craft = c;\n\t\t\t\tb->removeCraft(craft, true);\n\t\t\t\tdelete craft;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid Production::refundItem(Base * b, SavedGame * g, const Mod *m) const\n{\n\tg->setFunds(g->getFunds() + _rules->getManufactureCost());\n\tfor (const auto& pair : _rules->getRequiredItems())\n\t{\n\t\tb->getStorageItems()->addItem(pair.first, pair.second);\n\t}\n\t//for (const auto& pair : _rules->getRequiredCrafts())\n\t//{\n\t//\t// not supported\n\t//}\n}\n\nvoid Production::save(YAML::YamlNodeWriter writer) const\n{\n\twriter.setAsMap();\n\twriter.write(\"item\", getRules()->getName());\n\twriter.write(\"assigned\", getAssignedEngineers());\n\twriter.write(\"spent\", getTimeSpent());\n\twriter.write(\"amount\", getAmountTotal());\n\twriter.write(\"infinite\", getInfiniteAmount());\n\tif (getSellItems())\n\t\twriter.write(\"sell\", getSellItems());\n\tif (_isFallback)\n\t\twriter.write(\"isFallback\", _isFallback);\n\tif (!_rules->getRandomProducedItems().empty())\n\t\twriter.write(\"randomProductionInfo\", _randomProductionInfo);\n}\n\nvoid Production::load(const YAML::YamlNodeReader& reader)\n{\n\tsetAssignedEngineers(reader[\"assigned\"].readVal(getAssignedEngineers()));\n\tsetTimeSpent(reader[\"spent\"].readVal(getTimeSpent()));\n\tsetAmountTotal(reader[\"amount\"].readVal(getAmountTotal()));\n\tsetInfiniteAmount(reader[\"infinite\"].readVal(getInfiniteAmount()));\n\tsetSellItems(reader[\"sell\"].readVal(getSellItems()));\n\treader.tryRead(\"isFallback\", _isFallback);\n\tif (!_rules->getRandomProducedItems().empty())\n\t{\n\t\t_randomProductionInfo = reader[\"randomProductionInfo\"].readVal(_randomProductionInfo);\n\t}\n\t// backwards compatibility\n\tif (getAmountTotal() == INT_MAX)\n\t{\n\t\tsetAmountTotal(999);\n\t\tsetInfiniteAmount(true);\n\t\tsetSellItems(true);\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Savegame/Production.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/Yaml.h\"\n\nnamespace OpenXcom\n{\n\nclass RuleManufacture;\nclass Base;\nclass SavedGame;\nclass Language;\nclass Mod;\nenum productionProgress_e { PROGRESS_NOT_COMPLETE, PROGRESS_COMPLETE, PROGRESS_NOT_ENOUGH_MONEY, PROGRESS_NOT_ENOUGH_MATERIALS, PROGRESS_NOT_ENOUGH_LIVING_SPACE, PROGRESS_MAX, PROGRESS_CONSTRUCTION };\n\nclass Production\n{\npublic:\n\tProduction (const RuleManufacture * rules, int amount);\n\tint getAmountTotal() const;\n\tvoid setAmountTotal (int);\n\tbool getInfiniteAmount() const;\n\tvoid setInfiniteAmount (bool);\n\tint getTimeSpent() const;\n\tvoid setTimeSpent (int);\n\tbool isQueuedOnly() const;\n\tint getAmountProduced() const;\n\tint getAssignedEngineers() const;\n\tvoid setAssignedEngineers (int);\n\tbool getSellItems() const;\n\tvoid setSellItems (bool);\n\tbool isFallback() const { return _isFallback; }\n\tvoid setFallback(bool newValue) { _isFallback = newValue; }\n\tproductionProgress_e step(Base * b, SavedGame * g, const Mod *m, Language *lang);\n\tconst RuleManufacture * getRules() const;\n\tvoid startItem(Base * b, SavedGame * g, const Mod *m) const;\n\tvoid refundItem(Base * b, SavedGame * g, const Mod *m) const;\n\tvoid save(YAML::YamlNodeWriter writer) const;\n\tvoid load(const YAML::YamlNodeReader& reader);\n\tconst std::map<std::string, int> &getRandomProductionInfo() const { return _randomProductionInfo; }\nprivate:\n\tconst RuleManufacture * _rules;\n\tint _amount;\n\tbool _infinite;\n\tint _timeSpent;\n\tint _engineers;\n\tbool _sell;\n\tbool _isFallback;\n\tstd::map<std::string, int> _randomProductionInfo;\n\tbool haveEnoughMoneyForOneMoreUnit(SavedGame * g) const;\n\tbool haveEnoughLivingSpaceForOneMoreUnit(Base * b);\n\tbool haveEnoughMaterialsForOneMoreUnit(Base * b, const Mod *m) const;\n};\n\n}\n"
  },
  {
    "path": "src/Savegame/RankCount.cpp",
    "content": "/*\n * Copyright 2010-2023 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"RankCount.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleSoldier.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Gets the count of promotions by SoldierRank.\n * @param rank to query for promotions\n * @return the count of this rank\n */\nint &RankCountBase::operator[](const SoldierRank rank)\n{\n\treturn _rankCounts[rank];\n}\n\n/**\n * @brief Gets the total number of soldiers counted.\n * @return The total number of soldiers.\n */\nint RankCountBase::getTotalSoldiers() const\n{\n\treturn _totalSoldiers;\n}\n\n/**\n * @brief Creates a new RankCount object containing rank\n * @param The list of soldiers to collect rank information about. Typically should be all soldiers.\n */\nRankCount::RankCount(const std::vector<Soldier*> soldiers)\n{\n\t_totalSoldiers = 0;\n\tfor (auto* soldier : soldiers)\n\t{\n\t\tif (soldier->getRules()->getAllowPromotion())\n\t\t{\n\t\t\t_rankCounts[soldier->getRank()]++;\n\t\t\t_totalSoldiers++;\n\t\t}\n\t}\n}\n\n/**\n * Creates a new PromotionOpenings object, containing the count of promotion openings based on the mods promotion rules.\n * Ranks that are overfull for some reason will show as 0 openings, ranks that have unlimited openings will have -1 openings.\n * @param soldiers The set of soldiers to consider for calculation, typically should be all active soldiers.\n * @param mod The mod containing the rules for promotions.\n */\nPromotionOpenings::PromotionOpenings(const std::vector<Soldier*> soldiers, const Mod* mod)\n{\n\tRankCount currentRankCount = RankCount(soldiers);\n\n\tint totalSoldiers = currentRankCount.getTotalSoldiers();\n\n\t// special logic, there is only one Commander ever.\n\tif (currentRankCount[RANK_COMMANDER] == 0 && totalSoldiers >= mod->getSoldiersPerRank(RANK_COMMANDER))\n\t{\n\t\t_rankCounts[RANK_COMMANDER]++;\n\t}\n\n\t_rankCounts[RANK_COLONEL] += std::max(0, totalSoldiers / mod->getSoldiersPerRank(RANK_COLONEL) - currentRankCount[RANK_COLONEL]);\n\t_rankCounts[RANK_CAPTAIN] += std::max(0, totalSoldiers / mod->getSoldiersPerRank(RANK_CAPTAIN) - currentRankCount[RANK_CAPTAIN]);\n\t_rankCounts[RANK_SERGEANT] += std::max(0, totalSoldiers / mod->getSoldiersPerRank(RANK_SERGEANT) - currentRankCount[RANK_SERGEANT]);\n\n\t// promotions to Squaddie and Rookie are unlimited, indicate this with a -1.\n\t_rankCounts[RANK_SQUADDIE] = -1;\n\t_rankCounts[RANK_ROOKIE] = -1;\n}\n\n/**\n * @brief Tests if a soldier can be manually promoted to a new rank.\n * @param soldier The soldier to test for promotion.\n * @param newRank The new rank to promote the soldier to.\n * @return True if the soldier can be promoted to this rank, false otherwise.\n */\nbool PromotionOpenings::isManualPromotionPossible(const Soldier* soldier, const SoldierRank newRank) const\n{\n\t// check if the soldiers rules allow promotion.\n\tconst auto* soldierRules = soldier->getRules();\n\tif (!soldierRules->getAllowPromotion())\n\t{\n\t\treturn false;\n\t}\n\n\tconst SoldierRank currentRank = soldier->getRank();\n\n\t// rookies cannot be promoted\n\tif (currentRank == RANK_ROOKIE /* || newRank == RANK_ROOKIE */)\n\t{\n\t\treturn false;\n\t}\n\n\t// can't promote to same rank.\n\tif (currentRank == newRank)\n\t{\n\t\treturn false;\n\t}\n\n\t// If the rankString for the soldier is not empty, check if the new rank is defined in the rank strings.\n\t// If not, it is not allowed. If no rankStrings are defined, we assume default behavior.\n\tconst size_t rankStringsSize = soldierRules->getRankStrings().size();\n\tif (rankStringsSize != 0 && (size_t)newRank >= rankStringsSize)\n\t{\n\t\treturn false;\n\t}\n\n\t// can always demote to rookie or squaddie\n\tif (newRank == RANK_ROOKIE || newRank == RANK_SQUADDIE)\n\t{\n\t\treturn true;\n\t}\n\n\t// otherwise promotion or demotion depends on there being an opening.\n\treturn _rankCounts[newRank] > 0;\n}\n\n}\n"
  },
  {
    "path": "src/Savegame/RankCount.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2023 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Soldier.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Base class for the rank count classes.\n */\nclass RankCountBase\n{\n  protected:\n\t/// count of soldiers in each rank.\n\tstd::array<int, RANK_COMMANDER + 1> _rankCounts;\n\tint _totalSoldiers;\n\n\tRankCountBase() : _rankCounts(), _totalSoldiers(0) {}\n\n  public:\n\tint& operator[](const SoldierRank rank);\n\n\tint getTotalSoldiers() const;\n};\n\n/**\n * @brief Container for counts of soldier ranks.\n */\nclass RankCount : public RankCountBase\n{\n  public:\n\tRankCount(const std::vector<Soldier*> soldiers);\n};\n\n/**\n * @brief Container for counts of promotion openings.\n */\nclass PromotionOpenings : public RankCountBase\n{\n  public:\n\tPromotionOpenings(const std::vector<Soldier*> soldiers, const Mod* mod);\n\n\t// check if a soldier can be promoted to a given rank.\n\tbool isManualPromotionPossible(const Soldier* soldier, const SoldierRank newRank) const;\n};\n\n}\n"
  },
  {
    "path": "src/Savegame/Region.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Region.h\"\n#include \"../Mod/RuleRegion.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes a region of the specified type.\n * @param rules Pointer to ruleset.\n */\nRegion::Region(RuleRegion *rules): _rules(rules)\n{\n\t_activityAlien.push_back(0);\n\t_activityXcom.push_back(0);\n}\n\n/**\n *\n */\nRegion::~Region()\n{\n}\n\n/**\n * Loads the region from a YAML file.\n * @param node YAML node.\n */\nvoid Region::load(const YAML::YamlNodeReader& reader)\n{\n\treader.tryRead(\"activityXcom\", _activityXcom);\n\treader.tryRead(\"activityAlien\", _activityAlien);\n}\n\n/**\n * Saves the region to a YAML file.\n * @return YAML node.\n */\nvoid Region::save(YAML::YamlNodeWriter writer) const\n{\n\twriter.setAsMap();\n\twriter.write(\"type\", _rules->getType());\n\twriter.write(\"activityXcom\", _activityXcom);\n\twriter.write(\"activityAlien\", _activityAlien);\n}\n\n/**\n * Returns the ruleset for the region's type.\n * @return Pointer to ruleset.\n */\nRuleRegion *Region::getRules() const\n{\n\treturn _rules;\n}\n\n/**\n * Adds to the region's xcom activity level.\n * @param activity Amount to add.\n */\nvoid Region::addActivityXcom(int activity)\n{\n\t_activityXcom.back() += activity;\n}\n\n/**\n * Adds to the region's alien activity level.\n * @param activity Amount to add.\n */\nvoid Region::addActivityAlien(int activity)\n{\n\t_activityAlien.back() += activity;\n}\n\n/**\n * Gets the region's xcom activity level.\n * @return activity level.\n */\nstd::vector<int> &Region::getActivityXcom()\n{\n\treturn _activityXcom;\n}\n\n/**\n * Gets the region's alien activity level.\n * @return activity level.\n */\nstd::vector<int> &Region::getActivityAlien()\n{\n\treturn _activityAlien;\n}\n\n/**\n * Store last month's counters, start new counters.\n */\nvoid Region::newMonth()\n{\n\t_activityAlien.push_back(0);\n\t_activityXcom.push_back(0);\n\tif (_activityAlien.size() > 12)\n\t\t_activityAlien.erase(_activityAlien.begin());\n\tif (_activityXcom.size() > 12)\n\t\t_activityXcom.erase(_activityXcom.begin());\n}\n\n}\n"
  },
  {
    "path": "src/Savegame/Region.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <vector>\n#include \"../Engine/Yaml.h\"\n\nnamespace OpenXcom\n{\n\nclass RuleRegion;\n\n/**\n * Represents a region of the world.\n * Contains variable info about a region like\n * X-Com and alien activity in it.\n */\nclass Region\n{\nprivate:\n\tRuleRegion *_rules;\n\tstd::vector<int> _activityXcom, _activityAlien;\npublic:\n\t/// Creates a new region of the specified type.\n\tRegion(RuleRegion *rules);\n\t/// Cleans up the region.\n\t~Region();\n\t/// Loads the region from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader);\n\t/// Saves the region to YAML.\n\tvoid save(YAML::YamlNodeWriter writer) const;\n\t/// Gets the region's ruleset.\n\tRuleRegion *getRules() const;\n\t/// add xcom activity in this region\n\tvoid addActivityXcom(int activity);\n\t/// add alien activity in this region\n\tvoid addActivityAlien(int activity);\n\t/// get xcom activity to this region\n\tstd::vector<int> &getActivityXcom();\n\t/// get xcom activity to this region\n\tstd::vector<int> &getActivityAlien();\n\t/// start new month of activity\n\tvoid newMonth();\n};\n\n}\n"
  },
  {
    "path": "src/Savegame/ResearchDiary.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2025 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/Yaml.h\"\n#include \"GameTime.h\"\n#include <string>\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleResearch.h\"\n#include \"../Mod/RuleEvent.h\"\n#include \"../Mod/AlienDeployment.h\"\n\nnamespace OpenXcom\n{\n\nenum DiscoverySourceType : Uint8 { BASE = 0, FREE_FROM = 1, FREE_AFTER = 2, MISSION = 3, EVENT = 4 };\n\nstruct DiscoverySource\n{\n\tDiscoverySourceType type;\n\tstd::string name; // Not guaranteed to be valid\n\tconst RuleResearch* research;\n\tconst RuleEvent* event;\n\tconst AlienDeployment* mission;\n\n\tstd::string_view getTypeString()\n\t{\n\t\tswitch (type)\n\t\t{\n\t\tcase DiscoverySourceType::BASE:\n\t\t\treturn \"STR_DISCOVERY_SOURCE_BASE\";\n\t\tcase DiscoverySourceType::FREE_FROM:\n\t\t\treturn \"STR_DISCOVERY_SOURCE_FREE_FROM\";\n\t\tcase DiscoverySourceType::FREE_AFTER:\n\t\t\treturn \"STR_DISCOVERY_SOURCE_FREE_AFTER\";\n\t\tcase DiscoverySourceType::MISSION:\n\t\t\treturn \"STR_DISCOVERY_SOURCE_MISSION\";\n\t\tcase DiscoverySourceType::EVENT:\n\t\t\treturn \"STR_DISCOVERY_SOURCE_EVENT\";\n\t\tdefault:\n\t\t\tthrow Exception(\"Invalid DiscoverySourceType!\");\n\t\t}\n\t}\n};\n\n/**\n * Element of the research diary\n */\nstruct ResearchDiaryEntry\n{\n\tconst RuleResearch* research;\n\tUint32 year;\n\tUint32 month;\n\tUint32 day;\n\tDiscoverySource source;\n\n\tResearchDiaryEntry(const RuleResearch* r) : year(), month(), day()\n\t{\n\t\tresearch = r;\n\t}\n\n\tvoid setDate(GameTime* time)\n\t{\n\t\tyear = time->getYear();\n\t\tmonth = time->getMonth();\n\t\tday = time->getDay();\n\t}\n\n\tvoid load(const YAML::YamlNodeReader& reader, Mod* mod)\n\t{\n\t\tif (!research)\n\t\t{\n\t\t\tstd::string name;\n\t\t\treader.tryRead(\"name\", name);\n\t\t\tresearch = mod->getResearch(name);\n\t\t}\n\t\tconst YAML::YamlNodeReader& dateReader = reader[\"date\"];\n\t\tyear = dateReader[0].readVal<Uint32>();\n\t\tmonth = dateReader[1].readVal<Uint32>();\n\t\tday = dateReader[2].readVal<Uint32>();\n\t\treader.tryRead(\"sourceType\", source.type);\n\t\treader.tryRead(\"sourceName\", source.name);\n\t\tswitch (source.type)\n\t\t{\n\t\tcase DiscoverySourceType::FREE_FROM:\n\t\tcase DiscoverySourceType::FREE_AFTER:\n\t\t\tsource.research = mod->getResearch(source.name, false);\n\t\t\tbreak;\n\t\tcase DiscoverySourceType::MISSION:\n\t\t\tsource.mission = mod->getDeployment(source.name, false);\n\t\t\tbreak;\n\t\tcase DiscoverySourceType::EVENT:\n\t\t\tsource.event = mod->getEvent(source.name, false);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tvoid save(YAML::YamlNodeWriter writer) const\n\t{\n\t\twriter.setAsMap();\n\t\twriter.setFlowStyle();\n\t\tYAML::YamlNodeWriter dateWriter = writer[\"date\"];\n\t\tdateWriter.setAsSeq();\n\t\tdateWriter.setFlowStyle();\n\t\tdateWriter.write(year);\n\t\tdateWriter.write(month);\n\t\tdateWriter.write(day);\n\t\twriter.write(\"name\", research->getName());\n\t\twriter.write(\"sourceType\", source.type);\n\t\twriter.write(\"sourceName\", source.name);\n\t}\n};\n\n}\n"
  },
  {
    "path": "src/Savegame/ResearchProject.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ResearchProject.h\"\n#include \"../Mod/RuleResearch.h\"\n\nnamespace OpenXcom\n{\nconst float PROGRESS_LIMIT_UNKNOWN = 0.333f;\nconst float PROGRESS_LIMIT_POOR = 0.07f;\nconst float PROGRESS_LIMIT_AVERAGE = 0.13f;\nconst float PROGRESS_LIMIT_GOOD = 0.25f;\n\nResearchProject::ResearchProject(RuleResearch * p, int c) : _project(p), _assigned(0), _spent(0), _cost(c)\n{\n}\n\n/**\n * Called every day to compute time spent on this ResearchProject\n * @return true if the ResearchProject is finished\n */\nbool ResearchProject::step()\n{\n\t_spent += _assigned;\n\treturn isFinished();\n}\n\n/**\n * gets state of project.\n */\nbool ResearchProject::isFinished()\n{\n\treturn _spent >= getCost();\n}\n\n/**\n * Changes the number of scientist to the ResearchProject\n * @param nb number of scientist assigned to this ResearchProject\n */\nvoid ResearchProject::setAssigned (int nb)\n{\n\t_assigned = nb;\n}\n\nconst RuleResearch * ResearchProject::getRules() const\n{\n\treturn _project;\n}\n\n/**\n * Returns the number of scientist assigned to this project\n * @return Number of assigned scientist.\n */\nint ResearchProject::getAssigned() const\n{\n\treturn _assigned;\n}\n\n/**\n * Returns the time already spent on this project\n * @return the time already spent on this ResearchProject(in man/day)\n */\nint ResearchProject::getSpent() const\n{\n\treturn _spent;\n}\n\n/**\n * Changes the cost of the ResearchProject\n * @param spent new project cost(in man/day)\n */\nvoid ResearchProject::setSpent (int spent)\n{\n\t_spent = spent;\n}\n\n/**\n * Returns the cost of the ResearchProject\n * @return the cost of the ResearchProject(in man/day)\n */\nint ResearchProject::getCost() const\n{\n\treturn _cost;\n}\n\n/**\n * Changes the cost of the ResearchProject\n * @param f new project cost(in man/day)\n */\nvoid ResearchProject::setCost(int f)\n{\n\t_cost = f;\n}\n\n/**\n * Loads the research project from a YAML file.\n * @param node YAML node.\n */\nvoid ResearchProject::load(const YAML::YamlNodeReader& reader)\n{\n\tsetAssigned(reader[\"assigned\"].readVal(getAssigned()));\n\tsetSpent(reader[\"spent\"].readVal(getSpent()));\n\tsetCost(reader[\"cost\"].readVal(getCost()));\n}\n\n/**\n * Saves the research project to a YAML file.\n * @return YAML node.\n */\nvoid ResearchProject::save(YAML::YamlNodeWriter writer) const\n{\n\twriter.setAsMap();\n\twriter.write(\"project\", getRules()->getName());\n\twriter.write(\"assigned\", getAssigned());\n\twriter.write(\"spent\", getSpent());\n\twriter.write(\"cost\", getCost());\n}\n\n/**\n * Return a string describing Research progress.\n * @return a string describing Research progress.\n */\nstd::string ResearchProject::getResearchProgress() const\n{\n\tfloat progress = (float)getSpent() / getRules()->getCost();\n\tif (getAssigned() == 0)\n\t{\n\t\treturn \"STR_NONE\";\n\t}\n\telse if (progress <= PROGRESS_LIMIT_UNKNOWN)\n\t{\n\t\treturn \"STR_UNKNOWN\";\n\t}\n\telse\n\t{\n\t\tfloat rating = (float)getAssigned();\n\t\trating /= getRules()->getCost();\n\t\tif (rating <= PROGRESS_LIMIT_POOR)\n\t\t{\n\t\t\treturn \"STR_POOR\";\n\t\t}\n\t\telse if (rating <= PROGRESS_LIMIT_AVERAGE)\n\t\t{\n\t\t\treturn \"STR_AVERAGE\";\n\t\t}\n\t\telse if (rating <= PROGRESS_LIMIT_GOOD)\n\t\t{\n\t\t\treturn \"STR_GOOD\";\n\t\t}\n\t\treturn \"STR_EXCELLENT\";\n\t}\n}\n\n}\n"
  },
  {
    "path": "src/Savegame/ResearchProject.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/Yaml.h\"\n\nnamespace OpenXcom\n{\n\nclass RuleResearch;\nclass Mod;\n\n/**\n   Represent a ResearchProject\n   Contain information about assigned scientist, time already spent and cost of the project.\n */\nclass ResearchProject\n{\n\tRuleResearch * _project;\n\tint _assigned;\n\tint _spent;\n\tint _cost;\npublic:\n\tResearchProject(RuleResearch * p, int c = 0);\n\t/// Game logic. Called every new day to compute time spent.\n\tbool step();\n\t/// gets state of project.\n\tbool isFinished();\n\t/// set the number of scientist assigned to this ResearchProject\n\tvoid setAssigned (int nb);\n\t/// get the number of scientist assigned to this ResearchProject\n\tint getAssigned() const;\n\t/// get time already spent on this ResearchProject\n\tint getSpent() const;\n\t/// set time already spent on this ResearchProject\n\tvoid setSpent (int spent);\n\t/// get time cost of this ResearchProject\n\tint getCost() const;\n\t/// set time cost of this ResearchProject\n\tvoid setCost(int f);\n\t/// get the ResearchProject Mod\n\tconst RuleResearch * getRules() const;\n\t/// load the ResearchProject from YAML\n\tvoid load(const YAML::YamlNodeReader& reader);\n\t/// save the ResearchProject to YAML\n\tvoid save(YAML::YamlNodeWriter writer) const;\n\t/// Get a string describing current progress.\n\tstd::string getResearchProgress() const;\n};\n\n}\n"
  },
  {
    "path": "src/Savegame/SaveConverter.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"SaveConverter.h\"\n#include <algorithm>\n#include \"../Engine/Yaml.h\"\n#include <SDL_endian.h>\n#include <fstream>\n#include <sstream>\n#include <iomanip>\n#include <bitset>\n#include \"../Engine/Options.h\"\n#include \"../Engine/CrossPlatform.h\"\n#include \"../Engine/Exception.h\"\n#include \"../Engine/Language.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"SavedGame.h\"\n#include \"GameTime.h\"\n#include \"Country.h\"\n#include \"Region.h\"\n#include \"Base.h\"\n#include \"BaseFacility.h\"\n#include \"ItemContainer.h\"\n#include \"Ufo.h\"\n#include \"Craft.h\"\n#include \"AlienBase.h\"\n#include \"Waypoint.h\"\n#include \"MissionSite.h\"\n#include \"CraftWeapon.h\"\n#include \"Transfer.h\"\n#include \"Vehicle.h\"\n#include \"AlienStrategy.h\"\n#include \"AlienMission.h\"\n#include \"Soldier.h\"\n#include \"../Mod/RuleResearch.h\"\n#include \"../Mod/RuleRegion.h\"\n#include \"../Mod/ArticleDefinition.h\"\n#include \"ResearchProject.h\"\n#include \"../Mod/RuleManufacture.h\"\n#include \"Production.h\"\n#include \"../Mod/UfoTrajectory.h\"\n#include \"../Engine/RNG.h\"\n#include \"../Mod/RuleConverter.h\"\n#include \"../Ufopaedia/Ufopaedia.h\"\n#include \"../fmath.h\"\n\nnamespace OpenXcom\n{\n\nenum TargetType { TARGET_NONE, TARGET_UFO, TARGET_CRAFT, TARGET_XBASE, TARGET_ABASE, TARGET_CRASH, TARGET_LANDED, TARGET_WAYPOINT, TARGET_TERROR, TARGET_PORT = 0x51, TARGET_ISLAND = 0x52, TARGET_SHIP = 0x53, TARGET_ARTEFACT = 0x54 };\nconst char *xcomAltitudes[] = { \"STR_GROUND\", \"STR_VERY_LOW\", \"STR_LOW_UC\", \"STR_HIGH_UC\", \"STR_VERY_HIGH\" };\nconst char *xcomStatus[] = { \"STR_READY\", \"STR_OUT\", \"STR_REPAIRS\", \"STR_REFUELLING\", \"STR_REARMING\" };\n\n// Helper functions\ntemplate <typename T> T load(char* data) { return *(T*)data; }\ntemplate <> Uint16 load(char* data) { return SDL_SwapLE16(*(Uint16*)data); }\ntemplate <> Sint16 load(char* data) { return SDL_SwapLE16(*(Sint16*)data); }\ntemplate <> int load(char* data) { return SDL_SwapLE32(*(int*)data); }\ntemplate <> unsigned int load(char* data) { return SDL_SwapLE32(*(unsigned int*)data); }\ntemplate <> std::string load(char* data) { return data; }\n\nchar *SaveConverter::binaryBuffer(const std::string &filename, std::vector<char> &buffer) const\n{\n\tauto datFile = CrossPlatform::readFile(_savePath + \"/\" + filename);\n\tbuffer = std::vector<char>((std::istreambuf_iterator<char>(*datFile)), (std::istreambuf_iterator<char>()));\n\treturn &buffer[0];\n}\n\n/**\n * Creates a new converter for the given save folder.\n * @param save Number of the save folder GAME_#\n * @param mod Mod to associate with this save.\n */\nSaveConverter::SaveConverter(int save, Mod *mod) : _save(0), _mod(mod), _rules(mod->getConverter()), _year(0), _funds(0)\n{\n\tstd::ostringstream ssFolder, ssPath;\n\tssFolder << \"GAME_\" << save;\n\tssPath << Options::getMasterUserFolder() << ssFolder.str();\n\t_saveName = ssFolder.str();\n\t_savePath = ssPath.str();\n\tssPath << \"/SAVEINFO.DAT\";\n\tif (!CrossPlatform::fileExists(ssPath.str()))\n\t{\n\t\tthrow Exception(_saveName + \" is not a valid save folder\");\n\t}\n}\n\nSaveConverter::~SaveConverter()\n{\n}\n\n/**\n * Gets all the info of the saves found in the user folder.\n * @param lang Loaded language.\n * @param info Returned list of saves info.\n */\nvoid SaveConverter::getList(Language *lang, SaveOriginal info[NUM_SAVES])\n{\n\tfor (int i = 0; i < NUM_SAVES; ++i)\n\t{\n\t\tSaveOriginal &save = info[i];\n\t\tsave.id = 0;\n\n\t\tconst int id = i + 1;\n\t\tstd::string datname = Options::getMasterUserFolder() + \"GAME_\" + std::to_string(id) + \"/SAVEINFO.DAT\";\n\t\tif (!CrossPlatform::fileExists(datname)) {\n\t\t\tcontinue;\n\t\t}\n\t\tauto datFile = CrossPlatform::readFile(datname);\n\t\tstd::vector<char> buffer((std::istreambuf_iterator<char>(*datFile)), (std::istreambuf_iterator<char>()));\n\t\tchar *data = &buffer[0];\n\n\t\tstd::string name = load<std::string>(data + 0x02);\n\t\tint year = load<Uint16>(data + 0x1C);\n\t\tint month = load<Uint16>(data + 0x1E);\n\t\tint day = load<Uint16>(data + 0x20);\n\t\tint hour = load<Uint16>(data + 0x22);\n\t\tint minute = load<Uint16>(data + 0x24);\n\t\tbool tactical = load<char>(data + 0x26) != 0;\n\n\t\tGameTime time = GameTime(0, day, month + 1, year, hour, minute, 0);\n\n\t\tstd::ostringstream ssDate, ssTime;\n\t\tssDate << time.getDayString(lang) << \"  \" << lang->getString(time.getMonthString()) << \"  \" << time.getYear();\n\t\tssTime << time.getHour() << \":\" << std::setfill('0') << std::setw(2) << time.getMinute();\n\n\t\tsave.id = id;\n\t\tsave.name = name;\n\t\tsave.date = ssDate.str();\n\t\tsave.time = ssTime.str();\n\t\tsave.tactical = tactical;\n\t}\n}\n\n/**\n * Converts an original X-COM save into an OpenXcom save.\n * @return New OpenXcom save.\n */\nSavedGame *SaveConverter::loadOriginal()\n{\n\t_save = new SavedGame();\n\n\t// Load globe data\n\t_save->getIncomes().clear();\n\tfor (size_t i = 0; i < _rules->getCountries().size(); ++i)\n\t{\n\t\tCountry *country = new Country(_mod->getCountry(_rules->getCountries()[i], true));\n\t\tcountry->getActivityAlien().clear();\n\t\tcountry->getActivityXcom().clear();\n\t\tcountry->getFunding().clear();\n\t\t_save->getCountries()->push_back(country);\n\t}\n\tfor (size_t i = 0; i < _rules->getRegions().size(); ++i)\n\t{\n\t\tRegion *region = new Region(_mod->getRegion(_rules->getRegions()[i], true));\n\t\tregion->getActivityAlien().clear();\n\t\tregion->getActivityXcom().clear();\n\t\t_save->getRegions()->push_back(region);\n\t}\n\tloadDatXcom();\n\tloadDatAlien();\n\tloadDatDiplom();\n\tloadDatLease();\n\n\t// Load graph data\n\t_save->getExpenditures().clear();\n\t_save->getMaintenances().clear();\n\t_save->getFundsList().clear();\n\t_save->getResearchScores().clear();\n\tloadDatLIGlob();\n\tloadDatUIGlob();\n\tloadDatIGlob();\n\n\t// Load alien data\n\tloadDatZonal();\n\tloadDatActs();\n\tloadDatMissions();\n\n\t// Load player data\n\tloadDatLoc();\n\tloadDatBase();\n\tloadDatAStore();\n\tloadDatCraft();\n\tloadDatSoldier();\n\tloadDatTransfer();\n\tloadDatResearch();\n\tloadDatUp();\n\tloadDatProject();\n\tloadDatBProd();\n\tloadDatXBases();\n\n\treturn _save;\n}\n\n/**\n * Corrects vectors of graph data.\n * Original X-COM uses months as array indexes,\n * while OpenXcom stores month data in a linear fashion.\n * @param vector Vector of graph data.\n * @param month Current month.\n * @param year Has game gone longer than a year?\n */\ntemplate <typename T>\nvoid SaveConverter::graphVector(std::vector<T> &vector, int month, bool year)\n{\n\tif (year)\n\t{\n\t\tstd::vector<T> newVector;\n\t\tint i = month;\n\t\tdo\n\t\t{\n\t\t\tnewVector.push_back(vector[i]);\n\t\t\ti = (i + 1) % vector.size();\n\t\t}\n\t\twhile (i != month);\n\t\tvector = newVector;\n\t}\n\telse\n\t{\n\t\tvector.resize(month);\n\t}\n}\n\n/**\n * Loads the IGLOB.DAT file.\n * Contains game date, time and difficulty.\n */\nvoid SaveConverter::loadDatIGlob()\n{\n\tstd::vector<char> buffer;\n\tchar *data = binaryBuffer(\"IGLOB.DAT\", buffer);\n\n\tint month = load<int>(data + 0x00) + 1;\n\tint weekday = load<int>(data + 0x04) + 1;\n\tint day = load<int>(data + 0x08);\n\tint hour = load<int>(data + 0x0C);\n\tint minute = load<int>(data + 0x10);\n\tint second = load<int>(data + 0x14);\n\t_save->setTime(GameTime(weekday, day, month, _year, hour, minute, second));\n\n\t// account for difficulty bug\n\tif (buffer.size() > 0x3C)\n\t{\n\t\tint coefficient = load<int>(data + 0x3C);\n\t\tfor (size_t i = DIFF_BEGINNER; i <= DIFF_SUPERHUMAN; ++i)\n\t\t{\n\t\t\tif (coefficient == Mod::DIFFICULTY_COEFFICIENT[i])\n\t\t\t{\n\t\t\t\t_save->setDifficulty((GameDifficulty)i);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Fix up the months\n\tsize_t monthsPassed = month + (_year - _mod->getStartingTime().getYear()) * 12;\n\tfor (size_t i = 0; i < monthsPassed; ++i)\n\t{\n\t\t_save->addMonth();\n\t}\n\tgraphVector(_save->getIncomes(), month, _year != _mod->getStartingTime().getYear());\n\tgraphVector(_save->getExpenditures(), month, _year != _mod->getStartingTime().getYear());\n\tgraphVector(_save->getMaintenances(), month, _year != _mod->getStartingTime().getYear());\n\tgraphVector(_save->getFundsList(), month, _year != _mod->getStartingTime().getYear());\n\tgraphVector(_save->getResearchScores(), month, _year != _mod->getStartingTime().getYear());\n\tfor (size_t i = 0; i < _rules->getCountries().size(); ++i)\n\t{\n\t\tCountry *country = _save->getCountries()->at(i);\n\t\tgraphVector(country->getActivityAlien(), month, _year != _mod->getStartingTime().getYear());\n\t\tgraphVector(country->getActivityXcom(), month, _year != _mod->getStartingTime().getYear());\n\t\tgraphVector(country->getFunding(), month, _year != _mod->getStartingTime().getYear());\n\t}\n\tfor (size_t i = 0; i < _rules->getRegions().size(); ++i)\n\t{\n\t\tRegion *region = _save->getRegions()->at(i);\n\t\tgraphVector(region->getActivityAlien(), month, _year != _mod->getStartingTime().getYear());\n\t\tgraphVector(region->getActivityXcom(), month, _year != _mod->getStartingTime().getYear());\n\t}\n\t_save->getFundsList().back() = _funds;\n}\n\n/**\n * Loads the LIGLOB.DAT file.\n * Contains financial data.\n */\nvoid SaveConverter::loadDatLIGlob()\n{\n\tstd::vector<char> buffer;\n\tchar *data = binaryBuffer(\"LIGLOB.DAT\", buffer);\n\n\tconst size_t MONTHS = 12;\n\tfor (size_t i = 0; i < MONTHS; ++i)\n\t{\n\t\tint expenditure = load<int>(data + 0x04 + i * sizeof(int));\n\t\tint maintenance = load<int>(data + 0x34 + i * sizeof(int));\n\t\tint balance = load<int>(data + 0x64 + i * sizeof(int));\n\t\t_save->getExpenditures().push_back(expenditure);\n\t\t_save->getMaintenances().push_back(maintenance);\n\t\t_save->getFundsList().push_back(balance);\n\t}\n\n\t_funds = load<int>(data);\n}\n\n/**\n * Loads the UIGLOB.DAT file.\n * Contains Geoscape number IDs and scores.\n */\nvoid SaveConverter::loadDatUIGlob()\n{\n\tstd::vector<char> buffer;\n\tchar *data = binaryBuffer(\"UIGLOB.DAT\", buffer);\n\n\tstd::map<std::string, int> ids;\n\tfor (size_t i = 0; i < _rules->getMarkers().size(); ++i)\n\t{\n\t\tids[_rules->getMarkers()[i]] = load<Uint16>(data + i * sizeof(Uint16));\n\t}\n\tids[\"STR_CRASH_SITE\"] = ids[\"STR_LANDING_SITE\"] = ids[\"STR_UFO\"];\n\n\t_year = load<Uint16>(data + 0x16);\n\n\tconst size_t MONTHS = 12;\n\tfor (size_t i = 0; i < MONTHS; ++i)\n\t{\n\t\tint score = load<Sint16>(data + 0x18 + i * sizeof(Sint16));\n\t\t_save->getResearchScores().push_back(score);\n\t}\n\n\t// Loads the SITE.DAT file (TFTD only).\n\tstd::string s = _savePath + \"/\" + \"SITE.DAT\";\n\tif (CrossPlatform::fileExists(s))\n\t{\n\t\tstd::vector<char> sitebuffer;\n\t\tchar* sitedata = binaryBuffer(\"SITE.DAT\", sitebuffer);\n\t\tint generatedArtifactSiteMissions = load<Uint16>(sitedata + 0x24);\n\t\tif (generatedArtifactSiteMissions > 0)\n\t\t{\n\t\t\t_save->getAlienStrategy().addMissionRun(\"artifacts\", generatedArtifactSiteMissions);\n\n\t\t\tint spawnedArtifactSites = generatedArtifactSiteMissions;\n\t\t\tchar siteTypeToBeSpawned = load<char>(sitedata + 0x26);\n\t\t\tif (siteTypeToBeSpawned == 'T')\n\t\t\t{\n\t\t\t\t// before the first hour of the month, the mission was generated already, but the site has not spawned yet\n\t\t\t\tspawnedArtifactSites--;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// after the first hour of the month\n\t\t\t\t// or not an artifact site type\n\t\t\t}\n\t\t\tids[\"STR_ARTIFACT_SITE\"] = spawnedArtifactSites + 1; // OXC stores the ID of the next site, thus +1\n\t\t}\n\t}\n\n\t_save->setAllIds(ids);\n}\n\n/**\n * Loads the LEASE.DAT file.\n * Contains globe camera settings.\n */\nvoid SaveConverter::loadDatLease()\n{\n\tstd::vector<char> buffer;\n\tchar *data = binaryBuffer(\"LEASE.DAT\", buffer);\n\n\tdouble lat = -Xcom2Rad(load<Sint16>(data + 0x00));\n\tdouble lon = -Xcom2Rad(load<Sint16>(data + 0x06));\n\t_save->setGlobeLongitude(lon);\n\t_save->setGlobeLatitude(lat);\n\n\tint zoom = load<Sint16>(data + 0x0C);\n\tconst int DISTANCE[] = { 90, 120, 180, 360, 450, 720 };\n\tfor (size_t i = 0; i < 6; ++i)\n\t{\n\t\tif (zoom == DISTANCE[i])\n\t\t{\n\t\t\t_save->setGlobeZoom(i);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n/**\n * Loads the XCOM.DAT file.\n * Contains X-COM graph info.\n */\nvoid SaveConverter::loadDatXcom()\n{\n\tstd::vector<char> buffer;\n\tchar *data = binaryBuffer(\"XCOM.DAT\", buffer);\n\n\tconst size_t ENTRIES = _rules->getCountries().size() + _rules->getRegions().size();\n\tconst size_t MONTHS = 12;\n\tfor (size_t i = 0; i < ENTRIES * MONTHS; ++i)\n\t{\n\t\tint score = load<int>(data + i * sizeof(int));\n\t\tsize_t j = i % ENTRIES;\n\t\t// country\n\t\tif (j < _rules->getCountries().size())\n\t\t{\n\t\t\t_save->getCountries()->at(j)->getActivityXcom().push_back(score);\n\t\t}\n\t\t// region\n\t\telse\n\t\t{\n\t\t\tj -= _rules->getCountries().size();\n\t\t\t_save->getRegions()->at(j)->getActivityXcom().push_back(score);\n\t\t}\n\t}\n}\n\n/**\n * Loads the ALIEN.DAT file.\n * Contains Alien graph info.\n */\nvoid SaveConverter::loadDatAlien()\n{\n\tstd::vector<char> buffer;\n\tchar *data = binaryBuffer(\"ALIEN.DAT\", buffer);\n\n\tconst size_t ENTRIES = _rules->getCountries().size() + _rules->getRegions().size();\n\tconst size_t MONTHS = 12;\n\tfor (size_t i = 0; i < ENTRIES * MONTHS; ++i)\n\t{\n\t\tint score = load<int>(data + i * sizeof(int));\n\t\tsize_t j = i % ENTRIES;\n\t\t// country\n\t\tif (j < _rules->getCountries().size())\n\t\t{\n\t\t\t_save->getCountries()->at(j)->getActivityAlien().push_back(score);\n\t\t}\n\t\t// region\n\t\telse\n\t\t{\n\t\t\tj -= _rules->getCountries().size();\n\t\t\t_save->getRegions()->at(j)->getActivityAlien().push_back(score);\n\t\t}\n\t}\n}\n\n/**\n * Loads the DIPLOM.DAT file.\n * Contains country status.\n */\nvoid SaveConverter::loadDatDiplom()\n{\n\tstd::vector<char> buffer;\n\tchar *data = binaryBuffer(\"DIPLOM.DAT\", buffer);\n\n\tconst size_t MONTHS = 12;\n\tstd::vector<int64_t> income;\n\tfor (size_t i = 0; i < MONTHS; ++i)\n\t{\n\t\tincome.push_back(0);\n\t}\n\n\tconst size_t ENTRY_SIZE = 36;\n\tfor (size_t i = 0; i < _rules->getCountries().size(); ++i)\n\t{\n\t\tchar *cdata = (data + i * ENTRY_SIZE);\n\t\tCountry *country = _save->getCountries()->at(i);\n\n\t\tint satisfaction = load<Sint16>(cdata + 0x02);\n\t\tfor (size_t j = 0; j < MONTHS; ++j)\n\t\t{\n\t\t\tint funding = load<Sint16>(cdata + 0x04 + j * sizeof(Sint16));\n\t\t\tfunding *= 1000;\n\t\t\tincome[j] += funding;\n\t\t\tcountry->getFunding().push_back(funding);\n\t\t}\n\t\tbool pact = satisfaction == 0;\n\t\tbool newPact = load<Sint16>(cdata + 0x1E) != 0;\n\n\t\tif (pact)\n\t\t\tcountry->setPact();\n\t\tif (newPact)\n\t\t\tcountry->setNewPact();\n\t}\n\t_save->getIncomes() = income;\n}\n\n/**\n * Loads the ZONAL.DAT file.\n * Contains alien region chances.\n */\nvoid SaveConverter::loadDatZonal()\n{\n\tstd::vector<char> buffer;\n\tchar *data = binaryBuffer(\"ZONAL.DAT\", buffer);\n\n\tstd::map<std::string, int> chances;\n\tconst size_t REGIONS = 12;\n\tfor (size_t i = 0; i < REGIONS; ++i)\n\t{\n\t\tchances[_rules->getRegions()[i]] = load<Uint8>(data + i);\n\t}\n\tYAML::YamlRootNodeWriter writer;\n\twriter.setAsMap();\n\twriter.write(\"regions\", chances);\n\t_save->getAlienStrategy().load(writer.toReader(), _mod);\n}\n\n/**\n * Loads the ACTS.DAT file.\n * Contains alien mission chances.\n */\nvoid SaveConverter::loadDatActs()\n{\n\tstd::vector<char> buffer;\n\tchar *data = binaryBuffer(\"ACTS.DAT\", buffer);\n\n\tstd::map < std::string, std::map<std::string, int> > chances;\n\tconst size_t REGIONS = 12;\n\tconst size_t MISSIONS = 7;\n\tfor (size_t i = 0; i < REGIONS * MISSIONS; ++i)\n\t{\n\t\tsize_t mission = i % MISSIONS;\n\t\tsize_t region = i / MISSIONS;\n\n\t\tchances[_rules->getRegions()[region]][_rules->getMissions()[mission]] = load<Uint8>(data + i);\n\t}\n\n\tYAML::YamlRootNodeWriter writer;\n\twriter.setAsMap();\n\tif (!chances.empty())\n\t{\n\t\tauto possibleMisions = writer[\"possibleMissions\"];\n\t\tpossibleMisions.setAsSeq();\n\t\tfor (const auto& keyMapPair : chances)\n\t\t{\n\t\t\tauto regionAndMissions = possibleMisions.write();\n\t\t\tregionAndMissions.setAsMap();\n\t\t\tregionAndMissions.write(\"region\", keyMapPair.first);\n\t\t\tregionAndMissions.write(\"missions\", keyMapPair.second);\n\t\t}\n\t}\n\t_save->getAlienStrategy().load(writer.toReader(), _mod);\n}\n\n/**\n * Loads the MISSIONS.DAT file.\n * Contains ongoing alien missions.\n */\nvoid SaveConverter::loadDatMissions()\n{\n\tstd::vector<char> buffer;\n\tchar *data = binaryBuffer(\"MISSIONS.DAT\", buffer);\n\n\tconst size_t REGIONS = 12;\n\tconst size_t MISSIONS = 7;\n\tconst size_t ENTRY_SIZE = 8;\n\tfor (size_t i = 0; i < REGIONS * MISSIONS; ++i)\n\t{\n\t\tchar *mdata = (data + i * ENTRY_SIZE);\n\t\tint wave = load<Uint16>(mdata + 0x00);\n\t\tif (wave != 0xFFFF)\n\t\t{\n\t\t\tint ufoCounter = load<Uint16>(mdata + 0x02);\n\t\t\tint spawn = load<Uint16>(mdata + 0x04);\n\t\t\tint race = load<Uint16>(mdata + 0x06);\n\t\t\tint mission = i % MISSIONS;\n\t\t\tint region = i / MISSIONS;\n\n\t\t\tYAML::YamlRootNodeWriter writer;\n\t\t\twriter.setAsMap();\n\t\t\tAlienMission *m = new AlienMission(*_mod->getAlienMission(_rules->getMissions()[mission], true));\n\t\t\twriter.write(\"region\", _rules->getRegions()[region]);\n\t\t\twriter.write(\"race\", _rules->getCrews()[race]);\n\t\t\twriter.write(\"nextWave\", wave);\n\t\t\twriter.write(\"nextUfoCounter\", ufoCounter);\n\t\t\twriter.write(\"spawnCountdown\", spawn * 30);\n\t\t\twriter.write(\"uniqueID\", _save->getId(\"ALIEN_MISSIONS\"));\n\t\t\tif (m->getRules().getObjective() == OBJECTIVE_SITE)\n\t\t\t{\n\t\t\t\tint missionZone = 3; // pick a city for terror missions\n\t\t\t\tRuleRegion *rule = _mod->getRegion(_rules->getRegions()[region], true);\n\t\t\t\tif (rule->getMissionZones().size() <= 3)\n\t\t\t\t{\n\t\t\t\t\t// try to account for TFTD's artefacts and such\n\t\t\t\t\tmissionZone = 0;\n\t\t\t\t}\n\t\t\t\twriter.write(\"missionSiteZone\", RNG::generate(0, rule->getMissionZones().at(missionZone).areas.size() - 1));\n\t\t\t}\n\t\t\tm->load(writer.toReader(), *_save, _mod);\n\t\t\t_save->getAlienMissions().push_back(m);\n\t\t\t_missions[std::make_pair(mission, region)] = m;\n\t\t}\n\t}\n}\n\n/**\n * Loads the LOC.DAT file.\n * Contains globe markers.\n */\nvoid SaveConverter::loadDatLoc()\n{\n\tstd::vector<char> buffer;\n\tchar *data = binaryBuffer(\"LOC.DAT\", buffer);\n\n\tconst size_t ENTRIES = 50;\n\tconst size_t ENTRY_SIZE = buffer.size() / ENTRIES;\n\tfor (size_t i = 0; i < ENTRIES; ++i)\n\t{\n\t\tchar *tdata = (data + i * ENTRY_SIZE);\n\t\tTargetType type = (TargetType)load<Uint8>(tdata);\n\n\t\tint dat = load<Uint8>(tdata + 0x01);\n\t\tdouble lon = Xcom2Rad(load<Sint16>(tdata + 0x02));\n\t\tdouble lat = Xcom2Rad(load<Sint16>(tdata + 0x04));\n\t\tint timer = load<Sint16>(tdata + 0x06);\n\t\tint id = load<Sint16>(tdata + 0x0A);\n\t\tstd::bitset<3> visibility(load<int>(tdata + 0x10));\n\t\tbool detected = !visibility.test(0);\n\n\t\t// can't declare variables in switches :(\n\t\tTarget *target = 0;\n\t\tUfo *ufo = 0;\n\t\tCraft *craft = 0;\n\t\tBase *xbase = 0;\n\t\tAlienBase *abase = 0;\n\t\tWaypoint *waypoint = 0;\n\t\tMissionSite *mission = 0;\n\t\tswitch (type)\n\t\t{\n\t\tcase TARGET_NONE:\n\t\t\ttarget = 0;\n\t\t\tbreak;\n\t\tcase TARGET_UFO:\n\t\tcase TARGET_CRASH:\n\t\tcase TARGET_LANDED:\n\t\t\tufo = new Ufo(_mod->getUfo(_rules->getUfos()[0], true), 0);\n\t\t\tufo->setId(id);\n\t\t\tufo->setCrashId(id);\n\t\t\tufo->setLandId(id);\n\t\t\tufo->setSecondsRemaining(timer);\n\t\t\tufo->setDetected(detected);\n\t\t\ttarget = ufo;\n\t\t\tbreak;\n\t\tcase TARGET_CRAFT:\n\t\t\tcraft = new Craft(_mod->getCraft(_rules->getCrafts()[0], true), 0, id);\n\t\t\ttarget = craft;\n\t\t\tbreak;\n\t\tcase TARGET_XBASE:\n\t\t\txbase = new Base(_mod);\n\t\t\ttarget = xbase;\n\t\t\tbreak;\n\t\tcase TARGET_ABASE:\n\t\t\tabase = new AlienBase(_mod->getDeployment(\"STR_ALIEN_BASE_ASSAULT\", true), 0);\n\t\t\tabase->setId(id);\n\t\t\tabase->setAlienRace(_rules->getCrews()[dat]);\n\t\t\tabase->setDiscovered(detected);\n\t\t\t_save->getAlienBases()->push_back(abase);\n\t\t\ttarget = abase;\n\t\t\tbreak;\n\t\tcase TARGET_WAYPOINT:\n\t\t\twaypoint = new Waypoint();\n\t\t\twaypoint->setId(id);\n\t\t\t_save->getWaypoints()->push_back(waypoint);\n\t\t\ttarget = waypoint;\n\t\t\tbreak;\n\t\tcase TARGET_TERROR:\n\t\t\tmission = new MissionSite(_mod->getAlienMission(\"STR_ALIEN_TERROR\", true), _mod->getDeployment(\"STR_TERROR_MISSION\", true), nullptr);\n\t\t\tbreak;\n\t\tcase TARGET_PORT:\n\t\t\tmission = new MissionSite(_mod->getAlienMission(\"STR_ALIEN_SURFACE_ATTACK\", true), _mod->getDeployment(\"STR_PORT_TERROR\", true), nullptr);\n\t\t\tbreak;\n\t\tcase TARGET_ISLAND:\n\t\t\tmission = new MissionSite(_mod->getAlienMission(\"STR_ALIEN_SURFACE_ATTACK\", true), _mod->getDeployment(\"STR_ISLAND_TERROR\", true), nullptr);\n\t\t\tbreak;\n\t\tcase TARGET_SHIP:\n\t\t\tmission = new MissionSite(_mod->getAlienMission(\"STR_ALIEN_SHIP_ATTACK\", true), _mod->getDeployment(\"STR_CARGO_SHIP_P1\", true), nullptr);\n\t\t\tbreak;\n\t\tcase TARGET_ARTEFACT:\n\t\t\tmission = new MissionSite(_mod->getAlienMission(\"STR_ALIEN_ARTIFACT\", true), _mod->getDeployment(\"STR_ARTIFACT_SITE_P1\", true), nullptr);\n\t\t\tbreak;\n\t\t}\n\t\tif (mission != 0)\n\t\t{\n\t\t\tmission->setId(id);\n\t\t\tmission->setAlienRace(_rules->getCrews()[dat]);\n\t\t\tmission->setSecondsRemaining(timer * 3600);\n\t\t\tmission->setDetected(detected);\n\t\t\t_save->getMissionSites()->push_back(mission);\n\t\t\ttarget = mission;\n\t\t}\n\t\tif (target != 0)\n\t\t{\n\t\t\ttarget->setLongitude(lon);\n\t\t\ttarget->setLatitude(lat);\n\t\t}\n\t\t_targets.push_back(target);\n\t\t_targetDat.push_back(dat);\n\t}\n}\n\n/**\n * Loads the BASE.DAT file.\n * Contains X-COM base contents.\n */\nvoid SaveConverter::loadDatBase()\n{\n\tstd::vector<char> buffer;\n\tchar *data = binaryBuffer(\"BASE.DAT\", buffer);\n\n\tconst size_t BASES = 8;\n\tconst size_t BASE_SIZE = 6;\n\tconst size_t FACILITIES = BASE_SIZE * BASE_SIZE;\n\tconst size_t ENTRY_SIZE = buffer.size() / BASES;\n\tstd::vector<Base*> bases(BASES, 0);\n\tfor (size_t i = 0; i < _targets.size(); ++i)\n\t{\n\t\tBase *base = dynamic_cast<Base*>(_targets[i]);\n\t\tif (base != 0)\n\t\t{\n\t\t\tint j = _targetDat[i];\n\t\t\tchar *bdata = (data + j * ENTRY_SIZE);\n\t\t\tstd::string name = load<std::string>(bdata);\n\t\t\t// facilities\n\t\t\tfor (size_t k = 0; k < FACILITIES; ++k)\n\t\t\t{\n\t\t\t\tsize_t facilityType = load<Uint8>(bdata + _rules->getOffset(\"BASE.DAT_FACILITIES\") + k);\n\t\t\t\tif (facilityType < _rules->getFacilities().size())\n\t\t\t\t{\n\t\t\t\t\tBaseFacility *facility = new BaseFacility(_mod->getBaseFacility(_rules->getFacilities()[facilityType], true), base);\n\t\t\t\t\tint x = k % BASE_SIZE;\n\t\t\t\t\tint y = k / BASE_SIZE;\n\t\t\t\t\tint days = load<Uint8>(bdata + _rules->getOffset(\"BASE.DAT_FACILITIES\") + FACILITIES + k);\n\t\t\t\t\tfacility->setX(x);\n\t\t\t\t\tfacility->setY(y);\n\t\t\t\t\tfacility->setBuildTime(days);\n\t\t\t\t\tbase->getFacilities()->push_back(facility);\n\t\t\t\t}\n\t\t\t}\n\t\t\tint engineers = load<Uint8>(bdata + _rules->getOffset(\"BASE.DAT_ENGINEERS\"));\n\t\t\tint scientists = load<Uint8>(bdata + _rules->getOffset(\"BASE.DAT_SCIENTISTS\"));\n\t\t\t// items\n\t\t\tfor (size_t k = 0; k < _rules->getItems().size(); ++k)\n\t\t\t{\n\t\t\t\tint qty = load<Uint16>(bdata + _rules->getOffset(\"BASE.DAT_ITEMS\") + k * 2);\n\t\t\t\tif (qty != 0 && !_rules->getItems()[k].empty())\n\t\t\t\t{\n\t\t\t\t\tconst RuleItem *rule = _mod->getItem(_rules->getItems()[k], true);\n\t\t\t\t\tbase->getStorageItems()->addItem(rule, qty);\n\t\t\t\t}\n\t\t\t}\n\t\t\tbase->setEngineers(engineers);\n\t\t\tbase->setScientists(scientists);\n\t\t\tbase->setName(name);\n\t\t\tbases[j] = base;\n\t\t}\n\t}\n\n\tfor (auto i = bases.begin(); i != bases.end(); ++i)\n\t{\n\t\tif (*i != 0)\n\t\t{\n\t\t\t_save->getBases()->push_back(*i);\n\t\t}\n\t}\n}\n\n/**\n * Loads the ASTORE.DAT file.\n * Contains X-COM alien containment.\n */\nvoid SaveConverter::loadDatAStore()\n{\n\tstd::vector<char> buffer;\n\tchar *data = binaryBuffer(\"ASTORE.DAT\", buffer);\n\n\tconst size_t ENTRY_SIZE = 12;\n\tconst size_t ENTRIES = buffer.size() / ENTRY_SIZE;\n\tfor (size_t i = 0; i < ENTRIES; ++i)\n\t{\n\t\tchar *adata = (data + i * ENTRY_SIZE);\n\t\tint race = load<Uint8>(adata + 0x00);\n\t\tstd::string liveAlien;\n\t\tif (race != 0)\n\t\t{\n\t\t\tint rank = load<Uint8>(adata + 0x01);\n\t\t\tint base = load<Uint8>(adata + 0x02);\n\t\t\tliveAlien = _rules->getAlienRaces()[race];\n\t\t\tliveAlien += _rules->getAlienRanks()[rank];\n\t\t\tif (base != 0xFF)\n\t\t\t{\n\t\t\t\tBase *b = dynamic_cast<Base*>(_targets[base]);\n\t\t\t\tconst RuleItem *rule = _mod->getItem(liveAlien, true);\n\t\t\t\tb->getStorageItems()->addItem(rule);\n\t\t\t}\n\t\t}\n\t\t_aliens.push_back(liveAlien);\n\t}\n}\n\n/**\n * Loads the TRANSFER.DAT file.\n * Contains transfers to X-COM bases.\n */\nvoid SaveConverter::loadDatTransfer()\n{\n\tstd::vector<char> buffer;\n\tchar *data = binaryBuffer(\"TRANSFER.DAT\", buffer);\n\n\tconst size_t ENTRY_SIZE = 8;\n\tconst size_t ENTRIES = buffer.size() / ENTRY_SIZE;\n\tfor (size_t i = 0; i < ENTRIES; ++i)\n\t{\n\t\tchar *tdata = (data + i * ENTRY_SIZE);\n\t\tint qty = load<Uint8>(tdata + 0x06);\n\t\tif (qty != 0)\n\t\t{\n\t\t\tint baseSrc = load<Uint8>(tdata + 0x00);\n\t\t\tint baseDest = load<Uint8>(tdata + 0x01);\n\t\t\tBase *b = dynamic_cast<Base*>(_targets[baseDest]);\n\t\t\tint hours = load<Uint8>(tdata + 0x02);\n\t\t\tTransferType type = (TransferType)load<Uint8>(tdata + 0x03);\n\t\t\tint dat = load<Uint8>(tdata + 0x04);\n\n\t\t\tTransfer *transfer = new Transfer(hours);\n\t\t\tswitch (type)\n\t\t\t{\n\t\t\tcase TRANSFER_CRAFT:\n\t\t\t\tif (baseSrc == 255)\n\t\t\t\t{\n\t\t\t\t\tstd::string newCraft = _rules->getCrafts()[dat];\n\t\t\t\t\ttransfer->setCraft(new Craft(_mod->getCraft(newCraft, true), b, _save->getId(newCraft)));\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\ttransfer->setCraft(dynamic_cast<Craft*>(_targets[dat]));\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase TRANSFER_SOLDIER:\n\t\t\t\ttransfer->setSoldier(_soldiers[dat]);\n\t\t\t\tbreak;\n\t\t\tcase TRANSFER_SCIENTIST:\n\t\t\t\ttransfer->setScientists(qty);\n\t\t\t\tbreak;\n\t\t\tcase TRANSFER_ENGINEER:\n\t\t\t\ttransfer->setEngineers(qty);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tif (type == TRANSFER_ITEM)\n\t\t\t\t\ttransfer->setItems(_mod->getItem(_rules->getItems()[dat], true), qty);\n\t\t\t\telse\n\t\t\t\t\ttransfer->setItems(_mod->getItem(_aliens[dat], true));\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tb->getTransfers()->push_back(transfer);\n\t\t}\n\t}\n}\n\n\n/**\n * Loads the CRAFT.DAT file.\n * Contains X-COM craft and Alien UFOs.\n */\nvoid SaveConverter::loadDatCraft()\n{\n\tstd::vector<char> buffer;\n\tchar *data = binaryBuffer(\"CRAFT.DAT\", buffer);\n\n\tconst size_t ENTRY_SIZE = buffer.size() / _targets.size();\n\tfor (size_t i = 0; i < _targets.size(); ++i)\n\t{\n\t\tint j = _targetDat[i];\n\t\tchar *cdata = (data + j * ENTRY_SIZE);\n\t\tint type = load<Uint8>(cdata);\n\t\tif (type != 0xFF)\n\t\t{\n\t\t\tYAML::YamlRootNodeWriter writer;\n\t\t\twriter.setAsMap();\n\t\t\tCraft *craft = dynamic_cast<Craft*>(_targets[i]);\n\t\t\tif (craft != 0)\n\t\t\t{\n\t\t\t\tcraft->changeRules(_mod->getCraft(_rules->getCrafts()[type], true));\n\n\t\t\t\tint lweapon = load<Uint8>(cdata + _rules->getOffset(\"CRAFT.DAT_LEFT_WEAPON\"));\n\t\t\t\tint lammo = load<Uint16>(cdata + _rules->getOffset(\"CRAFT.DAT_LEFT_AMMO\"));\n\t\t\t\tif (lweapon != 0xFF)\n\t\t\t\t{\n\t\t\t\t\tCraftWeapon *cw = new CraftWeapon(_mod->getCraftWeapon(_rules->getCraftWeapons()[lweapon], true), lammo);\n\t\t\t\t\tcraft->getWeapons()->at(0) = cw;\n\t\t\t\t}\n\t\t\t\tint flight = load<Uint8>(cdata + _rules->getOffset(\"CRAFT.DAT_FLIGHT\"));\n\t\t\t\tint rweapon = load<Uint8>(cdata + _rules->getOffset(\"CRAFT.DAT_RIGHT_WEAPON\"));\n\t\t\t\tint rammo = load<Uint8>(cdata + _rules->getOffset(\"CRAFT.DAT_RIGHT_AMMO\"));\n\t\t\t\tif (rweapon != 0xFF)\n\t\t\t\t{\n\t\t\t\t\tCraftWeapon *cw = new CraftWeapon(_mod->getCraftWeapon(_rules->getCraftWeapons()[rweapon], true), rammo);\n\t\t\t\t\tcraft->getWeapons()->at(1) = cw;\n\t\t\t\t}\n\n\t\t\t\twriter.write(\"damage\", (int)load<Uint16>(cdata + _rules->getOffset(\"CRAFT.DAT_DAMAGE\")));\n\t\t\t\twriter.write(\"speed\", (int)load<Uint16>(cdata + _rules->getOffset(\"CRAFT.DAT_SPEED\")));\n\t\t\t\tint dest = load<Uint16>(cdata + _rules->getOffset(\"CRAFT.DAT_DESTINATION\"));\n\t\t\t\twriter.write(\"fuel\", (int)load<Uint16>(cdata + _rules->getOffset(\"CRAFT.DAT_FUEL\")));\n\t\t\t\tint base = load<Uint16>(cdata + _rules->getOffset(\"CRAFT.DAT_BASE\"));\n\t\t\t\twriter.write(\"status\", xcomStatus[load<Uint16>(cdata + _rules->getOffset(\"CRAFT.DAT_STATUS\"))]);\n\n\t\t\t\t// vehicles\n\t\t\t\tconst size_t VEHICLES = 5;\n\t\t\t\tfor (size_t k = 0; k < VEHICLES; ++k)\n\t\t\t\t{\n\t\t\t\t\tint qty = load<Uint8>(cdata + _rules->getOffset(\"CRAFT.DAT_ITEMS\") + k);\n\t\t\t\t\tfor (int v = 0; v < qty; ++v)\n\t\t\t\t\t{\n\t\t\t\t\t\tconst RuleItem *rule = _mod->getItem(_rules->getItems()[k + 10], true);\n\t\t\t\t\t\tcraft->getVehicles()->push_back(new Vehicle(rule, rule->getVehicleClipSize(), 4));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// items\n\t\t\t\tconst size_t ITEMS = 50;\n\t\t\t\tfor (size_t k = VEHICLES; k < VEHICLES + ITEMS; ++k)\n\t\t\t\t{\n\t\t\t\t\tint qty = load<Uint8>(cdata + _rules->getOffset(\"CRAFT.DAT_ITEMS\") + k);\n\t\t\t\t\tif (qty != 0 && !_rules->getItems()[k + 10].empty())\n\t\t\t\t\t{\n\t\t\t\t\t\tconst RuleItem *rule = _mod->getItem(_rules->getItems()[k + 10], true);\n\t\t\t\t\t\tcraft->getItems()->addItem(rule, qty);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tstd::bitset<7> state(load<int>(cdata + _rules->getOffset(\"CRAFT.DAT_STATE\")));\n\t\t\t\twriter.write(\"lowFuel\", state.test(1));\n\n\t\t\t\tcraft->load(writer.toReader(), _mod->getScriptGlobal(), _mod, _save);\n\n\t\t\t\tif (flight != 0 && dest != 0xFFFF)\n\t\t\t\t{\n\t\t\t\t\tTarget *t = _targets[dest];\n\t\t\t\t\tcraft->setDestination(t);\n\t\t\t\t}\n\t\t\t\tif (base != 0xFFFF)\n\t\t\t\t{\n\t\t\t\t\tBase *b = dynamic_cast<Base*>(_targets[base]);\n\t\t\t\t\tcraft->setBase(b, false);\n\t\t\t\t\tb->getCrafts()->push_back(craft);\n\t\t\t\t}\n\t\t\t}\n\t\t\tUfo *ufo = dynamic_cast<Ufo*>(_targets[i]);\n\t\t\tif (ufo != 0)\n\t\t\t{\n\t\t\t\tufo->changeRules(_mod->getUfo(_rules->getUfos()[type - 5], true));\n\t\t\t\twriter.write(\"damage\", (int)load<Uint16>(cdata + _rules->getOffset(\"CRAFT.DAT_DAMAGE\")));\n\t\t\t\twriter.write(\"altitude\", xcomAltitudes[load<Uint16>(cdata + _rules->getOffset(\"CRAFT.DAT_ALTITUDE\"))]);\n\t\t\t\twriter.write(\"speed\", (int)load<Uint16>(cdata + _rules->getOffset(\"CRAFT.DAT_SPEED\")));\n\t\t\t\tauto destWriter = writer[\"dest\"];\n\t\t\t\tdestWriter.setAsMap();\n\t\t\t\tdestWriter.write(\"lon\", Xcom2Rad(load<Sint16>(cdata + _rules->getOffset(\"CRAFT.DAT_DEST_LON\"))));\n\t\t\t\tdestWriter.write(\"lat\", Xcom2Rad(load<Sint16>(cdata + _rules->getOffset(\"CRAFT.DAT_DEST_LAT\"))));\n\n\t\t\t\tint mission = load<Uint16>(cdata + _rules->getOffset(\"CRAFT.DAT_MISSION\"));\n\t\t\t\tint region = load<Uint16>(cdata + _rules->getOffset(\"CRAFT.DAT_REGION\"));\n\t\t\t\tstd::ostringstream trajectory;\n\t\t\t\tAlienMission *m = _missions[std::make_pair(mission, region)];\n\t\t\t\tif (m == 0)\n\t\t\t\t{\n\t\t\t\t\tYAML::YamlRootNodeWriter missionWriter;\n\t\t\t\t\tmissionWriter.setAsMap();\n\t\t\t\t\tm = new AlienMission(*_mod->getAlienMission(_rules->getMissions()[mission], true));\n\t\t\t\t\tmissionWriter.write(\"region\", _rules->getRegions()[region]);\n\t\t\t\t\tmissionWriter.write(\"race\", _rules->getCrews()[load<Uint16>(cdata + _rules->getOffset(\"CRAFT.DAT_RACE\"))]);\n\t\t\t\t\tmissionWriter.write(\"nextWave\", 1);\n\t\t\t\t\tmissionWriter.write(\"nextUfoCounter\", 0);\n\t\t\t\t\tmissionWriter.write(\"spawnCountdown\", 1000);\n\t\t\t\t\tmissionWriter.write(\"uniqueID\", _save->getId(\"ALIEN_MISSIONS\"));\n\t\t\t\t\tm->load(missionWriter.toReader(), *_save, _mod);\n\t\t\t\t\t_save->getAlienMissions().push_back(m);\n\t\t\t\t\t_missions[std::make_pair(mission, region)] = m;\n\t\t\t\t\tif (mission == 6)\n\t\t\t\t\t{\n\t\t\t\t\t\ttrajectory << UfoTrajectory::RETALIATION_ASSAULT_RUN;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\twriter.write(\"mission\", m->getId());\n\t\t\t\tm->increaseLiveUfos();\n\t\t\t\tif (trajectory.str().empty())\n\t\t\t\t{\n\t\t\t\t\ttrajectory << \"P\" << load<Uint16>(cdata + _rules->getOffset(\"CRAFT.DAT_TRAJECTORY\"));\n\t\t\t\t}\n\t\t\t\twriter.write(\"trajectory\", trajectory.str());\n\t\t\t\twriter.write(\"trajectoryPoint\", (int)load<Uint16>(cdata + _rules->getOffset(\"CRAFT.DAT_TRAJECTORY_POINT\")));\n\t\t\t\tstd::bitset<7> state(load<int>(cdata + _rules->getOffset(\"CRAFT.DAT_STATE\")));\n\t\t\t\twriter.write(\"hyperDetected\", state.test(6));\n\n\t\t\t\tufo->load(writer.toReader(), _mod->getScriptGlobal(), *_mod, *_save);\n\t\t\t\tufo->setSpeed(ufo->getSpeed());\n\t\t\t\tif (ufo->getStatus() == Ufo::CRASHED)\n\t\t\t\t{\n\t\t\t\t\tufo->setSecondsRemaining(ufo->getSecondsRemaining() * 3600);\n\t\t\t\t}\n\t\t\t\telse if (ufo->getStatus() == Ufo::LANDED)\n\t\t\t\t{\n\t\t\t\t\tufo->setSecondsRemaining(ufo->getSecondsRemaining() * 5);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tufo->setSecondsRemaining(0);\n\t\t\t\t}\n\n\t\t\t\t_save->getUfos()->push_back(ufo);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Loads the SOLDIER.DAT file.\n * Contains X-COM soldiers.\n */\nvoid SaveConverter::loadDatSoldier()\n{\n\tstd::vector<char> buffer;\n\tchar *data = binaryBuffer(\"SOLDIER.DAT\", buffer);\n\n\tconst size_t SOLDIERS = 250;\n\tconst size_t ENTRY_SIZE = buffer.size() / SOLDIERS;\n\tfor (size_t i = 0; i < SOLDIERS; ++i)\n\t{\n\t\tchar *sdata = (data + i * ENTRY_SIZE);\n\t\tint rank = load<Uint16>(sdata + _rules->getOffset(\"SOLDIER.DAT_RANK\"));\n\t\tif (rank != 0xFFFF)\n\t\t{\n\t\t\tYAML::YamlRootNodeWriter writer;\n\t\t\twriter.setAsMap();\n\t\t\tint base = load<Uint16>(sdata + _rules->getOffset(\"SOLDIER.DAT_BASE\"));\n\t\t\tint craft = load<Uint16>(sdata + _rules->getOffset(\"SOLDIER.DAT_CRAFT\"));\n\t\t\twriter.write(\"missions\", (int)load<Sint16>(sdata + _rules->getOffset(\"SOLDIER.DAT_MISSIONS\")));\n\t\t\twriter.write(\"kills\", (int)load<Sint16>(sdata + _rules->getOffset(\"SOLDIER.DAT_KILLS\")));\n\t\t\twriter.write(\"recovery\", (int)load<Sint16>(sdata + _rules->getOffset(\"SOLDIER.DAT_RECOVERY\")));\n\t\t\twriter.write(\"name\", load<std::string>(sdata + _rules->getOffset(\"SOLDIER.DAT_NAME\")));\n\t\t\twriter.write(\"rank\", rank);\n\n\t\t\tUnitStats initial;\n\t\t\tinitial.tu = load<Uint8>(sdata + _rules->getOffset(\"SOLDIER.DAT_INITIAL_TU\"));\n\t\t\tinitial.health = load<Uint8>(sdata + _rules->getOffset(\"SOLDIER.DAT_INITIAL_HE\"));\n\t\t\tinitial.stamina = load<Uint8>(sdata + _rules->getOffset(\"SOLDIER.DAT_INITIAL_STA\"));\n\t\t\tinitial.reactions = load<Uint8>(sdata + _rules->getOffset(\"SOLDIER.DAT_INITIAL_RE\"));\n\t\t\tinitial.strength = load<Uint8>(sdata + _rules->getOffset(\"SOLDIER.DAT_INITIAL_STR\"));\n\t\t\tinitial.firing = load<Uint8>(sdata + _rules->getOffset(\"SOLDIER.DAT_INITIAL_FA\"));\n\t\t\tinitial.throwing = load<Uint8>(sdata + _rules->getOffset(\"SOLDIER.DAT_INITIAL_TA\"));\n\t\t\tinitial.melee = load<Uint8>(sdata + _rules->getOffset(\"SOLDIER.DAT_INITIAL_ME\"));\n\t\t\tinitial.psiStrength = load<Uint8>(sdata + _rules->getOffset(\"SOLDIER.DAT_INITIAL_PST\"));\n\t\t\tinitial.psiSkill = load<Uint8>(sdata + _rules->getOffset(\"SOLDIER.DAT_INITIAL_PSK\"));\n\t\t\tinitial.bravery = 110 - (10 * load<Uint8>(sdata + _rules->getOffset(\"SOLDIER.DAT_INITIAL_BR\")));\n\t\t\twriter.write(\"initialStats\", initial);\n\n\t\t\tUnitStats current;\n\t\t\tcurrent.tu = load<Uint8>(sdata + _rules->getOffset(\"SOLDIER.DAT_IMPROVED_TU\"));\n\t\t\tcurrent.health = load<Uint8>(sdata + _rules->getOffset(\"SOLDIER.DAT_IMPROVED_HE\"));\n\t\t\tcurrent.stamina = load<Uint8>(sdata + _rules->getOffset(\"SOLDIER.DAT_IMPROVED_STA\"));\n\t\t\tcurrent.reactions = load<Uint8>(sdata + _rules->getOffset(\"SOLDIER.DAT_IMPROVED_RE\"));\n\t\t\tcurrent.strength = load<Uint8>(sdata + _rules->getOffset(\"SOLDIER.DAT_IMPROVED_STR\"));\n\t\t\tcurrent.firing = load<Uint8>(sdata + _rules->getOffset(\"SOLDIER.DAT_IMPROVED_FA\"));\n\t\t\tcurrent.throwing = load<Uint8>(sdata + _rules->getOffset(\"SOLDIER.DAT_IMPROVED_TA\"));\n\t\t\tcurrent.melee = load<Uint8>(sdata + _rules->getOffset(\"SOLDIER.DAT_IMPROVED_ME\"));\n\t\t\tcurrent.psiStrength = 0;\n\t\t\tcurrent.psiSkill = 0;\n\t\t\tcurrent.bravery = 10 * load<Uint8>(sdata + _rules->getOffset(\"SOLDIER.DAT_IMPROVED_BR\"));\n\t\t\tcurrent += initial;\n\t\t\twriter.write(\"currentStats\", current);\n\n\t\t\tint armor = load<Uint8>(sdata + _rules->getOffset(\"SOLDIER.DAT_ARMOR\"));\n\t\t\tconst std::vector<std::string> &armors = _rules->getArmor();\n\t\t\tif (armor >= 0 && armor < (int)armors.size())\n\t\t\t{\n\t\t\t\twriter.write(\"armor\", armors[armor]);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tthrow Exception(\"Invalid armor index. Modded saves are not supported.\");\n\t\t\t}\n\t\t\twriter.write(\"improvement\", (int)load<Uint8>(sdata + _rules->getOffset(\"SOLDIER.DAT_PSI\")));\n\t\t\twriter.write(\"psiTraining\", (int)load<char>(sdata + _rules->getOffset(\"SOLDIER.DAT_PSILAB\")) != 0);\n\t\t\twriter.write(\"gender\", (int)load<Uint8>(sdata + _rules->getOffset(\"SOLDIER.DAT_GENDER\")));\n\t\t\twriter.write(\"look\", (int)load<Uint8>(sdata + _rules->getOffset(\"SOLDIER.DAT_LOOK\")));\n\t\t\twriter.write(\"id\", _save->getId(\"STR_SOLDIER\"));\n\n\t\t\tSoldier *soldier = new Soldier(_mod->getSoldier(_mod->getSoldiersList().front(), true), nullptr, 0 /*nationality*/);\n\t\t\tsoldier->load(writer.toReader(), _mod, _save, _mod->getScriptGlobal());\n\t\t\tif (base != 0xFFFF)\n\t\t\t{\n\t\t\t\tBase *b = dynamic_cast<Base*>(_targets[base]);\n\t\t\t\tb->getSoldiers()->push_back(soldier);\n\t\t\t}\n\t\t\tif (craft != 0xFFFF)\n\t\t\t{\n\t\t\t\tCraft *c = dynamic_cast<Craft*>(_targets[craft]);\n\t\t\t\tsoldier->setCraft(c);\n\t\t\t}\n\t\t\t_soldiers.push_back(soldier);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_soldiers.push_back(0);\n\t\t}\n\t}\n}\n\n/**\n * Loads the RESEARCH.DAT file.\n * Contains X-COM research progress.\n */\nvoid SaveConverter::loadDatResearch()\n{\n\tstd::vector<char> buffer;\n\tchar *data = binaryBuffer(\"RESEARCH.DAT\", buffer);\n\n\tconst size_t ENTRY_SIZE = buffer.size() / _rules->getResearch().size();\n\tfor (size_t i = 0; i < _rules->getResearch().size(); ++i)\n\t{\n\t\tchar *rdata = (data + i * ENTRY_SIZE);\n\t\tif (!_rules->getResearch()[i].empty())\n\t\t{\n\t\t\tRuleResearch *research = _mod->getResearch(_rules->getResearch()[i]);\n\t\t\tif (research != 0 && research->getCost() != 0)\n\t\t\t{\n\t\t\t\tbool discovered = load<Uint8>(rdata + 0x0A) != 0;\n\t\t\t\tbool popped = load<Uint8>(rdata + 0x12) != 0;\n\t\t\t\tif (discovered)\n\t\t\t\t{\n\t\t\t\t\t_save->addFinishedResearch(research, _mod, 0, false);\n\t\t\t\t}\n\t\t\t\telse if (popped)\n\t\t\t\t{\n\t\t\t\t\t_save->addPoppedResearch(research);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Loads the UP.DAT file.\n * Contains X-COM Ufopaedia progress.\n */\nvoid SaveConverter::loadDatUp()\n{\n\tstd::vector<char> buffer;\n\tchar *data = binaryBuffer(\"UP.DAT\", buffer);\n\n\tconst size_t ENTRY_SIZE = buffer.size() / _rules->getUfopaedia().size();\n\tfor (size_t i = 0; i < _rules->getUfopaedia().size(); ++i)\n\t{\n\t\tchar *rdata = (data + i * ENTRY_SIZE);\n\t\tArticleDefinition *article = _mod->getUfopaediaArticle(_rules->getUfopaedia()[i]);\n\t\tif (article != 0 && article->section != UFOPAEDIA_NOT_AVAILABLE)\n\t\t{\n\t\t\tbool discovered = load<Uint8>(rdata + 0x08) == 2;\n\t\t\tif (discovered)\n\t\t\t{\n\t\t\t\tfor (const auto& req : article->_requires)\n\t\t\t\t{\n\t\t\t\t\tRuleResearch *research = _mod->getResearch(req);\n\t\t\t\t\tif (research && research->getCost() == 0)\n\t\t\t\t\t{\n\t\t\t\t\t\t_save->addFinishedResearch(research, _mod, 0, false);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Loads the PROJECT.DAT file.\n * Contains X-COM research projects.\n */\nvoid SaveConverter::loadDatProject()\n{\n\tstd::vector<char> buffer;\n\tchar *data = binaryBuffer(\"PROJECT.DAT\", buffer);\n\n\tconst size_t ENTRIES = _rules->getResearch().size();\n\t// days (Uint16) | scientists (Uint8)\n\tconst size_t ENTRY_SIZE = ENTRIES * (sizeof(Uint16) + sizeof(Uint8));\n\tfor (size_t i = 0; i < _save->getBases()->size(); ++i)\n\t{\n\t\tBase *base = _save->getBases()->at(i);\n\t\tchar *pdata = (data + i * ENTRY_SIZE);\n\t\tUint16 *arrRemaining = (Uint16*)pdata;\n\t\tUint8 *arrScientists = (Uint8*)(&arrRemaining[ENTRIES]);\n\t\tfor (size_t j = 0; j < _rules->getResearch().size(); ++j)\n\t\t{\n\t\t\tint remaining = load<Uint16>((char*)&arrRemaining[j]);\n\t\t\tint scientists = load<Uint8>((char*)&arrScientists[j]);\n\t\t\tif (remaining != 0 && !_rules->getResearch()[j].empty())\n\t\t\t{\n\t\t\t\tRuleResearch *research = _mod->getResearch(_rules->getResearch()[j]);\n\t\t\t\tif (research != 0 && research->getCost() != 0)\n\t\t\t\t{\n\t\t\t\t\tResearchProject *project = new ResearchProject(research, research->getCost());\n\t\t\t\t\tproject->setAssigned(scientists);\n\t\t\t\t\tproject->setSpent(project->getCost() - remaining);\n\t\t\t\t\tbase->addResearch(project);\n\t\t\t\t\tbase->setScientists(base->getScientists() - scientists);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Loads the BPROD.DAT file.\n * Contains X-COM manufacture projects.\n */\nvoid SaveConverter::loadDatBProd()\n{\n\tstd::vector<char> buffer;\n\tchar *data = binaryBuffer(\"BPROD.DAT\", buffer);\n\n\tconst size_t ENTRIES = _rules->getManufacture().size();\n\t// hours (int) | engineers (Uint16) | quantity (Uint16)| produced (Uint16)\n\tconst size_t ENTRY_SIZE = ENTRIES * (sizeof(int) + 3 * sizeof(Uint16));\n\tfor (size_t i = 0; i < _save->getBases()->size(); ++i)\n\t{\n\t\tBase *base = _save->getBases()->at(i);\n\t\tchar *pdata = (data + i * ENTRY_SIZE);\n\t\tint *arrRemaining = (int*)pdata;\n\t\tUint16 *arrEngineers = (Uint16*)(&arrRemaining[ENTRIES]);\n\t\tUint16 *arrTotal = (Uint16*)(&arrEngineers[ENTRIES]);\n\t\tUint16 *arrProduced = (Uint16*)(&arrTotal[ENTRIES]);\n\t\tfor (size_t j = 0; j < _rules->getManufacture().size(); ++j)\n\t\t{\n\t\t\tint remaining = load<int>((char*)&arrRemaining[j]);\n\t\t\tint engineers = load<Uint16>((char*)&arrEngineers[j]);\n\t\t\tint total = load<Uint16>((char*)&arrTotal[j]);\n\t\t\tint produced = load<Uint16>((char*)&arrProduced[j]);\n\t\t\tif (remaining != 0 && !_rules->getManufacture()[j].empty())\n\t\t\t{\n\t\t\t\tRuleManufacture *manufacture = _mod->getManufacture(_rules->getManufacture()[j]);\n\t\t\t\tif (manufacture != 0)\n\t\t\t\t{\n\t\t\t\t\tProduction *project = new Production(manufacture, total);\n\t\t\t\t\tproject->setAssignedEngineers(engineers);\n\t\t\t\t\tproject->setTimeSpent(produced * manufacture->getManufactureTime() + manufacture->getManufactureTime() - remaining);\n\t\t\t\t\tbase->addProduction(project);\n\t\t\t\t\tbase->setEngineers(base->getEngineers() - engineers);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Loads the XBASES.DAT file.\n * Contains targeted X-COM bases.\n */\nvoid SaveConverter::loadDatXBases()\n{\n\tstd::vector<char> buffer;\n\tchar *data = binaryBuffer(\"XBASES.DAT\", buffer);\n\tconst size_t REGIONS = 12;\n\tfor (size_t i = 0; i < REGIONS; ++i)\n\t{\n\t\tchar *bdata = (data + i * 4);\n\t\tbool detected = load<Uint16>(bdata + 0x00) != 0;\n\t\tif (detected)\n\t\t{\n\t\t\tint loc = load<Uint16>(bdata + 0x02);\n\t\t\tBase *base = dynamic_cast<Base*>(_targets[loc]);\n\t\t\tif (base != 0)\n\t\t\t{\n\t\t\t\tbase->setRetaliationTarget(true);\n\t\t\t}\n\t\t}\n\t}\n\n}\n\n}\n"
  },
  {
    "path": "src/Savegame/SaveConverter.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include <vector>\n#include <map>\n#include <utility>\n\nnamespace OpenXcom\n{\n\n/**\n * Container for savegame info displayed on listings.\n */\nstruct SaveOriginal\n{\n\tint id;\n\tstd::string name, date, time;\n\tbool tactical;\n\tSaveOriginal() : id(0), tactical(false)\n\t{\n\t}\n};\n\nclass SavedGame;\nclass Mod;\nclass Language;\nclass Target;\nclass Soldier;\nclass AlienMission;\nclass RuleConverter;\n\n/**\n * Handles conversion operations for original X-COM savegames.\n * @sa http://ufopaedia.org/index.php?title=Saved_Game_Files\n */\nclass SaveConverter\n{\nprivate:\n\tstd::string _saveName, _savePath;\n\tSavedGame *_save;\n\tMod *_mod;\n\tRuleConverter *_rules;\n\tint _year, _funds;\n\tstd::vector<Target*> _targets;\n\tstd::vector<int> _targetDat;\n\tstd::vector<Soldier*> _soldiers;\n\tstd::vector<std::string> _aliens;\n\tstd::map<std::pair<int, int>, AlienMission*> _missions;\n\n\t/// Loads a binary file into a vector.\n\tchar *binaryBuffer(const std::string &filename, std::vector<char> &buffer) const;\n\t/// Corrects a vector of graph data.\n\ttemplate <typename T> void graphVector(std::vector<T> &vector, int month, bool year);\n\n\t/// Load XCOM.DAT\n\tvoid loadDatXcom();\n\t/// Load ALIEN.DAT\n\tvoid loadDatAlien();\n\t/// Load DIPLOM.DAT\n\tvoid loadDatDiplom();\n\t/// Load LEASE.DAT\n\tvoid loadDatLease();\n\t/// Load LIGLOB.DAT\n\tvoid loadDatLIGlob();\n\t/// Load UIGLOB.DAT\n\tvoid loadDatUIGlob();\n\t/// Load IGLOB.DAT\n\tvoid loadDatIGlob();\n\t/// Load ZONAL.DAT\n\tvoid loadDatZonal();\n\t/// Load ACTS.DAT\n\tvoid loadDatActs();\n\t/// Load MISSIONS.DAT\n\tvoid loadDatMissions();\n\t/// Load LOC.DAT\n\tvoid loadDatLoc();\n\t/// Load BASE.DAT\n\tvoid loadDatBase();\n\t/// Load ASTORE.DAT\n\tvoid loadDatAStore();\n\t/// Load CRAFT.DAT\n\tvoid loadDatCraft();\n\t/// Load SOLDIER.DAT\n\tvoid loadDatSoldier();\n\t/// Load TRANSFER.DAT\n\tvoid loadDatTransfer();\n\t/// Load RESEARCH.DAT\n\tvoid loadDatResearch();\n\t/// Load UP.DAT\n\tvoid loadDatUp();\n\t/// Load PROJECT.DAT\n\tvoid loadDatProject();\n\t/// Load BPROD.DAT\n\tvoid loadDatBProd();\n\t/// Load XBASES.DAT\n\tvoid loadDatXBases();\npublic:\n\tstatic const int NUM_SAVES = 10;\n\n\t/// Creates a converter for the specified save.\n\tSaveConverter(int save, Mod *mod);\n\t/// Cleans up the converter.\n\t~SaveConverter();\n\t/// Gets list of saves in the user directory.\n\tstatic void getList(Language *lang, SaveOriginal info[NUM_SAVES]);\n\t/// Loads an original X-COM save.\n\tSavedGame *loadOriginal();\n};\n\n}\n"
  },
  {
    "path": "src/Savegame/SavedBattleGame.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <assert.h>\n#include <vector>\n#include \"BattleItem.h\"\n#include \"ItemContainer.h\"\n#include \"Base.h\"\n#include \"Craft.h\"\n#include \"SavedBattleGame.h\"\n#include \"SavedGame.h\"\n#include \"Tile.h\"\n#include \"HitLog.h\"\n#include \"Node.h\"\n#include \"../Mod/MapDataSet.h\"\n#include \"../Battlescape/Pathfinding.h\"\n#include \"../Battlescape/TileEngine.h\"\n#include \"../Battlescape/BattlescapeState.h\"\n#include \"../Battlescape/BattlescapeGame.h\"\n#include \"../Battlescape/Position.h\"\n#include \"../Battlescape/Inventory.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Sound.h\"\n#include \"../Mod/RuleInventory.h\"\n#include \"../Battlescape/AIModule.h\"\n#include \"../Engine/RNG.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Logger.h\"\n#include \"../Engine/ScriptBind.h\"\n#include \"SerializationHelper.h\"\n#include \"../Mod/RuleStartingCondition.h\"\n#include \"../Mod/RuleEnviroEffects.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"../Mod/RuleSoldier.h\"\n#include \"../Mod/RuleSoldierBonus.h\"\n#include \"../Mod/RuleWeaponSet.h\"\n#include \"../fallthrough.h\"\n#include \"../fmath.h\"\n#include \"../Engine/Language.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes a brand new battlescape saved game.\n */\nSavedBattleGame::SavedBattleGame(Mod *rule, Language *lang, bool isPreview) :\n\t_isPreview(isPreview), _craftPos(), _craftZ(0), _craftForPreview(nullptr),\n\t_battleState(0), _rule(rule), _mapsize_x(0), _mapsize_y(0), _mapsize_z(0), _selectedUnit(0), _undoUnit(nullptr),\n\t_lastSelectedUnit(0), _pathfinding(0), _tileEngine(0),\n\t_reinforcementsItemLevel(0), _startingCondition(nullptr), _enviroEffects(nullptr), _ecEnabledFriendly(false), _ecEnabledHostile(false), _ecEnabledNeutral(false),\n\t_globalShade(0), _side(FACTION_PLAYER), _turn(0), _bughuntMinTurn(20), _animFrame(0), _nameDisplay(false),\n\t_debugMode(false), _bughuntMode(false), _aborted(false), _itemId(0),\n\t_vipEscapeType(ESCAPE_NONE), _vipSurvivalPercentage(0), _vipsSaved(0), _vipsLost(0), _vipsWaitingOutside(0), _vipsSavedScore(0), _vipsLostScore(0), _vipsWaitingOutsideScore(0),\n\t_objectiveType(-1), _objectivesDestroyed(0), _objectivesNeeded(0),\n\t_unitsFalling(false), _cheating(false), _tuReserved(BA_NONE), _kneelReserved(false), _depth(0),\n\t_ambience(-1), _ambientVolume(0.5), _minAmbienceRandomDelay(20), _maxAmbienceRandomDelay(60), _currentAmbienceDelay(0),\n\t_turnLimit(0), _cheatTurn(20), _chronoTrigger(FORCE_LOSE), _beforeGame(true),\n\t_togglePersonalLight(true), _toggleNightVision(false), _toggleBrightness(0)\n{\n\t_tileSearch.resize(11*11);\n\tfor (int i = 0; i < 121; ++i)\n\t{\n\t\t_tileSearch[i].x = ((i%11) - 5);\n\t\t_tileSearch[i].y = ((i/11) - 5);\n\t}\n\t_baseItems = new ItemContainer();\n\t_hitLog = new HitLog(lang);\n\n\tsetRandomHiddenMovementBackground(_rule);\n}\n\n/**\n * Deletes the game content from memory.\n */\nSavedBattleGame::~SavedBattleGame()\n{\n\tfor (auto* mds : _mapDataSets)\n\t{\n\t\tmds->unloadData();\n\t}\n\tfor (auto* node : _nodes)\n\t{\n\t\tdelete node;\n\t}\n\tfor (auto* bu : _units)\n\t{\n\t\tdelete bu;\n\t}\n\tfor (auto bi : _items)\n\t{\n\t\tdelete bi;\n\t}\n\tfor (auto* bi : _recoverGuaranteed)\n\t{\n\t\tdelete bi;\n\t}\n\tfor (auto* bi : _recoverConditional)\n\t{\n\t\tdelete bi;\n\t}\n\tfor (auto* bi : _deleted)\n\t{\n\t\tdelete bi;\n\t}\n\tdelete _pathfinding;\n\tdelete _tileEngine;\n\tdelete _baseItems;\n\tdelete _hitLog;\n}\n\n/**\n * Loads the saved battle game from a YAML file.\n * @param node YAML node.\n * @param mod for the saved game.\n * @param savedGame Pointer to saved game.\n */\nvoid SavedBattleGame::load(const YAML::YamlNodeReader& node, Mod *mod, SavedGame* savedGame)\n{\n\tconst auto& reader = node.useIndex();\n\tint mapsize_x = reader[\"width\"].readVal(_mapsize_x);\n\tint mapsize_y = reader[\"length\"].readVal(_mapsize_y);\n\tint mapsize_z = reader[\"height\"].readVal(_mapsize_z);\n\tinitMap(mapsize_x, mapsize_y, mapsize_z);\n\n\treader.tryRead(\"missionType\", _missionType);\n\treader.tryRead(\"strTarget\", _strTarget);\n\treader.tryRead(\"strCraftOrBase\", _strCraftOrBase);\n\tif (reader[\"startingConditionType\"])\n\t{\n\t\tstd::string startingConditionType = reader[\"startingConditionType\"].readVal<std::string>();\n\t\t_startingCondition = mod->getStartingCondition(startingConditionType);\n\t}\n\tif (reader[\"enviroEffectsType\"])\n\t{\n\t\tstd::string enviroEffectsType = reader[\"enviroEffectsType\"].readVal<std::string>();\n\t\t_enviroEffects = mod->getEnviroEffects(enviroEffectsType);\n\t}\n\treader.tryRead(\"nameDisplay\", _nameDisplay);\n\treader.tryRead(\"ecEnabledFriendly\", _ecEnabledFriendly);\n\treader.tryRead(\"ecEnabledHostile\", _ecEnabledHostile);\n\treader.tryRead(\"ecEnabledNeutral\", _ecEnabledNeutral);\n\treader.tryRead(\"alienCustomDeploy\", _alienCustomDeploy);\n\treader.tryRead(\"alienCustomMission\", _alienCustomMission);\n\treader.tryRead(\"alienItemLevel\", _alienItemLevel);\n\treader.tryRead(\"lastUsedMapScript\", _lastUsedMapScript);\n\treader.tryRead(\"reinforcementsDeployment\", _reinforcementsDeployment);\n\treader.tryRead(\"reinforcementsRace\", _reinforcementsRace);\n\treader.tryRead(\"reinforcementsItemLevel\", _reinforcementsItemLevel);\n\treader.tryRead(\"reinforcementsMemory\", _reinforcementsMemory);\n\treader.tryRead(\"reinforcementsBlocks\", _reinforcementsBlocks);\n\treader.tryRead(\"flattenedMapTerrainNames\", _flattenedMapTerrainNames);\n\treader.tryRead(\"flattenedMapBlockNames\", _flattenedMapBlockNames);\n\treader.tryRead(\"globalshade\", _globalShade);\n\treader.tryRead(\"turn\", _turn);\n\treader.tryRead(\"bughuntMinTurn\", _bughuntMinTurn);\n\treader.tryRead(\"bughuntMode\", _bughuntMode);\n\treader.tryRead(\"depth\", _depth);\n\treader.tryRead(\"animFrame\", _animFrame);\n\tint selectedUnitId = reader[\"selectedUnit\"].readVal<int>();\n\tint undoUnitId = reader[\"undoUnit\"].readVal<int>(-1);\n\n\tfor (const auto& mdsReader : reader[\"mapdatasets\"].children())\n\t{\n\t\tstd::string name = mdsReader.readVal<std::string>();\n\t\tMapDataSet *mds = mod->getMapDataSet(name);\n\t\t_mapDataSets.push_back(mds);\n\t}\n\n\tif (!reader[\"tileTotalBytesPer\"])\n\t{\n\t\t// binary tile data not found, load old-style text tiles :(\n\t\tfor (const auto& tile : reader[\"tiles\"].children())\n\t\t{\n\t\t\tPosition pos = tile[\"position\"].readVal<Position>();\n\t\t\tgetTile(pos)->load(tile);\n\t\t}\n\t}\n\telse\n\t{\n\t\t// load key to how the tile data was saved\n\t\tTile::SerializationKey serKey;\n\t\tsize_t totalTiles = reader[\"totalTiles\"].readVal<size_t>();\n\n\t\tmemset(&serKey, 0, sizeof(Tile::SerializationKey));\n\t\tserKey.index = reader[\"tileIndexSize\"].readVal<char>(serKey.index);\n\t\tserKey.totalBytes = reader[\"tileTotalBytesPer\"].readVal<Uint32>(serKey.totalBytes);\n\t\tserKey._fire = reader[\"tileFireSize\"].readVal<char>(serKey._fire);\n\t\tserKey._smoke = reader[\"tileSmokeSize\"].readVal<char>(serKey._smoke);\n\t\tserKey._mapDataID = reader[\"tileIDSize\"].readVal<char>(serKey._mapDataID);\n\t\tserKey._mapDataSetID = reader[\"tileSetIDSize\"].readVal<char>(serKey._mapDataSetID);\n\t\tserKey.boolFields = reader[\"tileBoolFieldsSize\"].readVal<char>(1); // boolean flags used to be stored in an unmentioned byte (Uint8) :|\n\n\t\t// load binary tile data!\n\t\tstd::vector<char> binTiles = reader[\"binTiles\"].readValBase64();\n\n\t\tUint8* ptr = (Uint8*)binTiles.data();\n\t\tUint8* dataEnd = ptr + totalTiles * serKey.totalBytes;\n\n\t\twhile (ptr < dataEnd)\n\t\t{\n\t\t\tint index = unserializeInt(&ptr, serKey.index);\n\t\t\tassert(index >= 0 && index < _mapsize_x * _mapsize_z * _mapsize_y);\n\t\t\t_tiles[index].loadBinary(ptr, serKey); // loadBinary's privileges to advance *r have been revoked\n\t\t\tptr += serKey.totalBytes - serKey.index; // r is now incremented strictly by totalBytes in case there are obsolete fields present in the data\n\t\t}\n\t}\n\n\tif (_missionType == \"STR_BASE_DEFENSE\")\n\t{\n\t\tif (!reader.tryRead(\"moduleMap\", _baseModules))\n\t\t{\n\t\t\t// backwards compatibility: imperfect solution, modules that were completely destroyed\n\t\t\t// prior to saving and updating builds will be counted as indestructible.\n\t\t\tcalculateModuleMap();\n\t\t}\n\t}\n\tfor (const auto& nodeConfig : reader[\"nodes\"].children())\n\t{\n\t\tNode *n = new Node();\n\t\tn->load(nodeConfig);\n\t\t_nodes.push_back(n);\n\t}\n\n\t//always reserve the sizes of your collections if you can\n\t_units.reserve(reader[\"units\"].childrenCount());\n\t_items.reserve(reader[\"items\"].childrenCount() + reader[\"itemsSpecial\"].childrenCount());\n\t_recoverConditional.reserve(reader[\"recoverConditional\"].childrenCount());\n\t_recoverGuaranteed.reserve(reader[\"recoverGuaranteed\"].childrenCount());\n\t// int -> BattleUnit; dictionaries for O(1) ID searching\n\tstd::unordered_map<int, BattleUnit*> unitIndex;\n\tstd::unordered_map<int, BattleItem*> itemIndex;\n\tunitIndex.reserve(_units.capacity());\n\titemIndex.reserve(_items.capacity() + _recoverConditional.capacity() + _recoverGuaranteed.capacity());\n\n\tauto findUnitById = [&](const YAML::YamlNodeReader& r) -> BattleUnit*\n\t{\n\t\tint id = r.readVal(-1);\n\t\tif (id == -1 || !unitIndex.count(id))\n\t\t\treturn nullptr;\n\t\treturn unitIndex.at(id);\n\t};\n\n\t// units 1st pass\n\tfor (const auto& unitReader : reader[\"units\"].children())\n\t{\n\t\tUnitFaction faction = unitReader[\"faction\"].readVal<UnitFaction>();\n\t\tUnitFaction originalFaction = unitReader[\"originalFaction\"].readVal(faction);\n\t\tint id = unitReader[\"id\"].readVal<int>();\n\t\tBattleUnit* unit;\n\t\tif (id < BattleUnit::MAX_SOLDIER_ID) // Unit is linked to a geoscape soldier\n\t\t\tunit = new BattleUnit(mod, savedGame->getSoldier(id), _depth, nullptr); // look up the matching soldier\n\t\telse\n\t\t{\n\t\t\tstd::string type = unitReader[\"genUnitType\"].readVal<std::string>();\n\t\t\tstd::string armor = unitReader[\"genUnitArmor\"].readVal<std::string>();\n\t\t\t// create a new Unit.\n\t\t\tif (!mod->getUnit(type) || !mod->getArmor(armor))\n\t\t\t\tcontinue;\n\t\t\tunit = new BattleUnit(mod, mod->getUnit(type), originalFaction, id, nullptr, mod->getArmor(armor), mod->getStatAdjustment(savedGame->getDifficulty()), _depth, nullptr);\n\t\t}\n\t\tunit->load(unitReader, this->getMod(), this->getMod()->getScriptGlobal());\n\t\t// Handling of special built-in weapons will be done during and after the load of items\n\t\t// unit->setSpecialWeapon(this, true);\n\t\tif (faction == FACTION_PLAYER)\n\t\t{\n\t\t\tif ((unit->getId() == selectedUnitId) || (_selectedUnit == 0 && !unit->isOut()))\n\t\t\t\t_selectedUnit = unit;\n\t\t\tif (unit->getId() == undoUnitId)\n\t\t\t\t_undoUnit = unit;\n\t\t}\n\t\telse if (unit->getStatus() != STATUS_DEAD && !unit->isIgnored())\n\t\t{\n\t\t\tif (const auto& ai = unitReader[\"AI\"])\n\t\t\t{\n\t\t\t\tAIModule* aiModule = new AIModule(this, unit, 0);\n\t\t\t\taiModule->load(ai);\n\t\t\t\tunit->setAIModule(aiModule);\n\t\t\t}\n\t\t}\n\t\tunitIndex[id] = unit;\n\t\t_units.push_back(unit);\n\t}\n\n\tstd::pair<const char*, std::vector<BattleItem*>*> itemKeysAndVectors[] =\n\t{\n\t\t{ \"items\", &_items },\n\t\t{ \"recoverConditional\", &_recoverConditional },\n\t\t{ \"recoverGuaranteed\", &_recoverGuaranteed },\n\t\t{ \"itemsSpecial\", &_items },\n\t};\n\t// items 1st pass\n\tfor (auto& keyAndVector : itemKeysAndVectors)\n\t{\n\t\tfor (const auto& itemReader : reader[keyAndVector.first].children())\n\t\t{\n\t\t\tstd::string type = itemReader[\"type\"].readVal<std::string>();\n\t\t\tif (!mod->getItem(type))\n\t\t\t{\n\t\t\t\tLog(LOG_ERROR) << \"Failed to load item \" << type;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tint id = itemReader[\"id\"].readVal<int>();\n\t\t\tBattleItem* item = new BattleItem(mod->getItem(type), &id); //passing id as a pointer to serve as a counter is no longer used\n\t\t\titem->load(itemReader, mod, this->getMod()->getScriptGlobal());\n\n\t\t\tif (BattleUnit* owner = findUnitById(itemReader[\"owner\"]))\n\t\t\t{\n\t\t\t\titem->setOwner(owner);\n\t\t\t\tif (item->isSpecialWeapon())\n\t\t\t\t\towner->addLoadedSpecialWeapon(item);\n\t\t\t\telse\n\t\t\t\t\towner->getInventory()->push_back(item);\n\t\t\t}\n\t\t\titem->setPreviousOwner(findUnitById(itemReader[\"previousOwner\"]));\n\t\t\titem->setUnit(findUnitById(itemReader[\"unit\"]));\n\n\t\t\t// match up items and tiles\n\t\t\tif (item->getSlot() && item->getSlot()->getType() == INV_GROUND)\n\t\t\t{\n\t\t\t\tPosition pos = itemReader[\"position\"].readVal(Position(-1, -1, -1));\n\t\t\t\tif (pos.x != -1)\n\t\t\t\t\tgetTile(pos)->addItem(item, item->getSlot());\n\t\t\t}\n\t\t\t_itemId = std::max(_itemId, item->getId());\n\t\t\titemIndex[item->getId()] = item;\n\t\t\tkeyAndVector.second->push_back(item);\n\t\t}\n\t}\n\t_itemId++;\n\n\t// units 2nd pass\n\tfor (const auto& unitReader : reader[\"units\"].children())\n\t{\n\t\tif (BattleUnit* bu = findUnitById(unitReader[\"id\"])) //not guaranteed that the unit was created\n\t\t{\n\t\t\tif (!bu->isIgnored() && bu->getStatus() != STATUS_DEAD)\n\t\t\t\tbu->setSpecialWeapon(this, true); // Note: this is for backwards-compatibility with older saves\n\t\t\tbu->setPreviousOwner(findUnitById(unitReader[\"previousOwner\"]));\n\t\t}\n\t}\n\n\t// items 2nd pass\n\tfor (auto& keyAndVector : itemKeysAndVectors)\n\t{\n\t\tfor (const auto& itemReader : reader[keyAndVector.first].children())\n\t\t{\n\t\t\tstd::string type = itemReader[\"type\"].readVal<std::string>();\n\t\t\tif (!mod->getItem(type))\n\t\t\t\tcontinue;\n\t\t\tBattleItem* item = itemIndex.at(itemReader[\"id\"].readVal<int>());\n\t\t\t// if \"ammoItemSlots\" node exists, then link ammo items for all slots, else try the backwards-compatibility node\n\t\t\tif (const auto& slotsReader = itemReader[\"ammoItemSlots\"])\n\t\t\t\tfor (size_t slotIndex = 0; slotIndex < RuleItem::AmmoSlotMax; slotIndex++)\n\t\t\t\t{\n\t\t\t\t\tint itemId = slotsReader[slotIndex].readVal(-1);\n\t\t\t\t\tif (itemId > -1 && itemIndex.count(itemId))\n\t\t\t\t\t\titem->setAmmoForSlot(slotIndex, itemIndex.at(itemId));\n\t\t\t\t}\n\t\t\telse if (const auto& slotReader = itemReader[\"ammoItem\"])\n\t\t\t\titem->setAmmoForSlot(0, itemIndex.at(slotReader.readVal(0)));\n\t\t}\n\t}\n\n\t// restore order like before save\n\t// is this necessary? who knows...\n\tfor (auto& keyAndVector : itemKeysAndVectors)\n\t{\n\t\tstd::sort(\n\t\t\tkeyAndVector.second->begin(), keyAndVector.second->end(),\n\t\t\t[](const BattleItem* itemA, const BattleItem* itemB)\n\t\t\t{\n\t\t\t\treturn itemA->getId() < itemB->getId();\n\t\t\t}\n\t\t);\n\t}\n\n\treader.tryRead(\"vipEscapeType\", _vipEscapeType);\n\treader.tryRead(\"vipSurvivalPercentage\", _vipSurvivalPercentage);\n\treader.tryRead(\"vipsSaved\", _vipsSaved);\n\treader.tryRead(\"vipsLost\", _vipsLost);\n\treader.tryRead(\"vipsWaitingOutside\", _vipsWaitingOutside);\n\treader.tryRead(\"vipsSavedScore\", _vipsSavedScore);\n\treader.tryRead(\"vipsLostScore\", _vipsLostScore);\n\treader.tryRead(\"vipsWaitingOutsideScore\", _vipsWaitingOutsideScore);\n\treader.tryRead(\"objectiveType\", _objectiveType);\n\treader.tryRead(\"objectivesDestroyed\", _objectivesDestroyed);\n\treader.tryRead(\"objectivesNeeded\", _objectivesNeeded);\n\treader.tryRead(\"tuReserved\", _tuReserved);\n\treader.tryRead(\"kneelReserved\", _kneelReserved);\n\treader.tryRead(\"ambience\", _ambience);\n\treader.tryRead(\"ambientVolume\", _ambientVolume);\n\treader.tryRead(\"ambienceRandom\", _ambienceRandom);\n\treader.tryRead(\"minAmbienceRandomDelay\", _minAmbienceRandomDelay);\n\treader.tryRead(\"maxAmbienceRandomDelay\", _maxAmbienceRandomDelay);\n\treader.tryRead(\"currentAmbienceDelay\", _currentAmbienceDelay);\n\treader.tryRead(\"music\", _music);\n\t_baseItems->load(reader[\"baseItems\"], mod);\n\treader.tryRead(\"turnLimit\", _turnLimit);\n\treader.tryRead(\"chronoTrigger\", _chronoTrigger);\n\treader.tryRead(\"cheatTurn\", _cheatTurn);\n\treader.tryRead(\"togglePersonalLight\", _togglePersonalLight);\n\treader.tryRead(\"toggleNightVision\", _toggleNightVision);\n\treader.tryRead(\"toggleBrightness\", _toggleBrightness);\n\t_scriptValues.load(reader, _rule->getScriptGlobal());\n\n\t// Sanity checks\n\tfor (auto* unit : _units)\n\t{\n\t\tswitch (unit->getStatus())\n\t\t{\n\t\tcase STATUS_STANDING:\n\t\tcase STATUS_DEAD:\n\t\tcase STATUS_UNCONSCIOUS:\n\t\tcase STATUS_IGNORE_ME:\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tLog(LOG_ERROR) << \"Save '\" << savedGame->getName()\n\t\t\t\t<< \"' is corrupted. Unit \" << unit->getType()\n\t\t\t\t<< \" (id: \" << unit->getId()\n\t\t\t\t<< \") has an invalid 'status: \" << unit->getStatus() << \"'\";\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n/**\n * Loads the resources required by the map in the battle save.\n * @param mod Pointer to the mod.\n */\nvoid SavedBattleGame::loadMapResources(Mod *mod)\n{\n\tfor (auto* mds : _mapDataSets)\n\t{\n\t\tmds->loadData(mod->getMCDPatch(mds->getName()));\n\t}\n\n\tint mdsID, mdID;\n\n\tfor (int i = 0; i < _mapsize_z * _mapsize_y * _mapsize_x; ++i)\n\t{\n\t\tfor (int part = O_FLOOR; part < O_MAX; part++)\n\t\t{\n\t\t\tTilePart tp = (TilePart)part;\n\t\t\t_tiles[i].getMapData(&mdID, &mdsID, tp);\n\t\t\tif (mdID != -1 && mdsID != -1)\n\t\t\t{\n\t\t\t\t_tiles[i].setMapData(_mapDataSets[mdsID]->getObject(mdID), mdID, mdsID, tp);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_tiles[i].setMapData(nullptr, -1, -1, tp);\n\t\t\t}\n\t\t}\n\t}\n\n\tinitUtilities(mod);\n\t// matches up tiles and units\n\tresetUnitTiles();\n\tgetTileEngine()->calculateLighting(LL_AMBIENT, TileEngine::invalid, 0, true);\n\tgetTileEngine()->recalculateFOV();\n}\n\n/**\n * Saves the saved battle game to a YAML file.\n * @return YAML node.\n */\nvoid SavedBattleGame::save(YAML::YamlNodeWriter writer) const\n{\n\twriter.setAsMap();\n\tif (_vipSurvivalPercentage > 0)\n\t{\n\t\twriter.write(\"vipEscapeType\", _vipEscapeType);\n\t\twriter.write(\"vipSurvivalPercentage\", _vipSurvivalPercentage);\n\t\twriter.write(\"vipsSaved\", _vipsSaved);\n\t\twriter.write(\"vipsLost\", _vipsLost);\n\t\twriter.write(\"vipsWaitingOutside\", _vipsWaitingOutside);\n\t\twriter.write(\"vipsSavedScore\", _vipsSavedScore);\n\t\twriter.write(\"vipsLostScore\", _vipsLostScore);\n\t\twriter.write(\"vipsWaitingOutsideScore\", _vipsWaitingOutsideScore);\n\t}\n\tif (_objectivesNeeded)\n\t{\n\t\twriter.write(\"objectivesDestroyed\", _objectivesDestroyed);\n\t\twriter.write(\"objectivesNeeded\", _objectivesNeeded);\n\t\twriter.write(\"objectiveType\", _objectiveType);\n\t}\n\twriter.write(\"width\", _mapsize_x);\n\twriter.write(\"length\", _mapsize_y);\n\twriter.write(\"height\", _mapsize_z);\n\twriter.write(\"missionType\", _missionType);\n\twriter.write(\"strTarget\", _strTarget);\n\twriter.write(\"strCraftOrBase\", _strCraftOrBase).setAsQuotedAndEscaped();\n\tif (_startingCondition)\n\t{\n\t\twriter.write(\"startingConditionType\", _startingCondition->getType());\n\t}\n\tif (_enviroEffects)\n\t{\n\t\twriter.write(\"enviroEffectsType\", _enviroEffects->getType());\n\t}\n\twriter.write(\"nameDisplay\", _nameDisplay);\n\twriter.write(\"ecEnabledFriendly\", _ecEnabledFriendly);\n\twriter.write(\"ecEnabledHostile\", _ecEnabledHostile);\n\twriter.write(\"ecEnabledNeutral\", _ecEnabledNeutral);\n\twriter.write(\"alienCustomDeploy\", _alienCustomDeploy);\n\twriter.write(\"alienCustomMission\", _alienCustomMission);\n\twriter.write(\"alienItemLevel\", _alienItemLevel);\n\twriter.write(\"lastUsedMapScript\", _lastUsedMapScript);\n\twriter.write(\"reinforcementsDeployment\", _reinforcementsDeployment);\n\twriter.write(\"reinforcementsRace\", _reinforcementsRace);\n\twriter.write(\"reinforcementsItemLevel\", _reinforcementsItemLevel);\n\twriter.write(\"reinforcementsMemory\", _reinforcementsMemory);\n\twriter.write(\"reinforcementsBlocks\", _reinforcementsBlocks);\n\twriter.write(\"flattenedMapTerrainNames\", _flattenedMapTerrainNames);\n\twriter.write(\"flattenedMapBlockNames\", _flattenedMapBlockNames);\n\twriter.write(\"globalshade\", _globalShade);\n\twriter.write(\"turn\", _turn);\n\twriter.write(\"bughuntMinTurn\", _bughuntMinTurn);\n\twriter.write(\"animFrame\", _animFrame);\n\twriter.write(\"bughuntMode\", _bughuntMode);\n\twriter.write(\"selectedUnit\", (_selectedUnit ? _selectedUnit->getId() : -1));\n\twriter.write(\"undoUnit\", (_undoUnit ? _undoUnit->getId() : -1));\n\n\twriter.write(\"mapdatasets\", _mapDataSets,\n\t\t[](YAML::YamlNodeWriter& w, MapDataSet* mds)\n\t\t{ w.write(mds->getName()); });\n#if 0\n\tfor (int i = 0; i < _mapsize_z * _mapsize_y * _mapsize_x; ++i)\n\t{\n\t\tif (!_tiles[i].isVoid())\n\t\t{\n\t\t\tnode[\"tiles\"].push_back(_tiles[i].save());\n\t\t}\n\t}\n#else\n\t// first, write out the field sizes we're going to use to write the tile data\n\twriter.write(\"tileIndexSize\", static_cast<char>(Tile::serializationKey.index)).setAsQuotedAndEscaped();\n\twriter.write(\"tileTotalBytesPer\", Tile::serializationKey.totalBytes);\n\twriter.write(\"tileFireSize\", static_cast<char>(Tile::serializationKey._fire)).setAsQuotedAndEscaped();\n\twriter.write(\"tileSmokeSize\", static_cast<char>(Tile::serializationKey._smoke)).setAsQuotedAndEscaped();\n\twriter.write(\"tileIDSize\", static_cast<char>(Tile::serializationKey._mapDataID)).setAsQuotedAndEscaped();\n\twriter.write(\"tileSetIDSize\", static_cast<char>(Tile::serializationKey._mapDataSetID)).setAsQuotedAndEscaped();\n\twriter.write(\"tileBoolFieldsSize\", static_cast<char>(Tile::serializationKey.boolFields)).setAsQuotedAndEscaped();\n\n\tsize_t tileDataSize = Tile::serializationKey.totalBytes * _mapsize_z * _mapsize_y * _mapsize_x;\n\tUint8* tileData = (Uint8*) calloc(tileDataSize, 1);\n\tUint8* ptr = tileData;\n\n\tfor (int i = 0; i < _mapsize_z * _mapsize_y * _mapsize_x; ++i)\n\t{\n\t\tif (!_tiles[i].isVoid())\n\t\t{\n\t\t\tserializeInt(&ptr, Tile::serializationKey.index, i);\n\t\t\t_tiles[i].saveBinary(&ptr);\n\t\t}\n\t\telse\n\t\t{\n\t\t\ttileDataSize -= Tile::serializationKey.totalBytes;\n\t\t}\n\t}\n\twriter.write(\"totalTiles\", tileDataSize / Tile::serializationKey.totalBytes); // not strictly necessary, just convenient\n\twriter.writeBase64(\"binTiles\", (char*)tileData, tileDataSize);\n\tfree(tileData);\n#endif\n\n\twriter.write(\"nodes\", _nodes,\n\t\t[](YAML::YamlNodeWriter& w, Node* n)\n\t\t{ n->save(w.write()); });\n\tif (_missionType == \"STR_BASE_DEFENSE\")\n\t\twriter.write(\"moduleMap\", _baseModules);\n\twriter.write(\"units\", _units,\n\t\t[&](YAML::YamlNodeWriter& w, BattleUnit* bu)\n\t\t{ bu->save(w.write(), this->getMod()->getScriptGlobal()); });\n\twriter.write(\"items\", _items,\n\t\t[&](YAML::YamlNodeWriter& w, BattleItem* bi)\n\t\t{ if (!bi->isSpecialWeapon()) bi->save(w.write(), this->getMod()->getScriptGlobal()); });\n\twriter.write(\"itemsSpecial\", _items,\n\t\t[&](YAML::YamlNodeWriter& w, BattleItem* bi)\n\t\t{ if (bi->isSpecialWeapon()) bi->save(w.write(), this->getMod()->getScriptGlobal()); });\n\twriter.write(\"tuReserved\", (int)_tuReserved);\n\twriter.write(\"kneelReserved\", _kneelReserved);\n\twriter.write(\"depth\", _depth);\n\twriter.write(\"ambience\", _ambience);\n\twriter.write(\"ambientVolume\", _ambientVolume);\n\twriter.write(\"ambienceRandom\", _ambienceRandom);\n\twriter.write(\"minAmbienceRandomDelay\", _minAmbienceRandomDelay);\n\twriter.write(\"maxAmbienceRandomDelay\", _maxAmbienceRandomDelay);\n\twriter.write(\"currentAmbienceDelay\", _currentAmbienceDelay);\n\twriter.write(\"recoverGuaranteed\", _recoverGuaranteed,\n\t\t[&](YAML::YamlNodeWriter& w, BattleItem* bi)\n\t\t{ bi->save(w.write(), this->getMod()->getScriptGlobal()); });\n\twriter.write(\"recoverConditional\", _recoverConditional,\n\t\t[&](YAML::YamlNodeWriter& w, BattleItem* bi)\n\t\t{ bi->save(w.write(), this->getMod()->getScriptGlobal()); });\n\twriter.write(\"music\", _music);\n\t_baseItems->save(writer[\"baseItems\"]);\n\twriter.write(\"turnLimit\", _turnLimit);\n\twriter.write(\"chronoTrigger\", _chronoTrigger);\n\twriter.write(\"cheatTurn\", _cheatTurn);\n\twriter.write(\"togglePersonalLight\", _togglePersonalLight);\n\twriter.write(\"toggleNightVision\", _toggleNightVision);\n\twriter.write(\"toggleBrightness\", _toggleBrightness);\n\t_scriptValues.save(writer, _rule->getScriptGlobal());\n}\n\n/**\n * Initializes the array of tiles and creates a pathfinding object.\n * @param mapsize_x\n * @param mapsize_y\n * @param mapsize_z\n */\nvoid SavedBattleGame::initMap(int mapsize_x, int mapsize_y, int mapsize_z, bool resetTerrain)\n{\n\t// Clear old map data\n\tfor (auto* node : _nodes)\n\t{\n\t\tdelete node;\n\t}\n\n\t_nodes.clear();\n\n\tif (resetTerrain)\n\t{\n\t\t_mapDataSets.clear();\n\t}\n\n\t// Create tile objects\n\t_mapsize_x = mapsize_x;\n\t_mapsize_y = mapsize_y;\n\t_mapsize_z = mapsize_z;\n\n\t_tiles.clear();\n\t_tiles.reserve(_mapsize_z * _mapsize_y * _mapsize_x);\n\tfor (int i = 0; i < _mapsize_z * _mapsize_y * _mapsize_x; ++i)\n\t{\n\t\t_tiles.push_back(Tile(getTileCoords(i), this));\n\t}\n\n}\n\n/**\n * Initializes the map utilities.\n * @param mod Pointer to mod.\n */\nvoid SavedBattleGame::initUtilities(Mod *mod, bool craftInventory)\n{\n\tdelete _pathfinding;\n\tdelete _tileEngine;\n\t_baseCraftInventory = craftInventory;\n\t_pathfinding = craftInventory ? nullptr : new Pathfinding(this);\n\t_tileEngine = new TileEngine(this, mod);\n}\n\n/**\n * Gets if this is craft pre-equip phase in base view.\n * @return True if it in base equip screen.\n */\nbool SavedBattleGame::isBaseCraftInventory()\n{\n\treturn _baseCraftInventory;\n}\n\n/**\n * Sets the mission type.\n * @param missionType The mission type.\n */\nvoid SavedBattleGame::setMissionType(const std::string &missionType)\n{\n\t_missionType = missionType;\n}\n\n/**\n * Gets the mission type.\n * @return The mission type.\n */\nconst std::string &SavedBattleGame::getMissionType() const\n{\n\treturn _missionType;\n}\n\n/**\n* Returns the list of items in the base storage rooms BEFORE the mission.\n* Does NOT return items assigned to craft or in transfer.\n* @return Pointer to the item list.\n*/\nItemContainer *SavedBattleGame::getBaseStorageItems()\n{\n\treturn _baseItems;\n}\n\n/**\n * Applies the enviro effects.\n * @param enviroEffects The enviro effects.\n */\nvoid SavedBattleGame::applyEnviroEffects(const RuleEnviroEffects* enviroEffects)\n{\n\t_enviroEffects = enviroEffects;\n\n\t_ecEnabledFriendly = false;\n\t_ecEnabledHostile = false;\n\t_ecEnabledNeutral = false;\n\n\tif (_enviroEffects)\n\t{\n\t\t_ecEnabledFriendly = RNG::percent(_enviroEffects->getEnvironmetalCondition(\"STR_FRIENDLY\").globalChance);\n\t\t_ecEnabledHostile = RNG::percent(_enviroEffects->getEnvironmetalCondition(\"STR_HOSTILE\").globalChance);\n\t\t_ecEnabledNeutral = RNG::percent(_enviroEffects->getEnvironmetalCondition(\"STR_NEUTRAL\").globalChance);\n\t}\n}\n\n/**\n * Gets the enviro effects.\n * @return The enviro effects.\n */\nconst RuleEnviroEffects* SavedBattleGame::getEnviroEffects() const\n{\n\treturn _enviroEffects;\n}\n\n/**\n * Are environmental conditions (for a given faction) enabled?\n * @param faction The relevant faction.\n * @return True, if enabled.\n */\nbool SavedBattleGame::getEnvironmentalConditionsEnabled(UnitFaction faction) const\n{\n\tif (faction == FACTION_PLAYER)\n\t{\n\t\treturn _ecEnabledFriendly;\n\t}\n\telse if (faction == FACTION_HOSTILE)\n\t{\n\t\treturn _ecEnabledHostile;\n\t}\n\telse if (faction == FACTION_NEUTRAL)\n\t{\n\t\treturn _ecEnabledNeutral;\n\t}\n\treturn false;\n}\n\n/**\n *  Sets the custom alien data.\n */\nvoid SavedBattleGame::setAlienCustom(const std::string &deploy, const std::string &mission)\n{\n\t_alienCustomDeploy = deploy;\n\t_alienCustomMission = mission;\n}\n\n/**\n *  Gets the custom alien deploy.\n */\nconst std::string &SavedBattleGame::getAlienCustomDeploy() const\n{\n\treturn _alienCustomDeploy;\n}\n\n/**\n *  Gets the custom mission definition\n */\nconst std::string &SavedBattleGame::getAlienCustomMission() const\n{\n\treturn _alienCustomMission;\n}\n\n/**\n * Sets the global shade.\n * @param shade The global shade.\n */\nvoid SavedBattleGame::setGlobalShade(int shade)\n{\n\t_globalShade = shade;\n}\n\n/**\n * Gets the global shade.\n * @return The global shade.\n */\nint SavedBattleGame::getGlobalShade() const\n{\n\treturn _globalShade;\n}\n\n/**\n * Pre-calculate all valid tiles for later use in map drawing.\n */\nvoid SavedBattleGame::calculateCraftTiles()\n{\n\tif (_craftForPreview && !_craftForPreview->getRules()->getDeployment().empty() && !_craftForPreview->getRules()->useAllStartTiles())\n\t{\n\t\tfor (auto& vec : _craftForPreview->getRules()->getDeployment())\n\t\t{\n\t\t\tif (vec.size() >= 3)\n\t\t\t{\n\t\t\t\tPosition tmp = Position(vec[0] + _craftPos.x * 10, vec[1] + _craftPos.y * 10, vec[2] + _craftZ);\n\t\t\t\t_craftTiles.push_back(tmp);\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\tfor (int i = 0; i < getMapSizeXYZ(); ++i)\n\t\t{\n\t\t\tauto* tile = getTile(i);\n\t\t\tif (tile &&\n\t\t\t\ttile->getFloorSpecialTileType() == START_POINT &&\n\t\t\t\t!tile->getMapData(O_OBJECT) &&\n\t\t\t\ttile->getMapData(O_FLOOR) && // for clarity this is checked again, first time was in `getFloorSpecialTileType`\n\t\t\t\ttile->getMapData(O_FLOOR)->getTUCost(MT_WALK) != Pathfinding::INVALID_MOVE_COST)\n\t\t\t{\n\t\t\t\t_craftTiles.push_back(tile->getPosition());\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Converts a tile index to coordinates.\n * @param index The (unique) tile index.\n * @param x Pointer to the X coordinate.\n * @param y Pointer to the Y coordinate.\n * @param z Pointer to the Z coordinate.\n */\nPosition SavedBattleGame::getTileCoords(int index) const\n{\n\tPosition p;\n\tp.z = index / (_mapsize_y * _mapsize_x);\n\tp.y = (index % (_mapsize_y * _mapsize_x)) / _mapsize_x;\n\tp.x = (index % (_mapsize_y * _mapsize_x)) % _mapsize_x;\n\treturn p;\n}\n\n/**\n * Gets the currently selected unit\n * @return Pointer to BattleUnit.\n */\nBattleUnit *SavedBattleGame::getSelectedUnit()\n{\n\treturn _selectedUnit;\n}\n\n/**\n * Gets the currently selected unit\n * @return Pointer to BattleUnit.\n */\nconst BattleUnit *SavedBattleGame::getSelectedUnit() const\n{\n\treturn _selectedUnit;\n}\n\n/**\n * Sets the currently selected unit.\n * @param unit Pointer to BattleUnit.\n */\nvoid SavedBattleGame::setSelectedUnit(BattleUnit *unit)\n{\n\t_selectedUnit = unit;\n}\n\n/**\n * Clear state that given unit is selected.\n */\nvoid SavedBattleGame::clearUnitSelection(BattleUnit *unit)\n{\n\tif (_selectedUnit == unit)\n\t{\n\t\t_selectedUnit = nullptr;\n\t}\n\tif (_undoUnit == unit)\n\t{\n\t\t_undoUnit = nullptr;\n\t}\n\tif (_lastSelectedUnit == unit)\n\t{\n\t\t_lastSelectedUnit = nullptr;\n\t}\n}\n\n/**\n * Selects the previous player unit.\n * @param checkReselect Whether to check if we should reselect a unit.\n * @param setReselect Don't reselect a unit.\n * @param checkInventory Whether to check if the unit has an inventory.\n * @return Pointer to new selected BattleUnit, NULL if none can be selected.\n * @sa selectPlayerUnit\n */\nBattleUnit *SavedBattleGame::selectPreviousPlayerUnit(bool checkReselect, bool setReselect, bool checkInventory)\n{\n\treturn selectPlayerUnit(-1, checkReselect, setReselect, checkInventory);\n}\n\n/**\n * Selects the next player unit.\n * @param checkReselect Whether to check if we should reselect a unit.\n * @param setReselect Don't reselect a unit.\n * @param checkInventory Whether to check if the unit has an inventory.\n * @return Pointer to new selected BattleUnit, NULL if none can be selected.\n * @sa selectPlayerUnit\n */\nBattleUnit *SavedBattleGame::selectNextPlayerUnit(bool checkReselect, bool setReselect, bool checkInventory)\n{\n\treturn selectPlayerUnit(+1, checkReselect, setReselect, checkInventory);\n}\n\n/**\n * Selects the next player unit in a certain direction.\n * @param dir Direction to select, eg. -1 for previous and 1 for next.\n * @param checkReselect Whether to check if we should reselect a unit.\n * @param setReselect Don't reselect a unit.\n * @param checkInventory Whether to check if the unit has an inventory.\n * @return Pointer to new selected BattleUnit, NULL if none can be selected.\n */\nBattleUnit *SavedBattleGame::selectPlayerUnit(int dir, bool checkReselect, bool setReselect, bool checkInventory)\n{\n\tif (_selectedUnit != 0 && setReselect)\n\t{\n\t\t_selectedUnit->dontReselect();\n\t}\n\tif (_units.empty())\n\t{\n\t\treturn 0;\n\t}\n\n\tstd::vector<BattleUnit*>::iterator begin, end;\n\tif (dir > 0)\n\t{\n\t\tbegin = _units.begin();\n\t\tend = _units.end()-1;\n\t}\n\telse if (dir < 0)\n\t{\n\t\tbegin = _units.end()-1;\n\t\tend = _units.begin();\n\t}\n\n\tauto i = std::find(_units.begin(), _units.end(), _selectedUnit);\n\tdo\n\t{\n\t\t// no unit selected\n\t\tif (i == _units.end())\n\t\t{\n\t\t\ti = begin;\n\t\t\tcontinue;\n\t\t}\n\t\tif (i != end)\n\t\t{\n\t\t\ti += dir;\n\t\t}\n\t\t// reached the end, wrap-around\n\t\telse\n\t\t{\n\t\t\ti = begin;\n\t\t}\n\t\t// back to where we started... no more units found\n\t\tif (*i == _selectedUnit)\n\t\t{\n\t\t\tif (checkReselect && !_selectedUnit->reselectAllowed())\n\t\t\t\t_selectedUnit = 0;\n\t\t\treturn _selectedUnit;\n\t\t}\n\t\telse if (_selectedUnit == 0 && i == begin)\n\t\t{\n\t\t\treturn _selectedUnit;\n\t\t}\n\t}\n\twhile (!(*i)->isSelectable(_side, checkReselect, checkInventory));\n\n\t_selectedUnit = (*i);\n\treturn _selectedUnit;\n}\n\n/**\n * Selects the next closest player unit.\n * @param checkReselect Whether to check if we should reselect a unit.\n * @param setReselect Don't reselect a unit.\n * @param checkInventory Whether to check if the unit has an inventory.\n * @return Pointer to new selected BattleUnit, NULL if none can be selected.\n */\nBattleUnit* SavedBattleGame::selectNextPlayerUnitByDistance(bool checkReselect, bool setReselect, bool checkInventory)\n{\n\tBattleUnit* backup = _selectedUnit;\n\tif (_selectedUnit != 0 && setReselect)\n\t{\n\t\t_selectedUnit->dontReselect();\n\t\t_selectedUnit = 0;\n\t}\n\n\tstd::vector< std::pair<int, BattleUnit*> > candidates;\n\tfor (auto* unit : _units)\n\t{\n\t\tif (unit != _selectedUnit && unit->isSelectable(_side, checkReselect, checkInventory))\n\t\t{\n\t\t\tint distance = backup ? backup->distance3dToUnitSq(unit) : 0;\n\t\t\tcandidates.push_back(std::make_pair(distance, unit));\n\t\t}\n\t}\n\n\tif (!candidates.empty())\n\t{\n\t\tstd::sort(candidates.begin(), candidates.end(),\n\t\t\t[](const std::pair<int, BattleUnit*>& a, const std::pair<int, BattleUnit*>& b)\n\t\t\t{ return a.first < b.first; });\n\n\t\t_selectedUnit = candidates.front().second;\n\t}\n\treturn _selectedUnit;\n}\n\n/**\n * Selects the unit at the given position on the map.\n * @param pos Position.\n * @return Pointer to a BattleUnit, or 0 when none is found.\n */\nBattleUnit *SavedBattleGame::selectUnit(Position pos)\n{\n\tBattleUnit *bu = getTile(pos)->getUnit();\n\n\tif (bu && bu->isOut())\n\t{\n\t\treturn 0;\n\t}\n\telse\n\t{\n\t\treturn bu;\n\t}\n}\n\n/**\n * Gets the list of nodes.\n * @return Pointer to the list of nodes.\n */\nstd::vector<Node*> *SavedBattleGame::getNodes()\n{\n\treturn &_nodes;\n}\n\n/**\n * Gets the list of units.\n * @return Pointer to the list of units.\n */\nstd::vector<BattleUnit*> *SavedBattleGame::getUnits()\n{\n\treturn &_units;\n}\n\n/**\n * Gets the list of items.\n * @return Pointer to the list of items.\n */\nstd::vector<BattleItem*> *SavedBattleGame::getItems()\n{\n\treturn &_items;\n}\n\n/**\n * Gets the pathfinding object.\n * @return Pointer to the pathfinding object.\n */\nPathfinding *SavedBattleGame::getPathfinding() const\n{\n\treturn _pathfinding;\n}\n\n/**\n * Gets the terrain modifier object.\n * @return Pointer to the terrain modifier object.\n */\nTileEngine *SavedBattleGame::getTileEngine() const\n{\n\treturn _tileEngine;\n}\n\n/**\n * Gets the array of mapblocks.\n * @return Pointer to the array of mapblocks.\n */\nstd::vector<MapDataSet*> *SavedBattleGame::getMapDataSets()\n{\n\treturn &_mapDataSets;\n}\n\n/**\n * Gets the side currently playing.\n * @return The unit faction currently playing.\n */\nUnitFaction SavedBattleGame::getSide() const\n{\n\treturn _side;\n}\n\n/**\n * Test if weapon is usable by unit.\n * @param weapon\n * @param unit\n * @return Unit can shoot/use it.\n */\nbool SavedBattleGame::canUseWeapon(const BattleItem* weapon, const BattleUnit* unit, bool isBerserking, BattleActionType actionType, std::string* message) const\n{\n\tif (!weapon || !unit) return false;\n\n\tconst RuleItem *rule = weapon->getRules();\n\n\tconst BattleItem* ammoItem;\n\tif (actionType != BA_NONE)\n\t{\n\t\t// Applies to:\n\t\t// 1. action type selected by the player from the UI\n\t\t// 2. leeroy jenkins AI\n\t\t// 3. all reaction fire\n\t\t// 4. all unit berserking\n\t\tammoItem = weapon->getAmmoForAction(actionType);\n\t}\n\telse\n\t{\n\t\t// Applies to:\n\t\t// 5. standard AI - action type (and thus ammoItem) is unknown when the check is done\n\t\tammoItem = nullptr;\n\t}\n\n\tif (unit->getFaction() == FACTION_HOSTILE && getTurn() < rule->getAIUseDelay(getMod()))\n\t{\n\t\treturn false;\n\t}\n\tif (unit->getOriginalFaction() == FACTION_PLAYER && !_battleState->getGame()->getSavedGame()->isResearched(rule->getRequirements()))\n\t{\n\t\treturn false;\n\t}\n\tif (rule->isPsiRequired() && unit->getBaseStats()->psiSkill <= 0)\n\t{\n\t\treturn false;\n\t}\n\tif (rule->isManaRequired() && unit->getOriginalFaction() == FACTION_PLAYER)\n\t{\n\t\tif (!_rule->isManaFeatureEnabled() || !_battleState->getGame()->getSavedGame()->isManaUnlocked(_rule))\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\tif (getDepth() == 0)\n\t{\n\t\tif (rule->isWaterOnly() || (ammoItem && ammoItem->getRules()->isWaterOnly()) )\n\t\t{\n\t\t\tif (message) *message = \"STR_UNDERWATER_EQUIPMENT\";\n\t\t\treturn false;\n\t\t}\n\t}\n\telse // if (getDepth() != 0)\n\t{\n\t\tif (rule->isLandOnly() || (ammoItem && ammoItem->getRules()->isLandOnly()) )\n\t\t{\n\t\t\tif (message) *message = \"STR_LAND_EQUIPMENT\";\n\t\t\treturn false;\n\t\t}\n\t}\n\tif (rule->isBlockingBothHands() && unit->getFaction() == FACTION_PLAYER && !isBerserking && unit->getLeftHandWeapon() != 0 && unit->getRightHandWeapon() != 0)\n\t{\n\t\tif (message) *message = \"STR_MUST_USE_BOTH_HANDS\";\n\t\treturn false;\n\t}\n\treturn true;\n}\n\n/**\n * Gets the current turn number.\n * @return The current turn.\n */\nint SavedBattleGame::getTurn() const\n{\n\treturn _turn;\n}\n\n/**\n* Sets the bug hunt turn number.\n*/\nvoid SavedBattleGame::setBughuntMinTurn(int bughuntMinTurn)\n{\n\t_bughuntMinTurn = bughuntMinTurn;\n}\n\n/**\n* Gets the bug hunt turn number.\n* @return The bug hunt turn.\n*/\nint SavedBattleGame::getBughuntMinTurn() const\n{\n\treturn _bughuntMinTurn;\n}\n\n/**\n * Start first turn of battle.\n */\nvoid SavedBattleGame::startFirstTurn()\n{\n\t// this should be first tile with all items, even if unit is in reality on other tile.\n\tTile *inventoryTile = getSelectedUnit()->getTile();\n\n\trandomizeItemLocations(inventoryTile);\n\n\tresetUnitTiles();\n\n\t// check what unit is still on this tile after reset.\n\tif (inventoryTile->getUnit())\n\t{\n\t\t// make sure we select the unit closest to the ramp.\n\t\tsetSelectedUnit(inventoryTile->getUnit());\n\t}\n\n\n\t// initialize xcom units for battle\n\tfor (auto* bu : *getUnits())\n\t{\n\t\tif (bu->getOriginalFaction() != FACTION_PLAYER || bu->isOut())\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\n\t\tbu->prepareNewTurn(false);\n\t}\n\n\t_turn = 1;\n\n\tnewTurnUpdateScripts();\n}\n\n/**\n * Scripts that are run at begining of new turn.\n */\nvoid SavedBattleGame::newTurnUpdateScripts()\n{\n\tif (_isPreview)\n\t{\n\t\treturn;\n\t}\n\n\tfor (auto* bu : _units)\n\t{\n\t\tif (bu->isIgnored())\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\n\t\tModScript::scriptCallback<ModScript::NewTurnUnit>(bu->getArmor(), bu, this, this->getTurn(), _side);\n\t}\n\n\tfor (auto* item : _items)\n\t{\n\t\tif (item->isOwnerIgnored())\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\n\t\tModScript::scriptCallback<ModScript::NewTurnItem>(item->getRules(), item, this, this->getTurn(), _side);\n\t}\n\n\treviveUnconsciousUnits(false);\n\n\tgetBattleGame()->convertInfected();\n}\n\n/**\n * Tallies the units in the craft deployment preview.\n */\nBattlescapeTally SavedBattleGame::tallyUnitsForPreview()\n{\n\tBattlescapeTally tally = { };\n\n\tbool custom = _isPreview && _craftForPreview && !_craftTiles.empty();\n\tPosition tmp;\n\n\tfor (auto* unit : _units)\n\t{\n\t\tif (unit->getOriginalFaction() == FACTION_PLAYER)\n\t\t{\n\t\t\tif (unit->isSummonedPlayerUnit())\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (custom)\n\t\t\t{\n\t\t\t\tbool placementOk = true;\n\t\t\t\tfor (int x = 0; x < unit->getArmor()->getSize(); ++x)\n\t\t\t\t{\n\t\t\t\t\tfor (int y = 0; y < unit->getArmor()->getSize(); ++y)\n\t\t\t\t\t{\n\t\t\t\t\t\ttmp = Position(x + unit->getPosition().x, y + unit->getPosition().y, unit->getPosition().z);\n\t\t\t\t\t\tbool found = false;\n\t\t\t\t\t\tfor (const auto& pos : _craftTiles)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (pos == tmp)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tfound = true;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!found)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tplacementOk = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (placementOk)\n\t\t\t\t{\n\t\t\t\t\ttally.inEntrance++;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\ttally.inField++;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (unit->isInExitArea(START_POINT))\n\t\t\t\t{\n\t\t\t\t\ttally.inEntrance++;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\ttally.inField++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn tally;\n}\n\n/**\n * Saves the custom craft deployment.\n */\nvoid SavedBattleGame::saveCustomCraftDeployment()\n{\n\t_craftForPreview->resetCustomDeployment();\n\tauto& customSoldierDeployment = _craftForPreview->getCustomSoldierDeployment();\n\tauto& customVehicleDeployment = _craftForPreview->getCustomVehicleDeployment();\n\n\tPosition tmp;\n\tfor (const auto* unit : _units)\n\t{\n\t\tif (unit->getOriginalFaction() == FACTION_PLAYER)\n\t\t{\n\t\t\tif (unit->isSummonedPlayerUnit())\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\ttmp = Position(unit->getPosition().x - _craftPos.x * 10, unit->getPosition().y - _craftPos.y * 10, unit->getPosition().z - _craftZ);\n\t\t\tif (unit->getGeoscapeSoldier())\n\t\t\t{\n\t\t\t\tcustomSoldierDeployment[unit->getGeoscapeSoldier()->getId()] = std::make_pair(tmp, unit->getDirection());\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tVehicleDeploymentData v;\n\t\t\t\tv.type = unit->getType();\n\t\t\t\tv.pos = tmp;\n\t\t\t\tv.dir = unit->getDirection();\n\t\t\t\tv.used = false; // irrelevant now, this will be used only in BattlescapeGenerator::addXCOMUnit()\n\t\t\t\tcustomVehicleDeployment.push_back(v);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Saves the custom RuleCraft deployment. Invalidates corresponding custom craft deployments.\n */\nvoid SavedBattleGame::saveDummyCraftDeployment()\n{\n\tauto* save = getGeoscapeSave();\n\n\t// don't forget to invalidate custom deployments of all real craft of this type\n\tfor (auto* xbase : *save->getBases())\n\t{\n\t\tfor (auto* xcraft : *xbase->getCrafts())\n\t\t{\n\t\t\tif (xcraft->getRules() == _craftForPreview->getRules())\n\t\t\t{\n\t\t\t\txcraft->resetCustomDeployment();\n\t\t\t}\n\t\t}\n\t}\n\n\tauto& data = save->getCustomRuleCraftDeployments();\n\n\tif (isCtrlPressed(true))\n\t{\n\t\t// delete\n\t\tdata.erase(_craftForPreview->getRules()->getType());\n\t}\n\telse\n\t{\n\t\t// save\n\t\tRuleCraftDeployment customDeployment;\n\t\tPosition tmp;\n\t\tfor (const auto* unit : _units)\n\t\t{\n\t\t\tif (unit->getOriginalFaction() == FACTION_PLAYER)\n\t\t\t{\n\t\t\t\tif (unit->isSummonedPlayerUnit())\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\ttmp = Position(unit->getPosition().x - _craftPos.x * 10, unit->getPosition().y - _craftPos.y * 10, unit->getPosition().z - _craftZ);\n\t\t\t\tif (unit->getGeoscapeSoldier())\n\t\t\t\t{\n\t\t\t\t\tcustomDeployment.push_back({ tmp.x, tmp.y, tmp.z, unit->getDirection() });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tdata[_craftForPreview->getRules()->getType()] = customDeployment;\n\t}\n}\n\n/**\n * Does the given craft type have a custom deployment?\n */\nbool SavedBattleGame::hasCustomDeployment(const RuleCraft* rule) const\n{\n\t// first check the fallback\n\tif (!rule->getDeployment().empty())\n\t{\n\t\treturn true;\n\t}\n\t// then the override\n\tauto* save = getGeoscapeSave();\n\tauto& data = save->getCustomRuleCraftDeployments();\n\tif (!data.empty())\n\t{\n\t\tauto find = data.find(rule->getType());\n\t\tif (find != data.end())\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Gets a custom deployment for the given craft type.\n */\nconst RuleCraftDeployment& SavedBattleGame::getCustomDeployment(const RuleCraft* rule) const\n{\n\t// first try the override\n\tauto* save = getGeoscapeSave();\n\tauto& data = save->getCustomRuleCraftDeployments();\n\tif (!data.empty())\n\t{\n\t\tauto find = data.find(rule->getType());\n\t\tif (find != data.end())\n\t\t{\n\t\t\treturn find->second;\n\t\t}\n\t}\n\t// this is the fallback\n\treturn rule->getDeployment();\n}\n\n/**\n * Ends the current turn and progresses to the next one.\n */\nvoid SavedBattleGame::endTurn()\n{\n\t// reset turret direction for all hostile and neutral units (as it may have been changed during reaction fire)\n\tfor (auto* bu : _units)\n\t{\n\t\tif (bu->getOriginalFaction() != FACTION_PLAYER)\n\t\t{\n\t\t\tbu->setDirection(bu->getDirection()); // this is not pointless, the method sets more than just the direction\n\t\t}\n\t}\n\n\tif (_side == FACTION_PLAYER)\n\t{\n\t\tif (_selectedUnit && _selectedUnit->getOriginalFaction() == FACTION_PLAYER)\n\t\t\t_lastSelectedUnit = _selectedUnit;\n\t\telse\n\t\t\t_lastSelectedUnit = nullptr;\n\t\t_selectedUnit =  0;\n\t\t_undoUnit = nullptr;\n\t\t_side = FACTION_HOSTILE;\n\t}\n\telse if (_side == FACTION_HOSTILE)\n\t{\n\t\t_selectedUnit =  0;\n\t\t_undoUnit = nullptr;\n\t\t_side = FACTION_NEUTRAL;\n\t\t// if there is no neutral team, we skip this and instantly prepare the new turn for the player\n//\t\tif (selectNextPlayerUnit() == 0)\n//\t\t{\n//\t\t\tprepareNewTurn();\n//\t\t\t_turn++;\n//\t\t\t_side = FACTION_PLAYER;\n//\t\t\tif (_lastSelectedUnit && _lastSelectedUnit->isSelectable(FACTION_PLAYER, false, false))\n//\t\t\t\t_selectedUnit = _lastSelectedUnit;\n//\t\t\telse\n//\t\t\t\tselectNextPlayerUnit();\n//\t\t\twhile (_selectedUnit && _selectedUnit->getFaction() != FACTION_PLAYER)\n//\t\t\t\tselectNextPlayerUnit();\n//\t\t}\n\t}\n\telse if (_side == FACTION_NEUTRAL)\n\t{\n\t\tprepareNewTurn();\n\t\t_turn++;\n\t\t_side = FACTION_PLAYER;\n\t\tif (_lastSelectedUnit && _lastSelectedUnit->isSelectable(FACTION_PLAYER, false, false))\n\t\t\t_selectedUnit = _lastSelectedUnit;\n\t\telse\n\t\t\tselectNextPlayerUnit();\n\t\twhile (_selectedUnit && _selectedUnit->getFaction() != FACTION_PLAYER)\n\t\t\tselectNextPlayerUnit();\n\n\t\t_undoUnit = nullptr;\n\t\t_lastSelectedUnit = nullptr;\n\t}\n\n\tBattlescapeTally tally = _battleState->getBattleGame()->tallyUnits();\n\n\tif ((_turn > _cheatTurn / 2 && tally.liveAliens <= 2) || _turn > _cheatTurn)\n\t{\n\t\t_cheating = true;\n\t}\n\n\tif (_side == FACTION_PLAYER)\n\t{\n\t\t// update the \"number of turns since last spotted\" and the number of turns left sniper AI knows about player units\n\t\tfor (auto* bu : _units)\n\t\t{\n\t\t\tif (bu->isIgnored())\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tbu->updateTurnsSince();\n\t\t\tif (_cheating && bu->getFaction() == FACTION_PLAYER && !bu->isOut())\n\t\t\t{\n\t\t\t\tbu->setTurnsSinceSpotted(0);\n\t\t\t}\n\t\t\tif (bu->getAIModule())\n\t\t\t{\n\t\t\t\tbu->getAIModule()->reset(); // clean up AI state\n\t\t\t}\n\t\t}\n\t}\n\n\t// hide all aliens (VOF calculations below will turn them visible again)\n\tfor (auto* bu : _units)\n\t{\n\t\tif (bu->isIgnored())\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Disclaimer: hardcoded!\n\t\tif (bu->getFaction() == FACTION_NEUTRAL && bu->getOriginalFaction() == FACTION_HOSTILE)\n\t\t{\n\t\t\tif (_side != FACTION_PLAYER)\n\t\t\t{\n\t\t\t\t// a hostile converted to a neutral during the player turn, just keep them mostly \"as is\" during the hostile/neutral turn...\n\t\t\t\tif (_side == FACTION_HOSTILE)\n\t\t\t\t{\n\t\t\t\t\tbu->updateUnitStats(false, true);\n\t\t\t\t}\n\t\t\t\tbu->setVisible(false);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// ...and convert them back at the beginning of the player turn\n\t\t\t\tbu->prepareNewTurn();\n\n\t\t\t\tif (bu->getAIModule())\n\t\t\t\t{\n\t\t\t\t\t// don't forget to rewire them back to attack the player again\n\t\t\t\t\tbu->getAIModule()->setTargetFaction(FACTION_PLAYER);\n\t\t\t\t}\n\t\t\t}\n\t\t\t// skip the standard logic\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (bu->getFaction() == _side)\n\t\t{\n\t\t\tbu->prepareNewTurn();\n\t\t}\n\t\telse if (bu->getOriginalFaction() == _side)\n\t\t{\n\t\t\tbu->updateUnitStats(false, true);\n\t\t}\n\t\tif (bu->getFaction() != FACTION_PLAYER)\n\t\t{\n\t\t\tbu->setVisible(false);\n\t\t}\n\t}\n\n\t//scripts update\n\tnewTurnUpdateScripts();\n\n\t//fov check will be done by `BattlescapeGame::endTurn`\n\n\tif (_side != FACTION_PLAYER)\n\t\tselectNextPlayerUnit();\n}\n\n/**\n * Get current animation frame number.\n * @return Frame number.\n */\nint SavedBattleGame::getAnimFrame() const\n{\n\treturn _animFrame;\n}\n\n/**\n * Increase animation frame with wrap around 705600.\n */\nvoid SavedBattleGame::nextAnimFrame()\n{\n\t_animFrame = (_animFrame + 1) % (64 * 3*3 * 5*5 * 7*7);\n}\n\n/**\n * Turns on debug mode.\n */\nvoid SavedBattleGame::setDebugMode()\n{\n\trevealMap();\n\n\t_debugMode = true;\n}\n\nvoid SavedBattleGame::revealMap()\n{\n\tfor (int i = 0; i < _mapsize_z * _mapsize_y * _mapsize_x; ++i)\n\t{\n\t\t_tiles[i].setDiscovered(true, O_FLOOR);\n\t}\n}\n\n/**\n * Gets the current debug mode.\n * @return Debug mode.\n */\nbool SavedBattleGame::getDebugMode() const\n{\n\treturn _debugMode;\n}\n\n/**\n* Sets the bug hunt mode.\n*/\nvoid SavedBattleGame::setBughuntMode(bool bughuntMode)\n{\n\t_bughuntMode = bughuntMode;\n}\n\n/**\n* Gets the current bug hunt mode.\n* @return Bug hunt mode.\n*/\nbool SavedBattleGame::getBughuntMode() const\n{\n\treturn _bughuntMode;\n}\n\n/**\n * Gets the BattlescapeState.\n * @return Pointer to the BattlescapeState.\n */\nBattlescapeState *SavedBattleGame::getBattleState()\n{\n\treturn _battleState;\n}\n\n/**\n * Gets the BattlescapeState.\n * @return Pointer to the BattlescapeState.\n */\nconst BattlescapeState *SavedBattleGame::getBattleState() const\n{\n\treturn _battleState;\n}\n\n/**\n * Gets the BattlescapeState.\n * @return Pointer to the BattlescapeState.\n */\nBattlescapeGame *SavedBattleGame::getBattleGame()\n{\n\treturn _battleState->getBattleGame();\n}\n\n/**\n * Gets the BattlescapeState.\n * @return Pointer to the BattlescapeState.\n */\nconst BattlescapeGame *SavedBattleGame::getBattleGame() const\n{\n\treturn _battleState->getBattleGame();\n}\n\n/**\n * Is BattlescapeState busy?\n * @return True, if busy.\n */\nbool SavedBattleGame::isBattlescapeStateBusy() const\n{\n\tif (_battleState)\n\t{\n\t\treturn _battleState->isBusy();\n\t}\n\treturn false;\n}\n\n/**\n * Sets the BattlescapeState.\n * @param bs A Pointer to a BattlescapeState.\n */\nvoid SavedBattleGame::setBattleState(BattlescapeState *bs)\n{\n\t_battleState = bs;\n}\n\n/**\n * Is CTRL pressed?\n */\nbool SavedBattleGame::isCtrlPressed(bool considerTouchButtons) const\n{\n\tif (_battleState)\n\t{\n\t\treturn _battleState->getGame()->isCtrlPressed(considerTouchButtons);\n\t}\n\treturn false;\n}\n\n/**\n * Is ALT pressed?\n */\nbool SavedBattleGame::isAltPressed(bool considerTouchButtons) const\n{\n\tif (_battleState)\n\t{\n\t\treturn _battleState->getGame()->isAltPressed(considerTouchButtons);\n\t}\n\treturn false;\n}\n\n/**\n * Is SHIFT pressed?\n */\nbool SavedBattleGame::isShiftPressed(bool considerTouchButtons) const\n{\n\tif (_battleState)\n\t{\n\t\treturn _battleState->getGame()->isShiftPressed(considerTouchButtons);\n\t}\n\treturn false;\n}\n\n/**\n * Resets all the units to their current standing tile(s).\n */\nvoid SavedBattleGame::resetUnitTiles()\n{\n\tfor (auto* bu : _units)\n\t{\n\t\tif (!bu->isOut())\n\t\t{\n\t\t\tbu->setTile(getTile(bu->getPosition()), this);\n\t\t}\n\t\tif (bu->getFaction() == FACTION_PLAYER)\n\t\t{\n\t\t\tbu->setVisible(true);\n\t\t}\n\t}\n\t_beforeGame = false;\n}\n\n/**\n * Gives access to the \"storage space\" vector, for distribution of items in base defense missions.\n * @return Vector of storage positions.\n */\nstd::vector<Position> &SavedBattleGame::getStorageSpace()\n{\n\treturn _storageSpace;\n}\n\n/**\n * Move all the leftover items in base defense missions to random locations in the storage facilities\n * @param t the tile where all our goodies are initially stored.\n */\nvoid SavedBattleGame::randomizeItemLocations(Tile *t)\n{\n\t// remove position of Tile t from the vector (because of potential endless loop)\n\tCollections::removeIf(_storageSpace, [&](Position& p) { return p == t->getPosition(); });\n\n\tif (!_storageSpace.empty())\n\t{\n\t\tfor (auto iter = t->getInventory()->begin(); iter != t->getInventory()->end();)\n\t\t{\n\t\t\tBattleItem* bi = (*iter);\n\t\t\tif (bi->getSlot()->getType() == INV_GROUND)\n\t\t\t{\n\t\t\t\tgetTile(_storageSpace.at(RNG::generate(0, _storageSpace.size() -1)))->addItem(bi, bi->getSlot());\n\t\t\t\titer = t->getInventory()->erase(iter);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t++iter;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Add item to delete list, usually when removing item from game or build in weapons\n * @param item Item to delete after game end.\n */\nvoid SavedBattleGame::deleteList(BattleItem* item)\n{\n\t_deleted.push_back(item);\n}\n\n/**\n * Removes an item from the game. Eg. when ammo item is depleted.\n * @param item The Item to remove.\n */\nvoid SavedBattleGame::removeItem(BattleItem *item)\n{\n\tauto purge = [](std::vector<BattleItem*> &inventory, BattleItem* forDelete)\n\t{\n\t\tauto end = inventory.end();\n\t\tfor (auto i = inventory.begin(); i != end; ++i)\n\t\t{\n\t\t\tif (*i == forDelete)\n\t\t\t{\n\t\t\t\tinventory.erase(i);\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t};\n\n\tif (item->isSpecialWeapon())\n\t{\n\t\t// we cannot remove it because load() would create a new one\n\t\t// only when a unit is killed or set to \"timeout\", we can remove its items.\n\t\treturn;\n\t}\n\n\tif (!purge(_items, item))\n\t{\n\t\treturn;\n\t}\n\n\t// due to strange design, the item has to be removed from the tile it is on too (if it is on a tile)\n\titem->moveToOwner(nullptr);\n\n\tdeleteList(item);\n\n\tfor (int slot = 0; slot < RuleItem::AmmoSlotMax; ++slot)\n\t{\n\t\tauto* ammo = item->getAmmoForSlot(slot);\n\t\tif (ammo && ammo != item)\n\t\t{\n\t\t\tif (purge(_items, ammo))\n\t\t\t{\n\t\t\t\tdeleteList(ammo);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Add built-in items from list to unit.\n * @param unit Unit that should get weapon.\n * @param fixed List of built-in items.\n */\nvoid SavedBattleGame::addFixedItems(BattleUnit *unit, const std::vector<const RuleItem*> &fixed)\n{\n\tif (!fixed.empty())\n\t{\n\t\tstd::vector<const RuleItem*> ammo;\n\t\tfor (const auto* ruleItem : fixed)\n\t\t{\n\t\t\tif (ruleItem)\n\t\t\t{\n\t\t\t\tif (ruleItem->getBattleType() == BT_AMMO)\n\t\t\t\t{\n\t\t\t\t\tammo.push_back(ruleItem);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tcreateItemForUnit(ruleItem, unit, true);\n\t\t\t}\n\t\t}\n\t\tfor (const auto* ruleItem : ammo)\n\t\t{\n\t\t\tcreateItemForUnit(ruleItem, unit, true);\n\t\t}\n\t}\n}\n\n/**\n * Create all fixed items for new created unit.\n * @param unit Unit to equip.\n */\nvoid SavedBattleGame::initUnit(BattleUnit *unit, size_t itemLevel)\n{\n\tif (_isPreview)\n\t{\n\t\treturn;\n\t}\n\n\tunit->setSpecialWeapon(this, false);\n\tconst Unit* rule = unit->getUnitRules();\n\tconst Armor* armor = unit->getArmor();\n\t// Built in weapons: the unit has this weapon regardless of loadout or what have you.\n\taddFixedItems(unit, armor->getBuiltInWeapons());\n\n\t// For aliens and HWP\n\tif (rule)\n\t{\n\t\tauto& buildin = rule->getBuiltInWeapons();\n\t\tif (!buildin.empty())\n\t\t{\n\t\t\tint idx = itemLevel >= buildin.size() ? buildin.size() - 1 : itemLevel;\n\t\t\t// Built in weapons: the unit has this weapon regardless of loadout or what have you.\n\t\t\taddFixedItems(unit, buildin.at(idx));\n\t\t}\n\n\t\tauto& buildin2 = rule->getWeightedBuiltInWeapons();\n\t\tif (!buildin2.empty())\n\t\t{\n\t\t\tint idx2 = itemLevel >= buildin2.size() ? buildin2.size() - 1 : itemLevel;\n\t\t\tauto* weights = buildin2.at(idx2);\n\t\t\tauto* weaponSetRule = _rule->getWeaponSet(weights->choose());\n\t\t\taddFixedItems(unit, weaponSetRule->getWeapons());\n\t\t}\n\n\t\t// terrorist alien's equipment is a special case - they are fitted with a weapon which is the alien's name with suffix _WEAPON\n\t\tif (rule->isLivingWeapon())\n\t\t{\n\t\t\tstd::string terroristWeapon = rule->getRace().substr(4);\n\t\t\tterroristWeapon += \"_WEAPON\";\n\t\t\tRuleItem *ruleItem = _rule->getItem(terroristWeapon);\n\t\t\tif (ruleItem)\n\t\t\t{\n\t\t\t\tBattleItem *item = createItemForUnit(ruleItem, unit);\n\t\t\t\tif (item)\n\t\t\t\t{\n\t\t\t\t\tunit->setTurretType(item->getRules()->getTurretType());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tModScript::scriptCallback<ModScript::CreateUnit>(armor, unit, this, this->getTurn());\n\n\tif (auto* solder = unit->getGeoscapeSoldier())\n\t{\n\t\tfor (const auto* bonus : *solder->getBonuses(nullptr))\n\t\t{\n\t\t\tModScript::scriptCallback<ModScript::ApplySoldierBonuses>(bonus, unit, this, bonus);\n\t\t}\n\t}\n}\n\n/**\n * Init new created item.\n * @param item\n */\nvoid SavedBattleGame::initItem(BattleItem *item, BattleUnit *unit)\n{\n\tif (_isPreview)\n\t{\n\t\treturn;\n\t}\n\n\tModScript::scriptCallback<ModScript::CreateItem>(item->getRules(), item, unit, this, this->getTurn());\n}\n\n/**\n * Create new item for unit.\n */\nBattleItem *SavedBattleGame::createItemForUnit(const RuleItem *rule, BattleUnit *unit, bool fixedWeapon)\n{\n\tif (_isPreview)\n\t{\n\t\treturn nullptr;\n\t}\n\n\tBattleItem *item = new BattleItem(rule, getCurrentItemId());\n\tif (!unit->addItem(item, _rule, false, fixedWeapon, fixedWeapon))\n\t{\n\t\tdelete item;\n\t\titem = nullptr;\n\t}\n\telse\n\t{\n\t\t_items.push_back(item);\n\t\tinitItem(item, unit);\n\t}\n\treturn item;\n}\n\n/**\n * Create new special built-in item for unit.\n */\nBattleItem *SavedBattleGame::createItemForUnitSpecialBuiltin(const RuleItem *rule, BattleUnit *unit)\n{\n\tif (_isPreview)\n\t{\n\t\treturn nullptr;\n\t}\n\n\tBattleItem *item = new BattleItem(rule, getCurrentItemId());\n\titem->setOwner(unit);\n\titem->setSlot(nullptr);\n\t_items.push_back(item);\n\tinitItem(item, unit);\n\treturn item;\n}\n/**\n * Create new item for tile.\n */\nBattleItem *SavedBattleGame::createItemForTile(const std::string& type, Tile *tile)\n{\n\treturn createItemForTile(_rule->getItem(type, true), tile);\n}\n\n/**\n * Create new item for tile;\n */\nBattleItem *SavedBattleGame::createItemForTile(const RuleItem *rule, Tile *tile, BattleUnit *corpseFor)\n{\n\t// Note: this is allowed also in preview mode; for items spawned from map blocks (and friendly units spawned from such items)\n\n\tBattleItem *item = new BattleItem(rule, getCurrentItemId());\n\tif (tile)\n\t{\n\t\tRuleInventory *ground = _rule->getInventoryGround();\n\t\ttile->addItem(item, ground);\n\t}\n\titem->setUnit(corpseFor);\n\t_items.push_back(item);\n\tinitItem(item);\n\treturn item;\n}\n\n/**\n * Create new temporary item. Item is not added to unit list and is not initialized fully.\n * @param rule Item config\n * @return New temporary item.\n */\nBattleItem *SavedBattleGame::createTempItem(const RuleItem *rule)\n{\n\treturn new BattleItem(rule, getCurrentItemId());\n}\n\n/**\n * Create new temporary unit. Unit is not added to unit list and is not initialized fully.\n * @param rules Unit config\n * @param faction Faction of unit\n * @param nextUnitId Optional next id of unit, if not given then it try get value based on last unit.\n * @return New temporary unit.\n */\nBattleUnit *SavedBattleGame::createTempUnit(const Unit *rules, UnitFaction faction, int nextUnitId)\n{\n\tBattleUnit *newUnit = new BattleUnit(\n\t\tgetMod(),\n\t\tconst_cast<Unit*>(rules),\n\t\tfaction,\n\t\tnextUnitId > 0 ? nextUnitId : getUnits()->back()->getId() + 1,\n\t\tgetEnviroEffects(),\n\t\trules->getArmor(),\n\t\tfaction == FACTION_HOSTILE ? _rule->getStatAdjustment(getGeoscapeSave()->getDifficulty()) : nullptr,\n\t\tgetDepth(),\n\t\tgetStartingCondition());\n\n\tif (faction == FACTION_PLAYER)\n\t{\n\t\t//Tanks are created with predefined `nextUnitId` value, if we do not have this value, its summoned unit.\n\t\tif (nextUnitId <= 0)\n\t\t{\n\t\t\tnewUnit->setSummonedPlayerUnit(true);\n\t\t}\n\t}\n\telse\n\t{\n\t\tnewUnit->setAIModule(new AIModule(this, newUnit, 0));\n\t}\n\n\treturn newUnit;\n}\n\n/**\n * Converts a unit into a unit of another type.\n * @param unit The unit to convert.\n * @return Pointer to the new unit.\n */\nBattleUnit *SavedBattleGame::convertUnit(BattleUnit *unit)\n{\n\t// only ever respawn once\n\tunit->setAlreadyRespawned(true);\n\n\tbool visible = unit->getVisible();\n\n\tclearUnitSelection(unit);\n\n\t// in case the unit was unconscious\n\tremoveUnconsciousBodyItem(unit);\n\n\tunit->instaKill();\n\n\tauto* tile = unit->getTile();\n\tif (tile == nullptr)\n\t{\n\t\tPosition pos = unit->getPosition();\n\t\tif (pos != TileEngine::invalid)\n\t\t{\n\t\t\ttile = getTile(pos);\n\t\t}\n\t}\n\n\t// in case of unconscious unit someone could stand on top of it, or take current unit to inventory, then we skip spawning anything\n\tif (!tile || (tile->getUnit() != nullptr && tile->getUnit() != unit))\n\t{\n\t\treturn nullptr;\n\t}\n\n\tgetTileEngine()->itemDropInventory(tile, unit, false, true);\n\n\t// remove unit-tile link\n\tunit->setTile(nullptr, this);\n\n\tconst Unit* type = unit->getSpawnUnit();\n\n\tBattleUnit *newUnit = createTempUnit(type, unit->getSpawnUnitFaction());\n\tnewUnit->setSpawnUnitFaction(unit->getSpawnUnitFaction()); // allied/neutral zombie should spawn an allied/neutral chryssalid?\n\n\tnewUnit->clearTimeUnits();\n\tnewUnit->setVisible(visible);\n\tnewUnit->setTile(tile, this);\n\tnewUnit->setPosition(unit->getPosition());\n\tnewUnit->setDirection(unit->getDirection());\n\tgetUnits()->push_back(newUnit);\n\tinitUnit(newUnit);\n\n\tgetTileEngine()->calculateFOV(newUnit->getPosition());  //happens fairly rarely, so do a full recalc for units in range to handle the potential unit visible cache issues.\n\tgetTileEngine()->applyGravity(newUnit->getTile());\n\tnewUnit->dontReselect();\n\treturn newUnit;\n}\n\n\n\n/**\n * Returns whether the battlescape should display the names of the soldiers or their callsigns.\n * @return True, if the battlescape should show player names + statstrings (default behaviour), or false, if the battlescape should display callsigns.\n */\nbool SavedBattleGame::isNameDisplay() const\n{\n\treturn _nameDisplay;\n}\n\n/**\n * Sets whether the player names (true) or their callsigns (false) are displayed\n * @param displayName True, if the battlescape should show player names + statstrings (default behaviour), or false, if the battlescape should display callsigns.\n */\nvoid SavedBattleGame::setNameDisplay(bool displayName)\n{\n\t_nameDisplay = displayName;\n}\n\n/**\n * Sets whether the mission was aborted or successful.\n * @param flag True, if the mission was aborted, or false, if the mission was successful.\n */\nvoid SavedBattleGame::setAborted(bool flag)\n{\n\t_aborted = flag;\n}\n\n/**\n * Returns whether the mission was aborted or successful.\n * @return True, if the mission was aborted, or false, if the mission was successful.\n */\nbool SavedBattleGame::isAborted() const\n{\n\treturn _aborted;\n}\n\n/**\n * increments the number of objectives to be destroyed.\n */\nvoid SavedBattleGame::setObjectiveCount(int counter)\n{\n\t_objectivesNeeded = counter;\n\t_objectivesDestroyed = 0;\n}\n\n/**\n * Sets whether the objective is destroyed.\n */\nvoid SavedBattleGame::addDestroyedObjective()\n{\n\tif (!allObjectivesDestroyed())\n\t{\n\t\t_objectivesDestroyed++;\n\t\tif (allObjectivesDestroyed())\n\t\t{\n\t\t\tif (getObjectiveType() == MUST_DESTROY)\n\t\t\t{\n\t\t\t\t_battleState->getBattleGame()->autoEndBattle();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_battleState->getBattleGame()->missionComplete();\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Returns whether the objectives are destroyed.\n * @return True if the objectives are destroyed.\n */\nbool SavedBattleGame::allObjectivesDestroyed() const\n{\n\treturn (_objectivesNeeded > 0 && _objectivesDestroyed == _objectivesNeeded);\n}\n\n/**\n * Gets the current item ID.\n * @return Current item ID pointer.\n */\nint *SavedBattleGame::getCurrentItemId()\n{\n\treturn &_itemId;\n}\n\n/**\n * Finds a fitting node where a unit can spawn.\n * @param nodeRank Rank of the node (this is not the rank of the alien!).\n * @param unit Pointer to the unit (to get its position).\n * @return Pointer to the chosen node.\n */\nNode *SavedBattleGame::getSpawnNode(int nodeRank, BattleUnit *unit)\n{\n\tint highestPriority = -1;\n\tstd::vector<Node*> compliantNodes;\n\n\tfor (auto* node : *getNodes())\n\t{\n\t\tif (node->isDummy())\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\t\tif (node->getRank() == nodeRank\t\t\t\t\t\t\t\t// ranks must match\n\t\t\t&& (!(node->getType() & Node::TYPE_SMALL)\n\t\t\t\t|| unit->isSmallUnit())\t\t\t\t\t\t\t\t// the small unit bit is not set or the unit is small\n\t\t\t&& (!(node->getType() & Node::TYPE_FLYING)\n\t\t\t\t|| unit->getMovementType() == MT_FLY)\t\t\t\t// the flying unit bit is not set or the unit can fly\n\t\t\t&& node->getPriority() > 0\t\t\t\t\t\t\t\t// priority 0 is no spawn place\n\t\t\t&& setUnitPosition(unit, node->getPosition(), true))\t// check if not already occupied\n\t\t{\n\t\t\tif (node->getPriority() > highestPriority)\n\t\t\t{\n\t\t\t\thighestPriority = node->getPriority();\n\t\t\t\tcompliantNodes.clear(); // drop the last nodes, as we found a higher priority now\n\t\t\t}\n\t\t\tif (node->getPriority() == highestPriority)\n\t\t\t{\n\t\t\t\tcompliantNodes.push_back(node);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (compliantNodes.empty()) return 0;\n\n\tint n = RNG::generate(0, compliantNodes.size() - 1);\n\n\treturn compliantNodes[n];\n}\n\n/**\n * Finds a fitting node where a unit can patrol to.\n * @param scout Is the unit scouting?\n * @param unit Pointer to the unit (to get its position).\n * @param fromNode Pointer to the node the unit is at.\n * @return Pointer to the chosen node.\n */\nNode *SavedBattleGame::getPatrolNode(bool scout, BattleUnit *unit, Node *fromNode)\n{\n\tstd::vector<Node *> compliantNodes;\n\tNode *preferred = 0;\n\n\tif (fromNode == 0)\n\t{\n\t\tif (Options::traceAI) { Log(LOG_INFO) << \"This alien got lost. :(\"; }\n\t\tfromNode = getNodes()->at(RNG::generate(0, getNodes()->size() - 1));\n\t\twhile (fromNode->isDummy())\n\t\t{\n\t\t\tfromNode = getNodes()->at(RNG::generate(0, getNodes()->size() - 1));\n\t\t}\n\t}\n\n\t// scouts roam all over while all others shuffle around to adjacent nodes at most:\n\tconst int end = scout ? getNodes()->size() : fromNode->getNodeLinks()->size();\n\n\tfor (int i = 0; i < end; ++i)\n\t{\n\t\tif (!scout && fromNode->getNodeLinks()->at(i) < 1) continue;\n\n\t\tNode *n = getNodes()->at(scout ? i : fromNode->getNodeLinks()->at(i));\n\t\tif ( !n->isDummy()\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// don't consider dummy nodes.\n\t\t\t&& (n->getFlags() > 0 || n->getRank() > 0 || scout)\t\t\t\t\t\t\t\t\t\t\t// for non-scouts we find a node with a desirability above 0\n\t\t\t&& (!(n->getType() & Node::TYPE_SMALL) || unit->isSmallUnit())\t\t\t\t\t\t\t\t// the small unit bit is not set or the unit is small\n\t\t\t&& (!(n->getType() & Node::TYPE_FLYING) || unit->getMovementType() == MT_FLY)\t// the flying unit bit is not set or the unit can fly\n\t\t\t&& !n->isAllocated()\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// check if not allocated\n\t\t\t&& !(n->getType() & Node::TYPE_DANGEROUS)\t\t\t\t\t\t\t\t\t\t\t\t\t// don't go there if an alien got shot there; stupid behavior like that\n\t\t\t&& setUnitPosition(unit, n->getPosition(), true)\t\t\t\t\t\t\t\t\t\t\t// check if not already occupied\n\t\t\t&& getTile(n->getPosition()) && !getTile(n->getPosition())->getFire()\t\t\t\t\t\t// you are not a firefighter; do not patrol into fire\n\t\t\t&& (unit->getFaction() != FACTION_HOSTILE || !getTile(n->getPosition())->getDangerous())\t// aliens don't run into a grenade blast\n\t\t\t&& (!scout || n != fromNode)\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// scouts push forward\n\t\t\t&& n->getPosition().x > 0 && n->getPosition().y > 0)\n\t\t{\n\t\t\tif (!preferred\n\t\t\t\t|| (unit->getRankInt() >=0 &&\n\t\t\t\t\tpreferred->getRank() == Node::nodeRank[unit->getRankInt()][0] &&\n\t\t\t\t\tpreferred->getFlags() < n->getFlags())\n\t\t\t\t|| preferred->getFlags() < n->getFlags())\n\t\t\t{\n\t\t\t\tpreferred = n;\n\t\t\t}\n\t\t\tcompliantNodes.push_back(n);\n\t\t}\n\t}\n\n\tif (compliantNodes.empty())\n\t{\n\t\tif (Options::traceAI) { Log(LOG_INFO) << (scout ? \"Scout \" : \"Guard\") << \" found on patrol node! XXX XXX XXX\"; }\n\t\tif (unit->isBigUnit() && !scout)\n\t\t{\n\t\t\treturn getPatrolNode(true, unit, fromNode); // move dammit\n\t\t}\n\t\telse\n\t\t\treturn 0;\n\t}\n\n\tif (scout)\n\t{\n\t\t// scout picks a random destination:\n\t\treturn compliantNodes[RNG::generate(0, compliantNodes.size() - 1)];\n\t}\n\telse\n\t{\n\t\tif (!preferred) return 0;\n\n\t\t// non-scout patrols to highest value unoccupied node that's not fromNode\n\t\tif (Options::traceAI) { Log(LOG_INFO) << \"Choosing node flagged \" << preferred->getFlags(); }\n\t\treturn preferred;\n\t}\n}\n\n/**\n * Carries out new turn preparations such as fire and smoke spreading.\n */\nvoid SavedBattleGame::prepareNewTurn()\n{\n\tstd::vector<Tile*> tilesOnFire;\n\tstd::vector<Tile*> tilesOnSmoke;\n\n\t// prepare a list of tiles on fire\n\tfor (int i = 0; i < _mapsize_x * _mapsize_y * _mapsize_z; ++i)\n\t{\n\t\tif (getTile(i)->getFire() > 0)\n\t\t{\n\t\t\ttilesOnFire.push_back(getTile(i));\n\t\t}\n\t}\n\n\t// first: fires spread\n\tfor (auto* tileOnFire : tilesOnFire)\n\t{\n\t\t// if we haven't added fire here this turn\n\t\tif (tileOnFire->getOverlaps() == 0)\n\t\t{\n\t\t\t// reduce the fire timer\n\t\t\ttileOnFire->setFire(tileOnFire->getFire() -1);\n\n\t\t\t// if we're still burning\n\t\t\tif (tileOnFire->getFire())\n\t\t\t{\n\t\t\t\t// propagate in four cardinal directions (0, 2, 4, 6)\n\t\t\t\tfor (int dir = 0; dir <= 6; dir += 2)\n\t\t\t\t{\n\t\t\t\t\tPosition pos;\n\t\t\t\t\tPathfinding::directionToVector(dir, &pos);\n\t\t\t\t\tTile *t = getTile(tileOnFire->getPosition() + pos);\n\t\t\t\t\t// if there's no wall blocking the path of the flames...\n\t\t\t\t\tif (t && getTileEngine()->horizontalBlockage(tileOnFire, t, DT_IN) == 0)\n\t\t\t\t\t{\n\t\t\t\t\t\t// attempt to set this tile on fire\n\t\t\t\t\t\tt->ignite(tileOnFire->getSmoke());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// fire has burnt out\n\t\t\telse\n\t\t\t{\n\t\t\t\ttileOnFire->setSmoke(0);\n\t\t\t\t// burn this tile, and any object in it, if it's not fireproof/indestructible.\n\t\t\t\tif (tileOnFire->getMapData(O_OBJECT))\n\t\t\t\t{\n\t\t\t\t\tif (tileOnFire->getMapData(O_OBJECT)->getFlammable() != 255 && tileOnFire->getMapData(O_OBJECT)->getArmor() != 255)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (tileOnFire->destroy(O_OBJECT, getObjectiveType()))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\taddDestroyedObjective();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (tileOnFire->destroy(O_FLOOR, getObjectiveType()))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\taddDestroyedObjective();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (tileOnFire->getMapData(O_FLOOR))\n\t\t\t\t{\n\t\t\t\t\tif (tileOnFire->getMapData(O_FLOOR)->getFlammable() != 255 && tileOnFire->getMapData(O_FLOOR)->getArmor() != 255)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (tileOnFire->destroy(O_FLOOR, getObjectiveType()))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\taddDestroyedObjective();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tgetTileEngine()->applyGravity(tileOnFire);\n\t\t\t}\n\t\t}\n\t}\n\n\t// prepare a list of tiles on fire/with smoke in them (smoke acts as fire intensity)\n\tfor (int i = 0; i < _mapsize_x * _mapsize_y * _mapsize_z; ++i)\n\t{\n\t\tif (getTile(i)->getSmoke() > 0)\n\t\t{\n\t\t\ttilesOnSmoke.push_back(getTile(i));\n\t\t}\n\t\tgetTile(i)->setDangerous(false);\n\t}\n\n\t// now make the smoke spread.\n\tfor (auto* tileOnSmoke : tilesOnSmoke)\n\t{\n\t\t// smoke and fire follow slightly different rules.\n\t\tif (tileOnSmoke->getFire() == 0)\n\t\t{\n\t\t\t// reduce the smoke counter\n\t\t\ttileOnSmoke->setSmoke(tileOnSmoke->getSmoke() - 1);\n\t\t\t// if we're still smoking\n\t\t\tif (tileOnSmoke->getSmoke())\n\t\t\t{\n\t\t\t\t// spread in four cardinal directions\n\t\t\t\tfor (int dir = 0; dir <= 6; dir += 2)\n\t\t\t\t{\n\t\t\t\t\tPosition pos;\n\t\t\t\t\tPathfinding::directionToVector(dir, &pos);\n\t\t\t\t\tTile *t = getTile(tileOnSmoke->getPosition() + pos);\n\t\t\t\t\t// as long as there are no walls blocking us\n\t\t\t\t\tif (t && getTileEngine()->horizontalBlockage(tileOnSmoke, t, DT_SMOKE) == 0)\n\t\t\t\t\t{\n\t\t\t\t\t\t// only add smoke to empty tiles, or tiles with no fire, and smoke that was added this turn\n\t\t\t\t\t\tif (t->getSmoke() == 0 || (t->getFire() == 0 && t->getOverlaps() != 0))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tt->addSmoke(tileOnSmoke->getSmoke());\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// smoke from fire spreads upwards one level if there's no floor blocking it.\n\t\t\tPosition pos = Position(0,0,1);\n\t\t\tTile *t = getTile(tileOnSmoke->getPosition() + pos);\n\t\t\tif (t && t->hasNoFloor(this))\n\t\t\t{\n\t\t\t\t// only add smoke equal to half the intensity of the fire\n\t\t\t\tt->addSmoke(tileOnSmoke->getSmoke()/2);\n\t\t\t}\n\t\t\t// then it spreads in the four cardinal directions.\n\t\t\tfor (int dir = 0; dir <= 6; dir += 2)\n\t\t\t{\n\t\t\t\tPathfinding::directionToVector(dir, &pos);\n\t\t\t\tt = getTile(tileOnSmoke->getPosition() + pos);\n\t\t\t\tif (t && getTileEngine()->horizontalBlockage(tileOnSmoke, t, DT_SMOKE) == 0)\n\t\t\t\t{\n\t\t\t\t\tt->addSmoke(tileOnSmoke->getSmoke()/2);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (!tilesOnFire.empty() || !tilesOnSmoke.empty())\n\t{\n\t\t// do damage to units, average out the smoke, etc.\n\t\tfor (int i = 0; i < _mapsize_x * _mapsize_y * _mapsize_z; ++i)\n\t\t{\n\t\t\tif (getTile(i)->getSmoke() != 0)\n\t\t\t\tgetTile(i)->prepareNewTurn(getDepth() == 0);\n\t\t}\n\t}\n\n\tMod *mod = getBattleState()->getGame()->getMod();\n\tfor (auto* bu : *getUnits())\n\t{\n\t\tbu->calculateEnviDamage(mod, this);\n\t}\n\n\t//fov and light udadates are done in `BattlescapeGame::endTurn`\n}\n\n/**\n * Checks for units that are unconscious and revives them if they shouldn't be.\n *\n * Revived units need a tile to stand on. If the unit's current position is occupied, then\n * all directions around the tile are searched for a free tile to place the unit in.\n * If no free tile is found the unit stays unconscious.\n */\nvoid SavedBattleGame::reviveUnconsciousUnits(bool noTU)\n{\n\tfor (auto* bu : *getUnits())\n\t{\n\t\tif (bu->isSmallUnit() && !bu->isIgnored())\n\t\t{\n\t\t\tPosition originalPosition = bu->getPosition();\n\t\t\tif (originalPosition == Position(-1, -1, -1))\n\t\t\t{\n\t\t\t\tfor (auto* bi : _items)\n\t\t\t\t{\n\t\t\t\t\tif (bi->getUnit() && bi->getUnit() == bu && bi->getOwner())\n\t\t\t\t\t{\n\t\t\t\t\t\toriginalPosition = bi->getOwner()->getPosition();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (bu->getStatus() == STATUS_UNCONSCIOUS && !bu->isOutThresholdExceed())\n\t\t\t{\n\t\t\t\tTile *targetTile = getTile(originalPosition);\n\t\t\t\tbool largeUnit = targetTile && targetTile->getUnit() && targetTile->getUnit() != bu && targetTile->getUnit()->isBigUnit();\n\t\t\t\tif (placeUnitNearPosition(bu, originalPosition, largeUnit))\n\t\t\t\t{\n\t\t\t\t\t// recover from unconscious\n\t\t\t\t\tbu->setNotificationShown(0);\n\t\t\t\t\tbu->turn(false); // makes the unit stand up again\n\t\t\t\t\tbu->kneel(false);\n\t\t\t\t\tbu->setAlreadyExploded(false);\n\t\t\t\t\tif (noTU)\n\t\t\t\t\t{\n\t\t\t\t\t\tbu->clearTimeUnits();\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tbu->updateUnitStats(true, false);\n\t\t\t\t\t\tif (getMod()->getTURecoveryWakeUpNewTurn() < 100)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tint newTU = bu->getTimeUnits() * getMod()->getTURecoveryWakeUpNewTurn() / 100;\n\t\t\t\t\t\t\tbu->setTimeUnits(newTU);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tremoveUnconsciousBodyItem(bu);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Removes the body item that corresponds to the unit.\n */\nvoid SavedBattleGame::removeUnconsciousBodyItem(BattleUnit *bu)\n{\n\tint size = bu->getArmor()->getSize();\n\tsize *= size;\n\t// remove the unconscious body item corresponding to this unit\n\tfor (auto iter = getItems()->begin(); iter != getItems()->end(); )\n\t{\n\t\tif ((*iter)->getUnit() == bu)\n\t\t{\n\t\t\tremoveItem((*iter)); //TODO: if used on anything other that corpse it will crash as it could remove MORE than one item from `getItems()` and them go pass `!= end()`\n\t\t\tif (--size == 0) break;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t++iter;\n\t\t}\n\t}\n}\n\n/**\n * Places units on the map. Handles large units that are placed on multiple tiles.\n * @param bu The unit to be placed.\n * @param position The position to place the unit.\n * @param testOnly If true then just checks if the unit can be placed at the position.\n * @return True if the unit could be successfully placed.\n */\nbool SavedBattleGame::setUnitPosition(BattleUnit *bu, Position position, bool testOnly)\n{\n\tint size = bu->getArmor()->getSize() - 1;\n\tPosition zOffset (0,0,0);\n\t// first check if the tiles are occupied\n\tfor (int x = size; x >= 0; x--)\n\t{\n\t\tfor (int y = size; y >= 0; y--)\n\t\t{\n\t\t\tTile *t = getTile(position + Position(x,y,0) + zOffset);\n\t\t\tif (t == 0 ||\n\t\t\t\t(t->getUnit() != 0 && t->getUnit() != bu) ||\n\t\t\t\tt->getTUCost(O_OBJECT, bu->getMovementType()) == Pathfinding::INVALID_MOVE_COST ||\n\t\t\t\t(t->hasNoFloor(this) && bu->getMovementType() != MT_FLY) ||\n\t\t\t\t(t->getMapData(O_OBJECT) && t->getMapData(O_OBJECT)->getBigWall() && t->getMapData(O_OBJECT)->getBigWall() <= 3))\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t// move the unit up to the next level (desert and seabed terrains)\n\t\t\tif (t && t->getTerrainLevel() == -24)\n\t\t\t{\n\t\t\t\tzOffset.z += 1;\n\t\t\t\tx = size;\n\t\t\t\ty = size + 1;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (size > 0)\n\t{\n\t\tgetPathfinding()->setUnit(bu); //TODO: remove as was required by `isBlockedDirection`\n\t\tfor (int dir = 2; dir <= 4; ++dir)\n\t\t{\n\t\t\tif (getPathfinding()->isBlockedDirection(bu, getTile(position + zOffset), dir))\n\t\t\t\treturn false;\n\t\t}\n\t}\n\n\tif (testOnly) return true;\n\n\tbu->setTile(getTile(position + zOffset), this);\n\tbu->setPosition(position + zOffset);\n\n\treturn true;\n}\n\n/**\n * @brief Checks whether anyone on a particular faction is looking at the unit.\n *\n * Similar to getSpottingUnits() but returns a bool and stops searching if one positive hit is found.\n *\n * @param faction Faction to check through.\n * @param unit Whom to spot.\n * @return True when the unit can be seen\n */\nbool SavedBattleGame::eyesOnTarget(UnitFaction faction, BattleUnit* unit)\n{\n\tfor (auto* bu : *getUnits())\n\t{\n\t\tif (bu->getFaction() != faction) continue;\n\n\t\tauto* vis = bu->getVisibleUnits();\n\t\tif (std::find(vis->begin(), vis->end(), unit) != vis->end()) return true;\n\t\t// aliens know the location of all XCom agents sighted by all other aliens due to sharing locations over their space-walkie-talkies\n\t}\n\n\treturn false;\n}\n\n/**\n * Adds this unit to the vector of falling units,\n * if it doesn't already exist.\n * @param unit The unit.\n * @return Was the unit added?\n */\nbool SavedBattleGame::addFallingUnit(BattleUnit* unit)\n{\n\tbool add = true;\n\tfor (auto* bu : _fallingUnits)\n\t{\n\t\tif (unit == bu)\n\t\t{\n\t\t\tadd = false;\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (add)\n\t{\n\t\t_fallingUnits.push_front(unit);\n\t\t_unitsFalling = true;\n\t}\n\treturn add;\n}\n\n/**\n * Gets all units in the battlescape that are falling.\n * @return The falling units in the battlescape.\n */\nstd::list<BattleUnit*> *SavedBattleGame::getFallingUnits()\n{\n\treturn &_fallingUnits;\n}\n\n/**\n * Toggles the switch that says \"there are units falling, start the fall state\".\n * @param fall True if there are any units falling in the battlescape.\n */\nvoid SavedBattleGame::setUnitsFalling(bool fall)\n{\n\t_unitsFalling = fall;\n}\n\n/**\n * Returns whether there are any units falling in the battlescape.\n * @return True if there are any units falling in the battlescape.\n */\nbool SavedBattleGame::getUnitsFalling() const\n{\n\treturn _unitsFalling;\n}\n\n/**\n * Gets the highest ranked, living XCom unit.\n * @return The highest ranked, living XCom unit.\n */\nBattleUnit* SavedBattleGame::getHighestRankedXCom()\n{\n\tBattleUnit* highest = 0;\n\tfor (auto* bu : _units)\n\t{\n\t\tif (bu->getOriginalFaction() == FACTION_PLAYER && !bu->isOut())\n\t\t{\n\t\t\tif (highest == 0 || bu->getRankInt() > highest->getRankInt())\n\t\t\t{\n\t\t\t\thighest = bu;\n\t\t\t}\n\t\t}\n\t}\n\treturn highest;\n}\n\n/**\n * Gets morale modifier of unit.\n * @param unit\n * @return Morale modifier.\n */\nint SavedBattleGame::getUnitMoraleModifier(BattleUnit* unit)\n{\n\tint result = 100;\n\n\tif (unit->getOriginalFaction() == FACTION_PLAYER)\n\t{\n\t\tswitch (unit->getRankInt())\n\t\t{\n\t\tcase 5:\n\t\t\tresult += 25;\n\t\t\tFALLTHROUGH;\n\t\tcase 4:\n\t\t\tresult += 20;\n\t\t\tFALLTHROUGH;\n\t\tcase 3:\n\t\t\tresult += 10;\n\t\t\tFALLTHROUGH;\n\t\tcase 2:\n\t\t\tresult += 20;\n\t\t\tFALLTHROUGH;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn result;\n}\n\n/**\n * Gets the morale loss modifier (by unit type) of the killed unit.\n * @param unit\n * @return Morale modifier.\n */\nint SavedBattleGame::getMoraleLossModifierWhenKilled(BattleUnit* unit)\n{\n\tint result = 100;\n\n\tif (!unit)\n\t\treturn result;\n\n\tif (unit->getGeoscapeSoldier())\n\t{\n\t\tresult = unit->getGeoscapeSoldier()->getRules()->getMoraleLossWhenKilled();\n\t}\n\telse if (unit->getUnitRules())\n\t{\n\t\tresult = unit->getUnitRules()->getMoraleLossWhenKilled();\n\t}\n\n\t// it's a morale loss, there's no way I am allowing modders to make it a morale gain!\n\treturn std::max(0, result);\n}\n\n/**\n * Gets the morale modifier for XCom based on the highest ranked, living XCom unit,\n * or Alien modifier based on they number.\n * @param hostile modifier for player or hostile?\n * @return The morale modifier.\n */\nint SavedBattleGame::getFactionMoraleModifier(bool player)\n{\n\tif (player)\n\t{\n\t\tBattleUnit *leader = getHighestRankedXCom();\n\t\tint result = 100;\n\t\tif (leader)\n\t\t{\n\t\t\tswitch (leader->getRankInt())\n\t\t\t{\n\t\t\tcase 5:\n\t\t\t\tresult += 25;\n\t\t\t\tFALLTHROUGH;\n\t\t\tcase 4:\n\t\t\t\tresult += 10;\n\t\t\t\tFALLTHROUGH;\n\t\t\tcase 3:\n\t\t\t\tresult += 5;\n\t\t\t\tFALLTHROUGH;\n\t\t\tcase 2:\n\t\t\t\tresult += 10;\n\t\t\t\tFALLTHROUGH;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\telse\n\t{\n\t\tint number = 0;\n\t\tfor (auto* bu : _units)\n\t\t{\n\t\t\tif (bu->getOriginalFaction() == FACTION_HOSTILE && !bu->isOut())\n\t\t\t{\n\t\t\t\t++number;\n\t\t\t}\n\t\t}\n\t\treturn std::max(6 * number, 100);\n\t}\n}\n\n/**\n * Places a unit on or near a position.\n * @param unit The unit to place.\n * @param entryPoint The position around which to attempt to place the unit.\n * @return True if the unit was successfully placed.\n */\nbool SavedBattleGame::placeUnitNearPosition(BattleUnit *unit, const Position& entryPoint, bool largeFriend)\n{\n\tif (setUnitPosition(unit, entryPoint))\n\t{\n\t\treturn true;\n\t}\n\n\tint me = 0 - unit->getArmor()->getSize();\n\tint you = largeFriend ? 2 : 1;\n\tint xArray[8] = {0, you, you, you, 0, me, me, me};\n\tint yArray[8] = {me, me, 0, you, you, you, 0, me};\n\tfor (int dir = 0; dir <= 7; ++dir)\n\t{\n\t\tPosition offset = Position (xArray[dir], yArray[dir], 0);\n\t\tTile *t = getTile(entryPoint + offset);\n\t\tif (t && !getPathfinding()->isBlockedDirection(unit, getTile(entryPoint + (offset / 2)), dir)\n\t\t\t&& setUnitPosition(unit, entryPoint + offset))\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t}\n\n\tif (unit->getMovementType() == MT_FLY)\n\t{\n\t\tTile *t = getTile(entryPoint + Position(0, 0, 1));\n\t\tif (t && t->hasNoFloor(this) && setUnitPosition(unit, entryPoint + Position(0, 0, 1)))\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Resets the turn counter.\n */\nvoid SavedBattleGame::resetTurnCounter()\n{\n\t_turn = 0;\n\t_cheating = false;\n\t_side = FACTION_PLAYER;\n\t_beforeGame = true;\n}\n\n/**\n * Resets visibility of all the tiles on the map.\n */\nvoid SavedBattleGame::resetTiles()\n{\n\tfor (int i = 0; i != getMapSizeXYZ(); ++i)\n\t{\n\t\t_tiles[i].setDiscovered(false, O_WESTWALL);\n\t\t_tiles[i].setDiscovered(false, O_NORTHWALL);\n\t\t_tiles[i].setDiscovered(false, O_FLOOR);\n\t}\n}\n\n/**\n * @return the tile search vector for use in AI functions.\n */\nconst std::vector<Position> &SavedBattleGame::getTileSearch() const\n{\n\treturn _tileSearch;\n}\n\n/**\n * is the AI allowed to cheat?\n * @return true if cheating.\n */\nbool SavedBattleGame::isCheating() const\n{\n\treturn _cheating;\n}\n\n/**\n * Gets the TU reserved type.\n * @return A battle action type.\n */\nBattleActionType SavedBattleGame::getTUReserved() const\n{\n\treturn _tuReserved;\n}\n\n/**\n * Sets the TU reserved type.\n * @param reserved A battle action type.\n */\nvoid SavedBattleGame::setTUReserved(BattleActionType reserved)\n{\n\t_tuReserved = reserved;\n}\n\n/**\n * Gets the kneel reservation setting.\n * @return Should we reserve an extra 4 TUs to kneel?\n */\nbool SavedBattleGame::getKneelReserved() const\n{\n\treturn _kneelReserved;\n}\n\n/**\n * Sets the kneel reservation setting.\n * @param reserved Should we reserve an extra 4 TUs to kneel?\n */\nvoid SavedBattleGame::setKneelReserved(bool reserved)\n{\n\t_kneelReserved = reserved;\n}\n\n/**\n * Return a reference to the base module destruction map\n * this map contains information on how many destructible base modules\n * remain at any given grid reference in the basescape, using [x][y] format.\n * -1 for \"no items\" 0 for \"destroyed\" and any actual number represents how many left.\n * @return the base module damage map.\n */\nstd::vector< std::vector<std::pair<int, int> > > &SavedBattleGame::getModuleMap()\n{\n\treturn _baseModules;\n}\n\n/**\n * calculate the number of map modules remaining by counting the map objects\n * on the top floor who have the baseModule flag set. we store this data in the grid\n * as outlined in the comments above, in pairs representing initial and current values.\n */\nvoid SavedBattleGame::calculateModuleMap()\n{\n\t_baseModules.resize((_mapsize_x / 10), std::vector<std::pair<int, int> >((_mapsize_y / 10), std::make_pair(-1, -1)));\n\n\tfor (int x = 0; x != _mapsize_x; ++x)\n\t{\n\t\tfor (int y = 0; y != _mapsize_y; ++y)\n\t\t{\n\t\t\tfor (int z = 0; z != _mapsize_z; ++z)\n\t\t\t{\n\t\t\t\tTile *tile = getTile(Position(x,y,z));\n\t\t\t\tif (tile && tile->getMapData(O_OBJECT) && tile->getMapData(O_OBJECT)->isBaseModule())\n\t\t\t\t{\n\t\t\t\t\t_baseModules[x/10][y/10].first += _baseModules[x/10][y/10].first > 0 ? 1 : 2;\n\t\t\t\t\t_baseModules[x/10][y/10].second = _baseModules[x/10][y/10].first;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * get a pointer to the geoscape save\n * @return a pointer to the geoscape save.\n */\nSavedGame *SavedBattleGame::getGeoscapeSave() const\n{\n\treturn _battleState->getGame()->getSavedGame();\n}\n\n/**\n * check the depth of the battlescape.\n * @return depth.\n */\nint SavedBattleGame::getDepth() const\n{\n\treturn _depth;\n}\n\n/**\n * set the depth of the battlescape game.\n * @param depth the intended depth 0-3.\n */\nvoid SavedBattleGame::setDepth(int depth)\n{\n\t_depth = depth;\n}\n\n/**\n * uses the depth variable to choose a palette.\n * @param state the state to set the palette for.\n */\nvoid SavedBattleGame::setPaletteByDepth(State *state)\n{\n\tif (_depth == 0)\n\t{\n\t\tstate->setStandardPalette(\"PAL_BATTLESCAPE\");\n\t}\n\telse\n\t{\n\t\tstd::ostringstream ss;\n\t\tss << \"PAL_BATTLESCAPE_\" << _depth;\n\t\tstate->setStandardPalette(ss.str());\n\t}\n}\n\n/**\n * set the ambient battlescape sound effect.\n * @param sound the intended sound.\n */\nvoid SavedBattleGame::setAmbientSound(int sound)\n{\n\t_ambience = sound;\n}\n\n/**\n * get the ambient battlescape sound effect.\n * @return the intended sound.\n */\nint SavedBattleGame::getAmbientSound() const\n{\n\treturn _ambience;\n}\n\n/**\n * Reset the current random ambient sound delay.\n */\nvoid SavedBattleGame::resetCurrentAmbienceDelay()\n{\n\t_currentAmbienceDelay = RNG::seedless(_minAmbienceRandomDelay * 10, _maxAmbienceRandomDelay * 10);\n\tif (_currentAmbienceDelay < 10)\n\t\t_currentAmbienceDelay = 10; // at least 1 second\n}\n\n/**\n * Play a random ambient sound.\n */\nvoid SavedBattleGame::playRandomAmbientSound()\n{\n\tif (!_ambienceRandom.empty())\n\t{\n\t\tint soundIndex = RNG::seedless(0, _ambienceRandom.size() - 1);\n\t\tgetMod()->getSoundByDepth(_depth, _ambienceRandom.at(soundIndex))->play(3); // use fixed ambience channel; don't check if previous sound is still playing or not\n\t}\n}\n\n/**\n * get the list of items we're guaranteed to take with us (ie: items that were in the skyranger)\n * @return the list of items we're guaranteed.\n */\nstd::vector<BattleItem*> *SavedBattleGame::getGuaranteedRecoveredItems()\n{\n\treturn &_recoverGuaranteed;\n}\n\n/**\n * get the list of items we're not guaranteed to take with us (ie: items that were NOT in the skyranger)\n * @return the list of items we might get.\n */\nstd::vector<BattleItem*> *SavedBattleGame::getConditionalRecoveredItems()\n{\n\treturn &_recoverConditional;\n}\n\n/**\n * Get the music track for the current battle.\n * @return the name of the music track.\n */\nconst std::string &SavedBattleGame::getMusic() const\n{\n\treturn _music;\n}\n\n/**\n * Set the music track for this battle.\n * @param track the track name.\n */\nvoid SavedBattleGame::setMusic(const std::string &track)\n{\n\t_music = track;\n}\n\n/**\n * Sets the VIP escape type.\n */\nvoid SavedBattleGame::setVIPEscapeType(EscapeType vipEscapeType)\n{\n\t_vipEscapeType = vipEscapeType;\n}\n\n/**\n * Gets the VIP escape type.\n */\nEscapeType SavedBattleGame::getVIPEscapeType() const\n{\n\treturn _vipEscapeType;\n}\n\n/**\n * Sets the percentage of VIPs that must survive in order to accomplish the mission.\n * If the mission has multiple stages, the biggest setting is used at the end.\n */\nvoid SavedBattleGame::setVIPSurvivalPercentage(int vipSurvivalPercentage)\n{\n\t_vipSurvivalPercentage = std::max(_vipSurvivalPercentage, vipSurvivalPercentage);\n}\n\n/**\n * Gets the percentage of VIPs that must survive in order to accomplish the mission.\n */\nint SavedBattleGame::getVIPSurvivalPercentage() const\n{\n\treturn _vipSurvivalPercentage;\n}\n\n/**\n * Increase the saved VIPs counter and score.\n */\nvoid SavedBattleGame::addSavedVIP(int score)\n{\n\t_vipsSaved++;\n\t_vipsSavedScore += score;\n}\n\n/**\n * Gets the saved VIPs counter.\n */\nint SavedBattleGame::getSavedVIPs() const\n{\n\treturn _vipsSaved;\n}\n\n/**\n * Gets the saved VIPs total score.\n */\nint SavedBattleGame::getSavedVIPsScore() const\n{\n\treturn _vipsSavedScore;\n}\n\n/**\n * Increase the lost VIPs counter and score.\n */\nvoid SavedBattleGame::addLostVIP(int score)\n{\n\t_vipsLost++;\n\t_vipsLostScore -= score;\n}\n\n/**\n * Gets the lost VIPs counter.\n */\nint SavedBattleGame::getLostVIPs() const\n{\n\treturn _vipsLost;\n}\n\n/**\n * Gets the lost VIPs total score.\n */\nint SavedBattleGame::getLostVIPsScore() const\n{\n\treturn _vipsLostScore;\n}\n\n/**\n * Increase the waiting outside VIPs counter and score.\n */\nvoid SavedBattleGame::addWaitingOutsideVIP(int score)\n{\n\t_vipsWaitingOutside++;\n\t_vipsWaitingOutsideScore += score;\n}\n\n/**\n * Corrects the VIP stats based on the final mission outcome.\n */\nvoid SavedBattleGame::correctVIPStats(bool success, bool retreated)\n{\n\tif (success)\n\t{\n\t\t// if we won, all waiting VIPs are saved\n\t\t_vipsSaved += _vipsWaitingOutside;\n\t\t_vipsWaitingOutside = 0;\n\n\t\t_vipsSavedScore += _vipsWaitingOutsideScore;\n\t\t_vipsWaitingOutsideScore = 0;\n\t}\n\telse\n\t{\n\t\t// if we lost, all waiting VIPs are lost\n\t\t_vipsLost += _vipsWaitingOutside;\n\t\t_vipsWaitingOutside = 0;\n\n\t\t_vipsLostScore -= _vipsWaitingOutsideScore;\n\t\t_vipsWaitingOutsideScore = 0;\n\n\t\tif (retreated)\n\t\t{\n\t\t\t// if we retreated, keep all VIPs waiting in the craft alive\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// if nobody from xcom survived, all VIPs are lost too\n\t\t\t_vipsLost += _vipsSaved;\n\t\t\t_vipsSaved = 0;\n\n\t\t\t_vipsLostScore -= _vipsSavedScore;\n\t\t\t_vipsSavedScore = 0;\n\t\t}\n\t}\n}\n\n/**\n * Set the objective type for the current battle.\n * @param the objective type.\n */\nvoid SavedBattleGame::setObjectiveType(int type)\n{\n\t_objectiveType = type;\n}\n\n/**\n * Get the objective type for the current battle.\n * @return the objective type.\n */\nSpecialTileType SavedBattleGame::getObjectiveType() const\n{\n\treturn (SpecialTileType)(_objectiveType);\n}\n\n\n\n/**\n * Sets the ambient sound effect volume.\n * @param volume the ambient volume.\n */\nvoid SavedBattleGame::setAmbientVolume(double volume)\n{\n\t_ambientVolume = volume;\n}\n\n/**\n * Gets the ambient sound effect volume.\n * @return the ambient sound volume.\n */\ndouble SavedBattleGame::getAmbientVolume() const\n{\n\treturn _ambientVolume;\n}\n\n/**\n * Gets the maximum number of turns we have before this mission ends.\n * @return the turn limit.\n */\nint SavedBattleGame::getTurnLimit() const\n{\n\treturn _turnLimit;\n}\n\n/**\n * Gets the action type to perform when the timer expires.\n * @return the action type to perform.\n */\nChronoTrigger SavedBattleGame::getChronoTrigger() const\n{\n\treturn _chronoTrigger;\n}\n\n/**\n * Sets the turn limit for this mission.\n * @param limit the turn limit.\n */\nvoid SavedBattleGame::setTurnLimit(int limit)\n{\n\t_turnLimit = limit;\n}\n\n/**\n * Sets the action type to occur when the timer runs out.\n * @param trigger the action type to perform.\n */\nvoid SavedBattleGame::setChronoTrigger(ChronoTrigger trigger)\n{\n\t_chronoTrigger = trigger;\n}\n\n/**\n * Sets the turn at which the players become exposed to the AI.\n * @param turn the turn to start cheating.\n */\nvoid SavedBattleGame::setCheatTurn(int turn)\n{\n\t_cheatTurn = turn;\n}\n\nbool SavedBattleGame::isBeforeGame() const\n{\n\treturn _beforeGame;\n}\n\n/**\n * Randomly chooses hidden movement background.\n */\nvoid SavedBattleGame::setRandomHiddenMovementBackground(const Mod *mod)\n{\n\tif (mod && !mod->getHiddenMovementBackgrounds().empty())\n\t{\n\t\tint rng = RNG::seedless(0, mod->getHiddenMovementBackgrounds().size() - 1);\n\t\t_hiddenMovementBackground = mod->getHiddenMovementBackgrounds().at(rng);\n\t}\n\telse\n\t{\n\t\t_hiddenMovementBackground = \"TAC00.SCR\";\n\t}\n}\n\n/**\n * Gets the hidden movement background ID.\n * @return hidden movement background ID\n */\nconst std::string& SavedBattleGame::getHiddenMovementBackground() const\n{\n\treturn _hiddenMovementBackground;\n}\n\n/**\n * Appends a given entry to the hit log. Works only during the player's turn.\n */\nvoid SavedBattleGame::appendToHitLog(HitLogEntryType type, UnitFaction faction)\n{\n\tif (_side != FACTION_PLAYER) return;\n\t_hitLog->appendToHitLog(type, faction);\n}\n\n/**\n * Appends a given entry to the hit log. Works only during the player's turn.\n */\nvoid SavedBattleGame::appendToHitLog(HitLogEntryType type, UnitFaction faction, const std::string &text)\n{\n\tif (_side != FACTION_PLAYER) return;\n\t_hitLog->appendToHitLog(type, faction, text);\n}\n\n/**\n * Gets the hit log.\n * @return hit log\n */\nconst HitLog *SavedBattleGame::getHitLog() const\n{\n\treturn _hitLog;\n}\n\n/**\n * Resets all unit hit state flags.\n */\nvoid SavedBattleGame::resetUnitHitStates()\n{\n\tfor (auto* bu : _units)\n\t{\n\t\tbu->resetHitState();\n\t}\n}\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tScript binding\n////////////////////////////////////////////////////////////\n\nnamespace\n{\n\ntemplate<typename... Args>\nvoid flashMessageVariadicScriptImpl(SavedBattleGame* sbg, ScriptText message, Args... args)\n{\n\tif (!sbg || !sbg->getBattleState())\n\t{\n\t\treturn;\n\t}\n\tconst Language *lang = sbg->getBattleState()->getGame()->getLanguage();\n\tLocalizedText translated = lang->getString(message);\n\t(translated.arg(args), ...);\n\tsbg->getBattleState()->warningRaw(translated);\n}\n\ntemplate<typename... Args>\nvoid flashLongMessageVariadicScriptImpl(SavedBattleGame* sbg, ScriptText message, Args... args)\n{\n\tif (!sbg || !sbg->getBattleState())\n\t{\n\t\treturn;\n\t}\n\tconst Language *lang = sbg->getBattleState()->getGame()->getLanguage();\n\tLocalizedText translated = lang->getString(message);\n\t(translated.arg(args), ...);\n\tsbg->getBattleState()->warningLongRaw(translated);\n}\n\n\n\nvoid randomChanceScript(SavedBattleGame* sbg, int& val)\n{\n\tif (sbg)\n\t{\n\t\tval = RNG::percent(val);\n\t}\n\telse\n\t{\n\t\tval = 0;\n\t}\n}\n\nvoid randomRangeScript(SavedBattleGame* sbg, int& val, int min, int max)\n{\n\tif (sbg && max >= min)\n\t{\n\t\tval = RNG::generate(min, max);\n\t}\n\telse\n\t{\n\t\tval = 0;\n\t}\n}\n\nvoid difficultyLevelScript(const SavedBattleGame* sbg, int& val)\n{\n\tif (sbg)\n\t{\n\t\tval = sbg->getGeoscapeSave()->getDifficulty();\n\t}\n\telse\n\t{\n\t\tval = 0;\n\t}\n}\n\nvoid turnSideScript(const SavedBattleGame* sbg, int& val)\n{\n\tif (sbg)\n\t{\n\t\tval = sbg->getSide();\n\t}\n\telse\n\t{\n\t\tval = 0;\n\t}\n}\n\nvoid getGeoscapeSaveScript(const SavedBattleGame* sbg, const SavedGame*& val)\n{\n\tif (sbg)\n\t{\n\t\tval = sbg->getGeoscapeSave();\n\t}\n\telse\n\t{\n\t\tval = nullptr;\n\t}\n}\n\nvoid getGeoscapeSaveScript(SavedBattleGame* sbg, SavedGame*& val)\n{\n\tif (sbg)\n\t{\n\t\tval = sbg->getGeoscapeSave();\n\t}\n\telse\n\t{\n\t\tval = nullptr;\n\t}\n}\n\nvoid getTileScript(const SavedBattleGame* sbg, const Tile*& t, int x, int y, int z)\n{\n\tif (sbg)\n\t{\n\t\tt = sbg->getTile(Position(x, y, z));\n\t}\n\telse\n\t{\n\t\tt = nullptr;\n\t}\n}\n\nvoid getTileEditableScript(SavedBattleGame* sbg, Tile*& t, int x, int y, int z)\n{\n\tif (sbg)\n\t{\n\t\tt = sbg->getTile(Position(x, y, z));\n\t}\n\telse\n\t{\n\t\tt = nullptr;\n\t}\n}\n\n\nbool filterUnitScript(SavedBattleGame* sbg, BattleUnit* unit)\n{\n\treturn unit && !unit->isIgnored() && unit->getStatus() != STATUS_DEAD;\n}\n\nbool filterUnitFactionScript(SavedBattleGame* sbg, BattleUnit* unit, int i)\n{\n\treturn filterUnitScript(sbg, unit) && unit->getFaction() == i;\n}\n\n\nbool filterItemScript(SavedBattleGame* sbg, BattleItem* item)\n{\n\treturn item && !item->isOwnerIgnored();\n}\n\n\nvoid setAlienItemLevelScript(SavedBattleGame* sbg, int val)\n{\n\tif (sbg)\n\t{\n\t\tsbg->setAlienItemLevel(Clamp(val, 0, (int)sbg->getMod()->getAlienItemLevels().size()));\n\t}\n}\n\nvoid setReinforcementsItemLevelScript(SavedBattleGame* sbg, int val)\n{\n\tif (sbg)\n\t{\n\t\tsbg->setReinforcementsItemLevel(Clamp(val, 0, (int)sbg->getMod()->getAlienItemLevels().size()));\n\t}\n}\n\nvoid tryConcealUnitScript(SavedBattleGame* sbg, BattleUnit* bu, int& val)\n{\n\tif (sbg && bu)\n\t{\n\t\tval = sbg->getTileEngine()->tryConcealUnit(bu);\n\t}\n\telse\n\t{\n\t\tval = 0;\n\t}\n}\n\nvoid isAltPressedScript(const SavedBattleGame* sbg, int& val)\n{\n\tif (sbg)\n\t{\n\t\tval = sbg->isAltPressed(true);\n\t}\n\telse\n\t{\n\t\tval = 0;\n\t}\n}\n\nvoid isCtrlPressedScript(const SavedBattleGame* sbg, int& val)\n{\n\tif (sbg)\n\t{\n\t\tval = sbg->isCtrlPressed(true);\n\t}\n\telse\n\t{\n\t\tval = 0;\n\t}\n}\n\nvoid isShiftPressedScript(const SavedBattleGame* sbg, int& val)\n{\n\tif (sbg)\n\t{\n\t\tval = sbg->isShiftPressed(true);\n\t}\n\telse\n\t{\n\t\tval = 0;\n\t}\n}\n\nvoid getSelectedUnitScript(const SavedBattleGame* sbg, const BattleUnit*& val)\n{\n\tif (sbg)\n\t{\n\t\tval = sbg->getSelectedUnit();\n\t}\n\telse\n\t{\n\t\tval = nullptr;\n\t}\n}\n\n\n\nstd::string debugDisplayScript(const SavedBattleGame* p)\n{\n\tif (p)\n\t{\n\t\tstd::string s;\n\t\ts += \"BattleGame\";\n\t\ts += \"(missionType: \\\"\";\n\t\ts += p->getMissionType();\n\t\ts += \"\\\" missionTarget: \\\"\";\n\t\ts += p->getMissionTarget();\n\t\ts += \"\\\" turn: \";\n\t\ts += std::to_string(p->getTurn());\n\t\ts += \")\";\n\t\treturn s;\n\t}\n\telse\n\t{\n\t\treturn \"null\";\n\t}\n}\n\n} // namespace\n\n/**\n * Register Armor in script parser.\n * @param parser Script parser.\n */\nvoid SavedBattleGame::ScriptRegister(ScriptParserBase* parser)\n{\n\tparser->registerPointerType<SavedGame>();\n\tparser->registerPointerType<Tile>();\n\n\tBind<SavedBattleGame> sbg = { parser };\n\n\tsbg.add<&SavedBattleGame::getTurn>(\"getTurn\", \"Current turn, 0 - before battle, 1 - first turn, each stage reset this value.\");\n\tsbg.add<&SavedBattleGame::getAnimFrame>(\"getAnimFrame\");\n\tsbg.add<&SavedBattleGame::getMapSizeX>(\"getSize.getX\", \"Get size in x direction\");\n\tsbg.add<&SavedBattleGame::getMapSizeY>(\"getSize.getY\", \"Get size in y direction\");\n\tsbg.add<&SavedBattleGame::getMapSizeZ>(\"getSize.getZ\", \"Get size in z direction\");\n\tsbg.add<&getTileScript>(\"getTile\", \"Get tile on position x, y, z\");\n\tsbg.add<&getTileEditableScript>(\"getTile\", \"Get tile on position x, y, z\");\n\tsbg.addList<&filterUnitScript, &SavedBattleGame::_units>(\"getUnits\", \"Get list of all units\");\n\tsbg.addList<&filterUnitFactionScript, &SavedBattleGame::_units>(\"getUnits.byFaction\", \"Get list of units from faction\");\n\tsbg.addList<&filterItemScript, &SavedBattleGame::_items>(\"getItems\", \"Get list of all items\");\n\n\tsbg.add<&SavedBattleGame::getAlienItemLevel>(\"getAlienItemLevel\");\n\tsbg.add<&setAlienItemLevelScript>(\"setAlienItemLevel\");\n\tsbg.add<&SavedBattleGame::getReinforcementsItemLevel>(\"getReinforcementsItemLevel\");\n\tsbg.add<&setReinforcementsItemLevelScript>(\"setReinforcementsItemLevel\");\n\n\tsbg.addPair<SavedGame, &getGeoscapeSaveScript, &getGeoscapeSaveScript>(\"getGeoscapeGame\");\n\n\tsbg.add<void(*)(SavedBattleGame*, ScriptText), &flashMessageVariadicScriptImpl>(\"flashMessage\");\n\tsbg.add<void(*)(SavedBattleGame*, ScriptText, int), &flashMessageVariadicScriptImpl>(\"flashMessage\");\n\tsbg.add<void(*)(SavedBattleGame*, ScriptText, int, int), &flashMessageVariadicScriptImpl>(\"flashMessage\");\n\tsbg.add<void(*)(SavedBattleGame*, ScriptText, int, int, int), &flashMessageVariadicScriptImpl>(\"flashMessage\");\n\tsbg.add<void(*)(SavedBattleGame*, ScriptText, int, int, int, int), &flashMessageVariadicScriptImpl>(\"flashMessage\");\n\n\tsbg.add<void(*)(SavedBattleGame*, ScriptText), &flashLongMessageVariadicScriptImpl>(\"flashLongMessage\");\n\tsbg.add<void(*)(SavedBattleGame*, ScriptText, int), &flashLongMessageVariadicScriptImpl>(\"flashLongMessage\");\n\tsbg.add<void(*)(SavedBattleGame*, ScriptText, int, int), &flashLongMessageVariadicScriptImpl>(\"flashLongMessage\");\n\tsbg.add<void(*)(SavedBattleGame*, ScriptText, int, int, int), &flashLongMessageVariadicScriptImpl>(\"flashLongMessage\");\n\tsbg.add<void(*)(SavedBattleGame*, ScriptText, int, int, int, int), &flashLongMessageVariadicScriptImpl>(\"flashLongMessage\");\n\n\tsbg.add<&randomChanceScript>(\"randomChance\", \"first argument is percent in range 0 - 100, then return in that argument random 1 or 0 based on percent\");\n\tsbg.add<&randomRangeScript>(\"randomRange\", \"set in first argument random value from range given in two last arguments\");\n\n\tsbg.add<&turnSideScript>(\"getTurnSide\", \"Return the faction whose turn it is.\");\n\tsbg.add<&SavedBattleGame::getDepth>(\"getDepth\", \"Return the depth of the battlescape.\");\n\tsbg.add<&SavedBattleGame::getGlobalShade>(\"getGlobalShade\", \"Return the global shade of the battlescape.\");\n\n\tsbg.addCustomConst(\"FACTION_PLAYER\", FACTION_PLAYER);\n\tsbg.addCustomConst(\"FACTION_HOSTILE\", FACTION_HOSTILE);\n\tsbg.addCustomConst(\"FACTION_NEUTRAL\", FACTION_NEUTRAL);\n\n\tsbg.add<&tryConcealUnitScript>(\"tryConcealUnit\");\n\n\tsbg.add<&difficultyLevelScript>(\"difficultyLevel\");\n\n\tsbg.addScriptValue<&SavedBattleGame::_scriptValues>();\n\n\tsbg.addDebugDisplay<&debugDisplayScript>();\n\n\tsbg.addCustomConst(\"DIFF_BEGINNER\", DIFF_BEGINNER);\n\tsbg.addCustomConst(\"DIFF_EXPERIENCED\", DIFF_EXPERIENCED);\n\tsbg.addCustomConst(\"DIFF_VETERAN\", DIFF_VETERAN);\n\tsbg.addCustomConst(\"DIFF_GENIUS\", DIFF_GENIUS);\n\tsbg.addCustomConst(\"DIFF_SUPERHUMAN\", DIFF_SUPERHUMAN);\n}\n\n/**\n * Register useful function used by graphic scripts.\n */\nvoid SavedBattleGame::ScriptRegisterUnitAnimations(ScriptParserBase* parser)\n{\n\tBind<SavedBattleGame> sbg = { parser, BindBase::ExtensionBinding{} };\n\n\tsbg.add<&isAltPressedScript>(\"isAltPressed\");\n\tsbg.add<&isCtrlPressedScript>(\"isCtrlPressed\");\n\tsbg.add<&isShiftPressedScript>(\"isShiftPressed\");\n\tsbg.addField<&SavedBattleGame::_toggleBrightnessTemp>(\"getDebugVisionMode\");\n\tsbg.addField<&SavedBattleGame::_toggleNightVisionTemp>(\"isNightVisionEnabled\");\n\tsbg.addField<&SavedBattleGame::_togglePersonalLightTemp>(\"isPersonalLightEnabled\");\n\tsbg.addField<&SavedBattleGame::_toggleNightVisionColorTemp>(\"getNightVisionColor\");\n\tsbg.add<&getSelectedUnitScript>(\"getSelectedUnit\");\n}\n\n}\n"
  },
  {
    "path": "src/Savegame/SavedBattleGame.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <vector>\n#include <string>\n#include <list>\n#include \"../Engine/Yaml.h\"\n#include \"Tile.h\"\n#include \"../Mod/AlienDeployment.h\"\n#include \"../Mod/RuleCraft.h\"\n\nnamespace OpenXcom\n{\n\nclass Tile;\nclass SavedGame;\nclass MapDataSet;\nclass Node;\nclass BattlescapeState;\nclass BattlescapeGame;\nclass Position;\nclass Pathfinding;\nclass TileEngine;\nclass RuleStartingCondition;\nclass RuleEnviroEffects;\nclass BattleItem;\nclass BattleUnit;\nclass Mod;\nclass State;\nclass ItemContainer;\nclass Craft;\nclass RuleItem;\nclass HitLog;\nenum HitLogEntryType : int;\nstruct BattlescapeTally;\n\n/**\n * The battlescape data that gets written to disk when the game is saved.\n * A saved game holds all the variable info in a game like mapdata,\n * soldiers, items, etc.\n */\nclass SavedBattleGame\n{\npublic:\n\t/// Name of class used in script.\n\tstatic constexpr const char *ScriptName = \"BattleGame\";\n\t/// Register all useful function used by script.\n\tstatic void ScriptRegister(ScriptParserBase* parser);\n\t/// Register useful function used by graphic scripts.\n\tstatic void ScriptRegisterUnitAnimations(ScriptParserBase* parser);\n\nprivate:\n\tbool _isPreview;\n\tSDL_Rect _craftPos;\n\tint _craftZ;\n\tCraft* _craftForPreview;\n\tstd::vector<Position> _craftTiles;\n\tBattlescapeState *_battleState;\n\tMod *_rule;\n\tint _mapsize_x, _mapsize_y, _mapsize_z;\n\tstd::vector<MapDataSet*> _mapDataSets;\n\tstd::vector<Tile> _tiles;\n\tBattleUnit *_selectedUnit, *_undoUnit, *_lastSelectedUnit;\n\tstd::vector<Node*> _nodes;\n\tstd::vector<BattleUnit*> _units;\n\tstd::vector<BattleItem*> _items, _deleted;\n\tPathfinding *_pathfinding;\n\tTileEngine *_tileEngine;\n\tstd::string _missionType, _strTarget, _strCraftOrBase, _alienCustomDeploy, _alienCustomMission;\n\tstd::string _lastUsedMapScript;\n\tint _alienItemLevel = 0;\n\tstd::string _reinforcementsDeployment, _reinforcementsRace;\n\tint _reinforcementsItemLevel;\n\tstd::map<std::string, int> _reinforcementsMemory;\n\tstd::vector< std::vector<int> > _reinforcementsBlocks;\n\tstd::vector< std::vector<std::string> > _flattenedMapTerrainNames;\n\tstd::vector< std::vector<std::string> > _flattenedMapBlockNames;\n\tconst RuleStartingCondition *_startingCondition;\n\tconst RuleEnviroEffects *_enviroEffects;\n\tbool _ecEnabledFriendly, _ecEnabledHostile, _ecEnabledNeutral;\n\tint _globalShade;\n\tUnitFaction _side;\n\tint _turn, _bughuntMinTurn;\n\tint _animFrame;\n\tbool _nameDisplay;\n\tbool _debugMode, _bughuntMode;\n\tbool _aborted;\n\tbool _baseCraftInventory = false;\n\tint _itemId;\n\tEscapeType _vipEscapeType;\n\tint _vipSurvivalPercentage, _vipsSaved, _vipsLost, _vipsWaitingOutside, _vipsSavedScore, _vipsLostScore, _vipsWaitingOutsideScore;\n\tint _objectiveType, _objectivesDestroyed, _objectivesNeeded;\n\tstd::vector<BattleUnit*> _exposedUnits;\n\tstd::list<BattleUnit*> _fallingUnits;\n\tbool _unitsFalling, _cheating;\n\tstd::vector<Position> _tileSearch, _storageSpace;\n\tBattleActionType _tuReserved;\n\tbool _kneelReserved;\n\tstd::vector< std::vector<std::pair<int, int> > > _baseModules;\n\tItemContainer *_baseItems;\n\tint _depth, _ambience;\n\tdouble _ambientVolume;\n\tstd::vector<int> _ambienceRandom;\n\tint _minAmbienceRandomDelay, _maxAmbienceRandomDelay, _currentAmbienceDelay;\n\tstd::vector<BattleItem*> _recoverGuaranteed, _recoverConditional;\n\tstd::string _music;\n\tint _turnLimit, _cheatTurn;\n\tChronoTrigger _chronoTrigger;\n\tbool _beforeGame;\n\tbool _togglePersonalLight, _toggleNightVision;\n\tint _toggleBrightness;\n\tbool _togglePersonalLightTemp = false, _toggleNightVisionTemp = false;\n\tint _toggleBrightnessTemp = 0, _toggleNightVisionColorTemp = 0;\n\tstd::string _hiddenMovementBackground;\n\tHitLog *_hitLog;\n\tScriptValues<SavedBattleGame> _scriptValues;\n\t/// Selects a soldier.\n\tBattleUnit *selectPlayerUnit(int dir, bool checkReselect = false, bool setReselect = false, bool checkInventory = false);\n\t/// Run newTurnUnit and newTurnItem scripts\n\tvoid newTurnUpdateScripts();\npublic:\n\t/// Creates a new battle save, based on the current generic save.\n\tSavedBattleGame(Mod *rule, Language *lang, bool isPreview = false);\n\t/// Cleans up the saved game.\n\t~SavedBattleGame();\n\t/// Loads a saved battle game from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader, Mod *mod, SavedGame* savedGame);\n\t/// Saves a saved battle game to YAML.\n\tvoid save(YAML::YamlNodeWriter writer) const;\n\t/// Sets the dimensions of the map and initializes it.\n\tvoid initMap(int mapsize_x, int mapsize_y, int mapsize_z, bool resetTerrain = true);\n\t/// Initialises the pathfinding and tile engine.\n\tvoid initUtilities(Mod *mod, bool craftInventory = false);\n\t/// Gets if this is craft pre-equip phase in base view.\n\tbool isBaseCraftInventory();\n\t/// Gets the game's mapdata files.\n\tstd::vector<MapDataSet*> *getMapDataSets();\n\t/// Sets the mission type.\n\tvoid setMissionType(const std::string &missionType);\n\t/// Gets the mission type.\n\tconst std::string &getMissionType() const;\n\t/// Sets the mission target.\n\tvoid setMissionTarget(const std::string& missionTarget) { _strTarget = missionTarget; }\n\t/// Gets the mission target.\n\tconst std::string& getMissionTarget() const { return _strTarget; }\n\t/// Sets the mission craft/base.\n\tvoid setMissionCraftOrBase(const std::string& missionCraftOrBase) { _strCraftOrBase = missionCraftOrBase; }\n\t/// Gets the mission craft/base.\n\tconst std::string& getMissionCraftOrBase() const { return _strCraftOrBase; }\n\t/// Gets the base's items BEFORE the mission.\n\tItemContainer *getBaseStorageItems();\n\t/// Sets the starting conditions.\n\tvoid setStartingCondition(const RuleStartingCondition* sc) { _startingCondition = sc; }\n\t/// Gets the starting conditions.\n\tconst RuleStartingCondition* getStartingCondition() const { return _startingCondition; }\n\t/// Applies the enviro effects.\n\tvoid applyEnviroEffects(const RuleEnviroEffects* enviroEffects);\n\t/// Gets the enviro effects.\n\tconst RuleEnviroEffects* getEnviroEffects() const;\n\t/// Are environmental conditions (for a given faction) enabled?\n\tbool getEnvironmentalConditionsEnabled(UnitFaction faction) const;\n\t/// Sets the custom alien data.\n\tvoid setAlienCustom(const std::string &deploy, const std::string &mission);\n\t/// Gets the custom alien deploy.\n\tconst std::string &getAlienCustomDeploy() const;\n\t/// Gets the custom mission definition.\n\tconst std::string &getAlienCustomMission() const;\n\t/// Sets the last used map script.\n\tvoid setLastUsedMapScript(const std::string& lastUsedMapScript) { _lastUsedMapScript = lastUsedMapScript; }\n\t/// Gets the last used map script.\n\tconst std::string& getLastUsedMapScript() const { return _lastUsedMapScript; }\n\n\t/// Sets the alien item level.\n\tvoid setAlienItemLevel(int itemLevel) { _alienItemLevel = itemLevel; }\n\t/// Gets the alien item level.\n\tint getAlienItemLevel() const { return _alienItemLevel; }\n\n\t/// Sets the alien deployment to use for reinforcements.\n\tvoid setReinforcementsDeployment(const std::string &reinforcementsDeployment) { _reinforcementsDeployment = reinforcementsDeployment; }\n\t/// Gets the alien deployment to use for reinforcements.\n\tconst std::string &getReinforcementsDeployment() const { return _reinforcementsDeployment; }\n\t/// Sets the alien race to use for reinforcements.\n\tvoid setReinforcementsRace(const std::string &reinforcementsRace) { _reinforcementsRace = reinforcementsRace; }\n\t/// Gets the alien race to use for reinforcements.\n\tconst std::string &getReinforcementsRace() const { return _reinforcementsRace; }\n\t/// Sets the alien item level to use for reinforcements.\n\tvoid setReinforcementsItemLevel(int reinforcementsItemLevel) { _reinforcementsItemLevel = reinforcementsItemLevel; }\n\t/// Gets the alien item level to use for reinforcements.\n\tint getReinforcementsItemLevel() const { return _reinforcementsItemLevel; }\n\t/// Gets the memory used for reinforcements.\n\tstd::map<std::string, int> &getReinforcementsMemory() { return _reinforcementsMemory; }\n\t/// Gets the map blocks used for reinforcements.\n\tstd::vector< std::vector<int> > &getReinforcementsBlocks() { return _reinforcementsBlocks; }\n\n\t/// Gets the flattened map block terrain names (or craft/ufo names) generated by the BattlescapeGenerator.\n\tstd::vector< std::vector<std::string> > &getFlattenedMapTerrainNames() { return _flattenedMapTerrainNames; }\n\t/// Gets the flattened map block names generated by the BattlescapeGenerator.\n\tstd::vector< std::vector<std::string> > &getFlattenedMapBlockNames() { return _flattenedMapBlockNames; }\n\n\t/// Sets the global shade.\n\tvoid setGlobalShade(int shade);\n\t/// Gets the global shade.\n\tint getGlobalShade() const;\n\t/// Gets a pointer to the list of nodes.\n\tstd::vector<Node*> *getNodes();\n\t/// Gets a pointer to the list of items.\n\tstd::vector<BattleItem*> *getItems();\n\t/// Gets a pointer to the list of units.\n\tstd::vector<BattleUnit*> *getUnits();\n\t/// Gets terrain size x.\n\tint getMapSizeX() const { return _mapsize_x; }\n\t/// Gets terrain size y.\n\tint getMapSizeY() const { return _mapsize_y; }\n\t/// Gets terrain size z.\n\tint getMapSizeZ() const { return _mapsize_z; }\n\t/// Gets terrain x*y*z\n\tint getMapSizeXYZ() const { return _mapsize_x * _mapsize_y * _mapsize_z; }\n\n\t/// Is this just a craft or base deployment preview?\n\tbool isPreview() const { return _isPreview; }\n\t/// Sets craft position.\n\tvoid setCraftPos(SDL_Rect craftPos) { _craftPos = craftPos; }\n\t/// Sets craft elevation.\n\tvoid setCraftZ(int craftZ) { _craftZ = craftZ; }\n\t/// Sets craft for preview.\n\tvoid setCraftForPreview(Craft* craftForPreview) { _craftForPreview = craftForPreview; }\n\t/// Gets craft for preview.\n\tconst Craft* getCraftForPreview() const { return _craftForPreview; }\n\t/// Pre-calculate all valid tiles for later use in map drawing.\n\tvoid calculateCraftTiles();\n\t/// Gets craft tiles.\n\tconst std::vector<Position>& getCraftTiles() const { return _craftTiles; }\n\n\t/**\n\t * Converts coordinates into a unique index.\n\t * getTile() calls this every time, so should be inlined along with it.\n\t * @param pos The position to convert.\n\t * @return A unique index.\n\t */\n\tinline int getTileIndex(Position pos) const\n\t{\n\t\treturn pos.z * _mapsize_y * _mapsize_x + pos.y * _mapsize_x + pos.x;\n\t}\n\n\t/// Converts a tile index to its coordinates.\n\tPosition getTileCoords(int index) const;\n\n\t/**\n\t * Gets the Tile at a given position on the map.\n\t * This method is called over 50mil+ times per turn so it seems useful\n\t * to inline it.\n\t * @param pos Map position.\n\t * @return Pointer to the tile at that position.\n\t */\n\tinline Tile *getTile(Position pos)\n\t{\n\t\tif (pos.x < 0 || pos.y < 0 || pos.z < 0\n\t\t\t|| pos.x >= _mapsize_x || pos.y >= _mapsize_y || pos.z >= _mapsize_z)\n\t\t\treturn 0;\n\n\t\treturn &_tiles[getTileIndex(pos)];\n\t}\n\n\t/**\n\t * Gets the Tile at a given position on the map.\n\t * This method is called over 50mil+ times per turn so it seems useful\n\t * to inline it.\n\t * @param pos Map position.\n\t * @return Pointer to the tile at that position.\n\t */\n\tinline const Tile *getTile(Position pos) const\n\t{\n\t\tif (pos.x < 0 || pos.y < 0 || pos.z < 0\n\t\t\t|| pos.x >= _mapsize_x || pos.y >= _mapsize_y || pos.z >= _mapsize_z)\n\t\t\treturn 0;\n\n\t\treturn &_tiles[getTileIndex(pos)];\n\t}\n\n\t/*\n\t * Gets a pointer to the tiles, a tile is the smallest component of battlescape.\n\t * @param pos Index position, less than `getMapSizeXYZ()`.\n\t * @return Pointer to the tile at that index.\n\t */\n\tTile* getTile(int i)\n\t{\n\t\treturn &_tiles[i];\n\t}\n\n\t/**\n\t * Get tile that is below current one (const version).\n\t * @param tile\n\t * @return Tile below\n\t */\n\tinline const Tile *getBelowTile(const Tile* tile) const\n\t{\n\t\tif (!tile || tile->getPosition().z == 0)\n\t\t{\n\t\t\treturn nullptr;\n\t\t}\n\t\t// difference of pointers between layers is equal `_mapsize_y * _mapsize_x`\n\t\t// when we subtract this value from valid tile we get valid tile from lower layer.\n\t\treturn tile - _mapsize_y * _mapsize_x;\n\t}\n\n\t/**\n\t * Get tile that is below current one.\n\t * @param tile\n\t * @return Tile below\n\t */\n\tinline Tile *getBelowTile(Tile* tile)\n\t{\n\t\tif (!tile || tile->getPosition().z == 0)\n\t\t{\n\t\t\treturn nullptr;\n\t\t}\n\t\t// difference of pointers between layers is equal `_mapsize_y * _mapsize_x`\n\t\t// when we subtract this value from valid tile we get valid tile from lower layer.\n\t\treturn tile - _mapsize_y * _mapsize_x;\n\t}\n\n\t/**\n\t * Get tile that is over current one (const version).\n\t * @param tile\n\t * @return Tile over\n\t */\n\tinline const Tile *getAboveTile(const Tile* tile) const\n\t{\n\t\tif (!tile || tile->getPosition().z == _mapsize_z - 1)\n\t\t{\n\t\t\treturn nullptr;\n\t\t}\n\t\t// difference of pointers between layers is equal `_mapsize_y * _mapsize_x`\n\t\t// when we add this value from valid tile we get valid tile from upper layer.\n\t\treturn tile + _mapsize_y * _mapsize_x;\n\t}\n\n\t/**\n\t * Get tile that is over current one.\n\t * @param tile\n\t * @return Tile over\n\t */\n\tinline Tile *getAboveTile(Tile* tile)\n\t{\n\t\tif (!tile || tile->getPosition().z == _mapsize_z - 1)\n\t\t{\n\t\t\treturn nullptr;\n\t\t}\n\t\t// difference of pointers between layers is equal `_mapsize_y * _mapsize_x`\n\t\t// when we add this value from valid tile we get valid tile from upper layer.\n\t\treturn tile + _mapsize_y * _mapsize_x;\n\t}\n\n\t/// Gets the currently selected unit.\n\tBattleUnit *getSelectedUnit();\n\t/// Gets the currently selected unit.\n\tconst BattleUnit *getSelectedUnit() const;\n\t/// Sets the currently selected unit.\n\tvoid setSelectedUnit(BattleUnit *unit);\n\t/// Gets the \"undo\" unit.\n\tBattleUnit* getUndoUnit() const { return _undoUnit; }\n\t/// Sets the \"undo\" unit.\n\tvoid setUndoUnit(BattleUnit* unit) { _undoUnit = unit; }\n\t/// Clear state that given unit is selected.\n\tvoid clearUnitSelection(BattleUnit *unit);\n\t/// Selects the previous soldier.\n\tBattleUnit *selectPreviousPlayerUnit(bool checkReselect = false, bool setReselect = false, bool checkInventory = false);\n\t/// Selects the next soldier.\n\tBattleUnit *selectNextPlayerUnit(bool checkReselect = false, bool setReselect = false, bool checkInventory = false);\n\tBattleUnit *selectNextPlayerUnitByDistance(bool checkReselect = false, bool setReselect = false, bool checkInventory = false);\n\t/// Selects the unit with position on map.\n\tBattleUnit *selectUnit(Position pos);\n\t/// Gets the pathfinding object.\n\tPathfinding *getPathfinding() const;\n\t/// Gets a pointer to the tile engine.\n\tTileEngine *getTileEngine() const;\n\t/// Gets the playing side.\n\tUnitFaction getSide() const;\n\t/// Can unit use that weapon?\n\tbool canUseWeapon(const BattleItem *weapon, const BattleUnit *unit, bool isBerserking, BattleActionType actionType, std::string* message = nullptr) const;\n\t/// Gets the turn number.\n\tint getTurn() const;\n\t/// Sets the bug hunt turn number.\n\tvoid setBughuntMinTurn(int bughuntMinTurn);\n\t/// Gets the bug hunt turn number.\n\tint getBughuntMinTurn() const;\n\t/// Start first turn of battle.\n\tvoid startFirstTurn();\n\t/// Check count of units in different state for craft deployment preview.\n\tBattlescapeTally tallyUnitsForPreview();\n\t/// Saves the custom craft deployment.\n\tvoid saveCustomCraftDeployment();\n\t/// Saves the custom RuleCraft deployment. Invalidates corresponding custom craft deployments.\n\tvoid saveDummyCraftDeployment();\n\t/// Does the given craft type have a custom deployment?\n\tbool hasCustomDeployment(const RuleCraft* rule) const;\n\t/// Gets a custom deployment for the given craft type.\n\tconst RuleCraftDeployment& getCustomDeployment(const RuleCraft* rule) const;\n\t/// Ends the turn.\n\tvoid endTurn();\n\t/// Gets animation frame.\n\tint getAnimFrame() const;\n\t/// Increase animation frame.\n\tvoid nextAnimFrame();\n\t/// Sets debug mode.\n\tvoid setDebugMode();\n\tvoid revealMap();\n\t/// Gets debug mode.\n\tbool getDebugMode() const;\n\t/// Sets bug hunt mode.\n\tvoid setBughuntMode(bool bughuntMode);\n\t/// Gets bug hunt mode.\n\tbool getBughuntMode() const;\n\t/// Load map resources.\n\tvoid loadMapResources(Mod *mod);\n\t/// Resets tiles units are standing on\n\tvoid resetUnitTiles();\n\t/// Add item to delete list.\n\tvoid deleteList(BattleItem *item);\n\t/// Removes an item from the game.\n\tvoid removeItem(BattleItem *item);\n\n\t/// Add buildIn weapon from list to unit.\n\tvoid addFixedItems(BattleUnit *unit, const std::vector<const RuleItem*> &fixed);\n\t/// Init new created unit.\n\tvoid initUnit(BattleUnit *unit, size_t itemLevel = 0);\n\t/// Init new created item.\n\tvoid initItem(BattleItem *item, BattleUnit *unit = nullptr);\n\t/// Create new item for unit.\n\tBattleItem *createItemForUnit(const RuleItem *rule, BattleUnit *unit, bool fixedWeapon = false);\n\t/// Create new special built-in item for unit.\n\tBattleItem *createItemForUnitSpecialBuiltin(const RuleItem *rule, BattleUnit *unit);\n\t/// Create new item for tile.\n\tBattleItem *createItemForTile(const RuleItem *rule, Tile *tile, BattleUnit *corpseFor = nullptr);\n\t/// Create new item for tile.\n\tBattleItem *createItemForTile(const std::string& type, Tile *tile);\n\t/// Create new temporary item.\n\tBattleItem *createTempItem(const RuleItem *rule);\n\t/// Create new temporary unit.\n\tBattleUnit *createTempUnit(const Unit *rules, UnitFaction faction, int nextUnitId = -1);\n\t/// Converts a unit into a unit of another type.\n\tBattleUnit *convertUnit(BattleUnit *unit);\n\n\t/// Sets whether the mission was aborted.\n\tvoid setAborted(bool flag);\n\t/// Checks if the mission was aborted.\n\tbool isAborted() const;\n\t/// Sets how many objectives need to be destroyed.\n\tvoid setObjectiveCount(int counter);\n\t/// increments the objective counter.\n\tvoid addDestroyedObjective();\n\t/// Checks if all the objectives are destroyed.\n\tbool allObjectivesDestroyed() const;\n\t/// Gets the current item ID.\n\tint *getCurrentItemId();\n\t/// Gets a spawn node.\n\tNode *getSpawnNode(int nodeRank, BattleUnit *unit);\n\t/// Gets a patrol node.\n\tNode *getPatrolNode(bool scout, BattleUnit *unit, Node *fromNode);\n\t/// Carries out new turn preparations.\n\tvoid prepareNewTurn();\n\t/// Revives unconscious units (health check).\n\tvoid reviveUnconsciousUnits(bool noTU = false);\n\t/// Removes the body item that corresponds to the unit.\n\tvoid removeUnconsciousBodyItem(BattleUnit *bu);\n\t/// Sets or tries to set a unit of a certain size on a certain position of the map.\n\tbool setUnitPosition(BattleUnit *bu, Position position, bool testOnly = false);\n\t/// Adds this unit to the vector of falling units.\n\tbool addFallingUnit(BattleUnit* unit);\n\t/// Gets the vector of falling units.\n\tstd::list<BattleUnit*> *getFallingUnits();\n\t/// Toggles the switch that says \"there are units falling, start the fall state\".\n\tvoid setUnitsFalling(bool fall);\n\t/// Checks the status of the switch that says \"there are units falling\".\n\tbool getUnitsFalling() const;\n\t/// Gets a pointer to the BattlescapeState.\n\tBattlescapeState *getBattleState();\n\t/// Gets a pointer to the BattlescapeState.\n\tconst BattlescapeState *getBattleState() const;\n\t/// Gets a pointer to the BattlescapeGame.\n\tBattlescapeGame *getBattleGame();\n\t/// Gets a pointer to the BattlescapeGame.\n\tconst BattlescapeGame *getBattleGame() const;\n\t/// Is BattlescapeState busy?\n\tbool isBattlescapeStateBusy() const;\n\t/// Sets the pointer to the BattlescapeState.\n\tvoid setBattleState(BattlescapeState *bs);\n\n\t/// Is CTRL pressed?\n\tbool isCtrlPressed(bool considerTouchButtons = false) const;\n\t/// Is ALT pressed?\n\tbool isAltPressed(bool considerTouchButtons = false) const;\n\t/// Is SHIFT pressed?\n\tbool isShiftPressed(bool considerTouchButtons = false) const;\n\n\t/// Gets the highest ranked, living XCom unit.\n\tBattleUnit* getHighestRankedXCom();\n\t/// Gets the morale modifier for the unit passed to this function.\n\tint getUnitMoraleModifier(BattleUnit* unit);\n\t/// Gets the morale loss modifier (by unit type) of the killed unit.\n\tint getMoraleLossModifierWhenKilled(BattleUnit* unit);\n\t/// Gets the morale modifier for Aliens based on they number or XCom based on the highest ranked soldier.\n\tint getFactionMoraleModifier(bool player);\n\t/// Checks whether a particular faction has eyes on *unit (whether any unit on that faction sees *unit).\n\tbool eyesOnTarget(UnitFaction faction, BattleUnit* unit);\n\t/// Attempts to place a unit on or near entryPoint.\n\tbool placeUnitNearPosition(BattleUnit *unit, const Position& entryPoint, bool largeFriend);\n\t/// Resets the turn counter.\n\tvoid resetTurnCounter();\n\t/// Resets the visibility of all tiles on the map.\n\tvoid resetTiles();\n\t/// get an 11x11 grid of positions (-10 to +10) to check.\n\tconst std::vector<Position> &getTileSearch() const;\n\t/// check if the names or the callsigns of the soldiers should be displayed\n\tbool isNameDisplay() const;\n\t/// set displaying the name (true) or the callsign (false)\n\tvoid setNameDisplay(bool displayName);\n\t/// check if the AI has engaged cheat mode.\n\tbool isCheating() const;\n\t/// get the reserved fire mode.\n\tBattleActionType getTUReserved() const;\n\t/// set the reserved fire mode.\n\tvoid setTUReserved(BattleActionType reserved);\n\t/// get whether we are reserving TUs to kneel.\n\tbool getKneelReserved() const;\n\t/// set whether we are reserving TUs to kneel.\n\tvoid setKneelReserved(bool reserved);\n\t/// give me access to the storage tiles vector.\n\tstd::vector<Position> &getStorageSpace();\n\t/// move all the leftover items to random locations in the storage tiles vector.\n\tvoid randomizeItemLocations(Tile *t);\n\t/// get a reference to the baseModules map.\n\tstd::vector< std::vector<std::pair<int, int> > > &getModuleMap();\n\t/// calculate the number of map modules remaining\n\tvoid calculateModuleMap();\n\t/// a shortcut to the geoscape save.\n\tSavedGame *getGeoscapeSave() const;\n\t/// get the depth of the battlescape game.\n\tint getDepth() const;\n\t/// set the depth of the battlescape game.\n\tvoid setDepth(int depth);\n\t/// uses the depth variable to set a palette.\n\tvoid setPaletteByDepth(State *state);\n\t/// sets the ambient sound effect;\n\tvoid setAmbientSound(int sound);\n\t/// gets the ambient sound effect;\n\tint getAmbientSound() const;\n\t/// Gets/sets the random ambient sound effects.\n\tconst std::vector<int> &getAmbienceRandom() const { return _ambienceRandom; };\n\tvoid setAmbienceRandom(const std::vector<int> &ambienceRandom) { _ambienceRandom = ambienceRandom; }\n\t/// Gets/sets the minimum delay for the random ambient sound effect.\n\tint getMinAmbienceRandomDelay() const { return _minAmbienceRandomDelay; }\n\tvoid setMinAmbienceRandomDelay(int minAmbienceRandomDelay) { _minAmbienceRandomDelay = minAmbienceRandomDelay; }\n\t/// Gets/sets the maximum delay for the random ambient sound effect.\n\tint getMaxAmbienceRandomDelay() const { return _maxAmbienceRandomDelay; }\n\tvoid setMaxAmbienceRandomDelay(int maxAmbienceRandomDelay) { _maxAmbienceRandomDelay = maxAmbienceRandomDelay; }\n\t/// Gets/sets the current delay for the random ambient sound effect.\n\tint getCurrentAmbienceDelay() const { return _currentAmbienceDelay; }\n\tvoid setCurrentAmbienceDelay(int currentAmbienceDelay) { _currentAmbienceDelay = currentAmbienceDelay; }\n\tvoid decreaseCurrentAmbienceDelay() { _currentAmbienceDelay--; }\n\t/// Reset the current random ambient sound delay.\n\tvoid resetCurrentAmbienceDelay();\n\t/// Play a random ambient sound.\n\tvoid playRandomAmbientSound();\n\t/// Gets ruleset.\n\tconst Mod *getMod() const { return _rule; }\n\t/// gets the list of items we're guaranteed.\n\tstd::vector<BattleItem*> *getGuaranteedRecoveredItems();\n\t/// gets the list of items we MIGHT get.\n\tstd::vector<BattleItem*> *getConditionalRecoveredItems();\n\t/// Get the name of the music track.\n\tconst std::string &getMusic() const;\n\t/// Set the name of the music track.\n\tvoid setMusic(const std::string &track);\n\n\t/// Sets the VIP escape type.\n\tvoid setVIPEscapeType(EscapeType vipEscapeType);\n\t/// Gets the VIP escape type.\n\tEscapeType getVIPEscapeType() const;\n\t/// Sets the percentage of VIPs that must survive in order to accomplish the mission.\n\tvoid setVIPSurvivalPercentage(int vipSurvivalPercentage);\n\t/// Gets the percentage of VIPs that must survive in order to accomplish the mission.\n\tint getVIPSurvivalPercentage() const;\n\t/// Increase the saved VIPs counter.\n\tvoid addSavedVIP(int score);\n\t/// Gets the saved VIPs counter.\n\tint getSavedVIPs() const;\n\t/// Gets the saved VIPs total score.\n\tint getSavedVIPsScore() const;\n\t/// Increase the lost VIPs counter.\n\tvoid addLostVIP(int score);\n\t/// Gets the lost VIPs counter.\n\tint getLostVIPs() const;\n\t/// Gets the lost VIPs total score.\n\tint getLostVIPsScore() const;\n\t/// Increase the waiting outside VIPs counter.\n\tvoid addWaitingOutsideVIP(int score);\n\t/// Corrects the VIP stats based on the final mission outcome.\n\tvoid correctVIPStats(bool success, bool retreated);\n\n\t/// Sets the objective type for this mission.\n\tvoid setObjectiveType(int type);\n\t/// Gets the objective type of this mission.\n\tSpecialTileType getObjectiveType() const;\n\t/// sets the ambient sound effect;\n\tvoid setAmbientVolume(double volume);\n\t/// gets the ambient sound effect;\n\tdouble getAmbientVolume() const;\n\t/// Gets the turn limit for this mission.\n\tint getTurnLimit() const;\n\t/// Gets the action that triggers when the timer runs out.\n\tChronoTrigger getChronoTrigger() const;\n\t/// Sets the turn limit for this mission.\n\tvoid setTurnLimit(int limit);\n\t/// Sets the action that triggers when the timer runs out.\n\tvoid setChronoTrigger(ChronoTrigger trigger);\n\t/// Sets the turn to start the aliens cheating.\n\tvoid setCheatTurn(int turn);\n\t/// Check whether the battle has actually commenced or not.\n\tbool isBeforeGame() const;\n\n\t/// gets personal light toggle\n\tbool getTogglePersonalLight() const { return _togglePersonalLight; }\n\t/// sets personal light toggle\n\tvoid setTogglePersonalLight(bool togglePersonalLight) { _togglePersonalLight = togglePersonalLight; }\n\t/// gets night vision toggle\n\tbool getToggleNightVision() const { return _toggleNightVision; }\n\t/// sets night vision toggle\n\tvoid setToggleNightVision(bool toggleNightVision) { _toggleNightVision = toggleNightVision; }\n\t/// gets brightness toggle\n\tint getToggleBrightness() const { return _toggleBrightness; }\n\t/// sets brightness toggle\n\tvoid setToggleBrightness(int toggleBrightness) { _toggleBrightness = toggleBrightness; }\n\n\t/// sets final value for personal light toggle (for scripts)\n\tvoid setTogglePersonalLightTemp(bool togglePersonalLight) { _togglePersonalLightTemp = togglePersonalLight; }\n\t/// sets final value for night vision toggle (for scripts)\n\tvoid setToggleNightVisionTemp(bool toggleNightVision) { _toggleNightVisionTemp = toggleNightVision; }\n\t/// sets final value for night vision color toggle (for scripts)\n\tvoid setToggleNightVisionColorTemp(int toggleNightColorVision) { _toggleNightVisionColorTemp = toggleNightColorVision; }\n\t/// sets final value for brightness toggle (for scripts)\n\tvoid setToggleBrightnessTemp(int toggleBrightness) { _toggleBrightnessTemp = toggleBrightness; }\n\n\t/// Randomly chooses hidden movement background.\n\tvoid setRandomHiddenMovementBackground(const Mod *mod);\n\t/// Gets the hidden movement background ID.\n\tconst std::string& getHiddenMovementBackground() const;\n\t/// Appends a given entry to the hit log. Works only during the player's turn.\n\tvoid appendToHitLog(HitLogEntryType type, UnitFaction faction);\n\tvoid appendToHitLog(HitLogEntryType type, UnitFaction faction, const std::string &text);\n\t/// Gets the hit log.\n\tconst HitLog *getHitLog() const;\n\t/// Reset all the unit hit state flags.\n\tvoid resetUnitHitStates();\n};\n\n}\n"
  },
  {
    "path": "src/Savegame/SavedGame.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"SavedGame.h\"\n#include <sstream>\n#include <set>\n#include <iomanip>\n#include <algorithm>\n#include <functional>\n#include <ctime>\n#include \"../Engine/Yaml.h\"\n#include \"../version.h\"\n#include \"../Engine/Logger.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/RNG.h\"\n#include \"../Engine/Exception.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/CrossPlatform.h\"\n#include \"../Engine/ScriptBind.h\"\n#include \"SavedBattleGame.h\"\n#include \"SerializationHelper.h\"\n#include \"GameTime.h\"\n#include \"Country.h\"\n#include \"Base.h\"\n#include \"Craft.h\"\n#include \"EquipmentLayoutItem.h\"\n#include \"Region.h\"\n#include \"Ufo.h\"\n#include \"Waypoint.h\"\n#include \"../Mod/RuleResearch.h\"\n#include \"ResearchProject.h\"\n#include \"ItemContainer.h\"\n#include \"Soldier.h\"\n#include \"Transfer.h\"\n#include \"../Mod/RuleManufacture.h\"\n#include \"../Mod/RuleBaseFacility.h\"\n#include \"../Mod/RuleCraft.h\"\n#include \"../Mod/RuleSoldierTransformation.h\"\n#include \"Production.h\"\n#include \"MissionSite.h\"\n#include \"AlienBase.h\"\n#include \"AlienStrategy.h\"\n#include \"AlienMission.h\"\n#include \"GeoscapeEvent.h\"\n#include \"../Mod/RuleCountry.h\"\n#include \"../Mod/RuleRegion.h\"\n#include \"../Mod/RuleSoldier.h\"\n#include \"../Mod/SoldierNamePool.h\"\n#include \"BaseFacility.h\"\n#include \"MissionStatistics.h\"\n#include \"SoldierDeath.h\"\n#include \"SoldierDiary.h\"\n#include \"ResearchDiary.h\"\n#include \"../Mod/AlienRace.h\"\n#include \"RankCount.h\"\n\nnamespace OpenXcom\n{\n\nconst std::string SavedGame::AUTOSAVE_GEOSCAPE = \"_autogeo_.asav\",\n\t\t\t\t  SavedGame::AUTOSAVE_BATTLESCAPE = \"_autobattle_.asav\",\n\t\t\t\t  SavedGame::QUICKSAVE = \"_quick_.asav\";\n\nnamespace\n{\n\nbool researchLess(const RuleResearch *a, const RuleResearch *b)\n{\n\treturn std::less<const RuleResearch *>{}(a, b);\n}\n\ntemplate<typename T>\nvoid sortReserchVector(std::vector<T> &vec)\n{\n\tstd::sort(vec.begin(), vec.end(), researchLess);\n}\n\nbool haveReserchVector(const std::vector<const RuleResearch*> &vec, const RuleResearch *res)\n{\n\tauto find = std::lower_bound(vec.begin(), vec.end(), res, researchLess);\n\treturn find != vec.end() && *find == res;\n}\n\nbool haveReserchVector(const std::vector<const RuleResearch*> &vec,  const std::string &res)\n{\n\tauto find = std::find_if(vec.begin(), vec.end(), [&](const RuleResearch* r){ return r->getName() == res; });\n\treturn find != vec.end();\n}\n\n}\n\n/**\n * Initializes a brand new saved game according to the specified difficulty.\n */\nSavedGame::SavedGame() :\n\t_difficulty(DIFF_BEGINNER), _end(END_NONE), _ironman(false), _globeLon(0.0), _globeLat(0.0), _globeZoom(0),\n\t_battleGame(0), _previewBase(nullptr), _debug(false), _warned(false),\n\t_togglePersonalLight(true), _toggleNightVision(false), _toggleBrightness(0),\n\t_monthsPassed(-1), _daysPassed(0), _vehiclesLost(0), _craftLostDogfight(0), _craftLostMission(0),\n\t_selectedBase(0), _autosales(), _disableSoldierEquipment(false), _alienContainmentChecked(false)\n{\n\t_time = new GameTime(6, 1, 1, 1999, 12, 0, 0);\n\t_alienStrategy = new AlienStrategy();\n\t_funds.push_back(0);\n\t_maintenance.push_back(0);\n\t_researchScores.push_back(0);\n\t_incomes.push_back(0);\n\t_expenditures.push_back(0);\n\t_lastselectedArmor=\"STR_NONE_UC\";\n\n\tfor (int j = 0; j < MAX_CRAFT_LOADOUT_TEMPLATES; ++j)\n\t{\n\t\t_globalCraftLoadout[j] = new ItemContainer();\n\t}\n}\n\n/**\n * Deletes the game content from memory.\n */\nSavedGame::~SavedGame()\n{\n\tdelete _time;\n\tfor (auto* country : _countries)\n\t{\n\t\tdelete country;\n\t}\n\tfor (auto* region : _regions)\n\t{\n\t\tdelete region;\n\t}\n\tfor (auto* xbase : _bases)\n\t{\n\t\tdelete xbase;\n\t}\n\tdelete _previewBase;\n\tfor (auto* ufo : _ufos)\n\t{\n\t\tdelete ufo;\n\t}\n\tfor (auto* wp : _waypoints)\n\t{\n\t\tdelete wp;\n\t}\n\tfor (auto* site : _missionSites)\n\t{\n\t\tdelete site;\n\t}\n\tfor (auto* ab : _alienBases)\n\t{\n\t\tdelete ab;\n\t}\n\tdelete _alienStrategy;\n\tfor (auto* am : _activeMissions)\n\t{\n\t\tdelete am;\n\t}\n\tfor (auto* ge : _geoscapeEvents)\n\t{\n\t\tdelete ge;\n\t}\n\tfor (auto* soldier : _deadSoldiers)\n\t{\n\t\tdelete soldier;\n\t}\n\tfor (int j = 0; j < Options::oxceMaxEquipmentLayoutTemplates; ++j)\n\t{\n\t\tfor (auto* entry : _globalEquipmentLayout[j])\n\t\t{\n\t\t\tdelete entry;\n\t\t}\n\t}\n\tfor (int j = 0; j < MAX_CRAFT_LOADOUT_TEMPLATES; ++j)\n\t{\n\t\tdelete _globalCraftLoadout[j];\n\t}\n\tfor (auto* ms : _missionStatistics)\n\t{\n\t\tdelete ms;\n\t}\n\tfor (auto* rde : _researchDiary)\n\t{\n\t\tdelete rde;\n\t}\n\n\tdelete _battleGame;\n}\n\n/**\n * Removes version number from a mod name, if any.\n * @param name Mod id from a savegame.\n * @return Sanitized mod name.\n */\nstd::string SavedGame::sanitizeModName(const std::string &name)\n{\n\tsize_t versionInfoBreakPoint = name.find(\" ver: \");\n\tif (versionInfoBreakPoint == std::string::npos)\n\t{\n\t\treturn name;\n\t}\n\telse\n\t{\n\t\treturn name.substr(0, versionInfoBreakPoint);\n\t}\n}\n\nstatic bool _isCurrentGameType(const SaveInfo &saveInfo, const std::string &curMaster)\n{\n\tbool matchMasterMod = false;\n\tif (saveInfo.mods.empty())\n\t{\n\t\t// if no mods listed in the savegame, this is an old-style\n\t\t// savegame.  assume \"xcom1\" as the game type.\n\t\tmatchMasterMod = (curMaster == \"xcom1\");\n\t}\n\telse\n\t{\n\t\tfor (const auto& modName : saveInfo.mods)\n\t\t{\n\t\t\tstd::string name = SavedGame::sanitizeModName(modName);\n\t\t\tif (name == curMaster)\n\t\t\t{\n\t\t\t\tmatchMasterMod = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (!matchMasterMod)\n\t{\n\t\tLog(LOG_DEBUG) << \"skipping save from inactive master: \" << saveInfo.fileName;\n\t}\n\n\treturn matchMasterMod;\n}\n\n/**\n * Gets all the info of the saves found in the user folder.\n * @param lang Loaded language.\n * @param autoquick Include autosaves and quicksaves.\n * @return List of saves info.\n */\nstd::vector<SaveInfo> SavedGame::getList(Language *lang, bool autoquick)\n{\n\tstd::vector<SaveInfo> info;\n\tstd::string curMaster = Options::getActiveMaster();\n\tauto saves = CrossPlatform::getFolderContents(Options::getMasterUserFolder(), \"sav\");\n\n\tif (autoquick)\n\t{\n\t\tauto asaves = CrossPlatform::getFolderContents(Options::getMasterUserFolder(), \"asav\");\n\t\tsaves.insert(saves.begin(), asaves.begin(), asaves.end());\n\t}\n\tfor (const auto& tuple : saves)\n\t{\n\t\tconst auto& filename = std::get<0>(tuple);\n\t\ttry\n\t\t{\n\t\t\tSaveInfo saveInfo = getSaveInfo(filename, lang);\n\t\t\tif (!_isCurrentGameType(saveInfo, curMaster))\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tinfo.push_back(saveInfo);\n\t\t}\n\t\tcatch (Exception &e)\n\t\t{\n\t\t\tLog(LOG_ERROR) << filename << \": \" << e.what();\n\t\t\tcontinue;\n\t\t}\n\t\tcatch (YAML::Exception& e)\n\t\t{\n\t\t\tLog(LOG_ERROR) << filename << \": \" << e.what();\n\t\t\tcontinue;\n\t\t}\n\t}\n\n\treturn info;\n}\n\n/**\n * Gets the info of a specific save file.\n * @param file Save filename.\n * @param lang Loaded language.\n */\nSaveInfo SavedGame::getSaveInfo(const std::string &file, Language *lang)\n{\n\tstd::string fullname = Options::getMasterUserFolder() + file;\n\tYAML::YamlRootNodeReader reader(fullname, true);\n\tSaveInfo save;\n\n\tsave.fileName = file;\n\n\tif (save.fileName == QUICKSAVE)\n\t{\n\t\tsave.displayName = lang->getString(\"STR_QUICK_SAVE_SLOT\");\n\t\tsave.reserved = true;\n\t}\n\telse if (save.fileName == AUTOSAVE_GEOSCAPE)\n\t{\n\t\tsave.displayName = lang->getString(\"STR_AUTO_SAVE_GEOSCAPE_SLOT\");\n\t\tsave.reserved = true;\n\t}\n\telse if (save.fileName.find(AUTOSAVE_GEOSCAPE) != std::string::npos)\n\t{\n\t\tGameTime time = GameTime(6, 1, 1, 1999, 12, 0, 0);\n\t\tif (reader[\"time\"])\n\t\t\ttime.load(reader[\"time\"]);\n\t\tsave.displayName = lang->getString(\"STR_AUTO_SAVE_GEOSCAPE_SLOT_WITH_NUMBER\").arg(time.getDayString(lang));\n\t\tsave.reserved = true;\n\t}\n\telse if (save.fileName == AUTOSAVE_BATTLESCAPE)\n\t{\n\t\tsave.displayName = lang->getString(\"STR_AUTO_SAVE_BATTLESCAPE_SLOT\");\n\t\tsave.reserved = true;\n\t}\n\telse if (save.fileName.find(AUTOSAVE_BATTLESCAPE) != std::string::npos)\n\t{\n\t\tint turn = reader[\"turn\"].readVal(0);\n\t\tsave.displayName = lang->getString(\"STR_AUTO_SAVE_BATTLESCAPE_SLOT_WITH_NUMBER\").arg(turn);\n\t\tsave.reserved = true;\n\t}\n\telse\n\t{\n\t\tif (!reader.tryRead(\"name\", save.displayName))\n\t\t\tsave.displayName = CrossPlatform::noExt(file);\n\t\tsave.reserved = false;\n\t}\n\n\tsave.timestamp = CrossPlatform::getDateModified(fullname);\n\tstd::pair<std::string, std::string> str = CrossPlatform::timeToString(save.timestamp);\n\tsave.isoDate = str.first;\n\tsave.isoTime = str.second;\n\treader.tryRead(\"mods\", save.mods);\n\n\tstd::ostringstream details;\n\tif (reader[\"turn\"])\n\t{\n\t\tdetails << lang->getString(\"STR_BATTLESCAPE\") << \": \" << lang->getString(reader[\"mission\"].readVal<std::string>()) << \", \";\n\t\tdetails << lang->getString(\"STR_TURN\").arg(reader[\"turn\"].readVal<int>());\n\t}\n\telse\n\t{\n\t\tGameTime time = GameTime(6, 1, 1, 1999, 12, 0, 0);\n\t\ttime.load(reader[\"time\"]);\n\t\tdetails << lang->getString(\"STR_GEOSCAPE\") << \": \";\n\t\tdetails << time.getDayString(lang) << \" \" << lang->getString(time.getMonthString()) << \" \" << time.getYear() << \", \";\n\t\tdetails << time.getHour() << \":\" << std::setfill('0') << std::setw(2) << time.getMinute();\n\t}\n\tif (reader[\"ironman\"].readVal(false))\n\t{\n\t\tdetails << \" (\" << lang->getString(\"STR_IRONMAN\") << \")\";\n\t}\n\tsave.details = details.str();\n\n\treturn save;\n}\n\n/**\n * Loads a saved game's contents from a YAML file.\n * @note Assumes the saved game is blank.\n * @param filename YAML filename.\n * @param mod Mod for the saved game.\n * @param lang Loaded language.\n */\nvoid SavedGame::load(const std::string &filename, Mod *mod, Language *lang)\n{\n\tstd::string filepath = Options::getMasterUserFolder() + filename;\n\tYAML::YamlRootNodeReader documents(filepath, false, false);\n\n\t// Get brief save info\n\tconst auto& header = documents[0];\n\t_time->load(header[\"time\"]);\n\theader.readNode(\"name\", _name, filename);\n\theader.tryRead(\"ironman\", _ironman);\n\n\t// Get full save data\n\tconst auto& reader = documents[1].useIndex();\n\treader.tryRead(\"difficulty\", _difficulty);\n\treader.tryRead(\"end\", _end);\n\tif (reader[\"rng\"] && (_ironman || !Options::newSeedOnLoad))\n\t\tRNG::setSeed(reader[\"rng\"].readVal<uint64_t>());\n\treader.tryRead(\"monthsPassed\", _monthsPassed);\n\treader.tryRead(\"daysPassed\", _daysPassed);\n\treader.tryRead(\"vehiclesLost\", _vehiclesLost);\n\treader.tryRead(\"craftLostDogfight\", _craftLostDogfight);\n\treader.tryRead(\"craftLostMission\", _craftLostMission);\n\treader.tryRead(\"graphRegionToggles\", _graphRegionToggles);\n\treader.tryRead(\"graphCountryToggles\", _graphCountryToggles);\n\treader.tryRead(\"graphFinanceToggles\", _graphFinanceToggles);\n\treader.tryRead(\"funds\", _funds);\n\treader.tryRead(\"maintenance\", _maintenance);\n\treader.tryRead(\"userNotes\", _userNotes);\n\treader.tryRead(\"geoscapeDebugLog\", _geoscapeDebugLog);\n\treader.tryRead(\"researchScores\", _researchScores);\n\treader.tryRead(\"incomes\", _incomes);\n\treader.tryRead(\"expenditures\", _expenditures);\n\treader.tryRead(\"warned\", _warned);\n\treader.tryRead(\"togglePersonalLight\", _togglePersonalLight);\n\treader.tryRead(\"toggleNightVision\", _toggleNightVision);\n\treader.tryRead(\"toggleBrightness\", _toggleBrightness);\n\treader.tryRead(\"globeLon\", _globeLon);\n\treader.tryRead(\"globeLat\", _globeLat);\n\treader.tryRead(\"globeZoom\", _globeZoom);\n\treader.tryRead(\"ids\", _ids);\n\n\tfor (const auto& country : reader[\"countries\"].children())\n\t{\n\t\tstd::string type = country[\"type\"].readVal<std::string>();\n\t\tif (mod->getCountry(type))\n\t\t{\n\t\t\tCountry *c = new Country(mod->getCountry(type), false);\n\t\t\tc->load(country, mod->getScriptGlobal());\n\t\t\t_countries.push_back(c);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"Failed to load country \" << type;\n\t\t}\n\t}\n\n\tfor (const auto& region : reader[\"regions\"].children())\n\t{\n\t\tstd::string type = region[\"type\"].readVal<std::string>();\n\t\tif (mod->getRegion(type))\n\t\t{\n\t\t\tRegion *r = new Region(mod->getRegion(type));\n\t\t\tr->load(region);\n\t\t\t_regions.push_back(r);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"Failed to load region \" << type;\n\t\t}\n\t}\n\n\t// Alien bases must be loaded before alien missions\n\tfor (const auto& alienBase : reader[\"alienBases\"].children())\n\t{\n\t\tstd::string deployment = alienBase[\"deployment\"].readVal<std::string>(\"STR_ALIEN_BASE_ASSAULT\");\n\t\tif (mod->getDeployment(deployment))\n\t\t{\n\t\t\tAlienBase *b = new AlienBase(mod->getDeployment(deployment), 0);\n\t\t\tb->load(alienBase);\n\t\t\t_alienBases.push_back(b);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"Failed to load deployment for alien base \" << deployment;\n\t\t}\n\t}\n\n\t// Missions must be loaded before UFOs.\n\tfor (const auto& alienMission : reader[\"alienMissions\"].children())\n\t{\n\t\tstd::string missionType = alienMission[\"type\"].readVal<std::string>();\n\t\tif (mod->getAlienMission(missionType))\n\t\t{\n\t\t\tconst RuleAlienMission &mRule = *mod->getAlienMission(missionType);\n\t\t\tAlienMission *mission = new AlienMission(mRule);\n\t\t\tmission->load(alienMission, *this, mod);\n\t\t\t_activeMissions.push_back(mission);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"Failed to load mission \" << missionType;\n\t\t}\n\t}\n\n\tfor (const auto& ufo : reader[\"ufos\"].children())\n\t{\n\t\tstd::string type = ufo[\"type\"].readVal<std::string>();\n\t\tif (mod->getUfo(type))\n\t\t{\n\t\t\tUfo *u = new Ufo(mod->getUfo(type), 0);\n\t\t\tu->load(ufo, mod->getScriptGlobal(), *mod, *this);\n\t\t\t_ufos.push_back(u);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"Failed to load UFO \" << type;\n\t\t}\n\t}\n\n\tfor (const auto& geoEvent : reader[\"geoscapeEvents\"].children())\n\t{\n\t\tstd::string eventName = geoEvent[\"name\"].readVal<std::string>();\n\t\tif (mod->getEvent(eventName))\n\t\t{\n\t\t\tconst RuleEvent &eventRule = *mod->getEvent(eventName);\n\t\t\tGeoscapeEvent *event = new GeoscapeEvent(eventRule);\n\t\t\tevent->load(geoEvent);\n\t\t\t_geoscapeEvents.push_back(event);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"Failed to load geoscape event \" << eventName;\n\t\t}\n\t}\n\n\tfor (const auto& waypoint : reader[\"waypoints\"].children())\n\t{\n\t\tWaypoint *w = new Waypoint();\n\t\tw->load(waypoint);\n\t\t_waypoints.push_back(w);\n\t}\n\n\t// Backwards compatibility\n\tfor (const auto& terrorSite : reader[\"terrorSites\"].children())\n\t{\n\t\tstd::string type = \"STR_ALIEN_TERROR\";\n\t\tstd::string deployment = \"STR_TERROR_MISSION\";\n\t\tif (mod->getAlienMission(type) && mod->getDeployment(deployment))\n\t\t{\n\t\t\tMissionSite *m = new MissionSite(mod->getAlienMission(type), mod->getDeployment(deployment), nullptr);\n\t\t\tm->load(terrorSite);\n\t\t\t_missionSites.push_back(m);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"Failed to load mission \" << type << \" deployment \" << deployment;\n\t\t}\n\t}\n\n\tfor (const auto& missionSite : reader[\"missionSites\"].children())\n\t{\n\t\tstd::string type = missionSite[\"type\"].readVal<std::string>();\n\t\tstd::string deployment = missionSite[\"deployment\"].readVal<std::string>(\"STR_TERROR_MISSION\");\n\t\tstd::string alienWeaponDeploy = missionSite[\"missionCustomDeploy\"].readVal<std::string>(\"\");\n\t\tif (mod->getAlienMission(type) && mod->getDeployment(deployment))\n\t\t{\n\t\t\tMissionSite *m = new MissionSite(mod->getAlienMission(type), mod->getDeployment(deployment), mod->getDeployment(alienWeaponDeploy));\n\t\t\tm->load(missionSite);\n\t\t\t_missionSites.push_back(m);\n\t\t\t// link with UFO\n\t\t\tif (m->getUfoUniqueId() > 0)\n\t\t\t{\n\t\t\t\tUfo* ufo = nullptr;\n\t\t\t\tfor (auto* u : _ufos)\n\t\t\t\t{\n\t\t\t\t\tif (u->getUniqueId() == m->getUfoUniqueId())\n\t\t\t\t\t{\n\t\t\t\t\t\tufo = u;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (ufo)\n\t\t\t\t{\n\t\t\t\t\tm->setUfo(ufo);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"Failed to load mission \" << type << \" deployment \" << deployment;\n\t\t}\n\t}\n\n\t// Discovered Techs Should be loaded before Bases (e.g. for PSI evaluation)\n\tfor (const auto& discovery : reader[\"discovered\"].children())\n\t{\n\t\tstd::string research = discovery.readVal<std::string>();\n\t\tif (RuleResearch* researchRule = mod->getResearch(research))\n\t\t{\n\t\t\t_discovered.push_back(researchRule);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"Failed to load research \" << research;\n\t\t}\n\t}\n\tsortReserchVector(_discovered);\n\n\t// Research Diary\n\t{\n\t\tstd::string name;\n\t\tfor (const auto& researchDiaryEntryReader : reader[\"researchDiary\"].children())\n\t\t{\n\t\t\tresearchDiaryEntryReader.readNode(\"name\", name);\n\t\t\t// only valid topics are loaded\n\t\t\tif (RuleResearch* research = mod->getResearch(name, false))\n\t\t\t{\n\t\t\t\tResearchDiaryEntry* entry = new ResearchDiaryEntry(research);\n\t\t\t\tentry->load(researchDiaryEntryReader, mod);\n\t\t\t\t_researchDiary.push_back(entry);\n\t\t\t}\n\t\t}\n\t}\n\n\treader.tryRead(\"generatedEvents\", _generatedEvents);\n\tloadUfopediaRuleStatus(reader[\"ufopediaRuleStatus\"]);\n\treader.tryRead(\"manufactureRuleStatus\", _manufactureRuleStatus);\n\treader.tryRead(\"researchRuleStatus\", _researchRuleStatus);\n\treader.tryRead(\"monthlyPurchaseLimitLog\", _monthlyPurchaseLimitLog);\n\treader.tryRead(\"hiddenPurchaseItems\", _hiddenPurchaseItemsMap);\n\treader.tryRead(\"customRuleCraftDeployments\", _customRuleCraftDeployments);\n\n\tfor (const auto& base : reader[\"bases\"].children())\n\t{\n\t\tBase *b = new Base(mod);\n\t\tb->load(base, this, false);\n\t\t_bases.push_back(b);\n\t}\n\n\t// Finish loading crafts after bases (more specifically after all crafts) are loaded, because of references between crafts (i.e. friendly escorts)\n\tfor (size_t i = 0; i < _bases.size(); ++i)\n\t\t_bases[i]->finishLoading(reader[\"bases\"][i], this);\n\n\t// Finish loading UFOs after all craft and all other UFOs are loaded\n\tfor (const auto& ufoReader : reader[\"ufos\"].children())\n\t{\n\t\tint uniqueUfoId = ufoReader[\"uniqueId\"].readVal(0);\n\t\tif (uniqueUfoId > 0)\n\t\t{\n\t\t\tUfo *ufo = 0;\n\t\t\tfor (auto* u : _ufos)\n\t\t\t{\n\t\t\t\tif (u->getUniqueId() == uniqueUfoId)\n\t\t\t\t{\n\t\t\t\t\tufo = u;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (ufo)\n\t\t\t{\n\t\t\t\tufo->finishLoading(ufoReader, *this);\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (const auto& popped : reader[\"poppedResearch\"].children())\n\t{\n\t\tstd::string id = popped.readVal<std::string>();\n\t\tif (mod->getResearch(id))\n\t\t{\n\t\t\t_poppedResearch.push_back(mod->getResearch(id));\n\t\t}\n\t\telse\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"Failed to load popped research \" << id;\n\t\t}\n\t}\n\t_alienStrategy->load(reader[\"alienStrategy\"], mod);\n\n\tfor (const auto& weHardlyKnewYe : reader[\"deadSoldiers\"].children())\n\t{\n\t\tstd::string type = weHardlyKnewYe[\"type\"].readVal(mod->getSoldiersList().front());\n\t\tif (mod->getSoldier(type))\n\t\t{\n\t\t\tSoldier *soldier = new Soldier(mod->getSoldier(type), nullptr, 0 /*nationality*/);\n\t\t\tsoldier->load(weHardlyKnewYe, mod, this, mod->getScriptGlobal());\n\t\t\t_deadSoldiers.push_back(soldier);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"Failed to load dead soldier \" << type;\n\t\t}\n\t}\n\n\tloadTemplates(reader, mod);\n\n\tfor (const auto& missionStats : reader[\"missionStatistics\"].children())\n\t{\n\t\tMissionStatistics *ms = new MissionStatistics();\n\t\tms->load(missionStats);\n\t\t_missionStatistics.push_back(ms);\n\t}\n\n\tfor (const auto& autoSale : reader[\"autoSales\"].children())\n\t{\n\t\tstd::string itype = autoSale.readVal<std::string>();\n\t\tif (mod->getItem(itype))\n\t\t{\n\t\t\t_autosales.insert(mod->getItem(itype));\n\t\t}\n\t}\n\n\tif (const YAML::YamlNodeReader& battle = reader[\"battleGame\"])\n\t{\n\t\t_battleGame = new SavedBattleGame(mod, lang);\n\t\t_battleGame->load(battle, mod, this);\n\t}\n\n\t_scriptValues.load(reader, mod->getScriptGlobal());\n}\n\nvoid SavedGame::loadTemplates(const YAML::YamlNodeReader& reader, const Mod* mod)\n{\n\tfor (int j = 0; j < Options::oxceMaxEquipmentLayoutTemplates; ++j)\n\t{\n\t\tfor (const auto& layout : reader[ryml::to_csubstr(\"globalEquipmentLayout\" + std::to_string(j))].children())\n\t\t{\n\t\t\ttry\n\t\t\t{\n\t\t\t\t_globalEquipmentLayout[j].push_back(new EquipmentLayoutItem(layout, mod));\n\t\t\t}\n\t\t\tcatch (Exception& ex)\n\t\t\t{\n\t\t\t\tLog(LOG_ERROR) << \"Error loading Layout: \" << ex.what();\n\t\t\t}\n\t\t}\n\t\tif (const auto& layoutName = reader[ryml::to_csubstr(\"globalEquipmentLayoutName\" + std::to_string(j))])\n\t\t\t_globalEquipmentLayoutName[j] = layoutName.readVal<std::string>();\n\t\tif (const auto& layoutArmor = reader[ryml::to_csubstr(\"globalEquipmentLayoutArmor\" + std::to_string(j))])\n\t\t\t_globalEquipmentLayoutArmor[j] = layoutArmor.readVal<std::string>();\n\t}\n\n\tfor (int j = 0; j < MAX_CRAFT_LOADOUT_TEMPLATES; ++j)\n\t{\n\t\tif (const auto& loadout = reader[ryml::to_csubstr(\"globalCraftLoadout\" + std::to_string(j))])\n\t\t\t_globalCraftLoadout[j]->load(loadout, mod);\n\t\tif (const auto& loadoutName = reader[ryml::to_csubstr(\"globalCraftLoadoutName\" + std::to_string(j))])\n\t\t\t_globalCraftLoadoutName[j] = loadoutName.readVal<std::string>();\n\t}\n}\n\nvoid SavedGame::loadUfopediaRuleStatus(const YAML::YamlNodeReader& reader)\n{\n\treader.tryReadVal(_ufopediaRuleStatus);\n}\n\ntemplate <typename T, typename... Args>\nvoid saveVector(YAML::YamlNodeWriter& writer, const std::vector<T*>& vector, const ryml::csubstr& key, Args... args)\n{\n\tif (vector.empty())\n\t\treturn;\n\tYAML::YamlNodeWriter sequenceWriter = writer[key];\n\tsequenceWriter.setAsSeq();\n\tfor (const T* item : vector)\n\t\titem->save(sequenceWriter.write(), args...);\n}\n\n/**\n * Saves a saved game's contents to a YAML file.\n * @param filename YAML filename.\n */\nvoid SavedGame::save(const std::string &filename, Mod *mod) const\n{\n\tYAML::YamlRootNodeWriter headerWriter;\n\theaderWriter.setAsMap();\n\t// Saves the brief game info used in the saves list\n\n\theaderWriter.write(\"name\", _name);\n\theaderWriter.write(\"version\", OPENXCOM_VERSION_SHORT);\n\theaderWriter.write(\"engine\", OPENXCOM_VERSION_ENGINE);\n\tstd::string git_sha = OPENXCOM_VERSION_GIT;\n\tif (!git_sha.empty() && git_sha[0] == '.')\n\t\tgit_sha.erase(0, 1);\n\theaderWriter.write(\"build\", git_sha);\n\t_time->save(headerWriter[\"time\"]);\n\tif (_battleGame != 0)\n\t{\n\t\theaderWriter.write(\"mission\", _battleGame->getMissionType());\n\t\theaderWriter.write(\"target\", _battleGame->getMissionTarget());\n\t\theaderWriter.write(\"craftOrBase\", _battleGame->getMissionCraftOrBase()).setAsQuotedAndEscaped();\n\t\theaderWriter.write(\"turn\", _battleGame->getTurn());\n\t}\n\n\t// only save mods that work with the current master\n\tstd::vector<std::string> modsList;\n\tfor (const auto* modInfo : Options::getActiveMods())\n\t\tmodsList.push_back(modInfo->getId() + \" ver: \" + modInfo->getVersion());\n\theaderWriter.write(\"mods\", modsList);\n\n\tif (_ironman)\n\t\theaderWriter.write(\"ironman\", _ironman);\n\n\t// Saves the full game data to the save\n\tYAML::YamlRootNodeWriter writer(1000000); //1MB starting buffer\n\twriter.setAsMap();\n\twriter.write(\"difficulty\", _difficulty);\n\twriter.write(\"end\", _end);\n\twriter.write(\"monthsPassed\", _monthsPassed);\n\twriter.write(\"daysPassed\", _daysPassed);\n\twriter.write(\"vehiclesLost\", _vehiclesLost);\n\twriter.write(\"craftLostDogfight\", _craftLostDogfight);\n\twriter.write(\"craftLostMission\", _craftLostMission);\n\twriter.write(\"graphRegionToggles\", _graphRegionToggles);\n\twriter.write(\"graphCountryToggles\", _graphCountryToggles);\n\twriter.write(\"graphFinanceToggles\", _graphFinanceToggles);\n\twriter.write(\"rng\", RNG::getSeed());\n\twriter.write(\"funds\", _funds);\n\twriter.write(\"maintenance\", _maintenance);\n\twriter.write(\"userNotes\", _userNotes);\n\tif (Options::oxceGeoscapeDebugLogMaxEntries > 0 && _geoscapeDebugLog.size() > 0)\n\t{\n\t\tauto geoDebugLog = writer[\"geoscapeDebugLog\"];\n\t\tgeoDebugLog.setAsSeq();\n\t\tsize_t lastEntriesToWrite = std::min(_geoscapeDebugLog.size(), (size_t)Options::oxceGeoscapeDebugLogMaxEntries);\n\t\tfor (size_t j = _geoscapeDebugLog.size() - lastEntriesToWrite; j < _geoscapeDebugLog.size(); ++j)\n\t\t\tgeoDebugLog.write(_geoscapeDebugLog[j]);\n\t}\n\n\twriter.write(\"researchScores\", _researchScores);\n\twriter.write(\"incomes\", _incomes);\n\twriter.write(\"expenditures\", _expenditures);\n\twriter.write(\"warned\", _warned);\n\twriter.write(\"togglePersonalLight\", _togglePersonalLight);\n\twriter.write(\"toggleNightVision\", _toggleNightVision);\n\twriter.write(\"toggleBrightness\", _toggleBrightness);\n\twriter.write(\"globeLon\", _globeLon);\n\twriter.write(\"globeLat\", _globeLat);\n\twriter.write(\"globeZoom\", _globeZoom);\n\twriter.write(\"ids\", _ids);\n\n\tsaveVector(writer, _countries, \"countries\", mod->getScriptGlobal());\n\tsaveVector(writer, _regions, \"regions\");\n\tsaveVector(writer, _bases, \"bases\");\n\tsaveVector(writer, _waypoints, \"waypoints\");\n\tsaveVector(writer, _missionSites, \"missionSites\");\n\t// Alien bases must be saved before alien missions.\n\tsaveVector(writer, _alienBases, \"alienBases\");\n\t// Missions must be saved before UFOs, but after alien bases.\n\tsaveVector(writer, _activeMissions, \"alienMissions\");\n\t// UFOs must be after missions\n\tsaveVector(writer, _ufos, \"ufos\", mod->getScriptGlobal(), getMonthsPassed() == -1);\n\tsaveVector(writer, _geoscapeEvents, \"geoscapeEvents\");\n\tif (!_discovered.empty())\n\t{\n\t\tauto discoveredWriter = writer[\"discovered\"];\n\t\tdiscoveredWriter.setAsSeq();\n\t\t{\n\t\t\tauto discoveredCopy = _discovered;\n\t\t\tstd::sort(discoveredCopy.begin(), discoveredCopy.end(), [&](const RuleResearch* a, const RuleResearch* b)\n\t\t\t\t\t  { return a->getName().compare(b->getName()) < 0; });\n\t\t\tfor (const auto* research : discoveredCopy)\n\t\t\t{\n\t\t\t\tdiscoveredWriter.write(research->getName());\n\t\t\t}\n\t\t}\n\t}\n\tsaveVector(writer, _researchDiary, \"researchDiary\");\n\twriter.write(\"poppedResearch\", _poppedResearch,\n\t\t[](YAML::YamlNodeWriter& w, const RuleResearch* r)\n\t\t{ w.write(r->getName()); });\n\twriter.write(\"generatedEvents\", _generatedEvents);\n\twriter.write(\"ufopediaRuleStatus\", _ufopediaRuleStatus);\n\twriter.write(\"manufactureRuleStatus\", _manufactureRuleStatus);\n\twriter.write(\"researchRuleStatus\", _researchRuleStatus);\n\twriter.write(\"monthlyPurchaseLimitLog\", _monthlyPurchaseLimitLog);\n\twriter.write(\"hiddenPurchaseItems\", _hiddenPurchaseItemsMap);\n\twriter.write(\"customRuleCraftDeployments\", _customRuleCraftDeployments);\n\t_alienStrategy->save(writer[\"alienStrategy\"]);\n\n\tsaveVector(writer, _deadSoldiers, \"deadSoldiers\", mod->getScriptGlobal());\n\tfor (int j = 0; j < Options::oxceMaxEquipmentLayoutTemplates; ++j)\n\t{\n\t\tif (!_globalEquipmentLayout[j].empty())\n\t\t\tsaveVector(writer, _globalEquipmentLayout[j], writer.saveString(\"globalEquipmentLayout\" + std::to_string(j)));\n\t\tif (!_globalEquipmentLayoutName[j].empty())\n\t\t\twriter.write(writer.saveString(\"globalEquipmentLayoutName\" + std::to_string(j)), _globalEquipmentLayoutName[j]);\n\t\tif (!_globalEquipmentLayoutArmor[j].empty())\n\t\t\twriter.write(writer.saveString(\"globalEquipmentLayoutArmor\" + std::to_string(j)), _globalEquipmentLayoutArmor[j]);\n\t}\n\tfor (int j = 0; j < MAX_CRAFT_LOADOUT_TEMPLATES; ++j)\n\t{\n\t\tif (!_globalCraftLoadout[j]->getContents()->empty())\n\t\t\t_globalCraftLoadout[j]->save(writer[writer.saveString(\"globalCraftLoadout\" + std::to_string(j))]);\n\t\tif (!_globalCraftLoadoutName[j].empty())\n\t\t\twriter.write(writer.saveString(\"globalCraftLoadoutName\" + std::to_string(j)), _globalCraftLoadoutName[j]);\n\t}\n\tif (Options::soldierDiaries)\n\t\tsaveVector(writer, _missionStatistics, \"missionStatistics\");\n\n\tif (!_autosales.empty())\n\t{\n\t\tauto autoSales = writer[\"autoSales\"];\n\t\tautoSales.setAsSeq();\n\t\t{\n\t\t\tstd::vector<const RuleItem*> autosalesVector(_autosales.begin(), _autosales.end());\n\t\t\tstd::sort(autosalesVector.begin(), autosalesVector.end(), [&](const RuleItem* a, const RuleItem* b)\n\t\t\t\t{ return a->getType().compare(b->getType()) < 0; });\n\t\t\tfor (const auto* sale : autosalesVector)\n\t\t\t{\n\t\t\t\tautoSales.write(sale->getType());\n\t\t\t}\n\t\t}\n\t}\n\t// snapshot of the user options (just for debugging purposes)\n\tauto optionsWriter = writer[\"options\"];\n\toptionsWriter.setAsMap();\n\tfor (const auto& optionInfo : Options::getOptionInfo())\n\t\toptionInfo.save(optionsWriter);\n\n\tif (_battleGame)\n\t\t_battleGame->save(writer[\"battleGame\"]);\n\t_scriptValues.save(writer.toBase(), mod->getScriptGlobal());\n\n\t// concatenate header + separator + body\n\t// per yaml standard, \"bare documents\" in a yaml \"stream\" can be separated by either a \"document end\" or \"directives end\" marker line\n\tYAML::YamlString headerString = headerWriter.emit();\n\tstd::string directivesEndMarker = \"---\\n\";\n\tYAML::YamlString bodyString = writer.emit();\n\tstd::string finalString;\n\tfinalString.reserve(headerString.yaml.size() + directivesEndMarker.size() + bodyString.yaml.size());\n\tfinalString += headerString.yaml;\n\tfinalString\t+= directivesEndMarker;\n\tfinalString += bodyString.yaml;\n\n\tstd::string filepath = Options::getMasterUserFolder() + filename;\n\tif (!CrossPlatform::writeFile(filepath, finalString))\n\t{\n\t\tthrow Exception(\"Failed to save \" + filepath);\n\t}\n}\n\n/**\n * Returns the game's name shown in Save screens.\n * @return Save name.\n */\nstd::string SavedGame::getName() const\n{\n\treturn _name;\n}\n\n/**\n * Changes the game's name shown in Save screens.\n * @param name New name.\n */\nvoid SavedGame::setName(const std::string &name)\n{\n\t_name = name;\n}\n\n/**\n * Returns the game's difficulty level.\n * @return Difficulty level.\n */\nGameDifficulty SavedGame::getDifficulty() const\n{\n\treturn _difficulty;\n}\n\n/**\n * Changes the game's difficulty to a new level.\n * @param difficulty New difficulty.\n */\nvoid SavedGame::setDifficulty(GameDifficulty difficulty)\n{\n\t_difficulty = difficulty;\n}\n\n/**\n * Returns the game's difficulty coefficient based\n * on the current level.\n * @return Difficulty coefficient.\n */\nint SavedGame::getDifficultyCoefficient() const\n{\n\treturn Mod::DIFFICULTY_COEFFICIENT[std::min((int)_difficulty, 4)];\n}\n\n/**\n * Returns the game's sell price coefficient based\n * on the current difficulty level.\n * @return Sell price coefficient.\n */\nint SavedGame::getSellPriceCoefficient() const\n{\n\treturn Mod::SELL_PRICE_COEFFICIENT[std::min((int)_difficulty, 4)];\n}\n\n/**\n * Returns the game's buy price coefficient based\n * on the current difficulty level.\n * @return Buy price coefficient.\n */\nint SavedGame::getBuyPriceCoefficient() const\n{\n\treturn Mod::BUY_PRICE_COEFFICIENT[std::min((int)_difficulty, 4)];\n}\n\n/**\n * Returns the game's current ending.\n * @return Ending state.\n */\nGameEnding SavedGame::getEnding() const\n{\n\treturn _end;\n}\n\n/**\n * Changes the game's current ending.\n * @param end New ending.\n */\nvoid SavedGame::setEnding(GameEnding end)\n{\n\t_end = end;\n}\n\n/**\n * Returns if the game is set to ironman mode.\n * Ironman games cannot be manually saved.\n * @return Tony Stark\n */\nbool SavedGame::isIronman() const\n{\n\treturn _ironman;\n}\n\n/**\n * Changes if the game is set to ironman mode.\n * Ironman games cannot be manually saved.\n * @param ironman Tony Stark\n */\nvoid SavedGame::setIronman(bool ironman)\n{\n\t_ironman = ironman;\n}\n\n/**\n * Returns the player's current funds.\n * @return Current funds.\n */\nint64_t SavedGame::getFunds() const\n{\n\treturn _funds.back();\n}\n\n/**\n * Returns the player's funds for the last 12 months.\n * @return funds.\n */\nstd::vector<int64_t> &SavedGame::getFundsList()\n{\n\treturn _funds;\n}\n\n/**\n * Changes the player's funds to a new value.\n * @param funds New funds.\n */\nvoid SavedGame::setFunds(int64_t funds)\n{\n\tif (_funds.back() > funds)\n\t{\n\t\t_expenditures.back() += _funds.back() - funds;\n\t}\n\telse\n\t{\n\t\t_incomes.back() += funds - _funds.back();\n\t}\n\t_funds.back() = funds;\n}\n\n/**\n * Returns the current longitude of the Geoscape globe.\n * @return Longitude.\n */\ndouble SavedGame::getGlobeLongitude() const\n{\n\treturn _globeLon;\n}\n\n/**\n * Changes the current longitude of the Geoscape globe.\n * @param lon Longitude.\n */\nvoid SavedGame::setGlobeLongitude(double lon)\n{\n\t_globeLon = lon;\n}\n\n/**\n * Returns the current latitude of the Geoscape globe.\n * @return Latitude.\n */\ndouble SavedGame::getGlobeLatitude() const\n{\n\treturn _globeLat;\n}\n\n/**\n * Changes the current latitude of the Geoscape globe.\n * @param lat Latitude.\n */\nvoid SavedGame::setGlobeLatitude(double lat)\n{\n\t_globeLat = lat;\n}\n\n/**\n * Returns the current zoom level of the Geoscape globe.\n * @return Zoom level.\n */\nint SavedGame::getGlobeZoom() const\n{\n\treturn _globeZoom;\n}\n\n/**\n * Changes the current zoom level of the Geoscape globe.\n * @param zoom Zoom level.\n */\nvoid SavedGame::setGlobeZoom(int zoom)\n{\n\t_globeZoom = zoom;\n}\n\n/**\n * Gives the player his monthly funds, taking in account\n * all maintenance and profit costs.\n */\nvoid SavedGame::monthlyFunding()\n{\n\tint countryFunding = getCountryFunding();\n\tint baseMaintenance = getBaseMaintenance();\n\t_funds.back() += (countryFunding - baseMaintenance);\n\t_funds.push_back(_funds.back());\n\t_maintenance.back() = baseMaintenance;\n\t_maintenance.push_back(0);\n\t_incomes.push_back(countryFunding);\n\t_expenditures.push_back(baseMaintenance);\n\t_researchScores.push_back(0);\n\n\tif (_incomes.size() > 12)\n\t\t_incomes.erase(_incomes.begin());\n\tif (_expenditures.size() > 12)\n\t\t_expenditures.erase(_expenditures.begin());\n\tif (_researchScores.size() > 12)\n\t\t_researchScores.erase(_researchScores.begin());\n\tif (_funds.size() > 12)\n\t\t_funds.erase(_funds.begin());\n\tif (_maintenance.size() > 12)\n\t\t_maintenance.erase(_maintenance.begin());\n}\n\n/**\n * Returns the current time of the game.\n * @return Pointer to the game time.\n */\nGameTime *SavedGame::getTime() const\n{\n\treturn _time;\n}\n\n/**\n * Changes the current time of the game.\n * @param time Game time.\n */\nvoid SavedGame::setTime(const GameTime& time)\n{\n\t_time = new GameTime(time);\n}\n\n/**\n * Returns the latest ID for the specified object\n * and increases it.\n * @param name Object name.\n * @return Latest ID number.\n */\nint SavedGame::getId(const std::string &name)\n{\n\tauto i = _ids.find(name);\n\tif (i != _ids.end())\n\t{\n\t\treturn i->second++;\n\t}\n\telse\n\t{\n\t\t_ids[name] = 1;\n\t\treturn _ids[name]++;\n\t}\n}\n\n/**\n * Returns the last used ID for the specified object.\n * @param name Object name.\n * @return Last used ID number.\n */\nint SavedGame::getLastId(const std::string& name)\n{\n\tauto i = _ids.find(name);\n\tif (i != _ids.end())\n\t{\n\t\treturn std::max(1, i->second - 1);\n\t}\n\telse\n\t{\n\t\treturn 0;\n\t}\n}\n\n/**\n * Increase a custom counter.\n * @param name Counter name.\n */\nvoid SavedGame::increaseCustomCounter(const std::string& name)\n{\n\tif (!name.empty())\n\t{\n\t\tauto i = _ids.find(name);\n\t\tif (i != _ids.end())\n\t\t{\n\t\t\ti->second++;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_ids[name] = 2; // not a typo\n\t\t}\n\t}\n}\n\n/**\n * Decrease a custom counter.\n * @param name Counter name.\n */\nvoid SavedGame::decreaseCustomCounter(const std::string& name)\n{\n\tif (!name.empty())\n\t{\n\t\tauto i = _ids.find(name);\n\t\tif (i != _ids.end())\n\t\t{\n\t\t\t// don't go below \"zero\" (which is saved as one)\n\t\t\tif (i->second > 1)\n\t\t\t{\n\t\t\t\ti->second--;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_ids[name] = 1; // not a typo\n\t\t}\n\t}\n}\n\n/**\n* Resets the list of unique object IDs.\n* @param ids New ID list.\n*/\nconst std::map<std::string, int> &SavedGame::getAllIds() const\n{\n\treturn _ids;\n}\n\n/**\n * Resets the list of unique object IDs.\n * @param ids New ID list.\n */\nvoid SavedGame::setAllIds(const std::map<std::string, int> &ids)\n{\n\t_ids = ids;\n}\n\n/**\n * Returns the list of countries in the game world.\n * @return Pointer to country list.\n */\nstd::vector<Country*> *SavedGame::getCountries()\n{\n\treturn &_countries;\n}\n\n/**\n * Adds up the monthly funding of all the countries.\n * @return Total funding.\n */\nint SavedGame::getCountryFunding() const\n{\n\tint total = 0;\n\tfor (auto* country : _countries)\n\t{\n\t\ttotal += country->getFunding().back();\n\t}\n\treturn total;\n}\n\n/**\n * Returns the list of world regions.\n * @return Pointer to region list.\n */\nstd::vector<Region*> *SavedGame::getRegions()\n{\n\treturn &_regions;\n}\n\n/**\n * Returns the list of player bases.\n * @return Pointer to base list.\n */\nstd::vector<Base*> *SavedGame::getBases()\n{\n\treturn &_bases;\n}\n\n/**\n * Returns the last selected player base.\n * @return Pointer to base.\n */\nBase *SavedGame::getSelectedBase()\n{\n\t// in case a base was destroyed or something...\n\tif (_selectedBase < _bases.size())\n\t{\n\t\treturn _bases.at(_selectedBase);\n\t}\n\telse\n\t{\n\t\treturn _bases.front();\n\t}\n}\n\n/**\n * Sets the last selected player base.\n * @param base number of the base.\n */\nvoid SavedGame::setSelectedBase(size_t base)\n{\n\t_selectedBase = base;\n}\n\n/**\n * Returns an immutable list of player bases.\n * @return Pointer to base list.\n */\nconst std::vector<Base*> *SavedGame::getBases() const\n{\n\treturn &_bases;\n}\n\n/**\n * Adds up the monthly maintenance of all the bases.\n * @return Total maintenance.\n */\nint SavedGame::getBaseMaintenance() const\n{\n\tint total = 0;\n\tfor (const auto* xbase : _bases)\n\t{\n\t\ttotal += xbase->getMonthlyMaintenace();\n\t}\n\treturn total;\n}\n\n/**\n * Returns the list of alien UFOs.\n * @return Pointer to UFO list.\n */\nstd::vector<Ufo*> *SavedGame::getUfos()\n{\n\treturn &_ufos;\n}\n\n/**\n * Returns the list of alien UFOs.\n * @return Pointer to UFO list.\n */\nconst std::vector<Ufo*> *SavedGame::getUfos() const\n{\n\treturn &_ufos;\n}\n\n/**\n * Returns the list of craft waypoints.\n * @return Pointer to waypoint list.\n */\nstd::vector<Waypoint*> *SavedGame::getWaypoints()\n{\n\treturn &_waypoints;\n}\n\n/**\n * Returns the list of mission sites.\n * @return Pointer to mission site list.\n */\nstd::vector<MissionSite*> *SavedGame::getMissionSites()\n{\n\treturn &_missionSites;\n}\n\n/**\n * Get pointer to the battleGame object.\n * @return Pointer to the battleGame object.\n */\nSavedBattleGame *SavedGame::getSavedBattle()\n{\n\treturn _battleGame;\n}\n\n/**\n * Set battleGame object.\n * @param battleGame Pointer to the battleGame object.\n */\nvoid SavedGame::setBattleGame(SavedBattleGame *battleGame)\n{\n\tdelete _battleGame;\n\t_battleGame = battleGame;\n}\n\n/**\n * Sets the status of a ufopedia rule\n * @param ufopediaRule The rule ID\n * @param newStatus Status to be set\n */\nvoid SavedGame::setUfopediaRuleStatus(const std::string &ufopediaRule, int newStatus)\n{\n\t_ufopediaRuleStatus[ufopediaRule] = newStatus;\n}\n\n/**\n * Sets the status of a manufacture rule\n * @param manufactureRule The rule ID\n * @param newStatus Status to be set\n */\nvoid SavedGame::setManufactureRuleStatus(const std::string &manufactureRule, int newStatus)\n{\n\t_manufactureRuleStatus[manufactureRule] = newStatus;\n}\n\n/**\n* Sets the status of a research rule\n* @param researchRule The rule ID\n* @param newStatus Status to be set\n*/\nvoid SavedGame::setResearchRuleStatus(const std::string &researchRule, int newStatus)\n{\n\t_researchRuleStatus[researchRule] = newStatus;\n}\n\n/**\n * Sets the hidden status of a purchase item\n * @param purchase item name\n * @param hidden\n */\nvoid SavedGame::setHiddenPurchaseItemsStatus(const std::string &itemName, bool hidden)\n{\n\t_hiddenPurchaseItemsMap[itemName] = hidden;\n}\n\n/**\n * Get the map of hidden items\n * @return map\n */\nconst std::map<std::string, bool> &SavedGame::getHiddenPurchaseItems()\n{\n\treturn _hiddenPurchaseItemsMap;\n}\n\n/*\n * Selects a \"getOneFree\" topic for the given research rule.\n * @param research Pointer to the given research rule.\n * @return Pointer to the selected getOneFree topic. Nullptr, if nothing was selected.\n */\nconst RuleResearch* SavedGame::selectGetOneFree(const RuleResearch* research)\n{\n\tif (!research->getGetOneFree().empty() || !research->getGetOneFreeProtected().empty())\n\t{\n\t\tstd::vector<const RuleResearch*> possibilities;\n\t\tfor (auto* free : research->getGetOneFree())\n\t\t{\n\t\t\tif (isResearchRuleStatusDisabled(free->getName()))\n\t\t\t{\n\t\t\t\tcontinue; // skip disabled topics\n\t\t\t}\n\t\t\tif (!isResearched(free, false))\n\t\t\t{\n\t\t\t\tpossibilities.push_back(free);\n\t\t\t}\n\t\t}\n\t\tfor (auto& pair : research->getGetOneFreeProtected())\n\t\t{\n\t\t\tif (isResearched(pair.first, false))\n\t\t\t{\n\t\t\t\tfor (auto* res : pair.second)\n\t\t\t\t{\n\t\t\t\t\tif (isResearchRuleStatusDisabled(res->getName()))\n\t\t\t\t\t{\n\t\t\t\t\t\tcontinue; // skip disabled topics\n\t\t\t\t\t}\n\t\t\t\t\tif (!isResearched(res, false))\n\t\t\t\t\t{\n\t\t\t\t\t\tpossibilities.push_back(res);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (!possibilities.empty())\n\t\t{\n\t\t\tsize_t pick = 0;\n\t\t\tif (!research->sequentialGetOneFree())\n\t\t\t{\n\t\t\t\tpick = RNG::generate(0, possibilities.size() - 1);\n\t\t\t}\n\t\t\tauto* ret = possibilities.at(pick);\n\t\t\treturn ret;\n\t\t}\n\t}\n\treturn nullptr;\n}\n\n/*\n * Checks for and removes a research project from the \"already discovered\" list\n * @param research is the project we are checking for and removing, if necessary.\n */\nvoid SavedGame::removeDiscoveredResearch(const RuleResearch * research)\n{\n\tauto r = std::find(_discovered.begin(), _discovered.end(), research);\n\tif (r != _discovered.end())\n\t{\n\t\t_discovered.erase(r);\n\t}\n}\n\n/**\n * Make all research discovered (used in New Battle)\n * @param mod the game Mod\n */\nvoid SavedGame::makeAllResearchDiscovered(const Mod* mod)\n{\n\tfor (auto& pair : mod->getResearchMap())\n\t{\n\t\t_discovered.push_back(pair.second);\n\t}\n\tsortReserchVector(_discovered);\n}\n\n/**\n * Add a ResearchProject to the list of already discovered ResearchProject\n * @param research The newly found ResearchProject\n * @param mod the game Mod\n * @param base the base, in which the project was finished\n * @param score should the score be awarded or not?\n */\nvoid SavedGame::addFinishedResearch(const RuleResearch * research, const Mod * mod, Base * base, bool score)\n{\n\tif (isResearchRuleStatusDisabled(research->getName()))\n\t{\n\t\treturn;\n\t}\n\n\t// Not really a queue in C++ terminology (we don't need or want pop_front())\n\tstd::vector<const RuleResearch *> queue;\n\tqueue.push_back(research);\n\n\tsize_t currentQueueIndex = 0;\n\twhile (queue.size() > currentQueueIndex)\n\t{\n\t\tconst RuleResearch *currentQueueItem = queue.at(currentQueueIndex);\n\n\t\t// 1. Find out and remember if the currentQueueItem has any undiscovered non-disabled \"protected unlocks\" or \"getOneFree\"\n\t\tbool hasUndiscoveredProtectedUnlocks = hasUndiscoveredProtectedUnlock(currentQueueItem);\n\t\tbool hasAnyUndiscoveredGetOneFrees = hasUndiscoveredGetOneFree(currentQueueItem, false);\n\n\t\t// 2. If the currentQueueItem was *not* already discovered before, add it to discovered research\n\t\tbool checkRelatedZeroCostTopics = true;\n\t\tif (!isResearched(currentQueueItem, false))\n\t\t{\n\t\t\tif (!research->isRepeatable())\n\t\t\t{\n\t\t\t\t_discovered.push_back(currentQueueItem);\n\t\t\t\tsortReserchVector(_discovered);\n\t\t\t}\n\n\t\t\tif (currentQueueItem != research)\n\t\t\t{\n\t\t\t\tResearchDiaryEntry* entry = new ResearchDiaryEntry(currentQueueItem);\n\t\t\t\tentry->setDate(_time);\n\t\t\t\tentry->source.type = DiscoverySourceType::FREE_AFTER;\n\t\t\t\tentry->source.research = research;\n\t\t\t\tentry->source.name = research->getName();\n\t\t\t\taddResearchDiaryEntry(entry);\n\t\t\t}\n\n\t\t\tif (!hasUndiscoveredProtectedUnlocks && !hasAnyUndiscoveredGetOneFrees)\n\t\t\t{\n\t\t\t\t// If the currentQueueItem can't tell you anything anymore, remove it from popped research\n\t\t\t\t// Note: this is for optimisation purposes only, functionally it is *not* required...\n\t\t\t\t// ... removing it prematurely leads to bugs, maybe we should not do it at all?\n\t\t\t\tremovePoppedResearch(currentQueueItem);\n\t\t\t}\n\t\t\tif (score)\n\t\t\t{\n\t\t\t\taddResearchScore(currentQueueItem->getPoints());\n\t\t\t}\n\t\t\t// process \"disables\"\n\t\t\tfor (const auto* dis : currentQueueItem->getDisabled())\n\t\t\t{\n\t\t\t\tremoveDiscoveredResearch(dis); // unresearch\n\t\t\t\tsetResearchRuleStatus(dis->getName(), RuleResearch::RESEARCH_STATUS_DISABLED); // mark as permanently disabled\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// If the currentQueueItem *was* already discovered before, check if it has any undiscovered \"protected unlocks\".\n\t\t\t// If not, all zero-cost topics have already been processed before (during the first discovery)\n\t\t\t// and we can basically terminate here (i.e. skip step 3.).\n\t\t\tif (!hasUndiscoveredProtectedUnlocks)\n\t\t\t{\n\t\t\t\tcheckRelatedZeroCostTopics = false;\n\t\t\t}\n\t\t}\n\n\t\t// process \"re-enables\": https://openxcom.org/forum/index.php?topic=12071.0\n\t\tfor (const auto* ree : currentQueueItem->getReenabled())\n\t\t{\n\t\t\tif (isResearchRuleStatusDisabled(ree->getName()))\n\t\t\t{\n\t\t\t\tsetResearchRuleStatus(ree->getName(), RuleResearch::RESEARCH_STATUS_NEW); // reset status\n\t\t\t}\n\t\t}\n\n\t\t// 3. If currentQueueItem is completed for the *first* time, or if it has any undiscovered \"protected unlocks\",\n\t\t// process all related zero-cost topics\n\t\tif (checkRelatedZeroCostTopics)\n\t\t{\n\t\t\t// 3a. Gather all available research projects\n\t\t\tstd::vector<RuleResearch *> availableResearch;\n\t\t\tif (base)\n\t\t\t{\n\t\t\t\t// Note: even if two different but related projects are finished in two different bases at the same time,\n\t\t\t\t// the algorithm is robust enough to treat them *sequentially* (i.e. as if one was researched first and the other second),\n\t\t\t\t// thus calling this method for *one* base only is enough\n\t\t\t\tgetAvailableResearchProjects(availableResearch, mod, base);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// Used in vanilla save converter only\n\t\t\t\tgetAvailableResearchProjects(availableResearch, mod, 0);\n\t\t\t}\n\n\t\t\t// 3b. Iterate through all available projects and add zero-cost projects to the processing queue\n\t\t\tfor (const RuleResearch* projectToTest : availableResearch)\n\t\t\t{\n\t\t\t\t// We are only interested in zero-cost projects!\n\t\t\t\tif (projectToTest->getCost() == 0)\n\t\t\t\t{\n\t\t\t\t\t// We are only interested in *new* projects (i.e. not processed or scheduled for processing yet)\n\t\t\t\t\tbool isAlreadyInTheQueue = false;\n\t\t\t\t\tfor (const RuleResearch* res : queue)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (res->getName() == projectToTest->getName())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tisAlreadyInTheQueue = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!isAlreadyInTheQueue)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (projectToTest->getRequirements().empty())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// no additional checks for \"unprotected\" topics\n\t\t\t\t\t\t\tqueue.push_back(projectToTest);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// for \"protected\" topics, we need to check if the currentQueueItem can unlock it or not\n\t\t\t\t\t\t\tfor (const auto* unl : currentQueueItem->getUnlocked())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (projectToTest == unl)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tqueue.push_back(projectToTest);\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// 4. process remaining items in the queue\n\t\t++currentQueueIndex;\n\t}\n}\n\nvoid SavedGame::addResearchDiaryEntry(ResearchDiaryEntry* entry)\n{\n\t_researchDiary.push_back(entry);\n}\n\n/**\n *  Returns the list of already discovered ResearchProject\n * @return the list of already discovered ResearchProject\n */\nconst std::vector<const RuleResearch *> & SavedGame::getDiscoveredResearch() const\n{\n\treturn _discovered;\n}\n\n/**\n * Does this item correspond to at least one research topic that can be researched now or in the future?\n */\nbool SavedGame::isResearchable(const RuleItem* item, const Mod* mod) const\n{\n\tfor (const auto& pair : mod->getResearchMap())\n\t{\n\t\tif (pair.second->needItem() && pair.second->getNeededItem() == item)\n\t\t{\n\t\t\t// This research topic is \"permanently\" disabled, ignore it!\n\t\t\tif (isResearchRuleStatusDisabled(pair.first))\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (isResearched(pair.second, false))\n\t\t\t{\n\t\t\t\tif (hasUndiscoveredGetOneFree(pair.second, false))\n\t\t\t\t{\n\t\t\t\t\t// This research topic still has some more undiscovered non-disabled \"getOneFree\" topics, keep it!\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\telse if (hasUndiscoveredProtectedUnlock(pair.second))\n\t\t\t\t{\n\t\t\t\t\t// This research topic still has one or more undiscovered non-disabled \"protected unlocks\", keep it!\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// This topic can't give you anything else anymore, ignore it!\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// This research topic is not yet researched, keep it!\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn false;\n}\n\n/**\n * Get the list of RuleResearch which can be researched in a Base.\n * @param projects the list of ResearchProject which are available.\n * @param mod the game Mod\n * @param base a pointer to a Base\n * @param considerDebugMode Should debug mode be considered or not.\n */\nvoid SavedGame::getAvailableResearchProjects(std::vector<RuleResearch *> &projects, const Mod *mod, Base *base, bool considerDebugMode) const\n{\n\t// This list is used for topics that can be researched even if *not all* dependencies have been discovered yet (e.g. STR_ALIEN_ORIGINS)\n\t// Note: all requirements of such topics *have to* be discovered though! This will be handled elsewhere.\n\tstd::vector<const RuleResearch *> unlocked;\n\tfor (const auto* research : _discovered)\n\t{\n\t\tfor (const auto* unl : research->getUnlocked())\n\t\t{\n\t\t\tunlocked.push_back(unl);\n\t\t}\n\t\tsortReserchVector(unlocked);\n\t}\n\n\t// Create a list of research topics available for research in the given base\n\tfor (const auto& pair : mod->getResearchMap())\n\t{\n\t\t// This research topic is permanently disabled, ignore it!\n\t\tif (isResearchRuleStatusDisabled(pair.first))\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\n\t\tRuleResearch *research = pair.second;\n\n\t\tif ((considerDebugMode && _debug) || haveReserchVector(unlocked, research))\n\t\t{\n\t\t\t// Empty, these research topics are on the \"unlocked list\", *don't* check the dependencies!\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// These items are not on the \"unlocked list\", we must check if \"dependencies\" are satisfied!\n\t\t\tif (!isResearched(research->getDependencies(), considerDebugMode))\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\t// Check if \"requires\" are satisfied\n\t\t// IMPORTANT: research topics with \"requires\" will NEVER be directly visible to the player anyway\n\t\t//   - there is an additional filter in NewResearchListState::fillProjectList(), see comments there for more info\n\t\t//   - there is an additional filter in NewPossibleResearchState::NewPossibleResearchState()\n\t\t//   - we do this check for other functionality using this method, namely SavedGame::addFinishedResearch()\n\t\t//     - Note: when called from there, parameter considerDebugMode = false\n\t\tif (!isResearched(research->getRequirements(), considerDebugMode))\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Remove the already researched topics from the list *UNLESS* they can still give you something more\n\t\tif (isResearched(research->getName(), false))\n\t\t{\n\t\t\tif (hasUndiscoveredGetOneFree(research, true))\n\t\t\t{\n\t\t\t\t// This research topic still has some more undiscovered non-disabled and *AVAILABLE* \"getOneFree\" topics, keep it!\n\t\t\t}\n\t\t\telse if (hasUndiscoveredProtectedUnlock(research))\n\t\t\t{\n\t\t\t\t// This research topic still has one or more undiscovered non-disabled \"protected unlocks\", keep it!\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// This topic can't give you anything else anymore, ignore it!\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\tif (base)\n\t\t{\n\t\t\t// Check if this topic is already being researched in the given base\n\t\t\tbool found = false;\n\t\t\tfor (auto* ongoing : base->getResearch())\n\t\t\t{\n\t\t\t\tif (ongoing->getRules() == research)\n\t\t\t\t{\n\t\t\t\t\tfound = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (found)\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Check for needed item in the given base\n\t\t\tif (research->needItem() && base->getStorageItems()->getItem(research->getNeededItem()) == 0)\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Check for required buildings/functions in the given base\n\t\t\tif ((~base->getProvidedBaseFunc({}) & research->getRequireBaseFunc()).any())\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// Used in vanilla save converter only\n\t\t\tif (research->needItem() && research->getCost() == 0)\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\t// Hallelujah, all checks passed, add the research topic to the list\n\t\tprojects.push_back(research);\n\t}\n}\n\n/**\n * Get the list of newly available research projects once a ResearchProject has been completed.\n * @param before the list of available RuleResearch before completing new research.\n * @param after the list of available RuleResearch after completing new research.\n * @param diff the list of newly available RuleResearch after completing new research (after - before).\n */\nvoid SavedGame::getNewlyAvailableResearchProjects(std::vector<RuleResearch *> & before, std::vector<RuleResearch *> & after, std::vector<RuleResearch *> & diff) const\n{\n\t// History lesson:\n\t// Completely rewritten the original recursive algorithm, because it was inefficient, unreadable and wrong\n\t// a/ inefficient: it could call SavedGame::getAvailableResearchProjects() way too many times\n\t// b/ unreadable: because of recursion\n\t// c/ wrong: could end in an endless loop! in two different ways! (not in vanilla, but in mods)\n\n\t// Note:\n\t// We could move the sorting of \"before\" vector right after its creation to optimize a little bit more.\n\t// But sorting a short list is negligible compared to other operations we had to do to get to this point.\n\t// So I decided to leave it here, so that it's 100% clear what's going on.\n\tsortReserchVector(before);\n\tsortReserchVector(after);\n\tstd::set_difference(after.begin(), after.end(), before.begin(), before.end(), std::inserter(diff, diff.begin()), researchLess);\n}\n\n/**\n * Get the list of RuleManufacture which can be manufacture in a Base.\n * @param productions the list of Productions which are available.\n * @param mod the Game Mod\n * @param base a pointer to a Base\n */\nvoid SavedGame::getAvailableProductions (std::vector<RuleManufacture *> & productions, const Mod * mod, Base * base, ManufacturingFilterType filter) const\n{\n\tconst auto& baseProductions = base->getProductions();\n\tRuleBaseFacilityFunctions baseFunc = base->getProvidedBaseFunc({});\n\n\tfor (const auto& manuf : mod->getManufactureList())\n\t{\n\t\tRuleManufacture *m = mod->getManufacture(manuf);\n\t\tif (!isResearched(m->getRequirements()))\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\t\tbool found = false;\n\t\tfor (auto* ongoing : baseProductions)\n\t\t{\n\t\t\tif (ongoing->getRules() == m)\n\t\t\t{\n\t\t\t\tfound = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (found)\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\t\tif ((~baseFunc & m->getRequireBaseFunc()).any())\n\t\t{\n\t\t\tif (filter != MANU_FILTER_FACILITY_REQUIRED)\n\t\t\t\tcontinue;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (filter == MANU_FILTER_FACILITY_REQUIRED)\n\t\t\t\tcontinue;\n\t\t}\n\n\t\tproductions.push_back(m);\n\t}\n}\n\n/**\n * Get the list of newly available manufacture projects once a ResearchProject has been completed. This function check for fake ResearchProject.\n * @param dependables the list of RuleManufacture which are now available.\n * @param research The RuleResearch which has just been discovered\n * @param mod the Game Mod\n * @param base a pointer to a Base\n */\nvoid SavedGame::getDependableManufacture (std::vector<RuleManufacture *> & dependables, const RuleResearch *research, const Mod * mod, Base *) const\n{\n\tfor (const auto& manuf : mod->getManufactureList())\n\t{\n\t\t// don't show previously unlocked (and seen!) manufacturing topics\n\t\tauto i = _manufactureRuleStatus.find(manuf);\n\t\tif (i != _manufactureRuleStatus.end())\n\t\t{\n\t\t\tif (i->second != RuleManufacture::MANU_STATUS_NEW)\n\t\t\t\tcontinue;\n\t\t}\n\n\t\tRuleManufacture *m = mod->getManufacture(manuf);\n\t\tconst auto& reqs = m->getRequirements();\n\t\tif (isResearched(reqs) && std::find(reqs.begin(), reqs.end(), research) != reqs.end())\n\t\t{\n\t\t\tdependables.push_back(m);\n\t\t}\n\t}\n}\n\n/**\n * Get the list of RuleSoldierTransformation which can occur at a base.\n * @param transformations the list of Transformations which are available.\n * @param mod the Game Mod\n * @param base a pointer to a Base\n */\nvoid SavedGame::getAvailableTransformations (std::vector<RuleSoldierTransformation *> & transformations, const Mod * mod, Base * base) const\n{\n\tauto& list = mod->getSoldierTransformationList();\n\tif (list.empty())\n\t{\n\t\treturn;\n\t}\n\n\tRuleBaseFacilityFunctions baseFunc = base->getProvidedBaseFunc({});\n\n\tfor (const auto& transformType : list)\n\t{\n\t\tRuleSoldierTransformation *m = mod->getSoldierTransformation(transformType);\n\t\tif (!isResearched(m->getRequiredResearch()))\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\t\tif ((~baseFunc & m->getRequiredBaseFuncs()).any())\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\n\t\ttransformations.push_back(m);\n\t}\n}\n\n/**\n * Get the list of newly available items to purchase once a ResearchProject has been completed.\n * @param dependables the list of RuleItem which are now available.\n * @param research The RuleResearch which has just been discovered\n * @param mod the Game Mod\n */\nvoid SavedGame::getDependablePurchase(std::vector<RuleItem *> & dependables, const RuleResearch *research, const Mod * mod) const\n{\n\tfor (const auto& itemType : mod->getItemsList())\n\t{\n\t\tRuleItem *item = mod->getItem(itemType);\n\t\tif (item->getBuyCost() != 0)\n\t\t{\n\t\t\tconst auto& reqs = item->getRequirements();\n\t\t\tbool found = std::find(reqs.begin(), reqs.end(), research) != reqs.end();\n\t\t\tconst auto& reqsBuy = item->getBuyRequirements();\n\t\t\tbool foundBuy = std::find(reqsBuy.begin(), reqsBuy.end(), research) != reqsBuy.end();\n\t\t\tif (found || foundBuy)\n\t\t\t{\n\t\t\t\tif (isResearched(item->getBuyRequirements()) && isResearched(item->getRequirements()))\n\t\t\t\t{\n\t\t\t\t\tdependables.push_back(item);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Get the list of newly available craft to purchase/rent once a ResearchProject has been completed.\n * @param dependables the list of RuleCraft which are now available.\n * @param research The RuleResearch which has just been discovered\n * @param mod the Game Mod\n */\nvoid SavedGame::getDependableCraft(std::vector<RuleCraft *> & dependables, const RuleResearch *research, const Mod * mod) const\n{\n\tfor (const auto& craftType : mod->getCraftsList())\n\t{\n\t\tRuleCraft *craftItem = mod->getCraft(craftType);\n\t\tif (craftItem->getBuyCost() != 0)\n\t\t{\n\t\t\tconst auto& reqs = craftItem->getRequirements();\n\t\t\tif (std::find(reqs.begin(), reqs.end(), research->getName()) != reqs.end())\n\t\t\t{\n\t\t\t\tif (isResearched(craftItem->getRequirements()))\n\t\t\t\t{\n\t\t\t\t\tdependables.push_back(craftItem);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Get the list of newly available facilities to build once a ResearchProject has been completed.\n * @param dependables the list of RuleBaseFacility which are now available.\n * @param research The RuleResearch which has just been discovered\n * @param mod the Game Mod\n */\nvoid SavedGame::getDependableFacilities(std::vector<RuleBaseFacility *> & dependables, const RuleResearch *research, const Mod * mod) const\n{\n\tfor (const auto& facType : mod->getBaseFacilitiesList())\n\t{\n\t\tRuleBaseFacility *facilityItem = mod->getBaseFacility(facType);\n\t\tconst auto& reqs = facilityItem->getRequirements();\n\t\tif (std::find(reqs.begin(), reqs.end(), research->getName()) != reqs.end())\n\t\t{\n\t\t\tif (isResearched(facilityItem->getRequirements()))\n\t\t\t{\n\t\t\t\tdependables.push_back(facilityItem);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Gets the status of a ufopedia rule.\n * @param ufopediaRule Ufopedia rule ID.\n * @return Status (0=new, 1=normal).\n */\nint SavedGame::getUfopediaRuleStatus(const std::string &ufopediaRule)\n{\n\treturn _ufopediaRuleStatus[ufopediaRule];\n}\n\n/**\n * Gets the status of a manufacture rule.\n * @param manufactureRule Manufacture rule ID.\n * @return Status (0=new, 1=normal, 2=hidden).\n */\nint SavedGame::getManufactureRuleStatus(const std::string &manufactureRule)\n{\n\treturn _manufactureRuleStatus[manufactureRule];\n}\n\n/**\n * Gets the status of a research rule.\n * @param researchRule Research rule ID.\n * @return Status (0=new, 1=normal, 2=disabled, 3=hidden).\n */\nint SavedGame::getResearchRuleStatus(const std::string &researchRule) const\n{\n\tauto it = _researchRuleStatus.find(researchRule);\n\tif (it != _researchRuleStatus.end())\n\t{\n\t\treturn it->second;\n\t}\n\treturn RuleResearch::RESEARCH_STATUS_NEW; // no status = new\n}\n\n/**\n * Is the research permanently disabled?\n * @param researchRule Research rule ID.\n * @return True, if the research rule status is disabled.\n */\nbool SavedGame::isResearchRuleStatusDisabled(const std::string &researchRule) const\n{\n\tauto it = _researchRuleStatus.find(researchRule);\n\tif (it != _researchRuleStatus.end())\n\t{\n\t\tif (it->second == RuleResearch::RESEARCH_STATUS_DISABLED)\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Returns if a research still has undiscovered non-disabled \"getOneFree\".\n * @param r Research to check.\n * @param checkOnlyAvailableTopics Check only available topics (=topics with discovered prerequisite) or all topics?\n * @return Whether it has any undiscovered non-disabled \"getOneFree\" or not.\n */\nbool SavedGame::hasUndiscoveredGetOneFree(const RuleResearch * r, bool checkOnlyAvailableTopics) const\n{\n\tif (!isResearched(r->getGetOneFree(), false, true))\n\t{\n\t\treturn true; // found something undiscovered (and NOT disabled) already, no need to search further\n\t}\n\telse\n\t{\n\t\t// search through getOneFreeProtected topics too\n\t\tfor (const auto& pair : r->getGetOneFreeProtected())\n\t\t{\n\t\t\tif (checkOnlyAvailableTopics && !isResearched(pair.first, false))\n\t\t\t{\n\t\t\t\t// skip this group, its prerequisite has not been discovered yet\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (!isResearched(pair.second, false, true))\n\t\t\t\t{\n\t\t\t\t\treturn true; // found something undiscovered (and NOT disabled) already, no need to search further\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Returns if a research still has undiscovered non-disabled \"protected unlocks\".\n * @param r Research to check.\n * @return Whether it has any undiscovered non-disabled \"protected unlocks\" or not.\n */\nbool SavedGame::hasUndiscoveredProtectedUnlock(const RuleResearch * r) const\n{\n\t// Note: checking for not yet discovered unlocks protected by \"requires\" (which also implies cost = 0)\n\tfor (const auto* unlock : r->getUnlocked())\n\t{\n\t\tif (isResearchRuleStatusDisabled(unlock->getName()))\n\t\t{\n\t\t\t// ignore all disabled topics (as if they didn't exist)\n\t\t\tcontinue;\n\t\t}\n\t\tif (!unlock->getRequirements().empty())\n\t\t{\n\t\t\tif (!isResearched(unlock, false))\n\t\t\t{\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Returns if a certain research topic has been completed.\n * @param research Research ID.\n * @param considerDebugMode Should debug mode be considered or not.\n * @return Whether it's researched or not.\n */\nbool SavedGame::isResearched(const std::string &research, bool considerDebugMode) const\n{\n\t//if (research.empty())\n\t//\treturn true;\n\tif (considerDebugMode && _debug)\n\t\treturn true;\n\n\treturn haveReserchVector(_discovered, research);\n}\n\nbool SavedGame::isResearched(const RuleResearch *research, bool considerDebugMode) const\n{\n\t//if (research.empty())\n\t//\treturn true;\n\tif (considerDebugMode && _debug)\n\t\treturn true;\n\n\treturn haveReserchVector(_discovered, research);\n}\n\nbool SavedGame::isResearched(const std::vector<std::string> &research, bool considerDebugMode) const\n{\n\tif (research.empty())\n\t\treturn true;\n\tif (considerDebugMode && _debug)\n\t\treturn true;\n\n\tfor (const auto& res : research)\n\t{\n\t\tif (!haveReserchVector(_discovered, res))\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n/**\n * Returns if a certain list of research topics has been completed.\n * @param research List of research IDs.\n * @param considerDebugMode Should debug mode be considered or not.\n * @param skipDisabled Should permanently disabled topics be considered or not.\n * @return Whether it's researched or not.\n */\nbool SavedGame::isResearched(const std::vector<const RuleResearch *> &research, bool considerDebugMode, bool skipDisabled) const\n{\n\tif (research.empty())\n\t\treturn true;\n\tif (considerDebugMode && _debug)\n\t\treturn true;\n\n\tfor (const auto* res : research)\n\t{\n\t\tif (skipDisabled)\n\t\t{\n\t\t\t// ignore all disabled topics (as if they didn't exist)\n\t\t\tif (isResearchRuleStatusDisabled(res->getName()))\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\tif (!haveReserchVector(_discovered, res))\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n/**\n * Returns if a certain item has been obtained, i.e. is present in the base stores or on a craft.\n * Items in transfer, worn by soldiers, etc. are ignored!!\n * @param itemType Item ID.\n * @return Whether it's obtained or not.\n */\nbool SavedGame::isItemObtained(const std::string &itemType, const Mod* mod) const\n{\n\tconst RuleItem* item = mod->getItem(itemType);\n\tif (item)\n\t{\n\t\tfor (auto* xbase : _bases)\n\t\t{\n\t\t\tif (xbase->getStorageItems()->getItem(item) > 0)\n\t\t\t\treturn true;\n\n\t\t\tfor (auto* xcraft : *xbase->getCrafts())\n\t\t\t{\n\t\t\t\tif (xcraft->getItems()->getItem(item) > 0)\n\t\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n/**\n * Returns if a certain facility has been built in any base.\n * @param facilityType facility ID.\n * @return Whether it's been built or not. If false, the facility has not been built in any base.\n */\nbool SavedGame::isFacilityBuilt(const std::string &facilityType) const\n{\n\tfor (auto* xbase : _bases)\n\t{\n\t\tfor (auto* fac : *xbase->getFacilities())\n\t\t{\n\t\t\tif (fac->getBuildTime() == 0 && fac->getRules()->getType() == facilityType)\n\t\t\t{\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Returns if a certain soldier type has been hired in any base.\n * @param soldierType soldier type ID.\n * @return Whether it's been hired (and arrived already) or not.\n */\nbool SavedGame::isSoldierTypeHired(const std::string& soldierType) const\n{\n\tfor (auto* xbase : _bases)\n\t{\n\t\tfor (auto* soldier : *xbase->getSoldiers())\n\t\t{\n\t\t\tif (soldier->getRules()->getType() == soldierType)\n\t\t\t{\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Returns pointer to the Soldier given it's unique ID.\n * @param id A soldier's unique id.\n * @return Pointer to Soldier.\n */\nSoldier *SavedGame::getSoldier(int id) const\n{\n\tfor (auto* xbase : _bases)\n\t{\n\t\tfor (auto* soldier : *xbase->getSoldiers())\n\t\t{\n\t\t\tif (soldier->getId() == id)\n\t\t\t{\n\t\t\t\treturn soldier;\n\t\t\t}\n\t\t}\n\t}\n\tfor (auto* soldier : _deadSoldiers)\n\t{\n\t\tif (soldier->getId() == id)\n\t\t{\n\t\t\treturn soldier;\n\t\t}\n\t}\n\treturn 0;\n}\n\n/**\n * Handles the higher promotions (not the rookie-squaddie ones).\n * @param participants a list of soldiers that were actually present at the battle.\n * @param mod the Game Mod\n * @return Whether or not some promotions happened - to show the promotions screen.\n */\nbool SavedGame::handlePromotions(std::vector<Soldier*> &participants, const Mod *mod)\n{\n\tint soldiersPromoted = 0;\n\tSoldier *highestRanked = 0;\n\tstd::vector<Soldier*> soldiers = getAllActiveSoldiers();\n\tRankCount rankCounts = RankCount(soldiers);\n\n\tint totalSoldiers = rankCounts.getTotalSoldiers();\n\n\tif (rankCounts[RANK_COMMANDER] == 0 && totalSoldiers >= mod->getSoldiersPerRank(RANK_COMMANDER))\n\t{\n\t\thighestRanked = inspectSoldiers(soldiers, participants, RANK_COLONEL);\n\t\tif (highestRanked)\n\t\t{\n\t\t\t// only promote one colonel to commander\n\t\t\thighestRanked->promoteRank();\n\t\t\tsoldiersPromoted++;\n\t\t\trankCounts[RANK_COMMANDER]++;\n\t\t\trankCounts[RANK_COLONEL]--;\n\t\t}\n\t}\n\n\tfor (SoldierRank rank : { RANK_COLONEL, RANK_CAPTAIN, RANK_SERGEANT })\n\t{\n\t\twhile ((totalSoldiers / mod->getSoldiersPerRank(rank)) > rankCounts[rank])\n\t\t{\n\t\t\thighestRanked = inspectSoldiers(soldiers, participants, rank - 1);\n\t\t\tif (highestRanked)\n\t\t\t{\n\t\t\t\thighestRanked->promoteRank();\n\t\t\t\tsoldiersPromoted++;\n\t\t\t\trankCounts[rank]++;\n\t\t\t\trankCounts[(SoldierRank)(rank - 1)]--;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn (soldiersPromoted > 0);\n}\n\n/**\n * Checks how many soldiers of a rank exist and which one has the highest score.\n * @param soldiers full list of live soldiers.\n * @param participants list of participants on this mission.\n * @param rank Rank to inspect.\n * @return the highest ranked soldier\n */\nSoldier *SavedGame::inspectSoldiers(std::vector<Soldier*> &soldiers, std::vector<Soldier*> &participants, int rank)\n{\n\tint highestScore = 0;\n\tSoldier *highestRanked = 0;\n\tfor (auto* soldier : soldiers)\n\t{\n\t\tconst auto& rankStrings = soldier->getRules()->getRankStrings();\n\t\tbool rankIsMatching = (soldier->getRank() == rank);\n\t\tif (!rankStrings.empty())\n\t\t{\n\t\t\t// if rank is matching, but there are no more higher ranks defined for this soldier type, skip this soldier\n\t\t\tif (rankIsMatching && (rank >= (int)rankStrings.size() - 1))\n\t\t\t{\n\t\t\t\trankIsMatching = false;\n\t\t\t}\n\t\t}\n\t\tif (rankIsMatching)\n\t\t{\n\t\t\tint score = getSoldierScore(soldier);\n\t\t\tif (score > highestScore && (!Options::fieldPromotions || std::find(participants.begin(), participants.end(), soldier) != participants.end()))\n\t\t\t{\n\t\t\t\thighestScore = score;\n\t\t\t\thighestRanked = soldier;\n\t\t\t}\n\t\t}\n\t}\n\treturn highestRanked;\n}\n\n/**\n * Gets the (approximate) number of idle days since the soldier's last mission.\n */\nint SavedGame::getSoldierIdleDays(const Soldier *soldier)\n{\n\tint lastMissionId = -1;\n\tint idleDays = 999;\n\n\tif (!soldier->getDiary()->getMissionIdList().empty())\n\t{\n\t\tlastMissionId = soldier->getDiary()->getMissionIdList().back();\n\t}\n\n\tif (lastMissionId == -1)\n\t\treturn idleDays;\n\n\tfor (const auto* missionInfo : _missionStatistics)\n\t{\n\t\tif (missionInfo->id == lastMissionId)\n\t\t{\n\t\t\tidleDays = 0;\n\t\t\tidleDays += (_time->getYear() - missionInfo->time.getYear()) * 365;\n\t\t\tidleDays += (_time->getMonth() - missionInfo->time.getMonth()) * 30;\n\t\t\tidleDays += (_time->getDay() - missionInfo->time.getDay()) * 1;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (idleDays > 999)\n\t\tidleDays = 999;\n\n\treturn idleDays;\n}\n\n/**\n * Evaluate the score of a soldier based on all of his stats, missions and kills.\n * @param soldier the soldier to get a score for.\n * @return this soldier's score.\n */\nint SavedGame::getSoldierScore(Soldier *soldier)\n{\n\tconst UnitStats *s = soldier->getCurrentStats();\n\tint v1 = 2 * s->health + 2 * s->stamina + 4 * s->reactions + 4 * s->bravery;\n\tint v2 = v1 + 3*( s->tu + 2*( s->firing ) );\n\tint v3 = v2 + s->melee + s->throwing + s->strength;\n\tif (s->psiSkill > 0) v3 += s->psiStrength + 2 * s->psiSkill;\n\treturn v3 + 10 * ( soldier->getMissions() + soldier->getKills() );\n}\n\n/**\n  * Returns the list of alien bases.\n  * @return Pointer to alien base list.\n  */\nstd::vector<AlienBase*> *SavedGame::getAlienBases()\n{\n\treturn &_alienBases;\n}\n\n/**\n * Toggles debug mode.\n */\nvoid SavedGame::setDebugMode()\n{\n\t_debug = !_debug;\n}\n\n/**\n * Gets the current debug mode.\n * @return Debug mode.\n */\nbool SavedGame::getDebugMode() const\n{\n\treturn _debug;\n}\n\n/**\n * Find a mission type in the active alien missions.\n * @param region The region string ID.\n * @param objective The active mission objective.\n * @param race The alien race used for more specific search (by type instead of objective). Optional.\n * @return A pointer to the mission, or 0 if no mission matched.\n */\nAlienMission *SavedGame::findAlienMission(const std::string &region, MissionObjective objective, AlienRace* race) const\n{\n\tif (race)\n\t{\n\t\tauto* retalWeights = race->retaliationMissionWeights(_monthsPassed);\n\t\tif (retalWeights)\n\t\t{\n\t\t\tauto retalNames = retalWeights->getNames();\n\t\t\tif (!retalNames.empty())\n\t\t\t{\n\t\t\t\t// if we made it this far, search by type and region\n\t\t\t\tfor (const auto& missionType : retalNames)\n\t\t\t\t{\n\t\t\t\t\tfor (auto* mission : _activeMissions)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (mission->getRules().getType() == missionType && mission->getRegion() == region)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn mission;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (auto* mission : _activeMissions)\n\t{\n\t\tif (mission->getRules().getObjective() == objective && mission->getRegion() == region)\n\t\t{\n\t\t\treturn mission;\n\t\t}\n\t}\n\treturn 0;\n}\n\n/**\n * return the list of monthly maintenance costs\n * @return list of maintenances.\n */\nstd::vector<int64_t> &SavedGame::getMaintenances()\n{\n\treturn _maintenance;\n}\n\n/**\n * adds to this month's research score\n * @param score the amount to add.\n */\nvoid SavedGame::addResearchScore(int score)\n{\n\t_researchScores.back() += score;\n}\n\n/**\n * return the list of research scores\n * @return list of research scores.\n */\nstd::vector<int> &SavedGame::getResearchScores()\n{\n\treturn _researchScores;\n}\n\n/**\n * return the list of income scores\n * @return list of income scores.\n */\nstd::vector<int64_t> &SavedGame::getIncomes()\n{\n\treturn _incomes;\n}\n\n/**\n * return the list of expenditures scores\n * @return list of expenditures scores.\n */\nstd::vector<int64_t> &SavedGame::getExpenditures()\n{\n\treturn _expenditures;\n}\n\n/**\n * return if the player has been\n * warned about poor performance.\n * @return true or false.\n */\nbool SavedGame::getWarned() const\n{\n\treturn _warned;\n}\n\n/**\n * sets the player's \"warned\" status.\n * @param warned set \"warned\" to this.\n */\nvoid SavedGame::setWarned(bool warned)\n{\n\t_warned = warned;\n}\n\n/**\n * Find the region containing this location.\n * @param lon The longitude.\n * @param lat The latitude.\n * @return Pointer to the region, or 0.\n */\nRegion *SavedGame::locateRegion(double lon, double lat) const\n{\n\tRegion* found = nullptr;\n\tfor (auto* region : _regions)\n\t{\n\t\tif (region->getRules()->insideRegion(lon, lat))\n\t\t{\n\t\t\tfound = region;\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (found)\n\t{\n\t\treturn found;\n\t}\n\tLog(LOG_ERROR) << \"Failed to find a region at location [\" << lon << \", \" << lat << \"].\";\n\treturn 0;\n}\n\n/**\n * Find the region containing this target.\n * @param target The target to locate.\n * @return Pointer to the region, or 0.\n */\nRegion *SavedGame::locateRegion(const Target &target) const\n{\n\treturn locateRegion(target.getLongitude(), target.getLatitude());\n}\n\n/**\n * Find the country containing this location.\n * @param lon The longitude.\n * @param lat The latitude.\n * @return Pointer to the country, or 0.\n */\nCountry* SavedGame::locateCountry(double lon, double lat) const\n{\n\tCountry* found = nullptr;\n\tfor (auto* country : _countries)\n\t{\n\t\tif (country->getRules()->insideCountry(lon, lat))\n\t\t{\n\t\t\tfound = country;\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (found)\n\t{\n\t\treturn found;\n\t}\n\t//Log(LOG_DEBUG) << \"Failed to find a country at location [\" << lon << \", \" << lat << \"].\";\n\treturn 0;\n}\n\n/**\n * Find the country containing this target.\n * @param target The target to locate.\n * @return Pointer to the country, or 0.\n */\nCountry* SavedGame::locateCountry(const Target& target) const\n{\n\treturn locateCountry(target.getLongitude(), target.getLatitude());\n}\n\n/**\n * Select a soldier nationality based on mod rules and location on the globe.\n */\nint SavedGame::selectSoldierNationalityByLocation(const Mod* mod, const RuleSoldier* rule, const Target* target) const\n{\n\tif (!target)\n\t{\n\t\treturn -1;\n\t}\n\n\tif (mod->getHireByCountryOdds() > 0 && RNG::percent(mod->getHireByCountryOdds()))\n\t{\n\t\tCountry* country = locateCountry(*target);\n\t\tif (country)\n\t\t{\n\t\t\tint nationality = 0;\n\t\t\tfor (auto* namepool : rule->getNames())\n\t\t\t{\n\t\t\t\t// we assume there is only one such name pool (or none), thus we stop searching on the first hit\n\t\t\t\tif (country->getRules()->getType() == namepool->getCountry())\n\t\t\t\t{\n\t\t\t\t\treturn nationality;\n\t\t\t\t}\n\t\t\t\t++nationality;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (mod->getHireByRegionOdds() > 0 && RNG::percent(mod->getHireByRegionOdds()))\n\t{\n\t\tRegion* region = locateRegion(*target);\n\t\tif (region)\n\t\t{\n\t\t\t// build a new name pool collection, filtered by the region\n\t\t\tstd::vector<std::pair<SoldierNamePool*, int> > filteredNames;\n\t\t\tint totalFilteredNamePoolWeight = 0;\n\t\t\tint nationality = 0;\n\t\t\tfor (auto* namepool : rule->getNames())\n\t\t\t{\n\t\t\t\tif (region->getRules()->getType() == namepool->getRegion())\n\t\t\t\t{\n\t\t\t\t\tfilteredNames.push_back(std::make_pair(namepool, nationality));\n\t\t\t\t\ttotalFilteredNamePoolWeight += namepool->getGlobalWeight();\n\t\t\t\t}\n\t\t\t\t++nationality;\n\t\t\t}\n\n\t\t\t// the modder wants to have regional name pools, but didn't provide any, sigh\n\t\t\tif (totalFilteredNamePoolWeight < 1)\n\t\t\t{\n\t\t\t\treturn -1; // let's just ignore the modder's unfulfillable wish\n\t\t\t}\n\n\t\t\t// select the nationality from the filtered pool, by weight\n\t\t\tint tmp = RNG::generate(1, totalFilteredNamePoolWeight);\n\t\t\tfor (const auto& namepoolPair : filteredNames)\n\t\t\t{\n\t\t\t\tif (tmp <= namepoolPair.first->getGlobalWeight())\n\t\t\t\t{\n\t\t\t\t\treturn namepoolPair.second;\n\t\t\t\t}\n\t\t\t\ttmp -= namepoolPair.first->getGlobalWeight();\n\t\t\t}\n\t\t}\n\t}\n\n\treturn -1;\n}\n\n/*\n * @return the month counter.\n */\nint SavedGame::getMonthsPassed() const\n{\n\treturn _monthsPassed;\n}\n\n/*\n * @return the GraphRegionToggles.\n */\nconst std::string &SavedGame::getGraphRegionToggles() const\n{\n\treturn _graphRegionToggles;\n}\n\n/*\n * @return the GraphCountryToggles.\n */\nconst std::string &SavedGame::getGraphCountryToggles() const\n{\n\treturn _graphCountryToggles;\n}\n\n/*\n * @return the GraphFinanceToggles.\n */\nconst std::string &SavedGame::getGraphFinanceToggles() const\n{\n\treturn _graphFinanceToggles;\n}\n\n/**\n * Sets the GraphRegionToggles.\n * @param value The new value for GraphRegionToggles.\n */\nvoid SavedGame::setGraphRegionToggles(const std::string &value)\n{\n\t_graphRegionToggles = value;\n}\n\n/**\n * Sets the GraphCountryToggles.\n * @param value The new value for GraphCountryToggles.\n */\nvoid SavedGame::setGraphCountryToggles(const std::string &value)\n{\n\t_graphCountryToggles = value;\n}\n\n/**\n * Sets the GraphFinanceToggles.\n * @param value The new value for GraphFinanceToggles.\n */\nvoid SavedGame::setGraphFinanceToggles(const std::string &value)\n{\n\t_graphFinanceToggles = value;\n}\n\n/*\n * Increment the month counter.\n */\nvoid SavedGame::addMonth()\n{\n\t++_monthsPassed;\n\n\t_monthlyPurchaseLimitLog.clear();\n}\n\n/*\n * marks a research topic as having already come up as \"we can now research\"\n * @param research is the project we want to add to the vector\n */\nvoid SavedGame::addPoppedResearch(const RuleResearch* research)\n{\n\tif (!wasResearchPopped(research))\n\t\t_poppedResearch.push_back(research);\n}\n\n/*\n * checks if an unresearched topic has previously been popped up.\n * @param research is the project we are checking for\n * @return whether or not it has been popped up.\n */\nbool SavedGame::wasResearchPopped(const RuleResearch* research)\n{\n\treturn (std::find(_poppedResearch.begin(), _poppedResearch.end(), research) != _poppedResearch.end());\n}\n\n/*\n * checks for and removes a research project from the \"has been popped up\" array\n * @param research is the project we are checking for and removing, if necessary.\n */\nvoid SavedGame::removePoppedResearch(const RuleResearch* research)\n{\n\tauto r = std::find(_poppedResearch.begin(), _poppedResearch.end(), research);\n\tif (r != _poppedResearch.end())\n\t{\n\t\t_poppedResearch.erase(r);\n\t}\n}\n\n/*\n * remembers that this event has been generated\n * @param event is the event we want to remember\n */\nvoid SavedGame::addGeneratedEvent(const RuleEvent* event)\n{\n\t_generatedEvents[event->getName()] += 1;\n}\n\n/*\n * checks if an event has been generated previously\n * @param eventName is the event we are checking for\n * @return whether or not it has been generated previously\n */\nbool SavedGame::wasEventGenerated(const std::string& eventName)\n{\n\treturn (_generatedEvents.find(eventName) != _generatedEvents.end());\n}\n\n/**\n * Returns the list of dead soldiers.\n * @return Pointer to soldier list.\n */\nstd::vector<Soldier*> *SavedGame::getDeadSoldiers()\n{\n\treturn &_deadSoldiers;\n}\n\n/**\n * Calculates and returns a list of all active soldiers.\n * @return All active soldiers.\n*/\nstd::vector<Soldier*> SavedGame::getAllActiveSoldiers() const\n{\n\tstd::vector<Soldier*> soldiers;\n\tfor (auto* xbase : _bases)\n\t{\n\t\tstd::vector<Soldier*> baseSoldiers = *xbase->getSoldiers();\n\t\tsoldiers.insert(soldiers.end(), baseSoldiers.begin(), baseSoldiers.end());\n\n\t\tfor (auto* transfer : *xbase->getTransfers())\n\t\t{\n\t\t\tif (transfer->getType() == TRANSFER_SOLDIER)\n\t\t\t{\n\t\t\t\tsoldiers.push_back(transfer->getSoldier());\n\t\t\t}\n\t\t}\n\t}\n\n\treturn soldiers;\n}\n\n/**\n * Sets the last selected armor.\n * @param value The new value for last selected armor - Armor type string.\n */\n\nvoid SavedGame::setLastSelectedArmor(const std::string &value)\n{\n\t_lastselectedArmor = value;\n}\n\n/**\n * Gets the last selected armor\n * @return last used armor type string\n */\nstd::string SavedGame::getLastSelectedArmor() const\n{\n\treturn _lastselectedArmor;\n}\n\n/**\n* Returns the global equipment layout at specified index.\n* @return Pointer to the EquipmentLayoutItem list.\n*/\nstd::vector<EquipmentLayoutItem*> *SavedGame::getGlobalEquipmentLayout(int index)\n{\n\treturn &_globalEquipmentLayout[index];\n}\n\n/**\n* Returns the name of a global equipment layout at specified index.\n* @return A name.\n*/\nconst std::string &SavedGame::getGlobalEquipmentLayoutName(int index) const\n{\n\treturn _globalEquipmentLayoutName[index];\n}\n\n/**\n* Sets the name of a global equipment layout at specified index.\n* @param index Array index.\n* @param name New name.\n*/\nvoid SavedGame::setGlobalEquipmentLayoutName(int index, const std::string &name)\n{\n\t_globalEquipmentLayoutName[index] = name;\n}\n\n/**\n * Returns the armor type of a global equipment layout at specified index.\n * @return Armor type.\n */\nconst std::string& SavedGame::getGlobalEquipmentLayoutArmor(int index) const\n{\n\treturn _globalEquipmentLayoutArmor[index];\n}\n\n/**\n * Sets the armor type of a global equipment layout at specified index.\n * @param index Array index.\n * @param armorType New armor type.\n */\nvoid SavedGame::setGlobalEquipmentLayoutArmor(int index, const std::string& armorType)\n{\n\t_globalEquipmentLayoutArmor[index] = armorType;\n}\n\n/**\n* Returns the global craft loadout at specified index.\n* @return Pointer to the ItemContainer list.\n*/\nItemContainer *SavedGame::getGlobalCraftLoadout(int index)\n{\n\treturn _globalCraftLoadout[index];\n}\n\n/**\n* Returns the name of a global craft loadout at specified index.\n* @return A name.\n*/\nconst std::string &SavedGame::getGlobalCraftLoadoutName(int index) const\n{\n\treturn _globalCraftLoadoutName[index];\n}\n\n/**\n* Sets the name of a global craft loadout at specified index.\n* @param index Array index.\n* @param name New name.\n*/\nvoid SavedGame::setGlobalCraftLoadoutName(int index, const std::string &name)\n{\n\t_globalCraftLoadoutName[index] = name;\n}\n\n/**\n * Returns the list of mission statistics.\n * @return Pointer to statistics list.\n */\nstd::vector<MissionStatistics*> *SavedGame::getMissionStatistics()\n{\n\treturn &_missionStatistics;\n}\n\n/**\n* Adds a UFO to the ignore list.\n* @param ufoId Ufo ID.\n*/\nvoid SavedGame::addUfoToIgnoreList(int ufoId)\n{\n\tif (ufoId != 0)\n\t{\n\t\t_ignoredUfos.insert(ufoId);\n\t}\n}\n\n/**\n* Checks if a UFO is on the ignore list.\n* @param ufoId Ufo ID.\n*/\nbool SavedGame::isUfoOnIgnoreList(int ufoId)\n{\n\treturn _ignoredUfos.find(ufoId) != _ignoredUfos.end();\n}\n\n/**\n * Registers a soldier's death in the memorial.\n * @param soldier Pointer to dead soldier.\n * @param cause Pointer to cause of death, NULL if missing in action.\n */\nstd::vector<Soldier*>::iterator SavedGame::killSoldier(bool resetArmor, Soldier *soldier, BattleUnitKills *cause)\n{\n\tif (resetArmor)\n\t{\n\t\t// OXCE: soldiers are buried in their default armor (...nicer stats in the Memorial GUI; no free armor if resurrected)\n\t\tsoldier->setArmor(soldier->getRules()->getDefaultArmor());\n\t\tsoldier->setReplacedArmor(0);\n\t\tsoldier->setTransformedArmor(0);\n\t}\n\telse\n\t{\n\t\t// IMPORTANT: don't change the geoscape armor during the ongoing battle!\n\t\t// battlescape armor would reset to geoscape armor after save and reload\n\t}\n\n\tstd::vector<Soldier*>::iterator soldierIt;\n\tfor (auto* xbase : _bases)\n\t{\n\t\tfor (soldierIt = xbase->getSoldiers()->begin(); soldierIt != xbase->getSoldiers()->end(); ++soldierIt)\n\t\t{\n\t\t\tif ((*soldierIt) == soldier)\n\t\t\t{\n\t\t\t\tsoldier->die(new SoldierDeath(*_time, cause));\n\t\t\t\t_deadSoldiers.push_back(soldier);\n\t\t\t\treturn xbase->getSoldiers()->erase(soldierIt);\n\t\t\t}\n\t\t}\n\t}\n\treturn soldierIt;\n}\n\n/**\n * enables/disables autosell for an item type\n */\nvoid SavedGame::setAutosell(const RuleItem *itype, const bool enabled)\n{\n\tif (enabled)\n\t{\n\t\t_autosales.insert(itype);\n\t}\n\telse\n\t{\n\t\t_autosales.erase(itype);\n\t}\n}\n/**\n * get autosell state for an item type\n */\nbool SavedGame::getAutosell(const RuleItem *itype) const\n{\n\tif (!Options::oxceAutoSell)\n\t{\n\t\treturn false;\n\t}\n\treturn _autosales.find(itype) != _autosales.end();\n}\n\n/**\n * Removes all soldiers from a given craft.\n */\nvoid SavedGame::removeAllSoldiersFromXcomCraft(Craft *craft)\n{\n\tfor (auto* xbase : _bases)\n\t{\n\t\tfor (auto* soldier : *xbase->getSoldiers())\n\t\t{\n\t\t\tif (soldier->getCraft() == craft)\n\t\t\t{\n\t\t\t\tsoldier->setCraft(0);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Stop hunting the given xcom craft.\n */\nvoid SavedGame::stopHuntingXcomCraft(Craft *target)\n{\n\tfor (auto* ufo : _ufos)\n\t{\n\t\tufo->resetOriginalDestination(target);\n\t}\n}\n\n/**\n * Stop hunting all xcom craft from a given xcom base.\n */\nvoid SavedGame::stopHuntingXcomCrafts(Base *base)\n{\n\tfor (auto* xcraft : *base->getCrafts())\n\t{\n\t\tfor (auto* ufo : _ufos)\n\t\t{\n\t\t\tufo->resetOriginalDestination(xcraft);\n\t\t}\n\t}\n}\n\n/**\n * Should all xcom soldiers have completely empty starting inventory when doing base equipment?\n */\nbool SavedGame::getDisableSoldierEquipment() const\n{\n\treturn _disableSoldierEquipment;\n}\n\n/**\n * Sets the corresponding flag.\n */\nvoid SavedGame::setDisableSoldierEquipment(bool disableSoldierEquipment)\n{\n\t_disableSoldierEquipment = disableSoldierEquipment;\n}\n\n/**\n * Is the mana feature already unlocked?\n */\nbool SavedGame::isManaUnlocked(Mod *mod) const\n{\n\tauto& researchName = mod->getManaUnlockResearch();\n\tif (Mod::isEmptyRuleName(researchName) || isResearched(researchName))\n\t{\n\t\treturn true;\n\t}\n\treturn false;\n}\n\n/**\n * Gets the current score based on research score and xcom/alien activity in regions.\n */\nint SavedGame::getCurrentScore(int monthsPassed) const\n{\n\tsize_t invertedEntry = _funds.size() - 1;\n\tint scoreTotal = _researchScores.at(invertedEntry);\n\tif (monthsPassed > 1)\n\t\tscoreTotal += 400;\n\tfor (auto* region : _regions)\n\t{\n\t\tscoreTotal += region->getActivityXcom().at(invertedEntry) - region->getActivityAlien().at(invertedEntry);\n\t}\n\treturn scoreTotal;\n}\n\n/**\n * Clear links for the given alien base. Use this before deleting the alien base.\n */\nvoid SavedGame::clearLinksForAlienBase(AlienBase* alienBase, const Mod* mod)\n{\n\t// Take care to remove supply missions for this base.\n\tfor (auto* am : _activeMissions)\n\t{\n\t\tif (am->getAlienBase() == alienBase)\n\t\t{\n\t\t\tam->setAlienBase(0);\n\n\t\t\t// if this is an Earth-based operation, losing the base means mission cannot continue anymore\n\t\t\tif (am->getRules().getOperationType() != AMOT_SPACE)\n\t\t\t{\n\t\t\t\tam->setInterrupted(true);\n\t\t\t}\n\t\t}\n\t}\n\t// If there was a pact with this base, cancel it?\n\tif (mod->getAllowCountriesToCancelAlienPact() && !alienBase->getPactCountry().empty())\n\t{\n\t\tfor (auto* country : _countries)\n\t\t{\n\t\t\tif (country->getRules()->getType() == alienBase->getPactCountry())\n\t\t\t{\n\t\t\t\tcountry->setCancelPact();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Delete the given retaliation mission.\n */\nvoid SavedGame::deleteRetaliationMission(AlienMission* am, Base* base)\n{\n\tfor (auto iter = _ufos.begin(); iter != _ufos.end();)\n\t{\n\t\tUfo* ufo = (*iter);\n\t\tif (ufo->getMission() == am)\n\t\t{\n\t\t\tdelete ufo;\n\t\t\titer = _ufos.erase(iter);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t++iter;\n\t\t}\n\t}\n\tfor (auto iter = _activeMissions.begin(); iter != _activeMissions.end(); ++iter)\n\t{\n\t\tAlienMission* alienMission = (*iter);\n\t\tif (alienMission == am)\n\t\t{\n\t\t\tdelete alienMission;\n\t\t\t_activeMissions.erase(iter);\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (base)\n\t{\n\t\tbase->setRetaliationMission(nullptr);\n\t}\n}\n\n/**\n * Spawn a Geoscape event from the event rules.\n * @return True if successful.\n */\nbool SavedGame::spawnEvent(const RuleEvent* eventRules)\n{\n\tif (!eventRules)\n\t{\n\t\treturn false;\n\t}\n\n\tGeoscapeEvent* newEvent = new GeoscapeEvent(*eventRules);\n\tint minutes = (eventRules->getTimer() + (RNG::generate(0, eventRules->getTimerRandom()))) / 30 * 30;\n\tif (minutes < 60) minutes = 60; // just in case\n\tnewEvent->setSpawnCountdown(minutes);\n\t_geoscapeEvents.push_back(newEvent);\n\n\t// remember that it has been generated\n\taddGeneratedEvent(eventRules);\n\n\tif (Options::oxceGeoscapeDebugLogMaxEntries > 0)\n\t{\n\t\tstd::ostringstream ss;\n\t\tss << \"gameTime: \" << _time->getFullString();\n\t\tss << \" eventSpawn: \" << newEvent->getRules().getName();\n\t\tss << \" days/hours: \" << (minutes / 60) / 24 << \"/\" << (minutes / 60) % 24;\n\t\t_geoscapeDebugLog.push_back(ss.str());\n\t}\n\n\treturn true;\n}\n\n/**\n * Checks if an instant Geoscape event can be spawned.\n */\nbool SavedGame::canSpawnInstantEvent(const RuleEvent* eventRules)\n{\n\tif (!eventRules)\n\t{\n\t\treturn false;\n\t}\n\n\tbool interrupted = false;\n\tif (!eventRules->getInterruptResearch().empty())\n\t{\n\t\tif (isResearched(eventRules->getInterruptResearch(), false))\n\t\t{\n\t\t\tinterrupted = true;\n\t\t}\n\t}\n\n\tif (!interrupted)\n\t{\n\t\taddGeneratedEvent(eventRules);\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\n/**\n * Handles research unlocked by successful/failed missions and despawned mission sites.\n * 1. Adds the research topic to finished research list. Silently.\n * 2. Adds also getOneFree bonus and possible lookup(s). Also silently.\n * 3. Handles alien mission interruption.\n */\nbool SavedGame::handleResearchUnlockedByMissions(const RuleResearch* research, const Mod* mod, const AlienDeployment* deployment)\n{\n\tif (!research)\n\t{\n\t\treturn false;\n\t}\n\tif (_bases.empty())\n\t{\n\t\treturn false; // all bases lost, game over\n\t}\n\tBase* base = _bases.front();\n\n\tauto addResearchDiaryEntryForMission = [&](const RuleResearch* discoveredResearch, DiscoverySourceType sourceType, const AlienDeployment* sourceMission, const RuleResearch* sourceResearch)\n\t{\n\t\tif (!isResearched(discoveredResearch, false) && !isResearchRuleStatusDisabled(discoveredResearch->getName()))\n\t\t{\n\t\t\tResearchDiaryEntry* entry = new ResearchDiaryEntry(discoveredResearch);\n\t\t\tentry->setDate(_time);\n\t\t\tentry->source.type = sourceType;\n\t\t\tif (sourceType == DiscoverySourceType::MISSION)\n\t\t\t{\n\t\t\t\tentry->source.mission = sourceMission;\n\t\t\t\tentry->source.name = sourceMission->getType();\n\t\t\t}\n\t\t\telse // sourceType == DiscoverySourceType::FREE_FROM\n\t\t\t{\n\t\t\t\tentry->source.research = sourceResearch;\n\t\t\t\tentry->source.name = sourceResearch->getName();\n\t\t\t}\n\t\t\taddResearchDiaryEntry(entry);\n\t\t}\n\t};\n\n\tstd::vector<const RuleResearch*> researchVec;\n\tresearchVec.push_back(research);\n\taddResearchDiaryEntryForMission(research, DiscoverySourceType::MISSION, deployment, nullptr);\n\taddFinishedResearch(research, mod, base, true);\n\tif (research->getLookup())\n\t{\n\t\tresearchVec.push_back(research->getLookup());\n\t\taddResearchDiaryEntryForMission(researchVec.back(), DiscoverySourceType::MISSION, deployment, nullptr);\n\t\taddFinishedResearch(researchVec.back(), mod, base, true);\n\t}\n\n\tif (auto* bonus = selectGetOneFree(research))\n\t{\n\t\tresearchVec.push_back(bonus);\n\t\taddResearchDiaryEntryForMission(bonus, DiscoverySourceType::FREE_FROM, nullptr, research);\n\t\taddFinishedResearch(bonus, mod, base, true);\n\t\tif (bonus->getLookup())\n\t\t{\n\t\t\tresearchVec.push_back(bonus->getLookup());\n\t\t\taddResearchDiaryEntryForMission(researchVec.back(), DiscoverySourceType::FREE_FROM, nullptr, research);\n\t\t\taddFinishedResearch(researchVec.back(), mod, base, true);\n\t\t}\n\t}\n\n\t// check and interrupt alien missions if necessary (based on unlocked research)\n\tfor (auto* am : _activeMissions)\n\t{\n\t\tconst auto& interruptResearchName = am->getRules().getInterruptResearch();\n\t\tif (!interruptResearchName.empty())\n\t\t{\n\t\t\tauto* interruptResearch = mod->getResearch(interruptResearchName, true);\n\t\t\tif (std::find(researchVec.begin(), researchVec.end(), interruptResearch) != researchVec.end())\n\t\t\t{\n\t\t\t\tam->setInterrupted(true);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn true;\n}\n\n/**\n * Handles research side effects for primary research sources.\n */\nvoid SavedGame::handlePrimaryResearchSideEffects(const std::vector<const RuleResearch*> &topicsToCheck, const Mod* mod, Base* base)\n{\n\tfor (auto* myResearchRule : topicsToCheck)\n\t{\n\t\t// 3j. now iterate through all the bases and remove this project from their labs (unless it can still yield more stuff!)\n\t\tfor (Base* otherBase : _bases)\n\t\t{\n\t\t\tfor (ResearchProject* otherProject : otherBase->getResearch())\n\t\t\t{\n\t\t\t\tif (myResearchRule == otherProject->getRules())\n\t\t\t\t{\n\t\t\t\t\tif (hasUndiscoveredGetOneFree(myResearchRule, true))\n\t\t\t\t\t{\n\t\t\t\t\t\t// This research topic still has some more undiscovered non-disabled and *AVAILABLE* \"getOneFree\" topics, keep it!\n\t\t\t\t\t}\n\t\t\t\t\telse if (hasUndiscoveredProtectedUnlock(myResearchRule))\n\t\t\t\t\t{\n\t\t\t\t\t\t// This research topic still has one or more undiscovered non-disabled \"protected unlocks\", keep it!\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// This topic can't give you anything else anymore, remove it!\n\t\t\t\t\t\totherBase->removeResearch(otherProject);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// 3k. handle spawned items\n\t\tRuleItem* spawnedItem = mod->getItem(myResearchRule->getSpawnedItem());\n\t\tif (spawnedItem)\n\t\t{\n\t\t\tTransfer* t = new Transfer(1);\n\t\t\tt->setItems(spawnedItem, std::max(1, myResearchRule->getSpawnedItemCount()));\n\t\t\tbase->getTransfers()->push_back(t);\n\t\t}\n\t\tfor (const auto& spawnedItemName2 : myResearchRule->getSpawnedItemList())\n\t\t{\n\t\t\tRuleItem* spawnedItem2 = mod->getItem(spawnedItemName2);\n\t\t\tif (spawnedItem2)\n\t\t\t{\n\t\t\t\tTransfer* t = new Transfer(1);\n\t\t\t\tt->setItems(spawnedItem2);\n\t\t\t\tbase->getTransfers()->push_back(t);\n\t\t\t}\n\t\t}\n\t\t// 3l. handle spawned events\n\t\tRuleEvent* spawnedEventRule = mod->getEvent(myResearchRule->getSpawnedEvent());\n\t\tspawnEvent(spawnedEventRule);\n\t\t// try also the weighted list of events, it's the modder's responsibility to use only one or the other\n\t\t{\n\t\t\tconst std::string choice = myResearchRule->chooseEvent();\n\t\t\tif (!choice.empty())\n\t\t\t{\n\t\t\t\tRuleEvent* eventToSpawn = mod->getEvent(choice, false);\n\t\t\t\tif (eventToSpawn)\n\t\t\t\t{\n\t\t\t\t\tspawnEvent(eventToSpawn);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// 3m. handle counters\n\t\tfor (auto& inc : myResearchRule->getIncreaseCounter())\n\t\t{\n\t\t\tincreaseCustomCounter(inc);\n\t\t}\n\t\tfor (auto& dec : myResearchRule->getDecreaseCounter())\n\t\t{\n\t\t\tdecreaseCustomCounter(dec);\n\t\t}\n\t}\n}\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tScript binding\n////////////////////////////////////////////////////////////\n\nnamespace\n{\n\nvoid getRandomScript(SavedGame* sg, RNG::RandomState*& r)\n{\n\tif (sg)\n\t{\n\t\tr = &RNG::globalRandomState();\n\t}\n\telse\n\t{\n\t\tr = nullptr;\n\t}\n}\n\nvoid getTimeScript(const SavedGame* sg, const GameTime*& r)\n{\n\tif (sg)\n\t{\n\t\tr = sg->getTime();\n\t}\n\telse\n\t{\n\t\tr = nullptr;\n\t}\n}\n\nvoid randomChanceScript(RNG::RandomState* rs, int& val)\n{\n\tif (rs)\n\t{\n\t\tval = rs->generate(0, 99) < val;\n\t}\n\telse\n\t{\n\t\tval = 0;\n\t}\n}\n\nvoid randomRangeScript(RNG::RandomState* rs, int& val, int min, int max)\n{\n\tif (rs && max >= min)\n\t{\n\t\tval = rs->generate(min, max);\n\t}\n\telse\n\t{\n\t\tval = 0;\n\t}\n}\n\nvoid randomRangeSymmetricScript(RNG::RandomState* rs, int& val, int max)\n{\n\tif (rs && max >= 0)\n\t{\n\t\tval = rs->generate(-max, max);\n\t}\n\telse\n\t{\n\t\tval = 0;\n\t}\n}\n\nvoid difficultyLevelScript(const SavedGame* sg, int& val)\n{\n\tif (sg)\n\t{\n\t\tval = sg->getDifficulty();\n\t}\n\telse\n\t{\n\t\tval = 0;\n\t}\n}\n\nvoid getDaysPastEpochScript(const GameTime* p, int& val)\n{\n\tif (p)\n\t{\n\t\tstd::tm time = {  };\n\t\ttime.tm_year = p->getYear() - 1900;\n\t\ttime.tm_mon = p->getMonth() - 1;\n\t\ttime.tm_mday = p->getDay();\n\t\ttime.tm_hour = p->getHour();\n\t\ttime.tm_min = p->getMinute();\n\t\ttime.tm_sec = p->getSecond();\n\t\tval = (int)(std::mktime(&time) / (60 * 60 * 24));\n\t}\n\telse\n\t{\n\t\tval = 0;\n\t}\n}\n\nvoid getSecondsPastMidnightScript(const GameTime* p, int& val)\n{\n\tif (p)\n\t{\n\t\tval = p->getSecond() +\n\t\t\t60 * p->getMinute() +\n\t\t\t60 * 60 * p->getHour();\n\t}\n\telse\n\t{\n\t\tval = 0;\n\t}\n}\n\nstd::string debugDisplayScript(const RNG::RandomState* p)\n{\n\tif (p)\n\t{\n\t\tstd::string s;\n\t\ts += \"RandomState\";\n\t\ts += \"(seed: \\\"\";\n\t\ts += std::to_string(p->getSeed());\n\t\ts += \"\\\")\";\n\t\treturn s;\n\t}\n\telse\n\t{\n\t\treturn \"null\";\n\t}\n}\n\nstd::string debugDisplayScript(const GameTime* p)\n{\n\tif (p)\n\t{\n\t\tauto zeroPrefix = [](int i)\n\t\t{\n\t\t\tif (i < 10)\n\t\t\t{\n\t\t\t\treturn \"0\" + std::to_string(i);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn std::to_string(i);\n\t\t\t}\n\t\t};\n\n\t\tstd::string s;\n\t\ts += \"Time\";\n\t\ts += \"(\\\"\";\n\t\ts += std::to_string(p->getYear());\n\t\ts += \"-\";\n\t\ts += zeroPrefix(p->getMonth());\n\t\ts += \"-\";\n\t\ts += zeroPrefix(p->getDay());\n\t\ts += \" \";\n\t\ts += zeroPrefix(p->getHour());\n\t\ts += \":\";\n\t\ts += zeroPrefix(p->getMinute());\n\t\ts += \":\";\n\t\ts += zeroPrefix(p->getSecond());\n\t\ts += \"\\\")\";\n\t\treturn s;\n\t}\n\telse\n\t{\n\t\treturn \"null\";\n\t}\n}\n\nvoid isResearchedScript(const SavedGame* sg, int& val, const RuleResearch* name)\n{\n\tif (sg)\n\t{\n\t\tif (sg->isResearched(name, false))\n\t\t{\n\t\t\tval = 1;\n\t\t\treturn;\n\t\t}\n\t}\n\tval = 0;\n}\n\nbool filterCountryConstScript(const SavedGame*, const Country*)\n{\n\treturn true;\n}\n\nbool filterCountryScript(SavedGame*, Country*)\n{\n\treturn true;\n}\n\nstd::string debugDisplayScript(const SavedGame* p)\n{\n\tif (p)\n\t{\n\t\tstd::string s;\n\t\ts += SavedGame::ScriptName;\n\t\ts += \"(fileName: \\\"\";\n\t\ts += p->getName();\n\t\ts += \"\\\" time: \";\n\t\ts += debugDisplayScript(p->getTime());\n\t\ts += \")\";\n\t\treturn s;\n\t}\n\telse\n\t{\n\t\treturn \"null\";\n\t}\n}\n\n}\n\n/**\n * Register SavedGame in script parser.\n * @param parser Script parser.\n */\nvoid SavedGame::ScriptRegister(ScriptParserBase* parser)\n{\n\tparser->registerPointerType<Country>();\n\n\t{\n\t\tconst auto name = std::string{ \"RandomState\" };\n\t\tparser->registerRawPointerType<RNG::RandomState>(name);\n\t\tBind<RNG::RandomState> rs = { parser, name };\n\n\t\trs.add<&randomChanceScript>(\"randomChance\", \"Change value from range 0-100 to 0-1 based on probability\");\n\t\trs.add<&randomRangeScript>(\"randomRange\", \"Return random value from defined range\");\n\t\trs.add<&randomRangeSymmetricScript>(\"randomRangeSymmetric\", \"Return random value from negative to positive of given max value\");\n\n\t\trs.addDebugDisplay<&debugDisplayScript>();\n\t}\n\n\t{\n\t\tconst auto name = std::string{ \"Time\" };\n\t\tparser->registerRawPointerType<GameTime>(name);\n\t\tBind<GameTime> t = { parser, name };\n\n\t\tt.add<&GameTime::getSecond>(\"getSecond\");\n\t\tt.add<&GameTime::getMinute>(\"getMinute\");\n\t\tt.add<&GameTime::getHour>(\"getHour\");\n\t\tt.add<&GameTime::getDay>(\"getDay\");\n\t\tt.add<&GameTime::getMonth>(\"getMonth\");\n\t\tt.add<&GameTime::getYear>(\"getYear\");\n\t\tt.add<&getDaysPastEpochScript>(\"getDaysPastEpoch\", \"Days past 1970-01-01\");\n\t\tt.add<&getSecondsPastMidnightScript>(\"getSecondsPastMidnight\", \"Seconds past 00:00\");\n\n\t\tt.addDebugDisplay<&debugDisplayScript>();\n\t}\n\n\tBind<SavedGame> sgg = { parser };\n\n\tsgg.add<&getTimeScript>(\"getTime\", \"Get global time that is Greenwich Mean Time\");\n\tsgg.add<&getRandomScript>(\"getRandomState\");\n\n\tsgg.add<&difficultyLevelScript>(\"difficultyLevel\", \"Get difficulty level\");\n\tsgg.add<&SavedGame::getMonthsPassed>(\"getMonthsPassed\", \"Number of months passed from start\");\n\tsgg.add<&SavedGame::getDaysPassed>(\"getDaysPassed\", \"Number of days passed from start\");\n\n\tsgg.addList<&filterCountryConstScript, &SavedGame::_countries>(\"getCountries\");\n\tsgg.addList<&filterCountryScript, &SavedGame::_countries>(\"getCountries\");\n\n\tsgg.add<&isResearchedScript>(\"isResearched\");\n\n\tsgg.addScriptValue<&SavedGame::_scriptValues>();\n\n\tsgg.addDebugDisplay<&debugDisplayScript>();\n}\n\n}\n"
  },
  {
    "path": "src/Savegame/SavedGame.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <map>\n#include <vector>\n#include <set>\n#include <string>\n#include <time.h>\n#include <stdint.h>\n#include \"GameTime.h\"\n#include \"../Mod/RuleAlienMission.h\"\n#include \"../Mod/RuleEvent.h\"\n#include \"../Savegame/Craft.h\"\n#include \"../Mod/RuleManufacture.h\"\n#include \"../Mod/RuleBaseFacility.h\"\n#include \"../Mod/RuleCraft.h\"\n#include \"../Engine/Script.h\"\n#include \"ResearchDiary.h\"\n\nnamespace OpenXcom\n{\n\nclass Mod;\nclass GameTime;\nclass Country;\nclass Base;\nclass Region;\nclass Ufo;\nclass Waypoint;\nclass SavedBattleGame;\nclass TextList;\nclass Language;\nclass RuleResearch;\nclass ResearchProject;\nclass Soldier;\nclass RuleManufacture;\nclass RuleItem;\nclass ArticleDefinition;\nclass MissionSite;\nclass AlienBase;\nclass AlienStrategy;\nclass AlienMission;\nclass GeoscapeEvent;\nclass Target;\nclass Soldier;\nclass Craft;\nclass EquipmentLayoutItem;\nclass ItemContainer;\nclass RuleSoldierTransformation;\nclass AlienRace;\nstruct MissionStatistics;\nstruct BattleUnitKills;\n\n/**\n * Enumerator containing all the possible game difficulties.\n */\nenum GameDifficulty : int { DIFF_BEGINNER = 0, DIFF_EXPERIENCED, DIFF_VETERAN, DIFF_GENIUS, DIFF_SUPERHUMAN };\n\n/**\n * Enumerator for the various save types.\n */\nenum SaveType { SAVE_DEFAULT, SAVE_INSTA, SAVE_QUICK, SAVE_AUTO_GEOSCAPE, SAVE_AUTO_BATTLESCAPE, SAVE_IRONMAN, SAVE_IRONMAN_END };\n\n/**\n * Enumerator for the current game ending.\n */\nenum GameEnding { END_NONE, END_WIN, END_LOSE };\n\n/**\n * Container for savegame info displayed on listings.\n */\nstruct SaveInfo\n{\n\tstd::string fileName;\n\tstd::string displayName;\n\ttime_t timestamp;\n\tstd::string isoDate, isoTime;\n\tstd::string details;\n\tstd::vector<std::string> mods;\n\tbool reserved;\n};\n\n/**\n * The game data that gets written to disk when the game is saved.\n * A saved game holds all the variable info in a game like funds,\n * game time, current bases and contents, world activities, score, etc.\n */\nclass SavedGame\n{\npublic:\n\tCountry *debugCountry = nullptr;\n\tRegion *debugRegion = nullptr;\n\tint debugType = 0;\n\tsize_t debugZone = 0;\n\tsize_t debugArea = 0;\n\n\t/// Name of class used in script.\n\tstatic constexpr const char *ScriptName = \"GeoscapeGame\";\n\t/// Register all useful function used by script.\n\tstatic void ScriptRegister(ScriptParserBase* parser);\n\n\n\tstatic const int MAX_EQUIPMENT_LAYOUT_TEMPLATES = 50;\n\tstatic const int MAX_CRAFT_LOADOUT_TEMPLATES = 10;\n\nprivate:\n\tstd::string _name;\n\tGameDifficulty _difficulty;\n\tGameEnding _end;\n\tbool _ironman;\n\tGameTime *_time;\n\tstd::vector<std::string> _userNotes;\n\tstd::vector<std::string> _geoscapeDebugLog;\n\tstd::vector<int> _researchScores;\n\tstd::vector<int64_t> _funds, _maintenance, _incomes, _expenditures;\n\tdouble _globeLon, _globeLat;\n\tint _globeZoom;\n\tstd::map<std::string, int> _ids;\n\tstd::vector<Country*> _countries;\n\tstd::vector<Region*> _regions;\n\tstd::vector<Base*> _bases;\n\tstd::vector<Ufo*> _ufos;\n\tstd::vector<Waypoint*> _waypoints;\n\tstd::vector<MissionSite*> _missionSites;\n\tstd::vector<AlienBase*> _alienBases;\n\tAlienStrategy *_alienStrategy;\n\tSavedBattleGame *_battleGame;\n\tstd::vector<const RuleResearch*> _discovered;\n\tstd::vector<ResearchDiaryEntry*> _researchDiary;\n\tstd::map<std::string, int> _generatedEvents;\n\tstd::map<std::string, int> _ufopediaRuleStatus;\n\tstd::map<std::string, int> _manufactureRuleStatus;\n\tstd::map<std::string, int> _researchRuleStatus;\n\tstd::map<std::string, int> _monthlyPurchaseLimitLog;\n\tstd::map<std::string, bool> _hiddenPurchaseItemsMap;\n\tstd::map<std::string, RuleCraftDeployment> _customRuleCraftDeployments;\n\tBase* _previewBase;\n\tstd::vector<AlienMission*> _activeMissions;\n\tstd::vector<GeoscapeEvent*> _geoscapeEvents;\n\tbool _debug, _warned;\n\tbool _togglePersonalLight, _toggleNightVision;\n\tint _toggleBrightness;\n\tint _monthsPassed;\n\tint _daysPassed;\n\tint _vehiclesLost, _craftLostDogfight, _craftLostMission;\n\tstd::string _graphRegionToggles;\n\tstd::string _graphCountryToggles;\n\tstd::string _graphFinanceToggles;\n\tstd::vector<const RuleResearch*> _poppedResearch;\n\tstd::vector<Soldier*> _deadSoldiers;\n\tsize_t _selectedBase;\n\tstd::string _lastselectedArmor; //contains the last selected armor\n\tstd::string _globalEquipmentLayoutName[MAX_EQUIPMENT_LAYOUT_TEMPLATES];\n\tstd::string _globalEquipmentLayoutArmor[MAX_EQUIPMENT_LAYOUT_TEMPLATES];\n\tstd::vector<EquipmentLayoutItem*> _globalEquipmentLayout[MAX_EQUIPMENT_LAYOUT_TEMPLATES];\n\tstd::string _globalCraftLoadoutName[MAX_CRAFT_LOADOUT_TEMPLATES];\n\tItemContainer *_globalCraftLoadout[MAX_CRAFT_LOADOUT_TEMPLATES];\n\tstd::vector<MissionStatistics*> _missionStatistics;\n\tstd::set<int> _ignoredUfos;\n\tstd::set<const RuleItem *> _autosales;\n\tbool _disableSoldierEquipment;\n\tbool _alienContainmentChecked;\n\tScriptValues<SavedGame> _scriptValues;\n\n\tstatic SaveInfo getSaveInfo(const std::string &file, Language *lang);\npublic:\n\tstatic const std::string AUTOSAVE_GEOSCAPE, AUTOSAVE_BATTLESCAPE, QUICKSAVE;\n\t/// Creates a new saved game.\n\tSavedGame();\n\t/// Cleans up the saved game.\n\t~SavedGame();\n\t/// Sanitizes a mod name in a save.\n\tstatic std::string sanitizeModName(const std::string &name);\n\t/// Gets list of saves in the user directory.\n\tstatic std::vector<SaveInfo> getList(Language *lang, bool autoquick);\n\t/// Loads a saved game from YAML.\n\tvoid load(const std::string &filename, Mod *mod, Language *lang);\n\tvoid loadTemplates(const YAML::YamlNodeReader& reader, const Mod* mod);\n\tvoid loadUfopediaRuleStatus(const YAML::YamlNodeReader& reader);\n\t/// Saves a saved game to YAML.\n\tvoid save(const std::string &filename, Mod *mod) const;\n\t/// Gets the game name.\n\tstd::string getName() const;\n\t/// Sets the game name.\n\tvoid setName(const std::string &name);\n\t/// Gets the game difficulty.\n\tGameDifficulty getDifficulty() const;\n\t/// Sets the game difficulty.\n\tvoid setDifficulty(GameDifficulty difficulty);\n\t/// Gets the game difficulty coefficient.\n\tint getDifficultyCoefficient() const;\n\t/// Gets the sell price coefficient.\n\tint getSellPriceCoefficient() const;\n\t/// Gets the buy price coefficient.\n\tint getBuyPriceCoefficient() const;\n\t/// Gets the game ending.\n\tGameEnding getEnding() const;\n\t/// Sets the game ending.\n\tvoid setEnding(GameEnding end);\n\t/// Gets if the game is in ironman mode.\n\tbool isIronman() const;\n\t/// Sets if the game is in ironman mode.\n\tvoid setIronman(bool ironman);\n\t/// Gets the current funds.\n\tint64_t getFunds() const;\n\t/// Gets the list of funds from previous months.\n\tstd::vector<int64_t> &getFundsList();\n\t/// Sets new funds.\n\tvoid setFunds(int64_t funds);\n\t/// Gets the current globe longitude.\n\tdouble getGlobeLongitude() const;\n\t/// Sets the new globe longitude.\n\tvoid setGlobeLongitude(double lon);\n\t/// Gets the current globe latitude.\n\tdouble getGlobeLatitude() const;\n\t/// Sets the new globe latitude.\n\tvoid setGlobeLatitude(double lat);\n\t/// Gets the current globe zoom.\n\tint getGlobeZoom() const;\n\t/// Sets the new globe zoom.\n\tvoid setGlobeZoom(int zoom);\n\t/// Handles monthly funding.\n\tvoid monthlyFunding();\n\t/// Gets the current game time.\n\tGameTime *getTime() const;\n\t/// Sets the current game time.\n\tvoid setTime(const GameTime& time);\n\t/// Gets the current ID for an object.\n\tint getId(const std::string &name);\n\t/// Gets the last ID for an object.\n\tint getLastId(const std::string& name);\n\t/// Increase a custom counter.\n\tvoid increaseCustomCounter(const std::string& name);\n\t/// Decrease a custom counter.\n\tvoid decreaseCustomCounter(const std::string& name);\n\t/// Resets the list of object IDs.\n\tconst std::map<std::string, int> &getAllIds() const;\n\t/// Resets the list of object IDs.\n\tvoid setAllIds(const std::map<std::string, int> &ids);\n\t/// Gets the list of countries.\n\tstd::vector<Country*> *getCountries();\n\t/// Gets the total country funding.\n\tint getCountryFunding() const;\n\t/// Gets the list of regions.\n\tstd::vector<Region*> *getRegions();\n\t/// Gets the list of bases.\n\tstd::vector<Base*> *getBases();\n\t/// Gets the list of bases.\n\tconst std::vector<Base*> *getBases() const;\n\t/// Gets the total base maintenance.\n\tint getBaseMaintenance() const;\n\t/// Gets the list of UFOs.\n\tstd::vector<Ufo*> *getUfos();\n\t/// Gets the list of UFOs.\n\tconst std::vector<Ufo*> *getUfos() const;\n\t/// Gets the list of waypoints.\n\tstd::vector<Waypoint*> *getWaypoints();\n\t/// Gets the list of mission sites.\n\tstd::vector<MissionSite*> *getMissionSites();\n\t/// Gets the current battle game.\n\tSavedBattleGame *getSavedBattle();\n\t/// Sets the current battle game.\n\tvoid setBattleGame(SavedBattleGame *battleGame);\n\t/// Sets the status of a ufopedia rule\n\tvoid setUfopediaRuleStatus(const std::string &ufopediaRule, int newStatus);\n\t/// Sets the status of a manufacture rule\n\tvoid setManufactureRuleStatus(const std::string &manufactureRule, int newStatus);\n\t/// Sets the status of a research rule\n\tvoid setResearchRuleStatus(const std::string &researchRule, int newStatus);\n\t/// Sets the item as hidden or unhidden\n\tvoid setHiddenPurchaseItemsStatus(const std::string &itemName, bool hidden);\n\t/// Selects a \"getOneFree\" topic for the given research rule.\n\tconst RuleResearch* selectGetOneFree(const RuleResearch* research);\n\t/// Remove a research from the \"already discovered\" list\n\tvoid removeDiscoveredResearch(const RuleResearch *research);\n\t/// Make all research discovered (used in New Battle)\n\tvoid makeAllResearchDiscovered(const Mod* mod);\n\t/// Add a finished ResearchProject\n\tvoid addFinishedResearch(const RuleResearch *research, const Mod *mod, Base *base, bool score = true);\n\t/// Add a new record to the research diary\n\tvoid addResearchDiaryEntry(ResearchDiaryEntry* entry);\n\t/// Gets the research diary.\n\tconst std::vector<ResearchDiaryEntry*> & getResearchDiary() const { return _researchDiary; }\n\t/// Get the list of already discovered research projects\n\tconst std::vector<const RuleResearch*> & getDiscoveredResearch() const;\n\t/// Does this item correspond to at least one research topic that can be researched now or in the future?\n\tbool isResearchable(const RuleItem* item, const Mod* mod) const;\n\t/// Get the list of ResearchProject which can be researched in a Base\n\tvoid getAvailableResearchProjects(std::vector<RuleResearch*> & projects, const Mod *mod, Base *base, bool considerDebugMode = false) const;\n\t/// Get the list of newly available research projects once a research has been completed.\n\tvoid getNewlyAvailableResearchProjects(std::vector<RuleResearch*> & before, std::vector<RuleResearch*> & after, std::vector<RuleResearch*> & diff) const;\n\t/// Get the list of Productions which can be manufactured in a Base\n\tvoid getAvailableProductions(std::vector<RuleManufacture*> & productions, const Mod *mod, Base *base, ManufacturingFilterType filter = MANU_FILTER_DEFAULT) const;\n\t/// Get the list of newly available manufacture projects once a research has been completed.\n\tvoid getDependableManufacture(std::vector<RuleManufacture*> & dependables, const RuleResearch *research, const Mod *mod, Base *base) const;\n\t/// Get the list of Soldier Transformations that can occur at a base\n\tvoid getAvailableTransformations(std::vector<RuleSoldierTransformation*> & transformations, const Mod *mod, Base *base) const;\n\t/// Get the list of newly available items to purchase once a research has been completed.\n\tvoid getDependablePurchase(std::vector<RuleItem*> & dependables, const RuleResearch *research, const Mod *mod) const;\n\t/// Get the list of newly available craft to purchase/rent once a research has been completed.\n\tvoid getDependableCraft(std::vector<RuleCraft*> & dependables, const RuleResearch *research, const Mod *mod) const;\n\t/// Get the list of newly available facilities to build once a research has been completed.\n\tvoid getDependableFacilities(std::vector<RuleBaseFacility*> & dependables, const RuleResearch *research, const Mod *mod) const;\n\t/// Gets the status of a ufopedia rule.\n\tint getUfopediaRuleStatus(const std::string &ufopediaRule);\n\t/// Gets the log of monthly purchase limits\n\tstd::map<std::string, int>& getMonthlyPurchaseLimitLog() { return _monthlyPurchaseLimitLog; }\n\t/// Gets the list of hidden items\n\tconst std::map<std::string, bool> &getHiddenPurchaseItems();\n\t/// Gets the list of player-defined save-specific RuleCraft '_deployment' overrides\n\tstd::map<std::string, RuleCraftDeployment>& getCustomRuleCraftDeployments() { return _customRuleCraftDeployments; }\n\t/// Gets the preview base.\n\tBase* getPreviewBase() { return _previewBase; }\n\t/// Sets the preview base.\n\tvoid setPreviewBase(Base* previewBase) { _previewBase = previewBase; }\n\t/// Gets the status of a manufacture rule.\n\tint getManufactureRuleStatus(const std::string &manufactureRule);\n\t/// Gets all the research rule status info.\n\tconst std::map<std::string, int> &getResearchRuleStatusRaw() const { return _researchRuleStatus; }\n\t/// Gets the status of a research rule.\n\tint getResearchRuleStatus(const std::string &researchRule) const;\n\t/// Is the research permanently disabled?\n\tbool isResearchRuleStatusDisabled(const std::string &researchRule) const;\n\t/// Gets if a research still has undiscovered non-disabled \"getOneFree\".\n\tbool hasUndiscoveredGetOneFree(const RuleResearch * r, bool checkOnlyAvailableTopics) const;\n\t/// Gets if a research still has undiscovered non-disabled \"protected unlocks\".\n\tbool hasUndiscoveredProtectedUnlock(const RuleResearch * r) const;\n\t/// Gets if a certain research has been completed.\n\tbool isResearched(const std::string &research, bool considerDebugMode = true) const;\n\t/// Gets if a certain research has been completed.\n\tbool isResearched(const RuleResearch *research, bool considerDebugMode = true) const;\n\t/// Gets if a certain list of research topics has been completed.\n\tbool isResearched(const std::vector<std::string> &research, bool considerDebugMode = true) const;\n\t/// Gets if a certain list of research topics has been completed.\n\tbool isResearched(const std::vector<const RuleResearch *> &research, bool considerDebugMode = true, bool skipDisabled = false) const;\n\t/// Gets if a certain item has been obtained.\n\tbool isItemObtained(const std::string &itemType, const Mod* mod) const;\n\t/// Gets if a certain facility has been built.\n\tbool isFacilityBuilt(const std::string &facilityType) const;\n\t/// Gets if a certain soldier type has been hired.\n\tbool isSoldierTypeHired(const std::string& soldierType) const;\n\t/// Gets the soldier matching this ID.\n\tSoldier *getSoldier(int id) const;\n\t/// Handles the higher promotions.\n\tbool handlePromotions(std::vector<Soldier*> &participants, const Mod *mod);\n\t/// Checks how many soldiers of a rank exist and which one has the highest score.\n\tSoldier *inspectSoldiers(std::vector<Soldier*> &soldiers, std::vector<Soldier*> &participants, int rank);\n\t/// Gets the (approximate) number of idle days since the soldier's last mission.\n\tint getSoldierIdleDays(const Soldier *soldier);\n\t///  Returns the list of alien bases.\n\tstd::vector<AlienBase*> *getAlienBases();\n\t/// Sets debug mode.\n\tvoid setDebugMode();\n\t/// Gets debug mode.\n\tbool getDebugMode() const;\n\t/// return a list of maintenance costs\n\tstd::vector<int64_t> &getMaintenances();\n\t/// sets the research score for the month\n\tvoid addResearchScore(int score);\n\t/// gets the list of research scores\n\tstd::vector<int> &getResearchScores();\n\t/// gets the list of incomes.\n\tstd::vector<int64_t> &getIncomes();\n\t/// gets the list of expenditures.\n\tstd::vector<int64_t> &getExpenditures();\n\t/// gets whether or not the player has been warned\n\tbool getWarned() const;\n\t/// sets whether or not the player has been warned\n\tvoid setWarned(bool warned);\n\n\t/// gets personal light toggle\n\tbool getTogglePersonalLight() const { return _togglePersonalLight; }\n\t/// sets personal light toggle\n\tvoid setTogglePersonalLight(bool togglePersonalLight) { _togglePersonalLight = togglePersonalLight; }\n\t/// gets night vision toggle\n\tbool getToggleNightVision() const { return _toggleNightVision; }\n\t/// sets night vision toggle\n\tvoid setToggleNightVision(bool toggleNightVision) { _toggleNightVision = toggleNightVision; }\n\t/// gets brightness toggle\n\tint getToggleBrightness() const { return _toggleBrightness; }\n\t/// sets brightness toggle\n\tvoid setToggleBrightness(int toggleBrightness) { _toggleBrightness = toggleBrightness; }\n\n\t/// Full access to the alien strategy data.\n\tAlienStrategy &getAlienStrategy() { return *_alienStrategy; }\n\t/// Read-only access to the alien strategy data.\n\tconst AlienStrategy &getAlienStrategy() const { return *_alienStrategy; }\n\t/// Full access to the current alien missions.\n\tstd::vector<AlienMission*> &getAlienMissions() { return _activeMissions; }\n\t/// Read-only access to the current alien missions.\n\tconst std::vector<AlienMission*> &getAlienMissions() const { return _activeMissions; }\n\t/// Finds a mission by region and objective.\n\tAlienMission *findAlienMission(const std::string &region, MissionObjective objective, AlienRace* race = nullptr) const;\n\t/// Full access to the current geoscape events.\n\tstd::vector<GeoscapeEvent*> &getGeoscapeEvents() { return _geoscapeEvents; }\n\t/// Read-only access to the current geoscape events.\n\tconst std::vector<GeoscapeEvent*> &getGeoscapeEvents() const { return _geoscapeEvents; }\n\t/// Locate a region containing a position.\n\tRegion *locateRegion(double lon, double lat) const;\n\t/// Locate a region containing a Target.\n\tRegion *locateRegion(const Target &target) const;\n\t/// Locate a country containing a position.\n\tCountry* locateCountry(double lon, double lat) const;\n\t/// Locate a country containing a Target.\n\tCountry* locateCountry(const Target& target) const;\n\t/// Select a soldier nationality based on mod rules and location on the globe.\n\tint selectSoldierNationalityByLocation(const Mod* mod, const RuleSoldier* rule, const Target* target) const;\n\t/// Return the month counter.\n\tint getMonthsPassed() const;\n\t/// Return the day counter.\n\tint getDaysPassed() const { return _daysPassed; }\n\tvoid increaseDaysPassed() { _daysPassed++; }\n\t/// Return the vehicles lost counter.\n\tint getVehiclesLost() const { return _vehiclesLost; }\n\tvoid increaseVehiclesLost() { _vehiclesLost++; }\n\t/// Return the craft lost in dogfight counter.\n\tint getCraftLostDogfight() const { return _craftLostDogfight; }\n\tvoid increaseCraftLostDogfight() { _craftLostDogfight++; }\n\t/// Return the craft lost in mission counter.\n\tint getCraftLostMission() const { return _craftLostMission; }\n\tvoid increaseCraftLostMission() { _craftLostMission++; }\n\t/// Return the GraphRegionToggles.\n\tconst std::string &getGraphRegionToggles() const;\n\t/// Return the GraphCountryToggles.\n\tconst std::string &getGraphCountryToggles() const;\n\t/// Return the GraphFinanceToggles.\n\tconst std::string &getGraphFinanceToggles() const;\n\t/// Sets the GraphRegionToggles.\n\tvoid setGraphRegionToggles(const std::string &value);\n\t/// Sets the GraphCountryToggles.\n\tvoid setGraphCountryToggles(const std::string &value);\n\t/// Sets the GraphFinanceToggles.\n\tvoid setGraphFinanceToggles(const std::string &value);\n\t/// Increment the month counter.\n\tvoid addMonth();\n\t/// add a research to the \"popped up\" array\n\tvoid addPoppedResearch(const RuleResearch* research);\n\t/// check if a research is on the \"popped up\" array\n\tbool wasResearchPopped(const RuleResearch* research);\n\t/// remove a research from the \"popped up\" array\n\tvoid removePoppedResearch(const RuleResearch* research);\n\t/// remembers that this event has been generated\n\tvoid addGeneratedEvent(const RuleEvent* event);\n\t/// checks if an event has been generated previously\n\tbool wasEventGenerated(const std::string& eventName);\n\t/// Gets the list of dead soldiers.\n\tstd::vector<Soldier*> *getDeadSoldiers();\n\t/// Gets a list of all active soldiers.\n\tstd::vector<Soldier*> getAllActiveSoldiers() const;\n\t/// Gets the last selected player base.\n\tBase *getSelectedBase();\n\t/// Set the last selected player base.\n\tvoid setSelectedBase(size_t base);\n\t/// Evaluate the score of a soldier based on all of his stats, missions and kills.\n\tint getSoldierScore(Soldier *soldier);\n\t/// Sets the last selected armor\n\tvoid setLastSelectedArmor(const std::string &value);\n\t/// Gets the last selected armor\n\tstd::string getLastSelectedArmor() const;\n\t/// Gets the name of a global equipment layout at specified index.\n\tconst std::string &getGlobalEquipmentLayoutName(int index) const;\n\t/// Sets the name of a global equipment layout at specified index.\n\tvoid setGlobalEquipmentLayoutName(int index, const std::string &name);\n\t/// Gets the armor type of a global equipment layout at specified index.\n\tconst std::string& getGlobalEquipmentLayoutArmor(int index) const;\n\t/// Sets the armor type of a global equipment layout at specified index.\n\tvoid setGlobalEquipmentLayoutArmor(int index, const std::string& armorType);\n\t/// Gets the global equipment layout at specified index.\n\tstd::vector<EquipmentLayoutItem*> *getGlobalEquipmentLayout(int index);\n\t/// Gets the name of a global craft loadout at specified index.\n\tconst std::string &getGlobalCraftLoadoutName(int index) const;\n\t/// Sets the name of a global craft loadout at specified index.\n\tvoid setGlobalCraftLoadoutName(int index, const std::string &name);\n\t/// Gets the global craft loadout at specified index.\n\tItemContainer *getGlobalCraftLoadout(int index);\n\t/// Gets the list of missions statistics\n\tstd::vector<MissionStatistics*> *getMissionStatistics();\n\t/// Adds a UFO to the ignore list.\n\tvoid addUfoToIgnoreList(int ufoId);\n\t/// Checks if a UFO is on the ignore list.\n\tbool isUfoOnIgnoreList(int ufoId);\n\t/// Handles a soldier's death.\n\tstd::vector<Soldier*>::iterator killSoldier(bool resetArmor, Soldier *soldier, BattleUnitKills *cause = 0);\n\t/// enables/disables autosell for an item type\n\tvoid setAutosell(const RuleItem *itype, const bool enabled);\n\t/// get autosell state for an item type\n\tbool getAutosell(const RuleItem *) const;\n\t/// Removes all soldiers from a given craft.\n\tvoid removeAllSoldiersFromXcomCraft(Craft *craft);\n\t/// Stop hunting the given xcom craft.\n\tvoid stopHuntingXcomCraft(Craft *target);\n\t/// Stop hunting all xcom craft from a given xcom base.\n\tvoid stopHuntingXcomCrafts(Base *base);\n\t/// Should all xcom soldiers have completely empty starting inventory when doing base equipment?\n\tbool getDisableSoldierEquipment() const;\n\t/// Sets the corresponding flag.\n\tvoid setDisableSoldierEquipment(bool disableSoldierEquipment);\n\t/// Is alien containment check finished?\n\tbool getAlienContainmentChecked() const { return _alienContainmentChecked; }\n\t/// Sets the corresponding flag.\n\tvoid setAlienContainmentChecked(bool alienContainmentChecked) { _alienContainmentChecked = alienContainmentChecked; }\n\t/// Is the mana feature already unlocked?\n\tbool isManaUnlocked(Mod *mod) const;\n\t/// Gets the current score based on research score and xcom/alien activity in regions.\n\tint getCurrentScore(int monthsPassed) const;\n\t/// Clear links for the given alien base. Use this before deleting the alien base.\n\tvoid clearLinksForAlienBase(AlienBase* alienBase, const Mod* mod);\n\t/// Delete the given retaliation mission.\n\tvoid deleteRetaliationMission(AlienMission* am, Base* base);\n\t/// Spawn a Geoscape event from the event rules.\n\tbool spawnEvent(const RuleEvent* eventRules);\n\t/// Checks if an instant Geoscape event can be spawned.\n\tbool canSpawnInstantEvent(const RuleEvent* eventRules);\n\t/// Handles research unlocked by successful/failed missions and despawned mission sites.\n\tbool handleResearchUnlockedByMissions(const RuleResearch* research, const Mod* mod, const AlienDeployment* deployment);\n\t/// Handles research side effects for primary research sources.\n\tvoid handlePrimaryResearchSideEffects(const std::vector<const RuleResearch*> &topicsToCheck, const Mod* mod, Base* base);\n\t/// Gets the list of user notes.\n\tstd::vector<std::string>& getUserNotes() { return _userNotes; }\n\t/// Gets the list of geoscape debug log entries.\n\tstd::vector<std::string>& getGeoscapeDebugLog() { return _geoscapeDebugLog; }\n};\n\n}\n"
  },
  {
    "path": "src/Savegame/SerializationHelper.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"SerializationHelper.h\"\n#include <assert.h>\n#include <sstream>\n#include <cfloat>\n\nnamespace OpenXcom\n{\n\nint unserializeInt(Uint8 **buffer, Uint8 sizeKey)\n{\n\t/* The C spec explicitly requires *(Type*) pointer accesses to be\n\t * sizeof(Type) aligned, which is not guaranteed by the UInt8** buffer\n\t * passed in here.\n\t * memcpy() is explicitly designed to cope with any address alignment, so\n\t * use that to avoid undefined behaviour */\n\tint ret = 0;\n\tswitch(sizeKey)\n\t{\n\tcase 1:\n\t\tret = **buffer;\n\t\tbreak;\n\tcase 2:\n\t{\n\t\tSint16 tmp;\n\t\tmemcpy(&tmp, *buffer, sizeof(tmp));\n\t\tret = tmp;\n\t\tbreak;\n\t}\n\tcase 3:\n\t\tassert(false); // no.\n\t\tbreak;\n\tcase 4:\n\t{\n\t\tUint32 tmp;\n\t\tmemcpy(&tmp, *buffer, sizeof(tmp));\n\t\tret = tmp;\n\t\tbreak;\n\t}\n\tdefault:\n\t\tassert(false); // get out.\n\t}\n\n\t*buffer += sizeKey;\n\n\treturn ret;\n}\n\nvoid serializeInt(Uint8 **buffer, Uint8 sizeKey, int value)\n{\n\t/* The C spec explicitly requires *(Type*) pointer accesses to be\n\t * sizeof(Type) aligned, which is not guaranteed by the UInt8** buffer\n\t * passed in here.\n\t * memcpy() is explicitly designed to cope with any address alignment, so\n\t * use that to avoid undefined behaviour */\n\tswitch(sizeKey)\n\t{\n\tcase 1:\n\t\tassert(value < 256);\n\t\t**buffer = value;\n\t\tbreak;\n\tcase 2:\n\t{\n\t\tSint16 s16Value = value;\n\t\tassert(value < 65536);\n\t\tmemcpy(*buffer, &s16Value, sizeof(Sint16));\n\t\tbreak;\n\t}\n\tcase 3:\n\t\tassert(false); // no.\n\t\tbreak;\n\tcase 4:\n\t{\n\t\tUint32 u32Value = value;\n\t\tmemcpy(*buffer, &u32Value, sizeof(Uint32));\n\t\tbreak;\n\t}\n\tdefault:\n\t\tassert(false); // get out.\n\t}\n\n\t*buffer += sizeKey;\n}\n\nstd::string serializeDouble(double value)\n{\n\tstd::ostringstream stream;\n\tstream.precision(DBL_DIG + 2);\n\tstream << value;\n\treturn stream.str();\n}\n\n}\n"
  },
  {
    "path": "src/Savegame/SerializationHelper.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <SDL_types.h>\n#include <string>\n\nnamespace OpenXcom\n{\n\nint unserializeInt(Uint8 **buffer, Uint8 sizeKey);\nvoid serializeInt(Uint8 **buffer, Uint8 sizeKey, int value);\nstd::string serializeDouble(double value);\n\n}\n"
  },
  {
    "path": "src/Savegame/Soldier.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <cmath>\n#include <algorithm>\n#include \"Soldier.h\"\n#include \"../Engine/Collections.h\"\n#include \"../Engine/RNG.h\"\n#include \"../Engine/Language.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/ScriptBind.h\"\n#include \"Craft.h\"\n#include \"EquipmentLayoutItem.h\"\n#include \"SoldierDeath.h\"\n#include \"SoldierDiary.h\"\n#include \"../Mod/SoldierNamePool.h\"\n#include \"../Mod/RuleSoldier.h\"\n#include \"../Mod/RuleSoldierBonus.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/StatString.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Mod/RuleSoldierTransformation.h\"\n#include \"../Mod/RuleCommendations.h\"\n#include \"Base.h\"\n#include \"ItemContainer.h\"\n#include \"../Mod/RuleSkill.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes a new soldier, either blank or randomly generated.\n * @param rules Soldier ruleset.\n * @param armor Soldier armor.\n * @param id Unique soldier id for soldier generation.\n */\nSoldier::Soldier(RuleSoldier *rules, Armor *armor, int nationality, int id) :\n\t_id(id), _nationality(0),\n\t_improvement(0), _psiStrImprovement(0), _rules(rules), _rank(RANK_ROOKIE), _craft(0),\n\t_gender(GENDER_MALE), _look(LOOK_BLONDE), _lookVariant(0), _missions(0), _kills(0), _stuns(0),\n\t_recentlyPromoted(false), _psiTraining(false), _training(false), _returnToTrainingWhenHealed(false),\n\t_armor(armor), _replacedArmor(0), _transformedArmor(0), _personalEquipmentArmor(nullptr), _death(0), _diary(new SoldierDiary()),\n\t_corpseRecovered(false)\n{\n\tif (id != 0)\n\t{\n\t\tUnitStats minStats = rules->getMinStats();\n\t\tUnitStats maxStats = rules->getMaxStats();\n\n\t\t_initialStats.tu = RNG::generate(minStats.tu, maxStats.tu);\n\t\t_initialStats.stamina = RNG::generate(minStats.stamina, maxStats.stamina);\n\t\t_initialStats.health = RNG::generate(minStats.health, maxStats.health);\n\t\t_initialStats.mana = RNG::generate(minStats.mana, maxStats.mana);\n\t\t_initialStats.bravery = RNG::generate(minStats.bravery/10, maxStats.bravery/10)*10;\n\t\t_initialStats.reactions = RNG::generate(minStats.reactions, maxStats.reactions);\n\t\t_initialStats.firing = RNG::generate(minStats.firing, maxStats.firing);\n\t\t_initialStats.throwing = RNG::generate(minStats.throwing, maxStats.throwing);\n\t\t_initialStats.strength = RNG::generate(minStats.strength, maxStats.strength);\n\t\t_initialStats.psiStrength = RNG::generate(minStats.psiStrength, maxStats.psiStrength);\n\t\t_initialStats.melee = RNG::generate(minStats.melee, maxStats.melee);\n\t\t_initialStats.psiSkill = minStats.psiSkill;\n\n\t\t_currentStats = _initialStats;\n\n\t\tconst std::vector<SoldierNamePool*> &names = rules->getNames();\n\t\tif (!names.empty())\n\t\t{\n\t\t\tif (nationality > -1)\n\t\t\t{\n\t\t\t\t// nationality by location, or hardcoded/technical nationality\n\t\t\t\t_nationality = nationality;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// nationality by name pool weights\n\t\t\t\tint tmp = RNG::generate(1, rules->getTotalSoldierNamePoolWeight());\n\t\t\t\tint nat = 0;\n\t\t\t\tfor (auto* namepool : names)\n\t\t\t\t{\n\t\t\t\t\tif (tmp <= namepool->getGlobalWeight())\n\t\t\t\t\t{\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\ttmp -= namepool->getGlobalWeight();\n\t\t\t\t\t++nat;\n\t\t\t\t}\n\t\t\t\t_nationality = nat;\n\t\t\t}\n\t\t\tif ((size_t)_nationality >= names.size())\n\t\t\t{\n\t\t\t\t// handling weird cases, e.g. corner cases in soldier transformations\n\t\t\t\t_nationality = RNG::generate(0, names.size() - 1);\n\t\t\t}\n\t\t\t_name = names.at(_nationality)->genName(&_gender, rules->getFemaleFrequency());\n\t\t\t_callsign = generateCallsign(rules->getNames());\n\t\t\t_look = (SoldierLook)names.at(_nationality)->genLook(4); // Once we add the ability to mod in extra looks, this will need to reference the ruleset for the maximum amount of looks.\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// No possible names, just wing it\n\t\t\t_gender = (RNG::percent(rules->getFemaleFrequency()) ? GENDER_FEMALE : GENDER_MALE);\n\t\t\t_look = (SoldierLook)RNG::generate(0,3);\n\t\t\t_name = (_gender == GENDER_FEMALE) ? \"Jane\" : \"John\";\n\t\t\t_name += \" Doe\";\n\t\t\t_callsign = \"\";\n\t\t}\n\t}\n\t_lookVariant = RNG::seedless(0, RuleSoldier::LookVariantMax - 1);\n}\n\n/**\n *\n */\nSoldier::~Soldier()\n{\n\tfor (auto* entry : _equipmentLayout)\n\t{\n\t\tdelete entry;\n\t}\n\tCollections::deleteAll(_personalEquipmentLayout);\n\tdelete _death;\n\tdelete _diary;\n}\n\n/**\n * Loads the soldier from a YAML file.\n * @param node YAML node.\n * @param mod Game mod.\n * @param save Pointer to savegame.\n */\nvoid Soldier::load(const YAML::YamlNodeReader& node, const Mod *mod, SavedGame *save, const ScriptGlobal *shared, bool soldierTemplate)\n{\n\tconst auto& reader = node.useIndex();\n\n\tif (!soldierTemplate)\n\t\treader.tryRead(\"id\", _id);\n\treader.tryRead(\"name\", _name);\n\treader.tryRead(\"callsign\", _callsign);\n\treader.tryRead(\"nationality\", _nationality);\n\tif (soldierTemplate)\n\t{\n\t\tUnitStats ii, cc;\n\t\treader.tryRead(\"initialStats\", ii);\n\t\treader.tryRead(\"currentStats\", cc);\n\t\t_initialStats = UnitStats::templateMerge(_initialStats, ii);\n\t\t_currentStats = UnitStats::templateMerge(_currentStats, cc);\n\t}\n\telse\n\t{\n\t\treader.tryRead(\"initialStats\", _initialStats);\n\t\treader.tryRead(\"currentStats\", _currentStats);\n\t}\n\treader.tryRead(\"dailyDogfightExperienceCache\", _dailyDogfightExperienceCache);\n\n\t// re-roll mana stats when upgrading saves\n\tif (_currentStats.mana == 0 && _rules->getMaxStats().mana > 0)\n\t{\n\t\tint reroll = RNG::generate(_rules->getMinStats().mana, _rules->getMaxStats().mana);\n\t\t_currentStats.mana = reroll;\n\t\t_initialStats.mana = reroll;\n\t}\n\n\treader.tryRead(\"rank\", _rank);\n\treader.tryRead(\"gender\", _gender);\n\treader.tryRead(\"look\", _look);\n\treader.tryRead(\"lookVariant\", _lookVariant);\n\treader.tryRead(\"missions\", _missions);\n\treader.tryRead(\"kills\", _kills);\n\treader.tryRead(\"stuns\", _stuns);\n\treader.tryRead(\"manaMissing\", _manaMissing);\n\treader.tryRead(\"healthMissing\", _healthMissing);\n\treader.tryRead(\"recovery\", _recovery);\n\tArmor *armor = _armor;\n\tif (reader[\"armor\"])\n\t\tarmor = mod->getArmor(reader[\"armor\"].readVal<std::string>());\n\tif (armor == 0)\n\t\tarmor = mod->getSoldier(mod->getSoldiersList().front())->getDefaultArmor();\n\t_armor = armor;\n\tif (reader[\"replacedArmor\"])\n\t\t_replacedArmor = mod->getArmor(reader[\"replacedArmor\"].readVal<std::string>());\n\tif (reader[\"transformedArmor\"])\n\t\t_transformedArmor = mod->getArmor(reader[\"transformedArmor\"].readVal<std::string>());\n\treader.tryRead(\"psiTraining\", _psiTraining);\n\treader.tryRead(\"training\", _training);\n\treader.tryRead(\"returnToTrainingWhenHealed\", _returnToTrainingWhenHealed);\n\n\treader.tryRead(\"improvement\", _improvement);\n\treader.tryRead(\"psiStrImprovement\", _psiStrImprovement);\n\tfor (const auto& layoutItem : reader[\"equipmentLayout\"].children())\n\t{\n\t\ttry\n\t\t{\n\t\t\t_equipmentLayout.push_back(new EquipmentLayoutItem(layoutItem, mod));\n\t\t}\n\t\tcatch (Exception& ex)\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"Error loading Layout: \" << ex.what();\n\t\t}\n\t}\n\tfor (const auto& personalLayoutItem : reader[\"personalEquipmentLayout\"].children())\n\t{\n\t\ttry\n\t\t{\n\t\t\t_personalEquipmentLayout.push_back(new EquipmentLayoutItem(personalLayoutItem, mod));\n\t\t}\n\t\tcatch (Exception& ex)\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"Error loading Layout: \" << ex.what();\n\t\t}\n\t}\n\tif (reader[\"personalEquipmentArmor\"])\n\t{\n\t\t_personalEquipmentArmor = mod->getArmor(reader[\"personalEquipmentArmor\"].readVal<std::string>());\n\t}\n\tif (reader[\"death\"])\n\t{\n\t\t_death = new SoldierDeath();\n\t\t_death->load(reader[\"death\"]);\n\t}\n\tif (reader[\"diary\"])\n\t{\n\t\t_diary = new SoldierDiary();\n\t\t_diary->load(reader[\"diary\"], mod);\n\t}\n\tcalcStatString(mod->getStatStrings(), (Options::psiStrengthEval && save->isResearched(mod->getPsiRequirements())));\n\treader.tryRead(\"corpseRecovered\", _corpseRecovered);\n\treader.tryRead(\"previousTransformations\", _previousTransformations);\n\treader.tryRead(\"transformationBonuses\", _transformationBonuses);\n\n\tif (const auto& spawnInfo = reader[\"randomTransformationBonuses\"])\n\t{\n\t\tWeightedOptions randomTransformationBonuses;\n\t\trandomTransformationBonuses.load(spawnInfo);\n\t\tint transformationBonusesCount = reader[\"transformationBonusesCount\"].readVal(1); // if not provided, default is 1\n\t\twhile (transformationBonusesCount > 0 && !randomTransformationBonuses.empty())\n\t\t{\n\t\t\ttransformationBonusesCount--;\n\t\t\tstd::string chosen = randomTransformationBonuses.choose();\n\t\t\trandomTransformationBonuses.set(chosen, 0);\n\n\t\t\t// Award a soldier bonus, if defined\n\t\t\tif (!Mod::isEmptyRuleName(chosen))\n\t\t\t{\n\t\t\t\tauto it2 = _transformationBonuses.find(chosen);\n\t\t\t\tif (it2 != _transformationBonuses.end())\n\t\t\t\t{\n\t\t\t\t\tit2->second += 1;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t_transformationBonuses[chosen] = 1;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t_scriptValues.load(reader, shared);\n}\n\n/**\n * Saves the soldier to a YAML file.\n * @return YAML node.\n */\nvoid Soldier::save(YAML::YamlNodeWriter writer, const ScriptGlobal *shared) const\n{\n\twriter.setAsMap();\n\n\twriter.write(\"type\", _rules->getType());\n\twriter.write(\"id\", _id);\n\twriter.write(\"name\", _name);\n\tif (!_callsign.empty())\n\t\twriter.write(\"callsign\", _callsign);\n\twriter.write(\"nationality\", _nationality);\n\twriter.write(\"initialStats\", _initialStats);\n\twriter.write(\"currentStats\", _currentStats);\n\tif (_dailyDogfightExperienceCache.firing > 0 || _dailyDogfightExperienceCache.reactions > 0 || _dailyDogfightExperienceCache.bravery > 0)\n\t\twriter.write(\"dailyDogfightExperienceCache\", _dailyDogfightExperienceCache);\n\twriter.write(\"rank\", _rank);\n\tif (_craft)\n\t\t_craft->saveId(writer[\"craft\"]);\n\twriter.write(\"gender\", _gender);\n\twriter.write(\"look\", _look);\n\twriter.write(\"lookVariant\", _lookVariant);\n\twriter.write(\"missions\", _missions);\n\twriter.write(\"kills\", _kills);\n\twriter.write(\"stuns\", _stuns);\n\tif (_manaMissing > 0)\n\t\twriter.write(\"manaMissing\", _manaMissing);\n\tif (_healthMissing > 0)\n\t\twriter.write(\"healthMissing\", _healthMissing);\n\tif (_recovery > 0.0f)\n\t\twriter.write(\"recovery\", _recovery);\n\twriter.write(\"armor\", _armor->getType());\n\tif (_replacedArmor != 0)\n\t\twriter.write(\"replacedArmor\", _replacedArmor->getType());\n\tif (_transformedArmor != 0)\n\t\twriter.write(\"transformedArmor\", _transformedArmor->getType());\n\tif (_psiTraining)\n\t\twriter.write(\"psiTraining\", _psiTraining);\n\tif (_training)\n\t\twriter.write(\"training\", _training);\n\tif (_returnToTrainingWhenHealed)\n\t\twriter.write(\"returnToTrainingWhenHealed\", _returnToTrainingWhenHealed);\n\twriter.write(\"improvement\", _improvement);\n\twriter.write(\"psiStrImprovement\", _psiStrImprovement);\n\twriter.write(\"equipmentLayout\", _equipmentLayout,\n\t\t[](YAML::YamlNodeWriter& w, EquipmentLayoutItem* i)\n\t\t{ i->save(w.write()); });\n\twriter.write(\"personalEquipmentLayout\", _personalEquipmentLayout,\n\t\t[](YAML::YamlNodeWriter& w, EquipmentLayoutItem* i)\n\t\t{ i->save(w.write()); });\n\tif (_personalEquipmentArmor)\n\t\twriter.write(\"personalEquipmentArmor\", _personalEquipmentArmor->getType());\n\tif (_death != 0)\n\t\t _death->save(writer[\"death\"]);\n\tif (Options::soldierDiaries &&\n\t\t(!_diary->getMissionIdList().empty() || !_diary->getSoldierCommendations()->empty() || _diary->getMonthsService() > 0 || _diary->getUfosShotDown() > 0))\n\t{\n\t\t_diary->save(writer[\"diary\"]);\n\t}\n\tif (_corpseRecovered)\n\t\twriter.write(\"corpseRecovered\", _corpseRecovered);\n\tif (!_previousTransformations.empty())\n\t\twriter.write(\"previousTransformations\", _previousTransformations);\n\tif (!_transformationBonuses.empty())\n\t\twriter.write(\"transformationBonuses\", _transformationBonuses);\n\n\t_scriptValues.save(writer, shared);\n}\n\n/**\n * Returns the soldier's full name (and, optionally, statString).\n * @param statstring Add stat string?\n * @param maxLength Restrict length to a certain value.\n * @return Soldier name.\n */\nstd::string Soldier::getName(bool statstring, unsigned int maxLength) const\n{\n\tif (statstring && !_statString.empty())\n\t{\n\t\tauto nameCodePointLength = Unicode::codePointLengthUTF8(_name);\n\t\tauto statCodePointLength = Unicode::codePointLengthUTF8(_statString);\n\t\tif (nameCodePointLength + statCodePointLength > maxLength)\n\t\t{\n\t\t\treturn Unicode::codePointSubstrUTF8(_name, 0, maxLength - statCodePointLength) + \"/\" + _statString;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn _name + \"/\" + _statString;\n\t\t}\n\t}\n\telse\n\t{\n\t\treturn _name;\n\t}\n}\n\n/**\n * Changes the soldier's full name.\n * @param name Soldier name.\n */\nvoid Soldier::setName(const std::string &name)\n{\n\t_name = name;\n}\n\n/**\n * Generates a new name based on nationality.\n */\nvoid Soldier::genName()\n{\n\tconst std::vector<SoldierNamePool*>& names = _rules->getNames();\n\tif (!names.empty())\n\t{\n\t\t// clamp (and randomize) nationality if needed (i.e. if the modder messed up)\n\t\tif ((size_t)_nationality >= names.size())\n\t\t{\n\t\t\t_nationality = RNG::generate(0, names.size() - 1);\n\t\t}\n\t\t_name = names.at(_nationality)->genName(&_gender, _rules->getFemaleFrequency());\n\t\t_callsign = generateCallsign(_rules->getNames());\n\t\t_look = (SoldierLook)names.at(_nationality)->genLook(4); // Once we add the ability to mod in extra looks, this will need to reference the ruleset for the maximum amount of looks.\n\t}\n\telse\n\t{\n\t\t_nationality = 0;\n\t}\n}\n\n/**\n * Returns the soldier's callsign.\n * @param maxLength Restrict length to a certain value.\n * @return Soldier callsign.\n */\nstd::string Soldier::getCallsign(unsigned int maxLength) const\n{\n\tstd::ostringstream ss;\n\tss << \"\\\"\";\n\tss << Unicode::codePointSubstrUTF8(_callsign, 0, maxLength);\n\tss << \"\\\"\";\n\n\treturn ss.str();\n}\n\n/**\n * Changes the soldier's callsign.\n * @param callsign Soldier callsign.\n */\nvoid Soldier::setCallsign(const std::string &callsign)\n{\n\t_callsign = callsign;\n}\n\n/**\n * Check whether the soldier has a callsign assigned.\n * @return true, if the soldier has a callsign, false, if he has not.\n */\nbool Soldier::hasCallsign() const\n{\n\treturn !_callsign.empty();\n}\n\n/**\n * Generate a random callsign from the pool of names. Tries to fallback to the first entry in\n * in the namepool list if no callsigns for the given nationality are defined.\n * @return generated callsign.\n */\nstd::string Soldier::generateCallsign(const std::vector<SoldierNamePool*> &names)\n{\n\tstd::string callsign = names.at(_nationality)->genCallsign(_gender);\n\tif (callsign.empty())\n\t{\n\t\tcallsign = names.at(0)->genCallsign(_gender);\n\t}\n\treturn callsign;\n}\n\n/**\n* Returns the soldier's nationality.\n* @return Nationality ID.\n*/\nint Soldier::getNationality() const\n{\n\treturn _nationality;\n}\n\n/**\n* Changes the soldier's nationality.\n* @param nationality Nationality ID.\n*/\nvoid Soldier::setNationality(int nationality)\n{\n\t_nationality = nationality;\n}\n\n/**\n * Returns the craft the soldier is assigned to.\n * @return Pointer to craft.\n */\nCraft *Soldier::getCraft() const\n{\n\treturn _craft;\n}\n\n/**\n * Automatically move equipment between the craft and the base when assigning/deassigning/reassigning soldiers.\n */\nvoid Soldier::autoMoveEquipment(Craft* craft, Base* base, int toBase)\n{\n\tauto* inTheBase = base->getStorageItems();\n\tauto* onTheCraft = _craft->getItems();\n\tauto* reservedForTheCraft = _craft->getSoldierItems();\n\n\t// Disclaimer: no checks for items not allowed on crafts; no checks for any craft limits (item number or weight). I'm not willing to spend the next 5+ years fixing it!\n\tfor (auto* invItem : _equipmentLayout)\n\t{\n\t\t// ignore fixed weapons...\n\t\tif (!invItem->isFixed())\n\t\t{\n\t\t\tconst auto* invItemMain = invItem->getItemType();\n\t\t\tif (toBase > 0)\n\t\t\t{\n\t\t\t\tif (onTheCraft->getItem(invItemMain) > 0)\n\t\t\t\t{\n\t\t\t\t\tinTheBase->addItem(invItemMain, 1);\n\t\t\t\t\tonTheCraft->removeItem(invItemMain, 1);\n\t\t\t\t}\n\t\t\t\treservedForTheCraft->removeItem(invItemMain, 1);\n\t\t\t}\n\t\t\telse if (toBase < 0)\n\t\t\t{\n\t\t\t\tif (inTheBase->getItem(invItemMain) > 0)\n\t\t\t\t{\n\t\t\t\t\tinTheBase->removeItem(invItemMain, 1);\n\t\t\t\t\tonTheCraft->addItem(invItemMain, 1);\n\t\t\t\t}\n\t\t\t\treservedForTheCraft->addItem(invItemMain, 1);\n\t\t\t}\n\t\t}\n\t\t// ...but not their ammo\n\t\tfor (int slot = 0; slot < RuleItem::AmmoSlotMax; ++slot)\n\t\t{\n\t\t\tconst auto* invItemAmmo = invItem->getAmmoItemForSlot(slot);\n\t\t\tif (invItemAmmo != nullptr)\n\t\t\t{\n\t\t\t\tif (toBase > 0)\n\t\t\t\t{\n\t\t\t\t\tif (onTheCraft->getItem(invItemAmmo) > 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tinTheBase->addItem(invItemAmmo, 1);\n\t\t\t\t\t\tonTheCraft->removeItem(invItemAmmo, 1);\n\t\t\t\t\t}\n\t\t\t\t\treservedForTheCraft->removeItem(invItemAmmo, 1);\n\t\t\t\t}\n\t\t\t\telse if (toBase < 0)\n\t\t\t\t{\n\t\t\t\t\tif (inTheBase->getItem(invItemAmmo) > 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tinTheBase->removeItem(invItemAmmo, 1);\n\t\t\t\t\t\tonTheCraft->addItem(invItemAmmo, 1);\n\t\t\t\t\t}\n\t\t\t\t\treservedForTheCraft->addItem(invItemAmmo, 1);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Assigns the soldier to a new craft.\n * @param craft Pointer to craft.\n */\nvoid Soldier::setCraft(Craft *craft, bool resetCustomDeployment)\n{\n\t_craft = craft;\n\n\tif (resetCustomDeployment && _craft)\n\t{\n\t\t// adding a soldier into a craft invalidates a custom craft deployment\n\t\t_craft->resetCustomDeployment();\n\t}\n}\n/**\n * Assigns the soldier to a new craft and automatically moves the equipment (if enabled).\n */\nvoid Soldier::setCraftAndMoveEquipment(Craft* craft, Base* base, bool isNewBattle, bool resetCustomDeployment)\n{\n\tbool notTheSameCraft = (_craft != craft);\n\n\tif (Options::oxceAlternateCraftEquipmentManagement && !isNewBattle && notTheSameCraft && base)\n\t{\n\t\tif (_craft)\n\t\t{\n\t\t\tautoMoveEquipment(_craft, base, 1); // move from old craft to base\n\t\t}\n\t}\n\n\tsetCraft(craft, resetCustomDeployment);\n\n\tif (Options::oxceAlternateCraftEquipmentManagement && !isNewBattle && notTheSameCraft && base)\n\t{\n\t\tif (craft)\n\t\t{\n\t\t\tautoMoveEquipment(craft, base, -1); // move from base to new craft\n\t\t}\n\t}\n}\n\n/**\n * Returns the soldier's craft string, which\n * is either the soldier's wounded status,\n * the assigned craft name, or none.\n * @param lang Language to get strings from.\n * @return Full name.\n */\nstd::string Soldier::getCraftString(Language *lang, const BaseSumDailyRecovery& recovery) const\n{\n\tstd::string s;\n\tif (_death)\n\t{\n\t\tif (_death->getCause())\n\t\t{\n\t\t\ts = lang->getString(\"STR_KILLED_IN_ACTION\", _gender);\n\t\t}\n\t\telse\n\t\t{\n\t\t\ts = lang->getString(\"STR_MISSING_IN_ACTION\", _gender);\n\t\t}\n\t}\n\telse if (isWounded())\n\t{\n\t\tstd::ostringstream ss;\n\t\tss << lang->getString(\"STR_WOUNDED\");\n\t\tss << \">\";\n\t\tint days = getNeededRecoveryTime(recovery);\n\t\tif (days < 0)\n\t\t{\n\t\t\tss << \"∞\";\n\t\t}\n\t\telse\n\t\t{\n\t\t\tss << days;\n\t\t}\n\t\ts = ss.str();\n\t}\n\telse if (_craft == 0)\n\t{\n\t\ts = lang->getString(\"STR_NONE_UC\");\n\t}\n\telse\n\t{\n\t\ts = _craft->getName(lang);\n\t}\n\treturn s;\n}\n\n/**\n * Returns a localizable-string representation of\n * the soldier's military rank.\n * @return String ID for rank.\n */\nstd::string Soldier::getRankString() const\n{\n\tconst std::vector<std::string> &rankStrings = _rules->getRankStrings();\n\tif (!_rules->getAllowPromotion())\n\t{\n\t\t// even if promotion is not allowed, we allow to use a different \"Rookie\" translation per soldier type\n\t\tif (rankStrings.empty())\n\t\t{\n\t\t\treturn \"STR_RANK_NONE\";\n\t\t}\n\t}\n\n\tswitch (_rank)\n\t{\n\tcase RANK_ROOKIE:\n\t\tif (rankStrings.size() > 0)\n\t\t\treturn rankStrings.at(0);\n\t\treturn \"STR_ROOKIE\";\n\tcase RANK_SQUADDIE:\n\t\tif (rankStrings.size() > 1)\n\t\t\treturn rankStrings.at(1);\n\t\treturn \"STR_SQUADDIE\";\n\tcase RANK_SERGEANT:\n\t\tif (rankStrings.size() > 2)\n\t\t\treturn rankStrings.at(2);\n\t\treturn \"STR_SERGEANT\";\n\tcase RANK_CAPTAIN:\n\t\tif (rankStrings.size() > 3)\n\t\t\treturn rankStrings.at(3);\n\t\treturn \"STR_CAPTAIN\";\n\tcase RANK_COLONEL:\n\t\tif (rankStrings.size() > 4)\n\t\t\treturn rankStrings.at(4);\n\t\treturn \"STR_COLONEL\";\n\tcase RANK_COMMANDER:\n\t\tif (rankStrings.size() > 5)\n\t\t\treturn rankStrings.at(5);\n\t\treturn \"STR_COMMANDER\";\n\tdefault:\n\t\treturn \"\";\n\t}\n}\n\n/**\n * Returns a graphic representation of\n * the soldier's military rank from BASEBITS.PCK.\n * @note THE MEANING OF LIFE (is now obscured as a default)\n * @return Sprite ID for rank.\n */\nint Soldier::getRankSprite() const\n{\n\treturn _rules->getRankSprite() + _rank;\n}\n\n/**\n * Returns a graphic representation of\n * the soldier's military rank from SMOKE.PCK\n * @return Sprite ID for rank.\n */\nint Soldier::getRankSpriteBattlescape() const\n{\n\treturn _rules->getRankSpriteBattlescape() + _rank;\n}\n\n/**\n * Returns a graphic representation of\n * the soldier's military rank from TinyRanks\n * @return Sprite ID for rank.\n */\nint Soldier::getRankSpriteTiny() const\n{\n\treturn _rules->getRankSpriteTiny() + _rank;\n}\n\n/**\n * Returns the soldier's military rank.\n * @return Rank enum.\n */\nSoldierRank Soldier::getRank() const\n{\n\treturn _rank;\n}\n\n/**\n * Increase the soldier's military rank.\n */\nvoid Soldier::promoteRank()\n{\n\tif (!_rules->getAllowPromotion())\n\t\treturn;\n\n\tconst std::vector<std::string> &rankStrings = _rules->getRankStrings();\n\tif (!rankStrings.empty())\n\t{\n\t\t// stop if the soldier already has the maximum possible rank for his soldier type\n\t\tif ((size_t)_rank >= rankStrings.size() - 1)\n\t\t{\n\t\t\treturn;\n\t\t}\n\t}\n\n\t_rank = (SoldierRank)((int)_rank + 1);\n\tif (_rank > RANK_SQUADDIE)\n\t{\n\t\t// only promotions above SQUADDIE are worth to be mentioned\n\t\t_recentlyPromoted = true;\n\t}\n}\n\n/**\n * Promotes/demotes a soldier to a specific rank.\n */\nvoid Soldier::setRank(const SoldierRank newRank)\n{\n\tif (!_rules->getAllowPromotion())\n\t\treturn;\n\n\tconst std::vector<std::string> &rankStrings = _rules->getRankStrings();\n\tif (!rankStrings.empty())\n\t{\n\t\t// abort if the desired rank is not indexed in the rank strings\n\t\tif ((size_t)newRank >= rankStrings.size())\n\t\t{\n\t\t\treturn;\n\t\t}\n\t}\n\n\t_rank = newRank;\n\n\t// Note: we don't need to show a notification for this style of promotion\n}\n\n/**\n * Returns the soldier's amount of missions.\n * @return Missions.\n */\nint Soldier::getMissions() const\n{\n\treturn _missions;\n}\n\n/**\n * Returns the soldier's amount of kills.\n * @return Kills.\n */\nint Soldier::getKills() const\n{\n\treturn _kills;\n}\n\n/**\n * Returns the soldier's amount of stuns.\n * @return Stuns.\n */\nint Soldier::getStuns() const\n{\n\treturn _stuns;\n}\n\n/**\n * Returns the soldier's gender.\n * @return Gender.\n */\nSoldierGender Soldier::getGender() const\n{\n\treturn _gender;\n}\n\n/**\n * Changes the soldier's gender (1/3 of avatar).\n * @param gender Gender.\n */\nvoid Soldier::setGender(SoldierGender gender)\n{\n\t_gender = gender;\n}\n\n/**\n * Returns the soldier's look.\n * @return Look.\n */\nSoldierLook Soldier::getLook() const\n{\n\treturn _look;\n}\n\n/**\n * Changes the soldier's look (2/3 of avatar).\n * @param look Look.\n */\nvoid Soldier::setLook(SoldierLook look)\n{\n\t_look = look;\n}\n\n/**\n * Returns the soldier's look sub type.\n * @return Look.\n */\nint Soldier::getLookVariant() const\n{\n\treturn _lookVariant;\n}\n\n/**\n * Changes the soldier's look variant (3/3 of avatar).\n * @param lookVariant Look sub type.\n */\nvoid Soldier::setLookVariant(int lookVariant)\n{\n\t_lookVariant = lookVariant;\n}\n\n/**\n * Returns the soldier's rules.\n * @return rule soldier\n */\nconst RuleSoldier *Soldier::getRules() const\n{\n\treturn _rules;\n}\n\n/**\n * Returns the soldier's unique ID. Each soldier\n * can be identified by its ID. (not it's name)\n * @return Unique ID.\n */\nint Soldier::getId() const\n{\n\treturn _id;\n}\n\n/**\n * Add a mission to the counter.\n */\nvoid Soldier::addMissionCount()\n{\n\t_missions++;\n}\n\n/**\n * Add a kill to the counter.\n */\nvoid Soldier::addKillCount(int count)\n{\n\t_kills += count;\n}\n\n/**\n * Add a stun to the counter.\n */\nvoid Soldier::addStunCount(int count)\n{\n\t_stuns += count;\n}\n\n/**\n * Get pointer to initial stats.\n */\nconst UnitStats* Soldier::getInitStats() const\n{\n\treturn &_initialStats;\n}\n\n/**\n * Get pointer to current stats.\n */\nUnitStats *Soldier::getCurrentStatsEditable()\n{\n\treturn &_currentStats;\n}\nconst UnitStats* Soldier::getCurrentStats() const\n{\n\treturn &_currentStats;\n}\n\nvoid Soldier::setBothStats(UnitStats *stats)\n{\n\t_currentStats = *stats;\n\t_initialStats = *stats;\n}\n\n/**\n * Returns the unit's promotion status and resets it.\n * @return True if recently promoted, False otherwise.\n */\nbool Soldier::isPromoted()\n{\n\tbool promoted = _recentlyPromoted;\n\t_recentlyPromoted = false;\n\treturn promoted;\n}\n\n/**\n * Returns the unit's current armor.\n * @return Pointer to armor data.\n */\nArmor *Soldier::getArmor() const\n{\n\treturn _armor;\n}\n\n/**\n * Changes the unit's current armor.\n * @param armor Pointer to armor data.\n */\nvoid Soldier::setArmor(Armor *armor, bool resetCustomDeployment)\n{\n\tif (resetCustomDeployment && _craft && _armor && armor && _armor->getSize() < armor->getSize())\n\t{\n\t\t// increasing the size of a soldier's armor invalidates a custom craft deployment\n\t\t_craft->resetCustomDeployment();\n\t}\n\n\t_armor = armor;\n}\n\n/**\n * Returns a list of armor layers (sprite names).\n */\nconst std::vector<std::string>& Soldier::getArmorLayers(Armor *customArmor) const\n{\n\tstd::stringstream ss;\n\n\tconst Armor *armor = customArmor ? customArmor : _armor;\n\n\tconst std::string gender = _gender == GENDER_MALE ? \"M\" : \"F\";\n\tconst auto& layoutDefinition = armor->getLayersDefinition();\n\n\t// find relevant layer\n\tfor (int i = 0; i <= RuleSoldier::LookVariantBits; ++i)\n\t{\n\t\tss.str(\"\");\n\t\tss << gender;\n\t\tss << (int)_look + (_lookVariant & (RuleSoldier::LookVariantMask >> i)) * 4;\n\t\tauto it = layoutDefinition.find(ss.str());\n\t\tif (it != layoutDefinition.end())\n\t\t{\n\t\t\treturn it->second;\n\t\t}\n\t}\n\n\t{\n\t\t// try also gender + hardcoded look 0\n\t\tss.str(\"\");\n\t\tss << gender << \"0\";\n\t\tauto it = layoutDefinition.find(ss.str());\n\t\tif (it != layoutDefinition.end())\n\t\t{\n\t\t\treturn it->second;\n\t\t}\n\t}\n\n\tthrow Exception(\"Layered armor sprite definition (\" + armor->getType() + \") not found!\");\n}\n\n/**\n* Gets the soldier's original armor (before replacement).\n* @return Pointer to armor data.\n*/\nArmor *Soldier::getReplacedArmor() const\n{\n\treturn _replacedArmor;\n}\n\n/**\n* Backs up the soldier's original armor (before replacement).\n* @param armor Pointer to armor data.\n*/\nvoid Soldier::setReplacedArmor(Armor *armor)\n{\n\t_replacedArmor = armor;\n}\n\n/**\n* Gets the soldier's original armor (before transformation).\n* @return Pointer to armor data.\n*/\nArmor *Soldier::getTransformedArmor() const\n{\n\treturn _transformedArmor;\n}\n\n/**\n* Backs up the soldier's original armor (before transformation).\n* @param armor Pointer to armor data.\n*/\nvoid Soldier::setTransformedArmor(Armor *armor)\n{\n\t_transformedArmor = armor;\n}\n\nnamespace\n{\n\n/**\n * Calculates absolute threshold based on percentage threshold.\n * @param base base value\n * @param threshold threshold in percent\n * @return threshold in absolute value\n */\nint valueThreshold(int base, int threshold)\n{\n\treturn base * threshold / 100;\n}\n\n/**\n * Calculates the amount that exceeds the threshold of the base value.\n * @param value value to check\n * @param base base value\n * @param threshold threshold of the base value in percent\n * @return absolute value over the threshold\n */\nint valueOverThreshold(int value, int base, int threshold)\n{\n\treturn std::max(0, value - valueThreshold(base, threshold));\n}\n\n/**\n * Calculates how long will it take to recover.\n * @param current Total amount of days.\n * @param recovery Recovery per day.\n * @return How many days will it take to recover, can return -1 meaning infinity.\n */\nint recoveryTime(int current, int recovery)\n{\n\tif (current <= 0)\n\t{\n\t\treturn 0;\n\t}\n\n\tif (recovery <= 0)\n\t\treturn -1; // represents infinity\n\n\tint days = current / recovery;\n\tif (current % recovery > 0)\n\t\t++days;\n\n\treturn days;\n}\n\n\n}\n\n\n/**\n* Is the soldier wounded or not?.\n* @return True if wounded.\n*/\nbool Soldier::isWounded() const\n{\n\tif (_manaMissing > 0)\n\t{\n\t\tif (valueOverThreshold(_manaMissing, _currentStats.mana, _rules->getManaWoundThreshold()))\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t}\n\tif (_healthMissing > 0)\n\t{\n\t\tif (valueOverThreshold(_healthMissing, _currentStats.health, _rules->getHealthWoundThreshold()))\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn _recovery > 0.0f;\n}\n\n/**\n* Is the soldier wounded or not?.\n* @return False if wounded.\n*/\nbool Soldier::hasFullHealth() const\n{\n\treturn !isWounded();\n}\n\n/**\n * Is the soldier capable of defending a base?.\n * @return False if wounded too much.\n */\nbool Soldier::canDefendBase() const\n{\n\tint currentHealthPercentage = std::max(0, _currentStats.health - getWoundRecoveryInt() - getHealthMissing()) * 100 / _currentStats.health;\n\treturn currentHealthPercentage >= Options::oxceWoundedDefendBaseIf;\n}\n\n\n/**\n * Returns the amount of missing mana.\n * @return Missing mana.\n */\nint Soldier::getManaMissing() const\n{\n\treturn _manaMissing;\n}\n\n/**\n * Sets the amount of missing mana.\n * @param manaMissing Missing mana.\n */\nvoid Soldier::setManaMissing(int manaMissing)\n{\n\t_manaMissing = std::max(manaMissing, 0);\n}\n\n/**\n * Returns the amount of time until the soldier's mana is fully replenished.\n * @return Number of days. -1 represents infinity.\n */\nint Soldier::getManaRecovery(int manaRecoveryPerDay) const\n{\n\treturn recoveryTime(_manaMissing, manaRecoveryPerDay);\n}\n\n\n/**\n * Returns the amount of missing health.\n * @return Missing health.\n */\nint Soldier::getHealthMissing() const\n{\n\treturn _healthMissing;\n}\n\n/**\n * Sets the amount of missing health.\n * @param healthMissing Missing health.\n */\nvoid Soldier::setHealthMissing(int healthMissing)\n{\n\t_healthMissing = std::max(healthMissing, 0);\n}\n\n/**\n * Returns the amount of time until the soldier's health is fully replenished.\n * @return Number of days. -1 represents infinity.\n */\nint Soldier::getHealthRecovery(int healthRecoveryPerDay) const\n{\n\treturn recoveryTime(_healthMissing, healthRecoveryPerDay);\n}\n\n\n/**\n * Returns the amount of time until the soldier is healed.\n * @return Number of days.\n */\nint Soldier::getWoundRecoveryInt() const\n{\n\t// Note: only for use in Yankes scripts! ...and in base defense HP calculations :/\n\treturn (int)(std::ceil(_recovery));\n}\n\nint Soldier::getWoundRecovery(float absBonus, float relBonus) const\n{\n\tfloat hpPerDay = 1.0f + absBonus + (relBonus * _currentStats.health * 0.01f);\n\treturn (int)(std::ceil(_recovery / hpPerDay));\n}\n\n/**\n * Changes the amount of time until the soldier is healed.\n * @param recovery Number of days.\n */\nvoid Soldier::setWoundRecovery(int recovery)\n{\n\t_recovery = std::max(recovery, 0);\n}\n\n\n/**\n * Heals soldier wounds.\n */\nvoid Soldier::healWound(float absBonus, float relBonus)\n{\n\t// 1 hp per day as minimum\n\t_recovery -= 1.0f;\n\n\t// absolute bonus from sick bay facilities\n\t_recovery -= absBonus;\n\n\t// relative bonus from sick bay facilities\n\t_recovery -= (relBonus * _currentStats.health * 0.01f);\n\n\tif (_recovery < 0.0f)\n\t\t_recovery = 0.0f;\n}\n\n/**\n * Replenishes the soldier's mana.\n */\nvoid Soldier::replenishMana(int manaRecoveryPerDay)\n{\n\t_manaMissing -= manaRecoveryPerDay;\n\n\tif (_manaMissing < 0)\n\t\t_manaMissing = 0;\n\n\t// maximum amount of mana missing can be up to 2x the current mana pool (WITHOUT armor and bonuses!); at least 100\n\tint maxThreshold = std::max(100, _currentStats.mana * 2);\n\tif (_manaMissing > maxThreshold)\n\t\t_manaMissing = maxThreshold;\n}\n\n/**\n * Replenishes the soldier's health.\n */\nvoid Soldier::replenishHealth(int healthRecoveryPerDay)\n{\n\t_healthMissing -= healthRecoveryPerDay;\n\n\tif (_healthMissing < 0)\n\t\t_healthMissing = 0;\n}\n\n/**\n * Daily stat replenish and healing of the soldier based on the facilities available in the base.\n * @param recovery Recovery values provided by the base.\n */\nvoid Soldier::replenishStats(const BaseSumDailyRecovery& recovery)\n{\n\tif (_recovery > 0.0f)\n\t{\n\t\thealWound(recovery.SickBayAbsoluteBonus, recovery.SickBayRelativeBonus);\n\t}\n\telse\n\t{\n\t\tif (getManaMissing() > 0 && recovery.ManaRecovery > 0)\n\t\t{\n\t\t\t// positive mana recovery only when NOT wounded\n\t\t\treplenishMana(recovery.ManaRecovery);\n\t\t}\n\n\t\tif (getHealthMissing() > 0 && recovery.HealthRecovery > 0)\n\t\t{\n\t\t\t// health recovery only when NOT wounded\n\t\t\treplenishHealth(recovery.HealthRecovery);\n\t\t}\n\t}\n\n\tif (recovery.ManaRecovery  < 0)\n\t{\n\t\t// negative mana recovery always\n\t\treplenishMana(recovery.ManaRecovery);\n\t}\n}\n\n/**\n * Gets number of days until the soldier is ready for action again.\n * @return Number of days. -1 represents infinity.\n */\nint Soldier::getNeededRecoveryTime(const BaseSumDailyRecovery& recovery) const\n{\n\tint time = getWoundRecovery(recovery.SickBayAbsoluteBonus, recovery.SickBayRelativeBonus);\n\n\tint bonusTime = 0;\n\tif (_healthMissing > 0)\n\t{\n\t\tint t = recoveryTime(\n\t\t\tvalueOverThreshold(_healthMissing, _currentStats.health, _rules->getHealthWoundThreshold()),\n\t\t\trecovery.HealthRecovery\n\t\t);\n\n\t\tif (t < 0)\n\t\t{\n\t\t\treturn t;\n\t\t}\n\n\t\tbonusTime = std::max(bonusTime, t);\n\t}\n\tif (_manaMissing > 0)\n\t{\n\t\tint t = recoveryTime(\n\t\t\tvalueOverThreshold(_manaMissing, _currentStats.mana, _rules->getManaWoundThreshold()),\n\t\t\trecovery.ManaRecovery\n\t\t);\n\n\t\tif (t < 0)\n\t\t{\n\t\t\treturn t;\n\t\t}\n\n\t\tbonusTime = std::max(bonusTime, t);\n\t}\n\n\treturn time + bonusTime;\n}\n\n\n\n/**\n * Returns the list of EquipmentLayoutItems of a soldier.\n * @return Pointer to the EquipmentLayoutItem list.\n */\nstd::vector<EquipmentLayoutItem*> *Soldier::getEquipmentLayout()\n{\n\treturn &_equipmentLayout;\n}\n\n/**\n * Trains a soldier's Psychic abilities after 1 month.\n */\nvoid Soldier::trainPsi()\n{\n\tUnitStats::Type psiSkillCap = _rules->getStatCaps().psiSkill;\n\tUnitStats::Type psiStrengthCap = _rules->getStatCaps().psiStrength;\n\n\t_improvement = _psiStrImprovement = 0;\n\t// -10 days - tolerance threshold for switch from anytimePsiTraining option.\n\t// If soldier has psi skill -10..-1, he was trained 20..59 days. 81.7% probability, he was trained more that 30 days.\n\tif (_currentStats.psiSkill < -10 + _rules->getMinStats().psiSkill)\n\t\t_currentStats.psiSkill = _rules->getMinStats().psiSkill;\n\telse if (_currentStats.psiSkill <= _rules->getMaxStats().psiSkill)\n\t{\n\t\tint max = _rules->getMaxStats().psiSkill + _rules->getMaxStats().psiSkill / 2;\n\t\t_improvement = RNG::generate(_rules->getMaxStats().psiSkill, max);\n\t}\n\telse\n\t{\n\t\tif (_currentStats.psiSkill <= (psiSkillCap / 2)) _improvement = RNG::generate(5, 12);\n\t\telse if (_currentStats.psiSkill < psiSkillCap) _improvement = RNG::generate(1, 3);\n\n\t\tif (Options::allowPsiStrengthImprovement)\n\t\t{\n\t\t\tif (_currentStats.psiStrength <= (psiStrengthCap / 2)) _psiStrImprovement = RNG::generate(5, 12);\n\t\t\telse if (_currentStats.psiStrength < psiStrengthCap) _psiStrImprovement = RNG::generate(1, 3);\n\t\t}\n\t}\n\t_currentStats.psiSkill = std::max(_currentStats.psiSkill, std::min<UnitStats::Type>(_currentStats.psiSkill+_improvement, psiSkillCap));\n\t_currentStats.psiStrength = std::max(_currentStats.psiStrength, std::min<UnitStats::Type>(_currentStats.psiStrength+_psiStrImprovement, psiStrengthCap));\n}\n\n/**\n * Trains a soldier's Psychic abilities after 1 day.\n * (anytimePsiTraining option)\n */\nvoid Soldier::trainPsi1Day()\n{\n\tif (!_psiTraining)\n\t{\n\t\t_improvement = 0;\n\t\treturn;\n\t}\n\n\tif (_currentStats.psiSkill > 0) // yes, 0. _rules->getMinStats().psiSkill was wrong.\n\t{\n\t\tif (8 * 100 >= _currentStats.psiSkill * RNG::generate(1, 100) && _currentStats.psiSkill < _rules->getStatCaps().psiSkill)\n\t\t{\n\t\t\t++_improvement;\n\t\t\t++_currentStats.psiSkill;\n\t\t}\n\n\t\tif (Options::allowPsiStrengthImprovement)\n\t\t{\n\t\t\tif (8 * 100 >= _currentStats.psiStrength * RNG::generate(1, 100) && _currentStats.psiStrength < _rules->getStatCaps().psiStrength)\n\t\t\t{\n\t\t\t\t++_psiStrImprovement;\n\t\t\t\t++_currentStats.psiStrength;\n\t\t\t}\n\t\t}\n\t}\n\telse if (_currentStats.psiSkill < _rules->getMinStats().psiSkill)\n\t{\n\t\tif (++_currentStats.psiSkill == _rules->getMinStats().psiSkill)\t// initial training is over\n\t\t{\n\t\t\t_improvement = _rules->getMaxStats().psiSkill + RNG::generate(0, _rules->getMaxStats().psiSkill / 2);\n\t\t\t_currentStats.psiSkill = _improvement;\n\t\t}\n\t}\n\telse // minStats.psiSkill <= 0 && _currentStats.psiSkill == minStats.psiSkill\n\t\t_currentStats.psiSkill -= RNG::generate(30, 60);\t// set initial training from 30 to 60 days\n}\n\n/**\n * Is the soldier already fully psi-trained?\n * @return True, if the soldier cannot gain any more stats in the psi-training facility.\n */\nbool Soldier::isFullyPsiTrained()\n{\n\tif (_currentStats.psiSkill >= _rules->getStatCaps().psiSkill)\n\t{\n\t\tif (Options::allowPsiStrengthImprovement)\n\t\t{\n\t\t\tif (_currentStats.psiStrength >= _rules->getStatCaps().psiStrength)\n\t\t\t{\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * returns whether or not the unit is in psi training\n * @return true/false\n */\nbool Soldier::isInPsiTraining() const\n{\n\treturn _psiTraining;\n}\n\n/**\n * changes whether or not the unit is in psi training\n */\nvoid Soldier::setPsiTraining(bool psi)\n{\n\t_psiTraining = psi;\n}\n\n/**\n * returns this soldier's psionic skill improvement score for this month.\n * @return score\n */\nint Soldier::getImprovement() const\n{\n\treturn _improvement;\n}\n\n/**\n * returns this soldier's psionic strength improvement score for this month.\n */\nint Soldier::getPsiStrImprovement() const\n{\n\treturn _psiStrImprovement;\n}\n\n/**\n * Returns the soldier's death details.\n * @return Pointer to death data. NULL if no death has occurred.\n */\nSoldierDeath *Soldier::getDeath() const\n{\n\treturn _death;\n}\n\n/**\n * Kills the soldier in the Geoscape.\n * @param death Pointer to death data.\n */\nvoid Soldier::die(SoldierDeath *death)\n{\n\tdelete _death;\n\t_death = death;\n\n\t// Clean up associations\n\t_craft = 0;\n\t_psiTraining = false;\n\t_training = false;\n\t_returnToTrainingWhenHealed = false;\n\t_recentlyPromoted = false;\n\t_manaMissing = 0;\n\t_healthMissing = 0;\n\t_recovery = 0.0f;\n\tclearEquipmentLayout();\n\tCollections::deleteAll(_personalEquipmentLayout);\n}\n\n/**\n * Clears the equipment layout.\n */\nvoid Soldier::clearEquipmentLayout()\n{\n\tfor (auto* entry : _equipmentLayout)\n\t{\n\t\tdelete entry;\n\t}\n\t_equipmentLayout.clear();\n}\n\n/**\n * Returns the soldier's diary.\n * @return Diary.\n */\nSoldierDiary *Soldier::getDiary()\n{\n\treturn _diary;\n}\nconst SoldierDiary* Soldier::getDiary() const\n{\n\treturn _diary;\n}\n\n/**\n* Resets the soldier's diary.\n*/\nvoid Soldier::resetDiary()\n{\n\tdelete _diary;\n\t_diary = new SoldierDiary();\n}\n\n/**\n * Calculates the soldier's statString\n * Calculates the soldier's statString.\n * @param statStrings List of statString rules.\n * @param psiStrengthEval Are psi stats available?\n */\nvoid Soldier::calcStatString(const std::vector<StatString *> &statStrings, bool psiStrengthEval)\n{\n\tif (_rules->getStatStrings().empty())\n\t{\n\t\t_statString = StatString::calcStatString(_currentStats, statStrings, psiStrengthEval, _psiTraining);\n\t}\n\telse\n\t{\n\t\t_statString = StatString::calcStatString(_currentStats, _rules->getStatStrings(), psiStrengthEval, _psiTraining);\n\t}\n}\n\n/**\n * Trains a soldier's Physical abilities\n */\nvoid Soldier::trainPhys(int customTrainingFactor)\n{\n\tUnitStats caps1 = _rules->getStatCaps();\n\tUnitStats caps2 = _rules->getTrainingStatCaps();\n\t// no P.T. for the wounded\n\tif (hasFullHealth())\n\t{\n\t\tif(_currentStats.firing < caps1.firing && RNG::generate(0, caps2.firing) > _currentStats.firing && RNG::percent(customTrainingFactor))\n\t\t\t_currentStats.firing++;\n\t\tif(_currentStats.health < caps1.health && RNG::generate(0, caps2.health) > _currentStats.health && RNG::percent(customTrainingFactor))\n\t\t\t_currentStats.health++;\n\t\tif(_currentStats.melee < caps1.melee && RNG::generate(0, caps2.melee) > _currentStats.melee && RNG::percent(customTrainingFactor))\n\t\t\t_currentStats.melee++;\n\t\tif(_currentStats.throwing < caps1.throwing && RNG::generate(0, caps2.throwing) > _currentStats.throwing && RNG::percent(customTrainingFactor))\n\t\t\t_currentStats.throwing++;\n\t\tif(_currentStats.strength < caps1.strength && RNG::generate(0, caps2.strength) > _currentStats.strength && RNG::percent(customTrainingFactor))\n\t\t\t_currentStats.strength++;\n\t\tif(_currentStats.tu < caps1.tu && RNG::generate(0, caps2.tu) > _currentStats.tu && RNG::percent(customTrainingFactor))\n\t\t\t_currentStats.tu++;\n\t\tif(_currentStats.stamina < caps1.stamina && RNG::generate(0, caps2.stamina) > _currentStats.stamina && RNG::percent(customTrainingFactor))\n\t\t\t_currentStats.stamina++;\n\t}\n}\n\n/**\n * Is the soldier already fully trained?\n * @return True, if the soldier cannot gain any more stats in the training facility.\n */\nbool Soldier::isFullyTrained() const\n{\n\tUnitStats trainingCaps = _rules->getTrainingStatCaps();\n\n\tif (_currentStats.firing < trainingCaps.firing\n\t\t|| _currentStats.health < trainingCaps.health\n\t\t|| _currentStats.melee < trainingCaps.melee\n\t\t|| _currentStats.throwing < trainingCaps.throwing\n\t\t|| _currentStats.strength < trainingCaps.strength\n\t\t|| _currentStats.tu < trainingCaps.tu\n\t\t|| _currentStats.stamina < trainingCaps.stamina)\n\t{\n\t\treturn false;\n\t}\n\treturn true;\n}\n\n/**\n * returns whether or not the unit is in physical training\n */\nbool Soldier::isInTraining() const\n{\n\treturn _training;\n}\n\n/**\n * changes whether or not the unit is in physical training\n */\nvoid Soldier::setTraining(bool training)\n{\n\t_training = training;\n}\n\n/**\n * Should the soldier return to martial training automatically when fully healed?\n */\nbool Soldier::getReturnToTrainingWhenHealed() const\n{\n\treturn _returnToTrainingWhenHealed;\n}\n\n/**\n * Sets whether the soldier should return to martial training automatically when fully healed.\n */\nvoid Soldier::setReturnToTrainingWhenHealed(bool returnToTrainingWhenHealed)\n{\n\t_returnToTrainingWhenHealed = returnToTrainingWhenHealed;\n}\n\n/**\n * Sets whether or not the unit's corpse was recovered from a battle\n */\nvoid Soldier::setCorpseRecovered(bool corpseRecovered)\n{\n\t_corpseRecovered = corpseRecovered;\n}\n\n/**\n * Gets the previous transformations performed on this soldier\n * @return The map of previous transformations\n */\nstd::map<std::string, int> &Soldier::getPreviousTransformations()\n{\n\treturn _previousTransformations;\n}\n\n/**\n * Checks whether or not the soldier is eligible for a certain transformation\n */\nbool Soldier::isEligibleForTransformation(const RuleSoldierTransformation *transformationRule) const\n{\n\t// rank check\n\tif ((int)_rank < transformationRule->getMinRank())\n\t\treturn false;\n\n\t// alive and well\n\tif (!_death && !isWounded() && !transformationRule->isAllowingAliveSoldiers())\n\t\treturn false;\n\n\t// alive and wounded\n\tif (!_death && isWounded() && !transformationRule->isAllowingWoundedSoldiers())\n\t\treturn false;\n\n\t// dead\n\tif (_death && !transformationRule->isAllowingDeadSoldiers())\n\t\treturn false;\n\n\t// dead and vaporized, or missing in action\n\tif (_death && !_corpseRecovered && transformationRule->needsCorpseRecovered())\n\t\treturn false;\n\n\t// Is the soldier of the correct type?\n\tconst auto& allowedTypes = transformationRule->getAllowedSoldierTypes();\n\tauto it = std::find(allowedTypes.begin(), allowedTypes.end(), _rules->getType());\n\tif (it == allowedTypes.end())\n\t\treturn false;\n\n\t// Does this soldier's transformation history preclude this new project?\n\tfor (const auto& reqd_trans : transformationRule->getRequiredPreviousTransformations())\n\t{\n\t\tif (_previousTransformations.find(reqd_trans) == _previousTransformations.end())\n\t\t\treturn false;\n\t}\n\n\tfor (const auto& forb_trans : transformationRule->getForbiddenPreviousTransformations())\n\t{\n\t\tif (_previousTransformations.find(forb_trans) != _previousTransformations.end())\n\t\t\treturn false;\n\t}\n\n\t// Does this soldier meet the minimum stat requirements for the project?\n\tUnitStats currentStats = transformationRule->getIncludeBonusesForMinStats() ? _tmpStatsWithSoldierBonuses: _currentStats;\n\tUnitStats minStats = transformationRule->getRequiredMinStats();\n\tif (currentStats.tu < minStats.tu ||\n\t\tcurrentStats.stamina < minStats.stamina ||\n\t\tcurrentStats.health < minStats.health ||\n\t\tcurrentStats.bravery < minStats.bravery ||\n\t\tcurrentStats.reactions < minStats.reactions ||\n\t\tcurrentStats.firing < minStats.firing ||\n\t\tcurrentStats.throwing < minStats.throwing ||\n\t\tcurrentStats.melee < minStats.melee ||\n\t\tcurrentStats.mana < minStats.mana ||\n\t\tcurrentStats.strength < minStats.strength ||\n\t\tcurrentStats.psiStrength < minStats.psiStrength ||\n\t\t(currentStats.psiSkill < minStats.psiSkill && minStats.psiSkill != 0)) // The != 0 is required for the \"psi training at any time\" option, as it sets skill to negative in training\n\t\treturn false;\n\n\t// Does this soldier meet the maximum stat requirements for the project?\n\tcurrentStats = transformationRule->getIncludeBonusesForMaxStats() ? _tmpStatsWithSoldierBonuses : _currentStats;\n\tUnitStats maxStats = transformationRule->getRequiredMaxStats();\n\tif (currentStats.tu > maxStats.tu ||\n\t\tcurrentStats.stamina > maxStats.stamina ||\n\t\tcurrentStats.health > maxStats.health ||\n\t\tcurrentStats.bravery > maxStats.bravery ||\n\t\tcurrentStats.reactions > maxStats.reactions ||\n\t\tcurrentStats.firing > maxStats.firing ||\n\t\tcurrentStats.throwing > maxStats.throwing ||\n\t\tcurrentStats.melee > maxStats.melee ||\n\t\tcurrentStats.mana > maxStats.mana ||\n\t\tcurrentStats.strength > maxStats.strength ||\n\t\tcurrentStats.psiStrength > maxStats.psiStrength ||\n\t\tcurrentStats.psiSkill > maxStats.psiSkill)\n\t\treturn false;\n\n\t// Does the soldier have the required commendations?\n\tfor (const auto& reqd_comm : transformationRule->getRequiredCommendations())\n\t{\n\t\tbool found = false;\n\t\tfor (const auto* comm : *_diary->getSoldierCommendations())\n\t\t{\n\t\t\tif (comm->getDecorationLevelInt() >= reqd_comm.second && comm->getType() == reqd_comm.first)\n\t\t\t{\n\t\t\t\tfound = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (!found)\n\t\t\treturn false;\n\t}\n\n\treturn true;\n}\n\n/**\n * Performs a transformation on this unit\n */\nvoid Soldier::transform(const Mod *mod, RuleSoldierTransformation *transformationRule, Soldier *sourceSoldier, Base *base)\n{\n\tif (_death)\n\t{\n\t\t_corpseRecovered = false; // They're not a corpse anymore!\n\t\tdelete _death;\n\t\t_death = 0;\n\t}\n\n\tif (transformationRule->getRecoveryTime() > 0)\n\t{\n\t\t_recovery = transformationRule->getRecoveryTime();\n\t}\n\n\t// needed, because the armor size may change (also, it just makes sense)\n\tsourceSoldier->setCraftAndMoveEquipment(0, base, false);\n\n\tif (transformationRule->isCreatingClone())\n\t{\n\t\t// a clone already has the correct soldier type, but random stats\n\t\t// if we don't want random stats, let's copy them from the source soldier\n\t\tUnitStats sourceStats = *sourceSoldier->getCurrentStats() + calculateStatChanges(mod, transformationRule, sourceSoldier, 0, sourceSoldier->getRules());\n\t\tUnitStats mergedStats = UnitStats::combine(transformationRule->getRerollStats(), sourceStats, _currentStats);\n\t\tsetBothStats(&mergedStats);\n\t}\n\telse\n\t{\n\t\t// backup original soldier type, it will still be needed later for stat change calculations\n\t\tRuleSoldier* sourceSoldierType = _rules;\n\n\t\t// change soldier type if needed\n\t\tif (!Mod::isEmptyRuleName(transformationRule->getProducedSoldierType()) && _rules->getType() != transformationRule->getProducedSoldierType())\n\t\t{\n\t\t\t_rules = mod->getSoldier(transformationRule->getProducedSoldierType());\n\n\t\t\t// demote soldier if needed (i.e. when new soldier type doesn't support the current rank)\n\t\t\tif (!_rules->getAllowPromotion())\n\t\t\t{\n\t\t\t\t_rank = RANK_ROOKIE;\n\t\t\t}\n\t\t\telse if (!_rules->getRankStrings().empty() && (size_t)_rank > _rules->getRankStrings().size() - 1)\n\t\t\t{\n\t\t\t\tswitch (_rules->getRankStrings().size() - 1)\n\t\t\t\t{\n\t\t\t\tcase 1:\n\t\t\t\t\t_rank = RANK_SQUADDIE;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 2:\n\t\t\t\t\t_rank = RANK_SERGEANT;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 3:\n\t\t\t\t\t_rank = RANK_CAPTAIN;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 4:\n\t\t\t\t\t_rank = RANK_COLONEL;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 5:\n\t\t\t\t\t_rank = RANK_COMMANDER; // I hereby demote you to commander! :P\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\t_rank = RANK_ROOKIE;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// clamp (and randomize) nationality if needed\n\t\t\t{\n\t\t\t\tconst std::vector<SoldierNamePool *> &names = _rules->getNames();\n\t\t\t\tif (!names.empty())\n\t\t\t\t{\n\t\t\t\t\tif ((size_t)_nationality >= _rules->getNames().size())\n\t\t\t\t\t{\n\t\t\t\t\t\t_nationality = RNG::generate(0, names.size() - 1);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t_nationality = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// handle training (soldier type change rules)\n\t\tif (sourceSoldierType != _rules && _rules->getTrainingStatCaps().psiSkill <= 0)\n\t\t{\n\t\t\t// transformed into a new soldier type, which doesn't support psi training\n\t\t\t_psiTraining = false;\n\t\t}\n\t\t// handle training (recovery rules)\n\t\tif (_training && isWounded())\n\t\t{\n\t\t\t_training = false;\n\t\t\t_returnToTrainingWhenHealed = true;\n\t\t}\n\n\t\t// reset soldier rank, if needed\n\t\tif (transformationRule->getResetRank())\n\t\t{\n\t\t\t_rank = RANK_ROOKIE;\n\t\t}\n\n\t\t// change stats\n\t\t_currentStats += calculateStatChanges(mod, transformationRule, sourceSoldier, 0, sourceSoldierType);\n\n\t\t// and randomize stats where needed\n\t\t{\n\t\t\tSoldier *tmpSoldier = new Soldier(_rules, nullptr, 0 /*nationality*/, _id);\n\t\t\t_currentStats = UnitStats::combine(transformationRule->getRerollStats(), _currentStats, *tmpSoldier->getCurrentStats());\n\t\t\tdelete tmpSoldier;\n\t\t\ttmpSoldier = 0;\n\t\t}\n\t}\n\n\tif (!transformationRule->isKeepingSoldierArmor())\n\t{\n\t\tauto* oldArmor = _armor;\n\t\tif (Mod::isEmptyRuleName(transformationRule->getProducedSoldierArmor()))\n\t\t{\n\t\t\t// default armor of the soldier's type\n\t\t\t_armor = _rules->getDefaultArmor();\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// explicitly defined armor\n\t\t\t_armor = mod->getArmor(transformationRule->getProducedSoldierArmor());\n\t\t}\n\t\tif (oldArmor != _armor && !transformationRule->isCreatingClone())\n\t\t{\n\t\t\tif (oldArmor->getStoreItem())\n\t\t\t{\n\t\t\t\tbase->getStorageItems()->addItem(oldArmor->getStoreItem());\n\t\t\t}\n\t\t}\n\t}\n\n\t// Reset performed transformations (on the destination soldier), if needed\n\tif (transformationRule->getReset())\n\t{\n\t\t_previousTransformations.clear();\n\t}\n\telse if (!transformationRule->getRemoveTransformations().empty())\n\t{\n\t\t// Remove specific transformations and their related bonuses\n\t\tfor (const auto& remove_transf : transformationRule->getRemoveTransformations())\n\t\t{\n\t\t\tint count = 0;\n\t\t\tauto it1 = _previousTransformations.find(remove_transf);\n\t\t\tif (it1 != _previousTransformations.end())\n\t\t\t{\n\t\t\t\tcount = it1->second;\n\t\t\t\t_previousTransformations.erase(remove_transf);\n\t\t\t}\n\t\t\tif (count > 0)\n\t\t\t{\n\t\t\t\tconst auto* rtRule = mod->getSoldierTransformation(remove_transf, false);\n\t\t\t\tif (rtRule)\n\t\t\t\t{\n\t\t\t\t\tif (!Mod::isEmptyRuleName(rtRule->getSoldierBonusType()))\n\t\t\t\t\t{\n\t\t\t\t\t\tauto it2 = _transformationBonuses.find(rtRule->getSoldierBonusType());\n\t\t\t\t\t\tif (it2 != _transformationBonuses.end())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (it2->second > count)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tit2->second -= count;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t_transformationBonuses.erase(rtRule->getSoldierBonusType());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Remember the performed transformation (on the source soldier)\n\tauto& history = sourceSoldier->getPreviousTransformations();\n\tauto it = history.find(transformationRule->getName());\n\tif (it != history.end())\n\t{\n\t\tit->second += 1;\n\t}\n\telse\n\t{\n\t\thistory[transformationRule->getName()] = 1;\n\t}\n\n\t// Reset soldier bonuses, if needed\n\tif (transformationRule->getReset())\n\t{\n\t\t_transformationBonuses.clear();\n\t}\n\n\t// Award a soldier bonus, if defined\n\tif (!Mod::isEmptyRuleName(transformationRule->getSoldierBonusType()))\n\t{\n\t\tauto it2 = _transformationBonuses.find(transformationRule->getSoldierBonusType());\n\t\tif (it2 != _transformationBonuses.end())\n\t\t{\n\t\t\tit2->second += 1;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_transformationBonuses[transformationRule->getSoldierBonusType()] = 1;\n\t\t}\n\t}\n}\n\n/**\n * Calculates the stat changes a soldier undergoes from this project\n * @param mod Pointer to the mod\n * @param mode 0 = final, 1 = min, 2 = max\n * @return The stat changes\n */\nUnitStats Soldier::calculateStatChanges(const Mod *mod, RuleSoldierTransformation *transformationRule, Soldier *sourceSoldier, int mode, const RuleSoldier *sourceSoldierType)\n{\n\tUnitStats statChange;\n\n\tUnitStats initialStats = *sourceSoldier->getInitStats();\n\tUnitStats currentStats = *sourceSoldier->getCurrentStats();\n\tUnitStats gainedStats = currentStats - initialStats;\n\n\t// Flat stat changes\n\tstatChange += transformationRule->getFlatOverallStatChange();\n\tUnitStats rnd0;\n\tif (mode == 2)\n\t\trnd0 = UnitStats::max(transformationRule->getFlatMin(), transformationRule->getFlatMax());\n\telse if (mode == 1)\n\t\trnd0 = UnitStats::min(transformationRule->getFlatMin(), transformationRule->getFlatMax());\n\telse\n\t\trnd0 = UnitStats::random(transformationRule->getFlatMin(), transformationRule->getFlatMax());\n\tstatChange += rnd0;\n\n\t// Stat changes based on current stats\n\tstatChange += UnitStats::percent(currentStats, transformationRule->getPercentOverallStatChange());\n\tUnitStats rnd1;\n\tif (mode == 2)\n\t\trnd1 = UnitStats::max(transformationRule->getPercentMin(), transformationRule->getPercentMax());\n\telse if (mode == 1)\n\t\trnd1 = UnitStats::min(transformationRule->getPercentMin(), transformationRule->getPercentMax());\n\telse\n\t\trnd1 = UnitStats::random(transformationRule->getPercentMin(), transformationRule->getPercentMax());\n\tstatChange += UnitStats::percent(currentStats, rnd1);\n\n\t// Stat changes based on gained stats\n\tstatChange += UnitStats::percent(gainedStats, transformationRule->getPercentGainedStatChange());\n\tUnitStats rnd2;\n\tif (mode == 2)\n\t\trnd2 = UnitStats::max(transformationRule->getPercentGainedMin(), transformationRule->getPercentGainedMax());\n\telse if (mode == 1)\n\t\trnd2 = UnitStats::min(transformationRule->getPercentGainedMin(), transformationRule->getPercentGainedMax());\n\telse\n\t\trnd2 = UnitStats::random(transformationRule->getPercentGainedMin(), transformationRule->getPercentGainedMax());\n\tstatChange += UnitStats::percent(gainedStats, rnd2);\n\n\t// round (mathematically) to whole tens\n\tint sign = statChange.bravery < 0 ? -1 : 1;\n\tstatChange.bravery = ((statChange.bravery + (sign * 5)) / 10) * 10;\n\n\tRuleSoldier *transformationSoldierType = _rules;\n\tif (!Mod::isEmptyRuleName(transformationRule->getProducedSoldierType()))\n\t{\n\t\ttransformationSoldierType = mod->getSoldier(transformationRule->getProducedSoldierType());\n\t}\n\n\tif (transformationRule->hasLowerBoundAtMinStats())\n\t{\n\t\tUnitStats lowerBound = transformationSoldierType->getMinStats();\n\t\tUnitStats cappedChange = lowerBound - currentStats;\n\n\t\tstatChange = UnitStats::max(statChange, cappedChange);\n\t}\n\n\tif (transformationRule->hasUpperBoundAtMaxStats() || transformationRule->hasUpperBoundAtStatCaps())\n\t{\n\t\tUnitStats upperBound = transformationRule->hasUpperBoundAtMaxStats()\n\t\t\t? transformationSoldierType->getMaxStats()\n\t\t\t: transformationSoldierType->getStatCaps();\n\t\tUnitStats cappedChange = upperBound - currentStats;\n\n\t\tbool isSameSoldierType = (transformationSoldierType == sourceSoldierType);\n\t\tbool softLimit = transformationRule->isSoftLimit(isSameSoldierType);\n\t\tif (softLimit)\n\t\t{\n\t\t\t// soft limit\n\t\t\tstatChange = UnitStats::softLimit(statChange, currentStats, upperBound);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// hard limit\n\t\t\tstatChange = UnitStats::min(statChange, cappedChange);\n\t\t}\n\t}\n\n\treturn statChange;\n}\n\n/**\n * Checks whether the soldier has a given bonus.\n * Disclaimer: DOES NOT REFRESH THE BONUS CACHE!\n */\nbool Soldier::hasBonus(const RuleSoldierBonus* bonus) const\n{\n\tfor (auto* sb : _bonusCache)\n\t{\n\t\tif (sb == bonus)\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Gets all the soldier bonuses\n * @return The map of soldier bonuses\n */\nconst std::vector<const RuleSoldierBonus*> *Soldier::getBonuses(const Mod *mod)\n{\n\tif (mod)\n\t{\n\t\t_bonusCache.clear();\n\t\tauto addSorted = [&](const RuleSoldierBonus* b)\n\t\t{\n\t\t\tif (!b)\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tauto sort = [](const RuleSoldierBonus* l, const RuleSoldierBonus* r){ return l->getListOrder() < r->getListOrder(); };\n\n\t\t\tauto p = std::lower_bound(_bonusCache.begin(), _bonusCache.end(), b, sort);\n\t\t\tif (p == _bonusCache.end() || *p != b)\n\t\t\t{\n\t\t\t\t_bonusCache.insert(p, b);\n\t\t\t}\n\t\t};\n\n\t\tfor (const auto& bonusName : _transformationBonuses)\n\t\t{\n\t\t\tauto* bonusRule = mod->getSoldierBonus(bonusName.first, false);\n\n\t\t\taddSorted(bonusRule);\n\t\t}\n\t\tfor (auto* commendation : *_diary->getSoldierCommendations())\n\t\t{\n\t\t\tauto* bonusRule = commendation->getRule()->getSoldierBonus(commendation->getDecorationLevelInt());\n\n\t\t\taddSorted(bonusRule);\n\t\t}\n\t}\n\n\treturn &_bonusCache;\n}\n\n/**\n * Get pointer to current stats with soldier bonuses, but without armor bonuses.\n */\nconst UnitStats *Soldier::getStatsWithSoldierBonusesOnly() const\n{\n\treturn &_tmpStatsWithSoldierBonuses;\n}\n\n/**\n * Get pointer to current stats with armor and soldier bonuses.\n */\nconst UnitStats *Soldier::getStatsWithAllBonuses() const\n{\n\treturn &_tmpStatsWithAllBonuses;\n}\n\n/**\n * Pre-calculates soldier stats with various bonuses.\n */\nbool Soldier::prepareStatsWithBonuses(const Mod *mod)\n{\n\tbool hasSoldierBonus = false;\n\n\t// 1. current stats\n\tUnitStats tmp = _currentStats;\n\tauto basePsiSkill = _currentStats.psiSkill;\n\n\t// 2. refresh soldier bonuses\n\tauto* bonuses = getBonuses(mod); // this is the only place where bonus cache is rebuilt\n\n\t// 3. apply soldier bonuses\n\tfor (const auto* bonusRule : *bonuses)\n\t{\n\t\thasSoldierBonus = true;\n\t\ttmp += *(bonusRule->getStats());\n\t}\n\n\t// 4. stats with soldier bonuses, but without armor bonuses\n\t_tmpStatsWithSoldierBonuses = UnitStats::obeyFixedMinimum(tmp);\n\n\t// if the psi skill has not been \"unlocked\" yet by training, do not allow soldier bonuses to unlock it\n\tif (basePsiSkill <= 0 && _tmpStatsWithSoldierBonuses.psiSkill > 0)\n\t{\n\t\t_tmpStatsWithSoldierBonuses.psiSkill = basePsiSkill;\n\t}\n\n\t// 5. apply armor bonus\n\ttmp += *_armor->getStats();\n\n\t// 6. stats with all bonuses\n\t_tmpStatsWithAllBonuses = UnitStats::obeyFixedMinimum(tmp);\n\n\t// 7. pilot armors count as soldier bonuses\n\tif (_armor->isPilotArmor())\n\t{\n\t\t_tmpStatsWithSoldierBonuses = _tmpStatsWithAllBonuses;\n\t}\n\n\treturn hasSoldierBonus;\n}\n\n/**\n * Gets a pointer to the daily dogfight experience cache.\n */\nUnitStats* Soldier::getDailyDogfightExperienceCache()\n{\n\treturn &_dailyDogfightExperienceCache;\n}\n\n/**\n * Resets the daily dogfight experience cache.\n */\nvoid Soldier::resetDailyDogfightExperienceCache()\n{\n\t_dailyDogfightExperienceCache = UnitStats::scalar(0);\n}\n\n/**\n * Check if the soldier has all the required soldier bonuses for the given soldier skill.\n * @param skillRules Skill rules.\n */\nbool Soldier::hasAllRequiredBonusesForSkill(const RuleSkill* skillRules)\n{\n\tfor (auto* requiredBonusRule : skillRules->getRequiredBonuses())\n\t{\n\t\tbool found = false;\n\t\tfor (auto* bonusRule : *getBonuses(nullptr))\n\t\t{\n\t\t\tif (bonusRule == requiredBonusRule)\n\t\t\t{\n\t\t\t\tfound = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (!found)\n\t\t\treturn false;\n\t}\n\treturn true;\n}\n\n/**\n * Check if the soldier has all the required stats and soldier bonuses for piloting the (current or new) craft.\n */\nbool Soldier::hasAllPilotingRequirements(const Craft* newCraft) const\n{\n\tif (!_rules->getAllowPiloting())\n\t\treturn false;\n\n\tconst Craft* craft = newCraft ? newCraft : _craft;\n\n\tif (!craft)\n\t\treturn false;\n\n\t// Does this soldier meet the minimum stat requirements for piloting the current craft?\n\tconst UnitStats& currentStats = _tmpStatsWithAllBonuses; // all bonuses count\n\tconst UnitStats& minStats = craft->getRules()->getPilotMinStatsRequired();\n\tif (currentStats.tu < minStats.tu ||\n\t\tcurrentStats.stamina < minStats.stamina ||\n\t\tcurrentStats.health < minStats.health ||\n\t\tcurrentStats.bravery < minStats.bravery ||\n\t\tcurrentStats.reactions < minStats.reactions ||\n\t\tcurrentStats.firing < minStats.firing ||\n\t\tcurrentStats.throwing < minStats.throwing ||\n\t\tcurrentStats.melee < minStats.melee ||\n\t\tcurrentStats.mana < minStats.mana ||\n\t\tcurrentStats.strength < minStats.strength ||\n\t\tcurrentStats.psiStrength < minStats.psiStrength ||\n\t\t(currentStats.psiSkill < minStats.psiSkill && minStats.psiSkill != 0)) // The != 0 is required for the \"psi training at any time\" option, as it sets skill to negative in training\n\t\treturn false;\n\n\t// Does this soldier have all required soldier bonuses for piloting the current craft?\n\tfor (auto* requiredBonusRule : craft->getRules()->getPilotSoldierBonusesRequired())\n\t{\n\t\tbool found = false;\n\t\tfor (auto* bonusRule : _bonusCache) // *getBonuses(nullptr)\n\t\t{\n\t\t\tif (bonusRule == requiredBonusRule)\n\t\t\t{\n\t\t\t\tfound = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (!found)\n\t\t\treturn false;\n\t}\n\n\treturn true;\n}\n\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tScript binding\n////////////////////////////////////////////////////////////\n\nnamespace\n{\n\nvoid getGenderScript(const Soldier *so, int &ret)\n{\n\tif (so)\n\t{\n\t\tret = so->getGender();\n\t\treturn;\n\t}\n\tret = 0;\n}\nvoid getRankScript(const Soldier *so, int &ret)\n{\n\tif (so)\n\t{\n\t\tret = so->getRank();\n\t\treturn;\n\t}\n\tret = 0;\n}\nvoid getLookScript(const Soldier *so, int &ret)\n{\n\tif (so)\n\t{\n\t\tret = so->getLook();\n\t\treturn;\n\t}\n\tret = 0;\n}\nvoid getLookVariantScript(const Soldier *so, int &ret)\n{\n\tif (so)\n\t{\n\t\tret = so->getLookVariant();\n\t\treturn;\n\t}\n\tret = 0;\n}\nstruct getRuleSoldierScript\n{\n\tstatic RetEnum func(const Soldier *so, const RuleSoldier* &ret)\n\t{\n\t\tif (so)\n\t\t{\n\t\t\tret = so->getRules();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tret = nullptr;\n\t\t}\n\t\treturn RetContinue;\n\t}\n};\n\nstd::string debugDisplayScript(const Soldier* so)\n{\n\tif (so)\n\t{\n\t\tstd::string s;\n\t\ts += Soldier::ScriptName;\n\t\ts += \"(type: \\\"\";\n\t\ts += so->getRules()->getType();\n\t\ts += \"\\\" id: \";\n\t\ts += std::to_string(so->getId());\n\t\ts += \" name: \\\"\";\n\t\ts += so->getName(false, 0);\n\t\ts += \"\\\")\";\n\t\treturn s;\n\t}\n\telse\n\t{\n\t\treturn \"null\";\n\t}\n}\n\n} // namespace\n\n/**\n * Register Soldier in script parser.\n * @param parser Script parser.\n */\nvoid Soldier::ScriptRegister(ScriptParserBase* parser)\n{\n\tparser->registerPointerType<RuleSoldier>();\n\n\tBind<Soldier> so = { parser };\n\n\n\tso.addField<&Soldier::_id>(\"getId\");\n\tso.add<&getRankScript>(\"getRank\");\n\tso.add<&getGenderScript>(\"getGender\");\n\tso.add<&getLookScript>(\"getLook\");\n\tso.add<&getLookVariantScript>(\"getLookVariant\");\n\n\n\tUnitStats::addGetStatsScript<&Soldier::_currentStats>(so, \"Stats.\");\n\tUnitStats::addSetStatsScript<&Soldier::_currentStats>(so, \"Stats.\");\n\n\n\tso.addFunc<getRuleSoldierScript>(\"getRuleSoldier\");\n\tso.add<&Soldier::getWoundRecoveryInt>(\"getWoundRecovery\");\n\tso.add<&Soldier::setWoundRecovery>(\"setWoundRecovery\");\n\tso.add<&Soldier::getManaMissing>(\"getManaMissing\");\n\tso.add<&Soldier::setManaMissing>(\"setManaMissing\");\n\tso.add<&Soldier::getHealthMissing>(\"getHealthMissing\");\n\tso.add<&Soldier::setHealthMissing>(\"setHealthMissing\");\n\n\n\tso.addScriptValue<BindBase::OnlyGet, &Soldier::_rules, &RuleSoldier::getScriptValuesRaw>();\n\tso.addScriptValue<&Soldier::_scriptValues>();\n\tso.addDebugDisplay<&debugDisplayScript>();\n}\n\n} // namespace OpenXcom\n"
  },
  {
    "path": "src/Savegame/Soldier.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include \"../Engine/Yaml.h\"\n#include \"../Mod/Unit.h\"\n#include \"../Mod/StatString.h\"\n#include \"../Engine/Script.h\"\n\nnamespace OpenXcom\n{\n\nenum SoldierRank : char { RANK_ROOKIE, RANK_SQUADDIE, RANK_SERGEANT, RANK_CAPTAIN, RANK_COLONEL, RANK_COMMANDER};\nenum SoldierGender : char { GENDER_MALE, GENDER_FEMALE };\nenum SoldierLook : char { LOOK_BLONDE, LOOK_BROWNHAIR, LOOK_ORIENTAL, LOOK_AFRICAN };\n\nclass Craft;\nclass SoldierNamePool;\nclass Mod;\nclass RuleSoldier;\nclass Armor;\nclass Language;\nclass EquipmentLayoutItem;\nclass SoldierDeath;\nclass SoldierDiary;\nclass SavedGame;\nclass RuleSoldierTransformation;\nclass RuleSoldierBonus;\nclass RuleSkill;\nclass Base;\nstruct BaseSumDailyRecovery;\n\n/**\n * Represents a soldier hired by the player.\n * Soldiers have a wide variety of stats that affect\n * their performance during battles.\n */\nclass Soldier\n{\npublic:\n\n\t/// Name of class used in script.\n\tstatic constexpr const char *ScriptName = \"GeoscapeSoldier\";\n\t/// Register all useful function used by script.\n\tstatic void ScriptRegister(ScriptParserBase* parser);\n\nprivate:\n\tstd::string _name;\n\tstd::string _callsign;\n\tint _id, _nationality, _improvement, _psiStrImprovement;\n\tRuleSoldier *_rules;\n\tUnitStats _initialStats, _currentStats, _tmpStatsWithSoldierBonuses, _tmpStatsWithAllBonuses;\n\tUnitStats _dailyDogfightExperienceCache;\n\tSoldierRank _rank;\n\tCraft *_craft;\n\tSoldierGender _gender;\n\tSoldierLook _look;\n\tint _lookVariant;\n\tint _missions, _kills, _stuns;\n\tint _healthMissing = 0; // amount of health missing until full health recovery, this is less serious than wound recovery.\n\tint _manaMissing = 0;   // amount of mana missing until full mana recovery\n\tfloat _recovery = 0.0;  // amount of hospital attention soldier needs... used to calculate recovery time\n\tbool _recentlyPromoted, _psiTraining, _training, _returnToTrainingWhenHealed;\n\tArmor *_armor;\n\tArmor *_replacedArmor;\n\tArmor *_transformedArmor;\n\tstd::vector<EquipmentLayoutItem*> _equipmentLayout;           // last used equipment layout, managed by the game\n\tstd::vector<EquipmentLayoutItem*> _personalEquipmentLayout;   // personal  equipment layout, managed by the player\n\tconst Armor* _personalEquipmentArmor;\n\tSoldierDeath *_death;\n\tSoldierDiary *_diary;\n\tstd::string _statString;\n\tbool _corpseRecovered;\n\tstd::map<std::string, int> _previousTransformations, _transformationBonuses;\n\tstd::vector<const RuleSoldierBonus*> _bonusCache;\n\tScriptValues<Soldier> _scriptValues;\npublic:\n\t/// Creates a new soldier.\n\tSoldier(RuleSoldier *rules, Armor *armor, int nationality, int id = 0);\n\t/// Cleans up the soldier.\n\t~Soldier();\n\t/// Loads the soldier from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader, const Mod *mod, SavedGame *save, const ScriptGlobal *shared, bool soldierTemplate = false);\n\t/// Saves the soldier to YAML.\n\tvoid save(YAML::YamlNodeWriter writer, const ScriptGlobal *shared) const;\n\t/// Gets the soldier's name.\n\tstd::string getName(bool statstring = false, unsigned int maxLength = 20) const;\n\t/// Sets the soldier's name.\n\tvoid setName(const std::string &name);\n\t/// Generates a new name based on nationality.\n\tvoid genName();\n\t/// Gets the soldier's callsign.\n\tstd::string getCallsign(unsigned int maxLength = 20) const;\n\t/// Sets the soldier's callsign.\n\tvoid setCallsign(const std::string &callsign);\n\t/// Check for callsign assignment.\n\tbool hasCallsign() const;\n\t/// Gets the soldier's nationality.\n\tint getNationality() const;\n\t/// Sets the soldier's nationality.\n\tvoid setNationality(int nationality);\n\t/// Gets the soldier's craft.\n\tCraft *getCraft() const;\n\t/// Sets the soldier's craft.\n\tvoid setCraft(Craft *craft, bool resetCustomDeployment = false);\n\t/// Sets the soldier's craft and automatically moves the equipment (if enabled).\n\tvoid setCraftAndMoveEquipment(Craft* craft, Base* base, bool isNewBattle, bool resetCustomDeployment = false);\n\t/// Gets the soldier's craft string.\n\tstd::string getCraftString(Language *lang, const BaseSumDailyRecovery& recovery) const;\n\t/// Gets a string version of the soldier's rank.\n\tstd::string getRankString() const;\n\t/// Gets a sprite version of the soldier's rank. Used for BASEBITS.PCK.\n\tint getRankSprite() const;\n\t/// Gets a sprite version of the soldier's rank. Used for SMOKE.PCK.\n\tint getRankSpriteBattlescape() const;\n\t/// Gets a sprite version of the soldier's rank. Used for TinyRanks.\n\tint getRankSpriteTiny() const;\n\t/// Gets the soldier's rank.\n\tSoldierRank getRank() const;\n\t/// Increase the soldier's military rank.\n\tvoid promoteRank();\n\t/// Promotes/demotes a soldier to a specific rank.\n\tvoid setRank(const SoldierRank newRank);\n\t/// Gets the soldier's missions.\n\tint getMissions() const;\n\t/// Gets the soldier's kills.\n\tint getKills() const;\n\t/// Gets the soldier's stuns.\n\tint getStuns() const;\n\t/// Gets the soldier's gender.\n\tSoldierGender getGender() const;\n\t/// Sets the soldier's gender.\n\tvoid setGender(SoldierGender gender);\n\t/// Gets the soldier's look.\n\tSoldierLook getLook() const;\n\t/// Sets the soldier's look.\n\tvoid setLook(SoldierLook look);\n\t/// Gets the soldier's look sub type.\n\tint getLookVariant() const;\n\t/// Sets the soldier's look sub type.\n\tvoid setLookVariant(int lookVariant);\n\t/// Gets soldier rules.\n\tconst RuleSoldier *getRules() const;\n\t/// Gets the soldier's unique ID.\n\tint getId() const;\n\t/// Add a mission to the counter.\n\tvoid addMissionCount();\n\t/// Add a kill to the counter.\n\tvoid addKillCount(int count);\n\t/// Add a stun to the counter.\n\tvoid addStunCount(int count);\n\t/// Get pointer to initial stats.\n\tconst UnitStats* getInitStats() const;\n\t/// Get pointer to current stats.\n\tUnitStats *getCurrentStatsEditable();\n\tconst UnitStats* getCurrentStats() const;\n\t/// Set initial and current stats.\n\tvoid setBothStats(UnitStats *stats);\n\t/// Get whether the unit was recently promoted.\n\tbool isPromoted();\n\t/// Gets the soldier armor.\n\tArmor *getArmor() const;\n\t/// Sets the soldier armor.\n\tvoid setArmor(Armor *armor, bool resetCustomDeployment = false);\n\t/// Gets the armor layers (sprite names).\n\tconst std::vector<std::string>& getArmorLayers(Armor *customArmor = nullptr) const;\n\t/// Gets the soldier's original armor (before replacement).\n\tArmor *getReplacedArmor() const;\n\t/// Backs up the soldier's original armor (before replacement).\n\tvoid setReplacedArmor(Armor *armor);\n\t/// Gets the soldier's original armor (before transformation).\n\tArmor *getTransformedArmor() const;\n\t/// Backs up the soldier's original armor (before transformation).\n\tvoid setTransformedArmor(Armor *armor);\n\n\n\t/// Is the soldier wounded or not?.\n\tbool isWounded() const;\n\t/// Is the soldier wounded or not?.\n\tbool hasFullHealth() const;\n\t/// Is the soldier capable of defending a base?.\n\tbool canDefendBase() const;\n\n\t/// Gets the amount of missing mana.\n\tint getManaMissing() const;\n\t/// Sets the amount of missing mana.\n\tvoid setManaMissing(int manaMissing);\n\t/// Gets the soldier's mana recovery time.\n\tint getManaRecovery(int manaRecoveryPerDay) const;\n\n\t/// Gets the amount of missing health.\n\tint getHealthMissing() const;\n\t/// Sets the amount of missing health.\n\tvoid setHealthMissing(int healthMissing);\n\t/// Gets the soldier's health recovery time.\n\tint getHealthRecovery(int healthRecoveryPerDay) const;\n\n\t/// Gets the soldier's wound recovery time.\n\tint getWoundRecoveryInt() const;\n\t/// Sets the soldier's wound recovery time.\n\tvoid setWoundRecovery(int recovery);\n\t/// Gets ther soldier's wound recovery.\n\tint getWoundRecovery(float absBonus, float relBonus) const;\n\n\t/// Heals wound recoveries.\n\tvoid healWound(float absBonus, float relBonus);\n\t/// Replenishes mana.\n\tvoid replenishMana(int manaRecoveryPerDay);\n\t/// Replenishes health.\n\tvoid replenishHealth(int healthRecoveryPerDay);\n\n\t/// Daily stat replenish and healing of the soldier based on the facilities available in the base.\n\tvoid replenishStats(const BaseSumDailyRecovery& recovery);\n\t/// Gets number of days until the soldier is ready for action again.\n\tint getNeededRecoveryTime(const BaseSumDailyRecovery& recovery) const;\n\n\n\t/// Gets the soldier's equipment-layout.\n\tstd::vector<EquipmentLayoutItem*> *getEquipmentLayout();\n\tstd::vector<EquipmentLayoutItem*> *getPersonalEquipmentLayout() { return &_personalEquipmentLayout; }\n\t/// Gets the soldier's personal equipment armor.\n\tconst Armor* getPersonalEquipmentArmor() const { return _personalEquipmentArmor; }\n\t/// Sets the soldier's personal equipment armor.\n\tvoid setPersonalEquipmentArmor(const Armor* armor) { _personalEquipmentArmor = armor; }\n\n\t/// Trains a soldier's psychic stats\n\tvoid trainPsi();\n\t/// Trains a soldier's psionic abilities (anytimePsiTraining option).\n\tvoid trainPsi1Day();\n\t/// Is the soldier already fully psi-trained?\n\tbool isFullyPsiTrained();\n\t/// Returns whether the unit is in psi training or not\n\tbool isInPsiTraining() const;\n\t/// set the psi training status\n\tvoid setPsiTraining(bool psi);\n\t/// returns this soldier's psionic skill improvement score for this month.\n\tint getImprovement() const;\n\t/// returns this soldier's psionic strength improvement score for this month.\n\tint getPsiStrImprovement() const;\n\t/// Gets the soldier death info.\n\tSoldierDeath *getDeath() const;\n\t/// Kills the soldier.\n\tvoid die(SoldierDeath *death);\n\t/// Clears the equipment layout.\n\tvoid clearEquipmentLayout();\n\t/// Gets the soldier's diary.\n\tSoldierDiary *getDiary();\n\tconst SoldierDiary* getDiary() const;\n\t/// Resets the soldier's diary.\n\tvoid resetDiary();\n\t/// Calculate statString.\n\tvoid calcStatString(const std::vector<StatString *> &statStrings, bool psiStrengthEval);\n\t/// Trains a soldier's physical stats\n\tvoid trainPhys(int customTrainingFactor);\n\t/// Is the soldier already fully trained?\n\tbool isFullyTrained() const;\n\t/// Returns whether the unit is in training or not\n\tbool isInTraining() const;\n\t/// set the training status\n\tvoid setTraining(bool training);\n\t/// Should the soldier return to martial training automatically when fully healed?\n\tbool getReturnToTrainingWhenHealed() const;\n\t/// Sets whether the soldier should return to martial training automatically when fully healed.\n\tvoid setReturnToTrainingWhenHealed(bool returnToTrainingWhenHealed);\n\t/// Sets whether the soldier's body was recovered from a battle\n\tvoid setCorpseRecovered(bool corpseRecovered);\n\t/// Gets the previous transformations performed on this soldier\n\tstd::map<std::string, int> &getPreviousTransformations();\n\t/// Returns whether the unit is eligible for a certain transformation\n\tbool isEligibleForTransformation(const RuleSoldierTransformation *transformationRule) const;\n\t/// Performs a transformation on this soldier\n\tvoid transform(const Mod *mod, RuleSoldierTransformation *transformationRule, Soldier *sourceSoldier, Base *base);\n\t/// Calculates how this project changes the soldier's stats\n\tUnitStats calculateStatChanges(const Mod *mod, RuleSoldierTransformation *transformationRule, Soldier *sourceSoldier, int mode, const RuleSoldier *sourceSoldierType);\n\t/// Checks whether the soldier has a given bonus. Disclaimer: DOES NOT REFRESH THE BONUS CACHE!\n\tbool hasBonus(const RuleSoldierBonus* bonus) const;\n\t/// Gets all the soldier bonuses\n\tconst std::vector<const RuleSoldierBonus*> *getBonuses(const Mod *mod);\n\t/// Get pointer to current stats with soldier bonuses, but without armor bonuses.\n\tconst UnitStats *getStatsWithSoldierBonusesOnly() const;\n\t/// Get pointer to current stats with armor and soldier bonuses.\n\tconst UnitStats *getStatsWithAllBonuses() const;\n\t/// Pre-calculates soldier stats with various bonuses.\n\tbool prepareStatsWithBonuses(const Mod *mod);\n\t/// Gets a pointer to the daily dogfight experience cache.\n\tUnitStats* getDailyDogfightExperienceCache();\n\t/// Resets the daily dogfight experience cache.\n\tvoid resetDailyDogfightExperienceCache();\n\t/// Check if the soldier has all the required soldier bonuses for the given soldier skill.\n\tbool hasAllRequiredBonusesForSkill(const RuleSkill* skillRules);\n\t/// Check if the soldier has all the required stats and soldier bonuses for piloting the (current or new) craft.\n\tbool hasAllPilotingRequirements(const Craft* newCraft = nullptr) const;\n\nprivate:\n\tstd::string generateCallsign(const std::vector<SoldierNamePool*> &names);\n\t/// Automatically move equipment between the craft and the base when assigning/deassigning/reassigning soldiers.\n\tvoid autoMoveEquipment(Craft* craft, Base* base, int toBase);\n\n};\n\n}\n"
  },
  {
    "path": "src/Savegame/SoldierAvatar.cpp",
    "content": "#include \"SoldierAvatar.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes a new empty soldier avatar.\n */\nSoldierAvatar::SoldierAvatar() : _gender(GENDER_MALE), _look(LOOK_BLONDE), _lookVariant(0)\n{\n}\n\n/**\n * Initializes a new soldier avatar.\n * @param avatarName ID of the avatar (for translation).\n * @param gender Soldier's gender.\n * @param look Soldier's look.\n * @param lookVariant Soldier's look variant.\n */\nSoldierAvatar::SoldierAvatar(const std::string &avatarName, SoldierGender gender, SoldierLook look, int lookVariant)\n\t: _avatarName(avatarName), _gender(gender), _look(look), _lookVariant(lookVariant)\n{\n}\n\n/**\n *\n */\nSoldierAvatar::~SoldierAvatar()\n{\n}\n\n/**\n * Returns the avatar's name.\n * @return Code for translation\n */\nstd::string SoldierAvatar::getAvatarName() const\n{\n\treturn _avatarName;\n}\n\n/**\n * Returns the avatar's first component (gender).\n * @return Gender\n */\nSoldierGender SoldierAvatar::getGender() const\n{\n\treturn _gender;\n}\n\n/**\n * Returns the avatar's second component (look).\n * @return Look\n */\nSoldierLook SoldierAvatar::getLook() const\n{\n\treturn _look;\n}\n\n/**\n * Returns the avatar's third component (lookVariant).\n * @return Look variant\n */\nint SoldierAvatar::getLookVariant() const\n{\n\treturn _lookVariant;\n}\n\n}\n"
  },
  {
    "path": "src/Savegame/SoldierAvatar.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2015 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Soldier.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Represents a soldier's avatar/paperdoll.\n * Avatar is a combination of soldier's gender, look and look variant\n */\nclass SoldierAvatar\n{\nprivate:\n\tstd::string _avatarName;\n\tSoldierGender _gender;\n\tSoldierLook _look;\n\tint _lookVariant;\npublic:\n\t/// Creates a new empty avatar.\n\tSoldierAvatar();\n\t/// Creates a new avatar.\n\tSoldierAvatar(const std::string &avatarName, SoldierGender gender, SoldierLook look, int lookVariant);\n\t/// Cleans up the avatar.\n\t~SoldierAvatar();\n\t/// returns avatar name\n\tstd::string getAvatarName() const;\n\t/// returns gender\n\tSoldierGender getGender() const;\n\t/// returns look\n\tSoldierLook getLook() const;\n\t/// returns look variant\n\tint getLookVariant() const;\n};\n\n}\n"
  },
  {
    "path": "src/Savegame/SoldierDeath.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"SoldierDeath.h\"\n#include \"BattleUnitStatistics.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes a death event.\n */\nSoldierDeath::SoldierDeath(GameTime time, BattleUnitKills *cause) : _time(time), _cause(cause)\n{\n}\n\n/**\n * Cleans up a death event.\n */\nSoldierDeath::~SoldierDeath()\n{\n\tdelete _cause;\n}\n\n/**\n * Loads the death from a YAML file.\n * @param node YAML node.\n */\nvoid SoldierDeath::load(const YAML::YamlNodeReader& reader)\n{\n\t_time.load(reader[\"time\"]);\n\tif (const auto& kill = reader[\"cause\"])\n\t\t_cause = new BattleUnitKills(kill);\n}\n\n/**\n * Saves the death to a YAML file.\n * @returns YAML node.\n */\nvoid SoldierDeath::save(YAML::YamlNodeWriter writer) const\n{\n\twriter.setAsMap();\n\t_time.save(writer[\"time\"]);\n\tif (_cause)\n\t\t_cause->save(writer[\"cause\"]);\n}\n\n/**\n * Returns the time of death of this soldier.\n * @return Pointer to the time.\n */\nconst GameTime *SoldierDeath::getTime() const\n{\n\treturn &_time;\n}\n\n/**\n* Returns the time of death of this soldier.\n* @return Pointer to the time.\n*/\nconst BattleUnitKills *SoldierDeath::getCause() const\n{\n\treturn _cause;\n}\n\n}\n"
  },
  {
    "path": "src/Savegame/SoldierDeath.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/Yaml.h\"\n#include \"GameTime.h\"\n\nnamespace OpenXcom\n{\n\nstruct BattleUnitKills;\n\n/**\n * Stores info about a soldier's death.\n */\nclass SoldierDeath\n{\nprivate:\n\tGameTime _time;\n\tBattleUnitKills *_cause;\npublic:\n\tSoldierDeath() : _time(0, 0, 0, 0, 0, 0, 0), _cause(0) {}\n\t/// Creates a death.\n\tSoldierDeath(GameTime time, BattleUnitKills *cause);\n\t/// Cleans up the death.\n\t~SoldierDeath();\n\t/// Loads the death from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader);\n\t/// Saves the death to YAML.\n\tvoid save(YAML::YamlNodeWriter writer) const;\n\t/// Gets the death time.\n\tconst GameTime *getTime() const;\n\t/// Gets the death cause.\n\tconst BattleUnitKills *getCause() const;\n};\n\n}\n"
  },
  {
    "path": "src/Savegame/SoldierDiary.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"SoldierDiary.h\"\n#include <algorithm>\n#include \"../Mod/RuleCommendations.h\"\n#include \"../Mod/Mod.h\"\n#include \"BattleUnitStatistics.h\"\n#include \"MissionStatistics.h\"\n#include <algorithm>\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes a new blank diary.\n */\nSoldierDiary::SoldierDiary() : _daysWoundedTotal(0), _totalShotByFriendlyCounter(0), _totalShotFriendlyCounter(0), _loneSurvivorTotal(0),\n\t_monthsService(0), _unconciousTotal(0),\t_shotAtCounterTotal(0), _hitCounterTotal(0), _ironManTotal(0), _longDistanceHitCounterTotal(0),\n\t_lowAccuracyHitCounterTotal(0), _shotsFiredCounterTotal(0), _shotsLandedCounterTotal(0), _shotAtCounter10in1Mission(0), _hitCounter5in1Mission(0),\n\t_timesWoundedTotal(0), _KIA(0), _allAliensKilledTotal(0), _allAliensStunnedTotal(0),\n\t_ufosShotDownTotal(0), _ufosDamageTotal(0), _woundsHealedTotal(0), _allUFOs(0), _allMissionTypes(0),\n\t_statGainTotal(0), _revivedUnitTotal(0), _wholeMedikitTotal(0), _braveryGainTotal(0), _bestOfRank(0),\n\t_MIA(0), _martyrKillsTotal(0), _postMortemKills(0), _slaveKillsTotal(0), _bestSoldier(false),\n\t_revivedSoldierTotal(0), _revivedHostileTotal(0), _revivedNeutralTotal(0), _globeTrotter(false)\n{\n}\n\n/**\n *\n */\nSoldierDiary::~SoldierDiary()\n{\n\tfor (auto* comm : _commendations)\n\t{\n\t\tdelete comm;\n\t}\n\tfor (auto* buk : _killList)\n\t{\n\t\tdelete buk;\n\t}\n}\n\n/**\n * Loads the diary from a YAML file.\n * @param node YAML node.\n */\nvoid SoldierDiary::load(const YAML::YamlNodeReader& node, const Mod *mod)\n{\n\tconst auto& reader = node.useIndex();\n\tfor (const auto& commendation : reader[\"commendations\"].children())\n\t{\n\t\tSoldierCommendations* sc = new SoldierCommendations(commendation, mod);\n\t\tif (sc->getRule())\n\t\t{\n\t\t\t_commendations.push_back(sc);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// obsolete commendation, ignore it... otherwise it would cause a crash later\n\t\t\tdelete sc;\n\t\t}\n\t}\n\tfor (const auto& battleUnitKillReader : reader[\"killList\"].children())\n\t\t_killList.push_back(new BattleUnitKills(battleUnitKillReader));\n\treader.tryRead(\"missionIdList\", _missionIdList);\n\treader.tryRead(\"daysWoundedTotal\", _daysWoundedTotal);\n\treader.tryRead(\"totalShotByFriendlyCounter\", _totalShotByFriendlyCounter);\n\treader.tryRead(\"totalShotFriendlyCounter\", _totalShotFriendlyCounter);\n\treader.tryRead(\"loneSurvivorTotal\", _loneSurvivorTotal);\n\treader.tryRead(\"monthsService\", _monthsService);\n\treader.tryRead(\"unconciousTotal\", _unconciousTotal);\n\treader.tryRead(\"shotAtCounterTotal\", _shotAtCounterTotal);\n\treader.tryRead(\"hitCounterTotal\", _hitCounterTotal);\n\treader.tryRead(\"ironManTotal\", _ironManTotal);\n\treader.tryRead(\"longDistanceHitCounterTotal\", _longDistanceHitCounterTotal);\n\treader.tryRead(\"lowAccuracyHitCounterTotal\", _lowAccuracyHitCounterTotal);\n\treader.tryRead(\"shotsFiredCounterTotal\", _shotsFiredCounterTotal);\n\treader.tryRead(\"shotsLandedCounterTotal\", _shotsLandedCounterTotal);\n\treader.tryRead(\"shotAtCounter10in1Mission\", _shotAtCounter10in1Mission);\n\treader.tryRead(\"hitCounter5in1Mission\", _hitCounter5in1Mission);\n\treader.tryRead(\"timesWoundedTotal\", _timesWoundedTotal);\n\treader.tryRead(\"killedInAction\", _KIA);\n\treader.tryRead(\"allAliensKilledTotal\", _allAliensKilledTotal);\n\treader.tryRead(\"allAliensStunnedTotal\", _allAliensStunnedTotal);\n\treader.tryRead(\"ufosShotDownTotal\", _ufosShotDownTotal);\n\treader.tryRead(\"ufosDamageTotal\", _ufosDamageTotal);\n\treader.tryRead(\"woundsHealedTotal\", _woundsHealedTotal);\n\treader.tryRead(\"allUFOs\", _allUFOs);\n\treader.tryRead(\"allMissionTypes\", _allMissionTypes);\n\treader.tryRead(\"statGainTotal\", _statGainTotal);\n\treader.tryRead(\"revivedUnitTotal\", _revivedUnitTotal);\n\treader.tryRead(\"revivedSoldierTotal\", _revivedSoldierTotal);\n\treader.tryRead(\"revivedHostileTotal\", _revivedHostileTotal);\n\treader.tryRead(\"revivedNeutralTotal\", _revivedNeutralTotal);\n\treader.tryRead(\"wholeMedikitTotal\", _wholeMedikitTotal);\n\treader.tryRead(\"braveryGainTotal\", _braveryGainTotal);\n\treader.tryRead(\"bestOfRank\", _bestOfRank);\n\treader.tryRead(\"missingInAction\", _MIA);\n\treader.tryRead(\"bestSoldier\", _bestSoldier);\n\treader.tryRead(\"martyrKillsTotal\", _martyrKillsTotal);\n\treader.tryRead(\"postMortemKills\", _postMortemKills);\n\treader.tryRead(\"globeTrotter\", _globeTrotter);\n\treader.tryRead(\"slaveKillsTotal\", _slaveKillsTotal);\n}\n\n/**\n * Saves the diary to a YAML file.\n * @return YAML node.\n */\nvoid SoldierDiary::save(YAML::YamlNodeWriter writer) const\n{\n\twriter.setAsMap();\n\twriter.write(\"commendations\", _commendations,\n\t\t[](YAML::YamlNodeWriter& w, SoldierCommendations* c)\n\t\t{ c->save(w.write()); });\n\twriter.write(\"killList\", _killList,\n\t\t[](YAML::YamlNodeWriter& w, BattleUnitKills* b)\n\t\t{ b->save(w.write()); });\n\tif (!_missionIdList.empty())\n\t\twriter.write(\"missionIdList\", _missionIdList).setFlowStyle();\n\tif (_daysWoundedTotal) writer.write(\"daysWoundedTotal\", _daysWoundedTotal);\n\tif (_totalShotByFriendlyCounter) writer.write(\"totalShotByFriendlyCounter\", _totalShotByFriendlyCounter);\n\tif (_totalShotFriendlyCounter) writer.write(\"totalShotFriendlyCounter\", _totalShotFriendlyCounter);\n\tif (_loneSurvivorTotal) writer.write(\"loneSurvivorTotal\", _loneSurvivorTotal);\n\tif (_monthsService) writer.write(\"monthsService\", _monthsService);\n\tif (_unconciousTotal) writer.write(\"unconciousTotal\", _unconciousTotal);\n\tif (_shotAtCounterTotal) writer.write(\"shotAtCounterTotal\", _shotAtCounterTotal);\n\tif (_hitCounterTotal) writer.write(\"hitCounterTotal\", _hitCounterTotal);\n\tif (_ironManTotal) writer.write(\"ironManTotal\", _ironManTotal);\n\tif (_longDistanceHitCounterTotal) writer.write(\"longDistanceHitCounterTotal\", _longDistanceHitCounterTotal);\n\tif (_lowAccuracyHitCounterTotal) writer.write(\"lowAccuracyHitCounterTotal\", _lowAccuracyHitCounterTotal);\n\tif (_shotsFiredCounterTotal) writer.write(\"shotsFiredCounterTotal\", _shotsFiredCounterTotal);\n\tif (_shotsLandedCounterTotal) writer.write(\"shotsLandedCounterTotal\", _shotsLandedCounterTotal);\n\tif (_shotAtCounter10in1Mission) writer.write(\"shotAtCounter10in1Mission\", _shotAtCounter10in1Mission);\n\tif (_hitCounter5in1Mission) writer.write(\"hitCounter5in1Mission\", _hitCounter5in1Mission);\n\tif (_timesWoundedTotal) writer.write(\"timesWoundedTotal\", _timesWoundedTotal);\n\tif (_KIA) writer.write(\"killedInAction\", _KIA);\n\tif (_allAliensKilledTotal) writer.write(\"allAliensKilledTotal\", _allAliensKilledTotal);\n\tif (_allAliensStunnedTotal) writer.write(\"allAliensStunnedTotal\", _allAliensStunnedTotal);\n\tif (_ufosShotDownTotal) writer.write(\"ufosShotDownTotal\", _ufosShotDownTotal);\n\tif (_ufosDamageTotal) writer.write(\"ufosDamageTotal\", _ufosDamageTotal);\n\tif (_woundsHealedTotal) writer.write(\"woundsHealedTotal\", _woundsHealedTotal);\n\tif (_allUFOs) writer.write(\"allUFOs\", _allUFOs);\n\tif (_allMissionTypes) writer.write(\"allMissionTypes\", _allMissionTypes);\n\tif (_statGainTotal) writer.write(\"statGainTotal\", _statGainTotal);\n\tif (_revivedUnitTotal) writer.write(\"revivedUnitTotal\", _revivedUnitTotal);\n\tif (_revivedSoldierTotal) writer.write(\"revivedSoldierTotal\", _revivedSoldierTotal);\n\tif (_revivedHostileTotal) writer.write(\"revivedHostileTotal\", _revivedHostileTotal);\n\tif (_revivedNeutralTotal) writer.write(\"revivedNeutralTotal\", _revivedNeutralTotal);\n\tif (_wholeMedikitTotal) writer.write(\"wholeMedikitTotal\", _wholeMedikitTotal);\n\tif (_braveryGainTotal) writer.write(\"braveryGainTotal\", _braveryGainTotal);\n\tif (_bestOfRank) writer.write(\"bestOfRank\", _bestOfRank);\n\tif (_MIA) writer.write(\"missingInAction\", _MIA);\n\tif (_bestSoldier) writer.write(\"bestSoldier\", _bestSoldier);\n\tif (_martyrKillsTotal) writer.write(\"martyrKillsTotal\", _martyrKillsTotal);\n\tif (_postMortemKills) writer.write(\"postMortemKills\", _postMortemKills);\n\tif (_globeTrotter) writer.write(\"globeTrotter\", _globeTrotter);\n\tif (_slaveKillsTotal) writer.write(\"slaveKillsTotal\", _slaveKillsTotal);\n}\n\n/**\n * Update soldier diary statistics.\n * @param unitStatistics BattleUnitStatistics to get stats from.\n * @param missionStatistics MissionStatistics to get stats from.\n */\nvoid SoldierDiary::updateDiary(BattleUnitStatistics *unitStatistics, std::vector<MissionStatistics*> *allMissionStatistics, Mod *rules)\n{\n\tif (allMissionStatistics->empty()) return;\n\tauto* missionStatistics = allMissionStatistics->back();\n\t_missionIdList.push_back(missionStatistics->id);\n\tauto& unitKills = unitStatistics->kills;\n\tfor (auto* buk : unitKills)\n\t{\n\t\tbuk->makeTurnUnique();\n\t\t_killList.push_back(buk);\n\t}\n\tunitKills.clear();\n\tif (missionStatistics->success)\n\t{\n\t\tif (unitStatistics->loneSurvivor)\n\t\t\t_loneSurvivorTotal++;\n\t\tif (unitStatistics->ironMan)\n\t\t\t_ironManTotal++;\n\t\tif (unitStatistics->nikeCross)\n\t\t\t_allAliensKilledTotal++;\n\t\tif (unitStatistics->mercyCross)\n\t\t\t_allAliensStunnedTotal++;\n\t}\n\t_daysWoundedTotal += unitStatistics->daysWounded;\n\tif (unitStatistics->daysWounded)\n\t\t_timesWoundedTotal++;\n\n\tif (unitStatistics->wasUnconcious)\n\t\t_unconciousTotal++;\n\t_shotAtCounterTotal += unitStatistics->shotAtCounter;\n\t_shotAtCounter10in1Mission += (unitStatistics->shotAtCounter)/10;\n\t_hitCounterTotal += unitStatistics->hitCounter;\n\t_hitCounter5in1Mission += (unitStatistics->hitCounter)/5;\n\t_totalShotByFriendlyCounter += unitStatistics->shotByFriendlyCounter;\n\t_totalShotFriendlyCounter += unitStatistics->shotFriendlyCounter;\n\t_longDistanceHitCounterTotal += unitStatistics->longDistanceHitCounter;\n\t_lowAccuracyHitCounterTotal += unitStatistics->lowAccuracyHitCounter;\n\t_shotsFiredCounterTotal += unitStatistics->shotsFiredCounter;\n\t_shotsLandedCounterTotal += unitStatistics->shotsLandedCounter;\n\tif (unitStatistics->KIA)\n\t\t_KIA++;\n\tif (unitStatistics->MIA)\n\t\t_MIA++;\n\t_woundsHealedTotal += unitStatistics->woundsHealed;\n\tif (getUFOTotal(allMissionStatistics).size() >= rules->getUfosList().size())\n\t\t_allUFOs = 1;\n\tif ((getUFOTotal(allMissionStatistics).size() + getTypeTotal(allMissionStatistics).size()) == (rules->getUfosList().size() + rules->getDeploymentsList().size() - 2))\n\t\t_allMissionTypes = 1;\n\tif (getCountryTotal(allMissionStatistics).size() == 1 + rules->getCountriesList().size())\n\t\t_globeTrotter = true;\n\t_martyrKillsTotal += unitStatistics->martyr;\n\t_slaveKillsTotal += unitStatistics->slaveKills;\n\n\t// Stat change long hand calculation\n\t_statGainTotal = 0; // Reset.\n\t_statGainTotal += unitStatistics->delta.tu;\n\t_statGainTotal += unitStatistics->delta.stamina;\n\t_statGainTotal += unitStatistics->delta.health;\n\t_statGainTotal += unitStatistics->delta.bravery / 10; // Normalize\n\t_statGainTotal += unitStatistics->delta.reactions;\n\t_statGainTotal += unitStatistics->delta.firing;\n\t_statGainTotal += unitStatistics->delta.throwing;\n\t_statGainTotal += unitStatistics->delta.strength;\n\t_statGainTotal += unitStatistics->delta.mana;\n\t_statGainTotal += unitStatistics->delta.psiStrength;\n\t_statGainTotal += unitStatistics->delta.melee;\n\t_statGainTotal += unitStatistics->delta.psiSkill;\n\n\t_braveryGainTotal = unitStatistics->delta.bravery;\n\t_revivedUnitTotal += (unitStatistics->revivedSoldier + unitStatistics->revivedHostile + unitStatistics->revivedNeutral);\n\t_revivedSoldierTotal += unitStatistics->revivedSoldier;\n\t_revivedNeutralTotal += unitStatistics->revivedNeutral;\n\t_revivedHostileTotal += unitStatistics->revivedHostile;\n\t_wholeMedikitTotal += std::min( std::min(unitStatistics->woundsHealed, unitStatistics->appliedStimulant), unitStatistics->appliedPainKill);\n}\n\n/**\n * Get soldier commendations.\n * @return SoldierCommendations list of soldier's commendations.\n */\nstd::vector<SoldierCommendations*> *SoldierDiary::getSoldierCommendations()\n{\n\treturn &_commendations;\n}\n\n/**\n * Checks whether the diary contains a given commendation.\n */\nbool SoldierDiary::containsCommendation(const RuleCommendations* rule) const\n{\n\tfor (auto* comm : _commendations)\n\t{\n\t\tif (comm->getRule() == rule)\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Manage the soldier's commendations.\n * Award new ones, if deserved.\n * @return bool Has a commendation been awarded?\n */\nbool SoldierDiary::manageCommendations(const Mod* mod, SavedGame* save, const Soldier* soldier)\n{\n\tstd::vector<MissionStatistics*>* missionStatistics = save->getMissionStatistics();\n\n\tconst int BATTLE_TYPES = 13;\n\tconst std::string battleTypeArray[BATTLE_TYPES] = { \"BT_NONE\", \"BT_FIREARM\", \"BT_AMMO\", \"BT_MELEE\", \"BT_GRENADE\",\n\t\t\"BT_PROXIMITYGRENADE\", \"BT_MEDIKIT\", \"BT_SCANNER\", \"BT_MINDPROBE\", \"BT_PSIAMP\", \"BT_FLARE\", \"BT_CORPSE\", \"BT_END\" };\n\tconst int DAMAGE_TYPES = 21;\n\tconst std::string damageTypeArray[DAMAGE_TYPES] = { \"DT_NONE\", \"DT_AP\", \"DT_IN\", \"DT_HE\", \"DT_LASER\", \"DT_PLASMA\",\n\t\t\"DT_STUN\", \"DT_MELEE\", \"DT_ACID\", \"DT_SMOKE\",\n\t\t\"DT_10\", \"DT_11\", \"DT_12\", \"DT_13\", \"DT_14\", \"DT_15\", \"DT_16\", \"DT_17\", \"DT_18\", \"DT_19\", \"DT_END\" };\n\n\tconst auto& commendationsList = mod->getCommendationsList();\n\tbool ret = false;                                   // This value is returned if at least one commendation was given.\n\tstd::map<std::string, int> nextCommendationLevel;   // Noun, threshold.\n\tstd::vector<std::string> modularCommendations;      // Noun.\n\tbool awardCommendationBool = false;                 // This value determines if a commendation will be given.\n\t// Loop over all possible commendations\n\tfor (auto iter = commendationsList.begin(); iter != commendationsList.end(); )\n\t{\n\t\tconst auto& commType = (*iter).first;\n\t\tconst RuleCommendations* commRule = (*iter).second;\n\n\t\tif (!commRule->isSupportedBy(soldier->getRules()))\n\t\t{\n\t\t\t// commendation does not apply to this soldier type\n\t\t\t++iter;\n\t\t\tcontinue;\n\t\t}\n\t\tif (!save->isResearched(commRule->getRequires(), false))\n\t\t{\n\t\t\t// commendation is not unlocked yet\n\t\t\t++iter;\n\t\t\tcontinue;\n\t\t}\n\n\t\tawardCommendationBool = true;\n\t\tnextCommendationLevel.clear();\n\t\tnextCommendationLevel[\"noNoun\"] = 0;\n\t\tmodularCommendations.clear();\n\t\t// Loop over all the soldier's commendations, see if we already have the commendation.\n\t\t// If so, get the level and noun.\n\t\tfor (const auto* sc : _commendations)\n\t\t{\n\t\t\tif (commType == sc->getType())\n\t\t\t{\n\t\t\t\tnextCommendationLevel[sc->getNoun()] = sc->getDecorationLevelInt() + 1;\n\t\t\t}\n\t\t}\n\t\t// Go through each possible criteria. Assume the medal is awarded, set to false if not.\n\t\t// As soon as we find a medal criteria that we FAIL TO achieve, then we are not awarded a medal.\n\t\tfor (const auto& critPair : *commRule->getCriteria())\n\t\t{\n\t\t\tconst auto& critName = critPair.first;\n\t\t\tconst auto& critDef = critPair.second;\n\t\t\tconst size_t nextLevel = nextCommendationLevel[\"noNoun\"];\n\t\t\tconst int nextLevelThreshold = (nextLevel >= critDef.size()) ? 0 /* just a dummy */ : critDef.at(nextLevel);\n\n\t\t\t// Skip this medal if we have reached its max award level.\n\t\t\tif (nextLevel >= critDef.size())\n\t\t\t{\n\t\t\t\tawardCommendationBool = false;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t// These criteria have no nouns, so only the nextCommendationLevel[\"noNoun\"] will ever be used.\n\t\t\telse if\n\t\t\t(\n\t\t\t\tnextCommendationLevel.count(\"noNoun\") == 1 &&\n\t\t\t\t(\n\t\t\t\t\t(critName == \"totalKills\" && getKillTotal() < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"totalMissions\" && getMissionTotalFiltered(missionStatistics, commRule) < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"totalWins\" && getWinTotal(missionStatistics) < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"totalScore\" && getScoreTotal(missionStatistics) < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"totalStuns\" && getStunTotal() < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"totalDaysWounded\" && _daysWoundedTotal < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"totalBaseDefenseMissions\" && getBaseDefenseMissionTotal(missionStatistics) < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"totalTerrorMissions\" && getTerrorMissionTotal(missionStatistics) < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"totalNightMissions\" && getNightMissionTotal(missionStatistics, mod) < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"totalNightTerrorMissions\" && getNightTerrorMissionTotal(missionStatistics, mod) < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"totalMonthlyService\" && _monthsService < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"totalFellUnconcious\" && _unconciousTotal < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"totalShotAt10Times\" && _shotAtCounter10in1Mission < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"totalHit5Times\" && _hitCounter5in1Mission < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"totalFriendlyFired\" && (_totalShotByFriendlyCounter < nextLevelThreshold || _KIA || _MIA)) ||\n\t\t\t\t\t(critName == \"total_lone_survivor\" && _loneSurvivorTotal < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"totalIronMan\" && _ironManTotal < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"totalImportantMissions\" && getImportantMissionTotal(missionStatistics) < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"totalLongDistanceHits\" && _longDistanceHitCounterTotal < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"totalLowAccuracyHits\" && _lowAccuracyHitCounterTotal < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"totalReactionFire\" && getReactionFireKillTotal(mod) < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"totalTimesWounded\" && _timesWoundedTotal < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"totalDaysWounded\" && _daysWoundedTotal < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"totalValientCrux\" && getValiantCruxTotal(missionStatistics) < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"isDead\" && _KIA < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"totalTrapKills\" && getTrapKillTotal(mod) < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"totalAlienBaseAssaults\" && getAlienBaseAssaultTotal(missionStatistics) < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"totalAllAliensKilled\" && _allAliensKilledTotal < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"totalAllAliensStunned\" && _allAliensStunnedTotal < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"totalUfosShotDown\" && _ufosShotDownTotal < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"totalUfosDamage\" && _ufosDamageTotal < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"totalWoundsHealed\" && _woundsHealedTotal < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"totalAllUFOs\" && _allUFOs < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"totalAllMissionTypes\" && _allMissionTypes < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"totalStatGain\" && _statGainTotal < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"totalRevives\" && _revivedUnitTotal < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"totalSoldierRevives\" && _revivedSoldierTotal < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"totalHostileRevives\" && _revivedHostileTotal < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"totalNeutralRevives\" && _revivedNeutralTotal < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"totalWholeMedikit\" && _wholeMedikitTotal < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"totalBraveryGain\" && _braveryGainTotal < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"bestOfRank\" && _bestOfRank < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"bestSoldier\" && _bestSoldier < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"isMIA\" && _MIA < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"totalMartyrKills\" && _martyrKillsTotal < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"totalPostMortemKills\" && _postMortemKills < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"globeTrotter\" && (int)_globeTrotter < nextLevelThreshold) ||\n\t\t\t\t\t(critName == \"totalSlaveKills\" && _slaveKillsTotal < nextLevelThreshold)\n\t\t\t\t)\n\t\t\t)\n\t\t\t{\n\t\t\t\tawardCommendationBool = false;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t// Medals with the following criteria are unique because they need a noun.\n\t\t\t// And because they loop over a map<> (this allows for maximum moddability).\n\t\t\telse if (critName == \"totalKillsWithAWeapon\" || critName == \"totalMissionsInARegion\" || critName == \"totalKillsByRace\" || critName == \"totalKillsByRank\")\n\t\t\t{\n\t\t\t\tstd::map<std::string, int> tempTotal;\n\t\t\t\tif (critName == \"totalKillsWithAWeapon\")\n\t\t\t\t\ttempTotal = getWeaponTotal();\n\t\t\t\telse if (critName == \"totalMissionsInARegion\")\n\t\t\t\t\ttempTotal = getRegionTotal(missionStatistics);\n\t\t\t\telse if (critName == \"totalKillsByRace\")\n\t\t\t\t\ttempTotal = getAlienRaceTotal();\n\t\t\t\telse if (critName == \"totalKillsByRank\")\n\t\t\t\t\ttempTotal = getAlienRankTotal();\n\t\t\t\t// Loop over the temporary map.\n\t\t\t\t// Match nouns and decoration levels.\n\t\t\t\tfor (const auto& pair : tempTotal)\n\t\t\t\t{\n\t\t\t\t\tint criteria = -1;\n\t\t\t\t\tconst auto& noun = pair.first;\n\t\t\t\t\t// If there is no matching noun, get the first award criteria.\n\t\t\t\t\tif (nextCommendationLevel.count(noun) == 0)\n\t\t\t\t\t\tcriteria = critDef.front();\n\t\t\t\t\t// Otherwise, get the criteria that reflects the soldier's commendation level.\n\t\t\t\t\telse if ((unsigned int)nextCommendationLevel[noun] != critDef.size())\n\t\t\t\t\t\tcriteria = critDef.at(nextCommendationLevel[noun]);\n\n\t\t\t\t\t// If a criteria was set AND the stat's count exceeds the criteria.\n\t\t\t\t\tif (criteria != -1 && pair.second >= criteria)\n\t\t\t\t\t{\n\t\t\t\t\t\tmodularCommendations.push_back(noun);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// If it is still empty, we did not get a commendation.\n\t\t\t\tif (modularCommendations.empty())\n\t\t\t\t{\n\t\t\t\t\tawardCommendationBool = false;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Medals that are based on _how_ a kill was achieved are found here.\n\t\t\telse if (critName == \"killsWithCriteriaCareer\" || critName == \"killsWithCriteriaMission\" || critName == \"killsWithCriteriaTurn\")\n\t\t\t{\n\t\t\t\t// Fetch the kill criteria list.\n\t\t\t\tif (!commRule->getKillCriteria())\n\t\t\t\t\tbreak;\n\t\t\t\tconst auto* _killCriteriaList = commRule->getKillCriteria();\n\n\t\t\t\tint totalKillGroups = 0; // holds the total number of kill groups which satisfy one of the OR criteria blocks\n\t\t\t\tbool enoughForNextCommendation = false;\n\n\t\t\t\t// Loop over the OR vectors.\n\t\t\t\t// if OR criteria are not disjunctive (e.g. \"kill 1 enemy\" or \"kill 1 enemy\"), each one will be counted and added to totals - avoid that if you want good statistics\n\t\t\t\tfor (auto orCriteria = _killCriteriaList->begin(); orCriteria != _killCriteriaList->end(); ++orCriteria)\n\t\t\t\t{\n\t\t\t\t\t// prepare counters\n\t\t\t\t\tstd::vector<int> referenceBlockCounters;\n\t\t\t\t\treferenceBlockCounters.assign((*orCriteria).size(), 0);\n\t\t\t\t\tint referenceTotalCounters = 0;\n\t\t\t\t\tfor (auto andCriteria2 = orCriteria->begin(); andCriteria2 != orCriteria->end(); ++andCriteria2)\n\t\t\t\t\t{\n\t\t\t\t\t\tint index = andCriteria2 - orCriteria->begin();\n\t\t\t\t\t\treferenceBlockCounters[index] = (*andCriteria2).first;\n\t\t\t\t\t\treferenceTotalCounters += (*andCriteria2).first;\n\t\t\t\t\t}\n\t\t\t\t\tstd::vector<int> currentBlockCounters;\n\t\t\t\t\tif (critName == \"killsWithCriteriaCareer\") {\n\t\t\t\t\t\tcurrentBlockCounters = referenceBlockCounters;\n\t\t\t\t\t}\n\t\t\t\t\tint currentTotalCounters = referenceTotalCounters;\n\t\t\t\t\tint lastTimeSpan = -1;\n\t\t\t\t\tbool skipThisTimeSpan = false;\n\t\t\t\t\t// Loop over the KILLS, seeking to fulfill all criteria from entire AND block within the specified time span (career/mission/turn)\n\t\t\t\t\tfor (const auto* singleKill : _killList)\n\t\t\t\t\t{\n\t\t\t\t\t\tint thisTimeSpan = -1;\n\t\t\t\t\t\tif (critName == \"killsWithCriteriaMission\")\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tthisTimeSpan = singleKill->mission;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (critName == \"killsWithCriteriaTurn\")\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tthisTimeSpan = singleKill->turn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (thisTimeSpan != lastTimeSpan)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// next time span, reset counters\n\t\t\t\t\t\t\tlastTimeSpan = thisTimeSpan;\n\t\t\t\t\t\t\tskipThisTimeSpan = false;\n\t\t\t\t\t\t\tcurrentBlockCounters = referenceBlockCounters;\n\t\t\t\t\t\t\tcurrentTotalCounters = referenceTotalCounters;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// same time span, we're skipping the rest of it if we already fulfilled criteria\n\t\t\t\t\t\telse if (skipThisTimeSpan)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbool andCriteriaMet = false;\n\n\t\t\t\t\t\t// Loop over the AND vectors.\n\t\t\t\t\t\tfor (auto andCriteria = orCriteria->begin(); andCriteria != orCriteria->end(); ++andCriteria)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tbool foundMatch = true;\n\n\t\t\t\t\t\t\t// Loop over the DETAILs of one AND vector.\n\t\t\t\t\t\t\tfor (auto detailIt = andCriteria->second.begin(); detailIt != andCriteria->second.end(); ++detailIt)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tconst auto& detail = (*detailIt);\n\t\t\t\t\t\t\t\t// Look if for match for this criteria.\n\t\t\t\t\t\t\t\t// If we find a match, continue to the next criteria. (We must match all criteria in the list.)\n\t\t\t\t\t\t\t\t// If we don't find a match, set foundMatch = false; then break.\n\n\t\t\t\t\t\t\t\tif (singleKill->rank == detail ||\n\t\t\t\t\t\t\t\t\tsingleKill->race == detail ||\n\t\t\t\t\t\t\t\t\tsingleKill->weapon == detail ||\n\t\t\t\t\t\t\t\t\tsingleKill->weaponAmmo == detail ||\n\t\t\t\t\t\t\t\t\tsingleKill->getUnitStatusString() == detail ||\n\t\t\t\t\t\t\t\t\tsingleKill->getUnitFactionString() == detail ||\n\t\t\t\t\t\t\t\t\tsingleKill->getUnitSideString() == detail ||\n\t\t\t\t\t\t\t\t\tsingleKill->getUnitBodyPartString() == detail)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t// Found match\n\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// check the weapon's battle type and damage type\n\t\t\t\t\t\t\t\tRuleItem *weapon = mod->getItem(singleKill->weapon);\n\t\t\t\t\t\t\t\tif (weapon != 0)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tint battleType = weapon->getBattleType();\n\n\t\t\t\t\t\t\t\t\tif (battleType >=0 && battleType < BATTLE_TYPES && battleTypeArray[battleType] == detail)\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t// the detail matched the weapon's battle type\n\t\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t\t\t}\n\n\n\t\t\t\t\t\t\t\t\tRuleItem *weaponAmmo = mod->getItem(singleKill->weaponAmmo);\n\t\t\t\t\t\t\t\t\tint damageType = -1;\n\n\t\t\t\t\t\t\t\t\tif (weaponAmmo != 0)\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tdamageType = weaponAmmo->getDamageType()->ResistType;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse if (singleKill->weaponAmmo == \"__GUNBUTT\")\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t// If weaponAmmo == \"__GUNBUTT\", that means the gun's secondary melee attack was used.\n\t\t\t\t\t\t\t\t\t\tdamageType = weapon->getMeleeType()->ResistType;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t// If we were unable to determine the damage type, leave it as -1.\n\n\t\t\t\t\t\t\t\t\tif (damageType >= 0 && damageType < DAMAGE_TYPES && damageTypeArray[damageType] == detail)\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t// the detail matched the damage type\n\t\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// That's all we can check. We didn't find a match\n\t\t\t\t\t\t\t\tfoundMatch = false;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t} /// End of DETAIL loop.\n\n\t\t\t\t\t\t\tif (foundMatch)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tint index = andCriteria - orCriteria->begin();\n\t\t\t\t\t\t\t\t// some current block counters might go into negatives, this is used to tally career kills correctly\n\t\t\t\t\t\t\t\t// currentTotalCounters will always ensure we're counting in proper batches\n\t\t\t\t\t\t\t\tif (currentBlockCounters[index]-- > 0 && --currentTotalCounters <= 0)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t// we just counted all counters in a block to zero, this certainly means that the entire block criteria is fulfilled\n\t\t\t\t\t\t\t\t\tandCriteriaMet = true;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} /// End of AND loop.\n\n\t\t\t\t\t\tif (andCriteriaMet)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// early exit if we got enough, no reason to continue iterations\n\t\t\t\t\t\t\tif (++totalKillGroups >= critDef.at(nextCommendationLevel[\"noNoun\"]))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tenoughForNextCommendation = true;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// \"killsWithCriteriaTurn\" and \"killsWithCriteriaMission\" are \"peak achivements\", they are counted once per their respective time span if criteria are fulfilled\n\t\t\t\t\t\t\t// so if we got them, we're skipping the rest of this time span to avoid counting more than once\n\t\t\t\t\t\t\t// e.g. 20 kills in a mission will not be counted as \"10 kills in a mission\" criteria twice\n\t\t\t\t\t\t\t// \"killsWithCriteriaCareer\" are totals, so they are never skipped this way\n\t\t\t\t\t\t\tif (critName == \"killsWithCriteriaTurn\" || critName == \"killsWithCriteriaMission\")\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tskipThisTimeSpan = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// for career kills we'll ADD reference counters to the current values and recalculate current total\n\t\t\t\t\t\t\t// this is used to count instances of full criteria blocks, e.g. if rules state that a career commendation must be awarded for 2 kills of alien leaders\n\t\t\t\t\t\t\t// and 1 kill of  alien commander, then we must ensure there's 2 leader kills + 1 commander kill for each instance of criteria fulfilled\n\t\t\t\t\t\t\telse if (critName == \"killsWithCriteriaCareer\")\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcurrentTotalCounters = 0;\n\t\t\t\t\t\t\t\tfor (std::size_t i2 = 0; i2 < currentBlockCounters.size(); i2++)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tcurrentBlockCounters[i2] += referenceBlockCounters[i2];\n\t\t\t\t\t\t\t\t\tcurrentTotalCounters += std::max(currentBlockCounters[i2], 0);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} /// End of KILLs loop.\n\n\t\t\t\t\tif (enoughForNextCommendation)\n\t\t\t\t\t\tbreak; // stop iterating here too, we've got enough\n\n\t\t\t\t} /// End of OR loop.\n\n\t\t\t\tif (!enoughForNextCommendation)\n\t\t\t\t\tawardCommendationBool = false;\n\n\t\t\t}\n\t\t}\n\t\tif (awardCommendationBool)\n\t\t{\n\t\t\t// If we do not have modular medals, but are awarded a different medal,\n\t\t\t// its noun will be \"noNoun\".\n\t\t\tif (modularCommendations.empty())\n\t\t\t{\n\t\t\t\tmodularCommendations.push_back(\"noNoun\");\n\t\t\t}\n\t\t\tfor (const auto& noun : modularCommendations)\n\t\t\t{\n\t\t\t\tbool newCommendation = true;\n\t\t\t\tfor (auto* soldierComm : _commendations)\n\t\t\t\t{\n\t\t\t\t\tif (soldierComm->getType() == commType && soldierComm->getNoun() == noun)\n\t\t\t\t\t{\n\t\t\t\t\t\tsoldierComm->addDecoration();\n\t\t\t\t\t\tnewCommendation = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (newCommendation)\n\t\t\t\t{\n\t\t\t\t\t_commendations.push_back(new SoldierCommendations(commType, noun, mod));\n\t\t\t\t}\n\t\t\t}\n\t\t\tret = true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t++iter;\n\t\t}\n\t}\n\treturn ret;\n}\n\n/**\n * Get vector of mission ids.\n * @return Vector of mission ids.\n */\nstd::vector<int> &SoldierDiary::getMissionIdList()\n{\n\treturn _missionIdList;\n}\nconst std::vector<int>& SoldierDiary::getMissionIdList() const\n{\n\treturn _missionIdList;\n}\n\n/**\n * Get vector of kills.\n * @return vector of BattleUnitKills\n */\nstd::vector<BattleUnitKills*> &SoldierDiary::getKills()\n{\n\treturn _killList;\n}\n\n/**\n * Get list of kills sorted by rank\n * @return\n */\nstd::map<std::string, int> SoldierDiary::getAlienRankTotal() const\n{\n\tstd::map<std::string, int> list;\n\tfor (const auto* buk : _killList)\n\t{\n\t\tlist[buk->rank]++;\n\t}\n\treturn list;\n}\n\n/**\n *\n */\nstd::map<std::string, int> SoldierDiary::getAlienRaceTotal() const\n{\n\tstd::map<std::string, int> list;\n\tfor (const auto* buk : _killList)\n\t{\n\t\tlist[buk->race]++;\n\t}\n\treturn list;\n}\n\n/**\n *\n */\nstd::map<std::string, int> SoldierDiary::getWeaponTotal() const\n{\n\tstd::map<std::string, int> list;\n\tfor (const auto* buk : _killList)\n\t{\n\t\tif (buk->faction == FACTION_HOSTILE)\n\t\t\tlist[buk->weapon]++;\n\t}\n\treturn list;\n}\n\n/**\n *\n */\nstd::map<std::string, int> SoldierDiary::getWeaponAmmoTotal() const\n{\n\tstd::map<std::string, int> list;\n\tfor (const auto* buk : _killList)\n\t{\n\t\tif (buk->faction == FACTION_HOSTILE)\n\t\t\tlist[buk->weaponAmmo]++;\n\t}\n\treturn list;\n}\n\n/**\n *  Get a map of the amount of missions done in each region.\n *  @param MissionStatistics\n */\nstd::map<std::string, int> SoldierDiary::getRegionTotal(std::vector<MissionStatistics*> *missionStatistics) const\n{\n\tstd::map<std::string, int> regionTotal;\n\n\tfor (const auto* ms : *missionStatistics)\n\t{\n\t\tfor (int missionId : _missionIdList)\n\t\t{\n\t\t\tif (missionId == ms->id)\n\t\t\t{\n\t\t\t\tregionTotal[ms->region]++;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn regionTotal;\n}\n\n/**\n *  Get a map of the amount of missions done in each country.\n *  @param MissionStatistics\n */\nstd::map<std::string, int> SoldierDiary::getCountryTotal(std::vector<MissionStatistics*> *missionStatistics) const\n{\n\tstd::map<std::string, int> countryTotal;\n\n\tfor (const auto* ms : *missionStatistics)\n\t{\n\t\tfor (int missionId : _missionIdList)\n\t\t{\n\t\t\tif (missionId == ms->id)\n\t\t\t{\n\t\t\t\tcountryTotal[ms->country]++;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn countryTotal;\n}\n\n/**\n *  Get a map of the amount of missions done in each type.\n *  @param MissionStatistics\n */\nstd::map<std::string, int> SoldierDiary::getTypeTotal(std::vector<MissionStatistics*> *missionStatistics) const\n{\n\tstd::map<std::string, int> typeTotal;\n\n\tfor (const auto* ms : *missionStatistics)\n\t{\n\t\tfor (int missionId : _missionIdList)\n\t\t{\n\t\t\tif (missionId == ms->id)\n\t\t\t{\n\t\t\t\ttypeTotal[ms->type]++;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn typeTotal;\n}\n\n/**\n *  Get a map of the amount of missions done in each UFO.\n *  @param MissionStatistics\n */\nstd::map<std::string, int> SoldierDiary::getUFOTotal(std::vector<MissionStatistics*> *missionStatistics) const\n{\n\tstd::map<std::string, int> ufoTotal;\n\n\tfor (const auto* ms : *missionStatistics)\n\t{\n\t\tfor (int missionId : _missionIdList)\n\t\t{\n\t\t\tif (missionId == ms->id)\n\t\t\t{\n\t\t\t\tufoTotal[ms->ufo]++;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn ufoTotal;\n}\n\n/**\n *\n */\nint SoldierDiary::getKillTotal() const\n{\n\tint killTotal = 0;\n\n\tfor (const auto* buk : _killList)\n\t{\n\t\tif (buk->status == STATUS_DEAD && buk->faction == FACTION_HOSTILE)\n\t\t{\n\t\t\tkillTotal++;\n\t\t}\n\t}\n\n\treturn killTotal;\n}\n\n/**\n *\n */\nint SoldierDiary::getMissionTotal() const\n{\n\treturn _missionIdList.size();\n}\n\n/**\n *\n */\nint SoldierDiary::getMissionTotalFiltered(std::vector<MissionStatistics*>* missionStatistics, const RuleCommendations* rule) const\n{\n\tif (!rule->getMissionTypeNames().empty())\n\t{\n\t\tint total = 0;\n\t\tfor (const auto* ms : *missionStatistics)\n\t\t{\n\t\t\tif (ms->success)\n\t\t\t{\n\t\t\t\tif (std::find(_missionIdList.begin(), _missionIdList.end(), ms->id) != _missionIdList.end())\n\t\t\t\t{\n\t\t\t\t\tif (std::find(rule->getMissionTypeNames().begin(), rule->getMissionTypeNames().end(), ms->type) != rule->getMissionTypeNames().end())\n\t\t\t\t\t{\n\t\t\t\t\t\t++total;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn total;\n\t}\n\telse if (!rule->getMissionMarkerNames().empty())\n\t{\n\t\tint total = 0;\n\t\tfor (const auto* ms : *missionStatistics)\n\t\t{\n\t\t\tif (ms->success)\n\t\t\t{\n\t\t\t\tif (std::find(_missionIdList.begin(), _missionIdList.end(), ms->id) != _missionIdList.end())\n\t\t\t\t{\n\t\t\t\t\tif (std::find(rule->getMissionMarkerNames().begin(), rule->getMissionMarkerNames().end(), ms->markerName) != rule->getMissionMarkerNames().end())\n\t\t\t\t\t{\n\t\t\t\t\t\t++total;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn total;\n\t}\n\n\treturn (int)_missionIdList.size();\n}\n\n/**\n *  Get the total if wins.\n *  @param Mission Statistics\n */\nint SoldierDiary::getWinTotal(std::vector<MissionStatistics*> *missionStatistics) const\n{\n\tint winTotal = 0;\n\n\tfor (const auto* ms : *missionStatistics)\n\t{\n\t\tfor (int missionId : _missionIdList)\n\t\t{\n\t\t\tif (missionId == ms->id)\n\t\t\t{\n\t\t\t\tif (ms->success)\n\t\t\t\t{\n\t\t\t\t\twinTotal++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn winTotal;\n}\n\n/**\n *\n */\nint SoldierDiary::getStunTotal() const\n{\n\tint stunTotal = 0;\n\n\tfor (const auto* buk : _killList)\n\t{\n\t\tif (buk->status == STATUS_UNCONSCIOUS && buk->faction == FACTION_HOSTILE)\n\t\t{\n\t\t\tstunTotal++;\n\t\t}\n\t}\n\n\treturn stunTotal;\n}\n\n/**\n *\n */\nint SoldierDiary::getPanickTotal() const\n{\n\tint panickTotal = 0;\n\n\tfor (const auto* buk : _killList)\n\t{\n\t\tif (buk->status == STATUS_PANICKING && buk->faction == FACTION_HOSTILE)\n\t\t{\n\t\t\tpanickTotal++;\n\t\t}\n\t}\n\n\treturn panickTotal;\n}\n\n/**\n *\n */\nint SoldierDiary::getControlTotal() const\n{\n\tint controlTotal = 0;\n\n\tfor (const auto* buk : _killList)\n\t{\n\t\tif (buk->status == STATUS_TURNING && buk->faction == FACTION_HOSTILE)\n\t\t{\n\t\t\tcontrolTotal++;\n\t\t}\n\t}\n\n\treturn controlTotal;\n}\n\n/**\n *\n */\nint SoldierDiary::getDaysWoundedTotal() const\n{\n\treturn _daysWoundedTotal;\n}\n\n/**\n * Increment soldier's service time one month\n */\nvoid SoldierDiary::addMonthlyService()\n{\n\t_monthsService++;\n}\n\n/**\n * Returns the total months this soldier has been in service.\n */\nint SoldierDiary::getMonthsService() const\n{\n\treturn _monthsService;\n}\n\n/**\n * Update the pilot's UFO stats.\n */\nvoid SoldierDiary::addUfoShotDown(int damage)\n{\n\t_ufosShotDownTotal += 1;\n\t_ufosDamageTotal += damage;\n}\n\n/**\n * Award special commendation to the original 8 soldiers.\n */\nvoid SoldierDiary::awardOriginalEightCommendation(const Mod* mod)\n{\n\t// TODO: Unhardcode this\n\t_commendations.push_back(new SoldierCommendations(\"STR_MEDAL_ORIGINAL8_NAME\", \"NoNoun\", mod));\n}\n\n/**\n * Award posthumous best-of commendation.\n */\nvoid SoldierDiary::awardBestOfRank(int score)\n{\n\t_bestOfRank = score;\n}\n\n/**\n * Award posthumous best-of commendation.\n */\nvoid SoldierDiary::awardBestOverall(int score)\n{\n\t_bestSoldier = score;\n}\n\n/**\n * Award posthumous kills commendation.\n */\nvoid SoldierDiary::awardPostMortemKill(int kills)\n{\n\t_postMortemKills = kills;\n}\n\n/**\n *\n */\nint SoldierDiary::getShotsFiredTotal() const\n{\n\treturn _shotsFiredCounterTotal;\n}\n\n/**\n *\n */\nint SoldierDiary::getShotsLandedTotal() const\n{\n\treturn _shotsLandedCounterTotal;\n}\n\n/**\n *  Get the soldier's accuracy.\n */\nint SoldierDiary::getAccuracy() const\n{\n\tif (_shotsFiredCounterTotal != 0)\n\t\treturn 100 * _shotsLandedCounterTotal / _shotsFiredCounterTotal;\n\treturn 0;\n}\n\n/**\n *  Get trap kills total.\n */\nint SoldierDiary::getTrapKillTotal(const Mod* mod) const\n{\n\tint trapKillTotal = 0;\n\n\tfor (const auto* buk : _killList)\n\t{\n\t\tRuleItem *item = mod->getItem(buk->weapon);\n\t\tif (buk->hostileTurn() && (item == 0 || item->getBattleType() == BT_GRENADE || item->getBattleType() == BT_PROXIMITYGRENADE))\n\t\t{\n\t\t\ttrapKillTotal++;\n\t\t}\n\t}\n\n\treturn trapKillTotal;\n}\n\n/**\n *  Get reaction kill total.\n */\n int SoldierDiary::getReactionFireKillTotal(const Mod* mod) const\n {\n\tint reactionFireKillTotal = 0;\n\n\tfor (const auto* buk : _killList)\n\t{\n\t\tRuleItem *item = mod->getItem(buk->weapon);\n\t\tif (buk->hostileTurn() && item != 0 && item->getBattleType() != BT_GRENADE && item->getBattleType() != BT_PROXIMITYGRENADE)\n\t\t{\n\t\t\treactionFireKillTotal++;\n\t\t}\n\t}\n\n\treturn reactionFireKillTotal;\n }\n\n/**\n *  Get the total of terror missions.\n *  @param Mission Statistics\n */\nint SoldierDiary::getTerrorMissionTotal(std::vector<MissionStatistics*> *missionStatistics) const\n{\n\t/// Not a UFO, not the base, not the alien base or colony\n\tint terrorMissionTotal = 0;\n\n\tfor (const auto* ms : *missionStatistics)\n\t{\n\t\tfor (int misionId : _missionIdList)\n\t\t{\n\t\t\tif (misionId == ms->id)\n\t\t\t{\n\t\t\t\tif (ms->success && !ms->isBaseDefense() && !ms->isUfoMission() && !ms->isAlienBase())\n\t\t\t\t{\n\t\t\t\t\tterrorMissionTotal++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn terrorMissionTotal;\n}\n\n/**\n *  Get the total of night missions.\n *  @param Mission Statistics\n */\nint SoldierDiary::getNightMissionTotal(std::vector<MissionStatistics*> *missionStatistics, const Mod* mod) const\n{\n\tint nightMissionTotal = 0;\n\n\tfor (const auto* ms : *missionStatistics)\n\t{\n\t\tfor (int misionId : _missionIdList)\n\t\t{\n\t\t\tif (misionId == ms->id)\n\t\t\t{\n\t\t\t\tif (ms->success && ms->isDarkness(mod) && !ms->isBaseDefense() && !ms->isAlienBase())\n\t\t\t\t{\n\t\t\t\t\tnightMissionTotal++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nightMissionTotal;\n}\n\n/**\n *  Get the total of night terror missions.\n *  @param Mission Statistics\n */\nint SoldierDiary::getNightTerrorMissionTotal(std::vector<MissionStatistics*> *missionStatistics, const Mod* mod) const\n{\n\tint nightTerrorMissionTotal = 0;\n\n\tfor (const auto* ms : *missionStatistics)\n\t{\n\t\tfor (int misionId : _missionIdList)\n\t\t{\n\t\t\tif (misionId == ms->id)\n\t\t\t{\n\t\t\t\tif (ms->success && ms->isDarkness(mod) && !ms->isBaseDefense() && !ms->isUfoMission() && !ms->isAlienBase())\n\t\t\t\t{\n\t\t\t\t\tnightTerrorMissionTotal++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nightTerrorMissionTotal;\n}\n\n/**\n *  Get the total of base defense missions.\n *  @param Mission Statistics\n */\nint SoldierDiary::getBaseDefenseMissionTotal(std::vector<MissionStatistics*> *missionStatistics) const\n{\n\tint baseDefenseMissionTotal = 0;\n\n\tfor (const auto* ms : *missionStatistics)\n\t{\n\t\tfor (int misionId : _missionIdList)\n\t\t{\n\t\t\tif (misionId == ms->id)\n\t\t\t{\n\t\t\t\tif (ms->success && ms->isBaseDefense())\n\t\t\t\t{\n\t\t\t\t\tbaseDefenseMissionTotal++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn baseDefenseMissionTotal;\n}\n\n/**\n *  Get the total of alien base assaults.\n *  @param Mission Statistics\n */\nint SoldierDiary::getAlienBaseAssaultTotal(std::vector<MissionStatistics*> *missionStatistics) const\n{\n\tint alienBaseAssaultTotal = 0;\n\n\tfor (const auto* ms : *missionStatistics)\n\t{\n\t\tfor (int misionId : _missionIdList)\n\t\t{\n\t\t\tif (misionId == ms->id)\n\t\t\t{\n\t\t\t\tif (ms->success && ms->isAlienBase())\n\t\t\t\t{\n\t\t\t\t\talienBaseAssaultTotal++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn alienBaseAssaultTotal;\n}\n\n/**\n *  Get the total of important missions.\n *  @param Mission Statistics\n */\nint SoldierDiary::getImportantMissionTotal(std::vector<MissionStatistics*> *missionStatistics) const\n{\n\tint importantMissionTotal = 0;\n\n\tfor (const auto* ms : *missionStatistics)\n\t{\n\t\tfor (int misionId : _missionIdList)\n\t\t{\n\t\t\tif (misionId == ms->id)\n\t\t\t{\n\t\t\t\tif (ms->success && ms->type != \"STR_UFO_CRASH_RECOVERY\")\n\t\t\t\t{\n\t\t\t\t\timportantMissionTotal++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn importantMissionTotal;\n}\n\n/**\n *  Get the total score.\n *  @param Mission Statistics\n */\nint SoldierDiary::getScoreTotal(std::vector<MissionStatistics*> *missionStatistics) const\n{\n\tint scoreTotal = 0;\n\n\tfor (const auto* ms : *missionStatistics)\n\t{\n\t\tfor (int misionId : _missionIdList)\n\t\t{\n\t\t\tif (misionId == ms->id)\n\t\t\t{\n\t\t\t\tscoreTotal += ms->score;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn scoreTotal;\n}\n\n/**\n *  Get the Valiant Crux total.\n *  @param Mission Statistics\n */\nint SoldierDiary::getValiantCruxTotal(std::vector<MissionStatistics*> *missionStatistics) const\n{\n\tint valiantCruxTotal = 0;\n\n\tfor (const auto* ms : *missionStatistics)\n\t{\n\t\tfor (int misionId : _missionIdList)\n\t\t{\n\t\t\tif (misionId == ms->id && ms->valiantCrux)\n\t\t\t{\n\t\t\t\tvaliantCruxTotal++;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn valiantCruxTotal;\n}\n\n/**\n *  Get the loot value total.\n *  @param Mission Statistics\n */\nint SoldierDiary::getLootValueTotal(std::vector<MissionStatistics*> *missionStatistics) const\n{\n\tint lootValueTotal = 0;\n\n\tfor (const auto* ms : *missionStatistics)\n\t{\n\t\tfor (int misionId : _missionIdList)\n\t\t{\n\t\t\tif (misionId == ms->id)\n\t\t\t{\n\t\t\t\tlootValueTotal += ms->lootValue;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn lootValueTotal;\n}\n\n/**\n * Initializes a new commendation entry from YAML.\n * @param node YAML node.\n */\nSoldierCommendations::SoldierCommendations(const YAML::YamlNodeReader& reader, const Mod* mod)\n{\n\tload(reader);\n\t_rule = mod->getCommendation(_type, false); //TODO: during load we can load obsolete value, some else need cleanup\n}\n\n/**\n * Initializes a soldier commendation.\n */\nSoldierCommendations::SoldierCommendations(const std::string& commendationName, const std::string& noun, const Mod* mod) :\n\t_type(commendationName), _noun(noun), _decorationLevel(0), _isNew(true)\n{\n\t_rule = mod->getCommendation(_type, true); //if there is no commendation rule then someone messed up\n}\n\n/**\n *\n */\nSoldierCommendations::~SoldierCommendations()\n{\n}\n\n/**\n * Loads the commendation from a YAML file.\n * @param node YAML node.\n */\nvoid SoldierCommendations::load(const YAML::YamlNodeReader& reader)\n{\n\treader.tryRead(\"commendationName\", _type);\n\treader.readNode<std::string>(\"noun\", _noun, \"noNoun\");\n\treader.tryRead(\"decorationLevel\", _decorationLevel);\n\treader.readNode(\"isNew\", _isNew, false);\n}\n\n/**\n * Saves the commendation to a YAML file.\n * @return YAML node.\n */\nvoid SoldierCommendations::save(YAML::YamlNodeWriter writer) const\n{\n\twriter.setAsMap();\n\twriter.setFlowStyle();\n\twriter.write(\"commendationName\", _type);\n\tif (_noun != \"noNoun\")\n\t\twriter.write(\"noun\", _noun);\n\twriter.write(\"decorationLevel\", _decorationLevel);\n}\n\n/**\n * Get the soldier's commendation's name.\n * @return string Commendation name.\n */\nconst std::string& SoldierCommendations::getType() const\n{\n\treturn _type;\n}\n\n/**\n * Get the soldier's commendation's noun.\n * @return string Commendation noun\n */\nconst std::string& SoldierCommendations::getNoun() const\n{\n\treturn _noun;\n}\n\n/**\n * Get the soldier commendation level's name.\n * @return string Commendation level.\n */\nstd::string SoldierCommendations::getDecorationLevelName(int skipCounter) const\n{\n\tstd::ostringstream ss;\n\tss << \"STR_AWARD_\" << _decorationLevel - skipCounter;\n\treturn ss.str();\n}\n\n/**\n * Get the soldier commendation level's description.\n * @return string Commendation level description.\n */\nstd::string SoldierCommendations::getDecorationDescription() const\n{\n\tstd::ostringstream ss;\n\tss << \"STR_AWARD_DECOR_\" << _decorationLevel;\n\treturn ss.str();\n}\n\n/**\n * Get the soldier commendation level's int.\n * @return int Commendation level.\n */\nint SoldierCommendations::getDecorationLevelInt() const\n{\n\treturn _decorationLevel;\n}\n\n/**\n * Get newness of commendation.\n * @return bool Is the commendation new?\n */\nbool SoldierCommendations::isNew() const\n{\n\treturn _isNew;\n}\n\n/**\n * Set the newness of the commendation to old.\n */\nvoid SoldierCommendations::makeOld()\n{\n\t_isNew = false;\n}\n\n/**\n * Add a level of decoration to the commendation.\n * Sets isNew to true.\n */\nvoid SoldierCommendations::addDecoration()\n{\n\t_decorationLevel++;\n\t_isNew = true;\n}\n\n}\n"
  },
  {
    "path": "src/Savegame/SoldierDiary.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/Yaml.h\"\n#include \"BattleUnit.h\"\n#include \"SavedGame.h\"\n\nnamespace OpenXcom\n{\n\nclass Mod;\nclass RuleCommendations;\nstruct BattleUnitKills;\n\n/**\n * Each entry will be its own commendation.\n */\nclass SoldierCommendations\n{\nprivate:\n\tstd::string  _type, _noun;\n\tint  _decorationLevel;\n\tbool _isNew;\n\tRuleCommendations *_rule = nullptr;\n\npublic:\n\t/// Creates a new commendation and loads its contents from YAML.\n\tSoldierCommendations(const YAML::YamlNodeReader& reader, const Mod* mod);\n\t/// Creates a commendation of the specified type.\n\tSoldierCommendations(const std::string& commendationName, const std::string& noun, const Mod* mod);\n\t/// Cleans up the commendation.\n\t~SoldierCommendations();\n\t/// Loads the commendation information from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader);\n\t/// Saves the commendation information to YAML.\n\tvoid save(YAML::YamlNodeWriter writer) const;\n\n\t/// Get commendation rule config.\n\tRuleCommendations* getRule() { return _rule; }\n\n\t/// Get commendation name.\n\tconst std::string &getType() const;\n\t/// Get commendation noun.\n\tconst std::string &getNoun() const;\n\t/// Get the commendation's decoration level's name.\n\tstd::string getDecorationLevelName(int skipCounter) const;\n\t/// Get the commendation's decoration description.\n\tstd::string getDecorationDescription() const;\n\t/// Get the commendation's decoration level's int.\n\tint getDecorationLevelInt() const;\n\t/// Get the newness of the commendation.\n\tbool isNew() const;\n\t/// Set the commendation newness to false.\n\tvoid makeOld();\n\t/// Increment decoration level.\n\t// Sets _isNew to true.\n\tvoid addDecoration();\n};\n\nclass SoldierDiary\n{\nprivate:\n\tstd::vector<SoldierCommendations*> _commendations;\n\tstd::vector<BattleUnitKills*> _killList;\n\tstd::vector<int> _missionIdList;\n\tint _daysWoundedTotal, _totalShotByFriendlyCounter, _totalShotFriendlyCounter, _loneSurvivorTotal, _monthsService, _unconciousTotal, _shotAtCounterTotal,\n\t\t_hitCounterTotal, _ironManTotal, _longDistanceHitCounterTotal, _lowAccuracyHitCounterTotal, _shotsFiredCounterTotal, _shotsLandedCounterTotal,\n\t\t_shotAtCounter10in1Mission,\t_hitCounter5in1Mission, _timesWoundedTotal, _KIA, _allAliensKilledTotal, _allAliensStunnedTotal,\n\t\t_ufosShotDownTotal, _ufosDamageTotal,\n\t\t_woundsHealedTotal, _allUFOs, _allMissionTypes, _statGainTotal, _revivedUnitTotal, _wholeMedikitTotal, _braveryGainTotal, _bestOfRank, _MIA,\n\t\t_martyrKillsTotal, _postMortemKills, _slaveKillsTotal, _bestSoldier, _revivedSoldierTotal, _revivedHostileTotal, _revivedNeutralTotal;\n\tbool _globeTrotter;\npublic:\n\t/// Construct a diary.\n\tSoldierDiary();\n\t/// Cleans up a diary.\n\t~SoldierDiary();\n\t/// Load a diary.\n\tvoid load(const YAML::YamlNodeReader& reader, const Mod *mod);\n\t/// Save a diary.\n\tvoid save(YAML::YamlNodeWriter writer) const;\n\t/// Update the diary statistics.\n\tvoid updateDiary(BattleUnitStatistics*, std::vector<MissionStatistics*>*, Mod*);\n\t/// Get the list of kills, mapped by rank.\n\tstd::map<std::string, int> getAlienRankTotal() const;\n\t/// Get the list of kills, mapped by race.\n\tstd::map<std::string, int> getAlienRaceTotal() const;\n\t/// Get the list of kills, mapped by weapon used.\n\tstd::map<std::string, int> getWeaponTotal() const;\n\t/// Get the list of kills, mapped by weapon ammo used.\n\tstd::map<std::string, int> getWeaponAmmoTotal() const;\n\t/// Get the list of missions, mapped by region.\n\tstd::map<std::string, int> getRegionTotal(std::vector<MissionStatistics*>*) const;\n\t/// Get the list of missions, mapped by country.\n\tstd::map<std::string, int> getCountryTotal(std::vector<MissionStatistics*>*) const;\n\t/// Get the list of missions, mapped by type.\n\tstd::map<std::string, int> getTypeTotal(std::vector<MissionStatistics*>*) const;\n\t/// Get the list of missions, mapped by UFO.\n\tstd::map<std::string, int> getUFOTotal(std::vector<MissionStatistics*>*) const;\n\t/// Get the total number of kills.\n\tint getKillTotal() const;\n\t/// Get the total number of missions.\n\tint getMissionTotal() const;\n\t/// Get the total number of missions filtered by modder's criteria.\n\tint getMissionTotalFiltered(std::vector<MissionStatistics*>*, const RuleCommendations* rule) const;\n\t/// Get the total number of wins.\n\tint getWinTotal(std::vector<MissionStatistics*>*) const;\n\t/// Get the total number of stuns.\n\tint getStunTotal() const;\n\t/// Get the total number of psi panics.\n\tint getPanickTotal() const;\n\t/// Get the total number of psi mind controls.\n\tint getControlTotal() const;\n\t/// Get the total number of days wounded.\n\tint getDaysWoundedTotal() const;\n\t/// Get the solder's commendations.\n\tstd::vector<SoldierCommendations*> *getSoldierCommendations();\n\t/// Checks whether the diary contains a given commendation.\n\tbool containsCommendation(const RuleCommendations* rule) const;\n\t/// Manage commendations, return true if a medal is awarded.\n\tbool manageCommendations(const Mod* mod, SavedGame* save, const Soldier* soldier);\n\t/// Increment the soldier's service time.\n\tvoid addMonthlyService();\n\t/// Get the total months in service.\n\tint getMonthsService() const;\n\t/// Update the pilot's UFO stats.\n\tvoid addUfoShotDown(int damage);\n\t/// Get the total UFOs shot down.\n\tint getUfosShotDown() const { return _ufosShotDownTotal; }\n\t/// Get the mission id list.\n\tstd::vector<int> &getMissionIdList();\n\tconst std::vector<int>& getMissionIdList() const;\n\t/// Get the kill list.\n\tstd::vector<BattleUnitKills*> &getKills();\n\t/// Award special commendation to the original 8 soldiers.\n\tvoid awardOriginalEightCommendation(const Mod* mod);\n\t/// Award posthumous best-of rank commendation.\n\tvoid awardBestOfRank(int score);\n\t/// Award posthumous best overall commendation.\n\tvoid awardBestOverall(int score);\n\t/// Award posthumous kills commendation.\n\tvoid awardPostMortemKill(int kills);\n\t/// Get the total number of shots fired.\n\tint getShotsFiredTotal() const;\n\t/// Get the total number of shots landed on target.\n\tint getShotsLandedTotal() const;\n\t/// Get the soldier's accuracy.\n\tint getAccuracy() const;\n\t/// Get the total number of trap kills.\n\tint getTrapKillTotal(const Mod* mod) const;\n\t/// Get the total number of reaction fire kills.\n\tint getReactionFireKillTotal(const Mod* mod) const;\n\t/// Get the total number of terror missions.\n\tint getTerrorMissionTotal(std::vector<MissionStatistics*>*) const;\n\t/// Get the total number of night missions.\n\tint getNightMissionTotal(std::vector<MissionStatistics*>*, const Mod* mod) const;\n\t/// Get the total number of night terror missions.\n\tint getNightTerrorMissionTotal(std::vector<MissionStatistics*>*, const Mod* mod) const;\n\t/// Get the total number of base defense missions.\n\tint getBaseDefenseMissionTotal(std::vector<MissionStatistics*>*) const;\n\t/// Get the total number of alien base assaults.\n\tint getAlienBaseAssaultTotal(std::vector<MissionStatistics*>*) const;\n\t/// Get the total number of important missions.\n\tint getImportantMissionTotal(std::vector<MissionStatistics*>*) const;\n\t/// Get the total score.\n\tint getScoreTotal(std::vector<MissionStatistics*>*) const;\n\t/// Get the Valiant Crux total.\n\tint getValiantCruxTotal(std::vector<MissionStatistics*>*) const;\n\t/// Get the loot value total.\n\tint getLootValueTotal(std::vector<MissionStatistics*>*) const;\n};\n\n}\n"
  },
  {
    "path": "src/Savegame/Target.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Target.h\"\n#include \"Craft.h\"\n#include \"Ufo.h\"\n#include \"SerializationHelper.h\"\n#include \"../fmath.h\"\n#include \"../Engine/Language.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes a target with blank coordinates.\n */\nTarget::Target() : _lon(0.0), _lat(0.0), _id(0)\n{\n}\n\n/**\n * Make sure no crafts are chasing this target.\n */\nTarget::~Target()\n{\n\tfor (auto* follower : getCraftFollowers())\n\t{\n\t\tfollower->returnToBase();\n\t}\n\tfor (auto* ufoFollower : getUfoFollowers())\n\t{\n\t\tufoFollower->resetOriginalDestination(false);\n\t}\n}\n\n/**\n * Loads the target from a YAML file.\n * @param node YAML node.\n */\nvoid Target::load(const YAML::YamlNodeReader& reader)\n{\n\treader.tryRead(\"lon\", _lon);\n\treader.tryRead(\"lat\", _lat);\n\treader.tryRead(\"id\", _id);\n\treader.tryRead(\"name\", _name);\n}\n\n/**\n * Saves the target to a YAML file.\n * @returns YAML node.\n */\nvoid Target::save(YAML::YamlNodeWriter writer) const\n{\n\twriter.setAsMap();\n\twriter.write(\"lon\", _lon);\n\twriter.write(\"lat\", _lat);\n\tif (_id)\n\t\twriter.write(\"id\", _id);\n\tif (!_name.empty())\n\t\twriter.write(\"name\", _name);\n}\n\n/**\n * Saves the target's unique identifiers to a YAML file.\n * @return YAML node.\n */\nvoid Target::saveId(YAML::YamlNodeWriter writer) const\n{\n\twriter.setAsMap();\n\twriter.write(\"lon\", _lon);\n\twriter.write(\"lat\", _lat);\n\twriter.write(\"type\", getType());\n\twriter.write(\"id\", _id);\n}\n\n/**\n * Returns the longitude coordinate of the target.\n * @return Longitude in radian.\n */\ndouble Target::getLongitude() const\n{\n\treturn _lon;\n}\n\n/**\n * Changes the longitude coordinate of the target.\n * @param lon Longitude in radian.\n */\nvoid Target::setLongitude(double lon)\n{\n\t_lon = lon;\n\n\t// Keep between 0 and 2xPI\n\twhile (_lon < 0)\n\t\t_lon += 2 * M_PI;\n\twhile (_lon >= 2 * M_PI)\n\t\t_lon -= 2 * M_PI;\n}\n\n/**\n * Returns the latitude coordinate of the target.\n * @return Latitude in radian.\n */\ndouble Target::getLatitude() const\n{\n\treturn _lat;\n}\n\n/**\n * Changes the latitude coordinate of the target.\n * @param lat Latitude in radian.\n */\nvoid Target::setLatitude(double lat)\n{\n\t_lat = lat;\n\t// If you travel past a pole, continue on the other side of the globe.\n\tif (_lat < -M_PI/2)\n\t{\n\t\t_lat = -M_PI - _lat;\n\t\tsetLongitude(_lon + M_PI);\n\t}\n\telse if (_lat > M_PI/2)\n\t{\n\t\t_lat = M_PI - _lat;\n\t\tsetLongitude(_lon - M_PI);\n\t}\n}\n\n/**\n * Returns the target's unique ID.\n * @return Unique ID, 0 if none.\n */\nint Target::getId() const\n{\n\treturn _id;\n}\n\n/**\n * Changes the target's unique ID.\n * @param id Unique ID.\n */\nvoid Target::setId(int id)\n{\n\t_id = id;\n}\n\n/**\n * Returns the target's user-readable name.\n * If there's no custom name, the language default is used.\n * @param lang Language to get strings from.\n * @return Full name.\n */\nstd::string Target::getName(Language *lang) const\n{\n\tif (_name.empty())\n\t\treturn getDefaultName(lang);\n\treturn _name;\n}\n\n/**\n * Changes the target's custom name.\n * @param newName New custom name. If set to blank, the language default is used.\n */\nvoid Target::setName(const std::string &newName)\n{\n\t_name = newName;\n}\n\n/**\n * Returns the target's unique default name.\n * @param lang Language to get strings from.\n * @return Full name.\n */\nstd::string Target::getDefaultName(Language *lang) const\n{\n\treturn lang->getString(getMarkerName()).arg(_id);\n}\n\n/**\n * Returns the name on the globe for the target.\n * @return String ID.\n */\nstd::string Target::getMarkerName() const\n{\n\treturn getType() + \"_\";\n}\n\n/**\n * Returns the marker ID on the globe for the target.\n * @return Marker ID.\n */\nint Target::getMarkerId() const\n{\n\treturn _id;\n}\n\n/**\n * Returns the list of targets currently\n * following this target.\n * @return Pointer to list of targets.\n */\nstd::vector<MovingTarget*> *Target::getFollowers()\n{\n\treturn &_followers;\n}\n\n/**\n * Returns the list of crafts currently\n * following this target.\n * @return List of crafts.\n */\nstd::vector<Craft*> Target::getCraftFollowers() const\n{\n\tstd::vector<Craft*> crafts;\n\tfor (auto* mt : _followers)\n\t{\n\t\tCraft *craft = dynamic_cast<Craft*>(mt);\n\t\tif (craft)\n\t\t{\n\t\t\tcrafts.push_back(craft);\n\t\t}\n\t}\n\treturn crafts;\n}\n\n/**\n * Returns the list of UFOs currently\n * following this target.\n * @return List of UFOs.\n */\nstd::vector<Ufo*> Target::getUfoFollowers() const\n{\n\tstd::vector<Ufo*> ufos;\n\tfor (auto* mt : _followers)\n\t{\n\t\tUfo *ufo = dynamic_cast<Ufo*>(mt);\n\t\tif (ufo)\n\t\t{\n\t\t\tufos.push_back(ufo);\n\t\t}\n\t}\n\treturn ufos;\n}\n\n/**\n * Returns the great circle distance to another\n * target on the globe.\n * @param lon Longitude.\n * @param lat Latitude.\n * @returns Distance in radian.\n */\ndouble Target::getDistance(double lon, double lat) const\n{\n\tif (AreSame(lon, _lon) && AreSame(lat, _lat))\n\t\treturn 0.0;\n\treturn acos(cos(_lat) * cos(lat) * cos(lon - _lon) + sin(_lat) * sin(lat));\n}\n\n}\n"
  },
  {
    "path": "src/Savegame/Target.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include <vector>\n#include \"../Engine/Yaml.h\"\n\nnamespace OpenXcom\n{\n\nclass Language;\nclass MovingTarget;\nclass Craft;\nclass Ufo;\n\n/**\n * Base class for targets on the globe\n * with a set of radian coordinates.\n */\nclass Target\n{\nprotected:\n\tdouble _lon, _lat;\n\tint _id;\n\tstd::string _name;\n\tstd::vector<MovingTarget*> _followers;\n\t/// Creates a target.\n\tTarget();\npublic:\n\t/// Cleans up the target.\n\tvirtual ~Target();\n\t/// Loads the target from YAML.\n\tvirtual void load(const YAML::YamlNodeReader& reader);\n\t/// Saves the target to YAML.\n\tvirtual void save(YAML::YamlNodeWriter writer) const;\n\t/// Saves the target's ID to YAML.\n\tvirtual void saveId(YAML::YamlNodeWriter writer) const;\n\t/// Gets the target's type.\n\tvirtual std::string getType() const = 0;\n\t/// Gets the target's longitude.\n\tdouble getLongitude() const;\n\t/// Sets the target's longitude.\n\tvoid setLongitude(double lon);\n\t/// Gets the target's latitude.\n\tdouble getLatitude() const;\n\t/// Sets the target's latitude.\n\tvoid setLatitude(double lat);\n\t/// Gets the target's ID.\n\tint getId() const;\n\t/// Sets the target's ID.\n\tvoid setId(int id);\n\t/// Gets the target's name.\n\tvirtual std::string getName(Language *lang) const;\n\t/// Sets the target's name.\n\tvoid setName(const std::string &newName);\n\t/// Gets the target's default name.\n\tvirtual std::string getDefaultName(Language *lang) const;\n\t/// Gets the target's marker name.\n\tvirtual std::string getMarkerName() const;\n\t/// Gets the target's marker ID.\n\tvirtual int getMarkerId() const;\n\t/// Gets the target's marker sprite.\n\tvirtual int getMarker() const = 0;\n\t/// Gets the target's followers.\n\tstd::vector<MovingTarget*> *getFollowers();\n\t/// Gets the target's craft followers.\n\tstd::vector<Craft*> getCraftFollowers() const;\n\t/// Gets the target's UFO followers.\n\tstd::vector<Ufo*> getUfoFollowers() const;\n\t/// Gets the distance to another target.\n\tdouble getDistance(const Target *target) const { return getDistance(target->getLongitude(), target->getLatitude()); }\n\t/// Gets the distance to another position.\n\tdouble getDistance(double lon, double lat) const;\n};\n\n}\n"
  },
  {
    "path": "src/Savegame/Tile.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Tile.h\"\n#include <algorithm>\n#include \"../Mod/MapData.h\"\n#include \"../Mod/MapDataSet.h\"\n#include \"../Engine/SurfaceSet.h\"\n#include \"../Engine/Surface.h\"\n#include \"../Engine/RNG.h\"\n#include \"../Engine/ScriptBind.h\"\n#include \"BattleUnit.h\"\n#include \"BattleItem.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"../Mod/Armor.h\"\n#include \"SerializationHelper.h\"\n#include \"../Battlescape/BattlescapeGame.h\"\n#include \"../fmath.h\"\n#include \"SavedBattleGame.h\"\n\nnamespace OpenXcom\n{\n\n/// How many bytes various fields use in a serialized tile. See header.\nTile::SerializationKey Tile::serializationKey =\n{4, // index\n 2, // _mapDataSetID, four of these\n 2, // _mapDataID, four of these\n 1, // _fire\n 1, // _smoke\n 1,\t// one 8-bit bool field\n 4 + 2*4 + 2*4 + 1 + 1 + 1 // total bytes to save one tile\n};\n\n/**\n * constructor\n * @param pos Position.\n */\nTile::Tile(Position pos, SavedBattleGame* save): _save(save), _pos(pos)\n{\n\tfor (int i = 0; i < O_MAX; ++i)\n\t{\n\t\t_objects[i] = 0;\n\t\t_mapData->ID[i] = -1;\n\t\t_mapData->SetID[i] = -1;\n\t\t_objectsCache[i].currentFrame = 0;\n\t}\n\tfor (int layer = 0; layer < LL_MAX; layer++)\n\t{\n\t\t_light[layer] = 0;\n\t}\n\tfor (int i = 0; i < O_MAX; ++i)\n\t{\n\t\t_objectsCache[i].discovered = 0;\n\t}\n\t_cache.isNoFloor = 1;\n\t_cache.isGravLift = 0;\n\t_cache.isLadderOnObject = 0;\n\t_cache.isLadderOnNorth = 0;\n\t_cache.isLadderOnWest = 0;\n}\n\n/**\n * destructor\n */\nTile::~Tile()\n{\n\t_inventory.clear();\n}\n\n/**\n * Load the tile from a YAML node.\n * @param node YAML node.\n */\nvoid Tile::load(const YAML::YamlNodeReader& reader)\n{\n\t//reader.tryRead(\"position\", _position);\n\tfor (int i = 0; i < 4; i++)\n\t{\n\t\treader[\"mapDataID\"][i].tryReadVal(_mapData->ID[i]);\n\t\treader[\"mapDataSetID\"][i].tryReadVal(_mapData->SetID[i]);\n\t}\n\n\treader.tryRead(\"fire\", _fire);\n\treader.tryRead(\"smoke\", _smoke);\n\tif (const auto& discovered = reader[\"discovered\"])\n\t{\n\t\tfor (int i = 0; i < 3; i++)\n\t\t{\n\t\t\tint realTilePart = (i == 2 ? 0 : i - 1); //convert old convention to new one\n\t\t\t_objectsCache[realTilePart].discovered = (Uint8)discovered[i].readVal<bool>();\n\t\t}\n\t}\n\tif (reader[\"openDoorWest\"])\n\t{\n\t\t_objectsCache[1].currentFrame = 7;\n\t}\n\tif (reader[\"openDoorNorth\"])\n\t{\n\t\t_objectsCache[2].currentFrame = 7;\n\t}\n\tif (_fire || _smoke)\n\t{\n\t\t_animationOffset = RNG::seedless(0, 3);\n\t}\n}\n\n/**\n * Load the tile from binary.\n * @param buffer Pointer to buffer.\n * @param serKey Serialization key.\n */\nvoid Tile::loadBinary(Uint8 *buffer, Tile::SerializationKey& serKey)\n{\n\t_mapData->ID[0] = unserializeInt(&buffer, serKey._mapDataID);\n\t_mapData->ID[1] = unserializeInt(&buffer, serKey._mapDataID);\n\t_mapData->ID[2] = unserializeInt(&buffer, serKey._mapDataID);\n\t_mapData->ID[3] = unserializeInt(&buffer, serKey._mapDataID);\n\t_mapData->SetID[0] = unserializeInt(&buffer, serKey._mapDataSetID);\n\t_mapData->SetID[1] = unserializeInt(&buffer, serKey._mapDataSetID);\n\t_mapData->SetID[2] = unserializeInt(&buffer, serKey._mapDataSetID);\n\t_mapData->SetID[3] = unserializeInt(&buffer, serKey._mapDataSetID);\n\n\t_smoke = unserializeInt(&buffer, serKey._smoke);\n\t_fire = unserializeInt(&buffer, serKey._fire);\n\n\tUint8 boolFields = unserializeInt(&buffer, serKey.boolFields);\n\t_objectsCache[O_WESTWALL].discovered = (boolFields & 1) ? 1 : 0;\n\t_objectsCache[O_NORTHWALL].discovered = (boolFields & 2) ? 1 : 0;\n\t_objectsCache[O_FLOOR].discovered = (boolFields & 4) ? 1 : 0;\n\t_objectsCache[O_WESTWALL].currentFrame = (boolFields & 8) ? 7 : 0;\n\t_objectsCache[O_NORTHWALL].currentFrame = (boolFields & 0x10) ? 7 : 0;\n\tif (_fire || _smoke)\n\t{\n\t\t_animationOffset = RNG::seedless(0, 3);\n\t}\n}\n\n\n/**\n * Saves the tile to a YAML node.\n * @return YAML node.\n */\nvoid Tile::save(YAML::YamlNodeWriter writer) const\n{\n\twriter.setAsMap();\n\twriter.write(\"position\", _pos);\n\tstd::vector<int> ids(std::begin(_mapData->ID), std::end(_mapData->ID));\n\tstd::vector<int> setIds(std::begin(_mapData->SetID), std::end(_mapData->SetID));\n\twriter.write(\"mapDataID\", ids);\n\twriter.write(\"mapDataSetID\", setIds);\n\tif (_smoke)\n\t\twriter.write(\"smoke\", _smoke);\n\tif (_fire)\n\t\twriter.write(\"fire\", _fire);\n\tif (_objectsCache[O_FLOOR].discovered || _objectsCache[O_WESTWALL].discovered || _objectsCache[O_NORTHWALL].discovered)\n\t{\n\t\tthrow Exception(\"Obsolete code\");\n//\t\tfor (int i = O_FLOOR; i <= O_NORTHWALL; i++)\n//\t\t{\n//\t\t\tnode[\"discovered\"].push_back(_objectsCache[i].discovered);\n//\t\t}\n\t}\n\tif (isUfoDoorOpen(O_WESTWALL))\n\t{\n\t\twriter.write(\"openDoorWest\", true);\n\t}\n\tif (isUfoDoorOpen(O_NORTHWALL))\n\t{\n\t\twriter.write(\"openDoorNorth\", true);\n\t}\n}\n\n/**\n * Saves the tile to binary.\n * @param buffer pointer to buffer.\n */\nvoid Tile::saveBinary(Uint8** buffer) const\n{\n\tserializeInt(buffer, serializationKey._mapDataID, _mapData->ID[0]);\n\tserializeInt(buffer, serializationKey._mapDataID, _mapData->ID[1]);\n\tserializeInt(buffer, serializationKey._mapDataID, _mapData->ID[2]);\n\tserializeInt(buffer, serializationKey._mapDataID, _mapData->ID[3]);\n\tserializeInt(buffer, serializationKey._mapDataSetID, _mapData->SetID[0]);\n\tserializeInt(buffer, serializationKey._mapDataSetID, _mapData->SetID[1]);\n\tserializeInt(buffer, serializationKey._mapDataSetID, _mapData->SetID[2]);\n\tserializeInt(buffer, serializationKey._mapDataSetID, _mapData->SetID[3]);\n\n\tserializeInt(buffer, serializationKey._smoke, _smoke);\n\tserializeInt(buffer, serializationKey._fire, _fire);\n\n\tUint8 boolFields = (_objectsCache[O_WESTWALL].discovered?1:0) + (_objectsCache[O_NORTHWALL].discovered?2:0) + (_objectsCache[O_FLOOR].discovered?4:0);\n\tboolFields |= isUfoDoorOpen(O_WESTWALL) ? 8 : 0; // west\n\tboolFields |= isUfoDoorOpen(O_NORTHWALL) ? 0x10 : 0; // north?\n\tserializeInt(buffer, serializationKey.boolFields, boolFields);\n}\n\n/**\n * Set the MapData references of part 0 to 3.\n * @param dat pointer to the data object\n * @param mapDataID\n * @param mapDataSetID\n * @param part Part of the tile to set data of\n */\nvoid Tile::setMapData(MapData *dat, int mapDataID, int mapDataSetID, TilePart part)\n{\n\t_objects[part] = dat;\n\t_mapData->ID[part] = mapDataID;\n\t_mapData->SetID[part] = mapDataSetID;\n\t_objectsCache[part].isDoor = dat ? dat->isDoor() : 0;\n\t_objectsCache[part].isUfoDoor = dat ? dat->isUFODoor() : 0;\n\t_objectsCache[part].offsetY = dat ? dat->getYOffset() : 0;\n\t_objectsCache[part].isBackTileObject = dat ? dat->isBackTileObject() : 0;\n\tif (part == O_FLOOR || part == O_OBJECT)\n\t{\n\t\tint level = 0;\n\n\t\tif (_objects[O_FLOOR])\n\t\t{\n\t\t\tlevel = _objects[O_FLOOR]->getTerrainLevel();\n\t\t\t_cache.isNoFloor = _objects[O_FLOOR]->isNoFloor();\n\t\t\t_cache.isGravLift = _objects[O_FLOOR]->isGravLift();\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_cache.isNoFloor = 1;\n\t\t\t_cache.isGravLift = 0;\n\t\t}\n\t\t// whichever's higher, but not the sum.\n\t\tif (_objects[O_OBJECT])\n\t\t{\n\t\t\tlevel = std::min(_objects[O_OBJECT]->getTerrainLevel(), level);\n\t\t\t_cache.bigWall = _objects[O_OBJECT]->getBigWall() != 0;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_cache.bigWall = 0;\n\t\t}\n\t\t_cache.terrainLevel = level;\n\t}\n\tif (part == O_OBJECT)\n\t{\n\t\t_cache.isLadderOnObject = _objects[O_OBJECT] && _objects[O_OBJECT]->isGravLift();\n\t}\n\tif (part == O_NORTHWALL)\n\t{\n\t\t_cache.isLadderOnNorth = _objects[O_NORTHWALL] && _objects[O_NORTHWALL]->isGravLift();\n\t}\n\tif (part == O_WESTWALL)\n\t{\n\t\t_cache.isLadderOnWest = _objects[O_WESTWALL] && _objects[O_WESTWALL]->isGravLift();\n\t}\n\tupdateSprite(part);\n}\n\n/**\n * get the MapData references of part 0 to 3.\n * @param mapDataID\n * @param mapDataSetID\n * @param part is part of the tile to get data from\n * @return the object ID\n */\nvoid Tile::getMapData(int *mapDataID, int *mapDataSetID, TilePart part) const\n{\n\t*mapDataID = _mapData->ID[part];\n\t*mapDataSetID = _mapData->SetID[part];\n}\n\n/**\n * Gets whether this tile has no objects. Note that we can have a unit or smoke on this tile.\n * @return bool True if there is nothing but air on this tile.\n */\nbool Tile::isVoid() const\n{\n\treturn _objects[0] == 0 && _objects[1] == 0 && _objects[2] == 0 && _objects[3] == 0 && _smoke == 0 && _inventory.empty();\n}\n\n/**\n * Gets the TU cost to walk over a certain part of the tile.\n * @param part The part number.\n * @param movementType The movement type.\n * @return TU cost.\n */\nint Tile::getTUCost(int part, MovementType movementType) const\n{\n\tif (_objects[part])\n\t{\n\t\tif (_objectsCache[part].isUfoDoor && _objectsCache[part].currentFrame > 1)\n\t\t\treturn 0;\n\t\tif (part == O_OBJECT && _objects[part]->getBigWall() >= 4)\n\t\t\treturn 0;\n\t\treturn _objects[part]->getTUCost(movementType);\n\t}\n\telse\n\t\treturn 0;\n}\n\n/**\n * Whether this tile has a floor or not. If no object defined as floor, it has no floor.\n * @param savedBattleGame Save to get tile below to check if it can work as floor.\n * @return bool\n */\nbool Tile::hasNoFloor(const SavedBattleGame *savedBattleGame) const\n{\n\t//There's no point in checking for \"floor\" below if we have floor in this tile already.\n\tif (_cache.isNoFloor)\n\t{\n\t\tif (_pos.z > 0 && savedBattleGame)\n\t\t{\n\t\t\tconst Tile* tileBelow = savedBattleGame->getBelowTile(this);\n\t\t\tif (tileBelow != 0 && tileBelow->getTerrainLevel() == -24)\n\t\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn _cache.isNoFloor;\n}\n\n/**\n * Gets the tile's footstep sound.\n * @param tileBelow\n * @return sound ID\n */\nint Tile::getFootstepSound(Tile *tileBelow) const\n{\n\tint sound = -1;\n\n\tif (_objects[O_FLOOR])\n\t\tsound = _objects[O_FLOOR]->getFootstepSound();\n\tif (_objects[O_OBJECT] && _objects[O_OBJECT]->getBigWall() <= 1 && _objects[O_OBJECT]->getFootstepSound() > -1)\n\t\tsound = _objects[O_OBJECT]->getFootstepSound();\n\tif (!_objects[O_FLOOR] && !_objects[O_OBJECT] && tileBelow != 0 && tileBelow->getTerrainLevel() == -24 && tileBelow->getMapData(O_OBJECT))\n\t\tsound = tileBelow->getMapData(O_OBJECT)->getFootstepSound();\n\n\treturn sound;\n}\n\n\n/**\n * Open a door on this tile.\n * @param part\n * @param unit\n * @param reserve\n * @param rClick\n * @return a value: 0(normal door), 1(ufo door) or -1 if no door opened or 3 if ufo door(=animated) is still opening 4 if not enough TUs\n */\nint Tile::openDoor(TilePart part, BattleUnit *unit, BattleActionType reserve, bool rClick)\n{\n\tif (!_objects[part]) return -1;\n\n\tBattleActionCost cost;\n\tif (unit)\n\t{\n\t\tint tuCost = _objects[part]->getTUCost(unit->getMovementType());\n\t\tcost = BattleActionCost(reserve, unit, unit->getMainHandWeapon(false));\n\t\tcost.Time += (_save->getKneelReserved() && !unit->isKneeled() && unit->getArmor()->allowsKneeling(unit->getType() == \"SOLDIER\")) ? unit->getKneelDownCost() : 0;\n\t\tcost.Time += tuCost;\n\t\tif (!rClick)\n\t\t{\n\t\t\tcost.Energy += tuCost / 2;\n\t\t}\n\t}\n\n\tif (_objectsCache[part].isDoor)\n\t{\n\t\tif (unit && unit->isBigUnit()) // don't allow double-wide units to open swinging doors due to engine limitations\n\t\t\treturn -1;\n\t\tif (unit && cost.Time && !cost.haveTU())\n\t\t\treturn 4;\n\t\tif (_unit && _unit != unit && _unit->getPosition() != getPosition())\n\t\t\treturn -1;\n\t\tsetMapData(_objects[part]->getDataset()->getObject(_objects[part]->getAltMCD()), _objects[part]->getAltMCD(), _mapData->SetID[part],\n\t\t\t\t   _objects[part]->getDataset()->getObject(_objects[part]->getAltMCD())->getObjectType());\n\t\tsetMapData(0, -1, -1, part);\n\t\treturn 0;\n\t}\n\tif (_objectsCache[part].isUfoDoor && _objectsCache[part].currentFrame == 0) // ufo door part 0 - door is closed\n\t{\n\t\tif (unit && cost.Time && !cost.haveTU())\n\t\t\treturn 4;\n\t\t_objectsCache[part].currentFrame = 1; // start opening door\n\t\tupdateSprite((TilePart)part);\n\t\treturn 1;\n\t}\n\tif (_objectsCache[part].isUfoDoor && _objectsCache[part].currentFrame != 7) // ufo door != part 7 - door is still opening\n\t{\n\t\treturn 3;\n\t}\n\treturn -1;\n}\n\nint Tile::closeUfoDoor()\n{\n\tint retval = 0;\n\n\tfor (int part = O_FLOOR; part <= O_NORTHWALL; ++part)\n\t{\n\t\tif (isUfoDoorOpen((TilePart)part))\n\t\t{\n\t\t\t_objectsCache[part].currentFrame = 0;\n\t\t\tretval = 1;\n\t\t\tupdateSprite((TilePart)part);\n\t\t}\n\t}\n\n\treturn retval;\n}\n\n/**\n * Sets the tile's cache flag. - TODO: set this for each object separately?\n * @param flag true/false\n * @param part Tile part\n */\nvoid Tile::setDiscovered(bool flag, TilePart part)\n{\n\tif (_objectsCache[part].discovered != flag)\n\t{\n\t\t_objectsCache[part].discovered = flag;\n\t\tif (part == O_FLOOR && flag == true)\n\t\t{\n\t\t\t_objectsCache[O_WESTWALL].discovered = true;\n\t\t\t_objectsCache[O_NORTHWALL].discovered = true;\n\t\t}\n\t}\n}\n\n/**\n * Get the black fog of war state of this tile.\n * @param part Tile part\n * @return bool True = discovered the tile.\n */\nbool Tile::isDiscovered(TilePart part) const\n{\n\treturn _objectsCache[part].discovered;\n}\n\n\n/**\n * Reset the light amount on the tile. This is done before a light level recalculation.\n * @param layer Light is separated in 3 layers: Ambient, Static and Dynamic.\n */\nvoid Tile::resetLight(LightLayers layer)\n{\n\t_light[layer] = 0;\n}\n\n/**\n * Reset multiple layers of light from defined one.\n * @param layer From with layer start reset.\n */\nvoid Tile::resetLightMulti(LightLayers layer)\n{\n\tfor (int l = layer; l < LL_MAX; l++)\n\t{\n\t\t_light[l] = 0;\n\t}\n}\n\n/**\n * Add the light amount on the tile. Only add light if the current light is lower.\n * @param light Amount of light to add.\n * @param layer Light is separated in 3 layers: Ambient, Static and Dynamic.\n */\nvoid Tile::addLight(int light, LightLayers layer)\n{\n\tif (_light[layer] < light)\n\t\t_light[layer] = light;\n}\n\n/**\n * Get current light amount of the tile.\n * @param layer Light is separated in 3 layers: Ambient, Static and Dynamic.\n * @return Max light value of selected layer.\n */\nint Tile::getLight(LightLayers layer) const\n{\n\treturn _light[layer];\n}\n\nint Tile::getLightMulti(LightLayers layer) const\n{\n\tint light = 0;\n\n\tfor (int l = layer; l >= 0; --l)\n\t{\n\t\tif (_light[l] > light)\n\t\t\tlight = _light[l];\n\t}\n\n\treturn light;\n}\n\n\n/**\n * Gets the tile's shade amount 0-15. It returns the brightest of all light layers.\n * Shade level is the inverse of light level. So a maximum amount of light (15) returns shade level 0.\n * @return shade\n */\nint Tile::getShade() const\n{\n\tint light = 0;\n\n\tfor (int layer = 0; layer < LL_MAX; layer++)\n\t{\n\t\tif (_light[layer] > light)\n\t\t\tlight = _light[layer];\n\t}\n\n\treturn std::max(0, 15 - light);\n}\n\n/**\n * Destroy a part on this tile. We first remove the old object, then replace it with the destroyed one.\n * This is because the object type of the old and new one are not necessarily the same.\n * If the destroyed part is an explosive, set the tile's explosive value, which will trigger a chained explosion.\n * @param part the part to destroy.\n * @param type the objective type for this mission we are checking against.\n * @return bool Return true objective was destroyed.\n */\nbool Tile::destroy(TilePart part, SpecialTileType type)\n{\n\tbool _objective = false;\n\tif (_objects[part])\n\t{\n\t\tif (_objects[part]->isGravLift())\n\t\t\treturn false;\n\t\t_objective = _objects[part]->getSpecialType() == type;\n\t\tMapData *originalPart = _objects[part];\n\t\tint originalMapDataSetID = _mapData->SetID[part];\n\t\tsetMapData(0, -1, -1, part);\n\t\tif (originalPart->getDieMCD())\n\t\t{\n\t\t\tMapData *dead = originalPart->getDataset()->getObject(originalPart->getDieMCD());\n\t\t\tsetMapData(dead, originalPart->getDieMCD(), originalMapDataSetID, dead->getObjectType());\n\t\t}\n\t\tif (originalPart->getExplosive())\n\t\t{\n\t\t\tsetExplosive(originalPart->getExplosive(), originalPart->getExplosiveType());\n\t\t}\n\t}\n\t/* check if the floor on the lowest level is gone */\n\tif (part == O_FLOOR && getPosition().z == 0 && _objects[O_FLOOR] == 0)\n\t{\n\t\t/* replace with scorched earth */\n\t\tsetMapData(MapDataSet::getScorchedEarthTile(), 1, 0, O_FLOOR);\n\t}\n\treturn _objective;\n}\n\n/**\n * damage terrain - check against armor\n * @param part Part to check.\n * @param power Power of the damage.\n * @param type the objective type for this mission we are checking against.\n * @return bool Return true objective was destroyed\n */\nbool Tile::damage(TilePart part, int power, SpecialTileType type)\n{\n\tbool objective = false;\n\tif (power >= _objects[part]->getArmor())\n\t\tobjective = destroy(part, type);\n\treturn objective;\n}\n\n/**\n * Set a \"virtual\" explosive on this tile. We mark a tile this way to detonate it later.\n * We do it this way, because the same tile can be visited multiple times by an \"explosion ray\".\n * The explosive power on the tile is some kind of moving MAXIMUM of the explosive rays that passes it.\n * @param power Power of the damage.\n * @param damageType the damage type of the explosion (not the same as item damage types)\n * @param force Force damage.\n */\nvoid Tile::setExplosive(int power, int damageType, bool force)\n{\n\tif (force || _explosive < power)\n\t{\n\t\t_explosive = power;\n\t\t_explosiveType = damageType;\n\t}\n}\n\n/**\n * Get explosive on this tile.\n * @return explosive\n */\nint Tile::getExplosive() const\n{\n\treturn _explosive;\n}\n\n/**\n * Get explosive on this tile.\n * @return explosive\n */\nint Tile::getExplosiveType() const\n{\n\treturn _explosiveType;\n}\n\n/*\n * Flammability of a tile is the lowest flammability of it's objects.\n * @return Flammability : the lower the value, the higher the chance the tile/object catches fire.\n */\nint Tile::getFlammability() const\n{\n\tint flam = 255;\n\n\tfor (int i=0; i<4; ++i)\n\t\tif (_objects[i] && (_objects[i]->getFlammable() < flam))\n\t\t\tflam = _objects[i]->getFlammable();\n\n\treturn flam;\n}\n\n/*\n * Fuel of a tile is the highest fuel of it's objects.\n * @return how long to burn.\n */\nint Tile::getFuel() const\n{\n\tint fuel = 0;\n\n\tfor (int i=0; i<4; ++i)\n\t\tif (_objects[i] && (_objects[i]->getFuel() > fuel))\n\t\t\tfuel = _objects[i]->getFuel();\n\n\treturn fuel;\n}\n\n\n/*\n * Flammability of the particular part of the tile\n * @return Flammability : the lower the value, the higher the chance the tile/object catches fire.\n */\nint Tile::getFlammability(TilePart part) const\n{\n\treturn _objects[part]->getFlammable();\n}\n\n/*\n * Fuel of particular part of the tile\n * @return how long to burn.\n */\nint Tile::getFuel(TilePart part) const\n{\n\treturn _objects[part]->getFuel();\n}\n\n/*\n * Ignite starts fire on a tile, it will burn <fuel> rounds. Fuel of a tile is the highest fuel of its objects.\n * NOT the sum of the fuel of the objects!\n */\nvoid Tile::ignite(int power)\n{\n\tif (getFlammability() != 255)\n\t{\n\t\tpower = power - (getFlammability() / 10) + 15;\n\t\tif (power < 0)\n\t\t{\n\t\t\tpower = 0;\n\t\t}\n\t\tif (RNG::percent(power) && getFuel())\n\t\t{\n\t\t\tif (_fire == 0)\n\t\t\t{\n\t\t\t\t_smoke = 15 - Clamp(getFlammability() / 10, 1, 12);\n\t\t\t\t_overlaps = 1;\n\t\t\t\t_fire = getFuel() + 1;\n\t\t\t\t_animationOffset = RNG::generate(0,3);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Animate the tile. This means to advance the current frame for every object.\n * Ufo doors are a bit special, they animated only when triggered.\n * When ufo doors are on frame 0(closed) or frame 7(open) they are not animated further.\n */\nvoid Tile::animate()\n{\n\tint newframe;\n\tfor (int i = O_FLOOR; i < O_MAX; ++i)\n\t{\n\t\tif (_objects[i])\n\t\t{\n\t\t\tif (_objectsCache[i].isUfoDoor && (_objectsCache[i].currentFrame == 0 || _objectsCache[i].currentFrame == 7)) // ufo door is static\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tnewframe = _objectsCache[i].currentFrame + 1;\n\t\t\tif (_objectsCache[i].isUfoDoor && _objects[i]->getSpecialType() == START_POINT && newframe == 3)\n\t\t\t{\n\t\t\t\tnewframe = 7;\n\t\t\t}\n\t\t\tif (newframe == 8)\n\t\t\t{\n\t\t\t\tnewframe = 0;\n\t\t\t}\n\t\t\t_objectsCache[i].currentFrame = newframe;\n\t\t}\n\t\tupdateSprite((TilePart)i);\n\t}\n}\n\n/**\n * Update cached value of sprite.\n */\nvoid Tile::updateSprite(TilePart part)\n{\n\tif (_objects[part])\n\t{\n\t\t_currentSurface[part] = _objects[part]->getDataset()->getSurfaceset()->getFrame(_objects[part]->getSprite(_objectsCache[part].currentFrame));\n\t}\n\telse\n\t{\n\t\t_currentSurface[part] = nullptr;\n\t}\n}\n\n/**\n * Get unit from this tile or from tile below if unit poke out.\n * @param saveBattleGame\n * @return BattleUnit.\n */\nBattleUnit *Tile::getOverlappingUnit(const SavedBattleGame *saveBattleGame, TileUnitOverlapping range) const\n{\n\tauto* bu = getUnit();\n\tif (!bu && _pos.z > 0 && hasNoFloor(saveBattleGame) && _objects[O_OBJECT] == nullptr)\n\t{\n\t\tauto* tileBelow = saveBattleGame->getBelowTile(this);\n\t\tbu = tileBelow->getUnit();\n\t\tif (bu && bu->getHeight() + bu->getFloatHeight() - tileBelow->getTerrainLevel() <= static_cast<int>(range))\n\t\t{\n\t\t\tbu = nullptr; // if the unit below has no voxels poking into the tile, don't select it.\n\t\t}\n\t}\n\treturn bu;\n}\n\n/**\n * Set the amount of turns this tile is on fire. 0 = no fire.\n * @param fire : amount of turns this tile is on fire.\n */\nvoid Tile::setFire(int fire)\n{\n\t_fire = Clamp(fire, 0, 255);\n\t_animationOffset = RNG::generate(0,3);\n}\n\n/**\n * Get the amount of turns this tile is on fire. 0 = no fire.\n * @return fire : amount of turns this tile is on fire.\n */\nint Tile::getFire() const\n{\n\treturn _fire;\n}\n\n/**\n * Set the amount of turns this tile is smoking. 0 = no smoke.\n * @param smoke : amount of turns this tile is smoking.\n */\nvoid Tile::addSmoke(int smoke)\n{\n\tif (_fire == 0)\n\t{\n\t\tif (_overlaps == 0)\n\t\t{\n\t\t\t_smoke = Clamp(_smoke + smoke, 1, 15);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_smoke += smoke;\n\t\t}\n\t\t_animationOffset = RNG::generate(0,3);\n\t\taddOverlap();\n\t}\n}\n\n/**\n * Set the amount of turns this tile is smoking. 0 = no smoke.\n * @param smoke : amount of turns this tile is smoking.\n */\nvoid Tile::setSmoke(int smoke)\n{\n\t_smoke = Clamp(smoke, 0, 255);\n\t_animationOffset = RNG::generate(0,3);\n}\n\n\n/**\n * Get the amount of turns this tile is smoking. 0 = no smoke.\n * @return smoke : amount of turns this tile is smoking.\n */\nint Tile::getSmoke() const\n{\n\treturn _smoke;\n}\n\n/**\n * Get the number of frames the fire or smoke animation is off-sync.\n * To void fire and smoke animations of different tiles moving nice in sync - it looks fake.\n * @return offset\n */\nint Tile::getAnimationOffset() const\n{\n\treturn _animationOffset;\n}\n\n/**\n * Add an item on the tile.\n * @param item\n * @param ground\n */\nvoid Tile::addItem(BattleItem *item, const RuleInventory *ground)\n{\n\titem->setSlot(ground);\n\t_inventory.push_back(item);\n\titem->setTile(this);\n\n\t// Note: floorOb drawing optimisation\n\tif (item->getUnit() && _inventory.size() > 1)\n\t{\n\t\tstd::swap(_inventory.front(), _inventory.back());\n\t}\n}\n\n/**\n * Remove an item from the tile.\n * @param item\n */\nvoid Tile::removeItem(BattleItem *item)\n{\n\tfor (auto iter = _inventory.begin(); iter != _inventory.end(); ++iter)\n\t{\n\t\tif ((*iter) == item)\n\t\t{\n\t\t\t_inventory.erase(iter);\n\t\t\tbreak;\n\t\t}\n\t}\n\titem->setTile(0);\n}\n\n/**\n * Get the topmost item sprite to draw on the battlescape.\n * @return item sprite ID in floorob, or -1 when no item\n */\nBattleItem* Tile::getTopItem()\n{\n\t// Note: floorOb drawing optimisation\n\tif (_inventory.size() > 100)\n\t{\n\t\t// this tile has a metric ton of junk, it doesn't matter what gets drawn, let's draw it quickly\n\t\treturn _inventory.front();\n\t}\n\n\tint biggestWeight = -999;\n\tBattleItem* biggestItem = 0;\n\tfor (auto* bi : _inventory)\n\t{\n\t\t// Note: floorOb drawing optimisation\n\t\tif (bi->getUnit())\n\t\t{\n\t\t\t// any unit has the highest priority (btw. this is still backwards-compatible with both xcom1/xcom2, where corpses are the heaviest items)\n\t\t\treturn bi;\n\t\t}\n\t\tint temp = bi->getTotalWeight();\n\t\tif (temp > biggestWeight)\n\t\t{\n\t\t\tbiggestWeight = temp;\n\t\t\tbiggestItem = bi;\n\t\t}\n\t}\n\treturn biggestItem;\n}\n\n/**\n * Apply environment damage to unit.\n * @param unit affected unit.\n * @param smoke amount of smoke.\n * @param fire amount of file.\n */\nstatic inline void applyEnvi(BattleUnit* unit, int smoke, int fire, bool smokeDamage)\n{\n\tif (unit)\n\t{\n\t\tif (fire)\n\t\t{\n\t\t\t//and avoid setting fire elementals on fire\n\t\t\tif (unit->getSpecialAbility() != SPECAB_BURNFLOOR && unit->getSpecialAbility() != SPECAB_BURN_AND_EXPLODE)\n\t\t\t{\n\t\t\t\t// _smoke becomes our damage value\n\t\t\t\tunit->setEnviFire(smoke);\n\t\t\t}\n\t\t}\n\t\t// no fire: must be smoke\n\t\telse if (smokeDamage)\n\t\t{\n\t\t\t// try to knock this guy out.\n\t\t\tunit->setEnviSmoke(smoke / 4 + 1);\n\t\t}\n\t}\n}\n\n/**\n * New turn preparations.\n * average out any smoke added by the number of overlaps.\n * apply fire/smoke damage to units as applicable.\n */\nvoid Tile::prepareNewTurn(bool smokeDamage)\n{\n\t// we've received new smoke in this turn, but we're not on fire, average out the smoke.\n\tif ( _overlaps != 0 && _smoke != 0 && _fire == 0)\n\t{\n\t\t_smoke = Clamp((_smoke / _overlaps) - 1, 0, 15);\n\t}\n\t// if we still have smoke/fire\n\tif (_smoke)\n\t{\n\t\tapplyEnvi(_unit, _smoke, _fire, smokeDamage);\n\t\tfor (auto* bi : _inventory)\n\t\t{\n\t\t\tapplyEnvi(bi->getUnit(), _smoke, _fire, smokeDamage);\n\t\t}\n\t}\n\t_overlaps = 0;\n}\n\n/**\n * Get the inventory on this tile.\n * @return pointer to a vector of battle items.\n */\nstd::vector<BattleItem *> *Tile::getInventory()\n{\n\treturn &_inventory;\n}\n\n\n/**\n * Set the marker color on this tile.\n * @param color\n */\nvoid Tile::setMarkerColor(int color)\n{\n\t_markerColor = color;\n}\n\n/**\n * Get the marker color on this tile.\n * @return color\n */\nint Tile::getMarkerColor() const\n{\n\treturn _markerColor;\n}\n\n/**\n * Set the tile visible flag.\n * @param visibility\n */\nvoid Tile::setVisible(int visibility)\n{\n\t_visible += visibility;\n}\n\n/**\n * Get the tile visible flag.\n * @return visibility\n */\nint Tile::getVisible() const\n{\n\treturn _visible;\n}\n\n/**\n * set the direction used for path previewing.\n * @param dir\n */\nvoid Tile::setPreview(int dir)\n{\n\t_preview = dir;\n}\n\n/**\n * retrieve the direction stored by the pathfinding.\n * @return preview\n */\nint Tile::getPreview() const\n{\n\treturn _preview;\n}\n\n/**\n * set the number to be displayed for pathfinding preview.\n * @param tu\n */\nvoid Tile::setTUMarker(int tu)\n{\n\t_TUMarker = tu;\n}\n\n/**\n * get the number to be displayed for pathfinding preview.\n * @return marker\n */\nint Tile::getTUMarker() const\n{\n\treturn _TUMarker;\n}\n\n/**\n * set the number to be displayed for pathfinding preview.\n * @param energy\n */\nvoid Tile::setEnergyMarker(int energy)\n{\n       _EnergyMarker = energy;\n}\n\n/**\n * get the number to be displayed for pathfinding preview.\n * @return marker\n */\nint Tile::getEnergyMarker() const\n{\n       return _EnergyMarker;\n}\n\n\n/**\n * get the overlap value of this tile.\n * @return overlap\n */\nint Tile::getOverlaps() const\n{\n\treturn _overlaps;\n}\n\n/**\n * increment the overlap value on this tile.\n */\nvoid Tile::addOverlap()\n{\n\t++_overlaps;\n}\n\n/**\n * set the danger flag on this tile.\n */\nvoid Tile::setDangerous(bool danger)\n{\n\t_cache.danger = danger;\n}\n\n/**\n * get the danger flag on this tile.\n * @return the danger flag for this tile.\n */\nbool Tile::getDangerous() const\n{\n\treturn _cache.danger;\n}\n\n/**\n * sets the flag of an obstacle for single part.\n */\nvoid Tile::setObstacle(int part)\n{\n\t_obstacle |= (1 << part);\n}\n\n/**\n * resets obstacle flag for all parts of the tile.\n */\nvoid Tile::resetObstacle(void)\n{\n\t_obstacle = 0;\n}\n\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tScript binding\n////////////////////////////////////////////////////////////\n\nnamespace\n{\n\n/**\n * Get the X part of the tile coordinate of this tile.\n * @return X Position.\n */\nvoid getPositionXScript(const Tile *t, int &ret)\n{\n\tif (t)\n\t{\n\t\tret = t->getPosition().x;\n\t\treturn;\n\t}\n\tret = 0;\n}\n\n/**\n * Get the Y part of the tile coordinate of this tile.\n * @return Y Position.\n */\nvoid getPositionYScript(const Tile *t, int &ret)\n{\n\tif (t)\n\t{\n\t\tret = t->getPosition().y;\n\t\treturn;\n\t}\n\tret = 0;\n}\n\n/**\n * Get the Z part of the tile coordinate of this tile.\n * @return Z Position.\n */\nvoid getPositionZScript(const Tile *t, int &ret)\n{\n\tif (t)\n\t{\n\t\tret = t->getPosition().z;\n\t\treturn;\n\t}\n\tret = 0;\n}\n\nvoid getDistanceTileScript(const Tile *t, int &ret, const Tile *other)\n{\n\tret = t && other ? Position::distance(t->getPosition(), other->getPosition()) : -1;\n}\n\nvoid getDistanceVoxelScript(const Tile *t, int &ret, const Tile *other)\n{\n\tret = t && other ? Position::distance(t->getPosition().toVoxel(), other->getPosition().toVoxel()) : -1;\n}\n\nvoid getFloorSpecialTileTypeScript(const Tile *t, int &ret)\n{\n\tret = t ? t->getFloorSpecialTileType() : TILE;\n}\n\nvoid getObjectSpecialTileTypeScript(const Tile *t, int &ret)\n{\n\tret = t ? t->getObjectSpecialTileType() : TILE;\n}\n\nvoid isDiscoveredScript(const Tile *t, int &ret)\n{\n\tif (t)\n\t{\n\t\tret = (\n\t\t\t(t->isDiscovered(O_FLOOR) << 0) |\n\t\t\t(t->isDiscovered(O_WESTWALL) << 1) |\n\t\t\t(t->isDiscovered(O_NORTHWALL) << 2)\n\t\t);\n\t\treturn;\n\t}\n\tret = 0;\n}\n\nvoid makeDiscoveredScript(Tile *t, int i)\n{\n\tif (t)\n\t{\n\t\tif (i & (1<<0)) t->setDiscovered(true, O_FLOOR);\n\t\tif (i & (1<<1)) t->setDiscovered(true, O_WESTWALL);\n\t\tif (i & (1<<2)) t->setDiscovered(true, O_NORTHWALL);\n\t\treturn;\n\t}\n}\n\nvoid getUnitScript(const Tile *t, const BattleUnit*& ret)\n{\n\tret = t ? t->getUnit() : nullptr;\n}\n\n\n\n\nvoid addPositionScript(Position& a, Position v)\n{\n\ta += v;\n}\n\nvoid subPositionScript(Position& a, Position v)\n{\n\ta -= v;\n}\n\nvoid mulByPositionScript(Position& a, Position v)\n{\n\ta *= v;\n}\n\nvoid mulByIntScript(Position& a, int v)\n{\n\ta *= v;\n}\n\nvoid mulDivByIntScript(Position& a, int v, int d)\n{\n\tif (d)\n\t{\n\t\t// to avoid overflow on `Sint16` we multiply manually\n\t\ta = { a.x * v / d, a.y * v / d, a.z * v / d };\n\t}\n\telse\n\t{\n\t\ta = {};\n\t}\n}\n\n\n\n\nstd::string debugDisplayScript(const Position* t)\n{\n\tif (t)\n\t{\n\t\tstd::string s;\n\t\ts += \"Position\";\n\t\ts += \"(x: \";\n\t\ts += std::to_string(t->x);\n\t\ts += \" y: \";\n\t\ts += std::to_string(t->y);\n\t\ts += \" z: \";\n\t\ts += std::to_string(t->z);\n\t\ts += \")\";\n\t\treturn s;\n\t}\n\telse\n\t{\n\t\treturn \"null\";\n\t}\n}\n\nstd::string debugDisplayScript(const Tile* t)\n{\n\tif (t)\n\t{\n\t\tstd::string s;\n\t\ts += Tile::ScriptName;\n\t\ts += \"(x: \";\n\t\ts += std::to_string(t->getPosition().x);\n\t\ts += \" y: \";\n\t\ts += std::to_string(t->getPosition().y);\n\t\ts += \" z: \";\n\t\ts += std::to_string(t->getPosition().z);\n\t\ts += \" isVoid: \";\n\t\ts += t->isVoid() ? \"true\" : \"false\";\n\t\tif (t->getUnit())\n\t\t{\n\t\t\ts += \" unit: \\\"\";\n\t\t\ts += t->getUnit()->getType();\n\t\t\ts += \"\\\"\";\n\t\t}\n\t\ts += \")\";\n\t\treturn s;\n\t}\n\telse\n\t{\n\t\treturn \"null\";\n\t}\n}\n\n\n\n} //namespace\n\nvoid Tile::ScriptRegister(ScriptParserBase* parser)\n{\n\n\t{\n\t\tconst auto name = std::string{ \"Position\" };\n\t\tparser->registerRawValueType<Position>(name);\n\t\tBindValue<Position> rs = { parser, name };\n\n\t\trs.addConstructor<int, int, int>();\n\n\t\trs.addField<&Position::x>(\"getX\", \"setX\", \"addX\");\n\t\trs.addField<&Position::y>(\"getY\", \"setY\", \"addY\");\n\t\trs.addField<&Position::z>(\"getZ\", \"setZ\", \"addZ\");\n\n\t\trs.addFreeFunction<&mulByIntScript>(\"mul\");\n\t\trs.addFreeFunction<&mulDivByIntScript>(\"muldiv\");\n\t\trs.addFreeFunction<&mulByPositionScript>(\"mul\");\n\t\trs.addFreeFunction<&addPositionScript>(\"add\");\n\t\trs.addFreeFunction<&subPositionScript>(\"sub\");\n\n\t\trs.addDebugValueDisplay<&debugDisplayScript>();\n\t}\n\n\tBind<Tile> t = { parser };\n\n\tt.add<&getPositionXScript>(\"getPosition.getX\");\n\tt.add<&getPositionYScript>(\"getPosition.getY\");\n\tt.add<&getPositionZScript>(\"getPosition.getZ\");\n\tt.add<&Tile::getPosition>(\"getPosition\");\n\tt.add<&Tile::getFire>(\"getFire\");\n\tt.add<&Tile::getSmoke>(\"getSmoke\");\n\tt.add<&Tile::getShade>(\"getShade\");\n\n\tt.add<&isDiscoveredScript>(\"isDiscovered\", \"Check what part of tile is discovered, 0x1 - floor, 0x2 - westwall, 0x4 - eastwall\");\n\tt.add<&makeDiscoveredScript>(\"makeDiscovered\", \"Make part of tile discovered, 0x1 - floor (will make both walls visible too), 0x2 - westwall, 0x4 - eastwall\");\n\n\n\tt.add<&getUnitScript>(\"getUnit\");\n\n\tt.add<&getDistanceTileScript>(\"getDistanceTile\");\n\tt.add<&getDistanceVoxelScript>(\"getDistanceVoxel\");\n\n\tt.add<&getFloorSpecialTileTypeScript>(\"getFloorSpecialTileType\");\n\tt.add<&getObjectSpecialTileTypeScript>(\"getObjectSpecialTileType\");\n\n\tt.addDebugDisplay<&debugDisplayScript>();\n\n\tt.addCustomConst(\"STT_TILE\", SpecialTileType::TILE);\n\tt.addCustomConst(\"STT_START_POINT\", SpecialTileType::START_POINT);\n\tt.addCustomConst(\"STT_END_POINT\", SpecialTileType::END_POINT);\n\n}\n\n} //namespace OpenXcom\n"
  },
  {
    "path": "src/Savegame/Tile.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <vector>\n#include <memory>\n#include \"../Engine/Surface.h\"\n#include \"../Battlescape/Position.h\"\n#include \"../Mod/MapData.h\"\n\n#include <SDL_types.h> // for Uint8\n\nnamespace OpenXcom\n{\n\nclass MapData;\nclass BattleUnit;\nclass BattleItem;\nclass RuleInventory;\nclass SavedBattleGame;\nclass ScriptParserBase;\n\nenum LightLayers : Uint8 { LL_AMBIENT, LL_FIRE, LL_ITEMS, LL_UNITS, LL_MAX };\n\nenum TileUnitOverlapping : int\n{\n\t/// Any unit overlapping tile will be returned\n\tTUO_NORMAL = 24,\n\t/// Only units that overlap by 2 or more voxel will be returned\n\tTUO_IGNORE_SMALL = 26,\n\t/// Take unit from lower even if it not overlap\n\tTUO_ALWAYS = 0,\n};\n\n/**\n * Basic element of which a battle map is build.\n * @sa http://www.ufopaedia.org/index.php?title=MAPS\n */\nclass Tile\n{\npublic:\n\n\t/// Name of class used in script.\n\tstatic constexpr const char *ScriptName = \"Tile\";\n\t/// Register all useful function used by script.\n\tstatic void ScriptRegister(ScriptParserBase* parser);\n\n\tstatic struct SerializationKey\n\t{\n\t\t// how many bytes to store for each variable or each member of array of the same name\n\t\tUint8 index; // for indexing the actual tile array\n\t\tUint8 _mapDataSetID;\n\t\tUint8 _mapDataID;\n\t\tUint8 _smoke;\n\t\tUint8 _fire;\n\t\tUint8 boolFields;\n\t\tUint32 totalBytes; // per structure, including any data not mentioned here and accounting for all array members!\n\t} serializationKey;\n\n\tstatic const int NOT_CALCULATED = -1;\n\n\t/**\n\t * Cache of ID for tile parts used to save and load.\n\t */\n\tstruct TileMapDataCache\n\t{\n\t\tint ID[O_MAX];\n\t\tint SetID[O_MAX];\n\t};\n\t/**\n\t * Cached data that belongs to each tile object\n\t */\n\tstruct TileObjectCache\n\t{\n\t\tSint8 offsetY;\n\t\tUint8 currentFrame:4;\n\t\tUint8 discovered:1;\n\t\tUint8 isUfoDoor:1;\n\t\tUint8 isDoor:1;\n\t\tUint8 isBackTileObject:1;\n\t};\n\t/**\n\t * Cached data that belongs to whole tile\n\t */\n\tstruct TileCache\n\t{\n\t\tSint8 terrainLevel = 0;\n\t\tUint8 isNoFloor:1;\n\t\tUint8 isGravLift:1;\n\t\tUint8 isLadderOnObject:1;\n\t\tUint8 isLadderOnNorth:1;\n\t\tUint8 isLadderOnWest:1;\n\t\tUint8 bigWall:1;\n\t\tUint8 danger:1;\n\t};\n\nprotected:\n\tSavedBattleGame* _save;\n\tMapData *_objects[O_MAX];\n\tBattleUnit *_unit = nullptr;\n\tstd::vector<BattleItem *> _inventory;\n\tstd::unique_ptr<TileMapDataCache> _mapData = std::make_unique<TileMapDataCache>();\n\tSurfaceRaw<const Uint8> _currentSurface[O_MAX] = { };\n\tTileObjectCache _objectsCache[O_MAX] = { };\n\tTileCache _cache = { };\n\tPosition _pos;\n\tUint8 _light[LL_MAX];\n\tUint8 _fire = 0;\n\tUint8 _smoke = 0;\n\tUint8 _markerColor = 0;\n\tUint8 _animationOffset = 0;\n\tUint8 _obstacle = 0;\n\tUint8 _explosiveType = 0;\n\tSint16 _explosive = 0;\n\tSint16 _visible = 0;\n\tSint16 _TUMarker = -1;\n\tSint16 _EnergyMarker = -1;\n\tSint8 _preview = -1;\n\tUint8 _overlaps = 0;\n\n\npublic:\n\t/// Creates a tile.\n\tTile(Position pos, SavedBattleGame* save);\n\t/// Copy constructor.\n\tTile(Tile&&) = default;\n\t/// Cleans up a tile.\n\t~Tile();\n\t/// Load the tile from yaml\n\tvoid load(const YAML::YamlNodeReader& reader);\n\t/// Load the tile from binary buffer in memory\n\tvoid loadBinary(Uint8 *buffer, Tile::SerializationKey& serializationKey);\n\t/// Saves the tile to yaml\n\tvoid save(YAML::YamlNodeWriter writer) const;\n\t/// Saves the tile to binary\n\tvoid saveBinary(Uint8** buffer) const;\n\n\t/**\n\t * Get the MapData pointer of a part of the tile.\n\t * @param part TilePart whose data is needed.\n\t * @return pointer to mapdata\n\t */\n\tMapData *getMapData(TilePart part) const\n\t{\n\t\treturn _objects[part];\n\t}\n\n\t/**\n\t * Get special tile type of floor part.\n\t * @return Type of Tile.\n\t */\n\tSpecialTileType getFloorSpecialTileType() const\n\t{\n\t\treturn _objects[O_FLOOR] ? _objects[O_FLOOR]->getSpecialType() : TILE;\n\t}\n\n\t/**\n\t * Get special tile type of object part.\n\t * @return Type of Tile.\n\t */\n\tSpecialTileType getObjectSpecialTileType() const\n\t{\n\t\treturn _objects[O_OBJECT] ? _objects[O_OBJECT]->getSpecialType() : TILE;\n\t}\n\n\t/// Get saved battle game that tile belongs.\n\tconst SavedBattleGame* getSavedGame() const { return _save; }\n\t/// Get saved battle game that tile belongs.\n\tSavedBattleGame* getSavedGame() { return _save; }\n\n\n\t/// Sets the pointer to the mapdata for a specific part of the tile\n\tvoid setMapData(MapData *dat, int mapDataID, int mapDataSetID, TilePart part);\n\t/// Gets the IDs to the mapdata for a specific part of the tile\n\tvoid getMapData(int *mapDataID, int *mapDataSetID, TilePart part) const;\n\t/// Gets whether this tile has no objects\n\tbool isVoid() const;\n\t/// Get the TU cost to walk over a certain part of the tile.\n\tint getTUCost(int part, MovementType movementType) const;\n\t/// Checks if this tile has a floor.\n\tbool hasNoFloor(const SavedBattleGame *savedBattleGame = nullptr) const;\n\t/// Checks if this tile has a GravLift floor.\n\tbool hasGravLiftFloor() const { return _cache.isGravLift; }\n\t/// Check if this tile has a Ladder (similar to GravLift but on wall).\n\tbool hasLadder() const { return _cache.isLadderOnObject || _cache.isLadderOnNorth || _cache.isLadderOnWest; }\n\t/// Check if this tile object part has a Ladder (similar to GravLift but on wall).\n\tbool hasLadderOnObject() const { return _cache.isLadderOnObject; }\n\t/// Check if this tile wall part has a Ladder (similar to GravLift but on wall).\n\tbool hasLadderOnNorthWall() const { return _cache.isLadderOnNorth; }\n\t/// Check if this tile wall part has a Ladder (similar to GravLift but on wall).\n\tbool hasLadderOnWestWall() const { return _cache.isLadderOnWest; }\n\n\t/**\n\t * Whether this tile has a big wall.\n\t * @return bool\n\t */\n\tbool isBigWall() const\n\t{\n\t\treturn _cache.bigWall;\n\t}\n\n\t/**\n\t * Gets the height of the terrain (dirt/stairs/etc.) on this tile.\n\t * @return the height in voxels (more negative values are higher, e.g. -8 = lower stairs, -16 = higher stairs)\n\t */\n\tint getTerrainLevel() const\n\t{\n\t\treturn _cache.terrainLevel;\n\t}\n\n\t/**\n\t * Gets the tile's position.\n\t * @return position\n\t */\n\tPosition getPosition() const\n\t{\n\t\treturn _pos;\n\t}\n\n\t/// Gets the floor object footstep sound.\n\tint getFootstepSound(Tile *tileBelow) const;\n\t/// Open a door, returns the ID, 0(normal), 1(ufo) or -1 if no door opened.\n\tint openDoor(TilePart part, BattleUnit *unit = 0, BattleActionType reserve = BA_NONE, bool rClick = false);\n\n\t/**\n\t * Check if the ufo door is open or opening. Used for visibility/light blocking checks.\n\t * This function assumes that there never are 2 doors on 1 tile or a door and another wall on 1 tile.\n\t * @param part Tile part to look for door\n\t * @return bool\n\t */\n\tbool isUfoDoorOpen(TilePart tp) const\n\t{\n\t\treturn (_objectsCache[tp].isUfoDoor && _objectsCache[tp].currentFrame);\n\t}\n\n\t/**\n\t * Check if part is ufo door.\n\t * @param tp Part to check\n\t * @return True if part is ufo door.\n\t */\n\tbool isUfoDoor(TilePart tp) const\n\t{\n\t\treturn _objectsCache[tp].isUfoDoor;\n\t}\n\n\t/**\n\t * Check if part is door.\n\t * @param tp Part to check\n\t * @return True if part is door.\n\t */\n\tbool isDoor(TilePart tp) const\n\t{\n\t\treturn _objectsCache[tp].isDoor;\n\t}\n\n\t/**\n\t * Check if an object should be drawn behind or in front of a unit.\n\t * @param tp Part to check\n\t * @return True if its back object.\n\t */\n\tbool isBackTileObject(TilePart tp) const\n\t{\n\t\treturn _objectsCache[tp].isBackTileObject;\n\t}\n\n\t/**\n\t * Gets surface Y offset.\n\t * @param tp Part for offset.\n\t * @return Offset value.\n\t */\n\tint getYOffset(TilePart tp) const\n\t{\n\t\treturn _objectsCache[tp].offsetY;\n\t}\n\n\t/// Close ufo door.\n\tint closeUfoDoor();\n\t/// Sets the black fog of war status of this tile.\n\tvoid setDiscovered(bool flag, TilePart part);\n\t/// Gets the black fog of war status of this tile.\n\tbool isDiscovered(TilePart part) const;\n\t/// Reset light to zero for this tile.\n\tvoid resetLight(LightLayers layer);\n\t/// Reset light to zero for this tile and multiple layers.\n\tvoid resetLightMulti(LightLayers layer);\n\t/// Add light to this tile.\n\tvoid addLight(int light, LightLayers layer);\n\t/// Get max light to this tile.\n\tint getLight(LightLayers layer) const;\n\t/// Get max light to this tile and multiple layers.\n\tint getLightMulti(LightLayers layer) const;\n\t/// Get the shade amount.\n\tint getShade() const;\n\t/// Destroy a tile part.\n\tbool destroy(TilePart part, SpecialTileType type);\n\t/// Damage a tile part.\n\tbool damage(TilePart part, int power, SpecialTileType type);\n\t/// Set a \"virtual\" explosive on this tile, to detonate later.\n\tvoid setExplosive(int power, int damageType, bool force = false);\n\t/// Get explosive power of this tile.\n\tint getExplosive() const;\n\t/// Get explosive power of this tile.\n\tint getExplosiveType() const;\n\t/// Animated the tile parts.\n\tvoid animate();\n\t/// Update cached value of sprite.\n\tvoid updateSprite(TilePart part);\n\t/// Get object sprites.\n\tSurfaceRaw<const Uint8> getSprite(TilePart part) const\n\t{\n\t\treturn _currentSurface[part];\n\t}\n\n\t/**\n\t * Set a unit on this tile.\n\t */\n\tvoid setUnit(BattleUnit *unit)\n\t{\n\t\t_unit = unit;\n\t}\n\n\t/**\n\t * Get the (alive) unit on this tile.\n\t * @return BattleUnit.\n\t */\n\tBattleUnit *getUnit() const\n\t{\n\t\treturn _unit;\n\t}\n\n\t/// Get unit from this tile or from tile below.\n\tBattleUnit *getOverlappingUnit(const SavedBattleGame *saveBattleGame, TileUnitOverlapping range = TUO_NORMAL) const;\n\t/// Set fire, does not increment overlaps.\n\tvoid setFire(int fire);\n\t/// Get fire.\n\tint getFire() const;\n\t/// Add smoke, increments overlap.\n\tvoid addSmoke(int smoke);\n\t/// Set smoke, does not increment overlaps.\n\tvoid setSmoke(int smoke);\n\t/// Get smoke.\n\tint getSmoke() const;\n\t/// Get flammability.\n\tint getFlammability() const;\n\t/// Get turns to burn\n\tint getFuel() const;\n\t/// Get flammability of part.\n\tint getFlammability(TilePart part) const;\n\t/// Get turns to burn of part\n\tint getFuel(TilePart part) const;\n\t/// attempt to set the tile on fire, sets overlaps to one if successful.\n\tvoid ignite(int power);\n\t/// Get fire and smoke animation offset.\n\tint getAnimationOffset() const;\n\t/// Add item\n\tvoid addItem(BattleItem *item, const RuleInventory *ground);\n\t/// Remove item\n\tvoid removeItem(BattleItem *item);\n\t/// Get top-most item\n\tBattleItem* getTopItem();\n\t/// New turn preparations.\n\tvoid prepareNewTurn(bool smokeDamage);\n\t/// Get inventory on this tile.\n\tstd::vector<BattleItem *> *getInventory();\n\t/// Set the tile marker color.\n\tvoid setMarkerColor(int color);\n\t/// Get the tile marker color.\n\tint getMarkerColor() const;\n\t/// Set the tile visible flag.\n\tvoid setVisible(int visibility);\n\t/// Get the tile visible flag.\n\tint getVisible() const;\n\t/// set the direction (used for path previewing)\n\tvoid setPreview(int dir);\n\t/// retrieve the direction stored by the pathfinding.\n\tint getPreview() const;\n\t/// set the number to be displayed for pathfinding preview.\n\tvoid setTUMarker(int tu);\n\t/// get the number to be displayed for pathfinding preview.\n\tint getTUMarker() const;\n    /// set the number to be displayed for pathfinding preview.\n    void setEnergyMarker(int tu);\n    /// get the number to be displayed for pathfinding preview.\n    int getEnergyMarker() const;\n\t/// how many times has this tile been overlapped with smoke/fire (runtime only)\n\tint getOverlaps() const;\n\t/// increment the overlap value on this tile.\n\tvoid addOverlap();\n\t/// set the danger flag on this tile (so the AI will avoid it).\n\tvoid setDangerous(bool danger);\n\t/// check the danger flag on this tile.\n\tbool getDangerous() const;\n\n\t/// sets single obstacle flag.\n\tvoid setObstacle(int part);\n\t/// gets single obstacle flag.\n\tbool getObstacle(int part) const\n\t{\n\t\treturn _obstacle & (1 << part);\n\t}\n\t/// does the tile have obstacle flag set for at least one part?\n\tbool isObstacle(void) const\n\t{\n\t\treturn _obstacle != 0;\n\t}\n\t/// reset obstacle flags\n\tvoid resetObstacle(void);\n};\n\n}\n"
  },
  {
    "path": "src/Savegame/Transfer.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Transfer.h\"\n#include \"Base.h\"\n#include \"Soldier.h\"\n#include \"Craft.h\"\n#include \"ItemContainer.h\"\n#include \"../Engine/Language.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/Logger.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes a transfer.\n * @param hours Hours in-transit.\n */\nTransfer::Transfer(int hours) : _hours(hours), _soldier(0), _craft(0), _itemQty(0), _scientists(0), _engineers(0), _delivered(false)\n{\n}\n\n/**\n * Cleans up undelivered transfers.\n */\nTransfer::~Transfer()\n{\n\tif (!_delivered)\n\t{\n\t\tdelete _soldier;\n\t\tdelete _craft;\n\t}\n}\n\n/**\n * Loads the transfer from a YAML file.\n * @param node YAML node.\n * @param base Destination base.\n * @param rule Game mod.\n * @param save Pointer to savegame.\n * @return Was the transfer content valid?\n */\nbool Transfer::load(const YAML::YamlNodeReader& reader, Base *base, const Mod *mod, SavedGame *save)\n{\n\treader.tryRead(\"hours\", _hours);\n\n\tif (const auto& soldier = reader[\"soldier\"])\n\t{\n\t\tstd::string type = soldier[\"type\"].readVal(mod->getSoldiersList().front());\n\t\tif (mod->getSoldier(type))\n\t\t{\n\t\t\t_soldier = new Soldier(mod->getSoldier(type), nullptr, 0 /*nationality*/);\n\t\t\t_soldier->load(soldier, mod, save, mod->getScriptGlobal());\n\t\t}\n\t\telse\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"Failed to load soldier \" << type;\n\t\t\tdelete this;\n\t\t\treturn false;\n\t\t}\n\t}\n\tif (const auto& craft = reader[\"craft\"])\n\t{\n\t\tstd::string type = craft[\"type\"].readVal<std::string>();\n\t\tif (mod->getCraft(type))\n\t\t{\n\t\t\t_craft = new Craft(mod->getCraft(type), base);\n\t\t\t_craft->load(craft, mod->getScriptGlobal(), mod, 0);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"Failed to load craft \" << type;\n\t\t\tdelete this;\n\t\t\treturn false;\n\t\t}\n\n\t}\n\tif (const auto& item = reader[\"itemId\"])\n\t{\n\t\tstd::string name = item.readVal<std::string>();\n\t\t_itemId = mod->getItem(name);\n\t\tif (!_itemId)\n\t\t{\n\t\t\tLog(LOG_ERROR) << \"Failed to load item \" << name;\n\t\t\tdelete this;\n\t\t\treturn false;\n\t\t}\n\t}\n\treader.tryRead(\"itemQty\", _itemQty);\n\treader.tryRead(\"scientists\", _scientists);\n\treader.tryRead(\"engineers\", _engineers);\n\treader.tryRead(\"delivered\", _delivered);\n\treturn true;\n}\n\n/**\n * Saves the transfer to a YAML file.\n * @return YAML node.\n */\nvoid Transfer::save(YAML::YamlNodeWriter writer, const Base* b, const Mod* mod) const\n{\n\twriter.setAsMap();\n\twriter.write(\"hours\", _hours);\n\tif (_soldier != 0)\n\t{\n\t\t_soldier->save(writer[\"soldier\"], mod->getScriptGlobal());\n\t}\n\telse if (_craft != 0)\n\t{\n\t\t_craft->save(writer[\"craft\"], mod->getScriptGlobal());\n\t}\n\telse if (_itemQty != 0)\n\t{\n\t\twriter.write(\"itemId\", _itemId->getType());\n\t\twriter.write(\"itemQty\", _itemQty);\n\t}\n\telse if (_scientists != 0)\n\t{\n\t\twriter.write(\"scientists\", _scientists);\n\t}\n\telse if (_engineers != 0)\n\t{\n\t\twriter.write(\"engineers\", _engineers);\n\t}\n\tif (_delivered)\n\t\twriter.write(\"delivered\", _delivered);\n}\n\n/**\n * Changes the soldier being transferred.\n * @param soldier Pointer to soldier.\n */\nvoid Transfer::setSoldier(Soldier *soldier)\n{\n\t_soldier = soldier;\n}\n\n/**\n * Changes the craft being transferred.\n * @param craft Pointer to craft.\n */\nvoid Transfer::setCraft(Craft *craft)\n{\n\t_craft = craft;\n}\n\n/**\n * Gets the craft being transferred.\n * @return a Pointer to craft.\n */\nCraft *Transfer::getCraft()\n{\n\treturn _craft;\n}\n\n/**\n * Returns the items being transferred.\n * @return Item ID.\n */\nconst RuleItem* Transfer::getItems() const\n{\n\treturn _itemId;\n}\n\n/**\n * Changes the items being transferred.\n * @param id Item identifier.\n * @param qty Item quantity.\n */\nvoid Transfer::setItems(const RuleItem* rule, int qty)\n{\n\t_itemId = rule;\n\t_itemQty = qty;\n}\n\n/**\n * Changes the scientists being transferred.\n * @param scientists Amount of scientists.\n */\nvoid Transfer::setScientists(int scientists)\n{\n\t_scientists = scientists;\n}\n\n/**\n * Changes the engineers being transferred.\n * @param engineers Amount of engineers.\n */\nvoid Transfer::setEngineers(int engineers)\n{\n\t_engineers = engineers;\n}\n\n/**\n * Returns the name of the contents of the transfer.\n * @param lang Language to get strings from.\n * @return Name string.\n */\nstd::string Transfer::getName(Language *lang) const\n{\n\tif (_soldier != 0)\n\t{\n\t\treturn _soldier->getName();\n\t}\n\telse if (_craft != 0)\n\t{\n\t\treturn _craft->getName(lang);\n\t}\n\telse if (_scientists != 0)\n\t{\n\t\treturn lang->getString(\"STR_SCIENTISTS\");\n\t}\n\telse if (_engineers != 0)\n\t{\n\t\treturn lang->getString(\"STR_ENGINEERS\");\n\t}\n\treturn lang->getString(_itemId->getType());\n}\n\n/**\n * Returns the time remaining until the\n * transfer arrives at its destination.\n * @return Amount of hours.\n */\nint Transfer::getHours() const\n{\n\treturn _hours;\n}\n\n/**\n * Returns the quantity of items in the transfer.\n * @return Amount of items.\n */\nint Transfer::getQuantity() const\n{\n\tif (_itemQty != 0)\n\t{\n\t\treturn _itemQty;\n\t}\n\telse if (_scientists != 0)\n\t{\n\t\treturn _scientists;\n\t}\n\telse if (_engineers != 0)\n\t{\n\t\treturn _engineers;\n\t}\n\treturn 1;\n}\n\n/**\n * Returns the type of the contents of the transfer.\n * @return TransferType.\n */\nTransferType Transfer::getType() const\n{\n\tif (_soldier != 0)\n\t{\n\t\treturn TRANSFER_SOLDIER;\n\t}\n\telse if (_craft != 0)\n\t{\n\t\treturn TRANSFER_CRAFT;\n\t}\n\telse if (_scientists != 0)\n\t{\n\t\treturn TRANSFER_SCIENTIST;\n\t}\n\telse if (_engineers != 0)\n\t{\n\t\treturn TRANSFER_ENGINEER;\n\t}\n\treturn TRANSFER_ITEM;\n}\n\n/**\n * Advances the transfer and takes care of\n * the delivery once it's arrived.\n * @param base Pointer to destination base.\n */\nvoid Transfer::advance(Base *base)\n{\n\t_hours--;\n\tif (_hours <= 0)\n\t{\n\t\tif (_soldier != 0)\n\t\t{\n\t\t\tbase->getSoldiers()->push_back(_soldier);\n\t\t}\n\t\telse if (_craft != 0)\n\t\t{\n\t\t\tbase->getCrafts()->push_back(_craft);\n\t\t\t_craft->setBase(base);\n\t\t\t_craft->checkup();\n\t\t}\n\t\telse if (_itemQty != 0)\n\t\t{\n\t\t\tbase->getStorageItems()->addItem(_itemId, _itemQty);\n\t\t}\n\t\telse if (_scientists != 0)\n\t\t{\n\t\t\tbase->setScientists(base->getScientists() + _scientists);\n\t\t}\n\t\telse if (_engineers != 0)\n\t\t{\n\t\t\tbase->setEngineers(base->getEngineers() + _engineers);\n\t\t}\n\t\t_delivered = true;\n\t}\n}\n\n/**\n * Get a pointer to the soldier being transferred.\n * @return a pointer to the soldier being moved.\n */\nSoldier *Transfer::getSoldier()\n{\n\treturn _soldier;\n}\n\n}\n"
  },
  {
    "path": "src/Savegame/Transfer.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include \"../Engine/Yaml.h\"\n\nnamespace OpenXcom\n{\n\nenum class TransferSortDirection : int\n{\n\tBY_LIST_ORDER,\n\tBY_UNIT_SIZE,\n\tBY_TOTAL_SIZE,\n\tBY_UNIT_COST,\n\tBY_TOTAL_COST\n};\n\nenum TransferType { TRANSFER_ITEM, TRANSFER_CRAFT, TRANSFER_SOLDIER, TRANSFER_SCIENTIST, TRANSFER_ENGINEER };\n\nstruct TransferRow\n{\n\tTransferType type;\n\tconst void *rule;\n\tstd::string name;\n\tint cost;\n\tint qtySrc, qtyDst;\n\tint amount;\n\tint listOrder;\n\tdouble size, totalSize;\n\tint64_t totalCost;\n};\n\nclass Soldier;\nclass Craft;\nclass Language;\nclass Base;\nclass Mod;\nclass RuleItem;\nclass SavedGame;\n\n/**\n * Represents an item transfer.\n * Items are placed \"in transit\" whenever they are\n * purchased or transferred between bases.\n */\nclass Transfer\n{\nprivate:\n\tint _hours;\n\tSoldier *_soldier;\n\tCraft *_craft;\n\tconst RuleItem* _itemId;\n\tint _itemQty, _scientists, _engineers;\n\tbool _delivered;\npublic:\n\t/// Creates a new transfer.\n\tTransfer(int hours);\n\t/// Cleans up the transfer.\n\t~Transfer();\n\t/// Loads the transfer from YAML.\n\tbool load(const YAML::YamlNodeReader& reader, Base *base, const Mod *mod, SavedGame *save);\n\t/// Saves the transfer to YAML.\n\tvoid save(YAML::YamlNodeWriter writer, const Base *b, const Mod *mod) const;\n\t/// Sets the soldier of the transfer.\n\tvoid setSoldier(Soldier *soldier);\n\t/// Sets the craft of the transfer.\n\tvoid setCraft(Craft *craft);\n\t/// Gets the craft of the transfer.\n\tCraft *getCraft();\n\t/// Gets the items of the transfer.\n\tconst RuleItem* getItems() const;\n\t/// Sets the items of the transfer.\n\tvoid setItems(const RuleItem* rule, int qty = 1);\n\t/// Sets the scientists of the transfer.\n\tvoid setScientists(int scientists);\n\t/// Sets the engineers of the transfer.\n\tvoid setEngineers(int engineers);\n\t/// Gets the name of the transfer.\n\tstd::string getName(Language *lang) const;\n\t/// Gets the hours remaining of the transfer.\n\tint getHours() const;\n\t/// Gets the quantity of the transfer.\n\tint getQuantity() const;\n\t/// Gets the type of the transfer.\n\tTransferType getType() const;\n\t/// Advances the transfer.\n\tvoid advance(Base *base);\n\t/// Get a pointer to the soldier being transferred.\n\tSoldier *getSoldier();\n\n};\n\n}\n"
  },
  {
    "path": "src/Savegame/Ufo.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Ufo.h\"\n#include <assert.h>\n#include <algorithm>\n#include <functional>\n#include \"../fmath.h\"\n#include \"Craft.h\"\n#include \"AlienMission.h\"\n#include \"../Engine/Exception.h\"\n#include \"../Engine/Language.h\"\n#include \"../Engine/RNG.h\"\n#include \"../Engine/ScriptBind.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleUfo.h\"\n#include \"../Mod/UfoTrajectory.h\"\n#include \"../Mod/RuleAlienMission.h\"\n#include \"Base.h\"\n#include \"SavedGame.h\"\n#include \"Waypoint.h\"\n\nnamespace OpenXcom\n{\n\nconst char *Ufo::ALTITUDE_STRING[] = {\n\t\"STR_GROUND\",\n\t\"STR_VERY_LOW\",\n\t\"STR_LOW_UC\",\n\t\"STR_HIGH_UC\",\n\t\"STR_VERY_HIGH\"\n};\n\n/**\n * Initializes a UFO of the specified type.\n * @param rules Pointer to ruleset.\n * @param uniqueId unique ID to assign to the UFO (0 to not assign).\n */\nUfo::Ufo(const RuleUfo *rules, int uniqueId, int hunterKillerPercentage, int huntMode, int huntBehavior) : MovingTarget(),\n\t_rules(rules), _missionWaveNumber(-1), _crashId(0), _landId(0), _damage(0), _direction(\"STR_NORTH\"),\n\t_altitude(\"STR_HIGH_UC\"), _status(FLYING), _secondsRemaining(0),\n\t_inBattlescape(false), _mission(0), _trajectory(0),\n\t_trajectoryPoint(0), _detected(false), _hyperDetected(false), _processedIntercept(false),\n\t_shootingAt(0), _hitFrame(0), _fireCountdown(0), _escapeCountdown(0), _stats(), _shield(-1), _shieldRechargeHandle(0),\n\t_tractorBeamSlowdown(0), _isHunterKiller(false), _isEscort(false), _huntMode(0), _huntBehavior(0),\n\t_isHunting(false), _isEscorting(false), _softlockShotCounter(0), _origWaypoint(0)\n{\n\t_stats = rules->getStats();\n\tif (uniqueId != 0)\n\t{\n\t\t_uniqueId = uniqueId;\n\t}\n\tif (hunterKillerPercentage > 0)\n\t{\n\t\t_isHunterKiller = RNG::percent(hunterKillerPercentage);\n\t\tif (_isHunterKiller)\n\t\t{\n\t\t\t_huntMode = huntMode > 1 ? RNG::generate(0, 1) : huntMode;\n\t\t\t_huntBehavior = huntBehavior > 1 ? RNG::generate(0, 1) : huntBehavior;\n\t\t}\n\t}\n}\n\n/**\n * Make sure our mission forget's us, and we only delete targets we own (waypoints).\n *\n */\nUfo::~Ufo()\n{\n\tif (_mission)\n\t{\n\t\t_mission->decreaseLiveUfos();\n\t}\n\n\tresetOriginalDestination(false);\n\n\tif (_dest)\n\t{\n\t\tWaypoint *wp = dynamic_cast<Waypoint*>(_dest);\n\t\tif (wp != 0)\n\t\t{\n\t\t\tdelete _dest;\n\t\t\t_dest = 0;\n\t\t}\n\t}\n}\n\n/**\n * Loads the UFO from a YAML file.\n * @param node YAML node.\n * @param mod The game mod. Use to access the trajectory rules.\n * @param game The game data. Used to find the UFO's mission.\n */\nvoid Ufo::load(const YAML::YamlNodeReader& node, const ScriptGlobal *shared, const Mod &mod, SavedGame &game)\n{\n\tconst auto& reader = node.useIndex();\n\tMovingTarget::load(reader);\n\treader.tryRead(\"uniqueId\", _uniqueId);\n\treader.tryRead(\"missionWaveNumber\", _missionWaveNumber);\n\treader.tryRead(\"crashId\", _crashId);\n\treader.tryRead(\"landId\", _landId);\n\treader.tryRead(\"damage\", _damage);\n\treader.tryRead(\"shield\", _shield);\n\treader.tryRead(\"shieldRechargeHandle\", _shieldRechargeHandle);\n\treader.tryRead(\"altitude\", _altitude);\n\treader.tryRead(\"direction\", _direction);\n\treader.tryRead(\"detected\", _detected);\n\treader.tryRead(\"hyperDetected\", _hyperDetected);\n\treader.tryRead(\"secondsRemaining\", _secondsRemaining);\n\treader.tryRead(\"inBattlescape\", _inBattlescape);\n\t_dest = new Waypoint();\n\t_dest->setLongitude(reader[\"dest\"][\"lon\"].readVal(_lon));\n\t_dest->setLatitude(reader[\"dest\"][\"lat\"].readVal(_lat));\n\treader.tryRead(\"status\", _status);\n\tif (game.getMonthsPassed() != -1)\n\t{\n\t\tint missionID = reader[\"mission\"].readVal<int>();\n\t\tAlienMission* found = nullptr;\n\t\tfor (auto* am : game.getAlienMissions())\n\t\t{\n\t\t\tif (am->getId() == missionID)\n\t\t\t{\n\t\t\t\tfound = am;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (!found)\n\t\t{\n\t\t\t// Corrupt save file.\n\t\t\tthrow Exception(\"Unknown UFO mission, save file is corrupt.\");\n\t\t}\n\t\t_mission = found;\n\t\t_stats += _rules->getRaceBonus(_mission->getRace());\n\n\t\tstd::string tid = reader[\"trajectory\"].readVal<std::string>();\n\t\t_trajectory = mod.getUfoTrajectory(tid);\n\t\tif (_trajectory == 0)\n\t\t{\n\t\t\t// Corrupt save file.\n\t\t\tthrow Exception(\"Unknown UFO trajectory, save file is corrupt.\");\n\t\t}\n\t\treader.tryRead(\"trajectoryPoint\", _trajectoryPoint);\n\t}\n\treader.tryRead(\"fireCountdown\", _fireCountdown);\n\treader.tryRead(\"escapeCountdown\", _escapeCountdown);\n\tif (_inBattlescape)\n\t\tsetSpeed(0);\n\n\t_scriptValues.load(reader, shared);\n}\n\n/**\n * Finishes loading the UFO from YAML (called after XCOM craft and other UFOs are loaded).\n * @param node YAML node.\n * @param save The game data. Used to find the UFO's target (= XCOM craft or another UFO).\n */\nvoid Ufo::finishLoading(const YAML::YamlNodeReader& reader, SavedGame &save)\n{\n\treader.tryRead(\"isHunterKiller\", _isHunterKiller);\n\treader.tryRead(\"isEscort\", _isEscort);\n\treader.tryRead(\"huntMode\", _huntMode);\n\treader.tryRead(\"huntBehavior\", _huntBehavior);\n\treader.tryRead(\"isHunting\", _isHunting);\n\treader.tryRead(\"isEscorting\", _isEscorting);\n\treader.tryRead(\"softlockShotCounter\", _softlockShotCounter);\n\n\tif (_isHunting)\n\t{\n\t\tif (const auto& dest = reader[\"dest\"])\n\t\t{\n\t\t\tstd::string type = dest[\"type\"].readVal<std::string>();\n\t\t\tint id = dest[\"id\"].readVal<int>();\n\t\t\tbool found = false;\n\t\t\tfor (auto* xbase : *save.getBases())\n\t\t\t{\n\t\t\t\tfor (auto* xcraft : *xbase->getCrafts())\n\t\t\t\t{\n\t\t\t\t\tif (xcraft->getId() == id && xcraft->getRules()->getType() == type)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (_dest)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// this is just a dummy waypoint created during normal loading, not a craft... yet\n\t\t\t\t\t\t\tdelete _dest;\n\t\t\t\t\t\t\t_dest = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tsetDestination(xcraft);\n\t\t\t\t\t\tfound = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (found) break;\n\t\t\t}\n\t\t}\n\t}\n\telse if (_isEscorting)\n\t{\n\t\tif (const auto& dest = reader[\"dest\"])\n\t\t{\n\t\t\tstd::string type = dest[\"type\"].readVal<std::string>();\n\t\t\tif (type == \"STR_UFO\")\n\t\t\t{\n\t\t\t\tint uniqueUfoId = dest[\"uniqueId\"].readVal(0);\n\t\t\t\tif (uniqueUfoId > 0)\n\t\t\t\t{\n\t\t\t\t\tfor (auto* ufo : *save.getUfos())\n\t\t\t\t\t{\n\t\t\t\t\t\tif (ufo->getUniqueId() == uniqueUfoId)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (_dest)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// this is just a dummy waypoint created during normal loading, not a UFO... yet\n\t\t\t\t\t\t\t\tdelete _dest;\n\t\t\t\t\t\t\t\t_dest = 0;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tsetDestination(ufo);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t//if (_isHunting || _isEscorting)\n\t{\n\t\tif (const auto& origWaypoint = reader[\"origWaypoint\"])\n\t\t{\n\t\t\t_origWaypoint = new Waypoint();\n\t\t\t_origWaypoint->setLongitude(origWaypoint[\"lon\"].readVal<double>());\n\t\t\t_origWaypoint->setLatitude(origWaypoint[\"lat\"].readVal<double>());\n\t\t}\n\t}\n}\n\n/**\n * Saves the UFO to a YAML file.\n * @return YAML node.\n */\nvoid Ufo::save(YAML::YamlNodeWriter writer, const ScriptGlobal *shared, bool newBattle) const\n{\n\twriter.setAsMap();\n\tMovingTarget::save(writer);\n\twriter.write(\"type\", _rules->getType());\n\twriter.write(\"uniqueId\", _uniqueId);\n\twriter.write(\"missionWaveNumber\", _missionWaveNumber);\n\tif (_crashId)\n\t\twriter.write(\"crashId\", _crashId);\n\telse if (_landId)\n\t\twriter.write(\"landId\", _landId);\n\twriter.write(\"damage\", _damage);\n\twriter.write(\"shield\", _shield);\n\twriter.write(\"shieldRechargeHandle\", _shieldRechargeHandle);\n\twriter.write(\"altitude\", _altitude);\n\twriter.write(\"direction\", _direction);\n\twriter.write(\"status\", _status);\n\tif (_detected)\n\t\twriter.write(\"detected\", _detected);\n\tif (_hyperDetected)\n\t\twriter.write(\"hyperDetected\", _hyperDetected);\n\tif (_secondsRemaining)\n\t\twriter.write(\"secondsRemaining\", _secondsRemaining);\n\tif (_inBattlescape)\n\t\twriter.write(\"inBattlescape\", _inBattlescape);\n\tif (_isHunterKiller)\n\t\twriter.write(\"isHunterKiller\", _isHunterKiller);\n\tif (_isEscort)\n\t\twriter.write(\"isEscort\", _isEscort);\n\twriter.write(\"huntMode\", _huntMode);\n\twriter.write(\"huntBehavior\", _huntBehavior);\n\tif (_isHunting)\n\t\twriter.write(\"isHunting\", _isHunting);\n\tif (_isEscorting)\n\t\twriter.write(\"isEscorting\", _isEscorting);\n\tif (_softlockShotCounter)\n\t\twriter.write(\"softlockShotCounter\", _softlockShotCounter);\n\tif (_origWaypoint)\n\t\t_origWaypoint->save(writer[\"origWaypoint\"]);\n\tif (!newBattle)\n\t{\n\t\twriter.write(\"mission\", _mission->getId());\n\t\twriter.write(\"trajectory\", _trajectory->getID());\n\t\twriter.write(\"trajectoryPoint\", _trajectoryPoint);\n\t}\n\n\twriter.write(\"fireCountdown\", _fireCountdown);\n\twriter.write(\"escapeCountdown\", _escapeCountdown);\n\n\t_scriptValues.save(writer, shared);\n}\n\n/**\n * Saves the UFO's unique identifiers to a YAML file.\n * @return YAML node.\n */\nvoid Ufo::saveId(YAML::YamlNodeWriter writer) const\n{\n\twriter.setAsMap();\n\tMovingTarget::saveId(writer);\n\t// this is needed, because _id is NOT unique until the UFO is detected\n\t// and UFOs can be referenced by other entities even before they are detected\n\t// (e.g. when they escort other UFOs)\n\twriter.write(\"uniqueId\", _uniqueId);\n}\n\n/**\n * Returns the UFO's unique type used for\n * savegame purposes.\n * @return ID.\n */\nstd::string Ufo::getType() const\n{\n\treturn \"STR_UFO\";\n}\n\n/**\n * Returns the ruleset for the UFO's type.\n * @return Pointer to ruleset.\n */\nconst RuleUfo *Ufo::getRules() const\n{\n\treturn _rules;\n}\n\n/**\n * Changes the ruleset for the UFO's type.\n * @param rules Pointer to ruleset.\n * @warning ONLY FOR NEW BATTLE USE!\n */\nvoid Ufo::changeRules(const RuleUfo *rules)\n{\n\t_rules = rules;\n}\n\n/**\n * Returns the UFO's unique ID.\n * @return Unique ID.\n */\nint Ufo::getUniqueId() const\n{\n\treturn _uniqueId;\n}\n\n/**\n * Returns the UFO's unique default name.\n * @param lang Language to get strings from.\n * @return Full name.\n */\nstd::string Ufo::getDefaultName(Language *lang) const\n{\n\tswitch (_status)\n\t{\n\tcase LANDED:\n\t\treturn lang->getString(getMarkerName()).arg(_landId);\n\tcase CRASHED:\n\t\treturn lang->getString(getMarkerName()).arg(_crashId);\n\tdefault:\n\t\treturn lang->getString(getMarkerName()).arg(_id);\n\t}\n}\n\n/**\n * Returns the name on the globe for the UFO.\n * @return String ID.\n */\nstd::string Ufo::getMarkerName() const\n{\n\tswitch (_status)\n\t{\n\tcase LANDED:\n\t\treturn \"STR_LANDING_SITE_\";\n\tcase CRASHED:\n\t\treturn \"STR_CRASH_SITE_\";\n\tdefault:\n\t\treturn \"STR_UFO_\";\n\t}\n}\n\n/**\n * Returns the marker ID on the globe for the UFO.\n * @return Marker ID.\n */\nint Ufo::getMarkerId() const\n{\n\tswitch (_status)\n\t{\n\tcase LANDED:\n\t\treturn _landId;\n\tcase CRASHED:\n\t\treturn _crashId;\n\tdefault:\n\t\treturn _id;\n\t}\n}\n\n/**\n * Returns the globe marker for the UFO.\n * @return Marker sprite, -1 if none.\n */\nint Ufo::getMarker() const\n{\n\tif (!_detected)\n\t\treturn -1;\n\tswitch (_status)\n\t{\n\tcase LANDED:\n\t\treturn _rules->getLandMarker() == -1 ? 3 : _rules->getLandMarker();\n\tcase CRASHED:\n\t\treturn _rules->getCrashMarker() == -1 ? 4 : _rules->getCrashMarker();\n\tdefault:\n\t\treturn _rules->getMarker() == -1 ? 2 : _rules->getMarker();\n\t}\n}\n\n/**\n * Returns the amount of damage this UFO has taken.\n * @return Amount of damage.\n */\nint Ufo::getDamage() const\n{\n\treturn _damage;\n}\n\n/**\n * Changes the amount of damage this UFO has taken.\n * @param damage Amount of damage.\n */\nvoid Ufo::setDamage(int damage, const Mod *mod)\n{\n\t_damage = damage;\n\tif (_damage < 0)\n\t{\n\t\t_damage = 0;\n\t}\n\tif (isDestroyed())\n\t{\n\t\t_status = DESTROYED;\n\t}\n\telse if (isCrashed())\n\t{\n\t\t_status = CRASHED;\n\t}\n\tif (_status == CRASHED || _status == DESTROYED)\n\t{\n\t\tint waveNumber = _missionWaveNumber;\n\n\t\t// special case for retaliation UFO attacking the base\n\t\tconst RuleUfo *battleshipRule = mod->getUfo(_mission->getRules().getSpawnUfo(), true);\n\t\tconst UfoTrajectory *assaultTrajectory = mod->getUfoTrajectory(UfoTrajectory::RETALIATION_ASSAULT_RUN, true);\n\t\tif (_rules == battleshipRule && _trajectory == assaultTrajectory)\n\t\t{\n\t\t\twaveNumber = _mission->getRules().getWaveCount() - 1; // last wave\n\t\t}\n\n\t\t// backwards save compatibility\n\t\tif (waveNumber > -1)\n\t\t{\n\t\t\tconst MissionWave &wave = _mission->getRules().getWave(waveNumber);\n\t\t\tif (wave.interruptPercentage > 0)\n\t\t\t{\n\t\t\t\tif (RNG::percent(wave.interruptPercentage))\n\t\t\t\t{\n\t\t\t\t\t_mission->setInterrupted(true);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Returns the ratio between the amount of damage this\n * ufo can take and the total it can take before it's\n * destroyed.\n * @return Percentage of damage.\n */\nint Ufo::getDamagePercentage() const\n{\n\treturn (int)floor((double)_damage / _stats.damageMax * 100);\n}\n\n/**\n * Returns whether this UFO has been detected by radars.\n * @return Detection status.\n */\nbool Ufo::getDetected() const\n{\n\treturn _detected;\n}\n\n/**\n * Changes whether this UFO has been detected by radars.\n * @param detected Detection status.\n */\nvoid Ufo::setDetected(bool detected)\n{\n\t_detected = detected;\n}\n\n/**\n * Returns the amount of remaining seconds the UFO has left on the ground.\n * After this many seconds the UFO will take off, if landed, or disappear, if\n * crashed.\n * @return Amount of seconds.\n */\nsize_t Ufo::getSecondsRemaining() const\n{\n\treturn _secondsRemaining;\n}\n\n/**\n * Changes the amount of remaining seconds the UFO has left on the ground.\n * After this many seconds the UFO will take off, if landed, or disappear, if\n * crashed.\n * @param seconds Amount of seconds.\n */\nvoid Ufo::setSecondsRemaining(size_t seconds)\n{\n\t_secondsRemaining = seconds;\n}\n\n/**\n * Returns the current direction the UFO is heading in.\n * @return Direction.\n */\nstd::string Ufo::getDirection() const\n{\n\treturn _direction;\n}\n\n/**\n * Returns the current altitude of the UFO.\n * @return Altitude as string ID.\n */\nstd::string Ufo::getAltitude() const\n{\n\treturn _altitude;\n}\n\n/**\n * Returns the current altitude of the UFO.\n * @return Altitude as integer (0-4).\n */\nint Ufo::getAltitudeInt() const\n{\n\tfor (size_t i = 0; i < 5; ++i)\n\t{\n\t\tif (ALTITUDE_STRING[i] == _altitude)\n\t\t{\n\t\t\treturn i;\n\t\t}\n\t}\n\treturn -1;\n}\n\n/**\n * Changes the current altitude of the UFO.\n * @param altitude Altitude.\n */\nvoid Ufo::setAltitude(const std::string &altitude)\n{\n\t_altitude = altitude;\n\tif (_altitude != \"STR_GROUND\")\n\t{\n\t\t_status = FLYING;\n\t}\n\telse\n\t{\n\t\t_status = isCrashed() ? CRASHED : LANDED;\n\t}\n}\n\n/**\n * Returns if this UFO took enough damage\n * to cause it to crash.\n * @return Crashed status.\n */\nbool Ufo::isCrashed() const\n{\n\t// Note: yes, this condition is necessary (in OXCE) and cannot be removed!\n\tif (isDestroyed())\n\t\treturn true;\n\n\tif (_huntBehavior == 1 || _rules->isUnmanned())\n\t{\n\t\t// kamikaze never crash lands; unmanned ditto\n\t\treturn false;\n\t}\n\n\treturn (_damage > _stats.damageMax / 2);\n}\n\n/**\n * Returns if this UFO took enough damage\n * to cause it to crash.\n * @return Crashed status.\n */\nbool Ufo::isDestroyed() const\n{\n\treturn (_damage >= _stats.damageMax);\n}\n\n/**\n * Calculates the direction for the UFO based\n * on the current raw speed and destination.\n */\nvoid Ufo::calculateSpeed()\n{\n\tMovingTarget::calculateSpeed();\n\n\tdouble x = _speedLon;\n\tdouble y = -_speedLat;\n\n\t// This section guards vs. divide-by-zero.\n\tif (AreSame(x, 0.0) || AreSame(y, 0.0))\n\t{\n\t\tif (AreSame(x, 0.0) && AreSame(y, 0.0))\n\t\t{\n\t\t\t_direction = \"STR_NONE_UC\";\n\t\t}\n\t\telse if (AreSame(x, 0.0))\n\t\t{\n\t\t\tif (y > 0.f)\n\t\t\t{\n\t\t\t\t_direction = \"STR_NORTH\";\n\t\t\t}\n\t\t\telse if (y < 0.f)\n\t\t\t{\n\t\t\t\t_direction = \"STR_SOUTH\";\n\t\t\t}\n\t\t}\n\t\telse if (AreSame(y, 0.0))\n\t\t{\n\t\t\tif (x > 0.f)\n\t\t\t{\n\t\t\t\t_direction = \"STR_EAST\";\n\t\t\t}\n\t\t\telse if (x < 0.f)\n\t\t\t{\n\t\t\t\t_direction = \"STR_WEST\";\n\t\t\t}\n\t\t}\n\n\t\treturn;\n\t}\n\n\tdouble theta = atan2(y, x); // radians\n\ttheta = theta * 180.f / M_PI; // +/- 180 deg.\n\n\tif (22.5f > theta && theta > -22.5f)\n\t{\n\t\t_direction = \"STR_EAST\";\n\t}\n\telse if (-22.5f > theta && theta > -67.5f)\n\t{\n\t\t_direction = \"STR_SOUTH_EAST\";\n\t}\n\telse if (-67.5f > theta && theta > -112.5f)\n\t{\n\t\t_direction = \"STR_SOUTH\";\n\t}\n\telse if (-112.5f > theta && theta > -157.5f)\n\t{\n\t\t_direction = \"STR_SOUTH_WEST\";\n\t}\n\telse if (-157.5f > theta || theta > 157.5f)\n\t{\n\t\t_direction = \"STR_WEST\";\n\t}\n\telse if (157.5f > theta && theta > 112.5f)\n\t{\n\t\t_direction = \"STR_NORTH_WEST\";\n\t}\n\telse if (112.5f > theta && theta > 67.5f)\n\t{\n\t\t_direction = \"STR_NORTH\";\n\t}\n\telse\n\t{\n\t\t_direction = \"STR_NORTH_EAST\";\n\t}\n}\n\n/**\n * Moves the UFO to its destination.\n */\nvoid Ufo::think()\n{\n\tswitch (_status)\n\t{\n\tcase FLYING:\n\t\tmove();\n\t\tif (reachedDestination() && !isHunting() && !isEscorting())\n\t\t{\n\t\t\t// Prevent further movement.\n\t\t\tsetSpeed(0);\n\t\t}\n\t\tbreak;\n\tcase LANDED:\n\t\tassert(_secondsRemaining >= 5 && \"Wrong time management.\");\n\t\t_secondsRemaining -= 5;\n\t\tbreak;\n\tcase CRASHED:\n\t\tif (!_detected)\n\t\t{\n\t\t\t_detected = true;\n\t\t}\n\t\t// This gets handled in GeoscapeState::time30Minutes()\n\t\t// Because the original game processes it every 30 minutes!\n\tcase DESTROYED:\n\tcase IGNORE_ME:\n\t\t// Do nothing\n\t\tbreak;\n\t}\n}\n\n/**\n * Gets the UFO's battlescape status.\n * @return Is the UFO currently in battle?\n */\nbool Ufo::isInBattlescape() const\n{\n\treturn _inBattlescape;\n}\n\n/**\n * Sets the UFO's battlescape status.\n * @param inbattle True if it's in battle, False otherwise.\n */\nvoid Ufo::setInBattlescape(bool inbattle)\n{\n\tif (inbattle)\n\t\tsetSpeed(0);\n\t_inBattlescape = inbattle;\n}\n\n/**\n * Returns the alien race currently residing in the UFO.\n * @return Alien race.\n */\nconst std::string &Ufo::getAlienRace() const\n{\n\treturn _mission->getRace();\n}\n\nvoid Ufo::setShotDownByCraftId(const CraftId& craft)\n{\n\t_shotDownByCraftId = craft;\n}\n\nCraftId Ufo::getShotDownByCraftId() const\n{\n\treturn _shotDownByCraftId;\n}\n\n/**\n * Returns a UFO's visibility to radar detection.\n * The UFO's size and altitude affect the chances\n * of it being detected by radars.\n * @return Visibility modifier.\n */\nint Ufo::getVisibility() const\n{\n\tint size = _rules->getDefaultVisibility();\n\n\tint visibility = 0;\n\tif (_altitude == \"STR_GROUND\")\n\t\tvisibility = -30;\n\telse if (_altitude == \"STR_VERY_LOW\")\n\t\tvisibility = size - 20;\n\telse if (_altitude == \"STR_LOW_UC\")\n\t\tvisibility = size - 10;\n\telse if (_altitude == \"STR_HIGH_UC\")\n\t\tvisibility = size;\n\telse if (_altitude == \"STR_VERY_HIGH\")\n\t\tvisibility = size - 10;\n\n\treturn visibility;\n}\n\n\n/**\n * Returns the Mission type of the UFO.\n * @return Mission.\n */\nconst std::string &Ufo::getMissionType() const\n{\n\treturn _mission->getRules().getType();\n}\n\n/**\n * Sets the mission information of the UFO.\n * The UFO will start at the first point of the trajectory. The actual UFO\n * information is not changed here, this only sets the information kept on\n * behalf of the mission.\n * @param mission Pointer to the actual mission object.\n * @param trajectory Pointer to the actual mission trajectory.\n */\nvoid Ufo::setMissionInfo(AlienMission *mission, const UfoTrajectory *trajectory)\n{\n\tassert(!_mission && mission && trajectory);\n\t_mission = mission;\n\t_mission->increaseLiveUfos();\n\t_trajectoryPoint = 0;\n\t_trajectory = trajectory;\n\t_stats += _rules->getRaceBonus(_mission->getRace());\n}\n\n/**\n * Returns whether this UFO has been detected by hyper-wave.\n * @return Detection status.\n */\nbool Ufo::getHyperDetected() const\n{\n\treturn _hyperDetected;\n}\n\n/**\n * Changes whether this UFO has been detected by hyper-wave.\n * @param hyperdetected Detection status.\n */\nvoid Ufo::setHyperDetected(bool hyperdetected)\n{\n\t_hyperDetected = hyperdetected;\n}\n\n/**\n * Gets the Xcom craft targeted by this UFO.\n * @return Pointer to Xcom craft.\n */\nCraft *Ufo::getTargetedXcomCraft() const\n{\n\tCraft *craft = dynamic_cast<Craft*>(_dest);\n\treturn craft;\n}\n\n/**\n * Resets the original destination if targeting the given craft.\n * @param dest Pointer to Xcom craft.\n */\nvoid Ufo::resetOriginalDestination(Craft *target)\n{\n\tif (target == getTargetedXcomCraft())\n\t{\n\t\tresetOriginalDestination(true);\n\t}\n}\n\n/**\n * Resets the original destination.\n */\nvoid Ufo::resetOriginalDestination(bool debugHelper)\n{\n\tif (_origWaypoint)\n\t{\n\t\tWaypoint *wp = new Waypoint();\n\t\twp->setLatitude(_origWaypoint->getLatitude());\n\t\twp->setLongitude(_origWaypoint->getLongitude());\n\n\t\tsetDestination(wp); // hunting and escorting flags will be reset too\n\n\t\tdelete _origWaypoint;\n\t\t_origWaypoint = 0;\n\t}\n\telse if (debugHelper)\n\t{\n\t\tthrow Exception(\"Corrupt state: Unknown original UFO destination.\");\n\t}\n}\n\n/**\n * Sets the Xcom craft targeted by this UFO.\n * @param dest Pointer to Xcom craft.\n */\nvoid Ufo::setTargetedXcomCraft(Craft *craft)\n{\n\tif (craft)\n\t{\n\t\tbackupOriginalDestination();\n\t\tsetDestination(craft);\n\t\t_isHunting = true; // must be after setDestination()\n\n\t\t// go hunt your target as quickly as you can\n\t\tif (_rules->getHuntSpeed() > 0)\n\t\t{\n\t\t\tsetSpeed(_stats.speedMax * _rules->getHuntSpeed() / 100);\n\t\t}\n\t}\n}\n\n/**\n * Sets the UFO escorted by this UFO.\n * @param ufo Pointer to escorted UFO.\n */\nvoid Ufo::setEscortedUfo(Ufo *ufo)\n{\n\tif (ufo)\n\t{\n\t\tbackupOriginalDestination();\n\t\tsetDestination(ufo);\n\t\t_isEscorting = true; // must be after setDestination()\n\n\t\t// go protect your target as quickly as you can\n\t\tsetSpeed(_stats.speedMax);\n\t}\n}\n\n/**\n * Backs up the original destination.\n */\nvoid Ufo::backupOriginalDestination()\n{\n\t// if we're not hunting or escorting yet, remember the original destination waypoint\n\t// if we're already occupied, keep the original information\n\tif (!_isHunting && !_isEscorting)\n\t{\n\t\tif (_origWaypoint)\n\t\t{\n\t\t\tdelete _origWaypoint;\n\t\t\t_origWaypoint = 0;\n\t\t}\n\t\t_origWaypoint = new Waypoint();\n\t\t_origWaypoint->setLatitude(_dest->getLatitude());\n\t\t_origWaypoint->setLongitude(_dest->getLongitude());\n\t}\n}\n\n/**\n * Handle destination changes, making sure to delete old waypoint destinations.\n * @param dest Pointer to the new destination.\n */\nvoid Ufo::setDestination(Target *dest)\n{\n\tWaypoint *old = dynamic_cast<Waypoint*>(_dest);\n\tMovingTarget::setDestination(dest);\n\tif (old && !_isHunting && !_isEscorting)\n\t{\n\t\t// delete only waypoints, not xcom craft or other UFOs\n\t\tdelete old;\n\t}\n\t_isHunting = false;   // reset flag, will be set in setTargetedXcomCraft()\n\t_isEscorting = false; // reset flag, will be set in setEscortedUfo()\n}\n\n/**\n * Gets which interception window the UFO is active in.\n * @return which interception window the UFO is active in.\n */\nint Ufo::getShootingAt() const\n{\n\treturn _shootingAt;\n}\n\n/**\n * Sets which interception window the UFO is active in.\n * @param target the window the UFO is active in.\n */\nvoid Ufo::setShootingAt(int target)\n{\n\t_shootingAt = target;\n}\n\n/**\n * Gets the UFO's landing site ID.\n * @return landing site ID.\n */\nint Ufo::getLandId() const\n{\n\treturn _landId;\n}\n\n/**\n * Sets the UFO's landing site ID.\n * @param id landing site ID.\n */\nvoid Ufo::setLandId(int id)\n{\n\t_landId = id;\n}\n\n/**\n * Gets the UFO's crash site ID.\n * @return the UFO's crash site ID.\n */\nint Ufo::getCrashId() const\n{\n\treturn _crashId;\n}\n\n/**\n * Sets the UFO's crash site ID.\n * @param id the UFO's crash site ID.\n */\nvoid Ufo::setCrashId(int id)\n{\n\t_crashId = id;\n}\n\n/**\n * Sets the UFO's hit frame.\n * @param frame the hit frame.\n */\nvoid Ufo::setHitFrame(int frame)\n{\n\t_hitFrame = frame;\n}\n\n/**\n * Gets the UFO's hit frame.\n * @return the hit frame.\n */\nint Ufo::getHitFrame() const\n{\n\treturn _hitFrame;\n}\n\n/// Gets the UFO's stats.\nconst RuleUfoStats& Ufo::getCraftStats() const\n{\n\treturn _stats;\n}\n\n/**\n * Sets the countdown timer for escaping a dogfight.\n * @param time how many ticks until the ship attempts to escape.\n */\nvoid Ufo::setEscapeCountdown(int time)\n{\n\t_escapeCountdown = time;\n}\n\n/**\n * Gets the escape timer for dogfights.\n * @return how many ticks until the ship tries to leave.\n */\nint Ufo::getEscapeCountdown() const\n{\n\treturn _escapeCountdown;\n}\n\n/**\n * Sets the number of ticks until the ufo fires its weapon.\n * @param time number of ticks until refire.\n */\nvoid Ufo::setFireCountdown(int time)\n{\n\t_fireCountdown = time;\n}\n\n/**\n * Gets the number of ticks until the ufo is ready to fire.\n * @return ticks until weapon is ready.\n */\nint Ufo::getFireCountdown() const\n{\n\treturn _fireCountdown;\n}\n\n/**\n * Sets a flag denoting that this ufo has had its timers decremented.\n * prevents multiple interceptions from decrementing or resetting an already running timer.\n * this flag is reset in advance each time the geoscape processes the dogfights.\n * @param processed whether or not we've had our timers processed.\n */\nvoid Ufo::setInterceptionProcessed(bool processed)\n{\n\t_processedIntercept = processed;\n}\n\n/**\n * Gets if the ufo has had its timers decremented on this cycle of interception updates.\n * @return if this ufo has already been processed.\n */\nbool Ufo::getInterceptionProcessed() const\n{\n\treturn _processedIntercept;\n}\n\n/**\n * Gets the UFO's shield level\n * @return the points of shield remaining\n */\nint Ufo::getShield() const\n{\n\treturn _shield;\n}\n\n/**\n * Sets the UFO's shield level\n * @param the shield point value to set\n */\nvoid Ufo::setShield(int shield)\n{\n\t_shield = std::max(0, std::min(_stats.shieldCapacity, shield));\n}\n\n/**\n * Sets which _interceptionNumber handles the UFO's shield recharge in a dogfight\n * @param the _interceptionNumber to set\n */\nvoid Ufo::setShieldRechargeHandle(int shieldRechargeHandle)\n{\n\t_shieldRechargeHandle = shieldRechargeHandle;\n}\n\n/**\n * Gets which _interceptionNumber handles the UFO's shield recharge in a dogfight\n * @return the _interceptionNumber to handle shield recharge\n */\nint Ufo::getShieldRechargeHandle() const\n{\n\treturn _shieldRechargeHandle;\n}\n\n/**\n * Gets the percent shield remaining\n */\nint Ufo::getShieldPercentage() const\n{\n\treturn _stats.shieldCapacity != 0 ? _shield * 100 / _stats.shieldCapacity : 0;\n}\n\n/**\n * Sets how much this UFO is being slowed down by craft tractor beams\n * @param the _tractorBeamSlowdown to set\n */\nvoid Ufo::setTractorBeamSlowdown(int tractorBeamSlowdown)\n{\n\t_tractorBeamSlowdown = std::max(0, std::min(_stats.speedMax, tractorBeamSlowdown));\n}\n\n/**\n * Gets how much this UFO is being slowed down by craft tractor beams\n * @return the tractor beam slowdown\n */\nint Ufo::getTractorBeamSlowdown() const\n{\n\treturn _tractorBeamSlowdown;\n}\n\n/**\n * Is this UFO a hunter-killer?\n * @return True if UFO is a hunter-killer.\n */\nbool Ufo::isHunterKiller() const\n{\n\treturn _isHunterKiller;\n}\n\n/**\n * Sets if the UFO is a hunter-killer.\n * @param isHunterKiller new value to set\n */\nvoid Ufo::setHunterKiller(bool isHunterKiller)\n{\n\t_isHunterKiller = isHunterKiller;\n}\n\n/**\n* Is this UFO an escort?\n* @return True if UFO is an escort.\n*/\nbool Ufo::isEscort() const\n{\n\treturn _isEscort;\n}\n\n/**\n* Sets if the UFO is an escort.\n* @param isEscort new value to set\n*/\nvoid Ufo::setEscort(bool isEscort)\n{\n\t_isEscort = isEscort;\n}\n\n/**\n * Gets the UFO's hunting preferences.\n * @return Hunt mode ID.\n */\nint Ufo::getHuntMode() const\n{\n\treturn _huntMode;\n}\n\n/**\n * Gets the UFO's hunting behavior.\n * @return Hunt behavior ID.\n */\nint Ufo::getHuntBehavior() const\n{\n\treturn _huntBehavior;\n}\n\n/**\n * Is this UFO actively hunting right now?\n * @return True if UFO is actively hunting.\n */\nbool Ufo::isHunting() const\n{\n\treturn _isHunting;\n}\n\n/**\n * Is this UFO escorting other UFO right now?\n * @return True if UFO is escorting.\n */\nbool Ufo::isEscorting() const\n{\n\treturn _isEscorting;\n}\n\n/**\n * Returns if a certain target is inside the UFO's\n * radar range, taking in account the positions of both.\n * @param target Pointer to target to compare.\n * @return True if inside radar range.\n */\nbool Ufo::insideRadarRange(Target *target) const\n{\n\tif (_stats.radarRange == 0)\n\t\treturn false;\n\n\tdouble range = Nautical(_stats.radarRange);\n\treturn (getDistance(target) <= range);\n}\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tScript binding\n////////////////////////////////////////////////////////////\n\nnamespace\n{\n\nvoid getDamageMaxScript(const Ufo *u, int &ret)\n{\n\tif (u)\n\t{\n\t\tret = u->getCraftStats().damageMax;\n\t\treturn;\n\t}\n\tret = 0;\n}\n\nvoid getStatusScript(const Ufo *u, int &ret)\n{\n\tif (u)\n\t{\n\t\tret = (int)u->getStatus();\n\t\treturn;\n\t}\n\tret = 0;\n}\n\nstd::string debugDisplayScript(const Ufo* u)\n{\n\tif (u)\n\t{\n\t\tstd::string s;\n\t\ts += Ufo::ScriptName;\n\t\ts += \"(type: \\\"\";\n\t\ts += u->getRules()->getType();\n\t\ts += \"\\\" id: \";\n\t\ts += std::to_string(u->getId());\n\t\ts += \"\\\" damage: \";\n\t\ts += std::to_string(u->getDamagePercentage());\n\t\ts += \"%)\";\n\t\treturn s;\n\t}\n\telse\n\t{\n\t\treturn \"null\";\n\t}\n}\n\n} // namespace\n\n\n/**\n * Register Ufo in script parser.\n * @param parser Script parser.\n */\nvoid Ufo::ScriptRegister(ScriptParserBase* parser)\n{\n\tparser->registerPointerType<RuleUfo>();\n\n\tBind<Ufo> u = { parser };\n\n\tu.add<&Ufo::getAltitudeInt>(\"getAltitude\");\n\tu.add<&Ufo::getId>(\"getId\");\n\tu.add<&Ufo::getRules>(\"getRules\");\n\tu.add<&getStatusScript>(\"getStatus\");\n\tu.add<&Ufo::getVisibility>(\"getVisibility\");\n\n\tu.add<&Ufo::getDamage>(\"getDamage\");\n\tu.add<&getDamageMaxScript>(\"getDamageMax\");\n\tu.add<&Ufo::getDamagePercentage>(\"getDamagePercentage\");\n\n\tu.add<&Ufo::getShield>(\"getShield\");\n\tu.addField<&Ufo::_stats, &RuleUfoStats::getBase, &RuleCraftStats::shieldCapacity>(\"getShieldMax\");\n\tu.add<&Ufo::getShieldPercentage>(\"getShieldPercentage\");\n\n\tu.add<&Ufo::isHunterKiller>(\"isHunterKiller\");\n\tu.add<&Ufo::isHunting>(\"isHunting\");\n\tu.add<&Ufo::isEscorting>(\"isEscorting\");\n\tu.add<&Ufo::getHuntBehavior>(\"getHuntBehavior\");\n\tu.add<&Ufo::getHuntMode>(\"getHuntMode\");\n\n\tu.add<&Ufo::getDetected>(\"getDetected\");\n\tu.add<&Ufo::getHyperDetected>(\"getHyperDetected\");\n\n\tu.addRules<RuleUfo, &Ufo::getRules>(\"getRuleUfo\");\n\n\tRuleCraftStats::addGetStatsScript<&Ufo::_stats>(u, \"Stats.\");\n\n\tu.addScriptValue<BindBase::OnlyGet, &Ufo::_rules, &RuleUfo::getScriptValuesRaw>();\n\tu.addScriptValue<&Ufo::_scriptValues>();\n\tu.addDebugDisplay<&debugDisplayScript>();\n\n\tu.addCustomConst(\"UFO_FLYING\", FLYING);\n\tu.addCustomConst(\"UFO_LANDED\", LANDED);\n\tu.addCustomConst(\"UFO_CRASHED\", CRASHED);\n\tu.addCustomConst(\"UFO_DESTROYED\", DESTROYED);\n\tu.addCustomConst(\"UFO_IGNORE_ME\", IGNORE_ME);\n\n\tu.addCustomConst(\"DETECTION_NONE\", DETECTION_NONE);\n\tu.addCustomConst(\"DETECTION_RADAR\", DETECTION_RADAR);\n\tu.addCustomConst(\"DETECTION_HYPERWAVE\", DETECTION_HYPERWAVE);\n}\n\n\n\nModScript::DetectUfoFromBaseParser::DetectUfoFromBaseParser(ScriptGlobal* shared, const std::string& name, Mod* mod) : ScriptParserEvents{ shared, name,\n\t\"detection_type\",\n\t\"detection_chance\",\n\t\"ufo\", \"geoscape_game\",\n\t\"distance\", \"already_tracked\", \"radar_total_strength\", \"radar_max_distance\", \"hyperwave_total_strength\", \"hyperwave_max_distance\", }\n{\n\tBindBase b { this };\n\n\tb.addCustomPtr<const Mod>(\"rules\", mod);\n}\n\nModScript::DetectUfoFromCraftParser::DetectUfoFromCraftParser(ScriptGlobal* shared, const std::string& name, Mod* mod) : ScriptParserEvents{ shared, name,\n\t\"detection_type\",\n\t\"detection_chance\",\n\t\"ufo\", \"geoscape_game\", \"craft\",\n\t\"distance\", \"already_tracked\", \"radar_total_strength\", \"radar_max_distance\", }\n{\n\tBindBase b { this };\n\n\tb.addCustomPtr<const Mod>(\"rules\", mod);\n}\n\n}\n"
  },
  {
    "path": "src/Savegame/Ufo.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include <string>\n#include \"../Engine/Yaml.h\"\n#include \"Craft.h\"\n#include \"MovingTarget.h\"\n#include \"../Mod/RuleUfo.h\"\n\nnamespace OpenXcom\n{\n\nclass AlienMission;\nclass UfoTrajectory;\nclass SavedGame;\nclass Mod;\nclass Waypoint;\n\nenum UfoDetection : int\n{\n\tDETECTION_NONE = 0x00,\n\tDETECTION_RADAR = 0x01,\n\tDETECTION_HYPERWAVE = 0x03,\n};\n\n/**\n * Represents an alien UFO on the map.\n * Contains variable info about a UFO like\n * position, damage, speed, etc.\n * @sa RuleUfo\n */\nclass Ufo : public MovingTarget\n{\npublic:\n\tstatic const char *ALTITUDE_STRING[];\n\tenum UfoStatus { FLYING, LANDED, CRASHED, DESTROYED, IGNORE_ME };\n\n\t/// Name of class used in script.\n\tstatic constexpr const char *ScriptName = \"Ufo\";\n\t/// Register all useful function used by script.\n\tstatic void ScriptRegister(ScriptParserBase* parser);\n\nprivate:\n\tconst RuleUfo *_rules;\n\tint _uniqueId;\n\tint _missionWaveNumber;\n\tint _crashId, _landId, _damage;\n\tstd::string _direction, _altitude;\n\tenum UfoStatus _status;\n\tsize_t _secondsRemaining;\n\tbool _inBattlescape;\n\tCraftId _shotDownByCraftId;\n\tAlienMission *_mission;\n\tconst UfoTrajectory *_trajectory;\n\tsize_t _trajectoryPoint;\n\tbool _detected, _hyperDetected, _processedIntercept;\n\tint _shootingAt, _hitFrame, _fireCountdown, _escapeCountdown;\n\tRuleUfoStats _stats;\n\t/// Calculates a new speed vector to the destination.\n\tvoid calculateSpeed() override;\n\tint _shield, _shieldRechargeHandle;\n\tint _tractorBeamSlowdown;\n\tbool _isHunterKiller, _isEscort;\n\tint _huntMode, _huntBehavior;\n\tbool _isHunting, _isEscorting;\n\tint _softlockShotCounter;\n\tWaypoint *_origWaypoint;\n\tScriptValues<Ufo> _scriptValues;\n\n\tusing MovingTarget::load;\n\tusing MovingTarget::save;\n\n\tvoid backupOriginalDestination();\npublic:\n\t/// Creates a UFO of the specified type.\n\tUfo(const RuleUfo *rules, int uniqueId, int hunterKillerPercentage = 0, int huntMode = 0, int huntBehavior = 0);\n\t/// Cleans up the UFO.\n\t~Ufo();\n\t/// Loads the UFO from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader, const ScriptGlobal *shared, const Mod &ruleset, SavedGame &game);\n\t/// Finishes loading the UFO from YAML (called after XCOM craft are loaded).\n\tvoid finishLoading(const YAML::YamlNodeReader& reader, SavedGame& save);\n\t/// Saves the UFO to YAML.\n\tvoid save(YAML::YamlNodeWriter writer, const ScriptGlobal *shared, bool newBattle) const;\n\t/// Saves the UFO's ID to YAML.\n\tvoid saveId(YAML::YamlNodeWriter writer) const override;\n\t/// Gets the UFO's type.\n\tstd::string getType() const override;\n\t/// Gets the UFO's ruleset.\n\tconst RuleUfo *getRules() const;\n\t/// Sets the UFO's ruleset.\n\tvoid changeRules(const RuleUfo *rules);\n\t/// Gets the (unique) UFO's ID.\n\tint getUniqueId() const;\n\t/// Gets the mission wave number that created this UFO.\n\tint getMissionWaveNumber() const { return _missionWaveNumber; }\n\t/// Sets the mission wave number that created this UFO.\n\tvoid setMissionWaveNumber(int missionWaveNumber) { _missionWaveNumber = missionWaveNumber; }\n\t/// Gets the UFO's default name.\n\tstd::string getDefaultName(Language *lang) const override;\n\t/// Gets the UFO's marker name.\n\tstd::string getMarkerName() const override;\n\t/// Gets the UFO's marker ID.\n\tint getMarkerId() const override;\n\t/// Gets the UFO's marker sprite.\n\tint getMarker() const override;\n\n\t/// Gets the UFO's amount of damage.\n\tint getDamage() const;\n\t/// Sets the UFO's amount of damage.\n\tvoid setDamage(int damage, const Mod *mod);\n\t/// Gets the UFO's percentage of damage.\n\tint getDamagePercentage() const;\n\n\t/// Gets the UFO's detection status.\n\tbool getDetected() const;\n\t/// Sets the UFO's detection status.\n\tvoid setDetected(bool detected);\n\t/// Gets the UFO's seconds left on the ground.\n\tsize_t getSecondsRemaining() const;\n\t/// Sets the UFO's seconds left on the ground.\n\tvoid setSecondsRemaining(size_t seconds);\n\t/// Gets the UFO's direction.\n\tstd::string getDirection() const;\n\t/// Gets the UFO's altitude.\n\tstd::string getAltitude() const;\n\t/// Gets the UFO's altitude.\n\tint getAltitudeInt() const;\n\t/// Sets the UFO's altitude.\n\tvoid setAltitude(const std::string &altitude);\n\t/// Gets the UFO status\n\tenum UfoStatus getStatus() const { return _status; }\n\t/// Set the UFO's status.\n\tvoid setStatus(enum UfoStatus status) {_status = status; }\n\t/// Gets if the UFO has crashed.\n\tbool isCrashed() const;\n\t/// Gets if the UFO has been destroyed.\n\tbool isDestroyed() const;\n\t/// Handles UFO logic.\n\tvoid think();\n\t/// Sets the UFO's battlescape status.\n\tvoid setInBattlescape(bool inbattle);\n\t/// Gets if the UFO is in battlescape.\n\tbool isInBattlescape() const;\n\t/// Gets the UFO's alien race.\n\tconst std::string &getAlienRace() const;\n\t/// Sets the ID of craft which shot down the UFO.\n\tvoid setShotDownByCraftId(const CraftId& craftId);\n\t/// Gets the ID of craft which shot down the UFO.\n\tCraftId getShotDownByCraftId() const;\n\t/// Gets the UFO's visibility.\n\tint getVisibility() const;\n\t/// Gets the UFO's Mission type.\n\tconst std::string &getMissionType() const;\n\t/// Sets the UFO's mission information.\n\tvoid setMissionInfo(AlienMission *mission, const UfoTrajectory *trajectory);\n\t/// Gets the UFO's hyper detection status.\n\tbool getHyperDetected() const;\n\t/// Sets the UFO's hyper detection status.\n\tvoid setHyperDetected(bool hyperdetected);\n\t/// Gets the UFO's progress on the trajectory track.\n\tsize_t getTrajectoryPoint() const { return _trajectoryPoint; }\n\t/// Sets the UFO's progress on the trajectory track.\n\tvoid setTrajectoryPoint(size_t np) { _trajectoryPoint = np; }\n\t/// Gets the UFO's trajectory.\n\tconst UfoTrajectory &getTrajectory() const { return *_trajectory; }\n\t/// Gets the UFO's mission object.\n\tAlienMission *getMission() const { return _mission; }\n\t/// Gets the Xcom craft targeted by this UFO.\n\tCraft *getTargetedXcomCraft() const;\n\t/// Resets the original destination if targeting the given craft.\n\tvoid resetOriginalDestination(Craft *target);\n\tvoid resetOriginalDestination(bool debugHelper);\n\t/// Sets the Xcom craft targeted by this UFO.\n\tvoid setTargetedXcomCraft(Craft *craft);\n\t/// Sets the UFO escorted by this UFO.\n\tvoid setEscortedUfo(Ufo *ufo);\n\t/// Sets the UFO's destination.\n\tvoid setDestination(Target *dest) override;\n\t/// Get which interceptor this ufo is engaging.\n\tint getShootingAt() const;\n\t/// Set which interceptor this ufo is engaging.\n\tvoid setShootingAt(int target);\n\t/// Gets the UFO's landing site ID.\n\tint getLandId() const;\n\t/// Sets the UFO's landing site ID.\n\tvoid setLandId(int id);\n\t/// Gets the UFO's crash site ID.\n\tint getCrashId() const;\n\t/// Sets the UFO's crash site ID.\n\tvoid setCrashId(int id);\n\t/// Sets the UFO's hit frame.\n\tvoid setHitFrame(int frame);\n\t/// Gets the UFO's hit frame.\n\tint getHitFrame() const;\n\t/// Gets the UFO's stats.\n\tconst RuleUfoStats& getCraftStats() const;\n\tvoid setFireCountdown(int time);\n\tint getFireCountdown() const;\n\tvoid setEscapeCountdown(int time);\n\tint getEscapeCountdown() const;\n\tvoid setInterceptionProcessed(bool processed);\n\tbool getInterceptionProcessed() const;\n\n\t/// Sets the UFO's shield\n\tvoid setShield(int shield);\n\t/// Gets the UFO's shield value\n\tint getShield() const;\n\t/// Sets which _interceptionNumber in a dogfight handles the UFO shield recharge\n\tvoid setShieldRechargeHandle(int shieldRechargeHandle);\n\t/// Gets which _interceptionNumber in a dogfight handles the UFO shield recharge\n\tint getShieldRechargeHandle() const;\n\t/// Gets the percent shield remaining\n\tint getShieldPercentage() const;\n\n\t/// Sets the number of tractor beams locked on to a UFO\n\tvoid setTractorBeamSlowdown(int tractorBeamSlowdown);\n\t/// Gets the number of tractor beams locked on to a UFO\n\tint getTractorBeamSlowdown() const;\n\t/// Is this UFO a hunter-killer?\n\tbool isHunterKiller() const;\n\tvoid setHunterKiller(bool isHunterKiller);\n\t/// Is this UFO an escort?\n\tbool isEscort() const;\n\tvoid setEscort(bool isEscort);\n\t/// Gets the UFO's hunting preferences.\n\tint getHuntMode() const;\n\t/// Gets the UFO's hunting behavior.\n\tint getHuntBehavior() const;\n\t/// Is this UFO actively hunting right now?\n\tbool isHunting() const;\n\t/// Is this UFO escorting other UFO right now?\n\tbool isEscorting() const;\n\t/// Gets the value of the softlock shot counter;\n\tint getSoftlockShotCounter() const { return _softlockShotCounter; }\n\t/// Increases the value of the softlock shot counter;\n\tvoid increaseSoftlockShotCounter() { _softlockShotCounter++; }\n\t/// Checks if a target is inside the UFO's radar range.\n\tbool insideRadarRange(Target *target) const;\n};\n\n}\n"
  },
  {
    "path": "src/Savegame/Vehicle.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Vehicle.h\"\n#include \"../Mod/RuleItem.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes a vehicle of the specified type.\n * @param rules Pointer to ruleset.\n * @param ammo Initial ammo.\n * @param size Size in tiles.\n */\nVehicle::Vehicle(const RuleItem *rules, int ammo, int size) : _rules(rules), _ammo(ammo), _size(size)\n{\n}\n\n/**\n *\n */\nVehicle::~Vehicle()\n{\n}\n\n/**\n * Loads the vehicle from a YAML file.\n * @param node YAML node.\n */\nvoid Vehicle::load(const YAML::YamlNodeReader& reader)\n{\n\treader.tryRead(\"ammo\", _ammo);\n\treader.tryRead(\"size\", _size);\n}\n\n/**\n * Saves the base to a YAML file.\n * @return YAML node.\n */\nvoid Vehicle::save(YAML::YamlNodeWriter writer) const\n{\n\twriter.setAsMap();\n\twriter.write(\"type\", _rules->getType());\n\twriter.write(\"ammo\", _ammo);\n\twriter.write(\"size\", _size);\n}\n\n/**\n * Returns the ruleset for the vehicle's type.\n * @return Pointer to ruleset.\n */\nconst RuleItem *Vehicle::getRules() const\n{\n\treturn _rules;\n}\n\n/**\n * Returns the ammo contained in this vehicle.\n * @return Weapon ammo.\n */\nint Vehicle::getAmmo() const\n{\n\tif (_ammo == -1)\n\t{\n\t\treturn 255;\n\t}\n\treturn _ammo;\n}\n\n/**\n * Changes the ammo contained in this vehicle.\n * @param ammo Weapon ammo.\n */\nvoid Vehicle::setAmmo(int ammo)\n{\n\tif (_ammo != -1)\n\t{\n\t\t_ammo = ammo;\n\t}\n}\n\n/**\n * Returns the size occupied by this vehicle\n * in a transport craft.\n * @return Size in tiles.\n */\nint Vehicle::getTotalSize() const\n{\n\treturn _size;\n}\n\n}\n"
  },
  {
    "path": "src/Savegame/Vehicle.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/Yaml.h\"\n\nnamespace OpenXcom\n{\n\nclass RuleItem;\n\n/**\n * Represents a vehicle (tanks etc.) kept in a craft.\n * Contains variable info about a vehicle like ammo.\n * @sa RuleItem\n */\nclass Vehicle\n{\nprivate:\n\tconst RuleItem *_rules;\n\tint _ammo, _size;\npublic:\n\t/// Creates a vehicle of the specified type.\n\tVehicle(const RuleItem *rules, int ammo, int size);\n\t/// Cleans up the vehicle.\n\t~Vehicle();\n\t/// Loads the vehicle from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader);\n\t/// Saves the vehicle to YAML.\n\tvoid save(YAML::YamlNodeWriter writer) const;\n\t/// Gets the vehicle's ruleset.\n\tconst RuleItem *getRules() const;\n\t/// Gets the vehicle's ammo.\n\tint getAmmo() const;\n\t/// Sets the vehicle's ammo.\n\tvoid setAmmo(int ammo);\n\t/// Gets the vehicle's size.\n\tint getTotalSize() const;\n};\n\n}\n"
  },
  {
    "path": "src/Savegame/Waypoint.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Waypoint.h\"\n#include \"../Engine/Language.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Initializes a waypoint.\n */\nWaypoint::Waypoint() : Target()\n{\n}\n\n/**\n *\n */\nWaypoint::~Waypoint()\n{\n}\n\n/**\n * Returns the waypoint's unique type used for\n * savegame purposes.\n * @return ID.\n */\nstd::string Waypoint::getType() const\n{\n\treturn \"STR_WAY_POINT\";\n}\n\n/**\n * Returns the globe marker for the waypoint.\n * @return Marker sprite, -1 if none.\n */\nint Waypoint::getMarker() const\n{\n\treturn 6;\n}\n\n}\n"
  },
  {
    "path": "src/Savegame/Waypoint.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"Target.h\"\n#include <string>\n\nnamespace OpenXcom\n{\n\n/**\n * Represents a fixed waypoint on the world.\n */\nclass Waypoint : public Target\n{\npublic:\n\t/// Creates a waypoint.\n\tWaypoint();\n\t/// Cleans up the waypoint.\n\t~Waypoint();\n\t/// Gets the waypoint's type.\n\tstd::string getType() const override;\n\t/// Gets the waypoint's marker sprite.\n\tint getMarker() const override;\n};\n\n}\n"
  },
  {
    "path": "src/Savegame/WeightedOptions.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"WeightedOptions.h\"\n#include \"../Engine/RNG.h\"\n\nnamespace OpenXcom\n{\n\n/**\n * Select a random choice from among the contents.\n * This MUST be called on non-empty objects.\n * Each time this is called, the returned value can be different.\n * @return The key of the selected choice.\n */\nstd::string WeightedOptions::choose() const\n{\n\tif (_totalWeight == 0)\n\t{\n\t\treturn \"\";\n\t}\n\tsize_t var = RNG::generate(1, _totalWeight);\n\tauto ii = _choices.begin();\n\tfor (; ii != _choices.end(); ++ii)\n\t{\n\t\tif (var <= ii->second)\n\t\t\tbreak;\n\t\tvar -= ii->second;\n\t}\n\t// We always have a valid iterator here.\n\treturn ii->first;\n}\n\n/**\n * Set an option's weight.\n * If @a weight is set to 0, the option is removed from the list of choices.\n * If @a id already exists, the new weight replaces the old one, otherwise\n * @a id is added to the list of choices, with @a weight as the weight.\n * @param id The option name.\n * @param weight The option's new weight.\n */\nvoid WeightedOptions::set(const std::string &id, size_t weight)\n{\n\tauto option = _choices.find(id);\n\tif (option != _choices.end())\n\t{\n\t\t_totalWeight -= option->second;\n\t\tif (0 != weight)\n\t\t{\n\t\t\toption->second = weight;\n\t\t\t_totalWeight += weight;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_choices.erase(option);\n\t\t}\n\t}\n\telse if (0 != weight)\n\t{\n\t\t_choices.insert(std::make_pair(id, weight));\n\t\t_totalWeight += weight;\n\t}\n}\n\n/**\n * Read all the weighted options from a node reader and add them to the WeightedOptions.\n * The weight option list is not replaced, only values in @a nd will be added /\n * changed.\n * @param nd The YAML node (containing a map) with the new values.\n */\nvoid WeightedOptions::load(const YAML::YamlNodeReader& reader)\n{\n\tfor (const auto& option : reader.children())\n\t\tset(option.readKey<std::string>(), option.readVal<size_t>());\n}\n\n/**\n * Send the WeightedOption contents to a YAML::Emitter.\n * @return YAML node.\n */\nvoid WeightedOptions::save(YAML::YamlNodeWriter writer) const\n{\n\tif (_choices.empty()) // for compatibility reasons, we output null instead of empty map\n\t{\n\t\twriter.setValueNull();\n\t\treturn;\n\t}\n\twriter.setAsMap();\n\tfor (const auto& pair : _choices)\n\t\twriter.write(writer.saveString(pair.first), pair.second);\n}\n\n/**\n * Get the list of strings associated with these weights.\n * @return the list of strings in these weights.\n */\nstd::vector<std::string> WeightedOptions::getNames()\n{\n\tstd::vector<std::string> names;\n\tfor (const auto& pair : _choices)\n\t{\n\t\tnames.push_back(pair.first);\n\t}\n\treturn names;\n}\n\n}\n"
  },
  {
    "path": "src/Savegame/WeightedOptions.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <string>\n#include <map>\n#include <vector>\n#include \"../Engine/Yaml.h\"\n\n\nnamespace OpenXcom\n{\n\n/**\n * Holds pairs of relative weights and IDs.\n * It is used to store options and make a random choice between them.\n */\nclass WeightedOptions\n{\npublic:\n\t/// Create an empty set.\n\tWeightedOptions() : _totalWeight(0) { /* Empty by design. */ }\n\t/// Select from among the items.\n\tstd::string choose() const;\n\t/// Set an option's weight.\n\tvoid set(const std::string &id, size_t weight);\n\t/// Is this empty?\n\tbool empty() const { return 0 == _totalWeight; }\n\t/// Remove all entries.\n\tvoid clear() { _totalWeight = 0; _choices.clear(); }\n\t/// Update our list with data from YAML.\n\tvoid load(const YAML::YamlNodeReader& reader);\n\t/// Store our list in YAML.\n\tvoid save(YAML::YamlNodeWriter writer) const;\n\t/// Get the list of strings associated with these weights.\n\tstd::vector<std::string> getNames();\n\tconst std::map<std::string, size_t>& getChoicesRaw() const { return _choices; }\nprivate:\n\tstd::map<std::string, size_t> _choices; //!< Options and weights\n\tsize_t _totalWeight; //!< The total weight of all options.\n};\n\n}\n"
  },
  {
    "path": "src/Ufopaedia/ArticleState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"Ufopaedia.h\"\n#include \"ArticleState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/Surface.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Mod/ArticleDefinition.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Savegame/SavedGame.h\"\n\nnamespace OpenXcom\n{\n\t/**\n\t * Change index position to next article.\n\t */\n\tvoid ArticleCommonState::nextArticle()\n\t{\n\t\tif (current_index >= articleList.size() - 1)\n\t\t{\n\t\t\t// goto first\n\t\t\tcurrent_index = 0;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tcurrent_index++;\n\t\t}\n\t\tif (isCurrentArticleHidden())\n\t\t{\n\t\t\tnextArticle();\n\t\t}\n\t}\n\n\t/**\n\t * Change page to next in article or move to next index position.\n\t * Each article can have multiple pages, if we are on last page we will move to first page of next article.\n\t */\n\tvoid ArticleCommonState::nextArticlePage()\n\t{\n\t\tif (!hasNextArticlePage())\n\t\t{\n\t\t\t// goto to first page of next article\n\t\t\tnextArticle();\n\t\t\tcurrent_page = 0;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tcurrent_page++;\n\t\t}\n\t}\n\n\tbool ArticleCommonState::hasNextArticlePage()\n\t{\n\t\treturn !(current_page >= getCurrentArticle()->getNumberOfPages() - 1);\n\t}\n\n\t/**\n\t * Change index position to previous article.\n\t */\n\tvoid ArticleCommonState::prevArticle()\n\t{\n\t\tif (current_index == 0 || current_index > articleList.size() - 1)\n\t\t{\n\t\t\t// goto last\n\t\t\tcurrent_index = articleList.size() - 1;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tcurrent_index--;\n\t\t}\n\t\tif (isCurrentArticleHidden())\n\t\t{\n\t\t\tprevArticle();\n\t\t}\n\t}\n\n\t/**\n\t * Change page to previous in article or move to previous index position.\n\t * Each article can have multiple pages, if we are on first page we will move to last page of previous article.\n\t */\n\tvoid ArticleCommonState::prevArticlePage()\n\t{\n\t\tif (!hasPrevArticlePage())\n\t\t{\n\t\t\t// goto last page of previous article\n\t\t\tprevArticle();\n\t\t\tcurrent_page = getCurrentArticle()->getNumberOfPages() - 1;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tcurrent_page--;\n\t\t}\n\t}\n\n\tbool ArticleCommonState::hasPrevArticlePage()\n\t{\n\t\treturn !(current_page == 0 || current_page > getCurrentArticle()->getNumberOfPages() - 1);\n\t}\n\n\t/**\n\t * Constructor\n\t * @param game Pointer to current game.\n\t * @param article_id The article id of this article state instance.\n\t */\n\tArticleState::ArticleState(const std::string &article_id, std::shared_ptr<ArticleCommonState> state) : _id(article_id)\n\t{\n\t\t// init background and navigation elements\n\t\t_bg = new Surface(320, 200, 0, 0);\n\t\t_btnOk = new TextButton(30, 14, 5, 5);\n\t\t_btnPrev = new TextButton(30, 14, 40, 5);\n\t\t_btnNext = new TextButton(30, 14, 75, 5);\n\t\t_btnInfo = new TextButton(40, 14, 110, 5);\n\n\t\t_state = std::move(state);\n\n\t\t// remember this article as seen/normal\n\t\tint ruleStatus = _game->getSavedGame()->getUfopediaRuleStatus(_id);\n\t\tif (ruleStatus != ArticleDefinition::PEDIA_STATUS_HIDDEN)\n\t\t{\n\t\t\t_game->getSavedGame()->setUfopediaRuleStatus(_id, ArticleDefinition::PEDIA_STATUS_NORMAL);\n\t\t}\n\t}\n\n\t/**\n\t * Destructor\n\t */\n\tArticleState::~ArticleState()\n\t{}\n\n\tstd::string ArticleState::getDamageTypeText(ItemDamageType dt) const\n\t{\n\t\tstd::string type;\n\t\tswitch (dt)\n\t\t{\n\t\tcase DT_NONE:\n\t\t\ttype = \"STR_DAMAGE_NONE\";\n\t\t\tbreak;\n\t\tcase DT_AP:\n\t\t\ttype = \"STR_DAMAGE_ARMOR_PIERCING\";\n\t\t\tbreak;\n\t\tcase DT_IN:\n\t\t\ttype = \"STR_DAMAGE_INCENDIARY\";\n\t\t\tbreak;\n\t\tcase DT_HE:\n\t\t\ttype = \"STR_DAMAGE_HIGH_EXPLOSIVE\";\n\t\t\tbreak;\n\t\tcase DT_LASER:\n\t\t\ttype = \"STR_DAMAGE_LASER_BEAM\";\n\t\t\tbreak;\n\t\tcase DT_PLASMA:\n\t\t\ttype = \"STR_DAMAGE_PLASMA_BEAM\";\n\t\t\tbreak;\n\t\tcase DT_STUN:\n\t\t\ttype = \"STR_DAMAGE_STUN\";\n\t\t\tbreak;\n\t\tcase DT_MELEE:\n\t\t\ttype = \"STR_DAMAGE_MELEE\";\n\t\t\tbreak;\n\t\tcase DT_ACID:\n\t\t\ttype = \"STR_DAMAGE_ACID\";\n\t\t\tbreak;\n\t\tcase DT_SMOKE:\n\t\t\ttype = \"STR_DAMAGE_SMOKE\";\n\t\t\tbreak;\n\t\tcase DT_10:\n\t\t\ttype = \"STR_DAMAGE_10\";\n\t\t\tbreak;\n\t\tcase DT_11:\n\t\t\ttype = \"STR_DAMAGE_11\";\n\t\t\tbreak;\n\t\tcase DT_12:\n\t\t\ttype = \"STR_DAMAGE_12\";\n\t\t\tbreak;\n\t\tcase DT_13:\n\t\t\ttype = \"STR_DAMAGE_13\";\n\t\t\tbreak;\n\t\tcase DT_14:\n\t\t\ttype = \"STR_DAMAGE_14\";\n\t\t\tbreak;\n\t\tcase DT_15:\n\t\t\ttype = \"STR_DAMAGE_15\";\n\t\t\tbreak;\n\t\tcase DT_16:\n\t\t\ttype = \"STR_DAMAGE_16\";\n\t\t\tbreak;\n\t\tcase DT_17:\n\t\t\ttype = \"STR_DAMAGE_17\";\n\t\t\tbreak;\n\t\tcase DT_18:\n\t\t\ttype = \"STR_DAMAGE_18\";\n\t\t\tbreak;\n\t\tcase DT_19:\n\t\t\ttype = \"STR_DAMAGE_19\";\n\t\t\tbreak;\n\t\tdefault:\n\t\t\ttype = \"STR_UNKNOWN\";\n\t\t\tbreak;\n\t\t}\n\t\treturn type;\n\t}\n\n\t/**\n\t * Set captions and click handlers for the common control elements.\n\t */\n\tvoid ArticleState::initLayout()\n\t{\n\t\tadd(_bg);\n\t\tadd(_btnOk);\n\t\tadd(_btnPrev);\n\t\tadd(_btnNext);\n\t\tadd(_btnInfo);\n\n\t\t_btnOk->setText(tr(\"STR_OK\"));\n\t\t_btnOk->onMouseClick((ActionHandler)&ArticleState::btnOkClick);\n\t\t_btnOk->onKeyboardPress((ActionHandler)&ArticleState::btnOkClick,Options::keyOk);\n\t\t_btnOk->onKeyboardPress((ActionHandler)&ArticleState::btnOkClick,Options::keyCancel);\n\t\t_btnOk->onKeyboardPress((ActionHandler)&ArticleState::btnResetMusicClick, Options::keySelectMusicTrack);\n\t\t_btnPrev->setText(\"<<\");\n\t\t_btnPrev->onMouseClick((ActionHandler)&ArticleState::btnPrevClick);\n\t\t_btnPrev->onKeyboardPress((ActionHandler)&ArticleState::btnPrevClick, Options::keyGeoLeft);\n\t\t_btnNext->setText(\">>\");\n\t\t_btnNext->onMouseClick((ActionHandler)&ArticleState::btnNextClick);\n\t\t_btnNext->onKeyboardPress((ActionHandler)&ArticleState::btnNextClick, Options::keyGeoRight);\n\t\t_btnInfo->setText(tr(\"STR_INFO_UFOPEDIA\"));\n\t\t_btnInfo->onMouseClick((ActionHandler)&ArticleState::btnInfoClick);\n\t\t_btnInfo->onKeyboardPress((ActionHandler)&ArticleState::btnInfoClick, Options::keyGeoUfopedia);\n\t\t_btnInfo->setVisible(false);\n\t}\n\n\t/**\n\t * Returns to the previous screen.\n\t * @param action Pointer to an action.\n\t */\n\tvoid ArticleState::btnOkClick(Action *)\n\t{\n\t\t_game->popState();\n\t}\n\n\t/**\n\t * Resets the music to a random geoscape music.\n\t * @param action Pointer to an action.\n\t */\n\tvoid ArticleState::btnResetMusicClick(Action *)\n\t{\n\t\t// reset that pesky interception music!\n\t\t_game->getMod()->playMusic(\"GMGEO\");\n\t}\n\n\t/**\n\t * Shows the previous available article.\n\t * @param action Pointer to an action.\n\t */\n\tvoid ArticleState::btnPrevClick(Action *)\n\t{\n\t\tUfopaedia::prev(_game, _state);\n\t}\n\n\t/**\n\t * Shows the next available article. Loops to the first.\n\t * @param action Pointer to an action.\n\t */\n\tvoid ArticleState::btnNextClick(Action *)\n\t{\n\t\tUfopaedia::next(_game, _state);\n\t}\n\n\t/**\n\t * Shows the detailed (raw) information about the current topic.\n\t * @param action Pointer to an action.\n\t */\n\tvoid ArticleState::btnInfoClick(Action *)\n\t{\n\t\tUfopaedia::openArticleDetail(_game, _id);\n\t}\n\n}\n"
  },
  {
    "path": "src/Ufopaedia/ArticleState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include \"../Mod/RuleItem.h\"\n#include <string>\n#include <memory>\n\nnamespace OpenXcom\n{\n\tclass Game;\n\tclass Action;\n\tclass Surface;\n\tclass TextButton;\n\tclass ArticleDefinition;\n\n\n\t/// Current state of ufopedia\n\tstruct ArticleCommonState\n\t{\n\t\t/// Invalid index.\n\t\tstatic constexpr size_t invalid = -1;\n\n\t\t/// Current selected article index (for previous/next navigation).\n\t\tsize_t current_index = invalid;\n\n\t\t/// Current sub page of article.\n\t\tsize_t current_page = 0;\n\n\t\t/// List of all available articles.\n\t\tstd::vector<ArticleDefinition *> articleList;\n\t\tstd::vector<bool> articleStatusList;\n\n\t\t/// Get current Article definition for current index position.\n\t\tArticleDefinition* getCurrentArticle() const\n\t\t{\n\t\t\treturn articleList[current_index];\n\t\t}\n\t\tbool isCurrentArticleHidden() const\n\t\t{\n\t\t\treturn articleStatusList[current_index];\n\t\t}\n\n\t\t/// Change index position to next article\n\t\tvoid nextArticle();\n\n\t\t/// Change page to next in article or move to next index position.\n\t\tvoid nextArticlePage();\n\t\tbool hasNextArticlePage();\n\n\t\t/// Change index position to previous article.\n\t\tvoid prevArticle();\n\n\t\t/// Change page to previous in article or move to previous index position.\n\t\tvoid prevArticlePage();\n\t\tbool hasPrevArticlePage();\n\t};\n\n\t/**\n\t * UfopaediaArticle is the base class for all articles of various types.\n\t *\n\t * It encapsulates the basic characteristics.\n\t */\n\n\tclass ArticleState : public State\n\t{\n\tprotected:\n\t\t/// constructor (protected, so it can only be instantiated by derived classes)\n\t\tArticleState(const std::string &article_id, std::shared_ptr<ArticleCommonState> state);\n\t\t/// destructor\n\t\tvirtual ~ArticleState();\n\n\tpublic:\n\t\t/// return the article id\n\t\tstd::string getId() const { return _id; }\n\n\tprotected:\n\n\t\t/// converts damage type to string\n\t\tstd::string getDamageTypeText(ItemDamageType dt) const;\n\n\t\t/// screen layout helpers\n\t\tvoid initLayout();\n\n\t\t/// callback for OK button\n\t\tvoid btnOkClick(Action *action);\n\t\tvoid btnResetMusicClick(Action *action);\n\n\t\t/// callback for PREV button\n\t\tvoid btnPrevClick(Action *action);\n\n\t\t/// callback for NEXT button\n\t\tvoid btnNextClick(Action *action);\n\n\t\t/// callback for INFO button\n\t\tvoid btnInfoClick(Action *action);\n\n\t\t/// the article id\n\t\tstd::string _id;\n\n\t\t/// screen elements common to all articles!\n\t\tSurface *_bg;\n\t\tTextButton *_btnOk;\n\t\tTextButton *_btnPrev;\n\t\tTextButton *_btnNext;\n\t\tTextButton *_btnInfo;\n\n\t\t/// Shared state.\n\t\tstd::shared_ptr<ArticleCommonState> _state;\n\t};\n}\n"
  },
  {
    "path": "src/Ufopaedia/ArticleStateArmor.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include <sstream>\n#include \"../fmath.h\"\n#include \"ArticleStateArmor.h\"\n#include \"../Mod/ArticleDefinition.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Surface.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/FileMap.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Mod/RuleInterface.h\"\n#include \"../Savegame/Soldier.h\"\n\nnamespace OpenXcom\n{\n\n\tArticleStateArmor::ArticleStateArmor(ArticleDefinitionArmor *defs, std::shared_ptr<ArticleCommonState> state) : ArticleState(defs->id, std::move(state)), _row(0)\n\t{\n\t\tArmor *armor = _game->getMod()->getArmor(defs->id, true);\n\n\t\t// add screen elements\n\t\t_txtTitle = new Text(300, 17, 5, 24);\n\n\t\t// Set palette\n\t\tSurface* customArmorSprite = defs->image_id.empty() ? nullptr : _game->getMod()->getSurface(defs->image_id, true);\n\t\tif (defs->customPalette && customArmorSprite)\n\t\t{\n\t\t\tsetCustomPalette(customArmorSprite->getPalette(), Mod::BATTLESCAPE_CURSOR);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tsetStandardPalette(\"PAL_BATTLEPEDIA\");\n\t\t}\n\n\t\tRuleInterface* itf = _game->getMod()->getInterface(\"articleArmor\");\n\t\t_buttonColor = itf->getElement(\"button\")->color;\n\t\t_textColor = itf->getElement(\"text\")->color;\n\t\t_textColor2 = itf->getElement(\"text\")->color2;\n\t\t_listColor1 = itf->getElement(\"list\")->color;\n\t\t_listColor2 = itf->getElement(\"list\")->color2;\n\n\t\tArticleState::initLayout();\n\n\t\t// add other elements\n\t\tadd(_txtTitle);\n\n\t\t// Set up objects\n\t\t_btnOk->setColor(_buttonColor);\n\t\t_btnPrev->setColor(_buttonColor);\n\t\t_btnNext->setColor(_buttonColor);\n\t\t_btnInfo->setColor(_buttonColor);\n\t\t_btnInfo->setVisible(_game->getMod()->getShowPediaInfoButton());\n\n\t\t_txtTitle->setColor(_textColor);\n\t\t_txtTitle->setBig();\n\t\t_txtTitle->setText(tr(defs->getTitleForPage(_state->current_page)));\n\n\t\t// optional background image\n\t\tif (!defs->customPalette)\n\t\t{\n\t\t\tauto& bgImageName = itf->getBackgroundImage(_game->getMod(), _game->getSavedGame());\n\t\t\tif (!bgImageName.empty())\n\t\t\t{\n\t\t\t\t_game->getMod()->getSurface(bgImageName)->blitNShade(_bg, 0, 0);\n\t\t\t}\n\t\t}\n\n\t\tif (customArmorSprite)\n\t\t{\n\t\t\t// blit on the background, so that text and button are always visible\n\t\t\tcustomArmorSprite->blitNShade(_bg, 0, 0);\n\t\t}\n\t\telse if (armor->hasLayersDefinition())\n\t\t{\n\t\t\t// dummy default soldier (M0)\n\t\t\tSoldier *s = new Soldier(_game->getMod()->getSoldier(_game->getMod()->getSoldiersList().front(), true), armor, 0 /*nationality*/, 0 /*id*/);\n\t\t\ts->setGender(GENDER_MALE);\n\t\t\ts->setLook(LOOK_BLONDE);\n\t\t\ts->setLookVariant(0);\n\n\t\t\tfor (const auto& layer : s->getArmorLayers())\n\t\t\t{\n\t\t\t\tauto* surf = _game->getMod()->getSurface(layer, true);\n\t\t\t\tsurf->blitNShade(_bg, 0, 0);\n\t\t\t}\n\t\t\tdelete s;\n\t\t\ts = nullptr;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tstd::string look = armor->getSpriteInventory();\n\t\t\tlook += \"M0.SPK\";\n\t\t\tif (!_game->getMod()->getSurface(look, false))\n\t\t\t{\n\t\t\t\tlook = armor->getSpriteInventory() + \".SPK\";\n\t\t\t}\n\t\t\tif (!_game->getMod()->getSurface(look, false))\n\t\t\t{\n\t\t\t\tlook = armor->getSpriteInventory();\n\t\t\t}\n\t\t\t_game->getMod()->getSurface(look, true)->blitNShade(_bg, 0, 0);\n\t\t}\n\n\n\t\t_lstInfo = new TextList(150, 96, 150, 46);\n\t\tadd(_lstInfo);\n\n\t\t_lstInfo->setColor(_listColor1);\n\t\t_lstInfo->setColumns(2, 125, 25);\n\t\t_lstInfo->setDot(true);\n\n\t\t_txtInfo = new Text(300, 48, 8, 150);\n\t\tadd(_txtInfo);\n\n\t\t_txtInfo->setColor(_textColor);\n\t\t_txtInfo->setSecondaryColor(_textColor2);\n\t\t_txtInfo->setWordWrap(true);\n\t\t_txtInfo->setScrollable(true);\n\t\t_txtInfo->setText(tr(defs->getTextForPage(_state->current_page)));\n\n\t\t// Add armor values\n\t\taddStat(\"STR_FRONT_ARMOR\", armor->getFrontArmor());\n\t\taddStat(\"STR_LEFT_ARMOR\", armor->getLeftSideArmor());\n\t\taddStat(\"STR_RIGHT_ARMOR\", armor->getRightSideArmor());\n\t\taddStat(\"STR_REAR_ARMOR\", armor->getRearArmor());\n\t\taddStat(\"STR_UNDER_ARMOR\", armor->getUnderArmor());\n\n\t\t_lstInfo->addRow(0);\n\t\t++_row;\n\n\t\tif (Options::oxcePediaSortResistances == 0)\n\t\t{\n\t\t\t// Add damage modifiers\n\t\t\tfor (int i = 0; i < DAMAGE_TYPES; ++i)\n\t\t\t{\n\t\t\t\tItemDamageType dt = (ItemDamageType)i;\n\t\t\t\tint percentage = (int)Round(armor->getDamageModifier(dt) * 100.0f);\n\t\t\t\tstd::string damage = getDamageTypeText(dt);\n\t\t\t\tif (percentage != 100 && damage != \"STR_UNKNOWN\")\n\t\t\t\t{\n\t\t\t\t\taddModifier(damage, Unicode::formatPercentage(percentage));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// Add resistances\n\t\t\tint counter = 0;\n\t\t\tbool first = true;\n\t\t\tfor (int i = 0; i < DAMAGE_TYPES; ++i)\n\t\t\t{\n\t\t\t\tItemDamageType dt = (ItemDamageType)i;\n\t\t\t\tint percentage = (int)Round(armor->getDamageModifier(dt) * 100.0f);\n\t\t\t\tstd::string damage = getDamageTypeText(dt);\n\t\t\t\tif (percentage < 100 && damage != \"STR_UNKNOWN\")\n\t\t\t\t{\n\t\t\t\t\taddModifier(damage, Unicode::formatPercentage(percentage));\n\t\t\t\t\tcounter++;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (Options::oxcePediaSortResistances >= 2)\n\t\t\t{\n\t\t\t\t// Add standard damage (100%)\n\t\t\t\tfor (int i = 0; i < DAMAGE_TYPES; ++i)\n\t\t\t\t{\n\t\t\t\t\tItemDamageType dt = (ItemDamageType)i;\n\t\t\t\t\tint percentage = (int)Round(armor->getDamageModifier(dt) * 100.0f);\n\t\t\t\t\tstd::string damage = getDamageTypeText(dt);\n\t\t\t\t\tif (percentage == 100 && damage != \"STR_UNKNOWN\")\n\t\t\t\t\t{\n\t\t\t\t\t\tif (counter > 0 && first)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfirst = false;\n\t\t\t\t\t\t\tcounter = 0;\n\t\t\t\t\t\t\t_lstInfo->addRow(0);\n\t\t\t\t\t\t\t++_row;\n\t\t\t\t\t\t}\n\t\t\t\t\t\taddModifier(damage, Unicode::formatPercentage(percentage));\n\t\t\t\t\t\tcounter++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Add vulnerabilities\n\t\t\tfirst = true;\n\t\t\tfor (int i = 0; i < DAMAGE_TYPES; ++i)\n\t\t\t{\n\t\t\t\tItemDamageType dt = (ItemDamageType)i;\n\t\t\t\tint percentage = (int)Round(armor->getDamageModifier(dt) * 100.0f);\n\t\t\t\tstd::string damage = getDamageTypeText(dt);\n\t\t\t\tif (percentage > 100 && damage != \"STR_UNKNOWN\")\n\t\t\t\t{\n\t\t\t\t\tif (counter > 0 && first)\n\t\t\t\t\t{\n\t\t\t\t\t\tfirst = false;\n\t\t\t\t\t\tcounter = 0;\n\t\t\t\t\t\t_lstInfo->addRow(0);\n\t\t\t\t\t\t++_row;\n\t\t\t\t\t}\n\t\t\t\t\taddModifier(damage, Unicode::formatPercentage(percentage));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t_lstInfo->addRow(0);\n\t\t++_row;\n\n\t\t// Add unit stats\n\t\taddStat(\"STR_TIME_UNITS\", armor->getStats()->tu, true);\n\t\taddStat(\"STR_STAMINA\", armor->getStats()->stamina, true);\n\t\taddStat(\"STR_HEALTH\", armor->getStats()->health, true);\n\t\taddStat(\"STR_BRAVERY\", armor->getStats()->bravery, true);\n\t\taddStat(\"STR_REACTIONS\", armor->getStats()->reactions, true);\n\t\taddStat(\"STR_FIRING_ACCURACY\", armor->getStats()->firing, true);\n\t\taddStat(\"STR_THROWING_ACCURACY\", armor->getStats()->throwing, true);\n\t\taddStat(\"STR_MELEE_ACCURACY\", armor->getStats()->melee, true);\n\t\taddStat(\"STR_STRENGTH\", armor->getStats()->strength, true);\n\t\taddStat(\"STR_MANA_POOL\", armor->getStats()->mana, true);\n\t\taddStat(\"STR_PSIONIC_STRENGTH\", armor->getStats()->psiStrength, true);\n\t\taddStat(\"STR_PSIONIC_SKILL\", armor->getStats()->psiSkill, true);\n\n\t\tcenterAllSurfaces();\n\t}\n\n\tArticleStateArmor::~ArticleStateArmor()\n\t{}\n\n\tvoid ArticleStateArmor::addStat(const std::string &label, int stat, bool plus)\n\t{\n\t\tif (stat != 0)\n\t\t{\n\t\t\tstd::ostringstream ss;\n\t\t\tif (plus && stat > 0)\n\t\t\t\tss << \"+\";\n\t\t\tss << stat;\n\t\t\t_lstInfo->addRow(2, tr(label).c_str(), ss.str().c_str());\n\t\t\t_lstInfo->setCellColor(_row, 1, _listColor2);\n\t\t\t++_row;\n\t\t}\n\t}\n\n\tvoid ArticleStateArmor::addModifier(const std::string &label, const std::string &stat)\n\t{\n\t\tstd::string translation = tr(label);\n\t\tif (translation.length() > 2) // filter out unused OXCE damage types\n\t\t{\n\t\t\t_lstInfo->addRow(2, tr(label).c_str(), stat.c_str());\n\t\t\t_lstInfo->setCellColor(_row, 1, _listColor2);\n\t\t\t++_row;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/Ufopaedia/ArticleStateArmor.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ArticleState.h\"\n\nnamespace OpenXcom\n{\n\tclass Game;\n\tclass Surface;\n\tclass Text;\n\tclass TextList;\n\tclass ArticleDefinitionArmor;\n\n\t/**\n\t * ArticleStateArmor has a caption, preview image and a stats block.\n\t * The image is found using the Armor class.\n\t */\n\n\tclass ArticleStateArmor : public ArticleState\n\t{\n\tpublic:\n\t\tArticleStateArmor(ArticleDefinitionArmor *article_defs, std::shared_ptr<ArticleCommonState> state);\n\t\tvirtual ~ArticleStateArmor();\n\n\tprotected:\n\t\tvoid addStat(const std::string &label, int stat, bool plus = false);\n\t\tvoid addModifier(const std::string &label, const std::string &stat);\n\n\t\tint _row;\n\t\tText *_txtTitle;\n\t\tTextList *_lstInfo;\n\t\tText *_txtInfo;\n\t\tUint8 _buttonColor, _textColor, _textColor2, _listColor1, _listColor2;\n\t};\n}\n"
  },
  {
    "path": "src/Ufopaedia/ArticleStateBaseFacility.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include <sstream>\n#include \"ArticleStateBaseFacility.h\"\n#include \"../Mod/ArticleDefinition.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleBaseFacility.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Palette.h\"\n#include \"../Engine/Surface.h\"\n#include \"../Engine/SurfaceSet.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/TextList.h\"\n\nnamespace OpenXcom\n{\n\n\tArticleStateBaseFacility::ArticleStateBaseFacility(ArticleDefinitionBaseFacility *defs, std::shared_ptr<ArticleCommonState> state) : ArticleState(defs->id, std::move(state))\n\t{\n\t\tRuleBaseFacility *facility = _game->getMod()->getBaseFacility(defs->id, true);\n\n\t\t// add screen elements\n\t\t_txtTitle = new Text(200, 17, 10, 24);\n\n\t\t// Set palette\n\t\tsetStandardPalette(\"PAL_BASESCAPE\");\n\n\t\tArticleState::initLayout();\n\n\t\t// add other elements\n\t\tadd(_txtTitle);\n\n\t\t// Set up objects\n\t\t_game->getMod()->getSurface(\"BACK09.SCR\")->blitNShade(_bg, 0, 0);\n\t\t_btnOk->setColor(Palette::blockOffset(4));\n\t\t_btnPrev->setColor(Palette::blockOffset(4));\n\t\t_btnNext->setColor(Palette::blockOffset(4));\n\t\t_btnInfo->setColor(Palette::blockOffset(4));\n\t\t_btnInfo->setVisible(_game->getMod()->getShowPediaInfoButton());\n\n\t\t_txtTitle->setColor(Palette::blockOffset(13)+10);\n\t\t_txtTitle->setBig();\n\t\t_txtTitle->setText(tr(defs->getTitleForPage(_state->current_page)));\n\n\t\t// build preview image\n\t\tint tile_size = 32;\n\t\t_image = new Surface(\n\t\t\ttile_size * std::max(1, Mod::PEDIA_FACILITY_RENDER_PARAMETERS[0]),\n\t\t\ttile_size * std::max(1, Mod::PEDIA_FACILITY_RENDER_PARAMETERS[1]),\n\t\t\t232 + Mod::PEDIA_FACILITY_RENDER_PARAMETERS[2],\n\t\t\t16 + Mod::PEDIA_FACILITY_RENDER_PARAMETERS[3]);\n\t\tadd(_image);\n\n\t\tSurfaceSet *graphic = _game->getMod()->getSurfaceSet(\"BASEBITS.PCK\");\n\t\tSurface *frame;\n\t\tint x_offset, y_offset;\n\t\tint x_pos, y_pos;\n\t\tint num;\n\n\t\t// calculate preview offset\n\t\tx_offset = (tile_size * std::max(0, Mod::PEDIA_FACILITY_RENDER_PARAMETERS[0] - facility->getSizeX())) / 2;\n\t\ty_offset = (tile_size * std::max(0, Mod::PEDIA_FACILITY_RENDER_PARAMETERS[1] - facility->getSizeY())) / 2;\n\n\t\t// render build preview\n\t\tnum = 0;\n\t\ty_pos = y_offset;\n\t\tfor (int y = 0; y < facility->getSizeY(); ++y)\n\t\t{\n\t\t\tx_pos = x_offset;\n\t\t\tfor (int x = 0; x < facility->getSizeX(); ++x)\n\t\t\t{\n\t\t\t\tframe = graphic->getFrame(facility->getSpriteShape() + num);\n\t\t\t\tframe->blitNShade(_image, x_pos, y_pos);\n\n\t\t\t\tif (facility->getSpriteEnabled())\n\t\t\t\t{\n\t\t\t\t\tframe = graphic->getFrame(facility->getSpriteFacility() + num);\n\t\t\t\t\tframe->blitNShade(_image, x_pos, y_pos);\n\t\t\t\t}\n\n\t\t\t\tx_pos += tile_size;\n\t\t\t\tnum++;\n\t\t\t}\n\t\t\ty_pos += tile_size;\n\t\t}\n\n\t\t_txtInfo = new Text(300, 90, 10, 104);\n\t\tadd(_txtInfo);\n\n\t\t_txtInfo->setColor(Palette::blockOffset(13)+10);\n\t\t_txtInfo->setSecondaryColor(Palette::blockOffset(13));\n\t\t_txtInfo->setWordWrap(true);\n\t\t_txtInfo->setScrollable(true);\n\t\t_txtInfo->setText(tr(defs->getTextForPage(_state->current_page)));\n\n\t\t_lstInfo = new TextList(200, 42, 10, 42);\n\t\tadd(_lstInfo);\n\n\t\t_lstInfo->setColor(Palette::blockOffset(13)+10);\n\t\t_lstInfo->setColumns(2, 140, 60);\n\t\t_lstInfo->setDot(true);\n\n\t\t_lstInfo->addRow(2, tr(\"STR_CONSTRUCTION_TIME\").c_str(), tr(\"STR_DAY\", facility->getBuildTime()).c_str());\n\t\t_lstInfo->setCellColor(0, 1, Palette::blockOffset(13)+0);\n\n\t\tstd::ostringstream ss;\n\t\tss << Unicode::formatFunding(facility->getBuildCost());\n\t\t_lstInfo->addRow(2, tr(\"STR_CONSTRUCTION_COST\").c_str(), ss.str().c_str());\n\t\t_lstInfo->setCellColor(1, 1, Palette::blockOffset(13)+0);\n\n\t\tss.str(\"\");ss.clear();\n\t\tss << Unicode::formatFunding(facility->getMonthlyCost());\n\t\t_lstInfo->addRow(2, tr(\"STR_MAINTENANCE_COST\").c_str(), ss.str().c_str());\n\t\t_lstInfo->setCellColor(2, 1, Palette::blockOffset(13)+0);\n\n\t\tif (facility->getDefenseValue() > 0)\n\t\t{\n\t\t\tss.str(\"\");ss.clear();\n\t\t\tss << facility->getDefenseValue();\n\t\t\t_lstInfo->addRow(2, tr(\"STR_DEFENSE_VALUE\").c_str(), ss.str().c_str());\n\t\t\t_lstInfo->setCellColor(3, 1, Palette::blockOffset(13)+0);\n\n\t\t\tss.str(\"\");ss.clear();\n\t\t\tss << Unicode::formatPercentage(facility->getHitRatio());\n\t\t\t_lstInfo->addRow(2, tr(\"STR_HIT_RATIO\").c_str(), ss.str().c_str());\n\t\t\t_lstInfo->setCellColor(4, 1, Palette::blockOffset(13)+0);\n\t\t}\n\t\tcenterAllSurfaces();\n\t}\n\n\tArticleStateBaseFacility::~ArticleStateBaseFacility()\n\t{}\n\n}\n"
  },
  {
    "path": "src/Ufopaedia/ArticleStateBaseFacility.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ArticleState.h\"\n\nnamespace OpenXcom\n{\n\tclass Game;\n\tclass Surface;\n\tclass Text;\n\tclass TextList;\n\tclass ArticleDefinitionBaseFacility;\n\n\t/**\n\t * ArticleStateBaseFacility has a caption, text, preview image and a stats block.\n\t * The facility image is found using the RuleBasefacility class.\n\t */\n\n\tclass ArticleStateBaseFacility : public ArticleState\n\t{\n\tpublic:\n\t\tArticleStateBaseFacility(ArticleDefinitionBaseFacility *article_defs, std::shared_ptr<ArticleCommonState> state);\n\t\tvirtual ~ArticleStateBaseFacility();\n\n\tprotected:\n\t\tSurface *_image;\n\t\tText *_txtTitle;\n\t\tText *_txtInfo;\n\t\tTextList *_lstInfo;\n\t};\n}\n"
  },
  {
    "path": "src/Ufopaedia/ArticleStateCraft.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include <sstream>\n#include \"ArticleStateCraft.h\"\n#include \"../Mod/ArticleDefinition.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleCraft.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Palette.h\"\n#include \"../Engine/Surface.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n\nnamespace OpenXcom\n{\n\n\tArticleStateCraft::ArticleStateCraft(ArticleDefinitionCraft *defs, std::shared_ptr<ArticleCommonState> state) : ArticleState(defs->id, std::move(state))\n\t{\n\t\tRuleCraft *craft = _game->getMod()->getCraft(defs->id, true);\n\n\t\t// add screen elements\n\t\t_txtTitle = new Text(210, 32, 5, 24);\n\n\t\t// Set palette\n\t\tif (defs->customPalette)\n\t\t{\n\t\t\tsetCustomPalette(_game->getMod()->getSurface(defs->image_id)->getPalette(), Mod::UFOPAEDIA_CURSOR);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tsetStandardPalette(\"PAL_UFOPAEDIA\");\n\t\t}\n\n\t\tArticleState::initLayout();\n\n\t\t// add other elements\n\t\tadd(_txtTitle);\n\n\t\t// Set up objects\n\t\t_game->getMod()->getSurface(defs->image_id)->blitNShade(_bg, 0, 0);\n\t\t_btnOk->setColor(Palette::blockOffset(15)-1);\n\t\t_btnPrev->setColor(Palette::blockOffset(15)-1);\n\t\t_btnNext->setColor(Palette::blockOffset(15)-1);\n\t\t_btnInfo->setColor(Palette::blockOffset(15)-1);\n\t\t_btnInfo->setVisible(_game->getMod()->getShowPediaInfoButton());\n\n\t\t_txtTitle->setColor(Palette::blockOffset(14)+15);\n\t\t_txtTitle->setBig();\n\t\t_txtTitle->setWordWrap(true);\n\t\t_txtTitle->setText(tr(defs->getTitleForPage(_state->current_page)));\n\n\t\t_txtInfo = new Text(defs->rect_text.width, defs->rect_text.height, defs->rect_text.x, defs->rect_text.y);\n\t\tadd(_txtInfo);\n\n\t\t_txtInfo->setColor(Palette::blockOffset(14)+15);\n\t\t_txtInfo->setSecondaryColor(Palette::blockOffset(15) + 4);\n\t\t_txtInfo->setWordWrap(true);\n\t\t_txtInfo->setScrollable(true);\n\t\t_txtInfo->setText(tr(defs->getTextForPage(_state->current_page)));\n\n\t\t_txtStats = new Text(defs->rect_stats.width, defs->rect_stats.height, defs->rect_stats.x, defs->rect_stats.y);\n\t\tadd(_txtStats);\n\n\t\t_txtStats->setColor(Palette::blockOffset(14)+15);\n\t\t_txtStats->setSecondaryColor(Palette::blockOffset(15)+4);\n\n\t\tstd::ostringstream ss;\n\t\tss << tr(\"STR_MAXIMUM_SPEED_UC\").arg(Unicode::formatNumber(craft->getMaxSpeed())) << '\\n';\n\t\tss << tr(\"STR_ACCELERATION\").arg(craft->getAcceleration()) << '\\n';\n\t\tint range;\n\t\tswitch (_game->getMod()->getPediaReplaceCraftFuelWithRangeType())\n\t\t{\n\t\t\t// Both max range alone and average range get rounded\n\t\t\tcase 0:\n\t\t\tcase 2:\n\t\t\t\trange = craft->calculateRange(_game->getMod()->getPediaReplaceCraftFuelWithRangeType());\n\t\t\t\tif (range == -1)\n\t\t\t\t{\n\t\t\t\t\tss << tr(\"STR_MAXIMUM_RANGE\").arg(tr(\"STR_INFINITE_RANGE\")) << '\\n';\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t// Round the answer to\n\t\t\t\tif (range < 100)\n\t\t\t\t{\n\t\t\t\t\t// don't round if it's small!\n\t\t\t\t}\n\t\t\t\telse if (range < 1000)\n\t\t\t\t{\n\t\t\t\t\t// nearest 10 nautical miles\n\t\t\t\t\trange += 10 / 2;\n\t\t\t\t\trange -= range % 10;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// nearest 100 nautical miles\n\t\t\t\t\trange += 100 / 2;\n\t\t\t\t\trange -= range % 100;\n\t\t\t\t}\n\n\t\t\t\tss << tr(\"STR_MAXIMUM_RANGE\").arg(Unicode::formatNumber(range)) << '\\n';\n\t\t\t\tbreak;\n\t\t\t// Min-maxxers can fret over exact numbers\n\t\t\tcase 1:\n\t\t\t\tif (craft->calculateRange(0) == -1)\n\t\t\t\t{\n\t\t\t\t\tss << tr(\"STR_MAXIMUM_RANGE\").arg(tr(\"STR_INFINITE_RANGE\")) << '\\n';\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tss << tr(\"STR_MINIMUM_RANGE\").arg(Unicode::formatNumber(craft->calculateRange(1))) << '\\n';\n\t\t\t\tss << tr(\"STR_MAXIMUM_RANGE\").arg(Unicode::formatNumber(craft->calculateRange(0))) << '\\n';\n\t\t\t\tbreak;\n\t\t\tdefault :\n\t\t\t\tss << tr(\"STR_FUEL_CAPACITY\").arg(Unicode::formatNumber(craft->getMaxFuel())) << '\\n';\n\t\t\t\tbreak;\n\t\t}\n\t\tss << tr(\"STR_WEAPON_PODS\").arg(craft->getWeapons()) << '\\n';\n\t\tss << tr(\"STR_DAMAGE_CAPACITY_UC\").arg(Unicode::formatNumber(craft->getMaxDamage())) << '\\n';\n\t\tif (craft->getMaxUnits() == craft->getMaxUnitsLimit())\n\t\t{\n\t\t\tss << tr(\"STR_CARGO_SPACE\").arg(craft->getMaxUnits()) << '\\n';\n\t\t}\n\t\telse\n\t\t{\n\t\t\tstd::ostringstream ss2;\n\t\t\tss2 << craft->getMaxUnits() << \"/\" << craft->getMaxUnitsLimit();\n\t\t\tss << tr(\"STR_CARGO_SPACE\").arg(ss2.str()) << '\\n';\n\t\t}\n\t\tif (craft->getPilots() > 0)\n\t\t{\n\t\t\tss << tr(\"STR_COCKPIT_CAPACITY\").arg(craft->getPilots()) << '\\n';\n\t\t}\n\t\tif (craft->getMaxVehiclesAndLargeSoldiers() == craft->getMaxVehiclesAndLargeSoldiersLimit())\n\t\t{\n\t\t\tss << tr(\"STR_HWP_CAPACITY\").arg(craft->getMaxVehiclesAndLargeSoldiers());\n\t\t}\n\t\telse\n\t\t{\n\t\t\tstd::ostringstream ss2;\n\t\t\tss2 << craft->getMaxVehiclesAndLargeSoldiers() << \"/\" << craft->getMaxVehiclesAndLargeSoldiersLimit();\n\t\t\tss << tr(\"STR_HWP_CAPACITY\").arg(ss2.str());\n\t\t}\n\t\t_txtStats->setText(ss.str());\n\n\t\tcenterAllSurfaces();\n\t}\n\n\tArticleStateCraft::~ArticleStateCraft()\n\t{}\n\n}\n"
  },
  {
    "path": "src/Ufopaedia/ArticleStateCraft.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ArticleState.h\"\n\nnamespace OpenXcom\n{\n\tclass Game;\n\tclass Text;\n\tclass ArticleDefinitionCraft;\n\n\t/**\n\t * ArticleStateCraft has a caption, text, background image and a stats block.\n\t * The layout of the description text and stats block can vary,\n\t * depending on the background craft image.\n\t */\n\n\tclass ArticleStateCraft : public ArticleState\n\t{\n\tpublic:\n\t\tArticleStateCraft(ArticleDefinitionCraft *article_defs, std::shared_ptr<ArticleCommonState> state);\n\t\tvirtual ~ArticleStateCraft();\n\n\tprotected:\n\t\tText *_txtTitle;\n\t\tText *_txtInfo;\n\t\tText *_txtStats;\n\t};\n}\n"
  },
  {
    "path": "src/Ufopaedia/ArticleStateCraftWeapon.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"ArticleStateCraftWeapon.h\"\n#include \"../Mod/ArticleDefinition.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleCraftWeapon.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Surface.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Mod/RuleInterface.h\"\n\nnamespace OpenXcom\n{\n\n\tArticleStateCraftWeapon::ArticleStateCraftWeapon(ArticleDefinitionCraftWeapon *defs, std::shared_ptr<ArticleCommonState> state) : ArticleState(defs->id, std::move(state))\n\t{\n\t\tRuleCraftWeapon *weapon = _game->getMod()->getCraftWeapon(defs->id, true);\n\n\t\tCraftWeaponCategory category = CWC_WEAPON;\n\t\tint offset = 0;\n\t\tif (weapon->getHidePediaInfo())\n\t\t{\n\t\t\tif (weapon->getTractorBeamPower() > 0)\n\t\t\t{\n\t\t\t\tcategory = CWC_TRACTOR_BEAM;\n\t\t\t\toffset = 32; // 2 * 16\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tcategory = CWC_EQUIPMENT;\n\t\t\t\toffset = 80; // 5 * 16\n\t\t\t}\n\t\t}\n\n\t\t// add screen elements\n\t\t_txtTitle = new Text(200, 32, 5, 24);\n\n\t\t// Set palette\n\t\tif (defs->customPalette)\n\t\t{\n\t\t\tsetCustomPalette(_game->getMod()->getSurface(defs->image_id)->getPalette(), Mod::BATTLESCAPE_CURSOR);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tsetStandardPalette(\"PAL_BATTLEPEDIA\");\n\t\t}\n\n\t\t_buttonColor = _game->getMod()->getInterface(\"articleCraftWeapon\")->getElement(\"button\")->color;\n\t\t_textColor = _game->getMod()->getInterface(\"articleCraftWeapon\")->getElement(\"text\")->color;\n\t\t_textColor2 = _game->getMod()->getInterface(\"articleCraftWeapon\")->getElement(\"text\")->color2;\n\t\t_listColor1 = _game->getMod()->getInterface(\"articleCraftWeapon\")->getElement(\"list\")->color;\n\t\t_listColor2 = _game->getMod()->getInterface(\"articleCraftWeapon\")->getElement(\"list\")->color2;\n\n\t\tArticleState::initLayout();\n\n\t\t// add other elements\n\t\tadd(_txtTitle);\n\n\t\t// Set up objects\n\t\t_game->getMod()->getSurface(defs->image_id)->blitNShade(_bg, 0, 0);\n\t\t_btnOk->setColor(_buttonColor);\n\t\t_btnPrev->setColor(_buttonColor);\n\t\t_btnNext->setColor(_buttonColor);\n\t\t_btnInfo->setColor(_buttonColor);\n\t\t_btnInfo->setVisible(_game->getMod()->getShowPediaInfoButton());\n\n\t\t_txtTitle->setColor(_textColor);\n\t\t_txtTitle->setBig();\n\t\t_txtTitle->setWordWrap(true);\n\t\t_txtTitle->setText(tr(defs->getTitleForPage(_state->current_page)));\n\n\t\t_txtInfo = new Text(310, 32 + offset, 5, 160 - offset);\n\t\tadd(_txtInfo);\n\n\t\t_txtInfo->setColor(_textColor);\n\t\t_txtInfo->setSecondaryColor(_textColor2);\n\t\t_txtInfo->setWordWrap(true);\n\t\t_txtInfo->setScrollable(true);\n\t\t_txtInfo->setText(tr(defs->getTextForPage(_state->current_page)));\n\n\t\t_lstInfo = new TextList(250, 111 - offset, 5, 80);\n\t\tadd(_lstInfo);\n\t\t_lstInfo->setVisible(category != CWC_EQUIPMENT);\n\n\t\t_lstInfo->setColor(_listColor1);\n\t\t_lstInfo->setColumns(2, 180, 70);\n\t\t_lstInfo->setDot(true);\n\t\t_lstInfo->setBig();\n\n\t\tif (category == CWC_WEAPON)\n\t\t{\n\t\t\t_lstInfo->addRow(2, tr(\"STR_DAMAGE\").c_str(), Unicode::formatNumber(weapon->getDamage()).c_str());\n\t\t\t_lstInfo->setCellColor(0, 1, _listColor2);\n\n\t\t\t_lstInfo->addRow(2, tr(\"STR_RANGE\").c_str(), tr(\"STR_KILOMETERS\").arg(weapon->getRange()).c_str());\n\t\t\t_lstInfo->setCellColor(1, 1, _listColor2);\n\n\t\t\t_lstInfo->addRow(2, tr(\"STR_ACCURACY\").c_str(), Unicode::formatPercentage(weapon->getAccuracy()).c_str());\n\t\t\t_lstInfo->setCellColor(2, 1, _listColor2);\n\n\t\t\t_lstInfo->addRow(2, tr(\"STR_RE_LOAD_TIME\").c_str(), tr(\"STR_SECONDS\").arg(weapon->getStandardReload()).c_str());\n\t\t\t_lstInfo->setCellColor(3, 1, _listColor2);\n\n\t\t\t_lstInfo->addRow(2, tr(\"STR_ROUNDS\").c_str(), Unicode::formatNumber(weapon->getAmmoMax()).c_str());\n\t\t\t_lstInfo->setCellColor(4, 1, _listColor2);\n\t\t}\n\t\telse if (category == CWC_TRACTOR_BEAM)\n\t\t{\n\t\t\t_lstInfo->addRow(2, tr(\"STR_TRACTOR_BEAM_POWER\").c_str(), Unicode::formatNumber(weapon->getTractorBeamPower()).c_str());\n\t\t\t_lstInfo->setCellColor(0, 1, _listColor2);\n\n\t\t\t_lstInfo->addRow(2, tr(\"STR_RANGE\").c_str(), tr(\"STR_KILOMETERS\").arg(weapon->getRange()).c_str());\n\t\t\t_lstInfo->setCellColor(1, 1, _listColor2);\n\t\t}\n\n\t\tcenterAllSurfaces();\n\t}\n\n\tArticleStateCraftWeapon::~ArticleStateCraftWeapon()\n\t{}\n\n}\n"
  },
  {
    "path": "src/Ufopaedia/ArticleStateCraftWeapon.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ArticleState.h\"\n\nnamespace OpenXcom\n{\n\tclass Game;\n\tclass Text;\n\tclass TextList;\n\tclass ArticleDefinitionCraftWeapon;\n\n\t/**\n\t * ArticleStateCraftWeapon has a caption, background image and a stats block.\n\t */\n\n\tclass ArticleStateCraftWeapon : public ArticleState\n\t{\n\tpublic:\n\t\tArticleStateCraftWeapon(ArticleDefinitionCraftWeapon *article_defs, std::shared_ptr<ArticleCommonState> state);\n\t\tvirtual ~ArticleStateCraftWeapon();\n\n\tprotected:\n\t\tText *_txtTitle;\n\t\tText *_txtInfo;\n\t\tTextList *_lstInfo;\n\t\tUint8 _buttonColor, _textColor, _textColor2, _listColor1, _listColor2;\n\t};\n}\n"
  },
  {
    "path": "src/Ufopaedia/ArticleStateItem.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include <sstream>\n#include <algorithm>\n#include \"Ufopaedia.h\"\n#include \"ArticleStateItem.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/ArticleDefinition.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Surface.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Interface/NumberText.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Mod/RuleInterface.h\"\n#include \"../fmath.h\"\n#include \"StatsForNerdsState.h\"\n\nnamespace OpenXcom\n{\n\n\tArticleStateItem::ArticleStateItem(ArticleDefinitionItem *defs, std::shared_ptr<ArticleCommonState> state) : ArticleState(defs->id, std::move(state))\n\t{\n\t\tRuleItem *item = _game->getMod()->getItem(defs->weapon, false);\n\t\tif (!item)\n\t\t{\n\t\t\titem = _game->getMod()->getItem(defs->id, true);\n\t\t}\n\n\t\tint bottomOffset = 20;\n\t\tstd::string accuracyModifier;\n\t\tbool isAccurracyModded = false;\n\t\tif (item->getBattleType() == BT_MELEE)\n\t\t{\n\t\t\taccuracyModifier = addRuleStatBonus(*item->getMeleeMultiplierRaw());\n\t\t\tisAccurracyModded = item->getMeleeMultiplierRaw()->isModded();\n\t\t}\n\t\telse\n\t\t{\n\t\t\taccuracyModifier = addRuleStatBonus(*item->getAccuracyMultiplierRaw());\n\t\t\tisAccurracyModded = item->getAccuracyMultiplierRaw()->isModded();\n\t\t}\n\t\tstd::string powerBonus = addRuleStatBonus(*item->getDamageBonusRaw());\n\n\t\tif (!isAccurracyModded)\n\t\t{\n\t\t\t// don't show default accuracy multiplier\n\t\t\tbottomOffset = 9;\n\t\t}\n\n\t\tif (_game->getMod()->getExtraNerdyPediaInfoType() == 0)\n\t\t{\n\t\t\t// feature turned off\n\t\t\tbottomOffset = 0;\n\t\t}\n\t\telse if (item->getBattleType() == BT_AMMO)\n\t\t{\n\t\t\t// don't show accuracy multiplier... even if someone mods it by mistake, it still makes no sense\n\t\t\tbottomOffset = 9;\n\t\t}\n\t\telse if (item->getBattleType() == BT_FIREARM || item->getBattleType() == BT_MELEE)\n\t\t{\n\t\t\tif (item->getClipSize() != 0 || item->getIgnoreAmmoPower())\n\t\t\t{\n\t\t\t\t// correct info loaded already... weapon has built-in ammo or ignores ammo power bonuses\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// need to check power bonus on all compatible ammo\n\t\t\t\tbool first = true;\n\t\t\t\tbool allSame = true;\n\t\t\t\tfor (int slot = 0; slot < RuleItem::AmmoSlotMax; ++slot)\n\t\t\t\t{\n\t\t\t\t\tfor (auto* ammoItemRule : *item->getCompatibleAmmoForSlot(slot))\n\t\t\t\t\t{\n\t\t\t\t\t\tif (first)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tpowerBonus = addRuleStatBonus(*ammoItemRule->getDamageBonusRaw());\n\t\t\t\t\t\t\tfirst = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tstd::string otherPowerBonus = addRuleStatBonus(*ammoItemRule->getDamageBonusRaw());\n\t\t\t\t\t\t\tif (powerBonus != otherPowerBonus)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tallSame = false;\n\t\t\t\t\t\t\t\tpowerBonus = tr(\"STR_MULTIPLE_DIFFERENT_BONUSES\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!allSame) break;\n\t\t\t\t\t}\n\t\t\t\t\tif (!allSame) break;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse if (item->getBattleType() == BT_PSIAMP)\n\t\t{\n\t\t\t// correct info loaded already\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// nothing to show for other item types\n\t\t\tbottomOffset = 0;\n\t\t}\n\n\t\tif (powerBonus.empty())\n\t\t{\n\t\t\tif (!isAccurracyModded)\n\t\t\t{\n\t\t\t\t// both power bonus and accuracy multiplier are vanilla, hide info completely\n\t\t\t\tbottomOffset = 0;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// display zero instead of empty string\n\t\t\t\tpowerBonus = \"0\";\n\t\t\t}\n\t\t}\n\n\t\t// add screen elements\n\t\t_txtTitle = new Text(148, 32, 5, 24);\n\t\t_txtWeight = new Text(88, 8, 104, 55);\n\n\t\t// Set palette\n\t\tsetStandardPalette(\"PAL_BATTLEPEDIA\");\n\n\t\t_buttonColor = _game->getMod()->getInterface(\"articleItem\")->getElement(\"button\")->color;\n\t\t_arrowColor = _buttonColor;\n\t\tif (_game->getMod()->getInterface(\"articleItem\")->getElementOptional(\"arrow\"))\n\t\t{\n\t\t\t_arrowColor = _game->getMod()->getInterface(\"articleItem\")->getElement(\"arrow\")->color;\n\t\t}\n\t\t_textColor = _game->getMod()->getInterface(\"articleItem\")->getElement(\"text\")->color;\n\t\t_textColor2 = _game->getMod()->getInterface(\"articleItem\")->getElement(\"text\")->color2;\n\t\t_listColor1 = _game->getMod()->getInterface(\"articleItem\")->getElement(\"list\")->color;\n\t\t_listColor2 = _game->getMod()->getInterface(\"articleItem\")->getElement(\"list\")->color2;\n\t\t_ammoColor = _game->getMod()->getInterface(\"articleItem\")->getElement(\"ammoColor\")->color;\n\n\t\tArticleState::initLayout();\n\n\t\t// add other elements\n\t\tadd(_txtTitle);\n\t\tadd(_txtWeight, \"weightText\", \"articleItem\", _bg);\n\n\t\t// Set up objects\n\t\t_game->getMod()->getSurface(\"BACK08.SCR\")->blitNShade(_bg, 0, 0);\n\t\t_btnOk->setColor(_buttonColor);\n\t\t_btnPrev->setColor(_buttonColor);\n\t\t_btnNext->setColor(_buttonColor);\n\t\t_btnInfo->setColor(_buttonColor);\n\t\t_btnInfo->setVisible(_game->getMod()->getShowPediaInfoButton());\n\n\t\t_txtTitle->setColor(_textColor);\n\t\t_txtTitle->setBig();\n\t\t_txtTitle->setWordWrap(true);\n\t\t_txtTitle->setText(tr(defs->getTitleForPage(_state->current_page)));\n\n\t\t_txtWeight->setColor(_textColor);\n\t\t_txtWeight->setAlign(ALIGN_RIGHT);\n\n\t\t// IMAGE\n\t\t_image = new Surface(32, 48, 157, 5);\n\t\tadd(_image, \"image\", \"articleItem\", _bg);\n\n\t\titem->drawHandSprite(_game->getMod()->getSurfaceSet(\"BIGOBS.PCK\"), _image);\n\n\t\t_txtWeaponClipSize = new NumberText(30, 5, 157, 5);\n\t\tadd(_txtWeaponClipSize, \"image\", \"articleItem\", _bg);\n\n\t\t_txtWeaponClipSize->setX(_txtWeaponClipSize->getX() + 2);\n\t\t_txtWeaponClipSize->setColor(_textColor);\n\t\t_txtWeaponClipSize->setValue(item->getClipSize());\n\t\t_txtWeaponClipSize->setVisible(Options::oxcePediaShowClipSize && item->getClipSize() > 0);\n\n\t\tint ammoSlot = defs->getAmmoSlotForPage(_state->current_page);\n\t\tint ammoSlotPrevUsage = defs->getAmmoSlotPrevUsageForPage(_state->current_page);\n\t\tconst std::vector<const RuleItem*> dummy;\n\t\tconst std::vector<const RuleItem*> *ammo_data = ammoSlot != RuleItem::AmmoSlotSelfUse ? item->getCompatibleAmmoForSlot(ammoSlot) : &dummy;\n\n\t\tint weight = item->getWeight();\n\t\tstd::string weightLabel = tr(\"STR_WEIGHT_PEDIA1\").arg(weight);\n\t\tif (!ammo_data->empty())\n\t\t{\n\t\t\t// Note: weight including primary ammo only!\n\t\t\tconst RuleItem *ammo_rule = (*ammo_data)[0];\n\t\t\tweightLabel = tr(\"STR_WEIGHT_PEDIA2\").arg(weight).arg(weight + ammo_rule->getWeight());\n\t\t}\n\t\t_txtWeight->setText(weight != 0 ? weightLabel : \"\");\n\n\t\t// SHOT STATS TABLE (for firearms and melee only)\n\t\tif (item->getBattleType() == BT_FIREARM || item->getBattleType() == BT_MELEE)\n\t\t{\n\t\t\t_txtShotType = new Text(100, 17, 8, 66);\n\t\t\tadd(_txtShotType);\n\t\t\t_txtShotType->setColor(_textColor);\n\t\t\t_txtShotType->setWordWrap(true);\n\t\t\t_txtShotType->setText(tr(\"STR_SHOT_TYPE\"));\n\n\t\t\t_txtAccuracy = new Text(50, 17, 104, 66);\n\t\t\tadd(_txtAccuracy);\n\t\t\t_txtAccuracy->setColor(_textColor);\n\t\t\t_txtAccuracy->setWordWrap(true);\n\t\t\t_txtAccuracy->setText(tr(\"STR_ACCURACY_UC\"));\n\n\t\t\t_txtTuCost = new Text(60, 17, 158, 66);\n\t\t\tadd(_txtTuCost);\n\t\t\t_txtTuCost->setColor(_textColor);\n\t\t\t_txtTuCost->setWordWrap(true);\n\t\t\t_txtTuCost->setText(tr(\"STR_TIME_UNIT_COST\"));\n\n\t\t\t_lstInfo = new TextList(204, 55, 8, 82);\n\t\t\tadd(_lstInfo);\n\n\t\t\t_lstInfo->setColor(_listColor2); // color for % data!\n\t\t\t_lstInfo->setColumns(3, 100, 52, 52);\n\t\t\t_lstInfo->setBig();\n\t\t}\n\n\t\tauto addAttack = [&](int& row, const std::string& name, const RuleItemUseCost& cost, const RuleItemUseFlat& flat, const RuleItemAction *config, const RuleItem *weapon)\n\t\t{\n\t\t\tif (row < 3 && cost.Time > 0 && config->ammoSlot == ammoSlot)\n\t\t\t{\n\t\t\t\tstd::string tu = Unicode::formatPercentage(cost.Time);\n\t\t\t\tif (flat.Time)\n\t\t\t\t{\n\t\t\t\t\ttu.erase(tu.end() - 1);\n\t\t\t\t}\n\t\t\t\tint range = std::min(config->range, weapon->getMaxRange());\n\t\t\t\tstd::string label = config->shortName.empty() ? tr(name).arg(config->shots).arg(range) : tr(config->shortName).arg(config->shots).arg(range);\n\t\t\t\t_lstInfo->addRow(3,\n\t\t\t\t\tlabel.c_str(),\n\t\t\t\t\tUnicode::formatPercentage(config->accuracy).c_str(),\n\t\t\t\t\ttu.c_str());\n\t\t\t\t_lstInfo->setCellColor(row, 0, _listColor1);\n\t\t\t\trow++;\n\t\t\t}\n\t\t};\n\n\t\tif (item->getBattleType() == BT_FIREARM)\n\t\t{\n\t\t\tint current_row = 0;\n\n\t\t\taddAttack(current_row, \"STR_SHOT_TYPE_AUTO\", item->getCostAuto(), item->getFlatAuto(), item->getConfigAuto(), item);\n\n\t\t\taddAttack(current_row, \"STR_SHOT_TYPE_SNAP\", item->getCostSnap(), item->getFlatSnap(), item->getConfigSnap(), item);\n\n\t\t\taddAttack(current_row, \"STR_SHOT_TYPE_AIMED\", item->getCostAimed(), item->getFlatAimed(), item->getConfigAimed(), item);\n\n\t\t\t//optional melee\n\t\t\taddAttack(current_row, \"STR_SHOT_TYPE_MELEE\", item->getCostMelee(), item->getFlatMelee(), item->getConfigMelee(), item);\n\n\t\t\t// text_info is BELOW the info table (table can have 0-3 rows)\n\t\t\tint shift = (3 - current_row) * 16;\n\t\t\tif (ammo_data->size() == 2 && current_row <= 1)\n\t\t\t{\n\t\t\t\tshift -= (2 - current_row) * 16;\n\t\t\t}\n\t\t\t_txtInfo = new Text((ammo_data->size()<3 ? 300 : 180), 56 + shift - bottomOffset, 8, 138 - shift);\n\t\t}\n\t\telse if (item->getBattleType() == BT_MELEE)\n\t\t{\n\t\t\tint current_row = 0;\n\n\t\t\taddAttack(current_row, \"STR_SHOT_TYPE_MELEE\", item->getCostMelee(), item->getFlatMelee(), item->getConfigMelee(), item);\n\n\t\t\t// text_info is BELOW the info table (with 1 row only)\n\t\t\t_txtInfo = new Text(300, 88 - bottomOffset, 8, 106);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// text_info is larger and starts on top\n\t\t\t_txtInfo = new Text(300, 125 - bottomOffset, 8, 67);\n\t\t}\n\n\t\tadd(_txtInfo);\n\n\t\t_txtInfo->setColor(_textColor);\n\t\t_txtInfo->setSecondaryColor(_textColor2);\n\t\t_txtInfo->setWordWrap(true);\n\t\t_txtInfo->setScrollable(true);\n\t\t_txtInfo->setText(tr(defs->getTextForPage(_state->current_page)));\n\n\t\t// STATS FOR NERDS extract\n\t\t_txtAccuracyModifier = new Text(300, 9, 8, 174);\n\t\t_txtPowerBonus = new Text(300, 17, 8, 183);\n\n\t\tadd(_txtAccuracyModifier);\n\t\tadd(_txtPowerBonus);\n\n\t\t_txtAccuracyModifier->setColor(_textColor);\n\t\t_txtAccuracyModifier->setSecondaryColor(_listColor2);\n\t\t_txtAccuracyModifier->setWordWrap(false);\n\t\t_txtAccuracyModifier->setText(tr(\"STR_ACCURACY_MODIFIER\").arg(accuracyModifier));\n\t\t_txtAccuracyModifier->setVisible(bottomOffset >= 20);\n\n\t\t_txtPowerBonus->setColor(_textColor);\n\t\t_txtPowerBonus->setSecondaryColor(_listColor2);\n\t\t_txtPowerBonus->setWordWrap(true);\n\t\t_txtPowerBonus->setText(tr(\"STR_POWER_BONUS\").arg(powerBonus));\n\t\t_txtPowerBonus->setVisible(bottomOffset > 0);\n\n\t\t// AMMO column\n\t\tstd::ostringstream ss;\n\n\t\tfor (int i = 0; i<3; ++i)\n\t\t{\n\t\t\t_txtAmmoType[i] = new Text(82, 16, 194, 20 + i*49);\n\t\t\tadd(_txtAmmoType[i]);\n\t\t\t_txtAmmoType[i]->setColor(_textColor);\n\t\t\t_txtAmmoType[i]->setAlign(ALIGN_CENTER);\n\t\t\t_txtAmmoType[i]->setVerticalAlign(ALIGN_MIDDLE);\n\t\t\t_txtAmmoType[i]->setWordWrap(true);\n\n\t\t\t_txtAmmoDamage[i] = new Text(82, 17, 194, 40 + i*49);\n\t\t\tadd(_txtAmmoDamage[i]);\n\t\t\t_txtAmmoDamage[i]->setColor(_ammoColor);\n\t\t\t_txtAmmoDamage[i]->setAlign(ALIGN_CENTER);\n\t\t\t_txtAmmoDamage[i]->setBig();\n\n\t\t\t_imageAmmo[i] = new Surface(32, 48, 280, 16 + i*49);\n\t\t\tadd(_imageAmmo[i]);\n\n\t\t\t_txtAmmoClipSize[i] = new NumberText(30, 5, 2 + 280, 2 + 16 + i*49);\n\t\t\tadd(_txtAmmoClipSize[i]);\n\t\t\t_txtAmmoClipSize[i]->setColor(_textColor);\n\t\t\t_txtAmmoClipSize[i]->setVisible(false);\n\t\t}\n\n\t\tauto addAmmoDamagePower = [&](int pos, const RuleItem *rule, const RuleItem* weaponRule)\n\t\t{\n\t\t\t_txtAmmoType[pos]->setText(tr(getDamageTypeText(rule->getDamageType()->ResistType)));\n\n\t\t\tss.str(\"\");ss.clear();\n\t\t\tif (weaponRule->getIgnoreAmmoPower())\n\t\t\t{\n\t\t\t\tss << weaponRule->getPower();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tss << rule->getPower();\n\t\t\t}\n\t\t\tif (rule->getShotgunPellets())\n\t\t\t{\n\t\t\t\tss << \"x\" << rule->getShotgunPellets();\n\t\t\t}\n\t\t\t_txtAmmoDamage[pos]->setText(ss.str());\n\t\t\t_txtAmmoDamage[pos]->setColor(getDamageTypeTextColor(rule->getDamageType()->ResistType));\n\t\t};\n\n\t\tswitch (item->getBattleType())\n\t\t{\n\t\t\tcase BT_FIREARM:\n\t\t\t\tif (item->getHidePower()) break;\n\t\t\t\t_txtDamage = new Text(82, 10, 194, 7);\n\t\t\t\tadd(_txtDamage);\n\t\t\t\t_txtDamage->setColor(_textColor);\n\t\t\t\t_txtDamage->setAlign(ALIGN_CENTER);\n\t\t\t\t_txtDamage->setText(tr(\"STR_DAMAGE_UC\"));\n\n\t\t\t\t_txtAmmo = new Text(50, 10, 268, 7);\n\t\t\t\tadd(_txtAmmo);\n\t\t\t\t_txtAmmo->setColor(_textColor);\n\t\t\t\t_txtAmmo->setAlign(ALIGN_CENTER);\n\t\t\t\t_txtAmmo->setText(tr(\"STR_AMMO\"));\n\n\t\t\t\tif (ammo_data->empty())\n\t\t\t\t{\n\t\t\t\t\taddAmmoDamagePower(0, item, item);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tint maxShow = 3;\n\t\t\t\t\tint skipShow = maxShow * ammoSlotPrevUsage;\n\t\t\t\t\tint currShow = 0;\n\t\t\t\t\tfor (auto* type : *ammo_data)\n\t\t\t\t\t{\n\t\t\t\t\t\tArticleDefinition *ammo_article = _game->getMod()->getUfopaediaArticle(type->getType(), true);\n\t\t\t\t\t\tif (Ufopaedia::isArticleAvailable(_game->getSavedGame(), ammo_article))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (skipShow > 0)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t--skipShow;\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\taddAmmoDamagePower(currShow, type, item);\n\n\t\t\t\t\t\t\ttype->drawHandSprite(_game->getMod()->getSurfaceSet(\"BIGOBS.PCK\"), _imageAmmo[currShow]);\n\t\t\t\t\t\t\t_txtAmmoClipSize[currShow]->setValue(type->getClipSize());\n\t\t\t\t\t\t\t_txtAmmoClipSize[currShow]->setVisible(Options::oxcePediaShowClipSize && type->getClipSize() > 0);\n\n\t\t\t\t\t\t\t++currShow;\n\t\t\t\t\t\t\tif (currShow == maxShow)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase BT_AMMO:\n\t\t\tcase BT_GRENADE:\n\t\t\tcase BT_PROXIMITYGRENADE:\n\t\t\tcase BT_MELEE:\n\t\t\t\tif (item->getHidePower()) break;\n\t\t\t\t_txtDamage = new Text(82, 10, 194, 7);\n\t\t\t\tadd(_txtDamage);\n\t\t\t\t_txtDamage->setColor(_textColor);\n\t\t\t\t_txtDamage->setAlign(ALIGN_CENTER);\n\t\t\t\t_txtDamage->setText(tr(\"STR_DAMAGE_UC\"));\n\n\t\t\t\taddAmmoDamagePower(0, item, item);\n\t\t\t\tbreak;\n\t\t\tdefault: break;\n\t\t}\n\n\t\t// multi-page indicator\n\t\t_txtArrows = new Text(32, 9, 280, 183);\n\t\tadd(_txtArrows);\n\t\t_txtArrows->setColor(_arrowColor);\n\t\t_txtArrows->setAlign(ALIGN_RIGHT);\n\t\tstd::ostringstream ss2;\n\t\tif (_state->hasPrevArticlePage()) ss2 << \"<<\";\n\t\tif (_state->hasNextArticlePage()) ss2 << \" >>\";\n\t\t_txtArrows->setText(ss2.str());\n\n\t\tcenterAllSurfaces();\n\t}\n\n\tArticleStateItem::~ArticleStateItem()\n\t{}\n\n\tstd::string ArticleStateItem::addRuleStatBonus(const RuleStatBonus &value)\n\t{\n\t\tstd::ostringstream ss;\n\t\tbool isFirst = true;\n\t\tfor (const auto& item : *value.getBonusRaw())\n\t\t{\n\t\t\tint power = 0;\n\t\t\tfor (float number : item.second)\n\t\t\t{\n\t\t\t\t++power;\n\t\t\t\tif (!AreSame(number, 0.0f))\n\t\t\t\t{\n\t\t\t\t\tfloat numberAbs = number;\n\t\t\t\t\tif (!isFirst)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (number > 0.0f)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tss << \" + \";\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tss << \" - \";\n\t\t\t\t\t\t\tnumberAbs = std::abs(number);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (item.first == \"flatOne\")\n\t\t\t\t\t{\n\t\t\t\t\t\tss << numberAbs * 1;\n\t\t\t\t\t}\n\t\t\t\t\tif (item.first == \"flatHundred\")\n\t\t\t\t\t{\n\t\t\t\t\t\tss << numberAbs * pow(100, power);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tif (!AreSame(numberAbs, 1.0f))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tss << numberAbs << \"*\";\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (_game->getMod()->getExtraNerdyPediaInfoType() > 1)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tss << tr(StatsForNerdsState::shortTranslationMap.at(item.first));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tss << tr(StatsForNerdsState::translationMap.at(item.first));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (power > 1)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tss << \"^\" << power;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tisFirst = false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn ss.str();\n\t}\n\n\tint ArticleStateItem::getDamageTypeTextColor(ItemDamageType dt)\n\t{\n\t\tconst Element *interfaceElement = 0;\n\t\tint color = _ammoColor;\n\n\t\tswitch (dt)\n\t\t{\n\t\t\tcase DT_NONE:\n\t\t\t\tinterfaceElement = _game->getMod()->getInterface(\"articleItem\")->getElementOptional(\"ammoColorDTNone\");\n\t\t\t\tbreak;\n\n\t\t\tcase DT_AP:\n\t\t\t\tinterfaceElement = _game->getMod()->getInterface(\"articleItem\")->getElementOptional(\"ammoColorDTAP\");\n\t\t\t\tbreak;\n\n\t\t\tcase DT_IN:\n\t\t\t\tinterfaceElement = _game->getMod()->getInterface(\"articleItem\")->getElementOptional(\"ammoColorDTIN\");\n\t\t\t\tbreak;\n\n\t\t\tcase DT_HE:\n\t\t\t\tinterfaceElement = _game->getMod()->getInterface(\"articleItem\")->getElementOptional(\"ammoColorDTHE\");\n\t\t\t\tbreak;\n\n\t\t\tcase DT_LASER:\n\t\t\t\tinterfaceElement = _game->getMod()->getInterface(\"articleItem\")->getElementOptional(\"ammoColorDTLaser\");\n\t\t\t\tbreak;\n\n\t\t\tcase DT_PLASMA:\n\t\t\t\tinterfaceElement = _game->getMod()->getInterface(\"articleItem\")->getElementOptional(\"ammoColorDTPlasma\");\n\t\t\t\tbreak;\n\n\t\t\tcase DT_STUN:\n\t\t\t\tinterfaceElement = _game->getMod()->getInterface(\"articleItem\")->getElementOptional(\"ammoColorDTStun\");\n\t\t\t\tbreak;\n\n\t\t\tcase DT_MELEE:\n\t\t\t\tinterfaceElement = _game->getMod()->getInterface(\"articleItem\")->getElementOptional(\"ammoColorDTMelee\");\n\t\t\t\tbreak;\n\n\t\t\tcase DT_ACID:\n\t\t\t\tinterfaceElement = _game->getMod()->getInterface(\"articleItem\")->getElementOptional(\"ammoColorDTAcid\");\n\t\t\t\tbreak;\n\n\t\t\tcase DT_SMOKE:\n\t\t\t\tinterfaceElement = _game->getMod()->getInterface(\"articleItem\")->getElementOptional(\"ammoColorDTSmoke\");\n\t\t\t\tbreak;\n\n\t\t\tcase DT_10:\n\t\t\t\tinterfaceElement = _game->getMod()->getInterface(\"articleItem\")->getElementOptional(\"ammoColorDT10\");\n\t\t\t\tbreak;\n\n\t\t\tcase DT_11:\n\t\t\t\tinterfaceElement = _game->getMod()->getInterface(\"articleItem\")->getElementOptional(\"ammoColorDT11\");\n\t\t\t\tbreak;\n\n\t\t\tcase DT_12:\n\t\t\t\tinterfaceElement = _game->getMod()->getInterface(\"articleItem\")->getElementOptional(\"ammoColorDT12\");\n\t\t\t\tbreak;\n\n\t\t\tcase DT_13:\n\t\t\t\tinterfaceElement = _game->getMod()->getInterface(\"articleItem\")->getElementOptional(\"ammoColorDT13\");\n\t\t\t\tbreak;\n\n\t\t\tcase DT_14:\n\t\t\t\tinterfaceElement = _game->getMod()->getInterface(\"articleItem\")->getElementOptional(\"ammoColorDT14\");\n\t\t\t\tbreak;\n\n\t\t\tcase DT_15:\n\t\t\t\tinterfaceElement = _game->getMod()->getInterface(\"articleItem\")->getElementOptional(\"ammoColorDT15\");\n\t\t\t\tbreak;\n\n\t\t\tcase DT_16:\n\t\t\t\tinterfaceElement = _game->getMod()->getInterface(\"articleItem\")->getElementOptional(\"ammoColorDT16\");\n\t\t\t\tbreak;\n\n\t\t\tcase DT_17:\n\t\t\t\tinterfaceElement = _game->getMod()->getInterface(\"articleItem\")->getElementOptional(\"ammoColorDT17\");\n\t\t\t\tbreak;\n\n\t\t\tcase DT_18:\n\t\t\t\tinterfaceElement = _game->getMod()->getInterface(\"articleItem\")->getElementOptional(\"ammoColorDT18\");\n\t\t\t\tbreak;\n\n\t\t\tcase DT_19:\n\t\t\t\tinterfaceElement = _game->getMod()->getInterface(\"articleItem\")->getElementOptional(\"ammoColorDT19\");\n\t\t\t\tbreak;\n\n\t\t\tdefault :\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif (interfaceElement)\n\t\t{\n\t\t\tcolor = interfaceElement->color;\n\t\t}\n\n\t\treturn color;\n\t}\n}\n"
  },
  {
    "path": "src/Ufopaedia/ArticleStateItem.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ArticleState.h\"\n\nnamespace OpenXcom\n{\n\tclass Game;\n\tclass Surface;\n\tclass NumberText;\n\tclass Text;\n\tclass TextList;\n\tclass ArticleDefinitionItem;\n\n\t/**\n\t * ArticleStateItem has a caption, text, preview image and a stats block.\n\t * The facility image is found using the RuleBasefacility class.\n\t */\n\n\tclass ArticleStateItem : public ArticleState\n\t{\n\tpublic:\n\t\tArticleStateItem(ArticleDefinitionItem *article_defs, std::shared_ptr<ArticleCommonState> state);\n\t\tvirtual ~ArticleStateItem();\n\n\tprotected:\n\t\tSurface *_image;\n\t\tNumberText *_txtWeaponClipSize;\n\t\tText *_txtTitle;\n\t\tText *_txtWeight;\n\t\tText *_txtInfo;\n\t\tText *_txtAccuracyModifier;\n\t\tText *_txtPowerBonus;\n\t\tTextList *_lstInfo;\n\t\tText *_txtShotType;\n\t\tText *_txtAccuracy;\n\t\tText *_txtTuCost;\n\t\tText *_txtDamage;\n\t\tText *_txtAmmo;\n\t\tText *_txtAmmoType[3];\n\t\tText *_txtAmmoDamage[3];\n\t\tSurface *_imageAmmo[3];\n\t\tNumberText *_txtAmmoClipSize[3];\n\t\tText * _txtArrows;\n\t\tUint8 _buttonColor, _textColor, _textColor2, _listColor1, _listColor2, _ammoColor, _arrowColor;\n\t\tstd::string addRuleStatBonus(const RuleStatBonus &value);\n\t\tint getDamageTypeTextColor(ItemDamageType dt);\n\t};\n}\n"
  },
  {
    "path": "src/Ufopaedia/ArticleStateSoldier.cpp",
    "content": "/*\n * Copyright 2010-2025 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include <sstream>\n#include \"ArticleStateSoldier.h\"\n#include \"../Mod/ArticleDefinition.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleSoldier.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Palette.h\"\n#include \"../Engine/Surface.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Mod/RuleInterface.h\"\n#include \"../fmath.h\"\n\nnamespace OpenXcom\n{\n\n\tArticleStateSoldier::ArticleStateSoldier(ArticleDefinitionSoldier *defs, std::shared_ptr<ArticleCommonState> state) : ArticleState(defs->id, std::move(state))\n\t{\n\t\tconst RuleSoldier *soldier = _game->getMod()->getSoldier(defs->id, true);\n\n\t\t// add screen elements\n\t\t_txtTitle = new Text(310, 17, 5, 23);\n\n\t\t// Set palette\n\t\tif (defs->customPalette)\n\t\t{\n\t\t\tsetCustomPalette(_game->getMod()->getSurface(defs->image_id)->getPalette(), Mod::UFOPAEDIA_CURSOR);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tsetStandardPalette(\"PAL_UFOPAEDIA\");\n\t\t}\n\n\t\tRuleInterface* itf = _game->getMod()->getInterface(\"articleSoldier\");\n\t\tint buttonColor = itf->getElement(\"button\")->color;\n\t\tint titleColor1 = itf->getElement(\"title\")->color;\n\t\tint titleColor2 = itf->getElement(\"title\")->color2;\n\t\tint textColor1 = itf->getElement(\"text\")->color;\n\t\tint textColor2 = itf->getElement(\"text\")->color2;\n\t\tint listColor1 = itf->getElement(\"list\")->color;\n\t\tint listColor2 = itf->getElement(\"list\")->color2;\n\n\t\tArticleState::initLayout();\n\n\t\t// add other elements\n\t\tadd(_txtTitle);\n\n\t\t// Set up objects\n\t\t_game->getMod()->getSurface(defs->image_id)->blitNShade(_bg, 0, 0);\n\t\t_btnOk->setColor(buttonColor);\n\t\t_btnPrev->setColor(buttonColor);\n\t\t_btnNext->setColor(buttonColor);\n\t\t_btnInfo->setColor(buttonColor);\n\t\t_btnInfo->setVisible(_game->getMod()->getShowPediaInfoButton());\n\n\t\t_txtTitle->setColor(titleColor1);\n\t\t_txtTitle->setSecondaryColor(titleColor2);\n\t\t_txtTitle->setBig();\n\t\t_txtTitle->setWordWrap(true);\n\t\t_txtTitle->setText(tr(defs->getTitleForPage(_state->current_page)));\n\n\t\t_txtInfo = new Text(defs->rect_text.width, defs->rect_text.height, defs->rect_text.x, defs->rect_text.y);\n\t\tadd(_txtInfo);\n\n\t\t_txtInfo->setColor(textColor1);\n\t\t_txtInfo->setSecondaryColor(textColor2);\n\t\t_txtInfo->setWordWrap(true);\n\t\t_txtInfo->setScrollable(true);\n\t\t_txtInfo->setText(tr(defs->getTextForPage(_state->current_page)));\n\n\t\tint width = Clamp(defs->rect_stats.width, 80, 320);\n\t\t_lstStats = new TextList(width, defs->rect_stats.height, defs->rect_stats.x, defs->rect_stats.y);\n\t\tadd(_lstStats);\n\n\t\t_lstStats->setColor(listColor1);\n\t\t_lstStats->setSecondaryColor(listColor2);\n\t\t_lstStats->setColumns(4, width - 60, 20, 20, 20);\n\t\t_lstStats->setDot(true);\n\n\t\tauto min = soldier->getMinStats();\n\t\tauto max = soldier->getMaxStats();\n\t\tauto cap = soldier->getStatCaps();\n\t\t_lstStats->addRow(4, tr(\"STR_TIME_UNITS\").c_str(), std::to_string(min.tu).c_str(), std::to_string(max.tu).c_str(), std::to_string(cap.tu).c_str());\n\t\t_lstStats->addRow(4, tr(\"STR_STAMINA\").c_str(), std::to_string(min.stamina).c_str(), std::to_string(max.stamina).c_str(), std::to_string(cap.stamina).c_str());\n\t\t_lstStats->addRow(4, tr(\"STR_HEALTH\").c_str(), std::to_string(min.health).c_str(), std::to_string(max.health).c_str(), std::to_string(cap.health).c_str());\n\t\t_lstStats->addRow(4, tr(\"STR_BRAVERY\").c_str(), std::to_string(min.bravery).c_str(), std::to_string(max.bravery).c_str(), std::to_string(cap.bravery).c_str());\n\t\t_lstStats->addRow(4, tr(\"STR_REACTIONS\").c_str(), std::to_string(min.reactions).c_str(), std::to_string(max.reactions).c_str(), std::to_string(cap.reactions).c_str());\n\t\t_lstStats->addRow(4, tr(\"STR_FIRING_ACCURACY\").c_str(), std::to_string(min.firing).c_str(), std::to_string(max.firing).c_str(), std::to_string(cap.firing).c_str());\n\t\t_lstStats->addRow(4, tr(\"STR_THROWING_ACCURACY\").c_str(), std::to_string(min.throwing).c_str(), std::to_string(max.throwing).c_str(), std::to_string(cap.throwing).c_str());\n\t\t_lstStats->addRow(4, tr(\"STR_MELEE_ACCURACY\").c_str(), std::to_string(min.melee).c_str(), std::to_string(max.melee).c_str(), std::to_string(cap.melee).c_str());\n\t\t_lstStats->addRow(4, tr(\"STR_STRENGTH\").c_str(), std::to_string(min.strength).c_str(), std::to_string(max.strength).c_str(), std::to_string(cap.strength).c_str());\n\t\tif (_game->getMod()->isManaFeatureEnabled())\n\t\t{\n\t\t\t_lstStats->addRow(4, tr(\"STR_MANA_POOL\").c_str(), std::to_string(min.mana).c_str(), std::to_string(max.mana).c_str(), std::to_string(cap.mana).c_str());\n\t\t}\n\t\t_lstStats->addRow(4, tr(\"STR_PSIONIC_STRENGTH\").c_str(), std::to_string(min.psiStrength).c_str(), std::to_string(max.psiStrength).c_str(), std::to_string(cap.psiStrength).c_str());\n\t\tif (defs->psi_skill_mode == 0)\n\t\t{\n\t\t\t// not shown\n\t\t\t_lstStats->addRow(4, tr(\"STR_PSIONIC_SKILL\").c_str(), \"\", \"\", std::to_string(cap.psiSkill).c_str());\n\t\t}\n\t\telse if (defs->psi_skill_mode == 1)\n\t\t{\n\t\t\t// shown processed\n\t\t\t_lstStats->addRow(4, tr(\"STR_PSIONIC_SKILL\").c_str(), std::to_string(max.psiSkill).c_str(), std::to_string(max.psiSkill*3/2).c_str(), std::to_string(cap.psiSkill).c_str());\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// shown raw\n\t\t\t_lstStats->addRow(4, tr(\"STR_PSIONIC_SKILL\").c_str(), std::to_string(min.psiSkill).c_str(), std::to_string(max.psiSkill).c_str(), std::to_string(cap.psiSkill).c_str());\n\t\t}\n\n\t\tcenterAllSurfaces();\n\t}\n\n\tArticleStateSoldier::~ArticleStateSoldier()\n\t{}\n\n}\n"
  },
  {
    "path": "src/Ufopaedia/ArticleStateSoldier.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2025 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ArticleState.h\"\n\nnamespace OpenXcom\n{\n\tclass Game;\n\tclass Text;\n\tclass TextList;\n\tclass ArticleDefinitionSoldier;\n\n\t/**\n\t * ArticleStateSoldier has a caption, text, background image and a stats block.\n\t * The layout of the description text and stats block can vary,\n\t * depending on the background image.\n\t */\n\n\tclass ArticleStateSoldier : public ArticleState\n\t{\n\tpublic:\n\t\tArticleStateSoldier(ArticleDefinitionSoldier *article_defs, std::shared_ptr<ArticleCommonState> state);\n\t\tvirtual ~ArticleStateSoldier();\n\n\tprotected:\n\t\tText *_txtTitle;\n\t\tText *_txtInfo;\n\t\tTextList *_lstStats;\n\t};\n}\n"
  },
  {
    "path": "src/Ufopaedia/ArticleStateTFTD.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"../Mod/ArticleDefinition.h\"\n#include \"ArticleStateTFTD.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Surface.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleInterface.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n\nnamespace OpenXcom\n{\n\n\tArticleStateTFTD::ArticleStateTFTD(ArticleDefinitionTFTD *defs, std::shared_ptr<ArticleCommonState> state) : ArticleState(defs->id, std::move(state))\n\t{\n\t\tRuleInterface *ruleInterface;\n\t\tswitch (defs->getType())\n\t\t{\n\t\t\tcase UFOPAEDIA_TYPE_TFTD:\n\t\t\t\truleInterface = _game->getMod()->getInterface(\"articleTFTD\");\n\t\t\t\tbreak;\n\t\t\tcase UFOPAEDIA_TYPE_TFTD_CRAFT:\n\t\t\t\truleInterface = _game->getMod()->getInterface(\"articleCraftTFTD\");\n\t\t\t\tbreak;\n\t\t\tcase UFOPAEDIA_TYPE_TFTD_CRAFT_WEAPON:\n\t\t\t\truleInterface = _game->getMod()->getInterface(\"articleCraftWeaponTFTD\");\n\t\t\t\tbreak;\n\t\t\tcase UFOPAEDIA_TYPE_TFTD_VEHICLE:\n\t\t\t\truleInterface = _game->getMod()->getInterface(\"articleVehicleTFTD\");\n\t\t\t\tbreak;\n\t\t\tcase UFOPAEDIA_TYPE_TFTD_ITEM:\n\t\t\t\truleInterface = _game->getMod()->getInterface(\"articleItemTFTD\");\n\t\t\t\tbreak;\n\t\t\tcase UFOPAEDIA_TYPE_TFTD_ARMOR:\n\t\t\t\truleInterface = _game->getMod()->getInterface(\"articleArmorTFTD\");\n\t\t\t\tbreak;\n\t\t\tcase UFOPAEDIA_TYPE_TFTD_BASE_FACILITY:\n\t\t\t\truleInterface = _game->getMod()->getInterface(\"articleBaseFacilityTFTD\");\n\t\t\t\tbreak;\n\t\t\tcase UFOPAEDIA_TYPE_TFTD_USO:\n\t\t\t\truleInterface = _game->getMod()->getInterface(\"articleUsoTFTD\");\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\truleInterface = _game->getMod()->getInterface(\"articleTFTD\");\n\t\t\t\tbreak;\n\t\t}\n\n\t\t// Set palette\n\t\tif (defs->customPalette)\n\t\t{\n\t\t\tif (ruleInterface->getPalette() == \"PAL_GEOSCAPE\")\n\t\t\t\t_cursorColor = Mod::GEOSCAPE_CURSOR;\n\t\t\telse if (ruleInterface->getPalette() == \"PAL_BASESCAPE\")\n\t\t\t\t_cursorColor = Mod::BASESCAPE_CURSOR;\n\t\t\telse if (ruleInterface->getPalette() == \"PAL_UFOPAEDIA\")\n\t\t\t\t_cursorColor = Mod::UFOPAEDIA_CURSOR;\n\t\t\telse if (ruleInterface->getPalette() == \"PAL_GRAPHS\")\n\t\t\t\t_cursorColor = Mod::GRAPHS_CURSOR;\n\t\t\telse\n\t\t\t\t_cursorColor = Mod::BATTLESCAPE_CURSOR;\n\n\t\t\tsetCustomPalette(_game->getMod()->getSurface(defs->image_id)->getPalette(), _cursorColor);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tsetStandardPalette(ruleInterface->getPalette());\n\t\t}\n\n\t\t_buttonColor = ruleInterface->getElement(\"button\")->color;\n\t\t_textColor = ruleInterface->getElement(\"text\")->color;\n\t\t_textColor2 = ruleInterface->getElement(\"text\")->color2;\n\t\t_listColor1 = ruleInterface->getElement(\"list\")->color;\n\t\t_listColor2 = ruleInterface->getElement(\"list\")->color2;\n\t\t_arrowColor = _listColor2;\n\t\tif (ruleInterface->getElementOptional(\"arrow\"))\n\t\t{\n\t\t\t_arrowColor = ruleInterface->getElement(\"arrow\")->color;\n\t\t}\n\t\tif (ruleInterface->getElementOptional(\"ammoColor\"))\n\t\t{\n\t\t\t_ammoColor = ruleInterface->getElement(\"ammoColor\")->color;\n\t\t}\n\n\t\t_btnInfo->setX(183);\n\t\t_btnInfo->setY(179);\n\t\t_btnInfo->setHeight(10);\n\t\t_btnInfo->setWidth(40);\n\t\t_btnInfo->setColor(_buttonColor);\n\t\t_btnOk->setX(227);\n\t\t_btnOk->setY(179);\n\t\t_btnOk->setHeight(10);\n\t\t_btnOk->setWidth(23);\n\t\t_btnOk->setColor(_buttonColor);\n\t\t_btnPrev->setX(254);\n\t\t_btnPrev->setY(179);\n\t\t_btnPrev->setHeight(10);\n\t\t_btnPrev->setWidth(23);\n\t\t_btnPrev->setColor(_buttonColor);\n\t\t_btnNext->setX(281);\n\t\t_btnNext->setY(179);\n\t\t_btnNext->setHeight(10);\n\t\t_btnNext->setWidth(23);\n\t\t_btnNext->setColor(_buttonColor);\n\n\t\tArticleState::initLayout();\n\n\t\t// Step 1: background image\n\t\tauto& bgImageName = ruleInterface->getBackgroundImage(_game->getMod(), _game->getSavedGame());\n\t\tif (!defs->customPalette)\n\t\t{\n\t\t\t_game->getMod()->getSurface(bgImageName)->blitNShade(_bg, 0, 0);\n\t\t}\n\n\t\t// Step 2: article image (optional)\n\t\tSurface *image = _game->getMod()->getSurface(defs->image_id, false);\n\t\tif (image)\n\t\t{\n\t\t\timage->blitNShade(_bg, 0, 0);\n\t\t}\n\n\t\t// Step 3: info button image\n\t\tSurface *button = _game->getMod()->getSurface(bgImageName + \"-InfoButton\", false);\n\t\tif (!defs->customPalette && button && _game->getMod()->getShowPediaInfoButton())\n\t\t{\n\t\t\tswitch (defs->getType())\n\t\t\t{\n\t\t\t\tcase UFOPAEDIA_TYPE_TFTD_ITEM:\n\t\t\t\tcase UFOPAEDIA_TYPE_TFTD_ARMOR:\n\t\t\t\tcase UFOPAEDIA_TYPE_TFTD_BASE_FACILITY:\n\t\t\t\tcase UFOPAEDIA_TYPE_TFTD_CRAFT:\n\t\t\t\tcase UFOPAEDIA_TYPE_TFTD_CRAFT_WEAPON:\n\t\t\t\tcase UFOPAEDIA_TYPE_TFTD_USO:\n\t\t\t\t\tbutton->blitNShade(_bg, 0, 0);\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t_txtInfo = new Text(defs->text_width, 136, 320 - defs->text_width, 34);\n\t\t_txtTitle = new Text(284, 16, 36, 14);\n\n\t\tadd(_txtTitle);\n\t\tadd(_txtInfo);\n\n\t\t_txtTitle->setColor(_textColor);\n\t\t_txtTitle->setBig();\n\t\t_txtTitle->setWordWrap(true);\n\t\t_txtTitle->setAlign(ALIGN_CENTER);\n\t\t_txtTitle->setText(tr(defs->getTitleForPage(_state->current_page)));\n\n\t\t_txtInfo->setColor(_textColor);\n\t\t_txtInfo->setSecondaryColor(_textColor2);\n\t\t_txtInfo->setWordWrap(true);\n\t\t_txtInfo->setScrollable(true);\n\t\t_txtInfo->setText(tr(defs->getTextForPage(_state->current_page)));\n\n\t\t// all of the above are common to the TFTD articles.\n\n\t\tif (defs->getType() == UFOPAEDIA_TYPE_TFTD)\n\t\t{\n\t\t\t// this command is contained in all the subtypes of this article,\n\t\t\t// and probably shouldn't run until all surfaces are added.\n\t\t\t// in the case of a simple image/title/text article,\n\t\t\t// we're done adding surfaces for now.\n\t\t\tcenterAllSurfaces();\n\t\t}\n\n\t}\n\n\tArticleStateTFTD::~ArticleStateTFTD()\n\t{}\n\n}\n"
  },
  {
    "path": "src/Ufopaedia/ArticleStateTFTD.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ArticleState.h\"\n\nnamespace OpenXcom\n{\n\tclass Text;\n\tclass ArticleDefinitionTFTD;\n\n\t/**\n\t * Every TFTD article has a title, text block and a background image, with little to no variation.\n\t */\n\n\tclass ArticleStateTFTD : public ArticleState\n\t{\n\tpublic:\n\t\tArticleStateTFTD(ArticleDefinitionTFTD *defs, std::shared_ptr<ArticleCommonState> state);\n\t\tvirtual ~ArticleStateTFTD();\n\n\tprotected:\n\t\tText *_txtTitle;\n\t\tText *_txtInfo;\n\t\tUint8 _buttonColor, _textColor, _textColor2, _listColor1, _listColor2, _ammoColor, _arrowColor;\n\t};\n}\n"
  },
  {
    "path": "src/Ufopaedia/ArticleStateTFTDArmor.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include <sstream>\n#include \"../fmath.h\"\n#include \"ArticleStateTFTD.h\"\n#include \"ArticleStateTFTDArmor.h\"\n#include \"../Mod/ArticleDefinition.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Interface/TextList.h\"\n\nnamespace OpenXcom\n{\n\n\tArticleStateTFTDArmor::ArticleStateTFTDArmor(ArticleDefinitionTFTD *defs, std::shared_ptr<ArticleCommonState> state) : ArticleStateTFTD(defs, std::move(state)), _row(0)\n\t{\n\t\t_txtInfo->setHeight(72);\n\n\t\t_btnInfo->setVisible(_game->getMod()->getShowPediaInfoButton());\n\n\t\tArmor *armor = _game->getMod()->getArmor(defs->id, true);\n\n\t\t_lstInfo = new TextList(150, 64, 168, 110);\n\t\tadd(_lstInfo);\n\n\t\t_lstInfo->setColor(_listColor1);\n\t\t_lstInfo->setColumns(2, 125, 25);\n\t\t_lstInfo->setDot(true);\n\n\t\t// Add armor values\n\t\taddStat(\"STR_FRONT_ARMOR\", armor->getFrontArmor());\n\t\taddStat(\"STR_LEFT_ARMOR\", armor->getLeftSideArmor());\n\t\taddStat(\"STR_RIGHT_ARMOR\", armor->getRightSideArmor());\n\t\taddStat(\"STR_REAR_ARMOR\", armor->getRearArmor());\n\t\taddStat(\"STR_UNDER_ARMOR\", armor->getUnderArmor());\n\n\t\t_lstInfo->addRow(0);\n\t\t++_row;\n\n\t\tif (Options::oxcePediaSortResistances == 0)\n\t\t{\n\t\t\t// Add damage modifiers\n\t\t\tfor (int i = 0; i < DAMAGE_TYPES; ++i)\n\t\t\t{\n\t\t\t\tItemDamageType dt = (ItemDamageType)i;\n\t\t\t\tint percentage = (int)Round(armor->getDamageModifier(dt) * 100.0f);\n\t\t\t\tstd::string damage = getDamageTypeText(dt);\n\t\t\t\tif (percentage != 100 && damage != \"STR_UNKNOWN\")\n\t\t\t\t{\n\t\t\t\t\taddModifier(damage, Unicode::formatPercentage(percentage));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// Add resistances\n\t\t\tint counter = 0;\n\t\t\tbool first = true;\n\t\t\tfor (int i = 0; i < DAMAGE_TYPES; ++i)\n\t\t\t{\n\t\t\t\tItemDamageType dt = (ItemDamageType)i;\n\t\t\t\tint percentage = (int)Round(armor->getDamageModifier(dt) * 100.0f);\n\t\t\t\tstd::string damage = getDamageTypeText(dt);\n\t\t\t\tif (percentage < 100 && damage != \"STR_UNKNOWN\")\n\t\t\t\t{\n\t\t\t\t\taddModifier(damage, Unicode::formatPercentage(percentage));\n\t\t\t\t\tcounter++;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (Options::oxcePediaSortResistances >= 2)\n\t\t\t{\n\t\t\t\t// Add standard damage (100%)\n\t\t\t\tfor (int i = 0; i < DAMAGE_TYPES; ++i)\n\t\t\t\t{\n\t\t\t\t\tItemDamageType dt = (ItemDamageType)i;\n\t\t\t\t\tint percentage = (int)Round(armor->getDamageModifier(dt) * 100.0f);\n\t\t\t\t\tstd::string damage = getDamageTypeText(dt);\n\t\t\t\t\tif (percentage == 100 && damage != \"STR_UNKNOWN\")\n\t\t\t\t\t{\n\t\t\t\t\t\tif (counter > 0 && first)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfirst = false;\n\t\t\t\t\t\t\tcounter = 0;\n\t\t\t\t\t\t\t_lstInfo->addRow(0);\n\t\t\t\t\t\t\t++_row;\n\t\t\t\t\t\t}\n\t\t\t\t\t\taddModifier(damage, Unicode::formatPercentage(percentage));\n\t\t\t\t\t\tcounter++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Add vulnerabilities\n\t\t\tfirst = true;\n\t\t\tfor (int i = 0; i < DAMAGE_TYPES; ++i)\n\t\t\t{\n\t\t\t\tItemDamageType dt = (ItemDamageType)i;\n\t\t\t\tint percentage = (int)Round(armor->getDamageModifier(dt) * 100.0f);\n\t\t\t\tstd::string damage = getDamageTypeText(dt);\n\t\t\t\tif (percentage > 100 && damage != \"STR_UNKNOWN\")\n\t\t\t\t{\n\t\t\t\t\tif (counter > 0 && first)\n\t\t\t\t\t{\n\t\t\t\t\t\tfirst = false;\n\t\t\t\t\t\tcounter = 0;\n\t\t\t\t\t\t_lstInfo->addRow(0);\n\t\t\t\t\t\t++_row;\n\t\t\t\t\t}\n\t\t\t\t\taddModifier(damage, Unicode::formatPercentage(percentage));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t_lstInfo->addRow(0);\n\t\t++_row;\n\n\t\t// Add unit stats\n\t\taddStat(\"STR_TIME_UNITS\", armor->getStats()->tu, true);\n\t\taddStat(\"STR_STAMINA\", armor->getStats()->stamina, true);\n\t\taddStat(\"STR_HEALTH\", armor->getStats()->health, true);\n\t\taddStat(\"STR_BRAVERY\", armor->getStats()->bravery, true);\n\t\taddStat(\"STR_REACTIONS\", armor->getStats()->reactions, true);\n\t\taddStat(\"STR_FIRING_ACCURACY\", armor->getStats()->firing, true);\n\t\taddStat(\"STR_THROWING_ACCURACY\", armor->getStats()->throwing, true);\n\t\taddStat(\"STR_MELEE_ACCURACY\", armor->getStats()->melee, true);\n\t\taddStat(\"STR_STRENGTH\", armor->getStats()->strength, true);\n\t\taddStat(\"STR_MANA_POOL\", armor->getStats()->mana, true);\n\t\taddStat(\"STR_PSIONIC_STRENGTH\", armor->getStats()->psiStrength, true);\n\t\taddStat(\"STR_PSIONIC_SKILL\", armor->getStats()->psiSkill, true);\n\n\t\tcenterAllSurfaces();\n\t}\n\n\tArticleStateTFTDArmor::~ArticleStateTFTDArmor()\n\t{}\n\n\tvoid ArticleStateTFTDArmor::addStat(const std::string &label, int stat, bool plus)\n\t{\n\t\tif (stat != 0)\n\t\t{\n\t\t\tstd::ostringstream ss;\n\t\t\tif (plus && stat > 0)\n\t\t\t\tss << \"+\";\n\t\t\tss << stat;\n\t\t\t_lstInfo->addRow(2, tr(label).c_str(), ss.str().c_str());\n\t\t\t_lstInfo->setCellColor(_row, 1, _listColor2);\n\t\t\t++_row;\n\t\t}\n\t}\n\n\tvoid ArticleStateTFTDArmor::addModifier(const std::string &label, const std::string &stat)\n\t{\n\t\tstd::string translation = tr(label);\n\t\tif (translation.length() > 2) // filter out unused OXCE damage types\n\t\t{\n\t\t\t_lstInfo->addRow(2, tr(label).c_str(), stat.c_str());\n\t\t\t_lstInfo->setCellColor(_row, 1, _listColor2);\n\t\t\t++_row;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/Ufopaedia/ArticleStateTFTDArmor.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ArticleStateTFTD.h\"\n\nnamespace OpenXcom\n{\n\tclass TextList;\n\tclass ArticleDefinitionTFTD;\n\n\tclass ArticleStateTFTDArmor : public ArticleStateTFTD\n\t{\n\tpublic:\n\t\tArticleStateTFTDArmor(ArticleDefinitionTFTD *defs, std::shared_ptr<ArticleCommonState> state);\n\t\tvirtual ~ArticleStateTFTDArmor();\n\n\tprotected:\n\t\tvoid addStat(const std::string &label, int stat, bool plus = false);\n\t\tvoid addModifier(const std::string &label, const std::string &stat);\n\n\t\tint _row;\n\t\tTextList *_lstInfo;\n\t};\n}\n"
  },
  {
    "path": "src/Ufopaedia/ArticleStateTFTDCraft.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"../Mod/ArticleDefinition.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleCraft.h\"\n#include \"ArticleStateTFTD.h\"\n#include \"ArticleStateTFTDCraft.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Interface/Text.h\"\n\nnamespace OpenXcom\n{\n\n\tArticleStateTFTDCraft::ArticleStateTFTDCraft(ArticleDefinitionTFTD *defs, std::shared_ptr<ArticleCommonState> state) : ArticleStateTFTD(defs, std::move(state))\n\t{\n\t\t_txtInfo->setHeight(80);\n\n\t\t_btnInfo->setVisible(_game->getMod()->getShowPediaInfoButton());\n\n\t\tRuleCraft *craft = _game->getMod()->getCraft(defs->id, true);\n\t\t_txtStats = new Text(131, 56, 187, 116);\n\t\tadd(_txtStats);\n\n\t\t_txtStats->setColor(_textColor);\n\t\t_txtStats->setSecondaryColor(_textColor2);\n\n\t\tstd::ostringstream ss;\n\t\tss << tr(\"STR_MAXIMUM_SPEED_UC\").arg(Unicode::formatNumber(craft->getMaxSpeed())) << '\\n';\n\t\tss << tr(\"STR_ACCELERATION\").arg(craft->getAcceleration()) << '\\n';\n\t\tint range;\n\t\tswitch (_game->getMod()->getPediaReplaceCraftFuelWithRangeType())\n\t\t{\n\t\t\t// Both max range alone and average range get rounded\n\t\t\tcase 0:\n\t\t\tcase 2:\n\t\t\t\trange = craft->calculateRange(_game->getMod()->getPediaReplaceCraftFuelWithRangeType());\n\t\t\t\tif (range == -1)\n\t\t\t\t{\n\t\t\t\t\tss << tr(\"STR_MAXIMUM_RANGE\").arg(tr(\"STR_INFINITE_RANGE\")) << '\\n';\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t// Round the answer to\n\t\t\t\tif (range < 100)\n\t\t\t\t{\n\t\t\t\t\t// don't round if it's small!\n\t\t\t\t}\n\t\t\t\telse if (range < 1000)\n\t\t\t\t{\n\t\t\t\t\t// nearest 10 nautical miles\n\t\t\t\t\trange += 10 / 2;\n\t\t\t\t\trange -= range % 10;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// nearest 100 nautical miles\n\t\t\t\t\trange += 100 / 2;\n\t\t\t\t\trange -= range % 100;\n\t\t\t\t}\n\n\t\t\t\tss << tr(\"STR_MAXIMUM_RANGE\").arg(Unicode::formatNumber(range)) << '\\n';\n\t\t\t\tbreak;\n\t\t\t// Min-maxxers can fret over exact numbers\n\t\t\tcase 1:\n\t\t\t\tif (craft->calculateRange(0) == -1)\n\t\t\t\t{\n\t\t\t\t\tss << tr(\"STR_MAXIMUM_RANGE\").arg(tr(\"STR_INFINITE_RANGE\")) << '\\n';\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tss << tr(\"STR_MINIMUM_RANGE\").arg(Unicode::formatNumber(craft->calculateRange(1))) << '\\n';\n\t\t\t\tss << tr(\"STR_MAXIMUM_RANGE\").arg(Unicode::formatNumber(craft->calculateRange(0))) << '\\n';\n\t\t\t\tbreak;\n\t\t\tdefault :\n\t\t\t\tss << tr(\"STR_FUEL_CAPACITY\").arg(Unicode::formatNumber(craft->getMaxFuel())) << '\\n';\n\t\t\t\tbreak;\n\t\t}\n\t\tss << tr(\"STR_WEAPON_PODS\").arg(craft->getWeapons()) << '\\n';\n\t\tss << tr(\"STR_DAMAGE_CAPACITY_UC\").arg(Unicode::formatNumber(craft->getMaxDamage())) << '\\n';\n\t\tif (craft->getMaxUnits() == craft->getMaxUnitsLimit())\n\t\t{\n\t\t\tss << tr(\"STR_CARGO_SPACE\").arg(craft->getMaxUnits()) << '\\n';\n\t\t}\n\t\telse\n\t\t{\n\t\t\tstd::ostringstream ss2;\n\t\t\tss2 << craft->getMaxUnits() << \"/\" << craft->getMaxUnitsLimit();\n\t\t\tss << tr(\"STR_CARGO_SPACE\").arg(ss2.str()) << '\\n';\n\t\t}\n\t\tif (craft->getMaxVehiclesAndLargeSoldiers() == craft->getMaxVehiclesAndLargeSoldiersLimit())\n\t\t{\n\t\t\tss << tr(\"STR_HWP_CAPACITY\").arg(craft->getMaxVehiclesAndLargeSoldiers());\n\t\t}\n\t\telse\n\t\t{\n\t\t\tstd::ostringstream ss2;\n\t\t\tss2 << craft->getMaxVehiclesAndLargeSoldiers() << \"/\" << craft->getMaxVehiclesAndLargeSoldiersLimit();\n\t\t\tss << tr(\"STR_HWP_CAPACITY\").arg(ss2.str());\n\t\t}\n\t\t_txtStats->setText(ss.str());\n\n\t\tcenterAllSurfaces();\n\t}\n\n\tArticleStateTFTDCraft::~ArticleStateTFTDCraft()\n\t{}\n\n}\n"
  },
  {
    "path": "src/Ufopaedia/ArticleStateTFTDCraft.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ArticleStateTFTD.h\"\n\nnamespace OpenXcom\n{\n\tclass Text;\n\tclass ArticleDefinitionTFTD;\n\n\tclass ArticleStateTFTDCraft : public ArticleStateTFTD\n\t{\n\tpublic:\n\t\tArticleStateTFTDCraft(ArticleDefinitionTFTD *defs, std::shared_ptr<ArticleCommonState> state);\n\t\tvirtual ~ArticleStateTFTDCraft();\n\n\tprotected:\n\t\tText *_txtStats;\n\t};\n}\n"
  },
  {
    "path": "src/Ufopaedia/ArticleStateTFTDCraftWeapon.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"ArticleStateTFTD.h\"\n#include \"ArticleStateTFTDCraftWeapon.h\"\n#include \"../Mod/ArticleDefinition.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleCraftWeapon.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/TextList.h\"\n\nnamespace OpenXcom\n{\n\n\tArticleStateTFTDCraftWeapon::ArticleStateTFTDCraftWeapon(ArticleDefinitionTFTD *defs, std::shared_ptr<ArticleCommonState> state) : ArticleStateTFTD(defs, std::move(state))\n\t{\n\t\t_txtInfo->setHeight(88);\n\n\t\t_btnInfo->setVisible(_game->getMod()->getShowPediaInfoButton());\n\n\t\tRuleCraftWeapon *weapon = _game->getMod()->getCraftWeapon(defs->id, true);\n\n\t\tCraftWeaponCategory category = CWC_WEAPON;\n\t\tint offset = 0;\n\t\tif (weapon->getHidePediaInfo())\n\t\t{\n\t\t\tif (weapon->getTractorBeamPower() > 0)\n\t\t\t{\n\t\t\t\tcategory = CWC_TRACTOR_BEAM;\n\t\t\t\toffset = 24; // 3 * 8\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tcategory = CWC_EQUIPMENT;\n\t\t\t\toffset = 0;\n\t\t\t}\n\t\t}\n\n\t\t_lstInfo = new TextList(150, 50 - offset, 168, 126 + offset);\n\t\tadd(_lstInfo);\n\t\t_lstInfo->setVisible(category != CWC_EQUIPMENT);\n\n\t\t_lstInfo->setColor(_listColor1);\n\t\t_lstInfo->setColumns(2, 100, 68); // deliberately making this wider than the original to account for finish.\n\t\t_lstInfo->setDot(true);\n\n\t\tif (category == CWC_WEAPON)\n\t\t{\n\t\t\t_lstInfo->addRow(2, tr(\"STR_DAMAGE\").c_str(), Unicode::formatNumber(weapon->getDamage()).c_str());\n\t\t\t_lstInfo->setCellColor(0, 1, _listColor2);\n\n\t\t\t_lstInfo->addRow(2, tr(\"STR_RANGE\").c_str(), tr(\"STR_KILOMETERS\").arg(weapon->getRange()).c_str());\n\t\t\t_lstInfo->setCellColor(1, 1, _listColor2);\n\n\t\t\t_lstInfo->addRow(2, tr(\"STR_ACCURACY\").c_str(), Unicode::formatPercentage(weapon->getAccuracy()).c_str());\n\t\t\t_lstInfo->setCellColor(2, 1, _listColor2);\n\n\t\t\t_lstInfo->addRow(2, tr(\"STR_RE_LOAD_TIME\").c_str(), tr(\"STR_SECONDS\").arg(weapon->getStandardReload()).c_str());\n\t\t\t_lstInfo->setCellColor(3, 1, _listColor2);\n\n\t\t\t_lstInfo->addRow(2, tr(\"STR_ROUNDS\").c_str(), Unicode::formatNumber(weapon->getAmmoMax()).c_str());\n\t\t\t_lstInfo->setCellColor(4, 1, _listColor2);\n\t\t}\n\t\telse if (category == CWC_TRACTOR_BEAM)\n\t\t{\n\t\t\t_lstInfo->addRow(2, tr(\"STR_TRACTOR_BEAM_POWER\").c_str(), Unicode::formatNumber(weapon->getTractorBeamPower()).c_str());\n\t\t\t_lstInfo->setCellColor(0, 1, _listColor2);\n\n\t\t\t_lstInfo->addRow(2, tr(\"STR_RANGE\").c_str(), tr(\"STR_KILOMETERS\").arg(weapon->getRange()).c_str());\n\t\t\t_lstInfo->setCellColor(1, 1, _listColor2);\n\t\t}\n\n\t\tcenterAllSurfaces();\n\t}\n\n\tArticleStateTFTDCraftWeapon::~ArticleStateTFTDCraftWeapon()\n\t{}\n\n}\n"
  },
  {
    "path": "src/Ufopaedia/ArticleStateTFTDCraftWeapon.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ArticleStateTFTD.h\"\n\nnamespace OpenXcom\n{\n\tclass TextList;\n\tclass ArticleDefinitionTFTD;\n\n\tclass ArticleStateTFTDCraftWeapon : public ArticleStateTFTD\n\t{\n\tpublic:\n\t\tArticleStateTFTDCraftWeapon(ArticleDefinitionTFTD *defs, std::shared_ptr<ArticleCommonState> state);\n\t\tvirtual ~ArticleStateTFTDCraftWeapon();\n\n\tprotected:\n\t\tTextList *_lstInfo;\n\t};\n}\n"
  },
  {
    "path": "src/Ufopaedia/ArticleStateTFTDFacility.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"../Mod/ArticleDefinition.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleBaseFacility.h\"\n#include \"ArticleStateTFTD.h\"\n#include \"ArticleStateTFTDFacility.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Interface/TextList.h\"\n\nnamespace OpenXcom\n{\n\n\tArticleStateTFTDFacility::ArticleStateTFTDFacility(ArticleDefinitionTFTD *defs, std::shared_ptr<ArticleCommonState> state) : ArticleStateTFTD(defs, std::move(state))\n\t{\n\t\t_txtInfo->setHeight(112);\n\n\t\t_btnInfo->setVisible(_game->getMod()->getShowPediaInfoButton());\n\n\t\tRuleBaseFacility *facility = _game->getMod()->getBaseFacility(defs->id, true);\n\n\t\t_lstInfo = new TextList(150, 50, 168, 150);\n\t\tadd(_lstInfo);\n\n\t\t_lstInfo->setColor(_listColor1);\n\t\t_lstInfo->setColumns(2, 104, 46);\n\t\t_lstInfo->setDot(true);\n\n\t\tstd::ostringstream ss;\n\t\tint row = 0;\n\t\tif (facility->getDefenseValue() > 0)\n\t\t{\n\t\t\t_lstInfo->setY(_lstInfo->getY() - 16);\n\t\t\t_txtInfo->setHeight(_txtInfo->getHeight() - 16);\n\t\t\tss.str(\"\");ss.clear();\n\t\t\tss << facility->getDefenseValue();\n\t\t\t_lstInfo->addRow(2, tr(\"STR_DEFENSE_VALUE\").c_str(), ss.str().c_str());\n\t\t\t_lstInfo->setCellColor(row++, 1, _listColor2);\n\n\t\t\tss.str(\"\");ss.clear();\n\t\t\tss << Unicode::formatPercentage(facility->getHitRatio());\n\t\t\t_lstInfo->addRow(2, tr(\"STR_HIT_RATIO\").c_str(), ss.str().c_str());\n\t\t\t_lstInfo->setCellColor(row++, 1, _listColor2);\n\t\t}\n\n\t\tss.str(\"\");ss.clear();\n\t\t_lstInfo->addRow(2, tr(\"STR_CONSTRUCTION_TIME\").c_str(), tr(\"STR_DAY\", facility->getBuildTime()).c_str());\n\t\t_lstInfo->setCellColor(row++, 1, _listColor2);\n\n\t\tss << Unicode::formatFunding(facility->getBuildCost());\n\t\t_lstInfo->addRow(2, tr(\"STR_CONSTRUCTION_COST\").c_str(), ss.str().c_str());\n\t\t_lstInfo->setCellColor(row++, 1, _listColor2);\n\n\t\tss.str(\"\");ss.clear();\n\t\tss << Unicode::formatFunding(facility->getMonthlyCost());\n\t\t_lstInfo->addRow(2, tr(\"STR_MAINTENANCE_COST\").c_str(), ss.str().c_str());\n\t\t_lstInfo->setCellColor(row++, 1, _listColor2);\n\n\t\tcenterAllSurfaces();\n\t}\n\n\tArticleStateTFTDFacility::~ArticleStateTFTDFacility()\n\t{}\n\n}\n"
  },
  {
    "path": "src/Ufopaedia/ArticleStateTFTDFacility.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ArticleStateTFTD.h\"\n\nnamespace OpenXcom\n{\n\tclass TextList;\n\tclass ArticleDefinitionTFTD;\n\n\tclass ArticleStateTFTDFacility : public ArticleStateTFTD\n\t{\n\tpublic:\n\t\tArticleStateTFTDFacility(ArticleDefinitionTFTD *defs, std::shared_ptr<ArticleCommonState> state);\n\t\tvirtual ~ArticleStateTFTDFacility();\n\n\tprotected:\n\t\tTextList *_lstInfo;\n\t};\n}\n"
  },
  {
    "path": "src/Ufopaedia/ArticleStateTFTDItem.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include <sstream>\n#include <algorithm>\n#include \"Ufopaedia.h\"\n#include \"ArticleStateTFTDItem.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/ArticleDefinition.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Interface/TextList.h\"\n#include <algorithm>\n\nnamespace OpenXcom\n{\n\n\tArticleStateTFTDItem::ArticleStateTFTDItem(ArticleDefinitionTFTD *defs, std::shared_ptr<ArticleCommonState> state) : ArticleStateTFTD(defs, std::move(state))\n\t{\n\t\t_btnInfo->setVisible(_game->getMod()->getShowPediaInfoButton());\n\n\t\tRuleItem *item = _game->getMod()->getItem(defs->weapon, false);\n\t\tif (!item)\n\t\t{\n\t\t\titem = _game->getMod()->getItem(defs->id, true);\n\t\t}\n\n\t\tint ammoSlot = defs->getAmmoSlotForPage(_state->current_page);\n\t\tint ammoSlotPrevUsage = defs->getAmmoSlotPrevUsageForPage(_state->current_page);\n\t\tconst std::vector<const RuleItem*> dummy;\n\t\tconst std::vector<const RuleItem*> *ammo_data = ammoSlot != RuleItem::AmmoSlotSelfUse ? item->getCompatibleAmmoForSlot(ammoSlot) : &dummy;\n\n\t\t// SHOT STATS TABLE (for firearms only)\n\t\tif (item->getBattleType() == BT_FIREARM)\n\t\t{\n\t\t\t_txtShotType = new Text(53, 17, 8, 157);\n\t\t\tadd(_txtShotType);\n\t\t\t_txtShotType->setColor(_textColor);\n\t\t\t_txtShotType->setWordWrap(true);\n\t\t\t_txtShotType->setText(tr(\"STR_SHOT_TYPE\"));\n\n\t\t\t_txtAccuracy = new Text(57, 17, 61, 157);\n\t\t\tadd(_txtAccuracy);\n\t\t\t_txtAccuracy->setColor(_textColor);\n\t\t\t_txtAccuracy->setWordWrap(true);\n\t\t\t_txtAccuracy->setText(tr(\"STR_ACCURACY_UC\"));\n\n\t\t\t_txtTuCost = new Text(56, 17, 118, 157);\n\t\t\tadd(_txtTuCost);\n\t\t\t_txtTuCost->setColor(_textColor);\n\t\t\t_txtTuCost->setWordWrap(true);\n\t\t\t_txtTuCost->setText(tr(\"STR_TIME_UNIT_COST\"));\n\n\t\t\t_lstInfo = new TextList(140, 55, 8, 170);\n\t\t\tadd(_lstInfo);\n\n\t\t\t_lstInfo->setColor(_listColor2); // color for % data!\n\t\t\t_lstInfo->setColumns(3, 70, 40, 30);\n\n\n\t\t\tauto addAttack = [&](int& row, const std::string& name, const RuleItemUseCost& cost, const RuleItemUseFlat& flat, const RuleItemAction *config, const RuleItem* weapon)\n\t\t\t{\n\t\t\t\tif (row < 3 && cost.Time > 0 && config->ammoSlot == ammoSlot)\n\t\t\t\t{\n\t\t\t\t\tstd::string tu = Unicode::formatPercentage(cost.Time);\n\t\t\t\t\tif (flat.Time)\n\t\t\t\t\t{\n\t\t\t\t\t\ttu.erase(tu.end() - 1);\n\t\t\t\t\t}\n\t\t\t\t\tint range = std::min(config->range, weapon->getMaxRange());\n\t\t\t\t\tstd::string label = config->shortName.empty() ? tr(name).arg(config->shots).arg(range) : tr(config->shortName).arg(config->shots).arg(range);\n\t\t\t\t\t_lstInfo->addRow(3,\n\t\t\t\t\t\tlabel.c_str(),\n\t\t\t\t\t\tUnicode::formatPercentage(config->accuracy).c_str(),\n\t\t\t\t\t\ttu.c_str());\n\t\t\t\t\t_lstInfo->setCellColor(row, 0, _listColor1);\n\t\t\t\t\trow++;\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tint current_row = 0;\n\n\t\t\taddAttack(current_row, \"STR_SHOT_TYPE_AUTO\", item->getCostAuto(), item->getFlatAuto(), item->getConfigAuto(), item);\n\n\t\t\taddAttack(current_row, \"STR_SHOT_TYPE_SNAP\", item->getCostSnap(), item->getFlatSnap(), item->getConfigSnap(), item);\n\n\t\t\taddAttack(current_row, \"STR_SHOT_TYPE_AIMED\", item->getCostAimed(), item->getFlatAimed(), item->getConfigAimed(), item);\n\n\t\t\t//optional melee\n\t\t\taddAttack(current_row, \"STR_SHOT_TYPE_MELEE\", item->getCostMelee(), item->getFlatMelee(), item->getConfigMelee(), item);\n\t\t}\n\n\t\t// AMMO column\n\t\tstd::ostringstream ss;\n\n\t\tfor (int i = 0; i<3; ++i)\n\t\t{\n\t\t\t_txtAmmoType[i] = new Text(120, 9, 168, 144 + i*10);\n\t\t\tadd(_txtAmmoType[i]);\n\t\t\t_txtAmmoType[i]->setColor(_textColor);\n\t\t\t_txtAmmoType[i]->setWordWrap(true);\n\n\t\t\t_txtAmmoDamage[i] = new Text(20, 9, 300, 144 + i*10);\n\t\t\tadd(_txtAmmoDamage[i]);\n\t\t\t_txtAmmoDamage[i]->setColor(_ammoColor);\n\t\t}\n\n\t\tauto addAmmoDamagePower = [&](int pos, const RuleItem *rule, const RuleItem* weaponRule)\n\t\t{\n\t\t\t_txtAmmoType[pos]->setText(tr(getDamageTypeText(rule->getDamageType()->ResistType)));\n\n\t\t\tss.str(\"\");ss.clear();\n\t\t\tif (weaponRule->getIgnoreAmmoPower())\n\t\t\t{\n\t\t\t\tss << weaponRule->getPower();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tss << rule->getPower();\n\t\t\t}\n\t\t\tif (rule->getShotgunPellets())\n\t\t\t{\n\t\t\t\tss << \"x\" << rule->getShotgunPellets();\n\t\t\t}\n\t\t\t_txtAmmoDamage[pos]->setText(ss.str());\n\t\t};\n\n\t\tswitch (item->getBattleType())\n\t\t{\n\t\t\tcase BT_FIREARM:\n\t\t\t\tif (item->getHidePower()) break;\n\t\t\t\tif (ammo_data->empty())\n\t\t\t\t{\n\t\t\t\t\taddAmmoDamagePower(0, item, item);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tint maxShow = 3;\n\t\t\t\t\tint skipShow = maxShow * ammoSlotPrevUsage;\n\t\t\t\t\tint currShow = 0;\n\t\t\t\t\tfor (auto* type : *ammo_data)\n\t\t\t\t\t{\n\t\t\t\t\t\tArticleDefinition *ammo_article = _game->getMod()->getUfopaediaArticle(type->getType(), true);\n\t\t\t\t\t\tif (Ufopaedia::isArticleAvailable(_game->getSavedGame(), ammo_article))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (skipShow > 0)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t--skipShow;\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\taddAmmoDamagePower(currShow, type, item);\n\n\t\t\t\t\t\t\t++currShow;\n\t\t\t\t\t\t\tif (currShow == maxShow)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase BT_AMMO:\n\t\t\tcase BT_GRENADE:\n\t\t\tcase BT_PROXIMITYGRENADE:\n\t\t\tcase BT_MELEE:\n\t\t\t\tif (item->getHidePower()) break;\n\t\t\t\taddAmmoDamagePower(0, item, item);\n\t\t\t\tbreak;\n\t\t\tdefault: break;\n\t\t}\n\n\t\tif (!_txtAmmoType[0]->getText().empty())\n\t\t\t_txtInfo->setHeight(112);\n\n\t\t// multi-page indicator\n\t\t_txtArrows = new Text(32, 9, 277, 134);\n\t\tadd(_txtArrows);\n\t\t_txtArrows->setColor(_arrowColor);\n\t\t_txtArrows->setAlign(ALIGN_RIGHT);\n\t\tstd::ostringstream ss2;\n\t\tif (_state->hasPrevArticlePage()) ss2 << \"<<\";\n\t\tif (_state->hasNextArticlePage()) ss2 << \" >>\";\n\t\t_txtArrows->setText(ss2.str());\n\n\t\tcenterAllSurfaces();\n\t}\n\n\tArticleStateTFTDItem::~ArticleStateTFTDItem()\n\t{}\n\n}\n"
  },
  {
    "path": "src/Ufopaedia/ArticleStateTFTDItem.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ArticleStateTFTD.h\"\n\nnamespace OpenXcom\n{\n\tclass TextList;\n\tclass Text;\n\tclass ArticleDefinitionTFTD;\n\n\tclass ArticleStateTFTDItem : public ArticleStateTFTD\n\t{\n\tpublic:\n\t\tArticleStateTFTDItem(ArticleDefinitionTFTD *defs, std::shared_ptr<ArticleCommonState> state);\n\t\tvirtual ~ArticleStateTFTDItem();\n\n\tprotected:\n\t\tTextList *_lstInfo;\n\t\tText *_txtShotType;\n\t\tText *_txtAccuracy;\n\t\tText *_txtTuCost;\n\t\tText *_txtAmmoType[3];\n\t\tText *_txtAmmoDamage[3];\n\t\tText *_txtArrows;\n\t};\n}\n"
  },
  {
    "path": "src/Ufopaedia/ArticleStateTFTDUso.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"../Mod/ArticleDefinition.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleUfo.h\"\n#include \"ArticleStateTFTD.h\"\n#include \"ArticleStateTFTDUso.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Interface/TextList.h\"\n\nnamespace OpenXcom\n{\n\n\tArticleStateTFTDUso::ArticleStateTFTDUso(ArticleDefinitionTFTD *defs, std::shared_ptr<ArticleCommonState> state) : ArticleStateTFTD(defs, std::move(state))\n\t{\n\t\t_txtInfo->setHeight(112);\n\n\t\t_btnInfo->setVisible(_game->getMod()->getShowPediaInfoButton());\n\n\t\tRuleUfo *ufo = _game->getMod()->getUfo(defs->id, true);\n\n\t\t_lstInfo = new TextList(150, 50, 168, 142);\n\t\tadd(_lstInfo);\n\n\t\t_lstInfo->setColor(_listColor1);\n\t\t_lstInfo->setColumns(2, 95, 55);\n\t\t_lstInfo->setDot(true);\n\n\t\t_lstInfo->addRow(2, tr(\"STR_DAMAGE_CAPACITY\").c_str(), Unicode::formatNumber(ufo->getStats().damageMax).c_str());\n\n\t\t_lstInfo->addRow(2, tr(\"STR_WEAPON_POWER\").c_str(), Unicode::formatNumber(ufo->getWeaponPower()).c_str());\n\n\t\t_lstInfo->addRow(2, tr(\"STR_WEAPON_RANGE\").c_str(), tr(\"STR_KILOMETERS\").arg(ufo->getWeaponRange()).c_str());\n\n\t\t_lstInfo->addRow(2, tr(\"STR_MAXIMUM_SPEED\").c_str(), tr(\"STR_KNOTS\").arg(Unicode::formatNumber(ufo->getStats().speedMax)).c_str());\n\t\tfor (int i = 0; i != 4; ++i)\n\t\t{\n\t\t\t_lstInfo->setCellColor(i, 1, _listColor2);\n\t\t}\n\n\t\tcenterAllSurfaces();\n\t}\n\n\tArticleStateTFTDUso::~ArticleStateTFTDUso()\n\t{}\n\n}\n"
  },
  {
    "path": "src/Ufopaedia/ArticleStateTFTDUso.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ArticleStateTFTD.h\"\n\nnamespace OpenXcom\n{\n\tclass TextList;\n\tclass ArticleDefinitionTFTD;\n\n\tclass ArticleStateTFTDUso : public ArticleStateTFTD\n\t{\n\tpublic:\n\t\tArticleStateTFTDUso(ArticleDefinitionTFTD *defs, std::shared_ptr<ArticleCommonState> state);\n\t\tvirtual ~ArticleStateTFTDUso();\n\n\tprotected:\n\t\tTextList *_lstInfo;\n\t};\n}\n"
  },
  {
    "path": "src/Ufopaedia/ArticleStateTFTDVehicle.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"../Mod/ArticleDefinition.h\"\n#include \"ArticleStateTFTDVehicle.h\"\n#include <sstream>\n#include \"../Engine/Game.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/Unit.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Mod/RuleItem.h\"\n\nnamespace OpenXcom\n{\n\n\tArticleStateTFTDVehicle::ArticleStateTFTDVehicle(ArticleDefinitionTFTD *defs, std::shared_ptr<ArticleCommonState> state) : ArticleStateTFTD(defs, std::move(state))\n\t{\n\t\t_txtInfo->setHeight(72);\n\n\t\tRuleItem *item = _game->getMod()->getItem(defs->id, true);\n\t\tUnit *unit = item->getVehicleUnit();\n\t\tif (!unit)\n\t\t{\n\t\t\tthrow Exception(\"ArticleStateTFTDVehicle: Item \" + defs->id + \" is missing a vehicle unit definition!\");\n\t\t}\n\t\tconst Armor *armor = unit->getArmor();\n\n\t\t_lstStats = new TextList(150, 65, 168, 106);\n\n\t\tadd(_lstStats);\n\n\t\t_lstStats->setColor(_listColor1);\n\t\t_lstStats->setColumns(2, 100, 50);\n\t\t_lstStats->setDot(true);\n\n\t\t_lstStats2 = new TextList(195, 33, 25, 166);\n\n\t\tadd(_lstStats2);\n\n\t\t_lstStats2->setColor(_listColor1);\n\t\t_lstStats2->setColumns(2, 65, 130);\n\t\t_lstStats2->setDot(true);\n\n\t\tstd::ostringstream ss;\n\t\tss << unit->getStats()->tu;\n\t\t_lstStats->addRow(2, tr(\"STR_TIME_UNITS\").c_str(), ss.str().c_str());\n\n\t\tstd::ostringstream ss2;\n\t\tss2 << unit->getStats()->health;\n\t\t_lstStats->addRow(2, tr(\"STR_HEALTH\").c_str(), ss2.str().c_str());\n\n\t\tstd::ostringstream ss3;\n\t\tss3 << armor->getFrontArmor();\n\t\t_lstStats->addRow(2, tr(\"STR_FRONT_ARMOR\").c_str(), ss3.str().c_str());\n\n\t\tstd::ostringstream ss4;\n\t\tss4 << armor->getLeftSideArmor();\n\t\t_lstStats->addRow(2, tr(\"STR_LEFT_ARMOR\").c_str(), ss4.str().c_str());\n\n\t\tstd::ostringstream ss5;\n\t\tss5 << armor->getRightSideArmor();\n\t\t_lstStats->addRow(2, tr(\"STR_RIGHT_ARMOR\").c_str(), ss5.str().c_str());\n\n\t\tstd::ostringstream ss6;\n\t\tss6 << armor->getRearArmor();\n\t\t_lstStats->addRow(2, tr(\"STR_REAR_ARMOR\").c_str(), ss6.str().c_str());\n\n\t\tstd::ostringstream ss7;\n\t\tss7 << armor->getUnderArmor();\n\t\t_lstStats->addRow(2, tr(\"STR_UNDER_ARMOR\").c_str(), ss7.str().c_str());\n\n\t\t_lstStats2->addRow(2, tr(\"STR_WEAPON\").c_str(), tr(defs->weapon).c_str());\n\n\t\tif (item->getVehicleClipAmmo())\n\t\t{\n\t\t\tconst RuleItem *ammo = item->getVehicleClipAmmo();\n\n\t\t\tstd::ostringstream ss8;\n\t\t\tif (item->getIgnoreAmmoPower())\n\t\t\t{\n\t\t\t\tss8 << item->getPower();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tss8 << ammo->getPower();\n\t\t\t}\n\t\t\t_lstStats2->addRow(2, tr(\"STR_WEAPON_POWER\").c_str(), ss8.str().c_str());\n\n\t\t\t_lstStats2->addRow(2, tr(\"STR_AMMUNITION\").c_str(), tr(ammo->getName()).c_str());\n\n\t\t\tstd::ostringstream ss9;\n\t\t\tss9 << item->getVehicleClipSize();\n\n\t\t\t_lstStats2->addRow(2, tr(\"STR_ROUNDS\").c_str(), ss9.str().c_str());\n\t\t}\n\t\telse\n\t\t{\n\t\t\tstd::ostringstream ss8;\n\t\t\tss8 << item->getPower();\n\t\t\t_lstStats2->addRow(2, tr(\"STR_WEAPON_POWER\").c_str(), ss8.str().c_str());\n\t\t}\n\n\t\tfor (size_t i = 0; i != _lstStats->getTexts(); ++i)\n\t\t{\n\t\t\t_lstStats->setCellColor(i, 1, _listColor2);\n\t\t}\n\t\tfor (size_t i = 0; i != _lstStats2->getTexts(); ++i)\n\t\t{\n\t\t\t_lstStats2->setCellColor(i, 1, _listColor2);\n\t\t}\n\n\t\tcenterAllSurfaces();\n\t}\n\n\tArticleStateTFTDVehicle::~ArticleStateTFTDVehicle()\n\t{}\n\n}\n"
  },
  {
    "path": "src/Ufopaedia/ArticleStateTFTDVehicle.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ArticleStateTFTD.h\"\n\nnamespace OpenXcom\n{\n\tclass TextList;\n\tclass ArticleDefinitionTFTD;\n\n\tclass ArticleStateTFTDVehicle : public ArticleStateTFTD\n\t{\n\tpublic:\n\t\tArticleStateTFTDVehicle(ArticleDefinitionTFTD *defs, std::shared_ptr<ArticleCommonState> state);\n\t\tvirtual ~ArticleStateTFTDVehicle();\n\n\tprotected:\n\t\tTextList *_lstStats, *_lstStats2;\n\t};\n}\n"
  },
  {
    "path": "src/Ufopaedia/ArticleStateText.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"../Mod/ArticleDefinition.h\"\n#include \"ArticleStateText.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Surface.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Mod/RuleInterface.h\"\n\nnamespace OpenXcom\n{\n\n\tArticleStateText::ArticleStateText(ArticleDefinitionText *defs, std::shared_ptr<ArticleCommonState> state) : ArticleState(defs->id, std::move(state))\n\t{\n\t\t// add screen elements\n\t\t_txtTitle = new Text(296, 17, 5, 23);\n\t\t_txtInfo = new Text(296, 150, 10, 48);\n\n\t\t// Set palette\n\t\tsetStandardPalette(\"PAL_UFOPAEDIA\");\n\n\t\t_buttonColor = _game->getMod()->getInterface(\"articleText\")->getElement(\"button\")->color;\n\t\t_titleColor = _game->getMod()->getInterface(\"articleText\")->getElement(\"title\")->color;\n\t\t_textColor1 = _game->getMod()->getInterface(\"articleText\")->getElement(\"text\")->color;\n\t\t_textColor2 = _game->getMod()->getInterface(\"articleText\")->getElement(\"text\")->color2;\n\n\t\tArticleState::initLayout();\n\n\t\t// add other elements\n\t\tadd(_txtTitle);\n\t\tadd(_txtInfo);\n\n\t\tcenterAllSurfaces();\n\n\t\t// Set up objects\n\t\t_game->getMod()->getSurface(\"BACK10.SCR\")->blitNShade(_bg, 0, 0);\n\t\t_btnOk->setColor(_buttonColor);\n\t\t_btnPrev->setColor(_buttonColor);\n\t\t_btnNext->setColor(_buttonColor);\n\n\t\t_txtTitle->setColor(_titleColor);\n\t\t_txtTitle->setBig();\n\t\t_txtTitle->setText(tr(defs->getTitleForPage(_state->current_page)));\n\n\t\t_txtInfo->setColor(_textColor1);\n\t\t_txtInfo->setSecondaryColor(_textColor2);\n\t\t_txtInfo->setWordWrap(true);\n\t\t_txtInfo->setScrollable(true);\n\t\t_txtInfo->setText(tr(defs->getTextForPage(_state->current_page)));\n\t}\n\n\tArticleStateText::~ArticleStateText()\n\t{}\n\n}\n"
  },
  {
    "path": "src/Ufopaedia/ArticleStateText.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ArticleState.h\"\n\nnamespace OpenXcom\n{\n\tclass Game;\n\tclass Text;\n\tclass ArticleDefinitionText;\n\n\t/**\n\t * ArticleStateText has only a caption and a text.\n\t */\n\n\tclass ArticleStateText : public ArticleState\n\t{\n\tpublic:\n\t\tArticleStateText(ArticleDefinitionText *article_defs, std::shared_ptr<ArticleCommonState> state);\n\t\tvirtual ~ArticleStateText();\n\n\tprotected:\n\t\tText *_txtTitle;\n\t\tText *_txtInfo;\n\t\tUint8 _buttonColor, _titleColor, _textColor1, _textColor2;\n\t};\n}\n"
  },
  {
    "path": "src/Ufopaedia/ArticleStateTextImage.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"../Mod/ArticleDefinition.h\"\n#include \"ArticleStateTextImage.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Surface.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Mod/RuleInterface.h\"\n\nnamespace OpenXcom\n{\n\n\tArticleStateTextImage::ArticleStateTextImage(ArticleDefinitionTextImage *defs, std::shared_ptr<ArticleCommonState> state) : ArticleState(defs->id, std::move(state))\n\t{\n\t\t// add screen elements\n\t\t_txtTitle = new Text(defs->text_width, 48, 5, 22);\n\n\t\t// Set palette\n\t\tif (defs->customPalette)\n\t\t{\n\t\t\tsetCustomPalette(_game->getMod()->getSurface(defs->image_id)->getPalette(), Mod::UFOPAEDIA_CURSOR);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tsetStandardPalette(\"PAL_UFOPAEDIA\");\n\t\t}\n\n\t\t_buttonColor = _game->getMod()->getInterface(\"articleTextImage\")->getElement(\"button\")->color;\n\t\t_titleColor = _game->getMod()->getInterface(\"articleTextImage\")->getElement(\"title\")->color;\n\t\t_textColor1 = _game->getMod()->getInterface(\"articleTextImage\")->getElement(\"text\")->color;\n\t\t_textColor2 = _game->getMod()->getInterface(\"articleTextImage\")->getElement(\"text\")->color2;\n\n\t\tArticleState::initLayout();\n\n\t\t// add other elements\n\t\tadd(_txtTitle);\n\n\t\t// Set up objects\n\t\t_game->getMod()->getSurface(defs->image_id)->blitNShade(_bg, 0, 0);\n\t\t_btnOk->setColor(_buttonColor);\n\t\t_btnPrev->setColor(_buttonColor);\n\t\t_btnNext->setColor(_buttonColor);\n\n\t\t_txtTitle->setColor(_titleColor);\n\t\t_txtTitle->setBig();\n\t\t_txtTitle->setWordWrap(true);\n\t\t_txtTitle->setText(tr(defs->getTitleForPage(_state->current_page)));\n\n\t\tint text_height = _txtTitle->getTextHeight();\n\n\t\tif (defs->rect_text.width == 0)\n\t\t{\n\t\t\t_txtInfo = new Text(defs->text_width, 176 - text_height, 5, 23 + text_height);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_txtInfo = new Text(defs->rect_text.width, defs->rect_text.height, defs->rect_text.x, defs->rect_text.y);\n\t\t}\n\t\tadd(_txtInfo);\n\n\t\t_txtInfo->setColor(_textColor1);\n\t\t_txtInfo->setSecondaryColor(_textColor2);\n\t\t_txtInfo->setWordWrap(true);\n\t\t_txtInfo->setScrollable(true);\n\t\tif (defs->align_bottom)\n\t\t{\n\t\t\t_txtInfo->setVerticalAlign(ALIGN_BOTTOM);\n\t\t}\n\t\t_txtInfo->setText(tr(defs->getTextForPage(_state->current_page)));\n\n\t\tcenterAllSurfaces();\n\t}\n\n\tArticleStateTextImage::~ArticleStateTextImage()\n\t{}\n\n}\n"
  },
  {
    "path": "src/Ufopaedia/ArticleStateTextImage.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ArticleState.h\"\n\nnamespace OpenXcom\n{\n\tclass Game;\n\tclass Text;\n\tclass ArticleStateTextImage;\n\tclass ArticleDefinitionTextImage;\n\n\t/**\n\t * ArticleStateTextImage has a title, text block and a background image.\n\t */\n\n\tclass ArticleStateTextImage : public ArticleState\n\t{\n\tpublic:\n\t\tArticleStateTextImage(ArticleDefinitionTextImage *defs, std::shared_ptr<ArticleCommonState> state);\n\t\tvirtual ~ArticleStateTextImage();\n\n\tprotected:\n\t\tText *_txtTitle;\n\t\tText *_txtInfo;\n\t\tUint8 _buttonColor, _titleColor, _textColor1, _textColor2;\n\t};\n}\n"
  },
  {
    "path": "src/Ufopaedia/ArticleStateUfo.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"ArticleStateUfo.h\"\n#include \"../Mod/ArticleDefinition.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleUfo.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Palette.h\"\n#include \"../Engine/Surface.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Mod/RuleInterface.h\"\n\nnamespace OpenXcom\n{\n\n\tArticleStateUfo::ArticleStateUfo(ArticleDefinitionUfo *defs, std::shared_ptr<ArticleCommonState> state) : ArticleState(defs->id, std::move(state))\n\t{\n\t\tRuleUfo *ufo = _game->getMod()->getUfo(defs->id, true);\n\n\t\t// add screen elements\n\t\t_txtTitle = new Text(155, 32, 5, 24);\n\n\t\t// Set palette\n\t\tsetStandardPalette(\"PAL_GEOSCAPE\");\n\n\t\tArticleState::initLayout();\n\n\t\t// add other elements\n\t\tadd(_txtTitle);\n\n\t\t// Set up objects\n\t\t_game->getMod()->getSurface(\"BACK11.SCR\")->blitNShade(_bg, 0, 0);\n\t\t_btnOk->setColor(Palette::blockOffset(8)+5);\n\t\t_btnPrev->setColor(Palette::blockOffset(8)+5);\n\t\t_btnNext->setColor(Palette::blockOffset(8)+5);\n\t\t_btnInfo->setColor(Palette::blockOffset(8)+5);\n\t\t_btnInfo->setVisible(_game->getMod()->getShowPediaInfoButton());\n\n\t\t_txtTitle->setColor(Palette::blockOffset(8)+5);\n\t\t_txtTitle->setBig();\n\t\t_txtTitle->setWordWrap(true);\n\t\t_txtTitle->setText(tr(defs->getTitleForPage(_state->current_page)));\n\n\t\t_image = new Surface(160, 52, 160, 6);\n\t\tadd(_image);\n\n\t\tRuleInterface *dogfightInterface = _game->getMod()->getInterface(\"dogfight\");\n\n\t\tSurfaceCrop crop = _game->getMod()->getSurface(\"INTERWIN.DAT\")->getCrop();\n\t\tcrop.setX(0);\n\t\tcrop.setY(0);\n\t\tcrop.getCrop()->x = 0;\n\t\tcrop.getCrop()->y = 0;\n\t\tcrop.getCrop()->w = _image->getWidth();\n\t\tcrop.getCrop()->h = _image->getHeight();\n\t\t_image->drawRect(crop.getCrop(), 15);\n\t\tcrop.blit(_image);\n\n\t\tif (ufo->getModSprite().empty())\n\t\t{\n\t\t\tcrop.getCrop()->y = dogfightInterface->getElement(\"previewMid\")->y + dogfightInterface->getElement(\"previewMid\")->h * ufo->getSprite();\n\t\t\tcrop.getCrop()->h = dogfightInterface->getElement(\"previewMid\")->h;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tcrop = _game->getMod()->getSurface(ufo->getModSprite())->getCrop();\n\t\t}\n\t\tcrop.setX(0);\n\t\tcrop.setY(0);\n\t\tcrop.blit(_image);\n\n\t\t_txtInfo = new Text(300, 50, 10, 140);\n\t\tadd(_txtInfo);\n\n\t\t_txtInfo->setColor(Palette::blockOffset(8)+5);\n\t\t_txtInfo->setSecondaryColor(Palette::blockOffset(8) + 10);\n\t\t_txtInfo->setWordWrap(true);\n\t\t_txtInfo->setScrollable(true);\n\t\t_txtInfo->setText(tr(defs->getTextForPage(_state->current_page)));\n\n\t\t_lstInfo = new TextList(310, 64, 10, 68);\n\t\tadd(_lstInfo);\n\n\t\tcenterAllSurfaces();\n\n\t\t_lstInfo->setColor(Palette::blockOffset(8)+5);\n\t\t_lstInfo->setColumns(2, 200, 110);\n//\t\t_lstInfo->setCondensed(true);\n\t\t_lstInfo->setBig();\n\t\t_lstInfo->setDot(true);\n\n\t\t_lstInfo->addRow(2, tr(\"STR_DAMAGE_CAPACITY\").c_str(), Unicode::formatNumber(ufo->getStats().damageMax).c_str());\n\n\t\t_lstInfo->addRow(2, tr(\"STR_WEAPON_POWER\").c_str(), Unicode::formatNumber(ufo->getWeaponPower()).c_str());\n\n\t\t_lstInfo->addRow(2, tr(\"STR_WEAPON_RANGE\").c_str(), tr(\"STR_KILOMETERS\").arg(ufo->getWeaponRange()).c_str());\n\n\t\t_lstInfo->addRow(2, tr(\"STR_MAXIMUM_SPEED\").c_str(), tr(\"STR_KNOTS\").arg(Unicode::formatNumber(ufo->getStats().speedMax)).c_str());\n\t}\n\n\tArticleStateUfo::~ArticleStateUfo()\n\t{}\n\n}\n"
  },
  {
    "path": "src/Ufopaedia/ArticleStateUfo.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ArticleState.h\"\n\nnamespace OpenXcom\n{\n\tclass Game;\n\tclass Surface;\n\tclass Text;\n\tclass TextList;\n\tclass ArticleDefinitionUfo;\n\n\t/**\n\t * ArticleStateUfo has a caption, text, preview image and a stats block.\n\t * The UFO image is found using the RuleUfo class.\n\t */\n\n\tclass ArticleStateUfo : public ArticleState\n\t{\n\tpublic:\n\t\tArticleStateUfo(ArticleDefinitionUfo *article_defs, std::shared_ptr<ArticleCommonState> state);\n\t\tvirtual ~ArticleStateUfo();\n\n\tprotected:\n\t\tSurface *_image;\n\t\tText *_txtTitle;\n\t\tText *_txtInfo;\n\t\tTextList *_lstInfo;\n\t};\n}\n"
  },
  {
    "path": "src/Ufopaedia/ArticleStateUnit.cpp",
    "content": "/*\n * Copyright 2010-2025 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include <sstream>\n#include \"ArticleStateUnit.h\"\n#include \"../Mod/ArticleDefinition.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Mod/Unit.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Palette.h\"\n#include \"../Engine/Surface.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Unicode.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Mod/RuleInterface.h\"\n#include \"../fmath.h\"\n#include \"../Savegame/SavedGame.h\"\n\nnamespace OpenXcom\n{\n\n\tArticleStateUnit::ArticleStateUnit(ArticleDefinitionUnit *defs, std::shared_ptr<ArticleCommonState> state) : ArticleState(defs->id, std::move(state))\n\t{\n\t\tUnit *unit = _game->getMod()->getUnit(defs->id, true);\n\n\t\t// add screen elements\n\t\t_txtTitle = new Text(310, 17, 5, 23);\n\n\t\t// Set palette\n\t\tif (defs->customPalette)\n\t\t{\n\t\t\tsetCustomPalette(_game->getMod()->getSurface(defs->image_id)->getPalette(), Mod::UFOPAEDIA_CURSOR);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tsetStandardPalette(\"PAL_UFOPAEDIA\");\n\t\t}\n\n\t\tRuleInterface* itf = _game->getMod()->getInterface(\"articleUnit\");\n\t\tint buttonColor = itf->getElement(\"button\")->color;\n\t\tint titleColor1 = itf->getElement(\"title\")->color;\n\t\tint titleColor2 = itf->getElement(\"title\")->color2;\n\t\tint textColor1 = itf->getElement(\"text\")->color;\n\t\tint textColor2 = itf->getElement(\"text\")->color2;\n\t\tint listColor1 = itf->getElement(\"list\")->color;\n\t\tint listColor2 = itf->getElement(\"list\")->color2;\n\n\t\tArticleState::initLayout();\n\n\t\t// add other elements\n\t\tadd(_txtTitle);\n\n\t\t// Set up objects\n\t\t_game->getMod()->getSurface(defs->image_id)->blitNShade(_bg, 0, 0);\n\t\t_btnOk->setColor(buttonColor);\n\t\t_btnPrev->setColor(buttonColor);\n\t\t_btnNext->setColor(buttonColor);\n\t\t_btnInfo->setColor(buttonColor);\n\t\t_btnInfo->setVisible(_game->getMod()->getShowPediaInfoButton());\n\n\t\t_txtTitle->setColor(titleColor1);\n\t\t_txtTitle->setSecondaryColor(titleColor2);\n\t\t_txtTitle->setBig();\n\t\t_txtTitle->setWordWrap(true);\n\t\t_txtTitle->setText(tr(defs->getTitleForPage(_state->current_page)));\n\n\t\t_txtInfo = new Text(defs->rect_text.width, defs->rect_text.height, defs->rect_text.x, defs->rect_text.y);\n\t\tadd(_txtInfo);\n\n\t\t_txtInfo->setColor(textColor1);\n\t\t_txtInfo->setSecondaryColor(textColor2);\n\t\t_txtInfo->setWordWrap(true);\n\t\t_txtInfo->setScrollable(true);\n\t\t_txtInfo->setText(tr(defs->getTextForPage(_state->current_page)));\n\n\t\tint widthStats = Clamp(defs->rect_stats.width, 60, 320);\n\t\t_lstStats = new TextList(widthStats, defs->rect_stats.height, defs->rect_stats.x, defs->rect_stats.y);\n\t\tadd(_lstStats);\n\n\t\t_lstStats->setColor(listColor1);\n\t\t_lstStats->setSecondaryColor(listColor2);\n\t\t_lstStats->setColumns(3, widthStats - 40, 20, 20);\n\t\t_lstStats->setDot(true);\n\n\t\tint widthArmor = Clamp(defs->rect_armor.width, 60, 320);\n\t\t_lstArmor = new TextList(widthArmor, defs->rect_armor.height, defs->rect_armor.x, defs->rect_armor.y);\n\t\tadd(_lstArmor);\n\n\t\t_lstArmor->setColor(listColor1);\n\t\t_lstArmor->setSecondaryColor(listColor2);\n\t\t_lstArmor->setColumns(3, widthArmor - 40, 20, 20);\n\t\t_lstArmor->setDot(true);\n\t\tif (defs->rect_armor.height == 0)\n\t\t{\n\t\t\t_lstArmor->setVisible(false);\n\t\t}\n\n\t\t_txtDifficulty = new Text(160, 9, defs->rect_stats.x + widthStats - (defs->unit_mode == 2 ? 20 : 40), defs->rect_stats.y - 10);\n\t\tadd(_txtDifficulty);\n\n\t\t_txtDifficulty->setColor(textColor1);\n\t\t_txtDifficulty->setSecondaryColor(textColor2);\n\n\t\tUnitStats civ = *unit->getStats();\n\t\tUnitStats alien = civ;\n\n\t\tint civArmor[SIDE_MAX];\n\t\tcivArmor[SIDE_FRONT] = unit->getArmor()->getFrontArmor();\n\t\tcivArmor[SIDE_LEFT] = unit->getArmor()->getLeftSideArmor();\n\t\tcivArmor[SIDE_RIGHT] = unit->getArmor()->getRightSideArmor();\n\t\tcivArmor[SIDE_REAR] = unit->getArmor()->getRearArmor();\n\t\tcivArmor[SIDE_UNDER] = unit->getArmor()->getUnderArmor();\n\n\t\tint alienArmor[SIDE_MAX];\n\t\talienArmor[SIDE_FRONT] = civArmor[SIDE_FRONT];\n\t\talienArmor[SIDE_LEFT] = civArmor[SIDE_LEFT];\n\t\talienArmor[SIDE_RIGHT] = civArmor[SIDE_RIGHT];\n\t\talienArmor[SIDE_REAR] = civArmor[SIDE_REAR];\n\t\talienArmor[SIDE_UNDER] = civArmor[SIDE_UNDER];\n\n\t\tif (_game->getSavedGame())\n\t\t{\n\t\t\tif (defs->unit_mode != 1)\n\t\t\t{\n\t\t\t\tstd::string diff;\n\t\t\t\tswitch (_game->getSavedGame()->getDifficulty())\n\t\t\t\t{\n\t\t\t\tcase DIFF_SUPERHUMAN: diff = tr(\"STR_5_SUPERHUMAN\"); break;\n\t\t\t\tcase DIFF_GENIUS: diff = tr(\"STR_4_GENIUS\"); break;\n\t\t\t\tcase DIFF_VETERAN: diff = tr(\"STR_3_VETERAN\"); break;\n\t\t\t\tcase DIFF_EXPERIENCED: diff = tr(\"STR_2_EXPERIENCED\"); break;\n\t\t\t\tdefault: diff = tr(\"STR_1_BEGINNER\"); break;\n\t\t\t\t}\n\t\t\t\t_txtDifficulty->setText(diff);\n\t\t\t}\n\n\t\t\t// FACTION_HOSTILE scales with difficulty\n\t\t\tauto* adjustment = _game->getMod()->getStatAdjustment(_game->getSavedGame()->getDifficulty());\n\n\t\t\talien += UnitStats::percent(alien, adjustment->statGrowth, adjustment->growthMultiplier);\n\n\t\t\talien.firing *= adjustment->aimMultiplier;\n\t\t\talien += adjustment->statGrowthAbs;\n\n\t\t\tfor (int i = 0; i < SIDE_MAX; ++i)\n\t\t\t{\n\t\t\t\talienArmor[i] *= adjustment->armorMultiplier;\n\t\t\t\talienArmor[i] += adjustment->armorMultiplierAbs;\n\t\t\t}\n\t\t}\n\n\t\t// defs->unit_mode == 0  show as hostile (incl. difficulty)\n\t\t// defs->unit_mode == 1  show as neutral/allied\n\t\t// defs->unit_mode == 2  show as neutral/allied first, then also as hostile (incl. difficulty)\n\t\tint columns = defs->unit_mode > 1 ? 3 : 2;\n\n\t\tif (defs->unit_mode == 0)\n\t\t{\n\t\t\tciv = alien;\n\n\t\t\tfor (int i = 0; i < SIDE_MAX; ++i)\n\t\t\t{\n\t\t\t\tcivArmor[i] = alienArmor[i];\n\t\t\t}\n\t\t}\n\n\t\t_lstStats->addRow(columns, tr(\"STR_TIME_UNITS\").c_str(), std::to_string(civ.tu).c_str(), std::to_string(alien.tu).c_str());\n\t\t_lstStats->addRow(columns, tr(\"STR_STAMINA\").c_str(), std::to_string(civ.stamina).c_str(), std::to_string(alien.stamina).c_str());\n\t\t_lstStats->addRow(columns, tr(\"STR_HEALTH\").c_str(), std::to_string(civ.health).c_str(), std::to_string(alien.health).c_str());\n\t\t_lstStats->addRow(columns, tr(\"STR_BRAVERY\").c_str(), std::to_string(civ.bravery).c_str(), std::to_string(alien.bravery).c_str());\n\t\t_lstStats->addRow(columns, tr(\"STR_REACTIONS\").c_str(), std::to_string(civ.reactions).c_str(), std::to_string(alien.reactions).c_str());\n\t\t_lstStats->addRow(columns, tr(\"STR_FIRING_ACCURACY\").c_str(), std::to_string(civ.firing).c_str(), std::to_string(alien.firing).c_str());\n\t\t_lstStats->addRow(columns, tr(\"STR_THROWING_ACCURACY\").c_str(), std::to_string(civ.throwing).c_str(), std::to_string(alien.throwing).c_str());\n\t\t_lstStats->addRow(columns, tr(\"STR_MELEE_ACCURACY\").c_str(), std::to_string(civ.melee).c_str(), std::to_string(alien.melee).c_str());\n\t\t_lstStats->addRow(columns, tr(\"STR_STRENGTH\").c_str(), std::to_string(civ.strength).c_str(), std::to_string(alien.strength).c_str());\n\t\tif (_game->getMod()->isManaFeatureEnabled())\n\t\t{\n\t\t\t_lstStats->addRow(columns, tr(\"STR_MANA_POOL\").c_str(), std::to_string(civ.mana).c_str(), std::to_string(alien.mana).c_str());\n\t\t}\n\t\t_lstStats->addRow(columns, tr(\"STR_PSIONIC_STRENGTH\").c_str(), std::to_string(civ.psiStrength).c_str(), std::to_string(alien.psiStrength).c_str());\n\t\t_lstStats->addRow(columns, tr(\"STR_PSIONIC_SKILL\").c_str(), std::to_string(civ.psiSkill).c_str(), std::to_string(alien.psiSkill).c_str());\n\n\t\t_lstArmor->addRow(columns, tr(\"STR_FRONT_ARMOR\").c_str(), std::to_string(civArmor[SIDE_FRONT]).c_str(), std::to_string(alienArmor[SIDE_FRONT]).c_str());\n\t\t_lstArmor->addRow(columns, tr(\"STR_LEFT_ARMOR\").c_str(), std::to_string(civArmor[SIDE_LEFT]).c_str(), std::to_string(alienArmor[SIDE_LEFT]).c_str());\n\t\t_lstArmor->addRow(columns, tr(\"STR_RIGHT_ARMOR\").c_str(), std::to_string(civArmor[SIDE_RIGHT]).c_str(), std::to_string(alienArmor[SIDE_RIGHT]).c_str());\n\t\t_lstArmor->addRow(columns, tr(\"STR_REAR_ARMOR\").c_str(), std::to_string(civArmor[SIDE_REAR]).c_str(), std::to_string(alienArmor[SIDE_REAR]).c_str());\n\t\t_lstArmor->addRow(columns, tr(\"STR_UNDER_ARMOR\").c_str(), std::to_string(civArmor[SIDE_UNDER]).c_str(), std::to_string(alienArmor[SIDE_UNDER]).c_str());\n\n\t\tcenterAllSurfaces();\n\t}\n\n\tArticleStateUnit::~ArticleStateUnit()\n\t{}\n\n}\n"
  },
  {
    "path": "src/Ufopaedia/ArticleStateUnit.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2025 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ArticleState.h\"\n\nnamespace OpenXcom\n{\n\tclass Game;\n\tclass Text;\n\tclass TextList;\n\tclass ArticleDefinitionUnit;\n\n\t/**\n\t * ArticleStateUnit has a caption, text, background image, an armor block and a stats block.\n\t * The layout of the description text, armor block and stats block can vary,\n\t * depending on the background image.\n\t */\n\n\tclass ArticleStateUnit : public ArticleState\n\t{\n\tpublic:\n\t\tArticleStateUnit(ArticleDefinitionUnit *article_defs, std::shared_ptr<ArticleCommonState> state);\n\t\tvirtual ~ArticleStateUnit();\n\n\tprotected:\n\t\tText *_txtTitle;\n\t\tText *_txtInfo;\n\t\tText *_txtDifficulty;\n\t\tTextList *_lstStats;\n\t\tTextList *_lstArmor;\n\t};\n}\n"
  },
  {
    "path": "src/Ufopaedia/ArticleStateVehicle.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"../Mod/ArticleDefinition.h\"\n#include \"ArticleStateVehicle.h\"\n#include <sstream>\n#include \"../Engine/Game.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Palette.h\"\n#include \"../Engine/Surface.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Mod/Unit.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Mod/RuleItem.h\"\n\nnamespace OpenXcom\n{\n\n\tArticleStateVehicle::ArticleStateVehicle(ArticleDefinitionVehicle *defs, std::shared_ptr<ArticleCommonState> state) : ArticleState(defs->id, std::move(state))\n\t{\n\t\tRuleItem *item = _game->getMod()->getItem(defs->id, true);\n\t\tUnit *unit = item->getVehicleUnit();\n\t\tif (!unit)\n\t\t{\n\t\t\tthrow Exception(\"ArticleStateVehicle: Item \" + defs->id + \" is missing a vehicle unit definition!\");\n\t\t}\n\t\tconst Armor *armor = unit->getArmor();\n\n\t\t// add screen elements\n\t\t_txtTitle = new Text(310, 17, 5, 23);\n\t\t_txtInfo = new Text(300, 150, 10, 122);\n\t\t_lstStats = new TextList(300, 89, 10, 48);\n\n\t\t// Set palette\n\t\tif (defs->customPalette)\n\t\t{\n\t\t\tsetCustomPalette(_game->getMod()->getSurface(defs->image_id)->getPalette(), Mod::UFOPAEDIA_CURSOR);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tsetStandardPalette(\"PAL_UFOPAEDIA\");\n\t\t}\n\n\t\tArticleState::initLayout();\n\n\t\t// add other elements\n\t\tadd(_txtTitle);\n\t\tadd(_txtInfo);\n\t\tadd(_lstStats);\n\n\t\t// Set up objects\n\t\tif (!defs->image_id.empty())\n\t\t{\n\t\t\t_game->getMod()->getSurface(defs->image_id)->blitNShade(_bg, 0, 0);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_game->getMod()->getSurface(\"BACK10.SCR\")->blitNShade(_bg, 0, 0);\n\t\t}\n\t\t_btnOk->setColor(Palette::blockOffset(5));\n\t\t_btnPrev->setColor(Palette::blockOffset(5));\n\t\t_btnNext->setColor(Palette::blockOffset(5));\n\n\t\t_txtTitle->setColor(Palette::blockOffset(15)+4);\n\t\t_txtTitle->setBig();\n\t\t_txtTitle->setText(tr(defs->getTitleForPage(_state->current_page)));\n\n\t\t_txtInfo->setColor(Palette::blockOffset(15)-1);\n\t\t_txtInfo->setSecondaryColor(Palette::blockOffset(15) + 4);\n\t\t_txtInfo->setWordWrap(true);\n\t\t_txtInfo->setScrollable(true);\n\t\t_txtInfo->setText(tr(defs->getTextForPage(_state->current_page)));\n\n\t\t_lstStats->setColor(Palette::blockOffset(15)+4);\n\t\t_lstStats->setColumns(2, 175, 145);\n\t\t_lstStats->setDot(true);\n\n\t\tstd::ostringstream ss;\n\t\tss << unit->getStats()->tu;\n\t\t_lstStats->addRow(2, tr(\"STR_TIME_UNITS\").c_str(), ss.str().c_str());\n\n\t\tstd::ostringstream ss2;\n\t\tss2 << unit->getStats()->health;\n\t\t_lstStats->addRow(2, tr(\"STR_HEALTH\").c_str(), ss2.str().c_str());\n\n\t\tstd::ostringstream ss3;\n\t\tss3 << armor->getFrontArmor();\n\t\t_lstStats->addRow(2, tr(\"STR_FRONT_ARMOR\").c_str(), ss3.str().c_str());\n\n\t\tstd::ostringstream ss4;\n\t\tss4 << armor->getLeftSideArmor();\n\t\t_lstStats->addRow(2, tr(\"STR_LEFT_ARMOR\").c_str(), ss4.str().c_str());\n\n\t\tstd::ostringstream ss5;\n\t\tss5 << armor->getRightSideArmor();\n\t\t_lstStats->addRow(2, tr(\"STR_RIGHT_ARMOR\").c_str(), ss5.str().c_str());\n\n\t\tstd::ostringstream ss6;\n\t\tss6 << armor->getRearArmor();\n\t\t_lstStats->addRow(2, tr(\"STR_REAR_ARMOR\").c_str(), ss6.str().c_str());\n\n\t\tstd::ostringstream ss7;\n\t\tss7 << armor->getUnderArmor();\n\t\t_lstStats->addRow(2, tr(\"STR_UNDER_ARMOR\").c_str(), ss7.str().c_str());\n\n\t\t_lstStats->addRow(2, tr(\"STR_WEAPON\").c_str(), tr(defs->weapon).c_str());\n\n\t\tif (item->getVehicleClipAmmo())\n\t\t{\n\t\t\tconst RuleItem *ammo = item->getVehicleClipAmmo();\n\n\t\t\tstd::ostringstream ss8;\n\t\t\tif (item->getIgnoreAmmoPower())\n\t\t\t{\n\t\t\t\tss8 << item->getPower();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tss8 << ammo->getPower();\n\t\t\t}\n\t\t\t_lstStats->addRow(2, tr(\"STR_WEAPON_POWER\").c_str(), ss8.str().c_str());\n\n\t\t\t_lstStats->addRow(2, tr(\"STR_AMMUNITION\").c_str(), tr(ammo->getName()).c_str());\n\n\t\t\tstd::ostringstream ss9;\n\t\t\tss9 << item->getVehicleClipSize();\n\n\t\t\t_lstStats->addRow(2, tr(\"STR_ROUNDS\").c_str(), ss9.str().c_str());\n\n\t\t\t_txtInfo->setY(138);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tstd::ostringstream ss8;\n\t\t\tss8 << item->getPower();\n\t\t\t_lstStats->addRow(2, tr(\"STR_WEAPON_POWER\").c_str(), ss8.str().c_str());\n\t\t}\n\t\tcenterAllSurfaces();\n\t}\n\n\tArticleStateVehicle::~ArticleStateVehicle()\n\t{}\n\n}\n"
  },
  {
    "path": "src/Ufopaedia/ArticleStateVehicle.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"ArticleState.h\"\n\nnamespace OpenXcom\n{\n\tclass Game;\n\tclass Text;\n\tclass TextList;\n\tclass ArticleDefinitionVehicle;\n\n\t/**\n\t * ArticleStateVehicle has a caption, text and a stats block.\n\t */\n\n\tclass ArticleStateVehicle : public ArticleState\n\t{\n\tpublic:\n\t\tArticleStateVehicle(ArticleDefinitionVehicle *article_defs, std::shared_ptr<ArticleCommonState> state);\n\t\tvirtual ~ArticleStateVehicle();\n\n\tprotected:\n\t\tText *_txtTitle;\n\t\tText *_txtInfo;\n\t\tTextList *_lstStats;\n\t};\n}\n"
  },
  {
    "path": "src/Ufopaedia/StatsForNerdsState.cpp",
    "content": "/*\n * Copyright 2010-2018 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"StatsForNerdsState.h\"\n#include \"Ufopaedia.h\"\n#include \"../Battlescape/BattlescapeGenerator.h\"\n#include \"../Battlescape/BriefingState.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Language.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/ScriptBind.h\"\n#include \"../Interface/ComboBox.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Interface/ToggleTextButton.h\"\n#include \"../Interface/Window.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Mod/ExtraSounds.h\"\n#include \"../Mod/ExtraSprites.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleBaseFacility.h\"\n#include \"../Mod/RuleCommendations.h\"\n#include \"../Mod/RuleCraft.h\"\n#include \"../Mod/RuleCraftWeapon.h\"\n#include \"../Mod/RuleInterface.h\"\n#include \"../Mod/RuleInventory.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"../Mod/RuleSoldier.h\"\n#include \"../Mod/RuleSoldierBonus.h\"\n#include \"../Mod/RuleUfo.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/BattleUnit.h\"\n#include \"../Savegame/SavedBattleGame.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../fmath.h\"\n#include <algorithm>\n\nnamespace OpenXcom\n{\n\nconst std::map<std::string, std::string> StatsForNerdsState::translationMap =\n{\n\t{ \"flatOne\", \"\" }, // no translation\n\t{ \"flatHundred\", \"\" }, // no translation\n\t{ \"strength\", \"STR_STRENGTH\" },\n\t{ \"psi\", \"STR_PSI_SKILL_AND_PSI_STRENGTH\" }, // new, STR_PSIONIC_SKILL * STR_PSIONIC_STRENGTH\n\t{ \"psiSkill\", \"STR_PSIONIC_SKILL\" },\n\t{ \"psiStrength\", \"STR_PSIONIC_STRENGTH\" },\n\t{ \"throwing\", \"STR_THROWING_ACCURACY\" },\n\t{ \"bravery\", \"STR_BRAVERY\" },\n\t{ \"firing\", \"STR_FIRING_ACCURACY\" },\n\t{ \"health\", \"STR_HEALTH\" },\n\t{ \"mana\", \"STR_MANA_POOL\" },\n\t{ \"tu\", \"STR_TIME_UNITS\" },\n\t{ \"reactions\", \"STR_REACTIONS\" },\n\t{ \"stamina\", \"STR_STAMINA\" },\n\t{ \"melee\", \"STR_MELEE_ACCURACY\" },\n\t{ \"strengthMelee\", \"STR_STRENGTH_AND_MELEE_ACCURACY\" }, // new, STR_STRENGTH * STR_MELEE_ACCURACY\n\t{ \"strengthThrowing\", \"STR_STRENGTH_AND_THROWING_ACCURACY\" }, // new, STR_STRENGTH * STR_THROWING_ACCURACY\n\t{ \"firingReactions\", \"STR_FIRING_ACCURACY_AND_REACTIONS\" }, // new, STR_FIRING_ACCURACY * STR_REACTIONS\n\n\t{ \"rank\", \"STR_RANK\" },\n\t{ \"fatalWounds\", \"STR_FATAL_WOUNDS\" },\n\n\t{ \"healthCurrent\", \"STR_HEALTH_CURRENT\" }, // new, current HP (i.e. not max HP)\n\t{ \"manaCurrent\", \"STR_MANA_CURRENT\" },\n\t{ \"tuCurrent\", \"STR_TIME_UNITS_CURRENT\" }, // new\n\t{ \"energyCurrent\", \"STR_ENERGY\" },\n\t{ \"moraleCurrent\", \"STR_MORALE\" },\n\t{ \"stunCurrent\", \"STR_STUN_LEVEL_CURRENT\" }, // new\n\n\t{ \"healthNormalized\", \"STR_HEALTH_NORMALIZED\" }, // new, current HP normalized to [0, 1] interval\n\t{ \"manaNormalized\", \"STR_MANA_NORMALIZED\" },\n\t{ \"tuNormalized\", \"STR_TIME_UNITS_NORMALIZED\" }, // new\n\t{ \"energyNormalized\", \"STR_ENERGY_NORMALIZED\" }, // new\n\t{ \"moraleNormalized\", \"STR_MORALE_NORMALIZED\" }, // new\n\t{ \"stunNormalized\", \"STR_STUN_LEVEL_NORMALIZED\" }, // new\n\n\t{ \"energyRegen\", \"STR_ENERGY_REGENERATION\" }, // new, special stat returning vanilla energy regen\n\n\t{ \"tuScaled\", \"STR_TIME_UNITS_SCALED\" },\n\t{ \"staminaScaled\", \"STR_STAMINA_SCALED\" },\n\t{ \"healthScaled\", \"STR_HEALTH_SCALED\" },\n\t{ \"braveryScaled\", \"STR_BRAVERY_SCALED\" },\n\t{ \"reactionsScaled\", \"STR_REACTIONS_SCALED\" },\n\t{ \"firingScaled\", \"STR_FIRING_ACCURACY_SCALED\" },\n\t{ \"throwingScaled\", \"STR_THROWING_ACCURACY_SCALED\" },\n\t{ \"strengthScaled\", \"STR_STRENGTH_SCALED\" },\n\t{ \"psiStrengthScaled\", \"STR_PSIONIC_STRENGTH_SCALED\" },\n\t{ \"psiSkillScaled\", \"STR_PSIONIC_SKILL_SCALED\" },\n\t{ \"meleeScaled\", \"STR_MELEE_ACCURACY_SCALED\" },\n\t{ \"manaScaled\", \"STR_MANA_POOL_SCALED\" },\n\t{ \"psiScaled\", \"STR_PSI_SKILL_AND_PSI_STRENGTH_SCALED\" },\n\t{ \"strengthMeleeScaled\", \"STR_STRENGTH_AND_MELEE_ACCURACY_SCALED\" },\n\t{ \"strengthThrowingScaled\", \"STR_STRENGTH_AND_THROWING_ACCURACY_SCALED\" },\n\t{ \"firingReactionsScaled\", \"STR_FIRING_ACCURACY_AND_REACTIONS_SCALED\" },\n};\n\nconst std::map<std::string, std::string> StatsForNerdsState::shortTranslationMap =\n{\n\t{ \"flatOne\", \"\" }, // no translation\n\t{ \"flatHundred\", \"\" }, // no translation\n\t{ \"strength\", \"STR_STRENGTH_ABBREVIATION\" },\n\t{ \"psi\", \"STR_PSI_SKILL_AND_PSI_STRENGTH_ABBREVIATION\" }, // new, STR_PSIONIC_SKILL * STR_PSIONIC_STRENGTH\n\t{ \"psiSkill\", \"STR_PSIONIC_SKILL_ABBREVIATION\" },\n\t{ \"psiStrength\", \"STR_PSIONIC_STRENGTH_ABBREVIATION\" },\n\t{ \"throwing\", \"STR_THROWING_ACCURACY_ABBREVIATION\" },\n\t{ \"bravery\", \"STR_BRAVERY_ABBREVIATION\" },\n\t{ \"firing\", \"STR_FIRING_ACCURACY_ABBREVIATION\" },\n\t{ \"health\", \"STR_HEALTH_ABBREVIATION\" },\n\t{ \"mana\", \"STR_MANA_ABBREVIATION\" },\n\t{ \"tu\", \"STR_TIME_UNITS_ABBREVIATION\" },\n\t{ \"reactions\", \"STR_REACTIONS_ABBREVIATION\" },\n\t{ \"stamina\", \"STR_STAMINA_ABBREVIATION\" },\n\t{ \"melee\", \"STR_MELEE_ACCURACY_ABBREVIATION\" },\n\t{ \"strengthMelee\", \"STR_STRENGTH_AND_MELEE_ACCURACY_ABBREVIATION\" }, // new, STR_STRENGTH * STR_MELEE_ACCURACY\n\t{ \"strengthThrowing\", \"STR_STRENGTH_AND_THROWING_ACCURACY_ABBREVIATION\" }, // new, STR_STRENGTH * STR_THROWING_ACCURACY\n\t{ \"firingReactions\", \"STR_FIRING_ACCURACY_AND_REACTIONS_ABBREVIATION\" }, // new, STR_FIRING_ACCURACY * STR_REACTIONS\n\n\t{ \"rank\", \"STR_RANK\" },\n\t{ \"fatalWounds\", \"STR_FATAL_WOUNDS\" },\n\n\t{ \"healthCurrent\", \"STR_HEALTH_CURRENT_ABBREVIATION\" }, // new, current HP (i.e. not max HP)\n\t{ \"manaCurrent\", \"STR_MANA_CURRENT_ABBREVIATION\" },\n\t{ \"tuCurrent\", \"STR_TIME_UNITS_CURRENT_ABBREVIATION\" }, // new\n\t{ \"energyCurrent\", \"STR_ENERGY\" },\n\t{ \"moraleCurrent\", \"STR_MORALE\" },\n\t{ \"stunCurrent\", \"STR_STUN_LEVEL_CURRENT_ABBREVIATION\" }, // new\n\n\t{ \"healthNormalized\", \"STR_HEALTH_NORMALIZED_ABBREVIATION\" }, // new, current HP normalized to [0, 1] interval\n\t{ \"manaNormalized\", \"STR_MANA_NORMALIZED_ABBREVIATION\" },\n\t{ \"tuNormalized\", \"STR_TIME_UNITS_NORMALIZED_ABBREVIATION\" }, // new\n\t{ \"energyNormalized\", \"STR_ENERGY_NORMALIZED_ABBREVIATION\" }, // new\n\t{ \"moraleNormalized\", \"STR_MORALE_NORMALIZED_ABBREVIATION\" }, // new\n\t{ \"stunNormalized\", \"STR_STUN_LEVEL_NORMALIZED_ABBREVIATION\" }, // new\n\n\t{ \"energyRegen\", \"STR_ENERGY_REGENERATION_ABBREVIATION\" }, // new, special stat returning vanilla energy regen\n\n\t{ \"tuScaled\", \"STR_TIME_UNITS_SCALED_ABBREVIATION\" },\n\t{ \"staminaScaled\", \"STR_STAMINA_SCALED_ABBREVIATION\" },\n\t{ \"healthScaled\", \"STR_HEALTH_SCALED_ABBREVIATION\" },\n\t{ \"braveryScaled\", \"STR_BRAVERY_SCALED_ABBREVIATION\" },\n\t{ \"reactionsScaled\", \"STR_REACTIONS_SCALED_ABBREVIATION\" },\n\t{ \"firingScaled\", \"STR_FIRING_ACCURACY_SCALED_ABBREVIATION\" },\n\t{ \"throwingScaled\", \"STR_THROWING_ACCURACY_SCALED_ABBREVIATION\" },\n\t{ \"strengthScaled\", \"STR_STRENGTH_SCALED_ABBREVIATION\" },\n\t{ \"psiStrengthScaled\", \"STR_PSIONIC_STRENGTH_SCALED_ABBREVIATION\" },\n\t{ \"psiSkillScaled\", \"STR_PSIONIC_SKILL_SCALED_ABBREVIATION\" },\n\t{ \"meleeScaled\", \"STR_MELEE_ACCURACY_SCALED_ABBREVIATION\" },\n\t{ \"manaScaled\", \"STR_MANA_POOL_SCALED_ABBREVIATION\" },\n\t{ \"psiScaled\", \"STR_PSI_SKILL_AND_PSI_STRENGTH_SCALED_ABBREVIATION\" },\n\t{ \"strengthMeleeScaled\", \"STR_STRENGTH_AND_MELEE_ACCURACY_SCALED_ABBREVIATION\" },\n\t{ \"strengthThrowingScaled\", \"STR_STRENGTH_AND_THROWING_ACCURACY_SCALED_ABBREVIATION\" },\n\t{ \"firingReactionsScaled\", \"STR_FIRING_ACCURACY_AND_REACTIONS_SCALED_ABBREVIATION\" },\n};\n\n/**\n * Initializes all the elements on the UI.\n */\nStatsForNerdsState::StatsForNerdsState(std::shared_ptr<ArticleCommonState> state, bool debug, bool ids, bool defaults) : _state{ std::move(state) }, _counter(0), _indent(false)\n{\n\tauto* article = _state->getCurrentArticle();\n\t_typeId = article->getType();\n\t_topicId = article->id;\n\t_mainArticle = true;\n\n\tbuildUI(debug, ids, defaults);\n}\n\n/**\n * Initializes all the elements on the UI.\n */\nStatsForNerdsState::StatsForNerdsState(const UfopaediaTypeId typeId, const std::string topicId, bool debug, bool ids, bool defaults) : _counter(0), _indent(false)\n{\n\t_typeId = typeId;\n\t_topicId = topicId;\n\t_mainArticle = false;\n\n\tbuildUI(debug, ids, defaults);\n}\n\n/**\n * Builds the UI.\n */\nvoid StatsForNerdsState::buildUI(bool debug, bool ids, bool defaults)\n{\n\t// Create objects\n\t_window = new Window(this, 320, 200, 0, 0);\n\t_txtTitle = new Text(304, 17, 8, 7);\n\t_cbxRelatedStuff = new ComboBox(this, 148, 16, 164, 7);\n\t_txtArticle = new Text(230, 9, 8, 24);\n\t_btnPrev = new TextButton(33, 14, 242, 24);\n\t_btnNext = new TextButton(33, 14, 279, 24);\n\t_lstRawData = new TextList(287, 128, 8, 40);\n\t_btnIncludeDebug = new ToggleTextButton(70, 16, 8, 176);\n\t_btnIncludeIds = new ToggleTextButton(70, 16, 86, 176);\n\t_btnIncludeDefaults = new ToggleTextButton(70, 16, 164, 176);\n\t_btnOk = new TextButton(70, 16, 242, 176);\n\t_btnPreview = new TextButton(102, 16, 210, 7);\n\n\t// Set palette\n\tsetInterface(\"statsForNerds\");\n\n\t_purple = _game->getMod()->getInterface(\"statsForNerds\")->getElement(\"list\")->color;\n\t_pink = _game->getMod()->getInterface(\"statsForNerds\")->getElement(\"list\")->color2;\n\t_blue = _game->getMod()->getInterface(\"statsForNerds\")->getElement(\"list\")->border;\n\t_white = _game->getMod()->getInterface(\"statsForNerds\")->getElement(\"listExtended\")->color;\n\t_gold = _game->getMod()->getInterface(\"statsForNerds\")->getElement(\"listExtended\")->color2;\n\n\tadd(_window, \"window\", \"statsForNerds\");\n\tadd(_txtTitle, \"text\", \"statsForNerds\");\n\tadd(_txtArticle, \"text\", \"statsForNerds\");\n\tadd(_lstRawData, \"list\", \"statsForNerds\");\n\tadd(_btnIncludeDebug, \"button\", \"statsForNerds\");\n\tadd(_btnIncludeIds, \"button\", \"statsForNerds\");\n\tadd(_btnIncludeDefaults, \"button\", \"statsForNerds\");\n\tadd(_btnOk, \"button\", \"statsForNerds\");\n\tadd(_btnPreview, \"button\", \"statsForNerds\");\n\tadd(_btnPrev, \"button\", \"statsForNerds\");\n\tadd(_btnNext, \"button\", \"statsForNerds\");\n\tadd(_cbxRelatedStuff, \"comboBox\", \"statsForNerds\");\n\n\tcenterAllSurfaces();\n\n\t// Set up objects\n\tsetWindowBackground(_window, \"statsForNerds\");\n\n\t_txtTitle->setBig();\n\t_txtTitle->setAlign(ALIGN_CENTER);\n\t_txtTitle->setText(tr(\"STR_STATS_FOR_NERDS\"));\n\n\t_txtArticle->setText(tr(\"STR_ARTICLE\").arg(tr(_topicId)));\n\n\t_lstRawData->setColumns(2, 110, 177);\n\t_lstRawData->setSelectable(true);\n\t_lstRawData->setBackground(_window);\n\t_lstRawData->setWordWrap(true);\n\n\t_btnIncludeDebug->setText(tr(\"STR_INCLUDE_DEBUG\"));\n\t_btnIncludeDebug->setPressed(debug);\n\t_btnIncludeDebug->onMouseClick((ActionHandler)&StatsForNerdsState::btnRefreshClick);\n\n\t_btnIncludeIds->setText(tr(\"STR_INCLUDE_IDS\"));\n\t_btnIncludeIds->setPressed(ids);\n\t_btnIncludeIds->onMouseClick((ActionHandler)&StatsForNerdsState::btnRefreshClick);\n\n\t_btnIncludeDefaults->setText(tr(\"STR_INCLUDE_DEFAULTS\"));\n\t_btnIncludeDefaults->setPressed(defaults);\n\t_btnIncludeDefaults->onMouseClick((ActionHandler)&StatsForNerdsState::btnRefreshClick);\n\n\t_btnOk->setText(tr(\"STR_OK\"));\n\t_btnOk->onMouseClick((ActionHandler)&StatsForNerdsState::btnOkClick);\n\t_btnOk->onKeyboardPress((ActionHandler)&StatsForNerdsState::btnOkClick, Options::keyCancel);\n\t_btnOk->onKeyboardPress((ActionHandler)&StatsForNerdsState::btnScrollUpClick, Options::keyGeoUp);\n\t_btnOk->onKeyboardPress((ActionHandler)&StatsForNerdsState::btnScrollDownClick, Options::keyGeoDown);\n\n\t_btnPreview->setText(tr(\"STR_CRAFT_DEPLOYMENT_PREVIEW\"));\n\t_btnPreview->onMouseClick((ActionHandler)&StatsForNerdsState::btnPreviewClick);\n\t_btnPreview->setVisible(false);\n\n\t_btnPrev->setText(\"<<\");\n\t_btnPrev->onMouseClick((ActionHandler)&StatsForNerdsState::btnPrevClick);\n\t_btnPrev->onKeyboardPress((ActionHandler)&StatsForNerdsState::btnPrevClick, Options::keyGeoLeft);\n\n\t_btnNext->setText(\">>\");\n\t_btnNext->onMouseClick((ActionHandler)&StatsForNerdsState::btnNextClick);\n\t_btnNext->onKeyboardPress((ActionHandler)&StatsForNerdsState::btnNextClick, Options::keyGeoRight);\n\n\tif (Options::oxceDisableStatsForNerds)\n\t{\n\t\t_txtTitle->setHeight(_txtTitle->getHeight() * 9);\n\t\t_txtTitle->setWordWrap(true);\n\t\t_txtTitle->setText(tr(\"STR_THIS_FEATURE_IS_DISABLED_2\"));\n\t\t_txtArticle->setVisible(false);\n\t\t_lstRawData->setVisible(false);\n\t\t_btnIncludeDebug->setVisible(false);\n\t\t_btnIncludeIds->setVisible(false);\n\t\t_btnIncludeDefaults->setVisible(false);\n\t\t_btnPrev->setVisible(false);\n\t\t_btnNext->setVisible(false);\n\t\t_cbxRelatedStuff->setVisible(false);\n\t\treturn;\n\t}\n\n\tif (!_mainArticle)\n\t{\n\t\t_btnPrev->setVisible(false);\n\t\t_btnNext->setVisible(false);\n\t}\n\n\t_filterOptions.clear();\n\t_filterOptions.push_back(\"STR_UNKNOWN\");\n\t_cbxRelatedStuff->setOptions(_filterOptions, true);\n\t_cbxRelatedStuff->onChange((ActionHandler)&StatsForNerdsState::cbxAmmoSelect);\n\t_cbxRelatedStuff->setVisible(_filterOptions.size() > 1);\n}\n\n/**\n *\n */\nStatsForNerdsState::~StatsForNerdsState()\n{\n}\n\n/**\n * Initializes the screen (fills the data).\n */\nvoid StatsForNerdsState::init()\n{\n\tState::init();\n\n\tif (!Options::oxceDisableStatsForNerds)\n\t{\n\t\tinitLists();\n\n\t\t_btnPreview->setVisible(false);\n\t\tif (_typeId == UFOPAEDIA_TYPE_CRAFT || _typeId == UFOPAEDIA_TYPE_TFTD_CRAFT)\n\t\t{\n\t\t\tif (!_game->getSavedGame())\n\t\t\t{\n\t\t\t\t// how did we even get here?\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (_game->getSavedGame()->getSavedBattle())\n\t\t\t{\n\t\t\t\t// there is already a battle going on, don't start another one\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!_game->containsUfopaediaStartState())\n\t\t\t{\n\t\t\t\t// let's ignore any random M-click articles too\n\t\t\t\t// and allow the preview only if the ufopedia was opened from the main geoscape menu\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tRuleCraft* craftRule = _game->getMod()->getCraft(_topicId);\n\t\t\tif (craftRule->isForNewBattle())\n\t\t\t{\n\t\t\t\tauto& data = _game->getSavedGame()->getCustomRuleCraftDeployments();\n\t\t\t\tauto find = data.find(craftRule->getType());\n\n\t\t\t\t// update the label to indicate presence of a saved deployment\n\t\t\t\tif (find != data.end())\n\t\t\t\t\t_btnPreview->setText(tr(\"STR_CRAFT_DEPLOYMENT_PREVIEW_SAVED\"));\n\t\t\t\telse\n\t\t\t\t\t_btnPreview->setText(tr(\"STR_CRAFT_DEPLOYMENT_PREVIEW\"));\n\n\t\t\t\t_txtTitle->setAlign(ALIGN_LEFT);\n\t\t\t\t_btnPreview->setVisible(true);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Opens the details for the selected ammo item.\n * @param action Pointer to an action.\n */\nvoid StatsForNerdsState::cbxAmmoSelect(Action *)\n{\n\tsize_t selIdx = _cbxRelatedStuff->getSelected();\n\tif (selIdx > 0)\n\t{\n\t\tif (_typeId == UFOPAEDIA_TYPE_ITEM || _typeId == UFOPAEDIA_TYPE_TFTD_ITEM)\n\t\t{\n\t\t\t// perform same checks as in ArticleStateItem.cpp\n\t\t\tconst auto& ammoId = _filterOptions.at(selIdx);\n\t\t\tauto* ammo_article = _game->getMod()->getUfopaediaArticle(ammoId, true);\n\t\t\tif (Ufopaedia::isArticleAvailable(_game->getSavedGame(), ammo_article))\n\t\t\t{\n\t\t\t\tauto* ammo_rule = _game->getMod()->getItem(ammoId, true);\n\t\t\t\t_game->pushState(new StatsForNerdsState(UFOPAEDIA_TYPE_ITEM, ammo_rule->getType(), _btnIncludeDebug->getPressed(), _btnIncludeIds->getPressed(), _btnIncludeDefaults->getPressed()));\n\t\t\t}\n\t\t}\n\t\telse if(_typeId == UFOPAEDIA_TYPE_ARMOR || _typeId == UFOPAEDIA_TYPE_TFTD_ARMOR)\n\t\t{\n\t\t\t// perform similar checks as above, but don't crash if article is not found\n\t\t\tconst auto& builtInItemId = _filterOptions.at(selIdx);\n\t\t\tauto* builtInItem_article = _game->getMod()->getUfopaediaArticle(builtInItemId, false);\n\t\t\tif (builtInItem_article && Ufopaedia::isArticleAvailable(_game->getSavedGame(), builtInItem_article))\n\t\t\t{\n\t\t\t\tauto* builtInItem_rule = _game->getMod()->getItem(builtInItemId, true);\n\t\t\t\t_game->pushState(new StatsForNerdsState(UFOPAEDIA_TYPE_ITEM, builtInItem_rule->getType(), _btnIncludeDebug->getPressed(), _btnIncludeIds->getPressed(), _btnIncludeDefaults->getPressed()));\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/**\n * Refresh the displayed data including/excluding the raw IDs.\n * @param action Pointer to an action.\n */\nvoid StatsForNerdsState::btnRefreshClick(Action *)\n{\n\tinitLists();\n}\n\n/**\n * Returns to the previous screen.\n * @param action Pointer to an action.\n */\nvoid StatsForNerdsState::btnOkClick(Action *)\n{\n\tif (_game->isCtrlPressed())\n\t{\n\t\tLog(LOG_INFO) << _txtArticle->getText();\n\t\tfor (size_t row = 0; row < _lstRawData->getTexts(); ++row)\n\t\t{\n\t\t\tLog(LOG_INFO) << _lstRawData->getCellText(row, 0) << \"\\t\\t\" << _lstRawData->getCellText(row, 1);\n\t\t}\n\t\treturn;\n\t}\n\n\t_game->popState();\n}\n\n/**\n * Shows the battlescape preview.\n * @param action Pointer to an action.\n */\nvoid StatsForNerdsState::btnPreviewClick(Action *)\n{\n\tconst Mod* mod = _game->getMod();\n\tSavedGame* save = _game->getSavedGame();\n\tBase* base = save->getPreviewBase();\n\tif (!base)\n\t{\n\t\t// create a new base\n\t\t// this base is temporary (i.e. not saved in the save file), but we also don't have to create a new one each time\n\t\tbase = new Base(mod);\n\t\tsave->setPreviewBase(base);\n\t\tbase->setName(\"Preview Base\");\n\n\t\t// create some 1x1 soldiers (as many as needed for the biggest craft type)\n\t\tRuleSoldier* soldierRule = nullptr;\n\t\tArmor* defaultArmor = nullptr;\n\t\tfor (auto& soldierType : mod->getSoldiersList())\n\t\t{\n\t\t\tsoldierRule = mod->getSoldier(soldierType);\n\t\t\tdefaultArmor = soldierRule->getDefaultArmor();\n\t\t\tif (defaultArmor->getSize() == 1)\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tint biggest = 0;\n\t\tfor (auto& craftType : mod->getCraftsList())\n\t\t{\n\t\t\tauto* cRule = mod->getCraft(craftType);\n\t\t\tif (cRule->getMaxUnitsLimit() > biggest)\n\t\t\t{\n\t\t\t\tbiggest = cRule->getMaxUnitsLimit();\n\t\t\t}\n\t\t}\n\t\tfor (int i = 0; i < biggest; ++i)\n\t\t{\n\t\t\t// we use NEGATIVE soldier IDs to make sure there is not even a theoretical chance of modifying real geoscape soldiers during the preview\n\t\t\tint newId = -(i + 1);\n\t\t\tSoldier* soldier = new Soldier(soldierRule, defaultArmor, 0 /*nationality*/, newId);\n\t\t\tbase->getSoldiers()->push_back(soldier);\n\t\t\tsoldier->setName(\"Position\" + std::to_string(newId));\n\t\t}\n\t}\n\t// now clean up from the previous preview\n\t{\n\t\tfor (auto* soldier : *base->getSoldiers())\n\t\t{\n\t\t\tsoldier->setCraft(nullptr);\n\t\t}\n\t\tfor (auto* craft : *base->getCrafts())\n\t\t{\n\t\t\tdelete craft;\n\t\t}\n\t\tbase->getCrafts()->clear();\n\t}\n\t// and finally create the craft we need\n\tRuleCraft* craftRule = mod->getCraft(_topicId);\n\tCraft* c = new Craft(craftRule, base, RuleCraft::DUMMY_CRAFT_ID); // a negative integer\n\tbase->getCrafts()->push_back(c);\n\tc->setName(tr(craftRule->getType()));\n\tint max = craftRule->getMaxUnitsLimit();\n\tfor (auto* soldier : *base->getSoldiers())\n\t{\n\t\tsoldier->setCraft(c);\n\t\tmax--;\n\t\tif (max <= 0) break;\n\t}\n\n\tSavedBattleGame* bgame = new SavedBattleGame(_game->getMod(), _game->getLanguage(), true);\n\t_game->getSavedGame()->setBattleGame(bgame);\n\tBattlescapeGenerator bgen = BattlescapeGenerator(_game);\n\tbgame->setMissionType(c->getRules()->getCustomPreviewType());\n\tbgame->setCraftForPreview(c);\n\tbgen.setCraft(c);\n\tbgen.run();\n\n\t// needed for preview of craft deployment tiles\n\tbgame->setCraftPos(bgen.getCraftPos());\n\tbgame->setCraftZ(bgen.getCraftZ());\n\tbgame->calculateCraftTiles();\n\n\t_game->pushState(new BriefingState(c));\n}\n\n/**\n * Shows the previous available article.\n * @param action Pointer to an action.\n */\nvoid StatsForNerdsState::btnPrevClick(Action *)\n{\n\tUfopaedia::prevDetail(_game, _state, _btnIncludeDebug->getPressed(), _btnIncludeIds->getPressed(), _btnIncludeDefaults->getPressed());\n}\n\n/**\n * Shows the next available article. Loops to the first.\n * @param action Pointer to an action.\n */\nvoid StatsForNerdsState::btnNextClick(Action *)\n{\n\tUfopaedia::nextDetail(_game, _state, _btnIncludeDebug->getPressed(), _btnIncludeIds->getPressed(), _btnIncludeDefaults->getPressed());\n}\n\n/**\n * Scrolls the main table up by one row.\n * @param action Pointer to an action.\n */\nvoid StatsForNerdsState::btnScrollUpClick(Action *)\n{\n\t_lstRawData->scrollUp(false);\n}\n\n/**\n * Scrolls the main table down by one row.\n * @param action Pointer to an action.\n */\nvoid StatsForNerdsState::btnScrollDownClick(Action *)\n{\n\t_lstRawData->scrollDown(false);\n}\n\n/**\n * Shows the \"raw\" data.\n */\nvoid StatsForNerdsState::initLists()\n{\n\t_showDebug = _btnIncludeDebug->getPressed();\n\t_showIds = _btnIncludeIds->getPressed();\n\t_showDefaults = _btnIncludeDefaults->getPressed();\n\n\t_counter = 0;\n\t_indent = false;\n\n\tswitch (_typeId)\n\t{\n\tcase UFOPAEDIA_TYPE_ITEM:\n\tcase UFOPAEDIA_TYPE_TFTD_ITEM:\n\t\tinitItemList();\n\t\tbreak;\n\tcase UFOPAEDIA_TYPE_ARMOR:\n\tcase UFOPAEDIA_TYPE_TFTD_ARMOR:\n\t\tinitArmorList();\n\t\tbreak;\n\tcase UFOPAEDIA_TYPE_BASE_FACILITY:\n\tcase UFOPAEDIA_TYPE_TFTD_BASE_FACILITY:\n\t\tinitFacilityList();\n\t\tbreak;\n\tcase UFOPAEDIA_TYPE_CRAFT:\n\tcase UFOPAEDIA_TYPE_TFTD_CRAFT:\n\t\tinitCraftList();\n\t\tbreak;\n\tcase UFOPAEDIA_TYPE_UFO:\n\tcase UFOPAEDIA_TYPE_TFTD_USO:\n\t\tinitUfoList();\n\t\tbreak;\n\tcase UFOPAEDIA_TYPE_CRAFT_WEAPON:\n\tcase UFOPAEDIA_TYPE_TFTD_CRAFT_WEAPON:\n\t\tinitCraftWeaponList();\n\t\tbreak;\n\tcase UFOPAEDIA_TYPE_SOLDIER:\n\t\tinitSoldierList();\n\t\tbreak;\n\tcase UFOPAEDIA_TYPE_UNIT:\n\t\tinitUnitList();\n\t\tbreak;\n\tcase UFOPAEDIA_TYPE_UNKNOWN:\n\t\tinitSoldierBonusList();\n\tdefault:\n\t\tbreak;\n\t}\n}\n\n/**\n * Resets the string stream.\n */\nvoid StatsForNerdsState::resetStream(std::ostringstream &ss)\n{\n\tss.str(\"\");\n\tss.clear();\n}\n\n/**\n * Adds a translatable item to the string stream, optionally with string ID.\n */\nvoid StatsForNerdsState::addTranslation(std::ostringstream &ss, const std::string &id)\n{\n\tss << tr(id);\n\tif (_showIds)\n\t{\n\t\tss << \" [\" << id << \"]\";\n\t}\n}\n\n/**\n * Translates a property name.\n */\nstd::string StatsForNerdsState::trp(const std::string &propertyName)\n{\n\tif (_showDebug)\n\t{\n\t\tif (_indent)\n\t\t{\n\t\t\tstd::string indentation = \" \";\n\t\t\tstd::string code = propertyName;\n\t\t\treturn indentation + code;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn propertyName;\n\t\t}\n\t}\n\telse\n\t{\n\t\tif (_indent)\n\t\t{\n\t\t\tstd::string indentation = \" \";\n\t\t\tstd::string translation = tr(propertyName);\n\t\t\treturn indentation + translation;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn tr(propertyName);\n\t\t}\n\t}\n}\n\n/**\n * Adds a section name to the table.\n */\nvoid StatsForNerdsState::addSection(const std::string &name, const std::string &desc, Uint8 color, bool forceShow)\n{\n\tif (_showDefaults || forceShow)\n\t{\n\t\t_lstRawData->addRow(2, name.c_str(), desc.c_str());\n\t\t_lstRawData->setRowColor(_lstRawData->getLastRowIndex(), color);\n\t}\n\n\t// reset counter\n\t_counter = 0;\n}\n\n/**\n * Adds a group heading to the table.\n */\nvoid StatsForNerdsState::addHeading(const std::string &propertyName, const std::string &moreDetail, bool addDifficulty)\n{\n\tif (moreDetail.empty())\n\t{\n\t\t_lstRawData->addRow(2, trp(propertyName).c_str(), \"\");\n\t}\n\telse\n\t{\n\t\tstd::ostringstream ss2;\n\t\tif (addDifficulty)\n\t\t{\n\t\t\tstd::string diff;\n\t\t\tswitch (_game->getSavedGame()->getDifficulty())\n\t\t\t{\n\t\t\t\tcase DIFF_SUPERHUMAN: diff = tr(\"STR_5_SUPERHUMAN\"); break;\n\t\t\t\tcase DIFF_GENIUS: diff = tr(\"STR_4_GENIUS\"); break;\n\t\t\t\tcase DIFF_VETERAN: diff = tr(\"STR_3_VETERAN\"); break;\n\t\t\t\tcase DIFF_EXPERIENCED: diff = tr(\"STR_2_EXPERIENCED\"); break;\n\t\t\t\tdefault: diff = tr(\"STR_1_BEGINNER\"); break;\n\t\t\t}\n\t\t\tss2 << tr(moreDetail).arg(diff);\n\t\t}\n\t\telse\n\t\t{\n\t\t\taddTranslation(ss2, moreDetail);\n\t\t}\n\t\t_lstRawData->addRow(2, trp(propertyName).c_str(), ss2.str().c_str());\n\t\t_lstRawData->setCellColor(_lstRawData->getLastRowIndex(), 1, _white);\n\t}\n\t_lstRawData->setCellColor(_lstRawData->getLastRowIndex(), 0, _blue);\n\n\t// reset counter\n\t_counter = 0;\n\t_indent = true;\n}\n\n/**\n * Ends a group with a heading, potentially removing the heading... if the group turned out to be empty.\n */\nvoid StatsForNerdsState::endHeading()\n{\n\tif (_counter == 0)\n\t{\n\t\t_lstRawData->removeLastRow();\n\t}\n\t_indent = false;\n}\n\n/**\n * Adds a vector of generic types\n */\ntemplate<typename T, typename Callback>\nvoid StatsForNerdsState::addVectorOfGeneric(std::ostringstream &ss, const std::vector<T> &vec, const std::string &propertyName, Callback&& callback, bool translate)\n{\n\tif (vec.empty() && !_showDefaults)\n\t{\n\t\treturn;\n\t}\n\tresetStream(ss);\n\tint i = 0;\n\tss << \"{\";\n\tfor (auto& item : vec)\n\t{\n\t\tif (i > 0)\n\t\t{\n\t\t\tss << \", \";\n\t\t}\n\t\tif (translate)\n\t\t{\n\t\t\taddTranslation(ss, callback(item));\n\t\t}\n\t\telse\n\t\t{\n\t\t\tss << callback(item);\n\t\t}\n\t\ti++;\n\t}\n\tss << \"}\";\n\t_lstRawData->addRow(2, trp(propertyName).c_str(), ss.str().c_str());\n\t++_counter;\n\tif (!vec.empty())\n\t{\n\t\t_lstRawData->setCellColor(_lstRawData->getLastRowIndex(), 1, _pink);\n\t}\n}\n\n/**\n * Adds a single string value to the table.\n */\nvoid StatsForNerdsState::addSingleString(std::ostringstream &ss, const std::string &id, const std::string &propertyName, const std::string &defaultId, bool translate)\n{\n\tif (id == defaultId && !_showDefaults)\n\t{\n\t\treturn;\n\t}\n\tresetStream(ss);\n\tif (translate)\n\t{\n\t\taddTranslation(ss, id);\n\t}\n\telse\n\t{\n\t\tss << id;\n\t}\n\t_lstRawData->addRow(2, trp(propertyName).c_str(), ss.str().c_str());\n\t++_counter;\n\tif (id != defaultId)\n\t{\n\t\t_lstRawData->setCellColor(_lstRawData->getLastRowIndex(), 1, _pink);\n\t}\n}\n\n\n/**\n * Adds a vector of strings to the table.\n */\nvoid StatsForNerdsState::addVectorOfStrings(std::ostringstream &ss, const std::vector<std::string> &vec, const std::string &propertyName, bool translate)\n{\n\taddVectorOfGeneric(ss, vec, propertyName, [](const std::string& s) -> const std::string& { return s; }, translate);\n}\n\n/**\n * Adds a vector of RuleResearch names to the table.\n */\nvoid StatsForNerdsState::addVectorOfResearch(std::ostringstream &ss, const std::vector<const RuleResearch *> &vec, const std::string &propertyName)\n{\n\taddVectorOfRulesNamed(ss, vec, propertyName);\n}\n\n/**\n * Adds generic Rule (requires `getType()`)\n */\ntemplate<typename T>\nvoid StatsForNerdsState::addRule(std::ostringstream &ss, T* rule, const std::string &propertyName)\n{\n\taddSingleString(ss, rule ? rule->getType() : \"\", propertyName);\n}\n\n/**\n * Adds generic Rule (requires `getId()`)\n */\ntemplate<typename T>\nvoid StatsForNerdsState::addRuleId(std::ostringstream &ss, T* rule, const std::string &propertyName)\n{\n\taddSingleString(ss, rule ? rule->getId() : \"\", propertyName);\n}\n\n/**\n * Adds generic Rule (requires `getName()`)\n */\ntemplate<typename T>\nvoid StatsForNerdsState::addRuleNamed(std::ostringstream &ss, T* rule, const std::string &propertyName)\n{\n\taddSingleString(ss, rule ? rule->getName() : \"\", propertyName);\n}\n\n/**\n * Adds a vector of generic Rules (requires `getType()`)\n */\ntemplate<typename T>\nvoid StatsForNerdsState::addVectorOfRules(std::ostringstream &ss, const std::vector<T*> &vec, const std::string &propertyName)\n{\n\taddVectorOfGeneric(ss, vec, propertyName, [](T* item){ return item->getType(); });\n}\n\n/**\n * Adds a vector of generic Rules (requires `getId()`)\n */\ntemplate<typename T>\nvoid StatsForNerdsState::addVectorOfRulesId(std::ostringstream &ss, const std::vector<T*> &vec, const std::string &propertyName)\n{\n\taddVectorOfGeneric(ss, vec, propertyName, [](T* item){ return item->getId(); });\n}\n\n/**\n * Adds a vector of generic Rules (requires `getName()`)\n */\ntemplate<typename T>\nvoid StatsForNerdsState::addVectorOfRulesNamed(std::ostringstream &ss, const std::vector<T*> &vec, const std::string &propertyName)\n{\n\taddVectorOfGeneric(ss, vec, propertyName, [](T* item){ return item->getName(); });\n}\n\n\ntemplate<typename T, typename I>\nvoid StatsForNerdsState::addScriptTags(std::ostringstream &ss, const ScriptValues<T, I> &values)\n{\n\tauto& tagValues = values.getValuesRaw();\n\tArgEnum index = ScriptParserBase::getArgType<ScriptTag<T, I>>();\n\tauto& tagNames = _game->getMod()->getScriptGlobal()->getTagNames().at(index);\n\tfor (size_t i = 0; i < tagValues.size(); ++i)\n\t{\n\t\tauto nameAsString = tagNames.values[i].name.toString().substr(4);\n\t\taddIntegerScriptTag(ss, tagValues.at(i), nameAsString);\n\t}\n}\n\nvoid StatsForNerdsState::addIntegerScript(const std::string &propertyName, const int &value)\n{\n\t_lstRawData->addRow(2, trp(propertyName).c_str(), std::to_string(value).c_str());\n\t_lstRawData->setCellColor(_lstRawData->getLastRowIndex(), 1, _pink);\n\t++_counter;\n}\n\nvoid StatsForNerdsState::addTextScript(const std::string &propertyName, const std::string &value)\n{\n\tstd::string text = _showDebug ? value : std::string(tr(value));\n\t_lstRawData->addRow(2, trp(propertyName).c_str(), text.c_str());\n\t_lstRawData->setCellColor(_lstRawData->getLastRowIndex(), 1, _pink);\n\t++_counter;\n}\n\nvoid StatsForNerdsState::addTextFormat1Script(const std::string &propertyName, const std::string &format, const int &value1)\n{\n\tstd::string text = tr(format).arg(value1);\n\t_lstRawData->addRow(2, trp(propertyName).c_str(), text.c_str());\n\t_lstRawData->setCellColor(_lstRawData->getLastRowIndex(), 1, _pink);\n\t++_counter;\n}\n\nvoid StatsForNerdsState::addTextFormat2Script(const std::string &propertyName, const std::string &format, const int &value1, const int &value2)\n{\n\tstd::string text = tr(format).arg(value1).arg(value2);\n\t_lstRawData->addRow(2, trp(propertyName).c_str(), text.c_str());\n\t_lstRawData->setCellColor(_lstRawData->getLastRowIndex(), 1, _pink);\n\t++_counter;\n}\n\n/**\n * Adds a single boolean value to the table.\n */\nvoid StatsForNerdsState::addBoolean(std::ostringstream &ss, const bool &value, const std::string &propertyName, const bool &defaultvalue)\n{\n\tif (value == defaultvalue && !_showDefaults)\n\t{\n\t\treturn;\n\t}\n\tresetStream(ss);\n\tif (value)\n\t{\n\t\tss << tr(\"STR_TRUE\");\n\t}\n\telse\n\t{\n\t\tss << tr(\"STR_FALSE\");\n\t}\n\t_lstRawData->addRow(2, trp(propertyName).c_str(), ss.str().c_str());\n\t++_counter;\n\tif (value != defaultvalue)\n\t{\n\t\t_lstRawData->setCellColor(_lstRawData->getLastRowIndex(), 1, _pink);\n\t}\n}\n\n/**\n * Adds a single floating point number to the table.\n */\nvoid StatsForNerdsState::addFloat(std::ostringstream &ss, const float &value, const std::string &propertyName, const float &defaultvalue)\n{\n\tif (AreSame(value, defaultvalue) && !_showDefaults)\n\t{\n\t\treturn;\n\t}\n\tresetStream(ss);\n\tss << value;\n\t_lstRawData->addRow(2, trp(propertyName).c_str(), ss.str().c_str());\n\t++_counter;\n\tif (!AreSame(value, defaultvalue))\n\t{\n\t\t_lstRawData->setCellColor(_lstRawData->getLastRowIndex(), 1, _pink);\n\t}\n}\n\n/**\n * Adds a single floating point number (formatted as percentage) to the table.\n */\nvoid StatsForNerdsState::addFloatAsPercentage(std::ostringstream &ss, const float &value, const std::string &propertyName, const float &defaultvalue)\n{\n\tif (AreSame(value, defaultvalue) && !_showDefaults)\n\t{\n\t\treturn;\n\t}\n\tresetStream(ss);\n\tss << (value * 100.0f) << \"%\";\n\tif (_showIds)\n\t{\n\t\tss << \" [\" << value << \"]\";\n\t}\n\t_lstRawData->addRow(2, trp(propertyName).c_str(), ss.str().c_str());\n\t++_counter;\n\tif (!AreSame(value, defaultvalue))\n\t{\n\t\t_lstRawData->setCellColor(_lstRawData->getLastRowIndex(), 1, _pink);\n\t}\n}\n\n/**\n * Adds a single floating point (double precision) number to the table.\n */\nvoid StatsForNerdsState::addDouble(std::ostringstream &ss, const double &value, const std::string &propertyName, const double &defaultvalue)\n{\n\tif (AreSame(value, defaultvalue) && !_showDefaults)\n\t{\n\t\treturn;\n\t}\n\tresetStream(ss);\n\tss << value;\n\t_lstRawData->addRow(2, trp(propertyName).c_str(), ss.str().c_str());\n\t++_counter;\n\tif (!AreSame(value, defaultvalue))\n\t{\n\t\t_lstRawData->setCellColor(_lstRawData->getLastRowIndex(), 1, _pink);\n\t}\n}\n\n/**\n * Adds a single integer number to the table.\n */\nvoid StatsForNerdsState::addInteger(std::ostringstream &ss, const int &value, const std::string &propertyName, const int &defaultvalue, bool formatAsMoney, const std::string &specialTranslation, const int &specialvalue)\n{\n\tif (value == defaultvalue && !_showDefaults)\n\t{\n\t\treturn;\n\t}\n\tresetStream(ss);\n\tif (value == specialvalue && !specialTranslation.empty())\n\t{\n\t\tss << tr(specialTranslation);\n\t\tif (_showIds)\n\t\t{\n\t\t\tss << \" [\" << specialvalue << \"]\";\n\t\t}\n\t}\n\telse\n\t{\n\t\tif (formatAsMoney)\n\t\t{\n\t\t\tss << Unicode::formatFunding(value);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tss << value;\n\t\t}\n\t}\n\t_lstRawData->addRow(2, trp(propertyName).c_str(), ss.str().c_str());\n\t++_counter;\n\tif (value != defaultvalue)\n\t{\n\t\t_lstRawData->setCellColor(_lstRawData->getLastRowIndex(), 1, _pink);\n\t}\n}\n\n/**\n * Adds a script tag to the table.\n */\nvoid StatsForNerdsState::addIntegerScriptTag(std::ostringstream &ss, const int &value, const std::string &propertyName, const int &defaultvalue)\n{\n\tif (value == defaultvalue && !_showDefaults)\n\t{\n\t\treturn;\n\t}\n\tresetStream(ss);\n\tss << trp(propertyName);\n\tss << \": \";\n\tss << value;\n\t_lstRawData->setFlooding(true);\n\t_lstRawData->addRow(1, ss.str().c_str());\n\t_lstRawData->setFlooding(false);\n\t++_counter;\n\tif (value != defaultvalue)\n\t{\n\t\t_lstRawData->setCellColor(_lstRawData->getLastRowIndex(), 0, _pink);\n\t}\n}\n\n/**\n * Adds a single integer number (representing a percentage) to the table.\n */\nvoid StatsForNerdsState::addIntegerPercent(std::ostringstream &ss, const int &value, const std::string &propertyName, const int &defaultvalue)\n{\n\tif (value == defaultvalue && !_showDefaults)\n\t{\n\t\treturn;\n\t}\n\tresetStream(ss);\n\tss << value;\n\t// -1 is not a percentage, usually means \"take value from somewhere else\"\n\tif (value != -1)\n\t{\n\t\tss << \"%\";\n\t}\n\t_lstRawData->addRow(2, trp(propertyName).c_str(), ss.str().c_str());\n\t++_counter;\n\tif (value != defaultvalue)\n\t{\n\t\t_lstRawData->setCellColor(_lstRawData->getLastRowIndex(), 1, _pink);\n\t}\n}\n\n/**\n * Adds a single integer number (representing a distance in nautical miles) to the table.\n */\nvoid StatsForNerdsState::addIntegerNauticalMiles(std::ostringstream &ss, const int &value, const std::string &propertyName, const int &defaultvalue)\n{\n\tif (value == defaultvalue && !_showDefaults)\n\t{\n\t\treturn;\n\t}\n\tresetStream(ss);\n\tss << tr(\"STR_NAUTICAL_MILES\").arg(value);\n\tss << \" = \";\n\tss << tr(\"STR_KILOMETERS\").arg(value * 1852 / 1000);\n\t_lstRawData->addRow(2, trp(propertyName).c_str(), ss.str().c_str());\n\t++_counter;\n\tif (value != defaultvalue)\n\t{\n\t\t_lstRawData->setCellColor(_lstRawData->getLastRowIndex(), 1, _pink);\n\t}\n}\n\n/**\n * Adds a single integer number (representing a speed in knots = nautical miles per hour) to the table.\n */\nvoid StatsForNerdsState::addIntegerKnots(std::ostringstream &ss, const int &value, const std::string &propertyName, const int &defaultvalue)\n{\n\tif (value == defaultvalue && !_showDefaults)\n\t{\n\t\treturn;\n\t}\n\tresetStream(ss);\n\tss << tr(\"STR_KNOTS\").arg(value);\n\tss << \" = \";\n\tss << tr(\"STR_KILOMETERS_PER_HOUR\").arg(value * 1852 / 1000);\n\t_lstRawData->addRow(2, trp(propertyName).c_str(), ss.str().c_str());\n\t++_counter;\n\tif (value != defaultvalue)\n\t{\n\t\t_lstRawData->setCellColor(_lstRawData->getLastRowIndex(), 1, _pink);\n\t}\n}\n\n/**\n * Adds a single integer number (representing a distance in kilometers) to the table.\n */\nvoid StatsForNerdsState::addIntegerKm(std::ostringstream &ss, const int &value, const std::string &propertyName, const int &defaultvalue)\n{\n\tif (value == defaultvalue && !_showDefaults)\n\t{\n\t\treturn;\n\t}\n\tresetStream(ss);\n\tss << tr(\"STR_KILOMETERS\").arg(value);\n\t_lstRawData->addRow(2, trp(propertyName).c_str(), ss.str().c_str());\n\t++_counter;\n\tif (value != defaultvalue)\n\t{\n\t\t_lstRawData->setCellColor(_lstRawData->getLastRowIndex(), 1, _pink);\n\t}\n}\n\n/**\n * Adds one or two integer numbers (representing a duration in seconds) to the table.\n */\nvoid StatsForNerdsState::addIntegerSeconds(std::ostringstream &ss, const int &value, const std::string &propertyName, const int &defaultvalue, const int &value2)\n{\n\tif (value == defaultvalue && !_showDefaults)\n\t{\n\t\treturn;\n\t}\n\tresetStream(ss);\n\tif (value2 == -1)\n\t{\n\t\tss << tr(\"STR_SECONDS_LONG\").arg(value);\n\t}\n\telse\n\t{\n\t\tstd::ostringstream ss2;\n\t\tss2 << value;\n\t\tss2 << \"-\";\n\t\tss2 << value2;\n\t\tss << tr(\"STR_SECONDS_LONG\").arg(ss2.str());\n\t}\n\t_lstRawData->addRow(2, trp(propertyName).c_str(), ss.str().c_str());\n\t++_counter;\n\tif (value != defaultvalue)\n\t{\n\t\t_lstRawData->setCellColor(_lstRawData->getLastRowIndex(), 1, _pink);\n\t}\n}\n\n/**\n * Adds a vector of integer numbers to the table.\n */\nvoid StatsForNerdsState::addVectorOfIntegers(std::ostringstream &ss, const std::vector<int> &vec, const std::string &propertyName)\n{\n\tif (vec.empty() && !_showDefaults)\n\t{\n\t\treturn;\n\t}\n\tresetStream(ss);\n\tint i = 0;\n\tss << \"{\";\n\tfor (auto& item : vec)\n\t{\n\t\tif (i > 0)\n\t\t{\n\t\t\tss << \", \";\n\t\t}\n\t\tss << item;\n\t\ti++;\n\t}\n\tss << \"}\";\n\t_lstRawData->addRow(2, trp(propertyName).c_str(), ss.str().c_str());\n\t++_counter;\n\tif (!vec.empty())\n\t{\n\t\t_lstRawData->setCellColor(_lstRawData->getLastRowIndex(), 1, _pink);\n\t}\n}\n\n/**\n * Adds a map of integer/integer numbers to the table.\n */\nvoid StatsForNerdsState::addMapOfIntegers(std::ostringstream& ss, const std::map<int, int>& map, const std::string& propertyName)\n{\n\tif (map.empty() && !_showDefaults)\n\t{\n\t\treturn;\n\t}\n\tresetStream(ss);\n\tint i = 0;\n\tss << \"{\";\n\tfor (auto& item : map)\n\t{\n\t\tif (i > 0)\n\t\t{\n\t\t\tss << \", \";\n\t\t}\n\t\tss << item.first << \":\" << item.second;\n\t\ti++;\n\t}\n\tss << \"}\";\n\t_lstRawData->addRow(2, trp(propertyName).c_str(), ss.str().c_str());\n\t++_counter;\n\tif (!map.empty())\n\t{\n\t\t_lstRawData->setCellColor(_lstRawData->getLastRowIndex(), 1, _pink);\n\t}\n}\n\n/**\n * Adds a BattleType to the table.\n */\nvoid StatsForNerdsState::addBattleType(std::ostringstream &ss, const BattleType &value, const std::string &propertyName, const BattleType &defaultvalue)\n{\n\tif (value == defaultvalue && !_showDefaults)\n\t{\n\t\treturn;\n\t}\n\tresetStream(ss);\n\tswitch (value)\n\t{\n\t\tcase BT_NONE: ss << tr(\"BT_NONE\"); break;\n\t\tcase BT_FIREARM: ss << tr(\"BT_FIREARM\"); break;\n\t\tcase BT_AMMO: ss << tr(\"BT_AMMO\"); break;\n\t\tcase BT_MELEE: ss << tr(\"BT_MELEE\"); break;\n\t\tcase BT_GRENADE: ss << tr(\"BT_GRENADE\"); break;\n\t\tcase BT_PROXIMITYGRENADE: ss << tr(\"BT_PROXIMITYGRENADE\"); break;\n\t\tcase BT_MEDIKIT: ss << tr(\"BT_MEDIKIT\"); break;\n\t\tcase BT_SCANNER: ss << tr(\"BT_SCANNER\"); break;\n\t\tcase BT_MINDPROBE: ss << tr(\"BT_MINDPROBE\"); break;\n\t\tcase BT_PSIAMP: ss << tr(\"BT_PSIAMP\"); break;\n\t\tcase BT_FLARE: ss << tr(\"BT_FLARE\"); break;\n\t\tcase BT_CORPSE: ss << tr(\"BT_CORPSE\"); break;\n\t\tdefault: ss << tr(\"STR_UNKNOWN\"); break;\n\t}\n\tif (_showIds)\n\t{\n\t\tss << \" [\" << value << \"]\";\n\t}\n\t_lstRawData->addRow(2, trp(propertyName).c_str(), ss.str().c_str());\n\t++_counter;\n\tif (value != defaultvalue)\n\t{\n\t\t_lstRawData->setCellColor(_lstRawData->getLastRowIndex(), 1, _pink);\n\t}\n}\n\n/**\n * Adds a DamageType to the table.\n */\nvoid StatsForNerdsState::addDamageType(std::ostringstream &ss, const ItemDamageType &value, const std::string &propertyName, const ItemDamageType &defaultvalue)\n{\n\tif (value == defaultvalue && !_showDefaults)\n\t{\n\t\treturn;\n\t}\n\tresetStream(ss);\n\tswitch (value)\n\t{\n\t\tcase DT_NONE: ss << tr( \"STR_DAMAGE_NONE\"); break;\n\t\tcase DT_AP: ss << tr(\"STR_DAMAGE_ARMOR_PIERCING\"); break;\n\t\tcase DT_IN: ss << tr(\"STR_DAMAGE_INCENDIARY\"); break;\n\t\tcase DT_HE: ss << tr(\"STR_DAMAGE_HIGH_EXPLOSIVE\"); break;\n\t\tcase DT_LASER: ss << tr(\"STR_DAMAGE_LASER_BEAM\"); break;\n\t\tcase DT_PLASMA: ss << tr(\"STR_DAMAGE_PLASMA_BEAM\"); break;\n\t\tcase DT_STUN: ss << tr(\"STR_DAMAGE_STUN\"); break;\n\t\tcase DT_MELEE: ss << tr(\"STR_DAMAGE_MELEE\"); break;\n\t\tcase DT_ACID: ss << tr(\"STR_DAMAGE_ACID\"); break;\n\t\tcase DT_SMOKE: ss << tr(\"STR_DAMAGE_SMOKE\"); break;\n\t\tcase DT_10: ss << tr(\"STR_DAMAGE_10\"); break;\n\t\tcase DT_11: ss << tr(\"STR_DAMAGE_11\"); break;\n\t\tcase DT_12: ss << tr(\"STR_DAMAGE_12\"); break;\n\t\tcase DT_13: ss << tr(\"STR_DAMAGE_13\"); break;\n\t\tcase DT_14: ss << tr(\"STR_DAMAGE_14\"); break;\n\t\tcase DT_15: ss << tr(\"STR_DAMAGE_15\"); break;\n\t\tcase DT_16: ss << tr(\"STR_DAMAGE_16\"); break;\n\t\tcase DT_17: ss << tr(\"STR_DAMAGE_17\"); break;\n\t\tcase DT_18: ss << tr(\"STR_DAMAGE_18\"); break;\n\t\tcase DT_19: ss << tr(\"STR_DAMAGE_19\"); break;\n\t\tdefault: ss << tr(\"STR_UNKNOWN\"); break;\n\t}\n\tif (_showIds)\n\t{\n\t\tss << \" [\" << value << \"]\";\n\t}\n\t_lstRawData->addRow(2, trp(propertyName).c_str(), ss.str().c_str());\n\t++_counter;\n\tif (value != defaultvalue)\n\t{\n\t\t_lstRawData->setCellColor(_lstRawData->getLastRowIndex(), 1, _pink);\n\t}\n}\n\n/**\n * Adds a DamageRandomType to the table.\n */\nvoid StatsForNerdsState::addDamageRandomType(std::ostringstream &ss, const ItemDamageRandomType &value, const std::string &propertyName, const ItemDamageRandomType &defaultvalue)\n{\n\tif (value == defaultvalue && !_showDefaults)\n\t{\n\t\treturn;\n\t}\n\tresetStream(ss);\n\tswitch (value)\n\t{\n\t\tcase DRT_DEFAULT: ss << tr(\"DRT_DEFAULT\"); break;\n\t\tcase DRT_UFO: ss << tr(\"DRT_UFO\"); break;\n\t\tcase DRT_TFTD: ss << tr(\"DRT_TFTD\"); break;\n\t\tcase DRT_FLAT: ss << tr(\"DRT_FLAT\"); break;\n\t\tcase DRT_FIRE: ss << tr(\"DRT_FIRE\"); break;\n\t\tcase DRT_NONE: ss << tr(\"DRT_NONE\"); break;\n\t\tcase DRT_UFO_WITH_TWO_DICE: ss << tr(\"DRT_UFO_WITH_TWO_DICE\"); break;\n\t\tcase DRT_EASY: ss << tr(\"DRT_EASY\"); break;\n\t\tcase DRT_STANDARD: ss << tr(\"DRT_STANDARD\"); break;\n\t\tcase DRT_EXPLOSION: ss << tr(\"DRT_EXPLOSION\"); break;\n\t\tdefault: ss << tr(\"STR_UNKNOWN\"); break;\n\t}\n\tif (_showIds)\n\t{\n\t\tss << \" [\" << value << \"]\";\n\t}\n\t_lstRawData->addRow(2, trp(propertyName).c_str(), ss.str().c_str());\n\t++_counter;\n\tif (value != defaultvalue)\n\t{\n\t\t_lstRawData->setCellColor(_lstRawData->getLastRowIndex(), 1, _pink);\n\t}\n}\n\n/**\n * Adds a BattleFuseType to the table.\n */\nvoid StatsForNerdsState::addBattleFuseType(std::ostringstream &ss, const BattleFuseType &value, const std::string &propertyName, const BattleFuseType &defaultvalue)\n{\n\tif (value == defaultvalue && !_showDefaults)\n\t{\n\t\treturn;\n\t}\n\tresetStream(ss);\n\tswitch (value)\n\t{\n\t\tcase BFT_NONE: ss << tr(\"BFT_NONE\"); break;\n\t\tcase BFT_INSTANT: ss << tr(\"BFT_INSTANT\"); break;\n\t\tcase BFT_SET: ss << tr(\"BFT_SET\"); break;\n\t\tdefault:\n\t\t{\n\t\t\tif (value >= BFT_FIX_MIN && value < BFT_FIX_MAX)\n\t\t\t{\n\t\t\t\tss << tr(\"BFT_FIXED\");\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tss << tr(\"STR_UNKNOWN\");\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (_showIds)\n\t{\n\t\tss << \" [\" << value << \"]\";\n\t}\n\t_lstRawData->addRow(2, trp(propertyName).c_str(), ss.str().c_str());\n\t++_counter;\n\tif (value != defaultvalue)\n\t{\n\t\t_lstRawData->setCellColor(_lstRawData->getLastRowIndex(), 1, _pink);\n\t}\n}\n\n/**\n * Adds a single RuleItemUseCost to the table.\n */\nvoid StatsForNerdsState::addRuleItemUseCostBasic(std::ostringstream &ss, const RuleItemUseCost &value, const std::string &propertyName, const int &defaultvalue)\n{\n\tif (value.Time == defaultvalue && !_showDefaults)\n\t{\n\t\treturn;\n\t}\n\tresetStream(ss);\n\tss << value.Time;\n\t_lstRawData->addRow(2, trp(propertyName).c_str(), ss.str().c_str());\n\t++_counter;\n\tif (value.Time != defaultvalue)\n\t{\n\t\t_lstRawData->setCellColor(_lstRawData->getLastRowIndex(), 1, _pink);\n\t}\n}\n\n/**\n * Adds a number to the string stream, optionally formatted as boolean.\n */\nvoid StatsForNerdsState::addBoolOrInteger(std::ostringstream &ss, const int &value, bool formatAsBoolean)\n{\n\tif (formatAsBoolean)\n\t{\n\t\tif (value == 1)\n\t\t\tss << tr(\"STR_TRUE\");\n\t\telse if (value == 0)\n\t\t\tss << tr(\"STR_FALSE\");\n\t\telse\n\t\t\tss << value;\n\t}\n\telse\n\t{\n\t\tss << value;\n\t}\n}\n\n/**\n * Adds a number to the string stream, optionally formatted as boolean.\n */\nvoid StatsForNerdsState::addPercentageSignOrNothing(std::ostringstream &ss, const int &value, bool smartFormat)\n{\n\tif (smartFormat)\n\t{\n\t\t// 1 means flat: true\n\t\tif (value != 1)\n\t\t{\n\t\t\tss << \"%\";\n\t\t}\n\t}\n}\n\n/**\n * Adds a full RuleItemUseCost to the table.\n */\ntemplate<typename T>\nvoid StatsForNerdsState::addRuleItemUseCostFull(std::ostringstream &ss, const RuleItemUseRuleBase<T> &value, const std::string &propertyName, const RuleItemUseRuleBase<T> &defaultvalue, bool smartFormat, const RuleItemUseFlat &formatBy)\n{\n\tbool isDefault = false;\n\tif (value.Time == defaultvalue.Time &&\n\t\tvalue.Energy == defaultvalue.Energy &&\n\t\tvalue.Morale == defaultvalue.Morale &&\n\t\tvalue.Health == defaultvalue.Health &&\n\t\tvalue.Stun == defaultvalue.Stun &&\n\t\tvalue.Mana == defaultvalue.Mana)\n\t{\n\t\tisDefault = true;\n\t}\n\tif (isDefault && !_showDefaults)\n\t{\n\t\treturn;\n\t}\n\tbool isFlatAttribute = propertyName.find(\"flat\") == 0;\n\tresetStream(ss);\n\tbool isFirst = true;\n\t// always show non-zero TUs, even if it's a default value\n\tif (value.Time != 0 || _showDefaults)\n\t{\n\t\tss << tr(\"STR_COST_TIME\") << \": \";\n\t\taddBoolOrInteger(ss, value.Time, isFlatAttribute);\n\t\taddPercentageSignOrNothing(ss, formatBy.Time, smartFormat);\n\t\tisFirst = false;\n\t}\n\tif (value.Energy != defaultvalue.Energy || _showDefaults)\n\t{\n\t\tif (!isFirst) ss << \", \";\n\t\tss << tr(\"STR_COST_ENERGY\") << \": \";\n\t\taddBoolOrInteger(ss, value.Energy, isFlatAttribute);\n\t\taddPercentageSignOrNothing(ss, formatBy.Energy, smartFormat);\n\t\tisFirst = false;\n\t}\n\tif (value.Morale != defaultvalue.Morale || _showDefaults)\n\t{\n\t\tif (!isFirst) ss << \", \";\n\t\tss << tr(\"STR_COST_MORALE\") << \": \";\n\t\taddBoolOrInteger(ss, value.Morale, isFlatAttribute);\n\t\taddPercentageSignOrNothing(ss, formatBy.Morale, smartFormat);\n\t\tisFirst = false;\n\t}\n\tif (value.Health != defaultvalue.Health || _showDefaults)\n\t{\n\t\tif (!isFirst) ss << \", \";\n\t\tss << tr(\"STR_COST_HEALTH\") << \": \";\n\t\taddBoolOrInteger(ss, value.Health, isFlatAttribute);\n\t\taddPercentageSignOrNothing(ss, formatBy.Health, smartFormat);\n\t\tisFirst = false;\n\t}\n\tif (value.Stun != defaultvalue.Stun || _showDefaults)\n\t{\n\t\tif (!isFirst) ss << \", \";\n\t\tss << tr(\"STR_COST_STUN\") << \": \";\n\t\taddBoolOrInteger(ss, value.Stun, isFlatAttribute);\n\t\taddPercentageSignOrNothing(ss, formatBy.Stun, smartFormat);\n\t\tisFirst = false;\n\t}\n\tif (value.Mana != defaultvalue.Mana || _showDefaults)\n\t{\n\t\tif (!isFirst) ss << \", \";\n\t\tss << tr(\"STR_COST_MANA\") << \": \";\n\t\taddBoolOrInteger(ss, value.Mana, isFlatAttribute);\n\t\taddPercentageSignOrNothing(ss, formatBy.Mana, smartFormat);\n\t\tisFirst = false;\n\t}\n\t_lstRawData->addRow(2, trp(propertyName).c_str(), ss.str().c_str());\n\t++_counter;\n\tif (!isDefault)\n\t{\n\t\t_lstRawData->setCellColor(_lstRawData->getLastRowIndex(), 1, _pink);\n\t}\n}\n\n/**\n * Adds a BattleMediKitType to the table.\n */\nvoid StatsForNerdsState::addBattleMediKitType(std::ostringstream &ss, const BattleMediKitType &value, const std::string &propertyName, const BattleMediKitType &defaultvalue)\n{\n\tif (value == defaultvalue && !_showDefaults)\n\t{\n\t\treturn;\n\t}\n\tresetStream(ss);\n\tswitch (value)\n\t{\n\t\tcase BMT_NORMAL: ss << tr(\"BMT_NORMAL\"); break;\n\t\tcase BMT_HEAL: ss << tr(\"BMT_HEAL\"); break;\n\t\tcase BMT_STIMULANT: ss << tr(\"BMT_STIMULANT\"); break;\n\t\tcase BMT_PAINKILLER: ss << tr(\"BMT_PAINKILLER\"); break;\n\t\tdefault: ss << tr(\"STR_UNKNOWN\"); break;\n\t}\n\tif (_showIds)\n\t{\n\t\tss << \" [\" << value << \"]\";\n\t}\n\t_lstRawData->addRow(2, trp(propertyName).c_str(), ss.str().c_str());\n\t++_counter;\n\tif (value != defaultvalue)\n\t{\n\t\t_lstRawData->setCellColor(_lstRawData->getLastRowIndex(), 1, _pink);\n\t}\n}\n\n/**\n * Adds medikit target types to the table.\n */\nvoid StatsForNerdsState::addMediKitTargets(std::ostringstream& ss, const RuleItem* value, const std::string& propertyName, const int& defaultvalue)\n{\n\tif (value->getMedikitTargetMatrixRaw() == defaultvalue && !_showDefaults)\n\t{\n\t\treturn;\n\t}\n\tresetStream(ss);\n\tss << \"{\";\n\t// FIXME: make translatable one day, when some better default names are suggested\n\tif (value->getAllowTargetFriendGround())\n\t\tss << \"friend down\" << \", \";\n\tif (value->getAllowTargetFriendStanding())\n\t\tss << \"friend up\" << \", \";\n\tif (value->getAllowTargetHostileGround())\n\t\tss << \"hostile down\" << \", \";\n\tif (value->getAllowTargetHostileStanding())\n\t\tss << \"hostile up\" << \", \";\n\tif (value->getAllowTargetNeutralGround())\n\t\tss << \"neutral down\" << \", \";\n\tif (value->getAllowTargetNeutralStanding())\n\t\tss << \"neutral up\" << \", \";\n\tss << \"}\";\n\tif (_showIds)\n\t{\n\t\tss << \" [\" << value->getMedikitTargetMatrixRaw() << \"]\";\n\t}\n\t_lstRawData->addRow(2, trp(propertyName).c_str(), ss.str().c_str());\n\t++_counter;\n\tif (value->getMedikitTargetMatrixRaw() != defaultvalue)\n\t{\n\t\t_lstRawData->setCellColor(_lstRawData->getLastRowIndex(), 1, _pink);\n\t}\n}\n\n/**\n * Adds item target types to the table.\n */\nvoid StatsForNerdsState::addItemTargets(std::ostringstream& ss, const RuleItem* value, const std::string& propertyName, const int& defaultvalue)\n{\n\tif (value->getTargetMatrixRaw() == defaultvalue && !_showDefaults)\n\t{\n\t\treturn;\n\t}\n\tresetStream(ss);\n\tss << \"{\";\n\t// FIXME: make translatable one day, when some better default names are suggested\n\tif (value->isTargetAllowed(FACTION_PLAYER, FACTION_PLAYER))\n\t\tss << \"friend\" << \", \";\n\tif (value->isTargetAllowed(FACTION_HOSTILE, FACTION_PLAYER))\n\t\tss << \"hostile\" << \", \";\n\tif (value->isTargetAllowed(FACTION_NEUTRAL, FACTION_PLAYER))\n\t\tss << \"neutral\" << \", \";\n\tss << \"}\";\n\tif (_showIds)\n\t{\n\t\tss << \" [\" << value->getTargetMatrixRaw() << \"]\";\n\t}\n\t_lstRawData->addRow(2, trp(propertyName).c_str(), ss.str().c_str());\n\t++_counter;\n\tif (value->getTargetMatrixRaw() != defaultvalue)\n\t{\n\t\t_lstRawData->setCellColor(_lstRawData->getLastRowIndex(), 1, _pink);\n\t}\n}\n\n/**\n * Adds a ExperienceTrainingMode to the table.\n */\nvoid StatsForNerdsState::addExperienceTrainingMode(std::ostringstream &ss, const ExperienceTrainingMode &value, const std::string &propertyName, const ExperienceTrainingMode &defaultvalue)\n{\n\tif (value == defaultvalue && !_showDefaults)\n\t{\n\t\treturn;\n\t}\n\tresetStream(ss);\n\tswitch (value)\n\t{\n\t\tcase ETM_DEFAULT: ss << tr(\"ETM_DEFAULT\"); break;\n\t\tcase ETM_MELEE_100: ss << tr(\"ETM_MELEE_100\"); break;\n\t\tcase ETM_MELEE_50: ss << tr(\"ETM_MELEE_50\"); break;\n\t\tcase ETM_MELEE_33: ss << tr(\"ETM_MELEE_33\"); break;\n\t\tcase ETM_FIRING_100: ss << tr(\"ETM_FIRING_100\"); break;\n\t\tcase ETM_FIRING_50: ss << tr(\"ETM_FIRING_50\"); break;\n\t\tcase ETM_FIRING_33: ss << tr(\"ETM_FIRING_33\"); break;\n\t\tcase ETM_THROWING_100: ss << tr(\"ETM_THROWING_100\"); break;\n\t\tcase ETM_THROWING_50: ss << tr(\"ETM_THROWING_50\"); break;\n\t\tcase ETM_THROWING_33: ss << tr(\"ETM_THROWING_33\"); break;\n\t\tcase ETM_FIRING_AND_THROWING: ss << tr(\"ETM_FIRING_AND_THROWING\"); break;\n\t\tcase ETM_FIRING_OR_THROWING: ss << tr(\"ETM_FIRING_OR_THROWING\"); break;\n\t\tcase ETM_REACTIONS: ss << tr(\"ETM_REACTIONS\"); break;\n\t\tcase ETM_REACTIONS_AND_MELEE: ss << tr(\"ETM_REACTIONS_AND_MELEE\"); break;\n\t\tcase ETM_REACTIONS_AND_FIRING: ss << tr(\"ETM_REACTIONS_AND_FIRING\"); break;\n\t\tcase ETM_REACTIONS_AND_THROWING: ss << tr(\"ETM_REACTIONS_AND_THROWING\"); break;\n\t\tcase ETM_REACTIONS_OR_MELEE: ss << tr(\"ETM_REACTIONS_OR_MELEE\"); break;\n\t\tcase ETM_REACTIONS_OR_FIRING: ss << tr(\"ETM_REACTIONS_OR_FIRING\"); break;\n\t\tcase ETM_REACTIONS_OR_THROWING: ss << tr(\"ETM_REACTIONS_OR_THROWING\"); break;\n\t\tcase ETM_BRAVERY: ss << tr(\"ETM_BRAVERY\"); break;\n\t\tcase ETM_BRAVERY_2X: ss << tr(\"ETM_BRAVERY_2X\"); break;\n\t\tcase ETM_BRAVERY_AND_REACTIONS: ss << tr(\"ETM_BRAVERY_AND_REACTIONS\"); break;\n\t\tcase ETM_BRAVERY_OR_REACTIONS: ss << tr(\"ETM_BRAVERY_OR_REACTIONS\"); break;\n\t\tcase ETM_BRAVERY_OR_REACTIONS_2X: ss << tr(\"ETM_BRAVERY_OR_REACTIONS_2X\"); break;\n\t\tcase ETM_PSI_STRENGTH: ss << tr(\"ETM_PSI_STRENGTH\"); break;\n\t\tcase ETM_PSI_STRENGTH_2X: ss << tr(\"ETM_PSI_STRENGTH_2X\"); break;\n\t\tcase ETM_PSI_SKILL: ss << tr(\"ETM_PSI_SKILL\"); break;\n\t\tcase ETM_PSI_SKILL_2X: ss << tr(\"ETM_PSI_SKILL_2X\"); break;\n\t\tcase ETM_PSI_STRENGTH_AND_SKILL: ss << tr(\"ETM_PSI_STRENGTH_AND_SKILL\"); break;\n\t\tcase ETM_PSI_STRENGTH_AND_SKILL_2X: ss << tr(\"ETM_PSI_STRENGTH_AND_SKILL_2X\"); break;\n\t\tcase ETM_PSI_STRENGTH_OR_SKILL: ss << tr(\"ETM_PSI_STRENGTH_OR_SKILL\"); break;\n\t\tcase ETM_PSI_STRENGTH_OR_SKILL_2X: ss << tr(\"ETM_PSI_STRENGTH_OR_SKILL_2X\"); break;\n\t\tcase ETM_NOTHING: ss << tr(\"ETM_NOTHING\"); break;\n\t\tdefault: ss << tr(\"STR_UNKNOWN\"); break;\n\t}\n\tif (_showIds)\n\t{\n\t\tss << \" [\" << value << \"]\";\n\t}\n\t_lstRawData->addRow(2, trp(propertyName).c_str(), ss.str().c_str());\n\t++_counter;\n\tif (value != defaultvalue)\n\t{\n\t\t_lstRawData->setCellColor(_lstRawData->getLastRowIndex(), 1, _pink);\n\t}\n}\n\n/**\n * Adds a RuleStatBonus info to the table.\n */\nvoid StatsForNerdsState::addRuleStatBonus(std::ostringstream &ss, const RuleStatBonus &value, const std::string &propertyName)\n{\n\tif (!value.isModded() && !_showDefaults)\n\t{\n\t\treturn;\n\t}\n\tresetStream(ss);\n\tbool isFirst = true;\n\tfor (const auto& item : *value.getBonusRaw())\n\t{\n\t\tint power = 0;\n\t\tfor (float number : item.second)\n\t\t{\n\t\t\t++power;\n\t\t\tif (!AreSame(number, 0.0f))\n\t\t\t{\n\t\t\t\tfloat numberAbs = number;\n\t\t\t\tif (!isFirst)\n\t\t\t\t{\n\t\t\t\t\tif (number > 0.0f)\n\t\t\t\t\t{\n\t\t\t\t\t\tss << \" + \";\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tss << \" - \";\n\t\t\t\t\t\tnumberAbs = std::abs(number);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (item.first == \"flatOne\")\n\t\t\t\t{\n\t\t\t\t\tss << numberAbs * 1;\n\t\t\t\t}\n\t\t\t\telse if (item.first == \"flatHundred\")\n\t\t\t\t{\n\t\t\t\t\tss << numberAbs * pow(100, power);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif (!AreSame(numberAbs, 1.0f))\n\t\t\t\t\t{\n\t\t\t\t\t\tss << numberAbs << \"*\";\n\t\t\t\t\t}\n\t\t\t\t\taddTranslation(ss, translationMap.at(item.first));\n\t\t\t\t\tif (power > 1)\n\t\t\t\t\t{\n\t\t\t\t\t\tss << \"^\" << power;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tisFirst = false;\n\t\t\t}\n\t\t}\n\t}\n\t_lstRawData->addRow(2, trp(propertyName).c_str(), ss.str().c_str());\n\t++_counter;\n\tif (value.isModded())\n\t{\n\t\t_lstRawData->setCellColor(_lstRawData->getLastRowIndex(), 1, _pink);\n\t}\n}\n\n/**\n * Adds a ArmorMoveCost info to the table.\n */\nvoid StatsForNerdsState::addRuleArmorMoveCost(std::ostringstream &ss, const ArmorMoveCost &value, const std::string &propertyName, const ArmorMoveCost &defaultvalue)\n{\n\tif (value == defaultvalue && !_showDefaults)\n\t{\n\t\treturn;\n\t}\n\tresetStream(ss);\n\n\tss << tr(\"STR_COST_TIME\") << \": \";\n\taddBoolOrInteger(ss, value.TimePercent, false);\n\tss << \"%\";\n\n\tss << \", \";\n\n\tss << tr(\"STR_COST_ENERGY\") << \": \";\n\taddBoolOrInteger(ss, value.EnergyPercent, false);\n\tss << \"%\";\n\n\t_lstRawData->addRow(2, trp(propertyName).c_str(), ss.str().c_str());\n\t++_counter;\n\tif (value != defaultvalue)\n\t{\n\t\t_lstRawData->setCellColor(_lstRawData->getLastRowIndex(), 1, _pink);\n\t}\n}\n\n/**\n * Adds a sprite resource path to the table.\n */\nvoid StatsForNerdsState::addSpriteResourcePath(std::ostringstream &ss, Mod *mod, const std::string &resourceSetName, const int &resourceId)\n{\n\tauto i = mod->getExtraSprites().find(resourceSetName);\n\tif (i != mod->getExtraSprites().end())\n\t{\n\t\tfor (auto* extraSprite : i->second)\n\t\t{\n\t\t\t// strip mod offset from the in-game ID\n\t\t\tint originalSpriteId = resourceId - (extraSprite->getModOwner()->offset);\n\n\t\t\tauto* mapOfSprites = extraSprite->getSprites();\n\t\t\tauto individualSprite = mapOfSprites->find(originalSpriteId);\n\t\t\tif (individualSprite != mapOfSprites->end())\n\t\t\t{\n\t\t\t\tstd::ostringstream numbers;\n\t\t\t\tresetStream(numbers);\n\t\t\t\tnumbers << \"  \" << originalSpriteId << \" + \" << extraSprite->getModOwner()->offset;\n\n\t\t\t\tresetStream(ss);\n\t\t\t\tss << individualSprite->second;\n\n\t\t\t\t_lstRawData->addRow(2, numbers.str().c_str(), ss.str().c_str());\n\t\t\t\t++_counter;\n\t\t\t\t_lstRawData->setRowColor(_lstRawData->getLastRowIndex(), _gold);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Adds sound resource paths to the table.\n */\nvoid StatsForNerdsState::addSoundVectorResourcePaths(std::ostringstream &ss, Mod *mod, const std::string &resourceSetName, const std::vector<int> &resourceIds)\n{\n\tif (resourceIds.empty())\n\t{\n\t\treturn;\n\t}\n\n\t// go through all extra sounds from all mods\n\tfor (auto& resourceSet : mod->getExtraSounds())\n\t{\n\t\t// only check the relevant ones (e.g. \"BATTLE.CAT\")\n\t\tif (resourceSet.first == resourceSetName)\n\t\t{\n\t\t\tfor (int resourceId : resourceIds)\n\t\t\t{\n\t\t\t\t// strip mod offset from the in-game ID\n\t\t\t\tint originalSoundId = resourceId - (resourceSet.second->getModOwner()->offset);\n\n\t\t\t\tauto* mapOfSounds = resourceSet.second->getSounds();\n\t\t\t\tauto individualSound = mapOfSounds->find(originalSoundId);\n\t\t\t\tif (individualSound != mapOfSounds->end())\n\t\t\t\t{\n\t\t\t\t\tstd::ostringstream numbers;\n\t\t\t\t\tresetStream(numbers);\n\t\t\t\t\tnumbers << \"  \" << originalSoundId << \" + \" << resourceSet.second->getModOwner()->offset;\n\n\t\t\t\t\tresetStream(ss);\n\t\t\t\t\tss << individualSound->second;\n\n\t\t\t\t\t_lstRawData->addRow(2, numbers.str().c_str(), ss.str().c_str());\n\t\t\t\t\t++_counter;\n\t\t\t\t\t_lstRawData->setRowColor(_lstRawData->getLastRowIndex(), _gold);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Shows the \"raw\" RuleItem data.\n */\nvoid StatsForNerdsState::initItemList()\n{\n\t_lstRawData->clearList();\n\t_lstRawData->setIgnoreSeparators(true);\n\n\tstd::ostringstream ssTopic;\n\tssTopic << tr(_topicId);\n\tif (_showIds)\n\t{\n\t\tssTopic << \" [\" << _topicId << \"]\";\n\t}\n\n\t_txtArticle->setText(tr(\"STR_ARTICLE\").arg(ssTopic.str()));\n\n\tMod *mod = _game->getMod();\n\tRuleItem *itemRule = mod->getItem(_topicId);\n\tif (!itemRule)\n\t\treturn;\n\n\t_filterOptions.clear();\n\t_filterOptions.push_back(\"STR_COMPATIBLE_AMMO\");\n\tfor (int slot = 0; slot < RuleItem::AmmoSlotMax; ++slot)\n\t{\n\t\tfor (auto* ammo : *itemRule->getCompatibleAmmoForSlot(slot))\n\t\t{\n\t\t\t_filterOptions.push_back(ammo->getType());\n\t\t}\n\t}\n\t_cbxRelatedStuff->setOptions(_filterOptions, true);\n\t_cbxRelatedStuff->setVisible(_filterOptions.size() > 1);\n\tif (_filterOptions.size() > 1)\n\t{\n\t\t_txtTitle->setAlign(ALIGN_LEFT);\n\t}\n\n\tconst auto itemBattleType = itemRule->getBattleType();\n\tstd::ostringstream ss;\n\n\taddBattleType(ss, itemBattleType, \"battleType\");\n\taddExperienceTrainingMode(ss, itemRule->getExperienceTrainingMode(), \"experienceTrainingMode\");\n\taddInteger(ss, itemRule->getManaExperience(), \"manaExperience\");\n\taddBoolean(ss, itemRule->getArcingShot(), \"arcingShot\");\n\taddBoolean(ss, itemRule->isFireExtinguisher(), \"isFireExtinguisher\");\n\taddInteger(ss, itemRule->getWaypoints(), \"waypoints\");\n\taddInteger(ss, itemRule->getSprayWaypoints(), \"sprayWaypoints\");\n\n\taddInteger(ss, itemRule->getShotgunPellets(), \"shotgunPellets\");\n\taddInteger(ss, itemRule->getShotgunBehaviorType(), \"shotgunBehavior\", 0, false, \"STR_SHOTGUN_BEHAVIOR_OXCE\", 1);\n\taddIntegerPercent(ss, itemRule->getShotgunSpread(), \"shotgunSpread\", 100);\n\taddIntegerPercent(ss, itemRule->getShotgunChoke(), \"shotgunChoke\", 100);\n\n\taddBoolean(ss, itemRule->isWaterOnly(), \"underwaterOnly\");\n\taddBoolean(ss, itemRule->isLandOnly(), \"landOnly\");\n\tint psiRequiredDefault = itemBattleType == BT_PSIAMP ? true : false;\n\taddBoolean(ss, itemRule->isPsiRequired(), \"psiRequired\", psiRequiredDefault);\n\taddBoolean(ss, itemRule->isManaRequired(), \"manaRequired\");\n\tint targetMatrixDefault = itemBattleType == BT_PSIAMP ? 6 : 7;\n\taddItemTargets(ss, itemRule, \"targetMatrix\", targetMatrixDefault);\n\taddBoolean(ss, itemRule->convertToCivilian(), \"convertToCivilian\");\n\taddBoolean(ss, itemRule->isLOSRequired(), \"LOSRequired\");\n\n\tif (itemBattleType == BT_GRENADE || _showDebug)\n\t{\n\t\taddInteger(ss, itemRule->getExplodeInventory(mod), \"explodeInventory\", 0); // not raw!\n\t}\n\tif (itemBattleType == BT_FIREARM\n\t\t|| itemBattleType == BT_GRENADE\n\t\t|| itemBattleType == BT_PROXIMITYGRENADE\n\t\t|| itemBattleType == BT_FLARE\n\t\t|| _showDebug)\n\t{\n\t\taddIntegerPercent(ss, itemRule->getNoLOSAccuracyPenalty(mod), \"noLOSAccuracyPenalty\", -1); // not raw!\n\t}\n\tif (itemBattleType == BT_FIREARM || _showDebug)\n\t{\n\t\taddIntegerPercent(ss, itemRule->getKneelBonus(mod), \"kneelBonus\", 115); // not raw!\n\t}\n\taddBoolean(ss, itemRule->isTwoHanded(), \"twoHanded\");\n\taddBoolean(ss, itemRule->isBlockingBothHands(), \"blockBothHands\");\n\tint oneHandedPenaltyCurrent = itemRule->getOneHandedPenalty(mod);\n\tint oneHandedPenaltyDefault = itemRule->isTwoHanded() ? 80 : oneHandedPenaltyCurrent;\n\taddIntegerPercent(ss, oneHandedPenaltyCurrent, \"oneHandedPenalty\", oneHandedPenaltyDefault); // not raw!\n\n\taddInteger(ss, itemRule->getMinRange(), \"minRange\");\n\taddInteger(ss, itemRule->getMaxRange(), \"maxRange\", 200);\n\tint aimRangeDefault = itemBattleType == BT_PSIAMP ? 0 : 200;\n\taddInteger(ss, itemRule->getAimRange(), \"aimRange\", aimRangeDefault);\n\taddInteger(ss, itemRule->getAutoRange(), \"autoRange\", 7);\n\taddInteger(ss, itemRule->getSnapRange(), \"snapRange\", 15);\n\tint dropoffDefault = itemBattleType == BT_PSIAMP ? 1 : 2;\n\taddInteger(ss, itemRule->getDropoff(), \"dropoff\", dropoffDefault);\n\n\taddRuleStatBonus(ss, *itemRule->getAccuracyMultiplierRaw(), \"accuracyMultiplier\");\n\taddIntegerPercent(ss, itemRule->getConfigAimed()->accuracy, \"accuracyAimed\");\n\taddIntegerPercent(ss, itemRule->getConfigAuto()->accuracy, \"accuracyAuto\");\n\taddIntegerPercent(ss, itemRule->getConfigSnap()->accuracy, \"accuracySnap\");\n\taddRuleItemUseCostFull(ss, itemRule->getCostAimed(), \"costAimed\", RuleItemUseCost(), true, itemRule->getFlatAimed());\n\taddRuleItemUseCostFull(ss, itemRule->getCostAuto(), \"costAuto\", RuleItemUseCost(), true, itemRule->getFlatAuto());\n\taddRuleItemUseCostFull(ss, itemRule->getCostSnap(), \"costSnap\", RuleItemUseCost(), true, itemRule->getFlatSnap());\n\n\taddRuleStatBonus(ss, *itemRule->getMeleeMultiplierRaw(), \"meleeMultiplier\");\n\taddIntegerPercent(ss, itemRule->getConfigMelee()->accuracy, \"accuracyMelee\");\n\taddRuleItemUseCostFull(ss, itemRule->getCostMelee(), \"costMelee\", RuleItemUseCost(), true, itemRule->getFlatMelee());\n\n\taddSingleString(ss, itemRule->getPsiAttackName(), \"psiAttackName\");\n\taddIntegerPercent(ss, itemRule->getAccuracyUse(), \"accuracyUse\");\n\tif (itemBattleType == BT_PSIAMP || _showDebug)\n\t{\n\t\taddIntegerPercent(ss, itemRule->getAccuracyMind(), \"accuracyMindControl\");\n\t\taddIntegerPercent(ss, itemRule->getAccuracyPanic(), \"accuracyPanic\", 20);\n\t}\n\tint tuUseDefault = (itemBattleType == BT_PSIAMP/* && itemRule->getPsiAttackName().empty()*/) ? 0 : 25;\n\taddRuleItemUseCostFull(ss, itemRule->getCostUse(), \"costUse\", RuleItemUseCost(tuUseDefault), true, itemRule->getFlatUse());\n\tif (itemBattleType == BT_PSIAMP || _showDebug)\n\t{\n\t\t// using flatUse! there are no flatMindcontrol and flatPanic\n\t\t// always show! as if default was 0 instead of 25\n\t\t// don't show if Time == 0, for the game it means disabled (even if other costs are non-zero)\n\t\tif (itemRule->getCostMind().Time > 0 || _showDebug)\n\t\t{\n\t\t\taddRuleItemUseCostFull(ss, itemRule->getCostMind(), \"costMindcontrol\", RuleItemUseCost(0), true, itemRule->getFlatUse());\n\t\t}\n\t\tif (itemRule->getCostPanic().Time > 0 || _showDebug)\n\t\t{\n\t\t\taddRuleItemUseCostFull(ss, itemRule->getCostPanic(), \"costPanic\", RuleItemUseCost(0), true, itemRule->getFlatUse());\n\t\t}\n\t}\n\n\taddInteger(ss, itemRule->getWeight(), \"weight\", 3);\n\taddInteger(ss, itemRule->getThrowRange(), \"throwRange\", 200);\n\taddInteger(ss, itemRule->getUnderwaterThrowRange(), \"underwaterThrowRange\", 200);\n\n\taddInteger(ss, itemRule->getThrowDropoffRange(), \"throwDropoffRange\", 99);\n\taddInteger(ss, itemRule->getUnderwaterThrowDropoffRange(), \"underwaterThrowDropoffRange\", 99);\n\taddInteger(ss, itemRule->getThrowDropoff(), \"throwDropoff\", 5);\n\n\taddRuleStatBonus(ss, *itemRule->getThrowMultiplierRaw(), \"throwMultiplier\");\n\taddIntegerPercent(ss, itemRule->getAccuracyThrow(), \"accuracyThrow\", 100);\n\taddRuleItemUseCostFull(ss, itemRule->getCostThrow(), \"costThrow\", RuleItemUseCost(25), true, itemRule->getFlatThrow());\n\taddRuleItemUseCostFull(ss, itemRule->getCostPrime(), \"costPrime\", RuleItemUseCost(50), true, itemRule->getFlatPrime());\n\taddRuleItemUseCostFull(ss, itemRule->getCostUnprime(), \"costUnprime\", RuleItemUseCost(25), true, itemRule->getFlatUnprime());\n\n\tif ((mod->getEnableCloseQuartersCombat() && itemBattleType == BT_FIREARM) || _showDebug)\n\t{\n\t\taddRuleStatBonus(ss, *itemRule->getCloseQuartersMultiplierRaw(), \"closeQuartersMultiplier\");\n\t\taddIntegerPercent(ss, itemRule->getAccuracyCloseQuarters(mod), \"accuracyCloseQuarters\", 100); // not raw!\n\t}\n\n\tfor (int i = 0; i < 2; i++)\n\t{\n\t\tconst RuleDamageType *rule = (i == 0) ? itemRule->getDamageType() : itemRule->getMeleeType();\n\t\tconst RuleDamageType *ruleByResistType = mod->getDamageType(rule->ResistType);\n\n\t\tif (i == 0)\n\t\t{\n\t\t\tItemDamageType damageTypeDefault = DT_NONE;\n\t\t\tif (rule->ResistType == DT_NONE)\n\t\t\t{\n\t\t\t\tif (itemBattleType == BT_FIREARM || itemBattleType == BT_AMMO || itemBattleType == BT_MELEE)\n\t\t\t\t{\n\t\t\t\t\tif (itemRule->getClipSize() != 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tdamageTypeDefault = DAMAGE_TYPES;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (itemBattleType == BT_PSIAMP)\n\t\t\t\t{\n\t\t\t\t\tif (!itemRule->getPsiAttackName().empty())\n\t\t\t\t\t{\n\t\t\t\t\t\tdamageTypeDefault = DAMAGE_TYPES;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\taddDamageType(ss, rule->ResistType, \"damageType\", damageTypeDefault);\n\t\t\taddInteger(ss, itemRule->getPower(), \"power\");\n\t\t\taddFloat(ss, itemRule->getPowerRangeReductionRaw(), \"powerRangeReduction\");\n\t\t\taddFloat(ss, itemRule->getPowerRangeThresholdRaw(), \"powerRangeThreshold\");\n\t\t\taddRuleStatBonus(ss, *itemRule->getDamageBonusRaw(), \"damageBonus\");\n\t\t\tif (!_showDebug)\n\t\t\t{\n\t\t\t\taddInteger(ss, rule->FixRadius, \"blastRadius\", ruleByResistType->FixRadius);\n\t\t\t}\n\t\t\taddHeading(\"damageAlter\");\n\t\t}\n\t\telse\n\t\t{\n\t\t\taddDamageType(ss, rule->ResistType, \"meleeType\", DT_MELEE);\n\t\t\taddInteger(ss, itemRule->getMeleePower(), \"meleePower\");\n\t\t\taddRuleStatBonus(ss, *itemRule->getMeleeBonusRaw(), \"meleeBonus\");\n\t\t\taddHeading(\"meleeAlter\");\n\t\t}\n\n\t\tif (_showDebug || i > 0)\n\t\t{\n\t\t\taddInteger(ss, rule->FixRadius, \"FixRadius\", ruleByResistType->FixRadius);\n\t\t}\n\n\t\tbool isCustomDefault = (i == 0 ? itemRule->isDamageTypeSet() : itemRule->isMeleeTypeSet());\n\t\tif (!isCustomDefault)\n\t\t{\n\t\t\t// default RandomType is 8 (DRT_STANDARD)\n\t\t\t// but the RandomType of a default ResistType 0 (DT_NONE) is 5 (DRT_NONE)\n\t\t\t// so we need this exceptional handling here to correctly show what's modded/changed and what's not\n\t\t\taddDamageRandomType(ss, rule->RandomType, \"RandomType\", DRT_STANDARD);\n\t\t}\n\t\telse\n\t\t{\n\t\t\taddDamageRandomType(ss, rule->RandomType, \"RandomType\", ruleByResistType->RandomType);\n\t\t}\n\n\t\taddBoolean(ss, rule->FireBlastCalc, \"FireBlastCalc\", ruleByResistType->FireBlastCalc);\n\t\taddBoolean(ss, rule->IgnoreDirection, \"IgnoreDirection\", ruleByResistType->IgnoreDirection);\n\t\taddBoolean(ss, rule->IgnoreSelfDestruct, \"IgnoreSelfDestruct\", ruleByResistType->IgnoreSelfDestruct);\n\t\taddBoolean(ss, rule->IgnorePainImmunity, \"IgnorePainImmunity\", ruleByResistType->IgnorePainImmunity);\n\t\taddBoolean(ss, rule->IgnoreNormalMoraleLose, \"IgnoreNormalMoraleLose\", ruleByResistType->IgnoreNormalMoraleLose);\n\t\taddBoolean(ss, rule->IgnoreOverKill, \"IgnoreOverKill\", ruleByResistType->IgnoreOverKill);\n\n\t\taddFloatAsPercentage(ss, rule->ArmorEffectiveness, \"ArmorEffectiveness\", ruleByResistType->ArmorEffectiveness);\n\t\taddFloatAsPercentage(ss, rule->RadiusEffectiveness, \"RadiusEffectiveness\", ruleByResistType->RadiusEffectiveness);\n\t\taddFloat(ss, rule->RadiusReduction, \"RadiusReduction\", ruleByResistType->RadiusReduction);\n\n\t\taddInteger(ss, rule->FireThreshold, \"FireThreshold\", ruleByResistType->FireThreshold);\n\t\taddInteger(ss, rule->SmokeThreshold, \"SmokeThreshold\", ruleByResistType->SmokeThreshold);\n\n\t\taddFloatAsPercentage(ss, rule->ToArmorPre, \"ToArmorPre\", ruleByResistType->ToArmorPre);\n\t\taddBoolean(ss, rule->RandomArmorPre, \"RandomArmorPre\", ruleByResistType->RandomArmorPre);\n\n\t\taddFloatAsPercentage(ss, rule->ToArmor, \"ToArmor\", ruleByResistType->ToArmor);\n\t\taddBoolean(ss, rule->RandomArmor, \"RandomArmor\", ruleByResistType->RandomArmor);\n\n\t\taddFloatAsPercentage(ss, rule->ToHealth, \"ToHealth\", ruleByResistType->ToHealth);\n\t\taddBoolean(ss, rule->RandomHealth, \"RandomHealth\", ruleByResistType->RandomHealth);\n\n\t\taddFloatAsPercentage(ss, rule->ToStun, \"ToStun\", ruleByResistType->ToStun);\n\t\taddBoolean(ss, rule->RandomStun, \"RandomStun\", ruleByResistType->RandomStun);\n\n\t\taddFloatAsPercentage(ss, rule->ToWound, \"ToWound\", ruleByResistType->ToWound);\n\t\taddBoolean(ss, rule->RandomWound, \"RandomWound\", ruleByResistType->RandomWound);\n\n\t\taddFloatAsPercentage(ss, rule->ToTime, \"ToTime\", ruleByResistType->ToTime);\n\t\taddBoolean(ss, rule->RandomTime, \"RandomTime\", ruleByResistType->RandomTime);\n\n\t\taddFloatAsPercentage(ss, rule->ToEnergy, \"ToEnergy\", ruleByResistType->ToEnergy);\n\t\taddBoolean(ss, rule->RandomEnergy, \"RandomEnergy\", ruleByResistType->RandomEnergy);\n\n\t\taddFloatAsPercentage(ss, rule->ToMorale, \"ToMorale\", ruleByResistType->ToMorale);\n\t\taddBoolean(ss, rule->RandomMorale, \"RandomMorale\", ruleByResistType->RandomMorale);\n\n\t\taddFloatAsPercentage(ss, rule->ToItem, \"ToItem\", ruleByResistType->ToItem);\n\t\taddBoolean(ss, rule->RandomItem, \"RandomItem\", ruleByResistType->RandomItem);\n\n\t\taddFloatAsPercentage(ss, rule->ToMana, \"ToMana\", ruleByResistType->ToMana);\n\t\taddBoolean(ss, rule->RandomMana, \"RandomMana\", ruleByResistType->RandomMana);\n\n\t\taddFloatAsPercentage(ss, rule->ToTile, \"ToTile\", ruleByResistType->ToTile);\n\t\taddBoolean(ss, rule->RandomTile, \"RandomTile\", ruleByResistType->RandomTile);\n\t\taddInteger(ss, rule->TileDamageMethod, \"TileDamageMethod\", ruleByResistType->TileDamageMethod);\n\t\taddInteger(ss, rule->TileDamageLimit, \"TileDamageLimit\", ruleByResistType->TileDamageLimit);\n\n\t\tendHeading();\n\t}\n\n\t// skillApplied*\n\t// strengthApplied*\n\t// autoShots*\n\n\taddHeading(\"confAimed\");\n\t{\n\t\taddInteger(ss, itemRule->getConfigAimed()->shots, \"shots\", 1);\n\t\taddInteger(ss, itemRule->getConfigAimed()->spendPerShot, \"spendPerShot\", 1);\n\t\taddBoolean(ss, itemRule->getConfigAimed()->followProjectiles, \"followProjectiles\", true);\n\t\taddSingleString(ss, itemRule->getConfigAimed()->name, \"name\", \"STR_AIMED_SHOT\");\n\t\taddSingleString(ss, itemRule->getConfigAimed()->shortName, \"shortName\");\n\t\taddInteger(ss, itemRule->getConfigAimed()->ammoSlot, \"ammoSlot\");\n\t\taddInteger(ss, itemRule->getConfigAimed()->ammoZombieUnitChanceOverride, \"ammoZombieUnitChanceOverride\", -1);\n\t\taddInteger(ss, itemRule->getConfigAimed()->ammoSpawnUnitChanceOverride, \"ammoSpawnUnitChanceOverride\", -1);\n\t\taddInteger(ss, itemRule->getConfigAimed()->ammoSpawnItemChanceOverride, \"ammoSpawnItemChanceOverride\", -1);\n\t\taddBoolean(ss, itemRule->getConfigAimed()->arcing, \"arcing\");\n\t\tendHeading();\n\t}\n\n\taddHeading(\"confAuto\");\n\t{\n\t\taddInteger(ss, itemRule->getConfigAuto()->shots, \"shots\", 3);\n\t\taddInteger(ss, itemRule->getConfigAuto()->spendPerShot, \"spendPerShot\", 1);\n\t\taddBoolean(ss, itemRule->getConfigAuto()->followProjectiles, \"followProjectiles\", true);\n\t\taddSingleString(ss, itemRule->getConfigAuto()->name, \"name\", \"STR_AUTO_SHOT\");\n\t\taddSingleString(ss, itemRule->getConfigAuto()->shortName, \"shortName\");\n\t\taddInteger(ss, itemRule->getConfigAuto()->ammoSlot, \"ammoSlot\");\n\t\taddInteger(ss, itemRule->getConfigAuto()->ammoZombieUnitChanceOverride, \"ammoZombieUnitChanceOverride\", -1);\n\t\taddInteger(ss, itemRule->getConfigAuto()->ammoSpawnUnitChanceOverride, \"ammoSpawnUnitChanceOverride\", -1);\n\t\taddInteger(ss, itemRule->getConfigAuto()->ammoSpawnItemChanceOverride, \"ammoSpawnItemChanceOverride\", -1);\n\t\taddBoolean(ss, itemRule->getConfigAuto()->arcing, \"arcing\");\n\t\tendHeading();\n\t}\n\n\taddHeading(\"confSnap\");\n\t{\n\t\taddInteger(ss, itemRule->getConfigSnap()->shots, \"shots\", 1);\n\t\taddInteger(ss, itemRule->getConfigSnap()->spendPerShot, \"spendPerShot\", 1);\n\t\taddBoolean(ss, itemRule->getConfigSnap()->followProjectiles, \"followProjectiles\", true);\n\t\taddSingleString(ss, itemRule->getConfigSnap()->name, \"name\", \"STR_SNAP_SHOT\");\n\t\taddSingleString(ss, itemRule->getConfigSnap()->shortName, \"shortName\");\n\t\taddInteger(ss, itemRule->getConfigSnap()->ammoSlot, \"ammoSlot\");\n\t\taddInteger(ss, itemRule->getConfigSnap()->ammoZombieUnitChanceOverride, \"ammoZombieUnitChanceOverride\", -1);\n\t\taddInteger(ss, itemRule->getConfigSnap()->ammoSpawnUnitChanceOverride, \"ammoSpawnUnitChanceOverride\", -1);\n\t\taddInteger(ss, itemRule->getConfigSnap()->ammoSpawnItemChanceOverride, \"ammoSpawnItemChanceOverride\", -1);\n\t\taddBoolean(ss, itemRule->getConfigSnap()->arcing, \"arcing\");\n\t\tendHeading();\n\t}\n\n\taddHeading(\"confMelee\");\n\t{\n\t\taddInteger(ss, itemRule->getConfigMelee()->shots, \"shots\", 1);\n\t\taddInteger(ss, itemRule->getConfigMelee()->spendPerShot, \"spendPerShot\", 1);\n\t\taddBoolean(ss, itemRule->getConfigMelee()->followProjectiles, \"followProjectiles\", true);\n\t\taddSingleString(ss, itemRule->getConfigMelee()->name, \"name\");\n\t\taddSingleString(ss, itemRule->getConfigMelee()->shortName, \"shortName\");\n\t\tint ammoSlotCurrent = itemRule->getConfigMelee()->ammoSlot;\n\t\tint ammoSlotDefault = itemBattleType == BT_MELEE ? 0 : RuleItem::AmmoSlotSelfUse;\n\t\tif (itemBattleType == BT_NONE)\n\t\t{\n\t\t\t// exception for unspecified battle type, e.g. Elerium-115 in vanilla\n\t\t\tif (ammoSlotCurrent <= 0)\n\t\t\t{\n\t\t\t\tammoSlotDefault = ammoSlotCurrent;\n\t\t\t}\n\t\t}\n\t\taddInteger(ss, ammoSlotCurrent, \"ammoSlot\", ammoSlotDefault);\n\t\taddInteger(ss, itemRule->getConfigMelee()->ammoZombieUnitChanceOverride, \"ammoZombieUnitChanceOverride\", -1);\n\t\taddInteger(ss, itemRule->getConfigMelee()->ammoSpawnUnitChanceOverride, \"ammoSpawnUnitChanceOverride\", -1);\n\t\taddInteger(ss, itemRule->getConfigMelee()->ammoSpawnItemChanceOverride, \"ammoSpawnItemChanceOverride\", -1);\n\t\taddBoolean(ss, itemRule->getConfigMelee()->arcing, \"arcing\");\n\t\tendHeading();\n\t}\n\n\taddInteger(ss, itemRule->getClipSize(), \"clipSize\", 0, false, \"STR_CLIP_SIZE_UNLIMITED\", -1);\n\taddBoolean(ss, itemRule->isAmmoRechargeable(), \"isAmmoRechargeable\");\n\n\t// compatibleAmmo*\n\t// tuLoad*\n\t// tuUnload*\n\n\taddHeading(\"primaryAmmo\");\n\t{\n\t\taddVectorOfRules(ss, *itemRule->getCompatibleAmmoForSlot(0), \"compatibleAmmo\");\n\t\taddInteger(ss, itemRule->getTULoad(0), \"tuLoad\", 15);\n\t\taddInteger(ss, itemRule->getTUUnload(0), \"tuUnload\", 8);\n\t\tendHeading();\n\t}\n\n\taddHeading(\"ammo[1]\");\n\t{\n\t\taddVectorOfRules(ss, *itemRule->getCompatibleAmmoForSlot(1), \"compatibleAmmo\");\n\t\taddInteger(ss, itemRule->getTULoad(1), \"tuLoad\", 15);\n\t\taddInteger(ss, itemRule->getTUUnload(1), \"tuUnload\", 8);\n\t\tendHeading();\n\t}\n\n\taddHeading(\"ammo[2]\");\n\t{\n\t\taddVectorOfRules(ss, *itemRule->getCompatibleAmmoForSlot(2), \"compatibleAmmo\");\n\t\taddInteger(ss, itemRule->getTULoad(2), \"tuLoad\", 15);\n\t\taddInteger(ss, itemRule->getTUUnload(2), \"tuUnload\", 8);\n\t\tendHeading();\n\t}\n\n\taddHeading(\"ammo[3]\");\n\t{\n\t\taddVectorOfRules(ss, *itemRule->getCompatibleAmmoForSlot(3), \"compatibleAmmo\");\n\t\taddInteger(ss, itemRule->getTULoad(3), \"tuLoad\", 15);\n\t\taddInteger(ss, itemRule->getTUUnload(3), \"tuUnload\", 8);\n\t\tendHeading();\n\t}\n\n\taddInteger(ss, itemRule->getArmor(), \"armor\", 20);\n\n\taddBattleMediKitType(ss, itemRule->getMediKitType(), \"medikitType\");\n\taddSingleString(ss, itemRule->getPainKillerActionName(), \"painKillerActionName\", \"STR_PAIN_KILLER\");\n\taddSingleString(ss, itemRule->getStimulantActionName(), \"stimulantActionName\", \"STR_STIMULANT\");\n\taddSingleString(ss, itemRule->getHealActionName(), \"healActionName\", \"STR_HEAL\");\n\taddSingleString(ss, itemRule->getMedikitActionName(), \"medikitActionName\", \"STR_USE_MEDI_KIT\");\n\taddBoolean(ss, itemRule->getAllowTargetSelf(), \"medikitTargetSelf\");\n\taddBoolean(ss, itemRule->getAllowTargetImmune(), \"medikitTargetImmune\");\n\taddMediKitTargets(ss, itemRule, \"medikitTargetMatrix\", 63);\n\taddBoolean(ss, itemRule->isConsumable(), \"isConsumable\");\n\taddInteger(ss, itemRule->getPainKillerQuantity(), \"painKiller\");\n\taddInteger(ss, itemRule->getHealQuantity(), \"heal\");\n\taddInteger(ss, itemRule->getStimulantQuantity(), \"stimulant\");\n\taddInteger(ss, itemRule->getWoundRecovery(), \"woundRecovery\");\n\taddInteger(ss, itemRule->getHealthRecovery(), \"healthRecovery\");\n\taddInteger(ss, itemRule->getStunRecovery(), \"stunRecovery\");\n\taddInteger(ss, itemRule->getEnergyRecovery(), \"energyRecovery\");\n\taddInteger(ss, itemRule->getManaRecovery(), \"manaRecovery\");\n\taddInteger(ss, itemRule->getMoraleRecovery(), \"moraleRecovery\");\n\taddFloatAsPercentage(ss, itemRule->getPainKillerRecovery(), \"painKillerRecovery\", 1.0f);\n\n\taddVectorOfResearch(ss, itemRule->getRequirements(), \"requires\");\n\taddVectorOfResearch(ss, itemRule->getBuyRequirements(), \"requiresBuy\");\n\taddVectorOfStrings(ss, mod->getBaseFunctionNames(itemRule->getRequiresBuyBaseFunc()), \"requiresBuyBaseFunc\");\n\taddSingleString(ss, itemRule->getRequiresBuyCountry(), \"requiresBuyCountry\");\n\taddVectorOfStrings(ss, itemRule->getCategories(), \"categories\");\n\taddVectorOfRulesId(ss, itemRule->getSupportedInventorySections(), \"supportedInventorySections\");\n\n\taddDouble(ss, itemRule->getSize(), \"size\");\n\tif (_game->getSavedGame()->getBuyPriceCoefficient() == 100)\n\t{\n\t\taddInteger(ss, itemRule->getBuyCost(), \"costBuy\", 0, true);\n\t}\n\telse\n\t{\n\t\taddHeading(\"_calculatedValues\", \"STR_FOR_DIFFICULTY\", true);\n\t\t{\n\t\t\tint adjustedCost = itemRule->getBuyCost() * _game->getSavedGame()->getBuyPriceCoefficient() / 100;\n\t\t\taddInteger(ss, adjustedCost, \"costBuy\", 0, true);\n\n\t\t\tendHeading();\n\t\t}\n\t}\n\taddInteger(ss, itemRule->getMonthlyBuyLimit(), \"monthlyBuyLimit\");\n\taddInteger(ss, itemRule->getTransferTime(), \"transferTime\", 24);\n\taddInteger(ss, itemRule->getMonthlySalary(), \"monthlySalary\", 0, true);\n\taddInteger(ss, itemRule->getMonthlyMaintenance(), \"monthlyMaintenance\", 0, true);\n\tif (_game->getSavedGame()->getSellPriceCoefficient() == 100)\n\t{\n\t\taddInteger(ss, itemRule->getSellCost(), \"costSell\", 0, true);\n\t}\n\telse\n\t{\n\t\taddHeading(\"_calculatedValues\", \"STR_FOR_DIFFICULTY\", true);\n\t\t{\n\t\t\tint adjustedCost = itemRule->getSellCost() * _game->getSavedGame()->getSellPriceCoefficient() / 100;\n\t\t\taddInteger(ss, adjustedCost, \"costSell\", 0, true);\n\n\t\t\tendHeading();\n\t\t}\n\t}\n\n\tModScript::scriptCallback<ModScript::StatsForNerdsItem>(itemRule, itemRule, this, _game->getSavedGame());\n\n\tif (_showDebug)\n\t{\n\t\taddSection(\"{Modding section}\", \"You don't need this info as a player\", _white, true);\n\n\t\taddSection(\"{Naming}\", \"\", _white);\n\t\taddSingleString(ss, itemRule->getType(), \"type\");\n\t\taddSingleString(ss, itemRule->getUfopediaType(), \"ufopediaType\");\n\t\taddSingleString(ss, itemRule->getName(), \"name\", itemRule->getType());\n\t\taddSingleString(ss, itemRule->getNameAsAmmo(), \"nameAsAmmo\");\n\t\taddInteger(ss, itemRule->getLoadOrder(), \"loadOrder\");\n\t\taddInteger(ss, itemRule->getListOrder(), \"listOrder\");\n\t\taddBoolean(ss, itemRule->getHidePower(), \"hidePower\");\n\t\taddBoolean(ss, itemRule->getIgnoreAmmoPower(), \"ignoreAmmoPower\");\n\t\taddSingleString(ss, itemRule->getMonthlyBuyLimitMessage(), \"monthlyBuyLimitMessage\");\n\n\t\taddSection(\"{Inventory}\", \"\", _white);\n\t\taddVectorOfIntegers(ss, itemRule->getCustomItemPreviewIndex(), \"customItemPreviewIndex\");\n\t\taddInteger(ss, itemRule->getInventoryWidth(), \"invWidth\", -1); // always show!\n\t\taddInteger(ss, itemRule->getInventoryHeight(), \"invHeight\", -1); // always show!\n\t\taddRuleId(ss, itemRule->getDefaultInventorySlot(), \"defaultInventorySlot\");\n\t\taddInteger(ss, itemRule->getDefaultInventorySlotX(), \"defaultInvSlotX\");\n\t\taddInteger(ss, itemRule->getDefaultInventorySlotY(), \"defaultInvSlotY\");\n\t\taddBoolean(ss, itemRule->isFixed(), \"fixedWeapon\");\n\t\taddBoolean(ss, itemRule->isSpecialUsingEmptyHand(), \"specialUseEmptyHand\");\n\t\taddBoolean(ss, itemRule->showSpecialInEmptyHand(), \"specialUseEmptyHandShow\");\n\n\t\taddHeading(\"inventoryMoveCost\");\n\t\t{\n\t\t\taddInteger(ss, itemRule->getInventoryMoveCostPercent(), \"basePercent\", 100);\n\n\t\t\tendHeading();\n\t\t}\n\n\t\taddSection(\"{Recovery}\", \"\", _white);\n\t\taddBoolean(ss, !itemRule->canBeEquippedBeforeBaseDefense(), \"ignoreInBaseDefense\"); // negated!\n\t\taddBoolean(ss, !itemRule->canBeEquippedToCraftInventory(), \"ignoreInCraftEquip\", !itemRule->isUsefulBattlescapeItem()); // negated!\n\t\taddInteger(ss, itemRule->getSpecialType(), \"specialType\", -1);\n\t\taddBoolean(ss, !itemRule->getRecoveryDividers().empty(), \"recoveryDividers*\", false); // just say if there are any or not\n\t\taddBoolean(ss, !itemRule->getRecoveryTransformations().empty(), \"recoveryTransformations*\", false); // just say if there are any or not\n\t\taddBoolean(ss, itemRule->isRecoverable(), \"recover\", true);\n\t\taddBoolean(ss, itemRule->isCorpseRecoverable(), \"recoverCorpse\", true);\n\t\taddInteger(ss, itemRule->getRecoveryPoints(), \"recoveryPoints\");\n\t\taddBoolean(ss, itemRule->isAlien(), \"liveAlien\");\n\t\taddInteger(ss, itemRule->getPrisonType(), \"prisonType\");\n\t\taddSingleString(ss, itemRule->getSellActionMessage(), \"sellActionMessage\");\n\t\taddInteger(ss, itemRule->getVehicleFixedAmmoSlot(), \"vehicleFixedAmmoSlot\");\n\n\t\taddSection(\"{Explosives}\", \"\", _white);\n\t\taddInteger(ss, itemRule->getPowerForAnimation(), \"powerForAnimation\");\n\t\taddBoolean(ss, itemRule->isHiddenOnMinimap(), \"hiddenOnMinimap\");\n\t\taddSingleString(ss, itemRule->getPrimeActionName(), \"primeActionName\", \"STR_PRIME_GRENADE\");\n\t\taddSingleString(ss, itemRule->getPrimeActionMessage(), \"primeActionMessage\", \"STR_GRENADE_IS_ACTIVATED\");\n\t\taddSingleString(ss, itemRule->getUnprimeActionName(), \"unprimeActionName\");\n\t\taddSingleString(ss, itemRule->getUnprimeActionMessage(), \"unprimeActionMessage\", \"STR_GRENADE_IS_DEACTIVATED\");\n\t\tBattleFuseType fuseTypeDefault = BFT_NONE;\n\t\tif (itemBattleType == BT_PROXIMITYGRENADE)\n\t\t{\n\t\t\tfuseTypeDefault = BFT_INSTANT;\n\t\t}\n\t\telse if (itemBattleType == BT_GRENADE)\n\t\t{\n\t\t\tfuseTypeDefault = BFT_SET;\n\t\t}\n\t\taddBattleFuseType(ss, itemRule->getFuseTimerType(), \"fuseType\", fuseTypeDefault);\n\t\taddHeading(\"fuseTriggerEvents:\");\n\t\t{\n\t\t\taddBoolean(ss, itemRule->getFuseTriggerEvent()->defaultBehavior, \"defaultBehavior\", true);\n\t\t\taddBoolean(ss, itemRule->getFuseTriggerEvent()->throwTrigger, \"throwTrigger\");\n\t\t\taddBoolean(ss, itemRule->getFuseTriggerEvent()->throwExplode, \"throwExplode\");\n\t\t\taddBoolean(ss, itemRule->getFuseTriggerEvent()->proximityTrigger, \"proximityTrigger\");\n\t\t\taddBoolean(ss, itemRule->getFuseTriggerEvent()->proximityExplode, \"proximityExplode\");\n\t\t\tendHeading();\n\t\t}\n\t\taddIntegerPercent(ss, itemRule->getSpecialChance(), \"specialChance\", 100);\n\n\t\taddSection(\"{Spawning}\", \"\", _white);\n\t\taddBoolean(ss, !itemRule->getZombieUnitByArmorMaleRaw().empty(), \"zombieUnitByArmorMale*\", false); // just say if there are any or not\n\t\taddBoolean(ss, !itemRule->getZombieUnitByArmorFemaleRaw().empty(), \"zombieUnitByArmorFemale*\", false); // just say if there are any or not\n\t\taddBoolean(ss, !itemRule->getZombieUnitByTypeRaw().empty(), \"zombieUnitByType*\", false); // just say if there are any or not\n\t\taddSingleString(ss, itemRule->getZombieUnit(nullptr), \"zombieUnit\");\n\t\taddIntegerPercent(ss, itemRule->getZombieUnitChance(), \"zombieUnitChance\", 100); // default -1 means same as \"specialChance\"\n\t\taddInteger(ss, itemRule->getZombieUnitFaction(), \"zombieUnitFaction\", 1); // hostile\n\t\taddRule(ss, itemRule->getSpawnUnit(), \"spawnUnit\");\n\t\taddIntegerPercent(ss, itemRule->getSpawnUnitChance(), \"spawnUnitChance\", 100); // default -1 means same as \"specialChance\"\n\t\taddInteger(ss, itemRule->getSpawnUnitFaction(), \"spawnUnitFaction\", -1); // none (i.e. same faction as attacker)\n\t\taddRule(ss, itemRule->getSpawnItem(), \"spawnItem\");\n\t\taddIntegerPercent(ss, itemRule->getSpawnItemChance(), \"spawnItemChance\", 100); // default -1 means same as \"specialChance\"\n\n\t\taddSection(\"{Sprites}\", \"\", _white);\n\t\taddBoolean(ss, itemRule->getFixedShow(), \"fixedWeaponShow\");\n\t\taddInteger(ss, itemRule->getTurretType(), \"turretType\", -1);\n\n\t\taddInteger(ss, itemRule->getBigSprite(), \"bigSprite\", -1);\n\t\taddSpriteResourcePath(ss, mod, \"BIGOBS.PCK\", itemRule->getBigSprite());\n\t\taddInteger(ss, itemRule->getFloorSprite(), \"floorSprite\", -1);\n\t\taddSpriteResourcePath(ss, mod, \"FLOOROB.PCK\", itemRule->getFloorSprite());\n\t\taddInteger(ss, itemRule->getHandSprite(), \"handSprite\", 120);\n\t\taddSpriteResourcePath(ss, mod, \"HANDOB.PCK\", itemRule->getHandSprite());\n\t\taddInteger(ss, itemRule->getSpecialIconSprite(), \"specialIconSprite\", -1);\n\t\taddSpriteResourcePath(ss, mod, \"SPICONS.DAT\", itemRule->getSpecialIconSprite());\n\t\taddInteger(ss, itemRule->getBulletSprite(), \"bulletSprite\", -1);\n\t\taddSingleString(ss, itemRule->getMediKitCustomBackground(), \"medikitBackground\");\n\n\t\taddSection(\"{Sounds}\", \"\", _white);\n\t\taddVectorOfIntegers(ss, itemRule->getReloadSoundRaw(), \"reloadSound\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", itemRule->getReloadSoundRaw());\n\t\taddVectorOfIntegers(ss, itemRule->getPrimeSoundRaw(), \"primeSound\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", itemRule->getPrimeSoundRaw());\n\t\taddVectorOfIntegers(ss, itemRule->getUnprimeSoundRaw(), \"unprimeSound\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", itemRule->getUnprimeSoundRaw());\n\t\taddVectorOfIntegers(ss, itemRule->getFireSoundRaw(), \"fireSound\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", itemRule->getFireSoundRaw());\n\t\taddVectorOfIntegers(ss, itemRule->getHitSoundRaw(), \"hitSound\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", itemRule->getHitSoundRaw());\n\t\taddVectorOfIntegers(ss, itemRule->getHitMissSoundRaw(), \"hitMissSound\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", itemRule->getHitMissSoundRaw());\n\t\taddVectorOfIntegers(ss, itemRule->getMeleeSoundRaw(), \"meleeSound\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", itemRule->getMeleeSoundRaw());\n\t\taddVectorOfIntegers(ss, itemRule->getMeleeHitSoundRaw(), \"meleeHitSound\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", itemRule->getMeleeHitSoundRaw());\n\t\taddVectorOfIntegers(ss, itemRule->getMeleeMissSoundRaw(), \"meleeMissSound\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", itemRule->getMeleeMissSoundRaw());\n\t\taddVectorOfIntegers(ss, itemRule->getPsiSoundRaw(), \"psiSound\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", itemRule->getPsiSoundRaw());\n\t\taddVectorOfIntegers(ss, itemRule->getPsiMissSoundRaw(), \"psiMissSound\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", itemRule->getPsiMissSoundRaw());\n\t\taddVectorOfIntegers(ss, itemRule->getExplosionHitSoundRaw(), \"explosionHitSound\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", itemRule->getExplosionHitSoundRaw());\n\n\t\taddSection(\"{Animations}\", \"\", _white);\n\t\taddInteger(ss, itemRule->getHitAnimation(), \"hitAnimation\");\n\t\taddInteger(ss, itemRule->getHitAnimationFrames(), \"hitAnimFrames\", -1);\n\t\taddInteger(ss, itemRule->getHitMissAnimation(), \"hitMissAnimation\", -1);\n\t\taddInteger(ss, itemRule->getHitMissAnimationFrames(), \"hitMissAnimFrames\", -1);\n\t\taddInteger(ss, itemRule->getMeleeAnimation(), \"meleeAnimation\");\n\t\taddInteger(ss, itemRule->getMeleeAnimationFrames(), \"meleeAnimFrames\", -1);\n\t\taddInteger(ss, itemRule->getMeleeMissAnimation(), \"meleeMissAnimation\", -1);\n\t\taddInteger(ss, itemRule->getMeleeMissAnimationFrames(), \"meleeMissAnimFrames\", -1);\n\t\taddInteger(ss, itemRule->getPsiAnimation(), \"psiAnimation\", -1);\n\t\taddInteger(ss, itemRule->getPsiAnimationFrames(), \"psiAnimFrames\", -1);\n\t\taddInteger(ss, itemRule->getPsiMissAnimation(), \"psiMissAnimation\", -1);\n\t\taddInteger(ss, itemRule->getPsiMissAnimationFrames(), \"psiMissAnimFrames\", -1);\n\n\t\taddInteger(ss, itemRule->getBulletSpeed(), \"bulletSpeed\");\n\t\taddInteger(ss, itemRule->getExplosionSpeed(), \"explosionSpeed\");\n\n\t\taddInteger(ss, itemRule->getVaporColor(1), \"vaporColor\", -1);\n\t\taddInteger(ss, itemRule->getVaporDensity(1), \"vaporDensity\");\n\t\taddIntegerPercent(ss, itemRule->getVaporProbability(1), \"vaporProbability\", 15);\n\t\taddInteger(ss, itemRule->getVaporColor(0), \"vaporColorSurface\", -1);\n\t\taddInteger(ss, itemRule->getVaporDensity(0), \"vaporDensitySurface\");\n\t\taddIntegerPercent(ss, itemRule->getVaporProbability(0), \"vaporProbabilitySurface\", 15);\n\n\t\taddSection(\"{AI}\", \"\", _white);\n\t\taddInteger(ss, itemRule->getAttraction(), \"attraction\");\n\t\taddHeading(\"ai:\");\n\t\t{\n\t\t\tint useDelayCurrent = itemRule->getAIUseDelay(mod);\n\t\t\tint useDelayDefault = useDelayCurrent > 0 ? -1 : useDelayCurrent;\n\t\t\taddInteger(ss, useDelayCurrent, \"useDelay\", useDelayDefault); // not raw!\n\t\t\taddInteger(ss, itemRule->getAIMeleeHitCount(), \"meleeHitCount\", 25);\n\t\t\tendHeading();\n\t\t}\n\n\t\taddSection(\"{TU/flat info}\", \"\", _white);\n\t\taddRuleItemUseCostBasic(ss, itemRule->getCostAimed(), \"tuAimed\");\n\t\taddRuleItemUseCostBasic(ss, itemRule->getCostAuto(), \"tuAuto\");\n\t\taddRuleItemUseCostBasic(ss, itemRule->getCostSnap(), \"tuSnap\");\n\t\taddRuleItemUseCostBasic(ss, itemRule->getCostMelee(), \"tuMelee\");\n\t\ttuUseDefault = (itemBattleType == BT_PSIAMP/* && itemRule->getPsiAttackName().empty()*/) ? 0 : 25;\n\t\taddRuleItemUseCostBasic(ss, itemRule->getCostUse(), \"tuUse\", tuUseDefault);\n\t\tif (itemBattleType == BT_PSIAMP || _showDebug)\n\t\t{\n\t\t\t// always show! as if default was 0 instead of 25\n\t\t\taddRuleItemUseCostBasic(ss, itemRule->getCostMind(), \"tuMindcontrol\", 0);\n\t\t\taddRuleItemUseCostBasic(ss, itemRule->getCostPanic(), \"tuPanic\", 0);\n\t\t}\n\t\taddRuleItemUseCostBasic(ss, itemRule->getCostThrow(), \"tuThrow\", 25);\n\t\taddRuleItemUseCostBasic(ss, itemRule->getCostPrime(), \"tuPrime\", 50);\n\t\taddRuleItemUseCostBasic(ss, itemRule->getCostUnprime(), \"tuUnprime\", 25);\n\n\t\t// flatRate*\n\n\t\taddRuleItemUseCostFull(ss, itemRule->getFlatAimed(), \"flatAimed\", RuleItemUseFlat(0, 1));\n\t\taddRuleItemUseCostFull(ss, itemRule->getFlatAuto(), \"flatAuto\", RuleItemUseFlat(0, 1));\n\t\taddRuleItemUseCostFull(ss, itemRule->getFlatSnap(), \"flatSnap\", RuleItemUseFlat(0, 1));\n\t\taddRuleItemUseCostFull(ss, itemRule->getFlatMelee(), \"flatMelee\", RuleItemUseFlat(0, 1));\n\t\taddRuleItemUseCostFull(ss, itemRule->getFlatUse(), \"flatUse\", RuleItemUseFlat(0, 1));\n\t\taddRuleItemUseCostFull(ss, itemRule->getFlatThrow(), \"flatThrow\", RuleItemUseFlat(0, 1));\n\t\taddRuleItemUseCostFull(ss, itemRule->getFlatPrime(), \"flatPrime\", RuleItemUseFlat(0, 1));\n\t\taddRuleItemUseCostFull(ss, itemRule->getFlatUnprime(), \"flatUnprime\", RuleItemUseFlat(0, 1));\n\n\t\taddSection(\"{Script tags}\", \"\", _white, true);\n\t\t{\n\t\t\taddScriptTags(ss, itemRule->getScriptValuesRaw());\n\t\t\tendHeading();\n\t\t}\n\n\t\taddSection(\"{Mod info}\", \"\", _white);\n\t\t{\n\t\t\taddSingleString(ss, mod->getModCreatingRule(itemRule)->name, \"createdByMod\");\n\t\t\taddSingleString(ss, mod->getModLastUpdatingRule(itemRule)->name, \"updatedByMod\");\n\t\t\tendHeading();\n\t\t}\n\t}\n}\n\n/**\n * Adds a unit stat to the string stream, formatted with a label.\n */\nvoid StatsForNerdsState::addUnitStatFormatted(std::ostringstream &ss, const int &value, const std::string &label, bool &isFirst)\n{\n\tif (value != 0 || _showDefaults)\n\t{\n\t\tif (!isFirst) ss << \", \";\n\t\tss << tr(label) << \":\" << value;\n\t\tisFirst = false;\n\t}\n}\n\n/**\n * Adds a UnitStats info to the table.\n */\nvoid StatsForNerdsState::addUnitStatBonus(std::ostringstream &ss, const UnitStats &value, const std::string &propertyName)\n{\n\tbool isDefault = value.tu == 0 && value.stamina == 0 && value.health == 0 && value.strength == 0\n\t\t&& value.reactions == 0 && value.firing == 0 && value.melee == 0 && value.throwing == 0\n\t\t&& value.psiSkill == 0 && value.psiStrength == 0 && value.bravery == 0 && value.mana == 0;\n\tif (isDefault && !_showDefaults)\n\t{\n\t\treturn;\n\t}\n\tresetStream(ss);\n\tbool isFirst = true;\n\taddUnitStatFormatted(ss, value.tu, \"STR_TIME_UNITS_ABBREVIATION\", isFirst);\n\taddUnitStatFormatted(ss, value.stamina, \"STR_STAMINA_ABBREVIATION\", isFirst);\n\taddUnitStatFormatted(ss, value.health, \"STR_HEALTH_ABBREVIATION\", isFirst);\n\taddUnitStatFormatted(ss, value.strength, \"STR_STRENGTH_ABBREVIATION\", isFirst);\n\taddUnitStatFormatted(ss, value.reactions, \"STR_REACTIONS_ABBREVIATION\", isFirst);\n\taddUnitStatFormatted(ss, value.firing, \"STR_FIRING_ACCURACY_ABBREVIATION\", isFirst);\n\taddUnitStatFormatted(ss, value.melee, \"STR_MELEE_ACCURACY_ABBREVIATION\", isFirst);\n\taddUnitStatFormatted(ss, value.throwing, \"STR_THROWING_ACCURACY_ABBREVIATION\", isFirst);\n\taddUnitStatFormatted(ss, value.mana, \"STR_MANA_ABBREVIATION\", isFirst);\n\taddUnitStatFormatted(ss, value.psiStrength, \"STR_PSIONIC_STRENGTH_ABBREVIATION\", isFirst);\n\taddUnitStatFormatted(ss, value.psiSkill, \"STR_PSIONIC_SKILL_ABBREVIATION\", isFirst);\n\taddUnitStatFormatted(ss, value.bravery, \"STR_BRAVERY_ABBREVIATION\", isFirst);\n\t_lstRawData->addRow(2, trp(propertyName).c_str(), ss.str().c_str());\n\t++_counter;\n\tif (!isDefault)\n\t{\n\t\t_lstRawData->setCellColor(_lstRawData->getLastRowIndex(), 1, _pink);\n\t}\n}\n\n/**\n * Adds a vector of damage modifiers to the table.\n */\nvoid StatsForNerdsState::addArmorDamageModifiers(std::ostringstream &ss, const std::vector<float> &vec, const std::string &propertyName)\n{\n\tbool isDefault = true;\n\tfor (auto& item : vec)\n\t{\n\t\tif (!AreSame(item, 1.0f))\n\t\t{\n\t\t\tisDefault = false;\n\t\t}\n\t}\n\tif (isDefault && !_showDefaults)\n\t{\n\t\treturn;\n\t}\n\tresetStream(ss);\n\tint index = 0;\n\tbool isFirst = true;\n\tss << \"{\";\n\tfor (auto& item : vec)\n\t{\n\t\tif (!AreSame(item, 1.0f) || _showDefaults)\n\t\t{\n\t\t\tif (!isFirst)\n\t\t\t{\n\t\t\t\tss << \", \";\n\t\t\t}\n\t\t\tswitch (index)\n\t\t\t{\n\t\t\t\tcase 0: ss << tr(\"STR_DAMAGE_NONE\"); break;\n\t\t\t\tcase 1: ss << tr(\"STR_DAMAGE_ARMOR_PIERCING\"); break;\n\t\t\t\tcase 2: ss << tr(\"STR_DAMAGE_INCENDIARY\"); break;\n\t\t\t\tcase 3: ss << tr(\"STR_DAMAGE_HIGH_EXPLOSIVE\"); break;\n\t\t\t\tcase 4: ss << tr(\"STR_DAMAGE_LASER_BEAM\"); break;\n\t\t\t\tcase 5: ss << tr(\"STR_DAMAGE_PLASMA_BEAM\"); break;\n\t\t\t\tcase 6: ss << tr(\"STR_DAMAGE_STUN\"); break;\n\t\t\t\tcase 7: ss << tr(\"STR_DAMAGE_MELEE\"); break;\n\t\t\t\tcase 8: ss << tr(\"STR_DAMAGE_ACID\"); break;\n\t\t\t\tcase 9: ss << tr(\"STR_DAMAGE_SMOKE\"); break;\n\t\t\t\tcase 10: ss << tr(\"STR_DAMAGE_10\"); break;\n\t\t\t\tcase 11: ss << tr(\"STR_DAMAGE_11\"); break;\n\t\t\t\tcase 12: ss << tr(\"STR_DAMAGE_12\"); break;\n\t\t\t\tcase 13: ss << tr(\"STR_DAMAGE_13\"); break;\n\t\t\t\tcase 14: ss << tr(\"STR_DAMAGE_14\"); break;\n\t\t\t\tcase 15: ss << tr(\"STR_DAMAGE_15\"); break;\n\t\t\t\tcase 16: ss << tr(\"STR_DAMAGE_16\"); break;\n\t\t\t\tcase 17: ss << tr(\"STR_DAMAGE_17\"); break;\n\t\t\t\tcase 18: ss << tr(\"STR_DAMAGE_18\"); break;\n\t\t\t\tcase 19: ss << tr(\"STR_DAMAGE_19\"); break;\n\t\t\t\tdefault: ss << tr(\"STR_UNKNOWN\"); break;\n\t\t\t}\n\t\t\tss << \": \" << item * 100 << \"%\";\n\t\t\tisFirst = false;\n\t\t}\n\t\tindex++;\n\t}\n\tss << \"}\";\n\t_lstRawData->addRow(2, trp(propertyName).c_str(), ss.str().c_str());\n\t++_counter;\n\tif (!isDefault)\n\t{\n\t\t_lstRawData->setCellColor(_lstRawData->getLastRowIndex(), 1, _pink);\n\t}\n}\n\n/**\n * Adds a SpecialAbility to the table.\n */\nvoid StatsForNerdsState::addSpecialAbility(std::ostringstream &ss, const SpecialAbility &value, const std::string &propertyName, const SpecialAbility &defaultvalue)\n{\n\tif (value == defaultvalue && !_showDefaults)\n\t{\n\t\treturn;\n\t}\n\tresetStream(ss);\n\tswitch (value)\n\t{\n\tcase SPECAB_NONE: ss << tr(\"SPECAB_NONE\"); break;\n\tcase SPECAB_EXPLODEONDEATH: ss << tr(\"SPECAB_EXPLODEONDEATH\"); break;\n\tcase SPECAB_BURNFLOOR: ss << tr(\"SPECAB_BURNFLOOR\"); break;\n\tcase SPECAB_BURN_AND_EXPLODE: ss << tr(\"SPECAB_BURN_AND_EXPLODE\"); break;\n\tdefault: ss << tr(\"STR_UNKNOWN\"); break;\n\t}\n\tif (_showIds)\n\t{\n\t\tss << \" [\" << value << \"]\";\n\t}\n\t_lstRawData->addRow(2, trp(propertyName).c_str(), ss.str().c_str());\n\t++_counter;\n\tif (value != defaultvalue)\n\t{\n\t\t_lstRawData->setCellColor(_lstRawData->getLastRowIndex(), 1, _pink);\n\t}\n}\n\n/**\n * Adds a MovementType to the table.\n */\nvoid StatsForNerdsState::addMovementType(std::ostringstream &ss, const MovementType &value, const std::string &propertyName, const MovementType &defaultvalue)\n{\n\tif (value == defaultvalue && !_showDefaults)\n\t{\n\t\treturn;\n\t}\n\tresetStream(ss);\n\tswitch (value)\n\t{\n\t\tcase MT_WALK: ss << tr(\"MT_WALK\"); break;\n\t\tcase MT_FLY: ss << tr(\"MT_FLY\"); break;\n\t\tcase MT_SLIDE: ss << tr(\"MT_SLIDE\"); break;\n\t\tcase MT_FLOAT: ss << tr(\"MT_FLOAT\"); break;\n\t\tcase MT_SINK: ss << tr(\"MT_SINK\"); break;\n\t\tdefault: ss << tr(\"STR_UNKNOWN\"); break;\n\t}\n\tif (_showIds)\n\t{\n\t\tss << \" [\" << value << \"]\";\n\t}\n\t_lstRawData->addRow(2, trp(propertyName).c_str(), ss.str().c_str());\n\t++_counter;\n\tif (value != defaultvalue)\n\t{\n\t\t_lstRawData->setCellColor(_lstRawData->getLastRowIndex(), 1, _pink);\n\t}\n}\n\n/**\n * Adds a ForcedTorso to the table.\n */\nvoid StatsForNerdsState::addForcedTorso(std::ostringstream &ss, const ForcedTorso &value, const std::string &propertyName, const ForcedTorso &defaultvalue)\n{\n\tif (value == defaultvalue && !_showDefaults)\n\t{\n\t\treturn;\n\t}\n\tresetStream(ss);\n\tswitch (value)\n\t{\n\t\tcase TORSO_USE_GENDER: ss << tr(\"TORSO_USE_GENDER\"); break;\n\t\tcase TORSO_ALWAYS_MALE: ss << tr(\"TORSO_ALWAYS_MALE\"); break;\n\t\tcase TORSO_ALWAYS_FEMALE: ss << tr(\"TORSO_ALWAYS_FEMALE\"); break;\n\t\tdefault: ss << tr(\"STR_UNKNOWN\"); break;\n\t}\n\tif (_showIds)\n\t{\n\t\tss << \" [\" << (int)value << \"]\";\n\t}\n\t_lstRawData->addRow(2, trp(propertyName).c_str(), ss.str().c_str());\n\t++_counter;\n\tif (value != defaultvalue)\n\t{\n\t\t_lstRawData->setCellColor(_lstRawData->getLastRowIndex(), 1, _pink);\n\t}\n}\n\n/**\n * Adds a DrawingRoutine to the table.\n */\nvoid StatsForNerdsState::addDrawingRoutine(std::ostringstream &ss, const int &value, const std::string &propertyName, const int &defaultvalue)\n{\n\tif (value == defaultvalue && !_showDefaults)\n\t{\n\t\treturn;\n\t}\n\tresetStream(ss);\n\tswitch (value)\n\t{\n\t\tcase 0: ss << tr(\"DRAWING_ROUTINE_SOLDIER_SECTOID\"); break;\n\t\tcase 1: ss << tr(\"DRAWING_ROUTINE_FLOATER\"); break;\n\t\tcase 2: ss << tr(\"DRAWING_ROUTINE_HWP\"); break;\n\t\tcase 3: ss << tr(\"DRAWING_ROUTINE_CYBERDISC\"); break;\n\t\tcase 4: ss << tr(\"DRAWING_ROUTINE_CIVILIAN_ETHEREAL\"); break;\n\t\tcase 5: ss << tr(\"DRAWING_ROUTINE_SECTOPOD_REAPER\"); break;\n\t\tcase 6: ss << tr(\"DRAWING_ROUTINE_SNAKEMAN\"); break;\n\t\tcase 7: ss << tr(\"DRAWING_ROUTINE_CHRYSSALID\"); break;\n\t\tcase 8: ss << tr(\"DRAWING_ROUTINE_SILACOID\"); break;\n\t\tcase 9: ss << tr(\"DRAWING_ROUTINE_CELATID\"); break;\n\t\tcase 10: ss << tr(\"DRAWING_ROUTINE_MUTON\"); break;\n\t\tcase 11: ss << tr(\"DRAWING_ROUTINE_SWS\"); break;\n\t\tcase 12: ss << tr(\"DRAWING_ROUTINE_HALLUCINOID\"); break;\n\t\tcase 13: ss << tr(\"DRAWING_ROUTINE_AQUANAUTS\"); break;\n\t\tcase 14: ss << tr(\"DRAWING_ROUTINE_CALCINITE_AND_MORE\"); break;\n\t\tcase 15: ss << tr(\"DRAWING_ROUTINE_AQUATOID\"); break;\n\t\tcase 16: ss << tr(\"DRAWING_ROUTINE_BIO_DRONE\"); break;\n\t\tcase 17: ss << tr(\"DRAWING_ROUTINE_TFTD_CIVILIAN_A\"); break;\n\t\tcase 18: ss << tr(\"DRAWING_ROUTINE_TFTD_CIVILIAN_B\"); break;\n\t\tcase 19: ss << tr(\"DRAWING_ROUTINE_TENTACULAT\"); break;\n\t\tcase 20: ss << tr(\"DRAWING_ROUTINE_TRISCENE\"); break;\n\t\tcase 21: ss << tr(\"DRAWING_ROUTINE_XARQUID\"); break;\n\t\tcase 22: ss << tr(\"DRAWING_ROUTINE_INVERTED_CYBERDISC\"); break;\n\t\tdefault: ss << tr(\"STR_UNKNOWN\"); break;\n\t}\n\tif (_showIds)\n\t{\n\t\tss << \" [\" << value << \"]\";\n\t}\n\t_lstRawData->addRow(2, trp(propertyName).c_str(), ss.str().c_str());\n\t++_counter;\n\tif (value != defaultvalue)\n\t{\n\t\t_lstRawData->setCellColor(_lstRawData->getLastRowIndex(), 1, _pink);\n\t}\n}\n\n/**\n * Shows the \"raw\" (Rule)Armor data.\n */\nvoid StatsForNerdsState::initArmorList()\n{\n\t_lstRawData->clearList();\n\t_lstRawData->setIgnoreSeparators(true);\n\n\tstd::ostringstream ssTopic;\n\tssTopic << tr(_topicId);\n\tif (_showIds)\n\t{\n\t\tssTopic << \" [\" << _topicId << \"]\";\n\t}\n\n\t_txtArticle->setText(tr(\"STR_ARTICLE\").arg(ssTopic.str()));\n\n\tMod *mod = _game->getMod();\n\tArmor *armorRule = mod->getArmor(_topicId);\n\tif (!armorRule)\n\t\treturn;\n\n\t_filterOptions.clear();\n\t_cbxRelatedStuff->setVisible(false);\n\n\tstd::ostringstream ss;\n\n\taddUnitStatBonus(ss, *armorRule->getStats(), \"stats\");\n\n\taddInteger(ss, armorRule->getWeight(), \"weight\");\n\n\taddInteger(ss, armorRule->getSize(), \"size\", 1);\n\n\taddSpecialAbility(ss, (SpecialAbility)armorRule->getSpecialAbility(), \"specab\");\n\taddMovementType(ss, armorRule->getMovementType(), \"movementType\");\n\n\taddBoolean(ss, armorRule->allowsRunning(), \"allowsRunning\", true);\n\taddBoolean(ss, armorRule->allowsStrafing(), \"allowsStrafing\", true);\n\taddBoolean(ss, armorRule->allowsSneaking(), \"allowsSneaking\", true);\n\taddBoolean(ss, armorRule->allowsKneeling(), \"allowsKneeling\", true);\n\taddBoolean(ss, armorRule->allowsMoving(), \"allowsMoving\", true);\n\n\tbool fearImmuneDefault = false;\n\tbool bleedImmuneDefault = false;\n\tbool painImmuneDefault = false;\n\tbool zombiImmuneDefault = false;\n\tbool ignoresMeleeThreatDefault = false;\n\tbool createsMeleeThreatDefault = true;\n\n\tif (armorRule->getSize() != 1)\n\t{\n\t\tfearImmuneDefault = true;\n\t\tbleedImmuneDefault = true;\n\t\tpainImmuneDefault = true;\n\t\tzombiImmuneDefault = true;\n\t\tignoresMeleeThreatDefault = true;\n\t\tcreatesMeleeThreatDefault = false;\n\t}\n\n\taddBoolean(ss, armorRule->getFearImmune(), \"fearImmune\", fearImmuneDefault);\n\taddBoolean(ss, armorRule->getBleedImmune(), \"bleedImmune\", bleedImmuneDefault); // not considering alienBleeding option!\n\taddBoolean(ss, armorRule->getPainImmune(), \"painImmune\", painImmuneDefault);\n\taddBoolean(ss, armorRule->getZombiImmune(), \"zombiImmune\", zombiImmuneDefault);\n\taddBoolean(ss, armorRule->getIgnoresMeleeThreat(), \"ignoresMeleeThreat\", ignoresMeleeThreatDefault);\n\taddBoolean(ss, armorRule->getCreatesMeleeThreat(), \"createsMeleeThreat\", createsMeleeThreatDefault);\n\n\t_filterOptions.clear();\n\tfor (auto* biw : armorRule->getBuiltInWeapons())\n\t{\n\t\t// ignore dummy inventory padding\n\t\tif (biw->getType().find(\"INV_NULL\") == std::string::npos || _showDebug)\n\t\t{\n\t\t\t_filterOptions.push_back(biw->getType());\n\t\t}\n\t}\n\taddVectorOfStrings(ss, _filterOptions, \"builtInWeapons\");\n\taddRule(ss, armorRule->getSpecialWeapon(), \"specialWeapon\");\n\n\tif (armorRule->getSpecialWeapon())\n\t{\n\t\t_filterOptions.push_back(armorRule->getSpecialWeapon()->getType());\n\t}\n\n\t_filterOptions.insert(_filterOptions.begin(), \"STR_BUILT_IN_ITEMS\");\n\t_cbxRelatedStuff->setOptions(_filterOptions, true);\n\t_cbxRelatedStuff->setVisible(_filterOptions.size() > 1);\n\tif (_filterOptions.size() > 1)\n\t{\n\t\t_txtTitle->setAlign(ALIGN_LEFT);\n\t}\n\n\taddIntegerPercent(ss, armorRule->getVisibilityThroughSmoke(), \"heatVision\"); // visibilityThroughSmoke\n\taddIntegerPercent(ss, armorRule->getVisibilityThroughFire(), \"visibilityThroughFire\", 100);\n\taddInteger(ss, armorRule->getPsiVision(), \"psiVision\");\n\taddInteger(ss, armorRule->getPsiCamouflage(), \"psiCamouflage\");\n\n\taddInteger(ss, armorRule->getVisibilityAtDay(), \"visibilityAtDay\");\n\taddInteger(ss, armorRule->getVisibilityAtDark(), \"visibilityAtDark\");\n\taddInteger(ss, armorRule->getCamouflageAtDay(), \"camouflageAtDay\");\n\taddInteger(ss, armorRule->getCamouflageAtDark(), \"camouflageAtDark\");\n\taddInteger(ss, armorRule->getAntiCamouflageAtDay(), \"antiCamouflageAtDay\");\n\taddInteger(ss, armorRule->getAntiCamouflageAtDark(), \"antiCamouflageAtDark\");\n\n\taddRuleStatBonus(ss, *armorRule->getPsiDefenceRaw(), \"psiDefence\");\n\taddRuleStatBonus(ss, *armorRule->getMeleeDodgeRaw(), \"meleeDodge\");\n\taddFloatAsPercentage(ss, armorRule->getMeleeDodgeBackPenalty(), \"meleeDodgeBackPenalty\");\n\n\taddHeading(\"recovery\");\n\t{\n\t\taddRuleStatBonus(ss, *armorRule->getTimeRecoveryRaw(), \"time\");\n\t\taddRuleStatBonus(ss, *armorRule->getEnergyRecoveryRaw(), \"energy\");\n\t\taddRuleStatBonus(ss, *armorRule->getMoraleRecoveryRaw(), \"morale\");\n\t\taddRuleStatBonus(ss, *armorRule->getHealthRecoveryRaw(), \"health\");\n\t\taddRuleStatBonus(ss, *armorRule->getStunRegenerationRaw(), \"stun\");\n\t\taddRuleStatBonus(ss, *armorRule->getManaRecoveryRaw(), \"mana\");\n\t\tendHeading();\n\t}\n\n\taddVectorOfRules(ss, armorRule->getUnitsRaw(), \"units\");\n\taddVectorOfIntegers(ss, armorRule->getRanksRaw(), \"ranks\");\n\taddRule(ss, armorRule->getRequiredAward(), \"requiresAward\");\n\taddRuleNamed(ss, armorRule->getRequiredBonus(), \"requiresBonus\");\n\n\tModScript::scriptCallback<ModScript::StatsForNerdsArmor>(armorRule, armorRule, this, _game->getSavedGame());\n\n\tif (_showDebug)\n\t{\n\t\taddSection(\"{Modding section}\", \"You don't need this info as a player\", _white, true);\n\n\t\taddSection(\"{Naming}\", \"\", _white);\n\t\taddSingleString(ss, armorRule->getType(), \"type\");\n\t\taddSingleString(ss, armorRule->getUfopediaType(), \"ufopediaType\");\n\t\taddInteger(ss, armorRule->getGroup(), \"group\");\n\t\taddInteger(ss, armorRule->getListOrder(), \"listOrder\");\n\t\taddRuleNamed(ss, armorRule->getRequiredResearch(), \"requires\");\n\n\t\taddSection(\"{Recovery}\", \"\", _white);\n\t\taddVectorOfRules(ss, armorRule->getCorpseBattlescape(), \"corpseBattle\");\n\t\taddRule(ss, armorRule->getCorpseGeoscape(), \"corpseGeo\");\n\t\taddRule(ss, armorRule->getSelfDestructItem(), \"selfDestructItem\");\n\t\taddRule(ss, armorRule->getStoreItem(), \"storeItem\");\n\n\t\taddSection(\"{Inventory}\", \"\", _white);\n\t\taddSingleString(ss, armorRule->getSpriteInventory(), \"spriteInv\", \"\", false);\n\t\taddBoolean(ss, armorRule->hasInventory(), \"allowInv\", true);\n\t\taddSingleString(ss, armorRule->getLayersDefaultPrefix(), \"layersDefaultPrefix\", \"\", false);\n\t\taddBoolean(ss, !armorRule->getLayersSpecificPrefix().empty(), \"layersSpecificPrefix*\", false); // just say if there are any or not\n\t\taddBoolean(ss, !armorRule->getLayersDefinition().empty(), \"layersDefinition*\", false); // just say if there are any or not\n\n\t\taddSection(\"{Sprites}\", \"\", _white);\n\t\taddVectorOfIntegers(ss, armorRule->getCustomArmorPreviewIndex(), \"customArmorPreviewIndex\");\n\t\taddSingleString(ss, armorRule->getSpriteSheet(), \"spriteSheet\", \"\", false);\n\t\taddInteger(ss, armorRule->getFaceColorGroup(), \"spriteFaceGroup\");\n\t\taddVectorOfIntegers(ss, armorRule->getFaceColorRaw(), \"spriteFaceColor\");\n\t\taddInteger(ss, armorRule->getHairColorGroup(), \"spriteHairGroup\");\n\t\taddVectorOfIntegers(ss, armorRule->getHairColorRaw(), \"spriteHairColor\");\n\t\taddInteger(ss, armorRule->getUtileColorGroup(), \"spriteUtileGroup\");\n\t\taddVectorOfIntegers(ss, armorRule->getUtileColorRaw(), \"spriteUtileColor\");\n\t\taddInteger(ss, armorRule->getRankColorGroup(), \"spriteRankGroup\");\n\t\taddVectorOfIntegers(ss, armorRule->getRankColorRaw(), \"spriteRankColor\");\n\n\t\taddSection(\"{Sounds}\", \"\", _white);\n\t\taddInteger(ss, armorRule->getMoveSound(), \"moveSound\", -1);\n\t\tstd::vector<int> tmpSoundVector;\n\t\ttmpSoundVector.push_back(armorRule->getMoveSound());\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", tmpSoundVector);\n\t\taddVectorOfIntegers(ss, armorRule->getMaleDeathSounds(), \"deathMale\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", armorRule->getMaleDeathSounds());\n\t\taddVectorOfIntegers(ss, armorRule->getFemaleDeathSounds(), \"deathFemale\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", armorRule->getFemaleDeathSounds());\n\t\taddVectorOfIntegers(ss, armorRule->getMaleSelectUnitSounds(), \"selectUnitMale\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", armorRule->getMaleSelectUnitSounds());\n\t\taddVectorOfIntegers(ss, armorRule->getFemaleSelectUnitSounds(), \"selectUnitFemale\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", armorRule->getFemaleSelectUnitSounds());\n\t\taddVectorOfIntegers(ss, armorRule->getMaleStartMovingSounds(), \"startMovingMale\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", armorRule->getMaleStartMovingSounds());\n\t\taddVectorOfIntegers(ss, armorRule->getFemaleStartMovingSounds(), \"startMovingFemale\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", armorRule->getFemaleStartMovingSounds());\n\t\taddVectorOfIntegers(ss, armorRule->getMaleSelectWeaponSounds(), \"selectWeaponMale\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", armorRule->getMaleSelectWeaponSounds());\n\t\taddVectorOfIntegers(ss, armorRule->getFemaleSelectWeaponSounds(), \"selectWeaponFemale\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", armorRule->getFemaleSelectWeaponSounds());\n\t\taddVectorOfIntegers(ss, armorRule->getMaleAnnoyedSounds(), \"annoyedMale\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", armorRule->getMaleAnnoyedSounds());\n\t\taddVectorOfIntegers(ss, armorRule->getFemaleAnnoyedSounds(), \"annoyedFemale\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", armorRule->getFemaleAnnoyedSounds());\n\n\t\taddSection(\"{Animations}\", \"\", _white);\n\t\taddDrawingRoutine(ss, armorRule->getDrawingRoutine(), \"drawingRoutine\");\n\t\taddBoolean(ss, armorRule->drawBubbles(), \"drawBubbles\");\n\t\taddBoolean(ss, armorRule->getConstantAnimation(), \"constantAnimation\");\n\t\taddForcedTorso(ss, armorRule->getForcedTorso(), \"forcedTorso\");\n\t\taddInteger(ss, armorRule->getDeathFrames(), \"deathFrames\", 3);\n\n\t\taddSection(\"{Calculations}\", \"\", _white);\n\t\taddVectorOfIntegers(ss, armorRule->getLoftempsSet(), \"loftempsSet\");\n\t\taddInteger(ss, armorRule->getPersonalLightFriend(), \"personalLight\", 15);\n\t\taddInteger(ss, armorRule->getPersonalLightHostile(), \"personalLightHostile\", 0);\n\t\taddInteger(ss, armorRule->getPersonalLightNeutral(), \"personalLightNeutral\", 0);\n\t\taddInteger(ss, armorRule->getStandHeight(), \"standHeight\", -1);\n\t\taddInteger(ss, armorRule->getKneelHeight(), \"kneelHeight\", -1);\n\t\taddInteger(ss, armorRule->getFloatHeight(), \"floatHeight\", -1);\n\t\taddInteger(ss, armorRule->getMeleeOriginVoxelVerticalOffset(), \"meleeOriginVoxelVerticalOffset\");\n\t\taddFloat(ss, armorRule->getOverKill(), \"overKill\", 0.5f);\n\t\taddBoolean(ss, armorRule->isPilotArmor(), \"isPilotArmor\");\n\t\taddBoolean(ss, armorRule->getAllowTwoMainWeapons(), \"allowTwoMainWeapons\");\n\t\taddBoolean(ss, armorRule->getInstantWoundRecovery(), \"instantWoundRecovery\");\n\n\t\taddHeading(\"moveCost\");\n\t\t{\n\t\t\taddRuleArmorMoveCost(ss, armorRule->getMoveCostBase(), \"basePercent\", { 100, 100 });\n\t\t\taddRuleArmorMoveCost(ss, armorRule->getMoveCostBaseFly(), \"baseFlyPercent\", { 100, 100 });\n\t\t\taddRuleArmorMoveCost(ss, armorRule->getMoveCostBaseClimb(), \"baseClimbPercent\", { 100, 100 });\n\t\t\taddRuleArmorMoveCost(ss, armorRule->getMoveCostBaseNormal(), \"baseNormalPercent\", { 100, 100 });\n\n\t\t\taddRuleArmorMoveCost(ss, armorRule->getMoveCostWalk(), \"walkPercent\", { 100, 50 });\n\t\t\taddRuleArmorMoveCost(ss, armorRule->getMoveCostRun(), \"runPercent\", { 75, 75 });\n\t\t\taddRuleArmorMoveCost(ss, armorRule->getMoveCostStrafe(), \"strafePercent\", { 100, 50 });\n\t\t\taddRuleArmorMoveCost(ss, armorRule->getMoveCostSneak(), \"sneakPercent\", { 100, 50 });\n\n\t\t\taddRuleArmorMoveCost(ss, armorRule->getMoveCostFlyWalk(), \"flyWalkPercent\", { 100, 50 });\n\t\t\taddRuleArmorMoveCost(ss, armorRule->getMoveCostFlyRun(), \"flyRunPercent\", { 75, 75 });\n\t\t\taddRuleArmorMoveCost(ss, armorRule->getMoveCostFlyStrafe(), \"flyStrafePercent\", { 100, 50 });\n\n\t\t\taddRuleArmorMoveCost(ss, armorRule->getMoveCostFlyUp(), \"flyUpPercent\", { 100, 0 });\n\t\t\taddRuleArmorMoveCost(ss, armorRule->getMoveCostFlyDown(), \"flyDownPercent\", { 100, 0 });\n\n\t\t\taddRuleArmorMoveCost(ss, armorRule->getMoveCostClimbUp(), \"climbUpPercent\", { 100, 50 });\n\t\t\taddRuleArmorMoveCost(ss, armorRule->getMoveCostClimbDown(), \"climbDownPercent\", { 100, 50 });\n\n\t\t\taddRuleArmorMoveCost(ss, armorRule->getMoveCostGravLift(), \"gravLiftPercent\", { 100, 0 });\n\n\t\t\tendHeading();\n\t\t}\n\n\t\taddSection(\"{Basics}\", \"Stuff from the main article\", _white, true);\n\t\taddInteger(ss, armorRule->getFrontArmor(), \"frontArmor\");\n\t\taddInteger(ss, armorRule->getRightSideArmor(), \"sideArmor\");\n\t\taddInteger(ss, armorRule->getLeftSideArmor() - armorRule->getRightSideArmor(), \"leftArmorDiff\");\n\t\taddInteger(ss, armorRule->getRearArmor(), \"rearArmor\");\n\t\taddInteger(ss, armorRule->getUnderArmor(), \"underArmor\");\n\n\t\taddArmorDamageModifiers(ss, armorRule->getDamageModifiersRaw(), \"damageModifier\");\n\n\t\taddSection(\"{Script tags}\", \"\", _white, true);\n\t\t{\n\t\t\taddScriptTags(ss, armorRule->getScriptValuesRaw());\n\t\t\tendHeading();\n\t\t}\n\n\t\taddSection(\"{Mod info}\", \"\", _white);\n\t\t{\n\t\t\taddSingleString(ss, mod->getModCreatingRule(armorRule)->name, \"createdByMod\");\n\t\t\taddSingleString(ss, mod->getModLastUpdatingRule(armorRule)->name, \"updatedByMod\");\n\t\t\tendHeading();\n\t\t}\n\t}\n}\n\n/**\n * Shows the \"raw\" RuleSoldierBonus data.\n */\nvoid StatsForNerdsState::initSoldierBonusList()\n{\n\t_lstRawData->clearList();\n\t_lstRawData->setIgnoreSeparators(true);\n\n\tstd::ostringstream ssTopic;\n\tssTopic << tr(_topicId);\n\tif (_showIds)\n\t{\n\t\tssTopic << \" [\" << _topicId << \"]\";\n\t}\n\n\t_txtArticle->setText(tr(\"STR_ARTICLE\").arg(ssTopic.str()));\n\n\tMod *mod = _game->getMod();\n\tRuleSoldierBonus *bonusRule = mod->getSoldierBonus(_topicId);\n\tif (!bonusRule)\n\t\treturn;\n\n\t_filterOptions.clear();\n\t_cbxRelatedStuff->setVisible(false);\n\n\tstd::ostringstream ss;\n\n\taddUnitStatBonus(ss, *bonusRule->getStats(), \"stats\");\n\n\taddInteger(ss, bonusRule->getFrontArmor(), \"frontArmor\");\n\taddInteger(ss, bonusRule->getRightSideArmor(), \"sideArmor\");\n\taddInteger(ss, bonusRule->getLeftSideArmor() - bonusRule->getRightSideArmor(), \"leftArmorDiff\");\n\taddInteger(ss, bonusRule->getRearArmor(), \"rearArmor\");\n\taddInteger(ss, bonusRule->getUnderArmor(), \"underArmor\");\n\n\taddInteger(ss, bonusRule->getVisibilityAtDark(), \"visibilityAtDark\");\n\taddInteger(ss, bonusRule->getVisibilityAtDay(), \"visibilityAtDay\");\n\taddInteger(ss, bonusRule->getPsiVision(), \"psiVision\");\n\taddInteger(ss, bonusRule->getVisibilityThroughSmoke(), \"heatVision\"); // visibilityThroughSmoke\n\taddInteger(ss, bonusRule->getVisibilityThroughFire(), \"visibilityThroughFire\", 0);\n\n\taddHeading(\"recovery\");\n\t{\n\t\taddRuleStatBonus(ss, *bonusRule->getTimeRecoveryRaw(), \"time\");\n\t\taddRuleStatBonus(ss, *bonusRule->getEnergyRecoveryRaw(), \"energy\");\n\t\taddRuleStatBonus(ss, *bonusRule->getMoraleRecoveryRaw(), \"morale\");\n\t\taddRuleStatBonus(ss, *bonusRule->getHealthRecoveryRaw(), \"health\");\n\t\taddRuleStatBonus(ss, *bonusRule->getStunRegenerationRaw(), \"stun\");\n\t\taddRuleStatBonus(ss, *bonusRule->getManaRecoveryRaw(), \"mana\");\n\t\tendHeading();\n\t}\n\n\tif (_showDebug)\n\t{\n\t\taddSection(\"{Script tags}\", \"\", _white, true);\n\t\t{\n\t\t\taddScriptTags(ss, bonusRule->getScriptValuesRaw());\n\t\t\tendHeading();\n\t\t}\n\n\t\taddSection(\"{Mod info}\", \"\", _white);\n\t\t{\n\t\t\taddSingleString(ss, mod->getModCreatingRule(bonusRule)->name, \"createdByMod\");\n\t\t\taddSingleString(ss, mod->getModLastUpdatingRule(bonusRule)->name, \"updatedByMod\");\n\t\t\tendHeading();\n\t\t}\n\t}\n}\n\n/**\n * Adds a vector of Positions to the table.\n */\nvoid StatsForNerdsState::addVectorOfPositions(std::ostringstream &ss, const std::vector<Position> &vec, const std::string &propertyName)\n{\n\tif (vec.empty() && !_showDefaults)\n\t{\n\t\treturn;\n\t}\n\tresetStream(ss);\n\tint i = 0;\n\tss << \"{\";\n\tfor (auto& item : vec)\n\t{\n\t\tif (i > 0)\n\t\t{\n\t\t\tss << \", \";\n\t\t}\n\t\tss << \"(\" << item.x << \",\" << item.y << \",\" << item.z << \")\";\n\t\ti++;\n\t}\n\tss << \"}\";\n\t_lstRawData->addRow(2, trp(propertyName).c_str(), ss.str().c_str());\n\t++_counter;\n\tif (!vec.empty())\n\t{\n\t\t_lstRawData->setCellColor(_lstRawData->getLastRowIndex(), 1, _pink);\n\t}\n}\n\n/**\n * Adds a build cost item to the table.\n */\nvoid StatsForNerdsState::addBuildCostItem(std::ostringstream &ss, const std::pair<const std::string, std::pair<int, int> > &costItem)\n{\n\tresetStream(ss);\n\taddTranslation(ss, costItem.first);\n\tss << \": \" << tr(\"STR_COST_BUILD\") << \": \";\n\tss << costItem.second.first;\n\tss << \", \" << tr(\"STR_COST_REFUND\") << \": \";\n\tss << costItem.second.second;\n\t_lstRawData->addRow(2, \"\", ss.str().c_str());\n\t++_counter;\n\t_lstRawData->setCellColor(_lstRawData->getLastRowIndex(), 1, _pink);\n}\n\n/**\n * Adds a human readable form of base facility right-click action type to the table.\n */\nvoid StatsForNerdsState::addRightClickActionType(std::ostringstream &ss, const int &value, const std::string &propertyName, const int &defaultvalue)\n{\n\tif (value == defaultvalue && !_showDefaults)\n\t{\n\t\treturn;\n\t}\n\tresetStream(ss);\n\tswitch (value)\n\t{\n\tcase 0: ss << tr(\"BFRCT_DEFAULT\"); break;\n\tcase 1: ss << tr(\"BFRCT_PRISON\"); break;\n\tcase 2: ss << tr(\"BFRCT_ENGINEERING\"); break;\n\tcase 3: ss << tr(\"BFRCT_RESEARCH\"); break;\n\tcase 4: ss << tr(\"BFRCT_GYM\"); break;\n\tcase 5: ss << tr(\"BFRCT_PSI_LABS\"); break;\n\tcase 6: ss << tr(\"BFRCT_BARRACKS\"); break;\n\tcase 7: ss << tr(\"BFRCT_GREY_MARKET\"); break;\n\tdefault: ss << tr(\"BFRCT_GEOSCAPE\"); break;\n\t}\n\tif (_showIds)\n\t{\n\t\tss << \" [\" << value << \"]\";\n\t}\n\t_lstRawData->addRow(2, trp(propertyName).c_str(), ss.str().c_str());\n\t++_counter;\n\tif (value != defaultvalue)\n\t{\n\t\t_lstRawData->setCellColor(_lstRawData->getLastRowIndex(), 1, _pink);\n\t}\n}\n\n/**\n * Shows the \"raw\" RuleBaseFacility data.\n */\nvoid StatsForNerdsState::initFacilityList()\n{\n\t_lstRawData->clearList();\n\t_lstRawData->setIgnoreSeparators(true);\n\n\tstd::ostringstream ssTopic;\n\tssTopic << tr(_topicId);\n\tif (_showIds)\n\t{\n\t\tssTopic << \" [\" << _topicId << \"]\";\n\t}\n\n\t_txtArticle->setText(tr(\"STR_ARTICLE\").arg(ssTopic.str()));\n\n\tMod *mod = _game->getMod();\n\tRuleBaseFacility *facilityRule = mod->getBaseFacility(_topicId);\n\tif (!facilityRule)\n\t\treturn;\n\n\t_filterOptions.clear();\n\t_cbxRelatedStuff->setVisible(false);\n\n\tstd::ostringstream ss;\n\n\taddVectorOfStrings(ss, facilityRule->getRequirements(), \"requires\");\n\n\tif (facilityRule->getSizeX() == facilityRule->getSizeY())\n\t{\n\t\taddInteger(ss, facilityRule->getSizeX(), \"size\", 1);\n\t}\n\telse\n\t{\n\t\taddInteger(ss, facilityRule->getSizeX(), \"sizeX\", 0);\n\t\taddInteger(ss, facilityRule->getSizeY(), \"sizeY\", 0);\n\t}\n\taddInteger(ss, facilityRule->getBuildCost(), \"buildCost\", 0, true);\n\taddHeading(\"buildCostItems\");\n\t{\n\t\tfor (auto& costItem : facilityRule->getBuildCostItems())\n\t\t{\n\t\t\taddBuildCostItem(ss, costItem);\n\t\t}\n\t\tendHeading();\n\t}\n\taddInteger(ss, facilityRule->getBuildTime(), \"buildTime\");\n\taddInteger(ss, facilityRule->getMonthlyCost(), \"monthlyCost\", 0, true);\n\taddInteger(ss, facilityRule->getRefundValue(), \"refundValue\", 0, true);\n\n\taddVectorOfStrings(ss, mod->getBaseFunctionNames(facilityRule->getRequireBaseFunc()), \"requiresBaseFunc\");\n\taddVectorOfStrings(ss, mod->getBaseFunctionNames(facilityRule->getProvidedBaseFunc()), \"provideBaseFunc\");\n\taddVectorOfStrings(ss, mod->getBaseFunctionNames(facilityRule->getForbiddenBaseFunc()), \"forbiddenBaseFunc\");\n\n\taddBoolean(ss, facilityRule->isLift(), \"lift\");\n\taddBoolean(ss, facilityRule->isHyperwave(), \"hyper\");\n\taddBoolean(ss, facilityRule->isMindShield(), \"mind\");\n\taddInteger(ss, facilityRule->getMindShieldPower(), \"mindPower\", 1);\n\taddBoolean(ss, facilityRule->isGravShield(), \"grav\");\n\n\taddInteger(ss, facilityRule->getStorage(), \"storage\");\n\taddInteger(ss, facilityRule->getPersonnel(), \"personnel\");\n\taddInteger(ss, facilityRule->getAliens(), \"aliens\");\n\taddInteger(ss, facilityRule->getPrisonType(), \"prisonType\");\n\taddInteger(ss, facilityRule->getCrafts(), \"crafts\");\n\taddInteger(ss, facilityRule->getLaboratories(), \"labs\");\n\taddInteger(ss, facilityRule->getWorkshops(), \"workshops\");\n\taddInteger(ss, facilityRule->getPsiLaboratories(), \"psiLabs\");\n\taddInteger(ss, facilityRule->getTrainingFacilities(), \"trainingRooms\");\n\n\taddIntegerNauticalMiles(ss, facilityRule->getSightRange(), \"sightRange\");\n\taddIntegerPercent(ss, facilityRule->getSightChance(), \"sightChance\");\n\taddIntegerNauticalMiles(ss, facilityRule->getRadarRange(), \"radarRange\");\n\taddIntegerPercent(ss, facilityRule->getRadarChance(), \"radarChance\");\n\taddInteger(ss, facilityRule->getDefenseValue(), \"defense\");\n\taddIntegerPercent(ss, facilityRule->getHitRatio(), \"hitRatio\");\n\taddInteger(ss, facilityRule->getAmmoMax(), \"ammoMax\", 0);\n\taddInteger(ss, facilityRule->getRearmRate(), \"rearmRate\", 1);\n\taddInteger(ss, facilityRule->getAmmoNeeded(), \"ammoNeeded\", 1);\n\taddBoolean(ss, facilityRule->unifiedDamageFormula(), \"unifiedDamageFormula\");\n\taddIntegerPercent(ss, facilityRule->getShieldDamageModifier(), \"shieldDamageModifier\", 100);\n\taddRule(ss, facilityRule->getAmmoItem(), \"ammoItem\");\n\n\taddInteger(ss, facilityRule->getMaxAllowedPerBase(), \"maxAllowedPerBase\");\n\taddInteger(ss, facilityRule->getManaRecoveryPerDay(), \"manaRecoveryPerDay\");\n\taddInteger(ss, facilityRule->getHealthRecoveryPerDay(), \"healthRecoveryPerDay\");\n\taddFloat(ss, facilityRule->getSickBayAbsoluteBonus(), \"sickBayAbsoluteBonus\");\n\taddFloat(ss, facilityRule->getSickBayRelativeBonus(), \"sickBayRelativeBonus\");\n\n\taddRightClickActionType(ss, facilityRule->getRightClickActionType(), \"rightClickActionType\");\n\n\taddVectorOfRules(ss, facilityRule->getLeavesBehindOnSell(), \"leavesBehindOnSell\");\n\taddInteger(ss, facilityRule->getRemovalTime(), \"removalTime\");\n\taddBoolean(ss, facilityRule->getCanBeBuiltOver(), \"canBeBuiltOver\");\n\taddBoolean(ss, facilityRule->isUpgradeOnly(), \"upgradeOnly\");\n\taddVectorOfRules(ss, facilityRule->getBuildOverFacilities(), \"buildOverFacilities\");\n\n\tif (facilityRule->getDefenseValue() > 0)\n\t{\n\t\taddHeading(\"_calculatedValues\");\n\t\tif (facilityRule->unifiedDamageFormula() && facilityRule->getAmmoItem())\n\t\t{\n\t\t\tstd::ostringstream ss2;\n\t\t\tss2 << facilityRule->getAmmoItem()->getDamageType()->getRandomDamage(facilityRule->getDefenseValue(), 1);\n\t\t\tss2 << \"-\";\n\t\t\tss2 << facilityRule->getAmmoItem()->getDamageType()->getRandomDamage(facilityRule->getDefenseValue(), 2);\n\t\t\taddSingleString(ss, ss2.str(), \"_damageRange\", \"\", false);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// (damage) * (50-150% damage spread)\n\t\t\tstd::ostringstream ss2;\n\t\t\tss2 << facilityRule->getDefenseValue() / 2;\n\t\t\tss2 << \"-\";\n\t\t\tss2 << facilityRule->getDefenseValue() / 2 + facilityRule->getDefenseValue();\n\t\t\taddSingleString(ss, ss2.str(), \"_damageRange\", \"\", false);\n\t\t}\n\t\tendHeading();\n\t}\n\n\tif (_showDebug)\n\t{\n\t\taddSection(\"{Modding section}\", \"You don't need this info as a player\", _white, true);\n\n\t\taddSection(\"{Naming}\", \"\", _white);\n\t\taddSingleString(ss, facilityRule->getType(), \"type\");\n\t\taddSingleString(ss, facilityRule->getUfopediaType(), \"ufopediaType\");\n\t\taddInteger(ss, facilityRule->getListOrder(), \"listOrder\");\n\t\taddInteger(ss, facilityRule->getMissileAttraction(), \"missileAttraction\", 100);\n\t\taddRule(ss, facilityRule->getDestroyedFacility(), \"destroyedFacility\");\n\n\t\taddSection(\"{Visuals}\", \"\", _white);\n\t\taddInteger(ss, facilityRule->getFakeUnderwaterRaw(), \"fakeUnderwater\", -1);\n\t\taddSingleString(ss, facilityRule->getMapName(), \"mapName\");\n\t\taddBoolean(ss, !facilityRule->getVerticalLevels().empty(), \"verticalLevels*\"); // just say if there are any or not\n\t\taddVectorOfPositions(ss, facilityRule->getStorageTiles(), \"storageTiles\");\n\n\t\taddInteger(ss, facilityRule->getSpriteShape(), \"spriteShape\", -1);\n\t\taddSpriteResourcePath(ss, mod, \"BASEBITS.PCK\", facilityRule->getSpriteShape());\n\n\t\taddInteger(ss, facilityRule->getSpriteFacility(), \"spriteFacility\", -1);\n\t\taddSpriteResourcePath(ss, mod, \"BASEBITS.PCK\", facilityRule->getSpriteFacility());\n\n\t\taddBoolean(ss, facilityRule->getSpriteEnabledRaw(), \"spriteEnabled\");\n\t\taddBoolean(ss, facilityRule->connectorsDisabled(), \"connectorsDisabled\");\n\n\t\taddSection(\"{Sounds}\", \"\", _white);\n\t\taddInteger(ss, facilityRule->getFireSound(), \"fireSound\");\n\t\tstd::vector<int> tmpSoundVector;\n\t\ttmpSoundVector.push_back(facilityRule->getFireSound());\n\t\taddSoundVectorResourcePaths(ss, mod, \"GEO.CAT\", tmpSoundVector);\n\n\t\taddInteger(ss, facilityRule->getHitSound(), \"hitSound\");\n\t\ttmpSoundVector.clear();\n\t\ttmpSoundVector.push_back(facilityRule->getHitSound());\n\t\taddSoundVectorResourcePaths(ss, mod, \"GEO.CAT\", tmpSoundVector);\n\n\t\taddInteger(ss, facilityRule->getPlaceSound(), \"placeSound\", -1);\n\t\ttmpSoundVector.clear();\n\t\ttmpSoundVector.push_back(facilityRule->getPlaceSound());\n\t\taddSoundVectorResourcePaths(ss, mod, \"GEO.CAT\", tmpSoundVector);\n\n\t\taddSection(\"{Mod info}\", \"\", _white);\n\t\t{\n\t\t\taddSingleString(ss, mod->getModCreatingRule(facilityRule)->name, \"createdByMod\");\n\t\t\taddSingleString(ss, mod->getModLastUpdatingRule(facilityRule)->name, \"updatedByMod\");\n\t\t\tendHeading();\n\t\t}\n\t}\n}\n\n/**\n * Shows the \"raw\" RuleCraft data.\n */\nvoid StatsForNerdsState::initCraftList()\n{\n\t_lstRawData->clearList();\n\t_lstRawData->setIgnoreSeparators(true);\n\n\tstd::ostringstream ssTopic;\n\tssTopic << tr(_topicId);\n\tif (_showIds)\n\t{\n\t\tssTopic << \" [\" << _topicId << \"]\";\n\t}\n\n\t_txtArticle->setText(tr(\"STR_ARTICLE\").arg(ssTopic.str()));\n\n\tMod *mod = _game->getMod();\n\tRuleCraft *craftRule = mod->getCraft(_topicId);\n\tif (!craftRule)\n\t\treturn;\n\n\t_filterOptions.clear();\n\t_cbxRelatedStuff->setVisible(false);\n\n\tstd::ostringstream ss;\n\n\taddVectorOfStrings(ss, craftRule->getRequirements(), \"requires\");\n\taddVectorOfStrings(ss, mod->getBaseFunctionNames(craftRule->getRequiresBuyBaseFunc()), \"requiresBuyBaseFunc\");\n\taddSingleString(ss, craftRule->getRequiresBuyCountry(), \"requiresBuyCountry\");\n\n\taddInteger(ss, craftRule->getBuyCost(), \"costBuy\", 0, true);\n\taddInteger(ss, craftRule->getMonthlyBuyLimit(), \"monthlyBuyLimit\");\n\taddInteger(ss, craftRule->getRentCost(), \"costRent\", 0, true);\n\taddInteger(ss, craftRule->getSellCost(), \"costSell\", 0, true);\n\taddInteger(ss, craftRule->getTransferTime(), \"transferTime\", 24);\n\n\taddInteger(ss, craftRule->getMaxUnits(), \"soldiers\");\n\taddInteger(ss, craftRule->getMaxUnitsLimit(), \"maxUnitsLimit\", craftRule->getMaxUnits());\n\taddInteger(ss, craftRule->getPilots(), \"pilots\");\n\taddUnitStatBonus(ss, craftRule->getPilotMinStatsRequired(), \"pilotMinStatsRequired\");\n\taddVectorOfRulesNamed(ss, craftRule->getPilotSoldierBonusesRequired(), \"pilotSoldierBonusesRequired\");\n\taddInteger(ss, craftRule->getMaxVehiclesAndLargeSoldiers(), \"vehicles\");\n\taddInteger(ss, craftRule->getMaxVehiclesAndLargeSoldiersLimit(), \"maxHWPUnitsLimit\", craftRule->getMaxVehiclesAndLargeSoldiers());\n\n\taddBoolean(ss, craftRule->isOnlyOneSoldierGroupAllowed(), \"onlyOneSoldierGroupAllowed\");\n\taddVectorOfIntegers(ss, craftRule->getAllowedSoldierGroups(), \"allowedSoldierGroups\");\n\taddVectorOfIntegers(ss, craftRule->getAllowedArmorGroups(), \"allowedArmorGroups\");\n\taddMapOfIntegers(ss, craftRule->getLimitArmorGroups(), \"limitArmorGroups\");\n\n\taddInteger(ss, craftRule->getMaxSmallSoldiers(), \"maxSmallSoldiers\", -1);\n\taddInteger(ss, craftRule->getMaxLargeSoldiers(), \"maxLargeSoldiers\", -1);\n\taddInteger(ss, craftRule->getMaxSmallVehicles(), \"maxSmallVehicles\", -1);\n\taddInteger(ss, craftRule->getMaxLargeVehicles(), \"maxLargeVehicles\", -1);\n\taddInteger(ss, craftRule->getMaxSmallUnits(), \"maxSmallUnits\", -1);\n\taddInteger(ss, craftRule->getMaxLargeUnits(), \"maxLargeUnits\", -1);\n\taddInteger(ss, craftRule->getMaxSoldiers(), \"maxSoldiers\", -1);\n\taddInteger(ss, craftRule->getMaxVehicles(), \"maxVehicles\", -1);\n\n\taddInteger(ss, craftRule->getMaxItems(), \"maxItems\", 999999);\n\taddDouble(ss, craftRule->getMaxStorageSpace(), \"maxStorageSpace\", 99999.0);\n\n\taddInteger(ss, craftRule->getMaxAltitude(), \"maxAltitude\", -1);\n\taddInteger(ss, craftRule->getWeapons(), \"weapons\");\n\n\t// weaponStrings\n\tbool modded = false;\n\tfor (int i = 0; i < RuleCraft::WeaponMax; ++i)\n\t{\n\t\tif (i == 0 && craftRule->getWeaponSlotString(i) != \"STR_WEAPON_ONE\")\n\t\t{\n\t\t\tmodded = true;\n\t\t}\n\t\tif (i == 1 && craftRule->getWeaponSlotString(i) != \"STR_WEAPON_TWO\")\n\t\t{\n\t\t\tmodded = true;\n\t\t}\n\t\tif (i > 1 && !craftRule->getWeaponSlotString(i).empty())\n\t\t{\n\t\t\tmodded = true;\n\t\t}\n\t}\n\tstd::vector<std::string> tmp;\n\tif (modded)\n\t{\n\t\tfor (int i = 0; i < RuleCraft::WeaponMax; ++i)\n\t\t{\n\t\t\ttmp.push_back(craftRule->getWeaponSlotString(i));\n\t\t}\n\t}\n\taddVectorOfStrings(ss, tmp, \"weaponStrings\");\n\n\t// fixedWeapons\n\tmodded = false;\n\tfor (int i = 0; i < RuleCraft::WeaponMax; ++i)\n\t{\n\t\tif (!craftRule->getFixedWeaponInSlot(i).empty())\n\t\t{\n\t\t\tmodded = true;\n\t\t\tbreak;\n\t\t}\n\t}\n\ttmp.clear();\n\tif (modded)\n\t{\n\t\tfor (int i = 0; i < RuleCraft::WeaponMax; ++i)\n\t\t{\n\t\t\ttmp.push_back(craftRule->getFixedWeaponInSlot(i));\n\t\t}\n\t}\n\taddVectorOfStrings(ss, tmp, \"fixedWeapons\");\n\n\t// weaponTypes\n\tmodded = false;\n\tfor (int i = 0; i < RuleCraft::WeaponMax; ++i)\n\t{\n\t\tfor (int j = 0; j < RuleCraft::WeaponTypeMax; ++j)\n\t\t{\n\t\t\tif (craftRule->getWeaponTypesRaw(i, j) != 0)\n\t\t\t{\n\t\t\t\tmodded = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (modded) break;\n\t}\n\ttmp.clear();\n\tif (modded)\n\t{\n\t\tfor (int i = 0; i < RuleCraft::WeaponMax; ++i)\n\t\t{\n\t\t\tstd::ostringstream ss2;\n\t\t\tint weaponType = craftRule->getWeaponTypesRaw(i, 0);\n\t\t\tss2 << \"{\" << weaponType;\n\t\t\tfor (int j = 1; j < RuleCraft::WeaponTypeMax; ++j)\n\t\t\t{\n\t\t\t\tif (weaponType != craftRule->getWeaponTypesRaw(i, j))\n\t\t\t\t{\n\t\t\t\t\tweaponType = craftRule->getWeaponTypesRaw(i, j);\n\t\t\t\t\tss2 << \",\" << weaponType;\n\t\t\t\t}\n\t\t\t}\n\t\t\tss2 << \"}\";\n\t\t\ttmp.push_back(ss2.str());\n\t\t}\n\t}\n\taddVectorOfStrings(ss, tmp, \"weaponTypes\", false);\n\n\taddHeading(\"stats\");\n\t{\n\t\taddInteger(ss, craftRule->getMaxDamage(), \"damageMax\");\n\t\taddInteger(ss, craftRule->getStats().armor, \"armor\");\n\t\taddIntegerPercent(ss, craftRule->getStats().avoidBonus, \"avoidBonus\");\n\t\taddIntegerPercent(ss, craftRule->getStats().avoidBonus2, \"avoidBonus2\");\n\t\taddIntegerPercent(ss, craftRule->getStats().powerBonus, \"powerBonus\");\n\t\taddIntegerPercent(ss, craftRule->getStats().hitBonus, \"hitBonus\");\n\t\taddInteger(ss, craftRule->getMaxFuel(), \"fuelMax\");\n\t\taddIntegerKnots(ss, craftRule->getMaxSpeed(), \"speedMax\");\n\t\taddInteger(ss, craftRule->getAcceleration(), \"accel\");\n\t\taddIntegerNauticalMiles(ss, craftRule->getRadarRange(), \"radarRange\", 672);\n\t\taddIntegerPercent(ss, craftRule->getRadarChance(), \"radarChance\", 100);\n\t\taddIntegerNauticalMiles(ss, craftRule->getSightRange(), \"sightRange\", 1696);\n\t\taddInteger(ss, craftRule->getStats().shieldCapacity, \"shieldCapacity\");\n\t\taddInteger(ss, craftRule->getStats().shieldRecharge, \"shieldRecharge\");\n\t\taddInteger(ss, craftRule->getStats().shieldRechargeInGeoscape, \"shieldRechargeInGeoscape\");\n\t\taddInteger(ss, craftRule->getStats().shieldBleedThrough, \"shieldBleedThrough\");\n\t\tendHeading();\n\t}\n\taddInteger(ss, craftRule->getShieldRechargeAtBase(), \"shieldRechargedAtBase\", 1000);\n\n\taddRule(ss, craftRule->getRefuelItem(), \"refuelItem\");\n\taddInteger(ss, craftRule->getRefuelRate(), \"refuelRate\", 1);\n\taddInteger(ss, craftRule->getRepairRate(), \"repairRate\", 1);\n\n\taddBoolean(ss, craftRule->getSpacecraft(), \"spacecraft\");\n\taddBoolean(ss, craftRule->getAllowLanding(), \"allowLanding\", true);\n\taddBoolean(ss, craftRule->notifyWhenRefueled(), \"notifyWhenRefueled\");\n\taddBoolean(ss, craftRule->canAutoPatrol(), \"autoPatrol\");\n\taddBoolean(ss, craftRule->isUndetectable(), \"undetectable\");\n\taddBoolean(ss, craftRule->patrolWithoutFuel(), \"patrolWithoutFuel\");\n\n\taddBoolean(ss, craftRule->keepCraftAfterFailedMission(), \"keepCraftAfterFailedMission\");\n\n\taddHeading(\"_calculatedValues\");\n\t{\n\t\tif (craftRule->calculateRange(0) != -1)\n\t\t{\n\t\t\taddIntegerNauticalMiles(ss, craftRule->calculateRange(0), \"_maxRange\");\n\t\t\taddIntegerNauticalMiles(ss, craftRule->calculateRange(1), \"_minRange\");\n\t\t\taddIntegerNauticalMiles(ss, craftRule->calculateRange(2), \"_avgRange\");\n\t\t}\n\t\telse\n\t\t{\n\t\t\taddSingleString(ss, \"STR_INFINITE_RANGE\", \"_maxRange\");\n\t\t\taddSingleString(ss, \"STR_INFINITE_RANGE\", \"_minRange\");\n\t\t\taddSingleString(ss, \"STR_INFINITE_RANGE\", \"_avgRange\");\n\t\t}\n\t\tendHeading();\n\t}\n\n\tModScript::scriptCallback<ModScript::StatsForNerdsCraft>(craftRule, craftRule, this, _game->getSavedGame());\n\n\tif (_showDebug)\n\t{\n\t\taddSection(\"{Modding section}\", \"You don't need this info as a player\", _white, true);\n\n\t\taddSection(\"{Naming}\", \"\", _white);\n\t\taddSingleString(ss, craftRule->getType(), \"type\");\n\t\taddInteger(ss, craftRule->getListOrder(), \"listOrder\");\n\t\taddSingleString(ss, craftRule->getMonthlyBuyLimitMessage(), \"monthlyBuyLimitMessage\");\n\n\t\taddSection(\"{Geoscape}\", \"\", _white);\n\t\taddSingleString(ss, craftRule->getDefaultDisplayAltitude(), \"defaultAltitude\", \"STR_VERY_LOW\");\n\t\taddInteger(ss, craftRule->getSprite(0), \"sprite (Minimized)\", -1);\n\t\taddSpriteResourcePath(ss, mod, \"INTICON.PCK\", craftRule->getSprite(0));\n\t\taddInteger(ss, craftRule->getSprite(0) + 11, \"_sprite (Dogfight)\", 10);\n\t\taddSpriteResourcePath(ss, mod, \"INTICON.PCK\", craftRule->getSprite(0) + 11);\n\t\taddInteger(ss, craftRule->getSprite(0) + 33, \"_sprite (Base)\", 32);\n\t\taddSpriteResourcePath(ss, mod, \"BASEBITS.PCK\", craftRule->getSprite(0) + 33);\n\t\taddInteger(ss, craftRule->getMarker(), \"marker\", -1);\n\t\taddInteger(ss, craftRule->getScore(), \"score\");\n\t\taddInteger(ss, craftRule->getMaxSkinIndex(), \"maxSkinIndex\");\n\t\taddBoolean(ss, !craftRule->getSkinSpritesRaw().empty(), \"skinSprites\", false); // just say if there is any or not\n\n\t\taddSection(\"{Sounds}\", \"\", _white);\n\t\taddVectorOfIntegers(ss, craftRule->getSelectSoundRaw(), \"selectSound\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"GEO.CAT\", craftRule->getSelectSoundRaw());\n\t\taddVectorOfIntegers(ss, craftRule->getTakeoffSoundRaw(), \"takeoffSound\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"GEO.CAT\", craftRule->getTakeoffSoundRaw());\n\n\t\taddSection(\"{Battlescape}\", \"\", _white);\n\t\taddBoolean(ss, craftRule->getBattlescapeTerrainData() != 0, \"battlescapeTerrainData\", false); // just say if there is any or not\n\t\taddBoolean(ss, craftRule->isMapVisible(), \"mapVisible\", true);\n\t\taddVectorOfIntegers(ss, craftRule->getCraftInventoryTile(), \"craftInventoryTile\");\n\t\taddVectorOfIntegers(ss, craftRule->getGroups(), \"groups\");\n\t\taddBoolean(ss, craftRule->useAllStartTiles(), \"useAllStartTiles\");\n\t\taddSingleString(ss, craftRule->getCustomPreviewTypeRaw(), \"customPreview\");\n\t\tif (craftRule->getDeployment().empty())\n\t\t{\n\t\t\tstd::vector<int> dummy;\n\t\t\taddVectorOfIntegers(ss, dummy, \"deployment\");\n\t\t}\n\t\telse\n\t\t{\n\t\t\taddHeading(\"deployment\");\n\t\t\t{\n\t\t\t\tfor (auto& d : craftRule->getDeployment())\n\t\t\t\t{\n\t\t\t\t\taddVectorOfIntegers(ss, d, \"\");\n\t\t\t\t}\n\t\t\t\tendHeading();\n\t\t\t}\n\t\t}\n\n\t\taddSection(\"{Script tags}\", \"\", _white, true);\n\t\t{\n\t\t\taddScriptTags(ss, craftRule->getScriptValuesRaw());\n\t\t\tendHeading();\n\t\t}\n\n\t\taddSection(\"{Mod info}\", \"\", _white);\n\t\t{\n\t\t\taddSingleString(ss, mod->getModCreatingRule(craftRule)->name, \"createdByMod\");\n\t\t\taddSingleString(ss, mod->getModLastUpdatingRule(craftRule)->name, \"updatedByMod\");\n\t\t\tendHeading();\n\t\t}\n\t}\n}\n\n/**\n * Adds a HuntMode to the table.\n */\nvoid StatsForNerdsState::addHuntMode(std::ostringstream &ss, const int &value, const std::string &propertyName, const int &defaultvalue)\n{\n\tif (value == defaultvalue && !_showDefaults)\n\t{\n\t\treturn;\n\t}\n\tresetStream(ss);\n\tswitch (value)\n\t{\n\tcase 0: ss << tr(\"HM_INTERCEPTORS\"); break;\n\tcase 1: ss << tr(\"HM_TRANSPORTS\"); break;\n\tcase 2: ss << tr(\"HM_RANDOM\"); break;\n\tdefault: ss << tr(\"STR_UNKNOWN\"); break;\n\t}\n\tif (_showIds)\n\t{\n\t\tss << \" [\" << value << \"]\";\n\t}\n\t_lstRawData->addRow(2, trp(propertyName).c_str(), ss.str().c_str());\n\t++_counter;\n\tif (value != defaultvalue)\n\t{\n\t\t_lstRawData->setCellColor(_lstRawData->getLastRowIndex(), 1, _pink);\n\t}\n}\n\n/**\n * Adds a HuntBehavior to the table.\n */\nvoid StatsForNerdsState::addHuntBehavior(std::ostringstream &ss, const int &value, const std::string &propertyName, const int &defaultvalue)\n{\n\tif (value == defaultvalue && !_showDefaults)\n\t{\n\t\treturn;\n\t}\n\tresetStream(ss);\n\tswitch (value)\n\t{\n\tcase 0: ss << tr(\"HB_FLEE\"); break;\n\tcase 1: ss << tr(\"HB_KAMIKAZE\"); break;\n\tcase 2: ss << tr(\"HB_RANDOM\"); break;\n\tdefault: ss << tr(\"STR_UNKNOWN\"); break;\n\t}\n\tif (_showIds)\n\t{\n\t\tss << \" [\" << value << \"]\";\n\t}\n\t_lstRawData->addRow(2, trp(propertyName).c_str(), ss.str().c_str());\n\t++_counter;\n\tif (value != defaultvalue)\n\t{\n\t\t_lstRawData->setCellColor(_lstRawData->getLastRowIndex(), 1, _pink);\n\t}\n}\n\n/**\n * Shows the \"raw\" RuleUfo data.\n */\nvoid StatsForNerdsState::initUfoList()\n{\n\t_lstRawData->clearList();\n\t_lstRawData->setIgnoreSeparators(true);\n\n\tstd::ostringstream ssTopic;\n\tssTopic << tr(_topicId);\n\tif (_showIds)\n\t{\n\t\tssTopic << \" [\" << _topicId << \"]\";\n\t}\n\n\t_txtArticle->setText(tr(\"STR_ARTICLE\").arg(ssTopic.str()));\n\n\tMod *mod = _game->getMod();\n\tRuleUfo *ufoRule = mod->getUfo(_topicId);\n\tif (!ufoRule)\n\t\treturn;\n\n\t_filterOptions.clear();\n\t_cbxRelatedStuff->setVisible(false);\n\n\tstd::ostringstream ss;\n\n\taddSingleString(ss, ufoRule->getSize(), \"size\");\n\n\taddIntegerPercent(ss, ufoRule->getHunterKillerPercentage(), \"hunterKillerPercentage\");\n\taddHuntMode(ss, ufoRule->getHuntMode(), \"huntMode\");\n\taddIntegerPercent(ss, ufoRule->getHuntSpeed(), \"huntSpeed\", 100);\n\taddHuntBehavior(ss, ufoRule->getHuntBehavior(), \"huntBehavior\", 2);\n\n\taddInteger(ss, ufoRule->getWeaponPower(), \"power\");\n\taddIntegerKm(ss, ufoRule->getWeaponRange(), \"range\");\n\taddIntegerSeconds(ss, ufoRule->getWeaponReload(), \"reload\");\n\taddIntegerSeconds(ss, ufoRule->getBreakOffTime(), \"breakOffTime\");\n\taddInteger(ss, ufoRule->getScore(), \"score\");\n\taddInteger(ss, ufoRule->getMissionScore(), \"missionScore\", 1);\n\n\taddHeading(\"stats\");\n\t{\n\t\taddInteger(ss, ufoRule->getStats().damageMax, \"damageMax\");\n\t\taddInteger(ss, ufoRule->getStats().armor, \"armor\");\n\t\taddIntegerPercent(ss, ufoRule->getStats().avoidBonus, \"avoidBonus\");\n\t\taddIntegerPercent(ss, ufoRule->getStats().avoidBonus2, \"avoidBonus2\");\n\t\taddIntegerPercent(ss, ufoRule->getStats().powerBonus, \"powerBonus\");\n\t\taddIntegerPercent(ss, ufoRule->getStats().hitBonus, \"hitBonus\");\n\t\taddInteger(ss, ufoRule->getStats().fuelMax, \"fuelMax\");\n\t\taddIntegerKnots(ss, ufoRule->getStats().speedMax, \"speedMax\");\n\t\taddInteger(ss, ufoRule->getStats().accel, \"accel\");\n\t\taddIntegerNauticalMiles(ss, ufoRule->getStats().radarRange, \"radarRange\", 672);\n\t\taddIntegerPercent(ss, ufoRule->getStats().radarChance, \"radarChance\");\n\t\taddIntegerNauticalMiles(ss, ufoRule->getStats().sightRange, \"sightRange\", 268);\n\t\taddInteger(ss, ufoRule->getStats().shieldCapacity, \"shieldCapacity\");\n\t\taddInteger(ss, ufoRule->getStats().shieldRecharge, \"shieldRecharge\");\n\t\taddInteger(ss, ufoRule->getStats().shieldRechargeInGeoscape, \"shieldRechargeInGeoscape\");\n\t\taddInteger(ss, ufoRule->getStats().shieldBleedThrough, \"shieldBleedThrough\");\n\t\t// UFO-specific\n\t\taddSingleString(ss, ufoRule->getStats().craftCustomDeploy, \"craftCustomDeploy\");\n\t\taddSingleString(ss, ufoRule->getStats().missionCustomDeploy, \"missionCustomDeploy\");\n\t\tendHeading();\n\t}\n\n\taddHeading(\"_calculatedValues\", \"STR_FOR_DIFFICULTY\", true);\n\t{\n\t\tint escapeCountdown = ufoRule->getBreakOffTime() - 30 * _game->getSavedGame()->getDifficultyCoefficient();\n\t\tint escapeCountdownMax = escapeCountdown + ufoRule->getBreakOffTime();\n\t\t{\n\t\t\tint diff = _game->getSavedGame()->getDifficulty();\n\t\t\tauto& custom = _game->getMod()->getUfoEscapeCountdownCoefficients();\n\t\t\tif (custom.size() > (size_t)diff)\n\t\t\t{\n\t\t\t\tescapeCountdown = ufoRule->getBreakOffTime() * custom[diff] / 100;\n\t\t\t\tescapeCountdownMax = ufoRule->getBreakOffTime() * 2 * custom[diff] / 100;\n\t\t\t}\n\t\t}\n\t\taddIntegerSeconds(ss, std::max(1, escapeCountdown), \"_escapeCountdown\", 0, std::max(1, escapeCountdownMax));\n\n\t\tint fireCountdown = std::max(1, (ufoRule->getWeaponReload() - 2 * _game->getSavedGame()->getDifficultyCoefficient()));\n\t\t{\n\t\t\tint diff = _game->getSavedGame()->getDifficulty();\n\t\t\tauto& custom = _game->getMod()->getUfoFiringRateCoefficients();\n\t\t\tif (custom.size() > (size_t)diff)\n\t\t\t{\n\t\t\t\tfireCountdown = std::max(1, ufoRule->getWeaponReload() * custom[diff] / 100);\n\t\t\t}\n\t\t}\n\t\taddIntegerSeconds(ss, fireCountdown, \"_fireRate\", 0, fireCountdown * 2);\n\n\t\t// not considering race bonus\n\t\tint totalPower = ufoRule->getWeaponPower() * (ufoRule->getStats().powerBonus + 100) / 100;\n\t\t// spread 0-100%\n\t\tdouble avgDamage = totalPower * 0.5;\n\t\t// not considering craft dodge, pilot dodge and evasive maneuvers\n\t\tint totalAccuracy = 60 + ufoRule->getStats().hitBonus;\n\t\t// spread 100-200%\n\t\tdouble avgFireRate = fireCountdown * 1.5;\n\t\tdouble avgDpm = avgDamage * (totalAccuracy / 100.0) * (60.0 / avgFireRate);\n\t\taddInteger(ss, Round(avgDpm), \"_averageDPM\");\n\n\t\tendHeading();\n\t}\n\n\tfor (auto& raceBonus : ufoRule->getRaceBonusRaw())\n\t{\n\t\tif (!raceBonus.first.empty())\n\t\t{\n\t\t\taddHeading(\"STR_RACE_BONUS\", raceBonus.first);\n\t\t\t{\n\t\t\t\taddInteger(ss, raceBonus.second.damageMax, \"damageMax\");\n\t\t\t\taddInteger(ss, raceBonus.second.armor, \"armor\");\n\t\t\t\taddIntegerPercent(ss, raceBonus.second.avoidBonus, \"avoidBonus\");\n\t\t\t\taddIntegerPercent(ss, raceBonus.second.avoidBonus2, \"avoidBonus2\");\n\t\t\t\taddIntegerPercent(ss, raceBonus.second.powerBonus, \"powerBonus\");\n\t\t\t\taddIntegerPercent(ss, raceBonus.second.hitBonus, \"hitBonus\");\n\t\t\t\taddInteger(ss, raceBonus.second.fuelMax, \"fuelMax\");\n\t\t\t\taddIntegerKnots(ss, raceBonus.second.speedMax, \"speedMax\");\n\t\t\t\taddInteger(ss, raceBonus.second.accel, \"accel\");\n\t\t\t\taddIntegerNauticalMiles(ss, raceBonus.second.radarRange, \"radarRange\", 0);\n\t\t\t\taddIntegerPercent(ss, raceBonus.second.radarChance, \"radarChance\");\n\t\t\t\taddIntegerNauticalMiles(ss, raceBonus.second.sightRange, \"sightRange\", 0);\n\t\t\t\taddInteger(ss, raceBonus.second.shieldCapacity, \"shieldCapacity\");\n\t\t\t\taddInteger(ss, raceBonus.second.shieldRecharge, \"shieldRecharge\");\n\t\t\t\taddInteger(ss, raceBonus.second.shieldRechargeInGeoscape, \"shieldRechargeInGeoscape\");\n\t\t\t\taddInteger(ss, raceBonus.second.shieldBleedThrough, \"shieldBleedThrough\");\n\t\t\t\t// UFO-specific\n\t\t\t\taddSingleString(ss, raceBonus.second.craftCustomDeploy, \"craftCustomDeploy\");\n\t\t\t\taddSingleString(ss, raceBonus.second.missionCustomDeploy, \"missionCustomDeploy\");\n\t\t\t\tendHeading();\n\t\t\t}\n\t\t}\n\t}\n\n\tModScript::scriptCallback<ModScript::StatsForNerdsUfo>(ufoRule, ufoRule, this, _game->getSavedGame());\n\n\tif (_showDebug)\n\t{\n\t\taddSection(\"{Modding section}\", \"You don't need this info as a player\", _white, true);\n\n\t\taddSection(\"{Naming}\", \"\", _white);\n\t\taddSingleString(ss, ufoRule->getType(), \"type\");\n\n\t\taddSection(\"{Exotic}\", \"\", _white);\n\t\taddInteger(ss, ufoRule->getSoftlockThreshold(), \"softlockThreshold\", 100);\n\t\taddSingleString(ss, ufoRule->getHitImage(), \"hitImage\");\n\t\taddInteger(ss, ufoRule->getMissilePower(), \"missilePower\");\n\t\taddInteger(ss, ufoRule->getMissileStopChance(), \"missileStopChance\");\n\t\taddBoolean(ss, ufoRule->isUnmanned(), \"unmanned\");\n\t\taddBoolean(ss, ufoRule->isInstaHyper(), \"instaHyper\");\n\t\taddBoolean(ss, ufoRule->isNoAlert(), \"noAlert\");\n\t\taddInteger(ss, ufoRule->getSplashdownSurvivalChance(), \"splashdownSurvivalChance\", 100);\n\t\taddInteger(ss, ufoRule->getFakeWaterLandingChance(), \"fakeWaterLandingChance\", 0);\n\n\t\taddSection(\"{Visuals}\", \"\", _white);\n\t\taddInteger(ss, ufoRule->getRadius(), \"radius\", -1);\n\t\taddInteger(ss, ufoRule->getDefaultVisibility(), \"visibility\");\n\t\taddInteger(ss, ufoRule->getBlobSize(), \"blobSize\", -1);\n\n\t\taddInteger(ss, ufoRule->getSprite(), \"sprite\", -1); // INTERWIN.DAT\n\t\taddSingleString(ss, ufoRule->getModSprite(), \"modSprite\", \"\", false);\n\t\taddInteger(ss, ufoRule->getMarker(), \"marker\", -1);\n\t\taddInteger(ss, ufoRule->getLandMarker(), \"markerLand\", -1);\n\t\taddInteger(ss, ufoRule->getCrashMarker(), \"markerCrash\", -1);\n\t\taddBoolean(ss, ufoRule->getBattlescapeTerrainData() != 0, \"battlescapeTerrainData\", false); // just say if there is any or not\n\n\t\taddSection(\"{Sounds}\", \"\", _white);\n\t\taddInteger(ss, ufoRule->getFireSound(), \"fireSound\", -1);\n\t\tstd::vector<int> tmpSoundVector;\n\t\ttmpSoundVector.push_back(ufoRule->getFireSound());\n\t\taddSoundVectorResourcePaths(ss, mod, \"GEO.CAT\", tmpSoundVector);\n\n\t\taddInteger(ss, ufoRule->getAlertSound(), \"alertSound\", -1);\n\t\ttmpSoundVector.clear();\n\t\ttmpSoundVector.push_back(ufoRule->getAlertSound());\n\t\taddSoundVectorResourcePaths(ss, mod, \"GEO.CAT\", tmpSoundVector);\n\n\t\taddInteger(ss, ufoRule->getHuntAlertSound(), \"huntAlertSound\", -1);\n\t\ttmpSoundVector.clear();\n\t\ttmpSoundVector.push_back(ufoRule->getHuntAlertSound());\n\t\taddSoundVectorResourcePaths(ss, mod, \"GEO.CAT\", tmpSoundVector);\n\n\t\taddInteger(ss, ufoRule->getHitSound(), \"hitSound\", -1);\n\t\ttmpSoundVector.clear();\n\t\ttmpSoundVector.push_back(ufoRule->getHitSound());\n\t\taddSoundVectorResourcePaths(ss, mod, \"GEO.CAT\", tmpSoundVector);\n\n\t\taddSection(\"{Script tags}\", \"\", _white, true);\n\t\t{\n\t\t\taddScriptTags(ss, ufoRule->getScriptValuesRaw());\n\t\t\tendHeading();\n\t\t}\n\n\t\taddSection(\"{Mod info}\", \"\", _white);\n\t\t{\n\t\t\taddSingleString(ss, mod->getModCreatingRule(ufoRule)->name, \"createdByMod\");\n\t\t\taddSingleString(ss, mod->getModLastUpdatingRule(ufoRule)->name, \"updatedByMod\");\n\t\t\tendHeading();\n\t\t}\n\t}\n}\n\n/**\n * Shows the \"raw\" RuleCraftWeapon data.\n */\nvoid StatsForNerdsState::initCraftWeaponList()\n{\n\t_lstRawData->clearList();\n\t_lstRawData->setIgnoreSeparators(true);\n\n\tstd::ostringstream ssTopic;\n\tssTopic << tr(_topicId);\n\tif (_showIds)\n\t{\n\t\tssTopic << \" [\" << _topicId << \"]\";\n\t}\n\n\t_txtArticle->setText(tr(\"STR_ARTICLE\").arg(ssTopic.str()));\n\n\tMod *mod = _game->getMod();\n\tRuleCraftWeapon *craftWeaponRule = mod->getCraftWeapon(_topicId);\n\tif (!craftWeaponRule)\n\t\treturn;\n\n\t_filterOptions.clear();\n\t_cbxRelatedStuff->setVisible(false);\n\n\tstd::ostringstream ss;\n\n\taddInteger(ss, craftWeaponRule->getTractorBeamPower(), \"tractorBeamPower\");\n\taddInteger(ss, craftWeaponRule->getDamage(), \"damage\");\n\taddBoolean(ss, craftWeaponRule->unifiedDamageFormula(), \"unifiedDamageFormula\");\n\taddIntegerPercent(ss, craftWeaponRule->getShieldDamageModifier(), \"shieldDamageModifier\", 100);\n\taddIntegerKm(ss, craftWeaponRule->getRange(), \"range\");\n\taddIntegerPercent(ss, craftWeaponRule->getAccuracy(), \"accuracy\");\n\taddIntegerSeconds(ss, craftWeaponRule->getCautiousReload(), \"reloadCautious\");\n\taddIntegerSeconds(ss, craftWeaponRule->getStandardReload(), \"reloadStandard\");\n\taddIntegerSeconds(ss, craftWeaponRule->getAggressiveReload(), \"reloadAggressive\");\n\n\taddRule(ss, craftWeaponRule->getLauncherItem(), \"launcher\");\n\taddInteger(ss, craftWeaponRule->getWeaponType(), \"weaponType\");\n\n\taddRule(ss, craftWeaponRule->getClipItem(), \"clip\");\n\taddInteger(ss, craftWeaponRule->getAmmoMax(), \"ammoMax\");\n\taddInteger(ss, craftWeaponRule->getRearmRate(), \"rearmRate\", 1);\n\taddBoolean(ss, craftWeaponRule->useStatisticalBulletSaving(), \"bulletSaving\");\n\n\taddHeading(\"stats\");\n\t{\n\t\taddInteger(ss, craftWeaponRule->getBonusStats().damageMax, \"damageMax\");\n\t\taddInteger(ss, craftWeaponRule->getBonusStats().armor, \"armor\");\n\t\taddIntegerPercent(ss, craftWeaponRule->getBonusStats().avoidBonus, \"avoidBonus\");\n\t\taddIntegerPercent(ss, craftWeaponRule->getBonusStats().avoidBonus2, \"avoidBonus2\");\n\t\taddIntegerPercent(ss, craftWeaponRule->getBonusStats().powerBonus, \"powerBonus\");\n\t\taddIntegerPercent(ss, craftWeaponRule->getBonusStats().hitBonus, \"hitBonus\");\n\t\taddInteger(ss, craftWeaponRule->getBonusStats().fuelMax, \"fuelMax\");\n\t\taddIntegerKnots(ss, craftWeaponRule->getBonusStats().speedMax, \"speedMax\");\n\t\taddInteger(ss, craftWeaponRule->getBonusStats().accel, \"accel\");\n\t\taddIntegerNauticalMiles(ss, craftWeaponRule->getBonusStats().radarRange, \"radarRange\");\n\t\taddIntegerPercent(ss, craftWeaponRule->getBonusStats().radarChance, \"radarChance\");\n\t\taddIntegerNauticalMiles(ss, craftWeaponRule->getBonusStats().sightRange, \"sightRange\");\n\t\taddInteger(ss, craftWeaponRule->getBonusStats().shieldCapacity, \"shieldCapacity\");\n\t\taddInteger(ss, craftWeaponRule->getBonusStats().shieldRecharge, \"shieldRecharge\");\n\t\taddInteger(ss, craftWeaponRule->getBonusStats().shieldRechargeInGeoscape, \"shieldRechargeInGeoscape\");\n\t\taddInteger(ss, craftWeaponRule->getBonusStats().shieldBleedThrough, \"shieldBleedThrough\");\n\t\taddInteger(ss, craftWeaponRule->getBonusStats().soldiers, \"soldiers\");\n\t\taddInteger(ss, craftWeaponRule->getBonusStats().vehicles, \"vehicles\");\n\t\taddInteger(ss, craftWeaponRule->getBonusStats().maxItems, \"maxItems\", 0);\n\t\taddDouble(ss, craftWeaponRule->getBonusStats().maxStorageSpace, \"maxStorageSpace\", 0.0);\n\t\tendHeading();\n\t}\n\n\taddBoolean(ss, craftWeaponRule->isWaterOnly(), \"underwaterOnly\");\n\n\tif (craftWeaponRule->getStandardReload() > 0)\n\t{\n\t\taddHeading(\"_calculatedValues\");\n\t\tif (craftWeaponRule->unifiedDamageFormula())\n\t\t{\n\t\t\tconst RuleItem* damageItem = craftWeaponRule->getClipItem() ? craftWeaponRule->getClipItem() : craftWeaponRule->getLauncherItem();\n\n\t\t\tstd::ostringstream ss2;\n\t\t\tss2 << damageItem->getDamageType()->getRandomDamage(craftWeaponRule->getDamage(), 1);\n\t\t\tss2 << \"-\";\n\t\t\tss2 << damageItem->getDamageType()->getRandomDamage(craftWeaponRule->getDamage(), 2);\n\t\t\taddSingleString(ss, ss2.str(), \"_damageRangeBasic\", \"\", false);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// (damage) * (50-100% damage spread), not considering craft `powerBonus`\n\t\t\tstd::ostringstream ss2;\n\t\t\tss2 << craftWeaponRule->getDamage() / 2;\n\t\t\tss2 << \"-\";\n\t\t\tss2 << craftWeaponRule->getDamage();\n\t\t\taddSingleString(ss, ss2.str(), \"_damageRangeBasic\", \"\", false);\n\n\t\t\t// (damage / standard reload * 60) * (accuracy / 100) * (50-100% damage spread)\n\t\t\tint avgDPM = craftWeaponRule->getDamage() * craftWeaponRule->getAccuracy() * 60 * 3 / 4 / craftWeaponRule->getStandardReload() / 100;\n\t\t\taddInteger(ss, avgDPM, \"_averageDPM\");\n\n\t\t\t// (damage * ammoMax) * (accuracy / 100) * (50-100% damage spread)\n\t\t\tint avgTotalDamage = craftWeaponRule->getDamage() * craftWeaponRule->getAmmoMax() * craftWeaponRule->getAccuracy() * 3 / 4 / 100;\n\t\t\taddInteger(ss, avgTotalDamage, \"_averageTotalDamage\");\n\t\t}\n\t\tendHeading();\n\t}\n\n\tif (_showDebug)\n\t{\n\t\taddSection(\"{Modding section}\", \"You don't need this info as a player\", _white, true);\n\n\t\taddSection(\"{Naming}\", \"\", _white);\n\t\taddSingleString(ss, craftWeaponRule->getType(), \"type\");\n\t\taddSingleString(ss, craftWeaponRule->getUfopediaType(), \"ufopediaType\");\n\t\taddBoolean(ss, craftWeaponRule->getHidePediaInfo(), \"hidePediaInfo\");\n\n\t\taddSection(\"{Visuals}\", \"\", _white);\n\t\taddInteger(ss, craftWeaponRule->getProjectileType(), \"projectileType\", CWPT_CANNON_ROUND); // FIXME: CraftWeaponProjectileType ?\n\t\taddInteger(ss, craftWeaponRule->getProjectileSpeed(), \"projectileSpeed\");\n\n\t\taddInteger(ss, craftWeaponRule->getSprite() + 5, \"_sprite (Dogfight)\", 4);\n\t\taddSpriteResourcePath(ss, mod, \"INTICON.PCK\", craftWeaponRule->getSprite() + 5);\n\t\taddInteger(ss, craftWeaponRule->getSprite() + 48, \"_sprite (Base)\", 47);\n\t\taddSpriteResourcePath(ss, mod, \"BASEBITS.PCK\", craftWeaponRule->getSprite() + 48);\n\n\t\taddSection(\"{Sounds}\", \"\", _white);\n\t\taddInteger(ss, craftWeaponRule->getSound(), \"sound\", -1);\n\t\tstd::vector<int> tmpSoundVector;\n\t\ttmpSoundVector.push_back(craftWeaponRule->getSound());\n\t\taddSoundVectorResourcePaths(ss, mod, \"GEO.CAT\", tmpSoundVector);\n\n\t\taddSection(\"{Mod info}\", \"\", _white);\n\t\t{\n\t\t\taddSingleString(ss, mod->getModCreatingRule(craftWeaponRule)->name, \"createdByMod\");\n\t\t\taddSingleString(ss, mod->getModLastUpdatingRule(craftWeaponRule)->name, \"updatedByMod\");\n\t\t\tendHeading();\n\t\t}\n\t}\n}\n\n/**\n * Shows the \"raw\" RuleSoldier data.\n */\nvoid StatsForNerdsState::initSoldierList()\n{\n\t_lstRawData->clearList();\n\t_lstRawData->setIgnoreSeparators(true);\n\n\tstd::ostringstream ssTopic;\n\tssTopic << tr(_topicId);\n\tif (_showIds)\n\t{\n\t\tssTopic << \" [\" << _topicId << \"]\";\n\t}\n\n\t_txtArticle->setText(tr(\"STR_ARTICLE\").arg(ssTopic.str()));\n\n\tMod* mod = _game->getMod();\n\tRuleSoldier* soldierRule = mod->getSoldier(_topicId);\n\tif (!soldierRule)\n\t\treturn;\n\n\t_filterOptions.clear();\n\t_cbxRelatedStuff->setVisible(false);\n\n\tstd::ostringstream ss;\n\n\taddBoolean(ss, soldierRule->getAllowPiloting(), \"allowPiloting\", true);\n\n\taddRule(ss, soldierRule->getDefaultArmor(), \"armor\");\n\taddRule(ss, soldierRule->getSpecialWeapon(), \"specialWeapon\");\n\n\taddVectorOfStrings(ss, soldierRule->getRequirements(), \"requires\");\n\taddVectorOfStrings(ss, mod->getBaseFunctionNames(soldierRule->getRequiresBuyBaseFunc()), \"requiresBuyBaseFunc\");\n\taddSingleString(ss, soldierRule->getRequiresBuyCountry(), \"requiresBuyCountry\");\n\n\taddInteger(ss, soldierRule->getBuyCost(), \"costBuy\", 0, true);\n\taddInteger(ss, soldierRule->getMonthlyBuyLimit(), \"monthlyBuyLimit\");\n\n\tint time = soldierRule->getTransferTime();\n\tif (time == 0)\n\t\ttime = _game->getMod()->getPersonnelTime();\n\n\taddInteger(ss, time, \"transferTime\"); // not raw!\n\n\tint baseCost = soldierRule->getSalaryCost(0);\n\taddInteger(ss, baseCost, \"costSalary\", 0, true);\n\taddInteger(ss, soldierRule->getSalaryCost(1) - baseCost, \"costSalarySquaddie\", 0, true);\n\taddInteger(ss, soldierRule->getSalaryCost(2) - baseCost, \"costSalarySergeant\", 0, true);\n\taddInteger(ss, soldierRule->getSalaryCost(3) - baseCost, \"costSalaryCaptain\", 0, true);\n\taddInteger(ss, soldierRule->getSalaryCost(4) - baseCost, \"costSalaryColonel\", 0, true);\n\taddInteger(ss, soldierRule->getSalaryCost(5) - baseCost, \"costSalaryCommander\", 0, true);\n\n\tif (_showDebug)\n\t{\n\t\taddSection(\"{Modding section}\", \"You don't need this info as a player\", _white, true);\n\n\t\taddSection(\"{Naming}\", \"\", _white);\n\t\taddSingleString(ss, soldierRule->getType(), \"type\");\n\t\taddBoolean(ss, soldierRule->getShowTypeInInventory(), \"showTypeInInventory\");\n\t\taddInteger(ss, soldierRule->getNames().size(), \"soldierNames*\"); // size only\n\t\taddInteger(ss, soldierRule->getFemaleFrequency(), \"femaleFrequency\", 50);\n\t\taddInteger(ss, soldierRule->getStatStrings().size(), \"statStrings*\"); // size only\n\n\t\taddInteger(ss, soldierRule->getRankStrings().size(), \"rankStrings*\"); // size only\n\t\taddBoolean(ss, soldierRule->getAllowPromotion(), \"allowPromotion\", true);\n\n\t\taddSingleString(ss, soldierRule->getMonthlyBuyLimitMessage(), \"monthlyBuyLimitMessage\");\n\n\t\taddSection(\"{Stats}\", \"\", _white);\n\t\taddBoolean(ss, !soldierRule->getSpawnedSoldierTemplate().yaml.empty(), \"spawnedSoldier*\"); // just say if there are any or not\n\n\t\taddInteger(ss, soldierRule->getStandHeight(), \"standHeight\");\n\t\taddInteger(ss, soldierRule->getKneelHeight(), \"kneelHeight\");\n\t\taddInteger(ss, soldierRule->getFloatHeight(), \"floatHeight\");\n\t\taddInteger(ss, soldierRule->getMoraleLossWhenKilled(), \"moraleLossWhenKilled\", 100);\n\t\taddInteger(ss, soldierRule->getValue(), \"value\", 20);\n\n\t\taddUnitStatBonus(ss, soldierRule->getMinStats(), \"minStats\");\n\t\taddUnitStatBonus(ss, soldierRule->getMaxStats(), \"maxStats\");\n\t\taddUnitStatBonus(ss, soldierRule->getStatCaps(), \"statCaps\");\n\t\taddUnitStatBonus(ss, soldierRule->getTrainingStatCaps(), \"trainingStatCaps\");\n\n\t\taddUnitStatBonus(ss, soldierRule->getDogfightExperience(), \"dogfightExperience\");\n\n\t\taddSection(\"{Other}\", \"\", _white);\n\t\taddInteger(ss, soldierRule->getGroup(), \"group\");\n\t\taddInteger(ss, soldierRule->getSkills().size(), \"skills*\"); // size only\n\n\t\taddSection(\"{Visuals}\", \"\", _white);\n\t\taddRule(ss, soldierRule->getDefaultArmor(), \"armorForAvatar\");\n\t\taddInteger(ss, soldierRule->getAvatarOffsetX(), \"avatarOffsetX\", 67);\n\t\taddInteger(ss, soldierRule->getAvatarOffsetY(), \"avatarOffsetY\", 48);\n\t\taddInteger(ss, soldierRule->getFlagOffset(), \"flagOffset\");\n\n\t\taddInteger(ss, soldierRule->getRankSprite(), \"rankSprite\", 42);\n\t\taddSpriteResourcePath(ss, mod, \"BASEBITS.PCK\", soldierRule->getRankSprite());\n\t\taddInteger(ss, soldierRule->getRankSpriteBattlescape(), \"rankBattleSprite\", 20);\n\t\taddSpriteResourcePath(ss, mod, \"SMOKE.PCK\", soldierRule->getRankSpriteBattlescape());\n\t\taddInteger(ss, soldierRule->getRankSpriteTiny(), \"rankTinySprite\", -1); // always show\n\t\taddSpriteResourcePath(ss, mod, \"TinyRanks\", soldierRule->getRankSpriteTiny());\n\t\taddInteger(ss, soldierRule->getSkillIconSprite(), \"skillIconSprite\", 1);\n\t\taddSpriteResourcePath(ss, mod, \"SPICONS.DAT\", soldierRule->getSkillIconSprite());\n\n\t\taddSection(\"{Sounds}\", \"\", _white);\n\t\taddVectorOfIntegers(ss, soldierRule->getMaleDeathSounds(), \"deathMale\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", soldierRule->getMaleDeathSounds());\n\t\taddVectorOfIntegers(ss, soldierRule->getFemaleDeathSounds(), \"deathFemale\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", soldierRule->getFemaleDeathSounds());\n\t\taddVectorOfIntegers(ss, soldierRule->getMaleSelectUnitSounds(), \"selectUnitMale\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", soldierRule->getMaleSelectUnitSounds());\n\t\taddVectorOfIntegers(ss, soldierRule->getFemaleSelectUnitSounds(), \"selectUnitFemale\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", soldierRule->getFemaleSelectUnitSounds());\n\t\taddVectorOfIntegers(ss, soldierRule->getMaleStartMovingSounds(), \"startMovingMale\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", soldierRule->getMaleStartMovingSounds());\n\t\taddVectorOfIntegers(ss, soldierRule->getFemaleStartMovingSounds(), \"startMovingFemale\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", soldierRule->getFemaleStartMovingSounds());\n\t\taddVectorOfIntegers(ss, soldierRule->getMaleSelectWeaponSounds(), \"selectWeaponMale\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", soldierRule->getMaleSelectWeaponSounds());\n\t\taddVectorOfIntegers(ss, soldierRule->getFemaleSelectWeaponSounds(), \"selectWeaponFemale\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", soldierRule->getFemaleSelectWeaponSounds());\n\t\taddVectorOfIntegers(ss, soldierRule->getMaleAnnoyedSounds(), \"annoyedMale\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", soldierRule->getMaleAnnoyedSounds());\n\t\taddVectorOfIntegers(ss, soldierRule->getFemaleAnnoyedSounds(), \"annoyedFemale\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", soldierRule->getFemaleAnnoyedSounds());\n\t\taddVectorOfIntegers(ss, soldierRule->getMalePanicSounds(), \"panicMale\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", soldierRule->getMalePanicSounds());\n\t\taddVectorOfIntegers(ss, soldierRule->getFemalePanicSounds(), \"panicFemale\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", soldierRule->getFemalePanicSounds());\n\t\taddVectorOfIntegers(ss, soldierRule->getMaleBerserkSounds(), \"berserkMale\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", soldierRule->getMaleBerserkSounds());\n\t\taddVectorOfIntegers(ss, soldierRule->getFemaleBerserkSounds(), \"berserkFemale\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", soldierRule->getFemaleBerserkSounds());\n\n\t\taddSection(\"{Mod info}\", \"\", _white);\n\t\t{\n\t\t\taddSingleString(ss, mod->getModCreatingRule(soldierRule)->name, \"createdByMod\");\n\t\t\taddSingleString(ss, mod->getModLastUpdatingRule(soldierRule)->name, \"updatedByMod\");\n\t\t\tendHeading();\n\t\t}\n\t}\n}\n\n/**\n * Shows the \"raw\" Unit/RuleUnit data.\n */\nvoid StatsForNerdsState::initUnitList()\n{\n\t_lstRawData->clearList();\n\t_lstRawData->setIgnoreSeparators(true);\n\n\tstd::ostringstream ssTopic;\n\tssTopic << tr(_topicId);\n\tif (_showIds)\n\t{\n\t\tssTopic << \" [\" << _topicId << \"]\";\n\t}\n\n\t_txtArticle->setText(tr(\"STR_ARTICLE\").arg(ssTopic.str()));\n\n\tMod* mod = _game->getMod();\n\tUnit* unitRule = mod->getUnit(_topicId);\n\tif (!unitRule)\n\t\treturn;\n\n\t_filterOptions.clear();\n\t_cbxRelatedStuff->setVisible(false);\n\n\tstd::ostringstream ss;\n\n\taddSingleString(ss, unitRule->getRace(), \"race\");\n\taddSingleString(ss, unitRule->getRank(), \"rank\");\n\n\taddRule(ss, unitRule->getArmor(), \"armor\");\n\taddSpecialAbility(ss, (SpecialAbility)unitRule->getSpecialAbility(), \"specab\");\n\taddBoolean(ss, unitRule->isLivingWeapon(), \"livingWeapon\");\n\taddSingleString(ss, unitRule->getMeleeWeapon(), \"meleeWeapon\");\n\taddSingleString(ss, unitRule->getPsiWeapon(), \"psiWeapon\", \"ALIEN_PSI_WEAPON\");\n\n\taddBoolean(ss, !unitRule->getBuiltInWeapons().empty(), \"_builtInWeaponSets\"); // just say if there are any or not\n\taddBoolean(ss, !unitRule->getWeightedBuiltInWeapons().empty(), \"_weightedBuiltInWeaponSets\"); // just say if there are any or not\n\n\taddRule(ss, unitRule->getSpawnUnit(), \"spawnUnit\");\n\n\tbool capturableTotal = unitRule->getCapturable() && unitRule->getArmor()->getCorpseBattlescape().front()->isRecoverable() && !unitRule->getSpawnUnit();\n\taddBoolean(ss, capturableTotal, \"_capturable\", true);\n\n\taddBoolean(ss, unitRule->getCapturable(), \"capturable\", true);\n\taddBoolean(ss, unitRule->canSurrender(), \"canSurrender\", false);\n\taddBoolean(ss, unitRule->autoSurrender(), \"autoSurrender\", false);\n\n\taddInteger(ss, unitRule->getSpotterDuration(), \"spotter\"); // not raw!\n\taddInteger(ss, unitRule->getSniperPercentage(), \"sniper\");\n\n\tif (_showDebug)\n\t{\n\t\taddSection(\"{Modding section}\", \"You don't need this info as a player\", _white, true);\n\n\t\taddSection(\"{Naming}\", \"\", _white);\n\t\taddSingleString(ss, unitRule->getType(), \"type\");\n\t\taddRule(ss, unitRule->getLiveAlienGeoscape(), \"liveAlien\");\n\t\taddInteger(ss, unitRule->getShowFullNameInAlienInventory(mod), \"showFullNameInAlienInventory\"); // not raw!\n\n\t\taddSection(\"{Stats}\", \"\", _white);\n\t\taddInteger(ss, unitRule->getStandHeight(), \"standHeight\");\n\t\taddInteger(ss, unitRule->getKneelHeight(), \"kneelHeight\");\n\t\taddInteger(ss, unitRule->getFloatHeight(), \"floatHeight\");\n\t\taddInteger(ss, unitRule->getMoraleLossWhenKilled(), \"moraleLossWhenKilled\", 100);\n\t\taddInteger(ss, unitRule->getBerserkChance(), \"berserkChance\", -1);\n\t\taddInteger(ss, unitRule->getEnergyRecovery(), \"energyRecovery\", 30);\n\n\t\taddUnitStatBonus(ss, *unitRule->getStats(), \"stats\");\n\n\t\taddSection(\"{Flags}\", \"\", _white);\n\t\taddBoolean(ss, unitRule->canPanic(), \"canPanic\", true);\n\t\taddBoolean(ss, unitRule->canBeMindControlled(), \"canBeMindControlled\", true);\n\t\taddBoolean(ss, unitRule->isIgnoredByAI(), \"ignoredByAI\", false);\n\t\taddBoolean(ss, unitRule->isCosmetic(), \"cosmetic\");\n\t\taddBoolean(ss, unitRule->isVIP(), \"vip\");\n\n\t\taddSection(\"{AI}\", \"\", _white);\n\t\taddInteger(ss, unitRule->getIntelligence(), \"intelligence\");\n\t\taddInteger(ss, unitRule->getAggression(), \"aggression\");\n\t\taddInteger(ss, unitRule->getPickUpWeaponsMoreActively(), \"pickUpWeaponsMoreActively\", -1);\n\t\taddBoolean(ss, unitRule->isLeeroyJenkins(), \"isLeeroyJenkins\");\n\t\taddBoolean(ss, unitRule->avoidsFire(), \"avoidsFire\", true); // default \"_specab < SPECAB_BURNFLOOR\"\n\t\taddBoolean(ss, unitRule->waitIfOutsideWeaponRange(), \"waitIfOutsideWeaponRange\");\n\n\t\taddSection(\"{Debriefing}\", \"\", _white);\n\t\taddInteger(ss, unitRule->getValue(), \"value\", 0);\n\t\taddBoolean(ss, unitRule->isRecoverableAsCivilian(), \"civilianRecoveryType*\"); // just say if there are any or not\n\t\taddBoolean(ss, unitRule->isRecoverableAsScientist(), \"_recoverScientist\");\n\t\taddBoolean(ss, unitRule->isRecoverableAsEngineer(), \"_recoverEngineer\");\n\t\taddRule(ss, unitRule->getCivilianRecoveryItemType(), \"_recoverItem\");\n\t\taddRule(ss, unitRule->getCivilianRecoverySoldierType(), \"_recoverSoldier\");\n\t\taddSingleString(ss, unitRule->getSpawnedPersonName(), \"spawnedPersonName\");\n\t\taddBoolean(ss, !unitRule->getSpawnedSoldierTemplate().yaml.empty(), \"spawnedSoldier*\"); // just say if there are any or not\n\n\t\taddSection(\"{Sounds}\", \"\", _white);\n\t\taddInteger(ss, unitRule->getMoveSound(), \"moveSound\", -1);\n\t\tstd::vector<int> tmpSoundVector;\n\t\ttmpSoundVector.push_back(unitRule->getMoveSound());\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", tmpSoundVector);\n\t\taddVectorOfIntegers(ss, unitRule->getDeathSounds(), \"deathSound\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", unitRule->getDeathSounds());\n\t\taddVectorOfIntegers(ss, unitRule->getSelectUnitSounds(), \"selectUnitSound\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", unitRule->getSelectUnitSounds());\n\t\taddVectorOfIntegers(ss, unitRule->getStartMovingSounds(), \"startMovingSound\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", unitRule->getStartMovingSounds());\n\t\taddVectorOfIntegers(ss, unitRule->getSelectWeaponSounds(), \"selectWeaponSound\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", unitRule->getSelectWeaponSounds());\n\t\taddVectorOfIntegers(ss, unitRule->getAnnoyedSounds(), \"annoyedSound\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", unitRule->getAnnoyedSounds());\n\t\taddVectorOfIntegers(ss, unitRule->getPanicSounds(), \"panicSound\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", unitRule->getPanicSounds());\n\t\taddVectorOfIntegers(ss, unitRule->getBerserkSounds(), \"berserkSound\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", unitRule->getBerserkSounds());\n\t\taddVectorOfIntegers(ss, unitRule->getAggroSounds(), \"aggroSound\");\n\t\taddSoundVectorResourcePaths(ss, mod, \"BATTLE.CAT\", unitRule->getAggroSounds());\n\n\t\taddSection(\"{Mod info}\", \"\", _white);\n\t\t{\n\t\t\taddSingleString(ss, mod->getModCreatingRule(unitRule)->name, \"createdByMod\");\n\t\t\taddSingleString(ss, mod->getModLastUpdatingRule(unitRule)->name, \"updatedByMod\");\n\t\t\tendHeading();\n\t\t}\n\t}\n}\n\n\n////////////////////////////////////////////////////////////\n//\t\t\t\t\tScript binding\n////////////////////////////////////////////////////////////\n\nnamespace\n{\n\nstd::string debugDisplayScript(const StatsForNerdsState* sfn)\n{\n\tif (sfn)\n\t{\n\t\tstd::string s;\n\t\ts += StatsForNerdsState::ScriptName;\n\t\ts += \"(typeId: \";\n\t\ts += std::to_string((int)sfn->getTypeId());\n\t\ts += \" topicId: \\\"\";\n\t\ts += sfn->getTopicId();\n\t\ts += \"\\\")\";\n\t\treturn s;\n\t}\n\telse\n\t{\n\t\treturn \"null\";\n\t}\n}\n\n} // namespace\n\n\n/**\n * Register object in script parser.\n * @param parser Script parser.\n */\nvoid StatsForNerdsState::ScriptRegister(ScriptParserBase* parser)\n{\n\tparser->registerPointerType<Mod>();\n\tparser->registerPointerType<SavedGame>();\n\n\tBind<StatsForNerdsState> b = { parser };\n\n\tb.add<&StatsForNerdsState::addIntegerScript>(\"addIntRow\", \"add new row with first argument as name and second argument as value\");\n\tb.add<&StatsForNerdsState::addTextScript>(\"addTextRow\", \"add new row with first argument as name and second argument as text value to translate\");\n\tb.add<&StatsForNerdsState::addTextFormat1Script>(\"addTextFormatRow\", \"add new row with first argument as name and second argument as text format with one argument\");\n\tb.add<&StatsForNerdsState::addTextFormat2Script>(\"addTextFormatRow\", \"add new row with first argument as name and second argument as text format with two arguments\");\n\n\tb.addDebugDisplay<&debugDisplayScript>();\n}\n\nModScript::StatsForNerdsItemParser::StatsForNerdsItemParser(ScriptGlobal* shared, const std::string& name, Mod* mod) : ScriptParserEvents{ shared, name,\n\t\"rule\", \"stats_state\", \"geoscape_game\" }\n{\n\tBindBase b { this };\n\n\tb.addCustomPtr<const Mod>(\"rules\", mod);\n}\n\nModScript::StatsForNerdsArmorParser::StatsForNerdsArmorParser(ScriptGlobal* shared, const std::string& name, Mod* mod) : ScriptParserEvents{ shared, name,\n\t\"rule\", \"stats_state\", \"geoscape_game\" }\n{\n\tBindBase b { this };\n\n\tb.addCustomPtr<const Mod>(\"rules\", mod);\n}\n\nModScript::StatsForNerdsCraftParser::StatsForNerdsCraftParser(ScriptGlobal* shared, const std::string& name, Mod* mod) : ScriptParserEvents{ shared, name,\n\t\"rule\", \"stats_state\", \"geoscape_game\" }\n{\n\tBindBase b { this };\n\n\tb.addCustomPtr<const Mod>(\"rules\", mod);\n}\n\nModScript::StatsForNerdsUfoParser::StatsForNerdsUfoParser(ScriptGlobal* shared, const std::string& name, Mod* mod) : ScriptParserEvents{ shared, name,\n\t\"rule\", \"stats_state\", \"geoscape_game\" }\n{\n\tBindBase b { this };\n\n\tb.addCustomPtr<const Mod>(\"rules\", mod);\n}\n\n\n}\n"
  },
  {
    "path": "src/Ufopaedia/StatsForNerdsState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2018 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Battlescape/Position.h\"\n#include \"../Engine/State.h\"\n#include \"../Mod/ArticleDefinition.h\"\n#include \"../Mod/Armor.h\"\n#include \"../Mod/MapData.h\"\n#include \"../Mod/RuleDamageType.h\"\n#include \"../Mod/RuleItem.h\"\n#include \"../Savegame/BattleUnit.h\"\n\nnamespace OpenXcom\n{\n\nclass Window;\nclass Text;\nclass ComboBox;\nclass TextList;\nclass ToggleTextButton;\nclass TextButton;\nclass ScriptParserBase;\nstruct ArticleCommonState;\nstruct ArmorMoveCost;\ntemplate<typename T, typename I> class ScriptValues;\n\n/**\n * A screen, where you can see the (almost) raw ruleset corresponding to the given Ufopedia article.\n */\nclass StatsForNerdsState : public State\n{\nprivate:\n\tWindow *_window;\n\tText *_txtTitle;\n\tComboBox *_cbxRelatedStuff;\n\tText *_txtArticle;\n\tTextButton *_btnPrev, *_btnNext;\n\tTextList *_lstRawData;\n\tToggleTextButton *_btnIncludeDebug, *_btnIncludeIds, *_btnIncludeDefaults;\n\tTextButton *_btnOk;\n\tTextButton *_btnPreview;\n\n\tUint8 _purple, _pink, _blue, _white, _gold;\n\n\tUfopaediaTypeId _typeId;\n\tstd::string _topicId;\n\tbool _mainArticle;\n\n\tstd::shared_ptr<ArticleCommonState> _state;\n\tstd::vector<std::string> _filterOptions;\n\tbool _showDebug, _showIds, _showDefaults;\n\tint _counter;\n\tbool _indent;\n\n\tvoid buildUI(bool debug, bool ids, bool defaults);\n\tvoid initLists();\n\tvoid resetStream(std::ostringstream &ss);\n\tvoid addTranslation(std::ostringstream &ss, const std::string &id);\n\tstd::string trp(const std::string &propertyName);\n\tvoid addSection(const std::string &name, const std::string &desc, Uint8 color, bool forceShow = false);\n\tvoid addHeading(const std::string &propertyName, const std::string &moreDetail = \"\", bool addDifficulty = false);\n\tvoid endHeading();\n\n\ttemplate<typename T, typename Callback>\n\tvoid addVectorOfGeneric(std::ostringstream &ss, const std::vector<T> &vec, const std::string &propertyName, Callback&& func, bool translate = true);\n\n\tvoid addSingleString(std::ostringstream &ss, const std::string &id, const std::string &propertyName, const std::string &defaultId = \"\", bool translate = true);\n\tvoid addVectorOfStrings(std::ostringstream &ss, const std::vector<std::string> &vec, const std::string &propertyName, bool translate = true);\n\n\tvoid addVectorOfResearch(std::ostringstream &ss, const std::vector<const RuleResearch *> &vec, const std::string &propertyName);\n\n\ttemplate<typename T>\n\tvoid addRule(std::ostringstream &ss, T* rule, const std::string &propertyName);\n\ttemplate<typename T>\n\tvoid addRuleId(std::ostringstream &ss, T* rule, const std::string &propertyName);\n\ttemplate<typename T>\n\tvoid addRuleNamed(std::ostringstream &ss, T* rule, const std::string &propertyName);\n\n\ttemplate<typename T>\n\tvoid addVectorOfRules(std::ostringstream &ss, const std::vector<T*> &vec, const std::string &propertyName);\n\ttemplate<typename T>\n\tvoid addVectorOfRulesId(std::ostringstream &ss, const std::vector<T*> &vec, const std::string &propertyName);\n\ttemplate<typename T>\n\tvoid addVectorOfRulesNamed(std::ostringstream &ss, const std::vector<T*> &vec, const std::string &propertyName);\n\n\ttemplate<typename T, typename I>\n\tvoid addScriptTags(std::ostringstream &ss, const ScriptValues<T, I> &vec);\n\n\tvoid addIntegerScript(const std::string &propertyName, const int &value);\n\tvoid addTextScript(const std::string &propertyName, const std::string &value);\n\tvoid addTextFormat1Script(const std::string &propertyName, const std::string &format, const int &value1);\n\tvoid addTextFormat2Script(const std::string &propertyName, const std::string &format, const int &value1, const int &value2);\n\n\tvoid addBoolean(std::ostringstream &ss, const bool &value, const std::string &propertyName, const bool &defaultvalue = false);\n\tvoid addFloat(std::ostringstream &ss, const float &value, const std::string &propertyName, const float &defaultvalue = 0.0f);\n\tvoid addFloatAsPercentage(std::ostringstream &ss, const float &value, const std::string &propertyName, const float &defaultvalue = 0.0f);\n\tvoid addDouble(std::ostringstream &ss, const double &value, const std::string &propertyName, const double &defaultvalue = 0.0);\n\tvoid addInteger(std::ostringstream &ss, const int &value, const std::string &propertyName, const int &defaultvalue = 0, bool formatAsMoney = false, const std::string &specialTranslation = \"\", const int &specialvalue = -1);\n\tvoid addIntegerScriptTag(std::ostringstream &ss, const int &value, const std::string &propertyName, const int &defaultvalue = 0);\n\tvoid addIntegerPercent(std::ostringstream &ss, const int &value, const std::string &propertyName, const int &defaultvalue = 0);\n\tvoid addIntegerNauticalMiles(std::ostringstream &ss, const int &value, const std::string &propertyName, const int &defaultvalue = 0);\n\tvoid addIntegerKnots(std::ostringstream &ss, const int &value, const std::string &propertyName, const int &defaultvalue = 0);\n\tvoid addIntegerKm(std::ostringstream &ss, const int &value, const std::string &propertyName, const int &defaultvalue = 0);\n\tvoid addIntegerSeconds(std::ostringstream &ss, const int &value, const std::string &propertyName, const int &defaultvalue = 0, const int &value2 = -1);\n\tvoid addVectorOfIntegers(std::ostringstream &ss, const std::vector<int> &vec, const std::string &propertyName);\n\tvoid addMapOfIntegers(std::ostringstream& ss, const std::map<int, int>& map, const std::string& propertyName);\n\tvoid addBattleType(std::ostringstream &ss, const BattleType &value, const std::string &propertyName, const BattleType &defaultvalue = BT_NONE);\n\tvoid addDamageType(std::ostringstream &ss, const ItemDamageType &value, const std::string &propertyName, const ItemDamageType &defaultvalue = DT_NONE);\n\tvoid addDamageRandomType(std::ostringstream &ss, const ItemDamageRandomType &value, const std::string &propertyName, const ItemDamageRandomType &defaultvalue = DRT_DEFAULT);\n\tvoid addBattleFuseType(std::ostringstream &ss, const BattleFuseType &value, const std::string &propertyName, const BattleFuseType &defaultvalue = BFT_NONE);\n\tvoid addRuleItemUseCostBasic(std::ostringstream &ss, const RuleItemUseCost &value, const std::string &propertyName, const int &defaultvalue = 0);\n\tvoid addBoolOrInteger(std::ostringstream &ss, const int &value, bool formatAsBoolean);\n\tvoid addPercentageSignOrNothing(std::ostringstream &ss, const int &value, bool smartFormat);\n\ttemplate<typename T>\n\tvoid addRuleItemUseCostFull(std::ostringstream &ss, const RuleItemUseRuleBase<T> &value, const std::string &propertyName, const RuleItemUseRuleBase<T> &defaultvalue = RuleItemUseRuleBase<T>(), bool smartFormat = false, const RuleItemUseFlat &formatBy = RuleItemUseFlat());\n\tvoid addBattleMediKitType(std::ostringstream &ss, const BattleMediKitType &value, const std::string &propertyName, const BattleMediKitType &defaultvalue = BMT_NORMAL);\n\tvoid addMediKitTargets(std::ostringstream& ss, const RuleItem* value, const std::string& propertyName, const int& defaultvalue);\n\tvoid addItemTargets(std::ostringstream& ss, const RuleItem* value, const std::string& propertyName, const int& defaultvalue);\n\tvoid addExperienceTrainingMode(std::ostringstream &ss, const ExperienceTrainingMode &value, const std::string &propertyName, const ExperienceTrainingMode &defaultvalue = ETM_DEFAULT);\n\tvoid addRuleStatBonus(std::ostringstream &ss, const RuleStatBonus &value, const std::string &propertyName);\n\tvoid addRuleArmorMoveCost(std::ostringstream &ss, const ArmorMoveCost &value, const std::string &propertyName, const ArmorMoveCost &defaultvalue = ArmorMoveCost());\n\tvoid addSpriteResourcePath(std::ostringstream &ss, Mod *mod, const std::string &resourceSetName, const int &resourceId);\n\tvoid addSoundVectorResourcePaths(std::ostringstream &ss, Mod *mod, const std::string &resourceSetName, const std::vector<int> &resourceIds);\n\tvoid initItemList();\n\n\tvoid addUnitStatFormatted(std::ostringstream &ss, const int &value, const std::string &label, bool &isFirst);\n\tvoid addUnitStatBonus(std::ostringstream &ss, const UnitStats &value, const std::string &propertyName);\n\tvoid addArmorDamageModifiers(std::ostringstream &ss, const std::vector<float> &vec, const std::string &propertyName);\n\tvoid addSpecialAbility(std::ostringstream &ss, const SpecialAbility &value, const std::string &propertyName, const SpecialAbility &defaultvalue = SPECAB_NONE);\n\tvoid addMovementType(std::ostringstream &ss, const MovementType &value, const std::string &propertyName, const MovementType &defaultvalue = MT_WALK);\n\tvoid addForcedTorso(std::ostringstream &ss, const ForcedTorso &value, const std::string &propertyName, const ForcedTorso &defaultvalue = TORSO_USE_GENDER);\n\tvoid addDrawingRoutine(std::ostringstream &ss, const int &value, const std::string &propertyName, const int &defaultvalue = 0);\n\tvoid initArmorList();\n\tvoid initSoldierBonusList();\n\n\tvoid addVectorOfPositions(std::ostringstream &ss, const std::vector<Position> &vec, const std::string &propertyName);\n\tvoid addBuildCostItem(std::ostringstream &ss, const std::pair<const std::string, std::pair<int, int> > &costItem);\n\tvoid addRightClickActionType(std::ostringstream &ss, const int &value, const std::string &propertyName, const int &defaultvalue = 0);\n\tvoid initFacilityList();\n\tvoid initCraftList();\n\n\tvoid addHuntMode(std::ostringstream &ss, const int &value, const std::string &propertyName, const int &defaultvalue = 0);\n\tvoid addHuntBehavior(std::ostringstream &ss, const int &value, const std::string &propertyName, const int &defaultvalue = 0);\n\tvoid initUfoList();\n\tvoid initCraftWeaponList();\n\n\tvoid initSoldierList();\n\tvoid initUnitList();\n\npublic:\n\t/// Name of class used in script.\n\tstatic constexpr const char *ScriptName = \"StatsForNerds\";\n\t/// Register all useful function used by script.\n\tstatic void ScriptRegister(ScriptParserBase* parser);\n\n\tstatic const std::map<std::string, std::string> translationMap;\n\tstatic const std::map<std::string, std::string> shortTranslationMap;\n\n\n\t/// Creates the StatsForNerdsState state.\n\tStatsForNerdsState(std::shared_ptr<ArticleCommonState> state, bool debug, bool ids, bool defaults);\n\tStatsForNerdsState(const UfopaediaTypeId typeId, const std::string topicId, bool debug, bool ids, bool defaults);\n\t/// Cleans up the StatsForNerdsState state.\n\t~StatsForNerdsState();\n\t/// Initializes the state.\n\tvoid init() override;\n\n\t/// Get ufopaedia type Id.\n\tUfopaediaTypeId getTypeId() const { return _typeId; }\n\t/// Get current topic Id.\n\tconst std::string& getTopicId() const { return _topicId; }\n\n\t/// Handler for selecting an item from the [Compatible ammo] combobox.\n\tvoid cbxAmmoSelect(Action *action);\n\t/// Handler for clicking the toggle buttons.\n\tvoid btnRefreshClick(Action *action);\n\t/// Handler for clicking the OK button.\n\tvoid btnOkClick(Action *action);\n\t/// Handler for clicking the [Preview] button.\n\tvoid btnPreviewClick(Action *action);\n\t/// Handler for clicking the [Previous] button.\n\tvoid btnPrevClick(Action *action);\n\t/// Handler for clicking the [Next] button.\n\tvoid btnNextClick(Action *action);\n\t/// Handler for clicking the [Scroll Up] button.\n\tvoid btnScrollUpClick(Action *action);\n\t/// Handler for clicking the [Scroll Down] button.\n\tvoid btnScrollDownClick(Action *action);\n};\n\n}\n"
  },
  {
    "path": "src/Ufopaedia/Ufopaedia.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"Ufopaedia.h\"\n#include \"UfopaediaStartState.h\"\n#include \"../Savegame/SavedGame.h\"\n#include \"../Savegame/Base.h\"\n#include \"../Savegame/Soldier.h\"\n#include \"../Savegame/SoldierDiary.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/ArticleDefinition.h\"\n#include \"ArticleState.h\"\n#include \"ArticleStateBaseFacility.h\"\n#include \"ArticleStateCraft.h\"\n#include \"ArticleStateCraftWeapon.h\"\n#include \"ArticleStateItem.h\"\n#include \"ArticleStateArmor.h\"\n#include \"ArticleStateSoldier.h\"\n#include \"ArticleStateText.h\"\n#include \"ArticleStateTextImage.h\"\n#include \"ArticleStateUfo.h\"\n#include \"ArticleStateUnit.h\"\n#include \"ArticleStateVehicle.h\"\n#include \"ArticleStateTFTD.h\"\n#include \"ArticleStateTFTDArmor.h\"\n#include \"ArticleStateTFTDVehicle.h\"\n#include \"ArticleStateTFTDItem.h\"\n#include \"ArticleStateTFTDFacility.h\"\n#include \"ArticleStateTFTDCraft.h\"\n#include \"ArticleStateTFTDCraftWeapon.h\"\n#include \"ArticleStateTFTDUso.h\"\n#include \"StatsForNerdsState.h\"\n#include \"../Engine/Game.h\"\n\nnamespace OpenXcom\n{\n\t/**\n\t * Checks, if an article has already been released.\n\t * @param save Pointer to saved game.\n\t * @param article Article definition to release.\n\t * @returns true, if the article is available.\n\t */\n\tbool Ufopaedia::isArticleAvailable(SavedGame *save, ArticleDefinition *article)\n\t{\n\t\tif (!article->disabledBy.empty())\n\t\t{\n\t\t\t// Note: yes, check for non-empty vector is necessary\n\t\t\tif (save->isResearched(article->disabledBy, false))\n\t\t\t{\n\t\t\t\treturn false; // article is disabled, i.e. not available\n\t\t\t}\n\t\t}\n\t\treturn save->isResearched(article->_requires);\n\t}\n\n\t/**\n\t * Gets the index of the selected article_id in the visible list.\n\t * If the id is not found, returns -1.\n\t * @param save Pointer to saved game.\n\t * @param mod Pointer to mod.\n\t * @param article_id Article id to find.\n\t * @returns Index of the given article id in the internal list, -1 if not found.\n\t */\n\tsize_t Ufopaedia::getArticleIndex(const ArticleDefinitionList& articles, const std::string &article_id)\n\t{\n\t\tstd::string UC_ID = article_id + \"_UC\";\n\t\tfor (size_t it=0; it<articles.size(); ++it)\n\t\t{\n\t\t\tif (articles[it]->id == article_id)\n\t\t\t{\n\t\t\t\treturn it;\n\t\t\t}\n\t\t}\n\t\tfor (size_t it = 0; it<articles.size(); ++it)\n\t\t{\n\t\t\tif (articles[it]->id == UC_ID)\n\t\t\t{\n\t\t\t\treturn it;\n\t\t\t}\n\t\t}\n\t\tfor (size_t it = 0; it<articles.size(); ++it)\n\t\t{\n\t\t\tfor (const auto& req : articles[it]->_requires)\n\t\t\t{\n\t\t\t\tif (article_id == req)\n\t\t\t\t{\n\t\t\t\t\treturn it;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn ArticleCommonState::invalid;\n\t}\n\n\t/**\n\t * Creates a new article state dependent on the given article definition.\n\t * @param game Pointer to actual game.\n\t * @param article Article definition to create from.\n\t * @returns Article state object if created, 0 otherwise.\n\t */\n\tArticleState *Ufopaedia::createArticleState(std::shared_ptr<ArticleCommonState> state)\n\t{\n\t\tArticleDefinition *article = state->getCurrentArticle();\n\t\tswitch (article->getType())\n\t\t{\n\t\t\tcase UFOPAEDIA_TYPE_UNIT:\n\t\t\t\treturn new ArticleStateUnit(dynamic_cast<ArticleDefinitionUnit *>(article), std::move(state));\n\t\t\tcase UFOPAEDIA_TYPE_SOLDIER:\n\t\t\t\treturn new ArticleStateSoldier(dynamic_cast<ArticleDefinitionSoldier *>(article), std::move(state));\n\t\t\tcase UFOPAEDIA_TYPE_CRAFT:\n\t\t\t\treturn new ArticleStateCraft(dynamic_cast<ArticleDefinitionCraft *>(article), std::move(state));\n\t\t\tcase UFOPAEDIA_TYPE_CRAFT_WEAPON:\n\t\t\t\treturn new ArticleStateCraftWeapon(dynamic_cast<ArticleDefinitionCraftWeapon *>(article), std::move(state));\n\t\t\tcase UFOPAEDIA_TYPE_VEHICLE:\n\t\t\t\treturn new ArticleStateVehicle(dynamic_cast<ArticleDefinitionVehicle *>(article), std::move(state));\n\t\t\tcase UFOPAEDIA_TYPE_ITEM:\n\t\t\t\treturn new ArticleStateItem(dynamic_cast<ArticleDefinitionItem *>(article), std::move(state));\n\t\t\tcase UFOPAEDIA_TYPE_ARMOR:\n\t\t\t\treturn new ArticleStateArmor(dynamic_cast<ArticleDefinitionArmor *>(article), std::move(state));\n\t\t\tcase UFOPAEDIA_TYPE_BASE_FACILITY:\n\t\t\t\treturn new ArticleStateBaseFacility(dynamic_cast<ArticleDefinitionBaseFacility *>(article), std::move(state));\n\t\t\tcase UFOPAEDIA_TYPE_TEXT:\n\t\t\t\treturn new ArticleStateText(dynamic_cast<ArticleDefinitionText *>(article), std::move(state));\n\t\t\tcase UFOPAEDIA_TYPE_TEXTIMAGE:\n\t\t\t\treturn new ArticleStateTextImage(dynamic_cast<ArticleDefinitionTextImage *>(article), std::move(state));\n\t\t\tcase UFOPAEDIA_TYPE_UFO:\n\t\t\t\treturn new ArticleStateUfo(dynamic_cast<ArticleDefinitionUfo *>(article), std::move(state));\n\t\t\tcase UFOPAEDIA_TYPE_TFTD:\n\t\t\t\treturn new ArticleStateTFTD(dynamic_cast<ArticleDefinitionTFTD *>(article), std::move(state));\n\t\t\tcase UFOPAEDIA_TYPE_TFTD_CRAFT:\n\t\t\t\treturn new ArticleStateTFTDCraft(dynamic_cast<ArticleDefinitionTFTD *>(article), std::move(state));\n\t\t\tcase UFOPAEDIA_TYPE_TFTD_CRAFT_WEAPON:\n\t\t\t\treturn new ArticleStateTFTDCraftWeapon(dynamic_cast<ArticleDefinitionTFTD *>(article), std::move(state));\n\t\t\tcase UFOPAEDIA_TYPE_TFTD_VEHICLE:\n\t\t\t\treturn new ArticleStateTFTDVehicle(dynamic_cast<ArticleDefinitionTFTD *>(article), std::move(state));\n\t\t\tcase UFOPAEDIA_TYPE_TFTD_ITEM:\n\t\t\t\treturn new ArticleStateTFTDItem(dynamic_cast<ArticleDefinitionTFTD *>(article), std::move(state));\n\t\t\tcase UFOPAEDIA_TYPE_TFTD_ARMOR:\n\t\t\t\treturn new ArticleStateTFTDArmor(dynamic_cast<ArticleDefinitionTFTD *>(article), std::move(state));\n\t\t\tcase UFOPAEDIA_TYPE_TFTD_BASE_FACILITY:\n\t\t\t\treturn new ArticleStateTFTDFacility(dynamic_cast<ArticleDefinitionTFTD *>(article), std::move(state));\n\t\t\tcase UFOPAEDIA_TYPE_TFTD_USO:\n\t\t\t\treturn new ArticleStateTFTDUso(dynamic_cast<ArticleDefinitionTFTD *>(article), std::move(state));\n\t\t\tdefault:\n\t\t\t\tthrow new Exception(\"Unknown type for article '\" + article->id + \"'\");\n\t\t}\n\t}\n\n\t/**\n\t * Set UPSaved index and open the new state.\n\t * @param game Pointer to actual game.\n\t * @param article Article definition of the article to open.\n\t */\n\tvoid Ufopaedia::openArticle(Game *game, ArticleDefinition *article)\n\t{\n\t\tauto state = createCommonArticleState(game->getSavedGame(), game->getMod());\n\t\tstate->current_index = getArticleIndex(state->articleList, article->id);\n\t\tif (state->current_index != ArticleCommonState::invalid)\n\t\t{\n\t\t\tgame->pushState(createArticleState(std::move(state)));\n\t\t}\n\t}\n\n\t/**\n\t * Checks if selected article_id is available -> if yes, open it.\n\t * @param game Pointer to actual game.\n\t * @param article_id Article id to find.\n\t */\n\tvoid Ufopaedia::openArticle(Game *game, const std::string &article_id)\n\t{\n\t\tauto state = createCommonArticleState(game->getSavedGame(), game->getMod());\n\t\tstate->current_index = getArticleIndex(state->articleList, article_id);\n\t\tif (state->current_index != ArticleCommonState::invalid)\n\t\t{\n\t\t\tgame->pushState(createArticleState(std::move(state)));\n\t\t}\n\t}\n\n\t/**\n\t * Checks if selected article_id is available -> if yes, open its (raw) details.\n\t * @param game Pointer to actual game.\n\t * @param article_id Article id to find.\n\t */\n\tvoid Ufopaedia::openArticleDetail(Game *game, const std::string &article_id)\n\t{\n\t\tauto state = createCommonArticleState(game->getSavedGame(), game->getMod());\n\t\tstate->current_index = getArticleIndex(state->articleList, article_id);\n\t\tif (state->current_index != ArticleCommonState::invalid)\n\t\t{\n\t\t\tgame->pushState(new StatsForNerdsState(std::move(state), false, false, false));\n\t\t}\n\t}\n\n\t/**\n\t * Open Ufopaedia start state, presenting the section selection buttons.\n\t * @param game Pointer to actual game.\n\t */\n\tvoid Ufopaedia::open(Game *game)\n\t{\n\t\tgame->pushState(new UfopaediaStartState);\n\t}\n\n\t/**\n\t * Open the next article in the list. Loops to the first.\n\t * @param game Pointer to actual game.\n\t */\n\tvoid Ufopaedia::next(Game *game, std::shared_ptr<ArticleCommonState> state)\n\t{\n\t\tif (state->isCurrentArticleHidden()) return;\n\t\tstate->nextArticlePage();\n\t\tgame->popState();\n\t\tgame->pushState(createArticleState(std::move(state)));\n\t}\n\n\t/**\n\t * Open the next article detail (Stats for Nerds) in the list. Loops to the first.\n\t * @param game Pointer to actual game.\n\t */\n\tvoid Ufopaedia::nextDetail(Game *game, std::shared_ptr<ArticleCommonState> state, bool debug, bool ids, bool defaults)\n\t{\n\t\tif (state->isCurrentArticleHidden()) return;\n\t\tstate->nextArticle();\n\t\tgame->popState();\n\t\tgame->pushState(new StatsForNerdsState(std::move(state), debug, ids, defaults));\n\t}\n\n\t/**\n\t * Open the previous article in the list. Loops to the last.\n\t * @param game Pointer to actual game.\n\t */\n\tvoid Ufopaedia::prev(Game *game, std::shared_ptr<ArticleCommonState> state)\n\t{\n\t\tif (state->isCurrentArticleHidden()) return;\n\t\tstate->prevArticlePage();\n\t\tgame->popState();\n\t\tgame->pushState(createArticleState(std::move(state)));\n\t}\n\n\t/**\n\t * Open the previous article detail (Stats for Nerds) in the list. Loops to the last.\n\t * @param game Pointer to actual game.\n\t */\n\tvoid Ufopaedia::prevDetail(Game *game, std::shared_ptr<ArticleCommonState> state, bool debug, bool ids, bool defaults)\n\t{\n\t\tif (state->isCurrentArticleHidden()) return;\n\t\tstate->prevArticle();\n\t\tgame->popState();\n\t\tgame->pushState(new StatsForNerdsState(std::move(state), debug, ids, defaults));\n\t}\n\n\t/**\n\t * Fill an ArticleList with the currently visible ArticleIds of the given section.\n\t * @param save Pointer to saved game.\n\t * @param mod Pointer to mod.\n\t * @param section Article section to find, e.g. \"XCOM Crafts & Armaments\", \"Alien Lifeforms\", etc.\n\t * @param data Article definition list object to fill data in.\n\t */\n\tvoid Ufopaedia::list(SavedGame *save, Mod *mod, const std::string &section, ArticleDefinitionList &data)\n\t{\n\t\tauto state = createCommonArticleState(save, mod);\n\t\tfor (auto* a : state->articleList)\n\t\t{\n\t\t\tif (a->section == section)\n\t\t\t{\n\t\t\t\tdata.push_back(a);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Check if this is an invisible commendation article.\n\t * @param save Pointer to saved game.\n\t * @param article Article to check.\n\t */\n\tbool Ufopaedia::isCommendationArticleInvisible(SavedGame *save, ArticleDefinition *article)\n\t{\n\t\t// show hidden Commendations entries if:\n\t\tif (article->hiddenCommendation)\n\t\t{\n\t\t\t// 1. debug mode is on\n\t\t\tif (save->getDebugMode())\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// 2. or if the article was opened already\n\t\t\tif (save->getUfopediaRuleStatus(article->id) != ArticleDefinition::PEDIA_STATUS_NEW)\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// 3. or if the medal was awarded at least once\n\t\t\tif (isAwardedCommendation(save, article))\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t/**\n\t * Check if the article corresponds to an awarded commendation.\n\t * @param save Pointer to saved game.\n\t * @param article Article to check.\n\t */\n\tbool Ufopaedia::isAwardedCommendation(SavedGame *save, ArticleDefinition *article)\n\t{\n\t\tif (article->section == UFOPAEDIA_COMMENDATIONS)\n\t\t{\n\t\t\t// 1. check living soldiers\n\t\t\tfor (auto* xbase : *save->getBases())\n\t\t\t{\n\t\t\t\tfor (auto* soldier : *xbase->getSoldiers())\n\t\t\t\t{\n\t\t\t\t\tfor (auto* comm : *soldier->getDiary()->getSoldierCommendations())\n\t\t\t\t\t{\n\t\t\t\t\t\tif (comm->getType() == article->getMainTitle())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// 2. check dead soldiers\n\t\t\tfor (std::vector<Soldier*>::reverse_iterator deadManIt = save->getDeadSoldiers()->rbegin(); deadManIt != save->getDeadSoldiers()->rend(); ++deadManIt)\n\t\t\t{\n\t\t\t\tfor (auto* comm : *(*deadManIt)->getDiary()->getSoldierCommendations())\n\t\t\t\t{\n\t\t\t\t\tif (comm->getType() == article->getMainTitle())\n\t\t\t\t\t{\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t/**\n\t * Return an ArticleList with all the currently visible ArticleIds.\n\t * @param save Pointer to saved game.\n\t * @param mod Pointer to mod.\n\t * @return List of visible ArticleDefinitions.\n\t */\n\tstd::shared_ptr<ArticleCommonState> Ufopaedia::createCommonArticleState(SavedGame *save, Mod *mod)\n\t{\n\t\tauto shared = std::make_shared<ArticleCommonState>();\n\t\tfor (const auto& articleName : mod->getUfopaediaList())\n\t\t{\n\t\t\tArticleDefinition *article = mod->getUfopaediaArticle(articleName);\n\t\t\tif (isArticleAvailable(save, article) && article->section != UFOPAEDIA_NOT_AVAILABLE && !isCommendationArticleInvisible(save, article))\n\t\t\t{\n\t\t\t\tshared->articleList.push_back(article);\n\t\t\t\tshared->articleStatusList.push_back(save->getUfopediaRuleStatus(articleName) == ArticleDefinition::PEDIA_STATUS_HIDDEN);\n\t\t\t}\n\t\t}\n\t\treturn shared;\n\t}\n\n}\n"
  },
  {
    "path": "src/Ufopaedia/Ufopaedia.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <vector>\n#include <string>\n#include <memory>\n\n#include \"ArticleState.h\"\n\nnamespace OpenXcom\n{\n\tclass Game;\n\tclass SavedGame;\n\tclass Mod;\n\tclass ArticleDefinition;\n\tclass ArticleState;\n\n\t/// definition of an article list\n\ttypedef std::vector<ArticleDefinition *> ArticleDefinitionList;\n\n\t// This section is meant for articles, that have to be activated,\n\t// but have no own entry in a list. E.g. Ammunition items.\n\t// Maybe others as well, that should just not be selectable.\n\tstatic const std::string UFOPAEDIA_NOT_AVAILABLE = \"STR_NOT_AVAILABLE\";\n\tstatic const std::string UFOPAEDIA_COMMENDATIONS = \"STR_COMMENDATIONS_UC\";\n\n\t/**\n\t * This static class encapsulates all functions related to Ufopaedia\n\t * for the game.\n\t * Main purpose is to open Ufopaedia from Geoscape, navigate between articles\n\t * and release new articles after successful research.\n\t */\n\n\tclass Ufopaedia\n\t{\n\tpublic:\n\t\t/// check, if a specific article is currently available.\n\t\tstatic bool isArticleAvailable(SavedGame *save, ArticleDefinition *article);\n\n\t\t/// open Ufopaedia on a certain entry.\n\t\tstatic void openArticle(Game *game, const std::string &article_id);\n\t\tstatic void openArticleDetail(Game *game, const std::string &article_id);\n\n\t\t/// open Ufopaedia article from a given article definition.\n\t\tstatic void openArticle(Game *game, ArticleDefinition *article);\n\n\t\t/// open Ufopaedia with selection dialog.\n\t\tstatic void open(Game *game);\n\n\t\t/// article navigation to next article.\n\t\tstatic void next(Game *game, std::shared_ptr<ArticleCommonState> state);\n\t\tstatic void nextDetail(Game *game, std::shared_ptr<ArticleCommonState> state, bool debug, bool ids, bool defaults);\n\n\t\t/// article navigation to previous article.\n\t\tstatic void prev(Game *game, std::shared_ptr<ArticleCommonState> state);\n\t\tstatic void prevDetail(Game *game, std::shared_ptr<ArticleCommonState> state, bool debug, bool ids, bool defaults);\n\n\t\t/// load a vector with article ids that are currently visible of a given section.\n\t\tstatic void list(SavedGame *save, Mod *rule, const std::string &section, ArticleDefinitionList &data);\n\n\t\t/// check if this is an invisible commendation article.\n\t\tstatic bool isCommendationArticleInvisible(SavedGame *save, ArticleDefinition *article);\n\n\t\t/// check if the article corresponds to an awarded commendation.\n\t\tstatic bool isAwardedCommendation(SavedGame *save, ArticleDefinition *article);\n\n\tprotected:\n\n\t\t/// get index of the given article id in the visible list.\n\t\tstatic size_t getArticleIndex(const ArticleDefinitionList& article, const std::string &article_id);\n\n\t\t/// get list of researched articles\n\t\tstatic std::shared_ptr<ArticleCommonState> createCommonArticleState(SavedGame *save, Mod *rule);\n\n\t\t/// create a new state object from article definition.\n\t\tstatic ArticleState *createArticleState(std::shared_ptr<ArticleCommonState> state);\n\t};\n}\n"
  },
  {
    "path": "src/Ufopaedia/UfopaediaSelectState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include <locale>\n#include \"Ufopaedia.h\"\n#include \"UfopaediaSelectState.h\"\n#include \"../Mod/ArticleDefinition.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Options.h\"\n#include \"../Engine/LocalizedText.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextEdit.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/ComboBox.h\"\n#include \"../Interface/TextList.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Mod/RuleInterface.h\"\n#include \"../Savegame/SavedGame.h\"\n\nnamespace OpenXcom\n{\n\tUfopaediaSelectState::UfopaediaSelectState(const std::string &section, int heightOffset, int windowOffset) : _section(section), _lstScroll(0)\n\t{\n\t\t_isCommendationsSection = (_section == UFOPAEDIA_COMMENDATIONS);\n\t\t_screen = false;\n\n\t\t// set background window\n\t\t_window = new Window(this, 256, 180 + heightOffset, 32, 10 - windowOffset, POPUP_NONE);\n\t\t_window->setInnerColor(239); // almost black = darkest index from backpals.dat\n\t\t_btnQuickSearch = new TextEdit(this, 48, 9, 48, 30 - windowOffset);\n\n\t\t// set title\n\t\t_txtTitle = new Text(224, 17, 48, 26 - windowOffset);\n\n\t\t// set buttons\n\t\t_btnOk = new TextButton(108, 16, 164, 166 - windowOffset + heightOffset);\n\t\t_cbxFilter = new ComboBox(this, 108, 16, 48, 166 - windowOffset + heightOffset, true);\n\t\tint listHeightOffset = (heightOffset / 8) * 8; // multiple of 8\n\t\t_lstSelection = new TextList(224, 104 + listHeightOffset, 40, 50 - windowOffset);\n\n\t\t// Set palette\n\t\tsetInterface(\"ufopaedia\");\n\n\t\tadd(_window, \"window\", \"ufopaedia\");\n\t\tadd(_btnQuickSearch, \"button2\", \"ufopaedia\");\n\t\tadd(_txtTitle, \"text\", \"ufopaedia\");\n\t\tadd(_btnOk, \"button2\", \"ufopaedia\");\n\t\tadd(_lstSelection, \"list\", \"ufopaedia\");\n\t\tadd(_cbxFilter, \"button2\", \"ufopaedia\");\n\n\t\t_colorNormal = _lstSelection->getColor();\n\t\t_colorNew = Options::oxceHighlightNewTopics ? _lstSelection->getSecondaryColor() : _colorNormal;\n\t\t_colorHidden = _game->getMod()->getInterface(\"ufopaedia\")->getElement(\"listExtended\")->color;\n\n\t\tcenterAllSurfaces();\n\n\t\tsetWindowBackground(_window, \"ufopaedia\");\n\n\t\t_txtTitle->setBig();\n\t\t_txtTitle->setAlign(ALIGN_CENTER);\n\t\t_txtTitle->setText(tr(\"STR_SELECT_ITEM\"));\n\n\t\t_btnOk->setText(tr(\"STR_OK\"));\n\t\t_btnOk->onMouseClick((ActionHandler)&UfopaediaSelectState::btnOkClick);\n\t\t_btnOk->onKeyboardPress((ActionHandler)&UfopaediaSelectState::btnOkClick,Options::keyCancel);\n\t\t_btnOk->onKeyboardPress((ActionHandler)&UfopaediaSelectState::btnMarkAllAsSeenClick, Options::keyMarkAllAsSeen);\n\n\t\t_lstSelection->setColumns(1, 206);\n\t\t_lstSelection->setSelectable(true);\n\t\t_lstSelection->setBackground(_window);\n\t\t_lstSelection->setMargin(18);\n\t\t_lstSelection->setAlign(ALIGN_CENTER);\n\t\t_lstSelection->onMouseClick((ActionHandler)&UfopaediaSelectState::lstSelectionClick, SDL_BUTTON_LEFT);\n\t\t_lstSelection->onMouseClick((ActionHandler)&UfopaediaSelectState::lstSelectionClickRight, SDL_BUTTON_RIGHT);\n\n\t\tstd::vector<std::string> filterOptions;\n\t\tfilterOptions.push_back(\"STR_FILTER_DEFAULT\");\n\t\tfilterOptions.push_back(_isCommendationsSection ? \"STR_NOT_AWARDED_YET\" : \"STR_SHOW_ONLY_NEW\");\n\t\tfilterOptions.push_back(\"STR_FILTER_HIDDEN\");\n\t\t_cbxFilter->setOptions(filterOptions, true);\n\t\t_cbxFilter->onChange((ActionHandler)&UfopaediaSelectState::cbxFilterChange);\n\n\t\t_btnQuickSearch->setText(\"\"); // redraw\n\t\t_btnQuickSearch->onEnter((ActionHandler)&UfopaediaSelectState::btnQuickSearchApply);\n\t\t_btnQuickSearch->setVisible(Options::oxceQuickSearchButton);\n\n\t\t_btnOk->onKeyboardRelease((ActionHandler)&UfopaediaSelectState::btnQuickSearchToggle, Options::keyToggleQuickSearch);\n\t}\n\n\tUfopaediaSelectState::~UfopaediaSelectState()\n\t{}\n\n\t/**\n\t * Initializes the state.\n\t */\n\tvoid UfopaediaSelectState::init()\n\t{\n\t\tState::init();\n\t\tloadSelectionList(false);\n\t}\n\n\t/**\n\t * Returns to the previous screen.\n\t * @param action Pointer to an action.\n\t */\n\tvoid UfopaediaSelectState::btnOkClick(Action *)\n\t{\n\t\t_game->popState();\n\t}\n\n\t/**\n\t *\n\t * @param action Pointer to an action.\n\t */\n\tvoid UfopaediaSelectState::lstSelectionClick(Action *)\n\t{\n\t\t_lstScroll = _lstSelection->getScroll();\n\t\tUfopaedia::openArticle(_game, _filtered_article_list[_lstSelection->getSelectedRow()]);\n\t}\n\n\t/**\n\t * Toggles the topic status.\n\t * @param action Pointer to an action.\n\t */\n\tvoid UfopaediaSelectState::lstSelectionClickRight(Action *)\n\t{\n\t\t// change status\n\t\tconst std::string rule = _filtered_article_list[_lstSelection->getSelectedRow()]->id;\n\t\tint oldState = _game->getSavedGame()->getUfopediaRuleStatus(rule);\n\t\tint newState = (oldState + 1) % ArticleDefinition::PEDIA_STATUSES;\n\t\tif (!Options::oxceHighlightNewTopics)\n\t\t{\n\t\t\t// only switch between hidden and not hidden\n\t\t\tnewState = (oldState == ArticleDefinition::PEDIA_STATUS_HIDDEN) ? ArticleDefinition::PEDIA_STATUS_NORMAL : ArticleDefinition::PEDIA_STATUS_HIDDEN;\n\t\t}\n\t\t_game->getSavedGame()->setUfopediaRuleStatus(rule, newState);\n\n\t\tif (newState == ArticleDefinition::PEDIA_STATUS_HIDDEN)\n\t\t{\n\t\t\t_lstSelection->setRowColor(_lstSelection->getSelectedRow(), _colorHidden);\n\t\t}\n\t\telse if (newState == ArticleDefinition::PEDIA_STATUS_NEW)\n\t\t{\n\t\t\t_lstSelection->setRowColor(_lstSelection->getSelectedRow(), _colorNew);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_lstSelection->setRowColor(_lstSelection->getSelectedRow(), _colorNormal);\n\t\t}\n\t}\n\n\t/**\n\t* Quick search toggle.\n\t* @param action Pointer to an action.\n\t*/\n\tvoid UfopaediaSelectState::btnQuickSearchToggle(Action *action)\n\t{\n\t\tif (_btnQuickSearch->getVisible())\n\t\t{\n\t\t\t_btnQuickSearch->setText(\"\");\n\t\t\t_btnQuickSearch->setVisible(false);\n\t\t\tbtnQuickSearchApply(action);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_btnQuickSearch->setVisible(true);\n\t\t\t_btnQuickSearch->setFocus(true);\n\t\t}\n\t}\n\n\t/**\n\t* Quick search.\n\t* @param action Pointer to an action.\n\t*/\n\tvoid UfopaediaSelectState::btnQuickSearchApply(Action *)\n\t{\n\t\tloadSelectionList(false);\n\t}\n\n\t/**\n\t* Updates the list to match the filter.\n\t* @param action Pointer to an action.\n\t*/\n\tvoid UfopaediaSelectState::cbxFilterChange(Action *)\n\t{\n\t\tloadSelectionList(false);\n\t}\n\n\t/**\n\t* Marks all items as seen\n\t* @param action Pointer to an action.\n\t*/\n\tvoid UfopaediaSelectState::btnMarkAllAsSeenClick(Action *)\n\t{\n\t\tloadSelectionList(true);\n\t}\n\n\tvoid UfopaediaSelectState::loadSelectionList(bool markAllAsSeen)\n\t{\n\t\tstd::string searchString = _btnQuickSearch->getText();\n\t\tUnicode::upperCase(searchString);\n\n\t\t_lstSelection->clearList();\n\t\t_article_list.clear();\n\t\tUfopaedia::list(_game->getSavedGame(), _game->getMod(), _section, _article_list);\n\t\t_filtered_article_list.clear();\n\t\tsize_t selectedFilter = _cbxFilter->getSelected();\n\n\t\tint row = 0;\n\t\tbool hasUnseen = false;\n\t\tint ruleStatus = 0;\n\t\tfor (auto* articleDef : _article_list)\n\t\t{\n\t\t\truleStatus = _game->getSavedGame()->getUfopediaRuleStatus(articleDef->id);\n\n\t\t\t// filter\n\t\t\tif (selectedFilter == 0)\n\t\t\t{\n\t\t\t\tif (ruleStatus == ArticleDefinition::PEDIA_STATUS_HIDDEN)\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (selectedFilter == 2)\n\t\t\t{\n\t\t\t\tif (ruleStatus != ArticleDefinition::PEDIA_STATUS_HIDDEN)\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (selectedFilter == 1)\n\t\t\t{\n\t\t\t\tif (_isCommendationsSection)\n\t\t\t\t{\n\t\t\t\t\tif (Ufopaedia::isAwardedCommendation(_game->getSavedGame(), articleDef))\n\t\t\t\t\t{\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif (ruleStatus != ArticleDefinition::PEDIA_STATUS_NEW)\n\t\t\t\t\t{\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// quick search\n\t\t\tif (!searchString.empty())\n\t\t\t{\n\t\t\t\tstd::string projectName = tr(articleDef->getMainTitle());\n\t\t\t\tUnicode::upperCase(projectName);\n\t\t\t\tif (projectName.find(searchString) == std::string::npos)\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t_filtered_article_list.push_back(articleDef);\n\t\t\t_lstSelection->addRow(1, tr(articleDef->getMainTitle()).c_str());\n\n\t\t\tif (markAllAsSeen)\n\t\t\t{\n\t\t\t\t// remember all listed articles as seen/normal\n\t\t\t\t_game->getSavedGame()->setUfopediaRuleStatus(articleDef->id, ArticleDefinition::PEDIA_STATUS_NORMAL);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (ruleStatus == ArticleDefinition::PEDIA_STATUS_NEW)\n\t\t\t\t{\n\t\t\t\t\t_lstSelection->setCellColor(row, 0, _colorNew);\n\t\t\t\t\thasUnseen = true;\n\t\t\t\t}\n\t\t\t\telse if (ruleStatus == ArticleDefinition::PEDIA_STATUS_HIDDEN)\n\t\t\t\t{\n\t\t\t\t\t_lstSelection->setCellColor(row, 0, _colorHidden);\n\t\t\t\t}\n\t\t\t}\n\t\t\trow++;\n\t\t}\n\n\t\tif (!_isCommendationsSection)\n\t\t{\n\t\t\tstd::string label = tr(\"STR_OK\");\n\t\t\t_btnOk->setText((hasUnseen ? \"* \" : \"\") + label);\n\t\t}\n\t\tif (_lstScroll > 0)\n\t\t{\n\t\t\t_lstSelection->scrollTo(_lstScroll);\n\t\t\t_lstScroll = 0;\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "src/Ufopaedia/UfopaediaSelectState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include \"Ufopaedia.h\"\n#include <string>\n\nnamespace OpenXcom\n{\n\tclass Game;\n\tclass Action;\n\tclass Window;\n\tclass Text;\n\tclass TextEdit;\n\tclass TextButton;\n\tclass ComboBox;\n\tclass TextList;\n\n\t/**\n\t * UfopaediaSelectState is the screen that lists articles of a given type.\n\t */\n\n\tclass UfopaediaSelectState : public State\n\t{\n\tpublic:\n\t\tUfopaediaSelectState(const std::string &section, int heightOffset, int windowOffset);\n\t\tvirtual ~UfopaediaSelectState();\n\t\tvoid init() override;\n\tprotected:\n\t\tstd::string _section;\n\t\tWindow *_window;\n\t\tTextEdit *_btnQuickSearch;\n\t\tText *_txtTitle;\n\t\tTextButton *_btnOk;\n\t\tComboBox *_cbxFilter;\n\t\tTextList *_lstSelection;\n\t\tArticleDefinitionList _article_list, _filtered_article_list;\n\t\tsize_t _lstScroll;\n\t\tUint8 _colorNormal, _colorNew, _colorHidden;\n\t\tbool _isCommendationsSection;\n\n\t\t/// Handler for clicking the OK button\n\t\tvoid btnOkClick(Action *action);\n\t\t/// Handlers for Quick Search.\n\t\tvoid btnQuickSearchToggle(Action *action);\n\t\tvoid btnQuickSearchApply(Action *action);\n\t\t/// Handler for clicking the selection list.\n\t\tvoid lstSelectionClick(Action *action);\n\t\tvoid lstSelectionClickRight(Action *action);\n\t\t/// Handler for changing the filter\n\t\tvoid cbxFilterChange(Action* action);\n\t\t/// Handler for clicking the [Mark All As Seen] button.\n\t\tvoid btnMarkAllAsSeenClick(Action *action);\n\t\t/// load available articles into the selection list\n\t\tvoid loadSelectionList(bool markAllAsSeen);\n\t};\n}\n"
  },
  {
    "path": "src/Ufopaedia/UfopaediaStartState.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"UfopaediaStartState.h\"\n#include \"UfopaediaSelectState.h\"\n#include \"../Engine/Game.h\"\n#include \"../Engine/Action.h\"\n#include \"../Engine/Options.h\"\n#include \"../Interface/Window.h\"\n#include \"../Interface/Text.h\"\n#include \"../Interface/TextButton.h\"\n#include \"../Interface/ArrowButton.h\"\n#include \"../Mod/Mod.h\"\n#include \"../Engine/Timer.h\"\n#include \"../fmath.h\"\n#include \"../Engine/Screen.h\"\n\nnamespace OpenXcom\n{\n\tUfopaediaStartState::UfopaediaStartState() : _offset(0), _scroll(0), _maxButtons(0), _heightOffset(0), _windowOffset(0), _cats(_game->getMod()->getUfopaediaCategoryList())\n\t{\n\t\tconst int MAX_VANILLA_BUTTONS = 10;\n\t\tconst int SPACE_PER_BUTTON = 13;\n\t\tconst int HALF_SPACE_PER_BUTTON = 7;\n\n\t\t_screen = false;\n\n\t\tint extraSpace = (_game->getScreen()->getDY() * 2) + 20; // upper extra + lower extra + 20 pixels from the original\n\t\tint maxButtons = (extraSpace / SPACE_PER_BUTTON) + MAX_VANILLA_BUTTONS;\n\t\t_maxButtons = std::min(_cats.size(), (size_t)maxButtons);\n\t\tmaxButtons = (int)_maxButtons;\n\n\t\tint buttonOffset = 0;\n\t\tif (maxButtons >= MAX_VANILLA_BUTTONS)\n\t\t{\n\t\t\t_heightOffset = (maxButtons - MAX_VANILLA_BUTTONS) * SPACE_PER_BUTTON;\n\t\t\t_windowOffset = ((maxButtons - MAX_VANILLA_BUTTONS) / 2 * SPACE_PER_BUTTON) + ((maxButtons - MAX_VANILLA_BUTTONS) % 2 * HALF_SPACE_PER_BUTTON);\n\t\t\tbuttonOffset = _windowOffset + SPACE_PER_BUTTON;\n\t\t}\n\n\t\t// set background window\n\t\t_window = new Window(this, 256, 180 + _heightOffset, 32, 10 - _windowOffset, POPUP_BOTH);\n\t\t_window->setInnerColor(239); // almost black = darkest index from backpals.dat\n\n\t\t// set title\n\t\t_txtTitle = new Text(220, 17, 50, 33);\n\n\t\t// Set palette\n\t\tsetInterface(\"ufopaedia\");\n\n\t\tadd(_window, \"window\", \"ufopaedia\");\n\t\tadd(_txtTitle, \"text\", \"ufopaedia\");\n\n\t\t// set buttons\n\t\tint y = 50 - buttonOffset;\n\n\t\t_btnScrollUp = new ArrowButton(ARROW_BIG_UP, 13, 14, 270, y);\n\t\tadd(_btnScrollUp, \"button1\", \"ufopaedia\");\n\n\t\tfor (size_t i = 0; i < _maxButtons; ++i)\n\t\t{\n\t\t\tTextButton *button = new TextButton(220, 12, 50, y);\n\t\t\ty += 13;\n\n\t\t\tadd(button, \"button1\", \"ufopaedia\");\n\n\t\t\tbutton->onMouseClick((ActionHandler)&UfopaediaStartState::btnSectionClick);\n\t\t\tbutton->onMousePress((ActionHandler)&UfopaediaStartState::btnScrollUpClick, SDL_BUTTON_WHEELUP);\n\t\t\tbutton->onMousePress((ActionHandler)&UfopaediaStartState::btnScrollDownClick, SDL_BUTTON_WHEELDOWN);\n\n\t\t\t_btnSections.push_back(button);\n\t\t}\n\n\t\t_btnOk = new TextButton(220, 12, 50, y);\n\t\tadd(_btnOk, \"button1\", \"ufopaedia\");\n\n\t\t_btnScrollDown = new ArrowButton(ARROW_BIG_DOWN, 13, 14, 270, y - 15);\n\t\tadd(_btnScrollDown, \"button1\", \"ufopaedia\");\n\n\t\tupdateButtons();\n\t\tif (!_btnSections.empty())\n\t\t{\n\t\t\tint titleY = _btnSections.front()->getY() - _txtTitle->getHeight();\n\t\t\tif (titleY < _window->getY()) titleY = _window->getY();\n\t\t\t_txtTitle->setY(titleY);\n\t\t}\n\n\t\tcenterAllSurfaces();\n\n\t\tsetWindowBackground(_window, \"ufopaedia\");\n\n\t\t_txtTitle->setBig();\n\t\t_txtTitle->setAlign(ALIGN_CENTER);\n\t\t_txtTitle->setText(tr(\"STR_UFOPAEDIA\"));\n\n\t\t_btnOk->setText(tr(\"STR_OK\"));\n\t\t_btnOk->onMouseClick((ActionHandler)&UfopaediaStartState::btnOkClick);\n\t\t_btnOk->onKeyboardPress((ActionHandler)&UfopaediaStartState::btnOkClick, Options::keyCancel);\n\t\t_btnOk->onKeyboardPress((ActionHandler)&UfopaediaStartState::btnOkClick, Options::keyGeoUfopedia);\n\n\t\t_btnScrollUp->setVisible(_cats.size() > _maxButtons);\n\t\t_btnScrollUp->onMousePress((ActionHandler)&UfopaediaStartState::btnScrollUpPress);\n\t\t_btnScrollUp->onMouseRelease((ActionHandler)&UfopaediaStartState::btnScrollRelease);\n\t\t_btnScrollDown->setVisible(_cats.size() > _maxButtons);\n\t\t_btnScrollDown->onMousePress((ActionHandler)&UfopaediaStartState::btnScrollDownPress);\n\t\t_btnScrollDown->onMouseRelease((ActionHandler)&UfopaediaStartState::btnScrollRelease);\n\n\t\t_timerScroll = new Timer(50);\n\t\t_timerScroll->onTimer((StateHandler)&UfopaediaStartState::scroll);\n\t}\n\n\t/**\n\t * Deletes timers.\n\t */\n\tUfopaediaStartState::~UfopaediaStartState()\n\t{\n\t\tdelete _timerScroll;\n\t}\n\n\t/**\n\t * Run timers.\n\t */\n\tvoid UfopaediaStartState::think()\n\t{\n\t\tState::think();\n\t\t_timerScroll->think(this, 0);\n\t}\n\n\t/**\n\t * Returns to the previous screen.\n\t * @param action Pointer to an action.\n\t */\n\tvoid UfopaediaStartState::btnOkClick(Action *)\n\t{\n\t\t_game->popState();\n\t}\n\n\t/**\n\t * Displays the list of articles for this section.\n\t * @param action Pointer to an action.\n\t */\n\tvoid UfopaediaStartState::btnSectionClick(Action *action)\n\t{\n\t\tfor (size_t i = 0; i < _btnSections.size(); ++i)\n\t\t{\n\t\t\tif (action->getSender() == _btnSections[i])\n\t\t\t{\n\t\t\t\t_game->pushState(new UfopaediaSelectState(_cats[_offset + i], _heightOffset, _windowOffset));\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Starts scrolling the section buttons up.\n\t * @param action Pointer to an action.\n\t */\n\tvoid UfopaediaStartState::btnScrollUpPress(Action *)\n\t{\n\t\t_scroll = -1;\n\t\t_timerScroll->start();\n\t}\n\n\t/**\n\t * Scrolls the section buttons up.\n\t * @param action Pointer to an action.\n\t */\n\tvoid UfopaediaStartState::btnScrollUpClick(Action *)\n\t{\n\t\t_scroll = -1;\n\t\tscroll();\n\t}\n\n\t/**\n\t * Starts scrolling the section buttons down.\n\t * @param action Pointer to an action.\n\t */\n\tvoid UfopaediaStartState::btnScrollDownPress(Action *)\n\t{\n\t\t_scroll = 1;\n\t\t_timerScroll->start();\n\t}\n\n\t/**\n\t * Scrolls the section buttons down.\n\t * @param action Pointer to an action.\n\t */\n\tvoid UfopaediaStartState::btnScrollDownClick(Action *)\n\t{\n\t\t_scroll = 1;\n\t\tscroll();\n\t}\n\n\t/**\n\t * Stops scrolling the section buttons.\n\t * @param action Pointer to an action.\n\t */\n\tvoid UfopaediaStartState::btnScrollRelease(Action *)\n\t{\n\t\t_timerScroll->stop();\n\t}\n\n\t/**\n\t * Offsets the list of section buttons.\n\t */\n\tvoid UfopaediaStartState::scroll()\n\t{\n\t\tif (_cats.size() > _maxButtons)\n\t\t{\n\t\t\t_offset = Clamp(_offset + _scroll, 0, int(_cats.size() - _maxButtons));\n\t\t\tupdateButtons();\n\t\t}\n\t}\n\n\t/**\n\t * Updates the section button labels based on scroll.\n\t */\n\tvoid UfopaediaStartState::updateButtons()\n\t{\n\t\tfor (size_t i = 0; i < _btnSections.size(); ++i)\n\t\t{\n\t\t\t_btnSections[i]->setText(tr(_cats[_offset + i]));\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/Ufopaedia/UfopaediaStartState.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include \"../Engine/State.h\"\n#include <string>\n#include <vector>\n\nnamespace OpenXcom\n{\n\tclass Game;\n\tclass Action;\n\tclass Window;\n\tclass Text;\n\tclass TextButton;\n\tclass ArrowButton;\n\tclass Timer;\n\n\t/**\n\t * UfopaediaStartState is the screen that opens when clicking Ufopaedia button in Geoscape.\n\t * Presents buttons to all sections of Ufopaedia, opening a UfopaediaSelectState on click.\n\t */\n\n\tclass UfopaediaStartState : public State\n\t{\n\tpublic:\n\t\tUfopaediaStartState();\n\t\tvirtual ~UfopaediaStartState();\n\n\tprotected:\n\t\tWindow *_window;\n\t\tText *_txtTitle;\n\t\tTextButton *_btnOk;\n\t\tstd::vector<TextButton*> _btnSections;\n\t\tArrowButton *_btnScrollUp, *_btnScrollDown;\n\t\tTimer *_timerScroll;\n\n\t\tint _offset, _scroll;\n\t\tsize_t _maxButtons;\n\t\tint _heightOffset, _windowOffset;\n\t\tconst std::vector<std::string> &_cats;\n\n\t\t// navigation callbacks\n\t\tvoid think() override;\n\t\tvoid btnSectionClick(Action *action);\n\t\tvoid btnOkClick(Action *action);\n\n\t\t// scrolling logic\n\t\tvoid btnScrollUpPress(Action *action);\n\t\tvoid btnScrollUpClick(Action *action);\n\t\tvoid btnScrollDownPress(Action *action);\n\t\tvoid btnScrollDownClick(Action *action);\n\t\tvoid btnScrollRelease(Action *action);\n\t\tvoid scroll();\n\t\tvoid updateButtons();\n\t};\n}\n"
  },
  {
    "path": "src/apple/SDLMain.h",
    "content": "/*   SDLMain.m - main entry point for our Cocoa-ized SDL app\n       Initial Version: Darrell Walisser <dwaliss1@purdue.edu>\n       Non-NIB-Code & other changes: Max Horn <max@quendi.de>\n    Feel free to customize this file to suit your needs\n*/\n\n#ifndef _SDLMain_h_\n#define _SDLMain_h_\n\n#import <Cocoa/Cocoa.h>\n\n@interface SDLMain : NSObject\n@end\n\n#endif /* _SDLMain_h_ */\n"
  },
  {
    "path": "src/apple/SDLMain.m",
    "content": "/*   SDLMain.m - main entry point for our Cocoa-ized SDL app\n       Initial Version: Darrell Walisser <dwaliss1@purdue.edu>\n       Non-NIB-Code & other changes: Max Horn <max@quendi.de>\n\n    Feel free to customize this file to suit your needs\n*/\n\n#include \"SDL.h\"\n#include \"SDLMain.h\"\n#include <sys/param.h> /* for MAXPATHLEN */\n#include <unistd.h>\n\n/* For some reaon, Apple removed setAppleMenu from the headers in 10.4,\n but the method still is there and works. To avoid warnings, we declare\n it ourselves here. */\n@interface NSApplication(SDL_Missing_Methods)\n- (void)setAppleMenu:(NSMenu *)menu;\n@end\n\n/* Use this flag to determine whether we use SDLMain.nib or not */\n#define\t\tSDL_USE_NIB_FILE\t0\n\nstatic int    gArgc;\nstatic char  **gArgv;\nstatic BOOL   gFinderLaunch;\nstatic BOOL   gCalledAppMainline = FALSE;\n\nstatic NSString *getApplicationName(void)\n{\n    const NSDictionary *dict;\n    NSString *appName = 0;\n\n    /* Determine the application name */\n    dict = (const NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle());\n    if (dict)\n        appName = [dict objectForKey: @\"CFBundleName\"];\n\n    if (![appName length])\n        appName = [[NSProcessInfo processInfo] processName];\n\n    return appName;\n}\n\n#if SDL_USE_NIB_FILE\n/* A helper category for NSString */\n@interface NSString (ReplaceSubString)\n- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString;\n@end\n#endif\n\n@interface NSApplication (SDLApplication)\n@end\n\n@implementation NSApplication (SDLApplication)\n/* Invoked from the Quit menu item */\n- (void)terminate:(id)__unused sender\n{\n    /* Post a SDL_QUIT event */\n    SDL_Event event;\n    event.type = SDL_QUIT;\n    SDL_PushEvent(&event);\n}\n@end\n\n/* The main class of the application, the application's delegate */\n@implementation SDLMain\n\n/* Set the working directory to the .app's parent directory */\n- (void) setupWorkingDirectory:(BOOL)__unused shouldChdir\n{\n    NSString *resourcePath = [[NSBundle mainBundle] resourcePath];\n    [[NSFileManager defaultManager] changeCurrentDirectoryPath:resourcePath];\n//    if (shouldChdir)\n//    {\n//        char parentdir[MAXPATHLEN];\n//        CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle());\n//        CFURLRef url2 = CFURLCreateCopyDeletingLastPathComponent(0, url);\n//        if (CFURLGetFileSystemRepresentation(url2, 1, (UInt8 *)parentdir, MAXPATHLEN)) {\n//            chdir(parentdir);   /* chdir to the binary app's parent */\n//        }\n//        CFRelease(url);\n//        CFRelease(url2);\n//    }\n}\n\n#if SDL_USE_NIB_FILE\n\n/* Fix menu to contain the real app name instead of \"SDL App\" */\n- (void)fixMenu:(NSMenu *)aMenu withAppName:(NSString *)appName\n{\n    NSRange aRange;\n    NSEnumerator *enumerator;\n    NSMenuItem *menuItem;\n\n    aRange = [[aMenu title] rangeOfString:@\"SDL App\"];\n    if (aRange.length != 0)\n        [aMenu setTitle: [[aMenu title] stringByReplacingRange:aRange with:appName]];\n\n    enumerator = [[aMenu itemArray] objectEnumerator];\n    while ((menuItem = [enumerator nextObject]))\n    {\n        aRange = [[menuItem title] rangeOfString:@\"SDL App\"];\n        if (aRange.length != 0)\n            [menuItem setTitle: [[menuItem title] stringByReplacingRange:aRange with:appName]];\n        if ([menuItem hasSubmenu])\n            [self fixMenu:[menuItem submenu] withAppName:appName];\n    }\n}\n\n#else\n\nstatic void setApplicationMenu(void)\n{\n    /* warning: this code is very odd */\n    NSMenu *appleMenu;\n    NSMenuItem *menuItem;\n    NSString *title;\n    NSString *appName;\n\n    appName = getApplicationName();\n    appleMenu = [[NSMenu alloc] initWithTitle:@\"\"];\n\n    /* Add menu items */\n    title = [@\"About \" stringByAppendingString:appName];\n    [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@\"\"];\n\n    [appleMenu addItem:[NSMenuItem separatorItem]];\n\n    title = [@\"Hide \" stringByAppendingString:appName];\n    [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@\"h\"];\n\n    menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@\"Hide Others\" action:@selector(hideOtherApplications:) keyEquivalent:@\"h\"];\n    [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)];\n\n    [appleMenu addItemWithTitle:@\"Show All\" action:@selector(unhideAllApplications:) keyEquivalent:@\"\"];\n\n    [appleMenu addItem:[NSMenuItem separatorItem]];\n\n    title = [@\"Quit \" stringByAppendingString:appName];\n    [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@\"q\"];\n\n\n    /* Put menu into the menubar */\n    menuItem = [[NSMenuItem alloc] initWithTitle:@\"\" action:nil keyEquivalent:@\"\"];\n    [menuItem setSubmenu:appleMenu];\n    [[NSApp mainMenu] addItem:menuItem];\n\n    /* Tell the application object that this is now the application menu */\n    [NSApp setAppleMenu:appleMenu];\n\n    /* Finally give up our references to the objects */\n    [appleMenu release];\n    [menuItem release];\n}\n\n/* Create a window menu */\nstatic void setupWindowMenu(void)\n{\n    NSMenu      *windowMenu;\n    NSMenuItem  *windowMenuItem;\n    NSMenuItem  *menuItem;\n\n    windowMenu = [[NSMenu alloc] initWithTitle:@\"Window\"];\n\n    /* \"Minimize\" item */\n    menuItem = [[NSMenuItem alloc] initWithTitle:@\"Minimize\" action:@selector(performMiniaturize:) keyEquivalent:@\"m\"];\n    [windowMenu addItem:menuItem];\n    [menuItem release];\n\n    /* Put menu into the menubar */\n    windowMenuItem = [[NSMenuItem alloc] initWithTitle:@\"Window\" action:nil keyEquivalent:@\"\"];\n    [windowMenuItem setSubmenu:windowMenu];\n    [[NSApp mainMenu] addItem:windowMenuItem];\n\n    /* Tell the application object that this is now the window menu */\n    [NSApp setWindowsMenu:windowMenu];\n\n    /* Finally give up our references to the objects */\n    [windowMenu release];\n    [windowMenuItem release];\n}\n\n/* Replacement for NSApplicationMain */\nstatic void CustomApplicationMain (__unused int argc, __unused char **argv)\n{\n    NSAutoreleasePool\t*pool = [[NSAutoreleasePool alloc] init];\n    SDLMain\t\t\t\t*sdlMain;\n\n    /* Ensure the application object is initialised */\n    [[NSApplication sharedApplication] activateIgnoringOtherApps: YES];\n\n    /* Set up the menubar */\n    [NSApp setMainMenu:[[NSMenu alloc] init]];\n    setApplicationMenu();\n    setupWindowMenu();\n\n    /* Create SDLMain and make it the app delegate */\n    sdlMain = [[SDLMain alloc] init];\n    [NSApp setDelegate:sdlMain];\n\n    /* Start the main event loop */\n    [NSApp run];\n\n    [sdlMain release];\n    [pool release];\n}\n\n#endif\n\n\n/*\n * Catch document open requests...this lets us notice files when the app\n *  was launched by double-clicking a document, or when a document was\n *  dragged/dropped on the app's icon. You need to have a\n *  CFBundleDocumentsType section in your Info.plist to get this message,\n *  apparently.\n *\n * Files are added to gArgv, so to the app, they'll look like command line\n *  arguments. Previously, apps launched from the finder had nothing but\n *  an argv[0].\n *\n * This message may be received multiple times to open several docs on launch.\n *\n * This message is ignored once the app's mainline has been called.\n */\n- (BOOL)application:(NSApplication *)__unused theApplication openFile:(NSString *)filename\n{\n    const char *temparg;\n    size_t arglen;\n    char *arg;\n    char **newargv;\n\n    if (!gFinderLaunch)  /* MacOS is passing command line args. */\n        return FALSE;\n\n    if (gCalledAppMainline)  /* app has started, ignore this document. */\n        return FALSE;\n\n    temparg = [filename UTF8String];\n    arglen = SDL_strlen(temparg) + 1;\n    arg = (char *) SDL_malloc(arglen);\n    if (arg == NULL)\n        return FALSE;\n\n    newargv = (char **) realloc(gArgv, sizeof (char *) * (gArgc + 2));\n    if (newargv == NULL)\n    {\n        SDL_free(arg);\n        return FALSE;\n    }\n    gArgv = newargv;\n\n    SDL_strlcpy(arg, temparg, arglen);\n    gArgv[gArgc++] = arg;\n    gArgv[gArgc] = NULL;\n    return TRUE;\n}\n\n\n/* Called when the internal event loop has just started running */\n- (void) applicationDidFinishLaunching: (NSNotification *)__unused note\n{\n    int status;\n\n    /* Set the working directory to the .app's parent directory */\n    [self setupWorkingDirectory:gFinderLaunch];\n\n#if SDL_USE_NIB_FILE\n    /* Set the main menu to contain the real app name instead of \"SDL App\" */\n    [self fixMenu:[NSApp mainMenu] withAppName:getApplicationName()];\n#endif\n\n    /* Hand off to main application code */\n    gCalledAppMainline = TRUE;\n    status = SDL_main (gArgc, gArgv);\n\n    /* We're done, thank you for playing */\n    exit(status);\n}\n@end\n\n\n@implementation NSString (ReplaceSubString)\n\n- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString\n{\n    unsigned int bufferSize;\n    unsigned int selfLen = [self length];\n    unsigned int aStringLen = [aString length];\n    unichar *buffer;\n    NSRange localRange;\n    NSString *result;\n\n    bufferSize = selfLen + aStringLen - aRange.length;\n    buffer = (unichar *)NSAllocateMemoryPages(bufferSize*sizeof(unichar));\n\n    /* Get first part into buffer */\n    localRange.location = 0;\n    localRange.length = aRange.location;\n    [self getCharacters:buffer range:localRange];\n\n    /* Get middle part into buffer */\n    localRange.location = 0;\n    localRange.length = aStringLen;\n    [aString getCharacters:(buffer+aRange.location) range:localRange];\n\n    /* Get last part into buffer */\n    localRange.location = aRange.location + aRange.length;\n    localRange.length = selfLen - localRange.location;\n    [self getCharacters:(buffer+aRange.location+aStringLen) range:localRange];\n\n    /* Build output string */\n    result = [NSString stringWithCharacters:buffer length:bufferSize];\n\n    NSDeallocateMemoryPages(buffer, bufferSize);\n\n    return result;\n}\n\n@end\n\n\n#ifdef main\n#  undef main\n#endif\n\n\nstatic int IsRootCwd()\n{\n    char buf[MAXPATHLEN];\n    char *cwd = getcwd(buf, sizeof (buf));\n    return (cwd && (strcmp(cwd, \"/\") == 0));\n}\n\nstatic int IsFinderLaunch(const int argc, char **argv)\n{\n    /* -psn_XXX is passed if we are launched from Finder, SOMETIMES */\n    if ( (argc >= 2) && (strncmp(argv[1], \"-psn\", 4) == 0) ) {\n        return 1;\n    } else if ((argc == 1) && IsRootCwd()) {\n        /* we might still be launched from the Finder; on 10.9+, you might not\n        get the -psn command line anymore. If there's no\n        command line, and if our current working directory is \"/\", it\n        might as well be a Finder launch. */\n        return 1;\n    }\n    return 0;  /* not a Finder launch. */\n}\n\n/* Main entry point to executable - should *not* be SDL_main! */\nint main (int argc, char **argv)\n{\n    /* Copy the arguments into a global variable */\n    if (IsFinderLaunch(argc, argv)) {\n        gArgv = (char **) SDL_malloc(sizeof (char *) * 2);\n        gArgv[0] = argv[0];\n        gArgv[1] = NULL;\n        gArgc = 1;\n        gFinderLaunch = YES;\n    } else {\n        int i;\n        gArgc = argc;\n        gArgv = (char **) SDL_malloc(sizeof (char *) * (argc+1));\n        for (i = 0; i <= argc; i++)\n            gArgv[i] = argv[i];\n        gFinderLaunch = NO;\n    }\n\n#if SDL_USE_NIB_FILE\n    NSApplicationMain (argc, argv);\n#else\n    CustomApplicationMain (argc, argv);\n#endif\n    return 0;\n}\n\n"
  },
  {
    "path": "src/fallthrough.h",
    "content": "#pragma once\n\n#ifndef __has_cpp_attribute\n#define __has_cpp_attribute(x) 0\n#endif\n\n#if __has_cpp_attribute(fallthrough)\n#define FALLTHROUGH [[fallthrough]]\n#elif __has_cpp_attribute(gnu::fallthrough)\n#define FALLTHROUGH [[gnu::fallthrough]]\n#elif __has_cpp_attribute(clang::fallthrough)\n#define FALLTHROUGH [[clang::fallthrough]]\n#else\n#define FALLTHROUGH\n#endif\n"
  },
  {
    "path": "src/fmath.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <algorithm>\n#include <cfloat>\n#define _USE_MATH_DEFINES\n#include <cmath>\n#include <assert.h>\n\n#ifndef M_PI\n#define M_PI       3.14159265358979323846\n#define M_PI_2     1.57079632679489661923\n#define M_PI_4     0.785398163397448309616\n#endif\n\n// Float operations\n\ninline bool AreSame(float l, float r)\n{\n\treturn std::fabs(l-r) <= FLT_EPSILON * std::max(1.0f, std::max(std::fabs(l), std::fabs(r)));\n}\n\ninline bool AreSame(double l, double r)\n{\n\treturn std::fabs(l-r) <= DBL_EPSILON * std::max(1.0, std::max(std::fabs(l), std::fabs(r)));\n}\n\ninline float Round(float x)\n{\n\treturn x < 0.0f ? std::ceil(x - 0.5f) : std::floor(x + 0.5f);\n}\n\ninline double Round(double x)\n{\n\treturn x < 0.0 ? std::ceil(x - 0.5) : std::floor(x + 0.5);\n}\n\n// Number operations\n\ntemplate <class _Tx>\ninline _Tx Sqr(const _Tx& x)\n{\n\treturn x * x;\n}\n\ntemplate <class _Tx>\ninline _Tx Sign(const _Tx& x)\n{\n\treturn (_Tx(0) < x) - (x < _Tx(0));\n}\n\ntemplate <class _Tx>\ninline _Tx Clamp(const _Tx& x, const _Tx& min, const _Tx& max)\n{\n\treturn std::min(std::max(x, min), max);\n}\n\ntemplate <class _Tx, class _Ts = int>\ninline _Tx VectCrossProduct(const _Tx& a, const _Tx& b, _Ts scale = 1)\n{\n\t_Tx temp\n\t{\n\t\t(a.y * b.z - a.z * b.y) / scale,\n\t\t(a.z * b.x - a.x * b.z) / scale,\n\t\t(a.x * b.y - a.y * b.x) / scale,\n\t};\n\treturn temp;\n}\n\ntemplate <class _Tx, class _Ts = int>\ninline _Ts VectDotProduct(const _Tx& a, const _Tx& b, _Ts scale = 1)\n{\n\treturn (a.x * b.x + a.y * b.y + a.z * b.z) / scale;\n}\n\ntemplate <class _Tx, class _Ts = int>\ninline _Tx VectNormalize(const _Tx& a, _Ts scale = 1)\n{\n\t_Ts dot = VectDotProduct(a, a, scale);\n\tif (dot > 0)\n\t{\n\t\tdot = std::sqrt(dot * scale);\n\t\t_Tx temp\n\t\t{\n\t\t\ta.x * scale / dot,\n\t\t\ta.y * scale / dot,\n\t\t\ta.z * scale / dot,\n\t\t};\n\t\treturn temp;\n\t}\n\treturn _Tx{ };\n}\n\n/**\n * Interpolate between two variables.\n * @param a Left side value\n * @param b Rigth side value\n * @param step Value from range 0 to `stepMax` (including)\n * @param stepMax Maximum value for `step`.\n * @return if `step` equal 0 or less then it returns `a`, if is equal `stepMax` or bigger it will return `b`. Any other value will interpolate between `a` and `b`.\n */\ntemplate <class TValue, class TStep>\ninline TValue Interpolate(const TValue& a, const TValue& b, TStep step, TStep stepMax)\n{\n\tassert((stepMax > TStep(0)) && \"max should be bigger than zero\");\n\tstep = Clamp(step, TStep(0), stepMax);\n\treturn  (a * (stepMax - step) + b * (step)) / stepMax;\n}\n\n// Degree operations\n\ninline double Deg2Rad(double deg)\n{\n\treturn deg * M_PI / 180.0;\n}\n\ninline double Rad2Deg(double rad)\n{\n\treturn rad / M_PI * 180.0;\n}\n\ninline double Xcom2Rad(int deg)\n{\n\treturn deg * 0.125 * M_PI / 180.0;\n}\n\ninline double Nautical(double x)\n{\n\treturn x * (1 / 60.0) * (M_PI / 180.0);\n}\n\n/**\n * Inversion of Nautical distance, use same value as in rulesets definitions\n */\ninline int XcomDistance(double nautical)\n{\n\treturn nautical * 60.0 * (180.0 / M_PI);\n}\n"
  },
  {
    "path": "src/git_version.h.in",
    "content": "/*\n * Copyright 2010-2015 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#ifndef GIT_VERSION_H\n#define GIT_VERSION_H\n\n#ifndef OPENXCOM_VERSION_GIT\n#define OPENXCOM_VERSION_GIT \"@OPENXCOM_VERSION_STRING@\"\n#endif\n\n#endif\n"
  },
  {
    "path": "src/lodepng.cpp",
    "content": "/*\nLodePNG version 20180114\n\nCopyright (c) 2005-2018 Lode Vandevenne\n\nThis software is provided 'as-is', without any express or implied\nwarranty. In no event will the authors be held liable for any damages\narising from the use of this software.\n\nPermission is granted to anyone to use this software for any purpose,\nincluding commercial applications, and to alter it and redistribute it\nfreely, subject to the following restrictions:\n\n    1. The origin of this software must not be misrepresented; you must not\n    claim that you wrote the original software. If you use this software\n    in a product, an acknowledgment in the product documentation would be\n    appreciated but is not required.\n\n    2. Altered source versions must be plainly marked as such, and must not be\n    misrepresented as being the original software.\n\n    3. This notice may not be removed or altered from any source\n    distribution.\n*/\n\n/*\nThe manual and changelog are in the header file \"lodepng.h\"\nRename this file to lodepng.cpp to use it for C++, or to lodepng.c to use it for C.\n*/\n\n#include \"lodepng.h\"\n\n#include <limits.h>\n#include <stdio.h>\n#include <stdlib.h>\n\n#if defined(_MSC_VER) && (_MSC_VER >= 1310) /*Visual Studio: A few warning types are not desired here.*/\n#pragma warning( disable : 4244 ) /*implicit conversions: not warned by gcc -Wall -Wextra and requires too much casts*/\n#pragma warning( disable : 4996 ) /*VS does not like fopen, but fopen_s is not standard C so unusable here*/\n#endif /*_MSC_VER */\n\nconst char* LODEPNG_VERSION_STRING = \"20180114\";\n\n/*\nThis source file is built up in the following large parts. The code sections\nwith the \"LODEPNG_COMPILE_\" #defines divide this up further in an intermixed way.\n-Tools for C and common code for PNG and Zlib\n-C Code for Zlib (huffman, deflate, ...)\n-C Code for PNG (file format chunks, adam7, PNG filters, color conversions, ...)\n-The C++ wrapper around all of the above\n*/\n\n/*The malloc, realloc and free functions defined here with \"lodepng_\" in front\nof the name, so that you can easily change them to others related to your\nplatform if needed. Everything else in the code calls these. Pass\n-DLODEPNG_NO_COMPILE_ALLOCATORS to the compiler, or comment out\n#define LODEPNG_COMPILE_ALLOCATORS in the header, to disable the ones here and\ndefine them in your own project's source files without needing to change\nlodepng source code. Don't forget to remove \"static\" if you copypaste them\nfrom here.*/\n\n#ifdef LODEPNG_COMPILE_ALLOCATORS\nstatic void* lodepng_malloc(size_t size)\n{\n  return malloc(size);\n}\n\nstatic void* lodepng_realloc(void* ptr, size_t new_size)\n{\n  return realloc(ptr, new_size);\n}\n\nstatic void lodepng_free(void* ptr)\n{\n  free(ptr);\n}\n#else /*LODEPNG_COMPILE_ALLOCATORS*/\nvoid* lodepng_malloc(size_t size);\nvoid* lodepng_realloc(void* ptr, size_t new_size);\nvoid lodepng_free(void* ptr);\n#endif /*LODEPNG_COMPILE_ALLOCATORS*/\n\n/* ////////////////////////////////////////////////////////////////////////// */\n/* ////////////////////////////////////////////////////////////////////////// */\n/* // Tools for C, and common code for PNG and Zlib.                       // */\n/* ////////////////////////////////////////////////////////////////////////// */\n/* ////////////////////////////////////////////////////////////////////////// */\n\n/*\nOften in case of an error a value is assigned to a variable and then it breaks\nout of a loop (to go to the cleanup phase of a function). This macro does that.\nIt makes the error handling code shorter and more readable.\n\nExample: if(!uivector_resizev(&frequencies_ll, 286, 0)) ERROR_BREAK(83);\n*/\n#define CERROR_BREAK(errorvar, code)\\\n{\\\n  errorvar = code;\\\n  break;\\\n}\n\n/*version of CERROR_BREAK that assumes the common case where the error variable is named \"error\"*/\n#define ERROR_BREAK(code) CERROR_BREAK(error, code)\n\n/*Set error var to the error code, and return it.*/\n#define CERROR_RETURN_ERROR(errorvar, code)\\\n{\\\n  errorvar = code;\\\n  return code;\\\n}\n\n/*Try the code, if it returns error, also return the error.*/\n#define CERROR_TRY_RETURN(call)\\\n{\\\n  unsigned error = call;\\\n  if(error) return error;\\\n}\n\n/*Set error var to the error code, and return from the void function.*/\n#define CERROR_RETURN(errorvar, code)\\\n{\\\n  errorvar = code;\\\n  return;\\\n}\n\n/*\nAbout uivector, ucvector and string:\n-All of them wrap dynamic arrays or text strings in a similar way.\n-LodePNG was originally written in C++. The vectors replace the std::vectors that were used in the C++ version.\n-The string tools are made to avoid problems with compilers that declare things like strncat as deprecated.\n-They're not used in the interface, only internally in this file as static functions.\n-As with many other structs in this file, the init and cleanup functions serve as ctor and dtor.\n*/\n\n#ifdef LODEPNG_COMPILE_ZLIB\n/*dynamic vector of unsigned ints*/\ntypedef struct uivector\n{\n  unsigned* data;\n  size_t size; /*size in number of unsigned longs*/\n  size_t allocsize; /*allocated size in bytes*/\n} uivector;\n\nstatic void uivector_cleanup(void* p)\n{\n  ((uivector*)p)->size = ((uivector*)p)->allocsize = 0;\n  lodepng_free(((uivector*)p)->data);\n  ((uivector*)p)->data = NULL;\n}\n\n/*returns 1 if success, 0 if failure ==> nothing done*/\nstatic unsigned uivector_reserve(uivector* p, size_t allocsize)\n{\n  if(allocsize > p->allocsize)\n  {\n    size_t newsize = (allocsize > p->allocsize * 2) ? allocsize : (allocsize * 3 / 2);\n    void* data = lodepng_realloc(p->data, newsize);\n    if(data)\n    {\n      p->allocsize = newsize;\n      p->data = (unsigned*)data;\n    }\n    else return 0; /*error: not enough memory*/\n  }\n  return 1;\n}\n\n/*returns 1 if success, 0 if failure ==> nothing done*/\nstatic unsigned uivector_resize(uivector* p, size_t size)\n{\n  if(!uivector_reserve(p, size * sizeof(unsigned))) return 0;\n  p->size = size;\n  return 1; /*success*/\n}\n\n/*resize and give all new elements the value*/\nstatic unsigned uivector_resizev(uivector* p, size_t size, unsigned value)\n{\n  size_t oldsize = p->size, i;\n  if(!uivector_resize(p, size)) return 0;\n  for(i = oldsize; i < size; ++i) p->data[i] = value;\n  return 1;\n}\n\nstatic void uivector_init(uivector* p)\n{\n  p->data = NULL;\n  p->size = p->allocsize = 0;\n}\n\n#ifdef LODEPNG_COMPILE_ENCODER\n/*returns 1 if success, 0 if failure ==> nothing done*/\nstatic unsigned uivector_push_back(uivector* p, unsigned c)\n{\n  if(!uivector_resize(p, p->size + 1)) return 0;\n  p->data[p->size - 1] = c;\n  return 1;\n}\n#endif /*LODEPNG_COMPILE_ENCODER*/\n#endif /*LODEPNG_COMPILE_ZLIB*/\n\n/* /////////////////////////////////////////////////////////////////////////// */\n\n/*dynamic vector of unsigned chars*/\ntypedef struct ucvector\n{\n  unsigned char* data;\n  size_t size; /*used size*/\n  size_t allocsize; /*allocated size*/\n} ucvector;\n\n/*returns 1 if success, 0 if failure ==> nothing done*/\nstatic unsigned ucvector_reserve(ucvector* p, size_t allocsize)\n{\n  if(allocsize > p->allocsize)\n  {\n    size_t newsize = (allocsize > p->allocsize * 2) ? allocsize : (allocsize * 3 / 2);\n    void* data = lodepng_realloc(p->data, newsize);\n    if(data)\n    {\n      p->allocsize = newsize;\n      p->data = (unsigned char*)data;\n    }\n    else return 0; /*error: not enough memory*/\n  }\n  return 1;\n}\n\n/*returns 1 if success, 0 if failure ==> nothing done*/\nstatic unsigned ucvector_resize(ucvector* p, size_t size)\n{\n  if(!ucvector_reserve(p, size * sizeof(unsigned char))) return 0;\n  p->size = size;\n  return 1; /*success*/\n}\n\n#ifdef LODEPNG_COMPILE_PNG\n\nstatic void ucvector_cleanup(void* p)\n{\n  ((ucvector*)p)->size = ((ucvector*)p)->allocsize = 0;\n  lodepng_free(((ucvector*)p)->data);\n  ((ucvector*)p)->data = NULL;\n}\n\nstatic void ucvector_init(ucvector* p)\n{\n  p->data = NULL;\n  p->size = p->allocsize = 0;\n}\n#endif /*LODEPNG_COMPILE_PNG*/\n\n#ifdef LODEPNG_COMPILE_ZLIB\n/*you can both convert from vector to buffer&size and vica versa. If you use\ninit_buffer to take over a buffer and size, it is not needed to use cleanup*/\nstatic void ucvector_init_buffer(ucvector* p, unsigned char* buffer, size_t size)\n{\n  p->data = buffer;\n  p->allocsize = p->size = size;\n}\n#endif /*LODEPNG_COMPILE_ZLIB*/\n\n#if (defined(LODEPNG_COMPILE_PNG) && defined(LODEPNG_COMPILE_ANCILLARY_CHUNKS)) || defined(LODEPNG_COMPILE_ENCODER)\n/*returns 1 if success, 0 if failure ==> nothing done*/\nstatic unsigned ucvector_push_back(ucvector* p, unsigned char c)\n{\n  if(!ucvector_resize(p, p->size + 1)) return 0;\n  p->data[p->size - 1] = c;\n  return 1;\n}\n#endif /*defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER)*/\n\n\n/* ////////////////////////////////////////////////////////////////////////// */\n\n#ifdef LODEPNG_COMPILE_PNG\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\n/*returns 1 if success, 0 if failure ==> nothing done*/\nstatic unsigned string_resize(char** out, size_t size)\n{\n  char* data = (char*)lodepng_realloc(*out, size + 1);\n  if(data)\n  {\n    data[size] = 0; /*null termination char*/\n    *out = data;\n  }\n  return data != 0;\n}\n\n/*init a {char*, size_t} pair for use as string*/\nstatic void string_init(char** out)\n{\n  *out = NULL;\n  string_resize(out, 0);\n}\n\n/*free the above pair again*/\nstatic void string_cleanup(char** out)\n{\n  lodepng_free(*out);\n  *out = NULL;\n}\n\nstatic void string_set(char** out, const char* in)\n{\n  size_t insize = strlen(in), i;\n  if(string_resize(out, insize))\n  {\n    for(i = 0; i != insize; ++i)\n    {\n      (*out)[i] = in[i];\n    }\n  }\n}\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n#endif /*LODEPNG_COMPILE_PNG*/\n\n/* ////////////////////////////////////////////////////////////////////////// */\n\nunsigned lodepng_read32bitInt(const unsigned char* buffer)\n{\n  return (unsigned)((buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]);\n}\n\n#if defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER)\n/*buffer must have at least 4 allocated bytes available*/\nstatic void lodepng_set32bitInt(unsigned char* buffer, unsigned value)\n{\n  buffer[0] = (unsigned char)((value >> 24) & 0xff);\n  buffer[1] = (unsigned char)((value >> 16) & 0xff);\n  buffer[2] = (unsigned char)((value >>  8) & 0xff);\n  buffer[3] = (unsigned char)((value      ) & 0xff);\n}\n#endif /*defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER)*/\n\n#ifdef LODEPNG_COMPILE_ENCODER\nstatic void lodepng_add32bitInt(ucvector* buffer, unsigned value)\n{\n  ucvector_resize(buffer, buffer->size + 4); /*todo: give error if resize failed*/\n  lodepng_set32bitInt(&buffer->data[buffer->size - 4], value);\n}\n#endif /*LODEPNG_COMPILE_ENCODER*/\n\n/* ////////////////////////////////////////////////////////////////////////// */\n/* / File IO                                                                / */\n/* ////////////////////////////////////////////////////////////////////////// */\n\n#ifdef LODEPNG_COMPILE_DISK\n\n/* returns negative value on error. This should be pure C compatible, so no fstat. */\nstatic long lodepng_filesize(const char* filename)\n{\n  FILE* file;\n  long size;\n  file = fopen(filename, \"rb\");\n  if(!file) return -1;\n\n  if(fseek(file, 0, SEEK_END) != 0)\n  {\n    fclose(file);\n    return -1;\n  }\n\n  size = ftell(file);\n  /* It may give LONG_MAX as directory size, this is invalid for us. */\n  if(size == LONG_MAX) size = -1;\n\n  fclose(file);\n  return size;\n}\n\n/* load file into buffer that already has the correct allocated size. Returns error code.*/\nstatic unsigned lodepng_buffer_file(unsigned char* out, size_t size, const char* filename)\n{\n  FILE* file;\n  size_t readsize;\n  file = fopen(filename, \"rb\");\n  if(!file) return 78;\n\n  readsize = fread(out, 1, size, file);\n  fclose(file);\n\n  if (readsize != size) return 78;\n  return 0;\n}\n\nunsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* filename)\n{\n  long size = lodepng_filesize(filename);\n  if (size < 0) return 78;\n  *outsize = (size_t)size;\n\n  *out = (unsigned char*)lodepng_malloc((size_t)size);\n  if(!(*out) && size > 0) return 83; /*the above malloc failed*/\n\n  return lodepng_buffer_file(*out, (size_t)size, filename);\n}\n\n/*write given buffer to the file, overwriting the file, it doesn't append to it.*/\nunsigned lodepng_save_file(const unsigned char* buffer, size_t buffersize, const char* filename)\n{\n  FILE* file;\n  file = fopen(filename, \"wb\" );\n  if(!file) return 79;\n  fwrite((char*)buffer , 1 , buffersize, file);\n  fclose(file);\n  return 0;\n}\n\n#endif /*LODEPNG_COMPILE_DISK*/\n\n/* ////////////////////////////////////////////////////////////////////////// */\n/* ////////////////////////////////////////////////////////////////////////// */\n/* // End of common code and tools. Begin of Zlib related code.            // */\n/* ////////////////////////////////////////////////////////////////////////// */\n/* ////////////////////////////////////////////////////////////////////////// */\n\n#ifdef LODEPNG_COMPILE_ZLIB\n#ifdef LODEPNG_COMPILE_ENCODER\n/*TODO: this ignores potential out of memory errors*/\n#define addBitToStream(/*size_t**/ bitpointer, /*ucvector**/ bitstream, /*unsigned char*/ bit)\\\n{\\\n  /*add a new byte at the end*/\\\n  if(((*bitpointer) & 7) == 0) ucvector_push_back(bitstream, (unsigned char)0);\\\n  /*earlier bit of huffman code is in a lesser significant bit of an earlier byte*/\\\n  (bitstream->data[bitstream->size - 1]) |= (bit << ((*bitpointer) & 0x7));\\\n  ++(*bitpointer);\\\n}\n\nstatic void addBitsToStream(size_t* bitpointer, ucvector* bitstream, unsigned value, size_t nbits)\n{\n  size_t i;\n  for(i = 0; i != nbits; ++i) addBitToStream(bitpointer, bitstream, (unsigned char)((value >> i) & 1));\n}\n\nstatic void addBitsToStreamReversed(size_t* bitpointer, ucvector* bitstream, unsigned value, size_t nbits)\n{\n  size_t i;\n  for(i = 0; i != nbits; ++i) addBitToStream(bitpointer, bitstream, (unsigned char)((value >> (nbits - 1 - i)) & 1));\n}\n#endif /*LODEPNG_COMPILE_ENCODER*/\n\n#ifdef LODEPNG_COMPILE_DECODER\n\n#define READBIT(bitpointer, bitstream) ((bitstream[bitpointer >> 3] >> (bitpointer & 0x7)) & (unsigned char)1)\n\nstatic unsigned char readBitFromStream(size_t* bitpointer, const unsigned char* bitstream)\n{\n  unsigned char result = (unsigned char)(READBIT(*bitpointer, bitstream));\n  ++(*bitpointer);\n  return result;\n}\n\nstatic unsigned readBitsFromStream(size_t* bitpointer, const unsigned char* bitstream, size_t nbits)\n{\n  unsigned result = 0, i;\n  for(i = 0; i != nbits; ++i)\n  {\n    result += ((unsigned)READBIT(*bitpointer, bitstream)) << i;\n    ++(*bitpointer);\n  }\n  return result;\n}\n#endif /*LODEPNG_COMPILE_DECODER*/\n\n/* ////////////////////////////////////////////////////////////////////////// */\n/* / Deflate - Huffman                                                      / */\n/* ////////////////////////////////////////////////////////////////////////// */\n\n#define FIRST_LENGTH_CODE_INDEX 257\n#define LAST_LENGTH_CODE_INDEX 285\n/*256 literals, the end code, some length codes, and 2 unused codes*/\n#define NUM_DEFLATE_CODE_SYMBOLS 288\n/*the distance codes have their own symbols, 30 used, 2 unused*/\n#define NUM_DISTANCE_SYMBOLS 32\n/*the code length codes. 0-15: code lengths, 16: copy previous 3-6 times, 17: 3-10 zeros, 18: 11-138 zeros*/\n#define NUM_CODE_LENGTH_CODES 19\n\n/*the base lengths represented by codes 257-285*/\nstatic const unsigned LENGTHBASE[29]\n  = {3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59,\n     67, 83, 99, 115, 131, 163, 195, 227, 258};\n\n/*the extra bits used by codes 257-285 (added to base length)*/\nstatic const unsigned LENGTHEXTRA[29]\n  = {0, 0, 0, 0, 0, 0, 0,  0,  1,  1,  1,  1,  2,  2,  2,  2,  3,  3,  3,  3,\n      4,  4,  4,   4,   5,   5,   5,   5,   0};\n\n/*the base backwards distances (the bits of distance codes appear after length codes and use their own huffman tree)*/\nstatic const unsigned DISTANCEBASE[30]\n  = {1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513,\n     769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577};\n\n/*the extra bits of backwards distances (added to base)*/\nstatic const unsigned DISTANCEEXTRA[30]\n  = {0, 0, 0, 0, 1, 1, 2,  2,  3,  3,  4,  4,  5,  5,   6,   6,   7,   7,   8,\n       8,    9,    9,   10,   10,   11,   11,   12,    12,    13,    13};\n\n/*the order in which \"code length alphabet code lengths\" are stored, out of this\nthe huffman tree of the dynamic huffman tree lengths is generated*/\nstatic const unsigned CLCL_ORDER[NUM_CODE_LENGTH_CODES]\n  = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};\n\n/* ////////////////////////////////////////////////////////////////////////// */\n\n/*\nHuffman tree struct, containing multiple representations of the tree\n*/\ntypedef struct HuffmanTree\n{\n  unsigned* tree2d;\n  unsigned* tree1d;\n  unsigned* lengths; /*the lengths of the codes of the 1d-tree*/\n  unsigned maxbitlen; /*maximum number of bits a single code can get*/\n  unsigned numcodes; /*number of symbols in the alphabet = number of codes*/\n} HuffmanTree;\n\n/*function used for debug purposes to draw the tree in ascii art with C++*/\n/*\nstatic void HuffmanTree_draw(HuffmanTree* tree)\n{\n  std::cout << \"tree. length: \" << tree->numcodes << \" maxbitlen: \" << tree->maxbitlen << std::endl;\n  for(size_t i = 0; i != tree->tree1d.size; ++i)\n  {\n    if(tree->lengths.data[i])\n      std::cout << i << \" \" << tree->tree1d.data[i] << \" \" << tree->lengths.data[i] << std::endl;\n  }\n  std::cout << std::endl;\n}*/\n\nstatic void HuffmanTree_init(HuffmanTree* tree)\n{\n  tree->tree2d = 0;\n  tree->tree1d = 0;\n  tree->lengths = 0;\n}\n\nstatic void HuffmanTree_cleanup(HuffmanTree* tree)\n{\n  lodepng_free(tree->tree2d);\n  lodepng_free(tree->tree1d);\n  lodepng_free(tree->lengths);\n}\n\n/*the tree representation used by the decoder. return value is error*/\nstatic unsigned HuffmanTree_make2DTree(HuffmanTree* tree)\n{\n  unsigned nodefilled = 0; /*up to which node it is filled*/\n  unsigned treepos = 0; /*position in the tree (1 of the numcodes columns)*/\n  unsigned n, i;\n\n  tree->tree2d = (unsigned*)lodepng_malloc(tree->numcodes * 2 * sizeof(unsigned));\n  if(!tree->tree2d) return 83; /*alloc fail*/\n\n  /*\n  convert tree1d[] to tree2d[][]. In the 2D array, a value of 32767 means\n  uninited, a value >= numcodes is an address to another bit, a value < numcodes\n  is a code. The 2 rows are the 2 possible bit values (0 or 1), there are as\n  many columns as codes - 1.\n  A good huffman tree has N * 2 - 1 nodes, of which N - 1 are internal nodes.\n  Here, the internal nodes are stored (what their 0 and 1 option point to).\n  There is only memory for such good tree currently, if there are more nodes\n  (due to too long length codes), error 55 will happen\n  */\n  for(n = 0; n < tree->numcodes * 2; ++n)\n  {\n    tree->tree2d[n] = 32767; /*32767 here means the tree2d isn't filled there yet*/\n  }\n\n  for(n = 0; n < tree->numcodes; ++n) /*the codes*/\n  {\n    for(i = 0; i != tree->lengths[n]; ++i) /*the bits for this code*/\n    {\n      unsigned char bit = (unsigned char)((tree->tree1d[n] >> (tree->lengths[n] - i - 1)) & 1);\n      /*oversubscribed, see comment in lodepng_error_text*/\n      if(treepos > 2147483647 || treepos + 2 > tree->numcodes) return 55;\n      if(tree->tree2d[2 * treepos + bit] == 32767) /*not yet filled in*/\n      {\n        if(i + 1 == tree->lengths[n]) /*last bit*/\n        {\n          tree->tree2d[2 * treepos + bit] = n; /*put the current code in it*/\n          treepos = 0;\n        }\n        else\n        {\n          /*put address of the next step in here, first that address has to be found of course\n          (it's just nodefilled + 1)...*/\n          ++nodefilled;\n          /*addresses encoded with numcodes added to it*/\n          tree->tree2d[2 * treepos + bit] = nodefilled + tree->numcodes;\n          treepos = nodefilled;\n        }\n      }\n      else treepos = tree->tree2d[2 * treepos + bit] - tree->numcodes;\n    }\n  }\n\n  for(n = 0; n < tree->numcodes * 2; ++n)\n  {\n    if(tree->tree2d[n] == 32767) tree->tree2d[n] = 0; /*remove possible remaining 32767's*/\n  }\n\n  return 0;\n}\n\n/*\nSecond step for the ...makeFromLengths and ...makeFromFrequencies functions.\nnumcodes, lengths and maxbitlen must already be filled in correctly. return\nvalue is error.\n*/\nstatic unsigned HuffmanTree_makeFromLengths2(HuffmanTree* tree)\n{\n  uivector blcount;\n  uivector nextcode;\n  unsigned error = 0;\n  unsigned bits, n;\n\n  uivector_init(&blcount);\n  uivector_init(&nextcode);\n\n  tree->tree1d = (unsigned*)lodepng_malloc(tree->numcodes * sizeof(unsigned));\n  if(!tree->tree1d) error = 83; /*alloc fail*/\n\n  if(!uivector_resizev(&blcount, tree->maxbitlen + 1, 0)\n  || !uivector_resizev(&nextcode, tree->maxbitlen + 1, 0))\n    error = 83; /*alloc fail*/\n\n  if(!error)\n  {\n    /*step 1: count number of instances of each code length*/\n    for(bits = 0; bits != tree->numcodes; ++bits) ++blcount.data[tree->lengths[bits]];\n    /*step 2: generate the nextcode values*/\n    for(bits = 1; bits <= tree->maxbitlen; ++bits)\n    {\n      nextcode.data[bits] = (nextcode.data[bits - 1] + blcount.data[bits - 1]) << 1;\n    }\n    /*step 3: generate all the codes*/\n    for(n = 0; n != tree->numcodes; ++n)\n    {\n      if(tree->lengths[n] != 0) tree->tree1d[n] = nextcode.data[tree->lengths[n]]++;\n    }\n  }\n\n  uivector_cleanup(&blcount);\n  uivector_cleanup(&nextcode);\n\n  if(!error) return HuffmanTree_make2DTree(tree);\n  else return error;\n}\n\n/*\ngiven the code lengths (as stored in the PNG file), generate the tree as defined\nby Deflate. maxbitlen is the maximum bits that a code in the tree can have.\nreturn value is error.\n*/\nstatic unsigned HuffmanTree_makeFromLengths(HuffmanTree* tree, const unsigned* bitlen,\n                                            size_t numcodes, unsigned maxbitlen)\n{\n  unsigned i;\n  tree->lengths = (unsigned*)lodepng_malloc(numcodes * sizeof(unsigned));\n  if(!tree->lengths) return 83; /*alloc fail*/\n  for(i = 0; i != numcodes; ++i) tree->lengths[i] = bitlen[i];\n  tree->numcodes = (unsigned)numcodes; /*number of symbols*/\n  tree->maxbitlen = maxbitlen;\n  return HuffmanTree_makeFromLengths2(tree);\n}\n\n#ifdef LODEPNG_COMPILE_ENCODER\n\n/*BPM: Boundary Package Merge, see \"A Fast and Space-Economical Algorithm for Length-Limited Coding\",\nJyrki Katajainen, Alistair Moffat, Andrew Turpin, 1995.*/\n\n/*chain node for boundary package merge*/\ntypedef struct BPMNode\n{\n  int weight; /*the sum of all weights in this chain*/\n  unsigned index; /*index of this leaf node (called \"count\" in the paper)*/\n  struct BPMNode* tail; /*the next nodes in this chain (null if last)*/\n  int in_use;\n} BPMNode;\n\n/*lists of chains*/\ntypedef struct BPMLists\n{\n  /*memory pool*/\n  unsigned memsize;\n  BPMNode* memory;\n  unsigned numfree;\n  unsigned nextfree;\n  BPMNode** freelist;\n  /*two heads of lookahead chains per list*/\n  unsigned listsize;\n  BPMNode** chains0;\n  BPMNode** chains1;\n} BPMLists;\n\n/*creates a new chain node with the given parameters, from the memory in the lists */\nstatic BPMNode* bpmnode_create(BPMLists* lists, int weight, unsigned index, BPMNode* tail)\n{\n  unsigned i;\n  BPMNode* result;\n\n  /*memory full, so garbage collect*/\n  if(lists->nextfree >= lists->numfree)\n  {\n    /*mark only those that are in use*/\n    for(i = 0; i != lists->memsize; ++i) lists->memory[i].in_use = 0;\n    for(i = 0; i != lists->listsize; ++i)\n    {\n      BPMNode* node;\n      for(node = lists->chains0[i]; node != 0; node = node->tail) node->in_use = 1;\n      for(node = lists->chains1[i]; node != 0; node = node->tail) node->in_use = 1;\n    }\n    /*collect those that are free*/\n    lists->numfree = 0;\n    for(i = 0; i != lists->memsize; ++i)\n    {\n      if(!lists->memory[i].in_use) lists->freelist[lists->numfree++] = &lists->memory[i];\n    }\n    lists->nextfree = 0;\n  }\n\n  result = lists->freelist[lists->nextfree++];\n  result->weight = weight;\n  result->index = index;\n  result->tail = tail;\n  return result;\n}\n\n/*sort the leaves with stable mergesort*/\nstatic void bpmnode_sort(BPMNode* leaves, size_t num)\n{\n  BPMNode* mem = (BPMNode*)lodepng_malloc(sizeof(*leaves) * num);\n  size_t width, counter = 0;\n  for(width = 1; width < num; width *= 2)\n  {\n    BPMNode* a = (counter & 1) ? mem : leaves;\n    BPMNode* b = (counter & 1) ? leaves : mem;\n    size_t p;\n    for(p = 0; p < num; p += 2 * width)\n    {\n      size_t q = (p + width > num) ? num : (p + width);\n      size_t r = (p + 2 * width > num) ? num : (p + 2 * width);\n      size_t i = p, j = q, k;\n      for(k = p; k < r; k++)\n      {\n        if(i < q && (j >= r || a[i].weight <= a[j].weight)) b[k] = a[i++];\n        else b[k] = a[j++];\n      }\n    }\n    counter++;\n  }\n  if(counter & 1) memcpy(leaves, mem, sizeof(*leaves) * num);\n  lodepng_free(mem);\n}\n\n/*Boundary Package Merge step, numpresent is the amount of leaves, and c is the current chain.*/\nstatic void boundaryPM(BPMLists* lists, BPMNode* leaves, size_t numpresent, int c, int num)\n{\n  unsigned lastindex = lists->chains1[c]->index;\n\n  if(c == 0)\n  {\n    if(lastindex >= numpresent) return;\n    lists->chains0[c] = lists->chains1[c];\n    lists->chains1[c] = bpmnode_create(lists, leaves[lastindex].weight, lastindex + 1, 0);\n  }\n  else\n  {\n    /*sum of the weights of the head nodes of the previous lookahead chains.*/\n    int sum = lists->chains0[c - 1]->weight + lists->chains1[c - 1]->weight;\n    lists->chains0[c] = lists->chains1[c];\n    if(lastindex < numpresent && sum > leaves[lastindex].weight)\n    {\n      lists->chains1[c] = bpmnode_create(lists, leaves[lastindex].weight, lastindex + 1, lists->chains1[c]->tail);\n      return;\n    }\n    lists->chains1[c] = bpmnode_create(lists, sum, lastindex, lists->chains1[c - 1]);\n    /*in the end we are only interested in the chain of the last list, so no\n    need to recurse if we're at the last one (this gives measurable speedup)*/\n    if(num + 1 < (int)(2 * numpresent - 2))\n    {\n      boundaryPM(lists, leaves, numpresent, c - 1, num);\n      boundaryPM(lists, leaves, numpresent, c - 1, num);\n    }\n  }\n}\n\nunsigned lodepng_huffman_code_lengths(unsigned* lengths, const unsigned* frequencies,\n                                      size_t numcodes, unsigned maxbitlen)\n{\n  unsigned error = 0;\n  unsigned i;\n  size_t numpresent = 0; /*number of symbols with non-zero frequency*/\n  BPMNode* leaves; /*the symbols, only those with > 0 frequency*/\n\n  if(numcodes == 0) return 80; /*error: a tree of 0 symbols is not supposed to be made*/\n  if((1u << maxbitlen) < (unsigned)numcodes) return 80; /*error: represent all symbols*/\n\n  leaves = (BPMNode*)lodepng_malloc(numcodes * sizeof(*leaves));\n  if(!leaves) return 83; /*alloc fail*/\n\n  for(i = 0; i != numcodes; ++i)\n  {\n    if(frequencies[i] > 0)\n    {\n      leaves[numpresent].weight = (int)frequencies[i];\n      leaves[numpresent].index = i;\n      ++numpresent;\n    }\n  }\n\n  for(i = 0; i != numcodes; ++i) lengths[i] = 0;\n\n  /*ensure at least two present symbols. There should be at least one symbol\n  according to RFC 1951 section 3.2.7. Some decoders incorrectly require two. To\n  make these work as well ensure there are at least two symbols. The\n  Package-Merge code below also doesn't work correctly if there's only one\n  symbol, it'd give it the theoritical 0 bits but in practice zlib wants 1 bit*/\n  if(numpresent == 0)\n  {\n    lengths[0] = lengths[1] = 1; /*note that for RFC 1951 section 3.2.7, only lengths[0] = 1 is needed*/\n  }\n  else if(numpresent == 1)\n  {\n    lengths[leaves[0].index] = 1;\n    lengths[leaves[0].index == 0 ? 1 : 0] = 1;\n  }\n  else\n  {\n    BPMLists lists;\n    BPMNode* node;\n\n    bpmnode_sort(leaves, numpresent);\n\n    lists.listsize = maxbitlen;\n    lists.memsize = 2 * maxbitlen * (maxbitlen + 1);\n    lists.nextfree = 0;\n    lists.numfree = lists.memsize;\n    lists.memory = (BPMNode*)lodepng_malloc(lists.memsize * sizeof(*lists.memory));\n    lists.freelist = (BPMNode**)lodepng_malloc(lists.memsize * sizeof(BPMNode*));\n    lists.chains0 = (BPMNode**)lodepng_malloc(lists.listsize * sizeof(BPMNode*));\n    lists.chains1 = (BPMNode**)lodepng_malloc(lists.listsize * sizeof(BPMNode*));\n    if(!lists.memory || !lists.freelist || !lists.chains0 || !lists.chains1) error = 83; /*alloc fail*/\n\n    if(!error)\n    {\n      for(i = 0; i != lists.memsize; ++i) lists.freelist[i] = &lists.memory[i];\n\n      bpmnode_create(&lists, leaves[0].weight, 1, 0);\n      bpmnode_create(&lists, leaves[1].weight, 2, 0);\n\n      for(i = 0; i != lists.listsize; ++i)\n      {\n        lists.chains0[i] = &lists.memory[0];\n        lists.chains1[i] = &lists.memory[1];\n      }\n\n      /*each boundaryPM call adds one chain to the last list, and we need 2 * numpresent - 2 chains.*/\n      for(i = 2; i != 2 * numpresent - 2; ++i) boundaryPM(&lists, leaves, numpresent, (int)maxbitlen - 1, (int)i);\n\n      for(node = lists.chains1[maxbitlen - 1]; node; node = node->tail)\n      {\n        for(i = 0; i != node->index; ++i) ++lengths[leaves[i].index];\n      }\n    }\n\n    lodepng_free(lists.memory);\n    lodepng_free(lists.freelist);\n    lodepng_free(lists.chains0);\n    lodepng_free(lists.chains1);\n  }\n\n  lodepng_free(leaves);\n  return error;\n}\n\n/*Create the Huffman tree given the symbol frequencies*/\nstatic unsigned HuffmanTree_makeFromFrequencies(HuffmanTree* tree, const unsigned* frequencies,\n                                                size_t mincodes, size_t numcodes, unsigned maxbitlen)\n{\n  unsigned error = 0;\n  while(!frequencies[numcodes - 1] && numcodes > mincodes) --numcodes; /*trim zeroes*/\n  tree->maxbitlen = maxbitlen;\n  tree->numcodes = (unsigned)numcodes; /*number of symbols*/\n  tree->lengths = (unsigned*)lodepng_realloc(tree->lengths, numcodes * sizeof(unsigned));\n  if(!tree->lengths) return 83; /*alloc fail*/\n  /*initialize all lengths to 0*/\n  memset(tree->lengths, 0, numcodes * sizeof(unsigned));\n\n  error = lodepng_huffman_code_lengths(tree->lengths, frequencies, numcodes, maxbitlen);\n  if(!error) error = HuffmanTree_makeFromLengths2(tree);\n  return error;\n}\n\nstatic unsigned HuffmanTree_getCode(const HuffmanTree* tree, unsigned index)\n{\n  return tree->tree1d[index];\n}\n\nstatic unsigned HuffmanTree_getLength(const HuffmanTree* tree, unsigned index)\n{\n  return tree->lengths[index];\n}\n#endif /*LODEPNG_COMPILE_ENCODER*/\n\n/*get the literal and length code tree of a deflated block with fixed tree, as per the deflate specification*/\nstatic unsigned generateFixedLitLenTree(HuffmanTree* tree)\n{\n  unsigned i, error = 0;\n  unsigned* bitlen = (unsigned*)lodepng_malloc(NUM_DEFLATE_CODE_SYMBOLS * sizeof(unsigned));\n  if(!bitlen) return 83; /*alloc fail*/\n\n  /*288 possible codes: 0-255=literals, 256=endcode, 257-285=lengthcodes, 286-287=unused*/\n  for(i =   0; i <= 143; ++i) bitlen[i] = 8;\n  for(i = 144; i <= 255; ++i) bitlen[i] = 9;\n  for(i = 256; i <= 279; ++i) bitlen[i] = 7;\n  for(i = 280; i <= 287; ++i) bitlen[i] = 8;\n\n  error = HuffmanTree_makeFromLengths(tree, bitlen, NUM_DEFLATE_CODE_SYMBOLS, 15);\n\n  lodepng_free(bitlen);\n  return error;\n}\n\n/*get the distance code tree of a deflated block with fixed tree, as specified in the deflate specification*/\nstatic unsigned generateFixedDistanceTree(HuffmanTree* tree)\n{\n  unsigned i, error = 0;\n  unsigned* bitlen = (unsigned*)lodepng_malloc(NUM_DISTANCE_SYMBOLS * sizeof(unsigned));\n  if(!bitlen) return 83; /*alloc fail*/\n\n  /*there are 32 distance codes, but 30-31 are unused*/\n  for(i = 0; i != NUM_DISTANCE_SYMBOLS; ++i) bitlen[i] = 5;\n  error = HuffmanTree_makeFromLengths(tree, bitlen, NUM_DISTANCE_SYMBOLS, 15);\n\n  lodepng_free(bitlen);\n  return error;\n}\n\n#ifdef LODEPNG_COMPILE_DECODER\n\n/*\nreturns the code, or (unsigned)(-1) if error happened\ninbitlength is the length of the complete buffer, in bits (so its byte length times 8)\n*/\nstatic unsigned huffmanDecodeSymbol(const unsigned char* in, size_t* bp,\n                                    const HuffmanTree* codetree, size_t inbitlength)\n{\n  unsigned treepos = 0, ct;\n  for(;;)\n  {\n    if(*bp >= inbitlength) return (unsigned)(-1); /*error: end of input memory reached without endcode*/\n    /*\n    decode the symbol from the tree. The \"readBitFromStream\" code is inlined in\n    the expression below because this is the biggest bottleneck while decoding\n    */\n    ct = codetree->tree2d[(treepos << 1) + READBIT(*bp, in)];\n    ++(*bp);\n    if(ct < codetree->numcodes) return ct; /*the symbol is decoded, return it*/\n    else treepos = ct - codetree->numcodes; /*symbol not yet decoded, instead move tree position*/\n\n    if(treepos >= codetree->numcodes) return (unsigned)(-1); /*error: it appeared outside the codetree*/\n  }\n}\n#endif /*LODEPNG_COMPILE_DECODER*/\n\n#ifdef LODEPNG_COMPILE_DECODER\n\n/* ////////////////////////////////////////////////////////////////////////// */\n/* / Inflator (Decompressor)                                                / */\n/* ////////////////////////////////////////////////////////////////////////// */\n\n/*get the tree of a deflated block with fixed tree, as specified in the deflate specification*/\nstatic void getTreeInflateFixed(HuffmanTree* tree_ll, HuffmanTree* tree_d)\n{\n  /*TODO: check for out of memory errors*/\n  generateFixedLitLenTree(tree_ll);\n  generateFixedDistanceTree(tree_d);\n}\n\n/*get the tree of a deflated block with dynamic tree, the tree itself is also Huffman compressed with a known tree*/\nstatic unsigned getTreeInflateDynamic(HuffmanTree* tree_ll, HuffmanTree* tree_d,\n                                      const unsigned char* in, size_t* bp, size_t inlength)\n{\n  /*make sure that length values that aren't filled in will be 0, or a wrong tree will be generated*/\n  unsigned error = 0;\n  unsigned n, HLIT, HDIST, HCLEN, i;\n  size_t inbitlength = inlength * 8;\n\n  /*see comments in deflateDynamic for explanation of the context and these variables, it is analogous*/\n  unsigned* bitlen_ll = 0; /*lit,len code lengths*/\n  unsigned* bitlen_d = 0; /*dist code lengths*/\n  /*code length code lengths (\"clcl\"), the bit lengths of the huffman tree used to compress bitlen_ll and bitlen_d*/\n  unsigned* bitlen_cl = 0;\n  HuffmanTree tree_cl; /*the code tree for code length codes (the huffman tree for compressed huffman trees)*/\n\n  if((*bp) + 14 > (inlength << 3)) return 49; /*error: the bit pointer is or will go past the memory*/\n\n  /*number of literal/length codes + 257. Unlike the spec, the value 257 is added to it here already*/\n  HLIT =  readBitsFromStream(bp, in, 5) + 257;\n  /*number of distance codes. Unlike the spec, the value 1 is added to it here already*/\n  HDIST = readBitsFromStream(bp, in, 5) + 1;\n  /*number of code length codes. Unlike the spec, the value 4 is added to it here already*/\n  HCLEN = readBitsFromStream(bp, in, 4) + 4;\n\n  if((*bp) + HCLEN * 3 > (inlength << 3)) return 50; /*error: the bit pointer is or will go past the memory*/\n\n  HuffmanTree_init(&tree_cl);\n\n  while(!error)\n  {\n    /*read the code length codes out of 3 * (amount of code length codes) bits*/\n\n    bitlen_cl = (unsigned*)lodepng_malloc(NUM_CODE_LENGTH_CODES * sizeof(unsigned));\n    if(!bitlen_cl) ERROR_BREAK(83 /*alloc fail*/);\n\n    for(i = 0; i != NUM_CODE_LENGTH_CODES; ++i)\n    {\n      if(i < HCLEN) bitlen_cl[CLCL_ORDER[i]] = readBitsFromStream(bp, in, 3);\n      else bitlen_cl[CLCL_ORDER[i]] = 0; /*if not, it must stay 0*/\n    }\n\n    error = HuffmanTree_makeFromLengths(&tree_cl, bitlen_cl, NUM_CODE_LENGTH_CODES, 7);\n    if(error) break;\n\n    /*now we can use this tree to read the lengths for the tree that this function will return*/\n    bitlen_ll = (unsigned*)lodepng_malloc(NUM_DEFLATE_CODE_SYMBOLS * sizeof(unsigned));\n    bitlen_d = (unsigned*)lodepng_malloc(NUM_DISTANCE_SYMBOLS * sizeof(unsigned));\n    if(!bitlen_ll || !bitlen_d) ERROR_BREAK(83 /*alloc fail*/);\n    for(i = 0; i != NUM_DEFLATE_CODE_SYMBOLS; ++i) bitlen_ll[i] = 0;\n    for(i = 0; i != NUM_DISTANCE_SYMBOLS; ++i) bitlen_d[i] = 0;\n\n    /*i is the current symbol we're reading in the part that contains the code lengths of lit/len and dist codes*/\n    i = 0;\n    while(i < HLIT + HDIST)\n    {\n      unsigned code = huffmanDecodeSymbol(in, bp, &tree_cl, inbitlength);\n      if(code <= 15) /*a length code*/\n      {\n        if(i < HLIT) bitlen_ll[i] = code;\n        else bitlen_d[i - HLIT] = code;\n        ++i;\n      }\n      else if(code == 16) /*repeat previous*/\n      {\n        unsigned replength = 3; /*read in the 2 bits that indicate repeat length (3-6)*/\n        unsigned value; /*set value to the previous code*/\n\n        if(i == 0) ERROR_BREAK(54); /*can't repeat previous if i is 0*/\n\n        if((*bp + 2) > inbitlength) ERROR_BREAK(50); /*error, bit pointer jumps past memory*/\n        replength += readBitsFromStream(bp, in, 2);\n\n        if(i < HLIT + 1) value = bitlen_ll[i - 1];\n        else value = bitlen_d[i - HLIT - 1];\n        /*repeat this value in the next lengths*/\n        for(n = 0; n < replength; ++n)\n        {\n          if(i >= HLIT + HDIST) ERROR_BREAK(13); /*error: i is larger than the amount of codes*/\n          if(i < HLIT) bitlen_ll[i] = value;\n          else bitlen_d[i - HLIT] = value;\n          ++i;\n        }\n      }\n      else if(code == 17) /*repeat \"0\" 3-10 times*/\n      {\n        unsigned replength = 3; /*read in the bits that indicate repeat length*/\n        if((*bp + 3) > inbitlength) ERROR_BREAK(50); /*error, bit pointer jumps past memory*/\n        replength += readBitsFromStream(bp, in, 3);\n\n        /*repeat this value in the next lengths*/\n        for(n = 0; n < replength; ++n)\n        {\n          if(i >= HLIT + HDIST) ERROR_BREAK(14); /*error: i is larger than the amount of codes*/\n\n          if(i < HLIT) bitlen_ll[i] = 0;\n          else bitlen_d[i - HLIT] = 0;\n          ++i;\n        }\n      }\n      else if(code == 18) /*repeat \"0\" 11-138 times*/\n      {\n        unsigned replength = 11; /*read in the bits that indicate repeat length*/\n        if((*bp + 7) > inbitlength) ERROR_BREAK(50); /*error, bit pointer jumps past memory*/\n        replength += readBitsFromStream(bp, in, 7);\n\n        /*repeat this value in the next lengths*/\n        for(n = 0; n < replength; ++n)\n        {\n          if(i >= HLIT + HDIST) ERROR_BREAK(15); /*error: i is larger than the amount of codes*/\n\n          if(i < HLIT) bitlen_ll[i] = 0;\n          else bitlen_d[i - HLIT] = 0;\n          ++i;\n        }\n      }\n      else /*if(code == (unsigned)(-1))*/ /*huffmanDecodeSymbol returns (unsigned)(-1) in case of error*/\n      {\n        if(code == (unsigned)(-1))\n        {\n          /*return error code 10 or 11 depending on the situation that happened in huffmanDecodeSymbol\n          (10=no endcode, 11=wrong jump outside of tree)*/\n          error = (*bp) > inbitlength ? 10 : 11;\n        }\n        else error = 16; /*unexisting code, this can never happen*/\n        break;\n      }\n    }\n    if(error) break;\n\n    if(bitlen_ll[256] == 0) ERROR_BREAK(64); /*the length of the end code 256 must be larger than 0*/\n\n    /*now we've finally got HLIT and HDIST, so generate the code trees, and the function is done*/\n    error = HuffmanTree_makeFromLengths(tree_ll, bitlen_ll, NUM_DEFLATE_CODE_SYMBOLS, 15);\n    if(error) break;\n    error = HuffmanTree_makeFromLengths(tree_d, bitlen_d, NUM_DISTANCE_SYMBOLS, 15);\n\n    break; /*end of error-while*/\n  }\n\n  lodepng_free(bitlen_cl);\n  lodepng_free(bitlen_ll);\n  lodepng_free(bitlen_d);\n  HuffmanTree_cleanup(&tree_cl);\n\n  return error;\n}\n\n/*inflate a block with dynamic of fixed Huffman tree*/\nstatic unsigned inflateHuffmanBlock(ucvector* out, const unsigned char* in, size_t* bp,\n                                    size_t* pos, size_t inlength, unsigned btype)\n{\n  unsigned error = 0;\n  HuffmanTree tree_ll; /*the huffman tree for literal and length codes*/\n  HuffmanTree tree_d; /*the huffman tree for distance codes*/\n  size_t inbitlength = inlength * 8;\n\n  HuffmanTree_init(&tree_ll);\n  HuffmanTree_init(&tree_d);\n\n  if(btype == 1) getTreeInflateFixed(&tree_ll, &tree_d);\n  else if(btype == 2) error = getTreeInflateDynamic(&tree_ll, &tree_d, in, bp, inlength);\n\n  while(!error) /*decode all symbols until end reached, breaks at end code*/\n  {\n    /*code_ll is literal, length or end code*/\n    unsigned code_ll = huffmanDecodeSymbol(in, bp, &tree_ll, inbitlength);\n    if(code_ll <= 255) /*literal symbol*/\n    {\n      /*ucvector_push_back would do the same, but for some reason the two lines below run 10% faster*/\n      if(!ucvector_resize(out, (*pos) + 1)) ERROR_BREAK(83 /*alloc fail*/);\n      out->data[*pos] = (unsigned char)code_ll;\n      ++(*pos);\n    }\n    else if(code_ll >= FIRST_LENGTH_CODE_INDEX && code_ll <= LAST_LENGTH_CODE_INDEX) /*length code*/\n    {\n      unsigned code_d, distance;\n      unsigned numextrabits_l, numextrabits_d; /*extra bits for length and distance*/\n      size_t start, forward, backward, length;\n\n      /*part 1: get length base*/\n      length = LENGTHBASE[code_ll - FIRST_LENGTH_CODE_INDEX];\n\n      /*part 2: get extra bits and add the value of that to length*/\n      numextrabits_l = LENGTHEXTRA[code_ll - FIRST_LENGTH_CODE_INDEX];\n      if((*bp + numextrabits_l) > inbitlength) ERROR_BREAK(51); /*error, bit pointer will jump past memory*/\n      length += readBitsFromStream(bp, in, numextrabits_l);\n\n      /*part 3: get distance code*/\n      code_d = huffmanDecodeSymbol(in, bp, &tree_d, inbitlength);\n      if(code_d > 29)\n      {\n        if(code_d == (unsigned)(-1)) /*huffmanDecodeSymbol returns (unsigned)(-1) in case of error*/\n        {\n          /*return error code 10 or 11 depending on the situation that happened in huffmanDecodeSymbol\n          (10=no endcode, 11=wrong jump outside of tree)*/\n          error = (*bp) > inlength * 8 ? 10 : 11;\n        }\n        else error = 18; /*error: invalid distance code (30-31 are never used)*/\n        break;\n      }\n      distance = DISTANCEBASE[code_d];\n\n      /*part 4: get extra bits from distance*/\n      numextrabits_d = DISTANCEEXTRA[code_d];\n      if((*bp + numextrabits_d) > inbitlength) ERROR_BREAK(51); /*error, bit pointer will jump past memory*/\n      distance += readBitsFromStream(bp, in, numextrabits_d);\n\n      /*part 5: fill in all the out[n] values based on the length and dist*/\n      start = (*pos);\n      if(distance > start) ERROR_BREAK(52); /*too long backward distance*/\n      backward = start - distance;\n\n      if(!ucvector_resize(out, (*pos) + length)) ERROR_BREAK(83 /*alloc fail*/);\n      if (distance < length) {\n        for(forward = 0; forward < length; ++forward)\n        {\n          out->data[(*pos)++] = out->data[backward++];\n        }\n      } else {\n        memcpy(out->data + *pos, out->data + backward, length);\n        *pos += length;\n      }\n    }\n    else if(code_ll == 256)\n    {\n      break; /*end code, break the loop*/\n    }\n    else /*if(code == (unsigned)(-1))*/ /*huffmanDecodeSymbol returns (unsigned)(-1) in case of error*/\n    {\n      /*return error code 10 or 11 depending on the situation that happened in huffmanDecodeSymbol\n      (10=no endcode, 11=wrong jump outside of tree)*/\n      error = ((*bp) > inlength * 8) ? 10 : 11;\n      break;\n    }\n  }\n\n  HuffmanTree_cleanup(&tree_ll);\n  HuffmanTree_cleanup(&tree_d);\n\n  return error;\n}\n\nstatic unsigned inflateNoCompression(ucvector* out, const unsigned char* in, size_t* bp, size_t* pos, size_t inlength)\n{\n  size_t p;\n  unsigned LEN, NLEN, n, error = 0;\n\n  /*go to first boundary of byte*/\n  while(((*bp) & 0x7) != 0) ++(*bp);\n  p = (*bp) / 8; /*byte position*/\n\n  /*read LEN (2 bytes) and NLEN (2 bytes)*/\n  if(p + 4 >= inlength) return 52; /*error, bit pointer will jump past memory*/\n  LEN = in[p] + 256u * in[p + 1]; p += 2;\n  NLEN = in[p] + 256u * in[p + 1]; p += 2;\n\n  /*check if 16-bit NLEN is really the one's complement of LEN*/\n  if(LEN + NLEN != 65535) return 21; /*error: NLEN is not one's complement of LEN*/\n\n  if(!ucvector_resize(out, (*pos) + LEN)) return 83; /*alloc fail*/\n\n  /*read the literal data: LEN bytes are now stored in the out buffer*/\n  if(p + LEN > inlength) return 23; /*error: reading outside of in buffer*/\n  for(n = 0; n < LEN; ++n) out->data[(*pos)++] = in[p++];\n\n  (*bp) = p * 8;\n\n  return error;\n}\n\nstatic unsigned lodepng_inflatev(ucvector* out,\n                                 const unsigned char* in, size_t insize,\n                                 const LodePNGDecompressSettings* settings)\n{\n  /*bit pointer in the \"in\" data, current byte is bp >> 3, current bit is bp & 0x7 (from lsb to msb of the byte)*/\n  size_t bp = 0;\n  unsigned BFINAL = 0;\n  size_t pos = 0; /*byte position in the out buffer*/\n  unsigned error = 0;\n\n  (void)settings;\n\n  while(!BFINAL)\n  {\n    unsigned BTYPE;\n    if(bp + 2 >= insize * 8) return 52; /*error, bit pointer will jump past memory*/\n    BFINAL = readBitFromStream(&bp, in);\n    BTYPE = 1u * readBitFromStream(&bp, in);\n    BTYPE += 2u * readBitFromStream(&bp, in);\n\n    if(BTYPE == 3) return 20; /*error: invalid BTYPE*/\n    else if(BTYPE == 0) error = inflateNoCompression(out, in, &bp, &pos, insize); /*no compression*/\n    else error = inflateHuffmanBlock(out, in, &bp, &pos, insize, BTYPE); /*compression, BTYPE 01 or 10*/\n\n    if(error) return error;\n  }\n\n  return error;\n}\n\nunsigned lodepng_inflate(unsigned char** out, size_t* outsize,\n                         const unsigned char* in, size_t insize,\n                         const LodePNGDecompressSettings* settings)\n{\n  unsigned error;\n  ucvector v;\n  ucvector_init_buffer(&v, *out, *outsize);\n  error = lodepng_inflatev(&v, in, insize, settings);\n  *out = v.data;\n  *outsize = v.size;\n  return error;\n}\n\nstatic unsigned inflate(unsigned char** out, size_t* outsize,\n                        const unsigned char* in, size_t insize,\n                        const LodePNGDecompressSettings* settings)\n{\n  if(settings->custom_inflate)\n  {\n    return settings->custom_inflate(out, outsize, in, insize, settings);\n  }\n  else\n  {\n    return lodepng_inflate(out, outsize, in, insize, settings);\n  }\n}\n\n#endif /*LODEPNG_COMPILE_DECODER*/\n\n#ifdef LODEPNG_COMPILE_ENCODER\n\n/* ////////////////////////////////////////////////////////////////////////// */\n/* / Deflator (Compressor)                                                  / */\n/* ////////////////////////////////////////////////////////////////////////// */\n\nstatic const size_t MAX_SUPPORTED_DEFLATE_LENGTH = 258;\n\n/*bitlen is the size in bits of the code*/\nstatic void addHuffmanSymbol(size_t* bp, ucvector* compressed, unsigned code, unsigned bitlen)\n{\n  addBitsToStreamReversed(bp, compressed, code, bitlen);\n}\n\n/*search the index in the array, that has the largest value smaller than or equal to the given value,\ngiven array must be sorted (if no value is smaller, it returns the size of the given array)*/\nstatic size_t searchCodeIndex(const unsigned* array, size_t array_size, size_t value)\n{\n  /*binary search (only small gain over linear). TODO: use CPU log2 instruction for getting symbols instead*/\n  size_t left = 1;\n  size_t right = array_size - 1;\n\n  while(left <= right) {\n    size_t mid = (left + right) >> 1;\n    if (array[mid] >= value) right = mid - 1;\n    else left = mid + 1;\n  }\n  if(left >= array_size || array[left] > value) left--;\n  return left;\n}\n\nstatic void addLengthDistance(uivector* values, size_t length, size_t distance)\n{\n  /*values in encoded vector are those used by deflate:\n  0-255: literal bytes\n  256: end\n  257-285: length/distance pair (length code, followed by extra length bits, distance code, extra distance bits)\n  286-287: invalid*/\n\n  unsigned length_code = (unsigned)searchCodeIndex(LENGTHBASE, 29, length);\n  unsigned extra_length = (unsigned)(length - LENGTHBASE[length_code]);\n  unsigned dist_code = (unsigned)searchCodeIndex(DISTANCEBASE, 30, distance);\n  unsigned extra_distance = (unsigned)(distance - DISTANCEBASE[dist_code]);\n\n  uivector_push_back(values, length_code + FIRST_LENGTH_CODE_INDEX);\n  uivector_push_back(values, extra_length);\n  uivector_push_back(values, dist_code);\n  uivector_push_back(values, extra_distance);\n}\n\n/*3 bytes of data get encoded into two bytes. The hash cannot use more than 3\nbytes as input because 3 is the minimum match length for deflate*/\nstatic const unsigned HASH_NUM_VALUES = 65536;\nstatic const unsigned HASH_BIT_MASK = 65535; /*HASH_NUM_VALUES - 1, but C90 does not like that as initializer*/\n\ntypedef struct Hash\n{\n  int* head; /*hash value to head circular pos - can be outdated if went around window*/\n  /*circular pos to prev circular pos*/\n  unsigned short* chain;\n  int* val; /*circular pos to hash value*/\n\n  /*TODO: do this not only for zeros but for any repeated byte. However for PNG\n  it's always going to be the zeros that dominate, so not important for PNG*/\n  int* headz; /*similar to head, but for chainz*/\n  unsigned short* chainz; /*those with same amount of zeros*/\n  unsigned short* zeros; /*length of zeros streak, used as a second hash chain*/\n} Hash;\n\nstatic unsigned hash_init(Hash* hash, unsigned windowsize)\n{\n  unsigned i;\n  hash->head = (int*)lodepng_malloc(sizeof(int) * HASH_NUM_VALUES);\n  hash->val = (int*)lodepng_malloc(sizeof(int) * windowsize);\n  hash->chain = (unsigned short*)lodepng_malloc(sizeof(unsigned short) * windowsize);\n\n  hash->zeros = (unsigned short*)lodepng_malloc(sizeof(unsigned short) * windowsize);\n  hash->headz = (int*)lodepng_malloc(sizeof(int) * (MAX_SUPPORTED_DEFLATE_LENGTH + 1));\n  hash->chainz = (unsigned short*)lodepng_malloc(sizeof(unsigned short) * windowsize);\n\n  if(!hash->head || !hash->chain || !hash->val  || !hash->headz|| !hash->chainz || !hash->zeros)\n  {\n    return 83; /*alloc fail*/\n  }\n\n  /*initialize hash table*/\n  for(i = 0; i != HASH_NUM_VALUES; ++i) hash->head[i] = -1;\n  for(i = 0; i != windowsize; ++i) hash->val[i] = -1;\n  for(i = 0; i != windowsize; ++i) hash->chain[i] = i; /*same value as index indicates uninitialized*/\n\n  for(i = 0; i <= MAX_SUPPORTED_DEFLATE_LENGTH; ++i) hash->headz[i] = -1;\n  for(i = 0; i != windowsize; ++i) hash->chainz[i] = i; /*same value as index indicates uninitialized*/\n\n  return 0;\n}\n\nstatic void hash_cleanup(Hash* hash)\n{\n  lodepng_free(hash->head);\n  lodepng_free(hash->val);\n  lodepng_free(hash->chain);\n\n  lodepng_free(hash->zeros);\n  lodepng_free(hash->headz);\n  lodepng_free(hash->chainz);\n}\n\n\n\nstatic unsigned getHash(const unsigned char* data, size_t size, size_t pos)\n{\n  unsigned result = 0;\n  if(pos + 2 < size)\n  {\n    /*A simple shift and xor hash is used. Since the data of PNGs is dominated\n    by zeroes due to the filters, a better hash does not have a significant\n    effect on speed in traversing the chain, and causes more time spend on\n    calculating the hash.*/\n    result ^= (unsigned)(data[pos + 0] << 0u);\n    result ^= (unsigned)(data[pos + 1] << 4u);\n    result ^= (unsigned)(data[pos + 2] << 8u);\n  } else {\n    size_t amount, i;\n    if(pos >= size) return 0;\n    amount = size - pos;\n    for(i = 0; i != amount; ++i) result ^= (unsigned)(data[pos + i] << (i * 8u));\n  }\n  return result & HASH_BIT_MASK;\n}\n\nstatic unsigned countZeros(const unsigned char* data, size_t size, size_t pos)\n{\n  const unsigned char* start = data + pos;\n  const unsigned char* end = start + MAX_SUPPORTED_DEFLATE_LENGTH;\n  if(end > data + size) end = data + size;\n  data = start;\n  while(data != end && *data == 0) ++data;\n  /*subtracting two addresses returned as 32-bit number (max value is MAX_SUPPORTED_DEFLATE_LENGTH)*/\n  return (unsigned)(data - start);\n}\n\n/*wpos = pos & (windowsize - 1)*/\nstatic void updateHashChain(Hash* hash, size_t wpos, unsigned hashval, unsigned short numzeros)\n{\n  hash->val[wpos] = (int)hashval;\n  if(hash->head[hashval] != -1) hash->chain[wpos] = hash->head[hashval];\n  hash->head[hashval] = (unsigned)wpos;\n\n  hash->zeros[wpos] = numzeros;\n  if(hash->headz[numzeros] != -1) hash->chainz[wpos] = hash->headz[numzeros];\n  hash->headz[numzeros] = (unsigned)wpos;\n}\n\n/*\nLZ77-encode the data. Return value is error code. The input are raw bytes, the output\nis in the form of unsigned integers with codes representing for example literal bytes, or\nlength/distance pairs.\nIt uses a hash table technique to let it encode faster. When doing LZ77 encoding, a\nsliding window (of windowsize) is used, and all past bytes in that window can be used as\nthe \"dictionary\". A brute force search through all possible distances would be slow, and\nthis hash technique is one out of several ways to speed this up.\n*/\nstatic unsigned encodeLZ77(uivector* out, Hash* hash,\n                           const unsigned char* in, size_t inpos, size_t insize, unsigned windowsize,\n                           unsigned minmatch, unsigned nicematch, unsigned lazymatching)\n{\n  size_t pos;\n  unsigned i, error = 0;\n  /*for large window lengths, assume the user wants no compression loss. Otherwise, max hash chain length speedup.*/\n  unsigned maxchainlength = windowsize >= 8192 ? windowsize : windowsize / 8;\n  unsigned maxlazymatch = windowsize >= 8192 ? MAX_SUPPORTED_DEFLATE_LENGTH : 64;\n\n  unsigned usezeros = 1; /*not sure if setting it to false for windowsize < 8192 is better or worse*/\n  unsigned numzeros = 0;\n\n  unsigned offset; /*the offset represents the distance in LZ77 terminology*/\n  unsigned length;\n  unsigned lazy = 0;\n  unsigned lazylength = 0, lazyoffset = 0;\n  unsigned hashval;\n  unsigned current_offset, current_length;\n  unsigned prev_offset;\n  const unsigned char *lastptr, *foreptr, *backptr;\n  unsigned hashpos;\n\n  if(windowsize == 0 || windowsize > 32768) return 60; /*error: windowsize smaller/larger than allowed*/\n  if((windowsize & (windowsize - 1)) != 0) return 90; /*error: must be power of two*/\n\n  if(nicematch > MAX_SUPPORTED_DEFLATE_LENGTH) nicematch = MAX_SUPPORTED_DEFLATE_LENGTH;\n\n  for(pos = inpos; pos < insize; ++pos)\n  {\n    size_t wpos = pos & (windowsize - 1); /*position for in 'circular' hash buffers*/\n    unsigned chainlength = 0;\n\n    hashval = getHash(in, insize, pos);\n\n    if(usezeros && hashval == 0)\n    {\n      if(numzeros == 0) numzeros = countZeros(in, insize, pos);\n      else if(pos + numzeros > insize || in[pos + numzeros - 1] != 0) --numzeros;\n    }\n    else\n    {\n      numzeros = 0;\n    }\n\n    updateHashChain(hash, wpos, hashval, numzeros);\n\n    /*the length and offset found for the current position*/\n    length = 0;\n    offset = 0;\n\n    hashpos = hash->chain[wpos];\n\n    lastptr = &in[insize < pos + MAX_SUPPORTED_DEFLATE_LENGTH ? insize : pos + MAX_SUPPORTED_DEFLATE_LENGTH];\n\n    /*search for the longest string*/\n    prev_offset = 0;\n    for(;;)\n    {\n      if(chainlength++ >= maxchainlength) break;\n      current_offset = (unsigned)(hashpos <= wpos ? wpos - hashpos : wpos - hashpos + windowsize);\n\n      if(current_offset < prev_offset) break; /*stop when went completely around the circular buffer*/\n      prev_offset = current_offset;\n      if(current_offset > 0)\n      {\n        /*test the next characters*/\n        foreptr = &in[pos];\n        backptr = &in[pos - current_offset];\n\n        /*common case in PNGs is lots of zeros. Quickly skip over them as a speedup*/\n        if(numzeros >= 3)\n        {\n          unsigned skip = hash->zeros[hashpos];\n          if(skip > numzeros) skip = numzeros;\n          backptr += skip;\n          foreptr += skip;\n        }\n\n        while(foreptr != lastptr && *backptr == *foreptr) /*maximum supported length by deflate is max length*/\n        {\n          ++backptr;\n          ++foreptr;\n        }\n        current_length = (unsigned)(foreptr - &in[pos]);\n\n        if(current_length > length)\n        {\n          length = current_length; /*the longest length*/\n          offset = current_offset; /*the offset that is related to this longest length*/\n          /*jump out once a length of max length is found (speed gain). This also jumps\n          out if length is MAX_SUPPORTED_DEFLATE_LENGTH*/\n          if(current_length >= nicematch) break;\n        }\n      }\n\n      if(hashpos == hash->chain[hashpos]) break;\n\n      if(numzeros >= 3 && length > numzeros)\n      {\n        hashpos = hash->chainz[hashpos];\n        if(hash->zeros[hashpos] != numzeros) break;\n      }\n      else\n      {\n        hashpos = hash->chain[hashpos];\n        /*outdated hash value, happens if particular value was not encountered in whole last window*/\n        if(hash->val[hashpos] != (int)hashval) break;\n      }\n    }\n\n    if(lazymatching)\n    {\n      if(!lazy && length >= 3 && length <= maxlazymatch && length < MAX_SUPPORTED_DEFLATE_LENGTH)\n      {\n        lazy = 1;\n        lazylength = length;\n        lazyoffset = offset;\n        continue; /*try the next byte*/\n      }\n      if(lazy)\n      {\n        lazy = 0;\n        if(pos == 0) ERROR_BREAK(81);\n        if(length > lazylength + 1)\n        {\n          /*push the previous character as literal*/\n          if(!uivector_push_back(out, in[pos - 1])) ERROR_BREAK(83 /*alloc fail*/);\n        }\n        else\n        {\n          length = lazylength;\n          offset = lazyoffset;\n          hash->head[hashval] = -1; /*the same hashchain update will be done, this ensures no wrong alteration*/\n          hash->headz[numzeros] = -1; /*idem*/\n          --pos;\n        }\n      }\n    }\n    if(length >= 3 && offset > windowsize) ERROR_BREAK(86 /*too big (or overflown negative) offset*/);\n\n    /*encode it as length/distance pair or literal value*/\n    if(length < 3) /*only lengths of 3 or higher are supported as length/distance pair*/\n    {\n      if(!uivector_push_back(out, in[pos])) ERROR_BREAK(83 /*alloc fail*/);\n    }\n    else if(length < minmatch || (length == 3 && offset > 4096))\n    {\n      /*compensate for the fact that longer offsets have more extra bits, a\n      length of only 3 may be not worth it then*/\n      if(!uivector_push_back(out, in[pos])) ERROR_BREAK(83 /*alloc fail*/);\n    }\n    else\n    {\n      addLengthDistance(out, length, offset);\n      for(i = 1; i < length; ++i)\n      {\n        ++pos;\n        wpos = pos & (windowsize - 1);\n        hashval = getHash(in, insize, pos);\n        if(usezeros && hashval == 0)\n        {\n          if(numzeros == 0) numzeros = countZeros(in, insize, pos);\n          else if(pos + numzeros > insize || in[pos + numzeros - 1] != 0) --numzeros;\n        }\n        else\n        {\n          numzeros = 0;\n        }\n        updateHashChain(hash, wpos, hashval, numzeros);\n      }\n    }\n  } /*end of the loop through each character of input*/\n\n  return error;\n}\n\n/* /////////////////////////////////////////////////////////////////////////// */\n\nstatic unsigned deflateNoCompression(ucvector* out, const unsigned char* data, size_t datasize)\n{\n  /*non compressed deflate block data: 1 bit BFINAL,2 bits BTYPE,(5 bits): it jumps to start of next byte,\n  2 bytes LEN, 2 bytes NLEN, LEN bytes literal DATA*/\n\n  size_t i, j, numdeflateblocks = (datasize + 65534) / 65535;\n  unsigned datapos = 0;\n  for(i = 0; i != numdeflateblocks; ++i)\n  {\n    unsigned BFINAL, BTYPE, LEN, NLEN;\n    unsigned char firstbyte;\n\n    BFINAL = (i == numdeflateblocks - 1);\n    BTYPE = 0;\n\n    firstbyte = (unsigned char)(BFINAL + ((BTYPE & 1) << 1) + ((BTYPE & 2) << 1));\n    ucvector_push_back(out, firstbyte);\n\n    LEN = 65535;\n    if(datasize - datapos < 65535) LEN = (unsigned)datasize - datapos;\n    NLEN = 65535 - LEN;\n\n    ucvector_push_back(out, (unsigned char)(LEN & 255));\n    ucvector_push_back(out, (unsigned char)(LEN >> 8));\n    ucvector_push_back(out, (unsigned char)(NLEN & 255));\n    ucvector_push_back(out, (unsigned char)(NLEN >> 8));\n\n    /*Decompressed data*/\n    for(j = 0; j < 65535 && datapos < datasize; ++j)\n    {\n      ucvector_push_back(out, data[datapos++]);\n    }\n  }\n\n  return 0;\n}\n\n/*\nwrite the lz77-encoded data, which has lit, len and dist codes, to compressed stream using huffman trees.\ntree_ll: the tree for lit and len codes.\ntree_d: the tree for distance codes.\n*/\nstatic void writeLZ77data(size_t* bp, ucvector* out, const uivector* lz77_encoded,\n                          const HuffmanTree* tree_ll, const HuffmanTree* tree_d)\n{\n  size_t i = 0;\n  for(i = 0; i != lz77_encoded->size; ++i)\n  {\n    unsigned val = lz77_encoded->data[i];\n    addHuffmanSymbol(bp, out, HuffmanTree_getCode(tree_ll, val), HuffmanTree_getLength(tree_ll, val));\n    if(val > 256) /*for a length code, 3 more things have to be added*/\n    {\n      unsigned length_index = val - FIRST_LENGTH_CODE_INDEX;\n      unsigned n_length_extra_bits = LENGTHEXTRA[length_index];\n      unsigned length_extra_bits = lz77_encoded->data[++i];\n\n      unsigned distance_code = lz77_encoded->data[++i];\n\n      unsigned distance_index = distance_code;\n      unsigned n_distance_extra_bits = DISTANCEEXTRA[distance_index];\n      unsigned distance_extra_bits = lz77_encoded->data[++i];\n\n      addBitsToStream(bp, out, length_extra_bits, n_length_extra_bits);\n      addHuffmanSymbol(bp, out, HuffmanTree_getCode(tree_d, distance_code),\n                       HuffmanTree_getLength(tree_d, distance_code));\n      addBitsToStream(bp, out, distance_extra_bits, n_distance_extra_bits);\n    }\n  }\n}\n\n/*Deflate for a block of type \"dynamic\", that is, with freely, optimally, created huffman trees*/\nstatic unsigned deflateDynamic(ucvector* out, size_t* bp, Hash* hash,\n                               const unsigned char* data, size_t datapos, size_t dataend,\n                               const LodePNGCompressSettings* settings, unsigned final)\n{\n  unsigned error = 0;\n\n  /*\n  A block is compressed as follows: The PNG data is lz77 encoded, resulting in\n  literal bytes and length/distance pairs. This is then huffman compressed with\n  two huffman trees. One huffman tree is used for the lit and len values (\"ll\"),\n  another huffman tree is used for the dist values (\"d\"). These two trees are\n  stored using their code lengths, and to compress even more these code lengths\n  are also run-length encoded and huffman compressed. This gives a huffman tree\n  of code lengths \"cl\". The code lenghts used to describe this third tree are\n  the code length code lengths (\"clcl\").\n  */\n\n  /*The lz77 encoded data, represented with integers since there will also be length and distance codes in it*/\n  uivector lz77_encoded;\n  HuffmanTree tree_ll; /*tree for lit,len values*/\n  HuffmanTree tree_d; /*tree for distance codes*/\n  HuffmanTree tree_cl; /*tree for encoding the code lengths representing tree_ll and tree_d*/\n  uivector frequencies_ll; /*frequency of lit,len codes*/\n  uivector frequencies_d; /*frequency of dist codes*/\n  uivector frequencies_cl; /*frequency of code length codes*/\n  uivector bitlen_lld; /*lit,len,dist code lenghts (int bits), literally (without repeat codes).*/\n  uivector bitlen_lld_e; /*bitlen_lld encoded with repeat codes (this is a rudemtary run length compression)*/\n  /*bitlen_cl is the code length code lengths (\"clcl\"). The bit lengths of codes to represent tree_cl\n  (these are written as is in the file, it would be crazy to compress these using yet another huffman\n  tree that needs to be represented by yet another set of code lengths)*/\n  uivector bitlen_cl;\n  size_t datasize = dataend - datapos;\n\n  /*\n  Due to the huffman compression of huffman tree representations (\"two levels\"), there are some anologies:\n  bitlen_lld is to tree_cl what data is to tree_ll and tree_d.\n  bitlen_lld_e is to bitlen_lld what lz77_encoded is to data.\n  bitlen_cl is to bitlen_lld_e what bitlen_lld is to lz77_encoded.\n  */\n\n  unsigned BFINAL = final;\n  size_t numcodes_ll, numcodes_d, i;\n  unsigned HLIT, HDIST, HCLEN;\n\n  uivector_init(&lz77_encoded);\n  HuffmanTree_init(&tree_ll);\n  HuffmanTree_init(&tree_d);\n  HuffmanTree_init(&tree_cl);\n  uivector_init(&frequencies_ll);\n  uivector_init(&frequencies_d);\n  uivector_init(&frequencies_cl);\n  uivector_init(&bitlen_lld);\n  uivector_init(&bitlen_lld_e);\n  uivector_init(&bitlen_cl);\n\n  /*This while loop never loops due to a break at the end, it is here to\n  allow breaking out of it to the cleanup phase on error conditions.*/\n  while(!error)\n  {\n    if(settings->use_lz77)\n    {\n      error = encodeLZ77(&lz77_encoded, hash, data, datapos, dataend, settings->windowsize,\n                         settings->minmatch, settings->nicematch, settings->lazymatching);\n      if(error) break;\n    }\n    else\n    {\n      if(!uivector_resize(&lz77_encoded, datasize)) ERROR_BREAK(83 /*alloc fail*/);\n      for(i = datapos; i < dataend; ++i) lz77_encoded.data[i - datapos] = data[i]; /*no LZ77, but still will be Huffman compressed*/\n    }\n\n    if(!uivector_resizev(&frequencies_ll, 286, 0)) ERROR_BREAK(83 /*alloc fail*/);\n    if(!uivector_resizev(&frequencies_d, 30, 0)) ERROR_BREAK(83 /*alloc fail*/);\n\n    /*Count the frequencies of lit, len and dist codes*/\n    for(i = 0; i != lz77_encoded.size; ++i)\n    {\n      unsigned symbol = lz77_encoded.data[i];\n      ++frequencies_ll.data[symbol];\n      if(symbol > 256)\n      {\n        unsigned dist = lz77_encoded.data[i + 2];\n        ++frequencies_d.data[dist];\n        i += 3;\n      }\n    }\n    frequencies_ll.data[256] = 1; /*there will be exactly 1 end code, at the end of the block*/\n\n    /*Make both huffman trees, one for the lit and len codes, one for the dist codes*/\n    error = HuffmanTree_makeFromFrequencies(&tree_ll, frequencies_ll.data, 257, frequencies_ll.size, 15);\n    if(error) break;\n    /*2, not 1, is chosen for mincodes: some buggy PNG decoders require at least 2 symbols in the dist tree*/\n    error = HuffmanTree_makeFromFrequencies(&tree_d, frequencies_d.data, 2, frequencies_d.size, 15);\n    if(error) break;\n\n    numcodes_ll = tree_ll.numcodes; if(numcodes_ll > 286) numcodes_ll = 286;\n    numcodes_d = tree_d.numcodes; if(numcodes_d > 30) numcodes_d = 30;\n    /*store the code lengths of both generated trees in bitlen_lld*/\n    for(i = 0; i != numcodes_ll; ++i) uivector_push_back(&bitlen_lld, HuffmanTree_getLength(&tree_ll, (unsigned)i));\n    for(i = 0; i != numcodes_d; ++i) uivector_push_back(&bitlen_lld, HuffmanTree_getLength(&tree_d, (unsigned)i));\n\n    /*run-length compress bitlen_ldd into bitlen_lld_e by using repeat codes 16 (copy length 3-6 times),\n    17 (3-10 zeroes), 18 (11-138 zeroes)*/\n    for(i = 0; i != (unsigned)bitlen_lld.size; ++i)\n    {\n      unsigned j = 0; /*amount of repititions*/\n      while(i + j + 1 < (unsigned)bitlen_lld.size && bitlen_lld.data[i + j + 1] == bitlen_lld.data[i]) ++j;\n\n      if(bitlen_lld.data[i] == 0 && j >= 2) /*repeat code for zeroes*/\n      {\n        ++j; /*include the first zero*/\n        if(j <= 10) /*repeat code 17 supports max 10 zeroes*/\n        {\n          uivector_push_back(&bitlen_lld_e, 17);\n          uivector_push_back(&bitlen_lld_e, j - 3);\n        }\n        else /*repeat code 18 supports max 138 zeroes*/\n        {\n          if(j > 138) j = 138;\n          uivector_push_back(&bitlen_lld_e, 18);\n          uivector_push_back(&bitlen_lld_e, j - 11);\n        }\n        i += (j - 1);\n      }\n      else if(j >= 3) /*repeat code for value other than zero*/\n      {\n        size_t k;\n        unsigned num = j / 6, rest = j % 6;\n        uivector_push_back(&bitlen_lld_e, bitlen_lld.data[i]);\n        for(k = 0; k < num; ++k)\n        {\n          uivector_push_back(&bitlen_lld_e, 16);\n          uivector_push_back(&bitlen_lld_e, 6 - 3);\n        }\n        if(rest >= 3)\n        {\n          uivector_push_back(&bitlen_lld_e, 16);\n          uivector_push_back(&bitlen_lld_e, rest - 3);\n        }\n        else j -= rest;\n        i += j;\n      }\n      else /*too short to benefit from repeat code*/\n      {\n        uivector_push_back(&bitlen_lld_e, bitlen_lld.data[i]);\n      }\n    }\n\n    /*generate tree_cl, the huffmantree of huffmantrees*/\n\n    if(!uivector_resizev(&frequencies_cl, NUM_CODE_LENGTH_CODES, 0)) ERROR_BREAK(83 /*alloc fail*/);\n    for(i = 0; i != bitlen_lld_e.size; ++i)\n    {\n      ++frequencies_cl.data[bitlen_lld_e.data[i]];\n      /*after a repeat code come the bits that specify the number of repetitions,\n      those don't need to be in the frequencies_cl calculation*/\n      if(bitlen_lld_e.data[i] >= 16) ++i;\n    }\n\n    error = HuffmanTree_makeFromFrequencies(&tree_cl, frequencies_cl.data,\n                                            frequencies_cl.size, frequencies_cl.size, 7);\n    if(error) break;\n\n    if(!uivector_resize(&bitlen_cl, tree_cl.numcodes)) ERROR_BREAK(83 /*alloc fail*/);\n    for(i = 0; i != tree_cl.numcodes; ++i)\n    {\n      /*lenghts of code length tree is in the order as specified by deflate*/\n      bitlen_cl.data[i] = HuffmanTree_getLength(&tree_cl, CLCL_ORDER[i]);\n    }\n    while(bitlen_cl.data[bitlen_cl.size - 1] == 0 && bitlen_cl.size > 4)\n    {\n      /*remove zeros at the end, but minimum size must be 4*/\n      if(!uivector_resize(&bitlen_cl, bitlen_cl.size - 1)) ERROR_BREAK(83 /*alloc fail*/);\n    }\n    if(error) break;\n\n    /*\n    Write everything into the output\n\n    After the BFINAL and BTYPE, the dynamic block consists out of the following:\n    - 5 bits HLIT, 5 bits HDIST, 4 bits HCLEN\n    - (HCLEN+4)*3 bits code lengths of code length alphabet\n    - HLIT + 257 code lenghts of lit/length alphabet (encoded using the code length\n      alphabet, + possible repetition codes 16, 17, 18)\n    - HDIST + 1 code lengths of distance alphabet (encoded using the code length\n      alphabet, + possible repetition codes 16, 17, 18)\n    - compressed data\n    - 256 (end code)\n    */\n\n    /*Write block type*/\n    addBitToStream(bp, out, BFINAL);\n    addBitToStream(bp, out, 0); /*first bit of BTYPE \"dynamic\"*/\n    addBitToStream(bp, out, 1); /*second bit of BTYPE \"dynamic\"*/\n\n    /*write the HLIT, HDIST and HCLEN values*/\n    HLIT = (unsigned)(numcodes_ll - 257);\n    HDIST = (unsigned)(numcodes_d - 1);\n    HCLEN = (unsigned)bitlen_cl.size - 4;\n    /*trim zeroes for HCLEN. HLIT and HDIST were already trimmed at tree creation*/\n    while(!bitlen_cl.data[HCLEN + 4 - 1] && HCLEN > 0) --HCLEN;\n    addBitsToStream(bp, out, HLIT, 5);\n    addBitsToStream(bp, out, HDIST, 5);\n    addBitsToStream(bp, out, HCLEN, 4);\n\n    /*write the code lenghts of the code length alphabet*/\n    for(i = 0; i != HCLEN + 4; ++i) addBitsToStream(bp, out, bitlen_cl.data[i], 3);\n\n    /*write the lenghts of the lit/len AND the dist alphabet*/\n    for(i = 0; i != bitlen_lld_e.size; ++i)\n    {\n      addHuffmanSymbol(bp, out, HuffmanTree_getCode(&tree_cl, bitlen_lld_e.data[i]),\n                       HuffmanTree_getLength(&tree_cl, bitlen_lld_e.data[i]));\n      /*extra bits of repeat codes*/\n      if(bitlen_lld_e.data[i] == 16) addBitsToStream(bp, out, bitlen_lld_e.data[++i], 2);\n      else if(bitlen_lld_e.data[i] == 17) addBitsToStream(bp, out, bitlen_lld_e.data[++i], 3);\n      else if(bitlen_lld_e.data[i] == 18) addBitsToStream(bp, out, bitlen_lld_e.data[++i], 7);\n    }\n\n    /*write the compressed data symbols*/\n    writeLZ77data(bp, out, &lz77_encoded, &tree_ll, &tree_d);\n    /*error: the length of the end code 256 must be larger than 0*/\n    if(HuffmanTree_getLength(&tree_ll, 256) == 0) ERROR_BREAK(64);\n\n    /*write the end code*/\n    addHuffmanSymbol(bp, out, HuffmanTree_getCode(&tree_ll, 256), HuffmanTree_getLength(&tree_ll, 256));\n\n    break; /*end of error-while*/\n  }\n\n  /*cleanup*/\n  uivector_cleanup(&lz77_encoded);\n  HuffmanTree_cleanup(&tree_ll);\n  HuffmanTree_cleanup(&tree_d);\n  HuffmanTree_cleanup(&tree_cl);\n  uivector_cleanup(&frequencies_ll);\n  uivector_cleanup(&frequencies_d);\n  uivector_cleanup(&frequencies_cl);\n  uivector_cleanup(&bitlen_lld_e);\n  uivector_cleanup(&bitlen_lld);\n  uivector_cleanup(&bitlen_cl);\n\n  return error;\n}\n\nstatic unsigned deflateFixed(ucvector* out, size_t* bp, Hash* hash,\n                             const unsigned char* data,\n                             size_t datapos, size_t dataend,\n                             const LodePNGCompressSettings* settings, unsigned final)\n{\n  HuffmanTree tree_ll; /*tree for literal values and length codes*/\n  HuffmanTree tree_d; /*tree for distance codes*/\n\n  unsigned BFINAL = final;\n  unsigned error = 0;\n  size_t i;\n\n  HuffmanTree_init(&tree_ll);\n  HuffmanTree_init(&tree_d);\n\n  generateFixedLitLenTree(&tree_ll);\n  generateFixedDistanceTree(&tree_d);\n\n  addBitToStream(bp, out, BFINAL);\n  addBitToStream(bp, out, 1); /*first bit of BTYPE*/\n  addBitToStream(bp, out, 0); /*second bit of BTYPE*/\n\n  if(settings->use_lz77) /*LZ77 encoded*/\n  {\n    uivector lz77_encoded;\n    uivector_init(&lz77_encoded);\n    error = encodeLZ77(&lz77_encoded, hash, data, datapos, dataend, settings->windowsize,\n                       settings->minmatch, settings->nicematch, settings->lazymatching);\n    if(!error) writeLZ77data(bp, out, &lz77_encoded, &tree_ll, &tree_d);\n    uivector_cleanup(&lz77_encoded);\n  }\n  else /*no LZ77, but still will be Huffman compressed*/\n  {\n    for(i = datapos; i < dataend; ++i)\n    {\n      addHuffmanSymbol(bp, out, HuffmanTree_getCode(&tree_ll, data[i]), HuffmanTree_getLength(&tree_ll, data[i]));\n    }\n  }\n  /*add END code*/\n  if(!error) addHuffmanSymbol(bp, out, HuffmanTree_getCode(&tree_ll, 256), HuffmanTree_getLength(&tree_ll, 256));\n\n  /*cleanup*/\n  HuffmanTree_cleanup(&tree_ll);\n  HuffmanTree_cleanup(&tree_d);\n\n  return error;\n}\n\nstatic unsigned lodepng_deflatev(ucvector* out, const unsigned char* in, size_t insize,\n                                 const LodePNGCompressSettings* settings)\n{\n  unsigned error = 0;\n  size_t i, blocksize, numdeflateblocks;\n  size_t bp = 0; /*the bit pointer*/\n  Hash hash;\n\n  if(settings->btype > 2) return 61;\n  else if(settings->btype == 0) return deflateNoCompression(out, in, insize);\n  else if(settings->btype == 1) blocksize = insize;\n  else /*if(settings->btype == 2)*/\n  {\n    /*on PNGs, deflate blocks of 65-262k seem to give most dense encoding*/\n    blocksize = insize / 8 + 8;\n    if(blocksize < 65536) blocksize = 65536;\n    if(blocksize > 262144) blocksize = 262144;\n  }\n\n  numdeflateblocks = (insize + blocksize - 1) / blocksize;\n  if(numdeflateblocks == 0) numdeflateblocks = 1;\n\n  error = hash_init(&hash, settings->windowsize);\n  if(error) return error;\n\n  for(i = 0; i != numdeflateblocks && !error; ++i)\n  {\n    unsigned final = (i == numdeflateblocks - 1);\n    size_t start = i * blocksize;\n    size_t end = start + blocksize;\n    if(end > insize) end = insize;\n\n    if(settings->btype == 1) error = deflateFixed(out, &bp, &hash, in, start, end, settings, final);\n    else if(settings->btype == 2) error = deflateDynamic(out, &bp, &hash, in, start, end, settings, final);\n  }\n\n  hash_cleanup(&hash);\n\n  return error;\n}\n\nunsigned lodepng_deflate(unsigned char** out, size_t* outsize,\n                         const unsigned char* in, size_t insize,\n                         const LodePNGCompressSettings* settings)\n{\n  unsigned error;\n  ucvector v;\n  ucvector_init_buffer(&v, *out, *outsize);\n  error = lodepng_deflatev(&v, in, insize, settings);\n  *out = v.data;\n  *outsize = v.size;\n  return error;\n}\n\nstatic unsigned deflate(unsigned char** out, size_t* outsize,\n                        const unsigned char* in, size_t insize,\n                        const LodePNGCompressSettings* settings)\n{\n  if(settings->custom_deflate)\n  {\n    return settings->custom_deflate(out, outsize, in, insize, settings);\n  }\n  else\n  {\n    return lodepng_deflate(out, outsize, in, insize, settings);\n  }\n}\n\n#endif /*LODEPNG_COMPILE_DECODER*/\n\n/* ////////////////////////////////////////////////////////////////////////// */\n/* / Adler32                                                                  */\n/* ////////////////////////////////////////////////////////////////////////// */\n\nstatic unsigned update_adler32(unsigned adler, const unsigned char* data, unsigned len)\n{\n   unsigned s1 = adler & 0xffff;\n   unsigned s2 = (adler >> 16) & 0xffff;\n\n  while(len > 0)\n  {\n    /*at least 5550 sums can be done before the sums overflow, saving a lot of module divisions*/\n    unsigned amount = len > 5550 ? 5550 : len;\n    len -= amount;\n    while(amount > 0)\n    {\n      s1 += (*data++);\n      s2 += s1;\n      --amount;\n    }\n    s1 %= 65521;\n    s2 %= 65521;\n  }\n\n  return (s2 << 16) | s1;\n}\n\n/*Return the adler32 of the bytes data[0..len-1]*/\nstatic unsigned adler32(const unsigned char* data, unsigned len)\n{\n  return update_adler32(1L, data, len);\n}\n\n/* ////////////////////////////////////////////////////////////////////////// */\n/* / Zlib                                                                   / */\n/* ////////////////////////////////////////////////////////////////////////// */\n\n#ifdef LODEPNG_COMPILE_DECODER\n\nunsigned lodepng_zlib_decompress(unsigned char** out, size_t* outsize, const unsigned char* in,\n                                 size_t insize, const LodePNGDecompressSettings* settings)\n{\n  unsigned error = 0;\n  unsigned CM, CINFO, FDICT;\n\n  if(insize < 2) return 53; /*error, size of zlib data too small*/\n  /*read information from zlib header*/\n  if((in[0] * 256 + in[1]) % 31 != 0)\n  {\n    /*error: 256 * in[0] + in[1] must be a multiple of 31, the FCHECK value is supposed to be made that way*/\n    return 24;\n  }\n\n  CM = in[0] & 15;\n  CINFO = (in[0] >> 4) & 15;\n  /*FCHECK = in[1] & 31;*/ /*FCHECK is already tested above*/\n  FDICT = (in[1] >> 5) & 1;\n  /*FLEVEL = (in[1] >> 6) & 3;*/ /*FLEVEL is not used here*/\n\n  if(CM != 8 || CINFO > 7)\n  {\n    /*error: only compression method 8: inflate with sliding window of 32k is supported by the PNG spec*/\n    return 25;\n  }\n  if(FDICT != 0)\n  {\n    /*error: the specification of PNG says about the zlib stream:\n      \"The additional flags shall not specify a preset dictionary.\"*/\n    return 26;\n  }\n\n  error = inflate(out, outsize, in + 2, insize - 2, settings);\n  if(error) return error;\n\n  if(!settings->ignore_adler32)\n  {\n    unsigned ADLER32 = lodepng_read32bitInt(&in[insize - 4]);\n    unsigned checksum = adler32(*out, (unsigned)(*outsize));\n    if(checksum != ADLER32) return 58; /*error, adler checksum not correct, data must be corrupted*/\n  }\n\n  return 0; /*no error*/\n}\n\nstatic unsigned zlib_decompress(unsigned char** out, size_t* outsize, const unsigned char* in,\n                                size_t insize, const LodePNGDecompressSettings* settings)\n{\n  if(settings->custom_zlib)\n  {\n    return settings->custom_zlib(out, outsize, in, insize, settings);\n  }\n  else\n  {\n    return lodepng_zlib_decompress(out, outsize, in, insize, settings);\n  }\n}\n\n#endif /*LODEPNG_COMPILE_DECODER*/\n\n#ifdef LODEPNG_COMPILE_ENCODER\n\nunsigned lodepng_zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in,\n                               size_t insize, const LodePNGCompressSettings* settings)\n{\n  /*initially, *out must be NULL and outsize 0, if you just give some random *out\n  that's pointing to a non allocated buffer, this'll crash*/\n  ucvector outv;\n  size_t i;\n  unsigned error;\n  unsigned char* deflatedata = 0;\n  size_t deflatesize = 0;\n\n  /*zlib data: 1 byte CMF (CM+CINFO), 1 byte FLG, deflate data, 4 byte ADLER32 checksum of the Decompressed data*/\n  unsigned CMF = 120; /*0b01111000: CM 8, CINFO 7. With CINFO 7, any window size up to 32768 can be used.*/\n  unsigned FLEVEL = 0;\n  unsigned FDICT = 0;\n  unsigned CMFFLG = 256 * CMF + FDICT * 32 + FLEVEL * 64;\n  unsigned FCHECK = 31 - CMFFLG % 31;\n  CMFFLG += FCHECK;\n\n  /*ucvector-controlled version of the output buffer, for dynamic array*/\n  ucvector_init_buffer(&outv, *out, *outsize);\n\n  ucvector_push_back(&outv, (unsigned char)(CMFFLG >> 8));\n  ucvector_push_back(&outv, (unsigned char)(CMFFLG & 255));\n\n  error = deflate(&deflatedata, &deflatesize, in, insize, settings);\n\n  if(!error)\n  {\n    unsigned ADLER32 = adler32(in, (unsigned)insize);\n    for(i = 0; i != deflatesize; ++i) ucvector_push_back(&outv, deflatedata[i]);\n    lodepng_free(deflatedata);\n    lodepng_add32bitInt(&outv, ADLER32);\n  }\n\n  *out = outv.data;\n  *outsize = outv.size;\n\n  return error;\n}\n\n/* compress using the default or custom zlib function */\nstatic unsigned zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in,\n                              size_t insize, const LodePNGCompressSettings* settings)\n{\n  if(settings->custom_zlib)\n  {\n    return settings->custom_zlib(out, outsize, in, insize, settings);\n  }\n  else\n  {\n    return lodepng_zlib_compress(out, outsize, in, insize, settings);\n  }\n}\n\n#endif /*LODEPNG_COMPILE_ENCODER*/\n\n#else /*no LODEPNG_COMPILE_ZLIB*/\n\n#ifdef LODEPNG_COMPILE_DECODER\nstatic unsigned zlib_decompress(unsigned char** out, size_t* outsize, const unsigned char* in,\n                                size_t insize, const LodePNGDecompressSettings* settings)\n{\n  if(!settings->custom_zlib) return 87; /*no custom zlib function provided */\n  return settings->custom_zlib(out, outsize, in, insize, settings);\n}\n#endif /*LODEPNG_COMPILE_DECODER*/\n#ifdef LODEPNG_COMPILE_ENCODER\nstatic unsigned zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in,\n                              size_t insize, const LodePNGCompressSettings* settings)\n{\n  if(!settings->custom_zlib) return 87; /*no custom zlib function provided */\n  return settings->custom_zlib(out, outsize, in, insize, settings);\n}\n#endif /*LODEPNG_COMPILE_ENCODER*/\n\n#endif /*LODEPNG_COMPILE_ZLIB*/\n\n/* ////////////////////////////////////////////////////////////////////////// */\n\n#ifdef LODEPNG_COMPILE_ENCODER\n\n/*this is a good tradeoff between speed and compression ratio*/\n#define DEFAULT_WINDOWSIZE 2048\n\nvoid lodepng_compress_settings_init(LodePNGCompressSettings* settings)\n{\n  /*compress with dynamic huffman tree (not in the mathematical sense, just not the predefined one)*/\n  settings->btype = 2;\n  settings->use_lz77 = 1;\n  settings->windowsize = DEFAULT_WINDOWSIZE;\n  settings->minmatch = 3;\n  settings->nicematch = 128;\n  settings->lazymatching = 1;\n\n  settings->custom_zlib = 0;\n  settings->custom_deflate = 0;\n  settings->custom_context = 0;\n}\n\nconst LodePNGCompressSettings lodepng_default_compress_settings = {2, 1, DEFAULT_WINDOWSIZE, 3, 128, 1, 0, 0, 0};\n\n\n#endif /*LODEPNG_COMPILE_ENCODER*/\n\n#ifdef LODEPNG_COMPILE_DECODER\n\nvoid lodepng_decompress_settings_init(LodePNGDecompressSettings* settings)\n{\n  settings->ignore_adler32 = 0;\n\n  settings->custom_zlib = 0;\n  settings->custom_inflate = 0;\n  settings->custom_context = 0;\n}\n\nconst LodePNGDecompressSettings lodepng_default_decompress_settings = {0, 0, 0, 0};\n\n#endif /*LODEPNG_COMPILE_DECODER*/\n\n/* ////////////////////////////////////////////////////////////////////////// */\n/* ////////////////////////////////////////////////////////////////////////// */\n/* // End of Zlib related code. Begin of PNG related code.                 // */\n/* ////////////////////////////////////////////////////////////////////////// */\n/* ////////////////////////////////////////////////////////////////////////// */\n\n#ifdef LODEPNG_COMPILE_PNG\n\n/* ////////////////////////////////////////////////////////////////////////// */\n/* / CRC32                                                                  / */\n/* ////////////////////////////////////////////////////////////////////////// */\n\n\n#ifndef LODEPNG_NO_COMPILE_CRC\n/* CRC polynomial: 0xedb88320 */\nstatic unsigned lodepng_crc32_table[256] = {\n           0u, 1996959894u, 3993919788u, 2567524794u,  124634137u, 1886057615u, 3915621685u, 2657392035u,\n   249268274u, 2044508324u, 3772115230u, 2547177864u,  162941995u, 2125561021u, 3887607047u, 2428444049u,\n   498536548u, 1789927666u, 4089016648u, 2227061214u,  450548861u, 1843258603u, 4107580753u, 2211677639u,\n   325883990u, 1684777152u, 4251122042u, 2321926636u,  335633487u, 1661365465u, 4195302755u, 2366115317u,\n   997073096u, 1281953886u, 3579855332u, 2724688242u, 1006888145u, 1258607687u, 3524101629u, 2768942443u,\n   901097722u, 1119000684u, 3686517206u, 2898065728u,  853044451u, 1172266101u, 3705015759u, 2882616665u,\n   651767980u, 1373503546u, 3369554304u, 3218104598u,  565507253u, 1454621731u, 3485111705u, 3099436303u,\n   671266974u, 1594198024u, 3322730930u, 2970347812u,  795835527u, 1483230225u, 3244367275u, 3060149565u,\n  1994146192u,   31158534u, 2563907772u, 4023717930u, 1907459465u,  112637215u, 2680153253u, 3904427059u,\n  2013776290u,  251722036u, 2517215374u, 3775830040u, 2137656763u,  141376813u, 2439277719u, 3865271297u,\n  1802195444u,  476864866u, 2238001368u, 4066508878u, 1812370925u,  453092731u, 2181625025u, 4111451223u,\n  1706088902u,  314042704u, 2344532202u, 4240017532u, 1658658271u,  366619977u, 2362670323u, 4224994405u,\n  1303535960u,  984961486u, 2747007092u, 3569037538u, 1256170817u, 1037604311u, 2765210733u, 3554079995u,\n  1131014506u,  879679996u, 2909243462u, 3663771856u, 1141124467u,  855842277u, 2852801631u, 3708648649u,\n  1342533948u,  654459306u, 3188396048u, 3373015174u, 1466479909u,  544179635u, 3110523913u, 3462522015u,\n  1591671054u,  702138776u, 2966460450u, 3352799412u, 1504918807u,  783551873u, 3082640443u, 3233442989u,\n  3988292384u, 2596254646u,   62317068u, 1957810842u, 3939845945u, 2647816111u,   81470997u, 1943803523u,\n  3814918930u, 2489596804u,  225274430u, 2053790376u, 3826175755u, 2466906013u,  167816743u, 2097651377u,\n  4027552580u, 2265490386u,  503444072u, 1762050814u, 4150417245u, 2154129355u,  426522225u, 1852507879u,\n  4275313526u, 2312317920u,  282753626u, 1742555852u, 4189708143u, 2394877945u,  397917763u, 1622183637u,\n  3604390888u, 2714866558u,  953729732u, 1340076626u, 3518719985u, 2797360999u, 1068828381u, 1219638859u,\n  3624741850u, 2936675148u,  906185462u, 1090812512u, 3747672003u, 2825379669u,  829329135u, 1181335161u,\n  3412177804u, 3160834842u,  628085408u, 1382605366u, 3423369109u, 3138078467u,  570562233u, 1426400815u,\n  3317316542u, 2998733608u,  733239954u, 1555261956u, 3268935591u, 3050360625u,  752459403u, 1541320221u,\n  2607071920u, 3965973030u, 1969922972u,   40735498u, 2617837225u, 3943577151u, 1913087877u,   83908371u,\n  2512341634u, 3803740692u, 2075208622u,  213261112u, 2463272603u, 3855990285u, 2094854071u,  198958881u,\n  2262029012u, 4057260610u, 1759359992u,  534414190u, 2176718541u, 4139329115u, 1873836001u,  414664567u,\n  2282248934u, 4279200368u, 1711684554u,  285281116u, 2405801727u, 4167216745u, 1634467795u,  376229701u,\n  2685067896u, 3608007406u, 1308918612u,  956543938u, 2808555105u, 3495958263u, 1231636301u, 1047427035u,\n  2932959818u, 3654703836u, 1088359270u,  936918000u, 2847714899u, 3736837829u, 1202900863u,  817233897u,\n  3183342108u, 3401237130u, 1404277552u,  615818150u, 3134207493u, 3453421203u, 1423857449u,  601450431u,\n  3009837614u, 3294710456u, 1567103746u,  711928724u, 3020668471u, 3272380065u, 1510334235u,  755167117u\n};\n\n/*Return the CRC of the bytes buf[0..len-1].*/\nunsigned lodepng_crc32(const unsigned char* data, size_t length)\n{\n  unsigned r = 0xffffffffu;\n  size_t i;\n  for(i = 0; i < length; ++i)\n  {\n    r = lodepng_crc32_table[(r ^ data[i]) & 0xff] ^ (r >> 8);\n  }\n  return r ^ 0xffffffffu;\n}\n#else /* !LODEPNG_NO_COMPILE_CRC */\nunsigned lodepng_crc32(const unsigned char* data, size_t length);\n#endif /* !LODEPNG_NO_COMPILE_CRC */\n\n/* ////////////////////////////////////////////////////////////////////////// */\n/* / Reading and writing single bits and bytes from/to stream for LodePNG   / */\n/* ////////////////////////////////////////////////////////////////////////// */\n\nstatic unsigned char readBitFromReversedStream(size_t* bitpointer, const unsigned char* bitstream)\n{\n  unsigned char result = (unsigned char)((bitstream[(*bitpointer) >> 3] >> (7 - ((*bitpointer) & 0x7))) & 1);\n  ++(*bitpointer);\n  return result;\n}\n\nstatic unsigned readBitsFromReversedStream(size_t* bitpointer, const unsigned char* bitstream, size_t nbits)\n{\n  unsigned result = 0;\n  size_t i;\n  for(i = 0 ; i < nbits; ++i)\n  {\n    result <<= 1;\n    result |= (unsigned)readBitFromReversedStream(bitpointer, bitstream);\n  }\n  return result;\n}\n\n#ifdef LODEPNG_COMPILE_DECODER\nstatic void setBitOfReversedStream0(size_t* bitpointer, unsigned char* bitstream, unsigned char bit)\n{\n  /*the current bit in bitstream must be 0 for this to work*/\n  if(bit)\n  {\n    /*earlier bit of huffman code is in a lesser significant bit of an earlier byte*/\n    bitstream[(*bitpointer) >> 3] |= (bit << (7 - ((*bitpointer) & 0x7)));\n  }\n  ++(*bitpointer);\n}\n#endif /*LODEPNG_COMPILE_DECODER*/\n\nstatic void setBitOfReversedStream(size_t* bitpointer, unsigned char* bitstream, unsigned char bit)\n{\n  /*the current bit in bitstream may be 0 or 1 for this to work*/\n  if(bit == 0) bitstream[(*bitpointer) >> 3] &=  (unsigned char)(~(1 << (7 - ((*bitpointer) & 0x7))));\n  else         bitstream[(*bitpointer) >> 3] |=  (1 << (7 - ((*bitpointer) & 0x7)));\n  ++(*bitpointer);\n}\n\n/* ////////////////////////////////////////////////////////////////////////// */\n/* / PNG chunks                                                             / */\n/* ////////////////////////////////////////////////////////////////////////// */\n\nunsigned lodepng_chunk_length(const unsigned char* chunk)\n{\n  return lodepng_read32bitInt(&chunk[0]);\n}\n\nvoid lodepng_chunk_type(char type[5], const unsigned char* chunk)\n{\n  unsigned i;\n  for(i = 0; i != 4; ++i) type[i] = (char)chunk[4 + i];\n  type[4] = 0; /*null termination char*/\n}\n\nunsigned char lodepng_chunk_type_equals(const unsigned char* chunk, const char* type)\n{\n  if(strlen(type) != 4) return 0;\n  return (chunk[4] == type[0] && chunk[5] == type[1] && chunk[6] == type[2] && chunk[7] == type[3]);\n}\n\nunsigned char lodepng_chunk_ancillary(const unsigned char* chunk)\n{\n  return((chunk[4] & 32) != 0);\n}\n\nunsigned char lodepng_chunk_private(const unsigned char* chunk)\n{\n  return((chunk[6] & 32) != 0);\n}\n\nunsigned char lodepng_chunk_safetocopy(const unsigned char* chunk)\n{\n  return((chunk[7] & 32) != 0);\n}\n\nunsigned char* lodepng_chunk_data(unsigned char* chunk)\n{\n  return &chunk[8];\n}\n\nconst unsigned char* lodepng_chunk_data_const(const unsigned char* chunk)\n{\n  return &chunk[8];\n}\n\nunsigned lodepng_chunk_check_crc(const unsigned char* chunk)\n{\n  unsigned length = lodepng_chunk_length(chunk);\n  unsigned CRC = lodepng_read32bitInt(&chunk[length + 8]);\n  /*the CRC is taken of the data and the 4 chunk type letters, not the length*/\n  unsigned checksum = lodepng_crc32(&chunk[4], length + 4);\n  if(CRC != checksum) return 1;\n  else return 0;\n}\n\nvoid lodepng_chunk_generate_crc(unsigned char* chunk)\n{\n  unsigned length = lodepng_chunk_length(chunk);\n  unsigned CRC = lodepng_crc32(&chunk[4], length + 4);\n  lodepng_set32bitInt(chunk + 8 + length, CRC);\n}\n\nunsigned char* lodepng_chunk_next(unsigned char* chunk)\n{\n  unsigned total_chunk_length = lodepng_chunk_length(chunk) + 12;\n  return &chunk[total_chunk_length];\n}\n\nconst unsigned char* lodepng_chunk_next_const(const unsigned char* chunk)\n{\n  unsigned total_chunk_length = lodepng_chunk_length(chunk) + 12;\n  return &chunk[total_chunk_length];\n}\n\nunsigned lodepng_chunk_append(unsigned char** out, size_t* outlength, const unsigned char* chunk)\n{\n  unsigned i;\n  unsigned total_chunk_length = lodepng_chunk_length(chunk) + 12;\n  unsigned char *chunk_start, *new_buffer;\n  size_t new_length = (*outlength) + total_chunk_length;\n  if(new_length < total_chunk_length || new_length < (*outlength)) return 77; /*integer overflow happened*/\n\n  new_buffer = (unsigned char*)lodepng_realloc(*out, new_length);\n  if(!new_buffer) return 83; /*alloc fail*/\n  (*out) = new_buffer;\n  (*outlength) = new_length;\n  chunk_start = &(*out)[new_length - total_chunk_length];\n\n  for(i = 0; i != total_chunk_length; ++i) chunk_start[i] = chunk[i];\n\n  return 0;\n}\n\nunsigned lodepng_chunk_create(unsigned char** out, size_t* outlength, unsigned length,\n                              const char* type, const unsigned char* data)\n{\n  unsigned i;\n  unsigned char *chunk, *new_buffer;\n  size_t new_length = (*outlength) + length + 12;\n  if(new_length < length + 12 || new_length < (*outlength)) return 77; /*integer overflow happened*/\n  new_buffer = (unsigned char*)lodepng_realloc(*out, new_length);\n  if(!new_buffer) return 83; /*alloc fail*/\n  (*out) = new_buffer;\n  (*outlength) = new_length;\n  chunk = &(*out)[(*outlength) - length - 12];\n\n  /*1: length*/\n  lodepng_set32bitInt(chunk, (unsigned)length);\n\n  /*2: chunk name (4 letters)*/\n  chunk[4] = (unsigned char)type[0];\n  chunk[5] = (unsigned char)type[1];\n  chunk[6] = (unsigned char)type[2];\n  chunk[7] = (unsigned char)type[3];\n\n  /*3: the data*/\n  for(i = 0; i != length; ++i) chunk[8 + i] = data[i];\n\n  /*4: CRC (of the chunkname characters and the data)*/\n  lodepng_chunk_generate_crc(chunk);\n\n  return 0;\n}\n\n/* ////////////////////////////////////////////////////////////////////////// */\n/* / Color types and such                                                   / */\n/* ////////////////////////////////////////////////////////////////////////// */\n\n/*return type is a LodePNG error code*/\nstatic unsigned checkColorValidity(LodePNGColorType colortype, unsigned bd) /*bd = bitdepth*/\n{\n  switch(colortype)\n  {\n    case 0: if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8 || bd == 16)) return 37; break; /*grey*/\n    case 2: if(!(                                 bd == 8 || bd == 16)) return 37; break; /*RGB*/\n    case 3: if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8            )) return 37; break; /*palette*/\n    case 4: if(!(                                 bd == 8 || bd == 16)) return 37; break; /*grey + alpha*/\n    case 6: if(!(                                 bd == 8 || bd == 16)) return 37; break; /*RGBA*/\n    default: return 31;\n  }\n  return 0; /*allowed color type / bits combination*/\n}\n\nstatic unsigned getNumColorChannels(LodePNGColorType colortype)\n{\n  switch(colortype)\n  {\n    case 0: return 1; /*grey*/\n    case 2: return 3; /*RGB*/\n    case 3: return 1; /*palette*/\n    case 4: return 2; /*grey + alpha*/\n    case 6: return 4; /*RGBA*/\n  }\n  return 0; /*unexisting color type*/\n}\n\nstatic unsigned lodepng_get_bpp_lct(LodePNGColorType colortype, unsigned bitdepth)\n{\n  /*bits per pixel is amount of channels * bits per channel*/\n  return getNumColorChannels(colortype) * bitdepth;\n}\n\n/* ////////////////////////////////////////////////////////////////////////// */\n\nvoid lodepng_color_mode_init(LodePNGColorMode* info)\n{\n  info->key_defined = 0;\n  info->key_r = info->key_g = info->key_b = 0;\n  info->colortype = LCT_RGBA;\n  info->bitdepth = 8;\n  info->palette = 0;\n  info->palettesize = 0;\n}\n\nvoid lodepng_color_mode_cleanup(LodePNGColorMode* info)\n{\n  lodepng_palette_clear(info);\n}\n\nunsigned lodepng_color_mode_copy(LodePNGColorMode* dest, const LodePNGColorMode* source)\n{\n  size_t i;\n  lodepng_color_mode_cleanup(dest);\n  *dest = *source;\n  if(source->palette)\n  {\n    dest->palette = (unsigned char*)lodepng_malloc(1024);\n    if(!dest->palette && source->palettesize) return 83; /*alloc fail*/\n    for(i = 0; i != source->palettesize * 4; ++i) dest->palette[i] = source->palette[i];\n  }\n  return 0;\n}\n\nstatic int lodepng_color_mode_equal(const LodePNGColorMode* a, const LodePNGColorMode* b)\n{\n  size_t i;\n  if(a->colortype != b->colortype) return 0;\n  if(a->bitdepth != b->bitdepth) return 0;\n  if(a->key_defined != b->key_defined) return 0;\n  if(a->key_defined)\n  {\n    if(a->key_r != b->key_r) return 0;\n    if(a->key_g != b->key_g) return 0;\n    if(a->key_b != b->key_b) return 0;\n  }\n  /*if one of the palette sizes is 0, then we consider it to be the same as the\n  other: it means that e.g. the palette was not given by the user and should be\n  considered the same as the palette inside the PNG.*/\n  if(1/*a->palettesize != 0 && b->palettesize != 0*/) {\n    if(a->palettesize != b->palettesize) return 0;\n    for(i = 0; i != a->palettesize * 4; ++i)\n    {\n      if(a->palette[i] != b->palette[i]) return 0;\n    }\n  }\n  return 1;\n}\n\nvoid lodepng_palette_clear(LodePNGColorMode* info)\n{\n  if(info->palette) lodepng_free(info->palette);\n  info->palette = 0;\n  info->palettesize = 0;\n}\n\nunsigned lodepng_palette_add(LodePNGColorMode* info,\n                             unsigned char r, unsigned char g, unsigned char b, unsigned char a)\n{\n  unsigned char* data;\n  /*the same resize technique as C++ std::vectors is used, and here it's made so that for a palette with\n  the max of 256 colors, it'll have the exact alloc size*/\n  if(!info->palette) /*allocate palette if empty*/\n  {\n    /*room for 256 colors with 4 bytes each*/\n    data = (unsigned char*)lodepng_realloc(info->palette, 1024);\n    if(!data) return 83; /*alloc fail*/\n    else info->palette = data;\n  }\n  info->palette[4 * info->palettesize + 0] = r;\n  info->palette[4 * info->palettesize + 1] = g;\n  info->palette[4 * info->palettesize + 2] = b;\n  info->palette[4 * info->palettesize + 3] = a;\n  ++info->palettesize;\n  return 0;\n}\n\nunsigned lodepng_get_bpp(const LodePNGColorMode* info)\n{\n  /*calculate bits per pixel out of colortype and bitdepth*/\n  return lodepng_get_bpp_lct(info->colortype, info->bitdepth);\n}\n\nunsigned lodepng_get_channels(const LodePNGColorMode* info)\n{\n  return getNumColorChannels(info->colortype);\n}\n\nunsigned lodepng_is_greyscale_type(const LodePNGColorMode* info)\n{\n  return info->colortype == LCT_GREY || info->colortype == LCT_GREY_ALPHA;\n}\n\nunsigned lodepng_is_alpha_type(const LodePNGColorMode* info)\n{\n  return (info->colortype & 4) != 0; /*4 or 6*/\n}\n\nunsigned lodepng_is_palette_type(const LodePNGColorMode* info)\n{\n  return info->colortype == LCT_PALETTE;\n}\n\nunsigned lodepng_has_palette_alpha(const LodePNGColorMode* info)\n{\n  size_t i;\n  for(i = 0; i != info->palettesize; ++i)\n  {\n    if(info->palette[i * 4 + 3] < 255) return 1;\n  }\n  return 0;\n}\n\nunsigned lodepng_can_have_alpha(const LodePNGColorMode* info)\n{\n  return info->key_defined\n      || lodepng_is_alpha_type(info)\n      || lodepng_has_palette_alpha(info);\n}\n\nsize_t lodepng_get_raw_size(unsigned w, unsigned h, const LodePNGColorMode* color)\n{\n  /*will not overflow for any color type if roughly w * h < 268435455*/\n  size_t bpp = lodepng_get_bpp(color);\n  size_t n = w * h;\n  return ((n / 8) * bpp) + ((n & 7) * bpp + 7) / 8;\n}\n\nsize_t lodepng_get_raw_size_lct(unsigned w, unsigned h, LodePNGColorType colortype, unsigned bitdepth)\n{\n  /*will not overflow for any color type if roughly w * h < 268435455*/\n  size_t bpp = lodepng_get_bpp_lct(colortype, bitdepth);\n  size_t n = w * h;\n  return ((n / 8) * bpp) + ((n & 7) * bpp + 7) / 8;\n}\n\n\n#ifdef LODEPNG_COMPILE_PNG\n#ifdef LODEPNG_COMPILE_DECODER\n/*in an idat chunk, each scanline is a multiple of 8 bits, unlike the lodepng output buffer*/\nstatic size_t lodepng_get_raw_size_idat(unsigned w, unsigned h, const LodePNGColorMode* color)\n{\n  /*will not overflow for any color type if roughly w * h < 268435455*/\n  size_t bpp = lodepng_get_bpp(color);\n  size_t line = ((w / 8) * bpp) + ((w & 7) * bpp + 7) / 8;\n  return h * line;\n}\n#endif /*LODEPNG_COMPILE_DECODER*/\n#endif /*LODEPNG_COMPILE_PNG*/\n\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\n\nstatic void LodePNGUnknownChunks_init(LodePNGInfo* info)\n{\n  unsigned i;\n  for(i = 0; i != 3; ++i) info->unknown_chunks_data[i] = 0;\n  for(i = 0; i != 3; ++i) info->unknown_chunks_size[i] = 0;\n}\n\nstatic void LodePNGUnknownChunks_cleanup(LodePNGInfo* info)\n{\n  unsigned i;\n  for(i = 0; i != 3; ++i) lodepng_free(info->unknown_chunks_data[i]);\n}\n\nstatic unsigned LodePNGUnknownChunks_copy(LodePNGInfo* dest, const LodePNGInfo* src)\n{\n  unsigned i;\n\n  LodePNGUnknownChunks_cleanup(dest);\n\n  for(i = 0; i != 3; ++i)\n  {\n    size_t j;\n    dest->unknown_chunks_size[i] = src->unknown_chunks_size[i];\n    dest->unknown_chunks_data[i] = (unsigned char*)lodepng_malloc(src->unknown_chunks_size[i]);\n    if(!dest->unknown_chunks_data[i] && dest->unknown_chunks_size[i]) return 83; /*alloc fail*/\n    for(j = 0; j < src->unknown_chunks_size[i]; ++j)\n    {\n      dest->unknown_chunks_data[i][j] = src->unknown_chunks_data[i][j];\n    }\n  }\n\n  return 0;\n}\n\n/******************************************************************************/\n\nstatic void LodePNGText_init(LodePNGInfo* info)\n{\n  info->text_num = 0;\n  info->text_keys = NULL;\n  info->text_strings = NULL;\n}\n\nstatic void LodePNGText_cleanup(LodePNGInfo* info)\n{\n  size_t i;\n  for(i = 0; i != info->text_num; ++i)\n  {\n    string_cleanup(&info->text_keys[i]);\n    string_cleanup(&info->text_strings[i]);\n  }\n  lodepng_free(info->text_keys);\n  lodepng_free(info->text_strings);\n}\n\nstatic unsigned LodePNGText_copy(LodePNGInfo* dest, const LodePNGInfo* source)\n{\n  size_t i = 0;\n  dest->text_keys = 0;\n  dest->text_strings = 0;\n  dest->text_num = 0;\n  for(i = 0; i != source->text_num; ++i)\n  {\n    CERROR_TRY_RETURN(lodepng_add_text(dest, source->text_keys[i], source->text_strings[i]));\n  }\n  return 0;\n}\n\nvoid lodepng_clear_text(LodePNGInfo* info)\n{\n  LodePNGText_cleanup(info);\n}\n\nunsigned lodepng_add_text(LodePNGInfo* info, const char* key, const char* str)\n{\n  char** new_keys = (char**)(lodepng_realloc(info->text_keys, sizeof(char*) * (info->text_num + 1)));\n  char** new_strings = (char**)(lodepng_realloc(info->text_strings, sizeof(char*) * (info->text_num + 1)));\n  if(!new_keys || !new_strings)\n  {\n    lodepng_free(new_keys);\n    lodepng_free(new_strings);\n    return 83; /*alloc fail*/\n  }\n\n  ++info->text_num;\n  info->text_keys = new_keys;\n  info->text_strings = new_strings;\n\n  string_init(&info->text_keys[info->text_num - 1]);\n  string_set(&info->text_keys[info->text_num - 1], key);\n\n  string_init(&info->text_strings[info->text_num - 1]);\n  string_set(&info->text_strings[info->text_num - 1], str);\n\n  return 0;\n}\n\n/******************************************************************************/\n\nstatic void LodePNGIText_init(LodePNGInfo* info)\n{\n  info->itext_num = 0;\n  info->itext_keys = NULL;\n  info->itext_langtags = NULL;\n  info->itext_transkeys = NULL;\n  info->itext_strings = NULL;\n}\n\nstatic void LodePNGIText_cleanup(LodePNGInfo* info)\n{\n  size_t i;\n  for(i = 0; i != info->itext_num; ++i)\n  {\n    string_cleanup(&info->itext_keys[i]);\n    string_cleanup(&info->itext_langtags[i]);\n    string_cleanup(&info->itext_transkeys[i]);\n    string_cleanup(&info->itext_strings[i]);\n  }\n  lodepng_free(info->itext_keys);\n  lodepng_free(info->itext_langtags);\n  lodepng_free(info->itext_transkeys);\n  lodepng_free(info->itext_strings);\n}\n\nstatic unsigned LodePNGIText_copy(LodePNGInfo* dest, const LodePNGInfo* source)\n{\n  size_t i = 0;\n  dest->itext_keys = 0;\n  dest->itext_langtags = 0;\n  dest->itext_transkeys = 0;\n  dest->itext_strings = 0;\n  dest->itext_num = 0;\n  for(i = 0; i != source->itext_num; ++i)\n  {\n    CERROR_TRY_RETURN(lodepng_add_itext(dest, source->itext_keys[i], source->itext_langtags[i],\n                                        source->itext_transkeys[i], source->itext_strings[i]));\n  }\n  return 0;\n}\n\nvoid lodepng_clear_itext(LodePNGInfo* info)\n{\n  LodePNGIText_cleanup(info);\n}\n\nunsigned lodepng_add_itext(LodePNGInfo* info, const char* key, const char* langtag,\n                           const char* transkey, const char* str)\n{\n  char** new_keys = (char**)(lodepng_realloc(info->itext_keys, sizeof(char*) * (info->itext_num + 1)));\n  char** new_langtags = (char**)(lodepng_realloc(info->itext_langtags, sizeof(char*) * (info->itext_num + 1)));\n  char** new_transkeys = (char**)(lodepng_realloc(info->itext_transkeys, sizeof(char*) * (info->itext_num + 1)));\n  char** new_strings = (char**)(lodepng_realloc(info->itext_strings, sizeof(char*) * (info->itext_num + 1)));\n  if(!new_keys || !new_langtags || !new_transkeys || !new_strings)\n  {\n    lodepng_free(new_keys);\n    lodepng_free(new_langtags);\n    lodepng_free(new_transkeys);\n    lodepng_free(new_strings);\n    return 83; /*alloc fail*/\n  }\n\n  ++info->itext_num;\n  info->itext_keys = new_keys;\n  info->itext_langtags = new_langtags;\n  info->itext_transkeys = new_transkeys;\n  info->itext_strings = new_strings;\n\n  string_init(&info->itext_keys[info->itext_num - 1]);\n  string_set(&info->itext_keys[info->itext_num - 1], key);\n\n  string_init(&info->itext_langtags[info->itext_num - 1]);\n  string_set(&info->itext_langtags[info->itext_num - 1], langtag);\n\n  string_init(&info->itext_transkeys[info->itext_num - 1]);\n  string_set(&info->itext_transkeys[info->itext_num - 1], transkey);\n\n  string_init(&info->itext_strings[info->itext_num - 1]);\n  string_set(&info->itext_strings[info->itext_num - 1], str);\n\n  return 0;\n}\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n\nvoid lodepng_info_init(LodePNGInfo* info)\n{\n  lodepng_color_mode_init(&info->color);\n  info->interlace_method = 0;\n  info->compression_method = 0;\n  info->filter_method = 0;\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\n  info->background_defined = 0;\n  info->background_r = info->background_g = info->background_b = 0;\n\n  LodePNGText_init(info);\n  LodePNGIText_init(info);\n\n  info->time_defined = 0;\n  info->phys_defined = 0;\n\n  LodePNGUnknownChunks_init(info);\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n}\n\nvoid lodepng_info_cleanup(LodePNGInfo* info)\n{\n  lodepng_color_mode_cleanup(&info->color);\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\n  LodePNGText_cleanup(info);\n  LodePNGIText_cleanup(info);\n\n  LodePNGUnknownChunks_cleanup(info);\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n}\n\nunsigned lodepng_info_copy(LodePNGInfo* dest, const LodePNGInfo* source)\n{\n  lodepng_info_cleanup(dest);\n  *dest = *source;\n  lodepng_color_mode_init(&dest->color);\n  CERROR_TRY_RETURN(lodepng_color_mode_copy(&dest->color, &source->color));\n\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\n  CERROR_TRY_RETURN(LodePNGText_copy(dest, source));\n  CERROR_TRY_RETURN(LodePNGIText_copy(dest, source));\n\n  LodePNGUnknownChunks_init(dest);\n  CERROR_TRY_RETURN(LodePNGUnknownChunks_copy(dest, source));\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n  return 0;\n}\n\nvoid lodepng_info_swap(LodePNGInfo* a, LodePNGInfo* b)\n{\n  LodePNGInfo temp = *a;\n  *a = *b;\n  *b = temp;\n}\n\n/* ////////////////////////////////////////////////////////////////////////// */\n\n/*index: bitgroup index, bits: bitgroup size(1, 2 or 4), in: bitgroup value, out: octet array to add bits to*/\nstatic void addColorBits(unsigned char* out, size_t index, unsigned bits, unsigned in)\n{\n  unsigned m = bits == 1 ? 7 : bits == 2 ? 3 : 1; /*8 / bits - 1*/\n  /*p = the partial index in the byte, e.g. with 4 palettebits it is 0 for first half or 1 for second half*/\n  unsigned p = index & m;\n  in &= (1u << bits) - 1u; /*filter out any other bits of the input value*/\n  in = in << (bits * (m - p));\n  if(p == 0) out[index * bits / 8] = in;\n  else out[index * bits / 8] |= in;\n}\n\ntypedef struct ColorTree ColorTree;\n\n/*\nOne node of a color tree\nThis is the data structure used to count the number of unique colors and to get a palette\nindex for a color. It's like an octree, but because the alpha channel is used too, each\nnode has 16 instead of 8 children.\n*/\nstruct ColorTree\n{\n  ColorTree* children[16]; /*up to 16 pointers to ColorTree of next level*/\n  int index; /*the payload. Only has a meaningful value if this is in the last level*/\n};\n\nstatic void color_tree_init(ColorTree* tree)\n{\n  int i;\n  for(i = 0; i != 16; ++i) tree->children[i] = 0;\n  tree->index = -1;\n}\n\nstatic void color_tree_cleanup(ColorTree* tree)\n{\n  int i;\n  for(i = 0; i != 16; ++i)\n  {\n    if(tree->children[i])\n    {\n      color_tree_cleanup(tree->children[i]);\n      lodepng_free(tree->children[i]);\n    }\n  }\n}\n\n/*returns -1 if color not present, its index otherwise*/\nstatic int color_tree_get(ColorTree* tree, unsigned char r, unsigned char g, unsigned char b, unsigned char a)\n{\n  int bit = 0;\n  for(bit = 0; bit < 8; ++bit)\n  {\n    int i = 8 * ((r >> bit) & 1) + 4 * ((g >> bit) & 1) + 2 * ((b >> bit) & 1) + 1 * ((a >> bit) & 1);\n    if(!tree->children[i]) return -1;\n    else tree = tree->children[i];\n  }\n  return tree ? tree->index : -1;\n}\n\n#ifdef LODEPNG_COMPILE_ENCODER\nstatic int color_tree_has(ColorTree* tree, unsigned char r, unsigned char g, unsigned char b, unsigned char a)\n{\n  return color_tree_get(tree, r, g, b, a) >= 0;\n}\n#endif /*LODEPNG_COMPILE_ENCODER*/\n\n/*color is not allowed to already exist.\nIndex should be >= 0 (it's signed to be compatible with using -1 for \"doesn't exist\")*/\nstatic void color_tree_add(ColorTree* tree,\n                           unsigned char r, unsigned char g, unsigned char b, unsigned char a, unsigned index)\n{\n  int bit;\n  for(bit = 0; bit < 8; ++bit)\n  {\n    int i = 8 * ((r >> bit) & 1) + 4 * ((g >> bit) & 1) + 2 * ((b >> bit) & 1) + 1 * ((a >> bit) & 1);\n    if(!tree->children[i])\n    {\n      tree->children[i] = (ColorTree*)lodepng_malloc(sizeof(ColorTree));\n      color_tree_init(tree->children[i]);\n    }\n    tree = tree->children[i];\n  }\n  tree->index = (int)index;\n}\n\n/*put a pixel, given its RGBA color, into image of any color type*/\nstatic unsigned rgba8ToPixel(unsigned char* out, size_t i,\n                             const LodePNGColorMode* mode, ColorTree* tree /*for palette*/,\n                             unsigned char r, unsigned char g, unsigned char b, unsigned char a)\n{\n  if(mode->colortype == LCT_GREY)\n  {\n    unsigned char grey = r; /*((unsigned short)r + g + b) / 3*/;\n    if(mode->bitdepth == 8) out[i] = grey;\n    else if(mode->bitdepth == 16) out[i * 2 + 0] = out[i * 2 + 1] = grey;\n    else\n    {\n      /*take the most significant bits of grey*/\n      grey = (grey >> (8 - mode->bitdepth)) & ((1 << mode->bitdepth) - 1);\n      addColorBits(out, i, mode->bitdepth, grey);\n    }\n  }\n  else if(mode->colortype == LCT_RGB)\n  {\n    if(mode->bitdepth == 8)\n    {\n      out[i * 3 + 0] = r;\n      out[i * 3 + 1] = g;\n      out[i * 3 + 2] = b;\n    }\n    else\n    {\n      out[i * 6 + 0] = out[i * 6 + 1] = r;\n      out[i * 6 + 2] = out[i * 6 + 3] = g;\n      out[i * 6 + 4] = out[i * 6 + 5] = b;\n    }\n  }\n  else if(mode->colortype == LCT_PALETTE)\n  {\n    int index = color_tree_get(tree, r, g, b, a);\n    if(index < 0) return 82; /*color not in palette*/\n    if(mode->bitdepth == 8) out[i] = index;\n    else addColorBits(out, i, mode->bitdepth, (unsigned)index);\n  }\n  else if(mode->colortype == LCT_GREY_ALPHA)\n  {\n    unsigned char grey = r; /*((unsigned short)r + g + b) / 3*/;\n    if(mode->bitdepth == 8)\n    {\n      out[i * 2 + 0] = grey;\n      out[i * 2 + 1] = a;\n    }\n    else if(mode->bitdepth == 16)\n    {\n      out[i * 4 + 0] = out[i * 4 + 1] = grey;\n      out[i * 4 + 2] = out[i * 4 + 3] = a;\n    }\n  }\n  else if(mode->colortype == LCT_RGBA)\n  {\n    if(mode->bitdepth == 8)\n    {\n      out[i * 4 + 0] = r;\n      out[i * 4 + 1] = g;\n      out[i * 4 + 2] = b;\n      out[i * 4 + 3] = a;\n    }\n    else\n    {\n      out[i * 8 + 0] = out[i * 8 + 1] = r;\n      out[i * 8 + 2] = out[i * 8 + 3] = g;\n      out[i * 8 + 4] = out[i * 8 + 5] = b;\n      out[i * 8 + 6] = out[i * 8 + 7] = a;\n    }\n  }\n\n  return 0; /*no error*/\n}\n\n/*put a pixel, given its RGBA16 color, into image of any color 16-bitdepth type*/\nstatic void rgba16ToPixel(unsigned char* out, size_t i,\n                         const LodePNGColorMode* mode,\n                         unsigned short r, unsigned short g, unsigned short b, unsigned short a)\n{\n  if(mode->colortype == LCT_GREY)\n  {\n    unsigned short grey = r; /*((unsigned)r + g + b) / 3*/;\n    out[i * 2 + 0] = (grey >> 8) & 255;\n    out[i * 2 + 1] = grey & 255;\n  }\n  else if(mode->colortype == LCT_RGB)\n  {\n    out[i * 6 + 0] = (r >> 8) & 255;\n    out[i * 6 + 1] = r & 255;\n    out[i * 6 + 2] = (g >> 8) & 255;\n    out[i * 6 + 3] = g & 255;\n    out[i * 6 + 4] = (b >> 8) & 255;\n    out[i * 6 + 5] = b & 255;\n  }\n  else if(mode->colortype == LCT_GREY_ALPHA)\n  {\n    unsigned short grey = r; /*((unsigned)r + g + b) / 3*/;\n    out[i * 4 + 0] = (grey >> 8) & 255;\n    out[i * 4 + 1] = grey & 255;\n    out[i * 4 + 2] = (a >> 8) & 255;\n    out[i * 4 + 3] = a & 255;\n  }\n  else if(mode->colortype == LCT_RGBA)\n  {\n    out[i * 8 + 0] = (r >> 8) & 255;\n    out[i * 8 + 1] = r & 255;\n    out[i * 8 + 2] = (g >> 8) & 255;\n    out[i * 8 + 3] = g & 255;\n    out[i * 8 + 4] = (b >> 8) & 255;\n    out[i * 8 + 5] = b & 255;\n    out[i * 8 + 6] = (a >> 8) & 255;\n    out[i * 8 + 7] = a & 255;\n  }\n}\n\n/*Get RGBA8 color of pixel with index i (y * width + x) from the raw image with given color type.*/\nstatic void getPixelColorRGBA8(unsigned char* r, unsigned char* g,\n                               unsigned char* b, unsigned char* a,\n                               const unsigned char* in, size_t i,\n                               const LodePNGColorMode* mode)\n{\n  if(mode->colortype == LCT_GREY)\n  {\n    if(mode->bitdepth == 8)\n    {\n      *r = *g = *b = in[i];\n      if(mode->key_defined && *r == mode->key_r) *a = 0;\n      else *a = 255;\n    }\n    else if(mode->bitdepth == 16)\n    {\n      *r = *g = *b = in[i * 2 + 0];\n      if(mode->key_defined && 256U * in[i * 2 + 0] + in[i * 2 + 1] == mode->key_r) *a = 0;\n      else *a = 255;\n    }\n    else\n    {\n      unsigned highest = ((1U << mode->bitdepth) - 1U); /*highest possible value for this bit depth*/\n      size_t j = i * mode->bitdepth;\n      unsigned value = readBitsFromReversedStream(&j, in, mode->bitdepth);\n      *r = *g = *b = (value * 255) / highest;\n      if(mode->key_defined && value == mode->key_r) *a = 0;\n      else *a = 255;\n    }\n  }\n  else if(mode->colortype == LCT_RGB)\n  {\n    if(mode->bitdepth == 8)\n    {\n      *r = in[i * 3 + 0]; *g = in[i * 3 + 1]; *b = in[i * 3 + 2];\n      if(mode->key_defined && *r == mode->key_r && *g == mode->key_g && *b == mode->key_b) *a = 0;\n      else *a = 255;\n    }\n    else\n    {\n      *r = in[i * 6 + 0];\n      *g = in[i * 6 + 2];\n      *b = in[i * 6 + 4];\n      if(mode->key_defined && 256U * in[i * 6 + 0] + in[i * 6 + 1] == mode->key_r\n         && 256U * in[i * 6 + 2] + in[i * 6 + 3] == mode->key_g\n         && 256U * in[i * 6 + 4] + in[i * 6 + 5] == mode->key_b) *a = 0;\n      else *a = 255;\n    }\n  }\n  else if(mode->colortype == LCT_PALETTE)\n  {\n    unsigned index;\n    if(mode->bitdepth == 8) index = in[i];\n    else\n    {\n      size_t j = i * mode->bitdepth;\n      index = readBitsFromReversedStream(&j, in, mode->bitdepth);\n    }\n\n    if(index >= mode->palettesize)\n    {\n      /*This is an error according to the PNG spec, but common PNG decoders make it black instead.\n      Done here too, slightly faster due to no error handling needed.*/\n      *r = *g = *b = 0;\n      *a = 255;\n    }\n    else\n    {\n      *r = mode->palette[index * 4 + 0];\n      *g = mode->palette[index * 4 + 1];\n      *b = mode->palette[index * 4 + 2];\n      *a = mode->palette[index * 4 + 3];\n    }\n  }\n  else if(mode->colortype == LCT_GREY_ALPHA)\n  {\n    if(mode->bitdepth == 8)\n    {\n      *r = *g = *b = in[i * 2 + 0];\n      *a = in[i * 2 + 1];\n    }\n    else\n    {\n      *r = *g = *b = in[i * 4 + 0];\n      *a = in[i * 4 + 2];\n    }\n  }\n  else if(mode->colortype == LCT_RGBA)\n  {\n    if(mode->bitdepth == 8)\n    {\n      *r = in[i * 4 + 0];\n      *g = in[i * 4 + 1];\n      *b = in[i * 4 + 2];\n      *a = in[i * 4 + 3];\n    }\n    else\n    {\n      *r = in[i * 8 + 0];\n      *g = in[i * 8 + 2];\n      *b = in[i * 8 + 4];\n      *a = in[i * 8 + 6];\n    }\n  }\n}\n\n/*Similar to getPixelColorRGBA8, but with all the for loops inside of the color\nmode test cases, optimized to convert the colors much faster, when converting\nto RGBA or RGB with 8 bit per cannel. buffer must be RGBA or RGB output with\nenough memory, if has_alpha is true the output is RGBA. mode has the color mode\nof the input buffer.*/\nstatic void getPixelColorsRGBA8(unsigned char* buffer, size_t numpixels,\n                                unsigned has_alpha, const unsigned char* in,\n                                const LodePNGColorMode* mode)\n{\n  unsigned num_channels = has_alpha ? 4 : 3;\n  size_t i;\n  if(mode->colortype == LCT_GREY)\n  {\n    if(mode->bitdepth == 8)\n    {\n      for(i = 0; i != numpixels; ++i, buffer += num_channels)\n      {\n        buffer[0] = buffer[1] = buffer[2] = in[i];\n        if(has_alpha) buffer[3] = mode->key_defined && in[i] == mode->key_r ? 0 : 255;\n      }\n    }\n    else if(mode->bitdepth == 16)\n    {\n      for(i = 0; i != numpixels; ++i, buffer += num_channels)\n      {\n        buffer[0] = buffer[1] = buffer[2] = in[i * 2];\n        if(has_alpha) buffer[3] = mode->key_defined && 256U * in[i * 2 + 0] + in[i * 2 + 1] == mode->key_r ? 0 : 255;\n      }\n    }\n    else\n    {\n      unsigned highest = ((1U << mode->bitdepth) - 1U); /*highest possible value for this bit depth*/\n      size_t j = 0;\n      for(i = 0; i != numpixels; ++i, buffer += num_channels)\n      {\n        unsigned value = readBitsFromReversedStream(&j, in, mode->bitdepth);\n        buffer[0] = buffer[1] = buffer[2] = (value * 255) / highest;\n        if(has_alpha) buffer[3] = mode->key_defined && value == mode->key_r ? 0 : 255;\n      }\n    }\n  }\n  else if(mode->colortype == LCT_RGB)\n  {\n    if(mode->bitdepth == 8)\n    {\n      for(i = 0; i != numpixels; ++i, buffer += num_channels)\n      {\n        buffer[0] = in[i * 3 + 0];\n        buffer[1] = in[i * 3 + 1];\n        buffer[2] = in[i * 3 + 2];\n        if(has_alpha) buffer[3] = mode->key_defined && buffer[0] == mode->key_r\n           && buffer[1]== mode->key_g && buffer[2] == mode->key_b ? 0 : 255;\n      }\n    }\n    else\n    {\n      for(i = 0; i != numpixels; ++i, buffer += num_channels)\n      {\n        buffer[0] = in[i * 6 + 0];\n        buffer[1] = in[i * 6 + 2];\n        buffer[2] = in[i * 6 + 4];\n        if(has_alpha) buffer[3] = mode->key_defined\n           && 256U * in[i * 6 + 0] + in[i * 6 + 1] == mode->key_r\n           && 256U * in[i * 6 + 2] + in[i * 6 + 3] == mode->key_g\n           && 256U * in[i * 6 + 4] + in[i * 6 + 5] == mode->key_b ? 0 : 255;\n      }\n    }\n  }\n  else if(mode->colortype == LCT_PALETTE)\n  {\n    unsigned index;\n    size_t j = 0;\n    for(i = 0; i != numpixels; ++i, buffer += num_channels)\n    {\n      if(mode->bitdepth == 8) index = in[i];\n      else index = readBitsFromReversedStream(&j, in, mode->bitdepth);\n\n      if(index >= mode->palettesize)\n      {\n        /*This is an error according to the PNG spec, but most PNG decoders make it black instead.\n        Done here too, slightly faster due to no error handling needed.*/\n        buffer[0] = buffer[1] = buffer[2] = 0;\n        if(has_alpha) buffer[3] = 255;\n      }\n      else\n      {\n        buffer[0] = mode->palette[index * 4 + 0];\n        buffer[1] = mode->palette[index * 4 + 1];\n        buffer[2] = mode->palette[index * 4 + 2];\n        if(has_alpha) buffer[3] = mode->palette[index * 4 + 3];\n      }\n    }\n  }\n  else if(mode->colortype == LCT_GREY_ALPHA)\n  {\n    if(mode->bitdepth == 8)\n    {\n      for(i = 0; i != numpixels; ++i, buffer += num_channels)\n      {\n        buffer[0] = buffer[1] = buffer[2] = in[i * 2 + 0];\n        if(has_alpha) buffer[3] = in[i * 2 + 1];\n      }\n    }\n    else\n    {\n      for(i = 0; i != numpixels; ++i, buffer += num_channels)\n      {\n        buffer[0] = buffer[1] = buffer[2] = in[i * 4 + 0];\n        if(has_alpha) buffer[3] = in[i * 4 + 2];\n      }\n    }\n  }\n  else if(mode->colortype == LCT_RGBA)\n  {\n    if(mode->bitdepth == 8)\n    {\n      for(i = 0; i != numpixels; ++i, buffer += num_channels)\n      {\n        buffer[0] = in[i * 4 + 0];\n        buffer[1] = in[i * 4 + 1];\n        buffer[2] = in[i * 4 + 2];\n        if(has_alpha) buffer[3] = in[i * 4 + 3];\n      }\n    }\n    else\n    {\n      for(i = 0; i != numpixels; ++i, buffer += num_channels)\n      {\n        buffer[0] = in[i * 8 + 0];\n        buffer[1] = in[i * 8 + 2];\n        buffer[2] = in[i * 8 + 4];\n        if(has_alpha) buffer[3] = in[i * 8 + 6];\n      }\n    }\n  }\n}\n\n/*Get RGBA16 color of pixel with index i (y * width + x) from the raw image with\ngiven color type, but the given color type must be 16-bit itself.*/\nstatic void getPixelColorRGBA16(unsigned short* r, unsigned short* g, unsigned short* b, unsigned short* a,\n                                const unsigned char* in, size_t i, const LodePNGColorMode* mode)\n{\n  if(mode->colortype == LCT_GREY)\n  {\n    *r = *g = *b = 256 * in[i * 2 + 0] + in[i * 2 + 1];\n    if(mode->key_defined && 256U * in[i * 2 + 0] + in[i * 2 + 1] == mode->key_r) *a = 0;\n    else *a = 65535;\n  }\n  else if(mode->colortype == LCT_RGB)\n  {\n    *r = 256u * in[i * 6 + 0] + in[i * 6 + 1];\n    *g = 256u * in[i * 6 + 2] + in[i * 6 + 3];\n    *b = 256u * in[i * 6 + 4] + in[i * 6 + 5];\n    if(mode->key_defined\n       && 256u * in[i * 6 + 0] + in[i * 6 + 1] == mode->key_r\n       && 256u * in[i * 6 + 2] + in[i * 6 + 3] == mode->key_g\n       && 256u * in[i * 6 + 4] + in[i * 6 + 5] == mode->key_b) *a = 0;\n    else *a = 65535;\n  }\n  else if(mode->colortype == LCT_GREY_ALPHA)\n  {\n    *r = *g = *b = 256u * in[i * 4 + 0] + in[i * 4 + 1];\n    *a = 256u * in[i * 4 + 2] + in[i * 4 + 3];\n  }\n  else if(mode->colortype == LCT_RGBA)\n  {\n    *r = 256u * in[i * 8 + 0] + in[i * 8 + 1];\n    *g = 256u * in[i * 8 + 2] + in[i * 8 + 3];\n    *b = 256u * in[i * 8 + 4] + in[i * 8 + 5];\n    *a = 256u * in[i * 8 + 6] + in[i * 8 + 7];\n  }\n}\n\nunsigned lodepng_convert(unsigned char* out, const unsigned char* in,\n                         const LodePNGColorMode* mode_out, const LodePNGColorMode* mode_in,\n                         unsigned w, unsigned h)\n{\n  size_t i;\n  ColorTree tree;\n  size_t numpixels = w * h;\n  unsigned error = 0;\n\n  if(lodepng_color_mode_equal(mode_out, mode_in))\n  {\n    size_t numbytes = lodepng_get_raw_size(w, h, mode_in);\n    for(i = 0; i != numbytes; ++i) out[i] = in[i];\n    return 0;\n  }\n\n  if(mode_out->colortype == LCT_PALETTE)\n  {\n    size_t palettesize = mode_out->palettesize;\n    const unsigned char* palette = mode_out->palette;\n    size_t palsize = 1u << mode_out->bitdepth;\n    /*if the user specified output palette but did not give the values, assume\n    they want the values of the input color type (assuming that one is palette).\n    Note that we never create a new palette ourselves.*/\n    if(palettesize == 0)\n    {\n      palettesize = mode_in->palettesize;\n      palette = mode_in->palette;\n    }\n    if(palettesize < palsize) palsize = palettesize;\n    color_tree_init(&tree);\n    for(i = 0; i != palsize; ++i)\n    {\n      const unsigned char* p = &palette[i * 4];\n      color_tree_add(&tree, p[0], p[1], p[2], p[3], (unsigned)i);\n    }\n  }\n\n  if(mode_in->bitdepth == 16 && mode_out->bitdepth == 16)\n  {\n    for(i = 0; i != numpixels; ++i)\n    {\n      unsigned short r = 0, g = 0, b = 0, a = 0;\n      getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode_in);\n      rgba16ToPixel(out, i, mode_out, r, g, b, a);\n    }\n  }\n  else if(mode_out->bitdepth == 8 && mode_out->colortype == LCT_RGBA)\n  {\n    getPixelColorsRGBA8(out, numpixels, 1, in, mode_in);\n  }\n  else if(mode_out->bitdepth == 8 && mode_out->colortype == LCT_RGB)\n  {\n    getPixelColorsRGBA8(out, numpixels, 0, in, mode_in);\n  }\n  else\n  {\n    unsigned char r = 0, g = 0, b = 0, a = 0;\n    for(i = 0; i != numpixels; ++i)\n    {\n      getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode_in);\n      error = rgba8ToPixel(out, i, mode_out, &tree, r, g, b, a);\n      if (error) break;\n    }\n  }\n\n  if(mode_out->colortype == LCT_PALETTE)\n  {\n    color_tree_cleanup(&tree);\n  }\n\n  return error;\n}\n\n#ifdef LODEPNG_COMPILE_ENCODER\n\nvoid lodepng_color_profile_init(LodePNGColorProfile* profile)\n{\n  profile->colored = 0;\n  profile->key = 0;\n  profile->key_r = profile->key_g = profile->key_b = 0;\n  profile->alpha = 0;\n  profile->numcolors = 0;\n  profile->bits = 1;\n}\n\n/*function used for debug purposes with C++*/\n/*void printColorProfile(LodePNGColorProfile* p)\n{\n  std::cout << \"colored: \" << (int)p->colored << \", \";\n  std::cout << \"key: \" << (int)p->key << \", \";\n  std::cout << \"key_r: \" << (int)p->key_r << \", \";\n  std::cout << \"key_g: \" << (int)p->key_g << \", \";\n  std::cout << \"key_b: \" << (int)p->key_b << \", \";\n  std::cout << \"alpha: \" << (int)p->alpha << \", \";\n  std::cout << \"numcolors: \" << (int)p->numcolors << \", \";\n  std::cout << \"bits: \" << (int)p->bits << std::endl;\n}*/\n\n/*Returns how many bits needed to represent given value (max 8 bit)*/\nstatic unsigned getValueRequiredBits(unsigned char value)\n{\n  if(value == 0 || value == 255) return 1;\n  /*The scaling of 2-bit and 4-bit values uses multiples of 85 and 17*/\n  if(value % 17 == 0) return value % 85 == 0 ? 2 : 4;\n  return 8;\n}\n\n/*profile must already have been inited with mode.\nIt's ok to set some parameters of profile to done already.*/\nunsigned lodepng_get_color_profile(LodePNGColorProfile* profile,\n                                   const unsigned char* in, unsigned w, unsigned h,\n                                   const LodePNGColorMode* mode)\n{\n  unsigned error = 0;\n  size_t i;\n  ColorTree tree;\n  size_t numpixels = w * h;\n\n  unsigned colored_done = lodepng_is_greyscale_type(mode) ? 1 : 0;\n  unsigned alpha_done = lodepng_can_have_alpha(mode) ? 0 : 1;\n  unsigned numcolors_done = 0;\n  unsigned bpp = lodepng_get_bpp(mode);\n  unsigned bits_done = bpp == 1 ? 1 : 0;\n  unsigned maxnumcolors = 257;\n  unsigned sixteen = 0;\n  if(bpp <= 8) maxnumcolors = bpp == 1 ? 2 : (bpp == 2 ? 4 : (bpp == 4 ? 16 : 256));\n\n  color_tree_init(&tree);\n\n  /*Check if the 16-bit input is truly 16-bit*/\n  if(mode->bitdepth == 16)\n  {\n    unsigned short r, g, b, a;\n    for(i = 0; i != numpixels; ++i)\n    {\n      getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode);\n      if((r & 255) != ((r >> 8) & 255) || (g & 255) != ((g >> 8) & 255) ||\n         (b & 255) != ((b >> 8) & 255) || (a & 255) != ((a >> 8) & 255)) /*first and second byte differ*/\n      {\n        sixteen = 1;\n        break;\n      }\n    }\n  }\n\n  if(sixteen)\n  {\n    unsigned short r = 0, g = 0, b = 0, a = 0;\n    profile->bits = 16;\n    bits_done = numcolors_done = 1; /*counting colors no longer useful, palette doesn't support 16-bit*/\n\n    for(i = 0; i != numpixels; ++i)\n    {\n      getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode);\n\n      if(!colored_done && (r != g || r != b))\n      {\n        profile->colored = 1;\n        colored_done = 1;\n      }\n\n      if(!alpha_done)\n      {\n        unsigned matchkey = (r == profile->key_r && g == profile->key_g && b == profile->key_b);\n        if(a != 65535 && (a != 0 || (profile->key && !matchkey)))\n        {\n          profile->alpha = 1;\n          profile->key = 0;\n          alpha_done = 1;\n        }\n        else if(a == 0 && !profile->alpha && !profile->key)\n        {\n          profile->key = 1;\n          profile->key_r = r;\n          profile->key_g = g;\n          profile->key_b = b;\n        }\n        else if(a == 65535 && profile->key && matchkey)\n        {\n          /* Color key cannot be used if an opaque pixel also has that RGB color. */\n          profile->alpha = 1;\n          profile->key = 0;\n          alpha_done = 1;\n        }\n      }\n      if(alpha_done && numcolors_done && colored_done && bits_done) break;\n    }\n\n    if(profile->key && !profile->alpha)\n    {\n      for(i = 0; i != numpixels; ++i)\n      {\n        getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode);\n        if(a != 0 && r == profile->key_r && g == profile->key_g && b == profile->key_b)\n        {\n          /* Color key cannot be used if an opaque pixel also has that RGB color. */\n          profile->alpha = 1;\n          profile->key = 0;\n          alpha_done = 1;\n        }\n      }\n    }\n  }\n  else /* < 16-bit */\n  {\n    unsigned char r = 0, g = 0, b = 0, a = 0;\n    for(i = 0; i != numpixels; ++i)\n    {\n      getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode);\n\n      if(!bits_done && profile->bits < 8)\n      {\n        /*only r is checked, < 8 bits is only relevant for greyscale*/\n        unsigned bits = getValueRequiredBits(r);\n        if(bits > profile->bits) profile->bits = bits;\n      }\n      bits_done = (profile->bits >= bpp);\n\n      if(!colored_done && (r != g || r != b))\n      {\n        profile->colored = 1;\n        colored_done = 1;\n        if(profile->bits < 8) profile->bits = 8; /*PNG has no colored modes with less than 8-bit per channel*/\n      }\n\n      if(!alpha_done)\n      {\n        unsigned matchkey = (r == profile->key_r && g == profile->key_g && b == profile->key_b);\n        if(a != 255 && (a != 0 || (profile->key && !matchkey)))\n        {\n          profile->alpha = 1;\n          profile->key = 0;\n          alpha_done = 1;\n          if(profile->bits < 8) profile->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/\n        }\n        else if(a == 0 && !profile->alpha && !profile->key)\n        {\n          profile->key = 1;\n          profile->key_r = r;\n          profile->key_g = g;\n          profile->key_b = b;\n        }\n        else if(a == 255 && profile->key && matchkey)\n        {\n          /* Color key cannot be used if an opaque pixel also has that RGB color. */\n          profile->alpha = 1;\n          profile->key = 0;\n          alpha_done = 1;\n          if(profile->bits < 8) profile->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/\n        }\n      }\n\n      if(!numcolors_done)\n      {\n        if(!color_tree_has(&tree, r, g, b, a))\n        {\n          color_tree_add(&tree, r, g, b, a, profile->numcolors);\n          if(profile->numcolors < 256)\n          {\n            unsigned char* p = profile->palette;\n            unsigned n = profile->numcolors;\n            p[n * 4 + 0] = r;\n            p[n * 4 + 1] = g;\n            p[n * 4 + 2] = b;\n            p[n * 4 + 3] = a;\n          }\n          ++profile->numcolors;\n          numcolors_done = profile->numcolors >= maxnumcolors;\n        }\n      }\n\n      if(alpha_done && numcolors_done && colored_done && bits_done) break;\n    }\n\n    if(profile->key && !profile->alpha)\n    {\n      for(i = 0; i != numpixels; ++i)\n      {\n        getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode);\n        if(a != 0 && r == profile->key_r && g == profile->key_g && b == profile->key_b)\n        {\n          /* Color key cannot be used if an opaque pixel also has that RGB color. */\n          profile->alpha = 1;\n          profile->key = 0;\n          alpha_done = 1;\n          if(profile->bits < 8) profile->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/\n        }\n      }\n    }\n\n    /*make the profile's key always 16-bit for consistency - repeat each byte twice*/\n    profile->key_r += (profile->key_r << 8);\n    profile->key_g += (profile->key_g << 8);\n    profile->key_b += (profile->key_b << 8);\n  }\n\n  color_tree_cleanup(&tree);\n  return error;\n}\n\n/*Automatically chooses color type that gives smallest amount of bits in the\noutput image, e.g. grey if there are only greyscale pixels, palette if there\nare less than 256 colors, ...\nUpdates values of mode with a potentially smaller color model. mode_out should\ncontain the user chosen color model, but will be overwritten with the new chosen one.*/\nunsigned lodepng_auto_choose_color(LodePNGColorMode* mode_out,\n                                   const unsigned char* image, unsigned w, unsigned h,\n                                   const LodePNGColorMode* mode_in)\n{\n  LodePNGColorProfile prof;\n  unsigned error = 0;\n  unsigned i, n, palettebits, palette_ok;\n\n  lodepng_color_profile_init(&prof);\n  error = lodepng_get_color_profile(&prof, image, w, h, mode_in);\n  if(error) return error;\n  mode_out->key_defined = 0;\n\n  if(prof.key && w * h <= 16)\n  {\n    prof.alpha = 1; /*too few pixels to justify tRNS chunk overhead*/\n    prof.key = 0;\n    if(prof.bits < 8) prof.bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/\n  }\n  n = prof.numcolors;\n  palettebits = n <= 2 ? 1 : (n <= 4 ? 2 : (n <= 16 ? 4 : 8));\n  palette_ok = n <= 256 && prof.bits <= 8;\n  if(w * h < n * 2) palette_ok = 0; /*don't add palette overhead if image has only a few pixels*/\n  if(!prof.colored && prof.bits <= palettebits) palette_ok = 0; /*grey is less overhead*/\n\n  if(palette_ok)\n  {\n    unsigned char* p = prof.palette;\n    lodepng_palette_clear(mode_out); /*remove potential earlier palette*/\n    for(i = 0; i != prof.numcolors; ++i)\n    {\n      error = lodepng_palette_add(mode_out, p[i * 4 + 0], p[i * 4 + 1], p[i * 4 + 2], p[i * 4 + 3]);\n      if(error) break;\n    }\n\n    mode_out->colortype = LCT_PALETTE;\n    mode_out->bitdepth = palettebits;\n\n    if(mode_in->colortype == LCT_PALETTE && mode_in->palettesize >= mode_out->palettesize\n        && mode_in->bitdepth == mode_out->bitdepth)\n    {\n      /*If input should have same palette colors, keep original to preserve its order and prevent conversion*/\n      lodepng_color_mode_cleanup(mode_out);\n      lodepng_color_mode_copy(mode_out, mode_in);\n    }\n  }\n  else /*8-bit or 16-bit per channel*/\n  {\n    mode_out->bitdepth = prof.bits;\n    mode_out->colortype = prof.alpha ? (prof.colored ? LCT_RGBA : LCT_GREY_ALPHA)\n                                     : (prof.colored ? LCT_RGB : LCT_GREY);\n\n    if(prof.key)\n    {\n      unsigned mask = (1u << mode_out->bitdepth) - 1u; /*profile always uses 16-bit, mask converts it*/\n      mode_out->key_r = prof.key_r & mask;\n      mode_out->key_g = prof.key_g & mask;\n      mode_out->key_b = prof.key_b & mask;\n      mode_out->key_defined = 1;\n    }\n  }\n\n  return error;\n}\n\n#endif /* #ifdef LODEPNG_COMPILE_ENCODER */\n\n/*\nPaeth predicter, used by PNG filter type 4\nThe parameters are of type short, but should come from unsigned chars, the shorts\nare only needed to make the paeth calculation correct.\n*/\nstatic unsigned char paethPredictor(short a, short b, short c)\n{\n  short pa = abs(b - c);\n  short pb = abs(a - c);\n  short pc = abs(a + b - c - c);\n\n  if(pc < pa && pc < pb) return (unsigned char)c;\n  else if(pb < pa) return (unsigned char)b;\n  else return (unsigned char)a;\n}\n\n/*shared values used by multiple Adam7 related functions*/\n\nstatic const unsigned ADAM7_IX[7] = { 0, 4, 0, 2, 0, 1, 0 }; /*x start values*/\nstatic const unsigned ADAM7_IY[7] = { 0, 0, 4, 0, 2, 0, 1 }; /*y start values*/\nstatic const unsigned ADAM7_DX[7] = { 8, 8, 4, 4, 2, 2, 1 }; /*x delta values*/\nstatic const unsigned ADAM7_DY[7] = { 8, 8, 8, 4, 4, 2, 2 }; /*y delta values*/\n\n/*\nOutputs various dimensions and positions in the image related to the Adam7 reduced images.\npassw: output containing the width of the 7 passes\npassh: output containing the height of the 7 passes\nfilter_passstart: output containing the index of the start and end of each\n reduced image with filter bytes\npadded_passstart output containing the index of the start and end of each\n reduced image when without filter bytes but with padded scanlines\npassstart: output containing the index of the start and end of each reduced\n image without padding between scanlines, but still padding between the images\nw, h: width and height of non-interlaced image\nbpp: bits per pixel\n\"padded\" is only relevant if bpp is less than 8 and a scanline or image does not\n end at a full byte\n*/\nstatic void Adam7_getpassvalues(unsigned passw[7], unsigned passh[7], size_t filter_passstart[8],\n                                size_t padded_passstart[8], size_t passstart[8], unsigned w, unsigned h, unsigned bpp)\n{\n  /*the passstart values have 8 values: the 8th one indicates the byte after the end of the 7th (= last) pass*/\n  unsigned i;\n\n  /*calculate width and height in pixels of each pass*/\n  for(i = 0; i != 7; ++i)\n  {\n    passw[i] = (w + ADAM7_DX[i] - ADAM7_IX[i] - 1) / ADAM7_DX[i];\n    passh[i] = (h + ADAM7_DY[i] - ADAM7_IY[i] - 1) / ADAM7_DY[i];\n    if(passw[i] == 0) passh[i] = 0;\n    if(passh[i] == 0) passw[i] = 0;\n  }\n\n  filter_passstart[0] = padded_passstart[0] = passstart[0] = 0;\n  for(i = 0; i != 7; ++i)\n  {\n    /*if passw[i] is 0, it's 0 bytes, not 1 (no filtertype-byte)*/\n    filter_passstart[i + 1] = filter_passstart[i]\n                            + ((passw[i] && passh[i]) ? passh[i] * (1 + (passw[i] * bpp + 7) / 8) : 0);\n    /*bits padded if needed to fill full byte at end of each scanline*/\n    padded_passstart[i + 1] = padded_passstart[i] + passh[i] * ((passw[i] * bpp + 7) / 8);\n    /*only padded at end of reduced image*/\n    passstart[i + 1] = passstart[i] + (passh[i] * passw[i] * bpp + 7) / 8;\n  }\n}\n\n#ifdef LODEPNG_COMPILE_DECODER\n\n/* ////////////////////////////////////////////////////////////////////////// */\n/* / PNG Decoder                                                            / */\n/* ////////////////////////////////////////////////////////////////////////// */\n\n/*read the information from the header and store it in the LodePNGInfo. return value is error*/\nunsigned lodepng_inspect(unsigned* w, unsigned* h, LodePNGState* state,\n                         const unsigned char* in, size_t insize)\n{\n  LodePNGInfo* info = &state->info_png;\n  if(insize == 0 || in == 0)\n  {\n    CERROR_RETURN_ERROR(state->error, 48); /*error: the given data is empty*/\n  }\n  if(insize < 33)\n  {\n    CERROR_RETURN_ERROR(state->error, 27); /*error: the data length is smaller than the length of a PNG header*/\n  }\n\n  /*when decoding a new PNG image, make sure all parameters created after previous decoding are reset*/\n  lodepng_info_cleanup(info);\n  lodepng_info_init(info);\n\n  if(in[0] != 137 || in[1] != 80 || in[2] != 78 || in[3] != 71\n     || in[4] != 13 || in[5] != 10 || in[6] != 26 || in[7] != 10)\n  {\n    CERROR_RETURN_ERROR(state->error, 28); /*error: the first 8 bytes are not the correct PNG signature*/\n  }\n  if(lodepng_chunk_length(in + 8) != 13)\n  {\n    CERROR_RETURN_ERROR(state->error, 94); /*error: header size must be 13 bytes*/\n  }\n  if(!lodepng_chunk_type_equals(in + 8, \"IHDR\"))\n  {\n    CERROR_RETURN_ERROR(state->error, 29); /*error: it doesn't start with a IHDR chunk!*/\n  }\n\n  /*read the values given in the header*/\n  *w = lodepng_read32bitInt(&in[16]);\n  *h = lodepng_read32bitInt(&in[20]);\n  info->color.bitdepth = in[24];\n  info->color.colortype = (LodePNGColorType)in[25];\n  info->compression_method = in[26];\n  info->filter_method = in[27];\n  info->interlace_method = in[28];\n\n  if(*w == 0 || *h == 0)\n  {\n    CERROR_RETURN_ERROR(state->error, 93);\n  }\n\n  if(!state->decoder.ignore_crc)\n  {\n    unsigned CRC = lodepng_read32bitInt(&in[29]);\n    unsigned checksum = lodepng_crc32(&in[12], 17);\n    if(CRC != checksum)\n    {\n      CERROR_RETURN_ERROR(state->error, 57); /*invalid CRC*/\n    }\n  }\n\n  /*error: only compression method 0 is allowed in the specification*/\n  if(info->compression_method != 0) CERROR_RETURN_ERROR(state->error, 32);\n  /*error: only filter method 0 is allowed in the specification*/\n  if(info->filter_method != 0) CERROR_RETURN_ERROR(state->error, 33);\n  /*error: only interlace methods 0 and 1 exist in the specification*/\n  if(info->interlace_method > 1) CERROR_RETURN_ERROR(state->error, 34);\n\n  state->error = checkColorValidity(info->color.colortype, info->color.bitdepth);\n  return state->error;\n}\n\nstatic unsigned unfilterScanline(unsigned char* recon, const unsigned char* scanline, const unsigned char* precon,\n                                 size_t bytewidth, unsigned char filterType, size_t length)\n{\n  /*\n  For PNG filter method 0\n  unfilter a PNG image scanline by scanline. when the pixels are smaller than 1 byte,\n  the filter works byte per byte (bytewidth = 1)\n  precon is the previous unfiltered scanline, recon the result, scanline the current one\n  the incoming scanlines do NOT include the filtertype byte, that one is given in the parameter filterType instead\n  recon and scanline MAY be the same memory address! precon must be disjoint.\n  */\n\n  size_t i;\n  switch(filterType)\n  {\n    case 0:\n      for(i = 0; i != length; ++i) recon[i] = scanline[i];\n      break;\n    case 1:\n      for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i];\n      for(i = bytewidth; i < length; ++i) recon[i] = scanline[i] + recon[i - bytewidth];\n      break;\n    case 2:\n      if(precon)\n      {\n        for(i = 0; i != length; ++i) recon[i] = scanline[i] + precon[i];\n      }\n      else\n      {\n        for(i = 0; i != length; ++i) recon[i] = scanline[i];\n      }\n      break;\n    case 3:\n      if(precon)\n      {\n        for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i] + (precon[i] >> 1);\n        for(i = bytewidth; i < length; ++i) recon[i] = scanline[i] + ((recon[i - bytewidth] + precon[i]) >> 1);\n      }\n      else\n      {\n        for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i];\n        for(i = bytewidth; i < length; ++i) recon[i] = scanline[i] + (recon[i - bytewidth] >> 1);\n      }\n      break;\n    case 4:\n      if(precon)\n      {\n        for(i = 0; i != bytewidth; ++i)\n        {\n          recon[i] = (scanline[i] + precon[i]); /*paethPredictor(0, precon[i], 0) is always precon[i]*/\n        }\n        for(i = bytewidth; i < length; ++i)\n        {\n          recon[i] = (scanline[i] + paethPredictor(recon[i - bytewidth], precon[i], precon[i - bytewidth]));\n        }\n      }\n      else\n      {\n        for(i = 0; i != bytewidth; ++i)\n        {\n          recon[i] = scanline[i];\n        }\n        for(i = bytewidth; i < length; ++i)\n        {\n          /*paethPredictor(recon[i - bytewidth], 0, 0) is always recon[i - bytewidth]*/\n          recon[i] = (scanline[i] + recon[i - bytewidth]);\n        }\n      }\n      break;\n    default: return 36; /*error: unexisting filter type given*/\n  }\n  return 0;\n}\n\nstatic unsigned unfilter(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp)\n{\n  /*\n  For PNG filter method 0\n  this function unfilters a single image (e.g. without interlacing this is called once, with Adam7 seven times)\n  out must have enough bytes allocated already, in must have the scanlines + 1 filtertype byte per scanline\n  w and h are image dimensions or dimensions of reduced image, bpp is bits per pixel\n  in and out are allowed to be the same memory address (but aren't the same size since in has the extra filter bytes)\n  */\n\n  unsigned y;\n  unsigned char* prevline = 0;\n\n  /*bytewidth is used for filtering, is 1 when bpp < 8, number of bytes per pixel otherwise*/\n  size_t bytewidth = (bpp + 7) / 8;\n  size_t linebytes = (w * bpp + 7) / 8;\n\n  for(y = 0; y < h; ++y)\n  {\n    size_t outindex = linebytes * y;\n    size_t inindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/\n    unsigned char filterType = in[inindex];\n\n    CERROR_TRY_RETURN(unfilterScanline(&out[outindex], &in[inindex + 1], prevline, bytewidth, filterType, linebytes));\n\n    prevline = &out[outindex];\n  }\n\n  return 0;\n}\n\n/*\nin: Adam7 interlaced image, with no padding bits between scanlines, but between\n reduced images so that each reduced image starts at a byte.\nout: the same pixels, but re-ordered so that they're now a non-interlaced image with size w*h\nbpp: bits per pixel\nout has the following size in bits: w * h * bpp.\nin is possibly bigger due to padding bits between reduced images.\nout must be big enough AND must be 0 everywhere if bpp < 8 in the current implementation\n(because that's likely a little bit faster)\nNOTE: comments about padding bits are only relevant if bpp < 8\n*/\nstatic void Adam7_deinterlace(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp)\n{\n  unsigned passw[7], passh[7];\n  size_t filter_passstart[8], padded_passstart[8], passstart[8];\n  unsigned i;\n\n  Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp);\n\n  if(bpp >= 8)\n  {\n    for(i = 0; i != 7; ++i)\n    {\n      unsigned x, y, b;\n      size_t bytewidth = bpp / 8;\n      for(y = 0; y < passh[i]; ++y)\n      for(x = 0; x < passw[i]; ++x)\n      {\n        size_t pixelinstart = passstart[i] + (y * passw[i] + x) * bytewidth;\n        size_t pixeloutstart = ((ADAM7_IY[i] + y * ADAM7_DY[i]) * w + ADAM7_IX[i] + x * ADAM7_DX[i]) * bytewidth;\n        for(b = 0; b < bytewidth; ++b)\n        {\n          out[pixeloutstart + b] = in[pixelinstart + b];\n        }\n      }\n    }\n  }\n  else /*bpp < 8: Adam7 with pixels < 8 bit is a bit trickier: with bit pointers*/\n  {\n    for(i = 0; i != 7; ++i)\n    {\n      unsigned x, y, b;\n      unsigned ilinebits = bpp * passw[i];\n      unsigned olinebits = bpp * w;\n      size_t obp, ibp; /*bit pointers (for out and in buffer)*/\n      for(y = 0; y < passh[i]; ++y)\n      for(x = 0; x < passw[i]; ++x)\n      {\n        ibp = (8 * passstart[i]) + (y * ilinebits + x * bpp);\n        obp = (ADAM7_IY[i] + y * ADAM7_DY[i]) * olinebits + (ADAM7_IX[i] + x * ADAM7_DX[i]) * bpp;\n        for(b = 0; b < bpp; ++b)\n        {\n          unsigned char bit = readBitFromReversedStream(&ibp, in);\n          /*note that this function assumes the out buffer is completely 0, use setBitOfReversedStream otherwise*/\n          setBitOfReversedStream0(&obp, out, bit);\n        }\n      }\n    }\n  }\n}\n\nstatic void removePaddingBits(unsigned char* out, const unsigned char* in,\n                              size_t olinebits, size_t ilinebits, unsigned h)\n{\n  /*\n  After filtering there are still padding bits if scanlines have non multiple of 8 bit amounts. They need\n  to be removed (except at last scanline of (Adam7-reduced) image) before working with pure image buffers\n  for the Adam7 code, the color convert code and the output to the user.\n  in and out are allowed to be the same buffer, in may also be higher but still overlapping; in must\n  have >= ilinebits*h bits, out must have >= olinebits*h bits, olinebits must be <= ilinebits\n  also used to move bits after earlier such operations happened, e.g. in a sequence of reduced images from Adam7\n  only useful if (ilinebits - olinebits) is a value in the range 1..7\n  */\n  unsigned y;\n  size_t diff = ilinebits - olinebits;\n  size_t ibp = 0, obp = 0; /*input and output bit pointers*/\n  for(y = 0; y < h; ++y)\n  {\n    size_t x;\n    for(x = 0; x < olinebits; ++x)\n    {\n      unsigned char bit = readBitFromReversedStream(&ibp, in);\n      setBitOfReversedStream(&obp, out, bit);\n    }\n    ibp += diff;\n  }\n}\n\n/*out must be buffer big enough to contain full image, and in must contain the full decompressed data from\nthe IDAT chunks (with filter index bytes and possible padding bits)\nreturn value is error*/\nstatic unsigned postProcessScanlines(unsigned char* out, unsigned char* in,\n                                     unsigned w, unsigned h, const LodePNGInfo* info_png)\n{\n  /*\n  This function converts the filtered-padded-interlaced data into pure 2D image buffer with the PNG's colortype.\n  Steps:\n  *) if no Adam7: 1) unfilter 2) remove padding bits (= posible extra bits per scanline if bpp < 8)\n  *) if adam7: 1) 7x unfilter 2) 7x remove padding bits 3) Adam7_deinterlace\n  NOTE: the in buffer will be overwritten with intermediate data!\n  */\n  unsigned bpp = lodepng_get_bpp(&info_png->color);\n  if(bpp == 0) return 31; /*error: invalid colortype*/\n\n  if(info_png->interlace_method == 0)\n  {\n    if(bpp < 8 && w * bpp != ((w * bpp + 7) / 8) * 8)\n    {\n      CERROR_TRY_RETURN(unfilter(in, in, w, h, bpp));\n      removePaddingBits(out, in, w * bpp, ((w * bpp + 7) / 8) * 8, h);\n    }\n    /*we can immediately filter into the out buffer, no other steps needed*/\n    else CERROR_TRY_RETURN(unfilter(out, in, w, h, bpp));\n  }\n  else /*interlace_method is 1 (Adam7)*/\n  {\n    unsigned passw[7], passh[7]; size_t filter_passstart[8], padded_passstart[8], passstart[8];\n    unsigned i;\n\n    Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp);\n\n    for(i = 0; i != 7; ++i)\n    {\n      CERROR_TRY_RETURN(unfilter(&in[padded_passstart[i]], &in[filter_passstart[i]], passw[i], passh[i], bpp));\n      /*TODO: possible efficiency improvement: if in this reduced image the bits fit nicely in 1 scanline,\n      move bytes instead of bits or move not at all*/\n      if(bpp < 8)\n      {\n        /*remove padding bits in scanlines; after this there still may be padding\n        bits between the different reduced images: each reduced image still starts nicely at a byte*/\n        removePaddingBits(&in[passstart[i]], &in[padded_passstart[i]], passw[i] * bpp,\n                          ((passw[i] * bpp + 7) / 8) * 8, passh[i]);\n      }\n    }\n\n    Adam7_deinterlace(out, in, w, h, bpp);\n  }\n\n  return 0;\n}\n\nstatic unsigned readChunk_PLTE(LodePNGColorMode* color, const unsigned char* data, size_t chunkLength)\n{\n  unsigned pos = 0, i;\n  if(color->palette) lodepng_free(color->palette);\n  color->palettesize = chunkLength / 3;\n  color->palette = (unsigned char*)lodepng_malloc(4 * color->palettesize);\n  if(!color->palette && color->palettesize)\n  {\n    color->palettesize = 0;\n    return 83; /*alloc fail*/\n  }\n  if(color->palettesize > 256) return 38; /*error: palette too big*/\n\n  for(i = 0; i != color->palettesize; ++i)\n  {\n    color->palette[4 * i + 0] = data[pos++]; /*R*/\n    color->palette[4 * i + 1] = data[pos++]; /*G*/\n    color->palette[4 * i + 2] = data[pos++]; /*B*/\n    color->palette[4 * i + 3] = 255; /*alpha*/\n  }\n\n  return 0; /* OK */\n}\n\nstatic unsigned readChunk_tRNS(LodePNGColorMode* color, const unsigned char* data, size_t chunkLength)\n{\n  unsigned i;\n  if(color->colortype == LCT_PALETTE)\n  {\n    /*error: more alpha values given than there are palette entries*/\n    if(chunkLength > color->palettesize) return 38;\n\n    for(i = 0; i != chunkLength; ++i) color->palette[4 * i + 3] = data[i];\n  }\n  else if(color->colortype == LCT_GREY)\n  {\n    /*error: this chunk must be 2 bytes for greyscale image*/\n    if(chunkLength != 2) return 30;\n\n    color->key_defined = 1;\n    color->key_r = color->key_g = color->key_b = 256u * data[0] + data[1];\n  }\n  else if(color->colortype == LCT_RGB)\n  {\n    /*error: this chunk must be 6 bytes for RGB image*/\n    if(chunkLength != 6) return 41;\n\n    color->key_defined = 1;\n    color->key_r = 256u * data[0] + data[1];\n    color->key_g = 256u * data[2] + data[3];\n    color->key_b = 256u * data[4] + data[5];\n  }\n  else return 42; /*error: tRNS chunk not allowed for other color models*/\n\n  return 0; /* OK */\n}\n\n\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\n/*background color chunk (bKGD)*/\nstatic unsigned readChunk_bKGD(LodePNGInfo* info, const unsigned char* data, size_t chunkLength)\n{\n  if(info->color.colortype == LCT_PALETTE)\n  {\n    /*error: this chunk must be 1 byte for indexed color image*/\n    if(chunkLength != 1) return 43;\n\n    info->background_defined = 1;\n    info->background_r = info->background_g = info->background_b = data[0];\n  }\n  else if(info->color.colortype == LCT_GREY || info->color.colortype == LCT_GREY_ALPHA)\n  {\n    /*error: this chunk must be 2 bytes for greyscale image*/\n    if(chunkLength != 2) return 44;\n\n    info->background_defined = 1;\n    info->background_r = info->background_g = info->background_b = 256u * data[0] + data[1];\n  }\n  else if(info->color.colortype == LCT_RGB || info->color.colortype == LCT_RGBA)\n  {\n    /*error: this chunk must be 6 bytes for greyscale image*/\n    if(chunkLength != 6) return 45;\n\n    info->background_defined = 1;\n    info->background_r = 256u * data[0] + data[1];\n    info->background_g = 256u * data[2] + data[3];\n    info->background_b = 256u * data[4] + data[5];\n  }\n\n  return 0; /* OK */\n}\n\n/*text chunk (tEXt)*/\nstatic unsigned readChunk_tEXt(LodePNGInfo* info, const unsigned char* data, size_t chunkLength)\n{\n  unsigned error = 0;\n  char *key = 0, *str = 0;\n  unsigned i;\n\n  while(!error) /*not really a while loop, only used to break on error*/\n  {\n    unsigned length, string2_begin;\n\n    length = 0;\n    while(length < chunkLength && data[length] != 0) ++length;\n    /*even though it's not allowed by the standard, no error is thrown if\n    there's no null termination char, if the text is empty*/\n    if(length < 1 || length > 79) CERROR_BREAK(error, 89); /*keyword too short or long*/\n\n    key = (char*)lodepng_malloc(length + 1);\n    if(!key) CERROR_BREAK(error, 83); /*alloc fail*/\n\n    key[length] = 0;\n    for(i = 0; i != length; ++i) key[i] = (char)data[i];\n\n    string2_begin = length + 1; /*skip keyword null terminator*/\n\n    length = (unsigned)(chunkLength < string2_begin ? 0 : chunkLength - string2_begin);\n    str = (char*)lodepng_malloc(length + 1);\n    if(!str) CERROR_BREAK(error, 83); /*alloc fail*/\n\n    str[length] = 0;\n    for(i = 0; i != length; ++i) str[i] = (char)data[string2_begin + i];\n\n    error = lodepng_add_text(info, key, str);\n\n    break;\n  }\n\n  lodepng_free(key);\n  lodepng_free(str);\n\n  return error;\n}\n\n/*compressed text chunk (zTXt)*/\nstatic unsigned readChunk_zTXt(LodePNGInfo* info, const LodePNGDecompressSettings* zlibsettings,\n                               const unsigned char* data, size_t chunkLength)\n{\n  unsigned error = 0;\n  unsigned i;\n\n  unsigned length, string2_begin;\n  char *key = 0;\n  ucvector decoded;\n\n  ucvector_init(&decoded);\n\n  while(!error) /*not really a while loop, only used to break on error*/\n  {\n    for(length = 0; length < chunkLength && data[length] != 0; ++length) ;\n    if(length + 2 >= chunkLength) CERROR_BREAK(error, 75); /*no null termination, corrupt?*/\n    if(length < 1 || length > 79) CERROR_BREAK(error, 89); /*keyword too short or long*/\n\n    key = (char*)lodepng_malloc(length + 1);\n    if(!key) CERROR_BREAK(error, 83); /*alloc fail*/\n\n    key[length] = 0;\n    for(i = 0; i != length; ++i) key[i] = (char)data[i];\n\n    if(data[length + 1] != 0) CERROR_BREAK(error, 72); /*the 0 byte indicating compression must be 0*/\n\n    string2_begin = length + 2;\n    if(string2_begin > chunkLength) CERROR_BREAK(error, 75); /*no null termination, corrupt?*/\n\n    length = (unsigned)chunkLength - string2_begin;\n    /*will fail if zlib error, e.g. if length is too small*/\n    error = zlib_decompress(&decoded.data, &decoded.size,\n                            (unsigned char*)(&data[string2_begin]),\n                            length, zlibsettings);\n    if(error) break;\n    ucvector_push_back(&decoded, 0);\n\n    error = lodepng_add_text(info, key, (char*)decoded.data);\n\n    break;\n  }\n\n  lodepng_free(key);\n  ucvector_cleanup(&decoded);\n\n  return error;\n}\n\n/*international text chunk (iTXt)*/\nstatic unsigned readChunk_iTXt(LodePNGInfo* info, const LodePNGDecompressSettings* zlibsettings,\n                               const unsigned char* data, size_t chunkLength)\n{\n  unsigned error = 0;\n  unsigned i;\n\n  unsigned length, begin, compressed;\n  char *key = 0, *langtag = 0, *transkey = 0;\n  ucvector decoded;\n  ucvector_init(&decoded);\n\n  while(!error) /*not really a while loop, only used to break on error*/\n  {\n    /*Quick check if the chunk length isn't too small. Even without check\n    it'd still fail with other error checks below if it's too short. This just gives a different error code.*/\n    if(chunkLength < 5) CERROR_BREAK(error, 30); /*iTXt chunk too short*/\n\n    /*read the key*/\n    for(length = 0; length < chunkLength && data[length] != 0; ++length) ;\n    if(length + 3 >= chunkLength) CERROR_BREAK(error, 75); /*no null termination char, corrupt?*/\n    if(length < 1 || length > 79) CERROR_BREAK(error, 89); /*keyword too short or long*/\n\n    key = (char*)lodepng_malloc(length + 1);\n    if(!key) CERROR_BREAK(error, 83); /*alloc fail*/\n\n    key[length] = 0;\n    for(i = 0; i != length; ++i) key[i] = (char)data[i];\n\n    /*read the compression method*/\n    compressed = data[length + 1];\n    if(data[length + 2] != 0) CERROR_BREAK(error, 72); /*the 0 byte indicating compression must be 0*/\n\n    /*even though it's not allowed by the standard, no error is thrown if\n    there's no null termination char, if the text is empty for the next 3 texts*/\n\n    /*read the langtag*/\n    begin = length + 3;\n    length = 0;\n    for(i = begin; i < chunkLength && data[i] != 0; ++i) ++length;\n\n    langtag = (char*)lodepng_malloc(length + 1);\n    if(!langtag) CERROR_BREAK(error, 83); /*alloc fail*/\n\n    langtag[length] = 0;\n    for(i = 0; i != length; ++i) langtag[i] = (char)data[begin + i];\n\n    /*read the transkey*/\n    begin += length + 1;\n    length = 0;\n    for(i = begin; i < chunkLength && data[i] != 0; ++i) ++length;\n\n    transkey = (char*)lodepng_malloc(length + 1);\n    if(!transkey) CERROR_BREAK(error, 83); /*alloc fail*/\n\n    transkey[length] = 0;\n    for(i = 0; i != length; ++i) transkey[i] = (char)data[begin + i];\n\n    /*read the actual text*/\n    begin += length + 1;\n\n    length = (unsigned)chunkLength < begin ? 0 : (unsigned)chunkLength - begin;\n\n    if(compressed)\n    {\n      /*will fail if zlib error, e.g. if length is too small*/\n      error = zlib_decompress(&decoded.data, &decoded.size,\n                              (unsigned char*)(&data[begin]),\n                              length, zlibsettings);\n      if(error) break;\n      if(decoded.allocsize < decoded.size) decoded.allocsize = decoded.size;\n      ucvector_push_back(&decoded, 0);\n    }\n    else\n    {\n      if(!ucvector_resize(&decoded, length + 1)) CERROR_BREAK(error, 83 /*alloc fail*/);\n\n      decoded.data[length] = 0;\n      for(i = 0; i != length; ++i) decoded.data[i] = data[begin + i];\n    }\n\n    error = lodepng_add_itext(info, key, langtag, transkey, (char*)decoded.data);\n\n    break;\n  }\n\n  lodepng_free(key);\n  lodepng_free(langtag);\n  lodepng_free(transkey);\n  ucvector_cleanup(&decoded);\n\n  return error;\n}\n\nstatic unsigned readChunk_tIME(LodePNGInfo* info, const unsigned char* data, size_t chunkLength)\n{\n  if(chunkLength != 7) return 73; /*invalid tIME chunk size*/\n\n  info->time_defined = 1;\n  info->time.year = 256u * data[0] + data[1];\n  info->time.month = data[2];\n  info->time.day = data[3];\n  info->time.hour = data[4];\n  info->time.minute = data[5];\n  info->time.second = data[6];\n\n  return 0; /* OK */\n}\n\nstatic unsigned readChunk_pHYs(LodePNGInfo* info, const unsigned char* data, size_t chunkLength)\n{\n  if(chunkLength != 9) return 74; /*invalid pHYs chunk size*/\n\n  info->phys_defined = 1;\n  info->phys_x = 16777216u * data[0] + 65536u * data[1] + 256u * data[2] + data[3];\n  info->phys_y = 16777216u * data[4] + 65536u * data[5] + 256u * data[6] + data[7];\n  info->phys_unit = data[8];\n\n  return 0; /* OK */\n}\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n\n/*read a PNG, the result will be in the same color type as the PNG (hence \"generic\")*/\nstatic void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h,\n                          LodePNGState* state,\n                          const unsigned char* in, size_t insize)\n{\n  unsigned char IEND = 0;\n  const unsigned char* chunk;\n  size_t i;\n  ucvector idat; /*the data from idat chunks*/\n  ucvector scanlines;\n  size_t predict;\n  size_t numpixels;\n  size_t outsize = 0;\n\n  /*for unknown chunk order*/\n  unsigned unknown = 0;\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\n  unsigned critical_pos = 1; /*1 = after IHDR, 2 = after PLTE, 3 = after IDAT*/\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n\n  /*provide some proper output values if error will happen*/\n  *out = 0;\n\n  state->error = lodepng_inspect(w, h, state, in, insize); /*reads header and resets other parameters in state->info_png*/\n  if(state->error) return;\n\n  numpixels = *w * *h;\n\n  /*multiplication overflow*/\n  if(*h != 0 && numpixels / *h != *w) CERROR_RETURN(state->error, 92);\n  /*multiplication overflow possible further below. Allows up to 2^31-1 pixel\n  bytes with 16-bit RGBA, the rest is room for filter bytes.*/\n  if(numpixels > 268435455) CERROR_RETURN(state->error, 92);\n\n  ucvector_init(&idat);\n  chunk = &in[33]; /*first byte of the first chunk after the header*/\n\n  /*loop through the chunks, ignoring unknown chunks and stopping at IEND chunk.\n  IDAT data is put at the start of the in buffer*/\n  while(!IEND && !state->error)\n  {\n    unsigned chunkLength;\n    const unsigned char* data; /*the data in the chunk*/\n\n    /*error: size of the in buffer too small to contain next chunk*/\n    if((size_t)((chunk - in) + 12) > insize || chunk < in)\n    {\n      if(state->decoder.ignore_end) break; /*other errors may still happen though*/\n      CERROR_BREAK(state->error, 30);\n    }\n\n    /*length of the data of the chunk, excluding the length bytes, chunk type and CRC bytes*/\n    chunkLength = lodepng_chunk_length(chunk);\n    /*error: chunk length larger than the max PNG chunk size*/\n    if(chunkLength > 2147483647)\n    {\n      if(state->decoder.ignore_end) break; /*other errors may still happen though*/\n      CERROR_BREAK(state->error, 63);\n    }\n\n    if((size_t)((chunk - in) + chunkLength + 12) > insize || (chunk + chunkLength + 12) < in)\n    {\n      CERROR_BREAK(state->error, 64); /*error: size of the in buffer too small to contain next chunk*/\n    }\n\n    data = lodepng_chunk_data_const(chunk);\n\n    /*IDAT chunk, containing compressed image data*/\n    if(lodepng_chunk_type_equals(chunk, \"IDAT\"))\n    {\n      size_t oldsize = idat.size;\n      if(!ucvector_resize(&idat, oldsize + chunkLength)) CERROR_BREAK(state->error, 83 /*alloc fail*/);\n      for(i = 0; i != chunkLength; ++i) idat.data[oldsize + i] = data[i];\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\n      critical_pos = 3;\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n    }\n    /*IEND chunk*/\n    else if(lodepng_chunk_type_equals(chunk, \"IEND\"))\n    {\n      IEND = 1;\n    }\n    /*palette chunk (PLTE)*/\n    else if(lodepng_chunk_type_equals(chunk, \"PLTE\"))\n    {\n      state->error = readChunk_PLTE(&state->info_png.color, data, chunkLength);\n      if(state->error) break;\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\n      critical_pos = 2;\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n    }\n    /*palette transparency chunk (tRNS)*/\n    else if(lodepng_chunk_type_equals(chunk, \"tRNS\"))\n    {\n      state->error = readChunk_tRNS(&state->info_png.color, data, chunkLength);\n      if(state->error) break;\n    }\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\n    /*background color chunk (bKGD)*/\n    else if(lodepng_chunk_type_equals(chunk, \"bKGD\"))\n    {\n      state->error = readChunk_bKGD(&state->info_png, data, chunkLength);\n      if(state->error) break;\n    }\n    /*text chunk (tEXt)*/\n    else if(lodepng_chunk_type_equals(chunk, \"tEXt\"))\n    {\n      if(state->decoder.read_text_chunks)\n      {\n        state->error = readChunk_tEXt(&state->info_png, data, chunkLength);\n        if(state->error) break;\n      }\n    }\n    /*compressed text chunk (zTXt)*/\n    else if(lodepng_chunk_type_equals(chunk, \"zTXt\"))\n    {\n      if(state->decoder.read_text_chunks)\n      {\n        state->error = readChunk_zTXt(&state->info_png, &state->decoder.zlibsettings, data, chunkLength);\n        if(state->error) break;\n      }\n    }\n    /*international text chunk (iTXt)*/\n    else if(lodepng_chunk_type_equals(chunk, \"iTXt\"))\n    {\n      if(state->decoder.read_text_chunks)\n      {\n        state->error = readChunk_iTXt(&state->info_png, &state->decoder.zlibsettings, data, chunkLength);\n        if(state->error) break;\n      }\n    }\n    else if(lodepng_chunk_type_equals(chunk, \"tIME\"))\n    {\n      state->error = readChunk_tIME(&state->info_png, data, chunkLength);\n      if(state->error) break;\n    }\n    else if(lodepng_chunk_type_equals(chunk, \"pHYs\"))\n    {\n      state->error = readChunk_pHYs(&state->info_png, data, chunkLength);\n      if(state->error) break;\n    }\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n    else /*it's not an implemented chunk type, so ignore it: skip over the data*/\n    {\n      /*error: unknown critical chunk (5th bit of first byte of chunk type is 0)*/\n      if(!state->decoder.ignore_critical && !lodepng_chunk_ancillary(chunk))\n      {\n        CERROR_BREAK(state->error, 69);\n      }\n\n      unknown = 1;\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\n      if(state->decoder.remember_unknown_chunks)\n      {\n        state->error = lodepng_chunk_append(&state->info_png.unknown_chunks_data[critical_pos - 1],\n                                            &state->info_png.unknown_chunks_size[critical_pos - 1], chunk);\n        if(state->error) break;\n      }\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n    }\n\n    if(!state->decoder.ignore_crc && !unknown) /*check CRC if wanted, only on known chunk types*/\n    {\n      if(lodepng_chunk_check_crc(chunk)) CERROR_BREAK(state->error, 57); /*invalid CRC*/\n    }\n\n    if(!IEND) chunk = lodepng_chunk_next_const(chunk);\n  }\n\n  ucvector_init(&scanlines);\n  /*predict output size, to allocate exact size for output buffer to avoid more dynamic allocation.\n  If the decompressed size does not match the prediction, the image must be corrupt.*/\n  if(state->info_png.interlace_method == 0)\n  {\n    /*The extra *h is added because this are the filter bytes every scanline starts with*/\n    predict = lodepng_get_raw_size_idat(*w, *h, &state->info_png.color) + *h;\n  }\n  else\n  {\n    /*Adam-7 interlaced: predicted size is the sum of the 7 sub-images sizes*/\n    const LodePNGColorMode* color = &state->info_png.color;\n    predict = 0;\n    predict += lodepng_get_raw_size_idat((*w + 7) >> 3, (*h + 7) >> 3, color) + ((*h + 7) >> 3);\n    if(*w > 4) predict += lodepng_get_raw_size_idat((*w + 3) >> 3, (*h + 7) >> 3, color) + ((*h + 7) >> 3);\n    predict += lodepng_get_raw_size_idat((*w + 3) >> 2, (*h + 3) >> 3, color) + ((*h + 3) >> 3);\n    if(*w > 2) predict += lodepng_get_raw_size_idat((*w + 1) >> 2, (*h + 3) >> 2, color) + ((*h + 3) >> 2);\n    predict += lodepng_get_raw_size_idat((*w + 1) >> 1, (*h + 1) >> 2, color) + ((*h + 1) >> 2);\n    if(*w > 1) predict += lodepng_get_raw_size_idat((*w + 0) >> 1, (*h + 1) >> 1, color) + ((*h + 1) >> 1);\n    predict += lodepng_get_raw_size_idat((*w + 0), (*h + 0) >> 1, color) + ((*h + 0) >> 1);\n  }\n  if(!state->error && !ucvector_reserve(&scanlines, predict)) state->error = 83; /*alloc fail*/\n  if(!state->error)\n  {\n    state->error = zlib_decompress(&scanlines.data, &scanlines.size, idat.data,\n                                   idat.size, &state->decoder.zlibsettings);\n    if(!state->error && scanlines.size != predict) state->error = 91; /*decompressed size doesn't match prediction*/\n  }\n  ucvector_cleanup(&idat);\n\n  if(!state->error)\n  {\n    outsize = lodepng_get_raw_size(*w, *h, &state->info_png.color);\n    *out = (unsigned char*)lodepng_malloc(outsize);\n    if(!*out) state->error = 83; /*alloc fail*/\n  }\n  if(!state->error)\n  {\n    for(i = 0; i < outsize; i++) (*out)[i] = 0;\n    state->error = postProcessScanlines(*out, scanlines.data, *w, *h, &state->info_png);\n  }\n  ucvector_cleanup(&scanlines);\n}\n\nunsigned lodepng_decode(unsigned char** out, unsigned* w, unsigned* h,\n                        LodePNGState* state,\n                        const unsigned char* in, size_t insize)\n{\n  *out = 0;\n  decodeGeneric(out, w, h, state, in, insize);\n  if(state->error) return state->error;\n  if(!state->decoder.color_convert || lodepng_color_mode_equal(&state->info_raw, &state->info_png.color))\n  {\n    /*same color type, no copying or converting of data needed*/\n    /*store the info_png color settings on the info_raw so that the info_raw still reflects what colortype\n    the raw image has to the end user*/\n    if(!state->decoder.color_convert)\n    {\n      state->error = lodepng_color_mode_copy(&state->info_raw, &state->info_png.color);\n      if(state->error) return state->error;\n    }\n  }\n  else\n  {\n    /*color conversion needed; sort of copy of the data*/\n    unsigned char* data = *out;\n    size_t outsize;\n\n    /*TODO: check if this works according to the statement in the documentation: \"The converter can convert\n    from greyscale input color type, to 8-bit greyscale or greyscale with alpha\"*/\n    if(!(state->info_raw.colortype == LCT_RGB || state->info_raw.colortype == LCT_RGBA)\n       && !(state->info_raw.bitdepth == 8))\n    {\n      return 56; /*unsupported color mode conversion*/\n    }\n\n    outsize = lodepng_get_raw_size(*w, *h, &state->info_raw);\n    *out = (unsigned char*)lodepng_malloc(outsize);\n    if(!(*out))\n    {\n      state->error = 83; /*alloc fail*/\n    }\n    else state->error = lodepng_convert(*out, data, &state->info_raw,\n                                        &state->info_png.color, *w, *h);\n    lodepng_free(data);\n  }\n  return state->error;\n}\n\nunsigned lodepng_decode_memory(unsigned char** out, unsigned* w, unsigned* h, const unsigned char* in,\n                               size_t insize, LodePNGColorType colortype, unsigned bitdepth)\n{\n  unsigned error;\n  LodePNGState state;\n  lodepng_state_init(&state);\n  state.info_raw.colortype = colortype;\n  state.info_raw.bitdepth = bitdepth;\n  error = lodepng_decode(out, w, h, &state, in, insize);\n  lodepng_state_cleanup(&state);\n  return error;\n}\n\nunsigned lodepng_decode32(unsigned char** out, unsigned* w, unsigned* h, const unsigned char* in, size_t insize)\n{\n  return lodepng_decode_memory(out, w, h, in, insize, LCT_RGBA, 8);\n}\n\nunsigned lodepng_decode24(unsigned char** out, unsigned* w, unsigned* h, const unsigned char* in, size_t insize)\n{\n  return lodepng_decode_memory(out, w, h, in, insize, LCT_RGB, 8);\n}\n\n#ifdef LODEPNG_COMPILE_DISK\nunsigned lodepng_decode_file(unsigned char** out, unsigned* w, unsigned* h, const char* filename,\n                             LodePNGColorType colortype, unsigned bitdepth)\n{\n  unsigned char* buffer = 0;\n  size_t buffersize;\n  unsigned error;\n  error = lodepng_load_file(&buffer, &buffersize, filename);\n  if(!error) error = lodepng_decode_memory(out, w, h, buffer, buffersize, colortype, bitdepth);\n  lodepng_free(buffer);\n  return error;\n}\n\nunsigned lodepng_decode32_file(unsigned char** out, unsigned* w, unsigned* h, const char* filename)\n{\n  return lodepng_decode_file(out, w, h, filename, LCT_RGBA, 8);\n}\n\nunsigned lodepng_decode24_file(unsigned char** out, unsigned* w, unsigned* h, const char* filename)\n{\n  return lodepng_decode_file(out, w, h, filename, LCT_RGB, 8);\n}\n#endif /*LODEPNG_COMPILE_DISK*/\n\nvoid lodepng_decoder_settings_init(LodePNGDecoderSettings* settings)\n{\n  settings->color_convert = 1;\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\n  settings->read_text_chunks = 1;\n  settings->remember_unknown_chunks = 0;\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n  settings->ignore_crc = 0;\n  settings->ignore_critical = 0;\n  settings->ignore_end = 0;\n  lodepng_decompress_settings_init(&settings->zlibsettings);\n}\n\n#endif /*LODEPNG_COMPILE_DECODER*/\n\n#if defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER)\n\nvoid lodepng_state_init(LodePNGState* state)\n{\n#ifdef LODEPNG_COMPILE_DECODER\n  lodepng_decoder_settings_init(&state->decoder);\n#endif /*LODEPNG_COMPILE_DECODER*/\n#ifdef LODEPNG_COMPILE_ENCODER\n  lodepng_encoder_settings_init(&state->encoder);\n#endif /*LODEPNG_COMPILE_ENCODER*/\n  lodepng_color_mode_init(&state->info_raw);\n  lodepng_info_init(&state->info_png);\n  state->error = 1;\n}\n\nvoid lodepng_state_cleanup(LodePNGState* state)\n{\n  lodepng_color_mode_cleanup(&state->info_raw);\n  lodepng_info_cleanup(&state->info_png);\n}\n\nvoid lodepng_state_copy(LodePNGState* dest, const LodePNGState* source)\n{\n  lodepng_state_cleanup(dest);\n  *dest = *source;\n  lodepng_color_mode_init(&dest->info_raw);\n  lodepng_info_init(&dest->info_png);\n  dest->error = lodepng_color_mode_copy(&dest->info_raw, &source->info_raw); if(dest->error) return;\n  dest->error = lodepng_info_copy(&dest->info_png, &source->info_png); if(dest->error) return;\n}\n\n#endif /* defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER) */\n\n#ifdef LODEPNG_COMPILE_ENCODER\n\n/* ////////////////////////////////////////////////////////////////////////// */\n/* / PNG Encoder                                                            / */\n/* ////////////////////////////////////////////////////////////////////////// */\n\n/*chunkName must be string of 4 characters*/\nstatic unsigned addChunk(ucvector* out, const char* chunkName, const unsigned char* data, size_t length)\n{\n  CERROR_TRY_RETURN(lodepng_chunk_create(&out->data, &out->size, (unsigned)length, chunkName, data));\n  out->allocsize = out->size; /*fix the allocsize again*/\n  return 0;\n}\n\nstatic void writeSignature(ucvector* out)\n{\n  /*8 bytes PNG signature, aka the magic bytes*/\n  ucvector_push_back(out, 137);\n  ucvector_push_back(out, 80);\n  ucvector_push_back(out, 78);\n  ucvector_push_back(out, 71);\n  ucvector_push_back(out, 13);\n  ucvector_push_back(out, 10);\n  ucvector_push_back(out, 26);\n  ucvector_push_back(out, 10);\n}\n\nstatic unsigned addChunk_IHDR(ucvector* out, unsigned w, unsigned h,\n                              LodePNGColorType colortype, unsigned bitdepth, unsigned interlace_method)\n{\n  unsigned error = 0;\n  ucvector header;\n  ucvector_init(&header);\n\n  lodepng_add32bitInt(&header, w); /*width*/\n  lodepng_add32bitInt(&header, h); /*height*/\n  ucvector_push_back(&header, (unsigned char)bitdepth); /*bit depth*/\n  ucvector_push_back(&header, (unsigned char)colortype); /*color type*/\n  ucvector_push_back(&header, 0); /*compression method*/\n  ucvector_push_back(&header, 0); /*filter method*/\n  ucvector_push_back(&header, interlace_method); /*interlace method*/\n\n  error = addChunk(out, \"IHDR\", header.data, header.size);\n  ucvector_cleanup(&header);\n\n  return error;\n}\n\nstatic unsigned addChunk_PLTE(ucvector* out, const LodePNGColorMode* info)\n{\n  unsigned error = 0;\n  size_t i;\n  ucvector PLTE;\n  ucvector_init(&PLTE);\n  for(i = 0; i != info->palettesize * 4; ++i)\n  {\n    /*add all channels except alpha channel*/\n    if(i % 4 != 3) ucvector_push_back(&PLTE, info->palette[i]);\n  }\n  error = addChunk(out, \"PLTE\", PLTE.data, PLTE.size);\n  ucvector_cleanup(&PLTE);\n\n  return error;\n}\n\nstatic unsigned addChunk_tRNS(ucvector* out, const LodePNGColorMode* info)\n{\n  unsigned error = 0;\n  size_t i;\n  ucvector tRNS;\n  ucvector_init(&tRNS);\n  if(info->colortype == LCT_PALETTE)\n  {\n    size_t amount = info->palettesize;\n    /*the tail of palette values that all have 255 as alpha, does not have to be encoded*/\n    for(i = info->palettesize; i != 0; --i)\n    {\n      if(info->palette[4 * (i - 1) + 3] == 255) --amount;\n      else break;\n    }\n    /*add only alpha channel*/\n    for(i = 0; i != amount; ++i) ucvector_push_back(&tRNS, info->palette[4 * i + 3]);\n  }\n  else if(info->colortype == LCT_GREY)\n  {\n    if(info->key_defined)\n    {\n      ucvector_push_back(&tRNS, (unsigned char)(info->key_r >> 8));\n      ucvector_push_back(&tRNS, (unsigned char)(info->key_r & 255));\n    }\n  }\n  else if(info->colortype == LCT_RGB)\n  {\n    if(info->key_defined)\n    {\n      ucvector_push_back(&tRNS, (unsigned char)(info->key_r >> 8));\n      ucvector_push_back(&tRNS, (unsigned char)(info->key_r & 255));\n      ucvector_push_back(&tRNS, (unsigned char)(info->key_g >> 8));\n      ucvector_push_back(&tRNS, (unsigned char)(info->key_g & 255));\n      ucvector_push_back(&tRNS, (unsigned char)(info->key_b >> 8));\n      ucvector_push_back(&tRNS, (unsigned char)(info->key_b & 255));\n    }\n  }\n\n  error = addChunk(out, \"tRNS\", tRNS.data, tRNS.size);\n  ucvector_cleanup(&tRNS);\n\n  return error;\n}\n\nstatic unsigned addChunk_IDAT(ucvector* out, const unsigned char* data, size_t datasize,\n                              LodePNGCompressSettings* zlibsettings)\n{\n  ucvector zlibdata;\n  unsigned error = 0;\n\n  /*compress with the Zlib compressor*/\n  ucvector_init(&zlibdata);\n  error = zlib_compress(&zlibdata.data, &zlibdata.size, data, datasize, zlibsettings);\n  if(!error) error = addChunk(out, \"IDAT\", zlibdata.data, zlibdata.size);\n  ucvector_cleanup(&zlibdata);\n\n  return error;\n}\n\nstatic unsigned addChunk_IEND(ucvector* out)\n{\n  unsigned error = 0;\n  error = addChunk(out, \"IEND\", 0, 0);\n  return error;\n}\n\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\n\nstatic unsigned addChunk_tEXt(ucvector* out, const char* keyword, const char* textstring)\n{\n  unsigned error = 0;\n  size_t i;\n  ucvector text;\n  ucvector_init(&text);\n  for(i = 0; keyword[i] != 0; ++i) ucvector_push_back(&text, (unsigned char)keyword[i]);\n  if(i < 1 || i > 79) return 89; /*error: invalid keyword size*/\n  ucvector_push_back(&text, 0); /*0 termination char*/\n  for(i = 0; textstring[i] != 0; ++i) ucvector_push_back(&text, (unsigned char)textstring[i]);\n  error = addChunk(out, \"tEXt\", text.data, text.size);\n  ucvector_cleanup(&text);\n\n  return error;\n}\n\nstatic unsigned addChunk_zTXt(ucvector* out, const char* keyword, const char* textstring,\n                              LodePNGCompressSettings* zlibsettings)\n{\n  unsigned error = 0;\n  ucvector data, compressed;\n  size_t i, textsize = strlen(textstring);\n\n  ucvector_init(&data);\n  ucvector_init(&compressed);\n  for(i = 0; keyword[i] != 0; ++i) ucvector_push_back(&data, (unsigned char)keyword[i]);\n  if(i < 1 || i > 79) return 89; /*error: invalid keyword size*/\n  ucvector_push_back(&data, 0); /*0 termination char*/\n  ucvector_push_back(&data, 0); /*compression method: 0*/\n\n  error = zlib_compress(&compressed.data, &compressed.size,\n                        (unsigned char*)textstring, textsize, zlibsettings);\n  if(!error)\n  {\n    for(i = 0; i != compressed.size; ++i) ucvector_push_back(&data, compressed.data[i]);\n    error = addChunk(out, \"zTXt\", data.data, data.size);\n  }\n\n  ucvector_cleanup(&compressed);\n  ucvector_cleanup(&data);\n  return error;\n}\n\nstatic unsigned addChunk_iTXt(ucvector* out, unsigned compressed, const char* keyword, const char* langtag,\n                              const char* transkey, const char* textstring, LodePNGCompressSettings* zlibsettings)\n{\n  unsigned error = 0;\n  ucvector data;\n  size_t i, textsize = strlen(textstring);\n\n  ucvector_init(&data);\n\n  for(i = 0; keyword[i] != 0; ++i) ucvector_push_back(&data, (unsigned char)keyword[i]);\n  if(i < 1 || i > 79) return 89; /*error: invalid keyword size*/\n  ucvector_push_back(&data, 0); /*null termination char*/\n  ucvector_push_back(&data, compressed ? 1 : 0); /*compression flag*/\n  ucvector_push_back(&data, 0); /*compression method*/\n  for(i = 0; langtag[i] != 0; ++i) ucvector_push_back(&data, (unsigned char)langtag[i]);\n  ucvector_push_back(&data, 0); /*null termination char*/\n  for(i = 0; transkey[i] != 0; ++i) ucvector_push_back(&data, (unsigned char)transkey[i]);\n  ucvector_push_back(&data, 0); /*null termination char*/\n\n  if(compressed)\n  {\n    ucvector compressed_data;\n    ucvector_init(&compressed_data);\n    error = zlib_compress(&compressed_data.data, &compressed_data.size,\n                          (unsigned char*)textstring, textsize, zlibsettings);\n    if(!error)\n    {\n      for(i = 0; i != compressed_data.size; ++i) ucvector_push_back(&data, compressed_data.data[i]);\n    }\n    ucvector_cleanup(&compressed_data);\n  }\n  else /*not compressed*/\n  {\n    for(i = 0; textstring[i] != 0; ++i) ucvector_push_back(&data, (unsigned char)textstring[i]);\n  }\n\n  if(!error) error = addChunk(out, \"iTXt\", data.data, data.size);\n  ucvector_cleanup(&data);\n  return error;\n}\n\nstatic unsigned addChunk_bKGD(ucvector* out, const LodePNGInfo* info)\n{\n  unsigned error = 0;\n  ucvector bKGD;\n  ucvector_init(&bKGD);\n  if(info->color.colortype == LCT_GREY || info->color.colortype == LCT_GREY_ALPHA)\n  {\n    ucvector_push_back(&bKGD, (unsigned char)(info->background_r >> 8));\n    ucvector_push_back(&bKGD, (unsigned char)(info->background_r & 255));\n  }\n  else if(info->color.colortype == LCT_RGB || info->color.colortype == LCT_RGBA)\n  {\n    ucvector_push_back(&bKGD, (unsigned char)(info->background_r >> 8));\n    ucvector_push_back(&bKGD, (unsigned char)(info->background_r & 255));\n    ucvector_push_back(&bKGD, (unsigned char)(info->background_g >> 8));\n    ucvector_push_back(&bKGD, (unsigned char)(info->background_g & 255));\n    ucvector_push_back(&bKGD, (unsigned char)(info->background_b >> 8));\n    ucvector_push_back(&bKGD, (unsigned char)(info->background_b & 255));\n  }\n  else if(info->color.colortype == LCT_PALETTE)\n  {\n    ucvector_push_back(&bKGD, (unsigned char)(info->background_r & 255)); /*palette index*/\n  }\n\n  error = addChunk(out, \"bKGD\", bKGD.data, bKGD.size);\n  ucvector_cleanup(&bKGD);\n\n  return error;\n}\n\nstatic unsigned addChunk_tIME(ucvector* out, const LodePNGTime* time)\n{\n  unsigned error = 0;\n  unsigned char* data = (unsigned char*)lodepng_malloc(7);\n  if(!data) return 83; /*alloc fail*/\n  data[0] = (unsigned char)(time->year >> 8);\n  data[1] = (unsigned char)(time->year & 255);\n  data[2] = (unsigned char)time->month;\n  data[3] = (unsigned char)time->day;\n  data[4] = (unsigned char)time->hour;\n  data[5] = (unsigned char)time->minute;\n  data[6] = (unsigned char)time->second;\n  error = addChunk(out, \"tIME\", data, 7);\n  lodepng_free(data);\n  return error;\n}\n\nstatic unsigned addChunk_pHYs(ucvector* out, const LodePNGInfo* info)\n{\n  unsigned error = 0;\n  ucvector data;\n  ucvector_init(&data);\n\n  lodepng_add32bitInt(&data, info->phys_x);\n  lodepng_add32bitInt(&data, info->phys_y);\n  ucvector_push_back(&data, info->phys_unit);\n\n  error = addChunk(out, \"pHYs\", data.data, data.size);\n  ucvector_cleanup(&data);\n\n  return error;\n}\n\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n\nstatic void filterScanline(unsigned char* out, const unsigned char* scanline, const unsigned char* prevline,\n                           size_t length, size_t bytewidth, unsigned char filterType)\n{\n  size_t i;\n  switch(filterType)\n  {\n    case 0: /*None*/\n      for(i = 0; i != length; ++i) out[i] = scanline[i];\n      break;\n    case 1: /*Sub*/\n      for(i = 0; i != bytewidth; ++i) out[i] = scanline[i];\n      for(i = bytewidth; i < length; ++i) out[i] = scanline[i] - scanline[i - bytewidth];\n      break;\n    case 2: /*Up*/\n      if(prevline)\n      {\n        for(i = 0; i != length; ++i) out[i] = scanline[i] - prevline[i];\n      }\n      else\n      {\n        for(i = 0; i != length; ++i) out[i] = scanline[i];\n      }\n      break;\n    case 3: /*Average*/\n      if(prevline)\n      {\n        for(i = 0; i != bytewidth; ++i) out[i] = scanline[i] - (prevline[i] >> 1);\n        for(i = bytewidth; i < length; ++i) out[i] = scanline[i] - ((scanline[i - bytewidth] + prevline[i]) >> 1);\n      }\n      else\n      {\n        for(i = 0; i != bytewidth; ++i) out[i] = scanline[i];\n        for(i = bytewidth; i < length; ++i) out[i] = scanline[i] - (scanline[i - bytewidth] >> 1);\n      }\n      break;\n    case 4: /*Paeth*/\n      if(prevline)\n      {\n        /*paethPredictor(0, prevline[i], 0) is always prevline[i]*/\n        for(i = 0; i != bytewidth; ++i) out[i] = (scanline[i] - prevline[i]);\n        for(i = bytewidth; i < length; ++i)\n        {\n          out[i] = (scanline[i] - paethPredictor(scanline[i - bytewidth], prevline[i], prevline[i - bytewidth]));\n        }\n      }\n      else\n      {\n        for(i = 0; i != bytewidth; ++i) out[i] = scanline[i];\n        /*paethPredictor(scanline[i - bytewidth], 0, 0) is always scanline[i - bytewidth]*/\n        for(i = bytewidth; i < length; ++i) out[i] = (scanline[i] - scanline[i - bytewidth]);\n      }\n      break;\n    default: return; /*unexisting filter type given*/\n  }\n}\n\n/* log2 approximation. A slight bit faster than std::log. */\nstatic float flog2(float f)\n{\n  float result = 0;\n  while(f > 32) { result += 4; f /= 16; }\n  while(f > 2) { ++result; f /= 2; }\n  return result + 1.442695f * (f * f * f / 3 - 3 * f * f / 2 + 3 * f - 1.83333f);\n}\n\nstatic unsigned filter(unsigned char* out, const unsigned char* in, unsigned w, unsigned h,\n                       const LodePNGColorMode* info, const LodePNGEncoderSettings* settings)\n{\n  /*\n  For PNG filter method 0\n  out must be a buffer with as size: h + (w * h * bpp + 7) / 8, because there are\n  the scanlines with 1 extra byte per scanline\n  */\n\n  unsigned bpp = lodepng_get_bpp(info);\n  /*the width of a scanline in bytes, not including the filter type*/\n  size_t linebytes = (w * bpp + 7) / 8;\n  /*bytewidth is used for filtering, is 1 when bpp < 8, number of bytes per pixel otherwise*/\n  size_t bytewidth = (bpp + 7) / 8;\n  const unsigned char* prevline = 0;\n  unsigned x, y;\n  unsigned error = 0;\n  LodePNGFilterStrategy strategy = settings->filter_strategy;\n\n  /*\n  There is a heuristic called the minimum sum of absolute differences heuristic, suggested by the PNG standard:\n   *  If the image type is Palette, or the bit depth is smaller than 8, then do not filter the image (i.e.\n      use fixed filtering, with the filter None).\n   * (The other case) If the image type is Grayscale or RGB (with or without Alpha), and the bit depth is\n     not smaller than 8, then use adaptive filtering heuristic as follows: independently for each row, apply\n     all five filters and select the filter that produces the smallest sum of absolute values per row.\n  This heuristic is used if filter strategy is LFS_MINSUM and filter_palette_zero is true.\n\n  If filter_palette_zero is true and filter_strategy is not LFS_MINSUM, the above heuristic is followed,\n  but for \"the other case\", whatever strategy filter_strategy is set to instead of the minimum sum\n  heuristic is used.\n  */\n  if(settings->filter_palette_zero &&\n     (info->colortype == LCT_PALETTE || info->bitdepth < 8)) strategy = LFS_ZERO;\n\n  if(bpp == 0) return 31; /*error: invalid color type*/\n\n  if(strategy == LFS_ZERO)\n  {\n    for(y = 0; y != h; ++y)\n    {\n      size_t outindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/\n      size_t inindex = linebytes * y;\n      out[outindex] = 0; /*filter type byte*/\n      filterScanline(&out[outindex + 1], &in[inindex], prevline, linebytes, bytewidth, 0);\n      prevline = &in[inindex];\n    }\n  }\n  else if(strategy == LFS_MINSUM)\n  {\n    /*adaptive filtering*/\n    size_t sum[5];\n    unsigned char* attempt[5]; /*five filtering attempts, one for each filter type*/\n    size_t smallest = 0;\n    unsigned char type, bestType = 0;\n\n    for(type = 0; type != 5; ++type)\n    {\n      attempt[type] = (unsigned char*)lodepng_malloc(linebytes);\n      if(!attempt[type]) return 83; /*alloc fail*/\n    }\n\n    if(!error)\n    {\n      for(y = 0; y != h; ++y)\n      {\n        /*try the 5 filter types*/\n        for(type = 0; type != 5; ++type)\n        {\n          filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type);\n\n          /*calculate the sum of the result*/\n          sum[type] = 0;\n          if(type == 0)\n          {\n            for(x = 0; x != linebytes; ++x) sum[type] += (unsigned char)(attempt[type][x]);\n          }\n          else\n          {\n            for(x = 0; x != linebytes; ++x)\n            {\n              /*For differences, each byte should be treated as signed, values above 127 are negative\n              (converted to signed char). Filtertype 0 isn't a difference though, so use unsigned there.\n              This means filtertype 0 is almost never chosen, but that is justified.*/\n              unsigned char s = attempt[type][x];\n              sum[type] += s < 128 ? s : (255U - s);\n            }\n          }\n\n          /*check if this is smallest sum (or if type == 0 it's the first case so always store the values)*/\n          if(type == 0 || sum[type] < smallest)\n          {\n            bestType = type;\n            smallest = sum[type];\n          }\n        }\n\n        prevline = &in[y * linebytes];\n\n        /*now fill the out values*/\n        out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/\n        for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x];\n      }\n    }\n\n    for(type = 0; type != 5; ++type) lodepng_free(attempt[type]);\n  }\n  else if(strategy == LFS_ENTROPY)\n  {\n    float sum[5];\n    unsigned char* attempt[5]; /*five filtering attempts, one for each filter type*/\n    float smallest = 0;\n    unsigned type, bestType = 0;\n    unsigned count[256];\n\n    for(type = 0; type != 5; ++type)\n    {\n      attempt[type] = (unsigned char*)lodepng_malloc(linebytes);\n      if(!attempt[type]) return 83; /*alloc fail*/\n    }\n\n    for(y = 0; y != h; ++y)\n    {\n      /*try the 5 filter types*/\n      for(type = 0; type != 5; ++type)\n      {\n        filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type);\n        for(x = 0; x != 256; ++x) count[x] = 0;\n        for(x = 0; x != linebytes; ++x) ++count[attempt[type][x]];\n        ++count[type]; /*the filter type itself is part of the scanline*/\n        sum[type] = 0;\n        for(x = 0; x != 256; ++x)\n        {\n          float p = count[x] / (float)(linebytes + 1);\n          sum[type] += count[x] == 0 ? 0 : flog2(1 / p) * p;\n        }\n        /*check if this is smallest sum (or if type == 0 it's the first case so always store the values)*/\n        if(type == 0 || sum[type] < smallest)\n        {\n          bestType = type;\n          smallest = sum[type];\n        }\n      }\n\n      prevline = &in[y * linebytes];\n\n      /*now fill the out values*/\n      out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/\n      for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x];\n    }\n\n    for(type = 0; type != 5; ++type) lodepng_free(attempt[type]);\n  }\n  else if(strategy == LFS_PREDEFINED)\n  {\n    for(y = 0; y != h; ++y)\n    {\n      size_t outindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/\n      size_t inindex = linebytes * y;\n      unsigned char type = settings->predefined_filters[y];\n      out[outindex] = type; /*filter type byte*/\n      filterScanline(&out[outindex + 1], &in[inindex], prevline, linebytes, bytewidth, type);\n      prevline = &in[inindex];\n    }\n  }\n  else if(strategy == LFS_BRUTE_FORCE)\n  {\n    /*brute force filter chooser.\n    deflate the scanline after every filter attempt to see which one deflates best.\n    This is very slow and gives only slightly smaller, sometimes even larger, result*/\n    size_t size[5];\n    unsigned char* attempt[5]; /*five filtering attempts, one for each filter type*/\n    size_t smallest = 0;\n    unsigned type = 0, bestType = 0;\n    unsigned char* dummy;\n    LodePNGCompressSettings zlibsettings = settings->zlibsettings;\n    /*use fixed tree on the attempts so that the tree is not adapted to the filtertype on purpose,\n    to simulate the true case where the tree is the same for the whole image. Sometimes it gives\n    better result with dynamic tree anyway. Using the fixed tree sometimes gives worse, but in rare\n    cases better compression. It does make this a bit less slow, so it's worth doing this.*/\n    zlibsettings.btype = 1;\n    /*a custom encoder likely doesn't read the btype setting and is optimized for complete PNG\n    images only, so disable it*/\n    zlibsettings.custom_zlib = 0;\n    zlibsettings.custom_deflate = 0;\n    for(type = 0; type != 5; ++type)\n    {\n      attempt[type] = (unsigned char*)lodepng_malloc(linebytes);\n      if(!attempt[type]) return 83; /*alloc fail*/\n    }\n    for(y = 0; y != h; ++y) /*try the 5 filter types*/\n    {\n      for(type = 0; type != 5; ++type)\n      {\n        unsigned testsize = (unsigned)linebytes;\n        /*if(testsize > 8) testsize /= 8;*/ /*it already works good enough by testing a part of the row*/\n\n        filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type);\n        size[type] = 0;\n        dummy = 0;\n        zlib_compress(&dummy, &size[type], attempt[type], testsize, &zlibsettings);\n        lodepng_free(dummy);\n        /*check if this is smallest size (or if type == 0 it's the first case so always store the values)*/\n        if(type == 0 || size[type] < smallest)\n        {\n          bestType = type;\n          smallest = size[type];\n        }\n      }\n      prevline = &in[y * linebytes];\n      out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/\n      for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x];\n    }\n    for(type = 0; type != 5; ++type) lodepng_free(attempt[type]);\n  }\n  else return 88; /* unknown filter strategy */\n\n  return error;\n}\n\nstatic void addPaddingBits(unsigned char* out, const unsigned char* in,\n                           size_t olinebits, size_t ilinebits, unsigned h)\n{\n  /*The opposite of the removePaddingBits function\n  olinebits must be >= ilinebits*/\n  unsigned y;\n  size_t diff = olinebits - ilinebits;\n  size_t obp = 0, ibp = 0; /*bit pointers*/\n  for(y = 0; y != h; ++y)\n  {\n    size_t x;\n    for(x = 0; x < ilinebits; ++x)\n    {\n      unsigned char bit = readBitFromReversedStream(&ibp, in);\n      setBitOfReversedStream(&obp, out, bit);\n    }\n    /*obp += diff; --> no, fill in some value in the padding bits too, to avoid\n    \"Use of uninitialised value of size ###\" warning from valgrind*/\n    for(x = 0; x != diff; ++x) setBitOfReversedStream(&obp, out, 0);\n  }\n}\n\n/*\nin: non-interlaced image with size w*h\nout: the same pixels, but re-ordered according to PNG's Adam7 interlacing, with\n no padding bits between scanlines, but between reduced images so that each\n reduced image starts at a byte.\nbpp: bits per pixel\nthere are no padding bits, not between scanlines, not between reduced images\nin has the following size in bits: w * h * bpp.\nout is possibly bigger due to padding bits between reduced images\nNOTE: comments about padding bits are only relevant if bpp < 8\n*/\nstatic void Adam7_interlace(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp)\n{\n  unsigned passw[7], passh[7];\n  size_t filter_passstart[8], padded_passstart[8], passstart[8];\n  unsigned i;\n\n  Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp);\n\n  if(bpp >= 8)\n  {\n    for(i = 0; i != 7; ++i)\n    {\n      unsigned x, y, b;\n      size_t bytewidth = bpp / 8;\n      for(y = 0; y < passh[i]; ++y)\n      for(x = 0; x < passw[i]; ++x)\n      {\n        size_t pixelinstart = ((ADAM7_IY[i] + y * ADAM7_DY[i]) * w + ADAM7_IX[i] + x * ADAM7_DX[i]) * bytewidth;\n        size_t pixeloutstart = passstart[i] + (y * passw[i] + x) * bytewidth;\n        for(b = 0; b < bytewidth; ++b)\n        {\n          out[pixeloutstart + b] = in[pixelinstart + b];\n        }\n      }\n    }\n  }\n  else /*bpp < 8: Adam7 with pixels < 8 bit is a bit trickier: with bit pointers*/\n  {\n    for(i = 0; i != 7; ++i)\n    {\n      unsigned x, y, b;\n      unsigned ilinebits = bpp * passw[i];\n      unsigned olinebits = bpp * w;\n      size_t obp, ibp; /*bit pointers (for out and in buffer)*/\n      for(y = 0; y < passh[i]; ++y)\n      for(x = 0; x < passw[i]; ++x)\n      {\n        ibp = (ADAM7_IY[i] + y * ADAM7_DY[i]) * olinebits + (ADAM7_IX[i] + x * ADAM7_DX[i]) * bpp;\n        obp = (8 * passstart[i]) + (y * ilinebits + x * bpp);\n        for(b = 0; b < bpp; ++b)\n        {\n          unsigned char bit = readBitFromReversedStream(&ibp, in);\n          setBitOfReversedStream(&obp, out, bit);\n        }\n      }\n    }\n  }\n}\n\n/*out must be buffer big enough to contain uncompressed IDAT chunk data, and in must contain the full image.\nreturn value is error**/\nstatic unsigned preProcessScanlines(unsigned char** out, size_t* outsize, const unsigned char* in,\n                                    unsigned w, unsigned h,\n                                    const LodePNGInfo* info_png, const LodePNGEncoderSettings* settings)\n{\n  /*\n  This function converts the pure 2D image with the PNG's colortype, into filtered-padded-interlaced data. Steps:\n  *) if no Adam7: 1) add padding bits (= posible extra bits per scanline if bpp < 8) 2) filter\n  *) if adam7: 1) Adam7_interlace 2) 7x add padding bits 3) 7x filter\n  */\n  unsigned bpp = lodepng_get_bpp(&info_png->color);\n  unsigned error = 0;\n\n  if(info_png->interlace_method == 0)\n  {\n    *outsize = h + (h * ((w * bpp + 7) / 8)); /*image size plus an extra byte per scanline + possible padding bits*/\n    *out = (unsigned char*)lodepng_malloc(*outsize);\n    if(!(*out) && (*outsize)) error = 83; /*alloc fail*/\n\n    if(!error)\n    {\n      /*non multiple of 8 bits per scanline, padding bits needed per scanline*/\n      if(bpp < 8 && w * bpp != ((w * bpp + 7) / 8) * 8)\n      {\n        unsigned char* padded = (unsigned char*)lodepng_malloc(h * ((w * bpp + 7) / 8));\n        if(!padded) error = 83; /*alloc fail*/\n        if(!error)\n        {\n          addPaddingBits(padded, in, ((w * bpp + 7) / 8) * 8, w * bpp, h);\n          error = filter(*out, padded, w, h, &info_png->color, settings);\n        }\n        lodepng_free(padded);\n      }\n      else\n      {\n        /*we can immediately filter into the out buffer, no other steps needed*/\n        error = filter(*out, in, w, h, &info_png->color, settings);\n      }\n    }\n  }\n  else /*interlace_method is 1 (Adam7)*/\n  {\n    unsigned passw[7], passh[7];\n    size_t filter_passstart[8], padded_passstart[8], passstart[8];\n    unsigned char* adam7;\n\n    Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp);\n\n    *outsize = filter_passstart[7]; /*image size plus an extra byte per scanline + possible padding bits*/\n    *out = (unsigned char*)lodepng_malloc(*outsize);\n    if(!(*out)) error = 83; /*alloc fail*/\n\n    adam7 = (unsigned char*)lodepng_malloc(passstart[7]);\n    if(!adam7 && passstart[7]) error = 83; /*alloc fail*/\n\n    if(!error)\n    {\n      unsigned i;\n\n      Adam7_interlace(adam7, in, w, h, bpp);\n      for(i = 0; i != 7; ++i)\n      {\n        if(bpp < 8)\n        {\n          unsigned char* padded = (unsigned char*)lodepng_malloc(padded_passstart[i + 1] - padded_passstart[i]);\n          if(!padded) ERROR_BREAK(83); /*alloc fail*/\n          addPaddingBits(padded, &adam7[passstart[i]],\n                         ((passw[i] * bpp + 7) / 8) * 8, passw[i] * bpp, passh[i]);\n          error = filter(&(*out)[filter_passstart[i]], padded,\n                         passw[i], passh[i], &info_png->color, settings);\n          lodepng_free(padded);\n        }\n        else\n        {\n          error = filter(&(*out)[filter_passstart[i]], &adam7[padded_passstart[i]],\n                         passw[i], passh[i], &info_png->color, settings);\n        }\n\n        if(error) break;\n      }\n    }\n\n    lodepng_free(adam7);\n  }\n\n  return error;\n}\n\n/*\npalette must have 4 * palettesize bytes allocated, and given in format RGBARGBARGBARGBA...\nreturns 0 if the palette is opaque,\nreturns 1 if the palette has a single color with alpha 0 ==> color key\nreturns 2 if the palette is semi-translucent.\n*/\nstatic unsigned getPaletteTranslucency(const unsigned char* palette, size_t palettesize)\n{\n  size_t i;\n  unsigned key = 0;\n  unsigned r = 0, g = 0, b = 0; /*the value of the color with alpha 0, so long as color keying is possible*/\n  for(i = 0; i != palettesize; ++i)\n  {\n    if(!key && palette[4 * i + 3] == 0)\n    {\n      r = palette[4 * i + 0]; g = palette[4 * i + 1]; b = palette[4 * i + 2];\n      key = 1;\n      i = (size_t)(-1); /*restart from beginning, to detect earlier opaque colors with key's value*/\n    }\n    else if(palette[4 * i + 3] != 255) return 2;\n    /*when key, no opaque RGB may have key's RGB*/\n    else if(key && r == palette[i * 4 + 0] && g == palette[i * 4 + 1] && b == palette[i * 4 + 2]) return 2;\n  }\n  return key;\n}\n\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\nstatic unsigned addUnknownChunks(ucvector* out, unsigned char* data, size_t datasize)\n{\n  unsigned char* inchunk = data;\n  while((size_t)(inchunk - data) < datasize)\n  {\n    CERROR_TRY_RETURN(lodepng_chunk_append(&out->data, &out->size, inchunk));\n    out->allocsize = out->size; /*fix the allocsize again*/\n    inchunk = lodepng_chunk_next(inchunk);\n  }\n  return 0;\n}\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n\nunsigned lodepng_encode(unsigned char** out, size_t* outsize,\n                        const unsigned char* image, unsigned w, unsigned h,\n                        LodePNGState* state)\n{\n  LodePNGInfo info;\n  ucvector outv;\n  unsigned char* data = 0; /*uncompressed version of the IDAT chunk data*/\n  size_t datasize = 0;\n\n  /*provide some proper output values if error will happen*/\n  *out = 0;\n  *outsize = 0;\n  state->error = 0;\n\n  /*check input values validity*/\n  if((state->info_png.color.colortype == LCT_PALETTE || state->encoder.force_palette)\n      && (state->info_png.color.palettesize == 0 || state->info_png.color.palettesize > 256))\n  {\n    CERROR_RETURN_ERROR(state->error, 68); /*invalid palette size, it is only allowed to be 1-256*/\n  }\n  if(state->encoder.zlibsettings.btype > 2)\n  {\n    CERROR_RETURN_ERROR(state->error, 61); /*error: unexisting btype*/\n  }\n  if(state->info_png.interlace_method > 1)\n  {\n    CERROR_RETURN_ERROR(state->error, 71); /*error: unexisting interlace mode*/\n  }\n  state->error = checkColorValidity(state->info_png.color.colortype, state->info_png.color.bitdepth);\n  if(state->error) return state->error; /*error: unexisting color type given*/\n  state->error = checkColorValidity(state->info_raw.colortype, state->info_raw.bitdepth);\n  if(state->error) return state->error; /*error: unexisting color type given*/\n\n  /* color convert and compute scanline filter types */\n  lodepng_info_init(&info);\n  lodepng_info_copy(&info, &state->info_png);\n  if(state->encoder.auto_convert)\n  {\n    state->error = lodepng_auto_choose_color(&info.color, image, w, h, &state->info_raw);\n  }\n  if (!state->error)\n  {\n    if(!lodepng_color_mode_equal(&state->info_raw, &info.color))\n    {\n      unsigned char* converted;\n      size_t size = (w * h * (size_t)lodepng_get_bpp(&info.color) + 7) / 8;\n\n      converted = (unsigned char*)lodepng_malloc(size);\n      if(!converted && size) state->error = 83; /*alloc fail*/\n      if(!state->error)\n      {\n        state->error = lodepng_convert(converted, image, &info.color, &state->info_raw, w, h);\n      }\n      if(!state->error) preProcessScanlines(&data, &datasize, converted, w, h, &info, &state->encoder);\n      lodepng_free(converted);\n    }\n    else preProcessScanlines(&data, &datasize, image, w, h, &info, &state->encoder);\n  }\n\n  /* output all PNG chunks */\n  ucvector_init(&outv);\n  while(!state->error) /*while only executed once, to break on error*/\n  {\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\n    size_t i;\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n    /*write signature and chunks*/\n    writeSignature(&outv);\n    /*IHDR*/\n    addChunk_IHDR(&outv, w, h, info.color.colortype, info.color.bitdepth, info.interlace_method);\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\n    /*unknown chunks between IHDR and PLTE*/\n    if(info.unknown_chunks_data[0])\n    {\n      state->error = addUnknownChunks(&outv, info.unknown_chunks_data[0], info.unknown_chunks_size[0]);\n      if(state->error) break;\n    }\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n    /*PLTE*/\n    if(info.color.colortype == LCT_PALETTE)\n    {\n      addChunk_PLTE(&outv, &info.color);\n    }\n    if(state->encoder.force_palette && (info.color.colortype == LCT_RGB || info.color.colortype == LCT_RGBA))\n    {\n      addChunk_PLTE(&outv, &info.color);\n    }\n    /*tRNS*/\n    if(info.color.colortype == LCT_PALETTE && getPaletteTranslucency(info.color.palette, info.color.palettesize) != 0)\n    {\n      addChunk_tRNS(&outv, &info.color);\n    }\n    if((info.color.colortype == LCT_GREY || info.color.colortype == LCT_RGB) && info.color.key_defined)\n    {\n      addChunk_tRNS(&outv, &info.color);\n    }\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\n    /*bKGD (must come between PLTE and the IDAt chunks*/\n    if(info.background_defined) addChunk_bKGD(&outv, &info);\n    /*pHYs (must come before the IDAT chunks)*/\n    if(info.phys_defined) addChunk_pHYs(&outv, &info);\n\n    /*unknown chunks between PLTE and IDAT*/\n    if(info.unknown_chunks_data[1])\n    {\n      state->error = addUnknownChunks(&outv, info.unknown_chunks_data[1], info.unknown_chunks_size[1]);\n      if(state->error) break;\n    }\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n    /*IDAT (multiple IDAT chunks must be consecutive)*/\n    state->error = addChunk_IDAT(&outv, data, datasize, &state->encoder.zlibsettings);\n    if(state->error) break;\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\n    /*tIME*/\n    if(info.time_defined) addChunk_tIME(&outv, &info.time);\n    /*tEXt and/or zTXt*/\n    for(i = 0; i != info.text_num; ++i)\n    {\n      if(strlen(info.text_keys[i]) > 79)\n      {\n        state->error = 66; /*text chunk too large*/\n        break;\n      }\n      if(strlen(info.text_keys[i]) < 1)\n      {\n        state->error = 67; /*text chunk too small*/\n        break;\n      }\n      if(state->encoder.text_compression)\n      {\n        addChunk_zTXt(&outv, info.text_keys[i], info.text_strings[i], &state->encoder.zlibsettings);\n      }\n      else\n      {\n        addChunk_tEXt(&outv, info.text_keys[i], info.text_strings[i]);\n      }\n    }\n    /*LodePNG version id in text chunk*/\n    if(state->encoder.add_id)\n    {\n      unsigned alread_added_id_text = 0;\n      for(i = 0; i != info.text_num; ++i)\n      {\n        if(!strcmp(info.text_keys[i], \"LodePNG\"))\n        {\n          alread_added_id_text = 1;\n          break;\n        }\n      }\n      if(alread_added_id_text == 0)\n      {\n        addChunk_tEXt(&outv, \"LodePNG\", LODEPNG_VERSION_STRING); /*it's shorter as tEXt than as zTXt chunk*/\n      }\n    }\n    /*iTXt*/\n    for(i = 0; i != info.itext_num; ++i)\n    {\n      if(strlen(info.itext_keys[i]) > 79)\n      {\n        state->error = 66; /*text chunk too large*/\n        break;\n      }\n      if(strlen(info.itext_keys[i]) < 1)\n      {\n        state->error = 67; /*text chunk too small*/\n        break;\n      }\n      addChunk_iTXt(&outv, state->encoder.text_compression,\n                    info.itext_keys[i], info.itext_langtags[i], info.itext_transkeys[i], info.itext_strings[i],\n                    &state->encoder.zlibsettings);\n    }\n\n    /*unknown chunks between IDAT and IEND*/\n    if(info.unknown_chunks_data[2])\n    {\n      state->error = addUnknownChunks(&outv, info.unknown_chunks_data[2], info.unknown_chunks_size[2]);\n      if(state->error) break;\n    }\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n    addChunk_IEND(&outv);\n\n    break; /*this isn't really a while loop; no error happened so break out now!*/\n  }\n\n  lodepng_info_cleanup(&info);\n  lodepng_free(data);\n  /*instead of cleaning the vector up, give it to the output*/\n  *out = outv.data;\n  *outsize = outv.size;\n\n  return state->error;\n}\n\nunsigned lodepng_encode_memory(unsigned char** out, size_t* outsize, const unsigned char* image,\n                               unsigned w, unsigned h, LodePNGColorType colortype, unsigned bitdepth)\n{\n  unsigned error;\n  LodePNGState state;\n  lodepng_state_init(&state);\n  state.info_raw.colortype = colortype;\n  state.info_raw.bitdepth = bitdepth;\n  state.info_png.color.colortype = colortype;\n  state.info_png.color.bitdepth = bitdepth;\n  lodepng_encode(out, outsize, image, w, h, &state);\n  error = state.error;\n  lodepng_state_cleanup(&state);\n  return error;\n}\n\nunsigned lodepng_encode32(unsigned char** out, size_t* outsize, const unsigned char* image, unsigned w, unsigned h)\n{\n  return lodepng_encode_memory(out, outsize, image, w, h, LCT_RGBA, 8);\n}\n\nunsigned lodepng_encode24(unsigned char** out, size_t* outsize, const unsigned char* image, unsigned w, unsigned h)\n{\n  return lodepng_encode_memory(out, outsize, image, w, h, LCT_RGB, 8);\n}\n\n#ifdef LODEPNG_COMPILE_DISK\nunsigned lodepng_encode_file(const char* filename, const unsigned char* image, unsigned w, unsigned h,\n                             LodePNGColorType colortype, unsigned bitdepth)\n{\n  unsigned char* buffer;\n  size_t buffersize;\n  unsigned error = lodepng_encode_memory(&buffer, &buffersize, image, w, h, colortype, bitdepth);\n  if(!error) error = lodepng_save_file(buffer, buffersize, filename);\n  lodepng_free(buffer);\n  return error;\n}\n\nunsigned lodepng_encode32_file(const char* filename, const unsigned char* image, unsigned w, unsigned h)\n{\n  return lodepng_encode_file(filename, image, w, h, LCT_RGBA, 8);\n}\n\nunsigned lodepng_encode24_file(const char* filename, const unsigned char* image, unsigned w, unsigned h)\n{\n  return lodepng_encode_file(filename, image, w, h, LCT_RGB, 8);\n}\n#endif /*LODEPNG_COMPILE_DISK*/\n\nvoid lodepng_encoder_settings_init(LodePNGEncoderSettings* settings)\n{\n  lodepng_compress_settings_init(&settings->zlibsettings);\n  settings->filter_palette_zero = 1;\n  settings->filter_strategy = LFS_MINSUM;\n  settings->auto_convert = 1;\n  settings->force_palette = 0;\n  settings->predefined_filters = 0;\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\n  settings->add_id = 0;\n  settings->text_compression = 1;\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n}\n\n#endif /*LODEPNG_COMPILE_ENCODER*/\n#endif /*LODEPNG_COMPILE_PNG*/\n\n#ifdef LODEPNG_COMPILE_ERROR_TEXT\n/*\nThis returns the description of a numerical error code in English. This is also\nthe documentation of all the error codes.\n*/\nconst char* lodepng_error_text(unsigned code)\n{\n  switch(code)\n  {\n    case 0: return \"no error, everything went ok\";\n    case 1: return \"nothing done yet\"; /*the Encoder/Decoder has done nothing yet, error checking makes no sense yet*/\n    case 10: return \"end of input memory reached without huffman end code\"; /*while huffman decoding*/\n    case 11: return \"error in code tree made it jump outside of huffman tree\"; /*while huffman decoding*/\n    case 13: return \"problem while processing dynamic deflate block\";\n    case 14: return \"problem while processing dynamic deflate block\";\n    case 15: return \"problem while processing dynamic deflate block\";\n    case 16: return \"unexisting code while processing dynamic deflate block\";\n    case 17: return \"end of out buffer memory reached while inflating\";\n    case 18: return \"invalid distance code while inflating\";\n    case 19: return \"end of out buffer memory reached while inflating\";\n    case 20: return \"invalid deflate block BTYPE encountered while decoding\";\n    case 21: return \"NLEN is not ones complement of LEN in a deflate block\";\n     /*end of out buffer memory reached while inflating:\n     This can happen if the inflated deflate data is longer than the amount of bytes required to fill up\n     all the pixels of the image, given the color depth and image dimensions. Something that doesn't\n     happen in a normal, well encoded, PNG image.*/\n    case 22: return \"end of out buffer memory reached while inflating\";\n    case 23: return \"end of in buffer memory reached while inflating\";\n    case 24: return \"invalid FCHECK in zlib header\";\n    case 25: return \"invalid compression method in zlib header\";\n    case 26: return \"FDICT encountered in zlib header while it's not used for PNG\";\n    case 27: return \"PNG file is smaller than a PNG header\";\n    /*Checks the magic file header, the first 8 bytes of the PNG file*/\n    case 28: return \"incorrect PNG signature, it's no PNG or corrupted\";\n    case 29: return \"first chunk is not the header chunk\";\n    case 30: return \"chunk length too large, chunk broken off at end of file\";\n    case 31: return \"illegal PNG color type or bpp\";\n    case 32: return \"illegal PNG compression method\";\n    case 33: return \"illegal PNG filter method\";\n    case 34: return \"illegal PNG interlace method\";\n    case 35: return \"chunk length of a chunk is too large or the chunk too small\";\n    case 36: return \"illegal PNG filter type encountered\";\n    case 37: return \"illegal bit depth for this color type given\";\n    case 38: return \"the palette is too big\"; /*more than 256 colors*/\n    case 39: return \"more palette alpha values given in tRNS chunk than there are colors in the palette\";\n    case 40: return \"tRNS chunk has wrong size for greyscale image\";\n    case 41: return \"tRNS chunk has wrong size for RGB image\";\n    case 42: return \"tRNS chunk appeared while it was not allowed for this color type\";\n    case 43: return \"bKGD chunk has wrong size for palette image\";\n    case 44: return \"bKGD chunk has wrong size for greyscale image\";\n    case 45: return \"bKGD chunk has wrong size for RGB image\";\n    case 48: return \"empty input buffer given to decoder. Maybe caused by non-existing file?\";\n    case 49: return \"jumped past memory while generating dynamic huffman tree\";\n    case 50: return \"jumped past memory while generating dynamic huffman tree\";\n    case 51: return \"jumped past memory while inflating huffman block\";\n    case 52: return \"jumped past memory while inflating\";\n    case 53: return \"size of zlib data too small\";\n    case 54: return \"repeat symbol in tree while there was no value symbol yet\";\n    /*jumped past tree while generating huffman tree, this could be when the\n    tree will have more leaves than symbols after generating it out of the\n    given lenghts. They call this an oversubscribed dynamic bit lengths tree in zlib.*/\n    case 55: return \"jumped past tree while generating huffman tree\";\n    case 56: return \"given output image colortype or bitdepth not supported for color conversion\";\n    case 57: return \"invalid CRC encountered (checking CRC can be disabled)\";\n    case 58: return \"invalid ADLER32 encountered (checking ADLER32 can be disabled)\";\n    case 59: return \"requested color conversion not supported\";\n    case 60: return \"invalid window size given in the settings of the encoder (must be 0-32768)\";\n    case 61: return \"invalid BTYPE given in the settings of the encoder (only 0, 1 and 2 are allowed)\";\n    /*LodePNG leaves the choice of RGB to greyscale conversion formula to the user.*/\n    case 62: return \"conversion from color to greyscale not supported\";\n    case 63: return \"length of a chunk too long, max allowed for PNG is 2147483647 bytes per chunk\"; /*(2^31-1)*/\n    /*this would result in the inability of a deflated block to ever contain an end code. It must be at least 1.*/\n    case 64: return \"the length of the END symbol 256 in the Huffman tree is 0\";\n    case 66: return \"the length of a text chunk keyword given to the encoder is longer than the maximum of 79 bytes\";\n    case 67: return \"the length of a text chunk keyword given to the encoder is smaller than the minimum of 1 byte\";\n    case 68: return \"tried to encode a PLTE chunk with a palette that has less than 1 or more than 256 colors\";\n    case 69: return \"unknown chunk type with 'critical' flag encountered by the decoder\";\n    case 71: return \"unexisting interlace mode given to encoder (must be 0 or 1)\";\n    case 72: return \"while decoding, unexisting compression method encountering in zTXt or iTXt chunk (it must be 0)\";\n    case 73: return \"invalid tIME chunk size\";\n    case 74: return \"invalid pHYs chunk size\";\n    /*length could be wrong, or data chopped off*/\n    case 75: return \"no null termination char found while decoding text chunk\";\n    case 76: return \"iTXt chunk too short to contain required bytes\";\n    case 77: return \"integer overflow in buffer size\";\n    case 78: return \"failed to open file for reading\"; /*file doesn't exist or couldn't be opened for reading*/\n    case 79: return \"failed to open file for writing\";\n    case 80: return \"tried creating a tree of 0 symbols\";\n    case 81: return \"lazy matching at pos 0 is impossible\";\n    case 82: return \"color conversion to palette requested while a color isn't in palette\";\n    case 83: return \"memory allocation failed\";\n    case 84: return \"given image too small to contain all pixels to be encoded\";\n    case 86: return \"impossible offset in lz77 encoding (internal bug)\";\n    case 87: return \"must provide custom zlib function pointer if LODEPNG_COMPILE_ZLIB is not defined\";\n    case 88: return \"invalid filter strategy given for LodePNGEncoderSettings.filter_strategy\";\n    case 89: return \"text chunk keyword too short or long: must have size 1-79\";\n    /*the windowsize in the LodePNGCompressSettings. Requiring POT(==> & instead of %) makes encoding 12% faster.*/\n    case 90: return \"windowsize must be a power of two\";\n    case 91: return \"invalid decompressed idat size\";\n    case 92: return \"too many pixels, not supported\";\n    case 93: return \"zero width or height is invalid\";\n    case 94: return \"header chunk must have a size of 13 bytes\";\n  }\n  return \"unknown error code\";\n}\n#endif /*LODEPNG_COMPILE_ERROR_TEXT*/\n\n/* ////////////////////////////////////////////////////////////////////////// */\n/* ////////////////////////////////////////////////////////////////////////// */\n/* // C++ Wrapper                                                          // */\n/* ////////////////////////////////////////////////////////////////////////// */\n/* ////////////////////////////////////////////////////////////////////////// */\n\n#ifdef LODEPNG_COMPILE_CPP\nnamespace lodepng\n{\n\n#ifdef LODEPNG_COMPILE_DISK\nunsigned load_file(std::vector<unsigned char>& buffer, const std::string& filename)\n{\n  long size = lodepng_filesize(filename.c_str());\n  if(size < 0) return 78;\n  buffer.resize((size_t)size);\n  return size == 0 ? 0 : lodepng_buffer_file(&buffer[0], (size_t)size, filename.c_str());\n}\n\n/*write given buffer to the file, overwriting the file, it doesn't append to it.*/\nunsigned save_file(const std::vector<unsigned char>& buffer, const std::string& filename)\n{\n  return lodepng_save_file(buffer.empty() ? 0 : &buffer[0], buffer.size(), filename.c_str());\n}\n#endif /* LODEPNG_COMPILE_DISK */\n\n#ifdef LODEPNG_COMPILE_ZLIB\n#ifdef LODEPNG_COMPILE_DECODER\nunsigned decompress(std::vector<unsigned char>& out, const unsigned char* in, size_t insize,\n                    const LodePNGDecompressSettings& settings)\n{\n  unsigned char* buffer = 0;\n  size_t buffersize = 0;\n  unsigned error = zlib_decompress(&buffer, &buffersize, in, insize, &settings);\n  if(buffer)\n  {\n    out.insert(out.end(), &buffer[0], &buffer[buffersize]);\n    lodepng_free(buffer);\n  }\n  return error;\n}\n\nunsigned decompress(std::vector<unsigned char>& out, const std::vector<unsigned char>& in,\n                    const LodePNGDecompressSettings& settings)\n{\n  return decompress(out, in.empty() ? 0 : &in[0], in.size(), settings);\n}\n#endif /* LODEPNG_COMPILE_DECODER */\n\n#ifdef LODEPNG_COMPILE_ENCODER\nunsigned compress(std::vector<unsigned char>& out, const unsigned char* in, size_t insize,\n                  const LodePNGCompressSettings& settings)\n{\n  unsigned char* buffer = 0;\n  size_t buffersize = 0;\n  unsigned error = zlib_compress(&buffer, &buffersize, in, insize, &settings);\n  if(buffer)\n  {\n    out.insert(out.end(), &buffer[0], &buffer[buffersize]);\n    lodepng_free(buffer);\n  }\n  return error;\n}\n\nunsigned compress(std::vector<unsigned char>& out, const std::vector<unsigned char>& in,\n                  const LodePNGCompressSettings& settings)\n{\n  return compress(out, in.empty() ? 0 : &in[0], in.size(), settings);\n}\n#endif /* LODEPNG_COMPILE_ENCODER */\n#endif /* LODEPNG_COMPILE_ZLIB */\n\n\n#ifdef LODEPNG_COMPILE_PNG\n\nState::State()\n{\n  lodepng_state_init(this);\n}\n\nState::State(const State& other)\n{\n  lodepng_state_init(this);\n  lodepng_state_copy(this, &other);\n}\n\nState::~State()\n{\n  lodepng_state_cleanup(this);\n}\n\nState& State::operator=(const State& other)\n{\n  lodepng_state_copy(this, &other);\n  return *this;\n}\n\n#ifdef LODEPNG_COMPILE_DECODER\n\nunsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h, const unsigned char* in,\n                size_t insize, LodePNGColorType colortype, unsigned bitdepth)\n{\n  unsigned char* buffer;\n  unsigned error = lodepng_decode_memory(&buffer, &w, &h, in, insize, colortype, bitdepth);\n  if(buffer && !error)\n  {\n    State state;\n    state.info_raw.colortype = colortype;\n    state.info_raw.bitdepth = bitdepth;\n    size_t buffersize = lodepng_get_raw_size(w, h, &state.info_raw);\n    out.insert(out.end(), &buffer[0], &buffer[buffersize]);\n    lodepng_free(buffer);\n  }\n  return error;\n}\n\nunsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,\n                const std::vector<unsigned char>& in, LodePNGColorType colortype, unsigned bitdepth)\n{\n  return decode(out, w, h, in.empty() ? 0 : &in[0], (unsigned)in.size(), colortype, bitdepth);\n}\n\nunsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,\n                State& state,\n                const unsigned char* in, size_t insize)\n{\n  unsigned char* buffer = NULL;\n  unsigned error = lodepng_decode(&buffer, &w, &h, &state, in, insize);\n  if(buffer && !error)\n  {\n    size_t buffersize = lodepng_get_raw_size(w, h, &state.info_raw);\n    out.insert(out.end(), &buffer[0], &buffer[buffersize]);\n  }\n  lodepng_free(buffer);\n  return error;\n}\n\nunsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,\n                State& state,\n                const std::vector<unsigned char>& in)\n{\n  return decode(out, w, h, state, in.empty() ? 0 : &in[0], in.size());\n}\n\n#ifdef LODEPNG_COMPILE_DISK\nunsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h, const std::string& filename,\n                LodePNGColorType colortype, unsigned bitdepth)\n{\n  std::vector<unsigned char> buffer;\n  unsigned error = load_file(buffer, filename);\n  if(error) return error;\n  return decode(out, w, h, buffer, colortype, bitdepth);\n}\n#endif /* LODEPNG_COMPILE_DECODER */\n#endif /* LODEPNG_COMPILE_DISK */\n\n#ifdef LODEPNG_COMPILE_ENCODER\nunsigned encode(std::vector<unsigned char>& out, const unsigned char* in, unsigned w, unsigned h,\n                LodePNGColorType colortype, unsigned bitdepth)\n{\n  unsigned char* buffer;\n  size_t buffersize;\n  unsigned error = lodepng_encode_memory(&buffer, &buffersize, in, w, h, colortype, bitdepth);\n  if(buffer)\n  {\n    out.insert(out.end(), &buffer[0], &buffer[buffersize]);\n    lodepng_free(buffer);\n  }\n  return error;\n}\n\nunsigned encode(std::vector<unsigned char>& out,\n                const std::vector<unsigned char>& in, unsigned w, unsigned h,\n                LodePNGColorType colortype, unsigned bitdepth)\n{\n  if(lodepng_get_raw_size_lct(w, h, colortype, bitdepth) > in.size()) return 84;\n  return encode(out, in.empty() ? 0 : &in[0], w, h, colortype, bitdepth);\n}\n\nunsigned encode(std::vector<unsigned char>& out,\n                const unsigned char* in, unsigned w, unsigned h,\n                State& state)\n{\n  unsigned char* buffer;\n  size_t buffersize;\n  unsigned error = lodepng_encode(&buffer, &buffersize, in, w, h, &state);\n  if(buffer)\n  {\n    out.insert(out.end(), &buffer[0], &buffer[buffersize]);\n    lodepng_free(buffer);\n  }\n  return error;\n}\n\nunsigned encode(std::vector<unsigned char>& out,\n                const std::vector<unsigned char>& in, unsigned w, unsigned h,\n                State& state)\n{\n  if(lodepng_get_raw_size(w, h, &state.info_raw) > in.size()) return 84;\n  return encode(out, in.empty() ? 0 : &in[0], w, h, state);\n}\n\n#ifdef LODEPNG_COMPILE_DISK\nunsigned encode(const std::string& filename,\n                const unsigned char* in, unsigned w, unsigned h,\n                LodePNGColorType colortype, unsigned bitdepth)\n{\n  std::vector<unsigned char> buffer;\n  unsigned error = encode(buffer, in, w, h, colortype, bitdepth);\n  if(!error) error = save_file(buffer, filename);\n  return error;\n}\n\nunsigned encode(const std::string& filename,\n                const std::vector<unsigned char>& in, unsigned w, unsigned h,\n                LodePNGColorType colortype, unsigned bitdepth)\n{\n  if(lodepng_get_raw_size_lct(w, h, colortype, bitdepth) > in.size()) return 84;\n  return encode(filename, in.empty() ? 0 : &in[0], w, h, colortype, bitdepth);\n}\n#endif /* LODEPNG_COMPILE_DISK */\n#endif /* LODEPNG_COMPILE_ENCODER */\n#endif /* LODEPNG_COMPILE_PNG */\n} /* namespace lodepng */\n#endif /*LODEPNG_COMPILE_CPP*/\n"
  },
  {
    "path": "src/lodepng.h",
    "content": "/*\nLodePNG version 20180114\n\nCopyright (c) 2005-2018 Lode Vandevenne\n\nThis software is provided 'as-is', without any express or implied\nwarranty. In no event will the authors be held liable for any damages\narising from the use of this software.\n\nPermission is granted to anyone to use this software for any purpose,\nincluding commercial applications, and to alter it and redistribute it\nfreely, subject to the following restrictions:\n\n    1. The origin of this software must not be misrepresented; you must not\n    claim that you wrote the original software. If you use this software\n    in a product, an acknowledgment in the product documentation would be\n    appreciated but is not required.\n\n    2. Altered source versions must be plainly marked as such, and must not be\n    misrepresented as being the original software.\n\n    3. This notice may not be removed or altered from any source\n    distribution.\n*/\n\n#ifndef LODEPNG_H\n#define LODEPNG_H\n\n#include <string.h> /*for size_t*/\n\nextern const char* LODEPNG_VERSION_STRING;\n\n/*\nThe following #defines are used to create code sections. They can be disabled\nto disable code sections, which can give faster compile time and smaller binary.\nThe \"NO_COMPILE\" defines are designed to be used to pass as defines to the\ncompiler command to disable them without modifying this header, e.g.\n-DLODEPNG_NO_COMPILE_ZLIB for gcc.\nIn addition to those below, you can also define LODEPNG_NO_COMPILE_CRC to\nallow implementing a custom lodepng_crc32.\n*/\n/*deflate & zlib. If disabled, you must specify alternative zlib functions in\nthe custom_zlib field of the compress and decompress settings*/\n#ifndef LODEPNG_NO_COMPILE_ZLIB\n#define LODEPNG_COMPILE_ZLIB\n#endif\n/*png encoder and png decoder*/\n#ifndef LODEPNG_NO_COMPILE_PNG\n#define LODEPNG_COMPILE_PNG\n#endif\n/*deflate&zlib decoder and png decoder*/\n#ifndef LODEPNG_NO_COMPILE_DECODER\n#define LODEPNG_COMPILE_DECODER\n#endif\n/*deflate&zlib encoder and png encoder*/\n#ifndef LODEPNG_NO_COMPILE_ENCODER\n#define LODEPNG_COMPILE_ENCODER\n#endif\n/*the optional built in harddisk file loading and saving functions*/\n#ifndef LODEPNG_NO_COMPILE_DISK\n#define LODEPNG_COMPILE_DISK\n#endif\n/*support for chunks other than IHDR, IDAT, PLTE, tRNS, IEND: ancillary and unknown chunks*/\n#ifndef LODEPNG_NO_COMPILE_ANCILLARY_CHUNKS\n#define LODEPNG_COMPILE_ANCILLARY_CHUNKS\n#endif\n/*ability to convert error numerical codes to English text string*/\n#ifndef LODEPNG_NO_COMPILE_ERROR_TEXT\n#define LODEPNG_COMPILE_ERROR_TEXT\n#endif\n/*Compile the default allocators (C's free, malloc and realloc). If you disable this,\nyou can define the functions lodepng_free, lodepng_malloc and lodepng_realloc in your\nsource files with custom allocators.*/\n#ifndef LODEPNG_NO_COMPILE_ALLOCATORS\n#define LODEPNG_COMPILE_ALLOCATORS\n#endif\n/*compile the C++ version (you can disable the C++ wrapper here even when compiling for C++)*/\n#ifdef __cplusplus\n#ifndef LODEPNG_NO_COMPILE_CPP\n#define LODEPNG_COMPILE_CPP\n#endif\n#endif\n\n#ifdef LODEPNG_COMPILE_CPP\n#include <vector>\n#include <string>\n#endif /*LODEPNG_COMPILE_CPP*/\n\n#ifdef LODEPNG_COMPILE_PNG\n/*The PNG color types (also used for raw).*/\ntypedef enum LodePNGColorType\n{\n  LCT_GREY = 0, /*greyscale: 1,2,4,8,16 bit*/\n  LCT_RGB = 2, /*RGB: 8,16 bit*/\n  LCT_PALETTE = 3, /*palette: 1,2,4,8 bit*/\n  LCT_GREY_ALPHA = 4, /*greyscale with alpha: 8,16 bit*/\n  LCT_RGBA = 6 /*RGB with alpha: 8,16 bit*/\n} LodePNGColorType;\n\n#ifdef LODEPNG_COMPILE_DECODER\n/*\nConverts PNG data in memory to raw pixel data.\nout: Output parameter. Pointer to buffer that will contain the raw pixel data.\n     After decoding, its size is w * h * (bytes per pixel) bytes larger than\n     initially. Bytes per pixel depends on colortype and bitdepth.\n     Must be freed after usage with free(*out).\n     Note: for 16-bit per channel colors, uses big endian format like PNG does.\nw: Output parameter. Pointer to width of pixel data.\nh: Output parameter. Pointer to height of pixel data.\nin: Memory buffer with the PNG file.\ninsize: size of the in buffer.\ncolortype: the desired color type for the raw output image. See explanation on PNG color types.\nbitdepth: the desired bit depth for the raw output image. See explanation on PNG color types.\nReturn value: LodePNG error code (0 means no error).\n*/\nunsigned lodepng_decode_memory(unsigned char** out, unsigned* w, unsigned* h,\n                               const unsigned char* in, size_t insize,\n                               LodePNGColorType colortype, unsigned bitdepth);\n\n/*Same as lodepng_decode_memory, but always decodes to 32-bit RGBA raw image*/\nunsigned lodepng_decode32(unsigned char** out, unsigned* w, unsigned* h,\n                          const unsigned char* in, size_t insize);\n\n/*Same as lodepng_decode_memory, but always decodes to 24-bit RGB raw image*/\nunsigned lodepng_decode24(unsigned char** out, unsigned* w, unsigned* h,\n                          const unsigned char* in, size_t insize);\n\n#ifdef LODEPNG_COMPILE_DISK\n/*\nLoad PNG from disk, from file with given name.\nSame as the other decode functions, but instead takes a filename as input.\n*/\nunsigned lodepng_decode_file(unsigned char** out, unsigned* w, unsigned* h,\n                             const char* filename,\n                             LodePNGColorType colortype, unsigned bitdepth);\n\n/*Same as lodepng_decode_file, but always decodes to 32-bit RGBA raw image.*/\nunsigned lodepng_decode32_file(unsigned char** out, unsigned* w, unsigned* h,\n                               const char* filename);\n\n/*Same as lodepng_decode_file, but always decodes to 24-bit RGB raw image.*/\nunsigned lodepng_decode24_file(unsigned char** out, unsigned* w, unsigned* h,\n                               const char* filename);\n#endif /*LODEPNG_COMPILE_DISK*/\n#endif /*LODEPNG_COMPILE_DECODER*/\n\n\n#ifdef LODEPNG_COMPILE_ENCODER\n/*\nConverts raw pixel data into a PNG image in memory. The colortype and bitdepth\n  of the output PNG image cannot be chosen, they are automatically determined\n  by the colortype, bitdepth and content of the input pixel data.\n  Note: for 16-bit per channel colors, needs big endian format like PNG does.\nout: Output parameter. Pointer to buffer that will contain the PNG image data.\n     Must be freed after usage with free(*out).\noutsize: Output parameter. Pointer to the size in bytes of the out buffer.\nimage: The raw pixel data to encode. The size of this buffer should be\n       w * h * (bytes per pixel), bytes per pixel depends on colortype and bitdepth.\nw: width of the raw pixel data in pixels.\nh: height of the raw pixel data in pixels.\ncolortype: the color type of the raw input image. See explanation on PNG color types.\nbitdepth: the bit depth of the raw input image. See explanation on PNG color types.\nReturn value: LodePNG error code (0 means no error).\n*/\nunsigned lodepng_encode_memory(unsigned char** out, size_t* outsize,\n                               const unsigned char* image, unsigned w, unsigned h,\n                               LodePNGColorType colortype, unsigned bitdepth);\n\n/*Same as lodepng_encode_memory, but always encodes from 32-bit RGBA raw image.*/\nunsigned lodepng_encode32(unsigned char** out, size_t* outsize,\n                          const unsigned char* image, unsigned w, unsigned h);\n\n/*Same as lodepng_encode_memory, but always encodes from 24-bit RGB raw image.*/\nunsigned lodepng_encode24(unsigned char** out, size_t* outsize,\n                          const unsigned char* image, unsigned w, unsigned h);\n\n#ifdef LODEPNG_COMPILE_DISK\n/*\nConverts raw pixel data into a PNG file on disk.\nSame as the other encode functions, but instead takes a filename as output.\nNOTE: This overwrites existing files without warning!\n*/\nunsigned lodepng_encode_file(const char* filename,\n                             const unsigned char* image, unsigned w, unsigned h,\n                             LodePNGColorType colortype, unsigned bitdepth);\n\n/*Same as lodepng_encode_file, but always encodes from 32-bit RGBA raw image.*/\nunsigned lodepng_encode32_file(const char* filename,\n                               const unsigned char* image, unsigned w, unsigned h);\n\n/*Same as lodepng_encode_file, but always encodes from 24-bit RGB raw image.*/\nunsigned lodepng_encode24_file(const char* filename,\n                               const unsigned char* image, unsigned w, unsigned h);\n#endif /*LODEPNG_COMPILE_DISK*/\n#endif /*LODEPNG_COMPILE_ENCODER*/\n\n\n#ifdef LODEPNG_COMPILE_CPP\nnamespace lodepng\n{\n#ifdef LODEPNG_COMPILE_DECODER\n/*Same as lodepng_decode_memory, but decodes to an std::vector. The colortype\nis the format to output the pixels to. Default is RGBA 8-bit per channel.*/\nunsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,\n                const unsigned char* in, size_t insize,\n                LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8);\nunsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,\n                const std::vector<unsigned char>& in,\n                LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8);\n#ifdef LODEPNG_COMPILE_DISK\n/*\nConverts PNG file from disk to raw pixel data in memory.\nSame as the other decode functions, but instead takes a filename as input.\n*/\nunsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,\n                const std::string& filename,\n                LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8);\n#endif /* LODEPNG_COMPILE_DISK */\n#endif /* LODEPNG_COMPILE_DECODER */\n\n#ifdef LODEPNG_COMPILE_ENCODER\n/*Same as lodepng_encode_memory, but encodes to an std::vector. colortype\nis that of the raw input data. The output PNG color type will be auto chosen.*/\nunsigned encode(std::vector<unsigned char>& out,\n                const unsigned char* in, unsigned w, unsigned h,\n                LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8);\nunsigned encode(std::vector<unsigned char>& out,\n                const std::vector<unsigned char>& in, unsigned w, unsigned h,\n                LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8);\n#ifdef LODEPNG_COMPILE_DISK\n/*\nConverts 32-bit RGBA raw pixel data into a PNG file on disk.\nSame as the other encode functions, but instead takes a filename as output.\nNOTE: This overwrites existing files without warning!\n*/\nunsigned encode(const std::string& filename,\n                const unsigned char* in, unsigned w, unsigned h,\n                LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8);\nunsigned encode(const std::string& filename,\n                const std::vector<unsigned char>& in, unsigned w, unsigned h,\n                LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8);\n#endif /* LODEPNG_COMPILE_DISK */\n#endif /* LODEPNG_COMPILE_ENCODER */\n} /* namespace lodepng */\n#endif /*LODEPNG_COMPILE_CPP*/\n#endif /*LODEPNG_COMPILE_PNG*/\n\n#ifdef LODEPNG_COMPILE_ERROR_TEXT\n/*Returns an English description of the numerical error code.*/\nconst char* lodepng_error_text(unsigned code);\n#endif /*LODEPNG_COMPILE_ERROR_TEXT*/\n\n#ifdef LODEPNG_COMPILE_DECODER\n/*Settings for zlib decompression*/\ntypedef struct LodePNGDecompressSettings LodePNGDecompressSettings;\nstruct LodePNGDecompressSettings\n{\n  /* Check LodePNGDecoderSettings for more ignorable errors */\n  unsigned ignore_adler32; /*if 1, continue and don't give an error message if the Adler32 checksum is corrupted*/\n\n  /*use custom zlib decoder instead of built in one (default: null)*/\n  unsigned (*custom_zlib)(unsigned char**, size_t*,\n                          const unsigned char*, size_t,\n                          const LodePNGDecompressSettings*);\n  /*use custom deflate decoder instead of built in one (default: null)\n  if custom_zlib is used, custom_deflate is ignored since only the built in\n  zlib function will call custom_deflate*/\n  unsigned (*custom_inflate)(unsigned char**, size_t*,\n                             const unsigned char*, size_t,\n                             const LodePNGDecompressSettings*);\n\n  const void* custom_context; /*optional custom settings for custom functions*/\n};\n\nextern const LodePNGDecompressSettings lodepng_default_decompress_settings;\nvoid lodepng_decompress_settings_init(LodePNGDecompressSettings* settings);\n#endif /*LODEPNG_COMPILE_DECODER*/\n\n#ifdef LODEPNG_COMPILE_ENCODER\n/*\nSettings for zlib compression. Tweaking these settings tweaks the balance\nbetween speed and compression ratio.\n*/\ntypedef struct LodePNGCompressSettings LodePNGCompressSettings;\nstruct LodePNGCompressSettings /*deflate = compress*/\n{\n  /*LZ77 related settings*/\n  unsigned btype; /*the block type for LZ (0, 1, 2 or 3, see zlib standard). Should be 2 for proper compression.*/\n  unsigned use_lz77; /*whether or not to use LZ77. Should be 1 for proper compression.*/\n  unsigned windowsize; /*must be a power of two <= 32768. higher compresses more but is slower. Default value: 2048.*/\n  unsigned minmatch; /*mininum lz77 length. 3 is normally best, 6 can be better for some PNGs. Default: 0*/\n  unsigned nicematch; /*stop searching if >= this length found. Set to 258 for best compression. Default: 128*/\n  unsigned lazymatching; /*use lazy matching: better compression but a bit slower. Default: true*/\n\n  /*use custom zlib encoder instead of built in one (default: null)*/\n  unsigned (*custom_zlib)(unsigned char**, size_t*,\n                          const unsigned char*, size_t,\n                          const LodePNGCompressSettings*);\n  /*use custom deflate encoder instead of built in one (default: null)\n  if custom_zlib is used, custom_deflate is ignored since only the built in\n  zlib function will call custom_deflate*/\n  unsigned (*custom_deflate)(unsigned char**, size_t*,\n                             const unsigned char*, size_t,\n                             const LodePNGCompressSettings*);\n\n  const void* custom_context; /*optional custom settings for custom functions*/\n};\n\nextern const LodePNGCompressSettings lodepng_default_compress_settings;\nvoid lodepng_compress_settings_init(LodePNGCompressSettings* settings);\n#endif /*LODEPNG_COMPILE_ENCODER*/\n\n#ifdef LODEPNG_COMPILE_PNG\n/*\nColor mode of an image. Contains all information required to decode the pixel\nbits to RGBA colors. This information is the same as used in the PNG file\nformat, and is used both for PNG and raw image data in LodePNG.\n*/\ntypedef struct LodePNGColorMode\n{\n  /*header (IHDR)*/\n  LodePNGColorType colortype; /*color type, see PNG standard or documentation further in this header file*/\n  unsigned bitdepth;  /*bits per sample, see PNG standard or documentation further in this header file*/\n\n  /*\n  palette (PLTE and tRNS)\n\n  Dynamically allocated with the colors of the palette, including alpha.\n  When encoding a PNG, to store your colors in the palette of the LodePNGColorMode, first use\n  lodepng_palette_clear, then for each color use lodepng_palette_add.\n  If you encode an image without alpha with palette, don't forget to put value 255 in each A byte of the palette.\n\n  When decoding, by default you can ignore this palette, since LodePNG already\n  fills the palette colors in the pixels of the raw RGBA output.\n\n  The palette is only supported for color type 3.\n  */\n  unsigned char* palette; /*palette in RGBARGBA... order. When allocated, must be either 0, or have size 1024*/\n  size_t palettesize; /*palette size in number of colors (amount of bytes is 4 * palettesize)*/\n\n  /*\n  transparent color key (tRNS)\n\n  This color uses the same bit depth as the bitdepth value in this struct, which can be 1-bit to 16-bit.\n  For greyscale PNGs, r, g and b will all 3 be set to the same.\n\n  When decoding, by default you can ignore this information, since LodePNG sets\n  pixels with this key to transparent already in the raw RGBA output.\n\n  The color key is only supported for color types 0 and 2.\n  */\n  unsigned key_defined; /*is a transparent color key given? 0 = false, 1 = true*/\n  unsigned key_r;       /*red/greyscale component of color key*/\n  unsigned key_g;       /*green component of color key*/\n  unsigned key_b;       /*blue component of color key*/\n} LodePNGColorMode;\n\n/*init, cleanup and copy functions to use with this struct*/\nvoid lodepng_color_mode_init(LodePNGColorMode* info);\nvoid lodepng_color_mode_cleanup(LodePNGColorMode* info);\n/*return value is error code (0 means no error)*/\nunsigned lodepng_color_mode_copy(LodePNGColorMode* dest, const LodePNGColorMode* source);\n\nvoid lodepng_palette_clear(LodePNGColorMode* info);\n/*add 1 color to the palette*/\nunsigned lodepng_palette_add(LodePNGColorMode* info,\n                             unsigned char r, unsigned char g, unsigned char b, unsigned char a);\n\n/*get the total amount of bits per pixel, based on colortype and bitdepth in the struct*/\nunsigned lodepng_get_bpp(const LodePNGColorMode* info);\n/*get the amount of color channels used, based on colortype in the struct.\nIf a palette is used, it counts as 1 channel.*/\nunsigned lodepng_get_channels(const LodePNGColorMode* info);\n/*is it a greyscale type? (only colortype 0 or 4)*/\nunsigned lodepng_is_greyscale_type(const LodePNGColorMode* info);\n/*has it got an alpha channel? (only colortype 2 or 6)*/\nunsigned lodepng_is_alpha_type(const LodePNGColorMode* info);\n/*has it got a palette? (only colortype 3)*/\nunsigned lodepng_is_palette_type(const LodePNGColorMode* info);\n/*only returns true if there is a palette and there is a value in the palette with alpha < 255.\nLoops through the palette to check this.*/\nunsigned lodepng_has_palette_alpha(const LodePNGColorMode* info);\n/*\nCheck if the given color info indicates the possibility of having non-opaque pixels in the PNG image.\nReturns true if the image can have translucent or invisible pixels (it still be opaque if it doesn't use such pixels).\nReturns false if the image can only have opaque pixels.\nIn detail, it returns true only if it's a color type with alpha, or has a palette with non-opaque values,\nor if \"key_defined\" is true.\n*/\nunsigned lodepng_can_have_alpha(const LodePNGColorMode* info);\n/*Returns the byte size of a raw image buffer with given width, height and color mode*/\nsize_t lodepng_get_raw_size(unsigned w, unsigned h, const LodePNGColorMode* color);\n\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\n/*The information of a Time chunk in PNG.*/\ntypedef struct LodePNGTime\n{\n  unsigned year;    /*2 bytes used (0-65535)*/\n  unsigned month;   /*1-12*/\n  unsigned day;     /*1-31*/\n  unsigned hour;    /*0-23*/\n  unsigned minute;  /*0-59*/\n  unsigned second;  /*0-60 (to allow for leap seconds)*/\n} LodePNGTime;\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n\n/*Information about the PNG image, except pixels, width and height.*/\ntypedef struct LodePNGInfo\n{\n  /*header (IHDR), palette (PLTE) and transparency (tRNS) chunks*/\n  unsigned compression_method;/*compression method of the original file. Always 0.*/\n  unsigned filter_method;     /*filter method of the original file*/\n  unsigned interlace_method;  /*interlace method of the original file*/\n  LodePNGColorMode color;     /*color type and bits, palette and transparency of the PNG file*/\n\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\n  /*\n  suggested background color chunk (bKGD)\n  This color uses the same color mode as the PNG (except alpha channel), which can be 1-bit to 16-bit.\n\n  For greyscale PNGs, r, g and b will all 3 be set to the same. When encoding\n  the encoder writes the red one. For palette PNGs: When decoding, the RGB value\n  will be stored, not a palette index. But when encoding, specify the index of\n  the palette in background_r, the other two are then ignored.\n\n  The decoder does not use this background color to edit the color of pixels.\n  */\n  unsigned background_defined; /*is a suggested background color given?*/\n  unsigned background_r;       /*red component of suggested background color*/\n  unsigned background_g;       /*green component of suggested background color*/\n  unsigned background_b;       /*blue component of suggested background color*/\n\n  /*\n  non-international text chunks (tEXt and zTXt)\n\n  The char** arrays each contain num strings. The actual messages are in\n  text_strings, while text_keys are keywords that give a short description what\n  the actual text represents, e.g. Title, Author, Description, or anything else.\n\n  A keyword is minimum 1 character and maximum 79 characters long. It's\n  discouraged to use a single line length longer than 79 characters for texts.\n\n  Don't allocate these text buffers yourself. Use the init/cleanup functions\n  correctly and use lodepng_add_text and lodepng_clear_text.\n  */\n  size_t text_num; /*the amount of texts in these char** buffers (there may be more texts in itext)*/\n  char** text_keys; /*the keyword of a text chunk (e.g. \"Comment\")*/\n  char** text_strings; /*the actual text*/\n\n  /*\n  international text chunks (iTXt)\n  Similar to the non-international text chunks, but with additional strings\n  \"langtags\" and \"transkeys\".\n  */\n  size_t itext_num; /*the amount of international texts in this PNG*/\n  char** itext_keys; /*the English keyword of the text chunk (e.g. \"Comment\")*/\n  char** itext_langtags; /*language tag for this text's language, ISO/IEC 646 string, e.g. ISO 639 language tag*/\n  char** itext_transkeys; /*keyword translated to the international language - UTF-8 string*/\n  char** itext_strings; /*the actual international text - UTF-8 string*/\n\n  /*time chunk (tIME)*/\n  unsigned time_defined; /*set to 1 to make the encoder generate a tIME chunk*/\n  LodePNGTime time;\n\n  /*phys chunk (pHYs)*/\n  unsigned phys_defined; /*if 0, there is no pHYs chunk and the values below are undefined, if 1 else there is one*/\n  unsigned phys_x; /*pixels per unit in x direction*/\n  unsigned phys_y; /*pixels per unit in y direction*/\n  unsigned phys_unit; /*may be 0 (unknown unit) or 1 (metre)*/\n\n  /*\n  unknown chunks\n  There are 3 buffers, one for each position in the PNG where unknown chunks can appear\n  each buffer contains all unknown chunks for that position consecutively\n  The 3 buffers are the unknown chunks between certain critical chunks:\n  0: IHDR-PLTE, 1: PLTE-IDAT, 2: IDAT-IEND\n  Do not allocate or traverse this data yourself. Use the chunk traversing functions declared\n  later, such as lodepng_chunk_next and lodepng_chunk_append, to read/write this struct.\n  */\n  unsigned char* unknown_chunks_data[3];\n  size_t unknown_chunks_size[3]; /*size in bytes of the unknown chunks, given for protection*/\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n} LodePNGInfo;\n\n/*init, cleanup and copy functions to use with this struct*/\nvoid lodepng_info_init(LodePNGInfo* info);\nvoid lodepng_info_cleanup(LodePNGInfo* info);\n/*return value is error code (0 means no error)*/\nunsigned lodepng_info_copy(LodePNGInfo* dest, const LodePNGInfo* source);\n\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\nvoid lodepng_clear_text(LodePNGInfo* info); /*use this to clear the texts again after you filled them in*/\nunsigned lodepng_add_text(LodePNGInfo* info, const char* key, const char* str); /*push back both texts at once*/\n\nvoid lodepng_clear_itext(LodePNGInfo* info); /*use this to clear the itexts again after you filled them in*/\nunsigned lodepng_add_itext(LodePNGInfo* info, const char* key, const char* langtag,\n                           const char* transkey, const char* str); /*push back the 4 texts of 1 chunk at once*/\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n\n/*\nConverts raw buffer from one color type to another color type, based on\nLodePNGColorMode structs to describe the input and output color type.\nSee the reference manual at the end of this header file to see which color conversions are supported.\nreturn value = LodePNG error code (0 if all went ok, an error if the conversion isn't supported)\nThe out buffer must have size (w * h * bpp + 7) / 8, where bpp is the bits per pixel\nof the output color type (lodepng_get_bpp).\nFor < 8 bpp images, there should not be padding bits at the end of scanlines.\nFor 16-bit per channel colors, uses big endian format like PNG does.\nReturn value is LodePNG error code\n*/\nunsigned lodepng_convert(unsigned char* out, const unsigned char* in,\n                         const LodePNGColorMode* mode_out, const LodePNGColorMode* mode_in,\n                         unsigned w, unsigned h);\n\n#ifdef LODEPNG_COMPILE_DECODER\n/*\nSettings for the decoder. This contains settings for the PNG and the Zlib\ndecoder, but not the Info settings from the Info structs.\n*/\ntypedef struct LodePNGDecoderSettings\n{\n  LodePNGDecompressSettings zlibsettings; /*in here is the setting to ignore Adler32 checksums*/\n\n  /* Check LodePNGDecompressSettings for more ignorable errors */\n  unsigned ignore_crc; /*ignore CRC checksums*/\n  unsigned ignore_critical; /*ignore unknown critical chunks*/\n  unsigned ignore_end; /*ignore issues at end of file if possible (missing IEND chunk, too large chunk, ...)*/\n\n  unsigned color_convert; /*whether to convert the PNG to the color type you want. Default: yes*/\n\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\n  unsigned read_text_chunks; /*if false but remember_unknown_chunks is true, they're stored in the unknown chunks*/\n  /*store all bytes from unknown chunks in the LodePNGInfo (off by default, useful for a png editor)*/\n  unsigned remember_unknown_chunks;\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n} LodePNGDecoderSettings;\n\nvoid lodepng_decoder_settings_init(LodePNGDecoderSettings* settings);\n#endif /*LODEPNG_COMPILE_DECODER*/\n\n#ifdef LODEPNG_COMPILE_ENCODER\n/*automatically use color type with less bits per pixel if losslessly possible. Default: AUTO*/\ntypedef enum LodePNGFilterStrategy\n{\n  /*every filter at zero*/\n  LFS_ZERO,\n  /*Use filter that gives minimum sum, as described in the official PNG filter heuristic.*/\n  LFS_MINSUM,\n  /*Use the filter type that gives smallest Shannon entropy for this scanline. Depending\n  on the image, this is better or worse than minsum.*/\n  LFS_ENTROPY,\n  /*\n  Brute-force-search PNG filters by compressing each filter for each scanline.\n  Experimental, very slow, and only rarely gives better compression than MINSUM.\n  */\n  LFS_BRUTE_FORCE,\n  /*use predefined_filters buffer: you specify the filter type for each scanline*/\n  LFS_PREDEFINED\n} LodePNGFilterStrategy;\n\n/*Gives characteristics about the colors of the image, which helps decide which color model to use for encoding.\nUsed internally by default if \"auto_convert\" is enabled. Public because it's useful for custom algorithms.*/\ntypedef struct LodePNGColorProfile\n{\n  unsigned colored; /*not greyscale*/\n  unsigned key; /*image is not opaque and color key is possible instead of full alpha*/\n  unsigned short key_r; /*key values, always as 16-bit, in 8-bit case the byte is duplicated, e.g. 65535 means 255*/\n  unsigned short key_g;\n  unsigned short key_b;\n  unsigned alpha; /*image is not opaque and alpha channel or alpha palette required*/\n  unsigned numcolors; /*amount of colors, up to 257. Not valid if bits == 16.*/\n  unsigned char palette[1024]; /*Remembers up to the first 256 RGBA colors, in no particular order*/\n  unsigned bits; /*bits per channel (not for palette). 1,2 or 4 for greyscale only. 16 if 16-bit per channel required.*/\n} LodePNGColorProfile;\n\nvoid lodepng_color_profile_init(LodePNGColorProfile* profile);\n\n/*Get a LodePNGColorProfile of the image.*/\nunsigned lodepng_get_color_profile(LodePNGColorProfile* profile,\n                                   const unsigned char* image, unsigned w, unsigned h,\n                                   const LodePNGColorMode* mode_in);\n/*The function LodePNG uses internally to decide the PNG color with auto_convert.\nChooses an optimal color model, e.g. grey if only grey pixels, palette if < 256 colors, ...*/\nunsigned lodepng_auto_choose_color(LodePNGColorMode* mode_out,\n                                   const unsigned char* image, unsigned w, unsigned h,\n                                   const LodePNGColorMode* mode_in);\n\n/*Settings for the encoder.*/\ntypedef struct LodePNGEncoderSettings\n{\n  LodePNGCompressSettings zlibsettings; /*settings for the zlib encoder, such as window size, ...*/\n\n  unsigned auto_convert; /*automatically choose output PNG color type. Default: true*/\n\n  /*If true, follows the official PNG heuristic: if the PNG uses a palette or lower than\n  8 bit depth, set all filters to zero. Otherwise use the filter_strategy. Note that to\n  completely follow the official PNG heuristic, filter_palette_zero must be true and\n  filter_strategy must be LFS_MINSUM*/\n  unsigned filter_palette_zero;\n  /*Which filter strategy to use when not using zeroes due to filter_palette_zero.\n  Set filter_palette_zero to 0 to ensure always using your chosen strategy. Default: LFS_MINSUM*/\n  LodePNGFilterStrategy filter_strategy;\n  /*used if filter_strategy is LFS_PREDEFINED. In that case, this must point to a buffer with\n  the same length as the amount of scanlines in the image, and each value must <= 5. You\n  have to cleanup this buffer, LodePNG will never free it. Don't forget that filter_palette_zero\n  must be set to 0 to ensure this is also used on palette or low bitdepth images.*/\n  const unsigned char* predefined_filters;\n\n  /*force creating a PLTE chunk if colortype is 2 or 6 (= a suggested palette).\n  If colortype is 3, PLTE is _always_ created.*/\n  unsigned force_palette;\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\n  /*add LodePNG identifier and version as a text chunk, for debugging*/\n  unsigned add_id;\n  /*encode text chunks as zTXt chunks instead of tEXt chunks, and use compression in iTXt chunks*/\n  unsigned text_compression;\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n} LodePNGEncoderSettings;\n\nvoid lodepng_encoder_settings_init(LodePNGEncoderSettings* settings);\n#endif /*LODEPNG_COMPILE_ENCODER*/\n\n\n#if defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER)\n/*The settings, state and information for extended encoding and decoding.*/\ntypedef struct LodePNGState\n{\n#ifdef LODEPNG_COMPILE_DECODER\n  LodePNGDecoderSettings decoder; /*the decoding settings*/\n#endif /*LODEPNG_COMPILE_DECODER*/\n#ifdef LODEPNG_COMPILE_ENCODER\n  LodePNGEncoderSettings encoder; /*the encoding settings*/\n#endif /*LODEPNG_COMPILE_ENCODER*/\n  LodePNGColorMode info_raw; /*specifies the format in which you would like to get the raw pixel buffer*/\n  LodePNGInfo info_png; /*info of the PNG image obtained after decoding*/\n  unsigned error;\n#ifdef LODEPNG_COMPILE_CPP\n  /* For the lodepng::State subclass. */\n  virtual ~LodePNGState(){}\n#endif\n} LodePNGState;\n\n/*init, cleanup and copy functions to use with this struct*/\nvoid lodepng_state_init(LodePNGState* state);\nvoid lodepng_state_cleanup(LodePNGState* state);\nvoid lodepng_state_copy(LodePNGState* dest, const LodePNGState* source);\n#endif /* defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER) */\n\n#ifdef LODEPNG_COMPILE_DECODER\n/*\nSame as lodepng_decode_memory, but uses a LodePNGState to allow custom settings and\ngetting much more information about the PNG image and color mode.\n*/\nunsigned lodepng_decode(unsigned char** out, unsigned* w, unsigned* h,\n                        LodePNGState* state,\n                        const unsigned char* in, size_t insize);\n\n/*\nRead the PNG header, but not the actual data. This returns only the information\nthat is in the header chunk of the PNG, such as width, height and color type. The\ninformation is placed in the info_png field of the LodePNGState.\n*/\nunsigned lodepng_inspect(unsigned* w, unsigned* h,\n                         LodePNGState* state,\n                         const unsigned char* in, size_t insize);\n#endif /*LODEPNG_COMPILE_DECODER*/\n\n\n#ifdef LODEPNG_COMPILE_ENCODER\n/*This function allocates the out buffer with standard malloc and stores the size in *outsize.*/\nunsigned lodepng_encode(unsigned char** out, size_t* outsize,\n                        const unsigned char* image, unsigned w, unsigned h,\n                        LodePNGState* state);\n#endif /*LODEPNG_COMPILE_ENCODER*/\n\n/*\nThe lodepng_chunk functions are normally not needed, except to traverse the\nunknown chunks stored in the LodePNGInfo struct, or add new ones to it.\nIt also allows traversing the chunks of an encoded PNG file yourself.\n\nPNG standard chunk naming conventions:\nFirst byte: uppercase = critical, lowercase = ancillary\nSecond byte: uppercase = public, lowercase = private\nThird byte: must be uppercase\nFourth byte: uppercase = unsafe to copy, lowercase = safe to copy\n*/\n\n/*\nGets the length of the data of the chunk. Total chunk length has 12 bytes more.\nThere must be at least 4 bytes to read from. If the result value is too large,\nit may be corrupt data.\n*/\nunsigned lodepng_chunk_length(const unsigned char* chunk);\n\n/*puts the 4-byte type in null terminated string*/\nvoid lodepng_chunk_type(char type[5], const unsigned char* chunk);\n\n/*check if the type is the given type*/\nunsigned char lodepng_chunk_type_equals(const unsigned char* chunk, const char* type);\n\n/*0: it's one of the critical chunk types, 1: it's an ancillary chunk (see PNG standard)*/\nunsigned char lodepng_chunk_ancillary(const unsigned char* chunk);\n\n/*0: public, 1: private (see PNG standard)*/\nunsigned char lodepng_chunk_private(const unsigned char* chunk);\n\n/*0: the chunk is unsafe to copy, 1: the chunk is safe to copy (see PNG standard)*/\nunsigned char lodepng_chunk_safetocopy(const unsigned char* chunk);\n\n/*get pointer to the data of the chunk, where the input points to the header of the chunk*/\nunsigned char* lodepng_chunk_data(unsigned char* chunk);\nconst unsigned char* lodepng_chunk_data_const(const unsigned char* chunk);\n\n/*returns 0 if the crc is correct, 1 if it's incorrect (0 for OK as usual!)*/\nunsigned lodepng_chunk_check_crc(const unsigned char* chunk);\n\n/*generates the correct CRC from the data and puts it in the last 4 bytes of the chunk*/\nvoid lodepng_chunk_generate_crc(unsigned char* chunk);\n\n/*iterate to next chunks. don't use on IEND chunk, as there is no next chunk then*/\nunsigned char* lodepng_chunk_next(unsigned char* chunk);\nconst unsigned char* lodepng_chunk_next_const(const unsigned char* chunk);\n\n/*\nAppends chunk to the data in out. The given chunk should already have its chunk header.\nThe out variable and outlength are updated to reflect the new reallocated buffer.\nReturns error code (0 if it went ok)\n*/\nunsigned lodepng_chunk_append(unsigned char** out, size_t* outlength, const unsigned char* chunk);\n\n/*\nAppends new chunk to out. The chunk to append is given by giving its length, type\nand data separately. The type is a 4-letter string.\nThe out variable and outlength are updated to reflect the new reallocated buffer.\nReturne error code (0 if it went ok)\n*/\nunsigned lodepng_chunk_create(unsigned char** out, size_t* outlength, unsigned length,\n                              const char* type, const unsigned char* data);\n\n\n/*Calculate CRC32 of buffer*/\nunsigned lodepng_crc32(const unsigned char* buf, size_t len);\n#endif /*LODEPNG_COMPILE_PNG*/\n\n\n#ifdef LODEPNG_COMPILE_ZLIB\n/*\nThis zlib part can be used independently to zlib compress and decompress a\nbuffer. It cannot be used to create gzip files however, and it only supports the\npart of zlib that is required for PNG, it does not support dictionaries.\n*/\n\n#ifdef LODEPNG_COMPILE_DECODER\n/*Inflate a buffer. Inflate is the decompression step of deflate. Out buffer must be freed after use.*/\nunsigned lodepng_inflate(unsigned char** out, size_t* outsize,\n                         const unsigned char* in, size_t insize,\n                         const LodePNGDecompressSettings* settings);\n\n/*\nDecompresses Zlib data. Reallocates the out buffer and appends the data. The\ndata must be according to the zlib specification.\nEither, *out must be NULL and *outsize must be 0, or, *out must be a valid\nbuffer and *outsize its size in bytes. out must be freed by user after usage.\n*/\nunsigned lodepng_zlib_decompress(unsigned char** out, size_t* outsize,\n                                 const unsigned char* in, size_t insize,\n                                 const LodePNGDecompressSettings* settings);\n#endif /*LODEPNG_COMPILE_DECODER*/\n\n#ifdef LODEPNG_COMPILE_ENCODER\n/*\nCompresses data with Zlib. Reallocates the out buffer and appends the data.\nZlib adds a small header and trailer around the deflate data.\nThe data is output in the format of the zlib specification.\nEither, *out must be NULL and *outsize must be 0, or, *out must be a valid\nbuffer and *outsize its size in bytes. out must be freed by user after usage.\n*/\nunsigned lodepng_zlib_compress(unsigned char** out, size_t* outsize,\n                               const unsigned char* in, size_t insize,\n                               const LodePNGCompressSettings* settings);\n\n/*\nFind length-limited Huffman code for given frequencies. This function is in the\npublic interface only for tests, it's used internally by lodepng_deflate.\n*/\nunsigned lodepng_huffman_code_lengths(unsigned* lengths, const unsigned* frequencies,\n                                      size_t numcodes, unsigned maxbitlen);\n\n/*Compress a buffer with deflate. See RFC 1951. Out buffer must be freed after use.*/\nunsigned lodepng_deflate(unsigned char** out, size_t* outsize,\n                         const unsigned char* in, size_t insize,\n                         const LodePNGCompressSettings* settings);\n\n#endif /*LODEPNG_COMPILE_ENCODER*/\n#endif /*LODEPNG_COMPILE_ZLIB*/\n\n#ifdef LODEPNG_COMPILE_DISK\n/*\nLoad a file from disk into buffer. The function allocates the out buffer, and\nafter usage you should free it.\nout: output parameter, contains pointer to loaded buffer.\noutsize: output parameter, size of the allocated out buffer\nfilename: the path to the file to load\nreturn value: error code (0 means ok)\n*/\nunsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* filename);\n\n/*\nSave a file from buffer to disk. Warning, if it exists, this function overwrites\nthe file without warning!\nbuffer: the buffer to write\nbuffersize: size of the buffer to write\nfilename: the path to the file to save to\nreturn value: error code (0 means ok)\n*/\nunsigned lodepng_save_file(const unsigned char* buffer, size_t buffersize, const char* filename);\n#endif /*LODEPNG_COMPILE_DISK*/\n\n#ifdef LODEPNG_COMPILE_CPP\n/* The LodePNG C++ wrapper uses std::vectors instead of manually allocated memory buffers. */\nnamespace lodepng\n{\n#ifdef LODEPNG_COMPILE_PNG\nclass State : public LodePNGState\n{\n  public:\n    State();\n    State(const State& other);\n    virtual ~State();\n    State& operator=(const State& other);\n};\n\n#ifdef LODEPNG_COMPILE_DECODER\n/* Same as other lodepng::decode, but using a State for more settings and information. */\nunsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,\n                State& state,\n                const unsigned char* in, size_t insize);\nunsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,\n                State& state,\n                const std::vector<unsigned char>& in);\n#endif /*LODEPNG_COMPILE_DECODER*/\n\n#ifdef LODEPNG_COMPILE_ENCODER\n/* Same as other lodepng::encode, but using a State for more settings and information. */\nunsigned encode(std::vector<unsigned char>& out,\n                const unsigned char* in, unsigned w, unsigned h,\n                State& state);\nunsigned encode(std::vector<unsigned char>& out,\n                const std::vector<unsigned char>& in, unsigned w, unsigned h,\n                State& state);\n#endif /*LODEPNG_COMPILE_ENCODER*/\n\n#ifdef LODEPNG_COMPILE_DISK\n/*\nLoad a file from disk into an std::vector.\nreturn value: error code (0 means ok)\n*/\nunsigned load_file(std::vector<unsigned char>& buffer, const std::string& filename);\n\n/*\nSave the binary data in an std::vector to a file on disk. The file is overwritten\nwithout warning.\n*/\nunsigned save_file(const std::vector<unsigned char>& buffer, const std::string& filename);\n#endif /* LODEPNG_COMPILE_DISK */\n#endif /* LODEPNG_COMPILE_PNG */\n\n#ifdef LODEPNG_COMPILE_ZLIB\n#ifdef LODEPNG_COMPILE_DECODER\n/* Zlib-decompress an unsigned char buffer */\nunsigned decompress(std::vector<unsigned char>& out, const unsigned char* in, size_t insize,\n                    const LodePNGDecompressSettings& settings = lodepng_default_decompress_settings);\n\n/* Zlib-decompress an std::vector */\nunsigned decompress(std::vector<unsigned char>& out, const std::vector<unsigned char>& in,\n                    const LodePNGDecompressSettings& settings = lodepng_default_decompress_settings);\n#endif /* LODEPNG_COMPILE_DECODER */\n\n#ifdef LODEPNG_COMPILE_ENCODER\n/* Zlib-compress an unsigned char buffer */\nunsigned compress(std::vector<unsigned char>& out, const unsigned char* in, size_t insize,\n                  const LodePNGCompressSettings& settings = lodepng_default_compress_settings);\n\n/* Zlib-compress an std::vector */\nunsigned compress(std::vector<unsigned char>& out, const std::vector<unsigned char>& in,\n                  const LodePNGCompressSettings& settings = lodepng_default_compress_settings);\n#endif /* LODEPNG_COMPILE_ENCODER */\n#endif /* LODEPNG_COMPILE_ZLIB */\n} /* namespace lodepng */\n#endif /*LODEPNG_COMPILE_CPP*/\n\n/*\nTODO:\n[.] test if there are no memory leaks or security exploits - done a lot but needs to be checked often\n[.] check compatibility with various compilers  - done but needs to be redone for every newer version\n[X] converting color to 16-bit per channel types\n[ ] read all public PNG chunk types (but never let the color profile and gamma ones touch RGB values)\n[ ] make sure encoder generates no chunks with size > (2^31)-1\n[ ] partial decoding (stream processing)\n[X] let the \"isFullyOpaque\" function check color keys and transparent palettes too\n[X] better name for the variables \"codes\", \"codesD\", \"codelengthcodes\", \"clcl\" and \"lldl\"\n[ ] don't stop decoding on errors like 69, 57, 58 (make warnings)\n[ ] make warnings like: oob palette, checksum fail, data after iend, wrong/unknown crit chunk, no null terminator in text, ...\n[ ] let the C++ wrapper catch exceptions coming from the standard library and return LodePNG error codes\n[ ] allow user to provide custom color conversion functions, e.g. for premultiplied alpha, padding bits or not, ...\n[ ] allow user to give data (void*) to custom allocator\n*/\n\n#endif /*LODEPNG_H inclusion guard*/\n\n/*\nLodePNG Documentation\n---------------------\n\n0. table of contents\n--------------------\n\n  1. about\n   1.1. supported features\n   1.2. features not supported\n  2. C and C++ version\n  3. security\n  4. decoding\n  5. encoding\n  6. color conversions\n    6.1. PNG color types\n    6.2. color conversions\n    6.3. padding bits\n    6.4. A note about 16-bits per channel and endianness\n  7. error values\n  8. chunks and PNG editing\n  9. compiler support\n  10. examples\n   10.1. decoder C++ example\n   10.2. decoder C example\n  11. state settings reference\n  12. changes\n  13. contact information\n\n\n1. about\n--------\n\nPNG is a file format to store raster images losslessly with good compression,\nsupporting different color types and alpha channel.\n\nLodePNG is a PNG codec according to the Portable Network Graphics (PNG)\nSpecification (Second Edition) - W3C Recommendation 10 November 2003.\n\nThe specifications used are:\n\n*) Portable Network Graphics (PNG) Specification (Second Edition):\n     http://www.w3.org/TR/2003/REC-PNG-20031110\n*) RFC 1950 ZLIB Compressed Data Format version 3.3:\n     http://www.gzip.org/zlib/rfc-zlib.html\n*) RFC 1951 DEFLATE Compressed Data Format Specification ver 1.3:\n     http://www.gzip.org/zlib/rfc-deflate.html\n\nThe most recent version of LodePNG can currently be found at\nhttp://lodev.org/lodepng/\n\nLodePNG works both in C (ISO C90) and C++, with a C++ wrapper that adds\nextra functionality.\n\nLodePNG exists out of two files:\n-lodepng.h: the header file for both C and C++\n-lodepng.c(pp): give it the name lodepng.c or lodepng.cpp (or .cc) depending on your usage\n\nIf you want to start using LodePNG right away without reading this doc, get the\nexamples from the LodePNG website to see how to use it in code, or check the\nsmaller examples in chapter 13 here.\n\nLodePNG is simple but only supports the basic requirements. To achieve\nsimplicity, the following design choices were made: There are no dependencies\non any external library. There are functions to decode and encode a PNG with\na single function call, and extended versions of these functions taking a\nLodePNGState struct allowing to specify or get more information. By default\nthe colors of the raw image are always RGB or RGBA, no matter what color type\nthe PNG file uses. To read and write files, there are simple functions to\nconvert the files to/from buffers in memory.\n\nThis all makes LodePNG suitable for loading textures in games, demos and small\nprograms, ... It's less suitable for full fledged image editors, loading PNGs\nover network (it requires all the image data to be available before decoding can\nbegin), life-critical systems, ...\n\n1.1. supported features\n-----------------------\n\nThe following features are supported by the decoder:\n\n*) decoding of PNGs with any color type, bit depth and interlace mode, to a 24- or 32-bit color raw image,\n   or the same color type as the PNG\n*) encoding of PNGs, from any raw image to 24- or 32-bit color, or the same color type as the raw image\n*) Adam7 interlace and deinterlace for any color type\n*) loading the image from harddisk or decoding it from a buffer from other sources than harddisk\n*) support for alpha channels, including RGBA color model, translucent palettes and color keying\n*) zlib decompression (inflate)\n*) zlib compression (deflate)\n*) CRC32 and ADLER32 checksums\n*) handling of unknown chunks, allowing making a PNG editor that stores custom and unknown chunks.\n*) the following chunks are supported (generated/interpreted) by both encoder and decoder:\n    IHDR: header information\n    PLTE: color palette\n    IDAT: pixel data\n    IEND: the final chunk\n    tRNS: transparency for palettized images\n    tEXt: textual information\n    zTXt: compressed textual information\n    iTXt: international textual information\n    bKGD: suggested background color\n    pHYs: physical dimensions\n    tIME: modification time\n\n1.2. features not supported\n---------------------------\n\nThe following features are _not_ supported:\n\n*) some features needed to make a conformant PNG-Editor might be still missing.\n*) partial loading/stream processing. All data must be available and is processed in one call.\n*) The following public chunks are not supported but treated as unknown chunks by LodePNG\n    cHRM, gAMA, iCCP, sRGB, sBIT, hIST, sPLT\n   Some of these are not supported on purpose: LodePNG wants to provide the RGB values\n   stored in the pixels, not values modified by system dependent gamma or color models.\n\n\n2. C and C++ version\n--------------------\n\nThe C version uses buffers allocated with alloc that you need to free()\nyourself. You need to use init and cleanup functions for each struct whenever\nusing a struct from the C version to avoid exploits and memory leaks.\n\nThe C++ version has extra functions with std::vectors in the interface and the\nlodepng::State class which is a LodePNGState with constructor and destructor.\n\nThese files work without modification for both C and C++ compilers because all\nthe additional C++ code is in \"#ifdef __cplusplus\" blocks that make C-compilers\nignore it, and the C code is made to compile both with strict ISO C90 and C++.\n\nTo use the C++ version, you need to rename the source file to lodepng.cpp\n(instead of lodepng.c), and compile it with a C++ compiler.\n\nTo use the C version, you need to rename the source file to lodepng.c (instead\nof lodepng.cpp), and compile it with a C compiler.\n\n\n3. Security\n-----------\n\nEven if carefully designed, it's always possible that LodePNG contains possible\nexploits. If you discover one, please let me know, and it will be fixed.\n\nWhen using LodePNG, care has to be taken with the C version of LodePNG, as well\nas the C-style structs when working with C++. The following conventions are used\nfor all C-style structs:\n\n-if a struct has a corresponding init function, always call the init function when making a new one\n-if a struct has a corresponding cleanup function, call it before the struct disappears to avoid memory leaks\n-if a struct has a corresponding copy function, use the copy function instead of \"=\".\n The destination must also be inited already.\n\n\n4. Decoding\n-----------\n\nDecoding converts a PNG compressed image to a raw pixel buffer.\n\nMost documentation on using the decoder is at its declarations in the header\nabove. For C, simple decoding can be done with functions such as\nlodepng_decode32, and more advanced decoding can be done with the struct\nLodePNGState and lodepng_decode. For C++, all decoding can be done with the\nvarious lodepng::decode functions, and lodepng::State can be used for advanced\nfeatures.\n\nWhen using the LodePNGState, it uses the following fields for decoding:\n*) LodePNGInfo info_png: it stores extra information about the PNG (the input) in here\n*) LodePNGColorMode info_raw: here you can say what color mode of the raw image (the output) you want to get\n*) LodePNGDecoderSettings decoder: you can specify a few extra settings for the decoder to use\n\nLodePNGInfo info_png\n--------------------\n\nAfter decoding, this contains extra information of the PNG image, except the actual\npixels, width and height because these are already gotten directly from the decoder\nfunctions.\n\nIt contains for example the original color type of the PNG image, text comments,\nsuggested background color, etc... More details about the LodePNGInfo struct are\nat its declaration documentation.\n\nLodePNGColorMode info_raw\n-------------------------\n\nWhen decoding, here you can specify which color type you want\nthe resulting raw image to be. If this is different from the colortype of the\nPNG, then the decoder will automatically convert the result. This conversion\nalways works, except if you want it to convert a color PNG to greyscale or to\na palette with missing colors.\n\nBy default, 32-bit color is used for the result.\n\nLodePNGDecoderSettings decoder\n------------------------------\n\nThe settings can be used to ignore the errors created by invalid CRC and Adler32\nchunks, and to disable the decoding of tEXt chunks.\n\nThere's also a setting color_convert, true by default. If false, no conversion\nis done, the resulting data will be as it was in the PNG (after decompression)\nand you'll have to puzzle the colors of the pixels together yourself using the\ncolor type information in the LodePNGInfo.\n\n\n5. Encoding\n-----------\n\nEncoding converts a raw pixel buffer to a PNG compressed image.\n\nMost documentation on using the encoder is at its declarations in the header\nabove. For C, simple encoding can be done with functions such as\nlodepng_encode32, and more advanced decoding can be done with the struct\nLodePNGState and lodepng_encode. For C++, all encoding can be done with the\nvarious lodepng::encode functions, and lodepng::State can be used for advanced\nfeatures.\n\nLike the decoder, the encoder can also give errors. However it gives less errors\nsince the encoder input is trusted, the decoder input (a PNG image that could\nbe forged by anyone) is not trusted.\n\nWhen using the LodePNGState, it uses the following fields for encoding:\n*) LodePNGInfo info_png: here you specify how you want the PNG (the output) to be.\n*) LodePNGColorMode info_raw: here you say what color type of the raw image (the input) has\n*) LodePNGEncoderSettings encoder: you can specify a few settings for the encoder to use\n\nLodePNGInfo info_png\n--------------------\n\nWhen encoding, you use this the opposite way as when decoding: for encoding,\nyou fill in the values you want the PNG to have before encoding. By default it's\nnot needed to specify a color type for the PNG since it's automatically chosen,\nbut it's possible to choose it yourself given the right settings.\n\nThe encoder will not always exactly match the LodePNGInfo struct you give,\nit tries as close as possible. Some things are ignored by the encoder. The\nencoder uses, for example, the following settings from it when applicable:\ncolortype and bitdepth, text chunks, time chunk, the color key, the palette, the\nbackground color, the interlace method, unknown chunks, ...\n\nWhen encoding to a PNG with colortype 3, the encoder will generate a PLTE chunk.\nIf the palette contains any colors for which the alpha channel is not 255 (so\nthere are translucent colors in the palette), it'll add a tRNS chunk.\n\nLodePNGColorMode info_raw\n-------------------------\n\nYou specify the color type of the raw image that you give to the input here,\nincluding a possible transparent color key and palette you happen to be using in\nyour raw image data.\n\nBy default, 32-bit color is assumed, meaning your input has to be in RGBA\nformat with 4 bytes (unsigned chars) per pixel.\n\nLodePNGEncoderSettings encoder\n------------------------------\n\nThe following settings are supported (some are in sub-structs):\n*) auto_convert: when this option is enabled, the encoder will\nautomatically choose the smallest possible color mode (including color key) that\ncan encode the colors of all pixels without information loss.\n*) btype: the block type for LZ77. 0 = uncompressed, 1 = fixed huffman tree,\n   2 = dynamic huffman tree (best compression). Should be 2 for proper\n   compression.\n*) use_lz77: whether or not to use LZ77 for compressed block types. Should be\n   true for proper compression.\n*) windowsize: the window size used by the LZ77 encoder (1 - 32768). Has value\n   2048 by default, but can be set to 32768 for better, but slow, compression.\n*) force_palette: if colortype is 2 or 6, you can make the encoder write a PLTE\n   chunk if force_palette is true. This can used as suggested palette to convert\n   to by viewers that don't support more than 256 colors (if those still exist)\n*) add_id: add text chunk \"Encoder: LodePNG <version>\" to the image.\n*) text_compression: default 1. If 1, it'll store texts as zTXt instead of tEXt chunks.\n  zTXt chunks use zlib compression on the text. This gives a smaller result on\n  large texts but a larger result on small texts (such as a single program name).\n  It's all tEXt or all zTXt though, there's no separate setting per text yet.\n\n\n6. color conversions\n--------------------\n\nAn important thing to note about LodePNG, is that the color type of the PNG, and\nthe color type of the raw image, are completely independent. By default, when\nyou decode a PNG, you get the result as a raw image in the color type you want,\nno matter whether the PNG was encoded with a palette, greyscale or RGBA color.\nAnd if you encode an image, by default LodePNG will automatically choose the PNG\ncolor type that gives good compression based on the values of colors and amount\nof colors in the image. It can be configured to let you control it instead as\nwell, though.\n\nTo be able to do this, LodePNG does conversions from one color mode to another.\nIt can convert from almost any color type to any other color type, except the\nfollowing conversions: RGB to greyscale is not supported, and converting to a\npalette when the palette doesn't have a required color is not supported. This is\nnot supported on purpose: this is information loss which requires a color\nreduction algorithm that is beyong the scope of a PNG encoder (yes, RGB to grey\nis easy, but there are multiple ways if you want to give some channels more\nweight).\n\nBy default, when decoding, you get the raw image in 32-bit RGBA or 24-bit RGB\ncolor, no matter what color type the PNG has. And by default when encoding,\nLodePNG automatically picks the best color model for the output PNG, and expects\nthe input image to be 32-bit RGBA or 24-bit RGB. So, unless you want to control\nthe color format of the images yourself, you can skip this chapter.\n\n6.1. PNG color types\n--------------------\n\nA PNG image can have many color types, ranging from 1-bit color to 64-bit color,\nas well as palettized color modes. After the zlib decompression and unfiltering\nin the PNG image is done, the raw pixel data will have that color type and thus\na certain amount of bits per pixel. If you want the output raw image after\ndecoding to have another color type, a conversion is done by LodePNG.\n\nThe PNG specification gives the following color types:\n\n0: greyscale, bit depths 1, 2, 4, 8, 16\n2: RGB, bit depths 8 and 16\n3: palette, bit depths 1, 2, 4 and 8\n4: greyscale with alpha, bit depths 8 and 16\n6: RGBA, bit depths 8 and 16\n\nBit depth is the amount of bits per pixel per color channel. So the total amount\nof bits per pixel is: amount of channels * bitdepth.\n\n6.2. color conversions\n----------------------\n\nAs explained in the sections about the encoder and decoder, you can specify\ncolor types and bit depths in info_png and info_raw to change the default\nbehaviour.\n\nIf, when decoding, you want the raw image to be something else than the default,\nyou need to set the color type and bit depth you want in the LodePNGColorMode,\nor the parameters colortype and bitdepth of the simple decoding function.\n\nIf, when encoding, you use another color type than the default in the raw input\nimage, you need to specify its color type and bit depth in the LodePNGColorMode\nof the raw image, or use the parameters colortype and bitdepth of the simple\nencoding function.\n\nIf, when encoding, you don't want LodePNG to choose the output PNG color type\nbut control it yourself, you need to set auto_convert in the encoder settings\nto false, and specify the color type you want in the LodePNGInfo of the\nencoder (including palette: it can generate a palette if auto_convert is true,\notherwise not).\n\nIf the input and output color type differ (whether user chosen or auto chosen),\nLodePNG will do a color conversion, which follows the rules below, and may\nsometimes result in an error.\n\nTo avoid some confusion:\n-the decoder converts from PNG to raw image\n-the encoder converts from raw image to PNG\n-the colortype and bitdepth in LodePNGColorMode info_raw, are those of the raw image\n-the colortype and bitdepth in the color field of LodePNGInfo info_png, are those of the PNG\n-when encoding, the color type in LodePNGInfo is ignored if auto_convert\n is enabled, it is automatically generated instead\n-when decoding, the color type in LodePNGInfo is set by the decoder to that of the original\n PNG image, but it can be ignored since the raw image has the color type you requested instead\n-if the color type of the LodePNGColorMode and PNG image aren't the same, a conversion\n between the color types is done if the color types are supported. If it is not\n supported, an error is returned. If the types are the same, no conversion is done.\n-even though some conversions aren't supported, LodePNG supports loading PNGs from any\n colortype and saving PNGs to any colortype, sometimes it just requires preparing\n the raw image correctly before encoding.\n-both encoder and decoder use the same color converter.\n\nNon supported color conversions:\n-color to greyscale: no error is thrown, but the result will look ugly because\nonly the red channel is taken\n-anything to palette when that palette does not have that color in it: in this\ncase an error is thrown\n\nSupported color conversions:\n-anything to 8-bit RGB, 8-bit RGBA, 16-bit RGB, 16-bit RGBA\n-any grey or grey+alpha, to grey or grey+alpha\n-anything to a palette, as long as the palette has the requested colors in it\n-removing alpha channel\n-higher to smaller bitdepth, and vice versa\n\nIf you want no color conversion to be done (e.g. for speed or control):\n-In the encoder, you can make it save a PNG with any color type by giving the\nraw color mode and LodePNGInfo the same color mode, and setting auto_convert to\nfalse.\n-In the decoder, you can make it store the pixel data in the same color type\nas the PNG has, by setting the color_convert setting to false. Settings in\ninfo_raw are then ignored.\n\nThe function lodepng_convert does the color conversion. It is available in the\ninterface but normally isn't needed since the encoder and decoder already call\nit.\n\n6.3. padding bits\n-----------------\n\nIn the PNG file format, if a less than 8-bit per pixel color type is used and the scanlines\nhave a bit amount that isn't a multiple of 8, then padding bits are used so that each\nscanline starts at a fresh byte. But that is NOT true for the LodePNG raw input and output.\nThe raw input image you give to the encoder, and the raw output image you get from the decoder\nwill NOT have these padding bits, e.g. in the case of a 1-bit image with a width\nof 7 pixels, the first pixel of the second scanline will the the 8th bit of the first byte,\nnot the first bit of a new byte.\n\n6.4. A note about 16-bits per channel and endianness\n----------------------------------------------------\n\nLodePNG uses unsigned char arrays for 16-bit per channel colors too, just like\nfor any other color format. The 16-bit values are stored in big endian (most\nsignificant byte first) in these arrays. This is the opposite order of the\nlittle endian used by x86 CPU's.\n\nLodePNG always uses big endian because the PNG file format does so internally.\nConversions to other formats than PNG uses internally are not supported by\nLodePNG on purpose, there are myriads of formats, including endianness of 16-bit\ncolors, the order in which you store R, G, B and A, and so on. Supporting and\nconverting to/from all that is outside the scope of LodePNG.\n\nThis may mean that, depending on your use case, you may want to convert the big\nendian output of LodePNG to little endian with a for loop. This is certainly not\nalways needed, many applications and libraries support big endian 16-bit colors\nanyway, but it means you cannot simply cast the unsigned char* buffer to an\nunsigned short* buffer on x86 CPUs.\n\n\n7. error values\n---------------\n\nAll functions in LodePNG that return an error code, return 0 if everything went\nOK, or a non-zero code if there was an error.\n\nThe meaning of the LodePNG error values can be retrieved with the function\nlodepng_error_text: given the numerical error code, it returns a description\nof the error in English as a string.\n\nCheck the implementation of lodepng_error_text to see the meaning of each code.\n\n\n8. chunks and PNG editing\n-------------------------\n\nIf you want to add extra chunks to a PNG you encode, or use LodePNG for a PNG\neditor that should follow the rules about handling of unknown chunks, or if your\nprogram is able to read other types of chunks than the ones handled by LodePNG,\nthen that's possible with the chunk functions of LodePNG.\n\nA PNG chunk has the following layout:\n\n4 bytes length\n4 bytes type name\nlength bytes data\n4 bytes CRC\n\n8.1. iterating through chunks\n-----------------------------\n\nIf you have a buffer containing the PNG image data, then the first chunk (the\nIHDR chunk) starts at byte number 8 of that buffer. The first 8 bytes are the\nsignature of the PNG and are not part of a chunk. But if you start at byte 8\nthen you have a chunk, and can check the following things of it.\n\nNOTE: none of these functions check for memory buffer boundaries. To avoid\nexploits, always make sure the buffer contains all the data of the chunks.\nWhen using lodepng_chunk_next, make sure the returned value is within the\nallocated memory.\n\nunsigned lodepng_chunk_length(const unsigned char* chunk):\n\nGet the length of the chunk's data. The total chunk length is this length + 12.\n\nvoid lodepng_chunk_type(char type[5], const unsigned char* chunk):\nunsigned char lodepng_chunk_type_equals(const unsigned char* chunk, const char* type):\n\nGet the type of the chunk or compare if it's a certain type\n\nunsigned char lodepng_chunk_critical(const unsigned char* chunk):\nunsigned char lodepng_chunk_private(const unsigned char* chunk):\nunsigned char lodepng_chunk_safetocopy(const unsigned char* chunk):\n\nCheck if the chunk is critical in the PNG standard (only IHDR, PLTE, IDAT and IEND are).\nCheck if the chunk is private (public chunks are part of the standard, private ones not).\nCheck if the chunk is safe to copy. If it's not, then, when modifying data in a critical\nchunk, unsafe to copy chunks of the old image may NOT be saved in the new one if your\nprogram doesn't handle that type of unknown chunk.\n\nunsigned char* lodepng_chunk_data(unsigned char* chunk):\nconst unsigned char* lodepng_chunk_data_const(const unsigned char* chunk):\n\nGet a pointer to the start of the data of the chunk.\n\nunsigned lodepng_chunk_check_crc(const unsigned char* chunk):\nvoid lodepng_chunk_generate_crc(unsigned char* chunk):\n\nCheck if the crc is correct or generate a correct one.\n\nunsigned char* lodepng_chunk_next(unsigned char* chunk):\nconst unsigned char* lodepng_chunk_next_const(const unsigned char* chunk):\n\nIterate to the next chunk. This works if you have a buffer with consecutive chunks. Note that these\nfunctions do no boundary checking of the allocated data whatsoever, so make sure there is enough\ndata available in the buffer to be able to go to the next chunk.\n\nunsigned lodepng_chunk_append(unsigned char** out, size_t* outlength, const unsigned char* chunk):\nunsigned lodepng_chunk_create(unsigned char** out, size_t* outlength, unsigned length,\n                              const char* type, const unsigned char* data):\n\nThese functions are used to create new chunks that are appended to the data in *out that has\nlength *outlength. The append function appends an existing chunk to the new data. The create\nfunction creates a new chunk with the given parameters and appends it. Type is the 4-letter\nname of the chunk.\n\n8.2. chunks in info_png\n-----------------------\n\nThe LodePNGInfo struct contains fields with the unknown chunk in it. It has 3\nbuffers (each with size) to contain 3 types of unknown chunks:\nthe ones that come before the PLTE chunk, the ones that come between the PLTE\nand the IDAT chunks, and the ones that come after the IDAT chunks.\nIt's necessary to make the distionction between these 3 cases because the PNG\nstandard forces to keep the ordering of unknown chunks compared to the critical\nchunks, but does not force any other ordering rules.\n\ninfo_png.unknown_chunks_data[0] is the chunks before PLTE\ninfo_png.unknown_chunks_data[1] is the chunks after PLTE, before IDAT\ninfo_png.unknown_chunks_data[2] is the chunks after IDAT\n\nThe chunks in these 3 buffers can be iterated through and read by using the same\nway described in the previous subchapter.\n\nWhen using the decoder to decode a PNG, you can make it store all unknown chunks\nif you set the option settings.remember_unknown_chunks to 1. By default, this\noption is off (0).\n\nThe encoder will always encode unknown chunks that are stored in the info_png.\nIf you need it to add a particular chunk that isn't known by LodePNG, you can\nuse lodepng_chunk_append or lodepng_chunk_create to the chunk data in\ninfo_png.unknown_chunks_data[x].\n\nChunks that are known by LodePNG should not be added in that way. E.g. to make\nLodePNG add a bKGD chunk, set background_defined to true and add the correct\nparameters there instead.\n\n\n9. compiler support\n-------------------\n\nNo libraries other than the current standard C library are needed to compile\nLodePNG. For the C++ version, only the standard C++ library is needed on top.\nAdd the files lodepng.c(pp) and lodepng.h to your project, include\nlodepng.h where needed, and your program can read/write PNG files.\n\nIt is compatible with C90 and up, and C++03 and up.\n\nIf performance is important, use optimization when compiling! For both the\nencoder and decoder, this makes a large difference.\n\nMake sure that LodePNG is compiled with the same compiler of the same version\nand with the same settings as the rest of the program, or the interfaces with\nstd::vectors and std::strings in C++ can be incompatible.\n\nCHAR_BITS must be 8 or higher, because LodePNG uses unsigned chars for octets.\n\n*) gcc and g++\n\nLodePNG is developed in gcc so this compiler is natively supported. It gives no\nwarnings with compiler options \"-Wall -Wextra -pedantic -ansi\", with gcc and g++\nversion 4.7.1 on Linux, 32-bit and 64-bit.\n\n*) Clang\n\nFully supported and warning-free.\n\n*) Mingw\n\nThe Mingw compiler (a port of gcc for Windows) should be fully supported by\nLodePNG.\n\n*) Visual Studio and Visual C++ Express Edition\n\nLodePNG should be warning-free with warning level W4. Two warnings were disabled\nwith pragmas though: warning 4244 about implicit conversions, and warning 4996\nwhere it wants to use a non-standard function fopen_s instead of the standard C\nfopen.\n\nVisual Studio may want \"stdafx.h\" files to be included in each source file and\ngive an error \"unexpected end of file while looking for precompiled header\".\nThis is not standard C++ and will not be added to the stock LodePNG. You can\ndisable it for lodepng.cpp only by right clicking it, Properties, C/C++,\nPrecompiled Headers, and set it to Not Using Precompiled Headers there.\n\nNOTE: Modern versions of VS should be fully supported, but old versions, e.g.\nVS6, are not guaranteed to work.\n\n*) Compilers on Macintosh\n\nLodePNG has been reported to work both with gcc and LLVM for Macintosh, both for\nC and C++.\n\n*) Other Compilers\n\nIf you encounter problems on any compilers, feel free to let me know and I may\ntry to fix it if the compiler is modern and standards complient.\n\n\n10. examples\n------------\n\nThis decoder example shows the most basic usage of LodePNG. More complex\nexamples can be found on the LodePNG website.\n\n10.1. decoder C++ example\n-------------------------\n\n#include \"lodepng.h\"\n#include <iostream>\n\nint main(int argc, char *argv[])\n{\n  const char* filename = argc > 1 ? argv[1] : \"test.png\";\n\n  //load and decode\n  std::vector<unsigned char> image;\n  unsigned width, height;\n  unsigned error = lodepng::decode(image, width, height, filename);\n\n  //if there's an error, display it\n  if(error) std::cout << \"decoder error \" << error << \": \" << lodepng_error_text(error) << std::endl;\n\n  //the pixels are now in the vector \"image\", 4 bytes per pixel, ordered RGBARGBA..., use it as texture, draw it, ...\n}\n\n10.2. decoder C example\n-----------------------\n\n#include \"lodepng.h\"\n\nint main(int argc, char *argv[])\n{\n  unsigned error;\n  unsigned char* image;\n  size_t width, height;\n  const char* filename = argc > 1 ? argv[1] : \"test.png\";\n\n  error = lodepng_decode32_file(&image, &width, &height, filename);\n\n  if(error) printf(\"decoder error %u: %s\\n\", error, lodepng_error_text(error));\n\n  / * use image here * /\n\n  free(image);\n  return 0;\n}\n\n11. state settings reference\n----------------------------\n\nA quick reference of some settings to set on the LodePNGState\n\nFor decoding:\n\nstate.decoder.zlibsettings.ignore_adler32: ignore ADLER32 checksums\nstate.decoder.zlibsettings.custom_...: use custom inflate function\nstate.decoder.ignore_crc: ignore CRC checksums\nstate.decoder.ignore_critical: ignore unknown critical chunks\nstate.decoder.ignore_end: ignore missing IEND chunk. May fail if this corruption causes other errors\nstate.decoder.color_convert: convert internal PNG color to chosen one\nstate.decoder.read_text_chunks: whether to read in text metadata chunks\nstate.decoder.remember_unknown_chunks: whether to read in unknown chunks\nstate.info_raw.colortype: desired color type for decoded image\nstate.info_raw.bitdepth: desired bit depth for decoded image\nstate.info_raw....: more color settings, see struct LodePNGColorMode\nstate.info_png....: no settings for decoder but ouput, see struct LodePNGInfo\n\nFor encoding:\n\nstate.encoder.zlibsettings.btype: disable compression by setting it to 0\nstate.encoder.zlibsettings.use_lz77: use LZ77 in compression\nstate.encoder.zlibsettings.windowsize: tweak LZ77 windowsize\nstate.encoder.zlibsettings.minmatch: tweak min LZ77 length to match\nstate.encoder.zlibsettings.nicematch: tweak LZ77 match where to stop searching\nstate.encoder.zlibsettings.lazymatching: try one more LZ77 matching\nstate.encoder.zlibsettings.custom_...: use custom deflate function\nstate.encoder.auto_convert: choose optimal PNG color type, if 0 uses info_png\nstate.encoder.filter_palette_zero: PNG filter strategy for palette\nstate.encoder.filter_strategy: PNG filter strategy to encode with\nstate.encoder.force_palette: add palette even if not encoding to one\nstate.encoder.add_id: add LodePNG identifier and version as a text chunk\nstate.encoder.text_compression: use compressed text chunks for metadata\nstate.info_raw.colortype: color type of raw input image you provide\nstate.info_raw.bitdepth: bit depth of raw input image you provide\nstate.info_raw: more color settings, see struct LodePNGColorMode\nstate.info_png.color.colortype: desired color type if auto_convert is false\nstate.info_png.color.bitdepth: desired bit depth if auto_convert is false\nstate.info_png.color....: more color settings, see struct LodePNGColorMode\nstate.info_png....: more PNG related settings, see struct LodePNGInfo\n\n\n12. changes\n-----------\n\nThe version number of LodePNG is the date of the change given in the format\nyyyymmdd.\n\nSome changes aren't backwards compatible. Those are indicated with a (!)\nsymbol.\n\n*) 14 jan 2018: allow optionally ignoring a few more recoverable errors\n*) 17 sep 2017: fix memory leak for some encoder input error cases\n*) 27 nov 2016: grey+alpha auto color model detection bugfix\n*) 18 apr 2016: Changed qsort to custom stable sort (for platforms w/o qsort).\n*) 09 apr 2016: Fixed colorkey usage detection, and better file loading (within\n   the limits of pure C90).\n*) 08 dec 2015: Made load_file function return error if file can't be opened.\n*) 24 okt 2015: Bugfix with decoding to palette output.\n*) 18 apr 2015: Boundary PM instead of just package-merge for faster encoding.\n*) 23 aug 2014: Reduced needless memory usage of decoder.\n*) 28 jun 2014: Removed fix_png setting, always support palette OOB for\n    simplicity. Made ColorProfile public.\n*) 09 jun 2014: Faster encoder by fixing hash bug and more zeros optimization.\n*) 22 dec 2013: Power of two windowsize required for optimization.\n*) 15 apr 2013: Fixed bug with LAC_ALPHA and color key.\n*) 25 mar 2013: Added an optional feature to ignore some PNG errors (fix_png).\n*) 11 mar 2013 (!): Bugfix with custom free. Changed from \"my\" to \"lodepng_\"\n    prefix for the custom allocators and made it possible with a new #define to\n    use custom ones in your project without needing to change lodepng's code.\n*) 28 jan 2013: Bugfix with color key.\n*) 27 okt 2012: Tweaks in text chunk keyword length error handling.\n*) 8 okt 2012 (!): Added new filter strategy (entropy) and new auto color mode.\n    (no palette). Better deflate tree encoding. New compression tweak settings.\n    Faster color conversions while decoding. Some internal cleanups.\n*) 23 sep 2012: Reduced warnings in Visual Studio a little bit.\n*) 1 sep 2012 (!): Removed #define's for giving custom (de)compression functions\n    and made it work with function pointers instead.\n*) 23 jun 2012: Added more filter strategies. Made it easier to use custom alloc\n    and free functions and toggle #defines from compiler flags. Small fixes.\n*) 6 may 2012 (!): Made plugging in custom zlib/deflate functions more flexible.\n*) 22 apr 2012 (!): Made interface more consistent, renaming a lot. Removed\n    redundant C++ codec classes. Reduced amount of structs. Everything changed,\n    but it is cleaner now imho and functionality remains the same. Also fixed\n    several bugs and shrunk the implementation code. Made new samples.\n*) 6 nov 2011 (!): By default, the encoder now automatically chooses the best\n    PNG color model and bit depth, based on the amount and type of colors of the\n    raw image. For this, autoLeaveOutAlphaChannel replaced by auto_choose_color.\n*) 9 okt 2011: simpler hash chain implementation for the encoder.\n*) 8 sep 2011: lz77 encoder lazy matching instead of greedy matching.\n*) 23 aug 2011: tweaked the zlib compression parameters after benchmarking.\n    A bug with the PNG filtertype heuristic was fixed, so that it chooses much\n    better ones (it's quite significant). A setting to do an experimental, slow,\n    brute force search for PNG filter types is added.\n*) 17 aug 2011 (!): changed some C zlib related function names.\n*) 16 aug 2011: made the code less wide (max 120 characters per line).\n*) 17 apr 2011: code cleanup. Bugfixes. Convert low to 16-bit per sample colors.\n*) 21 feb 2011: fixed compiling for C90. Fixed compiling with sections disabled.\n*) 11 dec 2010: encoding is made faster, based on suggestion by Peter Eastman\n    to optimize long sequences of zeros.\n*) 13 nov 2010: added LodePNG_InfoColor_hasPaletteAlpha and\n    LodePNG_InfoColor_canHaveAlpha functions for convenience.\n*) 7 nov 2010: added LodePNG_error_text function to get error code description.\n*) 30 okt 2010: made decoding slightly faster\n*) 26 okt 2010: (!) changed some C function and struct names (more consistent).\n     Reorganized the documentation and the declaration order in the header.\n*) 08 aug 2010: only changed some comments and external samples.\n*) 05 jul 2010: fixed bug thanks to warnings in the new gcc version.\n*) 14 mar 2010: fixed bug where too much memory was allocated for char buffers.\n*) 02 sep 2008: fixed bug where it could create empty tree that linux apps could\n    read by ignoring the problem but windows apps couldn't.\n*) 06 jun 2008: added more error checks for out of memory cases.\n*) 26 apr 2008: added a few more checks here and there to ensure more safety.\n*) 06 mar 2008: crash with encoding of strings fixed\n*) 02 feb 2008: support for international text chunks added (iTXt)\n*) 23 jan 2008: small cleanups, and #defines to divide code in sections\n*) 20 jan 2008: support for unknown chunks allowing using LodePNG for an editor.\n*) 18 jan 2008: support for tIME and pHYs chunks added to encoder and decoder.\n*) 17 jan 2008: ability to encode and decode compressed zTXt chunks added\n    Also various fixes, such as in the deflate and the padding bits code.\n*) 13 jan 2008: Added ability to encode Adam7-interlaced images. Improved\n    filtering code of encoder.\n*) 07 jan 2008: (!) changed LodePNG to use ISO C90 instead of C++. A\n    C++ wrapper around this provides an interface almost identical to before.\n    Having LodePNG be pure ISO C90 makes it more portable. The C and C++ code\n    are together in these files but it works both for C and C++ compilers.\n*) 29 dec 2007: (!) changed most integer types to unsigned int + other tweaks\n*) 30 aug 2007: bug fixed which makes this Borland C++ compatible\n*) 09 aug 2007: some VS2005 warnings removed again\n*) 21 jul 2007: deflate code placed in new namespace separate from zlib code\n*) 08 jun 2007: fixed bug with 2- and 4-bit color, and small interlaced images\n*) 04 jun 2007: improved support for Visual Studio 2005: crash with accessing\n    invalid std::vector element [0] fixed, and level 3 and 4 warnings removed\n*) 02 jun 2007: made the encoder add a tag with version by default\n*) 27 may 2007: zlib and png code separated (but still in the same file),\n    simple encoder/decoder functions added for more simple usage cases\n*) 19 may 2007: minor fixes, some code cleaning, new error added (error 69),\n    moved some examples from here to lodepng_examples.cpp\n*) 12 may 2007: palette decoding bug fixed\n*) 24 apr 2007: changed the license from BSD to the zlib license\n*) 11 mar 2007: very simple addition: ability to encode bKGD chunks.\n*) 04 mar 2007: (!) tEXt chunk related fixes, and support for encoding\n    palettized PNG images. Plus little interface change with palette and texts.\n*) 03 mar 2007: Made it encode dynamic Huffman shorter with repeat codes.\n    Fixed a bug where the end code of a block had length 0 in the Huffman tree.\n*) 26 feb 2007: Huffman compression with dynamic trees (BTYPE 2) now implemented\n    and supported by the encoder, resulting in smaller PNGs at the output.\n*) 27 jan 2007: Made the Adler-32 test faster so that a timewaste is gone.\n*) 24 jan 2007: gave encoder an error interface. Added color conversion from any\n    greyscale type to 8-bit greyscale with or without alpha.\n*) 21 jan 2007: (!) Totally changed the interface. It allows more color types\n    to convert to and is more uniform. See the manual for how it works now.\n*) 07 jan 2007: Some cleanup & fixes, and a few changes over the last days:\n    encode/decode custom tEXt chunks, separate classes for zlib & deflate, and\n    at last made the decoder give errors for incorrect Adler32 or Crc.\n*) 01 jan 2007: Fixed bug with encoding PNGs with less than 8 bits per channel.\n*) 29 dec 2006: Added support for encoding images without alpha channel, and\n    cleaned out code as well as making certain parts faster.\n*) 28 dec 2006: Added \"Settings\" to the encoder.\n*) 26 dec 2006: The encoder now does LZ77 encoding and produces much smaller files now.\n    Removed some code duplication in the decoder. Fixed little bug in an example.\n*) 09 dec 2006: (!) Placed output parameters of public functions as first parameter.\n    Fixed a bug of the decoder with 16-bit per color.\n*) 15 okt 2006: Changed documentation structure\n*) 09 okt 2006: Encoder class added. It encodes a valid PNG image from the\n    given image buffer, however for now it's not compressed.\n*) 08 sep 2006: (!) Changed to interface with a Decoder class\n*) 30 jul 2006: (!) LodePNG_InfoPng , width and height are now retrieved in different\n    way. Renamed decodePNG to decodePNGGeneric.\n*) 29 jul 2006: (!) Changed the interface: image info is now returned as a\n    struct of type LodePNG::LodePNG_Info, instead of a vector, which was a bit clumsy.\n*) 28 jul 2006: Cleaned the code and added new error checks.\n    Corrected terminology \"deflate\" into \"inflate\".\n*) 23 jun 2006: Added SDL example in the documentation in the header, this\n    example allows easy debugging by displaying the PNG and its transparency.\n*) 22 jun 2006: (!) Changed way to obtain error value. Added\n    loadFile function for convenience. Made decodePNG32 faster.\n*) 21 jun 2006: (!) Changed type of info vector to unsigned.\n    Changed position of palette in info vector. Fixed an important bug that\n    happened on PNGs with an uncompressed block.\n*) 16 jun 2006: Internally changed unsigned into unsigned where\n    needed, and performed some optimizations.\n*) 07 jun 2006: (!) Renamed functions to decodePNG and placed them\n    in LodePNG namespace. Changed the order of the parameters. Rewrote the\n    documentation in the header. Renamed files to lodepng.cpp and lodepng.h\n*) 22 apr 2006: Optimized and improved some code\n*) 07 sep 2005: (!) Changed to std::vector interface\n*) 12 aug 2005: Initial release (C++, decoder only)\n\n\n13. contact information\n-----------------------\n\nFeel free to contact me with suggestions, problems, comments, ... concerning\nLodePNG. If you encounter a PNG image that doesn't work properly with this\ndecoder, feel free to send it and I'll use it to find and fix the problem.\n\nMy email address is (puzzle the account and domain together with an @ symbol):\nDomain: gmail dot com.\nAccount: lode dot vandevenne.\n\n\nCopyright (c) 2005-2017 Lode Vandevenne\n*/\n"
  },
  {
    "path": "src/main.cpp",
    "content": "/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n#include <sstream>\n#include <exception>\n#include <cassert>\n#include \"version.h\"\n#include \"Engine/Exception.h\"\n#include \"Engine/Logger.h\"\n#include \"Engine/CrossPlatform.h\"\n#include \"Engine/Game.h\"\n#include \"Engine/Options.h\"\n#include \"Engine/FileMap.h\"\n#include \"Menu/StartState.h\"\n\n/** @mainpage\n * @author OpenXcom Developers\n *\n * OpenXcom is an open-source clone of the original X-Com\n * written entirely in C++ and SDL. This documentation contains info\n * on every class contained in the source code and its public methods.\n * The code itself also contains in-line comments for more complicated\n * code blocks. Hopefully all of this will make the code a lot more\n * readable for you in case you which to learn or make use of it in\n * your own projects, though note that all the source code is licensed\n * under the GNU General Public License. Enjoy!\n */\n\nusing namespace OpenXcom;\n\n// Crash handling routines\n#ifdef _MSC_VER\n\n#ifndef NOMINMAX\n#define NOMINMAX\n#endif\n\n#include <windows.h>\n\nLONG WINAPI crashLogger(PEXCEPTION_POINTERS exception)\n{\n\tCrossPlatform::crashDump(exception, \"\");\n\treturn EXCEPTION_CONTINUE_SEARCH;\n}\n#else\n#include <signal.h>\nvoid signalLogger(int sig)\n{\n\tCrossPlatform::crashDump(&sig, \"\");\n\texit(EXIT_FAILURE);\n}\n\n#endif\n\nvoid exceptionLogger()\n{\n\tstatic bool logged = false;\n\tstd::string error;\n\ttry\n\t{\n\t\tif (!logged)\n\t\t{\n\t\t\tlogged = true;\n\t\t\tthrow;\n\t\t}\n\t}\n\tcatch (const std::exception &e)\n\t{\n\t\terror = e.what();\n\t}\n\tcatch (...)\n\t{\n\t\terror = \"Unknown exception\";\n\t}\n\tCrossPlatform::crashDump(0, error);\n\texit(EXIT_FAILURE);\n}\n\nGame *game = 0;\n\n// If you can't tell what the main() is for you should have your\n// programming license revoked...\nint main(int argc, char *argv[])\n{\n#ifndef DUMP_CORE\n#ifdef _MSC_VER\n\t// Uncomment to check memory leaks in VS\n\t//_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );\n\n\tSetUnhandledExceptionFilter(crashLogger);\n#ifdef __MINGW32__\n\t// MinGW can use SJLJ or Dwarf exceptions, because of this SEH can't catch it.\n\tstd::set_terminate(exceptionLogger);\n#endif\n\t// Uncomment to debug crash handler\n\t// AddVectoredContinueHandler(1, crashLogger);\n#else\n\tsignal(SIGSEGV, signalLogger);\n\tstd::set_terminate(exceptionLogger);\n#endif\n#endif\n\tYAML::setGlobalErrorHandler();\n\tCrossPlatform::getErrorDialog();\n\tCrossPlatform::processArgs(argc, argv);\n\tif (!Options::init())\n\t\treturn EXIT_SUCCESS;\n\tstd::ostringstream title;\n\ttitle << \"OpenXcom \" << OPENXCOM_VERSION_SHORT << OPENXCOM_VERSION_GIT;\n\tOptions::baseXResolution = Options::displayWidth;\n\tOptions::baseYResolution = Options::displayHeight;\n\n\tgame = new Game(title.str());\n\tState::setGamePtr(game);\n\tgame->setState(new StartState);\n\tgame->run();\n\n\tbool startUpdate = game->getUpdateFlag();\n\n\t// Comment those two for faster exit.\n\tdelete game;\n\tFileMap::clear(true, false); // make valgrind happy\n\n\tif (startUpdate)\n\t{\n\t\tCrossPlatform::startUpdateProcess();\n\t}\n\n\treturn EXIT_SUCCESS;\n}\n\nnamespace OpenXcom\n{\n\tException::Exception(const std::string &msg) : runtime_error(msg) {\n#ifdef DUMP_CORE\n\t\t__builtin_trap();\n#endif\n\t}\n}\n\n#ifdef __MORPHOS__\nconst char Version[] = \"$VER: OpenXCom \" OPENXCOM_VERSION_SHORT \" (\" __AMIGADATE__  \")\";\n#endif\n\n\n\n#ifndef NDEBUG\n\n#include \"Engine/Collections.h\"\n#include \"fmath.h\"\n\nstruct BadMove\n{\n\tint i;\n\n\tBadMove(int b)\n\t{\n\t\ti = b;\n\t}\n\tBadMove(BadMove&& b)\n\t{\n\t\ti = b.i;\n\t\tb.i = {};\n\t}\n\tBadMove(const BadMove& b)\n\t{\n\t\ti = b.i;\n\t}\n\n\tBadMove& operator=(BadMove&& b)\n\t{\n\t\ti = {}; //this can reset other `b` too if we do not check for `this == &b`\n\t\ti = b.i;\n\t\tb.i = {}; //same there\n\t\treturn *this;\n\t}\n\n\tbool operator==(const BadMove& b) const\n\t{\n\t\treturn i == b.i;\n\t}\n};\n\nstatic auto dummy = ([]\n{\n\t{\n\t\tstd::vector<int> v = { 1, 2, 3, 4 };\n\t\tCollections::removeIf(v, [](int& i) { return i < 3; });\n\t\tassert((v == std::vector<int>{ 3, 4 }));\n\t}\n\t{\n\t\tstd::vector<int> v = { 1, 2, 3, 4 };\n\t\tCollections::removeIf(v, [](int& i) { return i > 2; });\n\t\tassert((v == std::vector<int>{ 1, 2 }));\n\t}\n\t{\n\t\tstd::vector<int> v = { 1, 2, 3, 4 };\n\t\tCollections::removeIf(v, [](int& i) { return i < 2 || i == 4; });\n\t\tassert((v == std::vector<int>{ 2, 3 }));\n\t}\n\t{\n\t\tstd::vector<int> v = { 1, 2, 3, 4 };\n\t\tCollections::removeIf(v, [](int& i) { if (i < 2 || i == 4) { return true; } else { i += 10; return false; } });\n\t\tassert((v == std::vector<int>{ 12, 13 }));\n\t}\n\t{\n\t\tstd::vector<int> v = { 1, 2, 3, 4 };\n\t\tCollections::removeIf(v, [](int& i) { return false; });\n\t\tassert((v == std::vector<int>{ 1, 2, 3, 4 }));\n\t}\n\t{\n\t\tstd::vector<int> v = { 1, 2, 3, 4 };\n\t\tCollections::removeIf(v, [](int& i) { return true; });\n\t\tassert((v == std::vector<int>{ }));\n\t}\n\t{\n\t\tstd::vector<int> v = { 1, 2, 3, 4 };\n\t\tCollections::removeIf(v, [](int& i) { i += 10; return false; });\n\t\tassert((v == std::vector<int>{ 11, 12, 13, 14 }));\n\t}\n\n\t{\n\t\tstd::vector<BadMove> v = { 1, 2, 3, 4 };\n\t\tCollections::removeIf(v, [](BadMove& i) { return i.i < 3; });\n\t\tassert((v == std::vector<BadMove>{ 3, 4 }));\n\t}\n\t{\n\t\tstd::vector<BadMove> v = { 1, 2, 3, 4 };\n\t\tCollections::removeIf(v, [](BadMove& i) { return i.i > 2; });\n\t\tassert((v == std::vector<BadMove>{ 1, 2 }));\n\t}\n\t{\n\t\tstd::vector<BadMove> v = { 1, 2, 3, 4 };\n\t\tCollections::removeIf(v, [](BadMove& i) { if (i.i < 2 || i.i == 4) { return true; } else { i.i += 10; return false; } });\n\t\tassert((v == std::vector<BadMove>{ 12, 13 }));\n\t}\n\t{\n\t\tstd::vector<BadMove> v = { 1, 2, 3, 4 };\n\t\tCollections::removeIf(v, [](BadMove& i) { return false; });\n\t\tassert((v == std::vector<BadMove>{ 1, 2, 3, 4 }));\n\t}\n\t{\n\t\tstd::vector<BadMove> v = { 1, 2, 3, 4 };\n\t\tCollections::removeIf(v, [](BadMove& i) { i.i += 10; return false; });\n\t\tassert((v == std::vector<BadMove>{ 11, 12, 13, 14 }));\n\t}\n\t{\n\t\tstd::vector<BadMove> v = { 1, 2, 3, 4 };\n\t\tCollections::removeIf(v, [](BadMove& i) { return true; });\n\t\tassert((v == std::vector<BadMove>{ }));\n\t}\n\n\treturn 0;\n})();\n\nstruct DummyVectDouble\n{\n\tdouble x, y, z;\n\n\tbool operator==(const DummyVectDouble& a) const { return AreSame(x, a.x) && AreSame(y, a.y) && AreSame(z, a.z); };\n};\n\nstatic auto dummyMath = ([]\n{\n\tconst DummyVectDouble x { 1, 0, 0 };\n\tconst DummyVectDouble y { 0, 1, 0 };\n\tconst DummyVectDouble z { 0, 0, 1 };\n\n\tconst DummyVectDouble x256 { 256, 0, 0 };\n\tconst DummyVectDouble y256 { 0, 256, 0 };\n\tconst DummyVectDouble z256 { 0, 0, 256 };\n\n\tassert(x == VectNormalize(x));\n\tassert(y == VectNormalize(y));\n\tassert(z == VectNormalize(z));\n\tassert(x == VectNormalize(x256));\n\tassert(y == VectNormalize(y256));\n\tassert(z == VectNormalize(z256));\n\tassert(x256 == VectNormalize(x256, 256));\n\tassert(y256 == VectNormalize(y256, 256));\n\tassert(z256 == VectNormalize(z256, 256));\n\n\tassert(z == VectCrossProduct(x, y));\n\tassert(x == VectCrossProduct(y, z));\n\tassert(y == VectCrossProduct(z, x));\n\n\tassert(z256 == VectCrossProduct(x256, y));\n\tassert(x256 == VectCrossProduct(y256, z));\n\tassert(y256 == VectCrossProduct(z256, x));\n\n\tassert(z256 == VectCrossProduct(x256, y256, 256));\n\tassert(x256 == VectCrossProduct(y256, z256, 256));\n\tassert(y256 == VectCrossProduct(z256, x256, 256));\n\n\treturn 0;\n})();\n\n#endif\n"
  },
  {
    "path": "src/md5.cpp",
    "content": "/* MD5\n converted to C++ class by Frank Thilo (thilo@unix-ag.org)\n for bzflag (http://www.bzflag.org)\n \n   based on:\n \n   md5.h and md5.c\n   reference implementation of RFC 1321\n \n   Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All\nrights reserved.\n \nLicense to copy and use this software is granted provided that it\nis identified as the \"RSA Data Security, Inc. MD5 Message-Digest\nAlgorithm\" in all material mentioning or referencing this software\nor this function.\n \nLicense is also granted to make and use derivative works provided\nthat such works are identified as \"derived from the RSA Data\nSecurity, Inc. MD5 Message-Digest Algorithm\" in all material\nmentioning or referencing the derived work.\n \nRSA Data Security, Inc. makes no representations concerning either\nthe merchantability of this software or the suitability of this\nsoftware for any particular purpose. It is provided \"as is\"\nwithout express or implied warranty of any kind.\n \nThese notices must be retained in any copies of any part of this\ndocumentation and/or software.\n \n*/\n \n/* interface header */\n#include \"md5.h\"\n \n/* system implementation headers */\n#include <cstdio>\n \n \n// Constants for MD5Transform routine.\n#define S11 7\n#define S12 12\n#define S13 17\n#define S14 22\n#define S21 5\n#define S22 9\n#define S23 14\n#define S24 20\n#define S31 4\n#define S32 11\n#define S33 16\n#define S34 23\n#define S41 6\n#define S42 10\n#define S43 15\n#define S44 21\n \n///////////////////////////////////////////////\n \n// F, G, H and I are basic MD5 functions.\ninline MD5::uint4 MD5::F(uint4 x, uint4 y, uint4 z) {\n  return (x&y) | (~x&z);\n}\n \ninline MD5::uint4 MD5::G(uint4 x, uint4 y, uint4 z) {\n  return (x&z) | (y&~z);\n}\n \ninline MD5::uint4 MD5::H(uint4 x, uint4 y, uint4 z) {\n  return x^y^z;\n}\n \ninline MD5::uint4 MD5::I(uint4 x, uint4 y, uint4 z) {\n  return y ^ (x | ~z);\n}\n \n// rotate_left rotates x left n bits.\ninline MD5::uint4 MD5::rotate_left(uint4 x, int n) {\n  return (x << n) | (x >> (32-n));\n}\n \n// FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.\n// Rotation is separate from addition to prevent recomputation.\ninline void MD5::FF(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {\n  a = rotate_left(a+ F(b,c,d) + x + ac, s) + b;\n}\n \ninline void MD5::GG(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {\n  a = rotate_left(a + G(b,c,d) + x + ac, s) + b;\n}\n \ninline void MD5::HH(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {\n  a = rotate_left(a + H(b,c,d) + x + ac, s) + b;\n}\n \ninline void MD5::II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {\n  a = rotate_left(a + I(b,c,d) + x + ac, s) + b;\n}\n \n//////////////////////////////////////////////\n \n// default ctor, just initailize\nMD5::MD5()\n{\n  init();\n}\n \n//////////////////////////////////////////////\n \n// nifty shortcut ctor, compute MD5 for string and finalize it right away\nMD5::MD5(const std::string &text)\n{\n  init();\n  update(text.c_str(), text.length());\n  finalize();\n}\n \n//////////////////////////////\n \nvoid MD5::init()\n{\n  finalized=false;\n \n  count[0] = 0;\n  count[1] = 0;\n \n  // load magic initialization constants.\n  state[0] = 0x67452301;\n  state[1] = 0xefcdab89;\n  state[2] = 0x98badcfe;\n  state[3] = 0x10325476;\n}\n \n//////////////////////////////\n \n// decodes input (unsigned char) into output (uint4). Assumes len is a multiple of 4.\nvoid MD5::decode(uint4 output[], const uint1 input[], size_type len)\n{\n  for (unsigned int i = 0, j = 0; j < len; i++, j += 4)\n    output[i] = ((uint4)input[j]) | (((uint4)input[j+1]) << 8) |\n      (((uint4)input[j+2]) << 16) | (((uint4)input[j+3]) << 24);\n}\n \n//////////////////////////////\n \n// encodes input (uint4) into output (unsigned char). Assumes len is\n// a multiple of 4.\nvoid MD5::encode(uint1 output[], const uint4 input[], size_type len)\n{\n  for (size_type i = 0, j = 0; j < len; i++, j += 4) {\n    output[j] = input[i] & 0xff;\n    output[j+1] = (input[i] >> 8) & 0xff;\n    output[j+2] = (input[i] >> 16) & 0xff;\n    output[j+3] = (input[i] >> 24) & 0xff;\n  }\n}\n \n//////////////////////////////\n \n// apply MD5 algo on a block\nvoid MD5::transform(const uint1 block[blocksize])\n{\n  uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];\n  decode (x, block, blocksize);\n \n  /* Round 1 */\n  FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */\n  FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */\n  FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */\n  FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */\n  FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */\n  FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */\n  FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */\n  FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */\n  FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */\n  FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */\n  FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */\n  FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */\n  FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */\n  FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */\n  FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */\n  FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */\n \n  /* Round 2 */\n  GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */\n  GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */\n  GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */\n  GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */\n  GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */\n  GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */\n  GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */\n  GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */\n  GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */\n  GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */\n  GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */\n  GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */\n  GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */\n  GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */\n  GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */\n  GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */\n \n  /* Round 3 */\n  HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */\n  HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */\n  HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */\n  HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */\n  HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */\n  HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */\n  HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */\n  HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */\n  HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */\n  HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */\n  HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */\n  HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */\n  HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */\n  HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */\n  HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */\n  HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */\n \n  /* Round 4 */\n  II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */\n  II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */\n  II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */\n  II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */\n  II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */\n  II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */\n  II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */\n  II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */\n  II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */\n  II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */\n  II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */\n  II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */\n  II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */\n  II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */\n  II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */\n  II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */\n \n  state[0] += a;\n  state[1] += b;\n  state[2] += c;\n  state[3] += d;\n \n  // Zeroize sensitive information.\n  memset(x, 0, sizeof x);\n}\n \n//////////////////////////////\n \n// MD5 block update operation. Continues an MD5 message-digest\n// operation, processing another message block\nvoid MD5::update(const unsigned char input[], size_type length)\n{\n  // compute number of bytes mod 64\n  size_type index = count[0] / 8 % blocksize;\n \n  // Update number of bits\n  if ((count[0] += (length << 3)) < (length << 3))\n    count[1]++;\n  count[1] += (length >> 29);\n \n  // number of bytes we need to fill in buffer\n  size_type firstpart = 64 - index;\n \n  size_type i;\n \n  // transform as many times as possible.\n  if (length >= firstpart)\n  {\n    // fill buffer first, transform\n    memcpy(&buffer[index], input, firstpart);\n    transform(buffer);\n \n    // transform chunks of blocksize (64 bytes)\n    for (i = firstpart; i + blocksize <= length; i += blocksize)\n      transform(&input[i]);\n \n    index = 0;\n  }\n  else\n    i = 0;\n \n  // buffer remaining input\n  memcpy(&buffer[index], &input[i], length-i);\n}\n \n//////////////////////////////\n \n// for convenience provide a verson with signed char\nvoid MD5::update(const char input[], size_type length)\n{\n  update((const unsigned char*)input, length);\n}\n \n//////////////////////////////\n \n// MD5 finalization. Ends an MD5 message-digest operation, writing the\n// the message digest and zeroizing the context.\nMD5& MD5::finalize()\n{\n  static unsigned char padding[64] = {\n    0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\n  };\n \n  if (!finalized) {\n    // Save number of bits\n    unsigned char bits[8];\n    encode(bits, count, 8);\n \n    // pad out to 56 mod 64.\n    size_type index = count[0] / 8 % 64;\n    size_type padLen = (index < 56) ? (56 - index) : (120 - index);\n    update(padding, padLen);\n \n    // Append length (before padding)\n    update(bits, 8);\n \n    // Store state in digest\n    encode(digest, state, 16);\n \n    // Zeroize sensitive information.\n    memset(buffer, 0, sizeof buffer);\n    memset(count, 0, sizeof count);\n \n    finalized=true;\n  }\n \n  return *this;\n}\n \n//////////////////////////////\n \n// return hex representation of digest as string\nstd::string MD5::hexdigest() const\n{\n  if (!finalized)\n    return \"\";\n \n  char buf[33];\n  for (int i=0; i<16; i++)\n    sprintf(buf+i*2, \"%02x\", digest[i]);\n  buf[32]=0;\n \n  return std::string(buf);\n}\n \n//////////////////////////////\n \nstd::ostream& operator<<(std::ostream& out, MD5 md5)\n{\n  return out << md5.hexdigest();\n}\n \n//////////////////////////////\n \nstd::string md5(const std::string str)\n{\n    MD5 md5 = MD5(str);\n \n    return md5.hexdigest();\n}\n"
  },
  {
    "path": "src/md5.h",
    "content": "/* MD5\n converted to C++ class by Frank Thilo (thilo@unix-ag.org)\n for bzflag (http://www.bzflag.org)\n \n   based on:\n \n   md5.h and md5.c\n   reference implementation of RFC 1321\n \n   Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All\nrights reserved.\n \nLicense to copy and use this software is granted provided that it\nis identified as the \"RSA Data Security, Inc. MD5 Message-Digest\nAlgorithm\" in all material mentioning or referencing this software\nor this function.\n \nLicense is also granted to make and use derivative works provided\nthat such works are identified as \"derived from the RSA Data\nSecurity, Inc. MD5 Message-Digest Algorithm\" in all material\nmentioning or referencing the derived work.\n \nRSA Data Security, Inc. makes no representations concerning either\nthe merchantability of this software or the suitability of this\nsoftware for any particular purpose. It is provided \"as is\"\nwithout express or implied warranty of any kind.\n \nThese notices must be retained in any copies of any part of this\ndocumentation and/or software.\n \n*/\n \n#ifndef BZF_MD5_H\n#define BZF_MD5_H\n \n#include <cstring>\n#include <iostream>\n \n \n// a small class for calculating MD5 hashes of strings or byte arrays\n// it is not meant to be fast or secure\n//\n// usage: 1) feed it blocks of uchars with update()\n//      2) finalize()\n//      3) get hexdigest() string\n//      or\n//      MD5(std::string).hexdigest()\n//\n// assumes that char is 8 bit and int is 32 bit\nclass MD5\n{\npublic:\n  typedef unsigned int size_type; // must be 32bit\n \n  MD5();\n  MD5(const std::string& text);\n  void update(const unsigned char *buf, size_type length);\n  void update(const char *buf, size_type length);\n  MD5& finalize();\n  std::string hexdigest() const;\n  friend std::ostream& operator<<(std::ostream&, MD5 md5);\n \nprivate:\n  void init();\n  typedef unsigned char uint1; //  8bit\n  typedef unsigned int uint4;  // 32bit\n  enum {blocksize = 64}; // VC6 won't eat a const static int here\n \n  void transform(const uint1 block[blocksize]);\n  static void decode(uint4 output[], const uint1 input[], size_type len);\n  static void encode(uint1 output[], const uint4 input[], size_type len);\n \n  bool finalized;\n  uint1 buffer[blocksize]; // bytes that didn't fit in last 64 byte chunk\n  uint4 count[2];   // 64bit counter for number of bits (lo, hi)\n  uint4 state[4];   // digest so far\n  uint1 digest[16]; // the result\n \n  // low level logic operations\n  static inline uint4 F(uint4 x, uint4 y, uint4 z);\n  static inline uint4 G(uint4 x, uint4 y, uint4 z);\n  static inline uint4 H(uint4 x, uint4 y, uint4 z);\n  static inline uint4 I(uint4 x, uint4 y, uint4 z);\n  static inline uint4 rotate_left(uint4 x, int n);\n  static inline void FF(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);\n  static inline void GG(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);\n  static inline void HH(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);\n  static inline void II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);\n};\n \nstd::string md5(const std::string str);\n \n#endif\n"
  },
  {
    "path": "src/resource.h",
    "content": "//{{NO_DEPENDENCIES}}\n// Microsoft Visual C++ generated include file.\n// Used by OpenXcom.rc\n//\n#define IDI_ICON1                       101\n\n// Next default values for new objects\n// \n#ifdef APSTUDIO_INVOKED\n#ifndef APSTUDIO_READONLY_SYMBOLS\n#define _APS_NEXT_RESOURCE_VALUE        102\n#define _APS_NEXT_COMMAND_VALUE         40001\n#define _APS_NEXT_CONTROL_VALUE         1001\n#define _APS_NEXT_SYMED_VALUE           101\n#endif\n#endif\n\n#define IDZ_COMMON_ZIP                  256\n#define IDZ_STANDARD_ZIP                257\n"
  },
  {
    "path": "src/ryml.natvis",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?> \n\n<!--\nVery good intro:\n@see https://docs.microsoft.com/en-us/visualstudio/debugger/create-custom-views-of-native-objects?view=vs-2017\n@see https://code.msdn.microsoft.com/windowsdesktop/Writing-type-visualizers-2eae77a2\nSee also:\n@see http://blogs.msdn.com/b/vcblog/archive/2013/06/28/using-visual-studio-2013-to-write-maintainable-native-visualizations-natvis.aspx?PageIndex=2\n@see http://blogs.msdn.com/b/vcblog/archive/2015/09/28/debug-visualizers-in-visual-c-2015.aspx\n@see http://stackoverflow.com/questions/36883414/limit-display-of-char-in-natvis-file-to-specific-length\n-->\n\n<AutoVisualizer xmlns=\"http://schemas.microsoft.com/vstudio/debugger/natvis/2010\">\n\n  <Type Name=\"c4::yml::NodeScalar\">\n    <DisplayString Condition=\"(tag.len == 0) &amp;&amp; (anchor.len == 0)\">{scalar.str,[scalar.len]}</DisplayString>\n    <DisplayString Condition=\"(tag.len >  0) &amp;&amp; (anchor.len == 0)\">{scalar.str,[scalar.len]} [T]</DisplayString>\n    <DisplayString Condition=\"(tag.len == 0) &amp;&amp; (anchor.len >  0)\">{scalar.str,[scalar.len]} [A]</DisplayString>\n    <DisplayString Condition=\"(tag.len >  0) &amp;&amp; (anchor.len >  0)\">{scalar.str,[scalar.len]} [T][A]</DisplayString>\n    <Expand>\n      <Item Name=\"scalar\">scalar</Item>\n      <Item Name=\"tag\">tag</Item>\n      <Item Name=\"anchor\">anchor</Item>\n    </Expand>\n  </Type>\n\n  <Type Name=\"c4::yml::NodeType\">\n    <DisplayString Condition=\"((type &amp; c4::yml::KEY  ) == c4::yml::KEY) &amp;&amp; ((type &amp; c4::yml::VAL) == c4::yml::VAL)\">[KEYVAL]</DisplayString>\n    <DisplayString Condition=\"((type &amp; c4::yml::KEY  ) == c4::yml::KEY) &amp;&amp; ((type &amp; c4::yml::SEQ) == c4::yml::SEQ)\">[KEYSEQ]</DisplayString>\n    <DisplayString Condition=\"((type &amp; c4::yml::KEY  ) == c4::yml::KEY) &amp;&amp; ((type &amp; c4::yml::MAP) == c4::yml::MAP)\">[KEYMAP]</DisplayString>\n    <DisplayString Condition=\"((type &amp; c4::yml::DOC  ) == c4::yml::DOC) &amp;&amp; ((type &amp; c4::yml::VAL) == c4::yml::VAL)\">[DOCVAL]</DisplayString>\n    <DisplayString Condition=\"((type &amp; c4::yml::DOC  ) == c4::yml::DOC) &amp;&amp; ((type &amp; c4::yml::SEQ) == c4::yml::SEQ)\">[DOCSEQ]</DisplayString>\n    <DisplayString Condition=\"((type &amp; c4::yml::DOC  ) == c4::yml::DOC) &amp;&amp; ((type &amp; c4::yml::MAP) == c4::yml::MAP)\">[DOCMAP]</DisplayString>\n    <DisplayString Condition=\"(type &amp; c4::yml::VAL   ) == c4::yml::VAL\"   >[VAL]</DisplayString>\n    <DisplayString Condition=\"(type &amp; c4::yml::KEY   ) == c4::yml::KEY\"   >[KEY]</DisplayString>\n    <DisplayString Condition=\"(type &amp; c4::yml::SEQ   ) == c4::yml::SEQ\"   >[SEQ]</DisplayString>\n    <DisplayString Condition=\"(type &amp; c4::yml::MAP   ) == c4::yml::MAP\"   >[MAP]</DisplayString>\n    <DisplayString Condition=\"(type &amp; c4::yml::DOC   ) == c4::yml::DOC\"   >[DOC]</DisplayString>\n    <DisplayString Condition=\"(type &amp; c4::yml::STREAM) == c4::yml::STREAM\">[STREAM]</DisplayString>\n    <DisplayString Condition=\"(type &amp; c4::yml::NOTYPE) == c4::yml::NOTYPE\">[NOTYPE]</DisplayString>\n    <Expand>\n      <Synthetic Name=\"[type bits]\">\n        <Expand>\n          <Item Name=\"[0]\" Condition=\"(type &amp; c4::yml::KEY) != 0\">c4::yml::KEY</Item>\n          <Item Name=\"[1]\" Condition=\"(type &amp; c4::yml::VAL) != 0\">c4::yml::VAL</Item>\n          <Item Name=\"[2]\" Condition=\"(type &amp; c4::yml::MAP) != 0\">c4::yml::MAP</Item>\n          <Item Name=\"[3]\" Condition=\"(type &amp; c4::yml::SEQ) != 0\">c4::yml::SEQ</Item>\n          <Item Name=\"[4]\" Condition=\"(type &amp; c4::yml::DOC) != 0\">c4::yml::DOC</Item>\n          <Item Name=\"[5]\" Condition=\"(type &amp; c4::yml::STREAM) != 0\">c4::yml::STREAM</Item>\n          <Item Name=\"[6]\" Condition=\"(type &amp; c4::yml::KEYREF) != 0\">c4::yml::KEYREF</Item>\n          <Item Name=\"[7]\" Condition=\"(type &amp; c4::yml::VALREF) != 0\">c4::yml::VALREF</Item>\n          <Item Name=\"[8]\" Condition=\"(type &amp; c4::yml::KEYANCH) != 0\">c4::yml::KEYANCH</Item>\n          <Item Name=\"[9]\" Condition=\"(type &amp; c4::yml::VALANCH) != 0\">c4::yml::VALANCH</Item>\n          <Item Name=\"[10]\" Condition=\"(type &amp; c4::yml::KEYTAG) != 0\">c4::yml::KEYTAG</Item>\n          <Item Name=\"[11]\" Condition=\"(type &amp; c4::yml::VALTAG) != 0\">c4::yml::VALTAG</Item>\n        </Expand>\n      </Synthetic>\n      <Synthetic Name=\"[style bits]\">\n        <Expand>\n          <Item Name=\"[0]\" Condition=\"(type &amp; c4::yml::_WIP_KEY_UNFILT) != 0\">c4::yml::_WIP_KEY_UNFILT</Item>\n          <Item Name=\"[1]\" Condition=\"(type &amp; c4::yml::_WIP_VAL_UNFILT) != 0\">c4::yml::_WIP_VAL_UNFILT</Item>\n          <Item Name=\"[2]\" Condition=\"(type &amp; c4::yml::_WIP_STYLE_FLOW_SL) != 0\">c4::yml::_WIP_STYLE_FLOW</Item>\n          <Item Name=\"[3]\" Condition=\"(type &amp; c4::yml::_WIP_STYLE_FLOW_ML) != 0\">c4::yml::_WIP_STYLE_FLOW</Item>\n          <Item Name=\"[4]\" Condition=\"(type &amp; c4::yml::_WIP_STYLE_BLOCK) != 0\">c4::yml::_WIP_STYLE_BLOCK</Item>\n          <Item Name=\"[5]\" Condition=\"(type &amp; c4::yml::_WIP_KEY_LITERAL) != 0\">c4::yml::_WIP_KEY_LITERAL</Item>\n          <Item Name=\"[6]\" Condition=\"(type &amp; c4::yml::_WIP_VAL_LITERAL) != 0\">c4::yml::_WIP_VAL_LITERAL</Item>\n          <Item Name=\"[7]\" Condition=\"(type &amp; c4::yml::_WIP_KEY_FOLDED) != 0\">c4::yml::_WIP_KEY_FOLDED</Item>\n          <Item Name=\"[8]\" Condition=\"(type &amp; c4::yml::_WIP_VAL_FOLDED) != 0\">c4::yml::_WIP_VAL_FOLDED</Item>\n          <Item Name=\"[9]\" Condition=\"(type &amp; c4::yml::_WIP_KEY_SQUO) != 0\">c4::yml::_WIP_KEY_SQUO</Item>\n          <Item Name=\"[10]\" Condition=\"(type &amp; c4::yml::_WIP_VAL_SQUO) != 0\">c4::yml::_WIP_VAL_SQUO</Item>\n          <Item Name=\"[11]\" Condition=\"(type &amp; c4::yml::_WIP_KEY_DQUO) != 0\">c4::yml::_WIP_KEY_DQUO</Item>\n          <Item Name=\"[12]\" Condition=\"(type &amp; c4::yml::_WIP_VAL_DQUO) != 0\">c4::yml::_WIP_VAL_DQUO</Item>\n          <Item Name=\"[13]\" Condition=\"(type &amp; c4::yml::_WIP_KEY_PLAIN) != 0\">c4::yml::_WIP_KEY_PLAIN</Item>\n          <Item Name=\"[14]\" Condition=\"(type &amp; c4::yml::_WIP_VAL_PLAIN) != 0\">c4::yml::_WIP_VAL_PLAIN</Item>\n        </Expand>\n      </Synthetic>\n    </Expand>\n  </Type>\n\n  <Type Name=\"c4::yml::NodeData\">\n    <DisplayString Condition=\"((m_type.type &amp; c4::yml::KEY  ) == c4::yml::KEY) &amp;&amp; ((m_type.type &amp; c4::yml::VAL) == c4::yml::VAL)\">[KEYVAL] {m_key.scalar.str,[m_key.scalar.len]}: {m_val.scalar.str,[m_val.scalar.len]}</DisplayString>\n    <DisplayString Condition=\"((m_type.type &amp; c4::yml::KEY  ) == c4::yml::KEY) &amp;&amp; ((m_type.type &amp; c4::yml::SEQ) == c4::yml::SEQ)\">[KEYSEQ] {m_key.scalar.str,[m_key.scalar.len]}</DisplayString>\n    <DisplayString Condition=\"((m_type.type &amp; c4::yml::KEY  ) == c4::yml::KEY) &amp;&amp; ((m_type.type &amp; c4::yml::MAP) == c4::yml::MAP)\">[KEYMAP] {m_key.scalar.str,[m_key.scalar.len]}</DisplayString>\n    <DisplayString Condition=\"((m_type.type &amp; c4::yml::DOC  ) == c4::yml::DOC) &amp;&amp; ((m_type.type &amp; c4::yml::SEQ) == c4::yml::SEQ)\">[DOCSEQ]</DisplayString>\n    <DisplayString Condition=\"((m_type.type &amp; c4::yml::DOC  ) == c4::yml::DOC) &amp;&amp; ((m_type.type &amp; c4::yml::MAP) == c4::yml::MAP)\">[DOCMAP]</DisplayString>\n    <DisplayString Condition=\"(m_type.type &amp; c4::yml::VAL   ) == c4::yml::VAL\"   >[VAL] {m_val.scalar.str,[m_val.scalar.len]}</DisplayString>\n    <DisplayString Condition=\"(m_type.type &amp; c4::yml::KEY   ) == c4::yml::KEY\"   >[KEY] {m_key.scalar.str,[m_key.scalar.len]}</DisplayString>\n    <DisplayString Condition=\"(m_type.type &amp; c4::yml::SEQ   ) == c4::yml::SEQ\"   >[SEQ]</DisplayString>\n    <DisplayString Condition=\"(m_type.type &amp; c4::yml::MAP   ) == c4::yml::MAP\"   >[MAP]</DisplayString>\n    <DisplayString Condition=\"(m_type.type &amp; c4::yml::DOC   ) == c4::yml::DOC\"   >[DOC]</DisplayString>\n    <DisplayString Condition=\"(m_type.type &amp; c4::yml::STREAM) == c4::yml::STREAM\">[STREAM]</DisplayString>\n    <DisplayString Condition=\"(m_type.type &amp; c4::yml::NOTYPE) == c4::yml::NOTYPE\">[NOTYPE]</DisplayString>\n    <Expand>\n      <Item Name=\"type\">m_type</Item>\n      <Item Name=\"key\" Condition=\"(m_type.type &amp; c4::yml::KEY) != 0\">m_key</Item>\n      <Item Name=\"val\" Condition=\"(m_type.type &amp; c4::yml::VAL) != 0\">m_val</Item>\n      <Item Name=\"key quoted\" Condition=\"((m_type.type &amp; c4::yml::KEY) != 0) &amp;&amp; ((m_type.type &amp; c4::yml::KEYQUO) != 0)\">c4::yml::KEYQUO</Item>\n      <Item Name=\"val quoted\" Condition=\"((m_type.type &amp; c4::yml::VAL) != 0) &amp;&amp; ((m_type.type &amp; c4::yml::VALQUO) != 0)\">c4::yml::VALQUO</Item>\n      <Item Name=\"key ref\" Condition=\"(m_type.type &amp; c4::yml::KEYREF) != 0\">m_key.anchor</Item>\n      <Item Name=\"val ref\" Condition=\"(m_type.type &amp; c4::yml::VALREF) != 0\">m_val.anchor</Item>\n      <Item Name=\"key anchor\" Condition=\"(m_type.type &amp; c4::yml::KEYANCH) != 0\">m_key.anchor</Item>\n      <Item Name=\"val anchor\" Condition=\"(m_type.type &amp; c4::yml::VALANCH) != 0\">m_val.anchor</Item>\n      <Item Name=\"parent\" Condition=\"m_parent == c4::yml::NONE\">NONE</Item>\n      <Item Name=\"parent\" Condition=\"m_parent != c4::yml::NONE\">m_parent</Item>\n      <Item Name=\"first child\"  Condition=\"m_first_child != c4::yml::NONE\">m_first_child</Item>\n      <Item Name=\"last child\"   Condition=\"m_last_child != c4::yml::NONE\">m_last_child</Item>\n      <Item Name=\"prev sibling\" Condition=\"m_prev_sibling != c4::yml::NONE\">m_prev_sibling</Item>\n      <Item Name=\"next sibling\" Condition=\"m_next_sibling != c4::yml::NONE\">m_next_sibling</Item>\n    </Expand>\n  </Type>\n\n  <Type Name=\"c4::yml::Tree\">\n    <DisplayString>sz={m_size}, cap={m_cap}</DisplayString>\n    <Expand>\n      <Item Name=\"[size]\">m_size</Item>\n      <Item Name=\"[capacity]\">m_cap</Item>\n      <Synthetic Name=\"[buffer]\">\n        <Expand>\n          <ArrayItems>\n            <Size>m_cap</Size>\n            <ValuePointer>m_buf</ValuePointer>\n          </ArrayItems>\n        </Expand>\n      </Synthetic>\n      <Item Name=\"free head\">m_free_head</Item>\n      <Item Name=\"arena\">m_arena</Item>\n    </Expand>\n  </Type>\n\n  <Type Name=\"c4::yml::Tree::_lookup_path_token\">\n    <DisplayString>{value} ({type})</DisplayString>\n    <Expand>\n      <Item Name=\"value\">value</Item>\n      <Item Name=\"type\">type</Item>\n    </Expand>\n  </Type>\n\n  <Type Name=\"c4::yml::Tree::lookup_result\">\n    <DisplayString>{path} -- target={target} closest={closest}</DisplayString>\n    <Expand>\n      <Item Name=\"target\">target</Item>\n      <Item Name=\"closest\">closest</Item>\n      <Item Name=\"path_pos\">path_pos</Item>\n      <Item Name=\"path\">path</Item>\n      <Synthetic Name=\"[resolved]\">\n        <DisplayString>{path.str,[path_pos]}</DisplayString>\n      </Synthetic>\n      <Synthetic Name=\"[unresolved]\">\n        <DisplayString>{path.str+path_pos,[path.len-path_pos]}</DisplayString>\n      </Synthetic>\n    </Expand>\n  </Type>\n\n  <Type Name=\"c4::yml::NodeRef\">\n    <DisplayString Condition=\"(m_id == c4::yml::NONE)\">(void)</DisplayString>\n    <DisplayString Condition=\"(m_seed.len != c4::yml::NONE) &amp;&amp; (m_seed.str == nullptr)\">[INDEX SEED for] {*(m_tree->m_buf + m_id)}</DisplayString>\n    <DisplayString Condition=\"(m_seed.len != c4::yml::NONE) &amp;&amp; (m_seed.str != nullptr)\">[NAMED SEED for] {*(m_tree->m_buf + m_id)}</DisplayString>\n    <DisplayString>{*(m_tree->m_buf + m_id)}</DisplayString>\n    <Expand>\n      <Item Name=\"id\">m_id</Item>\n      <Item Name=\"element\">*(m_tree->m_buf + m_id)</Item>\n      <Item Name=\"tree\">m_tree</Item>\n      <Synthetic Name=\"[children]\" Condition=\"(m_id != c4::yml::NONE) &amp;&amp; (((m_tree->m_buf + m_id)->m_type.type &amp; (c4::yml::MAP|c4::yml::SEQ)) != 0)\">\n        <Expand>\n          <CustomListItems>\n            <Variable Name=\"tree\" InitialValue=\"m_tree\"/>\n            <Variable Name=\"buf\" InitialValue=\"m_tree->m_buf\"/>\n            <Variable Name=\"curr\" InitialValue=\"(m_tree->m_buf + m_id)->m_first_child\"/>\n            <Loop>\n              <Item>buf + curr</Item>\n              <Exec>curr = (buf + curr)->m_next_sibling</Exec>\n              <Break Condition=\"curr == c4::yml::NONE\"/>\n            </Loop>\n          </CustomListItems>\n        </Expand>\n      </Synthetic>\n    </Expand>\n  </Type>\n\n  <Type Name=\"c4::yml::ConstNodeRef\">\n    <DisplayString Condition=\"(m_id == c4::yml::NONE)\">(void)</DisplayString>\n    <DisplayString>{*(m_tree->m_buf + m_id)}</DisplayString>\n    <Expand>\n      <Item Name=\"id\">m_id</Item>\n      <Item Name=\"element\">*(m_tree->m_buf + m_id)</Item>\n      <Item Name=\"tree\">m_tree</Item>\n      <Synthetic Name=\"[children]\" Condition=\"(m_id != c4::yml::NONE) &amp;&amp; (((m_tree->m_buf + m_id)->m_type.type &amp; (c4::yml::MAP|c4::yml::SEQ)) != 0)\">\n        <Expand>\n          <CustomListItems>\n            <Variable Name=\"tree\" InitialValue=\"m_tree\"/>\n            <Variable Name=\"buf\" InitialValue=\"m_tree->m_buf\"/>\n            <Variable Name=\"curr\" InitialValue=\"(m_tree->m_buf + m_id)->m_first_child\"/>\n            <Loop>\n              <Item>buf + curr</Item>\n              <Exec>curr = (buf + curr)->m_next_sibling</Exec>\n              <Break Condition=\"curr == c4::yml::NONE\"/>\n            </Loop>\n          </CustomListItems>\n        </Expand>\n      </Synthetic>\n    </Expand>\n  </Type>\n\n  <Type Name=\"c4::yml::detail::ReferenceResolver\">\n    <DisplayString>#refs={refs.m_size} #nodes={t->m_size}</DisplayString>\n    <Expand>\n      <Synthetic Name=\"[ref_nodes]\">\n        <Expand>\n          <CustomListItems>\n            <Variable Name=\"curr\" InitialValue=\"0\"/>\n            <Loop>\n              <Item>t->m_buf + (refs.m_stack + curr)->node</Item>\n              <Exec>curr = curr+1</Exec>\n              <Break Condition=\"curr >= refs.m_size\"/>\n            </Loop>\n          </CustomListItems>\n        </Expand>\n      </Synthetic>\n      <Synthetic Name=\"[refs]\">\n        <Expand>\n          <ArrayItems>\n            <Size>refs.m_size</Size>\n            <ValuePointer>refs.m_stack</ValuePointer>\n          </ArrayItems>\n        </Expand>\n      </Synthetic>\n      <Item Name=\"[tree]\">t</Item>\n    </Expand>\n  </Type>\n\n  <Type Name=\"c4::yml::detail::stack&lt;*,*&gt;\">\n    <DisplayString>sz={m_size} cap={m_capacity}</DisplayString>\n    <Expand>\n      <Item Name=\"[size]\">m_size</Item>\n      <Item Name=\"[capacity]\">m_capacity</Item>\n      <Item Name=\"[is small]\">m_buf == m_stack</Item>\n      <Synthetic Name=\"[items]\">\n        <Expand>\n          <ArrayItems>\n            <Size>m_size</Size>\n            <ValuePointer>m_stack</ValuePointer>\n          </ArrayItems>\n        </Expand>\n      </Synthetic>\n    </Expand>\n  </Type>\n\n  <Type Name=\"c4::yml::detail::FilterProcessorSrcDst\">\n    <DisplayString>src={src.str,[rpos]} dst={dst.str,[wpos]}</DisplayString>\n    <Expand>\n      <Item Name=\"[src]\">src</Item>\n      <Item Name=\"[dst]\">dst</Item>\n      <Item Name=\"[rpos]\">rpos</Item>\n      <Item Name=\"[wpos]\">wpos</Item>\n      <Synthetic Name=\"[read]\">\n        <StringView>src.str,[rpos]</StringView>\n        <Expand>\n          <ArrayItems>\n            <Size>rpos</Size>\n            <ValuePointer>src.str</ValuePointer>\n          </ArrayItems>\n        </Expand>\n      </Synthetic>\n    </Expand>\n  </Type>\n\n  <Type Name=\"c4::yml::detail::FilterProcessorInplace\">\n    <DisplayString>src={src.str,[rpos]} dst={src.str,[wpos]}</DisplayString>\n    <Expand>\n      <Item Name=\"[rpos]\">rpos</Item>\n      <Item Name=\"[wpos]\">wpos</Item>\n      <Item Name=\"[wcap]\">wcap</Item>\n      <Synthetic Name=\"[buf]\">\n        <StringView>src.str,[wcap]</StringView>\n        <Expand>\n          <ArrayItems>\n            <Size>wcap</Size>\n            <ValuePointer>src.str</ValuePointer>\n          </ArrayItems>\n        </Expand>\n      </Synthetic>\n      <Item Name=\"[src]\">src</Item>\n      <Synthetic Name=\"[to be read]\">\n        <StringView>src.str+rpos,[src.len-rpos]</StringView>\n        <Expand>\n          <ArrayItems><Size>src.len-rpos</Size><ValuePointer>src.str+rpos</ValuePointer></ArrayItems>\n        </Expand>\n      </Synthetic>\n      <Synthetic Name=\"[read]\">\n        <StringView>src.str,[rpos]</StringView>\n        <Expand>\n          <ArrayItems><Size>rpos</Size><ValuePointer>src.str</ValuePointer></ArrayItems>\n        </Expand>\n      </Synthetic>\n      <Synthetic Name=\"[written]\">\n        <StringView>src.str,[wpos]</StringView>\n        <Expand>\n          <ArrayItems><Size>wpos</Size><ValuePointer>src.str</ValuePointer></ArrayItems>\n        </Expand>\n      </Synthetic>\n    </Expand>\n  </Type>\n\n</AutoVisualizer>\n"
  },
  {
    "path": "src/version.h",
    "content": "#pragma once\n/*\n * Copyright 2010-2016 OpenXcom Developers.\n *\n * This file is part of OpenXcom.\n *\n * OpenXcom is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * OpenXcom is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#define MIN_REQUIRED_RULESET_VERSION_NUMBER 8,6,0,0\n\n#define OPENXCOM_VERSION_ENGINE \"Extended\"\n#define OPENXCOM_VERSION_SHORT \"Extended 8.6.1\"\n#define OPENXCOM_VERSION_LONG \"8.6.1.0\"\n#define OPENXCOM_VERSION_NUMBER 8,6,1,0\n\n#ifndef OPENXCOM_VERSION_GIT\n#define OPENXCOM_VERSION_GIT \" (v2026-05-02)\"\n#endif\n"
  }
]